[debian-edu-commits] debian-edu/pkg-team/ 01/01: Imported Upstream version 2.0~hg20140915+dfsg1

Mike Gabriel sunweaver at debian.org
Mon Sep 15 16:40:18 UTC 2014


This is an automated email from the git hooks/post-receive script.

sunweaver pushed a commit to branch master
in repository axcrypt.git.

commit 6856cee592ea9ab344dba2fcb3931713a5adf53c
Author: Mike Gabriel <mike.gabriel at das-netzwerkteam.de>
Date:   Mon Sep 15 17:48:48 2014 +0200

    Imported Upstream version 2.0~hg20140915+dfsg1
---
 AboutTheSolutions.txt                              |    23 +
 AxCrypt-MonoForAndroid.sln                         |    24 +
 AxCrypt-MonoMac.sln                                |    66 +
 AxCrypt-MonoTouch.sln                              |   118 +
 AxCrypt.NET.sln                                    |    89 +
 Axantum.AxCrypt.Core.Test/AboutThisAssembly.txt    |     9 +
 .../Axantum.AxCrypt.Core.Test.csproj               |   245 +
 Axantum.AxCrypt.Core.Test/AxantumStrongName.pfx    |   Bin 0 -> 1764 bytes
 .../CryptoValidation/TestRsaOeap.cs                |  3123 ++
 Axantum.AxCrypt.Core.Test/Endian.cs                |    35 +
 Axantum.AxCrypt.Core.Test/Extensions.cs            |    21 +
 Axantum.AxCrypt.Core.Test/FakeAsymmetricFactory.cs |   131 +
 Axantum.AxCrypt.Core.Test/FakeDataProtection.cs    |    52 +
 Axantum.AxCrypt.Core.Test/FakeDelayTimer.cs        |    97 +
 Axantum.AxCrypt.Core.Test/FakeFileWatcher.cs       |   112 +
 .../FakeIterationCalculator.cs                     |    41 +
 Axantum.AxCrypt.Core.Test/FakeLauncher.cs          |    84 +
 Axantum.AxCrypt.Core.Test/FakeLogging.cs           |   109 +
 .../FakeProgressBackground.cs                      |    75 +
 .../FakePseudoRandomGenerator.cs                   |    48 +
 Axantum.AxCrypt.Core.Test/FakeRandomGenerator.cs   |    48 +
 Axantum.AxCrypt.Core.Test/FakeRequestClient.cs     |    43 +
 Axantum.AxCrypt.Core.Test/FakeRequestServer.cs     |    60 +
 .../FakeRuntimeEnvironment.cs                      |   184 +
 Axantum.AxCrypt.Core.Test/FakeRuntimeFileInfo.cs   |   433 +
 Axantum.AxCrypt.Core.Test/FakeSleep.cs             |    52 +
 Axantum.AxCrypt.Core.Test/FakeStatusChecker.cs     |    51 +
 Axantum.AxCrypt.Core.Test/FakeStream.cs            |   147 +
 Axantum.AxCrypt.Core.Test/FakeTiming.cs            |    49 +
 Axantum.AxCrypt.Core.Test/FakeUIThread.cs          |    55 +
 Axantum.AxCrypt.Core.Test/FakeWebCaller.cs         |    66 +
 Axantum.AxCrypt.Core.Test/GlobalSuppressions.cs    |   Bin 0 -> 1464 bytes
 Axantum.AxCrypt.Core.Test/MockAxCryptFile.cs       |    77 +
 .../MockFileSystemStateActions.cs                  |    85 +
 .../Properties/AssemblyInfo.cs                     |    75 +
 .../Properties/Resources.Designer.cs               |   130 +
 .../Properties/Resources.resx                      |   136 +
 Axantum.AxCrypt.Core.Test/SetupAssembly.cs         |   111 +
 Axantum.AxCrypt.Core.Test/TestActiveFile.cs        |   212 +
 .../TestActiveFileCollectionTests.cs               |   104 +
 .../TestActiveFileComparer.cs                      |   134 +
 Axantum.AxCrypt.Core.Test/TestAsymmetricCrypto.cs  |   265 +
 .../TestAsymmetricUserKeysStore.cs                 |   116 +
 Axantum.AxCrypt.Core.Test/TestAxCryptFactory.cs    |    84 +
 Axantum.AxCrypt.Core.Test/TestAxCryptFile.cs       |   584 +
 Axantum.AxCrypt.Core.Test/TestAxCryptHMACSHA1.cs   |    74 +
 .../TestAxCryptHeaderKeyWrap.cs                    |   100 +
 .../TestAxCryptReaderIdTagHeaderBlock.cs           |    77 +
 .../TestAxCryptReaderMagicGuid.cs                  |   171 +
 .../TestAxCryptReaderPreambleHeaderBlock.cs        |   145 +
 .../TestAxCryptReaderVersionHeaderBlock.cs         |    94 +
 .../TestAxCryptStreamReader.cs                     |   362 +
 Axantum.AxCrypt.Core.Test/TestCancelContext.cs     |   112 +
 Axantum.AxCrypt.Core.Test/TestCommandLine.cs       |   120 +
 Axantum.AxCrypt.Core.Test/TestCommandService.cs    |    78 +
 .../TestCommandServiceEventArgsTest.cs             |    51 +
 .../TestCounterModeCryptoTransform.cs              |   103 +
 Axantum.AxCrypt.Core.Test/TestDataHmac.cs          |    89 +
 Axantum.AxCrypt.Core.Test/TestDelayedAction.cs     |   123 +
 Axantum.AxCrypt.Core.Test/TestDelegateAction.cs    |   116 +
 Axantum.AxCrypt.Core.Test/TestDocumentHeaders.cs   |   160 +
 .../TestEncryptedDataPartBlock.cs                  |    58 +
 Axantum.AxCrypt.Core.Test/TestExceptions.cs        |   156 +
 Axantum.AxCrypt.Core.Test/TestExtensions.cs        |   515 +
 Axantum.AxCrypt.Core.Test/TestFactoryRegistry.cs   |   130 +
 .../TestFileInfoEncryptedHeaderBlock.cs            |    71 +
 Axantum.AxCrypt.Core.Test/TestFileLock.cs          |   124 +
 .../TestFileNameInfoEncryptedHeaderBlock.cs        |    85 +
 Axantum.AxCrypt.Core.Test/TestFileOperation.cs     |   371 +
 .../TestFileOperationViewModel.cs                  |   932 +
 .../TestFileOperationsController.cs                |   768 +
 Axantum.AxCrypt.Core.Test/TestFileSystemState.cs   |   363 +
 .../TestFileSystemStateActions.cs                  |   619 +
 Axantum.AxCrypt.Core.Test/TestFileWatcher.cs       |    66 +
 Axantum.AxCrypt.Core.Test/TestHeaderBlock.cs       |   139 +
 Axantum.AxCrypt.Core.Test/TestHeaders.cs           |   147 +
 Axantum.AxCrypt.Core.Test/TestIOStreams.cs         |   356 +
 Axantum.AxCrypt.Core.Test/TestIdTagHeaderBlock.cs  |    57 +
 Axantum.AxCrypt.Core.Test/TestIdentityViewModel.cs |   402 +
 Axantum.AxCrypt.Core.Test/TestInstance.cs          |    59 +
 .../TestIterationCalculator.cs                     |   156 +
 Axantum.AxCrypt.Core.Test/TestKeyWrap.cs           |   165 +
 .../TestKeyWrap1HeaderBlock.cs                     |   102 +
 .../TestKeyWrap2HeaderBlock.cs                     |    57 +
 Axantum.AxCrypt.Core.Test/TestKnownFolder.cs       |   108 +
 .../TestKnownFoldersViewModel.cs                   |   145 +
 Axantum.AxCrypt.Core.Test/TestKnownKeys.cs         |   218 +
 .../TestLockingStreamTests.cs                      |   103 +
 Axantum.AxCrypt.Core.Test/TestLogOnViewModel.cs    |   188 +
 Axantum.AxCrypt.Core.Test/TestLogging.cs           |    62 +
 Axantum.AxCrypt.Core.Test/TestMainViewModel.cs     |   585 +
 Axantum.AxCrypt.Core.Test/TestNDeskOptions.cs      |  1223 +
 .../TestNewPassphraseViewModel.cs                  |   157 +
 .../TestParallelFileOperation.cs                   |   103 +
 Axantum.AxCrypt.Core.Test/TestPassphrase.cs        |    62 +
 Axantum.AxCrypt.Core.Test/TestPassphraseBase.cs    |    84 +
 .../TestPassphraseIdentity.cs                      |    64 +
 Axantum.AxCrypt.Core.Test/TestPbkdf2HmacSha512.cs  |   372 +
 .../TestPreambleHeaderBlock.cs                     |    60 +
 Axantum.AxCrypt.Core.Test/TestProcessState.cs      |    93 +
 Axantum.AxCrypt.Core.Test/TestProgressContext.cs   |   390 +
 .../TestProgressEventArgsTest.cs                   |    66 +
 Axantum.AxCrypt.Core.Test/TestProgressStream.cs    |   136 +
 Axantum.AxCrypt.Core.Test/TestRandomGenerator.cs   |    67 +
 Axantum.AxCrypt.Core.Test/TestResources.cs         |    78 +
 Axantum.AxCrypt.Core.Test/TestSalt.cs              |    95 +
 Axantum.AxCrypt.Core.Test/TestSessionEvent.cs      |   134 +
 .../TestSessionNotificationHandler.cs              |   263 +
 .../TestSessionNotificationMonitor.cs              |    68 +
 Axantum.AxCrypt.Core.Test/TestSubKey.cs            |    81 +
 Axantum.AxCrypt.Core.Test/TestSymmetricIV.cs       |    75 +
 Axantum.AxCrypt.Core.Test/TestSymmetricKey.cs      |   137 +
 .../TestSymmetricKeyThumbprint.cs                  |   124 +
 Axantum.AxCrypt.Core.Test/TestThreadWorker.cs      |   259 +
 .../TestThreadWorkerProgressContext.cs             |   166 +
 .../TestUnrecognizedHeaderBlock .cs                |    57 +
 Axantum.AxCrypt.Core.Test/TestUpdateCheck.cs       |   428 +
 Axantum.AxCrypt.Core.Test/TestUserSettings.cs      |   200 +
 Axantum.AxCrypt.Core.Test/TestV1AesCrypto.cs       |    71 +
 Axantum.AxCrypt.Core.Test/TestV1AxCryptDocument.cs |   686 +
 Axantum.AxCrypt.Core.Test/TestV1AxCryptReader.cs   |    82 +
 ...estV1UnicodeFileNameInfoEncryptedHeaderBlock.cs |    84 +
 Axantum.AxCrypt.Core.Test/TestV2AesCrypto.cs       |   152 +
 ...stV2AsymmetricRecipientsEncryptedHeaderBlock.cs |    56 +
 .../TestV2AxCryptDataStreamTest.cs                 |   237 +
 Axantum.AxCrypt.Core.Test/TestV2AxCryptDocument.cs |   422 +
 Axantum.AxCrypt.Core.Test/TestV2AxCryptReader.cs   |    89 +
 .../TestV2CompressionEncryptedHeaderBlock.cs       |    60 +
 Axantum.AxCrypt.Core.Test/TestV2DocumentHeaders.cs |   208 +
 Axantum.AxCrypt.Core.Test/TestV2HmacHeaderBlock.cs |    60 +
 Axantum.AxCrypt.Core.Test/TestV2HmacStreamTest.cs  |   232 +
 .../TestV2KeyWrapHeaderBlock.cs                    |   201 +
 .../TestV2PlainTextLengthsEncryptedHeaderBlock.cs  |   101 +
 .../TestV2RegressionCompleteFiles.cs               |    93 +
 ...estV2UnicodeFileNameInfoEncryptedHeaderBlock.cs |    94 +
 Axantum.AxCrypt.Core.Test/TestVXAxCryptReader.cs   |    98 +
 .../TestVersionHeaderBlock .cs                     |    70 +
 Axantum.AxCrypt.Core.Test/TestViewModelBaseTest.cs |   184 +
 Axantum.AxCrypt.Core.Test/TestWatchedFolder.cs     |   131 +
 .../TestWatchedFolderChangedEventArgsTest.cs       |    70 +
 Axantum.AxCrypt.Core.Test/TestWorkFolderWatcher.cs |    74 +
 Axantum.AxCrypt.Core.Test/TestWorkerGroup.cs       |   293 +
 .../TestWorkerGroupProgressContext.cs              |   154 +
 .../resources/Frankenstein-txt-AES256.axx          |   Bin 0 -> 170646 bytes
 .../resources/Frankenstein-txt-V2AES128.axx        |   Bin 0 -> 170646 bytes
 .../david copperfield-key-'aa ae oe'-ulu-txt.axx   |   Bin 0 -> 796190 bytes
 .../resources/david-copperfield.txt                | 38587 +++++++++++++++++++
 .../resources/helloworld-key-a-txt.axx             |   Bin 0 -> 334 bytes
 .../resources/short-txt-AES256.axx                 |   Bin 0 -> 1310 bytes
 .../resources/short-txt-V2AES128.axx               |   Bin 0 -> 1310 bytes
 .../resources/snow-jpg-AES256.axx                  |   Bin 0 -> 108048 bytes
 .../resources/snow-jpg-V2AES128.axx                |   Bin 0 -> 108048 bytes
 .../tst-0.0b6-key-'aaaeoe'-medium-html.axx         |   Bin 0 -> 3972 bytes
 .../resources/uncompressable-zip.axx               |   Bin 0 -> 9006 bytes
 Axantum.AxCrypt.Core/AboutThisAssembly.txt         |    11 +
 Axantum.AxCrypt.Core/AxCryptFactory.cs             |   118 +
 Axantum.AxCrypt.Core/AxCryptFile.cs                |   662 +
 Axantum.AxCrypt.Core/AxCryptOptions.cs             |    40 +
 Axantum.AxCrypt.Core/Axantum.AxCrypt.Core.csproj   |   329 +
 Axantum.AxCrypt.Core/AxantumStrongName.pfx         |   Bin 0 -> 1764 bytes
 Axantum.AxCrypt.Core/CommandLine.cs                |   138 +
 .../Asymmetric/BouncyCastleAsymmetricFactory.cs    |    49 +
 .../Crypto/Asymmetric/BouncyCastleDigest.cs        |    79 +
 .../Crypto/Asymmetric/BouncyCastleKeyPair.cs       |    91 +
 .../Crypto/Asymmetric/BouncyCastlePaddingHash.cs   |    79 +
 .../Crypto/Asymmetric/BouncyCastlePrivateKey.cs    |   120 +
 .../Crypto/Asymmetric/BouncyCastlePublicKey.cs     |   112 +
 .../Asymmetric/BouncyCastleRandomGenerator.cs      |    65 +
 .../Crypto/Asymmetric/IAsymmetricFactory.cs        |    23 +
 .../Crypto/Asymmetric/IAsymmetricKeyPair.cs        |    41 +
 .../Crypto/Asymmetric/IAsymmetricPaddingHash.cs    |    38 +
 .../Crypto/Asymmetric/IAsymmetricPrivateKey.cs     |    39 +
 .../Crypto/Asymmetric/IAsymmetricPublicKey.cs      |    39 +
 .../Crypto/BlockAlgorithmKeyWrapTransform.cs       |    94 +
 .../Crypto/CounterModeCryptoTransform.cs           |   179 +
 Axantum.AxCrypt.Core/Crypto/CryptoBase.cs          |    77 +
 Axantum.AxCrypt.Core/Crypto/CryptoExtensions.cs    |    36 +
 Axantum.AxCrypt.Core/Crypto/CryptoFactory.cs       |   114 +
 Axantum.AxCrypt.Core/Crypto/CryptoPolicy.cs        |    68 +
 Axantum.AxCrypt.Core/Crypto/DerivedKeyBase.cs      |    83 +
 Axantum.AxCrypt.Core/Crypto/FreeCryptoPolicy.cs    |    53 +
 Axantum.AxCrypt.Core/Crypto/HeaderSubkey.cs        |    41 +
 Axantum.AxCrypt.Core/Crypto/Hmac.cs                |   141 +
 Axantum.AxCrypt.Core/Crypto/ICrypto.cs             |    84 +
 Axantum.AxCrypt.Core/Crypto/ICryptoFactory.cs      |    87 +
 Axantum.AxCrypt.Core/Crypto/ICryptoHash.cs         |    82 +
 Axantum.AxCrypt.Core/Crypto/ICryptoPolicy.cs       |    44 +
 Axantum.AxCrypt.Core/Crypto/IDerivedKey.cs         |    41 +
 Axantum.AxCrypt.Core/Crypto/IKeyWrapTransform.cs   |    16 +
 Axantum.AxCrypt.Core/Crypto/IRandomGenerator.cs    |    10 +
 Axantum.AxCrypt.Core/Crypto/IterationCalculator.cs |    80 +
 Axantum.AxCrypt.Core/Crypto/KeyWrap.cs             |   232 +
 Axantum.AxCrypt.Core/Crypto/KeyWrapDirection.cs    |    26 +
 Axantum.AxCrypt.Core/Crypto/KeyWrapMode.cs         |    40 +
 Axantum.AxCrypt.Core/Crypto/LegacyCryptoPolicy.cs  |    53 +
 Axantum.AxCrypt.Core/Crypto/Passphrase.cs          |   107 +
 Axantum.AxCrypt.Core/Crypto/Pbkdf2HmacSha512.cs    |   111 +
 Axantum.AxCrypt.Core/Crypto/ProCryptoPolicy.cs     |    53 +
 Axantum.AxCrypt.Core/Crypto/RandomGenerator.cs     |    45 +
 Axantum.AxCrypt.Core/Crypto/Salt.cs                |   103 +
 Axantum.AxCrypt.Core/Crypto/Subkey.cs              |    92 +
 Axantum.AxCrypt.Core/Crypto/SymmetricIV.cs         |    90 +
 Axantum.AxCrypt.Core/Crypto/SymmetricKey.cs        |   154 +
 .../Crypto/SymmetricKeyThumbprint.cs               |   133 +
 .../Crypto/V1Aes128CryptoFactory.cs                |    86 +
 Axantum.AxCrypt.Core/Crypto/V1AesCrypto.cs         |   171 +
 Axantum.AxCrypt.Core/Crypto/V1DerivedKey.cs        |    61 +
 Axantum.AxCrypt.Core/Crypto/V1Hmac.cs              |    48 +
 .../Crypto/V2Aes128CryptoFactory.cs                |    50 +
 .../Crypto/V2Aes256CryptoFactory.cs                |    77 +
 Axantum.AxCrypt.Core/Crypto/V2AesCrypto.cs         |    64 +
 Axantum.AxCrypt.Core/Crypto/V2CryptoBase.cs        |   141 +
 Axantum.AxCrypt.Core/Crypto/V2DerivedKey.cs        |    55 +
 Axantum.AxCrypt.Core/Crypto/V2Hmac.cs              |    48 +
 Axantum.AxCrypt.Core/ErrorStatus.cs                |    45 +
 .../Extensions/ByteArrayExtensions.cs              |   254 +
 Axantum.AxCrypt.Core/Extensions/EnumExtensions.cs  |    48 +
 .../Extensions/PrimitiveTypeExtensions.cs          |   108 +
 .../Extensions/RuntimeFileInfoExtensions.cs        |   169 +
 .../Extensions/StreamExtensions.cs                 |   153 +
 .../Extensions/StringExtensions.cs                 |   215 +
 Axantum.AxCrypt.Core/Factory.cs                    |   247 +
 Axantum.AxCrypt.Core/Header/AxCrypt1Guid.cs        |    55 +
 Axantum.AxCrypt.Core/Header/DataHeaderBlock.cs     |    63 +
 .../Header/EncryptedDataPartBlock.cs               |    46 +
 .../Header/EncryptedHeaderBlock.cs                 |    47 +
 .../Header/FileInfoEncryptedHeaderBlock.cs         |   154 +
 Axantum.AxCrypt.Core/Header/HeaderBlock.cs         |   150 +
 Axantum.AxCrypt.Core/Header/HeaderBlockType.cs     |   151 +
 Axantum.AxCrypt.Core/Header/Headers.cs             |   204 +
 Axantum.AxCrypt.Core/Header/PreambleHeaderBlock.cs |    67 +
 .../Header/StringEncryptedHeaderBlockBase.cs       |    52 +
 .../Header/UnrecognizedHeaderBlock.cs              |    43 +
 .../Header/V1CompressionEncryptedHeaderBlock.cs    |    73 +
 .../V1CompressionInfoEncryptedHeaderBlock.cs       |    75 +
 Axantum.AxCrypt.Core/Header/V1DocumentHeaders.cs   |   415 +
 .../Header/V1EncryptionInfoEncryptedHeaderBlock.cs |   115 +
 .../Header/V1FileNameInfoEncryptedHeaderBlock.cs   |    80 +
 Axantum.AxCrypt.Core/Header/V1IdTagHeaderBlock.cs  |    76 +
 .../Header/V1KeyWrap1HeaderBlock.cs                |   142 +
 .../Header/V1KeyWrap2HeaderBlock.cs                |    43 +
 .../V1UnicodeFileNameInfoEncryptedHeaderBlock.cs   |    80 +
 .../Header/V2AsymmetricKeyWrapHeaderBlock.cs       |    65 +
 .../V2AsymmetricRecipientsEncryptedHeaderBlock.cs  |    44 +
 .../Header/V2CompressionEncryptedHeaderBlock.cs    |    72 +
 Axantum.AxCrypt.Core/Header/V2DocumentHeaders.cs   |   350 +
 Axantum.AxCrypt.Core/Header/V2HmacHeaderBlock.cs   |    69 +
 .../Header/V2KeyWrapHeaderBlock.cs                 |   214 +
 .../V2PlainTextLengthsEncryptedHeaderBlock.cs      |   100 +
 .../V2UnicodeFileNameInfoEncryptedHeaderBlock.cs   |    65 +
 Axantum.AxCrypt.Core/Header/VersionHeaderBlock.cs  |   109 +
 Axantum.AxCrypt.Core/IAxCryptDocument.cs           |    55 +
 Axantum.AxCrypt.Core/IO/AbstractJsonConverter.cs   |    26 +
 .../IO/EmailAddressJsonConverter.cs                |    28 +
 Axantum.AxCrypt.Core/IO/FileInfoTypes.cs           |    52 +
 Axantum.AxCrypt.Core/IO/FileLock.cs                |   113 +
 Axantum.AxCrypt.Core/IO/FileWatcherEventArgs.cs    |    50 +
 Axantum.AxCrypt.Core/IO/IFileWatcher.cs            |    39 +
 Axantum.AxCrypt.Core/IO/IRuntimeFileInfo.cs        |   154 +
 Axantum.AxCrypt.Core/IO/IWebCaller.cs              |    39 +
 Axantum.AxCrypt.Core/IO/LockingStream.cs           |   123 +
 Axantum.AxCrypt.Core/IO/LookAheadStream.cs         |   189 +
 Axantum.AxCrypt.Core/IO/NonClosingStream.cs        |   107 +
 Axantum.AxCrypt.Core/IO/ProgressStream.cs          |   151 +
 Axantum.AxCrypt.Core/IO/V1AxCryptDataStream.cs     |   141 +
 Axantum.AxCrypt.Core/IO/V1HmacStream.cs            |   200 +
 Axantum.AxCrypt.Core/IO/V2AxCryptDataStream.cs     |   240 +
 Axantum.AxCrypt.Core/IO/V2HmacStream.cs            |   193 +
 Axantum.AxCrypt.Core/Instance.cs                   |   156 +
 Axantum.AxCrypt.Core/Ipc/ArgumentBundles.cs        |    69 +
 .../Ipc/CommandCompleteEventArgs.cs                |    46 +
 Axantum.AxCrypt.Core/Ipc/CommandHandler.cs         |    74 +
 Axantum.AxCrypt.Core/Ipc/CommandItem.cs            |    52 +
 Axantum.AxCrypt.Core/Ipc/CommandService.cs         |   103 +
 .../Ipc/CommandServiceEventArgs.cs                 |    68 +
 Axantum.AxCrypt.Core/Ipc/CommandStatus.cs          |    40 +
 Axantum.AxCrypt.Core/Ipc/CommandVerb.cs            |    55 +
 Axantum.AxCrypt.Core/Ipc/IRequestClient.cs         |    37 +
 Axantum.AxCrypt.Core/Ipc/IRequestServer.cs         |    43 +
 .../Ipc/RequestCommandEventArgs.cs                 |    42 +
 Axantum.AxCrypt.Core/OS.cs                         |    64 +
 Axantum.AxCrypt.Core/Portable/AesManaged.cs        |    12 +
 Axantum.AxCrypt.Core/Portable/CipherMode.cs        |    18 +
 Axantum.AxCrypt.Core/Portable/CryptoStream.cs      |    13 +
 Axantum.AxCrypt.Core/Portable/CryptoStreamMode.cs  |    15 +
 Axantum.AxCrypt.Core/Portable/HMAC.cs              |    15 +
 Axantum.AxCrypt.Core/Portable/HMACSHA1.cs          |    12 +
 Axantum.AxCrypt.Core/Portable/HMACSHA512.cs        |    13 +
 Axantum.AxCrypt.Core/Portable/HashAlgorithm.cs     |    38 +
 Axantum.AxCrypt.Core/Portable/ICloneable.cs        |    13 +
 Axantum.AxCrypt.Core/Portable/ICryptoTransform.cs  |    23 +
 Axantum.AxCrypt.Core/Portable/IDataErrorInfo.cs    |    15 +
 Axantum.AxCrypt.Core/Portable/IPath.cs             |    26 +
 Axantum.AxCrypt.Core/Portable/IPortableFactory.cs  |    35 +
 Axantum.AxCrypt.Core/Portable/ISemaphore.cs        |    14 +
 Axantum.AxCrypt.Core/Portable/ISingleThread.cs     |    14 +
 Axantum.AxCrypt.Core/Portable/KeySizes.cs          |    17 +
 .../Portable/KeyedHashAlgorithm.cs                 |    13 +
 Axantum.AxCrypt.Core/Portable/PaddingMode.cs       |    17 +
 .../Portable/RandomNumberGenerator.cs              |    15 +
 Axantum.AxCrypt.Core/Portable/SHA1Managed.cs       |    12 +
 .../Portable/SymmetricAlgorithm.cs                 |   170 +
 Axantum.AxCrypt.Core/Properties/AssemblyInfo.cs    |    67 +
 .../Properties/AssemblyInfo.template               |    46 +
 .../Properties/Resources.Designer.cs               |    89 +
 Axantum.AxCrypt.Core/Properties/Resources.resx     |   128 +
 Axantum.AxCrypt.Core/Reader/AxCryptItemType.cs     |    63 +
 Axantum.AxCrypt.Core/Reader/AxCryptReader.cs       |   259 +
 Axantum.AxCrypt.Core/Reader/V1AxCryptReader.cs     |    98 +
 Axantum.AxCrypt.Core/Reader/V2AxCryptReader.cs     |    92 +
 Axantum.AxCrypt.Core/Reader/VxAxCryptReader.cs     |    82 +
 Axantum.AxCrypt.Core/Runtime/AxCryptException.cs   |    57 +
 Axantum.AxCrypt.Core/Runtime/DelayedAction.cs      |   111 +
 .../Runtime/FileFormatException.cs                 |    60 +
 Axantum.AxCrypt.Core/Runtime/IDataProtection.cs    |    41 +
 Axantum.AxCrypt.Core/Runtime/IDelayTimer.cs        |    41 +
 Axantum.AxCrypt.Core/Runtime/ILauncher.cs          |    43 +
 Axantum.AxCrypt.Core/Runtime/ILogging.cs           |    59 +
 .../Runtime/IRuntimeEnvironment.cs                 |    68 +
 Axantum.AxCrypt.Core/Runtime/ISleep.cs             |    39 +
 Axantum.AxCrypt.Core/Runtime/IThreadWorker.cs      |    81 +
 Axantum.AxCrypt.Core/Runtime/ITiming.cs            |    37 +
 .../Runtime/IncorrectDataException.cs              |    60 +
 .../Runtime/InternalErrorException.cs              |    64 +
 Axantum.AxCrypt.Core/Runtime/LogLevel.cs           |    43 +
 Axantum.AxCrypt.Core/Runtime/LoggingEventArgs.cs   |    42 +
 Axantum.AxCrypt.Core/Runtime/Platform.cs           |    47 +
 Axantum.AxCrypt.Core/Runtime/SleepEventArgs.cs     |    42 +
 .../Runtime/ThreadWorkerEventArgs.cs               |    51 +
 .../Runtime/ThreadWorkerProgressContext.cs         |   126 +
 Axantum.AxCrypt.Core/Runtime/TypeDiscovery.cs      |    66 +
 Axantum.AxCrypt.Core/Runtime/WorkFolder.cs         |    44 +
 Axantum.AxCrypt.Core/Runtime/WorkFolderWatcher.cs  |    78 +
 Axantum.AxCrypt.Core/Runtime/WorkerGroup.cs        |   329 +
 .../Runtime/WorkerGroupProgressContext.cs          |   118 +
 Axantum.AxCrypt.Core/Session/ActiveFile.cs         |   303 +
 Axantum.AxCrypt.Core/Session/ActiveFileAction.cs   |   358 +
 .../Session/ActiveFileChangedEventArgs.cs          |    44 +
 .../Session/ActiveFileCollection.cs                |    46 +
 Axantum.AxCrypt.Core/Session/ActiveFileComparer.cs |    82 +
 .../Session/ActiveFileProperties.cs                |    60 +
 Axantum.AxCrypt.Core/Session/ActiveFileStatus.cs   |    56 +
 .../Session/ActiveFileVisualState.cs               |    45 +
 Axantum.AxCrypt.Core/Session/ActiveFileWatcher.cs  |    69 +
 Axantum.AxCrypt.Core/Session/ChangedEventMode.cs   |    40 +
 Axantum.AxCrypt.Core/Session/FileSystemState.cs    |   539 +
 Axantum.AxCrypt.Core/Session/PassphraseIdentity.cs |    61 +
 Axantum.AxCrypt.Core/Session/ProcessState.cs       |   142 +
 .../Session/SessionNotification.cs                 |   146 +
 .../Session/SessionNotificationEventArgs.cs        |    42 +
 .../Session/SessionNotificationHandler.cs          |   135 +
 .../Session/SessionNotificationType.cs             |    50 +
 Axantum.AxCrypt.Core/Session/SessionNotify.cs      |    55 +
 Axantum.AxCrypt.Core/Session/UserAsymmetricKeys.cs |    45 +
 .../Session/UserAsymmetricKeysStore.cs             |   184 +
 Axantum.AxCrypt.Core/Session/WatchedFolder.cs      |   184 +
 .../Session/WatchedFolderChangedEventArgs.cs       |    47 +
 Axantum.AxCrypt.Core/UI/CancelProgressContext.cs   |   140 +
 Axantum.AxCrypt.Core/UI/EmailAddress.cs            |    23 +
 Axantum.AxCrypt.Core/UI/FileOperation.cs           |   300 +
 Axantum.AxCrypt.Core/UI/FileOperationContext.cs    |    47 +
 Axantum.AxCrypt.Core/UI/FileOperationEventArgs.cs  |    58 +
 Axantum.AxCrypt.Core/UI/FileOperationStatus.cs     |    50 +
 .../UI/FileOperationsController.cs                 |   534 +
 Axantum.AxCrypt.Core/UI/IProgressBackground.cs     |    43 +
 Axantum.AxCrypt.Core/UI/IProgressContext.cs        |    55 +
 Axantum.AxCrypt.Core/UI/IStatusChecker.cs          |    45 +
 Axantum.AxCrypt.Core/UI/IUIThread.cs               |    43 +
 Axantum.AxCrypt.Core/UI/IUserSettings.cs           |    82 +
 Axantum.AxCrypt.Core/UI/KnownFolder.cs             |    87 +
 Axantum.AxCrypt.Core/UI/KnownKeys.cs               |   178 +
 Axantum.AxCrypt.Core/UI/Options.cs                 |  1251 +
 Axantum.AxCrypt.Core/UI/ParallelFileOperation.cs   |    85 +
 Axantum.AxCrypt.Core/UI/ProgressContext.cs         |   243 +
 Axantum.AxCrypt.Core/UI/ProgressEventArgs.cs       |    41 +
 Axantum.AxCrypt.Core/UI/PublicResources.cs         |    86 +
 Axantum.AxCrypt.Core/UI/UpdateCheck.cs             |   256 +
 Axantum.AxCrypt.Core/UI/UserSettings.cs            |   283 +
 Axantum.AxCrypt.Core/UI/VersionEventArgs.cs        |    50 +
 Axantum.AxCrypt.Core/UI/VersionResponse.cs         |    71 +
 Axantum.AxCrypt.Core/UI/VersionUpdateStatus.cs     |    41 +
 .../UI/ViewModel/CreateNewAccountViewModel.cs      |   112 +
 .../UI/ViewModel/DelegateAction.cs                 |    85 +
 .../UI/ViewModel/FileOperationViewModel.cs         |   413 +
 .../UI/ViewModel/FileSelectionEventArgs.cs         |    51 +
 .../UI/ViewModel/FileSelectionType.cs              |    44 +
 Axantum.AxCrypt.Core/UI/ViewModel/IAction.cs       |    45 +
 Axantum.AxCrypt.Core/UI/ViewModel/IViewModel.cs    |    39 +
 .../UI/ViewModel/IdentityViewModel.cs              |   212 +
 .../UI/ViewModel/KnownFoldersViewModel.cs          |   111 +
 .../UI/ViewModel/LogOnAccountViewModel.cs          |   124 +
 .../UI/ViewModel/LogOnEventArgs.cs                 |    58 +
 .../UI/ViewModel/LogOnViewModel.cs                 |   125 +
 Axantum.AxCrypt.Core/UI/ViewModel/MainViewModel.cs |   395 +
 .../UI/ViewModel/NewPassphraseViewModel.cs         |   124 +
 .../UI/ViewModel/ValidationError.cs                |    41 +
 Axantum.AxCrypt.Core/UI/ViewModel/ViewModelBase.cs |   158 +
 .../UI/ViewModel/WatchedFoldersViewModel.cs        |   148 +
 Axantum.AxCrypt.Core/V1AxCryptDocument.cs          |   345 +
 Axantum.AxCrypt.Core/V2AxCryptDocument.cs          |   261 +
 Axantum.AxCrypt.Core/resources/axcrypticon.ico     |   Bin 0 -> 22486 bytes
 .../resources/bouncycastlelicense.txt              |     5 +
 Axantum.AxCrypt.Core/resources/json.netlicense.txt |     9 +
 .../Axantum.AxCrypt.Desktop.Test.csproj            |    80 +
 Axantum.AxCrypt.Desktop.Test/AxantumStrongName.pfx |   Bin 0 -> 1764 bytes
 .../Properties/AssemblyInfo.cs                     |    36 +
 Axantum.AxCrypt.Desktop.Test/TestFileWatcher.cs    |   157 +
 .../Axantum.AxCrypt.Desktop.csproj                 |    69 +
 Axantum.AxCrypt.Desktop/AxantumStrongName.pfx      |   Bin 0 -> 1764 bytes
 Axantum.AxCrypt.Desktop/DesktopFactory.cs          |    19 +
 Axantum.AxCrypt.Desktop/FileWatcher.cs             |   161 +
 Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.cs |    76 +
 .../Properties/AssemblyInfo.template               |    46 +
 Axantum.AxCrypt.Forms/Axantum.AxCrypt.Forms.csproj |    77 +
 Axantum.AxCrypt.Forms/AxantumStrongName.pfx        |   Bin 0 -> 1764 bytes
 Axantum.AxCrypt.Forms/DataProtection.cs            |    54 +
 Axantum.AxCrypt.Forms/ProgressBackground.cs        |   195 +
 Axantum.AxCrypt.Forms/Properties/AssemblyInfo.cs   |    72 +
 .../Properties/AssemblyInfo.template               |    46 +
 Axantum.AxCrypt.Mac/AppController.cs               |   228 +
 Axantum.AxCrypt.Mac/AppDelegate.cs                 |   113 +
 Axantum.AxCrypt.Mac/Axantum.AxCrypt.Mac.csproj     |   157 +
 Axantum.AxCrypt.Mac/Info.plist                     |    88 +
 Axantum.AxCrypt.Mac/Main.cs                        |    18 +
 Axantum.AxCrypt.Mac/MainMenu.xib                   |   757 +
 Axantum.AxCrypt.Mac/MainMenu.xib.designer.cs       |    33 +
 Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.icns  |   Bin 0 -> 60777 bytes
 Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.png   |   Bin 0 -> 23823 bytes
 Axantum.AxCrypt.Mac/Resources/logo_axantum.png     |   Bin 0 -> 16758 bytes
 Axantum.AxCrypt.Mac/Resources/tretton37.png        |   Bin 0 -> 9549 bytes
 Axantum.AxCrypt.Mac/Views/CreatePassphraseView.cs  |    56 +
 .../Views/CreatePassphraseView.designer.cs         |    72 +
 Axantum.AxCrypt.Mac/Views/CreatePassphraseView.xib |   649 +
 .../Views/CreatePassphraseViewController.cs        |    71 +
 Axantum.AxCrypt.Mac/Views/PasswordView.cs          |    41 +
 Axantum.AxCrypt.Mac/Views/PasswordView.designer.cs |    34 +
 Axantum.AxCrypt.Mac/Views/PasswordView.xib         |   302 +
 .../Views/PasswordViewController.cs                |    55 +
 Axantum.AxCrypt.Mac/Windows/AboutWindow.cs         |    35 +
 .../Windows/AboutWindow.designer.cs                |    43 +
 Axantum.AxCrypt.Mac/Windows/AboutWindow.xib        |   659 +
 .../Windows/AboutWindowController.cs               |    69 +
 Axantum.AxCrypt.Mac/Windows/MainWindow.cs          |    83 +
 Axantum.AxCrypt.Mac/Windows/MainWindow.designer.cs |   106 +
 Axantum.AxCrypt.Mac/Windows/MainWindow.xib         |   928 +
 .../Windows/MainWindowController.cs                |    50 +
 Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.cs  |    31 +
 .../Windows/OpenFileFromFinder.designer.cs         |    40 +
 Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.xib |   529 +
 .../Windows/OpenFileFromFinderController.cs        |    66 +
 .../Windows/VersionInformationWindow.cs            |    31 +
 .../Windows/VersionInformationWindow.designer.cs   |    61 +
 .../Windows/VersionInformationWindow.xib           |   489 +
 .../Windows/VersionInformationWindowController.cs  |    75 +
 Axantum.AxCrypt.Mono.Test/AboutThisAssembly.txt    |    10 +
 .../Axantum.AxCrypt.Mono.Test.csproj               |    95 +
 Axantum.AxCrypt.Mono.Test/AxantumStrongName.pfx    |   Bin 0 -> 1764 bytes
 .../Properties/AssemblyInfo.cs                     |    68 +
 .../Properties/Resources.Designer.cs               |    49 +
 .../Properties/Resources.resx                      |    15 +
 .../TestDelegateTraceListener.cs                   |    64 +
 Axantum.AxCrypt.Mono.Test/TestLogging.cs           |   200 +
 .../TestRuntimeEnvironment.cs                      |   131 +
 Axantum.AxCrypt.Mono.Test/TestRuntimeFileInfo.cs   |   153 +
 Axantum.AxCrypt.Mono/AboutThisAssembly.txt         |    14 +
 Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.csproj   |    99 +
 .../Axantum.AxCrypt.Mono.projitems                 |    40 +
 Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.shproj   |    11 +
 Axantum.AxCrypt.Mono/AxantumStrongName.pfx         |   Bin 0 -> 1764 bytes
 Axantum.AxCrypt.Mono/DelayTimer.cs                 |    96 +
 Axantum.AxCrypt.Mono/DelegateTraceListener.cs      |    64 +
 Axantum.AxCrypt.Mono/HttpRequestClient.cs          |    79 +
 Axantum.AxCrypt.Mono/HttpRequestServer.cs          |   129 +
 Axantum.AxCrypt.Mono/Launcher.cs                   |   147 +
 Axantum.AxCrypt.Mono/Logging.cs                    |   204 +
 Axantum.AxCrypt.Mono/Portable/AxCryptHMACSHA1.cs   |    69 +
 .../Portable/CryptographyCryptoTransformWrapper.cs |    53 +
 .../Portable/PortableCryptoStreamWrapper.cs        |   108 +
 .../Portable/PortableCryptoTransformWrapper.cs     |    52 +
 Axantum.AxCrypt.Mono/Portable/PortableFactory.cs   |    78 +
 .../Portable/PortableHashAlgorithmWrapper.cs       |    83 +
 .../Portable/PortableHmacWrapper.cs                |   106 +
 .../Portable/PortablePathImplementation.cs         |    52 +
 .../PortableRandomNumberGeneratorWrapper.cs        |    28 +
 .../Portable/PortableSemaphoreWrapper.cs           |    33 +
 .../Portable/PortableSymmetricAlgorithmWrapper.cs  |   237 +
 Axantum.AxCrypt.Mono/Portable/SingleThread.cs      |    72 +
 Axantum.AxCrypt.Mono/Properties/AssemblyInfo.cs    |    78 +
 .../Properties/AssemblyInfo.template               |    46 +
 Axantum.AxCrypt.Mono/RuntimeEnvironment.cs         |   234 +
 Axantum.AxCrypt.Mono/RuntimeFileInfo.cs            |   333 +
 Axantum.AxCrypt.Mono/Sleep.cs                      |    54 +
 Axantum.AxCrypt.Mono/ThreadWorker.cs               |   296 +
 Axantum.AxCrypt.Mono/Timing.cs                     |    50 +
 Axantum.AxCrypt.Mono/WebCaller.cs                  |    57 +
 Axantum.AxCrypt.MonoTouch/AboutThisAssembly.txt    |    30 +
 .../Axantum.AxCrypt.MonoTouch.csproj               |    84 +
 Axantum.AxCrypt.MonoTouch/DataProtection.cs        |    56 +
 Axantum.AxCrypt.MonoTouch/FileWatcher.cs           |    68 +
 Axantum.AxCrypt.MonoTouch/Logging.cs               |   149 +
 .../Properties/AssemblyInfo.cs                     |    69 +
 Axantum.AxCrypt.MonoTouch/RuntimeEnvironment.cs    |    84 +
 Axantum.AxCrypt.iOS/AboutThisAssembly.txt          |     8 +
 Axantum.AxCrypt.iOS/AppDelegate.cs                 |   279 +
 Axantum.AxCrypt.iOS/AxCrypt.Mono/DataProtection.cs |    19 +
 Axantum.AxCrypt.iOS/AxCrypt.Mono/FileWatcher.cs    |    24 +
 Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.csproj     |   237 +
 Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.sln        |    32 +
 .../Components/btprogresshud-1.5.info              |     1 +
 .../Components/btprogresshud-1.5.png               |   Bin 0 -> 9234 bytes
 .../btprogresshud-1.5/component/Details.md         |    32 +
 .../btprogresshud-1.5/component/GettingStarted.md  |    69 +
 .../btprogresshud-1.5/component/License.md         |    44 +
 .../btprogresshud-1.5/component/Manifest.xml       |    14 +
 .../component/icons/btprogresshud_128x128.png      |   Bin 0 -> 9234 bytes
 .../component/icons/btprogresshud_512x512.png      |   Bin 0 -> 82636 bytes
 .../btprogresshud-1.5/lib/ios/BTProgressHUD.dll    |   Bin 0 -> 20992 bytes
 .../samples/BTProgressHUDSample/BTProgressHUD.dll  |   Bin 0 -> 20992 bytes
 .../BTProgressHUDSample/BTProgressHUDSample.sln    |    32 +
 .../BTProgressHUDSample/AppDelegate.cs             |    47 +
 .../BTProgressHUDSample/BTProgressHUDDemo.csproj   |   104 +
 .../BTProgressHUDSample/Default-568h at 2x.png        |   Bin 0 -> 367019 bytes
 .../BTProgressHUDSample/Default.png                |   Bin 0 -> 68829 bytes
 .../BTProgressHUDSample/Default at 2x.png             |   Bin 0 -> 91679 bytes
 .../BTProgressHUDSample/Info.plist                 |    26 +
 .../BTProgressHUDSample/Main.cs                    |    20 +
 .../BTProgressHUDSample/MainView.cs                |   124 +
 Axantum.AxCrypt.iOS/DecryptionViewController.cs    |    79 +
 Axantum.AxCrypt.iOS/FileListingViewController.cs   |    83 +
 Axantum.AxCrypt.iOS/FilePresenter.cs               |    77 +
 .../Images/App Icons/logo 114x114.png              |   Bin 0 -> 26063 bytes
 .../Images/App Icons/logo 144x144.png              |   Bin 0 -> 38449 bytes
 .../Images/App Icons/logo 57x57.png                |   Bin 0 -> 8731 bytes
 .../Images/App Icons/logo 72x72.png                |   Bin 0 -> 12487 bytes
 .../Images/AppStore Images/iPad (Retina)/About.png |   Bin 0 -> 559826 bytes
 .../iPad (Retina)/Document with actions.png        |   Bin 0 -> 471443 bytes
 .../AppStore Images/iPad (Retina)/Main View.png    |   Bin 0 -> 197995 bytes
 .../iPad (Retina)/Password entry.png               |   Bin 0 -> 539155 bytes
 .../iPhone 3.5in/Document with actions.png         |   Bin 0 -> 167299 bytes
 .../AppStore Images/iPhone 3.5in/Main View.png     |   Bin 0 -> 90940 bytes
 .../iPhone 3.5in/Password entry.png                |   Bin 0 -> 240831 bytes
 .../iPhone 3.5in/Received documents.png            |   Bin 0 -> 115535 bytes
 .../iPhone 3.5in/Transferred documents.png         |   Bin 0 -> 126188 bytes
 .../iPhone 4in/Document with actions.png           |   Bin 0 -> 200806 bytes
 .../AppStore Images/iPhone 4in/Main View.png       |   Bin 0 -> 119406 bytes
 .../AppStore Images/iPhone 4in/Password entry.png  |   Bin 0 -> 266437 bytes
 .../iPhone 4in/Received documents.png              |   Bin 0 -> 120132 bytes
 .../iPhone 4in/Transferred documents.png           |   Bin 0 -> 133195 bytes
 ...mulator Screen shot Oct 16, 2012 2.30.48 PM.png |   Bin 0 -> 170115 bytes
 ...mulator Screen shot Oct 16, 2012 2.31.47 PM.png |   Bin 0 -> 171948 bytes
 ...mulator Screen shot Oct 16, 2012 2.34.39 PM.png |   Bin 0 -> 216996 bytes
 ...mulator Screen shot Oct 16, 2012 2.32.44 PM.png |   Bin 0 -> 87415 bytes
 .../iPhone iOS Simulator Screen shot.png           |   Bin 0 -> 73495 bytes
 .../Spotlight & Settings Icons/logo 100x100.png    |   Bin 0 -> 20925 bytes
 .../Spotlight & Settings Icons/logo 29x29.png      |   Bin 0 -> 3682 bytes
 .../Spotlight & Settings Icons/logo 50x50.png      |   Bin 0 -> 7300 bytes
 .../Spotlight & Settings Icons/logo 58x58.png      |   Bin 0 -> 8993 bytes
 .../iTunes Artwork/iTunes Artwork 1024x1024.png    |   Bin 0 -> 126288 bytes
 .../iTunes Artwork/iTunes Artwork 512x512.png      |   Bin 0 -> 47727 bytes
 Axantum.AxCrypt.iOS/Images/logo.png                |   Bin 0 -> 17179 bytes
 Axantum.AxCrypt.iOS/Info.plist                     |    91 +
 Axantum.AxCrypt.iOS/Infrastructure/BasePath.cs     |    44 +
 .../Infrastructure/EditableTableViewSource.cs      |    34 +
 Axantum.AxCrypt.iOS/Infrastructure/Theme.cs        |    94 +
 .../Infrastructure/ThemedFileElement.cs            |    51 +
 .../Infrastructure/ThemedStringElement.cs          |    24 +
 .../Infrastructure/UIAlertViewOkCancelDelegate.cs  |    33 +
 Axantum.AxCrypt.iOS/Infrastructure/Utilities.cs    |    16 +
 Axantum.AxCrypt.iOS/Main.cs                        |    15 +
 Axantum.AxCrypt.iOS/MainViewController.cs          |   113 +
 Axantum.AxCrypt.iOS/PassphraseController.cs        |    65 +
 Axantum.AxCrypt.iOS/Properties/AssemblyInfo.cs     |    69 +
 Axantum.AxCrypt.iOS/Resources/Default-568h at 2x.png  |   Bin 0 -> 18594 bytes
 Axantum.AxCrypt.iOS/Resources/Default.png          |   Bin 0 -> 73333 bytes
 Axantum.AxCrypt.iOS/Resources/Default at 2x.png       |   Bin 0 -> 169780 bytes
 Axantum.AxCrypt.iOS/WebViewController.cs           |    59 +
 Axantum.AxCrypt.iOS/iTunesArtwork                  |   Bin 0 -> 47727 bytes
 Axantum.AxCrypt.iOS/iTunesArtwork at 2x               |   Bin 0 -> 126288 bytes
 Axantum.AxCrypt/AboutBox.Designer.cs               |   116 +
 Axantum.AxCrypt/AboutBox.cs                        |   112 +
 Axantum.AxCrypt/AboutBox.resx                      |   745 +
 Axantum.AxCrypt/AboutBox.sv.resx                   |   132 +
 Axantum.AxCrypt/AboutThisProgram.txt               |    33 +
 Axantum.AxCrypt/AxCrypt.ico                        |   Bin 0 -> 22486 bytes
 Axantum.AxCrypt/AxCryptMainForm.Designer.cs        |   601 +
 Axantum.AxCrypt/AxCryptMainForm.cs                 |  1411 +
 Axantum.AxCrypt/AxCryptMainForm.resx               |  1501 +
 Axantum.AxCrypt/AxCryptMainForm.sv.resx            |  2204 ++
 Axantum.AxCrypt/Axantum.AxCrypt.csproj             |   289 +
 Axantum.AxCrypt/Axantum.AxCrypt_ml.xml             |  3352 ++
 Axantum.AxCrypt/AxantumStrongName.pfx              |   Bin 0 -> 1764 bytes
 Axantum.AxCrypt/ConfirmWipeDialog.Designer.cs      |   120 +
 Axantum.AxCrypt/ConfirmWipeDialog.cs               |    25 +
 Axantum.AxCrypt/ConfirmWipeDialog.resx             |   705 +
 Axantum.AxCrypt/ConfirmWipeDialog.sv.resx          |   141 +
 Axantum.AxCrypt/CreateNewAccountDialog.Designer.cs |   207 +
 Axantum.AxCrypt/CreateNewAccountDialog.cs          |    90 +
 Axantum.AxCrypt/CreateNewAccountDialog.resx        |   129 +
 Axantum.AxCrypt/DebugLogOutputDialog.Designer.cs   |    62 +
 Axantum.AxCrypt/DebugLogOutputDialog.cs            |    31 +
 Axantum.AxCrypt/DebugLogOutputDialog.resx          |   120 +
 Axantum.AxCrypt/DebugOptionsDialog.Designer.cs     |    97 +
 Axantum.AxCrypt/DebugOptionsDialog.cs              |    30 +
 Axantum.AxCrypt/DebugOptionsDialog.resx            |   245 +
 Axantum.AxCrypt/DebugOptionsDialog.sv.resx         |   120 +
 .../DecryptPassphraseDialog.Designer.cs            |   119 +
 Axantum.AxCrypt/DecryptPassphraseDialog.cs         |    61 +
 Axantum.AxCrypt/DecryptPassphraseDialog.resx       |   727 +
 Axantum.AxCrypt/DecryptPassphraseDialog.sv.resx    |   553 +
 Axantum.AxCrypt/Extensions.cs                      |    57 +
 Axantum.AxCrypt/KnownFoldersDiscovery.cs           |   140 +
 Axantum.AxCrypt/LogOnAccountDialog.Designer.cs     |   222 +
 Axantum.AxCrypt/LogOnAccountDialog.cs              |    98 +
 Axantum.AxCrypt/LogOnAccountDialog.resx            |   126 +
 Axantum.AxCrypt/LogOnDialog.Designer.cs            |   176 +
 Axantum.AxCrypt/LogOnDialog.cs                     |   111 +
 Axantum.AxCrypt/LogOnDialog.resx                   |   823 +
 Axantum.AxCrypt/LogOnDialog.sv.resx                |   574 +
 Axantum.AxCrypt/NewPassphraseDialog.Designer.cs    |   192 +
 Axantum.AxCrypt/NewPassphraseDialog.cs             |   120 +
 Axantum.AxCrypt/NewPassphraseDialog.resx           |   949 +
 Axantum.AxCrypt/NewPassphraseDialog.sv.resx        |   577 +
 Axantum.AxCrypt/Preferences.cs                     |    57 +
 Axantum.AxCrypt/Program.cs                         |   160 +
 Axantum.AxCrypt/Properties/AssemblyInfo.cs         |    72 +
 Axantum.AxCrypt/Properties/AssemblyInfo.template   |    46 +
 Axantum.AxCrypt/Properties/Resources.Designer.cs   |   791 +
 Axantum.AxCrypt/Properties/Resources.resx          |   363 +
 Axantum.AxCrypt/Properties/Resources.sv.resx       |   261 +
 Axantum.AxCrypt/Properties/Settings.Designer.cs    |    26 +
 Axantum.AxCrypt/Properties/Settings.settings       |     5 +
 Axantum.AxCrypt/UIThread.cs                        |    80 +
 Axantum.AxCrypt/WatchedFoldersDialog.Designer.cs   |   111 +
 Axantum.AxCrypt/WatchedFoldersDialog.cs            |    77 +
 Axantum.AxCrypt/WatchedFoldersDialog.resx          |   503 +
 Axantum.AxCrypt/app.config                         |    11 +
 Axantum.AxCrypt/resources/DocumentsLibrary.ico     |   Bin 0 -> 22486 bytes
 Axantum.AxCrypt/resources/DropBox.ico              |   Bin 0 -> 22486 bytes
 Axantum.AxCrypt/resources/GoogleDrive.ico          |   Bin 0 -> 15406 bytes
 Axantum.AxCrypt/resources/SkyDrive.ico             |   Bin 0 -> 26694 bytes
 Axantum.AxCrypt/resources/activefilegreen16.png    |   Bin 0 -> 391 bytes
 .../resources/activefileknownkeygreen16.png        |   Bin 0 -> 488 bytes
 Axantum.AxCrypt/resources/axcrypticon.ico          |   Bin 0 -> 22486 bytes
 Axantum.AxCrypt/resources/axcrypticon128.png       |   Bin 0 -> 23823 bytes
 .../resources/closeremovestandbygreen32.png        |   Bin 0 -> 1167 bytes
 .../resources/closeremovestandbyred32.png          |   Bin 0 -> 1134 bytes
 Axantum.AxCrypt/resources/decryptedfilered16.png   |   Bin 0 -> 477 bytes
 .../resources/decryptedunknownkeyfilered16.png     |   Bin 0 -> 431 bytes
 Axantum.AxCrypt/resources/decryptlockopen32.png    |   Bin 0 -> 928 bytes
 Axantum.AxCrypt/resources/encryptionkeygreen32.png |   Bin 0 -> 1071 bytes
 Axantum.AxCrypt/resources/encryptionkeyred32.png   |   Bin 0 -> 1017 bytes
 Axantum.AxCrypt/resources/encryptlock32.png        |   Bin 0 -> 962 bytes
 Axantum.AxCrypt/resources/exclamationgreen16.png   |   Bin 0 -> 443 bytes
 Axantum.AxCrypt/resources/exclamationgreen32.png   |   Bin 0 -> 854 bytes
 Axantum.AxCrypt/resources/fileknownkeygreen16.png  |   Bin 0 -> 488 bytes
 Axantum.AxCrypt/resources/helpquestiongreen32.png  |   Bin 0 -> 836 bytes
 Axantum.AxCrypt/resources/inactivefilegreen16.png  |   Bin 0 -> 447 bytes
 Axantum.AxCrypt/resources/opendocument32.png       |   Bin 0 -> 817 bytes
 Axantum.AxCrypt/resources/refreshgreen.png         |   Bin 0 -> 1269 bytes
 Axantum.AxCrypt/resources/refreshred.png           |   Bin 0 -> 1212 bytes
 Axantum.AxCrypt/resources/trashred16.png           |   Bin 0 -> 378 bytes
 BouncyCastle.AxCrypt/AxantumStrongName.pfx         |   Bin 0 -> 1764 bytes
 BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.csproj   |  1370 +
 BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.sln      |    20 +
 BouncyCastle.AxCrypt/Contributors.html             |   122 +
 BouncyCastle.AxCrypt/License.html                  |    39 +
 BouncyCastle.AxCrypt/NBuild.build                  |   247 +
 BouncyCastle.AxCrypt/ReadMe-AxCrypt.txt            |     0
 BouncyCastle.AxCrypt/Readme.html                   |   455 +
 BouncyCastle.AxCrypt/bzip2/src/BZip2Constants.cs   |   103 +
 .../bzip2/src/CBZip2InputStream.cs                 |   919 +
 .../bzip2/src/CBZip2OutputStream.cs                |  1697 +
 BouncyCastle.AxCrypt/bzip2/src/CRC.cs              |   134 +
 BouncyCastle.AxCrypt/checklist.txt                 |    16 +
 BouncyCastle.AxCrypt/crypto.csproj                 |  3994 ++
 BouncyCastle.AxCrypt/doc/crypto.xml                | 21747 +++++++++++
 BouncyCastle.AxCrypt/doc/wp7/crypto.xml            | 19296 ++++++++++
 BouncyCastle.AxCrypt/src/AssemblyInfo.cs           |    96 +
 BouncyCastle.AxCrypt/src/asn1/ASN1Generator.cs     |    27 +
 .../src/asn1/ASN1OctetStringParser.cs              |    10 +
 .../src/asn1/ASN1SequenceParser.cs                 |     8 +
 BouncyCastle.AxCrypt/src/asn1/ASN1SetParser.cs     |     8 +
 BouncyCastle.AxCrypt/src/asn1/ASN1StreamParser.cs  |   234 +
 .../src/asn1/ASN1TaggedObjectParser.cs             |    10 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Encodable.cs     |    78 +
 .../src/asn1/Asn1EncodableVector.cs                |    93 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Exception.cs     |    30 +
 BouncyCastle.AxCrypt/src/asn1/Asn1InputStream.cs   |   368 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Null.cs          |    18 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Object.cs        |    63 +
 BouncyCastle.AxCrypt/src/asn1/Asn1OctetString.cs   |   119 +
 BouncyCastle.AxCrypt/src/asn1/Asn1OutputStream.cs  |    35 +
 .../src/asn1/Asn1ParsingException.cs               |    29 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Sequence.cs      |   268 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Set.cs           |   351 +
 BouncyCastle.AxCrypt/src/asn1/Asn1TaggedObject.cs  |   178 +
 BouncyCastle.AxCrypt/src/asn1/Asn1Tags.cs          |    36 +
 BouncyCastle.AxCrypt/src/asn1/BERGenerator.cs      |   102 +
 .../src/asn1/BEROctetStringGenerator.cs            |   120 +
 .../src/asn1/BEROctetStringParser.cs               |    36 +
 .../src/asn1/BERSequenceGenerator.cs               |    24 +
 BouncyCastle.AxCrypt/src/asn1/BERSequenceParser.cs |    24 +
 BouncyCastle.AxCrypt/src/asn1/BERSetGenerator.cs   |    24 +
 BouncyCastle.AxCrypt/src/asn1/BERSetParser.cs      |    24 +
 .../src/asn1/BERTaggedObjectParser.cs              |    71 +
 .../src/asn1/BerApplicationSpecific.cs             |    15 +
 .../src/asn1/BerApplicationSpecificParser.cs       |    29 +
 BouncyCastle.AxCrypt/src/asn1/BerNull.cs           |    35 +
 BouncyCastle.AxCrypt/src/asn1/BerOctetString.cs    |   135 +
 BouncyCastle.AxCrypt/src/asn1/BerOutputStream.cs   |    36 +
 BouncyCastle.AxCrypt/src/asn1/BerSequence.cs       |    69 +
 BouncyCastle.AxCrypt/src/asn1/BerSet.cs            |    70 +
 BouncyCastle.AxCrypt/src/asn1/BerTaggedObject.cs   |   108 +
 .../src/asn1/ConstructedOctetStream.cs             |   102 +
 BouncyCastle.AxCrypt/src/asn1/DERExternal.cs       |   207 +
 BouncyCastle.AxCrypt/src/asn1/DERExternalParser.cs |    26 +
 BouncyCastle.AxCrypt/src/asn1/DERGenerator.cs      |   107 +
 .../src/asn1/DEROctetStringParser.cs               |    36 +
 .../src/asn1/DERSequenceGenerator.cs               |    40 +
 BouncyCastle.AxCrypt/src/asn1/DERSequenceParser.cs |    24 +
 BouncyCastle.AxCrypt/src/asn1/DERSetGenerator.cs   |    40 +
 BouncyCastle.AxCrypt/src/asn1/DERSetParser.cs      |    24 +
 .../src/asn1/DefiniteLengthInputStream.cs          |   100 +
 .../src/asn1/DerApplicationSpecific.cs             |   237 +
 BouncyCastle.AxCrypt/src/asn1/DerBMPString.cs      |   115 +
 BouncyCastle.AxCrypt/src/asn1/DerBitString.cs      |   248 +
 BouncyCastle.AxCrypt/src/asn1/DerBoolean.cs        |   122 +
 BouncyCastle.AxCrypt/src/asn1/DerEnumerated.cs     |   124 +
 BouncyCastle.AxCrypt/src/asn1/DerGeneralString.cs  |    81 +
 .../src/asn1/DerGeneralizedTime.cs                 |   308 +
 BouncyCastle.AxCrypt/src/asn1/DerIA5String.cs      |   145 +
 BouncyCastle.AxCrypt/src/asn1/DerInteger.cs        |   117 +
 BouncyCastle.AxCrypt/src/asn1/DerNull.cs           |    41 +
 BouncyCastle.AxCrypt/src/asn1/DerNumericString.cs  |   138 +
 .../src/asn1/DerObjectIdentifier.cs                |   347 +
 BouncyCastle.AxCrypt/src/asn1/DerOctetString.cs    |    34 +
 BouncyCastle.AxCrypt/src/asn1/DerOutputStream.cs   |   160 +
 .../src/asn1/DerPrintableString.cs                 |   163 +
 BouncyCastle.AxCrypt/src/asn1/DerSequence.cs       |    85 +
 BouncyCastle.AxCrypt/src/asn1/DerSet.cs            |   108 +
 BouncyCastle.AxCrypt/src/asn1/DerStringBase.cs     |    22 +
 BouncyCastle.AxCrypt/src/asn1/DerT61String.cs      |   102 +
 BouncyCastle.AxCrypt/src/asn1/DerTaggedObject.cs   |    72 +
 BouncyCastle.AxCrypt/src/asn1/DerUTCTime.cs        |   263 +
 BouncyCastle.AxCrypt/src/asn1/DerUTF8String.cs     |    96 +
 .../src/asn1/DerUniversalString.cs                 |   107 +
 BouncyCastle.AxCrypt/src/asn1/DerUnknownTag.cs     |    80 +
 BouncyCastle.AxCrypt/src/asn1/DerVisibleString.cs  |   111 +
 .../src/asn1/IAsn1ApplicationSpecificParser.cs     |    10 +
 BouncyCastle.AxCrypt/src/asn1/IAsn1Choice.cs       |    17 +
 BouncyCastle.AxCrypt/src/asn1/IAsn1Convertible.cs  |     7 +
 BouncyCastle.AxCrypt/src/asn1/IAsn1String.cs       |    10 +
 .../src/asn1/IndefiniteLengthInputStream.cs        |   170 +
 .../src/asn1/LazyASN1InputStream.cs                |    33 +
 BouncyCastle.AxCrypt/src/asn1/LazyDERSequence.cs   |    80 +
 BouncyCastle.AxCrypt/src/asn1/LazyDERSet.cs        |    80 +
 .../src/asn1/LimitedInputStream.cs                 |    35 +
 BouncyCastle.AxCrypt/src/asn1/OidTokenizer.cs      |    45 +
 .../src/asn1/bc/BCObjectIdentifiers.cs             |    39 +
 .../src/asn1/cmp/CAKeyUpdAnnContent.cs             |    60 +
 .../src/asn1/cmp/CertConfirmContent.cs             |    47 +
 BouncyCastle.AxCrypt/src/asn1/cmp/CertOrEncCert.cs |    85 +
 .../src/asn1/cmp/CertRepMessage.cs                 |    94 +
 BouncyCastle.AxCrypt/src/asn1/cmp/CertResponse.cs  |   115 +
 BouncyCastle.AxCrypt/src/asn1/cmp/CertStatus.cs    |    84 +
 .../src/asn1/cmp/CertifiedKeyPair.cs               |   114 +
 BouncyCastle.AxCrypt/src/asn1/cmp/Challenge.cs     |    79 +
 .../src/asn1/cmp/CmpCertificate.cs                 |    80 +
 .../src/asn1/cmp/CmpObjectIdentifiers.cs           |   106 +
 BouncyCastle.AxCrypt/src/asn1/cmp/CrlAnnContent.cs |    49 +
 .../src/asn1/cmp/ErrorMsgContent.cs                |    94 +
 BouncyCastle.AxCrypt/src/asn1/cmp/GenMsgContent.cs |    52 +
 BouncyCastle.AxCrypt/src/asn1/cmp/GenRepContent.cs |    52 +
 .../src/asn1/cmp/InfoTypeAndValue.cs               |   121 +
 .../src/asn1/cmp/KeyRecRepContent.cs               |   115 +
 BouncyCastle.AxCrypt/src/asn1/cmp/OobCertHash.cs   |    87 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIBody.cs       |   186 +
 .../src/asn1/cmp/PKIConfirmContent.cs              |    34 +
 .../src/asn1/cmp/PKIFailureInfo.cs                 |    73 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIFreeText.cs   |    97 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeader.cs     |   237 +
 .../src/asn1/cmp/PKIHeaderBuilder.cs               |   223 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessage.cs    |   140 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessages.cs   |    52 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatus.cs     |    62 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatusInfo.cs |   165 +
 BouncyCastle.AxCrypt/src/asn1/cmp/PbmParameter.cs  |   100 +
 .../src/asn1/cmp/PollRepContent.cs                 |    66 +
 .../src/asn1/cmp/PollReqContent.cs                 |    59 +
 .../src/asn1/cmp/PopoDecKeyChallContent.cs         |    47 +
 .../src/asn1/cmp/PopoDecKeyRespContent.cs          |    47 +
 BouncyCastle.AxCrypt/src/asn1/cmp/ProtectedPart.cs |    58 +
 BouncyCastle.AxCrypt/src/asn1/cmp/RevAnnContent.cs |    86 +
 BouncyCastle.AxCrypt/src/asn1/cmp/RevDetails.cs    |    75 +
 BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContent.cs |   112 +
 .../src/asn1/cmp/RevRepContentBuilder.cs           |    55 +
 BouncyCastle.AxCrypt/src/asn1/cmp/RevReqContent.cs |    52 +
 BouncyCastle.AxCrypt/src/asn1/cms/Attribute.cs     |    70 +
 .../src/asn1/cms/AttributeTable.cs                 |   231 +
 BouncyCastle.AxCrypt/src/asn1/cms/Attributes.cs    |    55 +
 .../src/asn1/cms/AuthEnvelopedData.cs              |   203 +
 .../src/asn1/cms/AuthEnvelopedDataParser.cs        |   145 +
 .../src/asn1/cms/AuthenticatedData.cs              |   270 +
 .../src/asn1/cms/AuthenticatedDataParser.cs        |   182 +
 BouncyCastle.AxCrypt/src/asn1/cms/CMSAttributes.cs |    14 +
 .../src/asn1/cms/CMSObjectIdentifiers.cs           |    28 +
 .../src/asn1/cms/CompressedData.cs                 |    96 +
 .../src/asn1/cms/CompressedDataParser.cs           |    47 +
 BouncyCastle.AxCrypt/src/asn1/cms/ContentInfo.cs   |    88 +
 .../src/asn1/cms/ContentInfoParser.cs              |    40 +
 .../src/asn1/cms/EncryptedContentInfo.cs           |    94 +
 .../src/asn1/cms/EncryptedContentInfoParser.cs     |    46 +
 BouncyCastle.AxCrypt/src/asn1/cms/EncryptedData.cs |    95 +
 BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedData.cs |   176 +
 .../src/asn1/cms/EnvelopedDataParser.cs            |   107 +
 BouncyCastle.AxCrypt/src/asn1/cms/Evidence.cs      |    47 +
 .../src/asn1/cms/IssuerAndSerialNumber.cs          |    64 +
 BouncyCastle.AxCrypt/src/asn1/cms/KEKIdentifier.cs |   119 +
 .../src/asn1/cms/KEKRecipientInfo.cs               |   106 +
 .../src/asn1/cms/KeyAgreeRecipientIdentifier.cs    |    92 +
 .../src/asn1/cms/KeyAgreeRecipientInfo.cs          |   141 +
 .../src/asn1/cms/KeyTransRecipientInfo.cs          |    99 +
 BouncyCastle.AxCrypt/src/asn1/cms/MetaData.cs      |    94 +
 .../src/asn1/cms/OriginatorIdentifierOrKey.cs      |   168 +
 .../src/asn1/cms/OriginatorInfo.cs                 |   121 +
 .../src/asn1/cms/OriginatorPublicKey.cs            |    87 +
 .../src/asn1/cms/OtherKeyAttribute.cs              |    70 +
 .../src/asn1/cms/OtherRecipientInfo.cs             |    83 +
 .../src/asn1/cms/OtherRevocationInfoFormat.cs      |    77 +
 .../src/asn1/cms/PasswordRecipientInfo.cs          |   133 +
 .../src/asn1/cms/RecipientEncryptedKey.cs          |    88 +
 .../src/asn1/cms/RecipientIdentifier.cs            |    89 +
 BouncyCastle.AxCrypt/src/asn1/cms/RecipientInfo.cs |   145 +
 .../src/asn1/cms/RecipientKeyIdentifier.cs         |   137 +
 BouncyCastle.AxCrypt/src/asn1/cms/SCVPReqRes.cs    |    77 +
 BouncyCastle.AxCrypt/src/asn1/cms/SignedData.cs    |   287 +
 .../src/asn1/cms/SignedDataParser.cs               |   112 +
 .../src/asn1/cms/SignerIdentifier.cs               |    89 +
 BouncyCastle.AxCrypt/src/asn1/cms/SignerInfo.cs    |   185 +
 BouncyCastle.AxCrypt/src/asn1/cms/Time.cs          |   118 +
 .../src/asn1/cms/TimeStampAndCRL.cs                |    62 +
 .../src/asn1/cms/TimeStampTokenEvidence.cs         |    65 +
 .../src/asn1/cms/TimeStampedData.cs                |    95 +
 .../src/asn1/cms/TimeStampedDataParser.cs          |    74 +
 .../src/asn1/cms/ecc/MQVuserKeyingMaterial.cs      |   103 +
 .../src/asn1/crmf/AttributeTypeAndValue.cs         |    66 +
 BouncyCastle.AxCrypt/src/asn1/crmf/CertId.cs       |    58 +
 .../src/asn1/crmf/CertReqMessages.cs               |    52 +
 BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMsg.cs   |   106 +
 BouncyCastle.AxCrypt/src/asn1/crmf/CertRequest.cs  |    82 +
 BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplate.cs |   149 +
 .../src/asn1/crmf/CertTemplateBuilder.cs           |   125 +
 BouncyCastle.AxCrypt/src/asn1/crmf/Controls.cs     |    52 +
 .../src/asn1/crmf/CrmfObjectIdentifiers.cs         |    23 +
 BouncyCastle.AxCrypt/src/asn1/crmf/EncKeyWithID.cs |   103 +
 BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedKey.cs |    78 +
 .../src/asn1/crmf/EncryptedValue.cs                |   154 +
 .../src/asn1/crmf/OptionalValidity.cs              |    71 +
 .../src/asn1/crmf/PKIArchiveOptions.cs             |   105 +
 .../src/asn1/crmf/PKIPublicationInfo.cs            |    64 +
 BouncyCastle.AxCrypt/src/asn1/crmf/PKMacValue.cs   |    89 +
 BouncyCastle.AxCrypt/src/asn1/crmf/PopoPrivKey.cs  |    84 +
 .../src/asn1/crmf/PopoSigningKey.cs                |   115 +
 .../src/asn1/crmf/PopoSigningKeyInput.cs           |   115 +
 .../src/asn1/crmf/ProofOfPossession.cs             |    98 +
 .../src/asn1/crmf/SinglePubInfo.cs                 |    58 +
 .../src/asn1/crmf/SubsequentMessage.cs             |    27 +
 .../asn1/cryptopro/CryptoProObjectIdentifiers.cs   |    51 +
 .../src/asn1/cryptopro/ECGOST3410NamedCurves.cs    |   184 +
 .../asn1/cryptopro/ECGOST3410ParamSetParameters.cs |    86 +
 .../src/asn1/cryptopro/GOST28147Parameters.cs      |    63 +
 .../src/asn1/cryptopro/GOST3410NamedParameters.cs  |   123 +
 .../asn1/cryptopro/GOST3410ParamSetParameters.cs   |    87 +
 .../cryptopro/GOST3410PublicKeyAlgParameters.cs    |    99 +
 .../src/asn1/eac/EACObjectIdentifiers.cs           |    50 +
 .../src/asn1/esf/CertificateValues.cs              |    85 +
 .../src/asn1/esf/CommitmentTypeIdentifier.cs       |    17 +
 .../src/asn1/esf/CommitmentTypeIndication.cs       |    95 +
 .../src/asn1/esf/CommitmentTypeQualifier.cs        |   119 +
 .../src/asn1/esf/CompleteCertificateRefs.cs        |    84 +
 .../src/asn1/esf/CompleteRevocationRefs.cs         |    84 +
 BouncyCastle.AxCrypt/src/asn1/esf/CrlIdentifier.cs |   110 +
 BouncyCastle.AxCrypt/src/asn1/esf/CrlListID.cs     |    89 +
 BouncyCastle.AxCrypt/src/asn1/esf/CrlOcspRef.cs    |   111 +
 .../src/asn1/esf/CrlValidatedID.cs                 |    89 +
 BouncyCastle.AxCrypt/src/asn1/esf/ESFAttributes.cs |    25 +
 .../src/asn1/esf/OcspIdentifier.cs                 |    77 +
 BouncyCastle.AxCrypt/src/asn1/esf/OcspListID.cs    |    88 +
 .../src/asn1/esf/OcspResponsesID.cs                |    92 +
 BouncyCastle.AxCrypt/src/asn1/esf/OtherCertID.cs   |    93 +
 BouncyCastle.AxCrypt/src/asn1/esf/OtherHash.cs     |    88 +
 .../src/asn1/esf/OtherHashAlgAndValue.cs           |    94 +
 BouncyCastle.AxCrypt/src/asn1/esf/OtherRevRefs.cs  |    78 +
 BouncyCastle.AxCrypt/src/asn1/esf/OtherRevVals.cs  |    78 +
 .../src/asn1/esf/OtherSigningCertificate.cs        |   138 +
 .../src/asn1/esf/RevocationValues.cs               |   165 +
 .../src/asn1/esf/SigPolicyQualifierInfo.cs         |    71 +
 .../src/asn1/esf/SignaturePolicyId.cs              |   145 +
 .../src/asn1/esf/SignaturePolicyIdentifier.cs      |    64 +
 .../src/asn1/esf/SignerAttribute.cs                |    96 +
 .../src/asn1/esf/SignerLocation.cs                 |   144 +
 BouncyCastle.AxCrypt/src/asn1/ess/ContentHints.cs  |    92 +
 .../src/asn1/ess/ContentIdentifier.cs              |    65 +
 BouncyCastle.AxCrypt/src/asn1/ess/ESSCertID.cs     |    93 +
 BouncyCastle.AxCrypt/src/asn1/ess/ESSCertIDv2.cs   |   146 +
 BouncyCastle.AxCrypt/src/asn1/ess/OtherCertID.cs   |   132 +
 .../src/asn1/ess/OtherSigningCertificate.cs        |   109 +
 .../src/asn1/ess/SigningCertificate.cs             |   108 +
 .../src/asn1/ess/SigningCertificateV2.cs           |   112 +
 .../src/asn1/gnu/GNUObjectIdentifiers.cs           |    31 +
 .../src/asn1/iana/IANAObjectIdentifiers.cs         |    18 +
 .../src/asn1/icao/CscaMasterList.cs                |    83 +
 .../src/asn1/icao/DataGroupHash.cs                 |    86 +
 .../src/asn1/icao/ICAOObjectIdentifiers.cs         |    34 +
 .../src/asn1/icao/LDSSecurityObject.cs             |   145 +
 .../src/asn1/icao/LDSVersionInfo.cs                |    61 +
 .../src/asn1/isismtt/ISISMTTObjectIdentifiers.cs   |   177 +
 .../src/asn1/isismtt/ocsp/CertHash.cs              |   121 +
 .../src/asn1/isismtt/ocsp/RequestedCertificate.cs  |   186 +
 .../isismtt/x509/AdditionalInformationSyntax.cs    |    70 +
 .../src/asn1/isismtt/x509/AdmissionSyntax.cs       |   277 +
 .../src/asn1/isismtt/x509/Admissions.cs            |   186 +
 .../src/asn1/isismtt/x509/DeclarationOfMajority.cs |   170 +
 .../src/asn1/isismtt/x509/MonetaryLimit.cs         |   121 +
 .../src/asn1/isismtt/x509/NamingAuthority.cs       |   214 +
 .../src/asn1/isismtt/x509/ProcurationSyntax.cs     |   232 +
 .../src/asn1/isismtt/x509/ProfessionInfo.cs        |   386 +
 .../src/asn1/isismtt/x509/Restriction.cs           |    81 +
 .../src/asn1/kisa/KISAObjectIdentifiers.cs         |     8 +
 .../asn1/microsoft/MicrosoftObjectIdentifiers.cs   |    18 +
 .../src/asn1/misc/CAST5CBCParameters.cs            |    74 +
 BouncyCastle.AxCrypt/src/asn1/misc/IDEACBCPar.cs   |    68 +
 .../src/asn1/misc/MiscObjectIdentifiers.cs         |    48 +
 .../src/asn1/misc/NetscapeCertType.cs              |    54 +
 .../src/asn1/misc/NetscapeRevocationURL.cs         |    18 +
 .../src/asn1/misc/VerisignCzagExtension.cs         |    18 +
 .../src/asn1/mozilla/PublicKeyAndChallenge.cs      |    67 +
 .../src/asn1/nist/NISTNamedCurves.cs               |   108 +
 .../src/asn1/nist/NISTObjectIdentifiers.cs         |    65 +
 .../src/asn1/ntt/NTTObjectIdentifiers.cs           |    14 +
 .../src/asn1/ocsp/BasicOCSPResponse.cs             |   131 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/CertID.cs       |    98 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/CertStatus.cs   |    94 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/CrlID.cs        |    82 +
 .../src/asn1/ocsp/OCSPObjectIdentifiers.cs         |    23 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPRequest.cs  |    89 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponse.cs |    90 +
 .../src/asn1/ocsp/OCSPResponseStatus.cs            |    41 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/Request.cs      |    90 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/ResponderID.cs  |   107 +
 .../src/asn1/ocsp/ResponseBytes.cs                 |    82 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseData.cs |   158 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/RevokedInfo.cs  |    96 +
 .../src/asn1/ocsp/ServiceLocator.cs                |    95 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/Signature.cs    |   110 +
 .../src/asn1/ocsp/SingleResponse.cs                |   137 +
 BouncyCastle.AxCrypt/src/asn1/ocsp/TBSRequest.cs   |   151 +
 .../src/asn1/oiw/ElGamalParameter.cs               |    47 +
 .../src/asn1/oiw/OIWObjectIdentifiers.cs           |    29 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/Attribute.cs    |    79 +
 .../src/asn1/pkcs/AuthenticatedSafe.cs             |    37 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/CertBag.cs      |    46 +
 .../src/asn1/pkcs/CertificationRequest.cs          |    81 +
 .../src/asn1/pkcs/CertificationRequestInfo.cs      |   123 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/ContentInfo.cs  |    74 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/DHParameter.cs  |    72 +
 .../src/asn1/pkcs/EncryptedData.cs                 |   104 +
 .../src/asn1/pkcs/EncryptedPrivateKeyInfo.cs       |    78 +
 .../src/asn1/pkcs/EncryptionScheme.cs              |    49 +
 .../src/asn1/pkcs/IssuerAndSerialNumber.cs         |    71 +
 .../src/asn1/pkcs/KeyDerivationFunc.cs             |    21 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/MacData.cs      |    96 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/PBEParameter.cs |    60 +
 .../src/asn1/pkcs/PBES2Parameters.cs               |    65 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/PBKDF2Params.cs |    86 +
 .../src/asn1/pkcs/PKCS12PBEParams.cs               |    63 +
 .../src/asn1/pkcs/PKCSObjectIdentifiers.cs         |   256 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/Pfx.cs          |    65 +
 .../src/asn1/pkcs/PrivateKeyInfo.cs                |   135 +
 .../src/asn1/pkcs/RC2CBCParameter.cs               |    81 +
 .../src/asn1/pkcs/RSAESOAEPparams.cs               |   145 +
 .../src/asn1/pkcs/RSAPrivateKeyStructure.cs        |   146 +
 .../src/asn1/pkcs/RSASSAPSSparams.cs               |   165 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/SafeBag.cs      |    70 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/SignedData.cs   |   157 +
 BouncyCastle.AxCrypt/src/asn1/pkcs/SignerInfo.cs   |   154 +
 .../src/asn1/sec/ECPrivateKeyStructure.cs          |   126 +
 .../src/asn1/sec/SECNamedCurves.cs                 |  1253 +
 .../src/asn1/sec/SECObjectIdentifiers.cs           |    52 +
 .../src/asn1/smime/SMIMEAttributes.cs              |    11 +
 .../src/asn1/smime/SMIMECapabilities.cs            |   128 +
 .../src/asn1/smime/SMIMECapabilitiesAttribute.cs   |    16 +
 .../src/asn1/smime/SMIMECapability.cs              |   101 +
 .../src/asn1/smime/SMIMECapabilityVector.cs        |    37 +
 .../smime/SMIMEEncryptionKeyPreferenceAttribute.cs |    44 +
 .../src/asn1/teletrust/TeleTrusTNamedCurves.cs     |   474 +
 .../asn1/teletrust/TeleTrusTObjectIdentifiers.cs   |    45 +
 BouncyCastle.AxCrypt/src/asn1/tsp/Accuracy.cs      |   149 +
 .../src/asn1/tsp/MessageImprint.cs                 |    74 +
 BouncyCastle.AxCrypt/src/asn1/tsp/TSTInfo.cs       |   249 +
 BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampReq.cs  |   164 +
 BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampResp.cs |    80 +
 BouncyCastle.AxCrypt/src/asn1/util/Asn1Dump.cs     |   373 +
 BouncyCastle.AxCrypt/src/asn1/util/Dump.cs         |    30 +
 BouncyCastle.AxCrypt/src/asn1/util/FilterStream.cs |    73 +
 .../src/asn1/x500/DirectoryString.cs               |    75 +
 .../src/asn1/x509/AccessDescription.cs             |    83 +
 .../src/asn1/x509/AlgorithmIdentifier.cs           |   109 +
 .../src/asn1/x509/AttCertIssuer.cs                 |    86 +
 .../src/asn1/x509/AttCertValidityPeriod.cs         |    78 +
 BouncyCastle.AxCrypt/src/asn1/x509/Attribute.cs    |    82 +
 .../src/asn1/x509/AttributeCertificate.cs          |    81 +
 .../src/asn1/x509/AttributeCertificateInfo.cs      |   156 +
 .../src/asn1/x509/AttributeTable.cs                |    73 +
 .../src/asn1/x509/AuthorityInformationAccess.cs    |    98 +
 .../src/asn1/x509/AuthorityKeyIdentifier.cs        |   211 +
 .../src/asn1/x509/BasicConstraints.cs              |   133 +
 BouncyCastle.AxCrypt/src/asn1/x509/CRLDistPoint.cs |    93 +
 BouncyCastle.AxCrypt/src/asn1/x509/CRLNumber.cs    |    30 +
 BouncyCastle.AxCrypt/src/asn1/x509/CRLReason.cs    |    61 +
 BouncyCastle.AxCrypt/src/asn1/x509/CertPolicyId.cs |    20 +
 .../src/asn1/x509/CertificateList.cs               |   108 +
 .../src/asn1/x509/CertificatePair.cs               |   160 +
 .../src/asn1/x509/CertificatePolicies.cs           |    81 +
 BouncyCastle.AxCrypt/src/asn1/x509/DSAParameter.cs |    77 +
 BouncyCastle.AxCrypt/src/asn1/x509/DigestInfo.cs   |    76 +
 BouncyCastle.AxCrypt/src/asn1/x509/DisplayText.cs  |   172 +
 .../src/asn1/x509/DistributionPoint.cs             |   161 +
 .../src/asn1/x509/DistributionPointName.cs         |   130 +
 .../src/asn1/x509/ExtendedKeyUsage.cs              |   132 +
 BouncyCastle.AxCrypt/src/asn1/x509/GeneralName.cs  |   418 +
 BouncyCastle.AxCrypt/src/asn1/x509/GeneralNames.cs |    95 +
 .../src/asn1/x509/GeneralSubtree.cs                |   189 +
 BouncyCastle.AxCrypt/src/asn1/x509/Holder.cs       |   257 +
 .../src/asn1/x509/IetfAttrSyntax.cs                |   161 +
 BouncyCastle.AxCrypt/src/asn1/x509/IssuerSerial.cs |    98 +
 .../src/asn1/x509/IssuingDistributionPoint.cs      |   247 +
 BouncyCastle.AxCrypt/src/asn1/x509/KeyPurposeId.cs |    36 +
 BouncyCastle.AxCrypt/src/asn1/x509/KeyUsage.cs     |    79 +
 .../src/asn1/x509/NameConstraints.cs               |   118 +
 .../src/asn1/x509/NoticeReference.cs               |   143 +
 .../src/asn1/x509/ObjectDigestInfo.cs              |   177 +
 .../src/asn1/x509/PolicyInformation.cs             |    80 +
 .../src/asn1/x509/PolicyMappings.cs                |    70 +
 .../src/asn1/x509/PolicyQualifierId.cs             |    28 +
 .../src/asn1/x509/PolicyQualifierInfo.cs           |    95 +
 .../src/asn1/x509/PrivateKeyUsagePeriod.cs         |    82 +
 .../src/asn1/x509/RSAPublicKeyStructure.cs         |    92 +
 BouncyCastle.AxCrypt/src/asn1/x509/ReasonFlags.cs  |    46 +
 BouncyCastle.AxCrypt/src/asn1/x509/RoleSyntax.cs   |   230 +
 .../src/asn1/x509/SubjectDirectoryAttributes.cs    |   142 +
 .../src/asn1/x509/SubjectKeyIdentifier.cs          |   141 +
 .../src/asn1/x509/SubjectPublicKeyInfo.cs          |   102 +
 BouncyCastle.AxCrypt/src/asn1/x509/TBSCertList.cs  |   274 +
 .../src/asn1/x509/TBSCertificateStructure.cs       |   185 +
 BouncyCastle.AxCrypt/src/asn1/x509/Target.cs       |   139 +
 .../src/asn1/x509/TargetInformation.cs             |   123 +
 BouncyCastle.AxCrypt/src/asn1/x509/Targets.cs      |   121 +
 BouncyCastle.AxCrypt/src/asn1/x509/Time.cs         |   120 +
 BouncyCastle.AxCrypt/src/asn1/x509/UserNotice.cs   |   122 +
 .../src/asn1/x509/V1TBSCertificateGenerator.cs     |   108 +
 .../x509/V2AttributeCertificateInfoGenerator.cs    |   137 +
 BouncyCastle.AxCrypt/src/asn1/x509/V2Form.cs       |   137 +
 .../src/asn1/x509/V2TBSCertListGenerator.cs        |   201 +
 .../src/asn1/x509/V3TBSCertificateGenerator.cs     |   168 +
 .../src/asn1/x509/X509Attributes.cs                |     9 +
 .../src/asn1/x509/X509CertificateStructure.cs      |   127 +
 .../src/asn1/x509/X509DefaultEntryConverter.cs     |    63 +
 .../src/asn1/x509/X509Extension.cs                 |    79 +
 .../src/asn1/x509/X509Extensions.cs                |   451 +
 .../src/asn1/x509/X509ExtensionsGenerator.cs       |    81 +
 BouncyCastle.AxCrypt/src/asn1/x509/X509Name.cs     |  1083 +
 .../src/asn1/x509/X509NameEntryConverter.cs        |    89 +
 .../src/asn1/x509/X509NameTokenizer.cs             |   104 +
 .../src/asn1/x509/X509ObjectIdentifiers.cs         |    59 +
 .../src/asn1/x509/qualified/BiometricData.cs       |   112 +
 .../asn1/x509/qualified/ETSIQCObjectIdentifiers.cs |    19 +
 .../src/asn1/x509/qualified/Iso4217CurrencyCode.cs |    84 +
 .../src/asn1/x509/qualified/MonetaryValue.cs       |    83 +
 .../src/asn1/x509/qualified/QCStatement.cs         |    85 +
 .../x509/qualified/RFC3739QCObjectIdentifiers.cs   |    21 +
 .../asn1/x509/qualified/SemanticsInformation.cs    |   124 +
 .../src/asn1/x509/qualified/TypeOfBiometricData.cs |    91 +
 .../src/asn1/x509/sigi/NameOrPseudonym.cs          |   177 +
 .../src/asn1/x509/sigi/PersonalData.cs             |   210 +
 .../src/asn1/x509/sigi/SigIObjectIdentifiers.cs    |    49 +
 .../src/asn1/x9/DHDomainParameters.cs              |   116 +
 BouncyCastle.AxCrypt/src/asn1/x9/DHPublicKey.cs    |    44 +
 .../src/asn1/x9/DHValidationParms.cs               |    62 +
 .../src/asn1/x9/ECNamedCurveTable.cs               |   118 +
 .../src/asn1/x9/KeySpecificInfo.cs                 |    58 +
 BouncyCastle.AxCrypt/src/asn1/x9/OtherInfo.cs      |    88 +
 .../src/asn1/x9/X962NamedCurves.cs                 |   753 +
 BouncyCastle.AxCrypt/src/asn1/x9/X962Parameters.cs |    53 +
 BouncyCastle.AxCrypt/src/asn1/x9/X9Curve.cs        |   146 +
 BouncyCastle.AxCrypt/src/asn1/x9/X9ECParameters.cs |   186 +
 .../src/asn1/x9/X9ECParametersHolder.cs            |    22 +
 BouncyCastle.AxCrypt/src/asn1/x9/X9ECPoint.cs      |    44 +
 BouncyCastle.AxCrypt/src/asn1/x9/X9FieldElement.cs |    69 +
 BouncyCastle.AxCrypt/src/asn1/x9/X9FieldID.cs      |   124 +
 .../src/asn1/x9/X9IntegerConverter.cs              |    40 +
 .../src/asn1/x9/X9ObjectIdentifiers.cs             |   137 +
 .../src/bcpg/ArmoredInputStream.cs                 |   516 +
 .../src/bcpg/ArmoredOutputStream.cs                |   332 +
 BouncyCastle.AxCrypt/src/bcpg/BcpgInputStream.cs   |   358 +
 BouncyCastle.AxCrypt/src/bcpg/BcpgObject.cs        |    22 +
 BouncyCastle.AxCrypt/src/bcpg/BcpgOutputStream.cs  |   393 +
 .../src/bcpg/CompressedDataPacket.cs               |    24 +
 .../src/bcpg/CompressionAlgorithmTags.cs           |    11 +
 BouncyCastle.AxCrypt/src/bcpg/ContainedPacket.cs   |    22 +
 BouncyCastle.AxCrypt/src/bcpg/Crc24.cs             |    46 +
 BouncyCastle.AxCrypt/src/bcpg/DsaPublicBcpgKey.cs  |    80 +
 BouncyCastle.AxCrypt/src/bcpg/DsaSecretBcpgKey.cs  |    61 +
 .../src/bcpg/ElGamalPublicBcpgKey.cs               |    71 +
 .../src/bcpg/ElGamalSecretBcpgKey.cs               |    61 +
 .../src/bcpg/ExperimentalPacket.cs                 |    38 +
 BouncyCastle.AxCrypt/src/bcpg/HashAlgorithmTags.cs |    19 +
 BouncyCastle.AxCrypt/src/bcpg/IBcpgKey.cs          |    16 +
 BouncyCastle.AxCrypt/src/bcpg/InputStreamPacket.cs |    20 +
 BouncyCastle.AxCrypt/src/bcpg/LiteralDataPacket.cs |    57 +
 BouncyCastle.AxCrypt/src/bcpg/MPInteger.cs         |    59 +
 BouncyCastle.AxCrypt/src/bcpg/MarkerPacket.cs      |    24 +
 .../src/bcpg/ModDetectionCodePacket.cs             |    42 +
 .../src/bcpg/OnePassSignaturePacket.cs             |    93 +
 .../src/bcpg/OutputStreamPacket.cs                 |    24 +
 BouncyCastle.AxCrypt/src/bcpg/Packet.cs            |     7 +
 BouncyCastle.AxCrypt/src/bcpg/PacketTags.cs        |    30 +
 .../src/bcpg/PublicKeyAlgorithmTags.cs             |    28 +
 .../src/bcpg/PublicKeyEncSessionPacket.cs          |   103 +
 BouncyCastle.AxCrypt/src/bcpg/PublicKeyPacket.cs   |   115 +
 .../src/bcpg/PublicSubkeyPacket.cs                 |    30 +
 BouncyCastle.AxCrypt/src/bcpg/RsaPublicBcpgKey.cs  |    66 +
 BouncyCastle.AxCrypt/src/bcpg/RsaSecretBcpgKey.cs  |   114 +
 BouncyCastle.AxCrypt/src/bcpg/S2k.cs               |   147 +
 BouncyCastle.AxCrypt/src/bcpg/SecretKeyPacket.cs   |   170 +
 .../src/bcpg/SecretSubkeyPacket.cs                 |    43 +
 BouncyCastle.AxCrypt/src/bcpg/SignaturePacket.cs   |   472 +
 .../src/bcpg/SignatureSubpacket.cs                 |    76 +
 .../src/bcpg/SignatureSubpacketTags.cs             |    33 +
 .../src/bcpg/SignatureSubpacketsReader.cs          |    88 +
 .../src/bcpg/SymmetricEncDataPacket.cs             |    15 +
 .../src/bcpg/SymmetricEncIntegrityPacket.cs        |    18 +
 .../src/bcpg/SymmetricKeyAlgorithmTags.cs          |    23 +
 .../src/bcpg/SymmetricKeyEncSessionPacket.cs       |    91 +
 BouncyCastle.AxCrypt/src/bcpg/TrustPacket.cs       |    43 +
 .../src/bcpg/UserAttributePacket.cs                |    61 +
 .../src/bcpg/UserAttributeSubpacket.cs             |    90 +
 .../src/bcpg/UserAttributeSubpacketTags.cs         |    10 +
 .../src/bcpg/UserAttributeSubpacketsReader.cs      |    65 +
 BouncyCastle.AxCrypt/src/bcpg/UserIdPacket.cs      |    37 +
 BouncyCastle.AxCrypt/src/bcpg/attr/ImageAttrib.cs  |    72 +
 .../src/bcpg/sig/EmbeddedSignature.cs              |    18 +
 BouncyCastle.AxCrypt/src/bcpg/sig/Exportable.cs    |    47 +
 BouncyCastle.AxCrypt/src/bcpg/sig/IssuerKeyId.cs   |    61 +
 .../src/bcpg/sig/KeyExpirationTime.cs              |    56 +
 BouncyCastle.AxCrypt/src/bcpg/sig/KeyFlags.cs      |    74 +
 BouncyCastle.AxCrypt/src/bcpg/sig/NotationData.cs  |   112 +
 .../src/bcpg/sig/PreferredAlgorithms.cs            |    54 +
 BouncyCastle.AxCrypt/src/bcpg/sig/PrimaryUserId.cs |    48 +
 BouncyCastle.AxCrypt/src/bcpg/sig/Revocable.cs     |    48 +
 BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKey.cs |    62 +
 .../src/bcpg/sig/RevocationKeyTags.cs              |     9 +
 .../src/bcpg/sig/RevocationReason.cs               |    59 +
 .../src/bcpg/sig/RevocationReasonTags.cs           |    14 +
 .../src/bcpg/sig/SignatureCreationTime.cs          |    47 +
 .../src/bcpg/sig/SignatureExpirationTime.cs        |    54 +
 BouncyCastle.AxCrypt/src/bcpg/sig/SignerUserId.cs  |    52 +
 .../src/bcpg/sig/TrustSignature.cs                 |    43 +
 .../src/cms/BaseDigestCalculator.cs                |    23 +
 .../cms/CMSAttributeTableGenerationException.cs    |    28 +
 .../src/cms/CMSAttributeTableGenerator.cs          |    25 +
 .../src/cms/CMSAuthEnvelopedData.cs                |   112 +
 .../src/cms/CMSAuthEnvelopedGenerator.cs           |    16 +
 .../src/cms/CMSAuthenticatedData.cs                |   137 +
 .../src/cms/CMSAuthenticatedDataGenerator.cs       |   156 +
 .../src/cms/CMSAuthenticatedDataParser.cs          |   214 +
 .../src/cms/CMSAuthenticatedDataStreamGenerator.cs |   276 +
 .../src/cms/CMSAuthenticatedGenerator.cs           |    35 +
 BouncyCastle.AxCrypt/src/cms/CMSCompressedData.cs  |   107 +
 .../src/cms/CMSCompressedDataGenerator.cs          |    66 +
 .../src/cms/CMSCompressedDataParser.cs             |    57 +
 .../src/cms/CMSCompressedDataStreamGenerator.cs    |   143 +
 .../src/cms/CMSContentInfoParser.cs                |    47 +
 BouncyCastle.AxCrypt/src/cms/CMSEnvelopedData.cs   |   115 +
 .../src/cms/CMSEnvelopedDataGenerator.cs           |   178 +
 .../src/cms/CMSEnvelopedDataParser.cs              |   161 +
 .../src/cms/CMSEnvelopedDataStreamGenerator.cs     |   284 +
 .../src/cms/CMSEnvelopedGenerator.cs               |   331 +
 BouncyCastle.AxCrypt/src/cms/CMSEnvelopedHelper.cs |   311 +
 BouncyCastle.AxCrypt/src/cms/CMSException.cs       |    28 +
 BouncyCastle.AxCrypt/src/cms/CMSPBEKey.cs          |   109 +
 BouncyCastle.AxCrypt/src/cms/CMSProcessable.cs     |    19 +
 .../src/cms/CMSProcessableByteArray.cs             |    36 +
 BouncyCastle.AxCrypt/src/cms/CMSProcessableFile.cs |    56 +
 .../src/cms/CMSProcessableInputStream.cs           |    52 +
 BouncyCastle.AxCrypt/src/cms/CMSReadable.cs        |    10 +
 BouncyCastle.AxCrypt/src/cms/CMSSecureReadable.cs  |    14 +
 BouncyCastle.AxCrypt/src/cms/CMSSignedData.cs      |   425 +
 .../src/cms/CMSSignedDataGenerator.cs              |   551 +
 .../src/cms/CMSSignedDataParser.cs                 |   450 +
 .../src/cms/CMSSignedDataStreamGenerator.cs        |   916 +
 BouncyCastle.AxCrypt/src/cms/CMSSignedGenerator.cs |   261 +
 BouncyCastle.AxCrypt/src/cms/CMSSignedHelper.cs    |   319 +
 BouncyCastle.AxCrypt/src/cms/CMSStreamException.cs |    29 +
 BouncyCastle.AxCrypt/src/cms/CMSTypedStream.cs     |    72 +
 BouncyCastle.AxCrypt/src/cms/CMSUtils.cs           |   186 +
 .../src/cms/CounterSignatureDigestCalculator.cs    |    28 +
 .../DefaultAuthenticatedAttributeTableGenerator.cs |    90 +
 .../cms/DefaultSignedAttributeTableGenerator.cs    |   124 +
 BouncyCastle.AxCrypt/src/cms/DigOutputStream.cs    |    28 +
 BouncyCastle.AxCrypt/src/cms/IDigestCalculator.cs  |     9 +
 .../src/cms/KEKRecipientInfoGenerator.cs           |   137 +
 .../src/cms/KEKRecipientInformation.cs             |    62 +
 .../src/cms/KeyAgreeRecipientInfoGenerator.cs      |   171 +
 .../src/cms/KeyAgreeRecipientInformation.cs        |   226 +
 .../src/cms/KeyTransRecipientInfoGenerator.cs      |    87 +
 .../src/cms/KeyTransRecipientInformation.cs        |   113 +
 BouncyCastle.AxCrypt/src/cms/MacOutputStream.cs    |    28 +
 BouncyCastle.AxCrypt/src/cms/NullOutputStream.cs   |    20 +
 BouncyCastle.AxCrypt/src/cms/OriginatorId.cs       |    51 +
 .../src/cms/OriginatorInfoGenerator.cs             |    42 +
 .../src/cms/OriginatorInformation.cs               |    96 +
 BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2PBEKey.cs |    64 +
 .../src/cms/PKCS5Scheme2UTF8PBEKey.cs              |    64 +
 .../src/cms/PasswordRecipientInfoGenerator.cs      |    69 +
 .../src/cms/PasswordRecipientInformation.cs        |    79 +
 BouncyCastle.AxCrypt/src/cms/RecipientId.cs        |    58 +
 .../src/cms/RecipientInfoGenerator.cs              |    26 +
 .../src/cms/RecipientInformation.cs                |   126 +
 .../src/cms/RecipientInformationStore.cs           |    86 +
 BouncyCastle.AxCrypt/src/cms/SigOutputStream.cs    |    43 +
 BouncyCastle.AxCrypt/src/cms/SignerId.cs           |    51 +
 .../src/cms/SignerInfoGenerator.cs                 |    14 +
 BouncyCastle.AxCrypt/src/cms/SignerInformation.cs  |   758 +
 .../src/cms/SignerInformationStore.cs              |    74 +
 .../src/cms/SimpleAttributeTableGenerator.cs       |    28 +
 .../src/crypto/AsymmetricCipherKeyPair.cs          |    52 +
 .../src/crypto/AsymmetricKeyParameter.cs           |    47 +
 .../src/crypto/BufferedAeadBlockCipher.cs          |   247 +
 .../src/crypto/BufferedAsymmetricBlockCipher.cs    |   152 +
 .../src/crypto/BufferedBlockCipher.cs              |   377 +
 .../src/crypto/BufferedCipherBase.cs               |   113 +
 .../src/crypto/BufferedIesCipher.cs                |   113 +
 .../src/crypto/BufferedStreamCipher.cs             |   131 +
 .../src/crypto/CipherKeyGenerator.cs               |    83 +
 BouncyCastle.AxCrypt/src/crypto/CryptoException.cs |    28 +
 .../src/crypto/DataLengthException.cs              |    42 +
 .../src/crypto/IAsymmetricBlockCipher.cs           |    30 +
 .../crypto/IAsymmetricCipherKeyPairGenerator.cs    |    24 +
 BouncyCastle.AxCrypt/src/crypto/IBasicAgreement.cs |    29 +
 BouncyCastle.AxCrypt/src/crypto/IBlockCipher.cs    |    36 +
 BouncyCastle.AxCrypt/src/crypto/IBufferedCipher.cs |    44 +
 .../src/crypto/ICipherParameters.cs                |    11 +
 BouncyCastle.AxCrypt/src/crypto/IDSA.cs            |    40 +
 .../src/crypto/IDerivationFunction.cs              |    24 +
 .../src/crypto/IDerivationParameters.cs            |    11 +
 BouncyCastle.AxCrypt/src/crypto/IDigest.cs         |    61 +
 BouncyCastle.AxCrypt/src/crypto/IMac.cs            |    69 +
 BouncyCastle.AxCrypt/src/crypto/ISigner.cs         |    50 +
 .../src/crypto/ISignerWithRecovery.cs              |    37 +
 BouncyCastle.AxCrypt/src/crypto/IStreamCipher.cs   |    45 +
 BouncyCastle.AxCrypt/src/crypto/IWrapper.cs        |    18 +
 .../src/crypto/InvalidCipherTextException.cs       |    40 +
 .../src/crypto/KeyGenerationParameters.cs          |    55 +
 .../src/crypto/MaxBytesExceededException.cs        |    32 +
 .../src/crypto/PbeParametersGenerator.cs           |   202 +
 .../src/crypto/StreamBlockCipher.cs                |   109 +
 .../src/crypto/agreement/DHAgreement.cs            |    93 +
 .../src/crypto/agreement/DHBasicAgreement.cs       |    64 +
 .../src/crypto/agreement/DHStandardGroups.cs       |   206 +
 .../src/crypto/agreement/ECDHBasicAgreement.cs     |    57 +
 .../src/crypto/agreement/ECDHCBasicAgreement.cs    |    66 +
 .../crypto/agreement/ECDHWithKdfBasicAgreement.cs  |    63 +
 .../src/crypto/agreement/ECMqvBasicAgreement.cs    |    89 +
 .../crypto/agreement/ECMqvWithKdfBasicAgreement.cs |    63 +
 .../src/crypto/agreement/kdf/DHKdfParameters.cs    |    57 +
 .../src/crypto/agreement/kdf/DHKekGenerator.cs     |   112 +
 .../src/crypto/agreement/kdf/ECDHKekGenerator.cs   |    55 +
 .../src/crypto/agreement/srp/SRP6Client.cs         |    93 +
 .../src/crypto/agreement/srp/SRP6Server.cs         |    90 +
 .../src/crypto/agreement/srp/SRP6Utilities.cs      |    85 +
 .../crypto/agreement/srp/SRP6VerifierGenerator.cs  |    49 +
 .../src/crypto/digests/GOST3411Digest.cs           |   356 +
 .../src/crypto/digests/GeneralDigest.cs            |   127 +
 .../src/crypto/digests/LongDigest.cs               |   355 +
 .../src/crypto/digests/MD2Digest.cs                |   269 +
 .../src/crypto/digests/MD4Digest.cs                |   292 +
 .../src/crypto/digests/MD5Digest.cs                |   313 +
 .../src/crypto/digests/NullDigest.cs               |    49 +
 .../src/crypto/digests/RipeMD128Digest.cs          |   484 +
 .../src/crypto/digests/RipeMD160Digest.cs          |   445 +
 .../src/crypto/digests/RipeMD256Digest.cs          |   430 +
 .../src/crypto/digests/RipeMD320Digest.cs          |   459 +
 .../src/crypto/digests/SHA3Digest.cs               |   560 +
 .../src/crypto/digests/SM3Digest.cs                |   328 +
 .../src/crypto/digests/Sha1Digest.cs               |   284 +
 .../src/crypto/digests/Sha224Digest.cs             |   289 +
 .../src/crypto/digests/Sha256Digest.cs             |   330 +
 .../src/crypto/digests/Sha384Digest.cs             |   101 +
 .../src/crypto/digests/Sha512Digest.cs             |   104 +
 .../src/crypto/digests/Sha512tDigest.cs            |   200 +
 .../src/crypto/digests/ShortenedDigest.cs          |    82 +
 .../src/crypto/digests/SkeinDigest.cs              |   117 +
 .../src/crypto/digests/SkeinEngine.cs              |   804 +
 .../src/crypto/digests/TigerDigest.cs              |   883 +
 .../src/crypto/digests/WhirlpoolDigest.cs          |   413 +
 .../src/crypto/ec/CustomNamedCurves.cs             |   366 +
 .../src/crypto/encodings/ISO9796d1Encoding.cs      |   273 +
 .../src/crypto/encodings/OaepEncoding.cs           |   349 +
 .../src/crypto/encodings/Pkcs1Encoding.cs          |   382 +
 .../src/crypto/engines/AesEngine.cs                |   532 +
 .../src/crypto/engines/AesFastEngine.cs            |   864 +
 .../src/crypto/engines/AesLightEngine.cs           |   427 +
 .../src/crypto/engines/AesWrapEngine.cs            |    16 +
 .../src/crypto/engines/BlowfishEngine.cs           |   561 +
 .../src/crypto/engines/CamelliaEngine.cs           |   669 +
 .../src/crypto/engines/CamelliaLightEngine.cs      |   581 +
 .../src/crypto/engines/CamelliaWrapEngine.cs       |    16 +
 .../src/crypto/engines/Cast5Engine.cs              |   802 +
 .../src/crypto/engines/Cast6Engine.cs              |   279 +
 .../src/crypto/engines/ChaChaEngine.cs             |   189 +
 .../src/crypto/engines/DesEdeEngine.cs             |   100 +
 .../src/crypto/engines/DesEdeWrapEngine.cs         |   322 +
 .../src/crypto/engines/DesEngine.cs                |   475 +
 .../src/crypto/engines/ElGamalEngine.cs            |   178 +
 .../src/crypto/engines/GOST28147Engine.cs          |   376 +
 .../src/crypto/engines/HC128Engine.cs              |   235 +
 .../src/crypto/engines/HC256Engine.cs              |   224 +
 .../src/crypto/engines/ISAACEngine.cs              |   212 +
 .../src/crypto/engines/IdeaEngine.cs               |   337 +
 .../src/crypto/engines/IesEngine.cs                |   233 +
 .../src/crypto/engines/NaccacheSternEngine.cs      |   433 +
 .../src/crypto/engines/NoekeonEngine.cs            |   240 +
 .../src/crypto/engines/NullEngine.cs               |    70 +
 .../src/crypto/engines/RC2Engine.cs                |   312 +
 .../src/crypto/engines/RC2WrapEngine.cs            |   370 +
 .../src/crypto/engines/RC4Engine.cs                |   147 +
 .../src/crypto/engines/RC532Engine.cs              |   294 +
 .../src/crypto/engines/RC564Engine.cs              |   295 +
 .../src/crypto/engines/RC6Engine.cs                |   362 +
 .../src/crypto/engines/RFC3211WrapEngine.cs        |   168 +
 .../src/crypto/engines/RFC3394WrapEngine.cs        |   178 +
 .../src/crypto/engines/RSABlindedEngine.cs         |   124 +
 .../src/crypto/engines/RSABlindingEngine.cs        |   139 +
 .../src/crypto/engines/RSACoreEngine.cs            |   156 +
 .../src/crypto/engines/RijndaelEngine.cs           |   747 +
 .../src/crypto/engines/RsaEngine.cs                |    78 +
 .../src/crypto/engines/SEEDEngine.cs               |   361 +
 .../src/crypto/engines/SEEDWrapEngine.cs           |    16 +
 .../src/crypto/engines/Salsa20Engine.cs            |   372 +
 .../src/crypto/engines/SerpentEngine.cs            |   779 +
 .../src/crypto/engines/SkipjackEngine.cs           |   255 +
 .../src/crypto/engines/TEAEngine.cs                |   168 +
 .../src/crypto/engines/ThreefishEngine.cs          |  1490 +
 .../src/crypto/engines/TwofishEngine.cs            |   675 +
 .../src/crypto/engines/VMPCEngine.cs               |   140 +
 .../src/crypto/engines/VMPCKSA3Engine.cs           |    51 +
 .../src/crypto/engines/XSalsa20Engine.cs           |    71 +
 .../src/crypto/engines/XTEAEngine.cs               |   168 +
 .../src/crypto/generators/BaseKdfBytesGenerator.cs |   132 +
 .../crypto/generators/DHBasicKeyPairGenerator.cs   |    38 +
 .../src/crypto/generators/DHKeyGeneratorHelper.cs  |    72 +
 .../src/crypto/generators/DHKeyPairGenerator.cs    |    38 +
 .../src/crypto/generators/DHParametersGenerator.cs |    45 +
 .../src/crypto/generators/DHParametersHelper.cs    |   156 +
 .../src/crypto/generators/DesEdeKeyGenerator.cs    |    67 +
 .../src/crypto/generators/DesKeyGenerator.cs       |    57 +
 .../src/crypto/generators/DsaKeyPairGenerator.cs   |    72 +
 .../crypto/generators/DsaParametersGenerator.cs    |   390 +
 .../src/crypto/generators/ECKeyPairGenerator.cs    |   167 +
 .../crypto/generators/ElGamalKeyPairGenerator.cs   |    40 +
 .../generators/ElGamalParametersGenerator.cs       |    46 +
 .../crypto/generators/GOST3410KeyPairGenerator.cs  |    88 +
 .../generators/GOST3410ParametersGenerator.cs      |   530 +
 .../src/crypto/generators/Kdf1BytesGenerator.cs    |    26 +
 .../src/crypto/generators/Kdf2BytesGenerator.cs    |    27 +
 .../src/crypto/generators/Mgf1BytesGenerator.cs    |   117 +
 .../generators/NaccacheSternKeyPairGenerator.cs    |   333 +
 .../generators/OpenSSLPBEParametersGenerator.cs    |   167 +
 .../crypto/generators/Pkcs12ParametersGenerator.cs |   245 +
 .../generators/Pkcs5S1ParametersGenerator.cs       |   162 +
 .../generators/Pkcs5S2ParametersGenerator.cs       |   180 +
 .../src/crypto/generators/Poly1305KeyGenerator.cs  |   123 +
 .../generators/RSABlindingFactorGenerator.cs       |    69 +
 .../src/crypto/generators/RsaKeyPairGenerator.cs   |   150 +
 .../src/crypto/generators/SCrypt.cs                |   140 +
 BouncyCastle.AxCrypt/src/crypto/io/CipherStream.cs |   238 +
 BouncyCastle.AxCrypt/src/crypto/io/DigestStream.cs |   141 +
 BouncyCastle.AxCrypt/src/crypto/io/MacStream.cs    |   140 +
 BouncyCastle.AxCrypt/src/crypto/io/SignerStream.cs |   141 +
 BouncyCastle.AxCrypt/src/crypto/macs/CMac.cs       |   257 +
 .../src/crypto/macs/CbcBlockCipherMac.cs           |   209 +
 .../src/crypto/macs/CfbBlockCipherMac.cs           |   368 +
 BouncyCastle.AxCrypt/src/crypto/macs/GMac.cs       |   112 +
 .../src/crypto/macs/GOST28147Mac.cs                |   296 +
 BouncyCastle.AxCrypt/src/crypto/macs/HMac.cs       |   154 +
 .../src/crypto/macs/ISO9797Alg3Mac.cs              |   275 +
 BouncyCastle.AxCrypt/src/crypto/macs/Poly1305.cs   |   291 +
 BouncyCastle.AxCrypt/src/crypto/macs/SipHash.cs    |   199 +
 BouncyCastle.AxCrypt/src/crypto/macs/SkeinMac.cs   |   117 +
 BouncyCastle.AxCrypt/src/crypto/macs/VMPCMac.cs    |   173 +
 .../src/crypto/modes/CbcBlockCipher.cs             |   241 +
 .../src/crypto/modes/CcmBlockCipher.cs             |   383 +
 .../src/crypto/modes/CfbBlockCipher.cs             |   224 +
 .../src/crypto/modes/CtsBlockCipher.cs             |   253 +
 .../src/crypto/modes/EAXBlockCipher.cs             |   370 +
 .../src/crypto/modes/GCMBlockCipher.cs             |   516 +
 .../src/crypto/modes/GOFBBlockCipher.cs            |   227 +
 .../src/crypto/modes/IAeadBlockCipher.cs           |   105 +
 .../src/crypto/modes/OCBBlockCipher.cs             |   558 +
 .../src/crypto/modes/OfbBlockCipher.cs             |   182 +
 .../src/crypto/modes/OpenPgpCfbBlockCipher.cs      |   337 +
 .../src/crypto/modes/SicBlockCipher.cs             |   115 +
 .../src/crypto/modes/gcm/BasicGcmExponentiator.cs  |    40 +
 .../src/crypto/modes/gcm/BasicGcmMultiplier.cs     |    22 +
 .../src/crypto/modes/gcm/GcmUtilities.cs           |   237 +
 .../src/crypto/modes/gcm/IGcmExponentiator.cs      |    10 +
 .../src/crypto/modes/gcm/IGcmMultiplier.cs         |    10 +
 .../crypto/modes/gcm/Tables1kGcmExponentiator.cs   |    60 +
 .../src/crypto/modes/gcm/Tables64kGcmMultiplier.cs |    77 +
 .../src/crypto/modes/gcm/Tables8kGcmMultiplier.cs  |   103 +
 .../src/crypto/paddings/BlockCipherPadding.cs      |    43 +
 .../src/crypto/paddings/ISO10126d2Padding.cs       |    76 +
 .../src/crypto/paddings/ISO7816d4Padding.cs        |    79 +
 .../crypto/paddings/PaddedBufferedBlockCipher.cs   |   288 +
 .../src/crypto/paddings/Pkcs7Padding.cs            |    79 +
 .../src/crypto/paddings/TbcPadding.cs              |    79 +
 .../src/crypto/paddings/X923Padding.cs             |    82 +
 .../src/crypto/paddings/ZeroBytePadding.cs         |    68 +
 .../src/crypto/parameters/AEADParameters.cs        |    65 +
 .../src/crypto/parameters/CcmParameters.cs         |    26 +
 .../crypto/parameters/DHKeyGenerationParameters.cs |    31 +
 .../src/crypto/parameters/DHKeyParameters.cs       |    76 +
 .../src/crypto/parameters/DHParameters.cs          |   184 +
 .../crypto/parameters/DHPrivateKeyParameters.cs    |    60 +
 .../src/crypto/parameters/DHPublicKeyParameters.cs |    66 +
 .../crypto/parameters/DHValidationParameters.cs    |    59 +
 .../parameters/DSAParameterGenerationParameters.cs |    74 +
 .../src/crypto/parameters/DesEdeParameters.cs      |    95 +
 .../src/crypto/parameters/DesParameters.cs         |   130 +
 .../parameters/DsaKeyGenerationParameters.cs       |    26 +
 .../src/crypto/parameters/DsaKeyParameters.cs      |    59 +
 .../src/crypto/parameters/DsaParameters.cs         |    85 +
 .../crypto/parameters/DsaPrivateKeyParameters.cs   |    53 +
 .../crypto/parameters/DsaPublicKeyParameters.cs    |    52 +
 .../crypto/parameters/DsaValidationParameters.cs   |    72 +
 .../src/crypto/parameters/ECDomainParameters.cs    |   116 +
 .../crypto/parameters/ECKeyGenerationParameters.cs |    41 +
 .../src/crypto/parameters/ECKeyParameters.cs       |   136 +
 .../crypto/parameters/ECPrivateKeyParameters.cs    |    87 +
 .../src/crypto/parameters/ECPublicKeyParameters.cs |    86 +
 .../parameters/ElGamalKeyGenerationParameters.cs   |    31 +
 .../src/crypto/parameters/ElGamalKeyParameters.cs  |    59 +
 .../src/crypto/parameters/ElGamalParameters.cs     |    81 +
 .../parameters/ElGamalPrivateKeyParameters.cs      |    53 +
 .../parameters/ElGamalPublicKeyParameters.cs       |    53 +
 .../parameters/GOST3410KeyGenerationParameters.cs  |    55 +
 .../src/crypto/parameters/GOST3410KeyParameters.cs |    58 +
 .../src/crypto/parameters/GOST3410Parameters.cs    |    86 +
 .../parameters/GOST3410PrivateKeyParameters.cs     |    41 +
 .../parameters/GOST3410PublicKeyParameters.cs      |    40 +
 .../parameters/GOST3410ValidationParameters.cs     |    51 +
 .../src/crypto/parameters/ISO18033KDFParameters.cs |    25 +
 .../src/crypto/parameters/IesParameters.cs         |    49 +
 .../crypto/parameters/IesWithCipherParameters.cs   |    33 +
 .../src/crypto/parameters/KdfParameters.cs         |    33 +
 .../src/crypto/parameters/KeyParameter.cs          |    43 +
 .../src/crypto/parameters/MgfParameters.cs         |    31 +
 .../src/crypto/parameters/MqvPrivateParameters.cs  |    44 +
 .../src/crypto/parameters/MqvPublicParameters.cs   |    29 +
 .../NaccacheSternKeyGenerationParameters.cs        |   101 +
 .../parameters/NaccacheSternKeyParameters.cs       |    44 +
 .../NaccacheSternPrivateKeyParameters.cs           |    79 +
 .../src/crypto/parameters/ParametersWithIV.cs      |    43 +
 .../src/crypto/parameters/ParametersWithRandom.cs  |    48 +
 .../src/crypto/parameters/ParametersWithSBox.cs    |    24 +
 .../src/crypto/parameters/ParametersWithSalt.cs    |    39 +
 .../src/crypto/parameters/RC2Parameters.cs         |    47 +
 .../src/crypto/parameters/RC5Parameters.cs         |    27 +
 .../src/crypto/parameters/RSABlindingParameters.cs |    34 +
 .../parameters/RsaKeyGenerationParameters.cs       |    55 +
 .../src/crypto/parameters/RsaKeyParameters.cs      |    63 +
 .../parameters/RsaPrivateCrtKeyParameters.cs       |   104 +
 .../src/crypto/parameters/SkeinParameters.cs       |   285 +
 .../parameters/TweakableBlockCipherParameters.cs   |    40 +
 .../src/crypto/prng/CryptoApiRandomGenerator.cs    |    66 +
 .../src/crypto/prng/DigestRandomGenerator.cs       |   129 +
 .../src/crypto/prng/IRandomGenerator.cs            |    26 +
 .../src/crypto/prng/ReversedWindowGenerator.cs     |    98 +
 .../src/crypto/prng/ThreadedSeedGenerator.cs       |   121 +
 .../src/crypto/prng/VMPCRandomGenerator.cs         |   114 +
 .../src/crypto/signers/DsaDigestSigner.cs          |   145 +
 .../src/crypto/signers/DsaSigner.cs                |   156 +
 .../src/crypto/signers/ECDsaSigner.cs              |   185 +
 .../src/crypto/signers/ECGOST3410Signer.cs         |   162 +
 .../src/crypto/signers/ECNRSigner.cs               |   188 +
 .../src/crypto/signers/GOST3410DigestSigner.cs     |   145 +
 .../src/crypto/signers/GOST3410Signer.cs           |   132 +
 .../src/crypto/signers/GenericSigner.cs            |   129 +
 .../src/crypto/signers/HMacDsaKCalculator.cs       |   150 +
 .../src/crypto/signers/IDsaKCalculator.cs          |    44 +
 .../src/crypto/signers/Iso9796d2PssSigner.cs       |   617 +
 .../src/crypto/signers/Iso9796d2Signer.cs          |   563 +
 .../src/crypto/signers/PssSigner.cs                |   345 +
 .../src/crypto/signers/RandomDsaKCalculator.cs     |    44 +
 .../src/crypto/signers/RsaDigestSigner.cs          |   218 +
 .../crypto/tls/AbstractTlsAgreementCredentials.cs  |    12 +
 .../src/crypto/tls/AbstractTlsCipherFactory.cs     |    15 +
 .../src/crypto/tls/AbstractTlsClient.cs            |   232 +
 .../src/crypto/tls/AbstractTlsContext.cs           |   132 +
 .../src/crypto/tls/AbstractTlsCredentials.cs       |    10 +
 .../crypto/tls/AbstractTlsEncryptionCredentials.cs |    12 +
 .../src/crypto/tls/AbstractTlsKeyExchange.cs       |   166 +
 .../src/crypto/tls/AbstractTlsPeer.cs              |    48 +
 .../src/crypto/tls/AbstractTlsServer.cs            |   318 +
 .../src/crypto/tls/AbstractTlsSigner.cs            |    50 +
 .../src/crypto/tls/AbstractTlsSignerCredentials.cs |    20 +
 .../src/crypto/tls/AlertDescription.cs             |   217 +
 BouncyCastle.AxCrypt/src/crypto/tls/AlertLevel.cs  |    11 +
 .../src/crypto/tls/AlwaysValidVerifyer.cs          |    24 +
 .../src/crypto/tls/BulkCipherAlgorithm.cs          |    25 +
 BouncyCastle.AxCrypt/src/crypto/tls/ByteQueue.cs   |   147 +
 .../src/crypto/tls/CertChainType.cs                |    18 +
 BouncyCastle.AxCrypt/src/crypto/tls/Certificate.cs |   136 +
 .../src/crypto/tls/CertificateRequest.cs           |   156 +
 .../src/crypto/tls/CertificateStatus.cs            |   102 +
 .../src/crypto/tls/CertificateStatusRequest.cs     |    95 +
 .../src/crypto/tls/CertificateStatusType.cs        |    12 +
 .../src/crypto/tls/CertificateUrl.cs               |   124 +
 .../src/crypto/tls/Chacha20Poly1305.cs             |   153 +
 .../src/crypto/tls/ChangeCipherSpec.cs             |     9 +
 BouncyCastle.AxCrypt/src/crypto/tls/CipherSuite.cs |   352 +
 BouncyCastle.AxCrypt/src/crypto/tls/CipherType.cs  |    20 +
 .../src/crypto/tls/ClientAuthenticationType.cs     |    14 +
 .../src/crypto/tls/ClientCertificateType.cs        |    23 +
 .../src/crypto/tls/CombinedHash.cs                 |   133 +
 .../src/crypto/tls/CompressionMethod.cs            |    22 +
 .../src/crypto/tls/ConnectionEnd.cs                |    15 +
 BouncyCastle.AxCrypt/src/crypto/tls/ContentType.cs |    14 +
 .../crypto/tls/DefaultTlsAgreementCredentials.cs   |    69 +
 .../src/crypto/tls/DefaultTlsCipherFactory.cs      |   225 +
 .../src/crypto/tls/DefaultTlsClient.cs             |   461 +
 .../crypto/tls/DefaultTlsEncryptionCredentials.cs  |    51 +
 .../src/crypto/tls/DefaultTlsServer.cs             |   548 +
 .../src/crypto/tls/DefaultTlsSignerCredentials.cs  |    92 +
 .../src/crypto/tls/DeferredHash.cs                 |   201 +
 .../src/crypto/tls/DigestAlgorithm.cs              |    21 +
 .../src/crypto/tls/DigestInputBuffer.cs            |    39 +
 .../src/crypto/tls/DigitallySigned.cs              |    70 +
 BouncyCastle.AxCrypt/src/crypto/tls/ECBasisType.cs |    16 +
 BouncyCastle.AxCrypt/src/crypto/tls/ECCurveType.cs |    29 +
 .../src/crypto/tls/ECPointFormat.cs                |    16 +
 .../src/crypto/tls/EncryptionAlgorithm.cs          |    69 +
 .../src/crypto/tls/ExporterLabel.cs                |    32 +
 .../src/crypto/tls/ExtensionType.cs                |    61 +
 .../src/crypto/tls/HandshakeType.cs                |    40 +
 .../src/crypto/tls/HashAlgorithm.cs                |    16 +
 .../src/crypto/tls/HeartbeatExtension.cs           |    52 +
 .../src/crypto/tls/HeartbeatMessage.cs             |   102 +
 .../src/crypto/tls/HeartbeatMessageType.cs         |    18 +
 .../src/crypto/tls/HeartbeatMode.cs                |    18 +
 .../src/crypto/tls/ICertificateVerifyer.cs         |    18 +
 .../src/crypto/tls/KeyExchangeAlgorithm.cs         |    54 +
 .../src/crypto/tls/LegacyTlsAuthentication.cs      |    30 +
 .../src/crypto/tls/LegacyTlsClient.cs              |    26 +
 .../src/crypto/tls/MacAlgorithm.cs                 |    25 +
 .../src/crypto/tls/MaxFragmentLength.cs            |    20 +
 BouncyCastle.AxCrypt/src/crypto/tls/NameType.cs    |    12 +
 BouncyCastle.AxCrypt/src/crypto/tls/NamedCurve.cs  |    77 +
 .../src/crypto/tls/NewSessionTicket.cs             |    53 +
 .../src/crypto/tls/OcspStatusRequest.cs            |   130 +
 .../src/crypto/tls/PrfAlgorithm.cs                 |    24 +
 .../src/crypto/tls/ProtocolVersion.cs              |   159 +
 .../src/crypto/tls/PskTlsClient.cs                 |   261 +
 .../src/crypto/tls/RecordStream.cs                 |   333 +
 .../src/crypto/tls/SecurityParameters.cs           |    94 +
 .../src/crypto/tls/ServerDHParams.cs               |    60 +
 BouncyCastle.AxCrypt/src/crypto/tls/ServerName.cs  |   105 +
 .../src/crypto/tls/ServerNameList.cs               |    81 +
 .../src/crypto/tls/ServerOnlyTlsAuthentication.cs  |    15 +
 .../src/crypto/tls/SessionParameters.cs            |   137 +
 .../src/crypto/tls/SignatureAlgorithm.cs           |    15 +
 .../src/crypto/tls/SignatureAndHashAlgorithm.cs    |    94 +
 .../src/crypto/tls/SignerInputBuffer.cs            |    39 +
 .../src/crypto/tls/SrpTlsClient.cs                 |   123 +
 .../src/crypto/tls/SrtpProtectionProfile.cs        |    15 +
 BouncyCastle.AxCrypt/src/crypto/tls/Ssl3Mac.cs     |   110 +
 .../src/crypto/tls/SupplementalDataEntry.cs        |    26 +
 .../src/crypto/tls/SupplementalDataType.cs         |    13 +
 .../src/crypto/tls/TlsAeadCipher.cs                |   189 +
 .../src/crypto/tls/TlsAgreementCredentials.cs      |    12 +
 .../src/crypto/tls/TlsAuthentication.cs            |    31 +
 .../src/crypto/tls/TlsBlockCipher.cs               |   378 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsCipher.cs   |    16 +
 .../src/crypto/tls/TlsCipherFactory.cs             |    11 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsClient.cs   |   134 +
 .../src/crypto/tls/TlsClientContext.cs             |    11 +
 .../src/crypto/tls/TlsClientContextImpl.cs         |    20 +
 .../src/crypto/tls/TlsClientProtocol.cs            |   861 +
 .../src/crypto/tls/TlsCompression.cs               |    12 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsContext.cs  |    45 +
 .../src/crypto/tls/TlsCredentials.cs               |     9 +
 .../src/crypto/tls/TlsDHKeyExchange.cs             |   193 +
 .../src/crypto/tls/TlsDHUtilities.cs               |   101 +
 .../src/crypto/tls/TlsDeflateCompression.cs        |    68 +
 .../src/crypto/tls/TlsDheKeyExchange.cs            |   105 +
 .../src/crypto/tls/TlsDsaSigner.cs                 |    83 +
 .../src/crypto/tls/TlsDssSigner.cs                 |    26 +
 .../src/crypto/tls/TlsECDHKeyExchange.cs           |   211 +
 .../src/crypto/tls/TlsECDheKeyExchange.cs          |   206 +
 .../src/crypto/tls/TlsECDsaSigner.cs               |    26 +
 .../src/crypto/tls/TlsEccUtilities.cs              |   647 +
 .../src/crypto/tls/TlsEncryptionCredentials.cs     |    12 +
 .../src/crypto/tls/TlsException.cs                 |    11 +
 .../src/crypto/tls/TlsExtensionsUtilities.cs       |   243 +
 .../src/crypto/tls/TlsFatalAlert.cs                |    27 +
 .../src/crypto/tls/TlsHandshakeHash.cs             |    22 +
 .../src/crypto/tls/TlsKeyExchange.cs               |    54 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsMac.cs      |   173 +
 .../src/crypto/tls/TlsNullCipher.cs                |   118 +
 .../src/crypto/tls/TlsNullCompression.cs           |    19 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsPeer.cs     |    62 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocol.cs |  1102 +
 .../src/crypto/tls/TlsProtocolHandler.cs           |    39 +
 .../src/crypto/tls/TlsPskIdentity.cs               |    15 +
 .../src/crypto/tls/TlsPskKeyExchange.cs            |   254 +
 .../src/crypto/tls/TlsRsaKeyExchange.cs            |   140 +
 .../src/crypto/tls/TlsRsaSigner.cs                 |   102 +
 .../src/crypto/tls/TlsRsaUtilities.cs              |   132 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsServer.cs   |    90 +
 .../src/crypto/tls/TlsServerContext.cs             |    11 +
 .../src/crypto/tls/TlsServerContextImpl.cs         |    20 +
 .../src/crypto/tls/TlsServerProtocol.cs            |   744 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsSession.cs  |    15 +
 .../src/crypto/tls/TlsSessionImpl.cs               |    54 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsSigner.cs   |    29 +
 .../src/crypto/tls/TlsSignerCredentials.cs         |    14 +
 .../src/crypto/tls/TlsSrpKeyExchange.cs            |   189 +
 .../src/crypto/tls/TlsSrpUtilities.cs              |    41 +
 .../src/crypto/tls/TlsSrtpUtilities.cs             |    62 +
 BouncyCastle.AxCrypt/src/crypto/tls/TlsStream.cs   |    89 +
 .../src/crypto/tls/TlsStreamCipher.cs              |   164 +
 .../src/crypto/tls/TlsUtilities.cs                 |  1631 +
 BouncyCastle.AxCrypt/src/crypto/tls/UrlAndHash.cs  |    94 +
 BouncyCastle.AxCrypt/src/crypto/tls/UseSrtpData.cs |    56 +
 .../src/crypto/tls/UserMappingType.cs              |    13 +
 BouncyCastle.AxCrypt/src/crypto/util/Pack.cs       |   266 +
 BouncyCastle.AxCrypt/src/math/BigInteger.cs        |  3565 ++
 BouncyCastle.AxCrypt/src/math/ec/ECAlgorithms.cs   |   459 +
 BouncyCastle.AxCrypt/src/math/ec/ECCurve.cs        |  1111 +
 BouncyCastle.AxCrypt/src/math/ec/ECFieldElement.cs |   917 +
 BouncyCastle.AxCrypt/src/math/ec/ECPoint.cs        |  2089 +
 BouncyCastle.AxCrypt/src/math/ec/ECPointMap.cs     |     9 +
 BouncyCastle.AxCrypt/src/math/ec/IntArray.cs       |   485 +
 BouncyCastle.AxCrypt/src/math/ec/LongArray.cs      |  2201 ++
 BouncyCastle.AxCrypt/src/math/ec/Mod.cs            |   184 +
 BouncyCastle.AxCrypt/src/math/ec/Nat.cs            |  1013 +
 BouncyCastle.AxCrypt/src/math/ec/ScaleXPointMap.cs |    20 +
 BouncyCastle.AxCrypt/src/math/ec/ScaleYPointMap.cs |    20 +
 .../src/math/ec/abc/SimpleBigDecimal.cs            |   241 +
 BouncyCastle.AxCrypt/src/math/ec/abc/Tnaf.cs       |   828 +
 .../src/math/ec/abc/ZTauElement.cs                 |    36 +
 .../src/math/ec/custom/djb/Curve25519.cs           |    77 +
 .../src/math/ec/custom/djb/Curve25519Field.cs      |   253 +
 .../math/ec/custom/djb/Curve25519FieldElement.cs   |   233 +
 .../src/math/ec/custom/djb/Curve25519Point.cs      |   313 +
 .../src/math/ec/custom/sec/Nat192.cs               |   962 +
 .../src/math/ec/custom/sec/Nat224.cs               |  1176 +
 .../src/math/ec/custom/sec/Nat256.cs               |  1300 +
 .../src/math/ec/custom/sec/Nat384.cs               |    46 +
 .../src/math/ec/custom/sec/Nat512.cs               |    46 +
 .../src/math/ec/custom/sec/SecP192K1Curve.cs       |    75 +
 .../src/math/ec/custom/sec/SecP192K1Field.cs       |   176 +
 .../math/ec/custom/sec/SecP192K1FieldElement.cs    |   212 +
 .../src/math/ec/custom/sec/SecP192K1Point.cs       |   265 +
 .../src/math/ec/custom/sec/SecP192R1Curve.cs       |    78 +
 .../src/math/ec/custom/sec/SecP192R1Field.cs       |   281 +
 .../math/ec/custom/sec/SecP192R1FieldElement.cs    |   187 +
 .../src/math/ec/custom/sec/SecP192R1Point.cs       |   277 +
 .../src/math/ec/custom/sec/SecP224K1Curve.cs       |    75 +
 .../src/math/ec/custom/sec/SecP224K1Field.cs       |   177 +
 .../math/ec/custom/sec/SecP224K1FieldElement.cs    |   241 +
 .../src/math/ec/custom/sec/SecP224K1Point.cs       |   265 +
 .../src/math/ec/custom/sec/SecP224R1Curve.cs       |    78 +
 .../src/math/ec/custom/sec/SecP224R1Field.cs       |   295 +
 .../math/ec/custom/sec/SecP224R1FieldElement.cs    |   268 +
 .../src/math/ec/custom/sec/SecP224R1Point.cs       |   277 +
 .../src/math/ec/custom/sec/SecP256K1Curve.cs       |    75 +
 .../src/math/ec/custom/sec/SecP256K1Field.cs       |   178 +
 .../math/ec/custom/sec/SecP256K1FieldElement.cs    |   213 +
 .../src/math/ec/custom/sec/SecP256K1Point.cs       |   265 +
 .../src/math/ec/custom/sec/SecP256R1Curve.cs       |    77 +
 .../src/math/ec/custom/sec/SecP256R1Field.cs       |   309 +
 .../math/ec/custom/sec/SecP256R1FieldElement.cs    |   187 +
 .../src/math/ec/custom/sec/SecP256R1Point.cs       |   277 +
 .../src/math/ec/custom/sec/SecP384R1Curve.cs       |    77 +
 .../src/math/ec/custom/sec/SecP384R1Field.cs       |   292 +
 .../math/ec/custom/sec/SecP384R1FieldElement.cs    |   209 +
 .../src/math/ec/custom/sec/SecP384R1Point.cs       |   278 +
 .../src/math/ec/custom/sec/SecP521R1Curve.cs       |    77 +
 .../src/math/ec/custom/sec/SecP521R1Field.cs       |   153 +
 .../math/ec/custom/sec/SecP521R1FieldElement.cs    |   166 +
 .../src/math/ec/custom/sec/SecP521R1Point.cs       |   273 +
 .../src/math/ec/endo/ECEndomorphism.cs             |    11 +
 .../src/math/ec/endo/GlvEndomorphism.cs            |    10 +
 .../src/math/ec/endo/GlvTypeBEndomorphism.cs       |    55 +
 .../src/math/ec/endo/GlvTypeBParameters.cs         |    60 +
 .../src/math/ec/multiplier/AbstractECMultiplier.cs |    24 +
 .../src/math/ec/multiplier/DoubleAddMultiplier.cs  |    24 +
 .../src/math/ec/multiplier/ECMultiplier.cs         |    18 +
 .../math/ec/multiplier/FixedPointCombMultiplier.cs |    59 +
 .../math/ec/multiplier/FixedPointPreCompInfo.cs    |    34 +
 .../src/math/ec/multiplier/FixedPointUtilities.cs  |    72 +
 .../src/math/ec/multiplier/FpNafMultiplier.cs      |    39 +
 .../src/math/ec/multiplier/GlvMultiplier.cs        |    40 +
 .../math/ec/multiplier/MixedNafR2LMultiplier.cs    |    75 +
 .../ec/multiplier/MontgomeryLadderMultiplier.cs    |    25 +
 .../src/math/ec/multiplier/NafL2RMultiplier.cs     |    30 +
 .../src/math/ec/multiplier/NafR2LMultiplier.cs     |    31 +
 .../src/math/ec/multiplier/PreCompInfo.cs          |    11 +
 .../src/math/ec/multiplier/ReferenceMultiplier.cs  |    11 +
 .../src/math/ec/multiplier/WNafL2RMultiplier.cs    |    98 +
 .../src/math/ec/multiplier/WNafMultiplier.cs       |   241 +
 .../src/math/ec/multiplier/WNafPreCompInfo.cs      |    46 +
 .../src/math/ec/multiplier/WNafUtilities.cs        |   469 +
 .../src/math/ec/multiplier/WTauNafMultiplier.cs    |   116 +
 .../src/math/ec/multiplier/WTauNafPreCompInfo.cs   |    24 +
 .../ec/multiplier/ZSignedDigitL2RMultiplier.cs     |    29 +
 .../ec/multiplier/ZSignedDigitR2LMultiplier.cs     |    30 +
 .../src/math/field/FiniteFields.cs                 |    54 +
 .../src/math/field/GF2Polynomial.cs                |    46 +
 .../math/field/GenericPolynomialExtensionField.cs  |    63 +
 .../src/math/field/IExtensionField.cs              |    12 +
 .../src/math/field/IFiniteField.cs                 |    11 +
 BouncyCastle.AxCrypt/src/math/field/IPolynomial.cs |    15 +
 .../src/math/field/IPolynomialExtensionField.cs    |    10 +
 BouncyCastle.AxCrypt/src/math/field/PrimeField.cs  |    44 +
 BouncyCastle.AxCrypt/src/ocsp/BasicOCSPResp.cs     |   220 +
 .../src/ocsp/BasicOCSPRespGenerator.cs             |   318 +
 BouncyCastle.AxCrypt/src/ocsp/CertificateID.cs     |   141 +
 BouncyCastle.AxCrypt/src/ocsp/CertificateStatus.cs |     9 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPException.cs     |    28 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPReq.cs           |   268 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPReqGenerator.cs  |   243 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPResp.cs          |   100 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPRespGenerator.cs |    54 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPRespStatus.cs    |    22 +
 BouncyCastle.AxCrypt/src/ocsp/OCSPUtil.cs          |   132 +
 BouncyCastle.AxCrypt/src/ocsp/Req.cs               |    38 +
 BouncyCastle.AxCrypt/src/ocsp/RespData.cs          |    60 +
 BouncyCastle.AxCrypt/src/ocsp/RespID.cs            |    72 +
 BouncyCastle.AxCrypt/src/ocsp/RevokedStatus.cs     |    58 +
 BouncyCastle.AxCrypt/src/ocsp/SingleResp.cs        |    81 +
 BouncyCastle.AxCrypt/src/ocsp/UnknownStatus.cs     |    15 +
 .../src/openpgp/IStreamGenerator.cs                |     7 +
 BouncyCastle.AxCrypt/src/openpgp/PGPKeyRing.cs     |    79 +
 BouncyCastle.AxCrypt/src/openpgp/PGPObject.cs      |     9 +
 .../PGPUserAttributeSubpacketVectorGenerator.cs    |    33 +
 .../src/openpgp/PgpCompressedData.cs               |    50 +
 .../src/openpgp/PgpCompressedDataGenerator.cs      |   204 +
 .../src/openpgp/PgpDataValidationException.cs      |    18 +
 .../src/openpgp/PgpEncryptedData.cs                |   151 +
 .../src/openpgp/PgpEncryptedDataGenerator.cs       |   506 +
 .../src/openpgp/PgpEncryptedDataList.cs            |    72 +
 BouncyCastle.AxCrypt/src/openpgp/PgpException.cs   |    22 +
 .../src/openpgp/PgpExperimental.cs                 |    16 +
 BouncyCastle.AxCrypt/src/openpgp/PgpKeyFlags.cs    |    13 +
 BouncyCastle.AxCrypt/src/openpgp/PgpKeyPair.cs     |    67 +
 .../src/openpgp/PgpKeyRingGenerator.cs             |   167 +
 .../src/openpgp/PgpKeyValidationException.cs       |    18 +
 BouncyCastle.AxCrypt/src/openpgp/PgpLiteralData.cs |    63 +
 .../src/openpgp/PgpLiteralDataGenerator.cs         |   182 +
 BouncyCastle.AxCrypt/src/openpgp/PgpMarker.cs      |    18 +
 .../src/openpgp/PgpObjectFactory.cs                |   143 +
 .../src/openpgp/PgpOnePassSignature.cs             |   179 +
 .../src/openpgp/PgpOnePassSignatureList.cs         |    51 +
 .../src/openpgp/PgpPbeEncryptedData.cs             |   135 +
 BouncyCastle.AxCrypt/src/openpgp/PgpPrivateKey.cs  |    42 +
 BouncyCastle.AxCrypt/src/openpgp/PgpPublicKey.cs   |   890 +
 .../src/openpgp/PgpPublicKeyEncryptedData.cs       |   252 +
 .../src/openpgp/PgpPublicKeyRing.cs                |   200 +
 .../src/openpgp/PgpPublicKeyRingBundle.cs          |   279 +
 BouncyCastle.AxCrypt/src/openpgp/PgpSecretKey.cs   |   702 +
 .../src/openpgp/PgpSecretKeyRing.cs                |   308 +
 .../src/openpgp/PgpSecretKeyRingBundle.cs          |   281 +
 BouncyCastle.AxCrypt/src/openpgp/PgpSignature.cs   |   422 +
 .../src/openpgp/PgpSignatureGenerator.cs           |   393 +
 .../src/openpgp/PgpSignatureList.cs                |    51 +
 .../src/openpgp/PgpSignatureSubpacketGenerator.cs  |   193 +
 .../src/openpgp/PgpSignatureSubpacketVector.cs     |   229 +
 .../src/openpgp/PgpUserAttributeSubpacketVector.cs |    81 +
 BouncyCastle.AxCrypt/src/openpgp/PgpUtilities.cs   |   437 +
 .../src/openpgp/PgpV3SignatureGenerator.cs         |   199 +
 .../src/openpgp/WrappedGeneratorStream.cs          |    29 +
 .../src/openssl/EncryptionException.cs             |    25 +
 .../src/openssl/IPasswordFinder.cs                 |     9 +
 .../src/openssl/MiscPemGenerator.cs                |   276 +
 BouncyCastle.AxCrypt/src/openssl/PEMException.cs   |    25 +
 BouncyCastle.AxCrypt/src/openssl/PEMReader.cs      |   400 +
 BouncyCastle.AxCrypt/src/openssl/PEMUtilities.cs   |   158 +
 BouncyCastle.AxCrypt/src/openssl/PEMWriter.cs      |    61 +
 .../src/openssl/PasswordException.cs               |    25 +
 BouncyCastle.AxCrypt/src/openssl/Pkcs8Generator.cs |   111 +
 .../src/pkcs/AsymmetricKeyEntry.cs                 |    60 +
 .../src/pkcs/EncryptedPrivateKeyInfoFactory.cs     |    64 +
 .../src/pkcs/PKCS12StoreBuilder.cs                 |    41 +
 .../src/pkcs/Pkcs10CertificationRequest.cs         |   465 +
 .../pkcs/Pkcs10CertificationRequestDelaySigned.cs  |   150 +
 BouncyCastle.AxCrypt/src/pkcs/Pkcs12Entry.cs       |    64 +
 BouncyCastle.AxCrypt/src/pkcs/Pkcs12Store.cs       |  1228 +
 BouncyCastle.AxCrypt/src/pkcs/Pkcs12Utilities.cs   |    77 +
 .../src/pkcs/PrivateKeyInfoFactory.cs              |   208 +
 .../src/pkcs/X509CertificateEntry.cs               |    60 +
 BouncyCastle.AxCrypt/src/pkix/CertStatus.cs        |    35 +
 .../src/pkix/PkixAttrCertChecker.cs                |    57 +
 .../src/pkix/PkixAttrCertPathBuilder.cs            |   215 +
 .../src/pkix/PkixAttrCertPathValidator.cs          |    76 +
 .../src/pkix/PkixBuilderParameters.cs              |   140 +
 BouncyCastle.AxCrypt/src/pkix/PkixCertPath.cs      |   460 +
 .../src/pkix/PkixCertPathBuilder.cs                |   205 +
 .../src/pkix/PkixCertPathBuilderException.cs       |    22 +
 .../src/pkix/PkixCertPathBuilderResult.cs          |    45 +
 .../src/pkix/PkixCertPathChecker.cs                |   101 +
 .../src/pkix/PkixCertPathValidator.cs              |   420 +
 .../src/pkix/PkixCertPathValidatorException.cs     |   221 +
 .../src/pkix/PkixCertPathValidatorResult.cs        |    69 +
 .../src/pkix/PkixCertPathValidatorUtilities.cs     |  1194 +
 BouncyCastle.AxCrypt/src/pkix/PkixCrlUtilities.cs  |   114 +
 .../src/pkix/PkixNameConstraintValidator.cs        |  1937 +
 .../pkix/PkixNameConstraintValidatorException.cs   |    16 +
 BouncyCastle.AxCrypt/src/pkix/PkixParameters.cs    |   893 +
 BouncyCastle.AxCrypt/src/pkix/PkixPolicyNode.cs    |   158 +
 BouncyCastle.AxCrypt/src/pkix/ReasonsMask.cs       |    96 +
 .../src/pkix/Rfc3280CertPathUtilities.cs           |  2448 ++
 .../src/pkix/Rfc3281CertPathUtilities.cs           |   608 +
 BouncyCastle.AxCrypt/src/pkix/TrustAnchor.cs       |   259 +
 .../src/security/AgreementUtilities.cs             |   105 +
 .../src/security/CipherUtilities.cs                |   735 +
 .../src/security/DigestUtilities.cs                |   202 +
 .../src/security/DotNetUtilities.cs                |   243 +
 .../src/security/GeneralSecurityException.cs       |    29 +
 .../src/security/GeneratorUtilities.cs             |   349 +
 .../src/security/InvalidKeyException.cs            |    14 +
 .../src/security/InvalidParameterException.cs      |    14 +
 BouncyCastle.AxCrypt/src/security/KeyException.cs  |    14 +
 BouncyCastle.AxCrypt/src/security/MacUtilities.cs  |   246 +
 .../src/security/NoSuchAlgorithmException.cs       |    15 +
 .../src/security/ParameterUtilities.cs             |   321 +
 BouncyCastle.AxCrypt/src/security/PbeUtilities.cs  |   663 +
 .../src/security/PrivateKeyFactory.cs              |   224 +
 .../src/security/PublicKeyFactory.cs               |   253 +
 BouncyCastle.AxCrypt/src/security/SecureRandom.cs  |   228 +
 .../src/security/SecurityUtilityException.cs       |    36 +
 .../src/security/SignatureException.cs             |    14 +
 .../src/security/SignerUtilities.cs                |   546 +
 .../src/security/WrapperUtilities.cs               |   153 +
 .../security/cert/CertificateEncodingException.cs  |    14 +
 .../src/security/cert/CertificateException.cs      |    14 +
 .../security/cert/CertificateExpiredException.cs   |    14 +
 .../cert/CertificateNotYetValidException.cs        |    14 +
 .../security/cert/CertificateParsingException.cs   |    14 +
 .../src/security/cert/CrlException.cs              |    14 +
 BouncyCastle.AxCrypt/src/tsp/GenTimeAccuracy.cs    |    33 +
 BouncyCastle.AxCrypt/src/tsp/TSPAlgorithms.cs      |    48 +
 BouncyCastle.AxCrypt/src/tsp/TSPException.cs       |    28 +
 BouncyCastle.AxCrypt/src/tsp/TSPUtil.cs            |   202 +
 .../src/tsp/TSPValidationException.cs              |    44 +
 BouncyCastle.AxCrypt/src/tsp/TimeStampRequest.cs   |   196 +
 .../src/tsp/TimeStampRequestGenerator.cs           |   139 +
 BouncyCastle.AxCrypt/src/tsp/TimeStampResponse.cs  |   184 +
 .../src/tsp/TimeStampResponseGenerator.cs          |   210 +
 BouncyCastle.AxCrypt/src/tsp/TimeStampToken.cs     |   305 +
 .../src/tsp/TimeStampTokenGenerator.cs             |   245 +
 BouncyCastle.AxCrypt/src/tsp/TimeStampTokenInfo.cs |   107 +
 BouncyCastle.AxCrypt/src/util/Arrays.cs            |   612 +
 BouncyCastle.AxCrypt/src/util/BigIntegers.cs       |    90 +
 BouncyCastle.AxCrypt/src/util/Enums.cs             |    69 +
 BouncyCastle.AxCrypt/src/util/IMemoable.cs         |    29 +
 BouncyCastle.AxCrypt/src/util/Integers.cs          |    17 +
 .../src/util/MemoableResetException.cs             |    27 +
 BouncyCastle.AxCrypt/src/util/Platform.cs          |   179 +
 BouncyCastle.AxCrypt/src/util/Strings.cs           |   103 +
 BouncyCastle.AxCrypt/src/util/Times.cs             |    14 +
 .../src/util/collections/CollectionUtilities.cs    |    64 +
 .../src/util/collections/EmptyEnumerable.cs        |    44 +
 .../src/util/collections/EnumerableProxy.cs        |    25 +
 .../src/util/collections/HashSet.cs                |    99 +
 BouncyCastle.AxCrypt/src/util/collections/ISet.cs  |    19 +
 .../src/util/collections/LinkedDictionary.cs       |   178 +
 .../src/util/collections/UnmodifiableDictionary.cs |    64 +
 .../collections/UnmodifiableDictionaryProxy.cs     |    66 +
 .../src/util/collections/UnmodifiableList.cs       |    67 +
 .../src/util/collections/UnmodifiableListProxy.cs  |    61 +
 .../src/util/collections/UnmodifiableSet.cs        |    59 +
 .../src/util/collections/UnmodifiableSetProxy.cs   |    56 +
 .../src/util/date/DateTimeObject.cs                |    25 +
 .../src/util/date/DateTimeUtilities.cs             |    47 +
 BouncyCastle.AxCrypt/src/util/encoders/Base64.cs   |   120 +
 .../src/util/encoders/Base64Encoder.cs             |   324 +
 .../src/util/encoders/BufferedDecoder.cs           |   117 +
 .../src/util/encoders/BufferedEncoder.cs           |   117 +
 BouncyCastle.AxCrypt/src/util/encoders/Hex.cs      |   130 +
 .../src/util/encoders/HexEncoder.cs                |   176 +
 .../src/util/encoders/HexTranslator.cs             |   108 +
 BouncyCastle.AxCrypt/src/util/encoders/IEncoder.cs |    18 +
 .../src/util/encoders/Translator.cs                |    19 +
 .../src/util/encoders/UrlBase64.cs                 |   127 +
 .../src/util/encoders/UrlBase64Encoder.cs          |    31 +
 .../src/util/io/BaseInputStream.cs                 |    56 +
 .../src/util/io/BaseOutputStream.cs                |    54 +
 .../src/util/io/NullOutputStream.cs                |    18 +
 BouncyCastle.AxCrypt/src/util/io/PushbackStream.cs |    52 +
 .../src/util/io/StreamOverflowException.cs         |    30 +
 BouncyCastle.AxCrypt/src/util/io/Streams.cs        |    94 +
 BouncyCastle.AxCrypt/src/util/io/TeeInputStream.cs |    55 +
 .../src/util/io/TeeOutputStream.cs                 |    43 +
 .../src/util/io/pem/PemGenerationException.cs      |    29 +
 BouncyCastle.AxCrypt/src/util/io/pem/PemHeader.cs  |    55 +
 BouncyCastle.AxCrypt/src/util/io/pem/PemObject.cs  |    47 +
 .../src/util/io/pem/PemObjectGenerator.cs          |    13 +
 .../src/util/io/pem/PemObjectParser.cs             |    17 +
 BouncyCastle.AxCrypt/src/util/io/pem/PemReader.cs  |    94 +
 BouncyCastle.AxCrypt/src/util/io/pem/PemWriter.cs  |   120 +
 BouncyCastle.AxCrypt/src/util/net/IPAddress.cs     |   197 +
 BouncyCastle.AxCrypt/src/util/zlib/Adler32.cs      |    88 +
 BouncyCastle.AxCrypt/src/util/zlib/Deflate.cs      |  1640 +
 BouncyCastle.AxCrypt/src/util/zlib/InfBlocks.cs    |   618 +
 BouncyCastle.AxCrypt/src/util/zlib/InfCodes.cs     |   611 +
 BouncyCastle.AxCrypt/src/util/zlib/InfTree.cs      |   523 +
 BouncyCastle.AxCrypt/src/util/zlib/Inflate.cs      |   387 +
 BouncyCastle.AxCrypt/src/util/zlib/JZlib.cs        |    73 +
 BouncyCastle.AxCrypt/src/util/zlib/StaticTree.cs   |   152 +
 BouncyCastle.AxCrypt/src/util/zlib/Tree.cs         |   367 +
 .../src/util/zlib/ZDeflaterOutputStream.cs         |   158 +
 .../src/util/zlib/ZInflaterInputStream.cs          |   132 +
 BouncyCastle.AxCrypt/src/util/zlib/ZInputStream.cs |   197 +
 .../src/util/zlib/ZOutputStream.cs                 |   233 +
 BouncyCastle.AxCrypt/src/util/zlib/ZStream.cs      |   214 +
 .../src/x509/AttributeCertificateHolder.cs         |   442 +
 .../src/x509/AttributeCertificateIssuer.cs         |   199 +
 .../src/x509/IX509AttributeCertificate.cs          |    57 +
 BouncyCastle.AxCrypt/src/x509/IX509Extension.cs    |    27 +
 BouncyCastle.AxCrypt/src/x509/PEMParser.cs         |    94 +
 BouncyCastle.AxCrypt/src/x509/PrincipalUtil.cs     |    70 +
 .../src/x509/SubjectPublicKeyInfoFactory.cs        |   187 +
 .../src/x509/X509AttrCertParser.cs                 |   173 +
 BouncyCastle.AxCrypt/src/x509/X509Attribute.cs     |    76 +
 .../src/x509/X509CertPairParser.cs                 |    95 +
 BouncyCastle.AxCrypt/src/x509/X509Certificate.cs   |   595 +
 .../src/x509/X509CertificatePair.cs                |   123 +
 .../src/x509/X509CertificateParser.cs              |   183 +
 BouncyCastle.AxCrypt/src/x509/X509Crl.cs           |   403 +
 BouncyCastle.AxCrypt/src/x509/X509CrlEntry.cs      |   201 +
 BouncyCastle.AxCrypt/src/x509/X509CrlParser.cs     |   195 +
 BouncyCastle.AxCrypt/src/x509/X509ExtensionBase.cs |    82 +
 BouncyCastle.AxCrypt/src/x509/X509KeyUsage.cs      |    59 +
 BouncyCastle.AxCrypt/src/x509/X509SignatureUtil.cs |   128 +
 BouncyCastle.AxCrypt/src/x509/X509Utilities.cs     |   187 +
 .../src/x509/X509V1CertificateGenerator.cs         |   205 +
 .../src/x509/X509V2AttributeCertificate.cs         |   255 +
 .../x509/X509V2AttributeCertificateGenerator.cs    |   180 +
 .../src/x509/X509V2CRLGenerator.cs                 |   261 +
 .../src/x509/X509V3CertificateGenerator.cs         |   346 +
 .../extension/AuthorityKeyIdentifierStructure.cs   |   102 +
 .../extension/SubjectKeyIdentifierStructure.cs     |    49 +
 .../src/x509/extension/X509ExtensionUtil.cs        |    89 +
 .../src/x509/store/IX509Selector.cs                |    15 +
 BouncyCastle.AxCrypt/src/x509/store/IX509Store.cs  |    11 +
 .../src/x509/store/IX509StoreParameters.cs         |     8 +
 .../src/x509/store/NoSuchStoreException.cs         |    28 +
 .../src/x509/store/X509AttrCertStoreSelector.cs    |   376 +
 .../src/x509/store/X509CertPairStoreSelector.cs    |    92 +
 .../src/x509/store/X509CertStoreSelector.cs        |   337 +
 .../src/x509/store/X509CollectionStore.cs          |    51 +
 .../x509/store/X509CollectionStoreParameters.cs    |    60 +
 .../src/x509/store/X509CrlStoreSelector.cs         |   283 +
 .../src/x509/store/X509StoreException.cs           |    28 +
 .../src/x509/store/X509StoreFactory.cs             |    62 +
 BouncyCastle.AxCrypt/test/data/PKITS/README.txt    |     3 +
 .../certs/AllCertificatesNoPoliciesTest2EE.crt     |   Bin 0 -> 627 bytes
 .../certs/AllCertificatesSamePoliciesTest10EE.crt  |   Bin 0 -> 670 bytes
 .../certs/AllCertificatesSamePoliciesTest13EE.crt  |   Bin 0 -> 687 bytes
 .../certs/AllCertificatesanyPolicyTest11EE.crt     |   Bin 0 -> 643 bytes
 .../test/data/PKITS/certs/AnyPolicyTest14EE.crt    |   Bin 0 -> 632 bytes
 .../data/PKITS/certs/BadCRLIssuerNameCACert.crt    |   Bin 0 -> 640 bytes
 .../data/PKITS/certs/BadCRLSignatureCACert.crt     |   Bin 0 -> 638 bytes
 .../test/data/PKITS/certs/BadSignedCACert.crt      |   Bin 0 -> 631 bytes
 .../data/PKITS/certs/BadnotAfterDateCACert.crt     |   Bin 0 -> 638 bytes
 .../data/PKITS/certs/BadnotBeforeDateCACert.crt    |   Bin 0 -> 639 bytes
 .../certs/BasicSelfIssuedCRLSigningKeyCACert.crt   |   Bin 0 -> 654 bytes
 .../certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt  |   Bin 0 -> 797 bytes
 .../PKITS/certs/BasicSelfIssuedNewKeyCACert.crt    |   Bin 0 -> 646 bytes
 .../BasicSelfIssuedNewKeyOldWithNewCACert.crt      |   Bin 0 -> 662 bytes
 .../PKITS/certs/BasicSelfIssuedOldKeyCACert.crt    |   Bin 0 -> 646 bytes
 .../BasicSelfIssuedOldKeyNewWithOldCACert.crt      |   Bin 0 -> 789 bytes
 .../PKITS/certs/CPSPointerQualifierTest20EE.crt    |   Bin 0 -> 701 bytes
 .../test/data/PKITS/certs/DSACACert.crt            |   Bin 0 -> 906 bytes
 .../PKITS/certs/DSAParametersInheritedCACert.crt   |   Bin 0 -> 536 bytes
 .../data/PKITS/certs/DifferentPoliciesTest12EE.crt |   Bin 0 -> 643 bytes
 .../data/PKITS/certs/DifferentPoliciesTest3EE.crt  |   Bin 0 -> 645 bytes
 .../data/PKITS/certs/DifferentPoliciesTest4EE.crt  |   Bin 0 -> 638 bytes
 .../data/PKITS/certs/DifferentPoliciesTest5EE.crt  |   Bin 0 -> 646 bytes
 .../data/PKITS/certs/DifferentPoliciesTest7EE.crt  |   Bin 0 -> 672 bytes
 .../data/PKITS/certs/DifferentPoliciesTest8EE.crt  |   Bin 0 -> 670 bytes
 .../data/PKITS/certs/DifferentPoliciesTest9EE.crt  |   Bin 0 -> 660 bytes
 .../certs/GeneralizedTimeCRLnextUpdateCACert.crt   |   Bin 0 -> 649 bytes
 .../test/data/PKITS/certs/GoodCACert.crt           |   Bin 0 -> 625 bytes
 .../test/data/PKITS/certs/GoodsubCACert.crt        |   Bin 0 -> 639 bytes
 .../certs/GoodsubCAPanyPolicyMapping1to2CACert.crt |   Bin 0 -> 697 bytes
 .../PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt |   Bin 0 -> 659 bytes
 .../PKITS/certs/InvalidBadCRLSignatureTest4EE.crt  |   Bin 0 -> 655 bytes
 .../InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt |   Bin 0 -> 687 bytes
 .../InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt |   Bin 0 -> 687 bytes
 .../InvalidBasicSelfIssuedNewWithOldTest5EE.crt    |   Bin 0 -> 676 bytes
 .../InvalidBasicSelfIssuedOldWithNewTest2EE.crt    |   Bin 0 -> 676 bytes
 .../data/PKITS/certs/InvalidCASignatureTest2EE.crt |   Bin 0 -> 628 bytes
 .../PKITS/certs/InvalidCAnotAfterDateTest5EE.crt   |   Bin 0 -> 654 bytes
 .../PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt  |   Bin 0 -> 656 bytes
 .../certs/InvalidDNSnameConstraintsTest31EE.crt    |   Bin 0 -> 710 bytes
 .../certs/InvalidDNSnameConstraintsTest33EE.crt    |   Bin 0 -> 699 bytes
 .../certs/InvalidDNSnameConstraintsTest38EE.crt    |   Bin 0 -> 698 bytes
 .../InvalidDNandRFC822nameConstraintsTest28EE.crt  |   Bin 0 -> 778 bytes
 .../InvalidDNandRFC822nameConstraintsTest29EE.crt  |   Bin 0 -> 780 bytes
 .../certs/InvalidDNnameConstraintsTest10EE.crt     |   Bin 0 -> 715 bytes
 .../certs/InvalidDNnameConstraintsTest12EE.crt     |   Bin 0 -> 720 bytes
 .../certs/InvalidDNnameConstraintsTest13EE.crt     |   Bin 0 -> 720 bytes
 .../certs/InvalidDNnameConstraintsTest15EE.crt     |   Bin 0 -> 690 bytes
 .../certs/InvalidDNnameConstraintsTest16EE.crt     |   Bin 0 -> 690 bytes
 .../certs/InvalidDNnameConstraintsTest17EE.crt     |   Bin 0 -> 690 bytes
 .../certs/InvalidDNnameConstraintsTest20EE.crt     |   Bin 0 -> 633 bytes
 .../certs/InvalidDNnameConstraintsTest2EE.crt      |   Bin 0 -> 685 bytes
 .../certs/InvalidDNnameConstraintsTest3EE.crt      |   Bin 0 -> 833 bytes
 .../certs/InvalidDNnameConstraintsTest7EE.crt      |   Bin 0 -> 685 bytes
 .../certs/InvalidDNnameConstraintsTest8EE.crt      |   Bin 0 -> 685 bytes
 .../certs/InvalidDNnameConstraintsTest9EE.crt      |   Bin 0 -> 685 bytes
 .../PKITS/certs/InvalidDSASignatureTest6EE.crt     |   Bin 0 -> 827 bytes
 .../data/PKITS/certs/InvalidEESignatureTest3EE.crt |   Bin 0 -> 622 bytes
 .../PKITS/certs/InvalidEEnotAfterDateTest6EE.crt   |   Bin 0 -> 641 bytes
 .../PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt  |   Bin 0 -> 642 bytes
 .../certs/InvalidIDPwithindirectCRLTest23EE.crt    |   Bin 0 -> 654 bytes
 .../certs/InvalidIDPwithindirectCRLTest26EE.crt    |   Bin 0 -> 743 bytes
 .../certs/InvalidLongSerialNumberTest18EE.crt      |   Bin 0 -> 677 bytes
 .../certs/InvalidMappingFromanyPolicyTest7EE.crt   |   Bin 0 -> 665 bytes
 .../certs/InvalidMappingToanyPolicyTest8EE.crt     |   Bin 0 -> 655 bytes
 .../data/PKITS/certs/InvalidMissingCRLTest1EE.crt  |   Bin 0 -> 638 bytes
 .../InvalidMissingbasicConstraintsTest1EE.crt      |   Bin 0 -> 669 bytes
 .../certs/InvalidNameChainingOrderTest2EE.crt      |   Bin 0 -> 728 bytes
 .../PKITS/certs/InvalidNameChainingTest1EE.crt     |   Bin 0 -> 643 bytes
 .../certs/InvalidNegativeSerialNumberTest15EE.crt  |   Bin 0 -> 666 bytes
 .../certs/InvalidOldCRLnextUpdateTest11EE.crt      |   Bin 0 -> 658 bytes
 .../PKITS/certs/InvalidPolicyMappingTest10EE.crt   |   Bin 0 -> 667 bytes
 .../PKITS/certs/InvalidPolicyMappingTest2EE.crt    |   Bin 0 -> 647 bytes
 .../PKITS/certs/InvalidPolicyMappingTest4EE.crt    |   Bin 0 -> 657 bytes
 .../certs/InvalidRFC822nameConstraintsTest22EE.crt |   Bin 0 -> 711 bytes
 .../certs/InvalidRFC822nameConstraintsTest24EE.crt |   Bin 0 -> 722 bytes
 .../certs/InvalidRFC822nameConstraintsTest26EE.crt |   Bin 0 -> 711 bytes
 .../data/PKITS/certs/InvalidRevokedCATest2EE.crt   |   Bin 0 -> 638 bytes
 .../data/PKITS/certs/InvalidRevokedEETest3EE.crt   |   Bin 0 -> 632 bytes
 .../InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt  |   Bin 0 -> 648 bytes
 .../InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt   |   Bin 0 -> 673 bytes
 ...validSelfIssuedinhibitPolicyMappingTest10EE.crt |   Bin 0 -> 681 bytes
 ...validSelfIssuedinhibitPolicyMappingTest11EE.crt |   Bin 0 -> 681 bytes
 ...nvalidSelfIssuedinhibitPolicyMappingTest8EE.crt |   Bin 0 -> 683 bytes
 ...nvalidSelfIssuedinhibitPolicyMappingTest9EE.crt |   Bin 0 -> 683 bytes
 .../InvalidSelfIssuedpathLenConstraintTest16EE.crt |   Bin 0 -> 673 bytes
 ...validSelfIssuedrequireExplicitPolicyTest7EE.crt |   Bin 0 -> 654 bytes
 ...validSelfIssuedrequireExplicitPolicyTest8EE.crt |   Bin 0 -> 654 bytes
 ...nvalidSeparateCertificateandCRLKeysTest20EE.crt |   Bin 0 -> 689 bytes
 ...nvalidSeparateCertificateandCRLKeysTest21EE.crt |   Bin 0 -> 689 bytes
 .../certs/InvalidURInameConstraintsTest35EE.crt    |   Bin 0 -> 716 bytes
 .../certs/InvalidURInameConstraintsTest37EE.crt    |   Bin 0 -> 716 bytes
 .../InvalidUnknownCRLEntryExtensionTest8EE.crt     |   Bin 0 -> 675 bytes
 .../certs/InvalidUnknownCRLExtensionTest10EE.crt   |   Bin 0 -> 664 bytes
 .../certs/InvalidUnknownCRLExtensionTest9EE.crt    |   Bin 0 -> 663 bytes
 ...dUnknownCriticalCertificateExtensionTest2EE.crt |   Bin 0 -> 683 bytes
 .../data/PKITS/certs/InvalidWrongCRLTest6EE.crt    |   Bin 0 -> 639 bytes
 .../data/PKITS/certs/InvalidcAFalseTest2EE.crt     |   Bin 0 -> 663 bytes
 .../data/PKITS/certs/InvalidcAFalseTest3EE.crt     |   Bin 0 -> 667 bytes
 .../data/PKITS/certs/InvalidcRLIssuerTest27EE.crt  |   Bin 0 -> 723 bytes
 .../data/PKITS/certs/InvalidcRLIssuerTest31EE.crt  |   Bin 0 -> 855 bytes
 .../data/PKITS/certs/InvalidcRLIssuerTest32EE.crt  |   Bin 0 -> 855 bytes
 .../data/PKITS/certs/InvalidcRLIssuerTest34EE.crt  |   Bin 0 -> 768 bytes
 .../data/PKITS/certs/InvalidcRLIssuerTest35EE.crt  |   Bin 0 -> 847 bytes
 .../InvaliddeltaCRLIndicatorNoBaseTest1EE.crt      |   Bin 0 -> 671 bytes
 .../data/PKITS/certs/InvaliddeltaCRLTest10EE.crt   |   Bin 0 -> 813 bytes
 .../data/PKITS/certs/InvaliddeltaCRLTest3EE.crt    |   Bin 0 -> 812 bytes
 .../data/PKITS/certs/InvaliddeltaCRLTest4EE.crt    |   Bin 0 -> 812 bytes
 .../data/PKITS/certs/InvaliddeltaCRLTest6EE.crt    |   Bin 0 -> 812 bytes
 .../data/PKITS/certs/InvaliddeltaCRLTest9EE.crt    |   Bin 0 -> 812 bytes
 .../certs/InvaliddistributionPointTest2EE.crt      |   Bin 0 -> 793 bytes
 .../certs/InvaliddistributionPointTest3EE.crt      |   Bin 0 -> 793 bytes
 .../certs/InvaliddistributionPointTest6EE.crt      |   Bin 0 -> 713 bytes
 .../certs/InvaliddistributionPointTest8EE.crt      |   Bin 0 -> 752 bytes
 .../certs/InvaliddistributionPointTest9EE.crt      |   Bin 0 -> 656 bytes
 .../PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt |   Bin 0 -> 648 bytes
 .../PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt |   Bin 0 -> 652 bytes
 .../PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt |   Bin 0 -> 654 bytes
 .../PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt |   Bin 0 -> 655 bytes
 .../certs/InvalidinhibitPolicyMappingTest1EE.crt   |   Bin 0 -> 679 bytes
 .../certs/InvalidinhibitPolicyMappingTest3EE.crt   |   Bin 0 -> 672 bytes
 .../certs/InvalidinhibitPolicyMappingTest5EE.crt   |   Bin 0 -> 671 bytes
 .../certs/InvalidinhibitPolicyMappingTest6EE.crt   |   Bin 0 -> 676 bytes
 .../InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt |   Bin 0 -> 683 bytes
 ...alidkeyUsageCriticalkeyCertSignFalseTest1EE.crt |   Bin 0 -> 691 bytes
 ...validkeyUsageNotCriticalcRLSignFalseTest5EE.crt |   Bin 0 -> 691 bytes
 ...dkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt |   Bin 0 -> 692 bytes
 .../InvalidonlyContainsAttributeCertsTest14EE.crt  |   Bin 0 -> 674 bytes
 .../certs/InvalidonlyContainsCACertsTest12EE.crt   |   Bin 0 -> 660 bytes
 .../certs/InvalidonlyContainsUserCertsTest11EE.crt |   Bin 0 -> 681 bytes
 .../PKITS/certs/InvalidonlySomeReasonsTest15EE.crt |   Bin 0 -> 653 bytes
 .../PKITS/certs/InvalidonlySomeReasonsTest16EE.crt |   Bin 0 -> 653 bytes
 .../PKITS/certs/InvalidonlySomeReasonsTest17EE.crt |   Bin 0 -> 653 bytes
 .../PKITS/certs/InvalidonlySomeReasonsTest20EE.crt |   Bin 0 -> 872 bytes
 .../PKITS/certs/InvalidonlySomeReasonsTest21EE.crt |   Bin 0 -> 872 bytes
 .../certs/InvalidpathLenConstraintTest10EE.crt     |   Bin 0 -> 682 bytes
 .../certs/InvalidpathLenConstraintTest11EE.crt     |   Bin 0 -> 669 bytes
 .../certs/InvalidpathLenConstraintTest12EE.crt     |   Bin 0 -> 686 bytes
 .../certs/InvalidpathLenConstraintTest5EE.crt      |   Bin 0 -> 659 bytes
 .../certs/InvalidpathLenConstraintTest6EE.crt      |   Bin 0 -> 676 bytes
 .../certs/InvalidpathLenConstraintTest9EE.crt      |   Bin 0 -> 664 bytes
 .../certs/Invalidpre2000CRLnextUpdateTest12EE.crt  |   Bin 0 -> 666 bytes
 .../Invalidpre2000UTCEEnotAfterDateTest7EE.crt     |   Bin 0 -> 655 bytes
 .../certs/InvalidrequireExplicitPolicyTest3EE.crt  |   Bin 0 -> 648 bytes
 .../certs/InvalidrequireExplicitPolicyTest5EE.crt  |   Bin 0 -> 654 bytes
 .../data/PKITS/certs/LongSerialNumberCACert.crt    |   Bin 0 -> 639 bytes
 .../test/data/PKITS/certs/Mapping1to2CACert.crt    |   Bin 0 -> 689 bytes
 .../PKITS/certs/MappingFromanyPolicyCACert.crt     |   Bin 0 -> 690 bytes
 .../data/PKITS/certs/MappingToanyPolicyCACert.crt  |   Bin 0 -> 694 bytes
 .../PKITS/certs/MissingbasicConstraintsCACert.crt  |   Bin 0 -> 628 bytes
 .../test/data/PKITS/certs/NameOrderingCACert.crt   |   Bin 0 -> 709 bytes
 .../PKITS/certs/NegativeSerialNumberCACert.crt     |   Bin 0 -> 643 bytes
 .../test/data/PKITS/certs/NoCRLCACert.crt          |   Bin 0 -> 627 bytes
 .../test/data/PKITS/certs/NoPoliciesCACert.crt     |   Bin 0 -> 607 bytes
 .../certs/NoissuingDistributionPointCACert.crt     |   Bin 0 -> 648 bytes
 .../data/PKITS/certs/OldCRLnextUpdateCACert.crt    |   Bin 0 -> 639 bytes
 .../PKITS/certs/OverlappingPoliciesTest6EE.crt     |   Bin 0 -> 677 bytes
 .../test/data/PKITS/certs/P12Mapping1to3CACert.crt |   Bin 0 -> 707 bytes
 .../data/PKITS/certs/P12Mapping1to3subCACert.crt   |   Bin 0 -> 729 bytes
 .../PKITS/certs/P12Mapping1to3subsubCACert.crt     |   Bin 0 -> 709 bytes
 .../data/PKITS/certs/P1Mapping1to234CACert.crt     |   Bin 0 -> 746 bytes
 .../data/PKITS/certs/P1Mapping1to234subCACert.crt  |   Bin 0 -> 731 bytes
 .../PKITS/certs/P1anyPolicyMapping1to2CACert.crt   |   Bin 0 -> 1058 bytes
 .../PKITS/certs/PanyPolicyMapping1to2CACert.crt    |   Bin 0 -> 694 bytes
 .../test/data/PKITS/certs/PoliciesP1234CACert.crt  |   Bin 0 -> 693 bytes
 .../PKITS/certs/PoliciesP1234subCAP123Cert.crt     |   Bin 0 -> 677 bytes
 .../certs/PoliciesP1234subsubCAP123P12Cert.crt     |   Bin 0 -> 676 bytes
 .../test/data/PKITS/certs/PoliciesP123CACert.crt   |   Bin 0 -> 678 bytes
 .../data/PKITS/certs/PoliciesP123subCAP12Cert.crt  |   Bin 0 -> 660 bytes
 .../PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt  |   Bin 0 -> 655 bytes
 .../PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt  |   Bin 0 -> 655 bytes
 .../certs/PoliciesP123subsubsubCAP12P2P1Cert.crt   |   Bin 0 -> 665 bytes
 .../test/data/PKITS/certs/PoliciesP12CACert.crt    |   Bin 0 -> 663 bytes
 .../data/PKITS/certs/PoliciesP12subCAP1Cert.crt    |   Bin 0 -> 641 bytes
 .../PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt    |   Bin 0 -> 651 bytes
 .../test/data/PKITS/certs/PoliciesP2subCA2Cert.crt |   Bin 0 -> 647 bytes
 .../test/data/PKITS/certs/PoliciesP2subCACert.crt  |   Bin 0 -> 630 bytes
 .../test/data/PKITS/certs/PoliciesP3CACert.crt     |   Bin 0 -> 648 bytes
 .../certs/RFC3280MandatoryAttributeTypesCACert.crt |   Bin 0 -> 709 bytes
 .../certs/RFC3280OptionalAttributeTypesCACert.crt  |   Bin 0 -> 721 bytes
 .../test/data/PKITS/certs/RevokedsubCACert.crt     |   Bin 0 -> 626 bytes
 ...lloverfromPrintableStringtoUTF8StringCACert.crt |   Bin 0 -> 664 bytes
 ...arateCertificateandCRLKeysCA2CRLSigningCert.crt |   Bin 0 -> 638 bytes
 ...ficateandCRLKeysCA2CertificateSigningCACert.crt |   Bin 0 -> 655 bytes
 ...SeparateCertificateandCRLKeysCRLSigningCert.crt |   Bin 0 -> 638 bytes
 ...rtificateandCRLKeysCertificateSigningCACert.crt |   Bin 0 -> 655 bytes
 .../PKITS/certs/TrustAnchorRootCertificate.crt     |   Bin 0 -> 572 bytes
 .../test/data/PKITS/certs/TwoCRLsCACert.crt        |   Bin 0 -> 629 bytes
 .../test/data/PKITS/certs/UIDCACert.crt            |   Bin 0 -> 629 bytes
 .../certs/UTF8StringCaseInsensitiveMatchCACert.crt |   Bin 0 -> 654 bytes
 .../PKITS/certs/UTF8StringEncodedNamesCACert.crt   |   Bin 0 -> 631 bytes
 .../PKITS/certs/UnknownCRLEntryExtensionCACert.crt |   Bin 0 -> 648 bytes
 .../data/PKITS/certs/UnknownCRLExtensionCACert.crt |   Bin 0 -> 642 bytes
 .../PKITS/certs/UserNoticeQualifierTest15EE.crt    |   Bin 0 -> 755 bytes
 .../PKITS/certs/UserNoticeQualifierTest16EE.crt    |   Bin 0 -> 874 bytes
 .../PKITS/certs/UserNoticeQualifierTest17EE.crt    |   Bin 0 -> 743 bytes
 .../PKITS/certs/UserNoticeQualifierTest18EE.crt    |   Bin 0 -> 969 bytes
 .../PKITS/certs/UserNoticeQualifierTest19EE.crt    |   Bin 0 -> 992 bytes
 .../ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt   |   Bin 0 -> 685 bytes
 .../ValidBasicSelfIssuedNewWithOldTest3EE.crt      |   Bin 0 -> 674 bytes
 .../ValidBasicSelfIssuedNewWithOldTest4EE.crt      |   Bin 0 -> 674 bytes
 .../ValidBasicSelfIssuedOldWithNewTest1EE.crt      |   Bin 0 -> 674 bytes
 .../PKITS/certs/ValidCertificatePathTest1EE.crt    |   Bin 0 -> 622 bytes
 .../certs/ValidDNSnameConstraintsTest30EE.crt      |   Bin 0 -> 705 bytes
 .../certs/ValidDNSnameConstraintsTest32EE.crt      |   Bin 0 -> 705 bytes
 .../ValidDNandRFC822nameConstraintsTest27EE.crt    |   Bin 0 -> 773 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest11EE.crt |   Bin 0 -> 714 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest14EE.crt |   Bin 0 -> 660 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest18EE.crt |   Bin 0 -> 661 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest19EE.crt |   Bin 0 -> 685 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest1EE.crt  |   Bin 0 -> 684 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest4EE.crt  |   Bin 0 -> 744 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest5EE.crt  |   Bin 0 -> 829 bytes
 .../PKITS/certs/ValidDNnameConstraintsTest6EE.crt  |   Bin 0 -> 684 bytes
 .../certs/ValidDSAParameterInheritanceTest5EE.crt  |   Bin 0 -> 566 bytes
 .../data/PKITS/certs/ValidDSASignaturesTest4EE.crt |   Bin 0 -> 826 bytes
 .../ValidGeneralizedTimeCRLnextUpdateTest13EE.crt  |   Bin 0 -> 678 bytes
 .../ValidGeneralizedTimenotAfterDateTest8EE.crt    |   Bin 0 -> 654 bytes
 .../ValidGeneralizedTimenotBeforeDateTest4EE.crt   |   Bin 0 -> 655 bytes
 .../certs/ValidIDPwithindirectCRLTest22EE.crt      |   Bin 0 -> 652 bytes
 .../certs/ValidIDPwithindirectCRLTest24EE.crt      |   Bin 0 -> 740 bytes
 .../certs/ValidIDPwithindirectCRLTest25EE.crt      |   Bin 0 -> 740 bytes
 .../PKITS/certs/ValidLongSerialNumberTest16EE.crt  |   Bin 0 -> 675 bytes
 .../PKITS/certs/ValidLongSerialNumberTest17EE.crt  |   Bin 0 -> 675 bytes
 .../ValidNameChainingCapitalizationTest5EE.crt     |   Bin 0 -> 651 bytes
 .../certs/ValidNameChainingWhitespaceTest3EE.crt   |   Bin 0 -> 652 bytes
 .../certs/ValidNameChainingWhitespaceTest4EE.crt   |   Bin 0 -> 653 bytes
 .../test/data/PKITS/certs/ValidNameUIDsTest6EE.crt |   Bin 0 -> 630 bytes
 .../certs/ValidNegativeSerialNumberTest14EE.crt    |   Bin 0 -> 665 bytes
 .../ValidNoissuingDistributionPointTest10EE.crt    |   Bin 0 -> 793 bytes
 .../PKITS/certs/ValidPolicyMappingTest11EE.crt     |   Bin 0 -> 665 bytes
 .../PKITS/certs/ValidPolicyMappingTest12EE.crt     |   Bin 0 -> 1068 bytes
 .../PKITS/certs/ValidPolicyMappingTest13EE.crt     |   Bin 0 -> 658 bytes
 .../PKITS/certs/ValidPolicyMappingTest14EE.crt     |   Bin 0 -> 658 bytes
 .../data/PKITS/certs/ValidPolicyMappingTest1EE.crt |   Bin 0 -> 645 bytes
 .../data/PKITS/certs/ValidPolicyMappingTest3EE.crt |   Bin 0 -> 655 bytes
 .../data/PKITS/certs/ValidPolicyMappingTest5EE.crt |   Bin 0 -> 653 bytes
 .../data/PKITS/certs/ValidPolicyMappingTest6EE.crt |   Bin 0 -> 653 bytes
 .../data/PKITS/certs/ValidPolicyMappingTest9EE.crt |   Bin 0 -> 656 bytes
 .../ValidRFC3280MandatoryAttributeTypesTest7EE.crt |   Bin 0 -> 740 bytes
 .../ValidRFC3280OptionalAttributeTypesTest8EE.crt  |   Bin 0 -> 751 bytes
 .../certs/ValidRFC822nameConstraintsTest21EE.crt   |   Bin 0 -> 720 bytes
 .../certs/ValidRFC822nameConstraintsTest23EE.crt   |   Bin 0 -> 709 bytes
 .../certs/ValidRFC822nameConstraintsTest25EE.crt   |   Bin 0 -> 720 bytes
 ...overfromPrintableStringtoUTF8StringTest10EE.crt |   Bin 0 -> 694 bytes
 .../ValidSelfIssuedinhibitAnyPolicyTest7EE.crt     |   Bin 0 -> 668 bytes
 .../ValidSelfIssuedinhibitAnyPolicyTest9EE.crt     |   Bin 0 -> 668 bytes
 .../ValidSelfIssuedinhibitPolicyMappingTest7EE.crt |   Bin 0 -> 678 bytes
 .../ValidSelfIssuedpathLenConstraintTest15EE.crt   |   Bin 0 -> 667 bytes
 .../ValidSelfIssuedpathLenConstraintTest17EE.crt   |   Bin 0 -> 670 bytes
 ...ValidSelfIssuedrequireExplicitPolicyTest6EE.crt |   Bin 0 -> 649 bytes
 .../ValidSeparateCertificateandCRLKeysTest19EE.crt |   Bin 0 -> 687 bytes
 .../test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt  |   Bin 0 -> 635 bytes
 .../certs/ValidURInameConstraintsTest34EE.crt      |   Bin 0 -> 723 bytes
 .../certs/ValidURInameConstraintsTest36EE.crt      |   Bin 0 -> 726 bytes
 ...ValidUTF8StringCaseInsensitiveMatchTest11EE.crt |   Bin 0 -> 691 bytes
 .../certs/ValidUTF8StringEncodedNamesTest9EE.crt   |   Bin 0 -> 653 bytes
 ...knownNotCriticalCertificateExtensionTest1EE.crt |   Bin 0 -> 681 bytes
 .../ValidbasicConstraintsNotCriticalTest4EE.crt    |   Bin 0 -> 677 bytes
 .../data/PKITS/certs/ValidcRLIssuerTest28EE.crt    |   Bin 0 -> 873 bytes
 .../data/PKITS/certs/ValidcRLIssuerTest29EE.crt    |   Bin 0 -> 788 bytes
 .../data/PKITS/certs/ValidcRLIssuerTest30EE.crt    |   Bin 0 -> 873 bytes
 .../data/PKITS/certs/ValidcRLIssuerTest33EE.crt    |   Bin 0 -> 853 bytes
 .../test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt |   Bin 0 -> 810 bytes
 .../test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt |   Bin 0 -> 810 bytes
 .../test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt |   Bin 0 -> 810 bytes
 .../test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt |   Bin 0 -> 810 bytes
 .../PKITS/certs/ValiddistributionPointTest1EE.crt  |   Bin 0 -> 791 bytes
 .../PKITS/certs/ValiddistributionPointTest4EE.crt  |   Bin 0 -> 711 bytes
 .../PKITS/certs/ValiddistributionPointTest5EE.crt  |   Bin 0 -> 711 bytes
 .../PKITS/certs/ValiddistributionPointTest7EE.crt  |   Bin 0 -> 791 bytes
 .../PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt   |   Bin 0 -> 660 bytes
 .../certs/ValidinhibitPolicyMappingTest2EE.crt     |   Bin 0 -> 667 bytes
 .../certs/ValidinhibitPolicyMappingTest4EE.crt     |   Bin 0 -> 670 bytes
 .../certs/ValidkeyUsageNotCriticalTest3EE.crt      |   Bin 0 -> 661 bytes
 .../certs/ValidonlyContainsCACertsTest13EE.crt     |   Bin 0 -> 675 bytes
 .../PKITS/certs/ValidonlySomeReasonsTest18EE.crt   |   Bin 0 -> 759 bytes
 .../PKITS/certs/ValidonlySomeReasonsTest19EE.crt   |   Bin 0 -> 870 bytes
 .../PKITS/certs/ValidpathLenConstraintTest13EE.crt |   Bin 0 -> 667 bytes
 .../PKITS/certs/ValidpathLenConstraintTest14EE.crt |   Bin 0 -> 684 bytes
 .../PKITS/certs/ValidpathLenConstraintTest7EE.crt  |   Bin 0 -> 654 bytes
 .../PKITS/certs/ValidpathLenConstraintTest8EE.crt  |   Bin 0 -> 671 bytes
 .../certs/Validpre2000UTCnotBeforeDateTest3EE.crt  |   Bin 0 -> 649 bytes
 .../certs/ValidrequireExplicitPolicyTest1EE.crt    |   Bin 0 -> 647 bytes
 .../certs/ValidrequireExplicitPolicyTest2EE.crt    |   Bin 0 -> 646 bytes
 .../certs/ValidrequireExplicitPolicyTest4EE.crt    |   Bin 0 -> 671 bytes
 .../test/data/PKITS/certs/WrongCRLCACert.crt       |   Bin 0 -> 630 bytes
 .../test/data/PKITS/certs/anyPolicyCACert.crt      |   Bin 0 -> 640 bytes
 .../basicConstraintsCriticalcAFalseCACert.crt      |   Bin 0 -> 652 bytes
 .../certs/basicConstraintsNotCriticalCACert.crt    |   Bin 0 -> 647 bytes
 .../basicConstraintsNotCriticalcAFalseCACert.crt   |   Bin 0 -> 653 bytes
 .../test/data/PKITS/certs/deltaCRLCA1Cert.crt      |   Bin 0 -> 630 bytes
 .../test/data/PKITS/certs/deltaCRLCA2Cert.crt      |   Bin 0 -> 630 bytes
 .../test/data/PKITS/certs/deltaCRLCA3Cert.crt      |   Bin 0 -> 630 bytes
 .../PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt  |   Bin 0 -> 646 bytes
 .../data/PKITS/certs/distributionPoint1CACert.crt  |   Bin 0 -> 639 bytes
 .../data/PKITS/certs/distributionPoint2CACert.crt  |   Bin 0 -> 639 bytes
 .../test/data/PKITS/certs/indirectCRLCA1Cert.crt   |   Bin 0 -> 633 bytes
 .../test/data/PKITS/certs/indirectCRLCA2Cert.crt   |   Bin 0 -> 633 bytes
 .../test/data/PKITS/certs/indirectCRLCA3Cert.crt   |   Bin 0 -> 633 bytes
 .../PKITS/certs/indirectCRLCA3cRLIssuerCert.crt    |   Bin 0 -> 734 bytes
 .../test/data/PKITS/certs/indirectCRLCA4Cert.crt   |   Bin 0 -> 633 bytes
 .../PKITS/certs/indirectCRLCA4cRLIssuerCert.crt    |   Bin 0 -> 861 bytes
 .../test/data/PKITS/certs/indirectCRLCA5Cert.crt   |   Bin 0 -> 633 bytes
 .../test/data/PKITS/certs/indirectCRLCA6Cert.crt   |   Bin 0 -> 633 bytes
 .../data/PKITS/certs/inhibitAnyPolicy0CACert.crt   |   Bin 0 -> 669 bytes
 .../data/PKITS/certs/inhibitAnyPolicy1CACert.crt   |   Bin 0 -> 669 bytes
 .../certs/inhibitAnyPolicy1SelfIssuedCACert.crt    |   Bin 0 -> 646 bytes
 .../inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt      |   Bin 0 -> 648 bytes
 .../PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt    |   Bin 0 -> 644 bytes
 .../PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt    |   Bin 0 -> 644 bytes
 .../PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt |   Bin 0 -> 670 bytes
 .../PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt |   Bin 0 -> 651 bytes
 .../data/PKITS/certs/inhibitAnyPolicy5CACert.crt   |   Bin 0 -> 669 bytes
 .../PKITS/certs/inhibitAnyPolicy5subCACert.crt     |   Bin 0 -> 666 bytes
 .../PKITS/certs/inhibitAnyPolicy5subsubCACert.crt  |   Bin 0 -> 655 bytes
 .../data/PKITS/certs/inhibitAnyPolicyTest3EE.crt   |   Bin 0 -> 650 bytes
 .../PKITS/certs/inhibitPolicyMapping0CACert.crt    |   Bin 0 -> 664 bytes
 .../PKITS/certs/inhibitPolicyMapping0subCACert.crt |   Bin 0 -> 699 bytes
 .../PKITS/certs/inhibitPolicyMapping1P12CACert.crt |   Bin 0 -> 682 bytes
 .../certs/inhibitPolicyMapping1P12subCACert.crt    |   Bin 0 -> 747 bytes
 .../inhibitPolicyMapping1P12subCAIPM5Cert.crt      |   Bin 0 -> 702 bytes
 .../certs/inhibitPolicyMapping1P12subsubCACert.crt |   Bin 0 -> 727 bytes
 .../inhibitPolicyMapping1P12subsubCAIPM5Cert.crt   |   Bin 0 -> 735 bytes
 .../PKITS/certs/inhibitPolicyMapping1P1CACert.crt  |   Bin 0 -> 667 bytes
 .../inhibitPolicyMapping1P1SelfIssuedCACert.crt    |   Bin 0 -> 660 bytes
 .../inhibitPolicyMapping1P1SelfIssuedsubCACert.crt |   Bin 0 -> 708 bytes
 .../certs/inhibitPolicyMapping1P1subCACert.crt     |   Bin 0 -> 705 bytes
 .../certs/inhibitPolicyMapping1P1subsubCACert.crt  |   Bin 0 -> 711 bytes
 .../PKITS/certs/inhibitPolicyMapping5CACert.crt    |   Bin 0 -> 664 bytes
 .../PKITS/certs/inhibitPolicyMapping5subCACert.crt |   Bin 0 -> 676 bytes
 .../certs/inhibitPolicyMapping5subsubCACert.crt    |   Bin 0 -> 663 bytes
 .../certs/inhibitPolicyMapping5subsubsubCACert.crt |   Bin 0 -> 711 bytes
 .../certs/keyUsageCriticalcRLSignFalseCACert.crt   |   Bin 0 -> 652 bytes
 .../keyUsageCriticalkeyCertSignFalseCACert.crt     |   Bin 0 -> 656 bytes
 .../data/PKITS/certs/keyUsageNotCriticalCACert.crt |   Bin 0 -> 639 bytes
 .../keyUsageNotCriticalcRLSignFalseCACert.crt      |   Bin 0 -> 653 bytes
 .../keyUsageNotCriticalkeyCertSignFalseCACert.crt  |   Bin 0 -> 657 bytes
 .../data/PKITS/certs/nameConstraintsDN1CACert.crt  |   Bin 0 -> 733 bytes
 .../certs/nameConstraintsDN1SelfIssuedCACert.crt   |   Bin 0 -> 650 bytes
 .../PKITS/certs/nameConstraintsDN1subCA1Cert.crt   |   Bin 0 -> 803 bytes
 .../PKITS/certs/nameConstraintsDN1subCA2Cert.crt   |   Bin 0 -> 775 bytes
 .../PKITS/certs/nameConstraintsDN1subCA3Cert.crt   |   Bin 0 -> 724 bytes
 .../data/PKITS/certs/nameConstraintsDN2CACert.crt  |   Bin 0 -> 814 bytes
 .../data/PKITS/certs/nameConstraintsDN3CACert.crt  |   Bin 0 -> 732 bytes
 .../PKITS/certs/nameConstraintsDN3subCA1Cert.crt   |   Bin 0 -> 746 bytes
 .../PKITS/certs/nameConstraintsDN3subCA2Cert.crt   |   Bin 0 -> 719 bytes
 .../data/PKITS/certs/nameConstraintsDN4CACert.crt  |   Bin 0 -> 812 bytes
 .../data/PKITS/certs/nameConstraintsDN5CACert.crt  |   Bin 0 -> 842 bytes
 .../data/PKITS/certs/nameConstraintsDNS1CACert.crt |   Bin 0 -> 683 bytes
 .../data/PKITS/certs/nameConstraintsDNS2CACert.crt |   Bin 0 -> 686 bytes
 .../PKITS/certs/nameConstraintsRFC822CA1Cert.crt   |   Bin 0 -> 687 bytes
 .../PKITS/certs/nameConstraintsRFC822CA2Cert.crt   |   Bin 0 -> 686 bytes
 .../PKITS/certs/nameConstraintsRFC822CA3Cert.crt   |   Bin 0 -> 686 bytes
 .../data/PKITS/certs/nameConstraintsURI1CACert.crt |   Bin 0 -> 684 bytes
 .../data/PKITS/certs/nameConstraintsURI2CACert.crt |   Bin 0 -> 686 bytes
 .../certs/onlyContainsAttributeCertsCACert.crt     |   Bin 0 -> 647 bytes
 .../data/PKITS/certs/onlyContainsCACertsCACert.crt |   Bin 0 -> 640 bytes
 .../PKITS/certs/onlyContainsUserCertsCACert.crt    |   Bin 0 -> 642 bytes
 .../data/PKITS/certs/onlySomeReasonsCA1Cert.crt    |   Bin 0 -> 637 bytes
 .../data/PKITS/certs/onlySomeReasonsCA2Cert.crt    |   Bin 0 -> 637 bytes
 .../data/PKITS/certs/onlySomeReasonsCA3Cert.crt    |   Bin 0 -> 637 bytes
 .../data/PKITS/certs/onlySomeReasonsCA4Cert.crt    |   Bin 0 -> 637 bytes
 .../data/PKITS/certs/pathLenConstraint0CACert.crt  |   Bin 0 -> 642 bytes
 .../certs/pathLenConstraint0SelfIssuedCACert.crt   |   Bin 0 -> 648 bytes
 .../PKITS/certs/pathLenConstraint0subCA2Cert.crt   |   Bin 0 -> 652 bytes
 .../PKITS/certs/pathLenConstraint0subCACert.crt    |   Bin 0 -> 651 bytes
 .../data/PKITS/certs/pathLenConstraint1CACert.crt  |   Bin 0 -> 642 bytes
 .../certs/pathLenConstraint1SelfIssuedCACert.crt   |   Bin 0 -> 648 bytes
 .../pathLenConstraint1SelfIssuedsubCACert.crt      |   Bin 0 -> 654 bytes
 .../PKITS/certs/pathLenConstraint1subCACert.crt    |   Bin 0 -> 651 bytes
 .../data/PKITS/certs/pathLenConstraint6CACert.crt  |   Bin 0 -> 642 bytes
 .../PKITS/certs/pathLenConstraint6subCA0Cert.crt   |   Bin 0 -> 655 bytes
 .../PKITS/certs/pathLenConstraint6subCA1Cert.crt   |   Bin 0 -> 655 bytes
 .../PKITS/certs/pathLenConstraint6subCA4Cert.crt   |   Bin 0 -> 655 bytes
 .../certs/pathLenConstraint6subsubCA00Cert.crt     |   Bin 0 -> 663 bytes
 .../certs/pathLenConstraint6subsubCA11Cert.crt     |   Bin 0 -> 663 bytes
 .../certs/pathLenConstraint6subsubCA41Cert.crt     |   Bin 0 -> 663 bytes
 .../certs/pathLenConstraint6subsubsubCA11XCert.crt |   Bin 0 -> 668 bytes
 .../certs/pathLenConstraint6subsubsubCA41XCert.crt |   Bin 0 -> 668 bytes
 .../PKITS/certs/pre2000CRLnextUpdateCACert.crt     |   Bin 0 -> 643 bytes
 .../PKITS/certs/requireExplicitPolicy0CACert.crt   |   Bin 0 -> 662 bytes
 .../certs/requireExplicitPolicy0subCACert.crt      |   Bin 0 -> 659 bytes
 .../certs/requireExplicitPolicy0subsubCACert.crt   |   Bin 0 -> 665 bytes
 .../requireExplicitPolicy0subsubsubCACert.crt      |   Bin 0 -> 671 bytes
 .../PKITS/certs/requireExplicitPolicy10CACert.crt  |   Bin 0 -> 663 bytes
 .../certs/requireExplicitPolicy10subCACert.crt     |   Bin 0 -> 661 bytes
 .../certs/requireExplicitPolicy10subsubCACert.crt  |   Bin 0 -> 667 bytes
 .../requireExplicitPolicy10subsubsubCACert.crt     |   Bin 0 -> 673 bytes
 .../PKITS/certs/requireExplicitPolicy2CACert.crt   |   Bin 0 -> 662 bytes
 .../requireExplicitPolicy2SelfIssuedCACert.crt     |   Bin 0 -> 656 bytes
 .../requireExplicitPolicy2SelfIssuedsubCACert.crt  |   Bin 0 -> 662 bytes
 .../certs/requireExplicitPolicy2subCACert.crt      |   Bin 0 -> 659 bytes
 .../PKITS/certs/requireExplicitPolicy4CACert.crt   |   Bin 0 -> 662 bytes
 .../certs/requireExplicitPolicy4subCACert.crt      |   Bin 0 -> 659 bytes
 .../certs/requireExplicitPolicy4subsubCACert.crt   |   Bin 0 -> 665 bytes
 .../requireExplicitPolicy4subsubsubCACert.crt      |   Bin 0 -> 671 bytes
 .../PKITS/certs/requireExplicitPolicy5CACert.crt   |   Bin 0 -> 662 bytes
 .../certs/requireExplicitPolicy5subCACert.crt      |   Bin 0 -> 659 bytes
 .../certs/requireExplicitPolicy5subsubCACert.crt   |   Bin 0 -> 665 bytes
 .../requireExplicitPolicy5subsubsubCACert.crt      |   Bin 0 -> 671 bytes
 .../PKITS/certs/requireExplicitPolicy7CACert.crt   |   Bin 0 -> 662 bytes
 .../certs/requireExplicitPolicy7subCARE2Cert.crt   |   Bin 0 -> 681 bytes
 .../requireExplicitPolicy7subsubCARE2RE4Cert.crt   |   Bin 0 -> 693 bytes
 ...requireExplicitPolicy7subsubsubCARE2RE4Cert.crt |   Bin 0 -> 683 bytes
 .../test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl |   Bin 0 -> 330 bytes
 .../test/data/PKITS/crls/BadCRLSignatureCACRL.crl  |   Bin 0 -> 325 bytes
 .../test/data/PKITS/crls/BadSignedCACRL.crl        |   Bin 0 -> 318 bytes
 .../test/data/PKITS/crls/BadnotAfterDateCACRL.crl  |   Bin 0 -> 325 bytes
 .../test/data/PKITS/crls/BadnotBeforeDateCACRL.crl |   Bin 0 -> 326 bytes
 .../crls/BasicSelfIssuedCRLSigningKeyCACRL.crl     |   Bin 0 -> 377 bytes
 .../BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl     |   Bin 0 -> 479 bytes
 .../data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl |   Bin 0 -> 369 bytes
 .../data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl |   Bin 0 -> 369 bytes
 .../BasicSelfIssuedOldKeySelfIssuedCertCRL.crl     |   Bin 0 -> 462 bytes
 .../test/data/PKITS/crls/DSACACRL.crl              |   Bin 0 -> 219 bytes
 .../PKITS/crls/DSAParametersInheritedCACRL.crl     |   Bin 0 -> 241 bytes
 .../crls/GeneralizedTimeCRLnextUpdateCACRL.crl     |   Bin 0 -> 338 bytes
 .../test/data/PKITS/crls/GoodCACRL.crl             |   Bin 0 -> 382 bytes
 .../test/data/PKITS/crls/GoodsubCACRL.crl          |   Bin 0 -> 315 bytes
 .../crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl   |   Bin 0 -> 339 bytes
 .../test/data/PKITS/crls/LongSerialNumberCACRL.crl |   Bin 0 -> 381 bytes
 .../test/data/PKITS/crls/Mapping1to2CACRL.crl      |   Bin 0 -> 320 bytes
 .../data/PKITS/crls/MappingFromanyPolicyCACRL.crl  |   Bin 0 -> 330 bytes
 .../data/PKITS/crls/MappingToanyPolicyCACRL.crl    |   Bin 0 -> 328 bytes
 .../PKITS/crls/MissingbasicConstraintsCACRL.crl    |   Bin 0 -> 332 bytes
 .../test/data/PKITS/crls/NameOrderCACRL.crl        |   Bin 0 -> 396 bytes
 .../data/PKITS/crls/NegativeSerialNumberCACRL.crl  |   Bin 0 -> 366 bytes
 .../test/data/PKITS/crls/NoPoliciesCACRL.crl       |   Bin 0 -> 319 bytes
 .../PKITS/crls/NoissuingDistributionPointCACRL.crl |   Bin 0 -> 335 bytes
 .../test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl |   Bin 0 -> 326 bytes
 .../test/data/PKITS/crls/P12Mapping1to3CACRL.crl   |   Bin 0 -> 324 bytes
 .../data/PKITS/crls/P12Mapping1to3subCACRL.crl     |   Bin 0 -> 327 bytes
 .../data/PKITS/crls/P12Mapping1to3subsubCACRL.crl  |   Bin 0 -> 330 bytes
 .../test/data/PKITS/crls/P1Mapping1to234CACRL.crl  |   Bin 0 -> 325 bytes
 .../data/PKITS/crls/P1Mapping1to234subCACRL.crl    |   Bin 0 -> 328 bytes
 .../PKITS/crls/P1anyPolicyMapping1to2CACRL.crl     |   Bin 0 -> 332 bytes
 .../data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl |   Bin 0 -> 331 bytes
 .../test/data/PKITS/crls/PoliciesP1234CACRL.crl    |   Bin 0 -> 322 bytes
 .../data/PKITS/crls/PoliciesP1234subCAP123CRL.crl  |   Bin 0 -> 329 bytes
 .../PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl |   Bin 0 -> 335 bytes
 .../test/data/PKITS/crls/PoliciesP123CACRL.crl     |   Bin 0 -> 321 bytes
 .../data/PKITS/crls/PoliciesP123subCAP12CRL.crl    |   Bin 0 -> 327 bytes
 .../PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl    |   Bin 0 -> 332 bytes
 .../PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl     |   Bin 0 -> 332 bytes
 .../crls/PoliciesP123subsubsubCAP12P2P1CRL.crl     |   Bin 0 -> 337 bytes
 .../test/data/PKITS/crls/PoliciesP12CACRL.crl      |   Bin 0 -> 320 bytes
 .../test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl |   Bin 0 -> 325 bytes
 .../data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl |   Bin 0 -> 330 bytes
 .../test/data/PKITS/crls/PoliciesP2subCA2CRL.crl   |   Bin 0 -> 323 bytes
 .../test/data/PKITS/crls/PoliciesP2subCACRL.crl    |   Bin 0 -> 322 bytes
 .../test/data/PKITS/crls/PoliciesP3CACRL.crl       |   Bin 0 -> 319 bytes
 .../crls/RFC3280MandatoryAttributeTypesCACRL.crl   |   Bin 0 -> 396 bytes
 .../crls/RFC3280OptionalAttributeTypesCACRL.crl    |   Bin 0 -> 408 bytes
 .../test/data/PKITS/crls/RevokedsubCACRL.crl       |   Bin 0 -> 318 bytes
 ...olloverfromPrintableStringtoUTF8StringCACRL.crl |   Bin 0 -> 351 bytes
 .../crls/SeparateCertificateandCRLKeysCA2CRL.crl   |   Bin 0 -> 342 bytes
 .../crls/SeparateCertificateandCRLKeysCRL.crl      |   Bin 0 -> 378 bytes
 .../test/data/PKITS/crls/TrustAnchorRootCRL.crl    |   Bin 0 -> 353 bytes
 .../test/data/PKITS/crls/TwoCRLsCABadCRL.crl       |   Bin 0 -> 364 bytes
 .../test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl      |   Bin 0 -> 316 bytes
 .../test/data/PKITS/crls/UIDCACRL.crl              |   Bin 0 -> 311 bytes
 .../crls/UTF8StringCaseInsensitiveMatchCACRL.crl   |   Bin 0 -> 341 bytes
 .../PKITS/crls/UTF8StringEncodedNamesCACRL.crl     |   Bin 0 -> 318 bytes
 .../PKITS/crls/UnknownCRLEntryExtensionCACRL.crl   |   Bin 0 -> 392 bytes
 .../data/PKITS/crls/UnknownCRLExtensionCACRL.crl   |   Bin 0 -> 386 bytes
 .../test/data/PKITS/crls/WrongCRLCACRL.crl         |   Bin 0 -> 353 bytes
 .../test/data/PKITS/crls/anyPolicyCACRL.crl        |   Bin 0 -> 317 bytes
 .../crls/basicConstraintsCriticalcAFalseCACRL.crl  |   Bin 0 -> 342 bytes
 .../crls/basicConstraintsNotCriticalCACRL.crl      |   Bin 0 -> 337 bytes
 .../basicConstraintsNotCriticalcAFalseCACRL.crl    |   Bin 0 -> 346 bytes
 .../test/data/PKITS/crls/deltaCRLCA1CRL.crl        |   Bin 0 -> 509 bytes
 .../test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl   |   Bin 0 -> 472 bytes
 .../test/data/PKITS/crls/deltaCRLCA2CRL.crl        |   Bin 0 -> 441 bytes
 .../test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl   |   Bin 0 -> 368 bytes
 .../test/data/PKITS/crls/deltaCRLCA3CRL.crl        |   Bin 0 -> 404 bytes
 .../test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl   |   Bin 0 -> 332 bytes
 .../PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl    |   Bin 0 -> 348 bytes
 .../data/PKITS/crls/distributionPoint1CACRL.crl    |   Bin 0 -> 501 bytes
 .../data/PKITS/crls/distributionPoint2CACRL.crl    |   Bin 0 -> 419 bytes
 .../test/data/PKITS/crls/indirectCRLCA1CRL.crl     |   Bin 0 -> 373 bytes
 .../test/data/PKITS/crls/indirectCRLCA3CRL.crl     |   Bin 0 -> 427 bytes
 .../data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl |   Bin 0 -> 481 bytes
 .../data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl |   Bin 0 -> 481 bytes
 .../test/data/PKITS/crls/indirectCRLCA5CRL.crl     |   Bin 0 -> 1408 bytes
 .../data/PKITS/crls/inhibitAnyPolicy0CACRL.crl     |   Bin 0 -> 325 bytes
 .../data/PKITS/crls/inhibitAnyPolicy1CACRL.crl     |   Bin 0 -> 325 bytes
 .../data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl |   Bin 0 -> 329 bytes
 .../data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl |   Bin 0 -> 329 bytes
 .../PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl   |   Bin 0 -> 332 bytes
 .../PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl   |   Bin 0 -> 332 bytes
 .../data/PKITS/crls/inhibitAnyPolicy5CACRL.crl     |   Bin 0 -> 325 bytes
 .../data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl  |   Bin 0 -> 328 bytes
 .../PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl    |   Bin 0 -> 331 bytes
 .../data/PKITS/crls/inhibitPolicyMapping0CACRL.crl |   Bin 0 -> 329 bytes
 .../PKITS/crls/inhibitPolicyMapping0subCACRL.crl   |   Bin 0 -> 332 bytes
 .../PKITS/crls/inhibitPolicyMapping1P12CACRL.crl   |   Bin 0 -> 333 bytes
 .../crls/inhibitPolicyMapping1P12subCACRL.crl      |   Bin 0 -> 336 bytes
 .../crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl  |   Bin 0 -> 340 bytes
 .../crls/inhibitPolicyMapping1P12subsubCACRL.crl   |   Bin 0 -> 339 bytes
 .../inhibitPolicyMapping1P12subsubCAIPM5CRL.crl    |   Bin 0 -> 343 bytes
 .../PKITS/crls/inhibitPolicyMapping1P1CACRL.crl    |   Bin 0 -> 332 bytes
 .../PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl |   Bin 0 -> 335 bytes
 .../crls/inhibitPolicyMapping1P1subsubCACRL.crl    |   Bin 0 -> 338 bytes
 .../data/PKITS/crls/inhibitPolicyMapping5CACRL.crl |   Bin 0 -> 329 bytes
 .../PKITS/crls/inhibitPolicyMapping5subCACRL.crl   |   Bin 0 -> 332 bytes
 .../crls/inhibitPolicyMapping5subsubCACRL.crl      |   Bin 0 -> 335 bytes
 .../crls/inhibitPolicyMapping5subsubsubCACRL.crl   |   Bin 0 -> 338 bytes
 .../crls/keyUsageCriticalcRLSignFalseCACRL.crl     |   Bin 0 -> 339 bytes
 .../crls/keyUsageCriticalkeyCertSignFalseCACRL.crl |   Bin 0 -> 343 bytes
 .../data/PKITS/crls/keyUsageNotCriticalCACRL.crl   |   Bin 0 -> 329 bytes
 .../crls/keyUsageNotCriticalcRLSignFalseCACRL.crl  |   Bin 0 -> 343 bytes
 .../keyUsageNotCriticalkeyCertSignFalseCACRL.crl   |   Bin 0 -> 347 bytes
 .../data/PKITS/crls/nameConstraintsDN1CACRL.crl    |   Bin 0 -> 327 bytes
 .../PKITS/crls/nameConstraintsDN1subCA1CRL.crl     |   Bin 0 -> 359 bytes
 .../PKITS/crls/nameConstraintsDN1subCA2CRL.crl     |   Bin 0 -> 359 bytes
 .../PKITS/crls/nameConstraintsDN1subCA3CRL.crl     |   Bin 0 -> 359 bytes
 .../data/PKITS/crls/nameConstraintsDN2CACRL.crl    |   Bin 0 -> 327 bytes
 .../data/PKITS/crls/nameConstraintsDN3CACRL.crl    |   Bin 0 -> 327 bytes
 .../PKITS/crls/nameConstraintsDN3subCA1CRL.crl     |   Bin 0 -> 331 bytes
 .../PKITS/crls/nameConstraintsDN3subCA2CRL.crl     |   Bin 0 -> 331 bytes
 .../data/PKITS/crls/nameConstraintsDN4CACRL.crl    |   Bin 0 -> 327 bytes
 .../data/PKITS/crls/nameConstraintsDN5CACRL.crl    |   Bin 0 -> 327 bytes
 .../data/PKITS/crls/nameConstraintsDNS1CACRL.crl   |   Bin 0 -> 328 bytes
 .../data/PKITS/crls/nameConstraintsDNS2CACRL.crl   |   Bin 0 -> 328 bytes
 .../PKITS/crls/nameConstraintsRFC822CA1CRL.crl     |   Bin 0 -> 331 bytes
 .../PKITS/crls/nameConstraintsRFC822CA2CRL.crl     |   Bin 0 -> 331 bytes
 .../PKITS/crls/nameConstraintsRFC822CA3CRL.crl     |   Bin 0 -> 331 bytes
 .../data/PKITS/crls/nameConstraintsURI1CACRL.crl   |   Bin 0 -> 328 bytes
 .../data/PKITS/crls/nameConstraintsURI2CACRL.crl   |   Bin 0 -> 328 bytes
 .../PKITS/crls/onlyContainsAttributeCertsCACRL.crl |   Bin 0 -> 351 bytes
 .../data/PKITS/crls/onlyContainsCACertsCACRL.crl   |   Bin 0 -> 344 bytes
 .../data/PKITS/crls/onlyContainsUserCertsCACRL.crl |   Bin 0 -> 346 bytes
 .../PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl |   Bin 0 -> 378 bytes
 .../crls/onlySomeReasonsCA1otherreasonsCRL.crl     |   Bin 0 -> 379 bytes
 .../data/PKITS/crls/onlySomeReasonsCA2CRL1.crl     |   Bin 0 -> 342 bytes
 .../data/PKITS/crls/onlySomeReasonsCA2CRL2.crl     |   Bin 0 -> 342 bytes
 .../PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl |   Bin 0 -> 438 bytes
 .../crls/onlySomeReasonsCA3otherreasonsCRL.crl     |   Bin 0 -> 439 bytes
 .../PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl |   Bin 0 -> 475 bytes
 .../crls/onlySomeReasonsCA4otherreasonsCRL.crl     |   Bin 0 -> 476 bytes
 .../data/PKITS/crls/pathLenConstraint0CACRL.crl    |   Bin 0 -> 326 bytes
 .../PKITS/crls/pathLenConstraint0subCA2CRL.crl     |   Bin 0 -> 330 bytes
 .../data/PKITS/crls/pathLenConstraint0subCACRL.crl |   Bin 0 -> 329 bytes
 .../data/PKITS/crls/pathLenConstraint1CACRL.crl    |   Bin 0 -> 326 bytes
 .../data/PKITS/crls/pathLenConstraint1subCACRL.crl |   Bin 0 -> 329 bytes
 .../data/PKITS/crls/pathLenConstraint6CACRL.crl    |   Bin 0 -> 326 bytes
 .../PKITS/crls/pathLenConstraint6subCA0CRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/pathLenConstraint6subCA1CRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/pathLenConstraint6subCA4CRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/pathLenConstraint6subsubCA00CRL.crl |   Bin 0 -> 334 bytes
 .../PKITS/crls/pathLenConstraint6subsubCA11CRL.crl |   Bin 0 -> 334 bytes
 .../PKITS/crls/pathLenConstraint6subsubCA41CRL.crl |   Bin 0 -> 334 bytes
 .../crls/pathLenConstraint6subsubsubCA11XCRL.crl   |   Bin 0 -> 338 bytes
 .../crls/pathLenConstraint6subsubsubCA41XCRL.crl   |   Bin 0 -> 338 bytes
 .../data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl  |   Bin 0 -> 330 bytes
 .../PKITS/crls/requireExplicitPolicy0CACRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/requireExplicitPolicy0subCACRL.crl  |   Bin 0 -> 333 bytes
 .../crls/requireExplicitPolicy0subsubCACRL.crl     |   Bin 0 -> 336 bytes
 .../crls/requireExplicitPolicy0subsubsubCACRL.crl  |   Bin 0 -> 339 bytes
 .../PKITS/crls/requireExplicitPolicy10CACRL.crl    |   Bin 0 -> 331 bytes
 .../PKITS/crls/requireExplicitPolicy10subCACRL.crl |   Bin 0 -> 334 bytes
 .../crls/requireExplicitPolicy10subsubCACRL.crl    |   Bin 0 -> 337 bytes
 .../crls/requireExplicitPolicy10subsubsubCACRL.crl |   Bin 0 -> 340 bytes
 .../PKITS/crls/requireExplicitPolicy2CACRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/requireExplicitPolicy2subCACRL.crl  |   Bin 0 -> 333 bytes
 .../PKITS/crls/requireExplicitPolicy4CACRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/requireExplicitPolicy4subCACRL.crl  |   Bin 0 -> 333 bytes
 .../crls/requireExplicitPolicy4subsubCACRL.crl     |   Bin 0 -> 336 bytes
 .../crls/requireExplicitPolicy4subsubsubCACRL.crl  |   Bin 0 -> 339 bytes
 .../PKITS/crls/requireExplicitPolicy5CACRL.crl     |   Bin 0 -> 330 bytes
 .../PKITS/crls/requireExplicitPolicy5subCACRL.crl  |   Bin 0 -> 333 bytes
 .../crls/requireExplicitPolicy5subsubCACRL.crl     |   Bin 0 -> 336 bytes
 .../crls/requireExplicitPolicy5subsubsubCACRL.crl  |   Bin 0 -> 339 bytes
 .../PKITS/crls/requireExplicitPolicy7CACRL.crl     |   Bin 0 -> 330 bytes
 .../crls/requireExplicitPolicy7subCARE2CRL.crl     |   Bin 0 -> 336 bytes
 .../requireExplicitPolicy7subsubCARE2RE4CRL.crl    |   Bin 0 -> 342 bytes
 .../requireExplicitPolicy7subsubsubCARE2RE4CRL.crl |   Bin 0 -> 345 bytes
 .../test/data/asn1/masterlist-content.data         |   Bin 0 -> 1748 bytes
 .../test/data/cms/sigs/PSSSignData.data            |     1 +
 .../test/data/cms/sigs/PSSSignDataSHA1.sig         |   Bin 0 -> 3345 bytes
 .../test/data/cms/sigs/PSSSignDataSHA1Enc.sig      |   Bin 0 -> 3371 bytes
 .../test/data/cms/sigs/PSSSignDataSHA256.sig       |   Bin 0 -> 3417 bytes
 .../test/data/cms/sigs/PSSSignDataSHA256Enc.sig    |   Bin 0 -> 3443 bytes
 .../test/data/cms/sigs/PSSSignDataSHA512.sig       |   Bin 0 -> 3450 bytes
 .../test/data/cms/sigs/PSSSignDataSHA512Enc.sig    |   Bin 0 -> 3476 bytes
 .../test/data/cms/sigs/counterSig.p7m              |   Bin 0 -> 5647 bytes
 .../test/data/hc256/hc128/ecrypt_HC-128.txt        |  2337 ++
 .../data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt  |  2337 ++
 .../data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt  |  2783 ++
 .../data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt  |  2783 ++
 .../data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt  |  3257 ++
 BouncyCastle.AxCrypt/test/data/keys/README.txt     |     4 +
 .../test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key  |   Bin 0 -> 677 bytes
 .../test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key  |   Bin 0 -> 677 bytes
 .../test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key  |   Bin 0 -> 677 bytes
 .../test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key  |   Bin 0 -> 677 bytes
 .../test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key |   Bin 0 -> 677 bytes
 .../test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key |   Bin 0 -> 677 bytes
 .../keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key    |   Bin 0 -> 678 bytes
 .../data/keys/pbes1/pbe_WithSHA1And128BitRC4.key   |   Bin 0 -> 673 bytes
 .../pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key   |   Bin 0 -> 678 bytes
 .../pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key   |   Bin 0 -> 678 bytes
 .../keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key     |   Bin 0 -> 678 bytes
 .../data/keys/pbes1/pbe_WithSHA1And40BitRC4.key    |   Bin 0 -> 673 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-cbc.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-cfb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-cfb1.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-cfb8.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-ecb.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-128-ofb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-cbc.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-cfb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-cfb1.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-cfb8.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-ecb.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-192-ofb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-cbc.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-cfb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-cfb1.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-cfb8.key    |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-ecb.key     |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes-256-ofb.key     |   Bin 0 -> 718 bytes
 .../test/data/keys/pbes2/pbes2.aes128.key          |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes192.key          |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.aes256.key          |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.bf-cbc.key          |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.bf.key              |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.blowfish.key        |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.cast-cbc.key        |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.cast.key            |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.cast5-cbc.key       |   Bin 0 -> 715 bytes
 .../test/data/keys/pbes2/pbes2.des-cbc.key         |   Bin 0 -> 711 bytes
 .../test/data/keys/pbes2/pbes2.des-cfb.key         |   Bin 0 -> 706 bytes
 .../test/data/keys/pbes2/pbes2.des-cfb1.key        |   Bin 0 -> 706 bytes
 .../test/data/keys/pbes2/pbes2.des-cfb8.key        |   Bin 0 -> 706 bytes
 .../test/data/keys/pbes2/pbes2.des-ecb.key         |   Bin 0 -> 711 bytes
 .../test/data/keys/pbes2/pbes2.des-ede.key         |   Bin 0 -> 711 bytes
 .../test/data/keys/pbes2/pbes2.des-ede3-cbc.key    |   Bin 0 -> 714 bytes
 .../test/data/keys/pbes2/pbes2.des-ofb.key         |   Bin 0 -> 706 bytes
 .../test/data/keys/pbes2/pbes2.des.key             |   Bin 0 -> 711 bytes
 .../test/data/keys/pbes2/pbes2.des3.key            |   Bin 0 -> 714 bytes
 .../test/data/keys/pbes2/pbes2.rc2-40-cbc.key      |   Bin 0 -> 723 bytes
 .../test/data/keys/pbes2/pbes2.rc2-64-cbc.key      |   Bin 0 -> 722 bytes
 .../test/data/keys/pbes2/pbes2.rc2-cbc.key         |   Bin 0 -> 722 bytes
 .../test/data/keys/pbes2/pbes2.rc2.key             |   Bin 0 -> 722 bytes
 .../test/data/openpgp/dsa/README.txt               |    36 +
 .../test/data/openpgp/dsa/keys/DSA-1024-160.pub    |   Bin 0 -> 534 bytes
 .../test/data/openpgp/dsa/keys/DSA-1024-160.sec    |   Bin 0 -> 597 bytes
 .../test/data/openpgp/dsa/keys/DSA-15360-512.pub   |   Bin 0 -> 6043 bytes
 .../test/data/openpgp/dsa/keys/DSA-15360-512.sec   |   Bin 0 -> 6150 bytes
 .../test/data/openpgp/dsa/keys/DSA-2048-224.pub    |   Bin 0 -> 941 bytes
 .../test/data/openpgp/dsa/keys/DSA-2048-224.sec    |   Bin 0 -> 1012 bytes
 .../test/data/openpgp/dsa/keys/DSA-3072-256.pub    |   Bin 0 -> 1337 bytes
 .../test/data/openpgp/dsa/keys/DSA-3072-256.sec    |   Bin 0 -> 1412 bytes
 .../test/data/openpgp/dsa/keys/DSA-7680-384.pub    |   Bin 0 -> 3113 bytes
 .../test/data/openpgp/dsa/keys/DSA-7680-384.sec    |   Bin 0 -> 3204 bytes
 .../data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg    |     1 +
 .../data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg    |   Bin 0 -> 121 bytes
 .../data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg    |   Bin 0 -> 123 bytes
 .../data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg    |   Bin 0 -> 122 bytes
 .../data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg    |   Bin 0 -> 122 bytes
 .../data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg   |   Bin 0 -> 216 bytes
 .../data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg    |   Bin 0 -> 141 bytes
 .../data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg    |   Bin 0 -> 150 bytes
 .../data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg    |   Bin 0 -> 184 bytes
 BouncyCastle.AxCrypt/test/data/openssl/README.txt  |     8 +
 .../data/openssl/dsa/openssl_dsa_aes128_cbc.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes128_cfb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes128_ecb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes128_ofb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes192_cbc.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes192_cfb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes192_ecb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes192_ofb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes256_cbc.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes256_cfb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes256_ecb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_aes256_ofb.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_blowfish_cbc.pem  |    23 +
 .../data/openssl/dsa/openssl_dsa_blowfish_cfb.pem  |    23 +
 .../data/openssl/dsa/openssl_dsa_blowfish_ecb.pem  |    23 +
 .../data/openssl/dsa/openssl_dsa_blowfish_ofb.pem  |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des1_cbc.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des1_cfb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des1_ecb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des1_ofb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des2_cbc.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des2_cfb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des2_ecb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des2_ofb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des3_cbc.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des3_cfb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des3_ecb.pem |    23 +
 .../test/data/openssl/dsa/openssl_dsa_des3_ofb.pem |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem   |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem   |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem   |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem   |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem    |    23 +
 .../data/openssl/dsa/openssl_dsa_unencrypted.pem   |    20 +
 BouncyCastle.AxCrypt/test/data/openssl/eckey.pem   |     9 +
 BouncyCastle.AxCrypt/test/data/openssl/enckey.pem  |    30 +
 BouncyCastle.AxCrypt/test/data/openssl/pkcs7.pem   |    54 +
 .../test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem  |    28 +
 .../data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem   |    30 +
 .../test/data/openssl/pkcs8test.pem                |   175 +
 .../data/openssl/rsa/openssl_rsa_aes128_cbc.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes128_cfb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes128_ecb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes128_ofb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes192_cbc.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes192_cfb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes192_ecb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes192_ofb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes256_cbc.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes256_cfb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes256_ecb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_aes256_ofb.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_blowfish_cbc.pem  |    30 +
 .../data/openssl/rsa/openssl_rsa_blowfish_cfb.pem  |    30 +
 .../data/openssl/rsa/openssl_rsa_blowfish_ecb.pem  |    30 +
 .../data/openssl/rsa/openssl_rsa_blowfish_ofb.pem  |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des1_cbc.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des1_cfb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des1_ecb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des1_ofb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des2_cbc.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des2_cfb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des2_ecb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des2_ofb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des3_cbc.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des3_cfb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des3_ecb.pem |    30 +
 .../test/data/openssl/rsa/openssl_rsa_des3_ofb.pem |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem   |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem   |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem   |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem   |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem    |    30 +
 .../data/openssl/rsa/openssl_rsa_unencrypted.pem   |    27 +
 BouncyCastle.AxCrypt/test/data/openssl/test.pem    |   133 +
 BouncyCastle.AxCrypt/test/data/rfc4134/3.1.bin     |   Bin 0 -> 55 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/3.2.bin     |     1 +
 BouncyCastle.AxCrypt/test/data/rfc4134/4.1.bin     |   Bin 0 -> 923 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.10.bin    |   Bin 0 -> 2051 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.11.bin    |   Bin 0 -> 1676 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.2.bin     |   Bin 0 -> 854 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.3.bin     |   Bin 0 -> 891 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.4.bin     |   Bin 0 -> 2833 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.5.bin     |   Bin 0 -> 1359 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.6.bin     |   Bin 0 -> 1467 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.7.bin     |   Bin 0 -> 920 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/4.8.eml     |    39 +
 BouncyCastle.AxCrypt/test/data/rfc4134/4.9.eml     |    28 +
 BouncyCastle.AxCrypt/test/data/rfc4134/5.1.bin     |   Bin 0 -> 290 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/5.2.bin     |   Bin 0 -> 361 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/5.3.eml     |    19 +
 BouncyCastle.AxCrypt/test/data/rfc4134/6.0.bin     |   Bin 0 -> 96 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/7.1.bin     |   Bin 0 -> 89 bytes
 BouncyCastle.AxCrypt/test/data/rfc4134/7.2.bin     |   Bin 0 -> 152 bytes
 .../data/rfc4134/AliceDSSSignByCarlNoInherit.cer   |   Bin 0 -> 736 bytes
 .../test/data/rfc4134/AlicePrivDSSSign.pri         |   Bin 0 -> 335 bytes
 .../test/data/rfc4134/AlicePrivRSASign.pri         |   Bin 0 -> 634 bytes
 .../test/data/rfc4134/AliceRSASignByCarl.cer       |   Bin 0 -> 560 bytes
 .../test/data/rfc4134/BobPrivRSAEncrypt.pri        |   Bin 0 -> 649 bytes
 .../test/data/rfc4134/BobRSASignByCarl.cer         |   Bin 0 -> 555 bytes
 .../test/data/rfc4134/CarlDSSCRLEmpty.crl          |   Bin 0 -> 111 bytes
 .../test/data/rfc4134/CarlDSSCRLForAll.crl         |   Bin 0 -> 219 bytes
 .../test/data/rfc4134/CarlDSSCRLForCarl.crl        |   Bin 0 -> 134 bytes
 .../test/data/rfc4134/CarlDSSSelf.cer              |   Bin 0 -> 671 bytes
 .../test/data/rfc4134/CarlPrivDSSSign.pri          |   Bin 0 -> 334 bytes
 .../test/data/rfc4134/CarlPrivRSASign.pri          |   Bin 0 -> 634 bytes
 .../test/data/rfc4134/CarlRSACRLEmpty.crl          |   Bin 0 -> 202 bytes
 .../test/data/rfc4134/CarlRSACRLForAll.crl         |   Bin 0 -> 311 bytes
 .../test/data/rfc4134/CarlRSACRLForCarl.crl        |   Bin 0 -> 239 bytes
 .../test/data/rfc4134/CarlRSASelf.cer              |   Bin 0 -> 495 bytes
 .../data/rfc4134/DianeDSSSignByCarlInherit.cer     |   Bin 0 -> 444 bytes
 .../test/data/rfc4134/DianePrivDSSSign.pri         |   Bin 0 -> 335 bytes
 .../test/data/rfc4134/DianePrivRSASignEncrypt.pri  |   Bin 0 -> 635 bytes
 .../test/data/rfc4134/DianeRSASignByCarl.cer       |   Bin 0 -> 560 bytes
 .../test/data/rfc4134/ExContent.bin                |     1 +
 BouncyCastle.AxCrypt/test/data/rfc4134/rfc4134.txt |  7619 ++++
 .../test/data/rsa3/self-testcase-A.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-A.pem             |    52 +
 .../test/data/rsa3/self-testcase-B.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-B.pem             |    52 +
 .../test/data/rsa3/self-testcase-C.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-C.pem             |    52 +
 .../test/data/rsa3/self-testcase-D.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-D.pem             |    52 +
 .../test/data/rsa3/self-testcase-E.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-E.pem             |    52 +
 .../test/data/rsa3/self-testcase-F.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-F.pem             |    52 +
 .../test/data/rsa3/self-testcase-G.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-G.pem             |    52 +
 .../test/data/rsa3/self-testcase-H.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-H.pem             |    52 +
 .../test/data/rsa3/self-testcase-I.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-I.pem             |    52 +
 .../test/data/rsa3/self-testcase-J.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-J.pem             |    52 +
 .../test/data/rsa3/self-testcase-L.p12             |   Bin 0 -> 2742 bytes
 .../test/data/rsa3/self-testcase-L.pem             |    52 +
 .../test/data/rsa3/testcases.README                |   Bin 0 -> 14352 bytes
 .../test/data/scrypt/TestVectors.txt               |    20 +
 BouncyCastle.AxCrypt/test/data/tls/README.txt      |     8 +
 BouncyCastle.AxCrypt/test/data/tls/ca.tmpl         |     4 +
 BouncyCastle.AxCrypt/test/data/tls/client.tmpl     |     5 +
 .../test/data/tls/keystores/client_store.dsa       |   Bin 0 -> 2035 bytes
 .../test/data/tls/keystores/client_store.rsa       |   Bin 0 -> 1947 bytes
 .../test/data/tls/keystores/server_store.dsa       |   Bin 0 -> 2035 bytes
 .../test/data/tls/keystores/server_store.rsa       |   Bin 0 -> 1947 bytes
 BouncyCastle.AxCrypt/test/data/tls/server.tmpl     |     5 +
 BouncyCastle.AxCrypt/test/data/tls/x509-ca-key.pem |    32 +
 BouncyCastle.AxCrypt/test/data/tls/x509-ca.pem     |    21 +
 .../test/data/tls/x509-client-key.pem              |    32 +
 BouncyCastle.AxCrypt/test/data/tls/x509-client.pem |    22 +
 .../test/data/tls/x509-server-key.pem              |    32 +
 BouncyCastle.AxCrypt/test/data/tls/x509-server.pem |    22 +
 BouncyCastle.AxCrypt/test/lib/nunit.core.dll       |   Bin 0 -> 90112 bytes
 .../test/lib/nunit.core.interfaces.dll             |   Bin 0 -> 40960 bytes
 BouncyCastle.AxCrypt/test/lib/nunit.framework.dll  |   Bin 0 -> 81920 bytes
 .../test/src/asn1/test/ASN1SequenceParserTest.cs   |   359 +
 .../test/src/asn1/test/ASN1UnitTest.cs             |    88 +
 .../test/AdditionalInformationSyntaxUnitTest.cs    |    77 +
 .../test/src/asn1/test/AdmissionSyntaxUnitTest.cs  |    99 +
 .../test/src/asn1/test/AdmissionsUnitTest.cs       |    90 +
 .../test/src/asn1/test/AllTests.cs                 |    34 +
 .../test/src/asn1/test/AttributeTableUnitTest.cs   |   151 +
 .../test/src/asn1/test/BiometricDataUnitTest.cs    |   133 +
 .../test/src/asn1/test/BitStringConstantTester.cs  |    25 +
 .../test/src/asn1/test/BitStringTest.cs            |    82 +
 BouncyCastle.AxCrypt/test/src/asn1/test/CMSTest.cs |   306 +
 .../test/src/asn1/test/CertHashUnitTest.cs         |    93 +
 .../test/src/asn1/test/CertificateTest.cs          |   395 +
 .../asn1/test/CommitmentTypeIndicationUnitTest.cs  |   107 +
 .../asn1/test/CommitmentTypeQualifierUnitTest.cs   |   107 +
 .../test/src/asn1/test/ContentHintsUnitTest.cs     |    93 +
 .../test/src/asn1/test/CscaMasterListTest.cs       |    57 +
 .../src/asn1/test/DERApplicationSpecificTest.cs    |    88 +
 .../test/src/asn1/test/DERUTF8StringTest.cs        |   113 +
 .../test/src/asn1/test/DataGroupHashUnitTest.cs    |   106 +
 .../src/asn1/test/DeclarationOfMajorityUnitTest.cs |    97 +
 .../src/asn1/test/EncryptedPrivateKeyInfoTest.cs   |   152 +
 .../test/src/asn1/test/EnumeratedTest.cs           |   115 +
 .../test/src/asn1/test/EqualsAndHashCodeTest.cs    |    93 +
 .../test/src/asn1/test/EssCertIDv2UnitTest.cs      |    46 +
 .../test/src/asn1/test/GeneralNameTest.cs          |   116 +
 .../test/src/asn1/test/GeneralizedTimeTest.cs      |   231 +
 .../test/src/asn1/test/GenerationTest.cs           |   325 +
 .../test/src/asn1/test/InputStreamTest.cs          |    85 +
 .../src/asn1/test/Iso4217CurrencyCodeUnitTest.cs   |   156 +
 .../src/asn1/test/IssuingDistributionPointTest.cs  |   133 +
 .../test/src/asn1/test/KeyUsageTest.cs             |    49 +
 .../src/asn1/test/LDSSecurityObjectUnitTest.cs     |   208 +
 .../test/src/asn1/test/MiscTest.cs                 |    94 +
 .../test/src/asn1/test/MonetaryLimitUnitTest.cs    |    93 +
 .../test/src/asn1/test/MonetaryValueUnitTest.cs    |    99 +
 .../test/src/asn1/test/NameOrPseudonymUnitTest.cs  |   114 +
 .../test/src/asn1/test/NamingAuthorityUnitTest.cs  |   106 +
 .../test/src/asn1/test/NetscapeCertTypeTest.cs     |    45 +
 .../test/src/asn1/test/OCSPTest.cs                 |   183 +
 BouncyCastle.AxCrypt/test/src/asn1/test/OIDTest.cs |   149 +
 .../test/src/asn1/test/OctetStringTest.cs          |   186 +
 .../test/src/asn1/test/OtherCertIDUnitTest.cs      |   100 +
 .../asn1/test/OtherSigningCertificateUnitTest.cs   |    94 +
 .../test/src/asn1/test/PKCS10Test.cs               |    95 +
 .../test/src/asn1/test/PKCS12Test.cs               |   210 +
 .../test/src/asn1/test/PKIFailureInfoTest.cs       |    76 +
 .../test/src/asn1/test/ParseTest.cs                |   303 +
 .../test/src/asn1/test/ParsingTest.cs              |   104 +
 .../test/src/asn1/test/PersonalDataUnitTest.cs     |   127 +
 .../src/asn1/test/ProcurationSyntaxUnitTest.cs     |   111 +
 .../test/src/asn1/test/ProfessionInfoUnitTest.cs   |   121 +
 .../test/src/asn1/test/QCStatementUnitTest.cs      |   108 +
 .../test/src/asn1/test/ReasonFlagsTest.cs          |    46 +
 .../test/src/asn1/test/RegressionTest.cs           |    85 +
 .../src/asn1/test/RequestedCertificateUnitTest.cs  |   117 +
 .../test/src/asn1/test/RestrictionUnitTest.cs      |    78 +
 .../test/src/asn1/test/SMIMETest.cs                |    90 +
 .../src/asn1/test/SemanticsInformationUnitTest.cs  |   138 +
 BouncyCastle.AxCrypt/test/src/asn1/test/SetTest.cs |   117 +
 .../test/src/asn1/test/SignerLocationUnitTest.cs   |   195 +
 .../test/src/asn1/test/StringTest.cs               |   105 +
 .../test/src/asn1/test/SubjectKeyIdentifierTest.cs |    61 +
 BouncyCastle.AxCrypt/test/src/asn1/test/TagTest.cs |   115 +
 .../test/src/asn1/test/TargetInformationTest.cs    |    58 +
 .../test/src/asn1/test/TimeTest.cs                 |    28 +
 .../src/asn1/test/TypeOfBiometricDataUnitTest.cs   |   152 +
 .../test/src/asn1/test/UTCTimeTest.cs              |   122 +
 .../test/src/asn1/test/X509ExtensionsTest.cs       |   117 +
 .../test/src/asn1/test/X509NameTest.cs             |   674 +
 BouncyCastle.AxCrypt/test/src/asn1/test/X9Test.cs  |   168 +
 BouncyCastle.AxCrypt/test/src/cms/test/AllTests.cs |    37 +
 .../src/cms/test/AuthenticatedDataStreamTest.cs    |   113 +
 .../test/src/cms/test/AuthenticatedDataTest.cs     |   320 +
 .../test/src/cms/test/CMSSampleMessages.cs         |   147 +
 .../test/src/cms/test/CMSTestUtil.cs               |   480 +
 .../test/src/cms/test/CompressedDataStreamTest.cs  |   116 +
 .../test/src/cms/test/CompressedDataTest.cs        |   117 +
 .../test/src/cms/test/EnvelopedDataStreamTest.cs   |   537 +
 .../test/src/cms/test/EnvelopedDataTest.cs         |   866 +
 .../test/src/cms/test/MiscDataStreamTest.cs        |   221 +
 .../test/src/cms/test/Rfc4134Test.cs               |   344 +
 .../test/src/cms/test/SignedDataStreamTest.cs      |  1235 +
 .../test/src/cms/test/SignedDataTest.cs            |  1480 +
 .../test/src/crypto/examples/DESExample.cs         |   396 +
 .../test/src/crypto/io/test/AllTests.cs            |    29 +
 .../test/src/crypto/io/test/CipherStreamTest.cs    |   166 +
 .../test/src/crypto/test/AESFastTest.cs            |   168 +
 .../test/src/crypto/test/AESLightTest.cs           |   168 +
 .../test/src/crypto/test/AESTest.cs                |   178 +
 .../test/src/crypto/test/AESWrapTest.cs            |   214 +
 .../test/src/crypto/test/AeadTestUtilities.cs      |    14 +
 .../test/src/crypto/test/AllTests.cs               |    52 +
 .../src/crypto/test/BlockCipherMonteCarloTest.cs   |    83 +
 .../test/src/crypto/test/BlockCipherVectorTest.cs  |    75 +
 .../test/src/crypto/test/BlowfishTest.cs           |    55 +
 .../test/src/crypto/test/CAST6Test.cs              |    57 +
 .../test/src/crypto/test/CCMTest.cs                |   268 +
 .../test/src/crypto/test/CMacTest.cs               |   302 +
 .../test/src/crypto/test/CTSTest.cs                |   192 +
 .../test/src/crypto/test/CamelliaLightTest.cs      |    80 +
 .../test/src/crypto/test/CamelliaTest.cs           |    80 +
 .../test/src/crypto/test/Cast5Test.cs              |    49 +
 .../test/src/crypto/test/ChaChaTest.cs             |   319 +
 .../test/src/crypto/test/CipherTest.cs             |   117 +
 .../test/src/crypto/test/DESTest.cs                |   214 +
 .../test/src/crypto/test/DESedeTest.cs             |   187 +
 .../test/src/crypto/test/DHKEKGeneratorTest.cs     |    79 +
 .../test/src/crypto/test/DHTest.cs                 |   403 +
 .../test/src/crypto/test/DSATest.cs                |   615 +
 .../test/src/crypto/test/DeterministicDSATest.cs   |   511 +
 .../test/src/crypto/test/DigestRandomNumberTest.cs |   163 +
 .../test/src/crypto/test/DigestTest.cs             |   183 +
 .../test/src/crypto/test/EAXTest.cs                |   352 +
 .../test/src/crypto/test/ECDHKEKGeneratorTest.cs   |    80 +
 .../test/src/crypto/test/ECGOST3410Test.cs         |   345 +
 .../test/src/crypto/test/ECIESTest.cs              |   252 +
 .../test/src/crypto/test/ECNRTest.cs               |   118 +
 .../test/src/crypto/test/ECTest.cs                 |   932 +
 .../test/src/crypto/test/ElGamalTest.cs            |   278 +
 .../test/src/crypto/test/EqualsHashCodeTest.cs     |   262 +
 .../test/src/crypto/test/GCMTest.cs                |   711 +
 .../test/src/crypto/test/GMacTest.cs               |   187 +
 .../test/src/crypto/test/GOST28147MacTest.cs       |   105 +
 .../test/src/crypto/test/GOST28147Test.cs          |   334 +
 .../test/src/crypto/test/GOST3410Test.cs           |  1604 +
 .../test/src/crypto/test/GOST3411DigestTest.cs     |    79 +
 .../test/src/crypto/test/GcmReorderTest.cs         |   362 +
 .../test/src/crypto/test/HCFamilyTest.cs           |   192 +
 .../test/src/crypto/test/HCFamilyVecTest.cs        |   184 +
 .../test/src/crypto/test/IDEATest.cs               |    53 +
 .../test/src/crypto/test/ISAACTest.cs              |   196 +
 .../test/src/crypto/test/ISO9796Test.cs            |   961 +
 .../test/src/crypto/test/ISO9797Alg3MacTest.cs     |    99 +
 .../test/src/crypto/test/KDF1GeneratorTest.cs      |   103 +
 .../test/src/crypto/test/KDF2GeneratorTest.cs      |   115 +
 .../test/src/crypto/test/MD2DigestTest.cs          |    67 +
 .../test/src/crypto/test/MD4DigestTest.cs          |    59 +
 .../test/src/crypto/test/MD5DigestTest.cs          |    59 +
 .../test/src/crypto/test/MD5HMacTest.cs            |    91 +
 .../test/src/crypto/test/MGF1GeneratorTest.cs      |   103 +
 .../test/src/crypto/test/MacTest.cs                |   214 +
 .../test/src/crypto/test/ModeTest.cs               |   108 +
 .../test/src/crypto/test/NaccacheSternTest.cs      |   354 +
 .../test/src/crypto/test/NoekeonTest.cs            |    59 +
 .../test/src/crypto/test/NullTest.cs               |    88 +
 .../test/src/crypto/test/OAEPTest.cs               |   798 +
 .../test/src/crypto/test/OCBTest.cs                |   515 +
 .../test/src/crypto/test/PSSBlindTest.cs           |   399 +
 .../test/src/crypto/test/PSSTest.cs                |   338 +
 .../test/src/crypto/test/PaddingTest.cs            |   171 +
 .../test/src/crypto/test/Pkcs12Test.cs             |   101 +
 .../test/src/crypto/test/Pkcs5Test.cs              |   243 +
 .../test/src/crypto/test/Poly1305Test.cs           |   395 +
 .../test/src/crypto/test/RC2Test.cs                |    58 +
 .../test/src/crypto/test/RC2WrapTest.cs            |   123 +
 .../test/src/crypto/test/RC4Test.cs                |    59 +
 .../test/src/crypto/test/RC5Test.cs                |   201 +
 .../test/src/crypto/test/RC6Test.cs                |    54 +
 .../test/src/crypto/test/RFC3211WrapTest.cs        |   216 +
 .../test/src/crypto/test/RSABlindedTest.cs         |   449 +
 .../test/src/crypto/test/RegressionTest.cs         |   135 +
 .../test/src/crypto/test/RijndaelTest.cs           |   135 +
 .../test/src/crypto/test/RipeMD128DigestTest.cs    |    74 +
 .../test/src/crypto/test/RipeMD128HMacTest.cs      |   100 +
 .../test/src/crypto/test/RipeMD160DigestTest.cs    |    74 +
 .../test/src/crypto/test/RipeMD160HMacTest.cs      |   102 +
 .../test/src/crypto/test/RipeMD256DigestTest.cs    |    74 +
 .../test/src/crypto/test/RipeMD320DigestTest.cs    |    74 +
 .../test/src/crypto/test/RsaTest.cs                |   596 +
 .../test/src/crypto/test/SCryptTest.cs             |   103 +
 .../test/src/crypto/test/SEEDTest.cs               |    65 +
 .../test/src/crypto/test/SHA1DigestTest.cs         |    57 +
 .../test/src/crypto/test/SHA1HMacTest.cs           |    93 +
 .../test/src/crypto/test/SHA224DigestTest.cs       |    70 +
 .../test/src/crypto/test/SHA224HMacTest.cs         |   122 +
 .../test/src/crypto/test/SHA256DigestTest.cs       |    71 +
 .../test/src/crypto/test/SHA256HMacTest.cs         |   122 +
 .../test/src/crypto/test/SHA384DigestTest.cs       |    70 +
 .../test/src/crypto/test/SHA384HMacTest.cs         |   122 +
 .../test/src/crypto/test/SHA3DigestTest.cs         |   374 +
 .../test/src/crypto/test/SHA512DigestTest.cs       |    70 +
 .../test/src/crypto/test/SHA512HMacTest.cs         |   123 +
 .../test/src/crypto/test/SHA512t224DigestTest.cs   |    62 +
 .../test/src/crypto/test/SHA512t256DigestTest.cs   |    62 +
 .../test/src/crypto/test/SM3DigestTest.cs          |    74 +
 .../test/src/crypto/test/SRP6Test.cs               |   300 +
 .../test/src/crypto/test/Salsa20Test.cs            |   318 +
 .../test/src/crypto/test/SerpentTest.cs            |   119 +
 .../test/src/crypto/test/ShortenedDigestTest.cs    |    98 +
 .../test/src/crypto/test/SipHashTest.cs            |   156 +
 .../test/src/crypto/test/SkeinDigestTest.cs        |   303 +
 .../test/src/crypto/test/SkeinMacTest.cs           |   174 +
 .../test/src/crypto/test/SkipjackTest.cs           |    46 +
 .../test/src/crypto/test/StreamCipherVectorTest.cs |    68 +
 .../test/src/crypto/test/TEATest.cs                |    59 +
 .../test/src/crypto/test/Threefish1024Test.cs      |    74 +
 .../test/src/crypto/test/Threefish256Test.cs       |    59 +
 .../test/src/crypto/test/Threefish512Test.cs       |    64 +
 .../test/src/crypto/test/TigerDigestTest.cs        |    82 +
 .../test/src/crypto/test/TwofishTest.cs            |    54 +
 .../test/src/crypto/test/VMPCKSA3Test.cs           |   112 +
 .../test/src/crypto/test/VMPCMacTest.cs            |    68 +
 .../test/src/crypto/test/VMPCTest.cs               |   112 +
 .../test/src/crypto/test/WhirlpoolDigestTest.cs    |   119 +
 .../test/src/crypto/test/XSalsa20Test.cs           |   183 +
 .../test/src/crypto/test/XTEATest.cs               |    59 +
 .../test/src/crypto/tls/test/MockTlsClient.cs      |   158 +
 .../test/src/crypto/tls/test/MockTlsServer.cs      |   137 +
 .../test/src/crypto/tls/test/TlsClientTest.cs      |    66 +
 .../test/src/crypto/tls/test/TlsServerTest.cs      |    78 +
 .../test/src/crypto/tls/test/TlsTestUtilities.cs   |   138 +
 .../test/src/math/ec/test/AllTests.cs              |    30 +
 .../test/src/math/ec/test/ECAlgorithmsTest.cs      |   153 +
 .../src/math/ec/test/ECPointPerformanceTest.cs     |   210 +
 .../test/src/math/ec/test/ECPointTest.cs           |   507 +
 .../test/src/math/ec/test/F2mProofer.cs            |   201 +
 .../test/src/math/ec/test/TnafTest.cs              |   158 +
 .../test/src/math/test/AllTests.cs                 |    29 +
 .../test/src/math/test/BigIntegerTest.cs           |  1048 +
 .../test/src/ocsp/test/AllTests.cs                 |    31 +
 .../test/src/ocsp/test/OCSPTest.cs                 |   852 +
 .../test/src/ocsp/test/OCSPTestUtil.cs             |   147 +
 .../test/src/openpgp/examples/ByteArrayHandler.cs  |   195 +
 .../openpgp/examples/ClearSignedFileProcessor.cs   |   375 +
 .../openpgp/examples/DetachedSignatureProcessor.cs |   167 +
 .../src/openpgp/examples/DirectKeySignature.cs     |   140 +
 .../openpgp/examples/DsaElGamalKeyRingGenerator.cs |   134 +
 .../src/openpgp/examples/KeyBasedFileProcessor.cs  |   259 +
 .../openpgp/examples/KeyBasedLargeFileProcessor.cs |   267 +
 .../test/src/openpgp/examples/PbeFileProcessor.cs  |   183 +
 .../src/openpgp/examples/PgpExampleUtilities.cs    |   123 +
 .../test/src/openpgp/examples/PublicKeyRingDump.cs |    98 +
 .../src/openpgp/examples/RsaKeyRingGenerator.cs    |   115 +
 .../src/openpgp/examples/SignedFileProcessor.cs    |   188 +
 .../test/src/openpgp/examples/test/AllTests.cs     |   405 +
 .../test/src/openpgp/test/DSA2Test.cs              |   237 +
 .../test/src/openpgp/test/PGPArmoredTest.cs        |   265 +
 .../openpgp/test/PGPClearSignedSignatureTest.cs    |   445 +
 .../test/src/openpgp/test/PGPCompressionTest.cs    |   117 +
 .../test/src/openpgp/test/PGPDSAElGamalTest.cs     |   492 +
 .../test/src/openpgp/test/PGPDSATest.cs            |   597 +
 .../test/src/openpgp/test/PGPNoPrivateKeyTest.cs   |   169 +
 .../test/src/openpgp/test/PGPPBETest.cs            |   384 +
 .../test/src/openpgp/test/PGPPacketTest.cs         |    80 +
 .../test/src/openpgp/test/PGPRSATest.cs            |  1233 +
 .../test/src/openpgp/test/PGPSignatureTest.cs      |  1045 +
 .../test/src/openpgp/test/PgpKeyRingTest.cs        |  2161 ++
 .../test/src/openpgp/test/PgpMarkerTest.cs         |   102 +
 .../test/src/openpgp/test/RegressionTest.cs        |    35 +
 .../test/src/openssl/test/AllTests.cs              |   135 +
 .../test/src/openssl/test/ReaderTest.cs            |   379 +
 .../test/src/openssl/test/WriterTest.cs            |   185 +
 .../test/src/pkcs/examples/PKCS12Example.cs        |   386 +
 .../src/pkcs/test/EncryptedPrivateKeyInfoTest.cs   |    92 +
 .../test/src/pkcs/test/PKCS10Test.cs               |    88 +
 .../test/src/pkcs/test/PKCS12StoreTest.cs          |   921 +
 .../test/src/security/test/SecureRandomTest.cs     |   150 +
 .../test/src/security/test/TestDigestUtil.cs       |    63 +
 .../test/src/security/test/TestDotNetUtil.cs       |    88 +
 .../test/src/security/test/TestEncodings.cs        |   188 +
 .../test/src/security/test/TestParameterUtil.cs    |    74 +
 .../test/src/security/test/TestSignerUtil.cs       |   181 +
 BouncyCastle.AxCrypt/test/src/test/AESSICTest.cs   |   147 +
 BouncyCastle.AxCrypt/test/src/test/AESTest.cs      |   363 +
 .../test/src/test/AttrCertSelectorTest.cs          |   214 +
 BouncyCastle.AxCrypt/test/src/test/AttrCertTest.cs |   621 +
 .../test/src/test/BaseBlockCipherTest.cs           |   146 +
 .../test/src/test/BlockCipherTest.cs               |   972 +
 BouncyCastle.AxCrypt/test/src/test/CMacTest.cs     |   276 +
 BouncyCastle.AxCrypt/test/src/test/CRL5Test.cs     |   257 +
 BouncyCastle.AxCrypt/test/src/test/CamelliaTest.cs |   204 +
 .../test/src/test/CertPathBuilderTest.cs           |   163 +
 BouncyCastle.AxCrypt/test/src/test/CertPathTest.cs |   359 +
 .../test/src/test/CertPathValidatorTest.cs         |   304 +
 BouncyCastle.AxCrypt/test/src/test/CertTest.cs     |  2544 ++
 .../test/src/test/CipherStreamTest.cs              |   449 +
 BouncyCastle.AxCrypt/test/src/test/DESedeTest.cs   |   298 +
 BouncyCastle.AxCrypt/test/src/test/DHTest.cs       |   651 +
 BouncyCastle.AxCrypt/test/src/test/DSATest.cs      |   888 +
 BouncyCastle.AxCrypt/test/src/test/DigestTest.cs   |   175 +
 BouncyCastle.AxCrypt/test/src/test/ECDSA5Test.cs   |   300 +
 .../test/src/test/ECEncodingTest.cs                |   243 +
 BouncyCastle.AxCrypt/test/src/test/ECNRTest.cs     |   204 +
 BouncyCastle.AxCrypt/test/src/test/ElGamalTest.cs  |   334 +
 .../test/src/test/EncryptedPrivateKeyInfoTest.cs   |   154 +
 BouncyCastle.AxCrypt/test/src/test/FIPSDESTest.cs  |   205 +
 .../test/src/test/GOST28147Test.cs                 |   245 +
 BouncyCastle.AxCrypt/test/src/test/GOST3410Test.cs |   380 +
 BouncyCastle.AxCrypt/test/src/test/HMacTest.cs     |   189 +
 BouncyCastle.AxCrypt/test/src/test/IESTest.cs      |   245 +
 BouncyCastle.AxCrypt/test/src/test/MacTest.cs      |   216 +
 BouncyCastle.AxCrypt/test/src/test/MqvTest.cs      |    99 +
 .../test/src/test/NamedCurveTest.cs                |   381 +
 .../test/src/test/NistCertPathTest.cs              |  5192 +++
 BouncyCastle.AxCrypt/test/src/test/NoekeonTest.cs  |   157 +
 BouncyCastle.AxCrypt/test/src/test/PBETest.cs      |   527 +
 BouncyCastle.AxCrypt/test/src/test/PEMData.cs      |   117 +
 .../test/src/test/PKCS10CertRequestTest.cs         |   470 +
 BouncyCastle.AxCrypt/test/src/test/PSSTest.cs      |   253 +
 .../test/src/test/PkixNameConstraintsTest.cs       |   433 +
 .../test/src/test/PkixPolicyMappingTest.cs         |   419 +
 BouncyCastle.AxCrypt/test/src/test/PkixTest.cs     |   248 +
 BouncyCastle.AxCrypt/test/src/test/RSATest.cs      |   685 +
 .../test/src/test/RegressionTest.cs                |    80 +
 BouncyCastle.AxCrypt/test/src/test/SEEDTest.cs     |   190 +
 BouncyCastle.AxCrypt/test/src/test/SigTest.cs      |   378 +
 .../test/src/test/TestUtilities.cs                 |   264 +
 BouncyCastle.AxCrypt/test/src/test/WrapTest.cs     |    94 +
 .../test/src/test/X509CertificatePairTest.cs       |   149 +
 .../test/src/test/X509StoreTest.cs                 |   335 +
 .../test/src/test/nist/NistCertPathTest.cs         |   847 +
 .../test/src/test/rsa3/RSA3CertTest.cs             |   127 +
 BouncyCastle.AxCrypt/test/src/tsp/test/AllTests.cs |    34 +
 .../test/src/tsp/test/GenTimeAccuracyTest.cs       |   116 +
 .../test/src/tsp/test/ParseTest.cs                 |   396 +
 BouncyCastle.AxCrypt/test/src/tsp/test/TSPTest.cs  |   548 +
 .../test/src/tsp/test/TSPTestUtil.cs               |   200 +
 .../test/src/tsp/test/TimeStampTokenInfoTest.cs    |   145 +
 .../test/src/util/io/pem/test/AllTests.cs          |    79 +
 .../test/src/util/net/test/IPAddressTest.cs        |    61 +
 .../test/src/util/test/FixedSecureRandom.cs        |    64 +
 BouncyCastle.AxCrypt/test/src/util/test/ITest.cs   |    17 +
 .../test/src/util/test/ITestResult.cs              |    13 +
 .../test/src/util/test/NumberParsing.cs            |    40 +
 .../test/src/util/test/SimpleTest.cs               |   164 +
 .../test/src/util/test/SimpleTestResult.cs         |    91 +
 .../test/src/util/test/TestFailedException.cs      |    24 +
 .../test/src/util/test/UncloseableStream.cs        |    22 +
 .../test/src/x509/test/TestCertificateGen.cs       |   715 +
 BouncyCastle.AxCrypt/testcfg.nunit                 |     6 +
 ChangeLog                                          |  6015 +++
 CustomDictionary.xml                               |    31 +
 Newtonsoft.Json/AxantumStrongName.pfx              |   Bin 0 -> 1764 bytes
 Newtonsoft.Json/Bson/BsonBinaryType.cs             |    44 +
 Newtonsoft.Json/Bson/BsonBinaryWriter.cs           |   325 +
 Newtonsoft.Json/Bson/BsonObjectId.cs               |    55 +
 Newtonsoft.Json/Bson/BsonReader.cs                 |   849 +
 Newtonsoft.Json/Bson/BsonToken.cs                  |   157 +
 Newtonsoft.Json/Bson/BsonType.cs                   |    51 +
 Newtonsoft.Json/Bson/BsonWriter.cs                 |   517 +
 Newtonsoft.Json/ConstructorHandling.cs             |    43 +
 Newtonsoft.Json/Converters/BinaryConverter.cs      |   183 +
 .../Converters/BsonObjectIdConverter.cs            |    89 +
 .../Converters/CustomCreationConverter.cs          |    99 +
 Newtonsoft.Json/Converters/DataSetConverter.cs     |   112 +
 Newtonsoft.Json/Converters/DataTableConverter.cs   |   220 +
 .../Converters/DateTimeConverterBase.cs            |    54 +
 .../Converters/DiscriminatedUnionConverter.cs      |   184 +
 .../Converters/EntityKeyMemberConverter.cs         |   146 +
 .../Converters/ExpandoObjectConverter.cs           |   165 +
 Newtonsoft.Json/Converters/IsoDateTimeConverter.cs |   169 +
 .../Converters/JavaScriptDateTimeConverter.cs      |   118 +
 Newtonsoft.Json/Converters/JsonValueConverter.cs   |   225 +
 .../Converters/KeyValuePairConverter.cs            |   145 +
 Newtonsoft.Json/Converters/RegexConverter.cs       |   201 +
 Newtonsoft.Json/Converters/StringEnumConverter.cs  |   239 +
 Newtonsoft.Json/Converters/VersionConverter.cs     |   106 +
 Newtonsoft.Json/Converters/XmlNodeConverter.cs     |  1758 +
 Newtonsoft.Json/DateFormatHandling.cs              |    43 +
 Newtonsoft.Json/DateParseHandling.cs               |    49 +
 Newtonsoft.Json/DateTimeZoneHandling.cs            |    56 +
 Newtonsoft.Json/DefaultValueHandling.cs            |    67 +
 Newtonsoft.Json/Dynamic.snk                        |   Bin 0 -> 596 bytes
 Newtonsoft.Json/FloatFormatHandling.cs             |    50 +
 Newtonsoft.Json/FloatParseHandling.cs              |    43 +
 Newtonsoft.Json/FormatterAssemblyStyle.cs          |    23 +
 Newtonsoft.Json/Formatting.cs                      |    43 +
 Newtonsoft.Json/IJsonLineInfo.cs                   |    53 +
 Newtonsoft.Json/JsonArrayAttribute.cs              |    73 +
 Newtonsoft.Json/JsonConstructorAttribute.cs        |    37 +
 Newtonsoft.Json/JsonContainerAttribute.cs          |   127 +
 Newtonsoft.Json/JsonConvert.cs                     |  1117 +
 Newtonsoft.Json/JsonConverter.cs                   |    93 +
 Newtonsoft.Json/JsonConverterAttribute.cs          |    73 +
 Newtonsoft.Json/JsonConverterCollection.cs         |    39 +
 Newtonsoft.Json/JsonDictionaryAttribute.cs         |    52 +
 Newtonsoft.Json/JsonException.cs                   |    92 +
 Newtonsoft.Json/JsonExtensionDataAttribute.cs      |    37 +
 Newtonsoft.Json/JsonIgnoreAttribute.cs             |    39 +
 Newtonsoft.Json/JsonObjectAttribute.cs             |    89 +
 Newtonsoft.Json/JsonPosition.cs                    |   115 +
 Newtonsoft.Json/JsonPropertyAttribute.cs           |   190 +
 Newtonsoft.Json/JsonReader.cs                      |  1010 +
 Newtonsoft.Json/JsonReaderException.cs             |   139 +
 Newtonsoft.Json/JsonSerializationException.cs      |   100 +
 Newtonsoft.Json/JsonSerializer.cs                  |   925 +
 Newtonsoft.Json/JsonSerializerSettings.cs          |   365 +
 Newtonsoft.Json/JsonTextReader.cs                  |  1615 +
 Newtonsoft.Json/JsonTextWriter.cs                  |   731 +
 Newtonsoft.Json/JsonToken.cs                       |   127 +
 Newtonsoft.Json/JsonValidatingReader.cs            |   917 +
 Newtonsoft.Json/JsonWriter.cs                      |  1523 +
 Newtonsoft.Json/JsonWriterException.cs             |   107 +
 Newtonsoft.Json/Linq/Extensions.cs                 |   312 +
 Newtonsoft.Json/Linq/IJEnumerable.cs               |    46 +
 Newtonsoft.Json/Linq/JArray.cs                     |   356 +
 Newtonsoft.Json/Linq/JConstructor.cs               |   206 +
 Newtonsoft.Json/Linq/JContainer.cs                 |  1011 +
 Newtonsoft.Json/Linq/JEnumerable.cs                |   118 +
 Newtonsoft.Json/Linq/JObject.cs                    |   790 +
 Newtonsoft.Json/Linq/JProperty.cs                  |   258 +
 Newtonsoft.Json/Linq/JPropertyDescriptor.cs        |   166 +
 Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs   |   231 +
 Newtonsoft.Json/Linq/JRaw.cs                       |    75 +
 Newtonsoft.Json/Linq/JToken.cs                     |  2023 +
 Newtonsoft.Json/Linq/JTokenEqualityComparer.cs     |    62 +
 Newtonsoft.Json/Linq/JTokenReader.cs               |   355 +
 Newtonsoft.Json/Linq/JTokenType.cs                 |   123 +
 Newtonsoft.Json/Linq/JTokenWriter.cs               |   456 +
 Newtonsoft.Json/Linq/JValue.cs                     |  1037 +
 Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs  |    40 +
 .../Linq/JsonPath/ArrayMultipleIndexFilter.cs      |    23 +
 Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs  |    74 +
 Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs       |    43 +
 .../Linq/JsonPath/FieldMultipleFilter.cs           |    42 +
 Newtonsoft.Json/Linq/JsonPath/JPath.cs             |   681 +
 Newtonsoft.Json/Linq/JsonPath/PathFilter.cs        |    49 +
 Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs   |   108 +
 Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs       |    22 +
 Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs        |    55 +
 Newtonsoft.Json/MemberSerialization.cs             |    58 +
 Newtonsoft.Json/MetadataPropertyHandling.cs        |    47 +
 Newtonsoft.Json/MissingMemberHandling.cs           |    47 +
 Newtonsoft.Json/Newtonsoft.Json.Net20.csproj       |   291 +
 Newtonsoft.Json/Newtonsoft.Json.Net35.csproj       |   307 +
 Newtonsoft.Json/Newtonsoft.Json.Net40.csproj       |   316 +
 Newtonsoft.Json/Newtonsoft.Json.Portable.csproj    |   243 +
 Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj  |   251 +
 Newtonsoft.Json/Newtonsoft.Json.WinRT.csproj       |   316 +
 Newtonsoft.Json/Newtonsoft.Json.csproj             |   250 +
 Newtonsoft.Json/Newtonsoft.Json.ruleset            |   236 +
 Newtonsoft.Json/NullValueHandling.cs               |    47 +
 Newtonsoft.Json/ObjectCreationHandling.cs          |    48 +
 Newtonsoft.Json/PreserveReferencesHandling.cs      |    62 +
 Newtonsoft.Json/Properties/AssemblyInfo.cs         |    94 +
 Newtonsoft.Json/ReadMe-AxCrypt.txt                 |    19 +
 Newtonsoft.Json/ReferenceLoopHandling.cs           |    52 +
 Newtonsoft.Json/Required.cs                        |    48 +
 Newtonsoft.Json/Schema/Extensions.cs               |   104 +
 Newtonsoft.Json/Schema/JsonSchema.cs               |   350 +
 Newtonsoft.Json/Schema/JsonSchemaBuilder.cs        |   448 +
 Newtonsoft.Json/Schema/JsonSchemaConstants.cs      |    78 +
 Newtonsoft.Json/Schema/JsonSchemaException.cs      |   108 +
 Newtonsoft.Json/Schema/JsonSchemaGenerator.cs      |   473 +
 Newtonsoft.Json/Schema/JsonSchemaModel.cs          |   119 +
 Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs   |   191 +
 Newtonsoft.Json/Schema/JsonSchemaNode.cs           |    80 +
 Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs |    37 +
 Newtonsoft.Json/Schema/JsonSchemaResolver.cs       |    71 +
 Newtonsoft.Json/Schema/JsonSchemaType.cs           |    81 +
 Newtonsoft.Json/Schema/JsonSchemaWriter.cs         |   243 +
 .../Schema/UndefinedSchemaIdHandling.cs            |    48 +
 Newtonsoft.Json/Schema/ValidationEventArgs.cs      |    71 +
 Newtonsoft.Json/Schema/ValidationEventHandler.cs   |    32 +
 .../Serialization/CachedAttributeGetter.cs         |    41 +
 .../CamelCasePropertyNamesContractResolver.cs      |    55 +
 .../Serialization/DefaultContractResolver.cs       |  1342 +
 .../Serialization/DefaultReferenceResolver.cs      |    83 +
 .../Serialization/DefaultSerializationBinder.cs    |   157 +
 .../Serialization/DiagnosticsTraceWriter.cs        |    75 +
 .../Serialization/DynamicValueProvider.cs          |   114 +
 Newtonsoft.Json/Serialization/ErrorContext.cs      |    75 +
 Newtonsoft.Json/Serialization/ErrorEventArgs.cs    |    58 +
 .../Serialization/ExpressionValueProvider.cs       |   114 +
 Newtonsoft.Json/Serialization/IContractResolver.cs |    46 +
 .../Serialization/IReferenceResolver.cs            |    67 +
 Newtonsoft.Json/Serialization/ITraceWriter.cs      |    28 +
 Newtonsoft.Json/Serialization/IValueProvider.cs    |    47 +
 Newtonsoft.Json/Serialization/JsonArrayContract.cs |   248 +
 .../Serialization/JsonContainerContract.cs         |   116 +
 Newtonsoft.Json/Serialization/JsonContract.cs      |   407 +
 .../Serialization/JsonDictionaryContract.cs        |   191 +
 .../Serialization/JsonDynamicContract.cs           |   119 +
 .../Serialization/JsonFormatterConverter.cs        |   152 +
 .../Serialization/JsonISerializableContract.cs     |    54 +
 Newtonsoft.Json/Serialization/JsonLinqContract.cs  |    45 +
 .../Serialization/JsonObjectContract.cs            |   147 +
 .../Serialization/JsonPrimitiveContract.cs         |    51 +
 Newtonsoft.Json/Serialization/JsonProperty.cs      |   282 +
 .../Serialization/JsonPropertyCollection.cs        |   165 +
 .../Serialization/JsonSerializerInternalBase.cs    |   141 +
 .../Serialization/JsonSerializerInternalReader.cs  |  2062 +
 .../Serialization/JsonSerializerInternalWriter.cs  |  1031 +
 .../Serialization/JsonSerializerProxy.cs           |   255 +
 .../Serialization/JsonStringContract.cs            |    45 +
 Newtonsoft.Json/Serialization/JsonTypeReflector.cs |   424 +
 .../LateBoundMetadataTypeAttribute.cs              |    60 +
 Newtonsoft.Json/Serialization/MemoryTraceWriter.cs |    81 +
 Newtonsoft.Json/Serialization/ObjectConstructor.cs |    33 +
 Newtonsoft.Json/Serialization/OnErrorAttribute.cs  |    37 +
 .../Serialization/ReflectionValueProvider.cs       |    84 +
 Newtonsoft.Json/Serialization/TraceJsonReader.cs   |   140 +
 Newtonsoft.Json/Serialization/TraceJsonWriter.cs   |   348 +
 Newtonsoft.Json/SerializationBinder.cs             |    35 +
 Newtonsoft.Json/StringEscapeHandling.cs            |    48 +
 Newtonsoft.Json/TraceLevel.cs                      |    39 +
 Newtonsoft.Json/TypeNameHandling.cs                |    61 +
 Newtonsoft.Json/Utilities/Base64Encoder.cs         |   120 +
 .../Utilities/BidirectionalDictionary.cs           |    93 +
 Newtonsoft.Json/Utilities/CollectionUtils.cs       |   281 +
 Newtonsoft.Json/Utilities/CollectionWrapper.cs     |   282 +
 Newtonsoft.Json/Utilities/ConvertUtils.cs          |   763 +
 Newtonsoft.Json/Utilities/DateTimeParser.cs        |   265 +
 Newtonsoft.Json/Utilities/DateTimeUtils.cs         |   613 +
 Newtonsoft.Json/Utilities/DictionaryWrapper.cs     |   556 +
 Newtonsoft.Json/Utilities/DynamicProxy.cs          |   113 +
 .../Utilities/DynamicProxyMetaObject.cs            |   423 +
 .../Utilities/DynamicReflectionDelegateFactory.cs  |   230 +
 Newtonsoft.Json/Utilities/DynamicUtils.cs          |   206 +
 Newtonsoft.Json/Utilities/DynamicWrapper.cs        |   266 +
 Newtonsoft.Json/Utilities/EnumUtils.cs             |   147 +
 Newtonsoft.Json/Utilities/EnumValue.cs             |    49 +
 Newtonsoft.Json/Utilities/EnumValues.cs            |    37 +
 .../ExpressionReflectionDelegateFactory.cs         |   269 +
 Newtonsoft.Json/Utilities/FSharpUtils.cs           |   156 +
 Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs |    75 +
 .../Utilities/ImmutableCollectionsUtils.cs         |   167 +
 Newtonsoft.Json/Utilities/JavaScriptUtils.cs       |   222 +
 .../LateBoundReflectionDelegateFactory.cs          |    96 +
 Newtonsoft.Json/Utilities/LinqBridge.cs            |  3014 ++
 Newtonsoft.Json/Utilities/MathUtils.cs             |   117 +
 Newtonsoft.Json/Utilities/MethodCall.cs            |    29 +
 Newtonsoft.Json/Utilities/MiscellaneousUtils.cs    |   140 +
 .../Utilities/ReflectionDelegateFactory.cs         |    72 +
 Newtonsoft.Json/Utilities/ReflectionUtils.cs       |   968 +
 Newtonsoft.Json/Utilities/StringBuffer.cs          |   107 +
 Newtonsoft.Json/Utilities/StringReference.cs       |    61 +
 Newtonsoft.Json/Utilities/StringUtils.cs           |   201 +
 Newtonsoft.Json/Utilities/ThreadSafeStore.cs       |    91 +
 Newtonsoft.Json/Utilities/TypeExtensions.cs        |   624 +
 Newtonsoft.Json/Utilities/ValidationUtils.cs       |    59 +
 Newtonsoft.Json/WriteState.cs                      |    72 +
 README.md                                          |    26 +
 Solution.FxCop                                     |    51 +
 SolutionItems/AxCrypt 2.0 Design.html              |   200 +
 SolutionItems/Axantum.targets                      |   266 +
 SolutionItems/AxantumStrongName.pub                |   Bin 0 -> 160 bytes
 SolutionItems/CustomDictionary.xml                 |    27 +
 SolutionItems/HowToBuild.txt                       |    54 +
 SolutionItems/ILMerge.exe                          |   Bin 0 -> 687104 bytes
 SolutionItems/MSBuild.Axantum.Tasks.dll            |   Bin 0 -> 19968 bytes
 SolutionItems/MSBuildVersioning.dll                |   Bin 0 -> 21504 bytes
 SolutionItems/Moq/lib/net35/Moq.dll                |   Bin 0 -> 675328 bytes
 SolutionItems/Moq/lib/net35/Moq.xml                |  6034 +++
 SolutionItems/Moq/lib/net40/Moq.dll                |   Bin 0 -> 658432 bytes
 SolutionItems/Moq/lib/net40/Moq.xml                |  5401 +++
 SolutionItems/Silverlight/Newtonsoft.Json.dll      |   Bin 0 -> 326656 bytes
 SolutionItems/SolutionItems.csproj                 |    56 +
 SolutionItems/nunit.framework.dll                  |   Bin 0 -> 147456 bytes
 SolutionItems/signtool.exe                         |   Bin 0 -> 237392 bytes
 SolutionItems/sn.exe                               |   Bin 0 -> 95552 bytes
 3357 files changed, 546481 insertions(+)

diff --git a/AboutTheSolutions.txt b/AboutTheSolutions.txt
new file mode 100644
index 0000000..4aa73b1
--- /dev/null
+++ b/AboutTheSolutions.txt
@@ -0,0 +1,23 @@
+About the Solutions
+===================
+
+There are several different solutions (.sln) that are used, depending on the target and development environment.
+
+AxCrypt.NET.sln            - The Windows Forms desktop client for Windows, Linux and Mac. Develop with Visual Studio or MonoDevelop on Windows, Linux or Mac.
+AxCrypt-MonoForAndroid.sln - The Android app. Develop with Visual Studio or MonoDevelop on Windows, Linux or Mac.
+AxCrypt-MonoMac.sln        - The MonoMac 'native' client for Mac. Develop with MonoDevelop on Mac.
+AxCrypt-MonoTouch.sln      - The iOS app for iPhone and iPad. Develop with MonoDevelop on Mac.
+
+Note that for 'AxCrypt-MonoTouch.sln' you must also build 'AxCrypt.NET.sln' in the approprate 'Debug' or 'Release' configuration, because
+the 'Axantum.AxCrypt.Core.dll' dependency must be built by that solution.
+
+About the Projects
+==================
+
+Depending on the target platform, different projects are required to build.
+
+Axantum.AxCrypt.csproj           - This is the main project for the Windows Forms-based desktop (Windows, Linux, Mac OS X) -> Axantum.AxCrypt.Windows.Forms
+Axantum.AxCrypt.Core.csproj      - All core AxCrypt functionality as a Portable Class Library for all targets.
+Axantum.AxCrypt.Desktop.csproj   - Implementations specific to full desktop .NET/Mono targets (Windows, Linux, Mac OS X) -> Axantum.AxCrypt.Core.Desktop
+Axantum.AxCrypt.Mono.csproj      - Implementations common to all targets (Windows, Linux, Mac OS X, iOS, Android) -> Axantum.AxCrypt.Core.?
+Axantum.AxCrypt.Forms.csproj     - Implementations specific to Windows Forms, not part of the main project...? -> Axantum.AxCrypt.Core.Forms
\ No newline at end of file
diff --git a/AxCrypt-MonoForAndroid.sln b/AxCrypt-MonoForAndroid.sln
new file mode 100644
index 0000000..83d4bd6
--- /dev/null
+++ b/AxCrypt-MonoForAndroid.sln
@@ -0,0 +1,24 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core.Android", "Axantum.AxCrypt.Core.Android\Axantum.AxCrypt.Core.Android.csproj", "{B81CB4AF-7DC9-4699-B0EF-089452C6F1D5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolutionItems", "SolutionItems\SolutionItems.csproj", "{A60D139A-7DBC-4BC5-976A-D89C32C913AD}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B81CB4AF-7DC9-4699-B0EF-089452C6F1D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B81CB4AF-7DC9-4699-B0EF-089452C6F1D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B81CB4AF-7DC9-4699-B0EF-089452C6F1D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B81CB4AF-7DC9-4699-B0EF-089452C6F1D5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/AxCrypt-MonoMac.sln b/AxCrypt-MonoMac.sln
new file mode 100644
index 0000000..4ee2e59
--- /dev/null
+++ b/AxCrypt-MonoMac.sln
@@ -0,0 +1,66 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mac", "Axantum.AxCrypt.Mac\Axantum.AxCrypt.Mac.csproj", "{0E46C5F6-8B43-4571-AE55-6A65C0B87525}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core", "Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj", "{966E9510-1A1D-46C7-97B5-460A0FF9B89F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono", "Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj", "{CE9E8614-8DC5-4757-9384-3C416AB61A47}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core.Test", "Axantum.AxCrypt.Core.Test\Axantum.AxCrypt.Core.Test.csproj", "{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono.Test", "Axantum.AxCrypt.Mono.Test\Axantum.AxCrypt.Mono.Test.csproj", "{79C4901A-BCAA-49AA-A789-6A8F97ACC881}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolutionItems", "SolutionItems\SolutionItems.csproj", "{A60D139A-7DBC-4BC5-976A-D89C32C913AD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core.MacOsx", "Axantum.AxCrypt.Core.MacOsx\Axantum.AxCrypt.Core.MacOsx.csproj", "{815C4EC9-5A6D-4548-89B3-046A21B20BB9}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x86 = Debug|x86
+		Release|x86 = Release|x86
+		AppStore|x86 = AppStore|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.AppStore|x86.ActiveCfg = AppStore|x86
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.AppStore|x86.Build.0 = AppStore|x86
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.Debug|x86.ActiveCfg = Debug|x86
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.Debug|x86.Build.0 = Debug|x86
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.Release|x86.ActiveCfg = Release|x86
+		{0E46C5F6-8B43-4571-AE55-6A65C0B87525}.Release|x86.Build.0 = Release|x86
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|x86.Build.0 = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|x86.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|x86.Build.0 = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|x86.Build.0 = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|x86.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|x86.Build.0 = Release|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.AppStore|x86.Build.0 = Release|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.Debug|x86.Build.0 = Debug|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.Release|x86.ActiveCfg = Release|Any CPU
+		{815C4EC9-5A6D-4548-89B3-046A21B20BB9}.Release|x86.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.AppStore|x86.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|x86.Build.0 = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|x86.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|x86.Build.0 = Release|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.AppStore|x86.ActiveCfg = AppStore|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Release|x86.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.AppStore|x86.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.AppStore|x86.Build.0 = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|x86.Build.0 = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|x86.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|x86.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = Axantum.AxCrypt.Mac\Axantum.AxCrypt.Mac.csproj
+	EndGlobalSection
+EndGlobal
diff --git a/AxCrypt-MonoTouch.sln b/AxCrypt-MonoTouch.sln
new file mode 100644
index 0000000..b7b0126
--- /dev/null
+++ b/AxCrypt-MonoTouch.sln
@@ -0,0 +1,118 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.iOS", "Axantum.AxCrypt.iOS\Axantum.AxCrypt.iOS.csproj", "{3773A07A-71B7-474C-A622-21ED8B8492DD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core", "Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj", "{966E9510-1A1D-46C7-97B5-460A0FF9B89F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BouncyCastle.AxCrypt", "BouncyCastle.AxCrypt\BouncyCastle.AxCrypt.csproj", "{3680C939-B21F-4444-B646-42FB4B29A786}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newtonsoft.Json.Portable40", "Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj", "{959F7F85-C98B-4876-971A-9036224578E4}"
+EndProject
+Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "Axantum.AxCrypt.Mono", "Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.shproj", "{E012DEFD-DD3A-411F-BDE3-6BCB12D96120}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono", "Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj", "{CE9E8614-8DC5-4757-9384-3C416AB61A47}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono.Test", "Axantum.AxCrypt.Mono.Test\Axantum.AxCrypt.Mono.Test.csproj", "{79C4901A-BCAA-49AA-A789-6A8F97ACC881}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core.Test", "Axantum.AxCrypt.Core.Test\Axantum.AxCrypt.Core.Test.csproj", "{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Debug|iPhone = Debug|iPhone
+		Release|iPhone = Release|iPhone
+		Ad-Hoc|iPhone = Ad-Hoc|iPhone
+		AppStore|iPhone = AppStore|iPhone
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|iPhone.Build.0 = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|iPhone.Build.0 = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.AppStore|iPhone.Build.0 = AppStore|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhone.Build.0 = Debug|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhone.ActiveCfg = Release|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhone.Build.0 = Release|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|iPhone.Build.0 = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|iPhone.Build.0 = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|iPhone.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.AppStore|iPhone.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.AppStore|iPhone.Build.0 = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|iPhone.ActiveCfg = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|iPhone.Build.0 = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|iPhone.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|iPhone.Build.0 = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = Axantum.AxCrypt.iOS\Axantum.AxCrypt.iOS.csproj
+	EndGlobalSection
+EndGlobal
diff --git a/AxCrypt.NET.sln b/AxCrypt.NET.sln
new file mode 100644
index 0000000..a5a090c
--- /dev/null
+++ b/AxCrypt.NET.sln
@@ -0,0 +1,89 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.30723.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono", "Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj", "{CE9E8614-8DC5-4757-9384-3C416AB61A47}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core", "Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj", "{966E9510-1A1D-46C7-97B5-460A0FF9B89F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Core.Test", "Axantum.AxCrypt.Core.Test\Axantum.AxCrypt.Core.Test.csproj", "{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Mono.Test", "Axantum.AxCrypt.Mono.Test\Axantum.AxCrypt.Mono.Test.csproj", "{79C4901A-BCAA-49AA-A789-6A8F97ACC881}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SolutionItems", "SolutionItems\SolutionItems.csproj", "{A60D139A-7DBC-4BC5-976A-D89C32C913AD}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt", "Axantum.AxCrypt\Axantum.AxCrypt.csproj", "{0998224C-F45E-4EBF-A944-7FFBCB2DB134}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Forms", "Axantum.AxCrypt.Forms\Axantum.AxCrypt.Forms.csproj", "{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Newtonsoft.Json.Portable40", "Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj", "{959F7F85-C98B-4876-971A-9036224578E4}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BouncyCastle.AxCrypt", "BouncyCastle.AxCrypt\BouncyCastle.AxCrypt.csproj", "{3680C939-B21F-4444-B646-42FB4B29A786}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Desktop", "Axantum.AxCrypt.Desktop\Axantum.AxCrypt.Desktop.csproj", "{D64DE570-3A36-49D3-95AA-9262647B04EE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.Desktop.Test", "Axantum.AxCrypt.Desktop.Test\Axantum.AxCrypt.Desktop.Test.csproj", "{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{CE9E8614-8DC5-4757-9384-3C416AB61A47}.Release|Any CPU.Build.0 = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{966E9510-1A1D-46C7-97B5-460A0FF9B89F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}.Release|Any CPU.Build.0 = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{79C4901A-BCAA-49AA-A789-6A8F97ACC881}.Release|Any CPU.Build.0 = Release|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{A60D139A-7DBC-4BC5-976A-D89C32C913AD}.Release|Any CPU.ActiveCfg = Debug|Any CPU
+		{0998224C-F45E-4EBF-A944-7FFBCB2DB134}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0998224C-F45E-4EBF-A944-7FFBCB2DB134}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0998224C-F45E-4EBF-A944-7FFBCB2DB134}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0998224C-F45E-4EBF-A944-7FFBCB2DB134}.Release|Any CPU.Build.0 = Release|Any CPU
+		{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{959F7F85-C98B-4876-971A-9036224578E4}.Release|Any CPU.Build.0 = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3680C939-B21F-4444-B646-42FB4B29A786}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D64DE570-3A36-49D3-95AA-9262647B04EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D64DE570-3A36-49D3-95AA-9262647B04EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D64DE570-3A36-49D3-95AA-9262647B04EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D64DE570-3A36-49D3-95AA-9262647B04EE}.Release|Any CPU.Build.0 = Release|Any CPU
+		{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = Axantum.AxCrypt\Axantum.AxCrypt.csproj
+		Policies = $0
+		$0.TextStylePolicy = $1
+		$1.FileWidth = 120
+		$1.inheritsSet = VisualStudio
+		$1.inheritsScope = text/plain
+		$1.scope = text/plain
+	EndGlobalSection
+EndGlobal
diff --git a/Axantum.AxCrypt.Core.Test/AboutThisAssembly.txt b/Axantum.AxCrypt.Core.Test/AboutThisAssembly.txt
new file mode 100644
index 0000000..0c44f34
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/AboutThisAssembly.txt
@@ -0,0 +1,9 @@
+About Axantum.AxCrypt.Core.Test
+
+This assembly should contain tests enough to cover Axantum.AxCrypt.Core to 100% .
+
+FxCop should pass without complaint.
+
+It must only depend on testing framework, Axantum.AxCrypt.Core and it's dependencies.
+
+In particular it must not depend on any implementation specific assembly.
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/Axantum.AxCrypt.Core.Test.csproj b/Axantum.AxCrypt.Core.Test/Axantum.AxCrypt.Core.Test.csproj
new file mode 100644
index 0000000..8df8974
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Axantum.AxCrypt.Core.Test.csproj
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{2689B1EF-29AF-4F3E-A7EC-C87FF66DC403}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Core.Test</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Core.Test</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Moq">
+      <HintPath>..\SolutionItems\Moq\lib\net40\Moq.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Xml" />
+    <Reference Include="nunit.framework">
+      <HintPath>..\SolutionItems\nunit.framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="CryptoValidation\TestRsaOeap.cs" />
+    <Compile Include="Endian.cs" />
+    <Compile Include="Extensions.cs" />
+    <Compile Include="FakeDataProtection.cs" />
+    <Compile Include="FakeDelayTimer.cs" />
+    <Compile Include="FakeFileWatcher.cs" />
+    <Compile Include="FakeIterationCalculator.cs" />
+    <Compile Include="FakePseudoRandomGenerator.cs" />
+    <Compile Include="FakeRandomGenerator.cs" />
+    <Compile Include="FakeRequestClient.cs" />
+    <Compile Include="FakeRequestServer.cs" />
+    <Compile Include="FakeProgressBackground.cs" />
+    <Compile Include="FakeSleep.cs" />
+    <Compile Include="FakeStatusChecker.cs" />
+    <Compile Include="FakeUIThread.cs" />
+    <Compile Include="FakeLauncher.cs" />
+    <Compile Include="FakeLogging.cs" />
+    <Compile Include="FakeRuntimeEnvironment.cs" />
+    <Compile Include="FakeRuntimeFileInfo.cs" />
+    <Compile Include="FakeTiming.cs" />
+    <Compile Include="FakeWebCaller.cs" />
+    <Compile Include="GlobalSuppressions.cs" />
+    <Compile Include="MockAxCryptFile.cs" />
+    <Compile Include="MockFileSystemStateActions.cs" />
+    <Compile Include="FakeAsymmetricFactory.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="SetupAssembly.cs" />
+    <Compile Include="TestActiveFile.cs" />
+    <Compile Include="TestActiveFileCollectionTests.cs" />
+    <Compile Include="TestActiveFileComparer.cs" />
+    <Compile Include="TestAxCryptFactory.cs" />
+    <Compile Include="TestCancelContext.cs" />
+    <Compile Include="TestCommandLine.cs" />
+    <Compile Include="TestCommandService.cs" />
+    <Compile Include="TestCommandServiceEventArgsTest.cs" />
+    <Compile Include="TestCounterModeCryptoTransform.cs" />
+    <Compile Include="TestDelayedAction.cs" />
+    <Compile Include="TestDelegateAction.cs" />
+    <Compile Include="TestEncryptedDataPartBlock.cs" />
+    <Compile Include="TestFactoryRegistry.cs" />
+    <Compile Include="TestFileOperation.cs" />
+    <Compile Include="TestFileOperationsController.cs" />
+    <Compile Include="TestFileOperationViewModel.cs" />
+    <Compile Include="TestFileSystemStateActions.cs" />
+    <Compile Include="TestHeaderBlock.cs" />
+    <Compile Include="TestHeaders.cs" />
+    <Compile Include="TestKnownFolder.cs" />
+    <Compile Include="TestKnownFoldersViewModel.cs" />
+    <Compile Include="TestPassphraseBase.cs" />
+    <Compile Include="TestPbkdf2HmacSha512.cs" />
+    <Compile Include="TestAsymmetricCrypto.cs" />
+    <Compile Include="TestRandomGenerator.cs" />
+    <Compile Include="TestAsymmetricUserKeysStore.cs" />
+    <Compile Include="TestV1AesCrypto.cs" />
+    <Compile Include="TestSymmetricIV.cs" />
+    <Compile Include="TestSymmetricKey.cs" />
+    <Compile Include="TestSymmetricKeyThumbprint.cs" />
+    <Compile Include="TestV1AxCryptDocument.cs" />
+    <Compile Include="TestAxCryptFile.cs" />
+    <Compile Include="TestAxCryptHeaderKeyWrap.cs" />
+    <Compile Include="TestAxCryptHMACSHA1.cs" />
+    <Compile Include="TestAxCryptReaderIdTagHeaderBlock.cs" />
+    <Compile Include="TestAxCryptReaderMagicGuid.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestAxCryptReaderPreambleHeaderBlock.cs" />
+    <Compile Include="TestAxCryptReaderVersionHeaderBlock.cs" />
+    <Compile Include="TestAxCryptStreamReader.cs" />
+    <Compile Include="TestDataHmac.cs" />
+    <Compile Include="TestDocumentHeaders.cs" />
+    <Compile Include="TestExceptions.cs" />
+    <Compile Include="TestExtensions.cs" />
+    <Compile Include="TestFileInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="TestFileLock.cs" />
+    <Compile Include="TestFileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="TestFileSystemState.cs" />
+    <Compile Include="TestFileWatcher.cs" />
+    <Compile Include="TestIdentityViewModel.cs" />
+    <Compile Include="TestIdTagHeaderBlock.cs" />
+    <Compile Include="TestInstance.cs" />
+    <Compile Include="TestIOStreams.cs" />
+    <Compile Include="TestKeyWrap.cs" />
+    <Compile Include="TestKeyWrap1HeaderBlock.cs" />
+    <Compile Include="TestKeyWrap2HeaderBlock.cs" />
+    <Compile Include="TestIterationCalculator.cs" />
+    <Compile Include="TestSalt.cs" />
+    <Compile Include="TestKnownKeys.cs" />
+    <Compile Include="TestLockingStreamTests.cs" />
+    <Compile Include="TestLogging.cs" />
+    <Compile Include="TestLogOnViewModel.cs" />
+    <Compile Include="TestMainViewModel.cs" />
+    <Compile Include="TestNDeskOptions.cs" />
+    <Compile Include="TestNewPassphraseViewModel.cs" />
+    <Compile Include="TestParallelFileOperation.cs" />
+    <Compile Include="TestPassphrase.cs" />
+    <Compile Include="TestPassphraseIdentity.cs" />
+    <Compile Include="TestPreambleHeaderBlock.cs" />
+    <Compile Include="TestProcessState.cs" />
+    <Compile Include="TestProgressContext.cs" />
+    <Compile Include="TestProgressEventArgsTest.cs" />
+    <Compile Include="TestProgressStream.cs" />
+    <Compile Include="TestResources.cs" />
+    <Compile Include="FakeStream.cs" />
+    <Compile Include="TestSessionEvent.cs" />
+    <Compile Include="TestSessionNotificationHandler.cs" />
+    <Compile Include="TestSessionNotificationMonitor.cs" />
+    <Compile Include="TestThreadWorker.cs" />
+    <Compile Include="TestThreadWorkerProgressContext.cs" />
+    <Compile Include="TestV1UnicodeFileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="TestUnrecognizedHeaderBlock .cs" />
+    <Compile Include="TestUpdateCheck.cs" />
+    <Compile Include="TestUserSettings.cs" />
+    <Compile Include="TestV1AxCryptReader.cs" />
+    <Compile Include="TestV2AsymmetricRecipientsEncryptedHeaderBlock.cs" />
+    <Compile Include="TestV2RegressionCompleteFiles.cs" />
+    <Compile Include="TestV2AesCrypto.cs" />
+    <Compile Include="TestV2AxCryptDataStreamTest.cs" />
+    <Compile Include="TestV2AxCryptDocument.cs" />
+    <Compile Include="TestV2AxCryptReader.cs" />
+    <Compile Include="TestV2CompressionEncryptedHeaderBlock.cs" />
+    <Compile Include="TestV2DocumentHeaders.cs" />
+    <Compile Include="TestV2HmacHeaderBlock.cs" />
+    <Compile Include="TestV2HmacStreamTest.cs" />
+    <Compile Include="TestV2KeyWrapHeaderBlock.cs" />
+    <Compile Include="TestV2UnicodeFileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="TestVersionHeaderBlock .cs" />
+    <Compile Include="TestViewModelBaseTest.cs" />
+    <Compile Include="TestVXAxCryptReader.cs" />
+    <Compile Include="TestWatchedFolder.cs" />
+    <Compile Include="TestWatchedFolderChangedEventArgsTest.cs" />
+    <Compile Include="TestWorkerGroup.cs" />
+    <Compile Include="TestWorkerGroupProgressContext.cs" />
+    <Compile Include="TestWorkFolderWatcher.cs" />
+    <Compile Include="TestSubKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="TestV2PlainTextLengthsEncryptedHeaderBlock.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+    <None Include="resources\david copperfield-key-%27aa ae oe%27-ulu-txt.axx" />
+    <EmbeddedResource Include="resources\Frankenstein-txt-AES256.axx" />
+    <EmbeddedResource Include="resources\Frankenstein-txt-V2AES128.axx" />
+    <None Include="resources\helloworld-key-a-txt.axx" />
+    <EmbeddedResource Include="resources\short-txt-AES256.axx" />
+    <EmbeddedResource Include="resources\snow-jpg-AES256.axx" />
+    <EmbeddedResource Include="resources\short-txt-V2AES128.axx" />
+    <EmbeddedResource Include="resources\snow-jpg-V2AES128.axx" />
+    <None Include="resources\tst-0.0b6-key-%27aaaeoe%27-medium-html.axx" />
+    <None Include="resources\uncompressable-zip.axx" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959F7F85-C98B-4876-971A-9036224578E4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj">
+      <Project>{CE9E8614-8DC5-4757-9384-3C416AB61A47}</Project>
+      <Name>Axantum.AxCrypt.Mono</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="resources\david-copperfield.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="AboutThisAssembly.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/AxantumStrongName.pfx b/Axantum.AxCrypt.Core.Test/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Core.Test/CryptoValidation/TestRsaOeap.cs b/Axantum.AxCrypt.Core.Test/CryptoValidation/TestRsaOeap.cs
new file mode 100644
index 0000000..db01826
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/CryptoValidation/TestRsaOeap.cs
@@ -0,0 +1,3123 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.Extensions;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test.CryptoValidation
+{
+    /// <summary>
+    /// ====================
+    /// pkcs-1v2-1-vec.zip
+    /// ====================
+    ///
+    /// This directory contains test vectors for RSAES-OAEP and
+    /// RSASSA-PSS as defined in PKCS #1 v2.1.
+    ///
+    /// The files:
+    ///
+    /// readme.txt              This file.
+    ///
+    /// oaep-vect.txt           Test vectors for RSAES-OAEP encryption.
+    ///
+    /// oaep-int.txt            Intermediate values for RSAES-OAEP
+    ///                         encryption and RSA decryption with CRT.
+    ///                         Also, DER-encoded RSAPrivateKey and
+    ///                         RSAPublicKey types.
+    ///
+    /// pss-vect.txt            Test vectors for RSASSA-PSS signing.
+    ///
+    /// pss-int.txt             Intermediate values for RSASSA-PSS
+    ///                         signing.
+    ///
+    /// =========================
+    /// TEST VECTORS FOR RSA-OAEP
+    /// =========================
+    ///
+    /// # This file contains test vectors for the
+    /// # RSAES-OAEP encryption scheme as defined in
+    /// # PKCS #1 v2.1. 10 RSA keys of different sizes
+    /// # have been generated. For each key, 6 random
+    /// # messages of length between 1 and 64 octets
+    /// # have been RSAES-OAEP encrypted via a random
+    /// # seed of length 20 octets.
+    /// #
+    /// # The underlying hash function is SHA-1; the
+    /// # mask generation function is MGF1 with SHA-1
+    /// # as specified in PKCS #1 v2.1.
+    /// #
+    /// # Integers are represented by strings of octets
+    /// # with the leftmost octet being the most
+    /// # significant octet. For example,
+    /// #
+    /// #           9,202,000 = (0x)8c 69 50.
+    /// #
+    /// # Key lengths:
+    /// #
+    /// # Key  1: 1024 bits
+    /// # Key  2: 1025 bits
+    /// # Key  3: 1026 bits
+    /// # Key  4: 1027 bits
+    /// # Key  5: 1028 bits
+    /// # Key  6: 1029 bits
+    /// # Key  7: 1030 bits
+    /// # Key  8: 1031 bits
+    /// # Key  9: 1536 bits
+    /// # Key 10: 2048 bits
+    /// # =============================================
+    /// </summary>
+    [TestFixture]
+    public static class TestRsaOeap
+    {
+        internal class InjectedBytesRandomGenerator : IRandomGenerator
+        {
+            private byte[] _bytes;
+
+            private int _offset = 0;
+
+            public InjectedBytesRandomGenerator(byte[] bytes)
+            {
+                _bytes = bytes;
+            }
+
+            public byte[] Generate(int count)
+            {
+                byte[] bytes = new byte[count];
+                for (int i = 0; i < bytes.Length; ++i)
+                {
+                    bytes[i] = _bytes[_offset++];
+                    _offset %= _bytes.Length;
+                }
+
+                return bytes;
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IAsymmetricFactory>(() => new FakeAsymmetricFactory("SHA1"));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        private static byte[] PositiveFromHex(string hex)
+        {
+            hex = "00" + hex.Replace(" ", String.Empty).Replace("\r", String.Empty).Replace("\n", String.Empty);
+            if (hex.Length % 2 != 0)
+            {
+                throw new ArgumentException("Odd number of characters is not allowed in a hex string.");
+            }
+
+            byte[] bytes = new byte[hex.Length / 2];
+            for (int i = 0; i < bytes.Length; ++i)
+            {
+                bytes[i] = Byte.Parse(hex.Substring(i + i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+            }
+            return bytes;
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            66 28 19 4e 12 07 3d b0 3b a9 4c da 9e f9 53 23
+            97 d5 0d ba 79 b9 87 00 4a fe fe 34
+            ";
+
+            //# Seed:
+            seed = @"
+            18 b7 76 ea 21 06 9d 69 77 6a 33 e9 6b ad 48 e1
+            dd a0 a5 ef
+            ";
+
+            //# Encryption:
+            encryption = @"
+            35 4f e6 7b 4a 12 6d 5d 35 fe 36 c7 77 79 1a 3f
+            7b a1 3d ef 48 4e 2d 39 08 af f7 22 fa d4 68 fb
+            21 69 6d e9 5d 0b e9 11 c2 d3 17 4f 8a fc c2 01
+            03 5f 7b 6d 8e 69 40 2d e5 45 16 18 c2 1a 53 5f
+            a9 d7 bf c5 b8 dd 9f c2 43 f8 cf 92 7d b3 13 22
+            d6 e8 81 ea a9 1a 99 61 70 e6 57 a0 5a 26 64 26
+            d9 8c 88 00 3f 84 77 c1 22 70 94 a0 d9 fa 1e 8c
+            40 24 30 9c e1 ec cc b5 21 00 35 d4 7a c7 2e 8a
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            75 0c 40 47 f5 47 e8 e4 14 11 85 65 23 29 8a c9
+            ba e2 45 ef af 13 97 fb e5 6f 9d d5
+            ";
+
+            //# Seed:
+            seed = @"
+            0c c7 42 ce 4a 9b 7f 32 f9 51 bc b2 51 ef d9 25
+            fe 4f e3 5f
+            ";
+
+            //# Encryption:
+            encryption = @"
+            64 0d b1 ac c5 8e 05 68 fe 54 07 e5 f9 b7 01 df
+            f8 c3 c9 1e 71 6c 53 6f c7 fc ec 6c b5 b7 1c 11
+            65 98 8d 4a 27 9e 15 77 d7 30 fc 7a 29 93 2e 3f
+            00 c8 15 15 23 6d 8d 8e 31 01 7a 7a 09 df 43 52
+            d9 04 cd eb 79 aa 58 3a dc c3 1e a6 98 a4 c0 52
+            83 da ba 90 89 be 54 91 f6 7c 1a 4e e4 8d c7 4b
+            bb e6 64 3a ef 84 66 79 b4 cb 39 5a 35 2d 5e d1
+            15 91 2d f6 96 ff e0 70 29 32 94 6d 71 49 2b 44
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            d9 4a e0 83 2e 64 45 ce 42 33 1c b0 6d 53 1a 82
+            b1 db 4b aa d3 0f 74 6d c9 16 df 24 d4 e3 c2 45
+            1f ff 59 a6 42 3e b0 e1 d0 2d 4f e6 46 cf 69 9d
+            fd 81 8c 6e 97 b0 51
+            ";
+
+            //# Seed:
+            seed = @"
+            25 14 df 46 95 75 5a 67 b2 88 ea f4 90 5c 36 ee
+            c6 6f d2 fd
+            ";
+
+            //# Encryption:
+            encryption = @"
+            42 37 36 ed 03 5f 60 26 af 27 6c 35 c0 b3 74 1b
+            36 5e 5f 76 ca 09 1b 4e 8c 29 e2 f0 be fe e6 03
+            59 5a a8 32 2d 60 2d 2e 62 5e 95 eb 81 b2 f1 c9
+            72 4e 82 2e ca 76 db 86 18 cf 09 c5 34 35 03 a4
+            36 08 35 b5 90 3b c6 37 e3 87 9f b0 5e 0e f3 26
+            85 d5 ae c5 06 7c d7 cc 96 fe 4b 26 70 b6 ea c3
+            06 6b 1f cf 56 86 b6 85 89 aa fb 7d 62 9b 02 d8
+            f8 62 5c a3 83 36 24 d4 80 0f b0 81 b1 cf 94 eb
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            52 e6 50 d9 8e 7f 2a 04 8b 4f 86 85 21 53 b9 7e
+            01 dd 31 6f 34 6a 19 f6 7a 85
+            ";
+
+            //# Seed:
+            seed = @"
+            c4 43 5a 3e 1a 18 a6 8b 68 20 43 62 90 a3 7c ef
+            b8 5d b3 fb
+            ";
+
+            //# Encryption:
+            encryption = @"
+            45 ea d4 ca 55 1e 66 2c 98 00 f1 ac a8 28 3b 05
+            25 e6 ab ae 30 be 4b 4a ba 76 2f a4 0f d3 d3 8e
+            22 ab ef c6 97 94 f6 eb bb c0 5d db b1 12 16 24
+            7d 2f 41 2f d0 fb a8 7c 6e 3a cd 88 88 13 64 6f
+            d0 e4 8e 78 52 04 f9 c3 f7 3d 6d 82 39 56 27 22
+            dd dd 87 71 fe c4 8b 83 a3 1e e6 f5 92 c4 cf d4
+            bc 88 17 4f 3b 13 a1 12 aa e3 b9 f7 b8 0e 0f c6
+            f7 25 5b a8 80 dc 7d 80 21 e2 2a d6 a8 5f 07 55
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            8d a8 9f d9 e5 f9 74 a2 9f ef fb 46 2b 49 18 0f
+            6c f9 e8 02
+            ";
+
+            //# Seed:
+            seed = @"
+            b3 18 c4 2d f3 be 0f 83 fe a8 23 f5 a7 b4 7e d5
+            e4 25 a3 b5
+            ";
+
+            //# Encryption:
+            encryption = @"
+            36 f6 e3 4d 94 a8 d3 4d aa cb a3 3a 21 39 d0 0a
+            d8 5a 93 45 a8 60 51 e7 30 71 62 00 56 b9 20 e2
+            19 00 58 55 a2 13 a0 f2 38 97 cd cd 73 1b 45 25
+            7c 77 7f e9 08 20 2b ef dd 0b 58 38 6b 12 44 ea
+            0c f5 39 a0 5d 5d 10 32 9d a4 4e 13 03 0f d7 60
+            dc d6 44 cf ef 20 94 d1 91 0d 3f 43 3e 1c 7c 6d
+            d1 8b c1 f2 df 7f 64 3d 66 2f b9 dd 37 ea d9 05
+            91 90 f4 fa 66 ca 39 e8 69 c4 eb 44 9c bd c4 39
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example1_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample1(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            26 52 10 50 84 42 71
+            ";
+
+            //# Seed:
+            seed = @"
+            e4 ec 09 82 c2 33 6f 3a 67 7f 6a 35 61 74 eb 0c
+            e8 87 ab c2
+            ";
+
+            //# Encryption:
+            encryption = @"
+            42 ce e2 61 7b 1e ce a4 db 3f 48 29 38 6f bd 61
+            da fb f0 38 e1 80 d8 37 c9 63 66 df 24 c0 97 b4
+            ab 0f ac 6b df 59 0d 82 1c 9f 10 64 2e 68 1a d0
+            5b 8d 78 b3 78 c0 f4 6c e2 fa d6 3f 74 e0 ad 3d
+            f0 6b 07 5d 7e b5 f5 63 6f 8d 40 3b 90 59 ca 76
+            1b 5c 62 bb 52 aa 45 00 2e a7 0b aa ce 08 de d2
+            43 b9 d8 cb d6 2a 68 ad e2 65 83 2b 56 56 4e 43
+            a6 fa 42 ed 19 9a 09 97 69 74 2d f1 53 9e 82 55
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 1.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            8f f0 0c aa 60 5c 70 28 30 63 4d 9a 6c 3d 42 c6
+            52 b5 8c f1 d9 2f ec 57 0b ee e7
+            ";
+
+            //# Seed:
+            seed = @"
+            8c 40 7b 5e c2 89 9e 50 99 c5 3e 8c e7 93 bf 94
+            e7 1b 17 82
+            ";
+
+            //# Encryption:
+            encryption = @"
+            01 81 af 89 22 b9 fc b4 d7 9d 92 eb e1 98 15 99
+            2f c0 c1 43 9d 8b cd 49 13 98 a0 f4 ad 3a 32 9a
+            5b d9 38 55 60 db 53 26 83 c8 b7 da 04 e4 b1 2a
+            ed 6a ac df 47 1c 34 c9 cd a8 91 ad dc c2 df 34
+            56 65 3a a6 38 2e 9a e5 9b 54 45 52 57 eb 09 9d
+            56 2b be 10 45 3f 2b 6d 13 c5 9c 02 e1 0f 1f 8a
+            bb 5d a0 d0 57 09 32 da cf 2d 09 01 db 72 9d 0f
+            ef cc 05 4e 70 96 8e a5 40 c8 1b 04 bc ae fe 72
+            0e
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            2d
+            ";
+
+            //# Seed:
+            seed = @"
+            b6 00 cf 3c 2e 50 6d 7f 16 77 8c 91 0d 3a 8b 00
+            3e ee 61 d5
+            ";
+
+            //# Encryption:
+            encryption = @"
+            01 87 59 ff 1d f6 3b 27 92 41 05 62 31 44 16 a8
+            ae af 2a c6 34 b4 6f 94 0a b8 2d 64 db f1 65 ee
+            e3 30 11 da 74 9d 4b ab 6e 2f cd 18 12 9c 9e 49
+            27 7d 84 53 11 2b 42 9a 22 2a 84 71 b0 70 99 39
+            98 e7 58 86 1c 4d 3f 6d 74 9d 91 c4 29 0d 33 2c
+            7a 4a b3 f7 ea 35 ff 3a 07 d4 97 c9 55 ff 0f fc
+            95 00 6b 62 c6 d2 96 81 0d 9b fa b0 24 19 6c 79
+            34 01 2c 2d f9 78 ef 29 9a ba 23 99 40 cb a1 02
+            45
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            74 fc 88 c5 1b c9 0f 77 af 9d 5e 9a 4a 70 13 3d
+            4b 4e 0b 34 da 3c 37 c7 ef 8e
+            ";
+
+            //# Seed:
+            seed = @"
+            a7 37 68 ae ea a9 1f 9d 8c 1e d6 f9 d2 b6 34 67
+            f0 7c ca e3
+            ";
+
+            //# Encryption:
+            encryption = @"
+            01 88 02 ba b0 4c 60 32 5e 81 c4 96 23 11 f2 be
+            7c 2a dc e9 30 41 a0 07 19 c8 8f 95 75 75 f2 c7
+            9f 1b 7b c8 ce d1 15 c7 06 b3 11 c0 8a 2d 98 6c
+            a3 b6 a9 33 6b 14 7c 29 c6 f2 29 40 9d de c6 51
+            bd 1f dd 5a 0b 7f 61 0c 99 37 fd b4 a3 a7 62 36
+            4b 8b 32 06 b4 ea 48 5f d0 98 d0 8f 63 d4 aa 8b
+            b2 69 7d 02 7b 75 0c 32 d7 f7 4e af 51 80 d2 e9
+            b6 6b 17 cb 2f a5 55 23 bc 28 0d a1 0d 14 be 20
+            53
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            a7 eb 2a 50 36 93 1d 27 d4 e8 91 32 6d 99 69 2f
+            fa dd a9 bf 7e fd 3e 34 e6 22 c4 ad c0 85 f7 21
+            df e8 85 07 2c 78 a2 03 b1 51 73 9b e5 40 fa 8c
+            15 3a 10 f0 0a
+            ";
+
+            //# Seed:
+            seed = @"
+            9a 7b 3b 0e 70 8b d9 6f 81 90 ec ab 4f b9 b2 b3
+            80 5a 81 56
+            ";
+
+            //# Encryption:
+            encryption = @"
+            00 a4 57 8c bc 17 63 18 a6 38 fb a7 d0 1d f1 57
+            46 af 44 d4 f6 cd 96 d7 e7 c4 95 cb f4 25 b0 9c
+            64 9d 32 bf 88 6d a4 8f ba f9 89 a2 11 71 87 ca
+            fb 1f b5 80 31 76 90 e3 cc d4 46 92 0b 7a f8 2b
+            31 db 58 04 d8 7d 01 51 4a cb fa 91 56 e7 82 f8
+            67 f6 be d9 44 9e 0e 9a 2c 09 bc ec c6 aa 08 76
+            36 96 5e 34 b3 ec 76 6f 2f e2 e4 30 18 a2 fd de
+            b1 40 61 6a 0e 9d 82 e5 33 10 24 ee 06 52 fc 76
+            41
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            2e f2 b0 66 f8 54 c3 3f 3b dc bb 59 94 a4 35 e7
+            3d 6c 6c
+            ";
+
+            //# Seed:
+            seed = @"
+            eb 3c eb bc 4a dc 16 bb 48 e8 8c 8a ec 0e 34 af
+            7f 42 7f d3
+            ";
+
+            //# Encryption:
+            encryption = @"
+            00 eb c5 f5 fd a7 7c fd ad 3c 83 64 1a 90 25 e7
+            7d 72 d8 a6 fb 33 a8 10 f5 95 0f 8d 74 c7 3e 8d
+            93 1e 86 34 d8 6a b1 24 62 56 ae 07 b6 00 5b 71
+            b7 f2 fb 98 35 12 18 33 1c e6 9b 8f fb dc 9d a0
+            8b bc 9c 70 4f 87 6d eb 9d f9 fc 2e c0 65 ca d8
+            7f 90 90 b0 7a cc 17 aa 7f 99 7b 27 ac a4 88 06
+            e8 97 f7 71 d9 51 41 fe 45 26 d8 a5 30 1b 67 86
+            27 ef ab 70 7f d4 0f be bd 6e 79 2a 25 61 3e 7a
+            ec
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example2_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample2(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+            8a 7f b3 44 c8 b6 cb 2c f2 ef 1f 64 3f 9a 32 18
+            f6 e1 9b ba 89 c0
+            ";
+
+            //# Seed:
+            seed = @"
+            4c 45 cf 4d 57 c9 8e 3d 6d 20 95 ad c5 1c 48 9e
+            b5 0d ff 84
+            ";
+
+            //# Encryption:
+            encryption = @"
+            01 08 39 ec 20 c2 7b 90 52 e5 5b ef b9 b7 7e 6f
+            c2 6e 90 75 d7 a5 43 78 c6 46 ab df 51 e4 45 bd
+            57 15 de 81 78 9f 56 f1 80 3d 91 70 76 4a 9e 93
+            cb 78 79 86 94 02 3e e7 39 3c e0 4b c5 d8 f8 c5
+            a5 2c 17 1d 43 83 7e 3a ca 62 f6 09 eb 0a a5 ff
+            b0 96 0e f0 41 98 dd 75 4f 57 f7 fb e6 ab f7 65
+            cf 11 8b 4c a4 43 b2 3b 5a ab 26 6f 95 23 26 ac
+            45 81 10 06 44 32 5f 8b 72 1a cd 5d 04 ff 14 ef
+            3a
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 2.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+08 78 20 b5 69 e8 fa 8d
+            ";
+
+            //# Seed:
+            seed = @"
+8c ed 6b 19 62 90 80 57 90 e9 09 07 40 15 e6 a2
+0b 0c 48 94
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 6a 04 85 d9 6a eb d9 6b 43 82 08 50 99 b9 62
+e6 a2 bd ec 3d 90 c8 db 62 5e 14 37 2d e8 5e 2d
+5b 7b aa b6 5c 8f af 91 bb 55 04 fb 49 5a fc e5
+c9 88 b3 f6 a5 2e 20 e1 d6 cb d3 56 6c 5c d1 f2
+b8 31 8b b5 42 cc 0e a2 5c 4a ab 99 32 af a2 07
+60 ea dd ec 78 43 96 a0 7e a0 ef 24 d4 e6 f4 d3
+7e 50 52 a7 a3 1e 14 6a a4 80 a1 11 bb e9 26 40
+13 07 e0 0f 41 00 33 84 2b 6d 82 fe 5c e4 df ae
+80
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+46 53 ac af 17 19 60 b0 1f 52 a7 be 63 a3 ab 21
+dc 36 8e c4 3b 50 d8 2e c3 78 1e 04
+            ";
+
+            //# Seed:
+            seed = @"
+b4 29 1d 65 67 55 08 48 cc 15 69 67 c8 09 ba ab
+6c a5 07 f0
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 4d b8 9c 78 02 98 9b e0 78 38 47 86 30 84 94
+1b f2 09 d7 61 98 7e 38 f9 7c b5 f6 f1 bc 88 da
+72 a5 0b 73 eb af 11 c8 79 c4 f9 5d f3 7b 85 0b
+8f 65 d7 62 2e 25 b1 b8 89 e8 0f e8 0b ac a2 06
+9d 6e 0e 1d 82 99 53 fc 45 90 69 de 98 ea 97 98
+b4 51 e5 57 e9 9a bf 8f e3 d9 cc f9 09 6e bb f3
+e5 25 5d 3b 4e 1c 6d 2e ca df 06 7a 35 9e ea 86
+40 5a cd 47 d5 e1 65 51 7c ca fd 47 d6 db ee 4b
+f5
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+d9 4c d0 e0 8f a4 04 ed 89
+            ";
+
+            //# Seed:
+            seed = @"
+ce 89 28 f6 05 95 58 25 40 08 ba dd 97 94 fa dc
+d2 fd 1f 65
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 39 bc e6 81 03 24 41 52 88 77 d6 d1 c8 bb 28
+aa 3b c9 7f 1d f5 84 56 36 18 99 57 97 68 38 44
+ca 86 66 47 32 f4 be d7 a0 aa b0 83 aa ab fb 72
+38 f5 82 e3 09 58 c2 02 4e 44 e5 70 43 b9 79 50
+fd 54 3d a9 77 c9 0c dd e5 33 7d 61 84 42 f9 9e
+60 d7 78 3a b5 9c e6 dd 9d 69 c4 7a d1 e9 62 be
+c2 2d 05 89 5c ff 8d 3f 64 ed 52 61 d9 2b 26 78
+51 03 93 48 49 90 ba 3f 7f 06 81 8a e6 ff ce 8a
+3a
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+6c c6 41 b6 b6 1e 6f 96 39 74 da d2 3a 90 13 28
+4e f1
+            ";
+
+            //# Seed:
+            seed = @"
+6e 29 79 f5 2d 68 14 a5 7d 83 b0 90 05 48 88 f1
+19 a5 b9 a3
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 99 4c 62 af d7 6f 49 8b a1 fd 2c f6 42 85 7f
+ca 81 f4 37 3c b0 8f 1c ba ee 6f 02 5c 3b 51 2b
+42 c3 e8 77 91 13 47 66 48 03 9d be 04 93 f9 24
+62 92 fa c2 89 50 60 0e 7c 0f 32 ed f9 c8 1b 9d
+ec 45 c3 bd e0 cc 8d 88 47 59 01 69 90 7b 7d c5
+99 1c eb 29 bb 07 14 d6 13 d9 6d f0 f1 2e c5 d8
+d3 50 7c 8e e7 ae 78 dd 83 f2 16 fa 61 de 10 03
+63 ac a4 8a 7e 91 4a e9 f4 2d df be 94 3b 09 d9
+a0
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+df 51 51 83 2b 61 f4 f2 58 91 fb 41 72 f3 28 d2
+ed df 83 71 ff cf db e9 97 93 92 95 f3 0e ca 69
+18 01 7c fd a1 15 3b f7 a6 af 87 59 32 23
+            ";
+
+            //# Seed:
+            seed = @"
+2d 76 0b fe 38 c5 9d e3 4c dc 8b 8c 78 a3 8e 66
+28 4a 2d 27
+            ";
+
+            //# Encryption:
+            encryption = @"
+01 62 04 2f f6 96 95 92 a6 16 70 31 81 1a 23 98
+34 ce 63 8a bf 54 fe c8 b9 94 78 12 2a fe 2e e6
+7f 8c 5b 18 b0 33 98 05 bf db c5 a4 e6 72 0b 37
+c5 9c fb a9 42 46 4c 59 7f f5 32 a1 19 82 15 45
+fd 2e 59 b1 14 e6 1d af 71 82 05 29 f5 02 9c f5
+24 95 43 27 c3 4e c5 e6 f5 ba 7e fc c4 de 94 3a
+b8 ad 4e d7 87 b1 45 43 29 f7 0d b7 98 a3 a8 f4
+d9 2f 82 74 e2 b2 94 8a de 62 7c e8 ee 33 e4 3c
+60
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example3_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample3(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+3c 3b ad 89 3c 54 4a 6d 52 0a b0 22 31 91 88 c8
+d5 04 b7 a7 88 b8 50 90 3b 85 97 2e aa 18 55 2e
+11 34 a7 ad 60 98 82 62 54 ff 7a b6 72 b3 d8 eb
+31 58 fa c6 d4 cb ae f1
+            ";
+
+            //# Seed:
+            seed = @"
+f1 74 77 9c 5f d3 cf e0 07 ba dc b7 a3 6c 9b 55
+bf cf bf 0e
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 11 20 51 e7 5d 06 49 43 bc 44 78 07 5e 43 48
+2f d5 9c ee 06 79 de 68 93 ee c3 a9 43 da a4 90
+b9 69 1c 93 df c0 46 4b 66 23 b9 f3 db d3 e7 00
+83 26 4f 03 4b 37 4f 74 16 4e 1a 00 76 37 25 e5
+74 74 4b a0 b9 db 83 43 4f 31 df 96 f6 e2 a2 6f
+6d 8e ba 34 8b d4 68 6c 22 38 ac 07 c3 7a ac 37
+85 d1 c7 ee a2 f8 19 fd 91 49 17 98 ed 8e 9c ef
+5e 43 b7 81 b0 e0 27 6e 37 c4 3f f9 49 2d 00 57
+30
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 3.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+4a 86 60 95 34 ee 43 4a 6c bc a3 f7 e9 62 e7 6d
+45 5e 32 64 c1 9f 60 5f 6e 5f f6 13 7c 65 c5 6d
+7f b3 44 cd 52 bc 93 37 4f 3d 16 6c 9f 0c 6f 9c
+50 6b ad 19 33 09 72 d2
+            ";
+
+            //# Seed:
+            seed = @"
+1c ac 19 ce 99 3d ef 55 f9 82 03 f6 85 28 96 c9
+5c cc a1 f3
+            ";
+
+            //# Encryption:
+            encryption = @"
+04 cc e1 96 14 84 5e 09 41 52 a3 fe 18 e5 4e 33
+30 c4 4e 5e fb c6 4a e1 68 86 cb 18 69 01 4c c5
+78 1b 1f 8f 9e 04 53 84 d0 11 2a 13 5c a0 d1 2e
+9c 88 a8 e4 06 34 16 de aa e3 84 4f 60 d6 e9 6f
+e1 55 14 5f 45 25 b9 a3 44 31 ca 37 66 18 0f 70
+e1 5a 5e 5d 8e 8b 1a 51 6f f8 70 60 9f 13 f8 96
+93 5c ed 18 82 79 a5 8e d1 3d 07 11 42 77 d7 5c
+65 68 60 7e 0a b0 92 fd 80 3a 22 3e 4a 8e e0 b1
+a8
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+b0 ad c4 f3 fe 11 da 59 ce 99 27 73 d9 05 99 43
+c0 30 46 49 7e e9 d9 f9 a0 6d f1 16 6d b4 6d 98
+f5 8d 27 ec 07 4c 02 ee e6 cb e2 44 9c 8b 9f c5
+08 0c 5c 3f 44 33 09 25 12 ec 46 aa 79 37 43 c8
+            ";
+
+            //# Seed:
+            seed = @"
+f5 45 d5 89 75 85 e3 db 71 aa 0c b8 da 76 c5 1d
+03 2a e9 63
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 97 b6 98 c6 16 56 45 b3 03 48 6f bf 5a 2a 44
+79 c0 ee 85 88 9b 54 1a 6f 0b 85 8d 6b 65 97 b1
+3b 85 4e b4 f8 39 af 03 39 9a 80 d7 9b da 65 78
+c8 41 f9 0d 64 57 15 b2 80 d3 71 43 99 2d d1 86
+c8 0b 94 9b 77 5c ae 97 37 0e 4e c9 74 43 13 6c
+6d a4 84 e9 70 ff db 13 23 a2 08 47 82 1d 3b 18
+38 1d e1 3b b4 9a ae a6 65 30 c4 a4 b8 27 1f 3e
+ae 17 2c d3 66 e0 7e 66 36 f1 01 9d 2a 28 ae d1
+5e
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+bf 6d 42 e7 01 70 7b 1d 02 06 b0 c8 b4 5a 1c 72
+64 1f f1 28 89 21 9a 82 bd ea 96 5b 5e 79 a9 6b
+0d 01 63 ed 9d 57 8e c9 ad a2 0f 2f bc f1 ea 3c
+40 89 d8 34 19 ba 81 b0 c6 0f 36 06 da 99
+            ";
+
+            //# Seed:
+            seed = @"
+ad 99 7f ee f7 30 d6 ea 7b e6 0d 0d c5 2e 72 ea
+cb fd d2 75
+            ";
+
+            //# Encryption:
+            encryption = @"
+03 01 f9 35 e9 c4 7a bc b4 8a cb be 09 89 5d 9f
+59 71 af 14 83 9d a4 ff 95 41 7e e4 53 d1 fd 77
+31 90 72 bb 72 97 e1 b5 5d 75 61 cd 9d 1b b2 4c
+1a 9a 37 c6 19 86 43 08 24 28 04 87 9d 86 eb d0
+01 dc e5 18 39 75 e1 50 69 89 b7 0e 5a 83 43 41
+54 d5 cb fd 6a 24 78 7e 60 eb 0c 65 8d 2a c1 93
+30 2d 11 92 c6 e6 22 d4 a1 2a d4 b5 39 23 bc a2
+46 df 31 c6 39 5e 37 70 2c 6a 78 ae 08 1f b9 d0
+65
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+fb 2e f1 12 f5 e7 66 eb 94 01 92 97 93 47 94 f7
+be 2f 6f c1 c5 8e
+            ";
+
+            //# Seed:
+            seed = @"
+13 64 54 df 57 30 f7 3c 80 7a 7e 40 d8 c1 a3 12
+ac 5b 9d d3
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 d1 10 ad 30 af b7 27 be b6 91 dd 0c f1 7d 0a
+f1 a1 e7 fa 0c c0 40 ec 1a 4b a2 6a 42 c5 9d 0a
+79 6a 2e 22 c8 f3 57 cc c9 8b 65 19 ac eb 68 2e
+94 5e 62 cb 73 46 14 a5 29 40 7c d4 52 be e3 e4
+4f ec e8 42 3c c1 9e 55 54 8b 8b 99 4b 84 9c 7e
+cd e4 93 3e 76 03 7e 1d 0c e4 42 75 b0 87 10 c6
+8e 43 01 30 b9 29 73 0e d7 7e 09 b0 15 64 2c 55
+93 f0 4e 4f fb 94 10 79 81 02 a8 e9 6f fd fe 11
+e4
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+28 cc d4 47 bb 9e 85 16 6d ab b9 e5 b7 d1 ad ad
+c4 b9 d3 9f 20 4e 96 d5 e4 40 ce 9a d9 28 bc 1c
+22 84
+            ";
+
+            //# Seed:
+            seed = @"
+bc a8 05 7f 82 4b 2e a2 57 f2 86 14 07 ee f6 3d
+33 20 86 81
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 db b8 a7 43 9d 90 ef d9 19 a3 77 c5 4f ae 8f
+e1 1e c5 8c 3b 85 83 62 e2 3a d1 b8 a4 43 10 79
+90 66 b9 93 47 aa 52 56 91 d2 ad c5 8d 9b 06 e3
+4f 28 8c 17 03 90 c5 f0 e1 1c 0a a3 64 59 59 f1
+8e e7 9e 8f 2b e8 d7 ac 5c 23 d0 61 f1 8d d7 4b
+8c 5f 2a 58 fc b5 eb 0c 54 f9 9f 01 a8 32 47 56
+82 92 53 65 83 34 09 48 d7 a8 c9 7c 4a cd 1e 98
+d1 e2 9d c3 20 e9 7a 26 05 32 a8 aa 7a 75 8a 1e
+c2
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example4_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample4(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+f2 22 42 75 1e c6 b1
+            ";
+
+            //# Seed:
+            seed = @"
+2e 7e 1e 17 f6 47 b5 dd d0 33 e1 54 72 f9 0f 68
+12 f3 ac 4e
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 a5 ff a4 76 8c 8b be ca ee 2d b7 7e 8f 2e ec
+99 59 59 33 54 55 20 83 5e 5b a7 db 94 93 d3 e1
+7c dd ef e6 a5 f5 67 62 44 71 90 8d b4 e2 d8 3a
+0f be e6 06 08 fc 84 04 95 03 b2 23 4a 07 dc 83
+b2 7b 22 84 7a d8 92 0f f4 2f 67 4e f7 9b 76 28
+0b 00 23 3d 2b 51 b8 cb 27 03 a9 d4 2b fb c8 25
+0c 96 ec 32 c0 51 e5 7f 1b 4b a5 28 db 89 c3 7e
+4c 54 e2 7e 6e 64 ac 69 63 5a e8 87 d9 54 16 19
+a9
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 4.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+af 71 a9 01 e3 a6 1d 31 32 f0 fc 1f db 47 4f 9e
+a6 57 92 57 ff c2 4d 16 41 70 14 5b 3d bd e8
+            ";
+
+            //# Seed:
+            seed = @"
+44 c9 2e 28 3f 77 b9 49 9c 60 3d 96 36 60 c8 7d
+2f 93 94 61
+            ";
+
+            //# Encryption:
+            encryption = @"
+03 60 46 a4 a4 7d 9e d3 ba 9a 89 13 9c 10 50 38
+eb 74 92 b0 5a 5d 68 bf d5 3a cc ff 45 97 f7 a6
+86 51 b4 7b 4a 46 27 d9 27 e4 85 ee d7 b4 56 64
+20 e8 b4 09 87 9e 5d 60 6e ae 25 1d 22 a5 df 79
+9f 79 20 bf c1 17 b9 92 57 2a 53 b1 26 31 46 bc
+ea 03 38 5c c5 e8 53 c9 a1 01 c8 c3 e1 bd a3 1a
+51 98 07 49 6c 6c b5 e5 ef b4 08 82 3a 35 2b 8f
+a0 66 1f b6 64 ef ad d5 93 de b9 9f ff 5e d0 00
+e5
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+a3 b8 44 a0 82 39 a8 ac 41 60 5a f1 7a 6c fd a4
+d3 50 13 65 85 90 3a 41 7a 79 26 87 60 51 9a 4b
+4a c3 30 3e c7 3f 0f 87 cf b3 23 99
+            ";
+
+            //# Seed:
+            seed = @"
+cb 28 f5 86 06 59 fc ee e4 9c 3e ea fc e6 25 a7
+08 03 bd 32
+            ";
+
+            //# Encryption:
+            encryption = @"
+03 d6 eb 65 4e dc e6 15 bc 59 f4 55 26 5e d4 e5
+a1 82 23 cb b9 be 4e 40 69 b4 73 80 4d 5d e9 6f
+54 dc aa a6 03 d0 49 c5 d9 4a a1 47 0d fc d2 25
+40 66 b7 c7 b6 1f f1 f6 f6 77 0e 32 15 c5 13 99
+fd 4e 34 ec 50 82 bc 48 f0 89 84 0a d0 43 54 ae
+66 dc 0f 1b d1 8e 46 1a 33 cc 12 58 b4 43 a2 83
+7a 6d f2 67 59 aa 23 02 33 49 86 f8 73 80 c9 cc
+9d 53 be 9f 99 60 5d 2c 9a 97 da 7b 09 15 a4 a7
+ad
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+30 8b 0e cb d2 c7 6c b7 7f c6 f7 0c 5e dd 23 3f
+d2 f2 09 29 d6 29 f0 26 95 3b b6 2a 8f 4a 3a 31
+4b de 19 5d e8 5b 5f 81 6d a2 aa b0 74 d2 6c b6
+ac dd f3 23 ae 3b 9c 67 8a c3 cf 12 fb dd e7
+            ";
+
+            //# Seed:
+            seed = @"
+22 85 f4 0d 77 04 82 f9 a9 ef a2 c7 2c b3 ac 55
+71 6d c0 ca
+            ";
+
+            //# Encryption:
+            encryption = @"
+07 70 95 21 81 64 9f 9f 9f 07 ff 62 6f f3 a2 2c
+35 c4 62 44 3d 90 5d 45 6a 9f d0 bf f4 3c ac 2c
+a7 a9 f5 54 e9 47 8b 9a cc 3a c8 38 b0 20 40 ff
+d3 e1 84 7d e2 e4 25 39 29 f9 dd 9e e4 04 43 25
+a9 b0 5c ab b8 08 b2 ee 84 0d 34 e1 5d 10 5a 3f
+1f 7b 27 69 5a 1a 07 a2 d7 3f e0 8e ca aa 3c 9c
+9d 4d 5a 89 ff 89 0d 54 72 7d 7a e4 0c 0e c1 a8
+dd 86 16 5d 8e e2 c6 36 81 41 01 6a 48 b5 5b 69
+67
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+15 c5 b9 ee 11 85
+            ";
+
+            //# Seed:
+            seed = @"
+49 fa 45 d3 a7 8d d1 0d fd 57 73 99 d1 eb 00 af
+7e ed 55 13
+            ";
+
+            //# Encryption:
+            encryption = @"
+08 12 b7 67 68 eb cb 64 2d 04 02 58 e5 f4 44 1a
+01 85 21 bd 96 68 7e 6c 5e 89 9f cd 6c 17 58 8f
+f5 9a 82 cc 8a e0 3a 4b 45 b3 12 99 af 17 88 c3
+29 f7 dc d2 85 f8 cf 4c ed 82 60 6b 97 61 26 71
+a4 5b ed ca 13 34 42 14 4d 16 17 d1 14 f8 02 85
+7f 0f 9d 73 97 51 c5 7a 3f 9e e4 00 91 2c 61 e2
+e6 99 2b e0 31 a4 3d d4 8f a6 ba 14 ee f7 c4 22
+b5 ed c4 e7 af a0 4f dd 38 f4 02 d1 c8 bb 71 9a
+bf
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+21 02 6e 68 00 c7 fa 72 8f ca ab a0 d1 96 ae 28
+d7 a2 ac 4f fd 8a bc e7 94 f0 98 5f 60 c8 a6 73
+72 77 36 5d 3f ea 11 db 89 23 a2 02 9a
+            ";
+
+            //# Seed:
+            seed = @"
+f0 28 74 13 23 4c c5 03 47 24 a0 94 c4 58 6b 87
+af f1 33 fc
+            ";
+
+            //# Encryption:
+            encryption = @"
+07 b6 0e 14 ec 95 4b fd 29 e6 0d 00 47 e7 89 f5
+1d 57 18 6c 63 58 99 03 30 67 93 ce d3 f6 82 41
+c7 43 52 9a ba 6a 63 74 f9 2e 19 e0 16 3e fa 33
+69 7e 19 6f 76 61 df aa a4 7a ac 6b de 5e 51 de
+b5 07 c7 2c 58 9a 2c a1 69 3d 96 b1 46 03 81 24
+9b 2c db 9e ac 44 76 9f 24 89 c5 d3 d2 f9 9f 0e
+e3 c7 ee 5b f6 4a 5a c7 9c 42 bd 43 3f 14 9b e8
+cb 59 54 83 61 64 05 95 51 3c 97 af 7b c2 50 97
+23
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example5_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample5(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+54 1e 37 b6 8b 6c 88 72 b8 4c 02
+            ";
+
+            //# Seed:
+            seed = @"
+d9 fb a4 5c 96 f2 1e 6e 26 d2 9e b2 cd cb 65 85
+be 9c b3 41
+            ";
+
+            //# Encryption:
+            encryption = @"
+08 c3 6d 4d da 33 42 3b 2e d6 83 0d 85 f6 41 1b
+a1 dc f4 70 a1 fa e0 eb ef ee 7c 08 9f 25 6c ef
+74 cb 96 ea 69 c3 8f 60 f3 9a be e4 41 29 bc b4
+c9 2d e7 f7 97 62 3b 20 07 4e 3d 9c 28 99 70 1e
+d9 07 1e 1e fa 0b dd 84 d4 c3 e5 13 03 02 d8 f0
+24 0b ab a4 b8 4a 71 cc 03 2f 22 35 a5 ff 0f ae
+27 7c 3e 8f 91 12 be f4 4c 9a e2 0d 17 5f c9 a4
+05 8b fc 93 0b a3 1b 02 e2 e4 f4 44 48 37 10 f2
+4a
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 5.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+40 46 ca 8b aa 33 47 ca 27 f4 9e 0d 81 f9 cc 1d
+71 be 9b a5 17 d4
+            ";
+
+            //# Seed:
+            seed = @"
+dd 0f 6c fe 41 5e 88 e5 a4 69 a5 1f bb a6 df d4
+0a db 43 84
+            ";
+
+            //# Encryption:
+            encryption = @"
+06 30 ee bc d2 85 6c 24 f7 98 80 6e 41 f9 e6 73
+45 ed a9 ce da 38 6a cc 9f ac ae a1 ee ed 06 ac
+e5 83 70 97 18 d9 d1 69 fa df 41 4d 5c 76 f9 29
+96 83 3e f3 05 b7 5b 1e 4b 95 f6 62 a2 0f ae dc
+3b ae 0c 48 27 a8 bf 8a 88 ed bd 57 ec 20 3a 27
+a8 41 f0 2e 43 a6 15 ba b1 a8 ca c0 70 1d e3 4d
+eb de f6 2a 08 80 89 b5 5e c3 6e a7 52 2f d3 ec
+8d 06 b6 a0 73 e6 df 83 31 53 bc 0a ef d9 3b d1
+a3
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+5c c7 2c 60 23 1d f0 3b 3d 40 f9 b5 79 31 bc 31
+10 9f 97 25 27 f2 8b 19 e7 48 0c 72 88 cb 3c 92
+b2 25 12 21 4e 4b e6 c9 14 79 2d da bd f5 7f aa
+8a a7
+            ";
+
+            //# Seed:
+            seed = @"
+8d 14 bd 94 6a 13 51 14 8f 5c ae 2e d9 a0 c6 53
+e8 5e bd 85
+            ";
+
+            //# Encryption:
+            encryption = @"
+0e bc 37 37 61 73 a4 fd 2f 89 cc 55 c2 ca 62 b2
+6b 11 d5 1c 3c 7c e4 9e 88 45 f7 4e 76 07 31 7c
+43 6b c8 d2 3b 96 67 df eb 9d 08 72 34 b4 7b c6
+83 71 75 ae 5c 05 59 f6 b8 1d 7d 22 41 6d 3e 50
+f4 ac 53 3d 8f 08 12 f2 db 9e 79 1f e9 c7 75 ac
+8b 6a d0 f5 35 ad 9c eb 23 a4 a0 20 14 c5 8a b3
+f8 d3 16 14 99 a2 60 f3 93 48 e7 14 ae 2a 1d 34
+43 20 8f d8 b7 22 cc fd fb 39 3e 98 01 1f 99 e6
+3f
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+b2 0e 65 13 03 09 2f 4b cc b4 30 70 c0 f8 6d 23
+04 93 62 ed 96 64 2f c5 63 2c 27 db 4a 52 e3 d8
+31 f2 ab 06 8b 23 b1 49 87 9c 00 2f 6b f3 fe ee
+97 59 11 12 56 2c
+            ";
+
+            //# Seed:
+            seed = @"
+6c 07 5b c4 55 20 f1 65 c0 bf 5e a4 c5 df 19 1b
+c9 ef 0e 44
+            ";
+
+            //# Encryption:
+            encryption = @"
+0a 98 bf 10 93 61 93 94 43 6c f6 8d 8f 38 e2 f1
+58 fd e8 ea 54 f3 43 5f 23 9b 8d 06 b8 32 18 44
+20 24 76 ae ed 96 00 94 92 48 0c e3 a8 d7 05 49
+8c 4c 8c 68 f0 15 01 dc 81 db 60 8f 60 08 73 50
+c8 c3 b0 bd 2e 9e f6 a8 14 58 b7 c8 01 b8 9f 2e
+4f e9 9d 49 00 ba 6a 4b 5e 5a 96 d8 65 dc 67 6c
+77 55 92 87 94 13 0d 62 80 a8 16 0a 19 0f 2d f3
+ea 7c f9 aa 02 71 d8 8e 9e 69 05 ec f1 c5 15 2d
+65
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+68 4e 30 38 c5 c0 41 f7
+            ";
+
+            //# Seed:
+            seed = @"
+3b bc 3b d6 63 7d fe 12 84 69 01 02 9b f5 b0 c0
+71 03 43 9c
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 8e 7a 67 ca cf b5 c4 e2 4b ec 7d ee 14 91 17
+f1 95 98 ce 8c 45 80 8f ef 88 c6 08 ff 9c d6 e6
+95 26 3b 9a 3c 0a d4 b8 ba 4c 95 23 8e 96 a8 42
+2b 85 35 62 9c 8d 53 82 37 44 79 ad 13 fa 39 97
+4b 24 2f 9a 75 9e ea f9 c8 3a d5 a8 ca 18 94 0a
+01 62 ba 75 58 76 df 26 3f 4b d5 0c 65 25 c5 60
+90 26 7c 1f 0e 09 ce 08 99 a0 cf 35 9e 88 12 0a
+bd 9b f8 93 44 5b 3c ae 77 d3 60 73 59 ae 9a 52
+f8
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+32 48 8c b2 62 d0 41 d6 e4 dd 35 f9 87 bf 3c a6
+96 db 1f 06 ac 29 a4 46 93
+            ";
+
+            //# Seed:
+            seed = @"
+b4 6b 41 89 3e 8b ef 32 6f 67 59 38 3a 83 07 1d
+ae 7f ca bc
+            ";
+
+            //# Encryption:
+            encryption = @"
+00 00 34 74 41 6c 7b 68 bd f9 61 c3 85 73 79 44
+d7 f1 f4 0c b3 95 34 3c 69 3c c0 b4 fe 63 b3 1f
+ed f1 ea ee ac 9c cc 06 78 b3 1d c3 2e 09 77 48
+95 14 c4 f0 90 85 f6 29 8a 96 53 f0 1a ea 40 45
+ff 58 2e e8 87 be 26 ae 57 5b 73 ee f7 f3 77 49
+21 e3 75 a3 d1 9a dd a0 ca 31 aa 18 49 88 7c 1f
+42 ca c9 67 7f 7a 2f 4e 92 3f 6e 5a 86 8b 38 c0
+84 ef 18 75 94 dc 9f 7f 04 8f ea 2e 02 95 53 84
+ab
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example6_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample6(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+50 ba 14 be 84 62 72 02 79 c3 06 ba
+            ";
+
+            //# Seed:
+            seed = @"
+0a 24 03 31 2a 41 e3 d5 2f 06 0f bc 13 a6 7d e5
+cf 76 09 a7
+            ";
+
+            //# Encryption:
+            encryption = @"
+0a 02 6d da 5f c8 78 5f 7b d9 bf 75 32 7b 63 e8
+5e 2c 0f de e5 da db 65 eb dc ac 9a e1 de 95 c9
+2c 67 2a b4 33 aa 7a 8e 69 ce 6a 6d 88 97 fa c4
+ac 4a 54 de 84 1a e5 e5 bb ce 76 87 87 9d 79 63
+4c ea 7a 30 68 40 65 c7 14 d5 24 09 b9 28 25 6b
+bf 53 ea bc d5 23 1e b7 25 95 04 53 73 99 bd 29
+16 4b 72 6d 33 a4 6d a7 01 36 0a 41 68 a0 91 cc
+ab 72 d4 4a 62 fe d2 46 c0 ff ea 5b 13 48 ab 54
+70
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 6.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+47 aa e9 09
+            ";
+
+            //# Seed:
+            seed = @"
+43 dd 09 a0 7f f4 ca c7 1c aa 46 32 ee 5e 1c 1d
+ae e4 cd 8f
+            ";
+
+            //# Encryption:
+            encryption = @"
+16 88 e4 ce 77 94 bb a6 cb 70 14 16 9e cd 55 9c
+ed e2 a3 0b 56 a5 2b 68 d9 fe 18 cf 19 73 ef 97
+b2 a0 31 53 95 1c 75 5f 62 94 aa 49 ad bd b5 58
+45 ab 68 75 fb 39 86 c9 3e cf 92 79 62 84 0d 28
+2f 9e 54 ce 8b 69 0f 7c 0c b8 bb d7 34 40 d9 57
+1d 1b 16 cd 92 60 f9 ea b4 78 3c c4 82 e5 22 3d
+c6 09 73 87 17 83 ec 27 b0 ae 0f d4 77 32 cb c2
+86 a1 73 fc 92 b0 0f b4 ba 68 24 64 7c d9 3c 85
+c1
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+1d 9b 2e 22 23 d9 bc 13 bf b9 f1 62 ce 73 5d b4
+8b a7 c6 8f 68 22 a0 a1 a7 b6 ae 16 58 34 e7
+            ";
+
+            //# Seed:
+            seed = @"
+3a 9c 3c ec 7b 84 f9 bd 3a de cb c6 73 ec 99 d5
+4b 22 bc 9b
+            ";
+
+            //# Encryption:
+            encryption = @"
+10 52 ed 39 7b 2e 01 e1 d0 ee 1c 50 bf 24 36 3f
+95 e5 04 f4 a0 34 34 a0 8f d8 22 57 4e d6 b9 73
+6e db b5 f3 90 db 10 32 14 79 a8 a1 39 35 0e 2b
+d4 97 7c 37 78 ef 33 1f 3e 78 ae 11 8b 26 84 51
+f2 0a 2f 01 d4 71 f5 d5 3c 56 69 37 17 1b 2d bc
+2d 4b de 45 9a 57 99 f0 37 2d 65 74 23 9b 23 23
+d2 45 d0 bb 81 c2 86 b6 3c 89 a3 61 01 73 37 e4
+90 2f 88 a4 67 f4 c7 f2 44 bf d5 ab 46 43 7f f3
+b6
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+d9 76 fc
+            ";
+
+            //# Seed:
+            seed = @"
+76 a7 5e 5b 61 57 a5 56 cf 88 84 bb 2e 45 c2 93
+dd 54 5c f5
+            ";
+
+            //# Encryption:
+            encryption = @"
+21 55 cd 84 3f f2 4a 4e e8 ba db 76 94 26 00 28
+a4 90 81 3b a8 b3 69 a4 cb f1 06 ec 14 8e 52 98
+70 7f 59 65 be 7d 10 1c 10 49 ea 85 84 c2 4c d6
+34 55 ad 9c 10 4d 68 62 82 d3 fb 80 3a 4c 11 c1
+c2 e9 b9 1c 71 78 80 1d 1b 66 40 f0 03 f5 72 8d
+f0 07 b8 a4 cc c9 2b ce 05 e4 1a 27 27 8d 7c 85
+01 8c 52 41 43 13 a5 07 77 89 00 1d 4f 01 91 0b
+72 aa d0 5d 22 0a a1 4a 58 73 3a 74 89 bc 54 55
+6b
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+d4 73 86 23 df 22 3a a4 38 43 df 84 67 53 4c 41
+d0 13 e0 c8 03 c6 24 e2 63 66 6b 23 9b de 40 a5
+f2 9a eb 8d e7 9e 3d aa 61 dd 03 70 f4 9b d4 b0
+13 83 4b 98 21 2a ef 6b 1c 5e e3 73 b3 cb
+            ";
+
+            //# Seed:
+            seed = @"
+78 66 31 4a 6a d6 f2 b2 50 a3 59 41 db 28 f5 86
+4b 58 58 59
+            ";
+
+            //# Encryption:
+            encryption = @"
+0a b1 4c 37 3a eb 7d 43 28 d0 aa ad 8c 09 4d 88
+b9 eb 09 8b 95 f2 10 54 a2 90 82 52 2b e7 c2 7a
+31 28 78 b6 37 91 7e 3d 81 9e 6c 3c 56 8d b5 d8
+43 80 2b 06 d5 1d 9e 98 a2 be 0b f4 0c 03 14 23
+b0 0e df bf f8 32 0e fb 91 71 bd 20 44 65 3a 4c
+b9 c5 12 2f 6c 65 e8 3c da 2e c3 c1 26 02 7a 9c
+1a 56 ba 87 4d 0f ea 23 f3 80 b8 2c f2 40 b8 cf
+54 00 04 75 8c 4c 77 d9 34 15 7a 74 f3 fc 12 bf
+ac
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+bb 47 23 1c a5 ea 1d 3a d4 6c 99 34 5d 9a 8a 61
+            ";
+
+            //# Seed:
+            seed = @"
+b2 16 6e d4 72 d5 8d b1 0c ab 2c 6b 00 0c cc f1
+0a 7d c5 09
+            ";
+
+            //# Encryption:
+            encryption = @"
+02 83 87 a3 18 27 74 34 79 8b 4d 97 f4 60 06 8d
+f5 29 8f ab a5 04 1b a1 17 61 a1 cb 73 16 b2 41
+84 11 4e c5 00 25 7e 25 89 ed 3b 60 7a 1e bb e9
+7a 6c c2 e0 2b f1 b6 81 f4 23 12 a3 3b 7a 77 d8
+e7 85 5c 4a 6d e0 3e 3c 04 64 3f 78 6b 91 a2 64
+a0 d6 80 5e 2c ea 91 e6 81 77 eb 7a 64 d9 25 5e
+4f 27 e7 13 b7 cc ec 00 dc 20 0e bd 21 c2 ea 2b
+b8 90 fe ae 49 42 df 94 1d c3 f9 78 90 ed 34 74
+78
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example7_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample7(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+21 84 82 70 95 d3 5c 3f 86 f6 00 e8 e5 97 54 01
+32 96
+            ";
+
+            //# Seed:
+            seed = @"
+52 67 3b de 2c a1 66 c2 aa 46 13 1a c1 dc 80 8d
+67 d7 d3 b1
+            ";
+
+            //# Encryption:
+            encryption = @"
+14 c6 78 a9 4a d6 05 25 ef 39 e9 59 b2 f3 ba 5c
+09 7a 94 ff 91 2b 67 db ac e8 05 35 c1 87 ab d4
+7d 07 54 20 b1 87 21 52 bb a0 8f 7f c3 1f 31 3b
+bf 92 73 c9 12 fc 4c 01 49 a9 b0 cf b7 98 07 e3
+46 eb 33 20 69 61 1b ec 0f f9 bc d1 68 f1 f7 c3
+3e 77 31 3c ea 45 4b 94 e2 54 9e ec f0 02 e2 ac
+f7 f6 f2 d2 84 5d 4f e0 aa b2 e5 a9 2d df 68 c4
+80 ae 11 24 79 35 d1 f6 25 74 84 22 16 ae 67 41
+15
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 7.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+05 0b 75 5e 5e 68 80 f7 b9 e9 d6 92 a7 4c 37 aa
+e4 49 b3 1b fe a6 de ff 83 74 7a 89 7f 6c 2c 82
+5b b1 ad bf 85 0a 3c 96 99 4b 5d e5 b3 3c bc 7d
+4a 17 91 3a 79 67
+            ";
+
+            //# Seed:
+            seed = @"
+77 06 ff ca 1e cf b1 eb ee 2a 55 e5 c6 e2 4c d2
+79 7a 41 25
+            ";
+
+            //# Encryption:
+            encryption = @"
+09 b3 68 3d 8a 2e b0 fb 29 5b 62 ed 1f b9 29 0b
+71 44 57 b7 82 53 19 f4 64 78 72 af 88 9b 30 40
+94 72 02 0a d1 29 12 bf 19 b1 1d 48 19 f4 96 14
+82 4f fd 84 d0 9c 0a 17 e7 d1 73 09 d1 29 19 79
+04 10 aa 29 95 69 9f 6a 86 db e3 24 2b 5a cc 23
+af 45 69 10 80 d6 b1 ae 81 0f b3 e3 05 70 87 f0
+97 00 92 ce 00 be 95 62 ff 40 53 b6 26 2c e0 ca
+a9 3e 13 72 3d 2e 3a 5b a0 75 d4 5f 0d 61 b5 4b
+61
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+4e b6 8d cd 93 ca 9b 19 df 11 1b d4 36 08 f5 57
+02 6f e4 aa 1d 5c fa c2 27 a3 eb 5a b9 54 8c 18
+a0 6d de d2 3f 81 82 59 86 b2 fc d7 11 09 ec ef
+7e ff 88 87 3f 07 5c 2a a0 c4 69 f6 9c 92 bc
+            ";
+
+            //# Seed:
+            seed = @"
+a3 71 7d a1 43 b4 dc ff bc 74 26 65 a8 fa 95 05
+85 54 83 43
+            ";
+
+            //# Encryption:
+            encryption = @"
+2e cf 15 c9 7c 5a 15 b1 47 6a e9 86 b3 71 b5 7a
+24 28 4f 4a 16 2a 8d 0c 81 82 e7 90 5e 79 22 56
+f1 81 2b a5 f8 3f 1f 7a 13 0e 42 dc c0 22 32 84
+4e dc 14 a3 1a 68 ee 97 ae 56 4a 38 3a 34 11 65
+64 24 c5 f6 2d db 64 60 93 c3 67 be 1f cd a4 26
+cf 00 a0 6d 8a cb 7e 57 77 6f bb d8 55 ac 3d f5
+06 fc 16 b1 d7 c3 f2 11 0f 3d 80 68 e9 1e 18 63
+63 83 1c 84 09 68 0d 8d a9 ec d8 cf 1f a2 0e e3
+9d
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+86 04 ac 56 32 8c 1a b5 ad 91 78 61
+            ";
+
+            //# Seed:
+            seed = @"
+ee 06 20 90 73 cc a0 26 bb 26 4e 51 85 bf 8c 68
+b7 73 9f 86
+            ";
+
+            //# Encryption:
+            encryption = @"
+4b c8 91 30 a5 b2 da bb 7c 2f cf 90 eb 5d 0e af
+9e 68 1b 71 46 a3 8f 31 73 a3 d9 cf ec 52 ea 9e
+0a 41 93 2e 64 8a 9d 69 34 4c 50 da 76 3f 51 a0
+3c 95 76 21 31 e8 05 22 54 dc d2 24 8c ba 40 fd
+31 66 77 86 ce 05 a2 b7 b5 31 ac 9d ac 9e d5 84
+a5 9b 67 7c 1a 8a ed 8c 5d 15 d6 8c 05 56 9e 2b
+e7 80 bf 7d b6 38 fd 2b fd 2a 85 ab 27 68 60 f3
+77 73 38 fc a9 89 ff d7 43 d1 3e e0 8e 0c a9 89
+3f
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+fd da 5f bf 6e c3 61 a9 d9 a4 ac 68 af 21 6a 06
+86 f4 38 b1 e0 e5 c3 6b 95 5f 74 e1 07 f3 9c 0d
+dd cc
+            ";
+
+            //# Seed:
+            seed = @"
+99 0a d5 73 dc 48 a9 73 23 5b 6d 82 54 36 18 f2
+e9 55 10 5d
+            ";
+
+            //# Encryption:
+            encryption = @"
+2e 45 68 47 d8 fc 36 ff 01 47 d6 99 35 94 b9 39
+72 27 d5 77 75 2c 79 d0 f9 04 fc b0 39 d4 d8 12
+fe a6 05 a7 b5 74 dd 82 ca 78 6f 93 75 23 48 43
+8e e9 f5 b5 45 49 85 d5 f0 e1 69 9e 3e 7a d1 75
+a3 2e 15 f0 3d eb 04 2a b9 fe 1d d9 db 1b b8 6f
+8c 08 9c cb 45 e7 ef 0c 5e e7 ca 9b 72 90 ca 6b
+15 be d4 70 39 78 8a 8a 93 ff 83 e0 e8 d6 24 4c
+71 00 63 62 de ef 69 b6 f4 16 fb 3c 68 43 83 fb
+d0
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+4a 5f 49 14 be e2 5d e3 c6 93 41 de 07
+            ";
+
+            //# Seed:
+            seed = @"
+ec c6 3b 28 f0 75 6f 22 f5 2a c8 e6 ec 12 51 a6
+ec 30 47 18
+            ";
+
+            //# Encryption:
+            encryption = @"
+1f b9 35 6f d5 c4 b1 79 6d b2 eb f7 d0 d3 93 cc
+81 0a df 61 45 de fc 2f ce 71 4f 79 d9 38 00 d5
+e2 ac 21 1e a8 bb ec ca 4b 65 4b 94 c3 b1 8b 30
+dd 57 6c e3 4d c9 54 36 ef 57 a0 94 15 64 59 23
+35 9a 5d 7b 41 71 ef 22 c2 46 70 f1 b2 29 d3 60
+3e 91 f7 66 71 b7 df 97 e7 31 7c 97 73 44 76 d5
+f3 d1 7d 21 cf 82 b5 ba 9f 83 df 2e 58 8d 36 98
+4f d1 b5 84 46 8b d2 3b 2e 87 5f 32 f6 89 53 f7
+b2
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example8_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample8(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+8e 07 d6 6f 7b 88 0a 72 56 3a bc d3 f3 50 92 bc
+33 40 9f b7 f8 8f 24 72 be
+            ";
+
+            //# Seed:
+            seed = @"
+39 25 c7 1b 36 2d 40 a0 a6 de 42 14 55 79 ba 1e
+7d d4 59 fc
+            ";
+
+            //# Encryption:
+            encryption = @"
+3a fd 9c 66 00 14 7b 21 79 8d 81 8c 65 5a 0f 4c
+92 12 db 26 d0 b0 df dc 2a 75 94 cc b3 d2 2f 5b
+f1 d7 c3 e1 12 cd 73 fc 7d 50 9c 7a 8b af dd 3c
+27 4d 13 99 00 9f 96 09 ec 4b e6 47 7e 45 3f 07
+5a a3 3d b3 82 87 0c 1c 34 09 ae f3 92 d7 38 6a
+e3 a6 96 b9 9a 94 b4 da 05 89 44 7e 95 5d 16 c9
+8b 17 60 2a 59 bd 73 62 79 fc d8 fb 28 0c 44 62
+d5 90 bf a9 bf 13 fe d5 70 ea fd e9 73 30 a2 c2
+10
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 8.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+f7 35 fd 55 ba 92 59 2c 3b 52 b8 f9 c4 f6 9a aa
+1c be f8 fe 88 ad d0 95 59 54 12 46 7f 9c f4 ec
+0b 89 6c 59 ed a1 62 10 e7 54 9c 8a bb 10 cd bc
+21 a1 2e c9 b6 b5 b8 fd 2f 10 39 9e b6
+            ";
+
+            //# Seed:
+            seed = @"
+8e c9 65 f1 34 a3 ec 99 31 e9 2a 1c a0 dc 81 69
+d5 ea 70 5c
+            ";
+
+            //# Encryption:
+            encryption = @"
+26 7b cd 11 8a ca b1 fc 8b a8 1c 85 d7 30 03 cb
+86 10 fa 55 c1 d9 7d a8 d4 8a 7c 7f 06 89 6a 4d
+b7 51 aa 28 42 55 b9 d3 6a d6 5f 37 65 3d 82 9f
+1b 37 f9 7b 80 01 94 25 45 b2 fc 2c 55 a7 37 6c
+a7 a1 be 4b 17 60 c8 e0 5a 33 e5 aa 25 26 b8 d9
+8e 31 70 88 e7 83 4c 75 5b 2a 59 b1 26 31 a1 82
+c0 5d 5d 43 ab 17 79 26 4f 84 56 f5 15 ce 57 df
+df 51 2d 54 93 da b7 b7 33 8d c4 b7 d7 8d b9 c0
+91 ac 3b af 53 7a 69 fc 7f 54 9d 97 9f 0e ff 9a
+94 fd a4 16 9b d4 d1 d1 9a 69 c9 9e 33 c3 b5 54
+90 d5 01 b3 9b 1e da e1 18 ff 67 93 a1 53 26 15
+84 d3 a5 f3 9f 6e 68 2e 3d 17 c8 cd 12 61 fa 72
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+81 b9 06 60 50 15 a6 3a ab e4 2d df 11 e1 97 89
+12 f5 40 4c 74 74 b2 6d ce 3e d4 82 bf 96 1e cc
+81 8b f4 20 c5 46 59
+            ";
+
+            //# Seed:
+            seed = @"
+ec b1 b8 b2 5f a5 0c da b0 8e 56 04 28 67 f4 af
+58 26 d1 6c
+            ";
+
+            //# Encryption:
+            encryption = @"
+93 ac 9f 06 71 ec 29 ac bb 44 4e ff c1 a5 74 13
+51 d6 0f db 0e 39 3f bf 75 4a cf 0d e4 97 61 a1
+48 41 df 77 72 e9 bc 82 77 39 66 a1 58 4c 4d 72
+ba ea 00 11 8f 83 f3 5c ca 6e 53 7c bd 4d 81 1f
+55 83 b2 97 83 d8 a6 d9 4c d3 1b e7 0d 6f 52 6c
+10 ff 09 c6 fa 7c e0 69 79 5a 3f cd 05 11 fd 5f
+cb 56 4b cc 80 ea 9c 78 f3 8b 80 01 25 39 d8 a4
+dd f6 fe 81 e9 cd db 7f 50 db bb bc c7 e5 d8 60
+97 cc f4 ec 49 18 9f b8 bf 31 8b e6 d5 a0 71 5d
+51 6b 49 af 19 12 58 cd 32 dc 83 3c e6 eb 46 73
+c0 3a 19 bb ac e8 8c c5 48 95 f6 36 cc 0c 1e c8
+90 96 d1 1c e2 35 a2 65 ca 17 64 23 2a 68 9a e8
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+fd 32 64 29 df 9b 89 0e 09 b5 4b 18 b8 f3 4f 1e
+24
+            ";
+
+            //# Seed:
+            seed = @"
+e8 9b b0 32 c6 ce 62 2c bd b5 3b c9 46 60 14 ea
+77 f7 77 c0
+            ";
+
+            //# Encryption:
+            encryption = @"
+81 eb dd 95 05 4b 0c 82 2e f9 ad 76 93 f5 a8 7a
+df b4 b4 c4 ce 70 df 2d f8 4e d4 9c 04 da 58 ba
+5f c2 0a 19 e1 a6 e8 b7 a3 90 0b 22 79 6d c4 e8
+69 ee 6b 42 79 2d 15 a8 ec eb 56 c0 9c 69 91 4e
+81 3c ea 8f 69 31 e4 b8 ed 6f 42 1a f2 98 d5 95
+c9 7f 47 89 c7 ca a6 12 c7 ef 36 09 84 c2 1b 93
+ed c5 40 10 68 b5 af 4c 78 a8 77 1b 98 4d 53 b8
+ea 8a df 2f 6a 7d 4a 0b a7 6c 75 e1 dd 9f 65 8f
+20 de d4 a4 60 71 d4 6d 77 91 b5 68 03 d8 fe a7
+f0 b0 f8 e4 1a e3 f0 93 83 a6 f9 58 5f e7 75 3e
+aa ff d2 bf 94 56 31 08 be ec c2 07 bb b5 35 f5
+fc c7 05 f0 dd e9 f7 08 c6 2f 49 a9 c9 03 71 d3
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+f1 45 9b 5f 0c 92 f0 1a 0f 72 3a 2e 56 62 48 4d
+8f 8c 0a 20 fc 29 da d6 ac d4 3b b5 f3 ef fd f4
+e1 b6 3e 07 fd fe 66 28 d0 d7 4c a1 9b f2 d6 9e
+4a 0a bf 86 d2 93 92 5a 79 67 72 f8 08 8e
+            ";
+
+            //# Seed:
+            seed = @"
+60 6f 3b 99 c0 b9 cc d7 71 ea a2 9e a0 e4 c8 84
+f3 18 9c cc
+            ";
+
+            //# Encryption:
+            encryption = @"
+bc c3 5f 94 cd e6 6c b1 13 66 25 d6 25 b9 44 32
+a3 5b 22 f3 d2 fa 11 a6 13 ff 0f ca 5b d5 7f 87
+b9 02 cc dc 1c d0 ae bc b0 71 5e e8 69 d1 d1 fe
+39 5f 67 93 00 3f 5e ca 46 50 59 c8 86 60 d4 46
+ff 5f 08 18 55 20 22 55 7e 38 c0 8a 67 ea d9 91
+26 22 54 f1 06 82 97 5e c5 63 97 76 85 37 f4 97
+7a f6 d5 f6 aa ce b7 fb 25 de c5 93 72 30 23 1f
+d8 97 8a f4 91 19 a2 9f 29 e4 24 ab 82 72 b4 75
+62 79 2d 5c 94 f7 74 b8 82 9d 0b 0d 9f 1a 8c 9e
+dd f3 75 74 d5 fa 24 8e ef a9 c5 27 1f c5 ec 25
+79 c8 1b dd 61 b4 10 fa 61 fe 36 e4 24 22 1c 11
+3a dd b2 75 66 4c 80 1d 34 ca 8c 63 51 e4 a8 58
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+53 e6 e8 c7 29 d6 f9 c3 19 dd 31 7e 74 b0 db 8e
+4c cc a2 5f 3c 83 05 74 6e 13 7a c6 3a 63 ef 37
+39 e7 b5 95 ab b9 6e 8d 55 e5 4f 7b d4 1a b4 33
+37 8f fb 91 1d
+            ";
+
+            //# Seed:
+            seed = @"
+fc bc 42 14 02 e9 ec ab c6 08 2a fa 40 ba 5f 26
+52 2c 84 0e
+            ";
+
+            //# Encryption:
+            encryption = @"
+23 2a fb c9 27 fa 08 c2 f6 a2 7b 87 d4 a5 cb 09
+c0 7d c2 6f ae 73 d7 3a 90 55 88 39 f4 fd 66 d2
+81 b8 7e c7 34 bc e2 37 ba 16 66 98 ed 82 91 06
+a7 de 69 42 cd 6c dc e7 8f ed 8d 2e 4d 81 42 8e
+66 49 0d 03 62 64 ce f9 2a f9 41 d3 e3 50 55 fe
+39 81 e1 4d 29 cb b9 a4 f6 74 73 06 3b ae c7 9a
+11 79 f5 a1 7c 9c 18 32 f2 83 8f d7 d5 e5 9b b9
+65 9d 56 dc e8 a0 19 ed ef 1b b3 ac cc 69 7c c6
+cc 7a 77 8f 60 a0 64 c7 f6 f5 d5 29 c6 21 02 62
+e0 03 de 58 3e 81 e3 16 7b 89 97 1f b8 c0 e1 5d
+44 ff fe f8 9b 53 d8 d6 4d d7 97 d1 59 b5 6d 2b
+08 ea 53 07 ea 12 c2 41 bd 58 d4 ee 27 8a 1f 2e
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example9_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample9(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+b6 b2 8e a2 19 8d 0c 10 08 bc 64
+            ";
+
+            //# Seed:
+            seed = @"
+23 aa de 0e 1e 08 bb 9b 9a 78 d2 30 2a 52 f9 c2
+1b 2e 1b a2
+            ";
+
+            //# Encryption:
+            encryption = @"
+43 8c c7 dc 08 a6 8d a2 49 e4 25 05 f8 57 3b a6
+0e 2c 27 73 d5 b2 90 f4 cf 9d ff 71 8e 84 20 81
+c3 83 e6 70 24 a0 f2 95 94 ea 98 7b 9d 25 e4 b7
+38 f2 85 97 0d 19 5a bb 3a 8c 80 54 e3 d7 9d 6b
+9c 9a 83 27 ba 59 6f 12 59 e2 71 26 67 47 66 90
+7d 8d 58 2f f3 a8 47 61 54 92 9a db 1e 6d 12 35
+b2 cc b4 ec 8f 66 3b a9 cc 67 0a 92 be bd 85 3c
+8d bf 69 c6 43 6d 01 6f 61 ad d8 36 e9 47 32 45
+04 34 20 7f 9f d4 c4 3d ec 2a 12 a9 58 ef a0 1e
+fe 26 69 89 9b 5e 60 4c 25 5c 55 fb 71 66 de 55
+89 e3 69 59 7b b0 91 68 c0 6d d5 db 17 7e 06 a1
+74 0e b2 d5 c8 2f ae ca 6d 92 fc ee 99 31 ba 9f
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 9.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_1()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+8b ba 6b f8 2a 6c 0f 86 d5 f1 75 6e 97 95 68 70
+b0 89 53 b0 6b 4e b2 05 bc 16 94 ee
+            ";
+
+            //# Seed:
+            seed = @"
+47 e1 ab 71 19 fe e5 6c 95 ee 5e aa d8 6f 40 d0
+aa 63 bd 33
+            ";
+
+            //# Encryption:
+            encryption = @"
+53 ea 5d c0 8c d2 60 fb 3b 85 85 67 28 7f a9 15
+52 c3 0b 2f eb fb a2 13 f0 ae 87 70 2d 06 8d 19
+ba b0 7f e5 74 52 3d fb 42 13 9d 68 c3 c5 af ee
+e0 bf e4 cb 79 69 cb f3 82 b8 04 d6 e6 13 96 14
+4e 2d 0e 60 74 1f 89 93 c3 01 4b 58 b9 b1 95 7a
+8b ab cd 23 af 85 4f 4c 35 6f b1 66 2a a7 2b fc
+c7 e5 86 55 9d c4 28 0d 16 0c 12 67 85 a7 23 eb
+ee be ff 71 f1 15 94 44 0a ae f8 7d 10 79 3a 87
+74 a2 39 d4 a0 4c 87 fe 14 67 b9 da f8 52 08 ec
+6c 72 55 79 4a 96 cc 29 14 2f 9a 8b d4 18 e3 c1
+fd 67 34 4b 0c d0 82 9d f3 b2 be c6 02 53 19 62
+93 c6 b3 4d 3f 75 d3 2f 21 3d d4 5c 62 73 d5 05
+ad f4 cc ed 10 57 cb 75 8f c2 6a ee fa 44 12 55
+ed 4e 64 c1 99 ee 07 5e 7f 16 64 61 82 fd b4 64
+73 9b 68 ab 5d af f0 e6 3e 95 52 01 68 24 f0 54
+bf 4d 3c 8c 90 a9 7b b6 b6 55 32 84 eb 42 9f cc
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.1", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_2()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+e6 ad 18 1f 05 3b 58 a9 04 f2 45 75 10 37 3e 57
+            ";
+
+            //# Seed:
+            seed = @"
+6d 17 f5 b4 c1 ff ac 35 1d 19 5b f7 b0 9d 09 f0
+9a 40 79 cf
+            ";
+
+            //# Encryption:
+            encryption = @"
+a2 b1 a4 30 a9 d6 57 e2 fa 1c 2b b5 ed 43 ff b2
+5c 05 a3 08 fe 90 93 c0 10 31 79 5f 58 74 40 01
+10 82 8a e5 8f b9 b5 81 ce 9d dd d3 e5 49 ae 04
+a0 98 54 59 bd e6 c6 26 59 4e 7b 05 dc 42 78 b2
+a1 46 5c 13 68 40 88 23 c8 5e 96 dc 66 c3 a3 09
+83 c6 39 66 4f c4 56 9a 37 fe 21 e5 a1 95 b5 77
+6e ed 2d f8 d8 d3 61 af 68 6e 75 02 29 bb d6 63
+f1 61 86 8a 50 61 5e 0c 33 7b ec 0c a3 5f ec 0b
+b1 9c 36 eb 2e 0b bc c0 58 2f a1 d9 3a ac db 06
+10 63 f5 9f 2c e1 ee 43 60 5e 5d 89 ec a1 83 d2
+ac df e9 f8 10 11 02 2a d3 b4 3a 3d d4 17 da c9
+4b 4e 11 ea 81 b1 92 96 6e 96 6b 18 20 82 e7 19
+64 60 7b 4f 80 02 f3 62 99 84 4a 11 f2 ae 0f ae
+ac 2e ae 70 f8 f4 f9 80 88 ac dc d0 ac 55 6e 9f
+cc c5 11 52 19 08 fa d2 6f 04 c6 42 01 45 03 05
+77 87 58 b0 53 8b f8 b5 bb 14 4a 82 8e 62 97 95
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.2", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_3()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+51 0a 2c f6 0e 86 6f a2 34 05 53 c9 4e a3 9f bc
+25 63 11 e8 3e 94 45 4b 41 24
+            ";
+
+            //# Seed:
+            seed = @"
+38 53 87 51 4d ec cc 7c 74 0d d8 cd f9 da ee 49
+a1 cb fd 54
+            ";
+
+            //# Encryption:
+            encryption = @"
+98 86 c3 e6 76 4a 8b 9a 84 e8 41 48 eb d8 c3 b1
+aa 80 50 38 1a 78 f6 68 71 4c 16 d9 cf d2 a6 ed
+c5 69 79 c5 35 d9 de e3 b4 4b 85 c1 8b e8 92 89
+92 37 17 11 47 22 16 d9 5d da 98 d2 ee 83 47 c9
+b1 4d ff df f8 4a a4 8d 25 ac 06 f7 d7 e6 53 98
+ac 96 7b 1c e9 09 25 f6 7d ce 04 9b 7f 81 2d b0
+74 29 97 a7 4d 44 fe 81 db e0 e7 a3 fe af 2e 5c
+40 af 88 8d 55 0d db be 3b c2 06 57 a2 95 43 f8
+fc 29 13 b9 bd 1a 61 b2 ab 22 56 ec 40 9b bd 7d
+c0 d1 77 17 ea 25 c4 3f 42 ed 27 df 87 38 bf 4a
+fc 67 66 ff 7a ff 08 59 55 5e e2 83 92 0f 4c 8a
+63 c4 a7 34 0c ba fd dc 33 9e cd b4 b0 51 50 02
+f9 6c 93 2b 5b 79 16 7a f6 99 c0 ad 3f cc fd f0
+f4 4e 85 a7 02 62 bf 2e 18 fe 34 b8 50 58 99 75
+e8 67 ff 96 9d 48 ea bf 21 22 71 54 6c dc 05 a6
+9e cb 52 6e 52 87 0c 83 6f 30 7b d7 98 78 0e de
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.3", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_4()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+bc dd 19 0d a3 b7 d3 00 df 9a 06 e2 2c aa e2 a7
+5f 10 c9 1f f6 67 b7 c1 6b de 8b 53 06 4a 26 49
+a9 40 45 c9
+            ";
+
+            //# Seed:
+            seed = @"
+5c ac a6 a0 f7 64 16 1a 96 84 f8 5d 92 b6 e0 ef
+37 ca 8b 65
+            ";
+
+            //# Encryption:
+            encryption = @"
+63 18 e9 fb 5c 0d 05 e5 30 7e 16 83 43 6e 90 32
+93 ac 46 42 35 8a aa 22 3d 71 63 01 3a ba 87 e2
+df da 8e 60 c6 86 0e 29 a1 e9 26 86 16 3e a0 b9
+17 5f 32 9c a3 b1 31 a1 ed d3 a7 77 59 a8 b9 7b
+ad 6a 4f 8f 43 96 f2 8c f6 f3 9c a5 81 12 e4 81
+60 d6 e2 03 da a5 85 6f 3a ca 5f fe d5 77 af 49
+94 08 e3 df d2 33 e3 e6 04 db e3 4a 9c 4c 90 82
+de 65 52 7c ac 63 31 d2 9d c8 0e 05 08 a0 fa 71
+22 e7 f3 29 f6 cc a5 cf a3 4d 4d 1d a4 17 80 54
+57 e0 08 be c5 49 e4 78 ff 9e 12 a7 63 c4 77 d1
+5b bb 78 f5 b6 9b d5 78 30 fc 2c 4e d6 86 d7 9b
+c7 2a 95 d8 5f 88 13 4c 6b 0a fe 56 a8 cc fb c8
+55 82 8b b3 39 bd 17 90 9c f1 d7 0d e3 33 5a e0
+70 39 09 3e 60 6d 65 53 65 de 65 50 b8 72 cd 6d
+e1 d4 40 ee 03 1b 61 94 5f 62 9a d8 a3 53 b0 d4
+09 39 e9 6a 3c 45 0d 2a 8d 5e ee 9f 67 80 93 c8
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.4", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_5()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+a7 dd 6c 7d c2 4b 46 f9 dd 5f 1e 91 ad a4 c3 b3
+df 94 7e 87 72 32 a9
+            ";
+
+            //# Seed:
+            seed = @"
+95 bc a9 e3 85 98 94 b3 dd 86 9f a7 ec d5 bb c6
+40 1b f3 e4
+            ";
+
+            //# Encryption:
+            encryption = @"
+75 29 08 72 cc fd 4a 45 05 66 0d 65 1f 56 da 6d
+aa 09 ca 13 01 d8 90 63 2f 6a 99 2f 3d 56 5c ee
+46 4a fd ed 40 ed 3b 5b e9 35 67 14 ea 5a a7 65
+5f 4a 13 66 c2 f1 7c 72 8f 6f 2c 5a 5d 1f 8e 28
+42 9b c4 e6 f8 f2 cf f8 da 8d c0 e0 a9 80 8e 45
+fd 09 ea 2f a4 0c b2 b6 ce 6f ff f5 c0 e1 59 d1
+1b 68 d9 0a 85 f7 b8 4e 10 3b 09 e6 82 66 64 80
+c6 57 50 5c 09 29 25 94 68 a3 14 78 6d 74 ea b1
+31 57 3c f2 34 bf 57 db 7d 9e 66 cc 67 48 19 2e
+00 2d c0 de ea 93 05 85 f0 83 1f dc d9 bc 33 d5
+1f 79 ed 2f fc 16 bc f4 d5 98 12 fc eb ca a3 f9
+06 9b 0e 44 56 86 d6 44 c2 5c cf 63 b4 56 ee 5f
+a6 ff e9 6f 19 cd f7 51 fe d9 ea f3 59 57 75 4d
+bf 4b fe a5 21 6a a1 84 4d c5 07 cb 2d 08 0e 72
+2e ba 15 03 08 c2 b5 ff 11 93 62 0f 17 66 ec f4
+48 1b af b9 43 bd 29 28 77 f2 13 6c a4 94 ab a0
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.5", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        [Test]
+        public static void TestRSAES_OAEP_Encryption_Example10_6()
+        {
+            string n, e, d, p, q, dp, dq, qinv, message, seed, encryption;
+            SetupKeysExample10(out n, out e, out d, out p, out q, out dp, out dq, out qinv);
+
+            //# Message to be encrypted:
+            message = @"
+ea f1 a7 3a 1b 0c 46 09 53 7d e6 9c d9 22 8b bc
+fb 9a 8c a8 c6 c3 ef af 05 6f e4 a7 f4 63 4e d0
+0b 7c 39 ec 69 22 d7 b8 ea 2c 04 eb ac
+            ";
+
+            //# Seed:
+            seed = @"
+9f 47 dd f4 2e 97 ee a8 56 a9 bd bc 71 4e b3 ac
+22 f6 eb 32
+            ";
+
+            //# Encryption:
+            encryption = @"
+2d 20 7a 73 43 2a 8f b4 c0 30 51 b3 f7 3b 28 a6
+17 64 09 8d fa 34 c4 7a 20 99 5f 81 15 aa 68 16
+67 9b 55 7e 82 db ee 58 49 08 c6 e6 97 82 d7 de
+b3 4d bd 65 af 06 3d 57 fc a7 6a 5f d0 69 49 2f
+d6 06 8d 99 84 d2 09 35 05 65 a6 2e 5c 77 f2 30
+38 c1 2c b1 0c 66 34 70 9b 54 7c 46 f6 b4 a7 09
+bd 85 ca 12 2d 74 46 5e f9 77 62 c2 97 63 e0 6d
+bc 7a 9e 73 8c 78 bf ca 01 02 dc 5e 79 d6 5b 97
+3f 28 24 0c aa b2 e1 61 a7 8b 57 d2 62 45 7e d8
+19 5d 53 e3 c7 ae 9d a0 21 88 3c 6d b7 c2 4a fd
+d2 32 2e ac 97 2a d3 c3 54 c5 fc ef 1e 14 6c 3a
+02 90 fb 67 ad f0 07 06 6e 00 42 8d 2c ec 18 ce
+58 f9 32 86 98 de fe f4 b2 eb 5e c7 69 18 fd e1
+c1 98 cb b3 8b 7a fc 67 62 6a 9a ef ec 43 22 bf
+d9 0d 25 63 48 1c 9a 22 1f 78 c8 27 2c 82 d1 b6
+2a b9 14 e1 c6 9f 6a f6 ef 30 ca 52 60 db 4a 46
+            ";
+
+            RunOneCase("RSAES-OAEP Encryption Example 10.6", n, e, d, p, q, dp, dq, qinv, message, seed, encryption);
+        }
+
+        private static void SetupKeysExample1(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# RSA modulus n:
+            n = @"
+            a8 b3 b2 84 af 8e b5 0b 38 70 34 a8 60 f1 46 c4
+            91 9f 31 87 63 cd 6c 55 98 c8 ae 48 11 a1 e0 ab
+            c4 c7 e0 b0 82 d6 93 a5 e7 fc ed 67 5c f4 66 85
+            12 77 2c 0c bc 64 a7 42 c6 c6 30 f5 33 c8 cc 72
+            f6 2a e8 33 c4 0b f2 58 42 e9 84 bb 78 bd bf 97
+            c0 10 7d 55 bd b6 62 f5 c4 e0 fa b9 84 5c b5 14
+            8e f7 39 2d d3 aa ff 93 ae 1e 6b 66 7b b3 d4 24
+            76 16 d4 f5 ba 10 d4 cf d2 26 de 88 d3 9f 16 fb";
+
+            //# RSA public exponent e:
+            e = @"01 00 01";
+
+            //# RSA private exponent d:
+            d = @"
+            53 33 9c fd b7 9f c8 46 6a 65 5c 73 16 ac a8 5c
+            55 fd 8f 6d d8 98 fd af 11 95 17 ef 4f 52 e8 fd
+            8e 25 8d f9 3f ee 18 0f a0 e4 ab 29 69 3c d8 3b
+            15 2a 55 3d 4a c4 d1 81 2b 8b 9f a5 af 0e 7f 55
+            fe 73 04 df 41 57 09 26 f3 31 1f 15 c4 d6 5a 73
+            2c 48 31 16 ee 3d 3d 2d 0a f3 54 9a d9 bf 7c bf
+            b7 8a d8 84 f8 4d 5b eb 04 72 4d c7 36 9b 31 de
+            f3 7d 0c f5 39 e9 cf cd d3 de 65 37 29 ea d5 d1";
+
+            //# Prime p:
+            p = @"
+            d3 27 37 e7 26 7f fe 13 41 b2 d5 c0 d1 50 a8 1b
+            58 6f b3 13 2b ed 2f 8d 52 62 86 4a 9c b9 f3 0a
+            f3 8b e4 48 59 8d 41 3a 17 2e fb 80 2c 21 ac f1
+            c1 1c 52 0c 2f 26 a4 71 dc ad 21 2e ac 7c a3 9d";
+
+            //# Prime q:
+            q = @"
+            cc 88 53 d1 d5 4d a6 30 fa c0 04 f4 71 f2 81 c7
+            b8 98 2d 82 24 a4 90 ed be b3 3d 3e 3d 5c c9 3c
+            47 65 70 3d 1d d7 91 64 2f 1f 11 6a 0d d8 52 be
+            24 19 b2 af 72 bf e9 a0 30 e8 60 b0 28 8b 5d 77";
+
+            //# p's CRT exponent dP:
+            dp = @"
+            0e 12 bf 17 18 e9 ce f5 59 9b a1 c3 88 2f e8 04
+            6a 90 87 4e ef ce 8f 2c cc 20 e4 f2 74 1f b0 a3
+            3a 38 48 ae c9 c9 30 5f be cb d2 d7 68 19 96 7d
+            46 71 ac c6 43 1e 40 37 96 8d b3 78 78 e6 95 c1";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+            95 29 7b 0f 95 a2 fa 67 d0 07 07 d6 09 df d4 fc
+            05 c8 9d af c2 ef 6d 6e a5 5b ec 77 1e a3 33 73
+            4d 92 51 e7 90 82 ec da 86 6e fe f1 3c 45 9e 1a
+            63 13 86 b7 e3 54 c8 99 f5 f1 12 ca 85 d7 15 83";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+            4f 45 6c 50 24 93 bd c0 ed 2a b7 56 a3 a6 ed 4d
+            67 35 2a 69 7d 42 16 e9 32 12 b1 27 a6 3d 54 11
+            ce 6f a9 8d 5d be fd 73 26 3e 37 28 14 27 43 81
+            81 66 ed 7d d6 36 87 dd 2a 8c a1 d2 f4 fb d8 e1";
+        }
+
+        private static void SetupKeysExample2(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# RSA modulus n:
+            n = @"
+            01 94 7c 7f ce 90 42 5f 47 27 9e 70 85 1f 25 d5
+            e6 23 16 fe 8a 1d f1 93 71 e3 e6 28 e2 60 54 3e
+            49 01 ef 60 81 f6 8c 0b 81 41 19 0d 2a e8 da ba
+            7d 12 50 ec 6d b6 36 e9 44 ec 37 22 87 7c 7c 1d
+            0a 67 f1 4b 16 94 c5 f0 37 94 51 a4 3e 49 a3 2d
+            de 83 67 0b 73 da 91 a1 c9 9b c2 3b 43 6a 60 05
+            5c 61 0f 0b af 99 c1 a0 79 56 5b 95 a3 f1 52 66
+            32 d1 d4 da 60 f2 0e da 25 e6 53 c4 f0 02 76 6f
+            45
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+            01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+            08 23 f2 0f ad b5 da 89 08 8a 9d 00 89 3e 21 fa
+            4a 1b 11 fb c9 3c 64 a3 be 0b aa ea 97 fb 3b 93
+            c3 ff 71 37 04 c1 9c 96 3c 1d 10 7a ae 99 05 47
+            39 f7 9e 02 e1 86 de 86 f8 7a 6d de fe a6 d8 cc
+            d1 d3 c8 1a 47 bf a7 25 5b e2 06 01 a4 a4 b2 f0
+            8a 16 7b 5e 27 9d 71 5b 1b 45 5b dd 7e ab 24 59
+            41 d9 76 8b 9a ce fb 3c cd a5 95 2d a3 ce e7 25
+            25 b4 50 16 63 a8 ee 15 c9 e9 92 d9 24 62 fe 39
+            ";
+
+            //# Prime p:
+            p = @"
+            01 59 db de 04 a3 3e f0 6f b6 08 b8 0b 19 0f 4d
+            3e 22 bc c1 3a c8 e4 a0 81 03 3a bf a4 16 ed b0
+            b3 38 aa 08 b5 73 09 ea 5a 52 40 e7 dc 6e 54 37
+            8c 69 41 4c 31 d9 7d db 1f 40 6d b3 76 9c c4 1a
+            43
+            ";
+
+            //# Prime q:
+            q = @"
+            01 2b 65 2f 30 40 3b 38 b4 09 95 fd 6f f4 1a 1a
+            cc 8a da 70 37 32 36 b7 20 2d 39 b2 ee 30 cf b4
+            6d b0 95 11 f6 f3 07 cc 61 cc 21 60 6c 18 a7 5b
+            8a 62 f8 22 df 03 1b a0 df 0d af d5 50 6f 56 8b
+            d7
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+            43 6e f5 08 de 73 65 19 c2 da 4c 58 0d 98 c8 2c
+            b7 45 2a 3f b5 ef ad c3 b9 c7 78 9a 1b c6 58 4f
+            79 5a dd bb d3 24 39 c7 46 86 55 2e cb 6c 2c 30
+            7a 4d 3a f7 f5 39 ee c1 57 24 8c 7b 31 f1 a2 55
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+            01 2b 15 a8 9f 3d fb 2b 39 07 3e 73 f0 2b dd 0c
+            1a 7b 37 9d d4 35 f0 5c dd e2 ef f9 e4 62 94 8b
+            7c ec 62 ee 90 50 d5 e0 81 6e 07 85 a8 56 b4 91
+            08 dc b7 5f 36 83 87 4d 1c a6 32 9a 19 01 30 66
+            ff
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+            02 70 db 17 d5 91 4b 01 8d 76 11 8b 24 38 9a 73
+            50 ec 83 6b 00 63 a2 17 21 23 6f d8 ed b6 d8 9b
+            51 e7 ee b8 7b 61 1b 71 32 cb 7e a7 35 6c 23 15
+            1c 1e 77 51 50 7c 78 6d 9e e1 79 41 70 a8 c8 e8
+            ";
+        }
+
+        private static void SetupKeysExample3(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 3: A 1026-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+02 b5 8f ec 03 9a 86 07 00 a4 d7 b6 46 2f 93 e6
+cd d4 91 16 1d dd 74 f4 e8 10 b4 0e 3c 16 52 00
+6a 5c 27 7b 27 74 c1 13 05 a4 cb ab 5a 78 ef a5
+7e 17 a8 6d f7 a3 fa 36 fc 4b 1d 22 49 f2 2e c7
+c2 dd 6a 46 32 32 ac ce a9 06 d6 6e be 80 b5 70
+4b 10 72 9d a6 f8 33 23 4a bb 5e fd d4 a2 92 cb
+fa d3 3b 4d 33 fa 7a 14 b8 c3 97 b5 6e 3a cd 21
+20 34 28 b7 7c df a3 3a 6d a7 06 b3 d8 b0 fc 43
+e9
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+15 b4 8a 5b 56 83 a9 46 70 e2 3b 57 18 f8 14 fa
+0e 13 f8 50 38 f5 07 11 18 2c ba 61 51 05 81 f3
+d2 2c 7e 23 2e f9 37 e2 2e 55 1d 68 b8 6e 2f 8c
+b1 aa d8 be 2e 48 8f 5d f7 ef d2 79 e3 f5 68 d4
+ea f3 6f 80 cf 71 41 ac e6 0f cc 91 13 fb 6c 4a
+84 1f d5 0b bc 7c 51 2f fc be ff 21 48 7a a8 11
+eb 3c a8 c6 20 05 34 6a 86 de 86 bf a1 d8 a9 48
+fd 3f 34 8c 22 ea ad f3 33 c3 ce 6c e1 32 08 fd
+            ";
+
+            //# Prime p:
+            p = @"
+01 bf 01 d2 16 d7 35 95 cf 02 70 c2 be b7 8d 40
+a0 d8 44 7d 31 da 91 9a 98 3f 7e ea 78 1b 77 d8
+5f e3 71 b3 e9 37 3e 7b 69 21 7d 31 50 a0 2d 89
+58 de 7f ad 9d 55 51 60 95 8b 44 54 12 7e 0e 7e
+af
+            ";
+
+            //# Prime q:
+            q = @"
+01 8d 33 99 65 81 66 db 38 29 81 6d 7b 29 54 16
+75 9e 9c 91 98 7f 5b 2d 8a ec d6 3b 04 b4 8b d7
+b2 fc f2 29 bb 7f 8a 6d c8 8b a1 3d d2 e3 9a d5
+5b 6d 1a 06 16 07 08 f9 70 0b e8 0b 8f d3 74 4c
+e7
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+06 c0 a2 49 d2 0a 6f 2e e7 5c 88 b4 94 d5 3f 6a
+ae 99 aa 42 7c 88 c2 8b 16 3a 76 94 45 e5 f3 90
+cf 40 c2 74 fd 6e a6 32 9a 5c e7 c7 ce 03 a2 15
+83 96 ee 2a 78 45 78 6e 09 e2 88 5a 97 28 e4 e5
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+d1 d2 7c 29 fe dd 92 d8 6c 34 8e dd 0c cb fa c1
+4f 74 6e 05 1c e1 d1 81 1d f3 5d 61 f2 ee 1c 97
+d4 bf 28 04 80 2f 64 27 18 7b a8 e9 0a 8a f4 42
+43 b4 07 9b 03 44 5e 60 2e 29 fa 51 93 e6 4f e9
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+8c b2 f7 56 bd 89 41 b1 d3 b7 70 e5 ad 31 ee 37
+3b 28 ac da 69 ff 9b 6f 40 fe 57 8b 9f 1a fb 85
+83 6f 96 27 d3 7a cf f7 3c 27 79 e6 34 bb 26 01
+1c 2c 8f 7f 33 61 ae 2a 9e a6 5e d6 89 e3 63 9a
+            ";
+        }
+
+        private static void SetupKeysExample4(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 4: A 1027-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+05 12 40 b6 cc 00 04 fa 48 d0 13 46 71 c0 78 c7
+c8 de c3 b3 e2 f2 5b c2 56 44 67 33 9d b3 88 53
+d0 6b 85 ee a5 b2 de 35 3b ff 42 ac 2e 46 bc 97
+fa e6 ac 96 18 da 95 37 a5 c8 f5 53 c1 e3 57 62
+59 91 d6 10 8d cd 78 85 fb 3a 25 41 3f 53 ef ca
+d9 48 cb 35 cd 9b 9a e9 c1 c6 76 26 d1 13 d5 7d
+de 4c 5b ea 76 bb 5b b7 de 96 c0 0d 07 37 2e 96
+85 a6 d7 5c f9 d2 39 fa 14 8d 70 93 1b 5f 3f b0
+39
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+04 11 ff ca 3b 7c a5 e9 e9 be 7f e3 8a 85 10 5e
+35 38 96 db 05 c5 79 6a ec d2 a7 25 16 1e b3 65
+1c 86 29 a9 b8 62 b9 04 d7 b0 c7 b3 7f 8c b5 a1
+c2 b5 40 01 01 8a 00 a1 eb 2c af e4 ee 4e 94 92
+c3 48 bc 2b ed ab 4b 9e bb f0 64 e8 ef f3 22 b9
+00 9f 8e ec 65 39 05 f4 0d f8 8a 3c dc 49 d4 56
+7f 75 62 7d 41 ac a6 24 12 9b 46 a0 b7 c6 98 e5
+e6 5f 2b 7b a1 02 c7 49 a1 01 35 b6 54 0d 04 01
+            ";
+
+            //# Prime p:
+            p = @"
+02 74 58 c1 9e c1 63 69 19 e7 36 c9 af 25 d6 09
+a5 1b 8f 56 1d 19 c6 bf 69 43 dd 1e e1 ab 8a 4a
+3f 23 21 00 bd 40 b8 8d ec c6 ba 23 55 48 b6 ef
+79 2a 11 c9 de 82 3d 0a 79 22 c7 09 5b 6e ba 57
+01
+            ";
+
+            //# Prime q:
+            q = @"
+02 10 ee 9b 33 ab 61 71 6e 27 d2 51 bd 46 5f 4b
+35 a1 a2 32 e2 da 00 90 1c 29 4b f2 23 50 ce 49
+0d 09 9f 64 2b 53 75 61 2d b6 3b a1 f2 03 86 49
+2b f0 4d 34 b3 c2 2b ce b9 09 d1 34 41 b5 3b 51
+39
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+39 fa 02 8b 82 6e 88 c1 12 1b 75 0a 8b 24 2f a9
+a3 5c 5b 66 bd fd 1f a6 37 d3 cc 48 a8 4a 4f 45
+7a 19 4e 77 27 e4 9f 7b cc 6e 5a 5a 41 26 57 fc
+47 0c 73 22 eb c3 74 16 ef 45 8c 30 7a 8c 09 01
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+01 5d 99 a8 41 95 94 39 79 fa 9e 1b e2 c3 c1 b6
+9f 43 2f 46 fd 03 e4 7d 5b ef bb bf d6 b1 d1 37
+1d 83 ef b3 30 a3 e0 20 94 2b 2f ed 11 5e 5d 02
+be 24 fd 92 c9 01 9d 1c ec d6 dd 4c f1 e5 4c c8
+99
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+01 f0 b7 01 51 70 b3 f5 e4 22 23 ba 30 30 1c 41
+a6 d8 7c bb 70 e3 0c b7 d3 c6 7d 25 47 3d b1 f6
+cb f0 3e 3f 91 26 e3 e9 79 68 27 9a 86 5b 2c 2b
+42 65 24 cf c5 2a 68 3d 31 ed 30 eb 98 4b e4 12
+ba
+            ";
+        }
+
+        private static void SetupKeysExample5(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 5: A 1028-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+0a ad f3 f9 c1 25 e5 d8 91 f3 1a c4 48 e9 93 de
+fe 58 0f 80 2b 45 f9 d7 f2 2b a5 02 1e 9c 47 57
+6b 5a 1e 68 03 1b a9 db 4e 6d ab e4 d9 6a 1d 6f
+3d 26 72 68 cf f4 08 00 5f 11 8e fc ad b9 98 88
+d1 c2 34 46 71 66 b2 a2 b8 49 a0 5a 88 9c 06 0a
+c0 da 0c 5f ae 8b 55 f3 09 ba 62 e7 03 74 2f a0
+32 6f 2d 10 b0 11 02 14 89 ff 49 77 70 19 0d 89
+5f d3 9f 52 29 3c 39 ef d7 3a 69 8b da b9 f1 0e
+d9
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+02 56 eb 4c ba 70 67 f2 d2 be 54 0d cd ff 45 82
+a3 6b 7d 31 d1 c9 09 9b b2 14 b7 98 48 46 6a 26
+8f 80 f5 8a 49 ac 04 c0 e3 64 89 34 a0 20 6c 04
+53 7c 19 b2 36 64 3a 60 82 73 21 44 df 75 fa 21
+75 88 f7 94 68 2b e8 91 68 27 6d c7 26 c5 c0 cb
+db 84 d3 1b bf 26 d0 a4 3a f4 95 71 7f 7d 52 8a
+cf ee 34 15 61 f6 ff 3c ae 05 c5 78 f8 47 0d 96
+82 f9 c0 d0 72 f9 f6 06 8b 56 d5 88 0f 68 2b e2
+c5
+            ";
+
+            //# Prime p:
+            p = @"
+03 b0 d3 96 2f 6d 17 54 9c bf ca 11 29 43 48 dc
+f0 e7 e3 9f 8c 2b c6 82 4f 21 64 b6 06 d6 87 86
+0d ae 1e 63 23 93 cf ed f5 13 22 82 29 06 9e 2f
+60 e4 ac d7 e6 33 a4 36 06 3f 82 38 5f 48 99 37
+07
+            ";
+
+            //# Prime q:
+            q = @"
+02 e4 c3 2e 2f 51 72 69 b7 07 23 09 f0 0c 0e 31
+36 5f 7c e2 8b 23 6b 82 91 2d f2 39 ab f3 95 72
+cf 0e d6 04 b0 29 82 e5 35 64 c5 2d 6a 05 39 7d
+e5 c0 52 a2 fd dc 14 1e f7 18 98 36 34 6a eb 33
+1f
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+01 e8 4b 11 9d 25 16 1f a6 7b 00 25 6a 5b d9 b6
+45 d2 b2 32 ec b0 5b 01 51 80 02 9a 88 62 2a dc
+3f 09 b3 ae ac de 61 61 ab 7c de 22 c2 ad 26 e7
+79 7d f5 4e 07 2c bd 3b 26 73 80 0b 3e 43 38 db
+d5
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+eb 90 aa 1a 40 13 5b 4c ea 07 19 7c ed c8 81 9b
+e1 e7 cb ff 25 47 66 21 16 f4 65 a4 a9 f4 87 ab
+12 f3 ba 4f ef 13 82 22 65 a6 52 97 d9 8b 7b de
+d9 37 2e 3f fe 81 a3 8b 3e 96 00 fe d0 55 75 4f
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+01 2f 7f 81 38 f9 40 40 62 eb 85 a4 29 24 52 0b
+38 f5 bb 88 6a 01 96 f4 8b b8 dc ea 60 fd 92 cc
+02 7f 18 e7 81 58 a3 4a 5c 5d 5f 86 0a 0f 6c 04
+07 1a 7d 01 31 2c 06 50 62 f1 eb 48 b7 9d 1c 83
+cb
+            ";
+        }
+
+        private static void SetupKeysExample6(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 6: A 1029-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+12 b1 7f 6d ad 2e cd 19 ff 46 dc 13 f7 86 0f 09
+e0 e0 cf b6 77 b3 8a 52 59 23 05 ce af 02 2c 16
+6d b9 0d 04 ac 29 e3 3f 7d d1 2d 9f af 66 e0 81
+6b b6 3e ad 26 7c c7 d4 6c 17 c3 7b e2 14 bc a2
+a2 2d 72 3a 64 e4 44 07 43 6b 6f c9 65 72 9a ef
+c2 55 4f 37 6c d5 dc ea 68 29 37 80 a6 2b f3 9d
+00 29 48 5a 16 0b bb 9e 5d c0 97 2d 21 a5 04 f5
+2e 5e e0 28 aa 41 63 32 f5 10 b2 e9 cf f5 f7 22
+af
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+02 95 ec a3 56 06 18 36 95 59 ce cd 30 3a a9 cf
+da fc 1d 9f 06 95 9d f7 5f fe f9 29 aa 89 69 61
+bc d1 90 dc 69 97 ed a7 f5 96 3e 72 4d 07 b4 dc
+11 f3 06 5e 5a e9 7d 96 83 51 12 28 0b 90 84 bb
+14 f2 a2 1e bd 4e 88 9d 41 b9 c4 13 2e c1 95 6f
+ca b8 bb 2f ed 05 75 88 49 36 52 2c 5f f7 d3 32
+61 90 48 24 e7 ca de e4 e0 bb 37 2d 24 57 cf 78
+e2 bd 12 86 22 8f f8 3f 10 73 1c e6 3c 90 cf f3
+f9
+            ";
+
+            //# Prime p:
+            p = @"
+04 a6 ce 8b 73 58 df a6 9b dc f7 42 61 70 05 af
+b5 38 5f 5f 3a 58 a2 4e f7 4a 22 a8 c0 5c b7 cc
+38 eb d4 cc 9d 9a 9d 78 9a 62 cd 0f 60 f0 cb 94
+1d 34 23 c9 69 2e fa 4f e3 ad ff 29 0c 47 49 a3
+8b
+            ";
+
+            //# Prime q:
+            q = @"
+04 04 c9 a8 03 37 1f ed b4 c5 be 39 f3 c0 0b 00
+9e 5e 08 a6 3b e1 e4 00 35 cd ac a5 01 1c c7 01
+cf 7e eb cb 99 f0 ff e1 7c fd 0a 4b f7 be fd 2d
+d5 36 ac 94 6d b7 97 fd bc 4a be 8f 29 34 9b 91
+ed
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+03 96 1c 8f 76 0a a2 bd 51 54 c7 aa fd 77 22 5b
+3b ac d0 13 9a e7 b5 94 8e a3 31 1f cc d8 6f b9
+5c 75 af a7 67 28 4b 9b 2d e5 59 57 2f 15 d8 d0
+44 c7 eb 83 a1 be 5f ad f2 cc 37 7c 0d 84 75 29
+4b
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+02 21 97 e0 66 74 21 96 aa bc 03 fa 2f ee b4 e7
+0b 15 cb 78 7d 61 7a cd 31 bb 75 c7 bc 23 4a d7
+06 f7 c4 8d 21 82 d1 f0 ff 9c 22 8d cf 41 96 7b
+6c 0b a6 d2 c0 ad 11 0a 1b 85 78 31 ec 24 5e 2c
+b1
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+04 01 c4 c0 c5 3d 45 db db 5e 9d 96 d0 fe cf 42
+75 df 09 74 bc 4a 07 36 b4 a7 4c 32 69 05 3e fb
+68 6a ce 24 06 e2 2c 9e 05 8d db 4a e5 40 62 7a
+e2 fd b0 82 61 e8 e7 e4 bc bc 99 4d aa fa 30 5c
+45
+            ";
+        }
+
+        private static void SetupKeysExample7(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 7: A 1030-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+31 11 79 f0 bc fc 9b 9d 3c a3 15 d0 0e f3 0d 7b
+dd 3a 2c fa e9 91 1b fe dc b9 48 b3 a4 78 2d 07
+32 b6 ab 44 aa 4b f0 37 41 a6 44 dc 01 be c3 e6
+9b 01 a0 33 e6 75 d8 ac d7 c4 92 5c 6b 1a ec 31
+19 05 1d fd 89 76 2d 21 5d 45 47 5f fc b5 9f 90
+81 48 62 3f 37 17 71 56 f6 ae 86 dd 7a 7c 5f 43
+dc 1e 1f 90 82 54 05 8a 28 4a 5f 06 c0 02 17 93
+a8 7f 1a c5 fe ff 7d ca ee 69 c5 e5 1a 37 89 e3
+73
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+07 0c fc ff 2f eb 82 76 e2 74 32 c4 5d fe e4 8f
+49 b7 91 7d 65 30 e1 f0 ca 34 60 f3 2e 02 76 17
+44 87 c5 6e 22 a4 5d 25 00 d7 77 54 95 21 9d 7d
+16 5a 9c f3 bd 92 c3 2a f9 a9 8d 8d c9 cc 29 68
+00 ad c9 4a 0a 54 fb 40 f3 42 91 bf 84 ee 8e a1
+2b 6f 10 93 59 c6 d3 54 2a 50 f9 c7 67 f5 cf ff
+05 a6 81 c2 e6 56 fb 77 ca aa db 4b e9 46 8d 8a
+bc d4 df 98 f5 8e 86 d2 05 3f a1 34 9f 74 8e 21
+b1
+            ";
+
+            //# Prime p:
+            p = @"
+07 49 26 2c 11 1c d4 70 ec 25 66 e6 b3 73 2f c0
+93 29 46 9a a1 90 71 d3 b9 c0 19 06 51 4c 6f 1d
+26 ba a1 4b ea b0 97 1c 8b 7e 61 1a 4f 79 00 9d
+6f ea 77 69 28 ca 25 28 5b 0d e3 64 3d 1a 3f 8c
+71
+            ";
+
+            //# Prime q:
+            q = @"
+06 bc 1e 50 e9 6c 02 bf 63 6e 9e ea 8b 89 9b be
+bf 76 51 de 77 dd 47 4c 3e 9b c2 3b ad 81 82 b6
+19 04 c7 d9 7d fb eb fb 1e 00 10 88 78 b6 e6 7e
+41 53 91 d6 79 42 c2 b2 bf 9b 44 35 f8 8b 0c b0
+23
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+03 bc 7e a7 f0 aa b1 43 ab c6 ce 8b 97 11 86 36
+a3 01 72 e4 cf e0 2c 8f a0 dd a3 b7 ba af 90 f8
+09 29 82 98 55 25 f4 88 bd fc b4 bd 72 6e 22 63
+9a c6 4a 30 92 ab 7f fc bf 1d 53 34 cf a5 0b 5b
+f1
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+02 62 a6 aa 29 c2 a3 c6 7d c5 34 6c 06 38 1a fd
+98 7a a3 cc 93 cf bf ec f5 4f dd 9f 9d 78 7d 7f
+59 a5 23 d3 98 97 9d a1 37 a2 f6 38 1f e9 48 01
+f7 c9 4d a2 15 18 dc 34 cb 40 87 0c 46 97 99 4a
+d9
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+64 9d 4c 17 b6 ee 17 21 e7 72 d0 38 9a 55 9c 3d
+3c df 95 50 d4 57 c4 6b 03 7b 74 64 1b 1d 52 16
+6a f8 a2 13 c8 39 62 06 cd fb a4 42 2f 18 d6 f6
+1d bc b5 d2 14 c9 71 bf 48 2a eb 97 6a 73 70 c2
+            ";
+        }
+
+        private static void SetupKeysExample8(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 8: A 1031-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+5b df 0e 30 d3 21 dd a5 14 7f 88 24 08 fa 69 19
+54 80 df 8f 80 d3 f6 e8 bf 58 18 50 4f 36 42 7c
+a9 b1 f5 54 0b 9c 65 a8 f6 97 4c f8 44 7a 24 4d
+92 80 20 1b b4 9f cb be 63 78 d1 94 4c d2 27 e2
+30 f9 6e 3d 10 f8 19 dc ef 27 6c 64 a0 0b 2a 4b
+67 01 e7 d0 1d e5 fa bd e3 b1 e9 a0 df 82 f4 63
+13 59 cd 22 66 96 47 fb b1 71 72 46 13 4e d7 b4
+97 cf ff bd c4 2b 59 c7 3a 96 ed 90 16 62 12 df
+f7
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+0f 7d 1e 9e 5a aa 25 fd 13 e4 a0 66 3a e1 44 e0
+d1 5f 5c d1 8b cd b0 9d f2 cc 7e 64 e3 c5 e9 15
+ad 62 64 53 04 16 1d 09 8c 71 5b b7 ab 8b d0 1d
+07 ea f3 fe d7 c7 ed 08 af 2a 8a 62 ef 44 ab 16
+b3 20 e1 4a f7 2a 48 f9 6a fe 26 2a 0a e4 cf 65
+e6 35 e9 10 79 0c d4 ee 5c ea 76 8a 4b 26 39 f7
+e6 f6 77 b3 f0 bb 6b e3 2b 75 74 7d 89 09 03 6f
+02 64 f5 8d 40 1c db a1 31 71 61 57 a7 5e cf 63
+31
+            ";
+
+            //# Prime p:
+            p = @"
+0a 02 ef 84 48 d9 fa d8 bb d0 d0 04 c8 c2 aa 97
+51 ef 97 21 c1 b0 d0 32 36 a5 4b 0d f9 47 cb ae
+d5 a2 55 ee 9e 8e 20 d4 91 ea 17 23 fe 09 47 04
+a9 76 2e 88 af d1 6e bb 59 94 41 2c a9 66 dc 4f
+9f
+            ";
+
+            //# Prime q:
+            q = @"
+09 2d 36 2e 7e d3 a0 bf d9 e9 fd 0e 6c 03 01 b6
+df 29 15 9c f5 0c c8 3b 9b 0c f4 d6 ee a7 1a 61
+e0 02 b4 6e 0a e9 f2 de 62 d2 5b 5d 74 52 d4 98
+b8 1c 9a c6 fc 58 59 3d 4c 3f b4 f5 d7 2d fb b0
+a9
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+07 c7 14 10 af 10 39 62 db 36 74 04 e3 7a e8 50
+ba a4 e9 c2 9d d9 21 45 81 52 94 a6 7c 7d 1c 6d
+ed 26 3a a0 30 a9 b6 33 ae 50 30 3e 14 03 5d 1a
+f0 14 12 3e ba 68 78 20 30 8d 8e bc 85 b6 95 7d
+7d
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+ae 2c 75 38 0c 02 c0 16 ad 05 89 1b 33 01 de 88
+1f 28 ae 11 71 18 2b 6b 2c 83 be a7 c5 15 ec a9
+ca 29 8c 7b 1c ab 58 17 a5 97 06 8f c8 50 60 de
+4d a8 a0 16 37 8a ae 43 c7 f9 67 bc c3 79 04 b9
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+05 98 d1 05 9e 3a da 4f 63 20 75 2c 09 d8 05 ff
+7d 1f 1a e0 d0 17 ae ee e9 ce fa 0d 7d d7 ff 77
+5e 44 b5 78 32 2f 64 05 d6 21 1d a1 95 19 66 6a
+a8 7f dc 4c d8 c8 8f 6b 6e 3d 67 e9 61 dc bb a3
+d0
+            ";
+        }
+
+        private static void SetupKeysExample9(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ==================================
+            //# Example 9: A 1536-bit RSA Key Pair
+            //# ==================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+cf 2c d4 1e 34 ca 3a 72 8e a5 cb 8a ff 64 c3 6d
+27 bd ef 53 64 e3 36 fd 68 d3 12 3c 5a 19 6a 8c
+28 70 13 e8 53 d5 15 6d 58 d1 51 95 45 20 fb 4f
+6d 7b 17 ab b6 81 77 65 90 9c 57 61 19 65 9d 90
+2b 19 06 ed 8a 2b 10 c1 55 c2 4d 12 45 28 da b9
+ee ae 37 9b ea c6 6e 4a 41 17 86 dc b8 fd 00 62
+eb c0 30 de 12 19 a0 4c 2a 8c 1b 7d d3 13 1e 4d
+6b 6c ae e2 e3 1a 5e d4 1a c1 50 9b 2e f1 ee 2a
+b1 83 64 be 56 8c a9 41 c2 5e cc 84 ff 9d 64 3b
+5e c1 aa ae 10 2a 20 d7 3f 47 9b 78 0f d6 da 91
+07 52 12 d9 ea c0 3a 06 74 d8 99 eb a2 e4 31 f4
+c4 4b 61 5b 6b a2 23 2b d4 b3 3b ae d7 3d 62 5d
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+19 8c 14 1e 23 71 5a 92 bc cf 6a 11 9a 5b c1 13
+89 46 8d 28 11 f5 48 d7 27 e1 7b 4a b0 eb 98 6d
+6f 21 1e fb 53 b7 1f 7c cb ea 87 ee 69 c7 5e e6
+15 00 8c 53 32 de b5 2b f3 90 ab df bf e3 7d 72
+05 36 81 59 b2 63 8c 1d e3 26 e2 1d 22 25 1f 0f
+b5 84 8b 3b f1 50 05 d2 a7 43 30 f0 af e9 16 ee
+62 cc c1 34 4d 1d 83 a7 09 e6 06 76 27 38 40 f7
+f3 77 42 4a 5e 0a 4d a7 5f 01 b3 1f f7 68 19 cf
+9c bf dd 21 52 43 c3 91 7c 03 ef 38 19 93 12 e5
+67 b3 bf 7a ed 3a b4 57 f3 71 ef 8a 14 23 f4 5b
+68 c6 e2 82 ec 11 1b ba 28 33 b9 87 fd 69 fa d8
+3b c1 b8 c6 13 c5 e1 ea 16 c1 1e d1 25 ea 7e c1
+            ";
+
+            //# Prime p:
+            p = @"
+fc 8d 6c 04 be c4 eb 9a 81 92 ca 79 00 cb e5 36
+e2 e8 b5 19 de cf 33 b2 45 97 98 c6 90 9d f4 f1
+76 db 7d 23 19 0f c7 2b 88 65 a7 18 af 89 5f 1b
+cd 91 45 29 80 27 42 3b 60 5e 70 a4 7c f5 83 90
+a8 c3 e8 8f c8 c4 8e 8b 32 e3 da 21 0d fb e3 e8
+81 ea 56 74 b6 a3 48 c2 1e 93 f9 e5 5e a6 5e fd
+            ";
+
+            //# Prime q:
+            q = @"
+d2 00 d4 5e 78 8a ac ea 60 6a 40 1d 04 60 f8 7d
+d5 c1 02 7e 12 dc 1a 0d 75 86 e8 93 9d 9c f7 89
+b4 0f 51 ac 04 42 96 1d e7 d2 1c c2 1e 05 c8 31
+55 c1 f2 aa 91 93 38 7c fd f9 56 cb 48 d1 53 ba
+27 04 06 f9 bb ba 53 7d 49 87 d9 e2 f9 94 2d 7a
+14 cb ff fe a7 4f ec dd a9 28 d2 3e 25 9f 5e e1
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+db 16 80 2f 79 a2 f0 d4 5f 35 8d 69 fd 33 e4 4b
+81 fa e8 28 62 2e 93 a5 42 53 e9 97 d0 1b 07 43
+75 9d a0 e8 12 b4 aa 4e 6c 8b ea b2 32 8d 54 31
+95 5a 41 8a 67 ff 26 a8 c5 c8 07 a5 da 35 4e 05
+ef 31 cc 8c f7 58 f4 63 73 29 50 b0 3e 26 57 26
+fb 94 e3 9d 6a 57 2a 26 24 4a b0 8d b7 57 52 ad
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+a0 a3 17 cf e7 df 14 23 f8 7a 6d ee 84 51 f4 e2
+b4 a6 7e 54 97 f2 9b 4f 1e 4e 83 0b 9f ad d9 40
+11 67 02 6f 55 96 e5 a3 9c 97 81 7e 0f 5f 16 e2
+7e 19 ec 99 02 e0 1d 7e a6 fb 9a a3 c7 60 af ee
+1e 38 1b 69 de 6a c9 c0 75 85 a0 6a d9 c4 ba 00
+bf 75 c8 ad 2f a8 98 a4 79 e8 0a e2 94 fe d2 a1
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+0b 21 f3 35 c3 53 34 2e b4 4c 3a a2 44 45 78 0c
+2d 65 5b 94 01 74 ca e3 8c 7c 8a 4e 64 93 c0 ba
+9f d3 03 74 82 67 b0 83 b9 a7 a6 cb 61 e4 2d b3
+62 b8 c9 89 6d b7 06 4e 02 ad 5a e6 15 87 da 15
+b4 64 9c 90 59 49 09 fe b3 7d bc b6 54 be b7 26
+8e c8 01 e5 a8 b4 aa 39 11 be bd 88 54 2f 05 be
+            ";
+        }
+
+        private static void SetupKeysExample10(out string n, out string e, out string d, out string p, out string q, out string dp, out string dq, out string qinv)
+        {
+            //# ===================================
+            //# Example 10: A 2048-bit RSA Key Pair
+            //# ===================================
+
+            //# ------------------------------
+            //# Components of the RSA Key Pair
+            //# ------------------------------
+
+            //# RSA modulus n:
+            n = @"
+ae 45 ed 56 01 ce c6 b8 cc 05 f8 03 93 5c 67 4d
+db e0 d7 5c 4c 09 fd 79 51 fc 6b 0c ae c3 13 a8
+df 39 97 0c 51 8b ff ba 5e d6 8f 3f 0d 7f 22 a4
+02 9d 41 3f 1a e0 7e 4e be 9e 41 77 ce 23 e7 f5
+40 4b 56 9e 4e e1 bd cf 3c 1f b0 3e f1 13 80 2d
+4f 85 5e b9 b5 13 4b 5a 7c 80 85 ad ca e6 fa 2f
+a1 41 7e c3 76 3b e1 71 b0 c6 2b 76 0e de 23 c1
+2a d9 2b 98 08 84 c6 41 f5 a8 fa c2 6b da d4 a0
+33 81 a2 2f e1 b7 54 88 50 94 c8 25 06 d4 01 9a
+53 5a 28 6a fe b2 71 bb 9b a5 92 de 18 dc f6 00
+c2 ae ea e5 6e 02 f7 cf 79 fc 14 cf 3b dc 7c d8
+4f eb bb f9 50 ca 90 30 4b 22 19 a7 aa 06 3a ef
+a2 c3 c1 98 0e 56 0c d6 4a fe 77 95 85 b6 10 76
+57 b9 57 85 7e fd e6 01 09 88 ab 7d e4 17 fc 88
+d8 f3 84 c4 e6 e7 2c 3f 94 3e 0c 31 c0 c4 a5 cc
+36 f8 79 d8 a3 ac 9d 7d 59 86 0e aa da 6b 83 bb
+            ";
+
+            //# RSA public exponent e:
+            e = @"
+01 00 01
+            ";
+
+            //# RSA private exponent d:
+            d = @"
+05 6b 04 21 6f e5 f3 54 ac 77 25 0a 4b 6b 0c 85
+25 a8 5c 59 b0 bd 80 c5 64 50 a2 2d 5f 43 8e 59
+6a 33 3a a8 75 e2 91 dd 43 f4 8c b8 8b 9d 5f c0
+d4 99 f9 fc d1 c3 97 f9 af c0 70 cd 9e 39 8c 8d
+19 e6 1d b7 c7 41 0a 6b 26 75 df bf 5d 34 5b 80
+4d 20 1a dd 50 2d 5c e2 df cb 09 1c e9 99 7b be
+be 57 30 6f 38 3e 4d 58 81 03 f0 36 f7 e8 5d 19
+34 d1 52 a3 23 e4 a8 db 45 1d 6f 4a 5b 1b 0f 10
+2c c1 50 e0 2f ee e2 b8 8d ea 4a d4 c1 ba cc b2
+4d 84 07 2d 14 e1 d2 4a 67 71 f7 40 8e e3 05 64
+fb 86 d4 39 3a 34 bc f0 b7 88 50 1d 19 33 03 f1
+3a 22 84 b0 01 f0 f6 49 ea f7 93 28 d4 ac 5c 43
+0a b4 41 49 20 a9 46 0e d1 b7 bc 40 ec 65 3e 87
+6d 09 ab c5 09 ae 45 b5 25 19 01 16 a0 c2 61 01
+84 82 98 50 9c 1c 3b f3 a4 83 e7 27 40 54 e1 5e
+97 07 50 36 e9 89 f6 09 32 80 7b 52 57 75 1e 79
+            ";
+
+            //# Prime p:
+            p = @"
+ec f5 ae cd 1e 55 15 ff fa cb d7 5a 28 16 c6 eb
+f4 90 18 cd fb 46 38 e1 85 d6 6a 73 96 b6 f8 09
+0f 80 18 c7 fd 95 cc 34 b8 57 dc 17 f0 cc 65 16
+bb 13 46 ab 4d 58 2c ad ad 7b 41 03 35 23 87 b7
+03 38 d0 84 04 7c 9d 95 39 b6 49 62 04 b3 dd 6e
+a4 42 49 92 07 be c0 1f 96 42 87 ff 63 36 c3 98
+46 58 33 68 46 f5 6e 46 86 18 81 c1 02 33 d2 17
+6b f1 5a 5e 96 dd c7 80 bc 86 8a a7 7d 3c e7 69
+            ";
+
+            //# Prime q:
+            q = @"
+bc 46 c4 64 fc 6a c4 ca 78 3b 0e b0 8a 3c 84 1b
+77 2f 7e 9b 2f 28 ba bd 58 8a e8 85 e1 a0 c6 1e
+48 58 a0 fb 25 ac 29 99 90 f3 5b e8 51 64 c2 59
+ba 11 75 cd d7 19 27 07 13 51 84 99 2b 6c 29 b7
+46 dd 0d 2c ab e1 42 83 5f 7d 14 8c c1 61 52 4b
+4a 09 94 6d 48 b8 28 47 3f 1c e7 6b 6c b6 88 6c
+34 5c 03 e0 5f 41 d5 1b 5c 3a 90 a3 f2 40 73 c7
+d7 4a 4f e2 5d 9c f2 1c 75 96 0f 3f c3 86 31 83
+            ";
+
+            //# p's CRT exponent dP:
+            dp = @"
+c7 35 64 57 1d 00 fb 15 d0 8a 3d e9 95 7a 50 91
+5d 71 26 e9 44 2d ac f4 2b c8 2e 86 2e 56 73 ff
+6a 00 8e d4 d2 e3 74 61 7d f8 9f 17 a1 60 b4 3b
+7f da 9c b6 b6 b7 42 18 60 98 15 f7 d4 5c a2 63
+c1 59 aa 32 d2 72 d1 27 fa f4 bc 8c a2 d7 73 78
+e8 ae b1 9b 0a d7 da 3c b3 de 0a e7 31 49 80 f6
+2b 6d 4b 0a 87 5d 1d f0 3c 1b ae 39 cc d8 33 ef
+6c d7 e2 d9 52 8b f0 84 d1 f9 69 e7 94 e9 f6 c1
+            ";
+
+            //# q's CRT exponent dQ:
+            dq = @"
+26 58 b3 7f 6d f9 c1 03 0b e1 db 68 11 7f a9 d8
+7e 39 ea 2b 69 3b 7e 6d 3a 2f 70 94 74 13 ee c6
+14 2e 18 fb 8d fc b6 ac 54 5d 7c 86 a0 ad 48 f8
+45 71 70 f0 ef b2 6b c4 81 26 c5 3e fd 1d 16 92
+01 98 dc 2a 11 07 dc 28 2d b6 a8 0c d3 06 23 60
+ba 3f a1 3f 70 e4 31 2f f1 a6 cd 6b 8f c4 cd 9c
+5c 3d b1 7c 6d 6a 57 21 2f 73 ae 29 f6 19 32 7b
+ad 59 b1 53 85 85 85 ba 4e 28 b6 0a 62 a4 5e 49
+            ";
+
+            //# CRT coefficient qInv:
+            qinv = @"
+6f 38 52 6b 39 25 08 55 34 ef 3e 41 5a 83 6e de
+8b 86 15 8a 2c 7c bf ec cb 0b d8 34 30 4f ec 68
+3b a8 d4 f4 79 c4 33 d4 34 16 e6 32 69 62 3c ea
+10 07 76 d8 5a ff 40 1d 3f ff 61 0e e6 54 11 ce
+3b 13 63 d6 3a 97 09 ee de 42 64 7c ea 56 14 93
+d5 45 70 a8 79 c1 86 82 cd 97 71 0b 96 20 5e c3
+11 17 d7 3b 5f 36 22 3f ad d6 e8 ba 90 dd 7c 0e
+e6 1d 44 e1 63 25 1e 20 c7 f6 6e b3 05 11 7c b8
+            ";
+        }
+
+        private static void RunOneCase(string testcase, string n, string e, string d, string p, string q, string dp, string dq, string qinv, string message, string seed, string encryption)
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new InjectedBytesRandomGenerator(seed.FromHex()));
+
+            IAsymmetricKeyPair keyPair = Factory.Instance.Singleton<IAsymmetricFactory>().CreateKeyPair(PositiveFromHex(n), PositiveFromHex(e), PositiveFromHex(d), PositiveFromHex(p), PositiveFromHex(q), PositiveFromHex(dp), PositiveFromHex(dq), PositiveFromHex(qinv));
+
+            byte[] cipher = keyPair.PublicKey.Transform(message.FromHex());
+            Assert.That(cipher, Is.EquivalentTo(encryption.FromHex()), testcase);
+
+            byte[] deciphered = keyPair.PrivateKey.Transform(cipher);
+            Assert.That(deciphered, Is.EquivalentTo(message.FromHex()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/Endian.cs b/Axantum.AxCrypt.Core.Test/Endian.cs
new file mode 100644
index 0000000..d845678
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Endian.cs
@@ -0,0 +1,35 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal enum Endian
+    {
+        Reverse,
+        Actual
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/Extensions.cs b/Axantum.AxCrypt.Core.Test/Extensions.cs
new file mode 100644
index 0000000..eb07974
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Extensions.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal static class Extensions
+    {
+        public static string PathCombine(this string path, params string[] parts)
+        {
+            foreach (string part in parts)
+            {
+                path = Path.Combine(path, part);
+            }
+            return path;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeAsymmetricFactory.cs b/Axantum.AxCrypt.Core.Test/FakeAsymmetricFactory.cs
new file mode 100644
index 0000000..c0f3c20
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeAsymmetricFactory.cs
@@ -0,0 +1,131 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeAsymmetricFactory : IAsymmetricFactory
+    {
+        private IAsymmetricFactory _factory = new BouncyCastleAsymmetricFactory();
+
+        private string _paddingHashAlgorithm;
+
+        public FakeAsymmetricFactory(string paddingHashAlgorithm)
+        {
+            _paddingHashAlgorithm = paddingHashAlgorithm;
+        }
+
+        public JsonConverter[] GetConverters()
+        {
+            return _factory.GetConverters();
+        }
+
+        public IAsymmetricPrivateKey CreatePrivateKey(string privateKeyPem)
+        {
+            return _factory.CreatePrivateKey(privateKeyPem); ;
+        }
+
+        public IAsymmetricPublicKey CreatePublicKey(string publicKeyPem)
+        {
+            return _factory.CreatePublicKey(publicKeyPem);
+        }
+
+        public IAsymmetricKeyPair CreateKeyPair(int bits)
+        {
+            return _factory.CreateKeyPair(bits);
+        }
+
+        public IAsymmetricKeyPair CreateKeyPair(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] qinv)
+        {
+            return _factory.CreateKeyPair(n, e, d, p, q, dp, dq, qinv);
+        }
+
+        public IPaddingHash CreatePaddingHash()
+        {
+            return new FakePaddingHash(_paddingHashAlgorithm);
+        }
+
+        private class FakePaddingHash : IPaddingHash
+        {
+            private HashAlgorithm _hash;
+
+            private string _paddingHashAlgorithm;
+
+            public FakePaddingHash(string paddingHashAlgorithm)
+            {
+                _paddingHashAlgorithm = paddingHashAlgorithm;
+                Reset();
+            }
+
+            public string AlgorithmName
+            {
+                get { return _paddingHashAlgorithm; }
+            }
+
+            public int HashSize
+            {
+                get { return _hash.HashSize / 8; }
+            }
+
+            public int BufferLength
+            {
+                get { return _hash.InputBlockSize / 8; }
+            }
+
+            public void Update(byte input)
+            {
+                byte[] buffer = new byte[] { input };
+                _hash.TransformBlock(buffer, 0, 1, buffer, 0);
+            }
+
+            public void BlockUpdate(byte[] input, int offset, int length)
+            {
+                _hash.TransformBlock(input, offset, length, input, offset);
+            }
+
+            public int DoFinal(byte[] output, int offset)
+            {
+                _hash.TransformFinalBlock(new byte[0], 0, 0);
+                _hash.Hash.CopyTo(output, offset);
+                Reset();
+                return _hash.HashSize / 8;
+            }
+
+            public void Reset()
+            {
+                _hash = HashAlgorithm.Create(_paddingHashAlgorithm);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeDataProtection.cs b/Axantum.AxCrypt.Core.Test/FakeDataProtection.cs
new file mode 100644
index 0000000..fc9dd91
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeDataProtection.cs
@@ -0,0 +1,52 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeDataProtection : IDataProtection
+    {
+        #region IDataProtection Members
+
+        public byte[] Protect(byte[] unprotectedData)
+        {
+            return (byte[])unprotectedData.Clone();
+        }
+
+        public byte[] Unprotect(byte[] protectedData)
+        {
+            return (byte[])protectedData.Clone();
+        }
+
+        #endregion IDataProtection Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeDelayTimer.cs b/Axantum.AxCrypt.Core.Test/FakeDelayTimer.cs
new file mode 100644
index 0000000..79002a6
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeDelayTimer.cs
@@ -0,0 +1,97 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeDelayTimer : IDelayTimer
+    {
+        private ISleep _sleep;
+
+        public FakeDelayTimer(ISleep sleep)
+        {
+            _sleep = sleep;
+            _sleep.Elapsed += Sleep_Elapsed;
+        }
+
+        private void Sleep_Elapsed(object sender, SleepEventArgs e)
+        {
+            if (_elapsed >= _interval)
+            {
+                return;
+            }
+            _elapsed += e.Time;
+            if (_elapsed >= _interval)
+            {
+                OnElapsed();
+            }
+        }
+
+        private bool disposed;
+
+        private TimeSpan _elapsed = TimeSpan.MinValue;
+
+        private TimeSpan _interval;
+
+        public void SetInterval(TimeSpan interval)
+        {
+            _interval = interval;
+        }
+
+        public event EventHandler<EventArgs> Elapsed;
+
+        public void Start()
+        {
+            if (disposed)
+            {
+                throw new ObjectDisposedException("this");
+            }
+            _elapsed = TimeSpan.Zero;
+        }
+
+        protected virtual void OnElapsed()
+        {
+            EventHandler<EventArgs> handler = Elapsed;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        public void Dispose()
+        {
+            if (!disposed)
+            {
+                disposed = true;
+                _sleep.Elapsed -= Sleep_Elapsed;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeFileWatcher.cs b/Axantum.AxCrypt.Core.Test/FakeFileWatcher.cs
new file mode 100644
index 0000000..689110f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeFileWatcher.cs
@@ -0,0 +1,112 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeFileWatcher : IFileWatcher
+    {
+        private bool disposed = false;
+
+        private static List<KeyValuePair<string, FakeFileWatcher>> _fileWatchers = new List<KeyValuePair<string, FakeFileWatcher>>();
+
+        internal string Path { get; set; }
+
+        public FakeFileWatcher(string path)
+        {
+            Path = path;
+            _fileWatchers.Add(new KeyValuePair<string, FakeFileWatcher>(path, this));
+        }
+
+        internal virtual void OnChanged(FileWatcherEventArgs eventArgs)
+        {
+            EventHandler<FileWatcherEventArgs> fileChanged = FileChanged;
+            if (fileChanged != null)
+            {
+                fileChanged(null, eventArgs);
+            }
+        }
+
+        #region IFileWatcher Members
+
+        public event EventHandler<FileWatcherEventArgs> FileChanged;
+
+        #endregion IFileWatcher Members
+
+        public static void HandleFileChanged(string path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException("path");
+            }
+            foreach (KeyValuePair<string, FakeFileWatcher> fileWatcher in _fileWatchers)
+            {
+                if (fileWatcher.Value.disposed)
+                {
+                    continue;
+                }
+                string key = fileWatcher.Key;
+                if (!key.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.Ordinal))
+                {
+                    key += System.IO.Path.DirectorySeparatorChar;
+                }
+                if (((path.Substring(0, path.Length - System.IO.Path.GetFileName(path).Length))).StartsWith(key, StringComparison.Ordinal))
+                {
+                    fileWatcher.Value.OnChanged(new FileWatcherEventArgs(path));
+                }
+            }
+        }
+
+        public bool IncludeSubdirectories
+        {
+            get;
+            set;
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+            }
+            disposed = true;
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeIterationCalculator.cs b/Axantum.AxCrypt.Core.Test/FakeIterationCalculator.cs
new file mode 100644
index 0000000..e8a0039
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeIterationCalculator.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using Axantum.AxCrypt.Core.Crypto;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    public class FakeIterationCalculator : IterationCalculator
+    {
+        public override long KeyWrapIterations(Guid cryptoId)
+        {
+            return 10;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeLauncher.cs b/Axantum.AxCrypt.Core.Test/FakeLauncher.cs
new file mode 100644
index 0000000..1b69b66
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeLauncher.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeLauncher : ILauncher
+    {
+        private string _path;
+
+        public FakeLauncher(string path)
+        {
+            _path = path;
+            HasExited = false;
+            WasStarted = true;
+        }
+
+        protected virtual void OnExited(EventArgs e)
+        {
+            EventHandler handler = Exited;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void RaiseExited()
+        {
+            OnExited(new EventArgs());
+        }
+
+        #region ILauncher Members
+
+        public event EventHandler Exited;
+
+        public bool HasExited { get; set; }
+
+        public bool WasStarted { get; set; }
+
+        public string Path
+        {
+            get { return _path; }
+        }
+
+        #endregion ILauncher Members
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeLogging.cs b/Axantum.AxCrypt.Core.Test/FakeLogging.cs
new file mode 100644
index 0000000..5f1e737
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeLogging.cs
@@ -0,0 +1,109 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeLogging : ILogging
+    {
+        #region ILogging Members
+
+        public event EventHandler<LoggingEventArgs> Logged;
+
+        protected virtual void OnLogged(string message)
+        {
+            EventHandler<LoggingEventArgs> handler = Logged;
+            if (handler != null)
+            {
+                handler(this, new LoggingEventArgs(message));
+            }
+        }
+
+        public void SetLevel(LogLevel level)
+        {
+        }
+
+        public bool IsFatalEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsErrorEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsWarningEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsInfoEnabled
+        {
+            get { return true; }
+        }
+
+        public bool IsDebugEnabled
+        {
+            get { return true; }
+        }
+
+        public void LogFatal(string message)
+        {
+            OnLogged(message);
+        }
+
+        public void LogError(string message)
+        {
+            OnLogged(message);
+        }
+
+        public void LogWarning(string message)
+        {
+            OnLogged(message);
+        }
+
+        public void LogInfo(string message)
+        {
+            OnLogged(message);
+        }
+
+        public void LogDebug(string message)
+        {
+            OnLogged(message);
+        }
+
+        #endregion ILogging Members
+
+        public void Dispose()
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeProgressBackground.cs b/Axantum.AxCrypt.Core.Test/FakeProgressBackground.cs
new file mode 100644
index 0000000..1222fb4
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeProgressBackground.cs
@@ -0,0 +1,75 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using Axantum.AxCrypt.Core.UI;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeProgressBackground : IProgressBackground
+    {
+        public void Work(Func<IProgressContext, FileOperationContext> work, Action<FileOperationContext> complete)
+        {
+            Busy = true;
+            OnWorkStatusChanged();
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            try
+            {
+                status = work(new ProgressContext());
+            }
+            catch (OperationCanceledException)
+            {
+                status = new FileOperationContext(String.Empty, FileOperationStatus.Canceled);
+            }
+            complete(status);
+            Busy = false;
+            OnWorkStatusChanged();
+        }
+
+        public void WaitForIdle()
+        {
+        }
+
+        public event EventHandler WorkStatusChanged;
+
+        protected virtual void OnWorkStatusChanged()
+        {
+            EventHandler handler = WorkStatusChanged;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        public bool Busy
+        {
+            get;
+            set;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakePseudoRandomGenerator.cs b/Axantum.AxCrypt.Core.Test/FakePseudoRandomGenerator.cs
new file mode 100644
index 0000000..ea4c30b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakePseudoRandomGenerator.cs
@@ -0,0 +1,48 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakePseudoRandomGenerator : IRandomGenerator
+    {
+        private Random _randomForTest = new Random(0);
+
+        public byte[] Generate(int count)
+        {
+            byte[] bytes = new byte[count];
+            _randomForTest.NextBytes(bytes);
+
+            return bytes;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeRandomGenerator.cs b/Axantum.AxCrypt.Core.Test/FakeRandomGenerator.cs
new file mode 100644
index 0000000..ecdcd07
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeRandomGenerator.cs
@@ -0,0 +1,48 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeRandomGenerator : IRandomGenerator
+    {
+        private byte _randomForTest = 0;
+
+        public byte[] Generate(int count)
+        {
+            byte[] bytes = new byte[count];
+            for (int i = 0; i < count; ++i)
+            {
+                bytes[i] = _randomForTest++;
+            }
+            return bytes;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeRequestClient.cs b/Axantum.AxCrypt.Core.Test/FakeRequestClient.cs
new file mode 100644
index 0000000..f65dcf8
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeRequestClient.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeRequestClient : IRequestClient
+    {
+        public CommandStatus Dispatch(CommandServiceEventArgs command)
+        {
+            return FakeDispatcher(command);
+        }
+
+        public Func<CommandServiceEventArgs, CommandStatus> FakeDispatcher { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeRequestServer.cs b/Axantum.AxCrypt.Core.Test/FakeRequestServer.cs
new file mode 100644
index 0000000..460da62
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeRequestServer.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeRequestServer : IRequestServer
+    {
+        public void Start()
+        {
+        }
+
+        public void Shutdown()
+        {
+        }
+
+        public void AcceptRequest(CommandServiceEventArgs command)
+        {
+            OnRequest(new RequestCommandEventArgs(command));
+        }
+
+        public event EventHandler<RequestCommandEventArgs> Request;
+
+        protected virtual void OnRequest(RequestCommandEventArgs e)
+        {
+            EventHandler<RequestCommandEventArgs> handler = Request;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeRuntimeEnvironment.cs b/Axantum.AxCrypt.Core.Test/FakeRuntimeEnvironment.cs
new file mode 100644
index 0000000..651053d
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeRuntimeEnvironment.cs
@@ -0,0 +1,184 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeRuntimeEnvironment : IRuntimeEnvironment, IDisposable
+    {
+        private bool _isLittleEndian = BitConverter.IsLittleEndian;
+
+        public Func<DateTime> TimeFunction { get; set; }
+
+        public FakeRuntimeEnvironment()
+        {
+            AxCryptExtension = ".axx";
+            TimeFunction = StandardTimeFunction;
+            Platform = Platform.WindowsDesktop;
+            CurrentTiming = new FakeTiming();
+            EnvironmentVariables = new Dictionary<string, string>();
+            MaxConcurrency = 2;
+            IsFirstInstance = true;
+            ExitCode = Int32.MinValue;
+        }
+
+        public FakeRuntimeEnvironment(Endian endianness)
+            : this()
+        {
+            _isLittleEndian = endianness == Endian.Reverse ? !_isLittleEndian : _isLittleEndian;
+        }
+
+        public static FakeRuntimeEnvironment Instance
+        {
+            get { return (FakeRuntimeEnvironment)Factory.Instance.Singleton<IRuntimeEnvironment>(); }
+        }
+
+        private static DateTime StandardTimeFunction()
+        {
+            return DateTime.UtcNow;
+        }
+
+        public bool IsLittleEndian
+        {
+            get { return _isLittleEndian; }
+        }
+
+        public string AxCryptExtension
+        {
+            get;
+            set;
+        }
+
+        public Platform Platform
+        {
+            get;
+            set;
+        }
+
+        public int StreamBufferSize
+        {
+            get { return 512; }
+        }
+
+        public DateTime UtcNow
+        {
+            get { return TimeFunction(); }
+        }
+
+        public Func<string, ILauncher> Launcher { get; set; }
+
+        public virtual ILauncher Launch(string path)
+        {
+            if (Launcher != null)
+            {
+                return Launcher(path);
+            }
+            return new FakeLauncher(path);
+        }
+
+        public ITiming StartTiming()
+        {
+            return CurrentTiming;
+        }
+
+        public FakeTiming CurrentTiming { get; set; }
+
+        public Func<IWebCaller> WebCallerCreator { get; set; }
+
+        public IWebCaller CreateWebCaller()
+        {
+            return WebCallerCreator();
+        }
+
+        public bool CanTrackProcess
+        {
+            get { return false; }
+        }
+
+        public void Dispose()
+        {
+        }
+
+        public IDictionary<string, string> EnvironmentVariables { get; private set; }
+
+        public string EnvironmentVariable(string name)
+        {
+            string variable;
+            if (!EnvironmentVariables.TryGetValue(name, out variable))
+            {
+                return String.Empty;
+            }
+            return variable;
+        }
+
+        public int MaxConcurrency { get; set; }
+
+        public bool IsFirstInstance { get; set; }
+
+        public bool IsFirstInstanceRunning { get; set; }
+
+        public bool FirstInstanceRunning(TimeSpan timeout)
+        {
+            return IsFirstInstanceRunning;
+        }
+
+        public int ExitCode { get; set; }
+
+        public void ExitApplication(int exitCode)
+        {
+            if (ExitCode == Int32.MinValue)
+            {
+                ExitCode = exitCode;
+            }
+        }
+
+        public bool IsDebugModeEnabled { get; private set; }
+
+        public void DebugMode(bool enable)
+        {
+            IsDebugModeEnabled = enable;
+        }
+
+        private class FakeSynchronizationContext : SynchronizationContext
+        {
+            public override void Post(SendOrPostCallback callback, object state)
+            {
+                callback(state);
+            }
+        }
+
+        public SynchronizationContext SynchronizationContext
+        {
+            get { return new FakeSynchronizationContext(); }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeRuntimeFileInfo.cs b/Axantum.AxCrypt.Core.Test/FakeRuntimeFileInfo.cs
new file mode 100644
index 0000000..ddb7ac4
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeRuntimeFileInfo.cs
@@ -0,0 +1,433 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeRuntimeFileInfo : IRuntimeFileInfo
+    {
+        private class FakeFileInfo
+        {
+            public bool IsFolder;
+            public string FullName;
+            public DateTime CreationTimeUtc;
+            public DateTime LastAccessTimeUtc;
+            public DateTime LastWriteTimeUtc;
+            public Stream Stream;
+        }
+
+        public static readonly DateTime TestDate1Utc = DateTime.Parse("2012-01-02 03:04:05", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+        public static readonly DateTime TestDate2Utc = DateTime.Parse("1950-12-24 15:16:17", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+        public static readonly DateTime TestDate3Utc = DateTime.Parse("2100-12-31 00:00:00", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+        public static readonly DateTime TestDate4Utc = DateTime.Parse("2008-09-10 11:12:13", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+        public static readonly DateTime TestDate5Utc = DateTime.Parse("2009-03-31 06:07:08", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+        public static readonly DateTime TestDate6Utc = DateTime.Parse("2012-02-29 12:00:00", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+
+        private static Dictionary<string, FakeFileInfo> _fakeFileSystem = new Dictionary<string, FakeFileInfo>(StringComparer.OrdinalIgnoreCase);
+
+        private FakeFileInfo _file;
+
+        public static event EventHandler Moving;
+
+        public static event EventHandler OpeningForRead;
+
+        public static event EventHandler OpeningForWrite;
+
+        public static event EventHandler Deleting;
+
+        public static event EventHandler ExceptionHook;
+
+        public string TestTag { get; private set; }
+
+        public static void AddFile(string path, bool isFolder, DateTime creationTimeUtc, DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc, Stream stream)
+        {
+            path = path.NormalizeFilePath();
+            FakeFileInfo fileInfo = new FakeFileInfo { FullName = path, CreationTimeUtc = creationTimeUtc, LastAccessTimeUtc = lastAccessTimeUtc, LastWriteTimeUtc = lastWriteTimeUtc, Stream = stream, IsFolder = isFolder, };
+            _fakeFileSystem.Add(path, fileInfo);
+            FakeFileWatcher.HandleFileChanged(path);
+        }
+
+        public static void AddFile(string path, DateTime creationTimeUtc, DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc, Stream stream)
+        {
+            AddFile(path, false, creationTimeUtc, lastAccessTimeUtc, lastWriteTimeUtc, stream);
+        }
+
+        public static void AddFile(string path, Stream stream)
+        {
+            AddFile(path, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, stream);
+        }
+
+        public static void AddFolder(string path)
+        {
+            AddFile(path.NormalizeFolderPath(), true, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, null);
+        }
+
+        public static void RemoveFileOrFolder(string path)
+        {
+            path = path.NormalizeFilePath();
+            _fakeFileSystem.Remove(path);
+            FakeFileWatcher.HandleFileChanged(path);
+        }
+
+        public static void ClearFiles()
+        {
+            _fakeFileSystem.Clear();
+        }
+
+        public FakeRuntimeFileInfo(string fullName)
+        {
+            fullName = fullName.NormalizeFilePath();
+            DateTime utcNow = OS.Current.UtcNow;
+            if (_fakeFileSystem.ContainsKey(fullName))
+            {
+                _file = _fakeFileSystem[fullName];
+                return;
+            }
+            _file = new FakeFileInfo { FullName = fullName, CreationTimeUtc = utcNow, LastAccessTimeUtc = utcNow, LastWriteTimeUtc = utcNow, Stream = Stream.Null };
+        }
+
+        protected virtual void OnOpeningForRead()
+        {
+            EventHandler handler = OpeningForRead;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        protected virtual void OnOpeningForWrite()
+        {
+            EventHandler handler = OpeningForWrite;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        protected virtual void OnDeleting()
+        {
+            EventHandler handler = Deleting;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        protected virtual void OnMoving()
+        {
+            EventHandler handler = Moving;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        protected virtual void OnExceptionHook(string testTag)
+        {
+            TestTag = testTag;
+            EventHandler handler = ExceptionHook;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+            TestTag = String.Empty;
+        }
+
+        private FakeFileInfo FindFileInfo()
+        {
+            FakeFileInfo fakeFileInfo;
+            if (!_fakeFileSystem.TryGetValue(_file.FullName, out fakeFileInfo))
+            {
+                return null;
+            }
+            return fakeFileInfo;
+        }
+
+        private static void EnsureDateTimes(FakeFileInfo fakeFileInfo)
+        {
+            DateTime utcNow = DateTime.UtcNow;
+            if (fakeFileInfo.CreationTimeUtc == DateTime.MinValue)
+            {
+                fakeFileInfo.CreationTimeUtc = utcNow;
+            }
+            if (fakeFileInfo.LastAccessTimeUtc == DateTime.MinValue)
+            {
+                fakeFileInfo.LastAccessTimeUtc = utcNow;
+            }
+            if (fakeFileInfo.LastWriteTimeUtc == DateTime.MinValue)
+            {
+                fakeFileInfo.LastWriteTimeUtc = utcNow;
+            }
+        }
+
+        public Stream OpenRead()
+        {
+            FakeFileInfo fakeFileInfo = FindFileInfo();
+            if (fakeFileInfo == null)
+            {
+                throw new FileNotFoundException("Can't find '{0}'.".InvariantFormat(_file.FullName));
+            }
+            OnOpeningForRead();
+            fakeFileInfo.Stream.Position = 0;
+            EnsureDateTimes(fakeFileInfo);
+            return new NonClosingStream(fakeFileInfo.Stream);
+        }
+
+        public Stream OpenWrite()
+        {
+            FakeFileInfo fakeFileInfo = FindFileInfo();
+            if (fakeFileInfo == null)
+            {
+                AddFile(_file.FullName, new MemoryStream());
+                _file = fakeFileInfo = FindFileInfo();
+            }
+            OnOpeningForWrite();
+            fakeFileInfo.Stream.Position = 0;
+            EnsureDateTimes(fakeFileInfo);
+            return new NonClosingStream(fakeFileInfo.Stream);
+        }
+
+        public bool IsLocked
+        {
+            get
+            {
+                return false;
+            }
+        }
+
+        public string Name
+        {
+            get
+            {
+                return Path.GetFileName(_file.FullName);
+            }
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                if (fakeFileInfo == null)
+                {
+                    return DateTime.MinValue;
+                }
+                return fakeFileInfo.CreationTimeUtc;
+            }
+            set
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                fakeFileInfo.CreationTimeUtc = value;
+            }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                if (fakeFileInfo == null)
+                {
+                    return DateTime.MinValue;
+                }
+                return fakeFileInfo.LastAccessTimeUtc;
+            }
+            set
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                fakeFileInfo.LastAccessTimeUtc = value;
+            }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                if (fakeFileInfo == null)
+                {
+                    return DateTime.MinValue;
+                }
+                return fakeFileInfo.LastWriteTimeUtc;
+            }
+            set
+            {
+                FakeFileInfo fakeFileInfo = FindFileInfo();
+                fakeFileInfo.LastWriteTimeUtc = value;
+            }
+        }
+
+        public void SetFileTimes(DateTime creationTimeUtc, DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc)
+        {
+            CreationTimeUtc = creationTimeUtc;
+            LastAccessTimeUtc = lastAccessTimeUtc;
+            LastWriteTimeUtc = lastWriteTimeUtc;
+        }
+
+        public string FullName
+        {
+            get { return _file.FullName; }
+        }
+
+        public bool IsExistingFile
+        {
+            get
+            {
+                FakeFileInfo fileInfo;
+                if (_fakeFileSystem.TryGetValue(_file.FullName, out fileInfo))
+                {
+                    return !fileInfo.IsFolder;
+                }
+                return false;
+            }
+        }
+
+        public void MoveTo(string destinationFileName)
+        {
+            destinationFileName = destinationFileName.NormalizeFilePath();
+            OnMoving();
+            FakeFileInfo source = _fakeFileSystem[_file.FullName];
+            _fakeFileSystem.Remove(_file.FullName);
+
+            _file = new FakeFileInfo { FullName = destinationFileName, CreationTimeUtc = source.CreationTimeUtc, LastAccessTimeUtc = source.LastAccessTimeUtc, LastWriteTimeUtc = source.LastWriteTimeUtc, Stream = source.Stream };
+            _fakeFileSystem.Remove(destinationFileName);
+            _fakeFileSystem.Add(destinationFileName, _file);
+
+            FakeFileWatcher.HandleFileChanged(destinationFileName);
+        }
+
+        public void Delete()
+        {
+            OnDeleting();
+            _fakeFileSystem.Remove(_file.FullName);
+            FakeFileWatcher.HandleFileChanged(_file.FullName);
+        }
+
+        public static MemoryStream ExpandableMemoryStream(byte[] buffer)
+        {
+            MemoryStream stream = new MemoryStream(buffer.Length);
+            stream.Write(buffer, 0, buffer.Length);
+            stream.Position = 0;
+
+            return stream;
+        }
+
+        public void CreateFolder()
+        {
+            string directory = Path.GetDirectoryName(_file.FullName);
+            DateTime utcNow = DateTime.UtcNow;
+
+            if (_fakeFileSystem.ContainsKey(directory))
+            {
+                return;
+            }
+            AddFile(directory, true, utcNow, utcNow, utcNow, Stream.Null);
+        }
+
+        public void CreateNewFile()
+        {
+            OnExceptionHook("CreateNewFile");
+
+            FakeFileInfo fileInfo = FindFileInfo();
+            if (fileInfo != null)
+            {
+                throw new InternalErrorException("File exists.", ErrorStatus.FileExists);
+            }
+            AddFile(FullName, new MemoryStream());
+        }
+
+        public bool IsExistingFolder
+        {
+            get
+            {
+                return _file.IsFolder;
+            }
+        }
+
+        public IEnumerable<IRuntimeFileInfo> Files
+        {
+            get
+            {
+                if (!IsExistingFolder)
+                {
+                    return new IRuntimeFileInfo[0];
+                }
+
+                List<FakeFileInfo> files = new List<FakeFileInfo>();
+                foreach (KeyValuePair<string, FakeFileInfo> kvp in _fakeFileSystem)
+                {
+                    if (kvp.Value.IsFolder)
+                    {
+                        continue;
+                    }
+                    if (!kvp.Value.FullName.StartsWith(FullName, StringComparison.OrdinalIgnoreCase))
+                    {
+                        continue;
+                    }
+                    files.Add(kvp.Value);
+                }
+                return files.Select((FakeFileInfo fileInfo) => { return Factory.New<IRuntimeFileInfo>(fileInfo.FullName); });
+            }
+        }
+
+        /// <summary>
+        /// Combine the path of this instance with another path, creating a new instance.
+        /// </summary>
+        /// <param name="path">The path to combine with.</param>
+        /// <returns>
+        /// A new instance representing the combined path.
+        /// </returns>
+        public IRuntimeFileInfo Combine(string path)
+        {
+            path = path.NormalizeFilePath();
+            return new FakeRuntimeFileInfo(Path.Combine(FullName, path));
+        }
+
+
+        /// <summary>
+        /// Removes a folder in the underlying file system with the path of this instance,
+        /// if the folder is empty. If it is not, nothing happens.
+        /// </summary>
+        /// <exception cref="System.NotImplementedException"></exception>
+        public void RemoveFolder()
+        {
+            if (!IsExistingFolder)
+            {
+                return;
+            }
+            RemoveFileOrFolder(FullName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeSleep.cs b/Axantum.AxCrypt.Core.Test/FakeSleep.cs
new file mode 100644
index 0000000..87b0b3b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeSleep.cs
@@ -0,0 +1,52 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeSleep : ISleep
+    {
+        public void Time(TimeSpan value)
+        {
+            OnElapsed(new SleepEventArgs(value));
+        }
+
+        public event EventHandler<SleepEventArgs> Elapsed;
+
+        protected virtual void OnElapsed(SleepEventArgs e)
+        {
+            EventHandler<SleepEventArgs> handler = Elapsed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeStatusChecker.cs b/Axantum.AxCrypt.Core.Test/FakeStatusChecker.cs
new file mode 100644
index 0000000..350c335
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeStatusChecker.cs
@@ -0,0 +1,51 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeStatusChecker : IStatusChecker
+    {
+        /// <summary>
+        /// Check if a status is deemed a success. If not, possibly display an interactive message
+        /// to a user, incorporating the displayContext-string in the message. This is typically
+        /// a file name or some other language independent context.
+        /// </summary>
+        /// <param name="status">The status to check.</param>
+        /// <param name="displayContext">A language independent context for the error, typically a file name.</param>
+        /// <returns>
+        /// True if the status indicated success, false otherwise.
+        /// </returns>
+        public bool CheckStatusAndShowMessage(FileOperationStatus status, string displayContext)
+        {
+            return status == FileOperationStatus.Success;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeStream.cs b/Axantum.AxCrypt.Core.Test/FakeStream.cs
new file mode 100644
index 0000000..546411b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeStream.cs
@@ -0,0 +1,147 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeStream : Stream
+    {
+        private Action<string> _visitorAction;
+        private Stream _stream;
+
+        public FakeStream(Stream stream, Action<string> visitorAction)
+        {
+            _stream = stream;
+            _visitorAction = visitorAction;
+        }
+
+        public override bool CanRead
+        {
+            get
+            {
+                _visitorAction("CanRead");
+                return _stream.CanRead;
+            }
+        }
+
+        public override bool CanSeek
+        {
+            get
+            {
+                _visitorAction("CanSeek");
+                return _stream.CanSeek;
+            }
+        }
+
+        public override bool CanWrite
+        {
+            get
+            {
+                _visitorAction("CanWrite");
+                return _stream.CanWrite;
+            }
+        }
+
+        public override void Flush()
+        {
+            _visitorAction("Flush");
+            _stream.Flush();
+        }
+
+        public override long Length
+        {
+            get
+            {
+                _visitorAction("Length");
+                return _stream.Length;
+            }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                _visitorAction("getPosition");
+                return _stream.Position;
+            }
+            set
+            {
+                _visitorAction("setPosition");
+                _stream.Position = value;
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            _visitorAction("Read");
+            return _stream.Read(buffer, offset, count);
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            _visitorAction("Seek");
+            return _stream.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            _visitorAction("SetLength");
+            _stream.SetLength(value);
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            _visitorAction("Write");
+            _stream.Write(buffer, offset, count);
+        }
+
+        private bool _disposed = false;
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_disposed)
+                {
+                    return;
+                }
+                if (_stream != null)
+                {
+                    _stream.Close();
+                    _stream = null;
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeTiming.cs b/Axantum.AxCrypt.Core.Test/FakeTiming.cs
new file mode 100644
index 0000000..5830c2d
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeTiming.cs
@@ -0,0 +1,49 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeTiming : ITiming
+    {
+        public TimeSpan CurrentTiming { get; set; }
+
+        #region ITiming Members
+
+        public TimeSpan Elapsed
+        {
+            get { return CurrentTiming; }
+        }
+
+        #endregion ITiming Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeUIThread.cs b/Axantum.AxCrypt.Core.Test/FakeUIThread.cs
new file mode 100644
index 0000000..798208e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeUIThread.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using Axantum.AxCrypt.Core.UI;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeUIThread : IUIThread
+    {
+        public FakeUIThread()
+        {
+            RunOnUIThreadAction = (action) => action();
+        }
+
+        public bool IsOnUIThread { get; set; }
+
+        public Action<Action> RunOnUIThreadAction { get; set; }
+
+        public void RunOnUIThread(Action action)
+        {
+            RunOnUIThreadAction(action);
+        }
+
+        public void PostOnUIThread(Action action)
+        {
+            RunOnUIThreadAction(action);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/FakeWebCaller.cs b/Axantum.AxCrypt.Core.Test/FakeWebCaller.cs
new file mode 100644
index 0000000..c819374
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/FakeWebCaller.cs
@@ -0,0 +1,66 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.IO;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class FakeWebCaller : IWebCaller
+    {
+        private string _result;
+
+        public event EventHandler<EventArgs> Calling;
+
+        public FakeWebCaller(string result)
+        {
+            _result = result;
+        }
+
+        #region IWebCaller Members
+
+        public string Go(Uri url)
+        {
+            OnCalling();
+            return _result;
+        }
+
+        #endregion IWebCaller Members
+
+        private void OnCalling()
+        {
+            EventHandler<EventArgs> handler = Calling;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/GlobalSuppressions.cs b/Axantum.AxCrypt.Core.Test/GlobalSuppressions.cs
new file mode 100644
index 0000000..03b1ac9
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/GlobalSuppressions.cs differ
diff --git a/Axantum.AxCrypt.Core.Test/MockAxCryptFile.cs b/Axantum.AxCrypt.Core.Test/MockAxCryptFile.cs
new file mode 100644
index 0000000..7e1118b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/MockAxCryptFile.cs
@@ -0,0 +1,77 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class MockAxCryptFile : AxCryptFile
+    {
+        public MockAxCryptFile()
+        {
+            EncryptMock = (sourceFile, destinationFile, passphrase, options, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            EncryptFilesUniqueWithBackupAndWipeMock = (fileInfo, encryptionKey, cryptoId, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            EncryptFileUniqueWithBackupAndWipeMock = (fileInfo, encryptionKey, cryptoId, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            DecryptFilesUniqueWithWipeOfOriginalMock = (fileInfo, decryptionKey, statusChecker, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+        }
+
+        public delegate void Action<T1, T2, T3, T4, T5>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5);
+
+        public Action<IRuntimeFileInfo, IRuntimeFileInfo, Passphrase, AxCryptOptions, IProgressContext> EncryptMock { get; set; }
+
+        public override void Encrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, Passphrase passphrase, AxCryptOptions options, IProgressContext progress)
+        {
+            EncryptMock(sourceFile, destinationFile, passphrase, options, progress);
+        }
+
+        public Action<IEnumerable<IRuntimeFileInfo>, Passphrase, Guid, IProgressContext> EncryptFilesUniqueWithBackupAndWipeMock { get; set; }
+
+        public override void EncryptFoldersUniqueWithBackupAndWipe(IEnumerable<IRuntimeFileInfo> folderInfos, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress)
+        {
+            EncryptFilesUniqueWithBackupAndWipeMock(folderInfos, encryptionKey, cryptoId, progress);
+        }
+
+        public Action<IRuntimeFileInfo, Passphrase, Guid, IProgressContext> EncryptFileUniqueWithBackupAndWipeMock { get; set; }
+
+        public override void EncryptFileUniqueWithBackupAndWipe(IRuntimeFileInfo fileInfo, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress)
+        {
+            EncryptFileUniqueWithBackupAndWipeMock(fileInfo, encryptionKey, cryptoId, progress);
+        }
+
+        public Action<IRuntimeFileInfo, Passphrase, IStatusChecker, IProgressContext> DecryptFilesUniqueWithWipeOfOriginalMock { get; set; }
+
+        public override void DecryptFilesInsideFolderUniqueWithWipeOfOriginal(IRuntimeFileInfo fileInfo, Passphrase decryptionKey, IStatusChecker statusChecker, IProgressContext progress)
+        {
+            DecryptFilesUniqueWithWipeOfOriginalMock(fileInfo, decryptionKey, statusChecker, progress);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/MockFileSystemStateActions.cs b/Axantum.AxCrypt.Core.Test/MockFileSystemStateActions.cs
new file mode 100644
index 0000000..0e0c044
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/MockFileSystemStateActions.cs
@@ -0,0 +1,85 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    internal class MockFileSystemStateActions : ActiveFileAction
+    {
+        public MockFileSystemStateActions()
+            : base()
+        {
+            CheckActiveFileMock = (activeFile, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            CheckActiveFilesMock = (mode, progress) => { };
+            PurgeActiveFilesMock = (progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            RemoveRecentFilesMock = (encryptedPaths, progress) => { throw new InvalidOperationException("Unexpected call to this method."); };
+            UpdateActiveFileWithKeyIfKeyMatchesThumbprintMock = (key) => { throw new InvalidOperationException("Unexpected call to this method."); };
+        }
+
+        public Func<ActiveFile, IProgressContext, ActiveFile> CheckActiveFileMock { get; set; }
+
+        public override ActiveFile CheckActiveFile(ActiveFile activeFile, IProgressContext progress)
+        {
+            return CheckActiveFileMock(activeFile, progress);
+        }
+
+        public Action<ChangedEventMode, IProgressContext> CheckActiveFilesMock { get; set; }
+
+        public override void CheckActiveFiles(ChangedEventMode mode, IProgressContext progress)
+        {
+            CheckActiveFilesMock(mode, progress);
+        }
+
+        public Action<IProgressContext> PurgeActiveFilesMock { get; set; }
+
+        public override void PurgeActiveFiles(IProgressContext progress)
+        {
+            PurgeActiveFilesMock(progress);
+        }
+
+        public Action<IEnumerable<IRuntimeFileInfo>, IProgressContext> RemoveRecentFilesMock { get; set; }
+
+        public override void RemoveRecentFiles(IEnumerable<IRuntimeFileInfo> encryptedPaths, IProgressContext progress)
+        {
+            RemoveRecentFilesMock(encryptedPaths, progress);
+        }
+
+        public Func<Passphrase, bool> UpdateActiveFileWithKeyIfKeyMatchesThumbprintMock { get; set; }
+
+        public override bool UpdateActiveFileWithKeyIfKeyMatchesThumbprint(Passphrase key)
+        {
+            return UpdateActiveFileWithKeyIfKeyMatchesThumbprintMock(key);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Core.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b279581
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,75 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[assembly: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Axantum.AxCrypt.Core.Test", Justification = "This will pass...")]
+[module: SuppressMessage("Microsoft.Naming", "CA1703:ResourceStringsShouldBeSpelledCorrectly", Scope = "resource", Target = "Axantum.AxCrypt.Core.Test.Properties.Resources.resources")]
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is only for unit tests and is never deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Axantum.AxCrypt.Core.Test")]
+[assembly: AssemblyDescription("NUnit tests for Axantum.AxCrypt.Core")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © 2014 Svante Seleborg")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("85dbaf9f-a7b5-47a9-8511-af62b28ee38b")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// used by Moq.
+[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/Properties/Resources.Designer.cs b/Axantum.AxCrypt.Core.Test/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..667e73b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Properties/Resources.Designer.cs
@@ -0,0 +1,130 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Axantum.AxCrypt.Core.Test.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Axantum.AxCrypt.Core.Test.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The Project Gutenberg EBook of David Copperfield, by Charles Dickens
+        ///
+        ///This eBook is for the use of anyone anywhere at no cost and with
+        ///almost no restrictions whatsoever.  You may copy it, give it away or
+        ///re-use it under the terms of the Project Gutenberg License included
+        ///with this eBook or online at www.gutenberg.org
+        ///
+        ///
+        ///Title: David Copperfield
+        ///
+        ///Author: Charles Dickens
+        ///
+        ///Release Date: December, 1996  [Etext #766]
+        ///Posting Date: November 24, 2009
+        ///
+        ///Language: English
+        ///
+        ///
+        ///*** START OF THIS PROJECT G [rest of string was truncated]";.
+        /// </summary>
+        internal static string david_copperfield {
+            get {
+                return ResourceManager.GetString("david_copperfield", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] david_copperfield_key__aa_ae_oe__ulu_txt {
+            get {
+                object obj = ResourceManager.GetObject("david_copperfield_key__aa_ae_oe__ulu_txt", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] helloworld_key_a_txt {
+            get {
+                object obj = ResourceManager.GetObject("helloworld_key_a_txt", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] tst_0_0b6_key__aaaeoe__medium_html {
+            get {
+                object obj = ResourceManager.GetObject("tst_0_0b6_key__aaaeoe__medium_html", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Byte[].
+        /// </summary>
+        internal static byte[] uncompressable_zip {
+            get {
+                object obj = ResourceManager.GetObject("uncompressable_zip", resourceCulture);
+                return ((byte[])(obj));
+            }
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Core.Test/Properties/Resources.resx b/Axantum.AxCrypt.Core.Test/Properties/Resources.resx
new file mode 100644
index 0000000..382c1b2
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/Properties/Resources.resx
@@ -0,0 +1,136 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="david_copperfield" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\david-copperfield.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
+  </data>
+  <data name="david_copperfield_key__aa_ae_oe__ulu_txt" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\david copperfield-key-'aa ae oe'-ulu-txt.axx;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="helloworld_key_a_txt" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\helloworld-key-a-txt.axx;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="tst_0_0b6_key__aaaeoe__medium_html" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\tst-0.0b6-key-'aaaeoe'-medium-html.axx;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="uncompressable_zip" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\uncompressable-zip.axx;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/SetupAssembly.cs b/Axantum.AxCrypt.Core.Test/SetupAssembly.cs
new file mode 100644
index 0000000..08ef5ce
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/SetupAssembly.cs
@@ -0,0 +1,111 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+using System.IO;
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Mono.Portable;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    /// <summary>
+    /// Not using SetUpFixtureAttribute etc because MonoDevelop does not always honor.
+    /// </summary>
+    [SuppressMessage("Microsoft.Design", "CA1053:StaticHolderTypesShouldNotHaveConstructors", Justification = "NUnit requires there to be a parameterless constructor.")]
+    internal static class SetupAssembly
+    {
+        public static void AssemblySetup()
+        {
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<WorkFolder>(() => new WorkFolder(Path.GetPathRoot(Environment.CurrentDirectory) + @"WorkFolder\"));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<ILogging>(() => new FakeLogging());
+            Factory.Instance.Singleton<IUserSettings>(() => new UserSettings(Instance.WorkFolder.FileInfo.Combine("UserSettings.txt"), Factory.New<IterationCalculator>()));
+            Factory.Instance.Singleton<KnownKeys>(() => new KnownKeys(Instance.FileSystemState, Instance.SessionNotify));
+            Factory.Instance.Singleton<ProcessState>(() => new ProcessState());
+            Factory.Instance.Singleton<IUIThread>(() => new FakeUIThread());
+            Factory.Instance.Singleton<IProgressBackground>(() => new FakeProgressBackground());
+            Factory.Instance.Singleton<SessionNotify>(() => new SessionNotify());
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("FileSystemState.xml")));
+            Factory.Instance.Singleton<IStatusChecker>(() => new FakeStatusChecker());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<CryptoFactory>(() => CreateCryptoFactory());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+            Factory.Instance.Singleton<ActiveFileWatcher>(() => new ActiveFileWatcher());
+            Factory.Instance.Singleton<UserAsymmetricKeysStore>(() => new UserAsymmetricKeysStore(Instance.WorkFolder.FileInfo, Instance.KnownKeys));
+
+            Factory.Instance.Register<AxCryptFactory>(() => new AxCryptFactory());
+            Factory.Instance.Register<AxCryptFile>(() => new AxCryptFile());
+            Factory.Instance.Register<ActiveFileAction>(() => new ActiveFileAction());
+            Factory.Instance.Register<FileOperation>(() => new FileOperation(Instance.FileSystemState, Instance.SessionNotify));
+            Factory.Instance.Register<IdentityViewModel>(() => new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings));
+            Factory.Instance.Register<FileOperationViewModel>(() => new FileOperationViewModel(Instance.FileSystemState, Instance.SessionNotify, Instance.KnownKeys, Instance.ParallelFileOperation, Factory.Instance.Singleton<IStatusChecker>(), Factory.New<IdentityViewModel>()));
+            Factory.Instance.Register<MainViewModel>(() => new MainViewModel(Instance.FileSystemState));
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new FakeRuntimeFileInfo(path));
+            Factory.Instance.Register<string, IFileWatcher>((path) => new FakeFileWatcher(path));
+            Factory.Instance.Register<IterationCalculator>(() => new FakeIterationCalculator());
+            Factory.Instance.Register<IDataProtection>(() => new FakeDataProtection());
+
+            Instance.UserSettings.SetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId, 1234);
+            Instance.UserSettings.ThumbprintSalt = Salt.Zero;
+            Instance.Log.SetLevel(LogLevel.Debug);
+        }
+
+        public static CryptoFactory CreateCryptoFactory()
+        {
+            CryptoFactory factory = new CryptoFactory();
+            factory.Add(() => new V2Aes256CryptoFactory());
+            factory.Add(() => new V2Aes128CryptoFactory());
+            factory.Add(() => new V1Aes128CryptoFactory());
+
+            return factory;
+        }
+
+        public static void AssemblyTeardown()
+        {
+            FakeRuntimeFileInfo.ClearFiles();
+            Factory.Instance.Clear();
+        }
+
+        internal static FakeRuntimeEnvironment FakeRuntimeEnvironment
+        {
+            get
+            {
+                return (FakeRuntimeEnvironment)OS.Current;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestActiveFile.cs b/Axantum.AxCrypt.Core.Test/TestActiveFile.cs
new file mode 100644
index 0000000..fe0d2bb
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestActiveFile.cs
@@ -0,0 +1,212 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestActiveFile
+    {
+        private static string _rootPath;
+        private static string _testTextPath;
+        private static string _davidCopperfieldTxtPath;
+        private static string _uncompressedAxxPath;
+        private static string _helloWorldAxxPath;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+            _testTextPath = _rootPath.PathCombine("test.txt");
+            _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+            _uncompressedAxxPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).PathCombine("Uncompressed.axx");
+            _helloWorldAxxPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments).PathCombine("HelloWorld.axx");
+
+            FakeRuntimeFileInfo.AddFile(_testTextPath, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            IRuntimeFileInfo nullFileInfo = null;
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Passphrase key = new Passphrase("key");
+            Passphrase nullKey = null;
+            ActiveFile nullActiveFile = null;
+
+            ActiveFile originalActiveFile = new ActiveFile(decryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, key) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(originalActiveFile, nullKey) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, ActiveFileStatus.None) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullActiveFile, DateTime.MinValue, ActiveFileStatus.None) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(nullFileInfo, decryptedFileInfo, new Passphrase("a"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(encryptedFileInfo, nullFileInfo, new Passphrase("b"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new ActiveFile(encryptedFileInfo, decryptedFileInfo, nullKey, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id) == null) { } });
+        }
+
+        [Test]
+        public static void TestConstructor()
+        {
+            Passphrase key = new Passphrase("key");
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            decryptedFileInfo = activeFile.DecryptedFileInfo;
+            Assert.That(decryptedFileInfo.IsExistingFile, Is.True, "The file should exist in the fake file system.");
+            Assert.That(decryptedFileInfo.FullName, Is.EqualTo(_testTextPath), "The file should be named as it was in the constructor");
+            Assert.That(decryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(decryptedFileInfo.LastWriteTimeUtc), "When a LastWriteTime is not specified, the decrypted file should be used to determine the value.");
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return DateTime.UtcNow.AddMinutes(1); });
+
+            ActiveFile otherFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);
+            Assert.That(otherFile.Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted), "The status should be as given in the constructor.");
+            Assert.That(otherFile.DecryptedFileInfo.FullName, Is.EqualTo(activeFile.DecryptedFileInfo.FullName), "This should be copied from the original instance.");
+            Assert.That(otherFile.EncryptedFileInfo.FullName, Is.EqualTo(activeFile.EncryptedFileInfo.FullName), "This should be copied from the original instance.");
+            Assert.That(otherFile.Key, Is.EqualTo(activeFile.Key), "This should be copied from the original instance.");
+            Assert.That(otherFile.Properties.LastActivityTimeUtc, Is.GreaterThan(activeFile.Properties.LastActivityTimeUtc), "This should not be copied from the original instance, but should be a later time.");
+            Assert.That(otherFile.ThumbprintMatch(activeFile.Key), Is.True, "The thumbprints should match.");
+
+            activeFile.DecryptedFileInfo.LastWriteTimeUtc = activeFile.DecryptedFileInfo.LastWriteTimeUtc.AddDays(1);
+            otherFile = new ActiveFile(activeFile, OS.Current.UtcNow, ActiveFileStatus.AssumedOpenAndDecrypted);
+            Assert.That(activeFile.IsModified, Is.True, "The original instance has not been encrypted since the last change.");
+            Assert.That(otherFile.IsModified, Is.False, "The copy indicates that it has been encrypted and thus is not modified.");
+        }
+
+        [Test]
+        public static void TestCopyConstructorWithKey()
+        {
+            Passphrase key = new Passphrase("key");
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            Passphrase newKey = new Passphrase("newKey");
+
+            ActiveFile newActiveFile = new ActiveFile(activeFile, newKey);
+            Assert.That(activeFile.Key, Is.Not.EqualTo(newKey), "Ensure that it's really a different key.");
+            Assert.That(newActiveFile.Key, Is.EqualTo(newKey), "The constructor should assign the new key to the new ActiveFile instance.");
+        }
+
+        [Test]
+        public static void TestThumbprint()
+        {
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+
+            Passphrase key = new Passphrase("key");
+
+            using (MemoryStream stream = new MemoryStream())
+            {
+                DataContractSerializer serializer = new DataContractSerializer(typeof(ActiveFile));
+                ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+                serializer.WriteObject(stream, activeFile);
+                stream.Position = 0;
+                ActiveFile deserializedActiveFile = (ActiveFile)serializer.ReadObject(stream);
+
+                Assert.That(deserializedActiveFile.ThumbprintMatch(key), Is.True, "The deserialized object should match the thumbprint with the key.");
+            }
+        }
+
+        [Test]
+        public static void TestThumbprintNullKey()
+        {
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+
+            Passphrase key = new Passphrase("key");
+            using (MemoryStream stream = new MemoryStream())
+            {
+                ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+                Assert.Throws<ArgumentNullException>(() =>
+                {
+                    Passphrase nullKey = null;
+                    activeFile.ThumbprintMatch(nullKey);
+                });
+            }
+        }
+
+        [Test]
+        public static void TestMethodIsModified()
+        {
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "doesnotexist.txt"));
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new Passphrase("new"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            Assert.That(activeFile.IsModified, Is.False, "A non-existing decrypted file should not be treated as modified.");
+        }
+
+        [Test]
+        public static void TestVisualState()
+        {
+            ActiveFile activeFile;
+            Passphrase key = new Passphrase("key");
+
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(@"C:\encrypted.axx"), Factory.New<IRuntimeFileInfo>(@"C:\decrypted.txt"), key, ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.EncryptedWithKnownKey));
+
+            activeFile = new ActiveFile(activeFile);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.EncryptedWithoutKnownKey));
+
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.DecryptedIsPendingDelete);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.DecryptedWithoutKnownKey));
+
+            activeFile = new ActiveFile(activeFile, key);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.DecryptedWithKnownKey));
+
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.DecryptedWithKnownKey));
+
+            activeFile = new ActiveFile(activeFile);
+            Assert.That(activeFile.VisualState, Is.EqualTo(ActiveFileVisualState.DecryptedWithoutKnownKey));
+
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.Error);
+            Assert.Throws<InvalidOperationException>(() => { if (activeFile.VisualState == ActiveFileVisualState.None) { } });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestActiveFileCollectionTests.cs b/Axantum.AxCrypt.Core.Test/TestActiveFileCollectionTests.cs
new file mode 100644
index 0000000..df2f600
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestActiveFileCollectionTests.cs
@@ -0,0 +1,104 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestActiveFileCollectionTests
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _testTextPath = Path.Combine(_rootPath, "test.txt");
+        private static readonly string _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+        private static readonly string _uncompressedAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Uncompressed.axx");
+        private static readonly string _helloWorldAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HelloWorld.axx");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            FakeRuntimeFileInfo.AddFile(_testTextPath, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestActiveFileCollectionSimpleConstructor()
+        {
+            ActiveFileCollection collection = new ActiveFileCollection();
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new Passphrase("new"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+
+            collection.Add(activeFile);
+
+            Assert.That(collection.Count, Is.EqualTo(1), "There should be one entry in the collection.");
+
+            foreach (ActiveFile member in collection)
+            {
+                Assert.That(member, Is.EqualTo(activeFile), "The one we added should now be in the collection.");
+            }
+        }
+
+        [Test]
+        public static void TestActiveFileCollectionEnumerationConstructor()
+        {
+            IRuntimeFileInfo decryptedFileInfo1 = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "test1.txt"));
+            IRuntimeFileInfo encryptedFileInfo1 = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "test1-txt.axx"));
+            IRuntimeFileInfo decryptedFileInfo2 = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "test2.txt"));
+            IRuntimeFileInfo encryptedFileInfo2 = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "test2-text.axx"));
+            ActiveFile activeFile1 = new ActiveFile(encryptedFileInfo1, decryptedFileInfo1, new Passphrase("newA"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            ActiveFile activeFile2 = new ActiveFile(encryptedFileInfo2, decryptedFileInfo2, new Passphrase("newB"), ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+
+            ActiveFileCollection collection = new ActiveFileCollection(new ActiveFile[] { activeFile1, activeFile2 });
+
+            Assert.That(collection.Count, Is.EqualTo(2), "There should be two entries in the collection.");
+
+            Assert.That(collection.First(), Is.EqualTo(activeFile1), "This should be the first in the collection.");
+            Assert.That(collection.Last(), Is.EqualTo(activeFile2), "This should be the last in the collection.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestActiveFileComparer.cs b/Axantum.AxCrypt.Core.Test/TestActiveFileComparer.cs
new file mode 100644
index 0000000..5b1f684
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestActiveFileComparer.cs
@@ -0,0 +1,134 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestActiveFileComparer
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestDateComparer()
+        {
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2013, 01, 01);
+            ActiveFile activeFile1a = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1.txt"), new Passphrase("activeFile1a"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().Id);
+
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2013, 01, 01);
+            ActiveFile activeFile1b = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted2.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted2.txt"), new Passphrase("activeFile1b"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+
+            ActiveFileComparer comparer = ActiveFileComparer.DateComparer;
+            Assert.That(comparer.ReverseSort, Is.False);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = false;
+
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2013, 01, 02);
+            ActiveFile activeFile2 = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted3.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted3.txt"), new Passphrase("activeFile2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.LessThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.GreaterThan(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.GreaterThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.LessThan(0));
+            comparer.ReverseSort = false;
+        }
+
+        [Test]
+        public static void TestEncryptedNameComparer()
+        {
+            ActiveFile activeFile1a = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1a.txt"), new Passphrase("activeFile1a"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().Id);
+            ActiveFile activeFile1b = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1b.txt"), new Passphrase("activeFile1b"), ActiveFileStatus.NotDecrypted, new V2Aes256CryptoFactory().Id);
+
+            ActiveFileComparer comparer = ActiveFileComparer.EncryptedNameComparer;
+            Assert.That(comparer.ReverseSort, Is.False);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = false;
+
+            ActiveFile activeFile2 = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted2.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1a.txt"), new Passphrase("activeFile2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.LessThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.GreaterThan(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.GreaterThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.LessThan(0));
+            comparer.ReverseSort = false;
+        }
+
+        [Test]
+        public static void TestDecryptedNameComparer()
+        {
+            ActiveFile activeFile1a = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1a.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1.txt"), new Passphrase("activeFile1a"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            ActiveFile activeFile1b = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1b.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted1.txt"), new Passphrase("activeFile1b"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+
+            ActiveFileComparer comparer = ActiveFileComparer.DecryptedNameComparer;
+            Assert.That(comparer.ReverseSort, Is.False);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile1b), Is.EqualTo(0));
+            Assert.That(comparer.Compare(activeFile1b, activeFile1a), Is.EqualTo(0));
+            comparer.ReverseSort = false;
+
+            ActiveFile activeFile2 = new ActiveFile(Factory.New<IRuntimeFileInfo>((@"C:\encrypted1a.axx")), Factory.New<IRuntimeFileInfo>(@"C:\decrypted2.txt"), new Passphrase("activeFile2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.LessThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.GreaterThan(0));
+            comparer.ReverseSort = true;
+            Assert.That(comparer.Compare(activeFile1a, activeFile2), Is.GreaterThan(0));
+            Assert.That(comparer.Compare(activeFile2, activeFile1a), Is.LessThan(0));
+            comparer.ReverseSort = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAsymmetricCrypto.cs b/Axantum.AxCrypt.Core.Test/TestAsymmetricCrypto.cs
new file mode 100644
index 0000000..62293e9
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAsymmetricCrypto.cs
@@ -0,0 +1,265 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAsymmetricCrypto
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakePseudoRandomGenerator());
+            Factory.Instance.Singleton<IAsymmetricFactory>(() => new FakeAsymmetricFactory("MD5"));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestKeyPairPem()
+        {
+            IAsymmetricKeyPair keyPair = Factory.Instance.Singleton<IAsymmetricFactory>().CreateKeyPair(512);
+
+            string privatePem = keyPair.PrivateKey.ToString();
+
+            Assert.That(privatePem.StartsWith("-----BEGIN RSA PRIVATE KEY-----", StringComparison.OrdinalIgnoreCase));
+            Assert.That(privatePem.EndsWith("-----END RSA PRIVATE KEY-----" + Environment.NewLine, StringComparison.OrdinalIgnoreCase));
+            Assert.That(privatePem.Length, Is.GreaterThan(490));
+            Assert.That(privatePem.Length, Is.LessThan(600));
+
+            string publicPem = keyPair.PublicKey.ToString();
+
+            Assert.That(publicPem.StartsWith("-----BEGIN PUBLIC KEY-----", StringComparison.OrdinalIgnoreCase));
+            Assert.That(publicPem.EndsWith("-----END PUBLIC KEY-----" + Environment.NewLine, StringComparison.OrdinalIgnoreCase));
+        }
+
+        [Test]
+        public static void TestAsymmetricEncryption()
+        {
+            IAsymmetricPublicKey key = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePublicKey(_publicKey1);
+
+            string text = "AxCrypt is Great!";
+            byte[] encryptedBytes = key.Transform(Encoding.UTF8.GetBytes(text));
+
+            Assert.That(encryptedBytes.Length, Is.EqualTo(512));
+        }
+
+        [Test]
+        public static void TestAsymmetricEncryptionDecryption()
+        {
+            IAsymmetricPublicKey publicKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePublicKey(_publicKey1);
+
+            string text = "AxCrypt is really very great!";
+            byte[] encryptedBytes = publicKey.Transform(Encoding.UTF8.GetBytes(text));
+            Assert.That(encryptedBytes.Length, Is.EqualTo(512));
+
+            IAsymmetricPrivateKey privateKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePrivateKey(_privateKey1);
+            byte[] decryptedBytes = privateKey.Transform(encryptedBytes);
+            string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
+
+            Assert.That(decryptedText, Is.EqualTo("AxCrypt is really very great!"));
+        }
+
+        [Test]
+        public static void TestAsymmetricEncryptionFailedDecryptionWrongKey1()
+        {
+            IAsymmetricPublicKey publicKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePublicKey(_publicKey1);
+
+            string text = "AxCrypt is really very great!";
+            byte[] encryptedBytes = publicKey.Transform(Encoding.UTF8.GetBytes(text));
+            Assert.That(encryptedBytes.Length, Is.EqualTo(512));
+
+            IAsymmetricPrivateKey privateKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePrivateKey(_privateKey2);
+            byte[] decryptedBytes = privateKey.Transform(encryptedBytes);
+            Assert.That(decryptedBytes, Is.Null);
+        }
+
+        [Test]
+        public static void TestAsymmetricEncryptionFailedDecryptionWrongKey2()
+        {
+            IAsymmetricPublicKey publicKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePublicKey(_publicKey2);
+
+            string text = "AxCrypt is really very great!";
+            byte[] encryptedBytes = publicKey.Transform(Encoding.UTF8.GetBytes(text));
+            Assert.That(encryptedBytes.Length, Is.EqualTo(512));
+
+            IAsymmetricPrivateKey privateKey = Factory.Instance.Singleton<IAsymmetricFactory>().CreatePrivateKey(_privateKey1);
+            byte[] decryptedBytes = privateKey.Transform(encryptedBytes);
+            Assert.That(decryptedBytes, Is.Null);
+        }
+
+        private const string _privateKey1 = @"-----BEGIN RSA PRIVATE KEY-----
+MIIJKAIBAAKCAgEAnJ8Tk4OBEL61g5iicA2F4eEQM2qG+Qoo8BwAVYs8kl6lBNoK
+GcbyUNcSUw78h05u9OYgMgluFrnbElNxDWa8K9XcG3mP60baMEnYrCwvpUK7jw2F
+aMjvfTipEKuB7vUGzRfvR726/qqoBNKYqGe5INYFUL/JyPCuEdKkmzPCvkREgsEI
+6wsnfJEdqteQYx5hwqXkm01A1Ov2fRISwaO2KEZp3mEfZygIaTscpBZyhu/LfsKK
+vaTe03EgLKciL/oKuHnam4i4NWDOgxvYHdhSGhOmDyu4DMc1HmtHTWjI53kVKLvq
+O3Z5oTe8LmAI8I5uzzzI6jhcOD4BdvblgU87AhFQ4jZTlCUsQ0i3wI4J1iNnEkB4
++3g5VEypoPOee7zCeMrZyznMnfsIR49vS+Imr/A6UhGsAUhQJseZXKkwfTib7xgs
+t+Mz0q0hUw+6z1WRrbMrl6WaDKuk5Q3HDDqNxq6pI+MEEDNC6OAh6GA+4+4Fu3N4
+mqwmhNICjDuaMwPco1JUxhhL1G7Xo9q41yKANkXVQwlbcX385q9ntUSwDKaPF5kz
+dSRJIRlfLC5ysS4plKRqXBVO4Frv3ejcQFXN5x1VQTJJzGHJhsNQ0lVL3MjyFAfi
+IivJORTk2jNAPkaOl9ei9IS6H7jAQcqrERXIvEASZTyAeQlcXprhbyZ2nf0CAwEA
+AQKCAgAbk3qr52SLITjuYaqAFjFzcuAaXXBEWwCYPiXk6e4RS268qvNKVJgHmcaV
+LzdRT4MDxZz3kmd6wuCKmnx2QpdxFGd7wuyPHVt/UxE+R01gSJ6jclsB9xcLsjU6
+RShMfYHkDInJ1OMewcdxie7s/849tNEcxZfutEnBw5fN59ArFfQGHZzHXaBnM1nI
+4cl/WjMWRYU5vuFiW+V7YfpBc+S3tKYhTHJuBENu28SQM4+YqJHo0LIC8At3qRxk
+IE1JqznF/1Z5OhpM862IshdcMeFKzBjZ5PWz8kMtBvB39bIh51TNZkC4lYSW2Sxd
+8fTA/iMOhAJQEvpRwMEbRB9mpB+cWAYWeMim+mMKBeFYeP5FkGNqdvCV7+Yu5OrU
+tczAgvAIIFcvieyR7k6r0mhKVb/Rrid3pl1rBuK+Emiz/xhEVJciuw5vF5IxMPS1
+kOgOQFDNNa8zHW+FZaFsnnWcWGAgIBbwFF2LZcNXRJCSGGoPgYWJK9Zea4kLntFr
+eQFvSOX1QM7TWC30+/PVY71SEOW8VuKG7x4HtyK0+zHgLBIFY7A7xJoM8eqvg7R8
+lg42okKc4SPru+eyuTXVVj3OqG+rZ0zqVvGLMNbsxvqW5oUpRrBAVmwNMoWzQ+Ed
+JCstWSw1fEeTCgUM66NVWSF8pr7VCdeZCfi5fAwxkOw9QgRAtQKCAQEAz/kg8Ihk
+6hasWZ5cRKT9FpZB0y879xtCaJeEE2TE9ERQCBY7Q8hGuU5fGrVbRC3AOnGJLyT0
+ghk6bszrZDxAVvXI8XPPFB0ihFvgkBI2cFLvjvtU0UptqZWaFLdITpbuUafOMm8A
+pezkNHmHXBqe7nurLvotIy2DFq+EMeGZEpz3txa7sqxFushbyLYHpgPj8kz6zx4y
+jr8SM/oMCRT09neIk8YPXDt2AbfwpV/XYrKDNgH76Sp85fLN1Xyaz6l1vggRsUKT
+9LzoCLV9zfmtCf5JlAb/bDJoS/Bb/E944XUebkrUgeqZW8Hn3fDVHphk4ClkY+EM
+9eNBD5UXnGKNPwKCAQEAwMonwDvCedjbwW7XzL0RV7FQV2PGSEwhwFuk7SZAEyKq
+DObAXhwJzzZ6PGqtJlJmx+3LcKAAAsOlyw9Br4cp8CXosVtOEGWV42B4CArD4gyX
+cFe71n5H/h1aX09gOEW55czoBPwYmNV/BsFpcnH3IsqWD5Gzk8RKTdCvMoAWjTsC
+C/zsIroWez8P0Ss2/+VBHmDoGuRJAM2czGMMVlXRnCIhj5p9JMZ8vOn7j+72F9hC
+n08s8x2QRiRuHnDow2O99S4476BMXMMxsE3zCuFmNwgLtS8d5jHDxXan2cxUrySN
+by1/1vhH+/KukyVDNxKeCwk4L8ubF6xfbtDxA445wwKCAQBoVLU2lWXynQ83Ih9t
+fEtOwnAhLmfpre4hpCjoxbucQozXkbeHaHg6S9uf/WzchgsSBpToZqSWg2tx3DEW
+JresKD73Cb7Pe1IujhzYiZpvvNtaojDJkYnz8g3K6KtIaaUCp6jkWhU8J9vPi0vh
+Y6VpQ/b7aRutsw45GjG6CE+PK9mFKs1cc9nDOvH4fYDWwsreacnEj4STYb0TABR7
+ldzRq+ODJm/cOCQZ9pmtjKfzZlQ2isZCEUN449Zoi8rp9DwR6eBeSWUJ+J56h/ml
+k+Q/yCZHMT9/msYBmoG60G92wxdSAw4aYoMuqdbU2xU+9PpeDcXD6UlkLO4dkBC5
+LiNnAoIBAQCWuHTDUPUFlYiYfTOxGM8KI9GPwK0vsHVikUMrNBA75YnUdEJIUNtK
+aGi/+xZLM3ivLTUzY6Mehh6D1fWgaKdc3AZDQgKRxxmbnbu5bdEeVIHAjpaHZkqa
+XBBfGws6cyiWg8+QthX0xlR8z5DErFxtkrwmh95A0+DTXSba8FCxMUS0YpOpwpn4
+2KBhAswI2w5B1bkf7QE144mGMJlglc89pWFfh4P20EaM2tCVAlja43OSYK/fkWlN
+rQV6PwN6XewQVoaksEmC7AdYslgkVXs34s5kY+WYJafMJKutFpXOJ2F7XbLoOUrt
+qhjZaPRXhfKQ5jBLDX6+zz/8vtTt1q9JAoIBACiYVz4zBRaAHHZjrnaUZKr63JkE
+TMICyPUfHBmcxzS4BXp4jHq889ZRZYQbTtCXXce2TeDLA1nA4hoi/PZTjcdmMnJ4
+PLzUMIFepR+F8131HMrd3HIsfarz3gaee4zEjJRSUJU9ZqLBbK2kmcycnWjpF4yo
+QdErVWoC8gkvkyA+iSzjrUvZsBTX2Qq4zGPI3KiniJWKDCQmdSTRM2uTIZbTOqbK
+yQE2SNeRAJcSl9xZRznI2qzFmbohKakuShofqAX+H8++DXXI0HaQio2lNAoho2uh
+XIlmrhV+Twqe6D0nFCpQe1FOBCxDnFKZxI1J/JxhtVD9UwkidCdgC2ENqWE=
+-----END RSA PRIVATE KEY-----
+";
+
+        private const string _publicKey1 = @"-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnJ8Tk4OBEL61g5iicA2F
+4eEQM2qG+Qoo8BwAVYs8kl6lBNoKGcbyUNcSUw78h05u9OYgMgluFrnbElNxDWa8
+K9XcG3mP60baMEnYrCwvpUK7jw2FaMjvfTipEKuB7vUGzRfvR726/qqoBNKYqGe5
+INYFUL/JyPCuEdKkmzPCvkREgsEI6wsnfJEdqteQYx5hwqXkm01A1Ov2fRISwaO2
+KEZp3mEfZygIaTscpBZyhu/LfsKKvaTe03EgLKciL/oKuHnam4i4NWDOgxvYHdhS
+GhOmDyu4DMc1HmtHTWjI53kVKLvqO3Z5oTe8LmAI8I5uzzzI6jhcOD4BdvblgU87
+AhFQ4jZTlCUsQ0i3wI4J1iNnEkB4+3g5VEypoPOee7zCeMrZyznMnfsIR49vS+Im
+r/A6UhGsAUhQJseZXKkwfTib7xgst+Mz0q0hUw+6z1WRrbMrl6WaDKuk5Q3HDDqN
+xq6pI+MEEDNC6OAh6GA+4+4Fu3N4mqwmhNICjDuaMwPco1JUxhhL1G7Xo9q41yKA
+NkXVQwlbcX385q9ntUSwDKaPF5kzdSRJIRlfLC5ysS4plKRqXBVO4Frv3ejcQFXN
+5x1VQTJJzGHJhsNQ0lVL3MjyFAfiIivJORTk2jNAPkaOl9ei9IS6H7jAQcqrERXI
+vEASZTyAeQlcXprhbyZ2nf0CAwEAAQ==
+-----END PUBLIC KEY-----
+";
+
+        private const string _privateKey2 = @"-----BEGIN RSA PRIVATE KEY-----
+MIIJJgIBAAKCAgEAoGjcmNAHjUk2l8bMZ/eLupjEhYFOZCbsNiDwITQFTF7j/9v9
+t4inz2cW4/DFrfWV+gXVBzWzc5w75K2cafSJMbdRfDKzeV9HLRV56SLa1gFphgBt
+ksKadve5pqrn15MozMpfQt8GNYjxHiTyfdm+4TDSBYn1QjMKHNuRwHu8AygzlQ2d
+mW12icWDUjTiWUnw/6wLZMMPoU0ZRyHkr+LcHxYnkS5Q46t15ziDAmHFijSO14y0
+L6oI70v6joEEFNUsjHFEFVtWxbz0lfoag9vCOp9K+ReS7AUFdAifS87HSDHNcevV
+vRg7MzlG9rcyuFktucOLdQcPv7B86IRvagfJIdbE1e9oOw3irLiE9RT60e0ivNhn
+usB36paZJnf1k7FMcwWkRvcnzcrdSyElSBSskkwP1gXnUgRe39R/zDSTkqtE3N+r
+8hjhnCvsqxzQdmQyDGTNZRF+CNWKpk6k4ToLnVV9oY3J4GNXQ5NdITUWVMDrUQ2k
+NO+GdRvPnfRq/r8SJ3rRG2W2co6QTFk5YWvMMyZzGpI7jici5x/WM5igA+6ifkot
+ngwpqU16M7yS2xMIxKVTw9CaoIX2jgNolgGAyhkO4poTyn0zanedSJdPn/kW96j0
+u3WCoRo4K+eOB7Pcv/qC82Az+AQbTEqQnRea8iTTI65co5+BXSxQvyjM4wMCAwEA
+AQKCAgAHPhTPtXzRzT9wxOIPw6aEa0dcO8VdUkCSBRSyexXOJ+6la7pd4gapn57x
+9boHK7J00nSW2b7bdm9h2NDaG9dh7kP4lpVx4nJlP7X8Z713siKgkT5hRPYSbwbr
+1oWXPya1cGGytD0kh6VTVhm4wu8SXdDtvRfcwE8xlFxVU4Dep58EmNPHzKBwggF2
+4bpii6sc8BinmQMIpmGAy6/2nQiRQr/Ql0XBsckmAnAv2FhB8DOO2eR8znGO1GBg
+tMSJaEKVqLuJN1GIpgppBxzRXUe8u9p3uq/Ahk2DuqvukUyAHveGsD47Rm/N1UU1
++HmKx0QAQir2wrXcUsyg9vHM2MMk+KFkFUtVbrE5Ieeeoc/1ew78gQCwHER8VO0p
+b+F0sCbX39FMK4JHsE0dMNavbjUL3cH2a17kO79c92UAhRhnGbhaXmmMZw2kLuuZ
+xqxawaZEAiEfoteveQ0vd+aLDe/OA/xh7wV7ycn4Ja0FN72O3rBsAEWVRBrRgdwQ
+hNIysCLsN/MmI1oyEDrXV7I93pCI2gT+dODGa9GZbQTfLrtfaKTuiyjSJhtS6fQr
+6zBYucQ4UCNdrJRFo+rzq9kjwNn40GtPNXBKkO4IpAN3ropEpFQxHpyVE2SBx76j
+QN46K/AF3EB76Sl2SCyp7yEJIqGmJsGq65n6meM2DZ/05QbdwQKCAQEA2zjUnibx
+1U9l8J6q5mOqiGK6kbTD3BBCJLUg4eLr2bl0jp8Kai9PkwCPolqu+r29dqzm1gi6
+L0toSsfwlZ8Qnp4jXiR5JOnHrGDvFMrlBOp4ywJcpEY5FfXrEIAnvYkeBSuA2mHg
+HfIHULNBjUdrVEpCBgh1mBsod4YhispAshopty7O5as3dqzMmoodhGgau2vo6Xp3
+Xt0rzJ6+gD7Jz174Ww5lC3LK5PVGEVjwR4691P8fNCV5zv1O/DGAW6U4FKCdAxmt
+34xnlCjdcFAvTjsXurN2A2ssJ0soR+B5/gSj8LNKSgljML+jcJwVA5y9b5qnoLs/
+PoOtyBwNEvLTowKCAQEAu1ImogZOUrubpEbLfFEjJxxFwmZjYwMpUVFuySBcx8hJ
+EiDWC9mtJV1s20mUcFIlIxemfCZDKifoztjT6Z/3GDSEJWWpLTzZYYsnuD4yz2bs
+w6fBOiVbPAUoKJmcdkr1VtyPUcfKWSRaqHpiv1wjoMXazPyZNw4Rqnd6x1lSp92S
+wVpPZflJPr4THwM5Gy3QY5niKY5dag4UupPAkjt+d9OOO0+O603WQHSAXkpy9fXp
+BXqjwDF6GXa6w1ES4VFY4hLFOOQi6Y+wb1dgKge62KPcOj3Wcru8N1LX47lnHCzp
+k22JoCBrrPMjopZ3UqYm1I4TmwF+WFsKa48PQ6OpIQKB/y49zpuNm3VjSh13WpU+
+cLpUGQajGq1QwKL9kfIT66wBcpSi949ua1qWw7V7a214mH5v+kErlhpjzZv4kMb+
+xoKu2McC6orexT+XMtcv9R8UVmZ8GQ6NwXzgYrUYU0mnoq10f7mQ67VlWCWtqiYi
+6oDdKRAcuLFdCSwtHuYnw33OBv6c4QeRFiHyUTZH6/ICA6GFIZweOQ/Jl3OSCJ0E
+oY0ce0a5wpanoCSrmBwQpp5xfZlwNyTIwujmhcKsrmamcy3mszf0Mrj05ORbuln2
+kAPwcxDuyfXupWGkeNqwfwsV737WUtVLJaEiy1b1lXktlsfz12gQF0cYf4+2Wwuk
+LQKCAQBkcQ9gD6uNtyUkuAVCWqtTvFg3fflKzRYpkVWrKNw3D9EGlG7Rmd26zFaj
+WtfqRlG9eF//7/BRuWafCyrN+cVfyEEXYGSPajJRmHEq3McX6OOJofj9OayrCUTY
+SE3aLCVTdx6uRkfc9p5Z+o3aeAhum8jP454wJC4azsgZ/m5QroGThd5PGpVIvFi6
+Z1sGlNFJpujbSYgTZwt8Y999ScNtcxWv/d/vkiQRGab/aEIuWrahBnqpgp4q6zwH
+oQBTqu/TASeZctK5lB+SBDL/Nnfc1DgxTpkfmkS5EYXLiM2eEQMJ11FVeCzkZtcz
+xiSjP45QqQIgOnPJ4r86n1Ia/bWhAoIBAQC+8lcW0F+/ab5VN6KrrlTGZ/fzzSHT
+QV+tu6uTa+NGaBV3xHj4ej1zjyTWCiY1A9+WWTcDr2Ky4z+OsxHl6IS8amSEoHsX
+D4TpF3CqGJ2tF1LxAA/+nv1ROJNMKIBAtCsg0dY4c3QghHK7I/Sip2tOrzfL5kVD
+QPGjo05czwFkJVoLnPcwlp088KVO5/OoKPoiLqEG2dD0Z1gpQXfPtQcrctBjZx8F
+9+ySOSBm23snFa279lvTsJMmADkqulU6RSOSMOr0tTepQ6a1ujzbx01SxHwzNwZA
+t7jxfxrynr201mA4NDYfy49E1ujbKrJOfS5QDPcDIdCoHb7wno/BVkfQ
+-----END RSA PRIVATE KEY-----
+";
+
+        private const string _publicKey2 = @"-----BEGIN PUBLIC KEY-----
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAoGjcmNAHjUk2l8bMZ/eL
+upjEhYFOZCbsNiDwITQFTF7j/9v9t4inz2cW4/DFrfWV+gXVBzWzc5w75K2cafSJ
+MbdRfDKzeV9HLRV56SLa1gFphgBtksKadve5pqrn15MozMpfQt8GNYjxHiTyfdm+
+4TDSBYn1QjMKHNuRwHu8AygzlQ2dmW12icWDUjTiWUnw/6wLZMMPoU0ZRyHkr+Lc
+HxYnkS5Q46t15ziDAmHFijSO14y0L6oI70v6joEEFNUsjHFEFVtWxbz0lfoag9vC
+Op9K+ReS7AUFdAifS87HSDHNcevVvRg7MzlG9rcyuFktucOLdQcPv7B86IRvagfJ
+IdbE1e9oOw3irLiE9RT60e0ivNhnusB36paZJnf1k7FMcwWkRvcnzcrdSyElSBSs
+kkwP1gXnUgRe39R/zDSTkqtE3N+r8hjhnCvsqxzQdmQyDGTNZRF+CNWKpk6k4ToL
+nVV9oY3J4GNXQ5NdITUWVMDrUQ2kNO+GdRvPnfRq/r8SJ3rRG2W2co6QTFk5YWvM
+MyZzGpI7jici5x/WM5igA+6ifkotngwpqU16M7yS2xMIxKVTw9CaoIX2jgNolgGA
+yhkO4poTyn0zanedSJdPn/kW96j0u3WCoRo4K+eOB7Pcv/qC82Az+AQbTEqQnRea
+8iTTI65co5+BXSxQvyjM4wMCAwEAAQ==
+-----END PUBLIC KEY-----
+";
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAsymmetricUserKeysStore.cs b/Axantum.AxCrypt.Core.Test/TestAsymmetricUserKeysStore.cs
new file mode 100644
index 0000000..a7c94b1
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAsymmetricUserKeysStore.cs
@@ -0,0 +1,116 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.Mail;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAsymmetricUserKeysStore
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakePseudoRandomGenerator());
+            Factory.Instance.Singleton<IAsymmetricFactory>(() => new FakeAsymmetricFactory("MD5"));
+            Instance.UserSettings.AsymmetricKeyBits = 512;
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimpleCreateAsymmetricKeysStore()
+        {
+            FakeRuntimeFileInfo.AddFolder(@"C:\Temp");
+            IRuntimeFileInfo workFolder = Factory.New<IRuntimeFileInfo>(@"C:\Temp");
+            UserAsymmetricKeysStore store = new UserAsymmetricKeysStore(workFolder, Instance.KnownKeys);
+
+            store.Create(new EmailAddress(@"svante at axantum.com"), new Passphrase("secret"));
+            Assert.That(store.Keys.KeyPair.PrivateKey, Is.Not.Null);
+            Assert.That(store.Keys.KeyPair.PublicKey, Is.Not.Null);
+        }
+
+        [Test]
+        public static void TestCreateAndLoadAsymmetricKeysStore()
+        {
+            FakeRuntimeFileInfo.AddFolder(@"C:\Temp");
+            IRuntimeFileInfo workFolder = Factory.New<IRuntimeFileInfo>(@"C:\Temp\");
+            UserAsymmetricKeysStore store = new UserAsymmetricKeysStore(workFolder, Instance.KnownKeys);
+
+            store.Create(new EmailAddress(@"svante at axantum.com"), new Passphrase("secret"));
+            Assert.That(store.Keys.KeyPair.PrivateKey, Is.Not.Null);
+            Assert.That(store.Keys.KeyPair.PublicKey, Is.Not.Null);
+
+            IAsymmetricKeyPair keyPair = store.Keys.KeyPair;
+
+            store = new UserAsymmetricKeysStore(workFolder, Instance.KnownKeys);
+            store.Load(new EmailAddress(@"svante at axantum.com"), new Passphrase("secret"));
+
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey, Is.EqualTo(new Passphrase("secret")));
+            Assert.That(store.Keys.KeyPair.PrivateKey.ToString(), Is.EqualTo(keyPair.PrivateKey.ToString()));
+            Assert.That(store.Keys.KeyPair.PublicKey.ToString(), Is.EqualTo(keyPair.PublicKey.ToString()));
+        }
+
+        [Test]
+        public static void TestEncryptCreateLoadDecryptWithAsymmetricKeysStore()
+        {
+            FakeRuntimeFileInfo.AddFolder(@"C:\Temp");
+            IRuntimeFileInfo workFolder = Factory.New<IRuntimeFileInfo>(@"C:\Temp\");
+            UserAsymmetricKeysStore store = new UserAsymmetricKeysStore(workFolder, Instance.KnownKeys);
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("secret");
+
+            store.Create(new EmailAddress(@"svante at axantum.com"), new Passphrase("secret"));
+
+            string text = "AxCrypt encryption rules!";
+            byte[] encryptedBytes = store.Keys.KeyPair.PublicKey.Transform(Encoding.UTF8.GetBytes(text));
+
+            store = new UserAsymmetricKeysStore(workFolder, Instance.KnownKeys);
+            store.Load(new EmailAddress(@"svante at axantum.com"), new Passphrase("secret"));
+
+            byte[] decryptedBytes = store.Keys.KeyPair.PrivateKey.Transform(encryptedBytes);
+            Assert.That(decryptedBytes != null);
+            string decryptedText = Encoding.UTF8.GetString(decryptedBytes);
+
+            Assert.That(text, Is.EqualTo(decryptedText));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptFactory.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptFactory.cs
new file mode 100644
index 0000000..3676199
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptFactory.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAxCryptFactory
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestCreateDocumentBadArgument()
+        {
+            AxCryptFactory axFactory = new AxCryptFactory();
+
+            IAxCryptDocument document = null;
+            Assert.Throws<ArgumentException>(() => document = axFactory.CreateDocument(new Passphrase("toohigh"), Guid.NewGuid()));
+            Assert.That(document, Is.Null);
+        }
+
+        [Test]
+        public static void TestV2Document()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(500);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (V2AxCryptDocument document = new V2AxCryptDocument(new Passphrase("properties"), V2Aes256CryptoFactory.CryptoId, 15))
+                    {
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+                        outputStream.Position = 0;
+
+                        AxCryptFactory axFactory = new AxCryptFactory();
+                        IAxCryptDocument decryptedDocument = axFactory.CreateDocument(new Passphrase("properties"), new V2Aes256CryptoFactory().Id, outputStream);
+                        Assert.That(decryptedDocument.PassphraseIsValid);
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptFile.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptFile.cs
new file mode 100644
index 0000000..785d8c6
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptFile.cs
@@ -0,0 +1,584 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAxCryptFile
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _testTextPath = Path.Combine(_rootPath, "test.txt");
+        private static readonly string _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+        private static readonly string _uncompressedAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Uncompressed.axx");
+        private static readonly string _helloWorldAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HelloWorld.axx");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            FakeRuntimeFileInfo.AddFile(_testTextPath, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate3Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo destinationFileInfo = sourceFileInfo.CreateEncryptedName();
+            IAxCryptDocument document = new V1AxCryptDocument();
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "decrypted test.txt"));
+
+            IAxCryptDocument nullDocument = null;
+            IRuntimeFileInfo nullFileInfo = null;
+            Passphrase nullKey = null;
+            ProgressContext nullProgress = null;
+            Passphrase nullPassphrase = null;
+            Stream nullStream = null;
+            string nullString = null;
+            Action<Stream> nullStreamAction = null;
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Encrypt(nullFileInfo, destinationFileInfo, new Passphrase("axcrypt"), AxCryptOptions.EncryptWithCompression, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Encrypt(sourceFileInfo, nullFileInfo, new Passphrase("axcrypt"), AxCryptOptions.EncryptWithCompression, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Encrypt(sourceFileInfo, destinationFileInfo, nullPassphrase, AxCryptOptions.EncryptWithCompression, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Encrypt(sourceFileInfo, destinationFileInfo, new Passphrase("axcrypt"), AxCryptOptions.EncryptWithCompression, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { AxCryptFile.Encrypt(nullFileInfo, new MemoryStream(), Passphrase.Empty, Guid.Empty, AxCryptOptions.None, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { AxCryptFile.Encrypt(sourceFileInfo, nullStream, Passphrase.Empty, Guid.Empty, AxCryptOptions.None, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { AxCryptFile.Encrypt(sourceFileInfo, new MemoryStream(), nullKey, Guid.Empty, AxCryptOptions.None, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { AxCryptFile.Encrypt(sourceFileInfo, new MemoryStream(), Passphrase.Empty, Guid.Empty, AxCryptOptions.None, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(nullDocument, decryptedFileInfo, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(document, nullFileInfo, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(document, decryptedFileInfo, AxCryptOptions.SetFileTimes, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(nullFileInfo, decryptedFileInfo, Passphrase.Empty, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, nullFileInfo, Passphrase.Empty, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, decryptedFileInfo, nullKey, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, decryptedFileInfo, Passphrase.Empty, AxCryptOptions.SetFileTimes, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(nullFileInfo, Path.Combine(_rootPath, "Directory"), Passphrase.Empty, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, nullString, Passphrase.Empty, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, Path.Combine(_rootPath, "Directory"), nullKey, AxCryptOptions.SetFileTimes, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, Path.Combine(_rootPath, "Directory"), Passphrase.Empty, AxCryptOptions.SetFileTimes, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Document(nullFileInfo, Passphrase.Empty, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Document(sourceFileInfo, nullKey, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Document(sourceFileInfo, Passphrase.Empty, nullProgress); });
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().WriteToFileWithBackup(null, (Stream stream) => { }, new ProgressContext()); });
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().WriteToFileWithBackup(fileInfo, nullStreamAction, new ProgressContext()); });
+
+            Assert.Throws<ArgumentNullException>(() => { AxCryptFile.MakeAxCryptFileName(nullFileInfo); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().Wipe(nullFileInfo, new ProgressContext()); });
+        }
+
+        [Test]
+        public static void TestSmallEncryptDecrypt()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo destinationFileInfo = sourceFileInfo.CreateEncryptedName();
+            Assert.That(destinationFileInfo.Name, Is.EqualTo("test-txt.axx"), "Wrong encrypted file name based on the plain text file name.");
+            Factory.New<AxCryptFile>().Encrypt(sourceFileInfo, destinationFileInfo, new Passphrase("axcrypt"), AxCryptOptions.EncryptWithCompression, new ProgressContext());
+            using (IAxCryptDocument document = Factory.New<AxCryptFile>().Document(destinationFileInfo, new Passphrase("axcrypt"), new ProgressContext()))
+            {
+                Assert.That(document.PassphraseIsValid, Is.True, "The passphrase should be ok.");
+                Assert.That(document.FileName, Is.EqualTo("test.txt"), "Unexpected file name in headers.");
+                Assert.That(document.CreationTimeUtc, Is.EqualTo(FakeRuntimeFileInfo.TestDate1Utc));
+                Assert.That(document.LastAccessTimeUtc, Is.EqualTo(FakeRuntimeFileInfo.TestDate2Utc));
+                Assert.That(document.LastWriteTimeUtc, Is.EqualTo(FakeRuntimeFileInfo.TestDate3Utc));
+                IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "decrypted test.txt"));
+                Factory.New<AxCryptFile>().Decrypt(document, decryptedFileInfo, AxCryptOptions.SetFileTimes, new ProgressContext());
+                using (Stream decryptedStream = decryptedFileInfo.OpenRead())
+                {
+                    string decrypted = new StreamReader(decryptedStream, Encoding.UTF8).ReadToEnd();
+                    Assert.That(decrypted, Is.EqualTo("This is a short file"));
+                }
+                Assert.That(decryptedFileInfo.CreationTimeUtc, Is.EqualTo(document.CreationTimeUtc), "We're expecting file times to be set as the original from the headers.");
+                Assert.That(decryptedFileInfo.LastAccessTimeUtc, Is.EqualTo(document.LastAccessTimeUtc), "We're expecting file times to be set as the original from the headers.");
+                Assert.That(decryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(document.LastWriteTimeUtc), "We're expecting file times to be set as the original from the headers.");
+            }
+        }
+
+        [Test]
+        public static void TestEncryptToStream()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo destinationFileInfo = sourceFileInfo.CreateEncryptedName();
+            Assert.That(destinationFileInfo.Name, Is.EqualTo("test-txt.axx"), "Wrong encrypted file name based on the plain text file name.");
+            using (Stream destinationStream = destinationFileInfo.OpenWrite())
+            {
+                AxCryptFile.Encrypt(sourceFileInfo, destinationStream, new Passphrase("axcrypt"), V2Aes128CryptoFactory.CryptoId, AxCryptOptions.EncryptWithCompression, new ProgressContext());
+            }
+
+            using (IAxCryptDocument document = Factory.New<AxCryptFile>().Document(destinationFileInfo, new Passphrase("axcrypt"), new ProgressContext()))
+            {
+                Assert.That(document.PassphraseIsValid, Is.True, "The passphrase should be ok.");
+            }
+        }
+
+        [Test]
+        public static void TestDecryptToDestinationDirectory()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            string destinationDirectory = Path.Combine(_rootPath, "Encrypted");
+
+            string destinationFileName = Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, destinationDirectory, new Passphrase("a"), AxCryptOptions.None, new ProgressContext());
+            Assert.That(destinationFileName, Is.EqualTo("HelloWorld-Key-a.txt"), "The correct filename should be returned from decryption.");
+        }
+
+        [Test]
+        public static void TestDecryptToDestinationDirectoryWithWrongPassphrase()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            string destinationDirectory = Path.Combine(_rootPath, "Encrypted");
+
+            string destinationFileName = Factory.New<AxCryptFile>().Decrypt(sourceFileInfo, destinationDirectory, new Passphrase("Wrong Passphrase"), AxCryptOptions.None, new ProgressContext());
+            Assert.That(destinationFileName, Is.Null, "When the wrong passphrase is given, the returned file name should be null to signal this.");
+        }
+
+        [Test]
+        public static void TestDecryptWithCancel()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Passphrase passphrase = new Passphrase("a");
+            using (IAxCryptDocument document = new V1AxCryptDocument())
+            {
+                IProgressContext progress = new CancelProgressContext(new ProgressContext(new TimeSpan(0, 0, 0, 0, 100)));
+                progress.Progressing += (object sender, ProgressEventArgs e) =>
+                {
+                    progress.Cancel = true;
+                };
+                using (Stream sourceStream = new ProgressStream(sourceFileInfo.OpenRead(), progress))
+                {
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, sourceStream);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(_rootPath.PathCombine("Destination", "Decrypted.txt"));
+
+                    FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+                    environment.CurrentTiming.CurrentTiming = new TimeSpan(0, 0, 0, 0, 100);
+                    Assert.Throws<OperationCanceledException>(() => { Factory.New<AxCryptFile>().Decrypt(document, destinationInfo, AxCryptOptions.None, progress); });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestLargeEncryptDecrypt()
+        {
+            string sourceFullName = _davidCopperfieldTxtPath;
+
+            IRuntimeFileInfo sourceRuntimeFileInfo = Factory.New<IRuntimeFileInfo>(sourceFullName);
+            IRuntimeFileInfo destinationRuntimeFileInfo = sourceRuntimeFileInfo.CreateEncryptedName();
+            Passphrase passphrase = new Passphrase("laDabled at tAmeopot33");
+
+            Factory.New<AxCryptFile>().Encrypt(sourceRuntimeFileInfo, destinationRuntimeFileInfo, passphrase, AxCryptOptions.SetFileTimes | AxCryptOptions.EncryptWithCompression, new ProgressContext());
+
+            Assert.That(destinationRuntimeFileInfo.CreationTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.CreationTimeUtc), "We're expecting file times to be set as the original from the headers.");
+            Assert.That(destinationRuntimeFileInfo.LastAccessTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.LastAccessTimeUtc), "We're expecting file times to be set as the original from the headers.");
+            Assert.That(destinationRuntimeFileInfo.LastWriteTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.LastWriteTimeUtc), "We're expecting file times to be set as the original from the headers.");
+
+            DirectoryInfo decryptedDirectoryInfo = new DirectoryInfo(_rootPath.PathCombine("Destination", "Decrypted.txt"));
+            string decryptedFullName = Path.Combine(decryptedDirectoryInfo.FullName, "David Copperfield.txt");
+            IRuntimeFileInfo decryptedRuntimeFileInfo = Factory.New<IRuntimeFileInfo>(decryptedFullName);
+
+            Factory.New<AxCryptFile>().Decrypt(destinationRuntimeFileInfo, decryptedRuntimeFileInfo, passphrase, AxCryptOptions.SetFileTimes, new ProgressContext());
+
+            Assert.That(decryptedRuntimeFileInfo.CreationTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.CreationTimeUtc), "We're expecting file times to be set as the original from the headers.");
+            Assert.That(decryptedRuntimeFileInfo.LastAccessTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.LastAccessTimeUtc), "We're expecting file times to be set as the original from the headers.");
+            Assert.That(decryptedRuntimeFileInfo.LastWriteTimeUtc, Is.EqualTo(sourceRuntimeFileInfo.LastWriteTimeUtc), "We're expecting file times to be set as the original from the headers.");
+
+            using (StreamReader sourceStreamReader = new StreamReader(sourceRuntimeFileInfo.OpenRead(), Encoding.GetEncoding("Windows-1252")))
+            {
+                using (StreamReader decryptedStreamReader = new StreamReader(decryptedRuntimeFileInfo.OpenRead(), Encoding.GetEncoding("Windows-1252")))
+                {
+                    string source = sourceStreamReader.ReadToEnd();
+                    string decrypted = decryptedStreamReader.ReadToEnd();
+
+                    Assert.That(decrypted, Is.EqualTo(source), "Comparing original plain text with the decrypted encrypted plain text.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestInvalidPassphrase()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_testTextPath);
+            IRuntimeFileInfo encryptedFileInfo = sourceFileInfo.CreateEncryptedName();
+            Assert.That(encryptedFileInfo.Name, Is.EqualTo("test-txt.axx"), "Wrong encrypted file name based on the plain text file name.");
+            Factory.New<AxCryptFile>().Encrypt(sourceFileInfo, encryptedFileInfo, new Passphrase("axcrypt"), AxCryptOptions.EncryptWithCompression, new ProgressContext());
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(_rootPath, "decrypted.txt"));
+            bool isPassphraseOk = Factory.New<AxCryptFile>().Decrypt(encryptedFileInfo, decryptedFileInfo, new Passphrase("wrong"), AxCryptOptions.None, new ProgressContext());
+            Assert.That(isPassphraseOk, Is.False, "The passphrase is wrong and should be wrong!");
+        }
+
+        [Test]
+        public static void TestUncompressedEncryptedDecryptAxCrypt17()
+        {
+            IRuntimeFileInfo sourceRuntimeFileInfo = Factory.New<IRuntimeFileInfo>(_uncompressedAxxPath);
+            IRuntimeFileInfo destinationRuntimeFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_uncompressedAxxPath), "Uncompressed.zip"));
+            Passphrase passphrase = new Passphrase("Uncompressable");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool isOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, sourceRuntimeFileInfo.OpenRead());
+                Assert.That(isOk, Is.True, "The document should load ok.");
+                Factory.New<AxCryptFile>().Decrypt(document, destinationRuntimeFileInfo, AxCryptOptions.None, new ProgressContext());
+                Assert.That(document.DocumentHeaders.UncompressedLength, Is.EqualTo(0), "Since the data is not compressed, there should not be a CompressionInfo, but in 1.x there is, with value zero.");
+            }
+        }
+
+        [Test]
+        public static void TestWriteToFileWithBackup()
+        {
+            string destinationFilePath = _rootPath.PathCombine("Written", "File.txt");
+            using (MemoryStream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("A string with some text")))
+            {
+                IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFilePath);
+                Factory.New<AxCryptFile>().WriteToFileWithBackup(destinationFileInfo, (Stream stream) => { inputStream.CopyTo(stream, 4096); }, new ProgressContext());
+                using (TextReader read = new StreamReader(destinationFileInfo.OpenRead()))
+                {
+                    string readString = read.ReadToEnd();
+                    Assert.That(readString, Is.EqualTo("A string with some text"), "Where expecting the same string to be read back.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestWriteToFileWithBackupWithCancel()
+        {
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(_rootPath.PathCombine("Written", "File.txt"));
+            using (MemoryStream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("A string with some text")))
+            {
+                Assert.Throws<OperationCanceledException>(() => { Factory.New<AxCryptFile>().WriteToFileWithBackup(destinationFileInfo, (Stream stream) => { throw new OperationCanceledException(); }, new ProgressContext()); });
+                string tempFilePath = _rootPath.PathCombine("Written", "File.bak");
+                IRuntimeFileInfo tempFileInfo = Factory.New<IRuntimeFileInfo>(tempFilePath);
+                Assert.That(tempFileInfo.IsExistingFile, Is.False, "The .bak file should be removed.");
+            }
+        }
+
+        [Test]
+        public static void TestWriteToFileWithBackupWhenDestinationExists()
+        {
+            string destinationFilePath = _rootPath.PathCombine("Written", "AnExistingFile.txt");
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFilePath);
+            IRuntimeFileInfo bakFileInfo = Factory.New<IRuntimeFileInfo>(_rootPath.PathCombine("Written", "AnExistingFile.bak"));
+            Assert.That(bakFileInfo.IsExistingFile, Is.False, "The file should not exist to start with.");
+            using (Stream writeStream = destinationFileInfo.OpenWrite())
+            {
+                byte[] bytes = Encoding.UTF8.GetBytes("A string");
+                writeStream.Write(bytes, 0, bytes.Length);
+            }
+
+            using (MemoryStream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("A string with some text")))
+            {
+                Factory.New<AxCryptFile>().WriteToFileWithBackup(destinationFileInfo, (Stream stream) => { inputStream.CopyTo(stream, 4096); }, new ProgressContext());
+                using (TextReader read = new StreamReader(destinationFileInfo.OpenRead()))
+                {
+                    string readString = read.ReadToEnd();
+                    Assert.That(readString, Is.EqualTo("A string with some text"), "Where expecting the same string to be read back.");
+                }
+            }
+            Assert.That(bakFileInfo.IsExistingFile, Is.False, "The file should not exist afterwards either.");
+        }
+
+        [Test]
+        public static void TestMakeAxCryptFileName()
+        {
+            string testFile = _rootPath.PathCombine("Directory", "file.txt");
+            string axxFile = _rootPath.PathCombine("Directory", "file-txt.axx");
+            string madeName = AxCryptFile.MakeAxCryptFileName(Factory.New<IRuntimeFileInfo>(testFile));
+            Assert.That(madeName, Is.EqualTo(axxFile), "The AxCrypt version of the name is unexpected.");
+        }
+
+        [Test]
+        public static void TestWipe()
+        {
+            string testFile = _rootPath.PathCombine("Folder", "file-to-be-wiped.txt");
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(testFile);
+            using (Stream writeStream = fileInfo.OpenWrite())
+            {
+            }
+            Assert.That(fileInfo.IsExistingFile, "Now it should exist.");
+            Factory.New<AxCryptFile>().Wipe(fileInfo, new ProgressContext());
+            Assert.That(!fileInfo.IsExistingFile, "And now it should not exist after wiping.");
+        }
+
+        [Test]
+        public static void TestEncryptFileWithBackupFileInfoAndWipeNullArguments()
+        {
+            string sourceFilePath = _davidCopperfieldTxtPath;
+            string destinationFilePath = Path.Combine(Path.GetDirectoryName(sourceFilePath), "David Copperfield-txt.axx");
+
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(sourceFilePath);
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFilePath);
+            IRuntimeFileInfo nullFileInfo = null;
+
+            Passphrase key = Passphrase.Empty;
+            Passphrase nullKey = null;
+
+            ProgressContext progress = new ProgressContext();
+            ProgressContext nullProgress = null;
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(nullFileInfo, destinationFileInfo, key, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFileInfo, nullFileInfo, key, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFileInfo, destinationFileInfo, nullKey, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFileInfo, destinationFileInfo, key, Guid.Empty, nullProgress); });
+        }
+
+        [Test]
+        public static void TestEncryptFileWithBackupAndWipeFileInfo()
+        {
+            string sourceFilePath = _davidCopperfieldTxtPath;
+            string destinationFilePath = Path.Combine(Path.GetDirectoryName(sourceFilePath), "David Copperfield-txt.axx");
+
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(sourceFilePath);
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFilePath);
+
+            Passphrase key = new Passphrase("a");
+
+            ProgressContext progress = new ProgressContext();
+
+            Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFileInfo, destinationFileInfo, key, V2Aes128CryptoFactory.CryptoId, progress);
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestEncryptFileWithBackupFileNameAndWipeNullArguments()
+        {
+            string sourceFilePath = _davidCopperfieldTxtPath;
+            string destinationFilePath = Path.Combine(Path.GetDirectoryName(sourceFilePath), "David Copperfield-txt.axx");
+
+            string nullFileName = null;
+
+            Passphrase key = new Passphrase(String.Empty);
+            Passphrase nullKey = null;
+
+            ProgressContext progress = new ProgressContext();
+            ProgressContext nullProgress = null;
+
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(nullFileName, destinationFilePath, key, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFilePath, nullFileName, key, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFilePath, destinationFilePath, nullKey, Guid.Empty, progress); });
+            Assert.Throws<ArgumentNullException>(() => { Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFilePath, destinationFilePath, key, Guid.Empty, nullProgress); });
+        }
+
+        [Test]
+        public static void TestEncryptFileWithBackupAndWipeFileName()
+        {
+            string sourceFilePath = _davidCopperfieldTxtPath;
+            string destinationFilePath = Path.Combine(Path.GetDirectoryName(sourceFilePath), "David Copperfield-txt.axx");
+
+            Passphrase key = new Passphrase("b");
+            ProgressContext progress = new ProgressContext();
+
+            Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(sourceFilePath, destinationFilePath, key, V2Aes256CryptoFactory.CryptoId, progress);
+
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(sourceFilePath);
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFilePath);
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestDecryptFileUniqueWithWipeOfOriginal()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));
+            Passphrase passphrase = new Passphrase("a");
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.True, "The source should exist.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.False, "The source should not exist yet.");
+
+            Factory.New<AxCryptFile>().DecryptFileUniqueWithWipeOfOriginal(sourceFileInfo, passphrase, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestDecryptFilesUniqueWithWipeOfOriginal()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new ParallelFileOperation());
+            Factory.Instance.Singleton<IProgressBackground>(() => new FakeProgressBackground());
+            Factory.Instance.Singleton<IUIThread>(() => new FakeUIThread());
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            sourceFileInfo.CreateFolder();
+            IRuntimeFileInfo sourceFolderInfo = Factory.New<IRuntimeFileInfo>(Path.GetDirectoryName(sourceFileInfo.FullName));
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));
+            Passphrase passphrase = new Passphrase("a");
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.True, "The source should exist.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.False, "The source should not exist yet.");
+
+            Factory.New<AxCryptFile>().DecryptFilesInsideFolderUniqueWithWipeOfOriginal(sourceFolderInfo, passphrase, mockStatusChecker.Object, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestEncryptFileUniqueWithBackupAndWipeWithNoCollision()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            sourceFileInfo.CreateFolder();
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.axx"));
+
+            Passphrase passphrase = new Passphrase("allan");
+
+            Factory.New<AxCryptFile>().EncryptFileUniqueWithBackupAndWipe(sourceFileInfo, passphrase, V1Aes128CryptoFactory.CryptoId, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestEncryptFileUniqueWithBackupAndWipeWithCollision()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            sourceFileInfo.CreateFolder();
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.axx"));
+            destinationFileInfo.CreateNewFile();
+
+            IRuntimeFileInfo alternateDestinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.1.axx"));
+
+            Passphrase passphrase = new Passphrase("allan");
+
+            Factory.New<AxCryptFile>().EncryptFileUniqueWithBackupAndWipe(sourceFileInfo, passphrase, V2Aes256CryptoFactory.CryptoId, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(alternateDestinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestEncryptFilesUniqueWithBackupAndWipeWithNoCollision()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            sourceFileInfo.CreateFolder();
+            IRuntimeFileInfo sourceFolderInfo = Factory.New<IRuntimeFileInfo>(Path.GetDirectoryName(sourceFileInfo.FullName));
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.axx"));
+
+            Passphrase passphrase = new Passphrase("allan");
+
+            Factory.New<AxCryptFile>().EncryptFoldersUniqueWithBackupAndWipe(new IRuntimeFileInfo[] { sourceFolderInfo }, passphrase, V1Aes128CryptoFactory.CryptoId, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(destinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestEncryptFilesUniqueWithBackupAndWipeWithCollision()
+        {
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            sourceFileInfo.CreateFolder();
+            IRuntimeFileInfo sourceFolderInfo = Factory.New<IRuntimeFileInfo>(Path.GetDirectoryName(sourceFileInfo.FullName));
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.axx"));
+            destinationFileInfo.CreateNewFile();
+
+            IRuntimeFileInfo alternateDestinationFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_davidCopperfieldTxtPath), "David Copperfield-txt.1.axx"));
+
+            Passphrase passphrase = new Passphrase("allan");
+
+            Factory.New<AxCryptFile>().EncryptFoldersUniqueWithBackupAndWipe(new IRuntimeFileInfo[] { sourceFolderInfo }, passphrase, V2Aes128CryptoFactory.CryptoId, new ProgressContext());
+
+            Assert.That(sourceFileInfo.IsExistingFile, Is.False, "The source should be wiped.");
+            Assert.That(alternateDestinationFileInfo.IsExistingFile, Is.True, "The destination should be created and exist now.");
+        }
+
+        [Test]
+        public static void TestWipeFileDoesNotExist()
+        {
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            bool progressed = false;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                progressed = true;
+            };
+
+            string filePath = Path.Combine(Path.Combine(_rootPath, "Folder"), "DoesNot.Exist");
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(filePath);
+
+            Assert.DoesNotThrow(() => { Factory.New<AxCryptFile>().Wipe(fileInfo, progress); });
+            Assert.That(!progressed, "There should be no progress-notification since nothing should happen.");
+        }
+
+        [Test]
+        public static void TestWipeWithDelayedUntilDoneCancel()
+        {
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+
+            IProgressContext progress = new CancelProgressContext(new ProgressContext(TimeSpan.Zero));
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                ((IProgressContext)sender).Cancel = true;
+            };
+            Assert.Throws<OperationCanceledException>(() => { Factory.New<AxCryptFile>().Wipe(fileInfo, progress); });
+            Assert.That(!fileInfo.IsExistingFile, "The file should be completely wiped, even if canceled at start.");
+        }
+
+        [Test]
+        public static void TestDocumentNullArguments()
+        {
+            IRuntimeFileInfo nullSourceFile = null;
+            Passphrase nullPassphrase = null;
+            IProgressContext nullProgress = null;
+
+            IRuntimeFileInfo sourceFile = Factory.New<IRuntimeFileInfo>(@"C:\Folder\File.txt");
+            Passphrase passphrase = new Passphrase("allan");
+            IProgressContext progress = new ProgressContext();
+
+            IAxCryptDocument document = null;
+            Assert.Throws<ArgumentNullException>(() => document = Factory.New<AxCryptFile>().Document(nullSourceFile, passphrase, progress));
+            Assert.Throws<ArgumentNullException>(() => document = Factory.New<AxCryptFile>().Document(sourceFile, nullPassphrase, progress));
+            Assert.Throws<ArgumentNullException>(() => document = Factory.New<AxCryptFile>().Document(sourceFile, passphrase, nullProgress));
+            Assert.That(document, Is.Null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptHMACSHA1.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptHMACSHA1.cs
new file mode 100644
index 0000000..7ea961b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptHMACSHA1.cs
@@ -0,0 +1,74 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Portable;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Justification = "Both HMAC and SHA1 are meaningful acronyms and this is the way .NET does the naming.")]
+    public static class TestAxCryptHMACSHA1
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            HMAC hmac = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                hmac = Instance.Portable.AxCryptHMACSHA1(null);
+            });
+
+            // Use the instance to avoid FxCop errors.
+            Object.Equals(hmac, null);
+        }
+
+        [Test]
+        public static void TestMethods()
+        {
+            SymmetricKey key = new SymmetricKey(128);
+            HMAC hmac = Instance.Portable.AxCryptHMACSHA1(key);
+
+            Assert.That(hmac.Key, Is.EquivalentTo(key.GetBytes()), "Ensure that we're using the specified key.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptHeaderKeyWrap.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptHeaderKeyWrap.cs
new file mode 100644
index 0000000..1e0452b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptHeaderKeyWrap.cs
@@ -0,0 +1,100 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public class TestAxCryptHeaderKeyWrap
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is test, readability and coding ease is a concern, not performance.")]
+        public void TestUnwrapFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                V1KeyWrap1HeaderBlock keyWrapHeaderBlock = null;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    int headers = 0;
+                    while (axCryptReader.Read())
+                    {
+                        switch (axCryptReader.CurrentItemType)
+                        {
+                            case AxCryptItemType.None:
+                                break;
+
+                            case AxCryptItemType.MagicGuid:
+                                break;
+
+                            case AxCryptItemType.HeaderBlock:
+                                if (axCryptReader.CurrentHeaderBlock.HeaderBlockType == HeaderBlockType.KeyWrap1)
+                                {
+                                    keyWrapHeaderBlock = (V1KeyWrap1HeaderBlock)axCryptReader.CurrentHeaderBlock;
+                                    ++headers;
+                                }
+                                break;
+
+                            case AxCryptItemType.Data:
+                                break;
+
+                            case AxCryptItemType.EndOfStream:
+                                break;
+
+                            default:
+                                break;
+                        }
+                    }
+                    Assert.That(headers, Is.EqualTo(1), "We're expecting exactly one KeyWrap1 block to be found!");
+                    byte[] wrapped = keyWrapHeaderBlock.GetKeyData();
+                    KeyWrap keyWrap = new KeyWrap(keyWrapHeaderBlock.Salt, keyWrapHeaderBlock.KeyWrapIterations, KeyWrapMode.AxCrypt);
+                    byte[] unwrapped = keyWrap.Unwrap(new V1AesCrypto(new V1Aes128CryptoFactory(), new V1DerivedKey(new Passphrase("a")).DerivedKey, SymmetricIV.Zero128), wrapped);
+                    Assert.That(unwrapped.Length, Is.Not.EqualTo(0), "An unwrapped key is invalid if it is returned as a zero-length array.");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptReaderIdTagHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderIdTagHeaderBlock.cs
new file mode 100644
index 0000000..dbef5c0
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderIdTagHeaderBlock.cs
@@ -0,0 +1,77 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public class TestAxCryptReaderIdTagHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is test, readability and coding ease is a concern, not performance.")]
+        public void TestFindFindIdTag()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                new PreambleHeaderBlock().Write(testStream);
+                new V1IdTagHeaderBlock("A test").Write(testStream);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "This should be a header block");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Preamble), "This should be an Preamble block");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "This should be a header block");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.IdTag), "This should be an IdTag block");
+                    V1IdTagHeaderBlock idTagHeaderBlock = (V1IdTagHeaderBlock)axCryptReader.CurrentHeaderBlock;
+                    Assert.That(idTagHeaderBlock.IdTag, Is.EqualTo("A test"), "We're expecting to be able to read the same tag we wrote");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptReaderMagicGuid.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderMagicGuid.cs
new file mode 100644
index 0000000..9b1128f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderMagicGuid.cs
@@ -0,0 +1,171 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.IO;
+using System.Text;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAxCryptReaderMagicGuid
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidFirstAndOnly()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestFindMagicGuidFirstWithMore()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                byte[] someBytes = Encoding.UTF8.GetBytes("This is a test string that we'll convert into some random bytes....");
+                testStream.Write(someBytes, 0, someBytes.Length);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidWithOtherFirstButNoMore()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                byte[] someBytes = Encoding.UTF8.GetBytes("This is a test string that we'll convert into some random bytes....");
+                testStream.Write(someBytes, 0, someBytes.Length);
+                AxCrypt1Guid.Write(testStream);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidWithOtherFirstAndMore()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                byte[] someBytes = Encoding.UTF8.GetBytes("This is a test string that we'll convert into some random bytes....");
+                testStream.Write(someBytes, 0, someBytes.Length);
+                AxCrypt1Guid.Write(testStream);
+                testStream.Write(someBytes, 0, someBytes.Length);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidWithMuchOtherFirstAndMore()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                byte[] someBytes = Encoding.UTF8.GetBytes("This is a test string that we'll convert into some random bytes....");
+                int targetAmountOfBytesBefore = 1024 * 1024 * 4;
+                while (targetAmountOfBytesBefore > 0)
+                {
+                    testStream.Write(someBytes, 0, someBytes.Length);
+                    targetAmountOfBytesBefore -= someBytes.Length;
+                }
+                AxCrypt1Guid.Write(testStream);
+                testStream.Write(someBytes, 0, someBytes.Length);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidButInputTooShort()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                byte[] someBytes = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
+                testStream.Write(someBytes, 0, someBytes.Length);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.False, "There should be no Guid found, since there are not enough bytes in the stream.");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.EndOfStream), "Nothing has been found yet in the stream.");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindMagicGuidFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptReaderPreambleHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderPreambleHeaderBlock.cs
new file mode 100644
index 0000000..887c387
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderPreambleHeaderBlock.cs
@@ -0,0 +1,145 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public class TestAxCryptReaderPreambleHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is test, readability and coding ease is a concern, not performance.")]
+        public void TestFindPreambleHeaderBlockFirstButMoreThanOnceShouldThrow()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+                preambleHeaderBlock.Write(testStream);
+                preambleHeaderBlock.Write(testStream);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Preamble), "We're expecting to have found a Preamble specifically");
+                    Assert.Throws<FileFormatException>(() => axCryptReader.Read());
+                }
+            }
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "This is test, readability and coding ease is a concern, not performance.")]
+        public void TestFindPreambleHeaderBlockNotFirstShouldThrow()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                VersionHeaderBlock versionHeaderBlock = new VersionHeaderBlock(new byte[] { 3, 2, 2, 0, 0 });
+                versionHeaderBlock.Write(testStream);
+                PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+                preambleHeaderBlock.Write(testStream);
+                testStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.Throws<FileFormatException>(() => axCryptReader.Read());
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindPreambleHeaderBlockFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    bool blockFound = false;
+                    int headers = 0;
+                    while (axCryptReader.Read())
+                    {
+                        switch (axCryptReader.CurrentItemType)
+                        {
+                            case AxCryptItemType.None:
+                                break;
+
+                            case AxCryptItemType.MagicGuid:
+                                break;
+
+                            case AxCryptItemType.HeaderBlock:
+                                if (axCryptReader.CurrentHeaderBlock.HeaderBlockType == HeaderBlockType.Preamble)
+                                {
+                                    Assert.That(blockFound, Is.False, "We should only find one single PreambleHeaderBlock");
+                                    blockFound = true;
+
+                                    Assert.That(headers, Is.EqualTo(0), "Preamble must be first");
+                                    PreambleHeaderBlock preambleHeaderBlock = (PreambleHeaderBlock)axCryptReader.CurrentHeaderBlock;
+                                    Assert.That(preambleHeaderBlock.Hmac.Length, Is.EqualTo(V1Hmac.RequiredLength), "The HMAC in the preamble must be exactly 16 bytes.");
+                                }
+                                ++headers;
+                                break;
+
+                            case AxCryptItemType.Data:
+                                break;
+
+                            case AxCryptItemType.EndOfStream:
+                                break;
+
+                            default:
+                                break;
+                        }
+                    }
+                    Assert.That(blockFound, Is.True, "We're expecting a VersionHeaderBlock to be found!");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptReaderVersionHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderVersionHeaderBlock.cs
new file mode 100644
index 0000000..c78151a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptReaderVersionHeaderBlock.cs
@@ -0,0 +1,94 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.IO;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAxCryptReaderVersionHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFindVersionHeaderBlockFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(testStream))
+                {
+                    bool blockFound = false;
+                    int headers = 0;
+                    while (axCryptReader.Read())
+                    {
+                        switch (axCryptReader.CurrentItemType)
+                        {
+                            case AxCryptItemType.None:
+                                break;
+
+                            case AxCryptItemType.MagicGuid:
+                                break;
+
+                            case AxCryptItemType.HeaderBlock:
+                                if (axCryptReader.CurrentHeaderBlock.HeaderBlockType == HeaderBlockType.Version)
+                                {
+                                    Assert.That(blockFound, Is.False, "We should only find one single VersionHeaderBlock");
+                                    blockFound = true;
+                                }
+                                ++headers;
+                                break;
+
+                            case AxCryptItemType.Data:
+                                break;
+
+                            case AxCryptItemType.EndOfStream:
+                                break;
+
+                            default:
+                                break;
+                        }
+                    }
+                    Assert.That(blockFound, Is.True, "We're expecting a VersionHeaderBlock to be found!");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestAxCryptStreamReader.cs b/Axantum.AxCrypt.Core.Test/TestAxCryptStreamReader.cs
new file mode 100644
index 0000000..a89a714
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestAxCryptStreamReader.cs
@@ -0,0 +1,362 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.IO;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestAxCryptStreamReader
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestConstructor()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(null)) { }
+            }, "A non-null input-stream must be specified.");
+
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                inputStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                inputStream.Position = 0;
+
+                // The stream reader supports both externally supplied LookAheadStream or will wrap it if it is not.
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(new LookAheadStream(inputStream)))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFactoryMethod()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(null)) { }
+            }, "A non-null input-stream must be specified.");
+
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                inputStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestObjectDisposed()
+        {
+            using (Stream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(inputStream))
+                {
+                    axCryptReader.Dispose();
+
+                    Assert.Throws<ObjectDisposedException>(() =>
+                    {
+                        bool isOk = axCryptReader.Read();
+                        Object.Equals(isOk, null);
+                    }, "The reader is disposed.");
+                }
+            }
+        }
+
+        private class AxCryptReaderForTest : V1AxCryptReader
+        {
+            public AxCryptReaderForTest(Stream inputStream)
+                : base(inputStream)
+            {
+            }
+
+            public void SetCurrentItemType(AxCryptItemType itemType)
+            {
+                CurrentItemType = itemType;
+            }
+        }
+
+        [Test]
+        public static void TestUndefinedItemType()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(testStream))
+                {
+                    axCryptReader.SetCurrentItemType(AxCryptItemType.Undefined);
+                    Assert.Throws<InternalErrorException>(() =>
+                    {
+                        bool isOk = axCryptReader.Read();
+                        Object.Equals(isOk, null);
+                    });
+                }
+            }
+        }
+
+        private class BadHeaderBlock : HeaderBlock
+        {
+            public BadHeaderBlock()
+                : base(HeaderBlockType.Undefined, new byte[0])
+            {
+                FakeHeaderBlockLength = 5;
+            }
+
+            public override object Clone()
+            {
+                throw new NotImplementedException();
+            }
+
+            public int FakeHeaderBlockLength { get; set; }
+
+            public void SetHeaderBlockType(HeaderBlockType headerBlockType)
+            {
+                HeaderBlockType = headerBlockType;
+            }
+
+            public override void Write(Stream stream)
+            {
+                byte[] headerBlockPrefix = new byte[4 + 1];
+                BitConverter.GetBytes(FakeHeaderBlockLength).CopyTo(headerBlockPrefix, 0);
+                headerBlockPrefix[4] = (byte)HeaderBlockType;
+                stream.Write(headerBlockPrefix, 0, headerBlockPrefix.Length);
+                stream.Write(GetDataBlockBytesReference(), 0, GetDataBlockBytesReference().Length);
+            }
+        }
+
+        [Test]
+        public static void TestNegativeHeaderBlockType()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+
+                BadHeaderBlock badHeaderBlock = new BadHeaderBlock();
+                badHeaderBlock.SetHeaderBlockType((HeaderBlockType)(-1));
+                badHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.Throws<FileFormatException>(() =>
+                    {
+                        axCryptReader.Read();
+                    }, "A negative header block type is not valid.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestNegativeHeaderBlockLength()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+
+                BadHeaderBlock badHeaderBlock = new BadHeaderBlock();
+                badHeaderBlock.FakeHeaderBlockLength = -50;
+                badHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.Throws<FileFormatException>(() =>
+                    {
+                        axCryptReader.Read();
+                    }, "A negative header block length is not valid.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestTooLargeHeaderBlockLength()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+
+                BadHeaderBlock badHeaderBlock = new BadHeaderBlock();
+                badHeaderBlock.FakeHeaderBlockLength = 0x1000000;
+                badHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.Throws<FileFormatException>(() =>
+                    {
+                        axCryptReader.Read();
+                    }, "A too large header block length is not valid.");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestTooShortStream()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+
+                BadHeaderBlock badHeaderBlock = new BadHeaderBlock();
+                badHeaderBlock.FakeHeaderBlockLength = 5 + 1;
+                badHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.False, "The stream is too short and end prematurely and should thus be able to read the block");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.EndOfStream), "The stream is at an end and current item type should reflect this.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestInvalidHeaderBlockType()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+                preambleHeaderBlock.Write(inputStream);
+
+                BadHeaderBlock badHeaderBlock = new BadHeaderBlock();
+                badHeaderBlock.FakeHeaderBlockLength = 5;
+                badHeaderBlock.SetHeaderBlockType(HeaderBlockType.Encrypted);
+                badHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Preamble), "We're expecting to have found a Preamble specifically");
+
+                    Assert.Throws<FileFormatException>(() =>
+                    {
+                        axCryptReader.Read();
+                    });
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestKeyWrap2HeaderBlock()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+                preambleHeaderBlock.Write(inputStream);
+                V1KeyWrap2HeaderBlock keyWrap2HeaderBlock = new V1KeyWrap2HeaderBlock(new byte[0]);
+                keyWrap2HeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Preamble), "We're expecting to have found a Preamble specifically");
+
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.KeyWrap2), "We're expecting to have found a KeyWrap2 specifically");
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestUnrecognizedHeaderBlock()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+                preambleHeaderBlock.Write(inputStream);
+                UnrecognizedHeaderBlock unrecognizedHeaderBlock = new UnrecognizedHeaderBlock(HeaderBlockType.Unrecognized, new byte[0]);
+                unrecognizedHeaderBlock.Write(inputStream);
+                inputStream.Position = 0;
+                using (AxCryptReader axCryptReader = new V1AxCryptReader(inputStream))
+                {
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the Guid");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.MagicGuid), "We're expecting to have found a MagicGuid");
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Preamble), "We're expecting to have found a Preamble specifically");
+
+                    Assert.That(axCryptReader.Read(), Is.True, "We should be able to read the next HeaderBlock");
+                    Assert.That(axCryptReader.CurrentItemType, Is.EqualTo(AxCryptItemType.HeaderBlock), "We're expecting to have found a HeaderBlock");
+                    Assert.That(axCryptReader.CurrentHeaderBlock.HeaderBlockType, Is.EqualTo(HeaderBlockType.Unrecognized), "We're expecting to have found an unrecognized block specifically");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestCancelContext.cs b/Axantum.AxCrypt.Core.Test/TestCancelContext.cs
new file mode 100644
index 0000000..afc4b8f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestCancelContext.cs
@@ -0,0 +1,112 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestCancelContext
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAddRemoveProgressingEvent()
+        {
+            CancelProgressContext progress = new CancelProgressContext(new ProgressContext(TimeSpan.Zero));
+            int percent = -1;
+
+            EventHandler<ProgressEventArgs> handler = (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+
+            progress.Progressing += handler;
+            progress.AddTotal(200);
+            progress.AddCount(100);
+            Assert.That(percent, Is.EqualTo(50), "When halfway, the percent should be 50.");
+
+            FakeRuntimeEnvironment.Instance.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1);
+            progress.AddCount(50);
+            Assert.That(percent, Is.EqualTo(75), "150 of 200 is 75%.");
+
+            progress.Progressing -= handler;
+
+            FakeRuntimeEnvironment.Instance.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1);
+            progress.AddCount(50);
+            Assert.That(percent, Is.EqualTo(75), "Since the event handler was removed, percent should stay the same.");
+        }
+
+        [Test]
+        public static void TestAllItemsConfirmed()
+        {
+            ProgressContext progressContext = new ProgressContext(TimeSpan.Zero);
+            CancelProgressContext cancelContext = new CancelProgressContext(progressContext);
+
+            Assert.That(progressContext.AllItemsConfirmed, Is.False, "The default value is false.");
+            Assert.That(cancelContext.AllItemsConfirmed, Is.EqualTo(progressContext.AllItemsConfirmed), "The cancel context should have the same value as the progressContext.");
+
+            cancelContext.AllItemsConfirmed = true;
+            Assert.That(progressContext.AllItemsConfirmed, Is.True, "The progressContext should reflect the setting of the cancelContext.");
+            Assert.That(cancelContext.AllItemsConfirmed, Is.EqualTo(progressContext.AllItemsConfirmed), "The cancel context should have the same value as the progressContext.");
+        }
+
+        [Test]
+        public static void TestRemoveCount()
+        {
+            ProgressContext progressContext = new ProgressContext(TimeSpan.Zero);
+            CancelProgressContext cancelContext = new CancelProgressContext(progressContext);
+            int percent = 0;
+            cancelContext.Progressing += (sender, e) =>
+            {
+                percent = e.Percent;
+            };
+
+            cancelContext.AddTotal(100);
+            cancelContext.AddCount(10);
+            Assert.That(percent, Is.EqualTo(10), "10 of 100 is 10%.");
+
+            cancelContext.RemoveCount(50, 10);
+            FakeRuntimeEnvironment.Instance.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(1000);
+            cancelContext.AddCount(10);
+            Assert.That(percent, Is.EqualTo(20), "10 of 50 is 20%.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestCommandLine.cs b/Axantum.AxCrypt.Core.Test/TestCommandLine.cs
new file mode 100644
index 0000000..2072c53
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestCommandLine.cs
@@ -0,0 +1,120 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using Axantum.AxCrypt.Core.Runtime;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestCommandLine
+    {
+        private static FakeRequestClient _fakeClient;
+
+        private static FakeRequestServer _fakeServer;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+            Factory.Instance.Singleton<FakeRequestClient>(() => new FakeRequestClient());
+            Factory.Instance.Singleton<FakeRequestServer>(() => new FakeRequestServer());
+            _fakeClient = Factory.Instance.Singleton<FakeRequestClient>();
+            _fakeServer = Factory.Instance.Singleton<FakeRequestServer>();
+            Factory.Instance.Singleton<CommandService>(() => new CommandService(_fakeServer, _fakeClient));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestFailedOpen()
+        {
+            _fakeClient.FakeDispatcher = (command) => { return CommandStatus.Error; };
+            CommandLine cl = new CommandLine("axcrypt.exe", new string[] { "file.axx" });
+            FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning = true;
+            cl.Execute();
+
+            Assert.That(FakeRuntimeEnvironment.Instance.ExitCode, Is.EqualTo(1), "An error during Open shall return status code 1.");
+        }
+
+        [Test]
+        public static void TestExit()
+        {
+            bool wasExit = false;
+            _fakeServer.Request += (sender, e) =>
+            {
+                wasExit = e.Command.Verb == CommandVerb.Exit;
+            };
+
+            _fakeClient.FakeDispatcher = (command) => { _fakeServer.AcceptRequest(command); return CommandStatus.Success; };
+
+            CommandLine cl = new CommandLine("axcrypt.exe", new string[] { "--exit" });
+            FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning = true;
+            cl.Execute();
+
+            Assert.That(wasExit, Is.True);
+        }
+
+        [Test]
+        public static void TestNeedToLaunchFirstInstance()
+        {
+            var mock = new Mock<FakeRuntimeEnvironment>() { CallBase = true };
+            mock.Setup<ILauncher>(x => x.Launch(It.IsAny<string>()))
+                .Returns((string path) =>
+                {
+                    FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning = path == "axcrypt.exe";
+                    return new FakeLauncher(path);
+                });
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => mock.Object);
+
+            _fakeClient.FakeDispatcher = (command) => { _fakeServer.AcceptRequest(command); return CommandStatus.Success; };
+            CommandLine cl = new CommandLine("axcrypt.exe", new string[0]);
+            Assert.That(FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning, Is.False);
+            cl.Execute();
+            Assert.That(FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning, Is.True);
+        }
+
+        [Test]
+        public static void TestFailedToLaunchFirstInstance()
+        {
+            _fakeClient.FakeDispatcher = (command) => { _fakeServer.AcceptRequest(command); return CommandStatus.Success; };
+            CommandLine cl = new CommandLine("axcrypt.exe", new string[0]);
+            Assert.That(FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning, Is.False);
+            cl.Execute();
+            Assert.That(FakeRuntimeEnvironment.Instance.IsFirstInstanceRunning, Is.False);
+            Assert.That(FakeRuntimeEnvironment.Instance.ExitCode, Is.EqualTo(2), "Failed to start the first instance shall return status code 2.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestCommandService.cs b/Axantum.AxCrypt.Core.Test/TestCommandService.cs
new file mode 100644
index 0000000..8fa0a23
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestCommandService.cs
@@ -0,0 +1,78 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestCommandService
+    {
+        [Test]
+        public static void TestCall()
+        {
+            IRequestServer serverMock = Mock.Of<IRequestServer>();
+            IRequestClient clientMock = Mock.Of<IRequestClient>(x => x.Dispatch(It.Is<CommandServiceEventArgs>(ca => ca.Verb == CommandVerb.Open)) == CommandStatus.Success);
+
+            CommandService service = new CommandService(serverMock, clientMock);
+            CommandStatus status = service.Call(CommandVerb.Open, -1, @"C:\folder\file.axx");
+
+            Assert.That(status, Is.EqualTo(CommandStatus.Success), "The call should indicate success.");
+        }
+
+        [Test]
+        public static void TestStart()
+        {
+            IRequestServer serverMock = Mock.Of<IRequestServer>();
+            IRequestClient clientMock = Mock.Of<IRequestClient>();
+
+            CommandService service = new CommandService(serverMock, clientMock);
+            service.StartListening();
+
+            Assert.DoesNotThrow(() => Mock.Get(serverMock).Verify(s => s.Start()));
+        }
+
+        [Test]
+        public static void TestServerReceive()
+        {
+            IRequestServer serverMock = Mock.Of<IRequestServer>();
+            IRequestClient clientMock = Mock.Of<IRequestClient>();
+
+            CommandService service = new CommandService(serverMock, clientMock);
+            bool received = false;
+            service.Received += (sender, e) => received = e.Verb == CommandVerb.Exit;
+
+            Mock.Get(serverMock).Raise(s => s.Request += null, new RequestCommandEventArgs(new CommandServiceEventArgs(CommandVerb.Exit, -1)));
+
+            Assert.That(received, Is.True, "A command should be received.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestCommandServiceEventArgsTest.cs b/Axantum.AxCrypt.Core.Test/TestCommandServiceEventArgsTest.cs
new file mode 100644
index 0000000..c38896c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestCommandServiceEventArgsTest.cs
@@ -0,0 +1,51 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using Newtonsoft.Json;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestCommandServiceEventArgsTest
+    {
+        [Test]
+        public static void TestJsonSerialization()
+        {
+            CommandServiceEventArgs args = new CommandServiceEventArgs();
+            string json = JsonConvert.SerializeObject(args);
+
+            args = JsonConvert.DeserializeObject<CommandServiceEventArgs>(json);
+
+            Assert.That(args.Verb, Is.EqualTo(CommandVerb.Unknown));
+            Assert.That(args.Arguments.Count(), Is.EqualTo(0));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestCounterModeCryptoTransform.cs b/Axantum.AxCrypt.Core.Test/TestCounterModeCryptoTransform.cs
new file mode 100644
index 0000000..acda72d
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestCounterModeCryptoTransform.cs
@@ -0,0 +1,103 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestCounterModeCryptoTransform
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructorWithBadArguments()
+        {
+            SymmetricAlgorithm algorithm = Instance.Portable.AesManaged();
+            ICryptoTransform transform = null;
+
+            try
+            {
+                algorithm.Mode = CipherMode.CBC;
+                Assert.Throws<ArgumentException>(() => transform = new CounterModeCryptoTransform(algorithm, 0, 0));
+
+                algorithm.Mode = CipherMode.ECB;
+                algorithm.Padding = PaddingMode.PKCS7;
+                Assert.Throws<ArgumentException>(() => transform = new CounterModeCryptoTransform(algorithm, 0, 0));
+
+                algorithm.Padding = PaddingMode.None;
+                Assert.DoesNotThrow(() => transform = new CounterModeCryptoTransform(algorithm, 0, 0));
+            }
+            finally
+            {
+                if (transform != null)
+                {
+                    transform.Dispose();
+                }
+            }
+        }
+
+        [Test]
+        public static void TestCanReuseTransform()
+        {
+            SymmetricAlgorithm algorithm = Instance.Portable.AesManaged();
+            algorithm.Mode = CipherMode.ECB;
+            algorithm.Padding = PaddingMode.None;
+            using (ICryptoTransform transform = new CounterModeCryptoTransform(algorithm, 0, 0))
+            {
+                Assert.That(transform.CanReuseTransform);
+            }
+        }
+
+        [Test]
+        public static void TestTransformBlockWithBadArgument()
+        {
+            SymmetricAlgorithm algorithm = Instance.Portable.AesManaged();
+            algorithm.Mode = CipherMode.ECB;
+            algorithm.Padding = PaddingMode.None;
+            using (ICryptoTransform transform = new CounterModeCryptoTransform(algorithm, 0, 0))
+            {
+                Assert.Throws<ArgumentException>(() => transform.TransformBlock(new byte[transform.InputBlockSize + 1], 0, transform.InputBlockSize + 1, new byte[transform.InputBlockSize + 1], 0));
+                Assert.DoesNotThrow(() => transform.TransformBlock(new byte[transform.InputBlockSize], 0, transform.InputBlockSize, new byte[transform.InputBlockSize], 0));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestDataHmac.cs b/Axantum.AxCrypt.Core.Test/TestDataHmac.cs
new file mode 100644
index 0000000..ce14e38
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestDataHmac.cs
@@ -0,0 +1,89 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestDataHmac
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            V1Hmac hmac = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                hmac = new V1Hmac(null);
+            });
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                hmac = new V1Hmac(new byte[20]);
+            });
+
+            // Use the instance to avoid FxCop errors.
+            Object.Equals(hmac, null);
+        }
+
+        [Test]
+        public static void TestMethods()
+        {
+            V1Hmac hmac = new V1Hmac(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 });
+
+            Assert.That(hmac.Length, Is.EqualTo(V1Hmac.RequiredLength), "The length should always be 16.");
+            Assert.That(hmac.GetBytes(), Is.EquivalentTo(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }), "Check that GetBytes() returns the expected.");
+            Assert.That(hmac, Is.EqualTo(new V1Hmac(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 })), "Check Equals() override.");
+            Assert.That(hmac == new V1Hmac(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }), Is.True, "Check operator== override.");
+            Assert.That(hmac != new V1Hmac(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }), Is.False, "Check operator!= override.");
+
+            V1Hmac hmac2 = new V1Hmac(new byte[] { 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 });
+            Assert.That(hmac.GetHashCode(), Is.Not.EqualTo(0), "The hash code should not be zero (can be, but it's not in this case).");
+            Assert.That(hmac.GetHashCode(), Is.EqualTo(hmac2.GetHashCode()), "The hash code for two different instances with same value should be the same.");
+
+            Assert.That(hmac.Equals(null), Is.False, "An instance is never equal to null.");
+            Assert.That(hmac.Equals(new object()), Is.False, "An instance is never equal to another instance of a differing type.");
+            V1Hmac hmacSynonym = hmac;
+            Assert.That(hmac == hmacSynonym, Is.True, "These should compare equal via reference equality.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestDelayedAction.cs b/Axantum.AxCrypt.Core.Test/TestDelayedAction.cs
new file mode 100644
index 0000000..8805e0e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestDelayedAction.cs
@@ -0,0 +1,123 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestDelayedAction
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<ISleep>(() => new FakeSleep());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestShortDelayButNoStart()
+        {
+            bool wasHere = false;
+            FakeSleep fakeSleep = new FakeSleep();
+            using (DelayedAction delayedAction = new DelayedAction(new FakeDelayTimer(fakeSleep), new TimeSpan(0, 0, 0, 0, 1)))
+            {
+                delayedAction.Action += (sender, e) => wasHere = true;
+                fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 50));
+                Assert.That(wasHere, Is.False, "The event should not be triggered until started.");
+            }
+        }
+
+        [Test]
+        public static void TestShortDelayAndImmediateStart()
+        {
+            bool wasHere = false;
+            FakeSleep fakeSleep = new FakeSleep();
+            using (DelayedAction delayedAction = new DelayedAction(new FakeDelayTimer(fakeSleep), new TimeSpan(0, 0, 0, 0, 1)))
+            {
+                delayedAction.Action += (sender, e) => wasHere = true;
+                delayedAction.StartIdleTimer();
+                fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 50));
+                Assert.That(wasHere, Is.True, "The event should be triggered once started.");
+                wasHere = false;
+                fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 50));
+                Assert.That(wasHere, Is.False, "The event should not be triggered more than once.");
+            }
+        }
+
+        [Test]
+        public static void TestManyRestartsButOnlyOneEvent()
+        {
+            int eventCount = 0;
+            FakeSleep fakeSleep = new FakeSleep();
+            using (DelayedAction delayedAction = new DelayedAction(new FakeDelayTimer(fakeSleep), new TimeSpan(0, 0, 0, 0, 5)))
+            {
+                delayedAction.Action += (sender, e) => ++eventCount;
+                for (int i = 0; i < 10; ++i)
+                {
+                    delayedAction.StartIdleTimer();
+                }
+                fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 5));
+                Assert.That(eventCount, Is.EqualTo(1), "The event should be triggered exactly once.");
+                fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 5));
+                Assert.That(eventCount, Is.EqualTo(1), "The event should still be triggered exactly once.");
+            }
+        }
+
+        [Test]
+        public static void TestEventAfterDispose()
+        {
+            bool wasHere = false;
+            FakeSleep fakeSleep = new FakeSleep();
+            using (DelayedAction delayedAction = new DelayedAction(new FakeDelayTimer(fakeSleep), new TimeSpan(0, 0, 0, 0, 1)))
+            {
+                delayedAction.Action += (sender, e) => wasHere = true;
+                delayedAction.StartIdleTimer();
+                Assert.That(wasHere, Is.False, "The event should not be triggered immediately.");
+            }
+            fakeSleep.Time(new TimeSpan(0, 0, 0, 0, 1));
+            Assert.That(wasHere, Is.False, "The event should be not be triggered once disposed.");
+        }
+
+        [Test]
+        public static void TestObjectDisposedException()
+        {
+            FakeSleep fakeSleep = new FakeSleep();
+            DelayedAction delayedAction = new DelayedAction(new FakeDelayTimer(fakeSleep), new TimeSpan(0, 0, 0, 0, 1));
+            delayedAction.Dispose();
+            Assert.Throws<ObjectDisposedException>(() => { delayedAction.StartIdleTimer(); });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestDelegateAction.cs b/Axantum.AxCrypt.Core.Test/TestDelegateAction.cs
new file mode 100644
index 0000000..ce05224
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestDelegateAction.cs
@@ -0,0 +1,116 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestDelegateAction
+    {
+        [SetUp]
+        public static void Setup()
+        {
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestCanExecute()
+        {
+            int result = 0;
+            DelegateAction<int> action = new DelegateAction<int>((i) => result = i + i, (i) => i == result);
+
+            Assert.That(action.CanExecute(0), Is.True);
+            Assert.That(action.CanExecute(1), Is.False);
+        }
+
+        [Test]
+        public static void TestCanExecuteChanged()
+        {
+            Factory.Instance.Singleton<IUIThread>(() => new Mock<IUIThread>().Object);
+            Mock.Get(Instance.UIThread).Setup(u => u.RunOnUIThread(It.IsAny<Action>())).Callback<Action>(a => a());
+
+            int result = 0;
+            bool canExecuteChanged = false;
+            DelegateAction<int> action = new DelegateAction<int>((i) => result = i + i, (i) => i == result);
+            action.CanExecuteChanged += (sender, e) =>
+            {
+                canExecuteChanged = true;
+            };
+
+            action.RaiseCanExecuteChanged();
+            Assert.That(canExecuteChanged, Is.True, "This should have raised the CanExecuteChanged event.");
+            Mock.Get(Instance.UIThread).Verify(u => u.RunOnUIThread(It.IsAny<Action>()), Times.Once);
+        }
+
+        [Test]
+        public static void TestExecute()
+        {
+            int result = 0;
+            DelegateAction<int> action = new DelegateAction<int>((i) => result = i + i, (i) => i == result);
+
+            result = 5;
+            action.Execute(5);
+
+            Assert.That(result, Is.EqualTo(10));
+        }
+
+        [Test]
+        public static void TestExecuteWhenNotCanExecute()
+        {
+            int result = 0;
+            DelegateAction<int> action = new DelegateAction<int>((i) => result = i + i, (i) => i == result);
+
+            Assert.That(action.CanExecute(0), Is.True);
+            Assert.Throws<InvalidOperationException>(() => action.Execute(5));
+        }
+
+        [Test]
+        public static void TestExecuteWithNoConditionForCanExecute()
+        {
+            int result = 0;
+            DelegateAction<int> action = new DelegateAction<int>((i) => result = i + i);
+
+            Assert.That(action.CanExecute(0), Is.True);
+            Assert.That(action.CanExecute(1), Is.True);
+
+            result = 5;
+            action.Execute(5);
+
+            Assert.That(result, Is.EqualTo(10));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestDocumentHeaders.cs b/Axantum.AxCrypt.Core.Test/TestDocumentHeaders.cs
new file mode 100644
index 0000000..d2eebae
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestDocumentHeaders.cs
@@ -0,0 +1,160 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestDocumentHeaders
+    {
+        private class AxCryptReaderForTest : V1AxCryptReader
+        {
+            public AxCryptReaderForTest(Stream inputStream)
+                : base(inputStream)
+            {
+            }
+
+            public override bool Read()
+            {
+                bool isOk = base.Read();
+                if (CurrentItemType != AxCryptItemType.MagicGuid)
+                {
+                    CurrentItemType = (AxCryptItemType)666;
+                }
+                return isOk;
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidItemType()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(inputStream);
+                new PreambleHeaderBlock().Write(inputStream);
+                inputStream.Position = 0;
+                using (AxCryptReaderForTest axCryptReader = new AxCryptReaderForTest(inputStream))
+                {
+                    V1DocumentHeaders documentHeaders = new V1DocumentHeaders(new Passphrase("secret"), 15);
+                    Assert.Throws<InternalErrorException>(() =>
+                    {
+                        documentHeaders.Load(axCryptReader);
+                    });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestBadArguments()
+        {
+            V1DocumentHeaders documentHeaders = new V1DocumentHeaders(Passphrase.Empty, 37);
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                documentHeaders.WriteWithHmac(null);
+            });
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                documentHeaders.WriteWithoutHmac(null);
+            });
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                documentHeaders.Headers.Hmac = null;
+            });
+        }
+
+        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestBadKey()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                using (AxCryptReader reader = new V1AxCryptReader(testStream))
+                {
+                    Passphrase passphrase = new Passphrase("b");
+                    V1DocumentHeaders documentHeaders = new V1DocumentHeaders(passphrase, 73);
+                    bool isPassphraseValid = documentHeaders.Load(reader);
+
+                    Assert.That(isPassphraseValid, Is.False, "The passphrase is intentionally wrong for this test case.");
+                    Assert.That(documentHeaders.HmacSubkey, Is.Null, "Since the passphrase is wrong, HmacSubkey should return null.");
+                    Assert.That(documentHeaders.DataSubkey, Is.Null, "Since the passphrase is wrong, DataSubkey should return null.");
+                    Assert.That(documentHeaders.HeadersSubkey, Is.Null, "Since the passphrase is wrong, HeadersSubkey should return null.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptOfTooNewFileVersion()
+        {
+            DateTime creationTimeUtc = new DateTime(2012, 1, 1, 1, 2, 3, DateTimeKind.Utc);
+            DateTime lastAccessTimeUtc = creationTimeUtc + new TimeSpan(1, 0, 0);
+            DateTime lastWriteTimeUtc = creationTimeUtc + new TimeSpan(2, 0, 0); ;
+            using (Stream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("AxCrypt is Great!")))
+            {
+                using (Stream outputStream = new MemoryStream())
+                {
+                    Passphrase passphrase = new Passphrase("a");
+                    using (V1AxCryptDocument document = new V1AxCryptDocument(passphrase, 101))
+                    {
+                        document.FileName = "MyFile.txt";
+                        document.CreationTimeUtc = creationTimeUtc;
+                        document.LastAccessTimeUtc = lastAccessTimeUtc;
+                        document.LastWriteTimeUtc = lastWriteTimeUtc;
+                        VersionHeaderBlock versionHeaderBlock = document.DocumentHeaders.VersionHeaderBlock;
+                        versionHeaderBlock.FileVersionMajor = (byte)(versionHeaderBlock.FileVersionMajor + 1);
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithoutCompression);
+                    }
+                    outputStream.Position = 0;
+                    using (IAxCryptDocument document = new V1AxCryptDocument())
+                    {
+                        Assert.Throws<FileFormatException>(() => { document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, outputStream); });
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestEncryptedDataPartBlock.cs b/Axantum.AxCrypt.Core.Test/TestEncryptedDataPartBlock.cs
new file mode 100644
index 0000000..270d7d4
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestEncryptedDataPartBlock.cs
@@ -0,0 +1,58 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestEncryptedDataPartBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            EncryptedDataPartBlock block = new EncryptedDataPartBlock(new byte[] { 1, 2, 3, 4, 5 });
+            EncryptedDataPartBlock clone = (EncryptedDataPartBlock)block.Clone();
+
+            Assert.That(!Object.ReferenceEquals(block.GetDataBlockBytes(), clone.GetDataBlockBytes()));
+            Assert.That(block.GetDataBlockBytes(), Is.EquivalentTo(clone.GetDataBlockBytes()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestExceptions.cs b/Axantum.AxCrypt.Core.Test/TestExceptions.cs
new file mode 100644
index 0000000..3a20699
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestExceptions.cs
@@ -0,0 +1,156 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestExceptions
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAxCryptExceptions()
+        {
+            Assert.Throws<FileFormatException>(() =>
+            {
+                throw new FileFormatException();
+            });
+            try
+            {
+                throw new FileFormatException();
+            }
+            catch (AxCryptException ace)
+            {
+                Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.Unknown), "Parameterless constructor should result in status Unknown.");
+            }
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                throw new InternalErrorException();
+            });
+            try
+            {
+                throw new InternalErrorException();
+            }
+            catch (AxCryptException ace)
+            {
+                Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.Unknown), "Parameterless constructor should result in status Unknown.");
+            }
+
+            Assert.Throws<Axantum.AxCrypt.Core.Runtime.IncorrectDataException>(() =>
+            {
+                throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException();
+            });
+            try
+            {
+                throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException();
+            }
+            catch (AxCryptException ace)
+            {
+                Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.Unknown), "Parameterless constructor should result in status Unknown.");
+            }
+        }
+
+        [Test]
+        public static void TestInnerException()
+        {
+            try
+            {
+                int i = (int)new object();
+
+                // Use the instance to avoid FxCop errors.
+                Object.Equals(i, null);
+            }
+            catch (InvalidCastException ice)
+            {
+                try
+                {
+                    throw new FileFormatException("Testing inner", ice);
+                }
+                catch (AxCryptException ace)
+                {
+                    Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.FileFormatError), "Wrong status.");
+                    Assert.That(ace.Message, Is.EqualTo("Testing inner"), "Wrong message.");
+                    Assert.That(ace.InnerException.GetType(), Is.EqualTo(typeof(InvalidCastException)), "Wrong inner exception.");
+                }
+            }
+
+            try
+            {
+                if ((int)new object() == 0) { }
+            }
+            catch (InvalidCastException ice)
+            {
+                try
+                {
+                    throw new InternalErrorException("Testing inner", ice);
+                }
+                catch (AxCryptException ace)
+                {
+                    Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.InternalError), "Wrong status.");
+                    Assert.That(ace.Message, Is.EqualTo("Testing inner"), "Wrong message.");
+                    Assert.That(ace.InnerException.GetType(), Is.EqualTo(typeof(InvalidCastException)), "Wrong inner exception.");
+                }
+            }
+
+            try
+            {
+                if ((int)new object() == 0) { }
+            }
+            catch (InvalidCastException ice)
+            {
+                try
+                {
+                    throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException("Testing inner", ice);
+                }
+                catch (AxCryptException ace)
+                {
+                    Assert.That(ace.ErrorStatus, Is.EqualTo(ErrorStatus.DataError), "Wrong status.");
+                    Assert.That(ace.Message, Is.EqualTo("Testing inner"), "Wrong message.");
+                    Assert.That(ace.InnerException.GetType(), Is.EqualTo(typeof(InvalidCastException)), "Wrong inner exception.");
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestExtensions.cs b/Axantum.AxCrypt.Core.Test/TestExtensions.cs
new file mode 100644
index 0000000..9451188
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestExtensions.cs
@@ -0,0 +1,515 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestExtensions
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestStringInvariantFormat()
+        {
+            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("sv-SE");
+            DateTime dateTime = new DateTime(2001, 2, 3, 4, 5, 6, DateTimeKind.Utc);
+
+            string dateTimeSwedishFormatted = String.Format(CultureInfo.CurrentCulture, "Formatted: {0}", dateTime);
+            Assert.That(dateTimeSwedishFormatted, Is.EqualTo("Formatted: 2001-02-03 04:05:06"));
+
+            string dateTimeInvariantFormatted = "Formatted: {0}".InvariantFormat(dateTime);
+            Assert.That(dateTimeInvariantFormatted, Is.EqualTo("Formatted: 02/03/2001 04:05:06"));
+        }
+
+        [Test]
+        public static void TestStringFormatWith()
+        {
+            Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("sv-SE");
+            DateTime dateTime = new DateTime(2001, 2, 3, 4, 5, 6, DateTimeKind.Utc);
+
+            string dateTimeSwedishFormatted = "Formatted: {0}".FormatWith(CultureInfo.CurrentCulture, dateTime);
+            Assert.That(dateTimeSwedishFormatted, Is.EqualTo("Formatted: 2001-02-03 04:05:06"));
+
+            string dateTimeInvariantFormatted = "Formatted: {0}".FormatWith(CultureInfo.InvariantCulture, dateTime);
+            Assert.That(dateTimeInvariantFormatted, Is.EqualTo("Formatted: 02/03/2001 04:05:06"));
+        }
+
+        [Test]
+        public static void TestByteArrayLocate()
+        {
+            byte[] testArray = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
+
+            int locationSingleByteFirstInArray = testArray.Locate(new byte[] { 0x01 }, 0, testArray.Length);
+            Assert.That(locationSingleByteFirstInArray, Is.EqualTo(0), "Looking for a single byte that is first in the array.");
+
+            int locationSingleByteLastInArray = testArray.Locate(new byte[] { 0x00 }, 0, testArray.Length);
+            Assert.That(locationSingleByteLastInArray, Is.EqualTo(testArray.Length - 1), "Looking for a single byte that is last in the array.");
+
+            int locationSingleByteNotInArray = testArray.Locate(new byte[] { 0xff }, 0, testArray.Length);
+            Assert.That(locationSingleByteNotInArray, Is.EqualTo(-1), "Looking for a single byte that is not part of the array.");
+
+            int locationSingleByteNotInPartOfArray = testArray.Locate(new byte[] { 0x01 }, 1, testArray.Length - 3);
+            Assert.That(locationSingleByteNotInPartOfArray, Is.EqualTo(-1), "Looking for a single byte that is not in a selected part of the array.");
+
+            int locationMultipleBytesFirstInArray = testArray.Locate(new byte[] { 0x01, 0x02, 0x03 }, 0, testArray.Length);
+            Assert.That(locationMultipleBytesFirstInArray, Is.EqualTo(0), "Looking for multiple bytes that are first in the array.");
+
+            int locationMultipleBytesLastInArray = testArray.Locate(new byte[] { 0x02, 0x01, 0x00 }, 0, testArray.Length);
+            Assert.That(locationMultipleBytesLastInArray, Is.EqualTo(testArray.Length - 3), "Looking for multiple bytes that are last in the array.");
+
+            int locationMultipleBytesMiddleInArray = testArray.Locate(new byte[] { 0x09, 0x09, 0x08 }, 0, testArray.Length);
+            Assert.That(locationMultipleBytesMiddleInArray, Is.EqualTo(8), "Looking for multiple bytes that are in the middle of the array.");
+
+            int locationMultipleBytesNotInArray = testArray.Locate(new byte[] { 0x02, 0x00, 0x01 }, 0, testArray.Length);
+            Assert.That(locationMultipleBytesNotInArray, Is.EqualTo(-1), "Looking for multiple bytes that are not in the array.");
+
+            int locationMultipleBytesLastInPartOfArray = testArray.Locate(new byte[] { 0x03, 0x02, 0x01 }, 2, testArray.Length - 3);
+            Assert.That(locationMultipleBytesLastInPartOfArray, Is.EqualTo(testArray.Length - 4), "Looking for multiple bytes that are last in part of the array.");
+
+            int locationMultipleBytesNotInPartOfArray = testArray.Locate(new byte[] { 0x03, 0x02, 0x01 }, 2, testArray.Length - 4);
+            Assert.That(locationMultipleBytesNotInPartOfArray, Is.EqualTo(-1), "Looking for multiple bytes that are not in part of the array.");
+        }
+
+        [Test]
+        public static void TestByteArrayXor()
+        {
+            byte[] testArray = new byte[] { 0x01, 0x02, 0x04, 0x08, 0x00, 0xff };
+
+            byte[] nullArray = null;
+
+            TestDelegate bufferArgumentNullException = () => nullArray.Xor(testArray);
+            Assert.Throws<ArgumentNullException>(bufferArgumentNullException, "Calling with a null-reference buffer.");
+
+            TestDelegate otherArgumentNullException = () => testArray.Xor(nullArray);
+            Assert.Throws<ArgumentNullException>(otherArgumentNullException, "Calling with a null-reference other argument.");
+            Assert.That(testArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0x08, 0x00, 0xff }), "Assuring that the array is still unmodified.");
+
+            byte[] xorArray = (byte[])testArray.Clone();
+            xorArray.Xor(testArray);
+            Assert.That(xorArray, Is.EqualTo(new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }), "Xor with all of itself should yield all zeros.");
+
+            xorArray.Xor(new byte[] { 0x01, 0x02, 0x04 });
+            Assert.That(xorArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0x00, 0x00, 0x00 }), "Xor with a short array should only affect those bytes.");
+
+            xorArray.Xor(new byte[] { 0x00, 0x00, 0x00, 0x08, 0x00, 0xff, 0x12, 0x34, 0x56 });
+            Assert.That(xorArray, Is.EqualTo(testArray), "Xor with a longer array should just ignore the extra bytes in other.");
+
+            TestDelegate bufferArgumentWithAllParametersNullException = () => nullArray.Xor(0, testArray, 0, testArray.Length);
+            Assert.Throws<ArgumentNullException>(bufferArgumentWithAllParametersNullException, "Calling all parameters overload with null-reference buffer.");
+
+            TestDelegate otherArgumentWithAllParametersNullException = () => testArray.Xor(0, nullArray, 0, testArray.Length);
+            Assert.Throws<ArgumentNullException>(otherArgumentWithAllParametersNullException, "Calling all parameters overload with a null-reference other argument.");
+            Assert.That(testArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0x08, 0x00, 0xff }), "Assuring that the array is still unmodified.");
+
+            TestDelegate bufferLengthArgumentOutOfRangeException = () => testArray.Xor(1, testArray, 0, testArray.Length);
+            Assert.Throws<ArgumentOutOfRangeException>(bufferLengthArgumentOutOfRangeException, "Calling with an offset into buffer causing length to be too long.");
+            Assert.That(testArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0x08, 0x00, 0xff }), "Assuring that the array is still unmodified.");
+
+            TestDelegate otherLengthArgumentOutOfRangeException = () => testArray.Xor(0, testArray, 1, testArray.Length);
+            Assert.Throws<ArgumentOutOfRangeException>(otherLengthArgumentOutOfRangeException, "Calling with an offset into other causing length to be too long.");
+            Assert.That(testArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0x08, 0x00, 0xff }), "Assuring that the array is still unmodified.");
+
+            xorArray.Xor(2, testArray, 4, 2);
+            Assert.That(xorArray, Is.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0xf7, 0x00, 0xff }), "Xor part of the buffer with part of the other byte array.");
+
+            Assert.That(xorArray, Is.Not.EqualTo(new byte[] { 0x01, 0x02, 0x04, 0xf7, 0xff, 0xff }), "Sanity check to ensure that we're really testing what we think.");
+        }
+
+        [Test]
+        public static void TestByteArrayAppend()
+        {
+            byte[] one = new byte[] { 0x01 };
+            byte[] two = new byte[] { 0x02, 0x02 };
+            byte[] three = new byte[] { 0x03, 0x03, 0x03 };
+
+            byte[] noAppend = one.Append();
+            Assert.That(noAppend, Is.EqualTo(one), "Append with zero arrays should yield the same.");
+            Assert.IsFalse(Object.ReferenceEquals(noAppend, one), "Append with zero arrays should yield a copy, not the same instance.");
+
+            byte[] oneTwoAppend = one.Append(two);
+            Assert.That(oneTwoAppend, Is.EqualTo(new byte[] { 0x01, 0x02, 0x02 }), "Append of one with two should yield the appended result.");
+
+            byte[] oneTwoThreeAppend = one.Append(two, three);
+            Assert.That(oneTwoThreeAppend, Is.EqualTo(new byte[] { 0x01, 0x02, 0x02, 0x03, 0x03, 0x03 }), "Append of one with two and three should yield the appended result.");
+
+            byte[] oneTwoAppendThreeAppend = one.Append(two).Append(three);
+            Assert.That(oneTwoAppendThreeAppend, Is.EqualTo(new byte[] { 0x01, 0x02, 0x02, 0x03, 0x03, 0x03 }), "Append of one with two and append again three should yield the appended result (just less efficiently).");
+        }
+
+        [Test]
+        public static void TestByteArrayIsEquivalentTo()
+        {
+            byte[] one = new byte[] { 0x01 };
+            byte[] two = new byte[] { 0x02, 0x01 };
+            byte[] three = new byte[] { 0x02, 0x01, 0x03 };
+            byte[] nullArray = null;
+            bool isEquivalent = false;
+
+            Assert.Throws<ArgumentNullException>(() => { isEquivalent = nullArray.IsEquivalentTo(0, one, 0, 1); });
+            Assert.Throws<ArgumentNullException>(() => { isEquivalent = one.IsEquivalentTo(0, nullArray, 0, 1); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = one.IsEquivalentTo(one.Length, one, 0, one.Length); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = two.IsEquivalentTo(0, one, 1, one.Length); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = three.IsEquivalentTo(0, two, 0, two.Length + 1); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = three.IsEquivalentTo(-1, three, 0, three.Length); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = two.IsEquivalentTo(0, three, -1, two.Length); });
+            Assert.Throws<ArgumentOutOfRangeException>(() => { isEquivalent = one.IsEquivalentTo(0, one, 0, -1); });
+
+            isEquivalent = one.IsEquivalentTo(0, one, 0, 1);
+            Assert.IsTrue(isEquivalent, "An array should be equivalent to itself.");
+
+            isEquivalent = one.IsEquivalentTo(0, two, 1, 1);
+            Assert.IsTrue(isEquivalent, "'one' should be equivalent to second byte of 'two'.");
+
+            isEquivalent = three.IsEquivalentTo(1, one, 0, 1);
+            Assert.IsTrue(isEquivalent, "the second byte of 'three' should be equivalent to 'one'");
+
+            isEquivalent = two.IsEquivalentTo(0, three, 1, two.Length);
+            Assert.IsFalse(isEquivalent, "'two' should not be equivalent to 'three' with offset one.");
+
+            Assert.Throws<ArgumentNullException>(() => { isEquivalent = nullArray.IsEquivalentTo(one); });
+            Assert.Throws<ArgumentNullException>(() => { isEquivalent = one.IsEquivalentTo(nullArray); });
+
+            byte[] threeAgain = new byte[] { 0x02, 0x01, 0x03 };
+            isEquivalent = threeAgain.IsEquivalentTo(three);
+            Assert.IsTrue(isEquivalent, "'threeAgain' should be equivalent to 'three'.");
+
+            isEquivalent = threeAgain.IsEquivalentTo(two);
+            Assert.IsFalse(isEquivalent, "'threeAgain' should be not be equivalent to 'two'.");
+        }
+
+        [Test]
+        public static void TestEndianOptimization()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment(Endian.Reverse));
+            if (BitConverter.IsLittleEndian)
+            {
+                byte[] actuallyLittleEndianBytes = 0x0102030405060708L.GetBigEndianBytes();
+                Assert.That(actuallyLittleEndianBytes, Is.EqualTo(new byte[] { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }), "Getting big endian long, thinking we are big endian but in fact are not, will get us little endian bytes.");
+
+                byte[] actuallyIntLittleEndianBytes = 0x01020304.GetBigEndianBytes();
+                Assert.That(actuallyIntLittleEndianBytes, Is.EqualTo(new byte[] { 0x04, 0x03, 0x02, 0x01 }), "Getting big endian int, thinking we are big endian but in fact are not, will get us little endian bytes.");
+
+                byte[] actuallyStillLittleEndianBytes = 0x0102030405060708L.GetLittleEndianBytes();
+                Assert.That(actuallyStillLittleEndianBytes, Is.EqualTo(new byte[] { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }), "Getting little endian long, thinking we are big endian but in fact are not, will still get us little endian.");
+
+                byte[] actuallyIntStillLittleEndianBytes = 0x01020304.GetLittleEndianBytes();
+                Assert.That(actuallyIntStillLittleEndianBytes, Is.EqualTo(new byte[] { 0x04, 0x03, 0x02, 0x01 }), "Getting little endian int, thinking we are big endian but in fact are not, will still get us little endian.");
+            }
+            else
+            {
+                byte[] actuallyStillBigEndianBytes = 0x0102030405060708L.GetBigEndianBytes();
+                Assert.That(actuallyStillBigEndianBytes, Is.EqualTo(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }), "Getting big endian long, thinking we are little endian but in fact are not, will still get us big endian bytes.");
+
+                byte[] actuallyIntStillBigEndianBytes = 0x01020304.GetBigEndianBytes();
+                Assert.That(actuallyIntStillBigEndianBytes, Is.EqualTo(new byte[] { 0x01, 0x02, 0x03, 0x04 }), "Getting big endian int, thinking we are little endian but in fact are not, will still get us big endian bytes.");
+
+                byte[] actuallyBigEndianBytes = 0x0102030405060708L.GetLittleEndianBytes();
+                Assert.That(actuallyBigEndianBytes, Is.EqualTo(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }), "Getting little endian long, thinking we are big endian but in fact are not, will get us big endian bytes.");
+
+                byte[] actuallyIntBigEndianBytes = 0x01020304.GetLittleEndianBytes();
+                Assert.That(actuallyIntBigEndianBytes, Is.EqualTo(new byte[] { 0x01, 0x02, 0x03, 0x04 }), "Getting little endian int, thinking we are big endian but in fact are not, will get us big endian bytes.");
+            }
+        }
+
+        [Test]
+        public static void TestEndianConversion()
+        {
+            byte[] actuallyLittleEndianBytes = 0x0102030405060708L.GetBigEndianBytes();
+            Assert.That(actuallyLittleEndianBytes, Is.EqualTo(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }), "Getting big endian long.");
+
+            byte[] actuallyStillLittleEndianBytes = 0x0102030405060708L.GetLittleEndianBytes();
+            Assert.That(actuallyStillLittleEndianBytes, Is.EqualTo(new byte[] { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }), "Getting little endian long.");
+
+            byte[] actuallyIntStillLittleEndianBytes = 0x01020304.GetLittleEndianBytes();
+            Assert.That(actuallyIntStillLittleEndianBytes, Is.EqualTo(new byte[] { 0x04, 0x03, 0x02, 0x01 }), "Getting little endian int.");
+        }
+
+        [Test]
+        public static void TestCreateEncryptedName()
+        {
+            string rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+            string fileName = rootPath.PathCombine("Users", "Axantum", "A Documents Folder", "My Document.docx");
+            string encryptedFileName = Factory.New<IRuntimeFileInfo>(fileName).CreateEncryptedName().FullName;
+            Assert.That(encryptedFileName, Is.EqualTo(rootPath.PathCombine("Users", "Axantum", "A Documents Folder", "My Document-docx.axx")), "Standard conversion of file name to encrypted form.");
+
+            Assert.Throws<InternalErrorException>(() =>
+                 {
+                     string encryptedEncryptedFileName = Factory.New<IRuntimeFileInfo>(encryptedFileName).CreateEncryptedName().FullName;
+
+                     // Use the instance to avoid FxCop errors.
+                     Object.Equals(encryptedEncryptedFileName, null);
+                 });
+
+            fileName = rootPath.PathCombine("Users", "Axantum", "A Documents Folder", "My Extensionless File");
+            encryptedFileName = Factory.New<IRuntimeFileInfo>(fileName).CreateEncryptedName().FullName;
+            Assert.That(encryptedFileName, Is.EqualTo(rootPath.PathCombine("Users", "Axantum", "A Documents Folder", "My Extensionless File.axx")), "Conversion of file name without extension to encrypted form.");
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                string encryptedEncryptedFileName = Factory.New<IRuntimeFileInfo>(encryptedFileName).CreateEncryptedName().FullName;
+
+                // Use the instance to avoid FxCop errors.
+                Object.Equals(encryptedEncryptedFileName, null);
+            });
+        }
+
+        [Test]
+        public static void TestTrimLogMessage()
+        {
+            string trimmed, untrimmed;
+
+            untrimmed = "This text should not be trimmed.";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo(untrimmed), "The text does not contain anything that should be trimmed.");
+
+            untrimmed = "Information: Should not be trimmed.";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo(untrimmed), "The text does not contain anything that should be trimmed.");
+
+            untrimmed = "blah blah Warning - should be trimmed!";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo("Warning - should be trimmed!"), "The text should be trimmed at the start.");
+
+            untrimmed = " Warning - should be trimmed!";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo("Warning - should be trimmed!"), "The text should be trimmed at the start, even just a single space.");
+
+            untrimmed = "18:30 Debug - should be trimmed!";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo("Debug - should be trimmed!"), "The text should be trimmed at the start.");
+
+            untrimmed = "Information Error Error - should be trimmed!";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo("Error Error - should be trimmed!"), "The text should be trimmed at the start, but only to the first occurrence.");
+
+            untrimmed = "Prefix Fatal";
+            trimmed = untrimmed.TrimLogMessage();
+            Assert.That(trimmed, Is.EqualTo("Fatal"), "The text should be trimmed at the start.");
+        }
+
+        [Test]
+        public static void TestCopyToArgumentExceptions()
+        {
+            Stream nullStream = null;
+            using (Stream stream = new MemoryStream())
+            {
+                Assert.Throws<ArgumentNullException>(() => { StreamExtensions.CopyTo(nullStream, stream, 100); });
+                Assert.Throws<ArgumentNullException>(() => { StreamExtensions.CopyTo(stream, nullStream, 100); });
+                Assert.Throws<ArgumentOutOfRangeException>(() => { StreamExtensions.CopyTo(stream, stream, 0); });
+                Assert.Throws<ArgumentOutOfRangeException>(() => { StreamExtensions.CopyTo(stream, stream, -1); });
+            }
+        }
+
+        [Test]
+        public static void TestCreateUniqueFileFirstIsOk()
+        {
+            string unique = @"C:\temp\test.txt".CreateUniqueFile();
+            Assert.That(unique, Is.EqualTo(@"C:\temp\test.txt".NormalizeFilePath()));
+        }
+
+        [Test]
+        public static void TestCreateUniqueFileFirstIsNotOk()
+        {
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(@"C:\temp\test.txt");
+            using (Stream stream = fileInfo.OpenWrite())
+            {
+            }
+            string unique = @"C:\temp\test.txt".CreateUniqueFile();
+            Assert.That(unique, Is.EqualTo(@"C:\temp\test.1.txt".NormalizeFilePath()));
+        }
+
+        [Test]
+        public static void TestCreateUniqueFileReallyCreates()
+        {
+            string unique = @"C:\temp\test.txt".CreateUniqueFile();
+            Assert.That(unique, Is.EqualTo(@"C:\temp\test.txt".NormalizeFilePath()));
+
+            unique = @"C:\temp\test.txt".CreateUniqueFile();
+            Assert.That(unique, Is.EqualTo(@"C:\temp\test.1.txt".NormalizeFilePath()));
+        }
+
+        [Test]
+        public static void TestCreateUniqueFileUnexpectedAxCryptException()
+        {
+            EventHandler handler = delegate(object sender, EventArgs e)
+            {
+                if (((FakeRuntimeFileInfo)sender).TestTag == "CreateNewFile")
+                {
+                    throw new InternalErrorException("An unexpected exception.", ErrorStatus.InternalError);
+                }
+            };
+            FakeRuntimeFileInfo.ExceptionHook += handler;
+            Assert.Throws<InternalErrorException>(() => @"C:\temp\test.txt".CreateUniqueFile());
+            FakeRuntimeFileInfo.ExceptionHook -= handler;
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "TestIs")]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Encryptable")]
+        public static void TestIsEncryptable()
+        {
+            OS.PathFilters.Add(new Regex(@"^C:\{0}Windows\{0}(?!Temp$)".InvariantFormat(Path.DirectorySeparatorChar)));
+
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Temp\test.txt").IsEncryptable(), Is.True);
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Windows\test.txt").IsEncryptable(), Is.False);
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Temp\test-txt.axx").IsEncryptable(), Is.False);
+
+            IRuntimeFileInfo nullFileInfo = null;
+            Assert.Throws<ArgumentNullException>(() => nullFileInfo.IsEncryptable());
+        }
+
+        [Test]
+        public static void TestNormalizeFolder()
+        {
+            IRuntimeFileInfo nullFileInfo = null;
+            Assert.Throws<ArgumentNullException>(() => nullFileInfo.NormalizeFolder());
+            Assert.Throws<ArgumentException>(() => Factory.New<IRuntimeFileInfo>(String.Empty).NormalizeFolder());
+
+            string expected = @"C:\Documents\".Replace('\\', Path.DirectorySeparatorChar);
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Documents\").NormalizeFolder().FullName, Is.EqualTo(expected));
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:/Documents\").NormalizeFolder().FullName, Is.EqualTo(expected));
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Documents").NormalizeFolder().FullName, Is.EqualTo(expected));
+            Assert.That(Factory.New<IRuntimeFileInfo>(@"C:\Documents\\//").NormalizeFolder().FullName, Is.EqualTo(expected));
+        }
+
+        [Test]
+        public static void TestFolderFromEnvironment()
+        {
+            string nullString = null;
+            Assert.Throws<ArgumentNullException>(() => nullString.FolderFromEnvironment());
+
+            string expected = @"C:\Windows\".Replace('\\', Path.DirectorySeparatorChar);
+
+            SetupAssembly.FakeRuntimeEnvironment.EnvironmentVariables.Add("VARIABLE", expected);
+
+            Assert.That("VARIABLE".FolderFromEnvironment(), Is.EqualTo(expected));
+            Assert.That("UNKNOWN".FolderFromEnvironment(), Is.EqualTo(String.Empty));
+        }
+
+        [Test]
+        public static void TestFallbackExtension()
+        {
+            Assert.That(default(int).Fallback<int>(2), Is.EqualTo(2));
+            Assert.That(3.Fallback<int>(3), Is.EqualTo(3));
+        }
+
+        [Test]
+        public static void TestFileInfoTypeExtension()
+        {
+            FakeRuntimeFileInfo.AddFile(@"c:\test.txt", null);
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(@"c:\test.txt");
+            Assert.That(fileInfo.Type(), Is.EqualTo(FileInfoTypes.EncryptableFile));
+
+            FakeRuntimeFileInfo.AddFile(@"c:\test-txt.axx", null);
+            fileInfo = Factory.New<IRuntimeFileInfo>(@"c:\test-txt.axx");
+            Assert.That(fileInfo.Type(), Is.EqualTo(FileInfoTypes.EncryptedFile));
+
+            FakeRuntimeFileInfo.AddFolder(@"c:\test\");
+            fileInfo = Factory.New<IRuntimeFileInfo>(@"c:\test\");
+            Assert.That(fileInfo.Type(), Is.EqualTo(FileInfoTypes.Folder));
+
+            fileInfo = Factory.New<IRuntimeFileInfo>(@"c:\not-there.txt");
+            Assert.That(fileInfo.Type(), Is.EqualTo(FileInfoTypes.NonExisting));
+
+            OS.PathFilters.Add(new Regex(@"^C:\{0}Windows\{0}".InvariantFormat(Path.DirectorySeparatorChar)));
+            FakeRuntimeFileInfo.AddFile(@"C:\Windows\System.drv", null);
+            fileInfo = Factory.New<IRuntimeFileInfo>(@"C:\Windows\System.drv");
+            Assert.That(fileInfo.Type(), Is.EqualTo(FileInfoTypes.OtherFile));
+        }
+
+        [Test]
+        public static void TestReduceByteArrayTooShort()
+        {
+            byte[] big = new byte[5];
+            byte[] reduced = null;
+
+            Assert.Throws<ArgumentException>(() => reduced = big.Reduce(6));
+            Assert.That(reduced, Is.Null);
+        }
+
+        [Test]
+        public static void TestFromHexBadArguments()
+        {
+            string nullString = null;
+            Assert.Throws<ArgumentNullException>(() => nullString.FromHex());
+
+            Assert.Throws<ArgumentException>(() => "01A".FromHex());
+        }
+
+        [Test]
+        public static void TestCopyToWithBufferSize()
+        {
+            using (Stream input = new MemoryStream())
+            {
+                input.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+                input.Position = 0;
+                using (MemoryStream output = new MemoryStream())
+                {
+                    StreamExtensions.CopyTo(input, output, 2);
+
+                    byte[] copy = output.ToArray();
+                    Assert.That(copy.IsEquivalentTo(new byte[] { 1, 2, 3, 4 }));
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptToBadArgumentsCausingEarlyException()
+        {
+            Stream nullStream = null;
+            ICryptoTransform nullEncryptor = null;
+            ICryptoTransform encryptor = new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0).CreateDecryptingTransform();
+
+            Assert.Throws<ArgumentNullException>(() => nullStream.DecryptTo(Stream.Null, encryptor, true));
+            Assert.Throws<ArgumentNullException>(() => Stream.Null.DecryptTo(nullStream, encryptor, true));
+            Assert.Throws<ArgumentNullException>(() => Stream.Null.DecryptTo(Stream.Null, nullEncryptor, true));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFactoryRegistry.cs b/Axantum.AxCrypt.Core.Test/TestFactoryRegistry.cs
new file mode 100644
index 0000000..27a3fb3
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFactoryRegistry.cs
@@ -0,0 +1,130 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFactoryRegistry
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestRegisterParameterless()
+        {
+            bool wasCalled = false;
+            Factory.Instance.Register<int>(() => { wasCalled = true; return 13; });
+
+            int value = Factory.New<int>();
+            Assert.That(value, Is.EqualTo(13));
+            Assert.That(wasCalled, Is.True);
+        }
+
+        [Test]
+        public static void TestRegisterWithParameter()
+        {
+            bool wasCalled = false;
+            Factory.Instance.Register<int, int>((argument) => { wasCalled = true; return argument; });
+
+            int value = Factory.New<int, int>(27);
+            Assert.That(value, Is.EqualTo(27));
+            Assert.That(wasCalled, Is.True);
+        }
+
+        [Test]
+        public static void TestDefault()
+        {
+            AxCryptFile axCryptFile = Factory.New<AxCryptFile>();
+            Assert.That(axCryptFile is AxCryptFile, Is.True);
+
+            Factory.Instance.Register<FileSystemState>(() => new FileSystemState());
+            ActiveFileAction actions = Factory.New<ActiveFileAction>();
+            Assert.That(actions is ActiveFileAction, Is.True);
+        }
+
+        [Test]
+        public static void TestNotRegistered()
+        {
+            Assert.Throws<ArgumentException>(() => Factory.New<int>());
+            Assert.Throws<ArgumentException>(() => Factory.New<int, int>(13));
+        }
+
+        [Test]
+        public static void TestNotRegisteredSingleton()
+        {
+            Assert.Throws<ArgumentException>(() => Factory.Instance.Singleton<object>());
+        }
+
+        private class MyDisposable : IDisposable
+        {
+            public bool IsDisposed { get; set; }
+
+            public void Dispose()
+            {
+                IsDisposed = true;
+            }
+        }
+
+        [Test]
+        public static void TestClearDisposable()
+        {
+            Factory.Instance.Singleton(() => new MyDisposable());
+
+            MyDisposable md = Factory.Instance.Singleton<MyDisposable>();
+            Assert.That(md.IsDisposed, Is.False);
+
+            Factory.Instance.Clear();
+            Assert.That(md.IsDisposed, Is.True);
+        }
+
+        [Test]
+        public static void TestSetDisposableSingletonTwice()
+        {
+            Factory.Instance.Singleton(() => new MyDisposable());
+
+            MyDisposable md = Factory.Instance.Singleton<MyDisposable>();
+            Assert.That(md.IsDisposed, Is.False);
+
+            Factory.Instance.Singleton(() => new MyDisposable());
+            Assert.That(md.IsDisposed, Is.True);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestFileInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..415505d
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,71 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileInfoEncryptedHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestNonUtcFileTimes()
+        {
+            FileInfoEncryptedHeaderBlock fileInfoHeaderBlock = new FileInfoEncryptedHeaderBlock(new V1AesCrypto(new V1Aes128CryptoFactory(), new V1DerivedKey(new Passphrase("nonutc")).DerivedKey, SymmetricIV.Zero128));
+
+            DateTime utcNow = OS.Current.UtcNow;
+            DateTime localNow = utcNow.ToLocalTime();
+
+            fileInfoHeaderBlock.CreationTimeUtc = localNow;
+            Assert.That(fileInfoHeaderBlock.CreationTimeUtc.Kind, Is.EqualTo(DateTimeKind.Utc), "The local time should be converted to UTC by the setter.");
+            Assert.That(fileInfoHeaderBlock.CreationTimeUtc, Is.EqualTo(utcNow), "The setter should have set the time to value of local time converted to UTC.");
+
+            fileInfoHeaderBlock.LastAccessTimeUtc = localNow;
+            Assert.That(fileInfoHeaderBlock.LastAccessTimeUtc.Kind, Is.EqualTo(DateTimeKind.Utc), "The local time should be converted to UTC by the setter.");
+            Assert.That(fileInfoHeaderBlock.LastAccessTimeUtc, Is.EqualTo(utcNow), "The setter should have set the time to value of local time converted to UTC.");
+
+            fileInfoHeaderBlock.LastWriteTimeUtc = localNow;
+            Assert.That(fileInfoHeaderBlock.LastWriteTimeUtc.Kind, Is.EqualTo(DateTimeKind.Utc), "The local time should be converted to UTC by the setter.");
+            Assert.That(fileInfoHeaderBlock.LastWriteTimeUtc, Is.EqualTo(utcNow), "The setter should have set the time to value of local time converted to UTC.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileLock.cs b/Axantum.AxCrypt.Core.Test/TestFileLock.cs
new file mode 100644
index 0000000..5517fcd
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileLock.cs
@@ -0,0 +1,124 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.IO;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileLock
+    {
+        private static readonly string _fileExtPath = Path.Combine(Path.GetPathRoot(Environment.CurrentDirectory), "file.ext");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestFileLockInvalidArguments()
+        {
+            IRuntimeFileInfo nullInfo = null;
+            Assert.Throws<ArgumentNullException>(() => { FileLock.Lock(nullInfo); });
+            Assert.Throws<ArgumentNullException>(() => { FileLock.IsLocked(nullInfo); });
+            Assert.Throws<ArgumentNullException>(() => { FileLock.IsLocked(Factory.New<IRuntimeFileInfo>(_fileExtPath), nullInfo); });
+        }
+
+        [Test]
+        public static void TestFileLockMethods()
+        {
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_fileExtPath);
+
+            Assert.That(FileLock.IsLocked(fileInfo), Is.False, "There should be no lock for this file yet.");
+            using (FileLock lock1 = FileLock.Lock(fileInfo))
+            {
+                Assert.That(FileLock.IsLocked(fileInfo), Is.True, "There should be now be a lock for this file.");
+            }
+            Assert.That(FileLock.IsLocked(fileInfo), Is.False, "There should be no lock for this file again.");
+        }
+
+        [Test]
+        public static void TestFileLockWhenLocked()
+        {
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_fileExtPath);
+            Assert.That(FileLock.IsLocked(fileInfo), Is.False, "There should be no lock for this file to start with.");
+            using (FileLock lock1 = FileLock.Lock(fileInfo))
+            {
+                Assert.That(FileLock.IsLocked(fileInfo), Is.True, "There should be a lock for this file.");
+                using (FileLock lock1a = FileLock.Lock(fileInfo))
+                {
+                    Assert.That(lock1a, Is.Null, "When trying to get a lock for a locked file, this should return null.");
+                    Assert.That(FileLock.IsLocked(fileInfo), Is.True, "There should still be a lock for this file.");
+                }
+                Assert.That(FileLock.IsLocked(fileInfo), Is.True, "There should still be a lock for this file.");
+            }
+            Assert.That(FileLock.IsLocked(fileInfo), Is.False, "There should be no lock for this file now.");
+        }
+
+        [Test]
+        public static void TestFileLockCaseSensitivity()
+        {
+            IRuntimeFileInfo fileInfo1 = Factory.New<IRuntimeFileInfo>(_fileExtPath);
+            IRuntimeFileInfo fileInfo2 = Factory.New<IRuntimeFileInfo>(_fileExtPath.ToUpper(CultureInfo.InvariantCulture));
+
+            Assert.That(FileLock.IsLocked(fileInfo1), Is.False, "There should be no lock for this file yet.");
+            Assert.That(FileLock.IsLocked(fileInfo2), Is.False, "There should be no lock for this file yet.");
+            using (FileLock lock1 = FileLock.Lock(fileInfo1))
+            {
+                Assert.That(FileLock.IsLocked(fileInfo1), Is.True, "There should be now be a lock for this file.");
+                Assert.That(FileLock.IsLocked(fileInfo2), Is.False, "There should be no lock for this file still.");
+            }
+            Assert.That(FileLock.IsLocked(fileInfo1), Is.False, "There should be no lock for this file again.");
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestFileLockDoubleDispose()
+        {
+            Assert.DoesNotThrow(() =>
+            {
+                using (FileLock aLock = FileLock.Lock(Factory.New<IRuntimeFileInfo>(_fileExtPath)))
+                {
+                    aLock.Dispose();
+                }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestFileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..eac1cf1
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,85 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileNameInfoEncryptedHeaderBlock
+    {
+        private class FileNameInfoHeaderBlockForTest : V1FileNameInfoEncryptedHeaderBlock
+        {
+            public FileNameInfoHeaderBlockForTest()
+                : base(new V1AesCrypto(new V1Aes128CryptoFactory(), SymmetricKey.Zero128, SymmetricIV.Zero128))
+            {
+            }
+
+            public void SetBadNameWithoutEndingNul()
+            {
+                byte[] rawFileName = Encoding.ASCII.GetBytes("ABCDEFGHIJK.LMNO");
+                byte[] dataBlock = new byte[16];
+                rawFileName.CopyTo(dataBlock, 0);
+                SetDataBlockBytesReference(HeaderCrypto.Encrypt(dataBlock));
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestNonTerminatingFileName()
+        {
+            FileNameInfoHeaderBlockForTest fileInfoHeaderBlock = new FileNameInfoHeaderBlockForTest();
+            fileInfoHeaderBlock.HeaderCrypto = new V1AesCrypto(new V1Aes128CryptoFactory(), new V1DerivedKey(new Passphrase("nonterminating")).DerivedKey, SymmetricIV.Zero128);
+
+            fileInfoHeaderBlock.FileName = "ABCDEFGHIJK.LMN";
+            fileInfoHeaderBlock.SetBadNameWithoutEndingNul();
+
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                string fileName = fileInfoHeaderBlock.FileName;
+
+                // Avoid FxCop errors
+                Object.Equals(fileName, null);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileOperation.cs b/Axantum.AxCrypt.Core.Test/TestFileOperation.cs
new file mode 100644
index 0000000..6d0fc4c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileOperation.cs
@@ -0,0 +1,371 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileOperation
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _testTextPath = Path.Combine(_rootPath, "test.txt");
+        private static readonly string _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+        private static readonly string _uncompressedAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Uncompressed.axx");
+        private static readonly string _helloWorldAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HelloWorld.axx");
+
+        [TestFixtureSetUp]
+        public static void SetupFixture()
+        {
+        }
+
+        [TestFixtureTearDown]
+        public static void TeardownFixture()
+        {
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            FakeRuntimeFileInfo.AddFile(_testTextPath, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("This is a short file")));
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            string file = _helloWorldAxxPath;
+            string nullFile = null;
+
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+            IEnumerable<Passphrase> nullKeys = null;
+
+            ProgressContext context = new ProgressContext();
+            ProgressContext nullContext = null;
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(nullFile, keys, context); }, "The file string is null.");
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(file, nullKeys, context); }, "The keys are null.");
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(file, keys, nullContext); }, "The context is null.");
+        }
+
+        [Test]
+        public static void TestSimpleOpenAndLaunch()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            var mock = new Mock<FakeRuntimeEnvironment>() { CallBase = true };
+            string launcherPath = null;
+            mock.Setup(x => x.Launch(It.IsAny<string>())).Callback((string path) => launcherPath = path).Returns((string path) => new FakeLauncher(path));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => mock.Object);
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+            Assert.DoesNotThrow(() => mock.Verify(x => x.Launch(launcherPath)));
+        }
+
+        [Test]
+        public static void TestOpenAndLaunchOfAxCryptDocument()
+        {
+            FakeLauncher launcher = null;
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                return launcher;
+            });
+
+            FileOperationContext status;
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            using (IAxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (Stream stream = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath).OpenRead())
+                {
+                    document.Load(new Passphrase("a"), V1Aes128CryptoFactory.CryptoId, stream);
+                    status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, new Passphrase("a"), document, new ProgressContext());
+                }
+            }
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+        }
+
+        [Test]
+        public static void TestOpenAndLaunchOfAxCryptDocumentWhenAlreadyDecrypted()
+        {
+            TestOpenAndLaunchOfAxCryptDocument();
+
+            FakeLauncher launcher = null;
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                return launcher;
+            });
+
+            FileOperationContext status;
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            using (IAxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (Stream stream = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath).OpenRead())
+                {
+                    document.Load(new Passphrase("a"), V1Aes128CryptoFactory.CryptoId, stream);
+                    status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, new Passphrase("a"), document, new ProgressContext());
+                }
+            }
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+        }
+
+        [Test]
+        public static void TestOpenAndLaunchOfAxCryptDocumentArgumentNullException()
+        {
+            string nullString = null;
+            IAxCryptDocument nullDocument = null;
+            ProgressContext nullProgressContext = null;
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(nullString, Passphrase.Empty, new V1AxCryptDocument(), new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, Passphrase.Empty, nullDocument, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, Passphrase.Empty, new V1AxCryptDocument(), nullProgressContext); });
+        }
+
+        [Test]
+        public static void TestFileDoesNotExist()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_rootPath.PathCombine("Documents", "HelloWorld-NotThere.axx"), keys, new ProgressContext());
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.FileDoesNotExist), "The launch should fail with status FileDoesNotExist.");
+        }
+
+        [Test]
+        public static void TestFileAlreadyDecryptedWithKnownKey()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile destinationActiveFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.Not.EqualTo(utcNow), "The decryption should restore the time stamp of the original file, and this is not now.");
+            destinationActiveFile.DecryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);
+            status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed this time too.");
+            destinationActiveFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(utcNow), "There should be no decryption again necessary, and thus the time stamp should be as just set.");
+        }
+
+        [Test]
+        public static void TestFileAlreadyDecryptedButWithUnknownKey()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile destinationActiveFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.Not.EqualTo(utcNow), "The decryption should restore the time stamp of the original file, and this is not now.");
+            destinationActiveFile.DecryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);
+
+            IEnumerable<Passphrase> badKeys = new Passphrase[] { new Passphrase("b") };
+
+            status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, badKeys, new ProgressContext());
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.InvalidKey), "The launch should fail this time, since the key is not known.");
+            destinationActiveFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            Assert.That(destinationActiveFile.DecryptedFileInfo.LastWriteTimeUtc, Is.EqualTo(utcNow), "There should be no decryption, and thus the time stamp should be as just set.");
+        }
+
+        [Test]
+        public static void TestInvalidKey()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("b") };
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.InvalidKey), "The key is invalid, so the launch should fail with that status.");
+        }
+
+        [Test]
+        public static void TestNoProcessLaunched()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            FakeLauncher launcher = null;
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                launcher.WasStarted = false;
+                return launcher;
+            });
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed even if no process was actually launched.");
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch to try launching.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+        }
+
+        [Test]
+        public static void TestWin32Exception()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                throw new Win32Exception("Fake Win32Exception from Unit Test.");
+            });
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.CannotStartApplication), "The launch should fail since the launch throws a Win32Exception.");
+        }
+
+        [Test]
+        public static void TestImmediateExit()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            FakeLauncher launcher = null;
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                launcher.WasStarted = true;
+                launcher.HasExited = true;
+                return launcher;
+            });
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed even if the process exits immediately.");
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch to try launching.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+        }
+
+        [Test]
+        public static void TestExitEvent()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            FakeLauncher launcher = null;
+            SetupAssembly.FakeRuntimeEnvironment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                launcher.WasStarted = true;
+                return launcher;
+            });
+
+            SessionNotify notificationMonitor = new SessionNotify();
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, notificationMonitor);
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch to try launching.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+
+            bool changedWasRaised = false;
+
+            notificationMonitor.Notification += (object sender, SessionNotificationEventArgs e) => { changedWasRaised = true; };
+            Assert.That(changedWasRaised, Is.False, "The global changed event should not have been raised yet.");
+
+            launcher.RaiseExited();
+            Assert.That(changedWasRaised, Is.True, "The global changed event should be raised when the process exits.");
+        }
+
+        [Test]
+        public static void TestFileContainedByActiveFilesButNotDecrypted()
+        {
+            IEnumerable<Passphrase> keys = new Passphrase[] { new Passphrase("a") };
+
+            FileOperation fileOperation = new FileOperation(Instance.FileSystemState, new SessionNotify());
+            FileOperationContext status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should succeed.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            ActiveFile destinationActiveFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            destinationActiveFile.DecryptedFileInfo.Delete();
+            destinationActiveFile = new ActiveFile(destinationActiveFile, ActiveFileStatus.NotDecrypted);
+            Instance.FileSystemState.Add(destinationActiveFile);
+            Instance.FileSystemState.Save();
+
+            status = fileOperation.OpenAndLaunchApplication(_helloWorldAxxPath, keys, new ProgressContext());
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The launch should once again succeed.");
+        }
+
+        [Test]
+        public static void TestGetTemporaryDestinationName()
+        {
+            string temporaryDestinationName = FileOperation.GetTemporaryDestinationName(_davidCopperfieldTxtPath);
+
+            Assert.That(temporaryDestinationName.StartsWith(Path.GetDirectoryName(Factory.Instance.Singleton<WorkFolder>().FileInfo.FullName), StringComparison.OrdinalIgnoreCase), "The temporary destination should be in the temporary directory.");
+            Assert.That(Path.GetFileName(temporaryDestinationName), Is.EqualTo(Path.GetFileName(_davidCopperfieldTxtPath)), "The temporary destination should have the same file name.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileOperationViewModel.cs b/Axantum.AxCrypt.Core.Test/TestFileOperationViewModel.cs
new file mode 100644
index 0000000..1004c3f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileOperationViewModel.cs
@@ -0,0 +1,932 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileOperationViewModel
+    {
+        private static bool _allCompleted;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            var mockParallelFile = new Mock<ParallelFileOperation>();
+            _allCompleted = false;
+            mockParallelFile.Setup(x => x.DoFiles(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()))
+                .Callback<IEnumerable<IRuntimeFileInfo>, Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>, Action<FileOperationContext>>((files, work, allComplete) => { allComplete(new FileOperationContext(String.Empty, FileOperationStatus.Success)); _allCompleted = true; });
+            Factory.Instance.Singleton<ParallelFileOperation>(() => mockParallelFile.Object);
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAddRecentFiles()
+        {
+            string file1 = @"C:\Folder\File3-txt.axx";
+            string decrypted1 = @"C:\Folder\File2.txt";
+            string file2 = @"C:\Folder\File2-txt.axx";
+            string decrypted2 = @"C:\Folder\File1.txt";
+
+            FakeRuntimeFileInfo.AddFile(file1, null);
+            FakeRuntimeFileInfo.AddFile(file2, null);
+            FakeRuntimeFileInfo.AddFile(decrypted1, null);
+            FakeRuntimeFileInfo.AddFile(decrypted2, null);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("asdf"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+            mvm.AddRecentFiles.Execute(new string[] { file1, file2, decrypted1 });
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+        }
+
+        [Test]
+        public static void TestDecryptFilesInteractively()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.axx");
+                e.SelectedFiles.Add(@"C:\Folder\File2.axx");
+            };
+            mvm.DecryptFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestDecryptFilesWithCancel()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.DecryptFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestDecryptFilesWithList()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.axx");
+                e.SelectedFiles.Add(@"C:\Folder\File2.axx");
+            };
+
+            mvm.DecryptFiles.Execute(new string[] { @"C:\Folder\File3.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestEncryptFilesInteractively()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.txt");
+                e.SelectedFiles.Add(@"C:\Folder\File2.txt");
+            };
+
+            mvm.EncryptFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestEncryptFilesWithCancel()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.EncryptFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestEncryptFilesWithList()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.txt");
+                e.SelectedFiles.Add(@"C:\Folder\File2.txt");
+            };
+
+            mvm.EncryptFiles.Execute(new string[] { @"C:\Folder\File3.txt" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestOpenFilesWithList()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.OpenFiles.Execute(new string[] { @"C:\Folder\File3.txt" });
+            Assert.That(_allCompleted, Is.True);
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOn()
+        {
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("logonwhenloggedon"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOffAndIdentityKnown()
+        {
+            Passphrase passphrase = new Passphrase("a");
+
+            PassphraseIdentity identity = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(identity);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id; ;
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+
+            mvm.IdentityViewModel.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1), "There should be one known key now.");
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True, "It should be logged on now.");
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOffAndNoIdentityKnown()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "b";
+                e.Name = "Name";
+            };
+            mvm.IdentityViewModel.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1));
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+            Assert.That(Instance.FileSystemState.Identities.Count, Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOffAndNoIdentityKnownAndNoPassphraseGiven()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = String.Empty;
+            };
+
+            mvm.IdentityViewModel.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(0));
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False);
+            Assert.That(Instance.FileSystemState.Identities.Count, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestDecryptFoldersWhenLoggedIn()
+        {
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("a"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.DecryptFolders.Execute(new string[] { @"C:\Folder\" });
+
+            Assert.That(_allCompleted, Is.True);
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestDecryptFoldersWhenNotLoggedIn()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            Assert.Throws<InvalidOperationException>(() => mvm.DecryptFolders.Execute(new string[] { @"C:\Folder\" }));
+        }
+
+        [Test]
+        public static void TestWipeFilesInteractively()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.txt");
+                e.SelectedFiles.Add(@"C:\Folder\File2.txt");
+            };
+
+            mvm.WipeFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestWipeFilesWithCancel()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.WipeFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestWipeFilesWithList()
+        {
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.txt");
+                e.SelectedFiles.Add(@"C:\Folder\File2.txt");
+            };
+
+            mvm.WipeFiles.Execute(new string[] { @"C:\Folder\File3.txt" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+        }
+
+        [Test]
+        public static void TestOpenFilesFromFolderWithCancelWhenLoggedOn()
+        {
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("b");
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.OpenFilesFromFolder.Execute(@"C:\Folder\");
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestOpenFilesFromFolderWhenLoggedOn()
+        {
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("c");
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Clear();
+                e.SelectedFiles.Add(@"C:\Folder\File1.axx");
+                e.SelectedFiles.Add(@"C:\Folder\File2.axx");
+            };
+
+            mvm.OpenFilesFromFolder.Execute(@"C:\Folder\");
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(files => files.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+        }
+
+        [Test]
+        public static void TestEncryptFilesAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1.txt");
+                e.SelectedFiles.Add(@"C:\Folder\File2.txt");
+            };
+
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            mvm.EncryptFiles.Execute(null);
+
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File1-txt.axx"), Is.Not.Null);
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File2-txt.axx"), Is.Not.Null);
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Exactly(2));
+        }
+
+        [Test]
+        public static void TestEncryptFilesWithSaveAsAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\Copy of File1-txt.axx");
+            };
+
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            mvm.EncryptFiles.Execute(new string[] { @"C:\Folder\File1.txt" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Exactly(1));
+        }
+
+        [Test]
+        public static void TestEncryptFilesWithAlreadyEncryptedFile()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+
+            mvm.EncryptFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestEncryptFilesWithCanceledLoggingOnAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.EncryptFiles.Execute(new string[] { @"C:\Folder\File1.txt" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Never);
+        }
+
+        [Test]
+        public static void TestDecryptFileAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 117);
+                acd.PassphraseIsValid = true;
+                acd.FileName = fileInfo.FullName.Replace("-txt.axx", ".txt");
+                return acd;
+            });
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase key, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(key, 117);
+                acd.PassphraseIsValid = true;
+                acd.FileName = fileInfo.FullName.Replace("-txt.axx", ".txt");
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            Mock<AxCryptFactory> axCryptFactoryMock = new Mock<AxCryptFactory>();
+            axCryptFactoryMock.Setup<Guid>(m => m.TryFindCryptoId(It.IsAny<Passphrase>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<IEnumerable<Guid>>())).Returns((Passphrase passphrase, IRuntimeFileInfo fileInfo, IEnumerable<Guid> cryptoIds) =>
+            {
+                return V1Aes128CryptoFactory.CryptoId;
+            });
+            Factory.Instance.Register<AxCryptFactory>(() => axCryptFactoryMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Add(@"C:\Folder\File1-txt.axx");
+                e.SelectedFiles.Add(@"C:\Folder\File2-txt.axx");
+            };
+
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            mvm.DecryptFiles.Execute(null);
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.DecryptFile(It.IsAny<IAxCryptDocument>(), It.IsAny<string>(), It.IsAny<IProgressContext>()), Times.Exactly(2));
+            axCryptFileMock.Verify(m => m.Wipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IProgressContext>()), Times.Exactly(2));
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestDecryptFileFileSaveAsAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 31);
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = Path.GetFileName(fileInfo.FullName.Replace("-txt.axx", ".txt"));
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.SelectedFiles.Clear();
+                e.SelectedFiles.Add(@"C:\Folder\Copy of File1.txt".NormalizeFilePath());
+            };
+
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1.txt", null);
+            mvm.DecryptFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx".NormalizeFilePath() });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.DecryptFile(It.Is<IAxCryptDocument>((a) => a.FileName == @"File1.txt"), It.Is<string>((s) => s == @"C:\Folder\Copy of File1.txt".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>((i) => i.FullName == @"C:\Folder\File1-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Once);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+        }
+
+        [Test]
+        public static void TestDecryptFileFileSaveAsCanceledAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 10);
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = Path.GetFileName(fileInfo.FullName.Replace("-txt.axx", ".txt"));
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "a";
+            };
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1.txt", null);
+            mvm.DecryptFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 0), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+            axCryptFileMock.Verify(m => m.DecryptFile(It.IsAny<IAxCryptDocument>(), It.IsAny<string>(), It.IsAny<IProgressContext>()), Times.Never);
+            axCryptFileMock.Verify(m => m.Wipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IProgressContext>()), Times.Never);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestDecryptLoggingOnCanceledAction()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            mvm.DecryptFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 0), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Never);
+            axCryptFileMock.Verify(m => m.DecryptFile(It.IsAny<IAxCryptDocument>(), It.IsAny<string>(), It.IsAny<IProgressContext>()), Times.Never);
+            axCryptFileMock.Verify(m => m.Wipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IProgressContext>()), Times.Never);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestAddRecentFilesActionAddingEncryptedWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 10);
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = Path.GetFileName(fileInfo.FullName.Replace("-txt.axx", ".txt"));
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "b";
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            mvm.AddRecentFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 1), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestAddRecentFilesActionAddingEncryptedButCancelingWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase key, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument();
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = Path.GetFileName(fileInfo.FullName.Replace("-txt.axx", ".txt"));
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            int logonTries = 0;
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+                logonTries++;
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            mvm.AddRecentFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(0));
+            Assert.That(logonTries, Is.EqualTo(1), "There should be only one logon try, since the first one cancels.");
+        }
+
+        [Test]
+        public static void TestWipeFilesWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            mvm.WipeFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IProgressContext>()), Times.Exactly(2));
+        }
+
+        [Test]
+        public static void TestWipeFilesSkippingOneWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                if (e.SelectedFiles[0].Contains("File2"))
+                {
+                    e.Skip = true;
+                }
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File3-txt.axx", null);
+            mvm.WipeFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx", @"C:\Folder\File3-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 3), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File1-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File2-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Never);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File3-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Once);
+        }
+
+        [Test]
+        public static void TestWipeFilesCancelingAfterOneWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            int callTimes = 0;
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.SelectingFiles += (sender, e) =>
+            {
+                ++callTimes;
+                if (e.SelectedFiles[0].Contains("File2"))
+                {
+                    SimulateDelayOfUserInteractionAllowingEarlierThreadsToReallyStartTheAsyncPart();
+                    e.Cancel = true;
+                }
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File3-txt.axx", null);
+            mvm.WipeFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx", @"C:\Folder\File3-txt.axx" });
+
+            Assert.That(callTimes, Is.EqualTo(2), "Only the first two calls should be made.");
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 3), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.IsAny<IRuntimeFileInfo>(), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File1-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File2-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Never);
+            axCryptFileMock.Verify(m => m.Wipe(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File3-txt.axx".NormalizeFilePath()), It.IsAny<IProgressContext>()), Times.Never);
+        }
+
+        private static void SimulateDelayOfUserInteractionAllowingEarlierThreadsToReallyStartTheAsyncPart()
+        {
+            Thread.Sleep(1);
+        }
+
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Encryptable", Justification = "Encryptable *is* a word.")]
+        [Test]
+        public static void TestAddRecentFilesActionWithEncryptableFilesNonInteractive()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("d"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File3-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1.txt", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2.txt", null);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.AddRecentFiles.Execute(new string[] { @"C:\Folder\File1.txt", @"C:\Folder\File2.txt", @"C:\Folder\File3-txt.axx" });
+
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File1-txt.axx"), Is.Null);
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File1-txt.1.axx"), Is.Not.Null);
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File2-txt.axx"), Is.Not.Null);
+            Assert.That(Instance.FileSystemState.FindActiveFileFromEncryptedPath(@"C:\Folder\File3-txt.axx"), Is.Null);
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File1-txt.1.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.EncryptFileWithBackupAndWipe(It.IsAny<IRuntimeFileInfo>(), It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder\File2-txt.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Once);
+        }
+
+        [Test]
+        public static void TestOpenFilesActionWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 87);
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = fileInfo.FullName.Replace("-txt.axx", ".txt");
+                return acd;
+            });
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase key, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(key, 87);
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = fileInfo.FullName.Replace("-txt.axx", ".txt");
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            Mock<AxCryptFactory> axCryptFactoryMock = new Mock<AxCryptFactory>();
+            axCryptFactoryMock.Setup<Guid>(m => m.TryFindCryptoId(It.IsAny<Passphrase>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<IEnumerable<Guid>>())).Returns((Passphrase passphrase, IRuntimeFileInfo fileInfo, IEnumerable<Guid> cryptoIds) =>
+            {
+                return V1Aes128CryptoFactory.CryptoId;
+            });
+            Factory.Instance.Register<AxCryptFactory>(() => axCryptFactoryMock.Object);
+
+            Mock<FileOperation> fileOperationMock = new Mock<FileOperation>(Instance.FileSystemState, Instance.SessionNotify);
+            Factory.Instance.Register<FileOperation>(() => fileOperationMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "b";
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            mvm.OpenFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            fileOperationMock.Verify(f => f.OpenAndLaunchApplication(It.Is<string>(s => s == @"C:\Folder\File1-txt.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IAxCryptDocument>(), It.IsAny<IProgressContext>()), Times.Once);
+            fileOperationMock.Verify(f => f.OpenAndLaunchApplication(It.Is<string>(s => s == @"C:\Folder\File2-txt.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IAxCryptDocument>(), It.IsAny<IProgressContext>()), Times.Once);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestOpenFilesActionCancelingWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            int count = 0;
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            axCryptFileMock.Setup<IAxCryptDocument>(m => m.Document(It.IsAny<IRuntimeFileInfo>(), It.IsAny<Passphrase>(), It.IsAny<IProgressContext>())).Returns((IRuntimeFileInfo fileInfo, Passphrase passphrase, IProgressContext progress) =>
+            {
+                V1AxCryptDocument acd = new V1AxCryptDocument(passphrase, 17);
+                count++;
+                acd.PassphraseIsValid = true;
+                acd.DocumentHeaders.FileName = fileInfo.FullName.Replace("-txt.axx", ".txt");
+                return acd;
+            });
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            Mock<FileOperation> fileOperationMock = new Mock<FileOperation>(Instance.FileSystemState, Instance.SessionNotify);
+            Factory.Instance.Register<FileOperation>(() => fileOperationMock.Object);
+
+            Mock<AxCryptFactory> axCryptFactoryMock = new Mock<AxCryptFactory>();
+            axCryptFactoryMock.Setup(acf => acf.TryFindCryptoId(It.IsAny<Passphrase>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<IEnumerable<Guid>>())).Returns((Passphrase passphrase, IRuntimeFileInfo fileInfo, IEnumerable<Guid> cryptoIds) =>
+            {
+                count++;
+                return Guid.Empty;
+            });
+            Factory.Instance.Register<AxCryptFactory>(() => axCryptFactoryMock.Object);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.IdentityViewModel.CryptoId = new V1Aes128CryptoFactory().Id;
+            mvm.IdentityViewModel.LoggingOn += (sender, e) =>
+            {
+                if (count == 2)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                e.Passphrase = "b";
+            };
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder\File2-txt.axx", null);
+            mvm.OpenFiles.Execute(new string[] { @"C:\Folder\File1-txt.axx", @"C:\Folder\File2-txt.axx" });
+
+            Mock.Get(Instance.ParallelFileOperation).Verify(x => x.DoFiles(It.Is<IEnumerable<IRuntimeFileInfo>>(f => f.Count() == 2), It.IsAny<Func<IRuntimeFileInfo, IProgressContext, FileOperationContext>>(), It.IsAny<Action<FileOperationContext>>()));
+            fileOperationMock.Verify(f => f.OpenAndLaunchApplication(It.Is<string>(s => s == @"C:\Folder\File1-txt.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IAxCryptDocument>(), It.IsAny<IProgressContext>()), Times.Once);
+            fileOperationMock.Verify(f => f.OpenAndLaunchApplication(It.Is<string>(s => s == @"C:\Folder\File2-txt.axx".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IAxCryptDocument>(), It.IsAny<IProgressContext>()), Times.Never);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True, "Should be logged on.");
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(1), "One known key.");
+        }
+
+        [Test]
+        public static void TestDecryptFoldersWithWork()
+        {
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new Mock<ParallelFileOperation>() { CallBase = true }.Object);
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+
+            Mock<AxCryptFile> axCryptFileMock = new Mock<AxCryptFile>();
+            Factory.Instance.Register<AxCryptFile>(() => axCryptFileMock.Object);
+
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("e"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder1\File1-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder1\File2-txt.axx", null);
+            FakeRuntimeFileInfo.AddFile(@"C:\Folder2\File1-txt.axx", null);
+
+            FileOperationViewModel mvm = Factory.New<FileOperationViewModel>();
+            mvm.DecryptFolders.Execute(new string[] { @"C:\Folder1\", @"C:\Folder2\" });
+
+            axCryptFileMock.Verify(m => m.DecryptFilesInsideFolderUniqueWithWipeOfOriginal(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder1\".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IStatusChecker>(), It.IsAny<IProgressContext>()), Times.Once);
+            axCryptFileMock.Verify(m => m.DecryptFilesInsideFolderUniqueWithWipeOfOriginal(It.Is<IRuntimeFileInfo>(r => r.FullName == @"C:\Folder2\".NormalizeFilePath()), It.IsAny<Passphrase>(), It.IsAny<IStatusChecker>(), It.IsAny<IProgressContext>()), Times.Once);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileOperationsController.cs b/Axantum.AxCrypt.Core.Test/TestFileOperationsController.cs
new file mode 100644
index 0000000..9e15409
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileOperationsController.cs
@@ -0,0 +1,768 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileOperationsController
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+        private static readonly string _uncompressedAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Uncompressed.axx");
+        private static readonly string _helloWorldAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HelloWorld.axx");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+
+            Factory.Instance.Singleton<IUIThread>(() => new FakeUIThread());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimpleEncryptFile()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            string destinationPath = String.Empty;
+            controller.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Passphrase = new Passphrase("allan");
+                };
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+            };
+
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After encryption the destination file should be created.");
+            using (IAxCryptDocument document = new V2AxCryptDocument())
+            {
+                using (Stream stream = destinationInfo.OpenRead())
+                {
+                    document.Load(new Passphrase("allan"), V2Aes256CryptoFactory.CryptoId, stream);
+                    Assert.That(document.PassphraseIsValid, "The encrypted document should be valid and encrypted with the passphrase given.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestSimpleEncryptFileOnThreadWorker()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("allan");
+            };
+            string destinationPath = String.Empty;
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+                status = e.Status;
+            };
+
+            controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After encryption the destination file should be created.");
+            using (IAxCryptDocument document = new V2AxCryptDocument())
+            {
+                using (Stream stream = destinationInfo.OpenRead())
+                {
+                    document.Load(new Passphrase("allan"), V2Aes256CryptoFactory.CryptoId, stream);
+                    Assert.That(document.PassphraseIsValid, "The encrypted document should be valid and encrypted with the passphrase given.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestEncryptFileWithDefaultEncryptionKey()
+        {
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new LegacyCryptoPolicy());
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("default");
+            FileOperationsController controller = new FileOperationsController();
+            bool queryEncryptionPassphraseWasCalled = false;
+            controller.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    queryEncryptionPassphraseWasCalled = true;
+                };
+            string destinationPath = String.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+                {
+                    destinationPath = e.SaveFileFullName;
+                };
+
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(!queryEncryptionPassphraseWasCalled, "No query of encryption passphrase should be needed since there is a default set.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After encryption the destination file should be created.");
+            using (IAxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (Stream stream = destinationInfo.OpenRead())
+                {
+                    document.Load(new Passphrase("default"), V1Aes128CryptoFactory.CryptoId, stream);
+                    Assert.That(document.PassphraseIsValid, "The encrypted document should be valid and encrypted with the default passphrase given.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestEncryptFileWhenDestinationExists()
+        {
+            IRuntimeFileInfo sourceInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            IRuntimeFileInfo expectedDestinationInfo = Factory.New<IRuntimeFileInfo>(AxCryptFile.MakeAxCryptFileName(sourceInfo));
+            using (Stream stream = expectedDestinationInfo.OpenWrite())
+            {
+            }
+
+            FileOperationsController controller = new FileOperationsController();
+            string destinationPath = String.Empty;
+            Passphrase key = null;
+            controller.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("allan");
+            };
+            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+            {
+                e.SaveFileFullName = Path.Combine(Path.GetDirectoryName(e.SaveFileFullName), "alternative-name.axx");
+            };
+            Guid cryptoId = Guid.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+                key = e.Passphrase;
+                cryptoId = e.CryptoId;
+            };
+
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            Assert.That(Path.GetFileName(destinationPath), Is.EqualTo("alternative-name.axx"), "The alternative name should be used, since the default existed.");
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After encryption the destination file should be created.");
+            using (IAxCryptDocument document = Factory.New<AxCryptFactory>().CreateDocument(key, cryptoId))
+            {
+                using (Stream stream = destinationInfo.OpenRead())
+                {
+                    document.Load(key, cryptoId, stream);
+                    Assert.That(document.PassphraseIsValid, "The encrypted document should be valid and encrypted with the passphrase given.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestEncryptFileWhenCanceledDuringQuerySaveAs()
+        {
+            IRuntimeFileInfo sourceInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            IRuntimeFileInfo expectedDestinationInfo = Factory.New<IRuntimeFileInfo>(AxCryptFile.MakeAxCryptFileName(sourceInfo));
+            using (Stream stream = expectedDestinationInfo.OpenWrite())
+            {
+            }
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = true;
+            };
+
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestEncryptFileWhenCanceledDuringQueryPassphrase()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryEncryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = true;
+            };
+
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestSimpleDecryptFile()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Passphrase = new Passphrase("a");
+                };
+            bool knownKeyWasAdded = false;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+                {
+                    knownKeyWasAdded = e.Passphrase.Equals(new Passphrase("a"));
+                };
+            string destinationPath = String.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+                {
+                    destinationPath = e.SaveFileFullName;
+                };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(knownKeyWasAdded, "A new known key was used, so the KnownKeyAdded event should have been raised.");
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestSimpleDecryptFileOnThreadWorker()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("a");
+            };
+            bool knownKeyWasAdded = false;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                knownKeyWasAdded = e.Passphrase.Equals(new Passphrase("a"));
+            };
+            string destinationPath = String.Empty;
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+                status = e.Status;
+            };
+
+            controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(knownKeyWasAdded, "A new known key was used, so the KnownKeyAdded event should have been raised.");
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestDecryptWithCancelDuringQueryDecryptionPassphrase()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = true;
+            };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestDecryptWithSkipDuringQueryDecryptionPassphrase()
+        {
+            IRuntimeFileInfo expectedDestinationInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));
+            using (Stream stream = expectedDestinationInfo.OpenWrite())
+            {
+            }
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Skip = true;
+            };
+            bool saveAs = false;
+            controller.QuerySaveFileAs += (sender, e) => saveAs = true;
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(saveAs, Is.False, "No Save As should happen, since skip was indicated.");
+        }
+
+        [Test]
+        public static void TestDecryptWithCancelDuringQuerySaveAs()
+        {
+            IRuntimeFileInfo expectedDestinationInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));
+            using (Stream stream = expectedDestinationInfo.OpenWrite())
+            {
+            }
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Passphrase = new Passphrase("a");
+                };
+            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Cancel = true;
+                };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestDecryptWithAlternativeDestinationName()
+        {
+            IRuntimeFileInfo expectedDestinationInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetDirectoryName(_helloWorldAxxPath), "HelloWorld-Key-a.txt"));
+            using (Stream stream = expectedDestinationInfo.OpenWrite())
+            {
+            }
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("a");
+            };
+            controller.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+            {
+                e.SaveFileFullName = Path.Combine(Path.GetDirectoryName(e.SaveFileFullName), "Other Hello World.txt");
+            };
+            string destinationPath = String.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+            };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+            Assert.That(fileContent.Contains("Hello"), "A file named 'Other Hello World.txt' should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestSimpleDecryptAndLaunch()
+        {
+            FakeLauncher launcher = null;
+            FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+            environment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                return launcher;
+            });
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("a");
+            };
+            FileOperationContext status = controller.DecryptAndLaunch(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(launcher.Path);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestSimpleDecryptAndLaunchOnThreadWorker()
+        {
+            FakeLauncher launcher = null;
+            FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+            environment.Launcher = ((string path) =>
+            {
+                launcher = new FakeLauncher(path);
+                return launcher;
+            });
+
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("a");
+            };
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                status = e.Status;
+            };
+
+            controller.DecryptAndLaunch(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            Assert.That(launcher, Is.Not.Null, "There should be a call to launch.");
+            Assert.That(Path.GetFileName(launcher.Path), Is.EqualTo("HelloWorld-Key-a.txt"), "The file should be decrypted and the name should be the original from the encrypted headers.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(launcher.Path);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestCanceledDecryptAndLaunch()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = true;
+            };
+            FileOperationContext status = controller.DecryptAndLaunch(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestDecryptWithKnownKey()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            Instance.KnownKeys.Add(new Passphrase("b"));
+            Instance.KnownKeys.Add(new Passphrase("c"));
+            Instance.KnownKeys.Add(new Passphrase("a"));
+            Instance.KnownKeys.Add(new Passphrase("e"));
+            bool passphraseWasQueried = false;
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                passphraseWasQueried = true;
+            };
+            string destinationPath = String.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+            };
+            bool knownKeyWasAdded = false;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                knownKeyWasAdded = true;
+            };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(!knownKeyWasAdded, "An already known key was used, so the KnownKeyAdded event should not have been raised.");
+            Assert.That(!passphraseWasQueried, "An already known key was used, so the there should be no need to query for a passphrase.");
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestDecryptFileWithRepeatedPassphraseQueries()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            int passphraseTry = 0;
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                switch (++passphraseTry)
+                {
+                    case 1:
+                        e.Passphrase = new Passphrase("b");
+                        break;
+
+                    case 2:
+                        e.Passphrase = new Passphrase("d");
+                        break;
+
+                    case 3:
+                        e.Passphrase = new Passphrase("a");
+                        break;
+
+                    case 4:
+                        e.Passphrase = new Passphrase("e");
+                        break;
+                };
+            };
+            string destinationPath = String.Empty;
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+            };
+            bool knownKeyWasAdded = false;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                knownKeyWasAdded = e.Passphrase.Equals(new Passphrase("a"));
+            };
+            FileOperationContext status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+            Assert.That(knownKeyWasAdded, "A new known key was used, so the KnownKeyAdded event should have been raised.");
+            Assert.That(passphraseTry, Is.EqualTo(3), "The third key was the correct one.");
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(destinationInfo.IsExistingFile, "After decryption the destination file should be created.");
+
+            string fileContent;
+            using (Stream stream = destinationInfo.OpenRead())
+            {
+                fileContent = new StreamReader(stream).ReadToEnd();
+            }
+            Assert.That(fileContent.Contains("Hello"), "A file named Hello World should contain that text when decrypted.");
+        }
+
+        [Test]
+        public static void TestDecryptFileWithExceptionBeforeStartingDecryption()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Passphrase = new Passphrase("a");
+                };
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+                {
+                    throw new FileNotFoundException("Just kidding, but we're faking...", e.OpenFileFullName);
+                };
+            string destinationPath = String.Empty;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+                {
+                    destinationPath = e.SaveFileFullName;
+                };
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            Assert.DoesNotThrow(() => { status = controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath)); });
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.FileDoesNotExist), "The status should indicate an exception occurred.");
+            Assert.That(String.IsNullOrEmpty(destinationPath), "Since an exception occurred, the destination file should not be created.");
+        }
+
+        [Test]
+        public static void TestEncryptFileThatIsAlreadyEncrypted()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            FileOperationContext status = controller.EncryptFile(Factory.New<IRuntimeFileInfo>("test" + OS.Current.AxCryptExtension));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.FileAlreadyEncrypted), "The status should indicate that it was already encrypted.");
+        }
+
+        [Test]
+        public static void TestDecryptWithCancelDuringQueryDecryptionPassphraseOnThreadWorker()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+                {
+                    e.Cancel = true;
+                };
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+                {
+                    status = e.Status;
+                };
+
+            controller.DecryptFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The status should indicate cancellation.");
+        }
+
+        [Test]
+        public static void TestSimpleWipe()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = false;
+                e.Skip = false;
+                e.ConfirmAll = false;
+            };
+            FileOperationContext status = controller.WipeFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Assert.That(!fileInfo.IsExistingFile, "The file should not exist after wiping.");
+        }
+
+        [Test]
+        public static void TestSimpleWipeOnThreadWorker()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = false;
+                e.Skip = false;
+                e.ConfirmAll = false;
+            };
+
+            string destinationPath = String.Empty;
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            controller.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                destinationPath = e.SaveFileFullName;
+                status = e.Status;
+            };
+
+            controller.WipeFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The status should indicate success.");
+
+            IRuntimeFileInfo destinationInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            Assert.That(!destinationInfo.IsExistingFile, "After wiping the destination file should not exist.");
+        }
+
+        [Test]
+        public static void TestWipeWithCancel()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Cancel = true;
+            };
+            FileOperationContext status = controller.WipeFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled), "The wipe should indicate cancellation.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Assert.That(fileInfo.IsExistingFile, "The file should still exist after wiping that was canceled during confirmation.");
+        }
+
+        [Test]
+        public static void TestWipeWithSkip()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Skip = true;
+            };
+            FileOperationContext status = controller.WipeFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success even when skipping.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Assert.That(fileInfo.IsExistingFile, "The file should still exist after wiping that was skipped during confirmation.");
+        }
+
+        [Test]
+        public static void TestWipeWithConfirmAll()
+        {
+            ProgressContext progress = new ProgressContext();
+            FileOperationsController controller = new FileOperationsController(progress);
+            int confirmationCount = 0;
+            controller.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                if (confirmationCount++ > 0)
+                {
+                    throw new InvalidOperationException("The event should not be raised a second time.");
+                }
+                e.ConfirmAll = true;
+            };
+            progress.NotifyLevelStart();
+            FileOperationContext status = controller.WipeFile(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success.");
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath);
+            Assert.That(!fileInfo.IsExistingFile, "The file should not exist after wiping.");
+
+            Assert.DoesNotThrow(() => { status = controller.WipeFile(Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath)); });
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success), "The wipe should indicate success.");
+            progress.NotifyLevelFinished();
+
+            fileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+            Assert.That(!fileInfo.IsExistingFile, "The file should not exist after wiping.");
+        }
+
+        [Test]
+        public static void TestVerifyEncrypted()
+        {
+            FileOperationsController controller = new FileOperationsController();
+            bool passphraseWasQueried = false;
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                passphraseWasQueried = true;
+                e.Cancel = true;
+            };
+            bool knownKeyWasAdded = false;
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                knownKeyWasAdded = true;
+            };
+
+            FileOperationContext status = controller.VerifyEncrypted(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Canceled));
+            Assert.That(knownKeyWasAdded, Is.False);
+            Assert.That(passphraseWasQueried, Is.True);
+
+            controller = new FileOperationsController();
+            controller.QueryDecryptionPassphrase += (object sender, FileOperationEventArgs e) =>
+            {
+                e.Passphrase = new Passphrase("a");
+            };
+            controller.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                knownKeyWasAdded = true;
+            };
+
+            Instance.KnownKeys.Add(new Passphrase("b"));
+            Instance.KnownKeys.Add(new Passphrase("c"));
+
+            status = controller.VerifyEncrypted(Factory.New<IRuntimeFileInfo>(_helloWorldAxxPath));
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Success));
+            Assert.That(knownKeyWasAdded, Is.True, "A known key should have been added.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileSystemState.cs b/Axantum.AxCrypt.Core.Test/TestFileSystemState.cs
new file mode 100644
index 0000000..100e68f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileSystemState.cs
@@ -0,0 +1,363 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileSystemState
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _encryptedAxxPath = Path.Combine(_rootPath, "Encrypted-txt.axx");
+        private static readonly string _encrypted1AxxPath = Path.Combine(_rootPath, "Encrypted1-txt.axx");
+        private static readonly string _encrypted2AxxPath = Path.Combine(_rootPath, "Encrypted2-txt.axx");
+        private static readonly string _encrypted3AxxPath = Path.Combine(_rootPath, "Encrypted3-txt.axx");
+        private static readonly string _encrypted4AxxPath = Path.Combine(_rootPath, "Encrypted4-txt.axx");
+        private static readonly string _decryptedTxtPath = Path.Combine(_rootPath, "Decrypted.txt");
+        private static readonly string _decrypted1TxtPath = Path.Combine(_rootPath, "Decrypted1.txt");
+        private static readonly string _decrypted2TxtPath = Path.Combine(_rootPath, "Decrypted2.txt");
+        private static readonly string _decrypted3TxtPath = Path.Combine(_rootPath, "Decrypted3.txt");
+        private static readonly string _decrypted4TxtPath = Path.Combine(_rootPath, "Decrypted4.txt");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestLoadNew()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(state, Is.Not.Null, "An instance should always be instantiated.");
+                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(0), "A new state should not have any active files.");
+            }
+        }
+
+        [Test]
+        public static void TestLoadExisting()
+        {
+            ActiveFile activeFile;
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(state, Is.Not.Null, "An instance should always be instantiated.");
+                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(0), "A new state should not have any active files.");
+
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+                state.Save();
+            }
+
+            using (FileSystemState reloadedState = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(reloadedState, Is.Not.Null, "An instance should always be instantiated.");
+                Assert.That(reloadedState.ActiveFiles.Count(), Is.EqualTo(1), "The reloaded state should have one active file.");
+                Assert.That(reloadedState.ActiveFiles.First().ThumbprintMatch(activeFile.Key), Is.True, "The reloaded thumbprint should  match the key.");
+            }
+        }
+
+        [Test]
+        public static void TestActiveFileChangedEvent()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                bool wasHere;
+                state.ActiveFileChanged += new EventHandler<ActiveFileChangedEventArgs>((object sender, ActiveFileChangedEventArgs e) => { wasHere = true; });
+                ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("a"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+
+                wasHere = false;
+                state.Add(activeFile);
+                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(1), "After the Add() the state should have one active file.");
+                Assert.That(wasHere, Is.True, "After the Add(), the changed event should have been raised.");
+
+                wasHere = false;
+                state.RemoveActiveFile(activeFile);
+                Assert.That(wasHere, Is.True, "After the Remove(), the changed event should have been raised.");
+                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(1), "After the Remove() the state should still have one active files.");
+                Assert.That(state.ActiveFiles.First().Status.HasFlag(ActiveFileStatus.Inactive), "But after the Remove(), the active file should have the inactive flag set.");
+            }
+        }
+
+        [Test]
+        public static void TestStatusMaskAtLoad()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+                state.Save();
+
+                FileSystemState reloadedState = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt"));
+                Assert.That(reloadedState, Is.Not.Null, "An instance should always be instantiated.");
+                Assert.That(reloadedState.ActiveFiles.Count(), Is.EqualTo(1), "The reloaded state should have one active file.");
+                Assert.That(reloadedState.ActiveFiles.First().Status, Is.EqualTo(ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NoProcessKnown), "When reloading saved state, some statuses should be masked away and NoProcessKnown added.");
+            }
+        }
+
+        [Test]
+        public static void TestFindEncryptedPath()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+
+                ActiveFile byEncryptedPath = state.FindActiveFileFromEncryptedPath(_encryptedAxxPath);
+                Assert.That(byEncryptedPath.EncryptedFileInfo.FullName, Is.EqualTo(_encryptedAxxPath), "The search should return the same path.");
+
+                ActiveFile notFoundEncrypted = state.FindActiveFileFromEncryptedPath(Path.Combine(_rootPath, "notfoundfile.txt"));
+                Assert.That(notFoundEncrypted, Is.Null, "A search that does not succeed should return null.");
+            }
+        }
+
+        [Test]
+        public static void TestForEach()
+        {
+            bool changedEventWasRaised = false;
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                state.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+                {
+                    changedEventWasRaised = true;
+                });
+
+                ActiveFile activeFile;
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted1AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted1TxtPath), new Passphrase("passphrase1"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted2AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted2TxtPath), new Passphrase("passphrase2"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted3AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted3TxtPath), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+                state.Add(activeFile);
+                Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised by the adding of active files.");
+
+                changedEventWasRaised = false;
+                Assert.That(state.ActiveFiles.Count(), Is.EqualTo(3), "There should be three.");
+                int i = 0;
+                state.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFileArgument) =>
+                {
+                    ++i;
+                    return activeFileArgument;
+                });
+                Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files.");
+                Assert.That(changedEventWasRaised, Is.False, "No change event should have been raised.");
+
+                i = 0;
+                state.ForEach(ChangedEventMode.RaiseAlways, (ActiveFile activeFileArgument) =>
+                {
+                    ++i;
+                    return activeFileArgument;
+                });
+                Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files.");
+                Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised.");
+
+                changedEventWasRaised = false;
+                i = 0;
+                state.ForEach(ChangedEventMode.RaiseAlways, (ActiveFile activeFileArgument) =>
+                {
+                    ++i;
+                    return new ActiveFile(activeFileArgument, activeFile.Status | ActiveFileStatus.Error);
+                });
+                Assert.That(i, Is.EqualTo(3), "The iteration should have visited three active files.");
+                Assert.That(changedEventWasRaised, Is.True, "The change event should have been raised.");
+            }
+        }
+
+        [Test]
+        public static void TestDecryptedActiveFiles()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                ActiveFile decryptedFile1 = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase1"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+                state.Add(decryptedFile1);
+
+                ActiveFile decryptedFile2 = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted2AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted2TxtPath), new Passphrase("passphrase2"), ActiveFileStatus.DecryptedIsPendingDelete, new V1Aes128CryptoFactory().Id);
+                state.Add(decryptedFile2);
+
+                ActiveFile notDecryptedFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted3AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted3TxtPath), new Passphrase("passphrase3"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+                state.Add(notDecryptedFile);
+
+                ActiveFile errorFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encrypted4AxxPath), Factory.New<IRuntimeFileInfo>(_decrypted4TxtPath), new Passphrase("passphrase"), ActiveFileStatus.Error, new V1Aes128CryptoFactory().Id);
+                state.Add(errorFile);
+
+                IList<ActiveFile> decryptedFiles = state.DecryptedActiveFiles;
+                Assert.That(decryptedFiles.Count, Is.EqualTo(2), "There should be two decrypted files.");
+                Assert.That(decryptedFiles.Contains(decryptedFile1), "A file marked as AssumedOpenAndDecrypted should be found.");
+                Assert.That(decryptedFiles.Contains(decryptedFile2), "A file marked as DecryptedIsPendingDelete should be found.");
+                Assert.That(decryptedFiles.Contains(notDecryptedFile), Is.Not.True, "A file marked as NotDecrypted should not be found.");
+            }
+        }
+
+        [Test]
+        public static void TestDoubleDispose()
+        {
+            FileSystemState state = new FileSystemState();
+            state.Dispose();
+
+            Assert.DoesNotThrow(() => { state.Dispose(); });
+        }
+
+        [Test]
+        public static void TestArgumentNull()
+        {
+            using (FileSystemState state = new FileSystemState())
+            {
+                ActiveFile nullActiveFile = null;
+                string nullPath = null;
+                Func<ActiveFile, ActiveFile> nullAction = null;
+                IRuntimeFileInfo nullFileInfo = null;
+
+                Assert.Throws<ArgumentNullException>(() => { state.RemoveActiveFile(nullActiveFile); });
+                Assert.Throws<ArgumentNullException>(() => { state.Add(nullActiveFile); });
+                Assert.Throws<ArgumentNullException>(() => { state.FindActiveFileFromEncryptedPath(nullPath); });
+                Assert.Throws<ArgumentNullException>(() => { state.ForEach(ChangedEventMode.RaiseAlways, nullAction); });
+                Assert.Throws<ArgumentNullException>(() => { FileSystemState.Create(nullFileInfo); });
+            }
+        }
+
+        [Test]
+        public static void TestInvalidXml()
+        {
+            string badXml = @"<FileSystemState xmlns=""http://www.axantum.com/Serialization/"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">";
+
+            IRuntimeFileInfo stateInfo = Instance.WorkFolder.FileInfo.Combine("mystate.txt");
+            using (Stream stream = stateInfo.OpenWrite())
+            {
+                byte[] bytes = Encoding.UTF8.GetBytes(badXml);
+                stream.Write(bytes, 0, bytes.Length);
+            }
+
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(state.ActiveFileCount, Is.EqualTo(0), "After loading damaged state, the count should be zero.");
+
+                ActiveFile decryptedFile1 = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+                state.Add(decryptedFile1);
+
+                Assert.That(state.ActiveFileCount, Is.EqualTo(1), "After adding a file, the count should be one.");
+            }
+        }
+
+        [Test]
+        public static void TestWatchedFolders()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(state.WatchedFolders, Is.Not.Null, "There should be a Watched Folders instance.");
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(0), "There should be no Watched folders.");
+
+                FakeRuntimeFileInfo.AddFolder(_rootPath);
+                state.AddWatchedFolder(new WatchedFolder(_rootPath, SymmetricKeyThumbprint.Zero));
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should be one Watched Folder.");
+
+                state.AddWatchedFolder(new WatchedFolder(_rootPath, SymmetricKeyThumbprint.Zero));
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should still only be one Watched Folder.");
+
+                state.Save();
+            }
+
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should be one Watched Folder.");
+
+                Assert.That(state.WatchedFolders.First(), Is.EqualTo(new WatchedFolder(_rootPath, SymmetricKeyThumbprint.Zero)), "The Watched Folder should be equal to this.");
+
+                state.RemoveWatchedFolder(Instance.WorkFolder.FileInfo.Combine("mystate.txt"));
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1), "There should still be one Watched folders.");
+
+                state.RemoveWatchedFolder(Factory.New<IRuntimeFileInfo>(_rootPath));
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(0), "There should be no Watched folders now.");
+            }
+        }
+
+        [Test]
+        public static void TestWatchedFolderChanged()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                FakeRuntimeFileInfo.AddFolder(_rootPath);
+                state.AddWatchedFolder(new WatchedFolder(_rootPath, SymmetricKeyThumbprint.Zero));
+
+                Assert.That(state.ActiveFileCount, Is.EqualTo(0));
+
+                FakeRuntimeFileInfo.AddFile(_encryptedAxxPath, null);
+                Assert.That(state.ActiveFileCount, Is.EqualTo(0));
+
+                state.Add(new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedAxxPath), Factory.New<IRuntimeFileInfo>(_decryptedTxtPath), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id));
+                Assert.That(state.ActiveFileCount, Is.EqualTo(1));
+
+                Factory.New<IRuntimeFileInfo>(_encryptedAxxPath).Delete();
+                Assert.That(state.ActiveFileCount, Is.EqualTo(1), "When deleted, the active file count should still be one.");
+                Assert.That(state.ActiveFiles.First().Status.HasFlag(ActiveFileStatus.Inactive), "But after the Remove(), the active file should have the inactive flag set.");
+            }
+        }
+
+        [Test]
+        public static void TestWatchedFolderRemoved()
+        {
+            using (FileSystemState state = FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("mystate.txt")))
+            {
+                FakeRuntimeFileInfo.AddFolder(_rootPath);
+                state.AddWatchedFolder(new WatchedFolder(_rootPath, SymmetricKeyThumbprint.Zero));
+
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(1));
+
+                FakeRuntimeFileInfo.RemoveFileOrFolder(_rootPath);
+
+                Assert.That(state.WatchedFolders.Count(), Is.EqualTo(0));
+            }
+        }
+
+        [Test]
+        public static void TestChangedEvent()
+        {
+            bool wasHere = false;
+
+            SessionNotify notificationMonitor = new SessionNotify();
+
+            notificationMonitor.Notification += (object sender, SessionNotificationEventArgs e) => { wasHere = e.Notification.NotificationType == SessionNotificationType.ActiveFileChange; };
+            notificationMonitor.Notify(new SessionNotification(SessionNotificationType.ActiveFileChange));
+
+            Assert.That(wasHere, Is.True, "The RaiseChanged() method should raise the event immediately.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileSystemStateActions.cs b/Axantum.AxCrypt.Core.Test/TestFileSystemStateActions.cs
new file mode 100644
index 0000000..bbae258
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileSystemStateActions.cs
@@ -0,0 +1,619 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileSystemStateActions
+    {
+        private static readonly string _pathRoot = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _documentsFolder = _pathRoot.PathCombine("Documents");
+        private static readonly string _decryptedFile1 = _documentsFolder.PathCombine("test.txt");
+        private static readonly string _encryptedFile1 = _documentsFolder.PathCombine("Uncompressed.axx");
+        private static readonly string _fileSystemStateFilePath = Path.Combine(Path.GetTempPath(), "DummyFileSystemState.xml");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesIsNotLocked()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            DateTime utcYesterday = utcNow.AddDays(-1);
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcYesterday, utcYesterday, utcYesterday, Stream.Null);
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(10); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.True, "The file should be detected as decrypted being created.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesIsLocked()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            DateTime utcYesterday = utcNow.AddDays(-1);
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcYesterday, utcYesterday, utcYesterday, Stream.Null);
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(10); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            using (FileLock fileLock = FileLock.Lock(activeFile.EncryptedFileInfo))
+            {
+                Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            }
+            Assert.That(changedWasRaised, Is.False, "The file should be not be detected as decrypted being created because the encrypted file is locked.");
+            using (FileLock fileLock = FileLock.Lock(activeFile.DecryptedFileInfo))
+            {
+                Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            }
+            Assert.That(changedWasRaised, Is.False, "The file should be not be detected as decrypted being created because the decrypted file is locked.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesKeyIsSet()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            DateTime utcJustNow = utcNow.AddMinutes(-1);
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcJustNow, utcJustNow, utcJustNow, Stream.Null);
+
+            Mock<AxCryptFactory> axCryptFactoryMock = new Mock<AxCryptFactory>() { CallBase = true };
+            axCryptFactoryMock.Setup<Guid>(m => m.TryFindCryptoId(It.IsAny<Passphrase>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<IEnumerable<Guid>>())).Returns((Passphrase passphrase, IRuntimeFileInfo fileInfo, IEnumerable<Guid> cryptoIds) =>
+            {
+                return V1Aes128CryptoFactory.CryptoId;
+            });
+            Factory.Instance.Register<AxCryptFactory>(() => axCryptFactoryMock.Object);
+
+            ActiveFile activeFile;
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.KnownKeys.Add(activeFile.Key);
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            decryptedFileInfo.SetFileTimes(utcNow, utcNow, utcNow);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => DateTime.UtcNow;
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.True, "The file should be detected as modified, because it is considered open and decrypted, has a proper key, is modified, no running process so it should be re-encrypted and deleted.");
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile, Is.Not.Null, "The encrypted file should be found.");
+            Assert.That(activeFile.IsModified, Is.False, "The file should no longer be flagged as modified.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The file should no longer be decrypted, since it was re-encrypted and deleted.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesKeyIsNotSetWithKnownKey()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+            Passphrase passphrase = new Passphrase("a");
+            Factory.New<AxCryptFile>().Decrypt(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Key, Is.Null, "The key should be null after loading of new FileSystemState");
+
+            Instance.KnownKeys.Add(passphrase);
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.True, "The ActiveFile should be modified because there is now a known key.");
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Key, Is.Not.Null, "The key should not be null after the checking of active files.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesKeyIsNotSetWithoutKnownKey()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+            Passphrase passphrase = new Passphrase("a");
+            Factory.New<AxCryptFile>().Decrypt(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            decryptedFileInfo.SetFileTimes(utcNow.AddSeconds(30), utcNow.AddSeconds(30), utcNow.AddSeconds(30));
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Key, Is.Null, "The key should be null after loading of new FileSystemState");
+
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because the file was modified as well and thus cannot be deleted.");
+
+            Instance.KnownKeys.Add(new Passphrase("x"));
+            Instance.KnownKeys.Add(new Passphrase("y"));
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because the file was modified as well and thus cannot be deleted.");
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Key, Is.Null, "The key should still be null after the checking of active files.");
+
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The file should still be there.");
+            Assert.That(activeFile.ThumbprintMatch(passphrase), Is.True, "The active file should still be known to be decryptable with the original passphrase.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesNotDecryptedAndDoesNotExist()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Factory.New<IRuntimeFileInfo>(_decryptedFile1).Delete();
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.NotDecrypted);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.KnownKeys.Add(activeFile.Key);
+
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+
+            Assert.That(changedWasRaised, Is.False, "The ActiveFile should be not be modified because it's already deleted.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesNoDeleteWhenNotDesktopWindows()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.KnownKeys.Add(activeFile.Key);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.Unknown;
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.False, "No change should be raised when the file is not modified and not Desktop Windows.");
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "Nothing should happen with the file when not running as Desktop Windows.");
+
+            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
+            changedWasRaised = false;
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(changedWasRaised, Is.True, "Since the file should be deleted because running as Desktop Windows the changed event should be raised.");
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The file should be deleted and marked as Not Decrypted when running as Desktop Windows.");
+        }
+
+        [Test]
+        public static void TestCheckActiveFilesUpdateButWithTargetLockedForSharing()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+            Passphrase passphrase = new Passphrase("a");
+            Factory.New<AxCryptFile>().Decrypt(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, AxCryptOptions.None, new ProgressContext());
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), passphrase, ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            decryptedFileInfo.SetFileTimes(utcNow.AddSeconds(30), utcNow.AddSeconds(30), utcNow.AddSeconds(30));
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            Instance.KnownKeys.Add(passphrase);
+
+            EventHandler eventHandler = ((object sender, EventArgs e) =>
+            {
+                FakeRuntimeFileInfo fileInfo = (FakeRuntimeFileInfo)sender;
+                if (fileInfo.FullName == _decryptedFile1)
+                {
+                    throw new IOException("Faked sharing violation.");
+                }
+            });
+            FakeRuntimeFileInfo.OpeningForRead += eventHandler;
+            try
+            {
+                Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            }
+            finally
+            {
+                FakeRuntimeFileInfo.OpeningForRead -= eventHandler;
+            }
+
+            Assert.That(changedWasRaised, Is.True, "The ActiveFile should be modified because it should now be marked as not shareable.");
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.True, "The ActiveFile should be marked as not shareable after the checking of active files.");
+        }
+
+        [Test]
+        public static void TestTryDeleteButProcessHasNotExited()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            FakeLauncher fakeLauncher = new FakeLauncher(_decryptedFile1);
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);
+            Instance.FileSystemState.Add(activeFile, fakeLauncher);
+            Instance.KnownKeys.Add(activeFile.Key);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(changedWasRaised, Is.False, "No changed event should be raised because no change should occur since the process is active.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The ActiveFile plain text should not be deleted after the checking of active files because the launcher is active.");
+        }
+
+        [Test]
+        public static void TestCheckProcessExitedWhenExited()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            FakeLauncher fakeLauncher = new FakeLauncher(_decryptedFile1);
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable);
+            Instance.FileSystemState.Add(activeFile, fakeLauncher);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
+            fakeLauncher.HasExited = true;
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the process has exited.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The ActiveFile plain text should be deleted after the checking of active files because the launcher is no longer active.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.False, "The file should be shareable after checking of active files because the launcher is no longer active.");
+        }
+
+        [Test]
+        public static void TestTryDeleteButDecryptedSharingLocked()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(_encryptedFile1), Factory.New<IRuntimeFileInfo>(_decryptedFile1), new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1); });
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+            SetupAssembly.FakeRuntimeEnvironment.Platform = Platform.WindowsDesktop;
+
+            EventHandler eventHandler = ((object sender, EventArgs e) =>
+            {
+                FakeRuntimeFileInfo fileInfo = (FakeRuntimeFileInfo)sender;
+                if (fileInfo.FullName == _decryptedFile1)
+                {
+                    throw new IOException("Faked sharing violation.");
+                }
+            });
+            FakeRuntimeFileInfo.Moving += eventHandler;
+            FakeRuntimeFileInfo.Deleting += eventHandler;
+            FakeRuntimeFileInfo.OpeningForWrite += eventHandler;
+            try
+            {
+                Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            }
+            finally
+            {
+                FakeRuntimeFileInfo.Deleting -= eventHandler;
+                FakeRuntimeFileInfo.OpeningForWrite -= eventHandler;
+            }
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because it should now be NotShareable.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted), Is.True, "The ActiveFile plain text should still be there after the checking of active files because the file is NotShareable.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotShareable), Is.True, "The ActiveFile plain text should be NotShareable after the checking of active files because the file could not be deleted.");
+        }
+
+        [Test]
+        public static void TestPurgeActiveFilesWhenFileIsLocked()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            using (FileLock fileLock = FileLock.Lock(decryptedFileInfo))
+            {
+                Factory.New<ActiveFileAction>().PurgeActiveFiles(new ProgressContext());
+            }
+
+            Assert.That(changedWasRaised, Is.False, "A changed event should not be raised because the decrypted file is locked.");
+        }
+
+        [Test]
+        public static void TestPurgeActiveFilesWhenFileIsModified()
+        {
+            DateTime utcNow = OS.Current.UtcNow;
+            FakeRuntimeFileInfo.AddFile(_encryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+            FakeRuntimeFileInfo.AddFile(_decryptedFile1, utcNow, utcNow, utcNow, Stream.Null);
+
+            Mock<AxCryptFactory> axCryptFactoryMock = new Mock<AxCryptFactory>() { CallBase = true };
+            axCryptFactoryMock.Setup<Guid>(m => m.TryFindCryptoId(It.IsAny<Passphrase>(), It.IsAny<IRuntimeFileInfo>(), It.IsAny<IEnumerable<Guid>>())).Returns((Passphrase passphrase, IRuntimeFileInfo fileInfo, IEnumerable<Guid> cryptoIds) =>
+            {
+                return V1Aes128CryptoFactory.CryptoId;
+            });
+            Factory.Instance.Register<AxCryptFactory>(() => axCryptFactoryMock.Object);
+
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, new Passphrase("passphrase"), ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            int timeCalls = 0;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return utcNow.AddMinutes(1).AddMilliseconds(100 * timeCalls++); });
+            DateTime utcLater = OS.Current.UtcNow;
+
+            decryptedFileInfo.SetFileTimes(utcLater, utcLater, utcLater);
+
+            bool changedWasRaised = false;
+            Instance.FileSystemState.ActiveFileChanged += ((object sender, ActiveFileChangedEventArgs e) =>
+            {
+                changedWasRaised = true;
+            });
+
+            Factory.New<ActiveFileAction>().PurgeActiveFiles(new ProgressContext());
+
+            activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(_encryptedFile1);
+            Assert.That(changedWasRaised, Is.True, "A changed event should be raised because the decrypted file is modified.");
+            Assert.That(activeFile.Status.HasMask(ActiveFileStatus.NotDecrypted), Is.True, "The NotShareable not withstanding, the purge should have updated the file and removed the decrypted file.");
+        }
+
+        [Test]
+        public static void TestUpdateActiveFileWithKeyIfKeyMatchesThumbprintWithKnownKey()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            bool updateWasMade = Factory.New<ActiveFileAction>().UpdateActiveFileWithKeyIfKeyMatchesThumbprint(key);
+            Assert.That(updateWasMade, Is.False, "Since there are only ActiveFiles with known keys in the list, no update should be made.");
+        }
+
+        [Test]
+        public static void TestUpdateActiveFileWithKeyIfKeyMatchesThumbprintWithWrongThumbprint()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("a");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+
+            Passphrase wrongKey = new Passphrase("b");
+            bool updateWasMade = Factory.New<ActiveFileAction>().UpdateActiveFileWithKeyIfKeyMatchesThumbprint(wrongKey);
+            Assert.That(updateWasMade, Is.False, "Since there are only ActiveFiles with wrong keys in the list, no update should be made.");
+        }
+
+        [Test]
+        public static void TestUpdateActiveFileWithKeyIfKeyMatchesThumbprintWithMatchingThumbprint()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+
+            bool updateWasMade = Factory.New<ActiveFileAction>().UpdateActiveFileWithKeyIfKeyMatchesThumbprint(key);
+            Assert.That(updateWasMade, Is.True, "Since there is an ActiveFile with the right thumbprint in the list, an update should be made.");
+        }
+
+        [Test]
+        public static void TestUpdateActiveFileButWithNoChangeDueToIrrelevantStatus()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.None, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return DateTime.UtcNow.AddMinutes(1); });
+
+            bool somethingWasChanged = false;
+            Instance.FileSystemState.ActiveFileChanged += (object sender, ActiveFileChangedEventArgs e) =>
+                {
+                    somethingWasChanged = true;
+                };
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(somethingWasChanged, Is.False, "No event should be raised, because nothing should change.");
+        }
+
+        [Test]
+        public static void TestUpdateActiveFileWithEventRaisedSinceItAppearsAProcessHasExited()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = (() => { return DateTime.UtcNow.AddMinutes(1); });
+
+            bool somethingWasChanged = false;
+            Instance.FileSystemState.ActiveFileChanged += (object sender, ActiveFileChangedEventArgs e) =>
+            {
+                somethingWasChanged = true;
+            };
+            Factory.New<ActiveFileAction>().CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+            Assert.That(somethingWasChanged, Is.True, "An event should be raised, because status was NotShareable, but no process is active.");
+        }
+
+        [Test]
+        public static void TestRemoveRecentFile()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            ActiveFile beforeRemoval = Instance.FileSystemState.FindActiveFileFromEncryptedPath(encryptedFileInfo.FullName);
+            Assert.That(beforeRemoval, Is.Not.Null, "Before being removed, the ActiveFile should be possible to find.");
+
+            Factory.New<ActiveFileAction>().RemoveRecentFiles(new IRuntimeFileInfo[] { Factory.New<IRuntimeFileInfo>(encryptedFileInfo.FullName) }, new ProgressContext());
+
+            ActiveFile afterRemoval = Instance.FileSystemState.FindActiveFileFromEncryptedPath(encryptedFileInfo.FullName);
+            Assert.That(afterRemoval, Is.Not.Null, "After being removed, the ActiveFile should still be possible to find.");
+            Assert.That(afterRemoval.Status.HasFlag(ActiveFileStatus.Inactive), "But after the Remove(), the active file should have the inactive flag set.");
+        }
+
+        [Test]
+        public static void TestRemoveRecentFileWhenFileDoesNotExist()
+        {
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(_encryptedFile1);
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(_decryptedFile1);
+            Passphrase key = new Passphrase("passphrase");
+            ActiveFile activeFile = new ActiveFile(encryptedFileInfo, decryptedFileInfo, key, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.NotShareable, new V2Aes256CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+            Instance.FileSystemState.Save();
+
+            ActiveFile beforeRemoval = Instance.FileSystemState.FindActiveFileFromEncryptedPath(encryptedFileInfo.FullName);
+            Assert.That(beforeRemoval, Is.Not.Null, "Before being removed, the ActiveFile should be possible to find.");
+
+            Assert.DoesNotThrow(() => { Factory.New<ActiveFileAction>().RemoveRecentFiles(new IRuntimeFileInfo[] { Factory.New<IRuntimeFileInfo>(encryptedFileInfo.FullName + ".notfound") }, new ProgressContext()); });
+
+            ActiveFile afterFailedRemoval = Instance.FileSystemState.FindActiveFileFromEncryptedPath(encryptedFileInfo.FullName);
+            Assert.That(afterFailedRemoval, Is.Not.Null, "After failed removal, the ActiveFile should still be possible to find.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestFileWatcher.cs b/Axantum.AxCrypt.Core.Test/TestFileWatcher.cs
new file mode 100644
index 0000000..67fdb69
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestFileWatcher.cs
@@ -0,0 +1,66 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestFileWatcher
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void SimpleTest()
+        {
+            IFileWatcher watcher = Factory.New<IFileWatcher>("c:\temp");
+            string fullName = String.Empty;
+            watcher.FileChanged += (object sender, FileWatcherEventArgs e) =>
+                {
+                    fullName = e.FullName;
+                };
+
+            FakeFileWatcher fakeWatcher = (FakeFileWatcher)watcher;
+            fakeWatcher.OnChanged(new FileWatcherEventArgs("c:\temp\test.txt"));
+
+            Assert.That(fullName, Is.EqualTo("c:\temp\test.txt"), "The changed event should pass the path specified.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestHeaderBlock.cs
new file mode 100644
index 0000000..3b4a63a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestHeaderBlock.cs
@@ -0,0 +1,139 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        private class TestingHeaderBlock : HeaderBlock
+        {
+            public TestingHeaderBlock(HeaderBlockType headerBlockType, byte[] dataBlock)
+                : base(headerBlockType, dataBlock)
+            {
+            }
+
+            public override object Clone()
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [Test]
+        public static void TestEquals()
+        {
+            byte[] data = new byte[] { 5, 6, 7, 8, 9, 10 };
+            byte[] other = new byte[] { 5, 6, 7, 8, 9, 11 };
+
+            TestingHeaderBlock block1 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block2 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block3 = new TestingHeaderBlock((HeaderBlockType)33, other);
+            TestingHeaderBlock block4 = new TestingHeaderBlock((HeaderBlockType)34, data);
+            TestingHeaderBlock nullBlock = null;
+
+            Assert.That(block1.Equals(block2));
+            Assert.That(block2.Equals(block1));
+            Assert.That(!block1.Equals(block3));
+            Assert.That(!block1.Equals(block4));
+            Assert.That(!block1.Equals(nullBlock));
+        }
+
+        [Test]
+        public static void TestObjectEquals()
+        {
+            byte[] data = new byte[] { 5, 6, 7, 8, 9, 10 };
+            byte[] other = new byte[] { 5, 6, 7, 8, 9, 11 };
+
+            object block1 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            object block2 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            object block3 = new TestingHeaderBlock((HeaderBlockType)33, other);
+            object block4 = new TestingHeaderBlock((HeaderBlockType)34, data);
+            object nullBlock = null;
+
+            Assert.That(block1.Equals(block2));
+            Assert.That(block2.Equals(block1));
+            Assert.That(!block1.Equals(block3));
+            Assert.That(!block1.Equals(block4));
+            Assert.That(!block1.Equals(nullBlock));
+        }
+
+        [Test]
+        public static void TestGetHashCode()
+        {
+            byte[] data = new byte[] { 5, 6, 7, 8, 9, 10 };
+            byte[] other = new byte[] { 5, 6, 7, 8, 9, 11 };
+
+            TestingHeaderBlock block1 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block2 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block3 = new TestingHeaderBlock((HeaderBlockType)33, other);
+            TestingHeaderBlock block4 = new TestingHeaderBlock((HeaderBlockType)34, data);
+
+            Assert.That(block1.GetHashCode(), Is.EqualTo(block2.GetHashCode()));
+            Assert.That(block1.GetHashCode(), Is.Not.EqualTo(block3.GetHashCode()));
+            Assert.That(block1.GetHashCode(), Is.Not.EqualTo(block4.GetHashCode()));
+        }
+
+        [Test]
+        public static void TestOperatorEquals()
+        {
+            byte[] data = new byte[] { 5, 6, 7, 8, 9, 10 };
+            byte[] other = new byte[] { 5, 6, 7, 8, 9, 11 };
+
+            TestingHeaderBlock block1 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block1alias = block1;
+            TestingHeaderBlock block2 = new TestingHeaderBlock((HeaderBlockType)33, data);
+            TestingHeaderBlock block3 = new TestingHeaderBlock((HeaderBlockType)33, other);
+            TestingHeaderBlock block4 = new TestingHeaderBlock((HeaderBlockType)34, data);
+            TestingHeaderBlock nullBlock = null;
+            TestingHeaderBlock nullBlockAlias = nullBlock;
+
+            Assert.That(block1 == block1alias);
+            Assert.That(block1 == block2);
+            Assert.That(block2 == block1);
+            Assert.That(block1 != block3);
+            Assert.That(block1 != block4);
+            Assert.That(block1 != nullBlock);
+            Assert.That(nullBlock != block1);
+            Assert.That(nullBlock == nullBlockAlias);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestHeaders.cs b/Axantum.AxCrypt.Core.Test/TestHeaders.cs
new file mode 100644
index 0000000..5d9fc6f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestHeaders.cs
@@ -0,0 +1,147 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestHeaders
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<ILogging>(() => new FakeLogging());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        private class NewHeaderBlock : HeaderBlock
+        {
+            public NewHeaderBlock(byte[] dataBlock)
+                : base((HeaderBlockType)99, (byte[])dataBlock.Clone())
+            {
+            }
+
+            public override object Clone()
+            {
+                NewHeaderBlock block = new NewHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+                return block;
+            }
+        }
+
+        [Test]
+        public static void TestTooNewVersionTooHigh()
+        {
+            using (MemoryStream stream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(stream);
+                new PreambleHeaderBlock().Write(stream);
+                new VersionHeaderBlock(new byte[] { 5, 0, 2, 0, 0 }).Write(stream);
+                new NewHeaderBlock(new byte[0]).Write(stream);
+                new DataHeaderBlock().Write(stream);
+                stream.Position = 0;
+
+                Assert.Throws<FileFormatException>(() => new Headers().Load(stream));
+            }
+        }
+
+        [Test]
+        public static void TestTooNewVersionTooLow()
+        {
+            using (MemoryStream stream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(stream);
+                new PreambleHeaderBlock().Write(stream);
+                new VersionHeaderBlock(new byte[] { 0, 0, 2, 0, 0 }).Write(stream);
+                new NewHeaderBlock(new byte[0]).Write(stream);
+                new DataHeaderBlock().Write(stream);
+                stream.Position = 0;
+
+                Assert.Throws<FileFormatException>(() => new Headers().Load(stream));
+            }
+        }
+
+        [Test]
+        public static void TestEnsureFileVersion()
+        {
+            Headers headers = new Headers();
+            headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            headers.HeaderBlocks.Add(new VersionHeaderBlock(new byte[] { 4, 1, 2, 0, 0 }));
+            headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            Assert.DoesNotThrow(() => headers.EnsureFileFormatVersion(4, 4));
+            Assert.Throws<FileFormatException>(() => headers.EnsureFileFormatVersion(5, 5));
+            Assert.Throws<FileFormatException>(() => headers.EnsureFileFormatVersion(1, 3));
+        }
+
+        [Test]
+        public static void TestFindHeaderBlockNotFound()
+        {
+            Headers headers = new Headers();
+            headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            headers.HeaderBlocks.Add(new VersionHeaderBlock(new byte[] { 4, 1, 2, 0, 0 }));
+            headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            FileInfoEncryptedHeaderBlock fileInfoHeaderBlock = headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+            Assert.That(fileInfoHeaderBlock, Is.Null);
+        }
+
+        [Test]
+        public static void TestBadAxCryptReader()
+        {
+            Mock<AxCryptReader> mockAxCryptReader = new Mock<AxCryptReader>(Stream.Null);
+            mockAxCryptReader.Setup(r => r.Read()).Returns(true);
+            mockAxCryptReader.Setup(r => r.CurrentItemType).Returns(AxCryptItemType.MagicGuid);
+
+            Headers headers = new Headers();
+            Assert.Throws<InternalErrorException>(() => headers.Load(mockAxCryptReader.Object));
+        }
+
+        [Test]
+        public static void TestEndOfFileAxCryptReader()
+        {
+            Mock<AxCryptReader> mockAxCryptReader = new Mock<AxCryptReader>(Stream.Null);
+            mockAxCryptReader.Setup(r => r.Read()).Returns(false);
+
+            Headers headers = new Headers();
+            Assert.Throws<FileFormatException>(() => headers.Load(mockAxCryptReader.Object));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestIOStreams.cs b/Axantum.AxCrypt.Core.Test/TestIOStreams.cs
new file mode 100644
index 0000000..cf50818
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestIOStreams.cs
@@ -0,0 +1,356 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.IO;
+using System.IO.Compression;
+using System.Text;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestIOStreams
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAxCryptDataStream()
+        {
+            string streamData = "This is some data in the streamEXTRA";
+            using (Stream inputStream = new MemoryStream())
+            {
+                byte[] streamBytes = Encoding.UTF8.GetBytes(streamData);
+                inputStream.Write(streamBytes, 0, streamBytes.Length);
+
+                using (Stream hmacStream = new MemoryStream())
+                {
+                    Assert.Throws<ArgumentNullException>(() =>
+                    {
+                        using (V1AxCryptDataStream axCryptDataStream = new V1AxCryptDataStream(null, hmacStream, inputStream.Length)) { }
+                    }, "An input stream must be given, it cannot be null.");
+                    Assert.Throws<ArgumentNullException>(() =>
+                    {
+                        using (V1AxCryptDataStream axCryptDataStream = new V1AxCryptDataStream(inputStream, null, inputStream.Length)) { }
+                    }, "An HmacStream must be given, it cannot be null.");
+                    Assert.Throws<ArgumentOutOfRangeException>(() =>
+                    {
+                        using (V1AxCryptDataStream axCryptDataStream = new V1AxCryptDataStream(inputStream, hmacStream, -inputStream.Length)) { }
+                    }, "Negative length is not allowed.");
+
+                    inputStream.Position = 0;
+                    using (V1AxCryptDataStream axCryptDataStream = new V1AxCryptDataStream(inputStream, hmacStream, inputStream.Length - 5))
+                    {
+                        Assert.Throws<NotSupportedException>(() =>
+                        {
+                            axCryptDataStream.Seek(0, SeekOrigin.Begin);
+                        }, "Seek is not supported.");
+
+                        Assert.Throws<NotSupportedException>(() =>
+                        {
+                            axCryptDataStream.SetLength(0);
+                        }, "SetLength is not supported.");
+
+                        Assert.Throws<NotSupportedException>(() =>
+                        {
+                            axCryptDataStream.Write(new byte[1], 0, 1);
+                        }, "Write is not supported.");
+
+                        Assert.Throws<NotSupportedException>(() =>
+                        {
+                            axCryptDataStream.Position = 0;
+                        }, "Setting the position is not supported.");
+
+                        Assert.Throws<NotSupportedException>(() =>
+                        {
+                            axCryptDataStream.Flush();
+                        }, "Flush is not supported, and not meaningful on a read-only stream.");
+
+                        Assert.That(axCryptDataStream.CanRead, Is.True, "AxCryptDataStream can be read.");
+                        Assert.That(axCryptDataStream.CanSeek, Is.True, "AxCryptDataStream is a forward only reader stream, but it does support Length and Position therefore it reports that it can Seek.");
+                        Assert.That(axCryptDataStream.CanWrite, Is.False, "AxCryptDataStream is a forward only reader stream, it does not support writing.");
+                        Assert.That(axCryptDataStream.Length, Is.EqualTo(inputStream.Length - 5), "The stream should report the length provided in the constructor.");
+                        inputStream.Position = 5;
+                        Assert.That(axCryptDataStream.Position, Is.EqualTo(0), "The original position should be zero, regardless of the actual position of the input stream.");
+                        inputStream.Position = 0;
+
+                        byte[] buffer = new byte[3];
+                        int count;
+                        int total = 0;
+                        while ((count = axCryptDataStream.Read(buffer, 0, buffer.Length)) > 0)
+                        {
+                            total += count;
+                        }
+                        Assert.That(total, Is.EqualTo(inputStream.Length - 5), "The AxCryptDataStream should be limited to the length provided, not the backing stream.");
+                        Assert.That(hmacStream.Length, Is.EqualTo(total), "The hmac stream should have all data read written to it.");
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestHmacStream()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                using (V1HmacStream hmacStream = new V1HmacStream(null)) { }
+            });
+
+            SymmetricKey key = new SymmetricKey(new byte[16]);
+            using (V1HmacStream hmacStream = new V1HmacStream(key))
+            {
+                Assert.That(hmacStream.CanRead, Is.False, "HmacStream does not support reading.");
+                Assert.That(hmacStream.CanSeek, Is.False, "HmacStream does not support seeking.");
+                Assert.That(hmacStream.CanWrite, Is.True, "HmacStream does support writing.");
+
+                Assert.Throws<NotSupportedException>(() =>
+                {
+                    byte[] buffer = new byte[5];
+                    hmacStream.Read(buffer, 0, buffer.Length);
+                });
+
+                Assert.Throws<NotSupportedException>(() =>
+                {
+                    hmacStream.Seek(0, SeekOrigin.Begin);
+                });
+
+                Assert.Throws<NotSupportedException>(() =>
+                {
+                    hmacStream.SetLength(0);
+                });
+
+                Assert.Throws<ArgumentNullException>(() =>
+                {
+                    hmacStream.ReadFrom(null);
+                });
+
+                hmacStream.Write(new byte[10], 0, 10);
+                using (Stream dataStream = new MemoryStream())
+                {
+                    dataStream.Write(new byte[10], 0, 10);
+                    dataStream.Position = 0;
+                    hmacStream.ReadFrom(dataStream);
+                }
+                Assert.That(hmacStream.Position, Is.EqualTo(20), "There are 20 bytes written so the position should be 20.");
+                Assert.That(hmacStream.Length, Is.EqualTo(20), "There are 20 bytes written so the position should be 20.");
+                hmacStream.Flush();
+                Assert.That(hmacStream.Position, Is.EqualTo(20), "Nothing should change after Flush(), this is not a buffered stream.");
+                Assert.That(hmacStream.Length, Is.EqualTo(20), "Nothing should change after Flush(), this is not a buffered stream.");
+
+                Assert.Throws<NotSupportedException>(() =>
+                {
+                    hmacStream.Position = 0;
+                }, "Position is not supported.");
+
+                Hmac dataHmac = hmacStream.HmacResult;
+                Assert.That(dataHmac.GetBytes(), Is.EquivalentTo(new byte[] { 0x62, 0x6f, 0x2c, 0x61, 0xc7, 0x68, 0x00, 0xb3, 0xa6, 0x8d, 0xf9, 0x55, 0x95, 0xbc, 0x1f, 0xd1 }), "The HMAC of 20 bytes of zero with 128-bit AesKey all zero should be this.");
+
+                Assert.Throws<InvalidOperationException>(() =>
+                {
+                    hmacStream.Write(new byte[1], 0, 1);
+                }, "Can't write to the stream after checking and thus finalizing the HMAC");
+
+                // This also implicitly covers double-dispose since we're in a using block.
+                hmacStream.Dispose();
+
+                Assert.Throws<ObjectDisposedException>(() =>
+                {
+                    Hmac invalidDataHmac = hmacStream.HmacResult;
+
+                    // Remove FxCop warning
+                    Object.Equals(invalidDataHmac, null);
+                });
+                Assert.Throws<ObjectDisposedException>(() =>
+                {
+                    hmacStream.Write(new byte[1], 0, 1);
+                });
+                Assert.Throws<ObjectDisposedException>(() =>
+                {
+                    using (Stream stream = new MemoryStream())
+                    {
+                        hmacStream.ReadFrom(stream);
+                    }
+                });
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestLookAheadStream()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                using (Stream stream = new LookAheadStream(null)) { }
+            }, "Input stream cannot be null.");
+
+            Assert.Throws<ArgumentException>(() =>
+            {
+                using (Stream writeOnlyStream = new DeflateStream(new MemoryStream(), CompressionMode.Compress))
+                {
+                    using (Stream stream = new LookAheadStream(writeOnlyStream)) { }
+                }
+            }, "The input stream must support reading.");
+
+            using (Stream inputStream = new MemoryStream())
+            {
+                byte[] inData = Encoding.UTF8.GetBytes("0123456789");
+                inputStream.Write(inData, 0, inData.Length);
+                inputStream.Position = 0;
+                using (LookAheadStream lookAheadStream = new LookAheadStream(inputStream))
+                {
+                    Assert.That(lookAheadStream.CanRead, Is.True, "The stream always supports reading.");
+                    Assert.That(lookAheadStream.CanSeek, Is.False, "The stream does not support seeking.");
+                    Assert.That(lookAheadStream.CanWrite, Is.False, "The stream does not support writing.");
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        long length = lookAheadStream.Length;
+
+                        // Make FxCop not complain
+                        Object.Equals(length, null);
+                    });
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        long position = lookAheadStream.Position;
+
+                        // Make FxCop not complain
+                        Object.Equals(position, null);
+                    });
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        lookAheadStream.Position = 0;
+                    });
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        lookAheadStream.Seek(0, SeekOrigin.Begin);
+                    });
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        lookAheadStream.SetLength(0);
+                    });
+                    Assert.Throws<NotSupportedException>(() =>
+                    {
+                        lookAheadStream.Write(new byte[1], 0, 1);
+                    });
+
+                    int count;
+                    byte[] buffer;
+
+                    lookAheadStream.Pushback(new byte[] { 0x99 }, 0, 1);
+                    buffer = new byte[1];
+                    count = lookAheadStream.Read(buffer, 0, 1);
+                    Assert.That(count, Is.EqualTo(1), "One byte was read.");
+                    Assert.That(buffer[0], Is.EqualTo(0x99), "A byte with value 0x99 was pushed back.");
+
+                    buffer = new byte[5];
+                    count = lookAheadStream.Read(buffer, 0, buffer.Length);
+                    Assert.That(count, Is.EqualTo(5), "Five bytes were read.");
+                    Assert.That(buffer, Is.EquivalentTo(new byte[] { 48, 49, 50, 51, 52 }), "The string '01234' was read.");
+
+                    lookAheadStream.Pushback(new byte[] { 52 }, 0, 1);
+                    lookAheadStream.Pushback(new byte[] { 51 }, 0, 1);
+                    lookAheadStream.Pushback(new byte[] { 48, 49, 50 }, 0, 3);
+
+                    // Nothing should happen, this is a pure dummy call.
+                    lookAheadStream.Flush();
+
+                    buffer = new byte[10];
+                    bool exactWasRead = lookAheadStream.ReadExact(buffer);
+                    Assert.That(exactWasRead, Is.True, "Ten bytes were read.");
+                    Assert.That(buffer, Is.EquivalentTo(new byte[] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 }), "The string '0123456789' was read.");
+
+                    // This also implicitly tests double-dispose since we're in a using block
+                    lookAheadStream.Dispose();
+                    Assert.Throws<ObjectDisposedException>(() =>
+                    {
+                        buffer = new byte[3];
+                        lookAheadStream.Read(buffer, 0, 3);
+                    });
+
+                    Assert.Throws<ObjectDisposedException>(() =>
+                    {
+                        buffer = new byte[5];
+                        lookAheadStream.ReadExact(buffer);
+                    });
+
+                    Assert.Throws<ObjectDisposedException>(() =>
+                    {
+                        buffer = new byte[5];
+                        lookAheadStream.Pushback(buffer, 0, buffer.Length);
+                    });
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestNonClosingStream()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                using (Stream stream = new NonClosingStream(null)) { }
+            });
+
+            using (MemoryStream backingStream = new MemoryStream())
+            {
+                using (NonClosingStream nonClosingStream = new NonClosingStream(backingStream))
+                {
+                    Assert.That(nonClosingStream.CanRead, Is.EqualTo(backingStream.CanRead), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    Assert.That(nonClosingStream.CanSeek, Is.EqualTo(backingStream.CanSeek), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    Assert.That(nonClosingStream.CanWrite, Is.EqualTo(backingStream.CanWrite), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    Assert.That(nonClosingStream.Length, Is.EqualTo(backingStream.Length), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+
+                    nonClosingStream.Flush();
+                    nonClosingStream.Write(new byte[] { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 }, 0, 10);
+                    Assert.That(backingStream.Length, Is.EqualTo(10), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    nonClosingStream.Position = 7;
+                    Assert.That(backingStream.Position, Is.EqualTo(7), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    nonClosingStream.Seek(-5, SeekOrigin.End);
+                    Assert.That(backingStream.Position, Is.EqualTo(5), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    nonClosingStream.SetLength(9);
+                    Assert.That(backingStream.Length, Is.EqualTo(9), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                    byte[] buffer = new byte[4];
+                    nonClosingStream.Read(buffer, 0, buffer.Length);
+                    Assert.That(backingStream.Position, Is.EqualTo(9), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+                }
+                backingStream.Position = 0;
+                byte[] otherBuffer = new byte[9];
+                backingStream.Read(otherBuffer, 0, otherBuffer.Length);
+                Assert.That(otherBuffer, Is.EquivalentTo(new byte[] { 20, 21, 22, 23, 24, 25, 26, 27, 28 }), "NonClosingStream is a clean wrapper and should always return the same as the backing stream.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestIdTagHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestIdTagHeaderBlock.cs
new file mode 100644
index 0000000..ff9980e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestIdTagHeaderBlock.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestIdTagHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            V1IdTagHeaderBlock idTagHeaderBlock = new V1IdTagHeaderBlock("This is my tag!");
+            V1IdTagHeaderBlock cloned = (V1IdTagHeaderBlock)idTagHeaderBlock.Clone();
+            Assert.That(idTagHeaderBlock, Is.Not.SameAs(cloned), "The clone should not be the same reference.");
+            Assert.That(cloned.IdTag, Is.EqualTo(idTagHeaderBlock.IdTag), "The clone should have the same id tag as the original.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestIdentityViewModel.cs b/Axantum.AxCrypt.Core.Test/TestIdentityViewModel.cs
new file mode 100644
index 0000000..4dee4f1
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestIdentityViewModel.cs
@@ -0,0 +1,402 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestIdentityViewModel
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestLogOnExistingIdentity()
+        {
+            Passphrase passphrase = new Passphrase("p");
+
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "p";
+            };
+
+            ivm.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.IsLoggedOn);
+        }
+
+        [Test]
+        public static void TestLogOnExistingIdentityWithCancel()
+        {
+            Passphrase passphrase = new Passphrase("p");
+
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            ivm.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(ivm.Passphrase, Is.Null);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False);
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOn()
+        {
+            Passphrase passphrase = new Passphrase("p");
+
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            bool wasLoggingOn = false;
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                wasLoggingOn = true;
+            };
+
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True);
+
+            ivm.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(wasLoggingOn, Is.False);
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False);
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOffAndNoIdentities()
+        {
+            bool wasCreateNew = false;
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                wasCreateNew = e.CreateNew;
+                e.Passphrase = "ccc";
+                e.Name = "New User Passphrase";
+            };
+
+            ivm.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(wasCreateNew, Is.True, "Logging on event should be with Create New set.");
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.True, "Should be logged on.");
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(new Passphrase("ccc").Thumbprint));
+            Assert.That(Instance.FileSystemState.Identities.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void TestLogOnLogOffWhenLoggedOffAndNoIdentitiesWithCancel()
+        {
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            ivm.Passphrase = new Passphrase("testing");
+            ivm.LogOnLogOff.Execute(Guid.Empty);
+
+            Assert.That(Instance.KnownKeys.IsLoggedOn, Is.False, "Not logged on.");
+            Assert.That(Instance.FileSystemState.Identities.Count(), Is.EqualTo(0));
+            Assert.That(ivm.Passphrase, Is.Null);
+        }
+
+        [Test]
+        public static void AskForLogOnOrDecryptPassphraseActionNotActiveFile()
+        {
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id; ;
+            PassphraseIdentity id = null;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                id = e.Identity;
+                e.Passphrase = "p";
+            };
+
+            ivm.AskForDecryptPassphrase.Execute(@"C:\Folder\File1-txt.axx");
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("p"));
+            Assert.That(id.Thumbprint, Is.EqualTo(PassphraseIdentity.Empty.Thumbprint));
+        }
+
+        [Test]
+        public static void AskForLogOnOrDecryptPassphraseActionActiveFile()
+        {
+            Passphrase key = new Passphrase("p");
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(@"C:\Folder\File1-txt.axx"), Factory.New<IRuntimeFileInfo>(@"C:\Folder\File1.txt"), key, ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            PassphraseIdentity id = null;
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                id = e.Identity;
+                e.Passphrase = "p";
+            };
+
+            ivm.AskForDecryptPassphrase.Execute(@"C:\Folder\File1-txt.axx");
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("p"));
+            Assert.That(id.Thumbprint, Is.EqualTo(PassphraseIdentity.Empty.Thumbprint));
+        }
+
+        [Test]
+        public static void AskForLogOnOrDecryptPassphraseActionActiveFileWithExistingIdentity()
+        {
+            Passphrase key = new Passphrase("p");
+
+            ActiveFile activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(@"C:\Folder\File1-txt.axx"), Factory.New<IRuntimeFileInfo>(@"C:\Folder\File1.txt"), key, ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            PassphraseIdentity id = new PassphraseIdentity(key);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "p";
+            };
+
+            ivm.AskForDecryptPassphrase.Execute(@"C:\Folder\File1-txt.axx");
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("p"));
+        }
+
+        [Test]
+        public static void AskForLogOnPassphraseAction()
+        {
+            Passphrase key = new Passphrase("ppp");
+
+            PassphraseIdentity id = new PassphraseIdentity(key);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "ppp";
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(id);
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("ppp"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(id.Thumbprint));
+        }
+
+        [Test]
+        public static void AskForLogOnPassphraseActionWithCancel()
+        {
+            Passphrase key = new Passphrase("ppp");
+
+            PassphraseIdentity id = new PassphraseIdentity(key);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Cancel = true;
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(id);
+
+            Assert.That(ivm.Passphrase, Is.Null);
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey, Is.Null);
+        }
+
+        [Test]
+        public static void AskForNewLogOnPassphrase()
+        {
+            string defaultPassphrase = null;
+            Instance.FileSystemState.Identities.Add(new PassphraseIdentity());
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                if (!e.CreateNew)
+                {
+                    e.CreateNew = true;
+                    e.Passphrase = "xxx";
+                    return;
+                }
+                defaultPassphrase = e.Passphrase;
+                e.Passphrase = "aaa";
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(defaultPassphrase, Is.EqualTo("xxx"));
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("aaa"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(new Passphrase("aaa").Thumbprint));
+
+            PassphraseIdentity id = Instance.FileSystemState.Identities.FirstOrDefault(i => i.Thumbprint == new Passphrase("aaa").Thumbprint);
+            Assert.That(id.Thumbprint, Is.EqualTo(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+        }
+
+        [Test]
+        public static void AskForNewLogOnPassphraseAutomaticallyBecauseNoIdentitiesExists()
+        {
+            string defaultPassphrase = null;
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.CryptoId = new V1Aes128CryptoFactory().Id;
+            ivm.LoggingOn += (sender, e) =>
+            {
+                if (e.CreateNew)
+                {
+                    defaultPassphrase = e.Passphrase;
+                    e.Passphrase = "aaa";
+                    e.Name = "New User Passphrase";
+                }
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(defaultPassphrase, Is.EqualTo(String.Empty));
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("aaa"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(new Passphrase("aaa").Thumbprint));
+
+            PassphraseIdentity id = Instance.FileSystemState.Identities.FirstOrDefault(i => i.Thumbprint == new Passphrase("aaa").Thumbprint);
+            Assert.That(id.Thumbprint, Is.EqualTo(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+        }
+
+        [Test]
+        public static void AskForNewLogOnPassphraseWithCancel()
+        {
+            string defaultPassphrase = null;
+            Instance.FileSystemState.Identities.Add(new PassphraseIdentity());
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                if (!e.CreateNew)
+                {
+                    e.CreateNew = true;
+                    e.Passphrase = "xxx";
+                    return;
+                }
+                defaultPassphrase = e.Passphrase;
+                e.Cancel = true;
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(defaultPassphrase, Is.EqualTo("xxx"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey, Is.Null);
+            Assert.That(ivm.Passphrase, Is.Null);
+
+            PassphraseIdentity id = Instance.FileSystemState.Identities.FirstOrDefault(i => i.Thumbprint == new Passphrase("xxx").Thumbprint);
+            Assert.That(id, Is.Null);
+        }
+
+        [Test]
+        public static void AskForNewLogOnPassphraseWithKnownIdentity()
+        {
+            Passphrase passphrase = new Passphrase("aaa");
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                if (!e.CreateNew)
+                {
+                    e.CreateNew = true;
+                }
+                e.Passphrase = "aaa";
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("aaa"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(passphrase.Thumbprint));
+            Assert.That(Instance.FileSystemState.Identities.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void AskForLogOnPassphraseWithKnownIdentity()
+        {
+            Passphrase passphrase = new Passphrase("aaa");
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "aaa";
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(ivm.Passphrase.Text, Is.EqualTo("aaa"));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey.Thumbprint, Is.EqualTo(passphrase.Thumbprint));
+            Assert.That(Instance.FileSystemState.Identities.Count(), Is.EqualTo(1));
+        }
+
+        [Test]
+        public static void AskForLogOnPassphraseWithKnownIdentityButWrongPassphraseEntered()
+        {
+            Passphrase passphrase = new Passphrase("aaa");
+            PassphraseIdentity id = new PassphraseIdentity(passphrase);
+            Instance.FileSystemState.Identities.Add(id);
+
+            IdentityViewModel ivm = new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings);
+            ivm.LoggingOn += (sender, e) =>
+            {
+                e.Passphrase = "bbb";
+            };
+
+            ivm.AskForLogOnPassphrase.Execute(null);
+
+            Assert.That(ivm.Passphrase, Is.Null);
+            Assert.That(Instance.FileSystemState.Identities.Count(), Is.EqualTo(1));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestInstance.cs b/Axantum.AxCrypt.Core.Test/TestInstance.cs
new file mode 100644
index 0000000..c7ee9d0
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestInstance.cs
@@ -0,0 +1,59 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestInstance
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestStatusChecker()
+        {
+            Factory.Instance.Singleton<IStatusChecker>(() => new FakeStatusChecker());
+
+            IStatusChecker sc = Instance.StatusChecker;
+            Assert.That(sc is FakeStatusChecker, Is.True);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestIterationCalculator.cs b/Axantum.AxCrypt.Core.Test/TestIterationCalculator.cs
new file mode 100644
index 0000000..b4dcf9c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestIterationCalculator.cs
@@ -0,0 +1,156 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    public static class TestIterationCalculator
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestMinimumGuaranteeV1KeyWrapIterations()
+        {
+            DateTime now = DateTime.UtcNow;
+            int callCounter = -1;
+            bool shouldTerminate = false;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () =>
+            {
+                if (shouldTerminate)
+                {
+                    throw new InvalidOperationException("There should be no more calls at this point.");
+                }
+                if (callCounter++ == 0)
+                {
+                    return now;
+                }
+                if (callCounter < 5)
+                {
+                    return now.AddMilliseconds(callCounter * 50);
+                }
+                shouldTerminate = true;
+                return now.AddMilliseconds(500);
+            };
+
+            long keyWrapIterations = new IterationCalculator().KeyWrapIterations(V1Aes128CryptoFactory.CryptoId);
+
+            Assert.That(keyWrapIterations, Is.EqualTo(5000), "The minimum guarantee should hold.");
+        }
+
+        [Test]
+        public static void TestMinimumGuaranteeV2KeyWrapIterations()
+        {
+            DateTime now = DateTime.UtcNow;
+            int callCounter = -1;
+            bool shouldTerminate = false;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () =>
+            {
+                if (shouldTerminate)
+                {
+                    throw new InvalidOperationException("There should be no more calls at this point.");
+                }
+                if (callCounter++ == 0)
+                {
+                    return now;
+                }
+                if (callCounter < 5)
+                {
+                    return now.AddMilliseconds(callCounter * 50);
+                }
+                shouldTerminate = true;
+                return now.AddMilliseconds(500);
+            };
+
+            long keyWrapIterations = new IterationCalculator().KeyWrapIterations(V2Aes256CryptoFactory.CryptoId);
+
+            Assert.That(keyWrapIterations, Is.EqualTo(5000), "The minimum guarantee should hold.");
+        }
+
+        [Test]
+        public static void TestCalculatedV1KeyWrapIterations()
+        {
+            DateTime now = DateTime.UtcNow;
+            int callCounter = -1;
+            bool shouldTerminate = false;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () =>
+            {
+                if (shouldTerminate)
+                {
+                    throw new InvalidOperationException("There should be no more calls at this point.");
+                }
+                if (callCounter++ == 0)
+                {
+                    return now;
+                }
+                return now.AddMilliseconds(callCounter * 4);
+            };
+
+            long keyWrapIterations = new IterationCalculator().KeyWrapIterations(V1Aes128CryptoFactory.CryptoId);
+
+            Assert.That(keyWrapIterations, Is.EqualTo(12500), "If we do 125000 iterations in 500ms, the result should be 12500 as default iterations (1/20s).");
+        }
+
+        [Test]
+        public static void TestCalculatedV2KeyWrapIterations()
+        {
+            DateTime now = DateTime.UtcNow;
+            int callCounter = -1;
+            bool shouldTerminate = false;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () =>
+            {
+                if (shouldTerminate)
+                {
+                    throw new InvalidOperationException("There should be no more calls at this point.");
+                }
+                if (callCounter++ == 0)
+                {
+                    return now;
+                }
+                // Reach 500 ms after 125 calls.
+                return now.AddMilliseconds(callCounter * 4);
+            };
+
+            long keyWrapIterations = new IterationCalculator().KeyWrapIterations(V2Aes256CryptoFactory.CryptoId);
+
+            Assert.That(keyWrapIterations, Is.EqualTo(12500), "If we do 125000 iterations in 500ms, the result should be 12500 as default iterations.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKeyWrap.cs b/Axantum.AxCrypt.Core.Test/TestKeyWrap.cs
new file mode 100644
index 0000000..2e2d3c7
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKeyWrap.cs
@@ -0,0 +1,165 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKeyWrap
+    {
+        private static SymmetricKey _keyEncryptingKey;
+        private static SymmetricKey _keyData;
+        private static byte[] _wrapped;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            _keyEncryptingKey = new SymmetricKey(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F });
+            _keyData = new SymmetricKey(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF });
+            _wrapped = new byte[] { 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 };
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestUnwrap()
+        {
+            byte[] unwrapped;
+            KeyWrap keyWrap = new KeyWrap(6, KeyWrapMode.Specification);
+            unwrapped = keyWrap.Unwrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), _wrapped);
+
+            Assert.That(unwrapped, Is.EquivalentTo(_keyData.GetBytes()), "Unwrapped the wrong data");
+        }
+
+        [Test]
+        public static void TestWrap()
+        {
+            byte[] wrapped;
+            KeyWrap keyWrap = new KeyWrap(6, KeyWrapMode.Specification);
+            wrapped = keyWrap.Wrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), _keyData);
+
+            Assert.That(wrapped, Is.EquivalentTo(_wrapped), "The wrapped data is not correct according to specification.");
+
+            keyWrap = new KeyWrap(6, KeyWrapMode.Specification);
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                wrapped = keyWrap.Wrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), (SymmetricKey)null);
+            });
+        }
+
+        [Test]
+        public static void TestWrapAndUnwrapAxCryptMode()
+        {
+            SymmetricKey keyToWrap = new SymmetricKey(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
+            Salt salt = new Salt(new byte[] { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 });
+            long keyWrapIterations = 12345;
+            byte[] wrapped;
+            KeyWrap keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.AxCrypt);
+            wrapped = keyWrap.Wrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), keyToWrap);
+            byte[] unwrapped;
+            keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.AxCrypt);
+            unwrapped = keyWrap.Unwrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), wrapped);
+
+            Assert.That(unwrapped, Is.EquivalentTo(keyToWrap.GetBytes()), "The unwrapped data should be equal to original.");
+        }
+
+        [Test]
+        public static void TestWrapAndUnwrapSpecificationMode()
+        {
+            SymmetricKey keyToWrap = new SymmetricKey(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 });
+            Salt salt = new Salt(new byte[] { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 });
+            long keyWrapIterations = 23456;
+            byte[] wrapped;
+            KeyWrap keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.Specification);
+            wrapped = keyWrap.Wrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), keyToWrap);
+            byte[] unwrapped;
+            keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.Specification);
+            unwrapped = keyWrap.Unwrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), wrapped);
+
+            Assert.That(unwrapped, Is.EquivalentTo(keyToWrap.GetBytes()), "The unwrapped data should be equal to original.");
+        }
+
+        [Test]
+        public static void TestKeyWrapConstructorWithBadArgument()
+        {
+            KeyWrap keyWrap = new KeyWrap(6, KeyWrapMode.Specification);
+            Assert.Throws<InternalErrorException>(() => { keyWrap.Unwrap(new V1AesCrypto(new V1Aes128CryptoFactory(), _keyEncryptingKey, SymmetricIV.Zero128), _keyData.GetBytes()); }, "Calling with too short wrapped data.");
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                keyWrap = new KeyWrap(5, KeyWrapMode.AxCrypt);
+            }, "Calling with too few iterations.");
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                keyWrap = new KeyWrap(0, KeyWrapMode.AxCrypt);
+            }, "Calling with zero (too few) iterations.");
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                keyWrap = new KeyWrap(-100, KeyWrapMode.AxCrypt);
+            }, "Calling with negative number of iterations.");
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                keyWrap = new KeyWrap(6, (KeyWrapMode)9999);
+            }, "Calling with bogus KeyWrapMode.");
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                keyWrap = new KeyWrap(null, 6, KeyWrapMode.Specification);
+            }, "Calling with null salt argument.");
+        }
+
+        [Test]
+        public static void TestUnwrapWithBadArgument()
+        {
+            KeyWrap keyWrap = new KeyWrap(100, KeyWrapMode.Specification);
+            Assert.Throws<InternalErrorException>(() => keyWrap.Unwrap(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0), new byte[25]));
+        }
+
+        [Test]
+        public static void TestWrapWithBadArgument()
+        {
+            KeyWrap keyWrap = new KeyWrap(100, KeyWrapMode.Specification);
+            {
+                byte[] nullKeyMaterial = null;
+                Assert.Throws<ArgumentNullException>(() => keyWrap.Wrap(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0), nullKeyMaterial));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKeyWrap1HeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestKeyWrap1HeaderBlock.cs
new file mode 100644
index 0000000..0323d65
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKeyWrap1HeaderBlock.cs
@@ -0,0 +1,102 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKeyWrap1HeaderBlock
+    {
+        private class KeyWrap1HeaderBlockForTest : V1KeyWrap1HeaderBlock
+        {
+            public KeyWrap1HeaderBlockForTest(SymmetricKey key)
+                : base(key, 13)
+            {
+            }
+
+            public void SetValuesDirect(byte[] wrapped, Salt salt, long keyWrapIterations)
+            {
+                Set(wrapped, salt, keyWrapIterations);
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSetBadArguments()
+        {
+            KeyWrap1HeaderBlockForTest keyWrap1HeaderBlock = new KeyWrap1HeaderBlockForTest(new V1DerivedKey(new Passphrase("passphrase")).DerivedKey);
+
+            Salt okSalt = new Salt(128);
+            Salt badSalt = new Salt(256);
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(null, okSalt, 100);
+            });
+
+            Assert.Throws<ArgumentException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(new byte[0], okSalt, 100);
+            });
+
+            Assert.Throws<ArgumentException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(new byte[16], okSalt, 100);
+            });
+
+            Assert.Throws<ArgumentException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(new byte[32], okSalt, 100);
+            });
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(new byte[24], null, 100);
+            });
+
+            Assert.Throws<ArgumentException>(() =>
+            {
+                keyWrap1HeaderBlock.SetValuesDirect(new byte[24], badSalt, 100);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKeyWrap2HeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestKeyWrap2HeaderBlock.cs
new file mode 100644
index 0000000..e2dc398
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKeyWrap2HeaderBlock.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKeyWrap2HeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            V1KeyWrap2HeaderBlock keyWrap2HeaderBlock = new V1KeyWrap2HeaderBlock(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            V1KeyWrap2HeaderBlock cloned = (V1KeyWrap2HeaderBlock)keyWrap2HeaderBlock.Clone();
+            Assert.That(keyWrap2HeaderBlock, Is.Not.SameAs(cloned), "The clone should not be the same reference.");
+            Assert.That(cloned.GetDataBlockBytes(), Is.EquivalentTo(keyWrap2HeaderBlock.GetDataBlockBytes()), "The clone should have equivalent data block bytes as the original.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKnownFolder.cs b/Axantum.AxCrypt.Core.Test/TestKnownFolder.cs
new file mode 100644
index 0000000..7e15fb6
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKnownFolder.cs
@@ -0,0 +1,108 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Drawing;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKnownFolder
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new FakeRuntimeFileInfo(path));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestNormalConstructor()
+        {
+            Bitmap image = new Bitmap(32, 32);
+            Uri providerUrl = new Uri("http://localhost/AxCrypt/");
+
+            KnownFolder kf = new KnownFolder(@"C:\Users\AxCrypt\My Documents", @"AxCrypt", image, providerUrl);
+            Assert.That(kf.RootFullPath.FullName, Is.EqualTo(@"C:\Users\AxCrypt\My Documents".NormalizeFolderPath()));
+            Assert.That(kf.MyFullPath.FullName, Is.EqualTo(@"C:\Users\AxCrypt\My Documents\AxCrypt".NormalizeFolderPath()));
+            Assert.That(kf.Image, Is.EqualTo(image));
+            Assert.That(kf.ProviderUrl, Is.EqualTo(providerUrl));
+            Assert.That(kf.Enabled, Is.False);
+        }
+
+        [Test]
+        public static void TestCopyConstructor()
+        {
+            Bitmap image = new Bitmap(32, 32);
+            Uri providerUrl = new Uri("http://localhost/AxCrypt/");
+
+            KnownFolder kf = new KnownFolder(@"C:\Users\AxCrypt\My Documents", @"AxCrypt", image, providerUrl);
+            KnownFolder kfCopy = new KnownFolder(kf, true);
+
+            Assert.That(kfCopy.RootFullPath.FullName, Is.EqualTo(@"C:\Users\AxCrypt\My Documents".NormalizeFolderPath()));
+            Assert.That(kfCopy.MyFullPath.FullName, Is.EqualTo(@"C:\Users\AxCrypt\My Documents\AxCrypt".NormalizeFolderPath()));
+            Assert.That(kfCopy.Image, Is.EqualTo(image));
+            Assert.That(kfCopy.ProviderUrl, Is.EqualTo(providerUrl));
+            Assert.That(kfCopy.Enabled, Is.True);
+        }
+
+        [Test]
+        public static void TestBadArgumentsToConstructor()
+        {
+            Bitmap image = new Bitmap(32, 32);
+            Uri providerUrl = new Uri("http://localhost/AxCrypt/");
+
+            Bitmap nullImage = null;
+            Uri nullUrl = null;
+            string nullString = null;
+
+            KnownFolder kf;
+
+            Assert.Throws<ArgumentNullException>(() => kf = new KnownFolder(nullString, @"AxCrypt", image, providerUrl));
+            Assert.Throws<ArgumentNullException>(() => kf = new KnownFolder(@"C:\Users\AxCrypt\My Documents", nullString, image, providerUrl));
+            Assert.Throws<ArgumentNullException>(() => kf = new KnownFolder(@"C:\Users\AxCrypt\My Documents", @"AxCrypt", nullImage, providerUrl));
+            Assert.DoesNotThrow(() => kf = new KnownFolder(@"C:\Users\AxCrypt\My Documents", @"AxCrypt", image, nullUrl));
+            kf = null;
+            Assert.Throws<ArgumentNullException>(() => kf = new KnownFolder(kf, true));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKnownFoldersViewModel.cs b/Axantum.AxCrypt.Core.Test/TestKnownFoldersViewModel.cs
new file mode 100644
index 0000000..305a788
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKnownFoldersViewModel.cs
@@ -0,0 +1,145 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using NUnit.Framework;
+using System;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKnownFoldersViewModel
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructor()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            KnownFoldersViewModel vm = new KnownFoldersViewModel(Instance.FileSystemState, Instance.SessionNotify, knownKeys);
+
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestSettingKnownFoldersAndLoggingOnAndOff()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            KnownFoldersViewModel vm = new KnownFoldersViewModel(Instance.FileSystemState, Instance.SessionNotify, knownKeys);
+
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(0));
+
+            KnownFolder folder1 = new KnownFolder(@"C:\BetterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            KnownFolder folder2 = new KnownFolder(@"C:\FasterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            FakeRuntimeFileInfo.AddFolder(folder1.MyFullPath.FullName);
+            FakeRuntimeFileInfo.AddFolder(folder2.MyFullPath.FullName);
+
+            vm.KnownFolders = new KnownFolder[] { folder1, folder2 };
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.False);
+
+            knownKeys.DefaultEncryptionKey = new Passphrase("aaa");
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.True);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.True);
+
+            knownKeys.DefaultEncryptionKey = null;
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.False);
+        }
+
+        [Test]
+        public static void TestAlreadyKnownFoldersAndLoggingOn()
+        {
+            KnownFolder folder1 = new KnownFolder(@"C:\BetterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            KnownFolder folder2 = new KnownFolder(@"C:\FasterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            FakeRuntimeFileInfo.AddFolder(folder1.MyFullPath.FullName);
+            FakeRuntimeFileInfo.AddFolder(folder2.MyFullPath.FullName);
+
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(folder1.MyFullPath.FullName, new Passphrase("PassPhrase").Thumbprint));
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(folder2.MyFullPath.FullName, new Passphrase("aaa").Thumbprint));
+
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            KnownFoldersViewModel vm = new KnownFoldersViewModel(Instance.FileSystemState, Instance.SessionNotify, knownKeys);
+
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(0));
+
+            vm.KnownFolders = new KnownFolder[] { folder1, folder2 };
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.False);
+
+            knownKeys.DefaultEncryptionKey = new Passphrase("aaa");
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.True);
+        }
+
+        [Test]
+        public static void TestFileWasCreatedWhereAKnownFolderWasExpected()
+        {
+            KnownFolder folder1 = new KnownFolder(@"C:\BetterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            KnownFolder folder2 = new KnownFolder(@"C:\FasterCloud", @"My AxCrypt", new Bitmap(10, 10), null);
+            FakeRuntimeFileInfo.AddFile(folder1.MyFullPath.FullName, Stream.Null);
+            FakeRuntimeFileInfo.AddFolder(folder2.MyFullPath.FullName);
+
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            KnownFoldersViewModel vm = new KnownFoldersViewModel(Instance.FileSystemState, Instance.SessionNotify, knownKeys);
+
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(0));
+
+            vm.KnownFolders = new KnownFolder[] { folder1, folder2 };
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.False);
+
+            knownKeys.DefaultEncryptionKey = new Passphrase("aaa");
+            Assert.That(Instance.FileSystemState.WatchedFolders.Count(), Is.EqualTo(1));
+            Assert.That(vm.KnownFolders.Count(), Is.EqualTo(2));
+            Assert.That(vm.KnownFolders.First().Enabled, Is.False);
+            Assert.That(vm.KnownFolders.Last().Enabled, Is.True);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestKnownKeys.cs b/Axantum.AxCrypt.Core.Test/TestKnownKeys.cs
new file mode 100644
index 0000000..3ad5b4b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestKnownKeys.cs
@@ -0,0 +1,218 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestKnownKeys
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+            Factory.Instance.Singleton<FileSystemState>(() => new FileSystemState());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAddNewKnownKey()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase passphrase = new Passphrase("a");
+            knownKeys.Add(passphrase);
+            Assert.That(knownKeys.Keys.First(), Is.EqualTo(passphrase), "The first and only key should be the one just added.");
+        }
+
+        [Test]
+        public static void TestAddTwoNewKnownKeys()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase key1 = new Passphrase("key1");
+            knownKeys.Add(key1);
+            Passphrase key2 = new Passphrase("key2");
+            knownKeys.Add(key2);
+            Assert.That(knownKeys.Keys.First(), Is.EqualTo(key2), "The first key should be the last one added.");
+            Assert.That(knownKeys.Keys.Last(), Is.EqualTo(key1), "The last key should be the first one added.");
+        }
+
+        [Test]
+        public static void TestAddSameKeyTwice()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase key = new Passphrase(String.Empty);
+            knownKeys.Add(key);
+            knownKeys.Add(key);
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(1), "Only one key should be in the collection even if added twice.");
+            Assert.That(knownKeys.Keys.First(), Is.EqualTo(key), "The first and only key should be the one just added.");
+        }
+
+        [Test]
+        public static void TestDefaultEncryptionKey()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase key = new Passphrase(String.Empty);
+            knownKeys.DefaultEncryptionKey = key;
+            Assert.That(knownKeys.DefaultEncryptionKey, Is.EqualTo(key), "The DefaultEncryptionKey should be the one just set as it.");
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(1), "Only one key should be in the collection.");
+            Assert.That(knownKeys.Keys.First(), Is.EqualTo(key), "The first and only key should be the one just set as DefaultEncryptionKey.");
+        }
+
+        [Test]
+        public static void TestClear()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase key1 = new Passphrase("key1");
+            knownKeys.Add(key1);
+            Passphrase key2 = new Passphrase("key2");
+            knownKeys.Add(key2);
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(2), "There should be two keys in the collection.");
+
+            knownKeys.Clear();
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(0), "There should be zero keys in the collection after Clear().");
+
+            knownKeys.Clear();
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(0), "There should be zero keys in the collection after Clear() with zero keys to start with.");
+        }
+
+        [Test]
+        public static void TestSettingNullDefaultEncryptionKey()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            Passphrase key1 = new Passphrase("a");
+            knownKeys.Add(key1);
+            Passphrase key2 = new Passphrase("B");
+            knownKeys.DefaultEncryptionKey = key2;
+
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(2), "Setting the DefaultEncryptionKey should also add it as a known key.");
+
+            knownKeys.DefaultEncryptionKey = null;
+            Assert.That(knownKeys.Keys.Count(), Is.EqualTo(2), "Setting the DefaultEncryptionKey to null should not affect the known keys.");
+        }
+
+        [Test]
+        public static void TestChangedEvent()
+        {
+            bool wasChanged = false;
+            SessionNotify notificationMonitor = new SessionNotify();
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, notificationMonitor);
+            notificationMonitor.Notification += (object sender, SessionNotificationEventArgs e) =>
+            {
+                wasChanged |= e.Notification.NotificationType == SessionNotificationType.KnownKeyChange;
+            };
+            Passphrase key1 = Passphrase.Empty;
+            knownKeys.Add(key1);
+            Assert.That(wasChanged, Is.True, "A new key should trigger the Changed event.");
+            wasChanged = false;
+            knownKeys.Add(key1);
+            Assert.That(wasChanged, Is.False, "Re-adding an existing key should not trigger the Changed event.");
+        }
+
+        [Test]
+        public static void TestLoggingOffWhenLoggingOnWhenAlreadyLoggedOn()
+        {
+            int wasLoggedOnCount = 0;
+            int wasLoggedOffCount = 0;
+            SessionNotify notificationMonitor = new SessionNotify();
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, notificationMonitor);
+            notificationMonitor.Notification += (object sender, SessionNotificationEventArgs e) =>
+            {
+                if (e.Notification.NotificationType == SessionNotificationType.LogOn)
+                {
+                    Assert.That(knownKeys.IsLoggedOn, Is.True, "The state of the IsLoggedOn property should be consistent with the event.");
+                    ++wasLoggedOnCount;
+                }
+                if (e.Notification.NotificationType == SessionNotificationType.LogOff)
+                {
+                    Assert.That(knownKeys.IsLoggedOn, Is.False, "The state of the IsLoggedOn property should be consistent with the event.");
+                    ++wasLoggedOffCount;
+                }
+            };
+
+            knownKeys.DefaultEncryptionKey = new Passphrase("passphrase1");
+            Assert.That(wasLoggedOnCount, Is.EqualTo(1));
+            Assert.That(wasLoggedOffCount, Is.EqualTo(0));
+            Assert.That(knownKeys.IsLoggedOn, Is.True);
+
+            knownKeys.DefaultEncryptionKey = new Passphrase("passphrase");
+            Assert.That(wasLoggedOnCount, Is.EqualTo(2));
+            Assert.That(wasLoggedOffCount, Is.EqualTo(1));
+            Assert.That(knownKeys.IsLoggedOn, Is.True);
+        }
+
+        [Test]
+        public static void TestAddKeyForKnownIdentity()
+        {
+            Instance.FileSystemState.Identities.Add(new PassphraseIdentity(new Passphrase("a")));
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            knownKeys.Add(new Passphrase("a"));
+
+            Assert.That(knownKeys.DefaultEncryptionKey.Equals(new Passphrase("a")), "When adding a key that is for a known identity it should be set as the default.");
+        }
+
+        [Test]
+        public static void TestWatchedFoldersNotLoggedOn()
+        {
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            FakeRuntimeFileInfo.AddFolder(@"C:\WatchedFolder\");
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\WatchedFolder\"));
+            IEnumerable<WatchedFolder> watchedFolders = knownKeys.LoggedOnWatchedFolders;
+
+            Assert.That(watchedFolders.Count(), Is.EqualTo(0), "When not logged on, no watched folders should be known.");
+        }
+
+        [Test]
+        public static void TestWatchedFoldersWhenLoggedOn()
+        {
+            Passphrase key1 = new Passphrase("a");
+            Passphrase key2 = new Passphrase("b");
+            KnownKeys knownKeys = new KnownKeys(Instance.FileSystemState, Instance.SessionNotify);
+            FakeRuntimeFileInfo.AddFolder(@"C:\WatchedFolder1\");
+            FakeRuntimeFileInfo.AddFolder(@"C:\WatchedFolder2\");
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\WatchedFolder1\", key1.Thumbprint));
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\WatchedFolder2\", key2.Thumbprint));
+            knownKeys.DefaultEncryptionKey = key2;
+            IEnumerable<WatchedFolder> watchedFolders = knownKeys.LoggedOnWatchedFolders;
+
+            Assert.That(watchedFolders.Count(), Is.EqualTo(1), "Only one of the two watched folders should be shown.");
+            Assert.That(watchedFolders.First().Thumbprint, Is.EqualTo(key2.Thumbprint), "The returned watched folder should be number 2.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestLockingStreamTests.cs b/Axantum.AxCrypt.Core.Test/TestLockingStreamTests.cs
new file mode 100644
index 0000000..4a92569
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestLockingStreamTests.cs
@@ -0,0 +1,103 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Test.Properties;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestLockingStreamTests
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.CurrentDirectory);
+        private static readonly string _davidCopperfieldTxtPath = _rootPath.PathCombine("Users", "AxCrypt", "David Copperfield.txt");
+        private static readonly string _uncompressedAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Uncompressed.axx");
+        private static readonly string _helloWorldAxxPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "HelloWorld.axx");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            FakeRuntimeFileInfo.AddFile(_davidCopperfieldTxtPath, FakeRuntimeFileInfo.TestDate4Utc, FakeRuntimeFileInfo.TestDate5Utc, FakeRuntimeFileInfo.TestDate6Utc, FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.GetEncoding(1252).GetBytes(Resources.david_copperfield)));
+            FakeRuntimeFileInfo.AddFile(_uncompressedAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.uncompressable_zip));
+            FakeRuntimeFileInfo.AddFile(_helloWorldAxxPath, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimple()
+        {
+            using (MemoryStream stream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("A short dummy stream")))
+            {
+                IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(_davidCopperfieldTxtPath);
+                using (LockingStream lockingStream = new LockingStream(fileInfo, stream))
+                {
+                    Assert.That(FileLock.IsLocked(fileInfo), "The file should be locked now.");
+                    Assert.That(lockingStream.CanRead, "The stream should be readable.");
+                    Assert.That(lockingStream.CanSeek, "The stream should be seekable.");
+                    Assert.That(lockingStream.CanWrite, "The stream should be writeable.");
+                    Assert.That(lockingStream.Length, Is.EqualTo("A short dummy stream".Length), "The length should be the same as the string.");
+
+                    byte[] b = new byte[1];
+                    int read = lockingStream.Read(b, 0, 1);
+                    Assert.That(read, Is.EqualTo(1), "There should be one byte read.");
+                    Assert.That(b[0], Is.EqualTo(Encoding.UTF8.GetBytes("A")[0]), "The byte read should be an 'A'.");
+                    Assert.That(lockingStream.Position, Is.EqualTo(1), "After reading the first byte, the position should be at one.");
+
+                    lockingStream.Write(b, 0, 1);
+                    lockingStream.Position = 1;
+                    read = lockingStream.Read(b, 0, 1);
+                    Assert.That(read, Is.EqualTo(1), "There should be one byte read.");
+                    Assert.That(b[0], Is.EqualTo(Encoding.UTF8.GetBytes("A")[0]), "The byte read should be an 'A'.");
+
+                    lockingStream.Seek(-1, SeekOrigin.End);
+                    Assert.That(lockingStream.Position, Is.EqualTo(lockingStream.Length - 1), "The position should be set by the Seek().");
+
+                    lockingStream.SetLength(5);
+                    lockingStream.Seek(0, SeekOrigin.End);
+                    Assert.That(lockingStream.Position, Is.EqualTo(5), "After setting the length to 5, seeking to the end should set the position at 5.");
+
+                    Assert.DoesNotThrow(() => { lockingStream.Flush(); }, "It's hard to test Flush() behavior here, not worth the trouble, but it should not throw!");
+                }
+                Assert.That(!FileLock.IsLocked(fileInfo), "The file should be unlocked now.");
+                Assert.Throws<ObjectDisposedException>(() => { stream.Position = 0; }, "The underlying stream should be disposed.");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestLogOnViewModel.cs b/Axantum.AxCrypt.Core.Test/TestLogOnViewModel.cs
new file mode 100644
index 0000000..0b501f7
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestLogOnViewModel.cs
@@ -0,0 +1,188 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestLogOnViewModel
+    {
+        private static IList<PassphraseIdentity> _identities;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            _identities = new List<PassphraseIdentity>();
+            Mock<FileSystemState> fileSystemStateMock = new Mock<FileSystemState>();
+            fileSystemStateMock.Setup<IList<PassphraseIdentity>>(f => f.Identities).Returns(_identities);
+            Factory.Instance.Singleton<FileSystemState>(() => fileSystemStateMock.Object);
+
+            Factory.Instance.Register<AxCryptFactory>(() => new AxCryptFactory());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructor()
+        {
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+
+            Assert.That(lovm.Passphrase, Is.EqualTo(""));
+        }
+
+        [Test]
+        public static void TestShowPassphrase()
+        {
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+
+            Assert.That(lovm.ShowPassphrase, Is.False);
+
+            lovm.ShowPassphrase = true;
+
+            Assert.That(lovm.ShowPassphrase, Is.True);
+        }
+
+        [Test]
+        public static void TestValidatePropertyThatCannotBeValidated()
+        {
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+            string s = null;
+            Assert.Throws<ArgumentException>(() => { s = lovm["ShowPassphrase"]; });
+            Assert.That(s, Is.Null, "Not a real assertion, only to make the variable used for FxCop.");
+        }
+
+        [Test]
+        public static void TestValidatePassphraseOk()
+        {
+            Mock<IUserSettings> userSettingsMock = new Mock<IUserSettings>();
+            userSettingsMock.Setup<Salt>(f => f.ThumbprintSalt).Returns(Salt.Zero);
+            userSettingsMock.Setup<long>(f => f.GetKeyWrapIterations(It.IsAny<Guid>())).Returns(10);
+            Factory.Instance.Singleton<IUserSettings>(() => userSettingsMock.Object);
+
+            Mock<IRuntimeEnvironment> environmentMock = new Mock<IRuntimeEnvironment>();
+            environmentMock.Setup<bool>(f => f.IsLittleEndian).Returns(true);
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => environmentMock.Object);
+
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+
+            _identities.Add(new PassphraseIdentity(new Passphrase("abc1234")));
+
+            lovm.Passphrase = "abc1234";
+
+            Assert.That(lovm["Passphrase"], Is.EqualTo(""));
+            Assert.That(lovm.ValidationError, Is.EqualTo((int)ValidationError.None));
+        }
+
+        [Test]
+        public static void TestValidatePassphraseNotOk()
+        {
+            Mock<IUserSettings> userSettingsMock = new Mock<IUserSettings>();
+            userSettingsMock.Setup<Salt>(f => f.ThumbprintSalt).Returns(Salt.Zero);
+            userSettingsMock.Setup<long>(f => f.GetKeyWrapIterations(It.IsAny<Guid>())).Returns(10);
+            Factory.Instance.Singleton<IUserSettings>(() => userSettingsMock.Object);
+
+            Mock<IRuntimeEnvironment> environmentMock = new Mock<IRuntimeEnvironment>();
+            environmentMock.Setup<bool>(f => f.IsLittleEndian).Returns(true);
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => environmentMock.Object);
+
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+
+            _identities.Add(new PassphraseIdentity(new Passphrase("abc1234")));
+
+            lovm.Passphrase = "abc12345";
+
+            Assert.That(lovm["Passphrase"], Is.Not.EqualTo(""));
+            Assert.That(lovm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
+        }
+
+        [Test]
+        public static void TestValidateNonExistingPropertyName()
+        {
+            LogOnViewModel lovm = new LogOnViewModel(String.Empty);
+            string s = null;
+            Assert.Throws<ArgumentException>(() => { s = lovm["NonExisting"]; });
+            Assert.That(s, Is.Null, "Not a real assertion, only to make the variable used for FxCop.");
+        }
+
+        [Test]
+        public static void TestValidateWrongPassphraseWithRealFile()
+        {
+            _identities.Add(new PassphraseIdentity(new Passphrase("a")));
+
+            FakeRuntimeFileInfo.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
+            LogOnViewModel npvm = new LogOnViewModel(@"C:\My Folder\MyFile-txt.axx");
+            npvm.Passphrase = "b";
+
+            Assert.That(npvm["Passphrase"], Is.Not.EqualTo(""));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
+        }
+
+        [Test]
+        public static void TestValidateCorrectPassphraseWithRealFile()
+        {
+            _identities.Add(new PassphraseIdentity(new Passphrase("a")));
+
+            FakeRuntimeFileInfo.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
+            LogOnViewModel npvm = new LogOnViewModel(@"C:\My Folder\MyFile-txt.axx");
+            npvm.Passphrase = "a";
+
+            Assert.That(npvm["Passphrase"], Is.EqualTo(""));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.None));
+        }
+
+        [Test]
+        public static void TestValidateWrongButKnownPassphraseWithRealFile()
+        {
+            _identities.Add(new PassphraseIdentity(new Passphrase("b")));
+
+            FakeRuntimeFileInfo.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
+            LogOnViewModel npvm = new LogOnViewModel(@"C:\My Folder\MyFile-txt.axx");
+            npvm.Passphrase = "b";
+
+            Assert.That(npvm["Passphrase"], Is.Not.EqualTo(String.Empty));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestLogging.cs b/Axantum.AxCrypt.Core.Test/TestLogging.cs
new file mode 100644
index 0000000..595964d
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestLogging.cs
@@ -0,0 +1,62 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestLogging
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimpleLogging()
+        {
+            string s = null;
+            Instance.Log.Logged += (sender, e) =>
+            {
+                s = e.Message;
+            };
+
+            Instance.Log.LogError("A Logging Message");
+            Assert.That(s, Is.EqualTo("A Logging Message"));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestMainViewModel.cs b/Axantum.AxCrypt.Core.Test/TestMainViewModel.cs
new file mode 100644
index 0000000..e2544a3
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestMainViewModel.cs
@@ -0,0 +1,585 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Net.Security;
+using System.Text.RegularExpressions;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestMainViewModel
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new ParallelFileOperation());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestOpenSelectedFolderAction()
+        {
+            string filePath = @"C:\Folder\File.txt";
+
+            var mockEnvironment = new Mock<FakeRuntimeEnvironment>() { CallBase = true };
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => mockEnvironment.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.OpenSelectedFolder.Execute(filePath);
+            }
+            mockEnvironment.Verify(r => r.Launch(filePath));
+        }
+
+        [Test]
+        public static void TestCurrentVersionPropertyBind()
+        {
+            UpdateCheck mockedUpdateCheck = null;
+            Factory.Instance.Register<Version, UpdateCheck>((version) => mockedUpdateCheck = new Mock<UpdateCheck>(version).Object);
+            Version ourVersion = new Version(1, 2, 3, 4);
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.CurrentVersion = ourVersion;
+            }
+
+            Mock.Get<UpdateCheck>(mockedUpdateCheck).Verify(x => x.CheckInBackground(It.Is<DateTime>((d) => d == Instance.UserSettings.LastUpdateCheckUtc), It.IsAny<string>(), It.IsAny<Uri>(), It.IsAny<Uri>()));
+        }
+
+        [Test]
+        public static void TestUpdateCheckWhenNotExecutable()
+        {
+            var mockUpdateCheck = new Mock<UpdateCheck>(new Version(1, 2, 3, 4));
+            Factory.Instance.Register<Version, UpdateCheck>((version) => mockUpdateCheck.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.UpdateCheck.CanExecute(null), Is.False);
+                Assert.Throws<InvalidOperationException>(() => mvm.UpdateCheck.Execute(new DateTime(2001, 2, 3)));
+            }
+        }
+
+        [Test]
+        public static void TestUpdateCheckWhenExecutable()
+        {
+            Version ourVersion = new Version(1, 2, 3, 4);
+            var mockUpdateCheck = new Mock<UpdateCheck>(ourVersion);
+            Factory.Instance.Register<Version, UpdateCheck>((version) => mockUpdateCheck.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.CurrentVersion = ourVersion;
+                Assert.That(mvm.UpdateCheck.CanExecute(null), Is.True);
+                mvm.UpdateCheck.Execute(new DateTime(2001, 2, 3));
+            }
+
+            mockUpdateCheck.Verify(x => x.CheckInBackground(It.Is<DateTime>(d => d == new DateTime(2001, 2, 3)), It.IsAny<string>(), It.IsAny<Uri>(), It.IsAny<Uri>()));
+        }
+
+        [Test]
+        public static void TestVersionUpdate()
+        {
+            Version ourVersion = new Version(1, 2, 3, 4);
+            var mockUpdateCheck = new Mock<UpdateCheck>(ourVersion);
+            Factory.Instance.Register<Version, UpdateCheck>((version) => mockUpdateCheck.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.CurrentVersion = ourVersion;
+
+                mockUpdateCheck.Raise(m => m.VersionUpdate += null, new VersionEventArgs(new Version(1, 2, 4, 4), new Uri("http://localhost/"), VersionUpdateStatus.NewerVersionIsAvailable));
+                Assert.That(mvm.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.NewerVersionIsAvailable));
+            }
+        }
+
+        [Test]
+        public static void TestDragAndDropFilesPropertyBindSetsDragAndDropFileTypes()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                string encryptedFilePath = @"C:\Folder\File-txt.axx";
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.None));
+
+                string decryptedFilePath = @"C:\Folder\File.txt";
+                mvm.DragAndDropFiles = new string[] { decryptedFilePath, };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.None));
+
+                FakeRuntimeFileInfo.AddFile(encryptedFilePath, null);
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptedFile));
+
+                FakeRuntimeFileInfo.AddFile(decryptedFilePath, null);
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));
+
+                string folderPath = @"C:\Folder\";
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, folderPath };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));
+
+                FakeRuntimeFileInfo.AddFolder(folderPath);
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, decryptedFilePath, folderPath };
+                Assert.That(mvm.DragAndDropFilesTypes, Is.EqualTo(FileInfoTypes.EncryptableFile | FileInfoTypes.EncryptedFile));
+            }
+        }
+
+        [Test]
+        public static void TestDragAndDropFilesPropertyBindSetsDroppableAsRecent()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                string encryptedFilePath = @"C:\Folder\File-txt.axx";
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.False, "An encrypted file that does not exist is not a candidate for recent.");
+
+                PassphraseIdentity id = new PassphraseIdentity(new Passphrase("passphrase1"));
+                Instance.FileSystemState.Identities.Add(id);
+                Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.False, "An encrypted file that does not exist, even when logged on, is not droppable as recent.");
+
+                FakeRuntimeFileInfo.AddFile(encryptedFilePath, null);
+                Instance.KnownKeys.DefaultEncryptionKey = null;
+                mvm.DragAndDropFiles = new string[] { encryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.True, "An encrypted file that exist is droppable as recent even when not logged on.");
+
+                string decryptedFilePath = @"C:\Folder\File.txt";
+                mvm.DragAndDropFiles = new string[] { decryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.False, "An encryptable file that does not exist is not droppable as recent.");
+
+                FakeRuntimeFileInfo.AddFile(decryptedFilePath, null);
+                mvm.DragAndDropFiles = new string[] { decryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.False, "An encrpytable file without a valid log on is not droppable as recent.");
+
+                id = new PassphraseIdentity(new Passphrase("passphrase"));
+                Instance.FileSystemState.Identities.Add(id);
+                Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+                mvm.DragAndDropFiles = new string[] { decryptedFilePath, };
+                Assert.That(mvm.DroppableAsRecent, Is.True, "An encryptable existing file with a valid log on should be droppable as recent.");
+            }
+        }
+
+        [Test]
+        public static void TestDragAndDropFilesPropertyBindSetsDroppableAsWatchedFolder()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                string folder1Path = @"C:\Folder1\FilesFolder\".NormalizeFilePath();
+                mvm.DragAndDropFiles = new string[] { folder1Path, };
+                Assert.That(mvm.DroppableAsWatchedFolder, Is.False, "A folder that does not exist is not a candidate for watched folders.");
+
+                FakeRuntimeFileInfo.AddFolder(folder1Path);
+                mvm.DragAndDropFiles = new string[] { folder1Path, };
+                Assert.That(mvm.DroppableAsWatchedFolder, Is.True, "This is a candidate for watched folders.");
+
+                OS.PathFilters.Add(new Regex(@"^C:\{0}Folder1\{0}".InvariantFormat(Path.DirectorySeparatorChar)));
+                mvm.DragAndDropFiles = new string[] { folder1Path, };
+                Assert.That(mvm.DroppableAsWatchedFolder, Is.False, "A folder that matches a path filter is not a candidate for watched folders.");
+
+                string folder2Path = @"C:\Folder1\FilesFolder2\".NormalizeFilePath();
+                FakeRuntimeFileInfo.AddFolder(folder2Path);
+                OS.PathFilters.Clear();
+
+                mvm.DragAndDropFiles = new string[] { folder1Path, folder2Path, };
+                Assert.That(mvm.DroppableAsWatchedFolder, Is.False, "Although both folders are ok, only a single folder is a candidate for watched folders.");
+            }
+        }
+
+        [Test]
+        public static void TestSetRecentFilesComparer()
+        {
+            string file1 = @"C:\Folder\File3-txt.axx";
+            string decrypted1 = @"C:\Folder\File2.txt";
+            string file2 = @"C:\Folder\File2-txt.axx";
+            string decrypted2 = @"C:\Folder\File1.txt";
+            string file3 = @"C:\Folder\File1-txt.axx";
+            string decrypted3 = @"C:\Folder\File3.txt";
+
+            ActiveFile activeFile;
+
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2001, 1, 1);
+            FakeRuntimeFileInfo.AddFile(file1, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file1), Factory.New<IRuntimeFileInfo>(decrypted1), new Passphrase("passphrase1"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2002, 2, 2);
+            FakeRuntimeFileInfo.AddFile(file2, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file2), Factory.New<IRuntimeFileInfo>(decrypted2), new Passphrase("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2003, 3, 3);
+            FakeRuntimeFileInfo.AddFile(file3, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file3), Factory.New<IRuntimeFileInfo>(decrypted3), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            ActiveFileComparer comparer;
+            List<ActiveFile> recentFiles;
+
+            comparer = ActiveFileComparer.DateComparer;
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.RecentFilesComparer = comparer;
+                recentFiles = mvm.RecentFiles.ToList();
+
+                Assert.That(recentFiles[0].EncryptedFileInfo.FullName, Is.EqualTo(file1.NormalizeFilePath()), "Sorted by Date, this should be number 1.");
+                Assert.That(recentFiles[1].EncryptedFileInfo.FullName, Is.EqualTo(file2.NormalizeFilePath()), "Sorted by Date, this should be number 2.");
+                Assert.That(recentFiles[2].EncryptedFileInfo.FullName, Is.EqualTo(file3.NormalizeFilePath()), "Sorted by Date, this should be number 3.");
+
+                comparer = ActiveFileComparer.DateComparer;
+                comparer.ReverseSort = true;
+                mvm.RecentFilesComparer = comparer;
+                recentFiles = mvm.RecentFiles.ToList();
+            }
+
+            Assert.That(recentFiles[0].EncryptedFileInfo.FullName, Is.EqualTo(file3.NormalizeFilePath()), "Sorted by Date in reverse, this should be number 1.");
+            Assert.That(recentFiles[1].EncryptedFileInfo.FullName, Is.EqualTo(file2.NormalizeFilePath()), "Sorted by Date, this should be number 2.");
+            Assert.That(recentFiles[2].EncryptedFileInfo.FullName, Is.EqualTo(file1.NormalizeFilePath()), "Sorted by Date, this should be number 3.");
+        }
+
+        [Test]
+        public static void TestOpenFiles()
+        {
+            string file1 = @"C:\Folder\File3-txt.axx";
+            string decrypted1 = @"C:\Folder\File2.txt";
+            string file2 = @"C:\Folder\File2-txt.axx";
+            string decrypted2 = @"C:\Folder\File1.txt";
+            string file3 = @"C:\Folder\File1-txt.axx";
+            string decrypted3 = @"C:\Folder\File3.txt";
+
+            ActiveFile activeFile;
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2001, 1, 1);
+                FakeRuntimeFileInfo.AddFile(file1, null);
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file1), Factory.New<IRuntimeFileInfo>(decrypted1), new Passphrase("passphrase1"), ActiveFileStatus.AssumedOpenAndDecrypted, new V1Aes128CryptoFactory().Id);
+                Instance.FileSystemState.Add(activeFile);
+
+                FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2002, 2, 2);
+                FakeRuntimeFileInfo.AddFile(file2, null);
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file2), Factory.New<IRuntimeFileInfo>(decrypted2), new Passphrase("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+                Instance.FileSystemState.Add(activeFile);
+
+                FakeRuntimeEnvironment.Instance.TimeFunction = () => new DateTime(2003, 3, 3);
+                FakeRuntimeFileInfo.AddFile(file3, null);
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file3), Factory.New<IRuntimeFileInfo>(decrypted3), new Passphrase("passphrase3"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+                Instance.FileSystemState.Add(activeFile);
+
+                Assert.That(mvm.FilesArePending, Is.True);
+
+                activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file1), Factory.New<IRuntimeFileInfo>(decrypted1), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+                Instance.FileSystemState.Add(activeFile);
+
+                Assert.That(mvm.FilesArePending, Is.False);
+            }
+        }
+
+        [Test]
+        public static void TestRemoveRecentFiles()
+        {
+            var mockFileSystemState = new Mock<FileSystemState>() { CallBase = true };
+            mockFileSystemState.Setup(x => x.Save());
+
+            Factory.Instance.Singleton<FileSystemState>(() => mockFileSystemState.Object);
+
+            string file1 = @"C:\Folder\File3-txt.axx";
+            string decrypted1 = @"C:\Folder\File2.txt";
+            string file2 = @"C:\Folder\File2-txt.axx";
+            string decrypted2 = @"C:\Folder\File1.txt";
+            string file3 = @"C:\Folder\File1-txt.axx";
+            string decrypted3 = @"C:\Folder\File3.txt";
+
+            ActiveFile activeFile;
+
+            FakeRuntimeFileInfo.AddFile(file1, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file1), Factory.New<IRuntimeFileInfo>(decrypted1), new Passphrase("passphrase1"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            FakeRuntimeFileInfo.AddFile(file2, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file2), Factory.New<IRuntimeFileInfo>(decrypted2), new Passphrase("passphrase2"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            FakeRuntimeFileInfo.AddFile(file3, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file3), Factory.New<IRuntimeFileInfo>(decrypted3), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.RemoveRecentFiles.CanExecute(null), Is.True, "RemoveRecentFiles should be executable by default.");
+
+                mvm.RemoveRecentFiles.Execute(new string[] { file2 });
+                mockFileSystemState.Verify(x => x.RemoveActiveFile(It.IsAny<ActiveFile>()), Times.Once, "Exactly one recent file should be removed.");
+
+                mockFileSystemState.ResetCalls();
+                mvm.RemoveRecentFiles.Execute(new string[] { file2 });
+            }
+            mockFileSystemState.Verify(x => x.RemoveActiveFile(It.IsAny<ActiveFile>()), Times.Never, "There is no longer any matching file, so no call to remove should happen.");
+        }
+
+        [Test]
+        public static void TestPurgeRecentFiles()
+        {
+            var mockActiveFileAction = new Mock<ActiveFileAction>();
+
+            Factory.Instance.Register<ActiveFileAction>(() => mockActiveFileAction.Object);
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            Factory.Instance.Register<SessionNotificationHandler>(() => new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), Factory.New<AxCryptFile>(), mockStatusChecker.Object));
+            Instance.SessionNotify.Notification += (sender, e) => Factory.New<SessionNotificationHandler>().HandleNotification(e.Notification);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.EncryptPendingFiles.CanExecute(null), Is.True, "PuregRecentFiles should be executable by default.");
+
+                mvm.EncryptPendingFiles.Execute(null);
+            }
+
+            mockActiveFileAction.Verify(x => x.PurgeActiveFiles(It.IsAny<IProgressContext>()), Times.Once, "Purge should be called.");
+        }
+
+        [Test]
+        public static void TestClearPassphraseMemory()
+        {
+            string file1 = @"C:\Folder\File3-txt.axx";
+            string decrypted1 = @"C:\Folder\File2.txt";
+
+            ActiveFile activeFile;
+
+            FakeRuntimeFileInfo.AddFile(file1, null);
+            activeFile = new ActiveFile(Factory.New<IRuntimeFileInfo>(file1), Factory.New<IRuntimeFileInfo>(decrypted1), new Passphrase("passphrase1"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            Instance.FileSystemState.Add(activeFile);
+
+            Instance.KnownKeys.Add(new Passphrase("passphrase2"));
+            PassphraseIdentity id = new PassphraseIdentity(new Passphrase("passphrase"));
+            Instance.FileSystemState.Identities.Add(id);
+            Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+            Assert.That(Instance.FileSystemState.ActiveFileCount, Is.EqualTo(1), "One ActiveFile is expected.");
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(2), "Two known keys are expected.");
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey, Is.Not.Null, "There should be a non-null default encryption key");
+
+            var sessionNotificationMonitorMock = new Mock<SessionNotify>();
+            Factory.Instance.Singleton<SessionNotify>(() => sessionNotificationMonitorMock.Object);
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                mvm.ClearPassphraseMemory.Execute(null);
+            }
+
+            Assert.That(Instance.FileSystemState.ActiveFileCount, Is.EqualTo(0));
+            Assert.That(Instance.KnownKeys.Keys.Count(), Is.EqualTo(0));
+            Assert.That(Instance.KnownKeys.DefaultEncryptionKey, Is.Null);
+
+            sessionNotificationMonitorMock.Verify(x => x.Notify(It.Is<SessionNotification>(sn => sn.NotificationType == SessionNotificationType.SessionStart)), Times.Once);
+        }
+
+        [Test]
+        public static void TestRemoveWatchedFolders()
+        {
+            var mockFileSystemState = new Mock<FileSystemState>() { CallBase = true };
+            mockFileSystemState.Setup(x => x.Save());
+
+            Factory.Instance.Singleton<FileSystemState>(() => mockFileSystemState.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                PassphraseIdentity id = new PassphraseIdentity(new Passphrase("passphrase"));
+                mockFileSystemState.Object.Identities.Add(id);
+                Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+                mvm.RemoveWatchedFolders.Execute(new string[] { "File1.txt", "file2.txt" });
+            }
+
+            mockFileSystemState.Verify(x => x.RemoveWatchedFolder(It.IsAny<IRuntimeFileInfo>()), Times.Exactly(2));
+            mockFileSystemState.Verify(x => x.Save(), Times.Once);
+        }
+
+        [Test]
+        public static void TestAddAndRemoveWatchedFolderState()
+        {
+            var fileSystemStateMock = new Mock<FileSystemState>() { CallBase = true };
+            fileSystemStateMock.Setup(x => x.Save());
+
+            Factory.Instance.Singleton<FileSystemState>(() => fileSystemStateMock.Object);
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.Throws<InvalidOperationException>(() => mvm.RemoveWatchedFolders.Execute(new string[] { }));
+
+                PassphraseIdentity id = new PassphraseIdentity(new Passphrase("passphrase"));
+                fileSystemStateMock.Object.Identities.Add(id);
+                Instance.KnownKeys.DefaultEncryptionKey = id.Key;
+
+                mvm.RemoveWatchedFolders.Execute(new string[] { });
+
+                fileSystemStateMock.Verify(x => x.RemoveWatchedFolder(It.IsAny<IRuntimeFileInfo>()), Times.Never);
+                fileSystemStateMock.Verify(x => x.Save(), Times.Never);
+
+                fileSystemStateMock.ResetCalls();
+                mvm.AddWatchedFolders.Execute(new string[] { });
+                fileSystemStateMock.Verify(x => x.AddWatchedFolder(It.IsAny<WatchedFolder>()), Times.Never);
+                fileSystemStateMock.Verify(x => x.Save(), Times.Never);
+
+                mvm.AddWatchedFolders.Execute(new string[] { @"C:\Folder1\", @"C:\Folder2\" });
+
+                fileSystemStateMock.Verify(x => x.AddWatchedFolder(It.IsAny<WatchedFolder>()), Times.Exactly(2));
+                fileSystemStateMock.Verify(x => x.Save(), Times.Once);
+
+                fileSystemStateMock.ResetCalls();
+                mvm.RemoveWatchedFolders.Execute(new string[] { @"C:\Folder1\" });
+            }
+
+            fileSystemStateMock.Verify(x => x.RemoveWatchedFolder(It.IsAny<IRuntimeFileInfo>()), Times.Exactly(1));
+            fileSystemStateMock.Verify(x => x.Save(), Times.Once);
+        }
+
+        [Test]
+        public static void TestSetDefaultEncryptionKeyWithoutIdentity()
+        {
+            var fileSystemStateMock = new Mock<FileSystemState>() { CallBase = true };
+            fileSystemStateMock.Setup(x => x.Save());
+
+            Factory.Instance.Singleton<FileSystemState>(() => fileSystemStateMock.Object);
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+            }
+            Assert.Throws<InvalidOperationException>(() => Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("passphrase"), "Should fail since there is no matching identity.");
+        }
+
+        [Test]
+        public static void TestSetDebugMode()
+        {
+            var fileSystemStateMock = new Mock<FileSystemState>();
+            var logMock = new Mock<ILogging>();
+
+            Factory.Instance.Singleton<FileSystemState>(() => fileSystemStateMock.Object);
+            Factory.Instance.Singleton<ILogging>(() => logMock.Object);
+
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                logMock.ResetCalls();
+
+                mvm.DebugMode = true;
+                logMock.Verify(x => x.SetLevel(It.Is<LogLevel>(ll => ll == LogLevel.Debug)));
+                Assert.That(FakeRuntimeEnvironment.Instance.IsDebugModeEnabled, Is.True);
+
+                logMock.ResetCalls();
+
+                mvm.DebugMode = false;
+            }
+            logMock.Verify(x => x.SetLevel(It.Is<LogLevel>(ll => ll == LogLevel.Error)));
+            Assert.That(FakeRuntimeEnvironment.Instance.IsDebugModeEnabled, Is.False);
+        }
+
+        [Test]
+        public static void TestSelectedRecentFiles()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.SelectedRecentFiles.Any(), Is.False);
+
+                mvm.SelectedRecentFiles = new string[] { @"C:\Folder\Test1.axx", @"C:\Folder\Test2.axx" };
+
+                Assert.That(mvm.SelectedRecentFiles.Count(), Is.EqualTo(2));
+            }
+        }
+
+        [Test]
+        public static void TestSelectedWatchedFolders()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.SelectedWatchedFolders.Any(), Is.False);
+
+                mvm.SelectedWatchedFolders = new string[] { @"C:\Folder1\", @"C:\Folder2\" };
+
+                Assert.That(mvm.SelectedWatchedFolders.Count(), Is.EqualTo(2));
+            }
+        }
+
+        [Test]
+        public static void TestTitle()
+        {
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.Title.Length, Is.EqualTo(0));
+
+                mvm.Title = "AxCrypt Title";
+
+                Assert.That(mvm.Title, Is.EqualTo("AxCrypt Title"));
+            }
+        }
+
+        [Test]
+        public static void TestNotifyWatchedFolderAdded()
+        {
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("passphrase");
+            FakeRuntimeFileInfo.AddFolder(@"C:\MyFolders\Folder1");
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.WatchedFolders.Count(), Is.EqualTo(0));
+
+                Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\MyFolders\Folder1", Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+
+                Assert.That(mvm.WatchedFolders.Count(), Is.EqualTo(1));
+                Assert.That(mvm.WatchedFolders.First(), Is.EqualTo(@"C:\MyFolders\Folder1".NormalizeFolderPath()));
+            }
+        }
+
+        [Test]
+        public static void TestSetFilesArePending()
+        {
+            Instance.KnownKeys.DefaultEncryptionKey = new Passphrase("passphrase");
+            FakeRuntimeFileInfo.AddFolder(@"C:\MyFolders\Folder1");
+            using (MainViewModel mvm = Factory.New<MainViewModel>())
+            {
+                Assert.That(mvm.FilesArePending, Is.False);
+                Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\MyFolders\Folder1", Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+                FakeRuntimeFileInfo.AddFile(@"C:\MyFolders\Folder1\Encryptable.txt", Stream.Null);
+                Assert.That(mvm.FilesArePending, Is.True);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestNDeskOptions.cs b/Axantum.AxCrypt.Core.Test/TestNDeskOptions.cs
new file mode 100644
index 0000000..11a448a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestNDeskOptions.cs
@@ -0,0 +1,1223 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using NDesk.Options;
+using NUnit.Framework;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters.Binary;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestNDeskOptions
+    {
+        [SetUp]
+        public static void Setup()
+        {
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestOptionContext()
+        {
+            OptionSetCollection optionSet = new OptionSetCollection();
+
+            OptionContext oc = new OptionContext(optionSet);
+
+            Assert.That(oc.OptionSet, Is.EqualTo(oc.OptionSet));
+            Assert.That(oc.OptionValues.Count(), Is.EqualTo(0));
+
+            oc.OptionIndex = 3;
+            Assert.That(oc.OptionIndex, Is.EqualTo(3));
+
+            oc.OptionName = "option";
+            Assert.That(oc.OptionName, Is.EqualTo("option"));
+        }
+
+        [Test]
+        public static void TestSimpleOption()
+        {
+            bool x = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", var => x = true},
+            };
+
+            options.Parse(new string[] { "-y" });
+            Assert.That(x, Is.False);
+
+            options.Parse(new string[] { "-x" });
+            Assert.That(x, Is.True);
+        }
+
+        [Test]
+        public static void TestExampleFromDocumentation()
+        {
+            int verbose = 0;
+            List<string> names = new List<string>();
+            OptionSetCollection options = new OptionSetCollection()
+              .Add("v", v => ++verbose)
+              .Add("name=|value=", v => names.Add(v));
+
+            IList<string> extra = options.Parse(new string[] { "-v", "--v", "/v", "-name=A", "/name", "B", "extra" });
+
+            Assert.That(verbose, Is.EqualTo(3));
+            Assert.That(names[0], Is.EqualTo("A"));
+            Assert.That(names[1], Is.EqualTo("B"));
+            Assert.That(extra[0], Is.EqualTo("extra"));
+        }
+
+        [Test]
+        public static void TestStopProcessingMarker()
+        {
+            int verbose = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"v", v => ++verbose}
+            };
+
+            IList<string> extra = options.Parse(new string[] { "-v", "--v", "/v", "--", "-v" });
+
+            Assert.That(verbose, Is.EqualTo(3));
+            Assert.That(extra[0], Is.EqualTo("-v"));
+        }
+
+        [Test]
+        public static void TestDefaultOptionHandler()
+        {
+            int verbose = 0;
+            List<string> names = new List<string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"v", v => ++verbose},
+                {"<>", arg => names.Add(arg)}
+            };
+
+            IList<string> extra = options.Parse(new string[] { "-v", "--v", "/v", "-y", "--", "-v" });
+            Assert.That(verbose, Is.EqualTo(3));
+            Assert.That(names[0], Is.EqualTo("-y"));
+            Assert.That(names[1], Is.EqualTo("-v"));
+            Assert.That(extra.Count, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestMissingTrailingRequiredValueThrows()
+        {
+            string value = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", v => value = v}
+            };
+
+            Assert.Throws<OptionException>(() => options.Parse(new string[] { "-name" }));
+            Assert.That(value, Is.Null);
+        }
+
+        [Test]
+        public static void TestMultipleValuesWithSpecifiedCharSeparator()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=,", (key, value) => dictionary.Add(key, value) },
+            };
+
+            options.Parse(new string[] { "-name=A,a", "-name=B,b" });
+            Assert.That(dictionary["A"], Is.EqualTo("a"));
+            Assert.That(dictionary["B"], Is.EqualTo("b"));
+        }
+
+        [Test]
+        public static void TestMultipleValuesWithDefaultSeparator()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", (key, value) => dictionary.Add(key, value) },
+            };
+
+            options.Parse(new string[] { "-name=A=a", "-name=B:b" });
+            Assert.That(dictionary["A"], Is.EqualTo("a"));
+            Assert.That(dictionary["B"], Is.EqualTo("b"));
+        }
+
+        [Test]
+        public static void TestOptionWithValue()
+        {
+            string v = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"y=", value => v = value},
+            };
+            options.Parse(new string[] { "-y=s" });
+
+            Assert.That(v, Is.EqualTo("s"));
+        }
+
+        [Test]
+        public static void TestBundledOptionWithValue()
+        {
+            bool x = false;
+            string v = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+                {"y=", value => v = value},
+            };
+            options.Parse(new string[] { "-xyoption" });
+
+            Assert.That(x, Is.True);
+            Assert.That(v, Is.EqualTo("option"));
+        }
+
+        [Test]
+        public static void TestBundledOptionWithKeyValuePair()
+        {
+            bool x = false;
+            string k = null;
+            string v = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+                {"D=", (key, value) => {k = key; v = value;}},
+            };
+            options.Parse(new string[] { "-xDname=value" });
+
+            Assert.That(x, Is.True);
+            Assert.That(k, Is.EqualTo("name"));
+            Assert.That(v, Is.EqualTo("value"));
+        }
+
+        [Test]
+        public static void TestStronglyTypedKeyValuePair()
+        {
+            int k = 0, v = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"D=", (int key, int value) => {k = key; v = value;}},
+            };
+            options.Parse(new string[] { "-D1=2" });
+            Assert.That(k, Is.EqualTo(1));
+            Assert.That(v, Is.EqualTo(2));
+        }
+
+        [Test]
+        public static void TestStronglyTypedKeyValuePairWithNullActionThrows()
+        {
+            OptionAction<int, int> action = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"D=", action},
+                };
+            });
+        }
+
+        [Test]
+        public static void TestRedefineOption()
+        {
+            bool first = false;
+            bool second = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"a|b", v => first = true },
+            };
+            OptionSetCollection options2 = new OptionSetCollection()
+            {
+                {"a|b", v => second = true }
+            };
+
+            options[0] = options2[0];
+
+            options.Parse(new string[] { "-b" });
+            Assert.That(first, Is.False);
+            Assert.That(second, Is.True);
+        }
+
+        [Test]
+        public static void TestMultipleValuesWithSpecifiedStringSeparator()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name={=>}", (key, value) => dictionary.Add(key, value) },
+            };
+
+            options.Parse(new string[] { "-name=A=>a", "-name=B=>b" });
+            Assert.That(dictionary["A"], Is.EqualTo("a"));
+            Assert.That(dictionary["B"], Is.EqualTo("b"));
+        }
+
+        [Test]
+        public static void TestMultipleValuesWithNoSeparator()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name={}", (key, value) => dictionary.Add(key, value) },
+            };
+
+            options.Parse(new string[] { "-name=A", "a", "-name=B", "b" });
+            Assert.That(dictionary["A"], Is.EqualTo("a"));
+            Assert.That(dictionary["B"], Is.EqualTo("b"));
+        }
+
+        [Test]
+        public static void TestTypedValue()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", (int value) => i = value },
+            };
+            options.Parse(new string[] { "-name=3" });
+            Assert.That(i, Is.EqualTo(3));
+        }
+
+        [Test]
+        public static void TestSimpleWriteOptionDescriptions()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "Description", (int value) => i = value },
+            };
+            string description = "      --name=VALUE           Description" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithTwoValues()
+        {
+            string k = null;
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "Description", (string key, int value) => {i = value; k=key;} },
+            };
+            string description = "      --name=VALUE1:VALUE2   Description" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(k, Is.Null);
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithInsertedValueNamesForSingleArgument()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "Description {Key} and {1:Value}", (int value) => {i = value;} },
+            };
+            string description = "      --name=Key             Description Key and Value" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithInsertedValueNamesIgnoredBecauseOfUnterminatedPlaceholderMarkerAndDescriptionBug()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "Description {Key and value", (int value) => {i = value;} },
+            };
+            string description = "      --name=VALUE           Description " + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithInsertedValueNamesForMultipleValueArgument()
+        {
+            string k = null;
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "Description {Key} and {1:Value}", (string key, int value) => {i = value; k=key;} },
+            };
+            string description = "      --name=VALUE1:Value    Description Key and Value" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(k, Is.Null);
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithLeftCurlyBraceEscape()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "A {{ Description", (int value) => i = value },
+            };
+            string description = "      --name=VALUE           A { Description" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithRightCurlyBraceEscape()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "A }} Description", (int value) => i = value },
+            };
+            string description = "      --name=VALUE           A } Description" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithBadRightCurlyBraceEscape()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "A }x Description", (int value) => i = value },
+            };
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                Assert.Throws<InvalidOperationException>(() => options.WriteOptionDescriptions(writer));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithUnterminatedRightCurlyBraceEscape()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "A Description }", (int value) => i = value },
+            };
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                Assert.Throws<InvalidOperationException>(() => options.WriteOptionDescriptions(writer));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestLongerWriteOptionDescriptions()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", "This:\nis a fairly long description, with a comma and a new line to boot! It's also so long it has to be broken into another line.", (int value) => i = value },
+            };
+            string description = "      --name=VALUE           This:" + Environment.NewLine +
+                "                               is a fairly long description, with a comma and a " + Environment.NewLine +
+                "                               new line to boot! It's also so long it has to be " + Environment.NewLine +
+                "                               broken into another line." + Environment.NewLine;
+
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(description));
+            }
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionIgnoresDefaultOptionHandler()
+        {
+            string d = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"<>", "", s => d = s},
+            };
+
+            string expectedDescription = String.Empty;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(expectedDescription));
+            }
+            Assert.That(d, Is.Null);
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithOptionPrototypeLongerThanLine()
+        {
+            string d = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"averylongoption|anotherverlongoption|athirdverylongoption|yetanotherverylongoption", "The Description", s => d = s},
+            };
+
+            string expectedDescription = "      --averylongoption, --anotherverlongoption, --athirdverylongoption, --yetanotherverylongoption" + Environment.NewLine +
+                                         "                             The Description" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(expectedDescription));
+            }
+            Assert.That(d, Is.Null);
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithValueArguments()
+        {
+            string value = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"a=", s => value = s},
+                {"b:|c:", s => value = s},
+                {"d={=>}", (s, v) => value = s + v},
+                {"e={}", (s, v) => value = s + v},
+                {"f", s => value = s},
+            };
+
+            string expectedDescription =
+                "  -a=VALUE                   " + Environment.NewLine +
+                "  -b, -c[=VALUE]             " + Environment.NewLine +
+                "  -d=VALUE1=>VALUE2          " + Environment.NewLine +
+                "  -e=VALUE1 VALUE2           " + Environment.NewLine +
+                "  -f                         " + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(expectedDescription));
+            }
+            Assert.That(value, Is.Null);
+        }
+
+        [Test]
+        public static void TestWriteOptionDescriptionsWithDescriptionThatMustBeBroken()
+        {
+            string d = null;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", "The_desciption_is_too_long_to_fit_on_a_single_line_so_the_code-must_break_it_up", s => d = s},
+            };
+
+            string expectedDescription = "  -x                         The_desciption_is_too_long_to_fit_on_a_single_li-" + Environment.NewLine +
+                                         "                               ne_so_the_code-must_break_it_up" + Environment.NewLine;
+            using (StringWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                options.WriteOptionDescriptions(writer);
+                string s = writer.ToString();
+                Assert.That(s, Is.EqualTo(expectedDescription));
+            }
+            Assert.That(d, Is.Null);
+        }
+
+        [Test]
+        public static void TestCannotUseTwoValuesWithSimpleArgumentThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"f", (s, v) => {}},
+                };
+            });
+        }
+
+        [Test]
+        public static void TestBadlyFormedTypedValueThrows()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"name=", (int value) => i = value },
+            };
+            Assert.Throws<OptionException>(() => options.Parse(new string[] { "-name=Three" }));
+            Assert.That(i, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestOptionBaseGetValueSeparators()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"a=-+", (key, value) => dictionary.Add(key, value) },
+            };
+            OptionBase ob = options["a"];
+            string[] separators = ob.GetValueSeparators();
+            Assert.That(separators[0], Is.EqualTo("-"));
+            Assert.That(separators[1], Is.EqualTo("+"));
+        }
+
+        [Test]
+        public static void TestOptionBaseGetValueSeparatorsWhenNone()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"a={}", (key, value) => dictionary.Add(key, value) },
+            };
+            OptionBase ob = options["a"];
+            string[] separators = ob.GetValueSeparators();
+            Assert.That(separators.Length, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestOptionBaseGetNames()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x|y", v => ++i},
+            };
+            OptionBase ob = options["x"];
+            string[] names = ob.GetNames();
+            Assert.That(names[0], Is.EqualTo("x"));
+            Assert.That(names[1], Is.EqualTo("y"));
+        }
+
+        [Test]
+        public static void TestOptionBaseGetPrototype()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x|y", v => ++i},
+            };
+            OptionBase ob = options["x"];
+            Assert.That(ob.Prototype, Is.EqualTo("x|y"));
+        }
+
+        [Test]
+        public static void TestOptionBaseToString()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x|y", v => ++i},
+            };
+            OptionBase ob = options["x"];
+            Assert.That(ob.ToString(), Is.EqualTo("x|y"));
+        }
+
+        [Test]
+        public static void TestOptionBaseGetDescription()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x|y", "X or Y", v => ++i},
+            };
+            OptionBase ob = options["x"];
+            Assert.That(ob.Description, Is.EqualTo("X or Y"));
+        }
+
+        [Test]
+        public static void TestKeyValuePairsThrowsWhenDelegateOnlyTakesOneArgument()
+        {
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"name=-", v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestDuplicateOptionNameThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"b|a|a", v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestEmptyOptionNameThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"", v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestNullOptionNameThrows()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {null, v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestZeroLengthOptionNameThrows()
+        {
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a|", v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestDoubleKeyValuePairStartThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a={{=>}", (key, value) => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestTooManyOptionValuesThrows()
+        {
+            IDictionary<string, string> dictionary = new Dictionary<string, string>();
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"a={=>}", (key, value) => dictionary.Add(key, value) },
+            };
+            Assert.Throws<OptionException>(() => options.Parse(new string[] { "-a", "b=>c=>d" }));
+        }
+
+        [Test]
+        public static void TestOnlyEndKeyValuePairStartThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a=>}", (key, value) => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestMissingEndKeyValuePairStartThrows()
+        {
+            Assert.Throws<ArgumentException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a={=>", (key, value) => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestConflictingOptionTypesThrows()
+        {
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a:|b=", v => {} },
+                };
+            });
+        }
+
+        [Test]
+        public static void TestNullActionWithDescriptionAndOneArgumentThrows()
+        {
+            Action<string> nullAction = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a=", "Description", nullAction}
+                };
+            });
+        }
+
+        [Test]
+        public static void TestNullActionWithDescriptionAndOneStronglyTypedArgumentThrows()
+        {
+            Action<int> nullAction = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a=", "Description", nullAction}
+                };
+            });
+        }
+
+        [Test]
+        public static void TestNullActionWithDescriptionAndTwoArgumentsThrows()
+        {
+            OptionAction<string, string> nullAction = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                new OptionSetCollection()
+                {
+                    {"a={}", "Description", nullAction}
+                };
+            });
+        }
+
+        [Test]
+        public static void TestParsingNullElementThrows()
+        {
+            int i = 0;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", var => ++i},
+            };
+
+            Assert.Throws<ArgumentNullException>(() => options.Parse(new string[] { "-x", null }));
+        }
+
+        [Test]
+        public static void TestForcedEnabledOption()
+        {
+            bool x = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+            };
+
+            options.Parse(new string[] { "-x+" });
+            Assert.That(x, Is.True);
+        }
+
+        [Test]
+        public static void TestForcedDisabledOption()
+        {
+            bool x = true;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+            };
+
+            options.Parse(new string[] { "-x-" });
+            Assert.That(x, Is.False);
+        }
+
+        [Test]
+        public static void TestBundledOption()
+        {
+            bool x = false;
+            bool y = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+                {"y", value => y = value != null},
+            };
+
+            options.Parse(new string[] { "-xy" });
+            Assert.That(x, Is.True);
+            Assert.That(y, Is.True);
+        }
+
+        [Test]
+        public static void TestBundledOptionWithNonMinusSwitchWhichApparentlyIsNotSupported()
+        {
+            bool x = false;
+            bool y = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+                {"y", value => y = value != null},
+            };
+
+            IList<string> extra = options.Parse(new string[] { "/xy" });
+            Assert.That(extra[0], Is.EqualTo("/xy"));
+            Assert.That(x, Is.False);
+            Assert.That(y, Is.False);
+        }
+
+        [Test]
+        public static void TestBundledOptionWithUnknownOptionThrows()
+        {
+            bool x = false;
+            bool y = false;
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"x", value => x = value != null},
+                {"y", value => y = value != null},
+            };
+            Assert.Throws<OptionException>(() => options.Parse(new string[] { "-xyz" }));
+            Assert.That(x, Is.True);
+            Assert.That(y, Is.True);
+        }
+
+        [Test]
+        public static void TestAddNullOptionToCollectionThrows()
+        {
+            OptionSetCollection options = new OptionSetCollection();
+            OptionBase nullOb = null;
+            Assert.Throws<ArgumentNullException>(() => options.Add(nullOb));
+        }
+
+        private class TestOptionsForConstructorExceptions : OptionBase
+        {
+            public TestOptionsForConstructorExceptions(string prototype, string description, int maxValueCount)
+                : base(prototype, description, maxValueCount)
+            {
+            }
+
+            protected override void OnParseComplete(OptionContext optionContext)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [Test]
+        public static void TestOptionBaseConstructorExceptions()
+        {
+            string nullString = null;
+
+            OptionBase option = null;
+            Assert.Throws<ArgumentNullException>(() => option = new TestOptionsForConstructorExceptions(nullString, "Description", 0));
+            Assert.Throws<ArgumentException>(() => option = new TestOptionsForConstructorExceptions("", "Description", 0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => option = new TestOptionsForConstructorExceptions("prototype", "Description", -1));
+
+            Assert.Throws<ArgumentException>(() => option = new TestOptionsForConstructorExceptions("x=", "Description", 0));
+            Assert.Throws<ArgumentException>(() => option = new TestOptionsForConstructorExceptions("x:", "Description", 0));
+            Assert.DoesNotThrow(() => option = new TestOptionsForConstructorExceptions("x:", "Description", 1));
+
+            Assert.Throws<ArgumentException>(() => option = new TestOptionsForConstructorExceptions("x", "Description", 2));
+            Assert.Throws<ArgumentException>(() => option = new TestOptionsForConstructorExceptions("x=|<>", "Description", 2));
+
+            Assert.That(option, Is.Not.Null, "Should not reach here. Only here to make FxCop believe we're using the instantiated object.");
+        }
+
+        [Test]
+        public static void TestOptionException()
+        {
+            OptionException oe = new OptionException();
+
+            Assert.That(oe.Message, Is.EqualTo("Exception of type 'NDesk.Options.OptionException' was thrown."));
+            Assert.That(oe.OptionName, Is.Null);
+            Assert.That(oe.InnerException, Is.Null);
+
+            oe = new OptionException("My Message");
+
+            Assert.That(oe.Message, Is.EqualTo("My Message"));
+            Assert.That(oe.OptionName, Is.Null);
+            Assert.That(oe.InnerException, Is.Null);
+
+            oe = new OptionException("My Message", oe);
+
+            Assert.That(oe.Message, Is.EqualTo("My Message"));
+            Assert.That(oe.OptionName, Is.Null);
+            Assert.That(oe.InnerException, Is.Not.Null);
+        }
+
+        private static OptionContext CreateOptionContext()
+        {
+            OptionSetCollection optionSet = new OptionSetCollection()
+            {
+                { "x=", (k, v) => {}},
+            };
+            OptionContext oc = new OptionContext(optionSet);
+            return oc;
+        }
+
+        private static OptionValueCollection CreateOptionValueCollection()
+        {
+            OptionContext oc = CreateOptionContext();
+            oc.Option = oc.OptionSet[0];
+
+            OptionValueCollection ovc = oc.OptionValues;
+
+            return ovc;
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionAssertValid()
+        {
+            OptionContext oc = CreateOptionContext();
+            string s;
+
+            Assert.Throws<InvalidOperationException>(() => s = oc.OptionValues[0]);
+
+            oc.Option = oc.OptionSet[0];
+            Assert.Throws<ArgumentOutOfRangeException>(() => s = oc.OptionValues[99]);
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionItemSetter()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc[0] = "value";
+
+            Assert.That(ovc[0], Is.EqualTo("value"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionIListImplementation()
+        {
+            IList ilist = CreateOptionValueCollection() as IList;
+
+            Assert.That(ilist.IsReadOnly, Is.False);
+            Assert.That(ilist.IsFixedSize, Is.False);
+            Assert.That(ilist.IsSynchronized, Is.False);
+            Assert.That(ilist.SyncRoot, Is.Not.Null);
+
+            ilist.Add("first");
+            Assert.That(ilist[0], Is.EqualTo("first"));
+
+            ilist[0] = "second";
+            Assert.That(ilist[0], Is.EqualTo("second"));
+
+            ilist.Add("third");
+            Assert.That(ilist.ToString(), Is.EqualTo("second, third"));
+
+            Assert.That(ilist.IndexOf("third"), Is.EqualTo(1));
+            Assert.That(ilist.Contains("second"));
+            Assert.That(ilist.Contains("first"), Is.False);
+
+            string v = String.Empty;
+            foreach (string s in ilist)
+            {
+                v += s;
+            }
+            Assert.That(v, Is.EqualTo("secondthird"));
+
+            ilist.RemoveAt(0);
+            Assert.That(ilist.Count, Is.EqualTo(1));
+            Assert.That(ilist[0], Is.EqualTo("third"));
+
+            ilist.Insert(1, "forth");
+            Assert.That(ilist.Count, Is.EqualTo(2));
+            Assert.That(ilist[0], Is.EqualTo("third"));
+            Assert.That(ilist[1], Is.EqualTo("forth"));
+
+            ilist.Remove("third");
+            Assert.That(ilist.Count, Is.EqualTo(1));
+            Assert.That(ilist[0], Is.EqualTo("forth"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionGetEnumerator()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            string v = String.Empty;
+            foreach (string s in ovc)
+            {
+                v += s;
+            }
+            Assert.That(v, Is.EqualTo("firstsecond"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionRemove()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            ovc.Remove("second");
+
+            Assert.That(ovc.Count, Is.EqualTo(1));
+            Assert.That(ovc[0], Is.EqualTo("first"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionContains()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            Assert.That(ovc.Contains("first"));
+            Assert.That(ovc.Contains("first"));
+            Assert.That(ovc.Contains("third"), Is.False);
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionCopyTo()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            string[] array = new string[] { "one", "two", "three" };
+            ovc.CopyTo(array, 1);
+
+            Assert.That(array.Length, Is.EqualTo(3));
+            Assert.That(array[0], Is.EqualTo("one"));
+            Assert.That(array[1], Is.EqualTo("first"));
+            Assert.That(array[2], Is.EqualTo("second"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionICollectionCopyTo()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            ICollection collection = ovc as ICollection;
+
+            string[] array = new string[] { "one", "two", "three" };
+            collection.CopyTo(array, 1);
+
+            Assert.That(array.Length, Is.EqualTo(3));
+            Assert.That(array[0], Is.EqualTo("one"));
+            Assert.That(array[1], Is.EqualTo("first"));
+            Assert.That(array[2], Is.EqualTo("second"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionToArray()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            string[] array = ovc.ToArray();
+
+            Assert.That(array.Length, Is.EqualTo(2));
+            Assert.That(array[0], Is.EqualTo("first"));
+            Assert.That(array[1], Is.EqualTo("second"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionToList()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            List<string> list = ovc.ToList();
+
+            Assert.That(list.Count, Is.EqualTo(2));
+            Assert.That(list[0], Is.EqualTo("first"));
+            Assert.That(list[1], Is.EqualTo("second"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionRemoveAt()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("second");
+
+            ovc.RemoveAt(0);
+
+            Assert.That(ovc.Count, Is.EqualTo(1));
+            Assert.That(ovc[0], Is.EqualTo("second"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionInsert()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Insert(0, "half");
+
+            Assert.That(ovc.Count, Is.EqualTo(2));
+            Assert.That(ovc[0], Is.EqualTo("half"));
+            Assert.That(ovc[1], Is.EqualTo("first"));
+        }
+
+        [Test]
+        public static void TestOptionValueCollectionIndexOf()
+        {
+            OptionValueCollection ovc = CreateOptionValueCollection();
+
+            ovc.Add("first");
+            ovc.Add("Second");
+
+            Assert.That(ovc.IndexOf("Second"), Is.EqualTo(1));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestNewPassphraseViewModel.cs b/Axantum.AxCrypt.Core.Test/TestNewPassphraseViewModel.cs
new file mode 100644
index 0000000..5f1a736
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestNewPassphraseViewModel.cs
@@ -0,0 +1,157 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Moq;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestNewPassphraseViewModel
+    {
+        private static IList<PassphraseIdentity> _identities;
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            _identities = new List<PassphraseIdentity>();
+            Mock<FileSystemState> fileSystemStateMock = new Mock<FileSystemState>();
+            fileSystemStateMock.Setup<IList<PassphraseIdentity>>(f => f.Identities).Returns(_identities);
+            Factory.Instance.Singleton<FileSystemState>(() => fileSystemStateMock.Object);
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructorWithoutKnownDefaultIdentity()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty,String.Empty);
+
+            Assert.That(npvm.Passphrase, Is.EqualTo(""));
+        }
+
+        [Test]
+        public static void TestConstructorWithKnownDefaultIdentity()
+        {
+            _identities.Add(new PassphraseIdentity());
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, String.Empty);
+
+            Assert.That(npvm.Passphrase, Is.EqualTo(String.Empty));
+        }
+
+        [Test]
+        public static void TestShowPassphrase()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel("Identity", String.Empty);
+
+            Assert.That(npvm.ShowPassphrase, Is.False);
+
+            npvm.ShowPassphrase = true;
+
+            Assert.That(npvm.ShowPassphrase, Is.True);
+        }
+
+        [Test]
+        public static void TestValidateIdentity()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel("Identity", String.Empty);
+
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.None));
+        }
+
+        [Test]
+        public static void TestValidatePropertyThatCannotBeValidated()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, String.Empty);
+            string s = null;
+            Assert.Throws<ArgumentException>(() => { s = npvm["ShowPassphrase"]; });
+            Assert.That(s, Is.Null, "Not a real assertion, only to make the variable used for FxCop.");
+        }
+
+        [Test]
+        public static void TestValidatePassphraseOk()
+        {
+            Factory.Instance.Register<AxCryptFactory>(() => new AxCryptFactory());
+
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, String.Empty);
+
+            npvm.Passphrase = "abc1234";
+            npvm.Verification = "abc1234";
+
+            Assert.That(npvm["Passphrase"], Is.EqualTo(""));
+            Assert.That(npvm["Verification"], Is.EqualTo(""));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.None));
+        }
+
+        [Test]
+        public static void TestValidatePassphraseNotOk()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, String.Empty);
+
+            npvm.Passphrase = "abc1234";
+            npvm.Verification = "abc12345";
+
+            Assert.That(npvm["Verification"], Is.Not.EqualTo(""));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.VerificationPassphraseWrong));
+        }
+
+        [Test]
+        public static void TestValidateNonExistingPropertyName()
+        {
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, String.Empty);
+            string s = null;
+            Assert.Throws<ArgumentException>(() => { s = npvm["NonExisting"]; });
+            Assert.That(s, Is.Null, "Not a real assertion, only to make the variable used for FxCop.");
+        }
+
+        [Test]
+        public static void TestValidateWrongPassphraseWithRealFile()
+        {
+            FakeRuntimeFileInfo.AddFile(@"C:\My Folder\MyFile-txt.axx", new MemoryStream(Resources.helloworld_key_a_txt));
+            NewPassphraseViewModel npvm = new NewPassphraseViewModel(String.Empty, @"C:\My Folder\MyFile-txt.axx");
+            npvm.Passphrase = "b";
+            npvm.Verification = "b";
+
+            Assert.That(npvm["Passphrase"], Is.Not.EqualTo(""));
+            Assert.That(npvm.ValidationError, Is.EqualTo((int)ValidationError.WrongPassphrase));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestParallelFileOperation.cs b/Axantum.AxCrypt.Core.Test/TestParallelFileOperation.cs
new file mode 100644
index 0000000..fb675e0
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestParallelFileOperation.cs
@@ -0,0 +1,103 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using System.Threading;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestParallelFileOperation
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestParallelFileOperationSimple()
+        {
+            IRuntimeFileInfo info1 = Factory.New<IRuntimeFileInfo>(@"c:\file1.txt");
+            IRuntimeFileInfo info2 = Factory.New<IRuntimeFileInfo>(@"c:\file2.txt");
+            ParallelFileOperation pfo = new ParallelFileOperation();
+            int callCount = 0;
+            pfo.DoFiles(new IRuntimeFileInfo[] { info1, info2 },
+                (info, progress) =>
+                {
+                    ++callCount;
+                    return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                },
+                (status) =>
+                {
+                });
+
+            Assert.That(callCount, Is.EqualTo(2), "There are two files, so there should be two calls.");
+        }
+
+        [Test]
+        public static void TestQuitAllOnError()
+        {
+            FakeUIThread fakeUIThread = new FakeUIThread();
+            fakeUIThread.IsOnUIThread = true;
+            Factory.Instance.Singleton<IUIThread>(() => fakeUIThread);
+
+            FakeRuntimeEnvironment.Instance.MaxConcurrency = 2;
+
+            IRuntimeFileInfo info1 = Factory.New<IRuntimeFileInfo>(@"c:\file1.txt");
+            IRuntimeFileInfo info2 = Factory.New<IRuntimeFileInfo>(@"c:\file2.txt");
+            IRuntimeFileInfo info3 = Factory.New<IRuntimeFileInfo>(@"c:\file3.txt");
+            IRuntimeFileInfo info4 = Factory.New<IRuntimeFileInfo>(@"c:\file4.txt");
+            ParallelFileOperation pfo = new ParallelFileOperation();
+
+            int callCount = 0;
+            pfo.DoFiles(new IRuntimeFileInfo[] { info1, info2, info3, info4 },
+                (info, progress) =>
+                {
+                    int result = Interlocked.Increment(ref callCount);
+                    if (result == 1)
+                    {
+                        return new FileOperationContext(String.Empty, FileOperationStatus.UnspecifiedError);
+                    }
+                    Thread.Sleep(1);
+                    return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                },
+                (status) => { });
+            Assert.That(callCount, Is.LessThanOrEqualTo(2), "There are several files, but max concurrency is two, so there could be up to two calls.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestPassphrase.cs b/Axantum.AxCrypt.Core.Test/TestPassphrase.cs
new file mode 100644
index 0000000..2324aff
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestPassphrase.cs
@@ -0,0 +1,62 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestPassphrase
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestPassphraseConstructor()
+        {
+            V1DerivedKey passphrase = new V1DerivedKey(new Passphrase("A Passphrase"));
+            SymmetricKey derivedKey = passphrase.DerivedKey;
+            Assert.That(derivedKey.Size, Is.EqualTo(128), "The default derived key is 128 bits.");
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                passphrase = new V1DerivedKey(null);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestPassphraseBase.cs b/Axantum.AxCrypt.Core.Test/TestPassphraseBase.cs
new file mode 100644
index 0000000..4de6ee0
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestPassphraseBase.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestPassphraseBase
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        private class TestingPassphraseBase : DerivedKeyBase
+        {
+            public TestingPassphraseBase(SymmetricKey derivedKey)
+            {
+                DerivedKey = derivedKey;
+            }
+        }
+
+        [Test]
+        public static void TestEquals()
+        {
+            SymmetricKey key1 = new SymmetricKey(128);
+            TestingPassphraseBase p1a = new TestingPassphraseBase(key1);
+            TestingPassphraseBase p1b = new TestingPassphraseBase(key1);
+            TestingPassphraseBase nullPassphraseBase = null;
+
+            Assert.That(p1a.Equals(p1b));
+            Assert.That(p1b.Equals(p1a));
+            Assert.That(p1a.Equals(p1a));
+            Assert.That(p1b.Equals(p1b));
+            Assert.That(!p1a.Equals(nullPassphraseBase));
+
+            object p1aObject = p1a;
+            object p1bObject = p1b;
+
+            Assert.That(p1aObject.Equals(p1bObject));
+            Assert.That(p1bObject.Equals(p1aObject));
+            Assert.That(p1aObject.Equals(p1aObject));
+            Assert.That(p1bObject.Equals(p1bObject));
+            Assert.That(!p1aObject.Equals((object)nullPassphraseBase));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestPassphraseIdentity.cs b/Axantum.AxCrypt.Core.Test/TestPassphraseIdentity.cs
new file mode 100644
index 0000000..20ad072
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestPassphraseIdentity.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestPassphraseIdentity
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestEmptyField()
+        {
+            PassphraseIdentity zero = new PassphraseIdentity(Passphrase.Empty);
+            PassphraseIdentity nonzero = new PassphraseIdentity(new Passphrase("something"));
+
+            Assert.That(zero.Key.Equals(PassphraseIdentity.Empty.Key));
+            Assert.That(zero.Thumbprint, Is.EqualTo(PassphraseIdentity.Empty.Thumbprint));
+
+            Assert.That(!nonzero.Key.Equals(PassphraseIdentity.Empty.Key));
+            Assert.That(nonzero.Thumbprint, Is.Not.EqualTo(PassphraseIdentity.Empty.Thumbprint));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestPbkdf2HmacSha512.cs b/Axantum.AxCrypt.Core.Test/TestPbkdf2HmacSha512.cs
new file mode 100644
index 0000000..e2b773c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestPbkdf2HmacSha512.cs
@@ -0,0 +1,372 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Pbkdf")]
+    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha")]
+    public static class TestPbkdf2HmacSha512
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCase1FromStackOverflow()
+        {
+            byte[] expected = "867f70cf1ade02cff3752599a3a53dc4af34c7a669815ae5d513554e1c8cf252c02d470a285a0501bad999bfe943c08f050235d7d68b1da55e63f73b60a57fce".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("password", new Salt(Encoding.ASCII.GetBytes("salt")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCase2FromStackOverflow()
+        {
+            byte[] expected = "e1d9c16aa681708a45f5c7c4e215ceb66e011a2e9f0040713f18aefdb866d53cf76cab2868a39b9f7840edce4fef5a82be67335c77a6068e04112754f27ccf4e".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("password", new Salt(Encoding.ASCII.GetBytes("salt")), 2).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCase3FromStackOverflow()
+        {
+            byte[] expected = "d197b1b33db0143e018b12f3d1d1479e6cdebdcc97c5c0f87f6902e072f457b5143f30602641b3d55cd335988cb36b84376060ecd532e039b742a239434af2d5".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("password", new Salt(Encoding.ASCII.GetBytes("salt")), 4096).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCase4FromStackOverflow()
+        {
+            byte[] expected = "8c0511f4c6e597c6ac6315d8f0362e225f3c501495ba23b868c005174dc4ee71115b59f9e60cd9532fa33e0f75aefe30225c583a186cd82bd4daea9724a3d3b8".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passwordPASSWORDpassword", new Salt(Encoding.ASCII.GetBytes("saltSALTsaltSALTsaltSALTsaltSALTsalt")), 4096).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest1AFromStackOverflow()
+        {
+            byte[] expected = "CBE6088AD4359AF42E603C2A33760EF9D4017A7B2AAD10AF46F992C660A0B461ECB0DC2A79C2570941BEA6A08D15D6887E79F32B132E1C134E9525EEDDD744FA".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTT", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest1BFromStackOverflow()
+        {
+            byte[] expected = "ACCDCD8798AE5CD85804739015EF2A11E32591B7B7D16F76819B30B0D49D80E1ABEA6C9822B80A1FDFE421E26F5603ECA8A47A64C9A004FB5AF8229F762FF41F".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTT", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest2AFromStackOverflow()
+        {
+            byte[] expected = "8E5074A9513C1F1512C9B1DF1D8BFFA9D8B4EF9105DFC16681222839560FB63264BED6AABF761F180E912A66E0B53D65EC88F6A1519E14804EBA6DC9DF137007".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTl", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest2BFromStackOverflow()
+        {
+            byte[] expected = "594256B0BD4D6C9F21A87F7BA5772A791A10E6110694F44365CD94670E57F1AECD797EF1D1001938719044C7F018026697845EB9AD97D97DE36AB8786AAB5096".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTl", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest3AFromStackOverflow()
+        {
+            byte[] expected = "A6AC8C048A7DFD7B838DA88F22C3FAB5BFF15D7CB8D83A62C6721A8FAF6903EAB6152CB7421026E36F2FFEF661EB4384DC276495C71B5CAB72E1C1A38712E56B".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlR", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2P")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest3BFromStackOverflow()
+        {
+            byte[] expected = "94FFC2B1A390B7B8A9E6A44922C330DB2B193ADCF082EECD06057197F35931A9D0EC0EE5C660744B50B61F23119B847E658D179A914807F4B8AB8EB9505AF065".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlR", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2P")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest4AFromStackOverflow()
+        {
+            byte[] expected = "E2CCC7827F1DD7C33041A98906A8FD7BAE1920A55FCB8F831683F14F1C3979351CB868717E5AB342D9A11ACF0B12D3283931D609B06602DA33F8377D1F1F9902".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE5", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJe")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest4BFromStackOverflow()
+        {
+            byte[] expected = "07447401C85766E4AED583DE2E6BF5A675EABE4F3618281C95616F4FC1FDFE6ECBC1C3982789D4FD941D6584EF534A78BD37AE02555D9455E8F089FDB4DFB6BB".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE5", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJe")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// We agree with the posted vectors and thus Python and SQL, but not OpenSSL which appears to be in the wrong.
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest5AFromStackOverflow()
+        {
+            byte[] expected = "B029A551117FF36977F283F579DC7065B352266EA243BDD3F920F24D4D141ED8B6E02D96E2D3BDFB76F8D77BA8F4BB548996AD85BB6F11D01A015CE518F9A717".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJem")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest5BFromStackOverflow()
+        {
+            byte[] expected = "31F5CC83ED0E948C05A15735D818703AAA7BFF3F09F5169CAF5DBA6602A05A4D5CFF5553D42E82E40516D6DC157B8DAEAE61D3FEA456D964CB2F7F9A63BBBDB5".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJem")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// We agree with the posted vectors and thus Python and SQL, but not OpenSSL which appears to be in the wrong.
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest6AFromStackOverflow()
+        {
+            byte[] expected = "28B8A9F644D6800612197BB74DF460272E2276DE8CC07AC4897AC24DBC6EB77499FCAF97415244D9A29DA83FC347D09A5DBCFD6BD63FF6E410803DCA8A900AB6".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57U", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemk")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest6BFromStackOverflow()
+        {
+            byte[] expected = "056BC9072A356B7D4DA60DD66F5968C2CAA375C0220EDA6B47EF8E8D105ED68B44185FE9003FBBA49E2C84240C9E8FD3F5B2F4F6512FD936450253DB37D10028".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57U", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemk")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// We agree with the posted vectors and thus Python and SQL, but not OpenSSL which appears to be in the wrong.
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest7AFromStackOverflow()
+        {
+            byte[] expected = "16226C85E4F8D604573008BFE61C10B6947B53990450612DD4A3077F7DEE2116229E68EFD1DF6D73BD3C6D07567790EEA1E8B2AE9A1B046BE593847D9441A1B7".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi0", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest7BFromStackOverflow()
+        {
+            byte[] expected = "70CF39F14C4CAF3C81FA288FB46C1DB52D19F72722F7BC84F040676D3371C89C11C50F69BCFBC3ACB0AB9E92E4EF622727A916219554B2FA121BEDDA97FF3332".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi0", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// We agree with the posted vectors and thus Python and SQL, but not OpenSSL which appears to be in the wrong.
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest8AFromStackOverflow()
+        {
+            byte[] expected = "880C58C316D3A5B9F05977AB9C60C10ABEEBFAD5CE89CAE62905C1C4F80A0A098D82F95321A6220F8AECCFB45CE6107140899E8D655306AE6396553E2851376C".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy6")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest8BFromStackOverflow()
+        {
+            byte[] expected = "2668B71B3CA56136B5E87F30E098F6B4371CB5ED95537C7A073DAC30A2D5BE52756ADF5BB2F4320CB11C4E16B24965A9C790DEF0CBC62906920B4F2EB84D1D4A".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy6")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// We agree with the posted vectors and thus Python and SQL, but not OpenSSL which appears to be in the wrong.
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest9AFromStackOverflow()
+        {
+            byte[] expected = "93B9BA8283CC17D50EF3B44820828A258A996DE258225D24FB59990A6D0DE82DFB3FE2AC201952100E4CC8F06D883A9131419C0F6F5A6ECB8EC821545F14ADF1".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04U", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy6P")), 1).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest9BFromStackOverflow()
+        {
+            byte[] expected = "2575B485AFDF37C260B8F3386D33A60ED929993C9D48AC516EC66B87E06BE54ADE7E7C8CB3417C81603B080A8EEFC56072811129737CED96236B9364E22CE3A5".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04U", new Salt(Encoding.ASCII.GetBytes("saltKEYbcTcXHCBxtjD2PnBh44AIQ6XUOCESOhXpEp3HrcGMwbjzQKMSaf63IJemkURWoqHusIeVB8Il91NjiCGQacPUu9qTFaShLbKG0Yj4RCMV56WPj7E14EMpbxy6P")), 100000).GetBytes();
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest10AFromStackOverflow()
+        {
+            byte[] expected = "384BCD6914407E40C295D1037CF4F990E8F0E720AF43CB706683177016D36D1A14B3A7CF22B5DF8D5D7D44D69610B64251ADE2E7AB54A3813A89935592E391BF".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04Uz3ebEAhzZ4ve1A2wg5CnLXdZC5Y7gwfVgbEgZSTmoYQSzC5OW4dfrjqiwApTACO6xoOL1AjWj6X6f6qFfF8TVmOzU9RhOd1N4QtzWI4fP6FYttNz5FuLdtYVXWVXH2Tf7I9fieMeWCHTMkM4VcmQyQHpbcP8MEb5f1g6Ckg5xk3HQr3wMBvQcOHpCPy1K8HCM7a5wkPDhgVA0BVmwNpsRIbDQZRtHK6dT6bGyalp6gbFZBuBHwD86gTzkrFY7HkOVrgc0gJcGJZe65Ce8v4Jn5OzkuVsiU8efm2Pw2RnbpWSAr7SkVdCwXK2X [...]
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        /// <summary>
+        /// See http://stackoverflow.com/questions/15593184/pbkdf2-hmac-sha-512-test-vectors .
+        /// </summary>
+        [Test]
+        public static void TestCaseLongTest10BFromStackOverflow()
+        {
+            byte[] expected = "B8674F6C0CC9F8CF1F1874534FD5AF01FC1504D76C2BC2AA0A75FE4DD5DFD1DAF60EA7C85F122BCEEB8772659D601231607726998EAC3F6AAB72EFF7BA349F7F".FromHex();
+            byte[] actual = new Pbkdf2HmacSha512("passDATAb00AB7YxDTTlRH2dqxDx19GDxDV1zFMz7E6QVqKIzwOtMnlxQLttpE57Un4u12D2YD7oOPpiEvCDYvntXEe4NNPLCnGGeJArbYDEu6xDoCfWH6kbuV6awi04Uz3ebEAhzZ4ve1A2wg5CnLXdZC5Y7gwfVgbEgZSTmoYQSzC5OW4dfrjqiwApTACO6xoOL1AjWj6X6f6qFfF8TVmOzU9RhOd1N4QtzWI4fP6FYttNz5FuLdtYVXWVXH2Tf7I9fieMeWCHTMkM4VcmQyQHpbcP8MEb5f1g6Ckg5xk3HQr3wMBvQcOHpCPy1K8HCM7a5wkPDhgVA0BVmwNpsRIbDQZRtHK6dT6bGyalp6gbFZBuBHwD86gTzkrFY7HkOVrgc0gJcGJZe65Ce8v4Jn5OzkuVsiU8efm2Pw2RnbpWSAr7SkVdCwXK2X [...]
+
+            Assert.That(actual.IsEquivalentTo(expected));
+        }
+
+        [Test]
+        public static void TestConstructorWithBadArguments()
+        {
+            Pbkdf2HmacSha512 pbkdf = null;
+            Assert.Throws<ArgumentNullException>(() => pbkdf = new Pbkdf2HmacSha512("passphrase", null, 0));
+            Assert.Throws<ArgumentNullException>(() => pbkdf = new Pbkdf2HmacSha512(null, Salt.Zero, 0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => pbkdf = new Pbkdf2HmacSha512("passphrase", Salt.Zero, 0));
+            Assert.Throws<ArgumentOutOfRangeException>(() => pbkdf = new Pbkdf2HmacSha512("passphrase", Salt.Zero, -1));
+
+            Assert.DoesNotThrow(() => pbkdf = new Pbkdf2HmacSha512("passphrase", Salt.Zero, 10));
+            Assert.That(pbkdf, Is.Not.Null);
+        }
+
+        [Test]
+        public static void TestGetBytesTwice()
+        {
+            Pbkdf2HmacSha512 pbkdf = new Pbkdf2HmacSha512("passphrase", Salt.Zero, 10);
+
+            byte[] bytes = pbkdf.GetBytes();
+            Assert.Throws<InternalErrorException>(() => bytes = pbkdf.GetBytes());
+            Assert.That(bytes, Is.Not.Null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestPreambleHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestPreambleHeaderBlock.cs
new file mode 100644
index 0000000..7876207
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestPreambleHeaderBlock.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestPreambleHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestBadArguments()
+        {
+            PreambleHeaderBlock preambleHeaderBlock = new PreambleHeaderBlock();
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                preambleHeaderBlock.Hmac = null;
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestProcessState.cs b/Axantum.AxCrypt.Core.Test/TestProcessState.cs
new file mode 100644
index 0000000..91235af
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestProcessState.cs
@@ -0,0 +1,93 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestProcessState
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestDoubleDispose()
+        {
+            ProcessState ps = new ProcessState();
+            Assert.DoesNotThrow(() => ps.Dispose());
+            Assert.DoesNotThrow(() => ps.Dispose());
+        }
+
+        [Test]
+        public static void TestPurgeInactive()
+        {
+            ProcessState ps = new ProcessState();
+
+            ActiveFile activeFile1 = new ActiveFile(Factory.New<IRuntimeFileInfo>(@"C:\encrypted.axx"), Factory.New<IRuntimeFileInfo>(@"C:\decrypted.txt"), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            ILauncher launcher1 = OS.Current.Launch(activeFile1.EncryptedFileInfo.FullName);
+            ps.Add(launcher1, activeFile1);
+
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.True);
+
+            FakeLauncher fakeLauncher1 = (FakeLauncher)launcher1;
+
+            fakeLauncher1.HasExited = true;
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.False);
+
+            fakeLauncher1.HasExited = false;
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.True);
+
+            fakeLauncher1.HasExited = true;
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.False);
+
+            ActiveFile activeFile2 = new ActiveFile(Factory.New<IRuntimeFileInfo>(@"C:\encrypted2.axx"), Factory.New<IRuntimeFileInfo>(@"C:\decrypted2.txt"), new Passphrase("passphrase"), ActiveFileStatus.NotDecrypted, new V1Aes128CryptoFactory().Id);
+            ILauncher launcher2 = OS.Current.Launch(activeFile2.EncryptedFileInfo.FullName);
+            ps.Add(launcher2, activeFile2);
+
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.False);
+
+            fakeLauncher1.HasExited = false;
+            Assert.That(ps.HasActiveProcess(activeFile1), Is.False);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestProgressContext.cs b/Axantum.AxCrypt.Core.Test/TestProgressContext.cs
new file mode 100644
index 0000000..09a32c4
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestProgressContext.cs
@@ -0,0 +1,390 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestProgressContext
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestProgressNoMax()
+        {
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            int percent = -1;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            progress.AddCount(100);
+            Assert.That(percent, Is.EqualTo(0), "Since there is no Total set, the percentage should always be zero.");
+        }
+
+        [Test]
+        public static void TestCurrentAndMax()
+        {
+            ProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            int percent = -1;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            progress.AddTotal(99);
+            progress.NotifyLevelFinished();
+            Assert.That(percent, Is.EqualTo(100), "After Finished(), Percent should always be 100.");
+        }
+
+        [Test]
+        public static void TestPercent()
+        {
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            int percent = -1;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            progress.AddTotal(200);
+            progress.AddCount(100);
+            Assert.That(percent, Is.EqualTo(50), "When halfway, the percent should be 50.");
+        }
+
+        [Test]
+        public static void TestSeveralCallsToCount()
+        {
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            int percent = -1;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            FakeRuntimeEnvironment fakeEnvironment = (FakeRuntimeEnvironment)OS.Current;
+            progress.AddTotal(500);
+            progress.AddCount(50);
+            progress.AddCount(50);
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1);
+            progress.AddCount(50);
+            progress.AddCount(50);
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(2);
+            progress.AddCount(50);
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(2);
+            Assert.That(percent, Is.EqualTo(50), "When halfway, the percent should be 50.");
+        }
+
+        [Test]
+        public static void TestFirstDelay()
+        {
+            FakeRuntimeEnvironment fakeEnvironment = (FakeRuntimeEnvironment)OS.Current;
+            ProgressContext progress = new ProgressContext(TimeSpan.FromMilliseconds(13));
+            bool wasHere = false;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                wasHere = true;
+            };
+            progress.AddTotal(100);
+            progress.AddCount(50);
+            Assert.That(wasHere, Is.False, "No progress should be raised, since the first delay time has not elapsed as yet.");
+
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(12);
+            progress.AddCount(1);
+            Assert.That(wasHere, Is.False, "No progress should be raised, since the first delay time has not elapsed as yet.");
+
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(13);
+            progress.AddCount(1);
+            Assert.That(wasHere, Is.True, "Progress should be raised, since the first delay time has now elapsed.");
+        }
+
+        [Test]
+        public static void TestAddTotalAfterFinished()
+        {
+            ProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.NotifyLevelFinished();
+
+            Assert.Throws<InvalidOperationException>(() => { progress.AddTotal(1); });
+        }
+
+        [Test]
+        public static void TestAddCountAfterFinished()
+        {
+            ProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.NotifyLevelFinished();
+
+            Assert.Throws<InvalidOperationException>(() => { progress.AddCount(1); });
+        }
+
+        [Test]
+        public static void TestDoubleNotifyFinished()
+        {
+            ProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.NotifyLevelStart();
+            progress.NotifyLevelFinished();
+
+            Assert.DoesNotThrow(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestTooManyNotifyFinished()
+        {
+            ProgressContext progress = new ProgressContext();
+
+            Assert.Throws<InvalidOperationException>(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestProgressTo100AndAboveShouldOnlyReturn99BeforeFinishedPercent()
+        {
+            FakeRuntimeEnvironment fakeEnvironment = (FakeRuntimeEnvironment)OS.Current;
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(1000);
+
+            ProgressContext progress = new ProgressContext(TimeSpan.FromMilliseconds(1000));
+            progress.NotifyLevelStart();
+            int percent = 0;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+                {
+                    percent = e.Percent;
+                };
+            progress.AddTotal(2);
+            Assert.That(percent, Is.EqualTo(0), "No progress yet - should be zero.");
+            progress.AddCount(1);
+            Assert.That(percent, Is.EqualTo(50), "Halfway should be 50 percent.");
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(2000);
+            progress.AddCount(1);
+            Assert.That(percent, Is.EqualTo(99), "Even at 100 should report 99 percent.");
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(3000);
+            progress.AddCount(1000);
+            Assert.That(percent, Is.EqualTo(99), "Even at very much above 100 should report 99 percent.");
+            progress.NotifyLevelFinished();
+            Assert.That(percent, Is.EqualTo(100), "Only when NotifyFinished() is called should 100 percent be reported.");
+        }
+
+        [Test]
+        public static void TestAddingNegativeCount()
+        {
+            FakeRuntimeEnvironment fakeEnvironment = (FakeRuntimeEnvironment)OS.Current;
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(1000);
+
+            ProgressContext progress = new ProgressContext(TimeSpan.FromMilliseconds(1000));
+            int percent = 0;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            progress.AddTotal(2);
+            Assert.That(percent, Is.EqualTo(0), "No progress yet - should be zero.");
+            progress.AddCount(-100);
+            Assert.That(percent, Is.EqualTo(0), "Nothing should happen adding negative counts.");
+            fakeEnvironment.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(2000);
+            progress.AddCount(1);
+            Assert.That(percent, Is.EqualTo(50), "1 of 2 is 50 percent.");
+        }
+
+        [Test]
+        public static void TestRemoveCount()
+        {
+            int percent = 0;
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            progress.Progressing += (sender, e) => percent = e.Percent;
+            progress.AddTotal(100);
+            progress.AddCount(50);
+
+            Assert.That(percent, Is.EqualTo(50));
+
+            progress.RemoveCount(50, 50);
+            FakeRuntimeEnvironment.Instance.CurrentTiming.CurrentTiming = TimeSpan.FromMilliseconds(1000);
+            progress.AddCount(10);
+            Assert.That(percent, Is.EqualTo(20));
+        }
+
+        [Test]
+        public static void TestProgressWithoutSynchronizationContext()
+        {
+            bool didProgress = false;
+            SynchronizationContext currentContext = new SynchronizationContext();
+            Thread thread = new Thread(
+                (object state) =>
+                {
+                    currentContext = SynchronizationContext.Current;
+                    ProgressContext progress = new ProgressContext();
+                    progress.NotifyLevelStart();
+                    progress.Progressing += (object sender, ProgressEventArgs e) =>
+                        {
+                            didProgress = true;
+                        };
+                    progress.NotifyLevelFinished();
+                }
+                );
+            thread.Start();
+            thread.Join();
+            Assert.That(didProgress, "There should always be one Progressing event after NotifyFinished().");
+            Assert.That(currentContext, Is.Null, "There should be no SynchronizationContext here.");
+        }
+
+        private class StateForSynchronizationContext
+        {
+            public bool DidProgress { get; set; }
+
+            public SynchronizationContext SynchronizationContext { get; set; }
+
+            public ManualResetEvent WaitEvent { get; set; }
+        }
+
+        [Test]
+        public static void TestProgressWithSynchronizationContext()
+        {
+            SynchronizationContext synchronizationContext = new SynchronizationContext();
+            StateForSynchronizationContext s = new StateForSynchronizationContext();
+            s.WaitEvent = new ManualResetEvent(false);
+            s.SynchronizationContext = synchronizationContext;
+            synchronizationContext.Post(
+                (object state) =>
+                {
+                    StateForSynchronizationContext ss = (StateForSynchronizationContext)state;
+                    SynchronizationContext.SetSynchronizationContext(ss.SynchronizationContext);
+                    ss.SynchronizationContext = SynchronizationContext.Current;
+
+                    ProgressContext progress = new ProgressContext();
+                    progress.NotifyLevelStart();
+                    progress.Progressing += (object sender, ProgressEventArgs e) =>
+                    {
+                        ss.DidProgress = true;
+                    };
+                    progress.NotifyLevelFinished();
+                    ss.WaitEvent.Set();
+                }, s);
+            bool waitOk = s.WaitEvent.WaitOne(TimeSpan.FromSeconds(10), false);
+            Assert.That(waitOk, "The wait should not time-out");
+            Assert.That(s.SynchronizationContext, Is.EqualTo(synchronizationContext), "The SynchronizationContext should be current in the code executed.");
+            Assert.That(s.DidProgress, "There should always be one Progressing event after NotifyFinished().");
+        }
+
+        [Test]
+        public static void TestCancelNotifyLevelStart()
+        {
+            IProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.AddTotal(100);
+            progress.AddCount(10);
+            progress = new CancelProgressContext(progress);
+            progress.Cancel = true;
+            Assert.Throws<OperationCanceledException>(() => { progress.NotifyLevelStart(); });
+            Assert.DoesNotThrow(() => { progress.AddTotal(50); });
+            Assert.DoesNotThrow(() => { progress.AddCount(10); });
+            Assert.DoesNotThrow(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestCancelNotifyLevelFinished()
+        {
+            IProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.AddTotal(100);
+            progress.AddCount(10);
+            progress = new CancelProgressContext(progress);
+            Assert.DoesNotThrow(() => { progress.NotifyLevelStart(); });
+            Assert.DoesNotThrow(() => { progress.AddTotal(50); });
+            Assert.DoesNotThrow(() => { progress.AddCount(10); });
+            progress.Cancel = true;
+            Assert.Throws<OperationCanceledException>(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestCancelAddTotal()
+        {
+            IProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.AddTotal(100);
+            progress.AddCount(10);
+            progress = new CancelProgressContext(progress);
+            Assert.DoesNotThrow(() => { progress.NotifyLevelStart(); });
+            progress.Cancel = true;
+            Assert.Throws<OperationCanceledException>(() => { progress.AddTotal(50); });
+            Assert.DoesNotThrow(() => { progress.AddCount(10); });
+            Assert.DoesNotThrow(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestCancelAddCount()
+        {
+            IProgressContext progress = new ProgressContext();
+            progress.NotifyLevelStart();
+            progress.AddTotal(100);
+            progress.AddCount(10);
+            progress = new CancelProgressContext(progress);
+            Assert.DoesNotThrow(() => { progress.NotifyLevelStart(); });
+            Assert.DoesNotThrow(() => { progress.AddTotal(50); });
+            progress.Cancel = true;
+            Assert.Throws<OperationCanceledException>(() => { progress.AddCount(10); });
+            Assert.DoesNotThrow(() => { progress.NotifyLevelFinished(); });
+        }
+
+        [Test]
+        public static void TestMultipleAddTotal()
+        {
+            int percent = 0;
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                percent = e.Percent;
+            };
+            progress.AddTotal(50);
+            progress.AddTotal(50);
+            progress.AddCount(50);
+            Assert.That(percent, Is.EqualTo(50), "The total should be 100, so 50 is 50% and the progressing event should be raised at the first progress.");
+        }
+
+        [Test]
+        public static void TestItems()
+        {
+            ProgressContext progress = new ProgressContext();
+            Assert.That(progress.Items, Is.EqualTo(0), "At start there are no item counted.");
+            progress.AddItems(7);
+            Assert.That(progress.Items, Is.EqualTo(7), "There was just 7 added.");
+            progress.AddItems(-1);
+            Assert.That(progress.Items, Is.EqualTo(6), "Items are counted down by adding negative numbers.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestProgressEventArgsTest.cs b/Axantum.AxCrypt.Core.Test/TestProgressEventArgsTest.cs
new file mode 100644
index 0000000..d3b8ecc
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestProgressEventArgsTest.cs
@@ -0,0 +1,66 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestProgressEventArgsTest
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestProgress()
+        {
+            ProgressContext progress = new ProgressContext(TimeSpan.Zero);
+            progress.AddTotal(100);
+            bool wasHere = false;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                wasHere = true;
+            };
+            progress.AddCount(1);
+            Assert.That(wasHere, "The event should be raised.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestProgressStream.cs b/Axantum.AxCrypt.Core.Test/TestProgressStream.cs
new file mode 100644
index 0000000..e545d21
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestProgressStream.cs
@@ -0,0 +1,136 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestProgressStreamTest
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            Stream nullStream = null;
+            ProgressContext nullProgress = null;
+
+            ProgressStream progressStream;
+            Assert.Throws<ArgumentNullException>(() => { progressStream = new ProgressStream(nullStream, new ProgressContext()); });
+            Assert.Throws<ArgumentNullException>(() => { progressStream = new ProgressStream(new MemoryStream(), nullProgress); });
+
+            progressStream = new ProgressStream(new MemoryStream(), new ProgressContext());
+            byte[] nullBuffer = null;
+            Assert.Throws<ArgumentNullException>(() => { progressStream.Write(nullBuffer, 0, 0); });
+            Assert.Throws<ArgumentNullException>(() => { progressStream.Read(nullBuffer, 0, 0); });
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestPropertiesAndMethods()
+        {
+            using (MemoryStream memoryStream = FakeRuntimeFileInfo.ExpandableMemoryStream(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }))
+            {
+                string kilroy = String.Empty;
+                using (FakeStream testStream = new FakeStream(memoryStream, (string wasHere) => { kilroy += wasHere; }))
+                {
+                    using (ProgressStream progressStream = new ProgressStream(testStream, new ProgressContext()))
+                    {
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.CanRead, Is.True, "The underlying stream is readable.");
+                        Assert.That(kilroy, Is.EqualTo("CanRead"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.CanWrite, Is.True, "The underlying stream is writable.");
+                        Assert.That(kilroy, Is.EqualTo("CanWrite"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.CanSeek, Is.True, "The underlying stream is seekable.");
+                        Assert.That(kilroy, Is.EqualTo("CanSeek"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        progressStream.Flush();
+                        Assert.That(kilroy, Is.EqualTo("Flush"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.Length, Is.EqualTo(10), "There are 10 bytes  in the underlying stream.");
+                        Assert.That(kilroy, Is.EqualTo("Length"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.Seek(-4, SeekOrigin.End), Is.EqualTo(6), "4 bytes from the end of 10 should be 6.");
+                        Assert.That(kilroy, Is.EqualTo("Seek"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(progressStream.Position, Is.EqualTo(6), "The position should still be at 6.");
+                        Assert.That(kilroy, Is.EqualTo("getPosition"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        progressStream.Position = 0;
+                        Assert.That(kilroy, Is.EqualTo("setPosition"), "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        progressStream.Write(new byte[] { 13 }, 0, 1);
+                        Assert.That(kilroy.Contains("Write"), Is.True, "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        progressStream.Position = 0;
+                        byte[] firstByte = new byte[1];
+                        progressStream.Read(firstByte, 0, 1);
+                        Assert.That(kilroy.Contains("Read"), Is.True, "ProgressStream should delegate to the underlying stream.");
+                        kilroy = String.Empty;
+                        Assert.That(firstByte[0], Is.EqualTo(13), "13 was just written to the first position.");
+                        progressStream.SetLength(5);
+                        Assert.That(kilroy, Is.EqualTo("SetLength"), "ProgressStream should delegate to the underlying stream.");
+                    }
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestDoubleDispose()
+        {
+            using (Stream stream = Stream.Null)
+            {
+                Assert.DoesNotThrow(() =>
+                {
+                    using (ProgressStream progressStream = new ProgressStream(stream, new ProgressContext()))
+                    {
+                        progressStream.Dispose();
+                    }
+                });
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestRandomGenerator.cs b/Axantum.AxCrypt.Core.Test/TestRandomGenerator.cs
new file mode 100644
index 0000000..e43c88f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestRandomGenerator.cs
@@ -0,0 +1,67 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestRandomGenerator
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestGenerate()
+        {
+            RandomGenerator generator = new RandomGenerator();
+
+            byte[] randomBytes = generator.Generate(100);
+            Assert.That(randomBytes.Length, Is.EqualTo(100), "Ensuring we really got the right number of bytes.");
+            Assert.That(randomBytes, Is.Not.EquivalentTo(new byte[100]), "It is not in practice possible that all zero bytes are returned by GetRandomBytes().");
+
+            randomBytes = generator.Generate(1000);
+            double average = randomBytes.Average(b => b);
+            Assert.That(average >= 115 && average <= 140, "Unscientific, but the sample sequence should not vary much from a mean of 127.5, but was {0}".InvariantFormat(average));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestResources.cs b/Axantum.AxCrypt.Core.Test/TestResources.cs
new file mode 100644
index 0000000..b71abce
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestResources.cs
@@ -0,0 +1,78 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Globalization;
+using System.Linq;
+using System.Resources;
+using System.Text;
+using System.Threading;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestResources
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestIt()
+        {
+            CultureInfo culture = PublicResources.Culture;
+            Assert.That(culture, Is.Null, "There should be no explicitly culture set.");
+
+            PublicResources.Culture = CultureInfo.CreateSpecificCulture("sv-SE");
+            Assert.That(PublicResources.Culture, Is.EqualTo(CultureInfo.CreateSpecificCulture("sv-SE")), "The culture should be Swedish now.");
+
+            PublicResources.Culture = culture;
+            Assert.That(PublicResources.Culture, Is.Null, "There should be no explicitly culture set again.");
+
+            string license = PublicResources.BouncycastleLicense;
+            Assert.That(license, Is.Not.Null, "Just checking that there is a Bouncy Castle License Text.");
+
+            license = PublicResources.JsonNetLicense;
+            Assert.That(license, Is.Not.Null, "Just checking that there is a Json.NET License Text.");
+
+            Icon icon = new Icon(PublicResources.AxCryptIcon);
+            Assert.That(icon, Is.Not.Null, "Just checking that there is an icon.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSalt.cs b/Axantum.AxCrypt.Core.Test/TestSalt.cs
new file mode 100644
index 0000000..cc59587
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSalt.cs
@@ -0,0 +1,95 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSalt
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestMethodsEtc()
+        {
+            Salt salt = null;
+            Assert.DoesNotThrow(() =>
+            {
+                salt = new Salt(0);
+                Assert.That(salt.Length, Is.EqualTo(0), "As a special case, zero length salt is supported - equivalent to no salt.");
+
+                salt = new Salt(128);
+                Assert.That(salt.Length, Is.EqualTo(16), "The length should be what was asked for.");
+                Assert.That(salt.GetBytes(), Is.Not.EquivalentTo(new byte[16]), "A random salt is not likely to be all zeros.");
+
+                salt = new Salt(192);
+                Assert.That(salt.Length, Is.EqualTo(24), "The length should be what was asked for.");
+                Assert.That(salt.GetBytes(), Is.Not.EquivalentTo(new byte[24]), "A random salt is not likely to be all zeros.");
+
+                salt = new Salt(256);
+                Assert.That(salt.Length, Is.EqualTo(32), "The length should be what was asked for.");
+                Assert.That(salt.GetBytes(), Is.Not.EquivalentTo(new byte[32]), "A random salt is not likely to be all zeros.");
+
+                salt = new Salt(new byte[16]);
+                Assert.That(salt.GetBytes(), Is.EquivalentTo(new byte[16]), "A salt with all zeros was requested.");
+
+                salt = new Salt(new byte[24]);
+                Assert.That(salt.GetBytes(), Is.EquivalentTo(new byte[24]), "A salt with all zeros was requested.");
+
+                salt = new Salt(new byte[32]);
+                Assert.That(salt.GetBytes(), Is.EquivalentTo(new byte[32]), "A salt with all zeros was requested.");
+
+                salt = new Salt(new byte[0]);
+                Assert.That(salt.Length, Is.EqualTo(0), "As a special case, zero length salt is supported - equivalent to no salt.");
+            }
+            );
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                salt = new Salt(null);
+            });
+
+            Assert.Throws<ArgumentOutOfRangeException>(() =>
+            {
+                salt = new Salt(-128);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSessionEvent.cs b/Axantum.AxCrypt.Core.Test/TestSessionEvent.cs
new file mode 100644
index 0000000..54c02e3
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSessionEvent.cs
@@ -0,0 +1,134 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSessionEvent
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructors()
+        {
+            SessionNotification sessionEvent;
+
+            sessionEvent = new SessionNotification(SessionNotificationType.ProcessExit);
+            Assert.That(sessionEvent.NotificationType, Is.EqualTo(SessionNotificationType.ProcessExit));
+            Assert.That(sessionEvent.FullName, Is.EqualTo(String.Empty));
+            Assert.That(sessionEvent.Key.Equals(Passphrase.Empty));
+
+            Passphrase key = new Passphrase("key");
+            sessionEvent = new SessionNotification(SessionNotificationType.KnownKeyChange, key);
+            Assert.That(sessionEvent.NotificationType, Is.EqualTo(SessionNotificationType.KnownKeyChange));
+            Assert.That(sessionEvent.FullName, Is.EqualTo(String.Empty));
+            Assert.That(sessionEvent.Key, Is.EqualTo(key));
+
+            string fullName = @"C:\Test\Test.txt";
+            sessionEvent = new SessionNotification(SessionNotificationType.ActiveFileChange, fullName);
+            Assert.That(sessionEvent.NotificationType, Is.EqualTo(SessionNotificationType.ActiveFileChange));
+            Assert.That(sessionEvent.FullName, Is.EqualTo(fullName));
+            Assert.That(sessionEvent.Key.Equals(Passphrase.Empty));
+
+            fullName = @"C:\Test\";
+            sessionEvent = new SessionNotification(SessionNotificationType.WatchedFolderAdded, key, fullName);
+            Assert.That(sessionEvent.NotificationType, Is.EqualTo(SessionNotificationType.WatchedFolderAdded));
+            Assert.That(sessionEvent.FullName, Is.EqualTo(fullName));
+            Assert.That(sessionEvent.Key, Is.EqualTo(key));
+        }
+
+        [Test]
+        public static void TestEquality()
+        {
+            Passphrase key = new Passphrase("passphrase1");
+            string fullName = @"C:\Test\Test.txt";
+
+            SessionNotification sessionEventA1 = new SessionNotification(SessionNotificationType.ActiveFileChange);
+            SessionNotification sessionEventA2 = new SessionNotification(SessionNotificationType.ActiveFileChange);
+            SessionNotification sessionEventA3 = new SessionNotification(SessionNotificationType.KnownKeyChange);
+
+            SessionNotification sessionEventB1 = new SessionNotification(SessionNotificationType.ActiveFileChange, key);
+            SessionNotification sessionEventB2 = new SessionNotification(SessionNotificationType.ActiveFileChange, key);
+            SessionNotification sessionEventB3 = new SessionNotification(SessionNotificationType.ActiveFileChange, new Passphrase("passphrase2"));
+
+            SessionNotification sessionEventC1 = new SessionNotification(SessionNotificationType.ActiveFileChange, fullName);
+            SessionNotification sessionEventC2 = new SessionNotification(SessionNotificationType.ActiveFileChange, fullName);
+            SessionNotification sessionEventC3 = new SessionNotification(SessionNotificationType.ActiveFileChange, @"D:\Other\Different.txt");
+
+            SessionNotification sessionEventD1 = new SessionNotification(SessionNotificationType.ActiveFileChange, key, fullName);
+            SessionNotification sessionEventD2 = new SessionNotification(SessionNotificationType.ActiveFileChange, key, fullName);
+            SessionNotification sessionEventD3 = new SessionNotification(SessionNotificationType.ActiveFileChange, new Passphrase("passphrase"), fullName);
+
+            SessionNotification nullSessionEvent = null;
+            SessionNotification sessionEventA1Alias = sessionEventA1;
+            SessionNotification nullSessionEvent2 = null;
+
+            Assert.That(sessionEventD1.GetHashCode(), Is.EqualTo(sessionEventD2.GetHashCode()));
+            Assert.That(sessionEventC1.GetHashCode(), Is.Not.EqualTo(sessionEventD1.GetHashCode()));
+
+            Assert.That(sessionEventA1 == sessionEventA1Alias);
+            Assert.That(nullSessionEvent != sessionEventA1);
+            Assert.That(sessionEventA1 != nullSessionEvent);
+            Assert.That(nullSessionEvent == nullSessionEvent2);
+
+            Assert.That(sessionEventA1 == sessionEventA2);
+            Assert.That(sessionEventA1 != sessionEventA3);
+
+            Assert.That(sessionEventB1 == sessionEventB2);
+            Assert.That(sessionEventB1 != sessionEventB3);
+
+            Assert.That(sessionEventC1 == sessionEventC2);
+            Assert.That(sessionEventC1 != sessionEventC3);
+
+            Assert.That(sessionEventD1 == sessionEventD2);
+            Assert.That(sessionEventD1 != sessionEventD3);
+
+            object objectSessionEventD3 = sessionEventD3;
+            object objectSessionEventD1 = sessionEventD1;
+
+            Assert.That(objectSessionEventD1.Equals(sessionEventD1));
+            Assert.That(!objectSessionEventD1.Equals(objectSessionEventD3));
+            Assert.That(!objectSessionEventD1.Equals(new SymmetricKey(128)));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSessionNotificationHandler.cs b/Axantum.AxCrypt.Core.Test/TestSessionNotificationHandler.cs
new file mode 100644
index 0000000..66b35fb
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSessionNotificationHandler.cs
@@ -0,0 +1,263 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSessionNotificationHandler
+    {
+        private static readonly string _fileSystemStateFilePath = Path.Combine(Path.GetTempPath(), "DummyFileSystemState.xml");
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Factory.New<IRuntimeFileInfo>(_fileSystemStateFilePath)));
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestHandleSessionEventWatchedFolderAdded()
+        {
+            MockAxCryptFile mock = new MockAxCryptFile();
+            bool called = false;
+            mock.EncryptFilesUniqueWithBackupAndWipeMock = (IEnumerable<IRuntimeFileInfo> folderInfos, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress) => { called = folderInfos.First().FullName == @"C:\My Documents\".NormalizeFilePath(); };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock, mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.WatchedFolderAdded, new Passphrase("passphrase"), @"C:\My Documents\"));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventWatchedFolderRemoved()
+        {
+            FakeRuntimeFileInfo.AddFolder(@"C:\My Documents\");
+            MockAxCryptFile mock = new MockAxCryptFile();
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+            bool called = false;
+            mock.DecryptFilesUniqueWithWipeOfOriginalMock = (IRuntimeFileInfo fileInfo, Passphrase decryptionKey, IStatusChecker statusChecker, IProgressContext progress) => { called = fileInfo.FullName == @"C:\My Documents\".NormalizeFilePath(); };
+
+            Factory.Instance.Register<AxCryptFile>(() => mock);
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock, mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.WatchedFolderRemoved, new Passphrase("passphrase"), @"C:\My Documents\"));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventLogOn()
+        {
+            MockAxCryptFile mock = new MockAxCryptFile();
+            bool called = false;
+            int folderCount = -1;
+            mock.EncryptFilesUniqueWithBackupAndWipeMock = (IEnumerable<IRuntimeFileInfo> folderInfos, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress) =>
+            {
+                folderCount = folderInfos.Count();
+                called = true;
+            };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock, mockStatusChecker.Object);
+            FakeRuntimeFileInfo.AddFolder(@"C:\WatchedFolder");
+            Passphrase key = new Passphrase("passphrase");
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\WatchedFolder", key.Thumbprint));
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.LogOn, key));
+
+            Assert.That(called, Is.True);
+            Assert.That(folderCount, Is.EqualTo(1), "There should be one folder passed for encryption as a result of the event.");
+        }
+
+        [Test]
+        public static void TestHandleSessionEventLogOff()
+        {
+            MockAxCryptFile mock = new MockAxCryptFile();
+            bool called = false;
+            mock.EncryptFilesUniqueWithBackupAndWipeMock = (IEnumerable<IRuntimeFileInfo> folderInfos, Passphrase Passphrase, Guid cryptoId, IProgressContext progress) => { called = true; };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock, mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.LogOff, new Passphrase("passphrase")));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventActiveFileChange()
+        {
+            MockFileSystemStateActions mock = new MockFileSystemStateActions();
+            bool called = false;
+            mock.CheckActiveFilesMock = (ChangedEventMode mode, IProgressContext progress) => { called = true; };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, mock, Factory.New<AxCryptFile>(), mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.ActiveFileChange, new Passphrase("passphrase")));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventSessionStart()
+        {
+            MockFileSystemStateActions mock = new MockFileSystemStateActions();
+            bool called = false;
+            mock.CheckActiveFilesMock = (ChangedEventMode mode, IProgressContext progress) => { called = true; };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, mock, Factory.New<AxCryptFile>(), mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.SessionStart, new Passphrase("passphrase")));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventPurgeActiveFiles()
+        {
+            MockFileSystemStateActions mock = new MockFileSystemStateActions();
+            bool called = false;
+            mock.PurgeActiveFilesMock = (IProgressContext progress) => { called = true; };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, mock, Factory.New<AxCryptFile>(), mockStatusChecker.Object);
+
+            handler.HandleNotification(new SessionNotification(SessionNotificationType.EncryptPendingFiles, new Passphrase("passphrase")));
+
+            Assert.That(called, Is.True);
+        }
+
+        [Test]
+        public static void TestHandleSessionEventThatCauseNoSpecificAction()
+        {
+            MockFileSystemStateActions mock = new MockFileSystemStateActions();
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, mock, Factory.New<AxCryptFile>(), mockStatusChecker.Object);
+
+            Assert.DoesNotThrow(() =>
+            {
+                handler.HandleNotification(new SessionNotification(SessionNotificationType.ProcessExit));
+                handler.HandleNotification(new SessionNotification(SessionNotificationType.SessionChange));
+                handler.HandleNotification(new SessionNotification(SessionNotificationType.KnownKeyChange));
+                handler.HandleNotification(new SessionNotification(SessionNotificationType.WorkFolderChange));
+            });
+        }
+
+        [Test]
+        public static void TestHandleSessionEventThatIsNotHandled()
+        {
+            MockFileSystemStateActions mock = new MockFileSystemStateActions();
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, mock, Factory.New<AxCryptFile>(), mockStatusChecker.Object);
+
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                handler.HandleNotification(new SessionNotification((SessionNotificationType)(-1)));
+            });
+        }
+
+        [Test]
+        public static void TestHandleSessionEvents()
+        {
+            MockAxCryptFile mock = new MockAxCryptFile();
+            int callTimes = 0;
+            mock.EncryptFilesUniqueWithBackupAndWipeMock = (IEnumerable<IRuntimeFileInfo> folderInfos, Passphrase decryptionKey, Guid cryptoId, IProgressContext progress) => { if (folderInfos.First().FullName == @"C:\My Documents\".NormalizeFilePath()) ++callTimes; };
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock, mockStatusChecker.Object);
+
+            List<SessionNotification> sessionEvents = new List<SessionNotification>();
+            sessionEvents.Add(new SessionNotification(SessionNotificationType.WatchedFolderAdded, new Passphrase("passphrase1"), @"C:\My Documents\"));
+            sessionEvents.Add(new SessionNotification(SessionNotificationType.WatchedFolderAdded, new Passphrase("passphrase"), @"C:\My Documents\"));
+
+            foreach (SessionNotification sessionEvent in sessionEvents)
+            {
+                handler.HandleNotification(sessionEvent);
+            }
+            Assert.That(callTimes, Is.EqualTo(2));
+        }
+
+        [Test]
+        public static void TestNotificationEncryptPendingFilesInLoggedOnFolders()
+        {
+            FakeRuntimeFileInfo.AddFolder(@"C:\My Documents\");
+            Mock<AxCryptFile> mock = new Mock<AxCryptFile>();
+            mock.Setup(acf => acf.EncryptFoldersUniqueWithBackupAndWipe(It.IsAny<IEnumerable<IRuntimeFileInfo>>(), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()));
+
+            Mock<IStatusChecker> mockStatusChecker = new Mock<IStatusChecker>();
+
+            SessionNotificationHandler handler = new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), mock.Object, mockStatusChecker.Object);
+            Passphrase defaultKey = new Passphrase("default");
+            Instance.KnownKeys.DefaultEncryptionKey = defaultKey;
+            Instance.FileSystemState.AddWatchedFolder(new WatchedFolder(@"C:\My Documents\", defaultKey.Thumbprint));
+
+            List<SessionNotification> sessionEvents = new List<SessionNotification>();
+            sessionEvents.Add(new SessionNotification(SessionNotificationType.EncryptPendingFiles));
+
+            foreach (SessionNotification sessionEvent in sessionEvents)
+            {
+                handler.HandleNotification(sessionEvent);
+            }
+            mock.Verify(acf => acf.EncryptFoldersUniqueWithBackupAndWipe(It.Is<IEnumerable<IRuntimeFileInfo>>(infos => infos.Any((i) => i.FullName == @"C:\My Documents\".NormalizeFolderPath())), It.IsAny<Passphrase>(), It.IsAny<Guid>(), It.IsAny<IProgressContext>()), Times.Exactly(1));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSessionNotificationMonitor.cs b/Axantum.AxCrypt.Core.Test/TestSessionNotificationMonitor.cs
new file mode 100644
index 0000000..db1852e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSessionNotificationMonitor.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSessionNotificationMonitor
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestNotificationDuringProcessingOfNotification()
+        {
+            int notificationCount = 0;
+
+            SessionNotify monitor = new SessionNotify();
+            monitor.Notification += (sender, e) =>
+            {
+                if (e.Notification.NotificationType == SessionNotificationType.LogOn)
+                {
+                    ++notificationCount;
+                }
+            };
+
+            monitor.Notify(new SessionNotification(SessionNotificationType.LogOn));
+            Assert.That(notificationCount, Is.EqualTo(1));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSubKey.cs b/Axantum.AxCrypt.Core.Test/TestSubKey.cs
new file mode 100644
index 0000000..bd48f7e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSubKey.cs
@@ -0,0 +1,81 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSubkey
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSubkeyMethods()
+        {
+            SymmetricKey key = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            Subkey subkey = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                subkey = new Subkey(null, HeaderSubkey.Data);
+            });
+
+            Assert.Throws<InternalErrorException>(() =>
+            {
+                subkey = new Subkey(key, HeaderSubkey.None);
+            });
+
+            subkey = new Subkey(key, HeaderSubkey.Data);
+            Assert.That(subkey.Key.Size, Is.EqualTo(128), "A Subkey is exactly 16 bytes.");
+            Assert.That(subkey.Key.GetBytes(), Is.EquivalentTo(new byte[] { 0x5f, 0xfe, 0x14, 0x56, 0xd5, 0x94, 0xf9, 0x22, 0x42, 0xe3, 0x66, 0x8f, 0x8c, 0xe6, 0xea, 0xc6 }), "Comparing with a pre-calculated value assumed to be correct.");
+            subkey = new Subkey(key, HeaderSubkey.Headers);
+            Assert.That(subkey.Key.Size, Is.EqualTo(128), "A Subkey is exactly 16 bytes.");
+            Assert.That(subkey.Key.GetBytes(), Is.EquivalentTo(new byte[] { 0x1c, 0x81, 0x0e, 0xe7, 0x65, 0xe7, 0x0b, 0x8f, 0x7a, 0xa3, 0x2b, 0x03, 0x05, 0x07, 0xf8, 0x8a }), "Comparing with a pre-calculated value assumed to be correct.");
+            subkey = new Subkey(key, HeaderSubkey.Hmac);
+            Assert.That(subkey.Key.Size, Is.EqualTo(128), "A Subkey is exactly 16 bytes.");
+            Assert.That(subkey.Key.GetBytes(), Is.EquivalentTo(new byte[] { 0xdb, 0xf1, 0x84, 0x11, 0x2e, 0xb9, 0x11, 0x16, 0x59, 0x71, 0x2b, 0xaf, 0xcf, 0xf2, 0xab, 0x24 }), "Comparing with a pre-calculated value assumed to be correct.");
+            subkey = new Subkey(key, HeaderSubkey.Validator);
+            Assert.That(subkey.Key.Size, Is.EqualTo(128), "A Subkey is exactly 16 bytes.");
+            Assert.That(subkey.Key.GetBytes(), Is.EquivalentTo(new byte[] { 0x45, 0x22, 0xa0, 0x3d, 0x98, 0x00, 0x9d, 0x55, 0x45, 0xed, 0x42, 0xfb, 0xd8, 0x35, 0x78, 0xd0 }), "Comparing with a pre-calculated value assumed to be correct.");
+
+            Assert.That(new Subkey(key, HeaderSubkey.Hmac).Key.GetBytes(), Is.EquivalentTo(new Subkey(key, HeaderSubkey.Hmac).Key.GetBytes()), "The subkey generation should be stable.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSymmetricIV.cs b/Axantum.AxCrypt.Core.Test/TestSymmetricIV.cs
new file mode 100644
index 0000000..26d3394
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSymmetricIV.cs
@@ -0,0 +1,75 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSymmetricIV
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            SymmetricIV iv = null;
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                iv = new SymmetricIV(null);
+            });
+
+            // Use the instance to avoid FxCop errors.
+            Object.Equals(iv, null);
+        }
+
+        [Test]
+        public static void TestMethods()
+        {
+            SymmetricIV zeroIV = SymmetricIV.Zero128;
+            Assert.That(zeroIV.GetBytes(), Is.EquivalentTo(new byte[16]), "The IV 'zero' should consist of all zeros.");
+
+            SymmetricIV iv = new SymmetricIV(new byte[16] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            Assert.That(iv.GetBytes(), Is.EquivalentTo(new byte[16] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }), "An IV specified should consist of just those bytes.");
+
+            iv = new SymmetricIV(128);
+            Assert.That(iv.GetBytes(), Is.Not.EquivalentTo(new byte[16]), "A random iv will in practice never be all zeros.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSymmetricKey.cs b/Axantum.AxCrypt.Core.Test/TestSymmetricKey.cs
new file mode 100644
index 0000000..448e85c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSymmetricKey.cs
@@ -0,0 +1,137 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSymmetricKey
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            SymmetricKey key = null;
+            Assert.DoesNotThrow(() =>
+            {
+                key = new SymmetricKey(new byte[16]);
+            });
+            Assert.DoesNotThrow(() =>
+            {
+                key = new SymmetricKey(new byte[24]);
+            });
+            Assert.DoesNotThrow(() =>
+            {
+                key = new SymmetricKey(new byte[32]);
+            });
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                key = new SymmetricKey((byte[])null);
+            });
+
+            // Use the instance to avoid FxCop errors.
+            Object.Equals(key, null);
+        }
+
+        [Test]
+        public static void TestMethods()
+        {
+            SymmetricKey key = new SymmetricKey(128);
+            Assert.That(key.GetBytes().Length, Is.EqualTo(16), "The default key length is 128 bits.");
+            Assert.That(key.GetBytes(), Is.Not.EquivalentTo(new byte[16]), "A random key cannot be expected to be all zeros.");
+
+            SymmetricKey specifiedKey = new SymmetricKey(key.GetBytes());
+            Assert.That(specifiedKey.GetBytes(), Is.EquivalentTo(key.GetBytes()), "The specified key should contain the bits given to it.");
+        }
+
+        [Test]
+        public static void TestEquals()
+        {
+            SymmetricKey key1 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            SymmetricKey key2 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            SymmetricKey key3 = new SymmetricKey(128);
+
+            Assert.That(!key1.Equals(null), "A key is never equal to a null reference.");
+            Assert.That(key1.Equals(key2), "Two different, but equivalent keys should compare equal.");
+            Assert.That(!key1.Equals(key3), "Two really different keys should not compare equal.");
+        }
+
+        [Test]
+        public static void TestObjectEquals()
+        {
+            object key1 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            object key2 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            object key3 = new SymmetricKey(128);
+
+            Assert.That(!key1.Equals(null), "A key is never equal to a null reference.");
+            Assert.That(key1.Equals(key2), "Two different, but equivalent keys should compare equal.");
+            Assert.That(!key1.Equals(key3), "Two really different keys should not compare equal.");
+
+            Assert.That(key1.GetHashCode(), Is.EqualTo(key2.GetHashCode()), "The hashcodes should be the same for two different but equivalent keys.");
+        }
+
+        [Test]
+        public static void TestOperatorEquals()
+        {
+            SymmetricKey key1 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            SymmetricKey key2 = new SymmetricKey(new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            SymmetricKey key3 = new SymmetricKey(128);
+            SymmetricKey key3alias = key3;
+            SymmetricKey nullKey = null;
+
+            Assert.That(key3 == key3alias, "A key is always equal to itself.");
+            Assert.That(key1 != nullKey, "A key is never equal to a null reference.");
+            Assert.That(nullKey != key1, "A key is never equal to a null reference.");
+            Assert.That(key1 == key2, "Two different, but equivalent keys should compare equal.");
+            Assert.That(key1 != key3, "Two really different keys should not compare equal.");
+        }
+
+        [Test]
+        public static void TestThumbprint()
+        {
+            Passphrase key1 = new Passphrase("genericPassphrase");
+
+            SymmetricKeyThumbprint originalThumbprint = key1.Thumbprint;
+            Assert.That(originalThumbprint, Is.EqualTo(key1.Thumbprint), "The thumbprints should be the same.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestSymmetricKeyThumbprint.cs b/Axantum.AxCrypt.Core.Test/TestSymmetricKeyThumbprint.cs
new file mode 100644
index 0000000..eb5b243
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestSymmetricKeyThumbprint.cs
@@ -0,0 +1,124 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestSymmetricKeyThumbprint
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            Passphrase nullKey = null;
+            Salt nullSalt = null;
+            Assert.Throws<ArgumentNullException>(() => { if (new SymmetricKeyThumbprint(nullKey, new Salt(128), 10) == null) { } });
+            Assert.Throws<ArgumentNullException>(() => { if (new SymmetricKeyThumbprint(new Passphrase("passphrase"), nullSalt, 10) == null) { } });
+        }
+
+        [Test]
+        public static void TestAesKeyThumbprintMethods()
+        {
+            Passphrase key1 = new Passphrase("key");
+            Passphrase key2 = new Passphrase("key");
+            Salt salt1 = new Salt(512);
+            Salt salt2 = new Salt(salt1.GetBytes());
+
+            SymmetricKeyThumbprint thumbprint1 = new SymmetricKeyThumbprint(key1, salt1, 10);
+            SymmetricKeyThumbprint thumbprint2 = new SymmetricKeyThumbprint(key2, salt2, 10);
+
+            Assert.That(thumbprint1 == thumbprint2, "Two thumb prints made from the same key and salt bytes, although different AesKey instances should be equivalent.");
+
+            SymmetricKeyThumbprint thumbprint3 = new SymmetricKeyThumbprint(new Passphrase("passphrase"), new Salt(512), 10);
+            Assert.That(thumbprint2 != thumbprint3, "Two very different keys and salts should not be equivalent.");
+        }
+
+        [Test]
+        public static void TestComparisons()
+        {
+            Passphrase key1 = new Passphrase("samekey");
+            Passphrase key2 = new Passphrase("samekey");
+            Salt salt1 = new Salt(512);
+            Salt salt2 = new Salt(512);
+
+            SymmetricKeyThumbprint thumbprint1a = new SymmetricKeyThumbprint(key1, salt1, 13);
+            SymmetricKeyThumbprint thumbprint1a_alias = thumbprint1a;
+            SymmetricKeyThumbprint thumbprint1b = new SymmetricKeyThumbprint(key1, salt2, 25);
+            SymmetricKeyThumbprint thumbprint2a = new SymmetricKeyThumbprint(key2, salt2, 25);
+            SymmetricKeyThumbprint thumbprint2b = new SymmetricKeyThumbprint(key2, salt1, 13);
+            SymmetricKeyThumbprint nullThumbprint = null;
+
+            Assert.That(thumbprint1a == thumbprint1a_alias, "Same instance should of course compare equal.");
+            Assert.That(nullThumbprint != thumbprint1a, "A null should not compare equal to any other instance.");
+            Assert.That(thumbprint1a != nullThumbprint, "A null should not compare equal to any other instance.");
+            Assert.That(thumbprint1a == thumbprint2b, "Same raw key and salt, but different instance, should compare equal.");
+            Assert.That(thumbprint1b == thumbprint2a, "Same raw key and salt, but different instance, should compare equal.");
+            Assert.That(thumbprint1a != thumbprint1b, "Same raw key but different salt, should compare inequal.");
+            Assert.That(thumbprint2a != thumbprint2b, "Same raw key but different salt, should compare inequal.");
+
+            object object1a = thumbprint1a;
+            object object2b = thumbprint2b;
+            Assert.That(object1a.Equals(nullThumbprint), Is.False, "An instance does not equals null.");
+            Assert.That(object1a.Equals(object2b), Is.True, "The two instances are equivalent.");
+
+            object badTypeObject = key1;
+            Assert.That(object1a.Equals(badTypeObject), Is.False, "The object being compared to is of the wrong type.");
+        }
+
+        [Test]
+        public static void TestGetHashCode()
+        {
+            Passphrase key1 = new Passphrase("samekey");
+            Passphrase key2 = new Passphrase("samekey");
+            Salt salt1 = new Salt(512);
+            Salt salt2 = new Salt(512);
+
+            SymmetricKeyThumbprint thumbprint1a = new SymmetricKeyThumbprint(key1, salt1, 17);
+            SymmetricKeyThumbprint thumbprint1b = new SymmetricKeyThumbprint(key1, salt2, 17);
+            SymmetricKeyThumbprint thumbprint2a = new SymmetricKeyThumbprint(key2, salt2, 17);
+
+            Assert.That(thumbprint1a.GetHashCode() != thumbprint1b.GetHashCode(), "The salt is different, so the hash code should be different.");
+            Assert.That(thumbprint1b.GetHashCode() == thumbprint2a.GetHashCode(), "The keys are equivalent, and the salt the same, so the hash code should be different.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestThreadWorker.cs b/Axantum.AxCrypt.Core.Test/TestThreadWorker.cs
new file mode 100644
index 0000000..d2b81b0
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestThreadWorker.cs
@@ -0,0 +1,259 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestThreadWorker
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimple()
+        {
+            int workThreadId = -1;
+            FileOperationContext returnedStatus = new FileOperationContext(String.Empty, FileOperationStatus.UnspecifiedError);
+
+            bool done = false;
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        workThreadId = Thread.CurrentThread.ManagedThreadId;
+                        e.Result = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                    };
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        returnedStatus = e.Result;
+                        done = true;
+                    };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(returnedStatus.Status, Is.EqualTo(FileOperationStatus.Success), "The status should be returned as successful.");
+            Assert.That(workThreadId, Is.Not.EqualTo(Thread.CurrentThread.ManagedThreadId), "The work should not be performed on the caller thread.");
+            Assert.That(done, Is.True, "The background work must have executed the completed handler now.");
+        }
+
+        [Test]
+        public static void TestProgress()
+        {
+            FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+            int progressCalls = 0;
+
+            ProgressContext progress = new ProgressContext();
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(progress, false))
+            {
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        environment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1);
+                        e.Progress.AddCount(1);
+                        e.Result = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                    };
+                progress.Progressing += (object sender, ProgressEventArgs e) =>
+                    {
+                        ++progressCalls;
+                    };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(progressCalls, Is.EqualTo(1), "The Progressing event should be raised exactly one time.");
+        }
+
+        [Test]
+        public static void TestObjectDisposedException()
+        {
+            IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false);
+            worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    e.Result = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                };
+            try
+            {
+                worker.Run();
+                worker.Join();
+            }
+            finally
+            {
+                worker.Dispose();
+            }
+
+            bool hasCompleted = false;
+            Assert.Throws<ObjectDisposedException>(() => { worker.Run(); });
+            Assert.DoesNotThrow(() => { worker.Join(); });
+            Assert.DoesNotThrow(() => { hasCompleted = worker.HasCompleted; });
+            Assert.That(hasCompleted, "Even though the thread has completed, the variable should be set, since we allow calls to HasCompleted even after Dispose().");
+            Assert.DoesNotThrow(() => { worker.Dispose(); });
+        }
+
+        [Test]
+        public static void TestCancellationByException()
+        {
+            bool wasCanceled = false;
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        throw new OperationCanceledException();
+                    };
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        wasCanceled = e.Result.Status == FileOperationStatus.Canceled;
+                    };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(wasCanceled, Is.True, "The operation was canceled and should return status as such.");
+        }
+
+        [Test]
+        public static void TestCancellationByRequest()
+        {
+            bool wasCanceled = false;
+            FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new CancelProgressContext(new ProgressContext()), false))
+            {
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    e.Progress.Cancel = true;
+                    environment.CurrentTiming.CurrentTiming = TimeSpan.FromSeconds(1);
+                    e.Progress.AddCount(1);
+                };
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    wasCanceled = e.Result.Status == FileOperationStatus.Canceled;
+                };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(wasCanceled, Is.True, "The operation was canceled and should return status as such.");
+        }
+
+        [Test]
+        public static void TestPrepare()
+        {
+            bool wasPrepared = false;
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                worker.Prepare += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        wasPrepared = true;
+                    };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(wasPrepared, Is.True, "The Prepare event should be raised.");
+        }
+
+        [Test]
+        public static void TestErrorSetInWorkCompleted()
+        {
+            bool errorInWork = false;
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    throw new InvalidOperationException();
+                };
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    errorInWork = e.Result.Status == FileOperationStatus.Exception;
+                };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(errorInWork, Is.True, "The operation was interrupted by an exception and should return status as such.");
+        }
+
+        [Test]
+        public static void TestHasCompleted()
+        {
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                bool wasCompletedInWork = false;
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    wasCompletedInWork = worker.HasCompleted;
+                };
+                bool wasCompletedInCompleted = false;
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    wasCompletedInCompleted = worker.HasCompleted;
+                };
+                worker.Run();
+                worker.Join();
+                Assert.That(!wasCompletedInWork, "Completion is not set as true in the work event.");
+                Assert.That(!wasCompletedInCompleted, "Completion is not set as true until after the completed event.");
+                Assert.That(worker.HasCompleted, "Completion should be set as true when the thread is joined.");
+            }
+        }
+
+        [Test]
+        public static void TestExceptionDuringWork()
+        {
+            FileOperationContext status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+            using (IThreadWorker worker = Instance.Portable.ThreadWorker(new ProgressContext(), false))
+            {
+                worker.Work += (sender, e) =>
+                {
+                    throw new InvalidOperationException("Something went intentionally wrong.");
+                };
+                worker.Completed += (sender, e) =>
+                {
+                    status = e.Result;
+                };
+                worker.Run();
+                worker.Join();
+            }
+
+            Assert.That(status.Status, Is.EqualTo(FileOperationStatus.Exception));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestThreadWorkerProgressContext.cs b/Axantum.AxCrypt.Core.Test/TestThreadWorkerProgressContext.cs
new file mode 100644
index 0000000..b3541ed
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestThreadWorkerProgressContext.cs
@@ -0,0 +1,166 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestThreadWorkerProgressContext
+    {
+        private static Mock<IProgressContext> _progressMock;
+
+        private static ThreadWorkerProgressContext _progress;
+
+        [SetUp]
+        public static void Setup()
+        {
+            _progressMock = new Mock<IProgressContext>();
+
+            _progress = new ThreadWorkerProgressContext(_progressMock.Object);
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestAddCount()
+        {
+            _progress.AddCount(456);
+
+            _progressMock.Verify(p => p.AddCount(It.Is<long>(l => l == 456)), Times.Once);
+        }
+
+        [Test]
+        public static void TestAddTotal()
+        {
+            _progress.AddTotal(123);
+
+            _progressMock.Verify(p => p.AddTotal(It.Is<long>(l => l == 123)), Times.Once);
+        }
+
+        [Test]
+        public static void TestAllItemsConfirmed()
+        {
+            bool allConfirmed = _progress.AllItemsConfirmed;
+            _progress.AllItemsConfirmed = true;
+
+            Assert.That(allConfirmed, Is.False);
+            _progressMock.VerifyGet(p => p.AllItemsConfirmed, Times.Once);
+            _progressMock.VerifySet(p => p.AllItemsConfirmed = true, Times.Once);
+        }
+
+        [Test]
+        public static void TestCancel()
+        {
+            bool cancel = _progress.Cancel;
+            _progress.Cancel = true;
+
+            Assert.That(cancel, Is.False);
+            _progressMock.VerifyGet(p => p.Cancel, Times.Once);
+            _progressMock.VerifySet(p => p.Cancel = true, Times.Once);
+        }
+
+        [Test]
+        public static void TestEnterSingleThread()
+        {
+            _progress.EnterSingleThread();
+            _progressMock.Verify(m => m.EnterSingleThread(), Times.Once);
+
+            _progress.EnterSingleThread();
+            _progressMock.Verify(m => m.EnterSingleThread(), Times.Once);
+        }
+
+        [Test]
+        public static void TestLeaveSingleThread()
+        {
+            _progress.LeaveSingleThread();
+            _progressMock.Verify(m => m.LeaveSingleThread(), Times.Never, "No call should be made when this instance is not in single logical thread mode");
+
+            _progress.LeaveSingleThread();
+            _progressMock.Verify(m => m.LeaveSingleThread(), Times.Never, "No call should be made when this instance is not in single logical thread mode");
+
+            _progress.EnterSingleThread();
+            _progressMock.Verify(m => m.EnterSingleThread(), Times.Once, "One call should be made when this instance is put in single logical thread mode");
+
+            _progress.LeaveSingleThread();
+            _progressMock.Verify(m => m.LeaveSingleThread(), Times.Once, "One call should be made when this instance was in single logical thread mode");
+
+            _progress.LeaveSingleThread();
+            _progressMock.Verify(m => m.LeaveSingleThread(), Times.Once, "No further call should be made when this instance is not in single logical thread mode");
+        }
+
+        [Test]
+        public static void TestNotifyLevelFinished()
+        {
+            _progress.NotifyLevelFinished();
+            _progressMock.Verify(p => p.NotifyLevelFinished(), Times.Once);
+        }
+
+        [Test]
+        public static void TestNotifyLevelStart()
+        {
+            _progress.NotifyLevelStart();
+            _progressMock.Verify(p => p.NotifyLevelStart(), Times.Once);
+        }
+
+        [Test]
+        public static void TestProgressing()
+        {
+            int percent = 0;
+            EventHandler<ProgressEventArgs> handler = (sender, e) =>
+            {
+                percent = e.Percent;
+            };
+            _progress.Progressing += handler;
+
+            _progressMock.Raise(p => p.Progressing += null, new ProgressEventArgs(13));
+
+            Assert.That(percent, Is.EqualTo(13));
+
+            _progress.Progressing -= handler;
+            _progressMock.Raise(p => p.Progressing += null, new ProgressEventArgs(26));
+
+            Assert.That(percent, Is.EqualTo(13));
+        }
+
+        [Test]
+        public static void TestRemoveCount()
+        {
+            _progress.RemoveCount(999, 777);
+
+            _progressMock.Verify(p => p.RemoveCount(It.Is<long>(l => l == 999), It.Is<long>(l => l == 777)), Times.Once);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestUnrecognizedHeaderBlock .cs b/Axantum.AxCrypt.Core.Test/TestUnrecognizedHeaderBlock .cs
new file mode 100644
index 0000000..69f2712
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestUnrecognizedHeaderBlock .cs	
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestUnrecognizedHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            UnrecognizedHeaderBlock unrecognizedHeaderBlock = new UnrecognizedHeaderBlock(HeaderBlockType.Unrecognized, new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+            UnrecognizedHeaderBlock cloned = (UnrecognizedHeaderBlock)unrecognizedHeaderBlock.Clone();
+            Assert.That(unrecognizedHeaderBlock, Is.Not.SameAs(cloned), "The clone should not be the same reference.");
+            Assert.That(cloned.GetDataBlockBytes(), Is.EquivalentTo(unrecognizedHeaderBlock.GetDataBlockBytes()), "The clone should have equivalent data block bytes as the original.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestUpdateCheck.cs b/Axantum.AxCrypt.Core.Test/TestUpdateCheck.cs
new file mode 100644
index 0000000..12a93c9
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestUpdateCheck.cs
@@ -0,0 +1,428 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestUpdateCheck
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestVersionUpdated()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.307.0"",""R"":307,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 307, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.NewerVersionIsAvailable), "The new version was newer.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(newVersion), "The new version should be passed back.");
+        }
+
+        [Test]
+        public static void TestVersionUpdatedWithInvalidVersionFormatFromServer()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                // The version returned has 5 components - bad!
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.307.0.0"",""R"":307,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck), "This is not a successful check, and it was DateTime.MinValue since the last.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(UpdateCheck.VersionUnknown), "The new version has 5 components, and should be parsed as unknown.");
+
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                // The version returned is an empty string - bad!
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":"""",""R"":307,""S"":0,""M"":""OK""}");
+            };
+
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck), "This is not a successful check, and it was DateTime.MinValue since the last.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(UpdateCheck.VersionUnknown), "The new version is an empty string and should be parse as unknown.");
+        }
+
+        [Test]
+        public static void TestArgumentNullException()
+        {
+            string nullVersion = null;
+            Uri nullUrl = null;
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 307, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                Assert.Throws<ArgumentNullException>(() => { updateCheck.CheckInBackground(DateTime.MinValue, nullVersion, restApiUrl, updateWebPageUrl); }, "Null argument should throw.");
+                Assert.Throws<ArgumentNullException>(() => { updateCheck.CheckInBackground(DateTime.MinValue, newVersion.ToString(), nullUrl, updateWebPageUrl); }, "Null argument should throw.");
+                Assert.Throws<ArgumentNullException>(() => { updateCheck.CheckInBackground(DateTime.MinValue, newVersion.ToString(), restApiUrl, nullUrl); }, "Null argument should throw.");
+
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+        }
+
+        [Test]
+        public static void TestDoubleDisposeAndObjectDisposedException()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.307.0"",""R"":307,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 307, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            UpdateCheck updateCheck = new UpdateCheck(thisVersion);
+            updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+            {
+                eventArgs = e;
+            };
+            updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+            updateCheck.WaitForBackgroundCheckComplete();
+            updateCheck.Dispose();
+
+            Assert.DoesNotThrow(updateCheck.Dispose);
+            Assert.Throws<ObjectDisposedException>(() => { updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl); });
+            Assert.Throws<ObjectDisposedException>(updateCheck.WaitForBackgroundCheckComplete);
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.NewerVersionIsAvailable), "The new version was newer.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(newVersion), "The new version should be passed back.");
+        }
+
+        [Test]
+        public static void TestVersionNotUpdatedNotCheckedBefore()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.207.0"",""R"":207,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 207, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.IsUpToDateOrRecentlyChecked), "The new version was older, so this version is up to date.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(newVersion), "The new version should be passed back.");
+        }
+
+        [Test]
+        public static void TestVersionSameAndCheckedRecently()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.300.0"",""R"":300,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(utcNow.AddDays(-2), UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.IsUpToDateOrRecentlyChecked), "The new version was the same and we checked recently.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(newVersion), "The new version should be passed back.");
+        }
+
+        [Test]
+        public static void TestVersionAlreadyCheckedRecently()
+        {
+            bool wasCalled = false;
+            FakeWebCaller webCaller = new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.400.0"",""R"":300,""S"":0,""M"":""OK""}");
+            webCaller.Calling += (object sender, EventArgs e) => { wasCalled = true; };
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return webCaller;
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(utcNow.AddHours(-1), thisVersion.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.IsUpToDateOrRecentlyChecked), "No check should be made, and it is assumed this version is up to date.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(updateWebPageUrl), "The original URL should be passed in the event args since no call is made.");
+            Assert.That(wasCalled, Is.False, "The web caller should never be called.");
+            Assert.That(eventArgs.Version, Is.EqualTo(thisVersion), "The new version should not be passed back, since no call should be made.");
+        }
+
+        [Test]
+        public static void TestOnlyOneCallMadeWhenCheckIsMadeWithCheckPending()
+        {
+            int calls = 0;
+            ManualResetEvent wait = new ManualResetEvent(false);
+            FakeWebCaller webCaller = new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.400.0"",""R"":300,""S"":0,""M"":""OK""}");
+            webCaller.Calling += (object sender, EventArgs e) => { wait.WaitOne(); ++calls; };
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return webCaller;
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Version newVersion = new Version(2, 0, 400, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                wait.Set();
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.NewerVersionIsAvailable), "One check should be made, indicating a newer version is available.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The new URL should be passed since a call is made.");
+            Assert.That(calls, Is.EqualTo(1), "The web caller should only be called once.");
+            Assert.That(eventArgs.Version, Is.EqualTo(newVersion), "The new version should be passed back, since one call should be made.");
+        }
+
+        [Test]
+        public static void TestExceptionDuringVersionCall()
+        {
+            FakeWebCaller webCaller = new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.400.0"",""R"":300,""S"":0,""M"":""OK""}");
+            webCaller.Calling += (object sender, EventArgs e) => { throw new InvalidOperationException("Oops - a forced exception during the call."); };
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return webCaller;
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck), "No check could be made, and it was a long time since a check was made.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(updateWebPageUrl), "The original URL should be passed since the call failed.");
+            Assert.That(eventArgs.Version, Is.EqualTo(UpdateCheck.VersionUnknown), "An unknown version should be returned, since the call failed.");
+        }
+
+        [Test]
+        public static void TestExceptionDuringVersionCallButRecentlyChecked()
+        {
+            FakeWebCaller webCaller = new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""2.0.400.0"",""R"":300,""S"":0,""M"":""OK""}");
+            webCaller.Calling += (object sender, EventArgs e) => { throw new InvalidOperationException("Oops - a forced exception during the call."); };
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return webCaller;
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(utcNow.AddDays(-2), UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called with non-null VersionEventArgs.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.ShortTimeSinceLastSuccessfulCheck), "Although the check failed, a check was recently made a short time ago.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(updateWebPageUrl), "The original URL should be passed since the call failed.");
+            Assert.That(eventArgs.Version, Is.EqualTo(UpdateCheck.VersionUnknown), "An unknown version should be returned, since the call failed.");
+        }
+
+        [Test]
+        public static void TestInvalidVersionReturned()
+        {
+            SetupAssembly.FakeRuntimeEnvironment.WebCallerCreator = () =>
+            {
+                return new FakeWebCaller(@"{""U"":""http://localhost/AxCrypt/Downloads.html"",""V"":""x.y.z.z"",""R"":207,""S"":0,""M"":""OK""}");
+            };
+
+            DateTime utcNow = DateTime.UtcNow;
+            SetupAssembly.FakeRuntimeEnvironment.TimeFunction = () => { return utcNow; };
+
+            Version thisVersion = new Version(2, 0, 300, 0);
+            Uri restApiUrl = new Uri("http://localhost/RestApi.asxh/axcrypt2version");
+            Uri updateWebPageUrl = new Uri("http://www.axantum.com/");
+            VersionEventArgs eventArgs = null;
+            using (UpdateCheck updateCheck = new UpdateCheck(thisVersion))
+            {
+                updateCheck.VersionUpdate += (object sender, VersionEventArgs e) =>
+                {
+                    eventArgs = e;
+                };
+                updateCheck.CheckInBackground(DateTime.MinValue, UpdateCheck.VersionUnknown.ToString(), restApiUrl, updateWebPageUrl);
+                updateCheck.WaitForBackgroundCheckComplete();
+            }
+
+            Assert.That(eventArgs, Is.Not.Null, "The VersionUpdate event should be called even when an invalid version is returned.");
+            Assert.That(eventArgs.VersionUpdateStatus, Is.EqualTo(VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck), "No check has been performed previously and no new version is known.");
+            Assert.That(eventArgs.UpdateWebpageUrl, Is.EqualTo(new Uri("http://localhost/AxCrypt/Downloads.html")), "The right URL should be passed in the event args.");
+            Assert.That(eventArgs.Version, Is.EqualTo(UpdateCheck.VersionUnknown), "The version is not known since it could not be parsed.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestUserSettings.cs b/Axantum.AxCrypt.Core.Test/TestUserSettings.cs
new file mode 100644
index 0000000..3bf440f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestUserSettings.cs
@@ -0,0 +1,200 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestUserSettings
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+            FakeRuntimeFileInfo.AddFolder(@"C:\Folder\");
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSerializeDeserialize()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new IterationCalculator());
+
+            Assert.That(settings.DebugMode, Is.False, "The DebugMode is always false by default.");
+            settings.DebugMode = true;
+            Assert.That(settings.DebugMode, Is.True, "The DebugMode was set to true.");
+
+            settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new IterationCalculator());
+            Assert.That(settings.DebugMode, Is.True, "The DebugMode was set to true, and should have been saved.");
+        }
+
+        [Test]
+        public static void TestNamedStronglyTypedProperties()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new IterationCalculator());
+
+            settings.CultureName = "sv-SE";
+            Assert.That(settings.CultureName, Is.EqualTo("sv-SE"), "The value should be this.");
+
+            settings.AxCrypt2VersionCheckUrl = new Uri("http://localhost/versioncheck");
+            Assert.That(settings.AxCrypt2VersionCheckUrl, Is.EqualTo(new Uri("http://localhost/versioncheck")), "The value should be this.");
+
+            settings.UpdateUrl = new Uri("http://localhost/update");
+            Assert.That(settings.UpdateUrl, Is.EqualTo(new Uri("http://localhost/update")), "The value should be this.");
+
+            settings.LastUpdateCheckUtc = new DateTime(2001, 02, 03);
+            Assert.That(settings.LastUpdateCheckUtc, Is.EqualTo(new DateTime(2001, 02, 03)), "The value should be this.");
+
+            settings.NewestKnownVersion = "1.2.3.4";
+            Assert.That(settings.NewestKnownVersion, Is.EqualTo("1.2.3.4"), "The value should be this.");
+
+            settings.DebugMode = true;
+            Assert.That(settings.DebugMode, Is.True, "The value should be this.");
+
+            settings.AxCrypt2HelpUrl = new Uri("http://localhost/help");
+            Assert.That(settings.AxCrypt2HelpUrl, Is.EqualTo(new Uri("http://localhost/help")), "The value should be this.");
+
+            settings.DisplayEncryptPassphrase = true;
+            Assert.That(settings.DisplayEncryptPassphrase, Is.True, "The value should be this.");
+
+            settings.DisplayDecryptPassphrase = true;
+            Assert.That(settings.DisplayDecryptPassphrase, Is.True, "The value should be this.");
+
+            settings.SetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId, 1234);
+            Assert.That(settings.GetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId), Is.EqualTo(1234), "The value should be this.");
+
+            Salt salt = new Salt(128);
+            settings.ThumbprintSalt = salt;
+            Assert.That(settings.ThumbprintSalt.GetBytes(), Is.EqualTo(salt.GetBytes()), "The value should be this.");
+
+            settings.SessionNotificationMinimumIdle = new TimeSpan(1, 2, 3);
+            Assert.That(settings.SessionNotificationMinimumIdle, Is.EqualTo(new TimeSpan(1, 2, 3)), "The value should be this.");
+
+            settings.SetKeyWrapIterations(V2Aes256CryptoFactory.CryptoId, 999);
+            Assert.That(settings.GetKeyWrapIterations(V2Aes256CryptoFactory.CryptoId), Is.EqualTo(999));
+        }
+
+        [Test]
+        public static void TestKeyWrapIterationCalculator()
+        {
+            IterationCalculator calculator = Mock.Of<IterationCalculator>(c => c.KeyWrapIterations(It.Is<Guid>(g => g == V1Aes128CryptoFactory.CryptoId)) == 666);
+
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), calculator);
+            Assert.That(settings.GetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId), Is.EqualTo(666));
+        }
+
+        [Test]
+        public static void TestThumbprintSaltDefault()
+        {
+            Salt salt = new Salt(128);
+            Factory.Instance.Register((int n) => salt);
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+
+            Assert.That(settings.ThumbprintSalt.GetBytes(), Is.EqualTo(salt.GetBytes()), "The value should be this.");
+        }
+
+        [Test]
+        public static void TestUpdateToSameValueCausesNoSave()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+            int writeCount = 0;
+            FakeRuntimeFileInfo.OpeningForWrite += (sender, e) => ++writeCount;
+
+            settings.CultureName = "sv-SE";
+            Assert.That(settings.CultureName, Is.EqualTo("sv-SE"), "The value should be this.");
+            Assert.That(writeCount, Is.EqualTo(1), "One opening for write should have happened.");
+
+            settings.CultureName = "sv-SE";
+            Assert.That(settings.CultureName, Is.EqualTo("sv-SE"), "The value should be this.");
+            Assert.That(writeCount, Is.EqualTo(1), "Still only one opening for write should have happened.");
+        }
+
+        [Test]
+        public static void TestLoadOfDefaultKeyedValues()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+
+            int n = settings.Load<int>("MyKey");
+            Assert.That(n, Is.EqualTo(default(int)), "Since the key is unknown, the default value should be returned.");
+
+            settings.Store<int>("MyKey", 1234);
+            n = settings.Load<int>("MyKey");
+            Assert.That(n, Is.EqualTo(1234), "Since the value has been updated, this is what should be returned.");
+        }
+
+        [Test]
+        public static void TestLoadOfInvalidFormatKeyValueWithFallbackReturn()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+            settings.Store<string>("MyKey", "NotANumber");
+
+            int n = settings.Load("MyKey", () => 555);
+            Assert.That(n, Is.EqualTo(555), "Since the value is invalid, but there is a fallback this should be returned.");
+        }
+
+        [Test]
+        public static void TestLoadOfInvalidFormatKeyWrapSaltWithFallbackReturn()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+            settings.Store<string>("MyKey", "NotASalt");
+
+            Salt salt = new Salt(128);
+            Salt loadedSalt = settings.Load("MyKey", () => salt);
+            Assert.That(loadedSalt.GetBytes(), Is.EquivalentTo(salt.GetBytes()), "Since the value is invalid, but there is a fallback this should be returned.");
+        }
+
+        [Test]
+        public static void TestLoadOfUriWithFallbackReturn()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+
+            Uri url = settings.Load("MyKey", new Uri("http://localhost/fallback"));
+            Assert.That(url, Is.EqualTo(new Uri("http://localhost/fallback")));
+        }
+
+        [Test]
+        public static void TestLoadOfTimeSpanWithFallbackReturn()
+        {
+            UserSettings settings = new UserSettings(Factory.New<IRuntimeFileInfo>(@"C:\Folder\UserSettings.txt"), new FakeIterationCalculator());
+
+            TimeSpan timeSpan = settings.Load("MyKey", new TimeSpan(1, 2, 3));
+            Assert.That(timeSpan, Is.EqualTo(new TimeSpan(1, 2, 3)));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV1AesCrypto.cs b/Axantum.AxCrypt.Core.Test/TestV1AesCrypto.cs
new file mode 100644
index 0000000..2708497
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV1AesCrypto.cs
@@ -0,0 +1,71 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV1AesCrypto
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            SymmetricKey key = new SymmetricKey(128);
+            SymmetricIV iv = new SymmetricIV(128);
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                if (new V1AesCrypto(new V1Aes128CryptoFactory(), null, SymmetricIV.Zero128) == null) { }
+            });
+
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                if (new V1AesCrypto(new V1Aes128CryptoFactory(), null, iv) == null) { }
+            });
+
+            Assert.DoesNotThrow(() =>
+            {
+                if (new V1AesCrypto(new V1Aes128CryptoFactory(), key, iv) == null) { }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV1AxCryptDocument.cs b/Axantum.AxCrypt.Core.Test/TestV1AxCryptDocument.cs
new file mode 100644
index 0000000..53a798f
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV1AxCryptDocument.cs
@@ -0,0 +1,686 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Test.Properties;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV1AxCryptDocument
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestAnsiFileNameFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                Passphrase passphrase = new Passphrase("a");
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, testStream);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    string fileName = document.DocumentHeaders.FileName;
+                    Assert.That(fileName, Is.EqualTo("HelloWorld-Key-a.txt"), "Wrong file name");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestUnicodeFileNameFromSimpleFile()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                Passphrase passphrase = new Passphrase("a");
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, testStream);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    string fileName = document.DocumentHeaders.FileName;
+                    Assert.That(fileName, Is.EqualTo("HelloWorld-Key-a.txt"), "Wrong file name");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestFileNameFromSimpleFileWithUnicode()
+        {
+            using (Stream testStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt))
+            {
+                Passphrase passphrase = new Passphrase("a");
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, testStream);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    string fileName = document.DocumentHeaders.FileName;
+                    Assert.That(fileName, Is.EqualTo("HelloWorld-Key-a.txt"), "Wrong file name");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestHmacFromSimpleFile()
+        {
+            V1Hmac expectedHmac = new V1Hmac(new byte[] { 0xF9, 0xAF, 0x2E, 0x67, 0x7D, 0xCF, 0xC9, 0xFE, 0x06, 0x4B, 0x39, 0x08, 0xE7, 0x5A, 0x87, 0x81 });
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                Hmac hmac = document.DocumentHeaders.Headers.Hmac;
+                Assert.That(hmac.GetBytes(), Is.EqualTo(expectedHmac.GetBytes()), "Wrong HMAC");
+            }
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification = "This is a test, and they should start with 'Test'.")]
+        public static void TestIsCompressedFromSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                bool isCompressed = document.DocumentHeaders.IsCompressed;
+                Assert.That(isCompressed, Is.False, "This file should not be compressed.");
+            }
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification = "This is a test, and they should start with 'Test'.")]
+        public static void TestInvalidPassphraseWithSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("b");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.False, "The passphrase provided is wrong!");
+            }
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", Justification = "This is a test, and they should start with 'Test'.")]
+        public static void TestIsCompressedFromLargerFile()
+        {
+            Passphrase passphrase = new Passphrase("Å ä Ö");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                bool isCompressed = document.DocumentHeaders.IsCompressed;
+                Assert.That(isCompressed, Is.True, "This file should be compressed.");
+            }
+        }
+
+        [Test]
+        public static void TestDecryptUncompressedFromSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    document.DecryptTo(plaintextStream);
+                    Assert.That(Encoding.ASCII.GetString(plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length), Is.EqualTo("HelloWorld"), "Unexpected result of decryption.");
+                    Assert.That(document.DocumentHeaders.PlaintextLength, Is.EqualTo(10), "'HelloWorld' should be 10 bytes uncompressed plaintext.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptUncompressedWithCancel()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                IProgressContext progress = new CancelProgressContext(new ProgressContext(new TimeSpan(0, 0, 0, 0, 100)));
+                progress.Progressing += (object sender, ProgressEventArgs e) =>
+                {
+                    progress.Cancel = true;
+                };
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, new ProgressStream(FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt), progress));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+                    environment.CurrentTiming.CurrentTiming = new TimeSpan(0, 0, 0, 0, 100);
+                    Assert.Throws<OperationCanceledException>(() => { document.DecryptTo(plaintextStream); });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptUncompressedWithPaddingError()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (MemoryStream encryptedFile = FakeRuntimeFileInfo.ExpandableMemoryStream((byte[])Resources.helloworld_key_a_txt.Clone()))
+                {
+                    encryptedFile.Seek(-1, SeekOrigin.End);
+                    byte lastByte = (byte)encryptedFile.ReadByte();
+                    ++lastByte;
+                    encryptedFile.Seek(-1, SeekOrigin.End);
+                    encryptedFile.WriteByte(lastByte);
+                    encryptedFile.Position = 0;
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, encryptedFile);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    using (MemoryStream plaintextStream = new MemoryStream())
+                    {
+                        Assert.Throws<CryptographicException>(() => { document.DecryptTo(plaintextStream); });
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptCompressedWithTruncatedFile()
+        {
+            Passphrase passphrase = new Passphrase("Å ä Ö");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (MemoryStream encryptedFile = FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt))
+                {
+                    encryptedFile.SetLength(encryptedFile.Length / 2);
+                    encryptedFile.Position = 0;
+                    bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, encryptedFile);
+                    Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                    using (MemoryStream plaintextStream = new MemoryStream())
+                    {
+                        Assert.That(() => { document.DecryptTo(plaintextStream); }, Throws.InstanceOf<Exception>());
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptCompressedWithCancel()
+        {
+            Passphrase passphrase = new Passphrase("Å ä Ö");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                IProgressContext progress = new CancelProgressContext(new ProgressContext(new TimeSpan(0, 0, 0, 0, 100)));
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, new ProgressStream(FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt), progress));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    progress.Progressing += (object sender, ProgressEventArgs e) =>
+                    {
+                        progress.Cancel = true;
+                    };
+                    FakeRuntimeEnvironment environment = (FakeRuntimeEnvironment)OS.Current;
+                    environment.CurrentTiming.CurrentTiming = new TimeSpan(0, 0, 0, 0, 100);
+                    Assert.Throws<OperationCanceledException>(() => { document.DecryptTo(plaintextStream); });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptCompressedFromLegacy0B6()
+        {
+            Passphrase passphrase = new Passphrase("åäö");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.tst_0_0b6_key__aaaeoe__medium_html));
+                Assert.That(keyIsOk, Is.True, "A correct passphrase was provided, but it was not accepted.");
+                Assert.That(document.DocumentHeaders.IsCompressed, Is.True, "The file is compressed.");
+                Assert.That(document.DocumentHeaders.FileName, Is.EqualTo("readme.html"), "The file name should be 'readme.html'.");
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    document.DecryptTo(plaintextStream);
+                    Assert.That(document.DocumentHeaders.PlaintextLength, Is.EqualTo(3736), "The compressed content should be recorded as 3736 bytes in the headers.");
+                    Assert.That(plaintextStream.Length, Is.EqualTo(9528), "The file should be 9528 bytes uncompressed plaintext in actual fact.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptWithoutLoadFirstFromEmptyFile()
+        {
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    Assert.Throws<InternalErrorException>(() => { document.DecryptTo(plaintextStream); });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptAfterFailedLoad()
+        {
+            using (Stream testStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(testStream);
+                testStream.Position = 0;
+                Passphrase passphrase = new Passphrase("Å ä Ö");
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    Assert.Throws<FileFormatException>(() => { document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, testStream); });
+                    using (MemoryStream plaintextStream = new MemoryStream())
+                    {
+                        Assert.Throws<InternalErrorException>(() => { document.DecryptTo(plaintextStream); });
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptCompressedFromLargerFile()
+        {
+            Passphrase passphrase = new Passphrase("Å ä Ö");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                using (MemoryStream plaintextStream = new MemoryStream())
+                {
+                    document.DecryptTo(plaintextStream);
+                    string text = Encoding.UTF8.GetString(plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length);
+                    Assert.That(text, Is.StringStarting("The Project Gutenberg EBook of David Copperfield, by Charles Dickens"), "Unexpected start of David Copperfield.");
+                    Assert.That(text, Is.StringEnding("subscribe to our email newsletter to hear about new eBooks." + (Char)13 + (Char)10), "Unexpected end of David Copperfield.");
+                    Assert.That(text.Length, Is.EqualTo(1992490), "Wrong length of full text of David Copperfield.");
+                    Assert.That(document.DocumentHeaders.PlaintextLength, Is.EqualTo(795855), "Wrong expected length of compressed text of David Copperfield.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestHmacCalculationFromSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                document.DecryptTo(Stream.Null);
+            }
+        }
+
+        [Test]
+        public static void TestFailedHmacCalculationFromSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                document.DocumentHeaders.Headers.Hmac = new V1Hmac(new byte[V1Hmac.RequiredLength]);
+                Assert.Throws<Axantum.AxCrypt.Core.Runtime.IncorrectDataException>(() =>
+                {
+                    document.DecryptTo(Stream.Null);
+                });
+            }
+        }
+
+        [Test]
+        public static void TestNoMagicGuidFound()
+        {
+            byte[] dummy = Encoding.ASCII.GetBytes("This is a string that generates some bytes, none of which will match the magic GUID");
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                Assert.Throws<FileFormatException>(() => { document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(dummy)); }, "Calling with dummy data that does not contain a GUID.");
+            }
+        }
+
+        [Test]
+        public static void TestInputStreamTooShort()
+        {
+            using (MemoryStream testStream = new MemoryStream())
+            {
+                byte[] guid = AxCrypt1Guid.GetBytes();
+                testStream.Write(guid, 0, guid.Length);
+                testStream.Position = 0;
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    Assert.Throws<FileFormatException>(() => { document.Load(Passphrase.Empty, V1Aes128CryptoFactory.CryptoId, testStream); }, "Calling with too short a stream, only containing a GUID.");
+                }
+            }
+        }
+
+        [Test]
+        public static void TestFileTimesFromSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+
+                string creationTime = document.DocumentHeaders.CreationTimeUtc.ToString(CultureInfo.InvariantCulture);
+                Assert.That(creationTime, Is.EqualTo("01/13/2012 17:17:18"), "Checking creation time.");
+                string lastAccessTime = document.DocumentHeaders.LastAccessTimeUtc.ToString(CultureInfo.InvariantCulture);
+                Assert.That(lastAccessTime, Is.EqualTo("01/13/2012 17:17:18"), "Checking last access time.");
+                string lastWriteTime = document.DocumentHeaders.LastWriteTimeUtc.ToString(CultureInfo.InvariantCulture);
+                Assert.That(lastWriteTime, Is.EqualTo("01/13/2012 17:17:45"), "Checking last modify time.");
+            }
+        }
+
+        [Test]
+        public static void TestChangePassphraseForSimpleFile()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct and should work!");
+
+                Passphrase newPassphrase = new Passphrase("b");
+                using (Stream changedStream = new MemoryStream())
+                {
+                    V1DocumentHeaders outputDocumentHeaders = new V1DocumentHeaders(document.DocumentHeaders);
+                    outputDocumentHeaders.RewrapMasterKey(new V1DerivedKey(newPassphrase), 35);
+
+                    document.CopyEncryptedTo(outputDocumentHeaders, changedStream);
+                    changedStream.Position = 0;
+                    using (V1AxCryptDocument changedDocument = new V1AxCryptDocument())
+                    {
+                        bool changedKeyIsOk = changedDocument.Load(newPassphrase, V1Aes128CryptoFactory.CryptoId, changedStream);
+                        Assert.That(changedKeyIsOk, Is.True, "The changed passphrase provided is correct and should work!");
+
+                        using (MemoryStream plaintextStream = new MemoryStream())
+                        {
+                            changedDocument.DecryptTo(plaintextStream);
+                            Assert.That(Encoding.ASCII.GetString(plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length), Is.EqualTo("HelloWorld"), "Unexpected result of decryption.");
+                            Assert.That(changedDocument.DocumentHeaders.PlaintextLength, Is.EqualTo(10), "'HelloWorld' should be 10 bytes uncompressed plaintext.");
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestSimpleEncryptToWithCompression()
+        {
+            DateTime creationTimeUtc = new DateTime(2012, 1, 1, 1, 2, 3, DateTimeKind.Utc);
+            DateTime lastAccessTimeUtc = creationTimeUtc + new TimeSpan(1, 0, 0);
+            DateTime lastWriteTimeUtc = creationTimeUtc + new TimeSpan(2, 0, 0); ;
+            using (Stream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("AxCrypt is Great!")))
+            {
+                using (Stream outputStream = new MemoryStream())
+                {
+                    Passphrase passphrase = new Passphrase("a");
+                    using (V1AxCryptDocument document = new V1AxCryptDocument(passphrase, 47))
+                    {
+                        document.DocumentHeaders.FileName = "MyFile.txt";
+                        document.DocumentHeaders.CreationTimeUtc = creationTimeUtc;
+                        document.DocumentHeaders.LastAccessTimeUtc = lastAccessTimeUtc;
+                        document.DocumentHeaders.LastWriteTimeUtc = lastWriteTimeUtc;
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+                    }
+                    outputStream.Position = 0;
+                    using (V1AxCryptDocument document = new V1AxCryptDocument())
+                    {
+                        bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, outputStream);
+                        Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                        Assert.That(document.DocumentHeaders.FileName, Is.EqualTo("MyFile.txt"));
+                        Assert.That(document.DocumentHeaders.CreationTimeUtc, Is.EqualTo(creationTimeUtc));
+                        Assert.That(document.DocumentHeaders.LastAccessTimeUtc, Is.EqualTo(lastAccessTimeUtc));
+                        Assert.That(document.DocumentHeaders.LastWriteTimeUtc, Is.EqualTo(lastWriteTimeUtc));
+                        using (MemoryStream plaintextStream = new MemoryStream())
+                        {
+                            document.DecryptTo(plaintextStream);
+                            Assert.That(document.DocumentHeaders.UncompressedLength, Is.EqualTo(17), "'AxCrypt is Great!' should be 17 bytes uncompressed plaintext.");
+                            Assert.That(Encoding.ASCII.GetString(plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length), Is.EqualTo("AxCrypt is Great!"), "Unexpected result of decryption.");
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestSimpleEncryptToWithoutCompression()
+        {
+            DateTime creationTimeUtc = new DateTime(2012, 1, 1, 1, 2, 3, DateTimeKind.Utc);
+            DateTime lastAccessTimeUtc = creationTimeUtc + new TimeSpan(1, 0, 0);
+            DateTime lastWriteTimeUtc = creationTimeUtc + new TimeSpan(2, 0, 0); ;
+            using (Stream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("AxCrypt is Great!")))
+            {
+                using (Stream outputStream = new MemoryStream())
+                {
+                    Passphrase passphrase = new Passphrase("a");
+                    using (V1AxCryptDocument document = new V1AxCryptDocument(passphrase, 53))
+                    {
+                        document.DocumentHeaders.FileName = "MyFile.txt";
+                        document.DocumentHeaders.CreationTimeUtc = creationTimeUtc;
+                        document.DocumentHeaders.LastAccessTimeUtc = lastAccessTimeUtc;
+                        document.DocumentHeaders.LastWriteTimeUtc = lastWriteTimeUtc;
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithoutCompression);
+                    }
+                    outputStream.Position = 0;
+                    using (V1AxCryptDocument document = new V1AxCryptDocument())
+                    {
+                        bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, outputStream);
+                        Assert.That(keyIsOk, Is.True, "The passphrase provided is correct!");
+                        Assert.That(document.DocumentHeaders.FileName, Is.EqualTo("MyFile.txt"));
+                        Assert.That(document.DocumentHeaders.CreationTimeUtc, Is.EqualTo(creationTimeUtc));
+                        Assert.That(document.DocumentHeaders.LastAccessTimeUtc, Is.EqualTo(lastAccessTimeUtc));
+                        Assert.That(document.DocumentHeaders.LastWriteTimeUtc, Is.EqualTo(lastWriteTimeUtc));
+                        using (MemoryStream plaintextStream = new MemoryStream())
+                        {
+                            document.DecryptTo(plaintextStream);
+                            Assert.That(document.DocumentHeaders.UncompressedLength, Is.EqualTo(-1), "'AxCrypt is Great!' should not return a value at all for uncompressed, since it was not compressed.");
+                            Assert.That(document.DocumentHeaders.PlaintextLength, Is.EqualTo(17), "'AxCrypt is Great!' is 17 bytes plaintext length.");
+                            Assert.That(Encoding.ASCII.GetString(plaintextStream.GetBuffer(), 0, (int)plaintextStream.Length), Is.EqualTo("AxCrypt is Great!"), "Unexpected result of decryption.");
+                        }
+                    }
+                }
+            }
+        }
+
+        private class NonSeekableStream : Stream
+        {
+            public override bool CanRead
+            {
+                get { return false; }
+            }
+
+            public override bool CanSeek
+            {
+                get { return false; }
+            }
+
+            public override bool CanWrite
+            {
+                get { return true; }
+            }
+
+            public override void Flush()
+            {
+            }
+
+            public override long Length
+            {
+                get { return 0; }
+            }
+
+            public override long Position
+            {
+                get
+                {
+                    return 0;
+                }
+                set
+                {
+                }
+            }
+
+            public override int Read(byte[] buffer, int offset, int count)
+            {
+                return 0;
+            }
+
+            public override long Seek(long offset, SeekOrigin origin)
+            {
+                throw new NotSupportedException();
+            }
+
+            public override void SetLength(long value)
+            {
+                throw new NotSupportedException();
+            }
+
+            public override void Write(byte[] buffer, int offset, int count)
+            {
+            }
+        }
+
+        [Test]
+        public static void TestInvalidArguments()
+        {
+            using (Stream inputStream = FakeRuntimeFileInfo.ExpandableMemoryStream(Encoding.UTF8.GetBytes("AxCrypt is Great!")))
+            {
+                using (Stream outputStream = new MemoryStream())
+                {
+                    using (V1AxCryptDocument document = new V1AxCryptDocument())
+                    {
+                        Assert.Throws<ArgumentNullException>(() => { document.EncryptTo(inputStream, null, AxCryptOptions.EncryptWithCompression); });
+                        Assert.Throws<ArgumentNullException>(() => { document.EncryptTo(null, outputStream, AxCryptOptions.EncryptWithCompression); });
+                        Assert.Throws<ArgumentException>(() => { document.EncryptTo(inputStream, new NonSeekableStream(), AxCryptOptions.EncryptWithCompression); });
+                        Assert.Throws<ArgumentException>(() => { document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression | AxCryptOptions.EncryptWithoutCompression); });
+                        Assert.Throws<ArgumentException>(() => { document.EncryptTo(inputStream, outputStream, AxCryptOptions.None); });
+
+                        Passphrase passphrase = new Passphrase("a");
+                        V1DocumentHeaders headers = new V1DocumentHeaders(passphrase, 13);
+
+                        Assert.Throws<ArgumentNullException>(() => { document.CopyEncryptedTo(null, outputStream); });
+                        Assert.Throws<ArgumentNullException>(() => { document.CopyEncryptedTo(headers, null); });
+                        Assert.Throws<ArgumentException>(() => { document.CopyEncryptedTo(headers, new NonSeekableStream()); });
+                        Assert.Throws<InternalErrorException>(() => { document.CopyEncryptedTo(headers, outputStream); });
+                    }
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestDoubleDispose()
+        {
+            V1AxCryptDocument document = new V1AxCryptDocument();
+            document.Dispose();
+            document.Dispose();
+        }
+
+        [Test]
+        public static void TestInvalidHmacInCopyEncryptedTo()
+        {
+            Passphrase passphrase = new Passphrase("a");
+            using (V1AxCryptDocument document = new V1AxCryptDocument())
+            {
+                bool keyIsOk = document.Load(passphrase, V1Aes128CryptoFactory.CryptoId, FakeRuntimeFileInfo.ExpandableMemoryStream(Resources.helloworld_key_a_txt));
+                Assert.That(keyIsOk, Is.True, "The passphrase provided is correct and should work!");
+
+                Passphrase newPassphrase = new Passphrase("b");
+                using (Stream changedStream = new MemoryStream())
+                {
+                    V1DocumentHeaders outputDocumentHeaders = new V1DocumentHeaders(document.DocumentHeaders);
+                    outputDocumentHeaders.RewrapMasterKey(new V1DerivedKey(newPassphrase), 15);
+
+                    byte[] modifiedHmacBytes = document.DocumentHeaders.Headers.Hmac.GetBytes();
+                    modifiedHmacBytes[0] += 1;
+                    document.DocumentHeaders.Headers.Hmac = new V1Hmac(modifiedHmacBytes);
+                    Assert.Throws<Axantum.AxCrypt.Core.Runtime.IncorrectDataException>(() =>
+                    {
+                        document.CopyEncryptedTo(outputDocumentHeaders, changedStream);
+                    });
+                }
+            }
+        }
+
+        [Test]
+        public static void TestReaderNotPositionedAtData()
+        {
+            using (MemoryStream encryptedFile = new MemoryStream(Resources.david_copperfield_key__aa_ae_oe__ulu_txt))
+            {
+                Headers headers = new Headers();
+                AxCryptReader reader = headers.Load(encryptedFile);
+                using (V1AxCryptDocument document = new V1AxCryptDocument())
+                {
+                    Passphrase key = new Passphrase("Å ä Ö");
+                    bool keyIsOk = document.Load(key, reader, headers);
+                    Assert.That(keyIsOk, Is.True);
+
+                    reader.SetStartOfData();
+                    Assert.Throws<InvalidOperationException>(() => document.DecryptTo(Stream.Null));
+                }
+            }
+        }
+
+        [Test]
+        public static void TestHmacThrowsWhenTooLittleData()
+        {
+            using (MemoryStream plaintext = new MemoryStream(Resources.uncompressable_zip))
+            {
+                using (MemoryStream encryptedFile = new MemoryStream())
+                {
+                    using (V1AxCryptDocument encryptingDocument = new V1AxCryptDocument(new Passphrase("a"), 10))
+                    {
+                        encryptingDocument.EncryptTo(plaintext, encryptedFile, AxCryptOptions.EncryptWithoutCompression);
+                    }
+
+                    encryptedFile.Position = 0;
+                    Headers headers = new Headers();
+                    AxCryptReader reader = headers.Load(encryptedFile);
+                    using (V1AxCryptDocument document = new V1AxCryptDocument())
+                    {
+                        Passphrase key = new Passphrase("a");
+                        bool keyIsOk = document.Load(key, reader, headers);
+                        Assert.That(keyIsOk, Is.True);
+
+                        reader.InputStream.Read(new byte[16], 0, 16);
+                        Assert.Throws<InvalidOperationException>(() => document.DecryptTo(Stream.Null));
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV1AxCryptReader.cs b/Axantum.AxCrypt.Core.Test/TestV1AxCryptReader.cs
new file mode 100644
index 0000000..8fc5954
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV1AxCryptReader.cs
@@ -0,0 +1,82 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV1AxCryptReader
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestPrematureEndOfFile()
+        {
+            V1DocumentHeaders headers = new V1DocumentHeaders(new Passphrase("passphrase"), 10);
+            using (MemoryStream stream = new MemoryStream())
+            {
+                headers.WriteWithoutHmac(stream);
+                stream.Position = 0;
+
+                using (V1AxCryptReader reader = new V1AxCryptReader(stream))
+                {
+                    AxCryptItemType lastItemType = AxCryptItemType.Undefined;
+                    while (reader.Read())
+                    {
+                        lastItemType = reader.CurrentItemType;
+                    }
+                    Assert.That(lastItemType, Is.EqualTo(AxCryptItemType.Data));
+                    Assert.That(reader.CurrentItemType, Is.EqualTo(AxCryptItemType.Data));
+
+                    reader.SetStartOfData();
+                    Assert.That(reader.Read(), Is.False);
+                    Assert.That(reader.CurrentItemType, Is.EqualTo(AxCryptItemType.EndOfStream));
+
+                    Assert.That(reader.Read(), Is.False);
+                    Assert.That(reader.CurrentItemType, Is.EqualTo(AxCryptItemType.EndOfStream));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV1UnicodeFileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV1UnicodeFileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..b1a803e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV1UnicodeFileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV1UnicodeFileNameInfoEncryptedHeaderBlock
+    {
+        private class UnicodeFileNameInfoHeaderBlockForTest : V1UnicodeFileNameInfoEncryptedHeaderBlock
+        {
+            public UnicodeFileNameInfoHeaderBlockForTest(ICrypto headerCrypto)
+                : base(headerCrypto)
+            {
+            }
+
+            public void SetBadNameWithoutEndingNul()
+            {
+                byte[] rawFileName = Encoding.ASCII.GetBytes("ABCDEFGHIJK.LMNO");
+                byte[] dataBlock = new byte[16];
+                rawFileName.CopyTo(dataBlock, 0);
+                SetDataBlockBytesReference(HeaderCrypto.Encrypt(dataBlock));
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestNonTerminatingFileName()
+        {
+            UnicodeFileNameInfoHeaderBlockForTest unicodeFileInfoHeaderBlock = new UnicodeFileNameInfoHeaderBlockForTest(new V1AesCrypto(new V1Aes128CryptoFactory(), new V1DerivedKey(new Passphrase("passphrase")).DerivedKey, SymmetricIV.Zero128));
+
+            unicodeFileInfoHeaderBlock.FileName = "ABCDEFGHIJ.LMN";
+            unicodeFileInfoHeaderBlock.SetBadNameWithoutEndingNul();
+
+            Assert.Throws<InvalidOperationException>(() =>
+            {
+                string fileName = unicodeFileInfoHeaderBlock.FileName;
+
+                // Avoid FxCop errors
+                Object.Equals(fileName, null);
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2AesCrypto.cs b/Axantum.AxCrypt.Core.Test/TestV2AesCrypto.cs
new file mode 100644
index 0000000..815dfcf
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2AesCrypto.cs
@@ -0,0 +1,152 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2AesCrypto
+    {
+        private static byte[] testPlaintext = new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+        private static byte[] testKey = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f };
+        private static byte[] testCipertext = new byte[] { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf, 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 };
+
+        // Test vectors from NIST Special Publication 800-38A
+        private static byte[] nistKey = { 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 };
+
+        private static byte[] nistInitCounter = { 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, };
+
+        private static byte[] nistPlaintext1 = { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, };
+        private static byte[] nistCiphertext1 = { 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, };
+
+        private static byte[] nistPlaintext2 = { 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, };
+        private static byte[] nistCiphertext2 = { 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, };
+
+        private static byte[] nistPlaintext3 = { 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, };
+        private static byte[] nistCiphertext3 = { 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, };
+
+        private static byte[] nistPlaintext4 = { 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10, };
+        private static byte[] nistCiphertext4 = { 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6, };
+
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestEncrypt()
+        {
+            ICrypto crypto = new V2AesCrypto(new SymmetricKey(testKey), new SymmetricIV(testPlaintext), 0);
+
+            byte[] zeroPlain = new byte[testCipertext.Length];
+
+            byte[] cipherText = crypto.Encrypt(zeroPlain);
+
+            Assert.That(cipherText.IsEquivalentTo(testCipertext));
+        }
+
+        [Test]
+        public static void TestEncryptPartialBlock()
+        {
+            ICrypto crypto = new V2AesCrypto(new SymmetricKey(testKey), new SymmetricIV(testPlaintext), 3);
+            byte[] zeroPlain = new byte[5];
+
+            byte[] cipherText = crypto.Encrypt(zeroPlain);
+            byte[] partOfTestCipherText = new byte[5];
+            Array.Copy(testCipertext, 3, partOfTestCipherText, 0, 5);
+
+            Assert.That(cipherText.IsEquivalentTo(partOfTestCipherText));
+        }
+
+        [Test]
+        public static void TestEncryptSeveralBlocks()
+        {
+            byte[] iv = new byte[16];
+            Array.Copy(nistInitCounter, iv, 8);
+
+            long blockCounter = nistInitCounter.GetBigEndianValue(8, 8);
+            ICrypto crypto;
+
+            crypto = new V2AesCrypto(new SymmetricKey(nistKey), new SymmetricIV(iv), blockCounter << 4);
+            byte[] cipherText1 = crypto.Encrypt(nistPlaintext1);
+            Assert.That(cipherText1.IsEquivalentTo(nistCiphertext1));
+
+            crypto = new V2AesCrypto(new SymmetricKey(nistKey), new SymmetricIV(iv), (++blockCounter) << 4);
+            byte[] cipherText2 = crypto.Encrypt(nistPlaintext2);
+            Assert.That(cipherText2.IsEquivalentTo(nistCiphertext2));
+
+            crypto = new V2AesCrypto(new SymmetricKey(nistKey), new SymmetricIV(iv), (++blockCounter) << 4);
+            byte[] cipherText3 = crypto.Encrypt(nistPlaintext3);
+            Assert.That(cipherText3.IsEquivalentTo(nistCiphertext3));
+
+            crypto = new V2AesCrypto(new SymmetricKey(nistKey), new SymmetricIV(iv), (++blockCounter) << 4);
+            byte[] cipherText4 = crypto.Encrypt(nistPlaintext4);
+            Assert.That(cipherText4.IsEquivalentTo(nistCiphertext4));
+        }
+
+        [Test]
+        public static void TestConstructorWithBadArguments()
+        {
+            SymmetricKey nullKey = null;
+
+            SymmetricKey testKey = new SymmetricKey(128);
+            SymmetricIV testIV = new SymmetricIV(128);
+
+            ICrypto crypto = null;
+            Assert.Throws<ArgumentNullException>(() => crypto = new V2AesCrypto(nullKey, testIV, 0));
+
+            testKey = new SymmetricKey(64);
+            Assert.Throws<ArgumentException>(() => crypto = new V2AesCrypto(testKey, testIV, 0));
+
+            testKey = new SymmetricKey(256);
+            testIV = new SymmetricIV(64);
+            Assert.Throws<ArgumentException>(() => crypto = new V2AesCrypto(testKey, testIV, 0));
+
+            testIV = new SymmetricIV(128);
+            Assert.DoesNotThrow(() => crypto = new V2AesCrypto(testKey, testIV, 0));
+
+            Assert.That(crypto, Is.Not.Null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2AsymmetricRecipientsEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2AsymmetricRecipientsEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..8f98d93
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2AsymmetricRecipientsEncryptedHeaderBlock.cs
@@ -0,0 +1,56 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2AsymmetricRecipientsEncryptedHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<CryptoFactory>(() => CreateCryptoFactory());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+        }
+
+        private static CryptoFactory CreateCryptoFactory()
+        {
+            CryptoFactory factory = new CryptoFactory();
+            factory.Add(() => new V2Aes256CryptoFactory());
+            factory.Add(() => new V1Aes128CryptoFactory());
+
+            return factory;
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestGetSet()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+
+            V2AsymmetricRecipientsEncryptedHeaderBlock headerBlock = new V2AsymmetricRecipientsEncryptedHeaderBlock(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0));
+            headerBlock.Recipients = new string[] { "alice at email.com", "bob at email.com" };
+            Assert.That(headerBlock.Recipients.First(), Is.EqualTo("alice at email.com"));
+            Assert.That(headerBlock.Recipients.Skip(1).First(), Is.EqualTo("bob at email.com"));
+
+            V2AsymmetricRecipientsEncryptedHeaderBlock clone = (V2AsymmetricRecipientsEncryptedHeaderBlock)headerBlock.Clone();
+            Assert.That(clone.Recipients.First(), Is.EqualTo("alice at email.com"));
+            Assert.That(clone.Recipients.Skip(1).First(), Is.EqualTo("bob at email.com"));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2AxCryptDataStreamTest.cs b/Axantum.AxCrypt.Core.Test/TestV2AxCryptDataStreamTest.cs
new file mode 100644
index 0000000..c4f303a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2AxCryptDataStreamTest.cs
@@ -0,0 +1,237 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2AxCryptDataStreamTest
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<ILogging>(() => new FakeLogging());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        private class TestingAxCryptReader : AxCryptReader
+        {
+            public TestingAxCryptReader(Stream inputStream)
+                : base(inputStream)
+            {
+            }
+
+            protected override HeaderBlock HeaderBlockFactory(HeaderBlockType headerBlockType, byte[] dataBlock)
+            {
+                switch (headerBlockType)
+                {
+                    case HeaderBlockType.Preamble:
+                        return new PreambleHeaderBlock(dataBlock);
+
+                    case HeaderBlockType.Version:
+                        return new VersionHeaderBlock(dataBlock);
+
+                    case HeaderBlockType.Data:
+                        return new DataHeaderBlock(dataBlock);
+
+                    case HeaderBlockType.EncryptedDataPart:
+                        return new EncryptedDataPartBlock(dataBlock);
+                }
+                return new UnrecognizedHeaderBlock(headerBlockType, dataBlock);
+            }
+
+            public override IAxCryptDocument Document(Passphrase key, Guid cryptoId, Headers headers)
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestSimpleReadWrite()
+        {
+            using (MemoryStream dataPartStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(dataPartStream);
+                new PreambleHeaderBlock().Write(dataPartStream);
+                new DataHeaderBlock().Write(dataPartStream);
+                using (V2AxCryptDataStream axCryptDataStreamWriter = new V2AxCryptDataStream(dataPartStream))
+                {
+                    byte[] bytes = Encoding.UTF8.GetBytes("This is a short text.");
+                    axCryptDataStreamWriter.Write(bytes, 0, bytes.Length);
+                }
+                new V2HmacHeaderBlock().Write(dataPartStream);
+                dataPartStream.Position = 0;
+                using (AxCryptReader reader = new TestingAxCryptReader(dataPartStream))
+                {
+                    while (reader.Read()) ;
+                    reader.SetStartOfData();
+                    using (V2AxCryptDataStream axCryptDataStreamReader = new V2AxCryptDataStream(reader, Stream.Null))
+                    {
+                        using (TextReader textReader = new StreamReader(axCryptDataStreamReader, Encoding.UTF8))
+                        {
+                            string text = textReader.ReadToEnd();
+                            Assert.That(text, Is.EqualTo("This is a short text."));
+                        }
+                    }
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestLongerReadWrite()
+        {
+            byte[] bytesToWrite = new FakeRandomGenerator().Generate(V2AxCryptDataStream.WriteChunkSize + V2AxCryptDataStream.WriteChunkSize / 2);
+            using (MemoryStream dataPartStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(dataPartStream);
+                new PreambleHeaderBlock().Write(dataPartStream);
+                new DataHeaderBlock().Write(dataPartStream);
+                using (V2AxCryptDataStream axCryptDataStreamWriter = new V2AxCryptDataStream(dataPartStream))
+                {
+                    axCryptDataStreamWriter.Write(bytesToWrite, 0, bytesToWrite.Length);
+                }
+                new V2HmacHeaderBlock().Write(dataPartStream);
+                dataPartStream.Position = 0;
+                using (AxCryptReader reader = new TestingAxCryptReader(dataPartStream))
+                {
+                    while (reader.Read()) ;
+                    reader.SetStartOfData();
+                    using (V2AxCryptDataStream axCryptDataStreamReader = new V2AxCryptDataStream(reader, Stream.Null))
+                    {
+                        byte[] bytesRead = new byte[bytesToWrite.Length];
+                        int offset = 0;
+                        int count;
+                        do
+                        {
+                            count = axCryptDataStreamReader.Read(bytesRead, offset, 100);
+                            offset += count;
+                        } while (count > 0);
+                        Assert.That(bytesRead, Is.EquivalentTo(bytesToWrite));
+                    }
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestUnexpectedEndOfFile()
+        {
+            using (MemoryStream dataPartStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(dataPartStream);
+                new PreambleHeaderBlock().Write(dataPartStream);
+                new DataHeaderBlock().Write(dataPartStream);
+                using (V2AxCryptDataStream axCryptDataStreamWriter = new V2AxCryptDataStream(dataPartStream))
+                {
+                    byte[] bytes = Encoding.UTF8.GetBytes("This is a short text.");
+                    axCryptDataStreamWriter.Write(bytes, 0, bytes.Length);
+                }
+                dataPartStream.Position = 0;
+                using (AxCryptReader reader = new TestingAxCryptReader(dataPartStream))
+                {
+                    while (reader.Read()) ;
+                    reader.SetStartOfData();
+                    using (V2AxCryptDataStream axCryptDataStreamReader = new V2AxCryptDataStream(reader, Stream.Null))
+                    {
+                        using (TextReader textReader = new StreamReader(axCryptDataStreamReader, Encoding.UTF8))
+                        {
+                            string text = null;
+                            Assert.Throws<FileFormatException>(() => text = textReader.ReadToEnd());
+                            Assert.That(text, Is.Null);
+                        }
+                    }
+                }
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestUnexpectedBlockType()
+        {
+            using (MemoryStream dataPartStream = new MemoryStream())
+            {
+                AxCrypt1Guid.Write(dataPartStream);
+                new PreambleHeaderBlock().Write(dataPartStream);
+                new DataHeaderBlock().Write(dataPartStream);
+                using (V2AxCryptDataStream axCryptDataStreamWriter = new V2AxCryptDataStream(dataPartStream))
+                {
+                    byte[] bytes = Encoding.UTF8.GetBytes("This is a short text.");
+                    axCryptDataStreamWriter.Write(bytes, 0, bytes.Length);
+                }
+                new DataHeaderBlock().Write(dataPartStream);
+                dataPartStream.Position = 0;
+                using (AxCryptReader reader = new TestingAxCryptReader(dataPartStream))
+                {
+                    while (reader.Read()) ;
+                    reader.SetStartOfData();
+                    using (V2AxCryptDataStream axCryptDataStreamReader = new V2AxCryptDataStream(reader, Stream.Null))
+                    {
+                        using (TextReader textReader = new StreamReader(axCryptDataStreamReader, Encoding.UTF8))
+                        {
+                            string text = null;
+                            Assert.Throws<FileFormatException>(() => text = textReader.ReadToEnd());
+                            Assert.That(text, Is.Null);
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestNotSupportedMethods()
+        {
+            using (V2AxCryptDataStream stream = new V2AxCryptDataStream(Stream.Null))
+            {
+                long position;
+                Assert.Throws<NotSupportedException>(() => position = stream.Position);
+                Assert.Throws<NotSupportedException>(() => stream.Position = 0);
+
+                Assert.That(stream.CanSeek, Is.False);
+
+                long length;
+                Assert.Throws<NotSupportedException>(() => length = stream.Length);
+                Assert.Throws<NotSupportedException>(() => stream.SetLength(0));
+
+                Assert.Throws<NotSupportedException>(() => position = stream.Seek(0, SeekOrigin.Begin));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2AxCryptDocument.cs b/Axantum.AxCrypt.Core.Test/TestV2AxCryptDocument.cs
new file mode 100644
index 0000000..39ce86a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2AxCryptDocument.cs
@@ -0,0 +1,422 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2AxCryptDocument
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacSmall()
+        {
+            TestEncryptWithHmacHelper(23, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacAlmostChunkSize()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize - 1, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacChunkSize()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacSeveralChunkSizes()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize * 5, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacIncompleteChunkSizes()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize * 3 + V2AxCryptDataStream.WriteChunkSize / 2, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacSmallWithCompression()
+        {
+            TestEncryptWithHmacHelper(23, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacAlmostChunkSizeWithCompression()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize - 1, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacChunkSizeWithCompression()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacSeveralChunkSizesWithCompression()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize * 5, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptWithHmacIncompleteChunkSizesWithCompression()
+        {
+            TestEncryptWithHmacHelper(V2AxCryptDataStream.WriteChunkSize * 3 + V2AxCryptDataStream.WriteChunkSize / 2, AxCryptOptions.EncryptWithCompression);
+        }
+
+        private static void TestEncryptWithHmacHelper(int length, AxCryptOptions options)
+        {
+            byte[] output;
+            byte[] hmacKey;
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(length);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (V2AxCryptDocument document = new V2AxCryptDocument(new Passphrase("Secret"), V2Aes256CryptoFactory.CryptoId, 100))
+                    {
+                        document.EncryptTo(inputStream, outputStream, options);
+                        output = outputStream.ToArray();
+                        hmacKey = document.DocumentHeaders.GetHmacKey();
+                    }
+                }
+            }
+
+            byte[] hmacBytesFromHeaders = new byte[V2Hmac.RequiredLength];
+            Array.Copy(output, output.Length - V2Hmac.RequiredLength, hmacBytesFromHeaders, 0, V2Hmac.RequiredLength);
+            V2Hmac hmacFromHeaders = new V2Hmac(hmacBytesFromHeaders);
+
+            byte[] dataToHmac = new byte[output.Length - (V2Hmac.RequiredLength + 5)];
+            Array.Copy(output, 0, dataToHmac, 0, dataToHmac.Length);
+
+            HMACSHA512 hmac = new HMACSHA512(hmacKey);
+            hmac.TransformFinalBlock(dataToHmac, 0, dataToHmac.Length);
+            V2Hmac hmacFromCalculation = new V2Hmac(hmac.Hash);
+
+            Assert.That(hmacFromHeaders, Is.EqualTo(hmacFromCalculation));
+        }
+
+        [Test]
+        public static void TestEncryptDecryptSmall()
+        {
+            TestEncryptDecryptHelper(15, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptAlmostChunkSize()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize - 1, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptChunkSize()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptChunkSizePlusOne()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize + 1, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptSeveralChunkSizes()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize * 5, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptIncompleteChunk()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize * 3 + V2AxCryptDataStream.WriteChunkSize / 2, AxCryptOptions.EncryptWithoutCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptSmallWithCompression()
+        {
+            TestEncryptDecryptHelper(15, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptAlmostChunkSizeWithCompression()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize - 1, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptChunkSizeWithCompression()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptChunkSizePlusOneWithCompression()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize + 1, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptSeveralChunkSizesWithCompression()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize * 5, AxCryptOptions.EncryptWithCompression);
+        }
+
+        [Test]
+        public static void TestEncryptDecryptIncompleteChunkWithCompression()
+        {
+            TestEncryptDecryptHelper(V2AxCryptDataStream.WriteChunkSize * 3 + V2AxCryptDataStream.WriteChunkSize / 2, AxCryptOptions.EncryptWithCompression);
+        }
+
+        private static void TestEncryptDecryptHelper(int length, AxCryptOptions options)
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(length);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 113))
+                    {
+                        document.EncryptTo(inputStream, outputStream, options);
+
+                        outputStream.Position = 0;
+                        using (IAxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Assert.That(decryptedDocument.Load(new Passphrase("passphrase"), new V2Aes256CryptoFactory().Id, outputStream), Is.True);
+                            byte[] plain;
+                            using (MemoryStream decryptedStream = new MemoryStream())
+                            {
+                                decryptedDocument.DecryptTo(decryptedStream);
+                                plain = decryptedStream.ToArray();
+                            }
+
+                            Assert.That(plain.IsEquivalentTo(text));
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestEncryptToInvalidArguments()
+        {
+            Stream nullStream = null;
+
+            using (IAxCryptDocument document = new V2AxCryptDocument())
+            {
+                Assert.Throws<ArgumentNullException>(() => document.EncryptTo(nullStream, Stream.Null, AxCryptOptions.EncryptWithCompression));
+                Assert.Throws<ArgumentNullException>(() => document.EncryptTo(Stream.Null, nullStream, AxCryptOptions.EncryptWithCompression));
+                Assert.Throws<ArgumentException>(() => document.EncryptTo(Stream.Null, Stream.Null, AxCryptOptions.None));
+                Assert.Throws<ArgumentException>(() => document.EncryptTo(Stream.Null, Stream.Null, AxCryptOptions.EncryptWithCompression | AxCryptOptions.EncryptWithoutCompression));
+            }
+        }
+
+        [Test]
+        public static void TestLoadWithInvalidPassphrase()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(1000);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 113))
+                    {
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+
+                        outputStream.Position = 0;
+                        using (IAxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Assert.That(decryptedDocument.Load(new Passphrase("incorrect"), V2Aes256CryptoFactory.CryptoId, outputStream), Is.False);
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptToWithInvalidArgument()
+        {
+            Stream nullStream = null;
+
+            using (IAxCryptDocument document = new V2AxCryptDocument())
+            {
+                Assert.Throws<ArgumentNullException>(() => document.DecryptTo(nullStream));
+            }
+
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(1000);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 113))
+                    {
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+
+                        outputStream.Position = 0;
+                        using (IAxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Assert.That(decryptedDocument.Load(new Passphrase("incorrect"), V2Aes256CryptoFactory.CryptoId, outputStream), Is.False);
+                            Assert.Throws<InternalErrorException>(() => decryptedDocument.DecryptTo(Stream.Null));
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptWithInvalidHmac()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(1000);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 113))
+                    {
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithoutCompression);
+
+                        outputStream.Position = 1000;
+                        int b = outputStream.ReadByte();
+                        outputStream.Position = 1000;
+                        outputStream.WriteByte((byte)(b + 1));
+                        outputStream.Position = 0;
+
+                        using (IAxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Assert.That(decryptedDocument.Load(new Passphrase("passphrase"), new V2Aes256CryptoFactory().Id, outputStream), Is.True);
+                            Assert.Throws<Axantum.AxCrypt.Core.Runtime.IncorrectDataException>(() => decryptedDocument.DecryptTo(Stream.Null));
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDecryptToWithReaderWronglyPositioned()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(1000);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 113))
+                    {
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+
+                        outputStream.Position = 0;
+                        using (V2AxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Headers headers = new Headers();
+                            AxCryptReader reader = headers.Load(outputStream);
+
+                            Assert.That(decryptedDocument.Load(new Passphrase("passphrase"), new V2Aes256CryptoFactory().Id, reader, headers), Is.True);
+                            reader.SetStartOfData();
+                            Assert.Throws<InvalidOperationException>(() => decryptedDocument.DecryptTo(Stream.Null));
+                        }
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public static void TestDocumentHeaderProperties()
+        {
+            using (MemoryStream inputStream = new MemoryStream())
+            {
+                byte[] text = Instance.RandomGenerator.Generate(500);
+                inputStream.Write(text, 0, text.Length);
+                inputStream.Position = 0;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (IAxCryptDocument document = new V2AxCryptDocument(new Passphrase("properties"), V2Aes256CryptoFactory.CryptoId, 15))
+                    {
+                        DateTime utcNow = OS.Current.UtcNow;
+                        DateTime lastWrite = utcNow.AddHours(1);
+                        DateTime lastAccess = utcNow.AddHours(2);
+                        DateTime create = utcNow.AddHours(3);
+
+                        document.CreationTimeUtc = create;
+                        document.LastAccessTimeUtc = lastAccess;
+                        document.LastWriteTimeUtc = lastWrite;
+
+                        document.FileName = "Property Test.txt";
+                        document.EncryptTo(inputStream, outputStream, AxCryptOptions.EncryptWithCompression);
+
+                        outputStream.Position = 0;
+                        using (IAxCryptDocument decryptedDocument = new V2AxCryptDocument())
+                        {
+                            Assert.That(decryptedDocument.Load(new Passphrase("properties"), V2Aes256CryptoFactory.CryptoId, outputStream), Is.True);
+
+                            Assert.That(decryptedDocument.CreationTimeUtc, Is.EqualTo(create));
+                            Assert.That(decryptedDocument.LastAccessTimeUtc, Is.EqualTo(lastAccess));
+                            Assert.That(decryptedDocument.LastWriteTimeUtc, Is.EqualTo(lastWrite));
+                            Assert.That(decryptedDocument.FileName, Is.EqualTo("Property Test.txt"));
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2AxCryptReader.cs b/Axantum.AxCrypt.Core.Test/TestV2AxCryptReader.cs
new file mode 100644
index 0000000..b6849f8
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2AxCryptReader.cs
@@ -0,0 +1,89 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2AxCryptReader
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestGetCryptoFromHeaders()
+        {
+            Headers headers = new Headers();
+            V2DocumentHeaders documentHeaders = new V2DocumentHeaders(new Passphrase("passphrase"), V2Aes256CryptoFactory.CryptoId, 10);
+            using (Stream chainedStream = new MemoryStream())
+            {
+                using (V2HmacStream stream = new V2HmacStream(new byte[0], chainedStream))
+                {
+                    documentHeaders.WriteStartWithHmac(stream);
+                    stream.Flush();
+                    chainedStream.Position = 0;
+
+                    using (V2AxCryptReader reader = new V2AxCryptReader(chainedStream))
+                    {
+                        while (reader.Read())
+                        {
+                            if (reader.CurrentItemType == AxCryptItemType.HeaderBlock)
+                            {
+                                headers.HeaderBlocks.Add(reader.CurrentHeaderBlock);
+                            }
+                        }
+                        V2KeyWrapHeaderBlock keyWrap = headers.FindHeaderBlock<V2KeyWrapHeaderBlock>();
+                        SymmetricKey dataEncryptingKey = documentHeaders.DataEncryptingKey;
+
+                        IDerivedKey key = new V2Aes256CryptoFactory().RestoreDerivedKey(new Passphrase("passphrase"), keyWrap.DerivationSalt, keyWrap.DerivationIterations);
+                        keyWrap.SetCryptoKey(new V2Aes256CryptoFactory(), key);
+
+                        Assert.That(dataEncryptingKey.Equals(documentHeaders.DataEncryptingKey));
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2CompressionEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2CompressionEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..274da34
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2CompressionEncryptedHeaderBlock.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2CompressionEncryptedHeaderBlock
+    {
+        [Test]
+        public static void TestClone()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+
+            V2CompressionEncryptedHeaderBlock compressionHeaderBlock = new V2CompressionEncryptedHeaderBlock(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0));
+            compressionHeaderBlock.IsCompressed = false;
+            Assert.That(compressionHeaderBlock.IsCompressed, Is.False);
+
+            compressionHeaderBlock.IsCompressed = true;
+            V2CompressionEncryptedHeaderBlock clone = (V2CompressionEncryptedHeaderBlock)compressionHeaderBlock.Clone();
+            Assert.That(clone.IsCompressed, Is.True);
+
+            Factory.Instance.Clear();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2DocumentHeaders.cs b/Axantum.AxCrypt.Core.Test/TestV2DocumentHeaders.cs
new file mode 100644
index 0000000..e078602
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2DocumentHeaders.cs
@@ -0,0 +1,208 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2DocumentHeaders
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestFileTimes()
+        {
+            using (V2DocumentHeaders headers = new V2DocumentHeaders(new Passphrase("v2passx"), V2Aes256CryptoFactory.CryptoId, 12))
+            {
+                DateTime now = DateTime.UtcNow;
+                headers.LastAccessTimeUtc = now;
+                headers.LastWriteTimeUtc = now.AddHours(1);
+                headers.CreationTimeUtc = now.AddHours(2);
+
+                Assert.That(headers.LastAccessTimeUtc, Is.EqualTo(now));
+                Assert.That(headers.LastWriteTimeUtc, Is.EqualTo(now.AddHours(1)));
+                Assert.That(headers.CreationTimeUtc, Is.EqualTo(now.AddHours(2)));
+            }
+        }
+
+        [Test]
+        public static void TestCompression()
+        {
+            using (V2DocumentHeaders headers = new V2DocumentHeaders(new Passphrase("v2pass"), V2Aes256CryptoFactory.CryptoId, 10))
+            {
+                headers.IsCompressed = true;
+                Assert.That(headers.IsCompressed, Is.True);
+
+                headers.IsCompressed = false;
+                Assert.That(headers.IsCompressed, Is.False);
+            }
+        }
+
+        [Test]
+        public static void TestUnicodeFileNameShort()
+        {
+            using (V2DocumentHeaders headers = new V2DocumentHeaders(new Passphrase("v2passz"), V2Aes256CryptoFactory.CryptoId, 10))
+            {
+                headers.FileName = "My Secret Document.txt";
+                Assert.That(headers.FileName, Is.EqualTo("My Secret Document.txt"));
+            }
+        }
+
+        [Test]
+        public static void TestUnicodeFileNameLong()
+        {
+            using (V2DocumentHeaders headers = new V2DocumentHeaders(new Passphrase("v2passy"), V2Aes256CryptoFactory.CryptoId, 10))
+            {
+                string longName = "When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume among the powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the separation.";
+                Assert.That(longName.Length, Is.GreaterThan(256));
+
+                headers.FileName = longName;
+                Assert.That(headers.FileName, Is.EqualTo(longName));
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestWriteWithHmac()
+        {
+            using (V2DocumentHeaders headers = new V2DocumentHeaders(new Passphrase("v2passzz"), V2Aes256CryptoFactory.CryptoId, 20))
+            {
+                byte[] output;
+                using (MemoryStream outputStream = new MemoryStream())
+                {
+                    using (V2HmacStream hmacStream = new V2HmacStream(headers.GetHmacKey(), outputStream))
+                    {
+                        headers.WriteStartWithHmac(hmacStream);
+                        headers.WriteEndWithHmac(hmacStream, 0, 0);
+                    }
+                    output = outputStream.ToArray();
+                }
+
+                byte[] hmacBytesFromHeaders = new byte[V2Hmac.RequiredLength];
+                Array.Copy(output, output.Length - V2Hmac.RequiredLength, hmacBytesFromHeaders, 0, V2Hmac.RequiredLength);
+                V2Hmac hmacFromHeaders = new V2Hmac(hmacBytesFromHeaders);
+
+                byte[] dataToHmac = new byte[output.Length - (V2Hmac.RequiredLength + 5)];
+                Array.Copy(output, 0, dataToHmac, 0, dataToHmac.Length);
+
+                HMACSHA512 hmac = new HMACSHA512(headers.GetHmacKey());
+                hmac.TransformFinalBlock(dataToHmac, 0, dataToHmac.Length);
+                V2Hmac hmacFromCalculation = new V2Hmac(hmac.Hash);
+
+                Assert.That(hmacFromHeaders, Is.EqualTo(hmacFromCalculation));
+            }
+        }
+
+        [Test]
+        public static void TestLoadWithInvalidPassphrase()
+        {
+            Headers headers = new Headers();
+
+            headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            headers.HeaderBlocks.Add(new VersionHeaderBlock(new byte[] { 4, 0, 2, 0, 0 }));
+            headers.HeaderBlocks.Add(new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), new V2DerivedKey(new Passphrase("RealKey"), 256), 10));
+            headers.HeaderBlocks.Add(new FileInfoEncryptedHeaderBlock(new byte[0]));
+            headers.HeaderBlocks.Add(new V2CompressionEncryptedHeaderBlock(new byte[1]));
+            headers.HeaderBlocks.Add(new V2UnicodeFileNameInfoEncryptedHeaderBlock(new byte[0]));
+            headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            using (V2DocumentHeaders documentHeaders = new V2DocumentHeaders(new Passphrase("WrongKey"), V2Aes256CryptoFactory.CryptoId, 10))
+            {
+                Assert.That(documentHeaders.Load(headers), Is.False);
+            }
+        }
+
+        [Test]
+        public static void TestWriteStartWithHmacWithNullArgument()
+        {
+            using (V2DocumentHeaders documentHeaders = new V2DocumentHeaders(new Passphrase("Key"), V2Aes256CryptoFactory.CryptoId, 10))
+            {
+                Assert.Throws<ArgumentNullException>(() => documentHeaders.WriteStartWithHmac(null));
+            }
+        }
+
+        [Test]
+        public static void TestHeadersPropertyGetter()
+        {
+            using (V2DocumentHeaders documentHeaders = new V2DocumentHeaders(new V2DerivedKey(new Passphrase("Key"), 256), V2Aes256CryptoFactory.CryptoId))
+            {
+                Assert.That(documentHeaders.Headers.HeaderBlocks.Count, Is.EqualTo(0));
+            }
+        }
+
+        private class UnknownEncryptedHeaderBlock : EncryptedHeaderBlock
+        {
+            public UnknownEncryptedHeaderBlock(byte[] dataBlock)
+                : base((HeaderBlockType)199, dataBlock)
+            {
+            }
+
+            public override object Clone()
+            {
+                throw new NotImplementedException();
+            }
+        }
+
+        [Test]
+        public static void TestUnknownEncryptedHeader()
+        {
+            Headers headers = new Headers();
+            IDerivedKey key = new V2DerivedKey(new Passphrase("A key"), 256);
+            headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            headers.HeaderBlocks.Add(new VersionHeaderBlock(new byte[] { 4, 0, 2, 0, 0 }));
+            headers.HeaderBlocks.Add(new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), key, 10));
+            headers.HeaderBlocks.Add(new FileInfoEncryptedHeaderBlock(new byte[0]));
+            headers.HeaderBlocks.Add(new V2CompressionEncryptedHeaderBlock(new byte[1]));
+            headers.HeaderBlocks.Add(new V2UnicodeFileNameInfoEncryptedHeaderBlock(new byte[0]));
+            headers.HeaderBlocks.Add(new UnknownEncryptedHeaderBlock(new byte[0]));
+            headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            using (V2DocumentHeaders documentHeaders = new V2DocumentHeaders(key, V2Aes256CryptoFactory.CryptoId))
+            {
+                Assert.Throws<InternalErrorException>(() => documentHeaders.Load(headers));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2HmacHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2HmacHeaderBlock.cs
new file mode 100644
index 0000000..e341c83
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2HmacHeaderBlock.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2HmacHeaderBlock
+    {
+        [Test]
+        public static void TestBadConstructorArgument()
+        {
+            V2HmacHeaderBlock headerBlock = null;
+            Assert.Throws<ArgumentNullException>(() => headerBlock = new V2HmacHeaderBlock(null));
+			Assert.That(headerBlock, Is.Null);
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+
+            V2HmacHeaderBlock headerBlock = new V2HmacHeaderBlock();
+            headerBlock.Hmac = new V2Hmac(Instance.RandomGenerator.Generate(V2Hmac.RequiredLength));
+
+            V2HmacHeaderBlock clone = (V2HmacHeaderBlock)headerBlock.Clone();
+
+            Assert.That(clone.GetDataBlockBytes(), Is.EquivalentTo(headerBlock.GetDataBlockBytes()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2HmacStreamTest.cs b/Axantum.AxCrypt.Core.Test/TestV2HmacStreamTest.cs
new file mode 100644
index 0000000..383fada
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2HmacStreamTest.cs
@@ -0,0 +1,232 @@
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2HmacStreamTest
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase1()
+        {
+            byte[] key = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b".FromHex();
+            byte[] data = "4869205468657265".FromHex();
+            byte[] hmac_sha_512 = "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase2()
+        {
+            byte[] key = "4a656665".FromHex();
+            byte[] data = "7768617420646f2079612077616e7420666f72206e6f7468696e673f".FromHex();
+            byte[] hmac_sha_512 = "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase3()
+        {
+            byte[] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".FromHex();
+            byte[] data = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd".FromHex();
+            byte[] hmac_sha_512 = "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase4()
+        {
+            byte[] key = "0102030405060708090a0b0c0d0e0f10 111213141516171819".FromHex();
+            byte[] data = "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd cdcd".FromHex();
+            byte[] hmac_sha_512 = "b0ba465637458c6990e5a8c5f61d4af7 e576d97ff94b872de76f8050361ee3db a91ca5c11aa25eb4d679275cc5788063 a5f19741120c4f2de2adebeb10a298dd".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase5()
+        {
+            byte[] key = "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c 0c0c0c0c".FromHex();
+            byte[] data = "546573742057697468205472756e6361 74696f6e".FromHex();
+            byte[] hmac_sha_512 = "415fad6271580a531d4179bc891d87a6".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = new byte[16];
+                Array.Copy(stream.Hmac.GetBytes(), 0, result, 0, 16);
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase6()
+        {
+            byte[] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa".FromHex();
+            byte[] data = "54657374205573696e67204c61726765 72205468616e20426c6f636b2d53697a 65204b6579202d2048617368204b6579 204669727374".FromHex();
+            byte[] hmac_sha_512 = "80b24263c7c1a3ebb71493c1dd7be8b4 9b46d1f41b4aeec1121b013783f8f352 6b56d037e05f2598bd0fd2215d6a1e52 95e64f73f63f0aec8b915a985d786598".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase7()
+        {
+            byte[] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa".FromHex();
+            byte[] data = "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e".FromHex();
+            byte[] hmac_sha_512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffd debd71f8867289865df5a32d20cdc944 b6022cac3c4982b10d5eeb55c3e4de15 134676fb6de0446065c97440fa8c6a58".FromHex();
+
+            byte[] result;
+            using (V2HmacStream stream = new V2HmacStream(key))
+            {
+                stream.Write(data, 0, data.Length);
+                result = stream.Hmac.GetBytes();
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Rfc", Justification = "This is well-known acronymn")]
+        public static void Rfc4231TestCase7WithChaining()
+        {
+            byte[] key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaa".FromHex();
+            byte[] data = "54686973206973206120746573742075 73696e672061206c6172676572207468 616e20626c6f636b2d73697a65206b65 7920616e642061206c61726765722074 68616e20626c6f636b2d73697a652064 6174612e20546865206b6579206e6565 647320746f2062652068617368656420 6265666f7265206265696e6720757365 642062792074686520484d414320616c 676f726974686d2e".FromHex();
+            byte[] hmac_sha_512 = "e37b6a775dc87dbaa4dfa9f96e5e3ffd debd71f8867289865df5a32d20cdc944 b6022cac3c4982b10d5eeb55c3e4de15 134676fb6de0446065c97440fa8c6a58".FromHex();
+
+            byte[] result;
+            using (MemoryStream output = new MemoryStream())
+            {
+                using (V2HmacStream stream = new V2HmacStream(key, output))
+                {
+                    stream.Write(data, 0, data.Length);
+                    result = stream.Hmac.GetBytes();
+                }
+                byte[] chained = output.ToArray();
+                Assert.That(chained, Is.EquivalentTo(data));
+            }
+
+            Assert.That(result, Is.EquivalentTo(hmac_sha_512));
+        }
+
+        [Test]
+        public static void TestConstructorNullArgument()
+        {
+            byte[] nullBytes = null;
+            Stream stream = null;
+            Assert.Throws<ArgumentNullException>(() => stream = new V2HmacStream(nullBytes));
+            Assert.That(stream, Is.Null);
+        }
+
+        [Test]
+        public static void TestNotSupportedMethods()
+        {
+            using (V2HmacStream stream = new V2HmacStream(new byte[512]))
+            {
+                Assert.Throws<NotSupportedException>(() => stream.Read(new byte[1], 0, 1));
+                Assert.Throws<NotSupportedException>(() => stream.Seek(0, SeekOrigin.Begin));
+                Assert.Throws<NotSupportedException>(() => stream.SetLength(0));
+                Assert.Throws<NotSupportedException>(() => stream.Position = 0);
+            }
+        }
+
+        [Test]
+        public static void TestCapabilities()
+        {
+            using (V2HmacStream stream = new V2HmacStream(new byte[512]))
+            {
+                Assert.That(stream.CanRead, Is.False);
+                Assert.That(stream.CanSeek, Is.False);
+                Assert.That(stream.CanWrite, Is.True);
+            }
+        }
+
+        [Test]
+        public static void TestPosition()
+        {
+            using (V2HmacStream stream = new V2HmacStream(new byte[512]))
+            {
+                Assert.That(stream.Position, Is.EqualTo(0));
+                stream.Write(new byte[1], 0, 1);
+                Assert.That(stream.Position, Is.EqualTo(1));
+                Assert.That(stream.Length, Is.EqualTo(1));
+            }
+        }
+
+        [Test]
+        public static void TestDispose()
+        {
+            using (V2HmacStream stream = new V2HmacStream(new byte[512]))
+            {
+                stream.Dispose();
+                Assert.DoesNotThrow(() => stream.Dispose());
+                Assert.Throws<ObjectDisposedException>(() => stream.Write(new byte[1], 0, 1));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2KeyWrapHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2KeyWrapHeaderBlock.cs
new file mode 100644
index 0000000..a9484ae
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2KeyWrapHeaderBlock.cs
@@ -0,0 +1,201 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2KeyWrapHeaderBlock
+    {
+        private class DerivedKeyForTest : DerivedKeyBase
+        {
+            public DerivedKeyForTest(SymmetricKey key)
+            {
+                DerivedKey = key;
+                DerivationSalt = Salt.Zero;
+                DerivationIterations = 1;
+            }
+        }
+
+        private static readonly IDerivedKey _keyEncryptingKey128 = new DerivedKeyForTest(new SymmetricKey(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }));
+        private static readonly SymmetricKey _keyData128 = new SymmetricKey(new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF });
+        private static readonly byte[] _wrapped128 = new byte[] { 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 };
+
+        private static readonly IDerivedKey _keyEncryptingKey256 = new DerivedKeyForTest(new SymmetricKey(new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }));
+        private static readonly byte[] _keyData256 = new byte[] { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F };
+        private static readonly byte[] _wrapped256 = new byte[] { 0x28, 0xC9, 0xF4, 0x04, 0xC4, 0xB8, 0x10, 0xF4, 0xCB, 0xCC, 0xB3, 0x5C, 0xFB, 0x87, 0xF8, 0x26, 0x3F, 0x57, 0x86, 0xE2, 0xD8, 0x0E, 0xD3, 0x26, 0xCB, 0xC7, 0xF0, 0xE7, 0x1A, 0x99, 0xF4, 0x3B, 0xFB, 0x98, 0x8B, 0x9B, 0x7A, 0x02, 0xDD, 0x21 };
+
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<CryptoFactory>(() => SetupAssembly.CreateCryptoFactory());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestConstructorFromBytes()
+        {
+            byte[] datablock = new byte[248];
+            for (int i = 247; i >= 0; --i)
+            {
+                datablock[247 - i] = (byte)i;
+            }
+
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(datablock);
+            Assert.That(header.GetDataBlockBytes(), Is.EquivalentTo(datablock));
+
+            header = null;
+            Assert.Throws<ArgumentException>(() => header = new V2KeyWrapHeaderBlock(new byte[247]));
+            Assert.Throws<ArgumentNullException>(() => header = new V2KeyWrapHeaderBlock(null));
+            Assert.That(header, Is.Null);
+        }
+
+        [Test]
+        public static void TestConstructorFromKeyUsingKeyWrap128TestVectors()
+        {
+            var mock = new Mock<IRandomGenerator>();
+            mock.Setup<byte[]>(x => x.Generate(It.Is<int>(v => v == 248))).Returns(new byte[248]);
+            mock.Setup<byte[]>(x => x.Generate(It.Is<int>(v => v == (16 + 16)))).Returns(_keyData128.GetBytes());
+            Factory.Instance.Singleton<IRandomGenerator>(() => mock.Object);
+
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes128CryptoFactory(), _keyEncryptingKey128, 6);
+
+            byte[] bytes = header.GetDataBlockBytes();
+            byte[] wrapped = new byte[24];
+            Array.Copy(bytes, 0, wrapped, 0, wrapped.Length);
+
+            Assert.That(wrapped, Is.EquivalentTo(_wrapped128));
+        }
+
+        [Test]
+        public static void TestConstructorFromKeyUsingKeyWrap256TestVectors()
+        {
+            var mock = new Mock<IRandomGenerator>();
+            mock.Setup<byte[]>(x => x.Generate(It.Is<int>(v => v == 248))).Returns(new byte[248]);
+            mock.Setup<byte[]>(x => x.Generate(It.Is<int>(v => v == (32 + 16)))).Returns(_keyData256);
+            Factory.Instance.Singleton<IRandomGenerator>(() => mock.Object);
+
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), _keyEncryptingKey256, 6);
+
+            byte[] bytes = header.GetDataBlockBytes();
+            byte[] wrapped = new byte[40];
+            Array.Copy(bytes, 0, wrapped, 0, wrapped.Length);
+
+            Assert.That(wrapped, Is.EquivalentTo(_wrapped256));
+        }
+
+        [Test]
+        public static void TestUnwrapMasterKeyAndIV256WithZeroRandomNumbers()
+        {
+            var mock = new Mock<IRandomGenerator>();
+            mock.Setup<byte[]>(x => x.Generate(It.IsAny<int>())).Returns<int>(v => new byte[v]);
+            Factory.Instance.Singleton<IRandomGenerator>(() => mock.Object);
+
+            IDerivedKey keyEncryptingKey = new V2DerivedKey(new Passphrase("secret"), new Salt(256), 100, 256);
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), keyEncryptingKey, 250);
+
+            SymmetricKey key = header.MasterKey;
+            Assert.That(key.GetBytes(), Is.EquivalentTo(new byte[32]));
+
+            SymmetricIV iv = header.MasterIV;
+            Assert.That(iv.GetBytes(), Is.EquivalentTo(new byte[16]));
+        }
+
+        [Test]
+        public static void TestUnwrapMasterKeyAndIV256WithNonzeroRandomNumbers()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+
+            IDerivedKey keyEncryptingKey = new V2DerivedKey(new Passphrase("secret"), new Salt(256), 100, 256);
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), keyEncryptingKey, 125);
+
+            SymmetricKey key = header.MasterKey;
+            Assert.That(key.GetBytes(), Is.EquivalentTo(ByteSequence(key.GetBytes()[0], key.Size / 8)));
+
+            SymmetricIV iv = header.MasterIV;
+            Assert.That(iv.GetBytes(), Is.EquivalentTo(ByteSequence(iv.GetBytes()[0], iv.Length)));
+        }
+
+        private static byte[] ByteSequence(byte start, int length)
+        {
+            byte[] sequence = new byte[length];
+            sequence[0] = start;
+            for (int i = 1; i < sequence.Length; ++i)
+            {
+                sequence[i] = (byte)(sequence[i - 1] + 1);
+            }
+            return sequence;
+        }
+
+        [Test]
+        public static void TestMasterIVWithWrongKeyEncryptingCrypto()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+
+            IDerivedKey keyEncryptingKey = new V2DerivedKey(new Passphrase("secret"), new Salt(256), 100, 256);
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), keyEncryptingKey, 125);
+
+            header.SetCryptoKey(new V2Aes256CryptoFactory(), new V2DerivedKey(new Passphrase("another secret"), 256));
+            SymmetricIV iv = header.MasterIV;
+
+            Assert.That(iv, Is.Null);
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+
+            IDerivedKey keyEncryptingKey = new V2DerivedKey(new Passphrase("secret"), new Salt(256), 100, 256);
+            V2KeyWrapHeaderBlock header = new V2KeyWrapHeaderBlock(new V2Aes256CryptoFactory(), keyEncryptingKey, 125);
+
+            V2KeyWrapHeaderBlock clone = (V2KeyWrapHeaderBlock)header.Clone();
+
+            Assert.That(header.GetDataBlockBytes(), Is.EquivalentTo(clone.GetDataBlockBytes()));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2PlainTextLengthsEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2PlainTextLengthsEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..3419a84
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2PlainTextLengthsEncryptedHeaderBlock.cs
@@ -0,0 +1,101 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2PlaintextLengthsEncryptedHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<CryptoFactory>(() => CreateCryptoFactory());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+        }
+
+        private static CryptoFactory CreateCryptoFactory()
+        {
+            CryptoFactory factory = new CryptoFactory();
+            factory.Add(() => new V2Aes256CryptoFactory());
+            factory.Add(() => new V1Aes128CryptoFactory());
+
+            return factory;
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            V2PlaintextLengthsEncryptedHeaderBlock block = new V2PlaintextLengthsEncryptedHeaderBlock(new V2AesCrypto(new V2DerivedKey(new Passphrase("secret"), 256).DerivedKey, SymmetricIV.Zero128, 0));
+            V2PlaintextLengthsEncryptedHeaderBlock clone = (V2PlaintextLengthsEncryptedHeaderBlock)block.Clone();
+
+            Assert.That(!Object.ReferenceEquals(block.GetDataBlockBytes(), clone.GetDataBlockBytes()));
+            Assert.That(block.GetDataBlockBytes(), Is.EquivalentTo(clone.GetDataBlockBytes()));
+        }
+
+        [Test]
+        public static void TestPlaintextLength()
+        {
+            V2PlaintextLengthsEncryptedHeaderBlock block = new V2PlaintextLengthsEncryptedHeaderBlock(new V2AesCrypto(new V2DerivedKey(new Passphrase("secret"), 256).DerivedKey, SymmetricIV.Zero128, 0));
+
+            Assert.That(block.PlaintextLength, Is.EqualTo(0));
+
+            block.PlaintextLength = 123;
+            block.CompressedPlaintextLength = 456;
+            Assert.That(block.PlaintextLength, Is.EqualTo(123));
+        }
+
+        [Test]
+        public static void TestCompressedPlaintextLength()
+        {
+            V2PlaintextLengthsEncryptedHeaderBlock block = new V2PlaintextLengthsEncryptedHeaderBlock(new V2AesCrypto(new V2DerivedKey(new Passphrase("secret"), 256).DerivedKey, SymmetricIV.Zero128, 0));
+
+            Assert.That(block.CompressedPlaintextLength, Is.EqualTo(0));
+
+            block.PlaintextLength = 123;
+            block.CompressedPlaintextLength = 456;
+            Assert.That(block.CompressedPlaintextLength, Is.EqualTo(456));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2RegressionCompleteFiles.cs b/Axantum.AxCrypt.Core.Test/TestV2RegressionCompleteFiles.cs
new file mode 100644
index 0000000..8056c1e
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2RegressionCompleteFiles.cs
@@ -0,0 +1,93 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Security.Cryptography;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2RegressionCompleteFiles
+    {
+        private static readonly string _rootPath = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments));
+
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestSimpleSmallFile256()
+        {
+            TestOneFile("short-txt-AES256.axx", "PâsswördètMëd§½ Lôñg|´¨", "2de4823aa40ed2a6d040e7ba67bf60e3b1ae5c1f1bc2391ba8435ec7d1597f49");
+        }
+
+        [Test]
+        public static void TestLargerUncompressibleFile256()
+        {
+            TestOneFile("snow-jpg-AES256.axx", "PâsswördètMëd§½ Lôñg|´¨", "b541684642894f9385b15ddd62f980e20a730fc036bcb1bbb4bad75b1f4889b4");
+        }
+
+        [Test]
+        public static void TestLargerCompressibleTextFile256()
+        {
+            TestOneFile("Frankenstein-txt-AES256.axx", "PâsswördètMëd§½ Lôñg|´¨", "3493994a1a7d891e1a6fb4e3f60c58cbfb3e6f71f12f4c3ffe51c0c9498eb520");
+        }
+
+        [Test]
+        public static void TestSimpleSmallFile128()
+        {
+            TestV2RegressionCompleteFiles.TestOneFile("short-txt-V2AES128.axx", "PâsswördètMëd§½ Lôñg|´¨", "2de4823aa40ed2a6d040e7ba67bf60e3b1ae5c1f1bc2391ba8435ec7d1597f49");
+        }
+
+        [Test]
+        public static void TestLargerUncompressibleFile128()
+        {
+            TestV2RegressionCompleteFiles.TestOneFile("snow-jpg-V2AES128.axx", "PâsswördètMëd§½ Lôñg|´¨", "b541684642894f9385b15ddd62f980e20a730fc036bcb1bbb4bad75b1f4889b4");
+        }
+
+        [Test]
+        public static void TestLargerCompressibleTextFile128()
+        {
+            TestV2RegressionCompleteFiles.TestOneFile("Frankenstein-txt-V2AES128.axx", "PâsswördètMëd§½ Lôñg|´¨", "3493994a1a7d891e1a6fb4e3f60c58cbfb3e6f71f12f4c3ffe51c0c9498eb520");
+        }
+
+        internal static void TestOneFile(string resourceName, string password, string sha256HashValue)
+        {
+            string source = Path.Combine(_rootPath, "source.axx");
+            string destination = Path.Combine(_rootPath, "destination.file");
+            Stream stream = Assembly.GetAssembly(typeof(TestV2RegressionCompleteFiles)).GetManifestResourceStream("Axantum.AxCrypt.Core.Test.resources." + resourceName);
+            FakeRuntimeFileInfo.AddFile(source, FakeRuntimeFileInfo.TestDate1Utc, FakeRuntimeFileInfo.TestDate2Utc, FakeRuntimeFileInfo.TestDate3Utc, stream);
+
+            Passphrase passphrase = new Passphrase(password);
+
+            bool ok = new AxCryptFile().Decrypt(Factory.New<IRuntimeFileInfo>(source), Factory.New<IRuntimeFileInfo>(destination), passphrase, AxCryptOptions.SetFileTimes, new ProgressContext());
+            Assert.That(ok, Is.True, "The Decrypt() method should return true for ok.");
+
+            byte[] hash;
+            using (Stream plainStream = Factory.New<IRuntimeFileInfo>(destination).OpenRead())
+            {
+                HashAlgorithm hashAlgorithm = SHA256.Create();
+                using (Stream cryptoStream = new CryptoStream(plainStream, hashAlgorithm, CryptoStreamMode.Read))
+                {
+                    cryptoStream.CopyTo(Stream.Null);
+                }
+                hash = hashAlgorithm.Hash;
+            }
+
+            Assert.That(hash.IsEquivalentTo(sha256HashValue.FromHex()), "Wrong SHA-256.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestV2UnicodeFileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core.Test/TestV2UnicodeFileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..a4fa48b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestV2UnicodeFileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,94 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestV2UnicodeFileNameInfoEncryptedHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<CryptoFactory>(() => CreateCryptoFactory());
+            Factory.Instance.Singleton<ICryptoPolicy>(() => new ProCryptoPolicy());
+        }
+
+        private static CryptoFactory CreateCryptoFactory()
+        {
+            CryptoFactory factory = new CryptoFactory();
+            factory.Add(() => new V2Aes256CryptoFactory());
+            factory.Add(() => new V1Aes128CryptoFactory());
+
+            return factory;
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestClone()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+
+            V2UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = new V2UnicodeFileNameInfoEncryptedHeaderBlock(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0));
+            headerBlock.FileName = "A file name";
+            Assert.That(headerBlock.FileName, Is.EqualTo("A file name"));
+
+            V2UnicodeFileNameInfoEncryptedHeaderBlock clone = (V2UnicodeFileNameInfoEncryptedHeaderBlock)headerBlock.Clone();
+            Assert.That(clone.FileName, Is.EqualTo("A file name"));
+        }
+
+        [Test]
+        public static void TestBadDataCausedByBadKeyForExample()
+        {
+            Factory.Instance.Singleton<IRandomGenerator>(() => new FakeRandomGenerator());
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new FakeRuntimeEnvironment());
+
+            V2UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = new V2UnicodeFileNameInfoEncryptedHeaderBlock(new V2AesCrypto(SymmetricKey.Zero256, SymmetricIV.Zero128, 0));
+            headerBlock.FileName = "A file name";
+            Assert.That(headerBlock.FileName, Is.EqualTo("A file name"));
+
+            headerBlock.HeaderCrypto = new V2AesCrypto(new V2DerivedKey(new Passphrase("passphrase"), 256).DerivedKey, SymmetricIV.Zero128, 0);
+            string s;
+            Assert.Throws<InvalidOperationException>(() => s = headerBlock.FileName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestVXAxCryptReader.cs b/Axantum.AxCrypt.Core.Test/TestVXAxCryptReader.cs
new file mode 100644
index 0000000..bef8f9b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestVXAxCryptReader.cs
@@ -0,0 +1,98 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestVXAxCryptReader
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestHeaderBlockFactory()
+        {
+            V1DocumentHeaders headers = new V1DocumentHeaders(new Passphrase("passphrase"), 10);
+            using (MemoryStream stream = new MemoryStream())
+            {
+                headers.WriteWithoutHmac(stream);
+                stream.Position = 0;
+
+                using (VXAxCryptReader reader = new VXAxCryptReader(stream))
+                {
+                    bool unexpectedHeaderTypeFound = false;
+                    while (reader.Read())
+                    {
+                        if (reader.CurrentItemType != AxCryptItemType.HeaderBlock)
+                        {
+                            continue;
+                        }
+                        switch (reader.CurrentHeaderBlock.HeaderBlockType)
+                        {
+                            case HeaderBlockType.Preamble:
+                            case HeaderBlockType.Version:
+                            case HeaderBlockType.Data:
+                            case HeaderBlockType.Unrecognized:
+                                break;
+
+                            default:
+                                unexpectedHeaderTypeFound = !(reader.CurrentHeaderBlock is UnrecognizedHeaderBlock);
+                                break;
+                        }
+                    }
+                    Assert.That(unexpectedHeaderTypeFound, Is.False);
+                }
+            }
+        }
+
+        [Test]
+        public static void TestNotImplemented()
+        {
+            using (VXAxCryptReader reader = new VXAxCryptReader(Stream.Null))
+            {
+                Assert.Throws<NotImplementedException>(() => reader.Document(new Passphrase("test"), V1Aes128CryptoFactory.CryptoId, new Headers()));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestVersionHeaderBlock .cs b/Axantum.AxCrypt.Core.Test/TestVersionHeaderBlock .cs
new file mode 100644
index 0000000..1e5189a
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestVersionHeaderBlock .cs	
@@ -0,0 +1,70 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using NUnit.Framework;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestVersionHeaderBlock
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestVersionValues()
+        {
+            VersionHeaderBlock versionHeaderBlock = new VersionHeaderBlock(new byte[] { 3, 2, 2, 0, 0 });
+
+            Assert.That(versionHeaderBlock.FileVersionMajor, Is.EqualTo(3), "This is the current default version number");
+            Assert.That(versionHeaderBlock.FileVersionMinor, Is.EqualTo(2), "This is the current default version number");
+            Assert.That(versionHeaderBlock.VersionMajor, Is.EqualTo(2), "This is the current default version number");
+            Assert.That(versionHeaderBlock.VersionMinor, Is.EqualTo(0), "This is the current default version number");
+            Assert.That(versionHeaderBlock.VersionMinuscule, Is.EqualTo(0), "This is the current default version number");
+        }
+
+        [Test]
+        public static void TestSetCurrentVersion()
+        {
+            VersionHeaderBlock versionHeaderBlock = new VersionHeaderBlock(new byte[] { 3, 2, 2, 0, 0 });
+            Assert.That(versionHeaderBlock.GetDataBlockBytes(), Is.EquivalentTo(new byte[] { 3, 2, 2, 0, 0 }));
+
+            versionHeaderBlock.SetCurrentVersion(new byte[] { 5, 6, 7, 8, 9 });
+            Assert.That(versionHeaderBlock.GetDataBlockBytes(), Is.EquivalentTo(new byte[] { 5, 6, 7, 8, 9 }));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestViewModelBaseTest.cs b/Axantum.AxCrypt.Core.Test/TestViewModelBaseTest.cs
new file mode 100644
index 0000000..c4c1fb7
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestViewModelBaseTest.cs
@@ -0,0 +1,184 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using NUnit.Framework;
+using System;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestViewModelBaseTest
+    {
+        private enum TestValidationErrorCode
+        {
+            Unknown = 0,
+            BadString = 13,
+            BadInt = 14,
+        }
+
+        private class TestViewModel : ViewModelBase
+        {
+            public string StringProperty { get { return GetProperty<string>("StringProperty"); } set { SetProperty("StringProperty", value); } }
+
+            public int IntProperty { get { return GetProperty<int>("IntProperty"); } set { SetProperty("IntProperty", value); } }
+
+            public override string this[string columnName]
+            {
+                get
+                {
+                    switch (columnName)
+                    {
+                        case "StringProperty":
+                            if (StringProperty == "Error")
+                            {
+                                ValidationError = (int)TestValidationErrorCode.BadString;
+                                return "StringProperty Error";
+                            }
+                            break;
+
+                        case "IntProperty":
+                            if (IntProperty < 0)
+                            {
+                                ValidationError = (int)TestValidationErrorCode.BadInt;
+                                return "IntProperty Error";
+                            }
+                            break;
+                    }
+                    return base[columnName];
+                }
+            }
+        }
+
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IUIThread>(() => new FakeUIThread());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestGetSetProperty()
+        {
+            TestViewModel tvm = new TestViewModel();
+
+            Assert.That(tvm.StringProperty, Is.Null);
+
+            tvm.StringProperty = "A string value";
+            Assert.That(tvm.StringProperty, Is.EqualTo("A string value"));
+        }
+
+        [Test]
+        public static void TestSetPropertyValueChanged()
+        {
+            bool changed = false;
+            string value = null;
+            TestViewModel tvm = new TestViewModel();
+            tvm.BindPropertyChanged<string>("StringProperty", (v) => { value = v; changed = true; });
+
+            Assert.That(tvm.StringProperty, Is.Null);
+
+            tvm.StringProperty = "A string value";
+            Assert.That(tvm.StringProperty, Is.EqualTo("A string value"));
+
+            Assert.That(changed, Is.True);
+            Assert.That(value, Is.EqualTo("A string value"));
+
+            value = null;
+            changed = false;
+            tvm.StringProperty = "A string value";
+            Assert.That(tvm.StringProperty, Is.EqualTo("A string value"));
+
+            Assert.That(changed, Is.False);
+            Assert.That(value, Is.Null);
+
+            tvm.StringProperty = "Another string value";
+            Assert.That(tvm.StringProperty, Is.EqualTo("Another string value"));
+            Assert.That(changed, Is.True);
+            Assert.That(value, Is.EqualTo("Another string value"));
+        }
+
+        [Test]
+        public static void TestErrorNonExistingProperty()
+        {
+            TestViewModel tvm = new TestViewModel();
+
+            string s;
+            Assert.Throws<ArgumentException>(() => { s = tvm["NonExisting"]; });
+        }
+
+        [Test]
+        public static void TestNoErrorProperty()
+        {
+            TestViewModel tvm = new TestViewModel();
+
+            Assert.That(tvm["StringProperty"].Length, Is.EqualTo(0));
+            Assert.That(tvm.Error.Length, Is.EqualTo(0));
+        }
+
+        [Test]
+        public static void TestPropertyError()
+        {
+            TestViewModel tvm = new TestViewModel();
+            tvm.StringProperty = "Error";
+            tvm.IntProperty = -2;
+
+            Assert.That(tvm["StringProperty"], Is.EqualTo("StringProperty Error"));
+            Assert.That(tvm["IntProperty"], Is.EqualTo("IntProperty Error"));
+
+            Assert.That(tvm.Error, Is.StringContaining("StringProperty Error"));
+            Assert.That(tvm.Error, Is.StringContaining("IntProperty Error"));
+        }
+
+        [Test]
+        public static void TestValidationError()
+        {
+            TestViewModel tvm = new TestViewModel();
+            TestValidationErrorCode errorCode = TestValidationErrorCode.Unknown;
+            tvm.BindPropertyChanged<int>("ValidationError", (n) => { errorCode = (TestValidationErrorCode)n; });
+
+            tvm.StringProperty = "Error";
+            Assert.That(tvm.Error.Length, Is.GreaterThan(0));
+            Assert.That(errorCode, Is.EqualTo(TestValidationErrorCode.BadString));
+            Assert.That(tvm.ValidationError, Is.EqualTo((int)TestValidationErrorCode.BadString));
+
+            tvm.IntProperty = -100;
+            Assert.That(tvm.Error.Length, Is.GreaterThan(0));
+            Assert.That(errorCode, Is.EqualTo(TestValidationErrorCode.BadInt));
+            Assert.That(tvm.ValidationError, Is.EqualTo((int)TestValidationErrorCode.BadInt));
+
+            tvm.StringProperty = "";
+            tvm.IntProperty = 100;
+            Assert.That(tvm.Error.Length, Is.EqualTo(0));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestWatchedFolder.cs b/Axantum.AxCrypt.Core.Test/TestWatchedFolder.cs
new file mode 100644
index 0000000..0556d94
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestWatchedFolder.cs
@@ -0,0 +1,131 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    public static class TestWatchedFolder
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructor()
+        {
+            WatchedFolder watchedFolder = new WatchedFolder(@"C:\folder");
+            Assert.That(watchedFolder.Thumbprint, Is.EqualTo(SymmetricKeyThumbprint.Zero));
+        }
+
+        [Test]
+        public static void TestArgumentNullConstructor()
+        {
+            string nullString = null;
+            WatchedFolder watchedFolder = null;
+            SymmetricKeyThumbprint nullThumbprint = null;
+            Assert.Throws<ArgumentNullException>(() => { watchedFolder = new WatchedFolder(nullString, SymmetricKeyThumbprint.Zero); });
+            Assert.Throws<ArgumentNullException>(() => { watchedFolder = new WatchedFolder(String.Empty, nullThumbprint); });
+            Assert.Throws<ArgumentNullException>(() => { watchedFolder = new WatchedFolder(nullString); });
+            if (watchedFolder != null) { }
+        }
+
+        [Test]
+        public static void TestEquals()
+        {
+            WatchedFolder watchedFolder1a = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder1aReference = watchedFolder1a;
+            WatchedFolder watchedFolder1b = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder2 = new WatchedFolder(@"c:\test2", SymmetricKeyThumbprint.Zero);
+            WatchedFolder nullWatchedFolder = null;
+
+            Assert.That(watchedFolder1a.Equals(watchedFolder1aReference), "Reference equality should make them equal.");
+            Assert.That(watchedFolder1a.Equals(watchedFolder1b), "Value comparison should make them equal.");
+            Assert.That(!watchedFolder1a.Equals(nullWatchedFolder), "Never equal to null.");
+            Assert.That(!watchedFolder1a.Equals(watchedFolder2), "Different values, not equal.");
+        }
+
+        [Test]
+        public static void TestGetHashCode()
+        {
+            WatchedFolder watchedFolder1a = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder1b = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder2 = new WatchedFolder(@"c:\test2", SymmetricKeyThumbprint.Zero);
+
+            Assert.That(watchedFolder1a.GetHashCode(), Is.EqualTo(watchedFolder1b.GetHashCode()), "Different instances - same hash code.");
+            Assert.That(watchedFolder1a.GetHashCode(), Is.Not.EqualTo(watchedFolder2.GetHashCode()), "Different values - different hash code.");
+        }
+
+        [Test]
+        public static void TestOperatorOverloads()
+        {
+            WatchedFolder watchedFolder1a = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder1b = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            WatchedFolder watchedFolder2 = new WatchedFolder(@"c:\test2", SymmetricKeyThumbprint.Zero);
+
+            Assert.That(watchedFolder1a == watchedFolder1b, Is.True, "Different instances, same value.");
+            Assert.That(watchedFolder1a != watchedFolder2, Is.True, "Different values, not same.");
+        }
+
+        [Test]
+        public static void TestObjectEquals()
+        {
+            object watchedFolder1a = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            object watchedFolder1aReference = watchedFolder1a;
+            object watchedFolder1b = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+            object watchedFolder2 = @"c:\test1";
+            object nullObject = null;
+
+            Assert.That(watchedFolder1a.Equals(watchedFolder1b), Is.True, "Different instances, same value.");
+            Assert.That(watchedFolder1a.Equals(watchedFolder1aReference), Is.True, "Same instance.");
+            Assert.That(watchedFolder1a.Equals(watchedFolder2), Is.False, "Different values");
+            Assert.That(watchedFolder1a.Equals(watchedFolder2), Is.False, "Different types.");
+            Assert.That(watchedFolder1a.Equals(nullObject), Is.False, "Null is not equal to anything but null.");
+        }
+
+        [Test]
+        public static void TestDispose()
+        {
+            WatchedFolder watchedFolder = new WatchedFolder(@"c:\test1", SymmetricKeyThumbprint.Zero);
+
+            Assert.DoesNotThrow(() => watchedFolder.Dispose());
+            Assert.DoesNotThrow(() => watchedFolder.Dispose());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestWatchedFolderChangedEventArgsTest.cs b/Axantum.AxCrypt.Core.Test/TestWatchedFolderChangedEventArgsTest.cs
new file mode 100644
index 0000000..e1d268b
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestWatchedFolderChangedEventArgsTest.cs
@@ -0,0 +1,70 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using NUnit.Framework;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestWatchedFolderChangedEventArgsTest
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestConstructor()
+        {
+            List<WatchedFolder> addedFolders = new List<WatchedFolder>();
+            addedFolders.Add(new WatchedFolder(@"C:\Folder1\", SymmetricKeyThumbprint.Zero));
+            List<WatchedFolder> removedFolders = new List<WatchedFolder>();
+            removedFolders.Add(new WatchedFolder(@"C:\Folder2\", SymmetricKeyThumbprint.Zero));
+
+            WatchedFolderChangedEventArgs e = new WatchedFolderChangedEventArgs(addedFolders, removedFolders);
+
+            List<WatchedFolder> eventArgsAddedFolders = new List<WatchedFolder>(e.Added);
+            List<WatchedFolder> eventArgsRemovedFolders = new List<WatchedFolder>(e.Removed);
+
+            Assert.That(eventArgsAddedFolders, Is.EquivalentTo(addedFolders));
+            Assert.That(eventArgsRemovedFolders, Is.EquivalentTo(removedFolders));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestWorkFolderWatcher.cs b/Axantum.AxCrypt.Core.Test/TestWorkFolderWatcher.cs
new file mode 100644
index 0000000..b3f8e40
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestWorkFolderWatcher.cs
@@ -0,0 +1,74 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestWorkFolderWatcher
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestWorkFolderWatcherSimple()
+        {
+            Factory.Instance.Singleton<SessionNotify>(() => new Mock<SessionNotify>().Object);
+
+            using (WorkFolderWatcher wfw = new WorkFolderWatcher())
+            {
+                string fileName = Instance.WorkFolder.FileInfo.Combine("New File.txt").FullName;
+                FakeRuntimeFileInfo.AddFile(fileName, null);
+
+                Mock.Get(Instance.SessionNotify).Verify(s => s.Notify(It.Is<SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullName == fileName)), Times.Once);
+
+                Factory.New<IRuntimeFileInfo>(fileName).Delete();
+                Mock.Get(Instance.SessionNotify).Verify(s => s.Notify(It.Is<SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullName == fileName)), Times.Exactly(2));
+
+                IRuntimeFileInfo fileSystemStateInfo = Instance.WorkFolder.FileInfo.Combine("FileSystemState.xml");
+                fileSystemStateInfo.Delete();
+                Mock.Get(Instance.SessionNotify).Verify(s => s.Notify(It.Is<SessionNotification>(n => n.NotificationType == SessionNotificationType.WorkFolderChange && n.FullName == fileSystemStateInfo.FullName)), Times.Never);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestWorkerGroup.cs b/Axantum.AxCrypt.Core.Test/TestWorkerGroup.cs
new file mode 100644
index 0000000..a3ca629
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestWorkerGroup.cs
@@ -0,0 +1,293 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using NUnit.Framework;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestWorkerGroup
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            SetupAssembly.AssemblySetup();
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            SetupAssembly.AssemblyTeardown();
+        }
+
+        [Test]
+        public static void TestCoreFunctionality()
+        {
+            int threadCount = 0;
+            int maxCount = 0;
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                object threadLock = new object();
+                IThreadWorker worker1 = workerGroup.CreateWorker();
+                worker1.Work += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        lock (threadLock)
+                        {
+                            ++threadCount;
+                            if (threadCount > maxCount)
+                            {
+                                maxCount = threadCount;
+                            }
+                        }
+                        Thread.Sleep(new TimeSpan(0, 0, 0, 0, 100));
+                    };
+                worker1.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        --threadCount;
+                    };
+                worker1.Run();
+
+                IThreadWorker worker2 = workerGroup.CreateWorker();
+                worker2.Work += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        lock (threadLock)
+                        {
+                            ++threadCount;
+                            if (threadCount > maxCount)
+                            {
+                                maxCount = threadCount;
+                            }
+                        }
+                        Thread.Sleep(new TimeSpan(0, 0, 0, 0, 100));
+                    };
+                worker2.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        --threadCount;
+                    };
+                worker2.Run();
+
+                workerGroup.WaitAllAndFinish();
+                Assert.That(maxCount, Is.EqualTo(1), "There should never be more than one thread active at one time.");
+            }
+        }
+
+        [Test]
+        public static void TestInvalidOperationException()
+        {
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+
+                bool? f = null;
+                Assert.Throws<InvalidOperationException>(() => { f = worker.HasCompleted; });
+                Assert.That(!f.HasValue, "No value should be set, since an exception should have occurred.");
+                Assert.Throws<InvalidOperationException>(() => { worker.Join(); });
+                worker.Abort();
+            }
+        }
+
+        [Test]
+        public static void TestAddingSubscribersToWorkerThread()
+        {
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+                bool wasPrepared = false;
+                worker.Prepare += (object sender, ThreadWorkerEventArgs e) =>
+                    {
+                        wasPrepared = true;
+                    };
+                bool didWork = false;
+                worker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    didWork = true;
+                };
+                bool didComplete = false;
+                worker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    didComplete = true;
+                };
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+                Assert.That(wasPrepared, "The Prepare event should be raised.");
+                Assert.That(didWork, "The Work event should be raised.");
+                Assert.That(didComplete, "The Completed event should be raised.");
+            }
+        }
+
+        private static void ThreadWorkerEventHandler(object sender, ThreadWorkerEventArgs e)
+        {
+            e.Result = new FileOperationContext(String.Empty, FileOperationStatus.UnspecifiedError);
+        }
+
+        [Test]
+        public static void TestRemovingSubscribersFromWorkerThread()
+        {
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+                worker.Prepare += ThreadWorkerEventHandler;
+                worker.Work += ThreadWorkerEventHandler;
+                worker.Completing += ThreadWorkerEventHandler;
+
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+
+                Assert.That(workerGroup.FirstError.Status, Is.EqualTo(FileOperationStatus.UnspecifiedError), "The status should be set by one of the event handlers.");
+            }
+
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+                worker.Prepare += ThreadWorkerEventHandler;
+                worker.Work += ThreadWorkerEventHandler;
+                worker.Completing += ThreadWorkerEventHandler;
+
+                worker.Prepare -= ThreadWorkerEventHandler;
+                worker.Work -= ThreadWorkerEventHandler;
+                worker.Completing -= ThreadWorkerEventHandler;
+
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+
+                Assert.That(workerGroup.FirstError.Status, Is.EqualTo(FileOperationStatus.Success), "None of the event handlers should have been called, so the status should not have been set there.");
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestDoubleDispose()
+        {
+            Assert.DoesNotThrow(() =>
+                {
+                    using (WorkerGroup workerGroup = new WorkerGroup())
+                    {
+                        IThreadWorker worker = workerGroup.CreateWorker();
+                        worker.Run();
+                        workerGroup.Dispose();
+                    }
+                });
+        }
+
+        [Test]
+        public static void TestObjectDisposed()
+        {
+            WorkerGroup workerGroup = new WorkerGroup();
+            IThreadWorker worker = workerGroup.CreateWorker();
+            worker.Run();
+            workerGroup.Dispose();
+
+            worker = null;
+            Assert.Throws<ObjectDisposedException>(() => { worker = workerGroup.CreateWorker(); }, "A call to a method on a disposed object should raise ObjectDisposedException.");
+            Assert.That(worker, Is.Null, "The worker should still be null, since the previous attempt to create should fail with an exception.");
+            Assert.Throws<ObjectDisposedException>(() => { workerGroup.WaitAllAndFinish(); }, "A call to a method on a disposed object should raise ObjectDisposedException.");
+        }
+
+        [Test]
+        public static void TestDoubleFinished()
+        {
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+                Assert.Throws<InvalidOperationException>(() => { workerGroup.WaitAllAndFinish(); });
+            }
+        }
+
+        [Test]
+        public static void TestExplicitConstructor()
+        {
+            ProgressContext progress = new ProgressContext();
+            int percent = 0;
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+                {
+                    percent = e.Percent;
+                };
+            using (WorkerGroup workerGroup = new WorkerGroup(1, progress))
+            {
+                IThreadWorker worker = workerGroup.CreateWorker();
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+            }
+            Assert.That(percent, Is.EqualTo(100), "Progress at 100 percent should always be reported when the thread completes.");
+        }
+
+        [Test]
+        public static void TestProgressing()
+        {
+            using (WorkerGroup workerGroup = new WorkerGroup())
+            {
+                int percent = 0;
+                workerGroup.Progress.Progressing += (object sender, ProgressEventArgs e) =>
+                    {
+                        percent = e.Percent;
+                    };
+                IThreadWorker worker = workerGroup.CreateWorker();
+                worker.Run();
+                workerGroup.WaitAllAndFinish();
+                Assert.That(percent, Is.EqualTo(100), "Progress at 100 percent should always be reported when the thread completes.");
+            }
+        }
+
+        [Test]
+        public static void TestFinishInBackground()
+        {
+            bool didComplete = false;
+            ProgressContext progress = new ProgressContext();
+            progress.Progressing += (object sender2, ProgressEventArgs e2) =>
+            {
+                didComplete = true;
+            };
+
+            using (IThreadWorker threadWorker = Instance.Portable.ThreadWorker(progress, false))
+            {
+                threadWorker.Work += (object sender, ThreadWorkerEventArgs e) =>
+                {
+                    using (WorkerGroup workerGroup = new WorkerGroup(progress))
+                    {
+                        IThreadWorker worker = workerGroup.CreateWorker();
+                        worker.Work += (object sender2, ThreadWorkerEventArgs e2) =>
+                        {
+                            e2.Progress.NotifyLevelStart();
+                            e2.Progress.NotifyLevelFinished();
+                        };
+                        worker.Run();
+                    }
+                };
+                threadWorker.Run();
+                threadWorker.Join();
+            }
+
+            Assert.That(didComplete, "Execution should continue here, with the flag set indicating that the progress event occurred.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/TestWorkerGroupProgressContext.cs b/Axantum.AxCrypt.Core.Test/TestWorkerGroupProgressContext.cs
new file mode 100644
index 0000000..9c5e8da
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/TestWorkerGroupProgressContext.cs
@@ -0,0 +1,154 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using Moq;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Test
+{
+    [TestFixture]
+    public static class TestWorkerGroupProgressContext
+    {
+        private static Mock<IProgressContext> _progressMock;
+        private static Mock<ISingleThread> _singleThreadMock;
+
+        private static WorkerGroupProgressContext _progress;
+
+        [SetUp]
+        public static void Setup()
+        {
+            _progressMock = new Mock<IProgressContext>();
+            _singleThreadMock = new Mock<ISingleThread>();
+
+            _progress = new WorkerGroupProgressContext(_progressMock.Object, _singleThreadMock.Object);
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestAddCount()
+        {
+            _progress.AddCount(456);
+
+            _progressMock.Verify(p => p.AddCount(It.Is<long>(l => l == 456)), Times.Once);
+        }
+
+        [Test]
+        public static void TestAddTotal()
+        {
+            _progress.AddTotal(123);
+
+            _progressMock.Verify(p => p.AddTotal(It.Is<long>(l => l == 123)), Times.Once);
+        }
+
+        [Test]
+        public static void TestAllItemsConfirmed()
+        {
+            bool allConfirmed = _progress.AllItemsConfirmed;
+            _progress.AllItemsConfirmed = true;
+
+            Assert.That(allConfirmed, Is.False);
+            _progressMock.VerifyGet(p => p.AllItemsConfirmed, Times.Once);
+            _progressMock.VerifySet(p => p.AllItemsConfirmed = true, Times.Once);
+        }
+
+        [Test]
+        public static void TestCancel()
+        {
+            bool cancel = _progress.Cancel;
+            _progress.Cancel = true;
+
+            Assert.That(cancel, Is.False);
+            _progressMock.VerifyGet(p => p.Cancel, Times.Once);
+            _progressMock.VerifySet(p => p.Cancel = true, Times.Once);
+        }
+
+        [Test]
+        public static void TestEnterSingleThread()
+        {
+            _progress.EnterSingleThread();
+            _singleThreadMock.Verify(s => s.Enter(), Times.Once);
+        }
+
+        [Test]
+        public static void TestLeaveSingleThread()
+        {
+            _progress.LeaveSingleThread();
+            _singleThreadMock.Verify(s => s.Leave(), Times.Once);
+        }
+
+        [Test]
+        public static void TestNotifyLevelFinished()
+        {
+            _progress.NotifyLevelFinished();
+            _progressMock.Verify(p => p.NotifyLevelFinished(), Times.Once);
+        }
+
+        [Test]
+        public static void TestNotifyLevelStart()
+        {
+            _progress.NotifyLevelStart();
+            _progressMock.Verify(p => p.NotifyLevelStart(), Times.Once);
+        }
+
+        [Test]
+        public static void TestProgressing()
+        {
+            int percent = 0;
+            EventHandler<ProgressEventArgs> handler = (sender, e) =>
+            {
+                percent = e.Percent;
+            };
+            _progress.Progressing += handler;
+
+            _progressMock.Raise(p => p.Progressing += null, new ProgressEventArgs(13));
+
+            Assert.That(percent, Is.EqualTo(13));
+
+            _progress.Progressing -= handler;
+            _progressMock.Raise(p => p.Progressing += null, new ProgressEventArgs(26));
+
+            Assert.That(percent, Is.EqualTo(13));
+        }
+
+        [Test]
+        public static void TestRemoveCount()
+        {
+            _progress.RemoveCount(999, 777);
+
+            _progressMock.Verify(p => p.RemoveCount(It.Is<long>(l => l == 999), It.Is<long>(l => l == 777)), Times.Once);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-AES256.axx b/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-AES256.axx
new file mode 100644
index 0000000..7484543
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-AES256.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-V2AES128.axx b/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-V2AES128.axx
new file mode 100644
index 0000000..80ea9dd
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/Frankenstein-txt-V2AES128.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/david copperfield-key-'aa ae oe'-ulu-txt.axx b/Axantum.AxCrypt.Core.Test/resources/david copperfield-key-'aa ae oe'-ulu-txt.axx
new file mode 100644
index 0000000..ce3e5df
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/david copperfield-key-'aa ae oe'-ulu-txt.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/david-copperfield.txt b/Axantum.AxCrypt.Core.Test/resources/david-copperfield.txt
new file mode 100644
index 0000000..cec484c
--- /dev/null
+++ b/Axantum.AxCrypt.Core.Test/resources/david-copperfield.txt
@@ -0,0 +1,38587 @@
+The Project Gutenberg EBook of David Copperfield, by Charles Dickens
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.org
+
+
+Title: David Copperfield
+
+Author: Charles Dickens
+
+Release Date: December, 1996  [Etext #766]
+Posting Date: November 24, 2009
+
+Language: English
+
+
+*** START OF THIS PROJECT GUTENBERG EBOOK DAVID COPPERFIELD ***
+
+
+
+
+Produced by Jo Churcher
+
+
+
+
+
+DAVID COPPERFIELD
+
+
+By Charles Dickens
+
+
+
+               AFFECTIONATELY INSCRIBED TO
+               THE HON.  Mr. AND Mrs. RICHARD WATSON,
+               OF ROCKINGHAM, NORTHAMPTONSHIRE.
+
+
+CONTENTS
+
+
+     I.      I Am Born
+     II.     I Observe
+     III.    I Have a Change
+     IV.     I Fall into Disgrace
+     V.      I Am Sent Away
+     VI.     I Enlarge My Circle of Acquaintance
+     VII.    My 'First Half' at Salem House
+     VIII.   My Holidays.  Especially One Happy Afternoon
+     IX.     I Have a Memorable Birthday
+     X.      I Become Neglected, and Am Provided For
+     XI.     I Begin Life on My Own Account, and Don't Like It
+     XII.    Liking Life on My Own Account No Better, I Form a Great Resolution
+     XIII.   The Sequel of My Resolution
+     XIV.    My Aunt Makes up Her Mind About Me
+     XV.     I Make Another Beginning
+     XVI.    I Am a New Boy in More Senses Than One
+     XVII.   Somebody Turns Up
+     XVIII.  A Retrospect
+     XIX.    I Look About Me and Make a Discovery
+     XX.     Steerforth's Home
+     XXI.    Little Em'ly
+     XXII.   Some Old Scenes, and Some New People
+     XXIII.  I Corroborate Mr. Dick, and Choose a Profession
+     XXIV.   My First Dissipation
+     XXV.    Good and Bad Angels
+     XXVI.   I Fall into Captivity
+     XXVII.  Tommy Traddles
+     XXVIII. Mr. Micawber's Gauntlet
+     XXIX.   I Visit Steerforth at His Home, Again
+     XXX.    A Loss
+     XXXI.   A Greater Loss
+     XXXII.  The Beginning of a Long Journey
+     XXXIII. Blissful
+     XXXIV.  My Aunt Astonishes Me
+     XXXV.   Depression
+     XXXVI.  Enthusiasm
+     XXXVII.  A Little Cold Water
+     XXXVIII. A Dissolution of Partnership
+     XXXIX.   Wickfield and Heep
+     XL.      The Wanderer
+     XLI.     Dora's Aunts
+     XLII.    Mischief
+     XLIII.   Another Retrospect
+     XLIV.    Our Housekeeping
+     XLV.     Mr. Dick Fulfils My Aunt's Predictions
+     XLVI.    Intelligence
+     XLVII.   Martha
+     XLVIII.  Domestic
+     XLIX.    I Am Involved in Mystery
+     L.       Mr. Peggotty's Dream Comes True
+     LI.      The Beginning of a Longer Journey
+     LII.     I Assist at an Explosion
+     LIII.    Another Retrospect
+     LIV.     Mr. Micawber's Transactions
+     LV.      Tempest
+     LVI.     The New Wound, and the Old
+     LVII.    The Emigrants
+     LVIII.   Absence
+     LIX.     Return
+     LX.      Agnes
+     LXI.     I Am Shown Two Interesting Penitents
+     LXII.    A Light Shines on My Way
+     LXIII.   A Visitor
+     LXIV.    A Last Retrospect
+
+
+
+
+PREFACE TO 1850 EDITION
+
+
+I do not find it easy to get sufficiently far away from this Book, in
+the first sensations of having finished it, to refer to it with the
+composure which this formal heading would seem to require. My interest
+in it, is so recent and strong; and my mind is so divided between
+pleasure and regret--pleasure in the achievement of a long design,
+regret in the separation from many companions--that I am in danger of
+wearying the reader whom I love, with personal confidences, and private
+emotions.
+
+Besides which, all that I could say of the Story, to any purpose, I have
+endeavoured to say in it.
+
+It would concern the reader little, perhaps, to know, how sorrowfully
+the pen is laid down at the close of a two-years' imaginative task; or
+how an Author feels as if he were dismissing some portion of himself
+into the shadowy world, when a crowd of the creatures of his brain
+are going from him for ever. Yet, I have nothing else to tell; unless,
+indeed, I were to confess (which might be of less moment still) that no
+one can ever believe this Narrative, in the reading, more than I have
+believed it in the writing.
+
+Instead of looking back, therefore, I will look forward. I cannot close
+this Volume more agreeably to myself, than with a hopeful glance towards
+the time when I shall again put forth my two green leaves once a month,
+and with a faithful remembrance of the genial sun and showers that have
+fallen on these leaves of David Copperfield, and made me happy.
+
+     London, October, 1850.
+
+
+
+
+PREFACE TO THE CHARLES DICKENS EDITION
+
+
+I REMARKED in the original Preface to this Book, that I did not find it
+easy to get sufficiently far away from it, in the first sensations of
+having finished it, to refer to it with the composure which this formal
+heading would seem to require. My interest in it was so recent and
+strong, and my mind was so divided between pleasure and regret--pleasure
+in the achievement of a long design, regret in the separation from many
+companions--that I was in danger of wearying the reader with personal
+confidences and private emotions.
+
+Besides which, all that I could have said of the Story to any purpose, I
+had endeavoured to say in it.
+
+It would concern the reader little, perhaps, to know how sorrowfully the
+pen is laid down at the close of a two-years' imaginative task; or how
+an Author feels as if he were dismissing some portion of himself into
+the shadowy world, when a crowd of the creatures of his brain are going
+from him for ever. Yet, I had nothing else to tell; unless, indeed, I
+were to confess (which might be of less moment still), that no one can
+ever believe this Narrative, in the reading, more than I believed it in
+the writing.
+
+So true are these avowals at the present day, that I can now only take
+the reader into one confidence more. Of all my books, I like this the
+best. It will be easily believed that I am a fond parent to every child
+of my fancy, and that no one can ever love that family as dearly as I
+love them. But, like many fond parents, I have in my heart of hearts a
+favourite child. And his name is
+
+DAVID COPPERFIELD.
+
+     1869
+
+
+
+
+THE PERSONAL HISTORY AND EXPERIENCE OF DAVID COPPERFIELD THE YOUNGER
+
+
+
+CHAPTER 1. I AM BORN
+
+
+
+Whether I shall turn out to be the hero of my own life, or whether that
+station will be held by anybody else, these pages must show. To begin my
+life with the beginning of my life, I record that I was born (as I have
+been informed and believe) on a Friday, at twelve o'clock at night.
+It was remarked that the clock began to strike, and I began to cry,
+simultaneously.
+
+In consideration of the day and hour of my birth, it was declared by
+the nurse, and by some sage women in the neighbourhood who had taken a
+lively interest in me several months before there was any possibility
+of our becoming personally acquainted, first, that I was destined to be
+unlucky in life; and secondly, that I was privileged to see ghosts and
+spirits; both these gifts inevitably attaching, as they believed, to
+all unlucky infants of either gender, born towards the small hours on a
+Friday night.
+
+I need say nothing here, on the first head, because nothing can show
+better than my history whether that prediction was verified or falsified
+by the result. On the second branch of the question, I will only remark,
+that unless I ran through that part of my inheritance while I was still
+a baby, I have not come into it yet. But I do not at all complain of
+having been kept out of this property; and if anybody else should be in
+the present enjoyment of it, he is heartily welcome to keep it.
+
+I was born with a caul, which was advertised for sale, in the
+newspapers, at the low price of fifteen guineas. Whether sea-going
+people were short of money about that time, or were short of faith and
+preferred cork jackets, I don't know; all I know is, that there was but
+one solitary bidding, and that was from an attorney connected with the
+bill-broking business, who offered two pounds in cash, and the balance
+in sherry, but declined to be guaranteed from drowning on any higher
+bargain. Consequently the advertisement was withdrawn at a dead
+loss--for as to sherry, my poor dear mother's own sherry was in the
+market then--and ten years afterwards, the caul was put up in a raffle
+down in our part of the country, to fifty members at half-a-crown a
+head, the winner to spend five shillings. I was present myself, and I
+remember to have felt quite uncomfortable and confused, at a part of
+myself being disposed of in that way. The caul was won, I recollect, by
+an old lady with a hand-basket, who, very reluctantly, produced from it
+the stipulated five shillings, all in halfpence, and twopence halfpenny
+short--as it took an immense time and a great waste of arithmetic, to
+endeavour without any effect to prove to her. It is a fact which will
+be long remembered as remarkable down there, that she was never drowned,
+but died triumphantly in bed, at ninety-two. I have understood that it
+was, to the last, her proudest boast, that she never had been on the
+water in her life, except upon a bridge; and that over her tea (to which
+she was extremely partial) she, to the last, expressed her indignation
+at the impiety of mariners and others, who had the presumption to go
+'meandering' about the world. It was in vain to represent to her
+that some conveniences, tea perhaps included, resulted from this
+objectionable practice. She always returned, with greater emphasis and
+with an instinctive knowledge of the strength of her objection, 'Let us
+have no meandering.'
+
+Not to meander myself, at present, I will go back to my birth.
+
+I was born at Blunderstone, in Suffolk, or 'there by', as they say in
+Scotland. I was a posthumous child. My father's eyes had closed upon
+the light of this world six months, when mine opened on it. There is
+something strange to me, even now, in the reflection that he never saw
+me; and something stranger yet in the shadowy remembrance that I have
+of my first childish associations with his white grave-stone in the
+churchyard, and of the indefinable compassion I used to feel for it
+lying out alone there in the dark night, when our little parlour
+was warm and bright with fire and candle, and the doors of our house
+were--almost cruelly, it seemed to me sometimes--bolted and locked
+against it.
+
+An aunt of my father's, and consequently a great-aunt of mine, of whom
+I shall have more to relate by and by, was the principal magnate of our
+family. Miss Trotwood, or Miss Betsey, as my poor mother always called
+her, when she sufficiently overcame her dread of this formidable
+personage to mention her at all (which was seldom), had been married
+to a husband younger than herself, who was very handsome, except in the
+sense of the homely adage, 'handsome is, that handsome does'--for he
+was strongly suspected of having beaten Miss Betsey, and even of having
+once, on a disputed question of supplies, made some hasty but determined
+arrangements to throw her out of a two pair of stairs' window. These
+evidences of an incompatibility of temper induced Miss Betsey to pay him
+off, and effect a separation by mutual consent. He went to India with
+his capital, and there, according to a wild legend in our family, he was
+once seen riding on an elephant, in company with a Baboon; but I think
+it must have been a Baboo--or a Begum. Anyhow, from India tidings of his
+death reached home, within ten years. How they affected my aunt, nobody
+knew; for immediately upon the separation, she took her maiden name
+again, bought a cottage in a hamlet on the sea-coast a long way off,
+established herself there as a single woman with one servant, and
+was understood to live secluded, ever afterwards, in an inflexible
+retirement.
+
+My father had once been a favourite of hers, I believe; but she was
+mortally affronted by his marriage, on the ground that my mother was 'a
+wax doll'. She had never seen my mother, but she knew her to be not
+yet twenty. My father and Miss Betsey never met again. He was double
+my mother's age when he married, and of but a delicate constitution. He
+died a year afterwards, and, as I have said, six months before I came
+into the world.
+
+This was the state of matters, on the afternoon of, what I may be
+excused for calling, that eventful and important Friday. I can make no
+claim therefore to have known, at that time, how matters stood; or to
+have any remembrance, founded on the evidence of my own senses, of what
+follows.
+
+My mother was sitting by the fire, but poorly in health, and very low in
+spirits, looking at it through her tears, and desponding heavily about
+herself and the fatherless little stranger, who was already welcomed by
+some grosses of prophetic pins, in a drawer upstairs, to a world not at
+all excited on the subject of his arrival; my mother, I say, was sitting
+by the fire, that bright, windy March afternoon, very timid and sad, and
+very doubtful of ever coming alive out of the trial that was before her,
+when, lifting her eyes as she dried them, to the window opposite, she
+saw a strange lady coming up the garden.
+
+MY mother had a sure foreboding at the second glance, that it was
+Miss Betsey. The setting sun was glowing on the strange lady, over the
+garden-fence, and she came walking up to the door with a fell rigidity
+of figure and composure of countenance that could have belonged to
+nobody else.
+
+When she reached the house, she gave another proof of her identity.
+My father had often hinted that she seldom conducted herself like any
+ordinary Christian; and now, instead of ringing the bell, she came and
+looked in at that identical window, pressing the end of her nose against
+the glass to that extent, that my poor dear mother used to say it became
+perfectly flat and white in a moment.
+
+She gave my mother such a turn, that I have always been convinced I am
+indebted to Miss Betsey for having been born on a Friday.
+
+My mother had left her chair in her agitation, and gone behind it in
+the corner. Miss Betsey, looking round the room, slowly and inquiringly,
+began on the other side, and carried her eyes on, like a Saracen's Head
+in a Dutch clock, until they reached my mother. Then she made a frown
+and a gesture to my mother, like one who was accustomed to be obeyed, to
+come and open the door. My mother went.
+
+'Mrs. David Copperfield, I think,' said Miss Betsey; the emphasis
+referring, perhaps, to my mother's mourning weeds, and her condition.
+
+'Yes,' said my mother, faintly.
+
+'Miss Trotwood,' said the visitor. 'You have heard of her, I dare say?'
+
+My mother answered she had had that pleasure. And she had a disagreeable
+consciousness of not appearing to imply that it had been an overpowering
+pleasure.
+
+'Now you see her,' said Miss Betsey. My mother bent her head, and begged
+her to walk in.
+
+They went into the parlour my mother had come from, the fire in the best
+room on the other side of the passage not being lighted--not having
+been lighted, indeed, since my father's funeral; and when they were both
+seated, and Miss Betsey said nothing, my mother, after vainly trying to
+restrain herself, began to cry. 'Oh tut, tut, tut!' said Miss Betsey, in
+a hurry. 'Don't do that! Come, come!'
+
+My mother couldn't help it notwithstanding, so she cried until she had
+had her cry out.
+
+'Take off your cap, child,' said Miss Betsey, 'and let me see you.'
+
+MY mother was too much afraid of her to refuse compliance with this odd
+request, if she had any disposition to do so. Therefore she did as she
+was told, and did it with such nervous hands that her hair (which was
+luxuriant and beautiful) fell all about her face.
+
+'Why, bless my heart!' exclaimed Miss Betsey. 'You are a very Baby!'
+
+My mother was, no doubt, unusually youthful in appearance even for her
+years; she hung her head, as if it were her fault, poor thing, and said,
+sobbing, that indeed she was afraid she was but a childish widow, and
+would be but a childish mother if she lived. In a short pause which
+ensued, she had a fancy that she felt Miss Betsey touch her hair, and
+that with no ungentle hand; but, looking at her, in her timid hope, she
+found that lady sitting with the skirt of her dress tucked up, her hands
+folded on one knee, and her feet upon the fender, frowning at the fire.
+
+'In the name of Heaven,' said Miss Betsey, suddenly, 'why Rookery?'
+
+'Do you mean the house, ma'am?' asked my mother.
+
+'Why Rookery?' said Miss Betsey. 'Cookery would have been more to the
+purpose, if you had had any practical ideas of life, either of you.'
+
+'The name was Mr. Copperfield's choice,' returned my mother. 'When he
+bought the house, he liked to think that there were rooks about it.'
+
+The evening wind made such a disturbance just now, among some tall old
+elm-trees at the bottom of the garden, that neither my mother nor Miss
+Betsey could forbear glancing that way. As the elms bent to one another,
+like giants who were whispering secrets, and after a few seconds of such
+repose, fell into a violent flurry, tossing their wild arms about, as if
+their late confidences were really too wicked for their peace of mind,
+some weatherbeaten ragged old rooks'-nests, burdening their higher
+branches, swung like wrecks upon a stormy sea.
+
+'Where are the birds?' asked Miss Betsey.
+
+'The--?' My mother had been thinking of something else.
+
+'The rooks--what has become of them?' asked Miss Betsey.
+
+'There have not been any since we have lived here,' said my mother. 'We
+thought--Mr. Copperfield thought--it was quite a large rookery; but
+the nests were very old ones, and the birds have deserted them a long
+while.'
+
+'David Copperfield all over!' cried Miss Betsey. 'David Copperfield from
+head to foot! Calls a house a rookery when there's not a rook near it,
+and takes the birds on trust, because he sees the nests!'
+
+'Mr. Copperfield,' returned my mother, 'is dead, and if you dare to
+speak unkindly of him to me--'
+
+My poor dear mother, I suppose, had some momentary intention of
+committing an assault and battery upon my aunt, who could easily have
+settled her with one hand, even if my mother had been in far better
+training for such an encounter than she was that evening. But it passed
+with the action of rising from her chair; and she sat down again very
+meekly, and fainted.
+
+When she came to herself, or when Miss Betsey had restored her,
+whichever it was, she found the latter standing at the window. The
+twilight was by this time shading down into darkness; and dimly as they
+saw each other, they could not have done that without the aid of the
+fire.
+
+'Well?' said Miss Betsey, coming back to her chair, as if she had only
+been taking a casual look at the prospect; 'and when do you expect--'
+
+'I am all in a tremble,' faltered my mother. 'I don't know what's the
+matter. I shall die, I am sure!'
+
+'No, no, no,' said Miss Betsey. 'Have some tea.'
+
+'Oh dear me, dear me, do you think it will do me any good?' cried my
+mother in a helpless manner.
+
+'Of course it will,' said Miss Betsey. 'It's nothing but fancy. What do
+you call your girl?'
+
+'I don't know that it will be a girl, yet, ma'am,' said my mother
+innocently.
+
+'Bless the Baby!' exclaimed Miss Betsey, unconsciously quoting the
+second sentiment of the pincushion in the drawer upstairs, but
+applying it to my mother instead of me, 'I don't mean that. I mean your
+servant-girl.'
+
+'Peggotty,' said my mother.
+
+'Peggotty!' repeated Miss Betsey, with some indignation. 'Do you mean to
+say, child, that any human being has gone into a Christian church,
+and got herself named Peggotty?' 'It's her surname,' said my mother,
+faintly. 'Mr. Copperfield called her by it, because her Christian name
+was the same as mine.'
+
+'Here! Peggotty!' cried Miss Betsey, opening the parlour door. 'Tea.
+Your mistress is a little unwell. Don't dawdle.'
+
+Having issued this mandate with as much potentiality as if she had been
+a recognized authority in the house ever since it had been a house,
+and having looked out to confront the amazed Peggotty coming along the
+passage with a candle at the sound of a strange voice, Miss Betsey shut
+the door again, and sat down as before: with her feet on the fender, the
+skirt of her dress tucked up, and her hands folded on one knee.
+
+'You were speaking about its being a girl,' said Miss Betsey. 'I have no
+doubt it will be a girl. I have a presentiment that it must be a girl.
+Now child, from the moment of the birth of this girl--'
+
+'Perhaps boy,' my mother took the liberty of putting in.
+
+'I tell you I have a presentiment that it must be a girl,' returned Miss
+Betsey. 'Don't contradict. From the moment of this girl's birth, child,
+I intend to be her friend. I intend to be her godmother, and I beg
+you'll call her Betsey Trotwood Copperfield. There must be no mistakes
+in life with THIS Betsey Trotwood. There must be no trifling with HER
+affections, poor dear. She must be well brought up, and well guarded
+from reposing any foolish confidences where they are not deserved. I
+must make that MY care.'
+
+There was a twitch of Miss Betsey's head, after each of these sentences,
+as if her own old wrongs were working within her, and she repressed any
+plainer reference to them by strong constraint. So my mother suspected,
+at least, as she observed her by the low glimmer of the fire: too
+much scared by Miss Betsey, too uneasy in herself, and too subdued and
+bewildered altogether, to observe anything very clearly, or to know what
+to say.
+
+'And was David good to you, child?' asked Miss Betsey, when she had been
+silent for a little while, and these motions of her head had gradually
+ceased. 'Were you comfortable together?'
+
+'We were very happy,' said my mother. 'Mr. Copperfield was only too good
+to me.'
+
+'What, he spoilt you, I suppose?' returned Miss Betsey.
+
+'For being quite alone and dependent on myself in this rough world
+again, yes, I fear he did indeed,' sobbed my mother.
+
+'Well! Don't cry!' said Miss Betsey. 'You were not equally matched,
+child--if any two people can be equally matched--and so I asked the
+question. You were an orphan, weren't you?' 'Yes.'
+
+'And a governess?'
+
+'I was nursery-governess in a family where Mr. Copperfield came to
+visit. Mr. Copperfield was very kind to me, and took a great deal of
+notice of me, and paid me a good deal of attention, and at last proposed
+to me. And I accepted him. And so we were married,' said my mother
+simply.
+
+'Ha! Poor Baby!' mused Miss Betsey, with her frown still bent upon the
+fire. 'Do you know anything?'
+
+'I beg your pardon, ma'am,' faltered my mother.
+
+'About keeping house, for instance,' said Miss Betsey.
+
+'Not much, I fear,' returned my mother. 'Not so much as I could wish.
+But Mr. Copperfield was teaching me--'
+
+('Much he knew about it himself!') said Miss Betsey in a parenthesis.
+--'And I hope I should have improved, being very anxious to learn, and
+he very patient to teach me, if the great misfortune of his death'--my
+mother broke down again here, and could get no farther.
+
+'Well, well!' said Miss Betsey. --'I kept my housekeeping-book
+regularly, and balanced it with Mr. Copperfield every night,' cried my
+mother in another burst of distress, and breaking down again.
+
+'Well, well!' said Miss Betsey. 'Don't cry any more.' --'And I am
+sure we never had a word of difference respecting it, except when Mr.
+Copperfield objected to my threes and fives being too much like each
+other, or to my putting curly tails to my sevens and nines,' resumed my
+mother in another burst, and breaking down again.
+
+'You'll make yourself ill,' said Miss Betsey, 'and you know that will
+not be good either for you or for my god-daughter. Come! You mustn't do
+it!'
+
+This argument had some share in quieting my mother, though her
+increasing indisposition had a larger one. There was an interval of
+silence, only broken by Miss Betsey's occasionally ejaculating 'Ha!' as
+she sat with her feet upon the fender.
+
+'David had bought an annuity for himself with his money, I know,' said
+she, by and by. 'What did he do for you?'
+
+'Mr. Copperfield,' said my mother, answering with some difficulty, 'was
+so considerate and good as to secure the reversion of a part of it to
+me.'
+
+'How much?' asked Miss Betsey.
+
+'A hundred and five pounds a year,' said my mother.
+
+'He might have done worse,' said my aunt.
+
+The word was appropriate to the moment. My mother was so much worse
+that Peggotty, coming in with the teaboard and candles, and seeing at a
+glance how ill she was,--as Miss Betsey might have done sooner if there
+had been light enough,--conveyed her upstairs to her own room with all
+speed; and immediately dispatched Ham Peggotty, her nephew, who had been
+for some days past secreted in the house, unknown to my mother, as a
+special messenger in case of emergency, to fetch the nurse and doctor.
+
+Those allied powers were considerably astonished, when they arrived
+within a few minutes of each other, to find an unknown lady of
+portentous appearance, sitting before the fire, with her bonnet tied
+over her left arm, stopping her ears with jewellers' cotton. Peggotty
+knowing nothing about her, and my mother saying nothing about her,
+she was quite a mystery in the parlour; and the fact of her having a
+magazine of jewellers' cotton in her pocket, and sticking the article
+in her ears in that way, did not detract from the solemnity of her
+presence.
+
+The doctor having been upstairs and come down again, and having
+satisfied himself, I suppose, that there was a probability of this
+unknown lady and himself having to sit there, face to face, for some
+hours, laid himself out to be polite and social. He was the meekest of
+his sex, the mildest of little men. He sidled in and out of a room, to
+take up the less space. He walked as softly as the Ghost in Hamlet,
+and more slowly. He carried his head on one side, partly in modest
+depreciation of himself, partly in modest propitiation of everybody
+else. It is nothing to say that he hadn't a word to throw at a dog. He
+couldn't have thrown a word at a mad dog. He might have offered him one
+gently, or half a one, or a fragment of one; for he spoke as slowly as
+he walked; but he wouldn't have been rude to him, and he couldn't have
+been quick with him, for any earthly consideration.
+
+Mr. Chillip, looking mildly at my aunt with his head on one side, and
+making her a little bow, said, in allusion to the jewellers' cotton, as
+he softly touched his left ear:
+
+'Some local irritation, ma'am?'
+
+'What!' replied my aunt, pulling the cotton out of one ear like a cork.
+
+Mr. Chillip was so alarmed by her abruptness--as he told my mother
+afterwards--that it was a mercy he didn't lose his presence of mind. But
+he repeated sweetly:
+
+'Some local irritation, ma'am?'
+
+'Nonsense!' replied my aunt, and corked herself again, at one blow.
+
+Mr. Chillip could do nothing after this, but sit and look at her feebly,
+as she sat and looked at the fire, until he was called upstairs again.
+After some quarter of an hour's absence, he returned.
+
+'Well?' said my aunt, taking the cotton out of the ear nearest to him.
+
+'Well, ma'am,' returned Mr. Chillip, 'we are--we are progressing slowly,
+ma'am.'
+
+'Ba--a--ah!' said my aunt, with a perfect shake on the contemptuous
+interjection. And corked herself as before.
+
+Really--really--as Mr. Chillip told my mother, he was almost shocked;
+speaking in a professional point of view alone, he was almost shocked.
+But he sat and looked at her, notwithstanding, for nearly two hours,
+as she sat looking at the fire, until he was again called out. After
+another absence, he again returned.
+
+'Well?' said my aunt, taking out the cotton on that side again.
+
+'Well, ma'am,' returned Mr. Chillip, 'we are--we are progressing slowly,
+ma'am.'
+
+'Ya--a--ah!' said my aunt. With such a snarl at him, that Mr. Chillip
+absolutely could not bear it. It was really calculated to break his
+spirit, he said afterwards. He preferred to go and sit upon the stairs,
+in the dark and a strong draught, until he was again sent for.
+
+Ham Peggotty, who went to the national school, and was a very dragon at
+his catechism, and who may therefore be regarded as a credible witness,
+reported next day, that happening to peep in at the parlour-door an hour
+after this, he was instantly descried by Miss Betsey, then walking to
+and fro in a state of agitation, and pounced upon before he could make
+his escape. That there were now occasional sounds of feet and voices
+overhead which he inferred the cotton did not exclude, from the
+circumstance of his evidently being clutched by the lady as a victim on
+whom to expend her superabundant agitation when the sounds were loudest.
+That, marching him constantly up and down by the collar (as if he had
+been taking too much laudanum), she, at those times, shook him, rumpled
+his hair, made light of his linen, stopped his ears as if she confounded
+them with her own, and otherwise tousled and maltreated him. This was
+in part confirmed by his aunt, who saw him at half past twelve o'clock,
+soon after his release, and affirmed that he was then as red as I was.
+
+The mild Mr. Chillip could not possibly bear malice at such a time, if
+at any time. He sidled into the parlour as soon as he was at liberty,
+and said to my aunt in his meekest manner:
+
+'Well, ma'am, I am happy to congratulate you.'
+
+'What upon?' said my aunt, sharply.
+
+Mr. Chillip was fluttered again, by the extreme severity of my aunt's
+manner; so he made her a little bow and gave her a little smile, to
+mollify her.
+
+'Mercy on the man, what's he doing!' cried my aunt, impatiently. 'Can't
+he speak?'
+
+'Be calm, my dear ma'am,' said Mr. Chillip, in his softest accents.
+
+'There is no longer any occasion for uneasiness, ma'am. Be calm.'
+
+It has since been considered almost a miracle that my aunt didn't shake
+him, and shake what he had to say, out of him. She only shook her own
+head at him, but in a way that made him quail.
+
+'Well, ma'am,' resumed Mr. Chillip, as soon as he had courage, 'I am
+happy to congratulate you. All is now over, ma'am, and well over.'
+
+During the five minutes or so that Mr. Chillip devoted to the delivery
+of this oration, my aunt eyed him narrowly.
+
+'How is she?' said my aunt, folding her arms with her bonnet still tied
+on one of them.
+
+'Well, ma'am, she will soon be quite comfortable, I hope,' returned Mr.
+Chillip. 'Quite as comfortable as we can expect a young mother to be,
+under these melancholy domestic circumstances. There cannot be any
+objection to your seeing her presently, ma'am. It may do her good.'
+
+'And SHE. How is SHE?' said my aunt, sharply.
+
+Mr. Chillip laid his head a little more on one side, and looked at my
+aunt like an amiable bird.
+
+'The baby,' said my aunt. 'How is she?'
+
+'Ma'am,' returned Mr. Chillip, 'I apprehended you had known. It's a
+boy.'
+
+My aunt said never a word, but took her bonnet by the strings, in the
+manner of a sling, aimed a blow at Mr. Chillip's head with it, put it on
+bent, walked out, and never came back. She vanished like a discontented
+fairy; or like one of those supernatural beings, whom it was popularly
+supposed I was entitled to see; and never came back any more.
+
+No. I lay in my basket, and my mother lay in her bed; but Betsey
+Trotwood Copperfield was for ever in the land of dreams and shadows, the
+tremendous region whence I had so lately travelled; and the light upon
+the window of our room shone out upon the earthly bourne of all such
+travellers, and the mound above the ashes and the dust that once was he,
+without whom I had never been.
+
+
+
+CHAPTER 2. I OBSERVE
+
+
+The first objects that assume a distinct presence before me, as I look
+far back, into the blank of my infancy, are my mother with her pretty
+hair and youthful shape, and Peggotty with no shape at all, and eyes so
+dark that they seemed to darken their whole neighbourhood in her face,
+and cheeks and arms so hard and red that I wondered the birds didn't
+peck her in preference to apples.
+
+I believe I can remember these two at a little distance apart, dwarfed
+to my sight by stooping down or kneeling on the floor, and I going
+unsteadily from the one to the other. I have an impression on my mind
+which I cannot distinguish from actual remembrance, of the touch of
+Peggotty's forefinger as she used to hold it out to me, and of its being
+roughened by needlework, like a pocket nutmeg-grater.
+
+This may be fancy, though I think the memory of most of us can go
+farther back into such times than many of us suppose; just as I believe
+the power of observation in numbers of very young children to be quite
+wonderful for its closeness and accuracy. Indeed, I think that most
+grown men who are remarkable in this respect, may with greater propriety
+be said not to have lost the faculty, than to have acquired it; the
+rather, as I generally observe such men to retain a certain freshness,
+and gentleness, and capacity of being pleased, which are also an
+inheritance they have preserved from their childhood.
+
+I might have a misgiving that I am 'meandering' in stopping to say this,
+but that it brings me to remark that I build these conclusions, in part
+upon my own experience of myself; and if it should appear from
+anything I may set down in this narrative that I was a child of close
+observation, or that as a man I have a strong memory of my childhood, I
+undoubtedly lay claim to both of these characteristics.
+
+Looking back, as I was saying, into the blank of my infancy, the first
+objects I can remember as standing out by themselves from a confusion of
+things, are my mother and Peggotty. What else do I remember? Let me see.
+
+
+There comes out of the cloud, our house--not new to me, but quite
+familiar, in its earliest remembrance. On the ground-floor is Peggotty's
+kitchen, opening into a back yard; with a pigeon-house on a pole, in
+the centre, without any pigeons in it; a great dog-kennel in a corner,
+without any dog; and a quantity of fowls that look terribly tall to me,
+walking about, in a menacing and ferocious manner. There is one cock who
+gets upon a post to crow, and seems to take particular notice of me as
+I look at him through the kitchen window, who makes me shiver, he is so
+fierce. Of the geese outside the side-gate who come waddling after
+me with their long necks stretched out when I go that way, I dream at
+night: as a man environed by wild beasts might dream of lions.
+
+Here is a long passage--what an enormous perspective I make of
+it!--leading from Peggotty's kitchen to the front door. A dark
+store-room opens out of it, and that is a place to be run past at
+night; for I don't know what may be among those tubs and jars and old
+tea-chests, when there is nobody in there with a dimly-burning light,
+letting a mouldy air come out of the door, in which there is the smell
+of soap, pickles, pepper, candles, and coffee, all at one whiff. Then
+there are the two parlours: the parlour in which we sit of an evening,
+my mother and I and Peggotty--for Peggotty is quite our companion, when
+her work is done and we are alone--and the best parlour where we sit
+on a Sunday; grandly, but not so comfortably. There is something of a
+doleful air about that room to me, for Peggotty has told me--I don't
+know when, but apparently ages ago--about my father's funeral, and the
+company having their black cloaks put on. One Sunday night my mother
+reads to Peggotty and me in there, how Lazarus was raised up from the
+dead. And I am so frightened that they are afterwards obliged to take me
+out of bed, and show me the quiet churchyard out of the bedroom window,
+with the dead all lying in their graves at rest, below the solemn moon.
+
+There is nothing half so green that I know anywhere, as the grass of
+that churchyard; nothing half so shady as its trees; nothing half so
+quiet as its tombstones. The sheep are feeding there, when I kneel up,
+early in the morning, in my little bed in a closet within my mother's
+room, to look out at it; and I see the red light shining on the
+sun-dial, and think within myself, 'Is the sun-dial glad, I wonder, that
+it can tell the time again?'
+
+Here is our pew in the church. What a high-backed pew! With a window
+near it, out of which our house can be seen, and IS seen many times
+during the morning's service, by Peggotty, who likes to make herself
+as sure as she can that it's not being robbed, or is not in flames. But
+though Peggotty's eye wanders, she is much offended if mine does,
+and frowns to me, as I stand upon the seat, that I am to look at the
+clergyman. But I can't always look at him--I know him without that white
+thing on, and I am afraid of his wondering why I stare so, and perhaps
+stopping the service to inquire--and what am I to do? It's a dreadful
+thing to gape, but I must do something. I look at my mother, but she
+pretends not to see me. I look at a boy in the aisle, and he makes faces
+at me. I look at the sunlight coming in at the open door through
+the porch, and there I see a stray sheep--I don't mean a sinner, but
+mutton--half making up his mind to come into the church. I feel that
+if I looked at him any longer, I might be tempted to say something out
+loud; and what would become of me then! I look up at the monumental
+tablets on the wall, and try to think of Mr. Bodgers late of this
+parish, and what the feelings of Mrs. Bodgers must have been, when
+affliction sore, long time Mr. Bodgers bore, and physicians were in
+vain. I wonder whether they called in Mr. Chillip, and he was in vain;
+and if so, how he likes to be reminded of it once a week. I look from
+Mr. Chillip, in his Sunday neckcloth, to the pulpit; and think what a
+good place it would be to play in, and what a castle it would make, with
+another boy coming up the stairs to attack it, and having the velvet
+cushion with the tassels thrown down on his head. In time my eyes
+gradually shut up; and, from seeming to hear the clergyman singing a
+drowsy song in the heat, I hear nothing, until I fall off the seat with
+a crash, and am taken out, more dead than alive, by Peggotty.
+
+And now I see the outside of our house, with the latticed
+bedroom-windows standing open to let in the sweet-smelling air, and the
+ragged old rooks'-nests still dangling in the elm-trees at the bottom
+of the front garden. Now I am in the garden at the back, beyond the
+yard where the empty pigeon-house and dog-kennel are--a very preserve
+of butterflies, as I remember it, with a high fence, and a gate and
+padlock; where the fruit clusters on the trees, riper and richer than
+fruit has ever been since, in any other garden, and where my
+mother gathers some in a basket, while I stand by, bolting furtive
+gooseberries, and trying to look unmoved. A great wind rises, and the
+summer is gone in a moment. We are playing in the winter twilight,
+dancing about the parlour. When my mother is out of breath and rests
+herself in an elbow-chair, I watch her winding her bright curls round
+her fingers, and straitening her waist, and nobody knows better than I
+do that she likes to look so well, and is proud of being so pretty.
+
+That is among my very earliest impressions. That, and a sense that we
+were both a little afraid of Peggotty, and submitted ourselves in most
+things to her direction, were among the first opinions--if they may be
+so called--that I ever derived from what I saw.
+
+Peggotty and I were sitting one night by the parlour fire, alone. I
+had been reading to Peggotty about crocodiles. I must have read very
+perspicuously, or the poor soul must have been deeply interested, for I
+remember she had a cloudy impression, after I had done, that they were
+a sort of vegetable. I was tired of reading, and dead sleepy; but
+having leave, as a high treat, to sit up until my mother came home from
+spending the evening at a neighbour's, I would rather have died upon
+my post (of course) than have gone to bed. I had reached that stage of
+sleepiness when Peggotty seemed to swell and grow immensely large.
+I propped my eyelids open with my two forefingers, and looked
+perseveringly at her as she sat at work; at the little bit of wax-candle
+she kept for her thread--how old it looked, being so wrinkled in
+all directions!--at the little house with a thatched roof, where the
+yard-measure lived; at her work-box with a sliding lid, with a view of
+St. Paul's Cathedral (with a pink dome) painted on the top; at the brass
+thimble on her finger; at herself, whom I thought lovely. I felt so
+sleepy, that I knew if I lost sight of anything for a moment, I was
+gone.
+
+'Peggotty,' says I, suddenly, 'were you ever married?'
+
+'Lord, Master Davy,' replied Peggotty. 'What's put marriage in your
+head?'
+
+She answered with such a start, that it quite awoke me. And then she
+stopped in her work, and looked at me, with her needle drawn out to its
+thread's length.
+
+'But WERE you ever married, Peggotty?' says I. 'You are a very handsome
+woman, an't you?'
+
+I thought her in a different style from my mother, certainly; but of
+another school of beauty, I considered her a perfect example. There
+was a red velvet footstool in the best parlour, on which my mother
+had painted a nosegay. The ground-work of that stool, and Peggotty's
+complexion appeared to me to be one and the same thing. The stool was
+smooth, and Peggotty was rough, but that made no difference.
+
+'Me handsome, Davy!' said Peggotty. 'Lawk, no, my dear! But what put
+marriage in your head?'
+
+'I don't know!--You mustn't marry more than one person at a time, may
+you, Peggotty?'
+
+'Certainly not,' says Peggotty, with the promptest decision.
+
+'But if you marry a person, and the person dies, why then you may marry
+another person, mayn't you, Peggotty?'
+
+'YOU MAY,' says Peggotty, 'if you choose, my dear. That's a matter of
+opinion.'
+
+'But what is your opinion, Peggotty?' said I.
+
+I asked her, and looked curiously at her, because she looked so
+curiously at me.
+
+'My opinion is,' said Peggotty, taking her eyes from me, after a little
+indecision and going on with her work, 'that I never was married myself,
+Master Davy, and that I don't expect to be. That's all I know about the
+subject.'
+
+'You an't cross, I suppose, Peggotty, are you?' said I, after sitting
+quiet for a minute.
+
+I really thought she was, she had been so short with me; but I was quite
+mistaken: for she laid aside her work (which was a stocking of her own),
+and opening her arms wide, took my curly head within them, and gave it
+a good squeeze. I know it was a good squeeze, because, being very plump,
+whenever she made any little exertion after she was dressed, some of the
+buttons on the back of her gown flew off. And I recollect two bursting
+to the opposite side of the parlour, while she was hugging me.
+
+'Now let me hear some more about the Crorkindills,' said Peggotty, who
+was not quite right in the name yet, 'for I an't heard half enough.'
+
+I couldn't quite understand why Peggotty looked so queer, or why she
+was so ready to go back to the crocodiles. However, we returned to those
+monsters, with fresh wakefulness on my part, and we left their eggs in
+the sand for the sun to hatch; and we ran away from them, and baffled
+them by constantly turning, which they were unable to do quickly, on
+account of their unwieldy make; and we went into the water after them,
+as natives, and put sharp pieces of timber down their throats; and in
+short we ran the whole crocodile gauntlet. I did, at least; but I had
+my doubts of Peggotty, who was thoughtfully sticking her needle into
+various parts of her face and arms, all the time.
+
+We had exhausted the crocodiles, and begun with the alligators, when
+the garden-bell rang. We went out to the door; and there was my mother,
+looking unusually pretty, I thought, and with her a gentleman with
+beautiful black hair and whiskers, who had walked home with us from
+church last Sunday.
+
+As my mother stooped down on the threshold to take me in her arms and
+kiss me, the gentleman said I was a more highly privileged little fellow
+than a monarch--or something like that; for my later understanding
+comes, I am sensible, to my aid here.
+
+'What does that mean?' I asked him, over her shoulder.
+
+He patted me on the head; but somehow, I didn't like him or his deep
+voice, and I was jealous that his hand should touch my mother's in
+touching me--which it did. I put it away, as well as I could.
+
+'Oh, Davy!' remonstrated my mother.
+
+'Dear boy!' said the gentleman. 'I cannot wonder at his devotion!'
+
+I never saw such a beautiful colour on my mother's face before. She
+gently chid me for being rude; and, keeping me close to her shawl,
+turned to thank the gentleman for taking so much trouble as to bring her
+home. She put out her hand to him as she spoke, and, as he met it with
+his own, she glanced, I thought, at me.
+
+'Let us say "good night", my fine boy,' said the gentleman, when he had
+bent his head--I saw him!--over my mother's little glove.
+
+'Good night!' said I.
+
+'Come! Let us be the best friends in the world!' said the gentleman,
+laughing. 'Shake hands!'
+
+My right hand was in my mother's left, so I gave him the other.
+
+'Why, that's the Wrong hand, Davy!' laughed the gentleman.
+
+MY mother drew my right hand forward, but I was resolved, for my former
+reason, not to give it him, and I did not. I gave him the other, and he
+shook it heartily, and said I was a brave fellow, and went away.
+
+At this minute I see him turn round in the garden, and give us a last
+look with his ill-omened black eyes, before the door was shut.
+
+Peggotty, who had not said a word or moved a finger, secured the
+fastenings instantly, and we all went into the parlour. My mother,
+contrary to her usual habit, instead of coming to the elbow-chair by the
+fire, remained at the other end of the room, and sat singing to herself.
+--'Hope you have had a pleasant evening, ma'am,' said Peggotty, standing
+as stiff as a barrel in the centre of the room, with a candlestick in
+her hand.
+
+'Much obliged to you, Peggotty,' returned my mother, in a cheerful
+voice, 'I have had a VERY pleasant evening.'
+
+'A stranger or so makes an agreeable change,' suggested Peggotty.
+
+'A very agreeable change, indeed,' returned my mother.
+
+Peggotty continuing to stand motionless in the middle of the room, and
+my mother resuming her singing, I fell asleep, though I was not so sound
+asleep but that I could hear voices, without hearing what they said.
+When I half awoke from this uncomfortable doze, I found Peggotty and my
+mother both in tears, and both talking.
+
+'Not such a one as this, Mr. Copperfield wouldn't have liked,' said
+Peggotty. 'That I say, and that I swear!'
+
+'Good Heavens!' cried my mother, 'you'll drive me mad! Was ever any
+poor girl so ill-used by her servants as I am! Why do I do myself
+the injustice of calling myself a girl? Have I never been married,
+Peggotty?'
+
+'God knows you have, ma'am,' returned Peggotty. 'Then, how can you
+dare,' said my mother--'you know I don't mean how can you dare,
+Peggotty, but how can you have the heart--to make me so uncomfortable
+and say such bitter things to me, when you are well aware that I
+haven't, out of this place, a single friend to turn to?'
+
+'The more's the reason,' returned Peggotty, 'for saying that it won't
+do. No! That it won't do. No! No price could make it do. No!'--I thought
+Peggotty would have thrown the candlestick away, she was so emphatic
+with it.
+
+'How can you be so aggravating,' said my mother, shedding more tears
+than before, 'as to talk in such an unjust manner! How can you go on as
+if it was all settled and arranged, Peggotty, when I tell you over
+and over again, you cruel thing, that beyond the commonest civilities
+nothing has passed! You talk of admiration. What am I to do? If people
+are so silly as to indulge the sentiment, is it my fault? What am I to
+do, I ask you? Would you wish me to shave my head and black my face, or
+disfigure myself with a burn, or a scald, or something of that sort? I
+dare say you would, Peggotty. I dare say you'd quite enjoy it.'
+
+Peggotty seemed to take this aspersion very much to heart, I thought.
+
+'And my dear boy,' cried my mother, coming to the elbow-chair in which
+I was, and caressing me, 'my own little Davy! Is it to be hinted to me
+that I am wanting in affection for my precious treasure, the dearest
+little fellow that ever was!'
+
+'Nobody never went and hinted no such a thing,' said Peggotty.
+
+'You did, Peggotty!' returned my mother. 'You know you did. What else
+was it possible to infer from what you said, you unkind creature,
+when you know as well as I do, that on his account only last quarter I
+wouldn't buy myself a new parasol, though that old green one is frayed
+the whole way up, and the fringe is perfectly mangy? You know it is,
+Peggotty. You can't deny it.' Then, turning affectionately to me, with
+her cheek against mine, 'Am I a naughty mama to you, Davy? Am I a nasty,
+cruel, selfish, bad mama? Say I am, my child; say "yes", dear boy, and
+Peggotty will love you; and Peggotty's love is a great deal better than
+mine, Davy. I don't love you at all, do I?'
+
+At this, we all fell a-crying together. I think I was the loudest of
+the party, but I am sure we were all sincere about it. I was quite
+heart-broken myself, and am afraid that in the first transports of
+wounded tenderness I called Peggotty a 'Beast'. That honest creature was
+in deep affliction, I remember, and must have become quite buttonless
+on the occasion; for a little volley of those explosives went off,
+when, after having made it up with my mother, she kneeled down by the
+elbow-chair, and made it up with me.
+
+We went to bed greatly dejected. My sobs kept waking me, for a long
+time; and when one very strong sob quite hoisted me up in bed, I found
+my mother sitting on the coverlet, and leaning over me. I fell asleep in
+her arms, after that, and slept soundly.
+
+Whether it was the following Sunday when I saw the gentleman again,
+or whether there was any greater lapse of time before he reappeared,
+I cannot recall. I don't profess to be clear about dates. But there he
+was, in church, and he walked home with us afterwards. He came in, too,
+to look at a famous geranium we had, in the parlour-window. It did not
+appear to me that he took much notice of it, but before he went he asked
+my mother to give him a bit of the blossom. She begged him to choose it
+for himself, but he refused to do that--I could not understand why--so
+she plucked it for him, and gave it into his hand. He said he would
+never, never part with it any more; and I thought he must be quite a
+fool not to know that it would fall to pieces in a day or two.
+
+Peggotty began to be less with us, of an evening, than she had always
+been. My mother deferred to her very much--more than usual, it occurred
+to me--and we were all three excellent friends; still we were different
+from what we used to be, and were not so comfortable among ourselves.
+Sometimes I fancied that Peggotty perhaps objected to my mother's
+wearing all the pretty dresses she had in her drawers, or to her
+going so often to visit at that neighbour's; but I couldn't, to my
+satisfaction, make out how it was.
+
+Gradually, I became used to seeing the gentleman with the black
+whiskers. I liked him no better than at first, and had the same uneasy
+jealousy of him; but if I had any reason for it beyond a child's
+instinctive dislike, and a general idea that Peggotty and I could make
+much of my mother without any help, it certainly was not THE reason that
+I might have found if I had been older. No such thing came into my mind,
+or near it. I could observe, in little pieces, as it were; but as to
+making a net of a number of these pieces, and catching anybody in it,
+that was, as yet, beyond me.
+
+One autumn morning I was with my mother in the front garden, when Mr.
+Murdstone--I knew him by that name now--came by, on horseback. He reined
+up his horse to salute my mother, and said he was going to Lowestoft to
+see some friends who were there with a yacht, and merrily proposed to
+take me on the saddle before him if I would like the ride.
+
+The air was so clear and pleasant, and the horse seemed to like the
+idea of the ride so much himself, as he stood snorting and pawing at the
+garden-gate, that I had a great desire to go. So I was sent upstairs
+to Peggotty to be made spruce; and in the meantime Mr. Murdstone
+dismounted, and, with his horse's bridle drawn over his arm, walked
+slowly up and down on the outer side of the sweetbriar fence, while my
+mother walked slowly up and down on the inner to keep him company. I
+recollect Peggotty and I peeping out at them from my little window; I
+recollect how closely they seemed to be examining the sweetbriar between
+them, as they strolled along; and how, from being in a perfectly angelic
+temper, Peggotty turned cross in a moment, and brushed my hair the wrong
+way, excessively hard.
+
+Mr. Murdstone and I were soon off, and trotting along on the green turf
+by the side of the road. He held me quite easily with one arm, and I
+don't think I was restless usually; but I could not make up my mind to
+sit in front of him without turning my head sometimes, and looking up in
+his face. He had that kind of shallow black eye--I want a better word to
+express an eye that has no depth in it to be looked into--which, when
+it is abstracted, seems from some peculiarity of light to be disfigured,
+for a moment at a time, by a cast. Several times when I glanced at him,
+I observed that appearance with a sort of awe, and wondered what he
+was thinking about so closely. His hair and whiskers were blacker and
+thicker, looked at so near, than even I had given them credit for being.
+A squareness about the lower part of his face, and the dotted indication
+of the strong black beard he shaved close every day, reminded me of
+the wax-work that had travelled into our neighbourhood some half-a-year
+before. This, his regular eyebrows, and the rich white, and black, and
+brown, of his complexion--confound his complexion, and his memory!--made
+me think him, in spite of my misgivings, a very handsome man. I have no
+doubt that my poor dear mother thought him so too.
+
+We went to an hotel by the sea, where two gentlemen were smoking cigars
+in a room by themselves. Each of them was lying on at least four chairs,
+and had a large rough jacket on. In a corner was a heap of coats and
+boat-cloaks, and a flag, all bundled up together.
+
+They both rolled on to their feet in an untidy sort of manner, when we
+came in, and said, 'Halloa, Murdstone! We thought you were dead!'
+
+'Not yet,' said Mr. Murdstone.
+
+'And who's this shaver?' said one of the gentlemen, taking hold of me.
+
+'That's Davy,' returned Mr. Murdstone.
+
+'Davy who?' said the gentleman. 'Jones?'
+
+'Copperfield,' said Mr. Murdstone.
+
+'What! Bewitching Mrs. Copperfield's encumbrance?' cried the gentleman.
+'The pretty little widow?'
+
+'Quinion,' said Mr. Murdstone, 'take care, if you please. Somebody's
+sharp.'
+
+'Who is?' asked the gentleman, laughing. I looked up, quickly; being
+curious to know.
+
+'Only Brooks of Sheffield,' said Mr. Murdstone.
+
+I was quite relieved to find that it was only Brooks of Sheffield; for,
+at first, I really thought it was I.
+
+There seemed to be something very comical in the reputation of Mr.
+Brooks of Sheffield, for both the gentlemen laughed heartily when he
+was mentioned, and Mr. Murdstone was a good deal amused also. After some
+laughing, the gentleman whom he had called Quinion, said:
+
+'And what is the opinion of Brooks of Sheffield, in reference to the
+projected business?'
+
+'Why, I don't know that Brooks understands much about it at present,'
+replied Mr. Murdstone; 'but he is not generally favourable, I believe.'
+
+There was more laughter at this, and Mr. Quinion said he would ring the
+bell for some sherry in which to drink to Brooks. This he did; and when
+the wine came, he made me have a little, with a biscuit, and, before
+I drank it, stand up and say, 'Confusion to Brooks of Sheffield!' The
+toast was received with great applause, and such hearty laughter that
+it made me laugh too; at which they laughed the more. In short, we quite
+enjoyed ourselves.
+
+We walked about on the cliff after that, and sat on the grass, and
+looked at things through a telescope--I could make out nothing myself
+when it was put to my eye, but I pretended I could--and then we came
+back to the hotel to an early dinner. All the time we were out, the two
+gentlemen smoked incessantly--which, I thought, if I might judge from
+the smell of their rough coats, they must have been doing, ever since
+the coats had first come home from the tailor's. I must not forget that
+we went on board the yacht, where they all three descended into the
+cabin, and were busy with some papers. I saw them quite hard at work,
+when I looked down through the open skylight. They left me, during this
+time, with a very nice man with a very large head of red hair and a very
+small shiny hat upon it, who had got a cross-barred shirt or waistcoat
+on, with 'Skylark' in capital letters across the chest. I thought it was
+his name; and that as he lived on board ship and hadn't a street door
+to put his name on, he put it there instead; but when I called him Mr.
+Skylark, he said it meant the vessel.
+
+I observed all day that Mr. Murdstone was graver and steadier than the
+two gentlemen. They were very gay and careless. They joked freely with
+one another, but seldom with him. It appeared to me that he was
+more clever and cold than they were, and that they regarded him with
+something of my own feeling. I remarked that, once or twice when Mr.
+Quinion was talking, he looked at Mr. Murdstone sideways, as if to make
+sure of his not being displeased; and that once when Mr. Passnidge (the
+other gentleman) was in high spirits, he trod upon his foot, and gave
+him a secret caution with his eyes, to observe Mr. Murdstone, who was
+sitting stern and silent. Nor do I recollect that Mr. Murdstone laughed
+at all that day, except at the Sheffield joke--and that, by the by, was
+his own.
+
+We went home early in the evening. It was a very fine evening, and my
+mother and he had another stroll by the sweetbriar, while I was sent in
+to get my tea. When he was gone, my mother asked me all about the day I
+had had, and what they had said and done. I mentioned what they had said
+about her, and she laughed, and told me they were impudent fellows who
+talked nonsense--but I knew it pleased her. I knew it quite as well as
+I know it now. I took the opportunity of asking if she was at all
+acquainted with Mr. Brooks of Sheffield, but she answered No, only she
+supposed he must be a manufacturer in the knife and fork way.
+
+Can I say of her face--altered as I have reason to remember it, perished
+as I know it is--that it is gone, when here it comes before me at this
+instant, as distinct as any face that I may choose to look on in a
+crowded street? Can I say of her innocent and girlish beauty, that it
+faded, and was no more, when its breath falls on my cheek now, as it
+fell that night? Can I say she ever changed, when my remembrance brings
+her back to life, thus only; and, truer to its loving youth than I have
+been, or man ever is, still holds fast what it cherished then?
+
+I write of her just as she was when I had gone to bed after this talk,
+and she came to bid me good night. She kneeled down playfully by the
+side of the bed, and laying her chin upon her hands, and laughing, said:
+
+'What was it they said, Davy? Tell me again. I can't believe it.'
+
+'"Bewitching--"' I began.
+
+My mother put her hands upon my lips to stop me.
+
+'It was never bewitching,' she said, laughing. 'It never could have been
+bewitching, Davy. Now I know it wasn't!'
+
+'Yes, it was. "Bewitching Mrs. Copperfield",' I repeated stoutly. 'And,
+"pretty."'
+
+'No, no, it was never pretty. Not pretty,' interposed my mother, laying
+her fingers on my lips again.
+
+'Yes it was. "Pretty little widow."'
+
+'What foolish, impudent creatures!' cried my mother, laughing and
+covering her face. 'What ridiculous men! An't they? Davy dear--'
+
+'Well, Ma.'
+
+'Don't tell Peggotty; she might be angry with them. I am dreadfully
+angry with them myself; but I would rather Peggotty didn't know.'
+
+I promised, of course; and we kissed one another over and over again,
+and I soon fell fast asleep.
+
+It seems to me, at this distance of time, as if it were the next day
+when Peggotty broached the striking and adventurous proposition I am
+about to mention; but it was probably about two months afterwards.
+
+We were sitting as before, one evening (when my mother was out as
+before), in company with the stocking and the yard-measure, and the bit
+of wax, and the box with St. Paul's on the lid, and the crocodile book,
+when Peggotty, after looking at me several times, and opening her mouth
+as if she were going to speak, without doing it--which I thought was
+merely gaping, or I should have been rather alarmed--said coaxingly:
+
+'Master Davy, how should you like to go along with me and spend a
+fortnight at my brother's at Yarmouth? Wouldn't that be a treat?'
+
+'Is your brother an agreeable man, Peggotty?' I inquired, provisionally.
+
+'Oh, what an agreeable man he is!' cried Peggotty, holding up her hands.
+'Then there's the sea; and the boats and ships; and the fishermen; and
+the beach; and Am to play with--'
+
+Peggotty meant her nephew Ham, mentioned in my first chapter; but she
+spoke of him as a morsel of English Grammar.
+
+I was flushed by her summary of delights, and replied that it would
+indeed be a treat, but what would my mother say?
+
+'Why then I'll as good as bet a guinea,' said Peggotty, intent upon my
+face, 'that she'll let us go. I'll ask her, if you like, as soon as ever
+she comes home. There now!'
+
+'But what's she to do while we're away?' said I, putting my small elbows
+on the table to argue the point. 'She can't live by herself.'
+
+If Peggotty were looking for a hole, all of a sudden, in the heel of
+that stocking, it must have been a very little one indeed, and not worth
+darning.
+
+'I say! Peggotty! She can't live by herself, you know.'
+
+'Oh, bless you!' said Peggotty, looking at me again at last. 'Don't
+you know? She's going to stay for a fortnight with Mrs. Grayper. Mrs.
+Grayper's going to have a lot of company.'
+
+Oh! If that was it, I was quite ready to go. I waited, in the utmost
+impatience, until my mother came home from Mrs. Grayper's (for it was
+that identical neighbour), to ascertain if we could get leave to carry
+out this great idea. Without being nearly so much surprised as I had
+expected, my mother entered into it readily; and it was all arranged
+that night, and my board and lodging during the visit were to be paid
+for.
+
+The day soon came for our going. It was such an early day that it came
+soon, even to me, who was in a fever of expectation, and half afraid
+that an earthquake or a fiery mountain, or some other great convulsion
+of nature, might interpose to stop the expedition. We were to go in a
+carrier's cart, which departed in the morning after breakfast. I would
+have given any money to have been allowed to wrap myself up over-night,
+and sleep in my hat and boots.
+
+It touches me nearly now, although I tell it lightly, to recollect how
+eager I was to leave my happy home; to think how little I suspected what
+I did leave for ever.
+
+I am glad to recollect that when the carrier's cart was at the gate, and
+my mother stood there kissing me, a grateful fondness for her and for
+the old place I had never turned my back upon before, made me cry. I am
+glad to know that my mother cried too, and that I felt her heart beat
+against mine.
+
+I am glad to recollect that when the carrier began to move, my mother
+ran out at the gate, and called to him to stop, that she might kiss me
+once more. I am glad to dwell upon the earnestness and love with which
+she lifted up her face to mine, and did so.
+
+As we left her standing in the road, Mr. Murdstone came up to where
+she was, and seemed to expostulate with her for being so moved. I was
+looking back round the awning of the cart, and wondered what business
+it was of his. Peggotty, who was also looking back on the other side,
+seemed anything but satisfied; as the face she brought back in the cart
+denoted.
+
+I sat looking at Peggotty for some time, in a reverie on this
+supposititious case: whether, if she were employed to lose me like the
+boy in the fairy tale, I should be able to track my way home again by
+the buttons she would shed.
+
+
+
+CHAPTER 3. I HAVE A CHANGE
+
+
+The carrier's horse was the laziest horse in the world, I should hope,
+and shuffled along, with his head down, as if he liked to keep people
+waiting to whom the packages were directed. I fancied, indeed, that he
+sometimes chuckled audibly over this reflection, but the carrier said
+he was only troubled with a cough. The carrier had a way of keeping his
+head down, like his horse, and of drooping sleepily forward as he drove,
+with one of his arms on each of his knees. I say 'drove', but it struck
+me that the cart would have gone to Yarmouth quite as well without him,
+for the horse did all that; and as to conversation, he had no idea of it
+but whistling.
+
+Peggotty had a basket of refreshments on her knee, which would have
+lasted us out handsomely, if we had been going to London by the same
+conveyance. We ate a good deal, and slept a good deal. Peggotty always
+went to sleep with her chin upon the handle of the basket, her hold of
+which never relaxed; and I could not have believed unless I had heard
+her do it, that one defenceless woman could have snored so much.
+
+We made so many deviations up and down lanes, and were such a long time
+delivering a bedstead at a public-house, and calling at other places,
+that I was quite tired, and very glad, when we saw Yarmouth. It looked
+rather spongy and soppy, I thought, as I carried my eye over the great
+dull waste that lay across the river; and I could not help wondering, if
+the world were really as round as my geography book said, how any
+part of it came to be so flat. But I reflected that Yarmouth might be
+situated at one of the poles; which would account for it.
+
+As we drew a little nearer, and saw the whole adjacent prospect lying a
+straight low line under the sky, I hinted to Peggotty that a mound or so
+might have improved it; and also that if the land had been a little more
+separated from the sea, and the town and the tide had not been quite
+so much mixed up, like toast and water, it would have been nicer. But
+Peggotty said, with greater emphasis than usual, that we must take
+things as we found them, and that, for her part, she was proud to call
+herself a Yarmouth Bloater.
+
+When we got into the street (which was strange enough to me) and smelt
+the fish, and pitch, and oakum, and tar, and saw the sailors walking
+about, and the carts jingling up and down over the stones, I felt that I
+had done so busy a place an injustice; and said as much to Peggotty, who
+heard my expressions of delight with great complacency, and told me it
+was well known (I suppose to those who had the good fortune to be born
+Bloaters) that Yarmouth was, upon the whole, the finest place in the
+universe.
+
+'Here's my Am!' screamed Peggotty, 'growed out of knowledge!'
+
+He was waiting for us, in fact, at the public-house; and asked me how I
+found myself, like an old acquaintance. I did not feel, at first, that
+I knew him as well as he knew me, because he had never come to our house
+since the night I was born, and naturally he had the advantage of me.
+But our intimacy was much advanced by his taking me on his back to carry
+me home. He was, now, a huge, strong fellow of six feet high, broad in
+proportion, and round-shouldered; but with a simpering boy's face and
+curly light hair that gave him quite a sheepish look. He was dressed in
+a canvas jacket, and a pair of such very stiff trousers that they
+would have stood quite as well alone, without any legs in them. And you
+couldn't so properly have said he wore a hat, as that he was covered in
+a-top, like an old building, with something pitchy.
+
+Ham carrying me on his back and a small box of ours under his arm,
+and Peggotty carrying another small box of ours, we turned down lanes
+bestrewn with bits of chips and little hillocks of sand, and went
+past gas-works, rope-walks, boat-builders' yards, shipwrights' yards,
+ship-breakers' yards, caulkers' yards, riggers' lofts, smiths' forges,
+and a great litter of such places, until we came out upon the dull waste
+I had already seen at a distance; when Ham said,
+
+'Yon's our house, Mas'r Davy!'
+
+I looked in all directions, as far as I could stare over the wilderness,
+and away at the sea, and away at the river, but no house could I make
+out. There was a black barge, or some other kind of superannuated boat,
+not far off, high and dry on the ground, with an iron funnel sticking
+out of it for a chimney and smoking very cosily; but nothing else in the
+way of a habitation that was visible to me.
+
+'That's not it?' said I. 'That ship-looking thing?'
+
+'That's it, Mas'r Davy,' returned Ham.
+
+If it had been Aladdin's palace, roc's egg and all, I suppose I could
+not have been more charmed with the romantic idea of living in it. There
+was a delightful door cut in the side, and it was roofed in, and there
+were little windows in it; but the wonderful charm of it was, that
+it was a real boat which had no doubt been upon the water hundreds of
+times, and which had never been intended to be lived in, on dry land.
+That was the captivation of it to me. If it had ever been meant to be
+lived in, I might have thought it small, or inconvenient, or lonely; but
+never having been designed for any such use, it became a perfect abode.
+
+It was beautifully clean inside, and as tidy as possible. There was a
+table, and a Dutch clock, and a chest of drawers, and on the chest of
+drawers there was a tea-tray with a painting on it of a lady with a
+parasol, taking a walk with a military-looking child who was trundling a
+hoop. The tray was kept from tumbling down, by a bible; and the tray, if
+it had tumbled down, would have smashed a quantity of cups and saucers
+and a teapot that were grouped around the book. On the walls there were
+some common coloured pictures, framed and glazed, of scripture subjects;
+such as I have never seen since in the hands of pedlars, without seeing
+the whole interior of Peggotty's brother's house again, at one view.
+Abraham in red going to sacrifice Isaac in blue, and Daniel in yellow
+cast into a den of green lions, were the most prominent of these. Over
+the little mantelshelf, was a picture of the 'Sarah Jane' lugger, built
+at Sunderland, with a real little wooden stern stuck on to it; a work of
+art, combining composition with carpentry, which I considered to be one
+of the most enviable possessions that the world could afford. There
+were some hooks in the beams of the ceiling, the use of which I did not
+divine then; and some lockers and boxes and conveniences of that sort,
+which served for seats and eked out the chairs.
+
+All this I saw in the first glance after I crossed the
+threshold--child-like, according to my theory--and then Peggotty opened
+a little door and showed me my bedroom. It was the completest and most
+desirable bedroom ever seen--in the stern of the vessel; with a little
+window, where the rudder used to go through; a little looking-glass,
+just the right height for me, nailed against the wall, and framed with
+oyster-shells; a little bed, which there was just room enough to get
+into; and a nosegay of seaweed in a blue mug on the table. The walls
+were whitewashed as white as milk, and the patchwork counterpane made my
+eyes quite ache with its brightness. One thing I particularly noticed
+in this delightful house, was the smell of fish; which was so searching,
+that when I took out my pocket-handkerchief to wipe my nose, I found it
+smelt exactly as if it had wrapped up a lobster. On my imparting this
+discovery in confidence to Peggotty, she informed me that her brother
+dealt in lobsters, crabs, and crawfish; and I afterwards found that a
+heap of these creatures, in a state of wonderful conglomeration with one
+another, and never leaving off pinching whatever they laid hold of,
+were usually to be found in a little wooden outhouse where the pots and
+kettles were kept.
+
+We were welcomed by a very civil woman in a white apron, whom I had seen
+curtseying at the door when I was on Ham's back, about a quarter of a
+mile off. Likewise by a most beautiful little girl (or I thought her so)
+with a necklace of blue beads on, who wouldn't let me kiss her when I
+offered to, but ran away and hid herself. By and by, when we had dined
+in a sumptuous manner off boiled dabs, melted butter, and potatoes, with
+a chop for me, a hairy man with a very good-natured face came home. As
+he called Peggotty 'Lass', and gave her a hearty smack on the cheek, I
+had no doubt, from the general propriety of her conduct, that he was her
+brother; and so he turned out--being presently introduced to me as Mr.
+Peggotty, the master of the house.
+
+'Glad to see you, sir,' said Mr. Peggotty. 'You'll find us rough, sir,
+but you'll find us ready.'
+
+I thanked him, and replied that I was sure I should be happy in such a
+delightful place.
+
+'How's your Ma, sir?' said Mr. Peggotty. 'Did you leave her pretty
+jolly?'
+
+I gave Mr. Peggotty to understand that she was as jolly as I could wish,
+and that she desired her compliments--which was a polite fiction on my
+part.
+
+'I'm much obleeged to her, I'm sure,' said Mr. Peggotty. 'Well, sir,
+if you can make out here, fur a fortnut, 'long wi' her,' nodding at his
+sister, 'and Ham, and little Em'ly, we shall be proud of your company.'
+
+Having done the honours of his house in this hospitable manner, Mr.
+Peggotty went out to wash himself in a kettleful of hot water, remarking
+that 'cold would never get his muck off'. He soon returned, greatly
+improved in appearance; but so rubicund, that I couldn't help
+thinking his face had this in common with the lobsters, crabs, and
+crawfish,--that it went into the hot water very black, and came out very
+red.
+
+After tea, when the door was shut and all was made snug (the nights
+being cold and misty now), it seemed to me the most delicious retreat
+that the imagination of man could conceive. To hear the wind getting
+up out at sea, to know that the fog was creeping over the desolate flat
+outside, and to look at the fire, and think that there was no house near
+but this one, and this one a boat, was like enchantment. Little Em'ly
+had overcome her shyness, and was sitting by my side upon the lowest and
+least of the lockers, which was just large enough for us two, and just
+fitted into the chimney corner. Mrs. Peggotty with the white apron, was
+knitting on the opposite side of the fire. Peggotty at her needlework
+was as much at home with St. Paul's and the bit of wax-candle, as if
+they had never known any other roof. Ham, who had been giving me my
+first lesson in all-fours, was trying to recollect a scheme of telling
+fortunes with the dirty cards, and was printing off fishy impressions of
+his thumb on all the cards he turned. Mr. Peggotty was smoking his pipe.
+I felt it was a time for conversation and confidence.
+
+'Mr. Peggotty!' says I.
+
+'Sir,' says he.
+
+'Did you give your son the name of Ham, because you lived in a sort of
+ark?'
+
+Mr. Peggotty seemed to think it a deep idea, but answered:
+
+'No, sir. I never giv him no name.'
+
+'Who gave him that name, then?' said I, putting question number two of
+the catechism to Mr. Peggotty.
+
+'Why, sir, his father giv it him,' said Mr. Peggotty.
+
+'I thought you were his father!'
+
+'My brother Joe was his father,' said Mr. Peggotty.
+
+'Dead, Mr. Peggotty?' I hinted, after a respectful pause.
+
+'Drowndead,' said Mr. Peggotty.
+
+I was very much surprised that Mr. Peggotty was not Ham's father, and
+began to wonder whether I was mistaken about his relationship to anybody
+else there. I was so curious to know, that I made up my mind to have it
+out with Mr. Peggotty.
+
+'Little Em'ly,' I said, glancing at her. 'She is your daughter, isn't
+she, Mr. Peggotty?'
+
+'No, sir. My brother-in-law, Tom, was her father.'
+
+I couldn't help it. '--Dead, Mr. Peggotty?' I hinted, after another
+respectful silence.
+
+'Drowndead,' said Mr. Peggotty.
+
+I felt the difficulty of resuming the subject, but had not got to the
+bottom of it yet, and must get to the bottom somehow. So I said:
+
+'Haven't you ANY children, Mr. Peggotty?'
+
+'No, master,' he answered with a short laugh. 'I'm a bacheldore.'
+
+'A bachelor!' I said, astonished. 'Why, who's that, Mr. Peggotty?'
+pointing to the person in the apron who was knitting.
+
+'That's Missis Gummidge,' said Mr. Peggotty.
+
+'Gummidge, Mr. Peggotty?'
+
+But at this point Peggotty--I mean my own peculiar Peggotty--made such
+impressive motions to me not to ask any more questions, that I could
+only sit and look at all the silent company, until it was time to go to
+bed. Then, in the privacy of my own little cabin, she informed me that
+Ham and Em'ly were an orphan nephew and niece, whom my host had
+at different times adopted in their childhood, when they were left
+destitute: and that Mrs. Gummidge was the widow of his partner in
+a boat, who had died very poor. He was but a poor man himself, said
+Peggotty, but as good as gold and as true as steel--those were her
+similes. The only subject, she informed me, on which he ever showed a
+violent temper or swore an oath, was this generosity of his; and if it
+were ever referred to, by any one of them, he struck the table a heavy
+blow with his right hand (had split it on one such occasion), and swore
+a dreadful oath that he would be 'Gormed' if he didn't cut and run
+for good, if it was ever mentioned again. It appeared, in answer to
+my inquiries, that nobody had the least idea of the etymology of this
+terrible verb passive to be gormed; but that they all regarded it as
+constituting a most solemn imprecation.
+
+I was very sensible of my entertainer's goodness, and listened to the
+women's going to bed in another little crib like mine at the opposite
+end of the boat, and to him and Ham hanging up two hammocks for
+themselves on the hooks I had noticed in the roof, in a very luxurious
+state of mind, enhanced by my being sleepy. As slumber gradually stole
+upon me, I heard the wind howling out at sea and coming on across the
+flat so fiercely, that I had a lazy apprehension of the great deep
+rising in the night. But I bethought myself that I was in a boat, after
+all; and that a man like Mr. Peggotty was not a bad person to have on
+board if anything did happen.
+
+Nothing happened, however, worse than morning. Almost as soon as it
+shone upon the oyster-shell frame of my mirror I was out of bed, and out
+with little Em'ly, picking up stones upon the beach.
+
+'You're quite a sailor, I suppose?' I said to Em'ly. I don't know that I
+supposed anything of the kind, but I felt it an act of gallantry to
+say something; and a shining sail close to us made such a pretty little
+image of itself, at the moment, in her bright eye, that it came into my
+head to say this.
+
+'No,' replied Em'ly, shaking her head, 'I'm afraid of the sea.'
+
+'Afraid!' I said, with a becoming air of boldness, and looking very big
+at the mighty ocean. 'I an't!'
+
+'Ah! but it's cruel,' said Em'ly. 'I have seen it very cruel to some of
+our men. I have seen it tear a boat as big as our house, all to pieces.'
+
+'I hope it wasn't the boat that--'
+
+'That father was drownded in?' said Em'ly. 'No. Not that one, I never
+see that boat.'
+
+'Nor him?' I asked her.
+
+Little Em'ly shook her head. 'Not to remember!'
+
+Here was a coincidence! I immediately went into an explanation how I had
+never seen my own father; and how my mother and I had always lived
+by ourselves in the happiest state imaginable, and lived so then, and
+always meant to live so; and how my father's grave was in the churchyard
+near our house, and shaded by a tree, beneath the boughs of which I had
+walked and heard the birds sing many a pleasant morning. But there were
+some differences between Em'ly's orphanhood and mine, it appeared. She
+had lost her mother before her father; and where her father's grave was
+no one knew, except that it was somewhere in the depths of the sea.
+
+'Besides,' said Em'ly, as she looked about for shells and pebbles, 'your
+father was a gentleman and your mother is a lady; and my father was a
+fisherman and my mother was a fisherman's daughter, and my uncle Dan is
+a fisherman.'
+
+'Dan is Mr. Peggotty, is he?' said I.
+
+'Uncle Dan--yonder,' answered Em'ly, nodding at the boat-house.
+
+'Yes. I mean him. He must be very good, I should think?'
+
+'Good?' said Em'ly. 'If I was ever to be a lady, I'd give him a sky-blue
+coat with diamond buttons, nankeen trousers, a red velvet waistcoat, a
+cocked hat, a large gold watch, a silver pipe, and a box of money.'
+
+I said I had no doubt that Mr. Peggotty well deserved these treasures.
+I must acknowledge that I felt it difficult to picture him quite at his
+ease in the raiment proposed for him by his grateful little niece, and
+that I was particularly doubtful of the policy of the cocked hat; but I
+kept these sentiments to myself.
+
+Little Em'ly had stopped and looked up at the sky in her enumeration
+of these articles, as if they were a glorious vision. We went on again,
+picking up shells and pebbles.
+
+'You would like to be a lady?' I said.
+
+Emily looked at me, and laughed and nodded 'yes'.
+
+'I should like it very much. We would all be gentlefolks together, then.
+Me, and uncle, and Ham, and Mrs. Gummidge. We wouldn't mind then, when
+there comes stormy weather.---Not for our own sakes, I mean. We would
+for the poor fishermen's, to be sure, and we'd help 'em with money when
+they come to any hurt.' This seemed to me to be a very satisfactory and
+therefore not at all improbable picture. I expressed my pleasure in the
+contemplation of it, and little Em'ly was emboldened to say, shyly,
+
+'Don't you think you are afraid of the sea, now?'
+
+It was quiet enough to reassure me, but I have no doubt if I had seen a
+moderately large wave come tumbling in, I should have taken to my heels,
+with an awful recollection of her drowned relations. However, I said
+'No,' and I added, 'You don't seem to be either, though you say you
+are,'--for she was walking much too near the brink of a sort of old
+jetty or wooden causeway we had strolled upon, and I was afraid of her
+falling over.
+
+'I'm not afraid in this way,' said little Em'ly. 'But I wake when it
+blows, and tremble to think of Uncle Dan and Ham and believe I hear 'em
+crying out for help. That's why I should like so much to be a lady. But
+I'm not afraid in this way. Not a bit. Look here!'
+
+She started from my side, and ran along a jagged timber which protruded
+from the place we stood upon, and overhung the deep water at some
+height, without the least defence. The incident is so impressed on my
+remembrance, that if I were a draughtsman I could draw its form here,
+I dare say, accurately as it was that day, and little Em'ly springing
+forward to her destruction (as it appeared to me), with a look that I
+have never forgotten, directed far out to sea.
+
+The light, bold, fluttering little figure turned and came back safe
+to me, and I soon laughed at my fears, and at the cry I had uttered;
+fruitlessly in any case, for there was no one near. But there have been
+times since, in my manhood, many times there have been, when I have
+thought, Is it possible, among the possibilities of hidden things, that
+in the sudden rashness of the child and her wild look so far off, there
+was any merciful attraction of her into danger, any tempting her towards
+him permitted on the part of her dead father, that her life might have
+a chance of ending that day? There has been a time since when I have
+wondered whether, if the life before her could have been revealed to me
+at a glance, and so revealed as that a child could fully comprehend it,
+and if her preservation could have depended on a motion of my hand, I
+ought to have held it up to save her. There has been a time since--I do
+not say it lasted long, but it has been--when I have asked myself the
+question, would it have been better for little Em'ly to have had the
+waters close above her head that morning in my sight; and when I have
+answered Yes, it would have been.
+
+This may be premature. I have set it down too soon, perhaps. But let it
+stand.
+
+We strolled a long way, and loaded ourselves with things that we thought
+curious, and put some stranded starfish carefully back into the water--I
+hardly know enough of the race at this moment to be quite certain
+whether they had reason to feel obliged to us for doing so, or the
+reverse--and then made our way home to Mr. Peggotty's dwelling. We
+stopped under the lee of the lobster-outhouse to exchange an innocent
+kiss, and went in to breakfast glowing with health and pleasure.
+
+'Like two young mavishes,' Mr. Peggotty said. I knew this meant, in our
+local dialect, like two young thrushes, and received it as a compliment.
+
+Of course I was in love with little Em'ly. I am sure I loved that
+baby quite as truly, quite as tenderly, with greater purity and more
+disinterestedness, than can enter into the best love of a later time
+of life, high and ennobling as it is. I am sure my fancy raised up
+something round that blue-eyed mite of a child, which etherealized,
+and made a very angel of her. If, any sunny forenoon, she had spread
+a little pair of wings and flown away before my eyes, I don't think I
+should have regarded it as much more than I had had reason to expect.
+
+We used to walk about that dim old flat at Yarmouth in a loving manner,
+hours and hours. The days sported by us, as if Time had not grown up
+himself yet, but were a child too, and always at play. I told Em'ly
+I adored her, and that unless she confessed she adored me I should be
+reduced to the necessity of killing myself with a sword. She said she
+did, and I have no doubt she did.
+
+As to any sense of inequality, or youthfulness, or other difficulty
+in our way, little Em'ly and I had no such trouble, because we had no
+future. We made no more provision for growing older, than we did for
+growing younger. We were the admiration of Mrs. Gummidge and Peggotty,
+who used to whisper of an evening when we sat, lovingly, on our little
+locker side by side, 'Lor! wasn't it beautiful!' Mr. Peggotty smiled at
+us from behind his pipe, and Ham grinned all the evening and did nothing
+else. They had something of the sort of pleasure in us, I suppose, that
+they might have had in a pretty toy, or a pocket model of the Colosseum.
+
+I soon found out that Mrs. Gummidge did not always make herself so
+agreeable as she might have been expected to do, under the circumstances
+of her residence with Mr. Peggotty. Mrs. Gummidge's was rather a fretful
+disposition, and she whimpered more sometimes than was comfortable for
+other parties in so small an establishment. I was very sorry for
+her; but there were moments when it would have been more agreeable, I
+thought, if Mrs. Gummidge had had a convenient apartment of her own to
+retire to, and had stopped there until her spirits revived.
+
+Mr. Peggotty went occasionally to a public-house called The Willing
+Mind. I discovered this, by his being out on the second or third evening
+of our visit, and by Mrs. Gummidge's looking up at the Dutch clock,
+between eight and nine, and saying he was there, and that, what was
+more, she had known in the morning he would go there.
+
+Mrs. Gummidge had been in a low state all day, and had burst into tears
+in the forenoon, when the fire smoked. 'I am a lone lorn creetur',' were
+Mrs. Gummidge's words, when that unpleasant occurrence took place, 'and
+everythink goes contrary with me.'
+
+'Oh, it'll soon leave off,' said Peggotty--I again mean our
+Peggotty--'and besides, you know, it's not more disagreeable to you than
+to us.'
+
+'I feel it more,' said Mrs. Gummidge.
+
+It was a very cold day, with cutting blasts of wind. Mrs. Gummidge's
+peculiar corner of the fireside seemed to me to be the warmest and
+snuggest in the place, as her chair was certainly the easiest, but it
+didn't suit her that day at all. She was constantly complaining of the
+cold, and of its occasioning a visitation in her back which she called
+'the creeps'. At last she shed tears on that subject, and said again
+that she was 'a lone lorn creetur' and everythink went contrary with
+her'.
+
+'It is certainly very cold,' said Peggotty. 'Everybody must feel it so.'
+
+'I feel it more than other people,' said Mrs. Gummidge.
+
+So at dinner; when Mrs. Gummidge was always helped immediately after me,
+to whom the preference was given as a visitor of distinction. The
+fish were small and bony, and the potatoes were a little burnt. We all
+acknowledged that we felt this something of a disappointment; but Mrs.
+Gummidge said she felt it more than we did, and shed tears again, and
+made that former declaration with great bitterness.
+
+Accordingly, when Mr. Peggotty came home about nine o'clock, this
+unfortunate Mrs. Gummidge was knitting in her corner, in a very wretched
+and miserable condition. Peggotty had been working cheerfully. Ham had
+been patching up a great pair of waterboots; and I, with little Em'ly
+by my side, had been reading to them. Mrs. Gummidge had never made any
+other remark than a forlorn sigh, and had never raised her eyes since
+tea.
+
+'Well, Mates,' said Mr. Peggotty, taking his seat, 'and how are you?'
+
+We all said something, or looked something, to welcome him, except Mrs.
+Gummidge, who only shook her head over her knitting.
+
+'What's amiss?' said Mr. Peggotty, with a clap of his hands. 'Cheer up,
+old Mawther!' (Mr. Peggotty meant old girl.)
+
+Mrs. Gummidge did not appear to be able to cheer up. She took out an old
+black silk handkerchief and wiped her eyes; but instead of putting it
+in her pocket, kept it out, and wiped them again, and still kept it out,
+ready for use.
+
+'What's amiss, dame?' said Mr. Peggotty.
+
+'Nothing,' returned Mrs. Gummidge. 'You've come from The Willing Mind,
+Dan'l?'
+
+'Why yes, I've took a short spell at The Willing Mind tonight,' said Mr.
+Peggotty.
+
+'I'm sorry I should drive you there,' said Mrs. Gummidge.
+
+'Drive! I don't want no driving,' returned Mr. Peggotty with an honest
+laugh. 'I only go too ready.'
+
+'Very ready,' said Mrs. Gummidge, shaking her head, and wiping her eyes.
+'Yes, yes, very ready. I am sorry it should be along of me that you're
+so ready.'
+
+'Along o' you! It an't along o' you!' said Mr. Peggotty. 'Don't ye
+believe a bit on it.'
+
+'Yes, yes, it is,' cried Mrs. Gummidge. 'I know what I am. I know that I
+am a lone lorn creetur', and not only that everythink goes contrary with
+me, but that I go contrary with everybody. Yes, yes. I feel more than
+other people do, and I show it more. It's my misfortun'.'
+
+I really couldn't help thinking, as I sat taking in all this, that the
+misfortune extended to some other members of that family besides Mrs.
+Gummidge. But Mr. Peggotty made no such retort, only answering with
+another entreaty to Mrs. Gummidge to cheer up.
+
+'I an't what I could wish myself to be,' said Mrs. Gummidge. 'I am far
+from it. I know what I am. My troubles has made me contrary. I feel my
+troubles, and they make me contrary. I wish I didn't feel 'em, but I
+do. I wish I could be hardened to 'em, but I an't. I make the house
+uncomfortable. I don't wonder at it. I've made your sister so all day,
+and Master Davy.'
+
+Here I was suddenly melted, and roared out, 'No, you haven't, Mrs.
+Gummidge,' in great mental distress.
+
+'It's far from right that I should do it,' said Mrs. Gummidge. 'It an't
+a fit return. I had better go into the house and die. I am a lone lorn
+creetur', and had much better not make myself contrary here. If thinks
+must go contrary with me, and I must go contrary myself, let me go
+contrary in my parish. Dan'l, I'd better go into the house, and die and
+be a riddance!'
+
+Mrs. Gummidge retired with these words, and betook herself to bed. When
+she was gone, Mr. Peggotty, who had not exhibited a trace of any feeling
+but the profoundest sympathy, looked round upon us, and nodding his head
+with a lively expression of that sentiment still animating his face,
+said in a whisper:
+
+'She's been thinking of the old 'un!'
+
+I did not quite understand what old one Mrs. Gummidge was supposed to
+have fixed her mind upon, until Peggotty, on seeing me to bed, explained
+that it was the late Mr. Gummidge; and that her brother always took that
+for a received truth on such occasions, and that it always had a moving
+effect upon him. Some time after he was in his hammock that night, I
+heard him myself repeat to Ham, 'Poor thing! She's been thinking of the
+old 'un!' And whenever Mrs. Gummidge was overcome in a similar manner
+during the remainder of our stay (which happened some few times), he
+always said the same thing in extenuation of the circumstance, and
+always with the tenderest commiseration.
+
+So the fortnight slipped away, varied by nothing but the variation of
+the tide, which altered Mr. Peggotty's times of going out and coming in,
+and altered Ham's engagements also. When the latter was unemployed, he
+sometimes walked with us to show us the boats and ships, and once
+or twice he took us for a row. I don't know why one slight set of
+impressions should be more particularly associated with a place than
+another, though I believe this obtains with most people, in reference
+especially to the associations of their childhood. I never hear the
+name, or read the name, of Yarmouth, but I am reminded of a certain
+Sunday morning on the beach, the bells ringing for church, little Em'ly
+leaning on my shoulder, Ham lazily dropping stones into the water, and
+the sun, away at sea, just breaking through the heavy mist, and showing
+us the ships, like their own shadows.
+
+At last the day came for going home. I bore up against the separation
+from Mr. Peggotty and Mrs. Gummidge, but my agony of mind at leaving
+little Em'ly was piercing. We went arm-in-arm to the public-house where
+the carrier put up, and I promised, on the road, to write to her. (I
+redeemed that promise afterwards, in characters larger than those in
+which apartments are usually announced in manuscript, as being to let.)
+We were greatly overcome at parting; and if ever, in my life, I have had
+a void made in my heart, I had one made that day.
+
+Now, all the time I had been on my visit, I had been ungrateful to my
+home again, and had thought little or nothing about it. But I was no
+sooner turned towards it, than my reproachful young conscience seemed
+to point that way with a ready finger; and I felt, all the more for the
+sinking of my spirits, that it was my nest, and that my mother was my
+comforter and friend.
+
+This gained upon me as we went along; so that the nearer we drew, the
+more familiar the objects became that we passed, the more excited I was
+to get there, and to run into her arms. But Peggotty, instead of sharing
+in those transports, tried to check them (though very kindly), and
+looked confused and out of sorts.
+
+Blunderstone Rookery would come, however, in spite of her, when the
+carrier's horse pleased--and did. How well I recollect it, on a cold
+grey afternoon, with a dull sky, threatening rain!
+
+The door opened, and I looked, half laughing and half crying in my
+pleasant agitation, for my mother. It was not she, but a strange
+servant.
+
+'Why, Peggotty!' I said, ruefully, 'isn't she come home?'
+
+'Yes, yes, Master Davy,' said Peggotty. 'She's come home. Wait a bit,
+Master Davy, and I'll--I'll tell you something.'
+
+Between her agitation, and her natural awkwardness in getting out of the
+cart, Peggotty was making a most extraordinary festoon of herself, but
+I felt too blank and strange to tell her so. When she had got down, she
+took me by the hand; led me, wondering, into the kitchen; and shut the
+door.
+
+'Peggotty!' said I, quite frightened. 'What's the matter?'
+
+'Nothing's the matter, bless you, Master Davy dear!' she answered,
+assuming an air of sprightliness.
+
+'Something's the matter, I'm sure. Where's mama?'
+
+'Where's mama, Master Davy?' repeated Peggotty.
+
+'Yes. Why hasn't she come out to the gate, and what have we come in here
+for? Oh, Peggotty!' My eyes were full, and I felt as if I were going to
+tumble down.
+
+'Bless the precious boy!' cried Peggotty, taking hold of me. 'What is
+it? Speak, my pet!'
+
+'Not dead, too! Oh, she's not dead, Peggotty?'
+
+Peggotty cried out No! with an astonishing volume of voice; and then sat
+down, and began to pant, and said I had given her a turn.
+
+I gave her a hug to take away the turn, or to give her another turn
+in the right direction, and then stood before her, looking at her in
+anxious inquiry.
+
+'You see, dear, I should have told you before now,' said Peggotty,
+'but I hadn't an opportunity. I ought to have made it, perhaps, but
+I couldn't azackly'--that was always the substitute for exactly, in
+Peggotty's militia of words--'bring my mind to it.'
+
+'Go on, Peggotty,' said I, more frightened than before.
+
+'Master Davy,' said Peggotty, untying her bonnet with a shaking hand,
+and speaking in a breathless sort of way. 'What do you think? You have
+got a Pa!'
+
+I trembled, and turned white. Something--I don't know what, or
+how--connected with the grave in the churchyard, and the raising of the
+dead, seemed to strike me like an unwholesome wind.
+
+'A new one,' said Peggotty.
+
+'A new one?' I repeated.
+
+Peggotty gave a gasp, as if she were swallowing something that was very
+hard, and, putting out her hand, said:
+
+'Come and see him.'
+
+'I don't want to see him.' --'And your mama,' said Peggotty.
+
+I ceased to draw back, and we went straight to the best parlour, where
+she left me. On one side of the fire, sat my mother; on the other, Mr.
+Murdstone. My mother dropped her work, and arose hurriedly, but timidly
+I thought.
+
+'Now, Clara my dear,' said Mr. Murdstone. 'Recollect! control yourself,
+always control yourself! Davy boy, how do you do?'
+
+I gave him my hand. After a moment of suspense, I went and kissed my
+mother: she kissed me, patted me gently on the shoulder, and sat down
+again to her work. I could not look at her, I could not look at him,
+I knew quite well that he was looking at us both; and I turned to the
+window and looked out there, at some shrubs that were drooping their
+heads in the cold.
+
+As soon as I could creep away, I crept upstairs. My old dear bedroom was
+changed, and I was to lie a long way off. I rambled downstairs to find
+anything that was like itself, so altered it all seemed; and roamed into
+the yard. I very soon started back from there, for the empty dog-kennel
+was filled up with a great dog--deep mouthed and black-haired like
+Him--and he was very angry at the sight of me, and sprang out to get at
+me.
+
+
+
+CHAPTER 4. I FALL INTO DISGRACE
+
+
+If the room to which my bed was removed were a sentient thing that could
+give evidence, I might appeal to it at this day--who sleeps there now,
+I wonder!--to bear witness for me what a heavy heart I carried to it.
+I went up there, hearing the dog in the yard bark after me all the way
+while I climbed the stairs; and, looking as blank and strange upon the
+room as the room looked upon me, sat down with my small hands crossed,
+and thought.
+
+I thought of the oddest things. Of the shape of the room, of the
+cracks in the ceiling, of the paper on the walls, of the flaws in
+the window-glass making ripples and dimples on the prospect, of the
+washing-stand being rickety on its three legs, and having a discontented
+something about it, which reminded me of Mrs. Gummidge under the
+influence of the old one. I was crying all the time, but, except that I
+was conscious of being cold and dejected, I am sure I never thought
+why I cried. At last in my desolation I began to consider that I was
+dreadfully in love with little Em'ly, and had been torn away from her to
+come here where no one seemed to want me, or to care about me, half as
+much as she did. This made such a very miserable piece of business of
+it, that I rolled myself up in a corner of the counterpane, and cried
+myself to sleep.
+
+I was awoke by somebody saying 'Here he is!' and uncovering my hot head.
+My mother and Peggotty had come to look for me, and it was one of them
+who had done it.
+
+'Davy,' said my mother. 'What's the matter?'
+
+I thought it was very strange that she should ask me, and answered,
+'Nothing.' I turned over on my face, I recollect, to hide my trembling
+lip, which answered her with greater truth. 'Davy,' said my mother.
+'Davy, my child!'
+
+I dare say no words she could have uttered would have affected me
+so much, then, as her calling me her child. I hid my tears in the
+bedclothes, and pressed her from me with my hand, when she would have
+raised me up.
+
+'This is your doing, Peggotty, you cruel thing!' said my mother. 'I have
+no doubt at all about it. How can you reconcile it to your conscience,
+I wonder, to prejudice my own boy against me, or against anybody who is
+dear to me? What do you mean by it, Peggotty?'
+
+Poor Peggotty lifted up her hands and eyes, and only answered, in a
+sort of paraphrase of the grace I usually repeated after dinner, 'Lord
+forgive you, Mrs. Copperfield, and for what you have said this minute,
+may you never be truly sorry!'
+
+'It's enough to distract me,' cried my mother. 'In my honeymoon, too,
+when my most inveterate enemy might relent, one would think, and not
+envy me a little peace of mind and happiness. Davy, you naughty boy!
+Peggotty, you savage creature! Oh, dear me!' cried my mother, turning
+from one of us to the other, in her pettish wilful manner, 'what a
+troublesome world this is, when one has the most right to expect it to
+be as agreeable as possible!'
+
+I felt the touch of a hand that I knew was neither hers nor Peggotty's,
+and slipped to my feet at the bed-side. It was Mr. Murdstone's hand, and
+he kept it on my arm as he said:
+
+'What's this? Clara, my love, have you forgotten?--Firmness, my dear!'
+
+'I am very sorry, Edward,' said my mother. 'I meant to be very good, but
+I am so uncomfortable.'
+
+'Indeed!' he answered. 'That's a bad hearing, so soon, Clara.'
+
+'I say it's very hard I should be made so now,' returned my mother,
+pouting; 'and it is--very hard--isn't it?'
+
+He drew her to him, whispered in her ear, and kissed her. I knew as
+well, when I saw my mother's head lean down upon his shoulder, and her
+arm touch his neck--I knew as well that he could mould her pliant nature
+into any form he chose, as I know, now, that he did it.
+
+'Go you below, my love,' said Mr. Murdstone. 'David and I will come
+down, together. My friend,' turning a darkening face on Peggotty, when
+he had watched my mother out, and dismissed her with a nod and a smile;
+'do you know your mistress's name?'
+
+'She has been my mistress a long time, sir,' answered Peggotty, 'I ought
+to know it.' 'That's true,' he answered. 'But I thought I heard you, as
+I came upstairs, address her by a name that is not hers. She has taken
+mine, you know. Will you remember that?'
+
+Peggotty, with some uneasy glances at me, curtseyed herself out of the
+room without replying; seeing, I suppose, that she was expected to go,
+and had no excuse for remaining. When we two were left alone, he shut
+the door, and sitting on a chair, and holding me standing before him,
+looked steadily into my eyes. I felt my own attracted, no less steadily,
+to his. As I recall our being opposed thus, face to face, I seem again
+to hear my heart beat fast and high.
+
+'David,' he said, making his lips thin, by pressing them together, 'if I
+have an obstinate horse or dog to deal with, what do you think I do?'
+
+'I don't know.'
+
+'I beat him.'
+
+I had answered in a kind of breathless whisper, but I felt, in my
+silence, that my breath was shorter now.
+
+'I make him wince, and smart. I say to myself, "I'll conquer that
+fellow"; and if it were to cost him all the blood he had, I should do
+it. What is that upon your face?'
+
+'Dirt,' I said.
+
+He knew it was the mark of tears as well as I. But if he had asked the
+question twenty times, each time with twenty blows, I believe my baby
+heart would have burst before I would have told him so.
+
+'You have a good deal of intelligence for a little fellow,' he said,
+with a grave smile that belonged to him, 'and you understood me very
+well, I see. Wash that face, sir, and come down with me.'
+
+He pointed to the washing-stand, which I had made out to be like Mrs.
+Gummidge, and motioned me with his head to obey him directly. I had
+little doubt then, and I have less doubt now, that he would have knocked
+me down without the least compunction, if I had hesitated.
+
+'Clara, my dear,' he said, when I had done his bidding, and he walked me
+into the parlour, with his hand still on my arm; 'you will not be made
+uncomfortable any more, I hope. We shall soon improve our youthful
+humours.'
+
+God help me, I might have been improved for my whole life, I might have
+been made another creature perhaps, for life, by a kind word at that
+season. A word of encouragement and explanation, of pity for my childish
+ignorance, of welcome home, of reassurance to me that it was home, might
+have made me dutiful to him in my heart henceforth, instead of in my
+hypocritical outside, and might have made me respect instead of hate
+him. I thought my mother was sorry to see me standing in the room so
+scared and strange, and that, presently, when I stole to a chair, she
+followed me with her eyes more sorrowfully still--missing, perhaps, some
+freedom in my childish tread--but the word was not spoken, and the time
+for it was gone.
+
+We dined alone, we three together. He seemed to be very fond of my
+mother--I am afraid I liked him none the better for that--and she was
+very fond of him. I gathered from what they said, that an elder sister
+of his was coming to stay with them, and that she was expected that
+evening. I am not certain whether I found out then, or afterwards, that,
+without being actively concerned in any business, he had some share in,
+or some annual charge upon the profits of, a wine-merchant's house
+in London, with which his family had been connected from his
+great-grandfather's time, and in which his sister had a similar
+interest; but I may mention it in this place, whether or no.
+
+After dinner, when we were sitting by the fire, and I was meditating an
+escape to Peggotty without having the hardihood to slip away, lest
+it should offend the master of the house, a coach drove up to the
+garden-gate and he went out to receive the visitor. My mother followed
+him. I was timidly following her, when she turned round at the parlour
+door, in the dusk, and taking me in her embrace as she had been used to
+do, whispered me to love my new father and be obedient to him. She did
+this hurriedly and secretly, as if it were wrong, but tenderly; and,
+putting out her hand behind her, held mine in it, until we came near
+to where he was standing in the garden, where she let mine go, and drew
+hers through his arm.
+
+It was Miss Murdstone who was arrived, and a gloomy-looking lady she
+was; dark, like her brother, whom she greatly resembled in face and
+voice; and with very heavy eyebrows, nearly meeting over her large nose,
+as if, being disabled by the wrongs of her sex from wearing whiskers,
+she had carried them to that account. She brought with her two
+uncompromising hard black boxes, with her initials on the lids in hard
+brass nails. When she paid the coachman she took her money out of a hard
+steel purse, and she kept the purse in a very jail of a bag which hung
+upon her arm by a heavy chain, and shut up like a bite. I had never, at
+that time, seen such a metallic lady altogether as Miss Murdstone was.
+
+She was brought into the parlour with many tokens of welcome, and there
+formally recognized my mother as a new and near relation. Then she
+looked at me, and said:
+
+'Is that your boy, sister-in-law?'
+
+My mother acknowledged me.
+
+'Generally speaking,' said Miss Murdstone, 'I don't like boys. How d'ye
+do, boy?'
+
+Under these encouraging circumstances, I replied that I was very well,
+and that I hoped she was the same; with such an indifferent grace, that
+Miss Murdstone disposed of me in two words:
+
+'Wants manner!'
+
+Having uttered which, with great distinctness, she begged the favour of
+being shown to her room, which became to me from that time forth a place
+of awe and dread, wherein the two black boxes were never seen open or
+known to be left unlocked, and where (for I peeped in once or twice when
+she was out) numerous little steel fetters and rivets, with which Miss
+Murdstone embellished herself when she was dressed, generally hung upon
+the looking-glass in formidable array.
+
+As well as I could make out, she had come for good, and had no intention
+of ever going again. She began to 'help' my mother next morning, and was
+in and out of the store-closet all day, putting things to rights, and
+making havoc in the old arrangements. Almost the first remarkable thing
+I observed in Miss Murdstone was, her being constantly haunted by
+a suspicion that the servants had a man secreted somewhere on the
+premises. Under the influence of this delusion, she dived into the
+coal-cellar at the most untimely hours, and scarcely ever opened the
+door of a dark cupboard without clapping it to again, in the belief that
+she had got him.
+
+Though there was nothing very airy about Miss Murdstone, she was a
+perfect Lark in point of getting up. She was up (and, as I believe
+to this hour, looking for that man) before anybody in the house was
+stirring. Peggotty gave it as her opinion that she even slept with one
+eye open; but I could not concur in this idea; for I tried it myself
+after hearing the suggestion thrown out, and found it couldn't be done.
+
+On the very first morning after her arrival she was up and ringing her
+bell at cock-crow. When my mother came down to breakfast and was going
+to make the tea, Miss Murdstone gave her a kind of peck on the cheek,
+which was her nearest approach to a kiss, and said:
+
+'Now, Clara, my dear, I am come here, you know, to relieve you of all
+the trouble I can. You're much too pretty and thoughtless'--my mother
+blushed but laughed, and seemed not to dislike this character--'to have
+any duties imposed upon you that can be undertaken by me. If you'll be
+so good as give me your keys, my dear, I'll attend to all this sort of
+thing in future.'
+
+From that time, Miss Murdstone kept the keys in her own little jail all
+day, and under her pillow all night, and my mother had no more to do
+with them than I had.
+
+My mother did not suffer her authority to pass from her without a shadow
+of protest. One night when Miss Murdstone had been developing certain
+household plans to her brother, of which he signified his approbation,
+my mother suddenly began to cry, and said she thought she might have
+been consulted.
+
+'Clara!' said Mr. Murdstone sternly. 'Clara! I wonder at you.'
+
+'Oh, it's very well to say you wonder, Edward!' cried my mother, 'and
+it's very well for you to talk about firmness, but you wouldn't like it
+yourself.'
+
+Firmness, I may observe, was the grand quality on which both Mr. and
+Miss Murdstone took their stand. However I might have expressed
+my comprehension of it at that time, if I had been called upon, I
+nevertheless did clearly comprehend in my own way, that it was another
+name for tyranny; and for a certain gloomy, arrogant, devil's humour,
+that was in them both. The creed, as I should state it now, was this.
+Mr. Murdstone was firm; nobody in his world was to be so firm as Mr.
+Murdstone; nobody else in his world was to be firm at all, for everybody
+was to be bent to his firmness. Miss Murdstone was an exception.
+She might be firm, but only by relationship, and in an inferior and
+tributary degree. My mother was another exception. She might be firm,
+and must be; but only in bearing their firmness, and firmly believing
+there was no other firmness upon earth.
+
+'It's very hard,' said my mother, 'that in my own house--'
+
+'My own house?' repeated Mr. Murdstone. 'Clara!'
+
+'OUR own house, I mean,' faltered my mother, evidently frightened--'I
+hope you must know what I mean, Edward--it's very hard that in YOUR own
+house I may not have a word to say about domestic matters. I am sure
+I managed very well before we were married. There's evidence,' said my
+mother, sobbing; 'ask Peggotty if I didn't do very well when I wasn't
+interfered with!'
+
+'Edward,' said Miss Murdstone, 'let there be an end of this. I go
+tomorrow.'
+
+'Jane Murdstone,' said her brother, 'be silent! How dare you to
+insinuate that you don't know my character better than your words
+imply?'
+
+'I am sure,' my poor mother went on, at a grievous disadvantage, and
+with many tears, 'I don't want anybody to go. I should be very
+miserable and unhappy if anybody was to go. I don't ask much. I am not
+unreasonable. I only want to be consulted sometimes. I am very much
+obliged to anybody who assists me, and I only want to be consulted as a
+mere form, sometimes. I thought you were pleased, once, with my being a
+little inexperienced and girlish, Edward--I am sure you said so--but you
+seem to hate me for it now, you are so severe.'
+
+'Edward,' said Miss Murdstone, again, 'let there be an end of this. I go
+tomorrow.'
+
+'Jane Murdstone,' thundered Mr. Murdstone. 'Will you be silent? How dare
+you?'
+
+Miss Murdstone made a jail-delivery of her pocket-handkerchief, and held
+it before her eyes.
+
+'Clara,' he continued, looking at my mother, 'you surprise me! You
+astound me! Yes, I had a satisfaction in the thought of marrying
+an inexperienced and artless person, and forming her character, and
+infusing into it some amount of that firmness and decision of which
+it stood in need. But when Jane Murdstone is kind enough to come to my
+assistance in this endeavour, and to assume, for my sake, a condition
+something like a housekeeper's, and when she meets with a base return--'
+
+'Oh, pray, pray, Edward,' cried my mother, 'don't accuse me of being
+ungrateful. I am sure I am not ungrateful. No one ever said I was
+before. I have many faults, but not that. Oh, don't, my dear!'
+
+'When Jane Murdstone meets, I say,' he went on, after waiting until my
+mother was silent, 'with a base return, that feeling of mine is chilled
+and altered.'
+
+'Don't, my love, say that!' implored my mother very piteously.
+'Oh, don't, Edward! I can't bear to hear it. Whatever I am, I am
+affectionate. I know I am affectionate. I wouldn't say it, if I
+wasn't sure that I am. Ask Peggotty. I am sure she'll tell you I'm
+affectionate.'
+
+'There is no extent of mere weakness, Clara,' said Mr. Murdstone in
+reply, 'that can have the least weight with me. You lose breath.'
+
+'Pray let us be friends,' said my mother, 'I couldn't live under
+coldness or unkindness. I am so sorry. I have a great many defects, I
+know, and it's very good of you, Edward, with your strength of mind, to
+endeavour to correct them for me. Jane, I don't object to anything. I
+should be quite broken-hearted if you thought of leaving--' My mother
+was too much overcome to go on.
+
+'Jane Murdstone,' said Mr. Murdstone to his sister, 'any harsh words
+between us are, I hope, uncommon. It is not my fault that so unusual an
+occurrence has taken place tonight. I was betrayed into it by another.
+Nor is it your fault. You were betrayed into it by another. Let us both
+try to forget it. And as this,' he added, after these magnanimous words,
+'is not a fit scene for the boy--David, go to bed!'
+
+I could hardly find the door, through the tears that stood in my eyes.
+I was so sorry for my mother's distress; but I groped my way out, and
+groped my way up to my room in the dark, without even having the heart
+to say good night to Peggotty, or to get a candle from her. When her
+coming up to look for me, an hour or so afterwards, awoke me, she said
+that my mother had gone to bed poorly, and that Mr. and Miss Murdstone
+were sitting alone.
+
+Going down next morning rather earlier than usual, I paused outside the
+parlour door, on hearing my mother's voice. She was very earnestly and
+humbly entreating Miss Murdstone's pardon, which that lady granted, and
+a perfect reconciliation took place. I never knew my mother afterwards
+to give an opinion on any matter, without first appealing to Miss
+Murdstone, or without having first ascertained by some sure means, what
+Miss Murdstone's opinion was; and I never saw Miss Murdstone, when out
+of temper (she was infirm that way), move her hand towards her bag as
+if she were going to take out the keys and offer to resign them to my
+mother, without seeing that my mother was in a terrible fright.
+
+The gloomy taint that was in the Murdstone blood, darkened the Murdstone
+religion, which was austere and wrathful. I have thought, since,
+that its assuming that character was a necessary consequence of Mr.
+Murdstone's firmness, which wouldn't allow him to let anybody off from
+the utmost weight of the severest penalties he could find any excuse
+for. Be this as it may, I well remember the tremendous visages with
+which we used to go to church, and the changed air of the place. Again,
+the dreaded Sunday comes round, and I file into the old pew first, like
+a guarded captive brought to a condemned service. Again, Miss Murdstone,
+in a black velvet gown, that looks as if it had been made out of a pall,
+follows close upon me; then my mother; then her husband. There is no
+Peggotty now, as in the old time. Again, I listen to Miss Murdstone
+mumbling the responses, and emphasizing all the dread words with a cruel
+relish. Again, I see her dark eyes roll round the church when she says
+'miserable sinners', as if she were calling all the congregation names.
+Again, I catch rare glimpses of my mother, moving her lips timidly
+between the two, with one of them muttering at each ear like low
+thunder. Again, I wonder with a sudden fear whether it is likely that
+our good old clergyman can be wrong, and Mr. and Miss Murdstone right,
+and that all the angels in Heaven can be destroying angels. Again, if I
+move a finger or relax a muscle of my face, Miss Murdstone pokes me with
+her prayer-book, and makes my side ache.
+
+Yes, and again, as we walk home, I note some neighbours looking at my
+mother and at me, and whispering. Again, as the three go on arm-in-arm,
+and I linger behind alone, I follow some of those looks, and wonder if
+my mother's step be really not so light as I have seen it, and if the
+gaiety of her beauty be really almost worried away. Again, I wonder
+whether any of the neighbours call to mind, as I do, how we used to
+walk home together, she and I; and I wonder stupidly about that, all the
+dreary dismal day.
+
+There had been some talk on occasions of my going to boarding-school.
+Mr. and Miss Murdstone had originated it, and my mother had of course
+agreed with them. Nothing, however, was concluded on the subject yet.
+In the meantime, I learnt lessons at home. Shall I ever forget those
+lessons! They were presided over nominally by my mother, but really by
+Mr. Murdstone and his sister, who were always present, and found them
+a favourable occasion for giving my mother lessons in that miscalled
+firmness, which was the bane of both our lives. I believe I was kept
+at home for that purpose. I had been apt enough to learn, and willing
+enough, when my mother and I had lived alone together. I can faintly
+remember learning the alphabet at her knee. To this day, when I look
+upon the fat black letters in the primer, the puzzling novelty of their
+shapes, and the easy good-nature of O and Q and S, seem to present
+themselves again before me as they used to do. But they recall no
+feeling of disgust or reluctance. On the contrary, I seem to have walked
+along a path of flowers as far as the crocodile-book, and to have been
+cheered by the gentleness of my mother's voice and manner all the
+way. But these solemn lessons which succeeded those, I remember as the
+death-blow of my peace, and a grievous daily drudgery and misery. They
+were very long, very numerous, very hard--perfectly unintelligible,
+some of them, to me--and I was generally as much bewildered by them as I
+believe my poor mother was herself.
+
+Let me remember how it used to be, and bring one morning back again.
+
+I come into the second-best parlour after breakfast, with my books,
+and an exercise-book, and a slate. My mother is ready for me at her
+writing-desk, but not half so ready as Mr. Murdstone in his easy-chair
+by the window (though he pretends to be reading a book), or as Miss
+Murdstone, sitting near my mother stringing steel beads. The very sight
+of these two has such an influence over me, that I begin to feel the
+words I have been at infinite pains to get into my head, all sliding
+away, and going I don't know where. I wonder where they do go, by the
+by?
+
+I hand the first book to my mother. Perhaps it is a grammar, perhaps a
+history, or geography. I take a last drowning look at the page as I give
+it into her hand, and start off aloud at a racing pace while I have
+got it fresh. I trip over a word. Mr. Murdstone looks up. I trip
+over another word. Miss Murdstone looks up. I redden, tumble over
+half-a-dozen words, and stop. I think my mother would show me the book
+if she dared, but she does not dare, and she says softly:
+
+'Oh, Davy, Davy!'
+
+'Now, Clara,' says Mr. Murdstone, 'be firm with the boy. Don't say, "Oh,
+Davy, Davy!" That's childish. He knows his lesson, or he does not know
+it.'
+
+'He does NOT know it,' Miss Murdstone interposes awfully.
+
+'I am really afraid he does not,' says my mother.
+
+'Then, you see, Clara,' returns Miss Murdstone, 'you should just give
+him the book back, and make him know it.'
+
+'Yes, certainly,' says my mother; 'that is what I intend to do, my dear
+Jane. Now, Davy, try once more, and don't be stupid.'
+
+I obey the first clause of the injunction by trying once more, but am
+not so successful with the second, for I am very stupid. I tumble down
+before I get to the old place, at a point where I was all right before,
+and stop to think. But I can't think about the lesson. I think of the
+number of yards of net in Miss Murdstone's cap, or of the price of Mr.
+Murdstone's dressing-gown, or any such ridiculous problem that I have
+no business with, and don't want to have anything at all to do with. Mr.
+Murdstone makes a movement of impatience which I have been expecting
+for a long time. Miss Murdstone does the same. My mother glances
+submissively at them, shuts the book, and lays it by as an arrear to be
+worked out when my other tasks are done.
+
+There is a pile of these arrears very soon, and it swells like a rolling
+snowball. The bigger it gets, the more stupid I get. The case is so
+hopeless, and I feel that I am wallowing in such a bog of nonsense, that
+I give up all idea of getting out, and abandon myself to my fate. The
+despairing way in which my mother and I look at each other, as I blunder
+on, is truly melancholy. But the greatest effect in these miserable
+lessons is when my mother (thinking nobody is observing her) tries
+to give me the cue by the motion of her lips. At that instant, Miss
+Murdstone, who has been lying in wait for nothing else all along, says
+in a deep warning voice:
+
+'Clara!'
+
+My mother starts, colours, and smiles faintly. Mr. Murdstone comes out
+of his chair, takes the book, throws it at me or boxes my ears with it,
+and turns me out of the room by the shoulders.
+
+Even when the lessons are done, the worst is yet to happen, in the shape
+of an appalling sum. This is invented for me, and delivered to me orally
+by Mr. Murdstone, and begins, 'If I go into a cheesemonger's shop, and
+buy five thousand double-Gloucester cheeses at fourpence-halfpenny each,
+present payment'--at which I see Miss Murdstone secretly overjoyed.
+I pore over these cheeses without any result or enlightenment until
+dinner-time, when, having made a Mulatto of myself by getting the dirt
+of the slate into the pores of my skin, I have a slice of bread to help
+me out with the cheeses, and am considered in disgrace for the rest of
+the evening.
+
+It seems to me, at this distance of time, as if my unfortunate studies
+generally took this course. I could have done very well if I had been
+without the Murdstones; but the influence of the Murdstones upon me was
+like the fascination of two snakes on a wretched young bird. Even when
+I did get through the morning with tolerable credit, there was not
+much gained but dinner; for Miss Murdstone never could endure to see me
+untasked, and if I rashly made any show of being unemployed, called her
+brother's attention to me by saying, 'Clara, my dear, there's nothing
+like work--give your boy an exercise'; which caused me to be clapped
+down to some new labour, there and then. As to any recreation with other
+children of my age, I had very little of that; for the gloomy theology
+of the Murdstones made all children out to be a swarm of little vipers
+(though there WAS a child once set in the midst of the Disciples), and
+held that they contaminated one another.
+
+The natural result of this treatment, continued, I suppose, for some six
+months or more, was to make me sullen, dull, and dogged. I was not
+made the less so by my sense of being daily more and more shut out and
+alienated from my mother. I believe I should have been almost stupefied
+but for one circumstance.
+
+It was this. My father had left a small collection of books in a little
+room upstairs, to which I had access (for it adjoined my own) and which
+nobody else in our house ever troubled. From that blessed little room,
+Roderick Random, Peregrine Pickle, Humphrey Clinker, Tom Jones, the
+Vicar of Wakefield, Don Quixote, Gil Blas, and Robinson Crusoe, came
+out, a glorious host, to keep me company. They kept alive my fancy, and
+my hope of something beyond that place and time,--they, and the Arabian
+Nights, and the Tales of the Genii,--and did me no harm; for whatever
+harm was in some of them was not there for me; I knew nothing of it. It
+is astonishing to me now, how I found time, in the midst of my porings
+and blunderings over heavier themes, to read those books as I did. It
+is curious to me how I could ever have consoled myself under my
+small troubles (which were great troubles to me), by impersonating my
+favourite characters in them--as I did--and by putting Mr. and Miss
+Murdstone into all the bad ones--which I did too. I have been Tom Jones
+(a child's Tom Jones, a harmless creature) for a week together. I have
+sustained my own idea of Roderick Random for a month at a stretch, I
+verily believe. I had a greedy relish for a few volumes of Voyages and
+Travels--I forget what, now--that were on those shelves; and for days
+and days I can remember to have gone about my region of our house,
+armed with the centre-piece out of an old set of boot-trees--the perfect
+realization of Captain Somebody, of the Royal British Navy, in danger of
+being beset by savages, and resolved to sell his life at a great price.
+The Captain never lost dignity, from having his ears boxed with the
+Latin Grammar. I did; but the Captain was a Captain and a hero, in
+despite of all the grammars of all the languages in the world, dead or
+alive.
+
+This was my only and my constant comfort. When I think of it, the
+picture always rises in my mind, of a summer evening, the boys at play
+in the churchyard, and I sitting on my bed, reading as if for life.
+Every barn in the neighbourhood, every stone in the church, and every
+foot of the churchyard, had some association of its own, in my mind,
+connected with these books, and stood for some locality made famous in
+them. I have seen Tom Pipes go climbing up the church-steeple; I have
+watched Strap, with the knapsack on his back, stopping to rest himself
+upon the wicket-gate; and I know that Commodore Trunnion held that club
+with Mr. Pickle, in the parlour of our little village alehouse.
+
+The reader now understands, as well as I do, what I was when I came to
+that point of my youthful history to which I am now coming again.
+
+One morning when I went into the parlour with my books, I found my
+mother looking anxious, Miss Murdstone looking firm, and Mr. Murdstone
+binding something round the bottom of a cane--a lithe and limber cane,
+which he left off binding when I came in, and poised and switched in the
+air.
+
+'I tell you, Clara,' said Mr. Murdstone, 'I have been often flogged
+myself.'
+
+'To be sure; of course,' said Miss Murdstone.
+
+'Certainly, my dear Jane,' faltered my mother, meekly. 'But--but do you
+think it did Edward good?'
+
+'Do you think it did Edward harm, Clara?' asked Mr. Murdstone, gravely.
+
+'That's the point,' said his sister.
+
+To this my mother returned, 'Certainly, my dear Jane,' and said no more.
+
+I felt apprehensive that I was personally interested in this dialogue,
+and sought Mr. Murdstone's eye as it lighted on mine.
+
+'Now, David,' he said--and I saw that cast again as he said it--'you
+must be far more careful today than usual.' He gave the cane another
+poise, and another switch; and having finished his preparation of it,
+laid it down beside him, with an impressive look, and took up his book.
+
+This was a good freshener to my presence of mind, as a beginning. I felt
+the words of my lessons slipping off, not one by one, or line by line,
+but by the entire page; I tried to lay hold of them; but they seemed,
+if I may so express it, to have put skates on, and to skim away from me
+with a smoothness there was no checking.
+
+We began badly, and went on worse. I had come in with an idea of
+distinguishing myself rather, conceiving that I was very well prepared;
+but it turned out to be quite a mistake. Book after book was added to
+the heap of failures, Miss Murdstone being firmly watchful of us all the
+time. And when we came at last to the five thousand cheeses (canes he
+made it that day, I remember), my mother burst out crying.
+
+'Clara!' said Miss Murdstone, in her warning voice.
+
+'I am not quite well, my dear Jane, I think,' said my mother.
+
+I saw him wink, solemnly, at his sister, as he rose and said, taking up
+the cane:
+
+'Why, Jane, we can hardly expect Clara to bear, with perfect firmness,
+the worry and torment that David has occasioned her today. That would be
+stoical. Clara is greatly strengthened and improved, but we can hardly
+expect so much from her. David, you and I will go upstairs, boy.'
+
+As he took me out at the door, my mother ran towards us. Miss Murdstone
+said, 'Clara! are you a perfect fool?' and interfered. I saw my mother
+stop her ears then, and I heard her crying.
+
+He walked me up to my room slowly and gravely--I am certain he had a
+delight in that formal parade of executing justice--and when we got
+there, suddenly twisted my head under his arm.
+
+'Mr. Murdstone! Sir!' I cried to him. 'Don't! Pray don't beat me! I have
+tried to learn, sir, but I can't learn while you and Miss Murdstone are
+by. I can't indeed!'
+
+'Can't you, indeed, David?' he said. 'We'll try that.'
+
+He had my head as in a vice, but I twined round him somehow, and stopped
+him for a moment, entreating him not to beat me. It was only a moment
+that I stopped him, for he cut me heavily an instant afterwards, and in
+the same instant I caught the hand with which he held me in my mouth,
+between my teeth, and bit it through. It sets my teeth on edge to think
+of it.
+
+He beat me then, as if he would have beaten me to death. Above all the
+noise we made, I heard them running up the stairs, and crying out--I
+heard my mother crying out--and Peggotty. Then he was gone; and the
+door was locked outside; and I was lying, fevered and hot, and torn, and
+sore, and raging in my puny way, upon the floor.
+
+How well I recollect, when I became quiet, what an unnatural stillness
+seemed to reign through the whole house! How well I remember, when my
+smart and passion began to cool, how wicked I began to feel!
+
+I sat listening for a long while, but there was not a sound. I crawled
+up from the floor, and saw my face in the glass, so swollen, red, and
+ugly that it almost frightened me. My stripes were sore and stiff, and
+made me cry afresh, when I moved; but they were nothing to the guilt I
+felt. It lay heavier on my breast than if I had been a most atrocious
+criminal, I dare say.
+
+It had begun to grow dark, and I had shut the window (I had been lying,
+for the most part, with my head upon the sill, by turns crying, dozing,
+and looking listlessly out), when the key was turned, and Miss Murdstone
+came in with some bread and meat, and milk. These she put down upon the
+table without a word, glaring at me the while with exemplary firmness,
+and then retired, locking the door after her.
+
+Long after it was dark I sat there, wondering whether anybody else would
+come. When this appeared improbable for that night, I undressed, and
+went to bed; and, there, I began to wonder fearfully what would be done
+to me. Whether it was a criminal act that I had committed? Whether I
+should be taken into custody, and sent to prison? Whether I was at all
+in danger of being hanged?
+
+I never shall forget the waking, next morning; the being cheerful and
+fresh for the first moment, and then the being weighed down by the stale
+and dismal oppression of remembrance. Miss Murdstone reappeared before
+I was out of bed; told me, in so many words, that I was free to walk in
+the garden for half an hour and no longer; and retired, leaving the door
+open, that I might avail myself of that permission.
+
+I did so, and did so every morning of my imprisonment, which lasted five
+days. If I could have seen my mother alone, I should have gone down on
+my knees to her and besought her forgiveness; but I saw no one, Miss
+Murdstone excepted, during the whole time--except at evening prayers in
+the parlour; to which I was escorted by Miss Murdstone after everybody
+else was placed; where I was stationed, a young outlaw, all alone by
+myself near the door; and whence I was solemnly conducted by my jailer,
+before any one arose from the devotional posture. I only observed that
+my mother was as far off from me as she could be, and kept her face
+another way so that I never saw it; and that Mr. Murdstone's hand was
+bound up in a large linen wrapper.
+
+The length of those five days I can convey no idea of to any one. They
+occupy the place of years in my remembrance. The way in which I listened
+to all the incidents of the house that made themselves audible to me;
+the ringing of bells, the opening and shutting of doors, the murmuring
+of voices, the footsteps on the stairs; to any laughing, whistling, or
+singing, outside, which seemed more dismal than anything else to me in
+my solitude and disgrace--the uncertain pace of the hours, especially
+at night, when I would wake thinking it was morning, and find that the
+family were not yet gone to bed, and that all the length of night had
+yet to come--the depressed dreams and nightmares I had--the return of
+day, noon, afternoon, evening, when the boys played in the churchyard,
+and I watched them from a distance within the room, being ashamed to
+show myself at the window lest they should know I was a prisoner--the
+strange sensation of never hearing myself speak--the fleeting intervals
+of something like cheerfulness, which came with eating and drinking,
+and went away with it--the setting in of rain one evening, with a fresh
+smell, and its coming down faster and faster between me and the church,
+until it and gathering night seemed to quench me in gloom, and fear, and
+remorse--all this appears to have gone round and round for years instead
+of days, it is so vividly and strongly stamped on my remembrance. On the
+last night of my restraint, I was awakened by hearing my own name spoken
+in a whisper. I started up in bed, and putting out my arms in the dark,
+said:
+
+'Is that you, Peggotty?'
+
+There was no immediate answer, but presently I heard my name again, in a
+tone so very mysterious and awful, that I think I should have gone into
+a fit, if it had not occurred to me that it must have come through the
+keyhole.
+
+I groped my way to the door, and putting my own lips to the keyhole,
+whispered: 'Is that you, Peggotty dear?'
+
+'Yes, my own precious Davy,' she replied. 'Be as soft as a mouse, or the
+Cat'll hear us.'
+
+I understood this to mean Miss Murdstone, and was sensible of the
+urgency of the case; her room being close by.
+
+'How's mama, dear Peggotty? Is she very angry with me?'
+
+I could hear Peggotty crying softly on her side of the keyhole, as I was
+doing on mine, before she answered. 'No. Not very.'
+
+'What is going to be done with me, Peggotty dear? Do you know?'
+
+'School. Near London,' was Peggotty's answer. I was obliged to get her
+to repeat it, for she spoke it the first time quite down my throat,
+in consequence of my having forgotten to take my mouth away from the
+keyhole and put my ear there; and though her words tickled me a good
+deal, I didn't hear them.
+
+'When, Peggotty?'
+
+'Tomorrow.'
+
+'Is that the reason why Miss Murdstone took the clothes out of my
+drawers?' which she had done, though I have forgotten to mention it.
+
+'Yes,' said Peggotty. 'Box.'
+
+'Shan't I see mama?'
+
+'Yes,' said Peggotty. 'Morning.'
+
+Then Peggotty fitted her mouth close to the keyhole, and delivered these
+words through it with as much feeling and earnestness as a keyhole
+has ever been the medium of communicating, I will venture to assert:
+shooting in each broken little sentence in a convulsive little burst of
+its own.
+
+'Davy, dear. If I ain't been azackly as intimate with you. Lately, as I
+used to be. It ain't because I don't love you. Just as well and more, my
+pretty poppet. It's because I thought it better for you. And for someone
+else besides. Davy, my darling, are you listening? Can you hear?'
+
+'Ye-ye-ye-yes, Peggotty!' I sobbed.
+
+'My own!' said Peggotty, with infinite compassion. 'What I want to say,
+is. That you must never forget me. For I'll never forget you. And I'll
+take as much care of your mama, Davy. As ever I took of you. And I won't
+leave her. The day may come when she'll be glad to lay her poor head.
+On her stupid, cross old Peggotty's arm again. And I'll write to you,
+my dear. Though I ain't no scholar. And I'll--I'll--' Peggotty fell to
+kissing the keyhole, as she couldn't kiss me.
+
+'Thank you, dear Peggotty!' said I. 'Oh, thank you! Thank you! Will you
+promise me one thing, Peggotty? Will you write and tell Mr. Peggotty and
+little Em'ly, and Mrs. Gummidge and Ham, that I am not so bad as they
+might suppose, and that I sent 'em all my love--especially to little
+Em'ly? Will you, if you please, Peggotty?'
+
+The kind soul promised, and we both of us kissed the keyhole with the
+greatest affection--I patted it with my hand, I recollect, as if it had
+been her honest face--and parted. From that night there grew up in my
+breast a feeling for Peggotty which I cannot very well define. She did
+not replace my mother; no one could do that; but she came into a vacancy
+in my heart, which closed upon her, and I felt towards her something
+I have never felt for any other human being. It was a sort of comical
+affection, too; and yet if she had died, I cannot think what I should
+have done, or how I should have acted out the tragedy it would have been
+to me.
+
+In the morning Miss Murdstone appeared as usual, and told me I was going
+to school; which was not altogether such news to me as she supposed. She
+also informed me that when I was dressed, I was to come downstairs into
+the parlour, and have my breakfast. There, I found my mother, very pale
+and with red eyes: into whose arms I ran, and begged her pardon from my
+suffering soul.
+
+'Oh, Davy!' she said. 'That you could hurt anyone I love! Try to be
+better, pray to be better! I forgive you; but I am so grieved, Davy,
+that you should have such bad passions in your heart.'
+
+They had persuaded her that I was a wicked fellow, and she was more
+sorry for that than for my going away. I felt it sorely. I tried to eat
+my parting breakfast, but my tears dropped upon my bread-and-butter,
+and trickled into my tea. I saw my mother look at me sometimes, and then
+glance at the watchful Miss Murdstone, and than look down, or look away.
+
+'Master Copperfield's box there!' said Miss Murdstone, when wheels were
+heard at the gate.
+
+I looked for Peggotty, but it was not she; neither she nor Mr. Murdstone
+appeared. My former acquaintance, the carrier, was at the door. The box
+was taken out to his cart, and lifted in.
+
+'Clara!' said Miss Murdstone, in her warning note.
+
+'Ready, my dear Jane,' returned my mother. 'Good-bye, Davy. You are
+going for your own good. Good-bye, my child. You will come home in the
+holidays, and be a better boy.'
+
+'Clara!' Miss Murdstone repeated.
+
+'Certainly, my dear Jane,' replied my mother, who was holding me. 'I
+forgive you, my dear boy. God bless you!'
+
+'Clara!' Miss Murdstone repeated.
+
+Miss Murdstone was good enough to take me out to the cart, and to say on
+the way that she hoped I would repent, before I came to a bad end; and
+then I got into the cart, and the lazy horse walked off with it.
+
+
+
+CHAPTER 5. I AM SENT AWAY FROM HOME
+
+
+We might have gone about half a mile, and my pocket-handkerchief was
+quite wet through, when the carrier stopped short. Looking out to
+ascertain for what, I saw, to MY amazement, Peggotty burst from a hedge
+and climb into the cart. She took me in both her arms, and squeezed me
+to her stays until the pressure on my nose was extremely painful, though
+I never thought of that till afterwards when I found it very tender. Not
+a single word did Peggotty speak. Releasing one of her arms, she put
+it down in her pocket to the elbow, and brought out some paper bags of
+cakes which she crammed into my pockets, and a purse which she put into
+my hand, but not one word did she say. After another and a final squeeze
+with both arms, she got down from the cart and ran away; and, my belief
+is, and has always been, without a solitary button on her gown. I
+picked up one, of several that were rolling about, and treasured it as a
+keepsake for a long time.
+
+The carrier looked at me, as if to inquire if she were coming back. I
+shook my head, and said I thought not. 'Then come up,' said the carrier
+to the lazy horse; who came up accordingly.
+
+Having by this time cried as much as I possibly could, I began to think
+it was of no use crying any more, especially as neither Roderick Random,
+nor that Captain in the Royal British Navy, had ever cried, that I
+could remember, in trying situations. The carrier, seeing me in this
+resolution, proposed that my pocket-handkerchief should be spread upon
+the horse's back to dry. I thanked him, and assented; and particularly
+small it looked, under those circumstances.
+
+I had now leisure to examine the purse. It was a stiff leather purse,
+with a snap, and had three bright shillings in it, which Peggotty had
+evidently polished up with whitening, for my greater delight. But its
+most precious contents were two half-crowns folded together in a bit
+of paper, on which was written, in my mother's hand, 'For Davy. With my
+love.' I was so overcome by this, that I asked the carrier to be so good
+as to reach me my pocket-handkerchief again; but he said he thought I
+had better do without it, and I thought I really had, so I wiped my eyes
+on my sleeve and stopped myself.
+
+For good, too; though, in consequence of my previous emotions, I was
+still occasionally seized with a stormy sob. After we had jogged on for
+some little time, I asked the carrier if he was going all the way.
+
+'All the way where?' inquired the carrier.
+
+'There,' I said.
+
+'Where's there?' inquired the carrier.
+
+'Near London,' I said.
+
+'Why that horse,' said the carrier, jerking the rein to point him out,
+'would be deader than pork afore he got over half the ground.'
+
+'Are you only going to Yarmouth then?' I asked.
+
+'That's about it,' said the carrier. 'And there I shall take you to the
+stage-cutch, and the stage-cutch that'll take you to--wherever it is.'
+
+As this was a great deal for the carrier (whose name was Mr. Barkis)
+to say--he being, as I observed in a former chapter, of a phlegmatic
+temperament, and not at all conversational--I offered him a cake as a
+mark of attention, which he ate at one gulp, exactly like an elephant,
+and which made no more impression on his big face than it would have
+done on an elephant's.
+
+'Did SHE make 'em, now?' said Mr. Barkis, always leaning forward, in his
+slouching way, on the footboard of the cart with an arm on each knee.
+
+'Peggotty, do you mean, sir?'
+
+'Ah!' said Mr. Barkis. 'Her.'
+
+'Yes. She makes all our pastry, and does all our cooking.'
+
+'Do she though?' said Mr. Barkis. He made up his mouth as if to whistle,
+but he didn't whistle. He sat looking at the horse's ears, as if he saw
+something new there; and sat so, for a considerable time. By and by, he
+said:
+
+'No sweethearts, I b'lieve?'
+
+'Sweetmeats did you say, Mr. Barkis?' For I thought he wanted
+something else to eat, and had pointedly alluded to that description of
+refreshment.
+
+'Hearts,' said Mr. Barkis. 'Sweet hearts; no person walks with her!'
+
+'With Peggotty?'
+
+'Ah!' he said. 'Her.'
+
+'Oh, no. She never had a sweetheart.'
+
+'Didn't she, though!' said Mr. Barkis.
+
+Again he made up his mouth to whistle, and again he didn't whistle, but
+sat looking at the horse's ears.
+
+'So she makes,' said Mr. Barkis, after a long interval of reflection,
+'all the apple parsties, and doos all the cooking, do she?'
+
+I replied that such was the fact.
+
+'Well. I'll tell you what,' said Mr. Barkis. 'P'raps you might be
+writin' to her?'
+
+'I shall certainly write to her,' I rejoined.
+
+'Ah!' he said, slowly turning his eyes towards me. 'Well! If you was
+writin' to her, p'raps you'd recollect to say that Barkis was willin';
+would you?'
+
+'That Barkis is willing,' I repeated, innocently. 'Is that all the
+message?'
+
+'Ye-es,' he said, considering. 'Ye-es. Barkis is willin'.'
+
+'But you will be at Blunderstone again tomorrow, Mr. Barkis,' I said,
+faltering a little at the idea of my being far away from it then, and
+could give your own message so much better.'
+
+As he repudiated this suggestion, however, with a jerk of his head,
+and once more confirmed his previous request by saying, with profound
+gravity, 'Barkis is willin'. That's the message,' I readily undertook
+its transmission. While I was waiting for the coach in the hotel
+at Yarmouth that very afternoon, I procured a sheet of paper and
+an inkstand, and wrote a note to Peggotty, which ran thus: 'My dear
+Peggotty. I have come here safe. Barkis is willing. My love to mama.
+Yours affectionately. P.S. He says he particularly wants you to
+know--BARKIS IS WILLING.'
+
+When I had taken this commission on myself prospectively, Mr. Barkis
+relapsed into perfect silence; and I, feeling quite worn out by all that
+had happened lately, lay down on a sack in the cart and fell asleep. I
+slept soundly until we got to Yarmouth; which was so entirely new
+and strange to me in the inn-yard to which we drove, that I at once
+abandoned a latent hope I had had of meeting with some of Mr. Peggotty's
+family there, perhaps even with little Em'ly herself.
+
+The coach was in the yard, shining very much all over, but without any
+horses to it as yet; and it looked in that state as if nothing was
+more unlikely than its ever going to London. I was thinking this, and
+wondering what would ultimately become of my box, which Mr. Barkis had
+put down on the yard-pavement by the pole (he having driven up the yard
+to turn his cart), and also what would ultimately become of me, when a
+lady looked out of a bow-window where some fowls and joints of meat were
+hanging up, and said:
+
+'Is that the little gentleman from Blunderstone?'
+
+'Yes, ma'am,' I said.
+
+'What name?' inquired the lady.
+
+'Copperfield, ma'am,' I said.
+
+'That won't do,' returned the lady. 'Nobody's dinner is paid for here,
+in that name.'
+
+'Is it Murdstone, ma'am?' I said.
+
+'If you're Master Murdstone,' said the lady, 'why do you go and give
+another name, first?'
+
+I explained to the lady how it was, who than rang a bell, and called
+out, 'William! show the coffee-room!' upon which a waiter came running
+out of a kitchen on the opposite side of the yard to show it, and seemed
+a good deal surprised when he was only to show it to me.
+
+It was a large long room with some large maps in it. I doubt if I could
+have felt much stranger if the maps had been real foreign countries, and
+I cast away in the middle of them. I felt it was taking a liberty to
+sit down, with my cap in my hand, on the corner of the chair nearest the
+door; and when the waiter laid a cloth on purpose for me, and put a set
+of castors on it, I think I must have turned red all over with modesty.
+
+He brought me some chops, and vegetables, and took the covers off in
+such a bouncing manner that I was afraid I must have given him some
+offence. But he greatly relieved my mind by putting a chair for me at
+the table, and saying, very affably, 'Now, six-foot! come on!'
+
+I thanked him, and took my seat at the board; but found it extremely
+difficult to handle my knife and fork with anything like dexterity,
+or to avoid splashing myself with the gravy, while he was standing
+opposite, staring so hard, and making me blush in the most dreadful
+manner every time I caught his eye. After watching me into the second
+chop, he said:
+
+'There's half a pint of ale for you. Will you have it now?'
+
+I thanked him and said, 'Yes.' Upon which he poured it out of a jug
+into a large tumbler, and held it up against the light, and made it look
+beautiful.
+
+'My eye!' he said. 'It seems a good deal, don't it?'
+
+'It does seem a good deal,' I answered with a smile. For it was quite
+delightful to me, to find him so pleasant. He was a twinkling-eyed,
+pimple-faced man, with his hair standing upright all over his head; and
+as he stood with one arm a-kimbo, holding up the glass to the light with
+the other hand, he looked quite friendly.
+
+'There was a gentleman here, yesterday,' he said--'a stout gentleman, by
+the name of Topsawyer--perhaps you know him?'
+
+'No,' I said, 'I don't think--'
+
+'In breeches and gaiters, broad-brimmed hat, grey coat, speckled
+choker,' said the waiter.
+
+'No,' I said bashfully, 'I haven't the pleasure--'
+
+'He came in here,' said the waiter, looking at the light through the
+tumbler, 'ordered a glass of this ale--WOULD order it--I told him
+not--drank it, and fell dead. It was too old for him. It oughtn't to be
+drawn; that's the fact.'
+
+I was very much shocked to hear of this melancholy accident, and said I
+thought I had better have some water.
+
+'Why you see,' said the waiter, still looking at the light through the
+tumbler, with one of his eyes shut up, 'our people don't like things
+being ordered and left. It offends 'em. But I'll drink it, if you like.
+I'm used to it, and use is everything. I don't think it'll hurt me, if I
+throw my head back, and take it off quick. Shall I?'
+
+I replied that he would much oblige me by drinking it, if he thought
+he could do it safely, but by no means otherwise. When he did throw his
+head back, and take it off quick, I had a horrible fear, I confess,
+of seeing him meet the fate of the lamented Mr. Topsawyer, and fall
+lifeless on the carpet. But it didn't hurt him. On the contrary, I
+thought he seemed the fresher for it.
+
+'What have we got here?' he said, putting a fork into my dish. 'Not
+chops?'
+
+'Chops,' I said.
+
+'Lord bless my soul!' he exclaimed, 'I didn't know they were chops. Why,
+a chop's the very thing to take off the bad effects of that beer! Ain't
+it lucky?'
+
+So he took a chop by the bone in one hand, and a potato in the other,
+and ate away with a very good appetite, to my extreme satisfaction.
+He afterwards took another chop, and another potato; and after that,
+another chop and another potato. When we had done, he brought me a
+pudding, and having set it before me, seemed to ruminate, and to become
+absent in his mind for some moments.
+
+'How's the pie?' he said, rousing himself.
+
+'It's a pudding,' I made answer.
+
+'Pudding!' he exclaimed. 'Why, bless me, so it is! What!' looking at it
+nearer. 'You don't mean to say it's a batter-pudding!'
+
+'Yes, it is indeed.'
+
+'Why, a batter-pudding,' he said, taking up a table-spoon, 'is my
+favourite pudding! Ain't that lucky? Come on, little 'un, and let's see
+who'll get most.'
+
+The waiter certainly got most. He entreated me more than once to come in
+and win, but what with his table-spoon to my tea-spoon, his dispatch to
+my dispatch, and his appetite to my appetite, I was left far behind at
+the first mouthful, and had no chance with him. I never saw anyone enjoy
+a pudding so much, I think; and he laughed, when it was all gone, as if
+his enjoyment of it lasted still.
+
+Finding him so very friendly and companionable, it was then that I asked
+for the pen and ink and paper, to write to Peggotty. He not only brought
+it immediately, but was good enough to look over me while I wrote the
+letter. When I had finished it, he asked me where I was going to school.
+
+I said, 'Near London,' which was all I knew.
+
+'Oh! my eye!' he said, looking very low-spirited, 'I am sorry for that.'
+
+'Why?' I asked him.
+
+'Oh, Lord!' he said, shaking his head, 'that's the school where they
+broke the boy's ribs--two ribs--a little boy he was. I should say he
+was--let me see--how old are you, about?'
+
+I told him between eight and nine.
+
+'That's just his age,' he said. 'He was eight years and six months old
+when they broke his first rib; eight years and eight months old when
+they broke his second, and did for him.'
+
+I could not disguise from myself, or from the waiter, that this was an
+uncomfortable coincidence, and inquired how it was done. His answer was
+not cheering to my spirits, for it consisted of two dismal words, 'With
+whopping.'
+
+The blowing of the coach-horn in the yard was a seasonable diversion,
+which made me get up and hesitatingly inquire, in the mingled pride and
+diffidence of having a purse (which I took out of my pocket), if there
+were anything to pay.
+
+'There's a sheet of letter-paper,' he returned. 'Did you ever buy a
+sheet of letter-paper?'
+
+I could not remember that I ever had.
+
+'It's dear,' he said, 'on account of the duty. Threepence. That's
+the way we're taxed in this country. There's nothing else, except the
+waiter. Never mind the ink. I lose by that.'
+
+'What should you--what should I--how much ought I to--what would it be
+right to pay the waiter, if you please?' I stammered, blushing.
+
+'If I hadn't a family, and that family hadn't the cowpock,' said the
+waiter, 'I wouldn't take a sixpence. If I didn't support a aged pairint,
+and a lovely sister,'--here the waiter was greatly agitated--'I wouldn't
+take a farthing. If I had a good place, and was treated well here, I
+should beg acceptance of a trifle, instead of taking of it. But I live
+on broken wittles--and I sleep on the coals'--here the waiter burst into
+tears.
+
+I was very much concerned for his misfortunes, and felt that any
+recognition short of ninepence would be mere brutality and hardness of
+heart. Therefore I gave him one of my three bright shillings, which he
+received with much humility and veneration, and spun up with his thumb,
+directly afterwards, to try the goodness of.
+
+It was a little disconcerting to me, to find, when I was being helped
+up behind the coach, that I was supposed to have eaten all the dinner
+without any assistance. I discovered this, from overhearing the lady in
+the bow-window say to the guard, 'Take care of that child, George, or
+he'll burst!' and from observing that the women-servants who were about
+the place came out to look and giggle at me as a young phenomenon. My
+unfortunate friend the waiter, who had quite recovered his spirits, did
+not appear to be disturbed by this, but joined in the general admiration
+without being at all confused. If I had any doubt of him, I suppose
+this half awakened it; but I am inclined to believe that with the simple
+confidence of a child, and the natural reliance of a child upon superior
+years (qualities I am very sorry any children should prematurely change
+for worldly wisdom), I had no serious mistrust of him on the whole, even
+then.
+
+I felt it rather hard, I must own, to be made, without deserving it, the
+subject of jokes between the coachman and guard as to the coach drawing
+heavy behind, on account of my sitting there, and as to the greater
+expediency of my travelling by waggon. The story of my supposed appetite
+getting wind among the outside passengers, they were merry upon it
+likewise; and asked me whether I was going to be paid for, at school,
+as two brothers or three, and whether I was contracted for, or went upon
+the regular terms; with other pleasant questions. But the worst of
+it was, that I knew I should be ashamed to eat anything, when an
+opportunity offered, and that, after a rather light dinner, I should
+remain hungry all night--for I had left my cakes behind, at the hotel,
+in my hurry. My apprehensions were realized. When we stopped for supper
+I couldn't muster courage to take any, though I should have liked it
+very much, but sat by the fire and said I didn't want anything. This did
+not save me from more jokes, either; for a husky-voiced gentleman with
+a rough face, who had been eating out of a sandwich-box nearly all the
+way, except when he had been drinking out of a bottle, said I was like
+a boa-constrictor who took enough at one meal to last him a long time;
+after which, he actually brought a rash out upon himself with boiled
+beef.
+
+We had started from Yarmouth at three o'clock in the afternoon, and we
+were due in London about eight next morning. It was Mid-summer weather,
+and the evening was very pleasant. When we passed through a village, I
+pictured to myself what the insides of the houses were like, and what
+the inhabitants were about; and when boys came running after us, and
+got up behind and swung there for a little way, I wondered whether their
+fathers were alive, and whether they Were happy at home. I had plenty to
+think of, therefore, besides my mind running continually on the kind
+of place I was going to--which was an awful speculation. Sometimes, I
+remember, I resigned myself to thoughts of home and Peggotty; and to
+endeavouring, in a confused blind way, to recall how I had felt, and
+what sort of boy I used to be, before I bit Mr. Murdstone: which I
+couldn't satisfy myself about by any means, I seemed to have bitten him
+in such a remote antiquity.
+
+The night was not so pleasant as the evening, for it got chilly; and
+being put between two gentlemen (the rough-faced one and another) to
+prevent my tumbling off the coach, I was nearly smothered by their
+falling asleep, and completely blocking me up. They squeezed me so hard
+sometimes, that I could not help crying out, 'Oh! If you please!'--which
+they didn't like at all, because it woke them. Opposite me was an
+elderly lady in a great fur cloak, who looked in the dark more like a
+haystack than a lady, she was wrapped up to such a degree. This lady had
+a basket with her, and she hadn't known what to do with it, for a long
+time, until she found that on account of my legs being short, it could
+go underneath me. It cramped and hurt me so, that it made me perfectly
+miserable; but if I moved in the least, and made a glass that was in the
+basket rattle against something else (as it was sure to do), she gave
+me the cruellest poke with her foot, and said, 'Come, don't YOU fidget.
+YOUR bones are young enough, I'm sure!'
+
+At last the sun rose, and then my companions seemed to sleep easier.
+The difficulties under which they had laboured all night, and which had
+found utterance in the most terrific gasps and snorts, are not to be
+conceived. As the sun got higher, their sleep became lighter, and so
+they gradually one by one awoke. I recollect being very much surprised
+by the feint everybody made, then, of not having been to sleep at all,
+and by the uncommon indignation with which everyone repelled the
+charge. I labour under the same kind of astonishment to this day, having
+invariably observed that of all human weaknesses, the one to which our
+common nature is the least disposed to confess (I cannot imagine why) is
+the weakness of having gone to sleep in a coach.
+
+What an amazing place London was to me when I saw it in the distance,
+and how I believed all the adventures of all my favourite heroes to be
+constantly enacting and re-enacting there, and how I vaguely made it
+out in my own mind to be fuller of wonders and wickedness than all the
+cities of the earth, I need not stop here to relate. We approached it by
+degrees, and got, in due time, to the inn in the Whitechapel district,
+for which we were bound. I forget whether it was the Blue Bull, or the
+Blue Boar; but I know it was the Blue Something, and that its likeness
+was painted up on the back of the coach.
+
+The guard's eye lighted on me as he was getting down, and he said at the
+booking-office door:
+
+'Is there anybody here for a yoongster booked in the name of Murdstone,
+from Bloonderstone, Sooffolk, to be left till called for?'
+
+Nobody answered.
+
+'Try Copperfield, if you please, sir,' said I, looking helplessly down.
+
+'Is there anybody here for a yoongster, booked in the name of Murdstone,
+from Bloonderstone, Sooffolk, but owning to the name of Copperfield, to
+be left till called for?' said the guard. 'Come! IS there anybody?'
+
+No. There was nobody. I looked anxiously around; but the inquiry made no
+impression on any of the bystanders, if I except a man in gaiters, with
+one eye, who suggested that they had better put a brass collar round my
+neck, and tie me up in the stable.
+
+A ladder was brought, and I got down after the lady, who was like a
+haystack: not daring to stir, until her basket was removed. The coach
+was clear of passengers by that time, the luggage was very soon cleared
+out, the horses had been taken out before the luggage, and now the coach
+itself was wheeled and backed off by some hostlers, out of the way.
+Still, nobody appeared, to claim the dusty youngster from Blunderstone,
+Suffolk.
+
+More solitary than Robinson Crusoe, who had nobody to look at him
+and see that he was solitary, I went into the booking-office, and, by
+invitation of the clerk on duty, passed behind the counter, and sat down
+on the scale at which they weighed the luggage. Here, as I sat looking
+at the parcels, packages, and books, and inhaling the smell of stables
+(ever since associated with that morning), a procession of most
+tremendous considerations began to march through my mind. Supposing
+nobody should ever fetch me, how long would they consent to keep me
+there? Would they keep me long enough to spend seven shillings? Should I
+sleep at night in one of those wooden bins, with the other luggage,
+and wash myself at the pump in the yard in the morning; or should I
+be turned out every night, and expected to come again to be left till
+called for, when the office opened next day? Supposing there was no
+mistake in the case, and Mr. Murdstone had devised this plan to get rid
+of me, what should I do? If they allowed me to remain there until my
+seven shillings were spent, I couldn't hope to remain there when I began
+to starve. That would obviously be inconvenient and unpleasant to the
+customers, besides entailing on the Blue Whatever-it-was, the risk of
+funeral expenses. If I started off at once, and tried to walk back home,
+how could I ever find my way, how could I ever hope to walk so far, how
+could I make sure of anyone but Peggotty, even if I got back? If I
+found out the nearest proper authorities, and offered myself to go for a
+soldier, or a sailor, I was such a little fellow that it was most likely
+they wouldn't take me in. These thoughts, and a hundred other such
+thoughts, turned me burning hot, and made me giddy with apprehension and
+dismay. I was in the height of my fever when a man entered and whispered
+to the clerk, who presently slanted me off the scale, and pushed me over
+to him, as if I were weighed, bought, delivered, and paid for.
+
+As I went out of the office, hand in hand with this new acquaintance,
+I stole a look at him. He was a gaunt, sallow young man, with hollow
+cheeks, and a chin almost as black as Mr. Murdstone's; but there the
+likeness ended, for his whiskers were shaved off, and his hair, instead
+of being glossy, was rusty and dry. He was dressed in a suit of black
+clothes which were rather rusty and dry too, and rather short in the
+sleeves and legs; and he had a white neck-kerchief on, that was not
+over-clean. I did not, and do not, suppose that this neck-kerchief was
+all the linen he wore, but it was all he showed or gave any hint of.
+
+'You're the new boy?' he said. 'Yes, sir,' I said.
+
+I supposed I was. I didn't know.
+
+'I'm one of the masters at Salem House,' he said.
+
+I made him a bow and felt very much overawed. I was so ashamed to allude
+to a commonplace thing like my box, to a scholar and a master at Salem
+House, that we had gone some little distance from the yard before I had
+the hardihood to mention it. We turned back, on my humbly insinuating
+that it might be useful to me hereafter; and he told the clerk that the
+carrier had instructions to call for it at noon.
+
+'If you please, sir,' I said, when we had accomplished about the same
+distance as before, 'is it far?'
+
+'It's down by Blackheath,' he said.
+
+'Is that far, sir?' I diffidently asked.
+
+'It's a good step,' he said. 'We shall go by the stage-coach. It's about
+six miles.'
+
+I was so faint and tired, that the idea of holding out for six miles
+more, was too much for me. I took heart to tell him that I had had
+nothing all night, and that if he would allow me to buy something to
+eat, I should be very much obliged to him. He appeared surprised at
+this--I see him stop and look at me now--and after considering for a few
+moments, said he wanted to call on an old person who lived not far off,
+and that the best way would be for me to buy some bread, or whatever I
+liked best that was wholesome, and make my breakfast at her house, where
+we could get some milk.
+
+Accordingly we looked in at a baker's window, and after I had made a
+series of proposals to buy everything that was bilious in the shop, and
+he had rejected them one by one, we decided in favour of a nice little
+loaf of brown bread, which cost me threepence. Then, at a grocer's shop,
+we bought an egg and a slice of streaky bacon; which still left what
+I thought a good deal of change, out of the second of the bright
+shillings, and made me consider London a very cheap place. These
+provisions laid in, we went on through a great noise and uproar that
+confused my weary head beyond description, and over a bridge which, no
+doubt, was London Bridge (indeed I think he told me so, but I was half
+asleep), until we came to the poor person's house, which was a part of
+some alms-houses, as I knew by their look, and by an inscription on a
+stone over the gate which said they were established for twenty-five
+poor women.
+
+The Master at Salem House lifted the latch of one of a number of little
+black doors that were all alike, and had each a little diamond-paned
+window on one side, and another little diamond--paned window above; and
+we went into the little house of one of these poor old women, who was
+blowing a fire to make a little saucepan boil. On seeing the master
+enter, the old woman stopped with the bellows on her knee, and said
+something that I thought sounded like 'My Charley!' but on seeing me
+come in too, she got up, and rubbing her hands made a confused sort of
+half curtsey.
+
+'Can you cook this young gentleman's breakfast for him, if you please?'
+said the Master at Salem House.
+
+'Can I?' said the old woman. 'Yes can I, sure!'
+
+'How's Mrs. Fibbitson today?' said the Master, looking at another old
+woman in a large chair by the fire, who was such a bundle of clothes
+that I feel grateful to this hour for not having sat upon her by
+mistake.
+
+'Ah, she's poorly,' said the first old woman. 'It's one of her bad days.
+If the fire was to go out, through any accident, I verily believe she'd
+go out too, and never come to life again.'
+
+As they looked at her, I looked at her also. Although it was a warm day,
+she seemed to think of nothing but the fire. I fancied she was jealous
+even of the saucepan on it; and I have reason to know that she took its
+impressment into the service of boiling my egg and broiling my bacon, in
+dudgeon; for I saw her, with my own discomfited eyes, shake her fist at
+me once, when those culinary operations were going on, and no one else
+was looking. The sun streamed in at the little window, but she sat with
+her own back and the back of the large chair towards it, screening the
+fire as if she were sedulously keeping IT warm, instead of it keeping
+her warm, and watching it in a most distrustful manner. The completion
+of the preparations for my breakfast, by relieving the fire, gave her
+such extreme joy that she laughed aloud--and a very unmelodious laugh
+she had, I must say.
+
+I sat down to my brown loaf, my egg, and my rasher of bacon, with a
+basin of milk besides, and made a most delicious meal. While I was yet
+in the full enjoyment of it, the old woman of the house said to the
+Master:
+
+'Have you got your flute with you?'
+
+'Yes,' he returned.
+
+'Have a blow at it,' said the old woman, coaxingly. 'Do!'
+
+The Master, upon this, put his hand underneath the skirts of his coat,
+and brought out his flute in three pieces, which he screwed together,
+and began immediately to play. My impression is, after many years of
+consideration, that there never can have been anybody in the world who
+played worse. He made the most dismal sounds I have ever heard produced
+by any means, natural or artificial. I don't know what the tunes
+were--if there were such things in the performance at all, which I
+doubt--but the influence of the strain upon me was, first, to make me
+think of all my sorrows until I could hardly keep my tears back; then to
+take away my appetite; and lastly, to make me so sleepy that I couldn't
+keep my eyes open. They begin to close again, and I begin to nod, as the
+recollection rises fresh upon me. Once more the little room, with its
+open corner cupboard, and its square-backed chairs, and its angular
+little staircase leading to the room above, and its three peacock's
+feathers displayed over the mantelpiece--I remember wondering when I
+first went in, what that peacock would have thought if he had known what
+his finery was doomed to come to--fades from before me, and I nod, and
+sleep. The flute becomes inaudible, the wheels of the coach are heard
+instead, and I am on my journey. The coach jolts, I wake with a start,
+and the flute has come back again, and the Master at Salem House is
+sitting with his legs crossed, playing it dolefully, while the old woman
+of the house looks on delighted. She fades in her turn, and he fades,
+and all fades, and there is no flute, no Master, no Salem House, no
+David Copperfield, no anything but heavy sleep.
+
+I dreamed, I thought, that once while he was blowing into this dismal
+flute, the old woman of the house, who had gone nearer and nearer to him
+in her ecstatic admiration, leaned over the back of his chair and gave
+him an affectionate squeeze round the neck, which stopped his playing
+for a moment. I was in the middle state between sleeping and waking,
+either then or immediately afterwards; for, as he resumed--it was a real
+fact that he had stopped playing--I saw and heard the same old woman ask
+Mrs. Fibbitson if it wasn't delicious (meaning the flute), to which Mrs.
+Fibbitson replied, 'Ay, ay! yes!' and nodded at the fire: to which, I am
+persuaded, she gave the credit of the whole performance.
+
+When I seemed to have been dozing a long while, the Master at Salem
+House unscrewed his flute into the three pieces, put them up as before,
+and took me away. We found the coach very near at hand, and got upon the
+roof; but I was so dead sleepy, that when we stopped on the road to take
+up somebody else, they put me inside where there were no passengers, and
+where I slept profoundly, until I found the coach going at a footpace up
+a steep hill among green leaves. Presently, it stopped, and had come to
+its destination.
+
+A short walk brought us--I mean the Master and me--to Salem House, which
+was enclosed with a high brick wall, and looked very dull. Over a door
+in this wall was a board with SALEM HOUSE upon it; and through a grating
+in this door we were surveyed when we rang the bell by a surly face,
+which I found, on the door being opened, belonged to a stout man with a
+bull-neck, a wooden leg, overhanging temples, and his hair cut close all
+round his head.
+
+'The new boy,' said the Master.
+
+The man with the wooden leg eyed me all over--it didn't take long, for
+there was not much of me--and locked the gate behind us, and took out
+the key. We were going up to the house, among some dark heavy trees,
+when he called after my conductor. 'Hallo!'
+
+We looked back, and he was standing at the door of a little lodge, where
+he lived, with a pair of boots in his hand.
+
+'Here! The cobbler's been,' he said, 'since you've been out, Mr. Mell,
+and he says he can't mend 'em any more. He says there ain't a bit of the
+original boot left, and he wonders you expect it.'
+
+With these words he threw the boots towards Mr. Mell, who went back a
+few paces to pick them up, and looked at them (very disconsolately,
+I was afraid), as we went on together. I observed then, for the first
+time, that the boots he had on were a good deal the worse for wear, and
+that his stocking was just breaking out in one place, like a bud.
+
+Salem House was a square brick building with wings; of a bare and
+unfurnished appearance. All about it was so very quiet, that I said to
+Mr. Mell I supposed the boys were out; but he seemed surprised at my
+not knowing that it was holiday-time. That all the boys were at their
+several homes. That Mr. Creakle, the proprietor, was down by the
+sea-side with Mrs. and Miss Creakle; and that I was sent in holiday-time
+as a punishment for my misdoing, all of which he explained to me as we
+went along.
+
+I gazed upon the schoolroom into which he took me, as the most forlorn
+and desolate place I had ever seen. I see it now. A long room with three
+long rows of desks, and six of forms, and bristling all round with pegs
+for hats and slates. Scraps of old copy-books and exercises litter the
+dirty floor. Some silkworms' houses, made of the same materials, are
+scattered over the desks. Two miserable little white mice, left behind
+by their owner, are running up and down in a fusty castle made of
+pasteboard and wire, looking in all the corners with their red eyes
+for anything to eat. A bird, in a cage very little bigger than himself,
+makes a mournful rattle now and then in hopping on his perch, two inches
+high, or dropping from it; but neither sings nor chirps. There is a
+strange unwholesome smell upon the room, like mildewed corduroys, sweet
+apples wanting air, and rotten books. There could not well be more ink
+splashed about it, if it had been roofless from its first construction,
+and the skies had rained, snowed, hailed, and blown ink through the
+varying seasons of the year.
+
+Mr. Mell having left me while he took his irreparable boots upstairs, I
+went softly to the upper end of the room, observing all this as I crept
+along. Suddenly I came upon a pasteboard placard, beautifully written,
+which was lying on the desk, and bore these words: 'TAKE CARE OF HIM. HE
+BITES.'
+
+I got upon the desk immediately, apprehensive of at least a great dog
+underneath. But, though I looked all round with anxious eyes, I could
+see nothing of him. I was still engaged in peering about, when Mr. Mell
+came back, and asked me what I did up there?
+
+'I beg your pardon, sir,' says I, 'if you please, I'm looking for the
+dog.'
+
+'Dog?' he says. 'What dog?'
+
+'Isn't it a dog, sir?'
+
+'Isn't what a dog?'
+
+'That's to be taken care of, sir; that bites.'
+
+'No, Copperfield,' says he, gravely, 'that's not a dog. That's a boy.
+My instructions are, Copperfield, to put this placard on your back. I am
+sorry to make such a beginning with you, but I must do it.' With that he
+took me down, and tied the placard, which was neatly constructed for
+the purpose, on my shoulders like a knapsack; and wherever I went,
+afterwards, I had the consolation of carrying it.
+
+What I suffered from that placard, nobody can imagine. Whether it was
+possible for people to see me or not, I always fancied that somebody was
+reading it. It was no relief to turn round and find nobody; for wherever
+my back was, there I imagined somebody always to be. That cruel man with
+the wooden leg aggravated my sufferings. He was in authority; and if he
+ever saw me leaning against a tree, or a wall, or the house, he roared
+out from his lodge door in a stupendous voice, 'Hallo, you sir! You
+Copperfield! Show that badge conspicuous, or I'll report you!' The
+playground was a bare gravelled yard, open to all the back of the house
+and the offices; and I knew that the servants read it, and the butcher
+read it, and the baker read it; that everybody, in a word, who came
+backwards and forwards to the house, of a morning when I was ordered to
+walk there, read that I was to be taken care of, for I bit, I recollect
+that I positively began to have a dread of myself, as a kind of wild boy
+who did bite.
+
+There was an old door in this playground, on which the boys had a
+custom of carving their names. It was completely covered with such
+inscriptions. In my dread of the end of the vacation and their coming
+back, I could not read a boy's name, without inquiring in what tone and
+with what emphasis HE would read, 'Take care of him. He bites.' There
+was one boy--a certain J. Steerforth--who cut his name very deep and
+very often, who, I conceived, would read it in a rather strong voice,
+and afterwards pull my hair. There was another boy, one Tommy Traddles,
+who I dreaded would make game of it, and pretend to be dreadfully
+frightened of me. There was a third, George Demple, who I fancied would
+sing it. I have looked, a little shrinking creature, at that door, until
+the owners of all the names--there were five-and-forty of them in the
+school then, Mr. Mell said--seemed to send me to Coventry by general
+acclamation, and to cry out, each in his own way, 'Take care of him. He
+bites!'
+
+It was the same with the places at the desks and forms. It was the same
+with the groves of deserted bedsteads I peeped at, on my way to, and
+when I was in, my own bed. I remember dreaming night after night, of
+being with my mother as she used to be, or of going to a party at Mr.
+Peggotty's, or of travelling outside the stage-coach, or of dining again
+with my unfortunate friend the waiter, and in all these circumstances
+making people scream and stare, by the unhappy disclosure that I had
+nothing on but my little night-shirt, and that placard.
+
+In the monotony of my life, and in my constant apprehension of the
+re-opening of the school, it was such an insupportable affliction! I had
+long tasks every day to do with Mr. Mell; but I did them, there being
+no Mr. and Miss Murdstone here, and got through them without disgrace.
+Before, and after them, I walked about--supervised, as I have mentioned,
+by the man with the wooden leg. How vividly I call to mind the damp
+about the house, the green cracked flagstones in the court, an old leaky
+water-butt, and the discoloured trunks of some of the grim trees, which
+seemed to have dripped more in the rain than other trees, and to have
+blown less in the sun! At one we dined, Mr. Mell and I, at the upper end
+of a long bare dining-room, full of deal tables, and smelling of fat.
+Then, we had more tasks until tea, which Mr. Mell drank out of a blue
+teacup, and I out of a tin pot. All day long, and until seven or eight
+in the evening, Mr. Mell, at his own detached desk in the schoolroom,
+worked hard with pen, ink, ruler, books, and writing-paper, making out
+the bills (as I found) for last half-year. When he had put up his things
+for the night he took out his flute, and blew at it, until I almost
+thought he would gradually blow his whole being into the large hole at
+the top, and ooze away at the keys.
+
+I picture my small self in the dimly-lighted rooms, sitting with my
+head upon my hand, listening to the doleful performance of Mr. Mell,
+and conning tomorrow's lessons. I picture myself with my books shut up,
+still listening to the doleful performance of Mr. Mell, and listening
+through it to what used to be at home, and to the blowing of the wind
+on Yarmouth flats, and feeling very sad and solitary. I picture myself
+going up to bed, among the unused rooms, and sitting on my bed-side
+crying for a comfortable word from Peggotty. I picture myself coming
+downstairs in the morning, and looking through a long ghastly gash of a
+staircase window at the school-bell hanging on the top of an out-house
+with a weathercock above it; and dreading the time when it shall ring J.
+Steerforth and the rest to work: which is only second, in my foreboding
+apprehensions, to the time when the man with the wooden leg shall unlock
+the rusty gate to give admission to the awful Mr. Creakle. I cannot
+think I was a very dangerous character in any of these aspects, but in
+all of them I carried the same warning on my back.
+
+Mr. Mell never said much to me, but he was never harsh to me. I suppose
+we were company to each other, without talking. I forgot to mention that
+he would talk to himself sometimes, and grin, and clench his fist, and
+grind his teeth, and pull his hair in an unaccountable manner. But he
+had these peculiarities: and at first they frightened me, though I soon
+got used to them.
+
+
+
+CHAPTER 6. I ENLARGE MY CIRCLE OF ACQUAINTANCE
+
+
+I HAD led this life about a month, when the man with the wooden leg
+began to stump about with a mop and a bucket of water, from which I
+inferred that preparations were making to receive Mr. Creakle and the
+boys. I was not mistaken; for the mop came into the schoolroom before
+long, and turned out Mr. Mell and me, who lived where we could, and got
+on how we could, for some days, during which we were always in the way
+of two or three young women, who had rarely shown themselves before, and
+were so continually in the midst of dust that I sneezed almost as much
+as if Salem House had been a great snuff-box.
+
+One day I was informed by Mr. Mell that Mr. Creakle would be home that
+evening. In the evening, after tea, I heard that he was come. Before
+bedtime, I was fetched by the man with the wooden leg to appear before
+him.
+
+Mr. Creakle's part of the house was a good deal more comfortable than
+ours, and he had a snug bit of garden that looked pleasant after the
+dusty playground, which was such a desert in miniature, that I thought
+no one but a camel, or a dromedary, could have felt at home in it. It
+seemed to me a bold thing even to take notice that the passage looked
+comfortable, as I went on my way, trembling, to Mr. Creakle's presence:
+which so abashed me, when I was ushered into it, that I hardly saw
+Mrs. Creakle or Miss Creakle (who were both there, in the parlour), or
+anything but Mr. Creakle, a stout gentleman with a bunch of watch-chain
+and seals, in an arm-chair, with a tumbler and bottle beside him.
+
+'So!' said Mr. Creakle. 'This is the young gentleman whose teeth are to
+be filed! Turn him round.'
+
+The wooden-legged man turned me about so as to exhibit the placard; and
+having afforded time for a full survey of it, turned me about again,
+with my face to Mr. Creakle, and posted himself at Mr. Creakle's side.
+Mr. Creakle's face was fiery, and his eyes were small, and deep in his
+head; he had thick veins in his forehead, a little nose, and a large
+chin. He was bald on the top of his head; and had some thin wet-looking
+hair that was just turning grey, brushed across each temple, so that
+the two sides interlaced on his forehead. But the circumstance about
+him which impressed me most, was, that he had no voice, but spoke in a
+whisper. The exertion this cost him, or the consciousness of talking in
+that feeble way, made his angry face so much more angry, and his thick
+veins so much thicker, when he spoke, that I am not surprised, on
+looking back, at this peculiarity striking me as his chief one. 'Now,'
+said Mr. Creakle. 'What's the report of this boy?'
+
+'There's nothing against him yet,' returned the man with the wooden leg.
+'There has been no opportunity.'
+
+I thought Mr. Creakle was disappointed. I thought Mrs. and Miss Creakle
+(at whom I now glanced for the first time, and who were, both, thin and
+quiet) were not disappointed.
+
+'Come here, sir!' said Mr. Creakle, beckoning to me.
+
+'Come here!' said the man with the wooden leg, repeating the gesture.
+
+'I have the happiness of knowing your father-in-law,' whispered Mr.
+Creakle, taking me by the ear; 'and a worthy man he is, and a man of
+a strong character. He knows me, and I know him. Do YOU know me? Hey?'
+said Mr. Creakle, pinching my ear with ferocious playfulness.
+
+'Not yet, sir,' I said, flinching with the pain.
+
+'Not yet? Hey?' repeated Mr. Creakle. 'But you will soon. Hey?'
+
+'You will soon. Hey?' repeated the man with the wooden leg. I afterwards
+found that he generally acted, with his strong voice, as Mr. Creakle's
+interpreter to the boys.
+
+I was very much frightened, and said, I hoped so, if he pleased. I felt,
+all this while, as if my ear were blazing; he pinched it so hard.
+
+'I'll tell you what I am,' whispered Mr. Creakle, letting it go at last,
+with a screw at parting that brought the water into my eyes. 'I'm a
+Tartar.'
+
+'A Tartar,' said the man with the wooden leg.
+
+'When I say I'll do a thing, I do it,' said Mr. Creakle; 'and when I say
+I will have a thing done, I will have it done.'
+
+'--Will have a thing done, I will have it done,' repeated the man with
+the wooden leg.
+
+'I am a determined character,' said Mr. Creakle. 'That's what I am. I
+do my duty. That's what I do. My flesh and blood'--he looked at Mrs.
+Creakle as he said this--'when it rises against me, is not my flesh
+and blood. I discard it. Has that fellow'--to the man with the wooden
+leg--'been here again?'
+
+'No,' was the answer.
+
+'No,' said Mr. Creakle. 'He knows better. He knows me. Let him keep
+away. I say let him keep away,' said Mr. Creakle, striking his hand upon
+the table, and looking at Mrs. Creakle, 'for he knows me. Now you have
+begun to know me too, my young friend, and you may go. Take him away.'
+
+I was very glad to be ordered away, for Mrs. and Miss Creakle were both
+wiping their eyes, and I felt as uncomfortable for them as I did for
+myself. But I had a petition on my mind which concerned me so nearly,
+that I couldn't help saying, though I wondered at my own courage:
+
+'If you please, sir--'
+
+Mr. Creakle whispered, 'Hah! What's this?' and bent his eyes upon me, as
+if he would have burnt me up with them.
+
+'If you please, sir,' I faltered, 'if I might be allowed (I am very
+sorry indeed, sir, for what I did) to take this writing off, before the
+boys come back--'
+
+Whether Mr. Creakle was in earnest, or whether he only did it to
+frighten me, I don't know, but he made a burst out of his chair, before
+which I precipitately retreated, without waiting for the escort Of the
+man with the wooden leg, and never once stopped until I reached my own
+bedroom, where, finding I was not pursued, I went to bed, as it was
+time, and lay quaking, for a couple of hours.
+
+Next morning Mr. Sharp came back. Mr. Sharp was the first master, and
+superior to Mr. Mell. Mr. Mell took his meals with the boys, but
+Mr. Sharp dined and supped at Mr. Creakle's table. He was a limp,
+delicate-looking gentleman, I thought, with a good deal of nose, and a
+way of carrying his head on one side, as if it were a little too heavy
+for him. His hair was very smooth and wavy; but I was informed by the
+very first boy who came back that it was a wig (a second-hand one HE
+said), and that Mr. Sharp went out every Saturday afternoon to get it
+curled.
+
+It was no other than Tommy Traddles who gave me this piece of
+intelligence. He was the first boy who returned. He introduced himself
+by informing me that I should find his name on the right-hand corner of
+the gate, over the top-bolt; upon that I said, 'Traddles?' to which he
+replied, 'The same,' and then he asked me for a full account of myself
+and family.
+
+It was a happy circumstance for me that Traddles came back first. He
+enjoyed my placard so much, that he saved me from the embarrassment of
+either disclosure or concealment, by presenting me to every other boy
+who came back, great or small, immediately on his arrival, in this form
+of introduction, 'Look here! Here's a game!' Happily, too, the greater
+part of the boys came back low-spirited, and were not so boisterous at
+my expense as I had expected. Some of them certainly did dance about me
+like wild Indians, and the greater part could not resist the temptation
+of pretending that I was a dog, and patting and soothing me, lest I
+should bite, and saying, 'Lie down, sir!' and calling me Towzer. This
+was naturally confusing, among so many strangers, and cost me some
+tears, but on the whole it was much better than I had anticipated.
+
+I was not considered as being formally received into the school,
+however, until J. Steerforth arrived. Before this boy, who was
+reputed to be a great scholar, and was very good-looking, and at least
+half-a-dozen years my senior, I was carried as before a magistrate. He
+inquired, under a shed in the playground, into the particulars of my
+punishment, and was pleased to express his opinion that it was 'a jolly
+shame'; for which I became bound to him ever afterwards.
+
+'What money have you got, Copperfield?' he said, walking aside with
+me when he had disposed of my affair in these terms. I told him seven
+shillings.
+
+'You had better give it to me to take care of,' he said. 'At least, you
+can if you like. You needn't if you don't like.'
+
+I hastened to comply with his friendly suggestion, and opening
+Peggotty's purse, turned it upside down into his hand.
+
+'Do you want to spend anything now?' he asked me.
+
+'No thank you,' I replied.
+
+'You can, if you like, you know,' said Steerforth. 'Say the word.'
+
+'No, thank you, sir,' I repeated.
+
+'Perhaps you'd like to spend a couple of shillings or so, in a bottle of
+currant wine by and by, up in the bedroom?' said Steerforth. 'You belong
+to my bedroom, I find.'
+
+It certainly had not occurred to me before, but I said, Yes, I should
+like that.
+
+'Very good,' said Steerforth. 'You'll be glad to spend another shilling
+or so, in almond cakes, I dare say?'
+
+I said, Yes, I should like that, too.
+
+'And another shilling or so in biscuits, and another in fruit, eh?' said
+Steerforth. 'I say, young Copperfield, you're going it!'
+
+I smiled because he smiled, but I was a little troubled in my mind, too.
+
+'Well!' said Steerforth. 'We must make it stretch as far as we can;
+that's all. I'll do the best in my power for you. I can go out when I
+like, and I'll smuggle the prog in.' With these words he put the money
+in his pocket, and kindly told me not to make myself uneasy; he would
+take care it should be all right. He was as good as his word, if that
+were all right which I had a secret misgiving was nearly all wrong--for
+I feared it was a waste of my mother's two half-crowns--though I had
+preserved the piece of paper they were wrapped in: which was a precious
+saving. When we went upstairs to bed, he produced the whole seven
+shillings' worth, and laid it out on my bed in the moonlight, saying:
+
+'There you are, young Copperfield, and a royal spread you've got.'
+
+I couldn't think of doing the honours of the feast, at my time of life,
+while he was by; my hand shook at the very thought of it. I begged him
+to do me the favour of presiding; and my request being seconded by the
+other boys who were in that room, he acceded to it, and sat upon my
+pillow, handing round the viands--with perfect fairness, I must say--and
+dispensing the currant wine in a little glass without a foot, which was
+his own property. As to me, I sat on his left hand, and the rest were
+grouped about us, on the nearest beds and on the floor.
+
+How well I recollect our sitting there, talking in whispers; or their
+talking, and my respectfully listening, I ought rather to say; the
+moonlight falling a little way into the room, through the window,
+painting a pale window on the floor, and the greater part of us in
+shadow, except when Steerforth dipped a match into a phosphorus-box,
+when he wanted to look for anything on the board, and shed a blue glare
+over us that was gone directly! A certain mysterious feeling, consequent
+on the darkness, the secrecy of the revel, and the whisper in which
+everything was said, steals over me again, and I listen to all they tell
+me with a vague feeling of solemnity and awe, which makes me glad that
+they are all so near, and frightens me (though I feign to laugh) when
+Traddles pretends to see a ghost in the corner.
+
+I heard all kinds of things about the school and all belonging to it.
+I heard that Mr. Creakle had not preferred his claim to being a Tartar
+without reason; that he was the sternest and most severe of masters;
+that he laid about him, right and left, every day of his life, charging
+in among the boys like a trooper, and slashing away, unmercifully. That
+he knew nothing himself, but the art of slashing, being more ignorant
+(J. Steerforth said) than the lowest boy in the school; that he had
+been, a good many years ago, a small hop-dealer in the Borough, and had
+taken to the schooling business after being bankrupt in hops, and making
+away with Mrs. Creakle's money. With a good deal more of that sort,
+which I wondered how they knew.
+
+I heard that the man with the wooden leg, whose name was Tungay, was an
+obstinate barbarian who had formerly assisted in the hop business, but
+had come into the scholastic line with Mr. Creakle, in consequence,
+as was supposed among the boys, of his having broken his leg in Mr.
+Creakle's service, and having done a deal of dishonest work for him,
+and knowing his secrets. I heard that with the single exception of Mr.
+Creakle, Tungay considered the whole establishment, masters and boys,
+as his natural enemies, and that the only delight of his life was to be
+sour and malicious. I heard that Mr. Creakle had a son, who had not been
+Tungay's friend, and who, assisting in the school, had once held some
+remonstrance with his father on an occasion when its discipline was very
+cruelly exercised, and was supposed, besides, to have protested against
+his father's usage of his mother. I heard that Mr. Creakle had turned
+him out of doors, in consequence; and that Mrs. and Miss Creakle had
+been in a sad way, ever since.
+
+But the greatest wonder that I heard of Mr. Creakle was, there being one
+boy in the school on whom he never ventured to lay a hand, and that
+boy being J. Steerforth. Steerforth himself confirmed this when it was
+stated, and said that he should like to begin to see him do it. On being
+asked by a mild boy (not me) how he would proceed if he did begin to see
+him do it, he dipped a match into his phosphorus-box on purpose to shed
+a glare over his reply, and said he would commence by knocking him down
+with a blow on the forehead from the seven-and-sixpenny ink-bottle
+that was always on the mantelpiece. We sat in the dark for some time,
+breathless.
+
+I heard that Mr. Sharp and Mr. Mell were both supposed to be wretchedly
+paid; and that when there was hot and cold meat for dinner at Mr.
+Creakle's table, Mr. Sharp was always expected to say he preferred cold;
+which was again corroborated by J. Steerforth, the only parlour-boarder.
+I heard that Mr. Sharp's wig didn't fit him; and that he needn't be so
+'bounceable'--somebody else said 'bumptious'--about it, because his own
+red hair was very plainly to be seen behind.
+
+I heard that one boy, who was a coal-merchant's son, came as a set-off
+against the coal-bill, and was called, on that account, 'Exchange or
+Barter'--a name selected from the arithmetic book as expressing this
+arrangement. I heard that the table beer was a robbery of parents, and
+the pudding an imposition. I heard that Miss Creakle was regarded by the
+school in general as being in love with Steerforth; and I am sure, as I
+sat in the dark, thinking of his nice voice, and his fine face, and his
+easy manner, and his curling hair, I thought it very likely. I heard
+that Mr. Mell was not a bad sort of fellow, but hadn't a sixpence to
+bless himself with; and that there was no doubt that old Mrs. Mell, his
+mother, was as poor as job. I thought of my breakfast then, and what had
+sounded like 'My Charley!' but I was, I am glad to remember, as mute as
+a mouse about it.
+
+The hearing of all this, and a good deal more, outlasted the banquet
+some time. The greater part of the guests had gone to bed as soon as the
+eating and drinking were over; and we, who had remained whispering and
+listening half-undressed, at last betook ourselves to bed, too.
+
+'Good night, young Copperfield,' said Steerforth. 'I'll take care of
+you.' 'You're very kind,' I gratefully returned. 'I am very much obliged
+to you.'
+
+'You haven't got a sister, have you?' said Steerforth, yawning.
+
+'No,' I answered.
+
+'That's a pity,' said Steerforth. 'If you had had one, I should think
+she would have been a pretty, timid, little, bright-eyed sort of girl. I
+should have liked to know her. Good night, young Copperfield.'
+
+'Good night, sir,' I replied.
+
+I thought of him very much after I went to bed, and raised myself,
+I recollect, to look at him where he lay in the moonlight, with his
+handsome face turned up, and his head reclining easily on his arm. He
+was a person of great power in my eyes; that was, of course, the reason
+of my mind running on him. No veiled future dimly glanced upon him in
+the moonbeams. There was no shadowy picture of his footsteps, in the
+garden that I dreamed of walking in all night.
+
+
+
+CHAPTER 7. MY 'FIRST HALF' AT SALEM HOUSE
+
+
+School began in earnest next day. A profound impression was made
+upon me, I remember, by the roar of voices in the schoolroom suddenly
+becoming hushed as death when Mr. Creakle entered after breakfast, and
+stood in the doorway looking round upon us like a giant in a story-book
+surveying his captives.
+
+Tungay stood at Mr. Creakle's elbow. He had no occasion, I thought,
+to cry out 'Silence!' so ferociously, for the boys were all struck
+speechless and motionless.
+
+Mr. Creakle was seen to speak, and Tungay was heard, to this effect.
+
+'Now, boys, this is a new half. Take care what you're about, in this new
+half. Come fresh up to the lessons, I advise you, for I come fresh up
+to the punishment. I won't flinch. It will be of no use your rubbing
+yourselves; you won't rub the marks out that I shall give you. Now get
+to work, every boy!'
+
+When this dreadful exordium was over, and Tungay had stumped out again,
+Mr. Creakle came to where I sat, and told me that if I were famous for
+biting, he was famous for biting, too. He then showed me the cane, and
+asked me what I thought of THAT, for a tooth? Was it a sharp tooth, hey?
+Was it a double tooth, hey? Had it a deep prong, hey? Did it bite, hey?
+Did it bite? At every question he gave me a fleshy cut with it that made
+me writhe; so I was very soon made free of Salem House (as Steerforth
+said), and was very soon in tears also.
+
+Not that I mean to say these were special marks of distinction,
+which only I received. On the contrary, a large majority of the boys
+(especially the smaller ones) were visited with similar instances
+of notice, as Mr. Creakle made the round of the schoolroom. Half the
+establishment was writhing and crying, before the day's work began; and
+how much of it had writhed and cried before the day's work was over, I
+am really afraid to recollect, lest I should seem to exaggerate.
+
+I should think there never can have been a man who enjoyed his
+profession more than Mr. Creakle did. He had a delight in cutting at
+the boys, which was like the satisfaction of a craving appetite. I am
+confident that he couldn't resist a chubby boy, especially; that there
+was a fascination in such a subject, which made him restless in his
+mind, until he had scored and marked him for the day. I was chubby
+myself, and ought to know. I am sure when I think of the fellow now, my
+blood rises against him with the disinterested indignation I should
+feel if I could have known all about him without having ever been in his
+power; but it rises hotly, because I know him to have been an incapable
+brute, who had no more right to be possessed of the great trust he held,
+than to be Lord High Admiral, or Commander-in-Chief--in either of
+which capacities it is probable that he would have done infinitely less
+mischief.
+
+Miserable little propitiators of a remorseless Idol, how abject we were
+to him! What a launch in life I think it now, on looking back, to be so
+mean and servile to a man of such parts and pretensions!
+
+Here I sit at the desk again, watching his eye--humbly watching his eye,
+as he rules a ciphering-book for another victim whose hands have just
+been flattened by that identical ruler, and who is trying to wipe the
+sting out with a pocket-handkerchief. I have plenty to do. I don't watch
+his eye in idleness, but because I am morbidly attracted to it, in a
+dread desire to know what he will do next, and whether it will be my
+turn to suffer, or somebody else's. A lane of small boys beyond me, with
+the same interest in his eye, watch it too. I think he knows it,
+though he pretends he don't. He makes dreadful mouths as he rules the
+ciphering-book; and now he throws his eye sideways down our lane, and we
+all droop over our books and tremble. A moment afterwards we are again
+eyeing him. An unhappy culprit, found guilty of imperfect exercise,
+approaches at his command. The culprit falters excuses, and professes a
+determination to do better tomorrow. Mr. Creakle cuts a joke before he
+beats him, and we laugh at it,--miserable little dogs, we laugh, with
+our visages as white as ashes, and our hearts sinking into our boots.
+
+Here I sit at the desk again, on a drowsy summer afternoon. A buzz and
+hum go up around me, as if the boys were so many bluebottles. A cloggy
+sensation of the lukewarm fat of meat is upon me (we dined an hour or
+two ago), and my head is as heavy as so much lead. I would give the
+world to go to sleep. I sit with my eye on Mr. Creakle, blinking at him
+like a young owl; when sleep overpowers me for a minute, he still looms
+through my slumber, ruling those ciphering-books, until he softly comes
+behind me and wakes me to plainer perception of him, with a red ridge
+across my back.
+
+Here I am in the playground, with my eye still fascinated by him, though
+I can't see him. The window at a little distance from which I know he is
+having his dinner, stands for him, and I eye that instead. If he shows
+his face near it, mine assumes an imploring and submissive expression.
+If he looks out through the glass, the boldest boy (Steerforth excepted)
+stops in the middle of a shout or yell, and becomes contemplative. One
+day, Traddles (the most unfortunate boy in the world) breaks that window
+accidentally, with a ball. I shudder at this moment with the tremendous
+sensation of seeing it done, and feeling that the ball has bounded on to
+Mr. Creakle's sacred head.
+
+Poor Traddles! In a tight sky-blue suit that made his arms and legs like
+German sausages, or roly-poly puddings, he was the merriest and most
+miserable of all the boys. He was always being caned--I think he was
+caned every day that half-year, except one holiday Monday when he was
+only ruler'd on both hands--and was always going to write to his uncle
+about it, and never did. After laying his head on the desk for a little
+while, he would cheer up, somehow, begin to laugh again, and draw
+skeletons all over his slate, before his eyes were dry. I used at first
+to wonder what comfort Traddles found in drawing skeletons; and for some
+time looked upon him as a sort of hermit, who reminded himself by those
+symbols of mortality that caning couldn't last for ever. But I believe
+he only did it because they were easy, and didn't want any features.
+
+He was very honourable, Traddles was, and held it as a solemn duty
+in the boys to stand by one another. He suffered for this on several
+occasions; and particularly once, when Steerforth laughed in church,
+and the Beadle thought it was Traddles, and took him out. I see him now,
+going away in custody, despised by the congregation. He never said
+who was the real offender, though he smarted for it next day, and was
+imprisoned so many hours that he came forth with a whole churchyard-full
+of skeletons swarming all over his Latin Dictionary. But he had his
+reward. Steerforth said there was nothing of the sneak in Traddles, and
+we all felt that to be the highest praise. For my part, I could have
+gone through a good deal (though I was much less brave than Traddles,
+and nothing like so old) to have won such a recompense.
+
+To see Steerforth walk to church before us, arm-in-arm with Miss
+Creakle, was one of the great sights of my life. I didn't think Miss
+Creakle equal to little Em'ly in point of beauty, and I didn't love
+her (I didn't dare); but I thought her a young lady of extraordinary
+attractions, and in point of gentility not to be surpassed. When
+Steerforth, in white trousers, carried her parasol for her, I felt proud
+to know him; and believed that she could not choose but adore him with
+all her heart. Mr. Sharp and Mr. Mell were both notable personages in my
+eyes; but Steerforth was to them what the sun was to two stars.
+
+Steerforth continued his protection of me, and proved a very useful
+friend; since nobody dared to annoy one whom he honoured with his
+countenance. He couldn't--or at all events he didn't--defend me from Mr.
+Creakle, who was very severe with me; but whenever I had been treated
+worse than usual, he always told me that I wanted a little of his pluck,
+and that he wouldn't have stood it himself; which I felt he intended
+for encouragement, and considered to be very kind of him. There was one
+advantage, and only one that I know of, in Mr. Creakle's severity. He
+found my placard in his way when he came up or down behind the form on
+which I sat, and wanted to make a cut at me in passing; for this reason
+it was soon taken off, and I saw it no more.
+
+An accidental circumstance cemented the intimacy between Steerforth
+and me, in a manner that inspired me with great pride and satisfaction,
+though it sometimes led to inconvenience. It happened on one occasion,
+when he was doing me the honour of talking to me in the playground, that
+I hazarded the observation that something or somebody--I forget what
+now--was like something or somebody in Peregrine Pickle. He said nothing
+at the time; but when I was going to bed at night, asked me if I had got
+that book?
+
+I told him no, and explained how it was that I had read it, and all
+those other books of which I have made mention.
+
+'And do you recollect them?' Steerforth said.
+
+'Oh yes,' I replied; I had a good memory, and I believed I recollected
+them very well.
+
+'Then I tell you what, young Copperfield,' said Steerforth, 'you
+shall tell 'em to me. I can't get to sleep very early at night, and I
+generally wake rather early in the morning. We'll go over 'em one after
+another. We'll make some regular Arabian Nights of it.'
+
+I felt extremely flattered by this arrangement, and we commenced
+carrying it into execution that very evening. What ravages I committed
+on my favourite authors in the course of my interpretation of them, I am
+not in a condition to say, and should be very unwilling to know; but
+I had a profound faith in them, and I had, to the best of my belief,
+a simple, earnest manner of narrating what I did narrate; and these
+qualities went a long way.
+
+The drawback was, that I was often sleepy at night, or out of spirits
+and indisposed to resume the story; and then it was rather hard work,
+and it must be done; for to disappoint or to displease Steerforth was of
+course out of the question. In the morning, too, when I felt weary, and
+should have enjoyed another hour's repose very much, it was a tiresome
+thing to be roused, like the Sultana Scheherazade, and forced into a
+long story before the getting-up bell rang; but Steerforth was resolute;
+and as he explained to me, in return, my sums and exercises, and
+anything in my tasks that was too hard for me, I was no loser by the
+transaction. Let me do myself justice, however. I was moved by no
+interested or selfish motive, nor was I moved by fear of him. I admired
+and loved him, and his approval was return enough. It was so precious to
+me that I look back on these trifles, now, with an aching heart.
+
+Steerforth was considerate, too; and showed his consideration, in
+one particular instance, in an unflinching manner that was a little
+tantalizing, I suspect, to poor Traddles and the rest. Peggotty's
+promised letter--what a comfortable letter it was!--arrived before
+'the half' was many weeks old; and with it a cake in a perfect nest
+of oranges, and two bottles of cowslip wine. This treasure, as in duty
+bound, I laid at the feet of Steerforth, and begged him to dispense.
+
+'Now, I'll tell you what, young Copperfield,' said he: 'the wine shall
+be kept to wet your whistle when you are story-telling.'
+
+I blushed at the idea, and begged him, in my modesty, not to think of
+it. But he said he had observed I was sometimes hoarse--a little roopy
+was his exact expression--and it should be, every drop, devoted to the
+purpose he had mentioned. Accordingly, it was locked up in his box, and
+drawn off by himself in a phial, and administered to me through a
+piece of quill in the cork, when I was supposed to be in want of a
+restorative. Sometimes, to make it a more sovereign specific, he was so
+kind as to squeeze orange juice into it, or to stir it up with ginger,
+or dissolve a peppermint drop in it; and although I cannot assert that
+the flavour was improved by these experiments, or that it was exactly
+the compound one would have chosen for a stomachic, the last thing at
+night and the first thing in the morning, I drank it gratefully and was
+very sensible of his attention.
+
+We seem, to me, to have been months over Peregrine, and months more over
+the other stories. The institution never flagged for want of a story, I
+am certain; and the wine lasted out almost as well as the matter. Poor
+Traddles--I never think of that boy but with a strange disposition to
+laugh, and with tears in my eyes--was a sort of chorus, in general;
+and affected to be convulsed with mirth at the comic parts, and to be
+overcome with fear when there was any passage of an alarming character
+in the narrative. This rather put me out, very often. It was a great
+jest of his, I recollect, to pretend that he couldn't keep his teeth
+from chattering, whenever mention was made of an Alguazill in connexion
+with the adventures of Gil Blas; and I remember that when Gil Blas met
+the captain of the robbers in Madrid, this unlucky joker counterfeited
+such an ague of terror, that he was overheard by Mr. Creakle, who
+was prowling about the passage, and handsomely flogged for disorderly
+conduct in the bedroom. Whatever I had within me that was romantic and
+dreamy, was encouraged by so much story-telling in the dark; and in that
+respect the pursuit may not have been very profitable to me. But the
+being cherished as a kind of plaything in my room, and the consciousness
+that this accomplishment of mine was bruited about among the boys, and
+attracted a good deal of notice to me though I was the youngest there,
+stimulated me to exertion. In a school carried on by sheer cruelty,
+whether it is presided over by a dunce or not, there is not likely to
+be much learnt. I believe our boys were, generally, as ignorant a set
+as any schoolboys in existence; they were too much troubled and knocked
+about to learn; they could no more do that to advantage, than any one
+can do anything to advantage in a life of constant misfortune, torment,
+and worry. But my little vanity, and Steerforth's help, urged me on
+somehow; and without saving me from much, if anything, in the way of
+punishment, made me, for the time I was there, an exception to the
+general body, insomuch that I did steadily pick up some crumbs of
+knowledge.
+
+In this I was much assisted by Mr. Mell, who had a liking for me that
+I am grateful to remember. It always gave me pain to observe that
+Steerforth treated him with systematic disparagement, and seldom lost
+an occasion of wounding his feelings, or inducing others to do so.
+This troubled me the more for a long time, because I had soon told
+Steerforth, from whom I could no more keep such a secret, than I could
+keep a cake or any other tangible possession, about the two old women
+Mr. Mell had taken me to see; and I was always afraid that Steerforth
+would let it out, and twit him with it.
+
+We little thought, any one of us, I dare say, when I ate my breakfast
+that first morning, and went to sleep under the shadow of the peacock's
+feathers to the sound of the flute, what consequences would come of the
+introduction into those alms-houses of my insignificant person. But the
+visit had its unforeseen consequences; and of a serious sort, too, in
+their way.
+
+One day when Mr. Creakle kept the house from indisposition, which
+naturally diffused a lively joy through the school, there was a good
+deal of noise in the course of the morning's work. The great relief and
+satisfaction experienced by the boys made them difficult to manage; and
+though the dreaded Tungay brought his wooden leg in twice or thrice, and
+took notes of the principal offenders' names, no great impression was
+made by it, as they were pretty sure of getting into trouble tomorrow,
+do what they would, and thought it wise, no doubt, to enjoy themselves
+today.
+
+It was, properly, a half-holiday; being Saturday. But as the noise in
+the playground would have disturbed Mr. Creakle, and the weather was
+not favourable for going out walking, we were ordered into school in the
+afternoon, and set some lighter tasks than usual, which were made for
+the occasion. It was the day of the week on which Mr. Sharp went out to
+get his wig curled; so Mr. Mell, who always did the drudgery, whatever
+it was, kept school by himself. If I could associate the idea of a bull
+or a bear with anyone so mild as Mr. Mell, I should think of him, in
+connexion with that afternoon when the uproar was at its height, as of
+one of those animals, baited by a thousand dogs. I recall him bending
+his aching head, supported on his bony hand, over the book on his desk,
+and wretchedly endeavouring to get on with his tiresome work, amidst an
+uproar that might have made the Speaker of the House of Commons giddy.
+Boys started in and out of their places, playing at puss in the corner
+with other boys; there were laughing boys, singing boys, talking boys,
+dancing boys, howling boys; boys shuffled with their feet, boys whirled
+about him, grinning, making faces, mimicking him behind his back and
+before his eyes; mimicking his poverty, his boots, his coat, his mother,
+everything belonging to him that they should have had consideration for.
+
+'Silence!' cried Mr. Mell, suddenly rising up, and striking his desk
+with the book. 'What does this mean! It's impossible to bear it. It's
+maddening. How can you do it to me, boys?'
+
+It was my book that he struck his desk with; and as I stood beside him,
+following his eye as it glanced round the room, I saw the boys all stop,
+some suddenly surprised, some half afraid, and some sorry perhaps.
+
+Steerforth's place was at the bottom of the school, at the opposite end
+of the long room. He was lounging with his back against the wall, and
+his hands in his pockets, and looked at Mr. Mell with his mouth shut up
+as if he were whistling, when Mr. Mell looked at him.
+
+'Silence, Mr. Steerforth!' said Mr. Mell.
+
+'Silence yourself,' said Steerforth, turning red. 'Whom are you talking
+to?'
+
+'Sit down,' said Mr. Mell.
+
+'Sit down yourself,' said Steerforth, 'and mind your business.'
+
+There was a titter, and some applause; but Mr. Mell was so white, that
+silence immediately succeeded; and one boy, who had darted out behind
+him to imitate his mother again, changed his mind, and pretended to want
+a pen mended.
+
+'If you think, Steerforth,' said Mr. Mell, 'that I am not acquainted
+with the power you can establish over any mind here'--he laid his hand,
+without considering what he did (as I supposed), upon my head--'or that
+I have not observed you, within a few minutes, urging your juniors on to
+every sort of outrage against me, you are mistaken.'
+
+'I don't give myself the trouble of thinking at all about you,' said
+Steerforth, coolly; 'so I'm not mistaken, as it happens.'
+
+'And when you make use of your position of favouritism here, sir,'
+pursued Mr. Mell, with his lip trembling very much, 'to insult a
+gentleman--'
+
+'A what?--where is he?' said Steerforth.
+
+Here somebody cried out, 'Shame, J. Steerforth! Too bad!' It was
+Traddles; whom Mr. Mell instantly discomfited by bidding him hold his
+tongue. --'To insult one who is not fortunate in life, sir, and who
+never gave you the least offence, and the many reasons for not insulting
+whom you are old enough and wise enough to understand,' said Mr. Mell,
+with his lips trembling more and more, 'you commit a mean and base
+action. You can sit down or stand up as you please, sir. Copperfield, go
+on.'
+
+'Young Copperfield,' said Steerforth, coming forward up the room,
+'stop a bit. I tell you what, Mr. Mell, once for all. When you take the
+liberty of calling me mean or base, or anything of that sort, you are
+an impudent beggar. You are always a beggar, you know; but when you do
+that, you are an impudent beggar.'
+
+I am not clear whether he was going to strike Mr. Mell, or Mr. Mell was
+going to strike him, or there was any such intention on either side.
+I saw a rigidity come upon the whole school as if they had been turned
+into stone, and found Mr. Creakle in the midst of us, with Tungay at his
+side, and Mrs. and Miss Creakle looking in at the door as if they were
+frightened. Mr. Mell, with his elbows on his desk and his face in his
+hands, sat, for some moments, quite still.
+
+'Mr. Mell,' said Mr. Creakle, shaking him by the arm; and his whisper
+was so audible now, that Tungay felt it unnecessary to repeat his words;
+'you have not forgotten yourself, I hope?'
+
+'No, sir, no,' returned the Master, showing his face, and shaking his
+head, and rubbing his hands in great agitation. 'No, sir. No. I have
+remembered myself, I--no, Mr. Creakle, I have not forgotten myself, I--I
+have remembered myself, sir. I--I--could wish you had remembered me a
+little sooner, Mr. Creakle. It--it--would have been more kind, sir, more
+just, sir. It would have saved me something, sir.'
+
+Mr. Creakle, looking hard at Mr. Mell, put his hand on Tungay's
+shoulder, and got his feet upon the form close by, and sat upon the
+desk. After still looking hard at Mr. Mell from his throne, as he
+shook his head, and rubbed his hands, and remained in the same state of
+agitation, Mr. Creakle turned to Steerforth, and said:
+
+'Now, sir, as he don't condescend to tell me, what is this?'
+
+Steerforth evaded the question for a little while; looking in scorn and
+anger on his opponent, and remaining silent. I could not help thinking
+even in that interval, I remember, what a noble fellow he was in
+appearance, and how homely and plain Mr. Mell looked opposed to him.
+
+'What did he mean by talking about favourites, then?' said Steerforth at
+length.
+
+'Favourites?' repeated Mr. Creakle, with the veins in his forehead
+swelling quickly. 'Who talked about favourites?'
+
+'He did,' said Steerforth.
+
+'And pray, what did you mean by that, sir?' demanded Mr. Creakle,
+turning angrily on his assistant.
+
+'I meant, Mr. Creakle,' he returned in a low voice, 'as I said; that
+no pupil had a right to avail himself of his position of favouritism to
+degrade me.'
+
+'To degrade YOU?' said Mr. Creakle. 'My stars! But give me leave to ask
+you, Mr. What's-your-name'; and here Mr. Creakle folded his arms, cane
+and all, upon his chest, and made such a knot of his brows that his
+little eyes were hardly visible below them; 'whether, when you talk
+about favourites, you showed proper respect to me? To me, sir,' said Mr.
+Creakle, darting his head at him suddenly, and drawing it back again,
+'the principal of this establishment, and your employer.'
+
+'It was not judicious, sir, I am willing to admit,' said Mr. Mell. 'I
+should not have done so, if I had been cool.'
+
+Here Steerforth struck in.
+
+'Then he said I was mean, and then he said I was base, and then I called
+him a beggar. If I had been cool, perhaps I shouldn't have called him a
+beggar. But I did, and I am ready to take the consequences of it.'
+
+Without considering, perhaps, whether there were any consequences to
+be taken, I felt quite in a glow at this gallant speech. It made an
+impression on the boys too, for there was a low stir among them, though
+no one spoke a word.
+
+'I am surprised, Steerforth--although your candour does you honour,'
+said Mr. Creakle, 'does you honour, certainly--I am surprised,
+Steerforth, I must say, that you should attach such an epithet to any
+person employed and paid in Salem House, sir.'
+
+Steerforth gave a short laugh.
+
+'That's not an answer, sir,' said Mr. Creakle, 'to my remark. I expect
+more than that from you, Steerforth.'
+
+If Mr. Mell looked homely, in my eyes, before the handsome boy, it would
+be quite impossible to say how homely Mr. Creakle looked. 'Let him deny
+it,' said Steerforth.
+
+'Deny that he is a beggar, Steerforth?' cried Mr. Creakle. 'Why, where
+does he go a-begging?'
+
+'If he is not a beggar himself, his near relation's one,' said
+Steerforth. 'It's all the same.'
+
+He glanced at me, and Mr. Mell's hand gently patted me upon the
+shoulder. I looked up with a flush upon my face and remorse in my heart,
+but Mr. Mell's eyes were fixed on Steerforth. He continued to pat me
+kindly on the shoulder, but he looked at him.
+
+'Since you expect me, Mr. Creakle, to justify myself,' said Steerforth,
+'and to say what I mean,--what I have to say is, that his mother lives
+on charity in an alms-house.'
+
+Mr. Mell still looked at him, and still patted me kindly on the
+shoulder, and said to himself, in a whisper, if I heard right: 'Yes, I
+thought so.'
+
+Mr. Creakle turned to his assistant, with a severe frown and laboured
+politeness:
+
+'Now, you hear what this gentleman says, Mr. Mell. Have the goodness, if
+you please, to set him right before the assembled school.'
+
+'He is right, sir, without correction,' returned Mr. Mell, in the midst
+of a dead silence; 'what he has said is true.'
+
+'Be so good then as declare publicly, will you,' said Mr. Creakle,
+putting his head on one side, and rolling his eyes round the school,
+'whether it ever came to my knowledge until this moment?'
+
+'I believe not directly,' he returned.
+
+'Why, you know not,' said Mr. Creakle. 'Don't you, man?'
+
+'I apprehend you never supposed my worldly circumstances to be very
+good,' replied the assistant. 'You know what my position is, and always
+has been, here.'
+
+'I apprehend, if you come to that,' said Mr. Creakle, with his veins
+swelling again bigger than ever, 'that you've been in a wrong position
+altogether, and mistook this for a charity school. Mr. Mell, we'll part,
+if you please. The sooner the better.'
+
+'There is no time,' answered Mr. Mell, rising, 'like the present.'
+
+'Sir, to you!' said Mr. Creakle.
+
+'I take my leave of you, Mr. Creakle, and all of you,' said Mr. Mell,
+glancing round the room, and again patting me gently on the shoulders.
+'James Steerforth, the best wish I can leave you is that you may come to
+be ashamed of what you have done today. At present I would prefer to see
+you anything rather than a friend, to me, or to anyone in whom I feel an
+interest.'
+
+Once more he laid his hand upon my shoulder; and then taking his
+flute and a few books from his desk, and leaving the key in it for his
+successor, he went out of the school, with his property under his arm.
+Mr. Creakle then made a speech, through Tungay, in which he thanked
+Steerforth for asserting (though perhaps too warmly) the independence
+and respectability of Salem House; and which he wound up by shaking
+hands with Steerforth, while we gave three cheers--I did not quite know
+what for, but I supposed for Steerforth, and so joined in them ardently,
+though I felt miserable. Mr. Creakle then caned Tommy Traddles for
+being discovered in tears, instead of cheers, on account of Mr. Mell's
+departure; and went back to his sofa, or his bed, or wherever he had
+come from.
+
+We were left to ourselves now, and looked very blank, I recollect, on
+one another. For myself, I felt so much self-reproach and contrition for
+my part in what had happened, that nothing would have enabled me to keep
+back my tears but the fear that Steerforth, who often looked at me, I
+saw, might think it unfriendly--or, I should rather say, considering our
+relative ages, and the feeling with which I regarded him, undutiful--if
+I showed the emotion which distressed me. He was very angry with
+Traddles, and said he was glad he had caught it.
+
+Poor Traddles, who had passed the stage of lying with his head upon the
+desk, and was relieving himself as usual with a burst of skeletons, said
+he didn't care. Mr. Mell was ill-used.
+
+'Who has ill-used him, you girl?' said Steerforth.
+
+'Why, you have,' returned Traddles.
+
+'What have I done?' said Steerforth.
+
+'What have you done?' retorted Traddles. 'Hurt his feelings, and lost
+him his situation.'
+
+'His feelings?' repeated Steerforth disdainfully. 'His feelings will
+soon get the better of it, I'll be bound. His feelings are not like
+yours, Miss Traddles. As to his situation--which was a precious one,
+wasn't it?--do you suppose I am not going to write home, and take care
+that he gets some money? Polly?'
+
+We thought this intention very noble in Steerforth, whose mother was
+a widow, and rich, and would do almost anything, it was said, that he
+asked her. We were all extremely glad to see Traddles so put down,
+and exalted Steerforth to the skies: especially when he told us, as he
+condescended to do, that what he had done had been done expressly for
+us, and for our cause; and that he had conferred a great boon upon us
+by unselfishly doing it. But I must say that when I was going on with a
+story in the dark that night, Mr. Mell's old flute seemed more than once
+to sound mournfully in my ears; and that when at last Steerforth was
+tired, and I lay down in my bed, I fancied it playing so sorrowfully
+somewhere, that I was quite wretched.
+
+I soon forgot him in the contemplation of Steerforth, who, in an easy
+amateur way, and without any book (he seemed to me to know everything by
+heart), took some of his classes until a new master was found. The new
+master came from a grammar school; and before he entered on his duties,
+dined in the parlour one day, to be introduced to Steerforth. Steerforth
+approved of him highly, and told us he was a Brick. Without exactly
+understanding what learned distinction was meant by this, I respected
+him greatly for it, and had no doubt whatever of his superior knowledge:
+though he never took the pains with me--not that I was anybody--that Mr.
+Mell had taken.
+
+There was only one other event in this half-year, out of the daily
+school-life, that made an impression upon me which still survives. It
+survives for many reasons.
+
+One afternoon, when we were all harassed into a state of dire confusion,
+and Mr. Creakle was laying about him dreadfully, Tungay came in, and
+called out in his usual strong way: 'Visitors for Copperfield!'
+
+A few words were interchanged between him and Mr. Creakle, as, who the
+visitors were, and what room they were to be shown into; and then I, who
+had, according to custom, stood up on the announcement being made, and
+felt quite faint with astonishment, was told to go by the back stairs
+and get a clean frill on, before I repaired to the dining-room. These
+orders I obeyed, in such a flutter and hurry of my young spirits as
+I had never known before; and when I got to the parlour door, and the
+thought came into my head that it might be my mother--I had only thought
+of Mr. or Miss Murdstone until then--I drew back my hand from the lock,
+and stopped to have a sob before I went in.
+
+At first I saw nobody; but feeling a pressure against the door, I looked
+round it, and there, to my amazement, were Mr. Peggotty and Ham, ducking
+at me with their hats, and squeezing one another against the wall. I
+could not help laughing; but it was much more in the pleasure of seeing
+them, than at the appearance they made. We shook hands in a very
+cordial way; and I laughed and laughed, until I pulled out my
+pocket-handkerchief and wiped my eyes.
+
+Mr. Peggotty (who never shut his mouth once, I remember, during the
+visit) showed great concern when he saw me do this, and nudged Ham to
+say something.
+
+'Cheer up, Mas'r Davy bor'!' said Ham, in his simpering way. 'Why, how
+you have growed!'
+
+'Am I grown?' I said, drying my eyes. I was not crying at anything
+in particular that I know of; but somehow it made me cry, to see old
+friends.
+
+'Growed, Mas'r Davy bor'? Ain't he growed!' said Ham.
+
+'Ain't he growed!' said Mr. Peggotty.
+
+They made me laugh again by laughing at each other, and then we all
+three laughed until I was in danger of crying again.
+
+'Do you know how mama is, Mr. Peggotty?' I said. 'And how my dear, dear,
+old Peggotty is?'
+
+'Oncommon,' said Mr. Peggotty.
+
+'And little Em'ly, and Mrs. Gummidge?'
+
+'On--common,' said Mr. Peggotty.
+
+There was a silence. Mr. Peggotty, to relieve it, took two prodigious
+lobsters, and an enormous crab, and a large canvas bag of shrimps, out
+of his pockets, and piled them up in Ham's arms.
+
+'You see,' said Mr. Peggotty, 'knowing as you was partial to a little
+relish with your wittles when you was along with us, we took the
+liberty. The old Mawther biled 'em, she did. Mrs. Gummidge biled 'em.
+Yes,' said Mr. Peggotty, slowly, who I thought appeared to stick to the
+subject on account of having no other subject ready, 'Mrs. Gummidge, I
+do assure you, she biled 'em.'
+
+I expressed my thanks; and Mr. Peggotty, after looking at Ham, who stood
+smiling sheepishly over the shellfish, without making any attempt to
+help him, said:
+
+'We come, you see, the wind and tide making in our favour, in one of our
+Yarmouth lugs to Gravesen'. My sister she wrote to me the name of this
+here place, and wrote to me as if ever I chanced to come to Gravesen',
+I was to come over and inquire for Mas'r Davy and give her dooty,
+humbly wishing him well and reporting of the fam'ly as they was oncommon
+toe-be-sure. Little Em'ly, you see, she'll write to my sister when I go
+back, as I see you and as you was similarly oncommon, and so we make it
+quite a merry-go-rounder.'
+
+I was obliged to consider a little before I understood what Mr. Peggotty
+meant by this figure, expressive of a complete circle of intelligence. I
+then thanked him heartily; and said, with a consciousness of reddening,
+that I supposed little Em'ly was altered too, since we used to pick up
+shells and pebbles on the beach?
+
+'She's getting to be a woman, that's wot she's getting to be,' said Mr.
+Peggotty. 'Ask HIM.' He meant Ham, who beamed with delight and assent
+over the bag of shrimps.
+
+'Her pretty face!' said Mr. Peggotty, with his own shining like a light.
+
+'Her learning!' said Ham.
+
+'Her writing!' said Mr. Peggotty. 'Why it's as black as jet! And so
+large it is, you might see it anywheres.'
+
+It was perfectly delightful to behold with what enthusiasm Mr. Peggotty
+became inspired when he thought of his little favourite. He stands
+before me again, his bluff hairy face irradiating with a joyful love and
+pride, for which I can find no description. His honest eyes fire up, and
+sparkle, as if their depths were stirred by something bright. His broad
+chest heaves with pleasure. His strong loose hands clench themselves,
+in his earnestness; and he emphasizes what he says with a right arm that
+shows, in my pigmy view, like a sledge-hammer.
+
+Ham was quite as earnest as he. I dare say they would have said much
+more about her, if they had not been abashed by the unexpected coming in
+of Steerforth, who, seeing me in a corner speaking with two strangers,
+stopped in a song he was singing, and said: 'I didn't know you were
+here, young Copperfield!' (for it was not the usual visiting room) and
+crossed by us on his way out.
+
+I am not sure whether it was in the pride of having such a friend as
+Steerforth, or in the desire to explain to him how I came to have such a
+friend as Mr. Peggotty, that I called to him as he was going away. But I
+said, modestly--Good Heaven, how it all comes back to me this long time
+afterwards--!
+
+'Don't go, Steerforth, if you please. These are two Yarmouth
+boatmen--very kind, good people--who are relations of my nurse, and have
+come from Gravesend to see me.'
+
+'Aye, aye?' said Steerforth, returning. 'I am glad to see them. How are
+you both?'
+
+There was an ease in his manner--a gay and light manner it was, but not
+swaggering--which I still believe to have borne a kind of enchantment
+with it. I still believe him, in virtue of this carriage, his animal
+spirits, his delightful voice, his handsome face and figure, and, for
+aught I know, of some inborn power of attraction besides (which I think
+a few people possess), to have carried a spell with him to which it was
+a natural weakness to yield, and which not many persons could withstand.
+I could not but see how pleased they were with him, and how they seemed
+to open their hearts to him in a moment.
+
+'You must let them know at home, if you please, Mr. Peggotty,' I said,
+'when that letter is sent, that Mr. Steerforth is very kind to me, and
+that I don't know what I should ever do here without him.'
+
+'Nonsense!' said Steerforth, laughing. 'You mustn't tell them anything
+of the sort.'
+
+'And if Mr. Steerforth ever comes into Norfolk or Suffolk, Mr.
+Peggotty,' I said, 'while I am there, you may depend upon it I shall
+bring him to Yarmouth, if he will let me, to see your house. You never
+saw such a good house, Steerforth. It's made out of a boat!'
+
+'Made out of a boat, is it?' said Steerforth. 'It's the right sort of a
+house for such a thorough-built boatman.'
+
+'So 'tis, sir, so 'tis, sir,' said Ham, grinning. 'You're right, young
+gen'l'm'n! Mas'r Davy bor', gen'l'm'n's right. A thorough-built boatman!
+Hor, hor! That's what he is, too!'
+
+Mr. Peggotty was no less pleased than his nephew, though his modesty
+forbade him to claim a personal compliment so vociferously.
+
+'Well, sir,' he said, bowing and chuckling, and tucking in the ends
+of his neckerchief at his breast: 'I thankee, sir, I thankee! I do my
+endeavours in my line of life, sir.'
+
+'The best of men can do no more, Mr. Peggotty,' said Steerforth. He had
+got his name already.
+
+'I'll pound it, it's wot you do yourself, sir,' said Mr. Peggotty,
+shaking his head, 'and wot you do well--right well! I thankee, sir. I'm
+obleeged to you, sir, for your welcoming manner of me. I'm rough, sir,
+but I'm ready--least ways, I hope I'm ready, you unnerstand. My house
+ain't much for to see, sir, but it's hearty at your service if ever you
+should come along with Mas'r Davy to see it. I'm a reg'lar Dodman,
+I am,' said Mr. Peggotty, by which he meant snail, and this was in
+allusion to his being slow to go, for he had attempted to go after every
+sentence, and had somehow or other come back again; 'but I wish you both
+well, and I wish you happy!'
+
+Ham echoed this sentiment, and we parted with them in the heartiest
+manner. I was almost tempted that evening to tell Steerforth about
+pretty little Em'ly, but I was too timid of mentioning her name, and
+too much afraid of his laughing at me. I remember that I thought a good
+deal, and in an uneasy sort of way, about Mr. Peggotty having said that
+she was getting on to be a woman; but I decided that was nonsense.
+
+We transported the shellfish, or the 'relish' as Mr. Peggotty had
+modestly called it, up into our room unobserved, and made a great supper
+that evening. But Traddles couldn't get happily out of it. He was too
+unfortunate even to come through a supper like anybody else. He was
+taken ill in the night--quite prostrate he was--in consequence of Crab;
+and after being drugged with black draughts and blue pills, to an extent
+which Demple (whose father was a doctor) said was enough to undermine
+a horse's constitution, received a caning and six chapters of Greek
+Testament for refusing to confess.
+
+The rest of the half-year is a jumble in my recollection of the daily
+strife and struggle of our lives; of the waning summer and the changing
+season; of the frosty mornings when we were rung out of bed, and the
+cold, cold smell of the dark nights when we were rung into bed again; of
+the evening schoolroom dimly lighted and indifferently warmed, and the
+morning schoolroom which was nothing but a great shivering-machine; of
+the alternation of boiled beef with roast beef, and boiled mutton with
+roast mutton; of clods of bread-and-butter, dog's-eared lesson-books,
+cracked slates, tear-blotted copy-books, canings, rulerings,
+hair-cuttings, rainy Sundays, suet-puddings, and a dirty atmosphere of
+ink, surrounding all.
+
+I well remember though, how the distant idea of the holidays, after
+seeming for an immense time to be a stationary speck, began to come
+towards us, and to grow and grow. How from counting months, we came to
+weeks, and then to days; and how I then began to be afraid that I should
+not be sent for and when I learnt from Steerforth that I had been sent
+for, and was certainly to go home, had dim forebodings that I might
+break my leg first. How the breaking-up day changed its place fast, at
+last, from the week after next to next week, this week, the day after
+tomorrow, tomorrow, today, tonight--when I was inside the Yarmouth mail,
+and going home.
+
+I had many a broken sleep inside the Yarmouth mail, and many an
+incoherent dream of all these things. But when I awoke at intervals, the
+ground outside the window was not the playground of Salem House, and the
+sound in my ears was not the sound of Mr. Creakle giving it to Traddles,
+but the sound of the coachman touching up the horses.
+
+
+
+CHAPTER 8. MY HOLIDAYS. ESPECIALLY ONE HAPPY AFTERNOON
+
+
+When we arrived before day at the inn where the mail stopped, which was
+not the inn where my friend the waiter lived, I was shown up to a nice
+little bedroom, with DOLPHIN painted on the door. Very cold I was, I
+know, notwithstanding the hot tea they had given me before a large fire
+downstairs; and very glad I was to turn into the Dolphin's bed, pull the
+Dolphin's blankets round my head, and go to sleep.
+
+Mr. Barkis the carrier was to call for me in the morning at nine
+o'clock. I got up at eight, a little giddy from the shortness of my
+night's rest, and was ready for him before the appointed time. He
+received me exactly as if not five minutes had elapsed since we were
+last together, and I had only been into the hotel to get change for
+sixpence, or something of that sort.
+
+As soon as I and my box were in the cart, and the carrier seated, the
+lazy horse walked away with us all at his accustomed pace.
+
+'You look very well, Mr. Barkis,' I said, thinking he would like to know
+it.
+
+Mr. Barkis rubbed his cheek with his cuff, and then looked at his cuff
+as if he expected to find some of the bloom upon it; but made no other
+acknowledgement of the compliment.
+
+'I gave your message, Mr. Barkis,' I said: 'I wrote to Peggotty.'
+
+'Ah!' said Mr. Barkis.
+
+Mr. Barkis seemed gruff, and answered drily.
+
+'Wasn't it right, Mr. Barkis?' I asked, after a little hesitation.
+
+'Why, no,' said Mr. Barkis.
+
+'Not the message?'
+
+'The message was right enough, perhaps,' said Mr. Barkis; 'but it come
+to an end there.'
+
+Not understanding what he meant, I repeated inquisitively: 'Came to an
+end, Mr. Barkis?'
+
+'Nothing come of it,' he explained, looking at me sideways. 'No answer.'
+
+'There was an answer expected, was there, Mr. Barkis?' said I, opening
+my eyes. For this was a new light to me.
+
+'When a man says he's willin',' said Mr. Barkis, turning his glance
+slowly on me again, 'it's as much as to say, that man's a-waitin' for a
+answer.'
+
+'Well, Mr. Barkis?'
+
+'Well,' said Mr. Barkis, carrying his eyes back to his horse's ears;
+'that man's been a-waitin' for a answer ever since.'
+
+'Have you told her so, Mr. Barkis?'
+
+'No--no,' growled Mr. Barkis, reflecting about it. 'I ain't got no call
+to go and tell her so. I never said six words to her myself, I ain't
+a-goin' to tell her so.'
+
+'Would you like me to do it, Mr. Barkis?' said I, doubtfully. 'You might
+tell her, if you would,' said Mr. Barkis, with another slow look at me,
+'that Barkis was a-waitin' for a answer. Says you--what name is it?'
+
+'Her name?'
+
+'Ah!' said Mr. Barkis, with a nod of his head.
+
+'Peggotty.'
+
+'Chrisen name? Or nat'ral name?' said Mr. Barkis.
+
+'Oh, it's not her Christian name. Her Christian name is Clara.'
+
+'Is it though?' said Mr. Barkis.
+
+He seemed to find an immense fund of reflection in this circumstance,
+and sat pondering and inwardly whistling for some time.
+
+'Well!' he resumed at length. 'Says you, "Peggotty! Barkis is waitin'
+for a answer." Says she, perhaps, "Answer to what?" Says you, "To what I
+told you." "What is that?" says she. "Barkis is willin'," says you.'
+
+This extremely artful suggestion Mr. Barkis accompanied with a nudge
+of his elbow that gave me quite a stitch in my side. After that, he
+slouched over his horse in his usual manner; and made no other reference
+to the subject except, half an hour afterwards, taking a piece of chalk
+from his pocket, and writing up, inside the tilt of the cart, 'Clara
+Peggotty'--apparently as a private memorandum.
+
+Ah, what a strange feeling it was to be going home when it was not home,
+and to find that every object I looked at, reminded me of the happy old
+home, which was like a dream I could never dream again! The days when my
+mother and I and Peggotty were all in all to one another, and there was
+no one to come between us, rose up before me so sorrowfully on the road,
+that I am not sure I was glad to be there--not sure but that I would
+rather have remained away, and forgotten it in Steerforth's company. But
+there I was; and soon I was at our house, where the bare old elm-trees
+wrung their many hands in the bleak wintry air, and shreds of the old
+rooks'-nests drifted away upon the wind.
+
+The carrier put my box down at the garden-gate, and left me. I walked
+along the path towards the house, glancing at the windows, and fearing
+at every step to see Mr. Murdstone or Miss Murdstone lowering out of
+one of them. No face appeared, however; and being come to the house, and
+knowing how to open the door, before dark, without knocking, I went in
+with a quiet, timid step.
+
+God knows how infantine the memory may have been, that was awakened
+within me by the sound of my mother's voice in the old parlour, when I
+set foot in the hall. She was singing in a low tone. I think I must have
+lain in her arms, and heard her singing so to me when I was but a baby.
+The strain was new to me, and yet it was so old that it filled my heart
+brim-full; like a friend come back from a long absence.
+
+I believed, from the solitary and thoughtful way in which my mother
+murmured her song, that she was alone. And I went softly into the room.
+She was sitting by the fire, suckling an infant, whose tiny hand she
+held against her neck. Her eyes were looking down upon its face, and she
+sat singing to it. I was so far right, that she had no other companion.
+
+I spoke to her, and she started, and cried out. But seeing me, she
+called me her dear Davy, her own boy! and coming half across the room
+to meet me, kneeled down upon the ground and kissed me, and laid my head
+down on her bosom near the little creature that was nestling there, and
+put its hand to my lips.
+
+I wish I had died. I wish I had died then, with that feeling in my
+heart! I should have been more fit for Heaven than I ever have been
+since.
+
+'He is your brother,' said my mother, fondling me. 'Davy, my pretty boy!
+My poor child!' Then she kissed me more and more, and clasped me round
+the neck. This she was doing when Peggotty came running in, and bounced
+down on the ground beside us, and went mad about us both for a quarter
+of an hour.
+
+It seemed that I had not been expected so soon, the carrier being much
+before his usual time. It seemed, too, that Mr. and Miss Murdstone had
+gone out upon a visit in the neighbourhood, and would not return before
+night. I had never hoped for this. I had never thought it possible that
+we three could be together undisturbed, once more; and I felt, for the
+time, as if the old days were come back.
+
+We dined together by the fireside. Peggotty was in attendance to wait
+upon us, but my mother wouldn't let her do it, and made her dine with
+us. I had my own old plate, with a brown view of a man-of-war in full
+sail upon it, which Peggotty had hoarded somewhere all the time I
+had been away, and would not have had broken, she said, for a hundred
+pounds. I had my own old mug with David on it, and my own old little
+knife and fork that wouldn't cut.
+
+While we were at table, I thought it a favourable occasion to tell
+Peggotty about Mr. Barkis, who, before I had finished what I had to tell
+her, began to laugh, and throw her apron over her face.
+
+'Peggotty,' said my mother. 'What's the matter?'
+
+Peggotty only laughed the more, and held her apron tight over her face
+when my mother tried to pull it away, and sat as if her head were in a
+bag.
+
+'What are you doing, you stupid creature?' said my mother, laughing.
+
+'Oh, drat the man!' cried Peggotty. 'He wants to marry me.'
+
+'It would be a very good match for you; wouldn't it?' said my mother.
+
+'Oh! I don't know,' said Peggotty. 'Don't ask me. I wouldn't have him if
+he was made of gold. Nor I wouldn't have anybody.'
+
+'Then, why don't you tell him so, you ridiculous thing?' said my mother.
+
+'Tell him so,' retorted Peggotty, looking out of her apron. 'He has
+never said a word to me about it. He knows better. If he was to make so
+bold as say a word to me, I should slap his face.'
+
+Her own was as red as ever I saw it, or any other face, I think; but she
+only covered it again, for a few moments at a time, when she was taken
+with a violent fit of laughter; and after two or three of those attacks,
+went on with her dinner.
+
+I remarked that my mother, though she smiled when Peggotty looked at
+her, became more serious and thoughtful. I had seen at first that she
+was changed. Her face was very pretty still, but it looked careworn, and
+too delicate; and her hand was so thin and white that it seemed to me
+to be almost transparent. But the change to which I now refer was
+superadded to this: it was in her manner, which became anxious and
+fluttered. At last she said, putting out her hand, and laying it
+affectionately on the hand of her old servant,
+
+'Peggotty, dear, you are not going to be married?'
+
+'Me, ma'am?' returned Peggotty, staring. 'Lord bless you, no!'
+
+'Not just yet?' said my mother, tenderly.
+
+'Never!' cried Peggotty.
+
+My mother took her hand, and said:
+
+'Don't leave me, Peggotty. Stay with me. It will not be for long,
+perhaps. What should I ever do without you!'
+
+'Me leave you, my precious!' cried Peggotty. 'Not for all the world and
+his wife. Why, what's put that in your silly little head?'--For Peggotty
+had been used of old to talk to my mother sometimes like a child.
+
+But my mother made no answer, except to thank her, and Peggotty went
+running on in her own fashion.
+
+'Me leave you? I think I see myself. Peggotty go away from you? I should
+like to catch her at it! No, no, no,' said Peggotty, shaking her head,
+and folding her arms; 'not she, my dear. It isn't that there ain't some
+Cats that would be well enough pleased if she did, but they sha'n't be
+pleased. They shall be aggravated. I'll stay with you till I am a cross
+cranky old woman. And when I'm too deaf, and too lame, and too blind,
+and too mumbly for want of teeth, to be of any use at all, even to be
+found fault with, than I shall go to my Davy, and ask him to take me
+in.'
+
+'And, Peggotty,' says I, 'I shall be glad to see you, and I'll make you
+as welcome as a queen.'
+
+'Bless your dear heart!' cried Peggotty. 'I know you will!' And she
+kissed me beforehand, in grateful acknowledgement of my hospitality.
+After that, she covered her head up with her apron again and had another
+laugh about Mr. Barkis. After that, she took the baby out of its little
+cradle, and nursed it. After that, she cleared the dinner table;
+after that, came in with another cap on, and her work-box, and the
+yard-measure, and the bit of wax-candle, all just the same as ever.
+
+We sat round the fire, and talked delightfully. I told them what a hard
+master Mr. Creakle was, and they pitied me very much. I told them what a
+fine fellow Steerforth was, and what a patron of mine, and Peggotty said
+she would walk a score of miles to see him. I took the little baby in
+my arms when it was awake, and nursed it lovingly. When it was asleep
+again, I crept close to my mother's side according to my old custom,
+broken now a long time, and sat with my arms embracing her waist, and my
+little red cheek on her shoulder, and once more felt her beautiful
+hair drooping over me--like an angel's wing as I used to think, I
+recollect--and was very happy indeed.
+
+While I sat thus, looking at the fire, and seeing pictures in the
+red-hot coals, I almost believed that I had never been away; that Mr.
+and Miss Murdstone were such pictures, and would vanish when the fire
+got low; and that there was nothing real in all that I remembered, save
+my mother, Peggotty, and I.
+
+Peggotty darned away at a stocking as long as she could see, and then
+sat with it drawn on her left hand like a glove, and her needle in her
+right, ready to take another stitch whenever there was a blaze. I cannot
+conceive whose stockings they can have been that Peggotty was always
+darning, or where such an unfailing supply of stockings in want of
+darning can have come from. From my earliest infancy she seems to have
+been always employed in that class of needlework, and never by any
+chance in any other.
+
+'I wonder,' said Peggotty, who was sometimes seized with a fit of
+wondering on some most unexpected topic, 'what's become of Davy's
+great-aunt?' 'Lor, Peggotty!' observed my mother, rousing herself from a
+reverie, 'what nonsense you talk!'
+
+'Well, but I really do wonder, ma'am,' said Peggotty.
+
+'What can have put such a person in your head?' inquired my mother. 'Is
+there nobody else in the world to come there?'
+
+'I don't know how it is,' said Peggotty, 'unless it's on account of
+being stupid, but my head never can pick and choose its people. They
+come and they go, and they don't come and they don't go, just as they
+like. I wonder what's become of her?'
+
+'How absurd you are, Peggotty!' returned my mother. 'One would suppose
+you wanted a second visit from her.'
+
+'Lord forbid!' cried Peggotty.
+
+'Well then, don't talk about such uncomfortable things, there's a good
+soul,' said my mother. 'Miss Betsey is shut up in her cottage by the
+sea, no doubt, and will remain there. At all events, she is not likely
+ever to trouble us again.'
+
+'No!' mused Peggotty. 'No, that ain't likely at all.---I wonder, if she
+was to die, whether she'd leave Davy anything?'
+
+'Good gracious me, Peggotty,' returned my mother, 'what a nonsensical
+woman you are! when you know that she took offence at the poor dear
+boy's ever being born at all.'
+
+'I suppose she wouldn't be inclined to forgive him now,' hinted
+Peggotty.
+
+'Why should she be inclined to forgive him now?' said my mother, rather
+sharply.
+
+'Now that he's got a brother, I mean,' said Peggotty.
+
+MY mother immediately began to cry, and wondered how Peggotty dared to
+say such a thing.
+
+'As if this poor little innocent in its cradle had ever done any harm to
+you or anybody else, you jealous thing!' said she. 'You had much better
+go and marry Mr. Barkis, the carrier. Why don't you?'
+
+'I should make Miss Murdstone happy, if I was to,' said Peggotty.
+
+'What a bad disposition you have, Peggotty!' returned my mother. 'You
+are as jealous of Miss Murdstone as it is possible for a ridiculous
+creature to be. You want to keep the keys yourself, and give out all the
+things, I suppose? I shouldn't be surprised if you did. When you know
+that she only does it out of kindness and the best intentions! You know
+she does, Peggotty--you know it well.'
+
+Peggotty muttered something to the effect of 'Bother the best
+intentions!' and something else to the effect that there was a little
+too much of the best intentions going on.
+
+'I know what you mean, you cross thing,' said my mother. 'I understand
+you, Peggotty, perfectly. You know I do, and I wonder you don't colour
+up like fire. But one point at a time. Miss Murdstone is the point now,
+Peggotty, and you sha'n't escape from it. Haven't you heard her
+say, over and over again, that she thinks I am too thoughtless and
+too--a--a--'
+
+'Pretty,' suggested Peggotty.
+
+'Well,' returned my mother, half laughing, 'and if she is so silly as to
+say so, can I be blamed for it?'
+
+'No one says you can,' said Peggotty.
+
+'No, I should hope not, indeed!' returned my mother. 'Haven't you heard
+her say, over and over again, that on this account she wished to spare
+me a great deal of trouble, which she thinks I am not suited for, and
+which I really don't know myself that I AM suited for; and isn't she up
+early and late, and going to and fro continually--and doesn't she do
+all sorts of things, and grope into all sorts of places, coal-holes and
+pantries and I don't know where, that can't be very agreeable--and do
+you mean to insinuate that there is not a sort of devotion in that?'
+
+'I don't insinuate at all,' said Peggotty.
+
+'You do, Peggotty,' returned my mother. 'You never do anything else,
+except your work. You are always insinuating. You revel in it. And when
+you talk of Mr. Murdstone's good intentions--'
+
+'I never talked of 'em,' said Peggotty.
+
+'No, Peggotty,' returned my mother, 'but you insinuated. That's what I
+told you just now. That's the worst of you. You WILL insinuate. I said,
+at the moment, that I understood you, and you see I did. When you talk
+of Mr. Murdstone's good intentions, and pretend to slight them (for I
+don't believe you really do, in your heart, Peggotty), you must be as
+well convinced as I am how good they are, and how they actuate him in
+everything. If he seems to have been at all stern with a certain person,
+Peggotty--you understand, and so I am sure does Davy, that I am not
+alluding to anybody present--it is solely because he is satisfied that
+it is for a certain person's benefit. He naturally loves a certain
+person, on my account; and acts solely for a certain person's good. He
+is better able to judge of it than I am; for I very well know that I am
+a weak, light, girlish creature, and that he is a firm, grave, serious
+man. And he takes,' said my mother, with the tears which were engendered
+in her affectionate nature, stealing down her face, 'he takes great
+pains with me; and I ought to be very thankful to him, and very
+submissive to him even in my thoughts; and when I am not, Peggotty, I
+worry and condemn myself, and feel doubtful of my own heart, and don't
+know what to do.'
+
+Peggotty sat with her chin on the foot of the stocking, looking silently
+at the fire.
+
+'There, Peggotty,' said my mother, changing her tone, 'don't let us fall
+out with one another, for I couldn't bear it. You are my true friend, I
+know, if I have any in the world. When I call you a ridiculous creature,
+or a vexatious thing, or anything of that sort, Peggotty, I only mean
+that you are my true friend, and always have been, ever since the night
+when Mr. Copperfield first brought me home here, and you came out to the
+gate to meet me.'
+
+Peggotty was not slow to respond, and ratify the treaty of friendship by
+giving me one of her best hugs. I think I had some glimpses of the real
+character of this conversation at the time; but I am sure, now, that
+the good creature originated it, and took her part in it, merely that
+my mother might comfort herself with the little contradictory summary in
+which she had indulged. The design was efficacious; for I remember that
+my mother seemed more at ease during the rest of the evening, and that
+Peggotty observed her less.
+
+When we had had our tea, and the ashes were thrown up, and the candles
+snuffed, I read Peggotty a chapter out of the Crocodile Book, in
+remembrance of old times--she took it out of her pocket: I don't know
+whether she had kept it there ever since--and then we talked about Salem
+House, which brought me round again to Steerforth, who was my great
+subject. We were very happy; and that evening, as the last of its race,
+and destined evermore to close that volume of my life, will never pass
+out of my memory.
+
+It was almost ten o'clock before we heard the sound of wheels. We all
+got up then; and my mother said hurriedly that, as it was so late, and
+Mr. and Miss Murdstone approved of early hours for young people, perhaps
+I had better go to bed. I kissed her, and went upstairs with my candle
+directly, before they came in. It appeared to my childish fancy, as I
+ascended to the bedroom where I had been imprisoned, that they brought
+a cold blast of air into the house which blew away the old familiar
+feeling like a feather.
+
+I felt uncomfortable about going down to breakfast in the morning, as
+I had never set eyes on Mr. Murdstone since the day when I committed my
+memorable offence. However, as it must be done, I went down, after two
+or three false starts half-way, and as many runs back on tiptoe to my
+own room, and presented myself in the parlour.
+
+He was standing before the fire with his back to it, while Miss
+Murdstone made the tea. He looked at me steadily as I entered, but made
+no sign of recognition whatever. I went up to him, after a moment of
+confusion, and said: 'I beg your pardon, sir. I am very sorry for what I
+did, and I hope you will forgive me.'
+
+'I am glad to hear you are sorry, David,' he replied.
+
+The hand he gave me was the hand I had bitten. I could not restrain my
+eye from resting for an instant on a red spot upon it; but it was not so
+red as I turned, when I met that sinister expression in his face.
+
+'How do you do, ma'am?' I said to Miss Murdstone.
+
+'Ah, dear me!' sighed Miss Murdstone, giving me the tea-caddy scoop
+instead of her fingers. 'How long are the holidays?'
+
+'A month, ma'am.'
+
+'Counting from when?'
+
+'From today, ma'am.'
+
+'Oh!' said Miss Murdstone. 'Then here's one day off.'
+
+She kept a calendar of the holidays in this way, and every morning
+checked a day off in exactly the same manner. She did it gloomily until
+she came to ten, but when she got into two figures she became more
+hopeful, and, as the time advanced, even jocular.
+
+It was on this very first day that I had the misfortune to throw her,
+though she was not subject to such weakness in general, into a state of
+violent consternation. I came into the room where she and my mother
+were sitting; and the baby (who was only a few weeks old) being on
+my mother's lap, I took it very carefully in my arms. Suddenly Miss
+Murdstone gave such a scream that I all but dropped it.
+
+'My dear Jane!' cried my mother.
+
+'Good heavens, Clara, do you see?' exclaimed Miss Murdstone.
+
+'See what, my dear Jane?' said my mother; 'where?'
+
+'He's got it!' cried Miss Murdstone. 'The boy has got the baby!'
+
+She was limp with horror; but stiffened herself to make a dart at me,
+and take it out of my arms. Then, she turned faint; and was so very
+ill that they were obliged to give her cherry brandy. I was solemnly
+interdicted by her, on her recovery, from touching my brother any more
+on any pretence whatever; and my poor mother, who, I could see, wished
+otherwise, meekly confirmed the interdict, by saying: 'No doubt you are
+right, my dear Jane.'
+
+On another occasion, when we three were together, this same dear
+baby--it was truly dear to me, for our mother's sake--was the innocent
+occasion of Miss Murdstone's going into a passion. My mother, who had
+been looking at its eyes as it lay upon her lap, said:
+
+'Davy! come here!' and looked at mine.
+
+I saw Miss Murdstone lay her beads down.
+
+'I declare,' said my mother, gently, 'they are exactly alike. I suppose
+they are mine. I think they are the colour of mine. But they are
+wonderfully alike.'
+
+'What are you talking about, Clara?' said Miss Murdstone.
+
+'My dear Jane,' faltered my mother, a little abashed by the harsh tone
+of this inquiry, 'I find that the baby's eyes and Davy's are exactly
+alike.'
+
+'Clara!' said Miss Murdstone, rising angrily, 'you are a positive fool
+sometimes.'
+
+'My dear Jane,' remonstrated my mother.
+
+'A positive fool,' said Miss Murdstone. 'Who else could compare my
+brother's baby with your boy? They are not at all alike. They are
+exactly unlike. They are utterly dissimilar in all respects. I hope
+they will ever remain so. I will not sit here, and hear such comparisons
+made.' With that she stalked out, and made the door bang after her.
+
+In short, I was not a favourite with Miss Murdstone. In short, I was not
+a favourite there with anybody, not even with myself; for those who did
+like me could not show it, and those who did not, showed it so plainly
+that I had a sensitive consciousness of always appearing constrained,
+boorish, and dull.
+
+I felt that I made them as uncomfortable as they made me. If I came into
+the room where they were, and they were talking together and my mother
+seemed cheerful, an anxious cloud would steal over her face from the
+moment of my entrance. If Mr. Murdstone were in his best humour, I
+checked him. If Miss Murdstone were in her worst, I intensified it. I
+had perception enough to know that my mother was the victim always; that
+she was afraid to speak to me or to be kind to me, lest she should
+give them some offence by her manner of doing so, and receive a
+lecture afterwards; that she was not only ceaselessly afraid of her own
+offending, but of my offending, and uneasily watched their looks if I
+only moved. Therefore I resolved to keep myself as much out of their way
+as I could; and many a wintry hour did I hear the church clock strike,
+when I was sitting in my cheerless bedroom, wrapped in my little
+great-coat, poring over a book.
+
+In the evening, sometimes, I went and sat with Peggotty in the kitchen.
+There I was comfortable, and not afraid of being myself. But neither of
+these resources was approved of in the parlour. The tormenting humour
+which was dominant there stopped them both. I was still held to be
+necessary to my poor mother's training, and, as one of her trials, could
+not be suffered to absent myself.
+
+'David,' said Mr. Murdstone, one day after dinner when I was going to
+leave the room as usual; 'I am sorry to observe that you are of a sullen
+disposition.'
+
+'As sulky as a bear!' said Miss Murdstone.
+
+I stood still, and hung my head.
+
+'Now, David,' said Mr. Murdstone, 'a sullen obdurate disposition is, of
+all tempers, the worst.'
+
+'And the boy's is, of all such dispositions that ever I have seen,'
+remarked his sister, 'the most confirmed and stubborn. I think, my dear
+Clara, even you must observe it?'
+
+'I beg your pardon, my dear Jane,' said my mother, 'but are you quite
+sure--I am certain you'll excuse me, my dear Jane--that you understand
+Davy?'
+
+'I should be somewhat ashamed of myself, Clara,' returned Miss
+Murdstone, 'if I could not understand the boy, or any boy. I don't
+profess to be profound; but I do lay claim to common sense.'
+
+'No doubt, my dear Jane,' returned my mother, 'your understanding is
+very vigorous--'
+
+'Oh dear, no! Pray don't say that, Clara,' interposed Miss Murdstone,
+angrily.
+
+'But I am sure it is,' resumed my mother; 'and everybody knows it is. I
+profit so much by it myself, in many ways--at least I ought to--that no
+one can be more convinced of it than myself; and therefore I speak with
+great diffidence, my dear Jane, I assure you.'
+
+'We'll say I don't understand the boy, Clara,' returned Miss Murdstone,
+arranging the little fetters on her wrists. 'We'll agree, if you please,
+that I don't understand him at all. He is much too deep for me. But
+perhaps my brother's penetration may enable him to have some insight
+into his character. And I believe my brother was speaking on the subject
+when we--not very decently--interrupted him.'
+
+'I think, Clara,' said Mr. Murdstone, in a low grave voice, 'that there
+may be better and more dispassionate judges of such a question than
+you.'
+
+'Edward,' replied my mother, timidly, 'you are a far better judge of all
+questions than I pretend to be. Both you and Jane are. I only said--'
+
+'You only said something weak and inconsiderate,' he replied. 'Try not
+to do it again, my dear Clara, and keep a watch upon yourself.'
+
+MY mother's lips moved, as if she answered 'Yes, my dear Edward,' but
+she said nothing aloud.
+
+'I was sorry, David, I remarked,' said Mr. Murdstone, turning his head
+and his eyes stiffly towards me, 'to observe that you are of a sullen
+disposition. This is not a character that I can suffer to develop itself
+beneath my eyes without an effort at improvement. You must endeavour,
+sir, to change it. We must endeavour to change it for you.'
+
+'I beg your pardon, sir,' I faltered. 'I have never meant to be sullen
+since I came back.'
+
+'Don't take refuge in a lie, sir!' he returned so fiercely, that I saw
+my mother involuntarily put out her trembling hand as if to interpose
+between us. 'You have withdrawn yourself in your sullenness to your own
+room. You have kept your own room when you ought to have been here. You
+know now, once for all, that I require you to be here, and not there.
+Further, that I require you to bring obedience here. You know me, David.
+I will have it done.'
+
+Miss Murdstone gave a hoarse chuckle.
+
+'I will have a respectful, prompt, and ready bearing towards myself,' he
+continued, 'and towards Jane Murdstone, and towards your mother. I will
+not have this room shunned as if it were infected, at the pleasure of a
+child. Sit down.'
+
+He ordered me like a dog, and I obeyed like a dog.
+
+'One thing more,' he said. 'I observe that you have an attachment to low
+and common company. You are not to associate with servants. The
+kitchen will not improve you, in the many respects in which you need
+improvement. Of the woman who abets you, I say nothing--since you,
+Clara,' addressing my mother in a lower voice, 'from old associations
+and long-established fancies, have a weakness respecting her which is
+not yet overcome.'
+
+'A most unaccountable delusion it is!' cried Miss Murdstone.
+
+'I only say,' he resumed, addressing me, 'that I disapprove of your
+preferring such company as Mistress Peggotty, and that it is to be
+abandoned. Now, David, you understand me, and you know what will be the
+consequence if you fail to obey me to the letter.'
+
+I knew well--better perhaps than he thought, as far as my poor mother
+was concerned--and I obeyed him to the letter. I retreated to my own
+room no more; I took refuge with Peggotty no more; but sat wearily in
+the parlour day after day, looking forward to night, and bedtime.
+
+What irksome constraint I underwent, sitting in the same attitude hours
+upon hours, afraid to move an arm or a leg lest Miss Murdstone should
+complain (as she did on the least pretence) of my restlessness, and
+afraid to move an eye lest she should light on some look of dislike
+or scrutiny that would find new cause for complaint in mine! What
+intolerable dulness to sit listening to the ticking of the clock; and
+watching Miss Murdstone's little shiny steel beads as she strung them;
+and wondering whether she would ever be married, and if so, to what
+sort of unhappy man; and counting the divisions in the moulding of the
+chimney-piece; and wandering away, with my eyes, to the ceiling, among
+the curls and corkscrews in the paper on the wall!
+
+What walks I took alone, down muddy lanes, in the bad winter weather,
+carrying that parlour, and Mr. and Miss Murdstone in it, everywhere: a
+monstrous load that I was obliged to bear, a daymare that there was
+no possibility of breaking in, a weight that brooded on my wits, and
+blunted them!
+
+What meals I had in silence and embarrassment, always feeling that there
+were a knife and fork too many, and that mine; an appetite too many, and
+that mine; a plate and chair too many, and those mine; a somebody too
+many, and that I!
+
+What evenings, when the candles came, and I was expected to employ
+myself, but, not daring to read an entertaining book, pored over some
+hard-headed, harder-hearted treatise on arithmetic; when the tables of
+weights and measures set themselves to tunes, as 'Rule Britannia', or
+'Away with Melancholy'; when they wouldn't stand still to be learnt, but
+would go threading my grandmother's needle through my unfortunate head,
+in at one ear and out at the other! What yawns and dozes I lapsed into,
+in spite of all my care; what starts I came out of concealed sleeps
+with; what answers I never got, to little observations that I rarely
+made; what a blank space I seemed, which everybody overlooked, and
+yet was in everybody's way; what a heavy relief it was to hear Miss
+Murdstone hail the first stroke of nine at night, and order me to bed!
+
+Thus the holidays lagged away, until the morning came when Miss
+Murdstone said: 'Here's the last day off!' and gave me the closing cup
+of tea of the vacation.
+
+I was not sorry to go. I had lapsed into a stupid state; but I was
+recovering a little and looking forward to Steerforth, albeit Mr.
+Creakle loomed behind him. Again Mr. Barkis appeared at the gate, and
+again Miss Murdstone in her warning voice, said: 'Clara!' when my mother
+bent over me, to bid me farewell.
+
+I kissed her, and my baby brother, and was very sorry then; but not
+sorry to go away, for the gulf between us was there, and the parting was
+there, every day. And it is not so much the embrace she gave me, that
+lives in my mind, though it was as fervent as could be, as what followed
+the embrace.
+
+I was in the carrier's cart when I heard her calling to me. I looked
+out, and she stood at the garden-gate alone, holding her baby up in her
+arms for me to see. It was cold still weather; and not a hair of her
+head, nor a fold of her dress, was stirred, as she looked intently at
+me, holding up her child.
+
+So I lost her. So I saw her afterwards, in my sleep at school--a silent
+presence near my bed--looking at me with the same intent face--holding
+up her baby in her arms.
+
+
+
+CHAPTER 9. I HAVE A MEMORABLE BIRTHDAY
+
+
+I PASS over all that happened at school, until the anniversary of my
+birthday came round in March. Except that Steerforth was more to be
+admired than ever, I remember nothing. He was going away at the end of
+the half-year, if not sooner, and was more spirited and independent than
+before in my eyes, and therefore more engaging than before; but beyond
+this I remember nothing. The great remembrance by which that time is
+marked in my mind, seems to have swallowed up all lesser recollections,
+and to exist alone.
+
+It is even difficult for me to believe that there was a gap of full
+two months between my return to Salem House and the arrival of that
+birthday. I can only understand that the fact was so, because I know it
+must have been so; otherwise I should feel convinced that there was no
+interval, and that the one occasion trod upon the other's heels.
+
+How well I recollect the kind of day it was! I smell the fog that hung
+about the place; I see the hoar frost, ghostly, through it; I feel my
+rimy hair fall clammy on my cheek; I look along the dim perspective of
+the schoolroom, with a sputtering candle here and there to light up the
+foggy morning, and the breath of the boys wreathing and smoking in the
+raw cold as they blow upon their fingers, and tap their feet upon the
+floor. It was after breakfast, and we had been summoned in from the
+playground, when Mr. Sharp entered and said:
+
+'David Copperfield is to go into the parlour.'
+
+I expected a hamper from Peggotty, and brightened at the order. Some
+of the boys about me put in their claim not to be forgotten in the
+distribution of the good things, as I got out of my seat with great
+alacrity.
+
+'Don't hurry, David,' said Mr. Sharp. 'There's time enough, my boy,
+don't hurry.'
+
+I might have been surprised by the feeling tone in which he spoke, if I
+had given it a thought; but I gave it none until afterwards. I hurried
+away to the parlour; and there I found Mr. Creakle, sitting at his
+breakfast with the cane and a newspaper before him, and Mrs. Creakle
+with an opened letter in her hand. But no hamper.
+
+'David Copperfield,' said Mrs. Creakle, leading me to a sofa, and
+sitting down beside me. 'I want to speak to you very particularly. I
+have something to tell you, my child.'
+
+Mr. Creakle, at whom of course I looked, shook his head without looking
+at me, and stopped up a sigh with a very large piece of buttered toast.
+
+'You are too young to know how the world changes every day,' said Mrs.
+Creakle, 'and how the people in it pass away. But we all have to learn
+it, David; some of us when we are young, some of us when we are old,
+some of us at all times of our lives.'
+
+I looked at her earnestly.
+
+'When you came away from home at the end of the vacation,' said Mrs.
+Creakle, after a pause, 'were they all well?' After another pause, 'Was
+your mama well?'
+
+I trembled without distinctly knowing why, and still looked at her
+earnestly, making no attempt to answer.
+
+'Because,' said she, 'I grieve to tell you that I hear this morning your
+mama is very ill.'
+
+A mist rose between Mrs. Creakle and me, and her figure seemed to move
+in it for an instant. Then I felt the burning tears run down my face,
+and it was steady again.
+
+'She is very dangerously ill,' she added.
+
+I knew all now.
+
+'She is dead.'
+
+There was no need to tell me so. I had already broken out into a
+desolate cry, and felt an orphan in the wide world.
+
+She was very kind to me. She kept me there all day, and left me alone
+sometimes; and I cried, and wore myself to sleep, and awoke and
+cried again. When I could cry no more, I began to think; and then the
+oppression on my breast was heaviest, and my grief a dull pain that
+there was no ease for.
+
+And yet my thoughts were idle; not intent on the calamity that weighed
+upon my heart, but idly loitering near it. I thought of our house shut
+up and hushed. I thought of the little baby, who, Mrs. Creakle said, had
+been pining away for some time, and who, they believed, would die too. I
+thought of my father's grave in the churchyard, by our house, and of my
+mother lying there beneath the tree I knew so well. I stood upon a chair
+when I was left alone, and looked into the glass to see how red my eyes
+were, and how sorrowful my face. I considered, after some hours were
+gone, if my tears were really hard to flow now, as they seemed to be,
+what, in connexion with my loss, it would affect me most to think
+of when I drew near home--for I was going home to the funeral. I am
+sensible of having felt that a dignity attached to me among the rest of
+the boys, and that I was important in my affliction.
+
+If ever child were stricken with sincere grief, I was. But I remember
+that this importance was a kind of satisfaction to me, when I walked in
+the playground that afternoon while the boys were in school. When I
+saw them glancing at me out of the windows, as they went up to their
+classes, I felt distinguished, and looked more melancholy, and walked
+slower. When school was over, and they came out and spoke to me, I felt
+it rather good in myself not to be proud to any of them, and to take
+exactly the same notice of them all, as before.
+
+I was to go home next night; not by the mail, but by the heavy
+night-coach, which was called the Farmer, and was principally used by
+country-people travelling short intermediate distances upon the road. We
+had no story-telling that evening, and Traddles insisted on lending me
+his pillow. I don't know what good he thought it would do me, for I
+had one of my own: but it was all he had to lend, poor fellow, except a
+sheet of letter-paper full of skeletons; and that he gave me at parting,
+as a soother of my sorrows and a contribution to my peace of mind.
+
+I left Salem House upon the morrow afternoon. I little thought then that
+I left it, never to return. We travelled very slowly all night, and
+did not get into Yarmouth before nine or ten o'clock in the morning. I
+looked out for Mr. Barkis, but he was not there; and instead of him a
+fat, short-winded, merry-looking, little old man in black, with rusty
+little bunches of ribbons at the knees of his breeches, black stockings,
+and a broad-brimmed hat, came puffing up to the coach window, and said:
+
+'Master Copperfield?'
+
+'Yes, sir.'
+
+'Will you come with me, young sir, if you please,' he said, opening the
+door, 'and I shall have the pleasure of taking you home.'
+
+I put my hand in his, wondering who he was, and we walked away to a
+shop in a narrow street, on which was written OMER, DRAPER, TAILOR,
+HABERDASHER, FUNERAL FURNISHER, &c. It was a close and stifling little
+shop; full of all sorts of clothing, made and unmade, including
+one window full of beaver-hats and bonnets. We went into a little
+back-parlour behind the shop, where we found three young women at work
+on a quantity of black materials, which were heaped upon the table,
+and little bits and cuttings of which were littered all over the floor.
+There was a good fire in the room, and a breathless smell of warm black
+crape--I did not know what the smell was then, but I know now.
+
+The three young women, who appeared to be very industrious and
+comfortable, raised their heads to look at me, and then went on with
+their work. Stitch, stitch, stitch. At the same time there came from
+a workshop across a little yard outside the window, a regular sound
+of hammering that kept a kind of tune: RAT--tat-tat, RAT--tat-tat,
+RAT--tat-tat, without any variation.
+
+'Well,' said my conductor to one of the three young women. 'How do you
+get on, Minnie?'
+
+'We shall be ready by the trying-on time,' she replied gaily, without
+looking up. 'Don't you be afraid, father.'
+
+Mr. Omer took off his broad-brimmed hat, and sat down and panted. He was
+so fat that he was obliged to pant some time before he could say:
+
+'That's right.'
+
+'Father!' said Minnie, playfully. 'What a porpoise you do grow!'
+
+'Well, I don't know how it is, my dear,' he replied, considering about
+it. 'I am rather so.'
+
+'You are such a comfortable man, you see,' said Minnie. 'You take things
+so easy.'
+
+'No use taking 'em otherwise, my dear,' said Mr. Omer.
+
+'No, indeed,' returned his daughter. 'We are all pretty gay here, thank
+Heaven! Ain't we, father?'
+
+'I hope so, my dear,' said Mr. Omer. 'As I have got my breath now, I
+think I'll measure this young scholar. Would you walk into the shop,
+Master Copperfield?'
+
+I preceded Mr. Omer, in compliance with his request; and after showing
+me a roll of cloth which he said was extra super, and too good mourning
+for anything short of parents, he took my various dimensions, and put
+them down in a book. While he was recording them he called my attention
+to his stock in trade, and to certain fashions which he said had 'just
+come up', and to certain other fashions which he said had 'just gone
+out'.
+
+'And by that sort of thing we very often lose a little mint of money,'
+said Mr. Omer. 'But fashions are like human beings. They come in, nobody
+knows when, why, or how; and they go out, nobody knows when, why, or
+how. Everything is like life, in my opinion, if you look at it in that
+point of view.'
+
+I was too sorrowful to discuss the question, which would possibly have
+been beyond me under any circumstances; and Mr. Omer took me back into
+the parlour, breathing with some difficulty on the way.
+
+He then called down a little break-neck range of steps behind a door:
+'Bring up that tea and bread-and-butter!' which, after some time,
+during which I sat looking about me and thinking, and listening to the
+stitching in the room and the tune that was being hammered across the
+yard, appeared on a tray, and turned out to be for me.
+
+'I have been acquainted with you,' said Mr. Omer, after watching me
+for some minutes, during which I had not made much impression on the
+breakfast, for the black things destroyed my appetite, 'I have been
+acquainted with you a long time, my young friend.'
+
+'Have you, sir?'
+
+'All your life,' said Mr. Omer. 'I may say before it. I knew your
+father before you. He was five foot nine and a half, and he lays in
+five-and-twen-ty foot of ground.'
+
+'RAT--tat-tat, RAT--tat-tat, RAT--tat-tat,' across the yard.
+
+'He lays in five and twen-ty foot of ground, if he lays in a fraction,'
+said Mr. Omer, pleasantly. 'It was either his request or her direction,
+I forget which.'
+
+'Do you know how my little brother is, sir?' I inquired.
+
+Mr. Omer shook his head.
+
+'RAT--tat-tat, RAT--tat-tat, RAT--tat-tat.'
+
+'He is in his mother's arms,' said he.
+
+'Oh, poor little fellow! Is he dead?'
+
+'Don't mind it more than you can help,' said Mr. Omer. 'Yes. The baby's
+dead.'
+
+My wounds broke out afresh at this intelligence. I left the
+scarcely-tasted breakfast, and went and rested my head on another table,
+in a corner of the little room, which Minnie hastily cleared, lest I
+should spot the mourning that was lying there with my tears. She was
+a pretty, good-natured girl, and put my hair away from my eyes with a
+soft, kind touch; but she was very cheerful at having nearly finished
+her work and being in good time, and was so different from me!
+
+Presently the tune left off, and a good-looking young fellow came across
+the yard into the room. He had a hammer in his hand, and his mouth was
+full of little nails, which he was obliged to take out before he could
+speak.
+
+'Well, Joram!' said Mr. Omer. 'How do you get on?'
+
+'All right,' said Joram. 'Done, sir.'
+
+Minnie coloured a little, and the other two girls smiled at one another.
+
+'What! you were at it by candle-light last night, when I was at the
+club, then? Were you?' said Mr. Omer, shutting up one eye.
+
+'Yes,' said Joram. 'As you said we could make a little trip of it, and
+go over together, if it was done, Minnie and me--and you.'
+
+'Oh! I thought you were going to leave me out altogether,' said Mr.
+Omer, laughing till he coughed.
+
+'--As you was so good as to say that,' resumed the young man, 'why I
+turned to with a will, you see. Will you give me your opinion of it?'
+
+'I will,' said Mr. Omer, rising. 'My dear'; and he stopped and turned to
+me: 'would you like to see your--'
+
+'No, father,' Minnie interposed.
+
+'I thought it might be agreeable, my dear,' said Mr. Omer. 'But perhaps
+you're right.'
+
+I can't say how I knew it was my dear, dear mother's coffin that they
+went to look at. I had never heard one making; I had never seen one that
+I know of.--but it came into my mind what the noise was, while it was
+going on; and when the young man entered, I am sure I knew what he had
+been doing.
+
+The work being now finished, the two girls, whose names I had not heard,
+brushed the shreds and threads from their dresses, and went into the
+shop to put that to rights, and wait for customers. Minnie stayed behind
+to fold up what they had made, and pack it in two baskets. This she did
+upon her knees, humming a lively little tune the while. Joram, who I had
+no doubt was her lover, came in and stole a kiss from her while she was
+busy (he didn't appear to mind me, at all), and said her father was gone
+for the chaise, and he must make haste and get himself ready. Then he
+went out again; and then she put her thimble and scissors in her pocket,
+and stuck a needle threaded with black thread neatly in the bosom of her
+gown, and put on her outer clothing smartly, at a little glass behind
+the door, in which I saw the reflection of her pleased face.
+
+All this I observed, sitting at the table in the corner with my head
+leaning on my hand, and my thoughts running on very different things.
+The chaise soon came round to the front of the shop, and the baskets
+being put in first, I was put in next, and those three followed. I
+remember it as a kind of half chaise-cart, half pianoforte-van, painted
+of a sombre colour, and drawn by a black horse with a long tail. There
+was plenty of room for us all.
+
+I do not think I have ever experienced so strange a feeling in my life
+(I am wiser now, perhaps) as that of being with them, remembering how
+they had been employed, and seeing them enjoy the ride. I was not angry
+with them; I was more afraid of them, as if I were cast away among
+creatures with whom I had no community of nature. They were very
+cheerful. The old man sat in front to drive, and the two young people
+sat behind him, and whenever he spoke to them leaned forward, the one on
+one side of his chubby face and the other on the other, and made a great
+deal of him. They would have talked to me too, but I held back, and
+moped in my corner; scared by their love-making and hilarity, though
+it was far from boisterous, and almost wondering that no judgement came
+upon them for their hardness of heart.
+
+So, when they stopped to bait the horse, and ate and drank and enjoyed
+themselves, I could touch nothing that they touched, but kept my fast
+unbroken. So, when we reached home, I dropped out of the chaise behind,
+as quickly as possible, that I might not be in their company before
+those solemn windows, looking blindly on me like closed eyes once
+bright. And oh, how little need I had had to think what would move me to
+tears when I came back--seeing the window of my mother's room, and next
+it that which, in the better time, was mine!
+
+I was in Peggotty's arms before I got to the door, and she took me into
+the house. Her grief burst out when she first saw me; but she controlled
+it soon, and spoke in whispers, and walked softly, as if the dead could
+be disturbed. She had not been in bed, I found, for a long time. She
+sat up at night still, and watched. As long as her poor dear pretty was
+above the ground, she said, she would never desert her.
+
+Mr. Murdstone took no heed of me when I went into the parlour where he
+was, but sat by the fireside, weeping silently, and pondering in his
+elbow-chair. Miss Murdstone, who was busy at her writing-desk, which
+was covered with letters and papers, gave me her cold finger-nails, and
+asked me, in an iron whisper, if I had been measured for my mourning.
+
+I said: 'Yes.'
+
+'And your shirts,' said Miss Murdstone; 'have you brought 'em home?'
+
+'Yes, ma'am. I have brought home all my clothes.'
+
+This was all the consolation that her firmness administered to me. I do
+not doubt that she had a choice pleasure in exhibiting what she called
+her self-command, and her firmness, and her strength of mind, and
+her common sense, and the whole diabolical catalogue of her unamiable
+qualities, on such an occasion. She was particularly proud of her turn
+for business; and she showed it now in reducing everything to pen and
+ink, and being moved by nothing. All the rest of that day, and from
+morning to night afterwards, she sat at that desk, scratching composedly
+with a hard pen, speaking in the same imperturbable whisper to
+everybody; never relaxing a muscle of her face, or softening a tone of
+her voice, or appearing with an atom of her dress astray.
+
+Her brother took a book sometimes, but never read it that I saw. He
+would open it and look at it as if he were reading, but would remain for
+a whole hour without turning the leaf, and then put it down and walk to
+and fro in the room. I used to sit with folded hands watching him, and
+counting his footsteps, hour after hour. He very seldom spoke to her,
+and never to me. He seemed to be the only restless thing, except the
+clocks, in the whole motionless house.
+
+In these days before the funeral, I saw but little of Peggotty, except
+that, in passing up or down stairs, I always found her close to the room
+where my mother and her baby lay, and except that she came to me every
+night, and sat by my bed's head while I went to sleep. A day or
+two before the burial--I think it was a day or two before, but I am
+conscious of confusion in my mind about that heavy time, with nothing
+to mark its progress--she took me into the room. I only recollect that
+underneath some white covering on the bed, with a beautiful cleanliness
+and freshness all around it, there seemed to me to lie embodied the
+solemn stillness that was in the house; and that when she would have
+turned the cover gently back, I cried: 'Oh no! oh no!' and held her
+hand.
+
+If the funeral had been yesterday, I could not recollect it better. The
+very air of the best parlour, when I went in at the door, the bright
+condition of the fire, the shining of the wine in the decanters, the
+patterns of the glasses and plates, the faint sweet smell of cake, the
+odour of Miss Murdstone's dress, and our black clothes. Mr. Chillip is
+in the room, and comes to speak to me.
+
+'And how is Master David?' he says, kindly.
+
+I cannot tell him very well. I give him my hand, which he holds in his.
+
+'Dear me!' says Mr. Chillip, meekly smiling, with something shining in
+his eye. 'Our little friends grow up around us. They grow out of our
+knowledge, ma'am?' This is to Miss Murdstone, who makes no reply.
+
+'There is a great improvement here, ma'am?' says Mr. Chillip.
+
+Miss Murdstone merely answers with a frown and a formal bend: Mr.
+Chillip, discomfited, goes into a corner, keeping me with him, and opens
+his mouth no more.
+
+I remark this, because I remark everything that happens, not because
+I care about myself, or have done since I came home. And now the bell
+begins to sound, and Mr. Omer and another come to make us ready. As
+Peggotty was wont to tell me, long ago, the followers of my father to
+the same grave were made ready in the same room.
+
+There are Mr. Murdstone, our neighbour Mr. Grayper, Mr. Chillip, and
+I. When we go out to the door, the Bearers and their load are in the
+garden; and they move before us down the path, and past the elms, and
+through the gate, and into the churchyard, where I have so often heard
+the birds sing on a summer morning.
+
+We stand around the grave. The day seems different to me from every
+other day, and the light not of the same colour--of a sadder colour.
+Now there is a solemn hush, which we have brought from home with what is
+resting in the mould; and while we stand bareheaded, I hear the voice
+of the clergyman, sounding remote in the open air, and yet distinct and
+plain, saying: 'I am the Resurrection and the Life, saith the Lord!'
+Then I hear sobs; and, standing apart among the lookers-on, I see that
+good and faithful servant, whom of all the people upon earth I love the
+best, and unto whom my childish heart is certain that the Lord will one
+day say: 'Well done.'
+
+There are many faces that I know, among the little crowd; faces that I
+knew in church, when mine was always wondering there; faces that first
+saw my mother, when she came to the village in her youthful bloom. I do
+not mind them--I mind nothing but my grief--and yet I see and know them
+all; and even in the background, far away, see Minnie looking on, and
+her eye glancing on her sweetheart, who is near me.
+
+It is over, and the earth is filled in, and we turn to come away. Before
+us stands our house, so pretty and unchanged, so linked in my mind with
+the young idea of what is gone, that all my sorrow has been nothing to
+the sorrow it calls forth. But they take me on; and Mr. Chillip talks to
+me; and when we get home, puts some water to my lips; and when I ask his
+leave to go up to my room, dismisses me with the gentleness of a woman.
+
+All this, I say, is yesterday's event. Events of later date have floated
+from me to the shore where all forgotten things will reappear, but this
+stands like a high rock in the ocean.
+
+I knew that Peggotty would come to me in my room. The Sabbath stillness
+of the time (the day was so like Sunday! I have forgotten that) was
+suited to us both. She sat down by my side upon my little bed; and
+holding my hand, and sometimes putting it to her lips, and sometimes
+smoothing it with hers, as she might have comforted my little brother,
+told me, in her way, all that she had to tell concerning what had
+happened.
+
+'She was never well,' said Peggotty, 'for a long time. She was uncertain
+in her mind, and not happy. When her baby was born, I thought at first
+she would get better, but she was more delicate, and sunk a little every
+day. She used to like to sit alone before her baby came, and then she
+cried; but afterwards she used to sing to it--so soft, that I once
+thought, when I heard her, it was like a voice up in the air, that was
+rising away.
+
+'I think she got to be more timid, and more frightened-like, of late;
+and that a hard word was like a blow to her. But she was always the same
+to me. She never changed to her foolish Peggotty, didn't my sweet girl.'
+
+Here Peggotty stopped, and softly beat upon my hand a little while.
+
+'The last time that I saw her like her own old self, was the night when
+you came home, my dear. The day you went away, she said to me, "I never
+shall see my pretty darling again. Something tells me so, that tells the
+truth, I know."
+
+'She tried to hold up after that; and many a time, when they told her
+she was thoughtless and light-hearted, made believe to be so; but it was
+all a bygone then. She never told her husband what she had told me--she
+was afraid of saying it to anybody else--till one night, a little more
+than a week before it happened, when she said to him: "My dear, I think
+I am dying."
+
+'"It's off my mind now, Peggotty," she told me, when I laid her in her
+bed that night. "He will believe it more and more, poor fellow, every
+day for a few days to come; and then it will be past. I am very tired.
+If this is sleep, sit by me while I sleep: don't leave me. God bless
+both my children! God protect and keep my fatherless boy!"
+
+'I never left her afterwards,' said Peggotty. 'She often talked to them
+two downstairs--for she loved them; she couldn't bear not to love anyone
+who was about her--but when they went away from her bed-side, she always
+turned to me, as if there was rest where Peggotty was, and never fell
+asleep in any other way.
+
+'On the last night, in the evening, she kissed me, and said: "If my baby
+should die too, Peggotty, please let them lay him in my arms, and bury
+us together." (It was done; for the poor lamb lived but a day beyond
+her.) "Let my dearest boy go with us to our resting-place," she said,
+"and tell him that his mother, when she lay here, blessed him not once,
+but a thousand times."'
+
+Another silence followed this, and another gentle beating on my hand.
+
+'It was pretty far in the night,' said Peggotty, 'when she asked me for
+some drink; and when she had taken it, gave me such a patient smile, the
+dear!--so beautiful!
+
+'Daybreak had come, and the sun was rising, when she said to me, how
+kind and considerate Mr. Copperfield had always been to her, and how
+he had borne with her, and told her, when she doubted herself, that
+a loving heart was better and stronger than wisdom, and that he was a
+happy man in hers. "Peggotty, my dear," she said then, "put me nearer to
+you," for she was very weak. "Lay your good arm underneath my neck," she
+said, "and turn me to you, for your face is going far off, and I want it
+to be near." I put it as she asked; and oh Davy! the time had come when
+my first parting words to you were true--when she was glad to lay her
+poor head on her stupid cross old Peggotty's arm--and she died like a
+child that had gone to sleep!'
+
+
+Thus ended Peggotty's narration. From the moment of my knowing of the
+death of my mother, the idea of her as she had been of late had vanished
+from me. I remembered her, from that instant, only as the young mother
+of my earliest impressions, who had been used to wind her bright curls
+round and round her finger, and to dance with me at twilight in the
+parlour. What Peggotty had told me now, was so far from bringing me back
+to the later period, that it rooted the earlier image in my mind. It may
+be curious, but it is true. In her death she winged her way back to her
+calm untroubled youth, and cancelled all the rest.
+
+The mother who lay in the grave, was the mother of my infancy; the
+little creature in her arms, was myself, as I had once been, hushed for
+ever on her bosom.
+
+
+
+CHAPTER 10. I BECOME NEGLECTED, AND AM PROVIDED FOR
+
+
+The first act of business Miss Murdstone performed when the day of the
+solemnity was over, and light was freely admitted into the house, was
+to give Peggotty a month's warning. Much as Peggotty would have disliked
+such a service, I believe she would have retained it, for my sake, in
+preference to the best upon earth. She told me we must part, and told me
+why; and we condoled with one another, in all sincerity.
+
+As to me or my future, not a word was said, or a step taken. Happy
+they would have been, I dare say, if they could have dismissed me at a
+month's warning too. I mustered courage once, to ask Miss Murdstone when
+I was going back to school; and she answered dryly, she believed I was
+not going back at all. I was told nothing more. I was very anxious to
+know what was going to be done with me, and so was Peggotty; but neither
+she nor I could pick up any information on the subject.
+
+There was one change in my condition, which, while it relieved me of
+a great deal of present uneasiness, might have made me, if I had been
+capable of considering it closely, yet more uncomfortable about the
+future. It was this. The constraint that had been put upon me, was quite
+abandoned. I was so far from being required to keep my dull post in
+the parlour, that on several occasions, when I took my seat there, Miss
+Murdstone frowned to me to go away. I was so far from being warned off
+from Peggotty's society, that, provided I was not in Mr. Murdstone's, I
+was never sought out or inquired for. At first I was in daily dread of
+his taking my education in hand again, or of Miss Murdstone's
+devoting herself to it; but I soon began to think that such fears were
+groundless, and that all I had to anticipate was neglect.
+
+I do not conceive that this discovery gave me much pain then. I was
+still giddy with the shock of my mother's death, and in a kind of
+stunned state as to all tributary things. I can recollect, indeed, to
+have speculated, at odd times, on the possibility of my not being taught
+any more, or cared for any more; and growing up to be a shabby, moody
+man, lounging an idle life away, about the village; as well as on the
+feasibility of my getting rid of this picture by going away somewhere,
+like the hero in a story, to seek my fortune: but these were transient
+visions, daydreams I sat looking at sometimes, as if they were faintly
+painted or written on the wall of my room, and which, as they melted
+away, left the wall blank again.
+
+'Peggotty,' I said in a thoughtful whisper, one evening, when I was
+warming my hands at the kitchen fire, 'Mr. Murdstone likes me less than
+he used to. He never liked me much, Peggotty; but he would rather not
+even see me now, if he can help it.'
+
+'Perhaps it's his sorrow,' said Peggotty, stroking my hair.
+
+'I am sure, Peggotty, I am sorry too. If I believed it was his sorrow,
+I should not think of it at all. But it's not that; oh, no, it's not
+that.'
+
+'How do you know it's not that?' said Peggotty, after a silence.
+
+'Oh, his sorrow is another and quite a different thing. He is sorry at
+this moment, sitting by the fireside with Miss Murdstone; but if I was
+to go in, Peggotty, he would be something besides.'
+
+'What would he be?' said Peggotty.
+
+'Angry,' I answered, with an involuntary imitation of his dark frown.
+'If he was only sorry, he wouldn't look at me as he does. I am only
+sorry, and it makes me feel kinder.'
+
+Peggotty said nothing for a little while; and I warmed my hands, as
+silent as she.
+
+'Davy,' she said at length.
+
+'Yes, Peggotty?' 'I have tried, my dear, all ways I could think of--all
+the ways there are, and all the ways there ain't, in short--to get a
+suitable service here, in Blunderstone; but there's no such a thing, my
+love.'
+
+'And what do you mean to do, Peggotty,' says I, wistfully. 'Do you mean
+to go and seek your fortune?'
+
+'I expect I shall be forced to go to Yarmouth,' replied Peggotty, 'and
+live there.'
+
+'You might have gone farther off,' I said, brightening a little, 'and
+been as bad as lost. I shall see you sometimes, my dear old Peggotty,
+there. You won't be quite at the other end of the world, will you?'
+
+'Contrary ways, please God!' cried Peggotty, with great animation. 'As
+long as you are here, my pet, I shall come over every week of my life to
+see you. One day, every week of my life!'
+
+I felt a great weight taken off my mind by this promise: but even this
+was not all, for Peggotty went on to say:
+
+'I'm a-going, Davy, you see, to my brother's, first, for another
+fortnight's visit--just till I have had time to look about me, and
+get to be something like myself again. Now, I have been thinking that
+perhaps, as they don't want you here at present, you might be let to go
+along with me.'
+
+If anything, short of being in a different relation to every one about
+me, Peggotty excepted, could have given me a sense of pleasure at that
+time, it would have been this project of all others. The idea of being
+again surrounded by those honest faces, shining welcome on me; of
+renewing the peacefulness of the sweet Sunday morning, when the bells
+were ringing, the stones dropping in the water, and the shadowy ships
+breaking through the mist; of roaming up and down with little Em'ly,
+telling her my troubles, and finding charms against them in the shells
+and pebbles on the beach; made a calm in my heart. It was ruffled next
+moment, to be sure, by a doubt of Miss Murdstone's giving her consent;
+but even that was set at rest soon, for she came out to take an evening
+grope in the store-closet while we were yet in conversation, and
+Peggotty, with a boldness that amazed me, broached the topic on the
+spot.
+
+'The boy will be idle there,' said Miss Murdstone, looking into a
+pickle-jar, 'and idleness is the root of all evil. But, to be sure, he
+would be idle here--or anywhere, in my opinion.'
+
+Peggotty had an angry answer ready, I could see; but she swallowed it
+for my sake, and remained silent.
+
+'Humph!' said Miss Murdstone, still keeping her eye on the pickles;
+'it is of more importance than anything else--it is of paramount
+importance--that my brother should not be disturbed or made
+uncomfortable. I suppose I had better say yes.'
+
+I thanked her, without making any demonstration of joy, lest it should
+induce her to withdraw her assent. Nor could I help thinking this a
+prudent course, since she looked at me out of the pickle-jar, with
+as great an access of sourness as if her black eyes had absorbed its
+contents. However, the permission was given, and was never retracted;
+for when the month was out, Peggotty and I were ready to depart.
+
+Mr. Barkis came into the house for Peggotty's boxes. I had never known
+him to pass the garden-gate before, but on this occasion he came into
+the house. And he gave me a look as he shouldered the largest box and
+went out, which I thought had meaning in it, if meaning could ever be
+said to find its way into Mr. Barkis's visage.
+
+Peggotty was naturally in low spirits at leaving what had been her home
+so many years, and where the two strong attachments of her life--for
+my mother and myself--had been formed. She had been walking in the
+churchyard, too, very early; and she got into the cart, and sat in it
+with her handkerchief at her eyes.
+
+So long as she remained in this condition, Mr. Barkis gave no sign
+of life whatever. He sat in his usual place and attitude like a great
+stuffed figure. But when she began to look about her, and to speak to
+me, he nodded his head and grinned several times. I have not the least
+notion at whom, or what he meant by it.
+
+'It's a beautiful day, Mr. Barkis!' I said, as an act of politeness.
+
+'It ain't bad,' said Mr. Barkis, who generally qualified his speech, and
+rarely committed himself.
+
+'Peggotty is quite comfortable now, Mr. Barkis,' I remarked, for his
+satisfaction.
+
+'Is she, though?' said Mr. Barkis.
+
+After reflecting about it, with a sagacious air, Mr. Barkis eyed her,
+and said:
+
+'ARE you pretty comfortable?'
+
+Peggotty laughed, and answered in the affirmative.
+
+'But really and truly, you know. Are you?' growled Mr. Barkis, sliding
+nearer to her on the seat, and nudging her with his elbow. 'Are you?
+Really and truly pretty comfortable? Are you? Eh?'
+
+At each of these inquiries Mr. Barkis shuffled nearer to her, and gave
+her another nudge; so that at last we were all crowded together in the
+left-hand corner of the cart, and I was so squeezed that I could hardly
+bear it.
+
+Peggotty calling his attention to my sufferings, Mr. Barkis gave me a
+little more room at once, and got away by degrees. But I could not help
+observing that he seemed to think he had hit upon a wonderful expedient
+for expressing himself in a neat, agreeable, and pointed manner, without
+the inconvenience of inventing conversation. He manifestly chuckled over
+it for some time. By and by he turned to Peggotty again, and repeating,
+'Are you pretty comfortable though?' bore down upon us as before, until
+the breath was nearly edged out of my body. By and by he made another
+descent upon us with the same inquiry, and the same result. At length,
+I got up whenever I saw him coming, and standing on the foot-board,
+pretended to look at the prospect; after which I did very well.
+
+He was so polite as to stop at a public-house, expressly on our account,
+and entertain us with broiled mutton and beer. Even when Peggotty was
+in the act of drinking, he was seized with one of those approaches, and
+almost choked her. But as we drew nearer to the end of our journey, he
+had more to do and less time for gallantry; and when we got on Yarmouth
+pavement, we were all too much shaken and jolted, I apprehend, to have
+any leisure for anything else.
+
+Mr. Peggotty and Ham waited for us at the old place. They received me
+and Peggotty in an affectionate manner, and shook hands with Mr. Barkis,
+who, with his hat on the very back of his head, and a shame-faced leer
+upon his countenance, and pervading his very legs, presented but a
+vacant appearance, I thought. They each took one of Peggotty's trunks,
+and we were going away, when Mr. Barkis solemnly made a sign to me with
+his forefinger to come under an archway.
+
+'I say,' growled Mr. Barkis, 'it was all right.'
+
+I looked up into his face, and answered, with an attempt to be very
+profound: 'Oh!'
+
+'It didn't come to a end there,' said Mr. Barkis, nodding
+confidentially. 'It was all right.'
+
+Again I answered, 'Oh!'
+
+'You know who was willin',' said my friend. 'It was Barkis, and Barkis
+only.'
+
+I nodded assent.
+
+'It's all right,' said Mr. Barkis, shaking hands; 'I'm a friend of
+your'n. You made it all right, first. It's all right.'
+
+In his attempts to be particularly lucid, Mr. Barkis was so extremely
+mysterious, that I might have stood looking in his face for an hour, and
+most assuredly should have got as much information out of it as out
+of the face of a clock that had stopped, but for Peggotty's calling me
+away. As we were going along, she asked me what he had said; and I told
+her he had said it was all right.
+
+'Like his impudence,' said Peggotty, 'but I don't mind that! Davy dear,
+what should you think if I was to think of being married?'
+
+'Why--I suppose you would like me as much then, Peggotty, as you do
+now?' I returned, after a little consideration.
+
+Greatly to the astonishment of the passengers in the street, as well as
+of her relations going on before, the good soul was obliged to stop and
+embrace me on the spot, with many protestations of her unalterable love.
+
+'Tell me what should you say, darling?' she asked again, when this was
+over, and we were walking on.
+
+'If you were thinking of being married--to Mr. Barkis, Peggotty?'
+
+'Yes,' said Peggotty.
+
+'I should think it would be a very good thing. For then you know,
+Peggotty, you would always have the horse and cart to bring you over to
+see me, and could come for nothing, and be sure of coming.'
+
+'The sense of the dear!' cried Peggotty. 'What I have been thinking
+of, this month back! Yes, my precious; and I think I should be more
+independent altogether, you see; let alone my working with a better
+heart in my own house, than I could in anybody else's now. I don't know
+what I might be fit for, now, as a servant to a stranger. And I shall be
+always near my pretty's resting-place,' said Peggotty, musing, 'and be
+able to see it when I like; and when I lie down to rest, I may be laid
+not far off from my darling girl!'
+
+We neither of us said anything for a little while.
+
+'But I wouldn't so much as give it another thought,' said Peggotty,
+cheerily 'if my Davy was anyways against it--not if I had been asked in
+church thirty times three times over, and was wearing out the ring in my
+pocket.'
+
+'Look at me, Peggotty,' I replied; 'and see if I am not really glad, and
+don't truly wish it!' As indeed I did, with all my heart.
+
+'Well, my life,' said Peggotty, giving me a squeeze, 'I have thought of
+it night and day, every way I can, and I hope the right way; but I'll
+think of it again, and speak to my brother about it, and in the meantime
+we'll keep it to ourselves, Davy, you and me. Barkis is a good plain
+creature,' said Peggotty, 'and if I tried to do my duty by him, I think
+it would be my fault if I wasn't--if I wasn't pretty comfortable,'
+said Peggotty, laughing heartily. This quotation from Mr. Barkis was
+so appropriate, and tickled us both so much, that we laughed again and
+again, and were quite in a pleasant humour when we came within view of
+Mr. Peggotty's cottage.
+
+It looked just the same, except that it may, perhaps, have shrunk a
+little in my eyes; and Mrs. Gummidge was waiting at the door as if she
+had stood there ever since. All within was the same, down to the seaweed
+in the blue mug in my bedroom. I went into the out-house to look about
+me; and the very same lobsters, crabs, and crawfish possessed by the
+same desire to pinch the world in general, appeared to be in the same
+state of conglomeration in the same old corner.
+
+But there was no little Em'ly to be seen, so I asked Mr. Peggotty where
+she was.
+
+'She's at school, sir,' said Mr. Peggotty, wiping the heat consequent
+on the porterage of Peggotty's box from his forehead; 'she'll be home,'
+looking at the Dutch clock, 'in from twenty minutes to half-an-hour's
+time. We all on us feel the loss of her, bless ye!'
+
+Mrs. Gummidge moaned.
+
+'Cheer up, Mawther!' cried Mr. Peggotty.
+
+'I feel it more than anybody else,' said Mrs. Gummidge; 'I'm a lone
+lorn creetur', and she used to be a'most the only thing that didn't go
+contrary with me.'
+
+Mrs. Gummidge, whimpering and shaking her head, applied herself to
+blowing the fire. Mr. Peggotty, looking round upon us while she was so
+engaged, said in a low voice, which he shaded with his hand: 'The old
+'un!' From this I rightly conjectured that no improvement had taken
+place since my last visit in the state of Mrs. Gummidge's spirits.
+
+Now, the whole place was, or it should have been, quite as delightful
+a place as ever; and yet it did not impress me in the same way. I felt
+rather disappointed with it. Perhaps it was because little Em'ly was
+not at home. I knew the way by which she would come, and presently found
+myself strolling along the path to meet her.
+
+A figure appeared in the distance before long, and I soon knew it to be
+Em'ly, who was a little creature still in stature, though she was grown.
+But when she drew nearer, and I saw her blue eyes looking bluer, and her
+dimpled face looking brighter, and her whole self prettier and gayer, a
+curious feeling came over me that made me pretend not to know her, and
+pass by as if I were looking at something a long way off. I have done
+such a thing since in later life, or I am mistaken.
+
+Little Em'ly didn't care a bit. She saw me well enough; but instead of
+turning round and calling after me, ran away laughing. This obliged me
+to run after her, and she ran so fast that we were very near the cottage
+before I caught her.
+
+'Oh, it's you, is it?' said little Em'ly.
+
+'Why, you knew who it was, Em'ly,' said I.
+
+'And didn't YOU know who it was?' said Em'ly. I was going to kiss her,
+but she covered her cherry lips with her hands, and said she wasn't a
+baby now, and ran away, laughing more than ever, into the house.
+
+She seemed to delight in teasing me, which was a change in her I
+wondered at very much. The tea table was ready, and our little locker
+was put out in its old place, but instead of coming to sit by me, she
+went and bestowed her company upon that grumbling Mrs. Gummidge: and on
+Mr. Peggotty's inquiring why, rumpled her hair all over her face to hide
+it, and could do nothing but laugh.
+
+'A little puss, it is!' said Mr. Peggotty, patting her with his great
+hand.
+
+'So sh' is! so sh' is!' cried Ham. 'Mas'r Davy bor', so sh' is!' and he
+sat and chuckled at her for some time, in a state of mingled admiration
+and delight, that made his face a burning red.
+
+Little Em'ly was spoiled by them all, in fact; and by no one more than
+Mr. Peggotty himself, whom she could have coaxed into anything, by
+only going and laying her cheek against his rough whisker. That was my
+opinion, at least, when I saw her do it; and I held Mr. Peggotty to be
+thoroughly in the right. But she was so affectionate and sweet-natured,
+and had such a pleasant manner of being both sly and shy at once, that
+she captivated me more than ever.
+
+She was tender-hearted, too; for when, as we sat round the fire after
+tea, an allusion was made by Mr. Peggotty over his pipe to the loss
+I had sustained, the tears stood in her eyes, and she looked at me so
+kindly across the table, that I felt quite thankful to her.
+
+'Ah!' said Mr. Peggotty, taking up her curls, and running them over his
+hand like water, 'here's another orphan, you see, sir. And here,' said
+Mr. Peggotty, giving Ham a backhanded knock in the chest, 'is another of
+'em, though he don't look much like it.'
+
+'If I had you for my guardian, Mr. Peggotty,' said I, shaking my head,
+'I don't think I should FEEL much like it.'
+
+'Well said, Mas'r Davy bor'!' cried Ham, in an ecstasy. 'Hoorah! Well
+said! Nor more you wouldn't! Hor! Hor!'--Here he returned Mr. Peggotty's
+back-hander, and little Em'ly got up and kissed Mr. Peggotty. 'And how's
+your friend, sir?' said Mr. Peggotty to me.
+
+'Steerforth?' said I.
+
+'That's the name!' cried Mr. Peggotty, turning to Ham. 'I knowed it was
+something in our way.'
+
+'You said it was Rudderford,' observed Ham, laughing.
+
+'Well!' retorted Mr. Peggotty. 'And ye steer with a rudder, don't ye? It
+ain't fur off. How is he, sir?'
+
+'He was very well indeed when I came away, Mr. Peggotty.'
+
+'There's a friend!' said Mr. Peggotty, stretching out his pipe. 'There's
+a friend, if you talk of friends! Why, Lord love my heart alive, if it
+ain't a treat to look at him!'
+
+'He is very handsome, is he not?' said I, my heart warming with this
+praise.
+
+'Handsome!' cried Mr. Peggotty. 'He stands up to you like--like a--why I
+don't know what he don't stand up to you like. He's so bold!'
+
+'Yes! That's just his character,' said I. 'He's as brave as a lion, and
+you can't think how frank he is, Mr. Peggotty.'
+
+'And I do suppose, now,' said Mr. Peggotty, looking at me through the
+smoke of his pipe, 'that in the way of book-larning he'd take the wind
+out of a'most anything.'
+
+'Yes,' said I, delighted; 'he knows everything. He is astonishingly
+clever.'
+
+'There's a friend!' murmured Mr. Peggotty, with a grave toss of his
+head.
+
+'Nothing seems to cost him any trouble,' said I. 'He knows a task if he
+only looks at it. He is the best cricketer you ever saw. He will give
+you almost as many men as you like at draughts, and beat you easily.'
+
+Mr. Peggotty gave his head another toss, as much as to say: 'Of course
+he will.'
+
+'He is such a speaker,' I pursued, 'that he can win anybody over; and I
+don't know what you'd say if you were to hear him sing, Mr. Peggotty.'
+
+Mr. Peggotty gave his head another toss, as much as to say: 'I have no
+doubt of it.'
+
+'Then, he's such a generous, fine, noble fellow,' said I, quite carried
+away by my favourite theme, 'that it's hardly possible to give him as
+much praise as he deserves. I am sure I can never feel thankful enough
+for the generosity with which he has protected me, so much younger and
+lower in the school than himself.'
+
+I was running on, very fast indeed, when my eyes rested on little
+Em'ly's face, which was bent forward over the table, listening with the
+deepest attention, her breath held, her blue eyes sparkling like jewels,
+and the colour mantling in her cheeks. She looked so extraordinarily
+earnest and pretty, that I stopped in a sort of wonder; and they all
+observed her at the same time, for as I stopped, they laughed and looked
+at her.
+
+'Em'ly is like me,' said Peggotty, 'and would like to see him.'
+
+Em'ly was confused by our all observing her, and hung down her head,
+and her face was covered with blushes. Glancing up presently through her
+stray curls, and seeing that we were all looking at her still (I am sure
+I, for one, could have looked at her for hours), she ran away, and kept
+away till it was nearly bedtime.
+
+I lay down in the old little bed in the stern of the boat, and the wind
+came moaning on across the flat as it had done before. But I could not
+help fancying, now, that it moaned of those who were gone; and instead
+of thinking that the sea might rise in the night and float the boat
+away, I thought of the sea that had risen, since I last heard those
+sounds, and drowned my happy home. I recollect, as the wind and water
+began to sound fainter in my ears, putting a short clause into my
+prayers, petitioning that I might grow up to marry little Em'ly, and so
+dropping lovingly asleep.
+
+The days passed pretty much as they had passed before, except--it was
+a great exception--that little Em'ly and I seldom wandered on the beach
+now. She had tasks to learn, and needle-work to do; and was absent
+during a great part of each day. But I felt that we should not have had
+those old wanderings, even if it had been otherwise. Wild and full of
+childish whims as Em'ly was, she was more of a little woman than I
+had supposed. She seemed to have got a great distance away from me,
+in little more than a year. She liked me, but she laughed at me, and
+tormented me; and when I went to meet her, stole home another way, and
+was laughing at the door when I came back, disappointed. The best times
+were when she sat quietly at work in the doorway, and I sat on the
+wooden step at her feet, reading to her. It seems to me, at this
+hour, that I have never seen such sunlight as on those bright April
+afternoons; that I have never seen such a sunny little figure as I used
+to see, sitting in the doorway of the old boat; that I have never beheld
+such sky, such water, such glorified ships sailing away into golden air.
+
+On the very first evening after our arrival, Mr. Barkis appeared in an
+exceedingly vacant and awkward condition, and with a bundle of oranges
+tied up in a handkerchief. As he made no allusion of any kind to this
+property, he was supposed to have left it behind him by accident when
+he went away; until Ham, running after him to restore it, came back with
+the information that it was intended for Peggotty. After that occasion
+he appeared every evening at exactly the same hour, and always with a
+little bundle, to which he never alluded, and which he regularly put
+behind the door and left there. These offerings of affection were of a
+most various and eccentric description. Among them I remember a double
+set of pigs' trotters, a huge pin-cushion, half a bushel or so of
+apples, a pair of jet earrings, some Spanish onions, a box of dominoes,
+a canary bird and cage, and a leg of pickled pork.
+
+Mr. Barkis's wooing, as I remember it, was altogether of a peculiar
+kind. He very seldom said anything; but would sit by the fire in much
+the same attitude as he sat in his cart, and stare heavily at Peggotty,
+who was opposite. One night, being, as I suppose, inspired by love, he
+made a dart at the bit of wax-candle she kept for her thread, and put
+it in his waistcoat-pocket and carried it off. After that, his great
+delight was to produce it when it was wanted, sticking to the lining of
+his pocket, in a partially melted state, and pocket it again when it was
+done with. He seemed to enjoy himself very much, and not to feel at all
+called upon to talk. Even when he took Peggotty out for a walk on the
+flats, he had no uneasiness on that head, I believe; contenting himself
+with now and then asking her if she was pretty comfortable; and I
+remember that sometimes, after he was gone, Peggotty would throw her
+apron over her face, and laugh for half-an-hour. Indeed, we were
+all more or less amused, except that miserable Mrs. Gummidge, whose
+courtship would appear to have been of an exactly parallel nature, she
+was so continually reminded by these transactions of the old one.
+
+At length, when the term of my visit was nearly expired, it was given
+out that Peggotty and Mr. Barkis were going to make a day's holiday
+together, and that little Em'ly and I were to accompany them. I had but
+a broken sleep the night before, in anticipation of the pleasure of
+a whole day with Em'ly. We were all astir betimes in the morning; and
+while we were yet at breakfast, Mr. Barkis appeared in the distance,
+driving a chaise-cart towards the object of his affections.
+
+Peggotty was dressed as usual, in her neat and quiet mourning; but Mr.
+Barkis bloomed in a new blue coat, of which the tailor had given him
+such good measure, that the cuffs would have rendered gloves unnecessary
+in the coldest weather, while the collar was so high that it pushed his
+hair up on end on the top of his head. His bright buttons, too, were
+of the largest size. Rendered complete by drab pantaloons and a buff
+waistcoat, I thought Mr. Barkis a phenomenon of respectability.
+
+When we were all in a bustle outside the door, I found that Mr. Peggotty
+was prepared with an old shoe, which was to be thrown after us for luck,
+and which he offered to Mrs. Gummidge for that purpose.
+
+'No. It had better be done by somebody else, Dan'l,' said Mrs. Gummidge.
+'I'm a lone lorn creetur' myself, and everythink that reminds me of
+creetur's that ain't lone and lorn, goes contrary with me.'
+
+'Come, old gal!' cried Mr. Peggotty. 'Take and heave it.'
+
+'No, Dan'l,' returned Mrs. Gummidge, whimpering and shaking her head.
+'If I felt less, I could do more. You don't feel like me, Dan'l; thinks
+don't go contrary with you, nor you with them; you had better do it
+yourself.'
+
+But here Peggotty, who had been going about from one to another in a
+hurried way, kissing everybody, called out from the cart, in which we
+all were by this time (Em'ly and I on two little chairs, side by side),
+that Mrs. Gummidge must do it. So Mrs. Gummidge did it; and, I am sorry
+to relate, cast a damp upon the festive character of our departure, by
+immediately bursting into tears, and sinking subdued into the arms of
+Ham, with the declaration that she knowed she was a burden, and had
+better be carried to the House at once. Which I really thought was a
+sensible idea, that Ham might have acted on.
+
+Away we went, however, on our holiday excursion; and the first thing
+we did was to stop at a church, where Mr. Barkis tied the horse to some
+rails, and went in with Peggotty, leaving little Em'ly and me alone in
+the chaise. I took that occasion to put my arm round Em'ly's waist, and
+propose that as I was going away so very soon now, we should determine
+to be very affectionate to one another, and very happy, all day. Little
+Em'ly consenting, and allowing me to kiss her, I became desperate;
+informing her, I recollect, that I never could love another, and that
+I was prepared to shed the blood of anybody who should aspire to her
+affections.
+
+How merry little Em'ly made herself about it! With what a demure
+assumption of being immensely older and wiser than I, the fairy little
+woman said I was 'a silly boy'; and then laughed so charmingly that
+I forgot the pain of being called by that disparaging name, in the
+pleasure of looking at her.
+
+Mr. Barkis and Peggotty were a good while in the church, but came out at
+last, and then we drove away into the country. As we were going along,
+Mr. Barkis turned to me, and said, with a wink,--by the by, I should
+hardly have thought, before, that he could wink:
+
+'What name was it as I wrote up in the cart?'
+
+'Clara Peggotty,' I answered.
+
+'What name would it be as I should write up now, if there was a tilt
+here?'
+
+'Clara Peggotty, again?' I suggested.
+
+'Clara Peggotty BARKIS!' he returned, and burst into a roar of laughter
+that shook the chaise.
+
+In a word, they were married, and had gone into the church for no other
+purpose. Peggotty was resolved that it should be quietly done; and
+the clerk had given her away, and there had been no witnesses of the
+ceremony. She was a little confused when Mr. Barkis made this abrupt
+announcement of their union, and could not hug me enough in token of her
+unimpaired affection; but she soon became herself again, and said she
+was very glad it was over.
+
+We drove to a little inn in a by-road, where we were expected, and
+where we had a very comfortable dinner, and passed the day with great
+satisfaction. If Peggotty had been married every day for the last ten
+years, she could hardly have been more at her ease about it; it made no
+sort of difference in her: she was just the same as ever, and went
+out for a stroll with little Em'ly and me before tea, while Mr. Barkis
+philosophically smoked his pipe, and enjoyed himself, I suppose, with
+the contemplation of his happiness. If so, it sharpened his appetite;
+for I distinctly call to mind that, although he had eaten a good deal of
+pork and greens at dinner, and had finished off with a fowl or two, he
+was obliged to have cold boiled bacon for tea, and disposed of a large
+quantity without any emotion.
+
+I have often thought, since, what an odd, innocent, out-of-the-way kind
+of wedding it must have been! We got into the chaise again soon after
+dark, and drove cosily back, looking up at the stars, and talking about
+them. I was their chief exponent, and opened Mr. Barkis's mind to
+an amazing extent. I told him all I knew, but he would have believed
+anything I might have taken it into my head to impart to him; for he
+had a profound veneration for my abilities, and informed his wife in my
+hearing, on that very occasion, that I was 'a young Roeshus'--by which I
+think he meant prodigy.
+
+When we had exhausted the subject of the stars, or rather when I had
+exhausted the mental faculties of Mr. Barkis, little Em'ly and I made a
+cloak of an old wrapper, and sat under it for the rest of the journey.
+Ah, how I loved her! What happiness (I thought) if we were married,
+and were going away anywhere to live among the trees and in the fields,
+never growing older, never growing wiser, children ever, rambling hand
+in hand through sunshine and among flowery meadows, laying down our
+heads on moss at night, in a sweet sleep of purity and peace, and buried
+by the birds when we were dead! Some such picture, with no real world in
+it, bright with the light of our innocence, and vague as the stars afar
+off, was in my mind all the way. I am glad to think there were two such
+guileless hearts at Peggotty's marriage as little Em'ly's and mine. I
+am glad to think the Loves and Graces took such airy forms in its homely
+procession.
+
+Well, we came to the old boat again in good time at night; and there
+Mr. and Mrs. Barkis bade us good-bye, and drove away snugly to their
+own home. I felt then, for the first time, that I had lost Peggotty. I
+should have gone to bed with a sore heart indeed under any other roof
+but that which sheltered little Em'ly's head.
+
+Mr. Peggotty and Ham knew what was in my thoughts as well as I did, and
+were ready with some supper and their hospitable faces to drive it away.
+Little Em'ly came and sat beside me on the locker for the only time in
+all that visit; and it was altogether a wonderful close to a wonderful
+day.
+
+It was a night tide; and soon after we went to bed, Mr. Peggotty and Ham
+went out to fish. I felt very brave at being left alone in the solitary
+house, the protector of Em'ly and Mrs. Gummidge, and only wished that
+a lion or a serpent, or any ill-disposed monster, would make an attack
+upon us, that I might destroy him, and cover myself with glory. But as
+nothing of the sort happened to be walking about on Yarmouth flats that
+night, I provided the best substitute I could by dreaming of dragons
+until morning.
+
+With morning came Peggotty; who called to me, as usual, under my window
+as if Mr. Barkis the carrier had been from first to last a dream too.
+After breakfast she took me to her own home, and a beautiful little
+home it was. Of all the moveables in it, I must have been impressed by
+a certain old bureau of some dark wood in the parlour (the tile-floored
+kitchen was the general sitting-room), with a retreating top which
+opened, let down, and became a desk, within which was a large quarto
+edition of Foxe's Book of Martyrs. This precious volume, of which I do
+not recollect one word, I immediately discovered and immediately applied
+myself to; and I never visited the house afterwards, but I kneeled on
+a chair, opened the casket where this gem was enshrined, spread my arms
+over the desk, and fell to devouring the book afresh. I was chiefly
+edified, I am afraid, by the pictures, which were numerous, and
+represented all kinds of dismal horrors; but the Martyrs and Peggotty's
+house have been inseparable in my mind ever since, and are now.
+
+I took leave of Mr. Peggotty, and Ham, and Mrs. Gummidge, and little
+Em'ly, that day; and passed the night at Peggotty's, in a little room
+in the roof (with the Crocodile Book on a shelf by the bed's head) which
+was to be always mine, Peggotty said, and should always be kept for me
+in exactly the same state.
+
+'Young or old, Davy dear, as long as I am alive and have this house over
+my head,' said Peggotty, 'you shall find it as if I expected you here
+directly minute. I shall keep it every day, as I used to keep your old
+little room, my darling; and if you was to go to China, you might think
+of it as being kept just the same, all the time you were away.'
+
+I felt the truth and constancy of my dear old nurse, with all my heart,
+and thanked her as well as I could. That was not very well, for she
+spoke to me thus, with her arms round my neck, in the morning, and I was
+going home in the morning, and I went home in the morning, with herself
+and Mr. Barkis in the cart. They left me at the gate, not easily or
+lightly; and it was a strange sight to me to see the cart go on, taking
+Peggotty away, and leaving me under the old elm-trees looking at the
+house, in which there was no face to look on mine with love or liking
+any more.
+
+And now I fell into a state of neglect, which I cannot look back upon
+without compassion. I fell at once into a solitary condition,--apart
+from all friendly notice, apart from the society of all other boys of
+my own age, apart from all companionship but my own spiritless
+thoughts,--which seems to cast its gloom upon this paper as I write.
+
+What would I have given, to have been sent to the hardest school that
+ever was kept!--to have been taught something, anyhow, anywhere! No
+such hope dawned upon me. They disliked me; and they sullenly, sternly,
+steadily, overlooked me. I think Mr. Murdstone's means were straitened
+at about this time; but it is little to the purpose. He could not bear
+me; and in putting me from him he tried, as I believe, to put away the
+notion that I had any claim upon him--and succeeded.
+
+I was not actively ill-used. I was not beaten, or starved; but the wrong
+that was done to me had no intervals of relenting, and was done in a
+systematic, passionless manner. Day after day, week after week, month
+after month, I was coldly neglected. I wonder sometimes, when I think
+of it, what they would have done if I had been taken with an illness;
+whether I should have lain down in my lonely room, and languished
+through it in my usual solitary way, or whether anybody would have
+helped me out.
+
+When Mr. and Miss Murdstone were at home, I took my meals with them; in
+their absence, I ate and drank by myself. At all times I lounged about
+the house and neighbourhood quite disregarded, except that they were
+jealous of my making any friends: thinking, perhaps, that if I did, I
+might complain to someone. For this reason, though Mr. Chillip often
+asked me to go and see him (he was a widower, having, some years before
+that, lost a little small light-haired wife, whom I can just remember
+connecting in my own thoughts with a pale tortoise-shell cat), it was
+but seldom that I enjoyed the happiness of passing an afternoon in his
+closet of a surgery; reading some book that was new to me, with
+the smell of the whole Pharmacopoeia coming up my nose, or pounding
+something in a mortar under his mild directions.
+
+For the same reason, added no doubt to the old dislike of her, I was
+seldom allowed to visit Peggotty. Faithful to her promise, she either
+came to see me, or met me somewhere near, once every week, and never
+empty-handed; but many and bitter were the disappointments I had, in
+being refused permission to pay a visit to her at her house. Some few
+times, however, at long intervals, I was allowed to go there; and then
+I found out that Mr. Barkis was something of a miser, or as Peggotty
+dutifully expressed it, was 'a little near', and kept a heap of money
+in a box under his bed, which he pretended was only full of coats
+and trousers. In this coffer, his riches hid themselves with such a
+tenacious modesty, that the smallest instalments could only be tempted
+out by artifice; so that Peggotty had to prepare a long and elaborate
+scheme, a very Gunpowder Plot, for every Saturday's expenses.
+
+All this time I was so conscious of the waste of any promise I had
+given, and of my being utterly neglected, that I should have been
+perfectly miserable, I have no doubt, but for the old books. They were
+my only comfort; and I was as true to them as they were to me, and read
+them over and over I don't know how many times more.
+
+I now approach a period of my life, which I can never lose the
+remembrance of, while I remember anything: and the recollection of
+which has often, without my invocation, come before me like a ghost, and
+haunted happier times.
+
+I had been out, one day, loitering somewhere, in the listless,
+meditative manner that my way of life engendered, when, turning the
+corner of a lane near our house, I came upon Mr. Murdstone walking with
+a gentleman. I was confused, and was going by them, when the gentleman
+cried:
+
+'What! Brooks!'
+
+'No, sir, David Copperfield,' I said.
+
+'Don't tell me. You are Brooks,' said the gentleman. 'You are Brooks of
+Sheffield. That's your name.'
+
+At these words, I observed the gentleman more attentively. His laugh
+coming to my remembrance too, I knew him to be Mr. Quinion, whom I
+had gone over to Lowestoft with Mr. Murdstone to see, before--it is no
+matter--I need not recall when.
+
+'And how do you get on, and where are you being educated, Brooks?' said
+Mr. Quinion.
+
+He had put his hand upon my shoulder, and turned me about, to walk
+with them. I did not know what to reply, and glanced dubiously at Mr.
+Murdstone.
+
+'He is at home at present,' said the latter. 'He is not being educated
+anywhere. I don't know what to do with him. He is a difficult subject.'
+
+That old, double look was on me for a moment; and then his eyes darkened
+with a frown, as it turned, in its aversion, elsewhere.
+
+'Humph!' said Mr. Quinion, looking at us both, I thought. 'Fine
+weather!'
+
+Silence ensued, and I was considering how I could best disengage my
+shoulder from his hand, and go away, when he said:
+
+'I suppose you are a pretty sharp fellow still? Eh, Brooks?'
+
+'Aye! He is sharp enough,' said Mr. Murdstone, impatiently. 'You had
+better let him go. He will not thank you for troubling him.'
+
+On this hint, Mr. Quinion released me, and I made the best of my
+way home. Looking back as I turned into the front garden, I saw Mr.
+Murdstone leaning against the wicket of the churchyard, and Mr. Quinion
+talking to him. They were both looking after me, and I felt that they
+were speaking of me.
+
+Mr. Quinion lay at our house that night. After breakfast, the next
+morning, I had put my chair away, and was going out of the room, when
+Mr. Murdstone called me back. He then gravely repaired to another table,
+where his sister sat herself at her desk. Mr. Quinion, with his hands
+in his pockets, stood looking out of window; and I stood looking at them
+all.
+
+'David,' said Mr. Murdstone, 'to the young this is a world for action;
+not for moping and droning in.' --'As you do,' added his sister.
+
+'Jane Murdstone, leave it to me, if you please. I say, David, to the
+young this is a world for action, and not for moping and droning in. It
+is especially so for a young boy of your disposition, which requires a
+great deal of correcting; and to which no greater service can be done
+than to force it to conform to the ways of the working world, and to
+bend it and break it.'
+
+'For stubbornness won't do here,' said his sister 'What it wants is, to
+be crushed. And crushed it must be. Shall be, too!'
+
+He gave her a look, half in remonstrance, half in approval, and went on:
+
+'I suppose you know, David, that I am not rich. At any rate, you know it
+now. You have received some considerable education already. Education is
+costly; and even if it were not, and I could afford it, I am of opinion
+that it would not be at all advantageous to you to be kept at school.
+What is before you, is a fight with the world; and the sooner you begin
+it, the better.'
+
+I think it occurred to me that I had already begun it, in my poor way:
+but it occurs to me now, whether or no.
+
+'You have heard the "counting-house" mentioned sometimes,' said Mr.
+Murdstone.
+
+'The counting-house, sir?' I repeated. 'Of Murdstone and Grinby, in the
+wine trade,' he replied.
+
+I suppose I looked uncertain, for he went on hastily:
+
+'You have heard the "counting-house" mentioned, or the business, or the
+cellars, or the wharf, or something about it.'
+
+'I think I have heard the business mentioned, sir,' I said, remembering
+what I vaguely knew of his and his sister's resources. 'But I don't know
+when.'
+
+'It does not matter when,' he returned. 'Mr. Quinion manages that
+business.'
+
+I glanced at the latter deferentially as he stood looking out of window.
+
+'Mr. Quinion suggests that it gives employment to some other boys,
+and that he sees no reason why it shouldn't, on the same terms, give
+employment to you.'
+
+'He having,' Mr. Quinion observed in a low voice, and half turning
+round, 'no other prospect, Murdstone.'
+
+Mr. Murdstone, with an impatient, even an angry gesture, resumed,
+without noticing what he had said:
+
+'Those terms are, that you will earn enough for yourself to provide for
+your eating and drinking, and pocket-money. Your lodging (which I have
+arranged for) will be paid by me. So will your washing--'
+
+'--Which will be kept down to my estimate,' said his sister.
+
+'Your clothes will be looked after for you, too,' said Mr. Murdstone;
+'as you will not be able, yet awhile, to get them for yourself. So you
+are now going to London, David, with Mr. Quinion, to begin the world on
+your own account.'
+
+'In short, you are provided for,' observed his sister; 'and will please
+to do your duty.'
+
+Though I quite understood that the purpose of this announcement was
+to get rid of me, I have no distinct remembrance whether it pleased
+or frightened me. My impression is, that I was in a state of confusion
+about it, and, oscillating between the two points, touched neither. Nor
+had I much time for the clearing of my thoughts, as Mr. Quinion was to
+go upon the morrow.
+
+Behold me, on the morrow, in a much-worn little white hat, with a black
+crape round it for my mother, a black jacket, and a pair of hard, stiff
+corduroy trousers--which Miss Murdstone considered the best armour for
+the legs in that fight with the world which was now to come off. Behold
+me so attired, and with my little worldly all before me in a small
+trunk, sitting, a lone lorn child (as Mrs. Gummidge might have said),
+in the post-chaise that was carrying Mr. Quinion to the London coach at
+Yarmouth! See, how our house and church are lessening in the distance;
+how the grave beneath the tree is blotted out by intervening objects;
+how the spire points upwards from my old playground no more, and the sky
+is empty!
+
+
+
+CHAPTER 11. I BEGIN LIFE ON MY OWN ACCOUNT, AND DON'T LIKE IT
+
+
+I know enough of the world now, to have almost lost the capacity of
+being much surprised by anything; but it is matter of some surprise to
+me, even now, that I can have been so easily thrown away at such an age.
+A child of excellent abilities, and with strong powers of observation,
+quick, eager, delicate, and soon hurt bodily or mentally, it seems
+wonderful to me that nobody should have made any sign in my behalf. But
+none was made; and I became, at ten years old, a little labouring hind
+in the service of Murdstone and Grinby.
+
+Murdstone and Grinby's warehouse was at the waterside. It was down in
+Blackfriars. Modern improvements have altered the place; but it was the
+last house at the bottom of a narrow street, curving down hill to the
+river, with some stairs at the end, where people took boat. It was a
+crazy old house with a wharf of its own, abutting on the water when the
+tide was in, and on the mud when the tide was out, and literally overrun
+with rats. Its panelled rooms, discoloured with the dirt and smoke of
+a hundred years, I dare say; its decaying floors and staircase; the
+squeaking and scuffling of the old grey rats down in the cellars; and
+the dirt and rottenness of the place; are things, not of many years ago,
+in my mind, but of the present instant. They are all before me, just as
+they were in the evil hour when I went among them for the first time,
+with my trembling hand in Mr. Quinion's.
+
+Murdstone and Grinby's trade was among a good many kinds of people, but
+an important branch of it was the supply of wines and spirits to certain
+packet ships. I forget now where they chiefly went, but I think there
+were some among them that made voyages both to the East and West Indies.
+I know that a great many empty bottles were one of the consequences of
+this traffic, and that certain men and boys were employed to examine
+them against the light, and reject those that were flawed, and to rinse
+and wash them. When the empty bottles ran short, there were labels to be
+pasted on full ones, or corks to be fitted to them, or seals to be put
+upon the corks, or finished bottles to be packed in casks. All this work
+was my work, and of the boys employed upon it I was one.
+
+There were three or four of us, counting me. My working place was
+established in a corner of the warehouse, where Mr. Quinion could see
+me, when he chose to stand up on the bottom rail of his stool in the
+counting-house, and look at me through a window above the desk. Hither,
+on the first morning of my so auspiciously beginning life on my own
+account, the oldest of the regular boys was summoned to show me my
+business. His name was Mick Walker, and he wore a ragged apron and a
+paper cap. He informed me that his father was a bargeman, and walked, in
+a black velvet head-dress, in the Lord Mayor's Show. He also informed me
+that our principal associate would be another boy whom he introduced by
+the--to me--extraordinary name of Mealy Potatoes. I discovered, however,
+that this youth had not been christened by that name, but that it had
+been bestowed upon him in the warehouse, on account of his complexion,
+which was pale or mealy. Mealy's father was a waterman, who had the
+additional distinction of being a fireman, and was engaged as such at
+one of the large theatres; where some young relation of Mealy's--I think
+his little sister--did Imps in the Pantomimes.
+
+No words can express the secret agony of my soul as I sunk into this
+companionship; compared these henceforth everyday associates with those
+of my happier childhood--not to say with Steerforth, Traddles, and the
+rest of those boys; and felt my hopes of growing up to be a learned
+and distinguished man, crushed in my bosom. The deep remembrance of the
+sense I had, of being utterly without hope now; of the shame I felt in
+my position; of the misery it was to my young heart to believe that day
+by day what I had learned, and thought, and delighted in, and raised my
+fancy and my emulation up by, would pass away from me, little by little,
+never to be brought back any more; cannot be written. As often as Mick
+Walker went away in the course of that forenoon, I mingled my tears with
+the water in which I was washing the bottles; and sobbed as if there
+were a flaw in my own breast, and it were in danger of bursting.
+
+The counting-house clock was at half past twelve, and there was
+general preparation for going to dinner, when Mr. Quinion tapped at the
+counting-house window, and beckoned to me to go in. I went in, and
+found there a stoutish, middle-aged person, in a brown surtout and black
+tights and shoes, with no more hair upon his head (which was a large
+one, and very shining) than there is upon an egg, and with a very
+extensive face, which he turned full upon me. His clothes were shabby,
+but he had an imposing shirt-collar on. He carried a jaunty sort of a
+stick, with a large pair of rusty tassels to it; and a quizzing-glass
+hung outside his coat,--for ornament, I afterwards found, as he very
+seldom looked through it, and couldn't see anything when he did.
+
+'This,' said Mr. Quinion, in allusion to myself, 'is he.'
+
+'This,' said the stranger, with a certain condescending roll in his
+voice, and a certain indescribable air of doing something genteel, which
+impressed me very much, 'is Master Copperfield. I hope I see you well,
+sir?'
+
+I said I was very well, and hoped he was. I was sufficiently ill at
+ease, Heaven knows; but it was not in my nature to complain much at that
+time of my life, so I said I was very well, and hoped he was.
+
+'I am,' said the stranger, 'thank Heaven, quite well. I have received a
+letter from Mr. Murdstone, in which he mentions that he would desire
+me to receive into an apartment in the rear of my house, which is at
+present unoccupied--and is, in short, to be let as a--in short,'
+said the stranger, with a smile and in a burst of confidence, 'as a
+bedroom--the young beginner whom I have now the pleasure to--' and the
+stranger waved his hand, and settled his chin in his shirt-collar.
+
+'This is Mr. Micawber,' said Mr. Quinion to me.
+
+'Ahem!' said the stranger, 'that is my name.'
+
+'Mr. Micawber,' said Mr. Quinion, 'is known to Mr. Murdstone. He takes
+orders for us on commission, when he can get any. He has been written to
+by Mr. Murdstone, on the subject of your lodgings, and he will receive
+you as a lodger.'
+
+'My address,' said Mr. Micawber, 'is Windsor Terrace, City Road. I--in
+short,' said Mr. Micawber, with the same genteel air, and in another
+burst of confidence--'I live there.'
+
+I made him a bow.
+
+'Under the impression,' said Mr. Micawber, 'that your peregrinations in
+this metropolis have not as yet been extensive, and that you might have
+some difficulty in penetrating the arcana of the Modern Babylon in the
+direction of the City Road,--in short,' said Mr. Micawber, in another
+burst of confidence, 'that you might lose yourself--I shall be happy to
+call this evening, and install you in the knowledge of the nearest way.'
+
+I thanked him with all my heart, for it was friendly in him to offer to
+take that trouble.
+
+'At what hour,' said Mr. Micawber, 'shall I--'
+
+'At about eight,' said Mr. Quinion.
+
+'At about eight,' said Mr. Micawber. 'I beg to wish you good day, Mr.
+Quinion. I will intrude no longer.'
+
+So he put on his hat, and went out with his cane under his arm: very
+upright, and humming a tune when he was clear of the counting-house.
+
+Mr. Quinion then formally engaged me to be as useful as I could in
+the warehouse of Murdstone and Grinby, at a salary, I think, of six
+shillings a week. I am not clear whether it was six or seven. I am
+inclined to believe, from my uncertainty on this head, that it was six
+at first and seven afterwards. He paid me a week down (from his own
+pocket, I believe), and I gave Mealy sixpence out of it to get my
+trunk carried to Windsor Terrace that night: it being too heavy for my
+strength, small as it was. I paid sixpence more for my dinner, which was
+a meat pie and a turn at a neighbouring pump; and passed the hour which
+was allowed for that meal, in walking about the streets.
+
+At the appointed time in the evening, Mr. Micawber reappeared. I washed
+my hands and face, to do the greater honour to his gentility, and we
+walked to our house, as I suppose I must now call it, together; Mr.
+Micawber impressing the name of streets, and the shapes of corner houses
+upon me, as we went along, that I might find my way back, easily, in the
+morning.
+
+Arrived at this house in Windsor Terrace (which I noticed was shabby
+like himself, but also, like himself, made all the show it could), he
+presented me to Mrs. Micawber, a thin and faded lady, not at all
+young, who was sitting in the parlour (the first floor was altogether
+unfurnished, and the blinds were kept down to delude the neighbours),
+with a baby at her breast. This baby was one of twins; and I may remark
+here that I hardly ever, in all my experience of the family, saw both
+the twins detached from Mrs. Micawber at the same time. One of them was
+always taking refreshment.
+
+There were two other children; Master Micawber, aged about four, and
+Miss Micawber, aged about three. These, and a dark-complexioned young
+woman, with a habit of snorting, who was servant to the family, and
+informed me, before half an hour had expired, that she was 'a Orfling',
+and came from St. Luke's workhouse, in the neighbourhood, completed the
+establishment. My room was at the top of the house, at the back: a close
+chamber; stencilled all over with an ornament which my young imagination
+represented as a blue muffin; and very scantily furnished.
+
+'I never thought,' said Mrs. Micawber, when she came up, twin and all,
+to show me the apartment, and sat down to take breath, 'before I was
+married, when I lived with papa and mama, that I should ever find it
+necessary to take a lodger. But Mr. Micawber being in difficulties, all
+considerations of private feeling must give way.'
+
+I said: 'Yes, ma'am.'
+
+'Mr. Micawber's difficulties are almost overwhelming just at present,'
+said Mrs. Micawber; 'and whether it is possible to bring him through
+them, I don't know. When I lived at home with papa and mama, I really
+should have hardly understood what the word meant, in the sense in which
+I now employ it, but experientia does it,--as papa used to say.'
+
+I cannot satisfy myself whether she told me that Mr. Micawber had been
+an officer in the Marines, or whether I have imagined it. I only know
+that I believe to this hour that he WAS in the Marines once upon a time,
+without knowing why. He was a sort of town traveller for a number
+of miscellaneous houses, now; but made little or nothing of it, I am
+afraid.
+
+'If Mr. Micawber's creditors will not give him time,' said Mrs.
+Micawber, 'they must take the consequences; and the sooner they bring it
+to an issue the better. Blood cannot be obtained from a stone, neither
+can anything on account be obtained at present (not to mention law
+expenses) from Mr. Micawber.'
+
+I never can quite understand whether my precocious self-dependence
+confused Mrs. Micawber in reference to my age, or whether she was so
+full of the subject that she would have talked about it to the very
+twins if there had been nobody else to communicate with, but this was
+the strain in which she began, and she went on accordingly all the time
+I knew her.
+
+Poor Mrs. Micawber! She said she had tried to exert herself, and so,
+I have no doubt, she had. The centre of the street door was perfectly
+covered with a great brass-plate, on which was engraved 'Mrs. Micawber's
+Boarding Establishment for Young Ladies': but I never found that any
+young lady had ever been to school there; or that any young lady ever
+came, or proposed to come; or that the least preparation was ever made
+to receive any young lady. The only visitors I ever saw, or heard of,
+were creditors. THEY used to come at all hours, and some of them were
+quite ferocious. One dirty-faced man, I think he was a boot-maker,
+used to edge himself into the passage as early as seven o'clock in the
+morning, and call up the stairs to Mr. Micawber--'Come! You ain't out
+yet, you know. Pay us, will you? Don't hide, you know; that's mean. I
+wouldn't be mean if I was you. Pay us, will you? You just pay us, d'ye
+hear? Come!' Receiving no answer to these taunts, he would mount in
+his wrath to the words 'swindlers' and 'robbers'; and these being
+ineffectual too, would sometimes go to the extremity of crossing the
+street, and roaring up at the windows of the second floor, where he knew
+Mr. Micawber was. At these times, Mr. Micawber would be transported with
+grief and mortification, even to the length (as I was once made aware by
+a scream from his wife) of making motions at himself with a razor;
+but within half-an-hour afterwards, he would polish up his shoes with
+extraordinary pains, and go out, humming a tune with a greater air of
+gentility than ever. Mrs. Micawber was quite as elastic. I have known
+her to be thrown into fainting fits by the king's taxes at three
+o'clock, and to eat lamb chops, breaded, and drink warm ale (paid for
+with two tea-spoons that had gone to the pawnbroker's) at four. On one
+occasion, when an execution had just been put in, coming home through
+some chance as early as six o'clock, I saw her lying (of course with a
+twin) under the grate in a swoon, with her hair all torn about her face;
+but I never knew her more cheerful than she was, that very same night,
+over a veal cutlet before the kitchen fire, telling me stories about her
+papa and mama, and the company they used to keep.
+
+In this house, and with this family, I passed my leisure time. My own
+exclusive breakfast of a penny loaf and a pennyworth of milk, I provided
+myself. I kept another small loaf, and a modicum of cheese, on a
+particular shelf of a particular cupboard, to make my supper on when I
+came back at night. This made a hole in the six or seven shillings, I
+know well; and I was out at the warehouse all day, and had to support
+myself on that money all the week. From Monday morning until Saturday
+night, I had no advice, no counsel, no encouragement, no consolation,
+no assistance, no support, of any kind, from anyone, that I can call to
+mind, as I hope to go to heaven!
+
+I was so young and childish, and so little qualified--how could I be
+otherwise?--to undertake the whole charge of my own existence, that
+often, in going to Murdstone and Grinby's, of a morning, I could
+not resist the stale pastry put out for sale at half-price at the
+pastrycooks' doors, and spent in that the money I should have kept for
+my dinner. Then, I went without my dinner, or bought a roll or a slice
+of pudding. I remember two pudding shops, between which I was divided,
+according to my finances. One was in a court close to St. Martin's
+Church--at the back of the church,--which is now removed altogether.
+The pudding at that shop was made of currants, and was rather a special
+pudding, but was dear, twopennyworth not being larger than a pennyworth
+of more ordinary pudding. A good shop for the latter was in the
+Strand--somewhere in that part which has been rebuilt since. It was a
+stout pale pudding, heavy and flabby, and with great flat raisins in it,
+stuck in whole at wide distances apart. It came up hot at about my time
+every day, and many a day did I dine off it. When I dined regularly and
+handsomely, I had a saveloy and a penny loaf, or a fourpenny plate of
+red beef from a cook's shop; or a plate of bread and cheese and a
+glass of beer, from a miserable old public-house opposite our place of
+business, called the Lion, or the Lion and something else that I have
+forgotten. Once, I remember carrying my own bread (which I had brought
+from home in the morning) under my arm, wrapped in a piece of paper,
+like a book, and going to a famous alamode beef-house near Drury Lane,
+and ordering a 'small plate' of that delicacy to eat with it. What the
+waiter thought of such a strange little apparition coming in all alone,
+I don't know; but I can see him now, staring at me as I ate my dinner,
+and bringing up the other waiter to look. I gave him a halfpenny for
+himself, and I wish he hadn't taken it.
+
+We had half-an-hour, I think, for tea. When I had money enough, I used
+to get half-a-pint of ready-made coffee and a slice of bread and butter.
+When I had none, I used to look at a venison shop in Fleet Street; or
+I have strolled, at such a time, as far as Covent Garden Market, and
+stared at the pineapples. I was fond of wandering about the Adelphi,
+because it was a mysterious place, with those dark arches. I see myself
+emerging one evening from some of these arches, on a little public-house
+close to the river, with an open space before it, where some
+coal-heavers were dancing; to look at whom I sat down upon a bench. I
+wonder what they thought of me!
+
+I was such a child, and so little, that frequently when I went into the
+bar of a strange public-house for a glass of ale or porter, to moisten
+what I had had for dinner, they were afraid to give it me. I remember
+one hot evening I went into the bar of a public-house, and said to the
+landlord: 'What is your best--your very best--ale a glass?' For it was a
+special occasion. I don't know what. It may have been my birthday.
+
+'Twopence-halfpenny,' says the landlord, 'is the price of the Genuine
+Stunning ale.'
+
+'Then,' says I, producing the money, 'just draw me a glass of the
+Genuine Stunning, if you please, with a good head to it.'
+
+The landlord looked at me in return over the bar, from head to foot,
+with a strange smile on his face; and instead of drawing the beer,
+looked round the screen and said something to his wife. She came out
+from behind it, with her work in her hand, and joined him in surveying
+me. Here we stand, all three, before me now. The landlord in his
+shirt-sleeves, leaning against the bar window-frame; his wife looking
+over the little half-door; and I, in some confusion, looking up at them
+from outside the partition. They asked me a good many questions; as,
+what my name was, how old I was, where I lived, how I was employed,
+and how I came there. To all of which, that I might commit nobody, I
+invented, I am afraid, appropriate answers. They served me with the ale,
+though I suspect it was not the Genuine Stunning; and the landlord's
+wife, opening the little half-door of the bar, and bending down, gave
+me my money back, and gave me a kiss that was half admiring and half
+compassionate, but all womanly and good, I am sure.
+
+I know I do not exaggerate, unconsciously and unintentionally, the
+scantiness of my resources or the difficulties of my life. I know that
+if a shilling were given me by Mr. Quinion at any time, I spent it in
+a dinner or a tea. I know that I worked, from morning until night, with
+common men and boys, a shabby child. I know that I lounged about the
+streets, insufficiently and unsatisfactorily fed. I know that, but for
+the mercy of God, I might easily have been, for any care that was taken
+of me, a little robber or a little vagabond.
+
+Yet I held some station at Murdstone and Grinby's too. Besides that Mr.
+Quinion did what a careless man so occupied, and dealing with a thing so
+anomalous, could, to treat me as one upon a different footing from the
+rest, I never said, to man or boy, how it was that I came to be there,
+or gave the least indication of being sorry that I was there. That I
+suffered in secret, and that I suffered exquisitely, no one ever knew
+but I. How much I suffered, it is, as I have said already, utterly
+beyond my power to tell. But I kept my own counsel, and I did my work.
+I knew from the first, that, if I could not do my work as well as any
+of the rest, I could not hold myself above slight and contempt. I soon
+became at least as expeditious and as skilful as either of the other
+boys. Though perfectly familiar with them, my conduct and manner were
+different enough from theirs to place a space between us. They and
+the men generally spoke of me as 'the little gent', or 'the young
+Suffolker.' A certain man named Gregory, who was foreman of the packers,
+and another named Tipp, who was the carman, and wore a red jacket, used
+to address me sometimes as 'David': but I think it was mostly when we
+were very confidential, and when I had made some efforts to entertain
+them, over our work, with some results of the old readings; which were
+fast perishing out of my remembrance. Mealy Potatoes uprose once, and
+rebelled against my being so distinguished; but Mick Walker settled him
+in no time.
+
+My rescue from this kind of existence I considered quite hopeless, and
+abandoned, as such, altogether. I am solemnly convinced that I never for
+one hour was reconciled to it, or was otherwise than miserably unhappy;
+but I bore it; and even to Peggotty, partly for the love of her and
+partly for shame, never in any letter (though many passed between us)
+revealed the truth.
+
+Mr. Micawber's difficulties were an addition to the distressed state of
+my mind. In my forlorn state I became quite attached to the family, and
+used to walk about, busy with Mrs. Micawber's calculations of ways and
+means, and heavy with the weight of Mr. Micawber's debts. On a Saturday
+night, which was my grand treat,--partly because it was a great thing
+to walk home with six or seven shillings in my pocket, looking into the
+shops and thinking what such a sum would buy, and partly because I went
+home early,--Mrs. Micawber would make the most heart-rending confidences
+to me; also on a Sunday morning, when I mixed the portion of tea or
+coffee I had bought over-night, in a little shaving-pot, and sat late
+at my breakfast. It was nothing at all unusual for Mr. Micawber to sob
+violently at the beginning of one of these Saturday night conversations,
+and sing about jack's delight being his lovely Nan, towards the end of
+it. I have known him come home to supper with a flood of tears, and a
+declaration that nothing was now left but a jail; and go to bed making a
+calculation of the expense of putting bow-windows to the house, 'in
+case anything turned up', which was his favourite expression. And Mrs.
+Micawber was just the same.
+
+A curious equality of friendship, originating, I suppose, in our
+respective circumstances, sprung up between me and these people,
+notwithstanding the ludicrous disparity in our years. But I never
+allowed myself to be prevailed upon to accept any invitation to eat and
+drink with them out of their stock (knowing that they got on badly with
+the butcher and baker, and had often not too much for themselves),
+until Mrs. Micawber took me into her entire confidence. This she did one
+evening as follows:
+
+'Master Copperfield,' said Mrs. Micawber, 'I make no stranger of you,
+and therefore do not hesitate to say that Mr. Micawber's difficulties
+are coming to a crisis.'
+
+It made me very miserable to hear it, and I looked at Mrs. Micawber's
+red eyes with the utmost sympathy.
+
+'With the exception of the heel of a Dutch cheese--which is not adapted
+to the wants of a young family'--said Mrs. Micawber, 'there is really
+not a scrap of anything in the larder. I was accustomed to speak of
+the larder when I lived with papa and mama, and I use the word almost
+unconsciously. What I mean to express is, that there is nothing to eat
+in the house.'
+
+'Dear me!' I said, in great concern.
+
+I had two or three shillings of my week's money in my pocket--from which
+I presume that it must have been on a Wednesday night when we held this
+conversation--and I hastily produced them, and with heartfelt emotion
+begged Mrs. Micawber to accept of them as a loan. But that lady, kissing
+me, and making me put them back in my pocket, replied that she couldn't
+think of it.
+
+'No, my dear Master Copperfield,' said she, 'far be it from my thoughts!
+But you have a discretion beyond your years, and can render me another
+kind of service, if you will; and a service I will thankfully accept
+of.'
+
+I begged Mrs. Micawber to name it.
+
+'I have parted with the plate myself,' said Mrs. Micawber. 'Six tea, two
+salt, and a pair of sugars, I have at different times borrowed money on,
+in secret, with my own hands. But the twins are a great tie; and to me,
+with my recollections, of papa and mama, these transactions are very
+painful. There are still a few trifles that we could part with. Mr.
+Micawber's feelings would never allow him to dispose of them; and
+Clickett'--this was the girl from the workhouse--'being of a vulgar
+mind, would take painful liberties if so much confidence was reposed in
+her. Master Copperfield, if I might ask you--'
+
+I understood Mrs. Micawber now, and begged her to make use of me to any
+extent. I began to dispose of the more portable articles of property
+that very evening; and went out on a similar expedition almost every
+morning, before I went to Murdstone and Grinby's.
+
+Mr. Micawber had a few books on a little chiffonier, which he called the
+library; and those went first. I carried them, one after another, to
+a bookstall in the City Road--one part of which, near our house, was
+almost all bookstalls and bird shops then--and sold them for whatever
+they would bring. The keeper of this bookstall, who lived in a little
+house behind it, used to get tipsy every night, and to be violently
+scolded by his wife every morning. More than once, when I went there
+early, I had audience of him in a turn-up bedstead, with a cut in his
+forehead or a black eye, bearing witness to his excesses over-night (I
+am afraid he was quarrelsome in his drink), and he, with a shaking
+hand, endeavouring to find the needful shillings in one or other of the
+pockets of his clothes, which lay upon the floor, while his wife, with a
+baby in her arms and her shoes down at heel, never left off rating him.
+Sometimes he had lost his money, and then he would ask me to call again;
+but his wife had always got some--had taken his, I dare say, while he
+was drunk--and secretly completed the bargain on the stairs, as we went
+down together. At the pawnbroker's shop, too, I began to be very well
+known. The principal gentleman who officiated behind the counter, took
+a good deal of notice of me; and often got me, I recollect, to decline a
+Latin noun or adjective, or to conjugate a Latin verb, in his ear, while
+he transacted my business. After all these occasions Mrs. Micawber made
+a little treat, which was generally a supper; and there was a peculiar
+relish in these meals which I well remember.
+
+At last Mr. Micawber's difficulties came to a crisis, and he was
+arrested early one morning, and carried over to the King's Bench Prison
+in the Borough. He told me, as he went out of the house, that the God
+of day had now gone down upon him--and I really thought his heart was
+broken and mine too. But I heard, afterwards, that he was seen to play a
+lively game at skittles, before noon.
+
+On the first Sunday after he was taken there, I was to go and see him,
+and have dinner with him. I was to ask my way to such a place, and just
+short of that place I should see such another place, and just short of
+that I should see a yard, which I was to cross, and keep straight on
+until I saw a turnkey. All this I did; and when at last I did see a
+turnkey (poor little fellow that I was!), and thought how, when Roderick
+Random was in a debtors' prison, there was a man there with nothing
+on him but an old rug, the turnkey swam before my dimmed eyes and my
+beating heart.
+
+Mr. Micawber was waiting for me within the gate, and we went up to his
+room (top story but one), and cried very much. He solemnly conjured me,
+I remember, to take warning by his fate; and to observe that if a man
+had twenty pounds a-year for his income, and spent nineteen pounds
+nineteen shillings and sixpence, he would be happy, but that if he
+spent twenty pounds one he would be miserable. After which he borrowed a
+shilling of me for porter, gave me a written order on Mrs. Micawber for
+the amount, and put away his pocket-handkerchief, and cheered up.
+
+We sat before a little fire, with two bricks put within the rusted
+grate, one on each side, to prevent its burning too many coals; until
+another debtor, who shared the room with Mr. Micawber, came in from the
+bakehouse with the loin of mutton which was our joint-stock repast.
+Then I was sent up to 'Captain Hopkins' in the room overhead, with Mr.
+Micawber's compliments, and I was his young friend, and would Captain
+Hopkins lend me a knife and fork.
+
+Captain Hopkins lent me the knife and fork, with his compliments to Mr.
+Micawber. There was a very dirty lady in his little room, and two wan
+girls, his daughters, with shock heads of hair. I thought it was better
+to borrow Captain Hopkins's knife and fork, than Captain Hopkins's comb.
+The Captain himself was in the last extremity of shabbiness, with large
+whiskers, and an old, old brown great-coat with no other coat below it.
+I saw his bed rolled up in a corner; and what plates and dishes and pots
+he had, on a shelf; and I divined (God knows how) that though the two
+girls with the shock heads of hair were Captain Hopkins's children, the
+dirty lady was not married to Captain Hopkins. My timid station on his
+threshold was not occupied more than a couple of minutes at most; but
+I came down again with all this in my knowledge, as surely as the knife
+and fork were in my hand.
+
+There was something gipsy-like and agreeable in the dinner, after all.
+I took back Captain Hopkins's knife and fork early in the afternoon,
+and went home to comfort Mrs. Micawber with an account of my visit.
+She fainted when she saw me return, and made a little jug of egg-hot
+afterwards to console us while we talked it over.
+
+I don't know how the household furniture came to be sold for the family
+benefit, or who sold it, except that I did not. Sold it was, however,
+and carried away in a van; except the bed, a few chairs, and the kitchen
+table. With these possessions we encamped, as it were, in the two
+parlours of the emptied house in Windsor Terrace; Mrs. Micawber, the
+children, the Orfling, and myself; and lived in those rooms night and
+day. I have no idea for how long, though it seems to me for a long
+time. At last Mrs. Micawber resolved to move into the prison, where Mr.
+Micawber had now secured a room to himself. So I took the key of the
+house to the landlord, who was very glad to get it; and the beds were
+sent over to the King's Bench, except mine, for which a little room was
+hired outside the walls in the neighbourhood of that Institution, very
+much to my satisfaction, since the Micawbers and I had become too used
+to one another, in our troubles, to part. The Orfling was likewise
+accommodated with an inexpensive lodging in the same neighbourhood.
+Mine was a quiet back-garret with a sloping roof, commanding a pleasant
+prospect of a timberyard; and when I took possession of it, with the
+reflection that Mr. Micawber's troubles had come to a crisis at last, I
+thought it quite a paradise.
+
+All this time I was working at Murdstone and Grinby's in the same common
+way, and with the same common companions, and with the same sense of
+unmerited degradation as at first. But I never, happily for me no doubt,
+made a single acquaintance, or spoke to any of the many boys whom I
+saw daily in going to the warehouse, in coming from it, and in prowling
+about the streets at meal-times. I led the same secretly unhappy life;
+but I led it in the same lonely, self-reliant manner. The only changes
+I am conscious of are, firstly, that I had grown more shabby, and
+secondly, that I was now relieved of much of the weight of Mr. and Mrs.
+Micawber's cares; for some relatives or friends had engaged to help them
+at their present pass, and they lived more comfortably in the prison
+than they had lived for a long while out of it. I used to breakfast with
+them now, in virtue of some arrangement, of which I have forgotten
+the details. I forget, too, at what hour the gates were opened in the
+morning, admitting of my going in; but I know that I was often up at six
+o'clock, and that my favourite lounging-place in the interval was old
+London Bridge, where I was wont to sit in one of the stone recesses,
+watching the people going by, or to look over the balustrades at the sun
+shining in the water, and lighting up the golden flame on the top of the
+Monument. The Orfling met me here sometimes, to be told some astonishing
+fictions respecting the wharves and the Tower; of which I can say no
+more than that I hope I believed them myself. In the evening I used
+to go back to the prison, and walk up and down the parade with Mr.
+Micawber; or play casino with Mrs. Micawber, and hear reminiscences of
+her papa and mama. Whether Mr. Murdstone knew where I was, I am unable
+to say. I never told them at Murdstone and Grinby's.
+
+Mr. Micawber's affairs, although past their crisis, were very much
+involved by reason of a certain 'Deed', of which I used to hear a great
+deal, and which I suppose, now, to have been some former composition
+with his creditors, though I was so far from being clear about it
+then, that I am conscious of having confounded it with those demoniacal
+parchments which are held to have, once upon a time, obtained to a great
+extent in Germany. At last this document appeared to be got out of the
+way, somehow; at all events it ceased to be the rock-ahead it had been;
+and Mrs. Micawber informed me that 'her family' had decided that Mr.
+Micawber should apply for his release under the Insolvent Debtors Act,
+which would set him free, she expected, in about six weeks.
+
+'And then,' said Mr. Micawber, who was present, 'I have no doubt I
+shall, please Heaven, begin to be beforehand with the world, and to live
+in a perfectly new manner, if--in short, if anything turns up.'
+
+By way of going in for anything that might be on the cards, I call to
+mind that Mr. Micawber, about this time, composed a petition to the
+House of Commons, praying for an alteration in the law of imprisonment
+for debt. I set down this remembrance here, because it is an instance to
+myself of the manner in which I fitted my old books to my altered life,
+and made stories for myself, out of the streets, and out of men and
+women; and how some main points in the character I shall unconsciously
+develop, I suppose, in writing my life, were gradually forming all this
+while.
+
+There was a club in the prison, in which Mr. Micawber, as a gentleman,
+was a great authority. Mr. Micawber had stated his idea of this petition
+to the club, and the club had strongly approved of the same. Wherefore
+Mr. Micawber (who was a thoroughly good-natured man, and as active a
+creature about everything but his own affairs as ever existed, and never
+so happy as when he was busy about something that could never be of any
+profit to him) set to work at the petition, invented it, engrossed it
+on an immense sheet of paper, spread it out on a table, and appointed a
+time for all the club, and all within the walls if they chose, to come
+up to his room and sign it.
+
+When I heard of this approaching ceremony, I was so anxious to see them
+all come in, one after another, though I knew the greater part of
+them already, and they me, that I got an hour's leave of absence from
+Murdstone and Grinby's, and established myself in a corner for that
+purpose. As many of the principal members of the club as could be got
+into the small room without filling it, supported Mr. Micawber in front
+of the petition, while my old friend Captain Hopkins (who had washed
+himself, to do honour to so solemn an occasion) stationed himself close
+to it, to read it to all who were unacquainted with its contents. The
+door was then thrown open, and the general population began to come in,
+in a long file: several waiting outside, while one entered, affixed his
+signature, and went out. To everybody in succession, Captain Hopkins
+said: 'Have you read it?'--'No.'---'Would you like to hear it read?' If
+he weakly showed the least disposition to hear it, Captain Hopkins, in
+a loud sonorous voice, gave him every word of it. The Captain would
+have read it twenty thousand times, if twenty thousand people would have
+heard him, one by one. I remember a certain luscious roll he gave to
+such phrases as 'The people's representatives in Parliament assembled,'
+'Your petitioners therefore humbly approach your honourable house,' 'His
+gracious Majesty's unfortunate subjects,' as if the words were something
+real in his mouth, and delicious to taste; Mr. Micawber, meanwhile,
+listening with a little of an author's vanity, and contemplating (not
+severely) the spikes on the opposite wall.
+
+As I walked to and fro daily between Southwark and Blackfriars, and
+lounged about at meal-times in obscure streets, the stones of which
+may, for anything I know, be worn at this moment by my childish feet, I
+wonder how many of these people were wanting in the crowd that used to
+come filing before me in review again, to the echo of Captain Hopkins's
+voice! When my thoughts go back, now, to that slow agony of my youth, I
+wonder how much of the histories I invented for such people hangs like a
+mist of fancy over well-remembered facts! When I tread the old ground,
+I do not wonder that I seem to see and pity, going on before me, an
+innocent romantic boy, making his imaginative world out of such strange
+experiences and sordid things!
+
+
+
+CHAPTER 12. LIKING LIFE ON MY OWN ACCOUNT NO BETTER, I FORM A GREAT RESOLUTION
+
+
+In due time, Mr. Micawber's petition was ripe for hearing; and that
+gentleman was ordered to be discharged under the Act, to my great joy.
+His creditors were not implacable; and Mrs. Micawber informed me that
+even the revengeful boot-maker had declared in open court that he bore
+him no malice, but that when money was owing to him he liked to be paid.
+He said he thought it was human nature.
+
+M r Micawber returned to the King's Bench when his case was over, as
+some fees were to be settled, and some formalities observed, before he
+could be actually released. The club received him with transport, and
+held an harmonic meeting that evening in his honour; while Mrs. Micawber
+and I had a lamb's fry in private, surrounded by the sleeping family.
+
+'On such an occasion I will give you, Master Copperfield,' said Mrs.
+Micawber, 'in a little more flip,' for we had been having some already,
+'the memory of my papa and mama.'
+
+'Are they dead, ma'am?' I inquired, after drinking the toast in a
+wine-glass.
+
+'My mama departed this life,' said Mrs. Micawber, 'before Mr. Micawber's
+difficulties commenced, or at least before they became pressing. My papa
+lived to bail Mr. Micawber several times, and then expired, regretted by
+a numerous circle.'
+
+Mrs. Micawber shook her head, and dropped a pious tear upon the twin who
+happened to be in hand.
+
+As I could hardly hope for a more favourable opportunity of putting a
+question in which I had a near interest, I said to Mrs. Micawber:
+
+'May I ask, ma'am, what you and Mr. Micawber intend to do, now that Mr.
+Micawber is out of his difficulties, and at liberty? Have you settled
+yet?'
+
+'My family,' said Mrs. Micawber, who always said those two words with an
+air, though I never could discover who came under the denomination, 'my
+family are of opinion that Mr. Micawber should quit London, and exert
+his talents in the country. Mr. Micawber is a man of great talent,
+Master Copperfield.'
+
+I said I was sure of that.
+
+'Of great talent,' repeated Mrs. Micawber. 'My family are of opinion,
+that, with a little interest, something might be done for a man of his
+ability in the Custom House. The influence of my family being local, it
+is their wish that Mr. Micawber should go down to Plymouth. They think
+it indispensable that he should be upon the spot.'
+
+'That he may be ready?' I suggested.
+
+'Exactly,' returned Mrs. Micawber. 'That he may be ready--in case of
+anything turning up.'
+
+'And do you go too, ma'am?'
+
+The events of the day, in combination with the twins, if not with the
+flip, had made Mrs. Micawber hysterical, and she shed tears as she
+replied:
+
+'I never will desert Mr. Micawber. Mr. Micawber may have concealed his
+difficulties from me in the first instance, but his sanguine temper may
+have led him to expect that he would overcome them. The pearl necklace
+and bracelets which I inherited from mama, have been disposed of for
+less than half their value; and the set of coral, which was the wedding
+gift of my papa, has been actually thrown away for nothing. But I never
+will desert Mr. Micawber. No!' cried Mrs. Micawber, more affected than
+before, 'I never will do it! It's of no use asking me!'
+
+I felt quite uncomfortable--as if Mrs. Micawber supposed I had asked her
+to do anything of the sort!--and sat looking at her in alarm.
+
+'Mr. Micawber has his faults. I do not deny that he is improvident. I
+do not deny that he has kept me in the dark as to his resources and his
+liabilities both,' she went on, looking at the wall; 'but I never will
+desert Mr. Micawber!'
+
+Mrs. Micawber having now raised her voice into a perfect scream, I
+was so frightened that I ran off to the club-room, and disturbed Mr.
+Micawber in the act of presiding at a long table, and leading the chorus
+of
+
+     Gee up, Dobbin,
+     Gee ho, Dobbin,
+     Gee up, Dobbin,
+     Gee up, and gee ho--o--o!
+
+with the tidings that Mrs. Micawber was in an alarming state, upon
+which he immediately burst into tears, and came away with me with his
+waistcoat full of the heads and tails of shrimps, of which he had been
+partaking.
+
+'Emma, my angel!' cried Mr. Micawber, running into the room; 'what is
+the matter?'
+
+'I never will desert you, Micawber!' she exclaimed.
+
+'My life!' said Mr. Micawber, taking her in his arms. 'I am perfectly
+aware of it.'
+
+'He is the parent of my children! He is the father of my twins! He is
+the husband of my affections,' cried Mrs. Micawber, struggling; 'and I
+ne--ver--will--desert Mr. Micawber!'
+
+Mr. Micawber was so deeply affected by this proof of her devotion (as
+to me, I was dissolved in tears), that he hung over her in a passionate
+manner, imploring her to look up, and to be calm. But the more he asked
+Mrs. Micawber to look up, the more she fixed her eyes on nothing;
+and the more he asked her to compose herself, the more she wouldn't.
+Consequently Mr. Micawber was soon so overcome, that he mingled his
+tears with hers and mine; until he begged me to do him the favour of
+taking a chair on the staircase, while he got her into bed. I would have
+taken my leave for the night, but he would not hear of my doing that
+until the strangers' bell should ring. So I sat at the staircase window,
+until he came out with another chair and joined me.
+
+'How is Mrs. Micawber now, sir?' I said.
+
+'Very low,' said Mr. Micawber, shaking his head; 'reaction. Ah, this has
+been a dreadful day! We stand alone now--everything is gone from us!'
+
+Mr. Micawber pressed my hand, and groaned, and afterwards shed tears.
+I was greatly touched, and disappointed too, for I had expected that we
+should be quite gay on this happy and long-looked-for occasion. But Mr.
+and Mrs. Micawber were so used to their old difficulties, I think, that
+they felt quite shipwrecked when they came to consider that they were
+released from them. All their elasticity was departed, and I never saw
+them half so wretched as on this night; insomuch that when the bell
+rang, and Mr. Micawber walked with me to the lodge, and parted from me
+there with a blessing, I felt quite afraid to leave him by himself, he
+was so profoundly miserable.
+
+But through all the confusion and lowness of spirits in which we had
+been, so unexpectedly to me, involved, I plainly discerned that Mr. and
+Mrs. Micawber and their family were going away from London, and that a
+parting between us was near at hand. It was in my walk home that night,
+and in the sleepless hours which followed when I lay in bed, that the
+thought first occurred to me--though I don't know how it came into my
+head--which afterwards shaped itself into a settled resolution.
+
+I had grown to be so accustomed to the Micawbers, and had been so
+intimate with them in their distresses, and was so utterly friendless
+without them, that the prospect of being thrown upon some new shift for
+a lodging, and going once more among unknown people, was like being that
+moment turned adrift into my present life, with such a knowledge of it
+ready made as experience had given me. All the sensitive feelings it
+wounded so cruelly, all the shame and misery it kept alive within my
+breast, became more poignant as I thought of this; and I determined that
+the life was unendurable.
+
+That there was no hope of escape from it, unless the escape was my own
+act, I knew quite well. I rarely heard from Miss Murdstone, and never
+from Mr. Murdstone: but two or three parcels of made or mended clothes
+had come up for me, consigned to Mr. Quinion, and in each there was
+a scrap of paper to the effect that J. M. trusted D. C. was applying
+himself to business, and devoting himself wholly to his duties--not the
+least hint of my ever being anything else than the common drudge into
+which I was fast settling down.
+
+The very next day showed me, while my mind was in the first agitation of
+what it had conceived, that Mrs. Micawber had not spoken of their going
+away without warrant. They took a lodging in the house where I lived,
+for a week; at the expiration of which time they were to start for
+Plymouth. Mr. Micawber himself came down to the counting-house, in the
+afternoon, to tell Mr. Quinion that he must relinquish me on the day
+of his departure, and to give me a high character, which I am sure I
+deserved. And Mr. Quinion, calling in Tipp the carman, who was a married
+man, and had a room to let, quartered me prospectively on him--by our
+mutual consent, as he had every reason to think; for I said nothing,
+though my resolution was now taken.
+
+I passed my evenings with Mr. and Mrs. Micawber, during the remaining
+term of our residence under the same roof; and I think we became fonder
+of one another as the time went on. On the last Sunday, they invited me
+to dinner; and we had a loin of pork and apple sauce, and a pudding. I
+had bought a spotted wooden horse over-night as a parting gift to little
+Wilkins Micawber--that was the boy--and a doll for little Emma. I had
+also bestowed a shilling on the Orfling, who was about to be disbanded.
+
+We had a very pleasant day, though we were all in a tender state about
+our approaching separation.
+
+'I shall never, Master Copperfield,' said Mrs. Micawber, 'revert to the
+period when Mr. Micawber was in difficulties, without thinking of
+you. Your conduct has always been of the most delicate and obliging
+description. You have never been a lodger. You have been a friend.'
+
+'My dear,' said Mr. Micawber; 'Copperfield,' for so he had been
+accustomed to call me, of late, 'has a heart to feel for the distresses
+of his fellow-creatures when they are behind a cloud, and a head to
+plan, and a hand to--in short, a general ability to dispose of such
+available property as could be made away with.'
+
+I expressed my sense of this commendation, and said I was very sorry we
+were going to lose one another.
+
+'My dear young friend,' said Mr. Micawber, 'I am older than you; a man
+of some experience in life, and--and of some experience, in short, in
+difficulties, generally speaking. At present, and until something turns
+up (which I am, I may say, hourly expecting), I have nothing to bestow
+but advice. Still my advice is so far worth taking, that--in short, that
+I have never taken it myself, and am the'--here Mr. Micawber, who had
+been beaming and smiling, all over his head and face, up to the present
+moment, checked himself and frowned--'the miserable wretch you behold.'
+
+'My dear Micawber!' urged his wife.
+
+'I say,' returned Mr. Micawber, quite forgetting himself, and smiling
+again, 'the miserable wretch you behold. My advice is, never do tomorrow
+what you can do today. Procrastination is the thief of time. Collar
+him!'
+
+'My poor papa's maxim,' Mrs. Micawber observed.
+
+'My dear,' said Mr. Micawber, 'your papa was very well in his way, and
+Heaven forbid that I should disparage him. Take him for all in all, we
+ne'er shall--in short, make the acquaintance, probably, of anybody else
+possessing, at his time of life, the same legs for gaiters, and able to
+read the same description of print, without spectacles. But he applied
+that maxim to our marriage, my dear; and that was so far prematurely
+entered into, in consequence, that I never recovered the expense.' Mr.
+Micawber looked aside at Mrs. Micawber, and added: 'Not that I am sorry
+for it. Quite the contrary, my love.' After which, he was grave for a
+minute or so.
+
+'My other piece of advice, Copperfield,' said Mr. Micawber, 'you know.
+Annual income twenty pounds, annual expenditure nineteen nineteen and
+six, result happiness. Annual income twenty pounds, annual expenditure
+twenty pounds ought and six, result misery. The blossom is blighted,
+the leaf is withered, the god of day goes down upon the dreary scene,
+and--and in short you are for ever floored. As I am!'
+
+To make his example the more impressive, Mr. Micawber drank a glass of
+punch with an air of great enjoyment and satisfaction, and whistled the
+College Hornpipe.
+
+I did not fail to assure him that I would store these precepts in my
+mind, though indeed I had no need to do so, for, at the time, they
+affected me visibly. Next morning I met the whole family at the coach
+office, and saw them, with a desolate heart, take their places outside,
+at the back.
+
+'Master Copperfield,' said Mrs. Micawber, 'God bless you! I never can
+forget all that, you know, and I never would if I could.'
+
+'Copperfield,' said Mr. Micawber, 'farewell! Every happiness and
+prosperity! If, in the progress of revolving years, I could persuade
+myself that my blighted destiny had been a warning to you, I should feel
+that I had not occupied another man's place in existence altogether in
+vain. In case of anything turning up (of which I am rather confident),
+I shall be extremely happy if it should be in my power to improve your
+prospects.'
+
+I think, as Mrs. Micawber sat at the back of the coach, with the
+children, and I stood in the road looking wistfully at them, a mist
+cleared from her eyes, and she saw what a little creature I really was.
+I think so, because she beckoned to me to climb up, with quite a new and
+motherly expression in her face, and put her arm round my neck, and gave
+me just such a kiss as she might have given to her own boy. I had barely
+time to get down again before the coach started, and I could hardly see
+the family for the handkerchiefs they waved. It was gone in a minute.
+The Orfling and I stood looking vacantly at each other in the middle
+of the road, and then shook hands and said good-bye; she going back,
+I suppose, to St. Luke's workhouse, as I went to begin my weary day at
+Murdstone and Grinby's.
+
+But with no intention of passing many more weary days there. No. I had
+resolved to run away.---To go, by some means or other, down into the
+country, to the only relation I had in the world, and tell my story to
+my aunt, Miss Betsey. I have already observed that I don't know how this
+desperate idea came into my brain. But, once there, it remained there;
+and hardened into a purpose than which I have never entertained a more
+determined purpose in my life. I am far from sure that I believed there
+was anything hopeful in it, but my mind was thoroughly made up that it
+must be carried into execution.
+
+Again, and again, and a hundred times again, since the night when the
+thought had first occurred to me and banished sleep, I had gone over
+that old story of my poor mother's about my birth, which it had been one
+of my great delights in the old time to hear her tell, and which I knew
+by heart. My aunt walked into that story, and walked out of it, a dread
+and awful personage; but there was one little trait in her behaviour
+which I liked to dwell on, and which gave me some faint shadow of
+encouragement. I could not forget how my mother had thought that she
+felt her touch her pretty hair with no ungentle hand; and though it
+might have been altogether my mother's fancy, and might have had no
+foundation whatever in fact, I made a little picture, out of it, of my
+terrible aunt relenting towards the girlish beauty that I recollected so
+well and loved so much, which softened the whole narrative. It is very
+possible that it had been in my mind a long time, and had gradually
+engendered my determination.
+
+As I did not even know where Miss Betsey lived, I wrote a long letter
+to Peggotty, and asked her, incidentally, if she remembered; pretending
+that I had heard of such a lady living at a certain place I named at
+random, and had a curiosity to know if it were the same. In the course
+of that letter, I told Peggotty that I had a particular occasion for
+half a guinea; and that if she could lend me that sum until I could
+repay it, I should be very much obliged to her, and would tell her
+afterwards what I had wanted it for.
+
+Peggotty's answer soon arrived, and was, as usual, full of affectionate
+devotion. She enclosed the half guinea (I was afraid she must have had
+a world of trouble to get it out of Mr. Barkis's box), and told me that
+Miss Betsey lived near Dover, but whether at Dover itself, at Hythe,
+Sandgate, or Folkestone, she could not say. One of our men, however,
+informing me on my asking him about these places, that they were all
+close together, I deemed this enough for my object, and resolved to set
+out at the end of that week.
+
+Being a very honest little creature, and unwilling to disgrace the
+memory I was going to leave behind me at Murdstone and Grinby's, I
+considered myself bound to remain until Saturday night; and, as I had
+been paid a week's wages in advance when I first came there, not to
+present myself in the counting-house at the usual hour, to receive my
+stipend. For this express reason, I had borrowed the half-guinea, that
+I might not be without a fund for my travelling-expenses. Accordingly,
+when the Saturday night came, and we were all waiting in the warehouse
+to be paid, and Tipp the carman, who always took precedence, went in
+first to draw his money, I shook Mick Walker by the hand; asked him,
+when it came to his turn to be paid, to say to Mr. Quinion that I had
+gone to move my box to Tipp's; and, bidding a last good night to Mealy
+Potatoes, ran away.
+
+My box was at my old lodging, over the water, and I had written a
+direction for it on the back of one of our address cards that we nailed
+on the casks: 'Master David, to be left till called for, at the Coach
+Office, Dover.' This I had in my pocket ready to put on the box, after I
+should have got it out of the house; and as I went towards my lodging,
+I looked about me for someone who would help me to carry it to the
+booking-office.
+
+There was a long-legged young man with a very little empty donkey-cart,
+standing near the Obelisk, in the Blackfriars Road, whose eye I caught
+as I was going by, and who, addressing me as 'Sixpenn'orth of bad
+ha'pence,' hoped 'I should know him agin to swear to'--in allusion, I
+have no doubt, to my staring at him. I stopped to assure him that I had
+not done so in bad manners, but uncertain whether he might or might not
+like a job.
+
+'Wot job?' said the long-legged young man.
+
+'To move a box,' I answered.
+
+'Wot box?' said the long-legged young man.
+
+I told him mine, which was down that street there, and which I wanted
+him to take to the Dover coach office for sixpence.
+
+'Done with you for a tanner!' said the long-legged young man, and
+directly got upon his cart, which was nothing but a large wooden tray on
+wheels, and rattled away at such a rate, that it was as much as I could
+do to keep pace with the donkey.
+
+There was a defiant manner about this young man, and particularly about
+the way in which he chewed straw as he spoke to me, that I did not much
+like; as the bargain was made, however, I took him upstairs to the room
+I was leaving, and we brought the box down, and put it on his cart.
+Now, I was unwilling to put the direction-card on there, lest any of my
+landlord's family should fathom what I was doing, and detain me; so
+I said to the young man that I would be glad if he would stop for a
+minute, when he came to the dead-wall of the King's Bench prison. The
+words were no sooner out of my mouth, than he rattled away as if he, my
+box, the cart, and the donkey, were all equally mad; and I was quite out
+of breath with running and calling after him, when I caught him at the
+place appointed.
+
+Being much flushed and excited, I tumbled my half-guinea out of my
+pocket in pulling the card out. I put it in my mouth for safety, and
+though my hands trembled a good deal, had just tied the card on very
+much to my satisfaction, when I felt myself violently chucked under the
+chin by the long-legged young man, and saw my half-guinea fly out of my
+mouth into his hand.
+
+'Wot!' said the young man, seizing me by my jacket collar, with a
+frightful grin. 'This is a pollis case, is it? You're a-going to bolt,
+are you? Come to the pollis, you young warmin, come to the pollis!'
+
+'You give me my money back, if you please,' said I, very much
+frightened; 'and leave me alone.'
+
+'Come to the pollis!' said the young man. 'You shall prove it yourn to
+the pollis.'
+
+'Give me my box and money, will you,' I cried, bursting into tears.
+
+The young man still replied: 'Come to the pollis!' and was dragging me
+against the donkey in a violent manner, as if there were any affinity
+between that animal and a magistrate, when he changed his mind, jumped
+into the cart, sat upon my box, and, exclaiming that he would drive to
+the pollis straight, rattled away harder than ever.
+
+I ran after him as fast as I could, but I had no breath to call out
+with, and should not have dared to call out, now, if I had. I narrowly
+escaped being run over, twenty times at least, in half a mile. Now I
+lost him, now I saw him, now I lost him, now I was cut at with a whip,
+now shouted at, now down in the mud, now up again, now running into
+somebody's arms, now running headlong at a post. At length, confused by
+fright and heat, and doubting whether half London might not by this time
+be turning out for my apprehension, I left the young man to go where
+he would with my box and money; and, panting and crying, but never
+stopping, faced about for Greenwich, which I had understood was on
+the Dover Road: taking very little more out of the world, towards the
+retreat of my aunt, Miss Betsey, than I had brought into it, on the
+night when my arrival gave her so much umbrage.
+
+
+
+CHAPTER 13. THE SEQUEL OF MY RESOLUTION
+
+
+For anything I know, I may have had some wild idea of running all the
+way to Dover, when I gave up the pursuit of the young man with the
+donkey-cart, and started for Greenwich. My scattered senses were soon
+collected as to that point, if I had; for I came to a stop in the Kent
+Road, at a terrace with a piece of water before it, and a great foolish
+image in the middle, blowing a dry shell. Here I sat down on a doorstep,
+quite spent and exhausted with the efforts I had already made, and with
+hardly breath enough to cry for the loss of my box and half-guinea.
+
+It was by this time dark; I heard the clocks strike ten, as I sat
+resting. But it was a summer night, fortunately, and fine weather. When
+I had recovered my breath, and had got rid of a stifling sensation in
+my throat, I rose up and went on. In the midst of my distress, I had no
+notion of going back. I doubt if I should have had any, though there had
+been a Swiss snow-drift in the Kent Road.
+
+But my standing possessed of only three-halfpence in the world (and I
+am sure I wonder how they came to be left in my pocket on a Saturday
+night!) troubled me none the less because I went on. I began to picture
+to myself, as a scrap of newspaper intelligence, my being found dead in
+a day or two, under some hedge; and I trudged on miserably, though as
+fast as I could, until I happened to pass a little shop, where it was
+written up that ladies' and gentlemen's wardrobes were bought, and that
+the best price was given for rags, bones, and kitchen-stuff. The master
+of this shop was sitting at the door in his shirt-sleeves, smoking; and
+as there were a great many coats and pairs of trousers dangling from
+the low ceiling, and only two feeble candles burning inside to show
+what they were, I fancied that he looked like a man of a revengeful
+disposition, who had hung all his enemies, and was enjoying himself.
+
+My late experiences with Mr. and Mrs. Micawber suggested to me that here
+might be a means of keeping off the wolf for a little while. I went up
+the next by-street, took off my waistcoat, rolled it neatly under my
+arm, and came back to the shop door.
+
+'If you please, sir,' I said, 'I am to sell this for a fair price.'
+
+Mr. Dolloby--Dolloby was the name over the shop door, at least--took the
+waistcoat, stood his pipe on its head, against the door-post, went into
+the shop, followed by me, snuffed the two candles with his fingers,
+spread the waistcoat on the counter, and looked at it there, held it up
+against the light, and looked at it there, and ultimately said:
+
+'What do you call a price, now, for this here little weskit?'
+
+'Oh! you know best, sir,' I returned modestly.
+
+'I can't be buyer and seller too,' said Mr. Dolloby. 'Put a price on
+this here little weskit.'
+
+'Would eighteenpence be?'--I hinted, after some hesitation.
+
+Mr. Dolloby rolled it up again, and gave it me back. 'I should rob my
+family,' he said, 'if I was to offer ninepence for it.'
+
+This was a disagreeable way of putting the business; because it imposed
+upon me, a perfect stranger, the unpleasantness of asking Mr. Dolloby to
+rob his family on my account. My circumstances being so very pressing,
+however, I said I would take ninepence for it, if he pleased. Mr.
+Dolloby, not without some grumbling, gave ninepence. I wished him good
+night, and walked out of the shop the richer by that sum, and the
+poorer by a waistcoat. But when I buttoned my jacket, that was not much.
+Indeed, I foresaw pretty clearly that my jacket would go next, and that
+I should have to make the best of my way to Dover in a shirt and a pair
+of trousers, and might deem myself lucky if I got there even in that
+trim. But my mind did not run so much on this as might be supposed.
+Beyond a general impression of the distance before me, and of the young
+man with the donkey-cart having used me cruelly, I think I had no
+very urgent sense of my difficulties when I once again set off with my
+ninepence in my pocket.
+
+A plan had occurred to me for passing the night, which I was going to
+carry into execution. This was, to lie behind the wall at the back of my
+old school, in a corner where there used to be a haystack. I imagined
+it would be a kind of company to have the boys, and the bedroom where
+I used to tell the stories, so near me: although the boys would know
+nothing of my being there, and the bedroom would yield me no shelter.
+
+I had had a hard day's work, and was pretty well jaded when I came
+climbing out, at last, upon the level of Blackheath. It cost me some
+trouble to find out Salem House; but I found it, and I found a haystack
+in the corner, and I lay down by it; having first walked round the wall,
+and looked up at the windows, and seen that all was dark and silent
+within. Never shall I forget the lonely sensation of first lying down,
+without a roof above my head!
+
+Sleep came upon me as it came on many other outcasts, against whom
+house-doors were locked, and house-dogs barked, that night--and I
+dreamed of lying on my old school-bed, talking to the boys in my room;
+and found myself sitting upright, with Steerforth's name upon my lips,
+looking wildly at the stars that were glistening and glimmering above
+me. When I remembered where I was at that untimely hour, a feeling
+stole upon me that made me get up, afraid of I don't know what, and walk
+about. But the fainter glimmering of the stars, and the pale light in
+the sky where the day was coming, reassured me: and my eyes being very
+heavy, I lay down again and slept--though with a knowledge in my sleep
+that it was cold--until the warm beams of the sun, and the ringing of
+the getting-up bell at Salem House, awoke me. If I could have hoped that
+Steerforth was there, I would have lurked about until he came out
+alone; but I knew he must have left long since. Traddles still remained,
+perhaps, but it was very doubtful; and I had not sufficient confidence
+in his discretion or good luck, however strong my reliance was on his
+good nature, to wish to trust him with my situation. So I crept away
+from the wall as Mr. Creakle's boys were getting up, and struck into the
+long dusty track which I had first known to be the Dover Road when I was
+one of them, and when I little expected that any eyes would ever see me
+the wayfarer I was now, upon it.
+
+What a different Sunday morning from the old Sunday morning at Yarmouth!
+In due time I heard the church-bells ringing, as I plodded on; and I met
+people who were going to church; and I passed a church or two where the
+congregation were inside, and the sound of singing came out into the
+sunshine, while the beadle sat and cooled himself in the shade of the
+porch, or stood beneath the yew-tree, with his hand to his forehead,
+glowering at me going by. But the peace and rest of the old Sunday
+morning were on everything, except me. That was the difference. I felt
+quite wicked in my dirt and dust, with my tangled hair. But for the
+quiet picture I had conjured up, of my mother in her youth and beauty,
+weeping by the fire, and my aunt relenting to her, I hardly think I
+should have had the courage to go on until next day. But it always went
+before me, and I followed.
+
+I got, that Sunday, through three-and-twenty miles on the straight
+road, though not very easily, for I was new to that kind of toil. I
+see myself, as evening closes in, coming over the bridge at Rochester,
+footsore and tired, and eating bread that I had bought for supper.
+One or two little houses, with the notice, 'Lodgings for Travellers',
+hanging out, had tempted me; but I was afraid of spending the few pence
+I had, and was even more afraid of the vicious looks of the trampers I
+had met or overtaken. I sought no shelter, therefore, but the sky; and
+toiling into Chatham,--which, in that night's aspect, is a mere dream of
+chalk, and drawbridges, and mastless ships in a muddy river, roofed
+like Noah's arks,--crept, at last, upon a sort of grass-grown battery
+overhanging a lane, where a sentry was walking to and fro. Here I
+lay down, near a cannon; and, happy in the society of the sentry's
+footsteps, though he knew no more of my being above him than the boys
+at Salem House had known of my lying by the wall, slept soundly until
+morning.
+
+Very stiff and sore of foot I was in the morning, and quite dazed by the
+beating of drums and marching of troops, which seemed to hem me in on
+every side when I went down towards the long narrow street. Feeling
+that I could go but a very little way that day, if I were to reserve any
+strength for getting to my journey's end, I resolved to make the sale
+of my jacket its principal business. Accordingly, I took the jacket off,
+that I might learn to do without it; and carrying it under my arm, began
+a tour of inspection of the various slop-shops.
+
+It was a likely place to sell a jacket in; for the dealers in
+second-hand clothes were numerous, and were, generally speaking, on the
+look-out for customers at their shop doors. But as most of them had,
+hanging up among their stock, an officer's coat or two, epaulettes and
+all, I was rendered timid by the costly nature of their dealings, and
+walked about for a long time without offering my merchandise to anyone.
+
+This modesty of mine directed my attention to the marine-store shops,
+and such shops as Mr. Dolloby's, in preference to the regular dealers.
+At last I found one that I thought looked promising, at the corner of a
+dirty lane, ending in an enclosure full of stinging-nettles, against the
+palings of which some second-hand sailors' clothes, that seemed to have
+overflowed the shop, were fluttering among some cots, and rusty guns,
+and oilskin hats, and certain trays full of so many old rusty keys of so
+many sizes that they seemed various enough to open all the doors in the
+world.
+
+Into this shop, which was low and small, and which was darkened
+rather than lighted by a little window, overhung with clothes, and was
+descended into by some steps, I went with a palpitating heart; which was
+not relieved when an ugly old man, with the lower part of his face all
+covered with a stubbly grey beard, rushed out of a dirty den behind it,
+and seized me by the hair of my head. He was a dreadful old man to look
+at, in a filthy flannel waistcoat, and smelling terribly of rum. His
+bedstead, covered with a tumbled and ragged piece of patchwork, was in
+the den he had come from, where another little window showed a prospect
+of more stinging-nettles, and a lame donkey.
+
+'Oh, what do you want?' grinned this old man, in a fierce, monotonous
+whine. 'Oh, my eyes and limbs, what do you want? Oh, my lungs and liver,
+what do you want? Oh, goroo, goroo!'
+
+I was so much dismayed by these words, and particularly by the
+repetition of the last unknown one, which was a kind of rattle in his
+throat, that I could make no answer; hereupon the old man, still holding
+me by the hair, repeated:
+
+'Oh, what do you want? Oh, my eyes and limbs, what do you want? Oh, my
+lungs and liver, what do you want? Oh, goroo!'--which he screwed out of
+himself, with an energy that made his eyes start in his head.
+
+'I wanted to know,' I said, trembling, 'if you would buy a jacket.'
+
+'Oh, let's see the jacket!' cried the old man. 'Oh, my heart on fire,
+show the jacket to us! Oh, my eyes and limbs, bring the jacket out!'
+
+With that he took his trembling hands, which were like the claws of a
+great bird, out of my hair; and put on a pair of spectacles, not at all
+ornamental to his inflamed eyes.
+
+'Oh, how much for the jacket?' cried the old man, after examining it.
+'Oh--goroo!--how much for the jacket?'
+
+'Half-a-crown,' I answered, recovering myself.
+
+'Oh, my lungs and liver,' cried the old man, 'no! Oh, my eyes, no! Oh,
+my limbs, no! Eighteenpence. Goroo!'
+
+Every time he uttered this ejaculation, his eyes seemed to be in danger
+of starting out; and every sentence he spoke, he delivered in a sort
+of tune, always exactly the same, and more like a gust of wind, which
+begins low, mounts up high, and falls again, than any other comparison I
+can find for it.
+
+'Well,' said I, glad to have closed the bargain, 'I'll take
+eighteenpence.'
+
+'Oh, my liver!' cried the old man, throwing the jacket on a shelf. 'Get
+out of the shop! Oh, my lungs, get out of the shop! Oh, my eyes and
+limbs--goroo!--don't ask for money; make it an exchange.' I never was
+so frightened in my life, before or since; but I told him humbly that
+I wanted money, and that nothing else was of any use to me, but that I
+would wait for it, as he desired, outside, and had no wish to hurry
+him. So I went outside, and sat down in the shade in a corner. And I sat
+there so many hours, that the shade became sunlight, and the sunlight
+became shade again, and still I sat there waiting for the money.
+
+There never was such another drunken madman in that line of business,
+I hope. That he was well known in the neighbourhood, and enjoyed the
+reputation of having sold himself to the devil, I soon understood from
+the visits he received from the boys, who continually came skirmishing
+about the shop, shouting that legend, and calling to him to bring out
+his gold. 'You ain't poor, you know, Charley, as you pretend. Bring out
+your gold. Bring out some of the gold you sold yourself to the devil
+for. Come! It's in the lining of the mattress, Charley. Rip it open
+and let's have some!' This, and many offers to lend him a knife for
+the purpose, exasperated him to such a degree, that the whole day was a
+succession of rushes on his part, and flights on the part of the boys.
+Sometimes in his rage he would take me for one of them, and come at me,
+mouthing as if he were going to tear me in pieces; then, remembering
+me, just in time, would dive into the shop, and lie upon his bed, as I
+thought from the sound of his voice, yelling in a frantic way, to his
+own windy tune, the 'Death of Nelson'; with an Oh! before every line,
+and innumerable Goroos interspersed. As if this were not bad enough for
+me, the boys, connecting me with the establishment, on account of the
+patience and perseverance with which I sat outside, half-dressed, pelted
+me, and used me very ill all day.
+
+He made many attempts to induce me to consent to an exchange; at one
+time coming out with a fishing-rod, at another with a fiddle, at another
+with a cocked hat, at another with a flute. But I resisted all these
+overtures, and sat there in desperation; each time asking him, with
+tears in my eyes, for my money or my jacket. At last he began to pay me
+in halfpence at a time; and was full two hours getting by easy stages to
+a shilling.
+
+'Oh, my eyes and limbs!' he then cried, peeping hideously out of the
+shop, after a long pause, 'will you go for twopence more?'
+
+'I can't,' I said; 'I shall be starved.'
+
+'Oh, my lungs and liver, will you go for threepence?'
+
+'I would go for nothing, if I could,' I said, 'but I want the money
+badly.'
+
+'Oh, go-roo!' (it is really impossible to express how he twisted this
+ejaculation out of himself, as he peeped round the door-post at me,
+showing nothing but his crafty old head); 'will you go for fourpence?'
+
+I was so faint and weary that I closed with this offer; and taking the
+money out of his claw, not without trembling, went away more hungry and
+thirsty than I had ever been, a little before sunset. But at an expense
+of threepence I soon refreshed myself completely; and, being in better
+spirits then, limped seven miles upon my road.
+
+My bed at night was under another haystack, where I rested comfortably,
+after having washed my blistered feet in a stream, and dressed them as
+well as I was able, with some cool leaves. When I took the road again
+next morning, I found that it lay through a succession of hop-grounds
+and orchards. It was sufficiently late in the year for the orchards
+to be ruddy with ripe apples; and in a few places the hop-pickers were
+already at work. I thought it all extremely beautiful, and made up
+my mind to sleep among the hops that night: imagining some cheerful
+companionship in the long perspectives of poles, with the graceful
+leaves twining round them.
+
+The trampers were worse than ever that day, and inspired me with a
+dread that is yet quite fresh in my mind. Some of them were most
+ferocious-looking ruffians, who stared at me as I went by; and stopped,
+perhaps, and called after me to come back and speak to them, and when I
+took to my heels, stoned me. I recollect one young fellow--a tinker, I
+suppose, from his wallet and brazier--who had a woman with him, and
+who faced about and stared at me thus; and then roared to me in such a
+tremendous voice to come back, that I halted and looked round.
+
+'Come here, when you're called,' said the tinker, 'or I'll rip your
+young body open.'
+
+I thought it best to go back. As I drew nearer to them, trying to
+propitiate the tinker by my looks, I observed that the woman had a black
+eye.
+
+'Where are you going?' said the tinker, gripping the bosom of my shirt
+with his blackened hand.
+
+'I am going to Dover,' I said.
+
+'Where do you come from?' asked the tinker, giving his hand another turn
+in my shirt, to hold me more securely.
+
+'I come from London,' I said.
+
+'What lay are you upon?' asked the tinker. 'Are you a prig?'
+
+'N-no,' I said.
+
+'Ain't you, by G--? If you make a brag of your honesty to me,' said the
+tinker, 'I'll knock your brains out.'
+
+With his disengaged hand he made a menace of striking me, and then
+looked at me from head to foot.
+
+'Have you got the price of a pint of beer about you?' said the tinker.
+'If you have, out with it, afore I take it away!'
+
+I should certainly have produced it, but that I met the woman's look,
+and saw her very slightly shake her head, and form 'No!' with her lips.
+
+'I am very poor,' I said, attempting to smile, 'and have got no money.'
+
+'Why, what do you mean?' said the tinker, looking so sternly at me, that
+I almost feared he saw the money in my pocket.
+
+'Sir!' I stammered.
+
+'What do you mean,' said the tinker, 'by wearing my brother's silk
+handkerchief! Give it over here!' And he had mine off my neck in a
+moment, and tossed it to the woman.
+
+The woman burst into a fit of laughter, as if she thought this a joke,
+and tossed it back to me, nodded once, as slightly as before, and made
+the word 'Go!' with her lips. Before I could obey, however, the tinker
+seized the handkerchief out of my hand with a roughness that threw me
+away like a feather, and putting it loosely round his own neck, turned
+upon the woman with an oath, and knocked her down. I never shall forget
+seeing her fall backward on the hard road, and lie there with her bonnet
+tumbled off, and her hair all whitened in the dust; nor, when I looked
+back from a distance, seeing her sitting on the pathway, which was a
+bank by the roadside, wiping the blood from her face with a corner of
+her shawl, while he went on ahead.
+
+This adventure frightened me so, that, afterwards, when I saw any of
+these people coming, I turned back until I could find a hiding-place,
+where I remained until they had gone out of sight; which happened so
+often, that I was very seriously delayed. But under this difficulty, as
+under all the other difficulties of my journey, I seemed to be sustained
+and led on by my fanciful picture of my mother in her youth, before I
+came into the world. It always kept me company. It was there, among
+the hops, when I lay down to sleep; it was with me on my waking in the
+morning; it went before me all day. I have associated it, ever since,
+with the sunny street of Canterbury, dozing as it were in the hot light;
+and with the sight of its old houses and gateways, and the stately,
+grey Cathedral, with the rooks sailing round the towers. When I came,
+at last, upon the bare, wide downs near Dover, it relieved the solitary
+aspect of the scene with hope; and not until I reached that first great
+aim of my journey, and actually set foot in the town itself, on the
+sixth day of my flight, did it desert me. But then, strange to say,
+when I stood with my ragged shoes, and my dusty, sunburnt, half-clothed
+figure, in the place so long desired, it seemed to vanish like a dream,
+and to leave me helpless and dispirited.
+
+I inquired about my aunt among the boatmen first, and received various
+answers. One said she lived in the South Foreland Light, and had singed
+her whiskers by doing so; another, that she was made fast to the great
+buoy outside the harbour, and could only be visited at half-tide; a
+third, that she was locked up in Maidstone jail for child-stealing; a
+fourth, that she was seen to mount a broom in the last high wind, and
+make direct for Calais. The fly-drivers, among whom I inquired next,
+were equally jocose and equally disrespectful; and the shopkeepers, not
+liking my appearance, generally replied, without hearing what I had
+to say, that they had got nothing for me. I felt more miserable and
+destitute than I had done at any period of my running away. My money was
+all gone, I had nothing left to dispose of; I was hungry, thirsty, and
+worn out; and seemed as distant from my end as if I had remained in
+London.
+
+The morning had worn away in these inquiries, and I was sitting on
+the step of an empty shop at a street corner, near the market-place,
+deliberating upon wandering towards those other places which had been
+mentioned, when a fly-driver, coming by with his carriage, dropped a
+horsecloth. Something good-natured in the man's face, as I handed it up,
+encouraged me to ask him if he could tell me where Miss Trotwood lived;
+though I had asked the question so often, that it almost died upon my
+lips.
+
+'Trotwood,' said he. 'Let me see. I know the name, too. Old lady?'
+
+'Yes,' I said, 'rather.'
+
+'Pretty stiff in the back?' said he, making himself upright.
+
+'Yes,' I said. 'I should think it very likely.'
+
+'Carries a bag?' said he--'bag with a good deal of room in it--is
+gruffish, and comes down upon you, sharp?'
+
+My heart sank within me as I acknowledged the undoubted accuracy of this
+description.
+
+'Why then, I tell you what,' said he. 'If you go up there,' pointing
+with his whip towards the heights, 'and keep right on till you come to
+some houses facing the sea, I think you'll hear of her. My opinion is
+she won't stand anything, so here's a penny for you.'
+
+I accepted the gift thankfully, and bought a loaf with it. Dispatching
+this refreshment by the way, I went in the direction my friend had
+indicated, and walked on a good distance without coming to the houses
+he had mentioned. At length I saw some before me; and approaching them,
+went into a little shop (it was what we used to call a general shop,
+at home), and inquired if they could have the goodness to tell me where
+Miss Trotwood lived. I addressed myself to a man behind the counter,
+who was weighing some rice for a young woman; but the latter, taking the
+inquiry to herself, turned round quickly.
+
+'My mistress?' she said. 'What do you want with her, boy?'
+
+'I want,' I replied, 'to speak to her, if you please.'
+
+'To beg of her, you mean,' retorted the damsel.
+
+'No,' I said, 'indeed.' But suddenly remembering that in truth I came
+for no other purpose, I held my peace in confusion, and felt my face
+burn.
+
+MY aunt's handmaid, as I supposed she was from what she had said, put
+her rice in a little basket and walked out of the shop; telling me that
+I could follow her, if I wanted to know where Miss Trotwood lived. I
+needed no second permission; though I was by this time in such a state
+of consternation and agitation, that my legs shook under me. I followed
+the young woman, and we soon came to a very neat little cottage with
+cheerful bow-windows: in front of it, a small square gravelled court or
+garden full of flowers, carefully tended, and smelling deliciously.
+
+'This is Miss Trotwood's,' said the young woman. 'Now you know; and
+that's all I have got to say.' With which words she hurried into the
+house, as if to shake off the responsibility of my appearance; and left
+me standing at the garden-gate, looking disconsolately over the top of
+it towards the parlour window, where a muslin curtain partly undrawn
+in the middle, a large round green screen or fan fastened on to the
+windowsill, a small table, and a great chair, suggested to me that my
+aunt might be at that moment seated in awful state.
+
+My shoes were by this time in a woeful condition. The soles had shed
+themselves bit by bit, and the upper leathers had broken and burst until
+the very shape and form of shoes had departed from them. My hat (which
+had served me for a night-cap, too) was so crushed and bent, that no old
+battered handleless saucepan on a dunghill need have been ashamed to vie
+with it. My shirt and trousers, stained with heat, dew, grass, and
+the Kentish soil on which I had slept--and torn besides--might have
+frightened the birds from my aunt's garden, as I stood at the gate. My
+hair had known no comb or brush since I left London. My face, neck, and
+hands, from unaccustomed exposure to the air and sun, were burnt to a
+berry-brown. From head to foot I was powdered almost as white with chalk
+and dust, as if I had come out of a lime-kiln. In this plight, and with
+a strong consciousness of it, I waited to introduce myself to, and make
+my first impression on, my formidable aunt.
+
+The unbroken stillness of the parlour window leading me to infer, after
+a while, that she was not there, I lifted up my eyes to the window above
+it, where I saw a florid, pleasant-looking gentleman, with a grey head,
+who shut up one eye in a grotesque manner, nodded his head at me several
+times, shook it at me as often, laughed, and went away.
+
+I had been discomposed enough before; but I was so much the more
+discomposed by this unexpected behaviour, that I was on the point of
+slinking off, to think how I had best proceed, when there came out of
+the house a lady with her handkerchief tied over her cap, and a pair
+of gardening gloves on her hands, wearing a gardening pocket like a
+toll-man's apron, and carrying a great knife. I knew her immediately
+to be Miss Betsey, for she came stalking out of the house exactly as
+my poor mother had so often described her stalking up our garden at
+Blunderstone Rookery.
+
+'Go away!' said Miss Betsey, shaking her head, and making a distant chop
+in the air with her knife. 'Go along! No boys here!'
+
+I watched her, with my heart at my lips, as she marched to a corner of
+her garden, and stooped to dig up some little root there. Then, without
+a scrap of courage, but with a great deal of desperation, I went softly
+in and stood beside her, touching her with my finger.
+
+'If you please, ma'am,' I began.
+
+She started and looked up.
+
+'If you please, aunt.'
+
+'EH?' exclaimed Miss Betsey, in a tone of amazement I have never heard
+approached.
+
+'If you please, aunt, I am your nephew.'
+
+'Oh, Lord!' said my aunt. And sat flat down in the garden-path.
+
+'I am David Copperfield, of Blunderstone, in Suffolk--where you came,
+on the night when I was born, and saw my dear mama. I have been very
+unhappy since she died. I have been slighted, and taught nothing, and
+thrown upon myself, and put to work not fit for me. It made me run away
+to you. I was robbed at first setting out, and have walked all the
+way, and have never slept in a bed since I began the journey.' Here
+my self-support gave way all at once; and with a movement of my hands,
+intended to show her my ragged state, and call it to witness that I had
+suffered something, I broke into a passion of crying, which I suppose
+had been pent up within me all the week.
+
+My aunt, with every sort of expression but wonder discharged from her
+countenance, sat on the gravel, staring at me, until I began to cry;
+when she got up in a great hurry, collared me, and took me into the
+parlour. Her first proceeding there was to unlock a tall press, bring
+out several bottles, and pour some of the contents of each into my
+mouth. I think they must have been taken out at random, for I am sure
+I tasted aniseed water, anchovy sauce, and salad dressing. When she had
+administered these restoratives, as I was still quite hysterical, and
+unable to control my sobs, she put me on the sofa, with a shawl under
+my head, and the handkerchief from her own head under my feet, lest I
+should sully the cover; and then, sitting herself down behind the green
+fan or screen I have already mentioned, so that I could not see her
+face, ejaculated at intervals, 'Mercy on us!' letting those exclamations
+off like minute guns.
+
+After a time she rang the bell. 'Janet,' said my aunt, when her servant
+came in. 'Go upstairs, give my compliments to Mr. Dick, and say I wish
+to speak to him.'
+
+Janet looked a little surprised to see me lying stiffly on the sofa (I
+was afraid to move lest it should be displeasing to my aunt), but went
+on her errand. My aunt, with her hands behind her, walked up and down
+the room, until the gentleman who had squinted at me from the upper
+window came in laughing.
+
+'Mr. Dick,' said my aunt, 'don't be a fool, because nobody can be more
+discreet than you can, when you choose. We all know that. So don't be a
+fool, whatever you are.'
+
+The gentleman was serious immediately, and looked at me, I thought, as
+if he would entreat me to say nothing about the window.
+
+'Mr. Dick,' said my aunt, 'you have heard me mention David Copperfield?
+Now don't pretend not to have a memory, because you and I know better.'
+
+'David Copperfield?' said Mr. Dick, who did not appear to me to
+remember much about it. 'David Copperfield? Oh yes, to be sure. David,
+certainly.'
+
+'Well,' said my aunt, 'this is his boy--his son. He would be as like his
+father as it's possible to be, if he was not so like his mother, too.'
+
+'His son?' said Mr. Dick. 'David's son? Indeed!'
+
+'Yes,' pursued my aunt, 'and he has done a pretty piece of business.
+He has run away. Ah! His sister, Betsey Trotwood, never would have run
+away.' My aunt shook her head firmly, confident in the character and
+behaviour of the girl who never was born.
+
+'Oh! you think she wouldn't have run away?' said Mr. Dick.
+
+'Bless and save the man,' exclaimed my aunt, sharply, 'how he talks!
+Don't I know she wouldn't? She would have lived with her god-mother,
+and we should have been devoted to one another. Where, in the name of
+wonder, should his sister, Betsey Trotwood, have run from, or to?'
+
+'Nowhere,' said Mr. Dick.
+
+'Well then,' returned my aunt, softened by the reply, 'how can you
+pretend to be wool-gathering, Dick, when you are as sharp as a surgeon's
+lancet? Now, here you see young David Copperfield, and the question I
+put to you is, what shall I do with him?'
+
+'What shall you do with him?' said Mr. Dick, feebly, scratching his
+head. 'Oh! do with him?'
+
+'Yes,' said my aunt, with a grave look, and her forefinger held up.
+'Come! I want some very sound advice.'
+
+'Why, if I was you,' said Mr. Dick, considering, and looking vacantly
+at me, 'I should--' The contemplation of me seemed to inspire him with a
+sudden idea, and he added, briskly, 'I should wash him!'
+
+'Janet,' said my aunt, turning round with a quiet triumph, which I did
+not then understand, 'Mr. Dick sets us all right. Heat the bath!'
+
+Although I was deeply interested in this dialogue, I could not help
+observing my aunt, Mr. Dick, and Janet, while it was in progress, and
+completing a survey I had already been engaged in making of the room.
+
+MY aunt was a tall, hard-featured lady, but by no means ill-looking.
+There was an inflexibility in her face, in her voice, in her gait and
+carriage, amply sufficient to account for the effect she had made upon
+a gentle creature like my mother; but her features were rather handsome
+than otherwise, though unbending and austere. I particularly noticed
+that she had a very quick, bright eye. Her hair, which was grey, was
+arranged in two plain divisions, under what I believe would be called a
+mob-cap; I mean a cap, much more common then than now, with side-pieces
+fastening under the chin. Her dress was of a lavender colour, and
+perfectly neat; but scantily made, as if she desired to be as little
+encumbered as possible. I remember that I thought it, in form, more like
+a riding-habit with the superfluous skirt cut off, than anything else.
+She wore at her side a gentleman's gold watch, if I might judge from its
+size and make, with an appropriate chain and seals; she had some linen
+at her throat not unlike a shirt-collar, and things at her wrists like
+little shirt-wristbands.
+
+Mr. Dick, as I have already said, was grey-headed, and florid: I should
+have said all about him, in saying so, had not his head been curiously
+bowed--not by age; it reminded me of one of Mr. Creakle's boys' heads
+after a beating--and his grey eyes prominent and large, with a strange
+kind of watery brightness in them that made me, in combination with his
+vacant manner, his submission to my aunt, and his childish delight when
+she praised him, suspect him of being a little mad; though, if he were
+mad, how he came to be there puzzled me extremely. He was dressed
+like any other ordinary gentleman, in a loose grey morning coat and
+waistcoat, and white trousers; and had his watch in his fob, and his
+money in his pockets: which he rattled as if he were very proud of it.
+
+Janet was a pretty blooming girl, of about nineteen or twenty, and a
+perfect picture of neatness. Though I made no further observation of
+her at the moment, I may mention here what I did not discover until
+afterwards, namely, that she was one of a series of protegees whom my
+aunt had taken into her service expressly to educate in a renouncement
+of mankind, and who had generally completed their abjuration by marrying
+the baker.
+
+The room was as neat as Janet or my aunt. As I laid down my pen, a
+moment since, to think of it, the air from the sea came blowing
+in again, mixed with the perfume of the flowers; and I saw the
+old-fashioned furniture brightly rubbed and polished, my aunt's
+inviolable chair and table by the round green fan in the bow-window, the
+drugget-covered carpet, the cat, the kettle-holder, the two canaries,
+the old china, the punchbowl full of dried rose-leaves, the tall press
+guarding all sorts of bottles and pots, and, wonderfully out of keeping
+with the rest, my dusty self upon the sofa, taking note of everything.
+
+Janet had gone away to get the bath ready, when my aunt, to my great
+alarm, became in one moment rigid with indignation, and had hardly voice
+to cry out, 'Janet! Donkeys!'
+
+Upon which, Janet came running up the stairs as if the house were in
+flames, darted out on a little piece of green in front, and warned off
+two saddle-donkeys, lady-ridden, that had presumed to set hoof upon it;
+while my aunt, rushing out of the house, seized the bridle of a third
+animal laden with a bestriding child, turned him, led him forth from
+those sacred precincts, and boxed the ears of the unlucky urchin in
+attendance who had dared to profane that hallowed ground.
+
+To this hour I don't know whether my aunt had any lawful right of way
+over that patch of green; but she had settled it in her own mind that
+she had, and it was all the same to her. The one great outrage of her
+life, demanding to be constantly avenged, was the passage of a donkey
+over that immaculate spot. In whatever occupation she was engaged,
+however interesting to her the conversation in which she was taking
+part, a donkey turned the current of her ideas in a moment, and she was
+upon him straight. Jugs of water, and watering-pots, were kept in secret
+places ready to be discharged on the offending boys; sticks were laid
+in ambush behind the door; sallies were made at all hours; and
+incessant war prevailed. Perhaps this was an agreeable excitement to the
+donkey-boys; or perhaps the more sagacious of the donkeys, understanding
+how the case stood, delighted with constitutional obstinacy in coming
+that way. I only know that there were three alarms before the bath was
+ready; and that on the occasion of the last and most desperate of all,
+I saw my aunt engage, single-handed, with a sandy-headed lad of fifteen,
+and bump his sandy head against her own gate, before he seemed to
+comprehend what was the matter. These interruptions were of the more
+ridiculous to me, because she was giving me broth out of a table-spoon
+at the time (having firmly persuaded herself that I was actually
+starving, and must receive nourishment at first in very small
+quantities), and, while my mouth was yet open to receive the spoon, she
+would put it back into the basin, cry 'Janet! Donkeys!' and go out to
+the assault.
+
+The bath was a great comfort. For I began to be sensible of acute pains
+in my limbs from lying out in the fields, and was now so tired and low
+that I could hardly keep myself awake for five minutes together. When I
+had bathed, they (I mean my aunt and Janet) enrobed me in a shirt and a
+pair of trousers belonging to Mr. Dick, and tied me up in two or three
+great shawls. What sort of bundle I looked like, I don't know, but I
+felt a very hot one. Feeling also very faint and drowsy, I soon lay down
+on the sofa again and fell asleep.
+
+It might have been a dream, originating in the fancy which had occupied
+my mind so long, but I awoke with the impression that my aunt had come
+and bent over me, and had put my hair away from my face, and laid my
+head more comfortably, and had then stood looking at me. The words,
+'Pretty fellow,' or 'Poor fellow,' seemed to be in my ears, too; but
+certainly there was nothing else, when I awoke, to lead me to believe
+that they had been uttered by my aunt, who sat in the bow-window gazing
+at the sea from behind the green fan, which was mounted on a kind of
+swivel, and turned any way.
+
+We dined soon after I awoke, off a roast fowl and a pudding; I sitting
+at table, not unlike a trussed bird myself, and moving my arms with
+considerable difficulty. But as my aunt had swathed me up, I made no
+complaint of being inconvenienced. All this time I was deeply anxious
+to know what she was going to do with me; but she took her dinner in
+profound silence, except when she occasionally fixed her eyes on me
+sitting opposite, and said, 'Mercy upon us!' which did not by any means
+relieve my anxiety.
+
+The cloth being drawn, and some sherry put upon the table (of which I
+had a glass), my aunt sent up for Mr. Dick again, who joined us, and
+looked as wise as he could when she requested him to attend to my story,
+which she elicited from me, gradually, by a course of questions. During
+my recital, she kept her eyes on Mr. Dick, who I thought would have gone
+to sleep but for that, and who, whensoever he lapsed into a smile, was
+checked by a frown from my aunt.
+
+'Whatever possessed that poor unfortunate Baby, that she must go and be
+married again,' said my aunt, when I had finished, 'I can't conceive.'
+
+'Perhaps she fell in love with her second husband,' Mr. Dick suggested.
+
+'Fell in love!' repeated my aunt. 'What do you mean? What business had
+she to do it?'
+
+'Perhaps,' Mr. Dick simpered, after thinking a little, 'she did it for
+pleasure.'
+
+'Pleasure, indeed!' replied my aunt. 'A mighty pleasure for the poor
+Baby to fix her simple faith upon any dog of a fellow, certain to
+ill-use her in some way or other. What did she propose to herself,
+I should like to know! She had had one husband. She had seen David
+Copperfield out of the world, who was always running after wax dolls
+from his cradle. She had got a baby--oh, there were a pair of babies
+when she gave birth to this child sitting here, that Friday night!--and
+what more did she want?'
+
+Mr. Dick secretly shook his head at me, as if he thought there was no
+getting over this.
+
+'She couldn't even have a baby like anybody else,' said my aunt. 'Where
+was this child's sister, Betsey Trotwood? Not forthcoming. Don't tell
+me!'
+
+Mr. Dick seemed quite frightened.
+
+'That little man of a doctor, with his head on one side,' said my aunt,
+'Jellips, or whatever his name was, what was he about? All he could do,
+was to say to me, like a robin redbreast--as he is--"It's a boy." A boy!
+Yah, the imbecility of the whole set of 'em!'
+
+The heartiness of the ejaculation startled Mr. Dick exceedingly; and me,
+too, if I am to tell the truth.
+
+'And then, as if this was not enough, and she had not stood sufficiently
+in the light of this child's sister, Betsey Trotwood,' said my aunt,
+'she marries a second time--goes and marries a Murderer--or a man with
+a name like it--and stands in THIS child's light! And the natural
+consequence is, as anybody but a baby might have foreseen, that he
+prowls and wanders. He's as like Cain before he was grown up, as he can
+be.'
+
+Mr. Dick looked hard at me, as if to identify me in this character.
+
+'And then there's that woman with the Pagan name,' said my aunt, 'that
+Peggotty, she goes and gets married next. Because she has not seen
+enough of the evil attending such things, she goes and gets married
+next, as the child relates. I only hope,' said my aunt, shaking her
+head, 'that her husband is one of those Poker husbands who abound in the
+newspapers, and will beat her well with one.'
+
+I could not bear to hear my old nurse so decried, and made the subject
+of such a wish. I told my aunt that indeed she was mistaken. That
+Peggotty was the best, the truest, the most faithful, most devoted, and
+most self-denying friend and servant in the world; who had ever loved
+me dearly, who had ever loved my mother dearly; who had held my mother's
+dying head upon her arm, on whose face my mother had imprinted her last
+grateful kiss. And my remembrance of them both, choking me, I broke down
+as I was trying to say that her home was my home, and that all she had
+was mine, and that I would have gone to her for shelter, but for her
+humble station, which made me fear that I might bring some trouble on
+her--I broke down, I say, as I was trying to say so, and laid my face in
+my hands upon the table.
+
+'Well, well!' said my aunt, 'the child is right to stand by those who
+have stood by him--Janet! Donkeys!'
+
+I thoroughly believe that but for those unfortunate donkeys, we should
+have come to a good understanding; for my aunt had laid her hand on my
+shoulder, and the impulse was upon me, thus emboldened, to embrace her
+and beseech her protection. But the interruption, and the disorder she
+was thrown into by the struggle outside, put an end to all softer ideas
+for the present, and kept my aunt indignantly declaiming to Mr. Dick
+about her determination to appeal for redress to the laws of her
+country, and to bring actions for trespass against the whole donkey
+proprietorship of Dover, until tea-time.
+
+After tea, we sat at the window--on the look-out, as I imagined, from
+my aunt's sharp expression of face, for more invaders--until dusk, when
+Janet set candles, and a backgammon-board, on the table, and pulled down
+the blinds.
+
+'Now, Mr. Dick,' said my aunt, with her grave look, and her forefinger
+up as before, 'I am going to ask you another question. Look at this
+child.'
+
+'David's son?' said Mr. Dick, with an attentive, puzzled face.
+
+'Exactly so,' returned my aunt. 'What would you do with him, now?'
+
+'Do with David's son?' said Mr. Dick.
+
+'Ay,' replied my aunt, 'with David's son.'
+
+'Oh!' said Mr. Dick. 'Yes. Do with--I should put him to bed.'
+
+'Janet!' cried my aunt, with the same complacent triumph that I had
+remarked before. 'Mr. Dick sets us all right. If the bed is ready, we'll
+take him up to it.'
+
+Janet reporting it to be quite ready, I was taken up to it; kindly, but
+in some sort like a prisoner; my aunt going in front and Janet bringing
+up the rear. The only circumstance which gave me any new hope, was my
+aunt's stopping on the stairs to inquire about a smell of fire that was
+prevalent there; and janet's replying that she had been making tinder
+down in the kitchen, of my old shirt. But there were no other clothes in
+my room than the odd heap of things I wore; and when I was left there,
+with a little taper which my aunt forewarned me would burn exactly five
+minutes, I heard them lock my door on the outside. Turning these things
+over in my mind I deemed it possible that my aunt, who could know
+nothing of me, might suspect I had a habit of running away, and took
+precautions, on that account, to have me in safe keeping.
+
+The room was a pleasant one, at the top of the house, overlooking the
+sea, on which the moon was shining brilliantly. After I had said my
+prayers, and the candle had burnt out, I remember how I still sat
+looking at the moonlight on the water, as if I could hope to read my
+fortune in it, as in a bright book; or to see my mother with her child,
+coming from Heaven, along that shining path, to look upon me as she had
+looked when I last saw her sweet face. I remember how the solemn feeling
+with which at length I turned my eyes away, yielded to the sensation of
+gratitude and rest which the sight of the white-curtained bed--and how
+much more the lying softly down upon it, nestling in the snow-white
+sheets!--inspired. I remember how I thought of all the solitary places
+under the night sky where I had slept, and how I prayed that I never
+might be houseless any more, and never might forget the houseless. I
+remember how I seemed to float, then, down the melancholy glory of that
+track upon the sea, away into the world of dreams.
+
+
+
+CHAPTER 14. MY AUNT MAKES UP HER MIND ABOUT ME
+
+
+On going down in the morning, I found my aunt musing so profoundly over
+the breakfast table, with her elbow on the tray, that the contents of
+the urn had overflowed the teapot and were laying the whole table-cloth
+under water, when my entrance put her meditations to flight. I felt sure
+that I had been the subject of her reflections, and was more than ever
+anxious to know her intentions towards me. Yet I dared not express my
+anxiety, lest it should give her offence.
+
+My eyes, however, not being so much under control as my tongue, were
+attracted towards my aunt very often during breakfast. I never could
+look at her for a few moments together but I found her looking at me--in
+an odd thoughtful manner, as if I were an immense way off, instead of
+being on the other side of the small round table. When she had finished
+her breakfast, my aunt very deliberately leaned back in her chair,
+knitted her brows, folded her arms, and contemplated me at her leisure,
+with such a fixedness of attention that I was quite overpowered by
+embarrassment. Not having as yet finished my own breakfast, I attempted
+to hide my confusion by proceeding with it; but my knife tumbled over my
+fork, my fork tripped up my knife, I chipped bits of bacon a surprising
+height into the air instead of cutting them for my own eating, and
+choked myself with my tea, which persisted in going the wrong way
+instead of the right one, until I gave in altogether, and sat blushing
+under my aunt's close scrutiny.
+
+'Hallo!' said my aunt, after a long time.
+
+I looked up, and met her sharp bright glance respectfully.
+
+'I have written to him,' said my aunt.
+
+'To--?'
+
+'To your father-in-law,' said my aunt. 'I have sent him a letter that
+I'll trouble him to attend to, or he and I will fall out, I can tell
+him!'
+
+'Does he know where I am, aunt?' I inquired, alarmed.
+
+'I have told him,' said my aunt, with a nod.
+
+'Shall I--be--given up to him?' I faltered.
+
+'I don't know,' said my aunt. 'We shall see.'
+
+'Oh! I can't think what I shall do,' I exclaimed, 'if I have to go back
+to Mr. Murdstone!'
+
+'I don't know anything about it,' said my aunt, shaking her head. 'I
+can't say, I am sure. We shall see.'
+
+My spirits sank under these words, and I became very downcast and heavy
+of heart. My aunt, without appearing to take much heed of me, put on a
+coarse apron with a bib, which she took out of the press; washed up the
+teacups with her own hands; and, when everything was washed and set in
+the tray again, and the cloth folded and put on the top of the whole,
+rang for Janet to remove it. She next swept up the crumbs with a little
+broom (putting on a pair of gloves first), until there did not appear
+to be one microscopic speck left on the carpet; next dusted and arranged
+the room, which was dusted and arranged to a hair's breadth already.
+When all these tasks were performed to her satisfaction, she took off
+the gloves and apron, folded them up, put them in the particular corner
+of the press from which they had been taken, brought out her work-box
+to her own table in the open window, and sat down, with the green fan
+between her and the light, to work.
+
+'I wish you'd go upstairs,' said my aunt, as she threaded her needle,
+'and give my compliments to Mr. Dick, and I'll be glad to know how he
+gets on with his Memorial.'
+
+I rose with all alacrity, to acquit myself of this commission.
+
+'I suppose,' said my aunt, eyeing me as narrowly as she had eyed the
+needle in threading it, 'you think Mr. Dick a short name, eh?'
+
+'I thought it was rather a short name, yesterday,' I confessed.
+
+'You are not to suppose that he hasn't got a longer name, if he chose
+to use it,' said my aunt, with a loftier air. 'Babley--Mr. Richard
+Babley--that's the gentleman's true name.'
+
+I was going to suggest, with a modest sense of my youth and the
+familiarity I had been already guilty of, that I had better give him the
+full benefit of that name, when my aunt went on to say:
+
+'But don't you call him by it, whatever you do. He can't bear his name.
+That's a peculiarity of his. Though I don't know that it's much of a
+peculiarity, either; for he has been ill-used enough, by some that bear
+it, to have a mortal antipathy for it, Heaven knows. Mr. Dick is his
+name here, and everywhere else, now--if he ever went anywhere else,
+which he don't. So take care, child, you don't call him anything BUT Mr.
+Dick.'
+
+I promised to obey, and went upstairs with my message; thinking, as I
+went, that if Mr. Dick had been working at his Memorial long, at the
+same rate as I had seen him working at it, through the open door, when
+I came down, he was probably getting on very well indeed. I found him
+still driving at it with a long pen, and his head almost laid upon the
+paper. He was so intent upon it, that I had ample leisure to observe the
+large paper kite in a corner, the confusion of bundles of manuscript,
+the number of pens, and, above all, the quantity of ink (which he seemed
+to have in, in half-gallon jars by the dozen), before he observed my
+being present.
+
+'Ha! Phoebus!' said Mr. Dick, laying down his pen. 'How does the world
+go? I'll tell you what,' he added, in a lower tone, 'I shouldn't wish it
+to be mentioned, but it's a--' here he beckoned to me, and put his lips
+close to my ear--'it's a mad world. Mad as Bedlam, boy!' said Mr. Dick,
+taking snuff from a round box on the table, and laughing heartily.
+
+Without presuming to give my opinion on this question, I delivered my
+message.
+
+'Well,' said Mr. Dick, in answer, 'my compliments to her, and I--I
+believe I have made a start. I think I have made a start,' said Mr.
+Dick, passing his hand among his grey hair, and casting anything but a
+confident look at his manuscript. 'You have been to school?'
+
+'Yes, sir,' I answered; 'for a short time.'
+
+'Do you recollect the date,' said Mr. Dick, looking earnestly at me, and
+taking up his pen to note it down, 'when King Charles the First had his
+head cut off?' I said I believed it happened in the year sixteen hundred
+and forty-nine.
+
+'Well,' returned Mr. Dick, scratching his ear with his pen, and looking
+dubiously at me. 'So the books say; but I don't see how that can be.
+Because, if it was so long ago, how could the people about him have made
+that mistake of putting some of the trouble out of his head, after it
+was taken off, into mine?'
+
+I was very much surprised by the inquiry; but could give no information
+on this point.
+
+'It's very strange,' said Mr. Dick, with a despondent look upon his
+papers, and with his hand among his hair again, 'that I never can get
+that quite right. I never can make that perfectly clear. But no matter,
+no matter!' he said cheerfully, and rousing himself, 'there's time
+enough! My compliments to Miss Trotwood, I am getting on very well
+indeed.'
+
+I was going away, when he directed my attention to the kite.
+
+'What do you think of that for a kite?' he said.
+
+I answered that it was a beautiful one. I should think it must have been
+as much as seven feet high.
+
+'I made it. We'll go and fly it, you and I,' said Mr. Dick. 'Do you see
+this?'
+
+He showed me that it was covered with manuscript, very closely and
+laboriously written; but so plainly, that as I looked along the lines,
+I thought I saw some allusion to King Charles the First's head again, in
+one or two places.
+
+'There's plenty of string,' said Mr. Dick, 'and when it flies high, it
+takes the facts a long way. That's my manner of diffusing 'em. I don't
+know where they may come down. It's according to circumstances, and the
+wind, and so forth; but I take my chance of that.'
+
+His face was so very mild and pleasant, and had something so reverend in
+it, though it was hale and hearty, that I was not sure but that he was
+having a good-humoured jest with me. So I laughed, and he laughed, and
+we parted the best friends possible.
+
+'Well, child,' said my aunt, when I went downstairs. 'And what of Mr.
+Dick, this morning?'
+
+I informed her that he sent his compliments, and was getting on very
+well indeed.
+
+'What do you think of him?' said my aunt.
+
+I had some shadowy idea of endeavouring to evade the question, by
+replying that I thought him a very nice gentleman; but my aunt was
+not to be so put off, for she laid her work down in her lap, and said,
+folding her hands upon it:
+
+'Come! Your sister Betsey Trotwood would have told me what she thought
+of anyone, directly. Be as like your sister as you can, and speak out!'
+
+'Is he--is Mr. Dick--I ask because I don't know, aunt--is he at all out
+of his mind, then?' I stammered; for I felt I was on dangerous ground.
+
+'Not a morsel,' said my aunt.
+
+'Oh, indeed!' I observed faintly.
+
+'If there is anything in the world,' said my aunt, with great decision
+and force of manner, 'that Mr. Dick is not, it's that.'
+
+I had nothing better to offer, than another timid, 'Oh, indeed!'
+
+'He has been CALLED mad,' said my aunt. 'I have a selfish pleasure in
+saying he has been called mad, or I should not have had the benefit of
+his society and advice for these last ten years and upwards--in fact,
+ever since your sister, Betsey Trotwood, disappointed me.'
+
+'So long as that?' I said.
+
+'And nice people they were, who had the audacity to call him mad,'
+pursued my aunt. 'Mr. Dick is a sort of distant connexion of mine--it
+doesn't matter how; I needn't enter into that. If it hadn't been for me,
+his own brother would have shut him up for life. That's all.'
+
+I am afraid it was hypocritical in me, but seeing that my aunt felt
+strongly on the subject, I tried to look as if I felt strongly too.
+
+'A proud fool!' said my aunt. 'Because his brother was a little
+eccentric--though he is not half so eccentric as a good many people--he
+didn't like to have him visible about his house, and sent him away to
+some private asylum-place: though he had been left to his particular
+care by their deceased father, who thought him almost a natural. And a
+wise man he must have been to think so! Mad himself, no doubt.'
+
+Again, as my aunt looked quite convinced, I endeavoured to look quite
+convinced also.
+
+'So I stepped in,' said my aunt, 'and made him an offer. I said, "Your
+brother's sane--a great deal more sane than you are, or ever will be, it
+is to be hoped. Let him have his little income, and come and live with
+me. I am not afraid of him, I am not proud, I am ready to take care
+of him, and shall not ill-treat him as some people (besides the
+asylum-folks) have done." After a good deal of squabbling,' said my
+aunt, 'I got him; and he has been here ever since. He is the most
+friendly and amenable creature in existence; and as for advice!--But
+nobody knows what that man's mind is, except myself.'
+
+My aunt smoothed her dress and shook her head, as if she smoothed
+defiance of the whole world out of the one, and shook it out of the
+other.
+
+'He had a favourite sister,' said my aunt, 'a good creature, and very
+kind to him. But she did what they all do--took a husband. And HE did
+what they all do--made her wretched. It had such an effect upon the mind
+of Mr. Dick (that's not madness, I hope!) that, combined with his fear
+of his brother, and his sense of his unkindness, it threw him into a
+fever. That was before he came to me, but the recollection of it is
+oppressive to him even now. Did he say anything to you about King
+Charles the First, child?'
+
+'Yes, aunt.'
+
+'Ah!' said my aunt, rubbing her nose as if she were a little vexed.
+'That's his allegorical way of expressing it. He connects his illness
+with great disturbance and agitation, naturally, and that's the figure,
+or the simile, or whatever it's called, which he chooses to use. And why
+shouldn't he, if he thinks proper!'
+
+I said: 'Certainly, aunt.'
+
+'It's not a business-like way of speaking,' said my aunt, 'nor a worldly
+way. I am aware of that; and that's the reason why I insist upon it,
+that there shan't be a word about it in his Memorial.'
+
+'Is it a Memorial about his own history that he is writing, aunt?'
+
+'Yes, child,' said my aunt, rubbing her nose again. 'He is memorializing
+the Lord Chancellor, or the Lord Somebody or other--one of those people,
+at all events, who are paid to be memorialized--about his affairs. I
+suppose it will go in, one of these days. He hasn't been able to draw
+it up yet, without introducing that mode of expressing himself; but it
+don't signify; it keeps him employed.'
+
+In fact, I found out afterwards that Mr. Dick had been for upwards
+of ten years endeavouring to keep King Charles the First out of the
+Memorial; but he had been constantly getting into it, and was there now.
+
+'I say again,' said my aunt, 'nobody knows what that man's mind is
+except myself; and he's the most amenable and friendly creature in
+existence. If he likes to fly a kite sometimes, what of that! Franklin
+used to fly a kite. He was a Quaker, or something of that sort, if I
+am not mistaken. And a Quaker flying a kite is a much more ridiculous
+object than anybody else.'
+
+If I could have supposed that my aunt had recounted these particulars
+for my especial behoof, and as a piece of confidence in me, I should
+have felt very much distinguished, and should have augured favourably
+from such a mark of her good opinion. But I could hardly help observing
+that she had launched into them, chiefly because the question was raised
+in her own mind, and with very little reference to me, though she had
+addressed herself to me in the absence of anybody else.
+
+At the same time, I must say that the generosity of her championship
+of poor harmless Mr. Dick, not only inspired my young breast with
+some selfish hope for myself, but warmed it unselfishly towards her.
+I believe that I began to know that there was something about my aunt,
+notwithstanding her many eccentricities and odd humours, to be honoured
+and trusted in. Though she was just as sharp that day as on the day
+before, and was in and out about the donkeys just as often, and was
+thrown into a tremendous state of indignation, when a young man, going
+by, ogled Janet at a window (which was one of the gravest misdemeanours
+that could be committed against my aunt's dignity), she seemed to me to
+command more of my respect, if not less of my fear.
+
+The anxiety I underwent, in the interval which necessarily elapsed
+before a reply could be received to her letter to Mr. Murdstone, was
+extreme; but I made an endeavour to suppress it, and to be as agreeable
+as I could in a quiet way, both to my aunt and Mr. Dick. The latter and
+I would have gone out to fly the great kite; but that I had still no
+other clothes than the anything but ornamental garments with which I
+had been decorated on the first day, and which confined me to the house,
+except for an hour after dark, when my aunt, for my health's sake,
+paraded me up and down on the cliff outside, before going to bed. At
+length the reply from Mr. Murdstone came, and my aunt informed me, to my
+infinite terror, that he was coming to speak to her herself on the next
+day. On the next day, still bundled up in my curious habiliments, I sat
+counting the time, flushed and heated by the conflict of sinking hopes
+and rising fears within me; and waiting to be startled by the sight of
+the gloomy face, whose non-arrival startled me every minute.
+
+MY aunt was a little more imperious and stern than usual, but I observed
+no other token of her preparing herself to receive the visitor so much
+dreaded by me. She sat at work in the window, and I sat by, with my
+thoughts running astray on all possible and impossible results of Mr.
+Murdstone's visit, until pretty late in the afternoon. Our dinner had
+been indefinitely postponed; but it was growing so late, that my aunt
+had ordered it to be got ready, when she gave a sudden alarm of donkeys,
+and to my consternation and amazement, I beheld Miss Murdstone, on a
+side-saddle, ride deliberately over the sacred piece of green, and stop
+in front of the house, looking about her.
+
+'Go along with you!' cried my aunt, shaking her head and her fist at the
+window. 'You have no business there. How dare you trespass? Go along!
+Oh! you bold-faced thing!'
+
+MY aunt was so exasperated by the coolness with which Miss Murdstone
+looked about her, that I really believe she was motionless, and unable
+for the moment to dart out according to custom. I seized the opportunity
+to inform her who it was; and that the gentleman now coming near the
+offender (for the way up was very steep, and he had dropped behind), was
+Mr. Murdstone himself.
+
+'I don't care who it is!' cried my aunt, still shaking her head and
+gesticulating anything but welcome from the bow-window. 'I won't be
+trespassed upon. I won't allow it. Go away! Janet, turn him round.
+Lead him off!' and I saw, from behind my aunt, a sort of hurried
+battle-piece, in which the donkey stood resisting everybody, with all
+his four legs planted different ways, while Janet tried to pull him
+round by the bridle, Mr. Murdstone tried to lead him on, Miss Murdstone
+struck at Janet with a parasol, and several boys, who had come to see
+the engagement, shouted vigorously. But my aunt, suddenly descrying
+among them the young malefactor who was the donkey's guardian, and who
+was one of the most inveterate offenders against her, though hardly in
+his teens, rushed out to the scene of action, pounced upon him, captured
+him, dragged him, with his jacket over his head, and his heels grinding
+the ground, into the garden, and, calling upon Janet to fetch the
+constables and justices, that he might be taken, tried, and executed on
+the spot, held him at bay there. This part of the business, however, did
+not last long; for the young rascal, being expert at a variety of feints
+and dodges, of which my aunt had no conception, soon went whooping away,
+leaving some deep impressions of his nailed boots in the flower-beds,
+and taking his donkey in triumph with him.
+
+Miss Murdstone, during the latter portion of the contest, had
+dismounted, and was now waiting with her brother at the bottom of the
+steps, until my aunt should be at leisure to receive them. My aunt, a
+little ruffled by the combat, marched past them into the house, with
+great dignity, and took no notice of their presence, until they were
+announced by Janet.
+
+'Shall I go away, aunt?' I asked, trembling.
+
+'No, sir,' said my aunt. 'Certainly not!' With which she pushed me into
+a corner near her, and fenced Me in with a chair, as if it were a prison
+or a bar of justice. This position I continued to occupy during the
+whole interview, and from it I now saw Mr. and Miss Murdstone enter the
+room.
+
+'Oh!' said my aunt, 'I was not aware at first to whom I had the pleasure
+of objecting. But I don't allow anybody to ride over that turf. I make
+no exceptions. I don't allow anybody to do it.'
+
+'Your regulation is rather awkward to strangers,' said Miss Murdstone.
+
+'Is it!' said my aunt.
+
+Mr. Murdstone seemed afraid of a renewal of hostilities, and interposing
+began:
+
+'Miss Trotwood!'
+
+'I beg your pardon,' observed my aunt with a keen look. 'You are the Mr.
+Murdstone who married the widow of my late nephew, David Copperfield, of
+Blunderstone Rookery!--Though why Rookery, I don't know!'
+
+'I am,' said Mr. Murdstone.
+
+'You'll excuse my saying, sir,' returned my aunt, 'that I think it would
+have been a much better and happier thing if you had left that poor
+child alone.'
+
+'I so far agree with what Miss Trotwood has remarked,' observed Miss
+Murdstone, bridling, 'that I consider our lamented Clara to have been,
+in all essential respects, a mere child.'
+
+'It is a comfort to you and me, ma'am,' said my aunt, 'who are getting
+on in life, and are not likely to be made unhappy by our personal
+attractions, that nobody can say the same of us.'
+
+'No doubt!' returned Miss Murdstone, though, I thought, not with a very
+ready or gracious assent. 'And it certainly might have been, as you say,
+a better and happier thing for my brother if he had never entered into
+such a marriage. I have always been of that opinion.'
+
+'I have no doubt you have,' said my aunt. 'Janet,' ringing the bell, 'my
+compliments to Mr. Dick, and beg him to come down.'
+
+Until he came, my aunt sat perfectly upright and stiff, frowning at the
+wall. When he came, my aunt performed the ceremony of introduction.
+
+'Mr. Dick. An old and intimate friend. On whose judgement,' said my
+aunt, with emphasis, as an admonition to Mr. Dick, who was biting his
+forefinger and looking rather foolish, 'I rely.'
+
+Mr. Dick took his finger out of his mouth, on this hint, and stood among
+the group, with a grave and attentive expression of face.
+
+My aunt inclined her head to Mr. Murdstone, who went on:
+
+'Miss Trotwood: on the receipt of your letter, I considered it an act of
+greater justice to myself, and perhaps of more respect to you-'
+
+'Thank you,' said my aunt, still eyeing him keenly. 'You needn't mind
+me.'
+
+'To answer it in person, however inconvenient the journey,' pursued Mr.
+Murdstone, 'rather than by letter. This unhappy boy who has run away
+from his friends and his occupation--'
+
+'And whose appearance,' interposed his sister, directing general
+attention to me in my indefinable costume, 'is perfectly scandalous and
+disgraceful.'
+
+'Jane Murdstone,' said her brother, 'have the goodness not to interrupt
+me. This unhappy boy, Miss Trotwood, has been the occasion of much
+domestic trouble and uneasiness; both during the lifetime of my late
+dear wife, and since. He has a sullen, rebellious spirit; a violent
+temper; and an untoward, intractable disposition. Both my sister and
+myself have endeavoured to correct his vices, but ineffectually. And
+I have felt--we both have felt, I may say; my sister being fully in
+my confidence--that it is right you should receive this grave and
+dispassionate assurance from our lips.'
+
+'It can hardly be necessary for me to confirm anything stated by my
+brother,' said Miss Murdstone; 'but I beg to observe, that, of all the
+boys in the world, I believe this is the worst boy.'
+
+'Strong!' said my aunt, shortly.
+
+'But not at all too strong for the facts,' returned Miss Murdstone.
+
+'Ha!' said my aunt. 'Well, sir?'
+
+'I have my own opinions,' resumed Mr. Murdstone, whose face darkened
+more and more, the more he and my aunt observed each other, which they
+did very narrowly, 'as to the best mode of bringing him up; they are
+founded, in part, on my knowledge of him, and in part on my knowledge of
+my own means and resources. I am responsible for them to myself, I act
+upon them, and I say no more about them. It is enough that I place this
+boy under the eye of a friend of my own, in a respectable business;
+that it does not please him; that he runs away from it; makes himself a
+common vagabond about the country; and comes here, in rags, to appeal
+to you, Miss Trotwood. I wish to set before you, honourably, the exact
+consequences--so far as they are within my knowledge--of your abetting
+him in this appeal.'
+
+'But about the respectable business first,' said my aunt. 'If he had
+been your own boy, you would have put him to it, just the same, I
+suppose?'
+
+'If he had been my brother's own boy,' returned Miss Murdstone, striking
+in, 'his character, I trust, would have been altogether different.'
+
+'Or if the poor child, his mother, had been alive, he would still have
+gone into the respectable business, would he?' said my aunt.
+
+'I believe,' said Mr. Murdstone, with an inclination of his head,
+'that Clara would have disputed nothing which myself and my sister Jane
+Murdstone were agreed was for the best.'
+
+Miss Murdstone confirmed this with an audible murmur.
+
+'Humph!' said my aunt. 'Unfortunate baby!'
+
+Mr. Dick, who had been rattling his money all this time, was rattling it
+so loudly now, that my aunt felt it necessary to check him with a look,
+before saying:
+
+'The poor child's annuity died with her?'
+
+'Died with her,' replied Mr. Murdstone.
+
+'And there was no settlement of the little property--the house and
+garden--the what's-its-name Rookery without any rooks in it--upon her
+boy?'
+
+'It had been left to her, unconditionally, by her first husband,'
+Mr. Murdstone began, when my aunt caught him up with the greatest
+irascibility and impatience.
+
+'Good Lord, man, there's no occasion to say that. Left to her
+unconditionally! I think I see David Copperfield looking forward to any
+condition of any sort or kind, though it stared him point-blank in the
+face! Of course it was left to her unconditionally. But when she married
+again--when she took that most disastrous step of marrying you, in
+short,' said my aunt, 'to be plain--did no one put in a word for the boy
+at that time?'
+
+'My late wife loved her second husband, ma'am,' said Mr. Murdstone, 'and
+trusted implicitly in him.'
+
+'Your late wife, sir, was a most unworldly, most unhappy, most
+unfortunate baby,' returned my aunt, shaking her head at him. 'That's
+what she was. And now, what have you got to say next?'
+
+'Merely this, Miss Trotwood,' he returned. 'I am here to take David
+back--to take him back unconditionally, to dispose of him as I think
+proper, and to deal with him as I think right. I am not here to make any
+promise, or give any pledge to anybody. You may possibly have some
+idea, Miss Trotwood, of abetting him in his running away, and in his
+complaints to you. Your manner, which I must say does not seem intended
+to propitiate, induces me to think it possible. Now I must caution you
+that if you abet him once, you abet him for good and all; if you step
+in between him and me, now, you must step in, Miss Trotwood, for ever.
+I cannot trifle, or be trifled with. I am here, for the first and last
+time, to take him away. Is he ready to go? If he is not--and you tell me
+he is not; on any pretence; it is indifferent to me what--my doors are
+shut against him henceforth, and yours, I take it for granted, are open
+to him.'
+
+To this address, my aunt had listened with the closest attention,
+sitting perfectly upright, with her hands folded on one knee, and
+looking grimly on the speaker. When he had finished, she turned her
+eyes so as to command Miss Murdstone, without otherwise disturbing her
+attitude, and said:
+
+'Well, ma'am, have YOU got anything to remark?'
+
+'Indeed, Miss Trotwood,' said Miss Murdstone, 'all that I could say has
+been so well said by my brother, and all that I know to be the fact
+has been so plainly stated by him, that I have nothing to add except my
+thanks for your politeness. For your very great politeness, I am sure,'
+said Miss Murdstone; with an irony which no more affected my aunt, than
+it discomposed the cannon I had slept by at Chatham.
+
+'And what does the boy say?' said my aunt. 'Are you ready to go, David?'
+
+I answered no, and entreated her not to let me go. I said that neither
+Mr. nor Miss Murdstone had ever liked me, or had ever been kind to me.
+That they had made my mama, who always loved me dearly, unhappy about
+me, and that I knew it well, and that Peggotty knew it. I said that I
+had been more miserable than I thought anybody could believe, who only
+knew how young I was. And I begged and prayed my aunt--I forget in
+what terms now, but I remember that they affected me very much then--to
+befriend and protect me, for my father's sake.
+
+'Mr. Dick,' said my aunt, 'what shall I do with this child?'
+
+Mr. Dick considered, hesitated, brightened, and rejoined, 'Have him
+measured for a suit of clothes directly.'
+
+'Mr. Dick,' said my aunt triumphantly, 'give me your hand, for your
+common sense is invaluable.' Having shaken it with great cordiality, she
+pulled me towards her and said to Mr. Murdstone:
+
+'You can go when you like; I'll take my chance with the boy. If he's all
+you say he is, at least I can do as much for him then, as you have done.
+But I don't believe a word of it.'
+
+'Miss Trotwood,' rejoined Mr. Murdstone, shrugging his shoulders, as he
+rose, 'if you were a gentleman--'
+
+'Bah! Stuff and nonsense!' said my aunt. 'Don't talk to me!'
+
+'How exquisitely polite!' exclaimed Miss Murdstone, rising.
+'Overpowering, really!'
+
+'Do you think I don't know,' said my aunt, turning a deaf ear to the
+sister, and continuing to address the brother, and to shake her head at
+him with infinite expression, 'what kind of life you must have led that
+poor, unhappy, misdirected baby? Do you think I don't know what a woeful
+day it was for the soft little creature when you first came in her
+way--smirking and making great eyes at her, I'll be bound, as if you
+couldn't say boh! to a goose!'
+
+'I never heard anything so elegant!' said Miss Murdstone.
+
+'Do you think I can't understand you as well as if I had seen you,'
+pursued my aunt, 'now that I DO see and hear you--which, I tell you
+candidly, is anything but a pleasure to me? Oh yes, bless us! who so
+smooth and silky as Mr. Murdstone at first! The poor, benighted innocent
+had never seen such a man. He was made of sweetness. He worshipped her.
+He doted on her boy--tenderly doted on him! He was to be another father
+to him, and they were all to live together in a garden of roses, weren't
+they? Ugh! Get along with you, do!' said my aunt.
+
+'I never heard anything like this person in my life!' exclaimed Miss
+Murdstone.
+
+'And when you had made sure of the poor little fool,' said my aunt--'God
+forgive me that I should call her so, and she gone where YOU won't go in
+a hurry--because you had not done wrong enough to her and hers, you
+must begin to train her, must you? begin to break her, like a poor
+caged bird, and wear her deluded life away, in teaching her to sing YOUR
+notes?'
+
+'This is either insanity or intoxication,' said Miss Murdstone, in a
+perfect agony at not being able to turn the current of my aunt's address
+towards herself; 'and my suspicion is that it's intoxication.'
+
+Miss Betsey, without taking the least notice of the interruption,
+continued to address herself to Mr. Murdstone as if there had been no
+such thing.
+
+'Mr. Murdstone,' she said, shaking her finger at him, 'you were a tyrant
+to the simple baby, and you broke her heart. She was a loving baby--I
+know that; I knew it, years before you ever saw her--and through the
+best part of her weakness you gave her the wounds she died of. There
+is the truth for your comfort, however you like it. And you and your
+instruments may make the most of it.'
+
+'Allow me to inquire, Miss Trotwood,' interposed Miss Murdstone,
+'whom you are pleased to call, in a choice of words in which I am not
+experienced, my brother's instruments?'
+
+'It was clear enough, as I have told you, years before YOU ever saw
+her--and why, in the mysterious dispensations of Providence, you ever
+did see her, is more than humanity can comprehend--it was clear enough
+that the poor soft little thing would marry somebody, at some time or
+other; but I did hope it wouldn't have been as bad as it has turned out.
+That was the time, Mr. Murdstone, when she gave birth to her boy here,'
+said my aunt; 'to the poor child you sometimes tormented her through
+afterwards, which is a disagreeable remembrance and makes the sight of
+him odious now. Aye, aye! you needn't wince!' said my aunt. 'I know it's
+true without that.'
+
+He had stood by the door, all this while, observant of her with a smile
+upon his face, though his black eyebrows were heavily contracted. I
+remarked now, that, though the smile was on his face still, his colour
+had gone in a moment, and he seemed to breathe as if he had been
+running.
+
+'Good day, sir,' said my aunt, 'and good-bye! Good day to you, too,
+ma'am,' said my aunt, turning suddenly upon his sister. 'Let me see you
+ride a donkey over my green again, and as sure as you have a head upon
+your shoulders, I'll knock your bonnet off, and tread upon it!'
+
+It would require a painter, and no common painter too, to depict my
+aunt's face as she delivered herself of this very unexpected sentiment,
+and Miss Murdstone's face as she heard it. But the manner of the speech,
+no less than the matter, was so fiery, that Miss Murdstone, without a
+word in answer, discreetly put her arm through her brother's, and walked
+haughtily out of the cottage; my aunt remaining in the window looking
+after them; prepared, I have no doubt, in case of the donkey's
+reappearance, to carry her threat into instant execution.
+
+No attempt at defiance being made, however, her face gradually relaxed,
+and became so pleasant, that I was emboldened to kiss and thank her;
+which I did with great heartiness, and with both my arms clasped round
+her neck. I then shook hands with Mr. Dick, who shook hands with me a
+great many times, and hailed this happy close of the proceedings with
+repeated bursts of laughter.
+
+'You'll consider yourself guardian, jointly with me, of this child, Mr.
+Dick,' said my aunt.
+
+'I shall be delighted,' said Mr. Dick, 'to be the guardian of David's
+son.'
+
+'Very good,' returned my aunt, 'that's settled. I have been thinking, do
+you know, Mr. Dick, that I might call him Trotwood?'
+
+'Certainly, certainly. Call him Trotwood, certainly,' said Mr. Dick.
+'David's son's Trotwood.'
+
+'Trotwood Copperfield, you mean,' returned my aunt.
+
+'Yes, to be sure. Yes. Trotwood Copperfield,' said Mr. Dick, a little
+abashed.
+
+My aunt took so kindly to the notion, that some ready-made clothes,
+which were purchased for me that afternoon, were marked 'Trotwood
+Copperfield', in her own handwriting, and in indelible marking-ink,
+before I put them on; and it was settled that all the other clothes
+which were ordered to be made for me (a complete outfit was bespoke that
+afternoon) should be marked in the same way.
+
+Thus I began my new life, in a new name, and with everything new about
+me. Now that the state of doubt was over, I felt, for many days,
+like one in a dream. I never thought that I had a curious couple of
+guardians, in my aunt and Mr. Dick. I never thought of anything about
+myself, distinctly. The two things clearest in my mind were, that a
+remoteness had come upon the old Blunderstone life--which seemed to lie
+in the haze of an immeasurable distance; and that a curtain had for ever
+fallen on my life at Murdstone and Grinby's. No one has ever raised that
+curtain since. I have lifted it for a moment, even in this narrative,
+with a reluctant hand, and dropped it gladly. The remembrance of that
+life is fraught with so much pain to me, with so much mental suffering
+and want of hope, that I have never had the courage even to examine how
+long I was doomed to lead it. Whether it lasted for a year, or more, or
+less, I do not know. I only know that it was, and ceased to be; and that
+I have written, and there I leave it.
+
+
+
+CHAPTER 15. I MAKE ANOTHER BEGINNING
+
+
+Mr. Dick and I soon became the best of friends, and very often, when his
+day's work was done, went out together to fly the great kite. Every day
+of his life he had a long sitting at the Memorial, which never made the
+least progress, however hard he laboured, for King Charles the First
+always strayed into it, sooner or later, and then it was thrown aside,
+and another one begun. The patience and hope with which he bore these
+perpetual disappointments, the mild perception he had that there was
+something wrong about King Charles the First, the feeble efforts he made
+to keep him out, and the certainty with which he came in, and tumbled
+the Memorial out of all shape, made a deep impression on me. What Mr.
+Dick supposed would come of the Memorial, if it were completed; where he
+thought it was to go, or what he thought it was to do; he knew no more
+than anybody else, I believe. Nor was it at all necessary that he should
+trouble himself with such questions, for if anything were certain under
+the sun, it was certain that the Memorial never would be finished. It
+was quite an affecting sight, I used to think, to see him with the kite
+when it was up a great height in the air. What he had told me, in his
+room, about his belief in its disseminating the statements pasted on it,
+which were nothing but old leaves of abortive Memorials, might have been
+a fancy with him sometimes; but not when he was out, looking up at
+the kite in the sky, and feeling it pull and tug at his hand. He never
+looked so serene as he did then. I used to fancy, as I sat by him of an
+evening, on a green slope, and saw him watch the kite high in the quiet
+air, that it lifted his mind out of its confusion, and bore it (such was
+my boyish thought) into the skies. As he wound the string in and it came
+lower and lower down out of the beautiful light, until it fluttered to
+the ground, and lay there like a dead thing, he seemed to wake gradually
+out of a dream; and I remember to have seen him take it up, and look
+about him in a lost way, as if they had both come down together, so that
+I pitied him with all my heart.
+
+While I advanced in friendship and intimacy with Mr. Dick, I did not
+go backward in the favour of his staunch friend, my aunt. She took
+so kindly to me, that, in the course of a few weeks, she shortened my
+adopted name of Trotwood into Trot; and even encouraged me to hope, that
+if I went on as I had begun, I might take equal rank in her affections
+with my sister Betsey Trotwood.
+
+'Trot,' said my aunt one evening, when the backgammon-board was placed
+as usual for herself and Mr. Dick, 'we must not forget your education.'
+
+This was my only subject of anxiety, and I felt quite delighted by her
+referring to it.
+
+'Should you like to go to school at Canterbury?' said my aunt.
+
+I replied that I should like it very much, as it was so near her.
+
+'Good,' said my aunt. 'Should you like to go tomorrow?'
+
+Being already no stranger to the general rapidity of my aunt's
+evolutions, I was not surprised by the suddenness of the proposal, and
+said: 'Yes.'
+
+'Good,' said my aunt again. 'Janet, hire the grey pony and chaise
+tomorrow morning at ten o'clock, and pack up Master Trotwood's clothes
+tonight.'
+
+I was greatly elated by these orders; but my heart smote me for my
+selfishness, when I witnessed their effect on Mr. Dick, who was so
+low-spirited at the prospect of our separation, and played so ill in
+consequence, that my aunt, after giving him several admonitory raps on
+the knuckles with her dice-box, shut up the board, and declined to play
+with him any more. But, on hearing from my aunt that I should sometimes
+come over on a Saturday, and that he could sometimes come and see me
+on a Wednesday, he revived; and vowed to make another kite for those
+occasions, of proportions greatly surpassing the present one. In the
+morning he was downhearted again, and would have sustained himself by
+giving me all the money he had in his possession, gold and silver too,
+if my aunt had not interposed, and limited the gift to five shillings,
+which, at his earnest petition, were afterwards increased to ten. We
+parted at the garden-gate in a most affectionate manner, and Mr. Dick
+did not go into the house until my aunt had driven me out of sight of
+it.
+
+My aunt, who was perfectly indifferent to public opinion, drove the grey
+pony through Dover in a masterly manner; sitting high and stiff like
+a state coachman, keeping a steady eye upon him wherever he went, and
+making a point of not letting him have his own way in any respect. When
+we came into the country road, she permitted him to relax a little,
+however; and looking at me down in a valley of cushion by her side,
+asked me whether I was happy?
+
+'Very happy indeed, thank you, aunt,' I said.
+
+She was much gratified; and both her hands being occupied, patted me on
+the head with her whip.
+
+'Is it a large school, aunt?' I asked.
+
+'Why, I don't know,' said my aunt. 'We are going to Mr. Wickfield's
+first.'
+
+'Does he keep a school?' I asked.
+
+'No, Trot,' said my aunt. 'He keeps an office.'
+
+I asked for no more information about Mr. Wickfield, as she offered
+none, and we conversed on other subjects until we came to Canterbury,
+where, as it was market-day, my aunt had a great opportunity of
+insinuating the grey pony among carts, baskets, vegetables, and
+huckster's goods. The hair-breadth turns and twists we made, drew down
+upon us a variety of speeches from the people standing about, which
+were not always complimentary; but my aunt drove on with perfect
+indifference, and I dare say would have taken her own way with as much
+coolness through an enemy's country.
+
+At length we stopped before a very old house bulging out over the road;
+a house with long low lattice-windows bulging out still farther, and
+beams with carved heads on the ends bulging out too, so that I fancied
+the whole house was leaning forward, trying to see who was passing on
+the narrow pavement below. It was quite spotless in its cleanliness.
+The old-fashioned brass knocker on the low arched door, ornamented with
+carved garlands of fruit and flowers, twinkled like a star; the two
+stone steps descending to the door were as white as if they had been
+covered with fair linen; and all the angles and corners, and carvings
+and mouldings, and quaint little panes of glass, and quainter little
+windows, though as old as the hills, were as pure as any snow that ever
+fell upon the hills.
+
+When the pony-chaise stopped at the door, and my eyes were intent upon
+the house, I saw a cadaverous face appear at a small window on the
+ground floor (in a little round tower that formed one side of the
+house), and quickly disappear. The low arched door then opened, and
+the face came out. It was quite as cadaverous as it had looked in the
+window, though in the grain of it there was that tinge of red which is
+sometimes to be observed in the skins of red-haired people. It belonged
+to a red-haired person--a youth of fifteen, as I take it now, but
+looking much older--whose hair was cropped as close as the closest
+stubble; who had hardly any eyebrows, and no eyelashes, and eyes of a
+red-brown, so unsheltered and unshaded, that I remember wondering how he
+went to sleep. He was high-shouldered and bony; dressed in decent black,
+with a white wisp of a neckcloth; buttoned up to the throat; and had a
+long, lank, skeleton hand, which particularly attracted my attention, as
+he stood at the pony's head, rubbing his chin with it, and looking up at
+us in the chaise.
+
+'Is Mr. Wickfield at home, Uriah Heep?' said my aunt.
+
+'Mr. Wickfield's at home, ma'am,' said Uriah Heep, 'if you'll please to
+walk in there'--pointing with his long hand to the room he meant.
+
+We got out; and leaving him to hold the pony, went into a long low
+parlour looking towards the street, from the window of which I caught a
+glimpse, as I went in, of Uriah Heep breathing into the pony's nostrils,
+and immediately covering them with his hand, as if he were putting
+some spell upon him. Opposite to the tall old chimney-piece were two
+portraits: one of a gentleman with grey hair (though not by any means
+an old man) and black eyebrows, who was looking over some papers tied
+together with red tape; the other, of a lady, with a very placid and
+sweet expression of face, who was looking at me.
+
+I believe I was turning about in search of Uriah's picture, when, a door
+at the farther end of the room opening, a gentleman entered, at sight of
+whom I turned to the first-mentioned portrait again, to make quite sure
+that it had not come out of its frame. But it was stationary; and as the
+gentleman advanced into the light, I saw that he was some years older
+than when he had had his picture painted.
+
+'Miss Betsey Trotwood,' said the gentleman, 'pray walk in. I was engaged
+for a moment, but you'll excuse my being busy. You know my motive. I
+have but one in life.'
+
+Miss Betsey thanked him, and we went into his room, which was furnished
+as an office, with books, papers, tin boxes, and so forth. It looked
+into a garden, and had an iron safe let into the wall; so immediately
+over the mantelshelf, that I wondered, as I sat down, how the sweeps got
+round it when they swept the chimney.
+
+'Well, Miss Trotwood,' said Mr. Wickfield; for I soon found that it
+was he, and that he was a lawyer, and steward of the estates of a rich
+gentleman of the county; 'what wind blows you here? Not an ill wind, I
+hope?'
+
+'No,' replied my aunt. 'I have not come for any law.'
+
+'That's right, ma'am,' said Mr. Wickfield. 'You had better come for
+anything else.' His hair was quite white now, though his eyebrows were
+still black. He had a very agreeable face, and, I thought, was handsome.
+There was a certain richness in his complexion, which I had been long
+accustomed, under Peggotty's tuition, to connect with port wine; and I
+fancied it was in his voice too, and referred his growing corpulency
+to the same cause. He was very cleanly dressed, in a blue coat, striped
+waistcoat, and nankeen trousers; and his fine frilled shirt and cambric
+neckcloth looked unusually soft and white, reminding my strolling fancy
+(I call to mind) of the plumage on the breast of a swan.
+
+'This is my nephew,' said my aunt.
+
+'Wasn't aware you had one, Miss Trotwood,' said Mr. Wickfield.
+
+'My grand-nephew, that is to say,' observed my aunt.
+
+'Wasn't aware you had a grand-nephew, I give you my word,' said Mr.
+Wickfield.
+
+'I have adopted him,' said my aunt, with a wave of her hand, importing
+that his knowledge and his ignorance were all one to her, 'and I have
+brought him here, to put to a school where he may be thoroughly well
+taught, and well treated. Now tell me where that school is, and what it
+is, and all about it.'
+
+'Before I can advise you properly,' said Mr. Wickfield--'the old
+question, you know. What's your motive in this?'
+
+'Deuce take the man!' exclaimed my aunt. 'Always fishing for motives,
+when they're on the surface! Why, to make the child happy and useful.'
+
+'It must be a mixed motive, I think,' said Mr. Wickfield, shaking his
+head and smiling incredulously.
+
+'A mixed fiddlestick,' returned my aunt. 'You claim to have one plain
+motive in all you do yourself. You don't suppose, I hope, that you are
+the only plain dealer in the world?'
+
+'Ay, but I have only one motive in life, Miss Trotwood,' he rejoined,
+smiling. 'Other people have dozens, scores, hundreds. I have only one.
+There's the difference. However, that's beside the question. The best
+school? Whatever the motive, you want the best?'
+
+My aunt nodded assent.
+
+'At the best we have,' said Mr. Wickfield, considering, 'your nephew
+couldn't board just now.'
+
+'But he could board somewhere else, I suppose?' suggested my aunt.
+
+Mr. Wickfield thought I could. After a little discussion, he proposed to
+take my aunt to the school, that she might see it and judge for herself;
+also, to take her, with the same object, to two or three houses where he
+thought I could be boarded. My aunt embracing the proposal, we were all
+three going out together, when he stopped and said:
+
+'Our little friend here might have some motive, perhaps, for objecting
+to the arrangements. I think we had better leave him behind?'
+
+My aunt seemed disposed to contest the point; but to facilitate matters
+I said I would gladly remain behind, if they pleased; and returned into
+Mr. Wickfield's office, where I sat down again, in the chair I had first
+occupied, to await their return.
+
+It so happened that this chair was opposite a narrow passage, which
+ended in the little circular room where I had seen Uriah Heep's pale
+face looking out of the window. Uriah, having taken the pony to a
+neighbouring stable, was at work at a desk in this room, which had a
+brass frame on the top to hang paper upon, and on which the writing he
+was making a copy of was then hanging. Though his face was towards me, I
+thought, for some time, the writing being between us, that he could not
+see me; but looking that way more attentively, it made me uncomfortable
+to observe that, every now and then, his sleepless eyes would come below
+the writing, like two red suns, and stealthily stare at me for I dare
+say a whole minute at a time, during which his pen went, or pretended
+to go, as cleverly as ever. I made several attempts to get out of their
+way--such as standing on a chair to look at a map on the other side of
+the room, and poring over the columns of a Kentish newspaper--but they
+always attracted me back again; and whenever I looked towards those two
+red suns, I was sure to find them, either just rising or just setting.
+
+At length, much to my relief, my aunt and Mr. Wickfield came back,
+after a pretty long absence. They were not so successful as I could have
+wished; for though the advantages of the school were undeniable, my aunt
+had not approved of any of the boarding-houses proposed for me.
+
+'It's very unfortunate,' said my aunt. 'I don't know what to do, Trot.'
+
+'It does happen unfortunately,' said Mr. Wickfield. 'But I'll tell you
+what you can do, Miss Trotwood.'
+
+'What's that?' inquired my aunt.
+
+'Leave your nephew here, for the present. He's a quiet fellow. He
+won't disturb me at all. It's a capital house for study. As quiet as a
+monastery, and almost as roomy. Leave him here.'
+
+My aunt evidently liked the offer, though she was delicate of accepting
+it. So did I. 'Come, Miss Trotwood,' said Mr. Wickfield. 'This is the
+way out of the difficulty. It's only a temporary arrangement, you know.
+If it don't act well, or don't quite accord with our mutual convenience,
+he can easily go to the right-about. There will be time to find some
+better place for him in the meanwhile. You had better determine to leave
+him here for the present!'
+
+'I am very much obliged to you,' said my aunt; 'and so is he, I see;
+but--'
+
+'Come! I know what you mean,' cried Mr. Wickfield. 'You shall not be
+oppressed by the receipt of favours, Miss Trotwood. You may pay for
+him, if you like. We won't be hard about terms, but you shall pay if you
+will.'
+
+'On that understanding,' said my aunt, 'though it doesn't lessen the
+real obligation, I shall be very glad to leave him.'
+
+'Then come and see my little housekeeper,' said Mr. Wickfield.
+
+We accordingly went up a wonderful old staircase; with a balustrade
+so broad that we might have gone up that, almost as easily; and into
+a shady old drawing-room, lighted by some three or four of the quaint
+windows I had looked up at from the street: which had old oak seats
+in them, that seemed to have come of the same trees as the shining oak
+floor, and the great beams in the ceiling. It was a prettily furnished
+room, with a piano and some lively furniture in red and green, and some
+flowers. It seemed to be all old nooks and corners; and in every nook
+and corner there was some queer little table, or cupboard, or bookcase,
+or seat, or something or other, that made me think there was not such
+another good corner in the room; until I looked at the next one, and
+found it equal to it, if not better. On everything there was the same
+air of retirement and cleanliness that marked the house outside.
+
+Mr. Wickfield tapped at a door in a corner of the panelled wall, and a
+girl of about my own age came quickly out and kissed him. On her face,
+I saw immediately the placid and sweet expression of the lady whose
+picture had looked at me downstairs. It seemed to my imagination as
+if the portrait had grown womanly, and the original remained a child.
+Although her face was quite bright and happy, there was a tranquillity
+about it, and about her--a quiet, good, calm spirit--that I never have
+forgotten; that I shall never forget. This was his little housekeeper,
+his daughter Agnes, Mr. Wickfield said. When I heard how he said it, and
+saw how he held her hand, I guessed what the one motive of his life was.
+
+She had a little basket-trifle hanging at her side, with keys in it; and
+she looked as staid and as discreet a housekeeper as the old house
+could have. She listened to her father as he told her about me, with a
+pleasant face; and when he had concluded, proposed to my aunt that we
+should go upstairs and see my room. We all went together, she before us:
+and a glorious old room it was, with more oak beams, and diamond panes;
+and the broad balustrade going all the way up to it.
+
+I cannot call to mind where or when, in my childhood, I had seen a
+stained glass window in a church. Nor do I recollect its subject. But
+I know that when I saw her turn round, in the grave light of the old
+staircase, and wait for us, above, I thought of that window; and I
+associated something of its tranquil brightness with Agnes Wickfield
+ever afterwards.
+
+My aunt was as happy as I was, in the arrangement made for me; and we
+went down to the drawing-room again, well pleased and gratified. As she
+would not hear of staying to dinner, lest she should by any chance fail
+to arrive at home with the grey pony before dark; and as I apprehend Mr.
+Wickfield knew her too well to argue any point with her; some lunch was
+provided for her there, and Agnes went back to her governess, and Mr.
+Wickfield to his office. So we were left to take leave of one another
+without any restraint.
+
+She told me that everything would be arranged for me by Mr. Wickfield,
+and that I should want for nothing, and gave me the kindest words and
+the best advice.
+
+'Trot,' said my aunt in conclusion, 'be a credit to yourself, to me, and
+Mr. Dick, and Heaven be with you!'
+
+I was greatly overcome, and could only thank her, again and again, and
+send my love to Mr. Dick.
+
+'Never,' said my aunt, 'be mean in anything; never be false; never be
+cruel. Avoid those three vices, Trot, and I can always be hopeful of
+you.'
+
+I promised, as well as I could, that I would not abuse her kindness or
+forget her admonition.
+
+'The pony's at the door,' said my aunt, 'and I am off! Stay here.' With
+these words she embraced me hastily, and went out of the room, shutting
+the door after her. At first I was startled by so abrupt a departure,
+and almost feared I had displeased her; but when I looked into the
+street, and saw how dejectedly she got into the chaise, and drove away
+without looking up, I understood her better and did not do her that
+injustice.
+
+By five o'clock, which was Mr. Wickfield's dinner-hour, I had mustered
+up my spirits again, and was ready for my knife and fork. The cloth was
+only laid for us two; but Agnes was waiting in the drawing-room before
+dinner, went down with her father, and sat opposite to him at table. I
+doubted whether he could have dined without her.
+
+We did not stay there, after dinner, but came upstairs into the
+drawing-room again: in one snug corner of which, Agnes set glasses for
+her father, and a decanter of port wine. I thought he would have missed
+its usual flavour, if it had been put there for him by any other hands.
+
+There he sat, taking his wine, and taking a good deal of it, for two
+hours; while Agnes played on the piano, worked, and talked to him and
+me. He was, for the most part, gay and cheerful with us; but sometimes
+his eyes rested on her, and he fell into a brooding state, and was
+silent. She always observed this quickly, I thought, and always roused
+him with a question or caress. Then he came out of his meditation, and
+drank more wine.
+
+Agnes made the tea, and presided over it; and the time passed away after
+it, as after dinner, until she went to bed; when her father took her
+in his arms and kissed her, and, she being gone, ordered candles in his
+office. Then I went to bed too.
+
+But in the course of the evening I had rambled down to the door, and a
+little way along the street, that I might have another peep at the old
+houses, and the grey Cathedral; and might think of my coming through
+that old city on my journey, and of my passing the very house I lived
+in, without knowing it. As I came back, I saw Uriah Heep shutting up
+the office; and feeling friendly towards everybody, went in and spoke
+to him, and at parting, gave him my hand. But oh, what a clammy hand his
+was! as ghostly to the touch as to the sight! I rubbed mine afterwards,
+to warm it, AND TO RUB HIS OFF.
+
+It was such an uncomfortable hand, that, when I went to my room, it was
+still cold and wet upon my memory. Leaning out of the window, and seeing
+one of the faces on the beam-ends looking at me sideways, I fancied it
+was Uriah Heep got up there somehow, and shut him out in a hurry.
+
+
+
+CHAPTER 16. I AM A NEW BOY IN MORE SENSES THAN ONE
+
+
+Next morning, after breakfast, I entered on school life again. I went,
+accompanied by Mr. Wickfield, to the scene of my future studies--a grave
+building in a courtyard, with a learned air about it that seemed very
+well suited to the stray rooks and jackdaws who came down from the
+Cathedral towers to walk with a clerkly bearing on the grass-plot--and
+was introduced to my new master, Doctor Strong.
+
+Doctor Strong looked almost as rusty, to my thinking, as the tall iron
+rails and gates outside the house; and almost as stiff and heavy as the
+great stone urns that flanked them, and were set up, on the top of
+the red-brick wall, at regular distances all round the court, like
+sublimated skittles, for Time to play at. He was in his library (I mean
+Doctor Strong was), with his clothes not particularly well brushed, and
+his hair not particularly well combed; his knee-smalls unbraced; his
+long black gaiters unbuttoned; and his shoes yawning like two caverns on
+the hearth-rug. Turning upon me a lustreless eye, that reminded me of
+a long-forgotten blind old horse who once used to crop the grass, and
+tumble over the graves, in Blunderstone churchyard, he said he was glad
+to see me: and then he gave me his hand; which I didn't know what to do
+with, as it did nothing for itself.
+
+But, sitting at work, not far from Doctor Strong, was a very pretty
+young lady--whom he called Annie, and who was his daughter, I
+supposed--who got me out of my difficulty by kneeling down to put Doctor
+Strong's shoes on, and button his gaiters, which she did with great
+cheerfulness and quickness. When she had finished, and we were going
+out to the schoolroom, I was much surprised to hear Mr. Wickfield,
+in bidding her good morning, address her as 'Mrs. Strong'; and I was
+wondering could she be Doctor Strong's son's wife, or could she be Mrs.
+Doctor Strong, when Doctor Strong himself unconsciously enlightened me.
+
+'By the by, Wickfield,' he said, stopping in a passage with his hand on
+my shoulder; 'you have not found any suitable provision for my wife's
+cousin yet?'
+
+'No,' said Mr. Wickfield. 'No. Not yet.'
+
+'I could wish it done as soon as it can be done, Wickfield,' said
+Doctor Strong, 'for Jack Maldon is needy, and idle; and of those two
+bad things, worse things sometimes come. What does Doctor Watts say,' he
+added, looking at me, and moving his head to the time of his quotation,
+'"Satan finds some mischief still, for idle hands to do."'
+
+'Egad, Doctor,' returned Mr. Wickfield, 'if Doctor Watts knew mankind,
+he might have written, with as much truth, "Satan finds some mischief
+still, for busy hands to do." The busy people achieve their full share
+of mischief in the world, you may rely upon it. What have the people
+been about, who have been the busiest in getting money, and in getting
+power, this century or two? No mischief?'
+
+'Jack Maldon will never be very busy in getting either, I expect,' said
+Doctor Strong, rubbing his chin thoughtfully.
+
+'Perhaps not,' said Mr. Wickfield; 'and you bring me back to the
+question, with an apology for digressing. No, I have not been able
+to dispose of Mr. Jack Maldon yet. I believe,' he said this with some
+hesitation, 'I penetrate your motive, and it makes the thing more
+difficult.'
+
+'My motive,' returned Doctor Strong, 'is to make some suitable provision
+for a cousin, and an old playfellow, of Annie's.'
+
+'Yes, I know,' said Mr. Wickfield; 'at home or abroad.'
+
+'Aye!' replied the Doctor, apparently wondering why he emphasized those
+words so much. 'At home or abroad.'
+
+'Your own expression, you know,' said Mr. Wickfield. 'Or abroad.'
+
+'Surely,' the Doctor answered. 'Surely. One or other.'
+
+'One or other? Have you no choice?' asked Mr. Wickfield.
+
+'No,' returned the Doctor.
+
+'No?' with astonishment.
+
+'Not the least.'
+
+'No motive,' said Mr. Wickfield, 'for meaning abroad, and not at home?'
+
+'No,' returned the Doctor.
+
+'I am bound to believe you, and of course I do believe you,' said Mr.
+Wickfield. 'It might have simplified my office very much, if I had known
+it before. But I confess I entertained another impression.'
+
+Doctor Strong regarded him with a puzzled and doubting look,
+which almost immediately subsided into a smile that gave me great
+encouragement; for it was full of amiability and sweetness, and there
+was a simplicity in it, and indeed in his whole manner, when the
+studious, pondering frost upon it was got through, very attractive and
+hopeful to a young scholar like me. Repeating 'no', and 'not the least',
+and other short assurances to the same purport, Doctor Strong jogged
+on before us, at a queer, uneven pace; and we followed: Mr. Wickfield,
+looking grave, I observed, and shaking his head to himself, without
+knowing that I saw him.
+
+The schoolroom was a pretty large hall, on the quietest side of the
+house, confronted by the stately stare of some half-dozen of the great
+urns, and commanding a peep of an old secluded garden belonging to the
+Doctor, where the peaches were ripening on the sunny south wall. There
+were two great aloes, in tubs, on the turf outside the windows; the
+broad hard leaves of which plant (looking as if they were made of
+painted tin) have ever since, by association, been symbolical to me
+of silence and retirement. About five-and-twenty boys were studiously
+engaged at their books when we went in, but they rose to give the Doctor
+good morning, and remained standing when they saw Mr. Wickfield and me.
+
+'A new boy, young gentlemen,' said the Doctor; 'Trotwood Copperfield.'
+
+One Adams, who was the head-boy, then stepped out of his place and
+welcomed me. He looked like a young clergyman, in his white cravat, but
+he was very affable and good-humoured; and he showed me my place, and
+presented me to the masters, in a gentlemanly way that would have put me
+at my ease, if anything could.
+
+It seemed to me so long, however, since I had been among such boys,
+or among any companions of my own age, except Mick Walker and Mealy
+Potatoes, that I felt as strange as ever I have done in my life. I was
+so conscious of having passed through scenes of which they could have
+no knowledge, and of having acquired experiences foreign to my age,
+appearance, and condition as one of them, that I half believed it was an
+imposture to come there as an ordinary little schoolboy. I had become,
+in the Murdstone and Grinby time, however short or long it may have
+been, so unused to the sports and games of boys, that I knew I was
+awkward and inexperienced in the commonest things belonging to them.
+Whatever I had learnt, had so slipped away from me in the sordid cares
+of my life from day to night, that now, when I was examined about what
+I knew, I knew nothing, and was put into the lowest form of the school.
+But, troubled as I was, by my want of boyish skill, and of book-learning
+too, I was made infinitely more uncomfortable by the consideration,
+that, in what I did know, I was much farther removed from my companions
+than in what I did not. My mind ran upon what they would think, if they
+knew of my familiar acquaintance with the King's Bench Prison? Was there
+anything about me which would reveal my proceedings in connexion with
+the Micawber family--all those pawnings, and sellings, and suppers--in
+spite of myself? Suppose some of the boys had seen me coming through
+Canterbury, wayworn and ragged, and should find me out? What would they
+say, who made so light of money, if they could know how I had scraped my
+halfpence together, for the purchase of my daily saveloy and beer, or
+my slices of pudding? How would it affect them, who were so innocent of
+London life, and London streets, to discover how knowing I was (and was
+ashamed to be) in some of the meanest phases of both? All this ran in
+my head so much, on that first day at Doctor Strong's, that I felt
+distrustful of my slightest look and gesture; shrunk within myself
+whensoever I was approached by one of my new schoolfellows; and hurried
+off the minute school was over, afraid of committing myself in my
+response to any friendly notice or advance.
+
+But there was such an influence in Mr. Wickfield's old house, that when
+I knocked at it, with my new school-books under my arm, I began to feel
+my uneasiness softening away. As I went up to my airy old room, the
+grave shadow of the staircase seemed to fall upon my doubts and fears,
+and to make the past more indistinct. I sat there, sturdily conning my
+books, until dinner-time (we were out of school for good at three); and
+went down, hopeful of becoming a passable sort of boy yet.
+
+Agnes was in the drawing-room, waiting for her father, who was detained
+by someone in his office. She met me with her pleasant smile, and asked
+me how I liked the school. I told her I should like it very much, I
+hoped; but I was a little strange to it at first.
+
+'You have never been to school,' I said, 'have you?' 'Oh yes! Every
+day.'
+
+'Ah, but you mean here, at your own home?'
+
+'Papa couldn't spare me to go anywhere else,' she answered, smiling and
+shaking her head. 'His housekeeper must be in his house, you know.'
+
+'He is very fond of you, I am sure,' I said.
+
+She nodded 'Yes,' and went to the door to listen for his coming up, that
+she might meet him on the stairs. But, as he was not there, she came
+back again.
+
+'Mama has been dead ever since I was born,' she said, in her quiet way.
+'I only know her picture, downstairs. I saw you looking at it yesterday.
+Did you think whose it was?'
+
+I told her yes, because it was so like herself.
+
+'Papa says so, too,' said Agnes, pleased. 'Hark! That's papa now!'
+
+Her bright calm face lighted up with pleasure as she went to meet him,
+and as they came in, hand in hand. He greeted me cordially; and told
+me I should certainly be happy under Doctor Strong, who was one of the
+gentlest of men.
+
+'There may be some, perhaps--I don't know that there are--who abuse
+his kindness,' said Mr. Wickfield. 'Never be one of those, Trotwood, in
+anything. He is the least suspicious of mankind; and whether that's
+a merit, or whether it's a blemish, it deserves consideration in all
+dealings with the Doctor, great or small.'
+
+He spoke, I thought, as if he were weary, or dissatisfied with
+something; but I did not pursue the question in my mind, for dinner was
+just then announced, and we went down and took the same seats as before.
+
+We had scarcely done so, when Uriah Heep put in his red head and his
+lank hand at the door, and said:
+
+'Here's Mr. Maldon begs the favour of a word, sir.'
+
+'I am but this moment quit of Mr. Maldon,' said his master.
+
+'Yes, sir,' returned Uriah; 'but Mr. Maldon has come back, and he begs
+the favour of a word.'
+
+As he held the door open with his hand, Uriah looked at me, and looked
+at Agnes, and looked at the dishes, and looked at the plates, and looked
+at every object in the room, I thought,--yet seemed to look at nothing;
+he made such an appearance all the while of keeping his red eyes
+dutifully on his master. 'I beg your pardon. It's only to say, on
+reflection,' observed a voice behind Uriah, as Uriah's head was
+pushed away, and the speaker's substituted--'pray excuse me for this
+intrusion--that as it seems I have no choice in the matter, the sooner
+I go abroad the better. My cousin Annie did say, when we talked of it,
+that she liked to have her friends within reach rather than to have them
+banished, and the old Doctor--'
+
+'Doctor Strong, was that?' Mr. Wickfield interposed, gravely.
+
+'Doctor Strong, of course,' returned the other; 'I call him the old
+Doctor; it's all the same, you know.'
+
+'I don't know,' returned Mr. Wickfield.
+
+'Well, Doctor Strong,' said the other--'Doctor Strong was of the same
+mind, I believed. But as it appears from the course you take with me he
+has changed his mind, why there's no more to be said, except that the
+sooner I am off, the better. Therefore, I thought I'd come back and say,
+that the sooner I am off the better. When a plunge is to be made into
+the water, it's of no use lingering on the bank.'
+
+'There shall be as little lingering as possible, in your case, Mr.
+Maldon, you may depend upon it,' said Mr. Wickfield.
+
+'Thank'ee,' said the other. 'Much obliged. I don't want to look a
+gift-horse in the mouth, which is not a gracious thing to do; otherwise,
+I dare say, my cousin Annie could easily arrange it in her own way. I
+suppose Annie would only have to say to the old Doctor--'
+
+'Meaning that Mrs. Strong would only have to say to her husband--do I
+follow you?' said Mr. Wickfield.
+
+'Quite so,' returned the other, '--would only have to say, that she
+wanted such and such a thing to be so and so; and it would be so and so,
+as a matter of course.'
+
+'And why as a matter of course, Mr. Maldon?' asked Mr. Wickfield,
+sedately eating his dinner.
+
+'Why, because Annie's a charming young girl, and the old Doctor--Doctor
+Strong, I mean--is not quite a charming young boy,' said Mr. Jack
+Maldon, laughing. 'No offence to anybody, Mr. Wickfield. I only mean
+that I suppose some compensation is fair and reasonable in that sort of
+marriage.'
+
+'Compensation to the lady, sir?' asked Mr. Wickfield gravely.
+
+'To the lady, sir,' Mr. Jack Maldon answered, laughing. But appearing
+to remark that Mr. Wickfield went on with his dinner in the same sedate,
+immovable manner, and that there was no hope of making him relax a
+muscle of his face, he added: 'However, I have said what I came to say,
+and, with another apology for this intrusion, I may take myself off. Of
+course I shall observe your directions, in considering the matter as one
+to be arranged between you and me solely, and not to be referred to, up
+at the Doctor's.'
+
+'Have you dined?' asked Mr. Wickfield, with a motion of his hand towards
+the table.
+
+'Thank'ee. I am going to dine,' said Mr. Maldon, 'with my cousin Annie.
+Good-bye!'
+
+Mr. Wickfield, without rising, looked after him thoughtfully as he went
+out. He was rather a shallow sort of young gentleman, I thought, with
+a handsome face, a rapid utterance, and a confident, bold air. And this
+was the first I ever saw of Mr. Jack Maldon; whom I had not expected to
+see so soon, when I heard the Doctor speak of him that morning.
+
+When we had dined, we went upstairs again, where everything went on
+exactly as on the previous day. Agnes set the glasses and decanters in
+the same corner, and Mr. Wickfield sat down to drink, and drank a good
+deal. Agnes played the piano to him, sat by him, and worked and talked,
+and played some games at dominoes with me. In good time she made tea;
+and afterwards, when I brought down my books, looked into them, and
+showed me what she knew of them (which was no slight matter, though she
+said it was), and what was the best way to learn and understand them.
+I see her, with her modest, orderly, placid manner, and I hear her
+beautiful calm voice, as I write these words. The influence for all
+good, which she came to exercise over me at a later time, begins
+already to descend upon my breast. I love little Em'ly, and I don't love
+Agnes--no, not at all in that way--but I feel that there are goodness,
+peace, and truth, wherever Agnes is; and that the soft light of the
+coloured window in the church, seen long ago, falls on her always, and
+on me when I am near her, and on everything around.
+
+The time having come for her withdrawal for the night, and she having
+left us, I gave Mr. Wickfield my hand, preparatory to going away myself.
+But he checked me and said: 'Should you like to stay with us, Trotwood,
+or to go elsewhere?'
+
+'To stay,' I answered, quickly.
+
+'You are sure?'
+
+'If you please. If I may!'
+
+'Why, it's but a dull life that we lead here, boy, I am afraid,' he
+said.
+
+'Not more dull for me than Agnes, sir. Not dull at all!'
+
+'Than Agnes,' he repeated, walking slowly to the great chimney-piece,
+and leaning against it. 'Than Agnes!'
+
+He had drank wine that evening (or I fancied it), until his eyes were
+bloodshot. Not that I could see them now, for they were cast down, and
+shaded by his hand; but I had noticed them a little while before.
+
+'Now I wonder,' he muttered, 'whether my Agnes tires of me. When should
+I ever tire of her! But that's different, that's quite different.'
+
+He was musing, not speaking to me; so I remained quiet.
+
+'A dull old house,' he said, 'and a monotonous life; but I must have
+her near me. I must keep her near me. If the thought that I may die and
+leave my darling, or that my darling may die and leave me, comes like a
+spectre, to distress my happiest hours, and is only to be drowned in--'
+
+He did not supply the word; but pacing slowly to the place where he had
+sat, and mechanically going through the action of pouring wine from the
+empty decanter, set it down and paced back again.
+
+'If it is miserable to bear, when she is here,' he said, 'what would it
+be, and she away? No, no, no. I cannot try that.'
+
+He leaned against the chimney-piece, brooding so long that I could not
+decide whether to run the risk of disturbing him by going, or to remain
+quietly where I was, until he should come out of his reverie. At length
+he aroused himself, and looked about the room until his eyes encountered
+mine.
+
+'Stay with us, Trotwood, eh?' he said in his usual manner, and as if
+he were answering something I had just said. 'I am glad of it. You are
+company to us both. It is wholesome to have you here. Wholesome for me,
+wholesome for Agnes, wholesome perhaps for all of us.'
+
+'I am sure it is for me, sir,' I said. 'I am so glad to be here.'
+
+'That's a fine fellow!' said Mr. Wickfield. 'As long as you are glad
+to be here, you shall stay here.' He shook hands with me upon it, and
+clapped me on the back; and told me that when I had anything to do
+at night after Agnes had left us, or when I wished to read for my own
+pleasure, I was free to come down to his room, if he were there and if
+I desired it for company's sake, and to sit with him. I thanked him for
+his consideration; and, as he went down soon afterwards, and I was
+not tired, went down too, with a book in my hand, to avail myself, for
+half-an-hour, of his permission.
+
+But, seeing a light in the little round office, and immediately feeling
+myself attracted towards Uriah Heep, who had a sort of fascination for
+me, I went in there instead. I found Uriah reading a great fat book,
+with such demonstrative attention, that his lank forefinger followed up
+every line as he read, and made clammy tracks along the page (or so I
+fully believed) like a snail.
+
+'You are working late tonight, Uriah,' says I.
+
+'Yes, Master Copperfield,' says Uriah.
+
+As I was getting on the stool opposite, to talk to him more
+conveniently, I observed that he had not such a thing as a smile about
+him, and that he could only widen his mouth and make two hard creases
+down his cheeks, one on each side, to stand for one.
+
+'I am not doing office-work, Master Copperfield,' said Uriah.
+
+'What work, then?' I asked.
+
+'I am improving my legal knowledge, Master Copperfield,' said Uriah. 'I
+am going through Tidd's Practice. Oh, what a writer Mr. Tidd is, Master
+Copperfield!'
+
+My stool was such a tower of observation, that as I watched him reading
+on again, after this rapturous exclamation, and following up the lines
+with his forefinger, I observed that his nostrils, which were thin and
+pointed, with sharp dints in them, had a singular and most uncomfortable
+way of expanding and contracting themselves--that they seemed to twinkle
+instead of his eyes, which hardly ever twinkled at all.
+
+'I suppose you are quite a great lawyer?' I said, after looking at him
+for some time.
+
+'Me, Master Copperfield?' said Uriah. 'Oh, no! I'm a very umble person.'
+
+It was no fancy of mine about his hands, I observed; for he frequently
+ground the palms against each other as if to squeeze them dry and
+warm, besides often wiping them, in a stealthy way, on his
+pocket-handkerchief.
+
+'I am well aware that I am the umblest person going,' said Uriah Heep,
+modestly; 'let the other be where he may. My mother is likewise a very
+umble person. We live in a numble abode, Master Copperfield, but have
+much to be thankful for. My father's former calling was umble. He was a
+sexton.'
+
+'What is he now?' I asked.
+
+'He is a partaker of glory at present, Master Copperfield,' said Uriah
+Heep. 'But we have much to be thankful for. How much have I to be
+thankful for in living with Mr. Wickfield!'
+
+I asked Uriah if he had been with Mr. Wickfield long?
+
+'I have been with him, going on four year, Master Copperfield,' said
+Uriah; shutting up his book, after carefully marking the place where he
+had left off. 'Since a year after my father's death. How much have I
+to be thankful for, in that! How much have I to be thankful for, in Mr.
+Wickfield's kind intention to give me my articles, which would otherwise
+not lay within the umble means of mother and self!'
+
+'Then, when your articled time is over, you'll be a regular lawyer, I
+suppose?' said I.
+
+'With the blessing of Providence, Master Copperfield,' returned Uriah.
+
+'Perhaps you'll be a partner in Mr. Wickfield's business, one of these
+days,' I said, to make myself agreeable; 'and it will be Wickfield and
+Heep, or Heep late Wickfield.'
+
+'Oh no, Master Copperfield,' returned Uriah, shaking his head, 'I am
+much too umble for that!'
+
+He certainly did look uncommonly like the carved face on the beam
+outside my window, as he sat, in his humility, eyeing me sideways, with
+his mouth widened, and the creases in his cheeks.
+
+'Mr. Wickfield is a most excellent man, Master Copperfield,' said Uriah.
+'If you have known him long, you know it, I am sure, much better than I
+can inform you.'
+
+I replied that I was certain he was; but that I had not known him long
+myself, though he was a friend of my aunt's.
+
+'Oh, indeed, Master Copperfield,' said Uriah. 'Your aunt is a sweet
+lady, Master Copperfield!'
+
+He had a way of writhing when he wanted to express enthusiasm, which was
+very ugly; and which diverted my attention from the compliment he had
+paid my relation, to the snaky twistings of his throat and body.
+
+'A sweet lady, Master Copperfield!' said Uriah Heep. 'She has a great
+admiration for Miss Agnes, Master Copperfield, I believe?'
+
+I said, 'Yes,' boldly; not that I knew anything about it, Heaven forgive
+me!
+
+'I hope you have, too, Master Copperfield,' said Uriah. 'But I am sure
+you must have.'
+
+'Everybody must have,' I returned.
+
+'Oh, thank you, Master Copperfield,' said Uriah Heep, 'for that remark!
+It is so true! Umble as I am, I know it is so true! Oh, thank you,
+Master Copperfield!' He writhed himself quite off his stool in the
+excitement of his feelings, and, being off, began to make arrangements
+for going home.
+
+'Mother will be expecting me,' he said, referring to a pale,
+inexpressive-faced watch in his pocket, 'and getting uneasy; for though
+we are very umble, Master Copperfield, we are much attached to one
+another. If you would come and see us, any afternoon, and take a cup of
+tea at our lowly dwelling, mother would be as proud of your company as I
+should be.'
+
+I said I should be glad to come.
+
+'Thank you, Master Copperfield,' returned Uriah, putting his book
+away upon the shelf--'I suppose you stop here, some time, Master
+Copperfield?'
+
+I said I was going to be brought up there, I believed, as long as I
+remained at school.
+
+'Oh, indeed!' exclaimed Uriah. 'I should think YOU would come into the
+business at last, Master Copperfield!'
+
+I protested that I had no views of that sort, and that no such scheme
+was entertained in my behalf by anybody; but Uriah insisted on blandly
+replying to all my assurances, 'Oh, yes, Master Copperfield, I should
+think you would, indeed!' and, 'Oh, indeed, Master Copperfield, I should
+think you would, certainly!' over and over again. Being, at last, ready
+to leave the office for the night, he asked me if it would suit my
+convenience to have the light put out; and on my answering 'Yes,'
+instantly extinguished it. After shaking hands with me--his hand felt
+like a fish, in the dark--he opened the door into the street a very
+little, and crept out, and shut it, leaving me to grope my way back into
+the house: which cost me some trouble and a fall over his stool. This
+was the proximate cause, I suppose, of my dreaming about him, for what
+appeared to me to be half the night; and dreaming, among other things,
+that he had launched Mr. Peggotty's house on a piratical expedition,
+with a black flag at the masthead, bearing the inscription 'Tidd's
+Practice', under which diabolical ensign he was carrying me and little
+Em'ly to the Spanish Main, to be drowned.
+
+I got a little the better of my uneasiness when I went to school
+next day, and a good deal the better next day, and so shook it off by
+degrees, that in less than a fortnight I was quite at home, and happy,
+among my new companions. I was awkward enough in their games, and
+backward enough in their studies; but custom would improve me in the
+first respect, I hoped, and hard work in the second. Accordingly, I
+went to work very hard, both in play and in earnest, and gained great
+commendation. And, in a very little while, the Murdstone and Grinby life
+became so strange to me that I hardly believed in it, while my present
+life grew so familiar, that I seemed to have been leading it a long
+time.
+
+Doctor Strong's was an excellent school; as different from Mr. Creakle's
+as good is from evil. It was very gravely and decorously ordered, and
+on a sound system; with an appeal, in everything, to the honour and good
+faith of the boys, and an avowed intention to rely on their possession
+of those qualities unless they proved themselves unworthy of it, which
+worked wonders. We all felt that we had a part in the management of
+the place, and in sustaining its character and dignity. Hence, we soon
+became warmly attached to it--I am sure I did for one, and I never knew,
+in all my time, of any other boy being otherwise--and learnt with a good
+will, desiring to do it credit. We had noble games out of hours, and
+plenty of liberty; but even then, as I remember, we were well spoken of
+in the town, and rarely did any disgrace, by our appearance or manner,
+to the reputation of Doctor Strong and Doctor Strong's boys.
+
+Some of the higher scholars boarded in the Doctor's house, and through
+them I learned, at second hand, some particulars of the Doctor's
+history--as, how he had not yet been married twelve months to the
+beautiful young lady I had seen in the study, whom he had married for
+love; for she had not a sixpence, and had a world of poor relations (so
+our fellows said) ready to swarm the Doctor out of house and home. Also,
+how the Doctor's cogitating manner was attributable to his being always
+engaged in looking out for Greek roots; which, in my innocence and
+ignorance, I supposed to be a botanical furor on the Doctor's part,
+especially as he always looked at the ground when he walked about,
+until I understood that they were roots of words, with a view to a new
+Dictionary which he had in contemplation. Adams, our head-boy, who had
+a turn for mathematics, had made a calculation, I was informed, of the
+time this Dictionary would take in completing, on the Doctor's plan, and
+at the Doctor's rate of going. He considered that it might be done
+in one thousand six hundred and forty-nine years, counting from the
+Doctor's last, or sixty-second, birthday.
+
+But the Doctor himself was the idol of the whole school: and it must
+have been a badly composed school if he had been anything else, for
+he was the kindest of men; with a simple faith in him that might have
+touched the stone hearts of the very urns upon the wall. As he walked up
+and down that part of the courtyard which was at the side of the house,
+with the stray rooks and jackdaws looking after him with their heads
+cocked slyly, as if they knew how much more knowing they were in worldly
+affairs than he, if any sort of vagabond could only get near enough to
+his creaking shoes to attract his attention to one sentence of a tale
+of distress, that vagabond was made for the next two days. It was so
+notorious in the house, that the masters and head-boys took pains to cut
+these marauders off at angles, and to get out of windows, and turn them
+out of the courtyard, before they could make the Doctor aware of their
+presence; which was sometimes happily effected within a few yards of
+him, without his knowing anything of the matter, as he jogged to and
+fro. Outside his own domain, and unprotected, he was a very sheep for
+the shearers. He would have taken his gaiters off his legs, to give
+away. In fact, there was a story current among us (I have no idea, and
+never had, on what authority, but I have believed it for so many
+years that I feel quite certain it is true), that on a frosty day, one
+winter-time, he actually did bestow his gaiters on a beggar-woman, who
+occasioned some scandal in the neighbourhood by exhibiting a fine infant
+from door to door, wrapped in those garments, which were universally
+recognized, being as well known in the vicinity as the Cathedral. The
+legend added that the only person who did not identify them was the
+Doctor himself, who, when they were shortly afterwards displayed at the
+door of a little second-hand shop of no very good repute, where such
+things were taken in exchange for gin, was more than once observed to
+handle them approvingly, as if admiring some curious novelty in the
+pattern, and considering them an improvement on his own.
+
+It was very pleasant to see the Doctor with his pretty young wife. He
+had a fatherly, benignant way of showing his fondness for her, which
+seemed in itself to express a good man. I often saw them walking in the
+garden where the peaches were, and I sometimes had a nearer observation
+of them in the study or the parlour. She appeared to me to take great
+care of the Doctor, and to like him very much, though I never thought
+her vitally interested in the Dictionary: some cumbrous fragments of
+which work the Doctor always carried in his pockets, and in the lining
+of his hat, and generally seemed to be expounding to her as they walked
+about.
+
+I saw a good deal of Mrs. Strong, both because she had taken a liking
+for me on the morning of my introduction to the Doctor, and was always
+afterwards kind to me, and interested in me; and because she was very
+fond of Agnes, and was often backwards and forwards at our house. There
+was a curious constraint between her and Mr. Wickfield, I thought (of
+whom she seemed to be afraid), that never wore off. When she came there
+of an evening, she always shrunk from accepting his escort home, and ran
+away with me instead. And sometimes, as we were running gaily across
+the Cathedral yard together, expecting to meet nobody, we would meet Mr.
+Jack Maldon, who was always surprised to see us.
+
+Mrs. Strong's mama was a lady I took great delight in. Her name was Mrs.
+Markleham; but our boys used to call her the Old Soldier, on account of
+her generalship, and the skill with which she marshalled great forces
+of relations against the Doctor. She was a little, sharp-eyed woman,
+who used to wear, when she was dressed, one unchangeable cap, ornamented
+with some artificial flowers, and two artificial butterflies supposed
+to be hovering above the flowers. There was a superstition among us
+that this cap had come from France, and could only originate in the
+workmanship of that ingenious nation: but all I certainly know about it,
+is, that it always made its appearance of an evening, wheresoever Mrs.
+Markleham made HER appearance; that it was carried about to friendly
+meetings in a Hindoo basket; that the butterflies had the gift of
+trembling constantly; and that they improved the shining hours at Doctor
+Strong's expense, like busy bees.
+
+I observed the Old Soldier--not to adopt the name disrespectfully--to
+pretty good advantage, on a night which is made memorable to me by
+something else I shall relate. It was the night of a little party at the
+Doctor's, which was given on the occasion of Mr. Jack Maldon's departure
+for India, whither he was going as a cadet, or something of that kind:
+Mr. Wickfield having at length arranged the business. It happened to be
+the Doctor's birthday, too. We had had a holiday, had made presents to
+him in the morning, had made a speech to him through the head-boy, and
+had cheered him until we were hoarse, and until he had shed tears. And
+now, in the evening, Mr. Wickfield, Agnes, and I, went to have tea with
+him in his private capacity.
+
+Mr. Jack Maldon was there, before us. Mrs. Strong, dressed in white,
+with cherry-coloured ribbons, was playing the piano, when we went in;
+and he was leaning over her to turn the leaves. The clear red and
+white of her complexion was not so blooming and flower-like as usual, I
+thought, when she turned round; but she looked very pretty, Wonderfully
+pretty.
+
+'I have forgotten, Doctor,' said Mrs. Strong's mama, when we were
+seated, 'to pay you the compliments of the day--though they are, as you
+may suppose, very far from being mere compliments in my case. Allow me
+to wish you many happy returns.'
+
+'I thank you, ma'am,' replied the Doctor.
+
+'Many, many, many, happy returns,' said the Old Soldier. 'Not only
+for your own sake, but for Annie's, and John Maldon's, and many other
+people's. It seems but yesterday to me, John, when you were a little
+creature, a head shorter than Master Copperfield, making baby love to
+Annie behind the gooseberry bushes in the back-garden.'
+
+'My dear mama,' said Mrs. Strong, 'never mind that now.'
+
+'Annie, don't be absurd,' returned her mother. 'If you are to blush to
+hear of such things now you are an old married woman, when are you not
+to blush to hear of them?'
+
+'Old?' exclaimed Mr. Jack Maldon. 'Annie? Come!'
+
+'Yes, John,' returned the Soldier. 'Virtually, an old married woman.
+Although not old by years--for when did you ever hear me say, or who has
+ever heard me say, that a girl of twenty was old by years!--your cousin
+is the wife of the Doctor, and, as such, what I have described her. It
+is well for you, John, that your cousin is the wife of the Doctor. You
+have found in him an influential and kind friend, who will be kinder
+yet, I venture to predict, if you deserve it. I have no false pride.
+I never hesitate to admit, frankly, that there are some members of our
+family who want a friend. You were one yourself, before your cousin's
+influence raised up one for you.'
+
+The Doctor, in the goodness of his heart, waved his hand as if to make
+light of it, and save Mr. Jack Maldon from any further reminder. But
+Mrs. Markleham changed her chair for one next the Doctor's, and putting
+her fan on his coat-sleeve, said:
+
+'No, really, my dear Doctor, you must excuse me if I appear to dwell
+on this rather, because I feel so very strongly. I call it quite my
+monomania, it is such a subject of mine. You are a blessing to us. You
+really are a Boon, you know.'
+
+'Nonsense, nonsense,' said the Doctor.
+
+'No, no, I beg your pardon,' retorted the Old Soldier. 'With nobody
+present, but our dear and confidential friend Mr. Wickfield, I cannot
+consent to be put down. I shall begin to assert the privileges of a
+mother-in-law, if you go on like that, and scold you. I am perfectly
+honest and outspoken. What I am saying, is what I said when you first
+overpowered me with surprise--you remember how surprised I was?--by
+proposing for Annie. Not that there was anything so very much out of
+the way, in the mere fact of the proposal--it would be ridiculous to say
+that!--but because, you having known her poor father, and having known
+her from a baby six months old, I hadn't thought of you in such a light
+at all, or indeed as a marrying man in any way,--simply that, you know.'
+
+'Aye, aye,' returned the Doctor, good-humouredly. 'Never mind.'
+
+'But I DO mind,' said the Old Soldier, laying her fan upon his lips. 'I
+mind very much. I recall these things that I may be contradicted if I am
+wrong. Well! Then I spoke to Annie, and I told her what had happened.
+I said, "My dear, here's Doctor Strong has positively been and made you
+the subject of a handsome declaration and an offer." Did I press it in
+the least? No. I said, "Now, Annie, tell me the truth this moment; is
+your heart free?" "Mama," she said crying, "I am extremely young"--which
+was perfectly true--"and I hardly know if I have a heart at all." "Then,
+my dear," I said, "you may rely upon it, it's free. At all events, my
+love," said I, "Doctor Strong is in an agitated state of mind, and
+must be answered. He cannot be kept in his present state of suspense."
+"Mama," said Annie, still crying, "would he be unhappy without me? If he
+would, I honour and respect him so much, that I think I will have him."
+So it was settled. And then, and not till then, I said to Annie, "Annie,
+Doctor Strong will not only be your husband, but he will represent your
+late father: he will represent the head of our family, he will represent
+the wisdom and station, and I may say the means, of our family; and will
+be, in short, a Boon to it." I used the word at the time, and I have
+used it again, today. If I have any merit it is consistency.'
+
+The daughter had sat quite silent and still during this speech, with her
+eyes fixed on the ground; her cousin standing near her, and looking on
+the ground too. She now said very softly, in a trembling voice:
+
+'Mama, I hope you have finished?' 'No, my dear Annie,' returned the Old
+Soldier, 'I have not quite finished. Since you ask me, my love, I reply
+that I have not. I complain that you really are a little unnatural
+towards your own family; and, as it is of no use complaining to you. I
+mean to complain to your husband. Now, my dear Doctor, do look at that
+silly wife of yours.'
+
+As the Doctor turned his kind face, with its smile of simplicity and
+gentleness, towards her, she drooped her head more. I noticed that Mr.
+Wickfield looked at her steadily.
+
+'When I happened to say to that naughty thing, the other day,' pursued
+her mother, shaking her head and her fan at her, playfully, 'that there
+was a family circumstance she might mention to you--indeed, I think, was
+bound to mention--she said, that to mention it was to ask a favour;
+and that, as you were too generous, and as for her to ask was always to
+have, she wouldn't.'
+
+'Annie, my dear,' said the Doctor. 'That was wrong. It robbed me of a
+pleasure.'
+
+'Almost the very words I said to her!' exclaimed her mother. 'Now
+really, another time, when I know what she would tell you but for this
+reason, and won't, I have a great mind, my dear Doctor, to tell you
+myself.'
+
+'I shall be glad if you will,' returned the Doctor.
+
+'Shall I?'
+
+'Certainly.'
+
+'Well, then, I will!' said the Old Soldier. 'That's a bargain.' And
+having, I suppose, carried her point, she tapped the Doctor's hand
+several times with her fan (which she kissed first), and returned
+triumphantly to her former station.
+
+Some more company coming in, among whom were the two masters and Adams,
+the talk became general; and it naturally turned on Mr. Jack Maldon, and
+his voyage, and the country he was going to, and his various plans and
+prospects. He was to leave that night, after supper, in a post-chaise,
+for Gravesend; where the ship, in which he was to make the voyage, lay;
+and was to be gone--unless he came home on leave, or for his health--I
+don't know how many years. I recollect it was settled by general
+consent that India was quite a misrepresented country, and had nothing
+objectionable in it, but a tiger or two, and a little heat in the warm
+part of the day. For my own part, I looked on Mr. Jack Maldon as a
+modern Sindbad, and pictured him the bosom friend of all the Rajahs in
+the East, sitting under canopies, smoking curly golden pipes--a mile
+long, if they could be straightened out.
+
+Mrs. Strong was a very pretty singer: as I knew, who often heard her
+singing by herself. But, whether she was afraid of singing before
+people, or was out of voice that evening, it was certain that she
+couldn't sing at all. She tried a duet, once, with her cousin Maldon,
+but could not so much as begin; and afterwards, when she tried to sing
+by herself, although she began sweetly, her voice died away on a sudden,
+and left her quite distressed, with her head hanging down over the keys.
+The good Doctor said she was nervous, and, to relieve her, proposed a
+round game at cards; of which he knew as much as of the art of playing
+the trombone. But I remarked that the Old Soldier took him into custody
+directly, for her partner; and instructed him, as the first preliminary
+of initiation, to give her all the silver he had in his pocket.
+
+We had a merry game, not made the less merry by the Doctor's mistakes,
+of which he committed an innumerable quantity, in spite of the
+watchfulness of the butterflies, and to their great aggravation. Mrs.
+Strong had declined to play, on the ground of not feeling very well; and
+her cousin Maldon had excused himself because he had some packing to
+do. When he had done it, however, he returned, and they sat together,
+talking, on the sofa. From time to time she came and looked over the
+Doctor's hand, and told him what to play. She was very pale, as she
+bent over him, and I thought her finger trembled as she pointed out
+the cards; but the Doctor was quite happy in her attention, and took no
+notice of this, if it were so.
+
+At supper, we were hardly so gay. Everyone appeared to feel that a
+parting of that sort was an awkward thing, and that the nearer it
+approached, the more awkward it was. Mr. Jack Maldon tried to be very
+talkative, but was not at his ease, and made matters worse. And they
+were not improved, as it appeared to me, by the Old Soldier: who
+continually recalled passages of Mr. Jack Maldon's youth.
+
+The Doctor, however, who felt, I am sure, that he was making everybody
+happy, was well pleased, and had no suspicion but that we were all at
+the utmost height of enjoyment.
+
+'Annie, my dear,' said he, looking at his watch, and filling his glass,
+'it is past your cousin jack's time, and we must not detain him, since
+time and tide--both concerned in this case--wait for no man. Mr. Jack
+Maldon, you have a long voyage, and a strange country, before you; but
+many men have had both, and many men will have both, to the end of time.
+The winds you are going to tempt, have wafted thousands upon thousands
+to fortune, and brought thousands upon thousands happily back.'
+
+'It's an affecting thing,' said Mrs. Markleham--'however it's viewed,
+it's affecting, to see a fine young man one has known from an infant,
+going away to the other end of the world, leaving all he knows behind,
+and not knowing what's before him. A young man really well deserves
+constant support and patronage,' looking at the Doctor, 'who makes such
+sacrifices.'
+
+'Time will go fast with you, Mr. Jack Maldon,' pursued the Doctor,
+'and fast with all of us. Some of us can hardly expect, perhaps, in the
+natural course of things, to greet you on your return. The next best
+thing is to hope to do it, and that's my case. I shall not weary you
+with good advice. You have long had a good model before you, in your
+cousin Annie. Imitate her virtues as nearly as you can.'
+
+Mrs. Markleham fanned herself, and shook her head.
+
+'Farewell, Mr. Jack,' said the Doctor, standing up; on which we all
+stood up. 'A prosperous voyage out, a thriving career abroad, and a
+happy return home!'
+
+We all drank the toast, and all shook hands with Mr. Jack Maldon; after
+which he hastily took leave of the ladies who were there, and hurried
+to the door, where he was received, as he got into the chaise, with a
+tremendous broadside of cheers discharged by our boys, who had assembled
+on the lawn for the purpose. Running in among them to swell the ranks,
+I was very near the chaise when it rolled away; and I had a lively
+impression made upon me, in the midst of the noise and dust, of having
+seen Mr. Jack Maldon rattle past with an agitated face, and something
+cherry-coloured in his hand.
+
+After another broadside for the Doctor, and another for the Doctor's
+wife, the boys dispersed, and I went back into the house, where I found
+the guests all standing in a group about the Doctor, discussing how Mr.
+Jack Maldon had gone away, and how he had borne it, and how he had
+felt it, and all the rest of it. In the midst of these remarks, Mrs.
+Markleham cried: 'Where's Annie?'
+
+No Annie was there; and when they called to her, no Annie replied. But
+all pressing out of the room, in a crowd, to see what was the matter, we
+found her lying on the hall floor. There was great alarm at first, until
+it was found that she was in a swoon, and that the swoon was yielding
+to the usual means of recovery; when the Doctor, who had lifted her
+head upon his knee, put her curls aside with his hand, and said, looking
+around:
+
+'Poor Annie! She's so faithful and tender-hearted! It's the parting from
+her old playfellow and friend--her favourite cousin--that has done this.
+Ah! It's a pity! I am very sorry!'
+
+When she opened her eyes, and saw where she was, and that we were all
+standing about her, she arose with assistance: turning her head, as she
+did so, to lay it on the Doctor's shoulder--or to hide it, I don't know
+which. We went into the drawing-room, to leave her with the Doctor and
+her mother; but she said, it seemed, that she was better than she had
+been since morning, and that she would rather be brought among us; so
+they brought her in, looking very white and weak, I thought, and sat her
+on a sofa.
+
+'Annie, my dear,' said her mother, doing something to her dress. 'See
+here! You have lost a bow. Will anybody be so good as find a ribbon; a
+cherry-coloured ribbon?'
+
+It was the one she had worn at her bosom. We all looked for it; I myself
+looked everywhere, I am certain--but nobody could find it.
+
+'Do you recollect where you had it last, Annie?' said her mother.
+
+I wondered how I could have thought she looked white, or anything but
+burning red, when she answered that she had had it safe, a little while
+ago, she thought, but it was not worth looking for.
+
+Nevertheless, it was looked for again, and still not found. She
+entreated that there might be no more searching; but it was still sought
+for, in a desultory way, until she was quite well, and the company took
+their departure.
+
+We walked very slowly home, Mr. Wickfield, Agnes, and I--Agnes and I
+admiring the moonlight, and Mr. Wickfield scarcely raising his eyes from
+the ground. When we, at last, reached our own door, Agnes discovered
+that she had left her little reticule behind. Delighted to be of any
+service to her, I ran back to fetch it.
+
+I went into the supper-room where it had been left, which was deserted
+and dark. But a door of communication between that and the Doctor's
+study, where there was a light, being open, I passed on there, to say
+what I wanted, and to get a candle.
+
+The Doctor was sitting in his easy-chair by the fireside, and his young
+wife was on a stool at his feet. The Doctor, with a complacent smile,
+was reading aloud some manuscript explanation or statement of a theory
+out of that interminable Dictionary, and she was looking up at him. But
+with such a face as I never saw. It was so beautiful in its form, it was
+so ashy pale, it was so fixed in its abstraction, it was so full of a
+wild, sleep-walking, dreamy horror of I don't know what. The eyes
+were wide open, and her brown hair fell in two rich clusters on her
+shoulders, and on her white dress, disordered by the want of the lost
+ribbon. Distinctly as I recollect her look, I cannot say of what it was
+expressive, I cannot even say of what it is expressive to me now, rising
+again before my older judgement. Penitence, humiliation, shame, pride,
+love, and trustfulness--I see them all; and in them all, I see that
+horror of I don't know what.
+
+My entrance, and my saying what I wanted, roused her. It disturbed the
+Doctor too, for when I went back to replace the candle I had taken from
+the table, he was patting her head, in his fatherly way, and saying he
+was a merciless drone to let her tempt him into reading on; and he would
+have her go to bed.
+
+But she asked him, in a rapid, urgent manner, to let her stay--to let
+her feel assured (I heard her murmur some broken words to this effect)
+that she was in his confidence that night. And, as she turned again
+towards him, after glancing at me as I left the room and went out at the
+door, I saw her cross her hands upon his knee, and look up at him with
+the same face, something quieted, as he resumed his reading.
+
+It made a great impression on me, and I remembered it a long time
+afterwards; as I shall have occasion to narrate when the time comes.
+
+
+
+CHAPTER 17. SOMEBODY TURNS UP
+
+
+It has not occurred to me to mention Peggotty since I ran away; but, of
+course, I wrote her a letter almost as soon as I was housed at Dover,
+and another, and a longer letter, containing all particulars fully
+related, when my aunt took me formally under her protection. On my being
+settled at Doctor Strong's I wrote to her again, detailing my happy
+condition and prospects. I never could have derived anything like the
+pleasure from spending the money Mr. Dick had given me, that I felt in
+sending a gold half-guinea to Peggotty, per post, enclosed in this last
+letter, to discharge the sum I had borrowed of her: in which epistle,
+not before, I mentioned about the young man with the donkey-cart.
+
+To these communications Peggotty replied as promptly, if not as
+concisely, as a merchant's clerk. Her utmost powers of expression (which
+were certainly not great in ink) were exhausted in the attempt to write
+what she felt on the subject of my journey. Four sides of incoherent and
+interjectional beginnings of sentences, that had no end, except blots,
+were inadequate to afford her any relief. But the blots were more
+expressive to me than the best composition; for they showed me that
+Peggotty had been crying all over the paper, and what could I have
+desired more?
+
+I made out, without much difficulty, that she could not take quite
+kindly to my aunt yet. The notice was too short after so long a
+prepossession the other way. We never knew a person, she wrote; but to
+think that Miss Betsey should seem to be so different from what she had
+been thought to be, was a Moral!--that was her word. She was evidently
+still afraid of Miss Betsey, for she sent her grateful duty to her but
+timidly; and she was evidently afraid of me, too, and entertained the
+probability of my running away again soon: if I might judge from the
+repeated hints she threw out, that the coach-fare to Yarmouth was always
+to be had of her for the asking.
+
+She gave me one piece of intelligence which affected me very much,
+namely, that there had been a sale of the furniture at our old home, and
+that Mr. and Miss Murdstone were gone away, and the house was shut up,
+to be let or sold. God knows I had no part in it while they remained
+there, but it pained me to think of the dear old place as altogether
+abandoned; of the weeds growing tall in the garden, and the fallen
+leaves lying thick and wet upon the paths. I imagined how the winds
+of winter would howl round it, how the cold rain would beat upon the
+window-glass, how the moon would make ghosts on the walls of the empty
+rooms, watching their solitude all night. I thought afresh of the grave
+in the churchyard, underneath the tree: and it seemed as if the house
+were dead too, now, and all connected with my father and mother were
+faded away.
+
+There was no other news in Peggotty's letters. Mr. Barkis was an
+excellent husband, she said, though still a little near; but we all had
+our faults, and she had plenty (though I am sure I don't know what they
+were); and he sent his duty, and my little bedroom was always ready for
+me. Mr. Peggotty was well, and Ham was well, and Mrs.. Gummidge was but
+poorly, and little Em'ly wouldn't send her love, but said that Peggotty
+might send it, if she liked.
+
+All this intelligence I dutifully imparted to my aunt, only reserving
+to myself the mention of little Em'ly, to whom I instinctively felt
+that she would not very tenderly incline. While I was yet new at Doctor
+Strong's, she made several excursions over to Canterbury to see me, and
+always at unseasonable hours: with the view, I suppose, of taking me by
+surprise. But, finding me well employed, and bearing a good character,
+and hearing on all hands that I rose fast in the school, she soon
+discontinued these visits. I saw her on a Saturday, every third or
+fourth week, when I went over to Dover for a treat; and I saw Mr. Dick
+every alternate Wednesday, when he arrived by stage-coach at noon, to
+stay until next morning.
+
+On these occasions Mr. Dick never travelled without a leathern
+writing-desk, containing a supply of stationery and the Memorial; in
+relation to which document he had a notion that time was beginning to
+press now, and that it really must be got out of hand.
+
+Mr. Dick was very partial to gingerbread. To render his visits the more
+agreeable, my aunt had instructed me to open a credit for him at a cake
+shop, which was hampered with the stipulation that he should not be
+served with more than one shilling's-worth in the course of any one day.
+This, and the reference of all his little bills at the county inn where
+he slept, to my aunt, before they were paid, induced me to suspect that
+he was only allowed to rattle his money, and not to spend it. I found
+on further investigation that this was so, or at least there was an
+agreement between him and my aunt that he should account to her for
+all his disbursements. As he had no idea of deceiving her, and always
+desired to please her, he was thus made chary of launching into expense.
+On this point, as well as on all other possible points, Mr. Dick was
+convinced that my aunt was the wisest and most wonderful of women; as he
+repeatedly told me with infinite secrecy, and always in a whisper.
+
+'Trotwood,' said Mr. Dick, with an air of mystery, after imparting this
+confidence to me, one Wednesday; 'who's the man that hides near our
+house and frightens her?'
+
+'Frightens my aunt, sir?'
+
+Mr. Dick nodded. 'I thought nothing would have frightened her,' he said,
+'for she's--' here he whispered softly, 'don't mention it--the wisest
+and most wonderful of women.' Having said which, he drew back, to
+observe the effect which this description of her made upon me.
+
+'The first time he came,' said Mr. Dick, 'was--let me see--sixteen
+hundred and forty-nine was the date of King Charles's execution. I think
+you said sixteen hundred and forty-nine?'
+
+'Yes, sir.'
+
+'I don't know how it can be,' said Mr. Dick, sorely puzzled and shaking
+his head. 'I don't think I am as old as that.'
+
+'Was it in that year that the man appeared, sir?' I asked.
+
+'Why, really' said Mr. Dick, 'I don't see how it can have been in that
+year, Trotwood. Did you get that date out of history?'
+
+'Yes, sir.'
+
+'I suppose history never lies, does it?' said Mr. Dick, with a gleam of
+hope.
+
+'Oh dear, no, sir!' I replied, most decisively. I was ingenuous and
+young, and I thought so.
+
+'I can't make it out,' said Mr. Dick, shaking his head. 'There's
+something wrong, somewhere. However, it was very soon after the mistake
+was made of putting some of the trouble out of King Charles's head into
+my head, that the man first came. I was walking out with Miss Trotwood
+after tea, just at dark, and there he was, close to our house.'
+
+'Walking about?' I inquired.
+
+'Walking about?' repeated Mr. Dick. 'Let me see, I must recollect a bit.
+N-no, no; he was not walking about.'
+
+I asked, as the shortest way to get at it, what he WAS doing.
+
+'Well, he wasn't there at all,' said Mr. Dick, 'until he came up behind
+her, and whispered. Then she turned round and fainted, and I stood still
+and looked at him, and he walked away; but that he should have
+been hiding ever since (in the ground or somewhere), is the most
+extraordinary thing!'
+
+'HAS he been hiding ever since?' I asked.
+
+'To be sure he has,' retorted Mr. Dick, nodding his head gravely. 'Never
+came out, till last night! We were walking last night, and he came up
+behind her again, and I knew him again.'
+
+'And did he frighten my aunt again?'
+
+'All of a shiver,' said Mr. Dick, counterfeiting that affection and
+making his teeth chatter. 'Held by the palings. Cried. But, Trotwood,
+come here,' getting me close to him, that he might whisper very softly;
+'why did she give him money, boy, in the moonlight?'
+
+'He was a beggar, perhaps.'
+
+Mr. Dick shook his head, as utterly renouncing the suggestion; and
+having replied a great many times, and with great confidence, 'No
+beggar, no beggar, no beggar, sir!' went on to say, that from his window
+he had afterwards, and late at night, seen my aunt give this person
+money outside the garden rails in the moonlight, who then slunk
+away--into the ground again, as he thought probable--and was seen no
+more: while my aunt came hurriedly and secretly back into the house, and
+had, even that morning, been quite different from her usual self; which
+preyed on Mr. Dick's mind.
+
+I had not the least belief, in the outset of this story, that the
+unknown was anything but a delusion of Mr. Dick's, and one of the line
+of that ill-fated Prince who occasioned him so much difficulty; but
+after some reflection I began to entertain the question whether an
+attempt, or threat of an attempt, might have been twice made to take
+poor Mr. Dick himself from under my aunt's protection, and whether
+my aunt, the strength of whose kind feeling towards him I knew from
+herself, might have been induced to pay a price for his peace and quiet.
+As I was already much attached to Mr. Dick, and very solicitous for his
+welfare, my fears favoured this supposition; and for a long time his
+Wednesday hardly ever came round, without my entertaining a misgiving
+that he would not be on the coach-box as usual. There he always
+appeared, however, grey-headed, laughing, and happy; and he never had
+anything more to tell of the man who could frighten my aunt.
+
+These Wednesdays were the happiest days of Mr. Dick's life; they were
+far from being the least happy of mine. He soon became known to every
+boy in the school; and though he never took an active part in any game
+but kite-flying, was as deeply interested in all our sports as anyone
+among us. How often have I seen him, intent upon a match at marbles
+or pegtop, looking on with a face of unutterable interest, and hardly
+breathing at the critical times! How often, at hare and hounds, have
+I seen him mounted on a little knoll, cheering the whole field on
+to action, and waving his hat above his grey head, oblivious of King
+Charles the Martyr's head, and all belonging to it! How many a
+summer hour have I known to be but blissful minutes to him in
+the cricket-field! How many winter days have I seen him, standing
+blue-nosed, in the snow and east wind, looking at the boys going down
+the long slide, and clapping his worsted gloves in rapture!
+
+He was an universal favourite, and his ingenuity in little things was
+transcendent. He could cut oranges into such devices as none of us had
+an idea of. He could make a boat out of anything, from a skewer upwards.
+He could turn cramp-bones into chessmen; fashion Roman chariots from old
+court cards; make spoked wheels out of cotton reels, and bird-cages of
+old wire. But he was greatest of all, perhaps, in the articles of string
+and straw; with which we were all persuaded he could do anything that
+could be done by hands.
+
+Mr. Dick's renown was not long confined to us. After a few Wednesdays,
+Doctor Strong himself made some inquiries of me about him, and I told
+him all my aunt had told me; which interested the Doctor so much that
+he requested, on the occasion of his next visit, to be presented to him.
+This ceremony I performed; and the Doctor begging Mr. Dick, whensoever
+he should not find me at the coach office, to come on there, and rest
+himself until our morning's work was over, it soon passed into a custom
+for Mr. Dick to come on as a matter of course, and, if we were a little
+late, as often happened on a Wednesday, to walk about the courtyard,
+waiting for me. Here he made the acquaintance of the Doctor's beautiful
+young wife (paler than formerly, all this time; more rarely seen by
+me or anyone, I think; and not so gay, but not less beautiful), and so
+became more and more familiar by degrees, until, at last, he would come
+into the school and wait. He always sat in a particular corner, on a
+particular stool, which was called 'Dick', after him; here he would sit,
+with his grey head bent forward, attentively listening to whatever might
+be going on, with a profound veneration for the learning he had never
+been able to acquire.
+
+This veneration Mr. Dick extended to the Doctor, whom he thought the
+most subtle and accomplished philosopher of any age. It was long before
+Mr. Dick ever spoke to him otherwise than bareheaded; and even when he
+and the Doctor had struck up quite a friendship, and would walk together
+by the hour, on that side of the courtyard which was known among us as
+The Doctor's Walk, Mr. Dick would pull off his hat at intervals to show
+his respect for wisdom and knowledge. How it ever came about that the
+Doctor began to read out scraps of the famous Dictionary, in these
+walks, I never knew; perhaps he felt it all the same, at first, as
+reading to himself. However, it passed into a custom too; and Mr. Dick,
+listening with a face shining with pride and pleasure, in his heart of
+hearts believed the Dictionary to be the most delightful book in the
+world.
+
+As I think of them going up and down before those schoolroom
+windows--the Doctor reading with his complacent smile, an occasional
+flourish of the manuscript, or grave motion of his head; and Mr. Dick
+listening, enchained by interest, with his poor wits calmly wandering
+God knows where, upon the wings of hard words--I think of it as one of
+the pleasantest things, in a quiet way, that I have ever seen. I feel
+as if they might go walking to and fro for ever, and the world might
+somehow be the better for it--as if a thousand things it makes a noise
+about, were not one half so good for it, or me.
+
+Agnes was one of Mr. Dick's friends, very soon; and in often coming
+to the house, he made acquaintance with Uriah. The friendship between
+himself and me increased continually, and it was maintained on this odd
+footing: that, while Mr. Dick came professedly to look after me as my
+guardian, he always consulted me in any little matter of doubt that
+arose, and invariably guided himself by my advice; not only having a
+high respect for my native sagacity, but considering that I inherited a
+good deal from my aunt.
+
+One Thursday morning, when I was about to walk with Mr. Dick from the
+hotel to the coach office before going back to school (for we had an
+hour's school before breakfast), I met Uriah in the street, who reminded
+me of the promise I had made to take tea with himself and his mother:
+adding, with a writhe, 'But I didn't expect you to keep it, Master
+Copperfield, we're so very umble.'
+
+I really had not yet been able to make up my mind whether I liked Uriah
+or detested him; and I was very doubtful about it still, as I stood
+looking him in the face in the street. But I felt it quite an affront to
+be supposed proud, and said I only wanted to be asked.
+
+'Oh, if that's all, Master Copperfield,' said Uriah, 'and it really
+isn't our umbleness that prevents you, will you come this evening?
+But if it is our umbleness, I hope you won't mind owning to it, Master
+Copperfield; for we are well aware of our condition.'
+
+I said I would mention it to Mr. Wickfield, and if he approved, as I had
+no doubt he would, I would come with pleasure. So, at six o'clock that
+evening, which was one of the early office evenings, I announced myself
+as ready, to Uriah.
+
+'Mother will be proud, indeed,' he said, as we walked away together. 'Or
+she would be proud, if it wasn't sinful, Master Copperfield.'
+
+'Yet you didn't mind supposing I was proud this morning,' I returned.
+
+'Oh dear, no, Master Copperfield!' returned Uriah. 'Oh, believe me, no!
+Such a thought never came into my head! I shouldn't have deemed it at
+all proud if you had thought US too umble for you. Because we are so
+very umble.'
+
+'Have you been studying much law lately?' I asked, to change the
+subject.
+
+'Oh, Master Copperfield,' he said, with an air of self-denial, 'my
+reading is hardly to be called study. I have passed an hour or two in
+the evening, sometimes, with Mr. Tidd.'
+
+'Rather hard, I suppose?' said I. 'He is hard to me sometimes,' returned
+Uriah. 'But I don't know what he might be to a gifted person.'
+
+After beating a little tune on his chin as he walked on, with the two
+forefingers of his skeleton right hand, he added:
+
+'There are expressions, you see, Master Copperfield--Latin words
+and terms--in Mr. Tidd, that are trying to a reader of my umble
+attainments.'
+
+'Would you like to be taught Latin?' I said briskly. 'I will teach it
+you with pleasure, as I learn it.'
+
+'Oh, thank you, Master Copperfield,' he answered, shaking his head. 'I
+am sure it's very kind of you to make the offer, but I am much too umble
+to accept it.'
+
+'What nonsense, Uriah!'
+
+'Oh, indeed you must excuse me, Master Copperfield! I am greatly
+obliged, and I should like it of all things, I assure you; but I am far
+too umble. There are people enough to tread upon me in my lowly state,
+without my doing outrage to their feelings by possessing learning.
+Learning ain't for me. A person like myself had better not aspire. If he
+is to get on in life, he must get on umbly, Master Copperfield!'
+
+I never saw his mouth so wide, or the creases in his cheeks so deep, as
+when he delivered himself of these sentiments: shaking his head all the
+time, and writhing modestly.
+
+'I think you are wrong, Uriah,' I said. 'I dare say there are several
+things that I could teach you, if you would like to learn them.'
+
+'Oh, I don't doubt that, Master Copperfield,' he answered; 'not in the
+least. But not being umble yourself, you don't judge well, perhaps, for
+them that are. I won't provoke my betters with knowledge, thank you. I'm
+much too umble. Here is my umble dwelling, Master Copperfield!'
+
+We entered a low, old-fashioned room, walked straight into from the
+street, and found there Mrs. Heep, who was the dead image of Uriah, only
+short. She received me with the utmost humility, and apologized to me
+for giving her son a kiss, observing that, lowly as they were, they
+had their natural affections, which they hoped would give no offence to
+anyone. It was a perfectly decent room, half parlour and half kitchen,
+but not at all a snug room. The tea-things were set upon the table, and
+the kettle was boiling on the hob. There was a chest of drawers with an
+escritoire top, for Uriah to read or write at of an evening; there was
+Uriah's blue bag lying down and vomiting papers; there was a company of
+Uriah's books commanded by Mr. Tidd; there was a corner cupboard: and
+there were the usual articles of furniture. I don't remember that any
+individual object had a bare, pinched, spare look; but I do remember
+that the whole place had.
+
+It was perhaps a part of Mrs. Heep's humility, that she still wore
+weeds. Notwithstanding the lapse of time that had occurred since Mr.
+Heep's decease, she still wore weeds. I think there was some compromise
+in the cap; but otherwise she was as weedy as in the early days of her
+mourning.
+
+'This is a day to be remembered, my Uriah, I am sure,' said Mrs. Heep,
+making the tea, 'when Master Copperfield pays us a visit.'
+
+'I said you'd think so, mother,' said Uriah.
+
+'If I could have wished father to remain among us for any reason,' said
+Mrs. Heep, 'it would have been, that he might have known his company
+this afternoon.'
+
+I felt embarrassed by these compliments; but I was sensible, too, of
+being entertained as an honoured guest, and I thought Mrs. Heep an
+agreeable woman.
+
+'My Uriah,' said Mrs. Heep, 'has looked forward to this, sir, a long
+while. He had his fears that our umbleness stood in the way, and I
+joined in them myself. Umble we are, umble we have been, umble we shall
+ever be,' said Mrs. Heep.
+
+'I am sure you have no occasion to be so, ma'am,' I said, 'unless you
+like.'
+
+'Thank you, sir,' retorted Mrs. Heep. 'We know our station and are
+thankful in it.'
+
+I found that Mrs. Heep gradually got nearer to me, and that Uriah
+gradually got opposite to me, and that they respectfully plied me
+with the choicest of the eatables on the table. There was nothing
+particularly choice there, to be sure; but I took the will for the deed,
+and felt that they were very attentive. Presently they began to talk
+about aunts, and then I told them about mine; and about fathers and
+mothers, and then I told them about mine; and then Mrs. Heep began to
+talk about fathers-in-law, and then I began to tell her about mine--but
+stopped, because my aunt had advised me to observe a silence on that
+subject. A tender young cork, however, would have had no more chance
+against a pair of corkscrews, or a tender young tooth against a pair of
+dentists, or a little shuttlecock against two battledores, than I had
+against Uriah and Mrs. Heep. They did just what they liked with me; and
+wormed things out of me that I had no desire to tell, with a certainty
+I blush to think of, the more especially, as in my juvenile frankness, I
+took some credit to myself for being so confidential and felt that I was
+quite the patron of my two respectful entertainers.
+
+They were very fond of one another: that was certain. I take it, that
+had its effect upon me, as a touch of nature; but the skill with which
+the one followed up whatever the other said, was a touch of art which I
+was still less proof against. When there was nothing more to be got
+out of me about myself (for on the Murdstone and Grinby life, and on my
+journey, I was dumb), they began about Mr. Wickfield and Agnes. Uriah
+threw the ball to Mrs. Heep, Mrs. Heep caught it and threw it back to
+Uriah, Uriah kept it up a little while, then sent it back to Mrs. Heep,
+and so they went on tossing it about until I had no idea who had got it,
+and was quite bewildered. The ball itself was always changing too. Now
+it was Mr. Wickfield, now Agnes, now the excellence of Mr. Wickfield,
+now my admiration of Agnes; now the extent of Mr. Wickfield's business
+and resources, now our domestic life after dinner; now, the wine that
+Mr. Wickfield took, the reason why he took it, and the pity that it was
+he took so much; now one thing, now another, then everything at once;
+and all the time, without appearing to speak very often, or to do
+anything but sometimes encourage them a little, for fear they should be
+overcome by their humility and the honour of my company, I found myself
+perpetually letting out something or other that I had no business to
+let out and seeing the effect of it in the twinkling of Uriah's dinted
+nostrils.
+
+I had begun to be a little uncomfortable, and to wish myself well out
+of the visit, when a figure coming down the street passed the door--it
+stood open to air the room, which was warm, the weather being close for
+the time of year--came back again, looked in, and walked in, exclaiming
+loudly, 'Copperfield! Is it possible?'
+
+It was Mr. Micawber! It was Mr. Micawber, with his eye-glass, and
+his walking-stick, and his shirt-collar, and his genteel air, and the
+condescending roll in his voice, all complete!
+
+'My dear Copperfield,' said Mr. Micawber, putting out his hand, 'this is
+indeed a meeting which is calculated to impress the mind with a sense
+of the instability and uncertainty of all human--in short, it is a most
+extraordinary meeting. Walking along the street, reflecting upon the
+probability of something turning up (of which I am at present rather
+sanguine), I find a young but valued friend turn up, who is connected
+with the most eventful period of my life; I may say, with the
+turning-point of my existence. Copperfield, my dear fellow, how do you
+do?'
+
+I cannot say--I really cannot say--that I was glad to see Mr. Micawber
+there; but I was glad to see him too, and shook hands with him,
+heartily, inquiring how Mrs. Micawber was.
+
+'Thank you,' said Mr. Micawber, waving his hand as of old, and settling
+his chin in his shirt-collar. 'She is tolerably convalescent. The twins
+no longer derive their sustenance from Nature's founts--in short,' said
+Mr. Micawber, in one of his bursts of confidence, 'they are weaned--and
+Mrs. Micawber is, at present, my travelling companion. She will be
+rejoiced, Copperfield, to renew her acquaintance with one who has
+proved himself in all respects a worthy minister at the sacred altar of
+friendship.'
+
+I said I should be delighted to see her.
+
+'You are very good,' said Mr. Micawber.
+
+Mr. Micawber then smiled, settled his chin again, and looked about him.
+
+'I have discovered my friend Copperfield,' said Mr. Micawber genteelly,
+and without addressing himself particularly to anyone, 'not in solitude,
+but partaking of a social meal in company with a widow lady, and one who
+is apparently her offspring--in short,' said Mr. Micawber, in another
+of his bursts of confidence, 'her son. I shall esteem it an honour to be
+presented.'
+
+I could do no less, under these circumstances, than make Mr. Micawber
+known to Uriah Heep and his mother; which I accordingly did. As they
+abased themselves before him, Mr. Micawber took a seat, and waved his
+hand in his most courtly manner.
+
+'Any friend of my friend Copperfield's,' said Mr. Micawber, 'has a
+personal claim upon myself.'
+
+'We are too umble, sir,' said Mrs. Heep, 'my son and me, to be the
+friends of Master Copperfield. He has been so good as take his tea with
+us, and we are thankful to him for his company, also to you, sir, for
+your notice.'
+
+'Ma'am,' returned Mr. Micawber, with a bow, 'you are very obliging: and
+what are you doing, Copperfield? Still in the wine trade?'
+
+I was excessively anxious to get Mr. Micawber away; and replied, with my
+hat in my hand, and a very red face, I have no doubt, that I was a pupil
+at Doctor Strong's.
+
+'A pupil?' said Mr. Micawber, raising his eyebrows. 'I am extremely
+happy to hear it. Although a mind like my friend Copperfield's'--to
+Uriah and Mrs. Heep--'does not require that cultivation which, without
+his knowledge of men and things, it would require, still it is a rich
+soil teeming with latent vegetation--in short,' said Mr. Micawber,
+smiling, in another burst of confidence, 'it is an intellect capable of
+getting up the classics to any extent.'
+
+Uriah, with his long hands slowly twining over one another, made a
+ghastly writhe from the waist upwards, to express his concurrence in
+this estimation of me.
+
+'Shall we go and see Mrs. Micawber, sir?' I said, to get Mr. Micawber
+away.
+
+'If you will do her that favour, Copperfield,' replied Mr. Micawber,
+rising. 'I have no scruple in saying, in the presence of our friends
+here, that I am a man who has, for some years, contended against the
+pressure of pecuniary difficulties.' I knew he was certain to say
+something of this kind; he always would be so boastful about his
+difficulties. 'Sometimes I have risen superior to my difficulties.
+Sometimes my difficulties have--in short, have floored me. There have
+been times when I have administered a succession of facers to them;
+there have been times when they have been too many for me, and I have
+given in, and said to Mrs. Micawber, in the words of Cato, "Plato, thou
+reasonest well. It's all up now. I can show fight no more." But at no
+time of my life,' said Mr. Micawber, 'have I enjoyed a higher degree of
+satisfaction than in pouring my griefs (if I may describe difficulties,
+chiefly arising out of warrants of attorney and promissory notes at two
+and four months, by that word) into the bosom of my friend Copperfield.'
+
+Mr. Micawber closed this handsome tribute by saying, 'Mr. Heep! Good
+evening. Mrs. Heep! Your servant,' and then walking out with me in his
+most fashionable manner, making a good deal of noise on the pavement
+with his shoes, and humming a tune as we went.
+
+It was a little inn where Mr. Micawber put up, and he occupied a little
+room in it, partitioned off from the commercial room, and strongly
+flavoured with tobacco-smoke. I think it was over the kitchen, because
+a warm greasy smell appeared to come up through the chinks in the floor,
+and there was a flabby perspiration on the walls. I know it was near the
+bar, on account of the smell of spirits and jingling of glasses. Here,
+recumbent on a small sofa, underneath a picture of a race-horse, with
+her head close to the fire, and her feet pushing the mustard off the
+dumb-waiter at the other end of the room, was Mrs. Micawber, to whom Mr.
+Micawber entered first, saying, 'My dear, allow me to introduce to you a
+pupil of Doctor Strong's.'
+
+I noticed, by the by, that although Mr. Micawber was just as much
+confused as ever about my age and standing, he always remembered, as a
+genteel thing, that I was a pupil of Doctor Strong's.
+
+Mrs. Micawber was amazed, but very glad to see me. I was very glad to
+see her too, and, after an affectionate greeting on both sides, sat down
+on the small sofa near her.
+
+'My dear,' said Mr. Micawber, 'if you will mention to Copperfield what
+our present position is, which I have no doubt he will like to know, I
+will go and look at the paper the while, and see whether anything turns
+up among the advertisements.'
+
+'I thought you were at Plymouth, ma'am,' I said to Mrs. Micawber, as he
+went out.
+
+'My dear Master Copperfield,' she replied, 'we went to Plymouth.'
+
+'To be on the spot,' I hinted.
+
+'Just so,' said Mrs. Micawber. 'To be on the spot. But, the truth is,
+talent is not wanted in the Custom House. The local influence of my
+family was quite unavailing to obtain any employment in that department,
+for a man of Mr. Micawber's abilities. They would rather NOT have a man
+of Mr. Micawber's abilities. He would only show the deficiency of the
+others. Apart from which,' said Mrs. Micawber, 'I will not disguise
+from you, my dear Master Copperfield, that when that branch of my
+family which is settled in Plymouth, became aware that Mr. Micawber was
+accompanied by myself, and by little Wilkins and his sister, and by the
+twins, they did not receive him with that ardour which he might have
+expected, being so newly released from captivity. In fact,' said Mrs.
+Micawber, lowering her voice,--'this is between ourselves--our reception
+was cool.'
+
+'Dear me!' I said.
+
+'Yes,' said Mrs. Micawber. 'It is truly painful to contemplate mankind
+in such an aspect, Master Copperfield, but our reception was, decidedly,
+cool. There is no doubt about it. In fact, that branch of my family
+which is settled in Plymouth became quite personal to Mr. Micawber,
+before we had been there a week.'
+
+I said, and thought, that they ought to be ashamed of themselves.
+
+'Still, so it was,' continued Mrs. Micawber. 'Under such circumstances,
+what could a man of Mr. Micawber's spirit do? But one obvious course
+was left. To borrow, of that branch of my family, the money to return to
+London, and to return at any sacrifice.'
+
+'Then you all came back again, ma'am?' I said.
+
+'We all came back again,' replied Mrs. Micawber. 'Since then, I have
+consulted other branches of my family on the course which it is most
+expedient for Mr. Micawber to take--for I maintain that he must take
+some course, Master Copperfield,' said Mrs. Micawber, argumentatively.
+'It is clear that a family of six, not including a domestic, cannot live
+upon air.'
+
+'Certainly, ma'am,' said I.
+
+'The opinion of those other branches of my family,' pursued Mrs.
+Micawber, 'is, that Mr. Micawber should immediately turn his attention
+to coals.'
+
+'To what, ma'am?'
+
+'To coals,' said Mrs. Micawber. 'To the coal trade. Mr. Micawber was
+induced to think, on inquiry, that there might be an opening for a
+man of his talent in the Medway Coal Trade. Then, as Mr. Micawber very
+properly said, the first step to be taken clearly was, to come and see
+the Medway. Which we came and saw. I say "we", Master Copperfield; for
+I never will,' said Mrs. Micawber with emotion, 'I never will desert Mr.
+Micawber.'
+
+I murmured my admiration and approbation.
+
+'We came,' repeated Mrs. Micawber, 'and saw the Medway. My opinion of
+the coal trade on that river is, that it may require talent, but that
+it certainly requires capital. Talent, Mr. Micawber has; capital, Mr.
+Micawber has not. We saw, I think, the greater part of the Medway; and
+that is my individual conclusion. Being so near here, Mr. Micawber was
+of opinion that it would be rash not to come on, and see the Cathedral.
+Firstly, on account of its being so well worth seeing, and our never
+having seen it; and secondly, on account of the great probability of
+something turning up in a cathedral town. We have been here,' said Mrs.
+Micawber, 'three days. Nothing has, as yet, turned up; and it may
+not surprise you, my dear Master Copperfield, so much as it would a
+stranger, to know that we are at present waiting for a remittance from
+London, to discharge our pecuniary obligations at this hotel. Until the
+arrival of that remittance,' said Mrs. Micawber with much feeling, 'I am
+cut off from my home (I allude to lodgings in Pentonville), from my boy
+and girl, and from my twins.'
+
+I felt the utmost sympathy for Mr. and Mrs. Micawber in this anxious
+extremity, and said as much to Mr. Micawber, who now returned: adding
+that I only wished I had money enough, to lend them the amount they
+needed. Mr. Micawber's answer expressed the disturbance of his mind. He
+said, shaking hands with me, 'Copperfield, you are a true friend; but
+when the worst comes to the worst, no man is without a friend who is
+possessed of shaving materials.' At this dreadful hint Mrs. Micawber
+threw her arms round Mr. Micawber's neck and entreated him to be calm.
+He wept; but so far recovered, almost immediately, as to ring the bell
+for the waiter, and bespeak a hot kidney pudding and a plate of shrimps
+for breakfast in the morning.
+
+When I took my leave of them, they both pressed me so much to come and
+dine before they went away, that I could not refuse. But, as I knew I
+could not come next day, when I should have a good deal to prepare in
+the evening, Mr. Micawber arranged that he would call at Doctor Strong's
+in the course of the morning (having a presentiment that the remittance
+would arrive by that post), and propose the day after, if it would suit
+me better. Accordingly I was called out of school next forenoon, and
+found Mr. Micawber in the parlour; who had called to say that the dinner
+would take place as proposed. When I asked him if the remittance had
+come, he pressed my hand and departed.
+
+As I was looking out of window that same evening, it surprised me, and
+made me rather uneasy, to see Mr. Micawber and Uriah Heep walk past, arm
+in arm: Uriah humbly sensible of the honour that was done him, and Mr.
+Micawber taking a bland delight in extending his patronage to Uriah. But
+I was still more surprised, when I went to the little hotel next day at
+the appointed dinner-hour, which was four o'clock, to find, from what
+Mr. Micawber said, that he had gone home with Uriah, and had drunk
+brandy-and-water at Mrs. Heep's.
+
+'And I'll tell you what, my dear Copperfield,' said Mr. Micawber, 'your
+friend Heep is a young fellow who might be attorney-general. If I had
+known that young man, at the period when my difficulties came to a
+crisis, all I can say is, that I believe my creditors would have been a
+great deal better managed than they were.'
+
+I hardly understood how this could have been, seeing that Mr. Micawber
+had paid them nothing at all as it was; but I did not like to
+ask. Neither did I like to say, that I hoped he had not been too
+communicative to Uriah; or to inquire if they had talked much about me.
+I was afraid of hurting Mr. Micawber's feelings, or, at all events, Mrs.
+Micawber's, she being very sensitive; but I was uncomfortable about it,
+too, and often thought about it afterwards.
+
+We had a beautiful little dinner. Quite an elegant dish of fish; the
+kidney-end of a loin of veal, roasted; fried sausage-meat; a partridge,
+and a pudding. There was wine, and there was strong ale; and after
+dinner Mrs. Micawber made us a bowl of hot punch with her own hands.
+
+Mr. Micawber was uncommonly convivial. I never saw him such good
+company. He made his face shine with the punch, so that it looked as if
+it had been varnished all over. He got cheerfully sentimental about
+the town, and proposed success to it; observing that Mrs. Micawber and
+himself had been made extremely snug and comfortable there and that he
+never should forget the agreeable hours they had passed in Canterbury.
+He proposed me afterwards; and he, and Mrs. Micawber, and I, took a
+review of our past acquaintance, in the course of which we sold the
+property all over again. Then I proposed Mrs. Micawber: or, at least,
+said, modestly, 'If you'll allow me, Mrs. Micawber, I shall now have
+the pleasure of drinking your health, ma'am.' On which Mr. Micawber
+delivered an eulogium on Mrs. Micawber's character, and said she
+had ever been his guide, philosopher, and friend, and that he would
+recommend me, when I came to a marrying time of life, to marry such
+another woman, if such another woman could be found.
+
+As the punch disappeared, Mr. Micawber became still more friendly and
+convivial. Mrs. Micawber's spirits becoming elevated, too, we sang 'Auld
+Lang Syne'. When we came to 'Here's a hand, my trusty frere', we all
+joined hands round the table; and when we declared we would 'take a
+right gude Willie Waught', and hadn't the least idea what it meant, we
+were really affected.
+
+In a word, I never saw anybody so thoroughly jovial as Mr. Micawber
+was, down to the very last moment of the evening, when I took a hearty
+farewell of himself and his amiable wife. Consequently, I was not
+prepared, at seven o'clock next morning, to receive the following
+communication, dated half past nine in the evening; a quarter of an hour
+after I had left him:--
+
+'My DEAR YOUNG FRIEND,
+
+'The die is cast--all is over. Hiding the ravages of care with a sickly
+mask of mirth, I have not informed you, this evening, that there is no
+hope of the remittance! Under these circumstances, alike humiliating to
+endure, humiliating to contemplate, and humiliating to relate, I have
+discharged the pecuniary liability contracted at this establishment,
+by giving a note of hand, made payable fourteen days after date, at
+my residence, Pentonville, London. When it becomes due, it will not be
+taken up. The result is destruction. The bolt is impending, and the tree
+must fall.
+
+'Let the wretched man who now addresses you, my dear Copperfield, be a
+beacon to you through life. He writes with that intention, and in that
+hope. If he could think himself of so much use, one gleam of day might,
+by possibility, penetrate into the cheerless dungeon of his remaining
+existence--though his longevity is, at present (to say the least of it),
+extremely problematical.
+
+'This is the last communication, my dear Copperfield, you will ever
+receive
+
+                         'From
+
+                              'The
+
+                                   'Beggared Outcast,
+
+                                        'WILKINS MICAWBER.'
+
+
+I was so shocked by the contents of this heart-rending letter, that I
+ran off directly towards the little hotel with the intention of taking
+it on my way to Doctor Strong's, and trying to soothe Mr. Micawber with
+a word of comfort. But, half-way there, I met the London coach with Mr.
+and Mrs. Micawber up behind; Mr. Micawber, the very picture of tranquil
+enjoyment, smiling at Mrs. Micawber's conversation, eating walnuts out
+of a paper bag, with a bottle sticking out of his breast pocket. As they
+did not see me, I thought it best, all things considered, not to
+see them. So, with a great weight taken off my mind, I turned into a
+by-street that was the nearest way to school, and felt, upon the whole,
+relieved that they were gone; though I still liked them very much,
+nevertheless.
+
+
+
+CHAPTER 18. A RETROSPECT
+
+
+My school-days! The silent gliding on of my existence--the unseen,
+unfelt progress of my life--from childhood up to youth! Let me think,
+as I look back upon that flowing water, now a dry channel overgrown with
+leaves, whether there are any marks along its course, by which I can
+remember how it ran.
+
+A moment, and I occupy my place in the Cathedral, where we all went
+together, every Sunday morning, assembling first at school for that
+purpose. The earthy smell, the sunless air, the sensation of the world
+being shut out, the resounding of the organ through the black and white
+arched galleries and aisles, are wings that take me back, and hold me
+hovering above those days, in a half-sleeping and half-waking dream.
+
+I am not the last boy in the school. I have risen in a few months, over
+several heads. But the first boy seems to me a mighty creature, dwelling
+afar off, whose giddy height is unattainable. Agnes says 'No,' but I say
+'Yes,' and tell her that she little thinks what stores of knowledge have
+been mastered by the wonderful Being, at whose place she thinks I, even
+I, weak aspirant, may arrive in time. He is not my private friend
+and public patron, as Steerforth was, but I hold him in a reverential
+respect. I chiefly wonder what he'll be, when he leaves Doctor Strong's,
+and what mankind will do to maintain any place against him.
+
+But who is this that breaks upon me? This is Miss Shepherd, whom I love.
+
+Miss Shepherd is a boarder at the Misses Nettingalls' establishment. I
+adore Miss Shepherd. She is a little girl, in a spencer, with a round
+face and curly flaxen hair. The Misses Nettingalls' young ladies come to
+the Cathedral too. I cannot look upon my book, for I must look upon
+Miss Shepherd. When the choristers chaunt, I hear Miss Shepherd. In the
+service I mentally insert Miss Shepherd's name--I put her in among the
+Royal Family. At home, in my own room, I am sometimes moved to cry out,
+'Oh, Miss Shepherd!' in a transport of love.
+
+For some time, I am doubtful of Miss Shepherd's feelings, but, at
+length, Fate being propitious, we meet at the dancing-school. I have
+Miss Shepherd for my partner. I touch Miss Shepherd's glove, and feel a
+thrill go up the right arm of my jacket, and come out at my hair. I say
+nothing to Miss Shepherd, but we understand each other. Miss Shepherd
+and myself live but to be united.
+
+Why do I secretly give Miss Shepherd twelve Brazil nuts for a present, I
+wonder? They are not expressive of affection, they are difficult to pack
+into a parcel of any regular shape, they are hard to crack, even in
+room doors, and they are oily when cracked; yet I feel that they are
+appropriate to Miss Shepherd. Soft, seedy biscuits, also, I bestow upon
+Miss Shepherd; and oranges innumerable. Once, I kiss Miss Shepherd in
+the cloak-room. Ecstasy! What are my agony and indignation next day,
+when I hear a flying rumour that the Misses Nettingall have stood Miss
+Shepherd in the stocks for turning in her toes!
+
+Miss Shepherd being the one pervading theme and vision of my life, how
+do I ever come to break with her? I can't conceive. And yet a coolness
+grows between Miss Shepherd and myself. Whispers reach me of Miss
+Shepherd having said she wished I wouldn't stare so, and having avowed a
+preference for Master Jones--for Jones! a boy of no merit whatever! The
+gulf between me and Miss Shepherd widens. At last, one day, I meet the
+Misses Nettingalls' establishment out walking. Miss Shepherd makes
+a face as she goes by, and laughs to her companion. All is over. The
+devotion of a life--it seems a life, it is all the same--is at an end;
+Miss Shepherd comes out of the morning service, and the Royal Family
+know her no more.
+
+I am higher in the school, and no one breaks my peace. I am not at all
+polite, now, to the Misses Nettingalls' young ladies, and shouldn't
+dote on any of them, if they were twice as many and twenty times as
+beautiful. I think the dancing-school a tiresome affair, and wonder why
+the girls can't dance by themselves and leave us alone. I am growing
+great in Latin verses, and neglect the laces of my boots. Doctor Strong
+refers to me in public as a promising young scholar. Mr. Dick is wild
+with joy, and my aunt remits me a guinea by the next post.
+
+The shade of a young butcher rises, like the apparition of an armed head
+in Macbeth. Who is this young butcher? He is the terror of the youth
+of Canterbury. There is a vague belief abroad, that the beef suet with
+which he anoints his hair gives him unnatural strength, and that he is
+a match for a man. He is a broad-faced, bull-necked, young butcher, with
+rough red cheeks, an ill-conditioned mind, and an injurious tongue.
+His main use of this tongue, is, to disparage Doctor Strong's young
+gentlemen. He says, publicly, that if they want anything he'll give it
+'em. He names individuals among them (myself included), whom he could
+undertake to settle with one hand, and the other tied behind him. He
+waylays the smaller boys to punch their unprotected heads, and calls
+challenges after me in the open streets. For these sufficient reasons I
+resolve to fight the butcher.
+
+It is a summer evening, down in a green hollow, at the corner of a wall.
+I meet the butcher by appointment. I am attended by a select body of our
+boys; the butcher, by two other butchers, a young publican, and a sweep.
+The preliminaries are adjusted, and the butcher and myself stand face to
+face. In a moment the butcher lights ten thousand candles out of my left
+eyebrow. In another moment, I don't know where the wall is, or where
+I am, or where anybody is. I hardly know which is myself and which the
+butcher, we are always in such a tangle and tussle, knocking about upon
+the trodden grass. Sometimes I see the butcher, bloody but confident;
+sometimes I see nothing, and sit gasping on my second's knee; sometimes
+I go in at the butcher madly, and cut my knuckles open against his face,
+without appearing to discompose him at all. At last I awake, very queer
+about the head, as from a giddy sleep, and see the butcher walking off,
+congratulated by the two other butchers and the sweep and publican, and
+putting on his coat as he goes; from which I augur, justly, that the
+victory is his.
+
+I am taken home in a sad plight, and I have beef-steaks put to my eyes,
+and am rubbed with vinegar and brandy, and find a great puffy place
+bursting out on my upper lip, which swells immoderately. For three or
+four days I remain at home, a very ill-looking subject, with a green
+shade over my eyes; and I should be very dull, but that Agnes is a
+sister to me, and condoles with me, and reads to me, and makes the time
+light and happy. Agnes has my confidence completely, always; I tell her
+all about the butcher, and the wrongs he has heaped upon me; she thinks
+I couldn't have done otherwise than fight the butcher, while she shrinks
+and trembles at my having fought him.
+
+Time has stolen on unobserved, for Adams is not the head-boy in the days
+that are come now, nor has he been this many and many a day. Adams has
+left the school so long, that when he comes back, on a visit to Doctor
+Strong, there are not many there, besides myself, who know him. Adams is
+going to be called to the bar almost directly, and is to be an advocate,
+and to wear a wig. I am surprised to find him a meeker man than I had
+thought, and less imposing in appearance. He has not staggered the world
+yet, either; for it goes on (as well as I can make out) pretty much the
+same as if he had never joined it.
+
+A blank, through which the warriors of poetry and history march on in
+stately hosts that seem to have no end--and what comes next! I am
+the head-boy, now! I look down on the line of boys below me, with a
+condescending interest in such of them as bring to my mind the boy I was
+myself, when I first came there. That little fellow seems to be no part
+of me; I remember him as something left behind upon the road of life--as
+something I have passed, rather than have actually been--and almost
+think of him as of someone else.
+
+And the little girl I saw on that first day at Mr. Wickfield's, where
+is she? Gone also. In her stead, the perfect likeness of the picture,
+a child likeness no more, moves about the house; and Agnes--my sweet
+sister, as I call her in my thoughts, my counsellor and friend, the
+better angel of the lives of all who come within her calm, good,
+self-denying influence--is quite a woman.
+
+What other changes have come upon me, besides the changes in my growth
+and looks, and in the knowledge I have garnered all this while? I wear
+a gold watch and chain, a ring upon my little finger, and a long-tailed
+coat; and I use a great deal of bear's grease--which, taken in
+conjunction with the ring, looks bad. Am I in love again? I am. I
+worship the eldest Miss Larkins.
+
+The eldest Miss Larkins is not a little girl. She is a tall, dark,
+black-eyed, fine figure of a woman. The eldest Miss Larkins is not a
+chicken; for the youngest Miss Larkins is not that, and the eldest must
+be three or four years older. Perhaps the eldest Miss Larkins may be
+about thirty. My passion for her is beyond all bounds.
+
+The eldest Miss Larkins knows officers. It is an awful thing to bear. I
+see them speaking to her in the street. I see them cross the way to meet
+her, when her bonnet (she has a bright taste in bonnets) is seen coming
+down the pavement, accompanied by her sister's bonnet. She laughs and
+talks, and seems to like it. I spend a good deal of my own spare time in
+walking up and down to meet her. If I can bow to her once in the day (I
+know her to bow to, knowing Mr. Larkins), I am happier. I deserve a bow
+now and then. The raging agonies I suffer on the night of the Race Ball,
+where I know the eldest Miss Larkins will be dancing with the military,
+ought to have some compensation, if there be even-handed justice in the
+world.
+
+My passion takes away my appetite, and makes me wear my newest silk
+neckerchief continually. I have no relief but in putting on my best
+clothes, and having my boots cleaned over and over again. I seem, then,
+to be worthier of the eldest Miss Larkins. Everything that belongs to
+her, or is connected with her, is precious to me. Mr. Larkins (a gruff
+old gentleman with a double chin, and one of his eyes immovable in his
+head) is fraught with interest to me. When I can't meet his daughter,
+I go where I am likely to meet him. To say 'How do you do, Mr. Larkins?
+Are the young ladies and all the family quite well?' seems so pointed,
+that I blush.
+
+I think continually about my age. Say I am seventeen, and say that
+seventeen is young for the eldest Miss Larkins, what of that? Besides,
+I shall be one-and-twenty in no time almost. I regularly take walks
+outside Mr. Larkins's house in the evening, though it cuts me to the
+heart to see the officers go in, or to hear them up in the drawing-room,
+where the eldest Miss Larkins plays the harp. I even walk, on two or
+three occasions, in a sickly, spoony manner, round and round the house
+after the family are gone to bed, wondering which is the eldest Miss
+Larkins's chamber (and pitching, I dare say now, on Mr. Larkins's
+instead); wishing that a fire would burst out; that the assembled crowd
+would stand appalled; that I, dashing through them with a ladder, might
+rear it against her window, save her in my arms, go back for something
+she had left behind, and perish in the flames. For I am generally
+disinterested in my love, and think I could be content to make a figure
+before Miss Larkins, and expire.
+
+Generally, but not always. Sometimes brighter visions rise before me.
+When I dress (the occupation of two hours), for a great ball given at
+the Larkins's (the anticipation of three weeks), I indulge my fancy with
+pleasing images. I picture myself taking courage to make a declaration
+to Miss Larkins. I picture Miss Larkins sinking her head upon my
+shoulder, and saying, 'Oh, Mr. Copperfield, can I believe my ears!' I
+picture Mr. Larkins waiting on me next morning, and saying, 'My dear
+Copperfield, my daughter has told me all. Youth is no objection. Here
+are twenty thousand pounds. Be happy!' I picture my aunt relenting,
+and blessing us; and Mr. Dick and Doctor Strong being present at the
+marriage ceremony. I am a sensible fellow, I believe--I believe,
+on looking back, I mean--and modest I am sure; but all this goes on
+notwithstanding. I repair to the enchanted house, where there are
+lights, chattering, music, flowers, officers (I am sorry to see), and
+the eldest Miss Larkins, a blaze of beauty. She is dressed in blue, with
+blue flowers in her hair--forget-me-nots--as if SHE had any need to wear
+forget-me-nots. It is the first really grown-up party that I have ever
+been invited to, and I am a little uncomfortable; for I appear not to
+belong to anybody, and nobody appears to have anything to say to me,
+except Mr. Larkins, who asks me how my schoolfellows are, which he
+needn't do, as I have not come there to be insulted.
+
+But after I have stood in the doorway for some time, and feasted my eyes
+upon the goddess of my heart, she approaches me--she, the eldest Miss
+Larkins!--and asks me pleasantly, if I dance?
+
+I stammer, with a bow, 'With you, Miss Larkins.'
+
+'With no one else?' inquires Miss Larkins.
+
+'I should have no pleasure in dancing with anyone else.'
+
+Miss Larkins laughs and blushes (or I think she blushes), and says,
+'Next time but one, I shall be very glad.'
+
+The time arrives. 'It is a waltz, I think,' Miss Larkins doubtfully
+observes, when I present myself. 'Do you waltz? If not, Captain
+Bailey--'
+
+But I do waltz (pretty well, too, as it happens), and I take Miss
+Larkins out. I take her sternly from the side of Captain Bailey. He
+is wretched, I have no doubt; but he is nothing to me. I have been
+wretched, too. I waltz with the eldest Miss Larkins! I don't know where,
+among whom, or how long. I only know that I swim about in space, with a
+blue angel, in a state of blissful delirium, until I find myself alone
+with her in a little room, resting on a sofa. She admires a flower (pink
+camellia japonica, price half-a-crown), in my button-hole. I give it
+her, and say:
+
+'I ask an inestimable price for it, Miss Larkins.'
+
+'Indeed! What is that?' returns Miss Larkins.
+
+'A flower of yours, that I may treasure it as a miser does gold.'
+
+'You're a bold boy,' says Miss Larkins. 'There.'
+
+She gives it me, not displeased; and I put it to my lips, and then into
+my breast. Miss Larkins, laughing, draws her hand through my arm, and
+says, 'Now take me back to Captain Bailey.'
+
+I am lost in the recollection of this delicious interview, and the
+waltz, when she comes to me again, with a plain elderly gentleman who
+has been playing whist all night, upon her arm, and says:
+
+'Oh! here is my bold friend! Mr. Chestle wants to know you, Mr.
+Copperfield.'
+
+I feel at once that he is a friend of the family, and am much gratified.
+
+'I admire your taste, sir,' says Mr. Chestle. 'It does you credit. I
+suppose you don't take much interest in hops; but I am a pretty
+large grower myself; and if you ever like to come over to our
+neighbourhood--neighbourhood of Ashford--and take a run about our
+place,--we shall be glad for you to stop as long as you like.'
+
+I thank Mr. Chestle warmly, and shake hands. I think I am in a happy
+dream. I waltz with the eldest Miss Larkins once again. She says I
+waltz so well! I go home in a state of unspeakable bliss, and waltz in
+imagination, all night long, with my arm round the blue waist of my dear
+divinity. For some days afterwards, I am lost in rapturous reflections;
+but I neither see her in the street, nor when I call. I am imperfectly
+consoled for this disappointment by the sacred pledge, the perished
+flower.
+
+'Trotwood,' says Agnes, one day after dinner. 'Who do you think is going
+to be married tomorrow? Someone you admire.'
+
+'Not you, I suppose, Agnes?'
+
+'Not me!' raising her cheerful face from the music she is copying. 'Do
+you hear him, Papa?--The eldest Miss Larkins.'
+
+'To--to Captain Bailey?' I have just enough power to ask.
+
+'No; to no Captain. To Mr. Chestle, a hop-grower.'
+
+I am terribly dejected for about a week or two. I take off my ring, I
+wear my worst clothes, I use no bear's grease, and I frequently lament
+over the late Miss Larkins's faded flower. Being, by that time, rather
+tired of this kind of life, and having received new provocation from
+the butcher, I throw the flower away, go out with the butcher, and
+gloriously defeat him.
+
+This, and the resumption of my ring, as well as of the bear's grease
+in moderation, are the last marks I can discern, now, in my progress to
+seventeen.
+
+
+
+CHAPTER 19. I LOOK ABOUT ME, AND MAKE A DISCOVERY
+
+
+I am doubtful whether I was at heart glad or sorry, when my school-days
+drew to an end, and the time came for my leaving Doctor Strong's. I had
+been very happy there, I had a great attachment for the Doctor, and I
+was eminent and distinguished in that little world. For these reasons
+I was sorry to go; but for other reasons, unsubstantial enough, I
+was glad. Misty ideas of being a young man at my own disposal, of
+the importance attaching to a young man at his own disposal, of the
+wonderful things to be seen and done by that magnificent animal, and the
+wonderful effects he could not fail to make upon society, lured me away.
+So powerful were these visionary considerations in my boyish mind, that
+I seem, according to my present way of thinking, to have left school
+without natural regret. The separation has not made the impression on
+me, that other separations have. I try in vain to recall how I felt
+about it, and what its circumstances were; but it is not momentous in my
+recollection. I suppose the opening prospect confused me. I know that my
+juvenile experiences went for little or nothing then; and that life was
+more like a great fairy story, which I was just about to begin to read,
+than anything else.
+
+MY aunt and I had held many grave deliberations on the calling to which
+I should be devoted. For a year or more I had endeavoured to find a
+satisfactory answer to her often-repeated question, 'What I would like
+to be?' But I had no particular liking, that I could discover, for
+anything. If I could have been inspired with a knowledge of the science
+of navigation, taken the command of a fast-sailing expedition, and gone
+round the world on a triumphant voyage of discovery, I think I might
+have considered myself completely suited. But, in the absence of any
+such miraculous provision, my desire was to apply myself to some pursuit
+that would not lie too heavily upon her purse; and to do my duty in it,
+whatever it might be.
+
+Mr. Dick had regularly assisted at our councils, with a meditative
+and sage demeanour. He never made a suggestion but once; and on that
+occasion (I don't know what put it in his head), he suddenly proposed
+that I should be 'a Brazier'. My aunt received this proposal so very
+ungraciously, that he never ventured on a second; but ever afterwards
+confined himself to looking watchfully at her for her suggestions, and
+rattling his money.
+
+'Trot, I tell you what, my dear,' said my aunt, one morning in the
+Christmas season when I left school: 'as this knotty point is still
+unsettled, and as we must not make a mistake in our decision if we can
+help it, I think we had better take a little breathing-time. In the
+meanwhile, you must try to look at it from a new point of view, and not
+as a schoolboy.'
+
+'I will, aunt.'
+
+'It has occurred to me,' pursued my aunt, 'that a little change, and a
+glimpse of life out of doors, may be useful in helping you to know your
+own mind, and form a cooler judgement. Suppose you were to go down into
+the old part of the country again, for instance, and see that--that
+out-of-the-way woman with the savagest of names,' said my aunt, rubbing
+her nose, for she could never thoroughly forgive Peggotty for being so
+called.
+
+'Of all things in the world, aunt, I should like it best!'
+
+'Well,' said my aunt, 'that's lucky, for I should like it too. But
+it's natural and rational that you should like it. And I am very
+well persuaded that whatever you do, Trot, will always be natural and
+rational.'
+
+'I hope so, aunt.'
+
+'Your sister, Betsey Trotwood,' said my aunt, 'would have been as
+natural and rational a girl as ever breathed. You'll be worthy of her,
+won't you?'
+
+'I hope I shall be worthy of YOU, aunt. That will be enough for me.'
+
+'It's a mercy that poor dear baby of a mother of yours didn't live,'
+said my aunt, looking at me approvingly, 'or she'd have been so vain
+of her boy by this time, that her soft little head would have been
+completely turned, if there was anything of it left to turn.' (My aunt
+always excused any weakness of her own in my behalf, by transferring it
+in this way to my poor mother.) 'Bless me, Trotwood, how you do remind
+me of her!'
+
+'Pleasantly, I hope, aunt?' said I.
+
+'He's as like her, Dick,' said my aunt, emphatically, 'he's as like her,
+as she was that afternoon before she began to fret--bless my heart, he's
+as like her, as he can look at me out of his two eyes!'
+
+'Is he indeed?' said Mr. Dick.
+
+'And he's like David, too,' said my aunt, decisively.
+
+'He is very like David!' said Mr. Dick.
+
+'But what I want you to be, Trot,' resumed my aunt, '--I don't mean
+physically, but morally; you are very well physically--is, a firm
+fellow. A fine firm fellow, with a will of your own. With resolution,'
+said my aunt, shaking her cap at me, and clenching her hand. 'With
+determination. With character, Trot--with strength of character that is
+not to be influenced, except on good reason, by anybody, or by anything.
+That's what I want you to be. That's what your father and mother might
+both have been, Heaven knows, and been the better for it.'
+
+I intimated that I hoped I should be what she described.
+
+'That you may begin, in a small way, to have a reliance upon yourself,
+and to act for yourself,' said my aunt, 'I shall send you upon your
+trip, alone. I did think, once, of Mr. Dick's going with you; but, on
+second thoughts, I shall keep him to take care of me.'
+
+Mr. Dick, for a moment, looked a little disappointed; until the honour
+and dignity of having to take care of the most wonderful woman in the
+world, restored the sunshine to his face.
+
+'Besides,' said my aunt, 'there's the Memorial--'
+
+'Oh, certainly,' said Mr. Dick, in a hurry, 'I intend, Trotwood, to get
+that done immediately--it really must be done immediately! And then it
+will go in, you know--and then--' said Mr. Dick, after checking himself,
+and pausing a long time, 'there'll be a pretty kettle of fish!'
+
+In pursuance of my aunt's kind scheme, I was shortly afterwards fitted
+out with a handsome purse of money, and a portmanteau, and tenderly
+dismissed upon my expedition. At parting, my aunt gave me some good
+advice, and a good many kisses; and said that as her object was that I
+should look about me, and should think a little, she would recommend me
+to stay a few days in London, if I liked it, either on my way down into
+Suffolk, or in coming back. In a word, I was at liberty to do what I
+would, for three weeks or a month; and no other conditions were imposed
+upon my freedom than the before-mentioned thinking and looking about me,
+and a pledge to write three times a week and faithfully report myself.
+
+I went to Canterbury first, that I might take leave of Agnes and Mr.
+Wickfield (my old room in whose house I had not yet relinquished), and
+also of the good Doctor. Agnes was very glad to see me, and told me that
+the house had not been like itself since I had left it.
+
+'I am sure I am not like myself when I am away,' said I. 'I seem to
+want my right hand, when I miss you. Though that's not saying much; for
+there's no head in my right hand, and no heart. Everyone who knows you,
+consults with you, and is guided by you, Agnes.'
+
+'Everyone who knows me, spoils me, I believe,' she answered, smiling.
+
+'No. It's because you are like no one else. You are so good, and so
+sweet-tempered. You have such a gentle nature, and you are always
+right.'
+
+'You talk,' said Agnes, breaking into a pleasant laugh, as she sat at
+work, 'as if I were the late Miss Larkins.'
+
+'Come! It's not fair to abuse my confidence,' I answered, reddening at
+the recollection of my blue enslaver. 'But I shall confide in you, just
+the same, Agnes. I can never grow out of that. Whenever I fall into
+trouble, or fall in love, I shall always tell you, if you'll let
+me--even when I come to fall in love in earnest.'
+
+'Why, you have always been in earnest!' said Agnes, laughing again.
+
+'Oh! that was as a child, or a schoolboy,' said I, laughing in my turn,
+not without being a little shame-faced. 'Times are altering now, and I
+suppose I shall be in a terrible state of earnestness one day or other.
+My wonder is, that you are not in earnest yourself, by this time,
+Agnes.'
+
+Agnes laughed again, and shook her head.
+
+'Oh, I know you are not!' said I, 'because if you had been you would
+have told me. Or at least'--for I saw a faint blush in her face, 'you
+would have let me find it out for myself. But there is no one that I
+know of, who deserves to love you, Agnes. Someone of a nobler character,
+and more worthy altogether than anyone I have ever seen here, must rise
+up, before I give my consent. In the time to come, I shall have a wary
+eye on all admirers; and shall exact a great deal from the successful
+one, I assure you.'
+
+We had gone on, so far, in a mixture of confidential jest and earnest,
+that had long grown naturally out of our familiar relations, begun as
+mere children. But Agnes, now suddenly lifting up her eyes to mine, and
+speaking in a different manner, said:
+
+'Trotwood, there is something that I want to ask you, and that I may not
+have another opportunity of asking for a long time, perhaps--something
+I would ask, I think, of no one else. Have you observed any gradual
+alteration in Papa?'
+
+I had observed it, and had often wondered whether she had too. I must
+have shown as much, now, in my face; for her eyes were in a moment cast
+down, and I saw tears in them.
+
+'Tell me what it is,' she said, in a low voice.
+
+'I think--shall I be quite plain, Agnes, liking him so much?'
+
+'Yes,' she said.
+
+'I think he does himself no good by the habit that has increased upon
+him since I first came here. He is often very nervous--or I fancy so.'
+
+'It is not fancy,' said Agnes, shaking her head.
+
+'His hand trembles, his speech is not plain, and his eyes look wild. I
+have remarked that at those times, and when he is least like himself, he
+is most certain to be wanted on some business.'
+
+'By Uriah,' said Agnes.
+
+'Yes; and the sense of being unfit for it, or of not having understood
+it, or of having shown his condition in spite of himself, seems to make
+him so uneasy, that next day he is worse, and next day worse, and so he
+becomes jaded and haggard. Do not be alarmed by what I say, Agnes, but
+in this state I saw him, only the other evening, lay down his head upon
+his desk, and shed tears like a child.'
+
+Her hand passed softly before my lips while I was yet speaking, and in
+a moment she had met her father at the door of the room, and was hanging
+on his shoulder. The expression of her face, as they both looked towards
+me, I felt to be very touching. There was such deep fondness for him,
+and gratitude to him for all his love and care, in her beautiful look;
+and there was such a fervent appeal to me to deal tenderly by him, even
+in my inmost thoughts, and to let no harsh construction find any place
+against him; she was, at once, so proud of him and devoted to him, yet
+so compassionate and sorry, and so reliant upon me to be so, too; that
+nothing she could have said would have expressed more to me, or moved me
+more.
+
+We were to drink tea at the Doctor's. We went there at the usual hour;
+and round the study fireside found the Doctor, and his young wife, and
+her mother. The Doctor, who made as much of my going away as if I were
+going to China, received me as an honoured guest; and called for a log
+of wood to be thrown on the fire, that he might see the face of his old
+pupil reddening in the blaze.
+
+'I shall not see many more new faces in Trotwood's stead, Wickfield,'
+said the Doctor, warming his hands; 'I am getting lazy, and want ease.
+I shall relinquish all my young people in another six months, and lead a
+quieter life.'
+
+'You have said so, any time these ten years, Doctor,' Mr. Wickfield
+answered.
+
+'But now I mean to do it,' returned the Doctor. 'My first master will
+succeed me--I am in earnest at last--so you'll soon have to arrange our
+contracts, and to bind us firmly to them, like a couple of knaves.'
+
+'And to take care,' said Mr. Wickfield, 'that you're not imposed on, eh?
+As you certainly would be, in any contract you should make for yourself.
+Well! I am ready. There are worse tasks than that, in my calling.'
+
+'I shall have nothing to think of then,' said the Doctor, with a smile,
+'but my Dictionary; and this other contract-bargain--Annie.'
+
+As Mr. Wickfield glanced towards her, sitting at the tea table by Agnes,
+she seemed to me to avoid his look with such unwonted hesitation and
+timidity, that his attention became fixed upon her, as if something were
+suggested to his thoughts.
+
+'There is a post come in from India, I observe,' he said, after a short
+silence.
+
+'By the by! and letters from Mr. Jack Maldon!' said the Doctor.
+
+'Indeed!' 'Poor dear Jack!' said Mrs. Markleham, shaking her head. 'That
+trying climate!--like living, they tell me, on a sand-heap, underneath
+a burning-glass! He looked strong, but he wasn't. My dear Doctor, it was
+his spirit, not his constitution, that he ventured on so boldly. Annie,
+my dear, I am sure you must perfectly recollect that your cousin
+never was strong--not what can be called ROBUST, you know,' said Mrs.
+Markleham, with emphasis, and looking round upon us generally, '--from
+the time when my daughter and himself were children together, and
+walking about, arm-in-arm, the livelong day.'
+
+Annie, thus addressed, made no reply.
+
+'Do I gather from what you say, ma'am, that Mr. Maldon is ill?' asked
+Mr. Wickfield.
+
+'Ill!' replied the Old Soldier. 'My dear sir, he's all sorts of things.'
+
+'Except well?' said Mr. Wickfield.
+
+'Except well, indeed!' said the Old Soldier. 'He has had dreadful
+strokes of the sun, no doubt, and jungle fevers and agues, and every
+kind of thing you can mention. As to his liver,' said the Old Soldier
+resignedly, 'that, of course, he gave up altogether, when he first went
+out!'
+
+'Does he say all this?' asked Mr. Wickfield.
+
+'Say? My dear sir,' returned Mrs. Markleham, shaking her head and her
+fan, 'you little know my poor Jack Maldon when you ask that question.
+Say? Not he. You might drag him at the heels of four wild horses first.'
+
+'Mama!' said Mrs. Strong.
+
+'Annie, my dear,' returned her mother, 'once for all, I must really beg
+that you will not interfere with me, unless it is to confirm what I say.
+You know as well as I do that your cousin Maldon would be dragged at the
+heels of any number of wild horses--why should I confine myself to four!
+I WON'T confine myself to four--eight, sixteen, two-and-thirty, rather
+than say anything calculated to overturn the Doctor's plans.'
+
+'Wickfield's plans,' said the Doctor, stroking his face, and looking
+penitently at his adviser. 'That is to say, our joint plans for him. I
+said myself, abroad or at home.'
+
+'And I said' added Mr. Wickfield gravely, 'abroad. I was the means of
+sending him abroad. It's my responsibility.'
+
+'Oh! Responsibility!' said the Old Soldier. 'Everything was done for
+the best, my dear Mr. Wickfield; everything was done for the kindest and
+best, we know. But if the dear fellow can't live there, he can't live
+there. And if he can't live there, he'll die there, sooner than he'll
+overturn the Doctor's plans. I know him,' said the Old Soldier, fanning
+herself, in a sort of calm prophetic agony, 'and I know he'll die there,
+sooner than he'll overturn the Doctor's plans.'
+
+'Well, well, ma'am,' said the Doctor cheerfully, 'I am not bigoted to
+my plans, and I can overturn them myself. I can substitute some other
+plans. If Mr. Jack Maldon comes home on account of ill health, he must
+not be allowed to go back, and we must endeavour to make some more
+suitable and fortunate provision for him in this country.'
+
+Mrs. Markleham was so overcome by this generous speech--which, I need
+not say, she had not at all expected or led up to--that she could only
+tell the Doctor it was like himself, and go several times through that
+operation of kissing the sticks of her fan, and then tapping his hand
+with it. After which she gently chid her daughter Annie, for not being
+more demonstrative when such kindnesses were showered, for her sake, on
+her old playfellow; and entertained us with some particulars concerning
+other deserving members of her family, whom it was desirable to set on
+their deserving legs.
+
+All this time, her daughter Annie never once spoke, or lifted up her
+eyes. All this time, Mr. Wickfield had his glance upon her as she sat
+by his own daughter's side. It appeared to me that he never thought of
+being observed by anyone; but was so intent upon her, and upon his own
+thoughts in connexion with her, as to be quite absorbed. He now asked
+what Mr. Jack Maldon had actually written in reference to himself, and
+to whom he had written?
+
+'Why, here,' said Mrs. Markleham, taking a letter from the chimney-piece
+above the Doctor's head, 'the dear fellow says to the Doctor
+himself--where is it? Oh!--"I am sorry to inform you that my health is
+suffering severely, and that I fear I may be reduced to the necessity
+of returning home for a time, as the only hope of restoration." That's
+pretty plain, poor fellow! His only hope of restoration! But Annie's
+letter is plainer still. Annie, show me that letter again.'
+
+'Not now, mama,' she pleaded in a low tone.
+
+'My dear, you absolutely are, on some subjects, one of the most
+ridiculous persons in the world,' returned her mother, 'and perhaps the
+most unnatural to the claims of your own family. We never should have
+heard of the letter at all, I believe, unless I had asked for it myself.
+Do you call that confidence, my love, towards Doctor Strong? I am
+surprised. You ought to know better.'
+
+The letter was reluctantly produced; and as I handed it to the old lady,
+I saw how the unwilling hand from which I took it, trembled.
+
+'Now let us see,' said Mrs. Markleham, putting her glass to her eye,
+'where the passage is. "The remembrance of old times, my dearest
+Annie"--and so forth--it's not there. "The amiable old Proctor"--who's
+he? Dear me, Annie, how illegibly your cousin Maldon writes, and how
+stupid I am! "Doctor," of course. Ah! amiable indeed!' Here she left
+off, to kiss her fan again, and shake it at the Doctor, who was looking
+at us in a state of placid satisfaction. 'Now I have found it. "You may
+not be surprised to hear, Annie,"--no, to be sure, knowing that he never
+was really strong; what did I say just now?--"that I have undergone
+so much in this distant place, as to have decided to leave it at all
+hazards; on sick leave, if I can; on total resignation, if that is
+not to be obtained. What I have endured, and do endure here, is
+insupportable." And but for the promptitude of that best of creatures,'
+said Mrs. Markleham, telegraphing the Doctor as before, and refolding
+the letter, 'it would be insupportable to me to think of.'
+
+Mr. Wickfield said not one word, though the old lady looked to him as if
+for his commentary on this intelligence; but sat severely silent, with
+his eyes fixed on the ground. Long after the subject was dismissed,
+and other topics occupied us, he remained so; seldom raising his eyes,
+unless to rest them for a moment, with a thoughtful frown, upon the
+Doctor, or his wife, or both.
+
+The Doctor was very fond of music. Agnes sang with great sweetness and
+expression, and so did Mrs. Strong. They sang together, and played duets
+together, and we had quite a little concert. But I remarked two things:
+first, that though Annie soon recovered her composure, and was quite
+herself, there was a blank between her and Mr. Wickfield which separated
+them wholly from each other; secondly, that Mr. Wickfield seemed
+to dislike the intimacy between her and Agnes, and to watch it with
+uneasiness. And now, I must confess, the recollection of what I had seen
+on that night when Mr. Maldon went away, first began to return upon me
+with a meaning it had never had, and to trouble me. The innocent beauty
+of her face was not as innocent to me as it had been; I mistrusted the
+natural grace and charm of her manner; and when I looked at Agnes by her
+side, and thought how good and true Agnes was, suspicions arose within
+me that it was an ill-assorted friendship.
+
+She was so happy in it herself, however, and the other was so happy too,
+that they made the evening fly away as if it were but an hour. It closed
+in an incident which I well remember. They were taking leave of each
+other, and Agnes was going to embrace her and kiss her, when Mr.
+Wickfield stepped between them, as if by accident, and drew Agnes
+quickly away. Then I saw, as though all the intervening time had been
+cancelled, and I were still standing in the doorway on the night of the
+departure, the expression of that night in the face of Mrs. Strong, as
+it confronted his.
+
+I cannot say what an impression this made upon me, or how impossible I
+found it, when I thought of her afterwards, to separate her from this
+look, and remember her face in its innocent loveliness again. It haunted
+me when I got home. I seemed to have left the Doctor's roof with a dark
+cloud lowering on it. The reverence that I had for his grey head, was
+mingled with commiseration for his faith in those who were treacherous
+to him, and with resentment against those who injured him. The impending
+shadow of a great affliction, and a great disgrace that had no distinct
+form in it yet, fell like a stain upon the quiet place where I had
+worked and played as a boy, and did it a cruel wrong. I had no pleasure
+in thinking, any more, of the grave old broad-leaved aloe-trees, which
+remained shut up in themselves a hundred years together, and of the trim
+smooth grass-plot, and the stone urns, and the Doctor's walk, and the
+congenial sound of the Cathedral bell hovering above them all. It was as
+if the tranquil sanctuary of my boyhood had been sacked before my face,
+and its peace and honour given to the winds.
+
+But morning brought with it my parting from the old house, which Agnes
+had filled with her influence; and that occupied my mind sufficiently.
+I should be there again soon, no doubt; I might sleep again--perhaps
+often--in my old room; but the days of my inhabiting there were gone,
+and the old time was past. I was heavier at heart when I packed up such
+of my books and clothes as still remained there to be sent to Dover,
+than I cared to show to Uriah Heep; who was so officious to help me,
+that I uncharitably thought him mighty glad that I was going.
+
+I got away from Agnes and her father, somehow, with an indifferent show
+of being very manly, and took my seat upon the box of the London coach.
+I was so softened and forgiving, going through the town, that I had half
+a mind to nod to my old enemy the butcher, and throw him five shillings
+to drink. But he looked such a very obdurate butcher as he stood
+scraping the great block in the shop, and moreover, his appearance was
+so little improved by the loss of a front tooth which I had knocked out,
+that I thought it best to make no advances.
+
+The main object on my mind, I remember, when we got fairly on the road,
+was to appear as old as possible to the coachman, and to speak extremely
+gruff. The latter point I achieved at great personal inconvenience; but
+I stuck to it, because I felt it was a grown-up sort of thing.
+
+'You are going through, sir?' said the coachman.
+
+'Yes, William,' I said, condescendingly (I knew him); 'I am going to
+London. I shall go down into Suffolk afterwards.'
+
+'Shooting, sir?' said the coachman.
+
+He knew as well as I did that it was just as likely, at that time of
+year, I was going down there whaling; but I felt complimented, too.
+
+'I don't know,' I said, pretending to be undecided, 'whether I shall
+take a shot or not.' 'Birds is got wery shy, I'm told,' said William.
+
+'So I understand,' said I.
+
+'Is Suffolk your county, sir?' asked William.
+
+'Yes,' I said, with some importance. 'Suffolk's my county.'
+
+'I'm told the dumplings is uncommon fine down there,' said William.
+
+I was not aware of it myself, but I felt it necessary to uphold the
+institutions of my county, and to evince a familiarity with them; so I
+shook my head, as much as to say, 'I believe you!'
+
+'And the Punches,' said William. 'There's cattle! A Suffolk Punch, when
+he's a good un, is worth his weight in gold. Did you ever breed any
+Suffolk Punches yourself, sir?'
+
+'N-no,' I said, 'not exactly.'
+
+'Here's a gen'lm'n behind me, I'll pound it,' said William, 'as has bred
+'em by wholesale.'
+
+The gentleman spoken of was a gentleman with a very unpromising squint,
+and a prominent chin, who had a tall white hat on with a narrow flat
+brim, and whose close-fitting drab trousers seemed to button all the way
+up outside his legs from his boots to his hips. His chin was cocked over
+the coachman's shoulder, so near to me, that his breath quite tickled
+the back of my head; and as I looked at him, he leered at the leaders
+with the eye with which he didn't squint, in a very knowing manner.
+
+'Ain't you?' asked William.
+
+'Ain't I what?' said the gentleman behind.
+
+'Bred them Suffolk Punches by wholesale?'
+
+'I should think so,' said the gentleman. 'There ain't no sort of orse
+that I ain't bred, and no sort of dorg. Orses and dorgs is some
+men's fancy. They're wittles and drink to me--lodging, wife, and
+children--reading, writing, and Arithmetic--snuff, tobacker, and sleep.'
+
+'That ain't a sort of man to see sitting behind a coach-box, is it
+though?' said William in my ear, as he handled the reins.
+
+I construed this remark into an indication of a wish that he should have
+my place, so I blushingly offered to resign it.
+
+'Well, if you don't mind, sir,' said William, 'I think it would be more
+correct.'
+
+I have always considered this as the first fall I had in life. When I
+booked my place at the coach office I had had 'Box Seat' written against
+the entry, and had given the book-keeper half-a-crown. I was got up in
+a special great-coat and shawl, expressly to do honour to that
+distinguished eminence; had glorified myself upon it a good deal; and
+had felt that I was a credit to the coach. And here, in the very first
+stage, I was supplanted by a shabby man with a squint, who had no other
+merit than smelling like a livery-stables, and being able to walk across
+me, more like a fly than a human being, while the horses were at a
+canter!
+
+A distrust of myself, which has often beset me in life on small
+occasions, when it would have been better away, was assuredly not
+stopped in its growth by this little incident outside the Canterbury
+coach. It was in vain to take refuge in gruffness of speech. I spoke
+from the pit of my stomach for the rest of the journey, but I felt
+completely extinguished, and dreadfully young.
+
+It was curious and interesting, nevertheless, to be sitting up there
+behind four horses: well educated, well dressed, and with plenty of
+money in my pocket; and to look out for the places where I had slept on
+my weary journey. I had abundant occupation for my thoughts, in every
+conspicuous landmark on the road. When I looked down at the trampers
+whom we passed, and saw that well-remembered style of face turned up,
+I felt as if the tinker's blackened hand were in the bosom of my shirt
+again. When we clattered through the narrow street of Chatham, and I
+caught a glimpse, in passing, of the lane where the old monster lived
+who had bought my jacket, I stretched my neck eagerly to look for the
+place where I had sat, in the sun and in the shade, waiting for my
+money. When we came, at last, within a stage of London, and passed the
+veritable Salem House where Mr. Creakle had laid about him with a heavy
+hand, I would have given all I had, for lawful permission to get down
+and thrash him, and let all the boys out like so many caged sparrows.
+
+We went to the Golden Cross at Charing Cross, then a mouldy sort of
+establishment in a close neighbourhood. A waiter showed me into the
+coffee-room; and a chambermaid introduced me to my small bedchamber,
+which smelt like a hackney-coach, and was shut up like a family vault.
+I was still painfully conscious of my youth, for nobody stood in any awe
+of me at all: the chambermaid being utterly indifferent to my opinions
+on any subject, and the waiter being familiar with me, and offering
+advice to my inexperience.
+
+'Well now,' said the waiter, in a tone of confidence, 'what would you
+like for dinner? Young gentlemen likes poultry in general: have a fowl!'
+
+I told him, as majestically as I could, that I wasn't in the humour for
+a fowl.
+
+'Ain't you?' said the waiter. 'Young gentlemen is generally tired of
+beef and mutton: have a weal cutlet!'
+
+I assented to this proposal, in default of being able to suggest
+anything else.
+
+'Do you care for taters?' said the waiter, with an insinuating smile,
+and his head on one side. 'Young gentlemen generally has been overdosed
+with taters.'
+
+I commanded him, in my deepest voice, to order a veal cutlet and
+potatoes, and all things fitting; and to inquire at the bar if there
+were any letters for Trotwood Copperfield, Esquire--which I knew there
+were not, and couldn't be, but thought it manly to appear to expect.
+
+He soon came back to say that there were none (at which I was much
+surprised) and began to lay the cloth for my dinner in a box by the
+fire. While he was so engaged, he asked me what I would take with it;
+and on my replying 'Half a pint of sherry,'thought it a favourable
+opportunity, I am afraid, to extract that measure of wine from the
+stale leavings at the bottoms of several small decanters. I am of this
+opinion, because, while I was reading the newspaper, I observed him
+behind a low wooden partition, which was his private apartment, very
+busy pouring out of a number of those vessels into one, like a chemist
+and druggist making up a prescription. When the wine came, too, I
+thought it flat; and it certainly had more English crumbs in it, than
+were to be expected in a foreign wine in anything like a pure state, but
+I was bashful enough to drink it, and say nothing.
+
+Being then in a pleasant frame of mind (from which I infer that
+poisoning is not always disagreeable in some stages of the process), I
+resolved to go to the play. It was Covent Garden Theatre that I chose;
+and there, from the back of a centre box, I saw Julius Caesar and the
+new Pantomime. To have all those noble Romans alive before me, and
+walking in and out for my entertainment, instead of being the stern
+taskmasters they had been at school, was a most novel and delightful
+effect. But the mingled reality and mystery of the whole show, the
+influence upon me of the poetry, the lights, the music, the company, the
+smooth stupendous changes of glittering and brilliant scenery, were so
+dazzling, and opened up such illimitable regions of delight, that when I
+came out into the rainy street, at twelve o'clock at night, I felt as if
+I had come from the clouds, where I had been leading a romantic life
+for ages, to a bawling, splashing, link-lighted, umbrella-struggling,
+hackney-coach-jostling, patten-clinking, muddy, miserable world.
+
+I had emerged by another door, and stood in the street for a little
+while, as if I really were a stranger upon earth: but the unceremonious
+pushing and hustling that I received, soon recalled me to myself, and
+put me in the road back to the hotel; whither I went, revolving the
+glorious vision all the way; and where, after some porter and oysters,
+I sat revolving it still, at past one o'clock, with my eyes on the
+coffee-room fire.
+
+I was so filled with the play, and with the past--for it was, in a
+manner, like a shining transparency, through which I saw my earlier
+life moving along--that I don't know when the figure of a handsome
+well-formed young man dressed with a tasteful easy negligence which I
+have reason to remember very well, became a real presence to me. But
+I recollect being conscious of his company without having noticed his
+coming in--and my still sitting, musing, over the coffee-room fire.
+
+At last I rose to go to bed, much to the relief of the sleepy waiter,
+who had got the fidgets in his legs, and was twisting them, and hitting
+them, and putting them through all kinds of contortions in his small
+pantry. In going towards the door, I passed the person who had come in,
+and saw him plainly. I turned directly, came back, and looked again. He
+did not know me, but I knew him in a moment.
+
+At another time I might have wanted the confidence or the decision to
+speak to him, and might have put it off until next day, and might have
+lost him. But, in the then condition of my mind, where the play was
+still running high, his former protection of me appeared so deserving
+of my gratitude, and my old love for him overflowed my breast so freshly
+and spontaneously, that I went up to him at once, with a fast-beating
+heart, and said:
+
+'Steerforth! won't you speak to me?'
+
+He looked at me--just as he used to look, sometimes--but I saw no
+recognition in his face.
+
+'You don't remember me, I am afraid,' said I.
+
+'My God!' he suddenly exclaimed. 'It's little Copperfield!'
+
+I grasped him by both hands, and could not let them go. But for very
+shame, and the fear that it might displease him, I could have held him
+round the neck and cried.
+
+'I never, never, never was so glad! My dear Steerforth, I am so
+overjoyed to see you!'
+
+'And I am rejoiced to see you, too!' he said, shaking my hands heartily.
+'Why, Copperfield, old boy, don't be overpowered!' And yet he was glad,
+too, I thought, to see how the delight I had in meeting him affected me.
+
+I brushed away the tears that my utmost resolution had not been able to
+keep back, and I made a clumsy laugh of it, and we sat down together,
+side by side.
+
+'Why, how do you come to be here?' said Steerforth, clapping me on the
+shoulder.
+
+'I came here by the Canterbury coach, today. I have been adopted by
+an aunt down in that part of the country, and have just finished my
+education there. How do YOU come to be here, Steerforth?'
+
+'Well, I am what they call an Oxford man,' he returned; 'that is to say,
+I get bored to death down there, periodically--and I am on my way now to
+my mother's. You're a devilish amiable-looking fellow, Copperfield. Just
+what you used to be, now I look at you! Not altered in the least!'
+
+'I knew you immediately,' I said; 'but you are more easily remembered.'
+
+He laughed as he ran his hand through the clustering curls of his hair,
+and said gaily:
+
+'Yes, I am on an expedition of duty. My mother lives a little way out of
+town; and the roads being in a beastly condition, and our house tedious
+enough, I remained here tonight instead of going on. I have not been in
+town half-a-dozen hours, and those I have been dozing and grumbling away
+at the play.'
+
+'I have been at the play, too,' said I. 'At Covent Garden. What a
+delightful and magnificent entertainment, Steerforth!'
+
+Steerforth laughed heartily.
+
+'My dear young Davy,' he said, clapping me on the shoulder again, 'you
+are a very Daisy. The daisy of the field, at sunrise, is not fresher
+than you are. I have been at Covent Garden, too, and there never was a
+more miserable business. Holloa, you sir!'
+
+This was addressed to the waiter, who had been very attentive to our
+recognition, at a distance, and now came forward deferentially.
+
+'Where have you put my friend, Mr. Copperfield?' said Steerforth.
+
+'Beg your pardon, sir?'
+
+'Where does he sleep? What's his number? You know what I mean,' said
+Steerforth.
+
+'Well, sir,' said the waiter, with an apologetic air. 'Mr. Copperfield
+is at present in forty-four, sir.'
+
+'And what the devil do you mean,' retorted Steerforth, 'by putting Mr.
+Copperfield into a little loft over a stable?'
+
+'Why, you see we wasn't aware, sir,' returned the waiter, still
+apologetically, 'as Mr. Copperfield was anyways particular. We can give
+Mr. Copperfield seventy-two, sir, if it would be preferred. Next you,
+sir.'
+
+'Of course it would be preferred,' said Steerforth. 'And do it at once.'
+The waiter immediately withdrew to make the exchange. Steerforth, very
+much amused at my having been put into forty-four, laughed again, and
+clapped me on the shoulder again, and invited me to breakfast with him
+next morning at ten o'clock--an invitation I was only too proud and
+happy to accept. It being now pretty late, we took our candles and went
+upstairs, where we parted with friendly heartiness at his door, and
+where I found my new room a great improvement on my old one, it not
+being at all musty, and having an immense four-post bedstead in it,
+which was quite a little landed estate. Here, among pillows enough for
+six, I soon fell asleep in a blissful condition, and dreamed of ancient
+Rome, Steerforth, and friendship, until the early morning coaches,
+rumbling out of the archway underneath, made me dream of thunder and the
+gods.
+
+
+
+CHAPTER 20. STEERFORTH'S HOME
+
+
+When the chambermaid tapped at my door at eight o'clock, and informed
+me that my shaving-water was outside, I felt severely the having no
+occasion for it, and blushed in my bed. The suspicion that she laughed
+too, when she said it, preyed upon my mind all the time I was dressing;
+and gave me, I was conscious, a sneaking and guilty air when I passed
+her on the staircase, as I was going down to breakfast. I was so
+sensitively aware, indeed, of being younger than I could have wished,
+that for some time I could not make up my mind to pass her at all, under
+the ignoble circumstances of the case; but, hearing her there with
+a broom, stood peeping out of window at King Charles on horseback,
+surrounded by a maze of hackney-coaches, and looking anything but regal
+in a drizzling rain and a dark-brown fog, until I was admonished by the
+waiter that the gentleman was waiting for me.
+
+It was not in the coffee-room that I found Steerforth expecting me, but
+in a snug private apartment, red-curtained and Turkey-carpeted, where
+the fire burnt bright, and a fine hot breakfast was set forth on a table
+covered with a clean cloth; and a cheerful miniature of the room, the
+fire, the breakfast, Steerforth, and all, was shining in the little
+round mirror over the sideboard. I was rather bashful at first,
+Steerforth being so self-possessed, and elegant, and superior to me in
+all respects (age included); but his easy patronage soon put that to
+rights, and made me quite at home. I could not enough admire the change
+he had wrought in the Golden Cross; or compare the dull forlorn state
+I had held yesterday, with this morning's comfort and this morning's
+entertainment. As to the waiter's familiarity, it was quenched as if it
+had never been. He attended on us, as I may say, in sackcloth and ashes.
+
+'Now, Copperfield,' said Steerforth, when we were alone, 'I should like
+to hear what you are doing, and where you are going, and all about you.
+I feel as if you were my property.' Glowing with pleasure to find that
+he had still this interest in me, I told him how my aunt had proposed
+the little expedition that I had before me, and whither it tended.
+
+'As you are in no hurry, then,' said Steerforth, 'come home with me to
+Highgate, and stay a day or two. You will be pleased with my mother--she
+is a little vain and prosy about me, but that you can forgive her--and
+she will be pleased with you.'
+
+'I should like to be as sure of that, as you are kind enough to say you
+are,' I answered, smiling.
+
+'Oh!' said Steerforth, 'everyone who likes me, has a claim on her that
+is sure to be acknowledged.'
+
+'Then I think I shall be a favourite,' said I.
+
+'Good!' said Steerforth. 'Come and prove it. We will go and see the
+lions for an hour or two--it's something to have a fresh fellow like you
+to show them to, Copperfield--and then we'll journey out to Highgate by
+the coach.'
+
+I could hardly believe but that I was in a dream, and that I should wake
+presently in number forty-four, to the solitary box in the coffee-room
+and the familiar waiter again. After I had written to my aunt and told
+her of my fortunate meeting with my admired old schoolfellow, and my
+acceptance of his invitation, we went out in a hackney-chariot, and saw
+a Panorama and some other sights, and took a walk through the Museum,
+where I could not help observing how much Steerforth knew, on an
+infinite variety of subjects, and of how little account he seemed to
+make his knowledge.
+
+'You'll take a high degree at college, Steerforth,' said I, 'if you have
+not done so already; and they will have good reason to be proud of you.'
+
+'I take a degree!' cried Steerforth. 'Not I! my dear Daisy--will you
+mind my calling you Daisy?'
+
+'Not at all!' said I.
+
+'That's a good fellow! My dear Daisy,' said Steerforth, laughing. 'I
+have not the least desire or intention to distinguish myself in that
+way. I have done quite sufficient for my purpose. I find that I am heavy
+company enough for myself as I am.'
+
+'But the fame--' I was beginning.
+
+'You romantic Daisy!' said Steerforth, laughing still more heartily:
+'why should I trouble myself, that a parcel of heavy-headed fellows may
+gape and hold up their hands? Let them do it at some other man. There's
+fame for him, and he's welcome to it.'
+
+I was abashed at having made so great a mistake, and was glad to change
+the subject. Fortunately it was not difficult to do, for Steerforth
+could always pass from one subject to another with a carelessness and
+lightness that were his own.
+
+Lunch succeeded to our sight-seeing, and the short winter day wore away
+so fast, that it was dusk when the stage-coach stopped with us at an
+old brick house at Highgate on the summit of the hill. An elderly lady,
+though not very far advanced in years, with a proud carriage and
+a handsome face, was in the doorway as we alighted; and greeting
+Steerforth as 'My dearest James,' folded him in her arms. To this lady
+he presented me as his mother, and she gave me a stately welcome.
+
+It was a genteel old-fashioned house, very quiet and orderly. From the
+windows of my room I saw all London lying in the distance like a great
+vapour, with here and there some lights twinkling through it. I had only
+time, in dressing, to glance at the solid furniture, the framed pieces
+of work (done, I supposed, by Steerforth's mother when she was a girl),
+and some pictures in crayons of ladies with powdered hair and bodices,
+coming and going on the walls, as the newly-kindled fire crackled and
+sputtered, when I was called to dinner.
+
+There was a second lady in the dining-room, of a slight short figure,
+dark, and not agreeable to look at, but with some appearance of good
+looks too, who attracted my attention: perhaps because I had not
+expected to see her; perhaps because I found myself sitting opposite
+to her; perhaps because of something really remarkable in her. She had
+black hair and eager black eyes, and was thin, and had a scar upon her
+lip. It was an old scar--I should rather call it seam, for it was not
+discoloured, and had healed years ago--which had once cut through her
+mouth, downward towards the chin, but was now barely visible across
+the table, except above and on her upper lip, the shape of which it had
+altered. I concluded in my own mind that she was about thirty years
+of age, and that she wished to be married. She was a little
+dilapidated--like a house--with having been so long to let; yet had, as
+I have said, an appearance of good looks. Her thinness seemed to be the
+effect of some wasting fire within her, which found a vent in her gaunt
+eyes.
+
+She was introduced as Miss Dartle, and both Steerforth and his mother
+called her Rosa. I found that she lived there, and had been for a long
+time Mrs. Steerforth's companion. It appeared to me that she never said
+anything she wanted to say, outright; but hinted it, and made a great
+deal more of it by this practice. For example, when Mrs. Steerforth
+observed, more in jest than earnest, that she feared her son led but a
+wild life at college, Miss Dartle put in thus:
+
+'Oh, really? You know how ignorant I am, and that I only ask for
+information, but isn't it always so? I thought that kind of life was
+on all hands understood to be--eh?' 'It is education for a very grave
+profession, if you mean that, Rosa,' Mrs. Steerforth answered with some
+coldness.
+
+'Oh! Yes! That's very true,' returned Miss Dartle. 'But isn't it,
+though?--I want to be put right, if I am wrong--isn't it, really?'
+
+'Really what?' said Mrs. Steerforth.
+
+'Oh! You mean it's not!' returned Miss Dartle. 'Well, I'm very glad to
+hear it! Now, I know what to do! That's the advantage of asking. I shall
+never allow people to talk before me about wastefulness and profligacy,
+and so forth, in connexion with that life, any more.'
+
+'And you will be right,' said Mrs. Steerforth. 'My son's tutor is a
+conscientious gentleman; and if I had not implicit reliance on my son, I
+should have reliance on him.'
+
+'Should you?' said Miss Dartle. 'Dear me! Conscientious, is he? Really
+conscientious, now?'
+
+'Yes, I am convinced of it,' said Mrs. Steerforth.
+
+'How very nice!' exclaimed Miss Dartle. 'What a comfort! Really
+conscientious? Then he's not--but of course he can't be, if he's really
+conscientious. Well, I shall be quite happy in my opinion of him, from
+this time. You can't think how it elevates him in my opinion, to know
+for certain that he's really conscientious!'
+
+Her own views of every question, and her correction of everything that
+was said to which she was opposed, Miss Dartle insinuated in the same
+way: sometimes, I could not conceal from myself, with great power,
+though in contradiction even of Steerforth. An instance happened before
+dinner was done. Mrs. Steerforth speaking to me about my intention
+of going down into Suffolk, I said at hazard how glad I should be, if
+Steerforth would only go there with me; and explaining to him that I was
+going to see my old nurse, and Mr. Peggotty's family, I reminded him of
+the boatman whom he had seen at school.
+
+'Oh! That bluff fellow!' said Steerforth. 'He had a son with him, hadn't
+he?'
+
+'No. That was his nephew,' I replied; 'whom he adopted, though, as
+a son. He has a very pretty little niece too, whom he adopted as a
+daughter. In short, his house--or rather his boat, for he lives in one,
+on dry land--is full of people who are objects of his generosity and
+kindness. You would be delighted to see that household.'
+
+'Should I?' said Steerforth. 'Well, I think I should. I must see what
+can be done. It would be worth a journey (not to mention the pleasure of
+a journey with you, Daisy), to see that sort of people together, and to
+make one of 'em.'
+
+My heart leaped with a new hope of pleasure. But it was in reference
+to the tone in which he had spoken of 'that sort of people', that Miss
+Dartle, whose sparkling eyes had been watchful of us, now broke in
+again.
+
+'Oh, but, really? Do tell me. Are they, though?' she said.
+
+'Are they what? And are who what?' said Steerforth.
+
+'That sort of people.---Are they really animals and clods, and beings of
+another order? I want to know SO much.'
+
+'Why, there's a pretty wide separation between them and us,' said
+Steerforth, with indifference. 'They are not to be expected to be
+as sensitive as we are. Their delicacy is not to be shocked, or hurt
+easily. They are wonderfully virtuous, I dare say--some people contend
+for that, at least; and I am sure I don't want to contradict them--but
+they have not very fine natures, and they may be thankful that, like
+their coarse rough skins, they are not easily wounded.'
+
+'Really!' said Miss Dartle. 'Well, I don't know, now, when I have been
+better pleased than to hear that. It's so consoling! It's such a delight
+to know that, when they suffer, they don't feel! Sometimes I have been
+quite uneasy for that sort of people; but now I shall just dismiss the
+idea of them, altogether. Live and learn. I had my doubts, I confess,
+but now they're cleared up. I didn't know, and now I do know, and that
+shows the advantage of asking--don't it?'
+
+I believed that Steerforth had said what he had, in jest, or to draw
+Miss Dartle out; and I expected him to say as much when she was gone,
+and we two were sitting before the fire. But he merely asked me what I
+thought of her.
+
+'She is very clever, is she not?' I asked.
+
+'Clever! She brings everything to a grindstone,' said Steerforth, and
+sharpens it, as she has sharpened her own face and figure these years
+past. She has worn herself away by constant sharpening. She is all
+edge.'
+
+'What a remarkable scar that is upon her lip!' I said.
+
+Steerforth's face fell, and he paused a moment.
+
+'Why, the fact is,' he returned, 'I did that.'
+
+'By an unfortunate accident!'
+
+'No. I was a young boy, and she exasperated me, and I threw a hammer at
+her. A promising young angel I must have been!' I was deeply sorry to
+have touched on such a painful theme, but that was useless now.
+
+'She has borne the mark ever since, as you see,' said Steerforth; 'and
+she'll bear it to her grave, if she ever rests in one--though I can
+hardly believe she will ever rest anywhere. She was the motherless child
+of a sort of cousin of my father's. He died one day. My mother, who was
+then a widow, brought her here to be company to her. She has a couple of
+thousand pounds of her own, and saves the interest of it every year, to
+add to the principal. There's the history of Miss Rosa Dartle for you.'
+
+'And I have no doubt she loves you like a brother?' said I.
+
+'Humph!' retorted Steerforth, looking at the fire. 'Some brothers are
+not loved over much; and some love--but help yourself, Copperfield!
+We'll drink the daisies of the field, in compliment to you; and the
+lilies of the valley that toil not, neither do they spin, in compliment
+to me--the more shame for me!' A moody smile that had overspread his
+features cleared off as he said this merrily, and he was his own frank,
+winning self again.
+
+I could not help glancing at the scar with a painful interest when we
+went in to tea. It was not long before I observed that it was the most
+susceptible part of her face, and that, when she turned pale, that mark
+altered first, and became a dull, lead-coloured streak, lengthening out
+to its full extent, like a mark in invisible ink brought to the fire.
+There was a little altercation between her and Steerforth about a cast
+of the dice at back gammon--when I thought her, for one moment, in a
+storm of rage; and then I saw it start forth like the old writing on the
+wall.
+
+It was no matter of wonder to me to find Mrs. Steerforth devoted to her
+son. She seemed to be able to speak or think about nothing else. She
+showed me his picture as an infant, in a locket, with some of his
+baby-hair in it; she showed me his picture as he had been when I first
+knew him; and she wore at her breast his picture as he was now. All the
+letters he had ever written to her, she kept in a cabinet near her own
+chair by the fire; and she would have read me some of them, and I should
+have been very glad to hear them too, if he had not interposed, and
+coaxed her out of the design.
+
+'It was at Mr. Creakle's, my son tells me, that you first became
+acquainted,' said Mrs. Steerforth, as she and I were talking at one
+table, while they played backgammon at another. 'Indeed, I recollect his
+speaking, at that time, of a pupil younger than himself who had taken
+his fancy there; but your name, as you may suppose, has not lived in my
+memory.'
+
+'He was very generous and noble to me in those days, I assure you,
+ma'am,' said I, 'and I stood in need of such a friend. I should have
+been quite crushed without him.'
+
+'He is always generous and noble,' said Mrs. Steerforth, proudly.
+
+I subscribed to this with all my heart, God knows. She knew I did; for
+the stateliness of her manner already abated towards me, except when she
+spoke in praise of him, and then her air was always lofty.
+
+'It was not a fit school generally for my son,' said she; 'far from it;
+but there were particular circumstances to be considered at the time, of
+more importance even than that selection. My son's high spirit made
+it desirable that he should be placed with some man who felt its
+superiority, and would be content to bow himself before it; and we found
+such a man there.'
+
+I knew that, knowing the fellow. And yet I did not despise him the more
+for it, but thought it a redeeming quality in him if he could be allowed
+any grace for not resisting one so irresistible as Steerforth.
+
+'My son's great capacity was tempted on, there, by a feeling of
+voluntary emulation and conscious pride,' the fond lady went on to say.
+'He would have risen against all constraint; but he found himself the
+monarch of the place, and he haughtily determined to be worthy of his
+station. It was like himself.'
+
+I echoed, with all my heart and soul, that it was like himself.
+
+'So my son took, of his own will, and on no compulsion, to the course
+in which he can always, when it is his pleasure, outstrip every
+competitor,' she pursued. 'My son informs me, Mr. Copperfield, that
+you were quite devoted to him, and that when you met yesterday you made
+yourself known to him with tears of joy. I should be an affected woman
+if I made any pretence of being surprised by my son's inspiring such
+emotions; but I cannot be indifferent to anyone who is so sensible of
+his merit, and I am very glad to see you here, and can assure you that
+he feels an unusual friendship for you, and that you may rely on his
+protection.'
+
+Miss Dartle played backgammon as eagerly as she did everything else.
+If I had seen her, first, at the board, I should have fancied that her
+figure had got thin, and her eyes had got large, over that pursuit, and
+no other in the world. But I am very much mistaken if she missed a
+word of this, or lost a look of mine as I received it with the utmost
+pleasure, and honoured by Mrs. Steerforth's confidence, felt older than
+I had done since I left Canterbury.
+
+When the evening was pretty far spent, and a tray of glasses and
+decanters came in, Steerforth promised, over the fire, that he would
+seriously think of going down into the country with me. There was no
+hurry, he said; a week hence would do; and his mother hospitably said
+the same. While we were talking, he more than once called me Daisy;
+which brought Miss Dartle out again.
+
+'But really, Mr. Copperfield,' she asked, 'is it a nickname? And
+why does he give it you? Is it--eh?--because he thinks you young and
+innocent? I am so stupid in these things.'
+
+I coloured in replying that I believed it was.
+
+'Oh!' said Miss Dartle. 'Now I am glad to know that! I ask for
+information, and I am glad to know it. He thinks you young and innocent;
+and so you are his friend. Well, that's quite delightful!'
+
+She went to bed soon after this, and Mrs. Steerforth retired too.
+Steerforth and I, after lingering for half-an-hour over the fire,
+talking about Traddles and all the rest of them at old Salem House, went
+upstairs together. Steerforth's room was next to mine, and I went in to
+look at it. It was a picture of comfort, full of easy-chairs, cushions
+and footstools, worked by his mother's hand, and with no sort of thing
+omitted that could help to render it complete. Finally, her handsome
+features looked down on her darling from a portrait on the wall, as if
+it were even something to her that her likeness should watch him while
+he slept.
+
+I found the fire burning clear enough in my room by this time, and the
+curtains drawn before the windows and round the bed, giving it a very
+snug appearance. I sat down in a great chair upon the hearth to meditate
+on my happiness; and had enjoyed the contemplation of it for some time,
+when I found a likeness of Miss Dartle looking eagerly at me from above
+the chimney-piece.
+
+It was a startling likeness, and necessarily had a startling look. The
+painter hadn't made the scar, but I made it; and there it was, coming
+and going; now confined to the upper lip as I had seen it at dinner, and
+now showing the whole extent of the wound inflicted by the hammer, as I
+had seen it when she was passionate.
+
+I wondered peevishly why they couldn't put her anywhere else instead
+of quartering her on me. To get rid of her, I undressed quickly,
+extinguished my light, and went to bed. But, as I fell asleep, I could
+not forget that she was still there looking, 'Is it really, though?
+I want to know'; and when I awoke in the night, I found that I was
+uneasily asking all sorts of people in my dreams whether it really was
+or not--without knowing what I meant.
+
+
+
+CHAPTER 21. LITTLE EM'LY
+
+
+There was a servant in that house, a man who, I understood, was usually
+with Steerforth, and had come into his service at the University, who
+was in appearance a pattern of respectability. I believe there never
+existed in his station a more respectable-looking man. He was taciturn,
+soft-footed, very quiet in his manner, deferential, observant, always at
+hand when wanted, and never near when not wanted; but his great claim to
+consideration was his respectability. He had not a pliant face, he had
+rather a stiff neck, rather a tight smooth head with short hair clinging
+to it at the sides, a soft way of speaking, with a peculiar habit of
+whispering the letter S so distinctly, that he seemed to use it
+oftener than any other man; but every peculiarity that he had he made
+respectable. If his nose had been upside-down, he would have made that
+respectable. He surrounded himself with an atmosphere of respectability,
+and walked secure in it. It would have been next to impossible to
+suspect him of anything wrong, he was so thoroughly respectable.
+Nobody could have thought of putting him in a livery, he was so highly
+respectable. To have imposed any derogatory work upon him, would have
+been to inflict a wanton insult on the feelings of a most respectable
+man. And of this, I noticed--the women-servants in the household were
+so intuitively conscious, that they always did such work themselves, and
+generally while he read the paper by the pantry fire.
+
+Such a self-contained man I never saw. But in that quality, as in every
+other he possessed, he only seemed to be the more respectable. Even the
+fact that no one knew his Christian name, seemed to form a part of his
+respectability. Nothing could be objected against his surname, Littimer,
+by which he was known. Peter might have been hanged, or Tom transported;
+but Littimer was perfectly respectable.
+
+It was occasioned, I suppose, by the reverend nature of respectability
+in the abstract, but I felt particularly young in this man's presence.
+How old he was himself, I could not guess--and that again went to his
+credit on the same score; for in the calmness of respectability he might
+have numbered fifty years as well as thirty.
+
+Littimer was in my room in the morning before I was up, to bring me that
+reproachful shaving-water, and to put out my clothes. When I undrew the
+curtains and looked out of bed, I saw him, in an equable temperature
+of respectability, unaffected by the east wind of January, and not
+even breathing frostily, standing my boots right and left in the first
+dancing position, and blowing specks of dust off my coat as he laid it
+down like a baby.
+
+I gave him good morning, and asked him what o'clock it was. He took
+out of his pocket the most respectable hunting-watch I ever saw, and
+preventing the spring with his thumb from opening far, looked in at the
+face as if he were consulting an oracular oyster, shut it up again, and
+said, if I pleased, it was half past eight.
+
+'Mr. Steerforth will be glad to hear how you have rested, sir.'
+
+'Thank you,' said I, 'very well indeed. Is Mr. Steerforth quite well?'
+
+'Thank you, sir, Mr. Steerforth is tolerably well.' Another of his
+characteristics--no use of superlatives. A cool calm medium always.
+
+'Is there anything more I can have the honour of doing for you, sir? The
+warning-bell will ring at nine; the family take breakfast at half past
+nine.'
+
+'Nothing, I thank you.'
+
+'I thank YOU, sir, if you please'; and with that, and with a little
+inclination of his head when he passed the bed-side, as an apology for
+correcting me, he went out, shutting the door as delicately as if I had
+just fallen into a sweet sleep on which my life depended.
+
+Every morning we held exactly this conversation: never any more, and
+never any less: and yet, invariably, however far I might have been
+lifted out of myself over-night, and advanced towards maturer years,
+by Steerforth's companionship, or Mrs. Steerforth's confidence, or Miss
+Dartle's conversation, in the presence of this most respectable man I
+became, as our smaller poets sing, 'a boy again'.
+
+He got horses for us; and Steerforth, who knew everything, gave me
+lessons in riding. He provided foils for us, and Steerforth gave me
+lessons in fencing--gloves, and I began, of the same master, to improve
+in boxing. It gave me no manner of concern that Steerforth should find
+me a novice in these sciences, but I never could bear to show my want of
+skill before the respectable Littimer. I had no reason to believe
+that Littimer understood such arts himself; he never led me to suppose
+anything of the kind, by so much as the vibration of one of his
+respectable eyelashes; yet whenever he was by, while we were practising,
+I felt myself the greenest and most inexperienced of mortals.
+
+I am particular about this man, because he made a particular effect on
+me at that time, and because of what took place thereafter.
+
+The week passed away in a most delightful manner. It passed rapidly, as
+may be supposed, to one entranced as I was; and yet it gave me so many
+occasions for knowing Steerforth better, and admiring him more in a
+thousand respects, that at its close I seemed to have been with him
+for a much longer time. A dashing way he had of treating me like a
+plaything, was more agreeable to me than any behaviour he could have
+adopted. It reminded me of our old acquaintance; it seemed the natural
+sequel of it; it showed me that he was unchanged; it relieved me of
+any uneasiness I might have felt, in comparing my merits with his, and
+measuring my claims upon his friendship by any equal standard; above
+all, it was a familiar, unrestrained, affectionate demeanour that he
+used towards no one else. As he had treated me at school differently
+from all the rest, I joyfully believed that he treated me in life unlike
+any other friend he had. I believed that I was nearer to his heart than
+any other friend, and my own heart warmed with attachment to him. He
+made up his mind to go with me into the country, and the day arrived for
+our departure. He had been doubtful at first whether to take Littimer
+or not, but decided to leave him at home. The respectable creature,
+satisfied with his lot whatever it was, arranged our portmanteaux on
+the little carriage that was to take us into London, as if they were
+intended to defy the shocks of ages, and received my modestly proffered
+donation with perfect tranquillity.
+
+We bade adieu to Mrs. Steerforth and Miss Dartle, with many thanks on
+my part, and much kindness on the devoted mother's. The last thing I
+saw was Littimer's unruffled eye; fraught, as I fancied, with the silent
+conviction that I was very young indeed.
+
+What I felt, in returning so auspiciously to the old familiar places,
+I shall not endeavour to describe. We went down by the Mail. I was
+so concerned, I recollect, even for the honour of Yarmouth, that when
+Steerforth said, as we drove through its dark streets to the inn, that,
+as well as he could make out, it was a good, queer, out-of-the-way kind
+of hole, I was highly pleased. We went to bed on our arrival (I observed
+a pair of dirty shoes and gaiters in connexion with my old friend the
+Dolphin as we passed that door), and breakfasted late in the morning.
+Steerforth, who was in great spirits, had been strolling about the
+beach before I was up, and had made acquaintance, he said, with half the
+boatmen in the place. Moreover, he had seen, in the distance, what he
+was sure must be the identical house of Mr. Peggotty, with smoke coming
+out of the chimney; and had had a great mind, he told me, to walk in and
+swear he was myself grown out of knowledge.
+
+'When do you propose to introduce me there, Daisy?' he said. 'I am at
+your disposal. Make your own arrangements.'
+
+'Why, I was thinking that this evening would be a good time, Steerforth,
+when they are all sitting round the fire. I should like you to see it
+when it's snug, it's such a curious place.'
+
+'So be it!' returned Steerforth. 'This evening.'
+
+'I shall not give them any notice that we are here, you know,' said I,
+delighted. 'We must take them by surprise.'
+
+'Oh, of course! It's no fun,' said Steerforth, 'unless we take them by
+surprise. Let us see the natives in their aboriginal condition.'
+
+'Though they ARE that sort of people that you mentioned,' I returned.
+
+'Aha! What! you recollect my skirmishes with Rosa, do you?' he exclaimed
+with a quick look. 'Confound the girl, I am half afraid of her. She's
+like a goblin to me. But never mind her. Now what are you going to do?
+You are going to see your nurse, I suppose?'
+
+'Why, yes,' I said, 'I must see Peggotty first of all.'
+
+'Well,' replied Steerforth, looking at his watch. 'Suppose I deliver you
+up to be cried over for a couple of hours. Is that long enough?'
+
+I answered, laughing, that I thought we might get through it in that
+time, but that he must come also; for he would find that his renown had
+preceded him, and that he was almost as great a personage as I was.
+
+'I'll come anywhere you like,' said Steerforth, 'or do anything you
+like. Tell me where to come to; and in two hours I'll produce myself in
+any state you please, sentimental or comical.'
+
+I gave him minute directions for finding the residence of Mr. Barkis,
+carrier to Blunderstone and elsewhere; and, on this understanding, went
+out alone. There was a sharp bracing air; the ground was dry; the sea
+was crisp and clear; the sun was diffusing abundance of light, if not
+much warmth; and everything was fresh and lively. I was so fresh and
+lively myself, in the pleasure of being there, that I could have stopped
+the people in the streets and shaken hands with them.
+
+The streets looked small, of course. The streets that we have only seen
+as children always do, I believe, when we go back to them. But I had
+forgotten nothing in them, and found nothing changed, until I came to
+Mr. Omer's shop. OMER AND Joram was now written up, where OMER used to
+be; but the inscription, DRAPER, TAILOR, HABERDASHER, FUNERAL FURNISHER,
+&c., remained as it was.
+
+My footsteps seemed to tend so naturally to the shop door, after I had
+read these words from over the way, that I went across the road and
+looked in. There was a pretty woman at the back of the shop, dancing
+a little child in her arms, while another little fellow clung to her
+apron. I had no difficulty in recognizing either Minnie or Minnie's
+children. The glass door of the parlour was not open; but in the
+workshop across the yard I could faintly hear the old tune playing, as
+if it had never left off.
+
+'Is Mr. Omer at home?' said I, entering. 'I should like to see him, for
+a moment, if he is.'
+
+'Oh yes, sir, he is at home,' said Minnie; 'the weather don't suit his
+asthma out of doors. Joe, call your grandfather!'
+
+The little fellow, who was holding her apron, gave such a lusty shout,
+that the sound of it made him bashful, and he buried his face in her
+skirts, to her great admiration. I heard a heavy puffing and blowing
+coming towards us, and soon Mr. Omer, shorter-winded than of yore, but
+not much older-looking, stood before me.
+
+'Servant, sir,' said Mr. Omer. 'What can I do for you, sir?' 'You can
+shake hands with me, Mr. Omer, if you please,' said I, putting out my
+own. 'You were very good-natured to me once, when I am afraid I didn't
+show that I thought so.'
+
+'Was I though?' returned the old man. 'I'm glad to hear it, but I don't
+remember when. Are you sure it was me?'
+
+'Quite.'
+
+'I think my memory has got as short as my breath,' said Mr. Omer,
+looking at me and shaking his head; 'for I don't remember you.'
+
+'Don't you remember your coming to the coach to meet me, and my having
+breakfast here, and our riding out to Blunderstone together: you, and I,
+and Mrs. Joram, and Mr. Joram too--who wasn't her husband then?'
+
+'Why, Lord bless my soul!' exclaimed Mr. Omer, after being thrown by his
+surprise into a fit of coughing, 'you don't say so! Minnie, my dear, you
+recollect? Dear me, yes; the party was a lady, I think?'
+
+'My mother,' I rejoined.
+
+'To--be--sure,' said Mr. Omer, touching my waistcoat with his
+forefinger, 'and there was a little child too! There was two parties.
+The little party was laid along with the other party. Over at
+Blunderstone it was, of course. Dear me! And how have you been since?'
+
+Very well, I thanked him, as I hoped he had been too.
+
+'Oh! nothing to grumble at, you know,' said Mr. Omer. 'I find my breath
+gets short, but it seldom gets longer as a man gets older. I take it as
+it comes, and make the most of it. That's the best way, ain't it?'
+
+Mr. Omer coughed again, in consequence of laughing, and was assisted out
+of his fit by his daughter, who now stood close beside us, dancing her
+smallest child on the counter.
+
+'Dear me!' said Mr. Omer. 'Yes, to be sure. Two parties! Why, in that
+very ride, if you'll believe me, the day was named for my Minnie to
+marry Joram. "Do name it, sir," says Joram. "Yes, do, father," says
+Minnie. And now he's come into the business. And look here! The
+youngest!'
+
+Minnie laughed, and stroked her banded hair upon her temples, as her
+father put one of his fat fingers into the hand of the child she was
+dancing on the counter.
+
+'Two parties, of course!' said Mr. Omer, nodding his head
+retrospectively. 'Ex-actly so! And Joram's at work, at this minute, on
+a grey one with silver nails, not this measurement'--the measurement of
+the dancing child upon the counter--'by a good two inches.---Will you
+take something?'
+
+I thanked him, but declined.
+
+'Let me see,' said Mr. Omer. 'Barkis's the carrier's wife--Peggotty's
+the boatman's sister--she had something to do with your family? She was
+in service there, sure?'
+
+My answering in the affirmative gave him great satisfaction.
+
+'I believe my breath will get long next, my memory's getting so much
+so,' said Mr. Omer. 'Well, sir, we've got a young relation of hers here,
+under articles to us, that has as elegant a taste in the dress-making
+business--I assure you I don't believe there's a Duchess in England can
+touch her.'
+
+'Not little Em'ly?' said I, involuntarily.
+
+'Em'ly's her name,' said Mr. Omer, 'and she's little too. But if you'll
+believe me, she has such a face of her own that half the women in this
+town are mad against her.'
+
+'Nonsense, father!' cried Minnie.
+
+'My dear,' said Mr. Omer, 'I don't say it's the case with you,' winking
+at me, 'but I say that half the women in Yarmouth--ah! and in five mile
+round--are mad against that girl.'
+
+'Then she should have kept to her own station in life, father,' said
+Minnie, 'and not have given them any hold to talk about her, and then
+they couldn't have done it.'
+
+'Couldn't have done it, my dear!' retorted Mr. Omer. 'Couldn't have
+done it! Is that YOUR knowledge of life? What is there that any woman
+couldn't do, that she shouldn't do--especially on the subject of another
+woman's good looks?'
+
+I really thought it was all over with Mr. Omer, after he had uttered
+this libellous pleasantry. He coughed to that extent, and his breath
+eluded all his attempts to recover it with that obstinacy, that I fully
+expected to see his head go down behind the counter, and his little
+black breeches, with the rusty little bunches of ribbons at the knees,
+come quivering up in a last ineffectual struggle. At length, however,
+he got better, though he still panted hard, and was so exhausted that he
+was obliged to sit on the stool of the shop-desk.
+
+'You see,' he said, wiping his head, and breathing with difficulty, 'she
+hasn't taken much to any companions here; she hasn't taken kindly to
+any particular acquaintances and friends, not to mention sweethearts. In
+consequence, an ill-natured story got about, that Em'ly wanted to be a
+lady. Now my opinion is, that it came into circulation principally on
+account of her sometimes saying, at the school, that if she was a lady
+she would like to do so-and-so for her uncle--don't you see?--and buy
+him such-and-such fine things.'
+
+'I assure you, Mr. Omer, she has said so to me,' I returned eagerly,
+'when we were both children.'
+
+Mr. Omer nodded his head and rubbed his chin. 'Just so. Then out of a
+very little, she could dress herself, you see, better than most others
+could out of a deal, and that made things unpleasant. Moreover, she was
+rather what might be called wayward--I'll go so far as to say what I
+should call wayward myself,' said Mr. Omer; '-didn't know her own mind
+quite--a little spoiled--and couldn't, at first, exactly bind herself
+down. No more than that was ever said against her, Minnie?'
+
+'No, father,' said Mrs. Joram. 'That's the worst, I believe.'
+
+'So when she got a situation,' said Mr. Omer, 'to keep a fractious old
+lady company, they didn't very well agree, and she didn't stop. At last
+she came here, apprenticed for three years. Nearly two of 'em are over,
+and she has been as good a girl as ever was. Worth any six! Minnie, is
+she worth any six, now?'
+
+'Yes, father,' replied Minnie. 'Never say I detracted from her!'
+
+'Very good,' said Mr. Omer. 'That's right. And so, young gentleman,' he
+added, after a few moments' further rubbing of his chin, 'that you may
+not consider me long-winded as well as short-breathed, I believe that's
+all about it.'
+
+As they had spoken in a subdued tone, while speaking of Em'ly, I had no
+doubt that she was near. On my asking now, if that were not so, Mr.
+Omer nodded yes, and nodded towards the door of the parlour. My hurried
+inquiry if I might peep in, was answered with a free permission; and,
+looking through the glass, I saw her sitting at her work. I saw her, a
+most beautiful little creature, with the cloudless blue eyes, that had
+looked into my childish heart, turned laughingly upon another child
+of Minnie's who was playing near her; with enough of wilfulness in her
+bright face to justify what I had heard; with much of the old capricious
+coyness lurking in it; but with nothing in her pretty looks, I am sure,
+but what was meant for goodness and for happiness, and what was on a
+good and happy course.
+
+The tune across the yard that seemed as if it never had left off--alas!
+it was the tune that never DOES leave off--was beating, softly, all the
+while.
+
+'Wouldn't you like to step in,' said Mr. Omer, 'and speak to her? Walk
+in and speak to her, sir! Make yourself at home!'
+
+I was too bashful to do so then--I was afraid of confusing her, and I
+was no less afraid of confusing myself.--but I informed myself of the
+hour at which she left of an evening, in order that our visit might
+be timed accordingly; and taking leave of Mr. Omer, and his pretty
+daughter, and her little children, went away to my dear old Peggotty's.
+
+Here she was, in the tiled kitchen, cooking dinner! The moment I knocked
+at the door she opened it, and asked me what I pleased to want. I looked
+at her with a smile, but she gave me no smile in return. I had never
+ceased to write to her, but it must have been seven years since we had
+met.
+
+'Is Mr. Barkis at home, ma'am?' I said, feigning to speak roughly to
+her.
+
+'He's at home, sir,' returned Peggotty, 'but he's bad abed with the
+rheumatics.'
+
+'Don't he go over to Blunderstone now?' I asked.
+
+'When he's well he do,' she answered.
+
+'Do YOU ever go there, Mrs. Barkis?'
+
+She looked at me more attentively, and I noticed a quick movement of her
+hands towards each other.
+
+'Because I want to ask a question about a house there, that they call
+the--what is it?--the Rookery,' said I.
+
+She took a step backward, and put out her hands in an undecided
+frightened way, as if to keep me off.
+
+'Peggotty!' I cried to her.
+
+She cried, 'My darling boy!' and we both burst into tears, and were
+locked in one another's arms.
+
+What extravagances she committed; what laughing and crying over me; what
+pride she showed, what joy, what sorrow that she whose pride and joy I
+might have been, could never hold me in a fond embrace; I have not the
+heart to tell. I was troubled with no misgiving that it was young in
+me to respond to her emotions. I had never laughed and cried in all my
+life, I dare say--not even to her--more freely than I did that morning.
+
+'Barkis will be so glad,' said Peggotty, wiping her eyes with her apron,
+'that it'll do him more good than pints of liniment. May I go and tell
+him you are here? Will you come up and see him, my dear?'
+
+Of course I would. But Peggotty could not get out of the room as easily
+as she meant to, for as often as she got to the door and looked round
+at me, she came back again to have another laugh and another cry upon my
+shoulder. At last, to make the matter easier, I went upstairs with
+her; and having waited outside for a minute, while she said a word of
+preparation to Mr. Barkis, presented myself before that invalid.
+
+He received me with absolute enthusiasm. He was too rheumatic to be
+shaken hands with, but he begged me to shake the tassel on the top of
+his nightcap, which I did most cordially. When I sat down by the side
+of the bed, he said that it did him a world of good to feel as if he
+was driving me on the Blunderstone road again. As he lay in bed, face
+upward, and so covered, with that exception, that he seemed to be
+nothing but a face--like a conventional cherubim--he looked the queerest
+object I ever beheld.
+
+'What name was it, as I wrote up in the cart, sir?' said Mr. Barkis,
+with a slow rheumatic smile.
+
+'Ah! Mr. Barkis, we had some grave talks about that matter, hadn't we?'
+
+'I was willin' a long time, sir?' said Mr. Barkis.
+
+'A long time,' said I.
+
+'And I don't regret it,' said Mr. Barkis. 'Do you remember what you
+told me once, about her making all the apple parsties and doing all the
+cooking?'
+
+'Yes, very well,' I returned.
+
+'It was as true,' said Mr. Barkis, 'as turnips is. It was as true,' said
+Mr. Barkis, nodding his nightcap, which was his only means of emphasis,
+'as taxes is. And nothing's truer than them.'
+
+Mr. Barkis turned his eyes upon me, as if for my assent to this result
+of his reflections in bed; and I gave it.
+
+'Nothing's truer than them,' repeated Mr. Barkis; 'a man as poor as I
+am, finds that out in his mind when he's laid up. I'm a very poor man,
+sir!'
+
+'I am sorry to hear it, Mr. Barkis.'
+
+'A very poor man, indeed I am,' said Mr. Barkis.
+
+Here his right hand came slowly and feebly from under the bedclothes,
+and with a purposeless uncertain grasp took hold of a stick which was
+loosely tied to the side of the bed. After some poking about with
+this instrument, in the course of which his face assumed a variety of
+distracted expressions, Mr. Barkis poked it against a box, an end
+of which had been visible to me all the time. Then his face became
+composed.
+
+'Old clothes,' said Mr. Barkis.
+
+'Oh!' said I.
+
+'I wish it was Money, sir,' said Mr. Barkis.
+
+'I wish it was, indeed,' said I.
+
+'But it AIN'T,' said Mr. Barkis, opening both his eyes as wide as he
+possibly could.
+
+I expressed myself quite sure of that, and Mr. Barkis, turning his eyes
+more gently to his wife, said:
+
+'She's the usefullest and best of women, C. P. Barkis. All the praise
+that anyone can give to C. P. Barkis, she deserves, and more! My dear,
+you'll get a dinner today, for company; something good to eat and drink,
+will you?'
+
+I should have protested against this unnecessary demonstration in
+my honour, but that I saw Peggotty, on the opposite side of the bed,
+extremely anxious I should not. So I held my peace.
+
+'I have got a trifle of money somewhere about me, my dear,' said Mr.
+Barkis, 'but I'm a little tired. If you and Mr. David will leave me for
+a short nap, I'll try and find it when I wake.'
+
+We left the room, in compliance with this request. When we got outside
+the door, Peggotty informed me that Mr. Barkis, being now 'a little
+nearer' than he used to be, always resorted to this same device before
+producing a single coin from his store; and that he endured unheard-of
+agonies in crawling out of bed alone, and taking it from that unlucky
+box. In effect, we presently heard him uttering suppressed groans of the
+most dismal nature, as this magpie proceeding racked him in every joint;
+but while Peggotty's eyes were full of compassion for him, she said his
+generous impulse would do him good, and it was better not to check it.
+So he groaned on, until he had got into bed again, suffering, I have no
+doubt, a martyrdom; and then called us in, pretending to have just
+woke up from a refreshing sleep, and to produce a guinea from under his
+pillow. His satisfaction in which happy imposition on us, and in
+having preserved the impenetrable secret of the box, appeared to be a
+sufficient compensation to him for all his tortures.
+
+I prepared Peggotty for Steerforth's arrival and it was not long before
+he came. I am persuaded she knew no difference between his having been a
+personal benefactor of hers, and a kind friend to me, and that she would
+have received him with the utmost gratitude and devotion in any case.
+But his easy, spirited good humour; his genial manner, his handsome
+looks, his natural gift of adapting himself to whomsoever he pleased,
+and making direct, when he cared to do it, to the main point of interest
+in anybody's heart; bound her to him wholly in five minutes. His
+manner to me, alone, would have won her. But, through all these causes
+combined, I sincerely believe she had a kind of adoration for him before
+he left the house that night.
+
+He stayed there with me to dinner--if I were to say willingly, I should
+not half express how readily and gaily. He went into Mr. Barkis's room
+like light and air, brightening and refreshing it as if he were healthy
+weather. There was no noise, no effort, no consciousness, in anything
+he did; but in everything an indescribable lightness, a seeming
+impossibility of doing anything else, or doing anything better, which
+was so graceful, so natural, and agreeable, that it overcomes me, even
+now, in the remembrance.
+
+We made merry in the little parlour, where the Book of Martyrs,
+unthumbed since my time, was laid out upon the desk as of old, and where
+I now turned over its terrific pictures, remembering the old sensations
+they had awakened, but not feeling them. When Peggotty spoke of what
+she called my room, and of its being ready for me at night, and of her
+hoping I would occupy it, before I could so much as look at Steerforth,
+hesitating, he was possessed of the whole case.
+
+'Of course,' he said. 'You'll sleep here, while we stay, and I shall
+sleep at the hotel.'
+
+'But to bring you so far,' I returned, 'and to separate, seems bad
+companionship, Steerforth.'
+
+'Why, in the name of Heaven, where do you naturally belong?' he said.
+'What is "seems", compared to that?' It was settled at once.
+
+He maintained all his delightful qualities to the last, until we started
+forth, at eight o'clock, for Mr. Peggotty's boat. Indeed, they were more
+and more brightly exhibited as the hours went on; for I thought even
+then, and I have no doubt now, that the consciousness of success in his
+determination to please, inspired him with a new delicacy of perception,
+and made it, subtle as it was, more easy to him. If anyone had told me,
+then, that all this was a brilliant game, played for the excitement of
+the moment, for the employment of high spirits, in the thoughtless love
+of superiority, in a mere wasteful careless course of winning what was
+worthless to him, and next minute thrown away--I say, if anyone had told
+me such a lie that night, I wonder in what manner of receiving it my
+indignation would have found a vent! Probably only in an increase, had
+that been possible, of the romantic feelings of fidelity and friendship
+with which I walked beside him, over the dark wintry sands towards the
+old boat; the wind sighing around us even more mournfully, than it had
+sighed and moaned upon the night when I first darkened Mr. Peggotty's
+door.
+
+'This is a wild kind of place, Steerforth, is it not?'
+
+'Dismal enough in the dark,' he said: 'and the sea roars as if it were
+hungry for us. Is that the boat, where I see a light yonder?' 'That's
+the boat,' said I.
+
+'And it's the same I saw this morning,' he returned. 'I came straight to
+it, by instinct, I suppose.'
+
+We said no more as we approached the light, but made softly for the
+door. I laid my hand upon the latch; and whispering Steerforth to keep
+close to me, went in.
+
+A murmur of voices had been audible on the outside, and, at the
+moment of our entrance, a clapping of hands: which latter noise, I
+was surprised to see, proceeded from the generally disconsolate Mrs.
+Gummidge. But Mrs. Gummidge was not the only person there who was
+unusually excited. Mr. Peggotty, his face lighted up with uncommon
+satisfaction, and laughing with all his might, held his rough arms
+wide open, as if for little Em'ly to run into them; Ham, with a mixed
+expression in his face of admiration, exultation, and a lumbering sort
+of bashfulness that sat upon him very well, held little Em'ly by
+the hand, as if he were presenting her to Mr. Peggotty; little Em'ly
+herself, blushing and shy, but delighted with Mr. Peggotty's delight, as
+her joyous eyes expressed, was stopped by our entrance (for she saw us
+first) in the very act of springing from Ham to nestle in Mr. Peggotty's
+embrace. In the first glimpse we had of them all, and at the moment of
+our passing from the dark cold night into the warm light room, this
+was the way in which they were all employed: Mrs. Gummidge in the
+background, clapping her hands like a madwoman.
+
+The little picture was so instantaneously dissolved by our going in,
+that one might have doubted whether it had ever been. I was in the midst
+of the astonished family, face to face with Mr. Peggotty, and holding
+out my hand to him, when Ham shouted:
+
+'Mas'r Davy! It's Mas'r Davy!'
+
+In a moment we were all shaking hands with one another, and asking one
+another how we did, and telling one another how glad we were to meet,
+and all talking at once. Mr. Peggotty was so proud and overjoyed to see
+us, that he did not know what to say or do, but kept over and over again
+shaking hands with me, and then with Steerforth, and then with me, and
+then ruffling his shaggy hair all over his head, and laughing with such
+glee and triumph, that it was a treat to see him.
+
+'Why, that you two gent'lmen--gent'lmen growed--should come to this here
+roof tonight, of all nights in my life,' said Mr. Peggotty, 'is such a
+thing as never happened afore, I do rightly believe! Em'ly, my darling,
+come here! Come here, my little witch! There's Mas'r Davy's friend, my
+dear! There's the gent'lman as you've heerd on, Em'ly. He comes to see
+you, along with Mas'r Davy, on the brightest night of your uncle's life
+as ever was or will be, Gorm the t'other one, and horroar for it!'
+
+After delivering this speech all in a breath, and with extraordinary
+animation and pleasure, Mr. Peggotty put one of his large hands
+rapturously on each side of his niece's face, and kissing it a dozen
+times, laid it with a gentle pride and love upon his broad chest, and
+patted it as if his hand had been a lady's. Then he let her go; and as
+she ran into the little chamber where I used to sleep, looked round upon
+us, quite hot and out of breath with his uncommon satisfaction.
+
+'If you two gent'lmen--gent'lmen growed now, and such gent'lmen--' said
+Mr. Peggotty.
+
+'So th' are, so th' are!' cried Ham. 'Well said! So th' are. Mas'r Davy
+bor'--gent'lmen growed--so th' are!'
+
+'If you two gent'lmen, gent'lmen growed,' said Mr. Peggotty, 'don't
+ex-cuse me for being in a state of mind, when you understand matters,
+I'll arks your pardon. Em'ly, my dear!--She knows I'm a going to tell,'
+here his delight broke out again, 'and has made off. Would you be so
+good as look arter her, Mawther, for a minute?'
+
+Mrs. Gummidge nodded and disappeared.
+
+'If this ain't,' said Mr. Peggotty, sitting down among us by the fire,
+'the brightest night o' my life, I'm a shellfish--biled too--and more I
+can't say. This here little Em'ly, sir,' in a low voice to Steerforth,
+'--her as you see a blushing here just now--'
+
+Steerforth only nodded; but with such a pleased expression of interest,
+and of participation in Mr. Peggotty's feelings, that the latter
+answered him as if he had spoken.
+
+'To be sure,' said Mr. Peggotty. 'That's her, and so she is. Thankee,
+sir.'
+
+Ham nodded to me several times, as if he would have said so too.
+
+'This here little Em'ly of ours,' said Mr. Peggotty, 'has been, in our
+house, what I suppose (I'm a ignorant man, but that's my belief) no one
+but a little bright-eyed creetur can be in a house. She ain't my
+child; I never had one; but I couldn't love her more. You understand! I
+couldn't do it!'
+
+'I quite understand,' said Steerforth.
+
+'I know you do, sir,' returned Mr. Peggotty, 'and thankee again. Mas'r
+Davy, he can remember what she was; you may judge for your own self what
+she is; but neither of you can't fully know what she has been, is, and
+will be, to my loving art. I am rough, sir,' said Mr. Peggotty, 'I am as
+rough as a Sea Porkypine; but no one, unless, mayhap, it is a woman, can
+know, I think, what our little Em'ly is to me. And betwixt ourselves,'
+sinking his voice lower yet, 'that woman's name ain't Missis Gummidge
+neither, though she has a world of merits.' Mr. Peggotty ruffled his
+hair again, with both hands, as a further preparation for what he was
+going to say, and went on, with a hand upon each of his knees:
+
+'There was a certain person as had know'd our Em'ly, from the time when
+her father was drownded; as had seen her constant; when a babby, when
+a young gal, when a woman. Not much of a person to look at, he warn't,'
+said Mr. Peggotty, 'something o' my own build--rough--a good deal o'
+the sou'-wester in him--wery salt--but, on the whole, a honest sort of a
+chap, with his art in the right place.'
+
+I thought I had never seen Ham grin to anything like the extent to which
+he sat grinning at us now.
+
+'What does this here blessed tarpaulin go and do,' said Mr. Peggotty,
+with his face one high noon of enjoyment, 'but he loses that there art
+of his to our little Em'ly. He follers her about, he makes hisself a
+sort o' servant to her, he loses in a great measure his relish for his
+wittles, and in the long-run he makes it clear to me wot's amiss. Now I
+could wish myself, you see, that our little Em'ly was in a fair way of
+being married. I could wish to see her, at all ewents, under articles to
+a honest man as had a right to defend her. I don't know how long I may
+live, or how soon I may die; but I know that if I was capsized, any
+night, in a gale of wind in Yarmouth Roads here, and was to see the
+town-lights shining for the last time over the rollers as I couldn't
+make no head against, I could go down quieter for thinking "There's a
+man ashore there, iron-true to my little Em'ly, God bless her, and no
+wrong can touch my Em'ly while so be as that man lives."'
+
+Mr. Peggotty, in simple earnestness, waved his right arm, as if he were
+waving it at the town-lights for the last time, and then, exchanging a
+nod with Ham, whose eye he caught, proceeded as before.
+
+'Well! I counsels him to speak to Em'ly. He's big enough, but he's
+bashfuller than a little un, and he don't like. So I speak. "What! Him!"
+says Em'ly. "Him that I've know'd so intimate so many years, and like so
+much. Oh, Uncle! I never can have him. He's such a good fellow!" I gives
+her a kiss, and I says no more to her than, "My dear, you're right to
+speak out, you're to choose for yourself, you're as free as a little
+bird." Then I aways to him, and I says, "I wish it could have been so,
+but it can't. But you can both be as you was, and wot I say to you is,
+Be as you was with her, like a man." He says to me, a-shaking of my
+hand, "I will!" he says. And he was--honourable and manful--for two year
+going on, and we was just the same at home here as afore.'
+
+Mr. Peggotty's face, which had varied in its expression with the various
+stages of his narrative, now resumed all its former triumphant delight,
+as he laid a hand upon my knee and a hand upon Steerforth's (previously
+wetting them both, for the greater emphasis of the action), and divided
+the following speech between us:
+
+'All of a sudden, one evening--as it might be tonight--comes little
+Em'ly from her work, and him with her! There ain't so much in that,
+you'll say. No, because he takes care on her, like a brother, arter
+dark, and indeed afore dark, and at all times. But this tarpaulin chap,
+he takes hold of her hand, and he cries out to me, joyful, "Look here!
+This is to be my little wife!" And she says, half bold and half shy, and
+half a laughing and half a crying, "Yes, Uncle! If you please."--If I
+please!' cried Mr. Peggotty, rolling his head in an ecstasy at the idea;
+'Lord, as if I should do anythink else!--"If you please, I am steadier
+now, and I have thought better of it, and I'll be as good a little wife
+as I can to him, for he's a dear, good fellow!" Then Missis Gummidge,
+she claps her hands like a play, and you come in. Theer! the murder's
+out!' said Mr. Peggotty--'You come in! It took place this here present
+hour; and here's the man that'll marry her, the minute she's out of her
+time.'
+
+Ham staggered, as well he might, under the blow Mr. Peggotty dealt
+him in his unbounded joy, as a mark of confidence and friendship; but
+feeling called upon to say something to us, he said, with much faltering
+and great difficulty:
+
+'She warn't no higher than you was, Mas'r Davy--when you first
+come--when I thought what she'd grow up to be. I see her grown
+up--gent'lmen--like a flower. I'd lay down my life for
+her--Mas'r Davy--Oh! most content and cheerful! She's more to
+me--gent'lmen--than--she's all to me that ever I can want, and more
+than ever I--than ever I could say. I--I love her true. There ain't a
+gent'lman in all the land--nor yet sailing upon all the sea--that
+can love his lady more than I love her, though there's many a common
+man--would say better--what he meant.'
+
+I thought it affecting to see such a sturdy fellow as Ham was now,
+trembling in the strength of what he felt for the pretty little creature
+who had won his heart. I thought the simple confidence reposed in us by
+Mr. Peggotty and by himself, was, in itself, affecting. I was affected
+by the story altogether. How far my emotions were influenced by the
+recollections of my childhood, I don't know. Whether I had come there
+with any lingering fancy that I was still to love little Em'ly, I don't
+know. I know that I was filled with pleasure by all this; but, at first,
+with an indescribably sensitive pleasure, that a very little would have
+changed to pain.
+
+Therefore, if it had depended upon me to touch the prevailing chord
+among them with any skill, I should have made a poor hand of it. But it
+depended upon Steerforth; and he did it with such address, that in a few
+minutes we were all as easy and as happy as it was possible to be.
+
+'Mr. Peggotty,' he said, 'you are a thoroughly good fellow, and deserve
+to be as happy as you are tonight. My hand upon it! Ham, I give you
+joy, my boy. My hand upon that, too! Daisy, stir the fire, and make it a
+brisk one! and Mr. Peggotty, unless you can induce your gentle niece to
+come back (for whom I vacate this seat in the corner), I shall go.
+Any gap at your fireside on such a night--such a gap least of all--I
+wouldn't make, for the wealth of the Indies!'
+
+So Mr. Peggotty went into my old room to fetch little Em'ly. At first
+little Em'ly didn't like to come, and then Ham went. Presently they
+brought her to the fireside, very much confused, and very shy,--but
+she soon became more assured when she found how gently and respectfully
+Steerforth spoke to her; how skilfully he avoided anything that would
+embarrass her; how he talked to Mr. Peggotty of boats, and ships, and
+tides, and fish; how he referred to me about the time when he had seen
+Mr. Peggotty at Salem House; how delighted he was with the boat and all
+belonging to it; how lightly and easily he carried on, until he brought
+us, by degrees, into a charmed circle, and we were all talking away
+without any reserve.
+
+Em'ly, indeed, said little all the evening; but she looked, and
+listened, and her face got animated, and she was charming. Steerforth
+told a story of a dismal shipwreck (which arose out of his talk with Mr.
+Peggotty), as if he saw it all before him--and little Em'ly's eyes were
+fastened on him all the time, as if she saw it too. He told us a merry
+adventure of his own, as a relief to that, with as much gaiety as if the
+narrative were as fresh to him as it was to us--and little Em'ly
+laughed until the boat rang with the musical sounds, and we all laughed
+(Steerforth too), in irresistible sympathy with what was so pleasant and
+light-hearted. He got Mr. Peggotty to sing, or rather to roar, 'When
+the stormy winds do blow, do blow, do blow'; and he sang a sailor's
+song himself, so pathetically and beautifully, that I could have almost
+fancied that the real wind creeping sorrowfully round the house, and
+murmuring low through our unbroken silence, was there to listen.
+
+As to Mrs. Gummidge, he roused that victim of despondency with a success
+never attained by anyone else (so Mr. Peggotty informed me), since
+the decease of the old one. He left her so little leisure for being
+miserable, that she said next day she thought she must have been
+bewitched.
+
+But he set up no monopoly of the general attention, or the conversation.
+When little Em'ly grew more courageous, and talked (but still bashfully)
+across the fire to me, of our old wanderings upon the beach, to pick up
+shells and pebbles; and when I asked her if she recollected how I used
+to be devoted to her; and when we both laughed and reddened, casting
+these looks back on the pleasant old times, so unreal to look at now; he
+was silent and attentive, and observed us thoughtfully. She sat, at this
+time, and all the evening, on the old locker in her old little corner
+by the fire--Ham beside her, where I used to sit. I could not satisfy
+myself whether it was in her own little tormenting way, or in a maidenly
+reserve before us, that she kept quite close to the wall, and away from
+him; but I observed that she did so, all the evening.
+
+As I remember, it was almost midnight when we took our leave. We had had
+some biscuit and dried fish for supper, and Steerforth had produced from
+his pocket a full flask of Hollands, which we men (I may say we men,
+now, without a blush) had emptied. We parted merrily; and as they all
+stood crowded round the door to light us as far as they could upon our
+road, I saw the sweet blue eyes of little Em'ly peeping after us, from
+behind Ham, and heard her soft voice calling to us to be careful how we
+went.
+
+'A most engaging little Beauty!' said Steerforth, taking my arm. 'Well!
+It's a quaint place, and they are quaint company, and it's quite a new
+sensation to mix with them.'
+
+'How fortunate we are, too,' I returned, 'to have arrived to witness
+their happiness in that intended marriage! I never saw people so happy.
+How delightful to see it, and to be made the sharers in their honest
+joy, as we have been!'
+
+'That's rather a chuckle-headed fellow for the girl; isn't he?' said
+Steerforth.
+
+He had been so hearty with him, and with them all, that I felt a shock
+in this unexpected and cold reply. But turning quickly upon him, and
+seeing a laugh in his eyes, I answered, much relieved:
+
+'Ah, Steerforth! It's well for you to joke about the poor! You may
+skirmish with Miss Dartle, or try to hide your sympathies in jest from
+me, but I know better. When I see how perfectly you understand them, how
+exquisitely you can enter into happiness like this plain fisherman's,
+or humour a love like my old nurse's, I know that there is not a joy or
+sorrow, not an emotion, of such people, that can be indifferent to you.
+And I admire and love you for it, Steerforth, twenty times the more!'
+
+He stopped, and, looking in my face, said, 'Daisy, I believe you are
+in earnest, and are good. I wish we all were!' Next moment he was
+gaily singing Mr. Peggotty's song, as we walked at a round pace back to
+Yarmouth.
+
+
+
+CHAPTER 22. SOME OLD SCENES, AND SOME NEW PEOPLE
+
+
+Steerforth and I stayed for more than a fortnight in that part of the
+country. We were very much together, I need not say; but occasionally we
+were asunder for some hours at a time. He was a good sailor, and I was
+but an indifferent one; and when he went out boating with Mr. Peggotty,
+which was a favourite amusement of his, I generally remained ashore. My
+occupation of Peggotty's spare-room put a constraint upon me, from which
+he was free: for, knowing how assiduously she attended on Mr. Barkis
+all day, I did not like to remain out late at night; whereas Steerforth,
+lying at the Inn, had nothing to consult but his own humour. Thus it
+came about, that I heard of his making little treats for the fishermen
+at Mr. Peggotty's house of call, 'The Willing Mind', after I was in bed,
+and of his being afloat, wrapped in fishermen's clothes, whole moonlight
+nights, and coming back when the morning tide was at flood. By this
+time, however, I knew that his restless nature and bold spirits
+delighted to find a vent in rough toil and hard weather, as in any other
+means of excitement that presented itself freshly to him; so none of his
+proceedings surprised me.
+
+Another cause of our being sometimes apart, was, that I had naturally an
+interest in going over to Blunderstone, and revisiting the old familiar
+scenes of my childhood; while Steerforth, after being there once, had
+naturally no great interest in going there again. Hence, on three or
+four days that I can at once recall, we went our several ways after an
+early breakfast, and met again at a late dinner. I had no idea how he
+employed his time in the interval, beyond a general knowledge that
+he was very popular in the place, and had twenty means of actively
+diverting himself where another man might not have found one.
+
+For my own part, my occupation in my solitary pilgrimages was to recall
+every yard of the old road as I went along it, and to haunt the old
+spots, of which I never tired. I haunted them, as my memory had often
+done, and lingered among them as my younger thoughts had lingered when I
+was far away. The grave beneath the tree, where both my parents lay--on
+which I had looked out, when it was my father's only, with such curious
+feelings of compassion, and by which I had stood, so desolate, when it
+was opened to receive my pretty mother and her baby--the grave which
+Peggotty's own faithful care had ever since kept neat, and made a garden
+of, I walked near, by the hour. It lay a little off the churchyard path,
+in a quiet corner, not so far removed but I could read the names
+upon the stone as I walked to and fro, startled by the sound of the
+church-bell when it struck the hour, for it was like a departed voice to
+me. My reflections at these times were always associated with the figure
+I was to make in life, and the distinguished things I was to do. My
+echoing footsteps went to no other tune, but were as constant to that as
+if I had come home to build my castles in the air at a living mother's
+side.
+
+There were great changes in my old home. The ragged nests, so long
+deserted by the rooks, were gone; and the trees were lopped and topped
+out of their remembered shapes. The garden had run wild, and half the
+windows of the house were shut up. It was occupied, but only by a poor
+lunatic gentleman, and the people who took care of him. He was always
+sitting at my little window, looking out into the churchyard; and I
+wondered whether his rambling thoughts ever went upon any of the fancies
+that used to occupy mine, on the rosy mornings when I peeped out of
+that same little window in my night-clothes, and saw the sheep quietly
+feeding in the light of the rising sun.
+
+Our old neighbours, Mr. and Mrs. Grayper, were gone to South America,
+and the rain had made its way through the roof of their empty house,
+and stained the outer walls. Mr. Chillip was married again to a tall,
+raw-boned, high-nosed wife; and they had a weazen little baby, with a
+heavy head that it couldn't hold up, and two weak staring eyes, with
+which it seemed to be always wondering why it had ever been born.
+
+It was with a singular jumble of sadness and pleasure that I used to
+linger about my native place, until the reddening winter sun admonished
+me that it was time to start on my returning walk. But, when the place
+was left behind, and especially when Steerforth and I were happily
+seated over our dinner by a blazing fire, it was delicious to think of
+having been there. So it was, though in a softened degree, when I
+went to my neat room at night; and, turning over the leaves of the
+crocodile-book (which was always there, upon a little table), remembered
+with a grateful heart how blest I was in having such a friend as
+Steerforth, such a friend as Peggotty, and such a substitute for what I
+had lost as my excellent and generous aunt.
+
+MY nearest way to Yarmouth, in coming back from these long walks, was by
+a ferry. It landed me on the flat between the town and the sea, which I
+could make straight across, and so save myself a considerable circuit by
+the high road. Mr. Peggotty's house being on that waste-place, and not
+a hundred yards out of my track, I always looked in as I went by.
+Steerforth was pretty sure to be there expecting me, and we went on
+together through the frosty air and gathering fog towards the twinkling
+lights of the town.
+
+One dark evening, when I was later than usual--for I had, that day, been
+making my parting visit to Blunderstone, as we were now about to return
+home--I found him alone in Mr. Peggotty's house, sitting thoughtfully
+before the fire. He was so intent upon his own reflections that he was
+quite unconscious of my approach. This, indeed, he might easily have
+been if he had been less absorbed, for footsteps fell noiselessly on the
+sandy ground outside; but even my entrance failed to rouse him. I was
+standing close to him, looking at him; and still, with a heavy brow, he
+was lost in his meditations.
+
+He gave such a start when I put my hand upon his shoulder, that he made
+me start too.
+
+'You come upon me,' he said, almost angrily, 'like a reproachful ghost!'
+
+'I was obliged to announce myself, somehow,' I replied. 'Have I called
+you down from the stars?'
+
+'No,' he answered. 'No.'
+
+'Up from anywhere, then?' said I, taking my seat near him.
+
+'I was looking at the pictures in the fire,' he returned.
+
+'But you are spoiling them for me,' said I, as he stirred it quickly
+with a piece of burning wood, striking out of it a train of red-hot
+sparks that went careering up the little chimney, and roaring out into
+the air.
+
+'You would not have seen them,' he returned. 'I detest this mongrel
+time, neither day nor night. How late you are! Where have you been?'
+
+'I have been taking leave of my usual walk,' said I.
+
+'And I have been sitting here,' said Steerforth, glancing round the
+room, 'thinking that all the people we found so glad on the night of
+our coming down, might--to judge from the present wasted air of the
+place--be dispersed, or dead, or come to I don't know what harm. David,
+I wish to God I had had a judicious father these last twenty years!'
+
+'My dear Steerforth, what is the matter?'
+
+'I wish with all my soul I had been better guided!' he exclaimed. 'I
+wish with all my soul I could guide myself better!'
+
+There was a passionate dejection in his manner that quite amazed me. He
+was more unlike himself than I could have supposed possible.
+
+'It would be better to be this poor Peggotty, or his lout of a nephew,'
+he said, getting up and leaning moodily against the chimney-piece, with
+his face towards the fire, 'than to be myself, twenty times richer and
+twenty times wiser, and be the torment to myself that I have been, in
+this Devil's bark of a boat, within the last half-hour!'
+
+I was so confounded by the alteration in him, that at first I could only
+observe him in silence, as he stood leaning his head upon his hand, and
+looking gloomily down at the fire. At length I begged him, with all
+the earnestness I felt, to tell me what had occurred to cross him so
+unusually, and to let me sympathize with him, if I could not hope to
+advise him. Before I had well concluded, he began to laugh--fretfully at
+first, but soon with returning gaiety.
+
+'Tut, it's nothing, Daisy! nothing!' he replied. 'I told you at the
+inn in London, I am heavy company for myself, sometimes. I have been a
+nightmare to myself, just now--must have had one, I think. At odd dull
+times, nursery tales come up into the memory, unrecognized for what
+they are. I believe I have been confounding myself with the bad boy who
+"didn't care", and became food for lions--a grander kind of going to
+the dogs, I suppose. What old women call the horrors, have been creeping
+over me from head to foot. I have been afraid of myself.'
+
+'You are afraid of nothing else, I think,' said I.
+
+'Perhaps not, and yet may have enough to be afraid of too,' he answered.
+'Well! So it goes by! I am not about to be hipped again, David; but I
+tell you, my good fellow, once more, that it would have been well for me
+(and for more than me) if I had had a steadfast and judicious father!'
+
+His face was always full of expression, but I never saw it express such
+a dark kind of earnestness as when he said these words, with his glance
+bent on the fire.
+
+'So much for that!' he said, making as if he tossed something light
+into the air, with his hand. "'Why, being gone, I am a man again," like
+Macbeth. And now for dinner! If I have not (Macbeth-like) broken up the
+feast with most admired disorder, Daisy.'
+
+'But where are they all, I wonder!' said I.
+
+'God knows,' said Steerforth. 'After strolling to the ferry looking
+for you, I strolled in here and found the place deserted. That set me
+thinking, and you found me thinking.'
+
+The advent of Mrs. Gummidge with a basket, explained how the house had
+happened to be empty. She had hurried out to buy something that was
+needed, against Mr. Peggotty's return with the tide; and had left the
+door open in the meanwhile, lest Ham and little Em'ly, with whom it was
+an early night, should come home while she was gone. Steerforth, after
+very much improving Mrs. Gummidge's spirits by a cheerful salutation and
+a jocose embrace, took my arm, and hurried me away.
+
+He had improved his own spirits, no less than Mrs. Gummidge's, for
+they were again at their usual flow, and he was full of vivacious
+conversation as we went along.
+
+'And so,' he said, gaily, 'we abandon this buccaneer life tomorrow, do
+we?'
+
+'So we agreed,' I returned. 'And our places by the coach are taken, you
+know.'
+
+'Ay! there's no help for it, I suppose,' said Steerforth. 'I have
+almost forgotten that there is anything to do in the world but to go out
+tossing on the sea here. I wish there was not.'
+
+'As long as the novelty should last,' said I, laughing.
+
+'Like enough,' he returned; 'though there's a sarcastic meaning in that
+observation for an amiable piece of innocence like my young friend.
+Well! I dare say I am a capricious fellow, David. I know I am; but
+while the iron is hot, I can strike it vigorously too. I could pass
+a reasonably good examination already, as a pilot in these waters, I
+think.'
+
+'Mr. Peggotty says you are a wonder,' I returned.
+
+'A nautical phenomenon, eh?' laughed Steerforth.
+
+'Indeed he does, and you know how truly; I know how ardent you are
+in any pursuit you follow, and how easily you can master it. And that
+amazes me most in you, Steerforth--that you should be contented with
+such fitful uses of your powers.'
+
+'Contented?' he answered, merrily. 'I am never contented, except with
+your freshness, my gentle Daisy. As to fitfulness, I have never learnt
+the art of binding myself to any of the wheels on which the Ixions of
+these days are turning round and round. I missed it somehow in a bad
+apprenticeship, and now don't care about it.---You know I have bought a
+boat down here?'
+
+'What an extraordinary fellow you are, Steerforth!' I exclaimed,
+stopping--for this was the first I had heard of it. 'When you may never
+care to come near the place again!'
+
+'I don't know that,' he returned. 'I have taken a fancy to the place. At
+all events,' walking me briskly on, 'I have bought a boat that was for
+sale--a clipper, Mr. Peggotty says; and so she is--and Mr. Peggotty will
+be master of her in my absence.'
+
+'Now I understand you, Steerforth!' said I, exultingly. 'You pretend
+to have bought it for yourself, but you have really done so to confer
+a benefit on him. I might have known as much at first, knowing you.
+My dear kind Steerforth, how can I tell you what I think of your
+generosity?'
+
+'Tush!' he answered, turning red. 'The less said, the better.'
+
+'Didn't I know?' cried I, 'didn't I say that there was not a joy, or
+sorrow, or any emotion of such honest hearts that was indifferent to
+you?'
+
+'Aye, aye,' he answered, 'you told me all that. There let it rest. We
+have said enough!'
+
+Afraid of offending him by pursuing the subject when he made so light
+of it, I only pursued it in my thoughts as we went on at even a quicker
+pace than before.
+
+'She must be newly rigged,' said Steerforth, 'and I shall leave Littimer
+behind to see it done, that I may know she is quite complete. Did I tell
+you Littimer had come down?'
+
+'No.'
+
+'Oh yes! came down this morning, with a letter from my mother.'
+
+As our looks met, I observed that he was pale even to his lips, though
+he looked very steadily at me. I feared that some difference between him
+and his mother might have led to his being in the frame of mind in which
+I had found him at the solitary fireside. I hinted so.
+
+'Oh no!' he said, shaking his head, and giving a slight laugh. 'Nothing
+of the sort! Yes. He is come down, that man of mine.'
+
+'The same as ever?' said I.
+
+'The same as ever,' said Steerforth. 'Distant and quiet as the North
+Pole. He shall see to the boat being fresh named. She's the "Stormy
+Petrel" now. What does Mr. Peggotty care for Stormy Petrels! I'll have
+her christened again.'
+
+'By what name?' I asked.
+
+'The "Little Em'ly".'
+
+As he had continued to look steadily at me, I took it as a reminder that
+he objected to being extolled for his consideration. I could not help
+showing in my face how much it pleased me, but I said little, and he
+resumed his usual smile, and seemed relieved.
+
+'But see here,' he said, looking before us, 'where the original little
+Em'ly comes! And that fellow with her, eh? Upon my soul, he's a true
+knight. He never leaves her!'
+
+Ham was a boat-builder in these days, having improved a natural
+ingenuity in that handicraft, until he had become a skilled workman. He
+was in his working-dress, and looked rugged enough, but manly withal,
+and a very fit protector for the blooming little creature at his
+side. Indeed, there was a frankness in his face, an honesty, and an
+undisguised show of his pride in her, and his love for her, which were,
+to me, the best of good looks. I thought, as they came towards us, that
+they were well matched even in that particular.
+
+She withdrew her hand timidly from his arm as we stopped to speak to
+them, and blushed as she gave it to Steerforth and to me. When they
+passed on, after we had exchanged a few words, she did not like to
+replace that hand, but, still appearing timid and constrained, walked
+by herself. I thought all this very pretty and engaging, and Steerforth
+seemed to think so too, as we looked after them fading away in the light
+of a young moon.
+
+Suddenly there passed us--evidently following them--a young woman whose
+approach we had not observed, but whose face I saw as she went by, and
+thought I had a faint remembrance of. She was lightly dressed; looked
+bold, and haggard, and flaunting, and poor; but seemed, for the time, to
+have given all that to the wind which was blowing, and to have nothing
+in her mind but going after them. As the dark distant level, absorbing
+their figures into itself, left but itself visible between us and the
+sea and clouds, her figure disappeared in like manner, still no nearer
+to them than before.
+
+'That is a black shadow to be following the girl,' said Steerforth,
+standing still; 'what does it mean?'
+
+He spoke in a low voice that sounded almost strange to Me.
+
+'She must have it in her mind to beg of them, I think,' said I.
+
+'A beggar would be no novelty,' said Steerforth; 'but it is a strange
+thing that the beggar should take that shape tonight.'
+
+'Why?' I asked.
+
+'For no better reason, truly, than because I was thinking,' he said,
+after a pause, 'of something like it, when it came by. Where the Devil
+did it come from, I wonder!'
+
+'From the shadow of this wall, I think,' said I, as we emerged upon a
+road on which a wall abutted.
+
+'It's gone!' he returned, looking over his shoulder. 'And all ill go
+with it. Now for our dinner!'
+
+But he looked again over his shoulder towards the sea-line glimmering
+afar off, and yet again. And he wondered about it, in some broken
+expressions, several times, in the short remainder of our walk; and only
+seemed to forget it when the light of fire and candle shone upon us,
+seated warm and merry, at table.
+
+Littimer was there, and had his usual effect upon me. When I said to
+him that I hoped Mrs. Steerforth and Miss Dartle were well, he answered
+respectfully (and of course respectably), that they were tolerably well,
+he thanked me, and had sent their compliments. This was all, and yet he
+seemed to me to say as plainly as a man could say: 'You are very young,
+sir; you are exceedingly young.'
+
+We had almost finished dinner, when taking a step or two towards the
+table, from the corner where he kept watch upon us, or rather upon me,
+as I felt, he said to his master:
+
+'I beg your pardon, sir. Miss Mowcher is down here.'
+
+'Who?' cried Steerforth, much astonished.
+
+'Miss Mowcher, sir.'
+
+'Why, what on earth does she do here?' said Steerforth.
+
+'It appears to be her native part of the country, sir. She informs me
+that she makes one of her professional visits here, every year, sir.
+I met her in the street this afternoon, and she wished to know if she
+might have the honour of waiting on you after dinner, sir.'
+
+'Do you know the Giantess in question, Daisy?' inquired Steerforth.
+
+I was obliged to confess--I felt ashamed, even of being at this
+disadvantage before Littimer--that Miss Mowcher and I were wholly
+unacquainted.
+
+'Then you shall know her,' said Steerforth, 'for she is one of the seven
+wonders of the world. When Miss Mowcher comes, show her in.'
+
+I felt some curiosity and excitement about this lady, especially as
+Steerforth burst into a fit of laughing when I referred to her, and
+positively refused to answer any question of which I made her the
+subject. I remained, therefore, in a state of considerable expectation
+until the cloth had been removed some half an hour, and we were sitting
+over our decanter of wine before the fire, when the door opened, and
+Littimer, with his habitual serenity quite undisturbed, announced:
+
+'Miss Mowcher!'
+
+I looked at the doorway and saw nothing. I was still looking at
+the doorway, thinking that Miss Mowcher was a long while making her
+appearance, when, to my infinite astonishment, there came waddling round
+a sofa which stood between me and it, a pursy dwarf, of about forty
+or forty-five, with a very large head and face, a pair of roguish grey
+eyes, and such extremely little arms, that, to enable herself to lay a
+finger archly against her snub nose, as she ogled Steerforth, she was
+obliged to meet the finger half-way, and lay her nose against it.
+Her chin, which was what is called a double chin, was so fat that it
+entirely swallowed up the strings of her bonnet, bow and all. Throat she
+had none; waist she had none; legs she had none, worth mentioning; for
+though she was more than full-sized down to where her waist would have
+been, if she had had any, and though she terminated, as human beings
+generally do, in a pair of feet, she was so short that she stood at a
+common-sized chair as at a table, resting a bag she carried on the seat.
+This lady--dressed in an off-hand, easy style; bringing her nose and her
+forefinger together, with the difficulty I have described; standing with
+her head necessarily on one side, and, with one of her sharp eyes shut
+up, making an uncommonly knowing face--after ogling Steerforth for a few
+moments, broke into a torrent of words.
+
+'What! My flower!' she pleasantly began, shaking her large head at him.
+'You're there, are you! Oh, you naughty boy, fie for shame, what do you
+do so far away from home? Up to mischief, I'll be bound. Oh, you're a
+downy fellow, Steerforth, so you are, and I'm another, ain't I? Ha, ha,
+ha! You'd have betted a hundred pound to five, now, that you wouldn't
+have seen me here, wouldn't you? Bless you, man alive, I'm everywhere.
+I'm here and there, and where not, like the conjurer's half-crown in the
+lady's handkercher. Talking of handkerchers--and talking of ladies--what
+a comfort you are to your blessed mother, ain't you, my dear boy, over
+one of my shoulders, and I don't say which!'
+
+Miss Mowcher untied her bonnet, at this passage of her discourse, threw
+back the strings, and sat down, panting, on a footstool in front of
+the fire--making a kind of arbour of the dining table, which spread its
+mahogany shelter above her head.
+
+'Oh my stars and what's-their-names!' she went on, clapping a hand on
+each of her little knees, and glancing shrewdly at me, 'I'm of too full
+a habit, that's the fact, Steerforth. After a flight of stairs, it gives
+me as much trouble to draw every breath I want, as if it was a bucket of
+water. If you saw me looking out of an upper window, you'd think I was a
+fine woman, wouldn't you?'
+
+'I should think that, wherever I saw you,' replied Steerforth.
+
+'Go along, you dog, do!' cried the little creature, making a whisk at
+him with the handkerchief with which she was wiping her face, 'and don't
+be impudent! But I give you my word and honour I was at Lady Mithers's
+last week--THERE'S a woman! How SHE wears!--and Mithers himself came
+into the room where I was waiting for her--THERE'S a man! How HE wears!
+and his wig too, for he's had it these ten years--and he went on at
+that rate in the complimentary line, that I began to think I should be
+obliged to ring the bell. Ha! ha! ha! He's a pleasant wretch, but he
+wants principle.'
+
+'What were you doing for Lady Mithers?' asked Steerforth.
+
+'That's tellings, my blessed infant,' she retorted, tapping her nose
+again, screwing up her face, and twinkling her eyes like an imp of
+supernatural intelligence. 'Never YOU mind! You'd like to know whether
+I stop her hair from falling off, or dye it, or touch up her
+complexion, or improve her eyebrows, wouldn't you? And so you shall, my
+darling--when I tell you! Do you know what my great grandfather's name
+was?'
+
+'No,' said Steerforth.
+
+'It was Walker, my sweet pet,' replied Miss Mowcher, 'and he came of a
+long line of Walkers, that I inherit all the Hookey estates from.'
+
+I never beheld anything approaching to Miss Mowcher's wink except Miss
+Mowcher's self-possession. She had a wonderful way too, when listening
+to what was said to her, or when waiting for an answer to what she had
+said herself, of pausing with her head cunningly on one side, and one
+eye turned up like a magpie's. Altogether I was lost in amazement,
+and sat staring at her, quite oblivious, I am afraid, of the laws of
+politeness.
+
+She had by this time drawn the chair to her side, and was busily engaged
+in producing from the bag (plunging in her short arm to the shoulder, at
+every dive) a number of small bottles, sponges, combs, brushes, bits of
+flannel, little pairs of curling-irons, and other instruments, which
+she tumbled in a heap upon the chair. From this employment she suddenly
+desisted, and said to Steerforth, much to my confusion:
+
+'Who's your friend?'
+
+'Mr. Copperfield,' said Steerforth; 'he wants to know you.'
+
+'Well, then, he shall! I thought he looked as if he did!' returned Miss
+Mowcher, waddling up to me, bag in hand, and laughing on me as she came.
+'Face like a peach!' standing on tiptoe to pinch my cheek as I
+sat. 'Quite tempting! I'm very fond of peaches. Happy to make your
+acquaintance, Mr. Copperfield, I'm sure.'
+
+I said that I congratulated myself on having the honour to make hers,
+and that the happiness was mutual.
+
+'Oh, my goodness, how polite we are!' exclaimed Miss Mowcher, making a
+preposterous attempt to cover her large face with her morsel of a hand.
+'What a world of gammon and spinnage it is, though, ain't it!'
+
+This was addressed confidentially to both of us, as the morsel of a
+hand came away from the face, and buried itself, arm and all, in the bag
+again.
+
+'What do you mean, Miss Mowcher?' said Steerforth.
+
+'Ha! ha! ha! What a refreshing set of humbugs we are, to be sure, ain't
+we, my sweet child?' replied that morsel of a woman, feeling in the bag
+with her head on one side and her eye in the air. 'Look here!' taking
+something out. 'Scraps of the Russian Prince's nails. Prince Alphabet
+turned topsy-turvy, I call him, for his name's got all the letters in
+it, higgledy-piggledy.'
+
+'The Russian Prince is a client of yours, is he?' said Steerforth.
+
+'I believe you, my pet,' replied Miss Mowcher. 'I keep his nails in
+order for him. Twice a week! Fingers and toes.'
+
+'He pays well, I hope?' said Steerforth.
+
+'Pays, as he speaks, my dear child--through the nose,' replied Miss
+Mowcher. 'None of your close shavers the Prince ain't. You'd say so, if
+you saw his moustachios. Red by nature, black by art.'
+
+'By your art, of course,' said Steerforth.
+
+Miss Mowcher winked assent. 'Forced to send for me. Couldn't help it.
+The climate affected his dye; it did very well in Russia, but it was no
+go here. You never saw such a rusty Prince in all your born days as he
+was. Like old iron!' 'Is that why you called him a humbug, just now?'
+inquired Steerforth.
+
+'Oh, you're a broth of a boy, ain't you?' returned Miss Mowcher, shaking
+her head violently. 'I said, what a set of humbugs we were in general,
+and I showed you the scraps of the Prince's nails to prove it. The
+Prince's nails do more for me in private families of the genteel sort,
+than all my talents put together. I always carry 'em about. They're the
+best introduction. If Miss Mowcher cuts the Prince's nails, she must be
+all right. I give 'em away to the young ladies. They put 'em in albums,
+I believe. Ha! ha! ha! Upon my life, "the whole social system" (as
+the men call it when they make speeches in Parliament) is a system of
+Prince's nails!' said this least of women, trying to fold her short
+arms, and nodding her large head.
+
+Steerforth laughed heartily, and I laughed too. Miss Mowcher continuing
+all the time to shake her head (which was very much on one side), and to
+look into the air with one eye, and to wink with the other.
+
+'Well, well!' she said, smiting her small knees, and rising, 'this is
+not business. Come, Steerforth, let's explore the polar regions, and
+have it over.'
+
+She then selected two or three of the little instruments, and a
+little bottle, and asked (to my surprise) if the table would bear. On
+Steerforth's replying in the affirmative, she pushed a chair against it,
+and begging the assistance of my hand, mounted up, pretty nimbly, to the
+top, as if it were a stage.
+
+'If either of you saw my ankles,' she said, when she was safely
+elevated, 'say so, and I'll go home and destroy myself!'
+
+'I did not,' said Steerforth.
+
+'I did not,' said I.
+
+'Well then,' cried Miss Mowcher,' I'll consent to live. Now, ducky,
+ducky, ducky, come to Mrs. Bond and be killed.'
+
+This was an invocation to Steerforth to place himself under her hands;
+who, accordingly, sat himself down, with his back to the table, and
+his laughing face towards me, and submitted his head to her inspection,
+evidently for no other purpose than our entertainment. To see Miss
+Mowcher standing over him, looking at his rich profusion of brown
+hair through a large round magnifying glass, which she took out of her
+pocket, was a most amazing spectacle.
+
+'You're a pretty fellow!' said Miss Mowcher, after a brief inspection.
+'You'd be as bald as a friar on the top of your head in twelve months,
+but for me. Just half a minute, my young friend, and we'll give you a
+polishing that shall keep your curls on for the next ten years!'
+
+With this, she tilted some of the contents of the little bottle on to
+one of the little bits of flannel, and, again imparting some of the
+virtues of that preparation to one of the little brushes, began rubbing
+and scraping away with both on the crown of Steerforth's head in the
+busiest manner I ever witnessed, talking all the time.
+
+'There's Charley Pyegrave, the duke's son,' she said. 'You know
+Charley?' peeping round into his face.
+
+'A little,' said Steerforth.
+
+'What a man HE is! THERE'S a whisker! As to Charley's legs, if they
+were only a pair (which they ain't), they'd defy competition. Would you
+believe he tried to do without me--in the Life-Guards, too?'
+
+'Mad!' said Steerforth.
+
+'It looks like it. However, mad or sane, he tried,' returned Miss
+Mowcher. 'What does he do, but, lo and behold you, he goes into a
+perfumer's shop, and wants to buy a bottle of the Madagascar Liquid.'
+
+'Charley does?' said Steerforth.
+
+'Charley does. But they haven't got any of the Madagascar Liquid.'
+
+'What is it? Something to drink?' asked Steerforth.
+
+'To drink?' returned Miss Mowcher, stopping to slap his cheek. 'To
+doctor his own moustachios with, you know. There was a woman in the
+shop--elderly female--quite a Griffin--who had never even heard of it
+by name. "Begging pardon, sir," said the Griffin to Charley, "it's
+not--not--not ROUGE, is it?" "Rouge," said Charley to the Griffin. "What
+the unmentionable to ears polite, do you think I want with rouge?" "No
+offence, sir," said the Griffin; "we have it asked for by so many names,
+I thought it might be." Now that, my child,' continued Miss Mowcher,
+rubbing all the time as busily as ever, 'is another instance of
+the refreshing humbug I was speaking of. I do something in that way
+myself--perhaps a good deal--perhaps a little--sharp's the word, my dear
+boy--never mind!'
+
+'In what way do you mean? In the rouge way?' said Steerforth.
+
+'Put this and that together, my tender pupil,' returned the wary
+Mowcher, touching her nose, 'work it by the rule of Secrets in all
+trades, and the product will give you the desired result. I say I do a
+little in that way myself. One Dowager, SHE calls it lip-salve. Another,
+SHE calls it gloves. Another, SHE calls it tucker-edging. Another, SHE
+calls it a fan. I call it whatever THEY call it. I supply it for 'em,
+but we keep up the trick so, to one another, and make believe with
+such a face, that they'd as soon think of laying it on, before a whole
+drawing-room, as before me. And when I wait upon 'em, they'll say to
+me sometimes--WITH IT ON--thick, and no mistake--"How am I looking,
+Mowcher? Am I pale?" Ha! ha! ha! ha! Isn't THAT refreshing, my young
+friend!'
+
+I never did in my days behold anything like Mowcher as she stood upon
+the dining table, intensely enjoying this refreshment, rubbing busily at
+Steerforth's head, and winking at me over it.
+
+'Ah!' she said. 'Such things are not much in demand hereabouts. That
+sets me off again! I haven't seen a pretty woman since I've been here,
+jemmy.'
+
+'No?' said Steerforth.
+
+'Not the ghost of one,' replied Miss Mowcher.
+
+'We could show her the substance of one, I think?' said Steerforth,
+addressing his eyes to mine. 'Eh, Daisy?'
+
+'Yes, indeed,' said I.
+
+'Aha?' cried the little creature, glancing sharply at my face, and then
+peeping round at Steerforth's. 'Umph?'
+
+The first exclamation sounded like a question put to both of us, and the
+second like a question put to Steerforth only. She seemed to have found
+no answer to either, but continued to rub, with her head on one side and
+her eye turned up, as if she were looking for an answer in the air and
+were confident of its appearing presently.
+
+'A sister of yours, Mr. Copperfield?' she cried, after a pause, and
+still keeping the same look-out. 'Aye, aye?'
+
+'No,' said Steerforth, before I could reply. 'Nothing of the sort. On
+the contrary, Mr. Copperfield used--or I am much mistaken--to have a
+great admiration for her.'
+
+'Why, hasn't he now?' returned Miss Mowcher. 'Is he fickle? Oh, for
+shame! Did he sip every flower, and change every hour, until Polly his
+passion requited?--Is her name Polly?'
+
+The Elfin suddenness with which she pounced upon me with this question,
+and a searching look, quite disconcerted me for a moment.
+
+'No, Miss Mowcher,' I replied. 'Her name is Emily.'
+
+'Aha?' she cried exactly as before. 'Umph? What a rattle I am! Mr.
+Copperfield, ain't I volatile?'
+
+Her tone and look implied something that was not agreeable to me in
+connexion with the subject. So I said, in a graver manner than any of us
+had yet assumed: 'She is as virtuous as she is pretty. She is engaged
+to be married to a most worthy and deserving man in her own station of
+life. I esteem her for her good sense, as much as I admire her for her
+good looks.'
+
+'Well said!' cried Steerforth. 'Hear, hear, hear! Now I'll quench the
+curiosity of this little Fatima, my dear Daisy, by leaving her nothing
+to guess at. She is at present apprenticed, Miss Mowcher, or articled,
+or whatever it may be, to Omer and Joram, Haberdashers, Milliners, and
+so forth, in this town. Do you observe? Omer and Joram. The promise of
+which my friend has spoken, is made and entered into with her cousin;
+Christian name, Ham; surname, Peggotty; occupation, boat-builder;
+also of this town. She lives with a relative; Christian name, unknown;
+surname, Peggotty; occupation, seafaring; also of this town. She is the
+prettiest and most engaging little fairy in the world. I admire her--as
+my friend does--exceedingly. If it were not that I might appear to
+disparage her Intended, which I know my friend would not like, I would
+add, that to me she seems to be throwing herself away; that I am sure
+she might do better; and that I swear she was born to be a lady.'
+
+Miss Mowcher listened to these words, which were very slowly and
+distinctly spoken, with her head on one side, and her eye in the air
+as if she were still looking for that answer. When he ceased she became
+brisk again in an instant, and rattled away with surprising volubility.
+
+'Oh! And that's all about it, is it?' she exclaimed, trimming his
+whiskers with a little restless pair of scissors, that went glancing
+round his head in all directions. 'Very well: very well! Quite a long
+story. Ought to end "and they lived happy ever afterwards"; oughtn't
+it? Ah! What's that game at forfeits? I love my love with an E, because
+she's enticing; I hate her with an E, because she's engaged. I took her
+to the sign of the exquisite, and treated her with an elopement, her
+name's Emily, and she lives in the east? Ha! ha! ha! Mr. Copperfield,
+ain't I volatile?'
+
+Merely looking at me with extravagant slyness, and not waiting for any
+reply, she continued, without drawing breath:
+
+'There! If ever any scapegrace was trimmed and touched up to perfection,
+you are, Steerforth. If I understand any noddle in the world, I
+understand yours. Do you hear me when I tell you that, my darling? I
+understand yours,' peeping down into his face. 'Now you may mizzle,
+jemmy (as we say at Court), and if Mr. Copperfield will take the chair
+I'll operate on him.'
+
+'What do you say, Daisy?' inquired Steerforth, laughing, and resigning
+his seat. 'Will you be improved?'
+
+'Thank you, Miss Mowcher, not this evening.'
+
+'Don't say no,' returned the little woman, looking at me with the aspect
+of a connoisseur; 'a little bit more eyebrow?'
+
+'Thank you,' I returned, 'some other time.'
+
+'Have it carried half a quarter of an inch towards the temple,' said
+Miss Mowcher. 'We can do it in a fortnight.'
+
+'No, I thank you. Not at present.'
+
+'Go in for a tip,' she urged. 'No? Let's get the scaffolding up, then,
+for a pair of whiskers. Come!'
+
+I could not help blushing as I declined, for I felt we were on my weak
+point, now. But Miss Mowcher, finding that I was not at present disposed
+for any decoration within the range of her art, and that I was, for the
+time being, proof against the blandishments of the small bottle which
+she held up before one eye to enforce her persuasions, said we would
+make a beginning on an early day, and requested the aid of my hand to
+descend from her elevated station. Thus assisted, she skipped down with
+much agility, and began to tie her double chin into her bonnet.
+
+'The fee,' said Steerforth, 'is--'
+
+'Five bob,' replied Miss Mowcher, 'and dirt cheap, my chicken. Ain't I
+volatile, Mr. Copperfield?'
+
+I replied politely: 'Not at all.' But I thought she was rather so, when
+she tossed up his two half-crowns like a goblin pieman, caught them,
+dropped them in her pocket, and gave it a loud slap.
+
+'That's the Till!' observed Miss Mowcher, standing at the chair again,
+and replacing in the bag a miscellaneous collection of little objects
+she had emptied out of it. 'Have I got all my traps? It seems so. It
+won't do to be like long Ned Beadwood, when they took him to church "to
+marry him to somebody", as he says, and left the bride behind. Ha! ha!
+ha! A wicked rascal, Ned, but droll! Now, I know I'm going to break
+your hearts, but I am forced to leave you. You must call up all your
+fortitude, and try to bear it. Good-bye, Mr. Copperfield! Take care of
+yourself, jockey of Norfolk! How I have been rattling on! It's all
+the fault of you two wretches. I forgive you! "Bob swore!"--as the
+Englishman said for "Good night", when he first learnt French, and
+thought it so like English. "Bob swore," my ducks!'
+
+With the bag slung over her arm, and rattling as she waddled away, she
+waddled to the door, where she stopped to inquire if she should leave
+us a lock of her hair. 'Ain't I volatile?' she added, as a commentary on
+this offer, and, with her finger on her nose, departed.
+
+Steerforth laughed to that degree, that it was impossible for me to help
+laughing too; though I am not sure I should have done so, but for this
+inducement. When we had had our laugh quite out, which was after some
+time, he told me that Miss Mowcher had quite an extensive connexion, and
+made herself useful to a variety of people in a variety of ways. Some
+people trifled with her as a mere oddity, he said; but she was as
+shrewdly and sharply observant as anyone he knew, and as long-headed as
+she was short-armed. He told me that what she had said of being here,
+and there, and everywhere, was true enough; for she made little darts
+into the provinces, and seemed to pick up customers everywhere, and to
+know everybody. I asked him what her disposition was: whether it was at
+all mischievous, and if her sympathies were generally on the right side
+of things: but, not succeeding in attracting his attention to these
+questions after two or three attempts, I forbore or forgot to repeat
+them. He told me instead, with much rapidity, a good deal about her
+skill, and her profits; and about her being a scientific cupper, if I
+should ever have occasion for her service in that capacity.
+
+She was the principal theme of our conversation during the evening:
+and when we parted for the night Steerforth called after me over the
+banisters, 'Bob swore!' as I went downstairs.
+
+I was surprised, when I came to Mr. Barkis's house, to find Ham walking
+up and down in front of it, and still more surprised to learn from him
+that little Em'ly was inside. I naturally inquired why he was not there
+too, instead of pacing the streets by himself?
+
+'Why, you see, Mas'r Davy,' he rejoined, in a hesitating manner, 'Em'ly,
+she's talking to some 'un in here.'
+
+'I should have thought,' said I, smiling, 'that that was a reason for
+your being in here too, Ham.'
+
+'Well, Mas'r Davy, in a general way, so 't would be,' he returned;
+'but look'ee here, Mas'r Davy,' lowering his voice, and speaking very
+gravely. 'It's a young woman, sir--a young woman, that Em'ly knowed
+once, and doen't ought to know no more.'
+
+When I heard these words, a light began to fall upon the figure I had
+seen following them, some hours ago.
+
+'It's a poor wurem, Mas'r Davy,' said Ham, 'as is trod under foot by all
+the town. Up street and down street. The mowld o' the churchyard don't
+hold any that the folk shrink away from, more.'
+
+'Did I see her tonight, Ham, on the sand, after we met you?'
+
+'Keeping us in sight?' said Ham. 'It's like you did, Mas'r Davy. Not
+that I know'd then, she was theer, sir, but along of her creeping soon
+arterwards under Em'ly's little winder, when she see the light come,
+and whispering "Em'ly, Em'ly, for Christ's sake, have a woman's heart
+towards me. I was once like you!" Those was solemn words, Mas'r Davy,
+fur to hear!'
+
+'They were indeed, Ham. What did Em'ly do?' 'Says Em'ly, "Martha, is
+it you? Oh, Martha, can it be you?"--for they had sat at work together,
+many a day, at Mr. Omer's.'
+
+'I recollect her now!' cried I, recalling one of the two girls I had
+seen when I first went there. 'I recollect her quite well!'
+
+'Martha Endell,' said Ham. 'Two or three year older than Em'ly, but was
+at the school with her.'
+
+'I never heard her name,' said I. 'I didn't mean to interrupt you.'
+
+'For the matter o' that, Mas'r Davy,' replied Ham, 'all's told a'most
+in them words, "Em'ly, Em'ly, for Christ's sake, have a woman's heart
+towards me. I was once like you!" She wanted to speak to Em'ly. Em'ly
+couldn't speak to her theer, for her loving uncle was come home, and
+he wouldn't--no, Mas'r Davy,' said Ham, with great earnestness, 'he
+couldn't, kind-natur'd, tender-hearted as he is, see them two together,
+side by side, for all the treasures that's wrecked in the sea.'
+
+I felt how true this was. I knew it, on the instant, quite as well as
+Ham.
+
+'So Em'ly writes in pencil on a bit of paper,' he pursued, 'and gives it
+to her out o' winder to bring here. "Show that," she says, "to my aunt,
+Mrs. Barkis, and she'll set you down by her fire, for the love of me,
+till uncle is gone out, and I can come." By and by she tells me what
+I tell you, Mas'r Davy, and asks me to bring her. What can I do? She
+doen't ought to know any such, but I can't deny her, when the tears is
+on her face.'
+
+He put his hand into the breast of his shaggy jacket, and took out with
+great care a pretty little purse.
+
+'And if I could deny her when the tears was on her face, Mas'r Davy,'
+said Ham, tenderly adjusting it on the rough palm of his hand, 'how
+could I deny her when she give me this to carry for her--knowing what
+she brought it for? Such a toy as it is!' said Ham, thoughtfully looking
+on it. 'With such a little money in it, Em'ly my dear.'
+
+I shook him warmly by the hand when he had put it away again--for that
+was more satisfactory to me than saying anything--and we walked up
+and down, for a minute or two, in silence. The door opened then, and
+Peggotty appeared, beckoning to Ham to come in. I would have kept away,
+but she came after me, entreating me to come in too. Even then, I
+would have avoided the room where they all were, but for its being the
+neat-tiled kitchen I have mentioned more than once. The door opening
+immediately into it, I found myself among them before I considered
+whither I was going.
+
+The girl--the same I had seen upon the sands--was near the fire. She
+was sitting on the ground, with her head and one arm lying on a chair.
+I fancied, from the disposition of her figure, that Em'ly had but newly
+risen from the chair, and that the forlorn head might perhaps have been
+lying on her lap. I saw but little of the girl's face, over which her
+hair fell loose and scattered, as if she had been disordering it with
+her own hands; but I saw that she was young, and of a fair complexion.
+Peggotty had been crying. So had little Em'ly. Not a word was spoken
+when we first went in; and the Dutch clock by the dresser seemed, in the
+silence, to tick twice as loud as usual. Em'ly spoke first.
+
+'Martha wants,' she said to Ham, 'to go to London.'
+
+'Why to London?' returned Ham.
+
+He stood between them, looking on the prostrate girl with a mixture of
+compassion for her, and of jealousy of her holding any companionship
+with her whom he loved so well, which I have always remembered
+distinctly. They both spoke as if she were ill; in a soft, suppressed
+tone that was plainly heard, although it hardly rose above a whisper.
+
+'Better there than here,' said a third voice aloud--Martha's, though she
+did not move. 'No one knows me there. Everybody knows me here.'
+
+'What will she do there?' inquired Ham.
+
+She lifted up her head, and looked darkly round at him for a moment;
+then laid it down again, and curved her right arm about her neck, as
+a woman in a fever, or in an agony of pain from a shot, might twist
+herself.
+
+'She will try to do well,' said little Em'ly. 'You don't know what she
+has said to us. Does he--do they--aunt?'
+
+Peggotty shook her head compassionately.
+
+'I'll try,' said Martha, 'if you'll help me away. I never can do worse
+than I have done here. I may do better. Oh!' with a dreadful shiver,
+'take me out of these streets, where the whole town knows me from a
+child!'
+
+As Em'ly held out her hand to Ham, I saw him put in it a little canvas
+bag. She took it, as if she thought it were her purse, and made a step
+or two forward; but finding her mistake, came back to where he had
+retired near me, and showed it to him.
+
+'It's all yourn, Em'ly,' I could hear him say. 'I haven't nowt in all
+the wureld that ain't yourn, my dear. It ain't of no delight to me,
+except for you!'
+
+The tears rose freshly in her eyes, but she turned away and went to
+Martha. What she gave her, I don't know. I saw her stooping over her,
+and putting money in her bosom. She whispered something, as she asked
+was that enough? 'More than enough,' the other said, and took her hand
+and kissed it.
+
+Then Martha arose, and gathering her shawl about her, covering her
+face with it, and weeping aloud, went slowly to the door. She stopped
+a moment before going out, as if she would have uttered something or
+turned back; but no word passed her lips. Making the same low, dreary,
+wretched moaning in her shawl, she went away.
+
+As the door closed, little Em'ly looked at us three in a hurried manner
+and then hid her face in her hands, and fell to sobbing.
+
+'Doen't, Em'ly!' said Ham, tapping her gently on the shoulder. 'Doen't,
+my dear! You doen't ought to cry so, pretty!'
+
+'Oh, Ham!' she exclaimed, still weeping pitifully, 'I am not so good a
+girl as I ought to be! I know I have not the thankful heart, sometimes,
+I ought to have!'
+
+'Yes, yes, you have, I'm sure,' said Ham.
+
+'No! no! no!' cried little Em'ly, sobbing, and shaking her head. 'I am
+not as good a girl as I ought to be. Not near! not near!' And still she
+cried, as if her heart would break.
+
+'I try your love too much. I know I do!' she sobbed. 'I'm often cross to
+you, and changeable with you, when I ought to be far different. You are
+never so to me. Why am I ever so to you, when I should think of nothing
+but how to be grateful, and to make you happy!'
+
+'You always make me so,' said Ham, 'my dear! I am happy in the sight of
+you. I am happy, all day long, in the thoughts of you.'
+
+'Ah! that's not enough!' she cried. 'That is because you are good; not
+because I am! Oh, my dear, it might have been a better fortune for
+you, if you had been fond of someone else--of someone steadier and
+much worthier than me, who was all bound up in you, and never vain and
+changeable like me!'
+
+'Poor little tender-heart,' said Ham, in a low voice. 'Martha has
+overset her, altogether.'
+
+'Please, aunt,' sobbed Em'ly, 'come here, and let me lay my head upon
+you. Oh, I am very miserable tonight, aunt! Oh, I am not as good a girl
+as I ought to be. I am not, I know!'
+
+Peggotty had hastened to the chair before the fire. Em'ly, with her
+arms around her neck, kneeled by her, looking up most earnestly into her
+face.
+
+'Oh, pray, aunt, try to help me! Ham, dear, try to help me! Mr. David,
+for the sake of old times, do, please, try to help me! I want to be a
+better girl than I am. I want to feel a hundred times more thankful than
+I do. I want to feel more, what a blessed thing it is to be the wife of
+a good man, and to lead a peaceful life. Oh me, oh me! Oh my heart, my
+heart!'
+
+She dropped her face on my old nurse's breast, and, ceasing this
+supplication, which in its agony and grief was half a woman's, half a
+child's, as all her manner was (being, in that, more natural, and better
+suited to her beauty, as I thought, than any other manner could have
+been), wept silently, while my old nurse hushed her like an infant.
+
+She got calmer by degrees, and then we soothed her; now talking
+encouragingly, and now jesting a little with her, until she began to
+raise her head and speak to us. So we got on, until she was able to
+smile, and then to laugh, and then to sit up, half ashamed; while
+Peggotty recalled her stray ringlets, dried her eyes, and made her neat
+again, lest her uncle should wonder, when she got home, why his darling
+had been crying.
+
+I saw her do, that night, what I had never seen her do before. I saw her
+innocently kiss her chosen husband on the cheek, and creep close to his
+bluff form as if it were her best support. When they went away together,
+in the waning moonlight, and I looked after them, comparing their
+departure in my mind with Martha's, I saw that she held his arm with
+both her hands, and still kept close to him.
+
+
+
+CHAPTER 23. I CORROBORATE Mr. DICK, AND CHOOSE A PROFESSION
+
+
+When I awoke in the morning I thought very much of little Em'ly, and her
+emotion last night, after Martha had left. I felt as if I had come into
+the knowledge of those domestic weaknesses and tendernesses in a sacred
+confidence, and that to disclose them, even to Steerforth, would be
+wrong. I had no gentler feeling towards anyone than towards the
+pretty creature who had been my playmate, and whom I have always been
+persuaded, and shall always be persuaded, to my dying day, I then
+devotedly loved. The repetition to any ears--even to Steerforth's--of
+what she had been unable to repress when her heart lay open to me by an
+accident, I felt would be a rough deed, unworthy of myself, unworthy of
+the light of our pure childhood, which I always saw encircling her head.
+I made a resolution, therefore, to keep it in my own breast; and there
+it gave her image a new grace.
+
+While we were at breakfast, a letter was delivered to me from my aunt.
+As it contained matter on which I thought Steerforth could advise me
+as well as anyone, and on which I knew I should be delighted to consult
+him, I resolved to make it a subject of discussion on our journey home.
+For the present we had enough to do, in taking leave of all our friends.
+Mr. Barkis was far from being the last among them, in his regret at
+our departure; and I believe would even have opened the box again, and
+sacrificed another guinea, if it would have kept us eight-and-forty
+hours in Yarmouth. Peggotty and all her family were full of grief at our
+going. The whole house of Omer and Joram turned out to bid us good-bye;
+and there were so many seafaring volunteers in attendance on Steerforth,
+when our portmanteaux went to the coach, that if we had had the baggage
+of a regiment with us, we should hardly have wanted porters to carry it.
+In a word, we departed to the regret and admiration of all concerned,
+and left a great many people very sorry behind US.
+
+Do you stay long here, Littimer?' said I, as he stood waiting to see the
+coach start.
+
+'No, sir,' he replied; 'probably not very long, sir.'
+
+'He can hardly say, just now,' observed Steerforth, carelessly. 'He
+knows what he has to do, and he'll do it.'
+
+'That I am sure he will,' said I.
+
+Littimer touched his hat in acknowledgement of my good opinion, and I
+felt about eight years old. He touched it once more, wishing us a good
+journey; and we left him standing on the pavement, as respectable a
+mystery as any pyramid in Egypt.
+
+For some little time we held no conversation, Steerforth being unusually
+silent, and I being sufficiently engaged in wondering, within myself,
+when I should see the old places again, and what new changes might
+happen to me or them in the meanwhile. At length Steerforth, becoming
+gay and talkative in a moment, as he could become anything he liked at
+any moment, pulled me by the arm:
+
+'Find a voice, David. What about that letter you were speaking of at
+breakfast?'
+
+'Oh!' said I, taking it out of my pocket. 'It's from my aunt.'
+
+'And what does she say, requiring consideration?'
+
+'Why, she reminds me, Steerforth,' said I, 'that I came out on this
+expedition to look about me, and to think a little.'
+
+'Which, of course, you have done?'
+
+'Indeed I can't say I have, particularly. To tell you the truth, I am
+afraid I have forgotten it.'
+
+'Well! look about you now, and make up for your negligence,' said
+Steerforth. 'Look to the right, and you'll see a flat country, with a
+good deal of marsh in it; look to the left, and you'll see the same.
+Look to the front, and you'll find no difference; look to the rear,
+and there it is still.' I laughed, and replied that I saw no suitable
+profession in the whole prospect; which was perhaps to be attributed to
+its flatness.
+
+'What says our aunt on the subject?' inquired Steerforth, glancing at
+the letter in my hand. 'Does she suggest anything?'
+
+'Why, yes,' said I. 'She asks me, here, if I think I should like to be a
+proctor? What do you think of it?'
+
+'Well, I don't know,' replied Steerforth, coolly. 'You may as well do
+that as anything else, I suppose?'
+
+I could not help laughing again, at his balancing all callings and
+professions so equally; and I told him so.
+
+'What is a proctor, Steerforth?' said I.
+
+'Why, he is a sort of monkish attorney,' replied Steerforth. 'He is, to
+some faded courts held in Doctors' Commons,--a lazy old nook near St.
+Paul's Churchyard--what solicitors are to the courts of law and equity.
+He is a functionary whose existence, in the natural course of things,
+would have terminated about two hundred years ago. I can tell you best
+what he is, by telling you what Doctors' Commons is. It's a
+little out-of-the-way place, where they administer what is called
+ecclesiastical law, and play all kinds of tricks with obsolete old
+monsters of acts of Parliament, which three-fourths of the world know
+nothing about, and the other fourth supposes to have been dug up, in
+a fossil state, in the days of the Edwards. It's a place that has an
+ancient monopoly in suits about people's wills and people's marriages,
+and disputes among ships and boats.'
+
+'Nonsense, Steerforth!' I exclaimed. 'You don't mean to say that there
+is any affinity between nautical matters and ecclesiastical matters?'
+
+'I don't, indeed, my dear boy,' he returned; 'but I mean to say that
+they are managed and decided by the same set of people, down in that
+same Doctors' Commons. You shall go there one day, and find them
+blundering through half the nautical terms in Young's Dictionary,
+apropos of the "Nancy" having run down the "Sarah Jane", or Mr. Peggotty
+and the Yarmouth boatmen having put off in a gale of wind with an anchor
+and cable to the "Nelson" Indiaman in distress; and you shall go there
+another day, and find them deep in the evidence, pro and con, respecting
+a clergyman who has misbehaved himself; and you shall find the judge
+in the nautical case, the advocate in the clergyman's case, or
+contrariwise. They are like actors: now a man's a judge, and now he is
+not a judge; now he's one thing, now he's another; now he's something
+else, change and change about; but it's always a very pleasant,
+profitable little affair of private theatricals, presented to an
+uncommonly select audience.'
+
+'But advocates and proctors are not one and the same?' said I, a little
+puzzled. 'Are they?'
+
+'No,' returned Steerforth, 'the advocates are civilians--men who have
+taken a doctor's degree at college--which is the first reason of my
+knowing anything about it. The proctors employ the advocates. Both get
+very comfortable fees, and altogether they make a mighty snug little
+party. On the whole, I would recommend you to take to Doctors' Commons
+kindly, David. They plume them-selves on their gentility there, I can
+tell you, if that's any satisfaction.'
+
+I made allowance for Steerforth's light way of treating the subject,
+and, considering it with reference to the staid air of gravity and
+antiquity which I associated with that 'lazy old nook near St. Paul's
+Churchyard', did not feel indisposed towards my aunt's suggestion; which
+she left to my free decision, making no scruple of telling me that it
+had occurred to her, on her lately visiting her own proctor in Doctors'
+Commons for the purpose of settling her will in my favour.
+
+'That's a laudable proceeding on the part of our aunt, at all events,'
+said Steerforth, when I mentioned it; 'and one deserving of all
+encouragement. Daisy, my advice is that you take kindly to Doctors'
+Commons.'
+
+I quite made up my mind to do so. I then told Steerforth that my aunt
+was in town awaiting me (as I found from her letter), and that she had
+taken lodgings for a week at a kind of private hotel at Lincoln's Inn
+Fields, where there was a stone staircase, and a convenient door in
+the roof; my aunt being firmly persuaded that every house in London was
+going to be burnt down every night.
+
+We achieved the rest of our journey pleasantly, sometimes recurring to
+Doctors' Commons, and anticipating the distant days when I should be a
+proctor there, which Steerforth pictured in a variety of humorous and
+whimsical lights, that made us both merry. When we came to our journey's
+end, he went home, engaging to call upon me next day but one; and I
+drove to Lincoln's Inn Fields, where I found my aunt up, and waiting
+supper.
+
+If I had been round the world since we parted, we could hardly have been
+better pleased to meet again. My aunt cried outright as she embraced me;
+and said, pretending to laugh, that if my poor mother had been alive,
+that silly little creature would have shed tears, she had no doubt.
+
+'So you have left Mr. Dick behind, aunt?' said I. 'I am sorry for that.
+Ah, Janet, how do you do?'
+
+As Janet curtsied, hoping I was well, I observed my aunt's visage
+lengthen very much.
+
+'I am sorry for it, too,' said my aunt, rubbing her nose. 'I have had
+no peace of mind, Trot, since I have been here.' Before I could ask why,
+she told me.
+
+'I am convinced,' said my aunt, laying her hand with melancholy firmness
+on the table, 'that Dick's character is not a character to keep the
+donkeys off. I am confident he wants strength of purpose. I ought to
+have left Janet at home, instead, and then my mind might perhaps have
+been at ease. If ever there was a donkey trespassing on my green,' said
+my aunt, with emphasis, 'there was one this afternoon at four o'clock.
+A cold feeling came over me from head to foot, and I know it was a
+donkey!'
+
+I tried to comfort her on this point, but she rejected consolation.
+
+'It was a donkey,' said my aunt; 'and it was the one with the stumpy
+tail which that Murdering sister of a woman rode, when she came to my
+house.' This had been, ever since, the only name my aunt knew for Miss
+Murdstone. 'If there is any Donkey in Dover, whose audacity it is harder
+to me to bear than another's, that,' said my aunt, striking the table,
+'is the animal!'
+
+Janet ventured to suggest that my aunt might be disturbing herself
+unnecessarily, and that she believed the donkey in question was then
+engaged in the sand-and-gravel line of business, and was not available
+for purposes of trespass. But my aunt wouldn't hear of it.
+
+Supper was comfortably served and hot, though my aunt's rooms were very
+high up--whether that she might have more stone stairs for her money, or
+might be nearer to the door in the roof, I don't know--and consisted of
+a roast fowl, a steak, and some vegetables, to all of which I did ample
+justice, and which were all excellent. But my aunt had her own ideas
+concerning London provision, and ate but little.
+
+'I suppose this unfortunate fowl was born and brought up in a cellar,'
+said my aunt, 'and never took the air except on a hackney coach-stand. I
+hope the steak may be beef, but I don't believe it. Nothing's genuine in
+the place, in my opinion, but the dirt.'
+
+'Don't you think the fowl may have come out of the country, aunt?' I
+hinted.
+
+'Certainly not,' returned my aunt. 'It would be no pleasure to a London
+tradesman to sell anything which was what he pretended it was.'
+
+I did not venture to controvert this opinion, but I made a good supper,
+which it greatly satisfied her to see me do. When the table was cleared,
+Janet assisted her to arrange her hair, to put on her nightcap, which
+was of a smarter construction than usual ('in case of fire', my aunt
+said), and to fold her gown back over her knees, these being her usual
+preparations for warming herself before going to bed. I then made her,
+according to certain established regulations from which no deviation,
+however slight, could ever be permitted, a glass of hot wine and
+water, and a slice of toast cut into long thin strips. With these
+accompaniments we were left alone to finish the evening, my aunt sitting
+opposite to me drinking her wine and water; soaking her strips of toast
+in it, one by one, before eating them; and looking benignantly on me,
+from among the borders of her nightcap.
+
+'Well, Trot,' she began, 'what do you think of the proctor plan? Or have
+you not begun to think about it yet?'
+
+'I have thought a good deal about it, my dear aunt, and I have talked a
+good deal about it with Steerforth. I like it very much indeed. I like
+it exceedingly.'
+
+'Come!' said my aunt. 'That's cheering!'
+
+'I have only one difficulty, aunt.'
+
+'Say what it is, Trot,' she returned.
+
+'Why, I want to ask, aunt, as this seems, from what I understand, to
+be a limited profession, whether my entrance into it would not be very
+expensive?'
+
+'It will cost,' returned my aunt, 'to article you, just a thousand
+pounds.'
+
+'Now, my dear aunt,' said I, drawing my chair nearer, 'I am uneasy in
+my mind about that. It's a large sum of money. You have expended a
+great deal on my education, and have always been as liberal to me in all
+things as it was possible to be. You have been the soul of generosity.
+Surely there are some ways in which I might begin life with hardly any
+outlay, and yet begin with a good hope of getting on by resolution and
+exertion. Are you sure that it would not be better to try that course?
+Are you certain that you can afford to part with so much money, and that
+it is right that it should be so expended? I only ask you, my second
+mother, to consider. Are you certain?'
+
+My aunt finished eating the piece of toast on which she was then
+engaged, looking me full in the face all the while; and then setting
+her glass on the chimney-piece, and folding her hands upon her folded
+skirts, replied as follows:
+
+'Trot, my child, if I have any object in life, it is to provide for
+your being a good, a sensible, and a happy man. I am bent upon it--so is
+Dick. I should like some people that I know to hear Dick's conversation
+on the subject. Its sagacity is wonderful. But no one knows the
+resources of that man's intellect, except myself!'
+
+She stopped for a moment to take my hand between hers, and went on:
+
+'It's in vain, Trot, to recall the past, unless it works some influence
+upon the present. Perhaps I might have been better friends with your
+poor father. Perhaps I might have been better friends with that poor
+child your mother, even after your sister Betsey Trotwood disappointed
+me. When you came to me, a little runaway boy, all dusty and way-worn,
+perhaps I thought so. From that time until now, Trot, you have ever been
+a credit to me and a pride and a pleasure. I have no other claim upon
+my means; at least'--here to my surprise she hesitated, and was
+confused--'no, I have no other claim upon my means--and you are my
+adopted child. Only be a loving child to me in my age, and bear with my
+whims and fancies; and you will do more for an old woman whose prime of
+life was not so happy or conciliating as it might have been, than ever
+that old woman did for you.'
+
+It was the first time I had heard my aunt refer to her past history.
+There was a magnanimity in her quiet way of doing so, and of dismissing
+it, which would have exalted her in my respect and affection, if
+anything could.
+
+'All is agreed and understood between us, now, Trot,' said my aunt,
+'and we need talk of this no more. Give me a kiss, and we'll go to the
+Commons after breakfast tomorrow.'
+
+We had a long chat by the fire before we went to bed. I slept in a room
+on the same floor with my aunt's, and was a little disturbed in the
+course of the night by her knocking at my door as often as she was
+agitated by a distant sound of hackney-coaches or market-carts, and
+inquiring, 'if I heard the engines?' But towards morning she slept
+better, and suffered me to do so too.
+
+At about mid-day, we set out for the office of Messrs Spenlow and
+Jorkins, in Doctors' Commons. My aunt, who had this other general
+opinion in reference to London, that every man she saw was a pickpocket,
+gave me her purse to carry for her, which had ten guineas in it and some
+silver.
+
+We made a pause at the toy shop in Fleet Street, to see the giants of
+Saint Dunstan's strike upon the bells--we had timed our going, so as to
+catch them at it, at twelve o'clock--and then went on towards Ludgate
+Hill, and St. Paul's Churchyard. We were crossing to the former place,
+when I found that my aunt greatly accelerated her speed, and looked
+frightened. I observed, at the same time, that a lowering ill-dressed
+man who had stopped and stared at us in passing, a little before, was
+coming so close after us as to brush against her.
+
+'Trot! My dear Trot!' cried my aunt, in a terrified whisper, and
+pressing my arm. 'I don't know what I am to do.'
+
+'Don't be alarmed,' said I. 'There's nothing to be afraid of. Step into
+a shop, and I'll soon get rid of this fellow.'
+
+'No, no, child!' she returned. 'Don't speak to him for the world. I
+entreat, I order you!'
+
+'Good Heaven, aunt!' said I. 'He is nothing but a sturdy beggar.'
+
+'You don't know what he is!' replied my aunt. 'You don't know who he is!
+You don't know what you say!'
+
+We had stopped in an empty door-way, while this was passing, and he had
+stopped too.
+
+'Don't look at him!' said my aunt, as I turned my head indignantly, 'but
+get me a coach, my dear, and wait for me in St. Paul's Churchyard.'
+
+'Wait for you?' I replied.
+
+'Yes,' rejoined my aunt. 'I must go alone. I must go with him.'
+
+'With him, aunt? This man?'
+
+'I am in my senses,' she replied, 'and I tell you I must. Get mea
+coach!'
+
+However much astonished I might be, I was sensible that I had no right
+to refuse compliance with such a peremptory command. I hurried away a
+few paces, and called a hackney-chariot which was passing empty. Almost
+before I could let down the steps, my aunt sprang in, I don't know how,
+and the man followed. She waved her hand to me to go away, so earnestly,
+that, all confounded as I was, I turned from them at once. In doing so,
+I heard her say to the coachman, 'Drive anywhere! Drive straight on!'
+and presently the chariot passed me, going up the hill.
+
+What Mr. Dick had told me, and what I had supposed to be a delusion of
+his, now came into my mind. I could not doubt that this person was the
+person of whom he had made such mysterious mention, though what the
+nature of his hold upon my aunt could possibly be, I was quite unable
+to imagine. After half an hour's cooling in the churchyard, I saw the
+chariot coming back. The driver stopped beside me, and my aunt was
+sitting in it alone.
+
+She had not yet sufficiently recovered from her agitation to be quite
+prepared for the visit we had to make. She desired me to get into the
+chariot, and to tell the coachman to drive slowly up and down a little
+while. She said no more, except, 'My dear child, never ask me what
+it was, and don't refer to it,' until she had perfectly regained her
+composure, when she told me she was quite herself now, and we might get
+out. On her giving me her purse to pay the driver, I found that all the
+guineas were gone, and only the loose silver remained.
+
+Doctors' Commons was approached by a little low archway. Before we had
+taken many paces down the street beyond it, the noise of the city seemed
+to melt, as if by magic, into a softened distance. A few dull courts
+and narrow ways brought us to the sky-lighted offices of Spenlow and
+Jorkins; in the vestibule of which temple, accessible to pilgrims
+without the ceremony of knocking, three or four clerks were at work as
+copyists. One of these, a little dry man, sitting by himself, who wore
+a stiff brown wig that looked as if it were made of gingerbread, rose to
+receive my aunt, and show us into Mr. Spenlow's room.
+
+'Mr. Spenlow's in Court, ma'am,' said the dry man; 'it's an Arches day;
+but it's close by, and I'll send for him directly.'
+
+As we were left to look about us while Mr. Spenlow was fetched, I
+availed myself of the opportunity. The furniture of the room was
+old-fashioned and dusty; and the green baize on the top of the
+writing-table had lost all its colour, and was as withered and pale as
+an old pauper. There were a great many bundles of papers on it, some
+endorsed as Allegations, and some (to my surprise) as Libels, and some
+as being in the Consistory Court, and some in the Arches Court, and some
+in the Prerogative Court, and some in the Admiralty Court, and some in
+the Delegates' Court; giving me occasion to wonder much, how many Courts
+there might be in the gross, and how long it would take to understand
+them all. Besides these, there were sundry immense manuscript Books
+of Evidence taken on affidavit, strongly bound, and tied together in
+massive sets, a set to each cause, as if every cause were a history in
+ten or twenty volumes. All this looked tolerably expensive, I thought,
+and gave me an agreeable notion of a proctor's business. I was casting
+my eyes with increasing complacency over these and many similar objects,
+when hasty footsteps were heard in the room outside, and Mr. Spenlow,
+in a black gown trimmed with white fur, came hurrying in, taking off his
+hat as he came.
+
+He was a little light-haired gentleman, with undeniable boots, and the
+stiffest of white cravats and shirt-collars. He was buttoned up, mighty
+trim and tight, and must have taken a great deal of pains with his
+whiskers, which were accurately curled. His gold watch-chain was so
+massive, that a fancy came across me, that he ought to have a sinewy
+golden arm, to draw it out with, like those which are put up over the
+goldbeaters' shops. He was got up with such care, and was so stiff, that
+he could hardly bend himself; being obliged, when he glanced at some
+papers on his desk, after sitting down in his chair, to move his whole
+body, from the bottom of his spine, like Punch.
+
+I had previously been presented by my aunt, and had been courteously
+received. He now said:
+
+'And so, Mr. Copperfield, you think of entering into our profession?
+I casually mentioned to Miss Trotwood, when I had the pleasure of an
+interview with her the other day,'--with another inclination of his
+body--Punch again--'that there was a vacancy here. Miss Trotwood was
+good enough to mention that she had a nephew who was her peculiar care,
+and for whom she was seeking to provide genteelly in life. That
+nephew, I believe, I have now the pleasure of'--Punch again. I bowed my
+acknowledgements, and said, my aunt had mentioned to me that there was
+that opening, and that I believed I should like it very much. That I was
+strongly inclined to like it, and had taken immediately to the proposal.
+That I could not absolutely pledge myself to like it, until I knew
+something more about it. That although it was little else than a matter
+of form, I presumed I should have an opportunity of trying how I liked
+it, before I bound myself to it irrevocably.
+
+'Oh surely! surely!' said Mr. Spenlow. 'We always, in this house,
+propose a month--an initiatory month. I should be happy, myself, to
+propose two months--three--an indefinite period, in fact--but I have a
+partner. Mr. Jorkins.'
+
+'And the premium, sir,' I returned, 'is a thousand pounds?'
+
+'And the premium, Stamp included, is a thousand pounds,' said Mr.
+Spenlow. 'As I have mentioned to Miss Trotwood, I am actuated by no
+mercenary considerations; few men are less so, I believe; but Mr.
+Jorkins has his opinions on these subjects, and I am bound to respect
+Mr. Jorkins's opinions. Mr. Jorkins thinks a thousand pounds too little,
+in short.'
+
+'I suppose, sir,' said I, still desiring to spare my aunt, 'that it is
+not the custom here, if an articled clerk were particularly useful,
+and made himself a perfect master of his profession'--I could not help
+blushing, this looked so like praising myself--'I suppose it is not the
+custom, in the later years of his time, to allow him any--'
+
+Mr. Spenlow, by a great effort, just lifted his head far enough out of
+his cravat to shake it, and answered, anticipating the word 'salary':
+
+'No. I will not say what consideration I might give to that point
+myself, Mr. Copperfield, if I were unfettered. Mr. Jorkins is
+immovable.'
+
+I was quite dismayed by the idea of this terrible Jorkins. But I found
+out afterwards that he was a mild man of a heavy temperament, whose
+place in the business was to keep himself in the background, and be
+constantly exhibited by name as the most obdurate and ruthless of men.
+If a clerk wanted his salary raised, Mr. Jorkins wouldn't listen to such
+a proposition. If a client were slow to settle his bill of costs, Mr.
+Jorkins was resolved to have it paid; and however painful these things
+might be (and always were) to the feelings of Mr. Spenlow, Mr. Jorkins
+would have his bond. The heart and hand of the good angel Spenlow would
+have been always open, but for the restraining demon Jorkins. As I have
+grown older, I think I have had experience of some other houses doing
+business on the principle of Spenlow and Jorkins!
+
+It was settled that I should begin my month's probation as soon as I
+pleased, and that my aunt need neither remain in town nor return at
+its expiration, as the articles of agreement, of which I was to be the
+subject, could easily be sent to her at home for her signature. When
+we had got so far, Mr. Spenlow offered to take me into Court then and
+there, and show me what sort of place it was. As I was willing enough
+to know, we went out with this object, leaving my aunt behind; who would
+trust herself, she said, in no such place, and who, I think, regarded
+all Courts of Law as a sort of powder-mills that might blow up at any
+time.
+
+Mr. Spenlow conducted me through a paved courtyard formed of grave brick
+houses, which I inferred, from the Doctors' names upon the doors, to be
+the official abiding-places of the learned advocates of whom Steerforth
+had told me; and into a large dull room, not unlike a chapel to my
+thinking, on the left hand. The upper part of this room was fenced off
+from the rest; and there, on the two sides of a raised platform of the
+horse-shoe form, sitting on easy old-fashioned dining-room chairs, were
+sundry gentlemen in red gowns and grey wigs, whom I found to be the
+Doctors aforesaid. Blinking over a little desk like a pulpit-desk, in
+the curve of the horse-shoe, was an old gentleman, whom, if I had seen
+him in an aviary, I should certainly have taken for an owl, but who, I
+learned, was the presiding judge. In the space within the horse-shoe,
+lower than these, that is to say, on about the level of the floor, were
+sundry other gentlemen, of Mr. Spenlow's rank, and dressed like him in
+black gowns with white fur upon them, sitting at a long green table.
+Their cravats were in general stiff, I thought, and their looks haughty;
+but in this last respect I presently conceived I had done them an
+injustice, for when two or three of them had to rise and answer a
+question of the presiding dignitary, I never saw anything more sheepish.
+The public, represented by a boy with a comforter, and a shabby-genteel
+man secretly eating crumbs out of his coat pockets, was warming itself
+at a stove in the centre of the Court. The languid stillness of the
+place was only broken by the chirping of this fire and by the voice of
+one of the Doctors, who was wandering slowly through a perfect library
+of evidence, and stopping to put up, from time to time, at little
+roadside inns of argument on the journey. Altogether, I have never,
+on any occasion, made one at such a cosey, dosey, old-fashioned,
+time-forgotten, sleepy-headed little family-party in all my life; and
+I felt it would be quite a soothing opiate to belong to it in any
+character--except perhaps as a suitor.
+
+Very well satisfied with the dreamy nature of this retreat, I informed
+Mr. Spenlow that I had seen enough for that time, and we rejoined
+my aunt; in company with whom I presently departed from the Commons,
+feeling very young when I went out of Spenlow and Jorkins's, on account
+of the clerks poking one another with their pens to point me out.
+
+We arrived at Lincoln's Inn Fields without any new adventures, except
+encountering an unlucky donkey in a costermonger's cart, who suggested
+painful associations to my aunt. We had another long talk about my
+plans, when we were safely housed; and as I knew she was anxious to
+get home, and, between fire, food, and pickpockets, could never be
+considered at her ease for half-an-hour in London, I urged her not to be
+uncomfortable on my account, but to leave me to take care of myself.
+
+'I have not been here a week tomorrow, without considering that too, my
+dear,' she returned. 'There is a furnished little set of chambers to be
+let in the Adelphi, Trot, which ought to suit you to a marvel.'
+
+With this brief introduction, she produced from her pocket an
+advertisement, carefully cut out of a newspaper, setting forth that in
+Buckingham Street in the Adelphi there was to be let furnished, with a
+view of the river, a singularly desirable, and compact set of chambers,
+forming a genteel residence for a young gentleman, a member of one
+of the Inns of Court, or otherwise, with immediate possession. Terms
+moderate, and could be taken for a month only, if required.
+
+'Why, this is the very thing, aunt!' said I, flushed with the possible
+dignity of living in chambers.
+
+'Then come,' replied my aunt, immediately resuming the bonnet she had a
+minute before laid aside. 'We'll go and look at 'em.'
+
+Away we went. The advertisement directed us to apply to Mrs. Crupp
+on the premises, and we rung the area bell, which we supposed to
+communicate with Mrs. Crupp. It was not until we had rung three or four
+times that we could prevail on Mrs. Crupp to communicate with us, but
+at last she appeared, being a stout lady with a flounce of flannel
+petticoat below a nankeen gown.
+
+'Let us see these chambers of yours, if you please, ma'am,' said my
+aunt.
+
+'For this gentleman?' said Mrs. Crupp, feeling in her pocket for her
+keys.
+
+'Yes, for my nephew,' said my aunt.
+
+'And a sweet set they is for sich!' said Mrs. Crupp.
+
+So we went upstairs.
+
+They were on the top of the house--a great point with my aunt, being
+near the fire-escape--and consisted of a little half-blind entry where
+you could see hardly anything, a little stone-blind pantry where you
+could see nothing at all, a sitting-room, and a bedroom. The furniture
+was rather faded, but quite good enough for me; and, sure enough, the
+river was outside the windows.
+
+As I was delighted with the place, my aunt and Mrs. Crupp withdrew into
+the pantry to discuss the terms, while I remained on the sitting-room
+sofa, hardly daring to think it possible that I could be destined to
+live in such a noble residence. After a single combat of some duration
+they returned, and I saw, to my joy, both in Mrs. Crupp's countenance
+and in my aunt's, that the deed was done.
+
+'Is it the last occupant's furniture?' inquired my aunt.
+
+'Yes, it is, ma'am,' said Mrs. Crupp.
+
+'What's become of him?' asked my aunt.
+
+Mrs. Crupp was taken with a troublesome cough, in the midst of which
+she articulated with much difficulty. 'He was took ill here, ma'am,
+and--ugh! ugh! ugh! dear me!--and he died!'
+
+'Hey! What did he die of?' asked my aunt.
+
+'Well, ma'am, he died of drink,' said Mrs. Crupp, in confidence. 'And
+smoke.'
+
+'Smoke? You don't mean chimneys?' said my aunt.
+
+'No, ma'am,' returned Mrs. Crupp. 'Cigars and pipes.'
+
+'That's not catching, Trot, at any rate,' remarked my aunt, turning to
+me.
+
+'No, indeed,' said I.
+
+In short, my aunt, seeing how enraptured I was with the premises, took
+them for a month, with leave to remain for twelve months when that
+time was out. Mrs. Crupp was to find linen, and to cook; every other
+necessary was already provided; and Mrs. Crupp expressly intimated that
+she should always yearn towards me as a son. I was to take possession
+the day after tomorrow, and Mrs. Crupp said, thank Heaven she had now
+found summun she could care for!
+
+On our way back, my aunt informed me how she confidently trusted that
+the life I was now to lead would make me firm and self-reliant, which
+was all I wanted. She repeated this several times next day, in the
+intervals of our arranging for the transmission of my clothes and books
+from Mr. Wickfield's; relative to which, and to all my late holiday, I
+wrote a long letter to Agnes, of which my aunt took charge, as she was
+to leave on the succeeding day. Not to lengthen these particulars, I
+need only add, that she made a handsome provision for all my
+possible wants during my month of trial; that Steerforth, to my great
+disappointment and hers too, did not make his appearance before she went
+away; that I saw her safely seated in the Dover coach, exulting in the
+coming discomfiture of the vagrant donkeys, with Janet at her side; and
+that when the coach was gone, I turned my face to the Adelphi, pondering
+on the old days when I used to roam about its subterranean arches, and
+on the happy changes which had brought me to the surface.
+
+
+
+CHAPTER 24. MY FIRST DISSIPATION
+
+
+It was a wonderfully fine thing to have that lofty castle to myself, and
+to feel, when I shut my outer door, like Robinson Crusoe, when he had
+got into his fortification, and pulled his ladder up after him. It was a
+wonderfully fine thing to walk about town with the key of my house in my
+pocket, and to know that I could ask any fellow to come home, and make
+quite sure of its being inconvenient to nobody, if it were not so to me.
+It was a wonderfully fine thing to let myself in and out, and to come
+and go without a word to anyone, and to ring Mrs. Crupp up, gasping,
+from the depths of the earth, when I wanted her--and when she was
+disposed to come. All this, I say, was wonderfully fine; but I must say,
+too, that there were times when it was very dreary.
+
+It was fine in the morning, particularly in the fine mornings. It looked
+a very fresh, free life, by daylight: still fresher, and more free, by
+sunlight. But as the day declined, the life seemed to go down too. I
+don't know how it was; it seldom looked well by candle-light. I wanted
+somebody to talk to, then. I missed Agnes. I found a tremendous blank,
+in the place of that smiling repository of my confidence. Mrs. Crupp
+appeared to be a long way off. I thought about my predecessor, who had
+died of drink and smoke; and I could have wished he had been so good as
+to live, and not bother me with his decease.
+
+After two days and nights, I felt as if I had lived there for a year,
+and yet I was not an hour older, but was quite as much tormented by my
+own youthfulness as ever.
+
+Steerforth not yet appearing, which induced me to apprehend that he must
+be ill, I left the Commons early on the third day, and walked out to
+Highgate. Mrs. Steerforth was very glad to see me, and said that he had
+gone away with one of his Oxford friends to see another who lived near
+St. Albans, but that she expected him to return tomorrow. I was so fond
+of him, that I felt quite jealous of his Oxford friends.
+
+As she pressed me to stay to dinner, I remained, and I believe we talked
+about nothing but him all day. I told her how much the people liked him
+at Yarmouth, and what a delightful companion he had been. Miss Dartle
+was full of hints and mysterious questions, but took a great interest
+in all our proceedings there, and said, 'Was it really though?' and so
+forth, so often, that she got everything out of me she wanted to know.
+Her appearance was exactly what I have described it, when I first saw
+her; but the society of the two ladies was so agreeable, and came so
+natural to me, that I felt myself falling a little in love with her. I
+could not help thinking, several times in the course of the evening, and
+particularly when I walked home at night, what delightful company she
+would be in Buckingham Street.
+
+I was taking my coffee and roll in the morning, before going to the
+Commons--and I may observe in this place that it is surprising how
+much coffee Mrs. Crupp used, and how weak it was, considering--when
+Steerforth himself walked in, to my unbounded joy.
+
+'My dear Steerforth,' cried I, 'I began to think I should never see you
+again!'
+
+'I was carried off, by force of arms,' said Steerforth, 'the very next
+morning after I got home. Why, Daisy, what a rare old bachelor you are
+here!'
+
+I showed him over the establishment, not omitting the pantry, with no
+little pride, and he commended it highly. 'I tell you what, old boy,' he
+added, 'I shall make quite a town-house of this place, unless you give
+me notice to quit.'
+
+This was a delightful hearing. I told him if he waited for that, he
+would have to wait till doomsday.
+
+'But you shall have some breakfast!' said I, with my hand on the
+bell-rope, 'and Mrs. Crupp shall make you some fresh coffee, and I'll
+toast you some bacon in a bachelor's Dutch-oven, that I have got here.'
+
+'No, no!' said Steerforth. 'Don't ring! I can't! I am going to breakfast
+with one of these fellows who is at the Piazza Hotel, in Covent Garden.'
+
+'But you'll come back to dinner?' said I.
+
+'I can't, upon my life. There's nothing I should like better, but I must
+remain with these two fellows. We are all three off together tomorrow
+morning.'
+
+'Then bring them here to dinner,' I returned. 'Do you think they would
+come?'
+
+'Oh! they would come fast enough,' said Steerforth; 'but we should
+inconvenience you. You had better come and dine with us somewhere.'
+
+I would not by any means consent to this, for it occurred to me that I
+really ought to have a little house-warming, and that there never
+could be a better opportunity. I had a new pride in my rooms after
+his approval of them, and burned with a desire to develop their utmost
+resources. I therefore made him promise positively in the names of his
+two friends, and we appointed six o'clock as the dinner-hour.
+
+When he was gone, I rang for Mrs. Crupp, and acquainted her with my
+desperate design. Mrs. Crupp said, in the first place, of course it was
+well known she couldn't be expected to wait, but she knew a handy young
+man, who she thought could be prevailed upon to do it, and whose terms
+would be five shillings, and what I pleased. I said, certainly we would
+have him. Next Mrs. Crupp said it was clear she couldn't be in two
+places at once (which I felt to be reasonable), and that 'a young gal'
+stationed in the pantry with a bedroom candle, there never to desist
+from washing plates, would be indispensable. I said, what would be
+the expense of this young female? and Mrs. Crupp said she supposed
+eighteenpence would neither make me nor break me. I said I supposed not;
+and THAT was settled. Then Mrs. Crupp said, Now about the dinner.
+
+It was a remarkable instance of want of forethought on the part of the
+ironmonger who had made Mrs. Crupp's kitchen fireplace, that it was
+capable of cooking nothing but chops and mashed potatoes. As to a
+fish-kittle, Mrs. Crupp said, well! would I only come and look at the
+range? She couldn't say fairer than that. Would I come and look at
+it? As I should not have been much the wiser if I HAD looked at it, I
+declined, and said, 'Never mind fish.' But Mrs. Crupp said, Don't say
+that; oysters was in, why not them? So THAT was settled. Mrs. Crupp
+then said what she would recommend would be this. A pair of hot
+roast fowls--from the pastry-cook's; a dish of stewed beef, with
+vegetables--from the pastry-cook's; two little corner things, as a
+raised pie and a dish of kidneys--from the pastrycook's; a tart, and (if
+I liked) a shape of jelly--from the pastrycook's. This, Mrs. Crupp said,
+would leave her at full liberty to concentrate her mind on the potatoes,
+and to serve up the cheese and celery as she could wish to see it done.
+
+I acted on Mrs. Crupp's opinion, and gave the order at the pastry-cook's
+myself. Walking along the Strand, afterwards, and observing a hard
+mottled substance in the window of a ham and beef shop, which resembled
+marble, but was labelled 'Mock Turtle', I went in and bought a slab of
+it, which I have since seen reason to believe would have sufficed for
+fifteen people. This preparation, Mrs. Crupp, after some difficulty,
+consented to warm up; and it shrunk so much in a liquid state, that we
+found it what Steerforth called 'rather a tight fit' for four.
+
+These preparations happily completed, I bought a little dessert in
+Covent Garden Market, and gave a rather extensive order at a retail
+wine-merchant's in that vicinity. When I came home in the afternoon, and
+saw the bottles drawn up in a square on the pantry floor, they looked
+so numerous (though there were two missing, which made Mrs. Crupp very
+uncomfortable), that I was absolutely frightened at them.
+
+One of Steerforth's friends was named Grainger, and the other Markham.
+They were both very gay and lively fellows; Grainger, something older
+than Steerforth; Markham, youthful-looking, and I should say not
+more than twenty. I observed that the latter always spoke of himself
+indefinitely, as 'a man', and seldom or never in the first person
+singular.
+
+'A man might get on very well here, Mr. Copperfield,' said
+Markham--meaning himself.
+
+'It's not a bad situation,' said I, 'and the rooms are really
+commodious.'
+
+'I hope you have both brought appetites with you?' said Steerforth.
+
+'Upon my honour,' returned Markham, 'town seems to sharpen a man's
+appetite. A man is hungry all day long. A man is perpetually eating.'
+
+Being a little embarrassed at first, and feeling much too young to
+preside, I made Steerforth take the head of the table when dinner was
+announced, and seated myself opposite to him. Everything was very good;
+we did not spare the wine; and he exerted himself so brilliantly to make
+the thing pass off well, that there was no pause in our festivity. I was
+not quite such good company during dinner as I could have wished to be,
+for my chair was opposite the door, and my attention was distracted by
+observing that the handy young man went out of the room very often, and
+that his shadow always presented itself, immediately afterwards, on the
+wall of the entry, with a bottle at its mouth. The 'young gal' likewise
+occasioned me some uneasiness: not so much by neglecting to wash the
+plates, as by breaking them. For being of an inquisitive disposition,
+and unable to confine herself (as her positive instructions were) to the
+pantry, she was constantly peering in at us, and constantly imagining
+herself detected; in which belief, she several times retired upon the
+plates (with which she had carefully paved the floor), and did a great
+deal of destruction.
+
+These, however, were small drawbacks, and easily forgotten when the
+cloth was cleared, and the dessert put on the table; at which period of
+the entertainment the handy young man was discovered to be speechless.
+Giving him private directions to seek the society of Mrs. Crupp, and
+to remove the 'young gal' to the basement also, I abandoned myself to
+enjoyment.
+
+I began, by being singularly cheerful and light-hearted; all sorts of
+half-forgotten things to talk about, came rushing into my mind, and made
+me hold forth in a most unwonted manner. I laughed heartily at my own
+jokes, and everybody else's; called Steerforth to order for not passing
+the wine; made several engagements to go to Oxford; announced that
+I meant to have a dinner-party exactly like that, once a week, until
+further notice; and madly took so much snuff out of Grainger's box, that
+I was obliged to go into the pantry, and have a private fit of sneezing
+ten minutes long.
+
+I went on, by passing the wine faster and faster yet, and continually
+starting up with a corkscrew to open more wine, long before any was
+needed. I proposed Steerforth's health. I said he was my dearest friend,
+the protector of my boyhood, and the companion of my prime. I said I was
+delighted to propose his health. I said I owed him more obligations than
+I could ever repay, and held him in a higher admiration than I could
+ever express. I finished by saying, 'I'll give you Steerforth! God bless
+him! Hurrah!' We gave him three times three, and another, and a good one
+to finish with. I broke my glass in going round the table to shake
+hands with him, and I said (in two words)
+
+'Steerforth--you'retheguidingstarofmyexistence.'
+
+I went on, by finding suddenly that somebody was in the middle of a
+song. Markham was the singer, and he sang 'When the heart of a man is
+depressed with care'. He said, when he had sung it, he would give us
+'Woman!' I took objection to that, and I couldn't allow it. I said
+it was not a respectful way of proposing the toast, and I would never
+permit that toast to be drunk in my house otherwise than as 'The
+Ladies!' I was very high with him, mainly I think because I saw
+Steerforth and Grainger laughing at me--or at him--or at both of us. He
+said a man was not to be dictated to. I said a man was. He said a man
+was not to be insulted, then. I said he was right there--never under
+my roof, where the Lares were sacred, and the laws of hospitality
+paramount. He said it was no derogation from a man's dignity to confess
+that I was a devilish good fellow. I instantly proposed his health.
+
+Somebody was smoking. We were all smoking. I was smoking, and trying
+to suppress a rising tendency to shudder. Steerforth had made a speech
+about me, in the course of which I had been affected almost to tears.
+I returned thanks, and hoped the present company would dine with me
+tomorrow, and the day after--each day at five o'clock, that we might
+enjoy the pleasures of conversation and society through a long evening.
+I felt called upon to propose an individual. I would give them my aunt.
+Miss Betsey Trotwood, the best of her sex!
+
+Somebody was leaning out of my bedroom window, refreshing his forehead
+against the cool stone of the parapet, and feeling the air upon his
+face. It was myself. I was addressing myself as 'Copperfield', and
+saying, 'Why did you try to smoke? You might have known you couldn't
+do it.' Now, somebody was unsteadily contemplating his features in the
+looking-glass. That was I too. I was very pale in the looking-glass;
+my eyes had a vacant appearance; and my hair--only my hair, nothing
+else--looked drunk.
+
+Somebody said to me, 'Let us go to the theatre, Copperfield!' There was
+no bedroom before me, but again the jingling table covered with glasses;
+the lamp; Grainger on my right hand, Markham on my left, and Steerforth
+opposite--all sitting in a mist, and a long way off. The theatre? To
+be sure. The very thing. Come along! But they must excuse me if I saw
+everybody out first, and turned the lamp off--in case of fire.
+
+Owing to some confusion in the dark, the door was gone. I was feeling
+for it in the window-curtains, when Steerforth, laughing, took me by
+the arm and led me out. We went downstairs, one behind another. Near
+the bottom, somebody fell, and rolled down. Somebody else said it was
+Copperfield. I was angry at that false report, until, finding myself on
+my back in the passage, I began to think there might be some foundation
+for it.
+
+A very foggy night, with great rings round the lamps in the streets!
+There was an indistinct talk of its being wet. I considered it frosty.
+Steerforth dusted me under a lamp-post, and put my hat into shape, which
+somebody produced from somewhere in a most extraordinary manner, for
+I hadn't had it on before. Steerforth then said, 'You are all right,
+Copperfield, are you not?' and I told him, 'Neverberrer.'
+
+A man, sitting in a pigeon-hole-place, looked out of the fog, and took
+money from somebody, inquiring if I was one of the gentlemen paid for,
+and appearing rather doubtful (as I remember in the glimpse I had of
+him) whether to take the money for me or not. Shortly afterwards, we
+were very high up in a very hot theatre, looking down into a large pit,
+that seemed to me to smoke; the people with whom it was crammed were so
+indistinct. There was a great stage, too, looking very clean and
+smooth after the streets; and there were people upon it, talking about
+something or other, but not at all intelligibly. There was an abundance
+of bright lights, and there was music, and there were ladies down in the
+boxes, and I don't know what more. The whole building looked to me as if
+it were learning to swim; it conducted itself in such an unaccountable
+manner, when I tried to steady it.
+
+On somebody's motion, we resolved to go downstairs to the dress-boxes,
+where the ladies were. A gentleman lounging, full dressed, on a sofa,
+with an opera-glass in his hand, passed before my view, and also my own
+figure at full length in a glass. Then I was being ushered into one of
+these boxes, and found myself saying something as I sat down, and people
+about me crying 'Silence!' to somebody, and ladies casting indignant
+glances at me, and--what! yes!--Agnes, sitting on the seat before me, in
+the same box, with a lady and gentleman beside her, whom I didn't
+know. I see her face now, better than I did then, I dare say, with its
+indelible look of regret and wonder turned upon me.
+
+'Agnes!' I said, thickly, 'Lorblessmer! Agnes!'
+
+'Hush! Pray!' she answered, I could not conceive why. 'You disturb the
+company. Look at the stage!'
+
+I tried, on her injunction, to fix it, and to hear something of what was
+going on there, but quite in vain. I looked at her again by and by, and
+saw her shrink into her corner, and put her gloved hand to her forehead.
+
+'Agnes!' I said. 'I'mafraidyou'renorwell.'
+
+'Yes, yes. Do not mind me, Trotwood,' she returned. 'Listen! Are you
+going away soon?'
+
+'Amigoarawaysoo?' I repeated.
+
+'Yes.'
+
+I had a stupid intention of replying that I was going to wait, to hand
+her downstairs. I suppose I expressed it, somehow; for after she had
+looked at me attentively for a little while, she appeared to understand,
+and replied in a low tone:
+
+'I know you will do as I ask you, if I tell you I am very earnest in
+it. Go away now, Trotwood, for my sake, and ask your friends to take you
+home.'
+
+She had so far improved me, for the time, that though I was angry with
+her, I felt ashamed, and with a short 'Goori!' (which I intended for
+'Good night!') got up and went away. They followed, and I stepped at
+once out of the box-door into my bedroom, where only Steerforth was with
+me, helping me to undress, and where I was by turns telling him that
+Agnes was my sister, and adjuring him to bring the corkscrew, that I
+might open another bottle of wine.
+
+How somebody, lying in my bed, lay saying and doing all this over again,
+at cross purposes, in a feverish dream all night--the bed a rocking sea
+that was never still! How, as that somebody slowly settled down into
+myself, did I begin to parch, and feel as if my outer covering of skin
+were a hard board; my tongue the bottom of an empty kettle, furred with
+long service, and burning up over a slow fire; the palms of my hands,
+hot plates of metal which no ice could cool!
+
+But the agony of mind, the remorse, and shame I felt when I became
+conscious next day! My horror of having committed a thousand offences I
+had forgotten, and which nothing could ever expiate--my recollection
+of that indelible look which Agnes had given me--the torturing
+impossibility of communicating with her, not knowing, Beast that I was,
+how she came to be in London, or where she stayed--my disgust of
+the very sight of the room where the revel had been held--my racking
+head--the smell of smoke, the sight of glasses, the impossibility of
+going out, or even getting up! Oh, what a day it was!
+
+Oh, what an evening, when I sat down by my fire to a basin of mutton
+broth, dimpled all over with fat, and thought I was going the way of my
+predecessor, and should succeed to his dismal story as well as to his
+chambers, and had half a mind to rush express to Dover and reveal
+all! What an evening, when Mrs. Crupp, coming in to take away the
+broth-basin, produced one kidney on a cheese-plate as the entire remains
+of yesterday's feast, and I was really inclined to fall upon her nankeen
+breast and say, in heartfelt penitence, 'Oh, Mrs. Crupp, Mrs. Crupp,
+never mind the broken meats! I am very miserable!'--only that I doubted,
+even at that pass, if Mrs. Crupp were quite the sort of woman to confide
+in!
+
+
+CHAPTER 25. GOOD AND BAD ANGELS
+
+
+I was going out at my door on the morning after that deplorable day of
+headache, sickness, and repentance, with an odd confusion in my mind
+relative to the date of my dinner-party, as if a body of Titans had
+taken an enormous lever and pushed the day before yesterday some months
+back, when I saw a ticket-porter coming upstairs, with a letter in his
+hand. He was taking his time about his errand, then; but when he saw me
+on the top of the staircase, looking at him over the banisters, he swung
+into a trot, and came up panting as if he had run himself into a state
+of exhaustion.
+
+'T. Copperfield, Esquire,' said the ticket-porter, touching his hat with
+his little cane.
+
+I could scarcely lay claim to the name: I was so disturbed by the
+conviction that the letter came from Agnes. However, I told him I was T.
+Copperfield, Esquire, and he believed it, and gave me the letter, which
+he said required an answer. I shut him out on the landing to wait for
+the answer, and went into my chambers again, in such a nervous state
+that I was fain to lay the letter down on my breakfast table, and
+familiarize myself with the outside of it a little, before I could
+resolve to break the seal.
+
+I found, when I did open it, that it was a very kind note, containing
+no reference to my condition at the theatre. All it said was, 'My dear
+Trotwood. I am staying at the house of papa's agent, Mr. Waterbrook, in
+Ely Place, Holborn. Will you come and see me today, at any time you like
+to appoint? Ever yours affectionately, AGNES.'
+
+It took me such a long time to write an answer at all to my
+satisfaction, that I don't know what the ticket-porter can have
+thought, unless he thought I was learning to write. I must have written
+half-a-dozen answers at least. I began one, 'How can I ever hope,
+my dear Agnes, to efface from your remembrance the disgusting
+impression'--there I didn't like it, and then I tore it up. I began
+another, 'Shakespeare has observed, my dear Agnes, how strange it is
+that a man should put an enemy into his mouth'--that reminded me of
+Markham, and it got no farther. I even tried poetry. I began one note,
+in a six-syllable line, 'Oh, do not remember'--but that associated
+itself with the fifth of November, and became an absurdity. After many
+attempts, I wrote, 'My dear Agnes. Your letter is like you, and what
+could I say of it that would be higher praise than that? I will come at
+four o'clock. Affectionately and sorrowfully, T.C.' With this missive
+(which I was in twenty minds at once about recalling, as soon as it was
+out of my hands), the ticket-porter at last departed.
+
+If the day were half as tremendous to any other professional gentleman
+in Doctors' Commons as it was to me, I sincerely believe he made some
+expiation for his share in that rotten old ecclesiastical cheese.
+Although I left the office at half past three, and was prowling about
+the place of appointment within a few minutes afterwards, the appointed
+time was exceeded by a full quarter of an hour, according to the
+clock of St. Andrew's, Holborn, before I could muster up sufficient
+desperation to pull the private bell-handle let into the left-hand
+door-post of Mr. Waterbrook's house.
+
+The professional business of Mr. Waterbrook's establishment was done on
+the ground-floor, and the genteel business (of which there was a good
+deal) in the upper part of the building. I was shown into a pretty but
+rather close drawing-room, and there sat Agnes, netting a purse.
+
+She looked so quiet and good, and reminded me so strongly of my airy
+fresh school days at Canterbury, and the sodden, smoky, stupid wretch
+I had been the other night, that, nobody being by, I yielded to my
+self-reproach and shame, and--in short, made a fool of myself. I cannot
+deny that I shed tears. To this hour I am undecided whether it was upon
+the whole the wisest thing I could have done, or the most ridiculous.
+
+'If it had been anyone but you, Agnes,' said I, turning away my head, 'I
+should not have minded it half so much. But that it should have been you
+who saw me! I almost wish I had been dead, first.'
+
+She put her hand--its touch was like no other hand--upon my arm for a
+moment; and I felt so befriended and comforted, that I could not help
+moving it to my lips, and gratefully kissing it.
+
+'Sit down,' said Agnes, cheerfully. 'Don't be unhappy, Trotwood. If you
+cannot confidently trust me, whom will you trust?'
+
+'Ah, Agnes!' I returned. 'You are my good Angel!'
+
+She smiled rather sadly, I thought, and shook her head.
+
+'Yes, Agnes, my good Angel! Always my good Angel!'
+
+'If I were, indeed, Trotwood,' she returned, 'there is one thing that I
+should set my heart on very much.'
+
+I looked at her inquiringly; but already with a foreknowledge of her
+meaning.
+
+'On warning you,' said Agnes, with a steady glance, 'against your bad
+Angel.'
+
+'My dear Agnes,' I began, 'if you mean Steerforth--'
+
+'I do, Trotwood,' she returned. 'Then, Agnes, you wrong him very much.
+He my bad Angel, or anyone's! He, anything but a guide, a support, and
+a friend to me! My dear Agnes! Now, is it not unjust, and unlike you, to
+judge him from what you saw of me the other night?'
+
+'I do not judge him from what I saw of you the other night,' she quietly
+replied.
+
+'From what, then?'
+
+'From many things--trifles in themselves, but they do not seem to me to
+be so, when they are put together. I judge him, partly from your account
+of him, Trotwood, and your character, and the influence he has over
+you.'
+
+There was always something in her modest voice that seemed to touch a
+chord within me, answering to that sound alone. It was always earnest;
+but when it was very earnest, as it was now, there was a thrill in it
+that quite subdued me. I sat looking at her as she cast her eyes down on
+her work; I sat seeming still to listen to her; and Steerforth, in spite
+of all my attachment to him, darkened in that tone.
+
+'It is very bold in me,' said Agnes, looking up again, 'who have lived
+in such seclusion, and can know so little of the world, to give you my
+advice so confidently, or even to have this strong opinion. But I know
+in what it is engendered, Trotwood,--in how true a remembrance of our
+having grown up together, and in how true an interest in all relating
+to you. It is that which makes me bold. I am certain that what I say is
+right. I am quite sure it is. I feel as if it were someone else speaking
+to you, and not I, when I caution you that you have made a dangerous
+friend.'
+
+Again I looked at her, again I listened to her after she was silent, and
+again his image, though it was still fixed in my heart, darkened.
+
+'I am not so unreasonable as to expect,' said Agnes, resuming her usual
+tone, after a little while, 'that you will, or that you can, at once,
+change any sentiment that has become a conviction to you; least of all
+a sentiment that is rooted in your trusting disposition. You ought not
+hastily to do that. I only ask you, Trotwood, if you ever think of me--I
+mean,' with a quiet smile, for I was going to interrupt her, and she
+knew why, 'as often as you think of me--to think of what I have said. Do
+you forgive me for all this?'
+
+'I will forgive you, Agnes,' I replied, 'when you come to do Steerforth
+justice, and to like him as well as I do.'
+
+'Not until then?' said Agnes.
+
+I saw a passing shadow on her face when I made this mention of him, but
+she returned my smile, and we were again as unreserved in our mutual
+confidence as of old.
+
+'And when, Agnes,' said I, 'will you forgive me the other night?'
+
+'When I recall it,' said Agnes.
+
+She would have dismissed the subject so, but I was too full of it to
+allow that, and insisted on telling her how it happened that I had
+disgraced myself, and what chain of accidental circumstances had had the
+theatre for its final link. It was a great relief to me to do this, and
+to enlarge on the obligation that I owed to Steerforth for his care of
+me when I was unable to take care of myself.
+
+'You must not forget,' said Agnes, calmly changing the conversation as
+soon as I had concluded, 'that you are always to tell me, not only when
+you fall into trouble, but when you fall in love. Who has succeeded to
+Miss Larkins, Trotwood?'
+
+'No one, Agnes.'
+
+'Someone, Trotwood,' said Agnes, laughing, and holding up her finger.
+
+'No, Agnes, upon my word! There is a lady, certainly, at Mrs.
+Steerforth's house, who is very clever, and whom I like to talk to--Miss
+Dartle--but I don't adore her.'
+
+Agnes laughed again at her own penetration, and told me that if I were
+faithful to her in my confidence she thought she should keep a little
+register of my violent attachments, with the date, duration, and
+termination of each, like the table of the reigns of the kings and
+queens, in the History of England. Then she asked me if I had seen
+Uriah.
+
+'Uriah Heep?' said I. 'No. Is he in London?'
+
+'He comes to the office downstairs, every day,' returned Agnes. 'He
+was in London a week before me. I am afraid on disagreeable business,
+Trotwood.'
+
+'On some business that makes you uneasy, Agnes, I see,' said I. 'What
+can that be?'
+
+Agnes laid aside her work, and replied, folding her hands upon one
+another, and looking pensively at me out of those beautiful soft eyes of
+hers:
+
+'I believe he is going to enter into partnership with papa.'
+
+'What? Uriah? That mean, fawning fellow, worm himself into such
+promotion!' I cried, indignantly. 'Have you made no remonstrance about
+it, Agnes? Consider what a connexion it is likely to be. You must speak
+out. You must not allow your father to take such a mad step. You must
+prevent it, Agnes, while there's time.'
+
+Still looking at me, Agnes shook her head while I was speaking, with a
+faint smile at my warmth: and then replied:
+
+'You remember our last conversation about papa? It was not long after
+that--not more than two or three days--when he gave me the first
+intimation of what I tell you. It was sad to see him struggling between
+his desire to represent it to me as a matter of choice on his part,
+and his inability to conceal that it was forced upon him. I felt very
+sorry.'
+
+'Forced upon him, Agnes! Who forces it upon him?'
+
+'Uriah,' she replied, after a moment's hesitation, 'has made himself
+indispensable to papa. He is subtle and watchful. He has mastered papa's
+weaknesses, fostered them, and taken advantage of them, until--to say
+all that I mean in a word, Trotwood,--until papa is afraid of him.'
+
+There was more that she might have said; more that she knew, or that she
+suspected; I clearly saw. I could not give her pain by asking what it
+was, for I knew that she withheld it from me, to spare her father. It
+had long been going on to this, I was sensible: yes, I could not but
+feel, on the least reflection, that it had been going on to this for a
+long time. I remained silent.
+
+'His ascendancy over papa,' said Agnes, 'is very great. He professes
+humility and gratitude--with truth, perhaps: I hope so--but his position
+is really one of power, and I fear he makes a hard use of his power.'
+
+I said he was a hound, which, at the moment, was a great satisfaction to
+me.
+
+'At the time I speak of, as the time when papa spoke to me,' pursued
+Agnes, 'he had told papa that he was going away; that he was very sorry,
+and unwilling to leave, but that he had better prospects. Papa was very
+much depressed then, and more bowed down by care than ever you or I have
+seen him; but he seemed relieved by this expedient of the partnership,
+though at the same time he seemed hurt by it and ashamed of it.'
+
+'And how did you receive it, Agnes?'
+
+'I did, Trotwood,' she replied, 'what I hope was right. Feeling sure
+that it was necessary for papa's peace that the sacrifice should be
+made, I entreated him to make it. I said it would lighten the load
+of his life--I hope it will!--and that it would give me increased
+opportunities of being his companion. Oh, Trotwood!' cried Agnes,
+putting her hands before her face, as her tears started on it, 'I almost
+feel as if I had been papa's enemy, instead of his loving child. For
+I know how he has altered, in his devotion to me. I know how he has
+narrowed the circle of his sympathies and duties, in the concentration
+of his whole mind upon me. I know what a multitude of things he has shut
+out for my sake, and how his anxious thoughts of me have shadowed his
+life, and weakened his strength and energy, by turning them always upon
+one idea. If I could ever set this right! If I could ever work out his
+restoration, as I have so innocently been the cause of his decline!'
+
+I had never before seen Agnes cry. I had seen tears in her eyes when I
+had brought new honours home from school, and I had seen them there when
+we last spoke about her father, and I had seen her turn her gentle head
+aside when we took leave of one another; but I had never seen her grieve
+like this. It made me so sorry that I could only say, in a foolish,
+helpless manner, 'Pray, Agnes, don't! Don't, my dear sister!'
+
+But Agnes was too superior to me in character and purpose, as I know
+well now, whatever I might know or not know then, to be long in need of
+my entreaties. The beautiful, calm manner, which makes her so different
+in my remembrance from everybody else, came back again, as if a cloud
+had passed from a serene sky.
+
+'We are not likely to remain alone much longer,' said Agnes, 'and while
+I have an opportunity, let me earnestly entreat you, Trotwood, to be
+friendly to Uriah. Don't repel him. Don't resent (as I think you have a
+general disposition to do) what may be uncongenial to you in him. He may
+not deserve it, for we know no certain ill of him. In any case, think
+first of papa and me!'
+
+Agnes had no time to say more, for the room door opened, and Mrs.
+Waterbrook, who was a large lady--or who wore a large dress: I don't
+exactly know which, for I don't know which was dress and which was
+lady--came sailing in. I had a dim recollection of having seen her
+at the theatre, as if I had seen her in a pale magic lantern; but she
+appeared to remember me perfectly, and still to suspect me of being in a
+state of intoxication.
+
+Finding by degrees, however, that I was sober, and (I hope) that I was
+a modest young gentleman, Mrs. Waterbrook softened towards me
+considerably, and inquired, firstly, if I went much into the parks,
+and secondly, if I went much into society. On my replying to both these
+questions in the negative, it occurred to me that I fell again in her
+good opinion; but she concealed the fact gracefully, and invited me to
+dinner next day. I accepted the invitation, and took my leave, making a
+call on Uriah in the office as I went out, and leaving a card for him in
+his absence.
+
+When I went to dinner next day, and on the street door being opened,
+plunged into a vapour-bath of haunch of mutton, I divined that I was
+not the only guest, for I immediately identified the ticket-porter in
+disguise, assisting the family servant, and waiting at the foot of the
+stairs to carry up my name. He looked, to the best of his ability, when
+he asked me for it confidentially, as if he had never seen me before;
+but well did I know him, and well did he know me. Conscience made
+cowards of us both.
+
+I found Mr. Waterbrook to be a middle-aged gentleman, with a short
+throat, and a good deal of shirt-collar, who only wanted a black nose to
+be the portrait of a pug-dog. He told me he was happy to have the
+honour of making my acquaintance; and when I had paid my homage to Mrs.
+Waterbrook, presented me, with much ceremony, to a very awful lady in
+a black velvet dress, and a great black velvet hat, whom I remember as
+looking like a near relation of Hamlet's--say his aunt.
+
+Mrs. Henry Spiker was this lady's name; and her husband was there
+too: so cold a man, that his head, instead of being grey, seemed to
+be sprinkled with hoar-frost. Immense deference was shown to the Henry
+Spikers, male and female; which Agnes told me was on account of Mr.
+Henry Spiker being solicitor to something Or to Somebody, I forget what
+or which, remotely connected with the Treasury.
+
+I found Uriah Heep among the company, in a suit of black, and in deep
+humility. He told me, when I shook hands with him, that he was proud
+to be noticed by me, and that he really felt obliged to me for my
+condescension. I could have wished he had been less obliged to me, for
+he hovered about me in his gratitude all the rest of the evening; and
+whenever I said a word to Agnes, was sure, with his shadowless eyes and
+cadaverous face, to be looking gauntly down upon us from behind.
+
+There were other guests--all iced for the occasion, as it struck me,
+like the wine. But there was one who attracted my attention before he
+came in, on account of my hearing him announced as Mr. Traddles! My mind
+flew back to Salem House; and could it be Tommy, I thought, who used to
+draw the skeletons!
+
+I looked for Mr. Traddles with unusual interest. He was a sober,
+steady-looking young man of retiring manners, with a comic head of hair,
+and eyes that were rather wide open; and he got into an obscure corner
+so soon, that I had some difficulty in making him out. At length I had
+a good view of him, and either my vision deceived me, or it was the old
+unfortunate Tommy.
+
+I made my way to Mr. Waterbrook, and said, that I believed I had the
+pleasure of seeing an old schoolfellow there.
+
+'Indeed!' said Mr. Waterbrook, surprised. 'You are too young to have
+been at school with Mr. Henry Spiker?'
+
+'Oh, I don't mean him!' I returned. 'I mean the gentleman named
+Traddles.'
+
+'Oh! Aye, aye! Indeed!' said my host, with much diminished interest.
+'Possibly.'
+
+'If it's really the same person,' said I, glancing towards him, 'it
+was at a place called Salem House where we were together, and he was an
+excellent fellow.'
+
+'Oh yes. Traddles is a good fellow,' returned my host nodding his head
+with an air of toleration. 'Traddles is quite a good fellow.'
+
+'It's a curious coincidence,' said I.
+
+'It is really,' returned my host, 'quite a coincidence, that Traddles
+should be here at all: as Traddles was only invited this morning, when
+the place at table, intended to be occupied by Mrs. Henry Spiker's
+brother, became vacant, in consequence of his indisposition. A very
+gentlemanly man, Mrs. Henry Spiker's brother, Mr. Copperfield.'
+
+I murmured an assent, which was full of feeling, considering that I
+knew nothing at all about him; and I inquired what Mr. Traddles was by
+profession.
+
+'Traddles,' returned Mr. Waterbrook, 'is a young man reading for the
+bar. Yes. He is quite a good fellow--nobody's enemy but his own.'
+
+'Is he his own enemy?' said I, sorry to hear this.
+
+'Well,' returned Mr. Waterbrook, pursing up his mouth, and playing with
+his watch-chain, in a comfortable, prosperous sort of way. 'I should say
+he was one of those men who stand in their own light. Yes, I should say
+he would never, for example, be worth five hundred pound. Traddles was
+recommended to me by a professional friend. Oh yes. Yes. He has a kind
+of talent for drawing briefs, and stating a case in writing, plainly. I
+am able to throw something in Traddles's way, in the course of the year;
+something--for him--considerable. Oh yes. Yes.'
+
+I was much impressed by the extremely comfortable and satisfied manner
+in which Mr. Waterbrook delivered himself of this little word 'Yes',
+every now and then. There was wonderful expression in it. It completely
+conveyed the idea of a man who had been born, not to say with a silver
+spoon, but with a scaling-ladder, and had gone on mounting all the
+heights of life one after another, until now he looked, from the top of
+the fortifications, with the eye of a philosopher and a patron, on the
+people down in the trenches.
+
+My reflections on this theme were still in progress when dinner was
+announced. Mr. Waterbrook went down with Hamlet's aunt. Mr. Henry Spiker
+took Mrs. Waterbrook. Agnes, whom I should have liked to take myself,
+was given to a simpering fellow with weak legs. Uriah, Traddles, and I,
+as the junior part of the company, went down last, how we could. I was
+not so vexed at losing Agnes as I might have been, since it gave me
+an opportunity of making myself known to Traddles on the stairs, who
+greeted me with great fervour; while Uriah writhed with such obtrusive
+satisfaction and self-abasement, that I could gladly have pitched
+him over the banisters. Traddles and I were separated at table, being
+billeted in two remote corners: he in the glare of a red velvet lady;
+I, in the gloom of Hamlet's aunt. The dinner was very long, and the
+conversation was about the Aristocracy--and Blood. Mrs. Waterbrook
+repeatedly told us, that if she had a weakness, it was Blood.
+
+It occurred to me several times that we should have got on better, if we
+had not been quite so genteel. We were so exceedingly genteel, that our
+scope was very limited. A Mr. and Mrs. Gulpidge were of the party, who
+had something to do at second-hand (at least, Mr. Gulpidge had) with
+the law business of the Bank; and what with the Bank, and what with
+the Treasury, we were as exclusive as the Court Circular. To mend the
+matter, Hamlet's aunt had the family failing of indulging in soliloquy,
+and held forth in a desultory manner, by herself, on every topic that
+was introduced. These were few enough, to be sure; but as we always fell
+back upon Blood, she had as wide a field for abstract speculation as her
+nephew himself.
+
+We might have been a party of Ogres, the conversation assumed such a
+sanguine complexion.
+
+'I confess I am of Mrs. Waterbrook's opinion,' said Mr. Waterbrook, with
+his wine-glass at his eye. 'Other things are all very well in their way,
+but give me Blood!'
+
+'Oh! There is nothing,' observed Hamlet's aunt, 'so satisfactory to one!
+There is nothing that is so much one's beau-ideal of--of all that sort
+of thing, speaking generally. There are some low minds (not many, I am
+happy to believe, but there are some) that would prefer to do what I
+should call bow down before idols. Positively Idols! Before service,
+intellect, and so on. But these are intangible points. Blood is not so.
+We see Blood in a nose, and we know it. We meet with it in a chin, and
+we say, "There it is! That's Blood!" It is an actual matter of fact. We
+point it out. It admits of no doubt.'
+
+The simpering fellow with the weak legs, who had taken Agnes down,
+stated the question more decisively yet, I thought.
+
+'Oh, you know, deuce take it,' said this gentleman, looking round the
+board with an imbecile smile, 'we can't forego Blood, you know. We must
+have Blood, you know. Some young fellows, you know, may be a little
+behind their station, perhaps, in point of education and behaviour, and
+may go a little wrong, you know, and get themselves and other people
+into a variety of fixes--and all that--but deuce take it, it's
+delightful to reflect that they've got Blood in 'em! Myself, I'd rather
+at any time be knocked down by a man who had got Blood in him, than I'd
+be picked up by a man who hadn't!'
+
+This sentiment, as compressing the general question into a nutshell,
+gave the utmost satisfaction, and brought the gentleman into great
+notice until the ladies retired. After that, I observed that Mr.
+Gulpidge and Mr. Henry Spiker, who had hitherto been very distant,
+entered into a defensive alliance against us, the common enemy, and
+exchanged a mysterious dialogue across the table for our defeat and
+overthrow.
+
+'That affair of the first bond for four thousand five hundred pounds has
+not taken the course that was expected, Spiker,' said Mr. Gulpidge.
+
+'Do you mean the D. of A.'s?' said Mr. Spiker.
+
+'The C. of B.'s!' said Mr. Gulpidge.
+
+Mr. Spiker raised his eyebrows, and looked much concerned.
+
+'When the question was referred to Lord--I needn't name him,' said Mr.
+Gulpidge, checking himself--
+
+'I understand,' said Mr. Spiker, 'N.'
+
+Mr. Gulpidge darkly nodded--'was referred to him, his answer was,
+"Money, or no release."'
+
+'Lord bless my soul!' cried Mr. Spiker.
+
+"'Money, or no release,"' repeated Mr. Gulpidge, firmly. 'The next in
+reversion--you understand me?'
+
+'K.,' said Mr. Spiker, with an ominous look.
+
+'--K. then positively refused to sign. He was attended at Newmarket for
+that purpose, and he point-blank refused to do it.'
+
+Mr. Spiker was so interested, that he became quite stony.
+
+'So the matter rests at this hour,' said Mr. Gulpidge, throwing himself
+back in his chair. 'Our friend Waterbrook will excuse me if I forbear to
+explain myself generally, on account of the magnitude of the interests
+involved.'
+
+Mr. Waterbrook was only too happy, as it appeared to me, to have such
+interests, and such names, even hinted at, across his table. He assumed
+an expression of gloomy intelligence (though I am persuaded he knew
+no more about the discussion than I did), and highly approved of the
+discretion that had been observed. Mr. Spiker, after the receipt of such
+a confidence, naturally desired to favour his friend with a confidence
+of his own; therefore the foregoing dialogue was succeeded by another,
+in which it was Mr. Gulpidge's turn to be surprised, and that by another
+in which the surprise came round to Mr. Spiker's turn again, and so on,
+turn and turn about. All this time we, the outsiders, remained oppressed
+by the tremendous interests involved in the conversation; and our
+host regarded us with pride, as the victims of a salutary awe and
+astonishment. I was very glad indeed to get upstairs to Agnes, and to
+talk with her in a corner, and to introduce Traddles to her, who was
+shy, but agreeable, and the same good-natured creature still. As he
+was obliged to leave early, on account of going away next morning for
+a month, I had not nearly so much conversation with him as I could have
+wished; but we exchanged addresses, and promised ourselves the pleasure
+of another meeting when he should come back to town. He was greatly
+interested to hear that I knew Steerforth, and spoke of him with such
+warmth that I made him tell Agnes what he thought of him. But Agnes only
+looked at me the while, and very slightly shook her head when only I
+observed her.
+
+As she was not among people with whom I believed she could be very much
+at home, I was almost glad to hear that she was going away within a few
+days, though I was sorry at the prospect of parting from her again
+so soon. This caused me to remain until all the company were gone.
+Conversing with her, and hearing her sing, was such a delightful
+reminder to me of my happy life in the grave old house she had made so
+beautiful, that I could have remained there half the night; but, having
+no excuse for staying any longer, when the lights of Mr. Waterbrook's
+society were all snuffed out, I took my leave very much against my
+inclination. I felt then, more than ever, that she was my better Angel;
+and if I thought of her sweet face and placid smile, as though they had
+shone on me from some removed being, like an Angel, I hope I thought no
+harm.
+
+I have said that the company were all gone; but I ought to have excepted
+Uriah, whom I don't include in that denomination, and who had never
+ceased to hover near us. He was close behind me when I went downstairs.
+He was close beside me, when I walked away from the house, slowly
+fitting his long skeleton fingers into the still longer fingers of a
+great Guy Fawkes pair of gloves.
+
+It was in no disposition for Uriah's company, but in remembrance of the
+entreaty Agnes had made to me, that I asked him if he would come home to
+my rooms, and have some coffee.
+
+'Oh, really, Master Copperfield,' he rejoined--'I beg your pardon,
+Mister Copperfield, but the other comes so natural, I don't like that
+you should put a constraint upon yourself to ask a numble person like me
+to your ouse.'
+
+'There is no constraint in the case,' said I. 'Will you come?'
+
+'I should like to, very much,' replied Uriah, with a writhe.
+
+'Well, then, come along!' said I.
+
+I could not help being rather short with him, but he appeared not to
+mind it. We went the nearest way, without conversing much upon the road;
+and he was so humble in respect of those scarecrow gloves, that he
+was still putting them on, and seemed to have made no advance in that
+labour, when we got to my place.
+
+I led him up the dark stairs, to prevent his knocking his head against
+anything, and really his damp cold hand felt so like a frog in mine,
+that I was tempted to drop it and run away. Agnes and hospitality
+prevailed, however, and I conducted him to my fireside. When I lighted
+my candles, he fell into meek transports with the room that was revealed
+to him; and when I heated the coffee in an unassuming block-tin vessel
+in which Mrs. Crupp delighted to prepare it (chiefly, I believe, because
+it was not intended for the purpose, being a shaving-pot, and because
+there was a patent invention of great price mouldering away in the
+pantry), he professed so much emotion, that I could joyfully have
+scalded him.
+
+'Oh, really, Master Copperfield,--I mean Mister Copperfield,' said
+Uriah, 'to see you waiting upon me is what I never could have expected!
+But, one way and another, so many things happen to me which I never
+could have expected, I am sure, in my umble station, that it seems
+to rain blessings on my ed. You have heard something, I des-say, of a
+change in my expectations, Master Copperfield,--I should say, Mister
+Copperfield?'
+
+As he sat on my sofa, with his long knees drawn up under his coffee-cup,
+his hat and gloves upon the ground close to him, his spoon going softly
+round and round, his shadowless red eyes, which looked as if they had
+scorched their lashes off, turned towards me without looking at me, the
+disagreeable dints I have formerly described in his nostrils coming and
+going with his breath, and a snaky undulation pervading his frame from
+his chin to his boots, I decided in my own mind that I disliked him
+intensely. It made me very uncomfortable to have him for a guest, for I
+was young then, and unused to disguise what I so strongly felt.
+
+'You have heard something, I des-say, of a change in my expectations,
+Master Copperfield,--I should say, Mister Copperfield?' observed Uriah.
+
+'Yes,' said I, 'something.'
+
+'Ah! I thought Miss Agnes would know of it!' he quietly returned. 'I'm
+glad to find Miss Agnes knows of it. Oh, thank you, Master--Mister
+Copperfield!'
+
+I could have thrown my bootjack at him (it lay ready on the rug), for
+having entrapped me into the disclosure of anything concerning Agnes,
+however immaterial. But I only drank my coffee.
+
+'What a prophet you have shown yourself, Mister Copperfield!' pursued
+Uriah. 'Dear me, what a prophet you have proved yourself to be! Don't
+you remember saying to me once, that perhaps I should be a partner in
+Mr. Wickfield's business, and perhaps it might be Wickfield and
+Heep? You may not recollect it; but when a person is umble, Master
+Copperfield, a person treasures such things up!'
+
+'I recollect talking about it,' said I, 'though I certainly did not
+think it very likely then.' 'Oh! who would have thought it likely,
+Mister Copperfield!' returned Uriah, enthusiastically. 'I am sure I
+didn't myself. I recollect saying with my own lips that I was much too
+umble. So I considered myself really and truly.'
+
+He sat, with that carved grin on his face, looking at the fire, as I
+looked at him.
+
+'But the umblest persons, Master Copperfield,' he presently resumed,
+'may be the instruments of good. I am glad to think I have been the
+instrument of good to Mr. Wickfield, and that I may be more so. Oh what
+a worthy man he is, Mister Copperfield, but how imprudent he has been!'
+
+'I am sorry to hear it,' said I. I could not help adding, rather
+pointedly, 'on all accounts.'
+
+'Decidedly so, Mister Copperfield,' replied Uriah. 'On all accounts.
+Miss Agnes's above all! You don't remember your own eloquent
+expressions, Master Copperfield; but I remember how you said one day
+that everybody must admire her, and how I thanked you for it! You have
+forgot that, I have no doubt, Master Copperfield?'
+
+'No,' said I, drily.
+
+'Oh how glad I am you have not!' exclaimed Uriah. 'To think that you
+should be the first to kindle the sparks of ambition in my umble breast,
+and that you've not forgot it! Oh!--Would you excuse me asking for a cup
+more coffee?'
+
+Something in the emphasis he laid upon the kindling of those sparks,
+and something in the glance he directed at me as he said it, had made me
+start as if I had seen him illuminated by a blaze of light. Recalled by
+his request, preferred in quite another tone of voice, I did the honours
+of the shaving-pot; but I did them with an unsteadiness of hand, a
+sudden sense of being no match for him, and a perplexed suspicious
+anxiety as to what he might be going to say next, which I felt could not
+escape his observation.
+
+He said nothing at all. He stirred his coffee round and round, he sipped
+it, he felt his chin softly with his grisly hand, he looked at the fire,
+he looked about the room, he gasped rather than smiled at me, he writhed
+and undulated about, in his deferential servility, he stirred and sipped
+again, but he left the renewal of the conversation to me.
+
+'So, Mr. Wickfield,' said I, at last, 'who is worth five hundred of
+you--or me'; for my life, I think, I could not have helped dividing that
+part of the sentence with an awkward jerk; 'has been imprudent, has he,
+Mr. Heep?'
+
+'Oh, very imprudent indeed, Master Copperfield,' returned Uriah, sighing
+modestly. 'Oh, very much so! But I wish you'd call me Uriah, if you
+please. It's like old times.'
+
+'Well! Uriah,' said I, bolting it out with some difficulty.
+
+'Thank you,' he returned, with fervour. 'Thank you, Master Copperfield!
+It's like the blowing of old breezes or the ringing of old bellses to
+hear YOU say Uriah. I beg your pardon. Was I making any observation?'
+
+'About Mr. Wickfield,' I suggested.
+
+'Oh! Yes, truly,' said Uriah. 'Ah! Great imprudence, Master Copperfield.
+It's a topic that I wouldn't touch upon, to any soul but you. Even to
+you I can only touch upon it, and no more. If anyone else had been in
+my place during the last few years, by this time he would have had Mr.
+Wickfield (oh, what a worthy man he is, Master Copperfield, too!) under
+his thumb. Un--der--his thumb,' said Uriah, very slowly, as he stretched
+out his cruel-looking hand above my table, and pressed his own thumb
+upon it, until it shook, and shook the room.
+
+If I had been obliged to look at him with him splay foot on Mr.
+Wickfield's head, I think I could scarcely have hated him more.
+
+'Oh, dear, yes, Master Copperfield,' he proceeded, in a soft voice,
+most remarkably contrasting with the action of his thumb, which did not
+diminish its hard pressure in the least degree, 'there's no doubt of
+it. There would have been loss, disgrace, I don't know what at all. Mr.
+Wickfield knows it. I am the umble instrument of umbly serving him,
+and he puts me on an eminence I hardly could have hoped to reach. How
+thankful should I be!' With his face turned towards me, as he finished,
+but without looking at me, he took his crooked thumb off the spot where
+he had planted it, and slowly and thoughtfully scraped his lank jaw with
+it, as if he were shaving himself.
+
+I recollect well how indignantly my heart beat, as I saw his crafty
+face, with the appropriately red light of the fire upon it, preparing
+for something else.
+
+'Master Copperfield,' he began--'but am I keeping you up?'
+
+'You are not keeping me up. I generally go to bed late.'
+
+'Thank you, Master Copperfield! I have risen from my umble station since
+first you used to address me, it is true; but I am umble still. I hope I
+never shall be otherwise than umble. You will not think the worse of
+my umbleness, if I make a little confidence to you, Master Copperfield?
+Will you?'
+
+'Oh no,' said I, with an effort.
+
+'Thank you!' He took out his pocket-handkerchief, and began wiping the
+palms of his hands. 'Miss Agnes, Master Copperfield--' 'Well, Uriah?'
+
+'Oh, how pleasant to be called Uriah, spontaneously!' he cried; and gave
+himself a jerk, like a convulsive fish. 'You thought her looking very
+beautiful tonight, Master Copperfield?'
+
+'I thought her looking as she always does: superior, in all respects, to
+everyone around her,' I returned.
+
+'Oh, thank you! It's so true!' he cried. 'Oh, thank you very much for
+that!'
+
+'Not at all,' I said, loftily. 'There is no reason why you should thank
+me.'
+
+'Why that, Master Copperfield,' said Uriah, 'is, in fact, the confidence
+that I am going to take the liberty of reposing. Umble as I am,' he
+wiped his hands harder, and looked at them and at the fire by turns,
+'umble as my mother is, and lowly as our poor but honest roof has ever
+been, the image of Miss Agnes (I don't mind trusting you with my secret,
+Master Copperfield, for I have always overflowed towards you since the
+first moment I had the pleasure of beholding you in a pony-shay) has
+been in my breast for years. Oh, Master Copperfield, with what a pure
+affection do I love the ground my Agnes walks on!'
+
+I believe I had a delirious idea of seizing the red-hot poker out of
+the fire, and running him through with it. It went from me with a shock,
+like a ball fired from a rifle: but the image of Agnes, outraged by so
+much as a thought of this red-headed animal's, remained in my mind when
+I looked at him, sitting all awry as if his mean soul griped his body,
+and made me giddy. He seemed to swell and grow before my eyes; the room
+seemed full of the echoes of his voice; and the strange feeling (to
+which, perhaps, no one is quite a stranger) that all this had occurred
+before, at some indefinite time, and that I knew what he was going to
+say next, took possession of me.
+
+A timely observation of the sense of power that there was in his face,
+did more to bring back to my remembrance the entreaty of Agnes, in
+its full force, than any effort I could have made. I asked him, with
+a better appearance of composure than I could have thought possible a
+minute before, whether he had made his feelings known to Agnes.
+
+'Oh no, Master Copperfield!' he returned; 'oh dear, no! Not to anyone
+but you. You see I am only just emerging from my lowly station. I rest a
+good deal of hope on her observing how useful I am to her father (for
+I trust to be very useful to him indeed, Master Copperfield), and how I
+smooth the way for him, and keep him straight. She's so much attached
+to her father, Master Copperfield (oh, what a lovely thing it is in a
+daughter!), that I think she may come, on his account, to be kind to
+me.'
+
+I fathomed the depth of the rascal's whole scheme, and understood why he
+laid it bare.
+
+'If you'll have the goodness to keep my secret, Master Copperfield,' he
+pursued, 'and not, in general, to go against me, I shall take it as a
+particular favour. You wouldn't wish to make unpleasantness. I know
+what a friendly heart you've got; but having only known me on my umble
+footing (on my umblest I should say, for I am very umble still), you
+might, unbeknown, go against me rather, with my Agnes. I call her mine,
+you see, Master Copperfield. There's a song that says, "I'd crowns
+resign, to call her mine!" I hope to do it, one of these days.'
+
+Dear Agnes! So much too loving and too good for anyone that I could
+think of, was it possible that she was reserved to be the wife of such a
+wretch as this!
+
+'There's no hurry at present, you know, Master Copperfield,' Uriah
+proceeded, in his slimy way, as I sat gazing at him, with this thought
+in my mind. 'My Agnes is very young still; and mother and me will have
+to work our way upwards, and make a good many new arrangements, before
+it would be quite convenient. So I shall have time gradually to make her
+familiar with my hopes, as opportunities offer. Oh, I'm so much obliged
+to you for this confidence! Oh, it's such a relief, you can't think, to
+know that you understand our situation, and are certain (as you wouldn't
+wish to make unpleasantness in the family) not to go against me!'
+
+He took the hand which I dared not withhold, and having given it a damp
+squeeze, referred to his pale-faced watch.
+
+'Dear me!' he said, 'it's past one. The moments slip away so, in the
+confidence of old times, Master Copperfield, that it's almost half past
+one!'
+
+I answered that I had thought it was later. Not that I had really
+thought so, but because my conversational powers were effectually
+scattered.
+
+'Dear me!' he said, considering. 'The ouse that I am stopping at--a sort
+of a private hotel and boarding ouse, Master Copperfield, near the New
+River ed--will have gone to bed these two hours.'
+
+'I am sorry,' I returned, 'that there is only one bed here, and that
+I--'
+
+'Oh, don't think of mentioning beds, Master Copperfield!' he rejoined
+ecstatically, drawing up one leg. 'But would you have any objections to
+my laying down before the fire?'
+
+'If it comes to that,' I said, 'pray take my bed, and I'll lie down
+before the fire.'
+
+His repudiation of this offer was almost shrill enough, in the excess of
+its surprise and humility, to have penetrated to the ears of Mrs. Crupp,
+then sleeping, I suppose, in a distant chamber, situated at about the
+level of low-water mark, soothed in her slumbers by the ticking of an
+incorrigible clock, to which she always referred me when we had any
+little difference on the score of punctuality, and which was never less
+than three-quarters of an hour too slow, and had always been put right
+in the morning by the best authorities. As no arguments I could urge,
+in my bewildered condition, had the least effect upon his modesty
+in inducing him to accept my bedroom, I was obliged to make the best
+arrangements I could, for his repose before the fire. The mattress of
+the sofa (which was a great deal too short for his lank figure), the
+sofa pillows, a blanket, the table-cover, a clean breakfast-cloth, and
+a great-coat, made him a bed and covering, for which he was more than
+thankful. Having lent him a night-cap, which he put on at once, and in
+which he made such an awful figure, that I have never worn one since, I
+left him to his rest.
+
+I never shall forget that night. I never shall forget how I turned
+and tumbled; how I wearied myself with thinking about Agnes and this
+creature; how I considered what could I do, and what ought I to do; how
+I could come to no other conclusion than that the best course for her
+peace was to do nothing, and to keep to myself what I had heard. If
+I went to sleep for a few moments, the image of Agnes with her tender
+eyes, and of her father looking fondly on her, as I had so often seen
+him look, arose before me with appealing faces, and filled me with vague
+terrors. When I awoke, the recollection that Uriah was lying in the next
+room, sat heavy on me like a waking nightmare; and oppressed me with a
+leaden dread, as if I had had some meaner quality of devil for a lodger.
+
+The poker got into my dozing thoughts besides, and wouldn't come out. I
+thought, between sleeping and waking, that it was still red hot, and I
+had snatched it out of the fire, and run him through the body. I was so
+haunted at last by the idea, though I knew there was nothing in it, that
+I stole into the next room to look at him. There I saw him, lying on his
+back, with his legs extending to I don't know where, gurglings taking
+place in his throat, stoppages in his nose, and his mouth open like
+a post-office. He was so much worse in reality than in my distempered
+fancy, that afterwards I was attracted to him in very repulsion, and
+could not help wandering in and out every half-hour or so, and taking
+another look at him. Still, the long, long night seemed heavy and
+hopeless as ever, and no promise of day was in the murky sky.
+
+When I saw him going downstairs early in the morning (for, thank Heaven!
+he would not stay to breakfast), it appeared to me as if the night was
+going away in his person. When I went out to the Commons, I charged
+Mrs. Crupp with particular directions to leave the windows open, that my
+sitting-room might be aired, and purged of his presence.
+
+
+
+CHAPTER 26. I FALL INTO CAPTIVITY
+
+
+I saw no more of Uriah Heep, until the day when Agnes left town. I was
+at the coach office to take leave of her and see her go; and there was
+he, returning to Canterbury by the same conveyance. It was some small
+satisfaction to me to observe his spare, short-waisted, high-shouldered,
+mulberry-coloured great-coat perched up, in company with an umbrella
+like a small tent, on the edge of the back seat on the roof, while
+Agnes was, of course, inside; but what I underwent in my efforts to be
+friendly with him, while Agnes looked on, perhaps deserved that little
+recompense. At the coach window, as at the dinner-party, he hovered
+about us without a moment's intermission, like a great vulture: gorging
+himself on every syllable that I said to Agnes, or Agnes said to me.
+
+In the state of trouble into which his disclosure by my fire had thrown
+me, I had thought very much of the words Agnes had used in reference to
+the partnership. 'I did what I hope was right. Feeling sure that it
+was necessary for papa's peace that the sacrifice should be made, I
+entreated him to make it.' A miserable foreboding that she would
+yield to, and sustain herself by, the same feeling in reference to any
+sacrifice for his sake, had oppressed me ever since. I knew how she
+loved him. I knew what the devotion of her nature was. I knew from her
+own lips that she regarded herself as the innocent cause of his errors,
+and as owing him a great debt she ardently desired to pay. I had no
+consolation in seeing how different she was from this detestable Rufus
+with the mulberry-coloured great-coat, for I felt that in the very
+difference between them, in the self-denial of her pure soul and the
+sordid baseness of his, the greatest danger lay. All this, doubtless, he
+knew thoroughly, and had, in his cunning, considered well.
+
+Yet I was so certain that the prospect of such a sacrifice afar off,
+must destroy the happiness of Agnes; and I was so sure, from her manner,
+of its being unseen by her then, and having cast no shadow on her yet;
+that I could as soon have injured her, as given her any warning of what
+impended. Thus it was that we parted without explanation: she waving
+her hand and smiling farewell from the coach window; her evil genius
+writhing on the roof, as if he had her in his clutches and triumphed.
+
+I could not get over this farewell glimpse of them for a long time. When
+Agnes wrote to tell me of her safe arrival, I was as miserable as when
+I saw her going away. Whenever I fell into a thoughtful state, this
+subject was sure to present itself, and all my uneasiness was sure to be
+redoubled. Hardly a night passed without my dreaming of it. It became a
+part of my life, and as inseparable from my life as my own head.
+
+I had ample leisure to refine upon my uneasiness: for Steerforth was at
+Oxford, as he wrote to me, and when I was not at the Commons, I was
+very much alone. I believe I had at this time some lurking distrust of
+Steerforth. I wrote to him most affectionately in reply to his, but I
+think I was glad, upon the whole, that he could not come to London just
+then. I suspect the truth to be, that the influence of Agnes was upon
+me, undisturbed by the sight of him; and that it was the more powerful
+with me, because she had so large a share in my thoughts and interest.
+
+In the meantime, days and weeks slipped away. I was articled to Spenlow
+and Jorkins. I had ninety pounds a year (exclusive of my house-rent
+and sundry collateral matters) from my aunt. My rooms were engaged
+for twelve months certain: and though I still found them dreary of an
+evening, and the evenings long, I could settle down into a state of
+equable low spirits, and resign myself to coffee; which I seem, on
+looking back, to have taken by the gallon at about this period of my
+existence. At about this time, too, I made three discoveries: first,
+that Mrs. Crupp was a martyr to a curious disorder called 'the
+spazzums', which was generally accompanied with inflammation of the
+nose, and required to be constantly treated with peppermint; secondly,
+that something peculiar in the temperature of my pantry, made the
+brandy-bottles burst; thirdly, that I was alone in the world, and much
+given to record that circumstance in fragments of English versification.
+
+On the day when I was articled, no festivity took place, beyond my
+having sandwiches and sherry into the office for the clerks, and going
+alone to the theatre at night. I went to see The Stranger, as a Doctors'
+Commons sort of play, and was so dreadfully cut up, that I hardly knew
+myself in my own glass when I got home. Mr. Spenlow remarked, on this
+occasion, when we concluded our business, that he should have been
+happy to have seen me at his house at Norwood to celebrate our becoming
+connected, but for his domestic arrangements being in some disorder,
+on account of the expected return of his daughter from finishing her
+education at Paris. But, he intimated that when she came home he should
+hope to have the pleasure of entertaining me. I knew that he was a
+widower with one daughter, and expressed my acknowledgements.
+
+Mr. Spenlow was as good as his word. In a week or two, he referred to
+this engagement, and said, that if I would do him the favour to come
+down next Saturday, and stay till Monday, he would be extremely happy.
+Of course I said I would do him the favour; and he was to drive me down
+in his phaeton, and to bring me back.
+
+When the day arrived, my very carpet-bag was an object of veneration
+to the stipendiary clerks, to whom the house at Norwood was a sacred
+mystery. One of them informed me that he had heard that Mr. Spenlow
+ate entirely off plate and china; and another hinted at champagne being
+constantly on draught, after the usual custom of table-beer. The old
+clerk with the wig, whose name was Mr. Tiffey, had been down on business
+several times in the course of his career, and had on each occasion
+penetrated to the breakfast-parlour. He described it as an apartment of
+the most sumptuous nature, and said that he had drunk brown East India
+sherry there, of a quality so precious as to make a man wink. We had
+an adjourned cause in the Consistory that day--about excommunicating a
+baker who had been objecting in a vestry to a paving-rate--and as the
+evidence was just twice the length of Robinson Crusoe, according to a
+calculation I made, it was rather late in the day before we finished.
+However, we got him excommunicated for six weeks, and sentenced in
+no end of costs; and then the baker's proctor, and the judge, and the
+advocates on both sides (who were all nearly related), went out of town
+together, and Mr. Spenlow and I drove away in the phaeton.
+
+The phaeton was a very handsome affair; the horses arched their necks
+and lifted up their legs as if they knew they belonged to Doctors'
+Commons. There was a good deal of competition in the Commons on all
+points of display, and it turned out some very choice equipages then;
+though I always have considered, and always shall consider, that in my
+time the great article of competition there was starch: which I think
+was worn among the proctors to as great an extent as it is in the nature
+of man to bear.
+
+We were very pleasant, going down, and Mr. Spenlow gave me some hints in
+reference to my profession. He said it was the genteelest profession in
+the world, and must on no account be confounded with the profession of a
+solicitor: being quite another sort of thing, infinitely more exclusive,
+less mechanical, and more profitable. We took things much more easily
+in the Commons than they could be taken anywhere else, he observed, and
+that set us, as a privileged class, apart. He said it was impossible
+to conceal the disagreeable fact, that we were chiefly employed by
+solicitors; but he gave me to understand that they were an inferior race
+of men, universally looked down upon by all proctors of any pretensions.
+
+I asked Mr. Spenlow what he considered the best sort of professional
+business? He replied, that a good case of a disputed will, where there
+was a neat little estate of thirty or forty thousand pounds, was,
+perhaps, the best of all. In such a case, he said, not only were there
+very pretty pickings, in the way of arguments at every stage of the
+proceedings, and mountains upon mountains of evidence on interrogatory
+and counter-interrogatory (to say nothing of an appeal lying, first to
+the Delegates, and then to the Lords), but, the costs being pretty sure
+to come out of the estate at last, both sides went at it in a lively
+and spirited manner, and expense was no consideration. Then, he launched
+into a general eulogium on the Commons. What was to be particularly
+admired (he said) in the Commons, was its compactness. It was the most
+conveniently organized place in the world. It was the complete idea of
+snugness. It lay in a nutshell. For example: You brought a divorce case,
+or a restitution case, into the Consistory. Very good. You tried it in
+the Consistory. You made a quiet little round game of it, among a family
+group, and you played it out at leisure. Suppose you were not satisfied
+with the Consistory, what did you do then? Why, you went into the
+Arches. What was the Arches? The same court, in the same room, with the
+same bar, and the same practitioners, but another judge, for there the
+Consistory judge could plead any court-day as an advocate. Well, you
+played your round game out again. Still you were not satisfied. Very
+good. What did you do then? Why, you went to the Delegates. Who were the
+Delegates? Why, the Ecclesiastical Delegates were the advocates without
+any business, who had looked on at the round game when it was playing in
+both courts, and had seen the cards shuffled, and cut, and played, and
+had talked to all the players about it, and now came fresh, as judges,
+to settle the matter to the satisfaction of everybody! Discontented
+people might talk of corruption in the Commons, closeness in the
+Commons, and the necessity of reforming the Commons, said Mr. Spenlow
+solemnly, in conclusion; but when the price of wheat per bushel had been
+highest, the Commons had been busiest; and a man might lay his hand upon
+his heart, and say this to the whole world,--'Touch the Commons, and
+down comes the country!'
+
+I listened to all this with attention; and though, I must say, I had my
+doubts whether the country was quite as much obliged to the Commons as
+Mr. Spenlow made out, I respectfully deferred to his opinion. That
+about the price of wheat per bushel, I modestly felt was too much for
+my strength, and quite settled the question. I have never, to this hour,
+got the better of that bushel of wheat. It has reappeared to annihilate
+me, all through my life, in connexion with all kinds of subjects. I
+don't know now, exactly, what it has to do with me, or what right it has
+to crush me, on an infinite variety of occasions; but whenever I see my
+old friend the bushel brought in by the head and shoulders (as he always
+is, I observe), I give up a subject for lost.
+
+This is a digression. I was not the man to touch the Commons, and
+bring down the country. I submissively expressed, by my silence, my
+acquiescence in all I had heard from my superior in years and knowledge;
+and we talked about The Stranger and the Drama, and the pairs of horses,
+until we came to Mr. Spenlow's gate.
+
+There was a lovely garden to Mr. Spenlow's house; and though that was
+not the best time of the year for seeing a garden, it was so beautifully
+kept, that I was quite enchanted. There was a charming lawn, there were
+clusters of trees, and there were perspective walks that I could just
+distinguish in the dark, arched over with trellis-work, on which shrubs
+and flowers grew in the growing season. 'Here Miss Spenlow walks by
+herself,' I thought. 'Dear me!'
+
+We went into the house, which was cheerfully lighted up, and into a hall
+where there were all sorts of hats, caps, great-coats, plaids, gloves,
+whips, and walking-sticks. 'Where is Miss Dora?' said Mr. Spenlow to the
+servant. 'Dora!' I thought. 'What a beautiful name!'
+
+We turned into a room near at hand (I think it was the identical
+breakfast-room, made memorable by the brown East Indian sherry), and I
+heard a voice say, 'Mr. Copperfield, my daughter Dora, and my daughter
+Dora's confidential friend!' It was, no doubt, Mr. Spenlow's voice,
+but I didn't know it, and I didn't care whose it was. All was over in a
+moment. I had fulfilled my destiny. I was a captive and a slave. I loved
+Dora Spenlow to distraction!
+
+She was more than human to me. She was a Fairy, a Sylph, I don't
+know what she was--anything that no one ever saw, and everything that
+everybody ever wanted. I was swallowed up in an abyss of love in an
+instant. There was no pausing on the brink; no looking down, or looking
+back; I was gone, headlong, before I had sense to say a word to her.
+
+'I,' observed a well-remembered voice, when I had bowed and murmured
+something, 'have seen Mr. Copperfield before.'
+
+The speaker was not Dora. No; the confidential friend, Miss Murdstone!
+
+I don't think I was much astonished. To the best of my judgement,
+no capacity of astonishment was left in me. There was nothing worth
+mentioning in the material world, but Dora Spenlow, to be astonished
+about. I said, 'How do you do, Miss Murdstone? I hope you are well.' She
+answered, 'Very well.' I said, 'How is Mr. Murdstone?' She replied, 'My
+brother is robust, I am obliged to you.'
+
+Mr. Spenlow, who, I suppose, had been surprised to see us recognize each
+other, then put in his word.
+
+'I am glad to find,' he said, 'Copperfield, that you and Miss Murdstone
+are already acquainted.'
+
+'Mr. Copperfield and myself,' said Miss Murdstone, with severe
+composure, 'are connexions. We were once slightly acquainted. It was in
+his childish days. Circumstances have separated us since. I should not
+have known him.'
+
+I replied that I should have known her, anywhere. Which was true enough.
+
+'Miss Murdstone has had the goodness,' said Mr. Spenlow to me, 'to
+accept the office--if I may so describe it--of my daughter Dora's
+confidential friend. My daughter Dora having, unhappily, no mother, Miss
+Murdstone is obliging enough to become her companion and protector.'
+
+A passing thought occurred to me that Miss Murdstone, like the pocket
+instrument called a life-preserver, was not so much designed for
+purposes of protection as of assault. But as I had none but passing
+thoughts for any subject save Dora, I glanced at her, directly
+afterwards, and was thinking that I saw, in her prettily pettish manner,
+that she was not very much inclined to be particularly confidential to
+her companion and protector, when a bell rang, which Mr. Spenlow said
+was the first dinner-bell, and so carried me off to dress.
+
+The idea of dressing one's self, or doing anything in the way of action,
+in that state of love, was a little too ridiculous. I could only sit
+down before my fire, biting the key of my carpet-bag, and think of the
+captivating, girlish, bright-eyed lovely Dora. What a form she had, what
+a face she had, what a graceful, variable, enchanting manner!
+
+The bell rang again so soon that I made a mere scramble of my dressing,
+instead of the careful operation I could have wished under the
+circumstances, and went downstairs. There was some company. Dora was
+talking to an old gentleman with a grey head. Grey as he was--and a
+great-grandfather into the bargain, for he said so--I was madly jealous
+of him.
+
+What a state of mind I was in! I was jealous of everybody. I couldn't
+bear the idea of anybody knowing Mr. Spenlow better than I did. It was
+torturing to me to hear them talk of occurrences in which I had had no
+share. When a most amiable person, with a highly polished bald head,
+asked me across the dinner table, if that were the first occasion of my
+seeing the grounds, I could have done anything to him that was savage
+and revengeful.
+
+I don't remember who was there, except Dora. I have not the least idea
+what we had for dinner, besides Dora. My impression is, that I dined off
+Dora, entirely, and sent away half-a-dozen plates untouched. I sat next
+to her. I talked to her. She had the most delightful little voice, the
+gayest little laugh, the pleasantest and most fascinating little
+ways, that ever led a lost youth into hopeless slavery. She was rather
+diminutive altogether. So much the more precious, I thought.
+
+When she went out of the room with Miss Murdstone (no other ladies
+were of the party), I fell into a reverie, only disturbed by the cruel
+apprehension that Miss Murdstone would disparage me to her. The amiable
+creature with the polished head told me a long story, which I think was
+about gardening. I think I heard him say, 'my gardener', several times.
+I seemed to pay the deepest attention to him, but I was wandering in a
+garden of Eden all the while, with Dora.
+
+My apprehensions of being disparaged to the object of my engrossing
+affection were revived when we went into the drawing-room, by the grim
+and distant aspect of Miss Murdstone. But I was relieved of them in an
+unexpected manner.
+
+'David Copperfield,' said Miss Murdstone, beckoning me aside into a
+window. 'A word.'
+
+I confronted Miss Murdstone alone.
+
+'David Copperfield,' said Miss Murdstone, 'I need not enlarge upon
+family circumstances. They are not a tempting subject.' 'Far from it,
+ma'am,' I returned.
+
+'Far from it,' assented Miss Murdstone. 'I do not wish to revive
+the memory of past differences, or of past outrages. I have received
+outrages from a person--a female I am sorry to say, for the credit of my
+sex--who is not to be mentioned without scorn and disgust; and therefore
+I would rather not mention her.'
+
+I felt very fiery on my aunt's account; but I said it would certainly be
+better, if Miss Murdstone pleased, not to mention her. I could not hear
+her disrespectfully mentioned, I added, without expressing my opinion in
+a decided tone.
+
+Miss Murdstone shut her eyes, and disdainfully inclined her head; then,
+slowly opening her eyes, resumed:
+
+'David Copperfield, I shall not attempt to disguise the fact, that I
+formed an unfavourable opinion of you in your childhood. It may have
+been a mistaken one, or you may have ceased to justify it. That is not
+in question between us now. I belong to a family remarkable, I believe,
+for some firmness; and I am not the creature of circumstance or change.
+I may have my opinion of you. You may have your opinion of me.'
+
+I inclined my head, in my turn.
+
+'But it is not necessary,' said Miss Murdstone, 'that these opinions
+should come into collision here. Under existing circumstances, it is as
+well on all accounts that they should not. As the chances of life have
+brought us together again, and may bring us together on other occasions,
+I would say, let us meet here as distant acquaintances. Family
+circumstances are a sufficient reason for our only meeting on that
+footing, and it is quite unnecessary that either of us should make the
+other the subject of remark. Do you approve of this?'
+
+'Miss Murdstone,' I returned, 'I think you and Mr. Murdstone used me
+very cruelly, and treated my mother with great unkindness. I shall
+always think so, as long as I live. But I quite agree in what you
+propose.'
+
+Miss Murdstone shut her eyes again, and bent her head. Then, just
+touching the back of my hand with the tips of her cold, stiff fingers,
+she walked away, arranging the little fetters on her wrists and round
+her neck; which seemed to be the same set, in exactly the same state,
+as when I had seen her last. These reminded me, in reference to Miss
+Murdstone's nature, of the fetters over a jail door; suggesting on the
+outside, to all beholders, what was to be expected within.
+
+All I know of the rest of the evening is, that I heard the empress of
+my heart sing enchanted ballads in the French language, generally to the
+effect that, whatever was the matter, we ought always to dance, Ta ra
+la, Ta ra la! accompanying herself on a glorified instrument, resembling
+a guitar. That I was lost in blissful delirium. That I refused
+refreshment. That my soul recoiled from punch particularly. That when
+Miss Murdstone took her into custody and led her away, she smiled and
+gave me her delicious hand. That I caught a view of myself in a mirror,
+looking perfectly imbecile and idiotic. That I retired to bed in a most
+maudlin state of mind, and got up in a crisis of feeble infatuation.
+
+It was a fine morning, and early, and I thought I would go and take a
+stroll down one of those wire-arched walks, and indulge my passion by
+dwelling on her image. On my way through the hall, I encountered her
+little dog, who was called Jip--short for Gipsy. I approached him
+tenderly, for I loved even him; but he showed his whole set of teeth,
+got under a chair expressly to snarl, and wouldn't hear of the least
+familiarity.
+
+The garden was cool and solitary. I walked about, wondering what my
+feelings of happiness would be, if I could ever become engaged to this
+dear wonder. As to marriage, and fortune, and all that, I believe I was
+almost as innocently undesigning then, as when I loved little Em'ly. To
+be allowed to call her 'Dora', to write to her, to dote upon and worship
+her, to have reason to think that when she was with other people she was
+yet mindful of me, seemed to me the summit of human ambition--I am
+sure it was the summit of mine. There is no doubt whatever that I was
+a lackadaisical young spooney; but there was a purity of heart in all
+this, that prevents my having quite a contemptuous recollection of it,
+let me laugh as I may.
+
+I had not been walking long, when I turned a corner, and met her. I
+tingle again from head to foot as my recollection turns that corner, and
+my pen shakes in my hand.
+
+'You--are--out early, Miss Spenlow,' said I.
+
+'It's so stupid at home,' she replied, 'and Miss Murdstone is so absurd!
+She talks such nonsense about its being necessary for the day to be
+aired, before I come out. Aired!' (She laughed, here, in the most
+melodious manner.) 'On a Sunday morning, when I don't practise, I must
+do something. So I told papa last night I must come out. Besides, it's
+the brightest time of the whole day. Don't you think so?'
+
+I hazarded a bold flight, and said (not without stammering) that it
+was very bright to me then, though it had been very dark to me a minute
+before.
+
+'Do you mean a compliment?' said Dora, 'or that the weather has really
+changed?'
+
+I stammered worse than before, in replying that I meant no compliment,
+but the plain truth; though I was not aware of any change having taken
+place in the weather. It was in the state of my own feelings, I added
+bashfully: to clench the explanation.
+
+I never saw such curls--how could I, for there never were such
+curls!--as those she shook out to hide her blushes. As to the straw hat
+and blue ribbons which was on the top of the curls, if I could only have
+hung it up in my room in Buckingham Street, what a priceless possession
+it would have been!
+
+'You have just come home from Paris,' said I.
+
+'Yes,' said she. 'Have you ever been there?'
+
+'No.'
+
+'Oh! I hope you'll go soon! You would like it so much!'
+
+Traces of deep-seated anguish appeared in my countenance. That she
+should hope I would go, that she should think it possible I could go,
+was insupportable. I depreciated Paris; I depreciated France. I said I
+wouldn't leave England, under existing circumstances, for any earthly
+consideration. Nothing should induce me. In short, she was shaking the
+curls again, when the little dog came running along the walk to our
+relief.
+
+He was mortally jealous of me, and persisted in barking at me. She took
+him up in her arms--oh my goodness!--and caressed him, but he persisted
+upon barking still. He wouldn't let me touch him, when I tried; and then
+she beat him. It increased my sufferings greatly to see the pats she
+gave him for punishment on the bridge of his blunt nose, while he winked
+his eyes, and licked her hand, and still growled within himself like a
+little double-bass. At length he was quiet--well he might be with her
+dimpled chin upon his head!--and we walked away to look at a greenhouse.
+
+'You are not very intimate with Miss Murdstone, are you?' said Dora.
+--'My pet.'
+
+(The two last words were to the dog. Oh, if they had only been to me!)
+
+'No,' I replied. 'Not at all so.'
+
+'She is a tiresome creature,' said Dora, pouting. 'I can't think what
+papa can have been about, when he chose such a vexatious thing to be my
+companion. Who wants a protector? I am sure I don't want a protector.
+Jip can protect me a great deal better than Miss Murdstone,--can't you,
+Jip, dear?'
+
+He only winked lazily, when she kissed his ball of a head.
+
+'Papa calls her my confidential friend, but I am sure she is no such
+thing--is she, Jip? We are not going to confide in any such cross
+people, Jip and I. We mean to bestow our confidence where we like,
+and to find out our own friends, instead of having them found out for
+us--don't we, Jip?'
+
+Jip made a comfortable noise, in answer, a little like a tea-kettle when
+it sings. As for me, every word was a new heap of fetters, riveted above
+the last.
+
+'It is very hard, because we have not a kind Mama, that we are to have,
+instead, a sulky, gloomy old thing like Miss Murdstone, always following
+us about--isn't it, Jip? Never mind, Jip. We won't be confidential, and
+we'll make ourselves as happy as we can in spite of her, and we'll tease
+her, and not please her--won't we, Jip?'
+
+If it had lasted any longer, I think I must have gone down on my knees
+on the gravel, with the probability before me of grazing them, and of
+being presently ejected from the premises besides. But, by good fortune
+the greenhouse was not far off, and these words brought us to it.
+
+It contained quite a show of beautiful geraniums. We loitered along in
+front of them, and Dora often stopped to admire this one or that one,
+and I stopped to admire the same one, and Dora, laughing, held the dog
+up childishly, to smell the flowers; and if we were not all three in
+Fairyland, certainly I was. The scent of a geranium leaf, at this day,
+strikes me with a half comical half serious wonder as to what change has
+come over me in a moment; and then I see a straw hat and blue ribbons,
+and a quantity of curls, and a little black dog being held up, in two
+slender arms, against a bank of blossoms and bright leaves.
+
+Miss Murdstone had been looking for us. She found us here; and presented
+her uncongenial cheek, the little wrinkles in it filled with hair
+powder, to Dora to be kissed. Then she took Dora's arm in hers, and
+marched us into breakfast as if it were a soldier's funeral.
+
+How many cups of tea I drank, because Dora made it, I don't know. But,
+I perfectly remember that I sat swilling tea until my whole nervous
+system, if I had had any in those days, must have gone by the board. By
+and by we went to church. Miss Murdstone was between Dora and me in the
+pew; but I heard her sing, and the congregation vanished. A sermon was
+delivered--about Dora, of course--and I am afraid that is all I know of
+the service.
+
+We had a quiet day. No company, a walk, a family dinner of four, and an
+evening of looking over books and pictures; Miss Murdstone with a homily
+before her, and her eye upon us, keeping guard vigilantly. Ah! little
+did Mr. Spenlow imagine, when he sat opposite to me after dinner that
+day, with his pocket-handkerchief over his head, how fervently I was
+embracing him, in my fancy, as his son-in-law! Little did he think, when
+I took leave of him at night, that he had just given his full consent to
+my being engaged to Dora, and that I was invoking blessings on his head!
+
+We departed early in the morning, for we had a Salvage case coming on in
+the Admiralty Court, requiring a rather accurate knowledge of the whole
+science of navigation, in which (as we couldn't be expected to know
+much about those matters in the Commons) the judge had entreated two old
+Trinity Masters, for charity's sake, to come and help him out. Dora was
+at the breakfast-table to make the tea again, however; and I had the
+melancholy pleasure of taking off my hat to her in the phaeton, as she
+stood on the door-step with Jip in her arms.
+
+What the Admiralty was to me that day; what nonsense I made of our case
+in my mind, as I listened to it; how I saw 'DORA' engraved upon the
+blade of the silver oar which they lay upon the table, as the emblem
+of that high jurisdiction; and how I felt when Mr. Spenlow went home
+without me (I had had an insane hope that he might take me back again),
+as if I were a mariner myself, and the ship to which I belonged had
+sailed away and left me on a desert island; I shall make no fruitless
+effort to describe. If that sleepy old court could rouse itself, and
+present in any visible form the daydreams I have had in it about Dora,
+it would reveal my truth.
+
+I don't mean the dreams that I dreamed on that day alone, but day after
+day, from week to week, and term to term. I went there, not to attend to
+what was going on, but to think about Dora. If ever I bestowed a thought
+upon the cases, as they dragged their slow length before me, it was only
+to wonder, in the matrimonial cases (remembering Dora), how it was
+that married people could ever be otherwise than happy; and, in the
+Prerogative cases, to consider, if the money in question had been left
+to me, what were the foremost steps I should immediately have taken
+in regard to Dora. Within the first week of my passion, I bought four
+sumptuous waistcoats--not for myself; I had no pride in them; for
+Dora--and took to wearing straw-coloured kid gloves in the streets, and
+laid the foundations of all the corns I have ever had. If the boots I
+wore at that period could only be produced and compared with the natural
+size of my feet, they would show what the state of my heart was, in a
+most affecting manner.
+
+And yet, wretched cripple as I made myself by this act of homage to
+Dora, I walked miles upon miles daily in the hope of seeing her. Not
+only was I soon as well known on the Norwood Road as the postmen on that
+beat, but I pervaded London likewise. I walked about the streets where
+the best shops for ladies were, I haunted the Bazaar like an unquiet
+spirit, I fagged through the Park again and again, long after I was
+quite knocked up. Sometimes, at long intervals and on rare occasions, I
+saw her. Perhaps I saw her glove waved in a carriage window; perhaps I
+met her, walked with her and Miss Murdstone a little way, and spoke to
+her. In the latter case I was always very miserable afterwards, to think
+that I had said nothing to the purpose; or that she had no idea of the
+extent of my devotion, or that she cared nothing about me. I was always
+looking out, as may be supposed, for another invitation to Mr. Spenlow's
+house. I was always being disappointed, for I got none.
+
+Mrs. Crupp must have been a woman of penetration; for when this
+attachment was but a few weeks old, and I had not had the courage
+to write more explicitly even to Agnes, than that I had been to Mr.
+Spenlow's house, 'whose family,' I added, 'consists of one daughter';--I
+say Mrs. Crupp must have been a woman of penetration, for, even in that
+early stage, she found it out. She came up to me one evening, when I
+was very low, to ask (she being then afflicted with the disorder I have
+mentioned) if I could oblige her with a little tincture of cardamums
+mixed with rhubarb, and flavoured with seven drops of the essence of
+cloves, which was the best remedy for her complaint;--or, if I had not
+such a thing by me, with a little brandy, which was the next best. It
+was not, she remarked, so palatable to her, but it was the next best. As
+I had never even heard of the first remedy, and always had the second in
+the closet, I gave Mrs. Crupp a glass of the second, which (that I might
+have no suspicion of its being devoted to any improper use) she began to
+take in my presence.
+
+'Cheer up, sir,' said Mrs. Crupp. 'I can't abear to see you so, sir: I'm
+a mother myself.'
+
+I did not quite perceive the application of this fact to myself, but I
+smiled on Mrs. Crupp, as benignly as was in my power.
+
+'Come, sir,' said Mrs. Crupp. 'Excuse me. I know what it is, sir.
+There's a lady in the case.'
+
+'Mrs. Crupp?' I returned, reddening.
+
+'Oh, bless you! Keep a good heart, sir!' said Mrs. Crupp, nodding
+encouragement. 'Never say die, sir! If She don't smile upon you,
+there's a many as will. You are a young gentleman to be smiled on, Mr.
+Copperfull, and you must learn your walue, sir.'
+
+Mrs. Crupp always called me Mr. Copperfull: firstly, no doubt, because
+it was not my name; and secondly, I am inclined to think, in some
+indistinct association with a washing-day.
+
+'What makes you suppose there is any young lady in the case, Mrs.
+Crupp?' said I.
+
+'Mr. Copperfull,' said Mrs. Crupp, with a great deal of feeling, 'I'm a
+mother myself.'
+
+For some time Mrs. Crupp could only lay her hand upon her nankeen bosom,
+and fortify herself against returning pain with sips of her medicine. At
+length she spoke again.
+
+'When the present set were took for you by your dear aunt, Mr.
+Copperfull,' said Mrs. Crupp, 'my remark were, I had now found summun
+I could care for. "Thank Ev'in!" were the expression, "I have now found
+summun I can care for!"--You don't eat enough, sir, nor yet drink.'
+
+'Is that what you found your supposition on, Mrs. Crupp?' said I.
+
+'Sir,' said Mrs. Crupp, in a tone approaching to severity, 'I've
+laundressed other young gentlemen besides yourself. A young gentleman
+may be over-careful of himself, or he may be under-careful of himself.
+He may brush his hair too regular, or too un-regular. He may wear his
+boots much too large for him, or much too small. That is according as
+the young gentleman has his original character formed. But let him go to
+which extreme he may, sir, there's a young lady in both of 'em.'
+
+Mrs. Crupp shook her head in such a determined manner, that I had not an
+inch of vantage-ground left.
+
+'It was but the gentleman which died here before yourself,' said Mrs.
+Crupp, 'that fell in love--with a barmaid--and had his waistcoats took
+in directly, though much swelled by drinking.'
+
+'Mrs. Crupp,' said I, 'I must beg you not to connect the young lady in
+my case with a barmaid, or anything of that sort, if you please.'
+
+'Mr. Copperfull,' returned Mrs. Crupp, 'I'm a mother myself, and not
+likely. I ask your pardon, sir, if I intrude. I should never wish to
+intrude where I were not welcome. But you are a young gentleman, Mr.
+Copperfull, and my adwice to you is, to cheer up, sir, to keep a good
+heart, and to know your own walue. If you was to take to something,
+sir,' said Mrs. Crupp, 'if you was to take to skittles, now, which is
+healthy, you might find it divert your mind, and do you good.'
+
+With these words, Mrs. Crupp, affecting to be very careful of the
+brandy--which was all gone--thanked me with a majestic curtsey, and
+retired. As her figure disappeared into the gloom of the entry, this
+counsel certainly presented itself to my mind in the light of a slight
+liberty on Mrs. Crupp's part; but, at the same time, I was content
+to receive it, in another point of view, as a word to the wise, and a
+warning in future to keep my secret better.
+
+
+
+CHAPTER 27. TOMMY TRADDLES
+
+
+It may have been in consequence of Mrs. Crupp's advice, and, perhaps,
+for no better reason than because there was a certain similarity in the
+sound of the word skittles and Traddles, that it came into my head, next
+day, to go and look after Traddles. The time he had mentioned was more
+than out, and he lived in a little street near the Veterinary College
+at Camden Town, which was principally tenanted, as one of our clerks who
+lived in that direction informed me, by gentlemen students, who bought
+live donkeys, and made experiments on those quadrupeds in their private
+apartments. Having obtained from this clerk a direction to the academic
+grove in question, I set out, the same afternoon, to visit my old
+schoolfellow.
+
+I found that the street was not as desirable a one as I could have
+wished it to be, for the sake of Traddles. The inhabitants appeared to
+have a propensity to throw any little trifles they were not in want of,
+into the road: which not only made it rank and sloppy, but untidy too,
+on account of the cabbage-leaves. The refuse was not wholly vegetable
+either, for I myself saw a shoe, a doubled-up saucepan, a black bonnet,
+and an umbrella, in various stages of decomposition, as I was looking
+out for the number I wanted.
+
+The general air of the place reminded me forcibly of the days when I
+lived with Mr. and Mrs. Micawber. An indescribable character of faded
+gentility that attached to the house I sought, and made it unlike
+all the other houses in the street--though they were all built on one
+monotonous pattern, and looked like the early copies of a blundering boy
+who was learning to make houses, and had not yet got out of his cramped
+brick-and-mortar pothooks--reminded me still more of Mr. and Mrs.
+Micawber. Happening to arrive at the door as it was opened to the
+afternoon milkman, I was reminded of Mr. and Mrs. Micawber more forcibly
+yet.
+
+'Now,' said the milkman to a very youthful servant girl. 'Has that there
+little bill of mine been heerd on?'
+
+'Oh, master says he'll attend to it immediate,' was the reply.
+
+'Because,' said the milkman, going on as if he had received no answer,
+and speaking, as I judged from his tone, rather for the edification of
+somebody within the house, than of the youthful servant--an
+impression which was strengthened by his manner of glaring down the
+passage--'because that there little bill has been running so long, that
+I begin to believe it's run away altogether, and never won't be heerd
+of. Now, I'm not a going to stand it, you know!' said the milkman, still
+throwing his voice into the house, and glaring down the passage.
+
+As to his dealing in the mild article of milk, by the by, there never
+was a greater anomaly. His deportment would have been fierce in a
+butcher or a brandy-merchant.
+
+The voice of the youthful servant became faint, but she seemed to me,
+from the action of her lips, again to murmur that it would be attended
+to immediate.
+
+'I tell you what,' said the milkman, looking hard at her for the first
+time, and taking her by the chin, 'are you fond of milk?'
+
+'Yes, I likes it,' she replied. 'Good,' said the milkman. 'Then you
+won't have none tomorrow. D'ye hear? Not a fragment of milk you won't
+have tomorrow.'
+
+I thought she seemed, upon the whole, relieved by the prospect of having
+any today. The milkman, after shaking his head at her darkly, released
+her chin, and with anything rather than good-will opened his can, and
+deposited the usual quantity in the family jug. This done, he went away,
+muttering, and uttered the cry of his trade next door, in a vindictive
+shriek.
+
+'Does Mr. Traddles live here?' I then inquired.
+
+A mysterious voice from the end of the passage replied 'Yes.' Upon which
+the youthful servant replied 'Yes.'
+
+'Is he at home?' said I.
+
+Again the mysterious voice replied in the affirmative, and again the
+servant echoed it. Upon this, I walked in, and in pursuance of the
+servant's directions walked upstairs; conscious, as I passed the
+back parlour-door, that I was surveyed by a mysterious eye, probably
+belonging to the mysterious voice.
+
+When I got to the top of the stairs--the house was only a story high
+above the ground floor--Traddles was on the landing to meet me. He was
+delighted to see me, and gave me welcome, with great heartiness, to
+his little room. It was in the front of the house, and extremely neat,
+though sparely furnished. It was his only room, I saw; for there was a
+sofa-bedstead in it, and his blacking-brushes and blacking were among
+his books--on the top shelf, behind a dictionary. His table was covered
+with papers, and he was hard at work in an old coat. I looked at
+nothing, that I know of, but I saw everything, even to the prospect of
+a church upon his china inkstand, as I sat down--and this, too, was a
+faculty confirmed in me in the old Micawber times. Various ingenious
+arrangements he had made, for the disguise of his chest of drawers,
+and the accommodation of his boots, his shaving-glass, and so forth,
+particularly impressed themselves upon me, as evidences of the same
+Traddles who used to make models of elephants' dens in writing-paper to
+put flies in; and to comfort himself under ill usage, with the memorable
+works of art I have so often mentioned.
+
+In a corner of the room was something neatly covered up with a large
+white cloth. I could not make out what that was.
+
+'Traddles,' said I, shaking hands with him again, after I had sat down,
+'I am delighted to see you.'
+
+'I am delighted to see YOU, Copperfield,' he returned. 'I am very glad
+indeed to see you. It was because I was thoroughly glad to see you when
+we met in Ely Place, and was sure you were thoroughly glad to see me,
+that I gave you this address instead of my address at chambers.' 'Oh!
+You have chambers?' said I.
+
+'Why, I have the fourth of a room and a passage, and the fourth of a
+clerk,' returned Traddles. 'Three others and myself unite to have a
+set of chambers--to look business-like--and we quarter the clerk too.
+Half-a-crown a week he costs me.'
+
+His old simple character and good temper, and something of his old
+unlucky fortune also, I thought, smiled at me in the smile with which he
+made this explanation.
+
+'It's not because I have the least pride, Copperfield, you understand,'
+said Traddles, 'that I don't usually give my address here. It's only on
+account of those who come to me, who might not like to come here. For
+myself, I am fighting my way on in the world against difficulties, and
+it would be ridiculous if I made a pretence of doing anything else.'
+
+'You are reading for the bar, Mr. Waterbrook informed me?' said I.
+
+'Why, yes,' said Traddles, rubbing his hands slowly over one another. 'I
+am reading for the bar. The fact is, I have just begun to keep my terms,
+after rather a long delay. It's some time since I was articled, but the
+payment of that hundred pounds was a great pull. A great pull!' said
+Traddles, with a wince, as if he had had a tooth out.
+
+'Do you know what I can't help thinking of, Traddles, as I sit here
+looking at you?' I asked him.
+
+'No,' said he.
+
+'That sky-blue suit you used to wear.'
+
+'Lord, to be sure!' cried Traddles, laughing. 'Tight in the arms and
+legs, you know? Dear me! Well! Those were happy times, weren't they?'
+
+'I think our schoolmaster might have made them happier, without doing
+any harm to any of us, I acknowledge,' I returned.
+
+'Perhaps he might,' said Traddles. 'But dear me, there was a good deal
+of fun going on. Do you remember the nights in the bedroom? When we used
+to have the suppers? And when you used to tell the stories? Ha, ha,
+ha! And do you remember when I got caned for crying about Mr. Mell? Old
+Creakle! I should like to see him again, too!'
+
+'He was a brute to you, Traddles,' said I, indignantly; for his good
+humour made me feel as if I had seen him beaten but yesterday.
+
+'Do you think so?' returned Traddles. 'Really? Perhaps he was rather.
+But it's all over, a long while. Old Creakle!'
+
+'You were brought up by an uncle, then?' said I.
+
+'Of course I was!' said Traddles. 'The one I was always going to write
+to. And always didn't, eh! Ha, ha, ha! Yes, I had an uncle then. He died
+soon after I left school.'
+
+'Indeed!'
+
+'Yes. He was a retired--what do you call
+it!--draper--cloth-merchant--and had made me his heir. But he didn't
+like me when I grew up.'
+
+'Do you really mean that?' said I. He was so composed, that I fancied he
+must have some other meaning.
+
+'Oh dear, yes, Copperfield! I mean it,' replied Traddles. 'It was an
+unfortunate thing, but he didn't like me at all. He said I wasn't at all
+what he expected, and so he married his housekeeper.'
+
+'And what did you do?' I asked.
+
+'I didn't do anything in particular,' said Traddles. 'I lived with them,
+waiting to be put out in the world, until his gout unfortunately flew
+to his stomach--and so he died, and so she married a young man, and so I
+wasn't provided for.'
+
+'Did you get nothing, Traddles, after all?'
+
+'Oh dear, yes!' said Traddles. 'I got fifty pounds. I had never been
+brought up to any profession, and at first I was at a loss what to
+do for myself. However, I began, with the assistance of the son of a
+professional man, who had been to Salem House--Yawler, with his nose on
+one side. Do you recollect him?'
+
+No. He had not been there with me; all the noses were straight in my
+day.
+
+'It don't matter,' said Traddles. 'I began, by means of his assistance,
+to copy law writings. That didn't answer very well; and then I began to
+state cases for them, and make abstracts, and that sort of work. For
+I am a plodding kind of fellow, Copperfield, and had learnt the way of
+doing such things pithily. Well! That put it in my head to enter myself
+as a law student; and that ran away with all that was left of the fifty
+pounds. Yawler recommended me to one or two other offices, however--Mr.
+Waterbrook's for one--and I got a good many jobs. I was fortunate
+enough, too, to become acquainted with a person in the publishing way,
+who was getting up an Encyclopaedia, and he set me to work; and, indeed'
+(glancing at his table), 'I am at work for him at this minute. I am not
+a bad compiler, Copperfield,' said Traddles, preserving the same air of
+cheerful confidence in all he said, 'but I have no invention at all; not
+a particle. I suppose there never was a young man with less originality
+than I have.'
+
+As Traddles seemed to expect that I should assent to this as a matter
+of course, I nodded; and he went on, with the same sprightly patience--I
+can find no better expression--as before.
+
+'So, by little and little, and not living high, I managed to scrape up
+the hundred pounds at last,' said Traddles; 'and thank Heaven that's
+paid--though it was--though it certainly was,' said Traddles, wincing
+again as if he had had another tooth out, 'a pull. I am living by the
+sort of work I have mentioned, still, and I hope, one of these days, to
+get connected with some newspaper: which would almost be the making of
+my fortune. Now, Copperfield, you are so exactly what you used to
+be, with that agreeable face, and it's so pleasant to see you, that I
+sha'n't conceal anything. Therefore you must know that I am engaged.'
+
+Engaged! Oh, Dora!
+
+'She is a curate's daughter,' said Traddles; 'one of ten, down in
+Devonshire. Yes!' For he saw me glance, involuntarily, at the prospect
+on the inkstand. 'That's the church! You come round here to the left,
+out of this gate,' tracing his finger along the inkstand, 'and exactly
+where I hold this pen, there stands the house--facing, you understand,
+towards the church.'
+
+The delight with which he entered into these particulars, did not fully
+present itself to me until afterwards; for my selfish thoughts were
+making a ground-plan of Mr. Spenlow's house and garden at the same
+moment.
+
+'She is such a dear girl!' said Traddles; 'a little older than me, but
+the dearest girl! I told you I was going out of town? I have been down
+there. I walked there, and I walked back, and I had the most delightful
+time! I dare say ours is likely to be a rather long engagement, but our
+motto is "Wait and hope!" We always say that. "Wait and hope," we always
+say. And she would wait, Copperfield, till she was sixty--any age you
+can mention--for me!'
+
+Traddles rose from his chair, and, with a triumphant smile, put his hand
+upon the white cloth I had observed.
+
+'However,' he said, 'it's not that we haven't made a beginning towards
+housekeeping. No, no; we have begun. We must get on by degrees, but we
+have begun. Here,' drawing the cloth off with great pride and care, 'are
+two pieces of furniture to commence with. This flower-pot and stand,
+she bought herself. You put that in a parlour window,' said Traddles,
+falling a little back from it to survey it with the greater admiration,
+'with a plant in it, and--and there you are! This little round table
+with the marble top (it's two feet ten in circumference), I bought. You
+want to lay a book down, you know, or somebody comes to see you or your
+wife, and wants a place to stand a cup of tea upon, and--and there you
+are again!' said Traddles. 'It's an admirable piece of workmanship--firm
+as a rock!' I praised them both, highly, and Traddles replaced the
+covering as carefully as he had removed it.
+
+'It's not a great deal towards the furnishing,' said Traddles, 'but
+it's something. The table-cloths, and pillow-cases, and articles of
+that kind, are what discourage me most, Copperfield. So does
+the ironmongery--candle-boxes, and gridirons, and that sort of
+necessaries--because those things tell, and mount up. However, "wait and
+hope!" And I assure you she's the dearest girl!'
+
+'I am quite certain of it,' said I.
+
+'In the meantime,' said Traddles, coming back to his chair; 'and this is
+the end of my prosing about myself, I get on as well as I can. I don't
+make much, but I don't spend much. In general, I board with the people
+downstairs, who are very agreeable people indeed. Both Mr. and Mrs.
+Micawber have seen a good deal of life, and are excellent company.'
+
+'My dear Traddles!' I quickly exclaimed. 'What are you talking about?'
+
+Traddles looked at me, as if he wondered what I was talking about.
+
+'Mr. and Mrs. Micawber!' I repeated. 'Why, I am intimately acquainted
+with them!'
+
+An opportune double knock at the door, which I knew well from old
+experience in Windsor Terrace, and which nobody but Mr. Micawber could
+ever have knocked at that door, resolved any doubt in my mind as to
+their being my old friends. I begged Traddles to ask his landlord
+to walk up. Traddles accordingly did so, over the banister; and Mr.
+Micawber, not a bit changed--his tights, his stick, his shirt-collar,
+and his eye-glass, all the same as ever--came into the room with a
+genteel and youthful air.
+
+'I beg your pardon, Mr. Traddles,' said Mr. Micawber, with the old roll
+in his voice, as he checked himself in humming a soft tune. 'I was not
+aware that there was any individual, alien to this tenement, in your
+sanctum.'
+
+Mr. Micawber slightly bowed to me, and pulled up his shirt-collar.
+
+'How do you do, Mr. Micawber?' said I.
+
+'Sir,' said Mr. Micawber, 'you are exceedingly obliging. I am in statu
+quo.'
+
+'And Mrs. Micawber?' I pursued.
+
+'Sir,' said Mr. Micawber, 'she is also, thank God, in statu quo.'
+
+'And the children, Mr. Micawber?'
+
+'Sir,' said Mr. Micawber, 'I rejoice to reply that they are, likewise,
+in the enjoyment of salubrity.'
+
+All this time, Mr. Micawber had not known me in the least, though he
+had stood face to face with me. But now, seeing me smile, he examined my
+features with more attention, fell back, cried, 'Is it possible! Have I
+the pleasure of again beholding Copperfield!' and shook me by both hands
+with the utmost fervour.
+
+'Good Heaven, Mr. Traddles!' said Mr. Micawber, 'to think that I should
+find you acquainted with the friend of my youth, the companion of
+earlier days! My dear!' calling over the banisters to Mrs. Micawber,
+while Traddles looked (with reason) not a little amazed at this
+description of me. 'Here is a gentleman in Mr. Traddles's apartment,
+whom he wishes to have the pleasure of presenting to you, my love!'
+
+Mr. Micawber immediately reappeared, and shook hands with me again.
+
+'And how is our good friend the Doctor, Copperfield?' said Mr. Micawber,
+'and all the circle at Canterbury?'
+
+'I have none but good accounts of them,' said I.
+
+'I am most delighted to hear it,' said Mr. Micawber. 'It was at
+Canterbury where we last met. Within the shadow, I may figuratively say,
+of that religious edifice immortalized by Chaucer, which was anciently
+the resort of Pilgrims from the remotest corners of--in short,' said Mr.
+Micawber, 'in the immediate neighbourhood of the Cathedral.'
+
+I replied that it was. Mr. Micawber continued talking as volubly as he
+could; but not, I thought, without showing, by some marks of concern in
+his countenance, that he was sensible of sounds in the next room, as
+of Mrs. Micawber washing her hands, and hurriedly opening and shutting
+drawers that were uneasy in their action.
+
+'You find us, Copperfield,' said Mr. Micawber, with one eye on Traddles,
+'at present established, on what may be designated as a small and
+unassuming scale; but, you are aware that I have, in the course of my
+career, surmounted difficulties, and conquered obstacles. You are no
+stranger to the fact, that there have been periods of my life, when it
+has been requisite that I should pause, until certain expected events
+should turn up; when it has been necessary that I should fall back,
+before making what I trust I shall not be accused of presumption in
+terming--a spring. The present is one of those momentous stages in the
+life of man. You find me, fallen back, FOR a spring; and I have every
+reason to believe that a vigorous leap will shortly be the result.'
+
+I was expressing my satisfaction, when Mrs. Micawber came in; a little
+more slatternly than she used to be, or so she seemed now, to my
+unaccustomed eyes, but still with some preparation of herself for
+company, and with a pair of brown gloves on.
+
+'My dear,' said Mr. Micawber, leading her towards me, 'here is
+a gentleman of the name of Copperfield, who wishes to renew his
+acquaintance with you.'
+
+It would have been better, as it turned out, to have led gently up
+to this announcement, for Mrs. Micawber, being in a delicate state of
+health, was overcome by it, and was taken so unwell, that Mr. Micawber
+was obliged, in great trepidation, to run down to the water-butt in
+the backyard, and draw a basinful to lave her brow with. She
+presently revived, however, and was really pleased to see me. We had
+half-an-hour's talk, all together; and I asked her about the twins,
+who, she said, were 'grown great creatures'; and after Master and Miss
+Micawber, whom she described as 'absolute giants', but they were not
+produced on that occasion.
+
+Mr. Micawber was very anxious that I should stay to dinner. I should not
+have been averse to do so, but that I imagined I detected trouble, and
+calculation relative to the extent of the cold meat, in Mrs. Micawber's
+eye. I therefore pleaded another engagement; and observing that Mrs.
+Micawber's spirits were immediately lightened, I resisted all persuasion
+to forego it.
+
+But I told Traddles, and Mr. and Mrs. Micawber, that before I could
+think of leaving, they must appoint a day when they would come and dine
+with me. The occupations to which Traddles stood pledged, rendered it
+necessary to fix a somewhat distant one; but an appointment was made for
+the purpose, that suited us all, and then I took my leave.
+
+Mr. Micawber, under pretence of showing me a nearer way than that by
+which I had come, accompanied me to the corner of the street; being
+anxious (he explained to me) to say a few words to an old friend, in
+confidence.
+
+'My dear Copperfield,' said Mr. Micawber, 'I need hardly tell you that
+to have beneath our roof, under existing circumstances, a mind like that
+which gleams--if I may be allowed the expression--which gleams--in your
+friend Traddles, is an unspeakable comfort. With a washerwoman, who
+exposes hard-bake for sale in her parlour-window, dwelling next door,
+and a Bow-street officer residing over the way, you may imagine that his
+society is a source of consolation to myself and to Mrs. Micawber. I
+am at present, my dear Copperfield, engaged in the sale of corn upon
+commission. It is not an avocation of a remunerative description--in
+other words, it does not pay--and some temporary embarrassments of a
+pecuniary nature have been the consequence. I am, however, delighted to
+add that I have now an immediate prospect of something turning up (I am
+not at liberty to say in what direction), which I trust will enable me
+to provide, permanently, both for myself and for your friend Traddles,
+in whom I have an unaffected interest. You may, perhaps, be prepared
+to hear that Mrs. Micawber is in a state of health which renders it
+not wholly improbable that an addition may be ultimately made to those
+pledges of affection which--in short, to the infantine group. Mrs.
+Micawber's family have been so good as to express their dissatisfaction
+at this state of things. I have merely to observe, that I am not aware
+that it is any business of theirs, and that I repel that exhibition of
+feeling with scorn, and with defiance!'
+
+Mr. Micawber then shook hands with me again, and left me.
+
+
+
+CHAPTER 28. Mr. MICAWBER'S GAUNTLET
+
+
+Until the day arrived on which I was to entertain my newly-found
+old friends, I lived principally on Dora and coffee. In my love-lorn
+condition, my appetite languished; and I was glad of it, for I felt
+as though it would have been an act of perfidy towards Dora to have a
+natural relish for my dinner. The quantity of walking exercise I took,
+was not in this respect attended with its usual consequence, as the
+disappointment counteracted the fresh air. I have my doubts, too,
+founded on the acute experience acquired at this period of my life,
+whether a sound enjoyment of animal food can develop itself freely in
+any human subject who is always in torment from tight boots. I think
+the extremities require to be at peace before the stomach will conduct
+itself with vigour.
+
+On the occasion of this domestic little party, I did not repeat my
+former extensive preparations. I merely provided a pair of soles,
+a small leg of mutton, and a pigeon-pie. Mrs. Crupp broke out into
+rebellion on my first bashful hint in reference to the cooking of the
+fish and joint, and said, with a dignified sense of injury, 'No! No,
+sir! You will not ask me sich a thing, for you are better acquainted
+with me than to suppose me capable of doing what I cannot do with ampial
+satisfaction to my own feelings!' But, in the end, a compromise was
+effected; and Mrs. Crupp consented to achieve this feat, on condition
+that I dined from home for a fortnight afterwards.
+
+And here I may remark, that what I underwent from Mrs. Crupp, in
+consequence of the tyranny she established over me, was dreadful. I
+never was so much afraid of anyone. We made a compromise of everything.
+If I hesitated, she was taken with that wonderful disorder which was
+always lying in ambush in her system, ready, at the shortest notice, to
+prey upon her vitals. If I rang the bell impatiently, after half-a-dozen
+unavailing modest pulls, and she appeared at last--which was not by any
+means to be relied upon--she would appear with a reproachful aspect,
+sink breathless on a chair near the door, lay her hand upon her nankeen
+bosom, and become so ill, that I was glad, at any sacrifice of brandy or
+anything else, to get rid of her. If I objected to having my bed made at
+five o'clock in the afternoon--which I do still think an uncomfortable
+arrangement--one motion of her hand towards the same nankeen region of
+wounded sensibility was enough to make me falter an apology. In short,
+I would have done anything in an honourable way rather than give Mrs.
+Crupp offence; and she was the terror of my life.
+
+I bought a second-hand dumb-waiter for this dinner-party, in preference
+to re-engaging the handy young man; against whom I had conceived a
+prejudice, in consequence of meeting him in the Strand, one Sunday
+morning, in a waistcoat remarkably like one of mine, which had been
+missing since the former occasion. The 'young gal' was re-engaged; but
+on the stipulation that she should only bring in the dishes, and then
+withdraw to the landing-place, beyond the outer door; where a habit of
+sniffing she had contracted would be lost upon the guests, and where her
+retiring on the plates would be a physical impossibility.
+
+Having laid in the materials for a bowl of punch, to be compounded
+by Mr. Micawber; having provided a bottle of lavender-water, two
+wax-candles, a paper of mixed pins, and a pincushion, to assist Mrs.
+Micawber in her toilette at my dressing-table; having also caused the
+fire in my bedroom to be lighted for Mrs. Micawber's convenience; and
+having laid the cloth with my own hands, I awaited the result with
+composure.
+
+At the appointed time, my three visitors arrived together. Mr. Micawber
+with more shirt-collar than usual, and a new ribbon to his eye-glass;
+Mrs. Micawber with her cap in a whitey-brown paper parcel; Traddles
+carrying the parcel, and supporting Mrs. Micawber on his arm. They were
+all delighted with my residence. When I conducted Mrs. Micawber to my
+dressing-table, and she saw the scale on which it was prepared for her,
+she was in such raptures, that she called Mr. Micawber to come in and
+look.
+
+'My dear Copperfield,' said Mr. Micawber, 'this is luxurious. This is a
+way of life which reminds me of the period when I was myself in a state
+of celibacy, and Mrs. Micawber had not yet been solicited to plight her
+faith at the Hymeneal altar.'
+
+'He means, solicited by him, Mr. Copperfield,' said Mrs. Micawber,
+archly. 'He cannot answer for others.'
+
+'My dear,' returned Mr. Micawber with sudden seriousness, 'I have no
+desire to answer for others. I am too well aware that when, in the
+inscrutable decrees of Fate, you were reserved for me, it is possible
+you may have been reserved for one, destined, after a protracted
+struggle, at length to fall a victim to pecuniary involvements of a
+complicated nature. I understand your allusion, my love. I regret it,
+but I can bear it.'
+
+'Micawber!' exclaimed Mrs. Micawber, in tears. 'Have I deserved this! I,
+who never have deserted you; who never WILL desert you, Micawber!' 'My
+love,' said Mr. Micawber, much affected, 'you will forgive, and our old
+and tried friend Copperfield will, I am sure, forgive, the momentary
+laceration of a wounded spirit, made sensitive by a recent collision
+with the Minion of Power--in other words, with a ribald Turncock
+attached to the water-works--and will pity, not condemn, its excesses.'
+
+Mr. Micawber then embraced Mrs. Micawber, and pressed my hand; leaving
+me to infer from this broken allusion that his domestic supply of
+water had been cut off that afternoon, in consequence of default in the
+payment of the company's rates.
+
+To divert his thoughts from this melancholy subject, I informed Mr.
+Micawber that I relied upon him for a bowl of punch, and led him to
+the lemons. His recent despondency, not to say despair, was gone in a
+moment. I never saw a man so thoroughly enjoy himself amid the fragrance
+of lemon-peel and sugar, the odour of burning rum, and the steam of
+boiling water, as Mr. Micawber did that afternoon. It was wonderful to
+see his face shining at us out of a thin cloud of these delicate fumes,
+as he stirred, and mixed, and tasted, and looked as if he were making,
+instead of punch, a fortune for his family down to the latest posterity.
+As to Mrs. Micawber, I don't know whether it was the effect of the cap,
+or the lavender-water, or the pins, or the fire, or the wax-candles, but
+she came out of my room, comparatively speaking, lovely. And the lark
+was never gayer than that excellent woman.
+
+I suppose--I never ventured to inquire, but I suppose--that Mrs. Crupp,
+after frying the soles, was taken ill. Because we broke down at that
+point. The leg of mutton came up very red within, and very pale without:
+besides having a foreign substance of a gritty nature sprinkled over
+it, as if if had had a fall into the ashes of that remarkable kitchen
+fireplace. But we were not in condition to judge of this fact from the
+appearance of the gravy, forasmuch as the 'young gal' had dropped it all
+upon the stairs--where it remained, by the by, in a long train, until it
+was worn out. The pigeon-pie was not bad, but it was a delusive pie: the
+crust being like a disappointing head, phrenologically speaking: full
+of lumps and bumps, with nothing particular underneath. In short, the
+banquet was such a failure that I should have been quite unhappy--about
+the failure, I mean, for I was always unhappy about Dora--if I had not
+been relieved by the great good humour of my company, and by a bright
+suggestion from Mr. Micawber.
+
+'My dear friend Copperfield,' said Mr. Micawber, 'accidents will occur
+in the best-regulated families; and in families not regulated by that
+pervading influence which sanctifies while it enhances the--a--I would
+say, in short, by the influence of Woman, in the lofty character of
+Wife, they may be expected with confidence, and must be borne with
+philosophy. If you will allow me to take the liberty of remarking that
+there are few comestibles better, in their way, than a Devil, and that
+I believe, with a little division of labour, we could accomplish a good
+one if the young person in attendance could produce a gridiron, I would
+put it to you, that this little misfortune may be easily repaired.'
+
+There was a gridiron in the pantry, on which my morning rasher of
+bacon was cooked. We had it in, in a twinkling, and immediately applied
+ourselves to carrying Mr. Micawber's idea into effect. The division of
+labour to which he had referred was this:--Traddles cut the mutton into
+slices; Mr. Micawber (who could do anything of this sort to perfection)
+covered them with pepper, mustard, salt, and cayenne; I put them on
+the gridiron, turned them with a fork, and took them off, under Mr.
+Micawber's direction; and Mrs. Micawber heated, and continually stirred,
+some mushroom ketchup in a little saucepan. When we had slices enough
+done to begin upon, we fell-to, with our sleeves still tucked up at the
+wrist, more slices sputtering and blazing on the fire, and our attention
+divided between the mutton on our plates, and the mutton then preparing.
+
+What with the novelty of this cookery, the excellence of it, the bustle
+of it, the frequent starting up to look after it, the frequent sitting
+down to dispose of it as the crisp slices came off the gridiron hot and
+hot, the being so busy, so flushed with the fire, so amused, and in the
+midst of such a tempting noise and savour, we reduced the leg of mutton
+to the bone. My own appetite came back miraculously. I am ashamed to
+record it, but I really believe I forgot Dora for a little while. I am
+satisfied that Mr. and Mrs. Micawber could not have enjoyed the
+feast more, if they had sold a bed to provide it. Traddles laughed as
+heartily, almost the whole time, as he ate and worked. Indeed we all
+did, all at once; and I dare say there was never a greater success.
+
+We were at the height of our enjoyment, and were all busily engaged, in
+our several departments, endeavouring to bring the last batch of slices
+to a state of perfection that should crown the feast, when I was aware
+of a strange presence in the room, and my eyes encountered those of the
+staid Littimer, standing hat in hand before me.
+
+'What's the matter?' I involuntarily asked.
+
+'I beg your pardon, sir, I was directed to come in. Is my master not
+here, sir?'
+
+'No.'
+
+'Have you not seen him, sir?'
+
+'No; don't you come from him?'
+
+'Not immediately so, sir.'
+
+'Did he tell you you would find him here?'
+
+'Not exactly so, sir. But I should think he might be here tomorrow, as
+he has not been here today.' 'Is he coming up from Oxford?'
+
+'I beg, sir,' he returned respectfully, 'that you will be seated, and
+allow me to do this.' With which he took the fork from my unresisting
+hand, and bent over the gridiron, as if his whole attention were
+concentrated on it.
+
+We should not have been much discomposed, I dare say, by the appearance
+of Steerforth himself, but we became in a moment the meekest of the meek
+before his respectable serving-man. Mr. Micawber, humming a tune, to
+show that he was quite at ease, subsided into his chair, with the handle
+of a hastily concealed fork sticking out of the bosom of his coat, as
+if he had stabbed himself. Mrs. Micawber put on her brown gloves, and
+assumed a genteel languor. Traddles ran his greasy hands through
+his hair, and stood it bolt upright, and stared in confusion on the
+table-cloth. As for me, I was a mere infant at the head of my own table;
+and hardly ventured to glance at the respectable phenomenon, who had
+come from Heaven knows where, to put my establishment to rights.
+
+Meanwhile he took the mutton off the gridiron, and gravely handed it
+round. We all took some, but our appreciation of it was gone, and we
+merely made a show of eating it. As we severally pushed away our plates,
+he noiselessly removed them, and set on the cheese. He took that off,
+too, when it was done with; cleared the table; piled everything on the
+dumb-waiter; gave us our wine-glasses; and, of his own accord, wheeled
+the dumb-waiter into the pantry. All this was done in a perfect manner,
+and he never raised his eyes from what he was about. Yet his very
+elbows, when he had his back towards me, seemed to teem with the
+expression of his fixed opinion that I was extremely young.
+
+'Can I do anything more, sir?'
+
+I thanked him and said, No; but would he take no dinner himself?
+
+'None, I am obliged to you, sir.'
+
+'Is Mr. Steerforth coming from Oxford?'
+
+'I beg your pardon, sir?'
+
+'Is Mr. Steerforth coming from Oxford?'
+
+'I should imagine that he might be here tomorrow, sir. I rather thought
+he might have been here today, sir. The mistake is mine, no doubt, sir.'
+
+'If you should see him first--' said I.
+
+'If you'll excuse me, sir, I don't think I shall see him first.'
+
+'In case you do,' said I, 'pray say that I am sorry he was not here
+today, as an old schoolfellow of his was here.'
+
+'Indeed, sir!' and he divided a bow between me and Traddles, with a
+glance at the latter.
+
+He was moving softly to the door, when, in a forlorn hope of saying
+something naturally--which I never could, to this man--I said:
+
+'Oh! Littimer!'
+
+'Sir!'
+
+'Did you remain long at Yarmouth, that time?'
+
+'Not particularly so, sir.'
+
+'You saw the boat completed?'
+
+'Yes, sir. I remained behind on purpose to see the boat completed.'
+
+'I know!' He raised his eyes to mine respectfully.
+
+'Mr. Steerforth has not seen it yet, I suppose?'
+
+'I really can't say, sir. I think--but I really can't say, sir. I wish
+you good night, sir.'
+
+He comprehended everybody present, in the respectful bow with which he
+followed these words, and disappeared. My visitors seemed to breathe
+more freely when he was gone; but my own relief was very great, for
+besides the constraint, arising from that extraordinary sense of
+being at a disadvantage which I always had in this man's presence, my
+conscience had embarrassed me with whispers that I had mistrusted his
+master, and I could not repress a vague uneasy dread that he might
+find it out. How was it, having so little in reality to conceal, that I
+always DID feel as if this man were finding me out?
+
+Mr. Micawber roused me from this reflection, which was blended with
+a certain remorseful apprehension of seeing Steerforth himself, by
+bestowing many encomiums on the absent Littimer as a most respectable
+fellow, and a thoroughly admirable servant. Mr. Micawber, I may remark,
+had taken his full share of the general bow, and had received it with
+infinite condescension.
+
+'But punch, my dear Copperfield,' said Mr. Micawber, tasting it, 'like
+time and tide, waits for no man. Ah! it is at the present moment in high
+flavour. My love, will you give me your opinion?'
+
+Mrs. Micawber pronounced it excellent.
+
+'Then I will drink,' said Mr. Micawber, 'if my friend Copperfield
+will permit me to take that social liberty, to the days when my friend
+Copperfield and myself were younger, and fought our way in the world
+side by side. I may say, of myself and Copperfield, in words we have
+sung together before now, that
+
+    We twa hae run about the braes
+    And pu'd the gowans' fine
+--in a figurative point of view--on several occasions. I am not exactly
+aware,' said Mr. Micawber, with the old roll in his voice, and the old
+indescribable air of saying something genteel, 'what gowans may be, but
+I have no doubt that Copperfield and myself would frequently have taken
+a pull at them, if it had been feasible.'
+
+Mr. Micawber, at the then present moment, took a pull at his punch. So
+we all did: Traddles evidently lost in wondering at what distant time
+Mr. Micawber and I could have been comrades in the battle of the world.
+
+'Ahem!' said Mr. Micawber, clearing his throat, and warming with the
+punch and with the fire. 'My dear, another glass?'
+
+Mrs. Micawber said it must be very little; but we couldn't allow that,
+so it was a glassful.
+
+'As we are quite confidential here, Mr. Copperfield,' said Mrs.
+Micawber, sipping her punch, 'Mr. Traddles being a part of our
+domesticity, I should much like to have your opinion on Mr. Micawber's
+prospects. For corn,' said Mrs. Micawber argumentatively, 'as I have
+repeatedly said to Mr. Micawber, may be gentlemanly, but it is not
+remunerative. Commission to the extent of two and ninepence in
+a fortnight cannot, however limited our ideas, be considered
+remunerative.'
+
+We were all agreed upon that.
+
+'Then,' said Mrs. Micawber, who prided herself on taking a clear view of
+things, and keeping Mr. Micawber straight by her woman's wisdom, when he
+might otherwise go a little crooked, 'then I ask myself this question.
+If corn is not to be relied upon, what is? Are coals to be relied upon?
+Not at all. We have turned our attention to that experiment, on the
+suggestion of my family, and we find it fallacious.'
+
+Mr. Micawber, leaning back in his chair with his hands in his pockets,
+eyed us aside, and nodded his head, as much as to say that the case was
+very clearly put.
+
+'The articles of corn and coals,' said Mrs. Micawber, still more
+argumentatively, 'being equally out of the question, Mr. Copperfield,
+I naturally look round the world, and say, "What is there in which a
+person of Mr. Micawber's talent is likely to succeed?" And I exclude
+the doing anything on commission, because commission is not a certainty.
+What is best suited to a person of Mr. Micawber's peculiar temperament
+is, I am convinced, a certainty.'
+
+Traddles and I both expressed, by a feeling murmur, that this great
+discovery was no doubt true of Mr. Micawber, and that it did him much
+credit.
+
+'I will not conceal from you, my dear Mr. Copperfield,' said Mrs.
+Micawber, 'that I have long felt the Brewing business to be particularly
+adapted to Mr. Micawber. Look at Barclay and Perkins! Look at Truman,
+Hanbury, and Buxton! It is on that extensive footing that Mr. Micawber,
+I know from my own knowledge of him, is calculated to shine; and the
+profits, I am told, are e-NOR-MOUS! But if Mr. Micawber cannot get into
+those firms--which decline to answer his letters, when he offers his
+services even in an inferior capacity--what is the use of dwelling upon
+that idea? None. I may have a conviction that Mr. Micawber's manners--'
+
+'Hem! Really, my dear,' interposed Mr. Micawber.
+
+'My love, be silent,' said Mrs. Micawber, laying her brown glove on his
+hand. 'I may have a conviction, Mr. Copperfield, that Mr. Micawber's
+manners peculiarly qualify him for the Banking business. I may argue
+within myself, that if I had a deposit at a banking-house, the manners
+of Mr. Micawber, as representing that banking-house, would inspire
+confidence, and must extend the connexion. But if the various
+banking-houses refuse to avail themselves of Mr. Micawber's abilities,
+or receive the offer of them with contumely, what is the use of dwelling
+upon THAT idea? None. As to originating a banking-business, I may know
+that there are members of my family who, if they chose to place their
+money in Mr. Micawber's hands, might found an establishment of that
+description. But if they do NOT choose to place their money in Mr.
+Micawber's hands--which they don't--what is the use of that? Again I
+contend that we are no farther advanced than we were before.'
+
+I shook my head, and said, 'Not a bit.' Traddles also shook his head,
+and said, 'Not a bit.'
+
+'What do I deduce from this?' Mrs. Micawber went on to say, still with
+the same air of putting a case lucidly. 'What is the conclusion, my
+dear Mr. Copperfield, to which I am irresistibly brought? Am I wrong in
+saying, it is clear that we must live?'
+
+I answered 'Not at all!' and Traddles answered 'Not at all!' and I found
+myself afterwards sagely adding, alone, that a person must either live
+or die.
+
+'Just so,' returned Mrs. Micawber, 'It is precisely that. And the fact
+is, my dear Mr. Copperfield, that we can not live without something
+widely different from existing circumstances shortly turning up. Now
+I am convinced, myself, and this I have pointed out to Mr. Micawber
+several times of late, that things cannot be expected to turn up of
+themselves. We must, in a measure, assist to turn them up. I may be
+wrong, but I have formed that opinion.'
+
+Both Traddles and I applauded it highly.
+
+'Very well,' said Mrs. Micawber. 'Then what do I recommend? Here is Mr.
+Micawber with a variety of qualifications--with great talent--'
+
+'Really, my love,' said Mr. Micawber.
+
+'Pray, my dear, allow me to conclude. Here is Mr. Micawber, with a
+variety of qualifications, with great talent--I should say, with genius,
+but that may be the partiality of a wife--'
+
+Traddles and I both murmured 'No.'
+
+'And here is Mr. Micawber without any suitable position or employment.
+Where does that responsibility rest? Clearly on society. Then I would
+make a fact so disgraceful known, and boldly challenge society to set it
+right. It appears to me, my dear Mr. Copperfield,' said Mrs. Micawber,
+forcibly, 'that what Mr. Micawber has to do, is to throw down the
+gauntlet to society, and say, in effect, "Show me who will take that up.
+Let the party immediately step forward."'
+
+I ventured to ask Mrs. Micawber how this was to be done.
+
+'By advertising,' said Mrs. Micawber--'in all the papers. It appears to
+me, that what Mr. Micawber has to do, in justice to himself, in justice
+to his family, and I will even go so far as to say in justice to
+society, by which he has been hitherto overlooked, is to advertise in
+all the papers; to describe himself plainly as so-and-so, with such and
+such qualifications and to put it thus: "Now employ me, on remunerative
+terms, and address, post-paid, to W. M., Post Office, Camden Town."'
+
+'This idea of Mrs. Micawber's, my dear Copperfield,' said Mr. Micawber,
+making his shirt-collar meet in front of his chin, and glancing at me
+sideways, 'is, in fact, the Leap to which I alluded, when I last had the
+pleasure of seeing you.'
+
+'Advertising is rather expensive,' I remarked, dubiously.
+
+'Exactly so!' said Mrs. Micawber, preserving the same logical air.
+'Quite true, my dear Mr. Copperfield! I have made the identical
+observation to Mr. Micawber. It is for that reason especially, that I
+think Mr. Micawber ought (as I have already said, in justice to himself,
+in justice to his family, and in justice to society) to raise a certain
+sum of money--on a bill.'
+
+Mr. Micawber, leaning back in his chair, trifled with his eye-glass
+and cast his eyes up at the ceiling; but I thought him observant of
+Traddles, too, who was looking at the fire.
+
+'If no member of my family,' said Mrs. Micawber, 'is possessed of
+sufficient natural feeling to negotiate that bill--I believe there is a
+better business-term to express what I mean--'
+
+Mr. Micawber, with his eyes still cast up at the ceiling, suggested
+'Discount.'
+
+'To discount that bill,' said Mrs. Micawber, 'then my opinion is, that
+Mr. Micawber should go into the City, should take that bill into the
+Money Market, and should dispose of it for what he can get. If the
+individuals in the Money Market oblige Mr. Micawber to sustain a great
+sacrifice, that is between themselves and their consciences. I view
+it, steadily, as an investment. I recommend Mr. Micawber, my dear Mr.
+Copperfield, to do the same; to regard it as an investment which is sure
+of return, and to make up his mind to any sacrifice.'
+
+I felt, but I am sure I don't know why, that this was self-denying
+and devoted in Mrs. Micawber, and I uttered a murmur to that effect.
+Traddles, who took his tone from me, did likewise, still looking at the
+fire.
+
+'I will not,' said Mrs. Micawber, finishing her punch, and gathering her
+scarf about her shoulders, preparatory to her withdrawal to my bedroom:
+'I will not protract these remarks on the subject of Mr. Micawber's
+pecuniary affairs. At your fireside, my dear Mr. Copperfield, and in the
+presence of Mr. Traddles, who, though not so old a friend, is quite one
+of ourselves, I could not refrain from making you acquainted with the
+course I advise Mr. Micawber to take. I feel that the time is arrived
+when Mr. Micawber should exert himself and--I will add--assert himself,
+and it appears to me that these are the means. I am aware that I am
+merely a female, and that a masculine judgement is usually considered
+more competent to the discussion of such questions; still I must not
+forget that, when I lived at home with my papa and mama, my papa was in
+the habit of saying, "Emma's form is fragile, but her grasp of a subject
+is inferior to none." That my papa was too partial, I well know; but
+that he was an observer of character in some degree, my duty and my
+reason equally forbid me to doubt.'
+
+With these words, and resisting our entreaties that she would grace
+the remaining circulation of the punch with her presence, Mrs. Micawber
+retired to my bedroom. And really I felt that she was a noble woman--the
+sort of woman who might have been a Roman matron, and done all manner of
+heroic things, in times of public trouble.
+
+In the fervour of this impression, I congratulated Mr. Micawber on the
+treasure he possessed. So did Traddles. Mr. Micawber extended his
+hand to each of us in succession, and then covered his face with his
+pocket-handkerchief, which I think had more snuff upon it than he
+was aware of. He then returned to the punch, in the highest state of
+exhilaration.
+
+He was full of eloquence. He gave us to understand that in our children
+we lived again, and that, under the pressure of pecuniary difficulties,
+any accession to their number was doubly welcome. He said that Mrs.
+Micawber had latterly had her doubts on this point, but that he had
+dispelled them, and reassured her. As to her family, they were totally
+unworthy of her, and their sentiments were utterly indifferent to him,
+and they might--I quote his own expression--go to the Devil.
+
+Mr. Micawber then delivered a warm eulogy on Traddles. He said
+Traddles's was a character, to the steady virtues of which he (Mr.
+Micawber) could lay no claim, but which, he thanked Heaven, he could
+admire. He feelingly alluded to the young lady, unknown, whom Traddles
+had honoured with his affection, and who had reciprocated that affection
+by honouring and blessing Traddles with her affection. Mr. Micawber
+pledged her. So did I. Traddles thanked us both, by saying, with a
+simplicity and honesty I had sense enough to be quite charmed with,
+'I am very much obliged to you indeed. And I do assure you, she's the
+dearest girl!--'
+
+Mr. Micawber took an early opportunity, after that, of hinting, with the
+utmost delicacy and ceremony, at the state of MY affections. Nothing
+but the serious assurance of his friend Copperfield to the contrary,
+he observed, could deprive him of the impression that his friend
+Copperfield loved and was beloved. After feeling very hot and
+uncomfortable for some time, and after a good deal of blushing,
+stammering, and denying, I said, having my glass in my hand, 'Well! I
+would give them D.!' which so excited and gratified Mr. Micawber,
+that he ran with a glass of punch into my bedroom, in order that Mrs.
+Micawber might drink D., who drank it with enthusiasm, crying from
+within, in a shrill voice, 'Hear, hear! My dear Mr. Copperfield, I am
+delighted. Hear!' and tapping at the wall, by way of applause.
+
+Our conversation, afterwards, took a more worldly turn; Mr. Micawber
+telling us that he found Camden Town inconvenient, and that the first
+thing he contemplated doing, when the advertisement should have been the
+cause of something satisfactory turning up, was to move. He mentioned
+a terrace at the western end of Oxford Street, fronting Hyde Park, on
+which he had always had his eye, but which he did not expect to attain
+immediately, as it would require a large establishment. There would
+probably be an interval, he explained, in which he should content
+himself with the upper part of a house, over some respectable place of
+business--say in Piccadilly,--which would be a cheerful situation for
+Mrs. Micawber; and where, by throwing out a bow-window, or carrying up
+the roof another story, or making some little alteration of that sort,
+they might live, comfortably and reputably, for a few years. Whatever
+was reserved for him, he expressly said, or wherever his abode might be,
+we might rely on this--there would always be a room for Traddles, and a
+knife and fork for me. We acknowledged his kindness; and he begged us
+to forgive his having launched into these practical and business-like
+details, and to excuse it as natural in one who was making entirely new
+arrangements in life.
+
+Mrs. Micawber, tapping at the wall again to know if tea were ready,
+broke up this particular phase of our friendly conversation. She made
+tea for us in a most agreeable manner; and, whenever I went near her, in
+handing about the tea-cups and bread-and-butter, asked me, in a whisper,
+whether D. was fair, or dark, or whether she was short, or tall: or
+something of that kind; which I think I liked. After tea, we discussed a
+variety of topics before the fire; and Mrs. Micawber was good enough
+to sing us (in a small, thin, flat voice, which I remembered to have
+considered, when I first knew her, the very table-beer of acoustics) the
+favourite ballads of 'The Dashing White Sergeant', and 'Little Tafflin'.
+For both of these songs Mrs. Micawber had been famous when she lived at
+home with her papa and mama. Mr. Micawber told us, that when he heard
+her sing the first one, on the first occasion of his seeing her beneath
+the parental roof, she had attracted his attention in an extraordinary
+degree; but that when it came to Little Tafflin, he had resolved to win
+that woman or perish in the attempt.
+
+It was between ten and eleven o'clock when Mrs. Micawber rose to replace
+her cap in the whitey-brown paper parcel, and to put on her bonnet. Mr.
+Micawber took the opportunity of Traddles putting on his great-coat, to
+slip a letter into my hand, with a whispered request that I would read
+it at my leisure. I also took the opportunity of my holding a candle
+over the banisters to light them down, when Mr. Micawber was going
+first, leading Mrs. Micawber, and Traddles was following with the cap,
+to detain Traddles for a moment on the top of the stairs.
+
+'Traddles,' said I, 'Mr. Micawber don't mean any harm, poor fellow: but,
+if I were you, I wouldn't lend him anything.'
+
+'My dear Copperfield,' returned Traddles, smiling, 'I haven't got
+anything to lend.'
+
+'You have got a name, you know,' said I.
+
+'Oh! You call THAT something to lend?' returned Traddles, with a
+thoughtful look.
+
+'Certainly.'
+
+'Oh!' said Traddles. 'Yes, to be sure! I am very much obliged to you,
+Copperfield; but--I am afraid I have lent him that already.'
+
+'For the bill that is to be a certain investment?' I inquired.
+
+'No,' said Traddles. 'Not for that one. This is the first I have heard
+of that one. I have been thinking that he will most likely propose that
+one, on the way home. Mine's another.'
+
+'I hope there will be nothing wrong about it,' said I. 'I hope not,'
+said Traddles. 'I should think not, though, because he told me, only the
+other day, that it was provided for. That was Mr. Micawber's expression,
+"Provided for."'
+
+Mr. Micawber looking up at this juncture to where we were standing, I
+had only time to repeat my caution. Traddles thanked me, and descended.
+But I was much afraid, when I observed the good-natured manner in which
+he went down with the cap in his hand, and gave Mrs. Micawber his arm,
+that he would be carried into the Money Market neck and heels.
+
+I returned to my fireside, and was musing, half gravely and half
+laughing, on the character of Mr. Micawber and the old relations between
+us, when I heard a quick step ascending the stairs. At first, I thought
+it was Traddles coming back for something Mrs. Micawber had left behind;
+but as the step approached, I knew it, and felt my heart beat high, and
+the blood rush to my face, for it was Steerforth's.
+
+I was never unmindful of Agnes, and she never left that sanctuary in my
+thoughts--if I may call it so--where I had placed her from the first.
+But when he entered, and stood before me with his hand out, the darkness
+that had fallen on him changed to light, and I felt confounded and
+ashamed of having doubted one I loved so heartily. I loved her none the
+less; I thought of her as the same benignant, gentle angel in my life; I
+reproached myself, not her, with having done him an injury; and I would
+have made him any atonement if I had known what to make, and how to make
+it.
+
+'Why, Daisy, old boy, dumb-foundered!' laughed Steerforth, shaking
+my hand heartily, and throwing it gaily away. 'Have I detected you in
+another feast, you Sybarite! These Doctors' Commons fellows are the
+gayest men in town, I believe, and beat us sober Oxford people all to
+nothing!' His bright glance went merrily round the room, as he took
+the seat on the sofa opposite to me, which Mrs. Micawber had recently
+vacated, and stirred the fire into a blaze.
+
+'I was so surprised at first,' said I, giving him welcome with all
+the cordiality I felt, 'that I had hardly breath to greet you with,
+Steerforth.'
+
+'Well, the sight of me is good for sore eyes, as the Scotch say,'
+replied Steerforth, 'and so is the sight of you, Daisy, in full bloom.
+How are you, my Bacchanal?'
+
+'I am very well,' said I; 'and not at all Bacchanalian tonight, though I
+confess to another party of three.'
+
+'All of whom I met in the street, talking loud in your praise,' returned
+Steerforth. 'Who's our friend in the tights?'
+
+I gave him the best idea I could, in a few words, of Mr. Micawber. He
+laughed heartily at my feeble portrait of that gentleman, and said he
+was a man to know, and he must know him. 'But who do you suppose our
+other friend is?' said I, in my turn.
+
+'Heaven knows,' said Steerforth. 'Not a bore, I hope? I thought he
+looked a little like one.'
+
+'Traddles!' I replied, triumphantly.
+
+'Who's he?' asked Steerforth, in his careless way.
+
+'Don't you remember Traddles? Traddles in our room at Salem House?'
+
+'Oh! That fellow!' said Steerforth, beating a lump of coal on the top
+of the fire, with the poker. 'Is he as soft as ever? And where the deuce
+did you pick him up?'
+
+I extolled Traddles in reply, as highly as I could; for I felt that
+Steerforth rather slighted him. Steerforth, dismissing the subject with
+a light nod, and a smile, and the remark that he would be glad to see
+the old fellow too, for he had always been an odd fish, inquired if I
+could give him anything to eat? During most of this short dialogue, when
+he had not been speaking in a wild vivacious manner, he had sat idly
+beating on the lump of coal with the poker. I observed that he did the
+same thing while I was getting out the remains of the pigeon-pie, and so
+forth.
+
+'Why, Daisy, here's a supper for a king!' he exclaimed, starting out of
+his silence with a burst, and taking his seat at the table. 'I shall do
+it justice, for I have come from Yarmouth.'
+
+'I thought you came from Oxford?' I returned.
+
+'Not I,' said Steerforth. 'I have been seafaring--better employed.'
+
+'Littimer was here today, to inquire for you,' I remarked, 'and I
+understood him that you were at Oxford; though, now I think of it, he
+certainly did not say so.'
+
+'Littimer is a greater fool than I thought him, to have been inquiring
+for me at all,' said Steerforth, jovially pouring out a glass of wine,
+and drinking to me. 'As to understanding him, you are a cleverer fellow
+than most of us, Daisy, if you can do that.'
+
+'That's true, indeed,' said I, moving my chair to the table. 'So you
+have been at Yarmouth, Steerforth!' interested to know all about it.
+'Have you been there long?'
+
+'No,' he returned. 'An escapade of a week or so.'
+
+'And how are they all? Of course, little Emily is not married yet?'
+
+'Not yet. Going to be, I believe--in so many weeks, or months, or
+something or other. I have not seen much of 'em. By the by'; he laid
+down his knife and fork, which he had been using with great diligence,
+and began feeling in his pockets; 'I have a letter for you.'
+
+'From whom?'
+
+'Why, from your old nurse,' he returned, taking some papers out of his
+breast pocket. "'J. Steerforth, Esquire, debtor, to The Willing
+Mind"; that's not it. Patience, and we'll find it presently. Old
+what's-his-name's in a bad way, and it's about that, I believe.'
+
+'Barkis, do you mean?'
+
+'Yes!' still feeling in his pockets, and looking over their contents:
+'it's all over with poor Barkis, I am afraid. I saw a little apothecary
+there--surgeon, or whatever he is--who brought your worship into the
+world. He was mighty learned about the case, to me; but the upshot of
+his opinion was, that the carrier was making his last journey rather
+fast.---Put your hand into the breast pocket of my great-coat on the
+chair yonder, and I think you'll find the letter. Is it there?'
+
+'Here it is!' said I.
+
+'That's right!'
+
+It was from Peggotty; something less legible than usual, and brief. It
+informed me of her husband's hopeless state, and hinted at his being
+'a little nearer' than heretofore, and consequently more difficult
+to manage for his own comfort. It said nothing of her weariness
+and watching, and praised him highly. It was written with a plain,
+unaffected, homely piety that I knew to be genuine, and ended with 'my
+duty to my ever darling'--meaning myself.
+
+While I deciphered it, Steerforth continued to eat and drink.
+
+'It's a bad job,' he said, when I had done; 'but the sun sets every day,
+and people die every minute, and we mustn't be scared by the common lot.
+If we failed to hold our own, because that equal foot at all men's doors
+was heard knocking somewhere, every object in this world would slip from
+us. No! Ride on! Rough-shod if need be, smooth-shod if that will do, but
+ride on! Ride on over all obstacles, and win the race!'
+
+'And win what race?' said I.
+
+'The race that one has started in,' said he. 'Ride on!'
+
+I noticed, I remember, as he paused, looking at me with his handsome
+head a little thrown back, and his glass raised in his hand, that,
+though the freshness of the sea-wind was on his face, and it was ruddy,
+there were traces in it, made since I last saw it, as if he had applied
+himself to some habitual strain of the fervent energy which, when
+roused, was so passionately roused within him. I had it in my thoughts
+to remonstrate with him upon his desperate way of pursuing any fancy
+that he took--such as this buffeting of rough seas, and braving of hard
+weather, for example--when my mind glanced off to the immediate subject
+of our conversation again, and pursued that instead.
+
+'I tell you what, Steerforth,' said I, 'if your high spirits will listen
+to me--'
+
+'They are potent spirits, and will do whatever you like,' he answered,
+moving from the table to the fireside again.
+
+'Then I tell you what, Steerforth. I think I will go down and see my
+old nurse. It is not that I can do her any good, or render her any real
+service; but she is so attached to me that my visit will have as much
+effect on her, as if I could do both. She will take it so kindly that it
+will be a comfort and support to her. It is no great effort to make,
+I am sure, for such a friend as she has been to me. Wouldn't you go a
+day's journey, if you were in my place?'
+
+His face was thoughtful, and he sat considering a little before he
+answered, in a low voice, 'Well! Go. You can do no harm.'
+
+'You have just come back,' said I, 'and it would be in vain to ask you
+to go with me?'
+
+'Quite,' he returned. 'I am for Highgate tonight. I have not seen
+my mother this long time, and it lies upon my conscience, for
+it's something to be loved as she loves her prodigal son.---Bah!
+Nonsense!--You mean to go tomorrow, I suppose?' he said, holding me out
+at arm's length, with a hand on each of my shoulders.
+
+'Yes, I think so.'
+
+'Well, then, don't go till next day. I wanted you to come and stay a
+few days with us. Here I am, on purpose to bid you, and you fly off to
+Yarmouth!'
+
+'You are a nice fellow to talk of flying off, Steerforth, who are always
+running wild on some unknown expedition or other!'
+
+He looked at me for a moment without speaking, and then rejoined, still
+holding me as before, and giving me a shake:
+
+'Come! Say the next day, and pass as much of tomorrow as you can with
+us! Who knows when we may meet again, else? Come! Say the next day! I
+want you to stand between Rosa Dartle and me, and keep us asunder.'
+
+'Would you love each other too much, without me?'
+
+'Yes; or hate,' laughed Steerforth; 'no matter which. Come! Say the next
+day!'
+
+I said the next day; and he put on his great-coat and lighted his cigar,
+and set off to walk home. Finding him in this intention, I put on my own
+great-coat (but did not light my own cigar, having had enough of that
+for one while) and walked with him as far as the open road: a dull road,
+then, at night. He was in great spirits all the way; and when we parted,
+and I looked after him going so gallantly and airily homeward, I thought
+of his saying, 'Ride on over all obstacles, and win the race!' and
+wished, for the first time, that he had some worthy race to run.
+
+I was undressing in my own room, when Mr. Micawber's letter tumbled on
+the floor. Thus reminded of it, I broke the seal and read as follows. It
+was dated an hour and a half before dinner. I am not sure whether I
+have mentioned that, when Mr. Micawber was at any particularly desperate
+crisis, he used a sort of legal phraseology, which he seemed to think
+equivalent to winding up his affairs.
+
+
+'SIR--for I dare not say my dear Copperfield,
+
+'It is expedient that I should inform you that the undersigned is
+Crushed. Some flickering efforts to spare you the premature knowledge of
+his calamitous position, you may observe in him this day; but hope has
+sunk beneath the horizon, and the undersigned is Crushed.
+
+'The present communication is penned within the personal range (I cannot
+call it the society) of an individual, in a state closely bordering
+on intoxication, employed by a broker. That individual is in legal
+possession of the premises, under a distress for rent. His inventory
+includes, not only the chattels and effects of every description
+belonging to the undersigned, as yearly tenant of this habitation, but
+also those appertaining to Mr. Thomas Traddles, lodger, a member of the
+Honourable Society of the Inner Temple.
+
+'If any drop of gloom were wanting in the overflowing cup, which is now
+"commended" (in the language of an immortal Writer) to the lips of the
+undersigned, it would be found in the fact, that a friendly acceptance
+granted to the undersigned, by the before-mentioned Mr. Thomas Traddles,
+for the sum Of 23l 4s 9 1/2d is over due, and is NOT provided for. Also,
+in the fact that the living responsibilities clinging to the undersigned
+will, in the course of nature, be increased by the sum of one more
+helpless victim; whose miserable appearance may be looked for--in round
+numbers--at the expiration of a period not exceeding six lunar months
+from the present date.
+
+'After premising thus much, it would be a work of supererogation to add,
+that dust and ashes are for ever scattered
+
+               'On
+                    'The
+                         'Head
+                              'Of
+                                   'WILKINS MICAWBER.'
+
+
+Poor Traddles! I knew enough of Mr. Micawber by this time, to foresee
+that he might be expected to recover the blow; but my night's rest was
+sorely distressed by thoughts of Traddles, and of the curate's daughter,
+who was one of ten, down in Devonshire, and who was such a dear girl,
+and who would wait for Traddles (ominous praise!) until she was sixty,
+or any age that could be mentioned.
+
+
+
+CHAPTER 29. I VISIT STEERFORTH AT HIS HOME, AGAIN
+
+
+I mentioned to Mr. Spenlow in the morning, that I wanted leave of
+absence for a short time; and as I was not in the receipt of any salary,
+and consequently was not obnoxious to the implacable Jorkins, there was
+no difficulty about it. I took that opportunity, with my voice sticking
+in my throat, and my sight failing as I uttered the words, to express
+my hope that Miss Spenlow was quite well; to which Mr. Spenlow replied,
+with no more emotion than if he had been speaking of an ordinary human
+being, that he was much obliged to me, and she was very well.
+
+We articled clerks, as germs of the patrician order of proctors, were
+treated with so much consideration, that I was almost my own master at
+all times. As I did not care, however, to get to Highgate before one
+or two o'clock in the day, and as we had another little excommunication
+case in court that morning, which was called The office of the judge
+promoted by Tipkins against Bullock for his soul's correction, I passed
+an hour or two in attendance on it with Mr. Spenlow very agreeably.
+It arose out of a scuffle between two churchwardens, one of whom was
+alleged to have pushed the other against a pump; the handle of which
+pump projecting into a school-house, which school-house was under a
+gable of the church-roof, made the push an ecclesiastical offence.
+It was an amusing case; and sent me up to Highgate, on the box of the
+stage-coach, thinking about the Commons, and what Mr. Spenlow had said
+about touching the Commons and bringing down the country.
+
+Mrs. Steerforth was pleased to see me, and so was Rosa Dartle. I was
+agreeably surprised to find that Littimer was not there, and that we
+were attended by a modest little parlour-maid, with blue ribbons in her
+cap, whose eye it was much more pleasant, and much less disconcerting,
+to catch by accident, than the eye of that respectable man. But what I
+particularly observed, before I had been half-an-hour in the house, was
+the close and attentive watch Miss Dartle kept upon me; and the lurking
+manner in which she seemed to compare my face with Steerforth's, and
+Steerforth's with mine, and to lie in wait for something to come out
+between the two. So surely as I looked towards her, did I see that eager
+visage, with its gaunt black eyes and searching brow, intent on mine; or
+passing suddenly from mine to Steerforth's; or comprehending both of us
+at once. In this lynx-like scrutiny she was so far from faltering when
+she saw I observed it, that at such a time she only fixed her piercing
+look upon me with a more intent expression still. Blameless as I was,
+and knew that I was, in reference to any wrong she could possibly
+suspect me of, I shrunk before her strange eyes, quite unable to endure
+their hungry lustre.
+
+All day, she seemed to pervade the whole house. If I talked to
+Steerforth in his room, I heard her dress rustle in the little gallery
+outside. When he and I engaged in some of our old exercises on the lawn
+behind the house, I saw her face pass from window to window, like a
+wandering light, until it fixed itself in one, and watched us. When we
+all four went out walking in the afternoon, she closed her thin hand on
+my arm like a spring, to keep me back, while Steerforth and his mother
+went on out of hearing: and then spoke to me.
+
+'You have been a long time,' she said, 'without coming here. Is your
+profession really so engaging and interesting as to absorb your whole
+attention? I ask because I always want to be informed, when I am
+ignorant. Is it really, though?'
+
+I replied that I liked it well enough, but that I certainly could not
+claim so much for it.
+
+'Oh! I am glad to know that, because I always like to be put right when
+I am wrong,' said Rosa Dartle. 'You mean it is a little dry, perhaps?'
+
+'Well,' I replied; 'perhaps it was a little dry.'
+
+'Oh! and that's a reason why you want relief and change--excitement and
+all that?' said she. 'Ah! very true! But isn't it a little--Eh?--for
+him; I don't mean you?'
+
+A quick glance of her eye towards the spot where Steerforth was walking,
+with his mother leaning on his arm, showed me whom she meant; but beyond
+that, I was quite lost. And I looked so, I have no doubt.
+
+'Don't it--I don't say that it does, mind I want to know--don't it
+rather engross him? Don't it make him, perhaps, a little more remiss
+than usual in his visits to his blindly-doting--eh?' With another
+quick glance at them, and such a glance at me as seemed to look into my
+innermost thoughts.
+
+'Miss Dartle,' I returned, 'pray do not think--'
+
+'I don't!' she said. 'Oh dear me, don't suppose that I think anything!
+I am not suspicious. I only ask a question. I don't state any opinion. I
+want to found an opinion on what you tell me. Then, it's not so? Well! I
+am very glad to know it.'
+
+'It certainly is not the fact,' said I, perplexed, 'that I am
+accountable for Steerforth's having been away from home longer than
+usual--if he has been: which I really don't know at this moment, unless
+I understand it from you. I have not seen him this long while, until
+last night.'
+
+'No?'
+
+'Indeed, Miss Dartle, no!'
+
+As she looked full at me, I saw her face grow sharper and paler, and the
+marks of the old wound lengthen out until it cut through the disfigured
+lip, and deep into the nether lip, and slanted down the face. There was
+something positively awful to me in this, and in the brightness of her
+eyes, as she said, looking fixedly at me:
+
+'What is he doing?'
+
+I repeated the words, more to myself than her, being so amazed.
+
+'What is he doing?' she said, with an eagerness that seemed enough to
+consume her like a fire. 'In what is that man assisting him, who never
+looks at me without an inscrutable falsehood in his eyes? If you are
+honourable and faithful, I don't ask you to betray your friend. I ask
+you only to tell me, is it anger, is it hatred, is it pride, is it
+restlessness, is it some wild fancy, is it love, what is it, that is
+leading him?'
+
+'Miss Dartle,' I returned, 'how shall I tell you, so that you will
+believe me, that I know of nothing in Steerforth different from what
+there was when I first came here? I can think of nothing. I firmly
+believe there is nothing. I hardly understand even what you mean.'
+
+As she still stood looking fixedly at me, a twitching or throbbing,
+from which I could not dissociate the idea of pain, came into that cruel
+mark; and lifted up the corner of her lip as if with scorn, or with a
+pity that despised its object. She put her hand upon it hurriedly--a
+hand so thin and delicate, that when I had seen her hold it up before
+the fire to shade her face, I had compared it in my thoughts to fine
+porcelain--and saying, in a quick, fierce, passionate way, 'I swear you
+to secrecy about this!' said not a word more.
+
+Mrs. Steerforth was particularly happy in her son's society, and
+Steerforth was, on this occasion, particularly attentive and respectful
+to her. It was very interesting to me to see them together, not only on
+account of their mutual affection, but because of the strong personal
+resemblance between them, and the manner in which what was haughty or
+impetuous in him was softened by age and sex, in her, to a gracious
+dignity. I thought, more than once, that it was well no serious cause of
+division had ever come between them; or two such natures--I ought rather
+to express it, two such shades of the same nature--might have been
+harder to reconcile than the two extremest opposites in creation. The
+idea did not originate in my own discernment, I am bound to confess, but
+in a speech of Rosa Dartle's.
+
+She said at dinner:
+
+'Oh, but do tell me, though, somebody, because I have been thinking
+about it all day, and I want to know.'
+
+'You want to know what, Rosa?' returned Mrs. Steerforth. 'Pray, pray,
+Rosa, do not be mysterious.'
+
+'Mysterious!' she cried. 'Oh! really? Do you consider me so?'
+
+'Do I constantly entreat you,' said Mrs. Steerforth, 'to speak plainly,
+in your own natural manner?'
+
+'Oh! then this is not my natural manner?' she rejoined. 'Now you must
+really bear with me, because I ask for information. We never know
+ourselves.'
+
+'It has become a second nature,' said Mrs. Steerforth, without any
+displeasure; 'but I remember,--and so must you, I think,--when your
+manner was different, Rosa; when it was not so guarded, and was more
+trustful.'
+
+'I am sure you are right,' she returned; 'and so it is that bad habits
+grow upon one! Really? Less guarded and more trustful? How can I,
+imperceptibly, have changed, I wonder! Well, that's very odd! I must
+study to regain my former self.'
+
+'I wish you would,' said Mrs. Steerforth, with a smile.
+
+'Oh! I really will, you know!' she answered. 'I will learn frankness
+from--let me see--from James.'
+
+'You cannot learn frankness, Rosa,' said Mrs. Steerforth quickly--for
+there was always some effect of sarcasm in what Rosa Dartle said,
+though it was said, as this was, in the most unconscious manner in the
+world--'in a better school.'
+
+'That I am sure of,' she answered, with uncommon fervour. 'If I am sure
+of anything, of course, you know, I am sure of that.'
+
+Mrs. Steerforth appeared to me to regret having been a little nettled;
+for she presently said, in a kind tone:
+
+'Well, my dear Rosa, we have not heard what it is that you want to be
+satisfied about?'
+
+'That I want to be satisfied about?' she replied, with provoking
+coldness. 'Oh! It was only whether people, who are like each other in
+their moral constitution--is that the phrase?'
+
+'It's as good a phrase as another,' said Steerforth.
+
+'Thank you:--whether people, who are like each other in their moral
+constitution, are in greater danger than people not so circumstanced,
+supposing any serious cause of variance to arise between them, of being
+divided angrily and deeply?'
+
+'I should say yes,' said Steerforth.
+
+'Should you?' she retorted. 'Dear me! Supposing then, for instance--any
+unlikely thing will do for a supposition--that you and your mother were
+to have a serious quarrel.'
+
+'My dear Rosa,' interposed Mrs. Steerforth, laughing good-naturedly,
+'suggest some other supposition! James and I know our duty to each other
+better, I pray Heaven!'
+
+'Oh!' said Miss Dartle, nodding her head thoughtfully. 'To be sure. That
+would prevent it? Why, of course it would. Exactly. Now, I am glad I
+have been so foolish as to put the case, for it is so very good to know
+that your duty to each other would prevent it! Thank you very much.'
+
+One other little circumstance connected with Miss Dartle I must
+not omit; for I had reason to remember it thereafter, when all the
+irremediable past was rendered plain. During the whole of this day, but
+especially from this period of it, Steerforth exerted himself with his
+utmost skill, and that was with his utmost ease, to charm this singular
+creature into a pleasant and pleased companion. That he should succeed,
+was no matter of surprise to me. That she should struggle against the
+fascinating influence of his delightful art--delightful nature I thought
+it then--did not surprise me either; for I knew that she was sometimes
+jaundiced and perverse. I saw her features and her manner slowly change;
+I saw her look at him with growing admiration; I saw her try, more and
+more faintly, but always angrily, as if she condemned a weakness in
+herself, to resist the captivating power that he possessed; and finally,
+I saw her sharp glance soften, and her smile become quite gentle, and I
+ceased to be afraid of her as I had really been all day, and we all sat
+about the fire, talking and laughing together, with as little reserve as
+if we had been children.
+
+Whether it was because we had sat there so long, or because Steerforth
+was resolved not to lose the advantage he had gained, I do not know; but
+we did not remain in the dining-room more than five minutes after her
+departure. 'She is playing her harp,' said Steerforth, softly, at the
+drawing-room door, 'and nobody but my mother has heard her do that, I
+believe, these three years.' He said it with a curious smile, which was
+gone directly; and we went into the room and found her alone.
+
+'Don't get up,' said Steerforth (which she had already done)' my dear
+Rosa, don't! Be kind for once, and sing us an Irish song.'
+
+'What do you care for an Irish song?' she returned.
+
+'Much!' said Steerforth. 'Much more than for any other. Here is Daisy,
+too, loves music from his soul. Sing us an Irish song, Rosa! and let me
+sit and listen as I used to do.'
+
+He did not touch her, or the chair from which she had risen, but sat
+himself near the harp. She stood beside it for some little while, in a
+curious way, going through the motion of playing it with her right hand,
+but not sounding it. At length she sat down, and drew it to her with one
+sudden action, and played and sang.
+
+I don't know what it was, in her touch or voice, that made that song the
+most unearthly I have ever heard in my life, or can imagine. There was
+something fearful in the reality of it. It was as if it had never been
+written, or set to music, but sprung out of passion within her; which
+found imperfect utterance in the low sounds of her voice, and crouched
+again when all was still. I was dumb when she leaned beside the harp
+again, playing it, but not sounding it, with her right hand.
+
+A minute more, and this had roused me from my trance:--Steerforth had
+left his seat, and gone to her, and had put his arm laughingly about
+her, and had said, 'Come, Rosa, for the future we will love each other
+very much!' And she had struck him, and had thrown him off with the fury
+of a wild cat, and had burst out of the room.
+
+'What is the matter with Rosa?' said Mrs. Steerforth, coming in.
+
+'She has been an angel, mother,' returned Steerforth, 'for a little
+while; and has run into the opposite extreme, since, by way of
+compensation.'
+
+'You should be careful not to irritate her, James. Her temper has been
+soured, remember, and ought not to be tried.'
+
+Rosa did not come back; and no other mention was made of her, until I
+went with Steerforth into his room to say Good night. Then he laughed
+about her, and asked me if I had ever seen such a fierce little piece of
+incomprehensibility.
+
+I expressed as much of my astonishment as was then capable of
+expression, and asked if he could guess what it was that she had taken
+so much amiss, so suddenly.
+
+'Oh, Heaven knows,' said Steerforth. 'Anything you like--or nothing!
+I told you she took everything, herself included, to a grindstone, and
+sharpened it. She is an edge-tool, and requires great care in dealing
+with. She is always dangerous. Good night!'
+
+'Good night!' said I, 'my dear Steerforth! I shall be gone before you
+wake in the morning. Good night!'
+
+He was unwilling to let me go; and stood, holding me out, with a hand on
+each of my shoulders, as he had done in my own room.
+
+'Daisy,' he said, with a smile--'for though that's not the name your
+godfathers and godmothers gave you, it's the name I like best to call
+you by--and I wish, I wish, I wish, you could give it to me!'
+
+'Why so I can, if I choose,' said I.
+
+'Daisy, if anything should ever separate us, you must think of me at my
+best, old boy. Come! Let us make that bargain. Think of me at my best,
+if circumstances should ever part us!'
+
+'You have no best to me, Steerforth,' said I, 'and no worst. You are
+always equally loved, and cherished in my heart.'
+
+So much compunction for having ever wronged him, even by a shapeless
+thought, did I feel within me, that the confession of having done so was
+rising to my lips. But for the reluctance I had to betray the confidence
+of Agnes, but for my uncertainty how to approach the subject with no
+risk of doing so, it would have reached them before he said, 'God bless
+you, Daisy, and good night!' In my doubt, it did NOT reach them; and we
+shook hands, and we parted.
+
+I was up with the dull dawn, and, having dressed as quietly as I could,
+looked into his room. He was fast asleep; lying, easily, with his head
+upon his arm, as I had often seen him lie at school.
+
+The time came in its season, and that was very soon, when I almost
+wondered that nothing troubled his repose, as I looked at him. But he
+slept--let me think of him so again--as I had often seen him sleep at
+school; and thus, in this silent hour, I left him. --Never more, oh
+God forgive you, Steerforth! to touch that passive hand in love and
+friendship. Never, never more!
+
+
+
+CHAPTER 30. A LOSS
+
+
+I got down to Yarmouth in the evening, and went to the inn. I knew that
+Peggotty's spare room--my room--was likely to have occupation enough
+in a little while, if that great Visitor, before whose presence all
+the living must give place, were not already in the house; so I betook
+myself to the inn, and dined there, and engaged my bed.
+
+It was ten o'clock when I went out. Many of the shops were shut, and the
+town was dull. When I came to Omer and Joram's, I found the shutters up,
+but the shop door standing open. As I could obtain a perspective view
+of Mr. Omer inside, smoking his pipe by the parlour door, I entered, and
+asked him how he was.
+
+'Why, bless my life and soul!' said Mr. Omer, 'how do you find yourself?
+Take a seat.---Smoke not disagreeable, I hope?'
+
+'By no means,' said I. 'I like it--in somebody else's pipe.'
+
+'What, not in your own, eh?' Mr. Omer returned, laughing. 'All the
+better, sir. Bad habit for a young man. Take a seat. I smoke, myself,
+for the asthma.'
+
+Mr. Omer had made room for me, and placed a chair. He now sat down again
+very much out of breath, gasping at his pipe as if it contained a supply
+of that necessary, without which he must perish.
+
+'I am sorry to have heard bad news of Mr. Barkis,' said I.
+
+Mr. Omer looked at me, with a steady countenance, and shook his head.
+
+'Do you know how he is tonight?' I asked.
+
+'The very question I should have put to you, sir,' returned Mr. Omer,
+'but on account of delicacy. It's one of the drawbacks of our line of
+business. When a party's ill, we can't ask how the party is.'
+
+The difficulty had not occurred to me; though I had had my apprehensions
+too, when I went in, of hearing the old tune. On its being mentioned, I
+recognized it, however, and said as much.
+
+'Yes, yes, you understand,' said Mr. Omer, nodding his head. 'We dursn't
+do it. Bless you, it would be a shock that the generality of parties
+mightn't recover, to say "Omer and Joram's compliments, and how do you
+find yourself this morning?"--or this afternoon--as it may be.'
+
+Mr. Omer and I nodded at each other, and Mr. Omer recruited his wind by
+the aid of his pipe.
+
+'It's one of the things that cut the trade off from attentions they
+could often wish to show,' said Mr. Omer. 'Take myself. If I have known
+Barkis a year, to move to as he went by, I have known him forty years.
+But I can't go and say, "how is he?"'
+
+I felt it was rather hard on Mr. Omer, and I told him so.
+
+'I'm not more self-interested, I hope, than another man,' said Mr. Omer.
+'Look at me! My wind may fail me at any moment, and it ain't
+likely that, to my own knowledge, I'd be self-interested under such
+circumstances. I say it ain't likely, in a man who knows his wind will
+go, when it DOES go, as if a pair of bellows was cut open; and that man
+a grandfather,' said Mr. Omer.
+
+I said, 'Not at all.'
+
+'It ain't that I complain of my line of business,' said Mr. Omer. 'It
+ain't that. Some good and some bad goes, no doubt, to all callings. What
+I wish is, that parties was brought up stronger-minded.'
+
+Mr. Omer, with a very complacent and amiable face, took several puffs in
+silence; and then said, resuming his first point:
+
+'Accordingly we're obleeged, in ascertaining how Barkis goes on, to
+limit ourselves to Em'ly. She knows what our real objects are, and she
+don't have any more alarms or suspicions about us, than if we was so
+many lambs. Minnie and Joram have just stepped down to the house, in
+fact (she's there, after hours, helping her aunt a bit), to ask her how
+he is tonight; and if you was to please to wait till they come back,
+they'd give you full partic'lers. Will you take something? A glass of
+srub and water, now? I smoke on srub and water, myself,' said Mr. Omer,
+taking up his glass, 'because it's considered softening to the passages,
+by which this troublesome breath of mine gets into action. But, Lord
+bless you,' said Mr. Omer, huskily, 'it ain't the passages that's out of
+order! "Give me breath enough," said I to my daughter Minnie, "and I'll
+find passages, my dear."'
+
+He really had no breath to spare, and it was very alarming to see him
+laugh. When he was again in a condition to be talked to, I thanked
+him for the proffered refreshment, which I declined, as I had just had
+dinner; and, observing that I would wait, since he was so good as to
+invite me, until his daughter and his son-in-law came back, I inquired
+how little Emily was?
+
+'Well, sir,' said Mr. Omer, removing his pipe, that he might rub his
+chin: 'I tell you truly, I shall be glad when her marriage has taken
+place.'
+
+'Why so?' I inquired.
+
+'Well, she's unsettled at present,' said Mr. Omer. 'It ain't that she's
+not as pretty as ever, for she's prettier--I do assure you, she is
+prettier. It ain't that she don't work as well as ever, for she does.
+She WAS worth any six, and she IS worth any six. But somehow she wants
+heart. If you understand,' said Mr. Omer, after rubbing his chin again,
+and smoking a little, 'what I mean in a general way by the expression,
+"A long pull, and a strong pull, and a pull altogether, my hearties,
+hurrah!" I should say to you, that that was--in a general way--what I
+miss in Em'ly.'
+
+Mr. Omer's face and manner went for so much, that I could
+conscientiously nod my head, as divining his meaning. My quickness of
+apprehension seemed to please him, and he went on: 'Now I consider this
+is principally on account of her being in an unsettled state, you
+see. We have talked it over a good deal, her uncle and myself, and her
+sweetheart and myself, after business; and I consider it is principally
+on account of her being unsettled. You must always recollect of Em'ly,'
+said Mr. Omer, shaking his head gently, 'that she's a most extraordinary
+affectionate little thing. The proverb says, "You can't make a silk
+purse out of a sow's ear." Well, I don't know about that. I rather think
+you may, if you begin early in life. She has made a home out of that old
+boat, sir, that stone and marble couldn't beat.'
+
+'I am sure she has!' said I.
+
+'To see the clinging of that pretty little thing to her uncle,' said
+Mr. Omer; 'to see the way she holds on to him, tighter and tighter, and
+closer and closer, every day, is to see a sight. Now, you know, there's
+a struggle going on when that's the case. Why should it be made a longer
+one than is needful?'
+
+I listened attentively to the good old fellow, and acquiesced, with all
+my heart, in what he said.
+
+'Therefore, I mentioned to them,' said Mr. Omer, in a comfortable,
+easy-going tone, 'this. I said, "Now, don't consider Em'ly nailed down
+in point of time, at all. Make it your own time. Her services have been
+more valuable than was supposed; her learning has been quicker than was
+supposed; Omer and Joram can run their pen through what remains; and
+she's free when you wish. If she likes to make any little arrangement,
+afterwards, in the way of doing any little thing for us at home,
+very well. If she don't, very well still. We're no losers, anyhow."
+For--don't you see,' said Mr. Omer, touching me with his pipe, 'it ain't
+likely that a man so short of breath as myself, and a grandfather too,
+would go and strain points with a little bit of a blue-eyed blossom,
+like her?'
+
+'Not at all, I am certain,' said I.
+
+'Not at all! You're right!' said Mr. Omer. 'Well, sir, her cousin--you
+know it's a cousin she's going to be married to?'
+
+'Oh yes,' I replied. 'I know him well.'
+
+'Of course you do,' said Mr. Omer. 'Well, sir! Her cousin being, as it
+appears, in good work, and well to do, thanked me in a very manly sort
+of manner for this (conducting himself altogether, I must say, in a way
+that gives me a high opinion of him), and went and took as comfortable
+a little house as you or I could wish to clap eyes on. That little
+house is now furnished right through, as neat and complete as a doll's
+parlour; and but for Barkis's illness having taken this bad turn, poor
+fellow, they would have been man and wife--I dare say, by this time. As
+it is, there's a postponement.'
+
+'And Emily, Mr. Omer?' I inquired. 'Has she become more settled?'
+
+'Why that, you know,' he returned, rubbing his double chin again, 'can't
+naturally be expected. The prospect of the change and separation, and
+all that, is, as one may say, close to her and far away from her, both
+at once. Barkis's death needn't put it off much, but his lingering
+might. Anyway, it's an uncertain state of matters, you see.'
+
+'I see,' said I.
+
+'Consequently,' pursued Mr. Omer, 'Em'ly's still a little down, and a
+little fluttered; perhaps, upon the whole, she's more so than she was.
+Every day she seems to get fonder and fonder of her uncle, and more loth
+to part from all of us. A kind word from me brings the tears into her
+eyes; and if you was to see her with my daughter Minnie's little girl,
+you'd never forget it. Bless my heart alive!' said Mr. Omer, pondering,
+'how she loves that child!'
+
+Having so favourable an opportunity, it occurred to me to ask Mr. Omer,
+before our conversation should be interrupted by the return of his
+daughter and her husband, whether he knew anything of Martha.
+
+'Ah!' he rejoined, shaking his head, and looking very much dejected.
+'No good. A sad story, sir, however you come to know it. I never thought
+there was harm in the girl. I wouldn't wish to mention it before my
+daughter Minnie--for she'd take me up directly--but I never did. None of
+us ever did.'
+
+Mr. Omer, hearing his daughter's footstep before I heard it, touched me
+with his pipe, and shut up one eye, as a caution. She and her husband
+came in immediately afterwards.
+
+Their report was, that Mr. Barkis was 'as bad as bad could be'; that he
+was quite unconscious; and that Mr. Chillip had mournfully said in the
+kitchen, on going away just now, that the College of Physicians, the
+College of Surgeons, and Apothecaries' Hall, if they were all called
+in together, couldn't help him. He was past both Colleges, Mr. Chillip
+said, and the Hall could only poison him.
+
+Hearing this, and learning that Mr. Peggotty was there, I determined to
+go to the house at once. I bade good night to Mr. Omer, and to Mr. and
+Mrs. Joram; and directed my steps thither, with a solemn feeling, which
+made Mr. Barkis quite a new and different creature.
+
+My low tap at the door was answered by Mr. Peggotty. He was not so much
+surprised to see me as I had expected. I remarked this in Peggotty,
+too, when she came down; and I have seen it since; and I think, in the
+expectation of that dread surprise, all other changes and surprises
+dwindle into nothing.
+
+I shook hands with Mr. Peggotty, and passed into the kitchen, while he
+softly closed the door. Little Emily was sitting by the fire, with her
+hands before her face. Ham was standing near her.
+
+We spoke in whispers; listening, between whiles, for any sound in the
+room above. I had not thought of it on the occasion of my last visit,
+but how strange it was to me, now, to miss Mr. Barkis out of the
+kitchen!
+
+'This is very kind of you, Mas'r Davy,' said Mr. Peggotty.
+
+'It's oncommon kind,' said Ham.
+
+'Em'ly, my dear,' cried Mr. Peggotty. 'See here! Here's Mas'r Davy come!
+What, cheer up, pretty! Not a wured to Mas'r Davy?'
+
+There was a trembling upon her, that I can see now. The coldness of her
+hand when I touched it, I can feel yet. Its only sign of animation was
+to shrink from mine; and then she glided from the chair, and creeping
+to the other side of her uncle, bowed herself, silently and trembling
+still, upon his breast.
+
+'It's such a loving art,' said Mr. Peggotty, smoothing her rich hair
+with his great hard hand, 'that it can't abear the sorrer of this.
+It's nat'ral in young folk, Mas'r Davy, when they're new to these here
+trials, and timid, like my little bird,--it's nat'ral.'
+
+She clung the closer to him, but neither lifted up her face, nor spoke a
+word.
+
+'It's getting late, my dear,' said Mr. Peggotty, 'and here's Ham come
+fur to take you home. Theer! Go along with t'other loving art! What'
+Em'ly? Eh, my pretty?'
+
+The sound of her voice had not reached me, but he bent his head as if he
+listened to her, and then said:
+
+'Let you stay with your uncle? Why, you doen't mean to ask me that! Stay
+with your uncle, Moppet? When your husband that'll be so soon, is here
+fur to take you home? Now a person wouldn't think it, fur to see this
+little thing alongside a rough-weather chap like me,' said Mr. Peggotty,
+looking round at both of us, with infinite pride; 'but the sea ain't
+more salt in it than she has fondness in her for her uncle--a foolish
+little Em'ly!'
+
+'Em'ly's in the right in that, Mas'r Davy!' said Ham. 'Lookee here! As
+Em'ly wishes of it, and as she's hurried and frightened, like, besides,
+I'll leave her till morning. Let me stay too!'
+
+'No, no,' said Mr. Peggotty. 'You doen't ought--a married man like
+you--or what's as good--to take and hull away a day's work. And you
+doen't ought to watch and work both. That won't do. You go home and turn
+in. You ain't afeerd of Em'ly not being took good care on, I know.'
+
+Ham yielded to this persuasion, and took his hat to go. Even when he
+kissed her--and I never saw him approach her, but I felt that nature
+had given him the soul of a gentleman--she seemed to cling closer to
+her uncle, even to the avoidance of her chosen husband. I shut the
+door after him, that it might cause no disturbance of the quiet that
+prevailed; and when I turned back, I found Mr. Peggotty still talking to
+her.
+
+'Now, I'm a going upstairs to tell your aunt as Mas'r Davy's here, and
+that'll cheer her up a bit,' he said. 'Sit ye down by the fire, the
+while, my dear, and warm those mortal cold hands. You doen't need to be
+so fearsome, and take on so much. What? You'll go along with me?--Well!
+come along with me--come! If her uncle was turned out of house and home,
+and forced to lay down in a dyke, Mas'r Davy,' said Mr. Peggotty, with
+no less pride than before, 'it's my belief she'd go along with him, now!
+But there'll be someone else, soon,--someone else, soon, Em'ly!'
+
+Afterwards, when I went upstairs, as I passed the door of my little
+chamber, which was dark, I had an indistinct impression of her being
+within it, cast down upon the floor. But, whether it was really she, or
+whether it was a confusion of the shadows in the room, I don't know now.
+
+I had leisure to think, before the kitchen fire, of pretty little
+Emily's dread of death--which, added to what Mr. Omer had told me, I
+took to be the cause of her being so unlike herself--and I had leisure,
+before Peggotty came down, even to think more leniently of the weakness
+of it: as I sat counting the ticking of the clock, and deepening my
+sense of the solemn hush around me. Peggotty took me in her arms, and
+blessed and thanked me over and over again for being such a comfort to
+her (that was what she said) in her distress. She then entreated me to
+come upstairs, sobbing that Mr. Barkis had always liked me and admired
+me; that he had often talked of me, before he fell into a stupor; and
+that she believed, in case of his coming to himself again, he would
+brighten up at sight of me, if he could brighten up at any earthly
+thing.
+
+The probability of his ever doing so, appeared to me, when I saw him, to
+be very small. He was lying with his head and shoulders out of bed, in
+an uncomfortable attitude, half resting on the box which had cost him so
+much pain and trouble. I learned, that, when he was past creeping out of
+bed to open it, and past assuring himself of its safety by means of the
+divining rod I had seen him use, he had required to have it placed on
+the chair at the bed-side, where he had ever since embraced it, night
+and day. His arm lay on it now. Time and the world were slipping from
+beneath him, but the box was there; and the last words he had uttered
+were (in an explanatory tone) 'Old clothes!'
+
+'Barkis, my dear!' said Peggotty, almost cheerfully: bending over him,
+while her brother and I stood at the bed's foot. 'Here's my dear boy--my
+dear boy, Master Davy, who brought us together, Barkis! That you sent
+messages by, you know! Won't you speak to Master Davy?'
+
+He was as mute and senseless as the box, from which his form derived the
+only expression it had.
+
+'He's a going out with the tide,' said Mr. Peggotty to me, behind his
+hand.
+
+My eyes were dim and so were Mr. Peggotty's; but I repeated in a
+whisper, 'With the tide?'
+
+'People can't die, along the coast,' said Mr. Peggotty, 'except when
+the tide's pretty nigh out. They can't be born, unless it's pretty nigh
+in--not properly born, till flood. He's a going out with the tide. It's
+ebb at half-arter three, slack water half an hour. If he lives till it
+turns, he'll hold his own till past the flood, and go out with the next
+tide.'
+
+We remained there, watching him, a long time--hours. What mysterious
+influence my presence had upon him in that state of his senses, I shall
+not pretend to say; but when he at last began to wander feebly, it is
+certain he was muttering about driving me to school.
+
+'He's coming to himself,' said Peggotty.
+
+Mr. Peggotty touched me, and whispered with much awe and reverence.
+'They are both a-going out fast.'
+
+'Barkis, my dear!' said Peggotty.
+
+'C. P. Barkis,' he cried faintly. 'No better woman anywhere!'
+
+'Look! Here's Master Davy!' said Peggotty. For he now opened his eyes.
+
+I was on the point of asking him if he knew me, when he tried to stretch
+out his arm, and said to me, distinctly, with a pleasant smile:
+
+'Barkis is willin'!'
+
+And, it being low water, he went out with the tide.
+
+
+
+CHAPTER 31. A GREATER LOSS
+
+
+It was not difficult for me, on Peggotty's solicitation, to resolve to
+stay where I was, until after the remains of the poor carrier should
+have made their last journey to Blunderstone. She had long ago bought,
+out of her own savings, a little piece of ground in our old churchyard
+near the grave of 'her sweet girl', as she always called my mother; and
+there they were to rest.
+
+In keeping Peggotty company, and doing all I could for her (little
+enough at the utmost), I was as grateful, I rejoice to think, as even
+now I could wish myself to have been. But I am afraid I had a supreme
+satisfaction, of a personal and professional nature, in taking charge of
+Mr. Barkis's will, and expounding its contents.
+
+I may claim the merit of having originated the suggestion that the will
+should be looked for in the box. After some search, it was found in the
+box, at the bottom of a horse's nose-bag; wherein (besides hay) there
+was discovered an old gold watch, with chain and seals, which Mr. Barkis
+had worn on his wedding-day, and which had never been seen before or
+since; a silver tobacco-stopper, in the form of a leg; an imitation
+lemon, full of minute cups and saucers, which I have some idea Mr.
+Barkis must have purchased to present to me when I was a child, and
+afterwards found himself unable to part with; eighty-seven guineas and
+a half, in guineas and half-guineas; two hundred and ten pounds, in
+perfectly clean Bank notes; certain receipts for Bank of England
+stock; an old horseshoe, a bad shilling, a piece of camphor, and an
+oyster-shell. From the circumstance of the latter article having
+been much polished, and displaying prismatic colours on the inside,
+I conclude that Mr. Barkis had some general ideas about pearls, which
+never resolved themselves into anything definite.
+
+For years and years, Mr. Barkis had carried this box, on all his
+journeys, every day. That it might the better escape notice, he had
+invented a fiction that it belonged to 'Mr. Blackboy', and was 'to be
+left with Barkis till called for'; a fable he had elaborately written on
+the lid, in characters now scarcely legible.
+
+He had hoarded, all these years, I found, to good purpose. His property
+in money amounted to nearly three thousand pounds. Of this he bequeathed
+the interest of one thousand to Mr. Peggotty for his life; on his
+decease, the principal to be equally divided between Peggotty, little
+Emily, and me, or the survivor or survivors of us, share and share
+alike. All the rest he died possessed of, he bequeathed to Peggotty;
+whom he left residuary legatee, and sole executrix of that his last will
+and testament.
+
+I felt myself quite a proctor when I read this document aloud with all
+possible ceremony, and set forth its provisions, any number of times,
+to those whom they concerned. I began to think there was more in the
+Commons than I had supposed. I examined the will with the deepest
+attention, pronounced it perfectly formal in all respects, made a
+pencil-mark or so in the margin, and thought it rather extraordinary
+that I knew so much.
+
+In this abstruse pursuit; in making an account for Peggotty, of all the
+property into which she had come; in arranging all the affairs in an
+orderly manner; and in being her referee and adviser on every point, to
+our joint delight; I passed the week before the funeral. I did not see
+little Emily in that interval, but they told me she was to be quietly
+married in a fortnight.
+
+I did not attend the funeral in character, if I may venture to say so.
+I mean I was not dressed up in a black coat and a streamer, to frighten
+the birds; but I walked over to Blunderstone early in the morning, and
+was in the churchyard when it came, attended only by Peggotty and her
+brother. The mad gentleman looked on, out of my little window; Mr.
+Chillip's baby wagged its heavy head, and rolled its goggle eyes, at
+the clergyman, over its nurse's shoulder; Mr. Omer breathed short in
+the background; no one else was there; and it was very quiet. We walked
+about the churchyard for an hour, after all was over; and pulled some
+young leaves from the tree above my mother's grave.
+
+A dread falls on me here. A cloud is lowering on the distant town,
+towards which I retraced my solitary steps. I fear to approach it. I
+cannot bear to think of what did come, upon that memorable night; of
+what must come again, if I go on.
+
+It is no worse, because I write of it. It would be no better, if I
+stopped my most unwilling hand. It is done. Nothing can undo it; nothing
+can make it otherwise than as it was.
+
+My old nurse was to go to London with me next day, on the business of
+the will. Little Emily was passing that day at Mr. Omer's. We were all
+to meet in the old boathouse that night. Ham would bring Emily at the
+usual hour. I would walk back at my leisure. The brother and sister
+would return as they had come, and be expecting us, when the day closed
+in, at the fireside.
+
+I parted from them at the wicket-gate, where visionary Strap had rested
+with Roderick Random's knapsack in the days of yore; and, instead of
+going straight back, walked a little distance on the road to Lowestoft.
+Then I turned, and walked back towards Yarmouth. I stayed to dine at
+a decent alehouse, some mile or two from the Ferry I have mentioned
+before; and thus the day wore away, and it was evening when I reached
+it. Rain was falling heavily by that time, and it was a wild night; but
+there was a moon behind the clouds, and it was not dark.
+
+I was soon within sight of Mr. Peggotty's house, and of the light within
+it shining through the window. A little floundering across the sand,
+which was heavy, brought me to the door, and I went in.
+
+It looked very comfortable indeed. Mr. Peggotty had smoked his evening
+pipe and there were preparations for some supper by and by. The fire was
+bright, the ashes were thrown up, the locker was ready for little Emily
+in her old place. In her own old place sat Peggotty, once more, looking
+(but for her dress) as if she had never left it. She had fallen back,
+already, on the society of the work-box with St. Paul's upon the lid,
+the yard-measure in the cottage, and the bit of wax-candle; and there
+they all were, just as if they had never been disturbed. Mrs. Gummidge
+appeared to be fretting a little, in her old corner; and consequently
+looked quite natural, too.
+
+'You're first of the lot, Mas'r Davy!' said Mr. Peggotty with a happy
+face. 'Doen't keep in that coat, sir, if it's wet.'
+
+'Thank you, Mr. Peggotty,' said I, giving him my outer coat to hang up.
+'It's quite dry.'
+
+'So 'tis!' said Mr. Peggotty, feeling my shoulders. 'As a chip! Sit ye
+down, sir. It ain't o' no use saying welcome to you, but you're welcome,
+kind and hearty.'
+
+'Thank you, Mr. Peggotty, I am sure of that. Well, Peggotty!' said I,
+giving her a kiss. 'And how are you, old woman?'
+
+'Ha, ha!' laughed Mr. Peggotty, sitting down beside us, and rubbing his
+hands in his sense of relief from recent trouble, and in the genuine
+heartiness of his nature; 'there's not a woman in the wureld, sir--as I
+tell her--that need to feel more easy in her mind than her! She done her
+dooty by the departed, and the departed know'd it; and the departed
+done what was right by her, as she done what was right by the
+departed;--and--and--and it's all right!'
+
+Mrs. Gummidge groaned.
+
+'Cheer up, my pritty mawther!' said Mr. Peggotty. (But he shook his head
+aside at us, evidently sensible of the tendency of the late occurrences
+to recall the memory of the old one.) 'Doen't be down! Cheer up, for
+your own self, on'y a little bit, and see if a good deal more doen't
+come nat'ral!'
+
+'Not to me, Dan'l,' returned Mrs. Gummidge. 'Nothink's nat'ral to me but
+to be lone and lorn.'
+
+'No, no,' said Mr. Peggotty, soothing her sorrows.
+
+'Yes, yes, Dan'l!' said Mrs. Gummidge. 'I ain't a person to live with
+them as has had money left. Thinks go too contrary with me. I had better
+be a riddance.'
+
+'Why, how should I ever spend it without you?' said Mr. Peggotty, with
+an air of serious remonstrance. 'What are you a talking on? Doen't I
+want you more now, than ever I did?'
+
+'I know'd I was never wanted before!' cried Mrs. Gummidge, with a
+pitiable whimper, 'and now I'm told so! How could I expect to be wanted,
+being so lone and lorn, and so contrary!'
+
+Mr. Peggotty seemed very much shocked at himself for having made a
+speech capable of this unfeeling construction, but was prevented from
+replying, by Peggotty's pulling his sleeve, and shaking her head. After
+looking at Mrs. Gummidge for some moments, in sore distress of mind, he
+glanced at the Dutch clock, rose, snuffed the candle, and put it in the
+window.
+
+'Theer!'said Mr. Peggotty, cheerily.'Theer we are, Missis Gummidge!'
+Mrs. Gummidge slightly groaned. 'Lighted up, accordin' to custom! You're
+a wonderin' what that's fur, sir! Well, it's fur our little Em'ly. You
+see, the path ain't over light or cheerful arter dark; and when I'm
+here at the hour as she's a comin' home, I puts the light in the winder.
+That, you see,' said Mr. Peggotty, bending over me with great glee,
+'meets two objects. She says, says Em'ly, "Theer's home!" she says. And
+likewise, says Em'ly, "My uncle's theer!" Fur if I ain't theer, I never
+have no light showed.'
+
+'You're a baby!' said Peggotty; very fond of him for it, if she thought
+so.
+
+'Well,' returned Mr. Peggotty, standing with his legs pretty wide apart,
+and rubbing his hands up and down them in his comfortable satisfaction,
+as he looked alternately at us and at the fire. 'I doen't know but I am.
+Not, you see, to look at.'
+
+'Not azackly,' observed Peggotty.
+
+'No,' laughed Mr. Peggotty, 'not to look at, but to--to consider on, you
+know. I doen't care, bless you! Now I tell you. When I go a looking and
+looking about that theer pritty house of our Em'ly's, I'm--I'm Gormed,'
+said Mr. Peggotty, with sudden emphasis--'theer! I can't say more--if
+I doen't feel as if the littlest things was her, a'most. I takes 'em up
+and I put 'em down, and I touches of 'em as delicate as if they was our
+Em'ly. So 'tis with her little bonnets and that. I couldn't see one on
+'em rough used a purpose--not fur the whole wureld. There's a babby fur
+you, in the form of a great Sea Porkypine!' said Mr. Peggotty, relieving
+his earnestness with a roar of laughter.
+
+Peggotty and I both laughed, but not so loud.
+
+'It's my opinion, you see,' said Mr. Peggotty, with a delighted face,
+after some further rubbing of his legs, 'as this is along of my havin'
+played with her so much, and made believe as we was Turks, and French,
+and sharks, and every wariety of forinners--bless you, yes; and lions
+and whales, and I doen't know what all!--when she warn't no higher than
+my knee. I've got into the way on it, you know. Why, this here candle,
+now!' said Mr. Peggotty, gleefully holding out his hand towards it,
+'I know wery well that arter she's married and gone, I shall put that
+candle theer, just the same as now. I know wery well that when I'm
+here o' nights (and where else should I live, bless your arts, whatever
+fortun' I come into!) and she ain't here or I ain't theer, I shall
+put the candle in the winder, and sit afore the fire, pretending I'm
+expecting of her, like I'm a doing now. THERE'S a babby for you,' said
+Mr. Peggotty, with another roar, 'in the form of a Sea Porkypine! Why,
+at the present minute, when I see the candle sparkle up, I says to
+myself, "She's a looking at it! Em'ly's a coming!" THERE'S a babby
+for you, in the form of a Sea Porkypine! Right for all that,' said Mr.
+Peggotty, stopping in his roar, and smiting his hands together; 'fur
+here she is!'
+
+It was only Ham. The night should have turned more wet since I came in,
+for he had a large sou'wester hat on, slouched over his face.
+
+'Wheer's Em'ly?' said Mr. Peggotty.
+
+Ham made a motion with his head, as if she were outside. Mr. Peggotty
+took the light from the window, trimmed it, put it on the table, and was
+busily stirring the fire, when Ham, who had not moved, said:
+
+'Mas'r Davy, will you come out a minute, and see what Em'ly and me has
+got to show you?'
+
+We went out. As I passed him at the door, I saw, to my astonishment and
+fright, that he was deadly pale. He pushed me hastily into the open air,
+and closed the door upon us. Only upon us two.
+
+'Ham! what's the matter?'
+
+'Mas'r Davy!--' Oh, for his broken heart, how dreadfully he wept!
+
+I was paralysed by the sight of such grief. I don't know what I thought,
+or what I dreaded. I could only look at him.
+
+'Ham! Poor good fellow! For Heaven's sake, tell me what's the matter!'
+
+'My love, Mas'r Davy--the pride and hope of my art--her that I'd have
+died for, and would die for now--she's gone!'
+
+'Gone!'
+
+'Em'ly's run away! Oh, Mas'r Davy, think HOW she's run away, when I
+pray my good and gracious God to kill her (her that is so dear above all
+things) sooner than let her come to ruin and disgrace!'
+
+The face he turned up to the troubled sky, the quivering of his clasped
+hands, the agony of his figure, remain associated with the lonely waste,
+in my remembrance, to this hour. It is always night there, and he is the
+only object in the scene.
+
+'You're a scholar,' he said, hurriedly, 'and know what's right and
+best. What am I to say, indoors? How am I ever to break it to him, Mas'r
+Davy?'
+
+I saw the door move, and instinctively tried to hold the latch on the
+outside, to gain a moment's time. It was too late. Mr. Peggotty thrust
+forth his face; and never could I forget the change that came upon it
+when he saw us, if I were to live five hundred years.
+
+I remember a great wail and cry, and the women hanging about him, and we
+all standing in the room; I with a paper in my hand, which Ham had given
+me; Mr. Peggotty, with his vest torn open, his hair wild, his face and
+lips quite white, and blood trickling down his bosom (it had sprung from
+his mouth, I think), looking fixedly at me.
+
+'Read it, sir,' he said, in a low shivering voice. 'Slow, please. I
+doen't know as I can understand.'
+
+In the midst of the silence of death, I read thus, from a blotted
+letter:
+
+
+'"When you, who love me so much better than I ever have deserved, even
+when my mind was innocent, see this, I shall be far away."'
+
+
+'I shall be fur away,' he repeated slowly. 'Stop! Em'ly fur away. Well!'
+
+
+'"When I leave my dear home--my dear home--oh, my dear home!--in the
+morning,"'
+
+the letter bore date on the previous night:
+
+
+'"--it will be never to come back, unless he brings me back a lady. This
+will be found at night, many hours after, instead of me. Oh, if you knew
+how my heart is torn. If even you, that I have wronged so much, that
+never can forgive me, could only know what I suffer! I am too wicked to
+write about myself! Oh, take comfort in thinking that I am so bad. Oh,
+for mercy's sake, tell uncle that I never loved him half so dear as
+now. Oh, don't remember how affectionate and kind you have all been to
+me--don't remember we were ever to be married--but try to think as if I
+died when I was little, and was buried somewhere. Pray Heaven that I
+am going away from, have compassion on my uncle! Tell him that I never
+loved him half so dear. Be his comfort. Love some good girl that will
+be what I was once to uncle, and be true to you, and worthy of you, and
+know no shame but me. God bless all! I'll pray for all, often, on my
+knees. If he don't bring me back a lady, and I don't pray for my own
+self, I'll pray for all. My parting love to uncle. My last tears, and my
+last thanks, for uncle!"'
+
+That was all.
+
+He stood, long after I had ceased to read, still looking at me. At
+length I ventured to take his hand, and to entreat him, as well as
+I could, to endeavour to get some command of himself. He replied, 'I
+thankee, sir, I thankee!' without moving.
+
+Ham spoke to him. Mr. Peggotty was so far sensible of HIS affliction,
+that he wrung his hand; but, otherwise, he remained in the same state,
+and no one dared to disturb him.
+
+Slowly, at last, he moved his eyes from my face, as if he were waking
+from a vision, and cast them round the room. Then he said, in a low
+voice:
+
+'Who's the man? I want to know his name.'
+
+Ham glanced at me, and suddenly I felt a shock that struck me back.
+
+'There's a man suspected,' said Mr. Peggotty. 'Who is it?'
+
+'Mas'r Davy!' implored Ham. 'Go out a bit, and let me tell him what I
+must. You doen't ought to hear it, sir.'
+
+I felt the shock again. I sank down in a chair, and tried to utter some
+reply; but my tongue was fettered, and my sight was weak.
+
+'I want to know his name!' I heard said once more.
+
+'For some time past,' Ham faltered, 'there's been a servant about here,
+at odd times. There's been a gen'lm'n too. Both of 'em belonged to one
+another.'
+
+Mr. Peggotty stood fixed as before, but now looking at him.
+
+'The servant,' pursued Ham, 'was seen along with--our poor girl--last
+night. He's been in hiding about here, this week or over. He was thought
+to have gone, but he was hiding. Doen't stay, Mas'r Davy, doen't!'
+
+I felt Peggotty's arm round my neck, but I could not have moved if the
+house had been about to fall upon me.
+
+'A strange chay and hosses was outside town, this morning, on the
+Norwich road, a'most afore the day broke,' Ham went on. 'The servant
+went to it, and come from it, and went to it again. When he went to it
+again, Em'ly was nigh him. The t'other was inside. He's the man.'
+
+'For the Lord's love,' said Mr. Peggotty, falling back, and putting out
+his hand, as if to keep off what he dreaded. 'Doen't tell me his name's
+Steerforth!'
+
+'Mas'r Davy,' exclaimed Ham, in a broken voice, 'it ain't no fault
+of yourn--and I am far from laying of it to you--but his name is
+Steerforth, and he's a damned villain!'
+
+Mr. Peggotty uttered no cry, and shed no tear, and moved no more, until
+he seemed to wake again, all at once, and pulled down his rough coat
+from its peg in a corner.
+
+'Bear a hand with this! I'm struck of a heap, and can't do it,' he said,
+impatiently. 'Bear a hand and help me. Well!' when somebody had done so.
+'Now give me that theer hat!'
+
+Ham asked him whither he was going.
+
+'I'm a going to seek my niece. I'm a going to seek my Em'ly. I'm a
+going, first, to stave in that theer boat, and sink it where I would
+have drownded him, as I'm a living soul, if I had had one thought of
+what was in him! As he sat afore me,' he said, wildly, holding out his
+clenched right hand, 'as he sat afore me, face to face, strike me down
+dead, but I'd have drownded him, and thought it right!--I'm a going to
+seek my niece.'
+
+'Where?' cried Ham, interposing himself before the door.
+
+'Anywhere! I'm a going to seek my niece through the wureld. I'm a going
+to find my poor niece in her shame, and bring her back. No one stop me!
+I tell you I'm a going to seek my niece!'
+
+'No, no!' cried Mrs. Gummidge, coming between them, in a fit of crying.
+'No, no, Dan'l, not as you are now. Seek her in a little while, my lone
+lorn Dan'l, and that'll be but right! but not as you are now. Sit ye
+down, and give me your forgiveness for having ever been a worrit to you,
+Dan'l--what have my contraries ever been to this!--and let us speak a
+word about them times when she was first an orphan, and when Ham was
+too, and when I was a poor widder woman, and you took me in. It'll
+soften your poor heart, Dan'l,' laying her head upon his shoulder, 'and
+you'll bear your sorrow better; for you know the promise, Dan'l, "As
+you have done it unto one of the least of these, you have done it unto
+me",--and that can never fail under this roof, that's been our shelter
+for so many, many year!'
+
+He was quite passive now; and when I heard him crying, the impulse that
+had been upon me to go down upon my knees, and ask their pardon for the
+desolation I had caused, and curse Steer--forth, yielded to a better
+feeling, My overcharged heart found the same relief, and I cried too.
+
+
+
+CHAPTER 32. THE BEGINNING OF A LONG JOURNEY
+
+
+What is natural in me, is natural in many other men, I infer, and so
+I am not afraid to write that I never had loved Steerforth better than
+when the ties that bound me to him were broken. In the keen distress
+of the discovery of his unworthiness, I thought more of all that was
+brilliant in him, I softened more towards all that was good in him, I
+did more justice to the qualities that might have made him a man of a
+noble nature and a great name, than ever I had done in the height of
+my devotion to him. Deeply as I felt my own unconscious part in his
+pollution of an honest home, I believed that if I had been brought face
+to face with him, I could not have uttered one reproach. I should have
+loved him so well still--though he fascinated me no longer--I should
+have held in so much tenderness the memory of my affection for him, that
+I think I should have been as weak as a spirit-wounded child, in all
+but the entertainment of a thought that we could ever be re-united.
+That thought I never had. I felt, as he had felt, that all was at an end
+between us. What his remembrances of me were, I have never known--they
+were light enough, perhaps, and easily dismissed--but mine of him were
+as the remembrances of a cherished friend, who was dead.
+
+Yes, Steerforth, long removed from the scenes of this poor history! My
+sorrow may bear involuntary witness against you at the judgement Throne;
+but my angry thoughts or my reproaches never will, I know!
+
+The news of what had happened soon spread through the town; insomuch
+that as I passed along the streets next morning, I overheard the people
+speaking of it at their doors. Many were hard upon her, some few were
+hard upon him, but towards her second father and her lover there was
+but one sentiment. Among all kinds of people a respect for them in
+their distress prevailed, which was full of gentleness and delicacy. The
+seafaring men kept apart, when those two were seen early, walking with
+slow steps on the beach; and stood in knots, talking compassionately
+among themselves.
+
+It was on the beach, close down by the sea, that I found them. It would
+have been easy to perceive that they had not slept all last night, even
+if Peggotty had failed to tell me of their still sitting just as I
+left them, when it was broad day. They looked worn; and I thought Mr.
+Peggotty's head was bowed in one night more than in all the years I had
+known him. But they were both as grave and steady as the sea itself,
+then lying beneath a dark sky, waveless--yet with a heavy roll upon it,
+as if it breathed in its rest--and touched, on the horizon, with a strip
+of silvery light from the unseen sun.
+
+'We have had a mort of talk, sir,' said Mr. Peggotty to me, when we had
+all three walked a little while in silence, 'of what we ought and doen't
+ought to do. But we see our course now.'
+
+I happened to glance at Ham, then looking out to sea upon the distant
+light, and a frightful thought came into my mind--not that his face
+was angry, for it was not; I recall nothing but an expression of stern
+determination in it--that if ever he encountered Steerforth, he would
+kill him.
+
+'My dooty here, sir,' said Mr. Peggotty, 'is done. I'm a going to seek
+my--' he stopped, and went on in a firmer voice: 'I'm a going to seek
+her. That's my dooty evermore.'
+
+He shook his head when I asked him where he would seek her, and inquired
+if I were going to London tomorrow? I told him I had not gone today,
+fearing to lose the chance of being of any service to him; but that I
+was ready to go when he would.
+
+'I'll go along with you, sir,' he rejoined, 'if you're agreeable,
+tomorrow.'
+
+We walked again, for a while, in silence.
+
+'Ham,'he presently resumed,'he'll hold to his present work, and go and
+live along with my sister. The old boat yonder--'
+
+'Will you desert the old boat, Mr. Peggotty?' I gently interposed.
+
+'My station, Mas'r Davy,' he returned, 'ain't there no longer; and if
+ever a boat foundered, since there was darkness on the face of the deep,
+that one's gone down. But no, sir, no; I doen't mean as it should be
+deserted. Fur from that.'
+
+We walked again for a while, as before, until he explained:
+
+'My wishes is, sir, as it shall look, day and night, winter and summer,
+as it has always looked, since she fust know'd it. If ever she should
+come a wandering back, I wouldn't have the old place seem to cast her
+off, you understand, but seem to tempt her to draw nigher to 't, and to
+peep in, maybe, like a ghost, out of the wind and rain, through the old
+winder, at the old seat by the fire. Then, maybe, Mas'r Davy, seein'
+none but Missis Gummidge there, she might take heart to creep in,
+trembling; and might come to be laid down in her old bed, and rest her
+weary head where it was once so gay.'
+
+I could not speak to him in reply, though I tried.
+
+'Every night,' said Mr. Peggotty, 'as reg'lar as the night comes, the
+candle must be stood in its old pane of glass, that if ever she should
+see it, it may seem to say "Come back, my child, come back!" If ever
+there's a knock, Ham (partic'ler a soft knock), arter dark, at your
+aunt's door, doen't you go nigh it. Let it be her--not you--that sees my
+fallen child!'
+
+He walked a little in front of us, and kept before us for some minutes.
+During this interval, I glanced at Ham again, and observing the same
+expression on his face, and his eyes still directed to the distant
+light, I touched his arm.
+
+Twice I called him by his name, in the tone in which I might have tried
+to rouse a sleeper, before he heeded me. When I at last inquired on what
+his thoughts were so bent, he replied:
+
+'On what's afore me, Mas'r Davy; and over yon.' 'On the life before you,
+do you mean?' He had pointed confusedly out to sea.
+
+'Ay, Mas'r Davy. I doen't rightly know how 'tis, but from over yon there
+seemed to me to come--the end of it like,' looking at me as if he were
+waking, but with the same determined face.
+
+'What end?' I asked, possessed by my former fear.
+
+'I doen't know,'he said, thoughtfully; 'I was calling to mind that the
+beginning of it all did take place here--and then the end come. But it's
+gone! Mas'r Davy,' he added; answering, as I think, my look; 'you han't
+no call to be afeerd of me: but I'm kiender muddled; I don't fare to
+feel no matters,'--which was as much as to say that he was not himself,
+and quite confounded.
+
+Mr. Peggotty stopping for us to join him: we did so, and said no more.
+The remembrance of this, in connexion with my former thought, however,
+haunted me at intervals, even until the inexorable end came at its
+appointed time.
+
+We insensibly approached the old boat, and entered. Mrs. Gummidge, no
+longer moping in her especial corner, was busy preparing breakfast.
+She took Mr. Peggotty's hat, and placed his seat for him, and spoke so
+comfortably and softly, that I hardly knew her.
+
+'Dan'l, my good man,' said she, 'you must eat and drink, and keep up
+your strength, for without it you'll do nowt. Try, that's a dear soul!
+An if I disturb you with my clicketten,' she meant her chattering, 'tell
+me so, Dan'l, and I won't.'
+
+When she had served us all, she withdrew to the window, where she
+sedulously employed herself in repairing some shirts and other clothes
+belonging to Mr. Peggotty, and neatly folding and packing them in an old
+oilskin bag, such as sailors carry. Meanwhile, she continued talking, in
+the same quiet manner:
+
+'All times and seasons, you know, Dan'l,' said Mrs. Gummidge, 'I shall
+be allus here, and everythink will look accordin' to your wishes. I'm a
+poor scholar, but I shall write to you, odd times, when you're away, and
+send my letters to Mas'r Davy. Maybe you'll write to me too, Dan'l, odd
+times, and tell me how you fare to feel upon your lone lorn journies.'
+
+'You'll be a solitary woman heer, I'm afeerd!' said Mr. Peggotty.
+
+'No, no, Dan'l,' she returned, 'I shan't be that. Doen't you mind me. I
+shall have enough to do to keep a Beein for you' (Mrs. Gummidge meant a
+home), 'again you come back--to keep a Beein here for any that may hap
+to come back, Dan'l. In the fine time, I shall set outside the door as I
+used to do. If any should come nigh, they shall see the old widder woman
+true to 'em, a long way off.'
+
+What a change in Mrs. Gummidge in a little time! She was another woman.
+She was so devoted, she had such a quick perception of what it would
+be well to say, and what it would be well to leave unsaid; she was so
+forgetful of herself, and so regardful of the sorrow about her, that I
+held her in a sort of veneration. The work she did that day! There
+were many things to be brought up from the beach and stored in the
+outhouse--as oars, nets, sails, cordage, spars, lobster-pots, bags of
+ballast, and the like; and though there was abundance of assistance
+rendered, there being not a pair of working hands on all that shore but
+would have laboured hard for Mr. Peggotty, and been well paid in being
+asked to do it, yet she persisted, all day long, in toiling under
+weights that she was quite unequal to, and fagging to and fro on all
+sorts of unnecessary errands. As to deploring her misfortunes, she
+appeared to have entirely lost the recollection of ever having had any.
+She preserved an equable cheerfulness in the midst of her sympathy,
+which was not the least astonishing part of the change that had come
+over her. Querulousness was out of the question. I did not even observe
+her voice to falter, or a tear to escape from her eyes, the whole day
+through, until twilight; when she and I and Mr. Peggotty being alone
+together, and he having fallen asleep in perfect exhaustion, she broke
+into a half-suppressed fit of sobbing and crying, and taking me to the
+door, said, 'Ever bless you, Mas'r Davy, be a friend to him, poor dear!'
+Then, she immediately ran out of the house to wash her face, in order
+that she might sit quietly beside him, and be found at work there, when
+he should awake. In short I left her, when I went away at night, the
+prop and staff of Mr. Peggotty's affliction; and I could not meditate
+enough upon the lesson that I read in Mrs. Gummidge, and the new
+experience she unfolded to me.
+
+It was between nine and ten o'clock when, strolling in a melancholy
+manner through the town, I stopped at Mr. Omer's door. Mr. Omer had
+taken it so much to heart, his daughter told me, that he had been very
+low and poorly all day, and had gone to bed without his pipe.
+
+'A deceitful, bad-hearted girl,' said Mrs. Joram. 'There was no good in
+her, ever!'
+
+'Don't say so,' I returned. 'You don't think so.'
+
+'Yes, I do!' cried Mrs. Joram, angrily.
+
+'No, no,' said I.
+
+Mrs. Joram tossed her head, endeavouring to be very stern and cross; but
+she could not command her softer self, and began to cry. I was young,
+to be sure; but I thought much the better of her for this sympathy, and
+fancied it became her, as a virtuous wife and mother, very well indeed.
+
+'What will she ever do!' sobbed Minnie. 'Where will she go! What will
+become of her! Oh, how could she be so cruel, to herself and him!'
+
+I remembered the time when Minnie was a young and pretty girl; and I was
+glad she remembered it too, so feelingly.
+
+'My little Minnie,' said Mrs. Joram, 'has only just now been got to
+sleep. Even in her sleep she is sobbing for Em'ly. All day long, little
+Minnie has cried for her, and asked me, over and over again, whether
+Em'ly was wicked? What can I say to her, when Em'ly tied a ribbon off
+her own neck round little Minnie's the last night she was here, and laid
+her head down on the pillow beside her till she was fast asleep! The
+ribbon's round my little Minnie's neck now. It ought not to be, perhaps,
+but what can I do? Em'ly is very bad, but they were fond of one another.
+And the child knows nothing!'
+
+Mrs. Joram was so unhappy that her husband came out to take care of
+her. Leaving them together, I went home to Peggotty's; more melancholy
+myself, if possible, than I had been yet.
+
+That good creature--I mean Peggotty--all untired by her late anxieties
+and sleepless nights, was at her brother's, where she meant to stay till
+morning. An old woman, who had been employed about the house for some
+weeks past, while Peggotty had been unable to attend to it, was the
+house's only other occupant besides myself. As I had no occasion for her
+services, I sent her to bed, by no means against her will, and sat down
+before the kitchen fire a little while, to think about all this.
+
+I was blending it with the deathbed of the late Mr. Barkis, and was
+driving out with the tide towards the distance at which Ham had looked
+so singularly in the morning, when I was recalled from my wanderings by
+a knock at the door. There was a knocker upon the door, but it was not
+that which made the sound. The tap was from a hand, and low down upon
+the door, as if it were given by a child.
+
+It made me start as much as if it had been the knock of a footman to a
+person of distinction. I opened the door; and at first looked down,
+to my amazement, on nothing but a great umbrella that appeared to be
+walking about of itself. But presently I discovered underneath it, Miss
+Mowcher.
+
+I might not have been prepared to give the little creature a very kind
+reception, if, on her removing the umbrella, which her utmost efforts
+were unable to shut up, she had shown me the 'volatile' expression of
+face which had made so great an impression on me at our first and last
+meeting. But her face, as she turned it up to mine, was so earnest;
+and when I relieved her of the umbrella (which would have been an
+inconvenient one for the Irish Giant), she wrung her little hands in
+such an afflicted manner; that I rather inclined towards her.
+
+'Miss Mowcher!' said I, after glancing up and down the empty street,
+without distinctly knowing what I expected to see besides; 'how do you
+come here? What is the matter?' She motioned to me with her short right
+arm, to shut the umbrella for her; and passing me hurriedly, went into
+the kitchen. When I had closed the door, and followed, with the umbrella
+in my hand, I found her sitting on the corner of the fender--it was a
+low iron one, with two flat bars at top to stand plates upon--in the
+shadow of the boiler, swaying herself backwards and forwards, and
+chafing her hands upon her knees like a person in pain.
+
+Quite alarmed at being the only recipient of this untimely visit, and
+the only spectator of this portentous behaviour, I exclaimed again,
+'Pray tell me, Miss Mowcher, what is the matter! are you ill?'
+
+'My dear young soul,' returned Miss Mowcher, squeezing her hands upon
+her heart one over the other. 'I am ill here, I am very ill. To think
+that it should come to this, when I might have known it and perhaps
+prevented it, if I hadn't been a thoughtless fool!'
+
+Again her large bonnet (very disproportionate to the figure) went
+backwards and forwards, in her swaying of her little body to and fro;
+while a most gigantic bonnet rocked, in unison with it, upon the wall.
+
+'I am surprised,' I began, 'to see you so distressed and serious'-when
+she interrupted me.
+
+'Yes, it's always so!' she said. 'They are all surprised, these
+inconsiderate young people, fairly and full grown, to see any natural
+feeling in a little thing like me! They make a plaything of me, use me
+for their amusement, throw me away when they are tired, and wonder that
+I feel more than a toy horse or a wooden soldier! Yes, yes, that's the
+way. The old way!'
+
+'It may be, with others,' I returned, 'but I do assure you it is not
+with me. Perhaps I ought not to be at all surprised to see you as you
+are now: I know so little of you. I said, without consideration, what I
+thought.'
+
+'What can I do?' returned the little woman, standing up, and holding out
+her arms to show herself. 'See! What I am, my father was; and my sister
+is; and my brother is. I have worked for sister and brother these many
+years--hard, Mr. Copperfield--all day. I must live. I do no harm. If
+there are people so unreflecting or so cruel, as to make a jest of
+me, what is left for me to do but to make a jest of myself, them, and
+everything? If I do so, for the time, whose fault is that? Mine?'
+
+No. Not Miss Mowcher's, I perceived.
+
+'If I had shown myself a sensitive dwarf to your false friend,' pursued
+the little woman, shaking her head at me, with reproachful earnestness,
+'how much of his help or good will do you think I should ever have had?
+If little Mowcher (who had no hand, young gentleman, in the making of
+herself) addressed herself to him, or the like of him, because of her
+misfortunes, when do you suppose her small voice would have been heard?
+Little Mowcher would have as much need to live, if she was the bitterest
+and dullest of pigmies; but she couldn't do it. No. She might whistle
+for her bread and butter till she died of Air.'
+
+Miss Mowcher sat down on the fender again, and took out her
+handkerchief, and wiped her eyes.
+
+'Be thankful for me, if you have a kind heart, as I think you have,' she
+said, 'that while I know well what I am, I can be cheerful and endure it
+all. I am thankful for myself, at any rate, that I can find my tiny way
+through the world, without being beholden to anyone; and that in return
+for all that is thrown at me, in folly or vanity, as I go along, I can
+throw bubbles back. If I don't brood over all I want, it is the better
+for me, and not the worse for anyone. If I am a plaything for you
+giants, be gentle with me.'
+
+Miss Mowcher replaced her handkerchief in her pocket, looking at me with
+very intent expression all the while, and pursued:
+
+'I saw you in the street just now. You may suppose I am not able to
+walk as fast as you, with my short legs and short breath, and I couldn't
+overtake you; but I guessed where you came, and came after you. I have
+been here before, today, but the good woman wasn't at home.'
+
+'Do you know her?' I demanded.
+
+'I know of her, and about her,' she replied, 'from Omer and Joram. I
+was there at seven o'clock this morning. Do you remember what Steerforth
+said to me about this unfortunate girl, that time when I saw you both at
+the inn?'
+
+The great bonnet on Miss Mowcher's head, and the greater bonnet on
+the wall, began to go backwards and forwards again when she asked this
+question.
+
+I remembered very well what she referred to, having had it in my
+thoughts many times that day. I told her so.
+
+'May the Father of all Evil confound him,' said the little woman,
+holding up her forefinger between me and her sparkling eyes, 'and ten
+times more confound that wicked servant; but I believed it was YOU who
+had a boyish passion for her!'
+
+'I?' I repeated.
+
+'Child, child! In the name of blind ill-fortune,' cried Miss Mowcher,
+wringing her hands impatiently, as she went to and fro again upon the
+fender, 'why did you praise her so, and blush, and look disturbed?'
+
+I could not conceal from myself that I had done this, though for a
+reason very different from her supposition.
+
+'What did I know?' said Miss Mowcher, taking out her handkerchief again,
+and giving one little stamp on the ground whenever, at short intervals,
+she applied it to her eyes with both hands at once. 'He was crossing you
+and wheedling you, I saw; and you were soft wax in his hands, I saw. Had
+I left the room a minute, when his man told me that "Young Innocence"
+(so he called you, and you may call him "Old Guilt" all the days of your
+life) had set his heart upon her, and she was giddy and liked him, but
+his master was resolved that no harm should come of it--more for your
+sake than for hers--and that that was their business here? How could I
+BUT believe him? I saw Steerforth soothe and please you by his praise
+of her! You were the first to mention her name. You owned to an old
+admiration of her. You were hot and cold, and red and white, all at once
+when I spoke to you of her. What could I think--what DID I think--but
+that you were a young libertine in everything but experience, and had
+fallen into hands that had experience enough, and could manage you
+(having the fancy) for your own good? Oh! oh! oh! They were afraid of my
+finding out the truth,' exclaimed Miss Mowcher, getting off the
+fender, and trotting up and down the kitchen with her two short arms
+distressfully lifted up, 'because I am a sharp little thing--I need be,
+to get through the world at all!--and they deceived me altogether, and
+I gave the poor unfortunate girl a letter, which I fully believe was
+the beginning of her ever speaking to Littimer, who was left behind on
+purpose!'
+
+I stood amazed at the revelation of all this perfidy, looking at Miss
+Mowcher as she walked up and down the kitchen until she was out of
+breath: when she sat upon the fender again, and, drying her face with
+her handkerchief, shook her head for a long time, without otherwise
+moving, and without breaking silence.
+
+'My country rounds,' she added at length, 'brought me to Norwich, Mr.
+Copperfield, the night before last. What I happened to find there,
+about their secret way of coming and going, without you--which was
+strange--led to my suspecting something wrong. I got into the coach
+from London last night, as it came through Norwich, and was here this
+morning. Oh, oh, oh! too late!'
+
+Poor little Mowcher turned so chilly after all her crying and fretting,
+that she turned round on the fender, putting her poor little wet feet in
+among the ashes to warm them, and sat looking at the fire, like a large
+doll. I sat in a chair on the other side of the hearth, lost in unhappy
+reflections, and looking at the fire too, and sometimes at her.
+
+'I must go,' she said at last, rising as she spoke. 'It's late. You
+don't mistrust me?'
+
+Meeting her sharp glance, which was as sharp as ever when she asked me,
+I could not on that short challenge answer no, quite frankly.
+
+'Come!' said she, accepting the offer of my hand to help her over the
+fender, and looking wistfully up into my face, 'you know you wouldn't
+mistrust me, if I was a full-sized woman!'
+
+I felt that there was much truth in this; and I felt rather ashamed of
+myself.
+
+'You are a young man,' she said, nodding. 'Take a word of advice,
+even from three foot nothing. Try not to associate bodily defects with
+mental, my good friend, except for a solid reason.'
+
+She had got over the fender now, and I had got over my suspicion. I told
+her that I believed she had given me a faithful account of herself,
+and that we had both been hapless instruments in designing hands. She
+thanked me, and said I was a good fellow.
+
+'Now, mind!' she exclaimed, turning back on her way to the door, and
+looking shrewdly at me, with her forefinger up again.--'I have some
+reason to suspect, from what I have heard--my ears are always open; I
+can't afford to spare what powers I have--that they are gone abroad. But
+if ever they return, if ever any one of them returns, while I am alive,
+I am more likely than another, going about as I do, to find it out soon.
+Whatever I know, you shall know. If ever I can do anything to serve the
+poor betrayed girl, I will do it faithfully, please Heaven! And Littimer
+had better have a bloodhound at his back, than little Mowcher!'
+
+I placed implicit faith in this last statement, when I marked the look
+with which it was accompanied.
+
+'Trust me no more, but trust me no less, than you would trust a
+full-sized woman,' said the little creature, touching me appealingly
+on the wrist. 'If ever you see me again, unlike what I am now, and like
+what I was when you first saw me, observe what company I am in. Call to
+mind that I am a very helpless and defenceless little thing. Think of
+me at home with my brother like myself and sister like myself, when my
+day's work is done. Perhaps you won't, then, be very hard upon me, or
+surprised if I can be distressed and serious. Good night!'
+
+I gave Miss Mowcher my hand, with a very different opinion of her from
+that which I had hitherto entertained, and opened the door to let her
+out. It was not a trifling business to get the great umbrella up, and
+properly balanced in her grasp; but at last I successfully accomplished
+this, and saw it go bobbing down the street through the rain, without
+the least appearance of having anybody underneath it, except when a
+heavier fall than usual from some over-charged water-spout sent it
+toppling over, on one side, and discovered Miss Mowcher struggling
+violently to get it right. After making one or two sallies to her
+relief, which were rendered futile by the umbrella's hopping on again,
+like an immense bird, before I could reach it, I came in, went to bed,
+and slept till morning.
+
+In the morning I was joined by Mr. Peggotty and by my old nurse, and we
+went at an early hour to the coach office, where Mrs. Gummidge and Ham
+were waiting to take leave of us.
+
+'Mas'r Davy,' Ham whispered, drawing me aside, while Mr. Peggotty was
+stowing his bag among the luggage, 'his life is quite broke up. He
+doen't know wheer he's going; he doen't know--what's afore him; he's
+bound upon a voyage that'll last, on and off, all the rest of his days,
+take my wured for 't, unless he finds what he's a seeking of. I am sure
+you'll be a friend to him, Mas'r Davy?'
+
+'Trust me, I will indeed,' said I, shaking hands with Ham earnestly.
+
+'Thankee. Thankee, very kind, sir. One thing furder. I'm in good employ,
+you know, Mas'r Davy, and I han't no way now of spending what I gets.
+Money's of no use to me no more, except to live. If you can lay it out
+for him, I shall do my work with a better art. Though as to that, sir,'
+and he spoke very steadily and mildly, 'you're not to think but I shall
+work at all times, like a man, and act the best that lays in my power!'
+
+I told him I was well convinced of it; and I hinted that I hoped the
+time might even come, when he would cease to lead the lonely life he
+naturally contemplated now.
+
+'No, sir,' he said, shaking his head, 'all that's past and over with me,
+sir. No one can never fill the place that's empty. But you'll bear in
+mind about the money, as theer's at all times some laying by for him?'
+
+Reminding him of the fact, that Mr. Peggotty derived a steady,
+though certainly a very moderate income from the bequest of his late
+brother-in-law, I promised to do so. We then took leave of each other. I
+cannot leave him even now, without remembering with a pang, at once his
+modest fortitude and his great sorrow.
+
+As to Mrs. Gummidge, if I were to endeavour to describe how she ran down
+the street by the side of the coach, seeing nothing but Mr. Peggotty on
+the roof, through the tears she tried to repress, and dashing herself
+against the people who were coming in the opposite direction, I should
+enter on a task of some difficulty. Therefore I had better leave her
+sitting on a baker's door-step, out of breath, with no shape at all
+remaining in her bonnet, and one of her shoes off, lying on the pavement
+at a considerable distance.
+
+When we got to our journey's end, our first pursuit was to look about
+for a little lodging for Peggotty, where her brother could have a
+bed. We were so fortunate as to find one, of a very clean and cheap
+description, over a chandler's shop, only two streets removed from
+me. When we had engaged this domicile, I bought some cold meat at an
+eating-house, and took my fellow-travellers home to tea; a proceeding,
+I regret to state, which did not meet with Mrs. Crupp's approval, but
+quite the contrary. I ought to observe, however, in explanation of that
+lady's state of mind, that she was much offended by Peggotty's tucking
+up her widow's gown before she had been ten minutes in the place, and
+setting to work to dust my bedroom. This Mrs. Crupp regarded in the
+light of a liberty, and a liberty, she said, was a thing she never
+allowed.
+
+Mr. Peggotty had made a communication to me on the way to London for
+which I was not unprepared. It was, that he purposed first seeing Mrs.
+Steerforth. As I felt bound to assist him in this, and also to mediate
+between them; with the view of sparing the mother's feelings as much
+as possible, I wrote to her that night. I told her as mildly as I could
+what his wrong was, and what my own share in his injury. I said he was a
+man in very common life, but of a most gentle and upright character; and
+that I ventured to express a hope that she would not refuse to see him
+in his heavy trouble. I mentioned two o'clock in the afternoon as the
+hour of our coming, and I sent the letter myself by the first coach in
+the morning.
+
+At the appointed time, we stood at the door--the door of that house
+where I had been, a few days since, so happy: where my youthful
+confidence and warmth of heart had been yielded up so freely: which was
+closed against me henceforth: which was now a waste, a ruin.
+
+No Littimer appeared. The pleasanter face which had replaced his, on the
+occasion of my last visit, answered to our summons, and went before
+us to the drawing-room. Mrs. Steerforth was sitting there. Rosa Dartle
+glided, as we went in, from another part of the room and stood behind
+her chair.
+
+I saw, directly, in his mother's face, that she knew from himself what
+he had done. It was very pale; and bore the traces of deeper emotion
+than my letter alone, weakened by the doubts her fondness would have
+raised upon it, would have been likely to create. I thought her more
+like him than ever I had thought her; and I felt, rather than saw, that
+the resemblance was not lost on my companion.
+
+She sat upright in her arm-chair, with a stately, immovable, passionless
+air, that it seemed as if nothing could disturb. She looked very
+steadfastly at Mr. Peggotty when he stood before her; and he looked
+quite as steadfastly at her. Rosa Dartle's keen glance comprehended all
+of us. For some moments not a word was spoken.
+
+She motioned to Mr. Peggotty to be seated. He said, in a low voice, 'I
+shouldn't feel it nat'ral, ma'am, to sit down in this house. I'd sooner
+stand.' And this was succeeded by another silence, which she broke thus:
+
+'I know, with deep regret, what has brought you here. What do you want
+of me? What do you ask me to do?'
+
+He put his hat under his arm, and feeling in his breast for Emily's
+letter, took it out, unfolded it, and gave it to her. 'Please to read
+that, ma'am. That's my niece's hand!'
+
+She read it, in the same stately and impassive way,--untouched by its
+contents, as far as I could see,--and returned it to him.
+
+'"Unless he brings me back a lady,"' said Mr. Peggotty, tracing out that
+part with his finger. 'I come to know, ma'am, whether he will keep his
+wured?'
+
+'No,' she returned.
+
+'Why not?' said Mr. Peggotty.
+
+'It is impossible. He would disgrace himself. You cannot fail to know
+that she is far below him.'
+
+'Raise her up!' said Mr. Peggotty.
+
+'She is uneducated and ignorant.'
+
+'Maybe she's not; maybe she is,' said Mr. Peggotty. 'I think not, ma'am;
+but I'm no judge of them things. Teach her better!'
+
+'Since you oblige me to speak more plainly, which I am very unwilling
+to do, her humble connexions would render such a thing impossible, if
+nothing else did.'
+
+'Hark to this, ma'am,' he returned, slowly and quietly. 'You know what
+it is to love your child. So do I. If she was a hundred times my child,
+I couldn't love her more. You doen't know what it is to lose your child.
+I do. All the heaps of riches in the wureld would be nowt to me (if they
+was mine) to buy her back! But, save her from this disgrace, and she
+shall never be disgraced by us. Not one of us that she's growed up
+among, not one of us that's lived along with her and had her for their
+all in all, these many year, will ever look upon her pritty face again.
+We'll be content to let her be; we'll be content to think of her, far
+off, as if she was underneath another sun and sky; we'll be content to
+trust her to her husband,--to her little children, p'raps,--and bide the
+time when all of us shall be alike in quality afore our God!'
+
+The rugged eloquence with which he spoke, was not devoid of all effect.
+She still preserved her proud manner, but there was a touch of softness
+in her voice, as she answered:
+
+'I justify nothing. I make no counter-accusations. But I am sorry to
+repeat, it is impossible. Such a marriage would irretrievably blight my
+son's career, and ruin his prospects. Nothing is more certain than
+that it never can take place, and never will. If there is any other
+compensation--'
+
+'I am looking at the likeness of the face,' interrupted Mr. Peggotty,
+with a steady but a kindling eye, 'that has looked at me, in my home, at
+my fireside, in my boat--wheer not?---smiling and friendly, when it was
+so treacherous, that I go half wild when I think of it. If the likeness
+of that face don't turn to burning fire, at the thought of offering
+money to me for my child's blight and ruin, it's as bad. I doen't know,
+being a lady's, but what it's worse.'
+
+She changed now, in a moment. An angry flush overspread her features;
+and she said, in an intolerant manner, grasping the arm-chair tightly
+with her hands:
+
+'What compensation can you make to ME for opening such a pit between me
+and my son? What is your love to mine? What is your separation to ours?'
+
+Miss Dartle softly touched her, and bent down her head to whisper, but
+she would not hear a word.
+
+'No, Rosa, not a word! Let the man listen to what I say! My son, who has
+been the object of my life, to whom its every thought has been devoted,
+whom I have gratified from a child in every wish, from whom I have had
+no separate existence since his birth,--to take up in a moment with a
+miserable girl, and avoid me! To repay my confidence with systematic
+deception, for her sake, and quit me for her! To set this wretched
+fancy, against his mother's claims upon his duty, love, respect,
+gratitude--claims that every day and hour of his life should have
+strengthened into ties that nothing could be proof against! Is this no
+injury?'
+
+Again Rosa Dartle tried to soothe her; again ineffectually.
+
+'I say, Rosa, not a word! If he can stake his all upon the lightest
+object, I can stake my all upon a greater purpose. Let him go where he
+will, with the means that my love has secured to him! Does he think to
+reduce me by long absence? He knows his mother very little if he does.
+Let him put away his whim now, and he is welcome back. Let him not put
+her away now, and he never shall come near me, living or dying, while
+I can raise my hand to make a sign against it, unless, being rid of her
+for ever, he comes humbly to me and begs for my forgiveness. This is my
+right. This is the acknowledgement I WILL HAVE. This is the separation
+that there is between us! And is this,' she added, looking at her
+visitor with the proud intolerant air with which she had begun, 'no
+injury?'
+
+While I heard and saw the mother as she said these words, I seemed to
+hear and see the son, defying them. All that I had ever seen in him of
+an unyielding, wilful spirit, I saw in her. All the understanding that
+I had now of his misdirected energy, became an understanding of her
+character too, and a perception that it was, in its strongest springs,
+the same.
+
+She now observed to me, aloud, resuming her former restraint, that it
+was useless to hear more, or to say more, and that she begged to put an
+end to the interview. She rose with an air of dignity to leave the room,
+when Mr. Peggotty signified that it was needless.
+
+'Doen't fear me being any hindrance to you, I have no more to say,
+ma'am,' he remarked, as he moved towards the door. 'I come beer with no
+hope, and I take away no hope. I have done what I thowt should be done,
+but I never looked fur any good to come of my stan'ning where I do.
+This has been too evil a house fur me and mine, fur me to be in my right
+senses and expect it.'
+
+With this, we departed; leaving her standing by her elbow-chair, a
+picture of a noble presence and a handsome face.
+
+We had, on our way out, to cross a paved hall, with glass sides and
+roof, over which a vine was trained. Its leaves and shoots were green
+then, and the day being sunny, a pair of glass doors leading to the
+garden were thrown open. Rosa Dartle, entering this way with a noiseless
+step, when we were close to them, addressed herself to me:
+
+'You do well,' she said, 'indeed, to bring this fellow here!'
+
+Such a concentration of rage and scorn as darkened her face, and flashed
+in her jet-black eyes, I could not have thought compressible even into
+that face. The scar made by the hammer was, as usual in this excited
+state of her features, strongly marked. When the throbbing I had seen
+before, came into it as I looked at her, she absolutely lifted up her
+hand, and struck it.
+
+'This is a fellow,' she said, 'to champion and bring here, is he not?
+You are a true man!'
+
+'Miss Dartle,' I returned, 'you are surely not so unjust as to condemn
+ME!'
+
+'Why do you bring division between these two mad creatures?' she
+returned. 'Don't you know that they are both mad with their own
+self-will and pride?'
+
+'Is it my doing?' I returned.
+
+'Is it your doing!' she retorted. 'Why do you bring this man here?'
+
+'He is a deeply-injured man, Miss Dartle,' I replied. 'You may not know
+it.'
+
+'I know that James Steerforth,' she said, with her hand on her bosom, as
+if to prevent the storm that was raging there, from being loud, 'has
+a false, corrupt heart, and is a traitor. But what need I know or care
+about this fellow, and his common niece?'
+
+'Miss Dartle,' I returned, 'you deepen the injury. It is sufficient
+already. I will only say, at parting, that you do him a great wrong.'
+
+'I do him no wrong,' she returned. 'They are a depraved, worthless set.
+I would have her whipped!'
+
+Mr. Peggotty passed on, without a word, and went out at the door.
+
+'Oh, shame, Miss Dartle! shame!' I said indignantly. 'How can you bear
+to trample on his undeserved affliction!'
+
+'I would trample on them all,' she answered. 'I would have his house
+pulled down. I would have her branded on the face, dressed in rags,
+and cast out in the streets to starve. If I had the power to sit in
+judgement on her, I would see it done. See it done? I would do it! I
+detest her. If I ever could reproach her with her infamous condition, I
+would go anywhere to do so. If I could hunt her to her grave, I would.
+If there was any word of comfort that would be a solace to her in her
+dying hour, and only I possessed it, I wouldn't part with it for Life
+itself.'
+
+The mere vehemence of her words can convey, I am sensible, but a weak
+impression of the passion by which she was possessed, and which made
+itself articulate in her whole figure, though her voice, instead of
+being raised, was lower than usual. No description I could give of her
+would do justice to my recollection of her, or to her entire deliverance
+of herself to her anger. I have seen passion in many forms, but I have
+never seen it in such a form as that.
+
+When I joined Mr. Peggotty, he was walking slowly and thoughtfully down
+the hill. He told me, as soon as I came up with him, that having now
+discharged his mind of what he had purposed doing in London, he meant
+'to set out on his travels', that night. I asked him where he meant to
+go? He only answered, 'I'm a going, sir, to seek my niece.'
+
+We went back to the little lodging over the chandler's shop, and there
+I found an opportunity of repeating to Peggotty what he had said to
+me. She informed me, in return, that he had said the same to her that
+morning. She knew no more than I did, where he was going, but she
+thought he had some project shaped out in his mind.
+
+I did not like to leave him, under such circumstances, and we all three
+dined together off a beefsteak pie--which was one of the many good
+things for which Peggotty was famous--and which was curiously flavoured
+on this occasion, I recollect well, by a miscellaneous taste of tea,
+coffee, butter, bacon, cheese, new loaves, firewood, candles, and walnut
+ketchup, continually ascending from the shop. After dinner we sat for an
+hour or so near the window, without talking much; and then Mr. Peggotty
+got up, and brought his oilskin bag and his stout stick, and laid them
+on the table.
+
+He accepted, from his sister's stock of ready money, a small sum on
+account of his legacy; barely enough, I should have thought, to keep him
+for a month. He promised to communicate with me, when anything befell
+him; and he slung his bag about him, took his hat and stick, and bade us
+both 'Good-bye!'
+
+'All good attend you, dear old woman,' he said, embracing Peggotty, 'and
+you too, Mas'r Davy!' shaking hands with me. 'I'm a-going to seek her,
+fur and wide. If she should come home while I'm away--but ah, that ain't
+like to be!--or if I should bring her back, my meaning is, that she
+and me shall live and die where no one can't reproach her. If any hurt
+should come to me, remember that the last words I left for her was, "My
+unchanged love is with my darling child, and I forgive her!"'
+
+He said this solemnly, bare-headed; then, putting on his hat, he went
+down the stairs, and away. We followed to the door. It was a warm, dusty
+evening, just the time when, in the great main thoroughfare out of which
+that by-way turned, there was a temporary lull in the eternal tread of
+feet upon the pavement, and a strong red sunshine. He turned, alone, at
+the corner of our shady street, into a glow of light, in which we lost
+him.
+
+Rarely did that hour of the evening come, rarely did I wake at night,
+rarely did I look up at the moon, or stars, or watch the falling rain,
+or hear the wind, but I thought of his solitary figure toiling on, poor
+pilgrim, and recalled the words:
+
+'I'm a going to seek her, fur and wide. If any hurt should come to me,
+remember that the last words I left for her was, "My unchanged love is
+with my darling child, and I forgive her!"'
+
+
+
+CHAPTER 33. BLISSFUL
+
+
+All this time, I had gone on loving Dora, harder than ever. Her idea was
+my refuge in disappointment and distress, and made some amends to me,
+even for the loss of my friend. The more I pitied myself, or pitied
+others, the more I sought for consolation in the image of Dora. The
+greater the accumulation of deceit and trouble in the world, the
+brighter and the purer shone the star of Dora high above the world. I
+don't think I had any definite idea where Dora came from, or in what
+degree she was related to a higher order of beings; but I am quite sure
+I should have scouted the notion of her being simply human, like any
+other young lady, with indignation and contempt.
+
+If I may so express it, I was steeped in Dora. I was not merely over
+head and ears in love with her, but I was saturated through and through.
+Enough love might have been wrung out of me, metaphorically speaking,
+to drown anybody in; and yet there would have remained enough within me,
+and all over me, to pervade my entire existence.
+
+The first thing I did, on my own account, when I came back, was to take
+a night-walk to Norwood, and, like the subject of a venerable riddle of
+my childhood, to go 'round and round the house, without ever
+touching the house', thinking about Dora. I believe the theme of this
+incomprehensible conundrum was the moon. No matter what it was, I, the
+moon-struck slave of Dora, perambulated round and round the house and
+garden for two hours, looking through crevices in the palings, getting
+my chin by dint of violent exertion above the rusty nails on the top,
+blowing kisses at the lights in the windows, and romantically calling
+on the night, at intervals, to shield my Dora--I don't exactly know what
+from, I suppose from fire. Perhaps from mice, to which she had a great
+objection.
+
+My love was so much in my mind and it was so natural to me to confide in
+Peggotty, when I found her again by my side of an evening with the old
+set of industrial implements, busily making the tour of my wardrobe,
+that I imparted to her, in a sufficiently roundabout way, my great
+secret. Peggotty was strongly interested, but I could not get her into
+my view of the case at all. She was audaciously prejudiced in my favour,
+and quite unable to understand why I should have any misgivings, or be
+low-spirited about it. 'The young lady might think herself well off,'
+she observed, 'to have such a beau. And as to her Pa,' she said, 'what
+did the gentleman expect, for gracious sake!'
+
+I observed, however, that Mr. Spenlow's proctorial gown and stiff cravat
+took Peggotty down a little, and inspired her with a greater reverence
+for the man who was gradually becoming more and more etherealized in my
+eyes every day, and about whom a reflected radiance seemed to me to beam
+when he sat erect in Court among his papers, like a little lighthouse in
+a sea of stationery. And by the by, it used to be uncommonly strange
+to me to consider, I remember, as I sat in Court too, how those dim old
+judges and doctors wouldn't have cared for Dora, if they had known
+her; how they wouldn't have gone out of their senses with rapture, if
+marriage with Dora had been proposed to them; how Dora might have sung,
+and played upon that glorified guitar, until she led me to the verge of
+madness, yet not have tempted one of those slow-goers an inch out of his
+road!
+
+I despised them, to a man. Frozen-out old gardeners in the flower-beds
+of the heart, I took a personal offence against them all. The Bench
+was nothing to me but an insensible blunderer. The Bar had no more
+tenderness or poetry in it, than the bar of a public-house.
+
+Taking the management of Peggotty's affairs into my own hands, with
+no little pride, I proved the will, and came to a settlement with the
+Legacy Duty-office, and took her to the Bank, and soon got everything
+into an orderly train. We varied the legal character of these
+proceedings by going to see some perspiring Wax-work, in Fleet Street
+(melted, I should hope, these twenty years); and by visiting Miss
+Linwood's Exhibition, which I remember as a Mausoleum of needlework,
+favourable to self-examination and repentance; and by inspecting the
+Tower of London; and going to the top of St. Paul's. All these wonders
+afforded Peggotty as much pleasure as she was able to enjoy, under
+existing circumstances: except, I think, St. Paul's, which, from her
+long attachment to her work-box, became a rival of the picture on the
+lid, and was, in some particulars, vanquished, she considered, by that
+work of art.
+
+Peggotty's business, which was what we used to call 'common-form
+business' in the Commons (and very light and lucrative the common-form
+business was), being settled, I took her down to the office one morning
+to pay her bill. Mr. Spenlow had stepped out, old Tiffey said, to get a
+gentleman sworn for a marriage licence; but as I knew he would be
+back directly, our place lying close to the Surrogate's, and to the
+Vicar-General's office too, I told Peggotty to wait.
+
+We were a little like undertakers, in the Commons, as regarded Probate
+transactions; generally making it a rule to look more or less cut up,
+when we had to deal with clients in mourning. In a similar feeling
+of delicacy, we were always blithe and light-hearted with the licence
+clients. Therefore I hinted to Peggotty that she would find Mr. Spenlow
+much recovered from the shock of Mr. Barkis's decease; and indeed he
+came in like a bridegroom.
+
+But neither Peggotty nor I had eyes for him, when we saw, in company
+with him, Mr. Murdstone. He was very little changed. His hair looked as
+thick, and was certainly as black, as ever; and his glance was as little
+to be trusted as of old.
+
+'Ah, Copperfield?' said Mr. Spenlow. 'You know this gentleman, I
+believe?'
+
+I made my gentleman a distant bow, and Peggotty barely recognized him.
+He was, at first, somewhat disconcerted to meet us two together; but
+quickly decided what to do, and came up to me.
+
+'I hope,' he said, 'that you are doing well?'
+
+'It can hardly be interesting to you,' said I. 'Yes, if you wish to
+know.'
+
+We looked at each other, and he addressed himself to Peggotty.
+
+'And you,' said he. 'I am sorry to observe that you have lost your
+husband.'
+
+'It's not the first loss I have had in my life, Mr. Murdstone,' replied
+Peggotty, trembling from head to foot. 'I am glad to hope that there is
+nobody to blame for this one,--nobody to answer for it.'
+
+'Ha!' said he; 'that's a comfortable reflection. You have done your
+duty?'
+
+'I have not worn anybody's life away,' said Peggotty, 'I am thankful to
+think! No, Mr. Murdstone, I have not worrited and frightened any sweet
+creetur to an early grave!'
+
+He eyed her gloomily--remorsefully I thought--for an instant; and said,
+turning his head towards me, but looking at my feet instead of my face:
+
+'We are not likely to encounter soon again;--a source of satisfaction to
+us both, no doubt, for such meetings as this can never be agreeable. I
+do not expect that you, who always rebelled against my just authority,
+exerted for your benefit and reformation, should owe me any good-will
+now. There is an antipathy between us--'
+
+'An old one, I believe?' said I, interrupting him.
+
+He smiled, and shot as evil a glance at me as could come from his dark
+eyes.
+
+'It rankled in your baby breast,' he said. 'It embittered the life of
+your poor mother. You are right. I hope you may do better, yet; I hope
+you may correct yourself.'
+
+Here he ended the dialogue, which had been carried on in a low voice,
+in a corner of the outer office, by passing into Mr. Spenlow's room, and
+saying aloud, in his smoothest manner:
+
+'Gentlemen of Mr. Spenlow's profession are accustomed to family
+differences, and know how complicated and difficult they always are!'
+With that, he paid the money for his licence; and, receiving it neatly
+folded from Mr. Spenlow, together with a shake of the hand, and a polite
+wish for his happiness and the lady's, went out of the office.
+
+I might have had more difficulty in constraining myself to be silent
+under his words, if I had had less difficulty in impressing upon
+Peggotty (who was only angry on my account, good creature!) that we were
+not in a place for recrimination, and that I besought her to hold her
+peace. She was so unusually roused, that I was glad to compound for
+an affectionate hug, elicited by this revival in her mind of our old
+injuries, and to make the best I could of it, before Mr. Spenlow and the
+clerks.
+
+Mr. Spenlow did not appear to know what the connexion between Mr.
+Murdstone and myself was; which I was glad of, for I could not bear to
+acknowledge him, even in my own breast, remembering what I did of the
+history of my poor mother. Mr. Spenlow seemed to think, if he thought
+anything about the matter, that my aunt was the leader of the state
+party in our family, and that there was a rebel party commanded by
+somebody else--so I gathered at least from what he said, while we were
+waiting for Mr. Tiffey to make out Peggotty's bill of costs.
+
+'Miss Trotwood,' he remarked, 'is very firm, no doubt, and not likely
+to give way to opposition. I have an admiration for her character, and
+I may congratulate you, Copperfield, on being on the right side.
+Differences between relations are much to be deplored--but they are
+extremely general--and the great thing is, to be on the right side':
+meaning, I take it, on the side of the moneyed interest.
+
+'Rather a good marriage this, I believe?' said Mr. Spenlow.
+
+I explained that I knew nothing about it.
+
+'Indeed!' he said. 'Speaking from the few words Mr. Murdstone
+dropped--as a man frequently does on these occasions--and from what Miss
+Murdstone let fall, I should say it was rather a good marriage.'
+
+'Do you mean that there is money, sir?' I asked.
+
+'Yes,' said Mr. Spenlow, 'I understand there's money. Beauty too, I am
+told.'
+
+'Indeed! Is his new wife young?'
+
+'Just of age,' said Mr. Spenlow. 'So lately, that I should think they
+had been waiting for that.'
+
+'Lord deliver her!' said Peggotty. So very emphatically and
+unexpectedly, that we were all three discomposed; until Tiffey came in
+with the bill.
+
+Old Tiffey soon appeared, however, and handed it to Mr. Spenlow, to
+look over. Mr. Spenlow, settling his chin in his cravat and rubbing it
+softly, went over the items with a deprecatory air--as if it were all
+Jorkins's doing--and handed it back to Tiffey with a bland sigh.
+
+'Yes,' he said. 'That's right. Quite right. I should have been extremely
+happy, Copperfield, to have limited these charges to the actual
+expenditure out of pocket, but it is an irksome incident in my
+professional life, that I am not at liberty to consult my own wishes. I
+have a partner--Mr. Jorkins.'
+
+As he said this with a gentle melancholy, which was the next thing to
+making no charge at all, I expressed my acknowledgements on Peggotty's
+behalf, and paid Tiffey in banknotes. Peggotty then retired to
+her lodging, and Mr. Spenlow and I went into Court, where we had a
+divorce-suit coming on, under an ingenious little statute (repealed
+now, I believe, but in virtue of which I have seen several marriages
+annulled), of which the merits were these. The husband, whose name was
+Thomas Benjamin, had taken out his marriage licence as Thomas only;
+suppressing the Benjamin, in case he should not find himself as
+comfortable as he expected. NOT finding himself as comfortable as he
+expected, or being a little fatigued with his wife, poor fellow, he
+now came forward, by a friend, after being married a year or two, and
+declared that his name was Thomas Benjamin, and therefore he was not
+married at all. Which the Court confirmed, to his great satisfaction.
+
+I must say that I had my doubts about the strict justice of this,
+and was not even frightened out of them by the bushel of wheat which
+reconciles all anomalies. But Mr. Spenlow argued the matter with me. He
+said, Look at the world, there was good and evil in that; look at the
+ecclesiastical law, there was good and evil in THAT. It was all part of
+a system. Very good. There you were!
+
+I had not the hardihood to suggest to Dora's father that possibly
+we might even improve the world a little, if we got up early in the
+morning, and took off our coats to the work; but I confessed that I
+thought we might improve the Commons. Mr. Spenlow replied that he would
+particularly advise me to dismiss that idea from my mind, as not being
+worthy of my gentlemanly character; but that he would be glad to hear
+from me of what improvement I thought the Commons susceptible?
+
+Taking that part of the Commons which happened to be nearest to us--for
+our man was unmarried by this time, and we were out of Court, and
+strolling past the Prerogative Office--I submitted that I thought the
+Prerogative Office rather a queerly managed institution. Mr. Spenlow
+inquired in what respect? I replied, with all due deference to his
+experience (but with more deference, I am afraid, to his being Dora's
+father), that perhaps it was a little nonsensical that the Registry of
+that Court, containing the original wills of all persons leaving effects
+within the immense province of Canterbury, for three whole centuries,
+should be an accidental building, never designed for the purpose, leased
+by the registrars for their Own private emolument, unsafe, not even
+ascertained to be fire-proof, choked with the important documents
+it held, and positively, from the roof to the basement, a mercenary
+speculation of the registrars, who took great fees from the public, and
+crammed the public's wills away anyhow and anywhere, having no other
+object than to get rid of them cheaply. That, perhaps, it was a little
+unreasonable that these registrars in the receipt of profits amounting
+to eight or nine thousand pounds a year (to say nothing of the profits
+of the deputy registrars, and clerks of seats), should not be obliged to
+spend a little of that money, in finding a reasonably safe place for the
+important documents which all classes of people were compelled to hand
+over to them, whether they would or no. That, perhaps, it was a little
+unjust, that all the great offices in this great office should be
+magnificent sinecures, while the unfortunate working-clerks in the cold
+dark room upstairs were the worst rewarded, and the least considered
+men, doing important services, in London. That perhaps it was a little
+indecent that the principal registrar of all, whose duty it was to
+find the public, constantly resorting to this place, all needful
+accommodation, should be an enormous sinecurist in virtue of that post
+(and might be, besides, a clergyman, a pluralist, the holder of a
+staff in a cathedral, and what not),--while the public was put to the
+inconvenience of which we had a specimen every afternoon when the office
+was busy, and which we knew to be quite monstrous. That, perhaps,
+in short, this Prerogative Office of the diocese of Canterbury was
+altogether such a pestilent job, and such a pernicious absurdity, that
+but for its being squeezed away in a corner of St. Paul's Churchyard,
+which few people knew, it must have been turned completely inside out,
+and upside down, long ago.
+
+Mr. Spenlow smiled as I became modestly warm on the subject, and then
+argued this question with me as he had argued the other. He said, what
+was it after all? It was a question of feeling. If the public felt
+that their wills were in safe keeping, and took it for granted that the
+office was not to be made better, who was the worse for it? Nobody. Who
+was the better for it? All the Sinecurists. Very well. Then the good
+predominated. It might not be a perfect system; nothing was perfect;
+but what he objected to, was, the insertion of the wedge. Under the
+Prerogative Office, the country had been glorious. Insert the wedge into
+the Prerogative Office, and the country would cease to be glorious. He
+considered it the principle of a gentleman to take things as he found
+them; and he had no doubt the Prerogative Office would last our time. I
+deferred to his opinion, though I had great doubts of it myself. I find
+he was right, however; for it has not only lasted to the present moment,
+but has done so in the teeth of a great parliamentary report made (not
+too willingly) eighteen years ago, when all these objections of mine
+were set forth in detail, and when the existing stowage for wills was
+described as equal to the accumulation of only two years and a half
+more. What they have done with them since; whether they have lost many,
+or whether they sell any, now and then, to the butter shops; I don't
+know. I am glad mine is not there, and I hope it may not go there, yet
+awhile.
+
+I have set all this down, in my present blissful chapter, because here
+it comes into its natural place. Mr. Spenlow and I falling into this
+conversation, prolonged it and our saunter to and fro, until we diverged
+into general topics. And so it came about, in the end, that Mr. Spenlow
+told me this day week was Dora's birthday, and he would be glad if I
+would come down and join a little picnic on the occasion. I went out of
+my senses immediately; became a mere driveller next day, on receipt of
+a little lace-edged sheet of note-paper, 'Favoured by papa. To remind';
+and passed the intervening period in a state of dotage.
+
+I think I committed every possible absurdity in the way of preparation
+for this blessed event. I turn hot when I remember the cravat I bought.
+My boots might be placed in any collection of instruments of torture.
+I provided, and sent down by the Norwood coach the night before, a
+delicate little hamper, amounting in itself, I thought, almost to a
+declaration. There were crackers in it with the tenderest mottoes that
+could be got for money. At six in the morning, I was in Covent Garden
+Market, buying a bouquet for Dora. At ten I was on horseback (I hired a
+gallant grey, for the occasion), with the bouquet in my hat, to keep it
+fresh, trotting down to Norwood.
+
+I suppose that when I saw Dora in the garden and pretended not to see
+her, and rode past the house pretending to be anxiously looking for
+it, I committed two small fooleries which other young gentlemen in my
+circumstances might have committed--because they came so very natural
+to me. But oh! when I DID find the house, and DID dismount at the
+garden-gate, and drag those stony-hearted boots across the lawn to Dora
+sitting on a garden-seat under a lilac tree, what a spectacle she was,
+upon that beautiful morning, among the butterflies, in a white chip
+bonnet and a dress of celestial blue! There was a young lady with
+her--comparatively stricken in years--almost twenty, I should say. Her
+name was Miss Mills. And Dora called her Julia. She was the bosom friend
+of Dora. Happy Miss Mills!
+
+Jip was there, and Jip WOULD bark at me again. When I presented my
+bouquet, he gnashed his teeth with jealousy. Well he might. If he had
+the least idea how I adored his mistress, well he might!
+
+'Oh, thank you, Mr. Copperfield! What dear flowers!' said Dora.
+
+I had had an intention of saying (and had been studying the best form of
+words for three miles) that I thought them beautiful before I saw them
+so near HER. But I couldn't manage it. She was too bewildering. To see
+her lay the flowers against her little dimpled chin, was to lose all
+presence of mind and power of language in a feeble ecstasy. I wonder I
+didn't say, 'Kill me, if you have a heart, Miss Mills. Let me die here!'
+
+Then Dora held my flowers to Jip to smell. Then Jip growled, and
+wouldn't smell them. Then Dora laughed, and held them a little closer
+to Jip, to make him. Then Jip laid hold of a bit of geranium with his
+teeth, and worried imaginary cats in it. Then Dora beat him, and pouted,
+and said, 'My poor beautiful flowers!' as compassionately, I thought, as
+if Jip had laid hold of me. I wished he had!
+
+'You'll be so glad to hear, Mr. Copperfield,' said Dora, 'that that
+cross Miss Murdstone is not here. She has gone to her brother's
+marriage, and will be away at least three weeks. Isn't that delightful?'
+
+I said I was sure it must be delightful to her, and all that was
+delightful to her was delightful to me. Miss Mills, with an air of
+superior wisdom and benevolence, smiled upon us.
+
+'She is the most disagreeable thing I ever saw,' said Dora. 'You can't
+believe how ill-tempered and shocking she is, Julia.'
+
+'Yes, I can, my dear!' said Julia.
+
+'YOU can, perhaps, love,' returned Dora, with her hand on julia's.
+'Forgive my not excepting you, my dear, at first.'
+
+I learnt, from this, that Miss Mills had had her trials in the course
+of a chequered existence; and that to these, perhaps, I might refer that
+wise benignity of manner which I had already noticed. I found, in
+the course of the day, that this was the case: Miss Mills having been
+unhappy in a misplaced affection, and being understood to have retired
+from the world on her awful stock of experience, but still to take a
+calm interest in the unblighted hopes and loves of youth.
+
+But now Mr. Spenlow came out of the house, and Dora went to him,
+saying, 'Look, papa, what beautiful flowers!' And Miss Mills smiled
+thoughtfully, as who should say, 'Ye Mayflies, enjoy your brief
+existence in the bright morning of life!' And we all walked from the
+lawn towards the carriage, which was getting ready.
+
+I shall never have such a ride again. I have never had such another.
+There were only those three, their hamper, my hamper, and the
+guitar-case, in the phaeton; and, of course, the phaeton was open; and
+I rode behind it, and Dora sat with her back to the horses, looking
+towards me. She kept the bouquet close to her on the cushion, and
+wouldn't allow Jip to sit on that side of her at all, for fear he should
+crush it. She often carried it in her hand, often refreshed herself
+with its fragrance. Our eyes at those times often met; and my great
+astonishment is that I didn't go over the head of my gallant grey into
+the carriage.
+
+There was dust, I believe. There was a good deal of dust, I believe. I
+have a faint impression that Mr. Spenlow remonstrated with me for riding
+in it; but I knew of none. I was sensible of a mist of love and beauty
+about Dora, but of nothing else. He stood up sometimes, and asked me
+what I thought of the prospect. I said it was delightful, and I dare
+say it was; but it was all Dora to me. The sun shone Dora, and the birds
+sang Dora. The south wind blew Dora, and the wild flowers in the hedges
+were all Doras, to a bud. My comfort is, Miss Mills understood me. Miss
+Mills alone could enter into my feelings thoroughly.
+
+I don't know how long we were going, and to this hour I know as little
+where we went. Perhaps it was near Guildford. Perhaps some Arabian-night
+magician, opened up the place for the day, and shut it up for ever when
+we came away. It was a green spot, on a hill, carpeted with soft turf.
+There were shady trees, and heather, and, as far as the eye could see, a
+rich landscape.
+
+It was a trying thing to find people here, waiting for us; and my
+jealousy, even of the ladies, knew no bounds. But all of my own
+sex--especially one impostor, three or four years my elder, with a red
+whisker, on which he established an amount of presumption not to be
+endured--were my mortal foes.
+
+We all unpacked our baskets, and employed ourselves in getting dinner
+ready. Red Whisker pretended he could make a salad (which I don't
+believe), and obtruded himself on public notice. Some of the young
+ladies washed the lettuces for him, and sliced them under his
+directions. Dora was among these. I felt that fate had pitted me against
+this man, and one of us must fall.
+
+Red Whisker made his salad (I wondered how they could eat it. Nothing
+should have induced ME to touch it!) and voted himself into the charge
+of the wine-cellar, which he constructed, being an ingenious beast, in
+the hollow trunk of a tree. By and by, I saw him, with the majority of a
+lobster on his plate, eating his dinner at the feet of Dora!
+
+I have but an indistinct idea of what happened for some time after this
+baleful object presented itself to my view. I was very merry, I know;
+but it was hollow merriment. I attached myself to a young creature in
+pink, with little eyes, and flirted with her desperately. She received
+my attentions with favour; but whether on my account solely, or because
+she had any designs on Red Whisker, I can't say. Dora's health was
+drunk. When I drank it, I affected to interrupt my conversation for that
+purpose, and to resume it immediately afterwards. I caught Dora's eye as
+I bowed to her, and I thought it looked appealing. But it looked at me
+over the head of Red Whisker, and I was adamant.
+
+The young creature in pink had a mother in green; and I rather think the
+latter separated us from motives of policy. Howbeit, there was a general
+breaking up of the party, while the remnants of the dinner were being
+put away; and I strolled off by myself among the trees, in a raging and
+remorseful state. I was debating whether I should pretend that I was not
+well, and fly--I don't know where--upon my gallant grey, when Dora and
+Miss Mills met me.
+
+'Mr. Copperfield,' said Miss Mills, 'you are dull.'
+
+I begged her pardon. Not at all.
+
+'And Dora,' said Miss Mills, 'YOU are dull.'
+
+Oh dear no! Not in the least.
+
+'Mr. Copperfield and Dora,' said Miss Mills, with an almost venerable
+air. 'Enough of this. Do not allow a trivial misunderstanding to wither
+the blossoms of spring, which, once put forth and blighted, cannot be
+renewed. I speak,' said Miss Mills, 'from experience of the past--the
+remote, irrevocable past. The gushing fountains which sparkle in the
+sun, must not be stopped in mere caprice; the oasis in the desert of
+Sahara must not be plucked up idly.'
+
+I hardly knew what I did, I was burning all over to that extraordinary
+extent; but I took Dora's little hand and kissed it--and she let me!
+I kissed Miss Mills's hand; and we all seemed, to my thinking, to go
+straight up to the seventh heaven. We did not come down again. We stayed
+up there all the evening. At first we strayed to and fro among the
+trees: I with Dora's shy arm drawn through mine: and Heaven knows,
+folly as it all was, it would have been a happy fate to have been struck
+immortal with those foolish feelings, and have stayed among the trees
+for ever!
+
+But, much too soon, we heard the others laughing and talking, and
+calling 'where's Dora?' So we went back, and they wanted Dora to sing.
+Red Whisker would have got the guitar-case out of the carriage, but Dora
+told him nobody knew where it was, but I. So Red Whisker was done for
+in a moment; and I got it, and I unlocked it, and I took the guitar out,
+and I sat by her, and I held her handkerchief and gloves, and I drank in
+every note of her dear voice, and she sang to ME who loved her, and all
+the others might applaud as much as they liked, but they had nothing to
+do with it!
+
+I was intoxicated with joy. I was afraid it was too happy to be real,
+and that I should wake in Buckingham Street presently, and hear Mrs.
+Crupp clinking the teacups in getting breakfast ready. But Dora sang,
+and others sang, and Miss Mills sang--about the slumbering echoes in the
+caverns of Memory; as if she were a hundred years old--and the evening
+came on; and we had tea, with the kettle boiling gipsy-fashion; and I
+was still as happy as ever.
+
+I was happier than ever when the party broke up, and the other people,
+defeated Red Whisker and all, went their several ways, and we went ours
+through the still evening and the dying light, with sweet scents
+rising up around us. Mr. Spenlow being a little drowsy after the
+champagne--honour to the soil that grew the grape, to the grape that
+made the wine, to the sun that ripened it, and to the merchant who
+adulterated it!--and being fast asleep in a corner of the carriage, I
+rode by the side and talked to Dora. She admired my horse and patted
+him--oh, what a dear little hand it looked upon a horse!--and her shawl
+would not keep right, and now and then I drew it round her with my arm;
+and I even fancied that Jip began to see how it was, and to understand
+that he must make up his mind to be friends with me.
+
+That sagacious Miss Mills, too; that amiable, though quite used up,
+recluse; that little patriarch of something less than twenty, who had
+done with the world, and mustn't on any account have the slumbering
+echoes in the caverns of Memory awakened; what a kind thing she did!
+
+'Mr. Copperfield,' said Miss Mills, 'come to this side of the carriage a
+moment--if you can spare a moment. I want to speak to you.'
+
+Behold me, on my gallant grey, bending at the side of Miss Mills, with
+my hand upon the carriage door!
+
+'Dora is coming to stay with me. She is coming home with me the day
+after tomorrow. If you would like to call, I am sure papa would be
+happy to see you.' What could I do but invoke a silent blessing on Miss
+Mills's head, and store Miss Mills's address in the securest corner of
+my memory! What could I do but tell Miss Mills, with grateful looks
+and fervent words, how much I appreciated her good offices, and what an
+inestimable value I set upon her friendship!
+
+Then Miss Mills benignantly dismissed me, saying, 'Go back to Dora!' and
+I went; and Dora leaned out of the carriage to talk to me, and we talked
+all the rest of the way; and I rode my gallant grey so close to the
+wheel that I grazed his near fore leg against it, and 'took the bark
+off', as his owner told me, 'to the tune of three pun' sivin'--which I
+paid, and thought extremely cheap for so much joy. What time Miss Mills
+sat looking at the moon, murmuring verses--and recalling, I suppose, the
+ancient days when she and earth had anything in common.
+
+Norwood was many miles too near, and we reached it many hours too soon;
+but Mr. Spenlow came to himself a little short of it, and said,
+'You must come in, Copperfield, and rest!' and I consenting, we had
+sandwiches and wine-and-water. In the light room, Dora blushing looked
+so lovely, that I could not tear myself away, but sat there staring, in
+a dream, until the snoring of Mr. Spenlow inspired me with sufficient
+consciousness to take my leave. So we parted; I riding all the way
+to London with the farewell touch of Dora's hand still light on mine,
+recalling every incident and word ten thousand times; lying down in my
+own bed at last, as enraptured a young noodle as ever was carried out of
+his five wits by love.
+
+When I awoke next morning, I was resolute to declare my passion to Dora,
+and know my fate. Happiness or misery was now the question. There was no
+other question that I knew of in the world, and only Dora could give the
+answer to it. I passed three days in a luxury of wretchedness, torturing
+myself by putting every conceivable variety of discouraging construction
+on all that ever had taken place between Dora and me. At last, arrayed
+for the purpose at a vast expense, I went to Miss Mills's, fraught with
+a declaration.
+
+How many times I went up and down the street, and round the
+square--painfully aware of being a much better answer to the old riddle
+than the original one--before I could persuade myself to go up the steps
+and knock, is no matter now. Even when, at last, I had knocked, and was
+waiting at the door, I had some flurried thought of asking if that
+were Mr. Blackboy's (in imitation of poor Barkis), begging pardon, and
+retreating. But I kept my ground.
+
+Mr. Mills was not at home. I did not expect he would be. Nobody wanted
+HIM. Miss Mills was at home. Miss Mills would do.
+
+I was shown into a room upstairs, where Miss Mills and Dora were. Jip
+was there. Miss Mills was copying music (I recollect, it was a new song,
+called 'Affection's Dirge'), and Dora was painting flowers. What were my
+feelings, when I recognized my own flowers; the identical Covent Garden
+Market purchase! I cannot say that they were very like, or that
+they particularly resembled any flowers that have ever come under my
+observation; but I knew from the paper round them which was accurately
+copied, what the composition was.
+
+Miss Mills was very glad to see me, and very sorry her papa was not at
+home: though I thought we all bore that with fortitude. Miss Mills was
+conversational for a few minutes, and then, laying down her pen upon
+'Affection's Dirge', got up, and left the room.
+
+I began to think I would put it off till tomorrow.
+
+'I hope your poor horse was not tired, when he got home at night,' said
+Dora, lifting up her beautiful eyes. 'It was a long way for him.'
+
+I began to think I would do it today.
+
+'It was a long way for him,' said I, 'for he had nothing to uphold him
+on the journey.'
+
+'Wasn't he fed, poor thing?' asked Dora.
+
+I began to think I would put it off till tomorrow.
+
+'Ye-yes,' I said, 'he was well taken care of. I mean he had not the
+unutterable happiness that I had in being so near you.'
+
+Dora bent her head over her drawing and said, after a little while--I
+had sat, in the interval, in a burning fever, and with my legs in a very
+rigid state--
+
+'You didn't seem to be sensible of that happiness yourself, at one time
+of the day.'
+
+I saw now that I was in for it, and it must be done on the spot.
+
+'You didn't care for that happiness in the least,' said Dora, slightly
+raising her eyebrows, and shaking her head, 'when you were sitting by
+Miss Kitt.'
+
+Kitt, I should observe, was the name of the creature in pink, with the
+little eyes.
+
+'Though certainly I don't know why you should,' said Dora, or why you
+should call it a happiness at all. But of course you don't mean what you
+say. And I am sure no one doubts your being at liberty to do whatever
+you like. Jip, you naughty boy, come here!'
+
+I don't know how I did it. I did it in a moment. I intercepted Jip.
+I had Dora in my arms. I was full of eloquence. I never stopped for a
+word. I told her how I loved her. I told her I should die without her.
+I told her that I idolized and worshipped her. Jip barked madly all the
+time.
+
+When Dora hung her head and cried, and trembled, my eloquence increased
+so much the more. If she would like me to die for her, she had but to
+say the word, and I was ready. Life without Dora's love was not a thing
+to have on any terms. I couldn't bear it, and I wouldn't. I had loved
+her every minute, day and night, since I first saw her. I loved her at
+that minute to distraction. I should always love her, every minute, to
+distraction. Lovers had loved before, and lovers would love again; but
+no lover had loved, might, could, would, or should ever love, as I loved
+Dora. The more I raved, the more Jip barked. Each of us, in his own way,
+got more mad every moment.
+
+Well, well! Dora and I were sitting on the sofa by and by, quiet enough,
+and Jip was lying in her lap, winking peacefully at me. It was off my
+mind. I was in a state of perfect rapture. Dora and I were engaged.
+
+I suppose we had some notion that this was to end in marriage. We must
+have had some, because Dora stipulated that we were never to be married
+without her papa's consent. But, in our youthful ecstasy, I don't think
+that we really looked before us or behind us; or had any aspiration
+beyond the ignorant present. We were to keep our secret from Mr.
+Spenlow; but I am sure the idea never entered my head, then, that there
+was anything dishonourable in that.
+
+Miss Mills was more than usually pensive when Dora, going to find her,
+brought her back;--I apprehend, because there was a tendency in what had
+passed to awaken the slumbering echoes in the caverns of Memory. But she
+gave us her blessing, and the assurance of her lasting friendship, and
+spoke to us, generally, as became a Voice from the Cloister.
+
+What an idle time it was! What an insubstantial, happy, foolish time it
+was!
+
+When I measured Dora's finger for a ring that was to be made of
+Forget-me-nots, and when the jeweller, to whom I took the measure, found
+me out, and laughed over his order-book, and charged me anything he
+liked for the pretty little toy, with its blue stones--so associated
+in my remembrance with Dora's hand, that yesterday, when I saw such
+another, by chance, on the finger of my own daughter, there was a
+momentary stirring in my heart, like pain!
+
+When I walked about, exalted with my secret, and full of my own
+interest, and felt the dignity of loving Dora, and of being beloved, so
+much, that if I had walked the air, I could not have been more above the
+people not so situated, who were creeping on the earth!
+
+When we had those meetings in the garden of the square, and sat within
+the dingy summer-house, so happy, that I love the London sparrows to
+this hour, for nothing else, and see the plumage of the tropics in their
+smoky feathers! When we had our first great quarrel (within a week
+of our betrothal), and when Dora sent me back the ring, enclosed in a
+despairing cocked-hat note, wherein she used the terrible expression
+that 'our love had begun in folly, and ended in madness!' which dreadful
+words occasioned me to tear my hair, and cry that all was over!
+
+When, under cover of the night, I flew to Miss Mills, whom I saw by
+stealth in a back kitchen where there was a mangle, and implored Miss
+Mills to interpose between us and avert insanity. When Miss Mills
+undertook the office and returned with Dora, exhorting us, from the
+pulpit of her own bitter youth, to mutual concession, and the avoidance
+of the Desert of Sahara!
+
+When we cried, and made it up, and were so blest again, that the back
+kitchen, mangle and all, changed to Love's own temple, where we arranged
+a plan of correspondence through Miss Mills, always to comprehend at
+least one letter on each side every day!
+
+What an idle time! What an insubstantial, happy, foolish time! Of all
+the times of mine that Time has in his grip, there is none that in one
+retrospect I can smile at half so much, and think of half so tenderly.
+
+
+
+CHAPTER 34. MY AUNT ASTONISHES ME
+
+
+I wrote to Agnes as soon as Dora and I were engaged. I wrote her a long
+letter, in which I tried to make her comprehend how blest I was, and
+what a darling Dora was. I entreated Agnes not to regard this as a
+thoughtless passion which could ever yield to any other, or had the
+least resemblance to the boyish fancies that we used to joke about. I
+assured her that its profundity was quite unfathomable, and expressed my
+belief that nothing like it had ever been known.
+
+Somehow, as I wrote to Agnes on a fine evening by my open window, and
+the remembrance of her clear calm eyes and gentle face came stealing
+over me, it shed such a peaceful influence upon the hurry and agitation
+in which I had been living lately, and of which my very happiness
+partook in some degree, that it soothed me into tears. I remember that
+I sat resting my head upon my hand, when the letter was half done,
+cherishing a general fancy as if Agnes were one of the elements of my
+natural home. As if, in the retirement of the house made almost sacred
+to me by her presence, Dora and I must be happier than anywhere. As if,
+in love, joy, sorrow, hope, or disappointment; in all emotions; my heart
+turned naturally there, and found its refuge and best friend.
+
+Of Steerforth I said nothing. I only told her there had been sad grief
+at Yarmouth, on account of Emily's flight; and that on me it made a
+double wound, by reason of the circumstances attending it. I knew how
+quick she always was to divine the truth, and that she would never be
+the first to breathe his name.
+
+To this letter, I received an answer by return of post. As I read it, I
+seemed to hear Agnes speaking to me. It was like her cordial voice in my
+ears. What can I say more!
+
+While I had been away from home lately, Traddles had called twice or
+thrice. Finding Peggotty within, and being informed by Peggotty (who
+always volunteered that information to whomsoever would receive
+it), that she was my old nurse, he had established a good-humoured
+acquaintance with her, and had stayed to have a little chat with her
+about me. So Peggotty said; but I am afraid the chat was all on her
+own side, and of immoderate length, as she was very difficult indeed to
+stop, God bless her! when she had me for her theme.
+
+This reminds me, not only that I expected Traddles on a certain
+afternoon of his own appointing, which was now come, but that Mrs. Crupp
+had resigned everything appertaining to her office (the salary excepted)
+until Peggotty should cease to present herself. Mrs. Crupp, after
+holding divers conversations respecting Peggotty, in a very high-pitched
+voice, on the staircase--with some invisible Familiar it would appear,
+for corporeally speaking she was quite alone at those times--addressed a
+letter to me, developing her views. Beginning it with that statement
+of universal application, which fitted every occurrence of her life,
+namely, that she was a mother herself, she went on to inform me that
+she had once seen very different days, but that at all periods of her
+existence she had had a constitutional objection to spies, intruders,
+and informers. She named no names, she said; let them the cap fitted,
+wear it; but spies, intruders, and informers, especially in widders'
+weeds (this clause was underlined), she had ever accustomed herself to
+look down upon. If a gentleman was the victim of spies, intruders, and
+informers (but still naming no names), that was his own pleasure. He
+had a right to please himself; so let him do. All that she, Mrs. Crupp,
+stipulated for, was, that she should not be 'brought in contract'
+with such persons. Therefore she begged to be excused from any further
+attendance on the top set, until things were as they formerly was, and
+as they could be wished to be; and further mentioned that her little
+book would be found upon the breakfast-table every Saturday morning,
+when she requested an immediate settlement of the same, with the
+benevolent view of saving trouble 'and an ill-conwenience' to all
+parties.
+
+After this, Mrs. Crupp confined herself to making pitfalls on the
+stairs, principally with pitchers, and endeavouring to delude Peggotty
+into breaking her legs. I found it rather harassing to live in this
+state of siege, but was too much afraid of Mrs. Crupp to see any way out
+of it.
+
+'My dear Copperfield,' cried Traddles, punctually appearing at my door,
+in spite of all these obstacles, 'how do you do?'
+
+'My dear Traddles,' said I, 'I am delighted to see you at last, and very
+sorry I have not been at home before. But I have been so much engaged--'
+
+'Yes, yes, I know,' said Traddles, 'of course. Yours lives in London, I
+think.'
+
+'What did you say?'
+
+'She--excuse me--Miss D., you know,' said Traddles, colouring in his
+great delicacy, 'lives in London, I believe?'
+
+'Oh yes. Near London.'
+
+'Mine, perhaps you recollect,' said Traddles, with a serious look,
+'lives down in Devonshire--one of ten. Consequently, I am not so much
+engaged as you--in that sense.'
+
+'I wonder you can bear,' I returned, 'to see her so seldom.'
+
+'Hah!' said Traddles, thoughtfully. 'It does seem a wonder. I suppose it
+is, Copperfield, because there is no help for it?'
+
+'I suppose so,' I replied with a smile, and not without a blush. 'And
+because you have so much constancy and patience, Traddles.'
+
+'Dear me!' said Traddles, considering about it, 'do I strike you in that
+way, Copperfield? Really I didn't know that I had. But she is such
+an extraordinarily dear girl herself, that it's possible she may
+have imparted something of those virtues to me. Now you mention it,
+Copperfield, I shouldn't wonder at all. I assure you she is always
+forgetting herself, and taking care of the other nine.'
+
+'Is she the eldest?' I inquired.
+
+'Oh dear, no,' said Traddles. 'The eldest is a Beauty.'
+
+He saw, I suppose, that I could not help smiling at the simplicity of
+this reply; and added, with a smile upon his own ingenuous face:
+
+'Not, of course, but that my Sophy--pretty name, Copperfield, I always
+think?'
+
+'Very pretty!' said I.
+
+'Not, of course, but that Sophy is beautiful too in my eyes, and would
+be one of the dearest girls that ever was, in anybody's eyes (I should
+think). But when I say the eldest is a Beauty, I mean she really is
+a--' he seemed to be describing clouds about himself, with both hands:
+'Splendid, you know,' said Traddles, energetically. 'Indeed!' said I.
+
+'Oh, I assure you,' said Traddles, 'something very uncommon, indeed!
+Then, you know, being formed for society and admiration, and not being
+able to enjoy much of it in consequence of their limited means, she
+naturally gets a little irritable and exacting, sometimes. Sophy puts
+her in good humour!'
+
+'Is Sophy the youngest?' I hazarded.
+
+'Oh dear, no!' said Traddles, stroking his chin. 'The two youngest are
+only nine and ten. Sophy educates 'em.'
+
+'The second daughter, perhaps?' I hazarded.
+
+'No,' said Traddles. 'Sarah's the second. Sarah has something the matter
+with her spine, poor girl. The malady will wear out by and by, the
+doctors say, but in the meantime she has to lie down for a twelvemonth.
+Sophy nurses her. Sophy's the fourth.'
+
+'Is the mother living?' I inquired.
+
+'Oh yes,' said Traddles, 'she is alive. She is a very superior woman
+indeed, but the damp country is not adapted to her constitution, and--in
+fact, she has lost the use of her limbs.'
+
+'Dear me!' said I.
+
+'Very sad, is it not?' returned Traddles. 'But in a merely domestic view
+it is not so bad as it might be, because Sophy takes her place. She is
+quite as much a mother to her mother, as she is to the other nine.'
+
+I felt the greatest admiration for the virtues of this young lady; and,
+honestly with the view of doing my best to prevent the good-nature
+of Traddles from being imposed upon, to the detriment of their joint
+prospects in life, inquired how Mr. Micawber was?
+
+'He is quite well, Copperfield, thank you,' said Traddles. 'I am not
+living with him at present.'
+
+'No?'
+
+'No. You see the truth is,' said Traddles, in a whisper, 'he had changed
+his name to Mortimer, in consequence of his temporary embarrassments;
+and he don't come out till after dark--and then in spectacles. There was
+an execution put into our house, for rent. Mrs. Micawber was in such
+a dreadful state that I really couldn't resist giving my name to that
+second bill we spoke of here. You may imagine how delightful it was to
+my feelings, Copperfield, to see the matter settled with it, and Mrs.
+Micawber recover her spirits.'
+
+'Hum!' said I. 'Not that her happiness was of long duration,' pursued
+Traddles, 'for, unfortunately, within a week another execution came
+in. It broke up the establishment. I have been living in a furnished
+apartment since then, and the Mortimers have been very private indeed.
+I hope you won't think it selfish, Copperfield, if I mention that
+the broker carried off my little round table with the marble top, and
+Sophy's flower-pot and stand?'
+
+'What a hard thing!' I exclaimed indignantly.
+
+'It was a--it was a pull,' said Traddles, with his usual wince at that
+expression. 'I don't mention it reproachfully, however, but with a
+motive. The fact is, Copperfield, I was unable to repurchase them at the
+time of their seizure; in the first place, because the broker, having an
+idea that I wanted them, ran the price up to an extravagant extent; and,
+in the second place, because I--hadn't any money. Now, I have kept
+my eye since, upon the broker's shop,' said Traddles, with a great
+enjoyment of his mystery, 'which is up at the top of Tottenham Court
+Road, and, at last, today I find them put out for sale. I have only
+noticed them from over the way, because if the broker saw me, bless you,
+he'd ask any price for them! What has occurred to me, having now the
+money, is, that perhaps you wouldn't object to ask that good nurse of
+yours to come with me to the shop--I can show it her from round the
+corner of the next street--and make the best bargain for them, as if
+they were for herself, that she can!'
+
+The delight with which Traddles propounded this plan to me, and the
+sense he had of its uncommon artfulness, are among the freshest things
+in my remembrance.
+
+I told him that my old nurse would be delighted to assist him, and that
+we would all three take the field together, but on one condition. That
+condition was, that he should make a solemn resolution to grant no more
+loans of his name, or anything else, to Mr. Micawber.
+
+'My dear Copperfield,' said Traddles, 'I have already done so, because
+I begin to feel that I have not only been inconsiderate, but that I have
+been positively unjust to Sophy. My word being passed to myself, there
+is no longer any apprehension; but I pledge it to you, too, with the
+greatest readiness. That first unlucky obligation, I have paid. I have
+no doubt Mr. Micawber would have paid it if he could, but he could not.
+One thing I ought to mention, which I like very much in Mr. Micawber,
+Copperfield. It refers to the second obligation, which is not yet due.
+He don't tell me that it is provided for, but he says it WILL BE. Now, I
+think there is something very fair and honest about that!'
+
+I was unwilling to damp my good friend's confidence, and therefore
+assented. After a little further conversation, we went round to the
+chandler's shop, to enlist Peggotty; Traddles declining to pass the
+evening with me, both because he endured the liveliest apprehensions
+that his property would be bought by somebody else before he could
+re-purchase it, and because it was the evening he always devoted to
+writing to the dearest girl in the world.
+
+I never shall forget him peeping round the corner of the street in
+Tottenham Court Road, while Peggotty was bargaining for the precious
+articles; or his agitation when she came slowly towards us after vainly
+offering a price, and was hailed by the relenting broker, and went back
+again. The end of the negotiation was, that she bought the property on
+tolerably easy terms, and Traddles was transported with pleasure.
+
+'I am very much obliged to you, indeed,' said Traddles, on hearing it
+was to be sent to where he lived, that night. 'If I might ask one other
+favour, I hope you would not think it absurd, Copperfield?'
+
+I said beforehand, certainly not.
+
+'Then if you WOULD be good enough,' said Traddles to Peggotty, 'to
+get the flower-pot now, I think I should like (it being Sophy's,
+Copperfield) to carry it home myself!'
+
+Peggotty was glad to get it for him, and he overwhelmed her with thanks,
+and went his way up Tottenham Court Road, carrying the flower-pot
+affectionately in his arms, with one of the most delighted expressions
+of countenance I ever saw.
+
+We then turned back towards my chambers. As the shops had charms for
+Peggotty which I never knew them possess in the same degree for anybody
+else, I sauntered easily along, amused by her staring in at the windows,
+and waiting for her as often as she chose. We were thus a good while in
+getting to the Adelphi.
+
+On our way upstairs, I called her attention to the sudden disappearance
+of Mrs. Crupp's pitfalls, and also to the prints of recent footsteps. We
+were both very much surprised, coming higher up, to find my outer door
+standing open (which I had shut) and to hear voices inside.
+
+We looked at one another, without knowing what to make of this, and went
+into the sitting-room. What was my amazement to find, of all people upon
+earth, my aunt there, and Mr. Dick! My aunt sitting on a quantity of
+luggage, with her two birds before her, and her cat on her knee, like a
+female Robinson Crusoe, drinking tea. Mr. Dick leaning thoughtfully on
+a great kite, such as we had often been out together to fly, with more
+luggage piled about him!
+
+'My dear aunt!' cried I. 'Why, what an unexpected pleasure!'
+
+We cordially embraced; and Mr. Dick and I cordially shook hands; and
+Mrs. Crupp, who was busy making tea, and could not be too attentive,
+cordially said she had knowed well as Mr. Copperfull would have his
+heart in his mouth, when he see his dear relations.
+
+'Holloa!' said my aunt to Peggotty, who quailed before her awful
+presence. 'How are YOU?'
+
+'You remember my aunt, Peggotty?' said I.
+
+'For the love of goodness, child,' exclaimed my aunt, 'don't call the
+woman by that South Sea Island name! If she married and got rid of
+it, which was the best thing she could do, why don't you give her the
+benefit of the change? What's your name now,--P?' said my aunt, as a
+compromise for the obnoxious appellation.
+
+'Barkis, ma'am,' said Peggotty, with a curtsey.
+
+'Well! That's human,' said my aunt. 'It sounds less as if you wanted a
+missionary. How d'ye do, Barkis? I hope you're well?'
+
+Encouraged by these gracious words, and by my aunt's extending her
+hand, Barkis came forward, and took the hand, and curtseyed her
+acknowledgements.
+
+'We are older than we were, I see,' said my aunt. 'We have only met each
+other once before, you know. A nice business we made of it then! Trot,
+my dear, another cup.'
+
+I handed it dutifully to my aunt, who was in her usual inflexible state
+of figure; and ventured a remonstrance with her on the subject of her
+sitting on a box.
+
+'Let me draw the sofa here, or the easy-chair, aunt,' said I. 'Why
+should you be so uncomfortable?'
+
+'Thank you, Trot,' replied my aunt, 'I prefer to sit upon my property.'
+Here my aunt looked hard at Mrs. Crupp, and observed, 'We needn't
+trouble you to wait, ma'am.'
+
+'Shall I put a little more tea in the pot afore I go, ma'am?' said Mrs.
+Crupp.
+
+'No, I thank you, ma'am,' replied my aunt.
+
+'Would you let me fetch another pat of butter, ma'am?' said Mrs. Crupp.
+'Or would you be persuaded to try a new-laid hegg? or should I brile
+a rasher? Ain't there nothing I could do for your dear aunt, Mr.
+Copperfull?'
+
+'Nothing, ma'am,' returned my aunt. 'I shall do very well, I thank you.'
+
+Mrs. Crupp, who had been incessantly smiling to express sweet temper,
+and incessantly holding her head on one side, to express a general
+feebleness of constitution, and incessantly rubbing her hands, to
+express a desire to be of service to all deserving objects, gradually
+smiled herself, one-sided herself, and rubbed herself, out of the room.
+'Dick!' said my aunt. 'You know what I told you about time-servers and
+wealth-worshippers?'
+
+Mr. Dick--with rather a scared look, as if he had forgotten it--returned
+a hasty answer in the affirmative.
+
+'Mrs. Crupp is one of them,' said my aunt. 'Barkis, I'll trouble you to
+look after the tea, and let me have another cup, for I don't fancy that
+woman's pouring-out!'
+
+I knew my aunt sufficiently well to know that she had something of
+importance on her mind, and that there was far more matter in this
+arrival than a stranger might have supposed. I noticed how her eye
+lighted on me, when she thought my attention otherwise occupied; and
+what a curious process of hesitation appeared to be going on within
+her, while she preserved her outward stiffness and composure. I began
+to reflect whether I had done anything to offend her; and my conscience
+whispered me that I had not yet told her about Dora. Could it by any
+means be that, I wondered!
+
+As I knew she would only speak in her own good time, I sat down near
+her, and spoke to the birds, and played with the cat, and was as easy
+as I could be. But I was very far from being really easy; and I should
+still have been so, even if Mr. Dick, leaning over the great kite behind
+my aunt, had not taken every secret opportunity of shaking his head
+darkly at me, and pointing at her.
+
+'Trot,' said my aunt at last, when she had finished her tea, and
+carefully smoothed down her dress, and wiped her lips--'you needn't go,
+Barkis!--Trot, have you got to be firm and self-reliant?'
+
+'I hope so, aunt.'
+
+'What do you think?' inquired Miss Betsey.
+
+'I think so, aunt.'
+
+'Then why, my love,' said my aunt, looking earnestly at me, 'why do you
+think I prefer to sit upon this property of mine tonight?'
+
+I shook my head, unable to guess.
+
+'Because,' said my aunt, 'it's all I have. Because I'm ruined, my dear!'
+
+If the house, and every one of us, had tumbled out into the river
+together, I could hardly have received a greater shock.
+
+'Dick knows it,' said my aunt, laying her hand calmly on my shoulder. 'I
+am ruined, my dear Trot! All I have in the world is in this room, except
+the cottage; and that I have left Janet to let. Barkis, I want to get a
+bed for this gentleman tonight. To save expense, perhaps you can make
+up something here for myself. Anything will do. It's only for tonight.
+We'll talk about this, more, tomorrow.'
+
+I was roused from my amazement, and concern for her--I am sure, for
+her--by her falling on my neck, for a moment, and crying that she only
+grieved for me. In another moment she suppressed this emotion; and said
+with an aspect more triumphant than dejected:
+
+'We must meet reverses boldly, and not suffer them to frighten us, my
+dear. We must learn to act the play out. We must live misfortune down,
+Trot!'
+
+
+
+CHAPTER 35. DEPRESSION
+
+
+As soon as I could recover my presence of mind, which quite deserted me
+in the first overpowering shock of my aunt's intelligence, I proposed
+to Mr. Dick to come round to the chandler's shop, and take possession of
+the bed which Mr. Peggotty had lately vacated. The chandler's shop being
+in Hungerford Market, and Hungerford Market being a very different place
+in those days, there was a low wooden colonnade before the door (not
+very unlike that before the house where the little man and woman used
+to live, in the old weather-glass), which pleased Mr. Dick mightily. The
+glory of lodging over this structure would have compensated him, I dare
+say, for many inconveniences; but, as there were really few to bear,
+beyond the compound of flavours I have already mentioned, and perhaps
+the want of a little more elbow-room, he was perfectly charmed with his
+accommodation. Mrs. Crupp had indignantly assured him that there wasn't
+room to swing a cat there; but, as Mr. Dick justly observed to me,
+sitting down on the foot of the bed, nursing his leg, 'You know,
+Trotwood, I don't want to swing a cat. I never do swing a cat.
+Therefore, what does that signify to ME!'
+
+I tried to ascertain whether Mr. Dick had any understanding of the
+causes of this sudden and great change in my aunt's affairs. As I might
+have expected, he had none at all. The only account he could give of it
+was, that my aunt had said to him, the day before yesterday, 'Now, Dick,
+are you really and truly the philosopher I take you for?' That then
+he had said, Yes, he hoped so. That then my aunt had said, 'Dick, I
+am ruined.' That then he had said, 'Oh, indeed!' That then my aunt had
+praised him highly, which he was glad of. And that then they had come to
+me, and had had bottled porter and sandwiches on the road.
+
+Mr. Dick was so very complacent, sitting on the foot of the bed, nursing
+his leg, and telling me this, with his eyes wide open and a surprised
+smile, that I am sorry to say I was provoked into explaining to him
+that ruin meant distress, want, and starvation; but I was soon bitterly
+reproved for this harshness, by seeing his face turn pale, and tears
+course down his lengthened cheeks, while he fixed upon me a look of such
+unutterable woe, that it might have softened a far harder heart than
+mine. I took infinitely greater pains to cheer him up again than I had
+taken to depress him; and I soon understood (as I ought to have known at
+first) that he had been so confident, merely because of his faith in
+the wisest and most wonderful of women, and his unbounded reliance on my
+intellectual resources. The latter, I believe, he considered a match for
+any kind of disaster not absolutely mortal.
+
+'What can we do, Trotwood?' said Mr. Dick. 'There's the Memorial-'
+
+'To be sure there is,' said I. 'But all we can do just now, Mr. Dick,
+is to keep a cheerful countenance, and not let my aunt see that we are
+thinking about it.'
+
+He assented to this in the most earnest manner; and implored me, if I
+should see him wandering an inch out of the right course, to recall him
+by some of those superior methods which were always at my command. But I
+regret to state that the fright I had given him proved too much for his
+best attempts at concealment. All the evening his eyes wandered to my
+aunt's face, with an expression of the most dismal apprehension, as if
+he saw her growing thin on the spot. He was conscious of this, and put
+a constraint upon his head; but his keeping that immovable, and sitting
+rolling his eyes like a piece of machinery, did not mend the matter at
+all. I saw him look at the loaf at supper (which happened to be a small
+one), as if nothing else stood between us and famine; and when my aunt
+insisted on his making his customary repast, I detected him in the act
+of pocketing fragments of his bread and cheese; I have no doubt for the
+purpose of reviving us with those savings, when we should have reached
+an advanced stage of attenuation.
+
+My aunt, on the other hand, was in a composed frame of mind, which was
+a lesson to all of us--to me, I am sure. She was extremely gracious
+to Peggotty, except when I inadvertently called her by that name; and,
+strange as I knew she felt in London, appeared quite at home. She was
+to have my bed, and I was to lie in the sitting-room, to keep guard over
+her. She made a great point of being so near the river, in case of a
+conflagration; and I suppose really did find some satisfaction in that
+circumstance.
+
+'Trot, my dear,' said my aunt, when she saw me making preparations for
+compounding her usual night-draught, 'No!'
+
+'Nothing, aunt?'
+
+'Not wine, my dear. Ale.'
+
+'But there is wine here, aunt. And you always have it made of wine.'
+
+'Keep that, in case of sickness,' said my aunt. 'We mustn't use it
+carelessly, Trot. Ale for me. Half a pint.'
+
+I thought Mr. Dick would have fallen, insensible. My aunt being
+resolute, I went out and got the ale myself. As it was growing late,
+Peggotty and Mr. Dick took that opportunity of repairing to the
+chandler's shop together. I parted from him, poor fellow, at the corner
+of the street, with his great kite at his back, a very monument of human
+misery.
+
+My aunt was walking up and down the room when I returned, crimping the
+borders of her nightcap with her fingers. I warmed the ale and made the
+toast on the usual infallible principles. When it was ready for her, she
+was ready for it, with her nightcap on, and the skirt of her gown turned
+back on her knees.
+
+'My dear,' said my aunt, after taking a spoonful of it; 'it's a great
+deal better than wine. Not half so bilious.'
+
+I suppose I looked doubtful, for she added:
+
+'Tut, tut, child. If nothing worse than Ale happens to us, we are well
+off.'
+
+'I should think so myself, aunt, I am sure,' said I.
+
+'Well, then, why DON'T you think so?' said my aunt.
+
+'Because you and I are very different people,' I returned.
+
+'Stuff and nonsense, Trot!' replied my aunt.
+
+MY aunt went on with a quiet enjoyment, in which there was very little
+affectation, if any; drinking the warm ale with a tea-spoon, and soaking
+her strips of toast in it.
+
+'Trot,' said she, 'I don't care for strange faces in general, but I
+rather like that Barkis of yours, do you know!'
+
+'It's better than a hundred pounds to hear you say so!' said I.
+
+'It's a most extraordinary world,' observed my aunt, rubbing her nose;
+'how that woman ever got into it with that name, is unaccountable to me.
+It would be much more easy to be born a Jackson, or something of that
+sort, one would think.'
+
+'Perhaps she thinks so, too; it's not her fault,' said I.
+
+'I suppose not,' returned my aunt, rather grudging the admission; 'but
+it's very aggravating. However, she's Barkis now. That's some comfort.
+Barkis is uncommonly fond of you, Trot.'
+
+'There is nothing she would leave undone to prove it,' said I.
+
+'Nothing, I believe,' returned my aunt. 'Here, the poor fool has been
+begging and praying about handing over some of her money--because she
+has got too much of it. A simpleton!'
+
+My aunt's tears of pleasure were positively trickling down into the warm
+ale.
+
+'She's the most ridiculous creature that ever was born,' said my aunt.
+'I knew, from the first moment when I saw her with that poor dear
+blessed baby of a mother of yours, that she was the most ridiculous of
+mortals. But there are good points in Barkis!'
+
+Affecting to laugh, she got an opportunity of putting her hand to
+her eyes. Having availed herself of it, she resumed her toast and her
+discourse together.
+
+'Ah! Mercy upon us!' sighed my aunt. 'I know all about it, Trot! Barkis
+and myself had quite a gossip while you were out with Dick. I know all
+about it. I don't know where these wretched girls expect to go to, for
+my part. I wonder they don't knock out their brains against--against
+mantelpieces,' said my aunt; an idea which was probably suggested to her
+by her contemplation of mine.
+
+'Poor Emily!' said I.
+
+'Oh, don't talk to me about poor,' returned my aunt. 'She should have
+thought of that, before she caused so much misery! Give me a kiss, Trot.
+I am sorry for your early experience.'
+
+As I bent forward, she put her tumbler on my knee to detain me, and
+said:
+
+'Oh, Trot, Trot! And so you fancy yourself in love! Do you?'
+
+'Fancy, aunt!' I exclaimed, as red as I could be. 'I adore her with my
+whole soul!'
+
+'Dora, indeed!' returned my aunt. 'And you mean to say the little thing
+is very fascinating, I suppose?'
+
+'My dear aunt,' I replied, 'no one can form the least idea what she is!'
+
+'Ah! And not silly?' said my aunt.
+
+'Silly, aunt!'
+
+I seriously believe it had never once entered my head for a single
+moment, to consider whether she was or not. I resented the idea, of
+course; but I was in a manner struck by it, as a new one altogether.
+
+'Not light-headed?' said my aunt.
+
+'Light-headed, aunt!' I could only repeat this daring speculation
+with the same kind of feeling with which I had repeated the preceding
+question.
+
+'Well, well!' said my aunt. 'I only ask. I don't depreciate her. Poor
+little couple! And so you think you were formed for one another, and are
+to go through a party-supper-table kind of life, like two pretty pieces
+of confectionery, do you, Trot?'
+
+She asked me this so kindly, and with such a gentle air, half playful
+and half sorrowful, that I was quite touched.
+
+'We are young and inexperienced, aunt, I know,' I replied; 'and I dare
+say we say and think a good deal that is rather foolish. But we love
+one another truly, I am sure. If I thought Dora could ever love anybody
+else, or cease to love me; or that I could ever love anybody else, or
+cease to love her; I don't know what I should do--go out of my mind, I
+think!'
+
+'Ah, Trot!' said my aunt, shaking her head, and smiling gravely; 'blind,
+blind, blind!'
+
+'Someone that I know, Trot,' my aunt pursued, after a pause, 'though of
+a very pliant disposition, has an earnestness of affection in him that
+reminds me of poor Baby. Earnestness is what that Somebody must look
+for, to sustain him and improve him, Trot. Deep, downright, faithful
+earnestness.'
+
+'If you only knew the earnestness of Dora, aunt!' I cried.
+
+'Oh, Trot!' she said again; 'blind, blind!' and without knowing why,
+I felt a vague unhappy loss or want of something overshadow me like a
+cloud.
+
+'However,' said my aunt, 'I don't want to put two young creatures out
+of conceit with themselves, or to make them unhappy; so, though it is a
+girl and boy attachment, and girl and boy attachments very often--mind!
+I don't say always!--come to nothing, still we'll be serious about it,
+and hope for a prosperous issue one of these days. There's time enough
+for it to come to anything!'
+
+This was not upon the whole very comforting to a rapturous lover; but
+I was glad to have my aunt in my confidence, and I was mindful of
+her being fatigued. So I thanked her ardently for this mark of her
+affection, and for all her other kindnesses towards me; and after a
+tender good night, she took her nightcap into my bedroom.
+
+How miserable I was, when I lay down! How I thought and thought about my
+being poor, in Mr. Spenlow's eyes; about my not being what I thought I
+was, when I proposed to Dora; about the chivalrous necessity of
+telling Dora what my worldly condition was, and releasing her from her
+engagement if she thought fit; about how I should contrive to live,
+during the long term of my articles, when I was earning nothing; about
+doing something to assist my aunt, and seeing no way of doing anything;
+about coming down to have no money in my pocket, and to wear a shabby
+coat, and to be able to carry Dora no little presents, and to ride no
+gallant greys, and to show myself in no agreeable light! Sordid and
+selfish as I knew it was, and as I tortured myself by knowing that it
+was, to let my mind run on my own distress so much, I was so devoted
+to Dora that I could not help it. I knew that it was base in me not to
+think more of my aunt, and less of myself; but, so far, selfishness
+was inseparable from Dora, and I could not put Dora on one side for any
+mortal creature. How exceedingly miserable I was, that night!
+
+As to sleep, I had dreams of poverty in all sorts of shapes, but I
+seemed to dream without the previous ceremony of going to sleep. Now I
+was ragged, wanting to sell Dora matches, six bundles for a halfpenny;
+now I was at the office in a nightgown and boots, remonstrated with by
+Mr. Spenlow on appearing before the clients in that airy attire; now
+I was hungrily picking up the crumbs that fell from old Tiffey's
+daily biscuit, regularly eaten when St. Paul's struck one; now I was
+hopelessly endeavouring to get a licence to marry Dora, having nothing
+but one of Uriah Heep's gloves to offer in exchange, which the whole
+Commons rejected; and still, more or less conscious of my own room, I
+was always tossing about like a distressed ship in a sea of bed-clothes.
+
+My aunt was restless, too, for I frequently heard her walking to and
+fro. Two or three times in the course of the night, attired in a long
+flannel wrapper in which she looked seven feet high, she appeared, like
+a disturbed ghost, in my room, and came to the side of the sofa on which
+I lay. On the first occasion I started up in alarm, to learn that she
+inferred from a particular light in the sky, that Westminster Abbey
+was on fire; and to be consulted in reference to the probability of its
+igniting Buckingham Street, in case the wind changed. Lying still, after
+that, I found that she sat down near me, whispering to herself 'Poor
+boy!' And then it made me twenty times more wretched, to know how
+unselfishly mindful she was of me, and how selfishly mindful I was of
+myself.
+
+It was difficult to believe that a night so long to me, could be short
+to anybody else. This consideration set me thinking and thinking of an
+imaginary party where people were dancing the hours away, until that
+became a dream too, and I heard the music incessantly playing one tune,
+and saw Dora incessantly dancing one dance, without taking the least
+notice of me. The man who had been playing the harp all night, was
+trying in vain to cover it with an ordinary-sized nightcap, when I
+awoke; or I should rather say, when I left off trying to go to sleep,
+and saw the sun shining in through the window at last.
+
+There was an old Roman bath in those days at the bottom of one of the
+streets out of the Strand--it may be there still--in which I have had
+many a cold plunge. Dressing myself as quietly as I could, and leaving
+Peggotty to look after my aunt, I tumbled head foremost into it,
+and then went for a walk to Hampstead. I had a hope that this brisk
+treatment might freshen my wits a little; and I think it did them good,
+for I soon came to the conclusion that the first step I ought to take
+was, to try if my articles could be cancelled and the premium recovered.
+I got some breakfast on the Heath, and walked back to Doctors' Commons,
+along the watered roads and through a pleasant smell of summer flowers,
+growing in gardens and carried into town on hucksters' heads, intent on
+this first effort to meet our altered circumstances.
+
+I arrived at the office so soon, after all, that I had half an hour's
+loitering about the Commons, before old Tiffey, who was always first,
+appeared with his key. Then I sat down in my shady corner, looking up
+at the sunlight on the opposite chimney-pots, and thinking about Dora;
+until Mr. Spenlow came in, crisp and curly.
+
+'How are you, Copperfield?' said he. 'Fine morning!'
+
+'Beautiful morning, sir,' said I. 'Could I say a word to you before you
+go into Court?'
+
+'By all means,' said he. 'Come into my room.'
+
+I followed him into his room, and he began putting on his gown, and
+touching himself up before a little glass he had, hanging inside a
+closet door.
+
+'I am sorry to say,' said I, 'that I have some rather disheartening
+intelligence from my aunt.'
+
+'No!' said he. 'Dear me! Not paralysis, I hope?'
+
+'It has no reference to her health, sir,' I replied. 'She has met with
+some large losses. In fact, she has very little left, indeed.'
+
+'You as-tound me, Copperfield!' cried Mr. Spenlow.
+
+I shook my head. 'Indeed, sir,' said I, 'her affairs are so changed,
+that I wished to ask you whether it would be possible--at a sacrifice on
+our part of some portion of the premium, of course,' I put in this, on
+the spur of the moment, warned by the blank expression of his face--'to
+cancel my articles?'
+
+What it cost me to make this proposal, nobody knows. It was like asking,
+as a favour, to be sentenced to transportation from Dora.
+
+'To cancel your articles, Copperfield? Cancel?'
+
+I explained with tolerable firmness, that I really did not know where
+my means of subsistence were to come from, unless I could earn them for
+myself. I had no fear for the future, I said--and I laid great emphasis
+on that, as if to imply that I should still be decidedly eligible for a
+son-in-law one of these days--but, for the present, I was thrown upon
+my own resources. 'I am extremely sorry to hear this, Copperfield,' said
+Mr. Spenlow. 'Extremely sorry. It is not usual to cancel articles for
+any such reason. It is not a professional course of proceeding. It is
+not a convenient precedent at all. Far from it. At the same time--'
+
+'You are very good, sir,' I murmured, anticipating a concession.
+
+'Not at all. Don't mention it,' said Mr. Spenlow. 'At the same time, I
+was going to say, if it had been my lot to have my hands unfettered--if
+I had not a partner--Mr. Jorkins--'
+
+My hopes were dashed in a moment, but I made another effort.
+
+'Do you think, sir,' said I, 'if I were to mention it to Mr. Jorkins--'
+
+Mr. Spenlow shook his head discouragingly. 'Heaven forbid, Copperfield,'
+he replied, 'that I should do any man an injustice: still less, Mr.
+jorkins. But I know my partner, Copperfield. Mr. jorkins is not a man
+to respond to a proposition of this peculiar nature. Mr. jorkins is very
+difficult to move from the beaten track. You know what he is!'
+
+I am sure I knew nothing about him, except that he had originally been
+alone in the business, and now lived by himself in a house near Montagu
+Square, which was fearfully in want of painting; that he came very
+late of a day, and went away very early; that he never appeared to be
+consulted about anything; and that he had a dingy little black-hole of
+his own upstairs, where no business was ever done, and where there was
+a yellow old cartridge-paper pad upon his desk, unsoiled by ink, and
+reported to be twenty years of age.
+
+'Would you object to my mentioning it to him, sir?' I asked.
+
+'By no means,' said Mr. Spenlow. 'But I have some experience of Mr.
+jorkins, Copperfield. I wish it were otherwise, for I should be happy
+to meet your views in any respect. I cannot have the objection to your
+mentioning it to Mr. jorkins, Copperfield, if you think it worth while.'
+
+Availing myself of this permission, which was given with a warm shake
+of the hand, I sat thinking about Dora, and looking at the sunlight
+stealing from the chimney-pots down the wall of the opposite house,
+until Mr. jorkins came. I then went up to Mr. jorkins's room, and
+evidently astonished Mr. jorkins very much by making my appearance
+there.
+
+'Come in, Mr. Copperfield,' said Mr. jorkins. 'Come in!'
+
+I went in, and sat down; and stated my case to Mr. jorkins pretty much
+as I had stated it to Mr. Spenlow. Mr. Jorkins was not by any means the
+awful creature one might have expected, but a large, mild, smooth-faced
+man of sixty, who took so much snuff that there was a tradition in the
+Commons that he lived principally on that stimulant, having little room
+in his system for any other article of diet.
+
+'You have mentioned this to Mr. Spenlow, I suppose?' said Mr. jorkins;
+when he had heard me, very restlessly, to an end.
+
+I answered Yes, and told him that Mr. Spenlow had introduced his name.
+
+'He said I should object?' asked Mr. jorkins.
+
+I was obliged to admit that Mr. Spenlow had considered it probable.
+
+'I am sorry to say, Mr. Copperfield, I can't advance your object,' said
+Mr. jorkins, nervously. 'The fact is--but I have an appointment at the
+Bank, if you'll have the goodness to excuse me.'
+
+With that he rose in a great hurry, and was going out of the room, when
+I made bold to say that I feared, then, there was no way of arranging
+the matter?
+
+'No!' said Mr. jorkins, stopping at the door to shake his head. 'Oh, no!
+I object, you know,' which he said very rapidly, and went out. 'You must
+be aware, Mr. Copperfield,' he added, looking restlessly in at the door
+again, 'if Mr. Spenlow objects--'
+
+'Personally, he does not object, sir,' said I.
+
+'Oh! Personally!' repeated Mr. Jorkins, in an impatient manner. 'I
+assure you there's an objection, Mr. Copperfield. Hopeless! What you
+wish to be done, can't be done. I--I really have got an appointment
+at the Bank.' With that he fairly ran away; and to the best of my
+knowledge, it was three days before he showed himself in the Commons
+again.
+
+Being very anxious to leave no stone unturned, I waited until Mr.
+Spenlow came in, and then described what had passed; giving him to
+understand that I was not hopeless of his being able to soften the
+adamantine jorkins, if he would undertake the task.
+
+'Copperfield,' returned Mr. Spenlow, with a gracious smile, 'you have
+not known my partner, Mr. jorkins, as long as I have. Nothing is
+farther from my thoughts than to attribute any degree of artifice to Mr.
+jorkins. But Mr. jorkins has a way of stating his objections which often
+deceives people. No, Copperfield!' shaking his head. 'Mr. jorkins is not
+to be moved, believe me!'
+
+I was completely bewildered between Mr. Spenlow and Mr. jorkins, as
+to which of them really was the objecting partner; but I saw with
+sufficient clearness that there was obduracy somewhere in the firm, and
+that the recovery of my aunt's thousand pounds was out of the
+question. In a state of despondency, which I remember with anything
+but satisfaction, for I know it still had too much reference to myself
+(though always in connexion with Dora), I left the office, and went
+homeward.
+
+I was trying to familiarize my mind with the worst, and to present to
+myself the arrangements we should have to make for the future in their
+sternest aspect, when a hackney-chariot coming after me, and stopping at
+my very feet, occasioned me to look up. A fair hand was stretched forth
+to me from the window; and the face I had never seen without a feeling
+of serenity and happiness, from the moment when it first turned back
+on the old oak staircase with the great broad balustrade, and when I
+associated its softened beauty with the stained-glass window in the
+church, was smiling on me.
+
+'Agnes!' I joyfully exclaimed. 'Oh, my dear Agnes, of all people in the
+world, what a pleasure to see you!'
+
+'Is it, indeed?' she said, in her cordial voice.
+
+'I want to talk to you so much!' said I. 'It's such a lightening of my
+heart, only to look at you! If I had had a conjuror's cap, there is no
+one I should have wished for but you!'
+
+'What?' returned Agnes.
+
+'Well! perhaps Dora first,' I admitted, with a blush.
+
+'Certainly, Dora first, I hope,' said Agnes, laughing.
+
+'But you next!' said I. 'Where are you going?'
+
+She was going to my rooms to see my aunt. The day being very fine, she
+was glad to come out of the chariot, which smelt (I had my head in it
+all this time) like a stable put under a cucumber-frame. I dismissed the
+coachman, and she took my arm, and we walked on together. She was like
+Hope embodied, to me. How different I felt in one short minute, having
+Agnes at my side!
+
+My aunt had written her one of the odd, abrupt notes--very little longer
+than a Bank note--to which her epistolary efforts were usually limited.
+She had stated therein that she had fallen into adversity, and was
+leaving Dover for good, but had quite made up her mind to it, and was
+so well that nobody need be uncomfortable about her. Agnes had come to
+London to see my aunt, between whom and herself there had been a mutual
+liking these many years: indeed, it dated from the time of my taking up
+my residence in Mr. Wickfield's house. She was not alone, she said. Her
+papa was with her--and Uriah Heep.
+
+'And now they are partners,' said I. 'Confound him!'
+
+'Yes,' said Agnes. 'They have some business here; and I took advantage
+of their coming, to come too. You must not think my visit all friendly
+and disinterested, Trotwood, for--I am afraid I may be cruelly
+prejudiced--I do not like to let papa go away alone, with him.' 'Does he
+exercise the same influence over Mr. Wickfield still, Agnes?'
+
+Agnes shook her head. 'There is such a change at home,' said she, 'that
+you would scarcely know the dear old house. They live with us now.'
+
+'They?' said I.
+
+'Mr. Heep and his mother. He sleeps in your old room,' said Agnes,
+looking up into my face.
+
+'I wish I had the ordering of his dreams,' said I. 'He wouldn't sleep
+there long.'
+
+'I keep my own little room,' said Agnes, 'where I used to learn my
+lessons. How the time goes! You remember? The little panelled room that
+opens from the drawing-room?'
+
+'Remember, Agnes? When I saw you, for the first time, coming out at the
+door, with your quaint little basket of keys hanging at your side?'
+
+'It is just the same,' said Agnes, smiling. 'I am glad you think of it
+so pleasantly. We were very happy.'
+
+'We were, indeed,' said I.
+
+'I keep that room to myself still; but I cannot always desert Mrs. Heep,
+you know. And so,' said Agnes, quietly, 'I feel obliged to bear her
+company, when I might prefer to be alone. But I have no other reason to
+complain of her. If she tires me, sometimes, by her praises of her son,
+it is only natural in a mother. He is a very good son to her.'
+
+I looked at Agnes when she said these words, without detecting in her
+any consciousness of Uriah's design. Her mild but earnest eyes met
+mine with their own beautiful frankness, and there was no change in her
+gentle face.
+
+'The chief evil of their presence in the house,' said Agnes, 'is that I
+cannot be as near papa as I could wish--Uriah Heep being so much between
+us--and cannot watch over him, if that is not too bold a thing to say,
+as closely as I would. But if any fraud or treachery is practising
+against him, I hope that simple love and truth will be strong in the
+end. I hope that real love and truth are stronger in the end than any
+evil or misfortune in the world.'
+
+A certain bright smile, which I never saw on any other face, died away,
+even while I thought how good it was, and how familiar it had once been
+to me; and she asked me, with a quick change of expression (we were
+drawing very near my street), if I knew how the reverse in my aunt's
+circumstances had been brought about. On my replying no, she had not
+told me yet, Agnes became thoughtful, and I fancied I felt her arm
+tremble in mine.
+
+We found my aunt alone, in a state of some excitement. A difference
+of opinion had arisen between herself and Mrs. Crupp, on an abstract
+question (the propriety of chambers being inhabited by the gentler sex);
+and my aunt, utterly indifferent to spasms on the part of Mrs. Crupp,
+had cut the dispute short, by informing that lady that she smelt of
+my brandy, and that she would trouble her to walk out. Both of these
+expressions Mrs. Crupp considered actionable, and had expressed her
+intention of bringing before a 'British Judy'--meaning, it was supposed,
+the bulwark of our national liberties.
+
+MY aunt, however, having had time to cool, while Peggotty was out
+showing Mr. Dick the soldiers at the Horse Guards--and being, besides,
+greatly pleased to see Agnes--rather plumed herself on the affair than
+otherwise, and received us with unimpaired good humour. When Agnes laid
+her bonnet on the table, and sat down beside her, I could not but think,
+looking on her mild eyes and her radiant forehead, how natural it
+seemed to have her there; how trustfully, although she was so young and
+inexperienced, my aunt confided in her; how strong she was, indeed, in
+simple love and truth.
+
+We began to talk about my aunt's losses, and I told them what I had
+tried to do that morning.
+
+'Which was injudicious, Trot,' said my aunt, 'but well meant. You are
+a generous boy--I suppose I must say, young man, now--and I am proud of
+you, my dear. So far, so good. Now, Trot and Agnes, let us look the case
+of Betsey Trotwood in the face, and see how it stands.'
+
+I observed Agnes turn pale, as she looked very attentively at my aunt.
+My aunt, patting her cat, looked very attentively at Agnes.
+
+'Betsey Trotwood,' said my aunt, who had always kept her money matters
+to herself. '--I don't mean your sister, Trot, my dear, but myself--had
+a certain property. It don't matter how much; enough to live on. More;
+for she had saved a little, and added to it. Betsey funded her property
+for some time, and then, by the advice of her man of business, laid
+it out on landed security. That did very well, and returned very good
+interest, till Betsey was paid off. I am talking of Betsey as if she
+was a man-of-war. Well! Then, Betsey had to look about her, for a new
+investment. She thought she was wiser, now, than her man of business,
+who was not such a good man of business by this time, as he used to
+be--I am alluding to your father, Agnes--and she took it into her head
+to lay it out for herself. So she took her pigs,' said my aunt, 'to a
+foreign market; and a very bad market it turned out to be. First, she
+lost in the mining way, and then she lost in the diving way--fishing up
+treasure, or some such Tom Tiddler nonsense,' explained my aunt, rubbing
+her nose; 'and then she lost in the mining way again, and, last of all,
+to set the thing entirely to rights, she lost in the banking way. I
+don't know what the Bank shares were worth for a little while,' said my
+aunt; 'cent per cent was the lowest of it, I believe; but the Bank was
+at the other end of the world, and tumbled into space, for what I know;
+anyhow, it fell to pieces, and never will and never can pay sixpence;
+and Betsey's sixpences were all there, and there's an end of them. Least
+said, soonest mended!'
+
+My aunt concluded this philosophical summary, by fixing her eyes with a
+kind of triumph on Agnes, whose colour was gradually returning.
+
+'Dear Miss Trotwood, is that all the history?' said Agnes.
+
+'I hope it's enough, child,' said my aunt. 'If there had been more
+money to lose, it wouldn't have been all, I dare say. Betsey would have
+contrived to throw that after the rest, and make another chapter, I have
+little doubt. But there was no more money, and there's no more story.'
+
+Agnes had listened at first with suspended breath. Her colour still came
+and went, but she breathed more freely. I thought I knew why. I thought
+she had had some fear that her unhappy father might be in some way to
+blame for what had happened. My aunt took her hand in hers, and laughed.
+
+'Is that all?' repeated my aunt. 'Why, yes, that's all, except, "And she
+lived happy ever afterwards." Perhaps I may add that of Betsey yet, one
+of these days. Now, Agnes, you have a wise head. So have you, Trot, in
+some things, though I can't compliment you always'; and here my aunt
+shook her own at me, with an energy peculiar to herself. 'What's to be
+done? Here's the cottage, taking one time with another, will produce
+say seventy pounds a year. I think we may safely put it down at
+that. Well!--That's all we've got,' said my aunt; with whom it was an
+idiosyncrasy, as it is with some horses, to stop very short when she
+appeared to be in a fair way of going on for a long while.
+
+'Then,' said my aunt, after a rest, 'there's Dick. He's good for a
+hundred a-year, but of course that must be expended on himself. I would
+sooner send him away, though I know I am the only person who appreciates
+him, than have him, and not spend his money on himself. How can Trot and
+I do best, upon our means? What do you say, Agnes?'
+
+'I say, aunt,' I interposed, 'that I must do something!'
+
+'Go for a soldier, do you mean?' returned my aunt, alarmed; 'or go to
+sea? I won't hear of it. You are to be a proctor. We're not going to
+have any knockings on the head in THIS family, if you please, sir.'
+
+I was about to explain that I was not desirous of introducing that mode
+of provision into the family, when Agnes inquired if my rooms were held
+for any long term?
+
+'You come to the point, my dear,' said my aunt. 'They are not to be got
+rid of, for six months at least, unless they could be underlet, and that
+I don't believe. The last man died here. Five people out of six would
+die--of course--of that woman in nankeen with the flannel petticoat. I
+have a little ready money; and I agree with you, the best thing we can
+do, is, to live the term out here, and get a bedroom hard by.'
+
+I thought it my duty to hint at the discomfort my aunt would sustain,
+from living in a continual state of guerilla warfare with Mrs. Crupp;
+but she disposed of that objection summarily by declaring that, on the
+first demonstration of hostilities, she was prepared to astonish Mrs.
+Crupp for the whole remainder of her natural life.
+
+'I have been thinking, Trotwood,' said Agnes, diffidently, 'that if you
+had time--'
+
+'I have a good deal of time, Agnes. I am always disengaged after four
+or five o'clock, and I have time early in the morning. In one way and
+another,' said I, conscious of reddening a little as I thought of the
+hours and hours I had devoted to fagging about town, and to and fro upon
+the Norwood Road, 'I have abundance of time.'
+
+'I know you would not mind,' said Agnes, coming to me, and speaking in
+a low voice, so full of sweet and hopeful consideration that I hear it
+now, 'the duties of a secretary.'
+
+'Mind, my dear Agnes?'
+
+'Because,' continued Agnes, 'Doctor Strong has acted on his intention of
+retiring, and has come to live in London; and he asked papa, I know,
+if he could recommend him one. Don't you think he would rather have his
+favourite old pupil near him, than anybody else?'
+
+'Dear Agnes!' said I. 'What should I do without you! You are always my
+good angel. I told you so. I never think of you in any other light.'
+
+Agnes answered with her pleasant laugh, that one good Angel (meaning
+Dora) was enough; and went on to remind me that the Doctor had been
+used to occupy himself in his study, early in the morning, and in the
+evening--and that probably my leisure would suit his requirements very
+well. I was scarcely more delighted with the prospect of earning my own
+bread, than with the hope of earning it under my old master; in short,
+acting on the advice of Agnes, I sat down and wrote a letter to the
+Doctor, stating my object, and appointing to call on him next day at
+ten in the forenoon. This I addressed to Highgate--for in that place, so
+memorable to me, he lived--and went and posted, myself, without losing a
+minute.
+
+Wherever Agnes was, some agreeable token of her noiseless presence
+seemed inseparable from the place. When I came back, I found my aunt's
+birds hanging, just as they had hung so long in the parlour window of
+the cottage; and my easy-chair imitating my aunt's much easier chair in
+its position at the open window; and even the round green fan, which my
+aunt had brought away with her, screwed on to the window-sill. I knew
+who had done all this, by its seeming to have quietly done itself; and I
+should have known in a moment who had arranged my neglected books in the
+old order of my school days, even if I had supposed Agnes to be miles
+away, instead of seeing her busy with them, and smiling at the disorder
+into which they had fallen.
+
+My aunt was quite gracious on the subject of the Thames (it really did
+look very well with the sun upon it, though not like the sea before the
+cottage), but she could not relent towards the London smoke, which, she
+said, 'peppered everything'. A complete revolution, in which Peggotty
+bore a prominent part, was being effected in every corner of my rooms,
+in regard of this pepper; and I was looking on, thinking how little even
+Peggotty seemed to do with a good deal of bustle, and how much Agnes did
+without any bustle at all, when a knock came at the door.
+
+'I think,' said Agnes, turning pale, 'it's papa. He promised me that he
+would come.'
+
+I opened the door, and admitted, not only Mr. Wickfield, but Uriah Heep.
+I had not seen Mr. Wickfield for some time. I was prepared for a great
+change in him, after what I had heard from Agnes, but his appearance
+shocked me.
+
+It was not that he looked many years older, though still dressed
+with the old scrupulous cleanliness; or that there was an unwholesome
+ruddiness upon his face; or that his eyes were full and bloodshot; or
+that there was a nervous trembling in his hand, the cause of which I
+knew, and had for some years seen at work. It was not that he had lost
+his good looks, or his old bearing of a gentleman--for that he had
+not--but the thing that struck me most, was, that with the evidences of
+his native superiority still upon him, he should submit himself to that
+crawling impersonation of meanness, Uriah Heep. The reversal of the
+two natures, in their relative positions, Uriah's of power and Mr.
+Wickfield's of dependence, was a sight more painful to me than I can
+express. If I had seen an Ape taking command of a Man, I should hardly
+have thought it a more degrading spectacle.
+
+He appeared to be only too conscious of it himself. When he came in, he
+stood still; and with his head bowed, as if he felt it. This was
+only for a moment; for Agnes softly said to him, 'Papa! Here is Miss
+Trotwood--and Trotwood, whom you have not seen for a long while!' and
+then he approached, and constrainedly gave my aunt his hand, and shook
+hands more cordially with me. In the moment's pause I speak of, I saw
+Uriah's countenance form itself into a most ill-favoured smile. Agnes
+saw it too, I think, for she shrank from him.
+
+What my aunt saw, or did not see, I defy the science of physiognomy
+to have made out, without her own consent. I believe there never was
+anybody with such an imperturbable countenance when she chose. Her face
+might have been a dead-wall on the occasion in question, for any light
+it threw upon her thoughts; until she broke silence with her usual
+abruptness.
+
+'Well, Wickfield!' said my aunt; and he looked up at her for the first
+time. 'I have been telling your daughter how well I have been disposing
+of my money for myself, because I couldn't trust it to you, as you were
+growing rusty in business matters. We have been taking counsel together,
+and getting on very well, all things considered. Agnes is worth the
+whole firm, in my opinion.'
+
+'If I may umbly make the remark,' said Uriah Heep, with a writhe, 'I
+fully agree with Miss Betsey Trotwood, and should be only too appy if
+Miss Agnes was a partner.'
+
+'You're a partner yourself, you know,' returned my aunt, 'and that's
+about enough for you, I expect. How do you find yourself, sir?'
+
+In acknowledgement of this question, addressed to him with extraordinary
+curtness, Mr. Heep, uncomfortably clutching the blue bag he carried,
+replied that he was pretty well, he thanked my aunt, and hoped she was
+the same.
+
+'And you, Master--I should say, Mister Copperfield,' pursued Uriah. 'I
+hope I see you well! I am rejoiced to see you, Mister Copperfield, even
+under present circumstances.' I believed that; for he seemed to relish
+them very much. 'Present circumstances is not what your friends would
+wish for you, Mister Copperfield, but it isn't money makes the man:
+it's--I am really unequal with my umble powers to express what it is,'
+said Uriah, with a fawning jerk, 'but it isn't money!'
+
+Here he shook hands with me: not in the common way, but standing at
+a good distance from me, and lifting my hand up and down like a pump
+handle, that he was a little afraid of.
+
+'And how do you think we are looking, Master Copperfield,--I should
+say, Mister?' fawned Uriah. 'Don't you find Mr. Wickfield blooming, sir?
+Years don't tell much in our firm, Master Copperfield, except in raising
+up the umble, namely, mother and self--and in developing,' he added, as
+an afterthought, 'the beautiful, namely, Miss Agnes.'
+
+He jerked himself about, after this compliment, in such an intolerable
+manner, that my aunt, who had sat looking straight at him, lost all
+patience.
+
+'Deuce take the man!' said my aunt, sternly, 'what's he about? Don't be
+galvanic, sir!'
+
+'I ask your pardon, Miss Trotwood,' returned Uriah; 'I'm aware you're
+nervous.'
+
+'Go along with you, sir!' said my aunt, anything but appeased. 'Don't
+presume to say so! I am nothing of the sort. If you're an eel, sir,
+conduct yourself like one. If you're a man, control your limbs, sir!
+Good God!' said my aunt, with great indignation, 'I am not going to be
+serpentined and corkscrewed out of my senses!'
+
+Mr. Heep was rather abashed, as most people might have been, by this
+explosion; which derived great additional force from the indignant
+manner in which my aunt afterwards moved in her chair, and shook her
+head as if she were making snaps or bounces at him. But he said to me
+aside in a meek voice:
+
+'I am well aware, Master Copperfield, that Miss Trotwood, though an
+excellent lady, has a quick temper (indeed I think I had the pleasure
+of knowing her, when I was a numble clerk, before you did, Master
+Copperfield), and it's only natural, I am sure, that it should be made
+quicker by present circumstances. The wonder is, that it isn't much
+worse! I only called to say that if there was anything we could do, in
+present circumstances, mother or self, or Wickfield and Heep,--we should
+be really glad. I may go so far?' said Uriah, with a sickly smile at his
+partner.
+
+'Uriah Heep,' said Mr. Wickfield, in a monotonous forced way, 'is active
+in the business, Trotwood. What he says, I quite concur in. You know
+I had an old interest in you. Apart from that, what Uriah says I quite
+concur in!'
+
+'Oh, what a reward it is,' said Uriah, drawing up one leg, at the risk
+of bringing down upon himself another visitation from my aunt, 'to be so
+trusted in! But I hope I am able to do something to relieve him from the
+fatigues of business, Master Copperfield!'
+
+'Uriah Heep is a great relief to me,' said Mr. Wickfield, in the same
+dull voice. 'It's a load off my mind, Trotwood, to have such a partner.'
+
+The red fox made him say all this, I knew, to exhibit him to me in the
+light he had indicated on the night when he poisoned my rest. I saw the
+same ill-favoured smile upon his face again, and saw how he watched me.
+
+'You are not going, papa?' said Agnes, anxiously. 'Will you not walk
+back with Trotwood and me?'
+
+He would have looked to Uriah, I believe, before replying, if that
+worthy had not anticipated him.
+
+'I am bespoke myself,' said Uriah, 'on business; otherwise I should
+have been appy to have kept with my friends. But I leave my partner to
+represent the firm. Miss Agnes, ever yours! I wish you good-day, Master
+Copperfield, and leave my umble respects for Miss Betsey Trotwood.'
+
+With those words, he retired, kissing his great hand, and leering at us
+like a mask.
+
+We sat there, talking about our pleasant old Canterbury days, an hour
+or two. Mr. Wickfield, left to Agnes, soon became more like his former
+self; though there was a settled depression upon him, which he never
+shook off. For all that, he brightened; and had an evident pleasure in
+hearing us recall the little incidents of our old life, many of which he
+remembered very well. He said it was like those times, to be alone with
+Agnes and me again; and he wished to Heaven they had never changed. I am
+sure there was an influence in the placid face of Agnes, and in the very
+touch of her hand upon his arm, that did wonders for him.
+
+My aunt (who was busy nearly all this while with Peggotty, in the inner
+room) would not accompany us to the place where they were staying, but
+insisted on my going; and I went. We dined together. After dinner, Agnes
+sat beside him, as of old, and poured out his wine. He took what she
+gave him, and no more--like a child--and we all three sat together at a
+window as the evening gathered in. When it was almost dark, he lay down
+on a sofa, Agnes pillowing his head and bending over him a little while;
+and when she came back to the window, it was not so dark but I could see
+tears glittering in her eyes.
+
+I pray Heaven that I never may forget the dear girl in her love and
+truth, at that time of my life; for if I should, I must be drawing near
+the end, and then I would desire to remember her best! She filled my
+heart with such good resolutions, strengthened my weakness so, by her
+example, so directed--I know not how, she was too modest and gentle
+to advise me in many words--the wandering ardour and unsettled purpose
+within me, that all the little good I have done, and all the harm I have
+forborne, I solemnly believe I may refer to her.
+
+And how she spoke to me of Dora, sitting at the window in the dark;
+listened to my praises of her; praised again; and round the little
+fairy-figure shed some glimpses of her own pure light, that made it yet
+more precious and more innocent to me! Oh, Agnes, sister of my boyhood,
+if I had known then, what I knew long afterwards--!
+
+There was a beggar in the street, when I went down; and as I turned my
+head towards the window, thinking of her calm seraphic eyes, he made me
+start by muttering, as if he were an echo of the morning: 'Blind! Blind!
+Blind!'
+
+
+
+CHAPTER 36. ENTHUSIASM
+
+I began the next day with another dive into the Roman bath, and then
+started for Highgate. I was not dispirited now. I was not afraid of the
+shabby coat, and had no yearnings after gallant greys. My whole manner
+of thinking of our late misfortune was changed. What I had to do, was,
+to show my aunt that her past goodness to me had not been thrown away
+on an insensible, ungrateful object. What I had to do, was, to turn the
+painful discipline of my younger days to account, by going to work with
+a resolute and steady heart. What I had to do, was, to take my woodman's
+axe in my hand, and clear my own way through the forest of difficulty,
+by cutting down the trees until I came to Dora. And I went on at a
+mighty rate, as if it could be done by walking.
+
+When I found myself on the familiar Highgate road, pursuing such a
+different errand from that old one of pleasure, with which it was
+associated, it seemed as if a complete change had come on my whole life.
+But that did not discourage me. With the new life, came new purpose,
+new intention. Great was the labour; priceless the reward. Dora was the
+reward, and Dora must be won.
+
+I got into such a transport, that I felt quite sorry my coat was not
+a little shabby already. I wanted to be cutting at those trees in the
+forest of difficulty, under circumstances that should prove my strength.
+I had a good mind to ask an old man, in wire spectacles, who was
+breaking stones upon the road, to lend me his hammer for a little while,
+and let me begin to beat a path to Dora out of granite. I stimulated
+myself into such a heat, and got so out of breath, that I felt as if I
+had been earning I don't know how much.
+
+In this state, I went into a cottage that I saw was to let, and examined
+it narrowly,--for I felt it necessary to be practical. It would do for
+me and Dora admirably: with a little front garden for Jip to run about
+in, and bark at the tradespeople through the railings, and a capital
+room upstairs for my aunt. I came out again, hotter and faster than
+ever, and dashed up to Highgate, at such a rate that I was there an
+hour too early; and, though I had not been, should have been obliged to
+stroll about to cool myself, before I was at all presentable.
+
+My first care, after putting myself under this necessary course of
+preparation, was to find the Doctor's house. It was not in that part of
+Highgate where Mrs. Steerforth lived, but quite on the opposite side
+of the little town. When I had made this discovery, I went back, in
+an attraction I could not resist, to a lane by Mrs. Steerforth's, and
+looked over the corner of the garden wall. His room was shut up close.
+The conservatory doors were standing open, and Rosa Dartle was walking,
+bareheaded, with a quick, impetuous step, up and down a gravel walk on
+one side of the lawn. She gave me the idea of some fierce thing, that
+was dragging the length of its chain to and fro upon a beaten track, and
+wearing its heart out.
+
+I came softly away from my place of observation, and avoiding that part
+of the neighbourhood, and wishing I had not gone near it, strolled about
+until it was ten o'clock. The church with the slender spire, that stands
+on the top of the hill now, was not there then to tell me the time. An
+old red-brick mansion, used as a school, was in its place; and a fine
+old house it must have been to go to school at, as I recollect it.
+
+When I approached the Doctor's cottage--a pretty old place, on which
+he seemed to have expended some money, if I might judge from the
+embellishments and repairs that had the look of being just completed--I
+saw him walking in the garden at the side, gaiters and all, as if he
+had never left off walking since the days of my pupilage. He had his old
+companions about him, too; for there were plenty of high trees in the
+neighbourhood, and two or three rooks were on the grass, looking after
+him, as if they had been written to about him by the Canterbury rooks,
+and were observing him closely in consequence.
+
+Knowing the utter hopelessness of attracting his attention from that
+distance, I made bold to open the gate, and walk after him, so as to
+meet him when he should turn round. When he did, and came towards me, he
+looked at me thoughtfully for a few moments, evidently without thinking
+about me at all; and then his benevolent face expressed extraordinary
+pleasure, and he took me by both hands.
+
+'Why, my dear Copperfield,' said the Doctor, 'you are a man! How do you
+do? I am delighted to see you. My dear Copperfield, how very much you
+have improved! You are quite--yes--dear me!'
+
+I hoped he was well, and Mrs. Strong too.
+
+'Oh dear, yes!' said the Doctor; 'Annie's quite well, and she'll be
+delighted to see you. You were always her favourite. She said so,
+last night, when I showed her your letter. And--yes, to be sure--you
+recollect Mr. Jack Maldon, Copperfield?'
+
+'Perfectly, sir.'
+
+'Of course,' said the Doctor. 'To be sure. He's pretty well, too.'
+
+'Has he come home, sir?' I inquired.
+
+'From India?' said the Doctor. 'Yes. Mr. Jack Maldon couldn't bear
+the climate, my dear. Mrs. Markleham--you have not forgotten Mrs.
+Markleham?'
+
+Forgotten the Old Soldier! And in that short time!
+
+'Mrs. Markleham,' said the Doctor, 'was quite vexed about him, poor
+thing; so we have got him at home again; and we have bought him a little
+Patent place, which agrees with him much better.' I knew enough of Mr.
+Jack Maldon to suspect from this account that it was a place where there
+was not much to do, and which was pretty well paid. The Doctor, walking
+up and down with his hand on my shoulder, and his kind face turned
+encouragingly to mine, went on:
+
+'Now, my dear Copperfield, in reference to this proposal of yours. It's
+very gratifying and agreeable to me, I am sure; but don't you think you
+could do better? You achieved distinction, you know, when you were with
+us. You are qualified for many good things. You have laid a foundation
+that any edifice may be raised upon; and is it not a pity that you
+should devote the spring-time of your life to such a poor pursuit as I
+can offer?'
+
+I became very glowing again, and, expressing myself in a rhapsodical
+style, I am afraid, urged my request strongly; reminding the Doctor that
+I had already a profession.
+
+'Well, well,' said the Doctor, 'that's true. Certainly, your having
+a profession, and being actually engaged in studying it, makes a
+difference. But, my good young friend, what's seventy pounds a year?'
+
+'It doubles our income, Doctor Strong,' said I.
+
+'Dear me!' replied the Doctor. 'To think of that! Not that I mean to
+say it's rigidly limited to seventy pounds a-year, because I have always
+contemplated making any young friend I might thus employ, a present too.
+Undoubtedly,' said the Doctor, still walking me up and down with
+his hand on my shoulder. 'I have always taken an annual present into
+account.'
+
+'My dear tutor,' said I (now, really, without any nonsense), 'to whom I
+owe more obligations already than I ever can acknowledge--'
+
+'No, no,' interposed the Doctor. 'Pardon me!'
+
+'If you will take such time as I have, and that is my mornings and
+evenings, and can think it worth seventy pounds a year, you will do me
+such a service as I cannot express.'
+
+'Dear me!' said the Doctor, innocently. 'To think that so little should
+go for so much! Dear, dear! And when you can do better, you will? On
+your word, now?' said the Doctor,--which he had always made a very grave
+appeal to the honour of us boys.
+
+'On my word, sir!' I returned, answering in our old school manner.
+
+'Then be it so,' said the Doctor, clapping me on the shoulder, and still
+keeping his hand there, as we still walked up and down.
+
+'And I shall be twenty times happier, sir,' said I, with a little--I
+hope innocent--flattery, 'if my employment is to be on the Dictionary.'
+
+The Doctor stopped, smilingly clapped me on the shoulder again, and
+exclaimed, with a triumph most delightful to behold, as if I had
+penetrated to the profoundest depths of mortal sagacity, 'My dear young
+friend, you have hit it. It IS the Dictionary!'
+
+How could it be anything else! His pockets were as full of it as his
+head. It was sticking out of him in all directions. He told me that
+since his retirement from scholastic life, he had been advancing with
+it wonderfully; and that nothing could suit him better than the proposed
+arrangements for morning and evening work, as it was his custom to walk
+about in the daytime with his considering cap on. His papers were in
+a little confusion, in consequence of Mr. Jack Maldon having lately
+proffered his occasional services as an amanuensis, and not being
+accustomed to that occupation; but we should soon put right what was
+amiss, and go on swimmingly. Afterwards, when we were fairly at our
+work, I found Mr. Jack Maldon's efforts more troublesome to me than
+I had expected, as he had not confined himself to making numerous
+mistakes, but had sketched so many soldiers, and ladies' heads, over
+the Doctor's manuscript, that I often became involved in labyrinths of
+obscurity.
+
+The Doctor was quite happy in the prospect of our going to work together
+on that wonderful performance, and we settled to begin next morning at
+seven o'clock. We were to work two hours every morning, and two or three
+hours every night, except on Saturdays, when I was to rest. On Sundays,
+of course, I was to rest also, and I considered these very easy terms.
+
+Our plans being thus arranged to our mutual satisfaction, the Doctor
+took me into the house to present me to Mrs. Strong, whom we found in
+the Doctor's new study, dusting his books,--a freedom which he never
+permitted anybody else to take with those sacred favourites.
+
+They had postponed their breakfast on my account, and we sat down to
+table together. We had not been seated long, when I saw an approaching
+arrival in Mrs. Strong's face, before I heard any sound of it. A
+gentleman on horseback came to the gate, and leading his horse into the
+little court, with the bridle over his arm, as if he were quite at home,
+tied him to a ring in the empty coach-house wall, and came into the
+breakfast parlour, whip in hand. It was Mr. Jack Maldon; and Mr. Jack
+Maldon was not at all improved by India, I thought. I was in a state
+of ferocious virtue, however, as to young men who were not cutting down
+trees in the forest of difficulty; and my impression must be received
+with due allowance.
+
+'Mr. Jack!' said the Doctor. 'Copperfield!'
+
+Mr. Jack Maldon shook hands with me; but not very warmly, I believed;
+and with an air of languid patronage, at which I secretly took great
+umbrage. But his languor altogether was quite a wonderful sight; except
+when he addressed himself to his cousin Annie. 'Have you breakfasted
+this morning, Mr. Jack?' said the Doctor.
+
+'I hardly ever take breakfast, sir,' he replied, with his head thrown
+back in an easy-chair. 'I find it bores me.'
+
+'Is there any news today?' inquired the Doctor.
+
+'Nothing at all, sir,' replied Mr. Maldon. 'There's an account about
+the people being hungry and discontented down in the North, but they are
+always being hungry and discontented somewhere.'
+
+The Doctor looked grave, and said, as though he wished to change the
+subject, 'Then there's no news at all; and no news, they say, is good
+news.'
+
+'There's a long statement in the papers, sir, about a murder,' observed
+Mr. Maldon. 'But somebody is always being murdered, and I didn't read
+it.'
+
+A display of indifference to all the actions and passions of mankind was
+not supposed to be such a distinguished quality at that time, I think,
+as I have observed it to be considered since. I have known it very
+fashionable indeed. I have seen it displayed with such success, that I
+have encountered some fine ladies and gentlemen who might as well have
+been born caterpillars. Perhaps it impressed me the more then, because
+it was new to me, but it certainly did not tend to exalt my opinion of,
+or to strengthen my confidence in, Mr. Jack Maldon.
+
+'I came out to inquire whether Annie would like to go to the opera
+tonight,' said Mr. Maldon, turning to her. 'It's the last good night
+there will be, this season; and there's a singer there, whom she really
+ought to hear. She is perfectly exquisite. Besides which, she is so
+charmingly ugly,' relapsing into languor.
+
+The Doctor, ever pleased with what was likely to please his young wife,
+turned to her and said:
+
+'You must go, Annie. You must go.'
+
+'I would rather not,' she said to the Doctor. 'I prefer to remain at
+home. I would much rather remain at home.'
+
+Without looking at her cousin, she then addressed me, and asked me about
+Agnes, and whether she should see her, and whether she was not likely to
+come that day; and was so much disturbed, that I wondered how even the
+Doctor, buttering his toast, could be blind to what was so obvious.
+
+But he saw nothing. He told her, good-naturedly, that she was young and
+ought to be amused and entertained, and must not allow herself to be
+made dull by a dull old fellow. Moreover, he said, he wanted to hear her
+sing all the new singer's songs to him; and how could she do that well,
+unless she went? So the Doctor persisted in making the engagement for
+her, and Mr. Jack Maldon was to come back to dinner. This concluded, he
+went to his Patent place, I suppose; but at all events went away on his
+horse, looking very idle.
+
+I was curious to find out next morning, whether she had been. She had
+not, but had sent into London to put her cousin off; and had gone out in
+the afternoon to see Agnes, and had prevailed upon the Doctor to go with
+her; and they had walked home by the fields, the Doctor told me, the
+evening being delightful. I wondered then, whether she would have gone
+if Agnes had not been in town, and whether Agnes had some good influence
+over her too!
+
+She did not look very happy, I thought; but it was a good face, or a
+very false one. I often glanced at it, for she sat in the window all the
+time we were at work; and made our breakfast, which we took by snatches
+as we were employed. When I left, at nine o'clock, she was kneeling on
+the ground at the Doctor's feet, putting on his shoes and gaiters for
+him. There was a softened shade upon her face, thrown from some green
+leaves overhanging the open window of the low room; and I thought all
+the way to Doctors' Commons, of the night when I had seen it looking at
+him as he read.
+
+I was pretty busy now; up at five in the morning, and home at nine
+or ten at night. But I had infinite satisfaction in being so
+closely engaged, and never walked slowly on any account, and felt
+enthusiastically that the more I tired myself, the more I was doing to
+deserve Dora. I had not revealed myself in my altered character to
+Dora yet, because she was coming to see Miss Mills in a few days, and
+I deferred all I had to tell her until then; merely informing her in
+my letters (all our communications were secretly forwarded through Miss
+Mills), that I had much to tell her. In the meantime, I put myself on
+a short allowance of bear's grease, wholly abandoned scented soap and
+lavender water, and sold off three waistcoats at a prodigious sacrifice,
+as being too luxurious for my stern career.
+
+Not satisfied with all these proceedings, but burning with impatience
+to do something more, I went to see Traddles, now lodging up behind the
+parapet of a house in Castle Street, Holborn. Mr. Dick, who had been
+with me to Highgate twice already, and had resumed his companionship
+with the Doctor, I took with me.
+
+I took Mr. Dick with me, because, acutely sensitive to my aunt's
+reverses, and sincerely believing that no galley-slave or convict worked
+as I did, he had begun to fret and worry himself out of spirits and
+appetite, as having nothing useful to do. In this condition, he felt
+more incapable of finishing the Memorial than ever; and the harder he
+worked at it, the oftener that unlucky head of King Charles the First
+got into it. Seriously apprehending that his malady would increase,
+unless we put some innocent deception upon him and caused him to believe
+that he was useful, or unless we could put him in the way of being
+really useful (which would be better), I made up my mind to try
+if Traddles could help us. Before we went, I wrote Traddles a full
+statement of all that had happened, and Traddles wrote me back a capital
+answer, expressive of his sympathy and friendship.
+
+We found him hard at work with his inkstand and papers, refreshed by the
+sight of the flower-pot stand and the little round table in a corner of
+the small apartment. He received us cordially, and made friends with
+Mr. Dick in a moment. Mr. Dick professed an absolute certainty of having
+seen him before, and we both said, 'Very likely.'
+
+The first subject on which I had to consult Traddles was this,--I had
+heard that many men distinguished in various pursuits had begun life
+by reporting the debates in Parliament. Traddles having mentioned
+newspapers to me, as one of his hopes, I had put the two things
+together, and told Traddles in my letter that I wished to know how I
+could qualify myself for this pursuit. Traddles now informed me, as the
+result of his inquiries, that the mere mechanical acquisition necessary,
+except in rare cases, for thorough excellence in it, that is to say,
+a perfect and entire command of the mystery of short-hand writing and
+reading, was about equal in difficulty to the mastery of six languages;
+and that it might perhaps be attained, by dint of perseverance, in the
+course of a few years. Traddles reasonably supposed that this would
+settle the business; but I, only feeling that here indeed were a few
+tall trees to be hewn down, immediately resolved to work my way on to
+Dora through this thicket, axe in hand.
+
+'I am very much obliged to you, my dear Traddles!' said I. 'I'll begin
+tomorrow.'
+
+Traddles looked astonished, as he well might; but he had no notion as
+yet of my rapturous condition.
+
+'I'll buy a book,' said I, 'with a good scheme of this art in it; I'll
+work at it at the Commons, where I haven't half enough to do; I'll take
+down the speeches in our court for practice--Traddles, my dear fellow,
+I'll master it!'
+
+'Dear me,' said Traddles, opening his eyes, 'I had no idea you were such
+a determined character, Copperfield!'
+
+I don't know how he should have had, for it was new enough to me. I
+passed that off, and brought Mr. Dick on the carpet.
+
+'You see,' said Mr. Dick, wistfully, 'if I could exert myself, Mr.
+Traddles--if I could beat a drum--or blow anything!'
+
+Poor fellow! I have little doubt he would have preferred such an
+employment in his heart to all others. Traddles, who would not have
+smiled for the world, replied composedly:
+
+'But you are a very good penman, sir. You told me so, Copperfield?'
+'Excellent!' said I. And indeed he was. He wrote with extraordinary
+neatness.
+
+'Don't you think,' said Traddles, 'you could copy writings, sir, if I
+got them for you?'
+
+Mr. Dick looked doubtfully at me. 'Eh, Trotwood?'
+
+I shook my head. Mr. Dick shook his, and sighed. 'Tell him about the
+Memorial,' said Mr. Dick.
+
+I explained to Traddles that there was a difficulty in keeping King
+Charles the First out of Mr. Dick's manuscripts; Mr. Dick in the
+meanwhile looking very deferentially and seriously at Traddles, and
+sucking his thumb.
+
+'But these writings, you know, that I speak of, are already drawn up
+and finished,' said Traddles after a little consideration. 'Mr. Dick has
+nothing to do with them. Wouldn't that make a difference, Copperfield?
+At all events, wouldn't it be well to try?'
+
+This gave us new hope. Traddles and I laying our heads together apart,
+while Mr. Dick anxiously watched us from his chair, we concocted a
+scheme in virtue of which we got him to work next day, with triumphant
+success.
+
+On a table by the window in Buckingham Street, we set out the work
+Traddles procured for him--which was to make, I forget how many copies
+of a legal document about some right of way--and on another table
+we spread the last unfinished original of the great Memorial. Our
+instructions to Mr. Dick were that he should copy exactly what he had
+before him, without the least departure from the original; and that when
+he felt it necessary to make the slightest allusion to King Charles the
+First, he should fly to the Memorial. We exhorted him to be resolute
+in this, and left my aunt to observe him. My aunt reported to us,
+afterwards, that, at first, he was like a man playing the kettle-drums,
+and constantly divided his attentions between the two; but that, finding
+this confuse and fatigue him, and having his copy there, plainly before
+his eyes, he soon sat at it in an orderly business-like manner, and
+postponed the Memorial to a more convenient time. In a word, although we
+took great care that he should have no more to do than was good for him,
+and although he did not begin with the beginning of a week, he earned
+by the following Saturday night ten shillings and nine-pence; and never,
+while I live, shall I forget his going about to all the shops in the
+neighbourhood to change this treasure into sixpences, or his bringing
+them to my aunt arranged in the form of a heart upon a waiter, with
+tears of joy and pride in his eyes. He was like one under the propitious
+influence of a charm, from the moment of his being usefully employed;
+and if there were a happy man in the world, that Saturday night, it was
+the grateful creature who thought my aunt the most wonderful woman in
+existence, and me the most wonderful young man.
+
+'No starving now, Trotwood,' said Mr. Dick, shaking hands with me in a
+corner. 'I'll provide for her, Sir!' and he flourished his ten fingers
+in the air, as if they were ten banks.
+
+I hardly know which was the better pleased, Traddles or I. 'It really,'
+said Traddles, suddenly, taking a letter out of his pocket, and giving
+it to me, 'put Mr. Micawber quite out of my head!'
+
+The letter (Mr. Micawber never missed any possible opportunity of
+writing a letter) was addressed to me, 'By the kindness of T. Traddles,
+Esquire, of the Inner Temple.' It ran thus:--
+
+
+'MY DEAR COPPERFIELD,
+
+'You may possibly not be unprepared to receive the intimation that
+something has turned up. I may have mentioned to you on a former
+occasion that I was in expectation of such an event.
+
+'I am about to establish myself in one of the provincial towns of our
+favoured island (where the society may be described as a happy admixture
+of the agricultural and the clerical), in immediate connexion with
+one of the learned professions. Mrs. Micawber and our offspring will
+accompany me. Our ashes, at a future period, will probably be found
+commingled in the cemetery attached to a venerable pile, for which the
+spot to which I refer has acquired a reputation, shall I say from China
+to Peru?
+
+'In bidding adieu to the modern Babylon, where we have undergone many
+vicissitudes, I trust not ignobly, Mrs. Micawber and myself cannot
+disguise from our minds that we part, it may be for years and it may be
+for ever, with an individual linked by strong associations to the altar
+of our domestic life. If, on the eve of such a departure, you will
+accompany our mutual friend, Mr. Thomas Traddles, to our present abode,
+and there reciprocate the wishes natural to the occasion, you will
+confer a Boon
+
+               'On
+                    'One
+                         'Who
+                              'Is
+                                   'Ever yours,
+                                        'WILKINS MICAWBER.'
+
+
+I was glad to find that Mr. Micawber had got rid of his dust and ashes,
+and that something really had turned up at last. Learning from Traddles
+that the invitation referred to the evening then wearing away, I
+expressed my readiness to do honour to it; and we went off together to
+the lodging which Mr. Micawber occupied as Mr. Mortimer, and which was
+situated near the top of the Gray's Inn Road.
+
+The resources of this lodging were so limited, that we found the twins,
+now some eight or nine years old, reposing in a turn-up bedstead in
+the family sitting-room, where Mr. Micawber had prepared, in a
+wash-hand-stand jug, what he called 'a Brew' of the agreeable beverage
+for which he was famous. I had the pleasure, on this occasion, of
+renewing the acquaintance of Master Micawber, whom I found a promising
+boy of about twelve or thirteen, very subject to that restlessness of
+limb which is not an unfrequent phenomenon in youths of his age. I also
+became once more known to his sister, Miss Micawber, in whom, as Mr.
+Micawber told us, 'her mother renewed her youth, like the Phoenix'.
+
+'My dear Copperfield,' said Mr. Micawber, 'yourself and Mr. Traddles
+find us on the brink of migration, and will excuse any little
+discomforts incidental to that position.'
+
+Glancing round as I made a suitable reply, I observed that the family
+effects were already packed, and that the amount of luggage was by no
+means overwhelming. I congratulated Mrs. Micawber on the approaching
+change.
+
+'My dear Mr. Copperfield,' said Mrs. Micawber, 'of your friendly
+interest in all our affairs, I am well assured. My family may consider
+it banishment, if they please; but I am a wife and mother, and I never
+will desert Mr. Micawber.'
+
+Traddles, appealed to by Mrs. Micawber's eye, feelingly acquiesced.
+
+'That,' said Mrs. Micawber, 'that, at least, is my view, my dear Mr.
+Copperfield and Mr. Traddles, of the obligation which I took upon myself
+when I repeated the irrevocable words, "I, Emma, take thee, Wilkins." I
+read the service over with a flat-candle on the previous night, and
+the conclusion I derived from it was, that I never could desert Mr.
+Micawber. And,' said Mrs. Micawber, 'though it is possible I may be
+mistaken in my view of the ceremony, I never will!'
+
+'My dear,' said Mr. Micawber, a little impatiently, 'I am not conscious
+that you are expected to do anything of the sort.'
+
+'I am aware, my dear Mr. Copperfield,' pursued Mrs. Micawber, 'that I am
+now about to cast my lot among strangers; and I am also aware that the
+various members of my family, to whom Mr. Micawber has written in the
+most gentlemanly terms, announcing that fact, have not taken the least
+notice of Mr. Micawber's communication. Indeed I may be superstitious,'
+said Mrs. Micawber, 'but it appears to me that Mr. Micawber is destined
+never to receive any answers whatever to the great majority of the
+communications he writes. I may augur, from the silence of my family,
+that they object to the resolution I have taken; but I should not allow
+myself to be swerved from the path of duty, Mr. Copperfield, even by my
+papa and mama, were they still living.'
+
+I expressed my opinion that this was going in the right direction. 'It
+may be a sacrifice,' said Mrs. Micawber, 'to immure one's-self in a
+Cathedral town; but surely, Mr. Copperfield, if it is a sacrifice in me,
+it is much more a sacrifice in a man of Mr. Micawber's abilities.'
+
+'Oh! You are going to a Cathedral town?' said I.
+
+Mr. Micawber, who had been helping us all, out of the wash-hand-stand
+jug, replied:
+
+'To Canterbury. In fact, my dear Copperfield, I have entered into
+arrangements, by virtue of which I stand pledged and contracted to our
+friend Heep, to assist and serve him in the capacity of--and to be--his
+confidential clerk.'
+
+I stared at Mr. Micawber, who greatly enjoyed my surprise.
+
+'I am bound to state to you,' he said, with an official air, 'that the
+business habits, and the prudent suggestions, of Mrs. Micawber, have
+in a great measure conduced to this result. The gauntlet, to which Mrs.
+Micawber referred upon a former occasion, being thrown down in the form
+of an advertisement, was taken up by my friend Heep, and led to a mutual
+recognition. Of my friend Heep,' said Mr. Micawber, 'who is a man of
+remarkable shrewdness, I desire to speak with all possible respect.
+My friend Heep has not fixed the positive remuneration at too high a
+figure, but he has made a great deal, in the way of extrication from
+the pressure of pecuniary difficulties, contingent on the value of
+my services; and on the value of those services I pin my faith. Such
+address and intelligence as I chance to possess,' said Mr. Micawber,
+boastfully disparaging himself, with the old genteel air, 'will be
+devoted to my friend Heep's service. I have already some acquaintance
+with the law--as a defendant on civil process--and I shall immediately
+apply myself to the Commentaries of one of the most eminent and
+remarkable of our English jurists. I believe it is unnecessary to add
+that I allude to Mr. justice Blackstone.'
+
+These observations, and indeed the greater part of the observations
+made that evening, were interrupted by Mrs. Micawber's discovering that
+Master Micawber was sitting on his boots, or holding his head on with
+both arms as if he felt it loose, or accidentally kicking Traddles under
+the table, or shuffling his feet over one another, or producing them
+at distances from himself apparently outrageous to nature, or lying
+sideways with his hair among the wine-glasses, or developing his
+restlessness of limb in some other form incompatible with the general
+interests of society; and by Master Micawber's receiving those
+discoveries in a resentful spirit. I sat all the while, amazed by Mr.
+Micawber's disclosure, and wondering what it meant; until Mrs. Micawber
+resumed the thread of the discourse, and claimed my attention.
+
+'What I particularly request Mr. Micawber to be careful of, is,' said
+Mrs. Micawber, 'that he does not, my dear Mr. Copperfield, in applying
+himself to this subordinate branch of the law, place it out of his power
+to rise, ultimately, to the top of the tree. I am convinced that Mr.
+Micawber, giving his mind to a profession so adapted to his fertile
+resources, and his flow of language, must distinguish himself. Now, for
+example, Mr. Traddles,' said Mrs. Micawber, assuming a profound air, 'a
+judge, or even say a Chancellor. Does an individual place himself beyond
+the pale of those preferments by entering on such an office as Mr.
+Micawber has accepted?'
+
+'My dear,' observed Mr. Micawber--but glancing inquisitively at
+Traddles, too; 'we have time enough before us, for the consideration of
+those questions.'
+
+'Micawber,' she returned, 'no! Your mistake in life is, that you do not
+look forward far enough. You are bound, in justice to your family, if
+not to yourself, to take in at a comprehensive glance the extremest
+point in the horizon to which your abilities may lead you.'
+
+Mr. Micawber coughed, and drank his punch with an air of exceeding
+satisfaction--still glancing at Traddles, as if he desired to have his
+opinion.
+
+'Why, the plain state of the case, Mrs. Micawber,' said Traddles, mildly
+breaking the truth to her. 'I mean the real prosaic fact, you know--'
+
+'Just so,' said Mrs. Micawber, 'my dear Mr. Traddles, I wish to be as
+prosaic and literal as possible on a subject of so much importance.'
+
+'--Is,' said Traddles, 'that this branch of the law, even if Mr.
+Micawber were a regular solicitor--'
+
+'Exactly so,' returned Mrs. Micawber. ('Wilkins, you are squinting, and
+will not be able to get your eyes back.')
+
+'--Has nothing,' pursued Traddles, 'to do with that. Only a barrister
+is eligible for such preferments; and Mr. Micawber could not be a
+barrister, without being entered at an inn of court as a student, for
+five years.'
+
+'Do I follow you?' said Mrs. Micawber, with her most affable air
+of business. 'Do I understand, my dear Mr. Traddles, that, at the
+expiration of that period, Mr. Micawber would be eligible as a Judge or
+Chancellor?'
+
+'He would be ELIGIBLE,' returned Traddles, with a strong emphasis on
+that word.
+
+'Thank you,' said Mrs. Micawber. 'That is quite sufficient. If such is
+the case, and Mr. Micawber forfeits no privilege by entering on these
+duties, my anxiety is set at rest. I speak,' said Mrs. Micawber, 'as a
+female, necessarily; but I have always been of opinion that Mr. Micawber
+possesses what I have heard my papa call, when I lived at home, the
+judicial mind; and I hope Mr. Micawber is now entering on a field where
+that mind will develop itself, and take a commanding station.'
+
+I quite believe that Mr. Micawber saw himself, in his judicial mind's
+eye, on the woolsack. He passed his hand complacently over his bald
+head, and said with ostentatious resignation:
+
+'My dear, we will not anticipate the decrees of fortune. If I am
+reserved to wear a wig, I am at least prepared, externally,' in allusion
+to his baldness, 'for that distinction. I do not,' said Mr. Micawber,
+'regret my hair, and I may have been deprived of it for a specific
+purpose. I cannot say. It is my intention, my dear Copperfield, to
+educate my son for the Church; I will not deny that I should be happy,
+on his account, to attain to eminence.'
+
+'For the Church?' said I, still pondering, between whiles, on Uriah
+Heep.
+
+'Yes,' said Mr. Micawber. 'He has a remarkable head-voice, and will
+commence as a chorister. Our residence at Canterbury, and our local
+connexion, will, no doubt, enable him to take advantage of any vacancy
+that may arise in the Cathedral corps.'
+
+On looking at Master Micawber again, I saw that he had a certain
+expression of face, as if his voice were behind his eyebrows; where it
+presently appeared to be, on his singing us (as an alternative between
+that and bed) 'The Wood-Pecker tapping'. After many compliments on this
+performance, we fell into some general conversation; and as I was too
+full of my desperate intentions to keep my altered circumstances to
+myself, I made them known to Mr. and Mrs. Micawber. I cannot express how
+extremely delighted they both were, by the idea of my aunt's being in
+difficulties; and how comfortable and friendly it made them.
+
+When we were nearly come to the last round of the punch, I addressed
+myself to Traddles, and reminded him that we must not separate, without
+wishing our friends health, happiness, and success in their new career.
+I begged Mr. Micawber to fill us bumpers, and proposed the toast in
+due form: shaking hands with him across the table, and kissing Mrs.
+Micawber, to commemorate that eventful occasion. Traddles imitated me
+in the first particular, but did not consider himself a sufficiently old
+friend to venture on the second.
+
+'My dear Copperfield,' said Mr. Micawber, rising with one of his thumbs
+in each of his waistcoat pockets, 'the companion of my youth: if I may
+be allowed the expression--and my esteemed friend Traddles: if I may be
+permitted to call him so--will allow me, on the part of Mrs. Micawber,
+myself, and our offspring, to thank them in the warmest and most
+uncompromising terms for their good wishes. It may be expected that
+on the eve of a migration which will consign us to a perfectly new
+existence,' Mr. Micawber spoke as if they were going five hundred
+thousand miles, 'I should offer a few valedictory remarks to two such
+friends as I see before me. But all that I have to say in this way, I
+have said. Whatever station in society I may attain, through the medium
+of the learned profession of which I am about to become an unworthy
+member, I shall endeavour not to disgrace, and Mrs. Micawber will be
+safe to adorn. Under the temporary pressure of pecuniary liabilities,
+contracted with a view to their immediate liquidation, but remaining
+unliquidated through a combination of circumstances, I have been
+under the necessity of assuming a garb from which my natural instincts
+recoil--I allude to spectacles--and possessing myself of a cognomen, to
+which I can establish no legitimate pretensions. All I have to say on
+that score is, that the cloud has passed from the dreary scene, and the
+God of Day is once more high upon the mountain tops. On Monday next, on
+the arrival of the four o'clock afternoon coach at Canterbury, my foot
+will be on my native heath--my name, Micawber!'
+
+Mr. Micawber resumed his seat on the close of these remarks, and
+drank two glasses of punch in grave succession. He then said with much
+solemnity:
+
+'One thing more I have to do, before this separation is complete, and
+that is to perform an act of justice. My friend Mr. Thomas Traddles
+has, on two several occasions, "put his name", if I may use a common
+expression, to bills of exchange for my accommodation. On the first
+occasion Mr. Thomas Traddles was left--let me say, in short, in the
+lurch. The fulfilment of the second has not yet arrived. The amount of
+the first obligation,' here Mr. Micawber carefully referred to papers,
+'was, I believe, twenty-three, four, nine and a half, of the second,
+according to my entry of that transaction, eighteen, six, two. These
+sums, united, make a total, if my calculation is correct, amounting to
+forty-one, ten, eleven and a half. My friend Copperfield will perhaps do
+me the favour to check that total?'
+
+I did so and found it correct.
+
+'To leave this metropolis,' said Mr. Micawber, 'and my friend Mr.
+Thomas Traddles, without acquitting myself of the pecuniary part of this
+obligation, would weigh upon my mind to an insupportable extent. I have,
+therefore, prepared for my friend Mr. Thomas Traddles, and I now hold
+in my hand, a document, which accomplishes the desired object. I beg
+to hand to my friend Mr. Thomas Traddles my I.O.U. for forty-one, ten,
+eleven and a half, and I am happy to recover my moral dignity, and to
+know that I can once more walk erect before my fellow man!'
+
+With this introduction (which greatly affected him), Mr. Micawber placed
+his I.O.U. in the hands of Traddles, and said he wished him well in
+every relation of life. I am persuaded, not only that this was quite
+the same to Mr. Micawber as paying the money, but that Traddles himself
+hardly knew the difference until he had had time to think about it. Mr.
+Micawber walked so erect before his fellow man, on the strength of
+this virtuous action, that his chest looked half as broad again when he
+lighted us downstairs. We parted with great heartiness on both sides;
+and when I had seen Traddles to his own door, and was going home alone,
+I thought, among the other odd and contradictory things I mused upon,
+that, slippery as Mr. Micawber was, I was probably indebted to some
+compassionate recollection he retained of me as his boy-lodger, for
+never having been asked by him for money. I certainly should not have
+had the moral courage to refuse it; and I have no doubt he knew that (to
+his credit be it written), quite as well as I did.
+
+
+
+CHAPTER 37. A LITTLE COLD WATER
+
+
+My new life had lasted for more than a week, and I was stronger than
+ever in those tremendous practical resolutions that I felt the crisis
+required. I continued to walk extremely fast, and to have a general idea
+that I was getting on. I made it a rule to take as much out of myself
+as I possibly could, in my way of doing everything to which I applied
+my energies. I made a perfect victim of myself. I even entertained some
+idea of putting myself on a vegetable diet, vaguely conceiving that, in
+becoming a graminivorous animal, I should sacrifice to Dora.
+
+As yet, little Dora was quite unconscious of my desperate firmness,
+otherwise than as my letters darkly shadowed it forth. But another
+Saturday came, and on that Saturday evening she was to be at Miss
+Mills's; and when Mr. Mills had gone to his whist-club (telegraphed to
+me in the street, by a bird-cage in the drawing-room middle window), I
+was to go there to tea.
+
+By this time, we were quite settled down in Buckingham Street, where Mr.
+Dick continued his copying in a state of absolute felicity. My aunt had
+obtained a signal victory over Mrs. Crupp, by paying her off, throwing
+the first pitcher she planted on the stairs out of window, and
+protecting in person, up and down the staircase, a supernumerary whom
+she engaged from the outer world. These vigorous measures struck such
+terror to the breast of Mrs. Crupp, that she subsided into her own
+kitchen, under the impression that my aunt was mad. My aunt being
+supremely indifferent to Mrs. Crupp's opinion and everybody else's, and
+rather favouring than discouraging the idea, Mrs. Crupp, of late the
+bold, became within a few days so faint-hearted, that rather than
+encounter my aunt upon the staircase, she would endeavour to hide her
+portly form behind doors--leaving visible, however, a wide margin of
+flannel petticoat--or would shrink into dark corners. This gave my aunt
+such unspeakable satisfaction, that I believe she took a delight in
+prowling up and down, with her bonnet insanely perched on the top of her
+head, at times when Mrs. Crupp was likely to be in the way.
+
+My aunt, being uncommonly neat and ingenious, made so many little
+improvements in our domestic arrangements, that I seemed to be richer
+instead of poorer. Among the rest, she converted the pantry into a
+dressing-room for me; and purchased and embellished a bedstead for my
+occupation, which looked as like a bookcase in the daytime as a bedstead
+could. I was the object of her constant solicitude; and my poor mother
+herself could not have loved me better, or studied more how to make me
+happy.
+
+Peggotty had considered herself highly privileged in being allowed to
+participate in these labours; and, although she still retained something
+of her old sentiment of awe in reference to my aunt, had received so
+many marks of encouragement and confidence, that they were the best
+friends possible. But the time had now come (I am speaking of the
+Saturday when I was to take tea at Miss Mills's) when it was necessary
+for her to return home, and enter on the discharge of the duties she had
+undertaken in behalf of Ham. 'So good-bye, Barkis,' said my aunt, 'and
+take care of yourself! I am sure I never thought I could be sorry to
+lose you!'
+
+I took Peggotty to the coach office and saw her off. She cried at
+parting, and confided her brother to my friendship as Ham had done. We
+had heard nothing of him since he went away, that sunny afternoon.
+
+'And now, my own dear Davy,' said Peggotty, 'if, while you're a
+prentice, you should want any money to spend; or if, when you're out of
+your time, my dear, you should want any to set you up (and you must do
+one or other, or both, my darling); who has such a good right to ask
+leave to lend it you, as my sweet girl's own old stupid me!'
+
+I was not so savagely independent as to say anything in reply, but that
+if ever I borrowed money of anyone, I would borrow it of her. Next to
+accepting a large sum on the spot, I believe this gave Peggotty more
+comfort than anything I could have done.
+
+'And, my dear!' whispered Peggotty, 'tell the pretty little angel that
+I should so have liked to see her, only for a minute! And tell her that
+before she marries my boy, I'll come and make your house so beautiful
+for you, if you'll let me!'
+
+I declared that nobody else should touch it; and this gave Peggotty such
+delight that she went away in good spirits.
+
+I fatigued myself as much as I possibly could in the Commons all day, by
+a variety of devices, and at the appointed time in the evening repaired
+to Mr. Mills's street. Mr. Mills, who was a terrible fellow to fall
+asleep after dinner, had not yet gone out, and there was no bird-cage in
+the middle window.
+
+He kept me waiting so long, that I fervently hoped the Club would fine
+him for being late. At last he came out; and then I saw my own Dora hang
+up the bird-cage, and peep into the balcony to look for me, and run
+in again when she saw I was there, while Jip remained behind, to bark
+injuriously at an immense butcher's dog in the street, who could have
+taken him like a pill.
+
+Dora came to the drawing-room door to meet me; and Jip came scrambling
+out, tumbling over his own growls, under the impression that I was a
+Bandit; and we all three went in, as happy and loving as could be. I
+soon carried desolation into the bosom of our joys--not that I meant to
+do it, but that I was so full of the subject--by asking Dora, without
+the smallest preparation, if she could love a beggar?
+
+My pretty, little, startled Dora! Her only association with the word was
+a yellow face and a nightcap, or a pair of crutches, or a wooden leg, or
+a dog with a decanter-stand in his mouth, or something of that kind; and
+she stared at me with the most delightful wonder.
+
+'How can you ask me anything so foolish?' pouted Dora. 'Love a beggar!'
+
+'Dora, my own dearest!' said I. 'I am a beggar!'
+
+'How can you be such a silly thing,' replied Dora, slapping my hand, 'as
+to sit there, telling such stories? I'll make Jip bite you!'
+
+Her childish way was the most delicious way in the world to me, but it
+was necessary to be explicit, and I solemnly repeated:
+
+'Dora, my own life, I am your ruined David!'
+
+'I declare I'll make Jip bite you!' said Dora, shaking her curls, 'if
+you are so ridiculous.'
+
+But I looked so serious, that Dora left off shaking her curls, and laid
+her trembling little hand upon my shoulder, and first looked scared
+and anxious, then began to cry. That was dreadful. I fell upon my knees
+before the sofa, caressing her, and imploring her not to rend my heart;
+but, for some time, poor little Dora did nothing but exclaim Oh dear! Oh
+dear! And oh, she was so frightened! And where was Julia Mills! And oh,
+take her to Julia Mills, and go away, please! until I was almost beside
+myself.
+
+At last, after an agony of supplication and protestation, I got Dora
+to look at me, with a horrified expression of face, which I gradually
+soothed until it was only loving, and her soft, pretty cheek was lying
+against mine. Then I told her, with my arms clasped round her, how I
+loved her, so dearly, and so dearly; how I felt it right to offer to
+release her from her engagement, because now I was poor; how I never
+could bear it, or recover it, if I lost her; how I had no fears of
+poverty, if she had none, my arm being nerved and my heart inspired by
+her; how I was already working with a courage such as none but lovers
+knew; how I had begun to be practical, and look into the future; how a
+crust well earned was sweeter far than a feast inherited; and much
+more to the same purpose, which I delivered in a burst of passionate
+eloquence quite surprising to myself, though I had been thinking about
+it, day and night, ever since my aunt had astonished me.
+
+'Is your heart mine still, dear Dora?' said I, rapturously, for I knew
+by her clinging to me that it was.
+
+'Oh, yes!' cried Dora. 'Oh, yes, it's all yours. Oh, don't be dreadful!'
+
+I dreadful! To Dora!
+
+'Don't talk about being poor, and working hard!' said Dora, nestling
+closer to me. 'Oh, don't, don't!'
+
+'My dearest love,' said I, 'the crust well-earned--'
+
+'Oh, yes; but I don't want to hear any more about crusts!' said Dora.
+'And Jip must have a mutton-chop every day at twelve, or he'll die.'
+
+I was charmed with her childish, winning way. I fondly explained to Dora
+that Jip should have his mutton-chop with his accustomed regularity.
+I drew a picture of our frugal home, made independent by my
+labour--sketching in the little house I had seen at Highgate, and my
+aunt in her room upstairs.
+
+'I am not dreadful now, Dora?' said I, tenderly.
+
+'Oh, no, no!' cried Dora. 'But I hope your aunt will keep in her own
+room a good deal. And I hope she's not a scolding old thing!'
+
+If it were possible for me to love Dora more than ever, I am sure I did.
+But I felt she was a little impracticable. It damped my new-born ardour,
+to find that ardour so difficult of communication to her. I made another
+trial. When she was quite herself again, and was curling Jip's ears, as
+he lay upon her lap, I became grave, and said:
+
+'My own! May I mention something?'
+
+'Oh, please don't be practical!' said Dora, coaxingly. 'Because it
+frightens me so!'
+
+'Sweetheart!' I returned; 'there is nothing to alarm you in all this. I
+want you to think of it quite differently. I want to make it nerve you,
+and inspire you, Dora!'
+
+'Oh, but that's so shocking!' cried Dora.
+
+'My love, no. Perseverance and strength of character will enable us to
+bear much worse things.' 'But I haven't got any strength at all,'
+said Dora, shaking her curls. 'Have I, Jip? Oh, do kiss Jip, and be
+agreeable!'
+
+It was impossible to resist kissing Jip, when she held him up to me for
+that purpose, putting her own bright, rosy little mouth into kissing
+form, as she directed the operation, which she insisted should be
+performed symmetrically, on the centre of his nose. I did as she bade
+me--rewarding myself afterwards for my obedience--and she charmed me out
+of my graver character for I don't know how long.
+
+'But, Dora, my beloved!' said I, at last resuming it; 'I was going to
+mention something.'
+
+The judge of the Prerogative Court might have fallen in love with her,
+to see her fold her little hands and hold them up, begging and praying
+me not to be dreadful any more.
+
+'Indeed I am not going to be, my darling!' I assured her. 'But, Dora, my
+love, if you will sometimes think,--not despondingly, you know; far from
+that!--but if you will sometimes think--just to encourage yourself--that
+you are engaged to a poor man--'
+
+'Don't, don't! Pray don't!' cried Dora. 'It's so very dreadful!'
+
+'My soul, not at all!' said I, cheerfully. 'If you will sometimes think
+of that, and look about now and then at your papa's housekeeping, and
+endeavour to acquire a little habit--of accounts, for instance--'
+
+Poor little Dora received this suggestion with something that was half a
+sob and half a scream.
+
+'--It would be so useful to us afterwards,' I went on. 'And if you would
+promise me to read a little--a little Cookery Book that I would send
+you, it would be so excellent for both of us. For our path in life, my
+Dora,' said I, warming with the subject, 'is stony and rugged now, and
+it rests with us to smooth it. We must fight our way onward. We must be
+brave. There are obstacles to be met, and we must meet, and crush them!'
+
+I was going on at a great rate, with a clenched hand, and a most
+enthusiastic countenance; but it was quite unnecessary to proceed. I had
+said enough. I had done it again. Oh, she was so frightened! Oh, where
+was Julia Mills! Oh, take her to Julia Mills, and go away, please!
+So that, in short, I was quite distracted, and raved about the
+drawing-room.
+
+I thought I had killed her, this time. I sprinkled water on her face.
+I went down on my knees. I plucked at my hair. I denounced myself as a
+remorseless brute and a ruthless beast. I implored her forgiveness.
+I besought her to look up. I ravaged Miss Mills's work-box for a
+smelling-bottle, and in my agony of mind applied an ivory needle-case
+instead, and dropped all the needles over Dora. I shook my fists at Jip,
+who was as frantic as myself. I did every wild extravagance that could
+be done, and was a long way beyond the end of my wits when Miss Mills
+came into the room.
+
+'Who has done this?' exclaimed Miss Mills, succouring her friend.
+
+I replied, 'I, Miss Mills! I have done it! Behold the destroyer!'--or
+words to that effect--and hid my face from the light, in the sofa
+cushion.
+
+At first Miss Mills thought it was a quarrel, and that we were verging
+on the Desert of Sahara; but she soon found out how matters stood, for
+my dear affectionate little Dora, embracing her, began exclaiming that I
+was 'a poor labourer'; and then cried for me, and embraced me, and asked
+me would I let her give me all her money to keep, and then fell on Miss
+Mills's neck, sobbing as if her tender heart were broken.
+
+Miss Mills must have been born to be a blessing to us. She ascertained
+from me in a few words what it was all about, comforted Dora, and
+gradually convinced her that I was not a labourer--from my manner of
+stating the case I believe Dora concluded that I was a navigator,
+and went balancing myself up and down a plank all day with a
+wheelbarrow--and so brought us together in peace. When we were quite
+composed, and Dora had gone up-stairs to put some rose-water to her
+eyes, Miss Mills rang for tea. In the ensuing interval, I told Miss
+Mills that she was evermore my friend, and that my heart must cease to
+vibrate ere I could forget her sympathy.
+
+I then expounded to Miss Mills what I had endeavoured, so very
+unsuccessfully, to expound to Dora. Miss Mills replied, on general
+principles, that the Cottage of content was better than the Palace of
+cold splendour, and that where love was, all was.
+
+I said to Miss Mills that this was very true, and who should know
+it better than I, who loved Dora with a love that never mortal had
+experienced yet? But on Miss Mills observing, with despondency, that
+it were well indeed for some hearts if this were so, I explained that
+I begged leave to restrict the observation to mortals of the masculine
+gender.
+
+I then put it to Miss Mills, to say whether she considered that there
+was or was not any practical merit in the suggestion I had been anxious
+to make, concerning the accounts, the housekeeping, and the Cookery
+Book?
+
+Miss Mills, after some consideration, thus replied:
+
+'Mr. Copperfield, I will be plain with you. Mental suffering and trial
+supply, in some natures, the place of years, and I will be as plain with
+you as if I were a Lady Abbess. No. The suggestion is not appropriate
+to our Dora. Our dearest Dora is a favourite child of nature. She is a
+thing of light, and airiness, and joy. I am free to confess that if it
+could be done, it might be well, but--' And Miss Mills shook her head.
+
+I was encouraged by this closing admission on the part of Miss Mills to
+ask her, whether, for Dora's sake, if she had any opportunity of luring
+her attention to such preparations for an earnest life, she would avail
+herself of it? Miss Mills replied in the affirmative so readily, that I
+further asked her if she would take charge of the Cookery Book; and, if
+she ever could insinuate it upon Dora's acceptance, without frightening
+her, undertake to do me that crowning service. Miss Mills accepted this
+trust, too; but was not sanguine.
+
+And Dora returned, looking such a lovely little creature, that I really
+doubted whether she ought to be troubled with anything so ordinary. And
+she loved me so much, and was so captivating (particularly when she made
+Jip stand on his hind legs for toast, and when she pretended to hold
+that nose of his against the hot teapot for punishment because he
+wouldn't), that I felt like a sort of Monster who had got into a Fairy's
+bower, when I thought of having frightened her, and made her cry.
+
+After tea we had the guitar; and Dora sang those same dear old French
+songs about the impossibility of ever on any account leaving off
+dancing, La ra la, La ra la, until I felt a much greater Monster than
+before.
+
+We had only one check to our pleasure, and that happened a little while
+before I took my leave, when, Miss Mills chancing to make some allusion
+to tomorrow morning, I unluckily let out that, being obliged to exert
+myself now, I got up at five o'clock. Whether Dora had any idea that
+I was a Private Watchman, I am unable to say; but it made a great
+impression on her, and she neither played nor sang any more.
+
+It was still on her mind when I bade her adieu; and she said to me, in
+her pretty coaxing way--as if I were a doll, I used to think:
+
+'Now don't get up at five o'clock, you naughty boy. It's so
+nonsensical!'
+
+'My love,' said I, 'I have work to do.'
+
+'But don't do it!' returned Dora. 'Why should you?'
+
+It was impossible to say to that sweet little surprised face, otherwise
+than lightly and playfully, that we must work to live.
+
+'Oh! How ridiculous!' cried Dora.
+
+'How shall we live without, Dora?' said I.
+
+'How? Any how!' said Dora.
+
+She seemed to think she had quite settled the question, and gave me such
+a triumphant little kiss, direct from her innocent heart, that I would
+hardly have put her out of conceit with her answer, for a fortune.
+
+Well! I loved her, and I went on loving her, most absorbingly, entirely,
+and completely. But going on, too, working pretty hard, and busily
+keeping red-hot all the irons I now had in the fire, I would sit
+sometimes of a night, opposite my aunt, thinking how I had frightened
+Dora that time, and how I could best make my way with a guitar-case
+through the forest of difficulty, until I used to fancy that my head was
+turning quite grey.
+
+
+
+CHAPTER 38. A DISSOLUTION OF PARTNERSHIP
+
+
+I did not allow my resolution, with respect to the Parliamentary
+Debates, to cool. It was one of the irons I began to heat immediately,
+and one of the irons I kept hot, and hammered at, with a perseverance
+I may honestly admire. I bought an approved scheme of the noble art and
+mystery of stenography (which cost me ten and sixpence); and plunged
+into a sea of perplexity that brought me, in a few weeks, to the
+confines of distraction. The changes that were rung upon dots, which
+in such a position meant such a thing, and in such another position
+something else, entirely different; the wonderful vagaries that were
+played by circles; the unaccountable consequences that resulted from
+marks like flies' legs; the tremendous effects of a curve in a wrong
+place; not only troubled my waking hours, but reappeared before me in
+my sleep. When I had groped my way, blindly, through these difficulties,
+and had mastered the alphabet, which was an Egyptian Temple in itself,
+there then appeared a procession of new horrors, called arbitrary
+characters; the most despotic characters I have ever known; who
+insisted, for instance, that a thing like the beginning of a cobweb,
+meant expectation, and that a pen-and-ink sky-rocket, stood for
+disadvantageous. When I had fixed these wretches in my mind, I found
+that they had driven everything else out of it; then, beginning again, I
+forgot them; while I was picking them up, I dropped the other fragments
+of the system; in short, it was almost heart-breaking.
+
+It might have been quite heart-breaking, but for Dora, who was the stay
+and anchor of my tempest-driven bark. Every scratch in the scheme was
+a gnarled oak in the forest of difficulty, and I went on cutting them
+down, one after another, with such vigour, that in three or four months
+I was in a condition to make an experiment on one of our crack speakers
+in the Commons. Shall I ever forget how the crack speaker walked off
+from me before I began, and left my imbecile pencil staggering about the
+paper as if it were in a fit!
+
+This would not do, it was quite clear. I was flying too high, and should
+never get on, so. I resorted to Traddles for advice; who suggested
+that he should dictate speeches to me, at a pace, and with occasional
+stoppages, adapted to my weakness. Very grateful for this friendly aid,
+I accepted the proposal; and night after night, almost every night, for
+a long time, we had a sort of Private Parliament in Buckingham Street,
+after I came home from the Doctor's.
+
+I should like to see such a Parliament anywhere else! My aunt and Mr.
+Dick represented the Government or the Opposition (as the case might
+be), and Traddles, with the assistance of Enfield's Speakers, or a
+volume of parliamentary orations, thundered astonishing invectives
+against them. Standing by the table, with his finger in the page to keep
+the place, and his right arm flourishing above his head, Traddles, as
+Mr. Pitt, Mr. Fox, Mr. Sheridan, Mr. Burke, Lord Castlereagh, Viscount
+Sidmouth, or Mr. Canning, would work himself into the most violent
+heats, and deliver the most withering denunciations of the profligacy
+and corruption of my aunt and Mr. Dick; while I used to sit, at a little
+distance, with my notebook on my knee, fagging after him with all my
+might and main. The inconsistency and recklessness of Traddles were not
+to be exceeded by any real politician. He was for any description of
+policy, in the compass of a week; and nailed all sorts of colours to
+every denomination of mast. My aunt, looking very like an immovable
+Chancellor of the Exchequer, would occasionally throw in an interruption
+or two, as 'Hear!' or 'No!' or 'Oh!' when the text seemed to require it:
+which was always a signal to Mr. Dick (a perfect country gentleman)
+to follow lustily with the same cry. But Mr. Dick got taxed with
+such things in the course of his Parliamentary career, and was made
+responsible for such awful consequences, that he became uncomfortable in
+his mind sometimes. I believe he actually began to be afraid he really
+had been doing something, tending to the annihilation of the British
+constitution, and the ruin of the country.
+
+Often and often we pursued these debates until the clock pointed to
+midnight, and the candles were burning down. The result of so much good
+practice was, that by and by I began to keep pace with Traddles pretty
+well, and should have been quite triumphant if I had had the least idea
+what my notes were about. But, as to reading them after I had got them,
+I might as well have copied the Chinese inscriptions of an immense
+collection of tea-chests, or the golden characters on all the great red
+and green bottles in the chemists' shops!
+
+There was nothing for it, but to turn back and begin all over again. It
+was very hard, but I turned back, though with a heavy heart, and began
+laboriously and methodically to plod over the same tedious ground at a
+snail's pace; stopping to examine minutely every speck in the way, on
+all sides, and making the most desperate efforts to know these elusive
+characters by sight wherever I met them. I was always punctual at
+the office; at the Doctor's too: and I really did work, as the common
+expression is, like a cart-horse. One day, when I went to the Commons as
+usual, I found Mr. Spenlow in the doorway looking extremely grave, and
+talking to himself. As he was in the habit of complaining of pains in
+his head--he had naturally a short throat, and I do seriously believe
+he over-starched himself--I was at first alarmed by the idea that he was
+not quite right in that direction; but he soon relieved my uneasiness.
+
+Instead of returning my 'Good morning' with his usual affability, he
+looked at me in a distant, ceremonious manner, and coldly requested me
+to accompany him to a certain coffee-house, which, in those days, had
+a door opening into the Commons, just within the little archway in St.
+Paul's Churchyard. I complied, in a very uncomfortable state, and with a
+warm shooting all over me, as if my apprehensions were breaking out into
+buds. When I allowed him to go on a little before, on account of the
+narrowness of the way, I observed that he carried his head with a lofty
+air that was particularly unpromising; and my mind misgave me that he
+had found out about my darling Dora.
+
+If I had not guessed this, on the way to the coffee-house, I could
+hardly have failed to know what was the matter when I followed him
+into an upstairs room, and found Miss Murdstone there, supported by
+a background of sideboard, on which were several inverted tumblers
+sustaining lemons, and two of those extraordinary boxes, all corners and
+flutings, for sticking knives and forks in, which, happily for mankind,
+are now obsolete.
+
+Miss Murdstone gave me her chilly finger-nails, and sat severely rigid.
+Mr. Spenlow shut the door, motioned me to a chair, and stood on the
+hearth-rug in front of the fireplace.
+
+'Have the goodness to show Mr. Copperfield,' said Mr. Spenlow, what you
+have in your reticule, Miss Murdstone.'
+
+I believe it was the old identical steel-clasped reticule of my
+childhood, that shut up like a bite. Compressing her lips, in sympathy
+with the snap, Miss Murdstone opened it--opening her mouth a little
+at the same time--and produced my last letter to Dora, teeming with
+expressions of devoted affection.
+
+'I believe that is your writing, Mr. Copperfield?' said Mr. Spenlow.
+
+I was very hot, and the voice I heard was very unlike mine, when I said,
+'It is, sir!'
+
+'If I am not mistaken,' said Mr. Spenlow, as Miss Murdstone brought a
+parcel of letters out of her reticule, tied round with the dearest bit
+of blue ribbon, 'those are also from your pen, Mr. Copperfield?'
+
+I took them from her with a most desolate sensation; and, glancing at
+such phrases at the top, as 'My ever dearest and own Dora,' 'My best
+beloved angel,' 'My blessed one for ever,' and the like, blushed deeply,
+and inclined my head.
+
+'No, thank you!' said Mr. Spenlow, coldly, as I mechanically offered
+them back to him. 'I will not deprive you of them. Miss Murdstone, be so
+good as to proceed!'
+
+That gentle creature, after a moment's thoughtful survey of the carpet,
+delivered herself with much dry unction as follows.
+
+'I must confess to having entertained my suspicions of Miss Spenlow, in
+reference to David Copperfield, for some time. I observed Miss Spenlow
+and David Copperfield, when they first met; and the impression made upon
+me then was not agreeable. The depravity of the human heart is such--'
+
+'You will oblige me, ma'am,' interrupted Mr. Spenlow, 'by confining
+yourself to facts.'
+
+Miss Murdstone cast down her eyes, shook her head as if protesting
+against this unseemly interruption, and with frowning dignity resumed:
+
+'Since I am to confine myself to facts, I will state them as dryly as I
+can. Perhaps that will be considered an acceptable course of proceeding.
+I have already said, sir, that I have had my suspicions of Miss Spenlow,
+in reference to David Copperfield, for some time. I have frequently
+endeavoured to find decisive corroboration of those suspicions, but
+without effect. I have therefore forborne to mention them to Miss
+Spenlow's father'; looking severely at him--'knowing how little
+disposition there usually is in such cases, to acknowledge the
+conscientious discharge of duty.'
+
+Mr. Spenlow seemed quite cowed by the gentlemanly sternness of Miss
+Murdstone's manner, and deprecated her severity with a conciliatory
+little wave of his hand.
+
+'On my return to Norwood, after the period of absence occasioned by my
+brother's marriage,' pursued Miss Murdstone in a disdainful voice, 'and
+on the return of Miss Spenlow from her visit to her friend Miss Mills,
+I imagined that the manner of Miss Spenlow gave me greater occasion for
+suspicion than before. Therefore I watched Miss Spenlow closely.'
+
+Dear, tender little Dora, so unconscious of this Dragon's eye!
+
+'Still,' resumed Miss Murdstone, 'I found no proof until last night.
+It appeared to me that Miss Spenlow received too many letters from her
+friend Miss Mills; but Miss Mills being her friend with her father's
+full concurrence,' another telling blow at Mr. Spenlow, 'it was not
+for me to interfere. If I may not be permitted to allude to the natural
+depravity of the human heart, at least I may--I must--be permitted, so
+far to refer to misplaced confidence.'
+
+Mr. Spenlow apologetically murmured his assent.
+
+'Last evening after tea,' pursued Miss Murdstone, 'I observed the little
+dog starting, rolling, and growling about the drawing-room, worrying
+something. I said to Miss Spenlow, "Dora, what is that the dog has in
+his mouth? It's paper." Miss Spenlow immediately put her hand to her
+frock, gave a sudden cry, and ran to the dog. I interposed, and said,
+"Dora, my love, you must permit me."'
+
+Oh Jip, miserable Spaniel, this wretchedness, then, was your work!
+
+'Miss Spenlow endeavoured,' said Miss Murdstone, 'to bribe me with
+kisses, work-boxes, and small articles of jewellery--that, of course,
+I pass over. The little dog retreated under the sofa on my approaching
+him, and was with great difficulty dislodged by the fire-irons. Even
+when dislodged, he still kept the letter in his mouth; and on my
+endeavouring to take it from him, at the imminent risk of being bitten,
+he kept it between his teeth so pertinaciously as to suffer himself
+to be held suspended in the air by means of the document. At length I
+obtained possession of it. After perusing it, I taxed Miss Spenlow with
+having many such letters in her possession; and ultimately obtained from
+her the packet which is now in David Copperfield's hand.'
+
+Here she ceased; and snapping her reticule again, and shutting her
+mouth, looked as if she might be broken, but could never be bent.
+
+'You have heard Miss Murdstone,' said Mr. Spenlow, turning to me. 'I beg
+to ask, Mr. Copperfield, if you have anything to say in reply?'
+
+The picture I had before me, of the beautiful little treasure of my
+heart, sobbing and crying all night--of her being alone, frightened,
+and wretched, then--of her having so piteously begged and prayed that
+stony-hearted woman to forgive her--of her having vainly offered her
+those kisses, work-boxes, and trinkets--of her being in such grievous
+distress, and all for me--very much impaired the little dignity I had
+been able to muster. I am afraid I was in a tremulous state for a minute
+or so, though I did my best to disguise it.
+
+'There is nothing I can say, sir,' I returned, 'except that all the
+blame is mine. Dora--'
+
+'Miss Spenlow, if you please,' said her father, majestically.
+
+'--was induced and persuaded by me,' I went on, swallowing that colder
+designation, 'to consent to this concealment, and I bitterly regret it.'
+
+'You are very much to blame, sir,' said Mr. Spenlow, walking to and fro
+upon the hearth-rug, and emphasizing what he said with his whole body
+instead of his head, on account of the stiffness of his cravat and
+spine. 'You have done a stealthy and unbecoming action, Mr. Copperfield.
+When I take a gentleman to my house, no matter whether he is nineteen,
+twenty-nine, or ninety, I take him there in a spirit of confidence.
+If he abuses my confidence, he commits a dishonourable action, Mr.
+Copperfield.'
+
+'I feel it, sir, I assure you,' I returned. 'But I never thought so,
+before. Sincerely, honestly, indeed, Mr. Spenlow, I never thought so,
+before. I love Miss Spenlow to that extent--'
+
+'Pooh! nonsense!' said Mr. Spenlow, reddening. 'Pray don't tell me to my
+face that you love my daughter, Mr. Copperfield!'
+
+'Could I defend my conduct if I did not, sir?' I returned, with all
+humility.
+
+'Can you defend your conduct if you do, sir?' said Mr. Spenlow, stopping
+short upon the hearth-rug. 'Have you considered your years, and my
+daughter's years, Mr. Copperfield? Have you considered what it is to
+undermine the confidence that should subsist between my daughter and
+myself? Have you considered my daughter's station in life, the projects
+I may contemplate for her advancement, the testamentary intentions I
+may have with reference to her? Have you considered anything, Mr.
+Copperfield?'
+
+'Very little, sir, I am afraid;' I answered, speaking to him as
+respectfully and sorrowfully as I felt; 'but pray believe me, I have
+considered my own worldly position. When I explained it to you, we were
+already engaged--'
+
+'I BEG,' said Mr. Spenlow, more like Punch than I had ever seen him,
+as he energetically struck one hand upon the other--I could not help
+noticing that even in my despair; 'that YOU Will NOT talk to me of
+engagements, Mr. Copperfield!'
+
+The otherwise immovable Miss Murdstone laughed contemptuously in one
+short syllable.
+
+'When I explained my altered position to you, sir,' I began again,
+substituting a new form of expression for what was so unpalatable to
+him, 'this concealment, into which I am so unhappy as to have led Miss
+Spenlow, had begun. Since I have been in that altered position, I have
+strained every nerve, I have exerted every energy, to improve it. I am
+sure I shall improve it in time. Will you grant me time--any length of
+time? We are both so young, sir,--'
+
+'You are right,' interrupted Mr. Spenlow, nodding his head a great
+many times, and frowning very much, 'you are both very young. It's all
+nonsense. Let there be an end of the nonsense. Take away those letters,
+and throw them in the fire. Give me Miss Spenlow's letters to throw in
+the fire; and although our future intercourse must, you are aware, be
+restricted to the Commons here, we will agree to make no further mention
+of the past. Come, Mr. Copperfield, you don't want sense; and this is
+the sensible course.'
+
+No. I couldn't think of agreeing to it. I was very sorry, but there
+was a higher consideration than sense. Love was above all earthly
+considerations, and I loved Dora to idolatry, and Dora loved me. I
+didn't exactly say so; I softened it down as much as I could; but I
+implied it, and I was resolute upon it. I don't think I made myself very
+ridiculous, but I know I was resolute.
+
+'Very well, Mr. Copperfield,' said Mr. Spenlow, 'I must try my influence
+with my daughter.'
+
+Miss Murdstone, by an expressive sound, a long drawn respiration, which
+was neither a sigh nor a moan, but was like both, gave it as her opinion
+that he should have done this at first.
+
+'I must try,' said Mr. Spenlow, confirmed by this support, 'my
+influence with my daughter. Do you decline to take those letters, Mr.
+Copperfield?' For I had laid them on the table.
+
+Yes. I told him I hoped he would not think it wrong, but I couldn't
+possibly take them from Miss Murdstone.
+
+'Nor from me?' said Mr. Spenlow.
+
+No, I replied with the profoundest respect; nor from him.
+
+'Very well!' said Mr. Spenlow.
+
+A silence succeeding, I was undecided whether to go or stay. At length
+I was moving quietly towards the door, with the intention of saying that
+perhaps I should consult his feelings best by withdrawing: when he said,
+with his hands in his coat pockets, into which it was as much as he
+could do to get them; and with what I should call, upon the whole, a
+decidedly pious air:
+
+'You are probably aware, Mr. Copperfield, that I am not altogether
+destitute of worldly possessions, and that my daughter is my nearest and
+dearest relative?'
+
+I hurriedly made him a reply to the effect, that I hoped the error into
+which I had been betrayed by the desperate nature of my love, did not
+induce him to think me mercenary too?
+
+'I don't allude to the matter in that light,' said Mr. Spenlow. 'It
+would be better for yourself, and all of us, if you WERE mercenary, Mr.
+Copperfield--I mean, if you were more discreet and less influenced by
+all this youthful nonsense. No. I merely say, with quite another view,
+you are probably aware I have some property to bequeath to my child?'
+
+I certainly supposed so.
+
+'And you can hardly think,' said Mr. Spenlow, 'having experience of what
+we see, in the Commons here, every day, of the various unaccountable
+and negligent proceedings of men, in respect of their testamentary
+arrangements--of all subjects, the one on which perhaps the strangest
+revelations of human inconsistency are to be met with--but that mine are
+made?'
+
+I inclined my head in acquiescence.
+
+'I should not allow,' said Mr. Spenlow, with an evident increase of
+pious sentiment, and slowly shaking his head as he poised himself upon
+his toes and heels alternately, 'my suitable provision for my child to
+be influenced by a piece of youthful folly like the present. It is mere
+folly. Mere nonsense. In a little while, it will weigh lighter than
+any feather. But I might--I might--if this silly business were not
+completely relinquished altogether, be induced in some anxious moment
+to guard her from, and surround her with protections against, the
+consequences of any foolish step in the way of marriage. Now, Mr.
+Copperfield, I hope that you will not render it necessary for me to
+open, even for a quarter of an hour, that closed page in the book of
+life, and unsettle, even for a quarter of an hour, grave affairs long
+since composed.'
+
+There was a serenity, a tranquillity, a calm sunset air about him, which
+quite affected me. He was so peaceful and resigned--clearly had his
+affairs in such perfect train, and so systematically wound up--that he
+was a man to feel touched in the contemplation of. I really think I saw
+tears rise to his eyes, from the depth of his own feeling of all this.
+
+But what could I do? I could not deny Dora and my own heart. When he
+told me I had better take a week to consider of what he had said, how
+could I say I wouldn't take a week, yet how could I fail to know that no
+amount of weeks could influence such love as mine?
+
+'In the meantime, confer with Miss Trotwood, or with any person with
+any knowledge of life,' said Mr. Spenlow, adjusting his cravat with both
+hands. 'Take a week, Mr. Copperfield.'
+
+I submitted; and, with a countenance as expressive as I was able to
+make it of dejected and despairing constancy, came out of the room. Miss
+Murdstone's heavy eyebrows followed me to the door--I say her eyebrows
+rather than her eyes, because they were much more important in her
+face--and she looked so exactly as she used to look, at about that
+hour of the morning, in our parlour at Blunderstone, that I could have
+fancied I had been breaking down in my lessons again, and that the
+dead weight on my mind was that horrible old spelling-book, with
+oval woodcuts, shaped, to my youthful fancy, like the glasses out of
+spectacles.
+
+When I got to the office, and, shutting out old Tiffey and the rest of
+them with my hands, sat at my desk, in my own particular nook, thinking
+of this earthquake that had taken place so unexpectedly, and in the
+bitterness of my spirit cursing Jip, I fell into such a state of torment
+about Dora, that I wonder I did not take up my hat and rush insanely to
+Norwood. The idea of their frightening her, and making her cry, and of
+my not being there to comfort her, was so excruciating, that it impelled
+me to write a wild letter to Mr. Spenlow, beseeching him not to visit
+upon her the consequences of my awful destiny. I implored him to spare
+her gentle nature--not to crush a fragile flower--and addressed him
+generally, to the best of my remembrance, as if, instead of being her
+father, he had been an Ogre, or the Dragon of Wantley.3 This letter I
+sealed and laid upon his desk before he returned; and when he came in,
+I saw him, through the half-opened door of his room, take it up and read
+it.
+
+He said nothing about it all the morning; but before he went away in the
+afternoon he called me in, and told me that I need not make myself at
+all uneasy about his daughter's happiness. He had assured her, he said,
+that it was all nonsense; and he had nothing more to say to her. He
+believed he was an indulgent father (as indeed he was), and I might
+spare myself any solicitude on her account.
+
+'You may make it necessary, if you are foolish or obstinate, Mr.
+Copperfield,' he observed, 'for me to send my daughter abroad again,
+for a term; but I have a better opinion of you. I hope you will be wiser
+than that, in a few days. As to Miss Murdstone,' for I had alluded to
+her in the letter, 'I respect that lady's vigilance, and feel obliged to
+her; but she has strict charge to avoid the subject. All I desire, Mr.
+Copperfield, is, that it should be forgotten. All you have got to do,
+Mr. Copperfield, is to forget it.'
+
+All! In the note I wrote to Miss Mills, I bitterly quoted this
+sentiment. All I had to do, I said, with gloomy sarcasm, was to forget
+Dora. That was all, and what was that! I entreated Miss Mills to see
+me, that evening. If it could not be done with Mr. Mills's sanction
+and concurrence, I besought a clandestine interview in the back kitchen
+where the Mangle was. I informed her that my reason was tottering on
+its throne, and only she, Miss Mills, could prevent its being deposed.
+I signed myself, hers distractedly; and I couldn't help feeling, while
+I read this composition over, before sending it by a porter, that it was
+something in the style of Mr. Micawber.
+
+However, I sent it. At night I repaired to Miss Mills's street, and
+walked up and down, until I was stealthily fetched in by Miss Mills's
+maid, and taken the area way to the back kitchen. I have since seen
+reason to believe that there was nothing on earth to prevent my going in
+at the front door, and being shown up into the drawing-room, except Miss
+Mills's love of the romantic and mysterious.
+
+In the back kitchen, I raved as became me. I went there, I suppose,
+to make a fool of myself, and I am quite sure I did it. Miss Mills had
+received a hasty note from Dora, telling her that all was discovered,
+and saying. 'Oh pray come to me, Julia, do, do!' But Miss Mills,
+mistrusting the acceptability of her presence to the higher powers, had
+not yet gone; and we were all benighted in the Desert of Sahara.
+
+Miss Mills had a wonderful flow of words, and liked to pour them out. I
+could not help feeling, though she mingled her tears with mine, that she
+had a dreadful luxury in our afflictions. She petted them, as I may say,
+and made the most of them. A deep gulf, she observed, had opened between
+Dora and me, and Love could only span it with its rainbow. Love must
+suffer in this stern world; it ever had been so, it ever would be so. No
+matter, Miss Mills remarked. Hearts confined by cobwebs would burst at
+last, and then Love was avenged.
+
+This was small consolation, but Miss Mills wouldn't encourage fallacious
+hopes. She made me much more wretched than I was before, and I felt (and
+told her with the deepest gratitude) that she was indeed a friend. We
+resolved that she should go to Dora the first thing in the morning,
+and find some means of assuring her, either by looks or words, of my
+devotion and misery. We parted, overwhelmed with grief; and I think Miss
+Mills enjoyed herself completely.
+
+I confided all to my aunt when I got home; and in spite of all she could
+say to me, went to bed despairing. I got up despairing, and went out
+despairing. It was Saturday morning, and I went straight to the Commons.
+
+I was surprised, when I came within sight of our office-door, to see the
+ticket-porters standing outside talking together, and some half-dozen
+stragglers gazing at the windows which were shut up. I quickened my
+pace, and, passing among them, wondering at their looks, went hurriedly
+in.
+
+The clerks were there, but nobody was doing anything. Old Tiffey, for
+the first time in his life I should think, was sitting on somebody
+else's stool, and had not hung up his hat.
+
+'This is a dreadful calamity, Mr. Copperfield,' said he, as I entered.
+
+'What is?' I exclaimed. 'What's the matter?'
+
+'Don't you know?' cried Tiffey, and all the rest of them, coming round
+me.
+
+'No!' said I, looking from face to face.
+
+'Mr. Spenlow,' said Tiffey.
+
+'What about him!'
+
+'Dead!' I thought it was the office reeling, and not I, as one of
+the clerks caught hold of me. They sat me down in a chair, untied my
+neck-cloth, and brought me some water. I have no idea whether this took
+any time.
+
+'Dead?' said I.
+
+'He dined in town yesterday, and drove down in the phaeton by himself,'
+said Tiffey, 'having sent his own groom home by the coach, as he
+sometimes did, you know--'
+
+'Well?'
+
+'The phaeton went home without him. The horses stopped at the
+stable-gate. The man went out with a lantern. Nobody in the carriage.'
+
+'Had they run away?'
+
+'They were not hot,' said Tiffey, putting on his glasses; 'no hotter, I
+understand, than they would have been, going down at the usual pace. The
+reins were broken, but they had been dragging on the ground. The house
+was roused up directly, and three of them went out along the road. They
+found him a mile off.'
+
+'More than a mile off, Mr. Tiffey,' interposed a junior.
+
+'Was it? I believe you are right,' said Tiffey,--'more than a mile
+off--not far from the church--lying partly on the roadside, and partly
+on the path, upon his face. Whether he fell out in a fit, or got out,
+feeling ill before the fit came on--or even whether he was quite dead
+then, though there is no doubt he was quite insensible--no one appears
+to know. If he breathed, certainly he never spoke. Medical assistance
+was got as soon as possible, but it was quite useless.'
+
+I cannot describe the state of mind into which I was thrown by this
+intelligence. The shock of such an event happening so suddenly, and
+happening to one with whom I had been in any respect at variance--the
+appalling vacancy in the room he had occupied so lately, where his chair
+and table seemed to wait for him, and his handwriting of yesterday was
+like a ghost--the in--definable impossibility of separating him from the
+place, and feeling, when the door opened, as if he might come in--the
+lazy hush and rest there was in the office, and the insatiable relish
+with which our people talked about it, and other people came in and
+out all day, and gorged themselves with the subject--this is easily
+intelligible to anyone. What I cannot describe is, how, in the innermost
+recesses of my own heart, I had a lurking jealousy even of Death. How
+I felt as if its might would push me from my ground in Dora's thoughts.
+How I was, in a grudging way I have no words for, envious of her grief.
+How it made me restless to think of her weeping to others, or being
+consoled by others. How I had a grasping, avaricious wish to shut out
+everybody from her but myself, and to be all in all to her, at that
+unseasonable time of all times.
+
+In the trouble of this state of mind--not exclusively my own, I hope,
+but known to others--I went down to Norwood that night; and finding from
+one of the servants, when I made my inquiries at the door, that Miss
+Mills was there, got my aunt to direct a letter to her, which I wrote.
+I deplored the untimely death of Mr. Spenlow, most sincerely, and shed
+tears in doing so. I entreated her to tell Dora, if Dora were in a
+state to hear it, that he had spoken to me with the utmost kindness and
+consideration; and had coupled nothing but tenderness, not a single or
+reproachful word, with her name. I know I did this selfishly, to have my
+name brought before her; but I tried to believe it was an act of justice
+to his memory. Perhaps I did believe it.
+
+My aunt received a few lines next day in reply; addressed, outside, to
+her; within, to me. Dora was overcome by grief; and when her friend had
+asked her should she send her love to me, had only cried, as she was
+always crying, 'Oh, dear papa! oh, poor papa!' But she had not said No,
+and that I made the most of.
+
+Mr. jorkins, who had been at Norwood since the occurrence, came to the
+office a few days afterwards. He and Tiffey were closeted together for
+some few moments, and then Tiffey looked out at the door and beckoned me
+in.
+
+'Oh!' said Mr. jorkins. 'Mr. Tiffey and myself, Mr. Copperfield, are
+about to examine the desks, the drawers, and other such repositories
+of the deceased, with the view of sealing up his private papers, and
+searching for a Will. There is no trace of any, elsewhere. It may be as
+well for you to assist us, if you please.'
+
+I had been in agony to obtain some knowledge of the circumstances
+in which my Dora would be placed--as, in whose guardianship, and so
+forth--and this was something towards it. We began the search at once;
+Mr. jorkins unlocking the drawers and desks, and we all taking out the
+papers. The office-papers we placed on one side, and the private papers
+(which were not numerous) on the other. We were very grave; and when we
+came to a stray seal, or pencil-case, or ring, or any little article of
+that kind which we associated personally with him, we spoke very low.
+
+We had sealed up several packets; and were still going on dustily and
+quietly, when Mr. jorkins said to us, applying exactly the same words to
+his late partner as his late partner had applied to him:
+
+'Mr. Spenlow was very difficult to move from the beaten track. You know
+what he was! I am disposed to think he had made no will.'
+
+'Oh, I know he had!' said I.
+
+They both stopped and looked at me. 'On the very day when I last saw
+him,' said I, 'he told me that he had, and that his affairs were long
+since settled.'
+
+Mr. jorkins and old Tiffey shook their heads with one accord.
+
+'That looks unpromising,' said Tiffey.
+
+'Very unpromising,' said Mr. jorkins.
+
+'Surely you don't doubt--' I began.
+
+'My good Mr. Copperfield!' said Tiffey, laying his hand upon my arm, and
+shutting up both his eyes as he shook his head: 'if you had been in the
+Commons as long as I have, you would know that there is no subject on
+which men are so inconsistent, and so little to be trusted.'
+
+'Why, bless my soul, he made that very remark!' I replied persistently.
+
+'I should call that almost final,' observed Tiffey. 'My opinion is--no
+will.'
+
+It appeared a wonderful thing to me, but it turned out that there was
+no will. He had never so much as thought of making one, so far as his
+papers afforded any evidence; for there was no kind of hint, sketch, or
+memorandum, of any testamentary intention whatever. What was scarcely
+less astonishing to me, was, that his affairs were in a most disordered
+state. It was extremely difficult, I heard, to make out what he owed, or
+what he had paid, or of what he died possessed. It was considered likely
+that for years he could have had no clear opinion on these subjects
+himself. By little and little it came out, that, in the competition on
+all points of appearance and gentility then running high in the Commons,
+he had spent more than his professional income, which was not a very
+large one, and had reduced his private means, if they ever had been
+great (which was exceedingly doubtful), to a very low ebb indeed. There
+was a sale of the furniture and lease, at Norwood; and Tiffey told me,
+little thinking how interested I was in the story, that, paying all the
+just debts of the deceased, and deducting his share of outstanding bad
+and doubtful debts due to the firm, he wouldn't give a thousand pounds
+for all the assets remaining.
+
+This was at the expiration of about six weeks. I had suffered tortures
+all the time; and thought I really must have laid violent hands upon
+myself, when Miss Mills still reported to me, that my broken-hearted
+little Dora would say nothing, when I was mentioned, but 'Oh, poor papa!
+Oh, dear papa!' Also, that she had no other relations than two aunts,
+maiden sisters of Mr. Spenlow, who lived at Putney, and who had not held
+any other than chance communication with their brother for many years.
+Not that they had ever quarrelled (Miss Mills informed me); but that
+having been, on the occasion of Dora's christening, invited to tea, when
+they considered themselves privileged to be invited to dinner, they
+had expressed their opinion in writing, that it was 'better for the
+happiness of all parties' that they should stay away. Since which they
+had gone their road, and their brother had gone his.
+
+These two ladies now emerged from their retirement, and proposed to
+take Dora to live at Putney. Dora, clinging to them both, and weeping,
+exclaimed, 'O yes, aunts! Please take Julia Mills and me and Jip to
+Putney!' So they went, very soon after the funeral.
+
+How I found time to haunt Putney, I am sure I don't know; but I
+contrived, by some means or other, to prowl about the neighbourhood
+pretty often. Miss Mills, for the more exact discharge of the duties of
+friendship, kept a journal; and she used to meet me sometimes, on the
+Common, and read it, or (if she had not time to do that) lend it to me.
+How I treasured up the entries, of which I subjoin a sample--!
+
+'Monday. My sweet D. still much depressed. Headache. Called attention to
+J. as being beautifully sleek. D. fondled J. Associations thus awakened,
+opened floodgates of sorrow. Rush of grief admitted. (Are tears the
+dewdrops of the heart? J. M.)
+
+'Tuesday. D. weak and nervous. Beautiful in pallor. (Do we not remark
+this in moon likewise? J. M.) D., J. M. and J. took airing in carriage.
+J. looking out of window, and barking violently at dustman, occasioned
+smile to overspread features of D. (Of such slight links is chain of
+life composed! J. M.)
+
+'Wednesday. D. comparatively cheerful. Sang to her, as congenial melody,
+"Evening Bells". Effect not soothing, but reverse. D. inexpressibly
+affected. Found sobbing afterwards, in own room. Quoted verses
+respecting self and young Gazelle. Ineffectually. Also referred to
+Patience on Monument. (Qy. Why on monument? J. M.)
+
+'Thursday. D. certainly improved. Better night. Slight tinge of damask
+revisiting cheek. Resolved to mention name of D. C. Introduced same,
+cautiously, in course of airing. D. immediately overcome. "Oh, dear,
+dear Julia! Oh, I have been a naughty and undutiful child!" Soothed
+and caressed. Drew ideal picture of D. C. on verge of tomb. D. again
+overcome. "Oh, what shall I do, what shall I do? Oh, take me somewhere!"
+Much alarmed. Fainting of D. and glass of water from public-house.
+(Poetical affinity. Chequered sign on door-post; chequered human life.
+Alas! J. M.)
+
+'Friday. Day of incident. Man appears in kitchen, with blue bag, "for
+lady's boots left out to heel". Cook replies, "No such orders." Man
+argues point. Cook withdraws to inquire, leaving man alone with J. On
+Cook's return, man still argues point, but ultimately goes. J. missing.
+D. distracted. Information sent to police. Man to be identified by
+broad nose, and legs like balustrades of bridge. Search made in
+every direction. No J. D. weeping bitterly, and inconsolable. Renewed
+reference to young Gazelle. Appropriate, but unavailing. Towards
+evening, strange boy calls. Brought into parlour. Broad nose, but no
+balustrades. Says he wants a pound, and knows a dog. Declines to explain
+further, though much pressed. Pound being produced by D. takes Cook
+to little house, where J. alone tied up to leg of table. Joy of D.
+who dances round J. while he eats his supper. Emboldened by this happy
+change, mention D. C. upstairs. D. weeps afresh, cries piteously, "Oh,
+don't, don't, don't! It is so wicked to think of anything but poor
+papa!"--embraces J. and sobs herself to sleep. (Must not D. C. confine
+himself to the broad pinions of Time? J. M.)'
+
+Miss Mills and her journal were my sole consolation at this period.
+To see her, who had seen Dora but a little while before--to trace the
+initial letter of Dora's name through her sympathetic pages--to be made
+more and more miserable by her--were my only comforts. I felt as if I
+had been living in a palace of cards, which had tumbled down, leaving
+only Miss Mills and me among the ruins; I felt as if some grim enchanter
+had drawn a magic circle round the innocent goddess of my heart, which
+nothing indeed but those same strong pinions, capable of carrying so
+many people over so much, would enable me to enter!
+
+
+
+CHAPTER 39. WICKFIELD AND HEEP
+
+
+My aunt, beginning, I imagine, to be made seriously uncomfortable by my
+prolonged dejection, made a pretence of being anxious that I should go
+to Dover, to see that all was working well at the cottage, which was
+let; and to conclude an agreement, with the same tenant, for a longer
+term of occupation. Janet was drafted into the service of Mrs. Strong,
+where I saw her every day. She had been undecided, on leaving Dover,
+whether or no to give the finishing touch to that renunciation of
+mankind in which she had been educated, by marrying a pilot; but she
+decided against that venture. Not so much for the sake of principle, I
+believe, as because she happened not to like him.
+
+Although it required an effort to leave Miss Mills, I fell rather
+willingly into my aunt's pretence, as a means of enabling me to pass a
+few tranquil hours with Agnes. I consulted the good Doctor relative
+to an absence of three days; and the Doctor wishing me to take that
+relaxation,--he wished me to take more; but my energy could not bear
+that,--I made up my mind to go.
+
+As to the Commons, I had no great occasion to be particular about my
+duties in that quarter. To say the truth, we were getting in no very
+good odour among the tip-top proctors, and were rapidly sliding down
+to but a doubtful position. The business had been indifferent under Mr.
+jorkins, before Mr. Spenlow's time; and although it had been quickened
+by the infusion of new blood, and by the display which Mr. Spenlow made,
+still it was not established on a sufficiently strong basis to bear,
+without being shaken, such a blow as the sudden loss of its active
+manager. It fell off very much. Mr. jorkins, notwithstanding his
+reputation in the firm, was an easy-going, incapable sort of man, whose
+reputation out of doors was not calculated to back it up. I was turned
+over to him now, and when I saw him take his snuff and let the business
+go, I regretted my aunt's thousand pounds more than ever.
+
+But this was not the worst of it. There were a number of hangers-on and
+outsiders about the Commons, who, without being proctors themselves,
+dabbled in common-form business, and got it done by real proctors, who
+lent their names in consideration of a share in the spoil;--and there
+were a good many of these too. As our house now wanted business on any
+terms, we joined this noble band; and threw out lures to the hangers-on
+and outsiders, to bring their business to us. Marriage licences and
+small probates were what we all looked for, and what paid us best;
+and the competition for these ran very high indeed. Kidnappers and
+inveiglers were planted in all the avenues of entrance to the Commons,
+with instructions to do their utmost to cut off all persons in mourning,
+and all gentlemen with anything bashful in their appearance, and entice
+them to the offices in which their respective employers were interested;
+which instructions were so well observed, that I myself, before I was
+known by sight, was twice hustled into the premises of our principal
+opponent. The conflicting interests of these touting gentlemen being of
+a nature to irritate their feelings, personal collisions took place;
+and the Commons was even scandalized by our principal inveigler (who
+had formerly been in the wine trade, and afterwards in the sworn brokery
+line) walking about for some days with a black eye. Any one of these
+scouts used to think nothing of politely assisting an old lady in
+black out of a vehicle, killing any proctor whom she inquired for,
+representing his employer as the lawful successor and representative of
+that proctor, and bearing the old lady off (sometimes greatly affected)
+to his employer's office. Many captives were brought to me in this way.
+As to marriage licences, the competition rose to such a pitch, that a
+shy gentleman in want of one, had nothing to do but submit himself
+to the first inveigler, or be fought for, and become the prey of the
+strongest. One of our clerks, who was an outsider, used, in the height
+of this contest, to sit with his hat on, that he might be ready to rush
+out and swear before a surrogate any victim who was brought in. The
+system of inveigling continues, I believe, to this day. The last time I
+was in the Commons, a civil able-bodied person in a white apron pounced
+out upon me from a doorway, and whispering the word 'Marriage-licence'
+in my ear, was with great difficulty prevented from taking me up in
+his arms and lifting me into a proctor's. From this digression, let me
+proceed to Dover.
+
+I found everything in a satisfactory state at the cottage; and was
+enabled to gratify my aunt exceedingly by reporting that the tenant
+inherited her feud, and waged incessant war against donkeys. Having
+settled the little business I had to transact there, and slept there one
+night, I walked on to Canterbury early in the morning. It was now
+winter again; and the fresh, cold windy day, and the sweeping downland,
+brightened up my hopes a little.
+
+Coming into Canterbury, I loitered through the old streets with a sober
+pleasure that calmed my spirits, and eased my heart. There were the old
+signs, the old names over the shops, the old people serving in them. It
+appeared so long, since I had been a schoolboy there, that I wondered
+the place was so little changed, until I reflected how little I
+was changed myself. Strange to say, that quiet influence which was
+inseparable in my mind from Agnes, seemed to pervade even the city where
+she dwelt. The venerable cathedral towers, and the old jackdaws and
+rooks whose airy voices made them more retired than perfect silence
+would have done; the battered gateways, one stuck full with statues,
+long thrown down, and crumbled away, like the reverential pilgrims
+who had gazed upon them; the still nooks, where the ivied growth of
+centuries crept over gabled ends and ruined walls; the ancient houses,
+the pastoral landscape of field, orchard, and garden; everywhere--on
+everything--I felt the same serener air, the same calm, thoughtful,
+softening spirit.
+
+Arrived at Mr. Wickfield's house, I found, in the little lower room on
+the ground floor, where Uriah Heep had been of old accustomed to sit,
+Mr. Micawber plying his pen with great assiduity. He was dressed in a
+legal-looking suit of black, and loomed, burly and large, in that small
+office.
+
+Mr. Micawber was extremely glad to see me, but a little confused too.
+He would have conducted me immediately into the presence of Uriah, but I
+declined.
+
+'I know the house of old, you recollect,' said I, 'and will find my way
+upstairs. How do you like the law, Mr. Micawber?'
+
+'My dear Copperfield,' he replied. 'To a man possessed of the higher
+imaginative powers, the objection to legal studies is the amount of
+detail which they involve. Even in our professional correspondence,'
+said Mr. Micawber, glancing at some letters he was writing, 'the mind is
+not at liberty to soar to any exalted form of expression. Still, it is a
+great pursuit. A great pursuit!'
+
+He then told me that he had become the tenant of Uriah Heep's old house;
+and that Mrs. Micawber would be delighted to receive me, once more,
+under her own roof.
+
+'It is humble,' said Mr. Micawber, '--to quote a favourite expression
+of my friend Heep; but it may prove the stepping-stone to more ambitious
+domiciliary accommodation.'
+
+I asked him whether he had reason, so far, to be satisfied with his
+friend Heep's treatment of him? He got up to ascertain if the door were
+close shut, before he replied, in a lower voice:
+
+'My dear Copperfield, a man who labours under the pressure of pecuniary
+embarrassments, is, with the generality of people, at a disadvantage.
+That disadvantage is not diminished, when that pressure necessitates the
+drawing of stipendiary emoluments, before those emoluments are strictly
+due and payable. All I can say is, that my friend Heep has responded
+to appeals to which I need not more particularly refer, in a manner
+calculated to redound equally to the honour of his head, and of his
+heart.'
+
+'I should not have supposed him to be very free with his money either,'
+I observed.
+
+'Pardon me!' said Mr. Micawber, with an air of constraint, 'I speak of
+my friend Heep as I have experience.'
+
+'I am glad your experience is so favourable,' I returned.
+
+'You are very obliging, my dear Copperfield,' said Mr. Micawber; and
+hummed a tune.
+
+'Do you see much of Mr. Wickfield?' I asked, to change the subject.
+
+'Not much,' said Mr. Micawber, slightingly. 'Mr. Wickfield is, I dare
+say, a man of very excellent intentions; but he is--in short, he is
+obsolete.'
+
+'I am afraid his partner seeks to make him so,' said I.
+
+'My dear Copperfield!' returned Mr. Micawber, after some uneasy
+evolutions on his stool, 'allow me to offer a remark! I am here, in
+a capacity of confidence. I am here, in a position of trust. The
+discussion of some topics, even with Mrs. Micawber herself (so long the
+partner of my various vicissitudes, and a woman of a remarkable lucidity
+of intellect), is, I am led to consider, incompatible with the functions
+now devolving on me. I would therefore take the liberty of suggesting
+that in our friendly intercourse--which I trust will never be
+disturbed!--we draw a line. On one side of this line,' said Mr.
+Micawber, representing it on the desk with the office ruler, 'is the
+whole range of the human intellect, with a trifling exception; on
+the other, IS that exception; that is to say, the affairs of Messrs
+Wickfield and Heep, with all belonging and appertaining thereunto. I
+trust I give no offence to the companion of my youth, in submitting this
+proposition to his cooler judgement?'
+
+Though I saw an uneasy change in Mr. Micawber, which sat tightly on
+him, as if his new duties were a misfit, I felt I had no right to be
+offended. My telling him so, appeared to relieve him; and he shook hands
+with me.
+
+'I am charmed, Copperfield,' said Mr. Micawber, 'let me assure you, with
+Miss Wickfield. She is a very superior young lady, of very remarkable
+attractions, graces, and virtues. Upon my honour,' said Mr. Micawber,
+indefinitely kissing his hand and bowing with his genteelest air, 'I do
+Homage to Miss Wickfield! Hem!' 'I am glad of that, at least,' said I.
+
+'If you had not assured us, my dear Copperfield, on the occasion of that
+agreeable afternoon we had the happiness of passing with you, that D.
+was your favourite letter,' said Mr. Micawber, 'I should unquestionably
+have supposed that A. had been so.'
+
+We have all some experience of a feeling, that comes over us
+occasionally, of what we are saying and doing having been said and done
+before, in a remote time--of our having been surrounded, dim ages ago,
+by the same faces, objects, and circumstances--of our knowing perfectly
+what will be said next, as if we suddenly remembered it! I never had
+this mysterious impression more strongly in my life, than before he
+uttered those words.
+
+I took my leave of Mr. Micawber, for the time, charging him with my best
+remembrances to all at home. As I left him, resuming his stool and his
+pen, and rolling his head in his stock, to get it into easier writing
+order, I clearly perceived that there was something interposed between
+him and me, since he had come into his new functions, which prevented
+our getting at each other as we used to do, and quite altered the
+character of our intercourse.
+
+There was no one in the quaint old drawing-room, though it presented
+tokens of Mrs. Heep's whereabouts. I looked into the room still
+belonging to Agnes, and saw her sitting by the fire, at a pretty
+old-fashioned desk she had, writing.
+
+My darkening the light made her look up. What a pleasure to be the cause
+of that bright change in her attentive face, and the object of that
+sweet regard and welcome!
+
+'Ah, Agnes!' said I, when we were sitting together, side by side; 'I
+have missed you so much, lately!'
+
+'Indeed?' she replied. 'Again! And so soon?'
+
+I shook my head.
+
+'I don't know how it is, Agnes; I seem to want some faculty of mind that
+I ought to have. You were so much in the habit of thinking for me, in
+the happy old days here, and I came so naturally to you for counsel and
+support, that I really think I have missed acquiring it.'
+
+'And what is it?' said Agnes, cheerfully.
+
+'I don't know what to call it,' I replied. 'I think I am earnest and
+persevering?'
+
+'I am sure of it,' said Agnes.
+
+'And patient, Agnes?' I inquired, with a little hesitation.
+
+'Yes,' returned Agnes, laughing. 'Pretty well.'
+
+'And yet,' said I, 'I get so miserable and worried, and am so unsteady
+and irresolute in my power of assuring myself, that I know I must
+want--shall I call it--reliance, of some kind?'
+
+'Call it so, if you will,' said Agnes.
+
+'Well!' I returned. 'See here! You come to London, I rely on you, and I
+have an object and a course at once. I am driven out of it, I come
+here, and in a moment I feel an altered person. The circumstances that
+distressed me are not changed, since I came into this room; but an
+influence comes over me in that short interval that alters me, oh, how
+much for the better! What is it? What is your secret, Agnes?'
+
+Her head was bent down, looking at the fire.
+
+'It's the old story,' said I. 'Don't laugh, when I say it was always
+the same in little things as it is in greater ones. My old troubles were
+nonsense, and now they are serious; but whenever I have gone away from
+my adopted sister--'
+
+Agnes looked up--with such a Heavenly face!--and gave me her hand, which
+I kissed.
+
+'Whenever I have not had you, Agnes, to advise and approve in the
+beginning, I have seemed to go wild, and to get into all sorts of
+difficulty. When I have come to you, at last (as I have always done),
+I have come to peace and happiness. I come home, now, like a tired
+traveller, and find such a blessed sense of rest!'
+
+I felt so deeply what I said, it affected me so sincerely, that my voice
+failed, and I covered my face with my hand, and broke into tears. I
+write the truth. Whatever contradictions and inconsistencies there were
+within me, as there are within so many of us; whatever might have been
+so different, and so much better; whatever I had done, in which I had
+perversely wandered away from the voice of my own heart; I knew nothing
+of. I only knew that I was fervently in earnest, when I felt the rest
+and peace of having Agnes near me.
+
+In her placid sisterly manner; with her beaming eyes; with her tender
+voice; and with that sweet composure, which had long ago made the house
+that held her quite a sacred place to me; she soon won me from this
+weakness, and led me on to tell all that had happened since our last
+meeting.
+
+'And there is not another word to tell, Agnes,' said I, when I had made
+an end of my confidence. 'Now, my reliance is on you.'
+
+'But it must not be on me, Trotwood,' returned Agnes, with a pleasant
+smile. 'It must be on someone else.'
+
+'On Dora?' said I.
+
+'Assuredly.'
+
+'Why, I have not mentioned, Agnes,' said I, a little embarrassed, 'that
+Dora is rather difficult to--I would not, for the world, say, to rely
+upon, because she is the soul of purity and truth--but rather difficult
+to--I hardly know how to express it, really, Agnes. She is a timid
+little thing, and easily disturbed and frightened. Some time ago, before
+her father's death, when I thought it right to mention to her--but I'll
+tell you, if you will bear with me, how it was.'
+
+Accordingly, I told Agnes about my declaration of poverty, about the
+cookery-book, the housekeeping accounts, and all the rest of it.
+
+'Oh, Trotwood!' she remonstrated, with a smile. 'Just your old headlong
+way! You might have been in earnest in striving to get on in the world,
+without being so very sudden with a timid, loving, inexperienced girl.
+Poor Dora!'
+
+I never heard such sweet forbearing kindness expressed in a voice,
+as she expressed in making this reply. It was as if I had seen her
+admiringly and tenderly embracing Dora, and tacitly reproving me, by
+her considerate protection, for my hot haste in fluttering that little
+heart. It was as if I had seen Dora, in all her fascinating artlessness,
+caressing Agnes, and thanking her, and coaxingly appealing against me,
+and loving me with all her childish innocence.
+
+I felt so grateful to Agnes, and admired her so! I saw those two
+together, in a bright perspective, such well-associated friends, each
+adorning the other so much!
+
+'What ought I to do then, Agnes?' I inquired, after looking at the fire
+a little while. 'What would it be right to do?'
+
+'I think,' said Agnes, 'that the honourable course to take, would be to
+write to those two ladies. Don't you think that any secret course is an
+unworthy one?'
+
+'Yes. If YOU think so,' said I.
+
+'I am poorly qualified to judge of such matters,' replied Agnes, with
+a modest hesitation, 'but I certainly feel--in short, I feel that your
+being secret and clandestine, is not being like yourself.'
+
+'Like myself, in the too high opinion you have of me, Agnes, I am
+afraid,' said I.
+
+'Like yourself, in the candour of your nature,' she returned; 'and
+therefore I would write to those two ladies. I would relate, as plainly
+and as openly as possible, all that has taken place; and I would ask
+their permission to visit sometimes, at their house. Considering that
+you are young, and striving for a place in life, I think it would be
+well to say that you would readily abide by any conditions they might
+impose upon you. I would entreat them not to dismiss your request,
+without a reference to Dora; and to discuss it with her when they should
+think the time suitable. I would not be too vehement,' said Agnes,
+gently, 'or propose too much. I would trust to my fidelity and
+perseverance--and to Dora.'
+
+'But if they were to frighten Dora again, Agnes, by speaking to her,'
+said I. 'And if Dora were to cry, and say nothing about me!'
+
+'Is that likely?' inquired Agnes, with the same sweet consideration in
+her face.
+
+'God bless her, she is as easily scared as a bird,' said I. 'It might
+be! Or if the two Miss Spenlows (elderly ladies of that sort are odd
+characters sometimes) should not be likely persons to address in that
+way!'
+
+'I don't think, Trotwood,' returned Agnes, raising her soft eyes
+to mine, 'I would consider that. Perhaps it would be better only to
+consider whether it is right to do this; and, if it is, to do it.'
+
+I had no longer any doubt on the subject. With a lightened heart, though
+with a profound sense of the weighty importance of my task, I devoted
+the whole afternoon to the composition of the draft of this letter; for
+which great purpose, Agnes relinquished her desk to me. But first I went
+downstairs to see Mr. Wickfield and Uriah Heep.
+
+I found Uriah in possession of a new, plaster-smelling office, built out
+in the garden; looking extraordinarily mean, in the midst of a quantity
+of books and papers. He received me in his usual fawning way, and
+pretended not to have heard of my arrival from Mr. Micawber; a
+pretence I took the liberty of disbelieving. He accompanied me into Mr.
+Wickfield's room, which was the shadow of its former self--having been
+divested of a variety of conveniences, for the accommodation of the new
+partner--and stood before the fire, warming his back, and shaving his
+chin with his bony hand, while Mr. Wickfield and I exchanged greetings.
+
+'You stay with us, Trotwood, while you remain in Canterbury?' said Mr.
+Wickfield, not without a glance at Uriah for his approval.
+
+'Is there room for me?' said I.
+
+'I am sure, Master Copperfield--I should say Mister, but the other
+comes so natural,' said Uriah,--'I would turn out of your old room with
+pleasure, if it would be agreeable.'
+
+'No, no,' said Mr. Wickfield. 'Why should you be inconvenienced? There's
+another room. There's another room.' 'Oh, but you know,' returned Uriah,
+with a grin, 'I should really be delighted!'
+
+To cut the matter short, I said I would have the other room or none at
+all; so it was settled that I should have the other room; and, taking my
+leave of the firm until dinner, I went upstairs again.
+
+I had hoped to have no other companion than Agnes. But Mrs. Heep had
+asked permission to bring herself and her knitting near the fire, in
+that room; on pretence of its having an aspect more favourable for
+her rheumatics, as the wind then was, than the drawing-room or
+dining-parlour. Though I could almost have consigned her to the mercies
+of the wind on the topmost pinnacle of the Cathedral, without remorse, I
+made a virtue of necessity, and gave her a friendly salutation.
+
+'I'm umbly thankful to you, sir,' said Mrs. Heep, in acknowledgement of
+my inquiries concerning her health, 'but I'm only pretty well. I haven't
+much to boast of. If I could see my Uriah well settled in life, I
+couldn't expect much more I think. How do you think my Ury looking,
+sir?'
+
+I thought him looking as villainous as ever, and I replied that I saw no
+change in him.
+
+'Oh, don't you think he's changed?' said Mrs. Heep. 'There I must umbly
+beg leave to differ from you. Don't you see a thinness in him?'
+
+'Not more than usual,' I replied.
+
+'Don't you though!' said Mrs. Heep. 'But you don't take notice of him
+with a mother's eye!'
+
+His mother's eye was an evil eye to the rest of the world, I thought as
+it met mine, howsoever affectionate to him; and I believe she and her
+son were devoted to one another. It passed me, and went on to Agnes.
+
+'Don't YOU see a wasting and a wearing in him, Miss Wickfield?' inquired
+Mrs. Heep.
+
+'No,' said Agnes, quietly pursuing the work on which she was engaged.
+'You are too solicitous about him. He is very well.'
+
+Mrs. Heep, with a prodigious sniff, resumed her knitting.
+
+She never left off, or left us for a moment. I had arrived early in the
+day, and we had still three or four hours before dinner; but she sat
+there, plying her knitting-needles as monotonously as an hour-glass
+might have poured out its sands. She sat on one side of the fire; I sat
+at the desk in front of it; a little beyond me, on the other side, sat
+Agnes. Whensoever, slowly pondering over my letter, I lifted up my
+eyes, and meeting the thoughtful face of Agnes, saw it clear, and beam
+encouragement upon me, with its own angelic expression, I was conscious
+presently of the evil eye passing me, and going on to her, and coming
+back to me again, and dropping furtively upon the knitting. What the
+knitting was, I don't know, not being learned in that art; but it looked
+like a net; and as she worked away with those Chinese chopsticks of
+knitting-needles, she showed in the firelight like an ill-looking
+enchantress, baulked as yet by the radiant goodness opposite, but
+getting ready for a cast of her net by and by.
+
+At dinner she maintained her watch, with the same unwinking eyes. After
+dinner, her son took his turn; and when Mr. Wickfield, himself, and I
+were left alone together, leered at me, and writhed until I could hardly
+bear it. In the drawing-room, there was the mother knitting and watching
+again. All the time that Agnes sang and played, the mother sat at the
+piano. Once she asked for a particular ballad, which she said her Ury
+(who was yawning in a great chair) doted on; and at intervals she looked
+round at him, and reported to Agnes that he was in raptures with the
+music. But she hardly ever spoke--I question if she ever did--without
+making some mention of him. It was evident to me that this was the duty
+assigned to her.
+
+This lasted until bedtime. To have seen the mother and son, like two
+great bats hanging over the whole house, and darkening it with their
+ugly forms, made me so uncomfortable, that I would rather have remained
+downstairs, knitting and all, than gone to bed. I hardly got any sleep.
+Next day the knitting and watching began again, and lasted all day.
+
+I had not an opportunity of speaking to Agnes, for ten minutes. I could
+barely show her my letter. I proposed to her to walk out with me; but
+Mrs. Heep repeatedly complaining that she was worse, Agnes charitably
+remained within, to bear her company. Towards the twilight I went out
+by myself, musing on what I ought to do, and whether I was justified
+in withholding from Agnes, any longer, what Uriah Heep had told me in
+London; for that began to trouble me again, very much.
+
+I had not walked out far enough to be quite clear of the town, upon the
+Ramsgate road, where there was a good path, when I was hailed, through
+the dust, by somebody behind me. The shambling figure, and the scanty
+great-coat, were not to be mistaken. I stopped, and Uriah Heep came up.
+
+'Well?' said I.
+
+'How fast you walk!' said he. 'My legs are pretty long, but you've given
+'em quite a job.'
+
+'Where are you going?' said I.
+
+'I am going with you, Master Copperfield, if you'll allow me the
+pleasure of a walk with an old acquaintance.' Saying this, with a jerk
+of his body, which might have been either propitiatory or derisive, he
+fell into step beside me.
+
+'Uriah!' said I, as civilly as I could, after a silence.
+
+'Master Copperfield!' said Uriah.
+
+'To tell you the truth (at which you will not be offended), I came Out
+to walk alone, because I have had so much company.'
+
+He looked at me sideways, and said with his hardest grin, 'You mean
+mother.'
+
+'Why yes, I do,' said I.
+
+'Ah! But you know we're so very umble,' he returned. 'And having such a
+knowledge of our own umbleness, we must really take care that we're not
+pushed to the wall by them as isn't umble. All stratagems are fair in
+love, sir.'
+
+Raising his great hands until they touched his chin, he rubbed them
+softly, and softly chuckled; looking as like a malevolent baboon, I
+thought, as anything human could look.
+
+'You see,' he said, still hugging himself in that unpleasant way,
+and shaking his head at me, 'you're quite a dangerous rival, Master
+Copperfield. You always was, you know.'
+
+'Do you set a watch upon Miss Wickfield, and make her home no home,
+because of me?' said I.
+
+'Oh! Master Copperfield! Those are very arsh words,' he replied.
+
+'Put my meaning into any words you like,' said I. 'You know what it is,
+Uriah, as well as I do.'
+
+'Oh no! You must put it into words,' he said. 'Oh, really! I couldn't
+myself.'
+
+'Do you suppose,' said I, constraining myself to be very temperate
+and quiet with him, on account of Agnes, 'that I regard Miss Wickfield
+otherwise than as a very dear sister?'
+
+'Well, Master Copperfield,' he replied, 'you perceive I am not bound
+to answer that question. You may not, you know. But then, you see, you
+may!'
+
+Anything to equal the low cunning of his visage, and of his shadowless
+eyes without the ghost of an eyelash, I never saw.
+
+'Come then!' said I. 'For the sake of Miss Wickfield--'
+
+'My Agnes!' he exclaimed, with a sickly, angular contortion of himself.
+'Would you be so good as call her Agnes, Master Copperfield!'
+
+'For the sake of Agnes Wickfield--Heaven bless her!'
+
+'Thank you for that blessing, Master Copperfield!'he interposed.
+
+'I will tell you what I should, under any other circumstances, as soon
+have thought of telling to--Jack Ketch.'
+
+'To who, sir?' said Uriah, stretching out his neck, and shading his ear
+with his hand.
+
+'To the hangman,' I returned. 'The most unlikely person I could think
+of,'--though his own face had suggested the allusion quite as a natural
+sequence. 'I am engaged to another young lady. I hope that contents
+you.'
+
+'Upon your soul?' said Uriah.
+
+I was about indignantly to give my assertion the confirmation he
+required, when he caught hold of my hand, and gave it a squeeze.
+
+'Oh, Master Copperfield!' he said. 'If you had only had the
+condescension to return my confidence when I poured out the fulness of
+my art, the night I put you so much out of the way by sleeping before
+your sitting-room fire, I never should have doubted you. As it is, I'm
+sure I'll take off mother directly, and only too appy. I know you'll
+excuse the precautions of affection, won't you? What a pity, Master
+Copperfield, that you didn't condescend to return my confidence! I'm
+sure I gave you every opportunity. But you never have condescended to
+me, as much as I could have wished. I know you have never liked me, as I
+have liked you!'
+
+All this time he was squeezing my hand with his damp fishy fingers,
+while I made every effort I decently could to get it away. But I was
+quite unsuccessful. He drew it under the sleeve of his mulberry-coloured
+great-coat, and I walked on, almost upon compulsion, arm-in-arm with
+him.
+
+'Shall we turn?' said Uriah, by and by wheeling me face about towards
+the town, on which the early moon was now shining, silvering the distant
+windows.
+
+'Before we leave the subject, you ought to understand,' said I, breaking
+a pretty long silence, 'that I believe Agnes Wickfield to be as far
+above you, and as far removed from all your aspirations, as that moon
+herself!'
+
+'Peaceful! Ain't she!' said Uriah. 'Very! Now confess, Master
+Copperfield, that you haven't liked me quite as I have liked you. All
+along you've thought me too umble now, I shouldn't wonder?'
+
+'I am not fond of professions of humility,' I returned, 'or professions
+of anything else.' 'There now!' said Uriah, looking flabby and
+lead-coloured in the moonlight. 'Didn't I know it! But how little
+you think of the rightful umbleness of a person in my station, Master
+Copperfield! Father and me was both brought up at a foundation school
+for boys; and mother, she was likewise brought up at a public, sort of
+charitable, establishment. They taught us all a deal of umbleness--not
+much else that I know of, from morning to night. We was to be umble to
+this person, and umble to that; and to pull off our caps here, and
+to make bows there; and always to know our place, and abase ourselves
+before our betters. And we had such a lot of betters! Father got the
+monitor-medal by being umble. So did I. Father got made a sexton by
+being umble. He had the character, among the gentlefolks, of being
+such a well-behaved man, that they were determined to bring him in. "Be
+umble, Uriah," says father to me, "and you'll get on. It was what was
+always being dinned into you and me at school; it's what goes down best.
+Be umble," says father, "and you'll do!" And really it ain't done bad!'
+
+It was the first time it had ever occurred to me, that this detestable
+cant of false humility might have originated out of the Heep family. I
+had seen the harvest, but had never thought of the seed.
+
+'When I was quite a young boy,' said Uriah, 'I got to know what
+umbleness did, and I took to it. I ate umble pie with an appetite. I
+stopped at the umble point of my learning, and says I, "Hold hard!" When
+you offered to teach me Latin, I knew better. "People like to be above
+you," says father, "keep yourself down." I am very umble to the present
+moment, Master Copperfield, but I've got a little power!'
+
+And he said all this--I knew, as I saw his face in the moonlight--that
+I might understand he was resolved to recompense himself by using his
+power. I had never doubted his meanness, his craft and malice; but I
+fully comprehended now, for the first time, what a base, unrelenting,
+and revengeful spirit, must have been engendered by this early, and this
+long, suppression.
+
+His account of himself was so far attended with an agreeable result,
+that it led to his withdrawing his hand in order that he might have
+another hug of himself under the chin. Once apart from him, I was
+determined to keep apart; and we walked back, side by side, saying
+very little more by the way. Whether his spirits were elevated by the
+communication I had made to him, or by his having indulged in this
+retrospect, I don't know; but they were raised by some influence. He
+talked more at dinner than was usual with him; asked his mother (off
+duty, from the moment of our re-entering the house) whether he was not
+growing too old for a bachelor; and once looked at Agnes so, that I
+would have given all I had, for leave to knock him down.
+
+When we three males were left alone after dinner, he got into a more
+adventurous state. He had taken little or no wine; and I presume it was
+the mere insolence of triumph that was upon him, flushed perhaps by the
+temptation my presence furnished to its exhibition.
+
+I had observed yesterday, that he tried to entice Mr. Wickfield to
+drink; and, interpreting the look which Agnes had given me as she went
+out, had limited myself to one glass, and then proposed that we should
+follow her. I would have done so again today; but Uriah was too quick
+for me.
+
+'We seldom see our present visitor, sir,' he said, addressing Mr.
+Wickfield, sitting, such a contrast to him, at the end of the table,
+'and I should propose to give him welcome in another glass or two
+of wine, if you have no objections. Mr. Copperfield, your elth and
+appiness!'
+
+I was obliged to make a show of taking the hand he stretched across
+to me; and then, with very different emotions, I took the hand of the
+broken gentleman, his partner.
+
+'Come, fellow-partner,' said Uriah, 'if I may take the liberty,--now,
+suppose you give us something or another appropriate to Copperfield!'
+
+I pass over Mr. Wickfield's proposing my aunt, his proposing Mr. Dick,
+his proposing Doctors' Commons, his proposing Uriah, his drinking
+everything twice; his consciousness of his own weakness, the ineffectual
+effort that he made against it; the struggle between his shame in
+Uriah's deportment, and his desire to conciliate him; the manifest
+exultation with which Uriah twisted and turned, and held him up before
+me. It made me sick at heart to see, and my hand recoils from writing
+it.
+
+'Come, fellow-partner!' said Uriah, at last, 'I'll give you another one,
+and I umbly ask for bumpers, seeing I intend to make it the divinest of
+her sex.'
+
+Her father had his empty glass in his hand. I saw him set it down, look
+at the picture she was so like, put his hand to his forehead, and shrink
+back in his elbow-chair.
+
+'I'm an umble individual to give you her elth,' proceeded Uriah, 'but I
+admire--adore her.'
+
+No physical pain that her father's grey head could have borne, I think,
+could have been more terrible to me, than the mental endurance I saw
+compressed now within both his hands.
+
+'Agnes,' said Uriah, either not regarding him, or not knowing what the
+nature of his action was, 'Agnes Wickfield is, I am safe to say, the
+divinest of her sex. May I speak out, among friends? To be her father is
+a proud distinction, but to be her usband--'
+
+Spare me from ever again hearing such a cry, as that with which her
+father rose up from the table! 'What's the matter?' said Uriah, turning
+of a deadly colour. 'You are not gone mad, after all, Mr. Wickfield, I
+hope? If I say I've an ambition to make your Agnes my Agnes, I have as
+good a right to it as another man. I have a better right to it than any
+other man!'
+
+I had my arms round Mr. Wickfield, imploring him by everything that I
+could think of, oftenest of all by his love for Agnes, to calm himself
+a little. He was mad for the moment; tearing out his hair, beating his
+head, trying to force me from him, and to force himself from me, not
+answering a word, not looking at or seeing anyone; blindly striving
+for he knew not what, his face all staring and distorted--a frightful
+spectacle.
+
+I conjured him, incoherently, but in the most impassioned manner, not
+to abandon himself to this wildness, but to hear me. I besought him to
+think of Agnes, to connect me with Agnes, to recollect how Agnes and I
+had grown up together, how I honoured her and loved her, how she was his
+pride and joy. I tried to bring her idea before him in any form; I even
+reproached him with not having firmness to spare her the knowledge of
+such a scene as this. I may have effected something, or his wildness may
+have spent itself; but by degrees he struggled less, and began to look
+at me--strangely at first, then with recognition in his eyes. At length
+he said, 'I know, Trotwood! My darling child and you--I know! But look
+at him!'
+
+He pointed to Uriah, pale and glowering in a corner, evidently very much
+out in his calculations, and taken by surprise.
+
+'Look at my torturer,' he replied. 'Before him I have step by step
+abandoned name and reputation, peace and quiet, house and home.'
+
+'I have kept your name and reputation for you, and your peace and
+quiet, and your house and home too,' said Uriah, with a sulky, hurried,
+defeated air of compromise. 'Don't be foolish, Mr. Wickfield. If I
+have gone a little beyond what you were prepared for, I can go back, I
+suppose? There's no harm done.'
+
+'I looked for single motives in everyone,' said Mr. Wickfield, and I was
+satisfied I had bound him to me by motives of interest. But see what he
+is--oh, see what he is!'
+
+'You had better stop him, Copperfield, if you can,' cried Uriah,
+with his long forefinger pointing towards me. 'He'll say something
+presently--mind you!--he'll be sorry to have said afterwards, and you'll
+be sorry to have heard!'
+
+'I'll say anything!' cried Mr. Wickfield, with a desperate air. 'Why
+should I not be in all the world's power if I am in yours?'
+
+'Mind! I tell you!' said Uriah, continuing to warn me. 'If you don't
+stop his mouth, you're not his friend! Why shouldn't you be in all the
+world's power, Mr. Wickfield? Because you have got a daughter. You and
+me know what we know, don't we? Let sleeping dogs lie--who wants to
+rouse 'em? I don't. Can't you see I am as umble as I can be? I tell you,
+if I've gone too far, I'm sorry. What would you have, sir?'
+
+'Oh, Trotwood, Trotwood!'exclaimed Mr. Wickfield, wringing his hands.
+'What I have come down to be, since I first saw you in this house! I was
+on my downward way then, but the dreary, dreary road I have traversed
+since! Weak indulgence has ruined me. Indulgence in remembrance, and
+indulgence in forgetfulness. My natural grief for my child's mother
+turned to disease; my natural love for my child turned to disease. I
+have infected everything I touched. I have brought misery on what I
+dearly love, I know--you know! I thought it possible that I could truly
+love one creature in the world, and not love the rest; I thought it
+possible that I could truly mourn for one creature gone out of the
+world, and not have some part in the grief of all who mourned. Thus the
+lessons of my life have been perverted! I have preyed on my own morbid
+coward heart, and it has preyed on me. Sordid in my grief, sordid in my
+love, sordid in my miserable escape from the darker side of both, oh see
+the ruin I am, and hate me, shun me!'
+
+He dropped into a chair, and weakly sobbed. The excitement into which he
+had been roused was leaving him. Uriah came out of his corner.
+
+'I don't know all I have done, in my fatuity,' said Mr. Wickfield,
+putting out his hands, as if to deprecate my condemnation. 'He knows
+best,' meaning Uriah Heep, 'for he has always been at my elbow,
+whispering me. You see the millstone that he is about my neck. You
+find him in my house, you find him in my business. You heard him, but a
+little time ago. What need have I to say more!'
+
+'You haven't need to say so much, nor half so much, nor anything at
+all,' observed Uriah, half defiant, and half fawning. 'You wouldn't have
+took it up so, if it hadn't been for the wine. You'll think better of
+it tomorrow, sir. If I have said too much, or more than I meant, what of
+it? I haven't stood by it!'
+
+The door opened, and Agnes, gliding in, without a vestige of colour in
+her face, put her arm round his neck, and steadily said, 'Papa, you are
+not well. Come with me!'
+
+He laid his head upon her shoulder, as if he were oppressed with heavy
+shame, and went out with her. Her eyes met mine for but an instant, yet
+I saw how much she knew of what had passed.
+
+'I didn't expect he'd cut up so rough, Master Copperfield,' said Uriah.
+'But it's nothing. I'll be friends with him tomorrow. It's for his good.
+I'm umbly anxious for his good.'
+
+I gave him no answer, and went upstairs into the quiet room where Agnes
+had so often sat beside me at my books. Nobody came near me until late
+at night. I took up a book, and tried to read. I heard the clocks strike
+twelve, and was still reading, without knowing what I read, when Agnes
+touched me.
+
+'You will be going early in the morning, Trotwood! Let us say good-bye,
+now!'
+
+She had been weeping, but her face then was so calm and beautiful!
+
+'Heaven bless you!' she said, giving me her hand.
+
+'Dearest Agnes!' I returned, 'I see you ask me not to speak of
+tonight--but is there nothing to be done?'
+
+'There is God to trust in!' she replied.
+
+'Can I do nothing--I, who come to you with my poor sorrows?'
+
+'And make mine so much lighter,' she replied. 'Dear Trotwood, no!'
+
+'Dear Agnes,' I said, 'it is presumptuous for me, who am so poor in all
+in which you are so rich--goodness, resolution, all noble qualities--to
+doubt or direct you; but you know how much I love you, and how much I
+owe you. You will never sacrifice yourself to a mistaken sense of duty,
+Agnes?'
+
+More agitated for a moment than I had ever seen her, she took her hands
+from me, and moved a step back.
+
+'Say you have no such thought, dear Agnes! Much more than sister!
+Think of the priceless gift of such a heart as yours, of such a love as
+yours!'
+
+Oh! long, long afterwards, I saw that face rise up before me, with its
+momentary look, not wondering, not accusing, not regretting. Oh, long,
+long afterwards, I saw that look subside, as it did now, into the lovely
+smile, with which she told me she had no fear for herself--I need have
+none for her--and parted from me by the name of Brother, and was gone!
+
+It was dark in the morning, when I got upon the coach at the inn door.
+The day was just breaking when we were about to start, and then, as
+I sat thinking of her, came struggling up the coach side, through the
+mingled day and night, Uriah's head.
+
+'Copperfield!' said he, in a croaking whisper, as he hung by the iron
+on the roof, 'I thought you'd be glad to hear before you went off, that
+there are no squares broke between us. I've been into his room already,
+and we've made it all smooth. Why, though I'm umble, I'm useful to him,
+you know; and he understands his interest when he isn't in liquor! What
+an agreeable man he is, after all, Master Copperfield!'
+
+I obliged myself to say that I was glad he had made his apology.
+
+'Oh, to be sure!' said Uriah. 'When a person's umble, you know, what's
+an apology? So easy! I say! I suppose,' with a jerk, 'you have sometimes
+plucked a pear before it was ripe, Master Copperfield?'
+
+'I suppose I have,' I replied.
+
+'I did that last night,' said Uriah; 'but it'll ripen yet! It only wants
+attending to. I can wait!'
+
+Profuse in his farewells, he got down again as the coachman got up. For
+anything I know, he was eating something to keep the raw morning
+air out; but he made motions with his mouth as if the pear were ripe
+already, and he were smacking his lips over it.
+
+
+
+CHAPTER 40. THE WANDERER
+
+
+We had a very serious conversation in Buckingham Street that night,
+about the domestic occurrences I have detailed in the last chapter. My
+aunt was deeply interested in them, and walked up and down the room with
+her arms folded, for more than two hours afterwards. Whenever she was
+particularly discomposed, she always performed one of these pedestrian
+feats; and the amount of her discomposure might always be estimated by
+the duration of her walk. On this occasion she was so much disturbed in
+mind as to find it necessary to open the bedroom door, and make a course
+for herself, comprising the full extent of the bedrooms from wall to
+wall; and while Mr. Dick and I sat quietly by the fire, she kept passing
+in and out, along this measured track, at an unchanging pace, with the
+regularity of a clock-pendulum.
+
+When my aunt and I were left to ourselves by Mr. Dick's going out to
+bed, I sat down to write my letter to the two old ladies. By that time
+she was tired of walking, and sat by the fire with her dress tucked up
+as usual. But instead of sitting in her usual manner, holding her glass
+upon her knee, she suffered it to stand neglected on the chimney-piece;
+and, resting her left elbow on her right arm, and her chin on her left
+hand, looked thoughtfully at me. As often as I raised my eyes from what
+I was about, I met hers. 'I am in the lovingest of tempers, my dear,'
+she would assure me with a nod, 'but I am fidgeted and sorry!'
+
+I had been too busy to observe, until after she was gone to bed, that
+she had left her night-mixture, as she always called it, untasted on
+the chimney-piece. She came to her door, with even more than her usual
+affection of manner, when I knocked to acquaint her with this discovery;
+but only said, 'I have not the heart to take it, Trot, tonight,' and
+shook her head, and went in again.
+
+She read my letter to the two old ladies, in the morning, and approved
+of it. I posted it, and had nothing to do then, but wait, as patiently
+as I could, for the reply. I was still in this state of expectation, and
+had been, for nearly a week; when I left the Doctor's one snowy night,
+to walk home.
+
+It had been a bitter day, and a cutting north-east wind had blown for
+some time. The wind had gone down with the light, and so the snow had
+come on. It was a heavy, settled fall, I recollect, in great flakes; and
+it lay thick. The noise of wheels and tread of people were as hushed, as
+if the streets had been strewn that depth with feathers.
+
+My shortest way home,--and I naturally took the shortest way on such a
+night--was through St. Martin's Lane. Now, the church which gives its
+name to the lane, stood in a less free situation at that time; there
+being no open space before it, and the lane winding down to the Strand.
+As I passed the steps of the portico, I encountered, at the corner,
+a woman's face. It looked in mine, passed across the narrow lane,
+and disappeared. I knew it. I had seen it somewhere. But I could not
+remember where. I had some association with it, that struck upon my
+heart directly; but I was thinking of anything else when it came upon
+me, and was confused.
+
+On the steps of the church, there was the stooping figure of a man, who
+had put down some burden on the smooth snow, to adjust it; my seeing the
+face, and my seeing him, were simultaneous. I don't think I had stopped
+in my surprise; but, in any case, as I went on, he rose, turned, and
+came down towards me. I stood face to face with Mr. Peggotty!
+
+Then I remembered the woman. It was Martha, to whom Emily had given the
+money that night in the kitchen. Martha Endell--side by side with whom,
+he would not have seen his dear niece, Ham had told me, for all the
+treasures wrecked in the sea.
+
+We shook hands heartily. At first, neither of us could speak a word.
+
+'Mas'r Davy!' he said, gripping me tight, 'it do my art good to see you,
+sir. Well met, well met!'
+
+'Well met, my dear old friend!' said I.
+
+'I had my thowts o' coming to make inquiration for you, sir, tonight,'
+he said, 'but knowing as your aunt was living along wi' you--fur I've
+been down yonder--Yarmouth way--I was afeerd it was too late. I should
+have come early in the morning, sir, afore going away.'
+
+'Again?' said I.
+
+'Yes, sir,' he replied, patiently shaking his head, 'I'm away tomorrow.'
+
+'Where were you going now?' I asked.
+
+'Well!' he replied, shaking the snow out of his long hair, 'I was
+a-going to turn in somewheers.'
+
+In those days there was a side-entrance to the stable-yard of the Golden
+Cross, the inn so memorable to me in connexion with his misfortune,
+nearly opposite to where we stood. I pointed out the gateway, put my arm
+through his, and we went across. Two or three public-rooms opened out of
+the stable-yard; and looking into one of them, and finding it empty, and
+a good fire burning, I took him in there.
+
+When I saw him in the light, I observed, not only that his hair was long
+and ragged, but that his face was burnt dark by the sun. He was greyer,
+the lines in his face and forehead were deeper, and he had every
+appearance of having toiled and wandered through all varieties
+of weather; but he looked very strong, and like a man upheld by
+steadfastness of purpose, whom nothing could tire out. He shook the snow
+from his hat and clothes, and brushed it away from his face, while I was
+inwardly making these remarks. As he sat down opposite to me at a table,
+with his back to the door by which we had entered, he put out his rough
+hand again, and grasped mine warmly.
+
+'I'll tell you, Mas'r Davy,' he said,--'wheer all I've been, and
+what-all we've heerd. I've been fur, and we've heerd little; but I'll
+tell you!'
+
+I rang the bell for something hot to drink. He would have nothing
+stronger than ale; and while it was being brought, and being warmed
+at the fire, he sat thinking. There was a fine, massive gravity in his
+face, I did not venture to disturb.
+
+'When she was a child,' he said, lifting up his head soon after we were
+left alone, 'she used to talk to me a deal about the sea, and about
+them coasts where the sea got to be dark blue, and to lay a-shining and
+a-shining in the sun. I thowt, odd times, as her father being drownded
+made her think on it so much. I doen't know, you see, but maybe she
+believed--or hoped--he had drifted out to them parts, where the flowers
+is always a-blowing, and the country bright.'
+
+'It is likely to have been a childish fancy,' I replied.
+
+'When she was--lost,' said Mr. Peggotty, 'I know'd in my mind, as he
+would take her to them countries. I know'd in my mind, as he'd have told
+her wonders of 'em, and how she was to be a lady theer, and how he got
+her to listen to him fust, along o' sech like. When we see his mother,
+I know'd quite well as I was right. I went across-channel to France, and
+landed theer, as if I'd fell down from the sky.'
+
+I saw the door move, and the snow drift in. I saw it move a little more,
+and a hand softly interpose to keep it open.
+
+'I found out an English gen'leman as was in authority,' said Mr.
+Peggotty, 'and told him I was a-going to seek my niece. He got me them
+papers as I wanted fur to carry me through--I doen't rightly know how
+they're called--and he would have give me money, but that I was thankful
+to have no need on. I thank him kind, for all he done, I'm sure! "I've
+wrote afore you," he says to me, "and I shall speak to many as will come
+that way, and many will know you, fur distant from here, when you're
+a-travelling alone." I told him, best as I was able, what my gratitoode
+was, and went away through France.'
+
+'Alone, and on foot?' said I.
+
+'Mostly a-foot,' he rejoined; 'sometimes in carts along with people
+going to market; sometimes in empty coaches. Many mile a day a-foot, and
+often with some poor soldier or another, travelling to see his friends.
+I couldn't talk to him,' said Mr. Peggotty, 'nor he to me; but we was
+company for one another, too, along the dusty roads.'
+
+I should have known that by his friendly tone.
+
+'When I come to any town,' he pursued, 'I found the inn, and waited
+about the yard till someone turned up (someone mostly did) as know'd
+English. Then I told how that I was on my way to seek my niece, and they
+told me what manner of gentlefolks was in the house, and I waited to see
+any as seemed like her, going in or out. When it warn't Em'ly, I went on
+agen. By little and little, when I come to a new village or that, among
+the poor people, I found they know'd about me. They would set me down at
+their cottage doors, and give me what-not fur to eat and drink, and show
+me where to sleep; and many a woman, Mas'r Davy, as has had a daughter
+of about Em'ly's age, I've found a-waiting fur me, at Our Saviour's
+Cross outside the village, fur to do me sim'lar kindnesses. Some has had
+daughters as was dead. And God only knows how good them mothers was to
+me!'
+
+It was Martha at the door. I saw her haggard, listening face distinctly.
+My dread was lest he should turn his head, and see her too.
+
+'They would often put their children--particular their little girls,'
+said Mr. Peggotty, 'upon my knee; and many a time you might have seen
+me sitting at their doors, when night was coming in, a'most as if they'd
+been my Darling's children. Oh, my Darling!'
+
+Overpowered by sudden grief, he sobbed aloud. I laid my trembling hand
+upon the hand he put before his face. 'Thankee, sir,' he said, 'doen't
+take no notice.'
+
+In a very little while he took his hand away and put it on his breast,
+and went on with his story. 'They often walked with me,' he said, 'in
+the morning, maybe a mile or two upon my road; and when we parted, and
+I said, "I'm very thankful to you! God bless you!" they always seemed to
+understand, and answered pleasant. At last I come to the sea. It warn't
+hard, you may suppose, for a seafaring man like me to work his way
+over to Italy. When I got theer, I wandered on as I had done afore. The
+people was just as good to me, and I should have gone from town to town,
+maybe the country through, but that I got news of her being seen among
+them Swiss mountains yonder. One as know'd his servant see 'em there,
+all three, and told me how they travelled, and where they was. I made
+fur them mountains, Mas'r Davy, day and night. Ever so fur as I went,
+ever so fur the mountains seemed to shift away from me. But I come up
+with 'em, and I crossed 'em. When I got nigh the place as I had been
+told of, I began to think within my own self, "What shall I do when I
+see her?"'
+
+The listening face, insensible to the inclement night, still drooped at
+the door, and the hands begged me--prayed me--not to cast it forth.
+
+'I never doubted her,' said Mr. Peggotty. 'No! Not a bit! On'y let her
+see my face--on'y let her beer my voice--on'y let my stanning still
+afore her bring to her thoughts the home she had fled away from, and the
+child she had been--and if she had growed to be a royal lady, she'd have
+fell down at my feet! I know'd it well! Many a time in my sleep had I
+heerd her cry out, "Uncle!" and seen her fall like death afore me. Many
+a time in my sleep had I raised her up, and whispered to her, "Em'ly, my
+dear, I am come fur to bring forgiveness, and to take you home!"'
+
+He stopped and shook his head, and went on with a sigh.
+
+'He was nowt to me now. Em'ly was all. I bought a country dress to put
+upon her; and I know'd that, once found, she would walk beside me over
+them stony roads, go where I would, and never, never, leave me more. To
+put that dress upon her, and to cast off what she wore--to take her on
+my arm again, and wander towards home--to stop sometimes upon the road,
+and heal her bruised feet and her worse-bruised heart--was all that I
+thowt of now. I doen't believe I should have done so much as look at
+him. But, Mas'r Davy, it warn't to be--not yet! I was too late, and they
+was gone. Wheer, I couldn't learn. Some said beer, some said theer.
+I travelled beer, and I travelled theer, but I found no Em'ly, and I
+travelled home.'
+
+'How long ago?' I asked.
+
+'A matter o' fower days,' said Mr. Peggotty. 'I sighted the old boat
+arter dark, and the light a-shining in the winder. When I come nigh and
+looked in through the glass, I see the faithful creetur Missis Gummidge
+sittin' by the fire, as we had fixed upon, alone. I called out, "Doen't
+be afeerd! It's Dan'l!" and I went in. I never could have thowt the old
+boat would have been so strange!' From some pocket in his breast, he
+took out, with a very careful hand a small paper bundle containing two
+or three letters or little packets, which he laid upon the table.
+
+'This fust one come,' he said, selecting it from the rest, 'afore I had
+been gone a week. A fifty pound Bank note, in a sheet of paper, directed
+to me, and put underneath the door in the night. She tried to hide her
+writing, but she couldn't hide it from Me!'
+
+He folded up the note again, with great patience and care, in exactly
+the same form, and laid it on one side.
+
+'This come to Missis Gummidge,' he said, opening another, 'two or three
+months ago.'After looking at it for some moments, he gave it to me, and
+added in a low voice, 'Be so good as read it, sir.'
+
+I read as follows:
+
+
+'Oh what will you feel when you see this writing, and know it comes from
+my wicked hand! But try, try--not for my sake, but for uncle's goodness,
+try to let your heart soften to me, only for a little little time! Try,
+pray do, to relent towards a miserable girl, and write down on a bit of
+paper whether he is well, and what he said about me before you left off
+ever naming me among yourselves--and whether, of a night, when it is my
+old time of coming home, you ever see him look as if he thought of one
+he used to love so dear. Oh, my heart is breaking when I think about
+it! I am kneeling down to you, begging and praying you not to be as
+hard with me as I deserve--as I well, well, know I deserve--but to be so
+gentle and so good, as to write down something of him, and to send it to
+me. You need not call me Little, you need not call me by the name I have
+disgraced; but oh, listen to my agony, and have mercy on me so far as to
+write me some word of uncle, never, never to be seen in this world by my
+eyes again!
+
+'Dear, if your heart is hard towards me--justly hard, I know--but,
+listen, if it is hard, dear, ask him I have wronged the most--him whose
+wife I was to have been--before you quite decide against my poor poor
+prayer! If he should be so compassionate as to say that you might write
+something for me to read--I think he would, oh, I think he would, if you
+would only ask him, for he always was so brave and so forgiving--tell
+him then (but not else), that when I hear the wind blowing at night,
+I feel as if it was passing angrily from seeing him and uncle, and was
+going up to God against me. Tell him that if I was to die tomorrow (and
+oh, if I was fit, I would be so glad to die!) I would bless him and
+uncle with my last words, and pray for his happy home with my last
+breath!'
+
+
+Some money was enclosed in this letter also. Five pounds. It was
+untouched like the previous sum, and he refolded it in the same way.
+Detailed instructions were added relative to the address of a reply,
+which, although they betrayed the intervention of several hands, and
+made it difficult to arrive at any very probable conclusion in reference
+to her place of concealment, made it at least not unlikely that she had
+written from that spot where she was stated to have been seen.
+
+'What answer was sent?' I inquired of Mr. Peggotty.
+
+'Missis Gummidge,' he returned, 'not being a good scholar, sir, Ham
+kindly drawed it out, and she made a copy on it. They told her I was
+gone to seek her, and what my parting words was.'
+
+'Is that another letter in your hand?' said I.
+
+'It's money, sir,' said Mr. Peggotty, unfolding it a little way. 'Ten
+pound, you see. And wrote inside, "From a true friend," like the fust.
+But the fust was put underneath the door, and this come by the post, day
+afore yesterday. I'm a-going to seek her at the post-mark.'
+
+He showed it to me. It was a town on the Upper Rhine. He had found out,
+at Yarmouth, some foreign dealers who knew that country, and they had
+drawn him a rude map on paper, which he could very well understand. He
+laid it between us on the table; and, with his chin resting on one hand,
+tracked his course upon it with the other.
+
+I asked him how Ham was? He shook his head.
+
+'He works,' he said, 'as bold as a man can. His name's as good, in all
+that part, as any man's is, anywheres in the wureld. Anyone's hand is
+ready to help him, you understand, and his is ready to help them. He's
+never been heerd fur to complain. But my sister's belief is ('twixt
+ourselves) as it has cut him deep.'
+
+'Poor fellow, I can believe it!'
+
+'He ain't no care, Mas'r Davy,' said Mr. Peggotty in a solemn
+whisper--'kinder no care no-how for his life. When a man's wanted for
+rough sarvice in rough weather, he's theer. When there's hard duty to
+be done with danger in it, he steps for'ard afore all his mates. And yet
+he's as gentle as any child. There ain't a child in Yarmouth that doen't
+know him.'
+
+He gathered up the letters thoughtfully, smoothing them with his hand;
+put them into their little bundle; and placed it tenderly in his breast
+again. The face was gone from the door. I still saw the snow drifting
+in; but nothing else was there.
+
+'Well!' he said, looking to his bag, 'having seen you tonight, Mas'r
+Davy (and that doos me good!), I shall away betimes tomorrow morning.
+You have seen what I've got heer'; putting his hand on where the little
+packet lay; 'all that troubles me is, to think that any harm might come
+to me, afore that money was give back. If I was to die, and it was lost,
+or stole, or elseways made away with, and it was never know'd by him
+but what I'd took it, I believe the t'other wureld wouldn't hold me! I
+believe I must come back!'
+
+He rose, and I rose too; we grasped each other by the hand again, before
+going out.
+
+'I'd go ten thousand mile,' he said, 'I'd go till I dropped dead, to lay
+that money down afore him. If I do that, and find my Em'ly, I'm content.
+If I doen't find her, maybe she'll come to hear, sometime, as her loving
+uncle only ended his search for her when he ended his life; and if I
+know her, even that will turn her home at last!'
+
+As he went out into the rigorous night, I saw the lonely figure flit
+away before us. I turned him hastily on some pretence, and held him in
+conversation until it was gone.
+
+He spoke of a traveller's house on the Dover Road, where he knew he
+could find a clean, plain lodging for the night. I went with him over
+Westminster Bridge, and parted from him on the Surrey shore. Everything
+seemed, to my imagination, to be hushed in reverence for him, as he
+resumed his solitary journey through the snow.
+
+I returned to the inn yard, and, impressed by my remembrance of the
+face, looked awfully around for it. It was not there. The snow had
+covered our late footprints; my new track was the only one to be seen;
+and even that began to die away (it snowed so fast) as I looked back
+over my shoulder.
+
+
+
+CHAPTER 41. DORA'S AUNTS
+
+
+At last, an answer came from the two old ladies. They presented their
+compliments to Mr. Copperfield, and informed him that they had given his
+letter their best consideration, 'with a view to the happiness of
+both parties'--which I thought rather an alarming expression, not
+only because of the use they had made of it in relation to the family
+difference before-mentioned, but because I had (and have all my life)
+observed that conventional phrases are a sort of fireworks, easily let
+off, and liable to take a great variety of shapes and colours not at
+all suggested by their original form. The Misses Spenlow added that they
+begged to forbear expressing, 'through the medium of correspondence', an
+opinion on the subject of Mr. Copperfield's communication; but that if
+Mr. Copperfield would do them the favour to call, upon a certain day
+(accompanied, if he thought proper, by a confidential friend), they
+would be happy to hold some conversation on the subject.
+
+To this favour, Mr. Copperfield immediately replied, with his respectful
+compliments, that he would have the honour of waiting on the Misses
+Spenlow, at the time appointed; accompanied, in accordance with their
+kind permission, by his friend Mr. Thomas Traddles of the Inner Temple.
+Having dispatched which missive, Mr. Copperfield fell into a condition
+of strong nervous agitation; and so remained until the day arrived.
+
+It was a great augmentation of my uneasiness to be bereaved, at this
+eventful crisis, of the inestimable services of Miss Mills. But Mr.
+Mills, who was always doing something or other to annoy me--or I felt
+as if he were, which was the same thing--had brought his conduct to a
+climax, by taking it into his head that he would go to India. Why should
+he go to India, except to harass me? To be sure he had nothing to do
+with any other part of the world, and had a good deal to do with that
+part; being entirely in the India trade, whatever that was (I had
+floating dreams myself concerning golden shawls and elephants' teeth);
+having been at Calcutta in his youth; and designing now to go out there
+again, in the capacity of resident partner. But this was nothing to me.
+However, it was so much to him that for India he was bound, and
+Julia with him; and Julia went into the country to take leave of
+her relations; and the house was put into a perfect suit of bills,
+announcing that it was to be let or sold, and that the furniture (Mangle
+and all) was to be taken at a valuation. So, here was another earthquake
+of which I became the sport, before I had recovered from the shock of
+its predecessor!
+
+I was in several minds how to dress myself on the important day; being
+divided between my desire to appear to advantage, and my apprehensions
+of putting on anything that might impair my severely practical character
+in the eyes of the Misses Spenlow. I endeavoured to hit a happy medium
+between these two extremes; my aunt approved the result; and Mr. Dick
+threw one of his shoes after Traddles and me, for luck, as we went
+downstairs.
+
+Excellent fellow as I knew Traddles to be, and warmly attached to him as
+I was, I could not help wishing, on that delicate occasion, that he had
+never contracted the habit of brushing his hair so very upright. It
+gave him a surprised look--not to say a hearth-broomy kind of
+expression--which, my apprehensions whispered, might be fatal to us.
+
+I took the liberty of mentioning it to Traddles, as we were walking to
+Putney; and saying that if he WOULD smooth it down a little--
+
+'My dear Copperfield,' said Traddles, lifting off his hat, and rubbing
+his hair all kinds of ways, 'nothing would give me greater pleasure. But
+it won't.'
+
+'Won't be smoothed down?' said I.
+
+'No,' said Traddles. 'Nothing will induce it. If I was to carry a
+half-hundred-weight upon it, all the way to Putney, it would be up again
+the moment the weight was taken off. You have no idea what obstinate
+hair mine is, Copperfield. I am quite a fretful porcupine.'
+
+I was a little disappointed, I must confess, but thoroughly charmed by
+his good-nature too. I told him how I esteemed his good-nature; and said
+that his hair must have taken all the obstinacy out of his character,
+for he had none.
+
+'Oh!' returned Traddles, laughing. 'I assure you, it's quite an old
+story, my unfortunate hair. My uncle's wife couldn't bear it. She said
+it exasperated her. It stood very much in my way, too, when I first fell
+in love with Sophy. Very much!'
+
+'Did she object to it?'
+
+'SHE didn't,' rejoined Traddles; 'but her eldest sister--the one that's
+the Beauty--quite made game of it, I understand. In fact, all the
+sisters laugh at it.'
+
+'Agreeable!' said I.
+
+'Yes,' returned Traddles with perfect innocence, 'it's a joke for us.
+They pretend that Sophy has a lock of it in her desk, and is obliged to
+shut it in a clasped book, to keep it down. We laugh about it.'
+
+'By the by, my dear Traddles,' said I, 'your experience may suggest
+something to me. When you became engaged to the young lady whom you have
+just mentioned, did you make a regular proposal to her family? Was there
+anything like--what we are going through today, for instance?' I added,
+nervously.
+
+'Why,' replied Traddles, on whose attentive face a thoughtful shade had
+stolen, 'it was rather a painful transaction, Copperfield, in my case.
+You see, Sophy being of so much use in the family, none of them could
+endure the thought of her ever being married. Indeed, they had quite
+settled among themselves that she never was to be married, and they
+called her the old maid. Accordingly, when I mentioned it, with the
+greatest precaution, to Mrs. Crewler--'
+
+'The mama?' said I.
+
+'The mama,' said Traddles--'Reverend Horace Crewler--when I mentioned it
+with every possible precaution to Mrs. Crewler, the effect upon her was
+such that she gave a scream and became insensible. I couldn't approach
+the subject again, for months.'
+
+'You did at last?' said I.
+
+'Well, the Reverend Horace did,' said Traddles. 'He is an excellent man,
+most exemplary in every way; and he pointed out to her that she ought,
+as a Christian, to reconcile herself to the sacrifice (especially as it
+was so uncertain), and to bear no uncharitable feeling towards me. As to
+myself, Copperfield, I give you my word, I felt a perfect bird of prey
+towards the family.'
+
+'The sisters took your part, I hope, Traddles?'
+
+'Why, I can't say they did,' he returned. 'When we had comparatively
+reconciled Mrs. Crewler to it, we had to break it to Sarah. You
+recollect my mentioning Sarah, as the one that has something the matter
+with her spine?'
+
+'Perfectly!'
+
+'She clenched both her hands,' said Traddles, looking at me in dismay;
+'shut her eyes; turned lead-colour; became perfectly stiff; and
+took nothing for two days but toast-and-water, administered with a
+tea-spoon.'
+
+'What a very unpleasant girl, Traddles!' I remarked.
+
+'Oh, I beg your pardon, Copperfield!' said Traddles. 'She is a very
+charming girl, but she has a great deal of feeling. In fact, they all
+have. Sophy told me afterwards, that the self-reproach she underwent
+while she was in attendance upon Sarah, no words could describe. I know
+it must have been severe, by my own feelings, Copperfield; which were
+like a criminal's. After Sarah was restored, we still had to break it
+to the other eight; and it produced various effects upon them of a most
+pathetic nature. The two little ones, whom Sophy educates, have only
+just left off de-testing me.'
+
+'At any rate, they are all reconciled to it now, I hope?' said I.
+
+'Ye-yes, I should say they were, on the whole, resigned to it,' said
+Traddles, doubtfully. 'The fact is, we avoid mentioning the subject;
+and my unsettled prospects and indifferent circumstances are a great
+consolation to them. There will be a deplorable scene, whenever we
+are married. It will be much more like a funeral, than a wedding. And
+they'll all hate me for taking her away!'
+
+His honest face, as he looked at me with a serio-comic shake of his
+head, impresses me more in the remembrance than it did in the reality,
+for I was by this time in a state of such excessive trepidation
+and wandering of mind, as to be quite unable to fix my attention on
+anything. On our approaching the house where the Misses Spenlow lived,
+I was at such a discount in respect of my personal looks and presence of
+mind, that Traddles proposed a gentle stimulant in the form of a glass
+of ale. This having been administered at a neighbouring public-house, he
+conducted me, with tottering steps, to the Misses Spenlow's door.
+
+I had a vague sensation of being, as it were, on view, when the maid
+opened it; and of wavering, somehow, across a hall with a weather-glass
+in it, into a quiet little drawing-room on the ground-floor, commanding
+a neat garden. Also of sitting down here, on a sofa, and seeing
+Traddles's hair start up, now his hat was removed, like one of those
+obtrusive little figures made of springs, that fly out of fictitious
+snuff-boxes when the lid is taken off. Also of hearing an old-fashioned
+clock ticking away on the chimney-piece, and trying to make it keep time
+to the jerking of my heart,--which it wouldn't. Also of looking round
+the room for any sign of Dora, and seeing none. Also of thinking that
+Jip once barked in the distance, and was instantly choked by somebody.
+Ultimately I found myself backing Traddles into the fireplace, and
+bowing in great confusion to two dry little elderly ladies, dressed in
+black, and each looking wonderfully like a preparation in chip or tan of
+the late Mr. Spenlow.
+
+'Pray,' said one of the two little ladies, 'be seated.'
+
+When I had done tumbling over Traddles, and had sat upon something which
+was not a cat--my first seat was--I so far recovered my sight, as to
+perceive that Mr. Spenlow had evidently been the youngest of the
+family; that there was a disparity of six or eight years between the
+two sisters; and that the younger appeared to be the manager of the
+conference, inasmuch as she had my letter in her hand--so familiar as
+it looked to me, and yet so odd!--and was referring to it through an
+eye-glass. They were dressed alike, but this sister wore her dress with
+a more youthful air than the other; and perhaps had a trifle more frill,
+or tucker, or brooch, or bracelet, or some little thing of that kind,
+which made her look more lively. They were both upright in their
+carriage, formal, precise, composed, and quiet. The sister who had
+not my letter, had her arms crossed on her breast, and resting on each
+other, like an Idol.
+
+'Mr. Copperfield, I believe,' said the sister who had got my letter,
+addressing herself to Traddles.
+
+This was a frightful beginning. Traddles had to indicate that I was Mr.
+Copperfield, and I had to lay claim to myself, and they had to divest
+themselves of a preconceived opinion that Traddles was Mr. Copperfield,
+and altogether we were in a nice condition. To improve it, we all
+distinctly heard Jip give two short barks, and receive another choke.
+
+'Mr. Copperfield!' said the sister with the letter.
+
+I did something--bowed, I suppose--and was all attention, when the other
+sister struck in.
+
+'My sister Lavinia,' said she 'being conversant with matters of this
+nature, will state what we consider most calculated to promote the
+happiness of both parties.'
+
+I discovered afterwards that Miss Lavinia was an authority in affairs
+of the heart, by reason of there having anciently existed a certain Mr.
+Pidger, who played short whist, and was supposed to have been enamoured
+of her. My private opinion is, that this was entirely a gratuitous
+assumption, and that Pidger was altogether innocent of any such
+sentiments--to which he had never given any sort of expression that
+I could ever hear of. Both Miss Lavinia and Miss Clarissa had a
+superstition, however, that he would have declared his passion, if he
+had not been cut short in his youth (at about sixty) by over-drinking
+his constitution, and over-doing an attempt to set it right again by
+swilling Bath water. They had a lurking suspicion even, that he died of
+secret love; though I must say there was a picture of him in the house
+with a damask nose, which concealment did not appear to have ever preyed
+upon.
+
+'We will not,' said Miss Lavinia, 'enter on the past history of this
+matter. Our poor brother Francis's death has cancelled that.'
+
+'We had not,' said Miss Clarissa, 'been in the habit of frequent
+association with our brother Francis; but there was no decided division
+or disunion between us. Francis took his road; we took ours. We
+considered it conducive to the happiness of all parties that it should
+be so. And it was so.'
+
+Each of the sisters leaned a little forward to speak, shook her head
+after speaking, and became upright again when silent. Miss Clarissa
+never moved her arms. She sometimes played tunes upon them with her
+fingers--minuets and marches I should think--but never moved them.
+
+'Our niece's position, or supposed position, is much changed by our
+brother Francis's death,' said Miss Lavinia; 'and therefore we consider
+our brother's opinions as regarded her position as being changed too. We
+have no reason to doubt, Mr. Copperfield, that you are a young gentleman
+possessed of good qualities and honourable character; or that you have
+an affection--or are fully persuaded that you have an affection--for our
+niece.'
+
+I replied, as I usually did whenever I had a chance, that nobody had
+ever loved anybody else as I loved Dora. Traddles came to my assistance
+with a confirmatory murmur.
+
+Miss Lavinia was going on to make some rejoinder, when Miss Clarissa,
+who appeared to be incessantly beset by a desire to refer to her brother
+Francis, struck in again:
+
+'If Dora's mama,' she said, 'when she married our brother Francis, had
+at once said that there was not room for the family at the dinner-table,
+it would have been better for the happiness of all parties.'
+
+'Sister Clarissa,' said Miss Lavinia. 'Perhaps we needn't mind that
+now.'
+
+'Sister Lavinia,' said Miss Clarissa, 'it belongs to the subject. With
+your branch of the subject, on which alone you are competent to speak, I
+should not think of interfering. On this branch of the subject I have a
+voice and an opinion. It would have been better for the happiness of
+all parties, if Dora's mama, when she married our brother Francis, had
+mentioned plainly what her intentions were. We should then have known
+what we had to expect. We should have said "Pray do not invite us,
+at any time"; and all possibility of misunderstanding would have been
+avoided.'
+
+When Miss Clarissa had shaken her head, Miss Lavinia resumed: again
+referring to my letter through her eye-glass. They both had little
+bright round twinkling eyes, by the way, which were like birds' eyes.
+They were not unlike birds, altogether; having a sharp, brisk, sudden
+manner, and a little short, spruce way of adjusting themselves, like
+canaries.
+
+Miss Lavinia, as I have said, resumed:
+
+'You ask permission of my sister Clarissa and myself, Mr. Copperfield,
+to visit here, as the accepted suitor of our niece.'
+
+'If our brother Francis,' said Miss Clarissa, breaking out again, if I
+may call anything so calm a breaking out, 'wished to surround himself
+with an atmosphere of Doctors' Commons, and of Doctors' Commons only,
+what right or desire had we to object? None, I am sure. We have ever
+been far from wishing to obtrude ourselves on anyone. But why not say
+so? Let our brother Francis and his wife have their society. Let
+my sister Lavinia and myself have our society. We can find it for
+ourselves, I hope.'
+
+As this appeared to be addressed to Traddles and me, both Traddles and
+I made some sort of reply. Traddles was inaudible. I think I observed,
+myself, that it was highly creditable to all concerned. I don't in the
+least know what I meant.
+
+'Sister Lavinia,' said Miss Clarissa, having now relieved her mind, 'you
+can go on, my dear.'
+
+Miss Lavinia proceeded:
+
+'Mr. Copperfield, my sister Clarissa and I have been very careful
+indeed in considering this letter; and we have not considered it without
+finally showing it to our niece, and discussing it with our niece. We
+have no doubt that you think you like her very much.'
+
+'Think, ma'am,' I rapturously began, 'oh!--'
+
+But Miss Clarissa giving me a look (just like a sharp canary), as
+requesting that I would not interrupt the oracle, I begged pardon.
+
+'Affection,' said Miss Lavinia, glancing at her sister for
+corroboration, which she gave in the form of a little nod to every
+clause, 'mature affection, homage, devotion, does not easily express
+itself. Its voice is low. It is modest and retiring, it lies in ambush,
+waits and waits. Such is the mature fruit. Sometimes a life glides away,
+and finds it still ripening in the shade.'
+
+Of course I did not understand then that this was an allusion to her
+supposed experience of the stricken Pidger; but I saw, from the gravity
+with which Miss Clarissa nodded her head, that great weight was attached
+to these words.
+
+'The light--for I call them, in comparison with such sentiments, the
+light--inclinations of very young people,' pursued Miss Lavinia, 'are
+dust, compared to rocks. It is owing to the difficulty of knowing
+whether they are likely to endure or have any real foundation, that
+my sister Clarissa and myself have been very undecided how to act, Mr.
+Copperfield, and Mr.--'
+
+'Traddles,' said my friend, finding himself looked at.
+
+'I beg pardon. Of the Inner Temple, I believe?' said Miss Clarissa,
+again glancing at my letter.
+
+Traddles said 'Exactly so,' and became pretty red in the face.
+
+Now, although I had not received any express encouragement as yet, I
+fancied that I saw in the two little sisters, and particularly in Miss
+Lavinia, an intensified enjoyment of this new and fruitful subject of
+domestic interest, a settling down to make the most of it, a disposition
+to pet it, in which there was a good bright ray of hope. I thought
+I perceived that Miss Lavinia would have uncommon satisfaction in
+superintending two young lovers, like Dora and me; and that Miss
+Clarissa would have hardly less satisfaction in seeing her superintend
+us, and in chiming in with her own particular department of the subject
+whenever that impulse was strong upon her. This gave me courage to
+protest most vehemently that I loved Dora better than I could tell, or
+anyone believe; that all my friends knew how I loved her; that my aunt,
+Agnes, Traddles, everyone who knew me, knew how I loved her, and how
+earnest my love had made me. For the truth of this, I appealed to
+Traddles. And Traddles, firing up as if he were plunging into a
+Parliamentary Debate, really did come out nobly: confirming me in good
+round terms, and in a plain sensible practical manner, that evidently
+made a favourable impression.
+
+'I speak, if I may presume to say so, as one who has some little
+experience of such things,' said Traddles, 'being myself engaged to a
+young lady--one of ten, down in Devonshire--and seeing no probability,
+at present, of our engagement coming to a termination.'
+
+'You may be able to confirm what I have said, Mr. Traddles,' observed
+Miss Lavinia, evidently taking a new interest in him, 'of the affection
+that is modest and retiring; that waits and waits?'
+
+'Entirely, ma'am,' said Traddles.
+
+Miss Clarissa looked at Miss Lavinia, and shook her head gravely. Miss
+Lavinia looked consciously at Miss Clarissa, and heaved a little sigh.
+'Sister Lavinia,' said Miss Clarissa, 'take my smelling-bottle.'
+
+Miss Lavinia revived herself with a few whiffs of aromatic
+vinegar--Traddles and I looking on with great solicitude the while; and
+then went on to say, rather faintly:
+
+'My sister and myself have been in great doubt, Mr. Traddles, what
+course we ought to take in reference to the likings, or imaginary
+likings, of such very young people as your friend Mr. Copperfield and
+our niece.'
+
+'Our brother Francis's child,' remarked Miss Clarissa. 'If our brother
+Francis's wife had found it convenient in her lifetime (though she had
+an unquestionable right to act as she thought best) to invite the family
+to her dinner-table, we might have known our brother Francis's child
+better at the present moment. Sister Lavinia, proceed.'
+
+Miss Lavinia turned my letter, so as to bring the superscription towards
+herself, and referred through her eye-glass to some orderly-looking
+notes she had made on that part of it.
+
+'It seems to us,' said she, 'prudent, Mr. Traddles, to bring these
+feelings to the test of our own observation. At present we know nothing
+of them, and are not in a situation to judge how much reality there
+may be in them. Therefore we are inclined so far to accede to Mr.
+Copperfield's proposal, as to admit his visits here.'
+
+'I shall never, dear ladies,' I exclaimed, relieved of an immense load
+of apprehension, 'forget your kindness!'
+
+'But,' pursued Miss Lavinia,--'but, we would prefer to regard those
+visits, Mr. Traddles, as made, at present, to us. We must guard
+ourselves from recognizing any positive engagement between Mr.
+Copperfield and our niece, until we have had an opportunity--'
+
+'Until YOU have had an opportunity, sister Lavinia,' said Miss Clarissa.
+
+'Be it so,' assented Miss Lavinia, with a sigh--'until I have had an
+opportunity of observing them.'
+
+'Copperfield,' said Traddles, turning to me, 'you feel, I am sure, that
+nothing could be more reasonable or considerate.'
+
+'Nothing!' cried I. 'I am deeply sensible of it.'
+
+'In this position of affairs,' said Miss Lavinia, again referring to
+her notes, 'and admitting his visits on this understanding only, we
+must require from Mr. Copperfield a distinct assurance, on his word of
+honour, that no communication of any kind shall take place between him
+and our niece without our knowledge. That no project whatever shall be
+entertained with regard to our niece, without being first submitted to
+us--' 'To you, sister Lavinia,' Miss Clarissa interposed.
+
+'Be it so, Clarissa!' assented Miss Lavinia resignedly--'to me--and
+receiving our concurrence. We must make this a most express and serious
+stipulation, not to be broken on any account. We wished Mr. Copperfield
+to be accompanied by some confidential friend today,' with an
+inclination of her head towards Traddles, who bowed, 'in order that
+there might be no doubt or misconception on this subject. If Mr.
+Copperfield, or if you, Mr. Traddles, feel the least scruple, in giving
+this promise, I beg you to take time to consider it.'
+
+I exclaimed, in a state of high ecstatic fervour, that not a moment's
+consideration could be necessary. I bound myself by the required
+promise, in a most impassioned manner; called upon Traddles to witness
+it; and denounced myself as the most atrocious of characters if I ever
+swerved from it in the least degree.
+
+'Stay!' said Miss Lavinia, holding up her hand; 'we resolved, before we
+had the pleasure of receiving you two gentlemen, to leave you alone
+for a quarter of an hour, to consider this point. You will allow us to
+retire.'
+
+It was in vain for me to say that no consideration was necessary. They
+persisted in withdrawing for the specified time. Accordingly, these
+little birds hopped out with great dignity; leaving me to receive the
+congratulations of Traddles, and to feel as if I were translated to
+regions of exquisite happiness. Exactly at the expiration of the
+quarter of an hour, they reappeared with no less dignity than they had
+disappeared. They had gone rustling away as if their little dresses were
+made of autumn-leaves: and they came rustling back, in like manner.
+
+I then bound myself once more to the prescribed conditions.
+
+'Sister Clarissa,' said Miss Lavinia, 'the rest is with you.'
+
+Miss Clarissa, unfolding her arms for the first time, took the notes and
+glanced at them.
+
+'We shall be happy,' said Miss Clarissa, 'to see Mr. Copperfield to
+dinner, every Sunday, if it should suit his convenience. Our hour is
+three.'
+
+I bowed.
+
+'In the course of the week,' said Miss Clarissa, 'we shall be happy to
+see Mr. Copperfield to tea. Our hour is half-past six.'
+
+I bowed again.
+
+'Twice in the week,' said Miss Clarissa, 'but, as a rule, not oftener.'
+
+I bowed again.
+
+'Miss Trotwood,' said Miss Clarissa, 'mentioned in Mr. Copperfield's
+letter, will perhaps call upon us. When visiting is better for the
+happiness of all parties, we are glad to receive visits, and return
+them. When it is better for the happiness of all parties that no
+visiting should take place, (as in the case of our brother Francis, and
+his establishment) that is quite different.'
+
+I intimated that my aunt would be proud and delighted to make their
+acquaintance; though I must say I was not quite sure of their getting
+on very satisfactorily together. The conditions being now closed, I
+expressed my acknowledgements in the warmest manner; and, taking the
+hand, first of Miss Clarissa, and then of Miss Lavinia, pressed it, in
+each case, to my lips.
+
+Miss Lavinia then arose, and begging Mr. Traddles to excuse us for a
+minute, requested me to follow her. I obeyed, all in a tremble, and was
+conducted into another room. There I found my blessed darling stopping
+her ears behind the door, with her dear little face against the wall;
+and Jip in the plate-warmer with his head tied up in a towel.
+
+Oh! How beautiful she was in her black frock, and how she sobbed and
+cried at first, and wouldn't come out from behind the door! How fond we
+were of one another, when she did come out at last; and what a state of
+bliss I was in, when we took Jip out of the plate-warmer, and restored
+him to the light, sneezing very much, and were all three reunited!
+
+'My dearest Dora! Now, indeed, my own for ever!'
+
+'Oh, DON'T!' pleaded Dora. 'Please!'
+
+'Are you not my own for ever, Dora?'
+
+'Oh yes, of course I am!' cried Dora, 'but I am so frightened!'
+
+'Frightened, my own?'
+
+'Oh yes! I don't like him,' said Dora. 'Why don't he go?'
+
+'Who, my life?'
+
+'Your friend,' said Dora. 'It isn't any business of his. What a stupid
+he must be!'
+
+'My love!' (There never was anything so coaxing as her childish ways.)
+'He is the best creature!'
+
+'Oh, but we don't want any best creatures!' pouted Dora.
+
+'My dear,' I argued, 'you will soon know him well, and like him of all
+things. And here is my aunt coming soon; and you'll like her of all
+things too, when you know her.'
+
+'No, please don't bring her!' said Dora, giving me a horrified
+little kiss, and folding her hands. 'Don't. I know she's a naughty,
+mischief-making old thing! Don't let her come here, Doady!' which was a
+corruption of David.
+
+Remonstrance was of no use, then; so I laughed, and admired, and was
+very much in love and very happy; and she showed me Jip's new trick of
+standing on his hind legs in a corner--which he did for about the space
+of a flash of lightning, and then fell down--and I don't know how long I
+should have stayed there, oblivious of Traddles, if Miss Lavinia had not
+come in to take me away. Miss Lavinia was very fond of Dora (she told
+me Dora was exactly like what she had been herself at her age--she must
+have altered a good deal), and she treated Dora just as if she had been
+a toy. I wanted to persuade Dora to come and see Traddles, but on my
+proposing it she ran off to her own room and locked herself in; so I
+went to Traddles without her, and walked away with him on air.
+
+'Nothing could be more satisfactory,' said Traddles; 'and they are very
+agreeable old ladies, I am sure. I shouldn't be at all surprised if you
+were to be married years before me, Copperfield.'
+
+'Does your Sophy play on any instrument, Traddles?' I inquired, in the
+pride of my heart.
+
+'She knows enough of the piano to teach it to her little sisters,' said
+Traddles.
+
+'Does she sing at all?' I asked.
+
+'Why, she sings ballads, sometimes, to freshen up the others a little
+when they're out of spirits,' said Traddles. 'Nothing scientific.'
+
+'She doesn't sing to the guitar?' said I.
+
+'Oh dear no!' said Traddles.
+
+'Paint at all?'
+
+'Not at all,' said Traddles.
+
+I promised Traddles that he should hear Dora sing, and see some of her
+flower-painting. He said he should like it very much, and we went home
+arm in arm in great good humour and delight. I encouraged him to talk
+about Sophy, on the way; which he did with a loving reliance on her
+that I very much admired. I compared her in my mind with Dora, with
+considerable inward satisfaction; but I candidly admitted to myself that
+she seemed to be an excellent kind of girl for Traddles, too.
+
+Of course my aunt was immediately made acquainted with the successful
+issue of the conference, and with all that had been said and done in the
+course of it. She was happy to see me so happy, and promised to call on
+Dora's aunts without loss of time. But she took such a long walk up and
+down our rooms that night, while I was writing to Agnes, that I began to
+think she meant to walk till morning.
+
+My letter to Agnes was a fervent and grateful one, narrating all the
+good effects that had resulted from my following her advice. She wrote,
+by return of post, to me. Her letter was hopeful, earnest, and cheerful.
+She was always cheerful from that time.
+
+I had my hands more full than ever, now. My daily journeys to Highgate
+considered, Putney was a long way off; and I naturally wanted to go
+there as often as I could. The proposed tea-drinkings being quite
+impracticable, I compounded with Miss Lavinia for permission to visit
+every Saturday afternoon, without detriment to my privileged Sundays.
+So, the close of every week was a delicious time for me; and I got
+through the rest of the week by looking forward to it.
+
+I was wonderfully relieved to find that my aunt and Dora's aunts
+rubbed on, all things considered, much more smoothly than I could have
+expected. My aunt made her promised visit within a few days of the
+conference; and within a few more days, Dora's aunts called upon her,
+in due state and form. Similar but more friendly exchanges took place
+afterwards, usually at intervals of three or four weeks. I know that my
+aunt distressed Dora's aunts very much, by utterly setting at naught the
+dignity of fly-conveyance, and walking out to Putney at extraordinary
+times, as shortly after breakfast or just before tea; likewise by
+wearing her bonnet in any manner that happened to be comfortable to her
+head, without at all deferring to the prejudices of civilization on that
+subject. But Dora's aunts soon agreed to regard my aunt as an eccentric
+and somewhat masculine lady, with a strong understanding; and although
+my aunt occasionally ruffled the feathers of Dora's aunts, by expressing
+heretical opinions on various points of ceremony, she loved me too
+well not to sacrifice some of her little peculiarities to the general
+harmony.
+
+The only member of our small society who positively refused to adapt
+himself to circumstances, was Jip. He never saw my aunt without
+immediately displaying every tooth in his head, retiring under a chair,
+and growling incessantly: with now and then a doleful howl, as if she
+really were too much for his feelings. All kinds of treatment were tried
+with him, coaxing, scolding, slapping, bringing him to Buckingham
+Street (where he instantly dashed at the two cats, to the terror of all
+beholders); but he never could prevail upon himself to bear my
+aunt's society. He would sometimes think he had got the better of his
+objection, and be amiable for a few minutes; and then would put up his
+snub nose, and howl to that extent, that there was nothing for it but
+to blind him and put him in the plate-warmer. At length, Dora regularly
+muffled him in a towel and shut him up there, whenever my aunt was
+reported at the door.
+
+One thing troubled me much, after we had fallen into this quiet train.
+It was, that Dora seemed by one consent to be regarded like a pretty toy
+or plaything. My aunt, with whom she gradually became familiar, always
+called her Little Blossom; and the pleasure of Miss Lavinia's life was
+to wait upon her, curl her hair, make ornaments for her, and treat her
+like a pet child. What Miss Lavinia did, her sister did as a matter of
+course. It was very odd to me; but they all seemed to treat Dora, in her
+degree, much as Dora treated Jip in his.
+
+I made up my mind to speak to Dora about this; and one day when we were
+out walking (for we were licensed by Miss Lavinia, after a while, to
+go out walking by ourselves), I said to her that I wished she could get
+them to behave towards her differently.
+
+'Because you know, my darling,' I remonstrated, 'you are not a child.'
+
+'There!' said Dora. 'Now you're going to be cross!'
+
+'Cross, my love?'
+
+'I am sure they're very kind to me,' said Dora, 'and I am very happy--'
+
+'Well! But my dearest life!' said I, 'you might be very happy, and yet
+be treated rationally.'
+
+Dora gave me a reproachful look--the prettiest look!--and then began to
+sob, saying, if I didn't like her, why had I ever wanted so much to be
+engaged to her? And why didn't I go away, now, if I couldn't bear her?
+
+What could I do, but kiss away her tears, and tell her how I doted on
+her, after that!
+
+'I am sure I am very affectionate,' said Dora; 'you oughtn't to be cruel
+to me, Doady!'
+
+'Cruel, my precious love! As if I would--or could--be cruel to you, for
+the world!'
+
+'Then don't find fault with me,' said Dora, making a rosebud of her
+mouth; 'and I'll be good.'
+
+I was charmed by her presently asking me, of her own accord, to give
+her that cookery-book I had once spoken of, and to show her how to keep
+accounts as I had once promised I would. I brought the volume with me on
+my next visit (I got it prettily bound, first, to make it look less dry
+and more inviting); and as we strolled about the Common, I showed her an
+old housekeeping-book of my aunt's, and gave her a set of tablets, and
+a pretty little pencil-case and box of leads, to practise housekeeping
+with.
+
+But the cookery-book made Dora's head ache, and the figures made her
+cry. They wouldn't add up, she said. So she rubbed them out, and drew
+little nosegays and likenesses of me and Jip, all over the tablets.
+
+Then I playfully tried verbal instruction in domestic matters, as we
+walked about on a Saturday afternoon. Sometimes, for example, when we
+passed a butcher's shop, I would say:
+
+'Now suppose, my pet, that we were married, and you were going to buy a
+shoulder of mutton for dinner, would you know how to buy it?'
+
+My pretty little Dora's face would fall, and she would make her mouth
+into a bud again, as if she would very much prefer to shut mine with a
+kiss.
+
+'Would you know how to buy it, my darling?' I would repeat, perhaps, if
+I were very inflexible.
+
+Dora would think a little, and then reply, perhaps, with great triumph:
+
+'Why, the butcher would know how to sell it, and what need I know? Oh,
+you silly boy!'
+
+So, when I once asked Dora, with an eye to the cookery-book, what she
+would do, if we were married, and I were to say I should like a nice
+Irish stew, she replied that she would tell the servant to make it; and
+then clapped her little hands together across my arm, and laughed in
+such a charming manner that she was more delightful than ever.
+
+Consequently, the principal use to which the cookery-book was devoted,
+was being put down in the corner for Jip to stand upon. But Dora was so
+pleased, when she had trained him to stand upon it without offering to
+come off, and at the same time to hold the pencil-case in his mouth,
+that I was very glad I had bought it.
+
+And we fell back on the guitar-case, and the flower-painting, and the
+songs about never leaving off dancing, Ta ra la! and were as happy as
+the week was long. I occasionally wished I could venture to hint to Miss
+Lavinia, that she treated the darling of my heart a little too much like
+a plaything; and I sometimes awoke, as it were, wondering to find that
+I had fallen into the general fault, and treated her like a plaything
+too--but not often.
+
+
+
+CHAPTER 42. MISCHIEF
+
+I feel as if it were not for me to record, even though this manuscript
+is intended for no eyes but mine, how hard I worked at that tremendous
+short-hand, and all improvement appertaining to it, in my sense of
+responsibility to Dora and her aunts. I will only add, to what I have
+already written of my perseverance at this time of my life, and of a
+patient and continuous energy which then began to be matured within me,
+and which I know to be the strong part of my character, if it have any
+strength at all, that there, on looking back, I find the source of my
+success. I have been very fortunate in worldly matters; many men have
+worked much harder, and not succeeded half so well; but I never could
+have done what I have done, without the habits of punctuality, order,
+and diligence, without the determination to concentrate myself on one
+object at a time, no matter how quickly its successor should come upon
+its heels, which I then formed. Heaven knows I write this, in no spirit
+of self-laudation. The man who reviews his own life, as I do mine,
+in going on here, from page to page, had need to have been a good man
+indeed, if he would be spared the sharp consciousness of many talents
+neglected, many opportunities wasted, many erratic and perverted
+feelings constantly at war within his breast, and defeating him. I
+do not hold one natural gift, I dare say, that I have not abused. My
+meaning simply is, that whatever I have tried to do in life, I have
+tried with all my heart to do well; that whatever I have devoted myself
+to, I have devoted myself to completely; that in great aims and in
+small, I have always been thoroughly in earnest. I have never believed
+it possible that any natural or improved ability can claim immunity from
+the companionship of the steady, plain, hard-working qualities, and
+hope to gain its end. There is no such thing as such fulfilment on this
+earth. Some happy talent, and some fortunate opportunity, may form the
+two sides of the ladder on which some men mount, but the rounds of that
+ladder must be made of stuff to stand wear and tear; and there is no
+substitute for thorough-going, ardent, and sincere earnestness. Never
+to put one hand to anything, on which I could throw my whole self; and
+never to affect depreciation of my work, whatever it was; I find, now,
+to have been my golden rules.
+
+How much of the practice I have just reduced to precept, I owe to Agnes,
+I will not repeat here. My narrative proceeds to Agnes, with a thankful
+love.
+
+She came on a visit of a fortnight to the Doctor's. Mr. Wickfield was
+the Doctor's old friend, and the Doctor wished to talk with him, and
+do him good. It had been matter of conversation with Agnes when she was
+last in town, and this visit was the result. She and her father came
+together. I was not much surprised to hear from her that she had engaged
+to find a lodging in the neighbourhood for Mrs. Heep, whose rheumatic
+complaint required change of air, and who would be charmed to have it in
+such company. Neither was I surprised when, on the very next day, Uriah,
+like a dutiful son, brought his worthy mother to take possession.
+
+'You see, Master Copperfield,' said he, as he forced himself upon my
+company for a turn in the Doctor's garden, 'where a person loves, a
+person is a little jealous--leastways, anxious to keep an eye on the
+beloved one.'
+
+'Of whom are you jealous, now?' said I.
+
+'Thanks to you, Master Copperfield,' he returned, 'of no one in
+particular just at present--no male person, at least.'
+
+'Do you mean that you are jealous of a female person?'
+
+He gave me a sidelong glance out of his sinister red eyes, and laughed.
+
+'Really, Master Copperfield,' he said, '--I should say Mister, but I
+know you'll excuse the abit I've got into--you're so insinuating, that
+you draw me like a corkscrew! Well, I don't mind telling you,' putting
+his fish-like hand on mine, 'I'm not a lady's man in general, sir, and I
+never was, with Mrs. Strong.'
+
+His eyes looked green now, as they watched mine with a rascally cunning.
+
+'What do you mean?' said I.
+
+'Why, though I am a lawyer, Master Copperfield,' he replied, with a dry
+grin, 'I mean, just at present, what I say.'
+
+'And what do you mean by your look?' I retorted, quietly.
+
+'By my look? Dear me, Copperfield, that's sharp practice! What do I mean
+by my look?'
+
+'Yes,' said I. 'By your look.'
+
+He seemed very much amused, and laughed as heartily as it was in his
+nature to laugh. After some scraping of his chin with his hand, he went
+on to say, with his eyes cast downward--still scraping, very slowly:
+
+'When I was but an umble clerk, she always looked down upon me. She was
+for ever having my Agnes backwards and forwards at her ouse, and she was
+for ever being a friend to you, Master Copperfield; but I was too far
+beneath her, myself, to be noticed.'
+
+'Well?' said I; 'suppose you were!'
+
+'--And beneath him too,' pursued Uriah, very distinctly, and in a
+meditative tone of voice, as he continued to scrape his chin.
+
+'Don't you know the Doctor better,' said I, 'than to suppose him
+conscious of your existence, when you were not before him?'
+
+He directed his eyes at me in that sidelong glance again, and he made
+his face very lantern-jawed, for the greater convenience of scraping, as
+he answered:
+
+'Oh dear, I am not referring to the Doctor! Oh no, poor man! I mean Mr.
+Maldon!'
+
+My heart quite died within me. All my old doubts and apprehensions on
+that subject, all the Doctor's happiness and peace, all the mingled
+possibilities of innocence and compromise, that I could not unravel, I
+saw, in a moment, at the mercy of this fellow's twisting.
+
+'He never could come into the office, without ordering and shoving me
+about,' said Uriah. 'One of your fine gentlemen he was! I was very meek
+and umble--and I am. But I didn't like that sort of thing--and I don't!'
+
+He left off scraping his chin, and sucked in his cheeks until they
+seemed to meet inside; keeping his sidelong glance upon me all the
+while.
+
+'She is one of your lovely women, she is,' he pursued, when he had
+slowly restored his face to its natural form; 'and ready to be no friend
+to such as me, I know. She's just the person as would put my Agnes up
+to higher sort of game. Now, I ain't one of your lady's men, Master
+Copperfield; but I've had eyes in my ed, a pretty long time back. We
+umble ones have got eyes, mostly speaking--and we look out of 'em.'
+
+I endeavoured to appear unconscious and not disquieted, but, I saw in
+his face, with poor success.
+
+'Now, I'm not a-going to let myself be run down, Copperfield,' he
+continued, raising that part of his countenance, where his red eyebrows
+would have been if he had had any, with malignant triumph, 'and I shall
+do what I can to put a stop to this friendship. I don't approve of it.
+I don't mind acknowledging to you that I've got rather a grudging
+disposition, and want to keep off all intruders. I ain't a-going, if I
+know it, to run the risk of being plotted against.'
+
+'You are always plotting, and delude yourself into the belief that
+everybody else is doing the like, I think,' said I.
+
+'Perhaps so, Master Copperfield,' he replied. 'But I've got a motive, as
+my fellow-partner used to say; and I go at it tooth and nail. I mustn't
+be put upon, as a numble person, too much. I can't allow people in my
+way. Really they must come out of the cart, Master Copperfield!'
+
+'I don't understand you,' said I.
+
+'Don't you, though?' he returned, with one of his jerks. 'I'm astonished
+at that, Master Copperfield, you being usually so quick! I'll try to be
+plainer, another time.---Is that Mr. Maldon a-norseback, ringing at the
+gate, sir?'
+
+'It looks like him,' I replied, as carelessly as I could.
+
+Uriah stopped short, put his hands between his great knobs of knees, and
+doubled himself up with laughter. With perfectly silent laughter. Not
+a sound escaped from him. I was so repelled by his odious behaviour,
+particularly by this concluding instance, that I turned away without any
+ceremony; and left him doubled up in the middle of the garden, like a
+scarecrow in want of support.
+
+It was not on that evening; but, as I well remember, on the next evening
+but one, which was a Sunday; that I took Agnes to see Dora. I had
+arranged the visit, beforehand, with Miss Lavinia; and Agnes was
+expected to tea.
+
+I was in a flutter of pride and anxiety; pride in my dear little
+betrothed, and anxiety that Agnes should like her. All the way to
+Putney, Agnes being inside the stage-coach, and I outside, I pictured
+Dora to myself in every one of the pretty looks I knew so well; now
+making up my mind that I should like her to look exactly as she looked
+at such a time, and then doubting whether I should not prefer her
+looking as she looked at such another time; and almost worrying myself
+into a fever about it.
+
+I was troubled by no doubt of her being very pretty, in any case; but
+it fell out that I had never seen her look so well. She was not in the
+drawing-room when I presented Agnes to her little aunts, but was shyly
+keeping out of the way. I knew where to look for her, now; and sure
+enough I found her stopping her ears again, behind the same dull old
+door.
+
+At first she wouldn't come at all; and then she pleaded for five minutes
+by my watch. When at length she put her arm through mine, to be taken
+to the drawing-room, her charming little face was flushed, and had never
+been so pretty. But, when we went into the room, and it turned pale, she
+was ten thousand times prettier yet.
+
+Dora was afraid of Agnes. She had told me that she knew Agnes was
+'too clever'. But when she saw her looking at once so cheerful and so
+earnest, and so thoughtful, and so good, she gave a faint little cry of
+pleased surprise, and just put her affectionate arms round Agnes's neck,
+and laid her innocent cheek against her face.
+
+I never was so happy. I never was so pleased as when I saw those two sit
+down together, side by side. As when I saw my little darling looking up
+so naturally to those cordial eyes. As when I saw the tender, beautiful
+regard which Agnes cast upon her.
+
+Miss Lavinia and Miss Clarissa partook, in their way, of my joy. It was
+the pleasantest tea-table in the world. Miss Clarissa presided. I cut
+and handed the sweet seed-cake--the little sisters had a bird-like
+fondness for picking up seeds and pecking at sugar; Miss Lavinia looked
+on with benignant patronage, as if our happy love were all her work; and
+we were perfectly contented with ourselves and one another.
+
+The gentle cheerfulness of Agnes went to all their hearts. Her quiet
+interest in everything that interested Dora; her manner of making
+acquaintance with Jip (who responded instantly); her pleasant way, when
+Dora was ashamed to come over to her usual seat by me; her modest grace
+and ease, eliciting a crowd of blushing little marks of confidence from
+Dora; seemed to make our circle quite complete.
+
+'I am so glad,' said Dora, after tea, 'that you like me. I didn't think
+you would; and I want, more than ever, to be liked, now Julia Mills is
+gone.'
+
+I have omitted to mention it, by the by. Miss Mills had sailed, and Dora
+and I had gone aboard a great East Indiaman at Gravesend to see her;
+and we had had preserved ginger, and guava, and other delicacies of that
+sort for lunch; and we had left Miss Mills weeping on a camp-stool on
+the quarter-deck, with a large new diary under her arm, in which the
+original reflections awakened by the contemplation of Ocean were to be
+recorded under lock and key.
+
+Agnes said she was afraid I must have given her an unpromising
+character; but Dora corrected that directly.
+
+'Oh no!' she said, shaking her curls at me; 'it was all praise. He
+thinks so much of your opinion, that I was quite afraid of it.'
+
+'My good opinion cannot strengthen his attachment to some people whom he
+knows,' said Agnes, with a smile; 'it is not worth their having.'
+
+'But please let me have it,' said Dora, in her coaxing way, 'if you
+can!'
+
+We made merry about Dora's wanting to be liked, and Dora said I was a
+goose, and she didn't like me at any rate, and the short evening flew
+away on gossamer-wings. The time was at hand when the coach was to call
+for us. I was standing alone before the fire, when Dora came stealing
+softly in, to give me that usual precious little kiss before I went.
+
+'Don't you think, if I had had her for a friend a long time ago, Doady,'
+said Dora, her bright eyes shining very brightly, and her little right
+hand idly busying itself with one of the buttons of my coat, 'I might
+have been more clever perhaps?'
+
+'My love!' said I, 'what nonsense!'
+
+'Do you think it is nonsense?' returned Dora, without looking at me.
+'Are you sure it is?'
+
+'Of course I am!' 'I have forgotten,' said Dora, still turning the
+button round and round, 'what relation Agnes is to you, you dear bad
+boy.'
+
+'No blood-relation,' I replied; 'but we were brought up together, like
+brother and sister.'
+
+'I wonder why you ever fell in love with me?' said Dora, beginning on
+another button of my coat.
+
+'Perhaps because I couldn't see you, and not love you, Dora!'
+
+'Suppose you had never seen me at all,' said Dora, going to another
+button.
+
+'Suppose we had never been born!' said I, gaily.
+
+I wondered what she was thinking about, as I glanced in admiring silence
+at the little soft hand travelling up the row of buttons on my coat, and
+at the clustering hair that lay against my breast, and at the lashes of
+her downcast eyes, slightly rising as they followed her idle fingers. At
+length her eyes were lifted up to mine, and she stood on tiptoe to
+give me, more thoughtfully than usual, that precious little kiss--once,
+twice, three times--and went out of the room.
+
+They all came back together within five minutes afterwards, and Dora's
+unusual thoughtfulness was quite gone then. She was laughingly resolved
+to put Jip through the whole of his performances, before the coach came.
+They took some time (not so much on account of their variety, as Jip's
+reluctance), and were still unfinished when it was heard at the door.
+There was a hurried but affectionate parting between Agnes and herself;
+and Dora was to write to Agnes (who was not to mind her letters being
+foolish, she said), and Agnes was to write to Dora; and they had a
+second parting at the coach door, and a third when Dora, in spite of
+the remonstrances of Miss Lavinia, would come running out once more to
+remind Agnes at the coach window about writing, and to shake her curls
+at me on the box.
+
+The stage-coach was to put us down near Covent Garden, where we were
+to take another stage-coach for Highgate. I was impatient for the short
+walk in the interval, that Agnes might praise Dora to me. Ah! what
+praise it was! How lovingly and fervently did it commend the pretty
+creature I had won, with all her artless graces best displayed, to my
+most gentle care! How thoughtfully remind me, yet with no pretence of
+doing so, of the trust in which I held the orphan child!
+
+Never, never, had I loved Dora so deeply and truly, as I loved her that
+night. When we had again alighted, and were walking in the starlight
+along the quiet road that led to the Doctor's house, I told Agnes it was
+her doing.
+
+'When you were sitting by her,' said I, 'you seemed to be no less her
+guardian angel than mine; and you seem so now, Agnes.'
+
+'A poor angel,' she returned, 'but faithful.'
+
+The clear tone of her voice, going straight to my heart, made it natural
+to me to say:
+
+'The cheerfulness that belongs to you, Agnes (and to no one else that
+ever I have seen), is so restored, I have observed today, that I have
+begun to hope you are happier at home?'
+
+'I am happier in myself,' she said; 'I am quite cheerful and
+light-hearted.'
+
+I glanced at the serene face looking upward, and thought it was the
+stars that made it seem so noble.
+
+'There has been no change at home,' said Agnes, after a few moments.
+
+'No fresh reference,' said I, 'to--I wouldn't distress you, Agnes, but I
+cannot help asking--to what we spoke of, when we parted last?'
+
+'No, none,' she answered.
+
+'I have thought so much about it.'
+
+'You must think less about it. Remember that I confide in simple love
+and truth at last. Have no apprehensions for me, Trotwood,' she added,
+after a moment; 'the step you dread my taking, I shall never take.'
+
+Although I think I had never really feared it, in any season of cool
+reflection, it was an unspeakable relief to me to have this assurance
+from her own truthful lips. I told her so, earnestly.
+
+'And when this visit is over,' said I,--'for we may not be alone another
+time,--how long is it likely to be, my dear Agnes, before you come to
+London again?'
+
+'Probably a long time,' she replied; 'I think it will be best--for
+papa's sake--to remain at home. We are not likely to meet often, for
+some time to come; but I shall be a good correspondent of Dora's, and we
+shall frequently hear of one another that way.'
+
+We were now within the little courtyard of the Doctor's cottage. It was
+growing late. There was a light in the window of Mrs. Strong's chamber,
+and Agnes, pointing to it, bade me good night.
+
+'Do not be troubled,' she said, giving me her hand, 'by our misfortunes
+and anxieties. I can be happier in nothing than in your happiness. If
+you can ever give me help, rely upon it I will ask you for it. God
+bless you always!' In her beaming smile, and in these last tones of her
+cheerful voice, I seemed again to see and hear my little Dora in her
+company. I stood awhile, looking through the porch at the stars, with
+a heart full of love and gratitude, and then walked slowly forth. I had
+engaged a bed at a decent alehouse close by, and was going out at the
+gate, when, happening to turn my head, I saw a light in the Doctor's
+study. A half-reproachful fancy came into my mind, that he had been
+working at the Dictionary without my help. With the view of seeing if
+this were so, and, in any case, of bidding him good night, if he were
+yet sitting among his books, I turned back, and going softly across the
+hall, and gently opening the door, looked in.
+
+The first person whom I saw, to my surprise, by the sober light of the
+shaded lamp, was Uriah. He was standing close beside it, with one of
+his skeleton hands over his mouth, and the other resting on the Doctor's
+table. The Doctor sat in his study chair, covering his face with his
+hands. Mr. Wickfield, sorely troubled and distressed, was leaning
+forward, irresolutely touching the Doctor's arm.
+
+For an instant, I supposed that the Doctor was ill. I hastily advanced a
+step under that impression, when I met Uriah's eye, and saw what was the
+matter. I would have withdrawn, but the Doctor made a gesture to detain
+me, and I remained.
+
+'At any rate,' observed Uriah, with a writhe of his ungainly person, 'we
+may keep the door shut. We needn't make it known to ALL the town.'
+
+Saying which, he went on his toes to the door, which I had left open,
+and carefully closed it. He then came back, and took up his former
+position. There was an obtrusive show of compassionate zeal in his voice
+and manner, more intolerable--at least to me--than any demeanour he
+could have assumed.
+
+'I have felt it incumbent upon me, Master Copperfield,' said Uriah, 'to
+point out to Doctor Strong what you and me have already talked about.
+You didn't exactly understand me, though?'
+
+I gave him a look, but no other answer; and, going to my good old
+master, said a few words that I meant to be words of comfort and
+encouragement. He put his hand upon my shoulder, as it had been his
+custom to do when I was quite a little fellow, but did not lift his grey
+head.
+
+'As you didn't understand me, Master Copperfield,' resumed Uriah in
+the same officious manner, 'I may take the liberty of umbly mentioning,
+being among friends, that I have called Doctor Strong's attention to the
+goings-on of Mrs. Strong. It's much against the grain with me, I assure
+you, Copperfield, to be concerned in anything so unpleasant; but really,
+as it is, we're all mixing ourselves up with what oughtn't to be. That
+was what my meaning was, sir, when you didn't understand me.' I wonder
+now, when I recall his leer, that I did not collar him, and try to shake
+the breath out of his body.
+
+'I dare say I didn't make myself very clear,' he went on, 'nor you
+neither. Naturally, we was both of us inclined to give such a subject
+a wide berth. Hows'ever, at last I have made up my mind to speak plain;
+and I have mentioned to Doctor Strong that--did you speak, sir?'
+
+This was to the Doctor, who had moaned. The sound might have touched any
+heart, I thought, but it had no effect upon Uriah's.
+
+'--mentioned to Doctor Strong,' he proceeded, 'that anyone may see that
+Mr. Maldon, and the lovely and agreeable lady as is Doctor Strong's
+wife, are too sweet on one another. Really the time is come (we being at
+present all mixing ourselves up with what oughtn't to be), when Doctor
+Strong must be told that this was full as plain to everybody as the sun,
+before Mr. Maldon went to India; that Mr. Maldon made excuses to come
+back, for nothing else; and that he's always here, for nothing else.
+When you come in, sir, I was just putting it to my fellow-partner,'
+towards whom he turned, 'to say to Doctor Strong upon his word and
+honour, whether he'd ever been of this opinion long ago, or not. Come,
+Mr. Wickfield, sir! Would you be so good as tell us? Yes or no, sir?
+Come, partner!'
+
+'For God's sake, my dear Doctor,' said Mr. Wickfield again laying his
+irresolute hand upon the Doctor's arm, 'don't attach too much weight to
+any suspicions I may have entertained.'
+
+'There!' cried Uriah, shaking his head. 'What a melancholy confirmation:
+ain't it? Him! Such an old friend! Bless your soul, when I was nothing
+but a clerk in his office, Copperfield, I've seen him twenty times, if
+I've seen him once, quite in a taking about it--quite put out, you know
+(and very proper in him as a father; I'm sure I can't blame him), to
+think that Miss Agnes was mixing herself up with what oughtn't to be.'
+
+'My dear Strong,' said Mr. Wickfield in a tremulous voice, 'my good
+friend, I needn't tell you that it has been my vice to look for some one
+master motive in everybody, and to try all actions by one narrow test. I
+may have fallen into such doubts as I have had, through this mistake.'
+
+'You have had doubts, Wickfield,' said the Doctor, without lifting up
+his head. 'You have had doubts.'
+
+'Speak up, fellow-partner,' urged Uriah.
+
+'I had, at one time, certainly,' said Mr. Wickfield. 'I--God forgive
+me--I thought YOU had.'
+
+'No, no, no!' returned the Doctor, in a tone of most pathetic grief.
+'I thought, at one time,' said Mr. Wickfield, 'that you wished to send
+Maldon abroad to effect a desirable separation.'
+
+'No, no, no!' returned the Doctor. 'To give Annie pleasure, by making
+some provision for the companion of her childhood. Nothing else.'
+
+'So I found,' said Mr. Wickfield. 'I couldn't doubt it, when you told
+me so. But I thought--I implore you to remember the narrow construction
+which has been my besetting sin--that, in a case where there was so much
+disparity in point of years--'
+
+'That's the way to put it, you see, Master Copperfield!' observed Uriah,
+with fawning and offensive pity.
+
+'--a lady of such youth, and such attractions, however real her
+respect for you, might have been influenced in marrying, by worldly
+considerations only. I make no allowance for innumerable feelings
+and circumstances that may have all tended to good. For Heaven's sake
+remember that!'
+
+'How kind he puts it!' said Uriah, shaking his head.
+
+'Always observing her from one point of view,' said Mr. Wickfield; 'but
+by all that is dear to you, my old friend, I entreat you to consider
+what it was; I am forced to confess now, having no escape-'
+
+'No! There's no way out of it, Mr. Wickfield, sir,' observed Uriah,
+'when it's got to this.'
+
+'--that I did,' said Mr. Wickfield, glancing helplessly and distractedly
+at his partner, 'that I did doubt her, and think her wanting in her
+duty to you; and that I did sometimes, if I must say all, feel averse
+to Agnes being in such a familiar relation towards her, as to see what I
+saw, or in my diseased theory fancied that I saw. I never mentioned
+this to anyone. I never meant it to be known to anyone. And though it
+is terrible to you to hear,' said Mr. Wickfield, quite subdued, 'if you
+knew how terrible it is for me to tell, you would feel compassion for
+me!'
+
+The Doctor, in the perfect goodness of his nature, put out his hand. Mr.
+Wickfield held it for a little while in his, with his head bowed down.
+
+'I am sure,' said Uriah, writhing himself into the silence like a
+Conger-eel, 'that this is a subject full of unpleasantness to everybody.
+But since we have got so far, I ought to take the liberty of mentioning
+that Copperfield has noticed it too.'
+
+I turned upon him, and asked him how he dared refer to me!
+
+'Oh! it's very kind of you, Copperfield,' returned Uriah, undulating all
+over, 'and we all know what an amiable character yours is; but you know
+that the moment I spoke to you the other night, you knew what I meant.
+You know you knew what I meant, Copperfield. Don't deny it! You deny it
+with the best intentions; but don't do it, Copperfield.'
+
+I saw the mild eye of the good old Doctor turned upon me for a moment,
+and I felt that the confession of my old misgivings and remembrances
+was too plainly written in my face to be overlooked. It was of no use
+raging. I could not undo that. Say what I would, I could not unsay it.
+
+We were silent again, and remained so, until the Doctor rose and walked
+twice or thrice across the room. Presently he returned to where his
+chair stood; and, leaning on the back of it, and occasionally putting
+his handkerchief to his eyes, with a simple honesty that did him more
+honour, to my thinking, than any disguise he could have effected, said:
+
+'I have been much to blame. I believe I have been very much to blame.
+I have exposed one whom I hold in my heart, to trials and aspersions--I
+call them aspersions, even to have been conceived in anybody's inmost
+mind--of which she never, but for me, could have been the object.'
+
+Uriah Heep gave a kind of snivel. I think to express sympathy.
+
+'Of which my Annie,' said the Doctor, 'never, but for me, could have
+been the object. Gentlemen, I am old now, as you know; I do not feel,
+tonight, that I have much to live for. But my life--my Life--upon the
+truth and honour of the dear lady who has been the subject of this
+conversation!'
+
+I do not think that the best embodiment of chivalry, the realization of
+the handsomest and most romantic figure ever imagined by painter, could
+have said this, with a more impressive and affecting dignity than the
+plain old Doctor did.
+
+'But I am not prepared,' he went on, 'to deny--perhaps I may have been,
+without knowing it, in some degree prepared to admit--that I may have
+unwittingly ensnared that lady into an unhappy marriage. I am a man
+quite unaccustomed to observe; and I cannot but believe that the
+observation of several people, of different ages and positions, all too
+plainly tending in one direction (and that so natural), is better than
+mine.'
+
+I had often admired, as I have elsewhere described, his benignant manner
+towards his youthful wife; but the respectful tenderness he manifested
+in every reference to her on this occasion, and the almost reverential
+manner in which he put away from him the lightest doubt of her
+integrity, exalted him, in my eyes, beyond description.
+
+'I married that lady,' said the Doctor, 'when she was extremely young. I
+took her to myself when her character was scarcely formed. So far as it
+was developed, it had been my happiness to form it. I knew her father
+well. I knew her well. I had taught her what I could, for the love of
+all her beautiful and virtuous qualities. If I did her wrong; as I fear
+I did, in taking advantage (but I never meant it) of her gratitude and
+her affection; I ask pardon of that lady, in my heart!'
+
+He walked across the room, and came back to the same place; holding
+the chair with a grasp that trembled, like his subdued voice, in its
+earnestness.
+
+'I regarded myself as a refuge, for her, from the dangers and
+vicissitudes of life. I persuaded myself that, unequal though we were in
+years, she would live tranquilly and contentedly with me. I did not shut
+out of my consideration the time when I should leave her free, and still
+young and still beautiful, but with her judgement more matured--no,
+gentlemen--upon my truth!'
+
+His homely figure seemed to be lightened up by his fidelity and
+generosity. Every word he uttered had a force that no other grace could
+have imparted to it.
+
+'My life with this lady has been very happy. Until tonight, I have
+had uninterrupted occasion to bless the day on which I did her great
+injustice.'
+
+His voice, more and more faltering in the utterance of these words,
+stopped for a few moments; then he went on:
+
+'Once awakened from my dream--I have been a poor dreamer, in one way or
+other, all my life--I see how natural it is that she should have some
+regretful feeling towards her old companion and her equal. That she does
+regard him with some innocent regret, with some blameless thoughts of
+what might have been, but for me, is, I fear, too true. Much that I have
+seen, but not noted, has come back upon me with new meaning, during
+this last trying hour. But, beyond this, gentlemen, the dear lady's name
+never must be coupled with a word, a breath, of doubt.'
+
+For a little while, his eye kindled and his voice was firm; for a little
+while he was again silent. Presently, he proceeded as before:
+
+'It only remains for me, to bear the knowledge of the unhappiness I have
+occasioned, as submissively as I can. It is she who should reproach; not
+I. To save her from misconstruction, cruel misconstruction, that even my
+friends have not been able to avoid, becomes my duty. The more retired
+we live, the better I shall discharge it. And when the time comes--may
+it come soon, if it be His merciful pleasure!--when my death shall
+release her from constraint, I shall close my eyes upon her honoured
+face, with unbounded confidence and love; and leave her, with no sorrow
+then, to happier and brighter days.'
+
+I could not see him for the tears which his earnestness and goodness,
+so adorned by, and so adorning, the perfect simplicity of his manner,
+brought into my eyes. He had moved to the door, when he added:
+
+'Gentlemen, I have shown you my heart. I am sure you will respect it.
+What we have said tonight is never to be said more. Wickfield, give me
+an old friend's arm upstairs!'
+
+Mr. Wickfield hastened to him. Without interchanging a word they went
+slowly out of the room together, Uriah looking after them.
+
+'Well, Master Copperfield!' said Uriah, meekly turning to me. 'The thing
+hasn't took quite the turn that might have been expected, for the old
+Scholar--what an excellent man!--is as blind as a brickbat; but this
+family's out of the cart, I think!'
+
+I needed but the sound of his voice to be so madly enraged as I never
+was before, and never have been since.
+
+'You villain,' said I, 'what do you mean by entrapping me into your
+schemes? How dare you appeal to me just now, you false rascal, as if we
+had been in discussion together?'
+
+As we stood, front to front, I saw so plainly, in the stealthy
+exultation of his face, what I already so plainly knew; I mean that he
+forced his confidence upon me, expressly to make me miserable, and had
+set a deliberate trap for me in this very matter; that I couldn't bear
+it. The whole of his lank cheek was invitingly before me, and I struck
+it with my open hand with that force that my fingers tingled as if I had
+burnt them.
+
+He caught the hand in his, and we stood in that connexion, looking at
+each other. We stood so, a long time; long enough for me to see the
+white marks of my fingers die out of the deep red of his cheek, and
+leave it a deeper red.
+
+'Copperfield,' he said at length, in a breathless voice, 'have you taken
+leave of your senses?'
+
+'I have taken leave of you,' said I, wresting my hand away. 'You dog,
+I'll know no more of you.'
+
+'Won't you?' said he, constrained by the pain of his cheek to put his
+hand there. 'Perhaps you won't be able to help it. Isn't this ungrateful
+of you, now?'
+
+'I have shown you often enough,' said I, 'that I despise you. I have
+shown you now, more plainly, that I do. Why should I dread your doing
+your worst to all about you? What else do you ever do?'
+
+He perfectly understood this allusion to the considerations that had
+hitherto restrained me in my communications with him. I rather think
+that neither the blow, nor the allusion, would have escaped me, but for
+the assurance I had had from Agnes that night. It is no matter.
+
+There was another long pause. His eyes, as he looked at me, seemed to
+take every shade of colour that could make eyes ugly.
+
+'Copperfield,' he said, removing his hand from his cheek, 'you have
+always gone against me. I know you always used to be against me at Mr.
+Wickfield's.'
+
+'You may think what you like,' said I, still in a towering rage. 'If it
+is not true, so much the worthier you.'
+
+'And yet I always liked you, Copperfield!' he rejoined.
+
+I deigned to make him no reply; and, taking up my hat, was going out to
+bed, when he came between me and the door.
+
+'Copperfield,' he said, 'there must be two parties to a quarrel. I won't
+be one.'
+
+'You may go to the devil!' said I.
+
+'Don't say that!' he replied. 'I know you'll be sorry afterwards. How
+can you make yourself so inferior to me, as to show such a bad spirit?
+But I forgive you.'
+
+'You forgive me!' I repeated disdainfully.
+
+'I do, and you can't help yourself,' replied Uriah. 'To think of your
+going and attacking me, that have always been a friend to you! But there
+can't be a quarrel without two parties, and I won't be one. I will be
+a friend to you, in spite of you. So now you know what you've got to
+expect.'
+
+The necessity of carrying on this dialogue (his part in which was
+very slow; mine very quick) in a low tone, that the house might not be
+disturbed at an unseasonable hour, did not improve my temper; though my
+passion was cooling down. Merely telling him that I should expect from
+him what I always had expected, and had never yet been disappointed in,
+I opened the door upon him, as if he had been a great walnut put there
+to be cracked, and went out of the house. But he slept out of the house
+too, at his mother's lodging; and before I had gone many hundred yards,
+came up with me.
+
+'You know, Copperfield,' he said, in my ear (I did not turn my head),
+'you're in quite a wrong position'; which I felt to be true, and that
+made me chafe the more; 'you can't make this a brave thing, and you
+can't help being forgiven. I don't intend to mention it to mother, nor
+to any living soul. I'm determined to forgive you. But I do wonder
+that you should lift your hand against a person that you knew to be so
+umble!'
+
+I felt only less mean than he. He knew me better than I knew myself. If
+he had retorted or openly exasperated me, it would have been a relief
+and a justification; but he had put me on a slow fire, on which I lay
+tormented half the night.
+
+In the morning, when I came out, the early church-bell was ringing,
+and he was walking up and down with his mother. He addressed me as if
+nothing had happened, and I could do no less than reply. I had struck
+him hard enough to give him the toothache, I suppose. At all events
+his face was tied up in a black silk handkerchief, which, with his hat
+perched on the top of it, was far from improving his appearance. I heard
+that he went to a dentist's in London on the Monday morning, and had a
+tooth out. I hope it was a double one.
+
+The Doctor gave out that he was not quite well; and remained alone, for
+a considerable part of every day, during the remainder of the visit.
+Agnes and her father had been gone a week, before we resumed our usual
+work. On the day preceding its resumption, the Doctor gave me with his
+own hands a folded note not sealed. It was addressed to myself; and laid
+an injunction on me, in a few affectionate words, never to refer to the
+subject of that evening. I had confided it to my aunt, but to no
+one else. It was not a subject I could discuss with Agnes, and Agnes
+certainly had not the least suspicion of what had passed.
+
+Neither, I felt convinced, had Mrs. Strong then. Several weeks elapsed
+before I saw the least change in her. It came on slowly, like a cloud
+when there is no wind. At first, she seemed to wonder at the gentle
+compassion with which the Doctor spoke to her, and at his wish that she
+should have her mother with her, to relieve the dull monotony of her
+life. Often, when we were at work, and she was sitting by, I would see
+her pausing and looking at him with that memorable face. Afterwards, I
+sometimes observed her rise, with her eyes full of tears, and go out
+of the room. Gradually, an unhappy shadow fell upon her beauty, and
+deepened every day. Mrs. Markleham was a regular inmate of the cottage
+then; but she talked and talked, and saw nothing.
+
+As this change stole on Annie, once like sunshine in the Doctor's house,
+the Doctor became older in appearance, and more grave; but the sweetness
+of his temper, the placid kindness of his manner, and his benevolent
+solicitude for her, if they were capable of any increase, were
+increased. I saw him once, early on the morning of her birthday, when
+she came to sit in the window while we were at work (which she had
+always done, but now began to do with a timid and uncertain air that I
+thought very touching), take her forehead between his hands, kiss it,
+and go hurriedly away, too much moved to remain. I saw her stand where
+he had left her, like a statue; and then bend down her head, and clasp
+her hands, and weep, I cannot say how sorrowfully.
+
+Sometimes, after that, I fancied that she tried to speak even to me,
+in intervals when we were left alone. But she never uttered a word. The
+Doctor always had some new project for her participating in amusements
+away from home, with her mother; and Mrs. Markleham, who was very fond
+of amusements, and very easily dissatisfied with anything else, entered
+into them with great good-will, and was loud in her commendations. But
+Annie, in a spiritless unhappy way, only went whither she was led, and
+seemed to have no care for anything.
+
+I did not know what to think. Neither did my aunt; who must have walked,
+at various times, a hundred miles in her uncertainty. What was strangest
+of all was, that the only real relief which seemed to make its way into
+the secret region of this domestic unhappiness, made its way there in
+the person of Mr. Dick.
+
+What his thoughts were on the subject, or what his observation was, I am
+as unable to explain, as I dare say he would have been to assist me in
+the task. But, as I have recorded in the narrative of my school days,
+his veneration for the Doctor was unbounded; and there is a subtlety of
+perception in real attachment, even when it is borne towards man by one
+of the lower animals, which leaves the highest intellect behind. To this
+mind of the heart, if I may call it so, in Mr. Dick, some bright ray of
+the truth shot straight.
+
+He had proudly resumed his privilege, in many of his spare hours,
+of walking up and down the garden with the Doctor; as he had been
+accustomed to pace up and down The Doctor's Walk at Canterbury. But
+matters were no sooner in this state, than he devoted all his spare time
+(and got up earlier to make it more) to these perambulations. If he had
+never been so happy as when the Doctor read that marvellous performance,
+the Dictionary, to him; he was now quite miserable unless the Doctor
+pulled it out of his pocket, and began. When the Doctor and I were
+engaged, he now fell into the custom of walking up and down with Mrs.
+Strong, and helping her to trim her favourite flowers, or weed the
+beds. I dare say he rarely spoke a dozen words in an hour: but his quiet
+interest, and his wistful face, found immediate response in both their
+breasts; each knew that the other liked him, and that he loved both; and
+he became what no one else could be--a link between them.
+
+When I think of him, with his impenetrably wise face, walking up and
+down with the Doctor, delighted to be battered by the hard words in the
+Dictionary; when I think of him carrying huge watering-pots after Annie;
+kneeling down, in very paws of gloves, at patient microscopic work among
+the little leaves; expressing as no philosopher could have expressed,
+in everything he did, a delicate desire to be her friend; showering
+sympathy, trustfulness, and affection, out of every hole in the
+watering-pot; when I think of him never wandering in that better mind
+of his to which unhappiness addressed itself, never bringing the
+unfortunate King Charles into the garden, never wavering in his grateful
+service, never diverted from his knowledge that there was something
+wrong, or from his wish to set it right--I really feel almost ashamed
+of having known that he was not quite in his wits, taking account of the
+utmost I have done with mine.
+
+'Nobody but myself, Trot, knows what that man is!' my aunt would proudly
+remark, when we conversed about it. 'Dick will distinguish himself yet!'
+
+I must refer to one other topic before I close this chapter. While the
+visit at the Doctor's was still in progress, I observed that the postman
+brought two or three letters every morning for Uriah Heep, who remained
+at Highgate until the rest went back, it being a leisure time; and that
+these were always directed in a business-like manner by Mr. Micawber,
+who now assumed a round legal hand. I was glad to infer, from these
+slight premises, that Mr. Micawber was doing well; and consequently was
+much surprised to receive, about this time, the following letter from
+his amiable wife.
+
+
+
+                         'CANTERBURY, Monday Evening.
+
+'You will doubtless be surprised, my dear Mr. Copperfield, to receive
+this communication. Still more so, by its contents. Still more so, by
+the stipulation of implicit confidence which I beg to impose. But my
+feelings as a wife and mother require relief; and as I do not wish to
+consult my family (already obnoxious to the feelings of Mr. Micawber),
+I know no one of whom I can better ask advice than my friend and former
+lodger.
+
+'You may be aware, my dear Mr. Copperfield, that between myself and Mr.
+Micawber (whom I will never desert), there has always been preserved a
+spirit of mutual confidence. Mr. Micawber may have occasionally given
+a bill without consulting me, or he may have misled me as to the period
+when that obligation would become due. This has actually happened.
+But, in general, Mr. Micawber has had no secrets from the bosom of
+affection--I allude to his wife--and has invariably, on our retirement
+to rest, recalled the events of the day.
+
+'You will picture to yourself, my dear Mr. Copperfield, what the
+poignancy of my feelings must be, when I inform you that Mr. Micawber is
+entirely changed. He is reserved. He is secret. His life is a mystery to
+the partner of his joys and sorrows--I again allude to his wife--and if
+I should assure you that beyond knowing that it is passed from morning
+to night at the office, I now know less of it than I do of the man in
+the south, connected with whose mouth the thoughtless children repeat
+an idle tale respecting cold plum porridge, I should adopt a popular
+fallacy to express an actual fact.
+
+'But this is not all. Mr. Micawber is morose. He is severe. He is
+estranged from our eldest son and daughter, he has no pride in his
+twins, he looks with an eye of coldness even on the unoffending stranger
+who last became a member of our circle. The pecuniary means of meeting
+our expenses, kept down to the utmost farthing, are obtained from him
+with great difficulty, and even under fearful threats that he will
+Settle himself (the exact expression); and he inexorably refuses to give
+any explanation whatever of this distracting policy.
+
+'This is hard to bear. This is heart-breaking. If you will advise me,
+knowing my feeble powers such as they are, how you think it will be best
+to exert them in a dilemma so unwonted, you will add another friendly
+obligation to the many you have already rendered me. With loves from the
+children, and a smile from the happily-unconscious stranger, I remain,
+dear Mr. Copperfield,
+
+                              Your afflicted,
+
+                                   'EMMA MICAWBER.'
+
+
+I did not feel justified in giving a wife of Mrs. Micawber's experience
+any other recommendation, than that she should try to reclaim Mr.
+Micawber by patience and kindness (as I knew she would in any case); but
+the letter set me thinking about him very much.
+
+
+
+CHAPTER 43. ANOTHER RETROSPECT
+
+
+Once again, let me pause upon a memorable period of my life. Let me
+stand aside, to see the phantoms of those days go by me, accompanying
+the shadow of myself, in dim procession.
+
+Weeks, months, seasons, pass along. They seem little more than a summer
+day and a winter evening. Now, the Common where I walk with Dora is all
+in bloom, a field of bright gold; and now the unseen heather lies in
+mounds and bunches underneath a covering of snow. In a breath, the river
+that flows through our Sunday walks is sparkling in the summer sun, is
+ruffled by the winter wind, or thickened with drifting heaps of ice.
+Faster than ever river ran towards the sea, it flashes, darkens, and
+rolls away.
+
+Not a thread changes, in the house of the two little bird-like ladies.
+The clock ticks over the fireplace, the weather-glass hangs in the hall.
+Neither clock nor weather-glass is ever right; but we believe in both,
+devoutly.
+
+I have come legally to man's estate. I have attained the dignity of
+twenty-one. But this is a sort of dignity that may be thrust upon one.
+Let me think what I have achieved.
+
+I have tamed that savage stenographic mystery. I make a respectable
+income by it. I am in high repute for my accomplishment in all
+pertaining to the art, and am joined with eleven others in reporting
+the debates in Parliament for a Morning Newspaper. Night after night, I
+record predictions that never come to pass, professions that are never
+fulfilled, explanations that are only meant to mystify. I wallow in
+words. Britannia, that unfortunate female, is always before me, like a
+trussed fowl: skewered through and through with office-pens, and bound
+hand and foot with red tape. I am sufficiently behind the scenes to know
+the worth of political life. I am quite an Infidel about it, and shall
+never be converted.
+
+My dear old Traddles has tried his hand at the same pursuit, but it
+is not in Traddles's way. He is perfectly good-humoured respecting his
+failure, and reminds me that he always did consider himself slow. He has
+occasional employment on the same newspaper, in getting up the facts of
+dry subjects, to be written about and embellished by more fertile minds.
+He is called to the bar; and with admirable industry and self-denial
+has scraped another hundred pounds together, to fee a Conveyancer whose
+chambers he attends. A great deal of very hot port wine was consumed at
+his call; and, considering the figure, I should think the Inner Temple
+must have made a profit by it.
+
+I have come out in another way. I have taken with fear and trembling
+to authorship. I wrote a little something, in secret, and sent it to a
+magazine, and it was published in the magazine. Since then, I have taken
+heart to write a good many trifling pieces. Now, I am regularly paid for
+them. Altogether, I am well off, when I tell my income on the fingers
+of my left hand, I pass the third finger and take in the fourth to the
+middle joint.
+
+We have removed, from Buckingham Street, to a pleasant little cottage
+very near the one I looked at, when my enthusiasm first came on. My
+aunt, however (who has sold the house at Dover, to good advantage), is
+not going to remain here, but intends removing herself to a still more
+tiny cottage close at hand. What does this portend? My marriage? Yes!
+
+Yes! I am going to be married to Dora! Miss Lavinia and Miss Clarissa
+have given their consent; and if ever canary birds were in a flutter,
+they are. Miss Lavinia, self-charged with the superintendence of my
+darling's wardrobe, is constantly cutting out brown-paper cuirasses, and
+differing in opinion from a highly respectable young man, with a long
+bundle, and a yard measure under his arm. A dressmaker, always stabbed
+in the breast with a needle and thread, boards and lodges in the house;
+and seems to me, eating, drinking, or sleeping, never to take her
+thimble off. They make a lay-figure of my dear. They are always sending
+for her to come and try something on. We can't be happy together for
+five minutes in the evening, but some intrusive female knocks at the
+door, and says, 'Oh, if you please, Miss Dora, would you step upstairs!'
+
+Miss Clarissa and my aunt roam all over London, to find out articles of
+furniture for Dora and me to look at. It would be better for them to buy
+the goods at once, without this ceremony of inspection; for, when we go
+to see a kitchen fender and meat-screen, Dora sees a Chinese house for
+Jip, with little bells on the top, and prefers that. And it takes a
+long time to accustom Jip to his new residence, after we have bought it;
+whenever he goes in or out, he makes all the little bells ring, and is
+horribly frightened.
+
+Peggotty comes up to make herself useful, and falls to work immediately.
+Her department appears to be, to clean everything over and over again.
+She rubs everything that can be rubbed, until it shines, like her own
+honest forehead, with perpetual friction. And now it is, that I begin to
+see her solitary brother passing through the dark streets at night, and
+looking, as he goes, among the wandering faces. I never speak to him at
+such an hour. I know too well, as his grave figure passes onward, what
+he seeks, and what he dreads.
+
+Why does Traddles look so important when he calls upon me this afternoon
+in the Commons--where I still occasionally attend, for form's sake, when
+I have time? The realization of my boyish day-dreams is at hand. I am
+going to take out the licence.
+
+It is a little document to do so much; and Traddles contemplates it,
+as it lies upon my desk, half in admiration, half in awe. There are the
+names, in the sweet old visionary connexion, David Copperfield and Dora
+Spenlow; and there, in the corner, is that Parental Institution,
+the Stamp Office, which is so benignantly interested in the various
+transactions of human life, looking down upon our Union; and there is
+the Archbishop of Canterbury invoking a blessing on us in print, and
+doing it as cheap as could possibly be expected.
+
+Nevertheless, I am in a dream, a flustered, happy, hurried dream. I
+can't believe that it is going to be; and yet I can't believe but that
+everyone I pass in the street, must have some kind of perception, that I
+am to be married the day after tomorrow. The Surrogate knows me, when
+I go down to be sworn; and disposes of me easily, as if there were a
+Masonic understanding between us. Traddles is not at all wanted, but is
+in attendance as my general backer.
+
+'I hope the next time you come here, my dear fellow,' I say to Traddles,
+'it will be on the same errand for yourself. And I hope it will be
+soon.'
+
+'Thank you for your good wishes, my dear Copperfield,' he replies. 'I
+hope so too. It's a satisfaction to know that she'll wait for me any
+length of time, and that she really is the dearest girl--'
+
+'When are you to meet her at the coach?' I ask.
+
+'At seven,' says Traddles, looking at his plain old silver watch--the
+very watch he once took a wheel out of, at school, to make a water-mill.
+'That is about Miss Wickfield's time, is it not?'
+
+'A little earlier. Her time is half past eight.' 'I assure you, my dear
+boy,' says Traddles, 'I am almost as pleased as if I were going to
+be married myself, to think that this event is coming to such a happy
+termination. And really the great friendship and consideration of
+personally associating Sophy with the joyful occasion, and inviting
+her to be a bridesmaid in conjunction with Miss Wickfield, demands my
+warmest thanks. I am extremely sensible of it.'
+
+I hear him, and shake hands with him; and we talk, and walk, and dine,
+and so on; but I don't believe it. Nothing is real.
+
+Sophy arrives at the house of Dora's aunts, in due course. She has the
+most agreeable of faces,--not absolutely beautiful, but extraordinarily
+pleasant,--and is one of the most genial, unaffected, frank, engaging
+creatures I have ever seen. Traddles presents her to us with great
+pride; and rubs his hands for ten minutes by the clock, with every
+individual hair upon his head standing on tiptoe, when I congratulate
+him in a corner on his choice.
+
+I have brought Agnes from the Canterbury coach, and her cheerful and
+beautiful face is among us for the second time. Agnes has a great liking
+for Traddles, and it is capital to see them meet, and to observe the
+glory of Traddles as he commends the dearest girl in the world to her
+acquaintance.
+
+Still I don't believe it. We have a delightful evening, and are
+supremely happy; but I don't believe it yet. I can't collect myself. I
+can't check off my happiness as it takes place. I feel in a misty and
+unsettled kind of state; as if I had got up very early in the morning a
+week or two ago, and had never been to bed since. I can't make out when
+yesterday was. I seem to have been carrying the licence about, in my
+pocket, many months.
+
+Next day, too, when we all go in a flock to see the house--our
+house--Dora's and mine--I am quite unable to regard myself as its
+master. I seem to be there, by permission of somebody else. I half
+expect the real master to come home presently, and say he is glad to see
+me. Such a beautiful little house as it is, with everything so bright
+and new; with the flowers on the carpets looking as if freshly gathered,
+and the green leaves on the paper as if they had just come out; with the
+spotless muslin curtains, and the blushing rose-coloured furniture, and
+Dora's garden hat with the blue ribbon--do I remember, now, how I loved
+her in such another hat when I first knew her!--already hanging on its
+little peg; the guitar-case quite at home on its heels in a corner;
+and everybody tumbling over Jip's pagoda, which is much too big for the
+establishment. Another happy evening, quite as unreal as all the rest
+of it, and I steal into the usual room before going away. Dora is not
+there. I suppose they have not done trying on yet. Miss Lavinia peeps
+in, and tells me mysteriously that she will not be long. She is rather
+long, notwithstanding; but by and by I hear a rustling at the door, and
+someone taps.
+
+I say, 'Come in!' but someone taps again.
+
+I go to the door, wondering who it is; there, I meet a pair of bright
+eyes, and a blushing face; they are Dora's eyes and face, and Miss
+Lavinia has dressed her in tomorrow's dress, bonnet and all, for me to
+see. I take my little wife to my heart; and Miss Lavinia gives a little
+scream because I tumble the bonnet, and Dora laughs and cries at once,
+because I am so pleased; and I believe it less than ever.
+
+'Do you think it pretty, Doady?' says Dora.
+
+Pretty! I should rather think I did.
+
+'And are you sure you like me very much?' says Dora.
+
+The topic is fraught with such danger to the bonnet, that Miss Lavinia
+gives another little scream, and begs me to understand that Dora is only
+to be looked at, and on no account to be touched. So Dora stands in a
+delightful state of confusion for a minute or two, to be admired; and
+then takes off her bonnet--looking so natural without it!--and runs away
+with it in her hand; and comes dancing down again in her own familiar
+dress, and asks Jip if I have got a beautiful little wife, and whether
+he'll forgive her for being married, and kneels down to make him stand
+upon the cookery-book, for the last time in her single life.
+
+I go home, more incredulous than ever, to a lodging that I have hard by;
+and get up very early in the morning, to ride to the Highgate road and
+fetch my aunt.
+
+I have never seen my aunt in such state. She is dressed in
+lavender-coloured silk, and has a white bonnet on, and is amazing. Janet
+has dressed her, and is there to look at me. Peggotty is ready to go to
+church, intending to behold the ceremony from the gallery. Mr. Dick,
+who is to give my darling to me at the altar, has had his hair curled.
+Traddles, whom I have taken up by appointment at the turnpike, presents
+a dazzling combination of cream colour and light blue; and both he and
+Mr. Dick have a general effect about them of being all gloves.
+
+No doubt I see this, because I know it is so; but I am astray, and seem
+to see nothing. Nor do I believe anything whatever. Still, as we drive
+along in an open carriage, this fairy marriage is real enough to fill
+me with a sort of wondering pity for the unfortunate people who have
+no part in it, but are sweeping out the shops, and going to their daily
+occupations.
+
+My aunt sits with my hand in hers all the way. When we stop a little way
+short of the church, to put down Peggotty, whom we have brought on the
+box, she gives it a squeeze, and me a kiss.
+
+'God bless you, Trot! My own boy never could be dearer. I think of poor
+dear Baby this morning.' 'So do I. And of all I owe to you, dear aunt.'
+
+'Tut, child!' says my aunt; and gives her hand in overflowing cordiality
+to Traddles, who then gives his to Mr. Dick, who then gives his to me,
+who then gives mine to Traddles, and then we come to the church door.
+
+The church is calm enough, I am sure; but it might be a steam-power loom
+in full action, for any sedative effect it has on me. I am too far gone
+for that.
+
+The rest is all a more or less incoherent dream.
+
+A dream of their coming in with Dora; of the pew-opener arranging us,
+like a drill-sergeant, before the altar rails; of my wondering, even
+then, why pew-openers must always be the most disagreeable females
+procurable, and whether there is any religious dread of a disastrous
+infection of good-humour which renders it indispensable to set those
+vessels of vinegar upon the road to Heaven.
+
+Of the clergyman and clerk appearing; of a few boatmen and some
+other people strolling in; of an ancient mariner behind me, strongly
+flavouring the church with rum; of the service beginning in a deep
+voice, and our all being very attentive.
+
+Of Miss Lavinia, who acts as a semi-auxiliary bridesmaid, being the
+first to cry, and of her doing homage (as I take it) to the memory of
+Pidger, in sobs; of Miss Clarissa applying a smelling-bottle; of Agnes
+taking care of Dora; of my aunt endeavouring to represent herself as
+a model of sternness, with tears rolling down her face; of little Dora
+trembling very much, and making her responses in faint whispers.
+
+Of our kneeling down together, side by side; of Dora's trembling less
+and less, but always clasping Agnes by the hand; of the service being
+got through, quietly and gravely; of our all looking at each other in an
+April state of smiles and tears, when it is over; of my young wife being
+hysterical in the vestry, and crying for her poor papa, her dear papa.
+
+Of her soon cheering up again, and our signing the register all round.
+Of my going into the gallery for Peggotty to bring her to sign it; of
+Peggotty's hugging me in a corner, and telling me she saw my own dear
+mother married; of its being over, and our going away.
+
+Of my walking so proudly and lovingly down the aisle with my sweet wife
+upon my arm, through a mist of half-seen people, pulpits, monuments,
+pews, fonts, organs, and church windows, in which there flutter faint
+airs of association with my childish church at home, so long ago.
+
+Of their whispering, as we pass, what a youthful couple we are, and what
+a pretty little wife she is. Of our all being so merry and talkative in
+the carriage going back. Of Sophy telling us that when she saw Traddles
+(whom I had entrusted with the licence) asked for it, she almost
+fainted, having been convinced that he would contrive to lose it, or to
+have his pocket picked. Of Agnes laughing gaily; and of Dora being so
+fond of Agnes that she will not be separated from her, but still keeps
+her hand.
+
+Of there being a breakfast, with abundance of things, pretty and
+substantial, to eat and drink, whereof I partake, as I should do in any
+other dream, without the least perception of their flavour; eating
+and drinking, as I may say, nothing but love and marriage, and no more
+believing in the viands than in anything else.
+
+Of my making a speech in the same dreamy fashion, without having an idea
+of what I want to say, beyond such as may be comprehended in the full
+conviction that I haven't said it. Of our being very sociably and simply
+happy (always in a dream though); and of Jip's having wedding cake, and
+its not agreeing with him afterwards.
+
+Of the pair of hired post-horses being ready, and of Dora's going away
+to change her dress. Of my aunt and Miss Clarissa remaining with us; and
+our walking in the garden; and my aunt, who has made quite a speech at
+breakfast touching Dora's aunts, being mightily amused with herself, but
+a little proud of it too.
+
+Of Dora's being ready, and of Miss Lavinia's hovering about her, loth to
+lose the pretty toy that has given her so much pleasant occupation.
+Of Dora's making a long series of surprised discoveries that she
+has forgotten all sorts of little things; and of everybody's running
+everywhere to fetch them.
+
+Of their all closing about Dora, when at last she begins to say
+good-bye, looking, with their bright colours and ribbons, like a bed
+of flowers. Of my darling being almost smothered among the flowers, and
+coming out, laughing and crying both together, to my jealous arms.
+
+Of my wanting to carry Jip (who is to go along with us), and Dora's
+saying no, that she must carry him, or else he'll think she don't like
+him any more, now she is married, and will break his heart. Of our
+going, arm in arm, and Dora stopping and looking back, and saying, 'If
+I have ever been cross or ungrateful to anybody, don't remember it!' and
+bursting into tears.
+
+Of her waving her little hand, and our going away once more. Of her
+once more stopping, and looking back, and hurrying to Agnes, and giving
+Agnes, above all the others, her last kisses and farewells.
+
+We drive away together, and I awake from the dream. I believe it at
+last. It is my dear, dear, little wife beside me, whom I love so well!
+
+'Are you happy now, you foolish boy?' says Dora, 'and sure you don't
+repent?'
+
+
+I have stood aside to see the phantoms of those days go by me. They are
+gone, and I resume the journey of my story.
+
+
+
+CHAPTER 44. OUR HOUSEKEEPING
+
+
+It was a strange condition of things, the honeymoon being over, and the
+bridesmaids gone home, when I found myself sitting down in my own
+small house with Dora; quite thrown out of employment, as I may say, in
+respect of the delicious old occupation of making love.
+
+It seemed such an extraordinary thing to have Dora always there. It was
+so unaccountable not to be obliged to go out to see her, not to have any
+occasion to be tormenting myself about her, not to have to write to her,
+not to be scheming and devising opportunities of being alone with her.
+Sometimes of an evening, when I looked up from my writing, and saw her
+seated opposite, I would lean back in my chair, and think how queer it
+was that there we were, alone together as a matter of course--nobody's
+business any more--all the romance of our engagement put away upon a
+shelf, to rust--no one to please but one another--one another to please,
+for life.
+
+When there was a debate, and I was kept out very late, it seemed so
+strange to me, as I was walking home, to think that Dora was at home! It
+was such a wonderful thing, at first, to have her coming softly down to
+talk to me as I ate my supper. It was such a stupendous thing to know
+for certain that she put her hair in papers. It was altogether such an
+astonishing event to see her do it!
+
+I doubt whether two young birds could have known less about keeping
+house, than I and my pretty Dora did. We had a servant, of course. She
+kept house for us. I have still a latent belief that she must have been
+Mrs. Crupp's daughter in disguise, we had such an awful time of it with
+Mary Anne.
+
+Her name was Paragon. Her nature was represented to us, when we engaged
+her, as being feebly expressed in her name. She had a written character,
+as large as a proclamation; and, according to this document, could do
+everything of a domestic nature that ever I heard of, and a great many
+things that I never did hear of. She was a woman in the prime of life;
+of a severe countenance; and subject (particularly in the arms) to
+a sort of perpetual measles or fiery rash. She had a cousin in the
+Life-Guards, with such long legs that he looked like the afternoon
+shadow of somebody else. His shell-jacket was as much too little for him
+as he was too big for the premises. He made the cottage smaller than it
+need have been, by being so very much out of proportion to it. Besides
+which, the walls were not thick, and, whenever he passed the evening at
+our house, we always knew of it by hearing one continual growl in the
+kitchen.
+
+Our treasure was warranted sober and honest. I am therefore willing to
+believe that she was in a fit when we found her under the boiler; and
+that the deficient tea-spoons were attributable to the dustman.
+
+But she preyed upon our minds dreadfully. We felt our inexperience, and
+were unable to help ourselves. We should have been at her mercy, if she
+had had any; but she was a remorseless woman, and had none. She was the
+cause of our first little quarrel.
+
+'My dearest life,' I said one day to Dora, 'do you think Mary Anne has
+any idea of time?'
+
+'Why, Doady?' inquired Dora, looking up, innocently, from her drawing.
+
+'My love, because it's five, and we were to have dined at four.'
+
+Dora glanced wistfully at the clock, and hinted that she thought it was
+too fast.
+
+'On the contrary, my love,' said I, referring to my watch, 'it's a few
+minutes too slow.'
+
+My little wife came and sat upon my knee, to coax me to be quiet, and
+drew a line with her pencil down the middle of my nose; but I couldn't
+dine off that, though it was very agreeable.
+
+'Don't you think, my dear,' said I, 'it would be better for you to
+remonstrate with Mary Anne?'
+
+'Oh no, please! I couldn't, Doady!' said Dora.
+
+'Why not, my love?' I gently asked.
+
+'Oh, because I am such a little goose,' said Dora, 'and she knows I am!'
+
+I thought this sentiment so incompatible with the establishment of any
+system of check on Mary Anne, that I frowned a little.
+
+'Oh, what ugly wrinkles in my bad boy's forehead!' said Dora, and still
+being on my knee, she traced them with her pencil; putting it to her
+rosy lips to make it mark blacker, and working at my forehead with a
+quaint little mockery of being industrious, that quite delighted me in
+spite of myself.
+
+'There's a good child,' said Dora, 'it makes its face so much prettier
+to laugh.' 'But, my love,' said I.
+
+'No, no! please!' cried Dora, with a kiss, 'don't be a naughty Blue
+Beard! Don't be serious!'
+
+'My precious wife,' said I, 'we must be serious sometimes. Come! Sit
+down on this chair, close beside me! Give me the pencil! There! Now let
+us talk sensibly. You know, dear'; what a little hand it was to hold,
+and what a tiny wedding-ring it was to see! 'You know, my love, it is
+not exactly comfortable to have to go out without one's dinner. Now, is
+it?'
+
+'N-n-no!' replied Dora, faintly.
+
+'My love, how you tremble!'
+
+'Because I KNOW you're going to scold me,' exclaimed Dora, in a piteous
+voice.
+
+'My sweet, I am only going to reason.'
+
+'Oh, but reasoning is worse than scolding!' exclaimed Dora, in despair.
+'I didn't marry to be reasoned with. If you meant to reason with such a
+poor little thing as I am, you ought to have told me so, you cruel boy!'
+
+I tried to pacify Dora, but she turned away her face, and shook her
+curls from side to side, and said, 'You cruel, cruel boy!' so many
+times, that I really did not exactly know what to do: so I took a few
+turns up and down the room in my uncertainty, and came back again.
+
+'Dora, my darling!'
+
+'No, I am not your darling. Because you must be sorry that you married
+me, or else you wouldn't reason with me!' returned Dora.
+
+I felt so injured by the inconsequential nature of this charge, that it
+gave me courage to be grave.
+
+'Now, my own Dora,' said I, 'you are very childish, and are talking
+nonsense. You must remember, I am sure, that I was obliged to go out
+yesterday when dinner was half over; and that, the day before, I was
+made quite unwell by being obliged to eat underdone veal in a hurry;
+today, I don't dine at all--and I am afraid to say how long we waited
+for breakfast--and then the water didn't boil. I don't mean to reproach
+you, my dear, but this is not comfortable.'
+
+'Oh, you cruel, cruel boy, to say I am a disagreeable wife!' cried Dora.
+
+'Now, my dear Dora, you must know that I never said that!'
+
+'You said, I wasn't comfortable!' cried Dora. 'I said the housekeeping
+was not comfortable!'
+
+'It's exactly the same thing!' cried Dora. And she evidently thought so,
+for she wept most grievously.
+
+I took another turn across the room, full of love for my pretty wife,
+and distracted by self-accusatory inclinations to knock my head against
+the door. I sat down again, and said:
+
+'I am not blaming you, Dora. We have both a great deal to learn. I am
+only trying to show you, my dear, that you must--you really must' (I
+was resolved not to give this up)--'accustom yourself to look after Mary
+Anne. Likewise to act a little for yourself, and me.'
+
+'I wonder, I do, at your making such ungrateful speeches,' sobbed Dora.
+'When you know that the other day, when you said you would like a little
+bit of fish, I went out myself, miles and miles, and ordered it, to
+surprise you.'
+
+'And it was very kind of you, my own darling,' said I. 'I felt it so
+much that I wouldn't on any account have even mentioned that you
+bought a Salmon--which was too much for two. Or that it cost one pound
+six--which was more than we can afford.'
+
+'You enjoyed it very much,' sobbed Dora. 'And you said I was a Mouse.'
+
+'And I'll say so again, my love,' I returned, 'a thousand times!'
+
+But I had wounded Dora's soft little heart, and she was not to be
+comforted. She was so pathetic in her sobbing and bewailing, that I felt
+as if I had said I don't know what to hurt her. I was obliged to hurry
+away; I was kept out late; and I felt all night such pangs of remorse as
+made me miserable. I had the conscience of an assassin, and was haunted
+by a vague sense of enormous wickedness.
+
+It was two or three hours past midnight when I got home. I found my
+aunt, in our house, sitting up for me.
+
+'Is anything the matter, aunt?' said I, alarmed.
+
+'Nothing, Trot,' she replied. 'Sit down, sit down. Little Blossom has
+been rather out of spirits, and I have been keeping her company. That's
+all.'
+
+I leaned my head upon my hand; and felt more sorry and downcast, as I
+sat looking at the fire, than I could have supposed possible so soon
+after the fulfilment of my brightest hopes. As I sat thinking, I
+happened to meet my aunt's eyes, which were resting on my face. There
+was an anxious expression in them, but it cleared directly.
+
+'I assure you, aunt,' said I, 'I have been quite unhappy myself all
+night, to think of Dora's being so. But I had no other intention than to
+speak to her tenderly and lovingly about our home-affairs.'
+
+MY aunt nodded encouragement.
+
+'You must have patience, Trot,' said she.
+
+'Of course. Heaven knows I don't mean to be unreasonable, aunt!'
+
+'No, no,' said my aunt. 'But Little Blossom is a very tender little
+blossom, and the wind must be gentle with her.'
+
+I thanked my good aunt, in my heart, for her tenderness towards my wife;
+and I was sure that she knew I did.
+
+'Don't you think, aunt,' said I, after some further contemplation of the
+fire, 'that you could advise and counsel Dora a little, for our mutual
+advantage, now and then?'
+
+'Trot,' returned my aunt, with some emotion, 'no! Don't ask me such a
+thing.'
+
+Her tone was so very earnest that I raised my eyes in surprise.
+
+'I look back on my life, child,' said my aunt, 'and I think of some who
+are in their graves, with whom I might have been on kinder terms. If I
+judged harshly of other people's mistakes in marriage, it may have been
+because I had bitter reason to judge harshly of my own. Let that pass. I
+have been a grumpy, frumpy, wayward sort of a woman, a good many years.
+I am still, and I always shall be. But you and I have done one another
+some good, Trot,--at all events, you have done me good, my dear; and
+division must not come between us, at this time of day.'
+
+'Division between us!' cried I.
+
+'Child, child!' said my aunt, smoothing her dress, 'how soon it might
+come between us, or how unhappy I might make our Little Blossom, if I
+meddled in anything, a prophet couldn't say. I want our pet to like me,
+and be as gay as a butterfly. Remember your own home, in that second
+marriage; and never do both me and her the injury you have hinted at!'
+
+I comprehended, at once, that my aunt was right; and I comprehended the
+full extent of her generous feeling towards my dear wife.
+
+'These are early days, Trot,' she pursued, 'and Rome was not built in a
+day, nor in a year. You have chosen freely for yourself'; a cloud passed
+over her face for a moment, I thought; 'and you have chosen a very
+pretty and a very affectionate creature. It will be your duty, and it
+will be your pleasure too--of course I know that; I am not delivering
+a lecture--to estimate her (as you chose her) by the qualities she has,
+and not by the qualities she may not have. The latter you must develop
+in her, if you can. And if you cannot, child,' here my aunt rubbed her
+nose, 'you must just accustom yourself to do without 'em. But remember,
+my dear, your future is between you two. No one can assist you; you are
+to work it out for yourselves. This is marriage, Trot; and Heaven bless
+you both, in it, for a pair of babes in the wood as you are!'
+
+My aunt said this in a sprightly way, and gave me a kiss to ratify the
+blessing.
+
+'Now,' said she, 'light my little lantern, and see me into my bandbox by
+the garden path'; for there was a communication between our cottages in
+that direction. 'Give Betsey Trotwood's love to Blossom, when you come
+back; and whatever you do, Trot, never dream of setting Betsey up as a
+scarecrow, for if I ever saw her in the glass, she's quite grim enough
+and gaunt enough in her private capacity!'
+
+With this my aunt tied her head up in a handkerchief, with which she was
+accustomed to make a bundle of it on such occasions; and I escorted her
+home. As she stood in her garden, holding up her little lantern to light
+me back, I thought her observation of me had an anxious air again; but
+I was too much occupied in pondering on what she had said, and too much
+impressed--for the first time, in reality--by the conviction that Dora
+and I had indeed to work out our future for ourselves, and that no one
+could assist us, to take much notice of it.
+
+Dora came stealing down in her little slippers, to meet me, now that I
+was alone; and cried upon my shoulder, and said I had been hard-hearted
+and she had been naughty; and I said much the same thing in effect, I
+believe; and we made it up, and agreed that our first little difference
+was to be our last, and that we were never to have another if we lived a
+hundred years.
+
+The next domestic trial we went through, was the Ordeal of Servants.
+Mary Anne's cousin deserted into our coal-hole, and was brought out, to
+our great amazement, by a piquet of his companions in arms, who took
+him away handcuffed in a procession that covered our front-garden with
+ignominy. This nerved me to get rid of Mary Anne, who went so mildly,
+on receipt of wages, that I was surprised, until I found out about the
+tea-spoons, and also about the little sums she had borrowed in my
+name of the tradespeople without authority. After an interval of Mrs.
+Kidgerbury--the oldest inhabitant of Kentish Town, I believe, who went
+out charing, but was too feeble to execute her conceptions of that
+art--we found another treasure, who was one of the most amiable of
+women, but who generally made a point of falling either up or down the
+kitchen stairs with the tray, and almost plunged into the parlour,
+as into a bath, with the tea-things. The ravages committed by this
+unfortunate, rendering her dismissal necessary, she was succeeded (with
+intervals of Mrs. Kidgerbury) by a long line of Incapables; terminating
+in a young person of genteel appearance, who went to Greenwich Fair in
+Dora's bonnet. After whom I remember nothing but an average equality of
+failure.
+
+Everybody we had anything to do with seemed to cheat us. Our appearance
+in a shop was a signal for the damaged goods to be brought out
+immediately. If we bought a lobster, it was full of water. All our meat
+turned out to be tough, and there was hardly any crust to our loaves.
+In search of the principle on which joints ought to be roasted, to be
+roasted enough, and not too much, I myself referred to the Cookery Book,
+and found it there established as the allowance of a quarter of an hour
+to every pound, and say a quarter over. But the principle always failed
+us by some curious fatality, and we never could hit any medium between
+redness and cinders.
+
+I had reason to believe that in accomplishing these failures we incurred
+a far greater expense than if we had achieved a series of triumphs. It
+appeared to me, on looking over the tradesmen's books, as if we might
+have kept the basement storey paved with butter, such was the extensive
+scale of our consumption of that article. I don't know whether the
+Excise returns of the period may have exhibited any increase in the
+demand for pepper; but if our performances did not affect the market,
+I should say several families must have left off using it. And the most
+wonderful fact of all was, that we never had anything in the house.
+
+As to the washerwoman pawning the clothes, and coming in a state of
+penitent intoxication to apologize, I suppose that might have happened
+several times to anybody. Also the chimney on fire, the parish engine,
+and perjury on the part of the Beadle. But I apprehend that we were
+personally fortunate in engaging a servant with a taste for cordials,
+who swelled our running account for porter at the public-house by such
+inexplicable items as 'quartern rum shrub (Mrs. C.)'; 'Half-quartern
+gin and cloves (Mrs. C.)'; 'Glass rum and peppermint (Mrs. C.)'--the
+parentheses always referring to Dora, who was supposed, it appeared on
+explanation, to have imbibed the whole of these refreshments.
+
+One of our first feats in the housekeeping way was a little dinner to
+Traddles. I met him in town, and asked him to walk out with me that
+afternoon. He readily consenting, I wrote to Dora, saying I would bring
+him home. It was pleasant weather, and on the road we made my domestic
+happiness the theme of conversation. Traddles was very full of it; and
+said, that, picturing himself with such a home, and Sophy waiting and
+preparing for him, he could think of nothing wanting to complete his
+bliss.
+
+I could not have wished for a prettier little wife at the opposite end
+of the table, but I certainly could have wished, when we sat down, for a
+little more room. I did not know how it was, but though there were only
+two of us, we were at once always cramped for room, and yet had always
+room enough to lose everything in. I suspect it may have been because
+nothing had a place of its own, except Jip's pagoda, which invariably
+blocked up the main thoroughfare. On the present occasion, Traddles
+was so hemmed in by the pagoda and the guitar-case, and Dora's
+flower-painting, and my writing-table, that I had serious doubts of the
+possibility of his using his knife and fork; but he protested, with his
+own good-humour, 'Oceans of room, Copperfield! I assure you, Oceans!'
+
+There was another thing I could have wished, namely, that Jip had never
+been encouraged to walk about the tablecloth during dinner. I began to
+think there was something disorderly in his being there at all, even
+if he had not been in the habit of putting his foot in the salt or the
+melted butter. On this occasion he seemed to think he was introduced
+expressly to keep Traddles at bay; and he barked at my old friend, and
+made short runs at his plate, with such undaunted pertinacity, that he
+may be said to have engrossed the conversation.
+
+However, as I knew how tender-hearted my dear Dora was, and how
+sensitive she would be to any slight upon her favourite, I hinted no
+objection. For similar reasons I made no allusion to the skirmishing
+plates upon the floor; or to the disreputable appearance of the castors,
+which were all at sixes and sevens, and looked drunk; or to the further
+blockade of Traddles by wandering vegetable dishes and jugs. I could
+not help wondering in my own mind, as I contemplated the boiled leg of
+mutton before me, previous to carving it, how it came to pass that
+our joints of meat were of such extraordinary shapes--and whether our
+butcher contracted for all the deformed sheep that came into the world;
+but I kept my reflections to myself.
+
+'My love,' said I to Dora, 'what have you got in that dish?'
+
+I could not imagine why Dora had been making tempting little faces at
+me, as if she wanted to kiss me.
+
+'Oysters, dear,' said Dora, timidly.
+
+'Was that YOUR thought?' said I, delighted.
+
+'Ye-yes, Doady,' said Dora.
+
+'There never was a happier one!' I exclaimed, laying down the
+carving-knife and fork. 'There is nothing Traddles likes so much!'
+
+'Ye-yes, Doady,' said Dora, 'and so I bought a beautiful little barrel
+of them, and the man said they were very good. But I--I am afraid
+there's something the matter with them. They don't seem right.' Here
+Dora shook her head, and diamonds twinkled in her eyes.
+
+'They are only opened in both shells,' said I. 'Take the top one off, my
+love.'
+
+'But it won't come off!' said Dora, trying very hard, and looking very
+much distressed.
+
+'Do you know, Copperfield,' said Traddles, cheerfully examining the
+dish, 'I think it is in consequence--they are capital oysters, but I
+think it is in consequence--of their never having been opened.'
+
+They never had been opened; and we had no oyster-knives--and couldn't
+have used them if we had; so we looked at the oysters and ate the
+mutton. At least we ate as much of it as was done, and made up with
+capers. If I had permitted him, I am satisfied that Traddles would have
+made a perfect savage of himself, and eaten a plateful of raw meat, to
+express enjoyment of the repast; but I would hear of no such immolation
+on the altar of friendship, and we had a course of bacon instead; there
+happening, by good fortune, to be cold bacon in the larder.
+
+My poor little wife was in such affliction when she thought I should be
+annoyed, and in such a state of joy when she found I was not, that the
+discomfiture I had subdued, very soon vanished, and we passed a happy
+evening; Dora sitting with her arm on my chair while Traddles and I
+discussed a glass of wine, and taking every opportunity of whispering
+in my ear that it was so good of me not to be a cruel, cross old boy. By
+and by she made tea for us; which it was so pretty to see her do, as if
+she was busying herself with a set of doll's tea-things, that I was not
+particular about the quality of the beverage. Then Traddles and I played
+a game or two at cribbage; and Dora singing to the guitar the while,
+it seemed to me as if our courtship and marriage were a tender dream
+of mine, and the night when I first listened to her voice were not yet
+over.
+
+When Traddles went away, and I came back into the parlour from seeing
+him out, my wife planted her chair close to mine, and sat down by my
+side. 'I am very sorry,' she said. 'Will you try to teach me, Doady?'
+
+'I must teach myself first, Dora,' said I. 'I am as bad as you, love.'
+
+'Ah! But you can learn,' she returned; 'and you are a clever, clever
+man!'
+
+'Nonsense, mouse!' said I.
+
+'I wish,' resumed my wife, after a long silence, 'that I could have gone
+down into the country for a whole year, and lived with Agnes!'
+
+Her hands were clasped upon my shoulder, and her chin rested on them,
+and her blue eyes looked quietly into mine.
+
+'Why so?' I asked.
+
+'I think she might have improved me, and I think I might have learned
+from her,' said Dora.
+
+'All in good time, my love. Agnes has had her father to take care of for
+these many years, you should remember. Even when she was quite a child,
+she was the Agnes whom we know,' said I.
+
+'Will you call me a name I want you to call me?' inquired Dora, without
+moving.
+
+'What is it?' I asked with a smile.
+
+'It's a stupid name,' she said, shaking her curls for a moment.
+'Child-wife.'
+
+I laughingly asked my child-wife what her fancy was in desiring to be so
+called. She answered without moving, otherwise than as the arm I twined
+about her may have brought her blue eyes nearer to me:
+
+'I don't mean, you silly fellow, that you should use the name instead
+of Dora. I only mean that you should think of me that way. When you are
+going to be angry with me, say to yourself, "it's only my child-wife!"
+When I am very disappointing, say, "I knew, a long time ago, that she
+would make but a child-wife!" When you miss what I should like to be,
+and I think can never be, say, "still my foolish child-wife loves me!"
+For indeed I do.'
+
+I had not been serious with her; having no idea until now, that she was
+serious herself. But her affectionate nature was so happy in what I now
+said to her with my whole heart, that her face became a laughing one
+before her glittering eyes were dry. She was soon my child-wife indeed;
+sitting down on the floor outside the Chinese House, ringing all
+the little bells one after another, to punish Jip for his recent bad
+behaviour; while Jip lay blinking in the doorway with his head out, even
+too lazy to be teased.
+
+This appeal of Dora's made a strong impression on me. I look back on the
+time I write of; I invoke the innocent figure that I dearly loved, to
+come out from the mists and shadows of the past, and turn its gentle
+head towards me once again; and I can still declare that this one little
+speech was constantly in my memory. I may not have used it to the best
+account; I was young and inexperienced; but I never turned a deaf ear to
+its artless pleading.
+
+Dora told me, shortly afterwards, that she was going to be a wonderful
+housekeeper. Accordingly, she polished the tablets, pointed the pencil,
+bought an immense account-book, carefully stitched up with a needle and
+thread all the leaves of the Cookery Book which Jip had torn, and made
+quite a desperate little attempt 'to be good', as she called it. But the
+figures had the old obstinate propensity--they WOULD NOT add up. When
+she had entered two or three laborious items in the account-book, Jip
+would walk over the page, wagging his tail, and smear them all out. Her
+own little right-hand middle finger got steeped to the very bone in ink;
+and I think that was the only decided result obtained.
+
+Sometimes, of an evening, when I was at home and at work--for I wrote
+a good deal now, and was beginning in a small way to be known as a
+writer--I would lay down my pen, and watch my child-wife trying to be
+good. First of all, she would bring out the immense account-book, and
+lay it down upon the table, with a deep sigh. Then she would open it at
+the place where Jip had made it illegible last night, and call Jip
+up, to look at his misdeeds. This would occasion a diversion in Jip's
+favour, and some inking of his nose, perhaps, as a penalty. Then she
+would tell Jip to lie down on the table instantly, 'like a lion'--which
+was one of his tricks, though I cannot say the likeness was
+striking--and, if he were in an obedient humour, he would obey. Then she
+would take up a pen, and begin to write, and find a hair in it. Then
+she would take up another pen, and begin to write, and find that it
+spluttered. Then she would take up another pen, and begin to write, and
+say in a low voice, 'Oh, it's a talking pen, and will disturb Doady!'
+And then she would give it up as a bad job, and put the account-book
+away, after pretending to crush the lion with it.
+
+Or, if she were in a very sedate and serious state of mind, she would
+sit down with the tablets, and a little basket of bills and other
+documents, which looked more like curl-papers than anything else, and
+endeavour to get some result out of them. After severely comparing one
+with another, and making entries on the tablets, and blotting them
+out, and counting all the fingers of her left hand over and over again,
+backwards and forwards, she would be so vexed and discouraged, and
+would look so unhappy, that it gave me pain to see her bright face
+clouded--and for me!--and I would go softly to her, and say:
+
+'What's the matter, Dora?'
+
+Dora would look up hopelessly, and reply, 'They won't come right. They
+make my head ache so. And they won't do anything I want!'
+
+Then I would say, 'Now let us try together. Let me show you, Dora.'
+
+Then I would commence a practical demonstration, to which Dora would pay
+profound attention, perhaps for five minutes; when she would begin to be
+dreadfully tired, and would lighten the subject by curling my hair,
+or trying the effect of my face with my shirt-collar turned down. If
+I tacitly checked this playfulness, and persisted, she would look so
+scared and disconsolate, as she became more and more bewildered, that
+the remembrance of her natural gaiety when I first strayed into her
+path, and of her being my child-wife, would come reproachfully upon me;
+and I would lay the pencil down, and call for the guitar.
+
+I had a great deal of work to do, and had many anxieties, but the same
+considerations made me keep them to myself. I am far from sure, now,
+that it was right to do this, but I did it for my child-wife's sake. I
+search my breast, and I commit its secrets, if I know them, without any
+reservation to this paper. The old unhappy loss or want of something
+had, I am conscious, some place in my heart; but not to the embitterment
+of my life. When I walked alone in the fine weather, and thought of the
+summer days when all the air had been filled with my boyish enchantment,
+I did miss something of the realization of my dreams; but I thought it
+was a softened glory of the Past, which nothing could have thrown upon
+the present time. I did feel, sometimes, for a little while, that I
+could have wished my wife had been my counsellor; had had more character
+and purpose, to sustain me and improve me by; had been endowed with
+power to fill up the void which somewhere seemed to be about me; but
+I felt as if this were an unearthly consummation of my happiness, that
+never had been meant to be, and never could have been.
+
+I was a boyish husband as to years. I had known the softening influence
+of no other sorrows or experiences than those recorded in these leaves.
+If I did any wrong, as I may have done much, I did it in mistaken love,
+and in my want of wisdom. I write the exact truth. It would avail me
+nothing to extenuate it now.
+
+Thus it was that I took upon myself the toils and cares of our life,
+and had no partner in them. We lived much as before, in reference to our
+scrambling household arrangements; but I had got used to those, and Dora
+I was pleased to see was seldom vexed now. She was bright and cheerful
+in the old childish way, loved me dearly, and was happy with her old
+trifles.
+
+When the debates were heavy--I mean as to length, not quality, for in
+the last respect they were not often otherwise--and I went home late,
+Dora would never rest when she heard my footsteps, but would always come
+downstairs to meet me. When my evenings were unoccupied by the pursuit
+for which I had qualified myself with so much pains, and I was engaged
+in writing at home, she would sit quietly near me, however late the
+hour, and be so mute, that I would often think she had dropped asleep.
+But generally, when I raised my head, I saw her blue eyes looking at me
+with the quiet attention of which I have already spoken.
+
+'Oh, what a weary boy!' said Dora one night, when I met her eyes as I
+was shutting up my desk.
+
+'What a weary girl!' said I. 'That's more to the purpose. You must go to
+bed another time, my love. It's far too late for you.'
+
+'No, don't send me to bed!' pleaded Dora, coming to my side. 'Pray,
+don't do that!'
+
+'Dora!' To my amazement she was sobbing on my neck. 'Not well, my dear!
+not happy!'
+
+'Yes! quite well, and very happy!' said Dora. 'But say you'll let me
+stop, and see you write.'
+
+'Why, what a sight for such bright eyes at midnight!' I replied.
+
+'Are they bright, though?' returned Dora, laughing. 'I'm so glad they're
+bright.' 'Little Vanity!' said I.
+
+But it was not vanity; it was only harmless delight in my admiration. I
+knew that very well, before she told me so.
+
+'If you think them pretty, say I may always stop, and see you write!'
+said Dora. 'Do you think them pretty?'
+
+'Very pretty.'
+
+'Then let me always stop and see you write.'
+
+'I am afraid that won't improve their brightness, Dora.'
+
+'Yes, it will! Because, you clever boy, you'll not forget me then, while
+you are full of silent fancies. Will you mind it, if I say something
+very, very silly?---more than usual?' inquired Dora, peeping over my
+shoulder into my face.
+
+'What wonderful thing is that?' said I.
+
+'Please let me hold the pens,' said Dora. 'I want to have something to
+do with all those many hours when you are so industrious. May I hold the
+pens?'
+
+The remembrance of her pretty joy when I said yes, brings tears into my
+eyes. The next time I sat down to write, and regularly afterwards,
+she sat in her old place, with a spare bundle of pens at her side. Her
+triumph in this connexion with my work, and her delight when I wanted a
+new pen--which I very often feigned to do--suggested to me a new way of
+pleasing my child-wife. I occasionally made a pretence of wanting a
+page or two of manuscript copied. Then Dora was in her glory. The
+preparations she made for this great work, the aprons she put on, the
+bibs she borrowed from the kitchen to keep off the ink, the time she
+took, the innumerable stoppages she made to have a laugh with Jip as if
+he understood it all, her conviction that her work was incomplete unless
+she signed her name at the end, and the way in which she would bring it
+to me, like a school-copy, and then, when I praised it, clasp me round
+the neck, are touching recollections to me, simple as they might appear
+to other men.
+
+She took possession of the keys soon after this, and went jingling about
+the house with the whole bunch in a little basket, tied to her slender
+waist. I seldom found that the places to which they belonged were
+locked, or that they were of any use except as a plaything for Jip--but
+Dora was pleased, and that pleased me. She was quite satisfied that a
+good deal was effected by this make-belief of housekeeping; and was as
+merry as if we had been keeping a baby-house, for a joke.
+
+So we went on. Dora was hardly less affectionate to my aunt than to me,
+and often told her of the time when she was afraid she was 'a cross old
+thing'. I never saw my aunt unbend more systematically to anyone. She
+courted Jip, though Jip never responded; listened, day after day, to the
+guitar, though I am afraid she had no taste for music; never attacked
+the Incapables, though the temptation must have been severe; went
+wonderful distances on foot to purchase, as surprises, any trifles that
+she found out Dora wanted; and never came in by the garden, and missed
+her from the room, but she would call out, at the foot of the stairs, in
+a voice that sounded cheerfully all over the house:
+
+'Where's Little Blossom?'
+
+
+
+CHAPTER 45. MR. DICK FULFILS MY AUNT'S PREDICTIONS
+
+
+It was some time now, since I had left the Doctor. Living in his
+neighbourhood, I saw him frequently; and we all went to his house on two
+or three occasions to dinner or tea. The Old Soldier was in permanent
+quarters under the Doctor's roof. She was exactly the same as ever, and
+the same immortal butterflies hovered over her cap.
+
+Like some other mothers, whom I have known in the course of my life,
+Mrs. Markleham was far more fond of pleasure than her daughter was.
+She required a great deal of amusement, and, like a deep old soldier,
+pretended, in consulting her own inclinations, to be devoting herself
+to her child. The Doctor's desire that Annie should be entertained,
+was therefore particularly acceptable to this excellent parent; who
+expressed unqualified approval of his discretion.
+
+I have no doubt, indeed, that she probed the Doctor's wound without
+knowing it. Meaning nothing but a certain matured frivolity and
+selfishness, not always inseparable from full-blown years, I think she
+confirmed him in his fear that he was a constraint upon his young
+wife, and that there was no congeniality of feeling between them, by so
+strongly commending his design of lightening the load of her life.
+
+'My dear soul,' she said to him one day when I was present, 'you know
+there is no doubt it would be a little pokey for Annie to be always shut
+up here.'
+
+The Doctor nodded his benevolent head. 'When she comes to her mother's
+age,' said Mrs. Markleham, with a flourish of her fan, 'then it'll be
+another thing. You might put ME into a Jail, with genteel society and
+a rubber, and I should never care to come out. But I am not Annie, you
+know; and Annie is not her mother.'
+
+'Surely, surely,' said the Doctor.
+
+'You are the best of creatures--no, I beg your pardon!' for the Doctor
+made a gesture of deprecation, 'I must say before your face, as I always
+say behind your back, you are the best of creatures; but of course you
+don't--now do you?---enter into the same pursuits and fancies as Annie?'
+
+'No,' said the Doctor, in a sorrowful tone.
+
+'No, of course not,' retorted the Old Soldier. 'Take your Dictionary,
+for example. What a useful work a Dictionary is! What a necessary work!
+The meanings of words! Without Doctor Johnson, or somebody of that sort,
+we might have been at this present moment calling an Italian-iron,
+a bedstead. But we can't expect a Dictionary--especially when it's
+making--to interest Annie, can we?'
+
+The Doctor shook his head.
+
+'And that's why I so much approve,' said Mrs. Markleham, tapping him
+on the shoulder with her shut-up fan, 'of your thoughtfulness. It shows
+that you don't expect, as many elderly people do expect, old heads on
+young shoulders. You have studied Annie's character, and you understand
+it. That's what I find so charming!'
+
+Even the calm and patient face of Doctor Strong expressed some little
+sense of pain, I thought, under the infliction of these compliments.
+
+'Therefore, my dear Doctor,' said the Old Soldier, giving him several
+affectionate taps, 'you may command me, at all times and seasons. Now,
+do understand that I am entirely at your service. I am ready to go with
+Annie to operas, concerts, exhibitions, all kinds of places; and you
+shall never find that I am tired. Duty, my dear Doctor, before every
+consideration in the universe!'
+
+She was as good as her word. She was one of those people who can bear
+a great deal of pleasure, and she never flinched in her perseverance
+in the cause. She seldom got hold of the newspaper (which she settled
+herself down in the softest chair in the house to read through an
+eye-glass, every day, for two hours), but she found out something that
+she was certain Annie would like to see. It was in vain for Annie to
+protest that she was weary of such things. Her mother's remonstrance
+always was, 'Now, my dear Annie, I am sure you know better; and I must
+tell you, my love, that you are not making a proper return for the
+kindness of Doctor Strong.'
+
+This was usually said in the Doctor's presence, and appeared to me to
+constitute Annie's principal inducement for withdrawing her objections
+when she made any. But in general she resigned herself to her mother,
+and went where the Old Soldier would.
+
+It rarely happened now that Mr. Maldon accompanied them. Sometimes
+my aunt and Dora were invited to do so, and accepted the invitation.
+Sometimes Dora only was asked. The time had been, when I should have
+been uneasy in her going; but reflection on what had passed that
+former night in the Doctor's study, had made a change in my mistrust. I
+believed that the Doctor was right, and I had no worse suspicions.
+
+My aunt rubbed her nose sometimes when she happened to be alone with
+me, and said she couldn't make it out; she wished they were happier; she
+didn't think our military friend (so she always called the Old Soldier)
+mended the matter at all. My aunt further expressed her opinion, 'that
+if our military friend would cut off those butterflies, and give 'em to
+the chimney-sweepers for May-day, it would look like the beginning of
+something sensible on her part.'
+
+But her abiding reliance was on Mr. Dick. That man had evidently an
+idea in his head, she said; and if he could only once pen it up into a
+corner, which was his great difficulty, he would distinguish himself in
+some extraordinary manner.
+
+Unconscious of this prediction, Mr. Dick continued to occupy precisely
+the same ground in reference to the Doctor and to Mrs. Strong. He seemed
+neither to advance nor to recede. He appeared to have settled into his
+original foundation, like a building; and I must confess that my faith
+in his ever Moving, was not much greater than if he had been a building.
+
+But one night, when I had been married some months, Mr. Dick put his
+head into the parlour, where I was writing alone (Dora having gone out
+with my aunt to take tea with the two little birds), and said, with a
+significant cough:
+
+'You couldn't speak to me without inconveniencing yourself, Trotwood, I
+am afraid?'
+
+'Certainly, Mr. Dick,' said I; 'come in!'
+
+'Trotwood,' said Mr. Dick, laying his finger on the side of his nose,
+after he had shaken hands with me. 'Before I sit down, I wish to make an
+observation. You know your aunt?'
+
+'A little,' I replied.
+
+'She is the most wonderful woman in the world, sir!'
+
+After the delivery of this communication, which he shot out of himself
+as if he were loaded with it, Mr. Dick sat down with greater gravity
+than usual, and looked at me.
+
+'Now, boy,' said Mr. Dick, 'I am going to put a question to you.'
+
+'As many as you please,' said I.
+
+'What do you consider me, sir?' asked Mr. Dick, folding his arms.
+
+'A dear old friend,' said I. 'Thank you, Trotwood,' returned Mr. Dick,
+laughing, and reaching across in high glee to shake hands with me. 'But
+I mean, boy,' resuming his gravity, 'what do you consider me in this
+respect?' touching his forehead.
+
+I was puzzled how to answer, but he helped me with a word.
+
+'Weak?' said Mr. Dick.
+
+'Well,' I replied, dubiously. 'Rather so.'
+
+'Exactly!' cried Mr. Dick, who seemed quite enchanted by my reply. 'That
+is, Trotwood, when they took some of the trouble out of you-know-who's
+head, and put it you know where, there was a--' Mr. Dick made his two
+hands revolve very fast about each other a great number of times, and
+then brought them into collision, and rolled them over and over one
+another, to express confusion. 'There was that sort of thing done to me
+somehow. Eh?'
+
+I nodded at him, and he nodded back again.
+
+'In short, boy,' said Mr. Dick, dropping his voice to a whisper, 'I am
+simple.'
+
+I would have qualified that conclusion, but he stopped me.
+
+'Yes, I am! She pretends I am not. She won't hear of it; but I am. I
+know I am. If she hadn't stood my friend, sir, I should have been shut
+up, to lead a dismal life these many years. But I'll provide for her!
+I never spend the copying money. I put it in a box. I have made a will.
+I'll leave it all to her. She shall be rich--noble!'
+
+Mr. Dick took out his pocket-handkerchief, and wiped his eyes. He then
+folded it up with great care, pressed it smooth between his two hands,
+put it in his pocket, and seemed to put my aunt away with it.
+
+'Now you are a scholar, Trotwood,' said Mr. Dick. 'You are a fine
+scholar. You know what a learned man, what a great man, the Doctor is.
+You know what honour he has always done me. Not proud in his wisdom.
+Humble, humble--condescending even to poor Dick, who is simple and knows
+nothing. I have sent his name up, on a scrap of paper, to the kite,
+along the string, when it has been in the sky, among the larks. The kite
+has been glad to receive it, sir, and the sky has been brighter with
+it.'
+
+I delighted him by saying, most heartily, that the Doctor was deserving
+of our best respect and highest esteem.
+
+'And his beautiful wife is a star,' said Mr. Dick. 'A shining star. I
+have seen her shine, sir. But,' bringing his chair nearer, and laying
+one hand upon my knee--'clouds, sir--clouds.'
+
+I answered the solicitude which his face expressed, by conveying the
+same expression into my own, and shaking my head.
+
+'What clouds?' said Mr. Dick.
+
+He looked so wistfully into my face, and was so anxious to understand,
+that I took great pains to answer him slowly and distinctly, as I might
+have entered on an explanation to a child.
+
+'There is some unfortunate division between them,' I replied. 'Some
+unhappy cause of separation. A secret. It may be inseparable from the
+discrepancy in their years. It may have grown up out of almost nothing.'
+
+Mr. Dick, who had told off every sentence with a thoughtful nod, paused
+when I had done, and sat considering, with his eyes upon my face, and
+his hand upon my knee.
+
+'Doctor not angry with her, Trotwood?' he said, after some time.
+
+'No. Devoted to her.'
+
+'Then, I have got it, boy!' said Mr. Dick.
+
+The sudden exultation with which he slapped me on the knee, and leaned
+back in his chair, with his eyebrows lifted up as high as he could
+possibly lift them, made me think him farther out of his wits than
+ever. He became as suddenly grave again, and leaning forward as before,
+said--first respectfully taking out his pocket-handkerchief, as if it
+really did represent my aunt:
+
+'Most wonderful woman in the world, Trotwood. Why has she done nothing
+to set things right?'
+
+'Too delicate and difficult a subject for such interference,' I replied.
+
+'Fine scholar,' said Mr. Dick, touching me with his finger. 'Why has HE
+done nothing?'
+
+'For the same reason,' I returned.
+
+'Then, I have got it, boy!' said Mr. Dick. And he stood up before me,
+more exultingly than before, nodding his head, and striking himself
+repeatedly upon the breast, until one might have supposed that he had
+nearly nodded and struck all the breath out of his body.
+
+'A poor fellow with a craze, sir,' said Mr. Dick, 'a simpleton, a
+weak-minded person--present company, you know!' striking himself again,
+'may do what wonderful people may not do. I'll bring them together, boy.
+I'll try. They'll not blame me. They'll not object to me. They'll not
+mind what I do, if it's wrong. I'm only Mr. Dick. And who minds Dick?
+Dick's nobody! Whoo!' He blew a slight, contemptuous breath, as if he
+blew himself away.
+
+It was fortunate he had proceeded so far with his mystery, for we heard
+the coach stop at the little garden gate, which brought my aunt and Dora
+home.
+
+'Not a word, boy!' he pursued in a whisper; 'leave all the blame with
+Dick--simple Dick--mad Dick. I have been thinking, sir, for some time,
+that I was getting it, and now I have got it. After what you have said
+to me, I am sure I have got it. All right!' Not another word did Mr.
+Dick utter on the subject; but he made a very telegraph of himself for
+the next half-hour (to the great disturbance of my aunt's mind), to
+enjoin inviolable secrecy on me.
+
+To my surprise, I heard no more about it for some two or three weeks,
+though I was sufficiently interested in the result of his endeavours;
+descrying a strange gleam of good sense--I say nothing of good feeling,
+for that he always exhibited--in the conclusion to which he had come. At
+last I began to believe, that, in the flighty and unsettled state of his
+mind, he had either forgotten his intention or abandoned it.
+
+One fair evening, when Dora was not inclined to go out, my aunt and I
+strolled up to the Doctor's cottage. It was autumn, when there were no
+debates to vex the evening air; and I remember how the leaves smelt like
+our garden at Blunderstone as we trod them under foot, and how the old,
+unhappy feeling, seemed to go by, on the sighing wind.
+
+It was twilight when we reached the cottage. Mrs. Strong was just coming
+out of the garden, where Mr. Dick yet lingered, busy with his knife,
+helping the gardener to point some stakes. The Doctor was engaged with
+someone in his study; but the visitor would be gone directly, Mrs.
+Strong said, and begged us to remain and see him. We went into the
+drawing-room with her, and sat down by the darkening window. There was
+never any ceremony about the visits of such old friends and neighbours
+as we were.
+
+We had not sat here many minutes, when Mrs. Markleham, who usually
+contrived to be in a fuss about something, came bustling in, with her
+newspaper in her hand, and said, out of breath, 'My goodness gracious,
+Annie, why didn't you tell me there was someone in the Study!'
+
+'My dear mama,' she quietly returned, 'how could I know that you desired
+the information?'
+
+'Desired the information!' said Mrs. Markleham, sinking on the sofa. 'I
+never had such a turn in all my life!'
+
+'Have you been to the Study, then, mama?' asked Annie.
+
+'BEEN to the Study, my dear!' she returned emphatically. 'Indeed I have!
+I came upon the amiable creature--if you'll imagine my feelings, Miss
+Trotwood and David--in the act of making his will.'
+
+Her daughter looked round from the window quickly.
+
+'In the act, my dear Annie,' repeated Mrs. Markleham, spreading the
+newspaper on her lap like a table-cloth, and patting her hands upon it,
+'of making his last Will and Testament. The foresight and affection of
+the dear! I must tell you how it was. I really must, in justice to the
+darling--for he is nothing less!--tell you how it was. Perhaps you know,
+Miss Trotwood, that there is never a candle lighted in this house, until
+one's eyes are literally falling out of one's head with being stretched
+to read the paper. And that there is not a chair in this house, in which
+a paper can be what I call, read, except one in the Study. This took me
+to the Study, where I saw a light. I opened the door. In company with
+the dear Doctor were two professional people, evidently connected with
+the law, and they were all three standing at the table: the
+darling Doctor pen in hand. "This simply expresses then," said the
+Doctor--Annie, my love, attend to the very words--"this simply expresses
+then, gentlemen, the confidence I have in Mrs. Strong, and gives her all
+unconditionally?" One of the professional people replied, "And gives her
+all unconditionally." Upon that, with the natural feelings of a mother,
+I said, "Good God, I beg your pardon!" fell over the door-step, and came
+away through the little back passage where the pantry is.'
+
+Mrs. Strong opened the window, and went out into the verandah, where she
+stood leaning against a pillar.
+
+'But now isn't it, Miss Trotwood, isn't it, David, invigorating,' said
+Mrs. Markleham, mechanically following her with her eyes, 'to find a man
+at Doctor Strong's time of life, with the strength of mind to do this
+kind of thing? It only shows how right I was. I said to Annie, when
+Doctor Strong paid a very flattering visit to myself, and made her the
+subject of a declaration and an offer, I said, "My dear, there is no
+doubt whatever, in my opinion, with reference to a suitable provision
+for you, that Doctor Strong will do more than he binds himself to do."'
+
+Here the bell rang, and we heard the sound of the visitors' feet as they
+went out.
+
+'It's all over, no doubt,' said the Old Soldier, after listening; 'the
+dear creature has signed, sealed, and delivered, and his mind's at rest.
+Well it may be! What a mind! Annie, my love, I am going to the Study
+with my paper, for I am a poor creature without news. Miss Trotwood,
+David, pray come and see the Doctor.'
+
+I was conscious of Mr. Dick's standing in the shadow of the room,
+shutting up his knife, when we accompanied her to the Study; and of my
+aunt's rubbing her nose violently, by the way, as a mild vent for her
+intolerance of our military friend; but who got first into the Study, or
+how Mrs. Markleham settled herself in a moment in her easy-chair, or how
+my aunt and I came to be left together near the door (unless her eyes
+were quicker than mine, and she held me back), I have forgotten, if I
+ever knew. But this I know,--that we saw the Doctor before he saw us,
+sitting at his table, among the folio volumes in which he delighted,
+resting his head calmly on his hand. That, in the same moment, we saw
+Mrs. Strong glide in, pale and trembling. That Mr. Dick supported her on
+his arm. That he laid his other hand upon the Doctor's arm, causing him
+to look up with an abstracted air. That, as the Doctor moved his head,
+his wife dropped down on one knee at his feet, and, with her hands
+imploringly lifted, fixed upon his face the memorable look I had never
+forgotten. That at this sight Mrs. Markleham dropped the newspaper,
+and stared more like a figure-head intended for a ship to be called The
+Astonishment, than anything else I can think of.
+
+The gentleness of the Doctor's manner and surprise, the dignity that
+mingled with the supplicating attitude of his wife, the amiable concern
+of Mr. Dick, and the earnestness with which my aunt said to herself,
+'That man mad!' (triumphantly expressive of the misery from which she
+had saved him)--I see and hear, rather than remember, as I write about
+it.
+
+'Doctor!' said Mr. Dick. 'What is it that's amiss? Look here!'
+
+'Annie!' cried the Doctor. 'Not at my feet, my dear!'
+
+'Yes!' she said. 'I beg and pray that no one will leave the room! Oh, my
+husband and father, break this long silence. Let us both know what it is
+that has come between us!'
+
+Mrs. Markleham, by this time recovering the power of speech, and seeming
+to swell with family pride and motherly indignation, here exclaimed,
+'Annie, get up immediately, and don't disgrace everybody belonging to
+you by humbling yourself like that, unless you wish to see me go out of
+my mind on the spot!'
+
+'Mama!' returned Annie. 'Waste no words on me, for my appeal is to my
+husband, and even you are nothing here.'
+
+'Nothing!' exclaimed Mrs. Markleham. 'Me, nothing! The child has taken
+leave of her senses. Please to get me a glass of water!'
+
+I was too attentive to the Doctor and his wife, to give any heed to this
+request; and it made no impression on anybody else; so Mrs. Markleham
+panted, stared, and fanned herself.
+
+'Annie!' said the Doctor, tenderly taking her in his hands. 'My dear!
+If any unavoidable change has come, in the sequence of time, upon our
+married life, you are not to blame. The fault is mine, and only mine.
+There is no change in my affection, admiration, and respect. I wish to
+make you happy. I truly love and honour you. Rise, Annie, pray!'
+
+But she did not rise. After looking at him for a little while, she sank
+down closer to him, laid her arm across his knee, and dropping her head
+upon it, said:
+
+'If I have any friend here, who can speak one word for me, or for my
+husband in this matter; if I have any friend here, who can give a voice
+to any suspicion that my heart has sometimes whispered to me; if I have
+any friend here, who honours my husband, or has ever cared for me, and
+has anything within his knowledge, no matter what it is, that may help
+to mediate between us, I implore that friend to speak!'
+
+There was a profound silence. After a few moments of painful hesitation,
+I broke the silence.
+
+'Mrs. Strong,' I said, 'there is something within my knowledge, which
+I have been earnestly entreated by Doctor Strong to conceal, and have
+concealed until tonight. But, I believe the time has come when it would
+be mistaken faith and delicacy to conceal it any longer, and when your
+appeal absolves me from his injunction.'
+
+She turned her face towards me for a moment, and I knew that I was
+right. I could not have resisted its entreaty, if the assurance that it
+gave me had been less convincing.
+
+'Our future peace,' she said, 'may be in your hands. I trust it
+confidently to your not suppressing anything. I know beforehand that
+nothing you, or anyone, can tell me, will show my husband's noble heart
+in any other light than one. Howsoever it may seem to you to touch me,
+disregard that. I will speak for myself, before him, and before God
+afterwards.'
+
+Thus earnestly besought, I made no reference to the Doctor for his
+permission, but, without any other compromise of the truth than a little
+softening of the coarseness of Uriah Heep, related plainly what had
+passed in that same room that night. The staring of Mrs. Markleham
+during the whole narration, and the shrill, sharp interjections with
+which she occasionally interrupted it, defy description.
+
+When I had finished, Annie remained, for some few moments, silent, with
+her head bent down, as I have described. Then, she took the Doctor's
+hand (he was sitting in the same attitude as when we had entered the
+room), and pressed it to her breast, and kissed it. Mr. Dick softly
+raised her; and she stood, when she began to speak, leaning on him, and
+looking down upon her husband--from whom she never turned her eyes.
+
+'All that has ever been in my mind, since I was married,' she said in a
+low, submissive, tender voice, 'I will lay bare before you. I could not
+live and have one reservation, knowing what I know now.'
+
+'Nay, Annie,' said the Doctor, mildly, 'I have never doubted you, my
+child. There is no need; indeed there is no need, my dear.'
+
+'There is great need,' she answered, in the same way, 'that I should
+open my whole heart before the soul of generosity and truth, whom, year
+by year, and day by day, I have loved and venerated more and more, as
+Heaven knows!'
+
+'Really,' interrupted Mrs. Markleham, 'if I have any discretion at
+all--'
+
+('Which you haven't, you Marplot,' observed my aunt, in an indignant
+whisper.) --'I must be permitted to observe that it cannot be requisite
+to enter into these details.'
+
+'No one but my husband can judge of that, mama,' said Annie without
+removing her eyes from his face, 'and he will hear me. If I say anything
+to give you pain, mama, forgive me. I have borne pain first, often and
+long, myself.'
+
+'Upon my word!' gasped Mrs. Markleham.
+
+'When I was very young,' said Annie, 'quite a little child, my first
+associations with knowledge of any kind were inseparable from a patient
+friend and teacher--the friend of my dead father--who was always dear
+to me. I can remember nothing that I know, without remembering him. He
+stored my mind with its first treasures, and stamped his character upon
+them all. They never could have been, I think, as good as they have been
+to me, if I had taken them from any other hands.'
+
+'Makes her mother nothing!' exclaimed Mrs. Markleham.
+
+'Not so mama,' said Annie; 'but I make him what he was. I must do that.
+As I grew up, he occupied the same place still. I was proud of his
+interest: deeply, fondly, gratefully attached to him. I looked up to
+him, I can hardly describe how--as a father, as a guide, as one whose
+praise was different from all other praise, as one in whom I could have
+trusted and confided, if I had doubted all the world. You know, mama,
+how young and inexperienced I was, when you presented him before me, of
+a sudden, as a lover.'
+
+'I have mentioned the fact, fifty times at least, to everybody here!'
+said Mrs. Markleham.
+
+('Then hold your tongue, for the Lord's sake, and don't mention it any
+more!' muttered my aunt.)
+
+'It was so great a change: so great a loss, I felt it, at first,' said
+Annie, still preserving the same look and tone, 'that I was agitated
+and distressed. I was but a girl; and when so great a change came in the
+character in which I had so long looked up to him, I think I was sorry.
+But nothing could have made him what he used to be again; and I was
+proud that he should think me so worthy, and we were married.' '--At
+Saint Alphage, Canterbury,' observed Mrs. Markleham.
+
+('Confound the woman!' said my aunt, 'she WON'T be quiet!')
+
+'I never thought,' proceeded Annie, with a heightened colour, 'of any
+worldly gain that my husband would bring to me. My young heart had no
+room in its homage for any such poor reference. Mama, forgive me when
+I say that it was you who first presented to my mind the thought that
+anyone could wrong me, and wrong him, by such a cruel suspicion.'
+
+'Me!' cried Mrs. Markleham.
+
+('Ah! You, to be sure!' observed my aunt, 'and you can't fan it away, my
+military friend!')
+
+'It was the first unhappiness of my new life,' said Annie. 'It was the
+first occasion of every unhappy moment I have known. These moments have
+been more, of late, than I can count; but not--my generous husband!--not
+for the reason you suppose; for in my heart there is not a thought, a
+recollection, or a hope, that any power could separate from you!'
+
+She raised her eyes, and clasped her hands, and looked as beautiful and
+true, I thought, as any Spirit. The Doctor looked on her, henceforth, as
+steadfastly as she on him.
+
+'Mama is blameless,' she went on, 'of having ever urged you for herself,
+and she is blameless in intention every way, I am sure,--but when I saw
+how many importunate claims were pressed upon you in my name; how you
+were traded on in my name; how generous you were, and how Mr. Wickfield,
+who had your welfare very much at heart, resented it; the first sense
+of my exposure to the mean suspicion that my tenderness was bought--and
+sold to you, of all men on earth--fell upon me like unmerited disgrace,
+in which I forced you to participate. I cannot tell you what it
+was--mama cannot imagine what it was--to have this dread and trouble
+always on my mind, yet know in my own soul that on my marriage-day I
+crowned the love and honour of my life!'
+
+'A specimen of the thanks one gets,' cried Mrs. Markleham, in tears,
+'for taking care of one's family! I wish I was a Turk!'
+
+('I wish you were, with all my heart--and in your native country!' said
+my aunt.)
+
+'It was at that time that mama was most solicitous about my Cousin
+Maldon. I had liked him': she spoke softly, but without any hesitation:
+'very much. We had been little lovers once. If circumstances had not
+happened otherwise, I might have come to persuade myself that I really
+loved him, and might have married him, and been most wretched. There can
+be no disparity in marriage like unsuitability of mind and purpose.'
+
+I pondered on those words, even while I was studiously attending to
+what followed, as if they had some particular interest, or some strange
+application that I could not divine. 'There can be no disparity in
+marriage like unsuitability of mind and purpose'--'no disparity in
+marriage like unsuitability of mind and purpose.'
+
+'There is nothing,' said Annie, 'that we have in common. I have long
+found that there is nothing. If I were thankful to my husband for no
+more, instead of for so much, I should be thankful to him for having
+saved me from the first mistaken impulse of my undisciplined heart.'
+
+She stood quite still, before the Doctor, and spoke with an earnestness
+that thrilled me. Yet her voice was just as quiet as before.
+
+'When he was waiting to be the object of your munificence, so freely
+bestowed for my sake, and when I was unhappy in the mercenary shape
+I was made to wear, I thought it would have become him better to have
+worked his own way on. I thought that if I had been he, I would have
+tried to do it, at the cost of almost any hardship. But I thought no
+worse of him, until the night of his departure for India. That night I
+knew he had a false and thankless heart. I saw a double meaning, then,
+in Mr. Wickfield's scrutiny of me. I perceived, for the first time, the
+dark suspicion that shadowed my life.'
+
+'Suspicion, Annie!' said the Doctor. 'No, no, no!'
+
+'In your mind there was none, I know, my husband!' she returned. 'And
+when I came to you, that night, to lay down all my load of shame and
+grief, and knew that I had to tell that, underneath your roof, one of my
+own kindred, to whom you had been a benefactor, for the love of me, had
+spoken to me words that should have found no utterance, even if I had
+been the weak and mercenary wretch he thought me--my mind revolted from
+the taint the very tale conveyed. It died upon my lips, and from that
+hour till now has never passed them.'
+
+Mrs. Markleham, with a short groan, leaned back in her easy-chair; and
+retired behind her fan, as if she were never coming out any more.
+
+'I have never, but in your presence, interchanged a word with him from
+that time; then, only when it has been necessary for the avoidance of
+this explanation. Years have passed since he knew, from me, what his
+situation here was. The kindnesses you have secretly done for his
+advancement, and then disclosed to me, for my surprise and pleasure,
+have been, you will believe, but aggravations of the unhappiness and
+burden of my secret.'
+
+She sunk down gently at the Doctor's feet, though he did his utmost to
+prevent her; and said, looking up, tearfully, into his face:
+
+'Do not speak to me yet! Let me say a little more! Right or wrong, if
+this were to be done again, I think I should do just the same. You never
+can know what it was to be devoted to you, with those old associations;
+to find that anyone could be so hard as to suppose that the truth of my
+heart was bartered away, and to be surrounded by appearances confirming
+that belief. I was very young, and had no adviser. Between mama and
+me, in all relating to you, there was a wide division. If I shrunk into
+myself, hiding the disrespect I had undergone, it was because I honoured
+you so much, and so much wished that you should honour me!'
+
+'Annie, my pure heart!' said the Doctor, 'my dear girl!'
+
+'A little more! a very few words more! I used to think there were so
+many whom you might have married, who would not have brought such charge
+and trouble on you, and who would have made your home a worthier home. I
+used to be afraid that I had better have remained your pupil, and almost
+your child. I used to fear that I was so unsuited to your learning and
+wisdom. If all this made me shrink within myself (as indeed it did),
+when I had that to tell, it was still because I honoured you so much,
+and hoped that you might one day honour me.'
+
+'That day has shone this long time, Annie,' said the Doctor, and can
+have but one long night, my dear.'
+
+'Another word! I afterwards meant--steadfastly meant, and purposed to
+myself--to bear the whole weight of knowing the unworthiness of one
+to whom you had been so good. And now a last word, dearest and best of
+friends! The cause of the late change in you, which I have seen with
+so much pain and sorrow, and have sometimes referred to my old
+apprehension--at other times to lingering suppositions nearer to the
+truth--has been made clear tonight; and by an accident I have also come
+to know, tonight, the full measure of your noble trust in me, even
+under that mistake. I do not hope that any love and duty I may render in
+return, will ever make me worthy of your priceless confidence; but with
+all this knowledge fresh upon me, I can lift my eyes to this dear
+face, revered as a father's, loved as a husband's, sacred to me in
+my childhood as a friend's, and solemnly declare that in my lightest
+thought I have never wronged you; never wavered in the love and the
+fidelity I owe you!'
+
+She had her arms around the Doctor's neck, and he leant his head down
+over her, mingling his grey hair with her dark brown tresses.
+
+'Oh, hold me to your heart, my husband! Never cast me out! Do not think
+or speak of disparity between us, for there is none, except in all my
+many imperfections. Every succeeding year I have known this better, as I
+have esteemed you more and more. Oh, take me to your heart, my husband,
+for my love was founded on a rock, and it endures!'
+
+In the silence that ensued, my aunt walked gravely up to Mr. Dick,
+without at all hurrying herself, and gave him a hug and a sounding kiss.
+And it was very fortunate, with a view to his credit, that she did so;
+for I am confident that I detected him at that moment in the act of
+making preparations to stand on one leg, as an appropriate expression of
+delight.
+
+'You are a very remarkable man, Dick!' said my aunt, with an air of
+unqualified approbation; 'and never pretend to be anything else, for I
+know better!'
+
+With that, my aunt pulled him by the sleeve, and nodded to me; and we
+three stole quietly out of the room, and came away.
+
+'That's a settler for our military friend, at any rate,' said my aunt,
+on the way home. 'I should sleep the better for that, if there was
+nothing else to be glad of!'
+
+'She was quite overcome, I am afraid,' said Mr. Dick, with great
+commiseration.
+
+'What! Did you ever see a crocodile overcome?' inquired my aunt.
+
+'I don't think I ever saw a crocodile,' returned Mr. Dick, mildly.
+
+'There never would have been anything the matter, if it hadn't been for
+that old Animal,' said my aunt, with strong emphasis. 'It's very much
+to be wished that some mothers would leave their daughters alone after
+marriage, and not be so violently affectionate. They seem to think the
+only return that can be made them for bringing an unfortunate young
+woman into the world--God bless my soul, as if she asked to be brought,
+or wanted to come!--is full liberty to worry her out of it again. What
+are you thinking of, Trot?'
+
+I was thinking of all that had been said. My mind was still running on
+some of the expressions used. 'There can be no disparity in marriage
+like unsuitability of mind and purpose.' 'The first mistaken impulse of
+an undisciplined heart.' 'My love was founded on a rock.' But we were at
+home; and the trodden leaves were lying under-foot, and the autumn wind
+was blowing.
+
+
+
+CHAPTER 46. INTELLIGENCE
+
+
+I must have been married, if I may trust to my imperfect memory for
+dates, about a year or so, when one evening, as I was returning from a
+solitary walk, thinking of the book I was then writing--for my success
+had steadily increased with my steady application, and I was engaged at
+that time upon my first work of fiction--I came past Mrs. Steerforth's
+house. I had often passed it before, during my residence in that
+neighbourhood, though never when I could choose another road. Howbeit,
+it did sometimes happen that it was not easy to find another, without
+making a long circuit; and so I had passed that way, upon the whole,
+pretty often.
+
+I had never done more than glance at the house, as I went by with a
+quickened step. It had been uniformly gloomy and dull. None of the best
+rooms abutted on the road; and the narrow, heavily-framed old-fashioned
+windows, never cheerful under any circumstances, looked very dismal,
+close shut, and with their blinds always drawn down. There was a covered
+way across a little paved court, to an entrance that was never used; and
+there was one round staircase window, at odds with all the rest, and the
+only one unshaded by a blind, which had the same unoccupied blank look.
+I do not remember that I ever saw a light in all the house. If I had
+been a casual passer-by, I should have probably supposed that some
+childless person lay dead in it. If I had happily possessed no knowledge
+of the place, and had seen it often in that changeless state, I should
+have pleased my fancy with many ingenious speculations, I dare say.
+
+As it was, I thought as little of it as I might. But my mind could not
+go by it and leave it, as my body did; and it usually awakened a long
+train of meditations. Coming before me, on this particular evening that
+I mention, mingled with the childish recollections and later fancies,
+the ghosts of half-formed hopes, the broken shadows of disappointments
+dimly seen and understood, the blending of experience and imagination,
+incidental to the occupation with which my thoughts had been busy, it
+was more than commonly suggestive. I fell into a brown study as I walked
+on, and a voice at my side made me start.
+
+It was a woman's voice, too. I was not long in recollecting Mrs.
+Steerforth's little parlour-maid, who had formerly worn blue ribbons in
+her cap. She had taken them out now, to adapt herself, I suppose, to
+the altered character of the house; and wore but one or two disconsolate
+bows of sober brown.
+
+'If you please, sir, would you have the goodness to walk in, and speak
+to Miss Dartle?'
+
+'Has Miss Dartle sent you for me?' I inquired.
+
+'Not tonight, sir, but it's just the same. Miss Dartle saw you pass a
+night or two ago; and I was to sit at work on the staircase, and when I
+saw you pass again, to ask you to step in and speak to her.'
+
+I turned back, and inquired of my conductor, as we went along, how Mrs.
+Steerforth was. She said her lady was but poorly, and kept her own room
+a good deal.
+
+When we arrived at the house, I was directed to Miss Dartle in the
+garden, and left to make my presence known to her myself. She was
+sitting on a seat at one end of a kind of terrace, overlooking the great
+city. It was a sombre evening, with a lurid light in the sky; and as
+I saw the prospect scowling in the distance, with here and there some
+larger object starting up into the sullen glare, I fancied it was no
+inapt companion to the memory of this fierce woman.
+
+She saw me as I advanced, and rose for a moment to receive me. I thought
+her, then, still more colourless and thin than when I had seen her last;
+the flashing eyes still brighter, and the scar still plainer.
+
+Our meeting was not cordial. We had parted angrily on the last occasion;
+and there was an air of disdain about her, which she took no pains to
+conceal.
+
+'I am told you wish to speak to me, Miss Dartle,' said I, standing near
+her, with my hand upon the back of the seat, and declining her gesture
+of invitation to sit down.
+
+'If you please,' said she. 'Pray has this girl been found?'
+
+'No.'
+
+'And yet she has run away!'
+
+I saw her thin lips working while she looked at me, as if they were
+eager to load her with reproaches.
+
+'Run away?' I repeated.
+
+'Yes! From him,' she said, with a laugh. 'If she is not found, perhaps
+she never will be found. She may be dead!'
+
+The vaunting cruelty with which she met my glance, I never saw expressed
+in any other face that ever I have seen.
+
+'To wish her dead,' said I, 'may be the kindest wish that one of her own
+sex could bestow upon her. I am glad that time has softened you so much,
+Miss Dartle.'
+
+She condescended to make no reply, but, turning on me with another
+scornful laugh, said:
+
+'The friends of this excellent and much-injured young lady are friends
+of yours. You are their champion, and assert their rights. Do you wish
+to know what is known of her?'
+
+'Yes,' said I.
+
+She rose with an ill-favoured smile, and taking a few steps towards
+a wall of holly that was near at hand, dividing the lawn from a
+kitchen-garden, said, in a louder voice, 'Come here!'--as if she were
+calling to some unclean beast.
+
+'You will restrain any demonstrative championship or vengeance in this
+place, of course, Mr. Copperfield?' said she, looking over her shoulder
+at me with the same expression.
+
+I inclined my head, without knowing what she meant; and she said, 'Come
+here!' again; and returned, followed by the respectable Mr. Littimer,
+who, with undiminished respectability, made me a bow, and took up his
+position behind her. The air of wicked grace: of triumph, in which,
+strange to say, there was yet something feminine and alluring: with
+which she reclined upon the seat between us, and looked at me, was
+worthy of a cruel Princess in a Legend.
+
+'Now,' said she, imperiously, without glancing at him, and touching
+the old wound as it throbbed: perhaps, in this instance, with pleasure
+rather than pain. 'Tell Mr. Copperfield about the flight.'
+
+'Mr. James and myself, ma'am--'
+
+'Don't address yourself to me!' she interrupted with a frown.
+
+'Mr. James and myself, sir--'
+
+'Nor to me, if you please,' said I.
+
+Mr. Littimer, without being at all discomposed, signified by a slight
+obeisance, that anything that was most agreeable to us was most
+agreeable to him; and began again.
+
+'Mr. James and myself have been abroad with the young woman, ever
+since she left Yarmouth under Mr. james's protection. We have been in a
+variety of places, and seen a deal of foreign country. We have been in
+France, Switzerland, Italy, in fact, almost all parts.'
+
+He looked at the back of the seat, as if he were addressing himself to
+that; and softly played upon it with his hands, as if he were striking
+chords upon a dumb piano.
+
+'Mr. James took quite uncommonly to the young woman; and was more
+settled, for a length of time, than I have known him to be since I have
+been in his service. The young woman was very improvable, and spoke the
+languages; and wouldn't have been known for the same country-person. I
+noticed that she was much admired wherever we went.'
+
+Miss Dartle put her hand upon her side. I saw him steal a glance at her,
+and slightly smile to himself.
+
+'Very much admired, indeed, the young woman was. What with her dress;
+what with the air and sun; what with being made so much of; what with
+this, that, and the other; her merits really attracted general notice.'
+
+He made a short pause. Her eyes wandered restlessly over the distant
+prospect, and she bit her nether lip to stop that busy mouth.
+
+Taking his hands from the seat, and placing one of them within the
+other, as he settled himself on one leg, Mr. Littimer proceeded, with
+his eyes cast down, and his respectable head a little advanced, and a
+little on one side:
+
+'The young woman went on in this manner for some time, being
+occasionally low in her spirits, until I think she began to weary Mr.
+James by giving way to her low spirits and tempers of that kind; and
+things were not so comfortable. Mr. James he began to be restless again.
+The more restless he got, the worse she got; and I must say, for myself,
+that I had a very difficult time of it indeed between the two. Still
+matters were patched up here, and made good there, over and over again;
+and altogether lasted, I am sure, for a longer time than anybody could
+have expected.'
+
+Recalling her eyes from the distance, she looked at me again now, with
+her former air. Mr. Littimer, clearing his throat behind his hand with a
+respectable short cough, changed legs, and went on:
+
+'At last, when there had been, upon the whole, a good many words and
+reproaches, Mr. James he set off one morning, from the neighbourhood of
+Naples, where we had a villa (the young woman being very partial to
+the sea), and, under pretence of coming back in a day or so, left it in
+charge with me to break it out, that, for the general happiness of all
+concerned, he was'--here an interruption of the short cough--'gone. But
+Mr. James, I must say, certainly did behave extremely honourable; for
+he proposed that the young woman should marry a very respectable person,
+who was fully prepared to overlook the past, and who was, at least, as
+good as anybody the young woman could have aspired to in a regular way:
+her connexions being very common.'
+
+He changed legs again, and wetted his lips. I was convinced that the
+scoundrel spoke of himself, and I saw my conviction reflected in Miss
+Dartle's face.
+
+'This I also had it in charge to communicate. I was willing to do
+anything to relieve Mr. James from his difficulty, and to restore
+harmony between himself and an affectionate parent, who has undergone
+so much on his account. Therefore I undertook the commission. The
+young woman's violence when she came to, after I broke the fact of his
+departure, was beyond all expectations. She was quite mad, and had to
+be held by force; or, if she couldn't have got to a knife, or got to the
+sea, she'd have beaten her head against the marble floor.'
+
+Miss Dartle, leaning back upon the seat, with a light of exultation in
+her face, seemed almost to caress the sounds this fellow had uttered.
+
+'But when I came to the second part of what had been entrusted to me,'
+said Mr. Littimer, rubbing his hands uneasily, 'which anybody might
+have supposed would have been, at all events, appreciated as a kind
+intention, then the young woman came out in her true colours. A more
+outrageous person I never did see. Her conduct was surprisingly bad. She
+had no more gratitude, no more feeling, no more patience, no more reason
+in her, than a stock or a stone. If I hadn't been upon my guard, I am
+convinced she would have had my blood.'
+
+'I think the better of her for it,' said I, indignantly.
+
+Mr. Littimer bent his head, as much as to say, 'Indeed, sir? But you're
+young!' and resumed his narrative.
+
+'It was necessary, in short, for a time, to take away everything nigh
+her, that she could do herself, or anybody else, an injury with, and
+to shut her up close. Notwithstanding which, she got out in the night;
+forced the lattice of a window, that I had nailed up myself; dropped on
+a vine that was trailed below; and never has been seen or heard of, to
+my knowledge, since.'
+
+'She is dead, perhaps,' said Miss Dartle, with a smile, as if she could
+have spurned the body of the ruined girl.
+
+'She may have drowned herself, miss,' returned Mr. Littimer, catching at
+an excuse for addressing himself to somebody. 'It's very possible. Or,
+she may have had assistance from the boatmen, and the boatmen's wives
+and children. Being given to low company, she was very much in the
+habit of talking to them on the beach, Miss Dartle, and sitting by their
+boats. I have known her do it, when Mr. James has been away, whole days.
+Mr. James was far from pleased to find out, once, that she had told the
+children she was a boatman's daughter, and that in her own country, long
+ago, she had roamed about the beach, like them.'
+
+Oh, Emily! Unhappy beauty! What a picture rose before me of her sitting
+on the far-off shore, among the children like herself when she was
+innocent, listening to little voices such as might have called her
+Mother had she been a poor man's wife; and to the great voice of the
+sea, with its eternal 'Never more!'
+
+'When it was clear that nothing could be done, Miss Dartle--'
+
+'Did I tell you not to speak to me?' she said, with stern contempt.
+
+'You spoke to me, miss,' he replied. 'I beg your pardon. But it is my
+service to obey.'
+
+'Do your service,' she returned. 'Finish your story, and go!'
+
+'When it was clear,' he said, with infinite respectability and an
+obedient bow, 'that she was not to be found, I went to Mr. James, at the
+place where it had been agreed that I should write to him, and informed
+him of what had occurred. Words passed between us in consequence, and
+I felt it due to my character to leave him. I could bear, and I have
+borne, a great deal from Mr. James; but he insulted me too far. He hurt
+me. Knowing the unfortunate difference between himself and his mother,
+and what her anxiety of mind was likely to be, I took the liberty of
+coming home to England, and relating--'
+
+'For money which I paid him,' said Miss Dartle to me.
+
+'Just so, ma'am--and relating what I knew. I am not aware,' said Mr.
+Littimer, after a moment's reflection, 'that there is anything else.
+I am at present out of employment, and should be happy to meet with a
+respectable situation.'
+
+Miss Dartle glanced at me, as though she would inquire if there were
+anything that I desired to ask. As there was something which had
+occurred to my mind, I said in reply:
+
+'I could wish to know from this--creature,' I could not bring myself
+to utter any more conciliatory word, 'whether they intercepted a letter
+that was written to her from home, or whether he supposes that she
+received it.'
+
+He remained calm and silent, with his eyes fixed on the ground, and the
+tip of every finger of his right hand delicately poised against the tip
+of every finger of his left.
+
+Miss Dartle turned her head disdainfully towards him.
+
+'I beg your pardon, miss,' he said, awakening from his abstraction,
+'but, however submissive to you, I have my position, though a servant.
+Mr. Copperfield and you, miss, are different people. If Mr. Copperfield
+wishes to know anything from me, I take the liberty of reminding Mr.
+Copperfield that he can put a question to me. I have a character to
+maintain.'
+
+After a momentary struggle with myself, I turned my eyes upon him, and
+said, 'You have heard my question. Consider it addressed to yourself, if
+you choose. What answer do you make?'
+
+'Sir,' he rejoined, with an occasional separation and reunion of those
+delicate tips, 'my answer must be qualified; because, to betray Mr.
+james's confidence to his mother, and to betray it to you, are two
+different actions. It is not probable, I consider, that Mr. James would
+encourage the receipt of letters likely to increase low spirits and
+unpleasantness; but further than that, sir, I should wish to avoid
+going.'
+
+'Is that all?' inquired Miss Dartle of me.
+
+I indicated that I had nothing more to say. 'Except,' I added, as I
+saw him moving off, 'that I understand this fellow's part in the wicked
+story, and that, as I shall make it known to the honest man who has been
+her father from her childhood, I would recommend him to avoid going too
+much into public.'
+
+He had stopped the moment I began, and had listened with his usual
+repose of manner.
+
+'Thank you, sir. But you'll excuse me if I say, sir, that there are
+neither slaves nor slave-drivers in this country, and that people are
+not allowed to take the law into their own hands. If they do, it is
+more to their own peril, I believe, than to other people's. Consequently
+speaking, I am not at all afraid of going wherever I may wish, sir.'
+
+With that, he made a polite bow; and, with another to Miss Dartle, went
+away through the arch in the wall of holly by which he had come. Miss
+Dartle and I regarded each other for a little while in silence; her
+manner being exactly what it was, when she had produced the man.
+
+'He says besides,' she observed, with a slow curling of her lip, 'that
+his master, as he hears, is coasting Spain; and this done, is away
+to gratify his seafaring tastes till he is weary. But this is of no
+interest to you. Between these two proud persons, mother and son, there
+is a wider breach than before, and little hope of its healing, for they
+are one at heart, and time makes each more obstinate and imperious.
+Neither is this of any interest to you; but it introduces what I wish to
+say. This devil whom you make an angel of. I mean this low girl whom he
+picked out of the tide-mud,' with her black eyes full upon me, and her
+passionate finger up, 'may be alive,--for I believe some common things
+are hard to die. If she is, you will desire to have a pearl of such
+price found and taken care of. We desire that, too; that he may not
+by any chance be made her prey again. So far, we are united in one
+interest; and that is why I, who would do her any mischief that so
+coarse a wretch is capable of feeling, have sent for you to hear what
+you have heard.'
+
+I saw, by the change in her face, that someone was advancing behind me.
+It was Mrs. Steerforth, who gave me her hand more coldly than of yore,
+and with an augmentation of her former stateliness of manner, but still,
+I perceived--and I was touched by it--with an ineffaceable remembrance
+of my old love for her son. She was greatly altered. Her fine figure was
+far less upright, her handsome face was deeply marked, and her hair was
+almost white. But when she sat down on the seat, she was a handsome lady
+still; and well I knew the bright eye with its lofty look, that had been
+a light in my very dreams at school.
+
+'Is Mr. Copperfield informed of everything, Rosa?'
+
+'Yes.'
+
+'And has he heard Littimer himself?'
+
+'Yes; I have told him why you wished it.' 'You are a good girl. I have
+had some slight correspondence with your former friend, sir,' addressing
+me, 'but it has not restored his sense of duty or natural obligation.
+Therefore I have no other object in this, than what Rosa has mentioned.
+If, by the course which may relieve the mind of the decent man you
+brought here (for whom I am sorry--I can say no more), my son may be
+saved from again falling into the snares of a designing enemy, well!'
+
+She drew herself up, and sat looking straight before her, far away.
+
+'Madam,' I said respectfully, 'I understand. I assure you I am in no
+danger of putting any strained construction on your motives. But I must
+say, even to you, having known this injured family from childhood,
+that if you suppose the girl, so deeply wronged, has not been cruelly
+deluded, and would not rather die a hundred deaths than take a cup of
+water from your son's hand now, you cherish a terrible mistake.'
+
+'Well, Rosa, well!' said Mrs. Steerforth, as the other was about to
+interpose, 'it is no matter. Let it be. You are married, sir, I am
+told?'
+
+I answered that I had been some time married.
+
+'And are doing well? I hear little in the quiet life I lead, but I
+understand you are beginning to be famous.'
+
+'I have been very fortunate,' I said, 'and find my name connected with
+some praise.'
+
+'You have no mother?'--in a softened voice.
+
+'No.'
+
+'It is a pity,' she returned. 'She would have been proud of you. Good
+night!'
+
+I took the hand she held out with a dignified, unbending air, and it
+was as calm in mine as if her breast had been at peace. Her pride could
+still its very pulses, it appeared, and draw the placid veil before
+her face, through which she sat looking straight before her on the far
+distance.
+
+As I moved away from them along the terrace, I could not help observing
+how steadily they both sat gazing on the prospect, and how it thickened
+and closed around them. Here and there, some early lamps were seen to
+twinkle in the distant city; and in the eastern quarter of the sky
+the lurid light still hovered. But, from the greater part of the broad
+valley interposed, a mist was rising like a sea, which, mingling with
+the darkness, made it seem as if the gathering waters would encompass
+them. I have reason to remember this, and think of it with awe; for
+before I looked upon those two again, a stormy sea had risen to their
+feet.
+
+Reflecting on what had been thus told me, I felt it right that it should
+be communicated to Mr. Peggotty. On the following evening I went into
+London in quest of him. He was always wandering about from place to
+place, with his one object of recovering his niece before him; but was
+more in London than elsewhere. Often and often, now, had I seen him in
+the dead of night passing along the streets, searching, among the few
+who loitered out of doors at those untimely hours, for what he dreaded
+to find.
+
+He kept a lodging over the little chandler's shop in Hungerford Market,
+which I have had occasion to mention more than once, and from which he
+first went forth upon his errand of mercy. Hither I directed my walk. On
+making inquiry for him, I learned from the people of the house that he
+had not gone out yet, and I should find him in his room upstairs.
+
+He was sitting reading by a window in which he kept a few plants. The
+room was very neat and orderly. I saw in a moment that it was always
+kept prepared for her reception, and that he never went out but he
+thought it possible he might bring her home. He had not heard my tap
+at the door, and only raised his eyes when I laid my hand upon his
+shoulder.
+
+'Mas'r Davy! Thankee, sir! thankee hearty, for this visit! Sit ye down.
+You're kindly welcome, sir!'
+
+'Mr. Peggotty,' said I, taking the chair he handed me, 'don't expect
+much! I have heard some news.'
+
+'Of Em'ly!'
+
+He put his hand, in a nervous manner, on his mouth, and turned pale, as
+he fixed his eyes on mine.
+
+'It gives no clue to where she is; but she is not with him.'
+
+He sat down, looking intently at me, and listened in profound silence
+to all I had to tell. I well remember the sense of dignity, beauty even,
+with which the patient gravity of his face impressed me, when, having
+gradually removed his eyes from mine, he sat looking downward, leaning
+his forehead on his hand. He offered no interruption, but remained
+throughout perfectly still. He seemed to pursue her figure through
+the narrative, and to let every other shape go by him, as if it were
+nothing.
+
+When I had done, he shaded his face, and continued silent. I looked out
+of the window for a little while, and occupied myself with the plants.
+
+'How do you fare to feel about it, Mas'r Davy?' he inquired at length.
+
+'I think that she is living,' I replied.
+
+'I doen't know. Maybe the first shock was too rough, and in the wildness
+of her art--! That there blue water as she used to speak on. Could she
+have thowt o' that so many year, because it was to be her grave!'
+
+He said this, musing, in a low, frightened voice; and walked across the
+little room.
+
+'And yet,' he added, 'Mas'r Davy, I have felt so sure as she was
+living--I have know'd, awake and sleeping, as it was so trew that I
+should find her--I have been so led on by it, and held up by it--that I
+doen't believe I can have been deceived. No! Em'ly's alive!'
+
+He put his hand down firmly on the table, and set his sunburnt face into
+a resolute expression.
+
+'My niece, Em'ly, is alive, sir!' he said, steadfastly. 'I doen't know
+wheer it comes from, or how 'tis, but I am told as she's alive!'
+
+He looked almost like a man inspired, as he said it. I waited for a
+few moments, until he could give me his undivided attention; and then
+proceeded to explain the precaution, that, it had occurred to me last
+night, it would be wise to take.
+
+'Now, my dear friend--'I began.
+
+'Thankee, thankee, kind sir,' he said, grasping my hand in both of his.
+
+'If she should make her way to London, which is likely--for where could
+she lose herself so readily as in this vast city; and what would she
+wish to do, but lose and hide herself, if she does not go home?--'
+
+'And she won't go home,' he interposed, shaking his head mournfully. 'If
+she had left of her own accord, she might; not as It was, sir.'
+
+'If she should come here,' said I, 'I believe there is one person,
+here, more likely to discover her than any other in the world. Do
+you remember--hear what I say, with fortitude--think of your great
+object!--do you remember Martha?'
+
+'Of our town?'
+
+I needed no other answer than his face.
+
+'Do you know that she is in London?'
+
+'I have seen her in the streets,' he answered, with a shiver.
+
+'But you don't know,' said I, 'that Emily was charitable to her, with
+Ham's help, long before she fled from home. Nor, that, when we met one
+night, and spoke together in the room yonder, over the way, she listened
+at the door.'
+
+'Mas'r Davy!' he replied in astonishment. 'That night when it snew so
+hard?'
+
+'That night. I have never seen her since. I went back, after parting
+from you, to speak to her, but she was gone. I was unwilling to mention
+her to you then, and I am now; but she is the person of whom I speak,
+and with whom I think we should communicate. Do you understand?'
+
+'Too well, sir,' he replied. We had sunk our voices, almost to a
+whisper, and continued to speak in that tone.
+
+'You say you have seen her. Do you think that you could find her? I
+could only hope to do so by chance.'
+
+'I think, Mas'r Davy, I know wheer to look.'
+
+'It is dark. Being together, shall we go out now, and try to find her
+tonight?'
+
+He assented, and prepared to accompany me. Without appearing to observe
+what he was doing, I saw how carefully he adjusted the little room,
+put a candle ready and the means of lighting it, arranged the bed, and
+finally took out of a drawer one of her dresses (I remember to have
+seen her wear it), neatly folded with some other garments, and a bonnet,
+which he placed upon a chair. He made no allusion to these clothes,
+neither did I. There they had been waiting for her, many and many a
+night, no doubt.
+
+'The time was, Mas'r Davy,' he said, as we came downstairs, 'when I
+thowt this girl, Martha, a'most like the dirt underneath my Em'ly's
+feet. God forgive me, theer's a difference now!'
+
+As we went along, partly to hold him in conversation, and partly to
+satisfy myself, I asked him about Ham. He said, almost in the same words
+as formerly, that Ham was just the same, 'wearing away his life with
+kiender no care nohow for 't; but never murmuring, and liked by all'.
+
+I asked him what he thought Ham's state of mind was, in reference to the
+cause of their misfortunes? Whether he believed it was dangerous? What
+he supposed, for example, Ham would do, if he and Steerforth ever should
+encounter?
+
+'I doen't know, sir,' he replied. 'I have thowt of it oftentimes, but I
+can't awize myself of it, no matters.'
+
+I recalled to his remembrance the morning after her departure, when we
+were all three on the beach. 'Do you recollect,' said I, 'a certain wild
+way in which he looked out to sea, and spoke about "the end of it"?'
+
+'Sure I do!' said he.
+
+'What do you suppose he meant?'
+
+'Mas'r Davy,' he replied, 'I've put the question to myself a mort o'
+times, and never found no answer. And theer's one curious thing--that,
+though he is so pleasant, I wouldn't fare to feel comfortable to try and
+get his mind upon 't. He never said a wured to me as warn't as dootiful
+as dootiful could be, and it ain't likely as he'd begin to speak any
+other ways now; but it's fur from being fleet water in his mind, where
+them thowts lays. It's deep, sir, and I can't see down.'
+
+'You are right,' said I, 'and that has sometimes made me anxious.'
+
+'And me too, Mas'r Davy,' he rejoined. 'Even more so, I do assure you,
+than his ventersome ways, though both belongs to the alteration in him.
+I doen't know as he'd do violence under any circumstances, but I hope as
+them two may be kep asunders.'
+
+We had come, through Temple Bar, into the city. Conversing no more now,
+and walking at my side, he yielded himself up to the one aim of his
+devoted life, and went on, with that hushed concentration of his
+faculties which would have made his figure solitary in a multitude.
+We were not far from Blackfriars Bridge, when he turned his head and
+pointed to a solitary female figure flitting along the opposite side of
+the street. I knew it, readily, to be the figure that we sought.
+
+We crossed the road, and were pressing on towards her, when it occurred
+to me that she might be more disposed to feel a woman's interest in the
+lost girl, if we spoke to her in a quieter place, aloof from the crowd,
+and where we should be less observed. I advised my companion, therefore,
+that we should not address her yet, but follow her; consulting in this,
+likewise, an indistinct desire I had, to know where she went.
+
+He acquiescing, we followed at a distance: never losing sight of her,
+but never caring to come very near, as she frequently looked about.
+Once, she stopped to listen to a band of music; and then we stopped too.
+
+She went on a long way. Still we went on. It was evident, from the
+manner in which she held her course, that she was going to some fixed
+destination; and this, and her keeping in the busy streets, and I
+suppose the strange fascination in the secrecy and mystery of so
+following anyone, made me adhere to my first purpose. At length she
+turned into a dull, dark street, where the noise and crowd were lost;
+and I said, 'We may speak to her now'; and, mending our pace, we went
+after her.
+
+
+CHAPTER 47. MARTHA
+
+
+We were now down in Westminster. We had turned back to follow her,
+having encountered her coming towards us; and Westminster Abbey was
+the point at which she passed from the lights and noise of the leading
+streets. She proceeded so quickly, when she got free of the two currents
+of passengers setting towards and from the bridge, that, between this
+and the advance she had of us when she struck off, we were in the narrow
+water-side street by Millbank before we came up with her. At that moment
+she crossed the road, as if to avoid the footsteps that she heard so
+close behind; and, without looking back, passed on even more rapidly.
+
+A glimpse of the river through a dull gateway, where some waggons were
+housed for the night, seemed to arrest my feet. I touched my companion
+without speaking, and we both forbore to cross after her, and both
+followed on that opposite side of the way; keeping as quietly as we
+could in the shadow of the houses, but keeping very near her.
+
+There was, and is when I write, at the end of that low-lying street,
+a dilapidated little wooden building, probably an obsolete old
+ferry-house. Its position is just at that point where the street ceases,
+and the road begins to lie between a row of houses and the river. As
+soon as she came here, and saw the water, she stopped as if she had come
+to her destination; and presently went slowly along by the brink of the
+river, looking intently at it.
+
+All the way here, I had supposed that she was going to some house;
+indeed, I had vaguely entertained the hope that the house might be in
+some way associated with the lost girl. But that one dark glimpse of the
+river, through the gateway, had instinctively prepared me for her going
+no farther.
+
+The neighbourhood was a dreary one at that time; as oppressive, sad, and
+solitary by night, as any about London. There were neither wharves nor
+houses on the melancholy waste of road near the great blank Prison. A
+sluggish ditch deposited its mud at the prison walls. Coarse grass and
+rank weeds straggled over all the marshy land in the vicinity. In one
+part, carcases of houses, inauspiciously begun and never finished,
+rotted away. In another, the ground was cumbered with rusty iron
+monsters of steam-boilers, wheels, cranks, pipes, furnaces, paddles,
+anchors, diving-bells, windmill-sails, and I know not what strange
+objects, accumulated by some speculator, and grovelling in the dust,
+underneath which--having sunk into the soil of their own weight in wet
+weather--they had the appearance of vainly trying to hide themselves.
+The clash and glare of sundry fiery Works upon the river-side, arose
+by night to disturb everything except the heavy and unbroken smoke that
+poured out of their chimneys. Slimy gaps and causeways, winding among
+old wooden piles, with a sickly substance clinging to the latter, like
+green hair, and the rags of last year's handbills offering rewards for
+drowned men fluttering above high-water mark, led down through the ooze
+and slush to the ebb-tide. There was a story that one of the pits
+dug for the dead in the time of the Great Plague was hereabout; and
+a blighting influence seemed to have proceeded from it over the whole
+place. Or else it looked as if it had gradually decomposed into that
+nightmare condition, out of the overflowings of the polluted stream.
+
+As if she were a part of the refuse it had cast out, and left to
+corruption and decay, the girl we had followed strayed down to the
+river's brink, and stood in the midst of this night-picture, lonely and
+still, looking at the water.
+
+There were some boats and barges astrand in the mud, and these enabled
+us to come within a few yards of her without being seen. I then signed
+to Mr. Peggotty to remain where he was, and emerged from their shade to
+speak to her. I did not approach her solitary figure without trembling;
+for this gloomy end to her determined walk, and the way in which she
+stood, almost within the cavernous shadow of the iron bridge, looking
+at the lights crookedly reflected in the strong tide, inspired a dread
+within me.
+
+I think she was talking to herself. I am sure, although absorbed in
+gazing at the water, that her shawl was off her shoulders, and that she
+was muffling her hands in it, in an unsettled and bewildered way, more
+like the action of a sleep-walker than a waking person. I know, and
+never can forget, that there was that in her wild manner which gave me
+no assurance but that she would sink before my eyes, until I had her arm
+within my grasp.
+
+At the same moment I said 'Martha!'
+
+She uttered a terrified scream, and struggled with me with such strength
+that I doubt if I could have held her alone. But a stronger hand than
+mine was laid upon her; and when she raised her frightened eyes and saw
+whose it was, she made but one more effort and dropped down between us.
+We carried her away from the water to where there were some dry stones,
+and there laid her down, crying and moaning. In a little while she sat
+among the stones, holding her wretched head with both her hands.
+
+'Oh, the river!' she cried passionately. 'Oh, the river!'
+
+'Hush, hush!' said I. 'Calm yourself.'
+
+But she still repeated the same words, continually exclaiming, 'Oh, the
+river!' over and over again.
+
+'I know it's like me!' she exclaimed. 'I know that I belong to it.
+I know that it's the natural company of such as I am! It comes from
+country places, where there was once no harm in it--and it creeps
+through the dismal streets, defiled and miserable--and it goes away,
+like my life, to a great sea, that is always troubled--and I feel that
+I must go with it!' I have never known what despair was, except in the
+tone of those words.
+
+'I can't keep away from it. I can't forget it. It haunts me day and
+night. It's the only thing in all the world that I am fit for, or that's
+fit for me. Oh, the dreadful river!'
+
+The thought passed through my mind that in the face of my companion,
+as he looked upon her without speech or motion, I might have read his
+niece's history, if I had known nothing of it. I never saw, in any
+painting or reality, horror and compassion so impressively blended. He
+shook as if he would have fallen; and his hand--I touched it with my
+own, for his appearance alarmed me--was deadly cold.
+
+'She is in a state of frenzy,' I whispered to him. 'She will speak
+differently in a little time.'
+
+I don't know what he would have said in answer. He made some motion with
+his mouth, and seemed to think he had spoken; but he had only pointed to
+her with his outstretched hand.
+
+A new burst of crying came upon her now, in which she once more hid
+her face among the stones, and lay before us, a prostrate image of
+humiliation and ruin. Knowing that this state must pass, before we could
+speak to her with any hope, I ventured to restrain him when he would
+have raised her, and we stood by in silence until she became more
+tranquil.
+
+'Martha,' said I then, leaning down, and helping her to rise--she seemed
+to want to rise as if with the intention of going away, but she was
+weak, and leaned against a boat. 'Do you know who this is, who is with
+me?'
+
+She said faintly, 'Yes.'
+
+'Do you know that we have followed you a long way tonight?'
+
+She shook her head. She looked neither at him nor at me, but stood in
+a humble attitude, holding her bonnet and shawl in one hand, without
+appearing conscious of them, and pressing the other, clenched, against
+her forehead.
+
+'Are you composed enough,' said I, 'to speak on the subject which so
+interested you--I hope Heaven may remember it!--that snowy night?'
+
+Her sobs broke out afresh, and she murmured some inarticulate thanks to
+me for not having driven her away from the door.
+
+'I want to say nothing for myself,' she said, after a few moments. 'I
+am bad, I am lost. I have no hope at all. But tell him, sir,' she had
+shrunk away from him, 'if you don't feel too hard to me to do it, that
+I never was in any way the cause of his misfortune.' 'It has never been
+attributed to you,' I returned, earnestly responding to her earnestness.
+
+'It was you, if I don't deceive myself,' she said, in a broken voice,
+'that came into the kitchen, the night she took such pity on me; was so
+gentle to me; didn't shrink away from me like all the rest, and gave me
+such kind help! Was it you, sir?'
+
+'It was,' said I.
+
+'I should have been in the river long ago,' she said, glancing at it
+with a terrible expression, 'if any wrong to her had been upon my mind.
+I never could have kept out of it a single winter's night, if I had not
+been free of any share in that!'
+
+'The cause of her flight is too well understood,' I said. 'You are
+innocent of any part in it, we thoroughly believe,--we know.'
+
+'Oh, I might have been much the better for her, if I had had a better
+heart!' exclaimed the girl, with most forlorn regret; 'for she was
+always good to me! She never spoke a word to me but what was pleasant
+and right. Is it likely I would try to make her what I am myself,
+knowing what I am myself, so well? When I lost everything that makes
+life dear, the worst of all my thoughts was that I was parted for ever
+from her!'
+
+Mr. Peggotty, standing with one hand on the gunwale of the boat, and his
+eyes cast down, put his disengaged hand before his face.
+
+'And when I heard what had happened before that snowy night, from some
+belonging to our town,' cried Martha, 'the bitterest thought in all my
+mind was, that the people would remember she once kept company with me,
+and would say I had corrupted her! When, Heaven knows, I would have died
+to have brought back her good name!'
+
+Long unused to any self-control, the piercing agony of her remorse and
+grief was terrible.
+
+'To have died, would not have been much--what can I say?---I would
+have lived!' she cried. 'I would have lived to be old, in the wretched
+streets--and to wander about, avoided, in the dark--and to see the day
+break on the ghastly line of houses, and remember how the same sun used
+to shine into my room, and wake me once--I would have done even that, to
+save her!'
+
+Sinking on the stones, she took some in each hand, and clenched them
+up, as if she would have ground them. She writhed into some new posture
+constantly: stiffening her arms, twisting them before her face, as
+though to shut out from her eyes the little light there was, and
+drooping her head, as if it were heavy with insupportable recollections.
+
+'What shall I ever do!' she said, fighting thus with her despair. 'How
+can I go on as I am, a solitary curse to myself, a living disgrace to
+everyone I come near!' Suddenly she turned to my companion. 'Stamp upon
+me, kill me! When she was your pride, you would have thought I had
+done her harm if I had brushed against her in the street. You can't
+believe--why should you?---a syllable that comes out of my lips. It
+would be a burning shame upon you, even now, if she and I exchanged a
+word. I don't complain. I don't say she and I are alike--I know there
+is a long, long way between us. I only say, with all my guilt and
+wretchedness upon my head, that I am grateful to her from my soul, and
+love her. Oh, don't think that all the power I had of loving anything is
+quite worn out! Throw me away, as all the world does. Kill me for being
+what I am, and having ever known her; but don't think that of me!'
+
+He looked upon her, while she made this supplication, in a wild
+distracted manner; and, when she was silent, gently raised her.
+
+'Martha,' said Mr. Peggotty, 'God forbid as I should judge you. Forbid
+as I, of all men, should do that, my girl! You doen't know half the
+change that's come, in course of time, upon me, when you think it
+likely. Well!' he paused a moment, then went on. 'You doen't understand
+how 'tis that this here gentleman and me has wished to speak to you. You
+doen't understand what 'tis we has afore us. Listen now!'
+
+His influence upon her was complete. She stood, shrinkingly, before him,
+as if she were afraid to meet his eyes; but her passionate sorrow was
+quite hushed and mute.
+
+'If you heerd,' said Mr. Peggotty, 'owt of what passed between Mas'r
+Davy and me, th' night when it snew so hard, you know as I have
+been--wheer not--fur to seek my dear niece. My dear niece,' he repeated
+steadily. 'Fur she's more dear to me now, Martha, than she was dear
+afore.'
+
+She put her hands before her face; but otherwise remained quiet.
+
+'I have heerd her tell,' said Mr. Peggotty, 'as you was early left
+fatherless and motherless, with no friend fur to take, in a rough
+seafaring-way, their place. Maybe you can guess that if you'd had such
+a friend, you'd have got into a way of being fond of him in course of
+time, and that my niece was kiender daughter-like to me.'
+
+As she was silently trembling, he put her shawl carefully about her,
+taking it up from the ground for that purpose.
+
+'Whereby,' said he, 'I know, both as she would go to the wureld's
+furdest end with me, if she could once see me again; and that she would
+fly to the wureld's furdest end to keep off seeing me. For though she
+ain't no call to doubt my love, and doen't--and doen't,' he repeated,
+with a quiet assurance of the truth of what he said, 'there's shame
+steps in, and keeps betwixt us.'
+
+I read, in every word of his plain impressive way of delivering himself,
+new evidence of his having thought of this one topic, in every feature
+it presented.
+
+'According to our reckoning,' he proceeded, 'Mas'r Davy's here, and
+mine, she is like, one day, to make her own poor solitary course to
+London. We believe--Mas'r Davy, me, and all of us--that you are as
+innocent of everything that has befell her, as the unborn child. You've
+spoke of her being pleasant, kind, and gentle to you. Bless her, I knew
+she was! I knew she always was, to all. You're thankful to her, and you
+love her. Help us all you can to find her, and may Heaven reward you!'
+
+She looked at him hastily, and for the first time, as if she were
+doubtful of what he had said.
+
+'Will you trust me?' she asked, in a low voice of astonishment.
+
+'Full and free!' said Mr. Peggotty.
+
+'To speak to her, if I should ever find her; shelter her, if I have any
+shelter to divide with her; and then, without her knowledge, come to
+you, and bring you to her?' she asked hurriedly.
+
+We both replied together, 'Yes!'
+
+She lifted up her eyes, and solemnly declared that she would devote
+herself to this task, fervently and faithfully. That she would never
+waver in it, never be diverted from it, never relinquish it, while there
+was any chance of hope. If she were not true to it, might the object
+she now had in life, which bound her to something devoid of evil, in its
+passing away from her, leave her more forlorn and more despairing, if
+that were possible, than she had been upon the river's brink that night;
+and then might all help, human and Divine, renounce her evermore!
+
+She did not raise her voice above her breath, or address us, but said
+this to the night sky; then stood profoundly quiet, looking at the
+gloomy water.
+
+We judged it expedient, now, to tell her all we knew; which I recounted
+at length. She listened with great attention, and with a face that often
+changed, but had the same purpose in all its varying expressions. Her
+eyes occasionally filled with tears, but those she repressed. It seemed
+as if her spirit were quite altered, and she could not be too quiet.
+
+She asked, when all was told, where we were to be communicated with, if
+occasion should arise. Under a dull lamp in the road, I wrote our two
+addresses on a leaf of my pocket-book, which I tore out and gave to
+her, and which she put in her poor bosom. I asked her where she lived
+herself. She said, after a pause, in no place long. It were better not
+to know.
+
+Mr. Peggotty suggesting to me, in a whisper, what had already occurred
+to myself, I took out my purse; but I could not prevail upon her to
+accept any money, nor could I exact any promise from her that she would
+do so at another time. I represented to her that Mr. Peggotty could
+not be called, for one in his condition, poor; and that the idea of her
+engaging in this search, while depending on her own resources, shocked
+us both. She continued steadfast. In this particular, his influence
+upon her was equally powerless with mine. She gratefully thanked him but
+remained inexorable.
+
+'There may be work to be got,' she said. 'I'll try.'
+
+'At least take some assistance,' I returned, 'until you have tried.'
+
+'I could not do what I have promised, for money,' she replied. 'I could
+not take it, if I was starving. To give me money would be to take away
+your trust, to take away the object that you have given me, to take away
+the only certain thing that saves me from the river.'
+
+'In the name of the great judge,' said I, 'before whom you and all of us
+must stand at His dread time, dismiss that terrible idea! We can all do
+some good, if we will.'
+
+She trembled, and her lip shook, and her face was paler, as she
+answered:
+
+'It has been put into your hearts, perhaps, to save a wretched creature
+for repentance. I am afraid to think so; it seems too bold. If any good
+should come of me, I might begin to hope; for nothing but harm has ever
+come of my deeds yet. I am to be trusted, for the first time in a long
+while, with my miserable life, on account of what you have given me to
+try for. I know no more, and I can say no more.'
+
+Again she repressed the tears that had begun to flow; and, putting out
+her trembling hand, and touching Mr. Peggotty, as if there was some
+healing virtue in him, went away along the desolate road. She had been
+ill, probably for a long time. I observed, upon that closer opportunity
+of observation, that she was worn and haggard, and that her sunken eyes
+expressed privation and endurance.
+
+We followed her at a short distance, our way lying in the same
+direction, until we came back into the lighted and populous streets. I
+had such implicit confidence in her declaration, that I then put it to
+Mr. Peggotty, whether it would not seem, in the onset, like distrusting
+her, to follow her any farther. He being of the same mind, and equally
+reliant on her, we suffered her to take her own road, and took ours,
+which was towards Highgate. He accompanied me a good part of the way;
+and when we parted, with a prayer for the success of this fresh effort,
+there was a new and thoughtful compassion in him that I was at no loss
+to interpret.
+
+It was midnight when I arrived at home. I had reached my own gate, and
+was standing listening for the deep bell of St. Paul's, the sound
+of which I thought had been borne towards me among the multitude of
+striking clocks, when I was rather surprised to see that the door of my
+aunt's cottage was open, and that a faint light in the entry was shining
+out across the road.
+
+Thinking that my aunt might have relapsed into one of her old alarms,
+and might be watching the progress of some imaginary conflagration in
+the distance, I went to speak to her. It was with very great surprise
+that I saw a man standing in her little garden.
+
+He had a glass and bottle in his hand, and was in the act of drinking. I
+stopped short, among the thick foliage outside, for the moon was up now,
+though obscured; and I recognized the man whom I had once supposed to be
+a delusion of Mr. Dick's, and had once encountered with my aunt in the
+streets of the city.
+
+He was eating as well as drinking, and seemed to eat with a hungry
+appetite. He seemed curious regarding the cottage, too, as if it were
+the first time he had seen it. After stooping to put the bottle on the
+ground, he looked up at the windows, and looked about; though with a
+covert and impatient air, as if he was anxious to be gone.
+
+The light in the passage was obscured for a moment, and my aunt came
+out. She was agitated, and told some money into his hand. I heard it
+chink.
+
+'What's the use of this?' he demanded.
+
+'I can spare no more,' returned my aunt.
+
+'Then I can't go,' said he. 'Here! You may take it back!'
+
+'You bad man,' returned my aunt, with great emotion; 'how can you use me
+so? But why do I ask? It is because you know how weak I am! What have
+I to do, to free myself for ever of your visits, but to abandon you to
+your deserts?'
+
+'And why don't you abandon me to my deserts?' said he.
+
+'You ask me why!' returned my aunt. 'What a heart you must have!'
+
+He stood moodily rattling the money, and shaking his head, until at
+length he said:
+
+'Is this all you mean to give me, then?'
+
+'It is all I CAN give you,' said my aunt. 'You know I have had losses,
+and am poorer than I used to be. I have told you so. Having got it, why
+do you give me the pain of looking at you for another moment, and seeing
+what you have become?'
+
+'I have become shabby enough, if you mean that,' he said. 'I lead the
+life of an owl.'
+
+'You stripped me of the greater part of all I ever had,' said my aunt.
+'You closed my heart against the whole world, years and years. You
+treated me falsely, ungratefully, and cruelly. Go, and repent of it.
+Don't add new injuries to the long, long list of injuries you have done
+me!'
+
+'Aye!' he returned. 'It's all very fine--Well! I must do the best I can,
+for the present, I suppose.'
+
+In spite of himself, he appeared abashed by my aunt's indignant tears,
+and came slouching out of the garden. Taking two or three quick steps,
+as if I had just come up, I met him at the gate, and went in as he came
+out. We eyed one another narrowly in passing, and with no favour.
+
+'Aunt,' said I, hurriedly. 'This man alarming you again! Let me speak to
+him. Who is he?'
+
+'Child,' returned my aunt, taking my arm, 'come in, and don't speak to
+me for ten minutes.'
+
+We sat down in her little parlour. My aunt retired behind the round
+green fan of former days, which was screwed on the back of a chair, and
+occasionally wiped her eyes, for about a quarter of an hour. Then she
+came out, and took a seat beside me.
+
+'Trot,' said my aunt, calmly, 'it's my husband.'
+
+'Your husband, aunt? I thought he had been dead!'
+
+'Dead to me,' returned my aunt, 'but living.'
+
+I sat in silent amazement.
+
+'Betsey Trotwood don't look a likely subject for the tender passion,'
+said my aunt, composedly, 'but the time was, Trot, when she believed in
+that man most entirely. When she loved him, Trot, right well. When there
+was no proof of attachment and affection that she would not have given
+him. He repaid her by breaking her fortune, and nearly breaking her
+heart. So she put all that sort of sentiment, once and for ever, in a
+grave, and filled it up, and flattened it down.'
+
+'My dear, good aunt!'
+
+'I left him,' my aunt proceeded, laying her hand as usual on the back of
+mine, 'generously. I may say at this distance of time, Trot, that I left
+him generously. He had been so cruel to me, that I might have effected
+a separation on easy terms for myself; but I did not. He soon made ducks
+and drakes of what I gave him, sank lower and lower, married another
+woman, I believe, became an adventurer, a gambler, and a cheat. What he
+is now, you see. But he was a fine-looking man when I married him,' said
+my aunt, with an echo of her old pride and admiration in her tone; 'and
+I believed him--I was a fool!--to be the soul of honour!'
+
+She gave my hand a squeeze, and shook her head.
+
+'He is nothing to me now, Trot--less than nothing. But, sooner than have
+him punished for his offences (as he would be if he prowled about in
+this country), I give him more money than I can afford, at intervals
+when he reappears, to go away. I was a fool when I married him; and I am
+so far an incurable fool on that subject, that, for the sake of what
+I once believed him to be, I wouldn't have even this shadow of my idle
+fancy hardly dealt with. For I was in earnest, Trot, if ever a woman
+was.'
+
+MY aunt dismissed the matter with a heavy sigh, and smoothed her dress.
+
+'There, my dear!' she said. 'Now you know the beginning, middle, and
+end, and all about it. We won't mention the subject to one another any
+more; neither, of course, will you mention it to anybody else. This is
+my grumpy, frumpy story, and we'll keep it to ourselves, Trot!'
+
+
+
+CHAPTER 48. DOMESTIC
+
+
+I laboured hard at my book, without allowing it to interfere with the
+punctual discharge of my newspaper duties; and it came out and was very
+successful. I was not stunned by the praise which sounded in my ears,
+notwithstanding that I was keenly alive to it, and thought better of
+my own performance, I have little doubt, than anybody else did. It has
+always been in my observation of human nature, that a man who has any
+good reason to believe in himself never flourishes himself before the
+faces of other people in order that they may believe in him. For this
+reason, I retained my modesty in very self-respect; and the more praise
+I got, the more I tried to deserve.
+
+It is not my purpose, in this record, though in all other essentials
+it is my written memory, to pursue the history of my own fictions. They
+express themselves, and I leave them to themselves. When I refer to
+them, incidentally, it is only as a part of my progress.
+
+Having some foundation for believing, by this time, that nature and
+accident had made me an author, I pursued my vocation with confidence.
+Without such assurance I should certainly have left it alone, and
+bestowed my energy on some other endeavour. I should have tried to find
+out what nature and accident really had made me, and to be that, and
+nothing else. I had been writing, in the newspaper and elsewhere, so
+prosperously, that when my new success was achieved, I considered myself
+reasonably entitled to escape from the dreary debates. One joyful night,
+therefore, I noted down the music of the parliamentary bagpipes for the
+last time, and I have never heard it since; though I still recognize the
+old drone in the newspapers, without any substantial variation (except,
+perhaps, that there is more of it), all the livelong session.
+
+I now write of the time when I had been married, I suppose, about a year
+and a half. After several varieties of experiment, we had given up the
+housekeeping as a bad job. The house kept itself, and we kept a page.
+The principal function of this retainer was to quarrel with the cook;
+in which respect he was a perfect Whittington, without his cat, or the
+remotest chance of being made Lord Mayor.
+
+He appears to me to have lived in a hail of saucepan-lids. His whole
+existence was a scuffle. He would shriek for help on the most improper
+occasions,--as when we had a little dinner-party, or a few friends in
+the evening,--and would come tumbling out of the kitchen, with iron
+missiles flying after him. We wanted to get rid of him, but he was very
+much attached to us, and wouldn't go. He was a tearful boy, and broke
+into such deplorable lamentations, when a cessation of our connexion
+was hinted at, that we were obliged to keep him. He had no mother--no
+anything in the way of a relative, that I could discover, except a
+sister, who fled to America the moment we had taken him off her hands;
+and he became quartered on us like a horrible young changeling. He had
+a lively perception of his own unfortunate state, and was always rubbing
+his eyes with the sleeve of his jacket, or stooping to blow his nose on
+the extreme corner of a little pocket-handkerchief, which he never would
+take completely out of his pocket, but always economized and secreted.
+
+This unlucky page, engaged in an evil hour at six pounds ten per annum,
+was a source of continual trouble to me. I watched him as he grew--and
+he grew like scarlet beans--with painful apprehensions of the time when
+he would begin to shave; even of the days when he would be bald or grey.
+I saw no prospect of ever getting rid of him; and, projecting myself
+into the future, used to think what an inconvenience he would be when he
+was an old man.
+
+I never expected anything less, than this unfortunate's manner of
+getting me out of my difficulty. He stole Dora's watch, which, like
+everything else belonging to us, had no particular place of its own;
+and, converting it into money, spent the produce (he was always a
+weak-minded boy) in incessantly riding up and down between London and
+Uxbridge outside the coach. He was taken to Bow Street, as well as
+I remember, on the completion of his fifteenth journey; when
+four-and-sixpence, and a second-hand fife which he couldn't play, were
+found upon his person.
+
+The surprise and its consequences would have been much less disagreeable
+to me if he had not been penitent. But he was very penitent indeed, and
+in a peculiar way--not in the lump, but by instalments. For example:
+the day after that on which I was obliged to appear against him, he made
+certain revelations touching a hamper in the cellar, which we believed
+to be full of wine, but which had nothing in it except bottles and
+corks. We supposed he had now eased his mind, and told the worst he knew
+of the cook; but, a day or two afterwards, his conscience sustained a
+new twinge, and he disclosed how she had a little girl, who, early every
+morning, took away our bread; and also how he himself had been suborned
+to maintain the milkman in coals. In two or three days more, I was
+informed by the authorities of his having led to the discovery of
+sirloins of beef among the kitchen-stuff, and sheets in the rag-bag. A
+little while afterwards, he broke out in an entirely new direction, and
+confessed to a knowledge of burglarious intentions as to our premises,
+on the part of the pot-boy, who was immediately taken up. I got to be so
+ashamed of being such a victim, that I would have given him any money
+to hold his tongue, or would have offered a round bribe for his being
+permitted to run away. It was an aggravating circumstance in the case
+that he had no idea of this, but conceived that he was making me amends
+in every new discovery: not to say, heaping obligations on my head.
+
+At last I ran away myself, whenever I saw an emissary of the police
+approaching with some new intelligence; and lived a stealthy life until
+he was tried and ordered to be transported. Even then he couldn't be
+quiet, but was always writing us letters; and wanted so much to see Dora
+before he went away, that Dora went to visit him, and fainted when she
+found herself inside the iron bars. In short, I had no peace of my life
+until he was expatriated, and made (as I afterwards heard) a shepherd
+of, 'up the country' somewhere; I have no geographical idea where.
+
+All this led me into some serious reflections, and presented our
+mistakes in a new aspect; as I could not help communicating to Dora one
+evening, in spite of my tenderness for her.
+
+'My love,' said I, 'it is very painful to me to think that our want of
+system and management, involves not only ourselves (which we have got
+used to), but other people.'
+
+'You have been silent for a long time, and now you are going to be
+cross!' said Dora.
+
+'No, my dear, indeed! Let me explain to you what I mean.'
+
+'I think I don't want to know,' said Dora.
+
+'But I want you to know, my love. Put Jip down.'
+
+Dora put his nose to mine, and said 'Boh!' to drive my seriousness away;
+but, not succeeding, ordered him into his Pagoda, and sat looking at
+me, with her hands folded, and a most resigned little expression of
+countenance.
+
+'The fact is, my dear,' I began, 'there is contagion in us. We infect
+everyone about us.'
+
+I might have gone on in this figurative manner, if Dora's face had not
+admonished me that she was wondering with all her might whether I was
+going to propose any new kind of vaccination, or other medical remedy,
+for this unwholesome state of ours. Therefore I checked myself, and made
+my meaning plainer.
+
+'It is not merely, my pet,' said I, 'that we lose money and comfort, and
+even temper sometimes, by not learning to be more careful; but that we
+incur the serious responsibility of spoiling everyone who comes into
+our service, or has any dealings with us. I begin to be afraid that the
+fault is not entirely on one side, but that these people all turn out
+ill because we don't turn out very well ourselves.'
+
+'Oh, what an accusation,' exclaimed Dora, opening her eyes wide; 'to say
+that you ever saw me take gold watches! Oh!'
+
+'My dearest,' I remonstrated, 'don't talk preposterous nonsense! Who has
+made the least allusion to gold watches?'
+
+'You did,' returned Dora. 'You know you did. You said I hadn't turned
+out well, and compared me to him.'
+
+'To whom?' I asked.
+
+'To the page,' sobbed Dora. 'Oh, you cruel fellow, to compare your
+affectionate wife to a transported page! Why didn't you tell me
+your opinion of me before we were married? Why didn't you say,
+you hard-hearted thing, that you were convinced I was worse than a
+transported page? Oh, what a dreadful opinion to have of me! Oh, my
+goodness!'
+
+'Now, Dora, my love,' I returned, gently trying to remove the
+handkerchief she pressed to her eyes, 'this is not only very ridiculous
+of you, but very wrong. In the first place, it's not true.'
+
+'You always said he was a story-teller,' sobbed Dora. 'And now you say
+the same of me! Oh, what shall I do! What shall I do!'
+
+'My darling girl,' I retorted, 'I really must entreat you to be
+reasonable, and listen to what I did say, and do say. My dear Dora,
+unless we learn to do our duty to those whom we employ, they will never
+learn to do their duty to us. I am afraid we present opportunities to
+people to do wrong, that never ought to be presented. Even if we were
+as lax as we are, in all our arrangements, by choice--which we are
+not--even if we liked it, and found it agreeable to be so--which we
+don't--I am persuaded we should have no right to go on in this way. We
+are positively corrupting people. We are bound to think of that. I can't
+help thinking of it, Dora. It is a reflection I am unable to dismiss,
+and it sometimes makes me very uneasy. There, dear, that's all. Come
+now. Don't be foolish!'
+
+Dora would not allow me, for a long time, to remove the handkerchief.
+She sat sobbing and murmuring behind it, that, if I was uneasy, why had
+I ever been married? Why hadn't I said, even the day before we went to
+church, that I knew I should be uneasy, and I would rather not? If I
+couldn't bear her, why didn't I send her away to her aunts at Putney, or
+to Julia Mills in India? Julia would be glad to see her, and would not
+call her a transported page; Julia never had called her anything of the
+sort. In short, Dora was so afflicted, and so afflicted me by being
+in that condition, that I felt it was of no use repeating this kind of
+effort, though never so mildly, and I must take some other course.
+
+What other course was left to take? To 'form her mind'? This was a
+common phrase of words which had a fair and promising sound, and I
+resolved to form Dora's mind.
+
+I began immediately. When Dora was very childish, and I would
+have infinitely preferred to humour her, I tried to be grave--and
+disconcerted her, and myself too. I talked to her on the subjects which
+occupied my thoughts; and I read Shakespeare to her--and fatigued her
+to the last degree. I accustomed myself to giving her, as it were quite
+casually, little scraps of useful information, or sound opinion--and she
+started from them when I let them off, as if they had been crackers.
+No matter how incidentally or naturally I endeavoured to form my little
+wife's mind, I could not help seeing that she always had an instinctive
+perception of what I was about, and became a prey to the keenest
+apprehensions. In particular, it was clear to me, that she thought
+Shakespeare a terrible fellow. The formation went on very slowly.
+
+I pressed Traddles into the service without his knowledge; and whenever
+he came to see us, exploded my mines upon him for the edification of
+Dora at second hand. The amount of practical wisdom I bestowed upon
+Traddles in this manner was immense, and of the best quality; but it
+had no other effect upon Dora than to depress her spirits, and make her
+always nervous with the dread that it would be her turn next. I found
+myself in the condition of a schoolmaster, a trap, a pitfall; of always
+playing spider to Dora's fly, and always pouncing out of my hole to her
+infinite disturbance.
+
+Still, looking forward through this intermediate stage, to the time
+when there should be a perfect sympathy between Dora and me, and when I
+should have 'formed her mind' to my entire satisfaction, I persevered,
+even for months. Finding at last, however, that, although I had been
+all this time a very porcupine or hedgehog, bristling all over with
+determination, I had effected nothing, it began to occur to me that
+perhaps Dora's mind was already formed.
+
+On further consideration this appeared so likely, that I abandoned
+my scheme, which had had a more promising appearance in words than in
+action; resolving henceforth to be satisfied with my child-wife, and to
+try to change her into nothing else by any process. I was heartily tired
+of being sagacious and prudent by myself, and of seeing my darling under
+restraint; so I bought a pretty pair of ear-rings for her, and a collar
+for Jip, and went home one day to make myself agreeable.
+
+Dora was delighted with the little presents, and kissed me joyfully; but
+there was a shadow between us, however slight, and I had made up my mind
+that it should not be there. If there must be such a shadow anywhere, I
+would keep it for the future in my own breast.
+
+I sat down by my wife on the sofa, and put the ear-rings in her ears;
+and then I told her that I feared we had not been quite as good company
+lately, as we used to be, and that the fault was mine. Which I sincerely
+felt, and which indeed it was.
+
+'The truth is, Dora, my life,' I said; 'I have been trying to be wise.'
+
+'And to make me wise too,' said Dora, timidly. 'Haven't you, Doady?'
+
+I nodded assent to the pretty inquiry of the raised eyebrows, and kissed
+the parted lips.
+
+'It's of not a bit of use,' said Dora, shaking her head, until the
+ear-rings rang again. 'You know what a little thing I am, and what I
+wanted you to call me from the first. If you can't do so, I am afraid
+you'll never like me. Are you sure you don't think, sometimes, it would
+have been better to have--'
+
+'Done what, my dear?' For she made no effort to proceed.
+
+'Nothing!' said Dora.
+
+'Nothing?' I repeated.
+
+She put her arms round my neck, and laughed, and called herself by her
+favourite name of a goose, and hid her face on my shoulder in such a
+profusion of curls that it was quite a task to clear them away and see
+it.
+
+'Don't I think it would have been better to have done nothing, than to
+have tried to form my little wife's mind?' said I, laughing at myself.
+'Is that the question? Yes, indeed, I do.'
+
+'Is that what you have been trying?' cried Dora. 'Oh what a shocking
+boy!'
+
+'But I shall never try any more,' said I. 'For I love her dearly as she
+is.'
+
+'Without a story--really?' inquired Dora, creeping closer to me.
+
+'Why should I seek to change,' said I, 'what has been so precious to me
+for so long! You never can show better than as your own natural self, my
+sweet Dora; and we'll try no conceited experiments, but go back to our
+old way, and be happy.'
+
+'And be happy!' returned Dora. 'Yes! All day! And you won't mind things
+going a tiny morsel wrong, sometimes?'
+
+'No, no,' said I. 'We must do the best we can.'
+
+'And you won't tell me, any more, that we make other people bad,' coaxed
+Dora; 'will you? Because you know it's so dreadfully cross!'
+
+'No, no,' said I.
+
+'It's better for me to be stupid than uncomfortable, isn't it?' said
+Dora.
+
+'Better to be naturally Dora than anything else in the world.'
+
+'In the world! Ah, Doady, it's a large place!'
+
+She shook her head, turned her delighted bright eyes up to mine, kissed
+me, broke into a merry laugh, and sprang away to put on Jip's new
+collar.
+
+So ended my last attempt to make any change in Dora. I had been unhappy
+in trying it; I could not endure my own solitary wisdom; I could not
+reconcile it with her former appeal to me as my child-wife. I resolved
+to do what I could, in a quiet way, to improve our proceedings myself,
+but I foresaw that my utmost would be very little, or I must degenerate
+into the spider again, and be for ever lying in wait.
+
+And the shadow I have mentioned, that was not to be between us any more,
+but was to rest wholly on my own heart? How did that fall?
+
+The old unhappy feeling pervaded my life. It was deepened, if it were
+changed at all; but it was as undefined as ever, and addressed me like
+a strain of sorrowful music faintly heard in the night. I loved my wife
+dearly, and I was happy; but the happiness I had vaguely anticipated,
+once, was not the happiness I enjoyed, and there was always something
+wanting.
+
+In fulfilment of the compact I have made with myself, to reflect my mind
+on this paper, I again examine it, closely, and bring its secrets to the
+light. What I missed, I still regarded--I always regarded--as something
+that had been a dream of my youthful fancy; that was incapable of
+realization; that I was now discovering to be so, with some natural
+pain, as all men did. But that it would have been better for me if my
+wife could have helped me more, and shared the many thoughts in which I
+had no partner; and that this might have been; I knew.
+
+Between these two irreconcilable conclusions: the one, that what I felt
+was general and unavoidable; the other, that it was particular to me,
+and might have been different: I balanced curiously, with no distinct
+sense of their opposition to each other. When I thought of the airy
+dreams of youth that are incapable of realization, I thought of the
+better state preceding manhood that I had outgrown; and then the
+contented days with Agnes, in the dear old house, arose before me, like
+spectres of the dead, that might have some renewal in another world, but
+never more could be reanimated here.
+
+Sometimes, the speculation came into my thoughts, What might have
+happened, or what would have happened, if Dora and I had never known
+each other? But she was so incorporated with my existence, that it
+was the idlest of all fancies, and would soon rise out of my reach and
+sight, like gossamer floating in the air.
+
+I always loved her. What I am describing, slumbered, and half awoke, and
+slept again, in the innermost recesses of my mind. There was no evidence
+of it in me; I know of no influence it had in anything I said or did. I
+bore the weight of all our little cares, and all my projects; Dora held
+the pens; and we both felt that our shares were adjusted as the case
+required. She was truly fond of me, and proud of me; and when Agnes
+wrote a few earnest words in her letters to Dora, of the pride and
+interest with which my old friends heard of my growing reputation, and
+read my book as if they heard me speaking its contents, Dora read them
+out to me with tears of joy in her bright eyes, and said I was a dear
+old clever, famous boy.
+
+'The first mistaken impulse of an undisciplined heart.' Those words of
+Mrs. Strong's were constantly recurring to me, at this time; were almost
+always present to my mind. I awoke with them, often, in the night; I
+remember to have even read them, in dreams, inscribed upon the walls
+of houses. For I knew, now, that my own heart was undisciplined when it
+first loved Dora; and that if it had been disciplined, it never
+could have felt, when we were married, what it had felt in its secret
+experience.
+
+'There can be no disparity in marriage, like unsuitability of mind and
+purpose.' Those words I remembered too. I had endeavoured to adapt
+Dora to myself, and found it impracticable. It remained for me to adapt
+myself to Dora; to share with her what I could, and be happy; to bear
+on my own shoulders what I must, and be happy still. This was the
+discipline to which I tried to bring my heart, when I began to think.
+It made my second year much happier than my first; and, what was better
+still, made Dora's life all sunshine.
+
+But, as that year wore on, Dora was not strong. I had hoped that lighter
+hands than mine would help to mould her character, and that a baby-smile
+upon her breast might change my child-wife to a woman. It was not to be.
+The spirit fluttered for a moment on the threshold of its little prison,
+and, unconscious of captivity, took wing.
+
+'When I can run about again, as I used to do, aunt,' said Dora, 'I shall
+make Jip race. He is getting quite slow and lazy.'
+
+'I suspect, my dear,' said my aunt quietly working by her side, 'he has
+a worse disorder than that. Age, Dora.'
+
+'Do you think he is old?' said Dora, astonished. 'Oh, how strange it
+seems that Jip should be old!'
+
+'It's a complaint we are all liable to, Little One, as we get on in
+life,' said my aunt, cheerfully; 'I don't feel more free from it than I
+used to be, I assure you.'
+
+'But Jip,' said Dora, looking at him with compassion, 'even little Jip!
+Oh, poor fellow!'
+
+'I dare say he'll last a long time yet, Blossom,' said my aunt, patting
+Dora on the cheek, as she leaned out of her couch to look at Jip, who
+responded by standing on his hind legs, and baulking himself in various
+asthmatic attempts to scramble up by the head and shoulders. 'He must
+have a piece of flannel in his house this winter, and I shouldn't wonder
+if he came out quite fresh again, with the flowers in the spring. Bless
+the little dog!' exclaimed my aunt, 'if he had as many lives as a cat,
+and was on the point of losing 'em all, he'd bark at me with his last
+breath, I believe!'
+
+Dora had helped him up on the sofa; where he really was defying my aunt
+to such a furious extent, that he couldn't keep straight, but barked
+himself sideways. The more my aunt looked at him, the more he reproached
+her; for she had lately taken to spectacles, and for some inscrutable
+reason he considered the glasses personal.
+
+Dora made him lie down by her, with a good deal of persuasion; and when
+he was quiet, drew one of his long ears through and through her hand,
+repeating thoughtfully, 'Even little Jip! Oh, poor fellow!'
+
+'His lungs are good enough,' said my aunt, gaily, 'and his dislikes are
+not at all feeble. He has a good many years before him, no doubt. But if
+you want a dog to race with, Little Blossom, he has lived too well for
+that, and I'll give you one.'
+
+'Thank you, aunt,' said Dora, faintly. 'But don't, please!'
+
+'No?' said my aunt, taking off her spectacles.
+
+'I couldn't have any other dog but Jip,' said Dora. 'It would be so
+unkind to Jip! Besides, I couldn't be such friends with any other dog
+but Jip; because he wouldn't have known me before I was married,
+and wouldn't have barked at Doady when he first came to our house. I
+couldn't care for any other dog but Jip, I am afraid, aunt.'
+
+'To be sure!' said my aunt, patting her cheek again. 'You are right.'
+
+'You are not offended,' said Dora. 'Are you?'
+
+'Why, what a sensitive pet it is!' cried my aunt, bending over her
+affectionately. 'To think that I could be offended!'
+
+'No, no, I didn't really think so,' returned Dora; 'but I am a little
+tired, and it made me silly for a moment--I am always a silly little
+thing, you know, but it made me more silly--to talk about Jip. He
+has known me in all that has happened to me, haven't you, Jip? And I
+couldn't bear to slight him, because he was a little altered--could I,
+Jip?'
+
+Jip nestled closer to his mistress, and lazily licked her hand.
+
+'You are not so old, Jip, are you, that you'll leave your mistress yet?'
+said Dora. 'We may keep one another company a little longer!'
+
+My pretty Dora! When she came down to dinner on the ensuing Sunday, and
+was so glad to see old Traddles (who always dined with us on Sunday), we
+thought she would be 'running about as she used to do', in a few days.
+But they said, wait a few days more; and then, wait a few days more; and
+still she neither ran nor walked. She looked very pretty, and was very
+merry; but the little feet that used to be so nimble when they danced
+round Jip, were dull and motionless.
+
+I began to carry her downstairs every morning, and upstairs every night.
+She would clasp me round the neck and laugh, the while, as if I did it
+for a wager. Jip would bark and caper round us, and go on before, and
+look back on the landing, breathing short, to see that we were coming.
+My aunt, the best and most cheerful of nurses, would trudge after us, a
+moving mass of shawls and pillows. Mr. Dick would not have relinquished
+his post of candle-bearer to anyone alive. Traddles would be often at
+the bottom of the staircase, looking on, and taking charge of sportive
+messages from Dora to the dearest girl in the world. We made quite a gay
+procession of it, and my child-wife was the gayest there.
+
+But, sometimes, when I took her up, and felt that she was lighter in
+my arms, a dead blank feeling came upon me, as if I were approaching
+to some frozen region yet unseen, that numbed my life. I avoided the
+recognition of this feeling by any name, or by any communing with
+myself; until one night, when it was very strong upon me, and my aunt
+had left her with a parting cry of 'Good night, Little Blossom,' I sat
+down at my desk alone, and cried to think, Oh what a fatal name it was,
+and how the blossom withered in its bloom upon the tree!
+
+
+CHAPTER 49. I AM INVOLVED IN MYSTERY
+
+
+I received one morning by the post, the following letter, dated
+Canterbury, and addressed to me at Doctor's Commons; which I read with
+some surprise:
+
+
+'MY DEAR SIR,
+
+'Circumstances beyond my individual control have, for a considerable
+lapse of time, effected a severance of that intimacy which, in the
+limited opportunities conceded to me in the midst of my professional
+duties, of contemplating the scenes and events of the past, tinged by
+the prismatic hues of memory, has ever afforded me, as it ever must
+continue to afford, gratifying emotions of no common description. This
+fact, my dear sir, combined with the distinguished elevation to which
+your talents have raised you, deters me from presuming to aspire to
+the liberty of addressing the companion of my youth, by the familiar
+appellation of Copperfield! It is sufficient to know that the name to
+which I do myself the honour to refer, will ever be treasured among
+the muniments of our house (I allude to the archives connected with our
+former lodgers, preserved by Mrs. Micawber), with sentiments of personal
+esteem amounting to affection.
+
+'It is not for one, situated, through his original errors and a
+fortuitous combination of unpropitious events, as is the foundered Bark
+(if he may be allowed to assume so maritime a denomination), who
+now takes up the pen to address you--it is not, I repeat, for one
+so circumstanced, to adopt the language of compliment, or of
+congratulation. That he leaves to abler and to purer hands.
+
+'If your more important avocations should admit of your ever tracing
+these imperfect characters thus far--which may be, or may not be, as
+circumstances arise--you will naturally inquire by what object am I
+influenced, then, in inditing the present missive? Allow me to say that
+I fully defer to the reasonable character of that inquiry, and proceed
+to develop it; premising that it is not an object of a pecuniary nature.
+
+'Without more directly referring to any latent ability that may
+possibly exist on my part, of wielding the thunderbolt, or directing
+the devouring and avenging flame in any quarter, I may be permitted
+to observe, in passing, that my brightest visions are for ever
+dispelled--that my peace is shattered and my power of enjoyment
+destroyed--that my heart is no longer in the right place--and that I no
+more walk erect before my fellow man. The canker is in the flower.
+The cup is bitter to the brim. The worm is at his work, and will soon
+dispose of his victim. The sooner the better. But I will not digress.
+'Placed in a mental position of peculiar painfulness, beyond the
+assuaging reach even of Mrs. Micawber's influence, though exercised in
+the tripartite character of woman, wife, and mother, it is my intention
+to fly from myself for a short period, and devote a respite of
+eight-and-forty hours to revisiting some metropolitan scenes of past
+enjoyment. Among other havens of domestic tranquillity and peace of
+mind, my feet will naturally tend towards the King's Bench Prison. In
+stating that I shall be (D. V.) on the outside of the south wall of
+that place of incarceration on civil process, the day after tomorrow,
+at seven in the evening, precisely, my object in this epistolary
+communication is accomplished.
+
+'I do not feel warranted in soliciting my former friend Mr. Copperfield,
+or my former friend Mr. Thomas Traddles of the Inner Temple, if that
+gentleman is still existent and forthcoming, to condescend to meet me,
+and renew (so far as may be) our past relations of the olden time. I
+confine myself to throwing out the observation, that, at the hour and
+place I have indicated, may be found such ruined vestiges as yet
+
+               'Remain,
+                    'Of
+                         'A
+                              'Fallen Tower,
+                                   'WILKINS MICAWBER.
+
+'P.S. It may be advisable to superadd to the above, the statement that
+Mrs. Micawber is not in confidential possession of my intentions.'
+
+
+I read the letter over several times. Making due allowance for Mr.
+Micawber's lofty style of composition, and for the extraordinary relish
+with which he sat down and wrote long letters on all possible and
+impossible occasions, I still believed that something important lay
+hidden at the bottom of this roundabout communication. I put it down,
+to think about it; and took it up again, to read it once more; and
+was still pursuing it, when Traddles found me in the height of my
+perplexity.
+
+'My dear fellow,' said I, 'I never was better pleased to see you. You
+come to give me the benefit of your sober judgement at a most opportune
+time. I have received a very singular letter, Traddles, from Mr.
+Micawber.'
+
+'No?' cried Traddles. 'You don't say so? And I have received one from
+Mrs. Micawber!'
+
+With that, Traddles, who was flushed with walking, and whose hair, under
+the combined effects of exercise and excitement, stood on end as if he
+saw a cheerful ghost, produced his letter and made an exchange with me.
+I watched him into the heart of Mr. Micawber's letter, and returned the
+elevation of eyebrows with which he said "'Wielding the thunderbolt,
+or directing the devouring and avenging flame!" Bless me,
+Copperfield!'--and then entered on the perusal of Mrs. Micawber's
+epistle.
+
+It ran thus:
+
+
+'My best regards to Mr. Thomas Traddles, and if he should still remember
+one who formerly had the happiness of being well acquainted with him,
+may I beg a few moments of his leisure time? I assure Mr. T. T. that I
+would not intrude upon his kindness, were I in any other position than
+on the confines of distraction.
+
+'Though harrowing to myself to mention, the alienation of Mr. Micawber
+(formerly so domesticated) from his wife and family, is the cause of my
+addressing my unhappy appeal to Mr. Traddles, and soliciting his best
+indulgence. Mr. T. can form no adequate idea of the change in Mr.
+Micawber's conduct, of his wildness, of his violence. It has gradually
+augmented, until it assumes the appearance of aberration of intellect.
+Scarcely a day passes, I assure Mr. Traddles, on which some paroxysm
+does not take place. Mr. T. will not require me to depict my feelings,
+when I inform him that I have become accustomed to hear Mr. Micawber
+assert that he has sold himself to the D. Mystery and secrecy have
+long been his principal characteristic, have long replaced unlimited
+confidence. The slightest provocation, even being asked if there is
+anything he would prefer for dinner, causes him to express a wish for a
+separation. Last night, on being childishly solicited for twopence, to
+buy 'lemon-stunners'--a local sweetmeat--he presented an oyster-knife at
+the twins!
+
+'I entreat Mr. Traddles to bear with me in entering into these details.
+Without them, Mr. T. would indeed find it difficult to form the faintest
+conception of my heart-rending situation.
+
+'May I now venture to confide to Mr. T. the purport of my letter? Will
+he now allow me to throw myself on his friendly consideration? Oh yes,
+for I know his heart!
+
+'The quick eye of affection is not easily blinded, when of the female
+sex. Mr. Micawber is going to London. Though he studiously concealed his
+hand, this morning before breakfast, in writing the direction-card which
+he attached to the little brown valise of happier days, the eagle-glance
+of matrimonial anxiety detected, d, o, n, distinctly traced. The
+West-End destination of the coach, is the Golden Cross. Dare I fervently
+implore Mr. T. to see my misguided husband, and to reason with him?
+Dare I ask Mr. T. to endeavour to step in between Mr. Micawber and his
+agonized family? Oh no, for that would be too much!
+
+'If Mr. Copperfield should yet remember one unknown to fame, will Mr.
+T. take charge of my unalterable regards and similar entreaties? In
+any case, he will have the benevolence to consider this communication
+strictly private, and on no account whatever to be alluded to, however
+distantly, in the presence of Mr. Micawber. If Mr. T. should ever
+reply to it (which I cannot but feel to be most improbable), a letter
+addressed to M. E., Post Office, Canterbury, will be fraught with
+less painful consequences than any addressed immediately to one, who
+subscribes herself, in extreme distress,
+
+'Mr. Thomas Traddles's respectful friend and suppliant,
+
+                                   'EMMA MICAWBER.'
+
+
+'What do you think of that letter?' said Traddles, casting his eyes upon
+me, when I had read it twice.
+
+'What do you think of the other?' said I. For he was still reading it
+with knitted brows.
+
+'I think that the two together, Copperfield,' replied Traddles,
+'mean more than Mr. and Mrs. Micawber usually mean in their
+correspondence--but I don't know what. They are both written in good
+faith, I have no doubt, and without any collusion. Poor thing!' he was
+now alluding to Mrs. Micawber's letter, and we were standing side by
+side comparing the two; 'it will be a charity to write to her, at all
+events, and tell her that we will not fail to see Mr. Micawber.'
+
+I acceded to this the more readily, because I now reproached myself with
+having treated her former letter rather lightly. It had set me thinking
+a good deal at the time, as I have mentioned in its place; but my
+absorption in my own affairs, my experience of the family, and my
+hearing nothing more, had gradually ended in my dismissing the subject.
+I had often thought of the Micawbers, but chiefly to wonder what
+'pecuniary liabilities' they were establishing in Canterbury, and to
+recall how shy Mr. Micawber was of me when he became clerk to Uriah
+Heep.
+
+However, I now wrote a comforting letter to Mrs. Micawber, in our
+joint names, and we both signed it. As we walked into town to post it,
+Traddles and I held a long conference, and launched into a number of
+speculations, which I need not repeat. We took my aunt into our counsels
+in the afternoon; but our only decided conclusion was, that we would be
+very punctual in keeping Mr. Micawber's appointment.
+
+Although we appeared at the stipulated place a quarter of an hour before
+the time, we found Mr. Micawber already there. He was standing with his
+arms folded, over against the wall, looking at the spikes on the top,
+with a sentimental expression, as if they were the interlacing boughs of
+trees that had shaded him in his youth.
+
+When we accosted him, his manner was something more confused, and
+something less genteel, than of yore. He had relinquished his legal suit
+of black for the purposes of this excursion, and wore the old surtout
+and tights, but not quite with the old air. He gradually picked up more
+and more of it as we conversed with him; but, his very eye-glass seemed
+to hang less easily, and his shirt-collar, though still of the old
+formidable dimensions, rather drooped.
+
+'Gentlemen!' said Mr. Micawber, after the first salutations, 'you are
+friends in need, and friends indeed. Allow me to offer my inquiries with
+reference to the physical welfare of Mrs. Copperfield in esse, and
+Mrs. Traddles in posse,--presuming, that is to say, that my friend Mr.
+Traddles is not yet united to the object of his affections, for weal and
+for woe.'
+
+We acknowledged his politeness, and made suitable replies. He then
+directed our attention to the wall, and was beginning, 'I assure you,
+gentlemen,' when I ventured to object to that ceremonious form of
+address, and to beg that he would speak to us in the old way.
+
+'My dear Copperfield,' he returned, pressing my hand, 'your cordiality
+overpowers me. This reception of a shattered fragment of the Temple once
+called Man--if I may be permitted so to express myself--bespeaks a heart
+that is an honour to our common nature. I was about to observe that
+I again behold the serene spot where some of the happiest hours of my
+existence fleeted by.'
+
+'Made so, I am sure, by Mrs. Micawber,' said I. 'I hope she is well?'
+
+'Thank you,' returned Mr. Micawber, whose face clouded at this
+reference, 'she is but so-so. And this,' said Mr. Micawber, nodding
+his head sorrowfully, 'is the Bench! Where, for the first time in many
+revolving years, the overwhelming pressure of pecuniary liabilities was
+not proclaimed, from day to day, by importune voices declining to vacate
+the passage; where there was no knocker on the door for any creditor
+to appeal to; where personal service of process was not required, and
+detainees were merely lodged at the gate! Gentlemen,' said Mr. Micawber,
+'when the shadow of that iron-work on the summit of the brick structure
+has been reflected on the gravel of the Parade, I have seen my children
+thread the mazes of the intricate pattern, avoiding the dark marks. I
+have been familiar with every stone in the place. If I betray weakness,
+you will know how to excuse me.'
+
+'We have all got on in life since then, Mr. Micawber,' said I.
+
+'Mr. Copperfield,' returned Mr. Micawber, bitterly, 'when I was an
+inmate of that retreat I could look my fellow-man in the face, and punch
+his head if he offended me. My fellow-man and myself are no longer on
+those glorious terms!'
+
+Turning from the building in a downcast manner, Mr. Micawber accepted
+my proffered arm on one side, and the proffered arm of Traddles on the
+other, and walked away between us.
+
+'There are some landmarks,' observed Mr. Micawber, looking fondly back
+over his shoulder, 'on the road to the tomb, which, but for the impiety
+of the aspiration, a man would wish never to have passed. Such is the
+Bench in my chequered career.'
+
+'Oh, you are in low spirits, Mr. Micawber,' said Traddles.
+
+'I am, sir,' interposed Mr. Micawber.
+
+'I hope,' said Traddles, 'it is not because you have conceived a dislike
+to the law--for I am a lawyer myself, you know.'
+
+Mr. Micawber answered not a word.
+
+'How is our friend Heep, Mr. Micawber?' said I, after a silence.
+
+'My dear Copperfield,' returned Mr. Micawber, bursting into a state of
+much excitement, and turning pale, 'if you ask after my employer as
+your friend, I am sorry for it; if you ask after him as MY friend,
+I sardonically smile at it. In whatever capacity you ask after my
+employer, I beg, without offence to you, to limit my reply to this--that
+whatever his state of health may be, his appearance is foxy: not to
+say diabolical. You will allow me, as a private individual, to
+decline pursuing a subject which has lashed me to the utmost verge of
+desperation in my professional capacity.'
+
+I expressed my regret for having innocently touched upon a theme
+that roused him so much. 'May I ask,' said I, 'without any hazard of
+repeating the mistake, how my old friends Mr. and Miss Wickfield are?'
+
+'Miss Wickfield,' said Mr. Micawber, now turning red, 'is, as she always
+is, a pattern, and a bright example. My dear Copperfield, she is the
+only starry spot in a miserable existence. My respect for that young
+lady, my admiration of her character, my devotion to her for her love
+and truth, and goodness!--Take me,' said Mr. Micawber, 'down a turning,
+for, upon my soul, in my present state of mind I am not equal to this!'
+
+We wheeled him off into a narrow street, where he took out his
+pocket-handkerchief, and stood with his back to a wall. If I looked as
+gravely at him as Traddles did, he must have found our company by no
+means inspiriting.
+
+'It is my fate,' said Mr. Micawber, unfeignedly sobbing, but doing even
+that, with a shadow of the old expression of doing something genteel;
+'it is my fate, gentlemen, that the finer feelings of our nature have
+become reproaches to me. My homage to Miss Wickfield, is a flight of
+arrows in my bosom. You had better leave me, if you please, to walk the
+earth as a vagabond. The worm will settle my business in double-quick
+time.'
+
+Without attending to this invocation, we stood by, until he put up his
+pocket-handkerchief, pulled up his shirt-collar, and, to delude any
+person in the neighbourhood who might have been observing him, hummed a
+tune with his hat very much on one side. I then mentioned--not knowing
+what might be lost if we lost sight of him yet--that it would give me
+great pleasure to introduce him to my aunt, if he would ride out to
+Highgate, where a bed was at his service.
+
+'You shall make us a glass of your own punch, Mr. Micawber,' said
+I, 'and forget whatever you have on your mind, in pleasanter
+reminiscences.'
+
+'Or, if confiding anything to friends will be more likely to relieve
+you, you shall impart it to us, Mr. Micawber,' said Traddles, prudently.
+
+'Gentlemen,' returned Mr. Micawber, 'do with me as you will! I am a
+straw upon the surface of the deep, and am tossed in all directions by
+the elephants--I beg your pardon; I should have said the elements.'
+
+We walked on, arm-in-arm, again; found the coach in the act of starting;
+and arrived at Highgate without encountering any difficulties by the
+way. I was very uneasy and very uncertain in my mind what to say or do
+for the best--so was Traddles, evidently. Mr. Micawber was for the most
+part plunged into deep gloom. He occasionally made an attempt to smarten
+himself, and hum the fag-end of a tune; but his relapses into profound
+melancholy were only made the more impressive by the mockery of a hat
+exceedingly on one side, and a shirt-collar pulled up to his eyes.
+
+We went to my aunt's house rather than to mine, because of Dora's not
+being well. My aunt presented herself on being sent for, and welcomed
+Mr. Micawber with gracious cordiality. Mr. Micawber kissed her hand,
+retired to the window, and pulling out his pocket-handkerchief, had a
+mental wrestle with himself.
+
+Mr. Dick was at home. He was by nature so exceedingly compassionate of
+anyone who seemed to be ill at ease, and was so quick to find any such
+person out, that he shook hands with Mr. Micawber, at least half-a-dozen
+times in five minutes. To Mr. Micawber, in his trouble, this warmth, on
+the part of a stranger, was so extremely touching, that he could
+only say, on the occasion of each successive shake, 'My dear sir, you
+overpower me!' Which gratified Mr. Dick so much, that he went at it
+again with greater vigour than before.
+
+'The friendliness of this gentleman,' said Mr. Micawber to my aunt, 'if
+you will allow me, ma'am, to cull a figure of speech from the vocabulary
+of our coarser national sports--floors me. To a man who is struggling
+with a complicated burden of perplexity and disquiet, such a reception
+is trying, I assure you.'
+
+'My friend Mr. Dick,' replied my aunt proudly, 'is not a common man.'
+
+'That I am convinced of,' said Mr. Micawber. 'My dear sir!' for Mr.
+Dick was shaking hands with him again; 'I am deeply sensible of your
+cordiality!'
+
+'How do you find yourself?' said Mr. Dick, with an anxious look.
+
+'Indifferent, my dear sir,' returned Mr. Micawber, sighing.
+
+'You must keep up your spirits,' said Mr. Dick, 'and make yourself as
+comfortable as possible.'
+
+Mr. Micawber was quite overcome by these friendly words, and by finding
+Mr. Dick's hand again within his own. 'It has been my lot,' he observed,
+'to meet, in the diversified panorama of human existence, with an
+occasional oasis, but never with one so green, so gushing, as the
+present!'
+
+At another time I should have been amused by this; but I felt that
+we were all constrained and uneasy, and I watched Mr. Micawber so
+anxiously, in his vacillations between an evident disposition to reveal
+something, and a counter-disposition to reveal nothing, that I was in a
+perfect fever. Traddles, sitting on the edge of his chair, with his eyes
+wide open, and his hair more emphatically erect than ever, stared by
+turns at the ground and at Mr. Micawber, without so much as attempting
+to put in a word. My aunt, though I saw that her shrewdest observation
+was concentrated on her new guest, had more useful possession of her
+wits than either of us; for she held him in conversation, and made it
+necessary for him to talk, whether he liked it or not.
+
+'You are a very old friend of my nephew's, Mr. Micawber,' said my aunt.
+'I wish I had had the pleasure of seeing you before.'
+
+'Madam,' returned Mr. Micawber, 'I wish I had had the honour of knowing
+you at an earlier period. I was not always the wreck you at present
+behold.'
+
+'I hope Mrs. Micawber and your family are well, sir,' said my aunt.
+
+Mr. Micawber inclined his head. 'They are as well, ma'am,' he
+desperately observed after a pause, 'as Aliens and Outcasts can ever
+hope to be.'
+
+'Lord bless you, sir!' exclaimed my aunt, in her abrupt way. 'What are
+you talking about?'
+
+'The subsistence of my family, ma'am,' returned Mr. Micawber, 'trembles
+in the balance. My employer--'
+
+Here Mr. Micawber provokingly left off; and began to peel the lemons
+that had been under my directions set before him, together with all the
+other appliances he used in making punch.
+
+'Your employer, you know,' said Mr. Dick, jogging his arm as a gentle
+reminder.
+
+'My good sir,' returned Mr. Micawber, 'you recall me, I am obliged to
+you.' They shook hands again. 'My employer, ma'am--Mr. Heep--once did
+me the favour to observe to me, that if I were not in the receipt of the
+stipendiary emoluments appertaining to my engagement with him, I should
+probably be a mountebank about the country, swallowing a sword-blade,
+and eating the devouring element. For anything that I can perceive to
+the contrary, it is still probable that my children may be reduced to
+seek a livelihood by personal contortion, while Mrs. Micawber abets
+their unnatural feats by playing the barrel-organ.'
+
+Mr. Micawber, with a random but expressive flourish of his knife,
+signified that these performances might be expected to take place after
+he was no more; then resumed his peeling with a desperate air.
+
+My aunt leaned her elbow on the little round table that she usually kept
+beside her, and eyed him attentively. Notwithstanding the aversion with
+which I regarded the idea of entrapping him into any disclosure he was
+not prepared to make voluntarily, I should have taken him up at this
+point, but for the strange proceedings in which I saw him engaged;
+whereof his putting the lemon-peel into the kettle, the sugar into the
+snuffer-tray, the spirit into the empty jug, and confidently attempting
+to pour boiling water out of a candlestick, were among the most
+remarkable. I saw that a crisis was at hand, and it came. He clattered
+all his means and implements together, rose from his chair, pulled out
+his pocket-handkerchief, and burst into tears.
+
+'My dear Copperfield,' said Mr. Micawber, behind his handkerchief,
+'this is an occupation, of all others, requiring an untroubled mind, and
+self-respect. I cannot perform it. It is out of the question.'
+
+'Mr. Micawber,' said I, 'what is the matter? Pray speak out. You are
+among friends.'
+
+'Among friends, sir!' repeated Mr. Micawber; and all he had reserved
+came breaking out of him. 'Good heavens, it is principally because I AM
+among friends that my state of mind is what it is. What is the matter,
+gentlemen? What is NOT the matter? Villainy is the matter; baseness is
+the matter; deception, fraud, conspiracy, are the matter; and the name
+of the whole atrocious mass is--HEEP!'
+
+MY aunt clapped her hands, and we all started up as if we were
+possessed.
+
+'The struggle is over!' said Mr. Micawber violently gesticulating with
+his pocket-handkerchief, and fairly striking out from time to time with
+both arms, as if he were swimming under superhuman difficulties. 'I will
+lead this life no longer. I am a wretched being, cut off from everything
+that makes life tolerable. I have been under a Taboo in that infernal
+scoundrel's service. Give me back my wife, give me back my family,
+substitute Micawber for the petty wretch who walks about in the boots
+at present on my feet, and call upon me to swallow a sword tomorrow, and
+I'll do it. With an appetite!'
+
+I never saw a man so hot in my life. I tried to calm him, that we might
+come to something rational; but he got hotter and hotter, and wouldn't
+hear a word.
+
+'I'll put my hand in no man's hand,' said Mr. Micawber, gasping,
+puffing, and sobbing, to that degree that he was like a man
+fighting with cold water, 'until I have--blown to
+fragments--the--a--detestable--serpent--HEEP! I'll partake of no
+one's hospitality, until I have--a--moved Mount Vesuvius--to
+eruption--on--a--the abandoned rascal--HEEP! Refreshment--a--underneath
+this roof--particularly punch--would--a--choke me--unless--I
+had--previously--choked the eyes--out of the head--a--of--interminable
+cheat, and liar--HEEP! I--a--I'll know nobody--and--a--say
+nothing--and--a--live nowhere--until I have
+crushed--to--a--undiscoverable atoms--the--transcendent and immortal
+hypocrite and perjurer--HEEP!'
+
+I really had some fear of Mr. Micawber's dying on the spot. The manner
+in which he struggled through these inarticulate sentences, and,
+whenever he found himself getting near the name of Heep, fought his way
+on to it, dashed at it in a fainting state, and brought it out with a
+vehemence little less than marvellous, was frightful; but now, when
+he sank into a chair, steaming, and looked at us, with every possible
+colour in his face that had no business there, and an endless procession
+of lumps following one another in hot haste up his throat, whence they
+seemed to shoot into his forehead, he had the appearance of being in
+the last extremity. I would have gone to his assistance, but he waved me
+off, and wouldn't hear a word.
+
+'No, Copperfield!--No communication--a--until--Miss
+Wickfield--a--redress from wrongs inflicted by consummate
+scoundrel--HEEP!' (I am quite convinced he could not have uttered three
+words, but for the amazing energy with which this word inspired him when
+he felt it coming.) 'Inviolable secret--a--from the whole world--a--no
+exceptions--this day week--a--at breakfast-time--a--everybody
+present--including aunt--a--and extremely friendly gentleman--to be at
+the hotel at Canterbury--a--where--Mrs. Micawber and myself--Auld Lang
+Syne in chorus--and--a--will expose intolerable ruffian--HEEP! No more
+to say--a--or listen to persuasion--go immediately--not capable--a--bear
+society--upon the track of devoted and doomed traitor--HEEP!'
+
+With this last repetition of the magic word that had kept him going at
+all, and in which he surpassed all his previous efforts, Mr. Micawber
+rushed out of the house; leaving us in a state of excitement, hope, and
+wonder, that reduced us to a condition little better than his own. But
+even then his passion for writing letters was too strong to be resisted;
+for while we were yet in the height of our excitement, hope, and wonder,
+the following pastoral note was brought to me from a neighbouring
+tavern, at which he had called to write it:--
+
+
+          'Most secret and confidential.
+'MY DEAR SIR,
+
+'I beg to be allowed to convey, through you, my apologies to your
+excellent aunt for my late excitement. An explosion of a smouldering
+volcano long suppressed, was the result of an internal contest more
+easily conceived than described.
+
+'I trust I rendered tolerably intelligible my appointment for the
+morning of this day week, at the house of public entertainment at
+Canterbury, where Mrs. Micawber and myself had once the honour of
+uniting our voices to yours, in the well-known strain of the Immortal
+exciseman nurtured beyond the Tweed.
+
+'The duty done, and act of reparation performed, which can alone enable
+me to contemplate my fellow mortal, I shall be known no more. I shall
+simply require to be deposited in that place of universal resort, where
+
+     Each in his narrow cell for ever laid,
+     The rude forefathers of the hamlet sleep,
+
+                    '--With the plain Inscription,
+
+                         'WILKINS MICAWBER.'
+
+
+
+CHAPTER 50. Mr. PEGGOTTY'S DREAM COMES TRUE
+
+
+By this time, some months had passed since our interview on the bank
+of the river with Martha. I had never seen her since, but she had
+communicated with Mr. Peggotty on several occasions. Nothing had come of
+her zealous intervention; nor could I infer, from what he told me, that
+any clue had been obtained, for a moment, to Emily's fate. I confess
+that I began to despair of her recovery, and gradually to sink deeper
+and deeper into the belief that she was dead.
+
+His conviction remained unchanged. So far as I know--and I believe
+his honest heart was transparent to me--he never wavered again, in his
+solemn certainty of finding her. His patience never tired. And, although
+I trembled for the agony it might one day be to him to have his strong
+assurance shivered at a blow, there was something so religious in it, so
+affectingly expressive of its anchor being in the purest depths of
+his fine nature, that the respect and honour in which I held him were
+exalted every day.
+
+His was not a lazy trustfulness that hoped, and did no more. He had
+been a man of sturdy action all his life, and he knew that in all things
+wherein he wanted help he must do his own part faithfully, and help
+himself. I have known him set out in the night, on a misgiving that the
+light might not be, by some accident, in the window of the old boat,
+and walk to Yarmouth. I have known him, on reading something in the
+newspaper that might apply to her, take up his stick, and go forth on a
+journey of three--or four-score miles. He made his way by sea to Naples,
+and back, after hearing the narrative to which Miss Dartle had assisted
+me. All his journeys were ruggedly performed; for he was always
+steadfast in a purpose of saving money for Emily's sake, when she should
+be found. In all this long pursuit, I never heard him repine; I never
+heard him say he was fatigued, or out of heart.
+
+Dora had often seen him since our marriage, and was quite fond of him.
+I fancy his figure before me now, standing near her sofa, with his rough
+cap in his hand, and the blue eyes of my child-wife raised, with a timid
+wonder, to his face. Sometimes of an evening, about twilight, when
+he came to talk with me, I would induce him to smoke his pipe in the
+garden, as we slowly paced to and fro together; and then, the picture
+of his deserted home, and the comfortable air it used to have in my
+childish eyes of an evening when the fire was burning, and the wind
+moaning round it, came most vividly into my mind.
+
+One evening, at this hour, he told me that he had found Martha waiting
+near his lodging on the preceding night when he came out, and that she
+had asked him not to leave London on any account, until he should have
+seen her again.
+
+'Did she tell you why?' I inquired.
+
+'I asked her, Mas'r Davy,' he replied, 'but it is but few words as she
+ever says, and she on'y got my promise and so went away.'
+
+'Did she say when you might expect to see her again?' I demanded.
+
+'No, Mas'r Davy,' he returned, drawing his hand thoughtfully down his
+face. 'I asked that too; but it was more (she said) than she could
+tell.'
+
+As I had long forborne to encourage him with hopes that hung on threads,
+I made no other comment on this information than that I supposed he
+would see her soon. Such speculations as it engendered within me I kept
+to myself, and those were faint enough.
+
+I was walking alone in the garden, one evening, about a fortnight
+afterwards. I remember that evening well. It was the second in Mr.
+Micawber's week of suspense. There had been rain all day, and there was
+a damp feeling in the air. The leaves were thick upon the trees, and
+heavy with wet; but the rain had ceased, though the sky was still dark;
+and the hopeful birds were singing cheerfully. As I walked to and fro
+in the garden, and the twilight began to close around me, their little
+voices were hushed; and that peculiar silence which belongs to such an
+evening in the country when the lightest trees are quite still, save for
+the occasional droppings from their boughs, prevailed.
+
+There was a little green perspective of trellis-work and ivy at the side
+of our cottage, through which I could see, from the garden where I was
+walking, into the road before the house. I happened to turn my eyes
+towards this place, as I was thinking of many things; and I saw a figure
+beyond, dressed in a plain cloak. It was bending eagerly towards me, and
+beckoning.
+
+'Martha!' said I, going to it.
+
+'Can you come with me?' she inquired, in an agitated whisper. 'I have
+been to him, and he is not at home. I wrote down where he was to come,
+and left it on his table with my own hand. They said he would not be out
+long. I have tidings for him. Can you come directly?'
+
+My answer was, to pass out at the gate immediately. She made a hasty
+gesture with her hand, as if to entreat my patience and my silence,
+and turned towards London, whence, as her dress betokened, she had come
+expeditiously on foot.
+
+I asked her if that were not our destination? On her motioning Yes,
+with the same hasty gesture as before, I stopped an empty coach that was
+coming by, and we got into it. When I asked her where the coachman was
+to drive, she answered, 'Anywhere near Golden Square! And quick!'--then
+shrunk into a corner, with one trembling hand before her face, and the
+other making the former gesture, as if she could not bear a voice.
+
+Now much disturbed, and dazzled with conflicting gleams of hope and
+dread, I looked at her for some explanation. But seeing how strongly
+she desired to remain quiet, and feeling that it was my own natural
+inclination too, at such a time, I did not attempt to break the silence.
+We proceeded without a word being spoken. Sometimes she glanced out of
+the window, as though she thought we were going slowly, though indeed we
+were going fast; but otherwise remained exactly as at first.
+
+We alighted at one of the entrances to the Square she had mentioned,
+where I directed the coach to wait, not knowing but that we might have
+some occasion for it. She laid her hand on my arm, and hurried me on
+to one of the sombre streets, of which there are several in that part,
+where the houses were once fair dwellings in the occupation of single
+families, but have, and had, long degenerated into poor lodgings let off
+in rooms. Entering at the open door of one of these, and releasing my
+arm, she beckoned me to follow her up the common staircase, which was
+like a tributary channel to the street.
+
+The house swarmed with inmates. As we went up, doors of rooms were
+opened and people's heads put out; and we passed other people on the
+stairs, who were coming down. In glancing up from the outside, before
+we entered, I had seen women and children lolling at the windows over
+flower-pots; and we seemed to have attracted their curiosity, for these
+were principally the observers who looked out of their doors. It was a
+broad panelled staircase, with massive balustrades of some dark wood;
+cornices above the doors, ornamented with carved fruit and flowers; and
+broad seats in the windows. But all these tokens of past grandeur
+were miserably decayed and dirty; rot, damp, and age, had weakened
+the flooring, which in many places was unsound and even unsafe. Some
+attempts had been made, I noticed, to infuse new blood into this
+dwindling frame, by repairing the costly old wood-work here and there
+with common deal; but it was like the marriage of a reduced old noble to
+a plebeian pauper, and each party to the ill-assorted union shrunk away
+from the other. Several of the back windows on the staircase had
+been darkened or wholly blocked up. In those that remained, there was
+scarcely any glass; and, through the crumbling frames by which the bad
+air seemed always to come in, and never to go out, I saw, through other
+glassless windows, into other houses in a similar condition, and looked
+giddily down into a wretched yard, which was the common dust-heap of the
+mansion.
+
+We proceeded to the top-storey of the house. Two or three times, by the
+way, I thought I observed in the indistinct light the skirts of a female
+figure going up before us. As we turned to ascend the last flight of
+stairs between us and the roof, we caught a full view of this figure
+pausing for a moment, at a door. Then it turned the handle, and went in.
+
+'What's this!' said Martha, in a whisper. 'She has gone into my room. I
+don't know her!'
+
+I knew her. I had recognized her with amazement, for Miss Dartle.
+
+I said something to the effect that it was a lady whom I had seen
+before, in a few words, to my conductress; and had scarcely done so,
+when we heard her voice in the room, though not, from where we stood,
+what she was saying. Martha, with an astonished look, repeated her
+former action, and softly led me up the stairs; and then, by a little
+back-door which seemed to have no lock, and which she pushed open with a
+touch, into a small empty garret with a low sloping roof, little better
+than a cupboard. Between this, and the room she had called hers,
+there was a small door of communication, standing partly open. Here we
+stopped, breathless with our ascent, and she placed her hand lightly on
+my lips. I could only see, of the room beyond, that it was pretty large;
+that there was a bed in it; and that there were some common pictures of
+ships upon the walls. I could not see Miss Dartle, or the person whom
+we had heard her address. Certainly, my companion could not, for my
+position was the best. A dead silence prevailed for some moments. Martha
+kept one hand on my lips, and raised the other in a listening attitude.
+
+'It matters little to me her not being at home,' said Rosa Dartle
+haughtily, 'I know nothing of her. It is you I come to see.'
+
+'Me?' replied a soft voice.
+
+At the sound of it, a thrill went through my frame. For it was Emily's!
+
+'Yes,' returned Miss Dartle, 'I have come to look at you. What? You are
+not ashamed of the face that has done so much?'
+
+The resolute and unrelenting hatred of her tone, its cold stern
+sharpness, and its mastered rage, presented her before me, as if I had
+seen her standing in the light. I saw the flashing black eyes, and the
+passion-wasted figure; and I saw the scar, with its white track cutting
+through her lips, quivering and throbbing as she spoke.
+
+'I have come to see,' she said, 'James Steerforth's fancy; the girl who
+ran away with him, and is the town-talk of the commonest people of her
+native place; the bold, flaunting, practised companion of persons like
+James Steerforth. I want to know what such a thing is like.'
+
+There was a rustle, as if the unhappy girl, on whom she heaped these
+taunts, ran towards the door, and the speaker swiftly interposed herself
+before it. It was succeeded by a moment's pause.
+
+When Miss Dartle spoke again, it was through her set teeth, and with a
+stamp upon the ground.
+
+'Stay there!' she said, 'or I'll proclaim you to the house, and the
+whole street! If you try to evade me, I'll stop you, if it's by the
+hair, and raise the very stones against you!'
+
+A frightened murmur was the only reply that reached my ears. A silence
+succeeded. I did not know what to do. Much as I desired to put an end to
+the interview, I felt that I had no right to present myself; that it was
+for Mr. Peggotty alone to see her and recover her. Would he never come?
+I thought impatiently.
+
+'So!' said Rosa Dartle, with a contemptuous laugh, 'I see her at last!
+Why, he was a poor creature to be taken by that delicate mock-modesty,
+and that hanging head!'
+
+'Oh, for Heaven's sake, spare me!' exclaimed Emily. 'Whoever you are,
+you know my pitiable story, and for Heaven's sake spare me, if you would
+be spared yourself!'
+
+'If I would be spared!' returned the other fiercely; 'what is there in
+common between US, do you think!'
+
+'Nothing but our sex,' said Emily, with a burst of tears.
+
+'And that,' said Rosa Dartle, 'is so strong a claim, preferred by one
+so infamous, that if I had any feeling in my breast but scorn and
+abhorrence of you, it would freeze it up. Our sex! You are an honour to
+our sex!'
+
+'I have deserved this,' said Emily, 'but it's dreadful! Dear, dear lady,
+think what I have suffered, and how I am fallen! Oh, Martha, come back!
+Oh, home, home!'
+
+Miss Dartle placed herself in a chair, within view of the door, and
+looked downward, as if Emily were crouching on the floor before her.
+Being now between me and the light, I could see her curled lip, and her
+cruel eyes intently fixed on one place, with a greedy triumph.
+
+'Listen to what I say!' she said; 'and reserve your false arts for your
+dupes. Do you hope to move me by your tears? No more than you could
+charm me by your smiles, you purchased slave.'
+
+'Oh, have some mercy on me!' cried Emily. 'Show me some compassion, or I
+shall die mad!'
+
+'It would be no great penance,' said Rosa Dartle, 'for your crimes. Do
+you know what you have done? Do you ever think of the home you have laid
+waste?'
+
+'Oh, is there ever night or day, when I don't think of it!' cried Emily;
+and now I could just see her, on her knees, with her head thrown back,
+her pale face looking upward, her hands wildly clasped and held out,
+and her hair streaming about her. 'Has there ever been a single minute,
+waking or sleeping, when it hasn't been before me, just as it used to
+be in the lost days when I turned my back upon it for ever and for ever!
+Oh, home, home! Oh dear, dear uncle, if you ever could have known the
+agony your love would cause me when I fell away from good, you never
+would have shown it to me so constant, much as you felt it; but would
+have been angry to me, at least once in my life, that I might have had
+some comfort! I have none, none, no comfort upon earth, for all of them
+were always fond of me!' She dropped on her face, before the imperious
+figure in the chair, with an imploring effort to clasp the skirt of her
+dress.
+
+Rosa Dartle sat looking down upon her, as inflexible as a figure of
+brass. Her lips were tightly compressed, as if she knew that she
+must keep a strong constraint upon herself--I write what I sincerely
+believe--or she would be tempted to strike the beautiful form with
+her foot. I saw her, distinctly, and the whole power of her face and
+character seemed forced into that expression.---Would he never come?
+
+'The miserable vanity of these earth-worms!' she said, when she had so
+far controlled the angry heavings of her breast, that she could trust
+herself to speak. 'YOUR home! Do you imagine that I bestow a thought
+on it, or suppose you could do any harm to that low place, which money
+would not pay for, and handsomely? YOUR home! You were a part of the
+trade of your home, and were bought and sold like any other vendible
+thing your people dealt in.'
+
+'Oh, not that!' cried Emily. 'Say anything of me; but don't visit
+my disgrace and shame, more than I have done, on folks who are as
+honourable as you! Have some respect for them, as you are a lady, if you
+have no mercy for me.'
+
+'I speak,' she said, not deigning to take any heed of this appeal, and
+drawing away her dress from the contamination of Emily's touch, 'I speak
+of HIS home--where I live. Here,' she said, stretching out her hand with
+her contemptuous laugh, and looking down upon the prostrate girl, 'is a
+worthy cause of division between lady-mother and gentleman-son; of grief
+in a house where she wouldn't have been admitted as a kitchen-girl; of
+anger, and repining, and reproach. This piece of pollution, picked up
+from the water-side, to be made much of for an hour, and then tossed
+back to her original place!'
+
+'No! no!' cried Emily, clasping her hands together. 'When he first came
+into my way--that the day had never dawned upon me, and he had met me
+being carried to my grave!--I had been brought up as virtuous as you or
+any lady, and was going to be the wife of as good a man as you or any
+lady in the world can ever marry. If you live in his home and know him,
+you know, perhaps, what his power with a weak, vain girl might be. I
+don't defend myself, but I know well, and he knows well, or he will know
+when he comes to die, and his mind is troubled with it, that he used all
+his power to deceive me, and that I believed him, trusted him, and loved
+him!'
+
+Rosa Dartle sprang up from her seat; recoiled; and in recoiling struck
+at her, with a face of such malignity, so darkened and disfigured by
+passion, that I had almost thrown myself between them. The blow, which
+had no aim, fell upon the air. As she now stood panting, looking at
+her with the utmost detestation that she was capable of expressing, and
+trembling from head to foot with rage and scorn, I thought I had never
+seen such a sight, and never could see such another.
+
+'YOU love him? You?' she cried, with her clenched hand, quivering as if
+it only wanted a weapon to stab the object of her wrath.
+
+Emily had shrunk out of my view. There was no reply.
+
+'And tell that to ME,' she added, 'with your shameful lips? Why don't
+they whip these creatures? If I could order it to be done, I would have
+this girl whipped to death.'
+
+And so she would, I have no doubt. I would not have trusted her with the
+rack itself, while that furious look lasted. She slowly, very slowly,
+broke into a laugh, and pointed at Emily with her hand, as if she were a
+sight of shame for gods and men.
+
+'SHE love!' she said. 'THAT carrion! And he ever cared for her, she'd
+tell me. Ha, ha! The liars that these traders are!'
+
+Her mockery was worse than her undisguised rage. Of the two, I would
+have much preferred to be the object of the latter. But, when she
+suffered it to break loose, it was only for a moment. She had chained
+it up again, and however it might tear her within, she subdued it to
+herself.
+
+'I came here, you pure fountain of love,' she said, 'to see--as I began
+by telling you--what such a thing as you was like. I was curious. I am
+satisfied. Also to tell you, that you had best seek that home of yours,
+with all speed, and hide your head among those excellent people who are
+expecting you, and whom your money will console. When it's all gone, you
+can believe, and trust, and love again, you know! I thought you a broken
+toy that had lasted its time; a worthless spangle that was tarnished,
+and thrown away. But, finding you true gold, a very lady, and
+an ill-used innocent, with a fresh heart full of love and
+trustfulness--which you look like, and is quite consistent with your
+story!--I have something more to say. Attend to it; for what I say I'll
+do. Do you hear me, you fairy spirit? What I say, I mean to do!'
+
+Her rage got the better of her again, for a moment; but it passed over
+her face like a spasm, and left her smiling.
+
+'Hide yourself,' she pursued, 'if not at home, somewhere. Let it be
+somewhere beyond reach; in some obscure life--or, better still, in some
+obscure death. I wonder, if your loving heart will not break, you have
+found no way of helping it to be still! I have heard of such means
+sometimes. I believe they may be easily found.'
+
+A low crying, on the part of Emily, interrupted her here. She stopped,
+and listened to it as if it were music.
+
+'I am of a strange nature, perhaps,' Rosa Dartle went on; 'but I can't
+breathe freely in the air you breathe. I find it sickly. Therefore, I
+will have it cleared; I will have it purified of you. If you live here
+tomorrow, I'll have your story and your character proclaimed on the
+common stair. There are decent women in the house, I am told; and it
+is a pity such a light as you should be among them, and concealed. If,
+leaving here, you seek any refuge in this town in any character but your
+true one (which you are welcome to bear, without molestation from me),
+the same service shall be done you, if I hear of your retreat. Being
+assisted by a gentleman who not long ago aspired to the favour of your
+hand, I am sanguine as to that.'
+
+Would he never, never come? How long was I to bear this? How long could
+I bear it? 'Oh me, oh me!' exclaimed the wretched Emily, in a tone that
+might have touched the hardest heart, I should have thought; but there
+was no relenting in Rosa Dartle's smile. 'What, what, shall I do!'
+
+'Do?' returned the other. 'Live happy in your own reflections!
+Consecrate your existence to the recollection of James Steerforth's
+tenderness--he would have made you his serving-man's wife, would he
+not?---or to feeling grateful to the upright and deserving creature who
+would have taken you as his gift. Or, if those proud remembrances, and
+the consciousness of your own virtues, and the honourable position to
+which they have raised you in the eyes of everything that wears the
+human shape, will not sustain you, marry that good man, and be happy in
+his condescension. If this will not do either, die! There are doorways
+and dust-heaps for such deaths, and such despair--find one, and take
+your flight to Heaven!'
+
+I heard a distant foot upon the stairs. I knew it, I was certain. It was
+his, thank God!
+
+She moved slowly from before the door when she said this, and passed out
+of my sight.
+
+'But mark!' she added, slowly and sternly, opening the other door to
+go away, 'I am resolved, for reasons that I have and hatreds that
+I entertain, to cast you out, unless you withdraw from my reach
+altogether, or drop your pretty mask. This is what I had to say; and
+what I say, I mean to do!'
+
+The foot upon the stairs came nearer--nearer--passed her as she went
+down--rushed into the room!
+
+'Uncle!'
+
+A fearful cry followed the word. I paused a moment, and looking in, saw
+him supporting her insensible figure in his arms. He gazed for a few
+seconds in the face; then stooped to kiss it--oh, how tenderly!--and
+drew a handkerchief before it.
+
+'Mas'r Davy,' he said, in a low tremulous voice, when it was covered, 'I
+thank my Heav'nly Father as my dream's come true! I thank Him hearty for
+having guided of me, in His own ways, to my darling!'
+
+With those words he took her up in his arms; and, with the veiled
+face lying on his bosom, and addressed towards his own, carried her,
+motionless and unconscious, down the stairs.
+
+
+
+CHAPTER 51. THE BEGINNING OF A LONGER JOURNEY
+
+
+It was yet early in the morning of the following day, when, as I was
+walking in my garden with my aunt (who took little other exercise
+now, being so much in attendance on my dear Dora), I was told that Mr.
+Peggotty desired to speak with me. He came into the garden to meet me
+half-way, on my going towards the gate; and bared his head, as it was
+always his custom to do when he saw my aunt, for whom he had a high
+respect. I had been telling her all that had happened overnight. Without
+saying a word, she walked up with a cordial face, shook hands with him,
+and patted him on the arm. It was so expressively done, that she had no
+need to say a word. Mr. Peggotty understood her quite as well as if she
+had said a thousand.
+
+'I'll go in now, Trot,' said my aunt, 'and look after Little Blossom,
+who will be getting up presently.'
+
+'Not along of my being heer, ma'am, I hope?' said Mr. Peggotty. 'Unless
+my wits is gone a bahd's neezing'--by which Mr. Peggotty meant to say,
+bird's-nesting--'this morning, 'tis along of me as you're a-going to
+quit us?'
+
+'You have something to say, my good friend,' returned my aunt, 'and will
+do better without me.'
+
+'By your leave, ma'am,' returned Mr. Peggotty, 'I should take it kind,
+pervising you doen't mind my clicketten, if you'd bide heer.'
+
+'Would you?' said my aunt, with short good-nature. 'Then I am sure I
+will!'
+
+So, she drew her arm through Mr. Peggotty's, and walked with him to a
+leafy little summer-house there was at the bottom of the garden, where
+she sat down on a bench, and I beside her. There was a seat for Mr.
+Peggotty too, but he preferred to stand, leaning his hand on the small
+rustic table. As he stood, looking at his cap for a little while before
+beginning to speak, I could not help observing what power and force
+of character his sinewy hand expressed, and what a good and trusty
+companion it was to his honest brow and iron-grey hair.
+
+'I took my dear child away last night,' Mr. Peggotty began, as he
+raised his eyes to ours, 'to my lodging, wheer I have a long time been
+expecting of her and preparing fur her. It was hours afore she knowed me
+right; and when she did, she kneeled down at my feet, and kiender said
+to me, as if it was her prayers, how it all come to be. You may believe
+me, when I heerd her voice, as I had heerd at home so playful--and see
+her humbled, as it might be in the dust our Saviour wrote in with his
+blessed hand--I felt a wownd go to my 'art, in the midst of all its
+thankfulness.'
+
+He drew his sleeve across his face, without any pretence of concealing
+why; and then cleared his voice.
+
+'It warn't for long as I felt that; for she was found. I had on'y to
+think as she was found, and it was gone. I doen't know why I do so much
+as mention of it now, I'm sure. I didn't have it in my mind a minute
+ago, to say a word about myself; but it come up so nat'ral, that I
+yielded to it afore I was aweer.'
+
+'You are a self-denying soul,' said my aunt, 'and will have your
+reward.'
+
+Mr. Peggotty, with the shadows of the leaves playing athwart his
+face, made a surprised inclination of the head towards my aunt, as an
+acknowledgement of her good opinion; then took up the thread he had
+relinquished.
+
+'When my Em'ly took flight,' he said, in stern wrath for the moment,
+'from the house wheer she was made a prisoner by that theer spotted
+snake as Mas'r Davy see,--and his story's trew, and may GOD confound
+him!--she took flight in the night. It was a dark night, with a many
+stars a-shining. She was wild. She ran along the sea beach, believing
+the old boat was theer; and calling out to us to turn away our faces,
+for she was a-coming by. She heerd herself a-crying out, like as if
+it was another person; and cut herself on them sharp-pinted stones and
+rocks, and felt it no more than if she had been rock herself. Ever so
+fur she run, and there was fire afore her eyes, and roarings in her
+ears. Of a sudden--or so she thowt, you unnerstand--the day broke, wet
+and windy, and she was lying b'low a heap of stone upon the shore, and
+a woman was a-speaking to her, saying, in the language of that country,
+what was it as had gone so much amiss?'
+
+He saw everything he related. It passed before him, as he spoke, so
+vividly, that, in the intensity of his earnestness, he presented what
+he described to me, with greater distinctness than I can express. I can
+hardly believe, writing now long afterwards, but that I was actually
+present in these scenes; they are impressed upon me with such an
+astonishing air of fidelity.
+
+'As Em'ly's eyes--which was heavy--see this woman better,' Mr. Peggotty
+went on, 'she know'd as she was one of them as she had often talked to
+on the beach. Fur, though she had run (as I have said) ever so fur in
+the night, she had oftentimes wandered long ways, partly afoot, partly
+in boats and carriages, and know'd all that country, 'long the coast,
+miles and miles. She hadn't no children of her own, this woman, being
+a young wife; but she was a-looking to have one afore long. And may
+my prayers go up to Heaven that 'twill be a happiness to her, and a
+comfort, and a honour, all her life! May it love her and be dootiful to
+her, in her old age; helpful of her at the last; a Angel to her heer,
+and heerafter!'
+
+'Amen!' said my aunt.
+
+'She had been summat timorous and down,' said Mr. Peggotty, and had sat,
+at first, a little way off, at her spinning, or such work as it was,
+when Em'ly talked to the children. But Em'ly had took notice of her,
+and had gone and spoke to her; and as the young woman was partial to
+the children herself, they had soon made friends. Sermuchser, that when
+Em'ly went that way, she always giv Em'ly flowers. This was her as
+now asked what it was that had gone so much amiss. Em'ly told her,
+and she--took her home. She did indeed. She took her home,' said Mr.
+Peggotty, covering his face.
+
+He was more affected by this act of kindness, than I had ever seen him
+affected by anything since the night she went away. My aunt and I did
+not attempt to disturb him.
+
+'It was a little cottage, you may suppose,' he said, presently, 'but she
+found space for Em'ly in it,--her husband was away at sea,--and she kep
+it secret, and prevailed upon such neighbours as she had (they was not
+many near) to keep it secret too. Em'ly was took bad with fever,
+and, what is very strange to me is,--maybe 'tis not so strange to
+scholars,--the language of that country went out of her head, and she
+could only speak her own, that no one unnerstood. She recollects, as if
+she had dreamed it, that she lay there always a-talking her own tongue,
+always believing as the old boat was round the next pint in the bay, and
+begging and imploring of 'em to send theer and tell how she was dying,
+and bring back a message of forgiveness, if it was on'y a wured. A'most
+the whole time, she thowt,--now, that him as I made mention on just now
+was lurking for her unnerneath the winder; now that him as had brought
+her to this was in the room,--and cried to the good young woman not to
+give her up, and know'd, at the same time, that she couldn't unnerstand,
+and dreaded that she must be took away. Likewise the fire was afore
+her eyes, and the roarings in her ears; and theer was no today, nor
+yesterday, nor yet tomorrow; but everything in her life as ever had
+been, or as ever could be, and everything as never had been, and as
+never could be, was a crowding on her all at once, and nothing clear nor
+welcome, and yet she sang and laughed about it! How long this lasted, I
+doen't know; but then theer come a sleep; and in that sleep, from being
+a many times stronger than her own self, she fell into the weakness of
+the littlest child.'
+
+Here he stopped, as if for relief from the terrors of his own
+description. After being silent for a few moments, he pursued his story.
+
+'It was a pleasant arternoon when she awoke; and so quiet, that there
+warn't a sound but the rippling of that blue sea without a tide, upon
+the shore. It was her belief, at first, that she was at home upon a
+Sunday morning; but the vine leaves as she see at the winder, and the
+hills beyond, warn't home, and contradicted of her. Then, come in her
+friend to watch alongside of her bed; and then she know'd as the old
+boat warn't round that next pint in the bay no more, but was fur off;
+and know'd where she was, and why; and broke out a-crying on that good
+young woman's bosom, wheer I hope her baby is a-lying now, a-cheering of
+her with its pretty eyes!'
+
+He could not speak of this good friend of Emily's without a flow of
+tears. It was in vain to try. He broke down again, endeavouring to bless
+her!
+
+'That done my Em'ly good,' he resumed, after such emotion as I could
+not behold without sharing in; and as to my aunt, she wept with all her
+heart; 'that done Em'ly good, and she begun to mend. But, the language
+of that country was quite gone from her, and she was forced to make
+signs. So she went on, getting better from day to day, slow, but sure,
+and trying to learn the names of common things--names as she seemed
+never to have heerd in all her life--till one evening come, when she
+was a-setting at her window, looking at a little girl at play upon the
+beach. And of a sudden this child held out her hand, and said, what
+would be in English, "Fisherman's daughter, here's a shell!"--for you
+are to unnerstand that they used at first to call her "Pretty lady", as
+the general way in that country is, and that she had taught 'em to
+call her "Fisherman's daughter" instead. The child says of a sudden,
+"Fisherman's daughter, here's a shell!" Then Em'ly unnerstands her; and
+she answers, bursting out a-crying; and it all comes back!
+
+'When Em'ly got strong again,' said Mr. Peggotty, after another short
+interval of silence, 'she cast about to leave that good young creetur,
+and get to her own country. The husband was come home, then; and the two
+together put her aboard a small trader bound to Leghorn, and from that
+to France. She had a little money, but it was less than little as they
+would take for all they done. I'm a'most glad on it, though they was
+so poor! What they done, is laid up wheer neither moth or rust doth
+corrupt, and wheer thieves do not break through nor steal. Mas'r Davy,
+it'll outlast all the treasure in the wureld.
+
+'Em'ly got to France, and took service to wait on travelling ladies at a
+inn in the port. Theer, theer come, one day, that snake. --Let him never
+come nigh me. I doen't know what hurt I might do him!--Soon as she see
+him, without him seeing her, all her fear and wildness returned upon
+her, and she fled afore the very breath he draw'd. She come to England,
+and was set ashore at Dover.
+
+'I doen't know,' said Mr. Peggotty, 'for sure, when her 'art begun to
+fail her; but all the way to England she had thowt to come to her dear
+home. Soon as she got to England she turned her face tow'rds it. But,
+fear of not being forgiv, fear of being pinted at, fear of some of
+us being dead along of her, fear of many things, turned her from it,
+kiender by force, upon the road: "Uncle, uncle," she says to me, "the
+fear of not being worthy to do what my torn and bleeding breast so
+longed to do, was the most fright'ning fear of all! I turned back, when
+my 'art was full of prayers that I might crawl to the old door-step, in
+the night, kiss it, lay my wicked face upon it, and theer be found dead
+in the morning."
+
+'She come,' said Mr. Peggotty, dropping his voice to an
+awe-stricken whisper, 'to London. She--as had never seen it in her
+life--alone--without a penny--young--so pretty--come to London. A'most
+the moment as she lighted heer, all so desolate, she found (as she
+believed) a friend; a decent woman as spoke to her about the needle-work
+as she had been brought up to do, about finding plenty of it fur her,
+about a lodging fur the night, and making secret inquiration concerning
+of me and all at home, tomorrow. When my child,' he said aloud, and with
+an energy of gratitude that shook him from head to foot, 'stood upon the
+brink of more than I can say or think on--Martha, trew to her promise,
+saved her.'
+
+I could not repress a cry of joy.
+
+'Mas'r Davy!' said he, gripping my hand in that strong hand of his,
+'it was you as first made mention of her to me. I thankee, sir! She was
+arnest. She had know'd of her bitter knowledge wheer to watch and what
+to do. She had done it. And the Lord was above all! She come, white and
+hurried, upon Em'ly in her sleep. She says to her, "Rise up from worse
+than death, and come with me!" Them belonging to the house would have
+stopped her, but they might as soon have stopped the sea. "Stand away
+from me," she says, "I am a ghost that calls her from beside her open
+grave!" She told Em'ly she had seen me, and know'd I loved her, and
+forgive her. She wrapped her, hasty, in her clothes. She took her, faint
+and trembling, on her arm. She heeded no more what they said, than if
+she had had no ears. She walked among 'em with my child, minding only
+her; and brought her safe out, in the dead of the night, from that black
+pit of ruin!
+
+'She attended on Em'ly,' said Mr. Peggotty, who had released my hand,
+and put his own hand on his heaving chest; 'she attended to my Em'ly,
+lying wearied out, and wandering betwixt whiles, till late next day.
+Then she went in search of me; then in search of you, Mas'r Davy. She
+didn't tell Em'ly what she come out fur, lest her 'art should fail, and
+she should think of hiding of herself. How the cruel lady know'd of
+her being theer, I can't say. Whether him as I have spoke so much of,
+chanced to see 'em going theer, or whether (which is most like, to my
+thinking) he had heerd it from the woman, I doen't greatly ask myself.
+My niece is found.
+
+'All night long,' said Mr. Peggotty, 'we have been together, Em'ly
+and me. 'Tis little (considering the time) as she has said, in wureds,
+through them broken-hearted tears; 'tis less as I have seen of her dear
+face, as grow'd into a woman's at my hearth. But, all night long, her
+arms has been about my neck; and her head has laid heer; and we knows
+full well, as we can put our trust in one another, ever more.'
+
+He ceased to speak, and his hand upon the table rested there in perfect
+repose, with a resolution in it that might have conquered lions.
+
+'It was a gleam of light upon me, Trot,' said my aunt, drying her eyes,
+'when I formed the resolution of being godmother to your sister Betsey
+Trotwood, who disappointed me; but, next to that, hardly anything would
+have given me greater pleasure, than to be godmother to that good young
+creature's baby!'
+
+Mr. Peggotty nodded his understanding of my aunt's feelings, but could
+not trust himself with any verbal reference to the subject of her
+commendation. We all remained silent, and occupied with our own
+reflections (my aunt drying her eyes, and now sobbing convulsively, and
+now laughing and calling herself a fool); until I spoke.
+
+'You have quite made up your mind,' said I to Mr. Peggotty, 'as to the
+future, good friend? I need scarcely ask you.'
+
+'Quite, Mas'r Davy,' he returned; 'and told Em'ly. Theer's mighty
+countries, fur from heer. Our future life lays over the sea.'
+
+'They will emigrate together, aunt,' said I.
+
+'Yes!' said Mr. Peggotty, with a hopeful smile. 'No one can't reproach
+my darling in Australia. We will begin a new life over theer!'
+
+I asked him if he yet proposed to himself any time for going away.
+
+'I was down at the Docks early this morning, sir,' he returned, 'to get
+information concerning of them ships. In about six weeks or two
+months from now, there'll be one sailing--I see her this morning--went
+aboard--and we shall take our passage in her.'
+
+'Quite alone?' I asked.
+
+'Aye, Mas'r Davy!' he returned. 'My sister, you see, she's that fond
+of you and yourn, and that accustomed to think on'y of her own country,
+that it wouldn't be hardly fair to let her go. Besides which, theer's
+one she has in charge, Mas'r Davy, as doen't ought to be forgot.'
+
+'Poor Ham!' said I.
+
+'My good sister takes care of his house, you see, ma'am, and he takes
+kindly to her,' Mr. Peggotty explained for my aunt's better information.
+'He'll set and talk to her, with a calm spirit, wen it's like he
+couldn't bring himself to open his lips to another. Poor fellow!' said
+Mr. Peggotty, shaking his head, 'theer's not so much left him, that he
+could spare the little as he has!'
+
+'And Mrs. Gummidge?' said I.
+
+'Well, I've had a mort of consideration, I do tell you,' returned Mr.
+Peggotty, with a perplexed look which gradually cleared as he went
+on, 'concerning of Missis Gummidge. You see, wen Missis Gummidge falls
+a-thinking of the old 'un, she an't what you may call good company.
+Betwixt you and me, Mas'r Davy--and you, ma'am--wen Mrs. Gummidge takes
+to wimicking,'--our old country word for crying,--'she's liable to be
+considered to be, by them as didn't know the old 'un, peevish-like. Now
+I DID know the old 'un,' said Mr. Peggotty, 'and I know'd his merits,
+so I unnerstan' her; but 'tan't entirely so, you see, with
+others--nat'rally can't be!'
+
+My aunt and I both acquiesced.
+
+'Wheerby,' said Mr. Peggotty, 'my sister might--I doen't say she would,
+but might--find Missis Gummidge give her a leetle trouble now-and-again.
+Theerfur 'tan't my intentions to moor Missis Gummidge 'long with them,
+but to find a Beein' fur her wheer she can fisherate for herself.'
+(A Beein' signifies, in that dialect, a home, and to fisherate is to
+provide.) 'Fur which purpose,' said Mr. Peggotty, 'I means to make her
+a 'lowance afore I go, as'll leave her pretty comfort'ble. She's the
+faithfullest of creeturs. 'Tan't to be expected, of course, at her
+time of life, and being lone and lorn, as the good old Mawther is to
+be knocked about aboardship, and in the woods and wilds of a new and
+fur-away country. So that's what I'm a-going to do with her.'
+
+He forgot nobody. He thought of everybody's claims and strivings, but
+his own.
+
+'Em'ly,' he continued, 'will keep along with me--poor child, she's sore
+in need of peace and rest!--until such time as we goes upon our voyage.
+She'll work at them clothes, as must be made; and I hope her troubles
+will begin to seem longer ago than they was, wen she finds herself once
+more by her rough but loving uncle.'
+
+MY aunt nodded confirmation of this hope, and imparted great
+satisfaction to Mr. Peggotty.
+
+'Theer's one thing furder, Mas'r Davy,' said he, putting his hand in his
+breast-pocket, and gravely taking out the little paper bundle I had
+seen before, which he unrolled on the table. 'Theer's these here
+banknotes--fifty pound, and ten. To them I wish to add the money as she
+come away with. I've asked her about that (but not saying why), and have
+added of it up. I an't a scholar. Would you be so kind as see how 'tis?'
+
+He handed me, apologetically for his scholarship, a piece of paper, and
+observed me while I looked it over. It was quite right.
+
+'Thankee, sir,' he said, taking it back. 'This money, if you doen't
+see objections, Mas'r Davy, I shall put up jest afore I go, in a cover
+directed to him; and put that up in another, directed to his mother.
+I shall tell her, in no more wureds than I speak to you, what it's the
+price on; and that I'm gone, and past receiving of it back.'
+
+I told him that I thought it would be right to do so--that I was
+thoroughly convinced it would be, since he felt it to be right.
+
+'I said that theer was on'y one thing furder,' he proceeded with a grave
+smile, when he had made up his little bundle again, and put it in his
+pocket; 'but theer was two. I warn't sure in my mind, wen I come out
+this morning, as I could go and break to Ham, of my own self, what had
+so thankfully happened. So I writ a letter while I was out, and put
+it in the post-office, telling of 'em how all was as 'tis; and that I
+should come down tomorrow to unload my mind of what little needs a-doing
+of down theer, and, most-like, take my farewell leave of Yarmouth.'
+
+'And do you wish me to go with you?' said I, seeing that he left
+something unsaid.
+
+'If you could do me that kind favour, Mas'r Davy,' he replied. 'I know
+the sight on you would cheer 'em up a bit.'
+
+My little Dora being in good spirits, and very desirous that I should
+go--as I found on talking it over with her--I readily pledged myself to
+accompany him in accordance with his wish. Next morning, consequently,
+we were on the Yarmouth coach, and again travelling over the old ground.
+
+As we passed along the familiar street at night--Mr. Peggotty, in
+despite of all my remonstrances, carrying my bag--I glanced into Omer
+and Joram's shop, and saw my old friend Mr. Omer there, smoking his
+pipe. I felt reluctant to be present, when Mr. Peggotty first met his
+sister and Ham; and made Mr. Omer my excuse for lingering behind.
+
+'How is Mr. Omer, after this long time?' said I, going in.
+
+He fanned away the smoke of his pipe, that he might get a better view of
+me, and soon recognized me with great delight.
+
+'I should get up, sir, to acknowledge such an honour as this visit,'
+said he, 'only my limbs are rather out of sorts, and I am wheeled about.
+With the exception of my limbs and my breath, howsoever, I am as hearty
+as a man can be, I'm thankful to say.'
+
+I congratulated him on his contented looks and his good spirits, and
+saw, now, that his easy-chair went on wheels.
+
+'It's an ingenious thing, ain't it?' he inquired, following the
+direction of my glance, and polishing the elbow with his arm. 'It runs
+as light as a feather, and tracks as true as a mail-coach. Bless you,
+my little Minnie--my grand-daughter you know, Minnie's child--puts her
+little strength against the back, gives it a shove, and away we go, as
+clever and merry as ever you see anything! And I tell you what--it's a
+most uncommon chair to smoke a pipe in.'
+
+I never saw such a good old fellow to make the best of a thing, and
+find out the enjoyment of it, as Mr. Omer. He was as radiant, as if
+his chair, his asthma, and the failure of his limbs, were the various
+branches of a great invention for enhancing the luxury of a pipe.
+
+'I see more of the world, I can assure you,' said Mr. Omer, 'in this
+chair, than ever I see out of it. You'd be surprised at the number of
+people that looks in of a day to have a chat. You really would! There's
+twice as much in the newspaper, since I've taken to this chair, as there
+used to be. As to general reading, dear me, what a lot of it I do get
+through! That's what I feel so strong, you know! If it had been my eyes,
+what should I have done? If it had been my ears, what should I have
+done? Being my limbs, what does it signify? Why, my limbs only made my
+breath shorter when I used 'em. And now, if I want to go out into
+the street or down to the sands, I've only got to call Dick, Joram's
+youngest 'prentice, and away I go in my own carriage, like the Lord
+Mayor of London.'
+
+He half suffocated himself with laughing here.
+
+'Lord bless you!' said Mr. Omer, resuming his pipe, 'a man must take
+the fat with the lean; that's what he must make up his mind to, in this
+life. Joram does a fine business. Ex-cellent business!'
+
+'I am very glad to hear it,' said I.
+
+'I knew you would be,' said Mr. Omer. 'And Joram and Minnie are like
+Valentines. What more can a man expect? What's his limbs to that!'
+
+His supreme contempt for his own limbs, as he sat smoking, was one of
+the pleasantest oddities I have ever encountered.
+
+'And since I've took to general reading, you've took to general writing,
+eh, sir?' said Mr. Omer, surveying me admiringly. 'What a lovely work
+that was of yours! What expressions in it! I read it every word--every
+word. And as to feeling sleepy! Not at all!'
+
+I laughingly expressed my satisfaction, but I must confess that I
+thought this association of ideas significant.
+
+'I give you my word and honour, sir,' said Mr. Omer, 'that when I lay
+that book upon the table, and look at it outside; compact in three
+separate and indiwidual wollumes--one, two, three; I am as proud as
+Punch to think that I once had the honour of being connected with
+your family. And dear me, it's a long time ago, now, ain't it? Over
+at Blunderstone. With a pretty little party laid along with the other
+party. And you quite a small party then, yourself. Dear, dear!'
+
+I changed the subject by referring to Emily. After assuring him that I
+did not forget how interested he had always been in her, and how
+kindly he had always treated her, I gave him a general account of her
+restoration to her uncle by the aid of Martha; which I knew would please
+the old man. He listened with the utmost attention, and said, feelingly,
+when I had done:
+
+'I am rejoiced at it, sir! It's the best news I have heard for many
+a day. Dear, dear, dear! And what's going to be undertook for that
+unfortunate young woman, Martha, now?'
+
+'You touch a point that my thoughts have been dwelling on since
+yesterday,' said I, 'but on which I can give you no information yet, Mr.
+Omer. Mr. Peggotty has not alluded to it, and I have a delicacy in
+doing so. I am sure he has not forgotten it. He forgets nothing that is
+disinterested and good.'
+
+'Because you know,' said Mr. Omer, taking himself up, where he had left
+off, 'whatever is done, I should wish to be a member of. Put me down for
+anything you may consider right, and let me know. I never could think
+the girl all bad, and I am glad to find she's not. So will my daughter
+Minnie be. Young women are contradictory creatures in some things--her
+mother was just the same as her--but their hearts are soft and kind.
+It's all show with Minnie, about Martha. Why she should consider it
+necessary to make any show, I don't undertake to tell you. But it's all
+show, bless you. She'd do her any kindness in private. So, put me down
+for whatever you may consider right, will you be so good? and drop me
+a line where to forward it. Dear me!' said Mr. Omer, 'when a man is
+drawing on to a time of life, where the two ends of life meet; when he
+finds himself, however hearty he is, being wheeled about for the second
+time, in a speeches of go-cart; he should be over-rejoiced to do a
+kindness if he can. He wants plenty. And I don't speak of myself,
+particular,' said Mr. Omer, 'because, sir, the way I look at it is, that
+we are all drawing on to the bottom of the hill, whatever age we are,
+on account of time never standing still for a single moment. So let us
+always do a kindness, and be over-rejoiced. To be sure!'
+
+He knocked the ashes out of his pipe, and put it on a ledge in the back
+of his chair, expressly made for its reception.
+
+'There's Em'ly's cousin, him that she was to have been married to,' said
+Mr. Omer, rubbing his hands feebly, 'as fine a fellow as there is in
+Yarmouth! He'll come and talk or read to me, in the evening, for an hour
+together sometimes. That's a kindness, I should call it! All his life's
+a kindness.'
+
+'I am going to see him now,' said I.
+
+'Are you?' said Mr. Omer. 'Tell him I was hearty, and sent my respects.
+Minnie and Joram's at a ball. They would be as proud to see you as I
+am, if they was at home. Minnie won't hardly go out at all, you see, "on
+account of father", as she says. So I swore tonight, that if she didn't
+go, I'd go to bed at six. In consequence of which,' Mr. Omer shook
+himself and his chair with laughter at the success of his device, 'she
+and Joram's at a ball.'
+
+I shook hands with him, and wished him good night.
+
+'Half a minute, sir,' said Mr. Omer. 'If you was to go without seeing
+my little elephant, you'd lose the best of sights. You never see such
+a sight! Minnie!' A musical little voice answered, from somewhere
+upstairs, 'I am coming, grandfather!' and a pretty little girl with
+long, flaxen, curling hair, soon came running into the shop.
+
+'This is my little elephant, sir,' said Mr. Omer, fondling the child.
+'Siamese breed, sir. Now, little elephant!'
+
+The little elephant set the door of the parlour open, enabling me to see
+that, in these latter days, it was converted into a bedroom for Mr.
+Omer who could not be easily conveyed upstairs; and then hid her pretty
+forehead, and tumbled her long hair, against the back of Mr. Omer's
+chair.
+
+'The elephant butts, you know, sir,' said Mr. Omer, winking, 'when he
+goes at a object. Once, elephant. Twice. Three times!'
+
+At this signal, the little elephant, with a dexterity that was next to
+marvellous in so small an animal, whisked the chair round with Mr. Omer
+in it, and rattled it off, pell-mell, into the parlour, without touching
+the door-post: Mr. Omer indescribably enjoying the performance, and
+looking back at me on the road as if it were the triumphant issue of his
+life's exertions.
+
+After a stroll about the town I went to Ham's house. Peggotty had now
+removed here for good; and had let her own house to the successor of
+Mr. Barkis in the carrying business, who had paid her very well for the
+good-will, cart, and horse. I believe the very same slow horse that Mr.
+Barkis drove was still at work.
+
+I found them in the neat kitchen, accompanied by Mrs. Gummidge, who had
+been fetched from the old boat by Mr. Peggotty himself. I doubt if
+she could have been induced to desert her post, by anyone else. He
+had evidently told them all. Both Peggotty and Mrs. Gummidge had their
+aprons to their eyes, and Ham had just stepped out 'to take a turn on
+the beach'. He presently came home, very glad to see me; and I hope they
+were all the better for my being there. We spoke, with some approach to
+cheerfulness, of Mr. Peggotty's growing rich in a new country, and of
+the wonders he would describe in his letters. We said nothing of Emily
+by name, but distantly referred to her more than once. Ham was the
+serenest of the party.
+
+But, Peggotty told me, when she lighted me to a little chamber where the
+Crocodile book was lying ready for me on the table, that he always was
+the same. She believed (she told me, crying) that he was broken-hearted;
+though he was as full of courage as of sweetness, and worked harder and
+better than any boat-builder in any yard in all that part. There were
+times, she said, of an evening, when he talked of their old life in
+the boat-house; and then he mentioned Emily as a child. But, he never
+mentioned her as a woman.
+
+I thought I had read in his face that he would like to speak to me
+alone. I therefore resolved to put myself in his way next evening, as he
+came home from his work. Having settled this with myself, I fell asleep.
+That night, for the first time in all those many nights, the candle was
+taken out of the window, Mr. Peggotty swung in his old hammock in the
+old boat, and the wind murmured with the old sound round his head.
+
+All next day, he was occupied in disposing of his fishing-boat and
+tackle; in packing up, and sending to London by waggon, such of his
+little domestic possessions as he thought would be useful to him; and in
+parting with the rest, or bestowing them on Mrs. Gummidge. She was with
+him all day. As I had a sorrowful wish to see the old place once more,
+before it was locked up, I engaged to meet them there in the evening.
+But I so arranged it, as that I should meet Ham first.
+
+It was easy to come in his way, as I knew where he worked. I met him
+at a retired part of the sands, which I knew he would cross, and turned
+back with him, that he might have leisure to speak to me if he really
+wished. I had not mistaken the expression of his face. We had walked but
+a little way together, when he said, without looking at me:
+
+'Mas'r Davy, have you seen her?'
+
+'Only for a moment, when she was in a swoon,' I softly answered.
+
+We walked a little farther, and he said:
+
+'Mas'r Davy, shall you see her, d'ye think?'
+
+'It would be too painful to her, perhaps,' said I.
+
+'I have thowt of that,' he replied. 'So 'twould, sir, so 'twould.'
+
+'But, Ham,' said I, gently, 'if there is anything that I could write
+to her, for you, in case I could not tell it; if there is anything
+you would wish to make known to her through me; I should consider it a
+sacred trust.'
+
+'I am sure on't. I thankee, sir, most kind! I think theer is something I
+could wish said or wrote.'
+
+'What is it?'
+
+We walked a little farther in silence, and then he spoke.
+
+''Tan't that I forgive her. 'Tan't that so much. 'Tis more as I beg of
+her to forgive me, for having pressed my affections upon her. Odd times,
+I think that if I hadn't had her promise fur to marry me, sir, she was
+that trustful of me, in a friendly way, that she'd have told me what was
+struggling in her mind, and would have counselled with me, and I might
+have saved her.'
+
+I pressed his hand. 'Is that all?' 'Theer's yet a something else,' he
+returned, 'if I can say it, Mas'r Davy.'
+
+We walked on, farther than we had walked yet, before he spoke again. He
+was not crying when he made the pauses I shall express by lines. He was
+merely collecting himself to speak very plainly.
+
+'I loved her--and I love the mem'ry of her--too deep--to be able to
+lead her to believe of my own self as I'm a happy man. I could only be
+happy--by forgetting of her--and I'm afeerd I couldn't hardly bear as
+she should be told I done that. But if you, being so full of learning,
+Mas'r Davy, could think of anything to say as might bring her to believe
+I wasn't greatly hurt: still loving of her, and mourning for her:
+anything as might bring her to believe as I was not tired of my life,
+and yet was hoping fur to see her without blame, wheer the wicked cease
+from troubling and the weary are at rest--anything as would ease her
+sorrowful mind, and yet not make her think as I could ever marry, or as
+'twas possible that anyone could ever be to me what she was--I should
+ask of you to say that--with my prayers for her--that was so dear.'
+
+I pressed his manly hand again, and told him I would charge myself to do
+this as well as I could.
+
+'I thankee, sir,' he answered. ''Twas kind of you to meet me. 'Twas kind
+of you to bear him company down. Mas'r Davy, I unnerstan' very well,
+though my aunt will come to Lon'on afore they sail, and they'll unite
+once more, that I am not like to see him agen. I fare to feel sure on't.
+We doen't say so, but so 'twill be, and better so. The last you see on
+him--the very last--will you give him the lovingest duty and thanks of
+the orphan, as he was ever more than a father to?'
+
+This I also promised, faithfully.
+
+'I thankee agen, sir,' he said, heartily shaking hands. 'I know wheer
+you're a-going. Good-bye!'
+
+With a slight wave of his hand, as though to explain to me that he could
+not enter the old place, he turned away. As I looked after his figure,
+crossing the waste in the moonlight, I saw him turn his face towards a
+strip of silvery light upon the sea, and pass on, looking at it, until
+he was a shadow in the distance.
+
+The door of the boat-house stood open when I approached; and, on
+entering, I found it emptied of all its furniture, saving one of the old
+lockers, on which Mrs. Gummidge, with a basket on her knee, was seated,
+looking at Mr. Peggotty. He leaned his elbow on the rough chimney-piece,
+and gazed upon a few expiring embers in the grate; but he raised his
+head, hopefully, on my coming in, and spoke in a cheery manner.
+
+'Come, according to promise, to bid farewell to 't, eh, Mas'r Davy?'
+he said, taking up the candle. 'Bare enough, now, an't it?' 'Indeed you
+have made good use of the time,' said I.
+
+'Why, we have not been idle, sir. Missis Gummidge has worked like a--I
+doen't know what Missis Gummidge an't worked like,' said Mr. Peggotty,
+looking at her, at a loss for a sufficiently approving simile.
+
+Mrs. Gummidge, leaning on her basket, made no observation.
+
+'Theer's the very locker that you used to sit on, 'long with Em'ly!'
+said Mr. Peggotty, in a whisper. 'I'm a-going to carry it away with me,
+last of all. And heer's your old little bedroom, see, Mas'r Davy! A'most
+as bleak tonight, as 'art could wish!'
+
+In truth, the wind, though it was low, had a solemn sound, and crept
+around the deserted house with a whispered wailing that was very
+mournful. Everything was gone, down to the little mirror with the
+oyster-shell frame. I thought of myself, lying here, when that first
+great change was being wrought at home. I thought of the blue-eyed child
+who had enchanted me. I thought of Steerforth: and a foolish, fearful
+fancy came upon me of his being near at hand, and liable to be met at
+any turn.
+
+''Tis like to be long,' said Mr. Peggotty, in a low voice, 'afore
+the boat finds new tenants. They look upon 't, down beer, as being
+unfortunate now!'
+
+'Does it belong to anybody in the neighbourhood?' I asked.
+
+'To a mast-maker up town,' said Mr. Peggotty. 'I'm a-going to give the
+key to him tonight.'
+
+We looked into the other little room, and came back to Mrs. Gummidge,
+sitting on the locker, whom Mr. Peggotty, putting the light on the
+chimney-piece, requested to rise, that he might carry it outside the
+door before extinguishing the candle.
+
+'Dan'l,' said Mrs. Gummidge, suddenly deserting her basket, and clinging
+to his arm 'my dear Dan'l, the parting words I speak in this house is, I
+mustn't be left behind. Doen't ye think of leaving me behind, Dan'l! Oh,
+doen't ye ever do it!'
+
+Mr. Peggotty, taken aback, looked from Mrs. Gummidge to me, and from me
+to Mrs. Gummidge, as if he had been awakened from a sleep.
+
+'Doen't ye, dearest Dan'l, doen't ye!' cried Mrs. Gummidge, fervently.
+'Take me 'long with you, Dan'l, take me 'long with you and Em'ly! I'll
+be your servant, constant and trew. If there's slaves in them parts
+where you're a-going, I'll be bound to you for one, and happy, but
+doen't ye leave me behind, Dan'l, that's a deary dear!'
+
+'My good soul,' said Mr. Peggotty, shaking his head, 'you doen't know
+what a long voyage, and what a hard life 'tis!' 'Yes, I do, Dan'l! I can
+guess!' cried Mrs. Gummidge. 'But my parting words under this roof is,
+I shall go into the house and die, if I am not took. I can dig, Dan'l.
+I can work. I can live hard. I can be loving and patient now--more than
+you think, Dan'l, if you'll on'y try me. I wouldn't touch the 'lowance,
+not if I was dying of want, Dan'l Peggotty; but I'll go with you and
+Em'ly, if you'll on'y let me, to the world's end! I know how 'tis; I
+know you think that I am lone and lorn; but, deary love, 'tan't so no
+more! I ain't sat here, so long, a-watching, and a-thinking of your
+trials, without some good being done me. Mas'r Davy, speak to him for
+me! I knows his ways, and Em'ly's, and I knows their sorrows, and can be
+a comfort to 'em, some odd times, and labour for 'em allus! Dan'l, deary
+Dan'l, let me go 'long with you!'
+
+And Mrs. Gummidge took his hand, and kissed it with a homely pathos and
+affection, in a homely rapture of devotion and gratitude, that he well
+deserved.
+
+We brought the locker out, extinguished the candle, fastened the door
+on the outside, and left the old boat close shut up, a dark speck in
+the cloudy night. Next day, when we were returning to London outside the
+coach, Mrs. Gummidge and her basket were on the seat behind, and Mrs.
+Gummidge was happy.
+
+
+
+CHAPTER 52. I ASSIST AT AN EXPLOSION
+
+
+When the time Mr. Micawber had appointed so mysteriously, was within
+four-and-twenty hours of being come, my aunt and I consulted how we
+should proceed; for my aunt was very unwilling to leave Dora. Ah! how
+easily I carried Dora up and down stairs, now!
+
+We were disposed, notwithstanding Mr. Micawber's stipulation for my
+aunt's attendance, to arrange that she should stay at home, and be
+represented by Mr. Dick and me. In short, we had resolved to take this
+course, when Dora again unsettled us by declaring that she never
+would forgive herself, and never would forgive her bad boy, if my aunt
+remained behind, on any pretence.
+
+'I won't speak to you,' said Dora, shaking her curls at my aunt. 'I'll
+be disagreeable! I'll make Jip bark at you all day. I shall be sure that
+you really are a cross old thing, if you don't go!'
+
+'Tut, Blossom!' laughed my aunt. 'You know you can't do without me!'
+
+'Yes, I can,' said Dora. 'You are no use to me at all. You never run up
+and down stairs for me, all day long. You never sit and tell me stories
+about Doady, when his shoes were worn out, and he was covered with
+dust--oh, what a poor little mite of a fellow! You never do anything at
+all to please me, do you, dear?' Dora made haste to kiss my aunt, and
+say, 'Yes, you do! I'm only joking!'-lest my aunt should think she
+really meant it.
+
+'But, aunt,' said Dora, coaxingly, 'now listen. You must go. I shall
+tease you, 'till you let me have my own way about it. I shall lead my
+naughty boy such a life, if he don't make you go. I shall make myself
+so disagreeable--and so will Jip! You'll wish you had gone, like a good
+thing, for ever and ever so long, if you don't go. Besides,' said Dora,
+putting back her hair, and looking wonderingly at my aunt and me, 'why
+shouldn't you both go? I am not very ill indeed. Am I?'
+
+'Why, what a question!' cried my aunt.
+
+'What a fancy!' said I.
+
+'Yes! I know I am a silly little thing!' said Dora, slowly looking from
+one of us to the other, and then putting up her pretty lips to kiss us
+as she lay upon her couch. 'Well, then, you must both go, or I shall not
+believe you; and then I shall cry!'
+
+I saw, in my aunt's face, that she began to give way now, and Dora
+brightened again, as she saw it too.
+
+'You'll come back with so much to tell me, that it'll take at least
+a week to make me understand!' said Dora. 'Because I know I shan't
+understand, for a length of time, if there's any business in it. And
+there's sure to be some business in it! If there's anything to add up,
+besides, I don't know when I shall make it out; and my bad boy will look
+so miserable all the time. There! Now you'll go, won't you? You'll only
+be gone one night, and Jip will take care of me while you are gone.
+Doady will carry me upstairs before you go, and I won't come down again
+till you come back; and you shall take Agnes a dreadfully scolding
+letter from me, because she has never been to see us!'
+
+We agreed, without any more consultation, that we would both go, and
+that Dora was a little Impostor, who feigned to be rather unwell,
+because she liked to be petted. She was greatly pleased, and very merry;
+and we four, that is to say, my aunt, Mr. Dick, Traddles, and I, went
+down to Canterbury by the Dover mail that night.
+
+At the hotel where Mr. Micawber had requested us to await him, which
+we got into, with some trouble, in the middle of the night, I found a
+letter, importing that he would appear in the morning punctually at half
+past nine. After which, we went shivering, at that uncomfortable hour,
+to our respective beds, through various close passages; which smelt as
+if they had been steeped, for ages, in a solution of soup and stables.
+
+Early in the morning, I sauntered through the dear old tranquil streets,
+and again mingled with the shadows of the venerable gateways and
+churches. The rooks were sailing about the cathedral towers; and the
+towers themselves, overlooking many a long unaltered mile of the rich
+country and its pleasant streams, were cutting the bright morning air,
+as if there were no such thing as change on earth. Yet the bells, when
+they sounded, told me sorrowfully of change in everything; told me of
+their own age, and my pretty Dora's youth; and of the many, never old,
+who had lived and loved and died, while the reverberations of the bells
+had hummed through the rusty armour of the Black Prince hanging up
+within, and, motes upon the deep of Time, had lost themselves in air, as
+circles do in water.
+
+I looked at the old house from the corner of the street, but did not go
+nearer to it, lest, being observed, I might unwittingly do any harm to
+the design I had come to aid. The early sun was striking edgewise on its
+gables and lattice-windows, touching them with gold; and some beams of
+its old peace seemed to touch my heart.
+
+I strolled into the country for an hour or so, and then returned by
+the main street, which in the interval had shaken off its last night's
+sleep. Among those who were stirring in the shops, I saw my ancient
+enemy the butcher, now advanced to top-boots and a baby, and in business
+for himself. He was nursing the baby, and appeared to be a benignant
+member of society.
+
+We all became very anxious and impatient, when we sat down to breakfast.
+As it approached nearer and nearer to half past nine o'clock, our
+restless expectation of Mr. Micawber increased. At last we made no more
+pretence of attending to the meal, which, except with Mr. Dick, had been
+a mere form from the first; but my aunt walked up and down the room,
+Traddles sat upon the sofa affecting to read the paper with his eyes on
+the ceiling; and I looked out of the window to give early notice of Mr.
+Micawber's coming. Nor had I long to watch, for, at the first chime of
+the half hour, he appeared in the street.
+
+'Here he is,' said I, 'and not in his legal attire!'
+
+My aunt tied the strings of her bonnet (she had come down to breakfast
+in it), and put on her shawl, as if she were ready for anything that
+was resolute and uncompromising. Traddles buttoned his coat with a
+determined air. Mr. Dick, disturbed by these formidable appearances, but
+feeling it necessary to imitate them, pulled his hat, with both hands,
+as firmly over his ears as he possibly could; and instantly took it off
+again, to welcome Mr. Micawber.
+
+'Gentlemen, and madam,' said Mr. Micawber, 'good morning! My dear sir,'
+to Mr. Dick, who shook hands with him violently, 'you are extremely
+good.'
+
+'Have you breakfasted?' said Mr. Dick. 'Have a chop!'
+
+'Not for the world, my good sir!' cried Mr. Micawber, stopping him on
+his way to the bell; 'appetite and myself, Mr. Dixon, have long been
+strangers.'
+
+Mr. Dixon was so well pleased with his new name, and appeared to think
+it so obliging in Mr. Micawber to confer it upon him, that he shook
+hands with him again, and laughed rather childishly.
+
+'Dick,' said my aunt, 'attention!'
+
+Mr. Dick recovered himself, with a blush.
+
+'Now, sir,' said my aunt to Mr. Micawber, as she put on her gloves, 'we
+are ready for Mount Vesuvius, or anything else, as soon as YOU please.'
+
+'Madam,' returned Mr. Micawber, 'I trust you will shortly witness an
+eruption. Mr. Traddles, I have your permission, I believe, to mention
+here that we have been in communication together?'
+
+'It is undoubtedly the fact, Copperfield,' said Traddles, to whom I
+looked in surprise. 'Mr. Micawber has consulted me in reference to
+what he has in contemplation; and I have advised him to the best of my
+judgement.'
+
+'Unless I deceive myself, Mr. Traddles,' pursued Mr. Micawber, 'what I
+contemplate is a disclosure of an important nature.'
+
+'Highly so,' said Traddles.
+
+'Perhaps, under such circumstances, madam and gentlemen,' said Mr.
+Micawber, 'you will do me the favour to submit yourselves, for the
+moment, to the direction of one who, however unworthy to be regarded in
+any other light but as a Waif and Stray upon the shore of human nature,
+is still your fellow-man, though crushed out of his original form
+by individual errors, and the accumulative force of a combination of
+circumstances?'
+
+'We have perfect confidence in you, Mr. Micawber,' said I, 'and will do
+what you please.'
+
+'Mr. Copperfield,' returned Mr. Micawber, 'your confidence is not, at
+the existing juncture, ill-bestowed. I would beg to be allowed a start
+of five minutes by the clock; and then to receive the present company,
+inquiring for Miss Wickfield, at the office of Wickfield and Heep, whose
+Stipendiary I am.'
+
+My aunt and I looked at Traddles, who nodded his approval.
+
+'I have no more,' observed Mr. Micawber, 'to say at present.'
+
+With which, to my infinite surprise, he included us all in a
+comprehensive bow, and disappeared; his manner being extremely distant,
+and his face extremely pale.
+
+Traddles only smiled, and shook his head (with his hair standing upright
+on the top of it), when I looked to him for an explanation; so I took
+out my watch, and, as a last resource, counted off the five minutes. My
+aunt, with her own watch in her hand, did the like. When the time was
+expired, Traddles gave her his arm; and we all went out together to the
+old house, without saying one word on the way.
+
+We found Mr. Micawber at his desk, in the turret office on the
+ground floor, either writing, or pretending to write, hard. The large
+office-ruler was stuck into his waistcoat, and was not so well concealed
+but that a foot or more of that instrument protruded from his bosom,
+like a new kind of shirt-frill.
+
+As it appeared to me that I was expected to speak, I said aloud:
+
+'How do you do, Mr. Micawber?'
+
+'Mr. Copperfield,' said Mr. Micawber, gravely, 'I hope I see you well?'
+
+'Is Miss Wickfield at home?' said I.
+
+'Mr. Wickfield is unwell in bed, sir, of a rheumatic fever,' he
+returned; 'but Miss Wickfield, I have no doubt, will be happy to see old
+friends. Will you walk in, sir?'
+
+He preceded us to the dining-room--the first room I had entered in that
+house--and flinging open the door of Mr. Wickfield's former office,
+said, in a sonorous voice:
+
+'Miss Trotwood, Mr. David Copperfield, Mr. Thomas Traddles, and Mr.
+Dixon!'
+
+I had not seen Uriah Heep since the time of the blow. Our visit
+astonished him, evidently; not the less, I dare say, because it
+astonished ourselves. He did not gather his eyebrows together, for he
+had none worth mentioning; but he frowned to that degree that he almost
+closed his small eyes, while the hurried raising of his grisly hand to
+his chin betrayed some trepidation or surprise. This was only when we
+were in the act of entering his room, and when I caught a glance at him
+over my aunt's shoulder. A moment afterwards, he was as fawning and as
+humble as ever.
+
+'Well, I am sure,' he said. 'This is indeed an unexpected pleasure! To
+have, as I may say, all friends round St. Paul's at once, is a treat
+unlooked for! Mr. Copperfield, I hope I see you well, and--if I may
+umbly express myself so--friendly towards them as is ever your friends,
+whether or not. Mrs. Copperfield, sir, I hope she's getting on. We have
+been made quite uneasy by the poor accounts we have had of her state,
+lately, I do assure you.'
+
+I felt ashamed to let him take my hand, but I did not know yet what else
+to do.
+
+'Things are changed in this office, Miss Trotwood, since I was an umble
+clerk, and held your pony; ain't they?' said Uriah, with his sickliest
+smile. 'But I am not changed, Miss Trotwood.'
+
+'Well, sir,' returned my aunt, 'to tell you the truth, I think you are
+pretty constant to the promise of your youth; if that's any satisfaction
+to you.'
+
+'Thank you, Miss Trotwood,' said Uriah, writhing in his ungainly manner,
+'for your good opinion! Micawber, tell 'em to let Miss Agnes know--and
+mother. Mother will be quite in a state, when she sees the present
+company!' said Uriah, setting chairs.
+
+'You are not busy, Mr. Heep?' said Traddles, whose eye the cunning red
+eye accidentally caught, as it at once scrutinized and evaded us.
+
+'No, Mr. Traddles,' replied Uriah, resuming his official seat, and
+squeezing his bony hands, laid palm to palm between his bony knees. 'Not
+so much so as I could wish. But lawyers, sharks, and leeches, are not
+easily satisfied, you know! Not but what myself and Micawber have our
+hands pretty full, in general, on account of Mr. Wickfield's being
+hardly fit for any occupation, sir. But it's a pleasure as well as a
+duty, I am sure, to work for him. You've not been intimate with Mr.
+Wickfield, I think, Mr. Traddles? I believe I've only had the honour of
+seeing you once myself?'
+
+'No, I have not been intimate with Mr. Wickfield,' returned Traddles;
+'or I might perhaps have waited on you long ago, Mr. Heep.'
+
+There was something in the tone of this reply, which made Uriah look at
+the speaker again, with a very sinister and suspicious expression. But,
+seeing only Traddles, with his good-natured face, simple manner, and
+hair on end, he dismissed it as he replied, with a jerk of his whole
+body, but especially his throat:
+
+'I am sorry for that, Mr. Traddles. You would have admired him as much
+as we all do. His little failings would only have endeared him to you
+the more. But if you would like to hear my fellow-partner eloquently
+spoken of, I should refer you to Copperfield. The family is a subject
+he's very strong upon, if you never heard him.'
+
+I was prevented from disclaiming the compliment (if I should have
+done so, in any case), by the entrance of Agnes, now ushered in by Mr.
+Micawber. She was not quite so self-possessed as usual, I thought; and
+had evidently undergone anxiety and fatigue. But her earnest cordiality,
+and her quiet beauty, shone with the gentler lustre for it.
+
+I saw Uriah watch her while she greeted us; and he reminded me of an
+ugly and rebellious genie watching a good spirit. In the meanwhile,
+some slight sign passed between Mr. Micawber and Traddles; and Traddles,
+unobserved except by me, went out.
+
+'Don't wait, Micawber,' said Uriah.
+
+Mr. Micawber, with his hand upon the ruler in his breast, stood erect
+before the door, most unmistakably contemplating one of his fellow-men,
+and that man his employer.
+
+'What are you waiting for?' said Uriah. 'Micawber! did you hear me tell
+you not to wait?'
+
+'Yes!' replied the immovable Mr. Micawber.
+
+'Then why DO you wait?' said Uriah.
+
+'Because I--in short, choose,' replied Mr. Micawber, with a burst.
+
+Uriah's cheeks lost colour, and an unwholesome paleness, still faintly
+tinged by his pervading red, overspread them. He looked at Mr. Micawber
+attentively, with his whole face breathing short and quick in every
+feature.
+
+'You are a dissipated fellow, as all the world knows,' he said, with an
+effort at a smile, 'and I am afraid you'll oblige me to get rid of you.
+Go along! I'll talk to you presently.'
+
+'If there is a scoundrel on this earth,' said Mr. Micawber, suddenly
+breaking out again with the utmost vehemence, 'with whom I have already
+talked too much, that scoundrel's name is--HEEP!'
+
+Uriah fell back, as if he had been struck or stung. Looking slowly round
+upon us with the darkest and wickedest expression that his face could
+wear, he said, in a lower voice:
+
+'Oho! This is a conspiracy! You have met here by appointment! You are
+playing Booty with my clerk, are you, Copperfield? Now, take care.
+You'll make nothing of this. We understand each other, you and me.
+There's no love between us. You were always a puppy with a proud
+stomach, from your first coming here; and you envy me my rise, do you?
+None of your plots against me; I'll counterplot you! Micawber, you be
+off. I'll talk to you presently.'
+
+'Mr. Micawber,' said I, 'there is a sudden change in this fellow, in
+more respects than the extraordinary one of his speaking the truth in
+one particular, which assures me that he is brought to bay. Deal with
+him as he deserves!'
+
+'You are a precious set of people, ain't you?' said Uriah, in the same
+low voice, and breaking out into a clammy heat, which he wiped from his
+forehead, with his long lean hand, 'to buy over my clerk, who is the
+very scum of society,--as you yourself were, Copperfield, you know it,
+before anyone had charity on you,--to defame me with his lies? Miss
+Trotwood, you had better stop this; or I'll stop your husband shorter
+than will be pleasant to you. I won't know your story professionally,
+for nothing, old lady! Miss Wickfield, if you have any love for your
+father, you had better not join that gang. I'll ruin him, if you do.
+Now, come! I have got some of you under the harrow. Think twice, before
+it goes over you. Think twice, you, Micawber, if you don't want to
+be crushed. I recommend you to take yourself off, and be talked to
+presently, you fool! while there's time to retreat. Where's mother?' he
+said, suddenly appearing to notice, with alarm, the absence of Traddles,
+and pulling down the bell-rope. 'Fine doings in a person's own house!'
+
+'Mrs. Heep is here, sir,' said Traddles, returning with that worthy
+mother of a worthy son. 'I have taken the liberty of making myself known
+to her.'
+
+'Who are you to make yourself known?' retorted Uriah. 'And what do you
+want here?'
+
+'I am the agent and friend of Mr. Wickfield, sir,' said Traddles, in a
+composed and business-like way. 'And I have a power of attorney from him
+in my pocket, to act for him in all matters.'
+
+'The old ass has drunk himself into a state of dotage,' said Uriah,
+turning uglier than before, 'and it has been got from him by fraud!'
+
+'Something has been got from him by fraud, I know,' returned Traddles
+quietly; 'and so do you, Mr. Heep. We will refer that question, if you
+please, to Mr. Micawber.'
+
+'Ury--!' Mrs. Heep began, with an anxious gesture.
+
+'YOU hold your tongue, mother,' he returned; 'least said, soonest
+mended.'
+
+'But, my Ury--'
+
+'Will you hold your tongue, mother, and leave it to me?'
+
+Though I had long known that his servility was false, and all his
+pretences knavish and hollow, I had had no adequate conception of the
+extent of his hypocrisy, until I now saw him with his mask off. The
+suddenness with which he dropped it, when he perceived that it was
+useless to him; the malice, insolence, and hatred, he revealed; the leer
+with which he exulted, even at this moment, in the evil he had done--all
+this time being desperate too, and at his wits' end for the means
+of getting the better of us--though perfectly consistent with the
+experience I had of him, at first took even me by surprise, who had
+known him so long, and disliked him so heartily.
+
+I say nothing of the look he conferred on me, as he stood eyeing us,
+one after another; for I had always understood that he hated me, and I
+remembered the marks of my hand upon his cheek. But when his eyes passed
+on to Agnes, and I saw the rage with which he felt his power over her
+slipping away, and the exhibition, in their disappointment, of the
+odious passions that had led him to aspire to one whose virtues he could
+never appreciate or care for, I was shocked by the mere thought of her
+having lived, an hour, within sight of such a man.
+
+After some rubbing of the lower part of his face, and some looking at us
+with those bad eyes, over his grisly fingers, he made one more address
+to me, half whining, and half abusive.
+
+'You think it justifiable, do you, Copperfield, you who pride yourself
+so much on your honour and all the rest of it, to sneak about my place,
+eaves-dropping with my clerk? If it had been ME, I shouldn't have
+wondered; for I don't make myself out a gentleman (though I never was
+in the streets either, as you were, according to Micawber), but being
+you!--And you're not afraid of doing this, either? You don't think at
+all of what I shall do, in return; or of getting yourself into
+trouble for conspiracy and so forth? Very well. We shall see! Mr.
+What's-your-name, you were going to refer some question to Micawber.
+There's your referee. Why don't you make him speak? He has learnt his
+lesson, I see.'
+
+Seeing that what he said had no effect on me or any of us, he sat on the
+edge of his table with his hands in his pockets, and one of his splay
+feet twisted round the other leg, waiting doggedly for what might
+follow.
+
+Mr. Micawber, whose impetuosity I had restrained thus far with the
+greatest difficulty, and who had repeatedly interposed with the first
+syllable Of SCOUN-drel! without getting to the second, now burst
+forward, drew the ruler from his breast (apparently as a defensive
+weapon), and produced from his pocket a foolscap document, folded in the
+form of a large letter. Opening this packet, with his old flourish, and
+glancing at the contents, as if he cherished an artistic admiration of
+their style of composition, he began to read as follows:
+
+
+'"Dear Miss Trotwood and gentlemen--"'
+
+'Bless and save the man!' exclaimed my aunt in a low voice. 'He'd write
+letters by the ream, if it was a capital offence!'
+
+Mr. Micawber, without hearing her, went on.
+
+'"In appearing before you to denounce probably the most consummate
+Villain that has ever existed,"' Mr. Micawber, without looking off the
+letter, pointed the ruler, like a ghostly truncheon, at Uriah Heep,
+'"I ask no consideration for myself. The victim, from my cradle, of
+pecuniary liabilities to which I have been unable to respond, I have
+ever been the sport and toy of debasing circumstances. Ignominy,
+Want, Despair, and Madness, have, collectively or separately, been the
+attendants of my career."'
+
+The relish with which Mr. Micawber described himself as a prey to these
+dismal calamities, was only to be equalled by the emphasis with which he
+read his letter; and the kind of homage he rendered to it with a roll of
+his head, when he thought he had hit a sentence very hard indeed.
+
+'"In an accumulation of Ignominy, Want, Despair, and Madness, I entered
+the office--or, as our lively neighbour the Gaul would term it, the
+Bureau--of the Firm, nominally conducted under the appellation of
+Wickfield and--HEEP, but in reality, wielded by--HEEP alone. HEEP, and
+only HEEP, is the mainspring of that machine. HEEP, and only HEEP, is
+the Forger and the Cheat."'
+
+Uriah, more blue than white at these words, made a dart at the letter,
+as if to tear it in pieces. Mr. Micawber, with a perfect miracle of
+dexterity or luck, caught his advancing knuckles with the ruler, and
+disabled his right hand. It dropped at the wrist, as if it were broken.
+The blow sounded as if it had fallen on wood.
+
+'The Devil take you!' said Uriah, writhing in a new way with pain. 'I'll
+be even with you.'
+
+'Approach me again, you--you--you HEEP of infamy,' gasped Mr. Micawber,
+'and if your head is human, I'll break it. Come on, come on!'
+
+I think I never saw anything more ridiculous--I was sensible of it, even
+at the time--than Mr. Micawber making broad-sword guards with the ruler,
+and crying, 'Come on!' while Traddles and I pushed him back into a
+corner, from which, as often as we got him into it, he persisted in
+emerging again.
+
+His enemy, muttering to himself, after wringing his wounded hand for
+sometime, slowly drew off his neck-kerchief and bound it up; then
+held it in his other hand, and sat upon his table with his sullen face
+looking down.
+
+Mr. Micawber, when he was sufficiently cool, proceeded with his letter.
+
+'"The stipendiary emoluments in consideration of which I entered into
+the service of--HEEP,"' always pausing before that word and uttering
+it with astonishing vigour, '"were not defined, beyond the pittance of
+twenty-two shillings and six per week. The rest was left contingent on
+the value of my professional exertions; in other and more expressive
+words, on the baseness of my nature, the cupidity of my motives, the
+poverty of my family, the general moral (or rather immoral) resemblance
+between myself and--HEEP. Need I say, that it soon became necessary for
+me to solicit from--HEEP--pecuniary advances towards the support of
+Mrs. Micawber, and our blighted but rising family? Need I say that this
+necessity had been foreseen by--HEEP? That those advances were secured
+by I.O.U.'s and other similar acknowledgements, known to the legal
+institutions of this country? And that I thus became immeshed in the web
+he had spun for my reception?"'
+
+Mr. Micawber's enjoyment of his epistolary powers, in describing this
+unfortunate state of things, really seemed to outweigh any pain or
+anxiety that the reality could have caused him. He read on:
+
+'"Then it was that--HEEP--began to favour me with just so much of his
+confidence, as was necessary to the discharge of his infernal business.
+Then it was that I began, if I may so Shakespearianly express myself, to
+dwindle, peak, and pine. I found that my services were constantly
+called into requisition for the falsification of business, and the
+mystification of an individual whom I will designate as Mr. W. That Mr.
+W. was imposed upon, kept in ignorance, and deluded, in every possible
+way; yet, that all this while, the ruffian--HEEP--was professing
+unbounded gratitude to, and unbounded friendship for, that much-abused
+gentleman. This was bad enough; but, as the philosophic Dane observes,
+with that universal applicability which distinguishes the illustrious
+ornament of the Elizabethan Era, worse remains behind!"'
+
+Mr. Micawber was so very much struck by this happy rounding off with a
+quotation, that he indulged himself, and us, with a second reading of
+the sentence, under pretence of having lost his place.
+
+'"It is not my intention,"' he continued reading on, '"to enter on a
+detailed list, within the compass of the present epistle (though it
+is ready elsewhere), of the various malpractices of a minor nature,
+affecting the individual whom I have denominated Mr. W., to which I
+have been a tacitly consenting party. My object, when the contest within
+myself between stipend and no stipend, baker and no baker, existence
+and non-existence, ceased, was to take advantage of my opportunities
+to discover and expose the major malpractices committed, to that
+gentleman's grievous wrong and injury, by--HEEP. Stimulated by the
+silent monitor within, and by a no less touching and appealing monitor
+without--to whom I will briefly refer as Miss W.--I entered on a not
+unlaborious task of clandestine investigation, protracted--now, to the
+best of my knowledge, information, and belief, over a period exceeding
+twelve calendar months."'
+
+He read this passage as if it were from an Act of Parliament; and
+appeared majestically refreshed by the sound of the words.
+
+'"My charges against--HEEP,"' he read on, glancing at him, and drawing
+the ruler into a convenient position under his left arm, in case of
+need, '"are as follows."'
+
+We all held our breath, I think. I am sure Uriah held his.
+
+'"First,"' said Mr. Micawber, '"When Mr. W.'s faculties and memory
+for business became, through causes into which it is not necessary or
+expedient for me to enter, weakened and confused,--HEEP--designedly
+perplexed and complicated the whole of the official transactions. When
+Mr. W. was least fit to enter on business,--HEEP was always at hand
+to force him to enter on it. He obtained Mr. W.'s signature under such
+circumstances to documents of importance, representing them to be other
+documents of no importance. He induced Mr. W. to empower him to draw
+out, thus, one particular sum of trust-money, amounting to twelve six
+fourteen, two and nine, and employed it to meet pretended business
+charges and deficiencies which were either already provided for, or
+had never really existed. He gave this proceeding, throughout, the
+appearance of having originated in Mr. W.'s own dishonest intention, and
+of having been accomplished by Mr. W.'s own dishonest act; and has used
+it, ever since, to torture and constrain him."'
+
+'You shall prove this, you Copperfield!' said Uriah, with a threatening
+shake of the head. 'All in good time!'
+
+'Ask--HEEP--Mr. Traddles, who lived in his house after him,' said Mr.
+Micawber, breaking off from the letter; 'will you?'
+
+'The fool himself--and lives there now,' said Uriah, disdainfully.
+
+'Ask--HEEP--if he ever kept a pocket-book in that house,' said Mr.
+Micawber; 'will you?'
+
+I saw Uriah's lank hand stop, involuntarily, in the scraping of his
+chin.
+
+'Or ask him,' said Mr. Micawber,'if he ever burnt one there. If he says
+yes, and asks you where the ashes are, refer him to Wilkins Micawber,
+and he will hear of something not at all to his advantage!'
+
+The triumphant flourish with which Mr. Micawber delivered himself of
+these words, had a powerful effect in alarming the mother; who cried
+out, in much agitation:
+
+'Ury, Ury! Be umble, and make terms, my dear!'
+
+'Mother!' he retorted, 'will you keep quiet? You're in a fright, and
+don't know what you say or mean. Umble!' he repeated, looking at me,
+with a snarl; 'I've umbled some of 'em for a pretty long time back,
+umble as I was!'
+
+Mr. Micawber, genteelly adjusting his chin in his cravat, presently
+proceeded with his composition.
+
+'"Second. HEEP has, on several occasions, to the best of my knowledge,
+information, and belief--"'
+
+'But that won't do,' muttered Uriah, relieved. 'Mother, you keep quiet.'
+
+'We will endeavour to provide something that WILL do, and do for you
+finally, sir, very shortly,' replied Mr. Micawber.
+
+'"Second. HEEP has, on several occasions, to the best of my knowledge,
+information, and belief, systematically forged, to various entries,
+books, and documents, the signature of Mr. W.; and has distinctly done
+so in one instance, capable of proof by me. To wit, in manner following,
+that is to say:"'
+
+Again, Mr. Micawber had a relish in this formal piling up of words,
+which, however ludicrously displayed in his case, was, I must say, not
+at all peculiar to him. I have observed it, in the course of my life,
+in numbers of men. It seems to me to be a general rule. In the taking of
+legal oaths, for instance, deponents seem to enjoy themselves mightily
+when they come to several good words in succession, for the expression
+of one idea; as, that they utterly detest, abominate, and abjure, or so
+forth; and the old anathemas were made relishing on the same principle.
+We talk about the tyranny of words, but we like to tyrannize over them
+too; we are fond of having a large superfluous establishment of words to
+wait upon us on great occasions; we think it looks important, and sounds
+well. As we are not particular about the meaning of our liveries on
+state occasions, if they be but fine and numerous enough, so, the
+meaning or necessity of our words is a secondary consideration, if there
+be but a great parade of them. And as individuals get into trouble by
+making too great a show of liveries, or as slaves when they are too
+numerous rise against their masters, so I think I could mention a
+nation that has got into many great difficulties, and will get into many
+greater, from maintaining too large a retinue of words.
+
+Mr. Micawber read on, almost smacking his lips:
+
+'"To wit, in manner following, that is to say. Mr. W. being infirm, and
+it being within the bounds of probability that his decease might lead
+to some discoveries, and to the downfall of--HEEP'S--power over the W.
+family,--as I, Wilkins Micawber, the undersigned, assume--unless the
+filial affection of his daughter could be secretly influenced from
+allowing any investigation of the partnership affairs to be ever made,
+the said--HEEP--deemed it expedient to have a bond ready by him, as from
+Mr. W., for the before-mentioned sum of twelve six fourteen, two and
+nine, with interest, stated therein to have been advanced by--HEEP--to
+Mr. W. to save Mr. W. from dishonour; though really the sum was never
+advanced by him, and has long been replaced. The signatures to this
+instrument purporting to be executed by Mr. W. and attested by Wilkins
+Micawber, are forgeries by--HEEP. I have, in my possession, in his hand
+and pocket-book, several similar imitations of Mr. W.'s signature, here
+and there defaced by fire, but legible to anyone. I never attested any
+such document. And I have the document itself, in my possession."' Uriah
+Heep, with a start, took out of his pocket a bunch of keys, and opened
+a certain drawer; then, suddenly bethought himself of what he was about,
+and turned again towards us, without looking in it.
+
+'"And I have the document,"' Mr. Micawber read again, looking about as
+if it were the text of a sermon, '"in my possession,--that is to say,
+I had, early this morning, when this was written, but have since
+relinquished it to Mr. Traddles."'
+
+'It is quite true,' assented Traddles.
+
+'Ury, Ury!' cried the mother, 'be umble and make terms. I know my
+son will be umble, gentlemen, if you'll give him time to think. Mr.
+Copperfield, I'm sure you know that he was always very umble, sir!'
+
+It was singular to see how the mother still held to the old trick, when
+the son had abandoned it as useless.
+
+'Mother,' he said, with an impatient bite at the handkerchief in which
+his hand was wrapped, 'you had better take and fire a loaded gun at me.'
+
+'But I love you, Ury,' cried Mrs. Heep. And I have no doubt she did; or
+that he loved her, however strange it may appear; though, to be sure,
+they were a congenial couple. 'And I can't bear to hear you provoking
+the gentlemen, and endangering of yourself more. I told the gentleman
+at first, when he told me upstairs it was come to light, that I would
+answer for your being umble, and making amends. Oh, see how umble I am,
+gentlemen, and don't mind him!'
+
+'Why, there's Copperfield, mother,' he angrily retorted, pointing his
+lean finger at me, against whom all his animosity was levelled, as the
+prime mover in the discovery; and I did not undeceive him; 'there's
+Copperfield, would have given you a hundred pound to say less than
+you've blurted out!'
+
+'I can't help it, Ury,' cried his mother. 'I can't see you running into
+danger, through carrying your head so high. Better be umble, as you
+always was.'
+
+He remained for a little, biting the handkerchief, and then said to me
+with a scowl:
+
+'What more have you got to bring forward? If anything, go on with it.
+What do you look at me for?'
+
+Mr. Micawber promptly resumed his letter, glad to revert to a
+performance with which he was so highly satisfied.
+
+'"Third. And last. I am now in a condition to show, by--HEEP'S--false
+books, and--HEEP'S--real memoranda, beginning with the partially
+destroyed pocket-book (which I was unable to comprehend, at the time of
+its accidental discovery by Mrs. Micawber, on our taking possession of
+our present abode, in the locker or bin devoted to the reception of the
+ashes calcined on our domestic hearth), that the weaknesses, the faults,
+the very virtues, the parental affections, and the sense of honour, of
+the unhappy Mr. W. have been for years acted on by, and warped to the
+base purposes of--HEEP. That Mr. W. has been for years deluded and
+plundered, in every conceivable manner, to the pecuniary aggrandisement
+of the avaricious, false, and grasping--HEEP. That the engrossing object
+of--HEEP--was, next to gain, to subdue Mr. and Miss W. (of his ulterior
+views in reference to the latter I say nothing) entirely to himself.
+That his last act, completed but a few months since, was to induce Mr.
+W. to execute a relinquishment of his share in the partnership, and even
+a bill of sale on the very furniture of his house, in consideration of a
+certain annuity, to be well and truly paid by--HEEP--on the four common
+quarter-days in each and every year. That these meshes; beginning with
+alarming and falsified accounts of the estate of which Mr. W. is the
+receiver, at a period when Mr. W. had launched into imprudent and
+ill-judged speculations, and may not have had the money, for which he
+was morally and legally responsible, in hand; going on with pretended
+borrowings of money at enormous interest, really coming from--HEEP--and
+by--HEEP--fraudulently obtained or withheld from Mr. W. himself,
+on pretence of such speculations or otherwise; perpetuated by a
+miscellaneous catalogue of unscrupulous chicaneries--gradually
+thickened, until the unhappy Mr. W. could see no world beyond. Bankrupt,
+as he believed, alike in circumstances, in all other hope, and
+in honour, his sole reliance was upon the monster in the garb of
+man,"'--Mr. Micawber made a good deal of this, as a new turn of
+expression,--'"who, by making himself necessary to him, had achieved his
+destruction. All this I undertake to show. Probably much more!"'
+
+I whispered a few words to Agnes, who was weeping, half joyfully, half
+sorrowfully, at my side; and there was a movement among us, as if Mr.
+Micawber had finished. He said, with exceeding gravity, 'Pardon me,'
+and proceeded, with a mixture of the lowest spirits and the most intense
+enjoyment, to the peroration of his letter.
+
+'"I have now concluded. It merely remains for me to substantiate these
+accusations; and then, with my ill-starred family, to disappear from the
+landscape on which we appear to be an encumbrance. That is soon done. It
+may be reasonably inferred that our baby will first expire of inanition,
+as being the frailest member of our circle; and that our twins will
+follow next in order. So be it! For myself, my Canterbury Pilgrimage has
+done much; imprisonment on civil process, and want, will soon do more.
+I trust that the labour and hazard of an investigation--of which the
+smallest results have been slowly pieced together, in the pressure of
+arduous avocations, under grinding penurious apprehensions, at rise of
+morn, at dewy eve, in the shadows of night, under the watchful eye of
+one whom it were superfluous to call Demon--combined with the struggle
+of parental Poverty to turn it, when completed, to the right account,
+may be as the sprinkling of a few drops of sweet water on my funeral
+pyre. I ask no more. Let it be, in justice, merely said of me, as of a
+gallant and eminent naval Hero, with whom I have no pretensions to
+cope, that what I have done, I did, in despite of mercenary and selfish
+objects,
+
+     For England, home, and Beauty.
+
+     '"Remaining always, &c.  &c., WILKINS MICAWBER."'
+
+
+Much affected, but still intensely enjoying himself, Mr. Micawber folded
+up his letter, and handed it with a bow to my aunt, as something she
+might like to keep.
+
+There was, as I had noticed on my first visit long ago, an iron safe in
+the room. The key was in it. A hasty suspicion seemed to strike Uriah;
+and, with a glance at Mr. Micawber, he went to it, and threw the doors
+clanking open. It was empty.
+
+'Where are the books?' he cried, with a frightful face. 'Some thief has
+stolen the books!'
+
+Mr. Micawber tapped himself with the ruler. 'I did, when I got the key
+from you as usual--but a little earlier--and opened it this morning.'
+
+'Don't be uneasy,' said Traddles. 'They have come into my possession. I
+will take care of them, under the authority I mentioned.'
+
+'You receive stolen goods, do you?' cried Uriah.
+
+'Under such circumstances,' answered Traddles, 'yes.'
+
+What was my astonishment when I beheld my aunt, who had been profoundly
+quiet and attentive, make a dart at Uriah Heep, and seize him by the
+collar with both hands!
+
+'You know what I want?' said my aunt.
+
+'A strait-waistcoat,' said he.
+
+'No. My property!' returned my aunt. 'Agnes, my dear, as long as
+I believed it had been really made away with by your father, I
+wouldn't--and, my dear, I didn't, even to Trot, as he knows--breathe a
+syllable of its having been placed here for investment. But, now I know
+this fellow's answerable for it, and I'll have it! Trot, come and take
+it away from him!'
+
+Whether my aunt supposed, for the moment, that he kept her property in
+his neck-kerchief, I am sure I don't know; but she certainly pulled at
+it as if she thought so. I hastened to put myself between them, and to
+assure her that we would all take care that he should make the utmost
+restitution of everything he had wrongly got. This, and a few moments'
+reflection, pacified her; but she was not at all disconcerted by what
+she had done (though I cannot say as much for her bonnet) and resumed
+her seat composedly.
+
+During the last few minutes, Mrs. Heep had been clamouring to her son
+to be 'umble'; and had been going down on her knees to all of us in
+succession, and making the wildest promises. Her son sat her down in his
+chair; and, standing sulkily by her, holding her arm with his hand, but
+not rudely, said to me, with a ferocious look:
+
+'What do you want done?'
+
+'I will tell you what must be done,' said Traddles.
+
+'Has that Copperfield no tongue?' muttered Uriah, 'I would do a good
+deal for you if you could tell me, without lying, that somebody had cut
+it out.'
+
+'My Uriah means to be umble!' cried his mother. 'Don't mind what he
+says, good gentlemen!'
+
+'What must be done,' said Traddles, 'is this. First, the deed of
+relinquishment, that we have heard of, must be given over to me
+now--here.'
+
+'Suppose I haven't got it,' he interrupted.
+
+'But you have,' said Traddles; 'therefore, you know, we won't suppose
+so.' And I cannot help avowing that this was the first occasion on
+which I really did justice to the clear head, and the plain, patient,
+practical good sense, of my old schoolfellow. 'Then,' said Traddles,
+'you must prepare to disgorge all that your rapacity has become
+possessed of, and to make restoration to the last farthing. All the
+partnership books and papers must remain in our possession; all your
+books and papers; all money accounts and securities, of both kinds. In
+short, everything here.'
+
+'Must it? I don't know that,' said Uriah. 'I must have time to think
+about that.'
+
+'Certainly,' replied Traddles; 'but, in the meanwhile, and until
+everything is done to our satisfaction, we shall maintain possession
+of these things; and beg you--in short, compel you--to keep to your own
+room, and hold no communication with anyone.'
+
+'I won't do it!' said Uriah, with an oath.
+
+'Maidstone jail is a safer place of detention,' observed Traddles; 'and
+though the law may be longer in righting us, and may not be able to
+right us so completely as you can, there is no doubt of its punishing
+YOU. Dear me, you know that quite as well as I! Copperfield, will you go
+round to the Guildhall, and bring a couple of officers?'
+
+Here, Mrs. Heep broke out again, crying on her knees to Agnes to
+interfere in their behalf, exclaiming that he was very humble, and it
+was all true, and if he didn't do what we wanted, she would, and much
+more to the same purpose; being half frantic with fears for her darling.
+To inquire what he might have done, if he had had any boldness, would
+be like inquiring what a mongrel cur might do, if it had the spirit of
+a tiger. He was a coward, from head to foot; and showed his dastardly
+nature through his sullenness and mortification, as much as at any time
+of his mean life.
+
+'Stop!' he growled to me; and wiped his hot face with his hand. 'Mother,
+hold your noise. Well! Let 'em have that deed. Go and fetch it!'
+
+'Do you help her, Mr. Dick,' said Traddles, 'if you please.'
+
+Proud of his commission, and understanding it, Mr. Dick accompanied her
+as a shepherd's dog might accompany a sheep. But, Mrs. Heep gave him
+little trouble; for she not only returned with the deed, but with the
+box in which it was, where we found a banker's book and some other
+papers that were afterwards serviceable.
+
+'Good!' said Traddles, when this was brought. 'Now, Mr. Heep, you can
+retire to think: particularly observing, if you please, that I declare
+to you, on the part of all present, that there is only one thing to be
+done; that it is what I have explained; and that it must be done without
+delay.'
+
+Uriah, without lifting his eyes from the ground, shuffled across the
+room with his hand to his chin, and pausing at the door, said:
+
+'Copperfield, I have always hated you. You've always been an upstart,
+and you've always been against me.'
+
+'As I think I told you once before,' said I, 'it is you who have been,
+in your greed and cunning, against all the world. It may be profitable
+to you to reflect, in future, that there never were greed and cunning in
+the world yet, that did not do too much, and overreach themselves. It is
+as certain as death.'
+
+'Or as certain as they used to teach at school (the same school where I
+picked up so much umbleness), from nine o'clock to eleven, that labour
+was a curse; and from eleven o'clock to one, that it was a blessing and
+a cheerfulness, and a dignity, and I don't know what all, eh?' said
+he with a sneer. 'You preach, about as consistent as they did.
+Won't umbleness go down? I shouldn't have got round my gentleman
+fellow-partner without it, I think. --Micawber, you old bully, I'll pay
+YOU!'
+
+Mr. Micawber, supremely defiant of him and his extended finger, and
+making a great deal of his chest until he had slunk out at the door,
+then addressed himself to me, and proffered me the satisfaction of
+'witnessing the re-establishment of mutual confidence between himself
+and Mrs. Micawber'. After which, he invited the company generally to the
+contemplation of that affecting spectacle.
+
+'The veil that has long been interposed between Mrs. Micawber and
+myself, is now withdrawn,' said Mr. Micawber; 'and my children and the
+Author of their Being can once more come in contact on equal terms.'
+
+As we were all very grateful to him, and all desirous to show that we
+were, as well as the hurry and disorder of our spirits would permit, I
+dare say we should all have gone, but that it was necessary for Agnes to
+return to her father, as yet unable to bear more than the dawn of
+hope; and for someone else to hold Uriah in safe keeping. So, Traddles
+remained for the latter purpose, to be presently relieved by Mr. Dick;
+and Mr. Dick, my aunt, and I, went home with Mr. Micawber. As I parted
+hurriedly from the dear girl to whom I owed so much, and thought from
+what she had been saved, perhaps, that morning--her better resolution
+notwithstanding--I felt devoutly thankful for the miseries of my younger
+days which had brought me to the knowledge of Mr. Micawber.
+
+His house was not far off; and as the street door opened into the
+sitting-room, and he bolted in with a precipitation quite his own,
+we found ourselves at once in the bosom of the family. Mr. Micawber
+exclaiming, 'Emma! my life!' rushed into Mrs. Micawber's arms. Mrs.
+Micawber shrieked, and folded Mr. Micawber in her embrace. Miss
+Micawber, nursing the unconscious stranger of Mrs. Micawber's last
+letter to me, was sensibly affected. The stranger leaped. The twins
+testified their joy by several inconvenient but innocent demonstrations.
+Master Micawber, whose disposition appeared to have been soured by
+early disappointment, and whose aspect had become morose, yielded to his
+better feelings, and blubbered.
+
+'Emma!' said Mr. Micawber. 'The cloud is past from my mind. Mutual
+confidence, so long preserved between us once, is restored, to know
+no further interruption. Now, welcome poverty!' cried Mr. Micawber,
+shedding tears. 'Welcome misery, welcome houselessness, welcome hunger,
+rags, tempest, and beggary! Mutual confidence will sustain us to the
+end!'
+
+With these expressions, Mr. Micawber placed Mrs. Micawber in a chair,
+and embraced the family all round; welcoming a variety of bleak
+prospects, which appeared, to the best of my judgement, to be anything
+but welcome to them; and calling upon them to come out into Canterbury
+and sing a chorus, as nothing else was left for their support.
+
+But Mrs. Micawber having, in the strength of her emotions, fainted away,
+the first thing to be done, even before the chorus could be considered
+complete, was to recover her. This my aunt and Mr. Micawber did; and
+then my aunt was introduced, and Mrs. Micawber recognized me.
+
+'Excuse me, dear Mr. Copperfield,' said the poor lady, giving me her
+hand, 'but I am not strong; and the removal of the late misunderstanding
+between Mr. Micawber and myself was at first too much for me.'
+
+'Is this all your family, ma'am?' said my aunt.
+
+'There are no more at present,' returned Mrs. Micawber.
+
+'Good gracious, I didn't mean that, ma'am,' said my aunt. 'I mean, are
+all these yours?'
+
+'Madam,' replied Mr. Micawber, 'it is a true bill.'
+
+'And that eldest young gentleman, now,' said my aunt, musing, 'what has
+he been brought up to?'
+
+'It was my hope when I came here,' said Mr. Micawber, 'to have got
+Wilkins into the Church: or perhaps I shall express my meaning more
+strictly, if I say the Choir. But there was no vacancy for a tenor in
+the venerable Pile for which this city is so justly eminent; and he
+has--in short, he has contracted a habit of singing in public-houses,
+rather than in sacred edifices.'
+
+'But he means well,' said Mrs. Micawber, tenderly.
+
+'I dare say, my love,' rejoined Mr. Micawber, 'that he means
+particularly well; but I have not yet found that he carries out his
+meaning, in any given direction whatsoever.'
+
+Master Micawber's moroseness of aspect returned upon him again, and he
+demanded, with some temper, what he was to do? Whether he had been born
+a carpenter, or a coach-painter, any more than he had been born a bird?
+Whether he could go into the next street, and open a chemist's shop?
+Whether he could rush to the next assizes, and proclaim himself a
+lawyer? Whether he could come out by force at the opera, and succeed
+by violence? Whether he could do anything, without being brought up to
+something?
+
+My aunt mused a little while, and then said:
+
+'Mr. Micawber, I wonder you have never turned your thoughts to
+emigration.'
+
+'Madam,' returned Mr. Micawber, 'it was the dream of my youth, and the
+fallacious aspiration of my riper years.' I am thoroughly persuaded, by
+the by, that he had never thought of it in his life.
+
+'Aye?' said my aunt, with a glance at me. 'Why, what a thing it would
+be for yourselves and your family, Mr. and Mrs. Micawber, if you were to
+emigrate now.'
+
+'Capital, madam, capital,' urged Mr. Micawber, gloomily.
+
+'That is the principal, I may say the only difficulty, my dear Mr.
+Copperfield,' assented his wife.
+
+'Capital?' cried my aunt. 'But you are doing us a great service--have
+done us a great service, I may say, for surely much will come out of
+the fire--and what could we do for you, that would be half so good as to
+find the capital?'
+
+'I could not receive it as a gift,' said Mr. Micawber, full of fire and
+animation, 'but if a sufficient sum could be advanced, say at five per
+cent interest, per annum, upon my personal liability--say my notes of
+hand, at twelve, eighteen, and twenty-four months, respectively, to
+allow time for something to turn up--'
+
+'Could be? Can be and shall be, on your own terms,' returned my aunt,
+'if you say the word. Think of this now, both of you. Here are some
+people David knows, going out to Australia shortly. If you decide to go,
+why shouldn't you go in the same ship? You may help each other. Think of
+this now, Mr. and Mrs. Micawber. Take your time, and weigh it well.'
+
+'There is but one question, my dear ma'am, I could wish to ask,' said
+Mrs. Micawber. 'The climate, I believe, is healthy?'
+
+'Finest in the world!' said my aunt.
+
+'Just so,' returned Mrs. Micawber. 'Then my question arises. Now, are
+the circumstances of the country such, that a man of Mr. Micawber's
+abilities would have a fair chance of rising in the social scale? I will
+not say, at present, might he aspire to be Governor, or anything of that
+sort; but would there be a reasonable opening for his talents to
+develop themselves--that would be amply sufficient--and find their own
+expansion?'
+
+'No better opening anywhere,' said my aunt, 'for a man who conducts
+himself well, and is industrious.'
+
+'For a man who conducts himself well,' repeated Mrs. Micawber, with her
+clearest business manner, 'and is industrious. Precisely. It is
+evident to me that Australia is the legitimate sphere of action for Mr.
+Micawber!'
+
+'I entertain the conviction, my dear madam,' said Mr. Micawber, 'that
+it is, under existing circumstances, the land, the only land, for myself
+and family; and that something of an extraordinary nature will turn up
+on that shore. It is no distance--comparatively speaking; and though
+consideration is due to the kindness of your proposal, I assure you that
+is a mere matter of form.'
+
+Shall I ever forget how, in a moment, he was the most sanguine of men,
+looking on to fortune; or how Mrs. Micawber presently discoursed
+about the habits of the kangaroo! Shall I ever recall that street of
+Canterbury on a market-day, without recalling him, as he walked
+back with us; expressing, in the hardy roving manner he assumed, the
+unsettled habits of a temporary sojourner in the land; and looking at
+the bullocks, as they came by, with the eye of an Australian farmer!
+
+
+
+CHAPTER 53. ANOTHER RETROSPECT
+
+
+I must pause yet once again. O, my child-wife, there is a figure in the
+moving crowd before my memory, quiet and still, saying in its innocent
+love and childish beauty, Stop to think of me--turn to look upon the
+Little Blossom, as it flutters to the ground!
+
+I do. All else grows dim, and fades away. I am again with Dora, in our
+cottage. I do not know how long she has been ill. I am so used to it in
+feeling, that I cannot count the time. It is not really long, in weeks
+or months; but, in my usage and experience, it is a weary, weary while.
+
+They have left off telling me to 'wait a few days more'. I have begun
+to fear, remotely, that the day may never shine, when I shall see my
+child-wife running in the sunlight with her old friend Jip.
+
+He is, as it were suddenly, grown very old. It may be that he misses in
+his mistress, something that enlivened him and made him younger; but he
+mopes, and his sight is weak, and his limbs are feeble, and my aunt is
+sorry that he objects to her no more, but creeps near her as he lies on
+Dora's bed--she sitting at the bedside--and mildly licks her hand.
+
+Dora lies smiling on us, and is beautiful, and utters no hasty or
+complaining word. She says that we are very good to her; that her dear
+old careful boy is tiring himself out, she knows; that my aunt has no
+sleep, yet is always wakeful, active, and kind. Sometimes, the
+little bird-like ladies come to see her; and then we talk about our
+wedding-day, and all that happy time.
+
+What a strange rest and pause in my life there seems to be--and in all
+life, within doors and without--when I sit in the quiet, shaded, orderly
+room, with the blue eyes of my child-wife turned towards me, and her
+little fingers twining round my hand! Many and many an hour I sit thus;
+but, of all those times, three times come the freshest on my mind.
+
+
+It is morning; and Dora, made so trim by my aunt's hands, shows me how
+her pretty hair will curl upon the pillow yet, an how long and bright it
+is, and how she likes to have it loosely gathered in that net she wears.
+
+'Not that I am vain of it, now, you mocking boy,' she says, when I
+smile; 'but because you used to say you thought it so beautiful; and
+because, when I first began to think about you, I used to peep in the
+glass, and wonder whether you would like very much to have a lock of it.
+Oh what a foolish fellow you were, Doady, when I gave you one!'
+
+'That was on the day when you were painting the flowers I had given you,
+Dora, and when I told you how much in love I was.'
+
+'Ah! but I didn't like to tell you,' says Dora, 'then, how I had cried
+over them, because I believed you really liked me! When I can run about
+again as I used to do, Doady, let us go and see those places where we
+were such a silly couple, shall we? And take some of the old walks? And
+not forget poor papa?'
+
+'Yes, we will, and have some happy days. So you must make haste to get
+well, my dear.'
+
+'Oh, I shall soon do that! I am so much better, you don't know!'
+
+
+It is evening; and I sit in the same chair, by the same bed, with the
+same face turned towards me. We have been silent, and there is a smile
+upon her face. I have ceased to carry my light burden up and down stairs
+now. She lies here all the day.
+
+'Doady!'
+
+'My dear Dora!'
+
+'You won't think what I am going to say, unreasonable, after what you
+told me, such a little while ago, of Mr. Wickfield's not being well? I
+want to see Agnes. Very much I want to see her.'
+
+'I will write to her, my dear.'
+
+'Will you?'
+
+'Directly.'
+
+'What a good, kind boy! Doady, take me on your arm. Indeed, my dear,
+it's not a whim. It's not a foolish fancy. I want, very much indeed, to
+see her!'
+
+'I am certain of it. I have only to tell her so, and she is sure to
+come.'
+
+'You are very lonely when you go downstairs, now?' Dora whispers, with
+her arm about my neck.
+
+'How can I be otherwise, my own love, when I see your empty chair?'
+
+'My empty chair!' She clings to me for a little while, in silence. 'And
+you really miss me, Doady?' looking up, and brightly smiling. 'Even
+poor, giddy, stupid me?'
+
+'My heart, who is there upon earth that I could miss so much?'
+
+'Oh, husband! I am so glad, yet so sorry!' creeping closer to me, and
+folding me in both her arms. She laughs and sobs, and then is quiet, and
+quite happy.
+
+'Quite!' she says. 'Only give Agnes my dear love, and tell her that I
+want very, very, much to see her; and I have nothing left to wish for.'
+
+'Except to get well again, Dora.'
+
+'Ah, Doady! Sometimes I think--you know I always was a silly little
+thing!--that that will never be!'
+
+'Don't say so, Dora! Dearest love, don't think so!'
+
+'I won't, if I can help it, Doady. But I am very happy; though my dear
+boy is so lonely by himself, before his child-wife's empty chair!'
+
+
+It is night; and I am with her still. Agnes has arrived; has been among
+us for a whole day and an evening. She, my aunt, and I, have sat with
+Dora since the morning, all together. We have not talked much, but Dora
+has been perfectly contented and cheerful. We are now alone.
+
+Do I know, now, that my child-wife will soon leave me? They have told me
+so; they have told me nothing new to my thoughts--but I am far from
+sure that I have taken that truth to heart. I cannot master it. I have
+withdrawn by myself, many times today, to weep. I have remembered Who
+wept for a parting between the living and the dead. I have bethought me
+of all that gracious and compassionate history. I have tried to resign
+myself, and to console myself; and that, I hope, I may have done
+imperfectly; but what I cannot firmly settle in my mind is, that the end
+will absolutely come. I hold her hand in mine, I hold her heart in mine,
+I see her love for me, alive in all its strength. I cannot shut out a
+pale lingering shadow of belief that she will be spared.
+
+'I am going to speak to you, Doady. I am going to say something I have
+often thought of saying, lately. You won't mind?' with a gentle look.
+
+'Mind, my darling?'
+
+'Because I don't know what you will think, or what you may have thought
+sometimes. Perhaps you have often thought the same. Doady, dear, I am
+afraid I was too young.'
+
+I lay my face upon the pillow by her, and she looks into my eyes, and
+speaks very softly. Gradually, as she goes on, I feel, with a stricken
+heart, that she is speaking of herself as past.
+
+'I am afraid, dear, I was too young. I don't mean in years only, but
+in experience, and thoughts, and everything. I was such a silly little
+creature! I am afraid it would have been better, if we had only loved
+each other as a boy and girl, and forgotten it. I have begun to think I
+was not fit to be a wife.'
+
+I try to stay my tears, and to reply, 'Oh, Dora, love, as fit as I to be
+a husband!'
+
+'I don't know,' with the old shake of her curls. 'Perhaps! But if I had
+been more fit to be married I might have made you more so, too. Besides,
+you are very clever, and I never was.'
+
+'We have been very happy, my sweet Dora.'
+
+'I was very happy, very. But, as years went on, my dear boy would have
+wearied of his child-wife. She would have been less and less a companion
+for him. He would have been more and more sensible of what was wanting
+in his home. She wouldn't have improved. It is better as it is.'
+
+'Oh, Dora, dearest, dearest, do not speak to me so. Every word seems a
+reproach!'
+
+'No, not a syllable!' she answers, kissing me. 'Oh, my dear, you never
+deserved it, and I loved you far too well to say a reproachful word to
+you, in earnest--it was all the merit I had, except being pretty--or you
+thought me so. Is it lonely, down-stairs, Doady?'
+
+'Very! Very!'
+
+'Don't cry! Is my chair there?'
+
+'In its old place.'
+
+'Oh, how my poor boy cries! Hush, hush! Now, make me one promise. I want
+to speak to Agnes. When you go downstairs, tell Agnes so, and send her
+up to me; and while I speak to her, let no one come--not even aunt.
+I want to speak to Agnes by herself. I want to speak to Agnes, quite
+alone.'
+
+I promise that she shall, immediately; but I cannot leave her, for my
+grief.
+
+'I said that it was better as it is!' she whispers, as she holds me in
+her arms. 'Oh, Doady, after more years, you never could have loved your
+child-wife better than you do; and, after more years, she would so have
+tried and disappointed you, that you might not have been able to love
+her half so well! I know I was too young and foolish. It is much better
+as it is!'
+
+Agnes is downstairs, when I go into the parlour; and I give her the
+message. She disappears, leaving me alone with Jip.
+
+His Chinese house is by the fire; and he lies within it, on his bed of
+flannel, querulously trying to sleep. The bright moon is high and clear.
+As I look out on the night, my tears fall fast, and my undisciplined
+heart is chastened heavily--heavily.
+
+I sit down by the fire, thinking with a blind remorse of all those
+secret feelings I have nourished since my marriage. I think of every
+little trifle between me and Dora, and feel the truth, that trifles
+make the sum of life. Ever rising from the sea of my remembrance, is the
+image of the dear child as I knew her first, graced by my young love,
+and by her own, with every fascination wherein such love is rich. Would
+it, indeed, have been better if we had loved each other as a boy and a
+girl, and forgotten it? Undisciplined heart, reply!
+
+How the time wears, I know not; until I am recalled by my child-wife's
+old companion. More restless than he was, he crawls out of his house,
+and looks at me, and wanders to the door, and whines to go upstairs.
+
+'Not tonight, Jip! Not tonight!'
+
+He comes very slowly back to me, licks my hand, and lifts his dim eyes
+to my face.
+
+'Oh, Jip! It may be, never again!'
+
+He lies down at my feet, stretches himself out as if to sleep, and with
+a plaintive cry, is dead.
+
+'Oh, Agnes! Look, look, here!' --That face, so full of pity, and of
+grief, that rain of tears, that awful mute appeal to me, that solemn
+hand upraised towards Heaven!
+
+'Agnes?'
+
+It is over. Darkness comes before my eyes; and, for a time, all things
+are blotted out of my remembrance.
+
+
+
+CHAPTER 54. Mr. MICAWBER'S TRANSACTIONS
+
+
+This is not the time at which I am to enter on the state of my mind
+beneath its load of sorrow. I came to think that the Future was walled
+up before me, that the energy and action of my life were at an end, that
+I never could find any refuge but in the grave. I came to think so, I
+say, but not in the first shock of my grief. It slowly grew to that.
+If the events I go on to relate, had not thickened around me, in the
+beginning to confuse, and in the end to augment, my affliction, it is
+possible (though I think not probable), that I might have fallen at once
+into this condition. As it was, an interval occurred before I fully knew
+my own distress; an interval, in which I even supposed that its sharpest
+pangs were past; and when my mind could soothe itself by resting on
+all that was most innocent and beautiful, in the tender story that was
+closed for ever.
+
+When it was first proposed that I should go abroad, or how it came to be
+agreed among us that I was to seek the restoration of my peace in change
+and travel, I do not, even now, distinctly know. The spirit of Agnes so
+pervaded all we thought, and said, and did, in that time of sorrow, that
+I assume I may refer the project to her influence. But her influence was
+so quiet that I know no more.
+
+And now, indeed, I began to think that in my old association of her with
+the stained-glass window in the church, a prophetic foreshadowing of
+what she would be to me, in the calamity that was to happen in the
+fullness of time, had found a way into my mind. In all that sorrow, from
+the moment, never to be forgotten, when she stood before me with her
+upraised hand, she was like a sacred presence in my lonely house. When
+the Angel of Death alighted there, my child-wife fell asleep--they told
+me so when I could bear to hear it--on her bosom, with a smile. From my
+swoon, I first awoke to a consciousness of her compassionate tears, her
+words of hope and peace, her gentle face bending down as from a purer
+region nearer Heaven, over my undisciplined heart, and softening its
+pain.
+
+Let me go on.
+
+I was to go abroad. That seemed to have been determined among us from
+the first. The ground now covering all that could perish of my
+departed wife, I waited only for what Mr. Micawber called the 'final
+pulverization of Heep'; and for the departure of the emigrants.
+
+At the request of Traddles, most affectionate and devoted of friends in
+my trouble, we returned to Canterbury: I mean my aunt, Agnes, and I. We
+proceeded by appointment straight to Mr. Micawber's house; where, and at
+Mr. Wickfield's, my friend had been labouring ever since our explosive
+meeting. When poor Mrs. Micawber saw me come in, in my black clothes,
+she was sensibly affected. There was a great deal of good in Mrs.
+Micawber's heart, which had not been dunned out of it in all those many
+years.
+
+'Well, Mr. and Mrs. Micawber,' was my aunt's first salutation after we
+were seated. 'Pray, have you thought about that emigration proposal of
+mine?'
+
+'My dear madam,' returned Mr. Micawber, 'perhaps I cannot better express
+the conclusion at which Mrs. Micawber, your humble servant, and I may
+add our children, have jointly and severally arrived, than by borrowing
+the language of an illustrious poet, to reply that our Boat is on the
+shore, and our Bark is on the sea.'
+
+'That's right,' said my aunt. 'I augur all sort of good from your
+sensible decision.'
+
+'Madam, you do us a great deal of honour,' he rejoined. He then referred
+to a memorandum. 'With respect to the pecuniary assistance enabling
+us to launch our frail canoe on the ocean of enterprise, I have
+reconsidered that important business-point; and would beg to propose
+my notes of hand--drawn, it is needless to stipulate, on stamps of the
+amounts respectively required by the various Acts of Parliament applying
+to such securities--at eighteen, twenty-four, and thirty months.
+The proposition I originally submitted, was twelve, eighteen, and
+twenty-four; but I am apprehensive that such an arrangement might not
+allow sufficient time for the requisite amount of--Something--to turn
+up. We might not,' said Mr. Micawber, looking round the room as if it
+represented several hundred acres of highly cultivated land, 'on the
+first responsibility becoming due, have been successful in our harvest,
+or we might not have got our harvest in. Labour, I believe, is sometimes
+difficult to obtain in that portion of our colonial possessions where it
+will be our lot to combat with the teeming soil.'
+
+'Arrange it in any way you please, sir,' said my aunt.
+
+'Madam,' he replied, 'Mrs. Micawber and myself are deeply sensible of
+the very considerate kindness of our friends and patrons. What I wish
+is, to be perfectly business-like, and perfectly punctual. Turning over,
+as we are about to turn over, an entirely new leaf; and falling back,
+as we are now in the act of falling back, for a Spring of no common
+magnitude; it is important to my sense of self-respect, besides being
+an example to my son, that these arrangements should be concluded as
+between man and man.'
+
+I don't know that Mr. Micawber attached any meaning to this last phrase;
+I don't know that anybody ever does, or did; but he appeared to relish
+it uncommonly, and repeated, with an impressive cough, 'as between man
+and man'.
+
+'I propose,' said Mr. Micawber, 'Bills--a convenience to the mercantile
+world, for which, I believe, we are originally indebted to the Jews, who
+appear to me to have had a devilish deal too much to do with them
+ever since--because they are negotiable. But if a Bond, or any other
+description of security, would be preferred, I should be happy to
+execute any such instrument. As between man and man.'
+
+MY aunt observed, that in a case where both parties were willing to
+agree to anything, she took it for granted there would be no difficulty
+in settling this point. Mr. Micawber was of her opinion.
+
+'In reference to our domestic preparations, madam,' said Mr. Micawber,
+with some pride, 'for meeting the destiny to which we are now understood
+to be self-devoted, I beg to report them. My eldest daughter attends
+at five every morning in a neighbouring establishment, to acquire
+the process--if process it may be called--of milking cows. My younger
+children are instructed to observe, as closely as circumstances will
+permit, the habits of the pigs and poultry maintained in the poorer
+parts of this city: a pursuit from which they have, on two occasions,
+been brought home, within an inch of being run over. I have myself
+directed some attention, during the past week, to the art of baking; and
+my son Wilkins has issued forth with a walking-stick and driven cattle,
+when permitted, by the rugged hirelings who had them in charge, to
+render any voluntary service in that direction--which I regret to say,
+for the credit of our nature, was not often; he being generally warned,
+with imprecations, to desist.'
+
+'All very right indeed,' said my aunt, encouragingly. 'Mrs. Micawber has
+been busy, too, I have no doubt.'
+
+'My dear madam,' returned Mrs. Micawber, with her business-like air.
+'I am free to confess that I have not been actively engaged in pursuits
+immediately connected with cultivation or with stock, though well aware
+that both will claim my attention on a foreign shore. Such opportunities
+as I have been enabled to alienate from my domestic duties, I have
+devoted to corresponding at some length with my family. For I own it
+seems to me, my dear Mr. Copperfield,' said Mrs. Micawber, who always
+fell back on me, I suppose from old habit, to whomsoever else she might
+address her discourse at starting, 'that the time is come when the past
+should be buried in oblivion; when my family should take Mr. Micawber by
+the hand, and Mr. Micawber should take my family by the hand; when the
+lion should lie down with the lamb, and my family be on terms with Mr.
+Micawber.'
+
+I said I thought so too.
+
+'This, at least, is the light, my dear Mr. Copperfield,' pursued Mrs.
+Micawber, 'in which I view the subject. When I lived at home with my
+papa and mama, my papa was accustomed to ask, when any point was under
+discussion in our limited circle, "In what light does my Emma view the
+subject?" That my papa was too partial, I know; still, on such a point
+as the frigid coldness which has ever subsisted between Mr. Micawber and
+my family, I necessarily have formed an opinion, delusive though it may
+be.'
+
+'No doubt. Of course you have, ma'am,' said my aunt.
+
+'Precisely so,' assented Mrs. Micawber. 'Now, I may be wrong in my
+conclusions; it is very likely that I am, but my individual impression
+is, that the gulf between my family and Mr. Micawber may be traced to an
+apprehension, on the part of my family, that Mr. Micawber would require
+pecuniary accommodation. I cannot help thinking,' said Mrs. Micawber,
+with an air of deep sagacity, 'that there are members of my family who
+have been apprehensive that Mr. Micawber would solicit them for their
+names.---I do not mean to be conferred in Baptism upon our children,
+but to be inscribed on Bills of Exchange, and negotiated in the Money
+Market.'
+
+The look of penetration with which Mrs. Micawber announced this
+discovery, as if no one had ever thought of it before, seemed rather to
+astonish my aunt; who abruptly replied, 'Well, ma'am, upon the whole, I
+shouldn't wonder if you were right!'
+
+'Mr. Micawber being now on the eve of casting off the pecuniary
+shackles that have so long enthralled him,' said Mrs. Micawber, 'and of
+commencing a new career in a country where there is sufficient range
+for his abilities,--which, in my opinion, is exceedingly important; Mr.
+Micawber's abilities peculiarly requiring space,--it seems to me that
+my family should signalize the occasion by coming forward. What I could
+wish to see, would be a meeting between Mr. Micawber and my family at
+a festive entertainment, to be given at my family's expense; where Mr.
+Micawber's health and prosperity being proposed, by some leading member
+of my family, Mr. Micawber might have an opportunity of developing his
+views.'
+
+'My dear,' said Mr. Micawber, with some heat, 'it may be better for me
+to state distinctly, at once, that if I were to develop my views to that
+assembled group, they would possibly be found of an offensive nature:
+my impression being that your family are, in the aggregate, impertinent
+Snobs; and, in detail, unmitigated Ruffians.'
+
+'Micawber,' said Mrs. Micawber, shaking her head, 'no! You have never
+understood them, and they have never understood you.'
+
+Mr. Micawber coughed.
+
+'They have never understood you, Micawber,' said his wife. 'They may
+be incapable of it. If so, that is their misfortune. I can pity their
+misfortune.'
+
+'I am extremely sorry, my dear Emma,' said Mr. Micawber, relenting, 'to
+have been betrayed into any expressions that might, even remotely, have
+the appearance of being strong expressions. All I would say is, that
+I can go abroad without your family coming forward to favour me,--in
+short, with a parting Shove of their cold shoulders; and that, upon the
+whole, I would rather leave England with such impetus as I possess, than
+derive any acceleration of it from that quarter. At the same time, my
+dear, if they should condescend to reply to your communications--which
+our joint experience renders most improbable--far be it from me to be a
+barrier to your wishes.'
+
+The matter being thus amicably settled, Mr. Micawber gave Mrs. Micawber
+his arm, and glancing at the heap of books and papers lying before
+Traddles on the table, said they would leave us to ourselves; which they
+ceremoniously did.
+
+'My dear Copperfield,' said Traddles, leaning back in his chair when
+they were gone, and looking at me with an affection that made his eyes
+red, and his hair all kinds of shapes, 'I don't make any excuse for
+troubling you with business, because I know you are deeply interested
+in it, and it may divert your thoughts. My dear boy, I hope you are not
+worn out?'
+
+'I am quite myself,' said I, after a pause. 'We have more cause to think
+of my aunt than of anyone. You know how much she has done.'
+
+'Surely, surely,' answered Traddles. 'Who can forget it!'
+
+'But even that is not all,' said I. 'During the last fortnight, some new
+trouble has vexed her; and she has been in and out of London every day.
+Several times she has gone out early, and been absent until evening.
+Last night, Traddles, with this journey before her, it was almost
+midnight before she came home. You know what her consideration for
+others is. She will not tell me what has happened to distress her.'
+
+My aunt, very pale, and with deep lines in her face, sat immovable until
+I had finished; when some stray tears found their way to her cheeks, and
+she put her hand on mine.
+
+'It's nothing, Trot; it's nothing. There will be no more of it. You
+shall know by and by. Now Agnes, my dear, let us attend to these
+affairs.'
+
+'I must do Mr. Micawber the justice to say,' Traddles began, 'that
+although he would appear not to have worked to any good account for
+himself, he is a most untiring man when he works for other people. I
+never saw such a fellow. If he always goes on in the same way, he must
+be, virtually, about two hundred years old, at present. The heat into
+which he has been continually putting himself; and the distracted and
+impetuous manner in which he has been diving, day and night, among
+papers and books; to say nothing of the immense number of letters he has
+written me between this house and Mr. Wickfield's, and often across the
+table when he has been sitting opposite, and might much more easily have
+spoken; is quite extraordinary.'
+
+'Letters!' cried my aunt. 'I believe he dreams in letters!'
+
+'There's Mr. Dick, too,' said Traddles, 'has been doing wonders! As soon
+as he was released from overlooking Uriah Heep, whom he kept in such
+charge as I never saw exceeded, he began to devote himself to Mr.
+Wickfield. And really his anxiety to be of use in the investigations we
+have been making, and his real usefulness in extracting, and copying,
+and fetching, and carrying, have been quite stimulating to us.'
+
+'Dick is a very remarkable man,' exclaimed my aunt; 'and I always said
+he was. Trot, you know it.'
+
+'I am happy to say, Miss Wickfield,' pursued Traddles, at once with
+great delicacy and with great earnestness, 'that in your absence Mr.
+Wickfield has considerably improved. Relieved of the incubus that had
+fastened upon him for so long a time, and of the dreadful apprehensions
+under which he had lived, he is hardly the same person. At times,
+even his impaired power of concentrating his memory and attention on
+particular points of business, has recovered itself very much; and he
+has been able to assist us in making some things clear, that we should
+have found very difficult indeed, if not hopeless, without him. But
+what I have to do is to come to results; which are short enough; not
+to gossip on all the hopeful circumstances I have observed, or I shall
+never have done.' His natural manner and agreeable simplicity made it
+transparent that he said this to put us in good heart, and to enable
+Agnes to hear her father mentioned with greater confidence; but it was
+not the less pleasant for that.
+
+'Now, let me see,' said Traddles, looking among the papers on the
+table. 'Having counted our funds, and reduced to order a great mass of
+unintentional confusion in the first place, and of wilful confusion and
+falsification in the second, we take it to be clear that Mr. Wickfield
+might now wind up his business, and his agency-trust, and exhibit no
+deficiency or defalcation whatever.'
+
+'Oh, thank Heaven!' cried Agnes, fervently.
+
+'But,' said Traddles, 'the surplus that would be left as his means of
+support--and I suppose the house to be sold, even in saying this--would
+be so small, not exceeding in all probability some hundreds of pounds,
+that perhaps, Miss Wickfield, it would be best to consider whether he
+might not retain his agency of the estate to which he has so long been
+receiver. His friends might advise him, you know; now he is free. You
+yourself, Miss Wickfield--Copperfield--I--'
+
+'I have considered it, Trotwood,' said Agnes, looking to me, 'and I feel
+that it ought not to be, and must not be; even on the recommendation of
+a friend to whom I am so grateful, and owe so much.'
+
+'I will not say that I recommend it,' observed Traddles. 'I think it
+right to suggest it. No more.'
+
+'I am happy to hear you say so,' answered Agnes, steadily, 'for it gives
+me hope, almost assurance, that we think alike. Dear Mr. Traddles and
+dear Trotwood, papa once free with honour, what could I wish for! I have
+always aspired, if I could have released him from the toils in which he
+was held, to render back some little portion of the love and care I owe
+him, and to devote my life to him. It has been, for years, the utmost
+height of my hopes. To take our future on myself, will be the next
+great happiness--the next to his release from all trust and
+responsibility--that I can know.'
+
+'Have you thought how, Agnes?'
+
+'Often! I am not afraid, dear Trotwood. I am certain of success. So many
+people know me here, and think kindly of me, that I am certain. Don't
+mistrust me. Our wants are not many. If I rent the dear old house, and
+keep a school, I shall be useful and happy.'
+
+The calm fervour of her cheerful voice brought back so vividly, first
+the dear old house itself, and then my solitary home, that my heart was
+too full for speech. Traddles pretended for a little while to be busily
+looking among the papers.
+
+'Next, Miss Trotwood,' said Traddles, 'that property of yours.'
+
+'Well, sir,' sighed my aunt. 'All I have got to say about it is, that if
+it's gone, I can bear it; and if it's not gone, I shall be glad to get
+it back.'
+
+'It was originally, I think, eight thousand pounds, Consols?' said
+Traddles.
+
+'Right!' replied my aunt.
+
+'I can't account for more than five,' said Traddles, with an air of
+perplexity.
+
+'--thousand, do you mean?' inquired my aunt, with uncommon composure,
+'or pounds?'
+
+'Five thousand pounds,' said Traddles.
+
+'It was all there was,' returned my aunt. 'I sold three, myself. One, I
+paid for your articles, Trot, my dear; and the other two I have by me.
+When I lost the rest, I thought it wise to say nothing about that sum,
+but to keep it secretly for a rainy day. I wanted to see how you would
+come out of the trial, Trot; and you came out nobly--persevering,
+self-reliant, self-denying! So did Dick. Don't speak to me, for I find
+my nerves a little shaken!'
+
+Nobody would have thought so, to see her sitting upright, with her arms
+folded; but she had wonderful self-command.
+
+'Then I am delighted to say,' cried Traddles, beaming with joy, 'that we
+have recovered the whole money!'
+
+'Don't congratulate me, anybody!' exclaimed my aunt. 'How so, sir?'
+
+'You believed it had been misappropriated by Mr. Wickfield?' said
+Traddles.
+
+'Of course I did,' said my aunt, 'and was therefore easily silenced.
+Agnes, not a word!'
+
+'And indeed,' said Traddles, 'it was sold, by virtue of the power of
+management he held from you; but I needn't say by whom sold, or on whose
+actual signature. It was afterwards pretended to Mr. Wickfield, by that
+rascal,--and proved, too, by figures,--that he had possessed himself of
+the money (on general instructions, he said) to keep other deficiencies
+and difficulties from the light. Mr. Wickfield, being so weak and
+helpless in his hands as to pay you, afterwards, several sums of
+interest on a pretended principal which he knew did not exist, made
+himself, unhappily, a party to the fraud.'
+
+'And at last took the blame upon himself,' added my aunt; 'and wrote me
+a mad letter, charging himself with robbery, and wrong unheard of. Upon
+which I paid him a visit early one morning, called for a candle, burnt
+the letter, and told him if he ever could right me and himself, to
+do it; and if he couldn't, to keep his own counsel for his daughter's
+sake.---If anybody speaks to me, I'll leave the house!'
+
+We all remained quiet; Agnes covering her face.
+
+'Well, my dear friend,' said my aunt, after a pause, 'and you have
+really extorted the money back from him?'
+
+'Why, the fact is,' returned Traddles, 'Mr. Micawber had so completely
+hemmed him in, and was always ready with so many new points if an
+old one failed, that he could not escape from us. A most remarkable
+circumstance is, that I really don't think he grasped this sum even so
+much for the gratification of his avarice, which was inordinate, as in
+the hatred he felt for Copperfield. He said so to me, plainly. He said
+he would even have spent as much, to baulk or injure Copperfield.'
+
+'Ha!' said my aunt, knitting her brows thoughtfully, and glancing at
+Agnes. 'And what's become of him?'
+
+'I don't know. He left here,' said Traddles, 'with his mother, who had
+been clamouring, and beseeching, and disclosing, the whole time. They
+went away by one of the London night coaches, and I know no more about
+him; except that his malevolence to me at parting was audacious. He
+seemed to consider himself hardly less indebted to me, than to Mr.
+Micawber; which I consider (as I told him) quite a compliment.'
+
+'Do you suppose he has any money, Traddles?' I asked.
+
+'Oh dear, yes, I should think so,' he replied, shaking his head,
+seriously. 'I should say he must have pocketed a good deal, in one
+way or other. But, I think you would find, Copperfield, if you had an
+opportunity of observing his course, that money would never keep that
+man out of mischief. He is such an incarnate hypocrite, that whatever
+object he pursues, he must pursue crookedly. It's his only compensation
+for the outward restraints he puts upon himself. Always creeping along
+the ground to some small end or other, he will always magnify every
+object in the way; and consequently will hate and suspect everybody that
+comes, in the most innocent manner, between him and it. So the crooked
+courses will become crookeder, at any moment, for the least reason,
+or for none. It's only necessary to consider his history here,' said
+Traddles, 'to know that.'
+
+'He's a monster of meanness!' said my aunt.
+
+'Really I don't know about that,' observed Traddles thoughtfully. 'Many
+people can be very mean, when they give their minds to it.'
+
+'And now, touching Mr. Micawber,' said my aunt.
+
+'Well, really,' said Traddles, cheerfully, 'I must, once more, give Mr.
+Micawber high praise. But for his having been so patient and persevering
+for so long a time, we never could have hoped to do anything worth
+speaking of. And I think we ought to consider that Mr. Micawber did
+right, for right's sake, when we reflect what terms he might have made
+with Uriah Heep himself, for his silence.'
+
+'I think so too,' said I.
+
+'Now, what would you give him?' inquired my aunt.
+
+'Oh! Before you come to that,' said Traddles, a little disconcerted,
+'I am afraid I thought it discreet to omit (not being able to carry
+everything before me) two points, in making this lawless adjustment--for
+it's perfectly lawless from beginning to end--of a difficult affair.
+Those I.O.U.'s, and so forth, which Mr. Micawber gave him for the
+advances he had--'
+
+'Well! They must be paid,' said my aunt.
+
+'Yes, but I don't know when they may be proceeded on, or where they
+are,' rejoined Traddles, opening his eyes; 'and I anticipate, that,
+between this time and his departure, Mr. Micawber will be constantly
+arrested, or taken in execution.'
+
+'Then he must be constantly set free again, and taken out of execution,'
+said my aunt. 'What's the amount altogether?'
+
+'Why, Mr. Micawber has entered the transactions--he calls them
+transactions--with great form, in a book,' rejoined Traddles, smiling;
+'and he makes the amount a hundred and three pounds, five.'
+
+'Now, what shall we give him, that sum included?' said my aunt. 'Agnes,
+my dear, you and I can talk about division of it afterwards. What should
+it be? Five hundred pounds?'
+
+Upon this, Traddles and I both struck in at once. We both recommended
+a small sum in money, and the payment, without stipulation to Mr.
+Micawber, of the Uriah claims as they came in. We proposed that the
+family should have their passage and their outfit, and a hundred pounds;
+and that Mr. Micawber's arrangement for the repayment of the advances
+should be gravely entered into, as it might be wholesome for him
+to suppose himself under that responsibility. To this, I added the
+suggestion, that I should give some explanation of his character and
+history to Mr. Peggotty, who I knew could be relied on; and that to Mr.
+Peggotty should be quietly entrusted the discretion of advancing another
+hundred. I further proposed to interest Mr. Micawber in Mr. Peggotty,
+by confiding so much of Mr. Peggotty's story to him as I might feel
+justified in relating, or might think expedient; and to endeavour to
+bring each of them to bear upon the other, for the common advantage. We
+all entered warmly into these views; and I may mention at once, that the
+principals themselves did so, shortly afterwards, with perfect good will
+and harmony.
+
+Seeing that Traddles now glanced anxiously at my aunt again, I reminded
+him of the second and last point to which he had adverted.
+
+'You and your aunt will excuse me, Copperfield, if I touch upon a
+painful theme, as I greatly fear I shall,' said Traddles, hesitating;
+'but I think it necessary to bring it to your recollection. On the day
+of Mr. Micawber's memorable denunciation a threatening allusion was made
+by Uriah Heep to your aunt's--husband.'
+
+My aunt, retaining her stiff position, and apparent composure, assented
+with a nod.
+
+'Perhaps,' observed Traddles, 'it was mere purposeless impertinence?'
+
+'No,' returned my aunt.
+
+'There was--pardon me--really such a person, and at all in his power?'
+hinted Traddles.
+
+'Yes, my good friend,' said my aunt.
+
+Traddles, with a perceptible lengthening of his face, explained that he
+had not been able to approach this subject; that it had shared the fate
+of Mr. Micawber's liabilities, in not being comprehended in the terms he
+had made; that we were no longer of any authority with Uriah Heep; and
+that if he could do us, or any of us, any injury or annoyance, no doubt
+he would.
+
+My aunt remained quiet; until again some stray tears found their way to
+her cheeks. 'You are quite right,' she said. 'It was very thoughtful to
+mention it.'
+
+'Can I--or Copperfield--do anything?' asked Traddles, gently.
+
+'Nothing,' said my aunt. 'I thank you many times. Trot, my dear, a vain
+threat! Let us have Mr. and Mrs. Micawber back. And don't any of you
+speak to me!' With that she smoothed her dress, and sat, with her
+upright carriage, looking at the door.
+
+'Well, Mr. and Mrs. Micawber!' said my aunt, when they entered. 'We have
+been discussing your emigration, with many apologies to you for keeping
+you out of the room so long; and I'll tell you what arrangements we
+propose.'
+
+These she explained to the unbounded satisfaction of the
+family,--children and all being then present,--and so much to the
+awakening of Mr. Micawber's punctual habits in the opening stage of
+all bill transactions, that he could not be dissuaded from immediately
+rushing out, in the highest spirits, to buy the stamps for his notes of
+hand. But, his joy received a sudden check; for within five minutes,
+he returned in the custody of a sheriff 's officer, informing us, in
+a flood of tears, that all was lost. We, being quite prepared for this
+event, which was of course a proceeding of Uriah Heep's, soon paid the
+money; and in five minutes more Mr. Micawber was seated at the table,
+filling up the stamps with an expression of perfect joy, which only
+that congenial employment, or the making of punch, could impart in full
+completeness to his shining face. To see him at work on the stamps, with
+the relish of an artist, touching them like pictures, looking at them
+sideways, taking weighty notes of dates and amounts in his pocket-book,
+and contemplating them when finished, with a high sense of their
+precious value, was a sight indeed.
+
+'Now, the best thing you can do, sir, if you'll allow me to advise
+you,' said my aunt, after silently observing him, 'is to abjure that
+occupation for evermore.'
+
+'Madam,' replied Mr. Micawber, 'it is my intention to register such a
+vow on the virgin page of the future. Mrs. Micawber will attest it. I
+trust,' said Mr. Micawber, solemnly, 'that my son Wilkins will ever bear
+in mind, that he had infinitely better put his fist in the fire, than
+use it to handle the serpents that have poisoned the life-blood of his
+unhappy parent!' Deeply affected, and changed in a moment to the image
+of despair, Mr. Micawber regarded the serpents with a look of gloomy
+abhorrence (in which his late admiration of them was not quite subdued),
+folded them up and put them in his pocket.
+
+This closed the proceedings of the evening. We were weary with sorrow
+and fatigue, and my aunt and I were to return to London on the morrow.
+It was arranged that the Micawbers should follow us, after effecting a
+sale of their goods to a broker; that Mr. Wickfield's affairs should be
+brought to a settlement, with all convenient speed, under the direction
+of Traddles; and that Agnes should also come to London, pending those
+arrangements. We passed the night at the old house, which, freed from
+the presence of the Heeps, seemed purged of a disease; and I lay in my
+old room, like a shipwrecked wanderer come home.
+
+We went back next day to my aunt's house--not to mine--and when she and
+I sat alone, as of old, before going to bed, she said:
+
+'Trot, do you really wish to know what I have had upon my mind lately?'
+
+'Indeed I do, aunt. If there ever was a time when I felt unwilling that
+you should have a sorrow or anxiety which I could not share, it is now.'
+
+'You have had sorrow enough, child,' said my aunt, affectionately,
+'without the addition of my little miseries. I could have no other
+motive, Trot, in keeping anything from you.'
+
+'I know that well,' said I. 'But tell me now.'
+
+'Would you ride with me a little way tomorrow morning?' asked my aunt.
+
+'Of course.'
+
+'At nine,' said she. 'I'll tell you then, my dear.'
+
+At nine, accordingly, we went out in a little chariot, and drove to
+London. We drove a long way through the streets, until we came to one of
+the large hospitals. Standing hard by the building was a plain hearse.
+The driver recognized my aunt, and, in obedience to a motion of her hand
+at the window, drove slowly off; we following.
+
+'You understand it now, Trot,' said my aunt. 'He is gone!'
+
+'Did he die in the hospital?'
+
+'Yes.'
+
+She sat immovable beside me; but, again I saw the stray tears on her
+face.
+
+'He was there once before,' said my aunt presently. 'He was ailing a
+long time--a shattered, broken man, these many years. When he knew his
+state in this last illness, he asked them to send for me. He was sorry
+then. Very sorry.'
+
+'You went, I know, aunt.'
+
+'I went. I was with him a good deal afterwards.'
+
+'He died the night before we went to Canterbury?' said I. My aunt
+nodded. 'No one can harm him now,' she said. 'It was a vain threat.'
+
+We drove away, out of town, to the churchyard at Hornsey. 'Better here
+than in the streets,' said my aunt. 'He was born here.'
+
+We alighted; and followed the plain coffin to a corner I remember well,
+where the service was read consigning it to the dust.
+
+'Six-and-thirty years ago, this day, my dear,' said my aunt, as we
+walked back to the chariot, 'I was married. God forgive us all!' We took
+our seats in silence; and so she sat beside me for a long time, holding
+my hand. At length she suddenly burst into tears, and said:
+
+'He was a fine-looking man when I married him, Trot--and he was sadly
+changed!'
+
+It did not last long. After the relief of tears, she soon became
+composed, and even cheerful. Her nerves were a little shaken, she said,
+or she would not have given way to it. God forgive us all!
+
+So we rode back to her little cottage at Highgate, where we found the
+following short note, which had arrived by that morning's post from Mr.
+Micawber:
+
+
+          'Canterbury,
+
+               'Friday.
+
+'My dear Madam, and Copperfield,
+
+'The fair land of promise lately looming on the horizon is again
+enveloped in impenetrable mists, and for ever withdrawn from the eyes of
+a drifting wretch whose Doom is sealed!
+
+'Another writ has been issued (in His Majesty's High Court of King's
+Bench at Westminster), in another cause of HEEP V. MICAWBER, and
+the defendant in that cause is the prey of the sheriff having legal
+jurisdiction in this bailiwick.
+
+     'Now's the day, and now's the hour,
+     See the front of battle lower,
+     See approach proud EDWARD'S power--
+     Chains and slavery!
+
+'Consigned to which, and to a speedy end (for mental torture is not
+supportable beyond a certain point, and that point I feel I have
+attained), my course is run. Bless you, bless you! Some future
+traveller, visiting, from motives of curiosity, not unmingled, let us
+hope, with sympathy, the place of confinement allotted to debtors in
+this city, may, and I trust will, Ponder, as he traces on its wall,
+inscribed with a rusty nail,
+
+                              'The obscure initials,
+
+                                   'W. M.
+
+'P.S. I re-open this to say that our common friend, Mr. Thomas Traddles
+(who has not yet left us, and is looking extremely well), has paid the
+debt and costs, in the noble name of Miss Trotwood; and that myself and
+family are at the height of earthly bliss.'
+
+
+
+CHAPTER 55. TEMPEST
+
+
+I now approach an event in my life, so indelible, so awful, so bound by
+an infinite variety of ties to all that has preceded it, in these pages,
+that, from the beginning of my narrative, I have seen it growing larger
+and larger as I advanced, like a great tower in a plain, and throwing
+its fore-cast shadow even on the incidents of my childish days.
+
+For years after it occurred, I dreamed of it often. I have started up so
+vividly impressed by it, that its fury has yet seemed raging in my quiet
+room, in the still night. I dream of it sometimes, though at lengthened
+and uncertain intervals, to this hour. I have an association between it
+and a stormy wind, or the lightest mention of a sea-shore, as strong as
+any of which my mind is conscious. As plainly as I behold what happened,
+I will try to write it down. I do not recall it, but see it done; for it
+happens again before me.
+
+The time drawing on rapidly for the sailing of the emigrant-ship, my
+good old nurse (almost broken-hearted for me, when we first met) came up
+to London. I was constantly with her, and her brother, and the Micawbers
+(they being very much together); but Emily I never saw.
+
+One evening when the time was close at hand, I was alone with Peggotty
+and her brother. Our conversation turned on Ham. She described to us how
+tenderly he had taken leave of her, and how manfully and quietly he
+had borne himself. Most of all, of late, when she believed he was most
+tried. It was a subject of which the affectionate creature never tired;
+and our interest in hearing the many examples which she, who was so much
+with him, had to relate, was equal to hers in relating them.
+
+MY aunt and I were at that time vacating the two cottages at Highgate; I
+intending to go abroad, and she to return to her house at Dover. We had
+a temporary lodging in Covent Garden. As I walked home to it, after this
+evening's conversation, reflecting on what had passed between Ham and
+myself when I was last at Yarmouth, I wavered in the original purpose
+I had formed, of leaving a letter for Emily when I should take leave of
+her uncle on board the ship, and thought it would be better to write to
+her now. She might desire, I thought, after receiving my communication,
+to send some parting word by me to her unhappy lover. I ought to give
+her the opportunity.
+
+I therefore sat down in my room, before going to bed, and wrote to her.
+I told her that I had seen him, and that he had requested me to tell her
+what I have already written in its place in these sheets. I faithfully
+repeated it. I had no need to enlarge upon it, if I had had the right.
+Its deep fidelity and goodness were not to be adorned by me or any
+man. I left it out, to be sent round in the morning; with a line to Mr.
+Peggotty, requesting him to give it to her; and went to bed at daybreak.
+
+I was weaker than I knew then; and, not falling asleep until the sun
+was up, lay late, and unrefreshed, next day. I was roused by the silent
+presence of my aunt at my bedside. I felt it in my sleep, as I suppose
+we all do feel such things.
+
+'Trot, my dear,' she said, when I opened my eyes, 'I couldn't make up my
+mind to disturb you. Mr. Peggotty is here; shall he come up?'
+
+I replied yes, and he soon appeared.
+
+'Mas'r Davy,' he said, when we had shaken hands, 'I giv Em'ly your
+letter, sir, and she writ this heer; and begged of me fur to ask you
+to read it, and if you see no hurt in't, to be so kind as take charge
+on't.'
+
+'Have you read it?' said I.
+
+He nodded sorrowfully. I opened it, and read as follows:
+
+
+'I have got your message. Oh, what can I write, to thank you for your
+good and blessed kindness to me!
+
+'I have put the words close to my heart. I shall keep them till I die.
+They are sharp thorns, but they are such comfort. I have prayed over
+them, oh, I have prayed so much. When I find what you are, and what
+uncle is, I think what God must be, and can cry to him.
+
+'Good-bye for ever. Now, my dear, my friend, good-bye for ever in this
+world. In another world, if I am forgiven, I may wake a child and come
+to you. All thanks and blessings. Farewell, evermore.'
+
+
+This, blotted with tears, was the letter.
+
+'May I tell her as you doen't see no hurt in't, and as you'll be so kind
+as take charge on't, Mas'r Davy?' said Mr. Peggotty, when I had read it.
+'Unquestionably,' said I--'but I am thinking--'
+
+'Yes, Mas'r Davy?'
+
+'I am thinking,' said I, 'that I'll go down again to Yarmouth. There's
+time, and to spare, for me to go and come back before the ship sails. My
+mind is constantly running on him, in his solitude; to put this letter
+of her writing in his hand at this time, and to enable you to tell her,
+in the moment of parting, that he has got it, will be a kindness to
+both of them. I solemnly accepted his commission, dear good fellow, and
+cannot discharge it too completely. The journey is nothing to me. I am
+restless, and shall be better in motion. I'll go down tonight.'
+
+Though he anxiously endeavoured to dissuade me, I saw that he was of my
+mind; and this, if I had required to be confirmed in my intention, would
+have had the effect. He went round to the coach office, at my request,
+and took the box-seat for me on the mail. In the evening I started,
+by that conveyance, down the road I had traversed under so many
+vicissitudes.
+
+'Don't you think that,' I asked the coachman, in the first stage out of
+London, 'a very remarkable sky? I don't remember to have seen one like
+it.'
+
+'Nor I--not equal to it,' he replied. 'That's wind, sir. There'll be
+mischief done at sea, I expect, before long.'
+
+It was a murky confusion--here and there blotted with a colour like the
+colour of the smoke from damp fuel--of flying clouds, tossed up into
+most remarkable heaps, suggesting greater heights in the clouds than
+there were depths below them to the bottom of the deepest hollows in the
+earth, through which the wild moon seemed to plunge headlong, as if, in
+a dread disturbance of the laws of nature, she had lost her way and were
+frightened. There had been a wind all day; and it was rising then, with
+an extraordinary great sound. In another hour it had much increased, and
+the sky was more overcast, and blew hard.
+
+But, as the night advanced, the clouds closing in and densely
+over-spreading the whole sky, then very dark, it came on to blow, harder
+and harder. It still increased, until our horses could scarcely face
+the wind. Many times, in the dark part of the night (it was then late in
+September, when the nights were not short), the leaders turned about, or
+came to a dead stop; and we were often in serious apprehension that the
+coach would be blown over. Sweeping gusts of rain came up before this
+storm, like showers of steel; and, at those times, when there was any
+shelter of trees or lee walls to be got, we were fain to stop, in a
+sheer impossibility of continuing the struggle.
+
+When the day broke, it blew harder and harder. I had been in Yarmouth
+when the seamen said it blew great guns, but I had never known the like
+of this, or anything approaching to it. We came to Ipswich--very late,
+having had to fight every inch of ground since we were ten miles out of
+London; and found a cluster of people in the market-place, who had
+risen from their beds in the night, fearful of falling chimneys. Some of
+these, congregating about the inn-yard while we changed horses, told us
+of great sheets of lead having been ripped off a high church-tower, and
+flung into a by-street, which they then blocked up. Others had to tell
+of country people, coming in from neighbouring villages, who had seen
+great trees lying torn out of the earth, and whole ricks scattered about
+the roads and fields. Still, there was no abatement in the storm, but it
+blew harder.
+
+As we struggled on, nearer and nearer to the sea, from which this mighty
+wind was blowing dead on shore, its force became more and more terrific.
+Long before we saw the sea, its spray was on our lips, and showered
+salt rain upon us. The water was out, over miles and miles of the flat
+country adjacent to Yarmouth; and every sheet and puddle lashed its
+banks, and had its stress of little breakers setting heavily towards us.
+When we came within sight of the sea, the waves on the horizon, caught
+at intervals above the rolling abyss, were like glimpses of another
+shore with towers and buildings. When at last we got into the town, the
+people came out to their doors, all aslant, and with streaming hair,
+making a wonder of the mail that had come through such a night.
+
+I put up at the old inn, and went down to look at the sea; staggering
+along the street, which was strewn with sand and seaweed, and with
+flying blotches of sea-foam; afraid of falling slates and tiles; and
+holding by people I met, at angry corners. Coming near the beach, I saw,
+not only the boatmen, but half the people of the town, lurking behind
+buildings; some, now and then braving the fury of the storm to look
+away to sea, and blown sheer out of their course in trying to get zigzag
+back.
+
+Joining these groups, I found bewailing women whose husbands were away
+in herring or oyster boats, which there was too much reason to think
+might have foundered before they could run in anywhere for safety.
+Grizzled old sailors were among the people, shaking their heads, as they
+looked from water to sky, and muttering to one another; ship-owners,
+excited and uneasy; children, huddling together, and peering into older
+faces; even stout mariners, disturbed and anxious, levelling their
+glasses at the sea from behind places of shelter, as if they were
+surveying an enemy.
+
+The tremendous sea itself, when I could find sufficient pause to look at
+it, in the agitation of the blinding wind, the flying stones and sand,
+and the awful noise, confounded me. As the high watery walls came
+rolling in, and, at their highest, tumbled into surf, they looked as if
+the least would engulf the town. As the receding wave swept back with a
+hoarse roar, it seemed to scoop out deep caves in the beach, as if its
+purpose were to undermine the earth. When some white-headed billows
+thundered on, and dashed themselves to pieces before they reached the
+land, every fragment of the late whole seemed possessed by the full
+might of its wrath, rushing to be gathered to the composition of another
+monster. Undulating hills were changed to valleys, undulating valleys
+(with a solitary storm-bird sometimes skimming through them) were lifted
+up to hills; masses of water shivered and shook the beach with a booming
+sound; every shape tumultuously rolled on, as soon as made, to change
+its shape and place, and beat another shape and place away; the ideal
+shore on the horizon, with its towers and buildings, rose and fell; the
+clouds fell fast and thick; I seemed to see a rending and upheaving of
+all nature.
+
+Not finding Ham among the people whom this memorable wind--for it is
+still remembered down there, as the greatest ever known to blow upon
+that coast--had brought together, I made my way to his house. It was
+shut; and as no one answered to my knocking, I went, by back ways and
+by-lanes, to the yard where he worked. I learned, there, that he had
+gone to Lowestoft, to meet some sudden exigency of ship-repairing
+in which his skill was required; but that he would be back tomorrow
+morning, in good time.
+
+I went back to the inn; and when I had washed and dressed, and tried to
+sleep, but in vain, it was five o'clock in the afternoon. I had not sat
+five minutes by the coffee-room fire, when the waiter, coming to stir
+it, as an excuse for talking, told me that two colliers had gone down,
+with all hands, a few miles away; and that some other ships had been
+seen labouring hard in the Roads, and trying, in great distress, to keep
+off shore. Mercy on them, and on all poor sailors, said he, if we had
+another night like the last!
+
+I was very much depressed in spirits; very solitary; and felt an
+uneasiness in Ham's not being there, disproportionate to the occasion. I
+was seriously affected, without knowing how much, by late events; and my
+long exposure to the fierce wind had confused me. There was that jumble
+in my thoughts and recollections, that I had lost the clear arrangement
+of time and distance. Thus, if I had gone out into the town, I should
+not have been surprised, I think, to encounter someone who I knew must
+be then in London. So to speak, there was in these respects a curious
+inattention in my mind. Yet it was busy, too, with all the remembrances
+the place naturally awakened; and they were particularly distinct and
+vivid.
+
+In this state, the waiter's dismal intelligence about the ships
+immediately connected itself, without any effort of my volition, with my
+uneasiness about Ham. I was persuaded that I had an apprehension of his
+returning from Lowestoft by sea, and being lost. This grew so strong
+with me, that I resolved to go back to the yard before I took my dinner,
+and ask the boat-builder if he thought his attempting to return by sea
+at all likely? If he gave me the least reason to think so, I would go
+over to Lowestoft and prevent it by bringing him with me.
+
+I hastily ordered my dinner, and went back to the yard. I was none too
+soon; for the boat-builder, with a lantern in his hand, was locking
+the yard-gate. He quite laughed when I asked him the question, and said
+there was no fear; no man in his senses, or out of them, would put off
+in such a gale of wind, least of all Ham Peggotty, who had been born to
+seafaring.
+
+So sensible of this, beforehand, that I had really felt ashamed of doing
+what I was nevertheless impelled to do, I went back to the inn. If
+such a wind could rise, I think it was rising. The howl and roar, the
+rattling of the doors and windows, the rumbling in the chimneys, the
+apparent rocking of the very house that sheltered me, and the prodigious
+tumult of the sea, were more fearful than in the morning. But there
+was now a great darkness besides; and that invested the storm with new
+terrors, real and fanciful.
+
+I could not eat, I could not sit still, I could not continue steadfast
+to anything. Something within me, faintly answering to the storm
+without, tossed up the depths of my memory and made a tumult in them.
+Yet, in all the hurry of my thoughts, wild running with the thundering
+sea,--the storm, and my uneasiness regarding Ham were always in the
+fore-ground.
+
+My dinner went away almost untasted, and I tried to refresh myself with
+a glass or two of wine. In vain. I fell into a dull slumber before
+the fire, without losing my consciousness, either of the uproar out of
+doors, or of the place in which I was. Both became overshadowed by a new
+and indefinable horror; and when I awoke--or rather when I shook off
+the lethargy that bound me in my chair--my whole frame thrilled with
+objectless and unintelligible fear.
+
+I walked to and fro, tried to read an old gazetteer, listened to the
+awful noises: looked at faces, scenes, and figures in the fire.
+At length, the steady ticking of the undisturbed clock on the wall
+tormented me to that degree that I resolved to go to bed.
+
+It was reassuring, on such a night, to be told that some of the
+inn-servants had agreed together to sit up until morning. I went to bed,
+exceedingly weary and heavy; but, on my lying down, all such sensations
+vanished, as if by magic, and I was broad awake, with every sense
+refined.
+
+For hours I lay there, listening to the wind and water; imagining, now,
+that I heard shrieks out at sea; now, that I distinctly heard the firing
+of signal guns; and now, the fall of houses in the town. I got up,
+several times, and looked out; but could see nothing, except the
+reflection in the window-panes of the faint candle I had left burning,
+and of my own haggard face looking in at me from the black void.
+
+At length, my restlessness attained to such a pitch, that I hurried on
+my clothes, and went downstairs. In the large kitchen, where I dimly
+saw bacon and ropes of onions hanging from the beams, the watchers were
+clustered together, in various attitudes, about a table, purposely moved
+away from the great chimney, and brought near the door. A pretty girl,
+who had her ears stopped with her apron, and her eyes upon the door,
+screamed when I appeared, supposing me to be a spirit; but the others
+had more presence of mind, and were glad of an addition to their
+company. One man, referring to the topic they had been discussing, asked
+me whether I thought the souls of the collier-crews who had gone down,
+were out in the storm?
+
+I remained there, I dare say, two hours. Once, I opened the yard-gate,
+and looked into the empty street. The sand, the sea-weed, and the flakes
+of foam, were driving by; and I was obliged to call for assistance
+before I could shut the gate again, and make it fast against the wind.
+
+There was a dark gloom in my solitary chamber, when I at length returned
+to it; but I was tired now, and, getting into bed again, fell--off
+a tower and down a precipice--into the depths of sleep. I have an
+impression that for a long time, though I dreamed of being elsewhere and
+in a variety of scenes, it was always blowing in my dream. At length,
+I lost that feeble hold upon reality, and was engaged with two dear
+friends, but who they were I don't know, at the siege of some town in a
+roar of cannonading.
+
+The thunder of the cannon was so loud and incessant, that I could not
+hear something I much desired to hear, until I made a great exertion
+and awoke. It was broad day--eight or nine o'clock; the storm raging, in
+lieu of the batteries; and someone knocking and calling at my door.
+
+'What is the matter?' I cried.
+
+'A wreck! Close by!'
+
+I sprung out of bed, and asked, what wreck?
+
+'A schooner, from Spain or Portugal, laden with fruit and wine. Make
+haste, sir, if you want to see her! It's thought, down on the beach,
+she'll go to pieces every moment.'
+
+The excited voice went clamouring along the staircase; and I wrapped
+myself in my clothes as quickly as I could, and ran into the street.
+
+Numbers of people were there before me, all running in one direction, to
+the beach. I ran the same way, outstripping a good many, and soon came
+facing the wild sea.
+
+The wind might by this time have lulled a little, though not more
+sensibly than if the cannonading I had dreamed of, had been diminished
+by the silencing of half-a-dozen guns out of hundreds. But the sea,
+having upon it the additional agitation of the whole night, was
+infinitely more terrific than when I had seen it last. Every appearance
+it had then presented, bore the expression of being swelled; and the
+height to which the breakers rose, and, looking over one another,
+bore one another down, and rolled in, in interminable hosts, was most
+appalling. In the difficulty of hearing anything but wind and waves,
+and in the crowd, and the unspeakable confusion, and my first breathless
+efforts to stand against the weather, I was so confused that I looked
+out to sea for the wreck, and saw nothing but the foaming heads of the
+great waves. A half-dressed boatman, standing next me, pointed with his
+bare arm (a tattoo'd arrow on it, pointing in the same direction) to the
+left. Then, O great Heaven, I saw it, close in upon us!
+
+One mast was broken short off, six or eight feet from the deck, and lay
+over the side, entangled in a maze of sail and rigging; and all that
+ruin, as the ship rolled and beat--which she did without a moment's
+pause, and with a violence quite inconceivable--beat the side as if it
+would stave it in. Some efforts were even then being made, to cut this
+portion of the wreck away; for, as the ship, which was broadside on,
+turned towards us in her rolling, I plainly descried her people at
+work with axes, especially one active figure with long curling hair,
+conspicuous among the rest. But a great cry, which was audible even
+above the wind and water, rose from the shore at this moment; the sea,
+sweeping over the rolling wreck, made a clean breach, and carried men,
+spars, casks, planks, bulwarks, heaps of such toys, into the boiling
+surge.
+
+The second mast was yet standing, with the rags of a rent sail, and
+a wild confusion of broken cordage flapping to and fro. The ship had
+struck once, the same boatman hoarsely said in my ear, and then lifted
+in and struck again. I understood him to add that she was parting
+amidships, and I could readily suppose so, for the rolling and beating
+were too tremendous for any human work to suffer long. As he spoke,
+there was another great cry of pity from the beach; four men arose with
+the wreck out of the deep, clinging to the rigging of the remaining
+mast; uppermost, the active figure with the curling hair.
+
+There was a bell on board; and as the ship rolled and dashed, like a
+desperate creature driven mad, now showing us the whole sweep of her
+deck, as she turned on her beam-ends towards the shore, now nothing but
+her keel, as she sprung wildly over and turned towards the sea, the bell
+rang; and its sound, the knell of those unhappy men, was borne towards
+us on the wind. Again we lost her, and again she rose. Two men were
+gone. The agony on the shore increased. Men groaned, and clasped their
+hands; women shrieked, and turned away their faces. Some ran wildly
+up and down along the beach, crying for help where no help could be. I
+found myself one of these, frantically imploring a knot of sailors whom
+I knew, not to let those two lost creatures perish before our eyes.
+
+They were making out to me, in an agitated way--I don't know how,
+for the little I could hear I was scarcely composed enough to
+understand--that the lifeboat had been bravely manned an hour ago, and
+could do nothing; and that as no man would be so desperate as to attempt
+to wade off with a rope, and establish a communication with the shore,
+there was nothing left to try; when I noticed that some new sensation
+moved the people on the beach, and saw them part, and Ham come breaking
+through them to the front.
+
+I ran to him--as well as I know, to repeat my appeal for help. But,
+distracted though I was, by a sight so new to me and terrible, the
+determination in his face, and his look out to sea--exactly the same
+look as I remembered in connexion with the morning after Emily's
+flight--awoke me to a knowledge of his danger. I held him back with both
+arms; and implored the men with whom I had been speaking, not to listen
+to him, not to do murder, not to let him stir from off that sand!
+
+Another cry arose on shore; and looking to the wreck, we saw the cruel
+sail, with blow on blow, beat off the lower of the two men, and fly up
+in triumph round the active figure left alone upon the mast.
+
+Against such a sight, and against such determination as that of the
+calmly desperate man who was already accustomed to lead half the people
+present, I might as hopefully have entreated the wind. 'Mas'r Davy,'
+he said, cheerily grasping me by both hands, 'if my time is come, 'tis
+come. If 'tan't, I'll bide it. Lord above bless you, and bless all!
+Mates, make me ready! I'm a-going off!'
+
+I was swept away, but not unkindly, to some distance, where the people
+around me made me stay; urging, as I confusedly perceived, that he was
+bent on going, with help or without, and that I should endanger the
+precautions for his safety by troubling those with whom they rested. I
+don't know what I answered, or what they rejoined; but I saw hurry on
+the beach, and men running with ropes from a capstan that was there, and
+penetrating into a circle of figures that hid him from me. Then, I saw
+him standing alone, in a seaman's frock and trousers: a rope in his
+hand, or slung to his wrist: another round his body: and several of the
+best men holding, at a little distance, to the latter, which he laid out
+himself, slack upon the shore, at his feet.
+
+The wreck, even to my unpractised eye, was breaking up. I saw that she
+was parting in the middle, and that the life of the solitary man upon
+the mast hung by a thread. Still, he clung to it. He had a singular red
+cap on,--not like a sailor's cap, but of a finer colour; and as the few
+yielding planks between him and destruction rolled and bulged, and his
+anticipative death-knell rung, he was seen by all of us to wave it. I
+saw him do it now, and thought I was going distracted, when his action
+brought an old remembrance to my mind of a once dear friend.
+
+Ham watched the sea, standing alone, with the silence of suspended
+breath behind him, and the storm before, until there was a great
+retiring wave, when, with a backward glance at those who held the rope
+which was made fast round his body, he dashed in after it, and in a
+moment was buffeting with the water; rising with the hills, falling
+with the valleys, lost beneath the foam; then drawn again to land. They
+hauled in hastily.
+
+He was hurt. I saw blood on his face, from where I stood; but he took
+no thought of that. He seemed hurriedly to give them some directions for
+leaving him more free--or so I judged from the motion of his arm--and
+was gone as before.
+
+And now he made for the wreck, rising with the hills, falling with the
+valleys, lost beneath the rugged foam, borne in towards the shore,
+borne on towards the ship, striving hard and valiantly. The distance was
+nothing, but the power of the sea and wind made the strife deadly. At
+length he neared the wreck. He was so near, that with one more of his
+vigorous strokes he would be clinging to it,--when a high, green, vast
+hill-side of water, moving on shoreward, from beyond the ship, he seemed
+to leap up into it with a mighty bound, and the ship was gone!
+
+Some eddying fragments I saw in the sea, as if a mere cask had been
+broken, in running to the spot where they were hauling in. Consternation
+was in every face. They drew him to my very feet--insensible--dead.
+He was carried to the nearest house; and, no one preventing me now, I
+remained near him, busy, while every means of restoration were tried;
+but he had been beaten to death by the great wave, and his generous
+heart was stilled for ever.
+
+As I sat beside the bed, when hope was abandoned and all was done, a
+fisherman, who had known me when Emily and I were children, and ever
+since, whispered my name at the door.
+
+'Sir,' said he, with tears starting to his weather-beaten face, which,
+with his trembling lips, was ashy pale, 'will you come over yonder?'
+
+The old remembrance that had been recalled to me, was in his look. I
+asked him, terror-stricken, leaning on the arm he held out to support
+me:
+
+'Has a body come ashore?'
+
+He said, 'Yes.'
+
+'Do I know it?' I asked then.
+
+He answered nothing.
+
+But he led me to the shore. And on that part of it where she and I had
+looked for shells, two children--on that part of it where some lighter
+fragments of the old boat, blown down last night, had been scattered by
+the wind--among the ruins of the home he had wronged--I saw him lying
+with his head upon his arm, as I had often seen him lie at school.
+
+
+
+CHAPTER 56. THE NEW WOUND, AND THE OLD
+
+No need, O Steerforth, to have said, when we last spoke together, in
+that hour which I so little deemed to be our parting-hour--no need to
+have said, 'Think of me at my best!' I had done that ever; and could I
+change now, looking on this sight!
+
+They brought a hand-bier, and laid him on it, and covered him with a
+flag, and took him up and bore him on towards the houses. All the men
+who carried him had known him, and gone sailing with him, and seen him
+merry and bold. They carried him through the wild roar, a hush in the
+midst of all the tumult; and took him to the cottage where Death was
+already.
+
+But when they set the bier down on the threshold, they looked at one
+another, and at me, and whispered. I knew why. They felt as if it were
+not right to lay him down in the same quiet room.
+
+We went into the town, and took our burden to the inn. So soon as I
+could at all collect my thoughts, I sent for Joram, and begged him to
+provide me a conveyance in which it could be got to London in the night.
+I knew that the care of it, and the hard duty of preparing his mother to
+receive it, could only rest with me; and I was anxious to discharge that
+duty as faithfully as I could.
+
+I chose the night for the journey, that there might be less curiosity
+when I left the town. But, although it was nearly midnight when I came
+out of the yard in a chaise, followed by what I had in charge, there
+were many people waiting. At intervals, along the town, and even a
+little way out upon the road, I saw more: but at length only the bleak
+night and the open country were around me, and the ashes of my youthful
+friendship.
+
+Upon a mellow autumn day, about noon, when the ground was perfumed by
+fallen leaves, and many more, in beautiful tints of yellow, red, and
+brown, yet hung upon the trees, through which the sun was shining, I
+arrived at Highgate. I walked the last mile, thinking as I went along of
+what I had to do; and left the carriage that had followed me all through
+the night, awaiting orders to advance.
+
+The house, when I came up to it, looked just the same. Not a blind was
+raised; no sign of life was in the dull paved court, with its covered
+way leading to the disused door. The wind had quite gone down, and
+nothing moved.
+
+I had not, at first, the courage to ring at the gate; and when I did
+ring, my errand seemed to me to be expressed in the very sound of the
+bell. The little parlour-maid came out, with the key in her hand; and
+looking earnestly at me as she unlocked the gate, said:
+
+'I beg your pardon, sir. Are you ill?'
+
+'I have been much agitated, and am fatigued.'
+
+'Is anything the matter, sir?---Mr. James?--' 'Hush!' said I. 'Yes,
+something has happened, that I have to break to Mrs. Steerforth. She is
+at home?'
+
+The girl anxiously replied that her mistress was very seldom out now,
+even in a carriage; that she kept her room; that she saw no company, but
+would see me. Her mistress was up, she said, and Miss Dartle was with
+her. What message should she take upstairs?
+
+Giving her a strict charge to be careful of her manner, and only to
+carry in my card and say I waited, I sat down in the drawing-room (which
+we had now reached) until she should come back. Its former pleasant air
+of occupation was gone, and the shutters were half closed. The harp had
+not been used for many and many a day. His picture, as a boy, was
+there. The cabinet in which his mother had kept his letters was there. I
+wondered if she ever read them now; if she would ever read them more!
+
+The house was so still that I heard the girl's light step upstairs. On
+her return, she brought a message, to the effect that Mrs. Steerforth
+was an invalid and could not come down; but that if I would excuse her
+being in her chamber, she would be glad to see me. In a few moments I
+stood before her.
+
+She was in his room; not in her own. I felt, of course, that she had
+taken to occupy it, in remembrance of him; and that the many tokens
+of his old sports and accomplishments, by which she was surrounded,
+remained there, just as he had left them, for the same reason. She
+murmured, however, even in her reception of me, that she was out of her
+own chamber because its aspect was unsuited to her infirmity; and with
+her stately look repelled the least suspicion of the truth.
+
+At her chair, as usual, was Rosa Dartle. From the first moment of
+her dark eyes resting on me, I saw she knew I was the bearer of evil
+tidings. The scar sprung into view that instant. She withdrew herself
+a step behind the chair, to keep her own face out of Mrs. Steerforth's
+observation; and scrutinized me with a piercing gaze that never
+faltered, never shrunk.
+
+'I am sorry to observe you are in mourning, sir,' said Mrs. Steerforth.
+
+'I am unhappily a widower,' said I.
+
+'You are very young to know so great a loss,' she returned. 'I am
+grieved to hear it. I am grieved to hear it. I hope Time will be good to
+you.'
+
+'I hope Time,' said I, looking at her, 'will be good to all of us.
+Dear Mrs. Steerforth, we must all trust to that, in our heaviest
+misfortunes.'
+
+The earnestness of my manner, and the tears in my eyes, alarmed her. The
+whole course of her thoughts appeared to stop, and change.
+
+I tried to command my voice in gently saying his name, but it trembled.
+She repeated it to herself, two or three times, in a low tone. Then,
+addressing me, she said, with enforced calmness:
+
+'My son is ill.'
+
+'Very ill.'
+
+'You have seen him?'
+
+'I have.'
+
+'Are you reconciled?'
+
+I could not say Yes, I could not say No. She slightly turned her head
+towards the spot where Rosa Dartle had been standing at her elbow, and
+in that moment I said, by the motion of my lips, to Rosa, 'Dead!'
+
+That Mrs. Steerforth might not be induced to look behind her, and read,
+plainly written, what she was not yet prepared to know, I met her look
+quickly; but I had seen Rosa Dartle throw her hands up in the air with
+vehemence of despair and horror, and then clasp them on her face.
+
+The handsome lady--so like, oh so like!--regarded me with a fixed look,
+and put her hand to her forehead. I besought her to be calm, and prepare
+herself to bear what I had to tell; but I should rather have entreated
+her to weep, for she sat like a stone figure.
+
+'When I was last here,' I faltered, 'Miss Dartle told me he was sailing
+here and there. The night before last was a dreadful one at sea. If he
+were at sea that night, and near a dangerous coast, as it is said he
+was; and if the vessel that was seen should really be the ship which--'
+
+'Rosa!' said Mrs. Steerforth, 'come to me!'
+
+She came, but with no sympathy or gentleness. Her eyes gleamed like fire
+as she confronted his mother, and broke into a frightful laugh.
+
+'Now,' she said, 'is your pride appeased, you madwoman? Now has he made
+atonement to you--with his life! Do you hear?---His life!'
+
+Mrs. Steerforth, fallen back stiffly in her chair, and making no sound
+but a moan, cast her eyes upon her with a wide stare.
+
+'Aye!' cried Rosa, smiting herself passionately on the breast, 'look at
+me! Moan, and groan, and look at me! Look here!' striking the scar, 'at
+your dead child's handiwork!'
+
+The moan the mother uttered, from time to time, went to My heart. Always
+the same. Always inarticulate and stifled. Always accompanied with
+an incapable motion of the head, but with no change of face. Always
+proceeding from a rigid mouth and closed teeth, as if the jaw were
+locked and the face frozen up in pain.
+
+'Do you remember when he did this?' she proceeded. 'Do you remember
+when, in his inheritance of your nature, and in your pampering of his
+pride and passion, he did this, and disfigured me for life? Look at me,
+marked until I die with his high displeasure; and moan and groan for
+what you made him!'
+
+'Miss Dartle,' I entreated her. 'For Heaven's sake--'
+
+'I WILL speak!' she said, turning on me with her lightning eyes. 'Be
+silent, you! Look at me, I say, proud mother of a proud, false son! Moan
+for your nurture of him, moan for your corruption of him, moan for your
+loss of him, moan for mine!'
+
+She clenched her hand, and trembled through her spare, worn figure, as
+if her passion were killing her by inches.
+
+'You, resent his self-will!' she exclaimed. 'You, injured by his haughty
+temper! You, who opposed to both, when your hair was grey, the qualities
+which made both when you gave him birth! YOU, who from his cradle reared
+him to be what he was, and stunted what he should have been! Are you
+rewarded, now, for your years of trouble?'
+
+'Oh, Miss Dartle, shame! Oh cruel!'
+
+'I tell you,' she returned, 'I WILL speak to her. No power on earth
+should stop me, while I was standing here! Have I been silent all these
+years, and shall I not speak now? I loved him better than you ever loved
+him!' turning on her fiercely. 'I could have loved him, and asked no
+return. If I had been his wife, I could have been the slave of his
+caprices for a word of love a year. I should have been. Who knows it
+better than I? You were exacting, proud, punctilious, selfish. My love
+would have been devoted--would have trod your paltry whimpering under
+foot!'
+
+With flashing eyes, she stamped upon the ground as if she actually did
+it.
+
+'Look here!' she said, striking the scar again, with a relentless hand.
+'When he grew into the better understanding of what he had done, he saw
+it, and repented of it! I could sing to him, and talk to him, and show
+the ardour that I felt in all he did, and attain with labour to such
+knowledge as most interested him; and I attracted him. When he was
+freshest and truest, he loved me. Yes, he did! Many a time, when you
+were put off with a slight word, he has taken Me to his heart!'
+
+She said it with a taunting pride in the midst of her frenzy--for it
+was little less--yet with an eager remembrance of it, in which the
+smouldering embers of a gentler feeling kindled for the moment.
+
+'I descended--as I might have known I should, but that he fascinated me
+with his boyish courtship--into a doll, a trifle for the occupation
+of an idle hour, to be dropped, and taken up, and trifled with, as the
+inconstant humour took him. When he grew weary, I grew weary. As his
+fancy died out, I would no more have tried to strengthen any power I
+had, than I would have married him on his being forced to take me for
+his wife. We fell away from one another without a word. Perhaps you saw
+it, and were not sorry. Since then, I have been a mere disfigured piece
+of furniture between you both; having no eyes, no ears, no feelings,
+no remembrances. Moan? Moan for what you made him; not for your love. I
+tell you that the time was, when I loved him better than you ever did!'
+
+She stood with her bright angry eyes confronting the wide stare, and the
+set face; and softened no more, when the moaning was repeated, than if
+the face had been a picture.
+
+'Miss Dartle,' said I, 'if you can be so obdurate as not to feel for
+this afflicted mother--'
+
+'Who feels for me?' she sharply retorted. 'She has sown this. Let her
+moan for the harvest that she reaps today!'
+
+'And if his faults--' I began.
+
+'Faults!' she cried, bursting into passionate tears. 'Who dares malign
+him? He had a soul worth millions of the friends to whom he stooped!'
+
+'No one can have loved him better, no one can hold him in dearer
+remembrance than I,' I replied. 'I meant to say, if you have no
+compassion for his mother; or if his faults--you have been bitter on
+them--'
+
+'It's false,' she cried, tearing her black hair; 'I loved him!'
+
+'--if his faults cannot,' I went on, 'be banished from your remembrance,
+in such an hour; look at that figure, even as one you have never seen
+before, and render it some help!'
+
+All this time, the figure was unchanged, and looked unchangeable.
+Motionless, rigid, staring; moaning in the same dumb way from time to
+time, with the same helpless motion of the head; but giving no other
+sign of life. Miss Dartle suddenly kneeled down before it, and began to
+loosen the dress.
+
+'A curse upon you!' she said, looking round at me, with a mingled
+expression of rage and grief. 'It was in an evil hour that you ever came
+here! A curse upon you! Go!'
+
+After passing out of the room, I hurried back to ring the bell, the
+sooner to alarm the servants. She had then taken the impassive figure
+in her arms, and, still upon her knees, was weeping over it, kissing it,
+calling to it, rocking it to and fro upon her bosom like a child, and
+trying every tender means to rouse the dormant senses. No longer afraid
+of leaving her, I noiselessly turned back again; and alarmed the house
+as I went out.
+
+Later in the day, I returned, and we laid him in his mother's room. She
+was just the same, they told me; Miss Dartle never left her; doctors
+were in attendance, many things had been tried; but she lay like a
+statue, except for the low sound now and then.
+
+I went through the dreary house, and darkened the windows. The windows
+of the chamber where he lay, I darkened last. I lifted up the leaden
+hand, and held it to my heart; and all the world seemed death and
+silence, broken only by his mother's moaning.
+
+
+
+CHAPTER 57. THE EMIGRANTS
+
+
+One thing more, I had to do, before yielding myself to the shock of
+these emotions. It was, to conceal what had occurred, from those who
+were going away; and to dismiss them on their voyage in happy ignorance.
+In this, no time was to be lost.
+
+I took Mr. Micawber aside that same night, and confided to him the
+task of standing between Mr. Peggotty and intelligence of the late
+catastrophe. He zealously undertook to do so, and to intercept any
+newspaper through which it might, without such precautions, reach him.
+
+'If it penetrates to him, sir,' said Mr. Micawber, striking himself on
+the breast, 'it shall first pass through this body!'
+
+Mr. Micawber, I must observe, in his adaptation of himself to a new
+state of society, had acquired a bold buccaneering air, not absolutely
+lawless, but defensive and prompt. One might have supposed him a child
+of the wilderness, long accustomed to live out of the confines of
+civilization, and about to return to his native wilds.
+
+He had provided himself, among other things, with a complete suit of
+oilskin, and a straw hat with a very low crown, pitched or caulked on
+the outside. In this rough clothing, with a common mariner's telescope
+under his arm, and a shrewd trick of casting up his eye at the sky
+as looking out for dirty weather, he was far more nautical, after his
+manner, than Mr. Peggotty. His whole family, if I may so express it,
+were cleared for action. I found Mrs. Micawber in the closest and most
+uncompromising of bonnets, made fast under the chin; and in a shawl
+which tied her up (as I had been tied up, when my aunt first received
+me) like a bundle, and was secured behind at the waist, in a strong
+knot. Miss Micawber I found made snug for stormy weather, in the same
+manner; with nothing superfluous about her. Master Micawber was hardly
+visible in a Guernsey shirt, and the shaggiest suit of slops I ever
+saw; and the children were done up, like preserved meats, in impervious
+cases. Both Mr. Micawber and his eldest son wore their sleeves loosely
+turned back at the wrists, as being ready to lend a hand in any
+direction, and to 'tumble up', or sing out, 'Yeo--Heave--Yeo!' on the
+shortest notice.
+
+Thus Traddles and I found them at nightfall, assembled on the wooden
+steps, at that time known as Hungerford Stairs, watching the departure
+of a boat with some of their property on board. I had told Traddles of
+the terrible event, and it had greatly shocked him; but there could be
+no doubt of the kindness of keeping it a secret, and he had come to help
+me in this last service. It was here that I took Mr. Micawber aside, and
+received his promise.
+
+The Micawber family were lodged in a little, dirty, tumble-down
+public-house, which in those days was close to the stairs, and whose
+protruding wooden rooms overhung the river. The family, as emigrants,
+being objects of some interest in and about Hungerford, attracted so
+many beholders, that we were glad to take refuge in their room. It was
+one of the wooden chambers upstairs, with the tide flowing underneath.
+My aunt and Agnes were there, busily making some little extra comforts,
+in the way of dress, for the children. Peggotty was quietly assisting,
+with the old insensible work-box, yard-measure, and bit of wax-candle
+before her, that had now outlived so much.
+
+It was not easy to answer her inquiries; still less to whisper Mr.
+Peggotty, when Mr. Micawber brought him in, that I had given the letter,
+and all was well. But I did both, and made them happy. If I showed any
+trace of what I felt, my own sorrows were sufficient to account for it.
+
+'And when does the ship sail, Mr. Micawber?' asked my aunt.
+
+Mr. Micawber considered it necessary to prepare either my aunt or his
+wife, by degrees, and said, sooner than he had expected yesterday.
+
+'The boat brought you word, I suppose?' said my aunt.
+
+'It did, ma'am,' he returned.
+
+'Well?' said my aunt. 'And she sails--'
+
+'Madam,' he replied, 'I am informed that we must positively be on board
+before seven tomorrow morning.'
+
+'Heyday!' said my aunt, 'that's soon. Is it a sea-going fact, Mr.
+Peggotty?' ''Tis so, ma'am. She'll drop down the river with that theer
+tide. If Mas'r Davy and my sister comes aboard at Gravesen', arternoon
+o' next day, they'll see the last on us.'
+
+'And that we shall do,' said I, 'be sure!'
+
+'Until then, and until we are at sea,' observed Mr. Micawber, with a
+glance of intelligence at me, 'Mr. Peggotty and myself will constantly
+keep a double look-out together, on our goods and chattels. Emma, my
+love,' said Mr. Micawber, clearing his throat in his magnificent way,
+'my friend Mr. Thomas Traddles is so obliging as to solicit, in my ear,
+that he should have the privilege of ordering the ingredients necessary
+to the composition of a moderate portion of that Beverage which is
+peculiarly associated, in our minds, with the Roast Beef of Old England.
+I allude to--in short, Punch. Under ordinary circumstances, I should
+scruple to entreat the indulgence of Miss Trotwood and Miss Wickfield,
+but-'
+
+'I can only say for myself,' said my aunt, 'that I will drink all
+happiness and success to you, Mr. Micawber, with the utmost pleasure.'
+
+'And I too!' said Agnes, with a smile.
+
+Mr. Micawber immediately descended to the bar, where he appeared to be
+quite at home; and in due time returned with a steaming jug. I could
+not but observe that he had been peeling the lemons with his own
+clasp-knife, which, as became the knife of a practical settler, was
+about a foot long; and which he wiped, not wholly without ostentation,
+on the sleeve of his coat. Mrs. Micawber and the two elder members
+of the family I now found to be provided with similar formidable
+instruments, while every child had its own wooden spoon attached to its
+body by a strong line. In a similar anticipation of life afloat, and in
+the Bush, Mr. Micawber, instead of helping Mrs. Micawber and his eldest
+son and daughter to punch, in wine-glasses, which he might easily have
+done, for there was a shelf-full in the room, served it out to them in a
+series of villainous little tin pots; and I never saw him enjoy anything
+so much as drinking out of his own particular pint pot, and putting it
+in his pocket at the close of the evening.
+
+'The luxuries of the old country,' said Mr. Micawber, with an intense
+satisfaction in their renouncement, 'we abandon. The denizens of the
+forest cannot, of course, expect to participate in the refinements of
+the land of the Free.'
+
+Here, a boy came in to say that Mr. Micawber was wanted downstairs.
+
+'I have a presentiment,' said Mrs. Micawber, setting down her tin pot,
+'that it is a member of my family!'
+
+'If so, my dear,' observed Mr. Micawber, with his usual suddenness of
+warmth on that subject, 'as the member of your family--whoever he, she,
+or it, may be--has kept us waiting for a considerable period, perhaps
+the Member may now wait MY convenience.'
+
+'Micawber,' said his wife, in a low tone, 'at such a time as this--'
+
+'"It is not meet,"' said Mr. Micawber, rising, '"that every nice offence
+should bear its comment!" Emma, I stand reproved.'
+
+'The loss, Micawber,' observed his wife, 'has been my family's, not
+yours. If my family are at length sensible of the deprivation to which
+their own conduct has, in the past, exposed them, and now desire to
+extend the hand of fellowship, let it not be repulsed.'
+
+'My dear,' he returned, 'so be it!'
+
+'If not for their sakes; for mine, Micawber,' said his wife.
+
+'Emma,' he returned, 'that view of the question is, at such a moment,
+irresistible. I cannot, even now, distinctly pledge myself to fall
+upon your family's neck; but the member of your family, who is now in
+attendance, shall have no genial warmth frozen by me.'
+
+Mr. Micawber withdrew, and was absent some little time; in the course of
+which Mrs. Micawber was not wholly free from an apprehension that words
+might have arisen between him and the Member. At length the same boy
+reappeared, and presented me with a note written in pencil, and headed,
+in a legal manner, 'Heep v. Micawber'. From this document, I learned
+that Mr. Micawber being again arrested, 'Was in a final paroxysm of
+despair; and that he begged me to send him his knife and pint pot, by
+bearer, as they might prove serviceable during the brief remainder of
+his existence, in jail. He also requested, as a last act of friendship,
+that I would see his family to the Parish Workhouse, and forget that
+such a Being ever lived.
+
+Of course I answered this note by going down with the boy to pay the
+money, where I found Mr. Micawber sitting in a corner, looking darkly at
+the Sheriff 's Officer who had effected the capture. On his release,
+he embraced me with the utmost fervour; and made an entry of the
+transaction in his pocket-book--being very particular, I recollect,
+about a halfpenny I inadvertently omitted from my statement of the
+total.
+
+This momentous pocket-book was a timely reminder to him of another
+transaction. On our return to the room upstairs (where he accounted for
+his absence by saying that it had been occasioned by circumstances over
+which he had no control), he took out of it a large sheet of paper,
+folded small, and quite covered with long sums, carefully worked. From
+the glimpse I had of them, I should say that I never saw such sums
+out of a school ciphering-book. These, it seemed, were calculations of
+compound interest on what he called 'the principal amount of forty-one,
+ten, eleven and a half', for various periods. After a careful
+consideration of these, and an elaborate estimate of his resources,
+he had come to the conclusion to select that sum which represented the
+amount with compound interest to two years, fifteen calendar months, and
+fourteen days, from that date. For this he had drawn a note-of-hand
+with great neatness, which he handed over to Traddles on the spot,
+a discharge of his debt in full (as between man and man), with many
+acknowledgements.
+
+'I have still a presentiment,' said Mrs. Micawber, pensively shaking her
+head, 'that my family will appear on board, before we finally depart.'
+
+Mr. Micawber evidently had his presentiment on the subject too, but he
+put it in his tin pot and swallowed it.
+
+'If you have any opportunity of sending letters home, on your passage,
+Mrs. Micawber,' said my aunt, 'you must let us hear from you, you know.'
+
+'My dear Miss Trotwood,' she replied, 'I shall only be too happy
+to think that anyone expects to hear from us. I shall not fail to
+correspond. Mr. Copperfield, I trust, as an old and familiar friend,
+will not object to receive occasional intelligence, himself, from one
+who knew him when the twins were yet unconscious?'
+
+I said that I should hope to hear, whenever she had an opportunity of
+writing.
+
+'Please Heaven, there will be many such opportunities,' said Mr.
+Micawber. 'The ocean, in these times, is a perfect fleet of ships; and
+we can hardly fail to encounter many, in running over. It is merely
+crossing,' said Mr. Micawber, trifling with his eye-glass, 'merely
+crossing. The distance is quite imaginary.'
+
+I think, now, how odd it was, but how wonderfully like Mr. Micawber,
+that, when he went from London to Canterbury, he should have talked as
+if he were going to the farthest limits of the earth; and, when he went
+from England to Australia, as if he were going for a little trip across
+the channel.
+
+'On the voyage, I shall endeavour,' said Mr. Micawber, 'occasionally
+to spin them a yarn; and the melody of my son Wilkins will, I trust,
+be acceptable at the galley-fire. When Mrs. Micawber has her
+sea-legs on--an expression in which I hope there is no conventional
+impropriety--she will give them, I dare say, "Little Tafflin". Porpoises
+and dolphins, I believe, will be frequently observed athwart our
+Bows; and, either on the starboard or the larboard quarter, objects of
+interest will be continually descried. In short,' said Mr. Micawber,
+with the old genteel air, 'the probability is, all will be found so
+exciting, alow and aloft, that when the lookout, stationed in the
+main-top, cries Land-oh! we shall be very considerably astonished!'
+
+With that he flourished off the contents of his little tin pot, as if he
+had made the voyage, and had passed a first-class examination before the
+highest naval authorities.
+
+'What I chiefly hope, my dear Mr. Copperfield,' said Mrs. Micawber,
+'is, that in some branches of our family we may live again in the old
+country. Do not frown, Micawber! I do not now refer to my own family,
+but to our children's children. However vigorous the sapling,' said Mrs.
+Micawber, shaking her head, 'I cannot forget the parent-tree; and when
+our race attains to eminence and fortune, I own I should wish that
+fortune to flow into the coffers of Britannia.'
+
+'My dear,' said Mr. Micawber, 'Britannia must take her chance. I am
+bound to say that she has never done much for me, and that I have no
+particular wish upon the subject.'
+
+'Micawber,' returned Mrs. Micawber, 'there, you are wrong. You are going
+out, Micawber, to this distant clime, to strengthen, not to weaken, the
+connexion between yourself and Albion.'
+
+'The connexion in question, my love,' rejoined Mr. Micawber, 'has not
+laid me, I repeat, under that load of personal obligation, that I am at
+all sensitive as to the formation of another connexion.'
+
+'Micawber,' returned Mrs. Micawber. 'There, I again say, you are wrong.
+You do not know your power, Micawber. It is that which will strengthen,
+even in this step you are about to take, the connexion between yourself
+and Albion.'
+
+Mr. Micawber sat in his elbow-chair, with his eyebrows raised; half
+receiving and half repudiating Mrs. Micawber's views as they were
+stated, but very sensible of their foresight.
+
+'My dear Mr. Copperfield,' said Mrs. Micawber, 'I wish Mr. Micawber to
+feel his position. It appears to me highly important that Mr. Micawber
+should, from the hour of his embarkation, feel his position. Your old
+knowledge of me, my dear Mr. Copperfield, will have told you that I have
+not the sanguine disposition of Mr. Micawber. My disposition is, if I
+may say so, eminently practical. I know that this is a long voyage. I
+know that it will involve many privations and inconveniences. I cannot
+shut my eyes to those facts. But I also know what Mr. Micawber is.
+I know the latent power of Mr. Micawber. And therefore I consider it
+vitally important that Mr. Micawber should feel his position.'
+
+'My love,' he observed, 'perhaps you will allow me to remark that it is
+barely possible that I DO feel my position at the present moment.'
+
+'I think not, Micawber,' she rejoined. 'Not fully. My dear Mr.
+Copperfield, Mr. Micawber's is not a common case. Mr. Micawber is going
+to a distant country expressly in order that he may be fully understood
+and appreciated for the first time. I wish Mr. Micawber to take his
+stand upon that vessel's prow, and firmly say, "This country I am
+come to conquer! Have you honours? Have you riches? Have you posts of
+profitable pecuniary emolument? Let them be brought forward. They are
+mine!"'
+
+Mr. Micawber, glancing at us all, seemed to think there was a good deal
+in this idea.
+
+'I wish Mr. Micawber, if I make myself understood,' said Mrs. Micawber,
+in her argumentative tone, 'to be the Caesar of his own fortunes. That,
+my dear Mr. Copperfield, appears to me to be his true position. From
+the first moment of this voyage, I wish Mr. Micawber to stand upon
+that vessel's prow and say, "Enough of delay: enough of disappointment:
+enough of limited means. That was in the old country. This is the new.
+Produce your reparation. Bring it forward!"'
+
+Mr. Micawber folded his arms in a resolute manner, as if he were then
+stationed on the figure-head.
+
+'And doing that,' said Mrs. Micawber, '--feeling his position--am I not
+right in saying that Mr. Micawber will strengthen, and not weaken, his
+connexion with Britain? An important public character arising in that
+hemisphere, shall I be told that its influence will not be felt at home?
+Can I be so weak as to imagine that Mr. Micawber, wielding the rod of
+talent and of power in Australia, will be nothing in England? I am but
+a woman; but I should be unworthy of myself and of my papa, if I were
+guilty of such absurd weakness.'
+
+Mrs. Micawber's conviction that her arguments were unanswerable, gave
+a moral elevation to her tone which I think I had never heard in it
+before.
+
+'And therefore it is,' said Mrs. Micawber, 'that I the more wish, that,
+at a future period, we may live again on the parent soil. Mr. Micawber
+may be--I cannot disguise from myself that the probability is, Mr.
+Micawber will be--a page of History; and he ought then to be represented
+in the country which gave him birth, and did NOT give him employment!'
+
+'My love,' observed Mr. Micawber, 'it is impossible for me not to be
+touched by your affection. I am always willing to defer to your good
+sense. What will be--will be. Heaven forbid that I should grudge my
+native country any portion of the wealth that may be accumulated by our
+descendants!'
+
+'That's well,' said my aunt, nodding towards Mr. Peggotty, 'and I drink
+my love to you all, and every blessing and success attend you!'
+
+Mr. Peggotty put down the two children he had been nursing, one on each
+knee, to join Mr. and Mrs. Micawber in drinking to all of us in return;
+and when he and the Micawbers cordially shook hands as comrades, and his
+brown face brightened with a smile, I felt that he would make his way,
+establish a good name, and be beloved, go where he would.
+
+Even the children were instructed, each to dip a wooden spoon into Mr.
+Micawber's pot, and pledge us in its contents. When this was done, my
+aunt and Agnes rose, and parted from the emigrants. It was a sorrowful
+farewell. They were all crying; the children hung about Agnes to the
+last; and we left poor Mrs. Micawber in a very distressed condition,
+sobbing and weeping by a dim candle, that must have made the room look,
+from the river, like a miserable light-house.
+
+I went down again next morning to see that they were away. They had
+departed, in a boat, as early as five o'clock. It was a wonderful
+instance to me of the gap such partings make, that although my
+association of them with the tumble-down public-house and the wooden
+stairs dated only from last night, both seemed dreary and deserted, now
+that they were gone.
+
+In the afternoon of the next day, my old nurse and I went down to
+Gravesend. We found the ship in the river, surrounded by a crowd
+of boats; a favourable wind blowing; the signal for sailing at her
+mast-head. I hired a boat directly, and we put off to her; and getting
+through the little vortex of confusion of which she was the centre, went
+on board.
+
+Mr. Peggotty was waiting for us on deck. He told me that Mr. Micawber
+had just now been arrested again (and for the last time) at the suit of
+Heep, and that, in compliance with a request I had made to him, he had
+paid the money, which I repaid him. He then took us down between decks;
+and there, any lingering fears I had of his having heard any rumours of
+what had happened, were dispelled by Mr. Micawber's coming out of the
+gloom, taking his arm with an air of friendship and protection, and
+telling me that they had scarcely been asunder for a moment, since the
+night before last.
+
+It was such a strange scene to me, and so confined and dark, that, at
+first, I could make out hardly anything; but, by degrees, it cleared, as
+my eyes became more accustomed to the gloom, and I seemed to stand in
+a picture by OSTADE. Among the great beams, bulks, and ringbolts of the
+ship, and the emigrant-berths, and chests, and bundles, and barrels, and
+heaps of miscellaneous baggage--'lighted up, here and there, by dangling
+lanterns; and elsewhere by the yellow daylight straying down a windsail
+or a hatchway--were crowded groups of people, making new friendships,
+taking leave of one another, talking, laughing, crying, eating and
+drinking; some, already settled down into the possession of their few
+feet of space, with their little households arranged, and tiny children
+established on stools, or in dwarf elbow-chairs; others, despairing of
+a resting-place, and wandering disconsolately. From babies who had but a
+week or two of life behind them, to crooked old men and women who seemed
+to have but a week or two of life before them; and from ploughmen bodily
+carrying out soil of England on their boots, to smiths taking away
+samples of its soot and smoke upon their skins; every age and occupation
+appeared to be crammed into the narrow compass of the 'tween decks.
+
+As my eye glanced round this place, I thought I saw sitting, by an open
+port, with one of the Micawber children near her, a figure like Emily's;
+it first attracted my attention, by another figure parting from it with
+a kiss; and as it glided calmly away through the disorder, reminding
+me of--Agnes! But in the rapid motion and confusion, and in the
+unsettlement of my own thoughts, I lost it again; and only knew that
+the time was come when all visitors were being warned to leave the ship;
+that my nurse was crying on a chest beside me; and that Mrs. Gummidge,
+assisted by some younger stooping woman in black, was busily arranging
+Mr. Peggotty's goods.
+
+'Is there any last wured, Mas'r Davy?' said he. 'Is there any one
+forgotten thing afore we parts?'
+
+'One thing!' said I. 'Martha!'
+
+He touched the younger woman I have mentioned on the shoulder, and
+Martha stood before me.
+
+'Heaven bless you, you good man!' cried I. 'You take her with you!'
+
+She answered for him, with a burst of tears. I could speak no more at
+that time, but I wrung his hand; and if ever I have loved and honoured
+any man, I loved and honoured that man in my soul.
+
+The ship was clearing fast of strangers. The greatest trial that I had,
+remained. I told him what the noble spirit that was gone, had given me
+in charge to say at parting. It moved him deeply. But when he charged
+me, in return, with many messages of affection and regret for those deaf
+ears, he moved me more.
+
+The time was come. I embraced him, took my weeping nurse upon my arm,
+and hurried away. On deck, I took leave of poor Mrs. Micawber. She was
+looking distractedly about for her family, even then; and her last words
+to me were, that she never would desert Mr. Micawber.
+
+We went over the side into our boat, and lay at a little distance, to
+see the ship wafted on her course. It was then calm, radiant sunset.
+She lay between us, and the red light; and every taper line and spar was
+visible against the glow. A sight at once so beautiful, so mournful, and
+so hopeful, as the glorious ship, lying, still, on the flushed water,
+with all the life on board her crowded at the bulwarks, and there
+clustering, for a moment, bare-headed and silent, I never saw.
+
+Silent, only for a moment. As the sails rose to the wind, and the ship
+began to move, there broke from all the boats three resounding cheers,
+which those on board took up, and echoed back, and which were echoed
+and re-echoed. My heart burst out when I heard the sound, and beheld the
+waving of the hats and handkerchiefs--and then I saw her!
+
+Then I saw her, at her uncle's side, and trembling on his shoulder. He
+pointed to us with an eager hand; and she saw us, and waved her last
+good-bye to me. Aye, Emily, beautiful and drooping, cling to him with
+the utmost trust of thy bruised heart; for he has clung to thee, with
+all the might of his great love!
+
+Surrounded by the rosy light, and standing high upon the deck, apart
+together, she clinging to him, and he holding her, they solemnly passed
+away. The night had fallen on the Kentish hills when we were rowed
+ashore--and fallen darkly upon me.
+
+
+
+CHAPTER 58. ABSENCE
+
+
+It was a long and gloomy night that gathered on me, haunted by the
+ghosts of many hopes, of many dear remembrances, many errors, many
+unavailing sorrows and regrets.
+
+I went away from England; not knowing, even then, how great the shock
+was, that I had to bear. I left all who were dear to me, and went away;
+and believed that I had borne it, and it was past. As a man upon a
+field of battle will receive a mortal hurt, and scarcely know that he is
+struck, so I, when I was left alone with my undisciplined heart, had no
+conception of the wound with which it had to strive.
+
+The knowledge came upon me, not quickly, but little by little, and grain
+by grain. The desolate feeling with which I went abroad, deepened
+and widened hourly. At first it was a heavy sense of loss and sorrow,
+wherein I could distinguish little else. By imperceptible degrees,
+it became a hopeless consciousness of all that I had lost--love,
+friendship, interest; of all that had been shattered--my first trust,
+my first affection, the whole airy castle of my life; of all that
+remained--a ruined blank and waste, lying wide around me, unbroken, to
+the dark horizon.
+
+If my grief were selfish, I did not know it to be so. I mourned for my
+child-wife, taken from her blooming world, so young. I mourned for him
+who might have won the love and admiration of thousands, as he had won
+mine long ago. I mourned for the broken heart that had found rest in the
+stormy sea; and for the wandering remnants of the simple home, where I
+had heard the night-wind blowing, when I was a child.
+
+From the accumulated sadness into which I fell, I had at length no hope
+of ever issuing again. I roamed from place to place, carrying my burden
+with me everywhere. I felt its whole weight now; and I drooped beneath
+it, and I said in my heart that it could never be lightened.
+
+When this despondency was at its worst, I believed that I should die.
+Sometimes, I thought that I would like to die at home; and actually
+turned back on my road, that I might get there soon. At other times, I
+passed on farther away,--from city to city, seeking I know not what, and
+trying to leave I know not what behind.
+
+It is not in my power to retrace, one by one, all the weary phases of
+distress of mind through which I passed. There are some dreams that can
+only be imperfectly and vaguely described; and when I oblige myself to
+look back on this time of my life, I seem to be recalling such a dream.
+I see myself passing on among the novelties of foreign towns, palaces,
+cathedrals, temples, pictures, castles, tombs, fantastic streets--the
+old abiding places of History and Fancy--as a dreamer might; bearing my
+painful load through all, and hardly conscious of the objects as they
+fade before me. Listlessness to everything, but brooding sorrow, was the
+night that fell on my undisciplined heart. Let me look up from it--as
+at last I did, thank Heaven!--and from its long, sad, wretched dream, to
+dawn.
+
+For many months I travelled with this ever-darkening cloud upon my
+mind. Some blind reasons that I had for not returning home--reasons then
+struggling within me, vainly, for more distinct expression--kept me
+on my pilgrimage. Sometimes, I had proceeded restlessly from place to
+place, stopping nowhere; sometimes, I had lingered long in one spot. I
+had had no purpose, no sustaining soul within me, anywhere.
+
+I was in Switzerland. I had come out of Italy, over one of the great
+passes of the Alps, and had since wandered with a guide among the
+by-ways of the mountains. If those awful solitudes had spoken to my
+heart, I did not know it. I had found sublimity and wonder in the dread
+heights and precipices, in the roaring torrents, and the wastes of ice
+and snow; but as yet, they had taught me nothing else.
+
+I came, one evening before sunset, down into a valley, where I was to
+rest. In the course of my descent to it, by the winding track along
+the mountain-side, from which I saw it shining far below, I think some
+long-unwonted sense of beauty and tranquillity, some softening influence
+awakened by its peace, moved faintly in my breast. I remember pausing
+once, with a kind of sorrow that was not all oppressive, not quite
+despairing. I remember almost hoping that some better change was
+possible within me.
+
+I came into the valley, as the evening sun was shining on the remote
+heights of snow, that closed it in, like eternal clouds. The bases of
+the mountains forming the gorge in which the little village lay, were
+richly green; and high above this gentler vegetation, grew forests of
+dark fir, cleaving the wintry snow-drift, wedge-like, and stemming the
+avalanche. Above these, were range upon range of craggy steeps, grey
+rock, bright ice, and smooth verdure-specks of pasture, all gradually
+blending with the crowning snow. Dotted here and there on the
+mountain's-side, each tiny dot a home, were lonely wooden cottages, so
+dwarfed by the towering heights that they appeared too small for toys.
+So did even the clustered village in the valley, with its wooden bridge
+across the stream, where the stream tumbled over broken rocks, and
+roared away among the trees. In the quiet air, there was a sound of
+distant singing--shepherd voices; but, as one bright evening cloud
+floated midway along the mountain's-side, I could almost have believed
+it came from there, and was not earthly music. All at once, in this
+serenity, great Nature spoke to me; and soothed me to lay down my weary
+head upon the grass, and weep as I had not wept yet, since Dora died!
+
+I had found a packet of letters awaiting me but a few minutes before,
+and had strolled out of the village to read them while my supper was
+making ready. Other packets had missed me, and I had received none for a
+long time. Beyond a line or two, to say that I was well, and had arrived
+at such a place, I had not had fortitude or constancy to write a letter
+since I left home.
+
+The packet was in my hand. I opened it, and read the writing of Agnes.
+
+She was happy and useful, was prospering as she had hoped. That was all
+she told me of herself. The rest referred to me.
+
+She gave me no advice; she urged no duty on me; she only told me, in her
+own fervent manner, what her trust in me was. She knew (she said) how
+such a nature as mine would turn affliction to good. She knew how trial
+and emotion would exalt and strengthen it. She was sure that in my every
+purpose I should gain a firmer and a higher tendency, through the grief
+I had undergone. She, who so gloried in my fame, and so looked forward
+to its augmentation, well knew that I would labour on. She knew that in
+me, sorrow could not be weakness, but must be strength. As the endurance
+of my childish days had done its part to make me what I was, so greater
+calamities would nerve me on, to be yet better than I was; and so, as
+they had taught me, would I teach others. She commended me to God, who
+had taken my innocent darling to His rest; and in her sisterly affection
+cherished me always, and was always at my side go where I would; proud
+of what I had done, but infinitely prouder yet of what I was reserved to
+do.
+
+I put the letter in my breast, and thought what had I been an hour ago!
+When I heard the voices die away, and saw the quiet evening cloud grow
+dim, and all the colours in the valley fade, and the golden snow upon
+the mountain-tops become a remote part of the pale night sky, yet felt
+that the night was passing from my mind, and all its shadows clearing,
+there was no name for the love I bore her, dearer to me, henceforward,
+than ever until then.
+
+I read her letter many times. I wrote to her before I slept. I told her
+that I had been in sore need of her help; that without her I was not,
+and I never had been, what she thought me; but that she inspired me to
+be that, and I would try.
+
+I did try. In three months more, a year would have passed since the
+beginning of my sorrow. I determined to make no resolutions until the
+expiration of those three months, but to try. I lived in that valley,
+and its neighbourhood, all the time.
+
+The three months gone, I resolved to remain away from home for some
+time longer; to settle myself for the present in Switzerland, which was
+growing dear to me in the remembrance of that evening; to resume my pen;
+to work.
+
+I resorted humbly whither Agnes had commended me; I sought out Nature,
+never sought in vain; and I admitted to my breast the human interest
+I had lately shrunk from. It was not long, before I had almost as many
+friends in the valley as in Yarmouth: and when I left it, before the
+winter set in, for Geneva, and came back in the spring, their cordial
+greetings had a homely sound to me, although they were not conveyed in
+English words.
+
+I worked early and late, patiently and hard. I wrote a Story, with a
+purpose growing, not remotely, out of my experience, and sent it to
+Traddles, and he arranged for its publication very advantageously for
+me; and the tidings of my growing reputation began to reach me from
+travellers whom I encountered by chance. After some rest and change, I
+fell to work, in my old ardent way, on a new fancy, which took strong
+possession of me. As I advanced in the execution of this task, I felt it
+more and more, and roused my utmost energies to do it well. This was my
+third work of fiction. It was not half written, when, in an interval of
+rest, I thought of returning home.
+
+For a long time, though studying and working patiently, I had accustomed
+myself to robust exercise. My health, severely impaired when I left
+England, was quite restored. I had seen much. I had been in many
+countries, and I hope I had improved my store of knowledge.
+
+I have now recalled all that I think it needful to recall here, of this
+term of absence--with one reservation. I have made it, thus far, with
+no purpose of suppressing any of my thoughts; for, as I have elsewhere
+said, this narrative is my written memory. I have desired to keep the
+most secret current of my mind apart, and to the last. I enter on it
+now. I cannot so completely penetrate the mystery of my own heart, as
+to know when I began to think that I might have set its earliest and
+brightest hopes on Agnes. I cannot say at what stage of my grief
+it first became associated with the reflection, that, in my wayward
+boyhood, I had thrown away the treasure of her love. I believe I may
+have heard some whisper of that distant thought, in the old unhappy loss
+or want of something never to be realized, of which I had been sensible.
+But the thought came into my mind as a new reproach and new regret, when
+I was left so sad and lonely in the world.
+
+If, at that time, I had been much with her, I should, in the weakness of
+my desolation, have betrayed this. It was what I remotely dreaded when I
+was first impelled to stay away from England. I could not have borne
+to lose the smallest portion of her sisterly affection; yet, in that
+betrayal, I should have set a constraint between us hitherto unknown.
+
+I could not forget that the feeling with which she now regarded me had
+grown up in my own free choice and course. That if she had ever loved me
+with another love--and I sometimes thought the time was when she might
+have done so--I had cast it away. It was nothing, now, that I had
+accustomed myself to think of her, when we were both mere children,
+as one who was far removed from my wild fancies. I had bestowed my
+passionate tenderness upon another object; and what I might have done,
+I had not done; and what Agnes was to me, I and her own noble heart had
+made her.
+
+In the beginning of the change that gradually worked in me, when I
+tried to get a better understanding of myself and be a better man, I
+did glance, through some indefinite probation, to a period when I might
+possibly hope to cancel the mistaken past, and to be so blessed as
+to marry her. But, as time wore on, this shadowy prospect faded, and
+departed from me. If she had ever loved me, then, I should hold her
+the more sacred; remembering the confidences I had reposed in her, her
+knowledge of my errant heart, the sacrifice she must have made to be my
+friend and sister, and the victory she had won. If she had never loved
+me, could I believe that she would love me now?
+
+I had always felt my weakness, in comparison with her constancy and
+fortitude; and now I felt it more and more. Whatever I might have been
+to her, or she to me, if I had been more worthy of her long ago, I was
+not now, and she was not. The time was past. I had let it go by, and had
+deservedly lost her.
+
+That I suffered much in these contentions, that they filled me with
+unhappiness and remorse, and yet that I had a sustaining sense that it
+was required of me, in right and honour, to keep away from myself, with
+shame, the thought of turning to the dear girl in the withering of my
+hopes, from whom I had frivolously turned when they were bright and
+fresh--which consideration was at the root of every thought I had
+concerning her--is all equally true. I made no effort to conceal from
+myself, now, that I loved her, that I was devoted to her; but I brought
+the assurance home to myself, that it was now too late, and that our
+long-subsisting relation must be undisturbed.
+
+I had thought, much and often, of my Dora's shadowing out to me what
+might have happened, in those years that were destined not to try us;
+I had considered how the things that never happen, are often as much
+realities to us, in their effects, as those that are accomplished. The
+very years she spoke of, were realities now, for my correction; and
+would have been, one day, a little later perhaps, though we had parted
+in our earliest folly. I endeavoured to convert what might have been
+between myself and Agnes, into a means of making me more self-denying,
+more resolved, more conscious of myself, and my defects and errors.
+Thus, through the reflection that it might have been, I arrived at the
+conviction that it could never be.
+
+These, with their perplexities and inconsistencies, were the shifting
+quicksands of my mind, from the time of my departure to the time of my
+return home, three years afterwards. Three years had elapsed since the
+sailing of the emigrant ship; when, at that same hour of sunset, and in
+the same place, I stood on the deck of the packet vessel that brought me
+home, looking on the rosy water where I had seen the image of that ship
+reflected.
+
+Three years. Long in the aggregate, though short as they went by. And
+home was very dear to me, and Agnes too--but she was not mine--she was
+never to be mine. She might have been, but that was past!
+
+
+
+CHAPTER 59. RETURN
+
+
+I landed in London on a wintry autumn evening. It was dark and raining,
+and I saw more fog and mud in a minute than I had seen in a year. I
+walked from the Custom House to the Monument before I found a coach;
+and although the very house-fronts, looking on the swollen gutters, were
+like old friends to me, I could not but admit that they were very dingy
+friends.
+
+I have often remarked--I suppose everybody has--that one's going away
+from a familiar place, would seem to be the signal for change in it.
+As I looked out of the coach window, and observed that an old house on
+Fish-street Hill, which had stood untouched by painter, carpenter, or
+bricklayer, for a century, had been pulled down in my absence; and that
+a neighbouring street, of time-honoured insalubrity and inconvenience,
+was being drained and widened; I half expected to find St. Paul's
+Cathedral looking older.
+
+For some changes in the fortunes of my friends, I was prepared. My aunt
+had long been re-established at Dover, and Traddles had begun to get
+into some little practice at the Bar, in the very first term after my
+departure. He had chambers in Gray's Inn, now; and had told me, in his
+last letters, that he was not without hopes of being soon united to the
+dearest girl in the world.
+
+They expected me home before Christmas; but had no idea of my returning
+so soon. I had purposely misled them, that I might have the pleasure of
+taking them by surprise. And yet, I was perverse enough to feel a chill
+and disappointment in receiving no welcome, and rattling, alone and
+silent, through the misty streets.
+
+The well-known shops, however, with their cheerful lights, did something
+for me; and when I alighted at the door of the Gray's Inn Coffee-house,
+I had recovered my spirits. It recalled, at first, that so-different
+time when I had put up at the Golden Cross, and reminded me of the
+changes that had come to pass since then; but that was natural.
+
+'Do you know where Mr. Traddles lives in the Inn?' I asked the waiter,
+as I warmed myself by the coffee-room fire.
+
+'Holborn Court, sir. Number two.'
+
+'Mr. Traddles has a rising reputation among the lawyers, I believe?'
+said I.
+
+'Well, sir,' returned the waiter, 'probably he has, sir; but I am not
+aware of it myself.'
+
+This waiter, who was middle-aged and spare, looked for help to a waiter
+of more authority--a stout, potential old man, with a double chin,
+in black breeches and stockings, who came out of a place like a
+churchwarden's pew, at the end of the coffee-room, where he kept company
+with a cash-box, a Directory, a Law-list, and other books and papers.
+
+'Mr. Traddles,' said the spare waiter. 'Number two in the Court.'
+
+The potential waiter waved him away, and turned, gravely, to me.
+
+'I was inquiring,' said I, 'whether Mr. Traddles, at number two in the
+Court, has not a rising reputation among the lawyers?'
+
+'Never heard his name,' said the waiter, in a rich husky voice.
+
+I felt quite apologetic for Traddles.
+
+'He's a young man, sure?' said the portentous waiter, fixing his eyes
+severely on me. 'How long has he been in the Inn?'
+
+'Not above three years,' said I.
+
+The waiter, who I supposed had lived in his churchwarden's pew for forty
+years, could not pursue such an insignificant subject. He asked me what
+I would have for dinner?
+
+I felt I was in England again, and really was quite cast down on
+Traddles's account. There seemed to be no hope for him. I meekly ordered
+a bit of fish and a steak, and stood before the fire musing on his
+obscurity.
+
+As I followed the chief waiter with my eyes, I could not help thinking
+that the garden in which he had gradually blown to be the flower he
+was, was an arduous place to rise in. It had such a prescriptive,
+stiff-necked, long-established, solemn, elderly air. I glanced about the
+room, which had had its sanded floor sanded, no doubt, in exactly the
+same manner when the chief waiter was a boy--if he ever was a boy,
+which appeared improbable; and at the shining tables, where I saw
+myself reflected, in unruffled depths of old mahogany; and at the lamps,
+without a flaw in their trimming or cleaning; and at the comfortable
+green curtains, with their pure brass rods, snugly enclosing the boxes;
+and at the two large coal fires, brightly burning; and at the rows of
+decanters, burly as if with the consciousness of pipes of expensive old
+port wine below; and both England, and the law, appeared to me to be
+very difficult indeed to be taken by storm. I went up to my bedroom
+to change my wet clothes; and the vast extent of that old wainscoted
+apartment (which was over the archway leading to the Inn, I remember),
+and the sedate immensity of the four-post bedstead, and the indomitable
+gravity of the chests of drawers, all seemed to unite in sternly
+frowning on the fortunes of Traddles, or on any such daring youth. I
+came down again to my dinner; and even the slow comfort of the meal,
+and the orderly silence of the place--which was bare of guests, the Long
+Vacation not yet being over--were eloquent on the audacity of Traddles,
+and his small hopes of a livelihood for twenty years to come.
+
+I had seen nothing like this since I went away, and it quite dashed my
+hopes for my friend. The chief waiter had had enough of me. He came near
+me no more; but devoted himself to an old gentleman in long gaiters, to
+meet whom a pint of special port seemed to come out of the cellar of its
+own accord, for he gave no order. The second waiter informed me, in a
+whisper, that this old gentleman was a retired conveyancer living in the
+Square, and worth a mint of money, which it was expected he would leave
+to his laundress's daughter; likewise that it was rumoured that he had
+a service of plate in a bureau, all tarnished with lying by, though more
+than one spoon and a fork had never yet been beheld in his chambers
+by mortal vision. By this time, I quite gave Traddles up for lost; and
+settled in my own mind that there was no hope for him.
+
+Being very anxious to see the dear old fellow, nevertheless, I
+dispatched my dinner, in a manner not at all calculated to raise me in
+the opinion of the chief waiter, and hurried out by the back way. Number
+two in the Court was soon reached; and an inscription on the door-post
+informing me that Mr. Traddles occupied a set of chambers on the top
+storey, I ascended the staircase. A crazy old staircase I found it to
+be, feebly lighted on each landing by a club--headed little oil wick,
+dying away in a little dungeon of dirty glass.
+
+In the course of my stumbling upstairs, I fancied I heard a pleasant
+sound of laughter; and not the laughter of an attorney or barrister, or
+attorney's clerk or barrister's clerk, but of two or three merry girls.
+Happening, however, as I stopped to listen, to put my foot in a hole
+where the Honourable Society of Gray's Inn had left a plank deficient,
+I fell down with some noise, and when I recovered my footing all was
+silent.
+
+Groping my way more carefully, for the rest of the journey, my heart
+beat high when I found the outer door, which had Mr. TRADDLES painted on
+it, open. I knocked. A considerable scuffling within ensued, but nothing
+else. I therefore knocked again.
+
+A small sharp-looking lad, half-footboy and half-clerk, who was very
+much out of breath, but who looked at me as if he defied me to prove it
+legally, presented himself.
+
+'Is Mr. Traddles within?' I said.
+
+'Yes, sir, but he's engaged.'
+
+'I want to see him.'
+
+After a moment's survey of me, the sharp-looking lad decided to let me
+in; and opening the door wider for that purpose, admitted me, first,
+into a little closet of a hall, and next into a little sitting-room;
+where I came into the presence of my old friend (also out of breath),
+seated at a table, and bending over papers.
+
+'Good God!' cried Traddles, looking up. 'It's Copperfield!' and rushed
+into my arms, where I held him tight.
+
+'All well, my dear Traddles?'
+
+'All well, my dear, dear Copperfield, and nothing but good news!'
+
+We cried with pleasure, both of us.
+
+'My dear fellow,' said Traddles, rumpling his hair in his excitement,
+which was a most unnecessary operation, 'my dearest Copperfield, my
+long-lost and most welcome friend, how glad I am to see you! How
+brown you are! How glad I am! Upon my life and honour, I never was so
+rejoiced, my beloved Copperfield, never!'
+
+I was equally at a loss to express my emotions. I was quite unable to
+speak, at first.
+
+'My dear fellow!' said Traddles. 'And grown so famous! My glorious
+Copperfield! Good gracious me, WHEN did you come, WHERE have you come
+from, WHAT have you been doing?'
+
+Never pausing for an answer to anything he said, Traddles, who had
+clapped me into an easy-chair by the fire, all this time impetuously
+stirred the fire with one hand, and pulled at my neck-kerchief with
+the other, under some wild delusion that it was a great-coat. Without
+putting down the poker, he now hugged me again; and I hugged him; and,
+both laughing, and both wiping our eyes, we both sat down, and shook
+hands across the hearth.
+
+'To think,' said Traddles, 'that you should have been so nearly coming
+home as you must have been, my dear old boy, and not at the ceremony!'
+
+'What ceremony, my dear Traddles?'
+
+'Good gracious me!' cried Traddles, opening his eyes in his old way.
+'Didn't you get my last letter?'
+
+'Certainly not, if it referred to any ceremony.'
+
+'Why, my dear Copperfield,' said Traddles, sticking his hair upright
+with both hands, and then putting his hands on my knees, 'I am married!'
+
+'Married!' I cried joyfully.
+
+'Lord bless me, yes!' said Traddles--'by the Reverend Horace--to
+Sophy--down in Devonshire. Why, my dear boy, she's behind the window
+curtain! Look here!'
+
+To my amazement, the dearest girl in the world came at that same
+instant, laughing and blushing, from her place of concealment. And a
+more cheerful, amiable, honest, happy, bright-looking bride, I believe
+(as I could not help saying on the spot) the world never saw. I kissed
+her as an old acquaintance should, and wished them joy with all my might
+of heart.
+
+'Dear me,' said Traddles, 'what a delightful re-union this is! You are
+so extremely brown, my dear Copperfield! God bless my soul, how happy I
+am!'
+
+'And so am I,' said I.
+
+'And I am sure I am!' said the blushing and laughing Sophy.
+
+'We are all as happy as possible!' said Traddles. 'Even the girls are
+happy. Dear me, I declare I forgot them!'
+
+'Forgot?' said I.
+
+'The girls,' said Traddles. 'Sophy's sisters. They are staying with us.
+They have come to have a peep at London. The fact is, when--was it you
+that tumbled upstairs, Copperfield?'
+
+'It was,' said I, laughing.
+
+'Well then, when you tumbled upstairs,' said Traddles, 'I was romping
+with the girls. In point of fact, we were playing at Puss in the Corner.
+But as that wouldn't do in Westminster Hall, and as it wouldn't look
+quite professional if they were seen by a client, they decamped. And
+they are now--listening, I have no doubt,' said Traddles, glancing at
+the door of another room.
+
+'I am sorry,' said I, laughing afresh, 'to have occasioned such a
+dispersion.'
+
+'Upon my word,' rejoined Traddles, greatly delighted, 'if you had seen
+them running away, and running back again, after you had knocked, to
+pick up the combs they had dropped out of their hair, and going on in
+the maddest manner, you wouldn't have said so. My love, will you fetch
+the girls?'
+
+Sophy tripped away, and we heard her received in the adjoining room with
+a peal of laughter.
+
+'Really musical, isn't it, my dear Copperfield?' said Traddles. 'It's
+very agreeable to hear. It quite lights up these old rooms. To an
+unfortunate bachelor of a fellow who has lived alone all his life, you
+know, it's positively delicious. It's charming. Poor things, they have
+had a great loss in Sophy--who, I do assure you, Copperfield is, and
+ever was, the dearest girl!--and it gratifies me beyond expression
+to find them in such good spirits. The society of girls is a very
+delightful thing, Copperfield. It's not professional, but it's very
+delightful.'
+
+Observing that he slightly faltered, and comprehending that in the
+goodness of his heart he was fearful of giving me some pain by what he
+had said, I expressed my concurrence with a heartiness that evidently
+relieved and pleased him greatly.
+
+'But then,' said Traddles, 'our domestic arrangements are, to say
+the truth, quite unprofessional altogether, my dear Copperfield. Even
+Sophy's being here, is unprofessional. And we have no other place of
+abode. We have put to sea in a cockboat, but we are quite prepared to
+rough it. And Sophy's an extraordinary manager! You'll be surprised how
+those girls are stowed away. I am sure I hardly know how it's done!'
+
+'Are many of the young ladies with you?' I inquired.
+
+'The eldest, the Beauty is here,' said Traddles, in a low confidential
+voice, 'Caroline. And Sarah's here--the one I mentioned to you as having
+something the matter with her spine, you know. Immensely better! And the
+two youngest that Sophy educated are with us. And Louisa's here.'
+
+'Indeed!' cried I.
+
+'Yes,' said Traddles. 'Now the whole set--I mean the chambers--is only
+three rooms; but Sophy arranges for the girls in the most wonderful way,
+and they sleep as comfortably as possible. Three in that room,' said
+Traddles, pointing. 'Two in that.'
+
+I could not help glancing round, in search of the accommodation
+remaining for Mr. and Mrs. Traddles. Traddles understood me.
+
+'Well!' said Traddles, 'we are prepared to rough it, as I said just now,
+and we did improvise a bed last week, upon the floor here. But there's
+a little room in the roof--a very nice room, when you're up there--which
+Sophy papered herself, to surprise me; and that's our room at present.
+It's a capital little gipsy sort of place. There's quite a view from
+it.'
+
+'And you are happily married at last, my dear Traddles!' said I. 'How
+rejoiced I am!'
+
+'Thank you, my dear Copperfield,' said Traddles, as we shook hands
+once more. 'Yes, I am as happy as it's possible to be. There's your old
+friend, you see,' said Traddles, nodding triumphantly at the flower-pot
+and stand; 'and there's the table with the marble top! All the other
+furniture is plain and serviceable, you perceive. And as to plate, Lord
+bless you, we haven't so much as a tea-spoon.'
+
+'All to be earned?' said I, cheerfully.
+
+'Exactly so,' replied Traddles, 'all to be earned. Of course we have
+something in the shape of tea-spoons, because we stir our tea. But
+they're Britannia metal.'
+
+'The silver will be the brighter when it comes,' said I.
+
+'The very thing we say!' cried Traddles. 'You see, my dear Copperfield,'
+falling again into the low confidential tone, 'after I had delivered my
+argument in DOE dem. JIPES versus WIGZIELL, which did me great service
+with the profession, I went down into Devonshire, and had some serious
+conversation in private with the Reverend Horace. I dwelt upon the fact
+that Sophy--who I do assure you, Copperfield, is the dearest girl!--'
+
+'I am certain she is!' said I.
+
+'She is, indeed!' rejoined Traddles. 'But I am afraid I am wandering
+from the subject. Did I mention the Reverend Horace?'
+
+'You said that you dwelt upon the fact--'
+
+'True! Upon the fact that Sophy and I had been engaged for a long
+period, and that Sophy, with the permission of her parents, was more
+than content to take me--in short,' said Traddles, with his old frank
+smile, 'on our present Britannia-metal footing. Very well. I then
+proposed to the Reverend Horace--who is a most excellent clergyman,
+Copperfield, and ought to be a Bishop; or at least ought to have enough
+to live upon, without pinching himself--that if I could turn the corner,
+say of two hundred and fifty pounds, in one year; and could see my
+way pretty clearly to that, or something better, next year; and could
+plainly furnish a little place like this, besides; then, and in that
+case, Sophy and I should be united. I took the liberty of representing
+that we had been patient for a good many years; and that the
+circumstance of Sophy's being extraordinarily useful at home, ought not
+to operate with her affectionate parents, against her establishment in
+life--don't you see?'
+
+'Certainly it ought not,' said I.
+
+'I am glad you think so, Copperfield,' rejoined Traddles, 'because,
+without any imputation on the Reverend Horace, I do think parents, and
+brothers, and so forth, are sometimes rather selfish in such cases.
+Well! I also pointed out, that my most earnest desire was, to be useful
+to the family; and that if I got on in the world, and anything should
+happen to him--I refer to the Reverend Horace--'
+
+'I understand,' said I.
+
+'--Or to Mrs. Crewler--it would be the utmost gratification of my
+wishes, to be a parent to the girls. He replied in a most admirable
+manner, exceedingly flattering to my feelings, and undertook to obtain
+the consent of Mrs. Crewler to this arrangement. They had a dreadful
+time of it with her. It mounted from her legs into her chest, and then
+into her head--'
+
+'What mounted?' I asked.
+
+'Her grief,' replied Traddles, with a serious look. 'Her feelings
+generally. As I mentioned on a former occasion, she is a very superior
+woman, but has lost the use of her limbs. Whatever occurs to harass
+her, usually settles in her legs; but on this occasion it mounted to the
+chest, and then to the head, and, in short, pervaded the whole system
+in a most alarming manner. However, they brought her through it by
+unremitting and affectionate attention; and we were married yesterday
+six weeks. You have no idea what a Monster I felt, Copperfield, when I
+saw the whole family crying and fainting away in every direction! Mrs.
+Crewler couldn't see me before we left--couldn't forgive me, then, for
+depriving her of her child--but she is a good creature, and has done so
+since. I had a delightful letter from her, only this morning.'
+
+'And in short, my dear friend,' said I, 'you feel as blest as you
+deserve to feel!'
+
+'Oh! That's your partiality!' laughed Traddles. 'But, indeed, I am in a
+most enviable state. I work hard, and read Law insatiably. I get up at
+five every morning, and don't mind it at all. I hide the girls in the
+daytime, and make merry with them in the evening. And I assure you I am
+quite sorry that they are going home on Tuesday, which is the day before
+the first day of Michaelmas Term. But here,' said Traddles, breaking off
+in his confidence, and speaking aloud, 'ARE the girls! Mr. Copperfield,
+Miss Crewler--Miss Sarah--Miss Louisa--Margaret and Lucy!'
+
+They were a perfect nest of roses; they looked so wholesome and fresh.
+They were all pretty, and Miss Caroline was very handsome; but there was
+a loving, cheerful, fireside quality in Sophy's bright looks, which was
+better than that, and which assured me that my friend had chosen well.
+We all sat round the fire; while the sharp boy, who I now divined had
+lost his breath in putting the papers out, cleared them away again, and
+produced the tea-things. After that, he retired for the night, shutting
+the outer door upon us with a bang. Mrs. Traddles, with perfect pleasure
+and composure beaming from her household eyes, having made the tea, then
+quietly made the toast as she sat in a corner by the fire.
+
+She had seen Agnes, she told me while she was toasting. 'Tom' had taken
+her down into Kent for a wedding trip, and there she had seen my aunt,
+too; and both my aunt and Agnes were well, and they had all talked of
+nothing but me. 'Tom' had never had me out of his thoughts, she really
+believed, all the time I had been away. 'Tom' was the authority for
+everything. 'Tom' was evidently the idol of her life; never to be shaken
+on his pedestal by any commotion; always to be believed in, and done
+homage to with the whole faith of her heart, come what might.
+
+The deference which both she and Traddles showed towards the Beauty,
+pleased me very much. I don't know that I thought it very reasonable;
+but I thought it very delightful, and essentially a part of their
+character. If Traddles ever for an instant missed the tea-spoons that
+were still to be won, I have no doubt it was when he handed the Beauty
+her tea. If his sweet-tempered wife could have got up any self-assertion
+against anyone, I am satisfied it could only have been because she was
+the Beauty's sister. A few slight indications of a rather petted and
+capricious manner, which I observed in the Beauty, were manifestly
+considered, by Traddles and his wife, as her birthright and natural
+endowment. If she had been born a Queen Bee, and they labouring Bees,
+they could not have been more satisfied of that.
+
+But their self-forgetfulness charmed me. Their pride in these girls, and
+their submission of themselves to all their whims, was the pleasantest
+little testimony to their own worth I could have desired to see. If
+Traddles were addressed as 'a darling', once in the course of that
+evening; and besought to bring something here, or carry something there,
+or take something up, or put something down, or find something, or fetch
+something, he was so addressed, by one or other of his sisters-in-law,
+at least twelve times in an hour. Neither could they do anything without
+Sophy. Somebody's hair fell down, and nobody but Sophy could put it up.
+Somebody forgot how a particular tune went, and nobody but Sophy could
+hum that tune right. Somebody wanted to recall the name of a place in
+Devonshire, and only Sophy knew it. Something was wanted to be written
+home, and Sophy alone could be trusted to write before breakfast in
+the morning. Somebody broke down in a piece of knitting, and no one but
+Sophy was able to put the defaulter in the right direction. They were
+entire mistresses of the place, and Sophy and Traddles waited on them.
+How many children Sophy could have taken care of in her time, I can't
+imagine; but she seemed to be famous for knowing every sort of song that
+ever was addressed to a child in the English tongue; and she sang dozens
+to order with the clearest little voice in the world, one after another
+(every sister issuing directions for a different tune, and the Beauty
+generally striking in last), so that I was quite fascinated. The best
+of all was, that, in the midst of their exactions, all the sisters had
+a great tenderness and respect both for Sophy and Traddles. I am sure,
+when I took my leave, and Traddles was coming out to walk with me to the
+coffee-house, I thought I had never seen an obstinate head of hair, or
+any other head of hair, rolling about in such a shower of kisses.
+
+Altogether, it was a scene I could not help dwelling on with pleasure,
+for a long time after I got back and had wished Traddles good night. If
+I had beheld a thousand roses blowing in a top set of chambers, in that
+withered Gray's Inn, they could not have brightened it half so much.
+The idea of those Devonshire girls, among the dry law-stationers and the
+attorneys' offices; and of the tea and toast, and children's songs, in
+that grim atmosphere of pounce and parchment, red-tape, dusty wafers,
+ink-jars, brief and draft paper, law reports, writs, declarations, and
+bills of costs; seemed almost as pleasantly fanciful as if I had
+dreamed that the Sultan's famous family had been admitted on the roll of
+attorneys, and had brought the talking bird, the singing tree, and the
+golden water into Gray's Inn Hall. Somehow, I found that I had taken
+leave of Traddles for the night, and come back to the coffee-house, with
+a great change in my despondency about him. I began to think he would
+get on, in spite of all the many orders of chief waiters in England.
+
+Drawing a chair before one of the coffee-room fires to think about him
+at my leisure, I gradually fell from the consideration of his happiness
+to tracing prospects in the live-coals, and to thinking, as they broke
+and changed, of the principal vicissitudes and separations that had
+marked my life. I had not seen a coal fire, since I had left England
+three years ago: though many a wood fire had I watched, as it crumbled
+into hoary ashes, and mingled with the feathery heap upon the hearth,
+which not inaptly figured to me, in my despondency, my own dead hopes.
+
+I could think of the past now, gravely, but not bitterly; and could
+contemplate the future in a brave spirit. Home, in its best sense, was
+for me no more. She in whom I might have inspired a dearer love, I had
+taught to be my sister. She would marry, and would have new claimants on
+her tenderness; and in doing it, would never know the love for her that
+had grown up in my heart. It was right that I should pay the forfeit of
+my headlong passion. What I reaped, I had sown.
+
+I was thinking. And had I truly disciplined my heart to this, and could
+I resolutely bear it, and calmly hold the place in her home which she
+had calmly held in mine,--when I found my eyes resting on a countenance
+that might have arisen out of the fire, in its association with my early
+remembrances.
+
+Little Mr. Chillip the Doctor, to whose good offices I was indebted in
+the very first chapter of this history, sat reading a newspaper in the
+shadow of an opposite corner. He was tolerably stricken in years by this
+time; but, being a mild, meek, calm little man, had worn so easily, that
+I thought he looked at that moment just as he might have looked when he
+sat in our parlour, waiting for me to be born.
+
+Mr. Chillip had left Blunderstone six or seven years ago, and I had
+never seen him since. He sat placidly perusing the newspaper, with his
+little head on one side, and a glass of warm sherry negus at his
+elbow. He was so extremely conciliatory in his manner that he seemed to
+apologize to the very newspaper for taking the liberty of reading it.
+
+I walked up to where he was sitting, and said, 'How do you do, Mr.
+Chillip?'
+
+He was greatly fluttered by this unexpected address from a stranger, and
+replied, in his slow way, 'I thank you, sir, you are very good. Thank
+you, sir. I hope YOU are well.'
+
+'You don't remember me?' said I.
+
+'Well, sir,' returned Mr. Chillip, smiling very meekly, and shaking his
+head as he surveyed me, 'I have a kind of an impression that something
+in your countenance is familiar to me, sir; but I couldn't lay my hand
+upon your name, really.'
+
+'And yet you knew it, long before I knew it myself,' I returned.
+
+'Did I indeed, sir?' said Mr. Chillip. 'Is it possible that I had the
+honour, sir, of officiating when--?'
+
+'Yes,' said I.
+
+'Dear me!' cried Mr. Chillip. 'But no doubt you are a good deal changed
+since then, sir?'
+
+'Probably,' said I.
+
+'Well, sir,' observed Mr. Chillip, 'I hope you'll excuse me, if I am
+compelled to ask the favour of your name?'
+
+On my telling him my name, he was really moved. He quite shook hands
+with me--which was a violent proceeding for him, his usual course being
+to slide a tepid little fish-slice, an inch or two in advance of his
+hip, and evince the greatest discomposure when anybody grappled with
+it. Even now, he put his hand in his coat-pocket as soon as he could
+disengage it, and seemed relieved when he had got it safe back.
+
+'Dear me, sir!' said Mr. Chillip, surveying me with his head on one
+side. 'And it's Mr. Copperfield, is it? Well, sir, I think I should have
+known you, if I had taken the liberty of looking more closely at you.
+There's a strong resemblance between you and your poor father, sir.'
+
+'I never had the happiness of seeing my father,' I observed.
+
+'Very true, sir,' said Mr. Chillip, in a soothing tone. 'And very much
+to be deplored it was, on all accounts! We are not ignorant, sir,' said
+Mr. Chillip, slowly shaking his little head again, 'down in our part of
+the country, of your fame. There must be great excitement here, sir,'
+said Mr. Chillip, tapping himself on the forehead with his forefinger.
+'You must find it a trying occupation, sir!'
+
+'What is your part of the country now?' I asked, seating myself near
+him.
+
+'I am established within a few miles of Bury St. Edmund's, sir,' said
+Mr. Chillip. 'Mrs. Chillip, coming into a little property in that
+neighbourhood, under her father's will, I bought a practice down there,
+in which you will be glad to hear I am doing well. My daughter is
+growing quite a tall lass now, sir,' said Mr. Chillip, giving his little
+head another little shake. 'Her mother let down two tucks in her frocks
+only last week. Such is time, you see, sir!'
+
+As the little man put his now empty glass to his lips, when he made this
+reflection, I proposed to him to have it refilled, and I would keep him
+company with another. 'Well, sir,' he returned, in his slow way, 'it's
+more than I am accustomed to; but I can't deny myself the pleasure
+of your conversation. It seems but yesterday that I had the honour of
+attending you in the measles. You came through them charmingly, sir!'
+
+I acknowledged this compliment, and ordered the negus, which was soon
+produced. 'Quite an uncommon dissipation!' said Mr. Chillip, stirring
+it, 'but I can't resist so extraordinary an occasion. You have no
+family, sir?'
+
+I shook my head.
+
+'I was aware that you sustained a bereavement, sir, some time ago,' said
+Mr. Chillip. 'I heard it from your father-in-law's sister. Very decided
+character there, sir?'
+
+'Why, yes,' said I, 'decided enough. Where did you see her, Mr.
+Chillip?'
+
+'Are you not aware, sir,' returned Mr. Chillip, with his placidest
+smile, 'that your father-in-law is again a neighbour of mine?'
+
+'No,' said I.
+
+'He is indeed, sir!' said Mr. Chillip. 'Married a young lady of that
+part, with a very good little property, poor thing.---And this action
+of the brain now, sir? Don't you find it fatigue you?' said Mr. Chillip,
+looking at me like an admiring Robin.
+
+I waived that question, and returned to the Murdstones. 'I was aware of
+his being married again. Do you attend the family?' I asked.
+
+'Not regularly. I have been called in,' he replied. 'Strong
+phrenological developments of the organ of firmness, in Mr. Murdstone
+and his sister, sir.'
+
+I replied with such an expressive look, that Mr. Chillip was emboldened
+by that, and the negus together, to give his head several short shakes,
+and thoughtfully exclaim, 'Ah, dear me! We remember old times, Mr.
+Copperfield!'
+
+'And the brother and sister are pursuing their old course, are they?'
+said I.
+
+'Well, sir,' replied Mr. Chillip, 'a medical man, being so much in
+families, ought to have neither eyes nor ears for anything but his
+profession. Still, I must say, they are very severe, sir: both as to
+this life and the next.'
+
+'The next will be regulated without much reference to them, I dare say,'
+I returned: 'what are they doing as to this?'
+
+Mr. Chillip shook his head, stirred his negus, and sipped it.
+
+'She was a charming woman, sir!' he observed in a plaintive manner.
+
+'The present Mrs. Murdstone?'
+
+A charming woman indeed, sir,' said Mr. Chillip; 'as amiable, I am sure,
+as it was possible to be! Mrs. Chillip's opinion is, that her spirit
+has been entirely broken since her marriage, and that she is all but
+melancholy mad. And the ladies,' observed Mr. Chillip, timorously, 'are
+great observers, sir.'
+
+'I suppose she was to be subdued and broken to their detestable mould,
+Heaven help her!' said I. 'And she has been.'
+
+'Well, sir, there were violent quarrels at first, I assure you,' said
+Mr. Chillip; 'but she is quite a shadow now. Would it be considered
+forward if I was to say to you, sir, in confidence, that since the
+sister came to help, the brother and sister between them have nearly
+reduced her to a state of imbecility?'
+
+I told him I could easily believe it.
+
+'I have no hesitation in saying,' said Mr. Chillip, fortifying himself
+with another sip of negus, 'between you and me, sir, that her mother
+died of it--or that tyranny, gloom, and worry have made Mrs. Murdstone
+nearly imbecile. She was a lively young woman, sir, before marriage, and
+their gloom and austerity destroyed her. They go about with her, now,
+more like her keepers than her husband and sister-in-law. That was
+Mrs. Chillip's remark to me, only last week. And I assure you, sir, the
+ladies are great observers. Mrs. Chillip herself is a great observer!'
+
+'Does he gloomily profess to be (I am ashamed to use the word in such
+association) religious still?' I inquired.
+
+'You anticipate, sir,' said Mr. Chillip, his eyelids getting quite
+red with the unwonted stimulus in which he was indulging. 'One of Mrs.
+Chillip's most impressive remarks. Mrs. Chillip,' he proceeded, in the
+calmest and slowest manner, 'quite electrified me, by pointing out
+that Mr. Murdstone sets up an image of himself, and calls it the Divine
+Nature. You might have knocked me down on the flat of my back, sir,
+with the feather of a pen, I assure you, when Mrs. Chillip said so. The
+ladies are great observers, sir?'
+
+'Intuitively,' said I, to his extreme delight.
+
+'I am very happy to receive such support in my opinion, sir,' he
+rejoined. 'It is not often that I venture to give a non-medical opinion,
+I assure you. Mr. Murdstone delivers public addresses sometimes, and it
+is said,--in short, sir, it is said by Mrs. Chillip,--that the darker
+tyrant he has lately been, the more ferocious is his doctrine.'
+
+'I believe Mrs. Chillip to be perfectly right,' said I.
+
+'Mrs. Chillip does go so far as to say,' pursued the meekest of little
+men, much encouraged, 'that what such people miscall their religion, is
+a vent for their bad humours and arrogance. And do you know I must say,
+sir,' he continued, mildly laying his head on one side, 'that I DON'T
+find authority for Mr. and Miss Murdstone in the New Testament?'
+
+'I never found it either!' said I.
+
+'In the meantime, sir,' said Mr. Chillip, 'they are much disliked;
+and as they are very free in consigning everybody who dislikes them
+to perdition, we really have a good deal of perdition going on in
+our neighbourhood! However, as Mrs. Chillip says, sir, they undergo a
+continual punishment; for they are turned inward, to feed upon their own
+hearts, and their own hearts are very bad feeding. Now, sir, about that
+brain of yours, if you'll excuse my returning to it. Don't you expose it
+to a good deal of excitement, sir?'
+
+I found it not difficult, in the excitement of Mr. Chillip's own brain,
+under his potations of negus, to divert his attention from this topic
+to his own affairs, on which, for the next half-hour, he was quite
+loquacious; giving me to understand, among other pieces of information,
+that he was then at the Gray's Inn Coffee-house to lay his professional
+evidence before a Commission of Lunacy, touching the state of mind of a
+patient who had become deranged from excessive drinking. 'And I assure
+you, sir,' he said, 'I am extremely nervous on such occasions. I could
+not support being what is called Bullied, sir. It would quite unman
+me. Do you know it was some time before I recovered the conduct of that
+alarming lady, on the night of your birth, Mr. Copperfield?'
+
+I told him that I was going down to my aunt, the Dragon of that night,
+early in the morning; and that she was one of the most tender-hearted
+and excellent of women, as he would know full well if he knew her
+better. The mere notion of the possibility of his ever seeing her again,
+appeared to terrify him. He replied with a small pale smile, 'Is she so,
+indeed, sir? Really?' and almost immediately called for a candle, and
+went to bed, as if he were not quite safe anywhere else. He did not
+actually stagger under the negus; but I should think his placid little
+pulse must have made two or three more beats in a minute, than it had
+done since the great night of my aunt's disappointment, when she struck
+at him with her bonnet.
+
+Thoroughly tired, I went to bed too, at midnight; passed the next day on
+the Dover coach; burst safe and sound into my aunt's old parlour while
+she was at tea (she wore spectacles now); and was received by her, and
+Mr. Dick, and dear old Peggotty, who acted as housekeeper, with open
+arms and tears of joy. My aunt was mightily amused, when we began to
+talk composedly, by my account of my meeting with Mr. Chillip, and of
+his holding her in such dread remembrance; and both she and Peggotty
+had a great deal to say about my poor mother's second husband, and 'that
+murdering woman of a sister',--on whom I think no pain or penalty would
+have induced my aunt to bestow any Christian or Proper Name, or any
+other designation.
+
+
+
+CHAPTER 60. AGNES
+
+
+My aunt and I, when we were left alone, talked far into the night. How
+the emigrants never wrote home, otherwise than cheerfully and hopefully;
+how Mr. Micawber had actually remitted divers small sums of money, on
+account of those 'pecuniary liabilities', in reference to which he had
+been so business-like as between man and man; how Janet, returning into
+my aunt's service when she came back to Dover, had finally carried out
+her renunciation of mankind by entering into wedlock with a thriving
+tavern-keeper; and how my aunt had finally set her seal on the same
+great principle, by aiding and abetting the bride, and crowning the
+marriage-ceremony with her presence; were among our topics--already
+more or less familiar to me through the letters I had had. Mr. Dick,
+as usual, was not forgotten. My aunt informed me how he incessantly
+occupied himself in copying everything he could lay his hands on, and
+kept King Charles the First at a respectful distance by that semblance
+of employment; how it was one of the main joys and rewards of her life
+that he was free and happy, instead of pining in monotonous restraint;
+and how (as a novel general conclusion) nobody but she could ever fully
+know what he was.
+
+'And when, Trot,' said my aunt, patting the back of my hand, as we sat
+in our old way before the fire, 'when are you going over to Canterbury?'
+
+'I shall get a horse, and ride over tomorrow morning, aunt, unless you
+will go with me?'
+
+'No!' said my aunt, in her short abrupt way. 'I mean to stay where I
+am.'
+
+Then, I should ride, I said. I could not have come through Canterbury
+today without stopping, if I had been coming to anyone but her.
+
+She was pleased, but answered, 'Tut, Trot; MY old bones would have
+kept till tomorrow!' and softly patted my hand again, as I sat looking
+thoughtfully at the fire.
+
+Thoughtfully, for I could not be here once more, and so near Agnes,
+without the revival of those regrets with which I had so long been
+occupied. Softened regrets they might be, teaching me what I had failed
+to learn when my younger life was all before me, but not the less
+regrets. 'Oh, Trot,' I seemed to hear my aunt say once more; and I
+understood her better now--'Blind, blind, blind!'
+
+We both kept silence for some minutes. When I raised my eyes, I found
+that she was steadily observant of me. Perhaps she had followed the
+current of my mind; for it seemed to me an easy one to track now, wilful
+as it had been once.
+
+'You will find her father a white-haired old man,' said my aunt, 'though
+a better man in all other respects--a reclaimed man. Neither will you
+find him measuring all human interests, and joys, and sorrows, with his
+one poor little inch-rule now. Trust me, child, such things must shrink
+very much, before they can be measured off in that way.'
+
+'Indeed they must,' said I.
+
+'You will find her,' pursued my aunt, 'as good, as beautiful, as
+earnest, as disinterested, as she has always been. If I knew higher
+praise, Trot, I would bestow it on her.'
+
+There was no higher praise for her; no higher reproach for me. Oh, how
+had I strayed so far away!
+
+'If she trains the young girls whom she has about her, to be like
+herself,' said my aunt, earnest even to the filling of her eyes with
+tears, 'Heaven knows, her life will be well employed! Useful and happy,
+as she said that day! How could she be otherwise than useful and happy!'
+
+'Has Agnes any--' I was thinking aloud, rather than speaking.
+
+'Well? Hey? Any what?' said my aunt, sharply.
+
+'Any lover,' said I.
+
+'A score,' cried my aunt, with a kind of indignant pride. 'She might
+have married twenty times, my dear, since you have been gone!'
+
+'No doubt,' said I. 'No doubt. But has she any lover who is worthy of
+her? Agnes could care for no other.'
+
+My aunt sat musing for a little while, with her chin upon her hand.
+Slowly raising her eyes to mine, she said:
+
+'I suspect she has an attachment, Trot.'
+
+'A prosperous one?' said I.
+
+'Trot,' returned my aunt gravely, 'I can't say. I have no right to tell
+you even so much. She has never confided it to me, but I suspect it.'
+
+She looked so attentively and anxiously at me (I even saw her tremble),
+that I felt now, more than ever, that she had followed my late thoughts.
+I summoned all the resolutions I had made, in all those many days and
+nights, and all those many conflicts of my heart.
+
+'If it should be so,' I began, 'and I hope it is-'
+
+'I don't know that it is,' said my aunt curtly. 'You must not be ruled
+by my suspicions. You must keep them secret. They are very slight,
+perhaps. I have no right to speak.'
+
+'If it should be so,' I repeated, 'Agnes will tell me at her own good
+time. A sister to whom I have confided so much, aunt, will not be
+reluctant to confide in me.'
+
+My aunt withdrew her eyes from mine, as slowly as she had turned them
+upon me; and covered them thoughtfully with her hand. By and by she
+put her other hand on my shoulder; and so we both sat, looking into the
+past, without saying another word, until we parted for the night.
+
+I rode away, early in the morning, for the scene of my old school-days.
+I cannot say that I was yet quite happy, in the hope that I was gaining
+a victory over myself; even in the prospect of so soon looking on her
+face again.
+
+The well-remembered ground was soon traversed, and I came into the quiet
+streets, where every stone was a boy's book to me. I went on foot to the
+old house, and went away with a heart too full to enter. I returned; and
+looking, as I passed, through the low window of the turret-room where
+first Uriah Heep, and afterwards Mr. Micawber, had been wont to sit,
+saw that it was a little parlour now, and that there was no office.
+Otherwise the staid old house was, as to its cleanliness and order,
+still just as it had been when I first saw it. I requested the new maid
+who admitted me, to tell Miss Wickfield that a gentleman who waited on
+her from a friend abroad, was there; and I was shown up the grave old
+staircase (cautioned of the steps I knew so well), into the unchanged
+drawing-room. The books that Agnes and I had read together, were on
+their shelves; and the desk where I had laboured at my lessons, many
+a night, stood yet at the same old corner of the table. All the little
+changes that had crept in when the Heeps were there, were changed again.
+Everything was as it used to be, in the happy time.
+
+I stood in a window, and looked across the ancient street at the
+opposite houses, recalling how I had watched them on wet afternoons,
+when I first came there; and how I had used to speculate about the
+people who appeared at any of the windows, and had followed them with my
+eyes up and down stairs, while women went clicking along the pavement in
+pattens, and the dull rain fell in slanting lines, and poured out of the
+water-spout yonder, and flowed into the road. The feeling with which
+I used to watch the tramps, as they came into the town on those wet
+evenings, at dusk, and limped past, with their bundles drooping over
+their shoulders at the ends of sticks, came freshly back to me; fraught,
+as then, with the smell of damp earth, and wet leaves and briar, and the
+sensation of the very airs that blew upon me in my own toilsome journey.
+
+The opening of the little door in the panelled wall made me start and
+turn. Her beautiful serene eyes met mine as she came towards me. She
+stopped and laid her hand upon her bosom, and I caught her in my arms.
+
+'Agnes! my dear girl! I have come too suddenly upon you.'
+
+'No, no! I am so rejoiced to see you, Trotwood!'
+
+'Dear Agnes, the happiness it is to me, to see you once again!'
+
+I folded her to my heart, and, for a little while, we were both silent.
+Presently we sat down, side by side; and her angel-face was turned upon
+me with the welcome I had dreamed of, waking and sleeping, for whole
+years.
+
+She was so true, she was so beautiful, she was so good,--I owed her so
+much gratitude, she was so dear to me, that I could find no utterance
+for what I felt. I tried to bless her, tried to thank her, tried to tell
+her (as I had often done in letters) what an influence she had upon me;
+but all my efforts were in vain. My love and joy were dumb.
+
+With her own sweet tranquillity, she calmed my agitation; led me back to
+the time of our parting; spoke to me of Emily, whom she had visited,
+in secret, many times; spoke to me tenderly of Dora's grave. With the
+unerring instinct of her noble heart, she touched the chords of my
+memory so softly and harmoniously, that not one jarred within me; I
+could listen to the sorrowful, distant music, and desire to shrink from
+nothing it awoke. How could I, when, blended with it all, was her dear
+self, the better angel of my life?
+
+'And you, Agnes,' I said, by and by. 'Tell me of yourself. You have
+hardly ever told me of your own life, in all this lapse of time!'
+
+'What should I tell?' she answered, with her radiant smile. 'Papa is
+well. You see us here, quiet in our own home; our anxieties set at rest,
+our home restored to us; and knowing that, dear Trotwood, you know all.'
+
+'All, Agnes?' said I.
+
+She looked at me, with some fluttering wonder in her face.
+
+'Is there nothing else, Sister?' I said.
+
+Her colour, which had just now faded, returned, and faded again. She
+smiled; with a quiet sadness, I thought; and shook her head.
+
+I had sought to lead her to what my aunt had hinted at; for, sharply
+painful to me as it must be to receive that confidence, I was to
+discipline my heart, and do my duty to her. I saw, however, that she was
+uneasy, and I let it pass.
+
+'You have much to do, dear Agnes?'
+
+'With my school?' said she, looking up again, in all her bright
+composure.
+
+'Yes. It is laborious, is it not?'
+
+'The labour is so pleasant,' she returned, 'that it is scarcely grateful
+in me to call it by that name.'
+
+'Nothing good is difficult to you,' said I.
+
+Her colour came and went once more; and once more, as she bent her head,
+I saw the same sad smile.
+
+'You will wait and see papa,' said Agnes, cheerfully, 'and pass the
+day with us? Perhaps you will sleep in your own room? We always call it
+yours.'
+
+I could not do that, having promised to ride back to my aunt's at night;
+but I would pass the day there, joyfully.
+
+'I must be a prisoner for a little while,' said Agnes, 'but here are the
+old books, Trotwood, and the old music.'
+
+'Even the old flowers are here,' said I, looking round; 'or the old
+kinds.'
+
+'I have found a pleasure,' returned Agnes, smiling, 'while you have been
+absent, in keeping everything as it used to be when we were children.
+For we were very happy then, I think.'
+
+'Heaven knows we were!' said I.
+
+'And every little thing that has reminded me of my brother,' said Agnes,
+with her cordial eyes turned cheerfully upon me, 'has been a welcome
+companion. Even this,' showing me the basket-trifle, full of keys, still
+hanging at her side, 'seems to jingle a kind of old tune!'
+
+She smiled again, and went out at the door by which she had come.
+
+It was for me to guard this sisterly affection with religious care. It
+was all that I had left myself, and it was a treasure. If I once shook
+the foundations of the sacred confidence and usage, in virtue of which
+it was given to me, it was lost, and could never be recovered. I set
+this steadily before myself. The better I loved her, the more it behoved
+me never to forget it.
+
+I walked through the streets; and, once more seeing my old adversary the
+butcher--now a constable, with his staff hanging up in the shop--went
+down to look at the place where I had fought him; and there meditated
+on Miss Shepherd and the eldest Miss Larkins, and all the idle loves and
+likings, and dislikings, of that time. Nothing seemed to have survived
+that time but Agnes; and she, ever a star above me, was brighter and
+higher.
+
+When I returned, Mr. Wickfield had come home, from a garden he had, a
+couple of miles or so out of town, where he now employed himself almost
+every day. I found him as my aunt had described him. We sat down to
+dinner, with some half-dozen little girls; and he seemed but the shadow
+of his handsome picture on the wall.
+
+The tranquillity and peace belonging, of old, to that quiet ground in my
+memory, pervaded it again. When dinner was done, Mr. Wickfield taking no
+wine, and I desiring none, we went up-stairs; where Agnes and her little
+charges sang and played, and worked. After tea the children left us; and
+we three sat together, talking of the bygone days.
+
+'My part in them,' said Mr. Wickfield, shaking his white head, 'has much
+matter for regret--for deep regret, and deep contrition, Trotwood, you
+well know. But I would not cancel it, if it were in my power.'
+
+I could readily believe that, looking at the face beside him.
+
+'I should cancel with it,' he pursued, 'such patience and devotion, such
+fidelity, such a child's love, as I must not forget, no! even to forget
+myself.'
+
+'I understand you, sir,' I softly said. 'I hold it--I have always held
+it--in veneration.'
+
+'But no one knows, not even you,' he returned, 'how much she has done,
+how much she has undergone, how hard she has striven. Dear Agnes!'
+
+She had put her hand entreatingly on his arm, to stop him; and was very,
+very pale.
+
+'Well, well!' he said with a sigh, dismissing, as I then saw, some trial
+she had borne, or was yet to bear, in connexion with what my aunt had
+told me. 'Well! I have never told you, Trotwood, of her mother. Has
+anyone?'
+
+'Never, sir.'
+
+'It's not much--though it was much to suffer. She married me in
+opposition to her father's wish, and he renounced her. She prayed him
+to forgive her, before my Agnes came into this world. He was a very hard
+man, and her mother had long been dead. He repulsed her. He broke her
+heart.'
+
+Agnes leaned upon his shoulder, and stole her arm about his neck.
+
+'She had an affectionate and gentle heart,' he said; 'and it was broken.
+I knew its tender nature very well. No one could, if I did not. She
+loved me dearly, but was never happy. She was always labouring, in
+secret, under this distress; and being delicate and downcast at the time
+of his last repulse--for it was not the first, by many--pined away
+and died. She left me Agnes, two weeks old; and the grey hair that you
+recollect me with, when you first came.' He kissed Agnes on her cheek.
+
+'My love for my dear child was a diseased love, but my mind was all
+unhealthy then. I say no more of that. I am not speaking of myself,
+Trotwood, but of her mother, and of her. If I give you any clue to what
+I am, or to what I have been, you will unravel it, I know. What Agnes
+is, I need not say. I have always read something of her poor mother's
+story, in her character; and so I tell it you tonight, when we three are
+again together, after such great changes. I have told it all.'
+
+His bowed head, and her angel-face and filial duty, derived a more
+pathetic meaning from it than they had had before. If I had wanted
+anything by which to mark this night of our re-union, I should have
+found it in this.
+
+Agnes rose up from her father's side, before long; and going softly to
+her piano, played some of the old airs to which we had often listened in
+that place.
+
+'Have you any intention of going away again?' Agnes asked me, as I was
+standing by.
+
+'What does my sister say to that?'
+
+'I hope not.'
+
+'Then I have no such intention, Agnes.'
+
+'I think you ought not, Trotwood, since you ask me,' she said, mildly.
+'Your growing reputation and success enlarge your power of doing good;
+and if I could spare my brother,' with her eyes upon me, 'perhaps the
+time could not.'
+
+'What I am, you have made me, Agnes. You should know best.'
+
+'I made you, Trotwood?'
+
+'Yes! Agnes, my dear girl!' I said, bending over her. 'I tried to tell
+you, when we met today, something that has been in my thoughts since
+Dora died. You remember, when you came down to me in our little
+room--pointing upward, Agnes?'
+
+'Oh, Trotwood!' she returned, her eyes filled with tears. 'So loving, so
+confiding, and so young! Can I ever forget?'
+
+'As you were then, my sister, I have often thought since, you have ever
+been to me. Ever pointing upward, Agnes; ever leading me to something
+better; ever directing me to higher things!'
+
+She only shook her head; through her tears I saw the same sad quiet
+smile.
+
+'And I am so grateful to you for it, Agnes, so bound to you, that there
+is no name for the affection of my heart. I want you to know, yet don't
+know how to tell you, that all my life long I shall look up to you,
+and be guided by you, as I have been through the darkness that is past.
+Whatever betides, whatever new ties you may form, whatever changes may
+come between us, I shall always look to you, and love you, as I do now,
+and have always done. You will always be my solace and resource, as you
+have always been. Until I die, my dearest sister, I shall see you always
+before me, pointing upward!'
+
+She put her hand in mine, and told me she was proud of me, and of what I
+said; although I praised her very far beyond her worth. Then she went
+on softly playing, but without removing her eyes from me. 'Do you know,
+what I have heard tonight, Agnes,' said I, strangely seems to be a part
+of the feeling with which I regarded you when I saw you first--with
+which I sat beside you in my rough school-days?'
+
+'You knew I had no mother,' she replied with a smile, 'and felt kindly
+towards me.'
+
+'More than that, Agnes, I knew, almost as if I had known this story,
+that there was something inexplicably gentle and softened, surrounding
+you; something that might have been sorrowful in someone else (as I can
+now understand it was), but was not so in you.'
+
+She softly played on, looking at me still.
+
+'Will you laugh at my cherishing such fancies, Agnes?'
+
+'No!'
+
+'Or at my saying that I really believe I felt, even then, that you could
+be faithfully affectionate against all discouragement, and never cease
+to be so, until you ceased to live?---Will you laugh at such a dream?'
+
+'Oh, no! Oh, no!'
+
+For an instant, a distressful shadow crossed her face; but, even in the
+start it gave me, it was gone; and she was playing on, and looking at me
+with her own calm smile.
+
+As I rode back in the lonely night, the wind going by me like a restless
+memory, I thought of this, and feared she was not happy. I was not
+happy; but, thus far, I had faithfully set the seal upon the Past, and,
+thinking of her, pointing upward, thought of her as pointing to that
+sky above me, where, in the mystery to come, I might yet love her with
+a love unknown on earth, and tell her what the strife had been within me
+when I loved her here.
+
+
+
+CHAPTER 61. I AM SHOWN TWO INTERESTING PENITENTS
+
+
+For a time--at all events until my book should be completed, which would
+be the work of several months--I took up my abode in my aunt's house at
+Dover; and there, sitting in the window from which I had looked out at
+the moon upon the sea, when that roof first gave me shelter, I quietly
+pursued my task.
+
+In pursuance of my intention of referring to my own fictions only when
+their course should incidentally connect itself with the progress of my
+story, I do not enter on the aspirations, the delights, anxieties, and
+triumphs of my art. That I truly devoted myself to it with my strongest
+earnestness, and bestowed upon it every energy of my soul, I have
+already said. If the books I have written be of any worth, they will
+supply the rest. I shall otherwise have written to poor purpose, and the
+rest will be of interest to no one.
+
+Occasionally, I went to London; to lose myself in the swarm of life
+there, or to consult with Traddles on some business point. He had
+managed for me, in my absence, with the soundest judgement; and my
+worldly affairs were prospering. As my notoriety began to bring upon
+me an enormous quantity of letters from people of whom I had no
+knowledge--chiefly about nothing, and extremely difficult to answer--I
+agreed with Traddles to have my name painted up on his door. There, the
+devoted postman on that beat delivered bushels of letters for me; and
+there, at intervals, I laboured through them, like a Home Secretary of
+State without the salary.
+
+Among this correspondence, there dropped in, every now and then, an
+obliging proposal from one of the numerous outsiders always lurking
+about the Commons, to practise under cover of my name (if I would take
+the necessary steps remaining to make a proctor of myself), and pay me
+a percentage on the profits. But I declined these offers; being already
+aware that there were plenty of such covert practitioners in existence,
+and considering the Commons quite bad enough, without my doing anything
+to make it worse.
+
+The girls had gone home, when my name burst into bloom on Traddles's
+door; and the sharp boy looked, all day, as if he had never heard of
+Sophy, shut up in a back room, glancing down from her work into a sooty
+little strip of garden with a pump in it. But there I always found her,
+the same bright housewife; often humming her Devonshire ballads when no
+strange foot was coming up the stairs, and blunting the sharp boy in his
+official closet with melody.
+
+I wondered, at first, why I so often found Sophy writing in a copy-book;
+and why she always shut it up when I appeared, and hurried it into the
+table-drawer. But the secret soon came out. One day, Traddles (who had
+just come home through the drizzling sleet from Court) took a paper out
+of his desk, and asked me what I thought of that handwriting?
+
+'Oh, DON'T, Tom!' cried Sophy, who was warming his slippers before the
+fire.
+
+'My dear,' returned Tom, in a delighted state, 'why not? What do you say
+to that writing, Copperfield?'
+
+'It's extraordinarily legal and formal,' said I. 'I don't think I ever
+saw such a stiff hand.'
+
+'Not like a lady's hand, is it?' said Traddles.
+
+'A lady's!' I repeated. 'Bricks and mortar are more like a lady's hand!'
+
+Traddles broke into a rapturous laugh, and informed me that it was
+Sophy's writing; that Sophy had vowed and declared he would need a
+copying-clerk soon, and she would be that clerk; that she had acquired
+this hand from a pattern; and that she could throw off--I forget how
+many folios an hour. Sophy was very much confused by my being told all
+this, and said that when 'Tom' was made a judge he wouldn't be so ready
+to proclaim it. Which 'Tom' denied; averring that he should always be
+equally proud of it, under all circumstances.
+
+'What a thoroughly good and charming wife she is, my dear Traddles!'
+said I, when she had gone away, laughing.
+
+'My dear Copperfield,' returned Traddles, 'she is, without any
+exception, the dearest girl! The way she manages this place; her
+punctuality, domestic knowledge, economy, and order; her cheerfulness,
+Copperfield!'
+
+'Indeed, you have reason to commend her!' I returned. 'You are a happy
+fellow. I believe you make yourselves, and each other, two of the
+happiest people in the world.'
+
+'I am sure we ARE two of the happiest people,' returned Traddles. 'I
+admit that, at all events. Bless my soul, when I see her getting up
+by candle-light on these dark mornings, busying herself in the day's
+arrangements, going out to market before the clerks come into the Inn,
+caring for no weather, devising the most capital little dinners out of
+the plainest materials, making puddings and pies, keeping everything in
+its right place, always so neat and ornamental herself, sitting up
+at night with me if it's ever so late, sweet-tempered and encouraging
+always, and all for me, I positively sometimes can't believe it,
+Copperfield!'
+
+He was tender of the very slippers she had been warming, as he put them
+on, and stretched his feet enjoyingly upon the fender.
+
+'I positively sometimes can't believe it,' said Traddles. 'Then our
+pleasures! Dear me, they are inexpensive, but they are quite wonderful!
+When we are at home here, of an evening, and shut the outer door, and
+draw those curtains--which she made--where could we be more snug? When
+it's fine, and we go out for a walk in the evening, the streets
+abound in enjoyment for us. We look into the glittering windows of the
+jewellers' shops; and I show Sophy which of the diamond-eyed serpents,
+coiled up on white satin rising grounds, I would give her if I could
+afford it; and Sophy shows me which of the gold watches that are
+capped and jewelled and engine-turned, and possessed of the horizontal
+lever-escape-movement, and all sorts of things, she would buy for me if
+she could afford it; and we pick out the spoons and forks, fish-slices,
+butter-knives, and sugar-tongs, we should both prefer if we could both
+afford it; and really we go away as if we had got them! Then, when we
+stroll into the squares, and great streets, and see a house to let,
+sometimes we look up at it, and say, how would THAT do, if I was made
+a judge? And we parcel it out--such a room for us, such rooms for the
+girls, and so forth; until we settle to our satisfaction that it
+would do, or it wouldn't do, as the case may be. Sometimes, we go at
+half-price to the pit of the theatre--the very smell of which is cheap,
+in my opinion, at the money--and there we thoroughly enjoy the play:
+which Sophy believes every word of, and so do I. In walking home,
+perhaps we buy a little bit of something at a cook's-shop, or a little
+lobster at the fishmongers, and bring it here, and make a splendid
+supper, chatting about what we have seen. Now, you know, Copperfield, if
+I was Lord Chancellor, we couldn't do this!'
+
+'You would do something, whatever you were, my dear Traddles,' thought
+I, 'that would be pleasant and amiable. And by the way,' I said aloud,
+'I suppose you never draw any skeletons now?'
+
+'Really,' replied Traddles, laughing, and reddening, 'I can't wholly
+deny that I do, my dear Copperfield. For being in one of the back rows
+of the King's Bench the other day, with a pen in my hand, the fancy came
+into my head to try how I had preserved that accomplishment. And I am
+afraid there's a skeleton--in a wig--on the ledge of the desk.'
+
+After we had both laughed heartily, Traddles wound up by looking with a
+smile at the fire, and saying, in his forgiving way, 'Old Creakle!'
+
+'I have a letter from that old--Rascal here,' said I. For I never was
+less disposed to forgive him the way he used to batter Traddles, than
+when I saw Traddles so ready to forgive him himself.
+
+'From Creakle the schoolmaster?' exclaimed Traddles. 'No!'
+
+'Among the persons who are attracted to me in my rising fame and
+fortune,' said I, looking over my letters, 'and who discover that they
+were always much attached to me, is the self-same Creakle. He is not
+a schoolmaster now, Traddles. He is retired. He is a Middlesex
+Magistrate.'
+
+I thought Traddles might be surprised to hear it, but he was not so at
+all.
+
+'How do you suppose he comes to be a Middlesex Magistrate?' said I.
+
+'Oh dear me!' replied Traddles, 'it would be very difficult to answer
+that question. Perhaps he voted for somebody, or lent money to somebody,
+or bought something of somebody, or otherwise obliged somebody, or
+jobbed for somebody, who knew somebody who got the lieutenant of the
+county to nominate him for the commission.'
+
+'On the commission he is, at any rate,' said I. 'And he writes to me
+here, that he will be glad to show me, in operation, the only true
+system of prison discipline; the only unchallengeable way of making
+sincere and lasting converts and penitents--which, you know, is by
+solitary confinement. What do you say?'
+
+'To the system?' inquired Traddles, looking grave.
+
+'No. To my accepting the offer, and your going with me?'
+
+'I don't object,' said Traddles.
+
+'Then I'll write to say so. You remember (to say nothing of our
+treatment) this same Creakle turning his son out of doors, I suppose,
+and the life he used to lead his wife and daughter?'
+
+'Perfectly,' said Traddles.
+
+'Yet, if you'll read his letter, you'll find he is the tenderest of
+men to prisoners convicted of the whole calendar of felonies,' said I;
+'though I can't find that his tenderness extends to any other class of
+created beings.'
+
+Traddles shrugged his shoulders, and was not at all surprised. I had not
+expected him to be, and was not surprised myself; or my observation of
+similar practical satires would have been but scanty. We arranged the
+time of our visit, and I wrote accordingly to Mr. Creakle that evening.
+
+On the appointed day--I think it was the next day, but no
+matter--Traddles and I repaired to the prison where Mr. Creakle was
+powerful. It was an immense and solid building, erected at a vast
+expense. I could not help thinking, as we approached the gate, what
+an uproar would have been made in the country, if any deluded man had
+proposed to spend one half the money it had cost, on the erection of an
+industrial school for the young, or a house of refuge for the deserving
+old.
+
+In an office that might have been on the ground-floor of the Tower of
+Babel, it was so massively constructed, we were presented to our old
+schoolmaster; who was one of a group, composed of two or three of the
+busier sort of magistrates, and some visitors they had brought. He
+received me, like a man who had formed my mind in bygone years, and
+had always loved me tenderly. On my introducing Traddles, Mr. Creakle
+expressed, in like manner, but in an inferior degree, that he had always
+been Traddles's guide, philosopher, and friend. Our venerable instructor
+was a great deal older, and not improved in appearance. His face was
+as fiery as ever; his eyes were as small, and rather deeper set. The
+scanty, wet-looking grey hair, by which I remembered him, was almost
+gone; and the thick veins in his bald head were none the more agreeable
+to look at.
+
+After some conversation among these gentlemen, from which I might have
+supposed that there was nothing in the world to be legitimately taken
+into account but the supreme comfort of prisoners, at any expense, and
+nothing on the wide earth to be done outside prison-doors, we began
+our inspection. It being then just dinner-time, we went, first into the
+great kitchen, where every prisoner's dinner was in course of being set
+out separately (to be handed to him in his cell), with the regularity
+and precision of clock-work. I said aside, to Traddles, that I wondered
+whether it occurred to anybody, that there was a striking contrast
+between these plentiful repasts of choice quality, and the dinners, not
+to say of paupers, but of soldiers, sailors, labourers, the great bulk
+of the honest, working community; of whom not one man in five hundred
+ever dined half so well. But I learned that the 'system' required high
+living; and, in short, to dispose of the system, once for all, I found
+that on that head and on all others, 'the system' put an end to all
+doubts, and disposed of all anomalies. Nobody appeared to have the least
+idea that there was any other system, but THE system, to be considered.
+
+As we were going through some of the magnificent passages, I inquired of
+Mr. Creakle and his friends what were supposed to be the main advantages
+of this all-governing and universally over-riding system? I found
+them to be the perfect isolation of prisoners--so that no one man in
+confinement there, knew anything about another; and the reduction of
+prisoners to a wholesome state of mind, leading to sincere contrition
+and repentance.
+
+Now, it struck me, when we began to visit individuals in their cells,
+and to traverse the passages in which those cells were, and to have the
+manner of the going to chapel and so forth, explained to us, that there
+was a strong probability of the prisoners knowing a good deal about each
+other, and of their carrying on a pretty complete system of intercourse.
+This, at the time I write, has been proved, I believe, to be the case;
+but, as it would have been flat blasphemy against the system to have
+hinted such a doubt then, I looked out for the penitence as diligently
+as I could.
+
+And here again, I had great misgivings. I found as prevalent a fashion
+in the form of the penitence, as I had left outside in the forms of the
+coats and waistcoats in the windows of the tailors' shops. I found a
+vast amount of profession, varying very little in character: varying
+very little (which I thought exceedingly suspicious), even in words. I
+found a great many foxes, disparaging whole vineyards of inaccessible
+grapes; but I found very few foxes whom I would have trusted within
+reach of a bunch. Above all, I found that the most professing men were
+the greatest objects of interest; and that their conceit, their vanity,
+their want of excitement, and their love of deception (which many
+of them possessed to an almost incredible extent, as their histories
+showed), all prompted to these professions, and were all gratified by
+them.
+
+However, I heard so repeatedly, in the course of our goings to and fro,
+of a certain Number Twenty Seven, who was the Favourite, and who really
+appeared to be a Model Prisoner, that I resolved to suspend my judgement
+until I should see Twenty Seven. Twenty Eight, I understood, was also
+a bright particular star; but it was his misfortune to have his glory
+a little dimmed by the extraordinary lustre of Twenty Seven. I heard so
+much of Twenty Seven, of his pious admonitions to everybody around him,
+and of the beautiful letters he constantly wrote to his mother (whom he
+seemed to consider in a very bad way), that I became quite impatient to
+see him.
+
+I had to restrain my impatience for some time, on account of Twenty
+Seven being reserved for a concluding effect. But, at last, we came to
+the door of his cell; and Mr. Creakle, looking through a little hole in
+it, reported to us, in a state of the greatest admiration, that he was
+reading a Hymn Book.
+
+There was such a rush of heads immediately, to see Number Twenty Seven
+reading his Hymn Book, that the little hole was blocked up, six or seven
+heads deep. To remedy this inconvenience, and give us an opportunity of
+conversing with Twenty Seven in all his purity, Mr. Creakle directed the
+door of the cell to be unlocked, and Twenty Seven to be invited out into
+the passage. This was done; and whom should Traddles and I then behold,
+to our amazement, in this converted Number Twenty Seven, but Uriah Heep!
+
+He knew us directly; and said, as he came out--with the old writhe,--
+
+'How do you do, Mr. Copperfield? How do you do, Mr. Traddles?'
+
+This recognition caused a general admiration in the party. I rather
+thought that everyone was struck by his not being proud, and taking
+notice of us.
+
+'Well, Twenty Seven,' said Mr. Creakle, mournfully admiring him. 'How do
+you find yourself today?'
+
+'I am very umble, sir!' replied Uriah Heep.
+
+'You are always so, Twenty Seven,' said Mr. Creakle.
+
+Here, another gentleman asked, with extreme anxiety: 'Are you quite
+comfortable?'
+
+'Yes, I thank you, sir!' said Uriah Heep, looking in that direction.
+'Far more comfortable here, than ever I was outside. I see my follies,
+now, sir. That's what makes me comfortable.'
+
+Several gentlemen were much affected; and a third questioner, forcing
+himself to the front, inquired with extreme feeling: 'How do you find
+the beef?'
+
+'Thank you, sir,' replied Uriah, glancing in the new direction of this
+voice, 'it was tougher yesterday than I could wish; but it's my duty to
+bear. I have committed follies, gentlemen,' said Uriah, looking round
+with a meek smile, 'and I ought to bear the consequences without
+repining.' A murmur, partly of gratification at Twenty Seven's celestial
+state of mind, and partly of indignation against the Contractor who had
+given him any cause of complaint (a note of which was immediately made
+by Mr. Creakle), having subsided, Twenty Seven stood in the midst of
+us, as if he felt himself the principal object of merit in a highly
+meritorious museum. That we, the neophytes, might have an excess of
+light shining upon us all at once, orders were given to let out Twenty
+Eight.
+
+I had been so much astonished already, that I only felt a kind of
+resigned wonder when Mr. Littimer walked forth, reading a good book!
+
+'Twenty Eight,' said a gentleman in spectacles, who had not yet spoken,
+'you complained last week, my good fellow, of the cocoa. How has it been
+since?'
+
+'I thank you, sir,' said Mr. Littimer, 'it has been better made. If I
+might take the liberty of saying so, sir, I don't think the milk which
+is boiled with it is quite genuine; but I am aware, sir, that there is
+a great adulteration of milk, in London, and that the article in a pure
+state is difficult to be obtained.'
+
+It appeared to me that the gentleman in spectacles backed his Twenty
+Eight against Mr. Creakle's Twenty Seven, for each of them took his own
+man in hand.
+
+'What is your state of mind, Twenty Eight?' said the questioner in
+spectacles.
+
+'I thank you, sir,' returned Mr. Littimer; 'I see my follies now, sir.
+I am a good deal troubled when I think of the sins of my former
+companions, sir; but I trust they may find forgiveness.'
+
+'You are quite happy yourself?' said the questioner, nodding
+encouragement.
+
+'I am much obliged to you, sir,' returned Mr. Littimer. 'Perfectly so.'
+
+'Is there anything at all on your mind now?' said the questioner. 'If
+so, mention it, Twenty Eight.'
+
+'Sir,' said Mr. Littimer, without looking up, 'if my eyes have not
+deceived me, there is a gentleman present who was acquainted with me
+in my former life. It may be profitable to that gentleman to know, sir,
+that I attribute my past follies, entirely to having lived a thoughtless
+life in the service of young men; and to having allowed myself to be led
+by them into weaknesses, which I had not the strength to resist. I hope
+that gentleman will take warning, sir, and will not be offended at my
+freedom. It is for his good. I am conscious of my own past follies. I
+hope he may repent of all the wickedness and sin to which he has been a
+party.'
+
+I observed that several gentlemen were shading their eyes, each with one
+hand, as if they had just come into church.
+
+'This does you credit, Twenty Eight,' returned the questioner. 'I should
+have expected it of you. Is there anything else?'
+
+'Sir,' returned Mr. Littimer, slightly lifting up his eyebrows, but not
+his eyes, 'there was a young woman who fell into dissolute courses, that
+I endeavoured to save, sir, but could not rescue. I beg that gentleman,
+if he has it in his power, to inform that young woman from me that
+I forgive her her bad conduct towards myself, and that I call her to
+repentance--if he will be so good.'
+
+'I have no doubt, Twenty Eight,' returned the questioner, 'that the
+gentleman you refer to feels very strongly--as we all must--what you
+have so properly said. We will not detain you.'
+
+'I thank you, sir,' said Mr. Littimer. 'Gentlemen, I wish you a good
+day, and hoping you and your families will also see your wickedness, and
+amend!'
+
+With this, Number Twenty Eight retired, after a glance between him and
+Uriah; as if they were not altogether unknown to each other, through
+some medium of communication; and a murmur went round the group, as his
+door shut upon him, that he was a most respectable man, and a beautiful
+case.
+
+'Now, Twenty Seven,' said Mr. Creakle, entering on a clear stage with
+his man, 'is there anything that anyone can do for you? If so, mention
+it.'
+
+'I would umbly ask, sir,' returned Uriah, with a jerk of his malevolent
+head, 'for leave to write again to mother.'
+
+'It shall certainly be granted,' said Mr. Creakle.
+
+'Thank you, sir! I am anxious about mother. I am afraid she ain't safe.'
+
+Somebody incautiously asked, what from? But there was a scandalized
+whisper of 'Hush!'
+
+'Immortally safe, sir,' returned Uriah, writhing in the direction of
+the voice. 'I should wish mother to be got into my state. I never should
+have been got into my present state if I hadn't come here. I wish mother
+had come here. It would be better for everybody, if they got took up,
+and was brought here.'
+
+This sentiment gave unbounded satisfaction--greater satisfaction, I
+think, than anything that had passed yet.
+
+'Before I come here,' said Uriah, stealing a look at us, as if he would
+have blighted the outer world to which we belonged, if he could, 'I was
+given to follies; but now I am sensible of my follies. There's a deal
+of sin outside. There's a deal of sin in mother. There's nothing but sin
+everywhere--except here.'
+
+'You are quite changed?' said Mr. Creakle.
+
+'Oh dear, yes, sir!' cried this hopeful penitent.
+
+'You wouldn't relapse, if you were going out?' asked somebody else.
+
+'Oh de-ar no, sir!'
+
+'Well!' said Mr. Creakle, 'this is very gratifying. You have addressed
+Mr. Copperfield, Twenty Seven. Do you wish to say anything further to
+him?'
+
+'You knew me, a long time before I came here and was changed, Mr.
+Copperfield,' said Uriah, looking at me; and a more villainous look
+I never saw, even on his visage. 'You knew me when, in spite of my
+follies, I was umble among them that was proud, and meek among them that
+was violent--you was violent to me yourself, Mr. Copperfield. Once, you
+struck me a blow in the face, you know.'
+
+General commiseration. Several indignant glances directed at me.
+
+'But I forgive you, Mr. Copperfield,' said Uriah, making his forgiving
+nature the subject of a most impious and awful parallel, which I shall
+not record. 'I forgive everybody. It would ill become me to bear malice.
+I freely forgive you, and I hope you'll curb your passions in future. I
+hope Mr. W. will repent, and Miss W., and all of that sinful lot. You've
+been visited with affliction, and I hope it may do you good; but you'd
+better have come here. Mr. W. had better have come here, and Miss W.
+too. The best wish I could give you, Mr. Copperfield, and give all of
+you gentlemen, is, that you could be took up and brought here. When I
+think of my past follies, and my present state, I am sure it would be
+best for you. I pity all who ain't brought here!'
+
+He sneaked back into his cell, amidst a little chorus of approbation;
+and both Traddles and I experienced a great relief when he was locked
+in.
+
+It was a characteristic feature in this repentance, that I was fain to
+ask what these two men had done, to be there at all. That appeared to be
+the last thing about which they had anything to say. I addressed
+myself to one of the two warders, who, I suspected from certain latent
+indications in their faces, knew pretty well what all this stir was
+worth.
+
+'Do you know,' said I, as we walked along the passage, 'what felony was
+Number Twenty Seven's last "folly"?'
+
+The answer was that it was a Bank case.
+
+'A fraud on the Bank of England?' I asked. 'Yes, sir. Fraud, forgery,
+and conspiracy. He and some others. He set the others on. It was a deep
+plot for a large sum. Sentence, transportation for life. Twenty Seven
+was the knowingest bird of the lot, and had very nearly kept himself
+safe; but not quite. The Bank was just able to put salt upon his
+tail--and only just.'
+
+'Do you know Twenty Eight's offence?'
+
+'Twenty Eight,' returned my informant, speaking throughout in a low
+tone, and looking over his shoulder as we walked along the passage, to
+guard himself from being overheard, in such an unlawful reference
+to these Immaculates, by Creakle and the rest; 'Twenty Eight (also
+transportation) got a place, and robbed a young master of a matter of
+two hundred and fifty pounds in money and valuables, the night before
+they were going abroad. I particularly recollect his case, from his
+being took by a dwarf.'
+
+'A what?'
+
+'A little woman. I have forgot her name?'
+
+'Not Mowcher?'
+
+'That's it! He had eluded pursuit, and was going to America in a flaxen
+wig, and whiskers, and such a complete disguise as never you see in all
+your born days; when the little woman, being in Southampton, met
+him walking along the street--picked him out with her sharp eye in a
+moment--ran betwixt his legs to upset him--and held on to him like grim
+Death.'
+
+'Excellent Miss Mowcher!' cried I.
+
+'You'd have said so, if you had seen her, standing on a chair in the
+witness-box at the trial, as I did,' said my friend. 'He cut her face
+right open, and pounded her in the most brutal manner, when she took
+him; but she never loosed her hold till he was locked up. She held so
+tight to him, in fact, that the officers were obliged to take 'em
+both together. She gave her evidence in the gamest way, and was highly
+complimented by the Bench, and cheered right home to her lodgings. She
+said in Court that she'd have took him single-handed (on account of what
+she knew concerning him), if he had been Samson. And it's my belief she
+would!'
+
+It was mine too, and I highly respected Miss Mowcher for it.
+
+We had now seen all there was to see. It would have been in vain to
+represent to such a man as the Worshipful Mr. Creakle, that Twenty Seven
+and Twenty Eight were perfectly consistent and unchanged; that exactly
+what they were then, they had always been; that the hypocritical knaves
+were just the subjects to make that sort of profession in such a place;
+that they knew its market-value at least as well as we did, in the
+immediate service it would do them when they were expatriated; in
+a word, that it was a rotten, hollow, painfully suggestive piece of
+business altogether. We left them to their system and themselves, and
+went home wondering.
+
+'Perhaps it's a good thing, Traddles,' said I, 'to have an unsound Hobby
+ridden hard; for it's the sooner ridden to death.'
+
+'I hope so,' replied Traddles.
+
+
+
+CHAPTER 62. A LIGHT SHINES ON MY WAY
+
+
+The year came round to Christmas-time, and I had been at home above
+two months. I had seen Agnes frequently. However loud the general voice
+might be in giving me encouragement, and however fervent the emotions
+and endeavours to which it roused me, I heard her lightest word of
+praise as I heard nothing else.
+
+At least once a week, and sometimes oftener, I rode over there, and
+passed the evening. I usually rode back at night; for the old unhappy
+sense was always hovering about me now--most sorrowfully when I left
+her--and I was glad to be up and out, rather than wandering over the
+past in weary wakefulness or miserable dreams. I wore away the longest
+part of many wild sad nights, in those rides; reviving, as I went, the
+thoughts that had occupied me in my long absence.
+
+Or, if I were to say rather that I listened to the echoes of those
+thoughts, I should better express the truth. They spoke to me from afar
+off. I had put them at a distance, and accepted my inevitable place.
+When I read to Agnes what I wrote; when I saw her listening face; moved
+her to smiles or tears; and heard her cordial voice so earnest on the
+shadowy events of that imaginative world in which I lived; I thought
+what a fate mine might have been--but only thought so, as I had thought
+after I was married to Dora, what I could have wished my wife to be.
+
+My duty to Agnes, who loved me with a love, which, if I disquieted, I
+wronged most selfishly and poorly, and could never restore; my matured
+assurance that I, who had worked out my own destiny, and won what I
+had impetuously set my heart on, had no right to murmur, and must bear;
+comprised what I felt and what I had learned. But I loved her: and now
+it even became some consolation to me, vaguely to conceive a distant day
+when I might blamelessly avow it; when all this should be over; when I
+could say 'Agnes, so it was when I came home; and now I am old, and I
+never have loved since!'
+
+She did not once show me any change in herself. What she always had been
+to me, she still was; wholly unaltered.
+
+Between my aunt and me there had been something, in this connexion,
+since the night of my return, which I cannot call a restraint, or an
+avoidance of the subject, so much as an implied understanding that we
+thought of it together, but did not shape our thoughts into words. When,
+according to our old custom, we sat before the fire at night, we often
+fell into this train; as naturally, and as consciously to each other, as
+if we had unreservedly said so. But we preserved an unbroken silence. I
+believed that she had read, or partly read, my thoughts that night; and
+that she fully comprehended why I gave mine no more distinct expression.
+
+This Christmas-time being come, and Agnes having reposed no new
+confidence in me, a doubt that had several times arisen in my
+mind--whether she could have that perception of the true state of
+my breast, which restrained her with the apprehension of giving me
+pain--began to oppress me heavily. If that were so, my sacrifice was
+nothing; my plainest obligation to her unfulfilled; and every poor
+action I had shrunk from, I was hourly doing. I resolved to set this
+right beyond all doubt;--if such a barrier were between us, to break it
+down at once with a determined hand.
+
+It was--what lasting reason have I to remember it!--a cold, harsh,
+winter day. There had been snow, some hours before; and it lay, not
+deep, but hard-frozen on the ground. Out at sea, beyond my window, the
+wind blew ruggedly from the north. I had been thinking of it, sweeping
+over those mountain wastes of snow in Switzerland, then inaccessible to
+any human foot; and had been speculating which was the lonelier, those
+solitary regions, or a deserted ocean.
+
+'Riding today, Trot?' said my aunt, putting her head in at the door.
+
+'Yes,' said I, 'I am going over to Canterbury. It's a good day for a
+ride.'
+
+'I hope your horse may think so too,' said my aunt; 'but at present he
+is holding down his head and his ears, standing before the door there,
+as if he thought his stable preferable.'
+
+My aunt, I may observe, allowed my horse on the forbidden ground, but
+had not at all relented towards the donkeys.
+
+'He will be fresh enough, presently!' said I.
+
+'The ride will do his master good, at all events,' observed my aunt,
+glancing at the papers on my table. 'Ah, child, you pass a good many
+hours here! I never thought, when I used to read books, what work it was
+to write them.'
+
+'It's work enough to read them, sometimes,' I returned. 'As to the
+writing, it has its own charms, aunt.'
+
+'Ah! I see!' said my aunt. 'Ambition, love of approbation, sympathy, and
+much more, I suppose? Well: go along with you!'
+
+'Do you know anything more,' said I, standing composedly before her--she
+had patted me on the shoulder, and sat down in my chair--'of that
+attachment of Agnes?'
+
+She looked up in my face a little while, before replying:
+
+'I think I do, Trot.'
+
+'Are you confirmed in your impression?' I inquired.
+
+'I think I am, Trot.'
+
+She looked so steadfastly at me: with a kind of doubt, or pity, or
+suspense in her affection: that I summoned the stronger determination to
+show her a perfectly cheerful face.
+
+'And what is more, Trot--' said my aunt.
+
+'Yes!'
+
+'I think Agnes is going to be married.'
+
+'God bless her!' said I, cheerfully.
+
+'God bless her!' said my aunt, 'and her husband too!'
+
+I echoed it, parted from my aunt, and went lightly downstairs, mounted,
+and rode away. There was greater reason than before to do what I had
+resolved to do.
+
+How well I recollect the wintry ride! The frozen particles of ice,
+brushed from the blades of grass by the wind, and borne across my face;
+the hard clatter of the horse's hoofs, beating a tune upon the ground;
+the stiff-tilled soil; the snowdrift, lightly eddying in the chalk-pit
+as the breeze ruffled it; the smoking team with the waggon of old hay,
+stopping to breathe on the hill-top, and shaking their bells musically;
+the whitened slopes and sweeps of Down-land lying against the dark sky,
+as if they were drawn on a huge slate!
+
+I found Agnes alone. The little girls had gone to their own homes now,
+and she was alone by the fire, reading. She put down her book on seeing
+me come in; and having welcomed me as usual, took her work-basket and
+sat in one of the old-fashioned windows.
+
+I sat beside her on the window-seat, and we talked of what I was doing,
+and when it would be done, and of the progress I had made since my last
+visit. Agnes was very cheerful; and laughingly predicted that I should
+soon become too famous to be talked to, on such subjects.
+
+'So I make the most of the present time, you see,' said Agnes, 'and talk
+to you while I may.'
+
+As I looked at her beautiful face, observant of her work, she raised her
+mild clear eyes, and saw that I was looking at her.
+
+'You are thoughtful today, Trotwood!'
+
+'Agnes, shall I tell you what about? I came to tell you.'
+
+She put aside her work, as she was used to do when we were seriously
+discussing anything; and gave me her whole attention.
+
+'My dear Agnes, do you doubt my being true to you?'
+
+'No!' she answered, with a look of astonishment.
+
+'Do you doubt my being what I always have been to you?'
+
+'No!' she answered, as before.
+
+'Do you remember that I tried to tell you, when I came home, what a debt
+of gratitude I owed you, dearest Agnes, and how fervently I felt towards
+you?'
+
+'I remember it,' she said, gently, 'very well.'
+
+'You have a secret,' said I. 'Let me share it, Agnes.'
+
+She cast down her eyes, and trembled.
+
+'I could hardly fail to know, even if I had not heard--but from other
+lips than yours, Agnes, which seems strange--that there is someone upon
+whom you have bestowed the treasure of your love. Do not shut me out of
+what concerns your happiness so nearly! If you can trust me, as you say
+you can, and as I know you may, let me be your friend, your brother, in
+this matter, of all others!'
+
+With an appealing, almost a reproachful, glance, she rose from the
+window; and hurrying across the room as if without knowing where, put
+her hands before her face, and burst into such tears as smote me to the
+heart.
+
+And yet they awakened something in me, bringing promise to my heart.
+Without my knowing why, these tears allied themselves with the quietly
+sad smile which was so fixed in my remembrance, and shook me more with
+hope than fear or sorrow.
+
+'Agnes! Sister! Dearest! What have I done?'
+
+'Let me go away, Trotwood. I am not well. I am not myself. I will speak
+to you by and by--another time. I will write to you. Don't speak to me
+now. Don't! don't!'
+
+I sought to recollect what she had said, when I had spoken to her on
+that former night, of her affection needing no return. It seemed a very
+world that I must search through in a moment. 'Agnes, I cannot bear
+to see you so, and think that I have been the cause. My dearest girl,
+dearer to me than anything in life, if you are unhappy, let me share
+your unhappiness. If you are in need of help or counsel, let me try to
+give it to you. If you have indeed a burden on your heart, let me try to
+lighten it. For whom do I live now, Agnes, if it is not for you!'
+
+'Oh, spare me! I am not myself! Another time!' was all I could
+distinguish.
+
+Was it a selfish error that was leading me away? Or, having once a clue
+to hope, was there something opening to me that I had not dared to think
+of?
+
+'I must say more. I cannot let you leave me so! For Heaven's sake,
+Agnes, let us not mistake each other after all these years, and all
+that has come and gone with them! I must speak plainly. If you have any
+lingering thought that I could envy the happiness you will confer; that
+I could not resign you to a dearer protector, of your own choosing; that
+I could not, from my removed place, be a contented witness of your joy;
+dismiss it, for I don't deserve it! I have not suffered quite in vain.
+You have not taught me quite in vain. There is no alloy of self in what
+I feel for you.'
+
+She was quiet now. In a little time, she turned her pale face towards
+me, and said in a low voice, broken here and there, but very clear:
+
+'I owe it to your pure friendship for me, Trotwood--which, indeed, I do
+not doubt--to tell you, you are mistaken. I can do no more. If I have
+sometimes, in the course of years, wanted help and counsel, they have
+come to me. If I have sometimes been unhappy, the feeling has passed
+away. If I have ever had a burden on my heart, it has been lightened
+for me. If I have any secret, it is--no new one; and is--not what you
+suppose. I cannot reveal it, or divide it. It has long been mine, and
+must remain mine.'
+
+'Agnes! Stay! A moment!'
+
+She was going away, but I detained her. I clasped my arm about her
+waist. 'In the course of years!' 'It is not a new one!' New thoughts and
+hopes were whirling through my mind, and all the colours of my life were
+changing.
+
+'Dearest Agnes! Whom I so respect and honour--whom I so devotedly love!
+When I came here today, I thought that nothing could have wrested this
+confession from me. I thought I could have kept it in my bosom all our
+lives, till we were old. But, Agnes, if I have indeed any new-born hope
+that I may ever call you something more than Sister, widely different
+from Sister!--'
+
+Her tears fell fast; but they were not like those she had lately shed,
+and I saw my hope brighten in them.
+
+'Agnes! Ever my guide, and best support! If you had been more mindful
+of yourself, and less of me, when we grew up here together, I think my
+heedless fancy never would have wandered from you. But you were so
+much better than I, so necessary to me in every boyish hope and
+disappointment, that to have you to confide in, and rely upon in
+everything, became a second nature, supplanting for the time the first
+and greater one of loving you as I do!'
+
+Still weeping, but not sadly--joyfully! And clasped in my arms as she
+had never been, as I had thought she never was to be!
+
+'When I loved Dora--fondly, Agnes, as you know--'
+
+'Yes!' she cried, earnestly. 'I am glad to know it!'
+
+'When I loved her--even then, my love would have been incomplete,
+without your sympathy. I had it, and it was perfected. And when I lost
+her, Agnes, what should I have been without you, still!'
+
+Closer in my arms, nearer to my heart, her trembling hand upon my
+shoulder, her sweet eyes shining through her tears, on mine!
+
+'I went away, dear Agnes, loving you. I stayed away, loving you. I
+returned home, loving you!'
+
+And now, I tried to tell her of the struggle I had had, and the
+conclusion I had come to. I tried to lay my mind before her, truly, and
+entirely. I tried to show her how I had hoped I had come into the better
+knowledge of myself and of her; how I had resigned myself to what that
+better knowledge brought; and how I had come there, even that day, in my
+fidelity to this. If she did so love me (I said) that she could take me
+for her husband, she could do so, on no deserving of mine, except upon
+the truth of my love for her, and the trouble in which it had ripened to
+be what it was; and hence it was that I revealed it. And O, Agnes, even
+out of thy true eyes, in that same time, the spirit of my child-wife
+looked upon me, saying it was well; and winning me, through thee, to
+tenderest recollections of the Blossom that had withered in its bloom!
+
+'I am so blest, Trotwood--my heart is so overcharged--but there is one
+thing I must say.'
+
+'Dearest, what?'
+
+She laid her gentle hands upon my shoulders, and looked calmly in my
+face.
+
+'Do you know, yet, what it is?'
+
+'I am afraid to speculate on what it is. Tell me, my dear.'
+
+'I have loved you all my life!'
+
+O, we were happy, we were happy! Our tears were not for the trials (hers
+so much the greater) through which we had come to be thus, but for the
+rapture of being thus, never to be divided more!
+
+We walked, that winter evening, in the fields together; and the blessed
+calm within us seemed to be partaken by the frosty air. The early stars
+began to shine while we were lingering on, and looking up to them, we
+thanked our GOD for having guided us to this tranquillity.
+
+We stood together in the same old-fashioned window at night, when the
+moon was shining; Agnes with her quiet eyes raised up to it; I following
+her glance. Long miles of road then opened out before my mind; and,
+toiling on, I saw a ragged way-worn boy, forsaken and neglected, who
+should come to call even the heart now beating against mine, his own.
+
+
+It was nearly dinner-time next day when we appeared before my aunt. She
+was up in my study, Peggotty said: which it was her pride to keep in
+readiness and order for me. We found her, in her spectacles, sitting by
+the fire.
+
+'Goodness me!' said my aunt, peering through the dusk, 'who's this
+you're bringing home?'
+
+'Agnes,' said I.
+
+As we had arranged to say nothing at first, my aunt was not a little
+discomfited. She darted a hopeful glance at me, when I said 'Agnes'; but
+seeing that I looked as usual, she took off her spectacles in despair,
+and rubbed her nose with them.
+
+She greeted Agnes heartily, nevertheless; and we were soon in the
+lighted parlour downstairs, at dinner. My aunt put on her spectacles
+twice or thrice, to take another look at me, but as often took them
+off again, disappointed, and rubbed her nose with them. Much to the
+discomfiture of Mr. Dick, who knew this to be a bad symptom.
+
+'By the by, aunt,' said I, after dinner; 'I have been speaking to Agnes
+about what you told me.'
+
+'Then, Trot,' said my aunt, turning scarlet, 'you did wrong, and broke
+your promise.'
+
+'You are not angry, aunt, I trust? I am sure you won't be, when you
+learn that Agnes is not unhappy in any attachment.'
+
+'Stuff and nonsense!' said my aunt.
+
+As my aunt appeared to be annoyed, I thought the best way was to cut her
+annoyance short. I took Agnes in my arm to the back of her chair, and we
+both leaned over her. My aunt, with one clap of her hands, and one look
+through her spectacles, immediately went into hysterics, for the first
+and only time in all my knowledge of her.
+
+The hysterics called up Peggotty. The moment my aunt was restored, she
+flew at Peggotty, and calling her a silly old creature, hugged her with
+all her might. After that, she hugged Mr. Dick (who was highly honoured,
+but a good deal surprised); and after that, told them why. Then, we were
+all happy together.
+
+I could not discover whether my aunt, in her last short conversation
+with me, had fallen on a pious fraud, or had really mistaken the state
+of my mind. It was quite enough, she said, that she had told me Agnes
+was going to be married; and that I now knew better than anyone how true
+it was.
+
+
+We were married within a fortnight. Traddles and Sophy, and Doctor and
+Mrs. Strong, were the only guests at our quiet wedding. We left them
+full of joy; and drove away together. Clasped in my embrace, I held the
+source of every worthy aspiration I had ever had; the centre of myself,
+the circle of my life, my own, my wife; my love of whom was founded on a
+rock!
+
+'Dearest husband!' said Agnes. 'Now that I may call you by that name, I
+have one thing more to tell you.'
+
+'Let me hear it, love.'
+
+'It grows out of the night when Dora died. She sent you for me.'
+
+'She did.'
+
+'She told me that she left me something. Can you think what it was?'
+
+I believed I could. I drew the wife who had so long loved me, closer to
+my side.
+
+'She told me that she made a last request to me, and left me a last
+charge.'
+
+'And it was--'
+
+'That only I would occupy this vacant place.'
+
+And Agnes laid her head upon my breast, and wept; and I wept with her,
+though we were so happy.
+
+
+
+
+CHAPTER 63. A VISITOR
+
+What I have purposed to record is nearly finished; but there is yet an
+incident conspicuous in my memory, on which it often rests with delight,
+and without which one thread in the web I have spun would have a
+ravelled end.
+
+I had advanced in fame and fortune, my domestic joy was perfect, I had
+been married ten happy years. Agnes and I were sitting by the fire, in
+our house in London, one night in spring, and three of our children were
+playing in the room, when I was told that a stranger wished to see me.
+
+He had been asked if he came on business, and had answered No; he had
+come for the pleasure of seeing me, and had come a long way. He was an
+old man, my servant said, and looked like a farmer.
+
+As this sounded mysterious to the children, and moreover was like the
+beginning of a favourite story Agnes used to tell them, introductory
+to the arrival of a wicked old Fairy in a cloak who hated everybody, it
+produced some commotion. One of our boys laid his head in his mother's
+lap to be out of harm's way, and little Agnes (our eldest child) left
+her doll in a chair to represent her, and thrust out her little heap
+of golden curls from between the window-curtains, to see what happened
+next.
+
+'Let him come in here!' said I.
+
+There soon appeared, pausing in the dark doorway as he entered, a hale,
+grey-haired old man. Little Agnes, attracted by his looks, had run to
+bring him in, and I had not yet clearly seen his face, when my wife,
+starting up, cried out to me, in a pleased and agitated voice, that it
+was Mr. Peggotty!
+
+It WAS Mr. Peggotty. An old man now, but in a ruddy, hearty, strong old
+age. When our first emotion was over, and he sat before the fire with
+the children on his knees, and the blaze shining on his face, he looked,
+to me, as vigorous and robust, withal as handsome, an old man, as ever I
+had seen.
+
+'Mas'r Davy,' said he. And the old name in the old tone fell so
+naturally on my ear! 'Mas'r Davy, 'tis a joyful hour as I see you, once
+more, 'long with your own trew wife!'
+
+'A joyful hour indeed, old friend!' cried I.
+
+'And these heer pretty ones,' said Mr. Peggotty. 'To look at these heer
+flowers! Why, Mas'r Davy, you was but the heighth of the littlest of
+these, when I first see you! When Em'ly warn't no bigger, and our poor
+lad were BUT a lad!'
+
+'Time has changed me more than it has changed you since then,' said I.
+'But let these dear rogues go to bed; and as no house in England but
+this must hold you, tell me where to send for your luggage (is the old
+black bag among it, that went so far, I wonder!), and then, over a glass
+of Yarmouth grog, we will have the tidings of ten years!'
+
+'Are you alone?' asked Agnes.
+
+'Yes, ma'am,' he said, kissing her hand, 'quite alone.'
+
+We sat him between us, not knowing how to give him welcome enough; and
+as I began to listen to his old familiar voice, I could have fancied he
+was still pursuing his long journey in search of his darling niece.
+
+'It's a mort of water,' said Mr. Peggotty, 'fur to come across, and
+on'y stay a matter of fower weeks. But water ('specially when 'tis salt)
+comes nat'ral to me; and friends is dear, and I am heer. --Which is
+verse,' said Mr. Peggotty, surprised to find it out, 'though I hadn't
+such intentions.'
+
+'Are you going back those many thousand miles, so soon?' asked Agnes.
+
+'Yes, ma'am,' he returned. 'I giv the promise to Em'ly, afore I come
+away. You see, I doen't grow younger as the years comes round, and if
+I hadn't sailed as 'twas, most like I shouldn't never have done 't. And
+it's allus been on my mind, as I must come and see Mas'r Davy and your
+own sweet blooming self, in your wedded happiness, afore I got to be too
+old.'
+
+He looked at us, as if he could never feast his eyes on us sufficiently.
+Agnes laughingly put back some scattered locks of his grey hair, that he
+might see us better.
+
+'And now tell us,' said I, 'everything relating to your fortunes.'
+
+'Our fortuns, Mas'r Davy,' he rejoined, 'is soon told. We haven't fared
+nohows, but fared to thrive. We've allus thrived. We've worked as we
+ought to 't, and maybe we lived a leetle hard at first or so, but
+we have allus thrived. What with sheep-farming, and what with
+stock-farming, and what with one thing and what with t'other, we are as
+well to do, as well could be. Theer's been kiender a blessing fell upon
+us,' said Mr. Peggotty, reverentially inclining his head, 'and we've
+done nowt but prosper. That is, in the long run. If not yesterday, why
+then today. If not today, why then tomorrow.'
+
+'And Emily?' said Agnes and I, both together.
+
+'Em'ly,' said he, 'arter you left her, ma'am--and I never heerd her
+saying of her prayers at night, t'other side the canvas screen, when we
+was settled in the Bush, but what I heerd your name--and arter she and
+me lost sight of Mas'r Davy, that theer shining sundown--was that low,
+at first, that, if she had know'd then what Mas'r Davy kep from us so
+kind and thowtful, 'tis my opinion she'd have drooped away. But theer
+was some poor folks aboard as had illness among 'em, and she took care
+of them; and theer was the children in our company, and she took care of
+them; and so she got to be busy, and to be doing good, and that helped
+her.'
+
+'When did she first hear of it?' I asked.
+
+'I kep it from her arter I heerd on 't,' said Mr. Peggotty, 'going
+on nigh a year. We was living then in a solitary place, but among the
+beautifullest trees, and with the roses a-covering our Beein to the
+roof. Theer come along one day, when I was out a-working on the land, a
+traveller from our own Norfolk or Suffolk in England (I doen't rightly
+mind which), and of course we took him in, and giv him to eat and drink,
+and made him welcome. We all do that, all the colony over. He'd got an
+old newspaper with him, and some other account in print of the storm.
+That's how she know'd it. When I came home at night, I found she know'd
+it.'
+
+He dropped his voice as he said these words, and the gravity I so well
+remembered overspread his face.
+
+'Did it change her much?' we asked.
+
+'Aye, for a good long time,' he said, shaking his head; 'if not to this
+present hour. But I think the solitoode done her good. And she had a
+deal to mind in the way of poultry and the like, and minded of it, and
+come through. I wonder,' he said thoughtfully, 'if you could see my
+Em'ly now, Mas'r Davy, whether you'd know her!'
+
+'Is she so altered?' I inquired.
+
+'I doen't know. I see her ev'ry day, and doen't know; But, odd-times, I
+have thowt so. A slight figure,' said Mr. Peggotty, looking at the fire,
+'kiender worn; soft, sorrowful, blue eyes; a delicate face; a pritty
+head, leaning a little down; a quiet voice and way--timid a'most. That's
+Em'ly!'
+
+We silently observed him as he sat, still looking at the fire.
+
+'Some thinks,' he said, 'as her affection was ill-bestowed; some, as her
+marriage was broken off by death. No one knows how 'tis. She might have
+married well, a mort of times, "but, uncle," she says to me, "that's
+gone for ever." Cheerful along with me; retired when others is by;
+fond of going any distance fur to teach a child, or fur to tend a sick
+person, or fur to do some kindness tow'rds a young girl's wedding (and
+she's done a many, but has never seen one); fondly loving of her uncle;
+patient; liked by young and old; sowt out by all that has any trouble.
+That's Em'ly!'
+
+He drew his hand across his face, and with a half-suppressed sigh looked
+up from the fire.
+
+'Is Martha with you yet?' I asked.
+
+'Martha,' he replied, 'got married, Mas'r Davy, in the second year. A
+young man, a farm-labourer, as come by us on his way to market with his
+mas'r's drays--a journey of over five hundred mile, theer and back--made
+offers fur to take her fur his wife (wives is very scarce theer), and
+then to set up fur their two selves in the Bush. She spoke to me fur to
+tell him her trew story. I did. They was married, and they live fower
+hundred mile away from any voices but their own and the singing birds.'
+
+'Mrs. Gummidge?' I suggested.
+
+It was a pleasant key to touch, for Mr. Peggotty suddenly burst into a
+roar of laughter, and rubbed his hands up and down his legs, as he had
+been accustomed to do when he enjoyed himself in the long-shipwrecked
+boat.
+
+'Would you believe it!' he said. 'Why, someun even made offer fur to
+marry her! If a ship's cook that was turning settler, Mas'r Davy, didn't
+make offers fur to marry Missis Gummidge, I'm Gormed--and I can't say no
+fairer than that!'
+
+I never saw Agnes laugh so. This sudden ecstasy on the part of Mr.
+Peggotty was so delightful to her, that she could not leave off
+laughing; and the more she laughed the more she made me laugh, and the
+greater Mr. Peggotty's ecstasy became, and the more he rubbed his legs.
+
+'And what did Mrs. Gummidge say?' I asked, when I was grave enough.
+
+'If you'll believe me,' returned Mr. Peggotty, 'Missis Gummidge, 'stead
+of saying "thank you, I'm much obleeged to you, I ain't a-going fur
+to change my condition at my time of life," up'd with a bucket as was
+standing by, and laid it over that theer ship's cook's head 'till he
+sung out fur help, and I went in and reskied of him.'
+
+Mr. Peggotty burst into a great roar of laughter, and Agnes and I both
+kept him company.
+
+'But I must say this, for the good creetur,' he resumed, wiping his
+face, when we were quite exhausted; 'she has been all she said she'd
+be to us, and more. She's the willingest, the trewest, the
+honestest-helping woman, Mas'r Davy, as ever draw'd the breath of life.
+I have never know'd her to be lone and lorn, for a single minute,
+not even when the colony was all afore us, and we was new to it. And
+thinking of the old 'un is a thing she never done, I do assure you,
+since she left England!'
+
+'Now, last, not least, Mr. Micawber,' said I. 'He has paid off every
+obligation he incurred here--even to Traddles's bill, you remember my
+dear Agnes--and therefore we may take it for granted that he is doing
+well. But what is the latest news of him?'
+
+Mr. Peggotty, with a smile, put his hand in his breast-pocket, and
+produced a flat-folded, paper parcel, from which he took out, with much
+care, a little odd-looking newspaper.
+
+'You are to understan', Mas'r Davy,' said he, 'as we have left the
+Bush now, being so well to do; and have gone right away round to Port
+Middlebay Harbour, wheer theer's what we call a town.'
+
+'Mr. Micawber was in the Bush near you?' said I.
+
+'Bless you, yes,' said Mr. Peggotty, 'and turned to with a will. I never
+wish to meet a better gen'l'man for turning to with a will. I've seen
+that theer bald head of his a perspiring in the sun, Mas'r Davy, till I
+a'most thowt it would have melted away. And now he's a Magistrate.'
+
+'A Magistrate, eh?' said I.
+
+Mr. Peggotty pointed to a certain paragraph in the newspaper, where I
+read aloud as follows, from the Port Middlebay Times:
+
+
+'The public dinner to our distinguished fellow-colonist and townsman,
+WILKINS MICAWBER, ESQUIRE, Port Middlebay District Magistrate, came
+off yesterday in the large room of the Hotel, which was crowded to
+suffocation. It is estimated that not fewer than forty-seven persons
+must have been accommodated with dinner at one time, exclusive of the
+company in the passage and on the stairs. The beauty, fashion, and
+exclusiveness of Port Middlebay, flocked to do honour to one so
+deservedly esteemed, so highly talented, and so widely popular. Doctor
+Mell (of Colonial Salem-House Grammar School, Port Middlebay) presided,
+and on his right sat the distinguished guest. After the removal of the
+cloth, and the singing of Non Nobis (beautifully executed, and in which
+we were at no loss to distinguish the bell-like notes of that gifted
+amateur, WILKINS MICAWBER, ESQUIRE, JUNIOR), the usual loyal and
+patriotic toasts were severally given and rapturously received. Doctor
+Mell, in a speech replete with feeling, then proposed "Our distinguished
+Guest, the ornament of our town. May he never leave us but to better
+himself, and may his success among us be such as to render his bettering
+himself impossible!" The cheering with which the toast was received
+defies description. Again and again it rose and fell, like the waves
+of ocean. At length all was hushed, and WILKINS MICAWBER, ESQUIRE,
+presented himself to return thanks. Far be it from us, in the present
+comparatively imperfect state of the resources of our establishment,
+to endeavour to follow our distinguished townsman through the
+smoothly-flowing periods of his polished and highly-ornate address!
+Suffice it to observe, that it was a masterpiece of eloquence; and that
+those passages in which he more particularly traced his own successful
+career to its source, and warned the younger portion of his auditory
+from the shoals of ever incurring pecuniary liabilities which they were
+unable to liquidate, brought a tear into the manliest eye present. The
+remaining toasts were DOCTOR MELL; Mrs. MICAWBER (who gracefully bowed
+her acknowledgements from the side-door, where a galaxy of beauty was
+elevated on chairs, at once to witness and adorn the gratifying scene),
+Mrs. RIDGER BEGS (late Miss Micawber); Mrs. MELL; WILKINS MICAWBER,
+ESQUIRE, JUNIOR (who convulsed the assembly by humorously remarking that
+he found himself unable to return thanks in a speech, but would do so,
+with their permission, in a song); Mrs. MICAWBER'S FAMILY (well known,
+it is needless to remark, in the mother-country), &c. &c. &c. At the
+conclusion of the proceedings the tables were cleared as if by art-magic
+for dancing. Among the votaries of TERPSICHORE, who disported themselves
+until Sol gave warning for departure, Wilkins Micawber, Esquire, Junior,
+and the lovely and accomplished Miss Helena, fourth daughter of Doctor
+Mell, were particularly remarkable.'
+
+
+I was looking back to the name of Doctor Mell, pleased to have
+discovered, in these happier circumstances, Mr. Mell, formerly poor
+pinched usher to my Middlesex magistrate, when Mr. Peggotty pointing
+to another part of the paper, my eyes rested on my own name, and I read
+thus:
+
+
+'TO DAVID COPPERFIELD, ESQUIRE,
+
+'THE EMINENT AUTHOR.
+
+'My Dear Sir,
+
+'Years have elapsed, since I had an opportunity of ocularly perusing the
+lineaments, now familiar to the imaginations of a considerable portion
+of the civilized world.
+
+'But, my dear Sir, though estranged (by the force of circumstances over
+which I have had no control) from the personal society of the friend and
+companion of my youth, I have not been unmindful of his soaring flight.
+Nor have I been debarred,
+
+     Though seas between us braid ha' roared,
+
+(BURNS) from participating in the intellectual feasts he has spread
+before us.
+
+'I cannot, therefore, allow of the departure from this place of an
+individual whom we mutually respect and esteem, without, my dear Sir,
+taking this public opportunity of thanking you, on my own behalf, and,
+I may undertake to add, on that of the whole of the Inhabitants of Port
+Middlebay, for the gratification of which you are the ministering agent.
+
+'Go on, my dear Sir! You are not unknown here, you are not
+unappreciated. Though "remote", we are neither "unfriended",
+"melancholy", nor (I may add) "slow". Go on, my dear Sir, in your Eagle
+course! The inhabitants of Port Middlebay may at least aspire to watch
+it, with delight, with entertainment, with instruction!
+
+'Among the eyes elevated towards you from this portion of the globe,
+will ever be found, while it has light and life,
+
+               'The
+                    'Eye
+                         'Appertaining to
+
+                              'WILKINS MICAWBER,
+                                   'Magistrate.'
+
+
+I found, on glancing at the remaining contents of the newspaper, that
+Mr. Micawber was a diligent and esteemed correspondent of that journal.
+There was another letter from him in the same paper, touching a bridge;
+there was an advertisement of a collection of similar letters by him, to
+be shortly republished, in a neat volume, 'with considerable additions';
+and, unless I am very much mistaken, the Leading Article was his also.
+
+We talked much of Mr. Micawber, on many other evenings while Mr.
+Peggotty remained with us. He lived with us during the whole term of his
+stay,--which, I think, was something less than a month,--and his sister
+and my aunt came to London to see him. Agnes and I parted from him
+aboard-ship, when he sailed; and we shall never part from him more, on
+earth.
+
+But before he left, he went with me to Yarmouth, to see a little tablet
+I had put up in the churchyard to the memory of Ham. While I was copying
+the plain inscription for him at his request, I saw him stoop, and
+gather a tuft of grass from the grave and a little earth.
+
+'For Em'ly,' he said, as he put it in his breast. 'I promised, Mas'r
+Davy.'
+
+
+
+CHAPTER 64. A LAST RETROSPECT
+
+
+And now my written story ends. I look back, once more--for the last
+time--before I close these leaves.
+
+I see myself, with Agnes at my side, journeying along the road of life.
+I see our children and our friends around us; and I hear the roar of
+many voices, not indifferent to me as I travel on.
+
+What faces are the most distinct to me in the fleeting crowd? Lo, these;
+all turning to me as I ask my thoughts the question!
+
+Here is my aunt, in stronger spectacles, an old woman of four-score
+years and more, but upright yet, and a steady walker of six miles at a
+stretch in winter weather.
+
+Always with her, here comes Peggotty, my good old nurse, likewise in
+spectacles, accustomed to do needle-work at night very close to the
+lamp, but never sitting down to it without a bit of wax candle, a
+yard-measure in a little house, and a work-box with a picture of St.
+Paul's upon the lid.
+
+The cheeks and arms of Peggotty, so hard and red in my childish days,
+when I wondered why the birds didn't peck her in preference to apples,
+are shrivelled now; and her eyes, that used to darken their whole
+neighbourhood in her face, are fainter (though they glitter still);
+but her rough forefinger, which I once associated with a pocket
+nutmeg-grater, is just the same, and when I see my least child catching
+at it as it totters from my aunt to her, I think of our little parlour
+at home, when I could scarcely walk. My aunt's old disappointment is set
+right, now. She is godmother to a real living Betsey Trotwood; and Dora
+(the next in order) says she spoils her.
+
+There is something bulky in Peggotty's pocket. It is nothing smaller
+than the Crocodile Book, which is in rather a dilapidated condition by
+this time, with divers of the leaves torn and stitched across, but which
+Peggotty exhibits to the children as a precious relic. I find it very
+curious to see my own infant face, looking up at me from the Crocodile
+stories; and to be reminded by it of my old acquaintance Brooks of
+Sheffield.
+
+Among my boys, this summer holiday time, I see an old man making giant
+kites, and gazing at them in the air, with a delight for which there
+are no words. He greets me rapturously, and whispers, with many nods
+and winks, 'Trotwood, you will be glad to hear that I shall finish the
+Memorial when I have nothing else to do, and that your aunt's the most
+extraordinary woman in the world, sir!'
+
+Who is this bent lady, supporting herself by a stick, and showing me
+a countenance in which there are some traces of old pride and beauty,
+feebly contending with a querulous, imbecile, fretful wandering of the
+mind? She is in a garden; and near her stands a sharp, dark, withered
+woman, with a white scar on her lip. Let me hear what they say.
+
+'Rosa, I have forgotten this gentleman's name.'
+
+Rosa bends over her, and calls to her, 'Mr. Copperfield.'
+
+'I am glad to see you, sir. I am sorry to observe you are in mourning. I
+hope Time will be good to you.'
+
+Her impatient attendant scolds her, tells her I am not in mourning, bids
+her look again, tries to rouse her.
+
+'You have seen my son, sir,' says the elder lady. 'Are you reconciled?'
+
+Looking fixedly at me, she puts her hand to her forehead, and moans.
+Suddenly, she cries, in a terrible voice, 'Rosa, come to me. He is
+dead!' Rosa kneeling at her feet, by turns caresses her, and quarrels
+with her; now fiercely telling her, 'I loved him better than you ever
+did!'--now soothing her to sleep on her breast, like a sick child. Thus
+I leave them; thus I always find them; thus they wear their time away,
+from year to year.
+
+What ship comes sailing home from India, and what English lady is this,
+married to a growling old Scotch Croesus with great flaps of ears? Can
+this be Julia Mills?
+
+Indeed it is Julia Mills, peevish and fine, with a black man to carry
+cards and letters to her on a golden salver, and a copper-coloured woman
+in linen, with a bright handkerchief round her head, to serve her Tiffin
+in her dressing-room. But Julia keeps no diary in these days; never
+sings Affection's Dirge; eternally quarrels with the old Scotch Croesus,
+who is a sort of yellow bear with a tanned hide. Julia is steeped in
+money to the throat, and talks and thinks of nothing else. I liked her
+better in the Desert of Sahara.
+
+Or perhaps this IS the Desert of Sahara! For, though Julia has a stately
+house, and mighty company, and sumptuous dinners every day, I see no
+green growth near her; nothing that can ever come to fruit or flower.
+What Julia calls 'society', I see; among it Mr. Jack Maldon, from his
+Patent Place, sneering at the hand that gave it him, and speaking to me
+of the Doctor as 'so charmingly antique'. But when society is the name
+for such hollow gentlemen and ladies, Julia, and when its breeding is
+professed indifference to everything that can advance or can retard
+mankind, I think we must have lost ourselves in that same Desert of
+Sahara, and had better find the way out.
+
+And lo, the Doctor, always our good friend, labouring at his Dictionary
+(somewhere about the letter D), and happy in his home and wife. Also
+the Old Soldier, on a considerably reduced footing, and by no means so
+influential as in days of yore!
+
+Working at his chambers in the Temple, with a busy aspect, and his hair
+(where he is not bald) made more rebellious than ever by the constant
+friction of his lawyer's-wig, I come, in a later time, upon my dear old
+Traddles. His table is covered with thick piles of papers; and I say, as
+I look around me:
+
+'If Sophy were your clerk, now, Traddles, she would have enough to do!'
+
+'You may say that, my dear Copperfield! But those were capital days,
+too, in Holborn Court! Were they not?'
+
+'When she told you you would be a judge? But it was not the town talk
+then!'
+
+'At all events,' says Traddles, 'if I ever am one--' 'Why, you know you
+will be.'
+
+'Well, my dear Copperfield, WHEN I am one, I shall tell the story, as I
+said I would.'
+
+We walk away, arm in arm. I am going to have a family dinner with
+Traddles. It is Sophy's birthday; and, on our road, Traddles discourses
+to me of the good fortune he has enjoyed.
+
+'I really have been able, my dear Copperfield, to do all that I had most
+at heart. There's the Reverend Horace promoted to that living at four
+hundred and fifty pounds a year; there are our two boys receiving the
+very best education, and distinguishing themselves as steady scholars
+and good fellows; there are three of the girls married very comfortably;
+there are three more living with us; there are three more keeping house
+for the Reverend Horace since Mrs. Crewler's decease; and all of them
+happy.'
+
+'Except--' I suggest.
+
+'Except the Beauty,' says Traddles. 'Yes. It was very unfortunate that
+she should marry such a vagabond. But there was a certain dash and glare
+about him that caught her. However, now we have got her safe at our
+house, and got rid of him, we must cheer her up again.'
+
+Traddles's house is one of the very houses--or it easily may have
+been--which he and Sophy used to parcel out, in their evening walks. It
+is a large house; but Traddles keeps his papers in his dressing-room
+and his boots with his papers; and he and Sophy squeeze themselves into
+upper rooms, reserving the best bedrooms for the Beauty and the girls.
+There is no room to spare in the house; for more of 'the girls' are
+here, and always are here, by some accident or other, than I know how
+to count. Here, when we go in, is a crowd of them, running down to
+the door, and handing Traddles about to be kissed, until he is out of
+breath. Here, established in perpetuity, is the poor Beauty, a widow
+with a little girl; here, at dinner on Sophy's birthday, are the three
+married girls with their three husbands, and one of the husband's
+brothers, and another husband's cousin, and another husband's sister,
+who appears to me to be engaged to the cousin. Traddles, exactly the
+same simple, unaffected fellow as he ever was, sits at the foot of the
+large table like a Patriarch; and Sophy beams upon him, from the head,
+across a cheerful space that is certainly not glittering with Britannia
+metal.
+
+And now, as I close my task, subduing my desire to linger yet, these
+faces fade away. But one face, shining on me like a Heavenly light by
+which I see all other objects, is above them and beyond them all. And
+that remains.
+
+I turn my head, and see it, in its beautiful serenity, beside me.
+
+My lamp burns low, and I have written far into the night; but the dear
+presence, without which I were nothing, bears me company.
+
+O Agnes, O my soul, so may thy face be by me when I close my life
+indeed; so may I, when realities are melting from me, like the shadows
+which I now dismiss, still find thee near me, pointing upward!
+
+
+
+
+
+
+End of the Project Gutenberg EBook of David Copperfield, by Charles Dickens
+
+*** END OF THIS PROJECT GUTENBERG EBOOK DAVID COPPERFIELD ***
+
+***** This file should be named 766.txt or 766.zip *****
+This and all associated files of various formats will be found in:
+        http://www.gutenberg.org/7/6/766/
+
+Produced by Jo Churcher
+
+Updated editions will replace the previous one--the old editions
+will be renamed.
+
+Creating the works from public domain print editions means that no
+one owns a United States copyright in these works, so the Foundation
+(and you!) can copy and distribute it in the United States without
+permission and without paying copyright royalties.  Special rules,
+set forth in the General Terms of Use part of this license, apply to
+copying and distributing Project Gutenberg-tm electronic works to
+protect the PROJECT GUTENBERG-tm concept and trademark.  Project
+Gutenberg is a registered trademark, and may not be used if you
+charge for the eBooks, unless you receive specific permission.  If you
+do not charge anything for copies of this eBook, complying with the
+rules is very easy.  You may use this eBook for nearly any purpose
+such as creation of derivative works, reports, performances and
+research.  They may be modified and printed and given away--you may do
+practically ANYTHING with public domain eBooks.  Redistribution is
+subject to the trademark license, especially commercial
+redistribution.
+
+
+
+*** START: FULL LICENSE ***
+
+THE FULL PROJECT GUTENBERG LICENSE
+PLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK
+
+To protect the Project Gutenberg-tm mission of promoting the free
+distribution of electronic works, by using or distributing this work
+(or any other work associated in any way with the phrase "Project
+Gutenberg"), you agree to comply with all the terms of the Full Project
+Gutenberg-tm License (available with this file or online at
+http://gutenberg.org/license).
+
+
+Section 1.  General Terms of Use and Redistributing Project Gutenberg-tm
+electronic works
+
+1.A.  By reading or using any part of this Project Gutenberg-tm
+electronic work, you indicate that you have read, understand, agree to
+and accept all the terms of this license and intellectual property
+(trademark/copyright) agreement.  If you do not agree to abide by all
+the terms of this agreement, you must cease using and return or destroy
+all copies of Project Gutenberg-tm electronic works in your possession.
+If you paid a fee for obtaining a copy of or access to a Project
+Gutenberg-tm electronic work and you do not agree to be bound by the
+terms of this agreement, you may obtain a refund from the person or
+entity to whom you paid the fee as set forth in paragraph 1.E.8.
+
+1.B.  "Project Gutenberg" is a registered trademark.  It may only be
+used on or associated in any way with an electronic work by people who
+agree to be bound by the terms of this agreement.  There are a few
+things that you can do with most Project Gutenberg-tm electronic works
+even without complying with the full terms of this agreement.  See
+paragraph 1.C below.  There are a lot of things you can do with Project
+Gutenberg-tm electronic works if you follow the terms of this agreement
+and help preserve free future access to Project Gutenberg-tm electronic
+works.  See paragraph 1.E below.
+
+1.C.  The Project Gutenberg Literary Archive Foundation ("the Foundation"
+or PGLAF), owns a compilation copyright in the collection of Project
+Gutenberg-tm electronic works.  Nearly all the individual works in the
+collection are in the public domain in the United States.  If an
+individual work is in the public domain in the United States and you are
+located in the United States, we do not claim a right to prevent you from
+copying, distributing, performing, displaying or creating derivative
+works based on the work as long as all references to Project Gutenberg
+are removed.  Of course, we hope that you will support the Project
+Gutenberg-tm mission of promoting free access to electronic works by
+freely sharing Project Gutenberg-tm works in compliance with the terms of
+this agreement for keeping the Project Gutenberg-tm name associated with
+the work.  You can easily comply with the terms of this agreement by
+keeping this work in the same format with its attached full Project
+Gutenberg-tm License when you share it without charge with others.
+
+1.D.  The copyright laws of the place where you are located also govern
+what you can do with this work.  Copyright laws in most countries are in
+a constant state of change.  If you are outside the United States, check
+the laws of your country in addition to the terms of this agreement
+before downloading, copying, displaying, performing, distributing or
+creating derivative works based on this work or any other Project
+Gutenberg-tm work.  The Foundation makes no representations concerning
+the copyright status of any work in any country outside the United
+States.
+
+1.E.  Unless you have removed all references to Project Gutenberg:
+
+1.E.1.  The following sentence, with active links to, or other immediate
+access to, the full Project Gutenberg-tm License must appear prominently
+whenever any copy of a Project Gutenberg-tm work (any work on which the
+phrase "Project Gutenberg" appears, or with which the phrase "Project
+Gutenberg" is associated) is accessed, displayed, performed, viewed,
+copied or distributed:
+
+This eBook is for the use of anyone anywhere at no cost and with
+almost no restrictions whatsoever.  You may copy it, give it away or
+re-use it under the terms of the Project Gutenberg License included
+with this eBook or online at www.gutenberg.org
+
+1.E.2.  If an individual Project Gutenberg-tm electronic work is derived
+from the public domain (does not contain a notice indicating that it is
+posted with permission of the copyright holder), the work can be copied
+and distributed to anyone in the United States without paying any fees
+or charges.  If you are redistributing or providing access to a work
+with the phrase "Project Gutenberg" associated with or appearing on the
+work, you must comply either with the requirements of paragraphs 1.E.1
+through 1.E.7 or obtain permission for the use of the work and the
+Project Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or
+1.E.9.
+
+1.E.3.  If an individual Project Gutenberg-tm electronic work is posted
+with the permission of the copyright holder, your use and distribution
+must comply with both paragraphs 1.E.1 through 1.E.7 and any additional
+terms imposed by the copyright holder.  Additional terms will be linked
+to the Project Gutenberg-tm License for all works posted with the
+permission of the copyright holder found at the beginning of this work.
+
+1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm
+License terms from this work, or any files containing a part of this
+work or any other work associated with Project Gutenberg-tm.
+
+1.E.5.  Do not copy, display, perform, distribute or redistribute this
+electronic work, or any part of this electronic work, without
+prominently displaying the sentence set forth in paragraph 1.E.1 with
+active links or immediate access to the full terms of the Project
+Gutenberg-tm License.
+
+1.E.6.  You may convert to and distribute this work in any binary,
+compressed, marked up, nonproprietary or proprietary form, including any
+word processing or hypertext form.  However, if you provide access to or
+distribute copies of a Project Gutenberg-tm work in a format other than
+"Plain Vanilla ASCII" or other format used in the official version
+posted on the official Project Gutenberg-tm web site (www.gutenberg.org),
+you must, at no additional cost, fee or expense to the user, provide a
+copy, a means of exporting a copy, or a means of obtaining a copy upon
+request, of the work in its original "Plain Vanilla ASCII" or other
+form.  Any alternate format must include the full Project Gutenberg-tm
+License as specified in paragraph 1.E.1.
+
+1.E.7.  Do not charge a fee for access to, viewing, displaying,
+performing, copying or distributing any Project Gutenberg-tm works
+unless you comply with paragraph 1.E.8 or 1.E.9.
+
+1.E.8.  You may charge a reasonable fee for copies of or providing
+access to or distributing Project Gutenberg-tm electronic works provided
+that
+
+- You pay a royalty fee of 20% of the gross profits you derive from
+     the use of Project Gutenberg-tm works calculated using the method
+     you already use to calculate your applicable taxes.  The fee is
+     owed to the owner of the Project Gutenberg-tm trademark, but he
+     has agreed to donate royalties under this paragraph to the
+     Project Gutenberg Literary Archive Foundation.  Royalty payments
+     must be paid within 60 days following each date on which you
+     prepare (or are legally required to prepare) your periodic tax
+     returns.  Royalty payments should be clearly marked as such and
+     sent to the Project Gutenberg Literary Archive Foundation at the
+     address specified in Section 4, "Information about donations to
+     the Project Gutenberg Literary Archive Foundation."
+
+- You provide a full refund of any money paid by a user who notifies
+     you in writing (or by e-mail) within 30 days of receipt that s/he
+     does not agree to the terms of the full Project Gutenberg-tm
+     License.  You must require such a user to return or
+     destroy all copies of the works possessed in a physical medium
+     and discontinue all use of and all access to other copies of
+     Project Gutenberg-tm works.
+
+- You provide, in accordance with paragraph 1.F.3, a full refund of any
+     money paid for a work or a replacement copy, if a defect in the
+     electronic work is discovered and reported to you within 90 days
+     of receipt of the work.
+
+- You comply with all other terms of this agreement for free
+     distribution of Project Gutenberg-tm works.
+
+1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm
+electronic work or group of works on different terms than are set
+forth in this agreement, you must obtain permission in writing from
+both the Project Gutenberg Literary Archive Foundation and Michael
+Hart, the owner of the Project Gutenberg-tm trademark.  Contact the
+Foundation as set forth in Section 3 below.
+
+1.F.
+
+1.F.1.  Project Gutenberg volunteers and employees expend considerable
+effort to identify, do copyright research on, transcribe and proofread
+public domain works in creating the Project Gutenberg-tm
+collection.  Despite these efforts, Project Gutenberg-tm electronic
+works, and the medium on which they may be stored, may contain
+"Defects," such as, but not limited to, incomplete, inaccurate or
+corrupt data, transcription errors, a copyright or other intellectual
+property infringement, a defective or damaged disk or other medium, a
+computer virus, or computer codes that damage or cannot be read by
+your equipment.
+
+1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the "Right
+of Replacement or Refund" described in paragraph 1.F.3, the Project
+Gutenberg Literary Archive Foundation, the owner of the Project
+Gutenberg-tm trademark, and any other party distributing a Project
+Gutenberg-tm electronic work under this agreement, disclaim all
+liability to you for damages, costs and expenses, including legal
+fees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT
+LIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE
+PROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE
+TRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE
+LIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR
+INCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a
+defect in this electronic work within 90 days of receiving it, you can
+receive a refund of the money (if any) you paid for it by sending a
+written explanation to the person you received the work from.  If you
+received the work on a physical medium, you must return the medium with
+your written explanation.  The person or entity that provided you with
+the defective work may elect to provide a replacement copy in lieu of a
+refund.  If you received the work electronically, the person or entity
+providing it to you may choose to give you a second opportunity to
+receive the work electronically in lieu of a refund.  If the second copy
+is also defective, you may demand a refund in writing without further
+opportunities to fix the problem.
+
+1.F.4.  Except for the limited right of replacement or refund set forth
+in paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER
+WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
+WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.
+
+1.F.5.  Some states do not allow disclaimers of certain implied
+warranties or the exclusion or limitation of certain types of damages.
+If any disclaimer or limitation set forth in this agreement violates the
+law of the state applicable to this agreement, the agreement shall be
+interpreted to make the maximum disclaimer or limitation permitted by
+the applicable state law.  The invalidity or unenforceability of any
+provision of this agreement shall not void the remaining provisions.
+
+1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the
+trademark owner, any agent or employee of the Foundation, anyone
+providing copies of Project Gutenberg-tm electronic works in accordance
+with this agreement, and any volunteers associated with the production,
+promotion and distribution of Project Gutenberg-tm electronic works,
+harmless from all liability, costs and expenses, including legal fees,
+that arise directly or indirectly from any of the following which you do
+or cause to occur: (a) distribution of this or any Project Gutenberg-tm
+work, (b) alteration, modification, or additions or deletions to any
+Project Gutenberg-tm work, and (c) any Defect you cause.
+
+
+Section  2.  Information about the Mission of Project Gutenberg-tm
+
+Project Gutenberg-tm is synonymous with the free distribution of
+electronic works in formats readable by the widest variety of computers
+including obsolete, old, middle-aged and new computers.  It exists
+because of the efforts of hundreds of volunteers and donations from
+people in all walks of life.
+
+Volunteers and financial support to provide volunteers with the
+assistance they need, are critical to reaching Project Gutenberg-tm's
+goals and ensuring that the Project Gutenberg-tm collection will
+remain freely available for generations to come.  In 2001, the Project
+Gutenberg Literary Archive Foundation was created to provide a secure
+and permanent future for Project Gutenberg-tm and future generations.
+To learn more about the Project Gutenberg Literary Archive Foundation
+and how your efforts and donations can help, see Sections 3 and 4
+and the Foundation web page at http://www.pglaf.org.
+
+
+Section 3.  Information about the Project Gutenberg Literary Archive
+Foundation
+
+The Project Gutenberg Literary Archive Foundation is a non profit
+501(c)(3) educational corporation organized under the laws of the
+state of Mississippi and granted tax exempt status by the Internal
+Revenue Service.  The Foundation's EIN or federal tax identification
+number is 64-6221541.  Its 501(c)(3) letter is posted at
+http://pglaf.org/fundraising.  Contributions to the Project Gutenberg
+Literary Archive Foundation are tax deductible to the full extent
+permitted by U.S. federal laws and your state's laws.
+
+The Foundation's principal office is located at 4557 Melan Dr. S.
+Fairbanks, AK, 99712., but its volunteers and employees are scattered
+throughout numerous locations.  Its business office is located at
+809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email
+business at pglaf.org.  Email contact links and up to date contact
+information can be found at the Foundation's web site and official
+page at http://pglaf.org
+
+For additional contact information:
+     Dr. Gregory B. Newby
+     Chief Executive and Director
+     gbnewby at pglaf.org
+
+
+Section 4.  Information about Donations to the Project Gutenberg
+Literary Archive Foundation
+
+Project Gutenberg-tm depends upon and cannot survive without wide
+spread public support and donations to carry out its mission of
+increasing the number of public domain and licensed works that can be
+freely distributed in machine readable form accessible by the widest
+array of equipment including outdated equipment.  Many small donations
+($1 to $5,000) are particularly important to maintaining tax exempt
+status with the IRS.
+
+The Foundation is committed to complying with the laws regulating
+charities and charitable donations in all 50 states of the United
+States.  Compliance requirements are not uniform and it takes a
+considerable effort, much paperwork and many fees to meet and keep up
+with these requirements.  We do not solicit donations in locations
+where we have not received written confirmation of compliance.  To
+SEND DONATIONS or determine the status of compliance for any
+particular state visit http://pglaf.org
+
+While we cannot and do not solicit contributions from states where we
+have not met the solicitation requirements, we know of no prohibition
+against accepting unsolicited donations from donors in such states who
+approach us with offers to donate.
+
+International donations are gratefully accepted, but we cannot make
+any statements concerning tax treatment of donations received from
+outside the United States.  U.S. laws alone swamp our small staff.
+
+Please check the Project Gutenberg Web pages for current donation
+methods and addresses.  Donations are accepted in a number of other
+ways including checks, online payments and credit card donations.
+To donate, please visit: http://pglaf.org/donate
+
+
+Section 5.  General Information About Project Gutenberg-tm electronic
+works.
+
+Professor Michael S. Hart is the originator of the Project Gutenberg-tm
+concept of a library of electronic works that could be freely shared
+with anyone.  For thirty years, he produced and distributed Project
+Gutenberg-tm eBooks with only a loose network of volunteer support.
+
+
+Project Gutenberg-tm eBooks are often created from several printed
+editions, all of which are confirmed as Public Domain in the U.S.
+unless a copyright notice is included.  Thus, we do not necessarily
+keep eBooks in compliance with any particular paper edition.
+
+
+Most people start at our Web site which has the main PG search facility:
+
+     http://www.gutenberg.org
+
+This Web site includes information about Project Gutenberg-tm,
+including how to make donations to the Project Gutenberg Literary
+Archive Foundation, how to help produce our new eBooks, and how to
+subscribe to our email newsletter to hear about new eBooks.
diff --git a/Axantum.AxCrypt.Core.Test/resources/helloworld-key-a-txt.axx b/Axantum.AxCrypt.Core.Test/resources/helloworld-key-a-txt.axx
new file mode 100644
index 0000000..f616543
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/helloworld-key-a-txt.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/short-txt-AES256.axx b/Axantum.AxCrypt.Core.Test/resources/short-txt-AES256.axx
new file mode 100644
index 0000000..d80a6b1
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/short-txt-AES256.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/short-txt-V2AES128.axx b/Axantum.AxCrypt.Core.Test/resources/short-txt-V2AES128.axx
new file mode 100644
index 0000000..76260e3
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/short-txt-V2AES128.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/snow-jpg-AES256.axx b/Axantum.AxCrypt.Core.Test/resources/snow-jpg-AES256.axx
new file mode 100644
index 0000000..9aaa356
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/snow-jpg-AES256.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/snow-jpg-V2AES128.axx b/Axantum.AxCrypt.Core.Test/resources/snow-jpg-V2AES128.axx
new file mode 100644
index 0000000..d65d82e
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/snow-jpg-V2AES128.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/tst-0.0b6-key-'aaaeoe'-medium-html.axx b/Axantum.AxCrypt.Core.Test/resources/tst-0.0b6-key-'aaaeoe'-medium-html.axx
new file mode 100644
index 0000000..9076868
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/tst-0.0b6-key-'aaaeoe'-medium-html.axx differ
diff --git a/Axantum.AxCrypt.Core.Test/resources/uncompressable-zip.axx b/Axantum.AxCrypt.Core.Test/resources/uncompressable-zip.axx
new file mode 100644
index 0000000..81fd3b4
Binary files /dev/null and b/Axantum.AxCrypt.Core.Test/resources/uncompressable-zip.axx differ
diff --git a/Axantum.AxCrypt.Core/AboutThisAssembly.txt b/Axantum.AxCrypt.Core/AboutThisAssembly.txt
new file mode 100644
index 0000000..498f818
--- /dev/null
+++ b/Axantum.AxCrypt.Core/AboutThisAssembly.txt
@@ -0,0 +1,11 @@
+About Axantum.AxCrypt.Core.dll
+
+This assembly contains all core platform-independent functionality.
+
+It must only depend on Mono-compatible assemblies for .NET 3.5 / 2.0.
+
+It must not depend on any other Axantum.AxCrypt.* assembly.
+
+Code coverage should be 100% by unit tests in Axantum.AxCrypt.Core.Test .
+
+FxCop should pass without complaint.
diff --git a/Axantum.AxCrypt.Core/AxCryptFactory.cs b/Axantum.AxCrypt.Core/AxCryptFactory.cs
new file mode 100644
index 0000000..4ea96b4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/AxCryptFactory.cs
@@ -0,0 +1,118 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    public class AxCryptFactory
+    {
+        public virtual Guid TryFindCryptoId(Passphrase passphrase, IRuntimeFileInfo encryptedFileInfo, IEnumerable<Guid> cryptoIds)
+        {
+            foreach (Guid cryptoId in cryptoIds)
+            {
+                if (TryOneCryptoId(passphrase, encryptedFileInfo, cryptoId))
+                {
+                    return cryptoId;
+                }
+            }
+            return Guid.Empty;
+        }
+
+        private static bool TryOneCryptoId(Passphrase passphrase, IRuntimeFileInfo encryptedFileInfo, Guid cryptoId)
+        {
+            using (Stream encryptedStream = encryptedFileInfo.OpenRead())
+            {
+                Headers headers = new Headers();
+                AxCryptReader reader = headers.Load(encryptedStream);
+
+                using (IAxCryptDocument document = reader.Document(passphrase, cryptoId, headers))
+                {
+                    if (document.PassphraseIsValid)
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        public virtual IAxCryptDocument CreateDocument(Passphrase key, Guid cryptoId)
+        {
+            ICryptoFactory factory = Instance.CryptoFactory.Create(cryptoId);
+            if (factory.Id == Instance.CryptoFactory.Legacy.Id)
+            {
+                return new V1AxCryptDocument(key, Instance.UserSettings.GetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId));
+            }
+            return new V2AxCryptDocument(key, cryptoId, Instance.UserSettings.GetKeyWrapIterations(cryptoId));
+        }
+
+        /// <summary>
+        /// Instantiate an instance of IAxCryptDocument appropriate for the file provided, i.e. V1 or V2.
+        /// </summary>
+        /// <param name="passphrase">The passphrase.</param>
+        /// <param name="fileInfo">The file to use.</param>
+        /// <returns></returns>
+        public virtual IAxCryptDocument CreateDocument(Passphrase passphrase, Stream inputStream)
+        {
+            Headers headers = new Headers();
+            AxCryptReader reader = headers.Load(inputStream);
+
+            IEnumerable<Guid> cryptoIds = Instance.CryptoFactory.OrderedIds;
+            IAxCryptDocument document = null;
+            foreach (Guid cryptoId in cryptoIds)
+            {
+                document = reader.Document(passphrase, cryptoId, headers);
+                if (document.PassphraseIsValid)
+                {
+                    return document;
+                }
+            }
+            return document;
+        }
+
+        /// <summary>
+        /// Instantiate an instance of IAxCryptDocument appropriate for the file provided, i.e. V1 or V2.
+        /// </summary>
+        /// <param name="fileInfo"></param>
+        /// <returns></returns>
+        public virtual IAxCryptDocument CreateDocument(Passphrase key, Guid cryptoId, Stream inputStream)
+        {
+            Headers headers = new Headers();
+            AxCryptReader reader = headers.Load(inputStream);
+
+            return reader.Document(key, cryptoId, headers);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/AxCryptFile.cs b/Axantum.AxCrypt.Core/AxCryptFile.cs
new file mode 100644
index 0000000..75a609b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/AxCryptFile.cs
@@ -0,0 +1,662 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core
+{
+    public class AxCryptFile
+    {
+        /// <summary>
+        /// Encrypt a file
+        /// </summary>
+        /// <param name="file">The file to encrypt</param>
+        /// <param name="destination">The destination file</param>
+        /// <remarks>It is the callers responsibility to ensure that the source file exists, that the destination file
+        /// does not exist and can be created etc.</remarks>
+        public virtual void Encrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, Passphrase key, AxCryptOptions options, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationFile == null)
+            {
+                throw new ArgumentNullException("destinationFile");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            using (Stream sourceStream = new ProgressStream(sourceFile.OpenRead(), progress))
+            {
+                using (Stream destinationStream = destinationFile.OpenWrite())
+                {
+                    using (IAxCryptDocument document = new V1AxCryptDocument(key, Instance.UserSettings.GetKeyWrapIterations(V1Aes128CryptoFactory.CryptoId)))
+                    {
+                        document.FileName = sourceFile.Name;
+                        document.CreationTimeUtc = sourceFile.CreationTimeUtc;
+                        document.LastAccessTimeUtc = sourceFile.LastAccessTimeUtc;
+                        document.LastWriteTimeUtc = sourceFile.LastWriteTimeUtc;
+                        document.EncryptTo(sourceStream, destinationStream, options);
+                    }
+                }
+                if (options.HasMask(AxCryptOptions.SetFileTimes))
+                {
+                    destinationFile.SetFileTimes(sourceFile.CreationTimeUtc, sourceFile.LastAccessTimeUtc, sourceFile.LastWriteTimeUtc);
+                }
+            }
+        }
+
+        public void Encrypt(Stream sourceStream, string sourceFileName, IRuntimeFileInfo destinationFileInfo, Passphrase passphrase, Guid cryptoId, AxCryptOptions options, IProgressContext progress)
+        {
+            if (sourceStream == null)
+            {
+                throw new ArgumentNullException("sourceStream");
+            }
+            if (sourceFileName == null)
+            {
+                throw new ArgumentNullException("sourceFileName");
+            }
+            if (destinationFileInfo == null)
+            {
+                throw new ArgumentNullException("destinationFileInfo");
+            }
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            using (Stream destinationStream = destinationFileInfo.OpenWrite())
+            {
+                using (IAxCryptDocument document = Factory.New<AxCryptFactory>().CreateDocument(passphrase, cryptoId))
+                {
+                    document.FileName = sourceFileName;
+                    document.CreationTimeUtc = OS.Current.UtcNow;
+                    document.LastAccessTimeUtc = document.CreationTimeUtc;
+                    document.LastWriteTimeUtc = document.CreationTimeUtc;
+                    document.EncryptTo(sourceStream, destinationStream, options);
+                }
+            }
+        }
+
+        public static void Encrypt(IRuntimeFileInfo sourceFile, Stream destinationStream, Passphrase key, Guid cryptoId, AxCryptOptions options, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationStream == null)
+            {
+                throw new ArgumentNullException("destinationStream");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            using (Stream sourceStream = new ProgressStream(sourceFile.OpenRead(), progress))
+            {
+                using (IAxCryptDocument document = Factory.New<AxCryptFactory>().CreateDocument(key, cryptoId))
+                {
+                    document.FileName = sourceFile.Name;
+                    document.CreationTimeUtc = sourceFile.CreationTimeUtc;
+                    document.LastAccessTimeUtc = sourceFile.LastAccessTimeUtc;
+                    document.LastWriteTimeUtc = sourceFile.LastWriteTimeUtc;
+
+                    document.EncryptTo(sourceStream, destinationStream, options);
+                }
+            }
+        }
+
+        public void EncryptFileWithBackupAndWipe(string sourceFile, string destinationFile, Passphrase key, Guid cryptoId, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationFile == null)
+            {
+                throw new ArgumentNullException("destinationFile");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+            IRuntimeFileInfo sourceFileInfo = Factory.New<IRuntimeFileInfo>(sourceFile);
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFile);
+            EncryptFileWithBackupAndWipe(sourceFileInfo, destinationFileInfo, key, cryptoId, progress);
+        }
+
+        public virtual void EncryptFoldersUniqueWithBackupAndWipe(IEnumerable<IRuntimeFileInfo> folders, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress)
+        {
+            progress.NotifyLevelStart();
+            try
+            {
+                IEnumerable<IRuntimeFileInfo> files = folders.SelectMany((folder) => folder.ListEncryptable());
+                progress.AddTotal(files.Count());
+                foreach (IRuntimeFileInfo file in files)
+                {
+                    EncryptFileUniqueWithBackupAndWipe(file, encryptionKey, cryptoId, progress);
+                    progress.AddCount(1);
+                }
+            }
+            finally
+            {
+                progress.NotifyLevelFinished();
+            }
+        }
+
+        public virtual void EncryptFileUniqueWithBackupAndWipe(IRuntimeFileInfo fileInfo, Passphrase encryptionKey, Guid cryptoId, IProgressContext progress)
+        {
+            IRuntimeFileInfo destinationFileInfo = fileInfo.CreateEncryptedName();
+            destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFileInfo.FullName.CreateUniqueFile());
+            EncryptFileWithBackupAndWipe(fileInfo, destinationFileInfo, encryptionKey, cryptoId, progress);
+        }
+
+        public virtual void EncryptFileWithBackupAndWipe(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFileInfo, Passphrase key, Guid cryptoId, IProgressContext progress)
+        {
+            if (sourceFileInfo == null)
+            {
+                throw new ArgumentNullException("sourceFileInfo");
+            }
+            if (destinationFileInfo == null)
+            {
+                throw new ArgumentNullException("destinationFileInfo");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+            progress.NotifyLevelStart();
+            using (Stream activeFileStream = sourceFileInfo.OpenRead())
+            {
+                WriteToFileWithBackup(destinationFileInfo, (Stream destination) =>
+                {
+                    Encrypt(sourceFileInfo, destination, key, cryptoId, AxCryptOptions.EncryptWithCompression, progress);
+                }, progress);
+            }
+            Wipe(sourceFileInfo, progress);
+            progress.NotifyLevelFinished();
+        }
+
+        public bool Decrypt(IRuntimeFileInfo sourceFile, Stream destinationStream, Passphrase passphrase)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationStream == null)
+            {
+                throw new ArgumentNullException("destinationStream");
+            }
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+
+            using (IAxCryptDocument document = Document(sourceFile, passphrase, new ProgressContext()))
+            {
+                if (!document.PassphraseIsValid)
+                {
+                    return false;
+                }
+                Decrypt(sourceFile.OpenRead(), destinationStream, passphrase, sourceFile.FullName, new ProgressContext());
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Decrypt a source file to a destination file, given a passphrase
+        /// </summary>
+        /// <param name="sourceFile">The source file</param>
+        /// <param name="destinationFile">The destination file</param>
+        /// <param name="passphrase">The passphrase</param>
+        /// <returns>true if the passphrase was correct</returns>
+        public bool Decrypt(IRuntimeFileInfo sourceFile, IRuntimeFileInfo destinationFile, Passphrase passphrase, AxCryptOptions options, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationFile == null)
+            {
+                throw new ArgumentNullException("destinationFile");
+            }
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            using (IAxCryptDocument document = Document(sourceFile, passphrase, new ProgressContext()))
+            {
+                if (!document.PassphraseIsValid)
+                {
+                    return false;
+                }
+                Decrypt(document, destinationFile, options, progress);
+            }
+            return true;
+        }
+
+        public void Decrypt(Stream source, Stream destination, Passphrase passphrase, string displayContext, IProgressContext progress)
+        {
+            using (IAxCryptDocument document = Document(source, passphrase, displayContext, progress))
+            {
+                document.DecryptTo(destination);
+            }
+        }
+
+        /// <summary>
+        /// Decrypt from loaded AxCryptDocument to a destination file
+        /// </summary>
+        /// <param name="document">The loaded AxCryptDocument</param>
+        /// <param name="destinationFile">The destination file</param>
+        public void Decrypt(IAxCryptDocument document, IRuntimeFileInfo destinationFile, AxCryptOptions options, IProgressContext progress)
+        {
+            if (document == null)
+            {
+                throw new ArgumentNullException("document");
+            }
+            if (destinationFile == null)
+            {
+                throw new ArgumentNullException("destinationFile");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+            try
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Decrypting to '{0}'.".InvariantFormat(destinationFile.Name));
+                }
+
+                using (Stream destinationStream = destinationFile.OpenWrite())
+                {
+                    document.DecryptTo(destinationStream);
+                }
+
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Decrypted to '{0}'.".InvariantFormat(destinationFile.Name));
+                }
+            }
+            catch (Exception)
+            {
+                if (destinationFile.IsExistingFile)
+                {
+                    Wipe(destinationFile, progress);
+                }
+                throw;
+            }
+            if (options.HasMask(AxCryptOptions.SetFileTimes))
+            {
+                destinationFile.SetFileTimes(document.CreationTimeUtc, document.LastAccessTimeUtc, document.LastWriteTimeUtc);
+            }
+        }
+
+        /// <summary>
+        /// Decrypt a source file to a destination file, given a passphrase
+        /// </summary>
+        /// <param name="sourceFile">The source file</param>
+        /// <param name="destinationFile">The destination file</param>
+        /// <param name="passphrase">The passphrase</param>
+        /// <returns>true if the passphrase was correct</returns>
+        public string Decrypt(IRuntimeFileInfo sourceFile, string destinationDirectory, Passphrase key, AxCryptOptions options, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (destinationDirectory == null)
+            {
+                throw new ArgumentNullException("destinationDirectory");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+            string destinationFileName = null;
+            using (IAxCryptDocument document = Document(sourceFile, key, new ProgressContext()))
+            {
+                if (!document.PassphraseIsValid)
+                {
+                    return destinationFileName;
+                }
+                destinationFileName = document.FileName;
+                IRuntimeFileInfo destinationFullPath = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().Combine(destinationDirectory, destinationFileName));
+                Decrypt(document, destinationFullPath, options, progress);
+            }
+            return destinationFileName;
+        }
+
+        public virtual void DecryptFilesInsideFolderUniqueWithWipeOfOriginal(IRuntimeFileInfo folderInfo, Passphrase decryptionKey, IStatusChecker statusChecker, IProgressContext progress)
+        {
+            IEnumerable<IRuntimeFileInfo> files = folderInfo.ListEncrypted();
+            Instance.ParallelFileOperation.DoFiles(files, (file, context) =>
+            {
+                context.LeaveSingleThread();
+                return DecryptFileUniqueWithWipeOfOriginal(file, decryptionKey, context);
+            },
+            (status) =>
+            {
+                Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.PurgeActiveFiles));
+                statusChecker.CheckStatusAndShowMessage(status.Status, status.FullName);
+            });
+        }
+
+        public FileOperationContext DecryptFileUniqueWithWipeOfOriginal(IRuntimeFileInfo fileInfo, Passphrase decryptionKey, IProgressContext progress)
+        {
+            progress.NotifyLevelStart();
+            using (IAxCryptDocument document = Factory.New<AxCryptFile>().Document(fileInfo, decryptionKey, progress))
+            {
+                if (!document.PassphraseIsValid)
+                {
+                    return new FileOperationContext(fileInfo.FullName, FileOperationStatus.Canceled);
+                }
+
+                IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(fileInfo.FullName), document.FileName));
+                destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationFileInfo.FullName.CreateUniqueFile());
+                DecryptFile(document, destinationFileInfo.FullName, progress);
+            }
+            Wipe(fileInfo, progress);
+            progress.NotifyLevelFinished();
+            return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+        }
+
+        public virtual void DecryptFile(IAxCryptDocument document, string decryptedFileFullName, IProgressContext progress)
+        {
+            if (document == null)
+            {
+                throw new ArgumentNullException("document");
+            }
+            if (decryptedFileFullName == null)
+            {
+                throw new ArgumentNullException("decryptedFileFullName");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            IRuntimeFileInfo decryptedFileInfo = Factory.New<IRuntimeFileInfo>(decryptedFileFullName);
+            Decrypt(document, decryptedFileInfo, AxCryptOptions.SetFileTimes, progress);
+        }
+
+        /// <summary>
+        /// Load an AxCryptDocument from a source file with a passphrase
+        /// </summary>
+        /// <param name="sourceFile">The source file</param>
+        /// <param name="passphrase">The passphrase</param>
+        /// <returns>An instance of AxCryptDocument. Use IsPassphraseValid property to determine validity.</returns>
+        public virtual IAxCryptDocument Document(IRuntimeFileInfo sourceFile, Passphrase key, IProgressContext progress)
+        {
+            if (sourceFile == null)
+            {
+                throw new ArgumentNullException("sourceFile");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            return Document(sourceFile.OpenRead(), key, sourceFile.FullName, progress);
+        }
+
+        /// <summary>
+        /// Creates an IAxCryptDocument instance from the specified source stream.
+        /// </summary>
+        /// <param name="source">The source stream. Ownership is passed to the IAxCryptDocument instance which disposes the stream when it is.</param>
+        /// <param name="key">The passphrase.</param>
+        /// <param name="displayContext">The display context.</param>
+        /// <param name="progress">The progress.</param>
+        /// <returns></returns>
+        /// <exception cref="System.ArgumentNullException">
+        /// source
+        /// or
+        /// key
+        /// or
+        /// progress
+        /// </exception>
+        public IAxCryptDocument Document(Stream source, Passphrase passphrase, string displayContext, IProgressContext progress)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException("source");
+            }
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            try
+            {
+                IAxCryptDocument document = Factory.New<AxCryptFactory>().CreateDocument(passphrase, new ProgressStream(source, progress));
+                return document;
+            }
+            catch (AxCryptException ace)
+            {
+                ace.DisplayContext = displayContext;
+                throw;
+            }
+            catch (Exception ex)
+            {
+                AxCryptException ace = new InternalErrorException("An unhandled exception occurred.", ErrorStatus.Unknown, ex);
+                ace.DisplayContext = displayContext;
+                throw ace;
+            }
+        }
+
+        public void WriteToFileWithBackup(IRuntimeFileInfo destinationFileInfo, Action<Stream> writeFileStreamTo, IProgressContext progress)
+        {
+            if (destinationFileInfo == null)
+            {
+                throw new ArgumentNullException("destinationFileInfo");
+            }
+            if (writeFileStreamTo == null)
+            {
+                throw new ArgumentNullException("writeFileStreamTo");
+            }
+
+            string temporaryFilePath = MakeAlternatePath(destinationFileInfo, ".tmp");
+            IRuntimeFileInfo temporaryFileInfo = Factory.New<IRuntimeFileInfo>(temporaryFilePath);
+
+            try
+            {
+                using (Stream temporaryStream = temporaryFileInfo.OpenWrite())
+                {
+                    writeFileStreamTo(temporaryStream);
+                }
+            }
+            catch (Exception)
+            {
+                if (temporaryFileInfo.IsExistingFile)
+                {
+                    Wipe(temporaryFileInfo, progress);
+                }
+                throw;
+            }
+
+            if (destinationFileInfo.IsExistingFile)
+            {
+                string backupFilePath = MakeAlternatePath(destinationFileInfo, ".bak");
+                IRuntimeFileInfo backupFileInfo = Factory.New<IRuntimeFileInfo>(destinationFileInfo.FullName);
+
+                backupFileInfo.MoveTo(backupFilePath);
+                temporaryFileInfo.MoveTo(destinationFileInfo.FullName);
+                Wipe(backupFileInfo, progress);
+            }
+            else
+            {
+                temporaryFileInfo.MoveTo(destinationFileInfo.FullName);
+            }
+        }
+
+        private static string MakeAlternatePath(IRuntimeFileInfo fileInfo, string extension)
+        {
+            string alternatePath = Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(fileInfo.FullName), Instance.Portable.Path().GetFileNameWithoutExtension(fileInfo.Name) + extension);
+            return alternatePath.CreateUniqueFile();
+        }
+
+        public static string MakeAxCryptFileName(IRuntimeFileInfo fileInfo)
+        {
+            if (fileInfo == null)
+            {
+                throw new ArgumentNullException("fileInfo");
+            }
+            string axCryptExtension = OS.Current.AxCryptExtension;
+            string originalExtension = Instance.Portable.Path().GetExtension(fileInfo.Name);
+            string modifiedExtension = originalExtension.Length == 0 ? String.Empty : "-" + originalExtension.Substring(1);
+            string axCryptFileName = Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(fileInfo.FullName), Instance.Portable.Path().GetFileNameWithoutExtension(fileInfo.Name) + modifiedExtension + axCryptExtension);
+
+            return axCryptFileName;
+        }
+
+        public virtual void Wipe(IRuntimeFileInfo fileInfo, IProgressContext progress)
+        {
+            if (fileInfo == null)
+            {
+                throw new ArgumentNullException("fileInfo");
+            }
+            if (!fileInfo.IsExistingFile)
+            {
+                return;
+            }
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Wiping '{0}'.".InvariantFormat(fileInfo.Name));
+            }
+            bool cancelPending = false;
+            progress.NotifyLevelStart();
+
+            string randomName;
+            do
+            {
+                randomName = GenerateRandomFileName(fileInfo.FullName);
+            } while (Factory.New<IRuntimeFileInfo>(randomName).IsExistingFile);
+            IRuntimeFileInfo moveToFileInfo = Factory.New<IRuntimeFileInfo>(fileInfo.FullName);
+            moveToFileInfo.MoveTo(randomName);
+
+            using (Stream stream = moveToFileInfo.OpenWrite())
+            {
+                long length = stream.Length + OS.Current.StreamBufferSize - stream.Length % OS.Current.StreamBufferSize;
+                progress.AddTotal(length);
+                for (long position = 0; position < length; position += OS.Current.StreamBufferSize)
+                {
+                    byte[] random = Instance.RandomGenerator.Generate(OS.Current.StreamBufferSize);
+                    stream.Write(random, 0, random.Length);
+                    stream.Flush();
+                    try
+                    {
+                        progress.AddCount(random.Length);
+                    }
+                    catch (OperationCanceledException)
+                    {
+                        cancelPending = true;
+                        progress.AddCount(random.Length);
+                    }
+                }
+            }
+
+            moveToFileInfo.Delete();
+            progress.NotifyLevelFinished();
+            if (cancelPending)
+            {
+                throw new OperationCanceledException("Delayed cancel during wipe.");
+            }
+        }
+
+        private static string GenerateRandomFileName(string originalFullName)
+        {
+            const string validFileNameChars = "abcdefghijklmnopqrstuvwxyz";
+
+            string directory = Instance.Portable.Path().GetDirectoryName(originalFullName);
+            string fileName = Instance.Portable.Path().GetFileNameWithoutExtension(originalFullName);
+
+            int randomLength = fileName.Length < 8 ? 8 : fileName.Length;
+            StringBuilder randomName = new StringBuilder(randomLength + 4);
+            byte[] random = Instance.RandomGenerator.Generate(randomLength);
+            for (int i = 0; i < randomLength; ++i)
+            {
+                randomName.Append(validFileNameChars[random[i] % validFileNameChars.Length]);
+            }
+            randomName.Append(".tmp");
+
+            return Instance.Portable.Path().Combine(directory, randomName.ToString());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/AxCryptOptions.cs b/Axantum.AxCrypt.Core/AxCryptOptions.cs
new file mode 100644
index 0000000..649fd15
--- /dev/null
+++ b/Axantum.AxCrypt.Core/AxCryptOptions.cs
@@ -0,0 +1,40 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core
+{
+    [Flags]
+    public enum AxCryptOptions
+    {
+        None = 0,
+        SetFileTimes = 1,
+        EncryptWithCompression = 2,
+        EncryptWithoutCompression = 4,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Axantum.AxCrypt.Core.csproj b/Axantum.AxCrypt.Core/Axantum.AxCrypt.Core.csproj
new file mode 100644
index 0000000..a5601d6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Axantum.AxCrypt.Core.csproj
@@ -0,0 +1,329 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Core</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Core</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .NET Framework is automatically included -->
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AxCryptFactory.cs" />
+    <Compile Include="Portable\AesManaged.cs" />
+    <Compile Include="Portable\CipherMode.cs" />
+    <Compile Include="Portable\IPortableFactory.cs" />
+    <Compile Include="Portable\CryptoStream.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastleAsymmetricFactory.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastleDigest.cs" />
+    <Compile Include="Crypto\Asymmetric\IAsymmetricFactory.cs" />
+    <Compile Include="Crypto\Asymmetric\IAsymmetricKeyPair.cs" />
+    <Compile Include="Crypto\Asymmetric\IAsymmetricPrivateKey.cs" />
+    <Compile Include="Crypto\Asymmetric\IAsymmetricPublicKey.cs" />
+    <Compile Include="Crypto\Asymmetric\IAsymmetricPaddingHash.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastlePaddingHash.cs" />
+    <Compile Include="Crypto\CryptoPolicy.cs" />
+    <Compile Include="Crypto\ICryptoHash.cs" />
+    <Compile Include="Crypto\Passphrase.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastlePrivateKey.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastlePublicKey.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastleKeyPair.cs" />
+    <Compile Include="Crypto\Asymmetric\BouncyCastleRandomGenerator.cs" />
+    <Compile Include="Header\StringEncryptedHeaderBlockBase.cs" />
+    <Compile Include="Header\V2AsymmetricKeyWrapHeaderBlock.cs" />
+    <Compile Include="Header\V2AsymmetricRecipientsEncryptedHeaderBlock.cs" />
+    <Compile Include="IO\AbstractJsonConverter.cs" />
+    <Compile Include="IO\EmailAddressJsonConverter.cs" />
+    <Compile Include="Portable\CryptoStreamMode.cs" />
+    <Compile Include="Portable\HashAlgorithm.cs" />
+    <Compile Include="Portable\HMAC.cs" />
+    <Compile Include="Portable\HMACSHA1.cs" />
+    <Compile Include="Portable\HMACSHA512.cs" />
+    <Compile Include="Portable\ICloneable.cs" />
+    <Compile Include="Portable\ICryptoTransform.cs" />
+    <Compile Include="Portable\IDataErrorInfo.cs" />
+    <Compile Include="Portable\IPath.cs" />
+    <Compile Include="Portable\ISemaphore.cs" />
+    <Compile Include="Portable\ISingleThread.cs" />
+    <Compile Include="Portable\KeyedHashAlgorithm.cs" />
+    <Compile Include="Portable\KeySizes.cs" />
+    <Compile Include="Portable\PaddingMode.cs" />
+    <Compile Include="Portable\RandomNumberGenerator.cs" />
+    <Compile Include="Portable\SHA1Managed.cs" />
+    <Compile Include="Portable\SymmetricAlgorithm.cs" />
+    <Compile Include="Runtime\TypeDiscovery.cs" />
+    <Compile Include="Crypto\CryptoExtensions.cs" />
+    <Compile Include="Crypto\FreeCryptoPolicy.cs" />
+    <Compile Include="Crypto\ICryptoPolicy.cs" />
+    <Compile Include="Crypto\LegacyCryptoPolicy.cs" />
+    <Compile Include="Crypto\ProCryptoPolicy.cs" />
+    <Compile Include="Crypto\V1Aes128CryptoFactory.cs" />
+    <Compile Include="Crypto\V2Aes128CryptoFactory.cs" />
+    <Compile Include="Crypto\V2Aes256CryptoFactory.cs" />
+    <Compile Include="Crypto\BlockAlgorithmKeyWrapTransform.cs" />
+    <Compile Include="Crypto\CounterModeCryptoTransform.cs" />
+    <Compile Include="Crypto\CryptoBase.cs" />
+    <Compile Include="Crypto\CryptoFactory.cs" />
+    <Compile Include="Crypto\Hmac.cs" />
+    <Compile Include="Crypto\ICrypto.cs" />
+    <Compile Include="Crypto\ICryptoFactory.cs" />
+    <Compile Include="Crypto\IKeyWrapTransform.cs" />
+    <Compile Include="Crypto\IDerivedKey.cs" />
+    <Compile Include="Crypto\IRandomGenerator.cs" />
+    <Compile Include="Crypto\KeyWrapDirection.cs" />
+    <Compile Include="Crypto\DerivedKeyBase.cs" />
+    <Compile Include="Crypto\Pbkdf2HmacSha512.cs" />
+    <Compile Include="Crypto\RandomGenerator.cs" />
+    <Compile Include="Crypto\V2AesCrypto.cs" />
+    <Compile Include="Crypto\V2CryptoBase.cs" />
+    <Compile Include="Crypto\V2DerivedKey.cs" />
+    <Compile Include="Header\EncryptedDataPartBlock.cs" />
+    <Compile Include="Header\V2CompressionEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\V2DocumentHeaders.cs" />
+    <Compile Include="Header\V2HmacHeaderBlock.cs" />
+    <Compile Include="Header\V2KeyWrapHeaderBlock.cs" />
+    <Compile Include="Header\V2UnicodeFileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="IAxCryptDocument.cs" />
+    <Compile Include="IO\V2AxCryptDataStream.cs" />
+    <Compile Include="IO\V2HmacStream.cs" />
+    <Compile Include="Ipc\ArgumentBundles.cs" />
+    <Compile Include="Ipc\CommandCompleteEventArgs.cs" />
+    <Compile Include="Ipc\CommandHandler.cs" />
+    <Compile Include="Ipc\CommandItem.cs" />
+    <Compile Include="Reader\AxCryptReader.cs" />
+    <Compile Include="Reader\V2AxCryptReader.cs" />
+    <Compile Include="Reader\VxAxCryptReader.cs" />
+    <Compile Include="Session\ActiveFileProperties.cs" />
+    <Compile Include="Session\ActiveFileWatcher.cs" />
+    <Compile Include="Session\UserAsymmetricKeys.cs" />
+    <Compile Include="Session\UserAsymmetricKeysStore.cs" />
+    <Compile Include="UI\EmailAddress.cs" />
+    <Compile Include="UI\FileOperationContext.cs" />
+    <Compile Include="UI\ViewModel\CreateNewAccountViewModel.cs" />
+    <Compile Include="UI\ViewModel\LogOnAccountViewModel.cs" />
+    <Compile Include="UI\ViewModel\WatchedFoldersViewModel.cs" />
+    <Compile Include="V1AxCryptDocument.cs" />
+    <Compile Include="V2AxCryptDocument.cs" />
+    <Compile Include="CommandLine.cs" />
+    <Compile Include="Extensions\ByteArrayExtensions.cs" />
+    <Compile Include="Extensions\EnumExtensions.cs" />
+    <Compile Include="Extensions\PrimitiveTypeExtensions.cs" />
+    <Compile Include="Extensions\RuntimeFileInfoExtensions.cs" />
+    <Compile Include="Extensions\StreamExtensions.cs" />
+    <Compile Include="Extensions\StringExtensions.cs" />
+    <Compile Include="Crypto\IterationCalculator.cs" />
+    <Compile Include="Factory.cs" />
+    <Compile Include="Header\Headers.cs" />
+    <Compile Include="Instance.cs" />
+    <Compile Include="IO\FileWatcherEventArgs.cs" />
+    <Compile Include="IO\IFileWatcher.cs" />
+    <Compile Include="IO\IWebCaller.cs" />
+    <Compile Include="IO\LockingStream.cs" />
+    <Compile Include="Ipc\IRequestServer.cs" />
+    <Compile Include="Ipc\IRequestClient.cs" />
+    <Compile Include="Ipc\CommandServiceEventArgs.cs" />
+    <Compile Include="Ipc\CommandService.cs" />
+    <Compile Include="Ipc\CommandVerb.cs" />
+    <Compile Include="Ipc\RequestCommandEventArgs.cs" />
+    <Compile Include="Ipc\CommandStatus.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+    <Compile Include="Runtime\DelayedAction.cs" />
+    <Compile Include="Runtime\IDelayTimer.cs" />
+    <Compile Include="Runtime\ISleep.cs" />
+    <Compile Include="Runtime\IThreadWorker.cs" />
+    <Compile Include="Runtime\LoggingEventArgs.cs" />
+    <Compile Include="Runtime\SleepEventArgs.cs" />
+    <Compile Include="Runtime\ThreadWorkerProgressContext.cs" />
+    <Compile Include="Runtime\WorkerGroup.cs" />
+    <Compile Include="Runtime\WorkerGroupProgressContext.cs" />
+    <Compile Include="Runtime\WorkFolder.cs" />
+    <Compile Include="Runtime\WorkFolderWatcher.cs" />
+    <Compile Include="Session\ActiveFileChangedEventArgs.cs" />
+    <Compile Include="Session\ActiveFileComparer.cs" />
+    <Compile Include="Session\ActiveFileVisualState.cs" />
+    <Compile Include="Session\ChangedEventMode.cs" />
+    <Compile Include="Runtime\AxCryptException.cs" />
+    <Compile Include="AxCryptFile.cs" />
+    <Compile Include="AxCryptOptions.cs" />
+    <Compile Include="Crypto\V1AesCrypto.cs" />
+    <Compile Include="Crypto\SymmetricIV.cs" />
+    <Compile Include="Crypto\SymmetricKey.cs" />
+    <Compile Include="Crypto\SymmetricKeyThumbprint.cs" />
+    <Compile Include="Crypto\V1Hmac.cs" />
+    <Compile Include="Crypto\HeaderSubkey.cs" />
+    <Compile Include="Crypto\KeyWrap.cs" />
+    <Compile Include="Crypto\KeyWrapMode.cs" />
+    <Compile Include="Crypto\Salt.cs" />
+    <Compile Include="Crypto\V1DerivedKey.cs" />
+    <Compile Include="Crypto\Subkey.cs" />
+    <Compile Include="OS.cs" />
+    <Compile Include="ErrorStatus.cs" />
+    <Compile Include="Runtime\FileFormatException.cs" />
+    <Compile Include="Header\AxCrypt1Guid.cs" />
+    <Compile Include="Header\V1CompressionEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\V1CompressionInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\DataHeaderBlock.cs" />
+    <Compile Include="Header\V1DocumentHeaders.cs" />
+    <Compile Include="Header\EncryptedHeaderBlock.cs" />
+    <Compile Include="Header\V1EncryptionInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\FileInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\V1FileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\V1IdTagHeaderBlock.cs" />
+    <Compile Include="Header\V1KeyWrap1HeaderBlock.cs" />
+    <Compile Include="Header\V1KeyWrap2HeaderBlock.cs" />
+    <Compile Include="Header\PreambleHeaderBlock.cs" />
+    <Compile Include="Header\V1UnicodeFileNameInfoEncryptedHeaderBlock.cs" />
+    <Compile Include="Header\UnrecognizedHeaderBlock.cs" />
+    <Compile Include="IO\ProgressStream.cs" />
+    <Compile Include="Runtime\IDataProtection.cs" />
+    <Compile Include="Runtime\ILauncher.cs" />
+    <Compile Include="Runtime\ILogging.cs" />
+    <Compile Include="Runtime\IRuntimeEnvironment.cs" />
+    <Compile Include="Runtime\InternalErrorException.cs" />
+    <Compile Include="Runtime\IncorrectDataException.cs" />
+    <Compile Include="IO\V1AxCryptDataStream.cs" />
+    <Compile Include="IO\V1HmacStream.cs" />
+    <Compile Include="IO\IRuntimeFileInfo.cs" />
+    <Compile Include="IO\LookAheadStream.cs" />
+    <Compile Include="IO\NonClosingStream.cs" />
+    <Compile Include="Header\HeaderBlock.cs" />
+    <Compile Include="Header\HeaderBlockType.cs" />
+    <Compile Include="Header\VersionHeaderBlock.cs" />
+    <Compile Include="Runtime\ITiming.cs" />
+    <Compile Include="Crypto\V2Hmac.cs" />
+    <None Include="Properties\AssemblyInfo.template" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Reader\V1AxCryptReader.cs" />
+    <Compile Include="Reader\AxCryptItemType.cs" />
+    <Compile Include="Runtime\LogLevel.cs" />
+    <Compile Include="Runtime\Platform.cs" />
+    <Compile Include="IO\FileLock.cs" />
+    <Compile Include="Session\ActiveFile.cs" />
+    <Compile Include="Session\ActiveFileCollection.cs" />
+    <Compile Include="IO\FileInfoTypes.cs" />
+    <Compile Include="Session\ActiveFileAction.cs" />
+    <Compile Include="Session\ActiveFileStatus.cs" />
+    <Compile Include="Session\FileSystemState.cs" />
+    <Compile Include="Runtime\ThreadWorkerEventArgs.cs" />
+    <Compile Include="Session\PassphraseIdentity.cs" />
+    <Compile Include="Session\ProcessState.cs" />
+    <Compile Include="Session\SessionNotification.cs" />
+    <Compile Include="Session\SessionNotificationHandler.cs" />
+    <Compile Include="Session\SessionNotify.cs" />
+    <Compile Include="Session\SessionNotificationType.cs" />
+    <Compile Include="Session\SessionNotificationEventArgs.cs" />
+    <Compile Include="Session\WatchedFolder.cs" />
+    <Compile Include="Session\WatchedFolderChangedEventArgs.cs" />
+    <Compile Include="UI\IUserSettings.cs" />
+    <Compile Include="UI\KnownFolder.cs" />
+    <Compile Include="UI\ViewModel\DelegateAction.cs" />
+    <Compile Include="UI\ViewModel\FileOperationViewModel.cs" />
+    <Compile Include="UI\ViewModel\FileSelectionEventArgs.cs" />
+    <Compile Include="UI\ViewModel\FileSelectionType.cs" />
+    <Compile Include="UI\ViewModel\IAction.cs" />
+    <Compile Include="UI\ViewModel\IdentityViewModel.cs" />
+    <Compile Include="UI\ViewModel\KnownFoldersViewModel.cs" />
+    <Compile Include="UI\ViewModel\LogOnEventArgs.cs" />
+    <Compile Include="UI\ViewModel\IViewModel.cs" />
+    <Compile Include="UI\ViewModel\LogOnViewModel.cs" />
+    <Compile Include="UI\ViewModel\MainViewModel.cs" />
+    <Compile Include="UI\Options.cs" />
+    <Compile Include="UI\ParallelFileOperation.cs" />
+    <Compile Include="UI\CancelProgressContext.cs" />
+    <Compile Include="UI\FileOperation.cs" />
+    <Compile Include="UI\FileOperationEventArgs.cs" />
+    <Compile Include="UI\FileOperationsController.cs" />
+    <Compile Include="UI\FileOperationStatus.cs" />
+    <Compile Include="UI\IProgressBackground.cs" />
+    <Compile Include="UI\IProgressContext.cs" />
+    <Compile Include="UI\IStatusChecker.cs" />
+    <Compile Include="UI\IUIThread.cs" />
+    <Compile Include="UI\KnownKeys.cs" />
+    <Compile Include="UI\ProgressContext.cs" />
+    <Compile Include="UI\ProgressEventArgs.cs" />
+    <Compile Include="UI\ViewModel\NewPassphraseViewModel.cs" />
+    <Compile Include="UI\ViewModel\ValidationError.cs" />
+    <Compile Include="UI\ViewModel\ViewModelBase.cs" />
+    <Compile Include="UI\PublicResources.cs" />
+    <Compile Include="UI\UpdateCheck.cs" />
+    <Compile Include="UI\UserSettings.cs" />
+    <Compile Include="UI\VersionEventArgs.cs" />
+    <Compile Include="UI\VersionResponse.cs" />
+    <Compile Include="UI\VersionUpdateStatus.cs" />
+    <Compile Include="Header\V2PlainTextLengthsEncryptedHeaderBlock.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <CodeAnalysisDictionary Include="..\SolutionItems\CustomDictionary.xml">
+      <Link>CustomDictionary.xml</Link>
+    </CodeAnalysisDictionary>
+    <Content Include="AboutThisAssembly.txt" />
+    <Content Include="resources\json.netlicense.txt" />
+    <EmbeddedResource Include="resources\axcrypticon.ico" />
+    <Content Include="resources\bouncycastlelicense.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <!--<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />-->
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <ItemGroup>
+    <ProjectReference Include="..\BouncyCastle.AxCrypt\BouncyCastle.AxCrypt.csproj">
+      <Project>{3680C939-B21F-4444-B646-42FB4B29A786}</Project>
+      <Name>BouncyCastle.AxCrypt</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959F7F85-C98B-4876-971A-9036224578E4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/AxantumStrongName.pfx b/Axantum.AxCrypt.Core/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Core/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Core/CommandLine.cs b/Axantum.AxCrypt.Core/CommandLine.cs
new file mode 100644
index 0000000..0c740d7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/CommandLine.cs
@@ -0,0 +1,138 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using NDesk.Options;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    public class CommandLine
+    {
+        private string _startPath;
+
+        private IEnumerable<string> _arguments;
+
+        private static readonly IEnumerable<string> NoArguments = new string[0];
+
+        public CommandLine(string startPath, IEnumerable<string> arguments)
+        {
+            _startPath = startPath;
+            _arguments = arguments.ToList();
+        }
+
+        public void Execute()
+        {
+            List<CommandItem> _commandItems = new List<CommandItem>();
+            int bundleId = 0;
+            CommandVerb fileVerb = CommandVerb.Unknown;
+
+            OptionSetCollection options = new OptionSetCollection()
+            {
+                {"batch", var => bundleId = 0},
+                {"bundle=", (int id) => bundleId = id},
+                {"files", var => fileVerb = CommandVerb.AddFiles},
+                {"encrypt", var => fileVerb = CommandVerb.Encrypt},
+                {"decrypt", var => fileVerb = CommandVerb.Decrypt},
+                {"wipe", var =>  fileVerb = CommandVerb.Wipe},
+                {"open", var =>  fileVerb = CommandVerb.Open},
+                {"rename", var => fileVerb = CommandVerb.RandomRename},
+                {"show", var => _commandItems.Add(new CommandItem(CommandVerb.Show, bundleId, NoArguments))},
+                {"exit", var => _commandItems.Add(new CommandItem(CommandVerb.Exit, bundleId, NoArguments))},
+                {"use_application=", (string path) => _commandItems.Add(new CommandItem(CommandVerb.UseForOpen, bundleId, new string[]{path}))},
+                {"login=", (string name) =>_commandItems.Add(new CommandItem(CommandVerb.LogOn, bundleId, new string[]{name}))},
+                {"passphrase=", (string passphrase) => _commandItems.Add(new CommandItem(CommandVerb.SetPassphrase, bundleId, new string[]{passphrase}))},
+                {"key_file=", (string path) => _commandItems.Add(new CommandItem(CommandVerb.SetKeyFile, bundleId, new string[]{path}))},
+                {"about", var => _commandItems.Add(new CommandItem(CommandVerb.About, bundleId, NoArguments))},
+                {"register", var => _commandItems.Add(new CommandItem(CommandVerb.Register, bundleId, NoArguments))},
+            };
+            IList<string> arguments = options.Parse(_arguments);
+            if (fileVerb == CommandVerb.Unknown)
+            {
+                fileVerb = bundleId == 0 ? CommandVerb.Open : CommandVerb.AddFiles;
+            }
+            if (arguments.Count > 0 || bundleId != 0)
+            {
+                _commandItems.Add(new CommandItem(fileVerb, bundleId, arguments));
+            }
+            Run(_commandItems);
+        }
+
+        private void Run(IList<CommandItem> commandItems)
+        {
+            if (commandItems.Count == 0)
+            {
+                EnsureFirstInstanceRunning();
+                return;
+            }
+            foreach (CommandItem commandItem in commandItems)
+            {
+                CallService(commandItem.Verb, commandItem.BundleId, commandItem.Arguments);
+            }
+        }
+
+        private void CallService(CommandVerb verb, int batchId, IEnumerable<string> files)
+        {
+            bool firstIsRunning = OS.Current.FirstInstanceRunning(TimeSpan.Zero);
+            if (verb == CommandVerb.Exit && !firstIsRunning)
+            {
+                return;
+            }
+            if (!firstIsRunning)
+            {
+                StartFirstInstance();
+            }
+            CommandStatus status = Instance.CommandService.Call(verb, batchId, files);
+            if (status == CommandStatus.Success)
+            {
+                return;
+            }
+            OS.Current.ExitApplication(1);
+        }
+
+        private void EnsureFirstInstanceRunning()
+        {
+            if (OS.Current.FirstInstanceRunning(TimeSpan.Zero))
+            {
+                return;
+            }
+            StartFirstInstance();
+        }
+
+        private void StartFirstInstance()
+        {
+            using (OS.Current.Launch(_startPath)) { }
+            if (OS.Current.FirstInstanceRunning(TimeSpan.FromSeconds(1)))
+            {
+                return;
+            }
+            OS.Current.ExitApplication(2);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleAsymmetricFactory.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleAsymmetricFactory.cs
new file mode 100644
index 0000000..87845a6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleAsymmetricFactory.cs
@@ -0,0 +1,49 @@
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public class BouncyCastleAsymmetricFactory : IAsymmetricFactory
+    {
+        public JsonConverter[] GetConverters()
+        {
+            JsonConverter[] jsonConverters = new JsonConverter[]
+            {
+                new AbstractJsonConverter<IAsymmetricPublicKey, BouncyCastlePublicKey>(),
+                new AbstractJsonConverter<IAsymmetricPrivateKey, BouncyCastlePrivateKey>(),
+                new AbstractJsonConverter<IAsymmetricKeyPair, BouncyCastleKeyPair>(),
+            };
+            return jsonConverters;
+        }
+
+        public IAsymmetricPrivateKey CreatePrivateKey(string privateKeyPem)
+        {
+            return new BouncyCastlePrivateKey(privateKeyPem);
+        }
+
+        public IAsymmetricPublicKey CreatePublicKey(string publicKeyPem)
+        {
+            return new BouncyCastlePublicKey(publicKeyPem);
+        }
+
+        public IAsymmetricKeyPair CreateKeyPair(int bits)
+        {
+            return new BouncyCastleKeyPair(bits);
+        }
+
+        public IAsymmetricKeyPair CreateKeyPair(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] qinv)
+        {
+            return new BouncyCastleKeyPair(n, e, d, p, q, dp, dq, qinv);
+        }
+
+        public IPaddingHash CreatePaddingHash()
+        {
+            return new BouncyCastlePaddingHash();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleDigest.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleDigest.cs
new file mode 100644
index 0000000..185e3ea
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleDigest.cs
@@ -0,0 +1,79 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    internal class BouncyCastleDigest : Org.BouncyCastle.Crypto.IDigest
+    {
+        private ICryptoHash _cryptoHash;
+
+        public BouncyCastleDigest(ICryptoHash cryptoHash)
+        {
+            _cryptoHash = cryptoHash;
+        }
+
+        public string AlgorithmName
+        {
+            get { return _cryptoHash.AlgorithmName; }
+        }
+
+        public int GetDigestSize()
+        {
+            return _cryptoHash.HashSize;
+        }
+
+        public int GetByteLength()
+        {
+            return _cryptoHash.BufferLength;
+        }
+
+        public void Update(byte input)
+        {
+            _cryptoHash.Update(input);
+        }
+
+        public void BlockUpdate(byte[] input, int inOff, int length)
+        {
+            _cryptoHash.BlockUpdate(input, inOff, length);
+        }
+
+        public int DoFinal(byte[] output, int outOff)
+        {
+            return _cryptoHash.DoFinal(output, outOff);
+        }
+
+        public void Reset()
+        {
+            _cryptoHash.Reset();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleKeyPair.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleKeyPair.cs
new file mode 100644
index 0000000..03dd189
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleKeyPair.cs
@@ -0,0 +1,91 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Newtonsoft.Json;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    [JsonObject(MemberSerialization.OptIn)]
+    internal class BouncyCastleKeyPair : IAsymmetricKeyPair
+    {
+        [JsonConstructor]
+        private BouncyCastleKeyPair()
+        {
+        }
+
+        public BouncyCastleKeyPair(int bits)
+        {
+            AsymmetricCipherKeyPair keyPair = GenerateKeyPair(bits);
+            SetKeys(keyPair.Public, keyPair.Private);
+        }
+
+        public BouncyCastleKeyPair(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] qinv)
+        {
+            AsymmetricKeyParameter publicKeyParameter = new RsaKeyParameters(false, new BigInteger(n), new BigInteger(e));
+            AsymmetricKeyParameter privateKeyParameter = new RsaPrivateCrtKeyParameters(new BigInteger(n), new BigInteger(e), new BigInteger(d), new BigInteger(p), new BigInteger(q), new BigInteger(dp), new BigInteger(dq), new BigInteger(qinv));
+            SetKeys(publicKeyParameter, privateKeyParameter);
+        }
+
+        private void SetKeys(AsymmetricKeyParameter publicKeyParameter, AsymmetricKeyParameter privateKeyParameter)
+        {
+            PublicKey = new BouncyCastlePublicKey(publicKeyParameter);
+            PrivateKey = new BouncyCastlePrivateKey(privateKeyParameter);
+        }
+
+        [JsonProperty("publickey")]
+        public IAsymmetricPublicKey PublicKey { get; private set; }
+
+        [JsonProperty("privatekey")]
+        public IAsymmetricPrivateKey PrivateKey { get; private set; }
+
+        private static AsymmetricCipherKeyPair GenerateKeyPair(int bits)
+        {
+            KeyGenerationParameters keyParameters = new KeyGenerationParameters(BouncyCastleRandomGenerator.CreateSecureRandom(), bits);
+            RsaKeyPairGenerator rsaGenerator = new RsaKeyPairGenerator();
+            rsaGenerator.Init(keyParameters);
+            AsymmetricCipherKeyPair keyPair = rsaGenerator.GenerateKeyPair();
+
+            return keyPair;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePaddingHash.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePaddingHash.cs
new file mode 100644
index 0000000..f395f2a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePaddingHash.cs
@@ -0,0 +1,79 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    internal class BouncyCastlePaddingHash : IPaddingHash
+    {
+        private Org.BouncyCastle.Crypto.IDigest _digest;
+
+        public BouncyCastlePaddingHash()
+        {
+            _digest = new Org.BouncyCastle.Crypto.Digests.Sha512Digest();
+        }
+
+        public string AlgorithmName
+        {
+            get { return _digest.AlgorithmName; }
+        }
+
+        public int HashSize
+        {
+            get { return _digest.GetDigestSize(); }
+        }
+
+        public int BufferLength
+        {
+            get { return _digest.GetByteLength(); }
+        }
+
+        public void Update(byte input)
+        {
+            _digest.Update(input);
+        }
+
+        public void BlockUpdate(byte[] input, int inOff, int length)
+        {
+            _digest.BlockUpdate(input, inOff, length);
+        }
+
+        public int DoFinal(byte[] output, int outOff)
+        {
+            return _digest.DoFinal(output, outOff);
+        }
+
+        public void Reset()
+        {
+            _digest.Reset();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePrivateKey.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePrivateKey.cs
new file mode 100644
index 0000000..05513f7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePrivateKey.cs
@@ -0,0 +1,120 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using Newtonsoft.Json;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    [JsonObject(MemberSerialization.OptIn)]
+    internal class BouncyCastlePrivateKey : IAsymmetricPrivateKey
+    {
+        [JsonProperty("pem")]
+        private string _serializedKey
+        {
+            get
+            {
+                return ToPem();
+            }
+            set
+            {
+                Key = FromPem(value);
+            }
+        }
+
+        public AsymmetricKeyParameter Key { get; private set; }
+
+        [JsonConstructor]
+        private BouncyCastlePrivateKey()
+        {
+        }
+
+        internal BouncyCastlePrivateKey(AsymmetricKeyParameter privateKey)
+        {
+            Key = privateKey;
+        }
+
+        public BouncyCastlePrivateKey(string privateKeyPem)
+        {
+            Key = FromPem(privateKeyPem);
+        }
+
+        private AsymmetricKeyParameter FromPem(string pem)
+        {
+            using (TextReader reader = new StringReader(pem))
+            {
+                PemReader pemReader = new PemReader(reader);
+
+                return ((AsymmetricCipherKeyPair)pemReader.ReadObject()).Private;
+            }
+        }
+
+        private string ToPem()
+        {
+            using (TextWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                PemWriter pem = new PemWriter(writer);
+                pem.WriteObject(Key);
+                return writer.ToString();
+            }
+        }
+
+        public byte[] Transform(byte[] buffer)
+        {
+            IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaBlindedEngine(), new BouncyCastleDigest(Factory.Instance.Singleton<IAsymmetricFactory>().CreatePaddingHash()));
+
+            cipher.Init(false, new ParametersWithRandom(Key, BouncyCastleRandomGenerator.CreateSecureRandom()));
+            try
+            {
+                byte[] transformed = cipher.ProcessBlock(buffer, 0, buffer.Length);
+                return transformed;
+            }
+            catch (CryptoException)
+            {
+                return null;
+            }
+        }
+
+        public override string ToString()
+        {
+            return ToPem();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePublicKey.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePublicKey.cs
new file mode 100644
index 0000000..6c233c0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastlePublicKey.cs
@@ -0,0 +1,112 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Newtonsoft.Json;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.OpenSsl;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    [JsonObject(MemberSerialization.OptIn)]
+    internal class BouncyCastlePublicKey : IAsymmetricPublicKey
+    {
+        [JsonProperty("pem")]
+        private string _serializedKey
+        {
+            get
+            {
+                return ToPem();
+            }
+            set
+            {
+                Key = FromPem(value);
+            }
+        }
+
+        private AsymmetricKeyParameter Key { get; set; }
+
+        [JsonConstructor]
+        private BouncyCastlePublicKey()
+        {
+        }
+
+        internal BouncyCastlePublicKey(AsymmetricKeyParameter publicKeyParameter)
+        {
+            Key = publicKeyParameter;
+        }
+
+        public BouncyCastlePublicKey(string publicKeyPem)
+        {
+            Key = FromPem(publicKeyPem);
+        }
+
+        private AsymmetricKeyParameter FromPem(string pem)
+        {
+            using (TextReader reader = new StringReader(pem))
+            {
+                PemReader pemReader = new PemReader(reader);
+
+                return (AsymmetricKeyParameter)pemReader.ReadObject();
+            }
+        }
+
+        private string ToPem()
+        {
+            using (TextWriter writer = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                PemWriter pem = new PemWriter(writer);
+                pem.WriteObject(Key);
+                return writer.ToString();
+            }
+        }
+
+        public byte[] Transform(byte[] buffer)
+        {
+            IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaBlindedEngine(), new BouncyCastleDigest(Factory.Instance.Singleton<IAsymmetricFactory>().CreatePaddingHash()));
+
+            cipher.Init(true, new ParametersWithRandom(Key, BouncyCastleRandomGenerator.CreateSecureRandom()));
+            byte[] transformed = cipher.ProcessBlock(buffer, 0, buffer.Length);
+
+            return transformed;
+        }
+
+        public override string ToString()
+        {
+            return ToPem();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleRandomGenerator.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleRandomGenerator.cs
new file mode 100644
index 0000000..60b89ca
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/BouncyCastleRandomGenerator.cs
@@ -0,0 +1,65 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    internal class BouncyCastleRandomGenerator : Org.BouncyCastle.Crypto.Prng.IRandomGenerator
+    {
+        public void AddSeedMaterial(byte[] seed)
+        {
+        }
+
+        public void AddSeedMaterial(long seed)
+        {
+        }
+
+        public void NextBytes(byte[] buffer)
+        {
+            byte[] random = Instance.RandomGenerator.Generate(buffer.Length);
+            random.CopyTo(buffer, 0);
+        }
+
+        public void NextBytes(byte[] buffer, int start, int len)
+        {
+            byte[] random = Instance.RandomGenerator.Generate(len);
+            Array.Copy(random, 0, buffer, start, len);
+        }
+
+        public static SecureRandom CreateSecureRandom()
+        {
+            return new SecureRandom(new BouncyCastleRandomGenerator());
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricFactory.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricFactory.cs
new file mode 100644
index 0000000..acb151a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricFactory.cs
@@ -0,0 +1,23 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public interface IAsymmetricFactory
+    {
+        JsonConverter[] GetConverters();
+
+        IAsymmetricPrivateKey CreatePrivateKey(string privateKeyPem);
+
+        IAsymmetricPublicKey CreatePublicKey(string publicKeyPem);
+
+        IAsymmetricKeyPair CreateKeyPair(int bits);
+
+        IAsymmetricKeyPair CreateKeyPair(byte[] n, byte[] e, byte[] d, byte[] p, byte[] q, byte[] dp, byte[] dq, byte[] qinv);
+
+        IPaddingHash CreatePaddingHash();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricKeyPair.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricKeyPair.cs
new file mode 100644
index 0000000..2abe0f5
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricKeyPair.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public interface IAsymmetricKeyPair
+    {
+        IAsymmetricPublicKey PublicKey { get; }
+
+        IAsymmetricPrivateKey PrivateKey { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPaddingHash.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPaddingHash.cs
new file mode 100644
index 0000000..3d93734
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPaddingHash.cs
@@ -0,0 +1,38 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public interface IPaddingHash : ICryptoHash
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPrivateKey.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPrivateKey.cs
new file mode 100644
index 0000000..d93f680
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPrivateKey.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public interface IAsymmetricPrivateKey
+    {
+        byte[] Transform(byte[] buffer);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPublicKey.cs b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPublicKey.cs
new file mode 100644
index 0000000..19413ae
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Asymmetric/IAsymmetricPublicKey.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto.Asymmetric
+{
+    public interface IAsymmetricPublicKey
+    {
+        byte[] Transform(byte[] buffer);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/BlockAlgorithmKeyWrapTransform.cs b/Axantum.AxCrypt.Core/Crypto/BlockAlgorithmKeyWrapTransform.cs
new file mode 100644
index 0000000..20fadd1
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/BlockAlgorithmKeyWrapTransform.cs
@@ -0,0 +1,94 @@
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class BlockAlgorithmKeyWrapTransform : IKeyWrapTransform
+    {
+        private SymmetricAlgorithm _algorithm;
+
+        private ICryptoTransform _transform;
+
+        public BlockAlgorithmKeyWrapTransform(SymmetricAlgorithm symmetricAlgorithm, Salt salt, KeyWrapDirection keyWrapDirection)
+        {
+            if (salt.Length != 0 && salt.Length < symmetricAlgorithm.Key.Length)
+            {
+                throw new InternalErrorException("Salt is too short. It must be at least as long as the algorithm key, or empty for no salt.");
+            }
+            _algorithm = symmetricAlgorithm;
+
+            byte[] saltedKey = _algorithm.Key;
+            saltedKey.Xor(salt.GetBytes().Reduce(saltedKey.Length));
+            _algorithm.Key = saltedKey;
+
+            _algorithm.Mode = CipherMode.ECB;
+            _algorithm.Padding = PaddingMode.None;
+
+            BlockLength = _algorithm.BlockSize / 8;
+
+            _transform = keyWrapDirection == KeyWrapDirection.Encrypt ? _algorithm.CreateEncryptor() : _algorithm.CreateDecryptor();
+        }
+
+        public byte[] TransformBlock(byte[] block)
+        {
+            if (block == null)
+            {
+                throw new ArgumentNullException("block");
+            }
+            if (block.Length != BlockLength)
+            {
+                throw new ArgumentException("Argument 'block' must be a single block for the algorithm.");
+            }
+            byte[] transformed = new byte[block.Length];
+            _transform.TransformBlock(block, 0, block.Length, transformed, 0);
+            return transformed;
+        }
+
+        public byte[] A()
+        {
+            byte[] a = new byte[BlockLength / 2];
+            for (int i = 0; i < a.Length; ++i)
+            {
+                a[i] = 0xA6;
+            }
+            return a;
+        }
+
+        /// <summary>
+        /// Gets the block length in bytes of the transforma.
+        /// </summary>
+        public int BlockLength
+        {
+            get;
+            private set;
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            if (_transform != null)
+            {
+                _transform.Dispose();
+                _transform = null;
+            }
+            if (_algorithm != null)
+            {
+                // Clear() is implemented as a call to Dispose(), but Mono does not implement Dispose(), so this avoids a MoMA warning.
+                _algorithm.Clear();
+                _algorithm = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/CounterModeCryptoTransform.cs b/Axantum.AxCrypt.Core/Crypto/CounterModeCryptoTransform.cs
new file mode 100644
index 0000000..ac2f854
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/CounterModeCryptoTransform.cs
@@ -0,0 +1,179 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class CounterModeCryptoTransform : ICryptoTransform
+    {
+        private SymmetricAlgorithm _algorithm;
+
+        private int _blockLength;
+
+        private long _startBlockCounter;
+
+        private long _currentBlockCounter;
+
+        private int _startBlockOffset;
+
+        private int _currentBlockOffset;
+
+        private ICryptoTransform _cryptoTransform;
+
+        public CounterModeCryptoTransform(SymmetricAlgorithm algorithm, long blockCounter, int blockOffset)
+        {
+            if (algorithm.Mode != CipherMode.ECB)
+            {
+                algorithm.Clear();
+                throw new ArgumentException("The algorithm must be in ECB mode.");
+            }
+            if (algorithm.Padding != PaddingMode.None)
+            {
+                algorithm.Clear();
+                throw new ArgumentException("The algorithm must be set to work without padding.");
+            }
+            _algorithm = algorithm;
+            _startBlockCounter = _currentBlockCounter = blockCounter;
+            _startBlockOffset = _currentBlockOffset = blockOffset;
+
+            _cryptoTransform = _algorithm.CreateEncryptor();
+            _blockLength = _cryptoTransform.InputBlockSize;
+        }
+
+        public bool CanReuseTransform
+        {
+            get { return true; }
+        }
+
+        public bool CanTransformMultipleBlocks
+        {
+            get { return true; }
+        }
+
+        public int InputBlockSize
+        {
+            get { return _cryptoTransform.InputBlockSize; }
+        }
+
+        public int OutputBlockSize
+        {
+            get { return _cryptoTransform.OutputBlockSize; }
+        }
+
+        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            if (inputCount % _blockLength != 0)
+            {
+                throw new ArgumentException("Only whole blocks may be transformed.");
+            }
+
+            TransformBlockInternal(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+            return inputCount;
+        }
+
+        private void Reset()
+        {
+            _currentBlockCounter = _startBlockCounter;
+            _currentBlockOffset = _startBlockOffset;
+        }
+
+        private void TransformBlockInternal(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            byte[] keyStreamblock = new byte[_blockLength];
+            int remainingCount = inputCount;
+            while (remainingCount > 0)
+            {
+                _cryptoTransform.TransformBlock(GetCounterBlock(_currentBlockCounter), 0, _blockLength, keyStreamblock, 0);
+
+                int blockBytes = _blockLength - _currentBlockOffset;
+                if (remainingCount < blockBytes)
+                {
+                    blockBytes = remainingCount;
+                }
+                keyStreamblock.Xor(_currentBlockOffset, inputBuffer, inputOffset, blockBytes);
+                Array.Copy(keyStreamblock, _currentBlockOffset, outputBuffer, outputOffset, blockBytes);
+
+                inputOffset += blockBytes;
+                outputOffset += blockBytes;
+                remainingCount -= blockBytes;
+                _currentBlockOffset += blockBytes;
+                if (_currentBlockOffset == _blockLength)
+                {
+                    _currentBlockOffset = 0;
+                    _currentBlockCounter += 1;
+                }
+            }
+        }
+
+        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+        {
+            byte[] outputBuffer = new byte[inputCount];
+            TransformBlockInternal(inputBuffer, inputOffset, inputCount, outputBuffer, 0);
+            Reset();
+            return outputBuffer;
+        }
+
+        private byte[] GetCounterBlock(long blockCounter)
+        {
+            byte[] counterBytes = blockCounter.GetBigEndianBytes();
+            byte[] counterBlock = ((byte[])_algorithm.IV.Clone()).Xor(_algorithm.IV.Length - counterBytes.Length, counterBytes, 0, counterBytes.Length);
+            return counterBlock;
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_cryptoTransform != null)
+            {
+                _cryptoTransform.Dispose();
+                _cryptoTransform = null;
+            }
+            if (_algorithm != null)
+            {
+                _algorithm.Clear();
+                _algorithm = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/CryptoBase.cs b/Axantum.AxCrypt.Core/Crypto/CryptoBase.cs
new file mode 100644
index 0000000..0515147
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/CryptoBase.cs
@@ -0,0 +1,77 @@
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public abstract class CryptoBase : ICrypto
+    {
+        private SymmetricKey _key;
+
+        /// <summary>
+        /// Gets the key associated with this instance.
+        /// </summary>
+        /// <value>
+        /// The key.
+        /// </value>
+        public SymmetricKey Key
+        {
+            get
+            {
+                return _key;
+            }
+
+            protected set
+            {
+                _key = value;
+            }
+        }
+
+        public abstract int BlockLength { get; }
+
+        /// <summary>
+        /// Create an instance of a transform suitable for NIST Key Wrap.
+        /// </summary>
+        /// <param name="salt"></param>
+        /// <param name="keyWrapDirection"></param>
+        /// <returns></returns>
+        /// <value>
+        /// An instance of the transform.
+        ///   </value>
+        public abstract IKeyWrapTransform CreateKeyWrapTransform(Salt salt, KeyWrapDirection keyWrapDirection);
+
+        /// <summary>
+        /// Decrypt in one operation.
+        /// </summary>
+        /// <param name="cipherText"></param>
+        /// <returns>
+        /// The decrypted result minus any padding
+        /// </returns>
+        public abstract byte[] Decrypt(byte[] cipherText);
+
+        /// <summary>
+        /// Encrypt in one operation
+        /// </summary>
+        /// <param name="plaintext">The complete plaintext bytes</param>
+        /// <returns>
+        /// The cipher text, complete with any padding
+        /// </returns>
+        public abstract byte[] Encrypt(byte[] plaintext);
+
+        /// <summary>
+        /// Using this instances parameters, create a decryptor
+        /// </summary>
+        /// <returns>
+        /// A new decrypting transformation instance
+        /// </returns>
+        public abstract ICryptoTransform CreateDecryptingTransform();
+
+        /// <summary>
+        /// Using this instances parameters, create an encryptor
+        /// </summary>
+        /// <returns>
+        /// A new encrypting transformation instance
+        /// </returns>
+        public abstract ICryptoTransform CreateEncryptingTransform();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/CryptoExtensions.cs b/Axantum.AxCrypt.Core/Crypto/CryptoExtensions.cs
new file mode 100644
index 0000000..06c1b9d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/CryptoExtensions.cs
@@ -0,0 +1,36 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public static class CryptoExtensions
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/CryptoFactory.cs b/Axantum.AxCrypt.Core/Crypto/CryptoFactory.cs
new file mode 100644
index 0000000..eeb52ed
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/CryptoFactory.cs
@@ -0,0 +1,114 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class CryptoFactory
+    {
+        public static readonly int DerivationIterations = 1000;
+
+        private Dictionary<Guid, CryptoFactoryCreator> _factories = new Dictionary<Guid, CryptoFactoryCreator>();
+
+        public void Add(CryptoFactoryCreator factory)
+        {
+            _factories.Add(factory().Id, factory);
+        }
+
+        public bool TypeNameExists(string fullName)
+        {
+            return _factories.Any(c => c.Value().GetType().FullName == fullName);
+        }
+
+        public ICryptoFactory Create(Guid id)
+        {
+            if (id == Guid.Empty)
+            {
+                return Default;
+            }
+            CryptoFactoryCreator factory;
+            if (_factories.TryGetValue(id, out factory))
+            {
+                return factory();
+            }
+            throw new ArgumentException("CryptoFactory not found.", "id");
+        }
+
+        public ICryptoFactory Create(ICryptoPolicy policy)
+        {
+            return policy.DefaultCryptoFactory(_factories.Values.OrderByDescending(f => f().Priority));
+        }
+
+        /// <summary>
+        /// Return a list of CryptoId's in a suitable order of preference and relevance, to be used to
+        /// try and match a passphrase against a file.
+        /// </summary>
+        /// <returns>A list of CryptoId's to try in the order provided.</returns>
+        public IEnumerable<Guid> OrderedIds
+        {
+            get
+            {
+                Guid defaultId = Default.Id;
+                Guid legacyId = Legacy.Id;
+
+                List<Guid> orderedIds = new List<Guid>();
+                orderedIds.Add(defaultId);
+                orderedIds.AddRange(_factories.Values.Where(f => f().Id != defaultId && f().Id != legacyId).Select(f => f().Id));
+                orderedIds.Add(legacyId);
+
+                return orderedIds;
+            }
+        }
+
+        public ICryptoFactory Default
+        {
+            get
+            {
+                return Create(Factory.Instance.Singleton<ICryptoPolicy>());
+            }
+        }
+
+        public ICryptoFactory Legacy
+        {
+            get
+            {
+                return Create(V1Aes128CryptoFactory.CryptoId);
+            }
+        }
+
+        public ICryptoFactory Minimum
+        {
+            get
+            {
+                return Create(V2Aes128CryptoFactory.CryptoId);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/CryptoPolicy.cs b/Axantum.AxCrypt.Core/Crypto/CryptoPolicy.cs
new file mode 100644
index 0000000..e16c7f4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/CryptoPolicy.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class CryptoPolicy
+    {
+        private Dictionary<string, ICryptoPolicy> _policies = new Dictionary<string, ICryptoPolicy>();
+
+        public CryptoPolicy(IEnumerable<Assembly> extraAssemblies)
+        {
+            IEnumerable<Type> policyTypes = TypeDiscovery.Interface(typeof(ICryptoPolicy), extraAssemblies);
+            foreach (Type policyType in policyTypes)
+            {
+                ICryptoPolicy instance = Activator.CreateInstance(policyType) as ICryptoPolicy;
+                _policies.Add(instance.Name, instance);
+            }
+        }
+
+        public ICryptoPolicy Create(string name)
+        {
+            return _policies[name];
+        }
+
+        public IEnumerable<string> PolicyNames
+        {
+            get
+            {
+                return _policies.Values.OrderByDescending(p => Instance.CryptoFactory.Create(p).Priority).Select(p => p.Name);
+            }
+        }
+
+        public ICryptoPolicy CreateDefault()
+        {
+            return _policies.Values.OrderByDescending(p => p.Priority).First();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/DerivedKeyBase.cs b/Axantum.AxCrypt.Core/Crypto/DerivedKeyBase.cs
new file mode 100644
index 0000000..ee23200
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/DerivedKeyBase.cs
@@ -0,0 +1,83 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public abstract class DerivedKeyBase : IDerivedKey
+    {
+        public SymmetricKey DerivedKey
+        {
+            get;
+            protected set;
+        }
+
+        public Salt DerivationSalt
+        {
+            get;
+            protected set;
+        }
+
+        public int DerivationIterations { get; protected set; }
+
+        #region IEquatable<SymmetricKey> Members
+
+        /// <summary>
+        /// Check if one instance is equivalent to another.
+        /// </summary>
+        /// <param name="other">The instance to compare to</param>
+        /// <returns>true if the keys are equivalent</returns>
+        public bool Equals(IDerivedKey other)
+        {
+            if ((object)other == null)
+            {
+                return false;
+            }
+            return DerivedKey == other.DerivedKey;
+        }
+
+        #endregion IEquatable<SymmetricKey> Members
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null || !typeof(IDerivedKey).IsAssignableFrom(obj.GetType()))
+            {
+                return false;
+            }
+            IDerivedKey other = (IDerivedKey)obj;
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return DerivedKey.GetHashCode();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/FreeCryptoPolicy.cs b/Axantum.AxCrypt.Core/Crypto/FreeCryptoPolicy.cs
new file mode 100644
index 0000000..5c8bcc7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/FreeCryptoPolicy.cs
@@ -0,0 +1,53 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class FreeCryptoPolicy : ICryptoPolicy
+    {
+        public string Name { get { return "Free"; } }
+
+        public ICryptoFactory DefaultCryptoFactory(IEnumerable<CryptoFactoryCreator> factories)
+        {
+            return factories.First(f => f().Id == V2Aes128CryptoFactory.CryptoId)();
+        }
+
+        public int Priority
+        {
+            get { return 200000; }
+        }
+
+        public bool Active
+        {
+            get { return true; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/HeaderSubkey.cs b/Axantum.AxCrypt.Core/Crypto/HeaderSubkey.cs
new file mode 100644
index 0000000..f133d9d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/HeaderSubkey.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Enumeration of the various sub keys used in an AxCrypt header.
+    /// </summary>
+    public enum HeaderSubkey
+    {
+        None,
+        Hmac,
+        Validator,
+        Headers,
+        Data,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Hmac.cs b/Axantum.AxCrypt.Core/Crypto/Hmac.cs
new file mode 100644
index 0000000..09da16e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Hmac.cs
@@ -0,0 +1,141 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// The HMAC of AxCrypt encrypted data. Instances of this class are immutable.
+    /// </summary>
+    public abstract class Hmac
+    {
+        private byte[] _hmac;
+
+        protected void Initialize(byte[] hmac, int requiredLength)
+        {
+            if (hmac == null)
+            {
+                throw new ArgumentNullException("hmac");
+            }
+            if (hmac.Length != requiredLength)
+            {
+                throw new InternalErrorException("HMAC must be exactly {0} bytes.".InvariantFormat(requiredLength));
+            }
+            _hmac = (byte[])hmac.Clone();
+        }
+
+        /// <summary>
+        /// Gets the length of the hash.
+        /// </summary>
+        public int Length
+        {
+            get
+            {
+                return _hmac.Length;
+            }
+        }
+
+        /// <summary>
+        /// Gets the hash bytes.
+        /// </summary>
+        /// <returns>The hash bytes</returns>
+        public byte[] GetBytes()
+        {
+            return (byte[])_hmac.Clone();
+        }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="Runtime.Object"/> is equal to this instance.
+        /// </summary>
+        /// <param name="obj">The <see cref="Runtime.Object"/> to compare with this instance.</param>
+        /// <returns>
+        ///   <c>true</c> if the specified <see cref="Runtime.Object"/> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool Equals(object obj)
+        {
+            if (obj == null || !GetType().Equals(obj.GetType()))
+            {
+                return false;
+            }
+            Hmac right = (Hmac)obj;
+            return this == right;
+        }
+
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+        /// </returns>
+        public override int GetHashCode()
+        {
+            int hashCode = 0;
+            foreach (byte b in _hmac)
+            {
+                hashCode += (hashCode << 8) + b;
+            }
+            return hashCode;
+        }
+
+        /// <summary>
+        /// Implements the operator == for DataHmac
+        /// </summary>
+        /// <param name="left">The left instance to compare</param>
+        /// <param name="right">The right instance to compare</param>
+        /// <returns>
+        /// True if the two instances compare as equivalent, false otherwise.
+        /// </returns>
+        public static bool operator ==(Hmac left, Hmac right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if (Object.ReferenceEquals(left, null) || Object.ReferenceEquals(right, null))
+            {
+                return false;
+            }
+            return left._hmac.IsEquivalentTo(right._hmac);
+        }
+
+        /// <summary>
+        /// Implements the operator !=.
+        /// </summary>
+        /// <param name="left">The left instance to compare</param>
+        /// <param name="right">The right instance to compare</param>
+        /// <returns>
+        /// True if the two instances do not compare as equivalent, false otherwise.
+        /// </returns>
+        public static bool operator !=(Hmac left, Hmac right)
+        {
+            return !(left == right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/ICrypto.cs b/Axantum.AxCrypt.Core/Crypto/ICrypto.cs
new file mode 100644
index 0000000..6751175
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/ICrypto.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface ICrypto
+    {
+        /// <summary>
+        /// Gets the key associated with this instance.
+        /// </summary>
+        /// <value>
+        /// The key.
+        /// </value>
+        SymmetricKey Key { get; }
+
+        /// <summary>
+        /// Gets the underlying algorithm block length in bytes
+        /// </summary>
+        int BlockLength { get; }
+
+        /// <summary>
+        /// Create an instance of a transform suitable for NIST Key Wrap.
+        /// </summary>
+        /// <returns></returns>
+        /// <value>
+        /// An instance of the transform.
+        /// </value>
+        IKeyWrapTransform CreateKeyWrapTransform(Salt salt, KeyWrapDirection keyWrapDirection);
+
+        /// <summary>
+        /// Decrypt in one operation.
+        /// </summary>
+        /// <param name="ciphertext">The complete cipher text</param>
+        /// <returns>The decrypted result minus any padding</returns>
+        byte[] Decrypt(byte[] cipherText);
+
+        /// <summary>
+        /// Encrypt in one operation
+        /// </summary>
+        /// <param name="plaintext">The complete plaintext bytes</param>
+        /// <returns>The cipher text, complete with any padding</returns>
+        byte[] Encrypt(byte[] plaintext);
+
+        /// <summary>
+        /// Using this instances parameters, create a decryptor
+        /// </summary>
+        /// <returns>A new decrypting transformation instance</returns>
+        ICryptoTransform CreateDecryptingTransform();
+
+        /// <summary>
+        /// Using this instances parameters, create an encryptor
+        /// </summary>
+        /// <returns>A new encrypting transformation instance</returns>
+        ICryptoTransform CreateEncryptingTransform();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/ICryptoFactory.cs b/Axantum.AxCrypt.Core/Crypto/ICryptoFactory.cs
new file mode 100644
index 0000000..3cb9b09
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/ICryptoFactory.cs
@@ -0,0 +1,87 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public delegate ICryptoFactory CryptoFactoryCreator();
+
+    public interface ICryptoFactory
+    {
+        int Priority { get; }
+
+        Guid Id { get; }
+
+        /// <summary>
+        /// Gets the unique name of the algorithm implementation.
+        /// </summary>
+        /// <value>
+        /// The name. This must be a short, language independent name usable both as an internal identifier, and as a display name.
+        /// Typical values are "AES-128", "AES-256". The UI may use these as indexes for localized or clearer names, but if unknown
+        /// the UI must be able to fallback and actually display this identifier as a selector for example in the UI. This is to
+        /// support plug-in algorithm implementations in the future.
+        /// </value>
+        string Name { get; }
+
+        /// <summary>
+        /// Gets the key size in bits
+        /// </summary>
+        int KeySize { get; }
+
+        /// <summary>
+        /// Gets the block size in bits
+        /// </summary>
+        int BlockSize { get; }
+
+        /// <summary>
+        /// Creates a new derived key, generating a random salt and an appropriate number of iterations.
+        /// </summary>
+        /// <param name="passphrase">The passphrase.</param>
+        /// <returns>A new IDerivedKey instance.</returns>
+        IDerivedKey CreateDerivedKey(Passphrase passphrase);
+
+        /// <summary>
+        /// Restores a derived key with the given salt and iterations.
+        /// </summary>
+        /// <param name="passphrase">The passphrase.</param>
+        /// <param name="salt">The salt.</param>
+        /// <param name="derivationIterations">The derivation iterations.</param>
+        /// <returns>A restored IDerivedKey instance.</returns>
+        IDerivedKey RestoreDerivedKey(Passphrase passphrase, Salt salt, int derivationIterations);
+
+        /// <summary>
+        /// Instantiate an approriate ICrypto implementation.
+        /// </summary>
+        /// <param name="key">The key to use.</param>
+        /// <param name="iv">The Initial Vector to use, if relevant or null otherwise.</param>
+        /// <param name="keyStreamOffset">The offset in the keystream to start it, if relevant.</param>
+        /// <returns>An instance of an appropriate ICrypto implementation.</returns>
+        ICrypto CreateCrypto(SymmetricKey key, SymmetricIV iv, long keyStreamOffset);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/ICryptoHash.cs b/Axantum.AxCrypt.Core/Crypto/ICryptoHash.cs
new file mode 100644
index 0000000..4e3734c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/ICryptoHash.cs
@@ -0,0 +1,82 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface ICryptoHash
+    {
+        /// <summary>
+        /// The algorithm name
+        /// </summary>
+        string AlgorithmName { get; }
+
+        /// <summary>
+        /// Gets the size, in bytes, of the digest produced by this message digest
+        /// </summary>
+        /// <returns>The size, in bytes</returns>
+        int HashSize { get; }
+
+        /// <summary>
+        /// Gets the size, in bytes, of the internal buffer used by this digest.
+        /// </summary>
+        /// <returns>The size, in bytes</returns>
+        int BufferLength { get; }
+
+        /// <summary>
+        /// Update the message digest with a single byte.
+        /// </summary>
+        /// <param name="input">The byte</param>
+        void Update(byte input);
+
+        /// <summary>
+        /// Update the message digest with a block of bytes
+        /// </summary>
+        /// <param name="input">The byte array containing the data.</param>
+        /// <param name="offset">The offset into the byte array where the data starts.</param>
+        /// <param name="length">The length of the data.</param>
+        void BlockUpdate(byte[] input, int offset, int length);
+
+        /// <summary>
+        /// Close the digest, producing the final digest value. The DoFinal
+        /// call leaves the digest reset.
+        /// </summary>
+        /// <param name="output">The array the digest is to be copied into.</param>
+        /// <param name="offset">The offset into the out array the digest is to start at.</param>
+        /// <returns></returns>
+        int DoFinal(byte[] output, int offset);
+
+        /// <summary>
+        /// Reset the digest back to it's initial state.
+        /// </summary>
+        void Reset();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/ICryptoPolicy.cs b/Axantum.AxCrypt.Core/Crypto/ICryptoPolicy.cs
new file mode 100644
index 0000000..16d3ae3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/ICryptoPolicy.cs
@@ -0,0 +1,44 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface ICryptoPolicy
+    {
+        int Priority { get; }
+
+        bool Active { get; }
+
+        string Name { get; }
+
+        ICryptoFactory DefaultCryptoFactory(IEnumerable<CryptoFactoryCreator> factories);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/IDerivedKey.cs b/Axantum.AxCrypt.Core/Crypto/IDerivedKey.cs
new file mode 100644
index 0000000..a98ff9c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/IDerivedKey.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface IDerivedKey : IEquatable<IDerivedKey>
+    {
+        SymmetricKey DerivedKey { get; }
+
+        Salt DerivationSalt { get; }
+
+        int DerivationIterations { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/IKeyWrapTransform.cs b/Axantum.AxCrypt.Core/Crypto/IKeyWrapTransform.cs
new file mode 100644
index 0000000..2663e55
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/IKeyWrapTransform.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface IKeyWrapTransform : IDisposable
+    {
+        int BlockLength { get; }
+
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "A", Justification = "NIST Key Wrap specification refers to this value as 'A'")]
+        byte[] A();
+
+        byte[] TransformBlock(byte[] block);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/IRandomGenerator.cs b/Axantum.AxCrypt.Core/Crypto/IRandomGenerator.cs
new file mode 100644
index 0000000..258afe9
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/IRandomGenerator.cs
@@ -0,0 +1,10 @@
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public interface IRandomGenerator
+    {
+        byte[] Generate(int count);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/IterationCalculator.cs b/Axantum.AxCrypt.Core/Crypto/IterationCalculator.cs
new file mode 100644
index 0000000..27ccb85
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/IterationCalculator.cs
@@ -0,0 +1,80 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class IterationCalculator
+    {
+        /// <summary>
+        /// Get the number of key wrap iterations we use by default. This is a calculated value intended to cause the wrapping
+        /// operation to take approximately 1/20th of a second in the system where the code is run.
+        /// A minimum of 5000 iterations are always guaranteed.
+        /// </summary>
+        /// <param name="cryptoId">The id of the crypto to use for the wrap.</param>
+        public virtual long KeyWrapIterations(Guid cryptoId)
+        {
+            long iterationsPerSecond = IterationsPerSecond(cryptoId, KeyWrapIterate);
+            long defaultIterations = iterationsPerSecond / 20;
+
+            if (defaultIterations < 5000)
+            {
+                defaultIterations = 5000;
+            }
+
+            return defaultIterations;
+        }
+
+        private static long IterationsPerSecond(Guid cryptoId, Func<Guid, long, object> iterate)
+        {
+            long iterationsIncrement = 1000;
+            long totalIterations = 0;
+            DateTime startTime = OS.Current.UtcNow;
+            DateTime endTime;
+            do
+            {
+                iterate(cryptoId, iterationsIncrement);
+                totalIterations += iterationsIncrement;
+                endTime = OS.Current.UtcNow;
+            } while ((endTime - startTime).TotalMilliseconds < 500);
+            long iterationsPerSecond = totalIterations * 1000 / (long)(endTime - startTime).TotalMilliseconds;
+            return iterationsPerSecond;
+        }
+
+        private static object KeyWrapIterate(Guid cryptoId, long keyWrapIterations)
+        {
+            ICryptoFactory factory = Instance.CryptoFactory.Create(cryptoId);
+            ICrypto dummyCrypto = factory.CreateCrypto(factory.CreateDerivedKey(new Passphrase("A dummy passphrase")).DerivedKey, null, 0);
+            Salt dummySalt = new Salt(dummyCrypto.Key.Size);
+            KeyWrap keyWrap = new KeyWrap(dummySalt, keyWrapIterations, KeyWrapMode.Specification);
+            byte[] wrapped = keyWrap.Wrap(dummyCrypto, new SymmetricKey(dummyCrypto.Key.Size));
+            return wrapped;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/KeyWrap.cs b/Axantum.AxCrypt.Core/Crypto/KeyWrap.cs
new file mode 100644
index 0000000..35eaa69
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/KeyWrap.cs
@@ -0,0 +1,232 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Implements AES (Generalized to any symmetric cipher) Key Wrap Specification - http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf .
+    /// </summary>
+    public class KeyWrap
+    {
+        private Salt _salt;
+
+        private long _keyWrapIterations;
+
+        private readonly KeyWrapMode _mode;
+
+        /// <summary>
+        /// Create a KeyWrap instance for wrapping or unwrapping
+        /// </summary>
+        /// <param name="keyWrapIterations">The number of wrapping iterations, at least 6</param>
+        /// <param name="mode">Use original specification mode or AxCrypt mode (only difference is that 't' is little endian in AxCrypt mode)</param>
+        public KeyWrap(long keyWrapIterations, KeyWrapMode mode)
+            : this(Salt.Zero, keyWrapIterations, mode)
+        {
+        }
+
+        /// <summary>
+        /// Create a KeyWrap instance for wrapping or unwrapping
+        /// </summary>
+        /// <param name="salt">A salt. This is required by AxCrypt, although the algorithm supports not using a salt.</param>
+        /// <param name="keyWrapIterations">The number of wrapping iterations, at least 6</param>
+        /// <param name="mode">Use original specification mode or AxCrypt mode (only difference is that 't' is little endian in AxCrypt mode)</param>
+        public KeyWrap(Salt salt, long keyWrapIterations, KeyWrapMode mode)
+        {
+            if (salt == null)
+            {
+                throw new ArgumentNullException("salt");
+            }
+            if (keyWrapIterations < 6)
+            {
+                throw new InternalErrorException("keyWrapIterations");
+            }
+            if (mode != KeyWrapMode.Specification && mode != KeyWrapMode.AxCrypt)
+            {
+                throw new InternalErrorException("mode");
+            }
+            _salt = salt;
+            _mode = mode;
+            _keyWrapIterations = keyWrapIterations;
+        }
+
+        public byte[] Wrap(ICrypto crypto, byte[] keyMaterial)
+        {
+            if (crypto == null)
+            {
+                throw new ArgumentNullException("crypto");
+            }
+            if (keyMaterial == null)
+            {
+                throw new ArgumentNullException("keyMaterial");
+            }
+
+            using (IKeyWrapTransform encryptor = crypto.CreateKeyWrapTransform(_salt, KeyWrapDirection.Encrypt))
+            {
+                return WrapInternal(keyMaterial, encryptor);
+            }
+        }
+
+        private byte[] WrapInternal(byte[] keyMaterial, IKeyWrapTransform encryptor)
+        {
+            byte[] a = encryptor.A();
+
+            byte[] wrapped = new byte[keyMaterial.Length + a.Length];
+            a.CopyTo(wrapped, 0);
+
+            Array.Copy(keyMaterial, 0, wrapped, a.Length, keyMaterial.Length);
+
+            byte[] block = new byte[encryptor.BlockLength];
+            int halfBlockLength = encryptor.BlockLength / 2;
+            // wrapped[0..halfBlockLength-1] contains the A (IV) of the Key Wrap algorithm,
+            // the rest is 'Key Data'. We do the transform in-place.
+            for (int j = 0; j < _keyWrapIterations; j++)
+            {
+                for (int i = 1; i <= keyMaterial.Length / halfBlockLength; i++)
+                {
+                    // B = AESE(K, A | R[i])
+                    Array.Copy(wrapped, 0, block, 0, halfBlockLength);
+                    Array.Copy(wrapped, i * halfBlockLength, block, halfBlockLength, halfBlockLength);
+                    byte[] b = encryptor.TransformBlock(block);
+                    // A = MSB64(B) XOR t where t = (n * j) + i
+                    long t = ((keyMaterial.Length / halfBlockLength) * j) + i;
+                    switch (_mode)
+                    {
+                        case KeyWrapMode.Specification:
+                            b.Xor(0, t.GetBigEndianBytes(), 0, halfBlockLength);
+                            break;
+
+                        case KeyWrapMode.AxCrypt:
+                            b.Xor(0, t.GetLittleEndianBytes(), 0, halfBlockLength);
+                            break;
+                    }
+                    Array.Copy(b, 0, wrapped, 0, halfBlockLength);
+                    // R[i] = LSB64(B)
+                    Array.Copy(b, halfBlockLength, wrapped, i * halfBlockLength, halfBlockLength);
+                }
+            }
+            return wrapped;
+        }
+
+        /// <summary>
+        /// Wrap key data using the AES Key Wrap specification
+        /// </summary>
+        /// <param name="keyToWrap">The key to wrap</param>
+        /// <returns>The wrapped key data, 8 bytes longer than the key</returns>
+        public byte[] Wrap(ICrypto crypto, SymmetricKey keyToWrap)
+        {
+            if (crypto == null)
+            {
+                throw new ArgumentNullException("crypto");
+            }
+            if (keyToWrap == null)
+            {
+                throw new ArgumentNullException("keyToWrap");
+            }
+            return Wrap(crypto, keyToWrap.GetBytes());
+        }
+
+        /// <summary>
+        /// Unwrap an AES Key Wrapped-key
+        /// </summary>
+        /// <param name="wrapped">The full wrapped data, the length of a key + 8 bytes</param>
+        /// <returns>The unwrapped key data, or a zero-length array if the unwrap was unsuccessful due to wrong key</returns>
+        public byte[] Unwrap(ICrypto crypto, byte[] wrapped)
+        {
+            if (crypto == null)
+            {
+                throw new ArgumentNullException("crypto");
+            }
+            if (wrapped.Length % (crypto.BlockLength / 2) != 0)
+            {
+                throw new InternalErrorException("The length of the wrapped data must a multiple of half the algorithm block size.");
+            }
+            if (wrapped.Length < 24)
+            {
+                throw new InternalErrorException("The length of the wrapped data must be large enough to accomodate at least a 128-bit key.");
+            }
+
+            using (IKeyWrapTransform decryptor = crypto.CreateKeyWrapTransform(_salt, KeyWrapDirection.Decrypt))
+            {
+                return UnwrapInternal(wrapped, decryptor);
+            }
+        }
+
+        private byte[] UnwrapInternal(byte[] wrapped, IKeyWrapTransform decryptor)
+        {
+            byte[] a = decryptor.A();
+            int halfBlockLength = decryptor.BlockLength / 2;
+            int wrappedKeyLength = wrapped.Length - a.Length;
+
+            wrapped = (byte[])wrapped.Clone();
+
+            byte[] block = new byte[decryptor.BlockLength];
+
+            // wrapped[0..7] contains the A (IV) of the Key Wrap algorithm,
+            // the rest is 'Wrapped Key Data', R[1], ..., R[n]. We do the transform in-place.
+            for (long j = _keyWrapIterations - 1; j >= 0; --j)
+            {
+                for (int i = wrappedKeyLength / halfBlockLength; i >= 1; --i)
+                {
+                    long t = ((wrappedKeyLength / halfBlockLength) * j) + i;
+                    // MSB(B) = A XOR t
+                    Array.Copy(wrapped, 0, block, 0, halfBlockLength);
+                    switch (_mode)
+                    {
+                        case KeyWrapMode.Specification:
+                            block.Xor(0, t.GetBigEndianBytes(), 0, halfBlockLength);
+                            break;
+
+                        case KeyWrapMode.AxCrypt:
+                            block.Xor(0, t.GetLittleEndianBytes(), 0, halfBlockLength);
+                            break;
+                    }
+                    // LSB(B) = R[i]
+                    Array.Copy(wrapped, i * halfBlockLength, block, halfBlockLength, halfBlockLength);
+                    // B = AESD(K, X xor t | R[i]) where t = (n * j) + i
+                    byte[] b = decryptor.TransformBlock(block);
+                    // A = MSB(B)
+                    Array.Copy(b, 0, wrapped, 0, halfBlockLength);
+                    // R[i] = LSB(B)
+                    Array.Copy(b, halfBlockLength, wrapped, i * halfBlockLength, halfBlockLength);
+                }
+            }
+
+            if (!wrapped.IsEquivalentTo(0, a, 0, a.Length))
+            {
+                return new byte[0];
+            }
+
+            byte[] unwrapped = new byte[wrapped.Length - a.Length];
+            Array.Copy(wrapped, a.Length, unwrapped, 0, wrapped.Length - a.Length);
+            return unwrapped;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/KeyWrapDirection.cs b/Axantum.AxCrypt.Core/Crypto/KeyWrapDirection.cs
new file mode 100644
index 0000000..4cf424d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/KeyWrapDirection.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Control the direction of the NIST Key Wrap
+    /// </summary>
+    public enum KeyWrapDirection
+    {
+        /// <summary>
+        /// Reserved
+        /// </summary>
+        Unknown,
+
+        /// <summary>
+        /// Use when wrapping
+        /// </summary>
+        Encrypt,
+
+        /// <summary>
+        /// Use when unwrapping
+        /// </summary>
+        Decrypt,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/KeyWrapMode.cs b/Axantum.AxCrypt.Core/Crypto/KeyWrapMode.cs
new file mode 100644
index 0000000..7cbdb75
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/KeyWrapMode.cs
@@ -0,0 +1,40 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Due to a minor bug in the AxCrypt-implementation we need to separate two modes. AxCrypt
+    /// treats the value 't' in the iteration using little endian notation, while it in fact should
+    /// be big endian according to the NIST specification. Oops... should not be a problem, but it's
+    /// still wrong.
+    /// </summary>
+    public enum KeyWrapMode
+    {
+        Specification, AxCrypt
+    };
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/LegacyCryptoPolicy.cs b/Axantum.AxCrypt.Core/Crypto/LegacyCryptoPolicy.cs
new file mode 100644
index 0000000..898aa89
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/LegacyCryptoPolicy.cs
@@ -0,0 +1,53 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class LegacyCryptoPolicy : ICryptoPolicy
+    {
+        public string Name { get { return "Legacy"; } }
+
+        public ICryptoFactory DefaultCryptoFactory(IEnumerable<CryptoFactoryCreator> factories)
+        {
+            return factories.First(f => f().Id == V1Aes128CryptoFactory.CryptoId)();
+        }
+
+        public int Priority
+        {
+            get { return 100000; }
+        }
+
+        public bool Active
+        {
+            get { return true; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Passphrase.cs b/Axantum.AxCrypt.Core/Crypto/Passphrase.cs
new file mode 100644
index 0000000..1faae44
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Passphrase.cs
@@ -0,0 +1,107 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class Passphrase : IEquatable<Passphrase>
+    {
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This type is in fact immutable.")]
+        public static readonly Passphrase Empty = new Passphrase(String.Empty);
+
+        public Passphrase(string text)
+        {
+            Text = text;
+        }
+
+        public string Text { get; private set; }
+
+        private SymmetricKeyThumbprint _thumbprint;
+
+        public SymmetricKeyThumbprint Thumbprint
+        {
+            get
+            {
+                if (_thumbprint == null)
+                {
+                    _thumbprint = new SymmetricKeyThumbprint(this, Instance.UserSettings.ThumbprintSalt, Instance.UserSettings.GetKeyWrapIterations(Instance.CryptoFactory.Minimum.Id));
+                }
+                return _thumbprint;
+            }
+        }
+
+        #region IEquatable<Passphrase> Members
+
+        public bool Equals(Passphrase other)
+        {
+            if ((object)other == null)
+            {
+                return false;
+            }
+            return Text == other.Text;
+        }
+
+        #endregion IEquatable<Passphrase> Members
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null || !typeof(Passphrase).IsAssignableFrom(obj.GetType()))
+            {
+                return false;
+            }
+            Passphrase other = (Passphrase)obj;
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return Text.GetHashCode();
+        }
+
+        public static bool operator ==(Passphrase left, Passphrase right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if ((object)left == null)
+            {
+                return false;
+            }
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(Passphrase left, Passphrase right)
+        {
+            return !(left == right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Pbkdf2HmacSha512.cs b/Axantum.AxCrypt.Core/Crypto/Pbkdf2HmacSha512.cs
new file mode 100644
index 0000000..e8a14d3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Pbkdf2HmacSha512.cs
@@ -0,0 +1,111 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>Implements password-based key derivation functionality, PBKDF2, by using a pseudo-random number generator based on <see cref="T:System.Security.Cryptography.HMACSHA512" />.</summary>
+    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Pbkdf")]
+    [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Sha")]
+    public class Pbkdf2HmacSha512
+    {
+        private byte[] _bytes;
+
+        /// <summary>Initializes a new instance of the <see cref="T:System.Security.Cryptography.Rfc2898DeriveBytes" /> class using a password, a salt, and number of iterations to derive the key.</summary>
+        /// <param name="password">The password used to derive the key. </param>
+        /// <param name="salt">The key salt used to derive the key.</param>
+        /// <param name="derivationIterations">The number of iterations for the operation. </param>
+        /// <exception cref="T:System.ArgumentNullException">The password or salt is null. </exception>
+        public Pbkdf2HmacSha512(string password, Salt salt, int derivationIterations)
+        {
+            if (password == null)
+            {
+                throw new ArgumentNullException("password");
+            }
+            if (salt == null)
+            {
+                throw new ArgumentNullException("salt");
+            }
+            if (derivationIterations <= 0)
+            {
+                throw new ArgumentOutOfRangeException("derivationIterations", "Must be greater than 0.");
+            }
+
+            _bytes = F(password, salt, derivationIterations);
+        }
+
+        /// <summary>Returns the pseudo-random key for this object.</summary>
+        /// <returns>A byte array filled with 64 pseudo-random key bytes.</returns>
+        public byte[] GetBytes()
+        {
+            if (_bytes == null)
+            {
+                throw new InternalErrorException("GetBytes() can only be called once.");
+            }
+
+            byte[] bytes = _bytes;
+            _bytes = null;
+            return bytes;
+        }
+
+        private static readonly byte[] _empty = new byte[0];
+
+        private static byte[] F(string password, Salt salt, int derivationIterations)
+        {
+            HMAC hmacsha512 = Instance.Portable.HMACSHA512(new UTF8Encoding(false).GetBytes(password));
+
+            hmacsha512.TransformBlock(salt.GetBytes(), 0, salt.Length, null, 0);
+            byte[] iBytes = 1.GetBigEndianBytes();
+
+            hmacsha512.TransformBlock(iBytes, 0, iBytes.Length, null, 0);
+            hmacsha512.TransformFinalBlock(_empty, 0, 0);
+
+            byte[] u = hmacsha512.Hash;
+            byte[] un = u;
+
+            for (int c = 2; c <= derivationIterations; ++c)
+            {
+                hmacsha512.Initialize();
+                hmacsha512.TransformBlock(u, 0, u.Length, null, 0);
+                hmacsha512.TransformFinalBlock(_empty, 0, 0);
+                u = hmacsha512.Hash;
+                for (int i = 0; i < u.Length; i++)
+                {
+                    un[i] ^= u[i];
+                }
+            }
+
+            return un;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/ProCryptoPolicy.cs b/Axantum.AxCrypt.Core/Crypto/ProCryptoPolicy.cs
new file mode 100644
index 0000000..0bcce0f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/ProCryptoPolicy.cs
@@ -0,0 +1,53 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class ProCryptoPolicy : ICryptoPolicy
+    {
+        public string Name { get { return "Pro"; } }
+
+        public ICryptoFactory DefaultCryptoFactory(IEnumerable<CryptoFactoryCreator> factories)
+        {
+            return factories.First()();
+        }
+
+        public int Priority
+        {
+            get { return 300000; }
+        }
+
+        public bool Active
+        {
+            get { return true; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/RandomGenerator.cs b/Axantum.AxCrypt.Core/Crypto/RandomGenerator.cs
new file mode 100644
index 0000000..be9c750
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/RandomGenerator.cs
@@ -0,0 +1,45 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class RandomGenerator : IRandomGenerator
+    {
+        private RandomNumberGenerator _rng = Instance.Portable.RandomNumberGenerator();
+
+        public byte[] Generate(int count)
+        {
+            byte[] data = new byte[count];
+            _rng.GetBytes(data);
+            return data;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Salt.cs b/Axantum.AxCrypt.Core/Crypto/Salt.cs
new file mode 100644
index 0000000..6cccdf3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Salt.cs
@@ -0,0 +1,103 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// A salt for the Symmetrical Key Wrap. Instances of this class are immutable.
+    /// </summary>
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class Salt
+    {
+        [DataMember(Name = "Salt")]
+        private readonly byte[] _salt;
+
+        /// <summary>
+        /// An instance of KeyWrapSalt with all zeroes.
+        /// </summary>
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "The reference type 'Salt' is, in fact, immutable.")]
+        public static readonly Salt Zero = new Salt(new byte[0]);
+
+        /// <summary>
+        /// Required for DataContract deserialization
+        /// </summary>
+        private Salt()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Salt"/> class.
+        /// </summary>
+        /// <param name="length">The length of the salt in bits.</param>
+        public Salt(int size)
+        {
+            if (size < 0)
+            {
+                throw new ArgumentOutOfRangeException("size");
+            }
+            _salt = Instance.RandomGenerator.Generate(size / 8);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Salt"/> class.
+        /// </summary>
+        /// <param name="length">The salt. It must be a valid symmetric key length.</param>
+        public Salt(byte[] salt)
+        {
+            if (salt == null)
+            {
+                throw new ArgumentNullException("salt");
+            }
+            _salt = (byte[])salt.Clone();
+        }
+
+        /// <summary>
+        /// Gets the length of the salt.
+        /// </summary>
+        ///
+        public int Length
+        {
+            get
+            {
+                return _salt.Length;
+            }
+        }
+
+        /// <summary>
+        /// Gets the bytes of the salt.
+        /// </summary>
+        /// <returns>Returns the bytes of the salt.</returns>
+        public byte[] GetBytes()
+        {
+            return (byte[])_salt.Clone();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/Subkey.cs b/Axantum.AxCrypt.Core/Crypto/Subkey.cs
new file mode 100644
index 0000000..d94f77d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/Subkey.cs
@@ -0,0 +1,92 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Generates a sub key from a master key. Instances of this class are immutable.
+    /// </summary>
+    public class Subkey
+    {
+        private SymmetricKey _subKey;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="Subkey"/> class. Different data is encrypted using
+        /// different variants of the master encryption key.
+        /// </summary>
+        /// <param name="masterKey">The master key.</param>
+        /// <param name="headerSubkey">The header subkey.</param>
+        public Subkey(SymmetricKey masterKey, HeaderSubkey headerSubkey)
+        {
+            if (masterKey == null)
+            {
+                throw new ArgumentNullException("masterKey");
+            }
+
+            byte[] block = new byte[16];
+            byte subKeyValue;
+            switch (headerSubkey)
+            {
+                case HeaderSubkey.Hmac:
+                    subKeyValue = 0;
+                    break;
+
+                case HeaderSubkey.Validator:
+                    subKeyValue = 1;
+                    break;
+
+                case HeaderSubkey.Headers:
+                    subKeyValue = 2;
+                    break;
+
+                case HeaderSubkey.Data:
+                    subKeyValue = 3;
+                    break;
+
+                default:
+                    throw new InternalErrorException("headerSubkey");
+            }
+
+            block[0] = subKeyValue;
+            _subKey = new SymmetricKey(Instance.CryptoFactory.Legacy.CreateCrypto(masterKey, null, 0).Encrypt(block));
+        }
+
+        /// <summary>
+        /// Gets the sub key.
+        /// </summary>
+        public SymmetricKey Key
+        {
+            get
+            {
+                return _subKey;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/SymmetricIV.cs b/Axantum.AxCrypt.Core/Crypto/SymmetricIV.cs
new file mode 100644
index 0000000..ba91995
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/SymmetricIV.cs
@@ -0,0 +1,90 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// An Initial Vector for block chaining with a symmetric algorithm. Instances of this class are immutable.
+    /// </summary>
+    public class SymmetricIV
+    {
+        private byte[] _iv;
+
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "The reference type 'SymmetricIV' is, in fact, immutable.")]
+        public static readonly SymmetricIV Zero128 = new SymmetricIV(new byte[128 / 8]);
+
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "The reference type 'SymmetricIV' is, in fact, immutable.")]
+        public static readonly SymmetricIV Zero64 = new SymmetricIV(new byte[64 / 8]);
+
+        /// <summary>
+        /// Instantiate a new random IV
+        /// </summary>
+        public SymmetricIV(int blockBits)
+        {
+            _iv = Instance.RandomGenerator.Generate(blockBits / 8);
+        }
+
+        /// <summary>
+        /// Instantiate a new IV
+        /// </summary>
+        /// <param name="iv">The Initial Vector to use</param>
+        public SymmetricIV(byte[] iv)
+        {
+            if (iv == null)
+            {
+                throw new ArgumentNullException("iv");
+            }
+            _iv = (byte[])iv.Clone();
+        }
+
+        /// <summary>
+        /// Get the actual IV bytes
+        /// </summary>
+        /// <returns></returns>
+        public byte[] GetBytes()
+        {
+            return (byte[])_iv.Clone();
+        }
+
+        /// <summary>
+        /// Gets the length of the IV.
+        /// </summary>
+        /// <value>
+        /// The length.
+        /// </value>
+        public int Length
+        {
+            get
+            {
+                return _iv.Length;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/SymmetricKey.cs b/Axantum.AxCrypt.Core/Crypto/SymmetricKey.cs
new file mode 100644
index 0000000..c5565ac
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/SymmetricKey.cs
@@ -0,0 +1,154 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Hold a key for a symmetric algorithm. Instances of this class are immutable.
+    /// </summary>
+    public class SymmetricKey : IEquatable<SymmetricKey>
+    {
+        private byte[] _symmetricKey;
+
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This type is immutable.")]
+        public static readonly SymmetricKey Zero128 = new SymmetricKey(new byte[16]);
+
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This type is immutable.")]
+        public static readonly SymmetricKey Zero256 = new SymmetricKey(new byte[32]);
+
+        /// <summary>
+        /// Instantiate a random key.
+        /// </summary>
+        public SymmetricKey(int keyBits)
+            : this(Instance.RandomGenerator.Generate(keyBits / 8))
+        {
+        }
+
+        /// <summary>
+        /// Instantiate a key.
+        /// </summary>
+        /// <param name="key">The key to use. The length can be any that is valid for the algorithm.</param>
+        public SymmetricKey(byte[] key)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            _symmetricKey = (byte[])key.Clone();
+        }
+
+        /// <summary>
+        /// Get the actual key bytes.
+        /// </summary>
+        /// <returns></returns>
+        public byte[] GetBytes()
+        {
+            return (byte[])_symmetricKey.Clone();
+        }
+
+        public int Size
+        {
+            get
+            {
+                return _symmetricKey.Length * 8;
+            }
+        }
+
+        #region IEquatable<SymmetricKey> Members
+
+        /// <summary>
+        /// Check if one instance is equivalent to another.
+        /// </summary>
+        /// <param name="other">The instance to compare to</param>
+        /// <returns>true if the keys are equivalent</returns>
+        public bool Equals(SymmetricKey other)
+        {
+            if ((object)other == null)
+            {
+                return false;
+            }
+            return _symmetricKey.IsEquivalentTo(other._symmetricKey);
+        }
+
+        #endregion IEquatable<SymmetricKey> Members
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null || typeof(SymmetricKey) != obj.GetType())
+            {
+                return false;
+            }
+            SymmetricKey other = (SymmetricKey)obj;
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            int hashcode = 0;
+            foreach (byte b in _symmetricKey)
+            {
+                hashcode += b;
+            }
+            return hashcode;
+        }
+
+        public static bool operator ==(SymmetricKey left, SymmetricKey right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if ((object)left == null)
+            {
+                return false;
+            }
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(SymmetricKey left, SymmetricKey right)
+        {
+            return !(left == right);
+        }
+
+        public static byte[] operator +(SymmetricKey left, SymmetricIV right)
+        {
+            byte[] leftBytes = left.GetBytes();
+            byte[] rightBytes = right.GetBytes();
+            byte[] result = new byte[leftBytes.Length + rightBytes.Length];
+
+            leftBytes.CopyTo(result, 0);
+            rightBytes.CopyTo(result, leftBytes.Length);
+
+            return result;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/SymmetricKeyThumbprint.cs b/Axantum.AxCrypt.Core/Crypto/SymmetricKeyThumbprint.cs
new file mode 100644
index 0000000..73db73f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/SymmetricKeyThumbprint.cs
@@ -0,0 +1,133 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Represent a salted thumb print for a symmetric key. Instances of this class are immutable. A thumb print is
+    /// typically only valid and comparable on the same computer and log on where it was created. However, it *is*
+    /// only based on the passphrase, and some user-specific values. It always uses the same crypto, the same
+    /// passphrase will have the same thumbprint regardless of which crypto is actually used when encrypting data
+    /// with the corresponding passphrase.
+    /// </summary>
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class SymmetricKeyThumbprint : IEquatable<SymmetricKeyThumbprint>
+    {
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This class is immutable.")]
+        public static readonly SymmetricKeyThumbprint Zero = new SymmetricKeyThumbprint();
+
+        [DataMember(Name = "Thumbprint")]
+        private byte[] _bytes;
+
+        private SymmetricKeyThumbprint()
+        {
+            _bytes = new byte[8];
+        }
+
+        /// <summary>
+        /// Instantiate a thumb print
+        /// </summary>
+        /// <param name="passphrase">The passphrase to thumbprint.</param>
+        /// <param name="salt">The salt to use.</param>
+        public SymmetricKeyThumbprint(Passphrase passphrase, Salt salt, long keyWrapIterations)
+        {
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+            if (salt == null)
+            {
+                throw new ArgumentNullException("salt");
+            }
+
+            ICryptoFactory factory = Instance.CryptoFactory.Minimum;
+            ICrypto crypto = factory.CreateCrypto(factory.RestoreDerivedKey(passphrase, salt, CryptoFactory.DerivationIterations).DerivedKey, null, 0);
+            KeyWrap keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.Specification);
+            byte[] wrap = keyWrap.Wrap(crypto, crypto.Key);
+
+            _bytes = wrap.Reduce(6);
+        }
+
+        #region IEquatable<AesKeyThumbprint> Members
+
+        public bool Equals(SymmetricKeyThumbprint other)
+        {
+            if ((object)other == null)
+            {
+                return false;
+            }
+
+            return _bytes.IsEquivalentTo(other._bytes);
+        }
+
+        #endregion IEquatable<AesKeyThumbprint> Members
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null || typeof(SymmetricKeyThumbprint) != obj.GetType())
+            {
+                return false;
+            }
+            SymmetricKeyThumbprint other = (SymmetricKeyThumbprint)obj;
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            int hashcode = 0;
+            foreach (byte b in _bytes)
+            {
+                hashcode += b;
+            }
+            return hashcode;
+        }
+
+        public static bool operator ==(SymmetricKeyThumbprint left, SymmetricKeyThumbprint right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if ((object)left == null)
+            {
+                return false;
+            }
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(SymmetricKeyThumbprint left, SymmetricKeyThumbprint right)
+        {
+            return !(left == right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V1Aes128CryptoFactory.cs b/Axantum.AxCrypt.Core/Crypto/V1Aes128CryptoFactory.cs
new file mode 100644
index 0000000..60e8e3c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V1Aes128CryptoFactory.cs
@@ -0,0 +1,86 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class V1Aes128CryptoFactory : ICryptoFactory
+    {
+        public static readonly Guid CryptoId = new Guid("1673BBEF-A56A-43AC-AB16-E14D2BAD1CBF");
+
+        public IDerivedKey CreateDerivedKey(Passphrase passphrase)
+        {
+            return new V1DerivedKey(passphrase);
+        }
+
+        public IDerivedKey RestoreDerivedKey(Passphrase passphrase, Salt salt, int derivationIterations)
+        {
+            return new V1DerivedKey(passphrase);
+        }
+
+        public ICrypto CreateCrypto(SymmetricKey key, SymmetricIV iv, long keyStreamOffset)
+        {
+            return new V1AesCrypto(this, key, iv);
+        }
+
+        public int Priority
+        {
+            get { return 100000; }
+        }
+
+        public Guid Id
+        {
+            get { return CryptoId; }
+        }
+
+        /// <summary>
+        /// Gets the unique name of the algorithm implementation.
+        /// </summary>
+        /// <value>
+        /// The name. This must be a short, language independent name usable both as an internal identifier, and as a display name.
+        /// Typical values are "AES-128", "AES-256". The UI may use these as indexes for localized or clearer names, but if unknown
+        /// the UI must be able to fallback and actually display this identifier as a selector for example in the UI. This is to
+        /// support plug-in algorithm implementations in the future.
+        /// </value>
+        public string Name
+        {
+            get { return "AES-128-V1"; }
+        }
+
+        public int KeySize
+        {
+            get { return 128; }
+        }
+
+        public int BlockSize
+        {
+            get { return 128; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V1AesCrypto.cs b/Axantum.AxCrypt.Core/Crypto/V1AesCrypto.cs
new file mode 100644
index 0000000..7ab4c85
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V1AesCrypto.cs
@@ -0,0 +1,171 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Wrap an AES implementation with key and parameters.
+    /// </summary>
+    public class V1AesCrypto : CryptoBase
+    {
+        internal const string InternalName = "AES-128-V1";
+
+        private SymmetricIV _iv;
+
+        /// <summary>
+        /// Instantiate a transformation
+        /// </summary>
+        /// <param name="key">The key</param>
+        /// <param name="iv">Initial Vector, or null for a zero vector.</param>
+        public V1AesCrypto(ICryptoFactory factory, SymmetricKey key, SymmetricIV iv)
+        {
+            if (factory == null)
+            {
+                throw new ArgumentNullException("factory");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (key.Size != 128)
+            {
+                throw new ArgumentException("Key length is invalid.");
+            }
+            using (SymmetricAlgorithm algorithm = CreateRawAlgorithm())
+            {
+                iv = iv ?? new SymmetricIV(new byte[algorithm.BlockSize / 8]);
+                if (iv.Length != algorithm.BlockSize / 8)
+                {
+                    throw new ArgumentException("The IV length must be the same as the algorithm block length.");
+                }
+            }
+
+            Key = key;
+            _iv = iv;
+        }
+
+        public override int BlockLength
+        {
+            get { return _iv.Length; }
+        }
+
+        /// <summary>
+        /// Create an instance of tranform suitable for NIST Key Wrap
+        /// </summary>
+        /// <returns></returns>
+        /// <value>
+        /// An instance of the algorithm.
+        /// </value>
+        public override IKeyWrapTransform CreateKeyWrapTransform(Salt salt, KeyWrapDirection keyWrapDirection)
+        {
+            return new BlockAlgorithmKeyWrapTransform(CreateAlgorithmInternal(), salt, keyWrapDirection);
+        }
+
+        private SymmetricAlgorithm CreateAlgorithmInternal()
+        {
+            SymmetricAlgorithm algorithm = CreateRawAlgorithm();
+            algorithm.Key = Key.GetBytes();
+            algorithm.IV = _iv.GetBytes();
+
+            return algorithm;
+        }
+
+        private static SymmetricAlgorithm CreateRawAlgorithm()
+        {
+            return Instance.Portable.AesManaged();
+        }
+
+        /// <summary>
+        /// Decrypt in one operation.
+        /// </summary>
+        /// <param name="cipherText">The complete cipher text</param>
+        /// <returns>The decrypted result minus any padding</returns>
+        public override byte[] Decrypt(byte[] cipherText)
+        {
+            using (SymmetricAlgorithm aes = CreateAlgorithmInternal())
+            {
+                aes.Mode = CipherMode.CBC;
+                aes.Padding = PaddingMode.None;
+                using (ICryptoTransform decryptor = aes.CreateDecryptor())
+                {
+                    byte[] plaintext = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);
+                    return plaintext;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Encrypt
+        /// </summary>
+        /// <param name="plaintext">The complete plaintext bytes</param>
+        /// <returns>The cipher text, complete with any padding</returns>
+        public override byte[] Encrypt(byte[] plaintext)
+        {
+            using (SymmetricAlgorithm aes = CreateAlgorithmInternal())
+            {
+                aes.Mode = CipherMode.CBC;
+                aes.Padding = PaddingMode.None;
+                using (ICryptoTransform encryptor = aes.CreateEncryptor())
+                {
+                    byte[] cipherText = encryptor.TransformFinalBlock(plaintext, 0, plaintext.Length);
+                    return cipherText;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Using this instances parameters, create a decryptor
+        /// </summary>
+        /// <returns>A new decrypting transformation instance</returns>
+        public override ICryptoTransform CreateDecryptingTransform()
+        {
+            using (SymmetricAlgorithm aes = CreateAlgorithmInternal())
+            {
+                aes.Mode = CipherMode.CBC;
+                aes.Padding = PaddingMode.PKCS7;
+                return aes.CreateDecryptor();
+            }
+        }
+
+        /// <summary>
+        /// Using this instances parameters, create an encryptor
+        /// </summary>
+        /// <returns>A new encrypting transformation instance</returns>
+        public override ICryptoTransform CreateEncryptingTransform()
+        {
+            using (SymmetricAlgorithm aes = CreateAlgorithmInternal())
+            {
+                aes.Mode = CipherMode.CBC;
+                aes.Padding = PaddingMode.PKCS7;
+                return aes.CreateEncryptor();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V1DerivedKey.cs b/Axantum.AxCrypt.Core/Crypto/V1DerivedKey.cs
new file mode 100644
index 0000000..f31f1f4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V1DerivedKey.cs
@@ -0,0 +1,61 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Derive a SymmetricKey from a string passphrase representation for AxCrypt. Instances of this class are immutable.
+    /// </summary>
+    public class V1DerivedKey : DerivedKeyBase
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="V1DerivedKey"/> class.
+        /// </summary>
+        /// <param name="passphrase">The passphrase.</param>
+        public V1DerivedKey(Passphrase passphrase)
+        {
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+
+            HashAlgorithm hashAlgorithm = Instance.Portable.SHA1Managed();
+            byte[] ansiBytes = Encoding.GetEncoding("Windows-1252").GetBytes(passphrase.Text);
+            byte[] hash = hashAlgorithm.ComputeHash(ansiBytes);
+            byte[] derivedKey = new byte[16];
+            Array.Copy(hash, derivedKey, derivedKey.Length);
+
+            DerivationSalt = Salt.Zero;
+            DerivationIterations = 0;
+            DerivedKey = new SymmetricKey(derivedKey);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V1Hmac.cs b/Axantum.AxCrypt.Core/Crypto/V1Hmac.cs
new file mode 100644
index 0000000..ae30855
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V1Hmac.cs
@@ -0,0 +1,48 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// The HMAC of AxCrypt encrypted data. Instances of this class are immutable.
+    /// </summary>
+    public class V1Hmac : Hmac
+    {
+        public static readonly int RequiredLength = 16;
+
+        /// <summary>
+        /// Initializes an instance of DataHmac with the provided bytes.
+        /// </summary>
+        /// <param name="hmac">The bytes of the DataHmac</param>
+        public V1Hmac(byte[] hmac)
+        {
+            Initialize(hmac, RequiredLength);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2Aes128CryptoFactory.cs b/Axantum.AxCrypt.Core/Crypto/V2Aes128CryptoFactory.cs
new file mode 100644
index 0000000..ef55140
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2Aes128CryptoFactory.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class V2Aes128CryptoFactory : ICryptoFactory
+    {
+        public static readonly Guid CryptoId = new Guid("2B0CCBB0-B978-4BC3-A293-F97585F06557");
+
+        public IDerivedKey CreateDerivedKey(Passphrase passphrase)
+        {
+            return new V2DerivedKey(passphrase, 128);
+        }
+
+        public IDerivedKey RestoreDerivedKey(Passphrase passphrase, Salt salt, int derivationIterations)
+        {
+            return new V2DerivedKey(passphrase, salt, derivationIterations, 128);
+        }
+
+        public ICrypto CreateCrypto(SymmetricKey key, SymmetricIV iv, long keyStreamOffset)
+        {
+            return new V2AesCrypto(key, iv, keyStreamOffset);
+        }
+
+        public int Priority
+        {
+            get { return 200000; }
+        }
+
+        public Guid Id
+        {
+            get { return CryptoId; }
+        }
+
+        public string Name
+        {
+            get { return "AES-128"; }
+        }
+
+        public int KeySize
+        {
+            get { return 128; }
+        }
+
+        public int BlockSize
+        {
+            get { return 128; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2Aes256CryptoFactory.cs b/Axantum.AxCrypt.Core/Crypto/V2Aes256CryptoFactory.cs
new file mode 100644
index 0000000..2116b7c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2Aes256CryptoFactory.cs
@@ -0,0 +1,77 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public class V2Aes256CryptoFactory : ICryptoFactory
+    {
+        public static readonly Guid CryptoId = new Guid("E20F33D4-89E2-4D88-A39C-21DD62FB674F");
+
+        public IDerivedKey CreateDerivedKey(Passphrase passphrase)
+        {
+            return new V2DerivedKey(passphrase, 256);
+        }
+
+        public IDerivedKey RestoreDerivedKey(Passphrase passphrase, Salt salt, int derivationIterations)
+        {
+            return new V2DerivedKey(passphrase, salt, derivationIterations, 256);
+        }
+
+        public ICrypto CreateCrypto(SymmetricKey key, SymmetricIV iv, long keyStreamOffset)
+        {
+            return new V2AesCrypto(key, iv, keyStreamOffset);
+        }
+
+        public int Priority
+        {
+            get { return 300000; }
+        }
+
+        public Guid Id
+        {
+            get { return CryptoId; }
+        }
+
+        public string Name
+        {
+            get { return "AES-256"; }
+        }
+
+        public int KeySize
+        {
+            get { return 256; }
+        }
+
+        public int BlockSize
+        {
+            get { return 128; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2AesCrypto.cs b/Axantum.AxCrypt.Core/Crypto/V2AesCrypto.cs
new file mode 100644
index 0000000..4c08326
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2AesCrypto.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Implements V2 AES Cryptography
+    /// </summary>
+    public class V2AesCrypto : V2CryptoBase
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="V2AesCrypto"/> class.
+        /// </summary>
+        /// <param name="factory">The factory.</param>
+        /// <param name="key">The key.</param>
+        /// <param name="iv">The iv, or null for none.</param>
+        /// <param name="keyStreamOffset">The key stream offset.</param>
+        public V2AesCrypto(SymmetricKey key, SymmetricIV iv, long keyStreamOffset)
+        {
+            using (SymmetricAlgorithm algorithm = CreateAlgorithmInternal())
+            {
+                Initialize(key, iv, keyStreamOffset, algorithm);
+            }
+        }
+
+        protected override SymmetricAlgorithm CreateAlgorithm()
+        {
+            return CreateAlgorithmInternal();
+        }
+
+        private static SymmetricAlgorithm CreateAlgorithmInternal()
+        {
+            return Instance.Portable.AesManaged();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2CryptoBase.cs b/Axantum.AxCrypt.Core/Crypto/V2CryptoBase.cs
new file mode 100644
index 0000000..ef7ebb1
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2CryptoBase.cs
@@ -0,0 +1,141 @@
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    public abstract class V2CryptoBase : CryptoBase
+    {
+        private SymmetricIV _iv;
+
+        private long _blockCounter;
+
+        private int _blockOffset;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="V2CryptoBase" /> class.
+        /// </summary>
+        /// <param name="key">The key.</param>
+        /// <param name="iv">The iv, or null for none.</param>
+        /// <param name="keyStreamOffset">The key stream offset.</param>
+        /// <exception cref="System.ArgumentNullException">factory
+        /// or
+        /// key
+        /// or
+        /// iv</exception>
+        /// <exception cref="System.ArgumentException">Key length is invalid.
+        /// or
+        /// The IV length must be the same as the algorithm block length.</exception>
+        protected void Initialize(SymmetricKey key, SymmetricIV iv, long keyStreamOffset, SymmetricAlgorithm algorithm)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            if (!algorithm.ValidKeySize(key.Size))
+            {
+                throw new ArgumentException("Key length is invalid.");
+            }
+            iv = iv ?? new SymmetricIV(new byte[algorithm.BlockSize / 8]);
+            if (iv.Length != algorithm.BlockSize / 8)
+            {
+                throw new ArgumentException("The IV length must be the same as the algorithm block length.");
+            }
+
+            Key = key;
+            _iv = iv;
+            _blockCounter = keyStreamOffset / iv.Length;
+            _blockOffset = (int)(keyStreamOffset % iv.Length);
+        }
+
+        public override int BlockLength
+        {
+            get
+            {
+                return _iv.Length;
+            }
+        }
+
+        /// <summary>
+        /// Create an instance of a transform suitable for NIST Key Wrap.
+        /// </summary>
+        /// <returns></returns>
+        /// <value>
+        /// An instance of the transform.
+        /// </value>
+        public override IKeyWrapTransform CreateKeyWrapTransform(Salt salt, KeyWrapDirection keyWrapDirection)
+        {
+            return new BlockAlgorithmKeyWrapTransform(CreateAlgorithmInternal(), salt, keyWrapDirection);
+        }
+
+        private SymmetricAlgorithm CreateAlgorithmInternal()
+        {
+            SymmetricAlgorithm algorithm = CreateAlgorithm();
+            algorithm.Key = Key.GetBytes();
+            algorithm.IV = _iv.GetBytes();
+            algorithm.Mode = CipherMode.ECB;
+            algorithm.Padding = PaddingMode.None;
+
+            return algorithm;
+        }
+
+        protected abstract SymmetricAlgorithm CreateAlgorithm();
+
+        /// <summary>
+        /// Decrypt in one operation.
+        /// </summary>
+        /// <param name="cipherText">The complete cipher text</param>
+        /// <returns>
+        /// The decrypted result minus any padding
+        /// </returns>
+        public override byte[] Decrypt(byte[] cipherText)
+        {
+            return Transform(cipherText);
+        }
+
+        /// <summary>
+        /// Encrypt in one operation
+        /// </summary>
+        /// <param name="plaintext">The complete plaintext bytes</param>
+        /// <returns>
+        /// The cipher text, complete with any padding
+        /// </returns>
+        public override byte[] Encrypt(byte[] plaintext)
+        {
+            return Transform(plaintext);
+        }
+
+        private byte[] Transform(byte[] plaintext)
+        {
+            using (SymmetricAlgorithm algorithm = CreateAlgorithmInternal())
+            {
+                using (ICryptoTransform transform = new CounterModeCryptoTransform(algorithm, _blockCounter, _blockOffset))
+                {
+                    return transform.TransformFinalBlock(plaintext, 0, plaintext.Length);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Using this instances parameters, create a decryptor
+        /// </summary>
+        /// <returns>
+        /// A new decrypting transformation instance
+        /// </returns>
+        public override ICryptoTransform CreateDecryptingTransform()
+        {
+            return new CounterModeCryptoTransform(CreateAlgorithmInternal(), _blockCounter, _blockOffset);
+        }
+
+        /// <summary>
+        /// Using this instances parameters, create an encryptor
+        /// </summary>
+        /// <returns>
+        /// A new encrypting transformation instance
+        /// </returns>
+        public override ICryptoTransform CreateEncryptingTransform()
+        {
+            return new CounterModeCryptoTransform(CreateAlgorithmInternal(), _blockCounter, _blockOffset);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2DerivedKey.cs b/Axantum.AxCrypt.Core/Crypto/V2DerivedKey.cs
new file mode 100644
index 0000000..2cf14af
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2DerivedKey.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// Derive a SymmetricKey from a string passphrase representation for AxCrypt V2. Instances of this class are immutable.
+    /// </summary>
+    public class V2DerivedKey : DerivedKeyBase
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="V2DerivedKey"/> class.
+        /// </summary>
+        /// <param name="passphrase">The passphrase.</param>
+        public V2DerivedKey(Passphrase passphrase, Salt salt, int derivationIterations, int keySize)
+        {
+            DerivationSalt = salt;
+            DerivationIterations = derivationIterations;
+            DerivedKey = new SymmetricKey(new Pbkdf2HmacSha512(passphrase.Text, salt, derivationIterations).GetBytes().Reduce(keySize / 8));
+        }
+
+        public V2DerivedKey(Passphrase passphrase, int keySize)
+            : this(passphrase, new Salt(256), CryptoFactory.DerivationIterations, keySize)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Crypto/V2Hmac.cs b/Axantum.AxCrypt.Core/Crypto/V2Hmac.cs
new file mode 100644
index 0000000..d25e8e0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Crypto/V2Hmac.cs
@@ -0,0 +1,48 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core.Crypto
+{
+    /// <summary>
+    /// The HMAC of AxCrypt encrypted data. Instances of this class are immutable.
+    /// </summary>
+    public class V2Hmac : Hmac
+    {
+        public static readonly int RequiredLength = 64;
+
+        /// <summary>
+        /// Initializes an instance of DataHmac with the provided bytes.
+        /// </summary>
+        /// <param name="hmac">The bytes of the DataHmac</param>
+        public V2Hmac(byte[] hmac)
+        {
+            Initialize(hmac, RequiredLength);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/ErrorStatus.cs b/Axantum.AxCrypt.Core/ErrorStatus.cs
new file mode 100644
index 0000000..84aa06d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/ErrorStatus.cs
@@ -0,0 +1,45 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core
+{
+    public enum ErrorStatus
+    {
+        Success,
+        Unknown,
+        MagicGuidMissing,
+        InternalError,
+        EndOfStream,
+        TooNewFileFormatVersion,
+        TooOldFileFormatVersion,
+        FileFormatError,
+        HmacValidationError,
+        DataError,
+        Cancel,
+        FileExists,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/ByteArrayExtensions.cs b/Axantum.AxCrypt.Core/Extensions/ByteArrayExtensions.cs
new file mode 100644
index 0000000..be85932
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/ByteArrayExtensions.cs
@@ -0,0 +1,254 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class ByteArrayExtensions
+    {
+        /// <summary>
+        /// Naive implementation of IndexOf - optimize only if it proves necessary. Look for Boyer Moore.
+        /// </summary>
+        /// <param name="buffer">The buffer to search in</param>
+        /// <param name="pattern">The pattern to search for</param>
+        /// <param name="offset">Where to start the search in buffer</param>
+        /// <param name="count">How many bytes to include in the search</param>
+        /// <returns>The location in the buffer of the pattern, or -1 if not found</returns>
+        public static int Locate(this byte[] buffer, byte[] pattern, int offset, int count)
+        {
+            return buffer.Locate(pattern, offset, count, 1);
+        }
+
+        /// <summary>
+        /// Naive implementation of IndexOf - optimize only if it proves necessary. Look for Boyer Moore.
+        /// </summary>
+        /// <param name="buffer">The buffer to search in</param>
+        /// <param name="pattern">The pattern to search for</param>
+        /// <param name="offset">Where to start the search in buffer</param>
+        /// <param name="count">How many bytes to include in the search</param>
+        /// <param name="increment">How much to increment when stepping forward</param>
+        /// <returns>The location in the buffer of the pattern, or -1 if not found</returns>
+        public static int Locate(this byte[] buffer, byte[] pattern, int offset, int count, int increment)
+        {
+            int candidatePosition = offset;
+            while (candidatePosition - offset + pattern.Length <= count)
+            {
+                int i;
+                for (i = 0; i < pattern.Length; i += increment)
+                {
+                    int j;
+                    for (j = 0; j < increment; ++j)
+                    {
+                        if (buffer[candidatePosition + i + j] != pattern[i + j])
+                        {
+                            break;
+                        }
+                    }
+                    if (j < increment)
+                    {
+                        break;
+                    }
+                }
+                if (i == pattern.Length)
+                {
+                    return candidatePosition;
+                }
+                candidatePosition += increment;
+            }
+            return -1;
+        }
+
+        public static byte[] Xor(this byte[] buffer, byte[] other)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            int bytesToXor = buffer.Length < other.Length ? buffer.Length : other.Length;
+            buffer.Xor(0, other, 0, bytesToXor);
+            return buffer;
+        }
+
+        public static byte[] Xor(this byte[] buffer, int bufferIndex, byte[] other, int otherIndex, int length)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+            if (other == null)
+            {
+                throw new ArgumentNullException("other");
+            }
+            if (bufferIndex + length > buffer.Length)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            if (otherIndex + length > other.Length)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            for (int i = 0; i < length; ++i)
+            {
+                buffer[bufferIndex + i] ^= other[otherIndex + i];
+            }
+            return buffer;
+        }
+
+        public static byte[] Append(this byte[] left, params byte[][] arrays)
+        {
+            int length = 0;
+            foreach (byte[] array in arrays)
+            {
+                length += array.Length;
+            }
+            length += left.Length;
+            byte[] concatenatedArray = new byte[length];
+            left.CopyTo(concatenatedArray, 0);
+            int index = left.Length;
+            foreach (byte[] array in arrays)
+            {
+                array.CopyTo(concatenatedArray, index);
+                index += array.Length;
+            }
+            return concatenatedArray;
+        }
+
+        public static bool IsEquivalentTo(this byte[] left, int leftOffset, byte[] right, int rightOffset, int length)
+        {
+            if (left == null)
+            {
+                throw new ArgumentNullException("left");
+            }
+            if (right == null)
+            {
+                throw new ArgumentNullException("right");
+            }
+            if (length < 0)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            if (leftOffset < 0)
+            {
+                throw new ArgumentOutOfRangeException("leftOffset");
+            }
+            if (leftOffset + length > left.Length)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            if (rightOffset < 0)
+            {
+                throw new ArgumentOutOfRangeException("rightOffset");
+            }
+            if (rightOffset + length > right.Length)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            return left.IsEquivalentToInternal(leftOffset, right, rightOffset, length);
+        }
+
+        private static bool IsEquivalentToInternal(this byte[] left, int leftOffset, byte[] right, int rightOffset, int length)
+        {
+            for (int i = 0; i < length; ++i)
+            {
+                if (left[leftOffset + i] != right[rightOffset + i])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsEquivalentTo(this byte[] left, byte[] right)
+        {
+            if (left == null)
+            {
+                throw new ArgumentNullException("left");
+            }
+            if (right == null)
+            {
+                throw new ArgumentNullException("right");
+            }
+            if (right.Length != left.Length)
+            {
+                return false;
+            }
+            return left.IsEquivalentToInternal(0, right, 0, right.Length);
+        }
+
+        public static long GetLittleEndianValue(this byte[] left, int offset, int length)
+        {
+            long value = 0;
+            while (length-- > 0)
+            {
+                value <<= 8;
+                value |= left[offset + length];
+            }
+            return value;
+        }
+
+        public static long GetBigEndianValue(this byte[] left, int offset, int length)
+        {
+            long value = 0;
+            for (int i = 0; i < length; ++i)
+            {
+                value <<= 8;
+                value |= left[offset + i];
+            }
+            return value;
+        }
+
+        public static byte[] Reduce(this byte[] value, int length)
+        {
+            if (value.Length == 0)
+            {
+                return value;
+            }
+            if (value.Length < length)
+            {
+                throw new ArgumentException("Can't reduce a byte array that is already shorter than the target length.");
+            }
+            byte[] reduced = new byte[length];
+            for (int i = 0; i < value.Length; ++i)
+            {
+                reduced[i % length] ^= value[i];
+            }
+            return reduced;
+        }
+
+        public static byte[] SetFrom(this byte[] left, byte[] right)
+        {
+            right.CopyTo(left, 0);
+            return left;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/EnumExtensions.cs b/Axantum.AxCrypt.Core/Extensions/EnumExtensions.cs
new file mode 100644
index 0000000..f015231
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/EnumExtensions.cs
@@ -0,0 +1,48 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Globalization;
+using System.Linq;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class EnumExtensions
+    {
+        public static bool HasMask(this AxCryptOptions options, AxCryptOptions mask)
+        {
+            return (options & mask) == mask;
+        }
+
+        public static bool HasMask(this ActiveFileStatus status, ActiveFileStatus mask)
+        {
+            return (status & mask) == mask;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/PrimitiveTypeExtensions.cs b/Axantum.AxCrypt.Core/Extensions/PrimitiveTypeExtensions.cs
new file mode 100644
index 0000000..b5cc517
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/PrimitiveTypeExtensions.cs
@@ -0,0 +1,108 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class PrimitiveTypeExtensions
+    {
+        public static byte[] GetLittleEndianBytes(this long value)
+        {
+            if (OS.Current.IsLittleEndian)
+            {
+                return BitConverter.GetBytes(value);
+            }
+
+            byte[] bytes = new byte[sizeof(long)];
+
+            for (int i = 0; value != 0 && i < bytes.Length; ++i)
+            {
+                bytes[i] = (byte)value;
+                value >>= 8;
+            }
+            return bytes;
+        }
+
+        public static byte[] GetLittleEndianBytes(this int value)
+        {
+            if (OS.Current.IsLittleEndian)
+            {
+                return BitConverter.GetBytes(value);
+            }
+
+            byte[] bytes = new byte[sizeof(int)];
+
+            for (int i = 0; value != 0 && i < bytes.Length; ++i)
+            {
+                bytes[i] = (byte)value;
+                value >>= 8;
+            }
+            return bytes;
+        }
+
+        public static byte[] GetBigEndianBytes(this long value)
+        {
+            if (!OS.Current.IsLittleEndian)
+            {
+                return BitConverter.GetBytes(value);
+            }
+
+            byte[] bytes = new byte[sizeof(long)];
+
+            for (int i = bytes.Length - 1; value != 0 && i >= 0; --i)
+            {
+                bytes[i] = (byte)value;
+                value >>= 8;
+            }
+            return bytes;
+        }
+
+        public static byte[] GetBigEndianBytes(this int value)
+        {
+            if (!OS.Current.IsLittleEndian)
+            {
+                return BitConverter.GetBytes(value);
+            }
+
+            byte[] bytes = new byte[sizeof(int)];
+
+            for (int i = bytes.Length - 1; value != 0 && i >= 0; --i)
+            {
+                bytes[i] = (byte)value;
+                value >>= 8;
+            }
+            return bytes;
+        }
+
+        public static T Fallback<T>(this T value, T fallbackValue) where T : IEquatable<T>
+        {
+            return !value.Equals(default(T)) ? value : fallbackValue;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/RuntimeFileInfoExtensions.cs b/Axantum.AxCrypt.Core/Extensions/RuntimeFileInfoExtensions.cs
new file mode 100644
index 0000000..7bf8830
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/RuntimeFileInfoExtensions.cs
@@ -0,0 +1,169 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class RuntimeFileInfoExtensions
+    {
+        public static FileInfoTypes Type(this IRuntimeFileInfo fileInfo)
+        {
+            if (!fileInfo.IsExistingFile && !fileInfo.IsExistingFolder)
+            {
+                return FileInfoTypes.NonExisting;
+            }
+            if (fileInfo.IsExistingFolder)
+            {
+                return FileInfoTypes.Folder;
+            }
+            if (fileInfo.IsEncryptable())
+            {
+                return FileInfoTypes.EncryptableFile;
+            }
+            if (fileInfo.IsEncrypted())
+            {
+                return FileInfoTypes.EncryptedFile;
+            }
+            return FileInfoTypes.OtherFile;
+        }
+
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Encryptable", Justification = "Encryptable is a word.")]
+        public static bool IsEncryptable(this IRuntimeFileInfo fileInfo)
+        {
+            if (fileInfo == null)
+            {
+                throw new ArgumentNullException("fileInfo");
+            }
+
+            foreach (Regex filter in OS.PathFilters)
+            {
+                if (filter.IsMatch(fileInfo.FullName))
+                {
+                    return false;
+                }
+            }
+            return !fileInfo.IsEncrypted();
+        }
+
+        public static IRuntimeFileInfo NormalizeFolder(this IRuntimeFileInfo folder)
+        {
+            if (folder == null)
+            {
+                throw new ArgumentNullException("folder");
+            }
+
+            if (folder.FullName.Length == 0)
+            {
+                throw new ArgumentException("The path must be a non-empty string.", "folder");
+            }
+
+            return Factory.New<IRuntimeFileInfo>(folder.FullName.NormalizeFolderPath());
+        }
+
+        public static bool IsEncrypted(this IRuntimeFileInfo fullName)
+        {
+            return String.Compare(Instance.Portable.Path().GetExtension(fullName.FullName), OS.Current.AxCryptExtension, StringComparison.OrdinalIgnoreCase) == 0;
+        }
+
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Encryptable", Justification = "Encryptable is a word.")]
+        public static IEnumerable<IRuntimeFileInfo> ListEncryptable(this IRuntimeFileInfo folderPath)
+        {
+            return folderPath.Files.Where((IRuntimeFileInfo fileInfo) => { return fileInfo.IsEncryptable(); });
+        }
+
+        public static IEnumerable<IRuntimeFileInfo> ListEncrypted(this IRuntimeFileInfo folderPath)
+        {
+            return folderPath.Files.Where((IRuntimeFileInfo fileInfo) => { return fileInfo.IsEncrypted(); });
+        }
+
+        /// <summary>
+        /// Create a file name based on an existing, but convert the file name to the pattern used by
+        /// AxCrypt for encrypted files. The original must not already be in that form.
+        /// </summary>
+        /// <param name="fileInfo">A file name representing a file that is not encrypted</param>
+        /// <returns>A corresponding file name representing the encrypted version of the original</returns>
+        /// <exception cref="InternalErrorException">Can't get encrypted name for a file that already has the encrypted extension.</exception>
+        public static IRuntimeFileInfo CreateEncryptedName(this IRuntimeFileInfo fullName)
+        {
+            if (fullName.IsEncrypted())
+            {
+                throw new InternalErrorException("Can't get encrypted name for a file that cannot be encrypted.");
+            }
+
+            string encryptedName = fullName.FullName.CreateEncryptedName();
+            return Factory.New<IRuntimeFileInfo>(encryptedName);
+        }
+
+        /// <summary>
+        /// Creates a random unique unique name in the same folder.
+        /// </summary>
+        /// <param name="fileInfo">The file information representing the new unique random name.</param>
+        /// <returns></returns>
+        public static IRuntimeFileInfo CreateRandomUniqueName(this IRuntimeFileInfo fileInfo)
+        {
+            while (true)
+            {
+                int r = Math.Abs(BitConverter.ToInt32(Instance.RandomGenerator.Generate(sizeof(int)), 0));
+                string alternatePath = Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(fileInfo.FullName), r.ToString(CultureInfo.InvariantCulture) + Instance.Portable.Path().GetExtension(fileInfo.FullName));
+                IRuntimeFileInfo alternateFileInfo = Factory.New<IRuntimeFileInfo>(alternatePath);
+                if (!alternateFileInfo.IsExistingFile && !alternateFileInfo.IsExistingFolder)
+                {
+                    return alternateFileInfo;
+                }
+            }
+        }
+
+        public static Passphrase TryFindPassphrase(this IRuntimeFileInfo fileInfo, out Guid cryptoId)
+        {
+            cryptoId = Guid.Empty;
+            if (!fileInfo.IsEncrypted())
+            {
+                return null;
+            }
+
+            foreach (Passphrase knownKey in Instance.KnownKeys.Keys)
+            {
+                cryptoId = Factory.New<AxCryptFactory>().TryFindCryptoId(knownKey, fileInfo, Instance.CryptoFactory.OrderedIds);
+                if (cryptoId != Guid.Empty)
+                {
+                    return knownKey;
+                }
+            }
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/StreamExtensions.cs b/Axantum.AxCrypt.Core/Extensions/StreamExtensions.cs
new file mode 100644
index 0000000..ec8a8a3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/StreamExtensions.cs
@@ -0,0 +1,153 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using Org.BouncyCastle.Utilities.Zlib;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class StreamExtensions
+    {
+        public static void CopyTo(this Stream source, Stream destination, int bufferSize)
+        {
+            if (source == null)
+            {
+                throw new ArgumentNullException("destination");
+            }
+            if (destination == null)
+            {
+                throw new ArgumentNullException("destination");
+            }
+            if (bufferSize <= 0)
+            {
+                throw new ArgumentOutOfRangeException("bufferSize", "Buffer size must be greater than zero.");
+            }
+
+            byte[] buffer = new byte[bufferSize];
+            int read;
+            while ((read = source.Read(buffer, 0, buffer.Length)) != 0)
+            {
+                destination.Write(buffer, 0, read);
+            }
+        }
+
+        public static long CopyTo(this Stream inputStream, Stream outputStream)
+        {
+            long totalDone = 0;
+            byte[] buffer = new byte[OS.Current.StreamBufferSize];
+            int bufferWrittenCount = 0;
+            int bufferRemainingCount = buffer.Length;
+            while (true)
+            {
+                int readCount = inputStream.Read(buffer, bufferWrittenCount, bufferRemainingCount);
+                bufferWrittenCount += readCount;
+                bufferRemainingCount -= readCount;
+                if (bufferRemainingCount > 0 && readCount > 0)
+                {
+                    continue;
+                }
+                if (bufferWrittenCount == 0)
+                {
+                    break;
+                }
+                outputStream.Write(buffer, 0, bufferWrittenCount);
+                outputStream.Flush();
+                totalDone += bufferWrittenCount;
+                bufferWrittenCount = 0;
+                bufferRemainingCount = buffer.Length;
+            }
+            return totalDone;
+        }
+
+        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
+        public static void DecryptTo(this Stream encryptedInputStream, Stream plaintextOutputStream, ICryptoTransform transform, bool isCompressed)
+        {
+            Exception savedExceptionIfCloseCausesException = null;
+            try
+            {
+                if (encryptedInputStream == null)
+                {
+                    throw new ArgumentNullException("encryptedInputStream");
+                }
+                if (plaintextOutputStream == null)
+                {
+                    throw new ArgumentNullException("plaintextOutputStream");
+                }
+                if (transform == null)
+                {
+                    throw new ArgumentNullException("transform");
+                }
+
+                if (isCompressed)
+                {
+                    using (Stream deflatedPlaintextStream = Instance.Portable.CryptoStream(encryptedInputStream, transform, CryptoStreamMode.Read))
+                    {
+                        using (Stream inflatedPlaintextStream = new ZInputStream(deflatedPlaintextStream))
+                        {
+                            try
+                            {
+                                inflatedPlaintextStream.CopyTo(plaintextOutputStream);
+                            }
+                            catch (Exception ex)
+                            {
+                                savedExceptionIfCloseCausesException = ex;
+                                throw;
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    using (Stream plainStream = Instance.Portable.CryptoStream(encryptedInputStream, transform, CryptoStreamMode.Read))
+                    {
+                        try
+                        {
+                            plainStream.CopyTo(plaintextOutputStream);
+                        }
+                        catch (Exception ex)
+                        {
+                            savedExceptionIfCloseCausesException = ex;
+                            throw;
+                        }
+                    }
+                }
+            }
+            catch (Exception)
+            {
+                if (savedExceptionIfCloseCausesException != null)
+                {
+                    throw savedExceptionIfCloseCausesException;
+                }
+                throw;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Extensions/StringExtensions.cs b/Axantum.AxCrypt.Core/Extensions/StringExtensions.cs
new file mode 100644
index 0000000..65f614f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Extensions/StringExtensions.cs
@@ -0,0 +1,215 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Extensions
+{
+    public static class StringExtensions
+    {
+        /// <summary>
+        /// Extension for String.Format using InvariantCulture
+        /// </summary>
+        /// <param name="format"></param>
+        /// <param name="parameters"></param>
+        /// <returns></returns>
+        public static string InvariantFormat(this string format, params object[] parameters)
+        {
+            string formatted = String.Format(CultureInfo.InvariantCulture, format, parameters);
+            return formatted;
+        }
+
+        /// <summary>
+        /// Convenience extension for String.Format using the provided CultureInfo
+        /// </summary>
+        /// <param name="format"></param>
+        /// <param name="cultureInfo"></param>
+        /// <param name="parameters"></param>
+        /// <returns></returns>
+        public static string FormatWith(this string format, CultureInfo cultureInfo, params object[] parameters)
+        {
+            string formatted = String.Format(cultureInfo, format, parameters);
+            return formatted;
+        }
+
+        /// <summary>
+        /// Create a file name based on an existing, but convert the file name to the pattern used by
+        /// AxCrypt for encrypted files. The original must not already be in that form.
+        /// </summary>
+        /// <param name="fileInfo">A file name representing a file that is not encrypted</param>
+        /// <returns>A corresponding file name representing the encrypted version of the original</returns>
+        public static string CreateEncryptedName(this string fullName)
+        {
+            string extension = Instance.Portable.Path().GetExtension(fullName);
+            string encryptedName = fullName;
+            encryptedName = encryptedName.Substring(0, encryptedName.Length - extension.Length);
+            encryptedName += extension.Replace('.', '-');
+            encryptedName += OS.Current.AxCryptExtension;
+
+            return encryptedName;
+        }
+
+        public static string CreateUniqueFile(this string fullName)
+        {
+            IRuntimeFileInfo pathInfo = Factory.New<IRuntimeFileInfo>(fullName);
+            string extension = Instance.Portable.Path().GetExtension(fullName);
+            int version = 0;
+            while (true)
+            {
+                try
+                {
+                    string alternateExtension = (version > 0 ? "." + version.ToString(CultureInfo.InvariantCulture) : String.Empty) + extension;
+                    string alternatePath = Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(pathInfo.FullName), Instance.Portable.Path().GetFileNameWithoutExtension(pathInfo.Name) + alternateExtension);
+                    IRuntimeFileInfo alternateFileInfo = Factory.New<IRuntimeFileInfo>(alternatePath);
+                    alternateFileInfo.CreateNewFile();
+                    return alternateFileInfo.FullName;
+                }
+                catch (AxCryptException ace)
+                {
+                    if (ace.ErrorStatus != ErrorStatus.FileExists)
+                    {
+                        throw;
+                    }
+                }
+                ++version;
+            }
+        }
+
+        /// <summary>
+        /// Trim a log message from extra information in front, specifically text preceding the
+        /// log level text such as Information, Warning etc. There must be a space preceding
+        /// the log level text. Recognized texts are 'Information', 'Warning', 'Debug', 'Error'
+        /// and 'Fatal'.
+        /// </summary>
+        /// <param name="message">A log message</param>
+        /// <returns>A possible trimmed message</returns>
+        /// <remarks>
+        /// This is primarily intended to facilitate more compact logging in a GUI
+        /// </remarks>
+        public static string TrimLogMessage(this string message)
+        {
+            int skipIndex = message.IndexOf(" Information", StringComparison.Ordinal);
+            skipIndex = skipIndex < 0 ? message.IndexOf(" Warning", StringComparison.Ordinal) : skipIndex;
+            skipIndex = skipIndex < 0 ? message.IndexOf(" Debug", StringComparison.Ordinal) : skipIndex;
+            skipIndex = skipIndex < 0 ? message.IndexOf(" Error", StringComparison.Ordinal) : skipIndex;
+            skipIndex = skipIndex < 0 ? message.IndexOf(" Fatal", StringComparison.Ordinal) : skipIndex;
+
+            return message.Substring(skipIndex + 1);
+        }
+
+        public static string FolderFromEnvironment(this string name)
+        {
+            if (name == null)
+            {
+                throw new ArgumentNullException("name");
+            }
+
+            string value = OS.Current.EnvironmentVariable(name);
+            if (String.IsNullOrEmpty(value))
+            {
+                return String.Empty;
+            }
+
+            value = value.Replace(Instance.Portable.Path().DirectorySeparatorChar == '/' ? '\\' : '/', Instance.Portable.Path().DirectorySeparatorChar);
+            return Factory.New<IRuntimeFileInfo>(value).NormalizeFolder().FullName;
+        }
+
+        public static string NormalizeFilePath(this string filePath)
+        {
+            filePath = filePath.Replace(Instance.Portable.Path().DirectorySeparatorChar == '/' ? '\\' : '/', Instance.Portable.Path().DirectorySeparatorChar);
+            return filePath;
+        }
+
+        public static string NormalizeFolderPath(this string folder)
+        {
+            folder = folder.NormalizeFilePath();
+            if (String.Compare(folder, Instance.Portable.Path().GetPathRoot(folder), StringComparison.OrdinalIgnoreCase) == 0)
+            {
+                return folder;
+            }
+            int directorySeparatorChars = 0;
+            while (folder.Length - (directorySeparatorChars + 1) > 0 && folder[folder.Length - (directorySeparatorChars + 1)] == Instance.Portable.Path().DirectorySeparatorChar)
+            {
+                ++directorySeparatorChars;
+            }
+
+            if (directorySeparatorChars == 0)
+            {
+                return folder + Instance.Portable.Path().DirectorySeparatorChar;
+            }
+            return folder.Substring(0, folder.Length - (directorySeparatorChars - 1));
+        }
+
+        public static byte[] FromHex(this string hex)
+        {
+            if (hex == null)
+            {
+                throw new ArgumentNullException("hex");
+            }
+            hex = hex.Replace(" ", String.Empty).Replace("\r", String.Empty).Replace("\n", String.Empty);
+            if (hex.Length % 2 != 0)
+            {
+                throw new ArgumentException("Odd number of characters is not allowed in a hex string.");
+            }
+
+            byte[] bytes = new byte[hex.Length / 2];
+            for (int i = 0; i < bytes.Length; ++i)
+            {
+                bytes[i] = Byte.Parse(hex.Substring(i + i, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
+            }
+            return bytes;
+        }
+
+        public static bool IsValidEmailOrEmpty(this string email)
+        {
+            if (String.IsNullOrEmpty(email))
+            {
+                return true;
+            }
+            return email.IsValidEmail();
+        }
+
+        public static bool IsValidEmail(this string email)
+        {
+            try
+            {
+                new EmailAddress(email);
+                return true;
+            }
+            catch (FormatException)
+            {
+                return false;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Factory.cs b/Axantum.AxCrypt.Core/Factory.cs
new file mode 100644
index 0000000..4570b93
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Factory.cs
@@ -0,0 +1,247 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    /// <summary>
+    /// Map a type to a class factory creating instances of that type. This is used as a simple dependency injection vehicle
+    /// for types that this library depends on external implementations of for flexibility or unit testing purposes.
+    /// </summary>
+    public class Factory
+    {
+        private class Creator<T>
+        {
+            public Func<T> CreateFunc { get; set; }
+
+            public Action PostAction { get; set; }
+
+            public Creator(Func<T> creator, Action postAction)
+            {
+                CreateFunc = creator;
+                PostAction = postAction;
+            }
+        }
+
+        private Dictionary<Type, object> _mapping = new Dictionary<Type, object>();
+
+        private Factory()
+        {
+        }
+
+        private static Factory _instance = new Factory();
+
+        /// <summary>
+        /// Gets the singleton instance of the Factory
+        /// </summary>
+        /// <value>
+        /// The instance. There can be only one.
+        /// </value>
+        public static Factory Instance
+        {
+            get
+            {
+                return _instance;
+            }
+        }
+
+        /// <summary>
+        /// Register a method that creates an instance of the given type. A second registration of the same type
+        /// overwrites the first.
+        /// </summary>
+        /// <typeparam name="TResult">The type to register a factory for.</typeparam>
+        /// <param name="creator">The delegate that creates an instance.</param>
+        public void Register<TResult>(Func<TResult> creator)
+        {
+            SetAndDisposeIfDisposable(typeof(TResult), creator);
+        }
+
+        /// <summary>
+        /// Register a method that creates an instance of the given type, taking a single argument.
+        /// A second registration of the same type overwrites the first.
+        /// </summary>
+        /// <typeparam name="TResult">The type to register a factory for.</typeparam>
+        /// <param name="creator">The Func<TArg, TResult> delegate that creates an instance.</param>
+        public void Register<TArgument, TResult>(Func<TArgument, TResult> creator)
+        {
+            SetAndDisposeIfDisposable(typeof(TResult), creator);
+        }
+
+        /// <summary>
+        /// Register a method that creates a singleton instance of the given type. This is lazy-evaluated at the first
+        /// request to resolve the type.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the singleton instance.</typeparam>
+        /// <param name="creator">The method delegate that creates the singleton.</param>
+        public void Singleton<TResult>(Func<TResult> creator)
+        {
+            Singleton(creator, () => { });
+        }
+
+        /// <summary>
+        /// Register a method that creates a singleton instance of the given type, and an Action delegate to
+        /// execute after creating the instance. Use this to ensure correct dependency ordering.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the singleton instance.</typeparam>
+        /// <param name="creator">The method delegate that creates the singleton.</param>
+        /// <param name="postAction">The method delegate to execute after creating the singleton.</param>
+        public void Singleton<TResult>(Func<TResult> creator, Action postAction)
+        {
+            SetAndDisposeIfDisposable(typeof(TResult), new Creator<TResult>(creator, postAction));
+        }
+
+        private void SetAndDisposeIfDisposable(Type type, object value)
+        {
+            object o;
+            if (_mapping.TryGetValue(type, out o))
+            {
+                DisposeIfDisposable(o);
+            }
+            _mapping[type] = value;
+        }
+
+        /// <summary>
+        /// Resolve a singleton instance of the given type. The method delegate registered to provide the instance is
+        /// only called once, on the first call.
+        /// </summary>
+        /// <typeparam name="TResult">The type of the singleton to resolve.</typeparam>
+        /// <returns>A singleton instance of the given type.</returns>
+        public TResult Singleton<TResult>() where TResult : class
+        {
+            object o;
+            if (!_mapping.TryGetValue(typeof(TResult), out o))
+            {
+                throw new ArgumentException("Unregistered singleton. Initialize with 'FactoryRegistry.Singleton<{0}>(() => {{ return new {0}(); }});'".InvariantFormat(typeof(TResult)));
+            }
+
+            TResult value = o as TResult;
+            if (value != null)
+            {
+                return value;
+            }
+
+            Creator<TResult> creator = (Creator<TResult>)o;
+            value = creator.CreateFunc();
+            _mapping[typeof(TResult)] = value;
+
+            creator.PostAction();
+            return value;
+        }
+
+        /// <summary>
+        /// Create an instance of a registered type.
+        /// </summary>
+        /// <typeparam name="TResult">The type to create an instance of.</typeparam>
+        /// <returns>An instance of the type, according to the rules of the factory. It may be a singleton.</returns>
+        public static TResult New<TResult>()
+        {
+            return Instance.CreateInternal<TResult>();
+        }
+
+        /// <summary>
+        /// Create an instance of a registered type.
+        /// </summary>
+        /// <typeparam name="TResult">The type to create an instance of.</typeparam>
+        /// <param name="argument">The argument to the constructor.</param>
+        /// <returns>
+        /// An instance of the type, according to the rules of the factory. It may be a singleton.
+        /// </returns>
+        public static TResult New<TResult>(string argument)
+        {
+            return Instance.CreateInternal<string, TResult>(argument);
+        }
+
+        /// <summary>
+        /// Create an instance of a registered type with an argument to the constructor.
+        /// </summary>
+        /// <typeparam name="TArgument">The type of the argument to the constructor.</typeparam>
+        /// <typeparam name="TResult">The type to create an instance of.</typeparam>
+        /// <param name="argument">The argument.</param>
+        /// <returns>An instance of the type, according to the rules of the factory. It may be a singleton.</returns>
+        public static TResult New<TArgument, TResult>(TArgument argument)
+        {
+            return Instance.CreateInternal<TArgument, TResult>(argument);
+        }
+
+        private TResult CreateInternal<TResult>()
+        {
+            Func<TResult> function = GetTypeFactory<TResult>();
+            return function();
+        }
+
+        private TResult CreateInternal<TArgument, TResult>(TArgument argument)
+        {
+            Func<TArgument, TResult> function = GetTypeFactory<TArgument, TResult>();
+            return function(argument);
+        }
+
+        private Func<TResult> GetTypeFactory<TResult>()
+        {
+            object function;
+            if (!_mapping.TryGetValue(typeof(TResult), out function))
+            {
+                throw new ArgumentException("Unregistered type factory. Initialize with 'Factory.Instance.Register<{0}>(() => {{ return new {0}(); }});'".InvariantFormat(typeof(TResult)));
+            }
+            return (Func<TResult>)function;
+        }
+
+        private Func<TArgument, TResult> GetTypeFactory<TArgument, TResult>()
+        {
+            object function;
+            if (!_mapping.TryGetValue(typeof(TResult), out function))
+            {
+                throw new ArgumentException("Unregistered type factory. Initialize with 'Factory.Instance.Register<{0}, {1}>((argument) => {{ return new {0}(argument); }});'".InvariantFormat(typeof(TArgument), typeof(TResult)));
+            }
+            return (Func<TArgument, TResult>)function;
+        }
+
+        /// <summary>
+        /// Unregister all factories and instances, dispose if required.
+        /// </summary>
+        public void Clear()
+        {
+            foreach (object o in _mapping.Values)
+            {
+                DisposeIfDisposable(o);
+            }
+            _mapping.Clear();
+        }
+
+        private static void DisposeIfDisposable(object o)
+        {
+            IDisposable disposable = o as IDisposable;
+            if (disposable != null)
+            {
+                disposable.Dispose();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/AxCrypt1Guid.cs b/Axantum.AxCrypt.Core/Header/AxCrypt1Guid.cs
new file mode 100644
index 0000000..9a1514a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/AxCrypt1Guid.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public static class AxCrypt1Guid
+    {
+        // c0b9072e4f93f146a015792ca1d9e821
+        public static readonly Guid Value = new Guid("2e07b9c0-934f-46f1-a015-792ca1d9e821");
+
+        private static readonly byte[] _axCrypt1GuidBytes = Value.ToByteArray();
+
+        public static byte[] GetBytes()
+        {
+            return (byte[])_axCrypt1GuidBytes.Clone();
+        }
+
+        public static void Write(Stream stream)
+        {
+            stream.Write(_axCrypt1GuidBytes, 0, _axCrypt1GuidBytes.Length);
+        }
+
+        public static int Length
+        {
+            get { return _axCrypt1GuidBytes.Length; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/DataHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/DataHeaderBlock.cs
new file mode 100644
index 0000000..e7e3b72
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/DataHeaderBlock.cs
@@ -0,0 +1,63 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class DataHeaderBlock : HeaderBlock
+    {
+        public DataHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.Data, dataBlock)
+        {
+        }
+
+        public DataHeaderBlock()
+            : this(new byte[8])
+        {
+        }
+
+        public override object Clone()
+        {
+            DataHeaderBlock block = new DataHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public long CipherTextLength
+        {
+            get
+            {
+                return GetDataBlockBytesReference().GetLittleEndianValue(0, sizeof(long));
+            }
+
+            set
+            {
+                value.GetLittleEndianBytes().CopyTo(GetDataBlockBytesReference(), 0);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/EncryptedDataPartBlock.cs b/Axantum.AxCrypt.Core/Header/EncryptedDataPartBlock.cs
new file mode 100644
index 0000000..d412f73
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/EncryptedDataPartBlock.cs
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class EncryptedDataPartBlock : HeaderBlock
+    {
+        public EncryptedDataPartBlock(byte[] dataBlock)
+            : base(HeaderBlockType.EncryptedDataPart, dataBlock)
+        {
+        }
+
+        public override object Clone()
+        {
+            EncryptedDataPartBlock block = new EncryptedDataPartBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/EncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/EncryptedHeaderBlock.cs
new file mode 100644
index 0000000..06cc656
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/EncryptedHeaderBlock.cs
@@ -0,0 +1,47 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public abstract class EncryptedHeaderBlock : HeaderBlock
+    {
+        public ICrypto HeaderCrypto { get; set; }
+
+        protected EncryptedHeaderBlock(HeaderBlockType headerBlockType, byte[] dataBlock)
+            : base(headerBlockType, dataBlock)
+        {
+        }
+
+        protected object CopyTo(EncryptedHeaderBlock headerBlock)
+        {
+            headerBlock.HeaderCrypto = HeaderCrypto;
+            return headerBlock;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/FileInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/FileInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..c19970a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/FileInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,154 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class FileInfoEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        private const int CreationTimeOffset = 0;
+        private const int LastAccessTimeOffset = 8;
+        private const int LastWriteTimeOffset = 16;
+        private static readonly long WindowsTimeTicksStart = new DateTime(1601, 1, 1).Ticks;
+
+        public FileInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.FileInfo, dataBlock)
+        {
+        }
+
+        public FileInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[0])
+        {
+            HeaderCrypto = headerCrypto;
+        }
+
+        private void EnsureDataBlock()
+        {
+            if (GetDataBlockBytesReference().Length > 0)
+            {
+                return;
+            }
+            byte[] timeBytes = GetTimeStampBytes(OS.Current.UtcNow);
+
+            byte[] rawData = new byte[32];
+            Array.Copy(timeBytes, 0, rawData, CreationTimeOffset, timeBytes.Length);
+            Array.Copy(timeBytes, 0, rawData, LastAccessTimeOffset, timeBytes.Length);
+            Array.Copy(timeBytes, 0, rawData, LastWriteTimeOffset, timeBytes.Length);
+
+            SetDataBlockBytesReference(HeaderCrypto.Encrypt(rawData));
+        }
+
+        public override object Clone()
+        {
+            FileInfoEncryptedHeaderBlock block = new FileInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get
+            {
+                DateTime creationTime = GetTimeStamp(CreationTimeOffset);
+                return creationTime;
+            }
+            set
+            {
+                SetTimeStamp(value, CreationTimeOffset);
+            }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get
+            {
+                DateTime lastAccessTime = GetTimeStamp(LastAccessTimeOffset);
+                return lastAccessTime;
+            }
+            set
+            {
+                SetTimeStamp(value, LastAccessTimeOffset);
+            }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get
+            {
+                DateTime lastWriteTime = GetTimeStamp(LastWriteTimeOffset);
+                return lastWriteTime;
+            }
+            set
+            {
+                SetTimeStamp(value, LastWriteTimeOffset);
+            }
+        }
+
+        private DateTime GetTimeStamp(int timeOffset)
+        {
+            EnsureDataBlock();
+            byte[] rawFileTimes = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+            uint lowDateTime = (uint)rawFileTimes.GetLittleEndianValue(timeOffset, 4);
+            uint hiDateTime = (uint)rawFileTimes.GetLittleEndianValue(timeOffset + 4, 4);
+            long filetime = ((long)hiDateTime << 32) | lowDateTime;
+
+            DateTime timeStampUtc = new DateTime(WindowsTimeTicksStart + filetime, DateTimeKind.Utc);
+            return timeStampUtc;
+        }
+
+        private void SetTimeStamp(DateTime dateTime, int timeOffset)
+        {
+            EnsureDataBlock();
+            byte[] timeStampBytes = GetTimeStampBytes(dateTime);
+            byte[] rawFileTimes = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+            Array.Copy(timeStampBytes, 0, rawFileTimes, timeOffset, timeStampBytes.Length);
+            SetDataBlockBytesReference(HeaderCrypto.Encrypt(rawFileTimes));
+        }
+
+        private static byte[] GetTimeStampBytes(DateTime dateTime)
+        {
+            if (dateTime.Kind != DateTimeKind.Utc)
+            {
+                dateTime = dateTime.ToUniversalTime();
+            }
+
+            long filetime = dateTime.Ticks - WindowsTimeTicksStart;
+            long lowDateTime = filetime & 0xffffffff;
+            long hiDateTime = (filetime >> 32) & 0xffffffff;
+            byte[] lowDateTimeBytes = lowDateTime.GetLittleEndianBytes();
+            byte[] hiDateTimeBytes = hiDateTime.GetLittleEndianBytes();
+
+            byte[] timeStampBytes = new byte[sizeof(long)];
+            Array.Copy(lowDateTimeBytes, 0, timeStampBytes, 0, sizeof(uint));
+            Array.Copy(hiDateTimeBytes, 0, timeStampBytes, sizeof(uint), sizeof(uint));
+
+            return timeStampBytes;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/HeaderBlock.cs b/Axantum.AxCrypt.Core/Header/HeaderBlock.cs
new file mode 100644
index 0000000..c5c9a2a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/HeaderBlock.cs
@@ -0,0 +1,150 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public abstract class HeaderBlock : ICloneable, IEquatable<HeaderBlock>
+    {
+        private byte[] _dataBlock;
+
+        protected HeaderBlock(HeaderBlockType headerBlockType, byte[] dataBlock)
+        {
+            HeaderBlockType = headerBlockType;
+            _dataBlock = dataBlock;
+        }
+
+        protected HeaderBlock(HeaderBlockType headerBlockType)
+        {
+            HeaderBlockType = headerBlockType;
+        }
+
+        public HeaderBlockType HeaderBlockType { get; protected set; }
+
+        /// <summary>
+        /// Get a reference to the internally maintained data block. Beware modifying the contents of the array!
+        /// </summary>
+        /// <returns></returns>
+        protected byte[] GetDataBlockBytesReference()
+        {
+            return _dataBlock;
+        }
+
+        /// <summary>
+        /// Get a copy of the raw data block.
+        /// </summary>
+        /// <returns>Returns a cloned copy of the data block.</returns>
+        public byte[] GetDataBlockBytes()
+        {
+            return (byte[])GetDataBlockBytesReference().Clone();
+        }
+
+        /// <summary>
+        /// Set a reference to the internally maintained data block. Beware modifying the contents of the array!
+        /// </summary>
+        /// <param name="dataBlock"></param>
+        protected void SetDataBlockBytesReference(byte[] dataBlock)
+        {
+            _dataBlock = dataBlock;
+        }
+
+        protected byte[] GetPrefixBytes()
+        {
+            byte[] headerBlockPrefix = new byte[4 + 1];
+            BitConverter.GetBytes(headerBlockPrefix.Length + _dataBlock.Length).CopyTo(headerBlockPrefix, 0);
+            headerBlockPrefix[4] = (byte)HeaderBlockType;
+
+            return headerBlockPrefix;
+        }
+
+        protected void WritePrefix(Stream stream)
+        {
+            byte[] headerPrefixBytes = GetPrefixBytes();
+            stream.Write(headerPrefixBytes, 0, headerPrefixBytes.Length);
+        }
+
+        public virtual void Write(Stream stream)
+        {
+            WritePrefix(stream);
+            stream.Write(_dataBlock, 0, _dataBlock.Length);
+        }
+
+        public abstract object Clone();
+
+        public bool Equals(HeaderBlock other)
+        {
+            if (other == null)
+            {
+                return false;
+            }
+            return HeaderBlockType == other.HeaderBlockType && GetDataBlockBytesReference().IsEquivalentTo(other.GetDataBlockBytesReference());
+        }
+
+        public override bool Equals(object obj)
+        {
+            HeaderBlock other = obj as HeaderBlock;
+            if (other == null)
+            {
+                return false;
+            }
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            int hashcode = (int)HeaderBlockType;
+            foreach (byte b in GetDataBlockBytesReference())
+            {
+                hashcode += b;
+            }
+            return hashcode;
+        }
+
+        public static bool operator ==(HeaderBlock left, HeaderBlock right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if ((object)left == null)
+            {
+                return false;
+            }
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(HeaderBlock left, HeaderBlock right)
+        {
+            return !(left == right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/HeaderBlockType.cs b/Axantum.AxCrypt.Core/Header/HeaderBlockType.cs
new file mode 100644
index 0000000..eee5a9c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/HeaderBlockType.cs
@@ -0,0 +1,151 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public enum HeaderBlockType
+    {
+        /// <summary>
+        /// Matches no type.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// Matches any type.
+        /// </summary>
+        Any = 1,
+
+        /// <summary>
+        /// Must be first.
+        /// </summary>
+        Preamble = 2,
+
+        /// <summary>
+        /// Version information etc.
+        /// </summary>
+        Version = 3,
+
+        /// <summary>
+        /// A 128-bit Data Enc Key and IV wrapped with 128-bit KEK
+        /// </summary>
+        KeyWrap1 = 4,
+
+        /// <summary>
+        /// Some other kind of KEK, DEK, IV scheme... Future use.
+        /// </summary>
+        KeyWrap2 = 5,
+
+        /// <summary>
+        /// An arbitrary string encoded as Ansi Code Page 1252 defined by the caller.
+        /// </summary>
+        IdTag = 6,
+
+        /// <summary>
+        /// HMAC-SHA-512 and end of file marker. Key stream index 0 generates the key.
+        /// </summary>
+        V2Hmac = 11,
+
+        /// <summary>
+        /// NIST Key Wrap Algorithm wrap of the Master Data Encrypting Key, IV, Derviation Salt & Iterations etc.
+        /// </summary>
+        V2KeyWrap = 13,
+
+        /// <summary>
+        /// A RSA OAEP encryption of the Master Data Encrypting Key and IV
+        /// </summary>
+        V2AsymmetricKeyWrap = 14,
+
+        /// <summary>
+        /// A block of encrypted data in the data stream.
+        /// </summary>
+        /// <remarks>
+        /// Technically it's encrypted, but it's not an encrypted header, therefore it's not classified as such.
+        /// </remarks>
+        EncryptedDataPart = 20,
+
+        /// <summary>
+        /// The code should accept and skip header block types that are defined later. This is here to simulate that
+        /// condition for tests.
+        /// </summary>
+        Unrecognized = 61,
+
+        /// <summary>
+        /// An undefined header block type, used for tests
+        /// </summary>
+        Undefined = 62,
+
+        /// <summary>
+        /// The data, compressed and/or encrypted.
+        /// </summary>
+        Data = 63,
+
+        /// <summary>
+        /// Start of headers containing encrypted header data
+        /// </summary>
+        Encrypted = 64,
+
+        /// <summary>
+        /// Original file name
+        /// </summary>
+        FileNameInfo = 65,
+
+        /// <summary>
+        /// Sizes of the original data file before encryption
+        /// </summary>
+        EncryptionInfo = 66,
+
+        /// <summary>
+        /// Indicates that the data is compressed and the sizes.
+        /// </summary>
+        CompressionInfo = 67,
+
+        /// <summary>
+        /// Time stamps and size of the original file
+        /// </summary>
+        FileInfo = 68,
+
+        /// <summary>
+        /// Indicates if the data is compressed. 1.2.2.
+        /// </summary>
+        Compression = 69,
+
+        /// <summary>
+        /// Original file name in Unicode. 1.6.3.3
+        /// </summary>
+        UnicodeFileNameInfo = 70,
+
+        /// <summary>
+        /// 2.x - Lengths in the trailer
+        /// </summary>
+        PlaintextLengths = 101,
+
+        /// <summary>
+        /// 2.x - Json-encoded array of e-mail adresses representing key sharing recipients.
+        /// </summary>
+        AsymmetricRecipients = 102,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/Headers.cs b/Axantum.AxCrypt.Core/Header/Headers.cs
new file mode 100644
index 0000000..36364a4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/Headers.cs
@@ -0,0 +1,204 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class Headers
+    {
+        public IList<HeaderBlock> HeaderBlocks { get; private set; }
+
+        public IList<HeaderBlock> TrailerBlocks { get; private set; }
+
+        public Headers()
+        {
+            HeaderBlocks = new List<HeaderBlock>();
+            TrailerBlocks = new List<HeaderBlock>();
+        }
+
+        public AxCryptReader Load(Stream inputStream)
+        {
+            inputStream = new LookAheadStream(inputStream);
+
+            IList<HeaderBlock> headers = LoadUnversionedHeaders(inputStream);
+            AxCryptReader reader = CreateVersionedReader(inputStream, headers);
+            reader.Reinterpret(headers, HeaderBlocks);
+
+            return reader;
+        }
+
+        public void Load(AxCryptReader reader)
+        {
+            HeaderBlocks = LoadFromReader(reader);
+        }
+
+        private static IList<HeaderBlock> LoadUnversionedHeaders(Stream inputStream)
+        {
+            using (VXAxCryptReader vxReader = new VXAxCryptReader(inputStream))
+            {
+                return LoadFromReader(vxReader);
+            }
+        }
+
+        private static IList<HeaderBlock> LoadFromReader(AxCryptReader vxReader)
+        {
+            List<HeaderBlock> headers = new List<HeaderBlock>();
+            vxReader.Read();
+            if (vxReader.CurrentItemType != AxCryptItemType.MagicGuid)
+            {
+                throw new FileFormatException("No magic Guid was found.", ErrorStatus.MagicGuidMissing);
+            }
+
+            ReadHeadersToLast(headers, vxReader, HeaderBlockType.Data);
+            return headers;
+        }
+
+        private static AxCryptReader CreateVersionedReader(Stream inputStream, IList<HeaderBlock> headers)
+        {
+            AxCryptReader reader;
+            VersionHeaderBlock versionHeaderBlock = FindHeaderBlock<VersionHeaderBlock>(headers);
+            switch (versionHeaderBlock.FileVersionMajor)
+            {
+                case 1:
+                case 2:
+                case 3:
+                    reader = new V1AxCryptReader(inputStream);
+                    break;
+
+                case 4:
+                    reader = new V2AxCryptReader(inputStream);
+                    break;
+
+                default:
+                    throw new FileFormatException("Too new file format. You need a more recent version.");
+            }
+            return reader;
+        }
+
+        public void Trailers(AxCryptReader reader)
+        {
+            TrailerBlocks.Add(reader.CurrentHeaderBlock);
+            ReadHeadersToLast(TrailerBlocks, reader, HeaderBlockType.V2Hmac);
+        }
+
+        private static void ReadHeadersToLast(IList<HeaderBlock> headerBlocks, AxCryptReader axCryptReader, HeaderBlockType last)
+        {
+            while (axCryptReader.Read())
+            {
+                switch (axCryptReader.CurrentItemType)
+                {
+                    case AxCryptItemType.Data:
+                    case AxCryptItemType.HeaderBlock:
+                        break;
+
+                    default:
+                        throw new InternalErrorException("The reader returned an AxCryptItemType it should not be possible for it to return.");
+                }
+
+                headerBlocks.Add(axCryptReader.CurrentHeaderBlock);
+
+                if (axCryptReader.CurrentHeaderBlock.HeaderBlockType == last)
+                {
+                    return;
+                }
+            }
+            throw new FileFormatException("Premature end of stream.", ErrorStatus.EndOfStream);
+        }
+
+        public VersionHeaderBlock VersionHeaderBlock
+        {
+            get
+            {
+                VersionHeaderBlock versionHeaderBlock = FindHeaderBlock<VersionHeaderBlock>();
+                return versionHeaderBlock;
+            }
+        }
+
+        public T FindHeaderBlock<T>() where T : HeaderBlock
+        {
+            return FindHeaderBlock<T>(HeaderBlocks);
+        }
+
+        public T FindTrailerBlock<T>() where T : HeaderBlock
+        {
+            return FindHeaderBlock<T>(TrailerBlocks);
+        }
+
+        private static T FindHeaderBlock<T>(IEnumerable<HeaderBlock> headerBlocks) where T : HeaderBlock
+        {
+            foreach (HeaderBlock headerBlock in headerBlocks)
+            {
+                T typedHeaderHeaderBlock = headerBlock as T;
+                if (typedHeaderHeaderBlock != null)
+                {
+                    return typedHeaderHeaderBlock;
+                }
+            }
+            return null;
+        }
+
+        public void EnsureFileFormatVersion(int lowestMajorVersion, int highestMajorVersion)
+        {
+            VersionHeaderBlock versionHeaderBlock = FindHeaderBlock<VersionHeaderBlock>();
+            if (versionHeaderBlock.FileVersionMajor > highestMajorVersion)
+            {
+                throw new FileFormatException("Too new file format.", ErrorStatus.TooNewFileFormatVersion);
+            }
+            if (versionHeaderBlock.FileVersionMajor < lowestMajorVersion)
+            {
+                throw new FileFormatException("Too old file format.", ErrorStatus.TooOldFileFormatVersion);
+            }
+        }
+
+        public Hmac Hmac
+        {
+            get
+            {
+                PreambleHeaderBlock headerBlock = FindHeaderBlock<PreambleHeaderBlock>();
+
+                return headerBlock.Hmac;
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+                PreambleHeaderBlock headerBlock = FindHeaderBlock<PreambleHeaderBlock>();
+                headerBlock.Hmac = value;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/PreambleHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/PreambleHeaderBlock.cs
new file mode 100644
index 0000000..785b1b8
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/PreambleHeaderBlock.cs
@@ -0,0 +1,67 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class PreambleHeaderBlock : HeaderBlock
+    {
+        public PreambleHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.Preamble, dataBlock)
+        {
+        }
+
+        public PreambleHeaderBlock()
+            : base(HeaderBlockType.Preamble, new byte[16])
+        {
+        }
+
+        public override object Clone()
+        {
+            PreambleHeaderBlock block = new PreambleHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public Hmac Hmac
+        {
+            get
+            {
+                return new V1Hmac(GetDataBlockBytesReference());
+            }
+            set
+            {
+                if (value == null)
+                {
+                    throw new ArgumentNullException("value");
+                }
+                SetDataBlockBytesReference(value.GetBytes());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/StringEncryptedHeaderBlockBase.cs b/Axantum.AxCrypt.Core/Header/StringEncryptedHeaderBlockBase.cs
new file mode 100644
index 0000000..1a4cbbd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/StringEncryptedHeaderBlockBase.cs
@@ -0,0 +1,52 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public abstract class StringEncryptedHeaderBlockBase : EncryptedHeaderBlock
+    {
+        protected StringEncryptedHeaderBlockBase(HeaderBlockType blockType, byte[] dataBlock)
+            : base(blockType, dataBlock)
+        {
+        }
+
+        protected StringEncryptedHeaderBlockBase(HeaderBlockType blockType, ICrypto headerCrypto)
+            : this(blockType, new byte[0])
+        {
+            HeaderCrypto = headerCrypto;
+        }
+
+        protected string StringValue
+        {
+            get
+            {
+                byte[] rawValue = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                int end = rawValue.Locate(new byte[] { 0, 0, }, 0, rawValue.Length, 1);
+                if (end == -1)
+                {
+                    throw new InvalidOperationException("Could not find terminating double nul byte in string value");
+                }
+
+                string stringValue = Encoding.UTF8.GetString(rawValue, 0, end);
+
+                return stringValue;
+            }
+
+            set
+            {
+                byte[] rawStringValue = Encoding.UTF8.GetBytes(value);
+                byte[] doubleNullTerminatedRawStringValue = new byte[rawStringValue.Length + 2];
+                rawStringValue.CopyTo(doubleNullTerminatedRawStringValue, 0);
+
+                byte[] dataBlock = Instance.RandomGenerator.Generate(doubleNullTerminatedRawStringValue.Length <= 256 ? 256 : doubleNullTerminatedRawStringValue.Length);
+                doubleNullTerminatedRawStringValue.CopyTo(dataBlock, 0);
+                SetDataBlockBytesReference(HeaderCrypto.Encrypt(dataBlock));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/UnrecognizedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/UnrecognizedHeaderBlock.cs
new file mode 100644
index 0000000..f21576e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/UnrecognizedHeaderBlock.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class UnrecognizedHeaderBlock : HeaderBlock
+    {
+        public UnrecognizedHeaderBlock(HeaderBlockType headerBlockType, byte[] dataBlock)
+            : base(headerBlockType, dataBlock)
+        {
+        }
+
+        public override object Clone()
+        {
+            UnrecognizedHeaderBlock block = new UnrecognizedHeaderBlock(HeaderBlockType, (byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1CompressionEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1CompressionEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..15ee225
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1CompressionEncryptedHeaderBlock.cs
@@ -0,0 +1,73 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1CompressionEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V1CompressionEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.Compression, dataBlock)
+        {
+        }
+
+        public V1CompressionEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[16])
+        {
+            HeaderCrypto = headerCrypto;
+            IsCompressed = false;
+        }
+
+        public override object Clone()
+        {
+            V1CompressionEncryptedHeaderBlock block = new V1CompressionEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public bool IsCompressed
+        {
+            get
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                Int32 isCompressed = (Int32)rawBlock.GetLittleEndianValue(0, sizeof(Int32));
+                return isCompressed != 0;
+            }
+
+            set
+            {
+                int isCompressed = value ? 1 : 0;
+                byte[] isCompressedBytes = isCompressed.GetLittleEndianBytes();
+                Array.Copy(isCompressedBytes, 0, GetDataBlockBytesReference(), 0, isCompressedBytes.Length);
+                byte[] encryptedBlock = HeaderCrypto.Encrypt(GetDataBlockBytesReference());
+                SetDataBlockBytesReference(encryptedBlock);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1CompressionInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1CompressionInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..555e334
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1CompressionInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,75 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1CompressionInfoEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V1CompressionInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.CompressionInfo, dataBlock)
+        {
+        }
+
+        public V1CompressionInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(Instance.RandomGenerator.Generate(16))
+        {
+            HeaderCrypto = headerCrypto;
+            UncompressedLength = 0;
+        }
+
+        public override object Clone()
+        {
+            V1CompressionInfoEncryptedHeaderBlock block = new V1CompressionInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        /// <summary>
+        /// The uncompressed size of the data
+        /// </summary>
+        public long UncompressedLength
+        {
+            get
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                long normalSize = rawBlock.GetLittleEndianValue(0, sizeof(long));
+                return normalSize;
+            }
+
+            set
+            {
+                byte[] normalSizeBytes = value.GetLittleEndianBytes();
+                Array.Copy(normalSizeBytes, 0, GetDataBlockBytesReference(), 0, normalSizeBytes.Length);
+                byte[] encryptedBlock = HeaderCrypto.Encrypt(GetDataBlockBytesReference());
+                SetDataBlockBytesReference(encryptedBlock);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1DocumentHeaders.cs b/Axantum.AxCrypt.Core/Header/V1DocumentHeaders.cs
new file mode 100644
index 0000000..70d4c51
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1DocumentHeaders.cs
@@ -0,0 +1,415 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1DocumentHeaders
+    {
+        private static readonly byte[] _version = new byte[] { 3, 2, 2, 0, 0 };
+
+        private Headers _headers = new Headers();
+
+        private IDerivedKey _keyEncryptingKey;
+
+        public V1DocumentHeaders(Passphrase passphrase, long keyWrapIterations)
+            : this(passphrase)
+        {
+            _headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            _headers.HeaderBlocks.Add(new VersionHeaderBlock(_version));
+            _headers.HeaderBlocks.Add(new V1KeyWrap1HeaderBlock(_keyEncryptingKey.DerivedKey, keyWrapIterations));
+
+            ICrypto headerCrypto = Instance.CryptoFactory.Legacy.CreateCrypto(HeadersSubkey.Key, null, 0);
+            _headers.HeaderBlocks.Add(new V1EncryptionInfoEncryptedHeaderBlock(headerCrypto));
+            _headers.HeaderBlocks.Add(new V1CompressionEncryptedHeaderBlock(headerCrypto));
+            _headers.HeaderBlocks.Add(new FileInfoEncryptedHeaderBlock(headerCrypto));
+            _headers.HeaderBlocks.Add(new V1UnicodeFileNameInfoEncryptedHeaderBlock(headerCrypto));
+            _headers.HeaderBlocks.Add(new V1FileNameInfoEncryptedHeaderBlock(headerCrypto));
+            _headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            SetMasterKeyForEncryptedHeaderBlocks(_headers.HeaderBlocks);
+
+            V1EncryptionInfoEncryptedHeaderBlock encryptionInfoHeaderBlock = _headers.FindHeaderBlock<V1EncryptionInfoEncryptedHeaderBlock>();
+            encryptionInfoHeaderBlock.IV = new SymmetricIV(128);
+            encryptionInfoHeaderBlock.PlaintextLength = 0;
+        }
+
+        public V1DocumentHeaders(Passphrase passphrase)
+        {
+            _keyEncryptingKey = Instance.CryptoFactory.Create(V1Aes128CryptoFactory.CryptoId).CreateDerivedKey(passphrase);
+        }
+
+        public V1DocumentHeaders(V1DocumentHeaders documentHeaders)
+        {
+            _keyEncryptingKey = documentHeaders._keyEncryptingKey;
+            foreach (HeaderBlock headerBlock in documentHeaders._headers.HeaderBlocks)
+            {
+                _headers.HeaderBlocks.Add((HeaderBlock)headerBlock.Clone());
+            }
+        }
+
+        public bool Load(AxCryptReader reader)
+        {
+            Headers headers = new Headers();
+            headers.Load(reader);
+
+            return Load(headers);
+        }
+
+        public bool Load(Headers headers)
+        {
+            _headers = headers;
+            _headers.EnsureFileFormatVersion(1, 3);
+
+            if (GetMasterKey() != null)
+            {
+                SetMasterKeyForEncryptedHeaderBlocks(_headers.HeaderBlocks);
+                return true;
+            }
+            return false;
+        }
+
+        public Headers Headers
+        {
+            get { return _headers; }
+        }
+
+        public VersionHeaderBlock VersionHeaderBlock
+        {
+            get
+            {
+                return _headers.VersionHeaderBlock;
+            }
+        }
+
+        private void SetMasterKeyForEncryptedHeaderBlocks(IList<HeaderBlock> headerBlocks)
+        {
+            ICrypto headerCrypto = Instance.CryptoFactory.Legacy.CreateCrypto(HeadersSubkey.Key, null, 0);
+
+            foreach (HeaderBlock headerBlock in headerBlocks)
+            {
+                EncryptedHeaderBlock encryptedHeaderBlock = headerBlock as EncryptedHeaderBlock;
+                if (encryptedHeaderBlock != null)
+                {
+                    encryptedHeaderBlock.HeaderCrypto = headerCrypto;
+                }
+            }
+        }
+
+        public void WriteWithoutHmac(Stream cipherStream)
+        {
+            if (cipherStream == null)
+            {
+                throw new ArgumentNullException("cipherStream");
+            }
+
+            WriteInternal(cipherStream, cipherStream);
+        }
+
+        public void WriteWithHmac(V1HmacStream hmacStream)
+        {
+            if (hmacStream == null)
+            {
+                throw new ArgumentNullException("hmacStream");
+            }
+
+            WriteInternal(hmacStream.ChainedStream, hmacStream);
+        }
+
+        private void WriteInternal(Stream cipherStream, Stream hmacStream)
+        {
+            cipherStream.Position = 0;
+            AxCrypt1Guid.Write(cipherStream);
+            PreambleHeaderBlock preambleHaderBlock = _headers.FindHeaderBlock<PreambleHeaderBlock>();
+            preambleHaderBlock.Write(cipherStream);
+            foreach (HeaderBlock headerBlock in _headers.HeaderBlocks)
+            {
+                if (headerBlock is DataHeaderBlock)
+                {
+                    continue;
+                }
+                if (headerBlock is PreambleHeaderBlock)
+                {
+                    continue;
+                }
+                headerBlock.Write(hmacStream);
+            }
+            DataHeaderBlock dataHeaderBlock = _headers.FindHeaderBlock<DataHeaderBlock>();
+            dataHeaderBlock.Write(hmacStream);
+        }
+
+        private SymmetricKey GetMasterKey()
+        {
+            V1KeyWrap1HeaderBlock keyHeaderBlock = _headers.FindHeaderBlock<V1KeyWrap1HeaderBlock>();
+            VersionHeaderBlock versionHeaderBlock = _headers.FindHeaderBlock<VersionHeaderBlock>();
+            byte[] unwrappedKeyData = keyHeaderBlock.UnwrapMasterKey(_keyEncryptingKey.DerivedKey, versionHeaderBlock.FileVersionMajor);
+            if (unwrappedKeyData.Length == 0)
+            {
+                return null;
+            }
+            return new SymmetricKey(unwrappedKeyData);
+        }
+
+        public void RewrapMasterKey(IDerivedKey keyEncryptingKey, long keyWrapIterations)
+        {
+            V1KeyWrap1HeaderBlock keyHeaderBlock = _headers.FindHeaderBlock<V1KeyWrap1HeaderBlock>();
+            keyHeaderBlock.RewrapMasterKey(GetMasterKey(), keyEncryptingKey.DerivedKey, keyWrapIterations);
+            _keyEncryptingKey = keyEncryptingKey;
+        }
+
+        public Subkey HmacSubkey
+        {
+            get
+            {
+                SymmetricKey masterKey = GetMasterKey();
+                if (masterKey == null)
+                {
+                    return null;
+                }
+                return new Subkey(masterKey, HeaderSubkey.Hmac);
+            }
+        }
+
+        public Subkey DataSubkey
+        {
+            get
+            {
+                SymmetricKey masterKey = GetMasterKey();
+                if (masterKey == null)
+                {
+                    return null;
+                }
+                return new Subkey(masterKey, HeaderSubkey.Data);
+            }
+        }
+
+        public Subkey HeadersSubkey
+        {
+            get
+            {
+                SymmetricKey masterKey = GetMasterKey();
+                if (masterKey == null)
+                {
+                    return null;
+                }
+                return new Subkey(masterKey, HeaderSubkey.Headers);
+            }
+        }
+
+        public long UncompressedLength
+        {
+            get
+            {
+                V1CompressionInfoEncryptedHeaderBlock compressionInfo = _headers.FindHeaderBlock<V1CompressionInfoEncryptedHeaderBlock>();
+                if (compressionInfo == null)
+                {
+                    return -1;
+                }
+                return compressionInfo.UncompressedLength;
+            }
+
+            set
+            {
+                V1CompressionInfoEncryptedHeaderBlock compressionInfo = _headers.FindHeaderBlock<V1CompressionInfoEncryptedHeaderBlock>();
+                if (compressionInfo == null)
+                {
+                    ICrypto headerCrypto = Instance.CryptoFactory.Legacy.CreateCrypto(HeadersSubkey.Key, null, 0);
+                    compressionInfo = new V1CompressionInfoEncryptedHeaderBlock(headerCrypto);
+                    _headers.HeaderBlocks.Add(compressionInfo);
+                }
+                compressionInfo.UncompressedLength = value;
+            }
+        }
+
+        private string AnsiFileName
+        {
+            get
+            {
+                V1FileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1FileNameInfoEncryptedHeaderBlock>();
+                return headerBlock.FileName;
+            }
+
+            set
+            {
+                V1FileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1FileNameInfoEncryptedHeaderBlock>();
+                headerBlock.FileName = value;
+            }
+        }
+
+        private string UnicodeFileName
+        {
+            get
+            {
+                V1UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1UnicodeFileNameInfoEncryptedHeaderBlock>();
+                if (headerBlock == null)
+                {
+                    // Unicode file name was added in 1.6.3.3 - if we can't find it signal it's absence with null.
+                    return null;
+                }
+
+                return headerBlock.FileName;
+            }
+
+            set
+            {
+                V1UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1UnicodeFileNameInfoEncryptedHeaderBlock>();
+                headerBlock.FileName = value;
+            }
+        }
+
+        public string FileName
+        {
+            get
+            {
+                return UnicodeFileName ?? AnsiFileName;
+            }
+
+            set
+            {
+                UnicodeFileName = value;
+                AnsiFileName = value;
+            }
+        }
+
+        public bool IsCompressed
+        {
+            get
+            {
+                V1CompressionEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1CompressionEncryptedHeaderBlock>();
+                if (headerBlock == null)
+                {
+                    // Conditional compression was added in 1.2.2, before then it was always compressed.
+                    return true;
+                }
+                return headerBlock.IsCompressed;
+            }
+            set
+            {
+                V1CompressionEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1CompressionEncryptedHeaderBlock>();
+                headerBlock.IsCompressed = value;
+                if (value)
+                {
+                    // When compressed, ensure we reserve room in headers for the CompressionInfo block
+                    UncompressedLength = 0;
+                }
+            }
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.CreationTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.CreationTimeUtc = value;
+            }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.LastAccessTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.LastAccessTimeUtc = value;
+            }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.LastWriteTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.LastWriteTimeUtc = value;
+            }
+        }
+
+        /// <summary>
+        /// The Initial Vector used for CBC encryption of the data
+        /// </summary>
+        /// <returns>The Initial Vector</returns>
+        public SymmetricIV IV
+        {
+            get
+            {
+                V1EncryptionInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1EncryptionInfoEncryptedHeaderBlock>();
+                return headerBlock.IV;
+            }
+        }
+
+        /// <summary>
+        /// The length in bytes of the plain text. This may still require decompression (inflate).
+        /// </summary>
+        public long PlaintextLength
+        {
+            get
+            {
+                V1EncryptionInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1EncryptionInfoEncryptedHeaderBlock>();
+                return headerBlock.PlaintextLength;
+            }
+
+            set
+            {
+                V1EncryptionInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V1EncryptionInfoEncryptedHeaderBlock>();
+                headerBlock.PlaintextLength = value;
+            }
+        }
+
+        public long CipherTextLength
+        {
+            get
+            {
+                DataHeaderBlock headerBlock = _headers.FindHeaderBlock<DataHeaderBlock>();
+                return headerBlock.CipherTextLength;
+            }
+            set
+            {
+                DataHeaderBlock headerBlock = _headers.FindHeaderBlock<DataHeaderBlock>();
+                headerBlock.CipherTextLength = value;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1EncryptionInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1EncryptionInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..c375c74
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1EncryptionInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,115 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1EncryptionInfoEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V1EncryptionInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.EncryptionInfo, dataBlock)
+        {
+        }
+
+        public V1EncryptionInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[0])
+        {
+            HeaderCrypto = headerCrypto;
+            PlaintextLength = 0;
+            IV = new SymmetricIV(new byte[16]);
+        }
+
+        public override object Clone()
+        {
+            V1EncryptionInfoEncryptedHeaderBlock block = new V1EncryptionInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        private void EnsureDataBlock()
+        {
+            if (GetDataBlockBytesReference().Length > 0)
+            {
+                return;
+            }
+
+            SetDataBlockBytesReference(HeaderCrypto.Encrypt(new byte[32]));
+        }
+
+        public long PlaintextLength
+        {
+            get
+            {
+                EnsureDataBlock();
+                byte[] rawData = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                long plaintextLength = rawData.GetLittleEndianValue(0, sizeof(long));
+                return plaintextLength;
+            }
+
+            set
+            {
+                EnsureDataBlock();
+                byte[] rawData = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                byte[] plaintextLengthBytes = value.GetLittleEndianBytes();
+                Array.Copy(plaintextLengthBytes, 0, rawData, 0, plaintextLengthBytes.Length);
+
+                byte[] encryptedData = HeaderCrypto.Encrypt(rawData);
+                SetDataBlockBytesReference(encryptedData);
+            }
+        }
+
+        public SymmetricIV IV
+        {
+            get
+            {
+                EnsureDataBlock();
+                byte[] rawData = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                byte[] iv = new byte[16];
+                Array.Copy(rawData, 8, iv, 0, iv.Length);
+
+                return new SymmetricIV(iv);
+            }
+
+            set
+            {
+                EnsureDataBlock();
+                byte[] rawData = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                byte[] encryptedIV = HeaderCrypto.Encrypt(value.GetBytes());
+                Array.Copy(encryptedIV, 0, rawData, 8, encryptedIV.Length);
+
+                byte[] encryptedData = HeaderCrypto.Encrypt(rawData);
+                SetDataBlockBytesReference(encryptedData);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1FileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1FileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..4ddcba6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1FileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,80 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1FileNameInfoEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V1FileNameInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.FileNameInfo, dataBlock)
+        {
+        }
+
+        public V1FileNameInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[0])
+        {
+            HeaderCrypto = headerCrypto;
+            FileName = String.Empty;
+        }
+
+        public override object Clone()
+        {
+            V1FileNameInfoEncryptedHeaderBlock block = new V1FileNameInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public string FileName
+        {
+            get
+            {
+                byte[] rawFileName = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                int end = Array.IndexOf<byte>(rawFileName, 0);
+                if (end == -1)
+                {
+                    throw new InvalidOperationException("Could not find terminating nul byte in file name");
+                }
+
+                string fileName = Encoding.GetEncoding("us-ascii").GetString(rawFileName, 0, end);
+
+                return fileName;
+            }
+
+            set
+            {
+                byte[] rawFileName = Encoding.GetEncoding("us-ascii").GetBytes(value);
+                byte[] dataBlock = new byte[rawFileName.Length + 1 + 15 - (rawFileName.Length + 1 + 15) % 16];
+                rawFileName.CopyTo(dataBlock, 0);
+                SetDataBlockBytesReference(HeaderCrypto.Encrypt(dataBlock));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1IdTagHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1IdTagHeaderBlock.cs
new file mode 100644
index 0000000..f9dac5a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1IdTagHeaderBlock.cs
@@ -0,0 +1,76 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    /// <summary>
+    /// An arbitrary string encoded as Ansi Code Page 1252, with a C-style terminating 'nul' character.
+    /// </summary>
+    public class V1IdTagHeaderBlock : HeaderBlock
+    {
+        public V1IdTagHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.IdTag, dataBlock)
+        {
+        }
+
+        public V1IdTagHeaderBlock(string idTag)
+            : base(HeaderBlockType.IdTag)
+        {
+            IdTag = idTag;
+        }
+
+        public override object Clone()
+        {
+            V1IdTagHeaderBlock block = new V1IdTagHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        private static Encoding GetEncoding()
+        {
+            return Encoding.GetEncoding("Windows-1252");
+        }
+
+        public string IdTag
+        {
+            get
+            {
+                string idTag = GetEncoding().GetString(GetDataBlockBytesReference(), 0, GetDataBlockBytesReference().Length - 1);
+                return idTag;
+            }
+            set
+            {
+                byte[] idTagBytes = GetEncoding().GetBytes(value);
+                byte[] dataBlock = new byte[idTagBytes.Length + 1];
+                idTagBytes.CopyTo(dataBlock, 0);
+                dataBlock[dataBlock.Length - 1] = 0;
+                SetDataBlockBytesReference(dataBlock);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1KeyWrap1HeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1KeyWrap1HeaderBlock.cs
new file mode 100644
index 0000000..02216b6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1KeyWrap1HeaderBlock.cs
@@ -0,0 +1,142 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1KeyWrap1HeaderBlock : HeaderBlock
+    {
+        public V1KeyWrap1HeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.KeyWrap1, dataBlock)
+        {
+        }
+
+        public V1KeyWrap1HeaderBlock(SymmetricKey keyEncryptingKey, long keyWrapIterations)
+            : this(new byte[44])
+        {
+            Initialize(keyEncryptingKey, keyWrapIterations);
+        }
+
+        public override object Clone()
+        {
+            V1KeyWrap1HeaderBlock block = new V1KeyWrap1HeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public byte[] GetKeyData()
+        {
+            byte[] keyData = new byte[16 + 8];
+            Array.Copy(GetDataBlockBytesReference(), 0, keyData, 0, keyData.Length);
+
+            return keyData;
+        }
+
+        protected void Set(byte[] wrapped, Salt salt, long keyWrapIterations)
+        {
+            if (wrapped == null)
+            {
+                throw new ArgumentNullException("wrapped");
+            }
+            if (wrapped.Length != 16 + 8)
+            {
+                throw new ArgumentException("wrapped must be 128 bits + 8 bytes.");
+            }
+            if (salt == null)
+            {
+                throw new ArgumentNullException("salt");
+            }
+            if (salt.Length != 16)
+            {
+                throw new ArgumentException("salt must have same length as the wrapped key, i.e. 128 bits.");
+            }
+            Array.Copy(wrapped, 0, GetDataBlockBytesReference(), 0, wrapped.Length);
+            Array.Copy(salt.GetBytes(), 0, GetDataBlockBytesReference(), 16 + 8, salt.Length);
+            byte[] iterationsBytes = keyWrapIterations.GetLittleEndianBytes();
+            Array.Copy(iterationsBytes, 0, GetDataBlockBytesReference(), 16 + 8 + 16, sizeof(uint));
+        }
+
+        public Salt Salt
+        {
+            get
+            {
+                byte[] salt = new byte[16];
+                Array.Copy(GetDataBlockBytesReference(), 16 + 8, salt, 0, salt.Length);
+
+                return new Salt(salt);
+            }
+        }
+
+        public long KeyWrapIterations
+        {
+            get
+            {
+                long keyWrapIterations = GetDataBlockBytesReference().GetLittleEndianValue(16 + 8 + 16, sizeof(uint));
+
+                return keyWrapIterations;
+            }
+        }
+
+        public byte[] UnwrapMasterKey(SymmetricKey keyEncryptingKey, byte fileVersionMajor)
+        {
+            byte[] wrappedKeyData = GetKeyData();
+            Salt salt = Salt;
+            SymmetricKey masterKeyEncryptingKey = keyEncryptingKey;
+            if (fileVersionMajor <= 1)
+            {
+                // Due to a bug in 1.1 and earlier we only used a truncated part of the key and salt :-(
+                // Compensate for this here. Users should be warned if FileVersionMajor <= 1 .
+                byte[] badKey = new byte[masterKeyEncryptingKey.Size / 8];
+                Array.Copy(keyEncryptingKey.GetBytes(), 0, badKey, 0, 4);
+                masterKeyEncryptingKey = new SymmetricKey(badKey);
+
+                byte[] badSalt = new byte[salt.Length];
+                Array.Copy(salt.GetBytes(), 0, badSalt, 0, 4);
+                salt = new Salt(badSalt);
+            }
+
+            KeyWrap keyWrap = new KeyWrap(salt, KeyWrapIterations, KeyWrapMode.AxCrypt);
+            byte[] unwrappedKeyData = keyWrap.Unwrap(Instance.CryptoFactory.Legacy.CreateCrypto(masterKeyEncryptingKey, null, 0), wrappedKeyData);
+            return unwrappedKeyData;
+        }
+
+        private void Initialize(SymmetricKey keyEncryptingKey, long keyWrapIterations)
+        {
+            RewrapMasterKey(new SymmetricKey(keyEncryptingKey.Size), keyEncryptingKey, keyWrapIterations);
+        }
+
+        public void RewrapMasterKey(SymmetricKey masterKey, SymmetricKey keyEncryptingKey, long keyWrapIterations)
+        {
+            Salt salt = new Salt(masterKey.Size);
+            KeyWrap keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.AxCrypt);
+            byte[] wrappedKeyData = keyWrap.Wrap(Instance.CryptoFactory.Legacy.CreateCrypto(keyEncryptingKey, null, 0), masterKey);
+            Set(wrappedKeyData, salt, keyWrapIterations);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1KeyWrap2HeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1KeyWrap2HeaderBlock.cs
new file mode 100644
index 0000000..75d5aa6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1KeyWrap2HeaderBlock.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1KeyWrap2HeaderBlock : HeaderBlock
+    {
+        public V1KeyWrap2HeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.KeyWrap2, dataBlock)
+        {
+        }
+
+        public override object Clone()
+        {
+            V1KeyWrap2HeaderBlock block = new V1KeyWrap2HeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V1UnicodeFileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V1UnicodeFileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..497369c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V1UnicodeFileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,80 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V1UnicodeFileNameInfoEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V1UnicodeFileNameInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.UnicodeFileNameInfo, dataBlock)
+        {
+        }
+
+        public V1UnicodeFileNameInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[0])
+        {
+            HeaderCrypto = headerCrypto;
+        }
+
+        public override object Clone()
+        {
+            V1UnicodeFileNameInfoEncryptedHeaderBlock block = new V1UnicodeFileNameInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public string FileName
+        {
+            get
+            {
+                byte[] rawFileName = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+
+                int end = rawFileName.Locate(new byte[] { 0, 0, }, 0, rawFileName.Length, 2);
+                if (end == -1)
+                {
+                    throw new InvalidOperationException("Could not find terminating double nul byte in file name");
+                }
+
+                string fileName = Encoding.Unicode.GetString(rawFileName, 0, end);
+
+                return fileName;
+            }
+
+            set
+            {
+                byte[] rawFileName = Encoding.Unicode.GetBytes(value);
+                byte[] dataBlock = new byte[rawFileName.Length + 2 + 15 - (rawFileName.Length + 2 + 15) % 16];
+                rawFileName.CopyTo(dataBlock, 0);
+                SetDataBlockBytesReference(HeaderCrypto.Encrypt(dataBlock));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2AsymmetricKeyWrapHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2AsymmetricKeyWrapHeaderBlock.cs
new file mode 100644
index 0000000..09fd7c9
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2AsymmetricKeyWrapHeaderBlock.cs
@@ -0,0 +1,65 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2AsymmetricKeyWrapHeaderBlock : HeaderBlock
+    {
+        private const int DATABLOCK_LENGTH = 4096 / 8;
+
+        public V2AsymmetricKeyWrapHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.V2AsymmetricKeyWrap, dataBlock)
+        {
+        }
+
+        public V2AsymmetricKeyWrapHeaderBlock(SymmetricKey masterKey, SymmetricIV masterIV)
+            : this(Instance.RandomGenerator.Generate(DATABLOCK_LENGTH))
+        {
+            byte[] encrypted = Instance.AsymmetricKeysStore.Keys.KeyPair.PublicKey.Transform(masterKey + masterIV);
+            GetDataBlockBytesReference().SetFrom(encrypted);
+        }
+
+        public override object Clone()
+        {
+            V2AsymmetricKeyWrapHeaderBlock block = new V2AsymmetricKeyWrapHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        private byte[] _decryptedDataBlock = null;
+
+        private byte[] DecryptedDataBlock
+        {
+            get
+            {
+                if (_decryptedDataBlock == null)
+                {
+                    _decryptedDataBlock = Instance.AsymmetricKeysStore.Keys.KeyPair.PrivateKey.Transform(GetDataBlockBytesReference());
+                }
+                return _decryptedDataBlock;
+            }
+        }
+
+        /// <summary>
+        /// Create an ICrypto instance from the decrypted asymmetric key wrap.
+        /// </summary>
+        /// <param name="cryptoFactory"></param>
+        /// <param name="keyStreamOffset"></param>
+        /// <returns>An ICrypto instance, initialized with key and iv.</returns>
+        public ICrypto Crypto(ICryptoFactory cryptoFactory, long keyStreamOffset)
+        {
+            byte[] iv = new byte[cryptoFactory.BlockSize / 8];
+            byte[] masterKey = new byte[cryptoFactory.KeySize / 8];
+
+            Array.Copy(DecryptedDataBlock, 0, masterKey, 0, masterKey.Length);
+            Array.Copy(DecryptedDataBlock, masterKey.Length, iv, 0, iv.Length);
+
+            ICrypto crypto = cryptoFactory.CreateCrypto(new SymmetricKey(masterKey), new SymmetricIV(iv), keyStreamOffset);
+            return crypto;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2AsymmetricRecipientsEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2AsymmetricRecipientsEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..4a36ebd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2AsymmetricRecipientsEncryptedHeaderBlock.cs
@@ -0,0 +1,44 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2AsymmetricRecipientsEncryptedHeaderBlock : StringEncryptedHeaderBlockBase
+    {
+        public V2AsymmetricRecipientsEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.AsymmetricRecipients, dataBlock)
+        {
+        }
+
+        public V2AsymmetricRecipientsEncryptedHeaderBlock(ICrypto headerCrypto)
+            : base(HeaderBlockType.AsymmetricRecipients, headerCrypto)
+        {
+        }
+
+        public override object Clone()
+        {
+            V2AsymmetricRecipientsEncryptedHeaderBlock block = new V2AsymmetricRecipientsEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public IEnumerable<string> Recipients
+        {
+            get
+            {
+                if (String.IsNullOrEmpty(StringValue))
+                {
+                    return new string[0];
+                }
+                return JsonConvert.DeserializeObject<IEnumerable<string>>(StringValue);
+            }
+            set
+            {
+                StringValue = JsonConvert.SerializeObject(value ?? new string[0]);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2CompressionEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2CompressionEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..dd3bf2a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2CompressionEncryptedHeaderBlock.cs
@@ -0,0 +1,72 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2CompressionEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V2CompressionEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.Compression, dataBlock)
+        {
+        }
+
+        public V2CompressionEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[1])
+        {
+            HeaderCrypto = headerCrypto;
+            IsCompressed = false;
+        }
+
+        public override object Clone()
+        {
+            V2CompressionEncryptedHeaderBlock block = new V2CompressionEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public bool IsCompressed
+        {
+            get
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                byte isCompressed = (byte)rawBlock.GetLittleEndianValue(0, sizeof(byte));
+                return isCompressed != 0;
+            }
+
+            set
+            {
+                byte[] isCompressedBytes = value ? new byte[] { 1 } : new byte[] { 0 };
+                Array.Copy(isCompressedBytes, 0, GetDataBlockBytesReference(), 0, isCompressedBytes.Length);
+                byte[] encryptedBlock = HeaderCrypto.Encrypt(GetDataBlockBytesReference());
+                SetDataBlockBytesReference(encryptedBlock);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2DocumentHeaders.cs b/Axantum.AxCrypt.Core/Header/V2DocumentHeaders.cs
new file mode 100644
index 0000000..a6693ad
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2DocumentHeaders.cs
@@ -0,0 +1,350 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2DocumentHeaders : IDisposable
+    {
+        private const int HMACKEY_KEYSTREAM_INDEX = 0;
+        private const int FILEINFO_KEYSTREAM_INDEX = 256;
+        private const int COMPRESSIONINFO_KEYSTREAM_INDEX = 512;
+        private const int FILENAMEINFO_KEYSTREAM_INDEX = 768;
+        private const int LENGTHSINFO_KEYSTREAM_INDEX = 2048;
+        private const int DATA_KEYSTREAM_INDEX = 1048576;
+
+        private static readonly byte[] _version = new byte[] { 4, 0, 2, 0, 0 };
+
+        private Headers _headers;
+
+        private V2HmacStream _hmacStream;
+
+        private ICryptoFactory _cryptoFactory;
+
+        private IDerivedKey _keyEncryptingKey;
+
+        public V2DocumentHeaders(Passphrase passphrase, Guid cryptoId, long keyWrapIterations)
+        {
+            _cryptoFactory = Instance.CryptoFactory.Create(cryptoId);
+            _keyEncryptingKey = _cryptoFactory.CreateDerivedKey(passphrase);
+            _headers = new Headers();
+
+            _headers.HeaderBlocks.Add(new PreambleHeaderBlock());
+            _headers.HeaderBlocks.Add(new VersionHeaderBlock(_version));
+            V2KeyWrapHeaderBlock keyWrap = new V2KeyWrapHeaderBlock(_cryptoFactory, _keyEncryptingKey, keyWrapIterations);
+            _headers.HeaderBlocks.Add(keyWrap);
+            if (Instance.AsymmetricKeysStore.HasKeys)
+            {
+                _headers.HeaderBlocks.Add(new V2AsymmetricKeyWrapHeaderBlock(keyWrap.MasterKey, keyWrap.MasterIV));
+            }
+            _headers.HeaderBlocks.Add(new FileInfoEncryptedHeaderBlock(GetHeaderCrypto(HeaderBlockType.FileInfo)));
+            _headers.HeaderBlocks.Add(new V2CompressionEncryptedHeaderBlock(GetHeaderCrypto(HeaderBlockType.Compression)));
+            _headers.HeaderBlocks.Add(new V2UnicodeFileNameInfoEncryptedHeaderBlock(GetHeaderCrypto(HeaderBlockType.UnicodeFileNameInfo)));
+            _headers.HeaderBlocks.Add(new DataHeaderBlock());
+
+            SetDataEncryptingCryptoForEncryptedHeaderBlocks(_headers.HeaderBlocks);
+        }
+
+        public V2DocumentHeaders(IDerivedKey key, Guid cryptoId)
+        {
+            _cryptoFactory = Instance.CryptoFactory.Create(cryptoId);
+            _keyEncryptingKey = key;
+            _headers = new Headers();
+        }
+
+        public Headers Headers
+        {
+            get { return _headers; }
+        }
+
+        public V2HmacStream HmacStream
+        {
+            get { return _hmacStream; }
+        }
+
+        public bool Load(Headers headers)
+        {
+            _headers = headers;
+            _headers.EnsureFileFormatVersion(4, 4);
+
+            V2KeyWrapHeaderBlock v2KeyWrapHeaderBlock = _headers.FindHeaderBlock<V2KeyWrapHeaderBlock>();
+            v2KeyWrapHeaderBlock.SetCryptoKey(_cryptoFactory, _keyEncryptingKey);
+
+            if (DataEncryptingKey == null)
+            {
+                return false;
+            }
+
+            _hmacStream = new V2HmacStream(GetHmacKey());
+            AxCrypt1Guid.Write(_hmacStream);
+            foreach (HeaderBlock header in _headers.HeaderBlocks)
+            {
+                header.Write(_hmacStream);
+            }
+
+            SetDataEncryptingCryptoForEncryptedHeaderBlocks(_headers.HeaderBlocks);
+            return true;
+        }
+
+        public void Trailers(AxCryptReader axCryptReader)
+        {
+            _headers.Trailers(axCryptReader);
+            foreach (HeaderBlock header in _headers.TrailerBlocks)
+            {
+                if (header.HeaderBlockType == HeaderBlockType.V2Hmac)
+                {
+                    continue;
+                }
+                header.Write(_hmacStream);
+            }
+        }
+
+        private void SetDataEncryptingCryptoForEncryptedHeaderBlocks(IList<HeaderBlock> headerBlocks)
+        {
+            foreach (HeaderBlock headerBlock in headerBlocks)
+            {
+                EncryptedHeaderBlock encryptedHeaderBlock = headerBlock as EncryptedHeaderBlock;
+                if (encryptedHeaderBlock == null)
+                {
+                    continue;
+                }
+                encryptedHeaderBlock.HeaderCrypto = GetHeaderCrypto(encryptedHeaderBlock.HeaderBlockType);
+            }
+        }
+
+        private ICrypto GetHeaderCrypto(HeaderBlockType headerBlockType)
+        {
+            switch (headerBlockType)
+            {
+                case HeaderBlockType.FileInfo:
+                    return CreateKeyStreamCrypto(FILEINFO_KEYSTREAM_INDEX);
+
+                case HeaderBlockType.Compression:
+                    return CreateKeyStreamCrypto(COMPRESSIONINFO_KEYSTREAM_INDEX);
+
+                case HeaderBlockType.UnicodeFileNameInfo:
+                    return CreateKeyStreamCrypto(FILENAMEINFO_KEYSTREAM_INDEX);
+            }
+            throw new InternalErrorException("Unexpected header block type. Can't determine Header Cryptop.");
+        }
+
+        private ICrypto CreateKeyStreamCrypto(long keyStreamOffset)
+        {
+            return _cryptoFactory.CreateCrypto(DataEncryptingKey, DataEncryptingIV, keyStreamOffset);
+        }
+
+        public void WriteStartWithHmac(V2HmacStream hmacStream)
+        {
+            if (hmacStream == null)
+            {
+                throw new ArgumentNullException("hmacStream");
+            }
+
+            AxCrypt1Guid.Write(hmacStream);
+
+            PreambleHeaderBlock preambleHeaderBlock = _headers.FindHeaderBlock<PreambleHeaderBlock>();
+            preambleHeaderBlock.Write(hmacStream);
+
+            WriteGeneralHeaders(hmacStream);
+
+            DataHeaderBlock dataHeaderBlock = _headers.FindHeaderBlock<DataHeaderBlock>();
+            dataHeaderBlock.Write(hmacStream);
+        }
+
+        public void WriteEndWithHmac(V2HmacStream hmacStream, long plaintextLength, long compressedPlaintextLength)
+        {
+            WriteGeneralHeaders(hmacStream);
+
+            V2PlaintextLengthsEncryptedHeaderBlock lengths = new V2PlaintextLengthsEncryptedHeaderBlock(CreateKeyStreamCrypto(LENGTHSINFO_KEYSTREAM_INDEX));
+            lengths.PlaintextLength = plaintextLength;
+            lengths.CompressedPlaintextLength = compressedPlaintextLength;
+            lengths.Write(hmacStream);
+
+            V2HmacHeaderBlock hmac = new V2HmacHeaderBlock();
+            hmac.Hmac = hmacStream.Hmac;
+            hmac.Write(hmacStream);
+        }
+
+        private void WriteGeneralHeaders(V2HmacStream hmacStream)
+        {
+            foreach (HeaderBlock headerBlock in _headers.HeaderBlocks)
+            {
+                switch (headerBlock.HeaderBlockType)
+                {
+                    case HeaderBlockType.Data:
+                    case HeaderBlockType.Preamble:
+                    case HeaderBlockType.PlaintextLengths:
+                        continue;
+                }
+                headerBlock.Write(hmacStream);
+            }
+        }
+
+        public SymmetricKey DataEncryptingKey
+        {
+            get
+            {
+                V2KeyWrapHeaderBlock keyHeaderBlock = _headers.FindHeaderBlock<V2KeyWrapHeaderBlock>();
+                return keyHeaderBlock.MasterKey;
+            }
+        }
+
+        public SymmetricIV DataEncryptingIV
+        {
+            get
+            {
+                V2KeyWrapHeaderBlock keyHeaderBlock = _headers.FindHeaderBlock<V2KeyWrapHeaderBlock>();
+                return keyHeaderBlock.MasterIV;
+            }
+        }
+
+        public ICrypto CreateDataCrypto()
+        {
+            return CreateKeyStreamCrypto(DATA_KEYSTREAM_INDEX);
+        }
+
+        public byte[] GetHmacKey()
+        {
+            ICrypto hmacKeyCrypto = CreateKeyStreamCrypto(HMACKEY_KEYSTREAM_INDEX);
+            byte[] key = new byte[V2Hmac.RequiredLength];
+            key = hmacKeyCrypto.Encrypt(key);
+
+            return key;
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.CreationTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.CreationTimeUtc = value;
+            }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.LastAccessTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.LastAccessTimeUtc = value;
+            }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                return headerBlock.LastWriteTimeUtc;
+            }
+            set
+            {
+                FileInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<FileInfoEncryptedHeaderBlock>();
+                headerBlock.LastWriteTimeUtc = value;
+            }
+        }
+
+        public bool IsCompressed
+        {
+            get
+            {
+                V2CompressionEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V2CompressionEncryptedHeaderBlock>();
+                return headerBlock.IsCompressed;
+            }
+            set
+            {
+                V2CompressionEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V2CompressionEncryptedHeaderBlock>();
+                headerBlock.IsCompressed = value;
+            }
+        }
+
+        public string FileName
+        {
+            get
+            {
+                V2UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V2UnicodeFileNameInfoEncryptedHeaderBlock>();
+                return headerBlock.FileName;
+            }
+
+            set
+            {
+                V2UnicodeFileNameInfoEncryptedHeaderBlock headerBlock = _headers.FindHeaderBlock<V2UnicodeFileNameInfoEncryptedHeaderBlock>();
+                headerBlock.FileName = value;
+            }
+        }
+
+        public Hmac Hmac
+        {
+            get
+            {
+                V2HmacHeaderBlock hmacHeaderBlock = _headers.FindTrailerBlock<V2HmacHeaderBlock>();
+                return hmacHeaderBlock.Hmac;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_hmacStream == null)
+            {
+                return;
+            }
+            _hmacStream.Dispose();
+            _hmacStream = null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2HmacHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2HmacHeaderBlock.cs
new file mode 100644
index 0000000..76cef05
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2HmacHeaderBlock.cs
@@ -0,0 +1,69 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2HmacHeaderBlock : HeaderBlock
+    {
+        public V2HmacHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.V2Hmac, dataBlock)
+        {
+            if (dataBlock == null)
+            {
+                throw new ArgumentNullException("dataBlock");
+            }
+        }
+
+        public V2HmacHeaderBlock()
+            : this(new byte[V2Hmac.RequiredLength])
+        {
+        }
+
+        public override object Clone()
+        {
+            V2HmacHeaderBlock block = new V2HmacHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public Hmac Hmac
+        {
+            get
+            {
+                V2Hmac hmac = new V2Hmac(GetDataBlockBytesReference());
+                return hmac;
+            }
+            set
+            {
+                SetDataBlockBytesReference(value.GetBytes());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2KeyWrapHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2KeyWrapHeaderBlock.cs
new file mode 100644
index 0000000..6e12942
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2KeyWrapHeaderBlock.cs
@@ -0,0 +1,214 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2KeyWrapHeaderBlock : HeaderBlock
+    {
+        private const int WRAP_MAX_LENGTH = 128 + 16;
+        private const int WRAP_SALT_MAX_LENGTH = 64;
+        private const int WRAP_ITERATIONS_LENGTH = sizeof(uint);
+        private const int PASSPHRASE_DERIVATION_SALT_MAX_LENGTH = 32;
+        private const int PASSPHRASE_DERIVATION_ITERATIONS_LENGTH = sizeof(uint);
+
+        private const int WRAP_OFFSET = 0;
+        private const int WRAP_SALT_OFFSET = WRAP_OFFSET + WRAP_MAX_LENGTH;
+        private const int WRAP_ITERATIONS_OFFSET = WRAP_SALT_OFFSET + WRAP_SALT_MAX_LENGTH;
+        private const int PASSPHRASE_DERIVATION_SALT_OFFSET = WRAP_ITERATIONS_OFFSET + WRAP_ITERATIONS_LENGTH;
+        private const int PASSPHRASE_DERIVATION_ITERATIONS_OFFSET = PASSPHRASE_DERIVATION_SALT_OFFSET + PASSPHRASE_DERIVATION_SALT_MAX_LENGTH;
+
+        private const int DATABLOCK_LENGTH = PASSPHRASE_DERIVATION_ITERATIONS_OFFSET + PASSPHRASE_DERIVATION_ITERATIONS_LENGTH;
+
+        public V2KeyWrapHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.V2KeyWrap, dataBlock)
+        {
+            if (dataBlock == null)
+            {
+                throw new ArgumentNullException("dataBlock");
+            }
+            if (dataBlock.Length != DATABLOCK_LENGTH)
+            {
+                throw new ArgumentException("Incorrect length for dataBlock");
+            }
+        }
+
+        private ICryptoFactory _cryptoFactory;
+        private IDerivedKey _keyEncryptingKey;
+
+        public V2KeyWrapHeaderBlock(ICryptoFactory cryptoFactory, IDerivedKey keyEncryptingKey, long keyWrapIterations)
+            : this(Instance.RandomGenerator.Generate(DATABLOCK_LENGTH))
+        {
+            _cryptoFactory = cryptoFactory;
+            _keyEncryptingKey = keyEncryptingKey;
+
+            Initialize(keyWrapIterations);
+        }
+
+        public void SetCryptoKey(ICryptoFactory cryptoFactory, IDerivedKey keyEncryptingKey)
+        {
+            _cryptoFactory = cryptoFactory;
+            _keyEncryptingKey = keyEncryptingKey;
+            _unwrappedKeyData = null;
+        }
+
+        public override object Clone()
+        {
+            V2KeyWrapHeaderBlock block = new V2KeyWrapHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public long KeyWrapIterations
+        {
+            get
+            {
+                long keyWrapIterations = GetDataBlockBytesReference().GetLittleEndianValue(WRAP_ITERATIONS_OFFSET, sizeof(uint));
+
+                return keyWrapIterations;
+            }
+        }
+
+        public int DerivationIterations
+        {
+            get
+            {
+                int derivationIterations = (int)GetDataBlockBytesReference().GetLittleEndianValue(PASSPHRASE_DERIVATION_ITERATIONS_OFFSET, PASSPHRASE_DERIVATION_ITERATIONS_LENGTH);
+
+                return derivationIterations;
+            }
+            set
+            {
+                byte[] derivationIterationBytes = value.GetLittleEndianBytes();
+
+                Array.Copy(derivationIterationBytes, 0, GetDataBlockBytesReference(), PASSPHRASE_DERIVATION_ITERATIONS_OFFSET, PASSPHRASE_DERIVATION_ITERATIONS_LENGTH);
+            }
+        }
+
+        private byte[] GetKeyData(int blockSize, int keyLength)
+        {
+            byte[] keyData = new byte[keyLength + blockSize + blockSize / 2];
+            Array.Copy(GetDataBlockBytesReference(), WRAP_OFFSET, keyData, 0, keyData.Length);
+
+            return keyData;
+        }
+
+        public Salt DerivationSalt
+        {
+            get
+            {
+                byte[] derivationSalt = new byte[PASSPHRASE_DERIVATION_SALT_MAX_LENGTH];
+                Array.Copy(GetDataBlockBytesReference(), PASSPHRASE_DERIVATION_SALT_OFFSET, derivationSalt, 0, derivationSalt.Length);
+
+                return new Salt(derivationSalt);
+            }
+            set
+            {
+                Array.Copy(value.GetBytes(), 0, GetDataBlockBytesReference(), PASSPHRASE_DERIVATION_SALT_OFFSET, value.Length);
+            }
+        }
+
+        private void Initialize(long keyWrapIterations)
+        {
+            DerivationSalt = _keyEncryptingKey.DerivationSalt;
+            DerivationIterations = _keyEncryptingKey.DerivationIterations;
+
+            Salt salt = new Salt(_keyEncryptingKey.DerivedKey.Size);
+            KeyWrap keyWrap = new KeyWrap(salt, keyWrapIterations, KeyWrapMode.Specification);
+            ICrypto crypto = _cryptoFactory.CreateCrypto(_keyEncryptingKey.DerivedKey, null, 0);
+            _unwrappedKeyData = Instance.RandomGenerator.Generate(_keyEncryptingKey.DerivedKey.Size / 8 + crypto.BlockLength);
+            byte[] wrappedKeyData = keyWrap.Wrap(crypto, _unwrappedKeyData);
+            Set(wrappedKeyData, salt, keyWrapIterations);
+        }
+
+        private void Set(byte[] wrapped, Salt salt, long keyWrapIterations)
+        {
+            Array.Copy(wrapped, 0, GetDataBlockBytesReference(), 0, wrapped.Length);
+            Array.Copy(salt.GetBytes(), 0, GetDataBlockBytesReference(), WRAP_SALT_OFFSET, salt.Length);
+            byte[] keyWrapIterationsBytes = keyWrapIterations.GetLittleEndianBytes();
+            Array.Copy(keyWrapIterationsBytes, 0, GetDataBlockBytesReference(), WRAP_ITERATIONS_OFFSET, WRAP_ITERATIONS_LENGTH);
+        }
+
+        private byte[] _unwrappedKeyData;
+
+        private byte[] UnwrappedMasterKeyData
+        {
+            get
+            {
+                if (_unwrappedKeyData == null)
+                {
+                    _unwrappedKeyData = UnwrapMasterKeyData();
+                }
+                return _unwrappedKeyData;
+            }
+        }
+
+        private byte[] UnwrapMasterKeyData()
+        {
+            byte[] saltBytes = new byte[_keyEncryptingKey.DerivedKey.Size / 8];
+            Array.Copy(GetDataBlockBytesReference(), WRAP_SALT_OFFSET, saltBytes, 0, saltBytes.Length);
+            Salt salt = new Salt(saltBytes);
+
+            KeyWrap keyWrap = new KeyWrap(salt, KeyWrapIterations, KeyWrapMode.Specification);
+            ICrypto crypto = _cryptoFactory.CreateCrypto(_keyEncryptingKey.DerivedKey, null, 0);
+            byte[] wrappedKeyData = GetKeyData(crypto.BlockLength, _keyEncryptingKey.DerivedKey.Size / 8);
+            return keyWrap.Unwrap(crypto, wrappedKeyData);
+        }
+
+        public SymmetricKey MasterKey
+        {
+            get
+            {
+                if (UnwrappedMasterKeyData.Length == 0)
+                {
+                    return null;
+                }
+                byte[] masterKeyBytes = new byte[_keyEncryptingKey.DerivedKey.Size / 8];
+                Array.Copy(UnwrappedMasterKeyData, 0, masterKeyBytes, 0, masterKeyBytes.Length);
+                return new SymmetricKey(masterKeyBytes);
+            }
+        }
+
+        public SymmetricIV MasterIV
+        {
+            get
+            {
+                if (UnwrappedMasterKeyData.Length == 0)
+                {
+                    return null;
+                }
+                ICrypto crypto = _cryptoFactory.CreateCrypto(_keyEncryptingKey.DerivedKey, null, 0);
+                byte[] masterIVBytes = new byte[crypto.BlockLength];
+                Array.Copy(UnwrappedMasterKeyData, _keyEncryptingKey.DerivedKey.Size / 8, masterIVBytes, 0, masterIVBytes.Length);
+                return new SymmetricIV(masterIVBytes);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2PlainTextLengthsEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2PlainTextLengthsEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..834913d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2PlainTextLengthsEncryptedHeaderBlock.cs
@@ -0,0 +1,100 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2PlaintextLengthsEncryptedHeaderBlock : EncryptedHeaderBlock
+    {
+        public V2PlaintextLengthsEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.PlaintextLengths, dataBlock)
+        {
+        }
+
+        public V2PlaintextLengthsEncryptedHeaderBlock(ICrypto headerCrypto)
+            : this(new byte[sizeof(long) + sizeof(long)])
+        {
+            HeaderCrypto = headerCrypto;
+            PlaintextLength = 0;
+            CompressedPlaintextLength = 0;
+        }
+
+        public override object Clone()
+        {
+            V2PlaintextLengthsEncryptedHeaderBlock clone = new V2PlaintextLengthsEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(clone);
+        }
+
+        /// <summary>
+        /// The uncompressed size of the data in bytes
+        /// </summary>
+        public long PlaintextLength
+        {
+            get
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                long plaintextLength = rawBlock.GetLittleEndianValue(0, sizeof(long));
+                return plaintextLength;
+            }
+
+            set
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                byte[] plaintextLength = value.GetLittleEndianBytes();
+                Array.Copy(plaintextLength, 0, rawBlock, 0, plaintextLength.Length);
+                byte[] encryptedBlock = HeaderCrypto.Encrypt(rawBlock);
+                SetDataBlockBytesReference(encryptedBlock);
+            }
+        }
+
+        /// <summary>
+        /// The Compressed size of the data in bytes
+        /// </summary>
+        public long CompressedPlaintextLength
+        {
+            get
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                long compressedPlaintextLength = rawBlock.GetLittleEndianValue(sizeof(long), sizeof(long));
+                return compressedPlaintextLength;
+            }
+
+            set
+            {
+                byte[] rawBlock = HeaderCrypto.Decrypt(GetDataBlockBytesReference());
+                byte[] compressedPlaintextLength = value.GetLittleEndianBytes();
+                Array.Copy(compressedPlaintextLength, 0, rawBlock, sizeof(long), compressedPlaintextLength.Length);
+                byte[] encryptedBlock = HeaderCrypto.Encrypt(rawBlock);
+                SetDataBlockBytesReference(encryptedBlock);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/V2UnicodeFileNameInfoEncryptedHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/V2UnicodeFileNameInfoEncryptedHeaderBlock.cs
new file mode 100644
index 0000000..9ffa87b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/V2UnicodeFileNameInfoEncryptedHeaderBlock.cs
@@ -0,0 +1,65 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class V2UnicodeFileNameInfoEncryptedHeaderBlock : StringEncryptedHeaderBlockBase
+    {
+        public V2UnicodeFileNameInfoEncryptedHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.UnicodeFileNameInfo, dataBlock)
+        {
+        }
+
+        public V2UnicodeFileNameInfoEncryptedHeaderBlock(ICrypto headerCrypto)
+            : base(HeaderBlockType.UnicodeFileNameInfo, headerCrypto)
+        {
+        }
+
+        public override object Clone()
+        {
+            V2UnicodeFileNameInfoEncryptedHeaderBlock block = new V2UnicodeFileNameInfoEncryptedHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return CopyTo(block);
+        }
+
+        public string FileName
+        {
+            get
+            {
+                return StringValue;
+            }
+            set
+            {
+                StringValue = value;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Header/VersionHeaderBlock.cs b/Axantum.AxCrypt.Core/Header/VersionHeaderBlock.cs
new file mode 100644
index 0000000..fafe66d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Header/VersionHeaderBlock.cs
@@ -0,0 +1,109 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core.Header
+{
+    public class VersionHeaderBlock : HeaderBlock
+    {
+        public VersionHeaderBlock(byte[] dataBlock)
+            : base(HeaderBlockType.Version, (byte[])dataBlock.Clone())
+        {
+        }
+
+        public override object Clone()
+        {
+            VersionHeaderBlock block = new VersionHeaderBlock((byte[])GetDataBlockBytesReference().Clone());
+            return block;
+        }
+
+        public void SetCurrentVersion(byte[] version)
+        {
+            Array.Copy(version, GetDataBlockBytesReference(), version.Length);
+        }
+
+        /// <summary>
+        /// FileMajor - Older versions cannot not read the format.
+        /// </summary>
+        public byte FileVersionMajor
+        {
+            get
+            {
+                return GetDataBlockBytesReference()[0];
+            }
+            set
+            {
+                GetDataBlockBytesReference()[0] = value;
+            }
+        }
+
+        /// <summary>
+        /// FileMinor - Older versions can read the format, but will not retain on save.
+        /// </summary>
+        public byte FileVersionMinor
+        {
+            get
+            {
+                return GetDataBlockBytesReference()[1];
+            }
+        }
+
+        /// <summary>
+        /// Major - New release, major functionality change.
+        /// </summary>
+        public byte VersionMajor
+        {
+            get
+            {
+                return GetDataBlockBytesReference()[2];
+            }
+        }
+
+        /// <summary>
+        /// Minor - Changes, but no big deal.
+        /// </summary>
+        public byte VersionMinor
+        {
+            get
+            {
+                return GetDataBlockBytesReference()[3];
+            }
+        }
+
+        /// <summary>
+        /// Minuscule - bug fix.
+        /// </summary>
+        public byte VersionMinuscule
+        {
+            get
+            {
+                return GetDataBlockBytesReference()[4];
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IAxCryptDocument.cs b/Axantum.AxCrypt.Core/IAxCryptDocument.cs
new file mode 100644
index 0000000..faa6990
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IAxCryptDocument.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    public interface IAxCryptDocument : IDisposable
+    {
+        bool PassphraseIsValid { get; }
+
+        string FileName { get; set; }
+
+        DateTime CreationTimeUtc { get; set; }
+
+        DateTime LastAccessTimeUtc { get; set; }
+
+        DateTime LastWriteTimeUtc { get; set; }
+
+        ICryptoFactory CryptoFactory { get; }
+
+        bool Load(Passphrase key, Guid cryptoId, Stream inputStream);
+
+        void EncryptTo(Stream inputStream, Stream outputStream, AxCryptOptions options);
+
+        void DecryptTo(Stream outputPlaintextStream);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/AbstractJsonConverter.cs b/Axantum.AxCrypt.Core/IO/AbstractJsonConverter.cs
new file mode 100644
index 0000000..0ef4835
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/AbstractJsonConverter.cs
@@ -0,0 +1,26 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class AbstractJsonConverter<TAbstract, TConcrete> : JsonConverter
+    {
+        public override bool CanConvert(Type objectType)
+        {
+            return objectType == typeof(TAbstract);
+        }
+
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            return serializer.Deserialize<TConcrete>(reader);
+        }
+
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            serializer.Serialize(writer, value);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/EmailAddressJsonConverter.cs b/Axantum.AxCrypt.Core/IO/EmailAddressJsonConverter.cs
new file mode 100644
index 0000000..2eb980a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/EmailAddressJsonConverter.cs
@@ -0,0 +1,28 @@
+using Axantum.AxCrypt.Core.UI;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class EmailAddressJsonConverter : JsonConverter
+    {
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            writer.WriteValue(value.ToString());
+        }
+
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            EmailAddress mailAddress = new EmailAddress((string)reader.Value);
+            return mailAddress;
+        }
+
+        public override bool CanConvert(Type objectType)
+        {
+            return objectType == typeof(EmailAddress);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/FileInfoTypes.cs b/Axantum.AxCrypt.Core/IO/FileInfoTypes.cs
new file mode 100644
index 0000000..6c890b5
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/FileInfoTypes.cs
@@ -0,0 +1,52 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    [Flags]
+    public enum FileInfoTypes
+    {
+        None = 0,
+
+        Folder = 1,
+
+        EncryptedFile = 2,
+
+        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Encryptable")]
+        EncryptableFile = 4,
+
+        NonExisting = 8,
+
+        OtherFile = 16,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/FileLock.cs b/Axantum.AxCrypt.Core/IO/FileLock.cs
new file mode 100644
index 0000000..f43be6f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/FileLock.cs
@@ -0,0 +1,113 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class FileLock : IDisposable
+    {
+        private static Collection<string> _lockedFiles = new Collection<string>();
+
+        private string _fullPath;
+
+        private FileLock(string fullPath)
+        {
+            _fullPath = fullPath;
+        }
+
+        public static FileLock Lock(IRuntimeFileInfo fileInfo)
+        {
+            if (fileInfo == null)
+            {
+                throw new ArgumentNullException("fileInfo");
+            }
+            lock (_lockedFiles)
+            {
+                if (IsLocked(fileInfo))
+                {
+                    return null;
+                }
+                _lockedFiles.Add(fileInfo.FullName);
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Locking file '{0}'.".InvariantFormat(fileInfo.FullName));
+                }
+                return new FileLock(fileInfo.FullName);
+            }
+        }
+
+        public static bool IsLocked(params IRuntimeFileInfo[] fileInfoParameters)
+        {
+            foreach (IRuntimeFileInfo fileInfo in fileInfoParameters)
+            {
+                if (fileInfo == null)
+                {
+                    throw new ArgumentNullException("fileInfoParameters");
+                }
+                lock (_lockedFiles)
+                {
+                    if (_lockedFiles.Contains(fileInfo.FullName))
+                    {
+                        if (Instance.Log.IsInfoEnabled)
+                        {
+                            Instance.Log.LogInfo("File '{0}' was found to be locked.".InvariantFormat(fileInfo.FullName));
+                        }
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            lock (_lockedFiles)
+            {
+                if (_fullPath == null)
+                {
+                    return;
+                }
+                _lockedFiles.Remove(_fullPath);
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Unlocking file '{0}'.".InvariantFormat(_fullPath));
+                }
+                _fullPath = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/FileWatcherEventArgs.cs b/Axantum.AxCrypt.Core/IO/FileWatcherEventArgs.cs
new file mode 100644
index 0000000..5e9878f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/FileWatcherEventArgs.cs
@@ -0,0 +1,50 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class FileWatcherEventArgs : EventArgs
+    {
+        public string FullName { get; private set; }
+
+        public string OldName { get; private set; }
+
+        public FileWatcherEventArgs(string fullName)
+            : this(String.Empty, fullName)
+        {
+        }
+
+        public FileWatcherEventArgs(string oldName, string fullName)
+        {
+            OldName = oldName;
+            FullName = fullName;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/IFileWatcher.cs b/Axantum.AxCrypt.Core/IO/IFileWatcher.cs
new file mode 100644
index 0000000..69eb7e8
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/IFileWatcher.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public interface IFileWatcher : IDisposable
+    {
+        event EventHandler<FileWatcherEventArgs> FileChanged;
+
+        bool IncludeSubdirectories { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/IRuntimeFileInfo.cs b/Axantum.AxCrypt.Core/IO/IRuntimeFileInfo.cs
new file mode 100644
index 0000000..2fc1d29
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/IRuntimeFileInfo.cs
@@ -0,0 +1,154 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    /// <summary>
+    /// Abstraction for FileInfo-related operations. Provides properties and instance methods for the operations with files, and aids in the creation of Stream objects.
+    /// </summary>
+    public interface IRuntimeFileInfo
+    {
+        /// <summary>
+        /// Opens a stream in read mode for the underlying file.
+        /// </summary>
+        /// <returns>A stream opened for reading.</returns>
+        Stream OpenRead();
+
+        /// <summary>
+        /// Opens a stream in write mode for the underlying file.
+        /// </summary>
+        /// <returns>A stream opened for writing.</returns>
+        Stream OpenWrite();
+
+        /// <summary>
+        /// Determine if the file is currently unavailable for exclusive locking.
+        /// </summary>
+        /// <returns></returns>
+        bool IsLocked { get; }
+
+        /// <summary>
+        /// Creates a folder in the underlying file system with the path of this instance.
+        /// </summary>
+        void CreateFolder();
+
+        /// <summary>
+        /// Removes a folder in the underlying file system with the path of this instance,
+        /// if the folder is empty. If it is not, nothing happens.
+        /// </summary>
+        void RemoveFolder();
+
+        /// <summary>
+        /// Creates a file in the underlying system. If it already exists, an AxCryptException is thrown with status FileExists.
+        /// </summary>
+        void CreateNewFile();
+
+        /// <summary>
+        /// Get the Name part without the folder part of the path.
+        /// </summary>
+        string Name { get; }
+
+        /// <summary>
+        /// Get the full name including drive, directory and file name if any
+        /// </summary>
+        string FullName { get; }
+
+        /// <summary>
+        /// Gets or sets the creation time UTC.
+        /// </summary>
+        /// <value>
+        /// The creation time UTC.
+        /// </value>
+        DateTime CreationTimeUtc { get; set; }
+
+        /// <summary>
+        /// Gets or sets the last access time UTC.
+        /// </summary>
+        /// <value>
+        /// The last access time UTC.
+        /// </value>
+        DateTime LastAccessTimeUtc { get; set; }
+
+        /// <summary>
+        /// Gets or sets the last write time UTC.
+        /// </summary>
+        /// <value>
+        /// The last write time UTC.
+        /// </value>
+        DateTime LastWriteTimeUtc { get; set; }
+
+        /// <summary>
+        /// Sets all of the file times of the underlying file.
+        /// </summary>
+        /// <param name="creationTimeUtc">The creation time UTC.</param>
+        /// <param name="lastAccessTimeUtc">The last access time UTC.</param>
+        /// <param name="lastWriteTimeUtc">The last write time UTC.</param>
+        void SetFileTimes(DateTime creationTimeUtc, DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc);
+
+        /// <summary>
+        /// Gets a value indicating whether the file this <see cref="IRuntimeFileInfo"/> represents exists in the underlying file system and is a file.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if exists; otherwise, <c>false</c>.
+        /// </value>
+        bool IsExistingFile { get; }
+
+        /// <summary>
+        /// Moves the underlying file to a new location.
+        /// </summary>
+        /// <param name="destinationFileName">Name of the destination file.</param>
+        void MoveTo(string destinationFileName);
+
+        /// <summary>
+        /// Deletes the underlying file this instance refers to.
+        /// </summary>
+        void Delete();
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is folder that exists.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this instance is folder; otherwise, <c>false</c>.
+        /// </value>
+        bool IsExistingFolder { get; }
+
+        /// <summary>
+        /// Enumerate all files (not folders) in this folder, if it's a folder.
+        /// </summary>
+        IEnumerable<IRuntimeFileInfo> Files { get; }
+
+        /// <summary>
+        /// Combine the path of this instance with another path, creating a new instance.
+        /// </summary>
+        /// <param name="path">The path to combine with.</param>
+        /// <returns>A new instance representing the combined path.</returns>
+        IRuntimeFileInfo Combine(string path);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/IWebCaller.cs b/Axantum.AxCrypt.Core/IO/IWebCaller.cs
new file mode 100644
index 0000000..451e3bd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/IWebCaller.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public interface IWebCaller
+    {
+        string Go(Uri url);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/LockingStream.cs b/Axantum.AxCrypt.Core/IO/LockingStream.cs
new file mode 100644
index 0000000..0c8e3b7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/LockingStream.cs
@@ -0,0 +1,123 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class LockingStream : Stream
+    {
+        private Stream _stream;
+
+        private FileLock _fileLock;
+
+        public LockingStream(IRuntimeFileInfo fileInfo, Stream stream)
+        {
+            _stream = stream;
+            _fileLock = FileLock.Lock(fileInfo);
+        }
+
+        public override bool CanRead
+        {
+            get { return _stream.CanRead; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return _stream.CanSeek; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return _stream.CanWrite; }
+        }
+
+        public override void Flush()
+        {
+            _stream.Flush();
+        }
+
+        public override long Length
+        {
+            get { return _stream.Length; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _stream.Position;
+            }
+            set
+            {
+                _stream.Position = value;
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            return _stream.Read(buffer, offset, count);
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return _stream.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            _stream.SetLength(value);
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            _stream.Write(buffer, offset, count);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_fileLock != null)
+                {
+                    _fileLock.Dispose();
+                    _fileLock = null;
+                }
+                if (_stream != null)
+                {
+                    _stream.Dispose();
+                    _stream = null;
+                }
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/LookAheadStream.cs b/Axantum.AxCrypt.Core/IO/LookAheadStream.cs
new file mode 100644
index 0000000..1076858
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/LookAheadStream.cs
@@ -0,0 +1,189 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    /// <summary>
+    /// A stream wrapper with push back capability, thus enabling look ahead in the stream.
+    /// </summary>
+    public class LookAheadStream : Stream
+    {
+        private struct ByteBuffer
+        {
+            public ByteBuffer(byte[] buffer, int offset, int length)
+            {
+                Buffer = buffer;
+                Offset = offset;
+                Length = length;
+            }
+
+            public byte[] Buffer;
+            public int Offset;
+            public int Length;
+        }
+
+        private Stream _inputStream;
+
+        private bool _disposed = false;
+
+        private Stack<ByteBuffer> pushBack = new Stack<ByteBuffer>();
+
+        /// <summary>
+        /// Implement a stream wrapper with push back capability thus enabling look ahead.
+        /// </summary>
+        /// <param name="inputStream">The stream. Will be disposed when this instance is disposed.</param>
+        public LookAheadStream(Stream inputStream)
+        {
+            if (inputStream == null)
+            {
+                throw new ArgumentNullException("inputStream");
+            }
+            if (!inputStream.CanRead)
+            {
+                throw new ArgumentException("inputStream must be readable.");
+            }
+            _inputStream = inputStream;
+        }
+
+        public override bool CanRead
+        {
+            get { return true; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return false; }
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override long Length
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                throw new NotSupportedException();
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        public void Pushback(byte[] buffer, int offset, int length)
+        {
+            EnsureNotDisposed();
+            pushBack.Push(new ByteBuffer(buffer, offset, length));
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            EnsureNotDisposed();
+            int bytesRead = 0;
+            while (count > 0 && pushBack.Count > 0)
+            {
+                ByteBuffer byteBuffer = pushBack.Pop();
+                int length = byteBuffer.Length >= count ? count : byteBuffer.Length;
+                Array.Copy(byteBuffer.Buffer, byteBuffer.Offset, buffer, offset, length);
+                offset += length;
+                count -= length;
+                byteBuffer.Length -= length;
+                byteBuffer.Offset += length;
+                bytesRead += length;
+                if (byteBuffer.Length > 0)
+                {
+                    pushBack.Push(byteBuffer);
+                }
+            }
+            bytesRead += _inputStream.Read(buffer, offset, count);
+            return bytesRead;
+        }
+
+        public bool ReadExact(byte[] buffer)
+        {
+            int bytesRead = Read(buffer, 0, buffer.Length);
+
+            return bytesRead == buffer.Length;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            throw new NotSupportedException();
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_disposed)
+                {
+                    return;
+                }
+                if (_inputStream != null)
+                {
+                    _inputStream.Dispose();
+                    _inputStream = null;
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+
+        private void EnsureNotDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().FullName);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/NonClosingStream.cs b/Axantum.AxCrypt.Core/IO/NonClosingStream.cs
new file mode 100644
index 0000000..5f3615b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/NonClosingStream.cs
@@ -0,0 +1,107 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class NonClosingStream : Stream
+    {
+        private Stream _stream;
+
+        public NonClosingStream(Stream stream)
+        {
+            if (stream == null)
+            {
+                throw new ArgumentNullException("stream");
+            }
+            _stream = stream;
+        }
+
+        public override bool CanRead
+        {
+            get { return _stream.CanRead; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return _stream.CanSeek; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return _stream.CanWrite; }
+        }
+
+        public override void Flush()
+        {
+            _stream.Flush();
+        }
+
+        public override long Length
+        {
+            get { return _stream.Length; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _stream.Position;
+            }
+            set
+            {
+                _stream.Position = value;
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            return _stream.Read(buffer, offset, count);
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return _stream.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            _stream.SetLength(value);
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            _stream.Write(buffer, offset, count);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/ProgressStream.cs b/Axantum.AxCrypt.Core/IO/ProgressStream.cs
new file mode 100644
index 0000000..b32cc01
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/ProgressStream.cs
@@ -0,0 +1,151 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class ProgressStream : Stream
+    {
+        private Stream _stream;
+
+        private IProgressContext _progress;
+
+        public ProgressStream(Stream stream, IProgressContext progress)
+        {
+            if (stream == null)
+            {
+                throw new ArgumentNullException("stream");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+            _stream = stream;
+            _progress = progress;
+
+            _progress.NotifyLevelStart();
+            if (stream.CanSeek)
+            {
+                _progress.AddTotal(_stream.Length - _stream.Position);
+            }
+        }
+
+        public override bool CanRead
+        {
+            get { return _stream.CanRead; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return _stream.CanSeek; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return _stream.CanWrite; }
+        }
+
+        public override void Flush()
+        {
+            _stream.Flush();
+        }
+
+        public override long Length
+        {
+            get { return _stream.Length; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _stream.Position;
+            }
+            set
+            {
+                _stream.Position = value;
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+            int bytes = _stream.Read(buffer, offset, count);
+
+            _progress.AddCount(bytes);
+            return bytes;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return _stream.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            _stream.SetLength(value);
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            if (buffer == null)
+            {
+                throw new ArgumentNullException("buffer");
+            }
+            _stream.Write(buffer, offset, count);
+
+            _progress.AddCount(count);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+            base.Dispose(disposing);
+        }
+
+        private void DisposeInternal()
+        {
+            if (_stream == null)
+            {
+                return;
+            }
+
+            _stream.Dispose();
+            _stream = null;
+            _progress.NotifyLevelFinished();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/V1AxCryptDataStream.cs b/Axantum.AxCrypt.Core/IO/V1AxCryptDataStream.cs
new file mode 100644
index 0000000..c812946
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/V1AxCryptDataStream.cs
@@ -0,0 +1,141 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    /// <summary>
+    /// Present an input stream as having an exact limit on it's size, although the input
+    /// stream in fact may be longer.
+    /// </summary>
+    /// <remarks>Does not dispose of the input stream or the hmac stream when disposed!</remarks>
+    public class V1AxCryptDataStream : Stream
+    {
+        private Stream _inputStream;
+        private Stream _hmacStream;
+        private long _length;
+
+        private long _remaining;
+
+        /// <summary>
+        /// Wrap a general stream to serve as a stream for AxCrypt data, limited in length
+        /// and optionally sending the data to a presumed hmacStream.
+        /// </summary>
+        /// <param name="inputStream">A stream positioned at the first byte of data</param>
+        /// <param name="hmacStream">A stream where all data read is mirrored, presumably to calculate an HMAC.</param>
+        /// <param name="length">The exact number of bytes to expect and read from the input stream</param>
+        public V1AxCryptDataStream(Stream inputStream, Stream hmacStream, long length)
+        {
+            if (inputStream == null)
+            {
+                throw new ArgumentNullException("inputStream");
+            }
+            if (hmacStream == null)
+            {
+                throw new ArgumentNullException("hmacStream");
+            }
+            if (length < 0)
+            {
+                throw new ArgumentOutOfRangeException("length");
+            }
+            _inputStream = inputStream;
+            _hmacStream = hmacStream;
+            _length = length;
+            _remaining = _length;
+        }
+
+        public override bool CanRead
+        {
+            get { return true; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return true; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return false; }
+        }
+
+        public override void Flush()
+        {
+            throw new NotSupportedException();
+        }
+
+        public override long Length
+        {
+            get { return _length; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _length - _remaining;
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (_remaining == 0)
+            {
+                return 0;
+            }
+
+            int bytesToRead = _remaining < count ? (int)_remaining : count;
+            int bytesRead = _inputStream.Read(buffer, offset, bytesToRead);
+            _remaining -= bytesRead;
+
+            _hmacStream.Write(buffer, 0, bytesRead);
+
+            return bytesRead;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            throw new NotSupportedException();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/V1HmacStream.cs b/Axantum.AxCrypt.Core/IO/V1HmacStream.cs
new file mode 100644
index 0000000..7324562
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/V1HmacStream.cs
@@ -0,0 +1,200 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class V1HmacStream : Stream
+    {
+        private HashAlgorithm _hmac;
+
+        public Stream ChainedStream { get; protected set; }
+
+        private long _count = 0;
+
+        private bool _disposed = false;
+
+        /// <summary>
+        /// A AxCrypt HMAC-calculating stream. This uses the AxCrypt variant with a block size of 20 for the key.
+        /// </summary>
+        /// <param name="key">The key for the HMAC</param>
+        public V1HmacStream(SymmetricKey key)
+            : this(key, Stream.Null)
+        {
+        }
+
+        /// <summary>
+        /// An AxCrypt HMAC SHA1-calculating stream. This uses the AxCrypt variant with a block size of 20 for the key.
+        /// </summary>
+        /// <param name="key">The key for the HMAC</param>
+        /// <param name="chainedStream">A stream where data is chain-written to. This stream is not disposed of when this instance is disposed.</param>
+        public V1HmacStream(SymmetricKey key, Stream chainedStream)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            _hmac = Instance.Portable.AxCryptHMACSHA1(key);
+            ChainedStream = chainedStream;
+        }
+
+        private V1Hmac _hmacResult = null;
+
+        /// <summary>
+        /// Get the calculated HMAC
+        /// </summary>
+        /// <returns>A HMAC truncated to 128 bits</returns>
+        public Hmac HmacResult
+        {
+            get
+            {
+                EnsureNotDisposed();
+                if (_hmacResult == null)
+                {
+                    _hmac.TransformFinalBlock(new byte[] { }, 0, 0);
+                    byte[] result = new byte[16];
+                    Array.Copy(_hmac.Hash, 0, result, 0, result.Length);
+                    _hmacResult = new V1Hmac(result);
+                }
+                return _hmacResult;
+            }
+        }
+
+        public override bool CanRead
+        {
+            get { return false; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return true; }
+        }
+
+        public override long Length
+        {
+            get { return _count; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _count;
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        public override void Flush()
+        {
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            EnsureNotDisposed();
+            WriteInternal(buffer, offset, count);
+            ChainedStream.Write(buffer, offset, count);
+        }
+
+        private void WriteInternal(byte[] buffer, int offset, int count)
+        {
+            if (_hmacResult != null)
+            {
+                throw new InvalidOperationException("Cannot add to the HMAC once it has been finalized.");
+            }
+            _hmac.TransformBlock(buffer, offset, count, null, 0);
+            _count += count;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_disposed)
+                {
+                    return;
+                }
+                if (_hmac != null)
+                {
+                    _hmac.Dispose();
+                    _hmac = null;
+                }
+                _disposed = true;
+            }
+            base.Dispose(disposing);
+        }
+
+        public void ReadFrom(Stream dataStream)
+        {
+            if (dataStream == null)
+            {
+                throw new ArgumentNullException("dataStream");
+            }
+            EnsureNotDisposed();
+            byte[] buffer = new byte[OS.Current.StreamBufferSize];
+            int count;
+            while ((count = dataStream.Read(buffer, 0, buffer.Length)) != 0)
+            {
+                WriteInternal(buffer, 0, count);
+            }
+        }
+
+        private void EnsureNotDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().FullName);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/V2AxCryptDataStream.cs b/Axantum.AxCrypt.Core/IO/V2AxCryptDataStream.cs
new file mode 100644
index 0000000..246d23e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/V2AxCryptDataStream.cs
@@ -0,0 +1,240 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    /// <summary>
+    /// Read and Write data to an encrypted data stream, wrapping the data during write in EncryptedDataPartBlock
+    /// blocks. During read, interpret and strip the EncryptedDataPartBlock structure, returning raw data.
+    /// </summary>
+    public class V2AxCryptDataStream : Stream
+    {
+        public static readonly int WriteChunkSize = 65536;
+
+        private AxCryptReader _reader;
+
+        private Stream _hmacStream;
+
+        private byte[] _buffer;
+
+        private int _offset;
+
+        /// <summary>
+        /// Instantiate an instance of a stream to write to.
+        /// </summary>
+        /// <param name="hmacStream">A stream to pass all data to, typically to calculate an HMAC.</param>
+        public V2AxCryptDataStream(Stream hmacStream)
+        {
+            _hmacStream = hmacStream;
+        }
+
+        /// <summary>
+        /// Instantiate an instance of a stream to read from.
+        /// </summary>
+        /// <param name="reader">An AxCrypt reader where EnryptedDataPartBlock parts are read from.</param>
+        /// <param name="hmacStream">A stream to pass all data to, typically to calculate an HMAC.</param>
+        public V2AxCryptDataStream(AxCryptReader reader, Stream hmacStream)
+            : this(hmacStream)
+        {
+            _reader = reader;
+        }
+
+        public override bool CanRead
+        {
+            get { return _reader != null; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return _hmacStream.CanWrite; }
+        }
+
+        public override void Flush()
+        {
+            if (CanRead || _buffer == null || _offset == 0)
+            {
+                return;
+            }
+
+            byte[] buffer = _buffer;
+            if (_offset != _buffer.Length)
+            {
+                byte[] partBuffer = new byte[_offset];
+                Array.Copy(_buffer, 0, partBuffer, 0, _offset);
+                buffer = partBuffer;
+            }
+            _offset = 0;
+
+            EncryptedDataPartBlock dataPart = new EncryptedDataPartBlock(buffer);
+            dataPart.Write(_hmacStream);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                Flush();
+                base.Dispose(disposing);
+            }
+        }
+
+        public override long Length
+        {
+            get
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                throw new NotSupportedException();
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        private bool _eof = false;
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            int read = 0;
+            while (read < count)
+            {
+                if (_eof || !DataInBuffer())
+                {
+                    _eof = true;
+                    return read;
+                }
+                int available = _buffer.Length - _offset;
+                int thisread = (count - read) > available ? available : count - read;
+
+                Array.Copy(_buffer, _offset, buffer, offset, thisread);
+                offset += thisread;
+                _offset += thisread;
+                read += thisread;
+            }
+            return read;
+        }
+
+        private bool DataInBuffer()
+        {
+            if (_buffer != null && _offset < _buffer.Length)
+            {
+                return true;
+            }
+
+            if (!ReadFromReader())
+            {
+                return false;
+            }
+
+            EncryptedDataPartBlock dataPart = (EncryptedDataPartBlock)_reader.CurrentHeaderBlock;
+            _buffer = dataPart.GetDataBlockBytes();
+            _offset = 0;
+            return true;
+        }
+
+        private bool ReadFromReader()
+        {
+            if (!_reader.Read())
+            {
+                throw new FileFormatException("Unexpected end of file during read of encrypted data stream.");
+            }
+
+            if (_reader.CurrentItemType != AxCryptItemType.HeaderBlock)
+            {
+                throw new FileFormatException("Unexpected block type encountered during read of encrypted data stream.");
+            }
+
+            if (_reader.CurrentHeaderBlock.HeaderBlockType != HeaderBlockType.EncryptedDataPart)
+            {
+                return false;
+            }
+
+            _reader.CurrentHeaderBlock.Write(_hmacStream);
+            return true;
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            while (count > 0)
+            {
+                int written = WriteToBuffer(buffer, offset, count);
+                count -= written;
+                offset += written;
+            }
+        }
+
+        private int WriteToBuffer(byte[] buffer, int offset, int count)
+        {
+            if (_buffer == null)
+            {
+                _buffer = new byte[WriteChunkSize];
+                _offset = 0;
+            }
+
+            int room = _buffer.Length - _offset;
+            int written = room > count ? count : room;
+            Array.Copy(buffer, offset, _buffer, _offset, written);
+
+            _offset += written;
+            if (_offset == _buffer.Length)
+            {
+                Flush();
+            }
+
+            return written;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/IO/V2HmacStream.cs b/Axantum.AxCrypt.Core/IO/V2HmacStream.cs
new file mode 100644
index 0000000..db24ecd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/IO/V2HmacStream.cs
@@ -0,0 +1,193 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.IO
+{
+    public class V2HmacStream : Stream
+    {
+        private HashAlgorithm _hmac;
+
+        public Stream ChainedStream { get; protected set; }
+
+        private long _count = 0;
+
+        private bool _disposed = false;
+
+        /// <summary>
+        /// A AxCrypt HMAC-calculating stream.
+        /// </summary>
+        /// <param name="key">The key for the HMAC</param>
+        public V2HmacStream(byte[] key)
+            : this(key, Stream.Null)
+        {
+        }
+
+        /// <summary>
+        /// An AxCrypt HMAC-SHA-512-calculating stream.
+        /// </summary>
+        /// <param name="key">The key for the HMAC</param>
+        /// <param name="chainedStream">A stream where data is chain-written to. This stream is not disposed of when this instance is disposed.</param>
+        public V2HmacStream(byte[] key, Stream chainedStream)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+
+            _hmac = Instance.Portable.HMACSHA512(key);
+
+            ChainedStream = chainedStream;
+        }
+
+        private byte[] _hmacResult = null;
+
+        /// <summary>
+        /// Get the calculated HMAC
+        /// </summary>
+        /// <returns>The HMAC</returns>
+        public Hmac Hmac
+        {
+            get
+            {
+                EnsureNotDisposed();
+                if (_hmacResult == null)
+                {
+                    _hmac.TransformFinalBlock(new byte[] { }, 0, 0);
+                    byte[] result = new byte[_hmac.HashSize / 8];
+                    Array.Copy(_hmac.Hash, 0, result, 0, result.Length);
+                    _hmacResult = result;
+                }
+                return new V2Hmac(_hmacResult);
+            }
+        }
+
+        public override bool CanRead
+        {
+            get { return false; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return true; }
+        }
+
+        public override long Length
+        {
+            get { return _count; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _count;
+            }
+            set
+            {
+                throw new NotSupportedException();
+            }
+        }
+
+        public override void Flush()
+        {
+            ChainedStream.Flush();
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            EnsureNotDisposed();
+            WriteInternal(buffer, offset, count);
+            ChainedStream.Write(buffer, offset, count);
+        }
+
+        private void WriteInternal(byte[] buffer, int offset, int count)
+        {
+            if (_hmacResult != null)
+            {
+                return;
+            }
+            _hmac.TransformBlock(buffer, offset, count, null, 0);
+            _count += count;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+            base.Dispose(disposing);
+        }
+
+        private void DisposeInternal()
+        {
+            if (_hmac != null)
+            {
+                _hmac.Dispose();
+                _hmac = null;
+            }
+            _disposed = true;
+        }
+
+        private void EnsureNotDisposed()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException(GetType().FullName);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Instance.cs b/Axantum.AxCrypt.Core/Instance.cs
new file mode 100644
index 0000000..91e09de
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Instance.cs
@@ -0,0 +1,156 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.Ipc;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    /// <summary>
+    /// Syntactic convenience methods for accessing well-known application singleton instances.
+    /// </summary>
+    public static class Instance
+    {
+        public static void RegisterTypeFactories(string workFolderPath)
+        {
+            Factory.Instance.Singleton<KnownKeys>(() => new KnownKeys(Instance.FileSystemState, Instance.SessionNotify));
+            Factory.Instance.Singleton<UserAsymmetricKeysStore>(() => new UserAsymmetricKeysStore(Instance.WorkFolder.FileInfo, Instance.KnownKeys));
+            Factory.Instance.Singleton<ParallelFileOperation>(() => new ParallelFileOperation());
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(Instance.WorkFolder.FileInfo.Combine("FileSystemState.xml")));
+            Factory.Instance.Singleton<ProcessState>(() => new ProcessState());
+            Factory.Instance.Singleton<IUserSettings>(() => new UserSettings(Instance.WorkFolder.FileInfo.Combine("UserSettings.txt"), Factory.New<IterationCalculator>()));
+            Factory.Instance.Singleton<SessionNotify>(() => new SessionNotify());
+            Factory.Instance.Singleton<WorkFolderWatcher>(() => new WorkFolderWatcher());
+            Factory.Instance.Singleton<WorkFolder>(() => new WorkFolder(workFolderPath), () => Factory.Instance.Singleton<WorkFolderWatcher>());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new RandomGenerator());
+            Factory.Instance.Singleton<CommandHandler>(() => new CommandHandler());
+            Factory.Instance.Singleton<ActiveFileWatcher>(() => new ActiveFileWatcher());
+            Factory.Instance.Singleton<IAsymmetricFactory>(() => new BouncyCastleAsymmetricFactory());
+
+            Factory.Instance.Register<AxCryptFactory>(() => new AxCryptFactory());
+            Factory.Instance.Register<AxCryptFile>(() => new AxCryptFile());
+            Factory.Instance.Register<ActiveFileAction>(() => new ActiveFileAction());
+            Factory.Instance.Register<FileOperation>(() => new FileOperation(Instance.FileSystemState, Instance.SessionNotify));
+            Factory.Instance.Register<int, Salt>((size) => new Salt(size));
+            Factory.Instance.Register<Version, UpdateCheck>((version) => new UpdateCheck(version));
+            Factory.Instance.Register<IProgressContext, FileOperationsController>((progress) => new FileOperationsController(progress));
+            Factory.Instance.Register<IterationCalculator>(() => new IterationCalculator());
+        }
+
+        public static KnownKeys KnownKeys
+        {
+            get { return Factory.Instance.Singleton<KnownKeys>(); }
+        }
+
+        public static UserAsymmetricKeysStore AsymmetricKeysStore
+        {
+            get { return Factory.Instance.Singleton<UserAsymmetricKeysStore>(); }
+        }
+
+        public static IUIThread UIThread
+        {
+            get { return Factory.Instance.Singleton<IUIThread>(); }
+        }
+
+        public static IProgressBackground ProgressBackground
+        {
+            get { return Factory.Instance.Singleton<IProgressBackground>(); }
+        }
+
+        public static ParallelFileOperation ParallelFileOperation
+        {
+            get { return Factory.Instance.Singleton<ParallelFileOperation>(); }
+        }
+
+        public static IRuntimeEnvironment Environment
+        {
+            get { return Factory.Instance.Singleton<IRuntimeEnvironment>(); }
+        }
+
+        public static FileSystemState FileSystemState
+        {
+            get { return Factory.Instance.Singleton<FileSystemState>(); }
+        }
+
+        public static ProcessState ProcessState
+        {
+            get { return Factory.Instance.Singleton<ProcessState>(); }
+        }
+
+        public static CommandService CommandService
+        {
+            get { return Factory.Instance.Singleton<CommandService>(); }
+        }
+
+        public static IStatusChecker StatusChecker
+        {
+            get { return Factory.Instance.Singleton<IStatusChecker>(); }
+        }
+
+        public static IUserSettings UserSettings
+        {
+            get { return Factory.Instance.Singleton<IUserSettings>(); }
+        }
+
+        public static ILogging Log
+        {
+            get { return Factory.Instance.Singleton<ILogging>(); }
+        }
+
+        public static SessionNotify SessionNotify
+        {
+            get { return Factory.Instance.Singleton<SessionNotify>(); }
+        }
+
+        public static WorkFolder WorkFolder
+        {
+            get { return Factory.Instance.Singleton<WorkFolder>(); }
+        }
+
+        public static IRandomGenerator RandomGenerator
+        {
+            get { return Factory.Instance.Singleton<IRandomGenerator>(); }
+        }
+
+        public static CryptoFactory CryptoFactory
+        {
+            get { return Factory.Instance.Singleton<CryptoFactory>(); }
+        }
+
+        public static IPortableFactory Portable
+        {
+            get { return Factory.Instance.Singleton<IPortableFactory>(); }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/ArgumentBundles.cs b/Axantum.AxCrypt.Core/Ipc/ArgumentBundles.cs
new file mode 100644
index 0000000..e10340d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/ArgumentBundles.cs
@@ -0,0 +1,69 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class ArgumentBundles
+    {
+        private Dictionary<int, List<string>> _bundles = new Dictionary<int, List<string>>();
+
+        public IEnumerable<string> Arguments(int bundleId)
+        {
+            List<string> arguments;
+            lock (_bundles)
+            {
+                if (!_bundles.TryGetValue(bundleId, out arguments))
+                {
+                    return new string[0];
+                }
+                _bundles.Remove(bundleId);
+            }
+            return arguments;
+        }
+
+        public void AddArguments(int bundleId, IEnumerable<string> argumentsToAdd)
+        {
+            List<string> arguments;
+            lock (_bundles)
+            {
+                if (!_bundles.TryGetValue(bundleId, out arguments))
+                {
+                    arguments = new List<string>();
+                    _bundles.Add(bundleId, arguments);
+                }
+                foreach (string argument in argumentsToAdd)
+                {
+                    arguments.Add(argument);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandCompleteEventArgs.cs b/Axantum.AxCrypt.Core/Ipc/CommandCompleteEventArgs.cs
new file mode 100644
index 0000000..dbb8db4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandCompleteEventArgs.cs
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class CommandCompleteEventArgs : EventArgs
+    {
+        public CommandVerb Verb { get; private set; }
+
+        public IEnumerable<string> Arguments { get; private set; }
+
+        public CommandCompleteEventArgs(CommandVerb verb, IEnumerable<string> arguments)
+        {
+            Verb = verb;
+            Arguments = arguments;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandHandler.cs b/Axantum.AxCrypt.Core/Ipc/CommandHandler.cs
new file mode 100644
index 0000000..999e719
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandHandler.cs
@@ -0,0 +1,74 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class CommandHandler
+    {
+        private static ArgumentBundles _bundles = new ArgumentBundles();
+
+        public void RequestReceived(object sender, CommandServiceEventArgs e)
+        {
+            switch (e.Verb)
+            {
+                case CommandVerb.Unknown:
+                    break;
+
+                case CommandVerb.AddFiles:
+                    _bundles.AddArguments(e.BundleId, e.Arguments);
+                    break;
+
+                case CommandVerb.Encrypt:
+                case CommandVerb.Decrypt:
+                case CommandVerb.Open:
+                case CommandVerb.Wipe:
+                case CommandVerb.RandomRename:
+                    _bundles.AddArguments(e.BundleId, e.Arguments);
+                    OnCommandComplete(new CommandCompleteEventArgs(e.Verb, _bundles.Arguments(e.BundleId)));
+                    break;
+
+                default:
+                    OnCommandComplete(new CommandCompleteEventArgs(e.Verb, e.Arguments));
+                    break;
+            }
+        }
+
+        public event EventHandler<CommandCompleteEventArgs> CommandComplete;
+
+        protected virtual void OnCommandComplete(CommandCompleteEventArgs e)
+        {
+            EventHandler<CommandCompleteEventArgs> handler = CommandComplete;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandItem.cs b/Axantum.AxCrypt.Core/Ipc/CommandItem.cs
new file mode 100644
index 0000000..77515d3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandItem.cs
@@ -0,0 +1,52 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class CommandItem
+    {
+        public CommandItem(CommandVerb verb, int bundleId, IEnumerable<string> arguments)
+        {
+            Verb = verb;
+            BundleId = bundleId;
+
+            List<string> args = new List<string>();
+            args.AddRange(arguments);
+            Arguments = args;
+        }
+
+        public CommandVerb Verb { get; private set; }
+
+        public int BundleId { get; private set; }
+
+        public IEnumerable<string> Arguments { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandService.cs b/Axantum.AxCrypt.Core/Ipc/CommandService.cs
new file mode 100644
index 0000000..3eb4715
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandService.cs
@@ -0,0 +1,103 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class CommandService : IDisposable
+    {
+        private IRequestServer _server;
+        private IRequestClient _client;
+
+        public CommandService(IRequestServer server, IRequestClient client)
+        {
+            _server = server;
+            _client = client;
+
+            _server.Request += HandleServerRequest;
+        }
+
+        private void HandleServerRequest(object sender, RequestCommandEventArgs e)
+        {
+            OnReceived(e.Command);
+        }
+
+        public CommandStatus Call(CommandVerb verb, int bundleId, params string[] arguments)
+        {
+            return Call(verb, bundleId, new List<string>(arguments));
+        }
+
+        public CommandStatus Call(CommandVerb verb, int bundleId, IEnumerable<string> arguments)
+        {
+            CommandStatus status;
+            status = _client.Dispatch(new CommandServiceEventArgs(verb, bundleId, arguments));
+            return status;
+        }
+
+        public void StartListening()
+        {
+            _server.Start();
+        }
+
+        public event EventHandler<CommandServiceEventArgs> Received;
+
+        protected virtual void OnReceived(CommandServiceEventArgs e)
+        {
+            EventHandler<CommandServiceEventArgs> handler = Received;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_server != null)
+            {
+                _server.Shutdown();
+                _server = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandServiceEventArgs.cs b/Axantum.AxCrypt.Core/Ipc/CommandServiceEventArgs.cs
new file mode 100644
index 0000000..64a59a2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandServiceEventArgs.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    [JsonObject(MemberSerialization.OptIn)]
+    public class CommandServiceEventArgs : EventArgs
+    {
+        [JsonProperty("verb")]
+        public CommandVerb Verb { get; private set; }
+
+        [JsonProperty("arguments")]
+        public IList<string> Arguments { get; private set; }
+
+        [JsonProperty("bundleid")]
+        public int BundleId { get; private set; }
+
+        public CommandServiceEventArgs()
+        {
+            Verb = CommandVerb.Unknown;
+            BundleId = -1;
+            Arguments = new List<string>();
+        }
+
+        public CommandServiceEventArgs(CommandVerb verb, int bundleId, IEnumerable<string> arguments)
+        {
+            Verb = verb;
+            BundleId = bundleId;
+            Arguments = new List<string>(arguments);
+        }
+
+        public CommandServiceEventArgs(CommandVerb verb, int bundleId, params string[] arguments)
+        {
+            Verb = verb;
+            BundleId = bundleId;
+            Arguments = new List<string>(arguments);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandStatus.cs b/Axantum.AxCrypt.Core/Ipc/CommandStatus.cs
new file mode 100644
index 0000000..fee40ba
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandStatus.cs
@@ -0,0 +1,40 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public enum CommandStatus
+    {
+        Unknown,
+        Success,
+        Error,
+        NoResponse,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/CommandVerb.cs b/Axantum.AxCrypt.Core/Ipc/CommandVerb.cs
new file mode 100644
index 0000000..a240bbf
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/CommandVerb.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    [JsonConverter(typeof(StringEnumConverter))]
+    public enum CommandVerb
+    {
+        Unknown,
+        AddFiles,
+        Encrypt,
+        Decrypt,
+        Open,
+        Show,
+        Exit,
+        Wipe,
+        RandomRename,
+        About,
+        Register,
+        UseForOpen,
+        ShowLogOn,
+        SetPassphrase,
+        SetKeyFile,
+        LogOn,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/IRequestClient.cs b/Axantum.AxCrypt.Core/Ipc/IRequestClient.cs
new file mode 100644
index 0000000..d19ed76
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/IRequestClient.cs
@@ -0,0 +1,37 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public interface IRequestClient
+    {
+        CommandStatus Dispatch(CommandServiceEventArgs command);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/IRequestServer.cs b/Axantum.AxCrypt.Core/Ipc/IRequestServer.cs
new file mode 100644
index 0000000..6eac277
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/IRequestServer.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public interface IRequestServer
+    {
+        void Start();
+
+        void Shutdown();
+
+        event EventHandler<RequestCommandEventArgs> Request;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Ipc/RequestCommandEventArgs.cs b/Axantum.AxCrypt.Core/Ipc/RequestCommandEventArgs.cs
new file mode 100644
index 0000000..c0234df
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Ipc/RequestCommandEventArgs.cs
@@ -0,0 +1,42 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Ipc
+{
+    public class RequestCommandEventArgs : EventArgs
+    {
+        public CommandServiceEventArgs Command { get; private set; }
+
+        public RequestCommandEventArgs(CommandServiceEventArgs command)
+        {
+            Command = command;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/OS.cs b/Axantum.AxCrypt.Core/OS.cs
new file mode 100644
index 0000000..5b512d2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/OS.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace Axantum.AxCrypt.Core
+{
+    /// <summary>
+    /// Provides syntactically convenient access to runtime dependent instances.
+    /// </summary>
+    public static class OS
+    {
+        /// <summary>
+        /// Gets the current IRuntimeEnvironment platform dependent implementation instance.
+        /// </summary>
+        /// <value>
+        /// The current IRuntimeEnvironment platform dependent implementation instance.
+        /// </value>
+        public static IRuntimeEnvironment Current
+        {
+            get
+            {
+                return Instance.Environment;
+            }
+        }
+
+        private static readonly List<Regex> _pathFilters = new List<Regex>();
+
+        public static IList<Regex> PathFilters
+        {
+            get
+            {
+                return _pathFilters;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/AesManaged.cs b/Axantum.AxCrypt.Core/Portable/AesManaged.cs
new file mode 100644
index 0000000..ea548e7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/AesManaged.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class AesManaged : SymmetricAlgorithm
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/CipherMode.cs b/Axantum.AxCrypt.Core/Portable/CipherMode.cs
new file mode 100644
index 0000000..14aaed1
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/CipherMode.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public enum CipherMode
+    {
+        None = 0,
+        CBC,
+        ECB,
+        OFB,
+        CFB,
+        CTS,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/CryptoStream.cs b/Axantum.AxCrypt.Core/Portable/CryptoStream.cs
new file mode 100644
index 0000000..9ce4996
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/CryptoStream.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class CryptoStream : Stream
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/CryptoStreamMode.cs b/Axantum.AxCrypt.Core/Portable/CryptoStreamMode.cs
new file mode 100644
index 0000000..7a942d1
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/CryptoStreamMode.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public enum CryptoStreamMode
+    {
+        Undefined = 0,
+        Read,
+        Write,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/HMAC.cs b/Axantum.AxCrypt.Core/Portable/HMAC.cs
new file mode 100644
index 0000000..552e37e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/HMAC.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class HMAC : KeyedHashAlgorithm
+    {
+        protected int BlockSizeValue { get; set; }
+
+        public abstract string HashName { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/HMACSHA1.cs b/Axantum.AxCrypt.Core/Portable/HMACSHA1.cs
new file mode 100644
index 0000000..31323ee
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/HMACSHA1.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class HMACSHA1 : HMAC
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/HMACSHA512.cs b/Axantum.AxCrypt.Core/Portable/HMACSHA512.cs
new file mode 100644
index 0000000..d2df9a3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/HMACSHA512.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class HMACSHA512 : HMAC
+    {
+        public abstract HMACSHA512 Create(byte[] key);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/HashAlgorithm.cs b/Axantum.AxCrypt.Core/Portable/HashAlgorithm.cs
new file mode 100644
index 0000000..c085d06
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/HashAlgorithm.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class HashAlgorithm : ICryptoTransform
+    {
+        public abstract byte[] ComputeHash(byte[] buffer);
+
+        public abstract byte[] ComputeHash(byte[] buffer, int offset, int count);
+
+        public abstract byte[] ComputeHash(Stream inputStream);
+
+        public abstract byte[] Hash { get; }
+
+        public abstract int HashSize { get; }
+
+        public abstract void Initialize();
+
+        public abstract bool CanReuseTransform { get; }
+
+        public abstract bool CanTransformMultipleBlocks { get; }
+
+        public abstract int InputBlockSize { get; }
+
+        public abstract int OutputBlockSize { get; }
+
+        public abstract int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+
+        public abstract byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
+
+        public abstract void Dispose();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/ICloneable.cs b/Axantum.AxCrypt.Core/Portable/ICloneable.cs
new file mode 100644
index 0000000..3866a46
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/ICloneable.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface ICloneable
+    {
+        object Clone();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/ICryptoTransform.cs b/Axantum.AxCrypt.Core/Portable/ICryptoTransform.cs
new file mode 100644
index 0000000..c1969fa
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/ICryptoTransform.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface ICryptoTransform : IDisposable
+    {
+        bool CanReuseTransform { get; }
+
+        bool CanTransformMultipleBlocks { get; }
+
+        int InputBlockSize { get; }
+
+        int OutputBlockSize { get; }
+
+        int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+
+        byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/IDataErrorInfo.cs b/Axantum.AxCrypt.Core/Portable/IDataErrorInfo.cs
new file mode 100644
index 0000000..67affe3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/IDataErrorInfo.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface IDataErrorInfo
+    {
+        string Error { get; }
+
+        string this[string columnName] { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/IPath.cs b/Axantum.AxCrypt.Core/Portable/IPath.cs
new file mode 100644
index 0000000..021a244
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/IPath.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface IPath
+    {
+        string GetFileName(string path);
+
+        string GetDirectoryName(string path);
+
+        string GetExtension(string path);
+
+        string Combine(string left, string right);
+
+        string GetFileNameWithoutExtension(string path);
+
+        char DirectorySeparatorChar { get; }
+
+        string GetPathRoot(string path);
+
+        string GetRandomFileName();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/IPortableFactory.cs b/Axantum.AxCrypt.Core/Portable/IPortableFactory.cs
new file mode 100644
index 0000000..28b384b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/IPortableFactory.cs
@@ -0,0 +1,35 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface IPortableFactory
+    {
+        HMAC AxCryptHMACSHA1(SymmetricKey key);
+
+        HMAC HMACSHA512(byte[] key);
+
+        SymmetricAlgorithm AesManaged();
+
+        HashAlgorithm SHA1Managed();
+
+        RandomNumberGenerator RandomNumberGenerator();
+
+        Stream CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode);
+
+        ISemaphore Semaphore(int initialCount, int maximumCoiunt);
+
+        IPath Path();
+
+        IThreadWorker ThreadWorker(IProgressContext progress, bool startSerializedOnUIThread);
+
+        ISingleThread SingleThread();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/ISemaphore.cs b/Axantum.AxCrypt.Core/Portable/ISemaphore.cs
new file mode 100644
index 0000000..2f1383a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/ISemaphore.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface ISemaphore : IDisposable
+    {
+        void WaitOne();
+
+        void Release();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/ISingleThread.cs b/Axantum.AxCrypt.Core/Portable/ISingleThread.cs
new file mode 100644
index 0000000..58b95be
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/ISingleThread.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public interface ISingleThread : IDisposable
+    {
+        void Enter();
+
+        void Leave();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/KeySizes.cs b/Axantum.AxCrypt.Core/Portable/KeySizes.cs
new file mode 100644
index 0000000..d6efbc5
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/KeySizes.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public class KeySizes
+    {
+        public int MaxSize { get; set; }
+
+        public int MinSize { get; set; }
+
+        public int SkipSize { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/KeyedHashAlgorithm.cs b/Axantum.AxCrypt.Core/Portable/KeyedHashAlgorithm.cs
new file mode 100644
index 0000000..393d7d5
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/KeyedHashAlgorithm.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class KeyedHashAlgorithm : HashAlgorithm
+    {
+        public abstract byte[] Key { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/PaddingMode.cs b/Axantum.AxCrypt.Core/Portable/PaddingMode.cs
new file mode 100644
index 0000000..4b8678e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/PaddingMode.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public enum PaddingMode
+    {
+        None = 1,
+        PKCS7,
+        Zeros,
+        ANSIX923,
+        ISO10126
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/RandomNumberGenerator.cs b/Axantum.AxCrypt.Core/Portable/RandomNumberGenerator.cs
new file mode 100644
index 0000000..6abd88b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/RandomNumberGenerator.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class RandomNumberGenerator : IDisposable
+    {
+        public abstract void GetBytes(byte[] data);
+
+        public abstract void Dispose();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/SHA1Managed.cs b/Axantum.AxCrypt.Core/Portable/SHA1Managed.cs
new file mode 100644
index 0000000..1b10e10
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/SHA1Managed.cs
@@ -0,0 +1,12 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class SHA1Managed : HashAlgorithm
+    {
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Portable/SymmetricAlgorithm.cs b/Axantum.AxCrypt.Core/Portable/SymmetricAlgorithm.cs
new file mode 100644
index 0000000..15e5318
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Portable/SymmetricAlgorithm.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.Portable
+{
+    public abstract class SymmetricAlgorithm : IDisposable
+    {
+        protected KeySizes[] blockSizes;
+
+        protected KeySizes[] keySizes;
+
+        public virtual int FeedbackSize { get; set; }
+
+        private byte[] _iv;
+
+        public virtual byte[] IV
+        {
+            get
+            {
+                if (_iv == null)
+                {
+                    GenerateIV();
+                }
+                return (byte[])_iv.Clone();
+            }
+            set
+            {
+                _iv = (byte[])value.Clone();
+            }
+        }
+
+        private byte[] _key;
+
+        public virtual byte[] Key
+        {
+            get
+            {
+                if (_key == null)
+                {
+                    GenerateKey();
+                }
+                return (byte[])_key.Clone();
+            }
+            set
+            {
+                _key = (byte[])value.Clone();
+                _keySize = _key.Length * 8;
+            }
+        }
+
+        private int _keySize;
+
+        public virtual int KeySize
+        {
+            get
+            {
+                return _keySize;
+            }
+            set
+            {
+                _keySize = value;
+                _key = null;
+            }
+        }
+
+        public virtual KeySizes[] LegalBlockSizes
+        {
+            get
+            {
+                return blockSizes;
+            }
+        }
+
+        public virtual KeySizes[] LegalKeySizes
+        {
+            get
+            {
+                return keySizes;
+            }
+        }
+
+        public virtual CipherMode Mode { get; set; }
+
+        public virtual PaddingMode Padding { get; set; }
+
+        public virtual bool ValidKeySize(int bitLength)
+        {
+            foreach (KeySizes sizes in keySizes)
+            {
+                for (int length = sizes.MinSize; length <= sizes.MaxSize; length += sizes.SkipSize)
+                {
+                    if (length == bitLength)
+                    {
+                        return true;
+                    }
+                    if (sizes.SkipSize == 0)
+                    {
+                        break;
+                    }
+                }
+            }
+            return false;
+        }
+
+        public virtual void Clear()
+        {
+            Dispose();
+        }
+
+        private int _blockSize;
+
+        public virtual int BlockSize
+        {
+            get
+            {
+                return _blockSize;
+            }
+            set
+            {
+                _blockSize = value;
+                _iv = null;
+            }
+        }
+
+        public virtual ICryptoTransform CreateDecryptor()
+        {
+            return CreateDecryptor(_key, _iv);
+        }
+
+        public abstract ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV);
+
+        public virtual ICryptoTransform CreateEncryptor()
+        {
+            return CreateEncryptor(_key, _iv);
+        }
+
+        public abstract ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV);
+
+        public abstract void GenerateIV();
+
+        public abstract void GenerateKey();
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            if (_key != null)
+            {
+                Array.Clear(_key, 0, _key.Length);
+                _key = null;
+            }
+            if (_iv != null)
+            {
+                Array.Clear(_iv, 0, _iv.Length);
+                _iv = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Core/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..823e19d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Properties/AssemblyInfo.cs
@@ -0,0 +1,67 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is strong named when deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AxCrypt Core Encryption Library")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © Svante Seleborg 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+#endif
+
+[module: SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", Scope = "namespace", Target = "Axantum.AxCrypt.Core.Ipc", MessageId = "Ipc")]
+[module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Axantum.AxCrypt.Core.Reader")]
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Properties/AssemblyInfo.template b/Axantum.AxCrypt.Core/Properties/AssemblyInfo.template
new file mode 100644
index 0000000..d4df9ab
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Properties/AssemblyInfo.template
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyFileVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyInformationalVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyConfiguration("")]
diff --git a/Axantum.AxCrypt.Core/Properties/Resources.Designer.cs b/Axantum.AxCrypt.Core/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..35c24c3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Properties/Resources.Designer.cs
@@ -0,0 +1,89 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Axantum.AxCrypt.Core.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Axantum.AxCrypt.Core.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+        ///
+        ///Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following  [rest of string was truncated]";.
+        /// </summary>
+        internal static string bouncycastlelicense {
+            get {
+                return ResourceManager.GetString("bouncycastlelicense", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The MIT License (MIT)
+        ///
+        ///Copyright (c) 2007 James Newton-King
+        ///
+        ///Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+        ///
+        ///The above c [rest of string was truncated]";.
+        /// </summary>
+        internal static string json_netlicense {
+            get {
+                return ResourceManager.GetString("json_netlicense", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Core/Properties/Resources.resx b/Axantum.AxCrypt.Core/Properties/Resources.resx
new file mode 100644
index 0000000..a583b3d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Properties/Resources.resx
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="bouncycastlelicense" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\bouncycastlelicense.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="json_netlicense" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\json.netlicense.txt;System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Reader/AxCryptItemType.cs b/Axantum.AxCrypt.Core/Reader/AxCryptItemType.cs
new file mode 100644
index 0000000..2bb7a1c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Reader/AxCryptItemType.cs
@@ -0,0 +1,63 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.Reader
+{
+    public enum AxCryptItemType
+    {
+        /// <summary>
+        /// Initial state before we have read any items at all, or an error state when
+        /// what was expected was not found.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// We have seen the AxCrypt Guid
+        /// </summary>
+        MagicGuid,
+
+        /// <summary>
+        /// A header block of HeaderBlockType has been found
+        /// </summary>
+        HeaderBlock,
+
+        /// <summary>
+        /// A (part) of Encrypted and possibly Compressed data has been found
+        /// </summary>
+        Data,
+
+        /// <summary>
+        /// The end of the stream has been reached
+        /// </summary>
+        EndOfStream,
+
+        /// <summary>
+        /// An undefined item type that should never occur, used for unit testing.
+        /// </summary>
+        Undefined,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Reader/AxCryptReader.cs b/Axantum.AxCrypt.Core/Reader/AxCryptReader.cs
new file mode 100644
index 0000000..77f9d08
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Reader/AxCryptReader.cs
@@ -0,0 +1,259 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Reader
+{
+    public abstract class AxCryptReader : IDisposable
+    {
+        public LookAheadStream InputStream { get; set; }
+
+        /// <summary>
+        /// Implement an AxCryptReader based on a Stream.
+        /// </summary>
+        /// <param name="inputStream">The stream. Will be disposed when this instance is disposed.</param>
+        protected AxCryptReader(Stream inputStream)
+        {
+            if (inputStream == null)
+            {
+                throw new ArgumentNullException("inputStream");
+            }
+            LookAheadStream lookAheadStream = inputStream as LookAheadStream;
+            if (lookAheadStream == null)
+            {
+                lookAheadStream = new LookAheadStream(inputStream);
+            }
+            InputStream = lookAheadStream;
+        }
+
+        public virtual void Reinterpret(IList<HeaderBlock> inputHeaders, IList<HeaderBlock> outputHeaders)
+        {
+            outputHeaders.Clear();
+            foreach (HeaderBlock header in inputHeaders)
+            {
+                outputHeaders.Add(HeaderBlockFactory(header.HeaderBlockType, header.GetDataBlockBytes()));
+            }
+            CurrentItemType = AxCryptItemType.Data;
+        }
+
+        public abstract IAxCryptDocument Document(Passphrase key, Guid cryptoId, Headers headers);
+
+        /// <summary>
+        /// Gets the type of the current item
+        /// </summary>
+        public virtual AxCryptItemType CurrentItemType { get; protected set; }
+
+        public HeaderBlock CurrentHeaderBlock { get; private set; }
+
+        protected abstract HeaderBlock HeaderBlockFactory(HeaderBlockType headerBlockType, byte[] dataBlock);
+
+        /// <summary>
+        /// Read the next item from the stream.
+        /// </summary>
+        /// <returns>true if there was a next item read, false if at end of stream.</returns>
+        /// <exception cref="Axantum.AxCrypt.Core.AxCryptException">Any error except premature end of stream will throw.</exception>
+        public virtual bool Read()
+        {
+            if (InputStream == null)
+            {
+                throw new ObjectDisposedException(GetType().FullName);
+            }
+            AxCryptItemType before = CurrentItemType;
+            bool readOk = ReadInternal();
+            AxCryptItemType after = CurrentItemType;
+            if (Instance.Log.IsDebugEnabled)
+            {
+                Instance.Log.LogDebug("AxCryptReader.Read() from type {0} to type {1} : {2}.".InvariantFormat(before, after, CurrentHeaderBlock == null ? "(None)" : CurrentHeaderBlock.GetType().ToString()));
+            }
+            return readOk;
+        }
+
+        public void SetEndOfStream()
+        {
+            CurrentItemType = AxCryptItemType.EndOfStream;
+        }
+
+        public void SetStartOfData()
+        {
+            CurrentItemType = AxCryptItemType.HeaderBlock;
+        }
+
+        private bool ReadInternal()
+        {
+            switch (CurrentItemType)
+            {
+                case AxCryptItemType.None:
+                    LookForMagicGuid();
+                    return CurrentItemType != AxCryptItemType.EndOfStream;
+
+                case AxCryptItemType.MagicGuid:
+                case AxCryptItemType.HeaderBlock:
+                    LookForHeaderBlock();
+                    return CurrentItemType != AxCryptItemType.EndOfStream;
+
+                case AxCryptItemType.Data:
+                    return false;
+
+                case AxCryptItemType.EndOfStream:
+                    return false;
+
+                default:
+                    throw new InternalErrorException("An AxCryptItemType that should not be possible to get was found.");
+            }
+        }
+
+        private static readonly byte[] _axCrypt1GuidBytes = AxCrypt1Guid.GetBytes();
+
+        private void LookForMagicGuid()
+        {
+            byte[] buffer = new byte[OS.Current.StreamBufferSize];
+            while (true)
+            {
+                int bytesRead = InputStream.Read(buffer, 0, buffer.Length);
+                if (bytesRead < AxCrypt1Guid.Length)
+                {
+                    InputStream.Pushback(buffer, 0, bytesRead);
+                    CurrentItemType = AxCryptItemType.EndOfStream;
+                    return;
+                }
+
+                int i = buffer.Locate(_axCrypt1GuidBytes, 0, bytesRead);
+                if (i < 0)
+                {
+                    int offsetToBytesToKeep = bytesRead - AxCrypt1Guid.Length + 1;
+                    InputStream.Pushback(buffer, offsetToBytesToKeep, bytesRead - offsetToBytesToKeep);
+                    continue;
+                }
+                int offsetJustAfterTheGuid = i + AxCrypt1Guid.Length;
+                InputStream.Pushback(buffer, offsetJustAfterTheGuid, bytesRead - offsetJustAfterTheGuid);
+                CurrentItemType = AxCryptItemType.MagicGuid;
+                return;
+            }
+        }
+
+        private void LookForHeaderBlock()
+        {
+            byte[] lengthBytes = new byte[sizeof(Int32)];
+            if (!InputStream.ReadExact(lengthBytes))
+            {
+                CurrentItemType = AxCryptItemType.EndOfStream;
+                return;
+            }
+            Int32 headerBlockLength = BitConverter.ToInt32(lengthBytes, 0) - 5;
+            if (headerBlockLength < 0 || headerBlockLength > 0xfffff)
+            {
+                throw new FileFormatException("Invalid headerBlockLength {0}".InvariantFormat(headerBlockLength), ErrorStatus.FileFormatError);
+            }
+
+            int blockType = InputStream.ReadByte();
+            if (blockType > 127)
+            {
+                throw new FileFormatException("Invalid block type {0}".InvariantFormat(blockType), ErrorStatus.FileFormatError);
+            }
+            HeaderBlockType headerBlockType = (HeaderBlockType)blockType;
+
+            byte[] dataBlock = new byte[headerBlockLength];
+            if (!InputStream.ReadExact(dataBlock))
+            {
+                CurrentItemType = AxCryptItemType.EndOfStream;
+                return;
+            }
+
+            ParseHeaderBlock(headerBlockType, dataBlock);
+
+            DataHeaderBlock dataHeaderBlock = CurrentHeaderBlock as DataHeaderBlock;
+            if (dataHeaderBlock != null)
+            {
+                CurrentItemType = AxCryptItemType.Data;
+            }
+        }
+
+        private void ParseHeaderBlock(HeaderBlockType headerBlockType, byte[] dataBlock)
+        {
+            bool isFirst = CurrentItemType == AxCryptItemType.MagicGuid;
+            switch (headerBlockType)
+            {
+                case HeaderBlockType.Preamble:
+                    if (!isFirst)
+                    {
+                        throw new FileFormatException("Preamble can only be first.", ErrorStatus.FileFormatError);
+                    }
+                    break;
+
+                case HeaderBlockType.Encrypted:
+                case HeaderBlockType.None:
+                case HeaderBlockType.Any:
+                    throw new FileFormatException("Illegal header block type.", ErrorStatus.FileFormatError);
+                default:
+                    if (isFirst)
+                    {
+                        throw new FileFormatException("Preamble must be first.", ErrorStatus.FileFormatError);
+                    }
+                    break;
+            }
+
+            CurrentItemType = AxCryptItemType.HeaderBlock;
+            CurrentHeaderBlock = HeaderBlockFactory(headerBlockType, dataBlock);
+            return;
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (InputStream != null)
+            {
+                InputStream.Dispose();
+                InputStream = null;
+            }
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Reader/V1AxCryptReader.cs b/Axantum.AxCrypt.Core/Reader/V1AxCryptReader.cs
new file mode 100644
index 0000000..590dabd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Reader/V1AxCryptReader.cs
@@ -0,0 +1,98 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Reader
+{
+    public class V1AxCryptReader : AxCryptReader
+    {
+        /// <summary>
+        /// Instantiate an AxCryptReader from a stream.
+        /// </summary>
+        /// <param name="inputStream">The stream to read from, will be disposed when this instance is disposed.</param>
+        /// <returns></returns>
+        public V1AxCryptReader(Stream inputStream)
+            : base(inputStream)
+        {
+        }
+
+        protected override HeaderBlock HeaderBlockFactory(HeaderBlockType headerBlockType, byte[] dataBlock)
+        {
+            switch (headerBlockType)
+            {
+                case HeaderBlockType.Preamble:
+                    return new PreambleHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Version:
+                    return new VersionHeaderBlock(dataBlock);
+
+                case HeaderBlockType.KeyWrap1:
+                    return new V1KeyWrap1HeaderBlock(dataBlock);
+
+                case HeaderBlockType.KeyWrap2:
+                    return new V1KeyWrap2HeaderBlock(dataBlock);
+
+                case HeaderBlockType.IdTag:
+                    return new V1IdTagHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Data:
+                    return new DataHeaderBlock(dataBlock);
+
+                case HeaderBlockType.FileNameInfo:
+                    return new V1FileNameInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.EncryptionInfo:
+                    return new V1EncryptionInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.CompressionInfo:
+                    return new V1CompressionInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.FileInfo:
+                    return new FileInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Compression:
+                    return new V1CompressionEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.UnicodeFileNameInfo:
+                    return new V1UnicodeFileNameInfoEncryptedHeaderBlock(dataBlock);
+            }
+            return new UnrecognizedHeaderBlock(headerBlockType, dataBlock);
+        }
+
+        public override IAxCryptDocument Document(Passphrase key, Guid cryptoId, Headers headers)
+        {
+            V1AxCryptDocument v1Document = new V1AxCryptDocument();
+            v1Document.Load(key, this, headers);
+
+            return v1Document;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Reader/V2AxCryptReader.cs b/Axantum.AxCrypt.Core/Reader/V2AxCryptReader.cs
new file mode 100644
index 0000000..0f6fe53
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Reader/V2AxCryptReader.cs
@@ -0,0 +1,92 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core.Reader
+{
+    public class V2AxCryptReader : AxCryptReader
+    {
+        /// <summary>
+        /// Instantiate an AxCryptReader from a stream.
+        /// </summary>
+        /// <param name="inputStream">The stream to read from, will be disposed when this instance is disposed.</param>
+        /// <returns></returns>
+        public V2AxCryptReader(Stream inputStream)
+            : base(inputStream)
+        {
+        }
+
+        protected override HeaderBlock HeaderBlockFactory(HeaderBlockType headerBlockType, byte[] dataBlock)
+        {
+            switch (headerBlockType)
+            {
+                case HeaderBlockType.Preamble:
+                    return new PreambleHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Version:
+                    return new VersionHeaderBlock(dataBlock);
+
+                case HeaderBlockType.V2KeyWrap:
+                    return new V2KeyWrapHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Data:
+                    return new DataHeaderBlock(dataBlock);
+
+                case HeaderBlockType.FileInfo:
+                    return new FileInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Compression:
+                    return new V2CompressionEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.UnicodeFileNameInfo:
+                    return new V2UnicodeFileNameInfoEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.PlaintextLengths:
+                    return new V2PlaintextLengthsEncryptedHeaderBlock(dataBlock);
+
+                case HeaderBlockType.V2Hmac:
+                    return new V2HmacHeaderBlock(dataBlock);
+
+                case HeaderBlockType.EncryptedDataPart:
+                    return new EncryptedDataPartBlock(dataBlock);
+            }
+            return new UnrecognizedHeaderBlock(headerBlockType, dataBlock);
+        }
+
+        public override IAxCryptDocument Document(Passphrase key, Guid cryptoId, Headers headers)
+        {
+            V2AxCryptDocument v2Document = new V2AxCryptDocument();
+            v2Document.Load(key, cryptoId, this, headers);
+
+            return v2Document;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Reader/VxAxCryptReader.cs b/Axantum.AxCrypt.Core/Reader/VxAxCryptReader.cs
new file mode 100644
index 0000000..2064c3f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Reader/VxAxCryptReader.cs
@@ -0,0 +1,82 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Header;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Reader
+{
+    public class VXAxCryptReader : AxCryptReader
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="VXAxCryptReader"/> class.
+        /// </summary>
+        /// <param name="inputStream">The stream. Will NOT be disposed when this instance is disposed.</param>
+        public VXAxCryptReader(Stream inputStream)
+            : base(inputStream)
+        {
+        }
+
+        protected override HeaderBlock HeaderBlockFactory(HeaderBlockType headerBlockType, byte[] dataBlock)
+        {
+            switch (headerBlockType)
+            {
+                case HeaderBlockType.Preamble:
+                    return new PreambleHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Version:
+                    return new VersionHeaderBlock(dataBlock);
+
+                case HeaderBlockType.Data:
+                    return new DataHeaderBlock(dataBlock);
+            }
+            return new UnrecognizedHeaderBlock(headerBlockType, dataBlock);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                PreventInputStreamDispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        private void PreventInputStreamDispose()
+        {
+            InputStream = null;
+        }
+
+        public override IAxCryptDocument Document(Passphrase key, Guid cryptoId, Headers headers)
+        {
+            throw new NotImplementedException();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/AxCryptException.cs b/Axantum.AxCrypt.Core/Runtime/AxCryptException.cs
new file mode 100644
index 0000000..7d95189
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/AxCryptException.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public abstract class AxCryptException : Exception
+    {
+        public ErrorStatus ErrorStatus { get; set; }
+
+        public string DisplayContext { get; set; }
+
+        protected AxCryptException()
+            : base()
+        {
+            ErrorStatus = ErrorStatus.Unknown;
+        }
+
+        protected AxCryptException(string message, ErrorStatus errorStatus)
+            : base(message)
+        {
+            ErrorStatus = errorStatus;
+        }
+
+        protected AxCryptException(string message, ErrorStatus errorStatus, Exception innerException)
+            : base(message, innerException)
+        {
+            ErrorStatus = errorStatus;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/DelayedAction.cs b/Axantum.AxCrypt.Core/Runtime/DelayedAction.cs
new file mode 100644
index 0000000..1405191
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/DelayedAction.cs
@@ -0,0 +1,111 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    /// <summary>
+    /// Delay an action for a minimum time, if action request occur while in a delay, the delay is extended.
+    /// In effect, delay an action until a minimum idle time has passed.
+    /// </summary>
+    public class DelayedAction : IDisposable
+    {
+        private IDelayTimer _timer;
+
+        /// <summary>
+        /// The action to perform after the specified idle time.
+        /// </summary>
+        public event EventHandler Action;
+
+        protected virtual void OnAction()
+        {
+            EventHandler handler = Action;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        /// <summary>
+        /// Create an instance bound to an action delegate and a minimum idle time.
+        /// </summary>
+        /// <param name="minimumIdleTime">The minium time of idle before actually performing the action.</param>
+        public DelayedAction(IDelayTimer timer, TimeSpan minimumIdleTime)
+        {
+            _timer = timer;
+            _timer.SetInterval(minimumIdleTime);
+            _timer.Elapsed += HandleTimerElapsedEvent;
+        }
+
+        private void HandleTimerElapsedEvent(object sender, EventArgs e)
+        {
+            if (_timer != null)
+            {
+                OnAction();
+            }
+        }
+
+        /// <summary>
+        /// (Re)Start the idle timeer.
+        /// </summary>
+        public void StartIdleTimer()
+        {
+            if (_timer == null)
+            {
+                throw new ObjectDisposedException("_timer");
+            }
+            _timer.Start();
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources.
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (_timer != null)
+                {
+                    _timer.Dispose();
+                    _timer = null;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/FileFormatException.cs b/Axantum.AxCrypt.Core/Runtime/FileFormatException.cs
new file mode 100644
index 0000000..11f71e2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/FileFormatException.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class FileFormatException : AxCryptException
+    {
+        public FileFormatException()
+            : base()
+        {
+        }
+
+        public FileFormatException(string message)
+            : this(message, ErrorStatus.FileFormatError)
+        {
+        }
+
+        public FileFormatException(string message, ErrorStatus errorStatus)
+            : base(message, errorStatus)
+        {
+        }
+
+        public FileFormatException(string message, Exception innerException)
+            : this(message, ErrorStatus.FileFormatError, innerException)
+        {
+        }
+
+        public FileFormatException(string message, ErrorStatus errorStatus, Exception innerException)
+            : base(message, errorStatus, innerException)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/IDataProtection.cs b/Axantum.AxCrypt.Core/Runtime/IDataProtection.cs
new file mode 100644
index 0000000..e6ae863
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/IDataProtection.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface IDataProtection
+    {
+        byte[] Protect(byte[] unprotectedData);
+
+        byte[] Unprotect(byte[] protectedData);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/IDelayTimer.cs b/Axantum.AxCrypt.Core/Runtime/IDelayTimer.cs
new file mode 100644
index 0000000..34bb430
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/IDelayTimer.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface IDelayTimer : IDisposable
+    {
+        void SetInterval(TimeSpan interval);
+
+        event EventHandler<EventArgs> Elapsed;
+
+        void Start();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ILauncher.cs b/Axantum.AxCrypt.Core/Runtime/ILauncher.cs
new file mode 100644
index 0000000..3a5c736
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ILauncher.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface ILauncher : IDisposable
+    {
+        event EventHandler Exited;
+
+        bool HasExited { get; }
+
+        bool WasStarted { get; }
+
+        string Path { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ILogging.cs b/Axantum.AxCrypt.Core/Runtime/ILogging.cs
new file mode 100644
index 0000000..cec1bb0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ILogging.cs
@@ -0,0 +1,59 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface ILogging : IDisposable
+    {
+        event EventHandler<LoggingEventArgs> Logged;
+
+        void SetLevel(LogLevel level);
+
+        bool IsFatalEnabled { get; }
+
+        bool IsErrorEnabled { get; }
+
+        bool IsWarningEnabled { get; }
+
+        bool IsInfoEnabled { get; }
+
+        bool IsDebugEnabled { get; }
+
+        void LogFatal(string message);
+
+        void LogError(string message);
+
+        void LogWarning(string message);
+
+        void LogInfo(string message);
+
+        void LogDebug(string message);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/IRuntimeEnvironment.cs b/Axantum.AxCrypt.Core/Runtime/IRuntimeEnvironment.cs
new file mode 100644
index 0000000..03c2f76
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/IRuntimeEnvironment.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface IRuntimeEnvironment
+    {
+        bool IsLittleEndian { get; }
+
+        string AxCryptExtension { get; }
+
+        Platform Platform { get; }
+
+        int StreamBufferSize { get; }
+
+        DateTime UtcNow { get; }
+
+        ILauncher Launch(string path);
+
+        ITiming StartTiming();
+
+        IWebCaller CreateWebCaller();
+
+        bool CanTrackProcess { get; }
+
+        string EnvironmentVariable(string name);
+
+        int MaxConcurrency { get; }
+
+        bool IsFirstInstance { get; }
+
+        bool FirstInstanceRunning(TimeSpan timeout);
+
+        void ExitApplication(int exitCode);
+
+        void DebugMode(bool enable);
+
+        SynchronizationContext SynchronizationContext { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ISleep.cs b/Axantum.AxCrypt.Core/Runtime/ISleep.cs
new file mode 100644
index 0000000..e78826e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ISleep.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface ISleep
+    {
+        void Time(TimeSpan value);
+
+        event EventHandler<SleepEventArgs> Elapsed;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/IThreadWorker.cs b/Axantum.AxCrypt.Core/Runtime/IThreadWorker.cs
new file mode 100644
index 0000000..986cd86
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/IThreadWorker.cs
@@ -0,0 +1,81 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface IThreadWorker : IDisposable
+    {
+        /// <summary>
+        /// Start the asynchronous execution of the work.
+        /// </summary>
+        void Run();
+
+        /// <summary>
+        /// Perform blocking wait until this thread has completed execution.
+        /// </summary>
+        void Join();
+
+        /// <summary>
+        /// Abort this thread - can only be called *before* Run() has been called.
+        /// </summary>
+        void Abort();
+
+        /// <summary>
+        /// Returns true if the thread has completed execution.
+        /// </summary>
+        bool HasCompleted { get; }
+
+        /// <summary>
+        /// Raised just before asynchronous execution starts. Runs on the
+        /// original thread, typically the GUI thread.
+        /// </summary>
+        event EventHandler<ThreadWorkerEventArgs> Prepare;
+
+        /// <summary>
+        /// Raised when asynchronous execution starts. Runs on a different
+        /// thread than the caller thread. Do not interact with the GUI here.
+        /// </summary>
+        event EventHandler<ThreadWorkerEventArgs> Work;
+
+        /// <summary>
+        /// Raised when all is about to be done. Runs on the original thread, typically
+        /// the GUI thread.
+        /// </summary>
+        event EventHandler<ThreadWorkerEventArgs> Completing;
+
+        /// <summary>
+        /// Raised when all is done. Runs on the original thread, typically
+        /// the GUI thread.
+        /// </summary>
+        event EventHandler<ThreadWorkerEventArgs> Completed;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ITiming.cs b/Axantum.AxCrypt.Core/Runtime/ITiming.cs
new file mode 100644
index 0000000..3409cdb
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ITiming.cs
@@ -0,0 +1,37 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public interface ITiming
+    {
+        TimeSpan Elapsed { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/IncorrectDataException.cs b/Axantum.AxCrypt.Core/Runtime/IncorrectDataException.cs
new file mode 100644
index 0000000..2f5f82a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/IncorrectDataException.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class IncorrectDataException : AxCryptException
+    {
+        public IncorrectDataException()
+            : base()
+        {
+        }
+
+        public IncorrectDataException(string message)
+            : this(message, ErrorStatus.DataError)
+        {
+        }
+
+        public IncorrectDataException(string message, ErrorStatus errorStatus)
+            : base(message, errorStatus)
+        {
+        }
+
+        public IncorrectDataException(string message, Exception innerException)
+            : this(message, ErrorStatus.DataError, innerException)
+        {
+        }
+
+        public IncorrectDataException(string message, ErrorStatus errorStatus, Exception innerException)
+            : base(message, errorStatus, innerException)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/InternalErrorException.cs b/Axantum.AxCrypt.Core/Runtime/InternalErrorException.cs
new file mode 100644
index 0000000..d4638c7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/InternalErrorException.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    /// <summary>
+    /// An internal program logic error in the library itself has been detected. Use InvalidOperationException for invalid
+    /// program states typically caused by caller errors.
+    /// </summary>
+    public class InternalErrorException : AxCryptException
+    {
+        public InternalErrorException()
+            : base()
+        {
+        }
+
+        public InternalErrorException(string message)
+            : base(message, ErrorStatus.InternalError)
+        {
+        }
+
+        public InternalErrorException(string message, ErrorStatus errorStatus)
+            : base(message, errorStatus)
+        {
+        }
+
+        public InternalErrorException(string message, Exception innerException)
+            : this(message, ErrorStatus.InternalError, innerException)
+        {
+        }
+
+        public InternalErrorException(string message, ErrorStatus errorStatus, Exception innerException)
+            : base(message, errorStatus, innerException)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/LogLevel.cs b/Axantum.AxCrypt.Core/Runtime/LogLevel.cs
new file mode 100644
index 0000000..1d56829
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/LogLevel.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public enum LogLevel
+    {
+        Fatal,
+        Error,
+        Warning,
+        Info,
+        Debug,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/LoggingEventArgs.cs b/Axantum.AxCrypt.Core/Runtime/LoggingEventArgs.cs
new file mode 100644
index 0000000..5f36ed3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/LoggingEventArgs.cs
@@ -0,0 +1,42 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class LoggingEventArgs : EventArgs
+    {
+        public string Message { get; private set; }
+
+        public LoggingEventArgs(string message)
+        {
+            Message = message;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/Platform.cs b/Axantum.AxCrypt.Core/Runtime/Platform.cs
new file mode 100644
index 0000000..98441b2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/Platform.cs
@@ -0,0 +1,47 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public enum Platform
+    {
+        Unknown,
+        WindowsDesktop,
+        WindowsMobile,
+        WindowsPhone,
+        Linux,
+        AppleIos,
+        MacOsx,
+        Android,
+        Xbox,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/SleepEventArgs.cs b/Axantum.AxCrypt.Core/Runtime/SleepEventArgs.cs
new file mode 100644
index 0000000..cbceeca
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/SleepEventArgs.cs
@@ -0,0 +1,42 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class SleepEventArgs : EventArgs
+    {
+        public TimeSpan Time { get; private set; }
+
+        public SleepEventArgs(TimeSpan time)
+        {
+            Time = time;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ThreadWorkerEventArgs.cs b/Axantum.AxCrypt.Core/Runtime/ThreadWorkerEventArgs.cs
new file mode 100644
index 0000000..7d802d4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ThreadWorkerEventArgs.cs
@@ -0,0 +1,51 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.UI;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class ThreadWorkerEventArgs : EventArgs
+    {
+        public ThreadWorkerEventArgs(IProgressContext progress)
+        {
+            Progress = progress;
+            Result = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+        }
+
+        public int ProgressPercentage { get; set; }
+
+        public IProgressContext Progress { get; private set; }
+
+        public FileOperationContext Result { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/ThreadWorkerProgressContext.cs b/Axantum.AxCrypt.Core/Runtime/ThreadWorkerProgressContext.cs
new file mode 100644
index 0000000..032678a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/ThreadWorkerProgressContext.cs
@@ -0,0 +1,126 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class ThreadWorkerProgressContext : IProgressContext
+    {
+        private IProgressContext _progress;
+
+        private bool _isSingleThread;
+
+        public ThreadWorkerProgressContext(IProgressContext progress)
+        {
+            _progress = progress;
+        }
+
+        public event EventHandler<ProgressEventArgs> Progressing
+        {
+            add
+            {
+                _progress.Progressing += value;
+            }
+            remove
+            {
+                _progress.Progressing -= value;
+            }
+        }
+
+        public void RemoveCount(long totalCount, long progressCount)
+        {
+            _progress.RemoveCount(totalCount, progressCount);
+        }
+
+        public void AddTotal(long count)
+        {
+            _progress.AddTotal(count);
+        }
+
+        public void AddCount(long count)
+        {
+            _progress.AddCount(count);
+        }
+
+        public void NotifyLevelStart()
+        {
+            _progress.NotifyLevelStart();
+        }
+
+        public void NotifyLevelFinished()
+        {
+            _progress.NotifyLevelFinished();
+        }
+
+        public bool Cancel
+        {
+            get
+            {
+                return _progress.Cancel;
+            }
+            set
+            {
+                _progress.Cancel = value;
+            }
+        }
+
+        public bool AllItemsConfirmed
+        {
+            get
+            {
+                return _progress.AllItemsConfirmed;
+            }
+            set
+            {
+                _progress.AllItemsConfirmed = value;
+            }
+        }
+
+        public void EnterSingleThread()
+        {
+            if (_isSingleThread)
+            {
+                return;
+            }
+            _progress.EnterSingleThread();
+            _isSingleThread = true;
+        }
+
+        public void LeaveSingleThread()
+        {
+            if (!_isSingleThread)
+            {
+                return;
+            }
+            _progress.LeaveSingleThread();
+            _isSingleThread = false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/TypeDiscovery.cs b/Axantum.AxCrypt.Core/Runtime/TypeDiscovery.cs
new file mode 100644
index 0000000..306b15f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/TypeDiscovery.cs
@@ -0,0 +1,66 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public static class TypeDiscovery
+    {
+        public static IEnumerable<Type> Interface(Type interfaceToDiscover, IEnumerable<Assembly> extraAssemblies)
+        {
+            List<Type> interfaces = new List<Type>();
+            foreach (Assembly assembly in new Assembly[] { interfaceToDiscover.Assembly }.Concat(extraAssemblies))
+            {
+                try
+                {
+                    ScanAssemblyForNewInterfaces(interfaceToDiscover, assembly, interfaces);
+                }
+                catch (TypeLoadException)
+                {
+                }
+            }
+            return interfaces;
+        }
+
+        private static void ScanAssemblyForNewInterfaces(Type interfaceToDiscover, Assembly assembly, IList<Type> interfaces)
+        {
+            IEnumerable<Type> types = from t in assembly.GetExportedTypes() where t.GetInterfaces().Contains(interfaceToDiscover) select t;
+
+            foreach (Type t in types)
+            {
+                if (!interfaces.Any(i => i.FullName == t.FullName))
+                {
+                    interfaces.Add(t);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/WorkFolder.cs b/Axantum.AxCrypt.Core/Runtime/WorkFolder.cs
new file mode 100644
index 0000000..dd9ddbd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/WorkFolder.cs
@@ -0,0 +1,44 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class WorkFolder
+    {
+        public WorkFolder(string path)
+        {
+            FileInfo = Factory.New<IRuntimeFileInfo>(path);
+            FileInfo.CreateFolder();
+        }
+
+        public IRuntimeFileInfo FileInfo { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/WorkFolderWatcher.cs b/Axantum.AxCrypt.Core/Runtime/WorkFolderWatcher.cs
new file mode 100644
index 0000000..67c842a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/WorkFolderWatcher.cs
@@ -0,0 +1,78 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class WorkFolderWatcher : IDisposable
+    {
+        private IFileWatcher _workFolderWatcher;
+
+        public WorkFolderWatcher()
+        {
+            _workFolderWatcher = Factory.New<IFileWatcher>(Factory.Instance.Singleton<WorkFolder>().FileInfo.FullName);
+            _workFolderWatcher.IncludeSubdirectories = true;
+            _workFolderWatcher.FileChanged += HandleWorkFolderFileChangedEvent;
+        }
+
+        private void HandleWorkFolderFileChangedEvent(object sender, FileWatcherEventArgs e)
+        {
+            if (e.FullName == Instance.FileSystemState.PathInfo.FullName)
+            {
+                return;
+            }
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.WorkFolderChange, e.FullName));
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_workFolderWatcher != null)
+            {
+                _workFolderWatcher.Dispose();
+                _workFolderWatcher = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/WorkerGroup.cs b/Axantum.AxCrypt.Core/Runtime/WorkerGroup.cs
new file mode 100644
index 0000000..ac3f6ae
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/WorkerGroup.cs
@@ -0,0 +1,329 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    /// <summary>
+    /// Manage a group of worker threads with a maximum level of concurrency.
+    /// </summary>
+    public class WorkerGroup : IDisposable
+    {
+        private class ThreadWorkerWrapper : IThreadWorker
+        {
+            private IThreadWorker _worker;
+
+            public ThreadWorkerWrapper(IThreadWorker worker)
+            {
+                _worker = worker;
+            }
+
+            #region IThreadWorker Members
+
+            /// <summary>
+            /// Start the asynchronous execution of the work.
+            /// </summary>
+            public void Run()
+            {
+                _worker.Run();
+            }
+
+            /// <summary>
+            /// Perform blocking wait until this thread has completed execution.
+            /// </summary>
+            public void Join()
+            {
+                throw new InvalidOperationException("This instance is managed by a WorkerGroup, and Join() cannot be called explicitly.");
+            }
+
+            /// <summary>
+            /// Abort this thread - can only be called *before* Run() has been called.
+            /// </summary>
+            public void Abort()
+            {
+                _worker.Abort();
+            }
+
+            /// <summary>
+            /// Returns true if the thread has completed execution.
+            /// </summary>
+            public bool HasCompleted
+            {
+                get { throw new InvalidOperationException("This instance is managed by a WorkerGroup, and HasCompleted cannot be called explicitly."); }
+            }
+
+            /// <summary>
+            /// Raised just before asynchronous execution starts. Runs on the
+            /// original thread, typically the GUI thread.
+            /// </summary>
+            public event EventHandler<ThreadWorkerEventArgs> Prepare
+            {
+                add { _worker.Prepare += value; }
+                remove { _worker.Prepare -= value; }
+            }
+
+            /// <summary>
+            /// Raised when asynchronous execution starts. Runs on a different
+            /// thread than the caller thread. Do not interact with the GUI here.
+            /// </summary>
+            public event EventHandler<ThreadWorkerEventArgs> Work
+            {
+                add { _worker.Work += value; }
+                remove { _worker.Work -= value; }
+            }
+
+            /// <summary>
+            /// Raised when all is done. Runs on the original thread, typically
+            /// the GUI thread.
+            /// </summary>
+            public event EventHandler<ThreadWorkerEventArgs> Completing
+            {
+                add { _worker.Completing += value; }
+                remove { _worker.Completing -= value; }
+            }
+
+            public event EventHandler<ThreadWorkerEventArgs> Completed
+            {
+                add { _worker.Completed += value; }
+                remove { _worker.Completed -= value; }
+            }
+
+            public void Dispose()
+            {
+                _worker.Dispose();
+            }
+
+            #endregion IThreadWorker Members
+        }
+
+        private ISemaphore _concurrencyControlSemaphore;
+
+        private int _maxConcurrencyCount;
+
+        private bool _disposed = false;
+
+        private bool _finished = false;
+
+        private ISingleThread _singleThread;
+
+        private readonly object _finishedLock = new object();
+
+        /// <summary>
+        /// Instantiate a worker group with no concurrency and implicit progress reporting. Progress
+        /// will be reported on the thread calling the constructor.
+        /// </summary>
+        public WorkerGroup()
+            : this(1)
+        {
+        }
+
+        /// <summary>
+        /// Instantiates a worker group with specified maximum concurrency and implicit progress reporting. Progress
+        /// will be reported on the thread calling the constructor.
+        /// </summary>
+        /// <param name="maxConcurrent">The maximum number of worker threads active at any one time</param>
+        public WorkerGroup(int maxConcurrent)
+            : this(maxConcurrent, new ProgressContext())
+        {
+        }
+
+        public WorkerGroup(IProgressContext progress)
+            : this(1, progress)
+        {
+        }
+
+        /// <summary
+        /// Instantiates a worker group with specified maximum concurrency and external progress reporting. Progress
+        /// will be reported on the thread instantiating the ProgressContext used.
+        /// </summary>
+        /// <param name="maxConcurrent">The maximum number of worker threads active at any one time</param>
+        /// <param name="progress">The ProgressContext that receives progress notifications</param>
+        public WorkerGroup(int maxConcurrent, IProgressContext progress)
+        {
+            _concurrencyControlSemaphore = Instance.Portable.Semaphore(maxConcurrent, maxConcurrent);
+            _maxConcurrencyCount = maxConcurrent;
+            _singleThread = Instance.Portable.SingleThread();
+            FirstError = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            progress.NotifyLevelStart();
+            Progress = new WorkerGroupProgressContext(progress, _singleThread);
+        }
+
+        /// <summary>
+        /// The ProgressContext that is passed to worker threads for progress reporting and cancellation checks. If it was
+        /// instantiated by this instance, then progress events are subscribed to and forwarded to the original instantiating
+        /// thread, typically the GUI thread. If the ProgressContext was supplied explicitly by the caller when instantiating this
+        /// instance, no progress events are subscribed to by this instance.
+        /// </summary>
+        public IProgressContext Progress { get; private set; }
+
+        /// <summary>
+        /// Call when work for this instance has been scheduled. This call will block until all executing threads have terminated.
+        /// It will also notify the ProgressContext that all work has finished.
+        /// </summary>
+        /// <remarks>
+        /// Since this call may block, it should never be called from a GUI thread.
+        /// </remarks>
+        public void WaitAllAndFinish()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException("WorkerGroup");
+            }
+            lock (_finishedLock)
+            {
+                if (_finished)
+                {
+                    throw new InvalidOperationException("NotifyFinished() must only be called once, but was called twice.");
+                }
+                NotifyFinishedInternal();
+            }
+        }
+
+        private void NotifyFinishedInternal()
+        {
+            lock (_finishedLock)
+            {
+                if (_finished)
+                {
+                    return;
+                }
+
+                for (int i = 0; i < _maxConcurrencyCount; ++i)
+                {
+                    AcquireOneConcurrencyRight();
+                }
+                _finished = true;
+            }
+            Progress.NotifyLevelFinished();
+        }
+
+        public IThreadWorker CreateWorker()
+        {
+            return CreateWorker(false);
+        }
+
+        /// <summary>
+        /// Create a ThreadWorker for background work. Concurrency limitations are effective, so this call may block.
+        /// </summary>
+        /// <remarks>
+        /// Since this call may block, it should not be called from the GUI thread if there is a risk of blocking.
+        /// </remarks>
+        /// <returns></returns>
+        public IThreadWorker CreateWorker(bool startSerializedOnUIThread)
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException("WorkerGroup");
+            }
+            AcquireOneConcurrencyRight();
+            IThreadWorker threadWorker = Instance.Portable.ThreadWorker(Progress, startSerializedOnUIThread);
+            threadWorker.Completed += new EventHandler<ThreadWorkerEventArgs>(HandleThreadWorkerCompletedEvent);
+            return new ThreadWorkerWrapper(threadWorker);
+        }
+
+        private void HandleThreadWorkerCompletedEvent(object sender, ThreadWorkerEventArgs e)
+        {
+            if (e.Result.Status != FileOperationStatus.Success)
+            {
+                lock (_firstErrorLock)
+                {
+                    if (FirstError.Status == FileOperationStatus.Success)
+                    {
+                        FirstError = e.Result;
+                    }
+                }
+            }
+            IDisposable disposable = sender as IDisposable;
+            if (disposable != null)
+            {
+                disposable.Dispose();
+            }
+            ReleaseOneConcurrencyRight();
+        }
+
+        private static readonly object _firstErrorLock = new object();
+
+        /// <summary>
+        /// The first error reported. Subsequent errors may be missed.
+        /// </summary>
+        public FileOperationContext FirstError { get; private set; }
+
+        private void AcquireOneConcurrencyRight()
+        {
+            _concurrencyControlSemaphore.WaitOne();
+        }
+
+        private void ReleaseOneConcurrencyRight()
+        {
+            _concurrencyControlSemaphore.Release();
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+            _disposed = true;
+        }
+
+        private void DisposeInternal()
+        {
+            NotifyFinishedInternal();
+            if (_concurrencyControlSemaphore != null)
+            {
+                _concurrencyControlSemaphore.Dispose();
+                _concurrencyControlSemaphore = null;
+            }
+            if (_singleThread != null)
+            {
+                _singleThread.Dispose();
+                _singleThread = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Runtime/WorkerGroupProgressContext.cs b/Axantum.AxCrypt.Core/Runtime/WorkerGroupProgressContext.cs
new file mode 100644
index 0000000..7be2e02
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Runtime/WorkerGroupProgressContext.cs
@@ -0,0 +1,118 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Runtime
+{
+    public class WorkerGroupProgressContext : IProgressContext
+    {
+        private IProgressContext _progress;
+
+        private ISingleThread _singleThread;
+
+        public WorkerGroupProgressContext(IProgressContext progress, ISingleThread singleThread)
+        {
+            _progress = progress;
+            _singleThread = singleThread;
+        }
+
+        public event EventHandler<ProgressEventArgs> Progressing
+        {
+            add
+            {
+                _progress.Progressing += value;
+            }
+            remove
+            {
+                _progress.Progressing -= value;
+            }
+        }
+
+        public void RemoveCount(long totalCount, long progressCount)
+        {
+            _progress.RemoveCount(totalCount, progressCount);
+        }
+
+        public void AddTotal(long count)
+        {
+            _progress.AddTotal(count);
+        }
+
+        public void AddCount(long count)
+        {
+            _progress.AddCount(count);
+        }
+
+        public void NotifyLevelStart()
+        {
+            _progress.NotifyLevelStart();
+        }
+
+        public void NotifyLevelFinished()
+        {
+            _progress.NotifyLevelFinished();
+        }
+
+        public bool Cancel
+        {
+            get
+            {
+                return _progress.Cancel;
+            }
+            set
+            {
+                _progress.Cancel = value;
+            }
+        }
+
+        public bool AllItemsConfirmed
+        {
+            get
+            {
+                return _progress.AllItemsConfirmed;
+            }
+            set
+            {
+                _progress.AllItemsConfirmed = value;
+            }
+        }
+
+        public void EnterSingleThread()
+        {
+            _singleThread.Enter();
+        }
+
+        public void LeaveSingleThread()
+        {
+            _singleThread.Leave();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFile.cs b/Axantum.AxCrypt.Core/Session/ActiveFile.cs
new file mode 100644
index 0000000..3aa708b
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFile.cs
@@ -0,0 +1,303 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// This class represent an active source files' current known state. Instances of this class are
+    /// immutable.
+    /// </summary>
+    ///
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public sealed class ActiveFile
+    {
+        public ActiveFile(ActiveFile activeFile)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            Initialize(activeFile);
+            Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, Properties.LastEncryptionWriteTimeUtc, activeFile.Properties.CryptoId);
+            Key = null;
+        }
+
+        public ActiveFile(ActiveFile activeFile, Passphrase key)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            Initialize(activeFile);
+            Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, Properties.LastEncryptionWriteTimeUtc, activeFile.Properties.CryptoId);
+            Key = key;
+        }
+
+        public ActiveFile(ActiveFile activeFile, IRuntimeFileInfo encryptedFileInfo)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            if (encryptedFileInfo == null)
+            {
+                throw new ArgumentNullException("encryptedFileInfo");
+            }
+
+            Initialize(activeFile);
+            EncryptedFileInfo = encryptedFileInfo;
+        }
+
+        public ActiveFile(ActiveFile activeFile, ActiveFileStatus status)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+
+            Initialize(activeFile);
+            Status = status;
+        }
+
+        public ActiveFile(ActiveFile activeFile, DateTime lastEncryptionWriteTimeUtc, ActiveFileStatus status)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            Initialize(activeFile);
+            Properties = new ActiveFileProperties(activeFile.Properties.LastActivityTimeUtc, lastEncryptionWriteTimeUtc, activeFile.Properties.CryptoId);
+            Status = status;
+        }
+
+        public ActiveFile(IRuntimeFileInfo encryptedFileInfo, IRuntimeFileInfo decryptedFileInfo, Passphrase key, ActiveFileStatus status, Guid cryptoId)
+        {
+            if (encryptedFileInfo == null)
+            {
+                throw new ArgumentNullException("encryptedFileInfo");
+            }
+            if (decryptedFileInfo == null)
+            {
+                throw new ArgumentNullException("decryptedFileInfo");
+            }
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            Initialize(encryptedFileInfo, decryptedFileInfo, key, null, status, new ActiveFileProperties(OS.Current.UtcNow, encryptedFileInfo.LastWriteTimeUtc, cryptoId));
+        }
+
+        private void Initialize(ActiveFile other)
+        {
+            Initialize(other.EncryptedFileInfo, other.DecryptedFileInfo, other.Key, other.Thumbprint, other.Status, other.Properties);
+        }
+
+        private void Initialize(IRuntimeFileInfo encryptedFileInfo, IRuntimeFileInfo decryptedFileInfo, Passphrase key, SymmetricKeyThumbprint thumbprint, ActiveFileStatus status, ActiveFileProperties properties)
+        {
+            EncryptedFileInfo = Factory.New<IRuntimeFileInfo>(encryptedFileInfo.FullName);
+            DecryptedFileInfo = Factory.New<IRuntimeFileInfo>(decryptedFileInfo.FullName);
+            Key = key;
+            Thumbprint = thumbprint;
+            Status = status;
+            Properties = new ActiveFileProperties(OS.Current.UtcNow, properties.LastEncryptionWriteTimeUtc, properties.CryptoId);
+        }
+
+        public IRuntimeFileInfo DecryptedFileInfo
+        {
+            get;
+            private set;
+        }
+
+        public IRuntimeFileInfo EncryptedFileInfo
+        {
+            get;
+            private set;
+        }
+
+        private SymmetricKeyThumbprint _thumbprint;
+
+        [DataMember(Name = "Thumbprint")]
+        public SymmetricKeyThumbprint Thumbprint
+        {
+            get
+            {
+                if (_thumbprint == null && Key != null)
+                {
+                    _thumbprint = Key.Thumbprint;
+                }
+                return _thumbprint;
+            }
+            private set
+            {
+                _thumbprint = value;
+            }
+        }
+
+        private string _decryptedFolder;
+
+        [DataMember]
+        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a private property used for serialization.")]
+        private string DecryptedFolder
+        {
+            get
+            {
+                return Instance.Portable.Path().GetDirectoryName(DecryptedFileInfo.FullName);
+            }
+            set
+            {
+                _decryptedFolder = value;
+            }
+        }
+
+        private string _decryptedName;
+
+        [DataMember]
+        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a private property used for serialization.")]
+        private byte[] ProtectedDecryptedName
+        {
+            get
+            {
+                return Factory.New<IDataProtection>().Protect(Encoding.UTF8.GetBytes(Instance.Portable.Path().GetFileName(DecryptedFileInfo.FullName)));
+            }
+            set
+            {
+                byte[] bytes = Factory.New<IDataProtection>().Unprotect(value);
+                _decryptedName = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
+            }
+        }
+
+        [DataMember]
+        [SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode", Justification = "This is a private property used for serialization.")]
+        private string EncryptedPath
+        {
+            get
+            {
+                return EncryptedFileInfo.FullName;
+            }
+            set
+            {
+                EncryptedFileInfo = Factory.New<IRuntimeFileInfo>(value);
+            }
+        }
+
+        [DataMember]
+        public ActiveFileStatus Status { get; private set; }
+
+        [DataMember]
+        public ActiveFileProperties Properties { get; private set; }
+
+        [OnDeserialized]
+        private void OnDeserialized(StreamingContext context)
+        {
+            DecryptedFileInfo = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().Combine(_decryptedFolder, _decryptedName));
+            if (Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
+            {
+                Status |= ActiveFileStatus.NoProcessKnown;
+            }
+        }
+
+        private Passphrase _key;
+
+        public Passphrase Key
+        {
+            get
+            {
+                return _key;
+            }
+            private set
+            {
+                _key = value;
+            }
+        }
+
+        /// <summary>
+        /// Check if a provided key matches the thumbprint of this instance.
+        /// </summary>
+        /// <param name="key">A key to check against this instances thumbprint.</param>
+        /// <returns>true if the thumbprint matches the provided key.</returns>
+        public bool ThumbprintMatch(Passphrase key)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+
+            return key.Thumbprint == Thumbprint;
+        }
+
+        public bool IsModified
+        {
+            get
+            {
+                if (!DecryptedFileInfo.IsExistingFile)
+                {
+                    return false;
+                }
+                bool isModified = DecryptedFileInfo.LastWriteTimeUtc > Properties.LastEncryptionWriteTimeUtc;
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("IsModified == '{0}' for file '{3}' info last write time '{1}' and active file last write time '{2}'".InvariantFormat(isModified.ToString(), DecryptedFileInfo.LastWriteTimeUtc.ToString(), Properties.LastEncryptionWriteTimeUtc.ToString(), DecryptedFileInfo.Name));
+                }
+                return isModified;
+            }
+        }
+
+        public ActiveFileVisualState VisualState
+        {
+            get
+            {
+                if (Status.HasMask(ActiveFileStatus.DecryptedIsPendingDelete))
+                {
+                    return Key != null ? ActiveFileVisualState.DecryptedWithKnownKey : ActiveFileVisualState.DecryptedWithoutKnownKey;
+                }
+                if (Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
+                {
+                    return Key != null ? ActiveFileVisualState.DecryptedWithKnownKey : ActiveFileVisualState.DecryptedWithoutKnownKey;
+                }
+                if (Status.HasMask(ActiveFileStatus.NotDecrypted))
+                {
+                    return Key != null ? ActiveFileVisualState.EncryptedWithKnownKey : ActiveFileVisualState.EncryptedWithoutKnownKey;
+                }
+                throw new InvalidOperationException("ActiveFile in an unhandled visual state.".InvariantFormat());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileAction.cs b/Axantum.AxCrypt.Core/Session/ActiveFileAction.cs
new file mode 100644
index 0000000..951f2c2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileAction.cs
@@ -0,0 +1,358 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class ActiveFileAction
+    {
+        public ActiveFileAction()
+        {
+        }
+
+        /// <summary>
+        /// Try do delete files that have been decrypted temporarily, if the conditions are met for such a deletion,
+        /// i.e. it is apparently not locked or in use etc.
+        /// </summary>
+        /// <param name="_fileSystemState">The instance of FileSystemState where active files are recorded.</param>
+        /// <param name="progress">The context where progress may be reported.</param>
+        public virtual void PurgeActiveFiles(IProgressContext progress)
+        {
+            progress.NotifyLevelStart();
+            Instance.FileSystemState.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFile) =>
+            {
+                if (FileLock.IsLocked(activeFile.DecryptedFileInfo))
+                {
+                    if (Instance.Log.IsInfoEnabled)
+                    {
+                        Instance.Log.LogInfo("Not deleting '{0}' because it is marked as locked.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                    }
+                    return activeFile;
+                }
+                if (activeFile.IsModified)
+                {
+                    if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable))
+                    {
+                        activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable);
+                    }
+                    activeFile = CheckIfTimeToUpdate(activeFile, progress);
+                }
+                if (activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
+                {
+                    activeFile = TryDelete(activeFile, progress);
+                }
+                return activeFile;
+            });
+            progress.NotifyLevelFinished();
+        }
+
+        /// <summary>
+        /// Enumerate all files listed as active, checking for status changes and take appropriate actions such as updating status
+        /// in the FileSystemState, re-encrypting or deleting temporary plaintext copies.
+        /// </summary>
+        /// <param name="_fileSystemState">The FileSystemState to enumerate and possibly update.</param>
+        /// <param name="mode">Under what circumstances is the FileSystemState.Changed event raised.</param>
+        /// <param name="progress">The ProgressContext to provide visual progress feedback via.</param>
+        public virtual void CheckActiveFiles(ChangedEventMode mode, IProgressContext progress)
+        {
+            progress.NotifyLevelStart();
+            progress.AddTotal(Instance.FileSystemState.ActiveFileCount);
+            Instance.FileSystemState.ForEach(mode, (ActiveFile activeFile) =>
+            {
+                try
+                {
+                    return CheckActiveFile(activeFile, progress);
+                }
+                finally
+                {
+                    progress.AddCount(1);
+                }
+            });
+            progress.NotifyLevelFinished();
+        }
+
+        public virtual ActiveFile CheckActiveFile(ActiveFile activeFile, IProgressContext progress)
+        {
+            if (FileLock.IsLocked(activeFile.DecryptedFileInfo, activeFile.EncryptedFileInfo))
+            {
+                return activeFile;
+            }
+            activeFile = CheckActiveFileActions(activeFile, progress);
+            return activeFile;
+        }
+
+        /// <summary>
+        /// For each active file, check if provided key matches the thumbprint of an active file that does not yet have
+        /// a known key. If so, update the active file with the now known key.
+        /// </summary>
+        /// <param name="_fileSystemState">The FileSystemState that contains the list of active files.</param>
+        /// <param name="key">The newly added key to check the files for a match with.</param>
+        /// <returns>True if any file was updated with the new key, False otherwise.</returns>
+        public virtual bool UpdateActiveFileWithKeyIfKeyMatchesThumbprint(Passphrase key)
+        {
+            bool keyMatch = false;
+            Instance.FileSystemState.ForEach(ChangedEventMode.RaiseOnlyOnModified, (ActiveFile activeFile) =>
+            {
+                if (activeFile.Key != null)
+                {
+                    return activeFile;
+                }
+                if (!activeFile.ThumbprintMatch(key))
+                {
+                    return activeFile;
+                }
+                keyMatch = true;
+
+                activeFile = new ActiveFile(activeFile, key);
+                return activeFile;
+            });
+            return keyMatch;
+        }
+
+        public virtual void RemoveRecentFiles(IEnumerable<IRuntimeFileInfo> encryptedPaths, IProgressContext progress)
+        {
+            progress.NotifyLevelStart();
+            progress.AddTotal(encryptedPaths.Count());
+            foreach (IRuntimeFileInfo encryptedPath in encryptedPaths)
+            {
+                ActiveFile activeFile = Instance.FileSystemState.FindActiveFileFromEncryptedPath(encryptedPath.FullName);
+                if (activeFile != null)
+                {
+                    Instance.FileSystemState.RemoveActiveFile(activeFile);
+                }
+                progress.AddCount(1);
+            }
+            Instance.FileSystemState.Save();
+            progress.NotifyLevelFinished();
+        }
+
+        private static ActiveFile CheckActiveFileActions(ActiveFile activeFile, IProgressContext progress)
+        {
+            activeFile = CheckIfKeyIsKnown(activeFile);
+            activeFile = CheckIfCreated(activeFile);
+            activeFile = CheckIfProcessExited(activeFile);
+            activeFile = CheckIfTimeToUpdate(activeFile, progress);
+            activeFile = CheckIfTimeToDelete(activeFile, progress);
+            return activeFile;
+        }
+
+        private static ActiveFile CheckIfKeyIsKnown(ActiveFile activeFile)
+        {
+            if ((activeFile.Status & (ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.DecryptedIsPendingDelete | ActiveFileStatus.NotDecrypted)) == 0)
+            {
+                return activeFile;
+            }
+
+            Passphrase key = FindKnownKeyOrNull(activeFile);
+            if (activeFile.Key != null)
+            {
+                if (key != null)
+                {
+                    return activeFile;
+                }
+                return new ActiveFile(activeFile);
+            }
+
+            if (key != null)
+            {
+                return new ActiveFile(activeFile, key);
+            }
+            return activeFile;
+        }
+
+        private static Passphrase FindKnownKeyOrNull(ActiveFile activeFile)
+        {
+            foreach (Passphrase key in Instance.KnownKeys.Keys)
+            {
+                if (activeFile.ThumbprintMatch(key))
+                {
+                    return key;
+                }
+            }
+            return null;
+        }
+
+        private static ActiveFile CheckIfCreated(ActiveFile activeFile)
+        {
+            if (activeFile.Status != ActiveFileStatus.NotDecrypted)
+            {
+                return activeFile;
+            }
+
+            if (!activeFile.DecryptedFileInfo.IsExistingFile)
+            {
+                return activeFile;
+            }
+
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.AssumedOpenAndDecrypted);
+
+            return activeFile;
+        }
+
+        private static ActiveFile CheckIfProcessExited(ActiveFile activeFile)
+        {
+            if (Instance.ProcessState.HasActiveProcess(activeFile))
+            {
+                return activeFile;
+            }
+            if (!activeFile.Status.HasMask(ActiveFileStatus.NotShareable))
+            {
+                return activeFile;
+            }
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Process exit for '{0}'".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+            }
+            activeFile = new ActiveFile(activeFile, activeFile.Status & ~ActiveFileStatus.NotShareable);
+            return activeFile;
+        }
+
+        private static ActiveFile CheckIfTimeToUpdate(ActiveFile activeFile, IProgressContext progress)
+        {
+            if (!activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted) || activeFile.Status.HasMask(ActiveFileStatus.NotShareable))
+            {
+                return activeFile;
+            }
+            if (activeFile.Key == null)
+            {
+                return activeFile;
+            }
+            if (!activeFile.IsModified)
+            {
+                return activeFile;
+            }
+
+            try
+            {
+                using (Stream activeFileStream = activeFile.DecryptedFileInfo.OpenRead())
+                {
+                    Factory.New<AxCryptFile>().WriteToFileWithBackup(activeFile.EncryptedFileInfo, (Stream destination) =>
+                    {
+                        AxCryptFile.Encrypt(activeFile.DecryptedFileInfo, destination, activeFile.Key, activeFile.Properties.CryptoId, AxCryptOptions.EncryptWithCompression, progress);
+                    }, progress);
+                }
+            }
+            catch (IOException)
+            {
+                if (Instance.Log.IsWarningEnabled)
+                {
+                    Instance.Log.LogWarning("Failed exclusive open modified for '{0}'.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                }
+                activeFile = new ActiveFile(activeFile, activeFile.Status | ActiveFileStatus.NotShareable);
+                return activeFile;
+            }
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Wrote back '{0}' to '{1}'".InvariantFormat(activeFile.DecryptedFileInfo.FullName, activeFile.EncryptedFileInfo.FullName));
+            }
+            activeFile = new ActiveFile(activeFile, activeFile.DecryptedFileInfo.LastWriteTimeUtc, ActiveFileStatus.AssumedOpenAndDecrypted);
+            return activeFile;
+        }
+
+        private static ActiveFile CheckIfTimeToDelete(ActiveFile activeFile, IProgressContext progress)
+        {
+            if (OS.Current.Platform != Platform.WindowsDesktop)
+            {
+                return activeFile;
+            }
+            if (!activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
+            {
+                return activeFile;
+            }
+            if (activeFile.Status.HasMask(ActiveFileStatus.NotShareable))
+            {
+                return activeFile;
+            }
+            if (activeFile.Status.HasMask(ActiveFileStatus.NoProcessKnown))
+            {
+                return activeFile;
+            }
+
+            activeFile = TryDelete(activeFile, progress);
+            return activeFile;
+        }
+
+        private static ActiveFile TryDelete(ActiveFile activeFile, IProgressContext progress)
+        {
+            if (Instance.ProcessState.HasActiveProcess(activeFile))
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Not deleting '{0}' because it has an active process.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                }
+                return activeFile;
+            }
+
+            if (activeFile.IsModified)
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Tried delete '{0}' but it is modified.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                }
+                return activeFile;
+            }
+
+            try
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Deleting '{0}'.".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                }
+                Factory.New<AxCryptFile>().Wipe(activeFile.DecryptedFileInfo, progress);
+                IRuntimeFileInfo decryptedFolder = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().GetDirectoryName(activeFile.DecryptedFileInfo.FullName));
+                decryptedFolder.RemoveFolder();
+            }
+            catch (IOException)
+            {
+                if (Instance.Log.IsWarningEnabled)
+                {
+                    Instance.Log.LogWarning("Wiping failed for '{0}'".InvariantFormat(activeFile.DecryptedFileInfo.FullName));
+                }
+                activeFile = new ActiveFile(activeFile, activeFile.Status | ActiveFileStatus.NotShareable);
+                return activeFile;
+            }
+
+            activeFile = new ActiveFile(activeFile, ActiveFileStatus.NotDecrypted);
+
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Deleted '{0}' from '{1}'.".InvariantFormat(activeFile.DecryptedFileInfo.FullName, activeFile.EncryptedFileInfo.FullName));
+            }
+
+            return activeFile;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileChangedEventArgs.cs b/Axantum.AxCrypt.Core/Session/ActiveFileChangedEventArgs.cs
new file mode 100644
index 0000000..b661265
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileChangedEventArgs.cs
@@ -0,0 +1,44 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class ActiveFileChangedEventArgs : EventArgs
+    {
+        public ActiveFileChangedEventArgs(ActiveFile activeFile)
+        {
+            ActiveFile = activeFile;
+        }
+
+        public ActiveFile ActiveFile { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileCollection.cs b/Axantum.AxCrypt.Core/Session/ActiveFileCollection.cs
new file mode 100644
index 0000000..8ab53a8
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileCollection.cs
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    [CollectionDataContract(ItemName = "FileState", Namespace = "http://wwww.axantum.com/Serialization/")]
+    public class ActiveFileCollection : List<ActiveFile>
+    {
+        public ActiveFileCollection()
+            : base()
+        {
+        }
+
+        public ActiveFileCollection(IEnumerable<ActiveFile> collection)
+            : base(collection)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileComparer.cs b/Axantum.AxCrypt.Core/Session/ActiveFileComparer.cs
new file mode 100644
index 0000000..f3c4674
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileComparer.cs
@@ -0,0 +1,82 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public abstract class ActiveFileComparer : IComparer<ActiveFile>
+    {
+        private class EncryptedNameComparerImpl : ActiveFileComparer
+        {
+            public override int Compare(ActiveFile x, ActiveFile y)
+            {
+                return (ReverseSort ? -1 : 1) * String.Compare(x.EncryptedFileInfo.FullName, y.EncryptedFileInfo.FullName, StringComparison.OrdinalIgnoreCase);
+            }
+        }
+
+        private class DecryptedNameComparerImpl : ActiveFileComparer
+        {
+            public override int Compare(ActiveFile x, ActiveFile y)
+            {
+                return (ReverseSort ? -1 : 1) * String.Compare(Instance.Portable.Path().GetFileName(x.DecryptedFileInfo.FullName), Instance.Portable.Path().GetFileName(y.DecryptedFileInfo.FullName), StringComparison.OrdinalIgnoreCase);
+            }
+        }
+
+        private class DateComparerImpl : ActiveFileComparer
+        {
+            public override int Compare(ActiveFile x, ActiveFile y)
+            {
+                return (ReverseSort ? -1 : 1) * x.Properties.LastActivityTimeUtc.CompareTo(y.Properties.LastActivityTimeUtc);
+            }
+        }
+
+        private class CryptoNameComparerImpl : ActiveFileComparer
+        {
+            public override int Compare(ActiveFile x, ActiveFile y)
+            {
+                return (ReverseSort ? -1 : 1) * String.Compare(Instance.CryptoFactory.Create(x.Properties.CryptoId).Name, Instance.CryptoFactory.Create(y.Properties.CryptoId).Name, StringComparison.OrdinalIgnoreCase);
+            }
+        }
+
+        public static ActiveFileComparer EncryptedNameComparer { get { return new EncryptedNameComparerImpl(); } }
+
+        public static ActiveFileComparer DecryptedNameComparer { get { return new DecryptedNameComparerImpl(); } }
+
+        public static ActiveFileComparer DateComparer { get { return new DateComparerImpl(); } }
+
+        public static ActiveFileComparer CryptoNameComparer { get { return new CryptoNameComparerImpl(); } }
+
+        public abstract int Compare(ActiveFile x, ActiveFile y);
+
+        public bool ReverseSort { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileProperties.cs b/Axantum.AxCrypt.Core/Session/ActiveFileProperties.cs
new file mode 100644
index 0000000..8337680
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileProperties.cs
@@ -0,0 +1,60 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class ActiveFileProperties
+    {
+        public ActiveFileProperties(DateTime lastActivityTimeUtc, DateTime lastEncryptionWriteTimeUtc, Guid cryptoId)
+        {
+            LastActivityTimeUtc = lastActivityTimeUtc;
+            LastEncryptionWriteTimeUtc = lastEncryptionWriteTimeUtc;
+            CryptoId = cryptoId;
+        }
+
+        [DataMember(Name = "CryptoId")]
+        public Guid CryptoId
+        {
+            get;
+            private set;
+        }
+
+        [DataMember]
+        public DateTime LastActivityTimeUtc { get; private set; }
+
+        /// <summary>
+        /// Records the Last Write Time that was valid at the most recent encryption update of the encrypted file.
+        /// </summary>
+        [DataMember]
+        public DateTime LastEncryptionWriteTimeUtc { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileStatus.cs b/Axantum.AxCrypt.Core/Session/ActiveFileStatus.cs
new file mode 100644
index 0000000..b474626
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileStatus.cs
@@ -0,0 +1,56 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    [Flags]
+    public enum ActiveFileStatus
+    {
+        None = 0,
+        AssumedOpenAndDecrypted = 1,
+        NotDecrypted = 2,
+        Error = 4,
+        DecryptedIsPendingDelete = 8,
+
+        /// <summary>
+        /// Indicates a file operation has failed due to a sharing violation. Is only advisory, and may be ignored
+        /// or reset when an event is raised that may change the situation.
+        /// </summary>
+        NotShareable = 16,
+
+        IgnoreChange = 32,
+        Inactive = 64,
+
+        /// <summary>
+        /// Set when an application was launched for the file, but no process could be seen to be started. This typically happens
+        /// with Windows 8 apps, as well as some multi document softwares such as Word etc.
+        /// </summary>
+        NoProcessKnown = 128,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileVisualState.cs b/Axantum.AxCrypt.Core/Session/ActiveFileVisualState.cs
new file mode 100644
index 0000000..4e742f2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileVisualState.cs
@@ -0,0 +1,45 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// Specifies how the ActiveFile should be visualized in a GUI, depending
+    /// on what operations are possible with it.
+    /// </summary>
+    public enum ActiveFileVisualState
+    {
+        None,
+        DecryptedWithKnownKey,
+        DecryptedWithoutKnownKey,
+        EncryptedWithKnownKey,
+        EncryptedWithoutKnownKey,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ActiveFileWatcher.cs b/Axantum.AxCrypt.Core/Session/ActiveFileWatcher.cs
new file mode 100644
index 0000000..da56aa0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ActiveFileWatcher.cs
@@ -0,0 +1,69 @@
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class ActiveFileWatcher : IDisposable
+    {
+        private Dictionary<string, IFileWatcher> _activeFileFolderWatchers = new Dictionary<string, IFileWatcher>();
+
+        public ActiveFileWatcher()
+        {
+        }
+
+        public void Add(IRuntimeFileInfo file)
+        {
+            string folder = Instance.Portable.Path().GetDirectoryName(file.FullName);
+            lock (_activeFileFolderWatchers)
+            {
+                if (_activeFileFolderWatchers.ContainsKey(folder))
+                {
+                    return;
+                }
+                IFileWatcher fileWatcher = Factory.New<IFileWatcher>(folder);
+                fileWatcher.FileChanged += HandleActiveFileFolderChangedEvent;
+                _activeFileFolderWatchers.Add(folder, fileWatcher);
+            }
+        }
+
+        private void HandleActiveFileFolderChangedEvent(object sender, FileWatcherEventArgs e)
+        {
+            if (String.IsNullOrEmpty(e.OldName))
+            {
+                Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.PurgeActiveFiles, e.FullName));
+                return;
+            }
+
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.FileMove, e.FullName, e.OldName));
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            lock (_activeFileFolderWatchers)
+            {
+                foreach (IFileWatcher fileWatcher in _activeFileFolderWatchers.Values)
+                {
+                    fileWatcher.Dispose();
+                }
+                _activeFileFolderWatchers.Clear();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ChangedEventMode.cs b/Axantum.AxCrypt.Core/Session/ChangedEventMode.cs
new file mode 100644
index 0000000..b517abb
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ChangedEventMode.cs
@@ -0,0 +1,40 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public enum ChangedEventMode
+    {
+        RaiseAlways,
+        RaiseOnlyOnModified,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/FileSystemState.cs b/Axantum.AxCrypt.Core/Session/FileSystemState.cs
new file mode 100644
index 0000000..deecaa3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/FileSystemState.cs
@@ -0,0 +1,539 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class FileSystemState : IDisposable
+    {
+        public FileSystemState()
+        {
+            Initialize(new StreamingContext());
+        }
+
+        private FileSystemState(IRuntimeFileInfo path)
+            : this()
+        {
+            _path = path;
+        }
+
+        public IRuntimeFileInfo PathInfo
+        {
+            get
+            {
+                return _path;
+            }
+        }
+
+        [OnDeserializing]
+        private void Initialize(StreamingContext context)
+        {
+            Identities = new List<PassphraseIdentity>();
+            _activeFilesByEncryptedPath = new Dictionary<string, ActiveFile>();
+        }
+
+        [OnDeserialized]
+        private void Finalize(StreamingContext context)
+        {
+            Identities = new List<PassphraseIdentity>(Identities);
+        }
+
+        private Dictionary<string, ActiveFile> _activeFilesByEncryptedPath;
+
+        [DataMember(Name = "PassphraseIdentities")]
+        public virtual IList<PassphraseIdentity> Identities
+        {
+            get;
+            private set;
+        }
+
+        private List<WatchedFolder> _watchedFolders;
+
+        private IList<WatchedFolder> WatchedFoldersInternal
+        {
+            get
+            {
+                if (_watchedFolders == null)
+                {
+                    _watchedFolders = new List<WatchedFolder>();
+                }
+                return _watchedFolders;
+            }
+        }
+
+        [DataMember(Name = "WatchedFolders")]
+        public IEnumerable<WatchedFolder> WatchedFolders
+        {
+            get
+            {
+                IEnumerable<WatchedFolder> folders = WatchedFoldersInternal.Where(folder => Factory.New<IRuntimeFileInfo>(folder.Path).IsExistingFolder).ToList();
+                return folders;
+            }
+            private set
+            {
+                foreach (WatchedFolder watchedFolder in value)
+                {
+                    AddWatchedFolderInternal(watchedFolder);
+                }
+            }
+        }
+
+        public virtual void AddWatchedFolder(WatchedFolder watchedFolder)
+        {
+            if (AddWatchedFolderInternal(watchedFolder))
+            {
+                Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.WatchedFolderAdded, Instance.KnownKeys.DefaultEncryptionKey, watchedFolder.Path));
+            }
+            else
+            {
+                Instance.StatusChecker.CheckStatusAndShowMessage(FileOperationStatus.FolderAlreadyWatched, watchedFolder.Path);
+            }
+        }
+
+        private bool AddWatchedFolderInternal(WatchedFolder watchedFolder)
+        {
+            if (WatchedFoldersInternal.Contains(watchedFolder))
+            {
+                return false;
+            }
+            if (!Factory.New<IRuntimeFileInfo>(watchedFolder.Path).IsExistingFolder)
+            {
+                return false;
+            }
+
+            WatchedFolder copy = new WatchedFolder(watchedFolder);
+            copy.Changed += watchedFolder_Changed;
+            WatchedFoldersInternal.Add(copy);
+            return true;
+        }
+
+        private void watchedFolder_Changed(object sender, FileWatcherEventArgs e)
+        {
+            WatchedFolder watchedFolder = (WatchedFolder)sender;
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(e.FullName);
+            HandleWatchedFolderChanges(watchedFolder, fileInfo);
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.WatchedFolderChange, fileInfo.FullName));
+        }
+
+        private void HandleWatchedFolderChanges(WatchedFolder watchedFolder, IRuntimeFileInfo fileInfo)
+        {
+            if (watchedFolder.Path == fileInfo.FullName && !fileInfo.IsExistingFolder)
+            {
+                RemoveWatchedFolder(fileInfo);
+                Save();
+                return;
+            }
+            if (!fileInfo.IsEncrypted())
+            {
+                return;
+            }
+            if (IsExisting(fileInfo))
+            {
+                return;
+            }
+            RemoveDeletedActiveFile(fileInfo);
+        }
+
+        private static bool IsExisting(IRuntimeFileInfo fileInfo)
+        {
+            return fileInfo.Type() != FileInfoTypes.NonExisting;
+        }
+
+        private void RemoveDeletedActiveFile(IRuntimeFileInfo fileInfo)
+        {
+            ActiveFile removedActiveFile = FindActiveFileFromEncryptedPath(fileInfo.FullName);
+            if (removedActiveFile != null)
+            {
+                RemoveActiveFile(removedActiveFile);
+                Save();
+            }
+        }
+
+        public virtual void RemoveWatchedFolder(IRuntimeFileInfo fileInfo)
+        {
+            WatchedFoldersInternal.Remove(new WatchedFolder(fileInfo.FullName, SymmetricKeyThumbprint.Zero));
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.WatchedFolderRemoved, Instance.KnownKeys.DefaultEncryptionKey, fileInfo.FullName));
+        }
+
+        public event EventHandler<ActiveFileChangedEventArgs> ActiveFileChanged;
+
+        protected virtual void OnActiveFileChanged(ActiveFileChangedEventArgs e)
+        {
+            EventHandler<ActiveFileChangedEventArgs> handler = ActiveFileChanged;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public IEnumerable<ActiveFile> ActiveFiles
+        {
+            get
+            {
+                lock (_activeFilesByEncryptedPath)
+                {
+                    return new List<ActiveFile>(_activeFilesByEncryptedPath.Values);
+                }
+            }
+        }
+
+        public int ActiveFileCount
+        {
+            get
+            {
+                return _activeFilesByEncryptedPath.Count;
+            }
+        }
+
+        public IList<ActiveFile> DecryptedActiveFiles
+        {
+            get
+            {
+                List<ActiveFile> activeFiles = new List<ActiveFile>();
+                foreach (ActiveFile activeFile in ActiveFiles)
+                {
+                    if (activeFile.Status.HasMask(ActiveFileStatus.DecryptedIsPendingDelete) || activeFile.Status.HasMask(ActiveFileStatus.AssumedOpenAndDecrypted))
+                    {
+                        activeFiles.Add(activeFile);
+                    }
+                }
+                return activeFiles;
+            }
+        }
+
+        /// <summary>
+        /// Find an active file by way of it's encrypted full path.
+        /// </summary>
+        /// <param name="decryptedPath">Full path to an encrypted file.</param>
+        /// <returns>An ActiveFile instance, or null if not found in file system state.</returns>
+        public virtual ActiveFile FindActiveFileFromEncryptedPath(string encryptedPath)
+        {
+            if (encryptedPath == null)
+            {
+                throw new ArgumentNullException("encryptedPath");
+            }
+            encryptedPath = encryptedPath.NormalizeFilePath();
+            ActiveFile activeFile;
+            lock (_activeFilesByEncryptedPath)
+            {
+                if (_activeFilesByEncryptedPath.TryGetValue(encryptedPath, out activeFile))
+                {
+                    return activeFile;
+                }
+            }
+            return null;
+        }
+
+        /// <summary>
+        /// Add a file to the volatile file system state. To persist, call Save().
+        /// </summary>
+        /// <param name="activeFile">The active file to save</param>
+        public void Add(ActiveFile activeFile)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            AddInternal(activeFile);
+            OnActiveFileChanged(new ActiveFileChangedEventArgs(activeFile));
+        }
+
+        public void Add(ActiveFile activeFile, ILauncher process)
+        {
+            Instance.ProcessState.Add(process, activeFile);
+            Add(activeFile);
+        }
+
+        public virtual void PurgeActiveFiles()
+        {
+            foreach (ActiveFile activeFile in ActiveFiles)
+            {
+                if (!activeFile.EncryptedFileInfo.IsExistingFile)
+                {
+                    RemoveActiveFile(activeFile);
+                    continue;
+                }
+                if (!activeFile.Status.HasFlag(ActiveFileStatus.Inactive))
+                {
+                    continue;
+                }
+                Guid cryptoId;
+                Passphrase passphrase = activeFile.EncryptedFileInfo.TryFindPassphrase(out cryptoId);
+                if (passphrase == null)
+                {
+                    continue;
+                }
+                ActiveFile resurrectedActiveFile = new ActiveFile(activeFile.EncryptedFileInfo, activeFile.DecryptedFileInfo, passphrase, activeFile.Status & ~ActiveFileStatus.Inactive, cryptoId);
+                Add(resurrectedActiveFile);
+            }
+            Save();
+        }
+
+        /// <summary>
+        /// Remove a file from the volatile file system state. To persist, call Save().
+        /// </summary>
+        /// <param name="activeFile">An active file to remove</param>
+        public virtual void RemoveActiveFile(ActiveFile activeFile)
+        {
+            if (activeFile == null)
+            {
+                throw new ArgumentNullException("activeFile");
+            }
+            lock (_activeFilesByEncryptedPath)
+            {
+                activeFile = new ActiveFile(activeFile, activeFile.Status | ActiveFileStatus.Inactive);
+                _activeFilesByEncryptedPath[activeFile.EncryptedFileInfo.FullName] = activeFile;
+            }
+            OnActiveFileChanged(new ActiveFileChangedEventArgs(activeFile));
+        }
+
+        public virtual void ChangeActiveFile(string oldFullName, string newFullName)
+        {
+            ActiveFile activeFile;
+            lock (_activeFilesByEncryptedPath)
+            {
+                activeFile = FindActiveFileFromEncryptedPath(oldFullName);
+                if (activeFile == null)
+                {
+                    return;
+                }
+
+                IRuntimeFileInfo newFileInfo = Factory.New<IRuntimeFileInfo>(newFullName);
+                if (!newFileInfo.IsEncrypted())
+                {
+                    RemoveActiveFile(activeFile);
+                    return;
+                }
+
+                _activeFilesByEncryptedPath.Remove(activeFile.EncryptedFileInfo.FullName);
+                activeFile = new ActiveFile(activeFile, Factory.New<IRuntimeFileInfo>(newFullName));
+                _activeFilesByEncryptedPath[activeFile.EncryptedFileInfo.FullName] = activeFile;
+            }
+            OnActiveFileChanged(new ActiveFileChangedEventArgs(activeFile));
+        }
+
+        private void AddInternal(ActiveFile activeFile)
+        {
+            lock (_activeFilesByEncryptedPath)
+            {
+                _activeFilesByEncryptedPath[activeFile.EncryptedFileInfo.FullName] = activeFile;
+            }
+            Factory.Instance.Singleton<ActiveFileWatcher>().Add(activeFile.EncryptedFileInfo);
+        }
+
+        [DataMember(Name = "ActiveFiles")]
+        private ICollection<ActiveFile> ActiveFilesForSerialization
+        {
+            get
+            {
+                lock (_activeFilesByEncryptedPath)
+                {
+                    return new ActiveFileCollection(_activeFilesByEncryptedPath.Values);
+                }
+            }
+            set
+            {
+                SetRangeInternal(value, ActiveFileStatus.Error | ActiveFileStatus.IgnoreChange | ActiveFileStatus.NotShareable);
+            }
+        }
+
+        private void SetRangeInternal(IEnumerable<ActiveFile> activeFiles, ActiveFileStatus mask)
+        {
+            lock (_activeFilesByEncryptedPath)
+            {
+                _activeFilesByEncryptedPath.Clear();
+            }
+            foreach (ActiveFile activeFile in activeFiles)
+            {
+                ActiveFile thisActiveFile = activeFile;
+                if ((activeFile.Status & mask) != 0)
+                {
+                    thisActiveFile = new ActiveFile(activeFile, activeFile.Status & ~mask);
+                }
+                AddInternal(thisActiveFile);
+            }
+        }
+
+        /// <summary>
+        /// Iterate over all active files in the state.
+        /// </summary>
+        /// <param name="mode">RaiseAlways to raise Changed event for each active file, RaiseOnlyOnModified to only raise for modified active files.</param>
+        /// <param name="action">A delegate with an action to take for each active file, returning the same or updated active file as need be.</param>
+        public void ForEach(ChangedEventMode mode, Func<ActiveFile, ActiveFile> action)
+        {
+            if (action == null)
+            {
+                throw new ArgumentNullException("action");
+            }
+
+            bool isAnyModified = false;
+            List<ActiveFile> activeFiles = new List<ActiveFile>();
+            List<ActiveFile> updatedActiveFiles = new List<ActiveFile>();
+            foreach (ActiveFile activeFile in ActiveFiles)
+            {
+                ActiveFile updatedActiveFile = action(activeFile);
+                activeFiles.Add(updatedActiveFile);
+                bool isModified = updatedActiveFile != activeFile;
+                if (isModified || mode == ChangedEventMode.RaiseAlways)
+                {
+                    updatedActiveFiles.Add(updatedActiveFile);
+                }
+                isAnyModified |= isModified;
+            }
+            if (isAnyModified)
+            {
+                SetRangeInternal(activeFiles, ActiveFileStatus.None);
+                Save();
+            }
+            foreach (ActiveFile updatedActiveFile in updatedActiveFiles)
+            {
+                OnActiveFileChanged(new ActiveFileChangedEventArgs(updatedActiveFile));
+            }
+        }
+
+        private IRuntimeFileInfo _path;
+
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "The actual exception thrown by the de-serialization varies, even by platform, and the idea is to catch those and let the user continue.")]
+        public static FileSystemState Create(IRuntimeFileInfo path)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException("path");
+            }
+
+            if (path.IsExistingFile)
+            {
+                return CreateFileSystemState(path);
+            }
+
+            FileSystemState fileSystemState = new FileSystemState(path);
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("No existing FileSystemState. Save location is '{0}'.".InvariantFormat(path.FullName));
+            }
+            return fileSystemState;
+        }
+
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "If the state can't be read, the software is rendered useless, so it's better to revert to empty here.")]
+        private static FileSystemState CreateFileSystemState(IRuntimeFileInfo path)
+        {
+            using (Stream fileSystemStateStream = path.OpenRead())
+            {
+                FileSystemState fileSystemState;
+                try
+                {
+                    DataContractSerializer serializer = CreateSerializer();
+                    fileSystemState = (FileSystemState)serializer.ReadObject(fileSystemStateStream);
+                }
+                catch (Exception ex)
+                {
+                    if (Instance.Log.IsErrorEnabled)
+                    {
+                        Instance.Log.LogError("Exception {1} reading {0}. Ignoring and re-initializing state.".InvariantFormat(path.FullName, ex.Message));
+                    }
+                    return new FileSystemState(path);
+                }
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Loaded FileSystemState from '{0}'.".InvariantFormat(path));
+                }
+                fileSystemState._path = path;
+                return fileSystemState;
+            }
+        }
+
+        public virtual void Save()
+        {
+            lock (_activeFilesByEncryptedPath)
+            {
+                using (Stream fileSystemStateStream = _path.OpenWrite())
+                {
+                    fileSystemStateStream.SetLength(0);
+                    DataContractSerializer serializer = CreateSerializer();
+                    serializer.WriteObject(fileSystemStateStream, this);
+                }
+            }
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Wrote FileSystemState to '{0}'.".InvariantFormat(_path));
+            }
+        }
+
+        public void Delete()
+        {
+            _path.Delete();
+        }
+
+        private static DataContractSerializer CreateSerializer()
+        {
+            DataContractSerializer serializer = new DataContractSerializer(typeof(FileSystemState), "FileSystemState", "http://www.axantum.com/Serialization/");
+            return serializer;
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_watchedFolders != null)
+            {
+                foreach (WatchedFolder watchedFolder in _watchedFolders)
+                {
+                    watchedFolder.Dispose();
+                }
+                _watchedFolders = null;
+            }
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/PassphraseIdentity.cs b/Axantum.AxCrypt.Core/Session/PassphraseIdentity.cs
new file mode 100644
index 0000000..5b2dad0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/PassphraseIdentity.cs
@@ -0,0 +1,61 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// A passphrase identity, associating a persisted thumbprint with an optional transient key.
+    /// Instances of this class are immutable.
+    /// </summary>
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class PassphraseIdentity
+    {
+        [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "This type is immutable.")]
+        public static readonly PassphraseIdentity Empty = new PassphraseIdentity(Passphrase.Empty);
+
+        public PassphraseIdentity()
+        {
+        }
+
+        public PassphraseIdentity(Passphrase key)
+        {
+            Key = key;
+            Thumbprint = Key.Thumbprint;
+        }
+
+        public Passphrase Key { get; private set; }
+
+        [DataMember(Name = "Thumbprint")]
+        public SymmetricKeyThumbprint Thumbprint { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/ProcessState.cs b/Axantum.AxCrypt.Core/Session/ProcessState.cs
new file mode 100644
index 0000000..32d3d28
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/ProcessState.cs
@@ -0,0 +1,142 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class ProcessState : IDisposable
+    {
+        private Dictionary<string, List<ILauncher>> _processState = new Dictionary<string, List<ILauncher>>();
+
+        private readonly object _lock = new object();
+
+        public void Add(ILauncher launcher, ActiveFile activeFile)
+        {
+            PurgeInactive();
+            lock (_lock)
+            {
+                List<ILauncher> processes = ActiveProcesses(activeFile);
+                if (processes == null)
+                {
+                    processes = new List<ILauncher>();
+                    _processState[activeFile.EncryptedFileInfo.FullName] = processes;
+                }
+                processes.Add(launcher);
+            }
+        }
+
+        public bool HasActiveProcess(ActiveFile activeFile)
+        {
+            lock (_lock)
+            {
+                List<ILauncher> processes = ActiveProcesses(activeFile);
+                if (processes == null)
+                {
+                    return false;
+                }
+                foreach (ILauncher process in processes)
+                {
+                    if (!process.HasExited)
+                    {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        private List<ILauncher> ActiveProcesses(ActiveFile activeFile)
+        {
+            lock (_lock)
+            {
+                List<ILauncher> processes;
+                if (!_processState.TryGetValue(activeFile.EncryptedFileInfo.FullName, out processes))
+                {
+                    return null;
+                }
+                return processes;
+            }
+        }
+
+        private void PurgeInactive()
+        {
+            lock (_lock)
+            {
+                foreach (List<ILauncher> processes in _processState.Values)
+                {
+                    for (int i = 0; i < processes.Count; ++i)
+                    {
+                        if (!processes[i].HasExited)
+                        {
+                            continue;
+                        }
+                        processes[i].Dispose();
+                        processes.RemoveAt(i);
+                        --i;
+                    }
+                }
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            lock (_lock)
+            {
+                if (_processState == null)
+                {
+                    return;
+                }
+                foreach (List<ILauncher> processes in _processState.Values)
+                {
+                    foreach (ILauncher process in processes)
+                    {
+                        process.Dispose();
+                    }
+                }
+                _processState = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/SessionNotification.cs b/Axantum.AxCrypt.Core/Session/SessionNotification.cs
new file mode 100644
index 0000000..a0788c2
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/SessionNotification.cs
@@ -0,0 +1,146 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class SessionNotification : IEquatable<SessionNotification>
+    {
+        public Passphrase Key { get; private set; }
+
+        public string FullName { get; private set; }
+
+        public string OtherFullName { get; private set; }
+
+        public SessionNotificationType NotificationType { get; private set; }
+
+        public SessionNotification(SessionNotificationType notificationType, Passphrase key, string fullName, string otherFullName)
+        {
+            NotificationType = notificationType;
+            Key = key;
+            FullName = fullName;
+            OtherFullName = otherFullName;
+        }
+
+        public SessionNotification(SessionNotificationType notificationType, Passphrase key, string fullName)
+            : this(notificationType, key, fullName, String.Empty)
+        {
+        }
+
+        public SessionNotification(SessionNotificationType notificationType, string fullName, string otherFullName)
+            : this(notificationType, Passphrase.Empty, fullName, otherFullName)
+        {
+        }
+
+        public SessionNotification(SessionNotificationType notificationType, string fullName)
+            : this(notificationType, Passphrase.Empty, fullName)
+        {
+        }
+
+        public SessionNotification(SessionNotificationType notificationType, Passphrase key)
+            : this(notificationType, key, String.Empty)
+        {
+        }
+
+        public SessionNotification(SessionNotificationType notificationType)
+            : this(notificationType, Passphrase.Empty, String.Empty)
+        {
+        }
+
+        #region IEquatable<AesKey> Members
+
+        public bool Equals(SessionNotification other)
+        {
+            if ((object)other == null)
+            {
+                return false;
+            }
+
+            if (other.NotificationType != NotificationType)
+            {
+                return false;
+            }
+
+            if (!other.Key.Equals(Key))
+            {
+                return false;
+            }
+
+            if (other.FullName != FullName)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        #endregion IEquatable<AesKey> Members
+
+        public override bool Equals(object obj)
+        {
+            if (obj == null || typeof(SessionNotification) != obj.GetType())
+            {
+                return false;
+            }
+            SessionNotification other = (SessionNotification)obj;
+
+            return Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            int hashcode;
+
+            hashcode = Key != null ? Key.GetHashCode() : 0;
+            hashcode ^= FullName != null ? FullName.GetHashCode() : 0;
+            hashcode ^= NotificationType.GetHashCode();
+
+            return hashcode;
+        }
+
+        public static bool operator ==(SessionNotification left, SessionNotification right)
+        {
+            if (Object.ReferenceEquals(left, right))
+            {
+                return true;
+            }
+            if ((object)left == null)
+            {
+                return false;
+            }
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(SessionNotification left, SessionNotification right)
+        {
+            return !(left == right);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/SessionNotificationEventArgs.cs b/Axantum.AxCrypt.Core/Session/SessionNotificationEventArgs.cs
new file mode 100644
index 0000000..5a4689c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/SessionNotificationEventArgs.cs
@@ -0,0 +1,42 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class SessionNotificationEventArgs : EventArgs
+    {
+        public SessionNotification Notification { get; private set; }
+
+        public SessionNotificationEventArgs(SessionNotification notification)
+        {
+            Notification = notification;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/SessionNotificationHandler.cs b/Axantum.AxCrypt.Core/Session/SessionNotificationHandler.cs
new file mode 100644
index 0000000..51eb4bf
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/SessionNotificationHandler.cs
@@ -0,0 +1,135 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class SessionNotificationHandler
+    {
+        private FileSystemState _fileSystemState;
+
+        private KnownKeys _knownKeys;
+
+        private ActiveFileAction _activeFileAction;
+
+        private AxCryptFile _axCryptFile;
+
+        private IStatusChecker _statusChecker;
+
+        public SessionNotificationHandler(FileSystemState fileSystemState, KnownKeys knownKeys, ActiveFileAction activeFileAction, AxCryptFile axCryptFile, IStatusChecker statusChecker)
+        {
+            _fileSystemState = fileSystemState;
+            _knownKeys = knownKeys;
+            _activeFileAction = activeFileAction;
+            _axCryptFile = axCryptFile;
+            _statusChecker = statusChecker;
+        }
+
+        public virtual void HandleNotification(SessionNotification notification)
+        {
+            Instance.ProgressBackground.Work(
+                (IProgressContext progress) =>
+                {
+                    progress.NotifyLevelStart();
+                    try
+                    {
+                        HandleNotificationInternal(notification, progress);
+                        _activeFileAction.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, progress);
+                    }
+                    finally
+                    {
+                        progress.NotifyLevelFinished();
+                    }
+                    return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                },
+                (FileOperationContext status) =>
+                {
+                });
+        }
+
+        private void HandleNotificationInternal(SessionNotification notification, IProgressContext progress)
+        {
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Received notification type '{0}'.".InvariantFormat(notification.NotificationType));
+            }
+            switch (notification.NotificationType)
+            {
+                case SessionNotificationType.WatchedFolderAdded:
+                    IRuntimeFileInfo addedFolderInfo = Factory.New<IRuntimeFileInfo>(notification.FullName);
+                    _axCryptFile.EncryptFoldersUniqueWithBackupAndWipe(new IRuntimeFileInfo[] { addedFolderInfo }, notification.Key, Instance.CryptoFactory.Default.Id, progress);
+                    break;
+
+                case SessionNotificationType.WatchedFolderRemoved:
+                    IRuntimeFileInfo removedFolderInfo = Factory.New<IRuntimeFileInfo>(notification.FullName);
+                    if (removedFolderInfo.IsExistingFolder)
+                    {
+                        _axCryptFile.DecryptFilesInsideFolderUniqueWithWipeOfOriginal(removedFolderInfo, notification.Key, _statusChecker, progress);
+                    }
+                    break;
+
+                case SessionNotificationType.LogOn:
+                case SessionNotificationType.LogOff:
+                    _axCryptFile.EncryptFoldersUniqueWithBackupAndWipe(_fileSystemState.WatchedFolders.Where(wf => wf.Thumbprint == notification.Key.Thumbprint).Select(wf => Factory.New<IRuntimeFileInfo>(wf.Path)), notification.Key, Instance.CryptoFactory.Default.Id, progress);
+                    break;
+
+                case SessionNotificationType.SessionStart:
+                    _activeFileAction.CheckActiveFiles(ChangedEventMode.RaiseAlways, progress);
+                    break;
+
+                case SessionNotificationType.EncryptPendingFiles:
+                    _activeFileAction.PurgeActiveFiles(progress);
+                    _axCryptFile.EncryptFoldersUniqueWithBackupAndWipe(_knownKeys.LoggedOnWatchedFolders.Select(wf => Factory.New<IRuntimeFileInfo>(wf.Path)), _knownKeys.DefaultEncryptionKey, Instance.CryptoFactory.Default.Id, progress);
+                    break;
+
+                case SessionNotificationType.PurgeActiveFiles:
+                    _fileSystemState.PurgeActiveFiles();
+                    break;
+
+                case SessionNotificationType.FileMove:
+                    _fileSystemState.ChangeActiveFile(notification.OtherFullName, notification.FullName);
+                    break;
+
+                case SessionNotificationType.WatchedFolderChange:
+                case SessionNotificationType.ProcessExit:
+                case SessionNotificationType.ActiveFileChange:
+                case SessionNotificationType.KnownKeyChange:
+                case SessionNotificationType.SessionChange:
+                case SessionNotificationType.WorkFolderChange:
+                    break;
+
+                default:
+                    throw new InvalidOperationException("Unhandled notification recieved");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/SessionNotificationType.cs b/Axantum.AxCrypt.Core/Session/SessionNotificationType.cs
new file mode 100644
index 0000000..2e57b25
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/SessionNotificationType.cs
@@ -0,0 +1,50 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public enum SessionNotificationType
+    {
+        ActiveFileChange,
+        WatchedFolderAdded,
+        WatchedFolderRemoved,
+        LogOn,
+        LogOff,
+        ProcessExit,
+        SessionChange,
+        SessionStart,
+        KnownKeyChange,
+        WorkFolderChange,
+        EncryptPendingFiles,
+        WatchedFolderChange,
+        PurgeActiveFiles,
+        FileMove,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/SessionNotify.cs b/Axantum.AxCrypt.Core/Session/SessionNotify.cs
new file mode 100644
index 0000000..3843b63
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/SessionNotify.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class SessionNotify
+    {
+        public SessionNotify()
+        {
+        }
+
+        public event EventHandler<SessionNotificationEventArgs> Notification;
+
+        protected virtual void OnNotification(SessionNotificationEventArgs e)
+        {
+            EventHandler<SessionNotificationEventArgs> handler = Notification;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public virtual void Notify(SessionNotification notification)
+        {
+            OnNotification(new SessionNotificationEventArgs(notification));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/UserAsymmetricKeys.cs b/Axantum.AxCrypt.Core/Session/UserAsymmetricKeys.cs
new file mode 100644
index 0000000..cc1b806
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/UserAsymmetricKeys.cs
@@ -0,0 +1,45 @@
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Serialization;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// A respository for a single user e-mail. A user has a single active key pair, with both a public
+    /// key for encryption and the matching private key for decryption. There may also be a list of
+    /// previously used private keys, in order to be able to decrypt files encrypted with older key pairs.
+    /// </summary>
+    [JsonObject(MemberSerialization.OptIn)]
+    public class UserAsymmetricKeys
+    {
+        [JsonConstructor]
+        private UserAsymmetricKeys()
+        {
+            RecalledPrivateKeys = new List<IAsymmetricPrivateKey>();
+        }
+
+        public UserAsymmetricKeys(EmailAddress userEmail, int bits)
+        {
+            UserEmail = userEmail;
+            RecalledPrivateKeys = new List<IAsymmetricPrivateKey>();
+            KeyPair = Factory.Instance.Singleton<IAsymmetricFactory>().CreateKeyPair(bits);
+        }
+
+        [JsonProperty("useremail")]
+        [JsonConverter(typeof(EmailAddressJsonConverter))]
+        public EmailAddress UserEmail { get; private set; }
+
+        [JsonProperty("recalledprivatekeys")]
+        public IList<IAsymmetricPrivateKey> RecalledPrivateKeys { get; private set; }
+
+        [JsonProperty("keypair")]
+        public IAsymmetricKeyPair KeyPair { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/UserAsymmetricKeysStore.cs b/Axantum.AxCrypt.Core/Session/UserAsymmetricKeysStore.cs
new file mode 100644
index 0000000..ba9b1c7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/UserAsymmetricKeysStore.cs
@@ -0,0 +1,184 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.UI;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// Persists a users asymmetric keys in the file system, encrypted with AxCrypt
+    /// </summary>
+    public class UserAsymmetricKeysStore
+    {
+        private class KeysStoreFile
+        {
+            public KeysStoreFile(UserAsymmetricKeys userKeys, string id, IRuntimeFileInfo file)
+            {
+                UserKeys = userKeys;
+                Id = id;
+                File = file;
+            }
+
+            public UserAsymmetricKeys UserKeys { get; private set; }
+
+            public string Id { get; private set; }
+
+            public IRuntimeFileInfo File { get; private set; }
+        }
+
+        private static Regex _filePattern = new Regex(@"^Keys-([\d]+)-txt\.axx$");
+
+        private const string _fileFormat = "Keys-{0}.txt";
+
+        private IRuntimeFileInfo _folderPath;
+
+        private KnownKeys _knownKeys;
+
+        private KeysStoreFile _keysStoreFile;
+
+        public UserAsymmetricKeysStore(IRuntimeFileInfo folderPath, KnownKeys knownKeys)
+        {
+            _folderPath = folderPath;
+            _knownKeys = knownKeys;
+        }
+
+        public bool Load(EmailAddress userEmail, Passphrase passphrase)
+        {
+            _keysStoreFile = null;
+
+            _keysStoreFile = TryLoadKeyStoreFile(userEmail, passphrase);
+            if (_keysStoreFile == null)
+            {
+                return false;
+            }
+            _knownKeys.DefaultEncryptionKey = passphrase;
+            return true;
+        }
+
+        public bool IsValidAccountLogOn(EmailAddress userEmail, Passphrase passphrase)
+        {
+            return TryLoadKeyStoreFile(userEmail, passphrase) != null;
+        }
+
+        private void CreateInternal(EmailAddress userEmail, Passphrase passphrase)
+        {
+            UserAsymmetricKeys userKeys = new UserAsymmetricKeys(userEmail, Instance.UserSettings.AsymmetricKeyBits);
+            string id = UniqueFilePart();
+            IRuntimeFileInfo file = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().Combine(_folderPath.FullName, _fileFormat.InvariantFormat(id)).CreateEncryptedName());
+
+            _keysStoreFile = new KeysStoreFile(userKeys, id, file);
+
+            Save(passphrase);
+        }
+
+        private KeysStoreFile TryLoadKeyStoreFile(EmailAddress userEmail, Passphrase passphrase)
+        {
+            foreach (IRuntimeFileInfo file in AsymmetricKeyFiles())
+            {
+                UserAsymmetricKeys keys = TryLoadKeys(file, passphrase);
+                if (keys == null)
+                {
+                    continue;
+                }
+                if (String.Compare(userEmail.Address, keys.UserEmail.Address, StringComparison.OrdinalIgnoreCase) != 0)
+                {
+                    continue;
+                }
+                return new KeysStoreFile(keys, IdFromFileName(file.Name), file);
+            }
+            return null;
+        }
+
+        private IEnumerable<IRuntimeFileInfo> AsymmetricKeyFiles()
+        {
+            return _folderPath.Files.Where(f => IdFromFileName(f.Name).Length > 0);
+        }
+
+        private string IdFromFileName(string fileName)
+        {
+            Match match = _filePattern.Match(fileName);
+            if (!match.Success)
+            {
+                return String.Empty;
+            }
+            return match.Groups[1].Value;
+        }
+
+        public void Create(EmailAddress userEmail, Passphrase passphrase)
+        {
+            _keysStoreFile = TryLoadKeyStoreFile(userEmail, passphrase);
+            if (_keysStoreFile != null)
+            {
+                return;
+            }
+            CreateInternal(userEmail, passphrase);
+        }
+
+        public UserAsymmetricKeys Keys
+        {
+            get
+            {
+                return _keysStoreFile.UserKeys;
+            }
+        }
+
+        public bool HasStore
+        {
+            get
+            {
+                return AsymmetricKeyFiles().Any();
+            }
+        }
+
+        public bool HasKeys
+        {
+            get
+            {
+                return _keysStoreFile != null;
+            }
+        }
+
+        private string UniqueFilePart()
+        {
+            DateTime now = OS.Current.UtcNow;
+            TimeSpan timeSince = now - new DateTime(now.Year, 1, 1);
+            return ((int)timeSince.TotalSeconds).ToString();
+        }
+
+        public void Save(Passphrase passphrase)
+        {
+            if (_keysStoreFile == null)
+            {
+                return;
+            }
+
+            string json = JsonConvert.SerializeObject(_keysStoreFile.UserKeys);
+            using (Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(json)))
+            {
+                Factory.New<AxCryptFile>().Encrypt(stream, _keysStoreFile.File.Name, _keysStoreFile.File, passphrase, Instance.CryptoFactory.Default.Id, AxCryptOptions.EncryptWithCompression, new ProgressContext());
+            }
+        }
+
+        private UserAsymmetricKeys TryLoadKeys(IRuntimeFileInfo file, Passphrase passphrase)
+        {
+            using (MemoryStream stream = new MemoryStream())
+            {
+                if (!Factory.New<AxCryptFile>().Decrypt(file, stream, passphrase))
+                {
+                    return null;
+                }
+
+                string json = Encoding.UTF8.GetString(stream.ToArray(), 0, (int)stream.Length);
+                return JsonConvert.DeserializeObject<UserAsymmetricKeys>(json, Factory.Instance.Singleton<IAsymmetricFactory>().GetConverters());
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/WatchedFolder.cs b/Axantum.AxCrypt.Core/Session/WatchedFolder.cs
new file mode 100644
index 0000000..e173033
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/WatchedFolder.cs
@@ -0,0 +1,184 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Extensions;
+using System;
+using System.Linq;
+using System.Runtime.Serialization;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    /// <summary>
+    /// Holds information about a folder that is watched for file changes, to enable
+    /// automatic encryption of files for example. Instances of this class are
+    /// immutable
+    /// </summary>
+    [DataContract(Namespace = "http://www.axantum.com/Serialization/")]
+    public class WatchedFolder : IEquatable<WatchedFolder>, IDisposable
+    {
+        [DataMember(Name = "Path")]
+        public string Path { get; private set; }
+
+        private IFileWatcher _fileWatcher;
+
+        public event EventHandler<FileWatcherEventArgs> Changed;
+
+        public WatchedFolder(string path, SymmetricKeyThumbprint thumbprint)
+        {
+            if (path == null)
+            {
+                throw new ArgumentNullException("path");
+            }
+            if (thumbprint == null)
+            {
+                throw new ArgumentNullException("thumbprint");
+            }
+
+            Path = path.NormalizeFolderPath();
+            Thumbprint = thumbprint;
+            Initialize(new StreamingContext());
+        }
+
+        public WatchedFolder(string fullName)
+            : this(fullName, SymmetricKeyThumbprint.Zero)
+        {
+        }
+
+        public WatchedFolder(WatchedFolder watchedFolder)
+        {
+            Path = watchedFolder.Path;
+            Thumbprint = watchedFolder.Thumbprint;
+            Initialize(new StreamingContext());
+        }
+
+        [DataMember(Name = "Thumbprint")]
+        public SymmetricKeyThumbprint Thumbprint
+        {
+            get;
+            private set;
+        }
+
+        [OnDeserialized]
+        private void Initialize(StreamingContext context)
+        {
+            if (Factory.New<IRuntimeFileInfo>(Path).IsExistingFolder)
+            {
+                _fileWatcher = Factory.New<IFileWatcher>(Path);
+                _fileWatcher.FileChanged += _fileWatcher_FileChanged;
+            }
+        }
+
+        private void _fileWatcher_FileChanged(object sender, FileWatcherEventArgs e)
+        {
+            OnChanged(e);
+        }
+
+        protected virtual void OnChanged(FileWatcherEventArgs e)
+        {
+            EventHandler<FileWatcherEventArgs> handler = Changed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public bool Equals(WatchedFolder other)
+        {
+            if (other == null)
+            {
+                return false;
+            }
+
+            if (Object.ReferenceEquals(this, other))
+            {
+                return true;
+            }
+
+            return String.Compare(Path, other.Path, StringComparison.OrdinalIgnoreCase) == 0;
+        }
+
+        public override bool Equals(object obj)
+        {
+            WatchedFolder watchedFolder = obj as WatchedFolder;
+            if (watchedFolder == null)
+            {
+                return false;
+            }
+
+            return Equals(watchedFolder);
+        }
+
+        public override int GetHashCode()
+        {
+            return Path.GetHashCode();
+        }
+
+        public static bool operator ==(WatchedFolder left, WatchedFolder right)
+        {
+            if ((object)left == null || ((object)right == null))
+            {
+                return Object.Equals(left, right);
+            }
+
+            return left.Equals(right);
+        }
+
+        public static bool operator !=(WatchedFolder left, WatchedFolder right)
+        {
+            return !(left == right);
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_fileWatcher != null)
+            {
+                _fileWatcher.Dispose();
+                _fileWatcher = null;
+            }
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/Session/WatchedFolderChangedEventArgs.cs b/Axantum.AxCrypt.Core/Session/WatchedFolderChangedEventArgs.cs
new file mode 100644
index 0000000..00e5352
--- /dev/null
+++ b/Axantum.AxCrypt.Core/Session/WatchedFolderChangedEventArgs.cs
@@ -0,0 +1,47 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.Session
+{
+    public class WatchedFolderChangedEventArgs : EventArgs
+    {
+        public WatchedFolderChangedEventArgs(IEnumerable<WatchedFolder> added, IEnumerable<WatchedFolder> removed)
+        {
+            Added = new List<WatchedFolder>(added);
+            Removed = new List<WatchedFolder>(removed);
+        }
+
+        public IEnumerable<WatchedFolder> Added { get; private set; }
+
+        public IEnumerable<WatchedFolder> Removed { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/CancelProgressContext.cs b/Axantum.AxCrypt.Core/UI/CancelProgressContext.cs
new file mode 100644
index 0000000..96ab99a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/CancelProgressContext.cs
@@ -0,0 +1,140 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class CancelProgressContext : IProgressContext
+    {
+        private IProgressContext _progress;
+
+        private long _totalCount;
+
+        private long _currentCount;
+
+        private bool _canceledExceptionThrown;
+
+        public CancelProgressContext(IProgressContext progress)
+        {
+            _progress = progress;
+        }
+
+        public void AddCount(long count)
+        {
+            _currentCount += count;
+            _progress.AddCount(count);
+
+            ThrowIfCancelled();
+        }
+
+        private void ThrowIfCancelled()
+        {
+            if (!Cancel || _canceledExceptionThrown)
+            {
+                return;
+            }
+
+            _progress.AddCount(_totalCount - _currentCount);
+            _currentCount = _totalCount;
+            _canceledExceptionThrown = true;
+            throw new OperationCanceledException("Operation canceled on request.");
+        }
+
+        public void NotifyLevelStart()
+        {
+            ThrowIfCancelled();
+            _progress.NotifyLevelStart();
+        }
+
+        public void NotifyLevelFinished()
+        {
+            ThrowIfCancelled();
+            _progress.NotifyLevelFinished();
+        }
+
+        public bool Cancel
+        {
+            get
+            {
+                return _progress.Cancel;
+            }
+            set
+            {
+                _progress.Cancel = value;
+            }
+        }
+
+        public void RemoveCount(long totalCount, long progressCount)
+        {
+            _progress.RemoveCount(totalCount, progressCount);
+        }
+
+        public void AddTotal(long count)
+        {
+            ThrowIfCancelled();
+
+            _totalCount += count;
+            _progress.AddTotal(count);
+        }
+
+        public bool AllItemsConfirmed
+        {
+            get
+            {
+                return _progress.AllItemsConfirmed;
+            }
+            set
+            {
+                _progress.AllItemsConfirmed = value;
+            }
+        }
+
+        public event EventHandler<ProgressEventArgs> Progressing
+        {
+            add
+            {
+                _progress.Progressing += value;
+            }
+            remove
+            {
+                _progress.Progressing -= value;
+            }
+        }
+
+        public void EnterSingleThread()
+        {
+            _progress.EnterSingleThread();
+        }
+
+        public void LeaveSingleThread()
+        {
+            _progress.LeaveSingleThread();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/EmailAddress.cs b/Axantum.AxCrypt.Core/UI/EmailAddress.cs
new file mode 100644
index 0000000..cba70e4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/EmailAddress.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class EmailAddress
+    {
+        public string Address { get; set; }
+
+        public EmailAddress(string address)
+        {
+            Address = address;
+        }
+
+        public override string ToString()
+        {
+            return Address;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/FileOperation.cs b/Axantum.AxCrypt.Core/UI/FileOperation.cs
new file mode 100644
index 0000000..91c0580
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/FileOperation.cs
@@ -0,0 +1,300 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class FileOperation
+    {
+        private FileSystemState _fileSystemState;
+        private SessionNotify _sessionNotify;
+
+        public FileOperation(FileSystemState fileSystemState, SessionNotify sessionNotify)
+        {
+            _fileSystemState = fileSystemState;
+            _sessionNotify = sessionNotify;
+        }
+
+        public FileOperationContext OpenAndLaunchApplication(string file, IEnumerable<Passphrase> keys, IProgressContext progress)
+        {
+            if (file == null)
+            {
+                throw new ArgumentNullException("file");
+            }
+            if (keys == null)
+            {
+                throw new ArgumentNullException("keys");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            IRuntimeFileInfo fileInfo = Factory.New<IRuntimeFileInfo>(file);
+            if (!fileInfo.IsExistingFile)
+            {
+                if (Instance.Log.IsWarningEnabled)
+                {
+                    Instance.Log.LogWarning("Tried to open non-existing '{0}'.".InvariantFormat(fileInfo.FullName));
+                }
+                return new FileOperationContext(fileInfo.FullName, FileOperationStatus.FileDoesNotExist);
+            }
+
+            ActiveFile destinationActiveFile = _fileSystemState.FindActiveFileFromEncryptedPath(fileInfo.FullName);
+
+            if (destinationActiveFile == null || !destinationActiveFile.DecryptedFileInfo.IsExistingFile)
+            {
+                IRuntimeFileInfo destinationFolderInfo = GetTemporaryDestinationFolder(destinationActiveFile);
+                destinationActiveFile = TryDecrypt(fileInfo, destinationFolderInfo, keys, progress);
+            }
+            else
+            {
+                destinationActiveFile = CheckKeysForAlreadyDecryptedFile(destinationActiveFile, keys, progress);
+            }
+
+            if (destinationActiveFile == null)
+            {
+                return new FileOperationContext(fileInfo.FullName, FileOperationStatus.InvalidKey);
+            }
+
+            _fileSystemState.Add(destinationActiveFile);
+            _fileSystemState.Save();
+
+            FileOperationContext status = LaunchApplicationForDocument(destinationActiveFile);
+            return status;
+        }
+
+        public virtual FileOperationContext OpenAndLaunchApplication(string encryptedFile, Passphrase passphrase, IAxCryptDocument document, IProgressContext progress)
+        {
+            if (encryptedFile == null)
+            {
+                throw new ArgumentNullException("encryptedFile");
+            }
+            if (passphrase == null)
+            {
+                throw new ArgumentNullException("passphrase");
+            }
+            if (document == null)
+            {
+                throw new ArgumentNullException("document");
+            }
+            if (progress == null)
+            {
+                throw new ArgumentNullException("progress");
+            }
+
+            IRuntimeFileInfo encryptedFileInfo = Factory.New<IRuntimeFileInfo>(encryptedFile);
+
+            ActiveFile encryptedActiveFile = _fileSystemState.FindActiveFileFromEncryptedPath(encryptedFileInfo.FullName);
+            encryptedActiveFile = EnsureDecryptedFolder(passphrase, document, encryptedFileInfo, encryptedActiveFile);
+            _fileSystemState.Add(encryptedActiveFile);
+            _fileSystemState.Save();
+
+            if (!encryptedActiveFile.DecryptedFileInfo.IsExistingFile)
+            {
+                DecryptActiveFileDocument(encryptedActiveFile, document, progress);
+            }
+            return LaunchApplicationForDocument(encryptedActiveFile);
+        }
+
+        private static ActiveFile EnsureDecryptedFolder(Passphrase passphrase, IAxCryptDocument document, IRuntimeFileInfo encryptedFileInfo, ActiveFile encryptedActiveFile)
+        {
+            if (encryptedActiveFile != null && encryptedActiveFile.DecryptedFileInfo.IsExistingFile)
+            {
+                encryptedActiveFile = new ActiveFile(encryptedActiveFile, passphrase);
+                return encryptedActiveFile;
+            }
+            IRuntimeFileInfo destinationFolderInfo = GetTemporaryDestinationFolder(encryptedActiveFile);
+            encryptedActiveFile = DestinationFileInfoFromDocument(encryptedFileInfo, destinationFolderInfo, passphrase, document);
+            return encryptedActiveFile;
+        }
+
+        private FileOperationContext LaunchApplicationForDocument(ActiveFile destinationActiveFile)
+        {
+            ActiveFileStatus status = ActiveFileStatus.AssumedOpenAndDecrypted;
+            ILauncher process;
+            try
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Starting process for '{0}'".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName));
+                }
+                process = OS.Current.Launch(destinationActiveFile.DecryptedFileInfo.FullName);
+                if (process.WasStarted)
+                {
+                    process.Exited += new EventHandler(process_Exited);
+                }
+                else
+                {
+                    status |= ActiveFileStatus.NoProcessKnown;
+                    if (Instance.Log.IsInfoEnabled)
+                    {
+                        Instance.Log.LogInfo("Starting process for '{0}' did not start a process, assumed handled by the shell.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName));
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                if (Instance.Log.IsErrorEnabled)
+                {
+                    Instance.Log.LogError("Could not launch application for '{0}', Exception was '{1}'.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName, ex.Message));
+                }
+                return new FileOperationContext(destinationActiveFile.DecryptedFileInfo.FullName, FileOperationStatus.CannotStartApplication);
+            }
+
+            if (Instance.Log.IsWarningEnabled)
+            {
+                if (process.HasExited)
+                {
+                    Instance.Log.LogWarning("The process seems to exit immediately for '{0}'".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName));
+                }
+            }
+
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Launched and opened '{0}'.".InvariantFormat(destinationActiveFile.DecryptedFileInfo.FullName));
+            }
+
+            destinationActiveFile = new ActiveFile(destinationActiveFile, status);
+            _fileSystemState.Add(destinationActiveFile, process);
+            _fileSystemState.Save();
+
+            return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+        }
+
+        private void process_Exited(object sender, EventArgs e)
+        {
+            string path = ((ILauncher)sender).Path;
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Process exit event for '{0}'.".InvariantFormat(path));
+            }
+
+            _sessionNotify.Notify(new SessionNotification(SessionNotificationType.ProcessExit, path));
+        }
+
+        private static ActiveFile TryDecrypt(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFolderInfo, IEnumerable<Passphrase> passphrases, IProgressContext progress)
+        {
+            ActiveFile destinationActiveFile = null;
+            foreach (Passphrase passphrase in passphrases)
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Decrypting '{0}'".InvariantFormat(sourceFileInfo.FullName));
+                }
+                using (FileLock sourceLock = FileLock.Lock(sourceFileInfo))
+                {
+                    using (IAxCryptDocument document = Factory.New<AxCryptFile>().Document(sourceFileInfo, passphrase, new ProgressContext()))
+                    {
+                        if (!document.PassphraseIsValid)
+                        {
+                            continue;
+                        }
+
+                        destinationActiveFile = DestinationFileInfoFromDocument(sourceFileInfo, destinationFolderInfo, passphrase, document);
+                        DecryptActiveFileDocument(destinationActiveFile, document, progress);
+                        break;
+                    }
+                }
+            }
+            return destinationActiveFile;
+        }
+
+        private static void DecryptActiveFileDocument(ActiveFile destinationActiveFile, IAxCryptDocument document, IProgressContext progress)
+        {
+            using (FileLock fileLock = FileLock.Lock(destinationActiveFile.DecryptedFileInfo))
+            {
+                Factory.New<AxCryptFile>().Decrypt(document, destinationActiveFile.DecryptedFileInfo, AxCryptOptions.SetFileTimes, progress);
+            }
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("File decrypted from '{0}' to '{1}'".InvariantFormat(destinationActiveFile.EncryptedFileInfo.FullName, destinationActiveFile.DecryptedFileInfo.FullName));
+            }
+        }
+
+        private static ActiveFile DestinationFileInfoFromDocument(IRuntimeFileInfo sourceFileInfo, IRuntimeFileInfo destinationFolderInfo, Passphrase passphrase, IAxCryptDocument document)
+        {
+            string destinationName = document.FileName;
+            string destinationPath = Instance.Portable.Path().Combine(destinationFolderInfo.FullName, destinationName);
+
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(destinationPath);
+            ActiveFile destinationActiveFile = new ActiveFile(sourceFileInfo, destinationFileInfo, passphrase, ActiveFileStatus.AssumedOpenAndDecrypted | ActiveFileStatus.IgnoreChange, document.CryptoFactory.Id);
+            return destinationActiveFile;
+        }
+
+        private static IRuntimeFileInfo GetTemporaryDestinationFolder(ActiveFile destinationActiveFile)
+        {
+            string destinationFolder;
+            if (destinationActiveFile != null)
+            {
+                destinationFolder = Instance.Portable.Path().GetDirectoryName(destinationActiveFile.DecryptedFileInfo.FullName);
+            }
+            else
+            {
+                destinationFolder = Instance.Portable.Path().Combine(Factory.Instance.Singleton<WorkFolder>().FileInfo.FullName, Instance.Portable.Path().GetFileNameWithoutExtension(Instance.Portable.Path().GetRandomFileName()) + Instance.Portable.Path().DirectorySeparatorChar);
+            }
+            IRuntimeFileInfo destinationFolderInfo = Factory.New<IRuntimeFileInfo>(destinationFolder);
+            destinationFolderInfo.CreateFolder();
+            return destinationFolderInfo;
+        }
+
+        public static string GetTemporaryDestinationName(string fileName)
+        {
+            string destinationFolder = Instance.Portable.Path().Combine(Factory.Instance.Singleton<WorkFolder>().FileInfo.FullName, Instance.Portable.Path().GetFileNameWithoutExtension(Instance.Portable.Path().GetRandomFileName()) + Instance.Portable.Path().DirectorySeparatorChar);
+            return Instance.Portable.Path().Combine(destinationFolder, Instance.Portable.Path().GetFileName(fileName));
+        }
+
+        private static ActiveFile CheckKeysForAlreadyDecryptedFile(ActiveFile destinationActiveFile, IEnumerable<Passphrase> keys, IProgressContext progress)
+        {
+            foreach (Passphrase key in keys)
+            {
+                using (IAxCryptDocument document = Factory.New<AxCryptFile>().Document(destinationActiveFile.EncryptedFileInfo, key, progress))
+                {
+                    if (document.PassphraseIsValid)
+                    {
+                        if (Instance.Log.IsWarningEnabled)
+                        {
+                            Instance.Log.LogWarning("File was already decrypted and the key was known for '{0}' to '{1}'".InvariantFormat(destinationActiveFile.EncryptedFileInfo.FullName, destinationActiveFile.DecryptedFileInfo.FullName));
+                        }
+                        return new ActiveFile(destinationActiveFile, key);
+                    }
+                }
+            }
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/FileOperationContext.cs b/Axantum.AxCrypt.Core/UI/FileOperationContext.cs
new file mode 100644
index 0000000..f398e2a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/FileOperationContext.cs
@@ -0,0 +1,47 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class FileOperationContext
+    {
+        public FileOperationContext(string fullName, FileOperationStatus status)
+        {
+            FullName = fullName;
+            Status = status;
+        }
+
+        public string FullName { get; private set; }
+
+        public FileOperationStatus Status { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/FileOperationEventArgs.cs b/Axantum.AxCrypt.Core/UI/FileOperationEventArgs.cs
new file mode 100644
index 0000000..8014628
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/FileOperationEventArgs.cs
@@ -0,0 +1,58 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class FileOperationEventArgs : CancelEventArgs
+    {
+        public FileOperationEventArgs()
+        {
+            Status = new FileOperationContext(String.Empty, FileOperationStatus.Unknown);
+        }
+
+        public string SaveFileFullName { get; set; }
+
+        public string OpenFileFullName { get; set; }
+
+        public Passphrase Passphrase { get; set; }
+
+        public Guid CryptoId { get; set; }
+
+        public bool ConfirmAll { get; set; }
+
+        public bool Skip { get; set; }
+
+        public IAxCryptDocument AxCryptDocument { get; set; }
+
+        public FileOperationContext Status { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/FileOperationStatus.cs b/Axantum.AxCrypt.Core/UI/FileOperationStatus.cs
new file mode 100644
index 0000000..1ab61dd
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/FileOperationStatus.cs
@@ -0,0 +1,50 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public enum FileOperationStatus
+    {
+        Success,
+        UnspecifiedError,
+        FileAlreadyExists,
+        FileDoesNotExist,
+        CannotWriteDestination,
+        CannotStartApplication,
+        InconsistentState,
+        InvalidKey,
+        Canceled,
+        Exception,
+        Unknown,
+        InvalidPath,
+        Working,
+        Aborted,
+        FileAlreadyEncrypted,
+        FolderAlreadyWatched,
+        FileLocked,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/FileOperationsController.cs b/Axantum.AxCrypt.Core/UI/FileOperationsController.cs
new file mode 100644
index 0000000..e10f92f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/FileOperationsController.cs
@@ -0,0 +1,534 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    /// <summary>
+    /// This class implements the controlling logic for various file-oriented operations which typically
+    /// require user interaction. Opportunity to insert user interaction is provided via events which are
+    /// raised on a need-to-know basis. Instances of this class should typically be instantiated on a GUI
+    /// thread and methods should be called from the GUI thread. Support is provided for doing the heavy
+    /// lifting on background threads.
+    /// </summary>
+    public class FileOperationsController
+    {
+        private FileOperationEventArgs _eventArgs;
+
+        private IProgressContext _progress;
+
+        #region Constructors
+
+        /// <summary>
+        /// Create a new instance, without any progress reporting.
+        /// </summary>
+        public FileOperationsController()
+            : this(new ProgressContext())
+        {
+        }
+
+        /// <summary>
+        /// Create a new instance, reporting progress
+        /// </summary>
+        /// <param name="progress">The instance of ProgressContext to report progress via</param>
+        public FileOperationsController(IProgressContext progress)
+        {
+            _eventArgs = new FileOperationEventArgs();
+            _progress = progress;
+        }
+
+        #endregion Constructors
+
+        #region Events
+
+        /// <summary>
+        /// Raised whenever there is a need to specify a file to save to because the expected target
+        /// name already exists.
+        /// </summary>
+        public event EventHandler<FileOperationEventArgs> QuerySaveFileAs;
+
+        protected virtual void OnQuerySaveFileAs(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = QuerySaveFileAs;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when a valid decryption passphrase was not found among the KnownKeys collection.
+        /// </summary>
+        public event EventHandler<FileOperationEventArgs> QueryDecryptionPassphrase;
+
+        protected virtual void OnQueryDecryptionPassphrase(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = QueryDecryptionPassphrase;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when the KnownKeys.DefaultEncryptionKey is not set.
+        /// </summary>
+        public event EventHandler<FileOperationEventArgs> QueryEncryptionPassphrase;
+
+        protected virtual void OnQueryEncryptionPassphrase(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = QueryEncryptionPassphrase;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised to confirm that a file really should be wiped.
+        /// </summary>
+        public event EventHandler<FileOperationEventArgs> WipeQueryConfirmation;
+
+        protected virtual void OnWipeQueryConfirmation(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = WipeQueryConfirmation;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when a new KnowKey is added.
+        /// </summary>
+        public event EventHandler<FileOperationEventArgs> KnownKeyAdded;
+
+        protected virtual void OnKnownKeyAdded(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = KnownKeyAdded;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Always raised at the end of an operation, regardless of errors or cancellation.
+        /// </summary>
+        /// <param name="e"></param>
+        public event EventHandler<FileOperationEventArgs> Completed;
+
+        protected virtual void OnCompleted(FileOperationEventArgs e)
+        {
+            EventHandler<FileOperationEventArgs> handler = Completed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        #endregion Events
+
+        #region Public Methods
+
+        /// <summary>
+        /// Encrypt file, raising events as required by the situation.
+        /// </summary>
+        /// <param name="sourceFile">The full path to a plain-text file to encrypt.</param>
+        /// <returns>'True' if the operation did not fail so far, 'False' if it definitely has failed.</returns>
+        /// <remarks>
+        /// Since especially the actual operation typically is executed asynchronously, the
+        /// return value and status do not conclusive indicate success. Only a failure return
+        /// is conclusive.
+        /// </remarks>
+        public FileOperationContext EncryptFile(IRuntimeFileInfo fileInfo)
+        {
+            return DoFile(fileInfo, EncryptFilePreparation, EncryptFileOperation);
+        }
+
+        /// <summary>
+        /// Decrypt a file, raising events as required by the situation.
+        /// </summary>
+        /// <param name="sourceFile">The full path to an encrypted file.</param>
+        /// <returns>The resulting status of the operation.</returns>
+        public FileOperationContext DecryptFile(IRuntimeFileInfo fileInfo)
+        {
+            return DoFile(fileInfo, DecryptFilePreparation, DecryptFileOperation);
+        }
+
+        /// <summary>
+        /// Decrypt a file, and launch the associated application raising events as required by
+        /// the situation.
+        /// </summary>
+        /// <param name="fileInfo">The full path to an encrypted file.</param>
+        /// <returns>A FileOperationStatus indicating the result of the operation.</returns>
+        public FileOperationContext DecryptAndLaunch(IRuntimeFileInfo fileInfo)
+        {
+            return DoFile(fileInfo, DecryptAndLaunchPreparation, DecryptAndLaunchFileOperation);
+        }
+
+        /// <summary>
+        /// Verify that a file is encrypted with a known key.
+        /// </summary>
+        /// <param name="fileInfo">The file to verify.</param>
+        /// <returns>FileOperationStatus.Success if  the file is encrypted with a known key.</returns>
+        public FileOperationContext VerifyEncrypted(IRuntimeFileInfo fileInfo)
+        {
+            return DoFile(fileInfo, DecryptAndLaunchPreparation, GetDocumentInfo);
+        }
+
+        /// <summary>
+        /// Wipes a file securely synchronously.
+        /// </summary>
+        /// <param name="fileInfo">The full name of the file to wipe</param>
+        /// <returns>A FileOperationStatus indicating the result of the operation.</returns>
+        public FileOperationContext WipeFile(IRuntimeFileInfo fileInfo)
+        {
+            return DoFile(fileInfo, WipeFilePreparation, WipeFileOperation);
+        }
+
+        #endregion Public Methods
+
+        #region Private Methods
+
+        private bool EncryptFilePreparation(IRuntimeFileInfo sourceFileInfo)
+        {
+            if (String.Compare(Instance.Portable.Path().GetExtension(sourceFileInfo.FullName), OS.Current.AxCryptExtension, StringComparison.OrdinalIgnoreCase) == 0)
+            {
+                _eventArgs.Status = new FileOperationContext(sourceFileInfo.FullName, FileOperationStatus.FileAlreadyEncrypted);
+                return false;
+            }
+
+            if (sourceFileInfo.IsLocked)
+            {
+                _eventArgs.Status = new FileOperationContext(sourceFileInfo.FullName, FileOperationStatus.FileLocked);
+                return false;
+            }
+
+            IRuntimeFileInfo destinationFileInfo = Factory.New<IRuntimeFileInfo>(AxCryptFile.MakeAxCryptFileName(sourceFileInfo));
+            _eventArgs.SaveFileFullName = destinationFileInfo.FullName;
+            _eventArgs.OpenFileFullName = sourceFileInfo.FullName;
+            if (destinationFileInfo.IsExistingFile)
+            {
+                OnQuerySaveFileAs(_eventArgs);
+                if (_eventArgs.Cancel)
+                {
+                    _eventArgs.Status = new FileOperationContext(sourceFileInfo.FullName, FileOperationStatus.Canceled);
+                    return false;
+                }
+            }
+
+            if (Instance.KnownKeys.DefaultEncryptionKey == null)
+            {
+                OnQueryEncryptionPassphrase(_eventArgs);
+                if (_eventArgs.Cancel)
+                {
+                    _eventArgs.Status = new FileOperationContext(sourceFileInfo.FullName, FileOperationStatus.Canceled);
+                    return false;
+                }
+            }
+            else
+            {
+                _eventArgs.Passphrase = Instance.KnownKeys.DefaultEncryptionKey;
+            }
+
+            return true;
+        }
+
+        private bool EncryptFileOperation()
+        {
+            _eventArgs.CryptoId = Instance.CryptoFactory.Default.Id;
+            Factory.New<AxCryptFile>().EncryptFileWithBackupAndWipe(_eventArgs.OpenFileFullName, _eventArgs.SaveFileFullName, _eventArgs.Passphrase, _eventArgs.CryptoId, _progress);
+
+            _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            return true;
+        }
+
+        private bool DecryptFilePreparation(IRuntimeFileInfo fileInfo)
+        {
+            if (fileInfo.IsLocked)
+            {
+                _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.FileLocked);
+                return false;
+            }
+
+            if (!OpenAxCryptDocument(fileInfo, _eventArgs) || _eventArgs.Skip)
+            {
+                return false;
+            }
+
+            IRuntimeFileInfo destination = Factory.New<IRuntimeFileInfo>(Instance.Portable.Path().Combine(Instance.Portable.Path().GetDirectoryName(fileInfo.FullName), _eventArgs.AxCryptDocument.FileName));
+            _eventArgs.SaveFileFullName = destination.FullName;
+            if (destination.IsExistingFile)
+            {
+                OnQuerySaveFileAs(_eventArgs);
+                if (_eventArgs.Cancel)
+                {
+                    _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.Canceled);
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private bool DecryptFileOperation()
+        {
+            _progress.NotifyLevelStart();
+            try
+            {
+                Factory.New<AxCryptFile>().DecryptFile(_eventArgs.AxCryptDocument, _eventArgs.SaveFileFullName, _progress);
+            }
+            finally
+            {
+                _eventArgs.AxCryptDocument.Dispose();
+                _eventArgs.AxCryptDocument = null;
+            }
+            Factory.New<AxCryptFile>().Wipe(Factory.New<IRuntimeFileInfo>(_eventArgs.OpenFileFullName), _progress);
+
+            _progress.NotifyLevelFinished();
+
+            _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            return true;
+        }
+
+        private bool DecryptAndLaunchPreparation(IRuntimeFileInfo fileInfo)
+        {
+            if (!OpenAxCryptDocument(fileInfo, _eventArgs))
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        private bool GetDocumentInfo()
+        {
+            try
+            {
+                if (!_eventArgs.Skip)
+                {
+                    _eventArgs.SaveFileFullName = _eventArgs.AxCryptDocument.FileName;
+                }
+            }
+            finally
+            {
+                if (_eventArgs.AxCryptDocument != null)
+                {
+                    _eventArgs.AxCryptDocument.Dispose();
+                    _eventArgs.AxCryptDocument = null;
+                }
+            }
+
+            _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            return true;
+        }
+
+        private bool DecryptAndLaunchFileOperation()
+        {
+            try
+            {
+                _eventArgs.Status = Factory.New<FileOperation>().OpenAndLaunchApplication(_eventArgs.OpenFileFullName, _eventArgs.Passphrase, _eventArgs.AxCryptDocument, _progress);
+            }
+            finally
+            {
+                _eventArgs.AxCryptDocument.Dispose();
+                _eventArgs.AxCryptDocument = null;
+            }
+
+            _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            return true;
+        }
+
+        private bool WipeFilePreparation(IRuntimeFileInfo fileInfo)
+        {
+            if (fileInfo.IsLocked)
+            {
+                _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.FileLocked);
+                return false;
+            }
+
+            _eventArgs.OpenFileFullName = fileInfo.FullName;
+            _eventArgs.SaveFileFullName = fileInfo.FullName;
+            if (_progress.AllItemsConfirmed)
+            {
+                return true;
+            }
+            OnWipeQueryConfirmation(_eventArgs);
+            if (_eventArgs.Cancel)
+            {
+                _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.Canceled);
+                return false;
+            }
+
+            if (_eventArgs.ConfirmAll)
+            {
+                _progress.AllItemsConfirmed = true;
+            }
+            return true;
+        }
+
+        private bool WipeFileOperation()
+        {
+            if (_eventArgs.Skip)
+            {
+                _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                return true;
+            }
+
+            _progress.NotifyLevelStart();
+            Factory.New<AxCryptFile>().Wipe(Factory.New<IRuntimeFileInfo>(_eventArgs.SaveFileFullName), _progress);
+            _progress.NotifyLevelFinished();
+
+            _eventArgs.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+            return true;
+        }
+
+        private bool OpenAxCryptDocument(IRuntimeFileInfo sourceFileInfo, FileOperationEventArgs e)
+        {
+            e.AxCryptDocument = null;
+            try
+            {
+                _progress.NotifyLevelStart();
+                e.OpenFileFullName = sourceFileInfo.FullName;
+                if (TryFindDecryptionKey(sourceFileInfo, e))
+                {
+                    e.AxCryptDocument = Factory.New<AxCryptFile>().Document(sourceFileInfo, e.Passphrase, _progress);
+                }
+
+                while (e.AxCryptDocument == null)
+                {
+                    OnQueryDecryptionPassphrase(e);
+                    if (e.Cancel)
+                    {
+                        e.Status = new FileOperationContext(sourceFileInfo.FullName, FileOperationStatus.Canceled);
+                        return false;
+                    }
+                    if (e.Skip)
+                    {
+                        e.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                        return true;
+                    }
+                    e.AxCryptDocument = Factory.New<AxCryptFile>().Document(sourceFileInfo, e.Passphrase, _progress);
+                    if (!e.AxCryptDocument.PassphraseIsValid)
+                    {
+                        e.AxCryptDocument.Dispose();
+                        e.AxCryptDocument = null;
+                        continue;
+                    }
+                    e.CryptoId = e.AxCryptDocument.CryptoFactory.Id;
+                    OnKnownKeyAdded(e);
+                }
+            }
+            catch (IOException ioex)
+            {
+                if (e.AxCryptDocument != null)
+                {
+                    e.AxCryptDocument.Dispose();
+                    e.AxCryptDocument = null;
+                }
+                FileOperationContext status = new FileOperationContext(sourceFileInfo.FullName, ioex is FileNotFoundException ? FileOperationStatus.FileDoesNotExist : FileOperationStatus.Exception);
+                e.Status = status;
+                return false;
+            }
+            finally
+            {
+                _progress.NotifyLevelFinished();
+            }
+            return true;
+        }
+
+        private static bool TryFindDecryptionKey(IRuntimeFileInfo fileInfo, FileOperationEventArgs e)
+        {
+            Guid cryptoId;
+            Passphrase passphrase = fileInfo.TryFindPassphrase(out cryptoId);
+            if (passphrase == null)
+            {
+                return false;
+            }
+
+            e.CryptoId = cryptoId;
+            e.Passphrase = passphrase;
+            return true;
+        }
+
+        private FileOperationContext DoFile(IRuntimeFileInfo fileInfo, Func<IRuntimeFileInfo, bool> preparation, Func<bool> operation)
+        {
+            try
+            {
+                bool ok = RunOnUIThread(fileInfo, preparation);
+                if (ok)
+                {
+                    operation();
+                }
+            }
+            finally
+            {
+                OnCompleted(_eventArgs);
+            }
+
+            return _eventArgs.Status;
+        }
+
+        private bool RunOnUIThread(IRuntimeFileInfo fileInfo, Func<IRuntimeFileInfo, bool> preparation)
+        {
+            bool ok = false;
+            _progress.EnterSingleThread();
+            try
+            {
+                if (_progress.Cancel)
+                {
+                    _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.Canceled);
+                    return ok;
+                }
+                Instance.UIThread.RunOnUIThread(() => ok = preparation(fileInfo));
+                if (_eventArgs.Status.Status == FileOperationStatus.Canceled)
+                {
+                    _progress.Cancel = true;
+                }
+            }
+            catch (Exception)
+            {
+                _eventArgs.Status = new FileOperationContext(fileInfo.FullName, FileOperationStatus.Exception);
+                throw;
+            }
+            finally
+            {
+                _progress.LeaveSingleThread();
+            }
+            return ok;
+        }
+
+        #endregion Private Methods
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/IProgressBackground.cs b/Axantum.AxCrypt.Core/UI/IProgressBackground.cs
new file mode 100644
index 0000000..9ffe7b6
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/IProgressBackground.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public interface IProgressBackground
+    {
+        void Work(Func<IProgressContext, FileOperationContext> workFunction, Action<FileOperationContext> complete);
+
+        void WaitForIdle();
+
+        event EventHandler WorkStatusChanged;
+
+        bool Busy { get; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/IProgressContext.cs b/Axantum.AxCrypt.Core/UI/IProgressContext.cs
new file mode 100644
index 0000000..0f60124
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/IProgressContext.cs
@@ -0,0 +1,55 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public interface IProgressContext
+    {
+        event EventHandler<ProgressEventArgs> Progressing;
+
+        void RemoveCount(long totalCount, long progressCount);
+
+        void AddTotal(long count);
+
+        void AddCount(long count);
+
+        void NotifyLevelStart();
+
+        void NotifyLevelFinished();
+
+        bool Cancel { get; set; }
+
+        bool AllItemsConfirmed { get; set; }
+
+        void EnterSingleThread();
+
+        void LeaveSingleThread();
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/IStatusChecker.cs b/Axantum.AxCrypt.Core/UI/IStatusChecker.cs
new file mode 100644
index 0000000..3803bab
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/IStatusChecker.cs
@@ -0,0 +1,45 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public interface IStatusChecker
+    {
+        /// <summary>
+        /// Check if a status is deemed a success. If not, possibly display an interactive message
+        /// to a user, incorporating the displayContext-string in the message. This is typically
+        /// a file name or some other language independent context.
+        /// </summary>
+        /// <param name="status">The status to check.</param>
+        /// <param name="displayContext">A language independent context for the error, typically a file name.</param>
+        /// <returns>True if the status indicated success, false otherwise.</returns>
+        bool CheckStatusAndShowMessage(FileOperationStatus status, string displayContext);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/IUIThread.cs b/Axantum.AxCrypt.Core/UI/IUIThread.cs
new file mode 100644
index 0000000..fe6fe66
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/IUIThread.cs
@@ -0,0 +1,43 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public interface IUIThread
+    {
+        bool IsOnUIThread { get; }
+
+        void RunOnUIThread(Action action);
+
+        void PostOnUIThread(Action action);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/IUserSettings.cs b/Axantum.AxCrypt.Core/UI/IUserSettings.cs
new file mode 100644
index 0000000..efa136c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/IUserSettings.cs
@@ -0,0 +1,82 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public interface IUserSettings
+    {
+        void Delete();
+
+        string this[string key]
+        {
+            get;
+            set;
+        }
+
+        T Load<T>(string key);
+
+        T Load<T>(string key, T fallback);
+
+        void Store<T>(string key, T value);
+
+        string CultureName { get; set; }
+
+        Uri AxCrypt2VersionCheckUrl { get; set; }
+
+        Uri UpdateUrl { get; set; }
+
+        DateTime LastUpdateCheckUtc { get; set; }
+
+        string NewestKnownVersion { get; set; }
+
+        bool DebugMode { get; set; }
+
+        Uri AxCrypt2HelpUrl { get; set; }
+
+        bool DisplayEncryptPassphrase { get; set; }
+
+        bool DisplayDecryptPassphrase { get; set; }
+
+        long GetKeyWrapIterations(Guid cryptoId);
+
+        void SetKeyWrapIterations(Guid cryptoId, long keyWrapIterations);
+
+        Salt ThumbprintSalt { get; set; }
+
+        TimeSpan SessionNotificationMinimumIdle { get; set; }
+
+        int SettingsVersion { get; set; }
+
+        int CurrentSettingsVersion { get; }
+
+        int AsymmetricKeyBits { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/KnownFolder.cs b/Axantum.AxCrypt.Core/UI/KnownFolder.cs
new file mode 100644
index 0000000..a239bd4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/KnownFolder.cs
@@ -0,0 +1,87 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Extensions;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    /// <summary>
+    /// Holds properties for specific known folders, such as DropBox, My Documents etc
+    /// </summary>
+    /// <remarks>
+    /// Instances of this class are immutable.
+    /// </remarks>
+    public class KnownFolder
+    {
+        public IRuntimeFileInfo RootFullPath { get; private set; }
+
+        public IRuntimeFileInfo MyFullPath { get; private set; }
+
+        public Uri ProviderUrl { get; private set; }
+
+        public object Image { get; private set; }
+
+        public bool Enabled { get; private set; }
+
+        public KnownFolder(string rootFullPath, string myRelativePath, object image, Uri providerUrl)
+        {
+            if (rootFullPath == null)
+            {
+                throw new ArgumentNullException("rootFullPath");
+            }
+            if (myRelativePath == null)
+            {
+                throw new ArgumentNullException("myRelativePath");
+            }
+            if (image == null)
+            {
+                throw new ArgumentNullException("image");
+            }
+            RootFullPath = Factory.New<IRuntimeFileInfo>(rootFullPath.NormalizeFolderPath());
+            MyFullPath = RootFullPath.Combine(myRelativePath).NormalizeFolder();
+            Image = image;
+            ProviderUrl = providerUrl;
+            Enabled = false;
+        }
+
+        public KnownFolder(KnownFolder knownFolder, bool enabled)
+        {
+            if (knownFolder == null)
+            {
+                throw new ArgumentNullException("knownFolder");
+            }
+            RootFullPath = knownFolder.RootFullPath;
+            MyFullPath = knownFolder.MyFullPath;
+            Image = knownFolder.Image;
+            ProviderUrl = knownFolder.ProviderUrl;
+            Enabled = enabled;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/KnownKeys.cs b/Axantum.AxCrypt.Core/UI/KnownKeys.cs
new file mode 100644
index 0000000..8478d9f
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/KnownKeys.cs
@@ -0,0 +1,178 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class KnownKeys
+    {
+        private List<Passphrase> _keys;
+
+        private FileSystemState _fileSystemState;
+
+        private SessionNotify _notificationMonitor;
+
+        public KnownKeys(FileSystemState fileSystemState, SessionNotify notificationMonitor)
+        {
+            _fileSystemState = fileSystemState;
+            _notificationMonitor = notificationMonitor;
+            _keys = new List<Passphrase>();
+            _knownThumbprints = new List<SymmetricKeyThumbprint>();
+        }
+
+        public bool IsLoggedOn
+        {
+            get
+            {
+                return DefaultEncryptionKey != null;
+            }
+        }
+
+        public void LogOff()
+        {
+            DefaultEncryptionKey = null;
+        }
+
+        public void Add(Passphrase key)
+        {
+            bool changed = false;
+            lock (_keys)
+            {
+                int i = _keys.IndexOf(key);
+                if (i < 0)
+                {
+                    _keys.Insert(0, key);
+                    changed = true;
+                }
+            }
+            changed |= AddKnownThumbprint(key);
+            if (changed)
+            {
+                DefaultEncryptionKey = key;
+                _notificationMonitor.Notify(new SessionNotification(SessionNotificationType.KnownKeyChange, key));
+            }
+        }
+
+        public void Clear()
+        {
+            lock (_keys)
+            {
+                if (_keys.Count == 0)
+                {
+                    return;
+                }
+                _keys.Clear();
+            }
+            LogOff();
+            _notificationMonitor.Notify(new SessionNotification(SessionNotificationType.KnownKeyChange));
+        }
+
+        public IEnumerable<Passphrase> Keys
+        {
+            get
+            {
+                lock (_keys)
+                {
+                    return new List<Passphrase>(_keys);
+                }
+            }
+        }
+
+        private Passphrase _defaultEncryptionKey;
+
+        /// <summary>
+        /// Gets or sets the default encryption key.
+        /// </summary>
+        /// <value>
+        /// The default encryption key, or null if none is known.
+        /// </value>
+        public Passphrase DefaultEncryptionKey
+        {
+            get
+            {
+                return _defaultEncryptionKey;
+            }
+            set
+            {
+                if (_defaultEncryptionKey != null && value != null && _defaultEncryptionKey == value)
+                {
+                    return;
+                }
+                if (_defaultEncryptionKey != null)
+                {
+                    Passphrase oldKey = _defaultEncryptionKey;
+                    _defaultEncryptionKey = null;
+                    _notificationMonitor.Notify(new SessionNotification(SessionNotificationType.LogOff, oldKey));
+                }
+                if (value == null)
+                {
+                    return;
+                }
+                _defaultEncryptionKey = value;
+                Add(_defaultEncryptionKey);
+                _notificationMonitor.Notify(new SessionNotification(SessionNotificationType.LogOn, value));
+            }
+        }
+
+        private List<SymmetricKeyThumbprint> _knownThumbprints;
+
+        /// <summary>
+        /// Add a thumb print to the list of known thumb prints
+        /// </summary>
+        /// <param name="thumbprint">The key to add the fingerprint of</param>
+        /// <returns>True if a new thumb print was added, false if it was already known.</returns>
+        private bool AddKnownThumbprint(Passphrase key)
+        {
+            lock (_knownThumbprints)
+            {
+                if (_knownThumbprints.Contains(key.Thumbprint))
+                {
+                    return false;
+                }
+                _knownThumbprints.Add(key.Thumbprint);
+                return true;
+            }
+        }
+
+        public IEnumerable<WatchedFolder> LoggedOnWatchedFolders
+        {
+            get
+            {
+                if (!IsLoggedOn)
+                {
+                    return new WatchedFolder[0];
+                }
+                return _fileSystemState.WatchedFolders.Where(wf => wf.Thumbprint == DefaultEncryptionKey.Thumbprint);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/Options.cs b/Axantum.AxCrypt.Core/UI/Options.cs
new file mode 100644
index 0000000..436cd95
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/Options.cs
@@ -0,0 +1,1251 @@
+//
+// Options.cs
+//
+// Authors:
+//  Jonathan Pryor <jpryor at novell.com>
+//
+// Copyright (C) 2008 Novell (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+// Compile With:
+//   gmcs -debug+ -r:System.Core Options.cs -o:NDesk.Options.dll
+//   gmcs -debug+ -d:LINQ -r:System.Core Options.cs -o:NDesk.Options.dll
+//
+// The LINQ version just changes the implementation of
+// OptionSet.Parse(IEnumerable<string>), and confers no semantic changes.
+
+//
+// A Getopt::Long-inspired option parsing library for C#.
+//
+// NDesk.Options.OptionSet is built upon a key/value table, where the
+// key is a option format string and the value is a delegate that is
+// invoked when the format string is matched.
+//
+// Option format strings:
+//  Regex-like BNF Grammar:
+//    name: .+
+//    type: [=:]
+//    sep: ( [^{}]+ | '{' .+ '}' )?
+//    aliases: ( name type sep ) ( '|' name type sep )*
+//
+// Each '|'-delimited name is an alias for the associated action.  If the
+// format string ends in a '=', it has a required value.  If the format
+// string ends in a ':', it has an optional value.  If neither '=' or ':'
+// is present, no value is supported.  `=' or `:' need only be defined on one
+// alias, but if they are provided on more than one they must be consistent.
+//
+// Each alias portion may also end with a "key/value separator", which is used
+// to split option values if the option accepts > 1 value.  If not specified,
+// it defaults to '=' and ':'.  If specified, it can be any character except
+// '{' and '}' OR the *string* between '{' and '}'.  If no separator should be
+// used (i.e. the separate values should be distinct arguments), then "{}"
+// should be used as the separator.
+//
+// Options are extracted either from the current option by looking for
+// the option name followed by an '=' or ':', or is taken from the
+// following option IFF:
+//  - The current option does not contain a '=' or a ':'
+//  - The current option requires a value (i.e. not a Option type of ':')
+//
+// The `name' used in the option format string does NOT include any leading
+// option indicator, such as '-', '--', or '/'.  All three of these are
+// permitted/required on any named option.
+//
+// Option bundling is permitted so long as:
+//   - '-' is used to start the option group
+//   - all of the bundled options are a single character
+//   - at most one of the bundled options accepts a value, and the value
+//     provided starts from the next character to the end of the string.
+//
+// This allows specifying '-a -b -c' as '-abc', and specifying '-D name=value'
+// as '-Dname=value'.
+//
+// Option processing is disabled by specifying "--".  All options after "--"
+// are returned by OptionSet.Parse() unchanged and unprocessed.
+//
+// Unprocessed options are returned from OptionSet.Parse().
+//
+// Examples:
+//  int verbose = 0;
+//  OptionSet p = new OptionSet ()
+//    .Add ("v", v => ++verbose)
+//    .Add ("name=|value=", v => Console.WriteLine (v));
+//  p.Parse (new string[]{"-v", "--v", "/v", "-name=A", "/name", "B", "extra"});
+//
+// The above would parse the argument string array, and would invoke the
+// lambda expression three times, setting `verbose' to 3 when complete.
+// It would also print out "A" and "B" to standard output.
+// The returned array would contain the string "extra".
+//
+// C# 3.0 collection initializers are supported and encouraged:
+//  var p = new OptionSet () {
+//    { "h|?|help", v => ShowHelp () },
+//  };
+//
+// System.ComponentModel.TypeConverter is also supported, allowing the use of
+// custom data types in the callback type; TypeConverter.ConvertFromString()
+// is used to convert the value option to an instance of the specified
+// type:
+//
+//  var p = new OptionSet () {
+//    { "foo=", (Foo f) => Console.WriteLine (f.ToString ()) },
+//  };
+//
+// Random other tidbits:
+//  - Boolean options (those w/o '=' or ':' in the option format string)
+//    are explicitly enabled if they are followed with '+', and explicitly
+//    disabled if they are followed with '-':
+//      string a = null;
+//      var p = new OptionSet () {
+//        { "a", s => a = s },
+//      };
+//      p.Parse (new string[]{"-a"});   // sets v != null
+//      p.Parse (new string[]{"-a+"});  // sets v != null
+//      p.Parse (new string[]{"-a-"});  // sets v == null
+//
+
+using System;
+using System.CodeDom.Compiler;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Text.RegularExpressions;
+
+#if LINQ
+using System.Linq;
+#endif
+
+#if TEST
+using NDesk.Options;
+#endif
+
+namespace NDesk.Options
+{
+    [GeneratedCode("NDesk.Options", "0.2.1")]
+    public class OptionValueCollection : IList, IList<string>
+    {
+        private List<string> values = new List<string>();
+        private OptionContext c;
+
+        internal OptionValueCollection(OptionContext c)
+        {
+            this.c = c;
+        }
+
+        #region ICollection
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            (values as ICollection).CopyTo(array, index);
+        }
+
+        bool ICollection.IsSynchronized { get { return (values as ICollection).IsSynchronized; } }
+
+        object ICollection.SyncRoot { get { return (values as ICollection).SyncRoot; } }
+
+        #endregion ICollection
+
+        #region ICollection<T>
+
+        public void Add(string item)
+        {
+            values.Add(item);
+        }
+
+        public void Clear()
+        {
+            values.Clear();
+        }
+
+        public bool Contains(string item)
+        {
+            return values.Contains(item);
+        }
+
+        public void CopyTo(string[] array, int arrayIndex)
+        {
+            values.CopyTo(array, arrayIndex);
+        }
+
+        public bool Remove(string item)
+        {
+            return values.Remove(item);
+        }
+
+        public int Count { get { return values.Count; } }
+
+        public bool IsReadOnly { get { return false; } }
+
+        #endregion ICollection<T>
+
+        #region IEnumerable
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return values.GetEnumerator();
+        }
+
+        #endregion IEnumerable
+
+        #region IEnumerable<T>
+
+        public IEnumerator<string> GetEnumerator()
+        {
+            return values.GetEnumerator();
+        }
+
+        #endregion IEnumerable<T>
+
+        #region IList
+
+        int IList.Add(object value)
+        {
+            return (values as IList).Add(value);
+        }
+
+        bool IList.Contains(object value)
+        {
+            return (values as IList).Contains(value);
+        }
+
+        int IList.IndexOf(object value)
+        {
+            return (values as IList).IndexOf(value);
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            (values as IList).Insert(index, value);
+        }
+
+        void IList.Remove(object value)
+        {
+            (values as IList).Remove(value);
+        }
+
+        void IList.RemoveAt(int index)
+        {
+            (values as IList).RemoveAt(index);
+        }
+
+        bool IList.IsFixedSize { get { return false; } }
+
+        object IList.this[int index] { get { return this[index]; } set { (values as IList)[index] = value; } }
+
+        #endregion IList
+
+        #region IList<T>
+
+        public int IndexOf(string item)
+        {
+            return values.IndexOf(item);
+        }
+
+        public void Insert(int index, string item)
+        {
+            values.Insert(index, item);
+        }
+
+        public void RemoveAt(int index)
+        {
+            values.RemoveAt(index);
+        }
+
+        private void AssertValid(int index)
+        {
+            if (c.Option == null)
+                throw new InvalidOperationException("OptionContext.Option is null.");
+            if (index >= c.Option.MaxValueCount)
+                throw new ArgumentOutOfRangeException("index");
+            if (c.Option.OptionValueType == OptionValueType.Required &&
+                    index >= values.Count)
+                throw new OptionException(string.Format(
+                            c.OptionSet.MessageLocalizer("Missing required value for option '{0}'."), c.OptionName),
+                        c.OptionName);
+        }
+
+        public string this[int index]
+        {
+            get
+            {
+                AssertValid(index);
+                return index >= values.Count ? null : values[index];
+            }
+            set
+            {
+                values[index] = value;
+            }
+        }
+
+        #endregion IList<T>
+
+        public List<string> ToList()
+        {
+            return new List<string>(values);
+        }
+
+        public string[] ToArray()
+        {
+            return values.ToArray();
+        }
+
+        public override string ToString()
+        {
+            return string.Join(", ", values.ToArray());
+        }
+    }
+
+    public class OptionContext
+    {
+        private OptionBase option;
+        private string name;
+        private int index;
+        private OptionSetCollection set;
+        private OptionValueCollection c;
+
+        public OptionContext(OptionSetCollection set)
+        {
+            this.set = set;
+            this.c = new OptionValueCollection(this);
+        }
+
+        public OptionBase Option
+        {
+            get { return option; }
+            set { option = value; }
+        }
+
+        public string OptionName
+        {
+            get { return name; }
+            set { name = value; }
+        }
+
+        public int OptionIndex
+        {
+            get { return index; }
+            set { index = value; }
+        }
+
+        public OptionSetCollection OptionSet
+        {
+            get { return set; }
+        }
+
+        public OptionValueCollection OptionValues
+        {
+            get { return c; }
+        }
+    }
+
+    public enum OptionValueType
+    {
+        None,
+        Optional,
+        Required,
+    }
+
+    public abstract class OptionBase
+    {
+        private string prototype, description;
+        private string[] names;
+        private OptionValueType type;
+        private int count;
+        private string[] separators;
+
+        protected OptionBase(string prototype, string description, int maxValueCount)
+        {
+            if (prototype == null)
+                throw new ArgumentNullException("prototype");
+            if (prototype.Length == 0)
+                throw new ArgumentException("Cannot be the empty string.", "prototype");
+            if (maxValueCount < 0)
+                throw new ArgumentOutOfRangeException("maxValueCount");
+
+            this.prototype = prototype;
+            this.names = prototype.Split('|');
+            this.description = description;
+            this.count = maxValueCount;
+            this.type = ParsePrototype();
+
+            if (this.count == 0 && type != OptionValueType.None)
+                throw new ArgumentException(
+                        "Cannot provide maxValueCount of 0 for OptionValueType.Required or " +
+                            "OptionValueType.Optional.",
+                        "maxValueCount");
+            if (this.type == OptionValueType.None && maxValueCount > 1)
+                throw new ArgumentException(
+                        string.Format(CultureInfo.InvariantCulture, "Cannot provide maxValueCount of {0} for OptionValueType.None.", maxValueCount),
+                        "maxValueCount");
+            if (Array.IndexOf(names, "<>") >= 0 &&
+                    ((names.Length == 1 && this.type != OptionValueType.None) ||
+                     (names.Length > 1 && this.MaxValueCount > 1)))
+                throw new ArgumentException(
+                        "The default option handler '<>' cannot require values.",
+                        "prototype");
+        }
+
+        public string Prototype { get { return prototype; } }
+
+        public string Description { get { return description; } }
+
+        public OptionValueType OptionValueType { get { return type; } }
+
+        public int MaxValueCount { get { return count; } }
+
+        public string[] GetNames()
+        {
+            return (string[])names.Clone();
+        }
+
+        public string[] GetValueSeparators()
+        {
+            if (separators == null)
+                return new string[0];
+            return (string[])separators.Clone();
+        }
+
+        protected static T Parse<T>(string value, OptionContext optionContext)
+        {
+            T t = default(T);
+            if (value == null)
+            {
+                return t;
+            }
+            try
+            {
+                switch (typeof(T).ToString())
+                {
+                    case "System.Int32":
+                        return (T)(object)Int32.Parse(value);
+
+                    case "System.String":
+                        return (T)(object)value;
+
+                    case "System.Boolean":
+                        return (T)(object)Boolean.Parse(value);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new OptionException(
+                        string.Format(CultureInfo.InvariantCulture,
+                            optionContext.OptionSet.MessageLocalizer("Could not convert string `{0}' to type {1} for option `{2}'."),
+                            value, typeof(T).Name, optionContext.OptionName),
+                        optionContext.OptionName, e);
+            }
+            return t;
+        }
+
+        internal string[] Names { get { return names; } }
+
+        internal string[] ValueSeparators { get { return separators; } }
+
+        private static readonly char[] NameTerminator = new char[] { '=', ':' };
+
+        private OptionValueType ParsePrototype()
+        {
+            char type = '\0';
+            List<string> seps = new List<string>();
+            for (int i = 0; i < names.Length; ++i)
+            {
+                string name = names[i];
+                if (name.Length == 0)
+                    throw new InvalidOperationException("Empty option names are not supported.");
+
+                int end = name.IndexOfAny(NameTerminator);
+                if (end == -1)
+                    continue;
+                names[i] = name.Substring(0, end);
+                if (type == '\0' || type == name[end])
+                    type = name[end];
+                else
+                    throw new InvalidOperationException(
+                            string.Format(CultureInfo.InvariantCulture, "Conflicting option types: '{0}' vs. '{1}'.", type, name[end]));
+                AddSeparators(name, end, seps);
+            }
+
+            if (type == '\0')
+                return OptionValueType.None;
+
+            if (count <= 1 && seps.Count != 0)
+                throw new InvalidOperationException(
+                        string.Format(CultureInfo.InvariantCulture, "Cannot provide key/value separators for Options taking {0} value(s).", count));
+            if (count > 1)
+            {
+                if (seps.Count == 0)
+                    this.separators = new string[] { ":", "=" };
+                else if (seps.Count == 1 && seps[0].Length == 0)
+                    this.separators = null;
+                else
+                    this.separators = seps.ToArray();
+            }
+
+            return type == '=' ? OptionValueType.Required : OptionValueType.Optional;
+        }
+
+        private static void AddSeparators(string name, int end, ICollection<string> seps)
+        {
+            int start = -1;
+            for (int i = end + 1; i < name.Length; ++i)
+            {
+                switch (name[i])
+                {
+                    case '{':
+                        if (start != -1)
+                            throw new ArgumentException(
+                                    string.Format(CultureInfo.InvariantCulture, "Ill-formed name/value separator found in \"{0}\".", name),
+                                    "name");
+                        start = i + 1;
+                        break;
+
+                    case '}':
+                        if (start == -1)
+                            throw new ArgumentException(
+                                    string.Format(CultureInfo.InvariantCulture, "Ill-formed name/value separator found in \"{0}\".", name),
+                                    "name");
+                        seps.Add(name.Substring(start, i - start));
+                        start = -1;
+                        break;
+
+                    default:
+                        if (start == -1)
+                            seps.Add(name[i].ToString());
+                        break;
+                }
+            }
+            if (start != -1)
+                throw new ArgumentException(
+                        string.Format(CultureInfo.InvariantCulture, "Ill-formed name/value separator found in \"{0}\".", name),
+                        "name");
+        }
+
+        public void Invoke(OptionContext optionContext)
+        {
+            OnParseComplete(optionContext);
+            optionContext.OptionName = null;
+            optionContext.Option = null;
+            optionContext.OptionValues.Clear();
+        }
+
+        protected abstract void OnParseComplete(OptionContext optionContext);
+
+        public override string ToString()
+        {
+            return Prototype;
+        }
+    }
+
+    public class OptionException : Exception
+    {
+        private string option;
+
+        public OptionException()
+        {
+        }
+
+        public OptionException(string message)
+            : base(message)
+        {
+        }
+
+        public OptionException(string message, Exception exception)
+            : base(message, exception)
+        {
+        }
+
+        public OptionException(string message, string optionName)
+            : base(message)
+        {
+            this.option = optionName;
+        }
+
+        public OptionException(string message, string optionName, Exception innerException)
+            : base(message, innerException)
+        {
+            this.option = optionName;
+        }
+
+        public string OptionName
+        {
+            get { return this.option; }
+        }
+    }
+
+    public delegate void OptionAction<TKey, TValue>(TKey key, TValue value);
+
+    public delegate TOutput Converter<in TInput, out TOutput>(TInput input);
+
+    public class OptionSetCollection : KeyedCollection<string, OptionBase>
+    {
+        public OptionSetCollection()
+            : this(delegate(string f) { return f; })
+        {
+        }
+
+        public OptionSetCollection(Converter<string, string> localizer)
+        {
+            this.localizer = localizer;
+        }
+
+        private Converter<string, string> localizer;
+
+        public Converter<string, string> MessageLocalizer
+        {
+            get { return localizer; }
+        }
+
+        protected override string GetKeyForItem(OptionBase item)
+        {
+            if (item == null)
+                throw new ArgumentNullException("item");
+            return item.Names[0];
+        }
+
+        protected override void InsertItem(int index, OptionBase item)
+        {
+            base.InsertItem(index, item);
+            AddImpl(item);
+        }
+
+        protected override void RemoveItem(int index)
+        {
+            OptionBase p = Items[index];
+            base.RemoveItem(index);
+            // KeyedCollection.RemoveItem() handles the 0th item
+            for (int i = 1; i < p.Names.Length; ++i)
+            {
+                Dictionary.Remove(p.Names[i]);
+            }
+        }
+
+        protected override void SetItem(int index, OptionBase item)
+        {
+            base.SetItem(index, item);
+            RemoveItem(index);
+            AddImpl(item);
+        }
+
+        private void AddImpl(OptionBase option)
+        {
+            List<string> added = new List<string>(option.Names.Length);
+            try
+            {
+                // KeyedCollection.InsertItem/SetItem handle the 0th name.
+                for (int i = 1; i < option.Names.Length; ++i)
+                {
+                    Dictionary.Add(option.Names[i], option);
+                    added.Add(option.Names[i]);
+                }
+            }
+            catch (Exception)
+            {
+                foreach (string name in added)
+                    Dictionary.Remove(name);
+                throw;
+            }
+        }
+
+        public new OptionSetCollection Add(OptionBase option)
+        {
+            base.Add(option);
+            return this;
+        }
+
+        private sealed class ActionOption : OptionBase
+        {
+            private Action<OptionValueCollection> action;
+
+            public ActionOption(string prototype, string description, int count, Action<OptionValueCollection> action)
+                : base(prototype, description, count)
+            {
+                this.action = action;
+            }
+
+            protected override void OnParseComplete(OptionContext c)
+            {
+                action(c.OptionValues);
+            }
+        }
+
+        public OptionSetCollection Add(string prototype, Action<string> action)
+        {
+            return Add(prototype, null, action);
+        }
+
+        public OptionSetCollection Add(string prototype, string description, Action<string> action)
+        {
+            if (action == null)
+                throw new ArgumentNullException("action");
+            OptionBase p = new ActionOption(prototype, description, 1,
+                    delegate(OptionValueCollection v) { action(v[0]); });
+            base.Add(p);
+            return this;
+        }
+
+        public OptionSetCollection Add(string prototype, OptionAction<string, string> action)
+        {
+            return Add(prototype, null, action);
+        }
+
+        public OptionSetCollection Add(string prototype, string description, OptionAction<string, string> action)
+        {
+            if (action == null)
+                throw new ArgumentNullException("action");
+            OptionBase p = new ActionOption(prototype, description, 2,
+                    delegate(OptionValueCollection v) { action(v[0], v[1]); });
+            base.Add(p);
+            return this;
+        }
+
+        private sealed class ActionOption<T> : OptionBase
+        {
+            private Action<T> action;
+
+            public ActionOption(string prototype, string description, Action<T> action)
+                : base(prototype, description, 1)
+            {
+                if (action == null)
+                    throw new ArgumentNullException("action");
+                this.action = action;
+            }
+
+            protected override void OnParseComplete(OptionContext c)
+            {
+                action(Parse<T>(c.OptionValues[0], c));
+            }
+        }
+
+        private sealed class ActionOption<TKey, TValue> : OptionBase
+        {
+            private OptionAction<TKey, TValue> action;
+
+            public ActionOption(string prototype, string description, OptionAction<TKey, TValue> action)
+                : base(prototype, description, 2)
+            {
+                if (action == null)
+                    throw new ArgumentNullException("action");
+                this.action = action;
+            }
+
+            protected override void OnParseComplete(OptionContext c)
+            {
+                action(
+                        Parse<TKey>(c.OptionValues[0], c),
+                        Parse<TValue>(c.OptionValues[1], c));
+            }
+        }
+
+        public OptionSetCollection Add<T>(string prototype, Action<T> action)
+        {
+            return Add(prototype, null, action);
+        }
+
+        public OptionSetCollection Add<T>(string prototype, string description, Action<T> action)
+        {
+            return Add(new ActionOption<T>(prototype, description, action));
+        }
+
+        public OptionSetCollection Add<TKey, TValue>(string prototype, OptionAction<TKey, TValue> action)
+        {
+            return Add(prototype, null, action);
+        }
+
+        public OptionSetCollection Add<TKey, TValue>(string prototype, string description, OptionAction<TKey, TValue> action)
+        {
+            return Add(new ActionOption<TKey, TValue>(prototype, description, action));
+        }
+
+        protected virtual OptionContext CreateOptionContext()
+        {
+            return new OptionContext(this);
+        }
+
+#if LINQ
+        public List<string> Parse (IEnumerable<string> arguments)
+        {
+            bool process = true;
+            OptionContext c = CreateOptionContext ();
+            c.OptionIndex = -1;
+            var def = GetOptionForName ("<>");
+            var unprocessed =
+                from argument in arguments
+                where ++c.OptionIndex >= 0 && (process || def != null)
+                    ? process
+                        ? argument == "--"
+                            ? (process = false)
+                            : !Parse (argument, c)
+                                ? def != null
+                                    ? Unprocessed (null, def, c, argument)
+                                    : true
+                                : false
+                        : def != null
+                            ? Unprocessed (null, def, c, argument)
+                            : true
+                    : true
+                select argument;
+            List<string> r = unprocessed.ToList ();
+            if (c.Option != null)
+                c.Option.Invoke (c);
+            return r;
+        }
+#else
+
+        public IList<string> Parse(IEnumerable<string> arguments)
+        {
+            OptionContext c = CreateOptionContext();
+            c.OptionIndex = -1;
+            bool process = true;
+            List<string> unprocessed = new List<string>();
+            OptionBase def = Contains("<>") ? this["<>"] : null;
+            foreach (string argument in arguments)
+            {
+                ++c.OptionIndex;
+                if (argument == "--")
+                {
+                    process = false;
+                    continue;
+                }
+                if (!process)
+                {
+                    Unprocessed(unprocessed, def, c, argument);
+                    continue;
+                }
+                if (!Parse(argument, c))
+                    Unprocessed(unprocessed, def, c, argument);
+            }
+            if (c.Option != null)
+                c.Option.Invoke(c);
+            return unprocessed;
+        }
+
+#endif
+
+        private static bool Unprocessed(ICollection<string> extra, OptionBase def, OptionContext c, string argument)
+        {
+            if (def == null)
+            {
+                extra.Add(argument);
+                return false;
+            }
+            c.OptionValues.Add(argument);
+            c.Option = def;
+            c.Option.Invoke(c);
+            return false;
+        }
+
+        private readonly Regex ValueOption = new Regex(
+            @"^(?<flag>--|-|/)(?<name>[^:=]+)((?<sep>[:=])(?<value>.*))?$");
+
+        [SuppressMessage("Microsoft.Naming", "CA1726:UsePreferredTerms", MessageId = "flag")]
+        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")]
+        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "2#")]
+        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "3#")]
+        [SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "4#")]
+        protected bool GetOptionParts(string argument, out string flag, out string name, out string sep, out string value)
+        {
+            if (argument == null)
+                throw new ArgumentNullException("argument");
+
+            flag = name = sep = value = null;
+            Match m = ValueOption.Match(argument);
+            if (!m.Success)
+            {
+                return false;
+            }
+            flag = m.Groups["flag"].Value;
+            name = m.Groups["name"].Value;
+            if (m.Groups["sep"].Success && m.Groups["value"].Success)
+            {
+                sep = m.Groups["sep"].Value;
+                value = m.Groups["value"].Value;
+            }
+            return true;
+        }
+
+        protected virtual bool Parse(string argument, OptionContext optionContext)
+        {
+            if (optionContext.Option != null)
+            {
+                ParseValue(argument, optionContext);
+                return true;
+            }
+
+            string f, n, s, v;
+            if (!GetOptionParts(argument, out f, out n, out s, out v))
+                return false;
+
+            OptionBase p;
+            if (Contains(n))
+            {
+                p = this[n];
+                optionContext.OptionName = f + n;
+                optionContext.Option = p;
+                switch (p.OptionValueType)
+                {
+                    case OptionValueType.None:
+                        optionContext.OptionValues.Add(n);
+                        optionContext.Option.Invoke(optionContext);
+                        break;
+
+                    case OptionValueType.Optional:
+                    case OptionValueType.Required:
+                        ParseValue(v, optionContext);
+                        break;
+                }
+                return true;
+            }
+            // no match; is it a bool option?
+            if (ParseBool(argument, n, optionContext))
+                return true;
+            // is it a bundled option?
+            if (ParseBundledValue(f, string.Concat(n + s + v), optionContext))
+                return true;
+
+            return false;
+        }
+
+        private void ParseValue(string option, OptionContext c)
+        {
+            if (option != null)
+                foreach (string o in c.Option.ValueSeparators != null
+                        ? option.Split(c.Option.ValueSeparators, StringSplitOptions.None)
+                        : new string[] { option })
+                {
+                    c.OptionValues.Add(o);
+                }
+            if (c.OptionValues.Count == c.Option.MaxValueCount ||
+                    c.Option.OptionValueType == OptionValueType.Optional)
+                c.Option.Invoke(c);
+            else if (c.OptionValues.Count > c.Option.MaxValueCount)
+            {
+                throw new OptionException(localizer(string.Format(CultureInfo.InvariantCulture,
+                                "Error: Found {0} option values when expecting {1}.",
+                                c.OptionValues.Count, c.Option.MaxValueCount)),
+                        c.OptionName);
+            }
+        }
+
+        private bool ParseBool(string option, string n, OptionContext c)
+        {
+            OptionBase p;
+            string rn;
+            if (n.Length >= 1 && (n[n.Length - 1] == '+' || n[n.Length - 1] == '-') &&
+                    Contains((rn = n.Substring(0, n.Length - 1))))
+            {
+                p = this[rn];
+                string v = n[n.Length - 1] == '+' ? option : null;
+                c.OptionName = option;
+                c.Option = p;
+                c.OptionValues.Add(v);
+                p.Invoke(c);
+                return true;
+            }
+            return false;
+        }
+
+        private bool ParseBundledValue(string f, string n, OptionContext c)
+        {
+            if (f != "-")
+                return false;
+            for (int i = 0; i < n.Length; ++i)
+            {
+                OptionBase p;
+                string opt = f + n[i].ToString();
+                string rn = n[i].ToString();
+                if (!Contains(rn))
+                {
+                    if (i == 0)
+                        return false;
+                    throw new OptionException(string.Format(CultureInfo.InvariantCulture, localizer(
+                                    "Cannot bundle unregistered option '{0}'."), opt), opt);
+                }
+                p = this[rn];
+                switch (p.OptionValueType)
+                {
+                    case OptionValueType.None:
+                        Invoke(c, opt, n, p);
+                        break;
+
+                    case OptionValueType.Optional:
+                    case OptionValueType.Required:
+                        {
+                            string v = n.Substring(i + 1);
+                            c.Option = p;
+                            c.OptionName = opt;
+                            ParseValue(v.Length != 0 ? v : null, c);
+                            return true;
+                        }
+                }
+            }
+            return true;
+        }
+
+        private static void Invoke(OptionContext c, string name, string value, OptionBase option)
+        {
+            c.OptionName = name;
+            c.Option = option;
+            c.OptionValues.Add(value);
+            option.Invoke(c);
+        }
+
+        private const int OptionWidth = 29;
+
+        public void WriteOptionDescriptions(TextWriter writer)
+        {
+            foreach (OptionBase p in this)
+            {
+                int written = 0;
+                if (!WriteOptionPrototype(writer, p, ref written))
+                    continue;
+
+                if (written < OptionWidth)
+                    writer.Write(new string(' ', OptionWidth - written));
+                else
+                {
+                    writer.WriteLine();
+                    writer.Write(new string(' ', OptionWidth));
+                }
+
+                List<string> lines = GetLines(localizer(GetDescription(p.Description)));
+                writer.WriteLine(lines[0]);
+                string prefix = new string(' ', OptionWidth + 2);
+                for (int i = 1; i < lines.Count; ++i)
+                {
+                    writer.Write(prefix);
+                    writer.WriteLine(lines[i]);
+                }
+            }
+        }
+
+        private bool WriteOptionPrototype(TextWriter o, OptionBase p, ref int written)
+        {
+            string[] names = p.Names;
+
+            int i = GetNextOptionIndex(names, 0);
+            if (i == names.Length)
+                return false;
+
+            if (names[i].Length == 1)
+            {
+                Write(o, ref written, "  -");
+                Write(o, ref written, names[0]);
+            }
+            else
+            {
+                Write(o, ref written, "      --");
+                Write(o, ref written, names[0]);
+            }
+
+            for (i = GetNextOptionIndex(names, i + 1);
+                    i < names.Length; i = GetNextOptionIndex(names, i + 1))
+            {
+                Write(o, ref written, ", ");
+                Write(o, ref written, names[i].Length == 1 ? "-" : "--");
+                Write(o, ref written, names[i]);
+            }
+
+            if (p.OptionValueType == OptionValueType.Optional ||
+                    p.OptionValueType == OptionValueType.Required)
+            {
+                if (p.OptionValueType == OptionValueType.Optional)
+                {
+                    Write(o, ref written, localizer("["));
+                }
+                Write(o, ref written, localizer("=" + GetArgumentName(0, p.MaxValueCount, p.Description)));
+                string sep = p.ValueSeparators != null && p.ValueSeparators.Length > 0
+                    ? p.ValueSeparators[0]
+                    : " ";
+                for (int c = 1; c < p.MaxValueCount; ++c)
+                {
+                    Write(o, ref written, localizer(sep + GetArgumentName(c, p.MaxValueCount, p.Description)));
+                }
+                if (p.OptionValueType == OptionValueType.Optional)
+                {
+                    Write(o, ref written, localizer("]"));
+                }
+            }
+            return true;
+        }
+
+        private static int GetNextOptionIndex(string[] names, int i)
+        {
+            while (i < names.Length && names[i] == "<>")
+            {
+                ++i;
+            }
+            return i;
+        }
+
+        private static void Write(TextWriter o, ref int n, string s)
+        {
+            n += s.Length;
+            o.Write(s);
+        }
+
+        private static string GetArgumentName(int index, int maxIndex, string description)
+        {
+            if (description == null)
+                return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+            string[] nameStart;
+            if (maxIndex == 1)
+                nameStart = new string[] { "{0:", "{" };
+            else
+                nameStart = new string[] { "{" + index + ":" };
+            for (int i = 0; i < nameStart.Length; ++i)
+            {
+                int start, j = 0;
+                do
+                {
+                    start = description.IndexOf(nameStart[i], j, StringComparison.Ordinal);
+                } while (start >= 0 && j != 0 ? description[j++ - 1] == '{' : false);
+                if (start == -1)
+                    continue;
+                int end = description.IndexOf("}", start, StringComparison.Ordinal);
+                if (end == -1)
+                    continue;
+                return description.Substring(start + nameStart[i].Length, end - start - nameStart[i].Length);
+            }
+            return maxIndex == 1 ? "VALUE" : "VALUE" + (index + 1);
+        }
+
+        private static string GetDescription(string description)
+        {
+            if (description == null)
+                return string.Empty;
+            StringBuilder sb = new StringBuilder(description.Length);
+            int start = -1;
+            for (int i = 0; i < description.Length; ++i)
+            {
+                switch (description[i])
+                {
+                    case '{':
+                        if (i == start)
+                        {
+                            sb.Append('{');
+                            start = -1;
+                        }
+                        else if (start < 0)
+                            start = i + 1;
+                        break;
+
+                    case '}':
+                        if (start < 0)
+                        {
+                            if ((i + 1) == description.Length || description[i + 1] != '}')
+                                throw new InvalidOperationException("Invalid option description: " + description);
+                            ++i;
+                            sb.Append("}");
+                        }
+                        else
+                        {
+                            sb.Append(description.Substring(start, i - start));
+                            start = -1;
+                        }
+                        break;
+
+                    case ':':
+                        if (start < 0)
+                            goto default;
+                        start = i + 1;
+                        break;
+
+                    default:
+                        if (start < 0)
+                            sb.Append(description[i]);
+                        break;
+                }
+            }
+            return sb.ToString();
+        }
+
+        private static List<string> GetLines(string description)
+        {
+            List<string> lines = new List<string>();
+            if (string.IsNullOrEmpty(description))
+            {
+                lines.Add(string.Empty);
+                return lines;
+            }
+            int length = 80 - OptionWidth - 2;
+            int start = 0, end;
+            do
+            {
+                end = GetLineEnd(start, length, description);
+                bool cont = false;
+                if (end < description.Length)
+                {
+                    char c = description[end];
+                    if (c == '-' || (char.IsWhiteSpace(c) && c != '\n'))
+                        ++end;
+                    else if (c != '\n')
+                    {
+                        cont = true;
+                        --end;
+                    }
+                }
+                lines.Add(description.Substring(start, end - start));
+                if (cont)
+                {
+                    lines[lines.Count - 1] += "-";
+                }
+                start = end;
+                if (start < description.Length && description[start] == '\n')
+                    ++start;
+            } while (end < description.Length);
+            return lines;
+        }
+
+        private static int GetLineEnd(int start, int length, string description)
+        {
+            int end = Math.Min(start + length, description.Length);
+            int sep = -1;
+            for (int i = start; i < end; ++i)
+            {
+                switch (description[i])
+                {
+                    case ' ':
+                    case '\t':
+                    case '\v':
+                    case '-':
+                    case ',':
+                    case '.':
+                    case ';':
+                        sep = i;
+                        break;
+
+                    case '\n':
+                        return i;
+                }
+            }
+            if (sep == -1 || end == description.Length)
+                return end;
+            return sep;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ParallelFileOperation.cs b/Axantum.AxCrypt.Core/UI/ParallelFileOperation.cs
new file mode 100644
index 0000000..aadfb9c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ParallelFileOperation.cs
@@ -0,0 +1,85 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    /// <summary>
+    /// Performs file operations with controlled degree of parallelism.
+    /// </summary>
+    public class ParallelFileOperation
+    {
+        public ParallelFileOperation()
+        {
+        }
+
+        /// <summary>
+        /// Does an operation on a list of files, with parallelism.
+        /// </summary>
+        /// <param name="files">The files to operation on.</param>
+        /// <param name="work">The work to do for each file.</param>
+        /// <param name="allComplete">The completion callback after *all* files have been processed.</param>
+        public virtual void DoFiles(IEnumerable<IRuntimeFileInfo> files, Func<IRuntimeFileInfo, IProgressContext, FileOperationContext> work, Action<FileOperationContext> allComplete)
+        {
+            WorkerGroup workerGroup = null;
+            Instance.ProgressBackground.Work(
+                (IProgressContext progress) =>
+                {
+                    using (workerGroup = new WorkerGroup(OS.Current.MaxConcurrency, progress))
+                    {
+                        foreach (IRuntimeFileInfo file in files)
+                        {
+                            IThreadWorker worker = workerGroup.CreateWorker(true);
+                            if (workerGroup.FirstError.Status != FileOperationStatus.Success)
+                            {
+                                worker.Abort();
+                                break;
+                            }
+
+                            IRuntimeFileInfo closureOverCopyOfLoopVariableFile = file;
+                            worker.Work += (sender, e) =>
+                            {
+                                e.Result = work(closureOverCopyOfLoopVariableFile, new CancelProgressContext(e.Progress));
+                            };
+                            worker.Run();
+                        }
+                        workerGroup.WaitAllAndFinish();
+                        return workerGroup.FirstError;
+                    }
+                },
+                (FileOperationContext status) =>
+                {
+                    allComplete(status);
+                });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ProgressContext.cs b/Axantum.AxCrypt.Core/UI/ProgressContext.cs
new file mode 100644
index 0000000..e82681d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ProgressContext.cs
@@ -0,0 +1,243 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    /// <summary>
+    /// Coordinate progress reporting, marshaling reports to the original instantiating thread (if
+    /// it has a SynchronizationContext) and throttle the amount of calls based on a timer.
+    /// </summary>
+    public class ProgressContext : IProgressContext
+    {
+        private static readonly TimeSpan TimeToFirstProgress = TimeSpan.FromMilliseconds(500);
+
+        private static readonly TimeSpan ProgressTimeInterval = TimeSpan.FromMilliseconds(100);
+
+        private TimeSpan _nextProgressTime;
+
+        private SynchronizationContext _synchronizationContext;
+
+        private ITiming _stopwatch = OS.Current.StartTiming();
+
+        private static readonly object _progressLock = new object();
+
+        private long _current = 0;
+
+        private long _total = -1;
+
+        private static readonly object _progressLevelLock = new object();
+
+        private int _progressLevel = 0;
+
+        public ProgressContext()
+            : this(TimeToFirstProgress)
+        {
+        }
+
+        public ProgressContext(TimeSpan timeToFirstProgress)
+        {
+            _nextProgressTime = timeToFirstProgress;
+            _synchronizationContext = OS.Current.SynchronizationContext;
+        }
+
+        /// <summary>
+        /// Set to true to have an OperationCanceledException being thrown in the progress reporting
+        /// thread at the earliest opportunity.
+        /// </summary>
+        public bool Cancel
+        {
+            get;
+            set;
+        }
+
+        public bool AllItemsConfirmed { get; set; }
+
+        private int _items;
+
+        public int Items { get { return _items; } }
+
+        public int AddItems(int count)
+        {
+            return Interlocked.Add(ref _items, count);
+        }
+
+        /// <summary>
+        /// Progress has occurred. The actual number of events are throttled, so not all reports
+        /// of progress will result in an event being raised. Only if NotifyLevelStart() / NotifyLevelFinished()
+        /// are used, will a percentage of 100 be reported, and then only exactly once.
+        /// </summary>
+        public event EventHandler<ProgressEventArgs> Progressing;
+
+        protected virtual void OnProgressing(ProgressEventArgs e)
+        {
+            EventHandler<ProgressEventArgs> handler = Progressing;
+            if (handler != null)
+            {
+                _synchronizationContext.Post((state) =>
+                {
+                    handler(this, (ProgressEventArgs)state);
+                },
+                e);
+            }
+        }
+
+        /// <summary>
+        /// Add to the total work count.
+        /// </summary>
+        /// <param name="count">The amount of work to add.</param>
+        public void AddTotal(long count)
+        {
+            Invariant();
+            if (count <= 0)
+            {
+                return;
+            }
+            lock (_progressLock)
+            {
+                if (_total < 0)
+                {
+                    _total = count;
+                }
+                else
+                {
+                    _total += count;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Add to the count of work having been performed. May lead to a Progressing event.
+        /// </summary>
+        /// <param name="count">The amount of work having been performed in this step.</param>
+        public void AddCount(long count)
+        {
+            Invariant();
+            if (count < 0)
+            {
+                return;
+            }
+            lock (_progressLock)
+            {
+                _current += count;
+                if (_stopwatch.Elapsed < _nextProgressTime)
+                {
+                    return;
+                }
+                _nextProgressTime = _stopwatch.Elapsed.Add(ProgressTimeInterval);
+            }
+            ProgressEventArgs e = new ProgressEventArgs(Percent);
+            OnProgressing(e);
+        }
+
+        public void RemoveCount(long totalCount, long progressCount)
+        {
+            lock (_progressLock)
+            {
+                _total -= totalCount;
+                _current -= progressCount;
+            }
+        }
+
+        private int Percent
+        {
+            get
+            {
+                lock (_progressLock)
+                {
+                    if (_total < 0)
+                    {
+                        return 0;
+                    }
+                    long current100 = _current * 100;
+                    int percent = (int)(current100 / _total);
+                    if (percent >= 100)
+                    {
+                        percent = 99;
+                    }
+                    return percent;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Start a new progress tracking level. Use this to indicate the start of a (sub-)operation
+        /// that tracks progress.
+        /// </summary>
+        public void NotifyLevelStart()
+        {
+            Invariant();
+            lock (_progressLevelLock)
+            {
+                ++_progressLevel;
+            }
+        }
+
+        /// <summary>
+        /// End a progress tracking level. When a transition to zero active levels occurs, then and only then,
+        /// is a Progressing event raised with a percent value of 100.
+        /// Calls to NotifyLevelStart() and NotifyLevelFinished() must be balanced.
+        /// </summary>
+        public void NotifyLevelFinished()
+        {
+            Invariant();
+            lock (_progressLevelLock)
+            {
+                if (_progressLevel == 0)
+                {
+                    throw new InvalidOperationException("Call to NotifyLevelFinished() without prior call to NotifyLevelStart().");
+                }
+                if (--_progressLevel > 0)
+                {
+                    return;
+                }
+                --_progressLevel;
+            }
+            ProgressEventArgs e = new ProgressEventArgs(100);
+            OnProgressing(e);
+        }
+
+        private void Invariant()
+        {
+            if (_progressLevel < 0)
+            {
+                throw new InvalidOperationException("Out-of-sequence call, cannot call after being finished.");
+            }
+        }
+
+        public void EnterSingleThread()
+        {
+        }
+
+        public void LeaveSingleThread()
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ProgressEventArgs.cs b/Axantum.AxCrypt.Core/UI/ProgressEventArgs.cs
new file mode 100644
index 0000000..d2fe042
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ProgressEventArgs.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class ProgressEventArgs : EventArgs
+    {
+        public ProgressEventArgs(int percent)
+        {
+            Percent = percent;
+        }
+
+        public int Percent { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/PublicResources.cs b/Axantum.AxCrypt.Core/UI/PublicResources.cs
new file mode 100644
index 0000000..4f07281
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/PublicResources.cs
@@ -0,0 +1,86 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Properties;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public static class PublicResources
+    {
+#if DEBUG
+#pragma warning disable 414
+
+        [SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields", Justification = "This is just a dummy here to ensure 100% code coverage in Unit Tests.")]
+        private static Axantum.AxCrypt.Core.Properties.Resources _codeCoverageForInternalDesignerGeneratedConstructorDummy = new Axantum.AxCrypt.Core.Properties.Resources();
+
+#pragma warning restore 414
+#endif
+
+        public static CultureInfo Culture
+        {
+            get
+            {
+                return Resources.Culture;
+            }
+            set
+            {
+                Resources.Culture = value;
+            }
+        }
+
+        public static Stream AxCryptIcon
+        {
+            get
+            {
+                return typeof(Resources).Assembly.GetManifestResourceStream("Axantum.AxCrypt.Core.resources.axcrypticon.ico");
+            }
+        }
+
+        public static string BouncycastleLicense
+        {
+            get
+            {
+                return Resources.bouncycastlelicense;
+            }
+        }
+
+        public static string JsonNetLicense
+        {
+            get
+            {
+                return Resources.json_netlicense;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/UpdateCheck.cs b/Axantum.AxCrypt.Core/UI/UpdateCheck.cs
new file mode 100644
index 0000000..226aeec
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/UpdateCheck.cs
@@ -0,0 +1,256 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Newtonsoft.Json;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class UpdateCheck : IDisposable
+    {
+        private class Pair<T, U>
+        {
+            public T First { get; set; }
+
+            public U Second { get; set; }
+
+            public Pair(T first, U second)
+            {
+                First = first;
+                Second = second;
+            }
+        }
+
+        public static readonly Version VersionUnknown = new Version(0, 0, 0, 0);
+
+        private Version _currentVersion;
+
+        public UpdateCheck(Version currentVersion)
+        {
+            _currentVersion = currentVersion;
+        }
+
+        public virtual event EventHandler<VersionEventArgs> VersionUpdate;
+
+        private ManualResetEvent _done = new ManualResetEvent(true);
+
+        private readonly object _doneLock = new object();
+
+        /// <summary>
+        /// Perform a background version check. The VersionUpdate event is guaranteed to be
+        /// raised, regardless of response and result. If a check is already in progress, the
+        /// later call is ignored and only one check is performed.
+        /// </summary>
+        public virtual void CheckInBackground(DateTime lastCheckTimeUtc, string newestKnownVersion, Uri webServiceUrl, Uri updateWebpageUrl)
+        {
+            if (newestKnownVersion == null)
+            {
+                throw new ArgumentNullException("newestKnownVersion");
+            }
+            if (webServiceUrl == null)
+            {
+                throw new ArgumentNullException("webServiceUrl");
+            }
+            if (updateWebpageUrl == null)
+            {
+                throw new ArgumentNullException("updateWebpageUrl");
+            }
+
+            Version newestKnownVersionValue = ParseVersion(newestKnownVersion);
+
+            if (_done == null)
+            {
+                throw new ObjectDisposedException("_done");
+            }
+            if (lastCheckTimeUtc.AddDays(1) >= OS.Current.UtcNow)
+            {
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Attempt to check for new version was ignored because it is too soon. Returning version {0}.".InvariantFormat(newestKnownVersionValue));
+                }
+                OnVersionUpdate(new VersionEventArgs(newestKnownVersionValue, updateWebpageUrl, CalculateStatus(newestKnownVersionValue, lastCheckTimeUtc)));
+                return;
+            }
+
+            lock (_doneLock)
+            {
+                if (!_done.WaitOne(TimeSpan.Zero))
+                {
+                    return;
+                }
+                _done.Reset();
+            }
+            ThreadPool.QueueUserWorkItem((object state) =>
+            {
+                try
+                {
+                    Pair<Version, Uri> newVersion = CheckWebForNewVersion(webServiceUrl, updateWebpageUrl);
+                    OnVersionUpdate(new VersionEventArgs(newVersion.First, newVersion.Second, CalculateStatus(newVersion.First, lastCheckTimeUtc)));
+                }
+                finally
+                {
+                    _done.Set();
+                }
+            });
+        }
+
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is one case where anything could go wrong and it is still required to continue.")]
+        private static Pair<Version, Uri> CheckWebForNewVersion(Uri webServiceUrl, Uri updateWebpageUrl)
+        {
+            Version newVersion = VersionUnknown;
+            try
+            {
+                IWebCaller webCaller = OS.Current.CreateWebCaller();
+                string result = webCaller.Go(webServiceUrl);
+
+                VersionResponse versionResponse = JsonConvert.DeserializeObject<VersionResponse>(result);
+
+                newVersion = ParseVersion(versionResponse.Version);
+                updateWebpageUrl = new Uri(versionResponse.WebReference);
+                if (Instance.Log.IsInfoEnabled)
+                {
+                    Instance.Log.LogInfo("Update check reports most recent version {0} at web page {1}".InvariantFormat(newVersion, updateWebpageUrl));
+                }
+            }
+            catch (Exception ex)
+            {
+                if (Instance.Log.IsWarningEnabled)
+                {
+                    Instance.Log.LogWarning("Failed call to check for new version with exception {0}.".InvariantFormat(ex));
+                }
+            }
+            return new Pair<Version, Uri>(newVersion, updateWebpageUrl);
+        }
+
+        /// <summary>
+        /// Wait for the background check (if any) to be complete. When this method returns, the
+        /// VersionUpdate event has already been raised.
+        /// </summary>
+        public void WaitForBackgroundCheckComplete()
+        {
+            if (_done == null)
+            {
+                throw new ObjectDisposedException("_done");
+            }
+            _done.WaitOne();
+        }
+
+        private static bool TryParseVersion(string versionString, out Version version)
+        {
+            version = VersionUnknown;
+            if (String.IsNullOrEmpty(versionString))
+            {
+                return false;
+            }
+            string[] parts = versionString.Split('.');
+            if (parts.Length > 4)
+            {
+                return false;
+            }
+            int[] numbers = new int[4];
+            for (int i = 0; i < parts.Length; ++i)
+            {
+                int number;
+                if (!Int32.TryParse(parts[i], NumberStyles.None, CultureInfo.InvariantCulture, out number))
+                {
+                    return false;
+                }
+                numbers[i] = number;
+            }
+            version = new Version(numbers[0], numbers[1], numbers[2], numbers[3]);
+            return true;
+        }
+
+        private static Version ParseVersion(string versionString)
+        {
+            Version version;
+            if (!TryParseVersion(versionString, out version))
+            {
+                return VersionUnknown;
+            }
+            if (version.Major == 0 && version.Minor == 0)
+            {
+                return VersionUnknown;
+            }
+            return version;
+        }
+
+        private VersionUpdateStatus CalculateStatus(Version version, DateTime lastCheckTimeutc)
+        {
+            if (version > _currentVersion)
+            {
+                return VersionUpdateStatus.NewerVersionIsAvailable;
+            }
+            if (version != VersionUnknown)
+            {
+                return VersionUpdateStatus.IsUpToDateOrRecentlyChecked;
+            }
+            if (lastCheckTimeutc.AddDays(30) >= OS.Current.UtcNow)
+            {
+                return VersionUpdateStatus.ShortTimeSinceLastSuccessfulCheck;
+            }
+            return VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck;
+        }
+
+        protected virtual void OnVersionUpdate(VersionEventArgs e)
+        {
+            EventHandler<VersionEventArgs> handler = VersionUpdate;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_done == null)
+            {
+                return;
+            }
+            if (disposing)
+            {
+                _done.Dispose();
+                _done = null;
+            }
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/UserSettings.cs b/Axantum.AxCrypt.Core/UI/UserSettings.cs
new file mode 100644
index 0000000..0f5c8e0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/UserSettings.cs
@@ -0,0 +1,283 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class UserSettings : IUserSettings
+    {
+        public int CurrentSettingsVersion { get { return 6; } }
+
+        private Dictionary<string, string> _settings = new Dictionary<string, string>();
+
+        private IRuntimeFileInfo _persistanceFileInfo;
+
+        private IterationCalculator _keyWrapIterationCalculator;
+
+        public UserSettings(IRuntimeFileInfo fileInfo, IterationCalculator keyWrapIterationCalculator)
+        {
+            _persistanceFileInfo = fileInfo;
+
+            _keyWrapIterationCalculator = keyWrapIterationCalculator;
+
+            if (!_persistanceFileInfo.IsExistingFile)
+            {
+                SettingsVersion = CurrentSettingsVersion;
+                return;
+            }
+
+            using (JsonReader reader = new JsonTextReader(new StreamReader(_persistanceFileInfo.OpenRead())))
+            {
+                JsonSerializer serializer = CreateSerializer();
+                _settings = serializer.Deserialize<Dictionary<string, string>>(reader);
+            }
+        }
+
+        private static JsonSerializer CreateSerializer()
+        {
+            JsonSerializerSettings serializerSettings = new JsonSerializerSettings()
+            {
+                DefaultValueHandling = DefaultValueHandling.Include,
+                Formatting = Formatting.Indented,
+                MissingMemberHandling = MissingMemberHandling.Ignore,
+                NullValueHandling = NullValueHandling.Include,
+            };
+            return JsonSerializer.Create(serializerSettings);
+        }
+
+        public void Delete()
+        {
+            _persistanceFileInfo.Delete();
+            _settings = new Dictionary<string, string>();
+        }
+
+        public string CultureName
+        {
+            get { return Load("CultureName", "en-US"); }
+            set { Store("CultureName", value); }
+        }
+
+        public Uri AxCrypt2VersionCheckUrl
+        {
+            get { return Load("AxCrypt2VersionCheckUrl", new Uri("https://www.axantum.com/Xecrets/RestApi.ashx/axcrypt2version/windows")); }
+            set { Store("AxCrypt2VersionCheckUrl", value.ToString()); }
+        }
+
+        public Uri UpdateUrl
+        {
+            get { return Load("UpdateUrl", new Uri("http://www.axantum.com/")); }
+            set { Store("UpdateUrl", value.ToString()); }
+        }
+
+        public DateTime LastUpdateCheckUtc
+        {
+            get { return Load("LastUpdateCheckUtc", DateTime.MinValue); }
+            set { Store("LastUpdateCheckUtc", value); }
+        }
+
+        public string NewestKnownVersion
+        {
+            get { return Load("NewestKnownVersion", String.Empty); }
+            set { Store("NewestKnownVersion", value); }
+        }
+
+        public bool DebugMode
+        {
+            get { return Load("DebugMode", false); }
+            set { Store("DebugMode", value); }
+        }
+
+        public Uri AxCrypt2HelpUrl
+        {
+            get { return Load("AxCrypt2HelpUrl", new Uri("http://www.axantum.com/AxCrypt/AxCryptNetHelp.html")); }
+            set { Store("AxCrypt2HelpUrl", value.ToString()); }
+        }
+
+        public bool DisplayEncryptPassphrase
+        {
+            get { return Load("DisplayEncryptPassphrase", true); }
+            set { Store("DisplayEncryptPassphrase", value); }
+        }
+
+        public bool DisplayDecryptPassphrase
+        {
+            get { return Load("DisplayDecryptPassphrase", true); }
+            set { Store("DisplayDecryptPassphrase", value); }
+        }
+
+        public long GetKeyWrapIterations(Guid cryptoId)
+        {
+            return Load(cryptoId.ToString("N"), () => _keyWrapIterationCalculator.KeyWrapIterations(cryptoId));
+        }
+
+        public void SetKeyWrapIterations(Guid cryptoId, long keyWrapIterations)
+        {
+            Store(cryptoId.ToString("N"), keyWrapIterations);
+        }
+
+        public Salt ThumbprintSalt
+        {
+            get { return Load("ThumbprintSalt", () => Factory.New<int, Salt>(512)); }
+            set { Store("ThumbprintSalt", JsonConvert.SerializeObject(value)); }
+        }
+
+        public TimeSpan SessionNotificationMinimumIdle
+        {
+            get { return Load("WorkFolderMinimumIdle", TimeSpan.FromMilliseconds(500)); }
+            set { Store("WorkFolderMinimumIdle", value); }
+        }
+
+        public int SettingsVersion
+        {
+            get { return Load("SettingsVersion", 0); }
+            set { Store("SettingsVersion", value); }
+        }
+
+        public int AsymmetricKeyBits
+        {
+            get { return Load("AsymmetricKeyBits", 4096); }
+            set { Store("AsymmetricKeyBits", value); }
+        }
+
+        public string this[string key]
+        {
+            get
+            {
+                string value;
+                if (!_settings.TryGetValue(key, out value))
+                {
+                    return String.Empty;
+                }
+                return value;
+            }
+            set
+            {
+                if (this[key] == value)
+                {
+                    return;
+                }
+                _settings[key] = value;
+                Save();
+            }
+        }
+
+        private void Save()
+        {
+            using (TextWriter writer = new StreamWriter(_persistanceFileInfo.OpenWrite()))
+            {
+                JsonSerializer serializer = CreateSerializer();
+                serializer.Serialize(writer, _settings);
+            }
+        }
+
+        public T Load<T>(string key)
+        {
+            return Load(key, default(T));
+        }
+
+        public T Load<T>(string key, Func<T> fallbackAction)
+        {
+            string value;
+            if (_settings.TryGetValue(key, out value))
+            {
+                try
+                {
+                    return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
+                }
+                catch (FormatException)
+                {
+                }
+            }
+
+            T fallback = fallbackAction();
+            this[key] = Convert.ToString(fallback, CultureInfo.InvariantCulture);
+            return fallback;
+        }
+
+        public Salt Load(string key, Func<Salt> fallbackAction)
+        {
+            string value;
+            if (_settings.TryGetValue(key, out value))
+            {
+                try
+                {
+                    return JsonConvert.DeserializeObject<Salt>(value);
+                }
+                catch (JsonException)
+                {
+                }
+            }
+
+            Salt fallback = fallbackAction();
+            this[key] = JsonConvert.SerializeObject(fallback);
+            return fallback;
+        }
+
+        public T Load<T>(string key, T fallback)
+        {
+            string value;
+            if (!_settings.TryGetValue(key, out value))
+            {
+                return fallback;
+            }
+            return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
+        }
+
+        public Uri Load(string key, Uri fallback)
+        {
+            string value;
+            if (!_settings.TryGetValue(key, out value))
+            {
+                return fallback;
+            }
+            return new Uri(value);
+        }
+
+        public TimeSpan Load(string key, TimeSpan fallback)
+        {
+            string value;
+            if (!_settings.TryGetValue(key, out value))
+            {
+                return fallback;
+            }
+            return TimeSpan.Parse(value, CultureInfo.InvariantCulture);
+        }
+
+        public void Store<T>(string key, T value)
+        {
+            this[key] = Convert.ToString(value, CultureInfo.InvariantCulture);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/VersionEventArgs.cs b/Axantum.AxCrypt.Core/UI/VersionEventArgs.cs
new file mode 100644
index 0000000..981e840
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/VersionEventArgs.cs
@@ -0,0 +1,50 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public class VersionEventArgs : EventArgs
+    {
+        public VersionEventArgs(Version version, Uri updateWebpageUrl, VersionUpdateStatus versionUpdateStatus)
+        {
+            Version = version;
+            UpdateWebpageUrl = updateWebpageUrl;
+            VersionUpdateStatus = versionUpdateStatus;
+        }
+
+        public Version Version { get; private set; }
+
+        public Uri UpdateWebpageUrl { get; private set; }
+
+        public VersionUpdateStatus VersionUpdateStatus { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/VersionResponse.cs b/Axantum.AxCrypt.Core/UI/VersionResponse.cs
new file mode 100644
index 0000000..1628231
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/VersionResponse.cs
@@ -0,0 +1,71 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Net;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    [DataContract]
+    public class VersionResponse
+    {
+        /// <summary>
+        /// Status
+        /// </summary>
+        [DataMember(Name = "S")]
+        public int Status { get; set; }
+
+        /// <summary>
+        /// Message
+        /// </summary>
+        [DataMember(Name = "M")]
+        public string Message { get; set; }
+
+        /// <summary>
+        /// Url where new version may be found
+        /// </summary>
+        [DataMember(Name = "U")]
+        public string WebReference { get; set; }
+
+        /// <summary>
+        /// String serialization of the full version
+        /// </summary>
+        [DataMember(Name = "V")]
+        public string Version { get; set; }
+
+        /// <summary>
+        /// The revision only
+        /// </summary>
+        [DataMember(Name = "R")]
+        public int Revision { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/VersionUpdateStatus.cs b/Axantum.AxCrypt.Core/UI/VersionUpdateStatus.cs
new file mode 100644
index 0000000..d69204c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/VersionUpdateStatus.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI
+{
+    public enum VersionUpdateStatus
+    {
+        Unknown,
+        IsUpToDateOrRecentlyChecked,
+        NewerVersionIsAvailable,
+        ShortTimeSinceLastSuccessfulCheck,
+        LongTimeSinceLastSuccessfulCheck,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/CreateNewAccountViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/CreateNewAccountViewModel.cs
new file mode 100644
index 0000000..f140377
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/CreateNewAccountViewModel.cs
@@ -0,0 +1,112 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    /// <summary>
+    /// Request user name and passphrase, get a public key pair from the server, or generate
+    /// locally, and store the result locally.
+    /// </summary>
+    public class CreateNewAccountViewModel : ViewModelBase
+    {
+        public string Passphrase { get { return GetProperty<string>("Passphrase"); } set { SetProperty("Passphrase", value); } }
+
+        public string Verification { get { return GetProperty<string>("Verification"); } set { SetProperty("Verification", value); } }
+
+        public bool ShowPassphrase { get { return GetProperty<bool>("ShowPassphrase"); } set { SetProperty("ShowPassphrase", value); } }
+
+        public string UserEmail { get { return GetProperty<string>("UserEmail"); } set { SetProperty("UserEmail", value); } }
+
+        public IAction CreateAccount { get { return new DelegateAction<object>((o) => CreateAccountAction()); } }
+
+        private UserAsymmetricKeysStore _keysStore;
+
+        public CreateNewAccountViewModel(UserAsymmetricKeysStore keysStore, string passphrase)
+        {
+            _keysStore = keysStore;
+
+            InitializePropertyValues(passphrase);
+            BindPropertyChangedEvents();
+        }
+
+        private void InitializePropertyValues(string passphrase)
+        {
+            Passphrase = passphrase ?? String.Empty;
+            Verification = passphrase ?? String.Empty;
+
+            UserEmail = String.Empty;
+            ShowPassphrase = Instance.UserSettings.DisplayEncryptPassphrase;
+        }
+
+        private void BindPropertyChangedEvents()
+        {
+            BindPropertyChangedInternal("ShowPassphrase", (bool show) => Instance.UserSettings.DisplayEncryptPassphrase = show);
+        }
+
+        public override string this[string columnName]
+        {
+            get
+            {
+                string error = base[columnName];
+                if (String.IsNullOrEmpty(error))
+                {
+                    error = Validate(columnName);
+                }
+                return error;
+            }
+        }
+
+        private string Validate(string columnName)
+        {
+            if (ValidateInternal(columnName))
+            {
+                return String.Empty;
+            }
+            return ValidationError.ToString(CultureInfo.InvariantCulture);
+        }
+
+        private bool ValidateInternal(string columnName)
+        {
+            switch (columnName)
+            {
+                case "UserEmail":
+                    if (!UserEmail.IsValidEmailOrEmpty())
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.InvalidEmail;
+                        return false;
+                    }
+                    return true;
+
+                case "Verification":
+                    if (String.IsNullOrEmpty(Verification))
+                    {
+                        return false;
+                    }
+                    return String.Compare(Passphrase, Verification, StringComparison.Ordinal) == 0;
+
+                case "Passphrase":
+                    return !String.IsNullOrEmpty(Passphrase);
+
+                default:
+                    throw new ArgumentException("Cannot validate property.", columnName);
+            }
+        }
+
+        private object CreateAccountAction()
+        {
+            if (String.IsNullOrEmpty(UserEmail))
+            {
+                return null;
+            }
+            _keysStore.Create(new EmailAddress(UserEmail), new Passphrase(Passphrase));
+
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/DelegateAction.cs b/Axantum.AxCrypt.Core/UI/ViewModel/DelegateAction.cs
new file mode 100644
index 0000000..703460c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/DelegateAction.cs
@@ -0,0 +1,85 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    /// <summary>
+    /// An IAction whose delegates can be attached for Execute(T) and CanExecute(T).
+    /// </summary>
+    public class DelegateAction<T> : IAction
+    {
+        private Action<T> _executeMethod;
+
+        private Func<T, bool> _canExecuteMethod;
+
+        public DelegateAction(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
+        {
+            _executeMethod = executeMethod;
+            _canExecuteMethod = canExecuteMethod;
+        }
+
+        public DelegateAction(Action<T> executeMethod)
+            : this(executeMethod, (parameter) => true)
+        {
+        }
+
+        public bool CanExecute(object parameter)
+        {
+            return _canExecuteMethod(parameter != null ? (T)parameter : default(T));
+        }
+
+        public void Execute(object parameter)
+        {
+            if (!CanExecute(parameter))
+            {
+                throw new InvalidOperationException("Execute() invoked when CanExecute() is false.");
+            }
+            _executeMethod((T)parameter);
+        }
+
+        public event EventHandler CanExecuteChanged;
+
+        protected virtual void OnCanExecuteChanged()
+        {
+            EventHandler handler = CanExecuteChanged;
+            if (handler != null)
+            {
+                Instance.UIThread.RunOnUIThread(() => handler(this, new EventArgs()));
+            }
+        }
+
+        [SuppressMessage("Microsoft.Design", "CA1030:UseEventsWhereAppropriate", Justification = "Method name taken from DelegateCommand implementation by Microsoft Patterns & Practices.")]
+        public void RaiseCanExecuteChanged()
+        {
+            OnCanExecuteChanged();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/FileOperationViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/FileOperationViewModel.cs
new file mode 100644
index 0000000..7ae7c64
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/FileOperationViewModel.cs
@@ -0,0 +1,413 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class FileOperationViewModel : ViewModelBase
+    {
+        private FileSystemState _fileSystemState;
+
+        private SessionNotify _sessionNotify;
+
+        private KnownKeys _knownKeys;
+
+        private ParallelFileOperation _fileOperation;
+
+        private IStatusChecker _statusChecker;
+
+        public IdentityViewModel IdentityViewModel { get; private set; }
+
+        public FileOperationViewModel(FileSystemState fileSystemState, SessionNotify sessionNotify, KnownKeys knownKeys, ParallelFileOperation fileOperation, IStatusChecker statusChecker, IdentityViewModel identityViewModel)
+        {
+            _fileSystemState = fileSystemState;
+            _sessionNotify = sessionNotify;
+            _knownKeys = knownKeys;
+            _fileOperation = fileOperation;
+            _statusChecker = statusChecker;
+
+            IdentityViewModel = identityViewModel;
+
+            InitializePropertyValues();
+            SubscribeToModelEvents();
+        }
+
+        private void SubscribeToModelEvents()
+        {
+            _sessionNotify.Notification += HandleSessionChanged;
+        }
+
+        private void InitializePropertyValues()
+        {
+            DecryptFiles = new DelegateAction<IEnumerable<string>>((files) => DecryptFilesAction(files));
+            EncryptFiles = new DelegateAction<IEnumerable<string>>((files) => EncryptFilesAction(files));
+            OpenFiles = new DelegateAction<IEnumerable<string>>((files) => OpenFilesAction(files));
+            DecryptFolders = new DelegateAction<IEnumerable<string>>((folders) => DecryptFoldersAction(folders), (folders) => _knownKeys.IsLoggedOn);
+            WipeFiles = new DelegateAction<IEnumerable<string>>((files) => WipeFilesAction(files));
+            RandomRenameFiles = new DelegateAction<IEnumerable<string>>((files) => RandomRenameFilesAction(files));
+            OpenFilesFromFolder = new DelegateAction<string>((folder) => OpenFilesFromFolderAction(folder), (folder) => _knownKeys.IsLoggedOn);
+            AddRecentFiles = new DelegateAction<IEnumerable<string>>((files) => AddRecentFilesAction(files));
+        }
+
+        public IAction DecryptFiles { get; private set; }
+
+        public IAction EncryptFiles { get; private set; }
+
+        public IAction OpenFiles { get; private set; }
+
+        public IAction DecryptFolders { get; private set; }
+
+        public IAction WipeFiles { get; private set; }
+
+        public IAction RandomRenameFiles { get; private set; }
+
+        public IAction OpenFilesFromFolder { get; private set; }
+
+        public IAction AddRecentFiles { get; private set; }
+
+        public event EventHandler<FileSelectionEventArgs> SelectingFiles;
+
+        protected virtual void OnSelectingFiles(FileSelectionEventArgs e)
+        {
+            EventHandler<FileSelectionEventArgs> handler = SelectingFiles;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        private void DecryptFoldersAction(IEnumerable<string> folders)
+        {
+            _fileOperation.DoFiles(folders.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), DecryptFolderWork, (status) => { });
+        }
+
+        private void EncryptFilesAction(IEnumerable<string> files)
+        {
+            files = files ?? SelectFiles(FileSelectionType.Encrypt);
+            if (!files.Any())
+            {
+                return;
+            }
+            if (!_knownKeys.IsLoggedOn)
+            {
+                IdentityViewModel.AskForLogOnPassphrase.Execute(PassphraseIdentity.Empty);
+            }
+            if (!_knownKeys.IsLoggedOn)
+            {
+                return;
+            }
+            _fileOperation.DoFiles(files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), EncryptFileWork, (status) => { });
+        }
+
+        private void DecryptFilesAction(IEnumerable<string> files)
+        {
+            files = files ?? SelectFiles(FileSelectionType.Decrypt);
+            if (!files.Any())
+            {
+                return;
+            }
+            if (!_knownKeys.IsLoggedOn)
+            {
+                IdentityViewModel.AskForLogOnPassphrase.Execute(PassphraseIdentity.Empty);
+            }
+            if (!_knownKeys.IsLoggedOn)
+            {
+                return;
+            }
+            _fileOperation.DoFiles(files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), DecryptFileWork, (status) => { });
+        }
+
+        private void WipeFilesAction(IEnumerable<string> files)
+        {
+            files = files ?? SelectFiles(FileSelectionType.Wipe);
+            if (!files.Any())
+            {
+                return;
+            }
+            _fileOperation.DoFiles(files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), WipeFileWork, (status) => { });
+        }
+
+        private void RandomRenameFilesAction(IEnumerable<string> files)
+        {
+            files = files ?? SelectFiles(FileSelectionType.Encrypt);
+            if (!files.Any())
+            {
+                return;
+            }
+            _fileOperation.DoFiles(files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), RandomRenameFileWork, (status) => { });
+        }
+
+        private IEnumerable<string> SelectFiles(FileSelectionType fileSelectionType)
+        {
+            FileSelectionEventArgs fileSelectionArgs = new FileSelectionEventArgs(new string[0])
+            {
+                FileSelectionType = fileSelectionType,
+            };
+            OnSelectingFiles(fileSelectionArgs);
+            if (fileSelectionArgs.Cancel)
+            {
+                return new string[0];
+            }
+            return fileSelectionArgs.SelectedFiles;
+        }
+
+        private void OpenFilesAction(IEnumerable<string> files)
+        {
+            _fileOperation.DoFiles(files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList(), OpenEncryptedWork, (status) => { });
+        }
+
+        private FileOperationContext DecryptFileWork(IRuntimeFileInfo file, IProgressContext progress)
+        {
+            FileOperationsController operationsController = new FileOperationsController(progress);
+
+            operationsController.QueryDecryptionPassphrase += HandleQueryDecryptionPassphraseEvent;
+
+            operationsController.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+            {
+                FileSelectionEventArgs fileSelectionArgs = new FileSelectionEventArgs(new string[] { e.SaveFileFullName })
+                {
+                    FileSelectionType = FileSelectionType.SaveAsDecrypted,
+                };
+                OnSelectingFiles(fileSelectionArgs);
+                if (fileSelectionArgs.Cancel)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                e.SaveFileFullName = fileSelectionArgs.SelectedFiles[0];
+            };
+
+            operationsController.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                _knownKeys.Add(e.Passphrase);
+            };
+
+            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                if (_statusChecker.CheckStatusAndShowMessage(e.Status.Status, e.Status.FullName))
+                {
+                    Factory.New<ActiveFileAction>().RemoveRecentFiles(new IRuntimeFileInfo[] { Factory.New<IRuntimeFileInfo>(e.OpenFileFullName) }, progress);
+                }
+            };
+
+            return operationsController.DecryptFile(file);
+        }
+
+        private FileOperationContext WipeFileWork(IRuntimeFileInfo file, IProgressContext progress)
+        {
+            FileOperationsController operationsController = new FileOperationsController(progress);
+
+            operationsController.WipeQueryConfirmation += (object sender, FileOperationEventArgs e) =>
+            {
+                FileSelectionEventArgs fileSelectionArgs = new FileSelectionEventArgs(new string[] { file.FullName, })
+                {
+                    FileSelectionType = FileSelectionType.WipeConfirm,
+                };
+                OnSelectingFiles(fileSelectionArgs);
+                e.Cancel = fileSelectionArgs.Cancel;
+                e.Skip = fileSelectionArgs.Skip;
+                e.ConfirmAll = fileSelectionArgs.ConfirmAll;
+                e.SaveFileFullName = fileSelectionArgs.SelectedFiles.FirstOrDefault() ?? String.Empty;
+            };
+
+            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                if (e.Skip)
+                {
+                    return;
+                }
+                if (Instance.StatusChecker.CheckStatusAndShowMessage(e.Status.Status, e.Status.FullName))
+                {
+                    Factory.New<ActiveFileAction>().RemoveRecentFiles(new IRuntimeFileInfo[] { Factory.New<IRuntimeFileInfo>(e.SaveFileFullName) }, progress);
+                }
+            };
+
+            return operationsController.WipeFile(file);
+        }
+
+        private FileOperationContext RandomRenameFileWork(IRuntimeFileInfo file, IProgressContext progress)
+        {
+            file.MoveTo(file.CreateRandomUniqueName().FullName);
+
+            return new FileOperationContext(file.FullName, FileOperationStatus.Success);
+        }
+
+        private FileOperationContext OpenEncryptedWork(IRuntimeFileInfo file, IProgressContext progress)
+        {
+            FileOperationsController operationsController = new FileOperationsController(progress);
+
+            operationsController.QueryDecryptionPassphrase += HandleQueryDecryptionPassphraseEvent;
+
+            operationsController.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                if (!_fileSystemState.Identities.Any(i => i.Thumbprint == e.Passphrase.Thumbprint))
+                {
+                    _fileSystemState.Identities.Add(new PassphraseIdentity(e.Passphrase));
+                    _fileSystemState.Save();
+                }
+                _knownKeys.Add(e.Passphrase);
+            };
+
+            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                if (e.Status.Status == FileOperationStatus.Canceled)
+                {
+                    return;
+                }
+                _statusChecker.CheckStatusAndShowMessage(e.Status.Status, e.OpenFileFullName);
+            };
+
+            return operationsController.DecryptAndLaunch(file);
+        }
+
+        private void HandleQueryDecryptionPassphraseEvent(object sender, FileOperationEventArgs e)
+        {
+            IdentityViewModel.AskForDecryptPassphrase.Execute(e.OpenFileFullName);
+            if (IdentityViewModel.Passphrase == null)
+            {
+                e.Cancel = true;
+                return;
+            }
+            e.Passphrase = IdentityViewModel.Passphrase;
+        }
+
+        private FileOperationContext EncryptFileWork(IRuntimeFileInfo file, IProgressContext progress)
+        {
+            FileOperationsController operationsController = Factory.New<IProgressContext, FileOperationsController>(progress);
+
+            operationsController.QuerySaveFileAs += (object sender, FileOperationEventArgs e) =>
+            {
+                e.SaveFileFullName = Factory.New<IRuntimeFileInfo>(e.SaveFileFullName).FullName.CreateUniqueFile();
+            };
+
+            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                if (e.Status.Status == FileOperationStatus.FileAlreadyEncrypted)
+                {
+                    e.Status = new FileOperationContext(String.Empty, FileOperationStatus.Success);
+                    return;
+                }
+                if (_statusChecker.CheckStatusAndShowMessage(e.Status.Status, e.Status.FullName))
+                {
+                    IRuntimeFileInfo encryptedInfo = Factory.New<IRuntimeFileInfo>(e.SaveFileFullName);
+                    IRuntimeFileInfo decryptedInfo = Factory.New<IRuntimeFileInfo>(FileOperation.GetTemporaryDestinationName(e.OpenFileFullName));
+                    ActiveFile activeFile = new ActiveFile(encryptedInfo, decryptedInfo, e.Passphrase, ActiveFileStatus.NotDecrypted, e.CryptoId);
+                    _fileSystemState.Add(activeFile);
+                    _fileSystemState.Save();
+                }
+            };
+
+            return operationsController.EncryptFile(file);
+        }
+
+        private FileOperationContext VerifyAndAddActiveWork(IRuntimeFileInfo fullName, IProgressContext progress)
+        {
+            FileOperationsController operationsController = new FileOperationsController(progress);
+
+            operationsController.QueryDecryptionPassphrase += HandleQueryDecryptionPassphraseEvent;
+
+            operationsController.KnownKeyAdded += (object sender, FileOperationEventArgs e) =>
+            {
+                if (!_fileSystemState.Identities.Any(i => i.Thumbprint == e.Passphrase.Thumbprint))
+                {
+                    _fileSystemState.Identities.Add(new PassphraseIdentity(e.Passphrase));
+                    _fileSystemState.Save();
+                }
+                _knownKeys.DefaultEncryptionKey = e.Passphrase;
+            };
+
+            operationsController.Completed += (object sender, FileOperationEventArgs e) =>
+            {
+                if (_statusChecker.CheckStatusAndShowMessage(e.Status.Status, e.OpenFileFullName))
+                {
+                    IRuntimeFileInfo encryptedInfo = Factory.New<IRuntimeFileInfo>(e.OpenFileFullName);
+                    IRuntimeFileInfo decryptedInfo = Factory.New<IRuntimeFileInfo>(FileOperation.GetTemporaryDestinationName(e.SaveFileFullName));
+                    ActiveFile activeFile = new ActiveFile(encryptedInfo, decryptedInfo, e.Passphrase, ActiveFileStatus.NotDecrypted, e.CryptoId);
+                    _fileSystemState.Add(activeFile);
+                    _fileSystemState.Save();
+                }
+            };
+
+            return operationsController.VerifyEncrypted(fullName);
+        }
+
+        private void OpenFilesFromFolderAction(string folder)
+        {
+            FileSelectionEventArgs fileSelectionArgs = new FileSelectionEventArgs(new string[] { folder })
+            {
+                FileSelectionType = FileSelectionType.Open,
+            };
+            OnSelectingFiles(fileSelectionArgs);
+            if (fileSelectionArgs.Cancel)
+            {
+                return;
+            }
+            OpenFilesAction(fileSelectionArgs.SelectedFiles);
+        }
+
+        private FileOperationContext DecryptFolderWork(IRuntimeFileInfo folder, IProgressContext progress)
+        {
+            Factory.New<AxCryptFile>().DecryptFilesInsideFolderUniqueWithWipeOfOriginal(folder, _knownKeys.DefaultEncryptionKey, _statusChecker, progress);
+            return new FileOperationContext(String.Empty, FileOperationStatus.Success);
+        }
+
+        private void AddRecentFilesAction(IEnumerable<string> files)
+        {
+            IEnumerable<IRuntimeFileInfo> fileInfos = files.Select(f => Factory.New<IRuntimeFileInfo>(f)).ToList();
+            ProcessEncryptableFilesDroppedInRecentList(fileInfos.Where(fileInfo => Instance.KnownKeys.IsLoggedOn && fileInfo.Type() == FileInfoTypes.EncryptableFile));
+            ProcessEncryptedFilesDroppedInRecentList(fileInfos.Where(fileInfo => fileInfo.Type() == FileInfoTypes.EncryptedFile));
+        }
+
+        private void ProcessEncryptedFilesDroppedInRecentList(IEnumerable<IRuntimeFileInfo> encryptedFiles)
+        {
+            _fileOperation.DoFiles(encryptedFiles, VerifyAndAddActiveWork, (status) => { });
+        }
+
+        private void ProcessEncryptableFilesDroppedInRecentList(IEnumerable<IRuntimeFileInfo> encryptableFiles)
+        {
+            _fileOperation.DoFiles(encryptableFiles, EncryptFileWork, (status) => { });
+        }
+
+        private void HandleSessionChanged(object sender, SessionNotificationEventArgs e)
+        {
+            switch (e.Notification.NotificationType)
+            {
+                case SessionNotificationType.LogOff:
+                case SessionNotificationType.LogOn:
+                case SessionNotificationType.SessionStart:
+                    ((DelegateAction<string>)OpenFilesFromFolder).RaiseCanExecuteChanged();
+                    break;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionEventArgs.cs b/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionEventArgs.cs
new file mode 100644
index 0000000..4de75c8
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionEventArgs.cs
@@ -0,0 +1,51 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class FileSelectionEventArgs : EventArgs
+    {
+        public FileSelectionEventArgs(IEnumerable<string> files)
+        {
+            SelectedFiles = new List<string>(files);
+        }
+
+        public FileSelectionType FileSelectionType { get; set; }
+
+        public bool Cancel { get; set; }
+
+        public bool ConfirmAll { get; set; }
+
+        public bool Skip { get; set; }
+
+        public IList<string> SelectedFiles { get; private set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionType.cs b/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionType.cs
new file mode 100644
index 0000000..d3c1e0a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/FileSelectionType.cs
@@ -0,0 +1,44 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public enum FileSelectionType
+    {
+        Unknown,
+        Decrypt,
+        Encrypt,
+        Open,
+        Wipe,
+        WipeConfirm,
+        SaveAsEncrypted,
+        SaveAsDecrypted,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/IAction.cs b/Axantum.AxCrypt.Core/UI/ViewModel/IAction.cs
new file mode 100644
index 0000000..b906c7c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/IAction.cs
@@ -0,0 +1,45 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    /// <summary>
+    /// Defines an action on the Model exposed via a ViewModel. It is identical to the System.Windows.Input.ICommand
+    /// interface, but duplicated to avoid pulling a dependency that may not always be supported.
+    /// </summary>
+    public interface IAction
+    {
+        bool CanExecute(object parameter);
+
+        void Execute(object parameter);
+
+        event EventHandler CanExecuteChanged;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/IViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/IViewModel.cs
new file mode 100644
index 0000000..976da30
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/IViewModel.cs
@@ -0,0 +1,39 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.ComponentModel;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public interface IViewModel : INotifyPropertyChanged, IDataErrorInfo
+    {
+        T GetProperty<T>(string name);
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/IdentityViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/IdentityViewModel.cs
new file mode 100644
index 0000000..3469078
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/IdentityViewModel.cs
@@ -0,0 +1,212 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class IdentityViewModel : ViewModelBase
+    {
+        private FileSystemState _fileSystemState;
+
+        private KnownKeys _knownKeys;
+
+        private IUserSettings _userSettings;
+
+        public IdentityViewModel(FileSystemState fileSystemState, KnownKeys knownKeys, IUserSettings userSettings)
+        {
+            _fileSystemState = fileSystemState;
+            _knownKeys = knownKeys;
+            _userSettings = userSettings;
+
+            Passphrase = null;
+
+            LogOnLogOff = new DelegateAction<Guid>((cryptoId) => Passphrase = LogOnLogOffAction(cryptoId));
+            AskForDecryptPassphrase = new DelegateAction<string>((name) => Passphrase = AskForDecryptPassphraseAction(name));
+            AskForLogOnPassphrase = new DelegateAction<PassphraseIdentity>((id) => Passphrase = AskForLogOnPassphraseAction(id, String.Empty));
+            CryptoId = Instance.CryptoFactory.Default.Id;
+        }
+
+        public Passphrase Passphrase { get { return GetProperty<Passphrase>("Passphrase"); } set { SetProperty("Passphrase", value); } }
+
+        public Guid CryptoId { get { return GetProperty<Guid>("CryptoId"); } set { SetProperty("CryptoId", value); } }
+
+        public IAction LogOnLogOff { get; private set; }
+
+        public IAction AskForDecryptPassphrase { get; private set; }
+
+        public IAction AskForLogOnPassphrase { get; private set; }
+
+        public event EventHandler<LogOnEventArgs> LoggingOn;
+
+        protected virtual void OnLoggingOn(LogOnEventArgs e)
+        {
+            EventHandler<LogOnEventArgs> handler = LoggingOn;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        private Passphrase LogOnLogOffAction(Guid cryptoId)
+        {
+            if (_knownKeys.IsLoggedOn)
+            {
+                _knownKeys.Clear();
+                return null;
+            }
+
+            CryptoId = cryptoId != Guid.Empty ? cryptoId : Instance.CryptoFactory.Default.Id;
+
+            Passphrase passphrase;
+            if (_fileSystemState.Identities.Any())
+            {
+                passphrase = AskForLogOnPassphraseAction(PassphraseIdentity.Empty, String.Empty);
+                return passphrase;
+            }
+
+            passphrase = AskForNewEncryptionPassphrase(String.Empty, String.Empty);
+            if (passphrase == null)
+            {
+                return null;
+            }
+
+            _knownKeys.DefaultEncryptionKey = passphrase;
+            return _knownKeys.DefaultEncryptionKey;
+        }
+
+        private Passphrase KeyFromPassphrase(string passphrase)
+        {
+            foreach (PassphraseIdentity identity in _fileSystemState.Identities)
+            {
+                Passphrase candidate = new Passphrase(passphrase);
+                if (identity.Thumbprint == candidate.Thumbprint)
+                {
+                    return candidate;
+                }
+            }
+            return null;
+        }
+
+        private Passphrase AskForDecryptPassphraseAction(string encryptedFileFullName)
+        {
+            LogOnEventArgs logOnArgs = new LogOnEventArgs()
+            {
+                DisplayPassphrase = _userSettings.DisplayEncryptPassphrase,
+                Identity = PassphraseIdentity.Empty,
+                EncryptedFileFullName = encryptedFileFullName,
+            };
+            OnLoggingOn(logOnArgs);
+
+            _userSettings.DisplayEncryptPassphrase = logOnArgs.DisplayPassphrase;
+
+            if (logOnArgs.Cancel || logOnArgs.Passphrase.Length == 0)
+            {
+                return null;
+            }
+
+            return new Passphrase(logOnArgs.Passphrase);
+        }
+
+        private Passphrase AskForLogOnPassphraseAction(PassphraseIdentity identity, string encryptedFileFullName)
+        {
+            Passphrase passphrase = AskForLogOnOrEncryptionPassphrase(identity, encryptedFileFullName);
+            if (passphrase == null)
+            {
+                return null;
+            }
+
+            _knownKeys.DefaultEncryptionKey = passphrase;
+            return passphrase;
+        }
+
+        private Passphrase AskForLogOnOrEncryptionPassphrase(PassphraseIdentity identity, string encryptedFileFullName)
+        {
+            if (!_fileSystemState.Identities.Any())
+            {
+                return AskForNewEncryptionPassphrase(String.Empty, encryptedFileFullName);
+            }
+
+            LogOnEventArgs logOnArgs = new LogOnEventArgs()
+            {
+                DisplayPassphrase = _userSettings.DisplayEncryptPassphrase,
+                Identity = identity,
+                EncryptedFileFullName = encryptedFileFullName,
+            };
+            OnLoggingOn(logOnArgs);
+
+            if (logOnArgs.CreateNew)
+            {
+                return AskForNewEncryptionPassphrase(logOnArgs.Passphrase, encryptedFileFullName);
+            }
+
+            if (logOnArgs.Cancel || logOnArgs.Passphrase.Length == 0)
+            {
+                return null;
+            }
+
+            _userSettings.DisplayEncryptPassphrase = logOnArgs.DisplayPassphrase;
+
+            return KeyFromPassphrase(logOnArgs.Passphrase);
+        }
+
+        private Passphrase AskForNewEncryptionPassphrase(string defaultPassphrase, string encryptedFileFullName)
+        {
+            LogOnEventArgs logOnArgs = new LogOnEventArgs()
+            {
+                CreateNew = true,
+                DisplayPassphrase = _userSettings.DisplayEncryptPassphrase,
+                Passphrase = defaultPassphrase,
+                EncryptedFileFullName = encryptedFileFullName,
+            };
+            OnLoggingOn(logOnArgs);
+
+            if (logOnArgs.Cancel || logOnArgs.Passphrase.Length == 0)
+            {
+                return null;
+            }
+
+            _userSettings.DisplayEncryptPassphrase = logOnArgs.DisplayPassphrase;
+
+            Passphrase passphrase = new Passphrase(logOnArgs.Passphrase);
+            PassphraseIdentity identity = _fileSystemState.Identities.FirstOrDefault(i => i.Thumbprint == passphrase.Thumbprint);
+            if (identity != null)
+            {
+                return passphrase;
+            }
+
+            identity = new PassphraseIdentity(passphrase);
+            _fileSystemState.Identities.Add(identity);
+            _fileSystemState.Save();
+
+            return passphrase;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/KnownFoldersViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/KnownFoldersViewModel.cs
new file mode 100644
index 0000000..b27ef95
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/KnownFoldersViewModel.cs
@@ -0,0 +1,111 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class KnownFoldersViewModel : ViewModelBase
+    {
+        private FileSystemState _fileSystemState;
+
+        private SessionNotify _sessionNotify;
+
+        private KnownKeys _knownKeys;
+
+        public KnownFoldersViewModel(FileSystemState fileSystemState, SessionNotify sessionNotify, KnownKeys knownKeys)
+        {
+            _fileSystemState = fileSystemState;
+            _sessionNotify = sessionNotify;
+            _knownKeys = knownKeys;
+
+            InitializePropertyValues();
+            SubscribeToModelEvents();
+        }
+
+        private void SubscribeToModelEvents()
+        {
+            _sessionNotify.Notification += HandleSessionChanged;
+        }
+
+        public IEnumerable<KnownFolder> KnownFolders { get { return GetProperty<IEnumerable<KnownFolder>>("KnownFolders"); } set { SetProperty("KnownFolders", value.ToList()); } }
+
+        private void InitializePropertyValues()
+        {
+            KnownFolders = new KnownFolder[0];
+        }
+
+        private void EnsureKnownFoldersWatched(IEnumerable<KnownFolder> folders)
+        {
+            foreach (KnownFolder knownFolder in folders)
+            {
+                if (_fileSystemState.WatchedFolders.Any((wf) => wf.Path == knownFolder.MyFullPath.FullName))
+                {
+                    continue;
+                }
+                if (knownFolder.MyFullPath.IsExistingFile)
+                {
+                    continue;
+                }
+                if (!knownFolder.MyFullPath.IsExistingFolder)
+                {
+                    knownFolder.MyFullPath.CreateFolder();
+                }
+                _fileSystemState.AddWatchedFolder(new WatchedFolder(knownFolder.MyFullPath.FullName, _knownKeys.DefaultEncryptionKey.Thumbprint));
+            }
+        }
+
+        private IEnumerable<KnownFolder> UpdateEnabledState(IEnumerable<KnownFolder> knownFolders)
+        {
+            List<KnownFolder> updatedFolders = new List<KnownFolder>();
+            foreach (KnownFolder folder in knownFolders)
+            {
+                KnownFolder updated = new KnownFolder(folder, _knownKeys.LoggedOnWatchedFolders.Any(f => f.Path == folder.MyFullPath.FullName));
+                updatedFolders.Add(updated);
+            }
+            return updatedFolders;
+        }
+
+        private void HandleSessionChanged(object sender, SessionNotificationEventArgs e)
+        {
+            switch (e.Notification.NotificationType)
+            {
+                case SessionNotificationType.LogOff:
+                    KnownFolders = UpdateEnabledState(KnownFolders);
+                    break;
+
+                case SessionNotificationType.LogOn:
+                    EnsureKnownFoldersWatched(KnownFolders);
+                    KnownFolders = UpdateEnabledState(KnownFolders);
+                    break;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/LogOnAccountViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnAccountViewModel.cs
new file mode 100644
index 0000000..251211a
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnAccountViewModel.cs
@@ -0,0 +1,124 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    /// <summary>
+    /// Log On (enable default encryption key). If an e-mail is provided, an attempt is made to log on to the Internet
+    /// server and synchronize keys. If that fails, a locally accessible key-pair is required.
+    /// If no e-mail is provided, classic mode encryption is attempted, if this is enabled by the current feature policy.
+    /// </summary>
+    public class LogOnAccountViewModel : ViewModelBase
+    {
+        public LogOnAccountViewModel(string userEmail)
+        {
+            InitializePropertyValues(userEmail);
+            BindPropertyChangedEvents();
+        }
+
+        private void InitializePropertyValues(string userEmail)
+        {
+            UserEmail = userEmail;
+            Passphrase = String.Empty;
+            ShowPassphrase = Instance.UserSettings.DisplayEncryptPassphrase;
+            ShowEmail = Instance.AsymmetricKeysStore.HasStore;
+        }
+
+        private void BindPropertyChangedEvents()
+        {
+            BindPropertyChangedInternal("ShowPassphrase", (bool show) => Instance.UserSettings.DisplayEncryptPassphrase = show);
+            BindPropertyChangedInternal("ShowEmail", (bool show) => { if (!ShowEmail) UserEmail = String.Empty; });
+        }
+
+        public bool ShowPassphrase { get { return GetProperty<bool>("ShowPassphrase"); } set { SetProperty("ShowPassphrase", value); } }
+
+        public string Passphrase { get { return GetProperty<string>("Passphrase"); } set { SetProperty("Passphrase", value); } }
+
+        public string UserEmail { get { return GetProperty<string>("UserEmail"); } set { SetProperty("UserEmail", value); } }
+
+        public bool ShowEmail { get { return GetProperty<bool>("ShowEmail"); } private set { SetProperty("ShowEmail", value); } }
+
+        public override string this[string columnName]
+        {
+            get
+            {
+                string error = base[columnName];
+                if (String.IsNullOrEmpty(error))
+                {
+                    error = Validate(columnName);
+                }
+
+                return error;
+            }
+        }
+
+        private string Validate(string columnName)
+        {
+            if (ValidateInternal(columnName))
+            {
+                return String.Empty;
+            }
+            return ValidationError.ToString(CultureInfo.InvariantCulture);
+        }
+
+        private bool ValidateInternal(string columnName)
+        {
+            switch (columnName)
+            {
+                case "UserEmail":
+                    if (!ShowEmail)
+                    {
+                        return true;
+                    }
+                    if (!UserEmail.IsValidEmailOrEmpty())
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.InvalidEmail;
+                        return false;
+                    }
+                    return true;
+
+                case "Passphrase":
+                    if (ShowEmail && UserEmail.Length > 0 && UserEmail.IsValidEmail())
+                    {
+                        return IsValidAccountLogOn();
+                    }
+                    if (ShowEmail && UserEmail.Length > 0)
+                    {
+                        return true;
+                    }
+                    bool isKnownIdentity = IsKnownIdentity();
+                    if (!isKnownIdentity)
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.WrongPassphrase;
+                        return false;
+                    }
+                    return true;
+
+                default:
+                    throw new ArgumentException("Cannot validate property.", columnName);
+            }
+        }
+
+        private bool IsValidAccountLogOn()
+        {
+            return Instance.AsymmetricKeysStore.IsValidAccountLogOn(new EmailAddress(UserEmail), new Passphrase(Passphrase));
+        }
+
+        private bool IsKnownIdentity()
+        {
+            SymmetricKeyThumbprint thumbprint = new Passphrase(Passphrase).Thumbprint;
+            PassphraseIdentity identity = Instance.FileSystemState.Identities.FirstOrDefault(id => id.Thumbprint == thumbprint);
+            if (identity != null)
+            {
+                return true;
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/LogOnEventArgs.cs b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnEventArgs.cs
new file mode 100644
index 0000000..b4ac462
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnEventArgs.cs
@@ -0,0 +1,58 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class LogOnEventArgs : EventArgs
+    {
+        public LogOnEventArgs()
+        {
+            Passphrase = String.Empty;
+            Identity = PassphraseIdentity.Empty;
+        }
+
+        public bool Cancel { get; set; }
+
+        public bool CreateNew { get; set; }
+
+        public bool DisplayPassphrase { get; set; }
+
+        public string Passphrase { get; set; }
+
+        public string Name { get; set; }
+
+        public string UserEmail { get; set; }
+
+        public string EncryptedFileFullName { get; set; }
+
+        public PassphraseIdentity Identity { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/LogOnViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnViewModel.cs
new file mode 100644
index 0000000..3265f80
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/LogOnViewModel.cs
@@ -0,0 +1,125 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class LogOnViewModel : ViewModelBase
+    {
+        private string _encryptedFileFullName;
+
+        public LogOnViewModel(string encryptedFileFullName)
+        {
+            _encryptedFileFullName = encryptedFileFullName;
+            InitializePropertyValues();
+        }
+
+        private void InitializePropertyValues()
+        {
+            Passphrase = String.Empty;
+            FileName = String.IsNullOrEmpty(_encryptedFileFullName) ? String.Empty : Factory.New<IRuntimeFileInfo>(_encryptedFileFullName).Name;
+        }
+
+        public bool ShowPassphrase { get { return GetProperty<bool>("ShowPassphrase"); } set { SetProperty("ShowPassphrase", value); } }
+
+        public string Passphrase { get { return GetProperty<string>("Passphrase"); } set { SetProperty("Passphrase", value); } }
+
+        public string FileName { get { return GetProperty<string>("FileName"); } set { SetProperty("FileName", value); } }
+
+        public override string this[string columnName]
+        {
+            get
+            {
+                string error = base[columnName];
+                if (String.IsNullOrEmpty(error))
+                {
+                    error = Validate(columnName);
+                }
+
+                return error;
+            }
+        }
+
+        private string Validate(string columnName)
+        {
+            if (ValidateInternal(columnName))
+            {
+                return String.Empty;
+            }
+            return ValidationError.ToString(CultureInfo.InvariantCulture);
+        }
+
+        private bool ValidateInternal(string columnName)
+        {
+            switch (columnName)
+            {
+                case "Passphrase":
+                    if (!IsPassphraseValidForFileIfAny(Passphrase, _encryptedFileFullName))
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.WrongPassphrase;
+                        return false;
+                    }
+                    bool isKnownIdentity = IsKnownIdentity();
+                    if (String.IsNullOrEmpty(_encryptedFileFullName) && !isKnownIdentity)
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.WrongPassphrase;
+                        return false;
+                    }
+                    return true;
+
+                default:
+                    throw new ArgumentException("Cannot validate property.", columnName);
+            }
+        }
+
+        private static bool IsPassphraseValidForFileIfAny(string passphrase, string encryptedFileFullName)
+        {
+            if (String.IsNullOrEmpty(encryptedFileFullName))
+            {
+                return true;
+            }
+            return Factory.New<AxCryptFactory>().TryFindCryptoId(new Passphrase(passphrase), Factory.New<IRuntimeFileInfo>(encryptedFileFullName), Instance.CryptoFactory.OrderedIds) != Guid.Empty;
+        }
+
+        private bool IsKnownIdentity()
+        {
+            SymmetricKeyThumbprint thumbprint = new Passphrase(Passphrase).Thumbprint;
+            PassphraseIdentity identity = Instance.FileSystemState.Identities.FirstOrDefault(id => id.Thumbprint == thumbprint);
+            if (identity != null)
+            {
+                return true;
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/MainViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/MainViewModel.cs
new file mode 100644
index 0000000..28f69c3
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/MainViewModel.cs
@@ -0,0 +1,395 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class MainViewModel : ViewModelBase, IDisposable
+    {
+        private FileSystemState _fileSystemState;
+
+        private UpdateCheck _updateCheck;
+
+        public bool LoggedOn { get { return GetProperty<bool>("LoggedOn"); } set { SetProperty("LoggedOn", value); } }
+
+        public bool EncryptFileEnabled { get { return GetProperty<bool>("EncryptFileEnabled"); } set { SetProperty("EncryptFileEnabled", value); } }
+
+        public bool DecryptFileEnabled { get { return GetProperty<bool>("DecryptFileEnabled"); } set { SetProperty("DecryptFileEnabled", value); } }
+
+        public bool OpenEncryptedEnabled { get { return GetProperty<bool>("OpenEncryptedEnabled"); } set { SetProperty("OpenEncryptedEnabled", value); } }
+
+        public bool WatchedFoldersEnabled { get { return GetProperty<bool>("WatchedFoldersEnabled"); } set { SetProperty("WatchedFoldersEnabled", value); } }
+
+        public string Title { get { return GetProperty<string>("Title"); } set { SetProperty("Title", value); } }
+
+        public PassphraseIdentity Identity { get { return GetProperty<PassphraseIdentity>("Identity"); } set { SetProperty("Identity", value); } }
+
+        public IEnumerable<string> WatchedFolders { get { return GetProperty<IEnumerable<string>>("WatchedFolders"); } set { SetProperty("WatchedFolders", value.ToList()); } }
+
+        public IEnumerable<ActiveFile> RecentFiles { get { return GetProperty<IEnumerable<ActiveFile>>("RecentFiles"); } set { SetProperty("RecentFiles", value.ToList()); } }
+
+        public IEnumerable<ActiveFile> DecryptedFiles { get { return GetProperty<IEnumerable<ActiveFile>>("DecryptedFiles"); } set { SetProperty("DecryptedFiles", value.ToList()); } }
+
+        public ActiveFileComparer RecentFilesComparer { get { return GetProperty<ActiveFileComparer>("RecentFilesComparer"); } set { SetProperty("RecentFilesComparer", value); } }
+
+        public IEnumerable<string> SelectedWatchedFolders { get { return GetProperty<IEnumerable<string>>("SelectedWatchedFolders"); } set { SetProperty("SelectedWatchedFolders", value.ToList()); } }
+
+        public IEnumerable<string> SelectedRecentFiles { get { return GetProperty<IEnumerable<string>>("SelectedRecentFiles"); } set { SetProperty("SelectedRecentFiles", value.ToList()); } }
+
+        public IEnumerable<string> DragAndDropFiles { get { return GetProperty<IEnumerable<string>>("DragAndDropFiles"); } set { SetProperty("DragAndDropFiles", value.ToList()); } }
+
+        public FileInfoTypes DragAndDropFilesTypes { get { return GetProperty<FileInfoTypes>("DragAndDropFilesTypes"); } set { SetProperty("DragAndDropFilesTypes", value); } }
+
+        public bool DroppableAsRecent { get { return GetProperty<bool>("DroppableAsRecent"); } set { SetProperty("DroppableAsRecent", value); } }
+
+        public bool DroppableAsWatchedFolder { get { return GetProperty<bool>("DroppableAsWatchedFolder"); } set { SetProperty("DroppableAsWatchedFolder", value); } }
+
+        public bool FilesArePending { get { return GetProperty<bool>("FilesArePending"); } set { SetProperty("FilesArePending", value); } }
+
+        public Version CurrentVersion { get { return GetProperty<Version>("CurrentVersion"); } set { SetProperty("CurrentVersion", value); } }
+
+        public Version UpdatedVersion { get { return GetProperty<Version>("UpdatedVersion"); } set { SetProperty("UpdatedVersion", value); } }
+
+        public VersionUpdateStatus VersionUpdateStatus { get { return GetProperty<VersionUpdateStatus>("VersionUpdateStatus"); } set { SetProperty("VersionUpdateStatus", value); } }
+
+        public bool DebugMode { get { return GetProperty<bool>("DebugMode"); } set { SetProperty("DebugMode", value); } }
+
+        public bool Working { get { return GetProperty<bool>("Working"); } set { SetProperty("Working", value); } }
+
+        public IAction RemoveRecentFiles { get; private set; }
+
+        public IAction AddWatchedFolders { get; private set; }
+
+        public IAction EncryptPendingFiles { get; private set; }
+
+        public IAction ClearPassphraseMemory { get; private set; }
+
+        public IAction RemoveWatchedFolders { get; private set; }
+
+        public IAction OpenSelectedFolder { get; private set; }
+
+        public IAction UpdateCheck { get; private set; }
+
+        public MainViewModel(FileSystemState fileSystemState)
+        {
+            _fileSystemState = fileSystemState;
+
+            InitializePropertyValues();
+            BindPropertyChangedEvents();
+            SubscribeToModelEvents();
+        }
+
+        private void InitializePropertyValues()
+        {
+            WatchedFoldersEnabled = false;
+            WatchedFolders = new string[0];
+            DragAndDropFiles = new string[0];
+            RecentFiles = new ActiveFile[0];
+            SelectedRecentFiles = new string[0];
+            SelectedWatchedFolders = new string[0];
+            DebugMode = false;
+            Title = String.Empty;
+            VersionUpdateStatus = UI.VersionUpdateStatus.Unknown;
+
+            AddWatchedFolders = new DelegateAction<IEnumerable<string>>((folders) => AddWatchedFoldersAction(folders), (folders) => LoggedOn);
+            RemoveRecentFiles = new DelegateAction<IEnumerable<string>>((files) => RemoveRecentFilesAction(files));
+            EncryptPendingFiles = new DelegateAction<object>((parameter) => EncryptPendingFilesAction());
+            ClearPassphraseMemory = new DelegateAction<object>((parameter) => ClearPassphraseMemoryAction());
+            RemoveWatchedFolders = new DelegateAction<IEnumerable<string>>((folders) => RemoveWatchedFoldersAction(folders), (folders) => LoggedOn);
+            OpenSelectedFolder = new DelegateAction<string>((folder) => OpenSelectedFolderAction(folder));
+            UpdateCheck = new DelegateAction<DateTime>((utc) => UpdateCheckAction(utc), (utc) => _updateCheck != null);
+        }
+
+        private void BindPropertyChangedEvents()
+        {
+            BindPropertyChangedInternal("DragAndDropFiles", (IEnumerable<string> files) => { DragAndDropFilesTypes = DetermineFileTypes(files.Select(f => Factory.New<IRuntimeFileInfo>(f))); });
+            BindPropertyChangedInternal("DragAndDropFiles", (IEnumerable<string> files) => { DroppableAsRecent = DetermineDroppableAsRecent(files.Select(f => Factory.New<IRuntimeFileInfo>(f))); });
+            BindPropertyChangedInternal("DragAndDropFiles", (IEnumerable<string> files) => { DroppableAsWatchedFolder = DetermineDroppableAsWatchedFolder(files.Select(f => Factory.New<IRuntimeFileInfo>(f))); });
+            BindPropertyChangedInternal("CurrentVersion", (Version cv) => { if (cv != null) UpdateUpdateCheck(cv); });
+            BindPropertyChangedInternal("DebugMode", (bool enabled) => { UpdateDebugMode(enabled); });
+            BindPropertyChangedInternal("RecentFilesComparer", (ActiveFileComparer comparer) => { SetRecentFiles(); });
+        }
+
+        private void SubscribeToModelEvents()
+        {
+            Instance.SessionNotify.Notification += HandleSessionChanged;
+            Instance.ProgressBackground.WorkStatusChanged += (sender, e) =>
+                {
+                    Working = Instance.ProgressBackground.Busy;
+                };
+            _fileSystemState.ActiveFileChanged += HandleActiveFileChangedEvent;
+        }
+
+        private static void UpdateDebugMode(bool enabled)
+        {
+            Instance.Log.SetLevel(enabled ? LogLevel.Debug : LogLevel.Error);
+            OS.Current.DebugMode(enabled);
+        }
+
+        private void UpdateUpdateCheck(Version currentVersion)
+        {
+            DisposeUpdateCheck();
+            _updateCheck = Factory.New<Version, UpdateCheck>(currentVersion);
+            _updateCheck.VersionUpdate += Handle_VersionUpdate;
+            UpdateCheckAction(Instance.UserSettings.LastUpdateCheckUtc);
+        }
+
+        private void Handle_VersionUpdate(object sender, VersionEventArgs e)
+        {
+            Instance.UserSettings.LastUpdateCheckUtc = OS.Current.UtcNow;
+            Instance.UserSettings.NewestKnownVersion = e.Version.ToString();
+            Instance.UserSettings.UpdateUrl = e.UpdateWebpageUrl;
+
+            UpdatedVersion = e.Version;
+            VersionUpdateStatus = e.VersionUpdateStatus;
+        }
+
+        private void HandleActiveFileChangedEvent(object sender, ActiveFileChangedEventArgs e)
+        {
+            SetFilesArePending();
+            SetRecentFiles();
+        }
+
+        private static FileInfoTypes DetermineFileTypes(IEnumerable<IRuntimeFileInfo> files)
+        {
+            FileInfoTypes types = FileInfoTypes.None;
+            FileInfoTypes typesToLookFor = FileInfoTypes.EncryptedFile | FileInfoTypes.EncryptableFile;
+            foreach (IRuntimeFileInfo file in files)
+            {
+                types |= file.Type() & typesToLookFor;
+                if ((types & typesToLookFor) == typesToLookFor)
+                {
+                    return types;
+                }
+            }
+            return types;
+        }
+
+        private static bool DetermineDroppableAsRecent(IEnumerable<IRuntimeFileInfo> files)
+        {
+            return files.Any(fileInfo => fileInfo.Type() == FileInfoTypes.EncryptedFile || (Instance.KnownKeys.IsLoggedOn && fileInfo.Type() == FileInfoTypes.EncryptableFile));
+        }
+
+        private static bool DetermineDroppableAsWatchedFolder(IEnumerable<IRuntimeFileInfo> files)
+        {
+            if (files.Count() != 1)
+            {
+                return false;
+            }
+
+            IRuntimeFileInfo fileInfo = files.First();
+            if (!fileInfo.IsExistingFolder)
+            {
+                return false;
+            }
+
+            if (!fileInfo.NormalizeFolder().IsEncryptable())
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        private void HandleSessionChanged(object sender, SessionNotificationEventArgs e)
+        {
+            switch (e.Notification.NotificationType)
+            {
+                case SessionNotificationType.WatchedFolderAdded:
+                    SetWatchedFolders();
+                    break;
+
+                case SessionNotificationType.WatchedFolderRemoved:
+                    SetWatchedFolders();
+                    break;
+
+                case SessionNotificationType.LogOn:
+                    SetLogOnState(Instance.KnownKeys.IsLoggedOn);
+                    SetWatchedFolders();
+                    break;
+
+                case SessionNotificationType.LogOff:
+                    SetLogOnState(Instance.KnownKeys.IsLoggedOn);
+                    SetWatchedFolders();
+                    break;
+
+                case SessionNotificationType.WatchedFolderChange:
+                    SetFilesArePending();
+                    break;
+
+                case SessionNotificationType.WorkFolderChange:
+                case SessionNotificationType.ProcessExit:
+                case SessionNotificationType.SessionChange:
+                case SessionNotificationType.SessionStart:
+                case SessionNotificationType.KnownKeyChange:
+                case SessionNotificationType.ActiveFileChange:
+                default:
+                    break;
+            }
+        }
+
+        private void SetWatchedFolders()
+        {
+            WatchedFolders = Instance.KnownKeys.LoggedOnWatchedFolders.Select(wf => wf.Path).ToList();
+        }
+
+        private void SetRecentFiles()
+        {
+            List<ActiveFile> activeFiles = new List<ActiveFile>(_fileSystemState.ActiveFiles).Where(af => !af.Status.HasFlag(ActiveFileStatus.Inactive)).ToList();
+            if (RecentFilesComparer != null)
+            {
+                activeFiles.Sort(RecentFilesComparer);
+            }
+            RecentFiles = activeFiles;
+            DecryptedFiles = _fileSystemState.DecryptedActiveFiles;
+        }
+
+        private void SetFilesArePending()
+        {
+            IList<ActiveFile> openFiles = _fileSystemState.DecryptedActiveFiles;
+            FilesArePending = openFiles.Count > 0 || Instance.KnownKeys.LoggedOnWatchedFolders.SelectMany(wf => Factory.New<IRuntimeFileInfo>(wf.Path).ListEncryptable()).Any();
+        }
+
+        private void SetLogOnState(bool isLoggedOn)
+        {
+            PassphraseIdentity identity = null;
+            if (isLoggedOn)
+            {
+                identity = _fileSystemState.Identities.FirstOrDefault(i => i.Thumbprint == Instance.KnownKeys.DefaultEncryptionKey.Thumbprint);
+                if (identity == null)
+                {
+                    throw new InvalidOperationException("Attempt to log on without a matching identity being defined.");
+                }
+            }
+            Identity = identity;
+            LoggedOn = isLoggedOn;
+            EncryptFileEnabled = isLoggedOn;
+            DecryptFileEnabled = isLoggedOn;
+            OpenEncryptedEnabled = isLoggedOn;
+            WatchedFoldersEnabled = isLoggedOn;
+        }
+
+        private void ClearPassphraseMemoryAction()
+        {
+            IRuntimeFileInfo fileSystemStateInfo = Instance.FileSystemState.PathInfo;
+            Factory.New<AxCryptFile>().Wipe(fileSystemStateInfo, new ProgressContext());
+            Factory.Instance.Singleton<FileSystemState>(() => FileSystemState.Create(fileSystemStateInfo));
+            Factory.Instance.Singleton<KnownKeys>(() => new KnownKeys(_fileSystemState, Instance.SessionNotify));
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.SessionStart));
+        }
+
+        private static void EncryptPendingFilesAction()
+        {
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.EncryptPendingFiles));
+        }
+
+        private void RemoveRecentFilesAction(IEnumerable<string> files)
+        {
+            foreach (string file in files)
+            {
+                ActiveFile activeFile = _fileSystemState.FindActiveFileFromEncryptedPath(file);
+                if (activeFile != null && !activeFile.Status.HasFlag(ActiveFileStatus.Inactive))
+                {
+                    _fileSystemState.RemoveActiveFile(activeFile);
+                }
+            }
+            _fileSystemState.Save();
+        }
+
+        private void AddWatchedFoldersAction(IEnumerable<string> folders)
+        {
+            if (!folders.Any())
+            {
+                return;
+            }
+            foreach (string folder in folders)
+            {
+                _fileSystemState.AddWatchedFolder(new WatchedFolder(folder, Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+            }
+            _fileSystemState.Save();
+        }
+
+        private void RemoveWatchedFoldersAction(IEnumerable<string> folders)
+        {
+            if (!folders.Any())
+            {
+                return;
+            }
+            foreach (string watchedFolderPath in folders)
+            {
+                _fileSystemState.RemoveWatchedFolder(Factory.New<IRuntimeFileInfo>(watchedFolderPath));
+            }
+            _fileSystemState.Save();
+        }
+
+        private static void OpenSelectedFolderAction(string folder)
+        {
+            OS.Current.Launch(folder);
+        }
+
+        private void UpdateCheckAction(DateTime lastUpdateCheckUtc)
+        {
+            _updateCheck.CheckInBackground(lastUpdateCheckUtc, Instance.UserSettings.NewestKnownVersion, Instance.UserSettings.AxCrypt2VersionCheckUrl, Instance.UserSettings.UpdateUrl);
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            DisposeUpdateCheck();
+        }
+
+        private void DisposeUpdateCheck()
+        {
+            if (_updateCheck != null)
+            {
+                _updateCheck.VersionUpdate -= Handle_VersionUpdate;
+                _updateCheck.Dispose();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/NewPassphraseViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/NewPassphraseViewModel.cs
new file mode 100644
index 0000000..7765a34
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/NewPassphraseViewModel.cs
@@ -0,0 +1,124 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Globalization;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class NewPassphraseViewModel : ViewModelBase
+    {
+        private string _encryptedFileFullName;
+
+        public NewPassphraseViewModel(string passphrase, string encryptedFileFullName)
+        {
+            _encryptedFileFullName = encryptedFileFullName;
+            InitializePropertyValues(passphrase);
+        }
+
+        private void InitializePropertyValues(string passphrase)
+        {
+            Passphrase = passphrase ?? String.Empty;
+            Verification = passphrase ?? String.Empty;
+            FileName = String.IsNullOrEmpty(_encryptedFileFullName) ? String.Empty : Factory.New<IRuntimeFileInfo>(_encryptedFileFullName).Name;
+        }
+
+        public bool ShowPassphrase { get { return GetProperty<bool>("ShowPassphrase"); } set { SetProperty("ShowPassphrase", value); } }
+
+        public string Passphrase { get { return GetProperty<string>("Passphrase"); } set { SetProperty("Passphrase", value); } }
+
+        public string Verification { get { return GetProperty<string>("Verification"); } set { SetProperty("Verification", value); } }
+
+        public string FileName { get { return GetProperty<string>("FileName"); } set { SetProperty("FileName", value); } }
+
+        public override string this[string columnName]
+        {
+            get
+            {
+                string error = base[columnName];
+                if (String.IsNullOrEmpty(error))
+                {
+                    error = Validate(columnName);
+                }
+                return error;
+            }
+        }
+
+        private string Validate(string columnName)
+        {
+            if (ValidateInternal(columnName))
+            {
+                return String.Empty;
+            }
+            return ValidationError.ToString(CultureInfo.InvariantCulture);
+        }
+
+        private bool ValidateInternal(string columnName)
+        {
+            switch (columnName)
+            {
+                case "Passphrase":
+                    if (!IsPassphraseValidForFileIfAny(Passphrase, _encryptedFileFullName))
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.WrongPassphrase;
+                        return false;
+                    }
+                    break;
+
+                case "Verification":
+                    if (!ValidateVerification())
+                    {
+                        ValidationError = (int)ViewModel.ValidationError.VerificationPassphraseWrong;
+                        return false;
+                    }
+                    break;
+
+                default:
+                    throw new ArgumentException("Cannot validate property.", columnName);
+            }
+            return true;
+        }
+
+        private bool ValidateVerification()
+        {
+            return String.Compare(Passphrase, Verification, StringComparison.Ordinal) == 0;
+        }
+
+        private static bool IsPassphraseValidForFileIfAny(string passphrase, string encryptedFileFullName)
+        {
+            if (String.IsNullOrEmpty(encryptedFileFullName))
+            {
+                return true;
+            }
+            return Factory.New<AxCryptFactory>().TryFindCryptoId(new Passphrase(passphrase), Factory.New<IRuntimeFileInfo>(encryptedFileFullName), Instance.CryptoFactory.OrderedIds) != Guid.Empty;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/ValidationError.cs b/Axantum.AxCrypt.Core/UI/ViewModel/ValidationError.cs
new file mode 100644
index 0000000..435403e
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/ValidationError.cs
@@ -0,0 +1,41 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public enum ValidationError
+    {
+        None = 0,
+        VerificationPassphraseWrong,
+        IdentityExistsAlready,
+        WrongPassphrase,
+        InvalidEmail,
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/ViewModelBase.cs b/Axantum.AxCrypt.Core/UI/ViewModel/ViewModelBase.cs
new file mode 100644
index 0000000..87405c4
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/ViewModelBase.cs
@@ -0,0 +1,158 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class ViewModelBase : IViewModel
+    {
+        private Dictionary<string, List<Action<object>>> _actions = new Dictionary<string, List<Action<object>>>();
+
+        private Dictionary<string, object> _items = new Dictionary<string, object>();
+
+        public ViewModelBase()
+        {
+            PropertyChanged += HandlePropertyChanged;
+        }
+
+        public virtual int ValidationError { get { return GetProperty<int>("ValidationError"); } set { SetProperty("ValidationError", value); } }
+
+        private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
+        {
+            object value = GetProperty(sender, e.PropertyName);
+            List<Action<object>> actions;
+            if (!_actions.TryGetValue(e.PropertyName, out actions))
+            {
+                return;
+            }
+            foreach (Action<object> action in actions)
+            {
+                action(value);
+            }
+        }
+
+        protected void SetProperty<T>(string name, T value)
+        {
+            if (!HasValueChanged(GetProperty<T>(name), value))
+            {
+                return;
+            }
+            _items[name] = value;
+            OnPropertyChanged(new PropertyChangedEventArgs(name));
+        }
+
+        private static bool HasValueChanged<T>(object o, T value)
+        {
+            if (o == null)
+            {
+                return value != null;
+            }
+            T oldValue = (T)o;
+            return !oldValue.Equals(value);
+        }
+
+        public T GetProperty<T>(string name)
+        {
+            object value;
+            _items.TryGetValue(name, out value);
+            if (value == null)
+            {
+                return default(T);
+            }
+            return (T)value;
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
+        {
+            PropertyChangedEventHandler handler = PropertyChanged;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void BindPropertyChanged<T>(string name, Action<T> action)
+        {
+            Action<T> actionUi = (T arg) => Instance.UIThread.RunOnUIThread(() => action((T)arg));
+            BindPropertyChangedInternal<T>(name, actionUi);
+            actionUi(GetProperty<T>(name));
+        }
+
+        protected void BindPropertyChangedInternal<T>(string name, Action<T> action)
+        {
+            List<Action<object>> actions;
+            if (!_actions.TryGetValue(name, out actions))
+            {
+                actions = new List<Action<object>>();
+                _actions.Add(name, actions);
+            }
+            actions.Add(arg => action((T)arg));
+        }
+
+        private static object GetProperty(object me, string name)
+        {
+            PropertyInfo pi = me.GetType().GetProperty(name);
+            return pi.GetValue(me, null);
+        }
+
+        public string Error
+        {
+            get
+            {
+                IEnumerable<string> propertyNames = GetType().GetProperties().Select(pi => pi.Name);
+
+                return
+                    (from name in propertyNames
+                     let error = this[name]
+                     where !String.IsNullOrEmpty(error)
+                     select error)
+                        .Aggregate(new StringBuilder(), (acc, next) => acc.Append(acc.Length > 0 ? " " : String.Empty).Append(next))
+                        .ToString();
+            }
+        }
+
+        public virtual string this[string columnName]
+        {
+            get
+            {
+                if (GetType().GetProperty(columnName) == null)
+                {
+                    throw new ArgumentException("Non-existing property name.", columnName);
+                }
+                return String.Empty;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/UI/ViewModel/WatchedFoldersViewModel.cs b/Axantum.AxCrypt.Core/UI/ViewModel/WatchedFoldersViewModel.cs
new file mode 100644
index 0000000..0f3707c
--- /dev/null
+++ b/Axantum.AxCrypt.Core/UI/ViewModel/WatchedFoldersViewModel.cs
@@ -0,0 +1,148 @@
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Session;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Core.UI.ViewModel
+{
+    public class WatchedFoldersViewModel : ViewModelBase
+    {
+        private FileSystemState _fileSystemState;
+
+        public bool LoggedOn { get { return GetProperty<bool>("LoggedOn"); } set { SetProperty("LoggedOn", value); } }
+
+        public IEnumerable<string> WatchedFolders { get { return GetProperty<IEnumerable<string>>("WatchedFolders"); } set { SetProperty("WatchedFolders", value.ToList()); } }
+
+        public bool WatchedFoldersEnabled { get { return GetProperty<bool>("WatchedFoldersEnabled"); } set { SetProperty("WatchedFoldersEnabled", value); } }
+
+        public IEnumerable<string> SelectedWatchedFolders { get { return GetProperty<IEnumerable<string>>("SelectedWatchedFolders"); } set { SetProperty("SelectedWatchedFolders", value.ToList()); } }
+
+        public bool FilesArePending { get { return GetProperty<bool>("FilesArePending"); } set { SetProperty("FilesArePending", value); } }
+
+        public bool DroppableAsWatchedFolder { get { return GetProperty<bool>("DroppableAsWatchedFolder"); } set { SetProperty("DroppableAsWatchedFolder", value); } }
+
+        public IEnumerable<string> DragAndDropFiles { get { return GetProperty<IEnumerable<string>>("DragAndDropFiles"); } set { SetProperty("DragAndDropFiles", value.ToList()); } }
+
+        public IAction AddWatchedFolders { get; private set; }
+
+        public IAction RemoveWatchedFolders { get; private set; }
+
+        public IAction OpenSelectedFolder { get; private set; }
+
+        public WatchedFoldersViewModel(FileSystemState fileSystemState)
+        {
+            _fileSystemState = fileSystemState;
+
+            InitializePropertyValues();
+            BindPropertyChangedEvents();
+            SubscribeToModelEvents();
+            SetWatchedFolders();
+            SetLogOnState(Instance.KnownKeys.IsLoggedOn);
+        }
+
+        private void InitializePropertyValues()
+        {
+            WatchedFoldersEnabled = false;
+            WatchedFolders = new string[0];
+            DragAndDropFiles = new string[0];
+            SelectedWatchedFolders = new string[0];
+
+            AddWatchedFolders = new DelegateAction<IEnumerable<string>>((folders) => AddWatchedFoldersAction(folders), (folders) => LoggedOn);
+            RemoveWatchedFolders = new DelegateAction<IEnumerable<string>>((folders) => RemoveWatchedFoldersAction(folders), (folders) => LoggedOn);
+            OpenSelectedFolder = new DelegateAction<string>((folder) => OpenSelectedFolderAction(folder));
+        }
+
+        private void BindPropertyChangedEvents()
+        {
+            BindPropertyChanged("DragAndDropFiles", (IEnumerable<string> files) => { DroppableAsWatchedFolder = DetermineDroppableAsWatchedFolder(files.Select(f => Factory.New<IRuntimeFileInfo>(f))); });
+        }
+
+        private void SubscribeToModelEvents()
+        {
+            Instance.SessionNotify.Notification += HandleSessionChanged;
+        }
+
+        private static bool DetermineDroppableAsWatchedFolder(IEnumerable<IRuntimeFileInfo> files)
+        {
+            if (files.Count() != 1)
+            {
+                return false;
+            }
+
+            IRuntimeFileInfo fileInfo = files.First();
+            if (!fileInfo.IsExistingFolder)
+            {
+                return false;
+            }
+
+            if (!fileInfo.NormalizeFolder().IsEncryptable())
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        private void HandleSessionChanged(object sender, SessionNotificationEventArgs e)
+        {
+            switch (e.Notification.NotificationType)
+            {
+                case SessionNotificationType.WatchedFolderAdded:
+                case SessionNotificationType.WatchedFolderRemoved:
+                    SetWatchedFolders();
+                    break;
+
+                case SessionNotificationType.LogOn:
+                case SessionNotificationType.LogOff:
+                    SetLogOnState(Instance.KnownKeys.IsLoggedOn);
+                    SetWatchedFolders();
+                    break;
+            }
+        }
+
+        private void SetWatchedFolders()
+        {
+            WatchedFolders = Instance.KnownKeys.LoggedOnWatchedFolders.Select(wf => wf.Path).ToList();
+        }
+
+        private void SetLogOnState(bool isLoggedOn)
+        {
+            WatchedFoldersEnabled = isLoggedOn;
+            LoggedOn = isLoggedOn;
+        }
+
+        private void AddWatchedFoldersAction(IEnumerable<string> folders)
+        {
+            if (!folders.Any())
+            {
+                return;
+            }
+            foreach (string folder in folders)
+            {
+                _fileSystemState.AddWatchedFolder(new WatchedFolder(folder, Instance.KnownKeys.DefaultEncryptionKey.Thumbprint));
+            }
+            _fileSystemState.Save();
+        }
+
+        private void RemoveWatchedFoldersAction(IEnumerable<string> folders)
+        {
+            if (!folders.Any())
+            {
+                return;
+            }
+            foreach (string watchedFolderPath in folders)
+            {
+                _fileSystemState.RemoveWatchedFolder(Factory.New<IRuntimeFileInfo>(watchedFolderPath));
+            }
+            _fileSystemState.Save();
+        }
+
+        private static void OpenSelectedFolderAction(string folder)
+        {
+            OS.Current.Launch(folder);
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Core/V1AxCryptDocument.cs b/Axantum.AxCrypt.Core/V1AxCryptDocument.cs
new file mode 100644
index 0000000..ee479c0
--- /dev/null
+++ b/Axantum.AxCrypt.Core/V1AxCryptDocument.cs
@@ -0,0 +1,345 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Org.BouncyCastle.Utilities.Zlib;
+using System;
+using System.IO;
+
+namespace Axantum.AxCrypt.Core
+{
+    /// <summary>
+    /// Enables a single point of interaction for an AxCrypt encrypted stream with all but the data available
+    /// in-memory.
+    /// </summary>
+    public class V1AxCryptDocument : IAxCryptDocument
+    {
+        private AxCryptReader _reader;
+
+        private V1HmacStream _hmacStream;
+
+        private long _expectedTotalHmacLength = 0;
+
+        public ICryptoFactory CryptoFactory { get; private set; }
+
+        public V1AxCryptDocument()
+        {
+            CryptoFactory = new V1Aes128CryptoFactory();
+        }
+
+        public V1AxCryptDocument(Passphrase passphrase, long keyWrapIterations)
+            : this()
+        {
+            DocumentHeaders = new V1DocumentHeaders(passphrase, keyWrapIterations);
+        }
+
+        public V1DocumentHeaders DocumentHeaders { get; private set; }
+
+        public bool PassphraseIsValid { get; set; }
+
+        public bool Load(Passphrase key, Guid cryptoId, Stream inputStream)
+        {
+            Headers headers = new Headers();
+            AxCryptReader reader = headers.Load(inputStream);
+
+            return Load(key, reader, headers);
+        }
+
+        /// <summary>
+        /// Loads an AxCrypt file from the specified reader. After this, the reader is positioned to
+        /// read encrypted data.
+        /// </summary>
+        /// <param name="inputStream">The stream to read from. Will be disposed when this instance is disposed.</param>
+        /// <returns>True if the key was valid, false if it was wrong.</returns>
+        public bool Load(Passphrase key, AxCryptReader reader, Headers headers)
+        {
+            _reader = reader;
+            DocumentHeaders = new V1DocumentHeaders(key);
+            PassphraseIsValid = DocumentHeaders.Load(headers);
+            if (!PassphraseIsValid)
+            {
+                return false;
+            }
+
+            _hmacStream = new V1HmacStream(DocumentHeaders.HmacSubkey.Key);
+            foreach (HeaderBlock header in DocumentHeaders.Headers.HeaderBlocks)
+            {
+                if (header.HeaderBlockType != HeaderBlockType.Preamble)
+                {
+                    header.Write(_hmacStream);
+                }
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Encrypt a stream with a given set of headers and write to an output stream. The caller is responsible for consistency and completeness
+        /// of the headers. Headers that are not known until encryption and compression are added here.
+        /// </summary>
+        /// <param name="inputStream"></param>
+        /// <param name="outputStream"></param>
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
+        public void EncryptTo(Stream inputStream, Stream outputStream, AxCryptOptions options)
+        {
+            if (inputStream == null)
+            {
+                throw new ArgumentNullException("inputStream");
+            }
+            if (outputStream == null)
+            {
+                throw new ArgumentNullException("outputStream");
+            }
+            if (!outputStream.CanSeek)
+            {
+                throw new ArgumentException("The output stream must support seek in order to back-track and write the HMAC.");
+            }
+            if (options.HasMask(AxCryptOptions.EncryptWithCompression) && options.HasMask(AxCryptOptions.EncryptWithoutCompression))
+            {
+                throw new ArgumentException("Invalid options, cannot specify both with and without compression.");
+            }
+            if (!options.HasMask(AxCryptOptions.EncryptWithCompression) && !options.HasMask(AxCryptOptions.EncryptWithoutCompression))
+            {
+                throw new ArgumentException("Invalid options, must specify either with or without compression.");
+            }
+            bool isCompressed = options.HasMask(AxCryptOptions.EncryptWithCompression);
+            DocumentHeaders.IsCompressed = isCompressed;
+            DocumentHeaders.WriteWithoutHmac(outputStream);
+            using (ICryptoTransform encryptor = DataCrypto.CreateEncryptingTransform())
+            {
+                long outputStartPosition = outputStream.Position;
+                using (Stream encryptingStream = Instance.Portable.CryptoStream(new NonClosingStream(outputStream), encryptor, CryptoStreamMode.Write))
+                {
+                    if (isCompressed)
+                    {
+                        EncryptWithCompressionInternal(DocumentHeaders, inputStream, encryptingStream);
+                    }
+                    else
+                    {
+                        DocumentHeaders.PlaintextLength = StreamExtensions.CopyTo(inputStream, encryptingStream);
+                    }
+                }
+                outputStream.Flush();
+                DocumentHeaders.CipherTextLength = outputStream.Position - outputStartPosition;
+                using (V1HmacStream outputHmacStream = new V1HmacStream(DocumentHeaders.HmacSubkey.Key, outputStream))
+                {
+                    DocumentHeaders.WriteWithHmac(outputHmacStream);
+                    outputHmacStream.ReadFrom(outputStream);
+                    DocumentHeaders.Headers.Hmac = outputHmacStream.HmacResult;
+                }
+
+                // Rewind and rewrite the headers, now with the updated HMAC
+                DocumentHeaders.WriteWithoutHmac(outputStream);
+                outputStream.Position = outputStream.Length;
+            }
+        }
+
+        private static void EncryptWithCompressionInternal(V1DocumentHeaders outputDocumentHeaders, Stream inputStream, Stream encryptingStream)
+        {
+            using (ZOutputStream deflatingStream = new ZOutputStream(encryptingStream, -1))
+            {
+                deflatingStream.FlushMode = JZlib.Z_SYNC_FLUSH;
+                inputStream.CopyTo(deflatingStream);
+                deflatingStream.FlushMode = JZlib.Z_FINISH;
+                deflatingStream.Finish();
+
+                outputDocumentHeaders.UncompressedLength = deflatingStream.TotalIn;
+                outputDocumentHeaders.PlaintextLength = deflatingStream.TotalOut;
+            }
+        }
+
+        /// <summary>
+        /// Write a copy of the current encrypted stream. Used to change meta-data
+        /// and encryption key(s) etc.
+        /// </summary>
+        /// <param name="outputStream"></param>
+        public void CopyEncryptedTo(V1DocumentHeaders outputDocumentHeaders, Stream cipherStream)
+        {
+            if (outputDocumentHeaders == null)
+            {
+                throw new ArgumentNullException("outputDocumentHeaders");
+            }
+            if (cipherStream == null)
+            {
+                throw new ArgumentNullException("cipherStream");
+            }
+            if (!cipherStream.CanSeek)
+            {
+                throw new ArgumentException("The output stream must support seek in order to back-track and write the HMAC.");
+            }
+            if (!PassphraseIsValid)
+            {
+                throw new InternalErrorException("Passphrase is not valid.");
+            }
+
+            using (V1HmacStream hmacStreamOutput = new V1HmacStream(outputDocumentHeaders.HmacSubkey.Key, cipherStream))
+            {
+                outputDocumentHeaders.WriteWithHmac(hmacStreamOutput);
+                using (V1AxCryptDataStream encryptedDataStream = CreateEncryptedDataStream(_reader.InputStream, DocumentHeaders.CipherTextLength))
+                {
+                    encryptedDataStream.CopyTo(hmacStreamOutput);
+
+                    if (Hmac != DocumentHeaders.Headers.Hmac)
+                    {
+                        throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException("HMAC validation error in the input stream.", ErrorStatus.HmacValidationError);
+                    }
+                }
+
+                outputDocumentHeaders.Headers.Hmac = hmacStreamOutput.HmacResult;
+
+                // Rewind and rewrite the headers, now with the updated HMAC
+                outputDocumentHeaders.WriteWithoutHmac(cipherStream);
+                cipherStream.Position = cipherStream.Length;
+            }
+        }
+
+        private ICrypto _dataCrypto;
+
+        private ICrypto DataCrypto
+        {
+            get
+            {
+                _dataCrypto = Instance.CryptoFactory.Legacy.CreateCrypto(DocumentHeaders.DataSubkey.Key, DocumentHeaders.IV, 0);
+
+                return _dataCrypto;
+            }
+        }
+
+        /// <summary>
+        /// Decrypts the encrypted data to the given stream
+        /// </summary>
+        /// <param name="outputPlaintextStream">The resulting plain text stream.</param>
+        public void DecryptTo(Stream outputPlaintextStream)
+        {
+            if (!PassphraseIsValid)
+            {
+                throw new InternalErrorException("Passsphrase is not valid!");
+            }
+
+            using (ICryptoTransform decryptor = DataCrypto.CreateDecryptingTransform())
+            {
+                using (V1AxCryptDataStream encryptedDataStream = CreateEncryptedDataStream(_reader.InputStream, DocumentHeaders.CipherTextLength))
+                {
+                    encryptedDataStream.DecryptTo(outputPlaintextStream, decryptor, DocumentHeaders.IsCompressed);
+                }
+            }
+
+            if (Hmac != DocumentHeaders.Headers.Hmac)
+            {
+                throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException("HMAC validation error.", ErrorStatus.HmacValidationError);
+            }
+        }
+
+        private V1AxCryptDataStream CreateEncryptedDataStream(Stream inputStream, long cipherTextLength)
+        {
+            if (_reader.CurrentItemType != AxCryptItemType.Data)
+            {
+                throw new InvalidOperationException("GetEncryptedDataStream() was called when the reader is not positioned at the data.");
+            }
+
+            _reader.SetEndOfStream();
+
+            _expectedTotalHmacLength = _hmacStream.Position + cipherTextLength;
+
+            V1AxCryptDataStream encryptedDataStream = new V1AxCryptDataStream(inputStream, _hmacStream, cipherTextLength);
+            return encryptedDataStream;
+        }
+
+        private Hmac Hmac
+        {
+            get
+            {
+                if (_hmacStream.Length != _expectedTotalHmacLength)
+                {
+                    throw new InvalidOperationException("There is no valid HMAC until the encrypted data stream is read to end.");
+                }
+                return _hmacStream.HmacResult;
+            }
+        }
+
+        private bool _disposed = false;
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+
+            if (disposing)
+            {
+                if (_reader != null)
+                {
+                    _reader.Dispose();
+                    _reader = null;
+                }
+                if (_hmacStream != null)
+                {
+                    _hmacStream.Dispose();
+                    _hmacStream = null;
+                }
+            }
+
+            _disposed = true;
+        }
+
+        public string FileName
+        {
+            get { return DocumentHeaders.FileName; }
+            set { DocumentHeaders.FileName = value; }
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get { return DocumentHeaders.CreationTimeUtc; }
+            set { DocumentHeaders.CreationTimeUtc = value; }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get { return DocumentHeaders.LastAccessTimeUtc; }
+            set { DocumentHeaders.LastAccessTimeUtc = value; }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get { return DocumentHeaders.LastWriteTimeUtc; }
+            set { DocumentHeaders.LastWriteTimeUtc = value; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/V2AxCryptDocument.cs b/Axantum.AxCrypt.Core/V2AxCryptDocument.cs
new file mode 100644
index 0000000..cec90b7
--- /dev/null
+++ b/Axantum.AxCrypt.Core/V2AxCryptDocument.cs
@@ -0,0 +1,261 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Header;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Reader;
+using Axantum.AxCrypt.Core.Runtime;
+using Org.BouncyCastle.Utilities.Zlib;
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Core
+{
+    /// <summary>
+    /// Enables a single point of interaction for an AxCrypt File Format Version 4 encrypted stream with all but the data available
+    /// in-memory. File Format Version 4 is only supported by AxCrypt 2.x or higher. It builds on, and is similar to, File Format
+    /// Version 3. See the specification titled "AxCrypt Version 2 Algorithms and File Format" for details.
+    /// </summary>
+    public class V2AxCryptDocument : IAxCryptDocument
+    {
+        private long _plaintextLength;
+
+        private long _compressedPlaintextLength;
+
+        public V2AxCryptDocument()
+        {
+        }
+
+        public V2AxCryptDocument(Passphrase key, Guid cryptoId, long keyWrapIterations)
+        {
+            DocumentHeaders = new V2DocumentHeaders(key, cryptoId, keyWrapIterations);
+        }
+
+        public V2DocumentHeaders DocumentHeaders { get; private set; }
+
+        public ICryptoFactory CryptoFactory { get; private set; }
+
+        private AxCryptReader _reader;
+
+        public bool PassphraseIsValid { get; set; }
+
+        public bool Load(Passphrase key, Guid cryptoId, Stream inputStream)
+        {
+            Headers headers = new Headers();
+            AxCryptReader reader = headers.Load(inputStream);
+
+            return Load(key, cryptoId, reader, headers);
+        }
+
+        /// <summary>
+        /// Loads an AxCrypt file from the specified reader. After this, the reader is positioned to
+        /// read encrypted data.
+        /// </summary>
+        /// <param name="stream">The stream to read from. Will be disposed when this instance is disposed.</param>
+        /// <returns>True if the key was valid, false if it was wrong.</returns>
+        public bool Load(Passphrase passphrase, Guid cryptoId, AxCryptReader reader, Headers headers)
+        {
+            _reader = reader;
+            CryptoFactory = Instance.CryptoFactory.Create(cryptoId);
+            V2KeyWrapHeaderBlock keyWrap = headers.FindHeaderBlock<V2KeyWrapHeaderBlock>();
+            IDerivedKey key = CryptoFactory.RestoreDerivedKey(passphrase, keyWrap.DerivationSalt, keyWrap.DerivationIterations);
+            DocumentHeaders = new V2DocumentHeaders(key, cryptoId);
+            PassphraseIsValid = DocumentHeaders.Load(headers);
+            if (!PassphraseIsValid)
+            {
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Encrypt a stream with a given set of headers and write to an output stream. The caller is responsible for consistency and completeness
+        /// of the headers. Headers that are not known until encryption and compression are added here.
+        /// </summary>
+        /// <param name="outputDocumentHeaders"></param>
+        /// <param name="inputStream"></param>
+        /// <param name="outputStream"></param>
+        [SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")]
+        public void EncryptTo(Stream inputStream, Stream outputStream, AxCryptOptions options)
+        {
+            if (inputStream == null)
+            {
+                throw new ArgumentNullException("inputStream");
+            }
+            if (outputStream == null)
+            {
+                throw new ArgumentNullException("outputStream");
+            }
+            if (options.HasMask(AxCryptOptions.EncryptWithCompression) && options.HasMask(AxCryptOptions.EncryptWithoutCompression))
+            {
+                throw new ArgumentException("Invalid options, cannot specify both with and without compression.");
+            }
+            if (!options.HasMask(AxCryptOptions.EncryptWithCompression) && !options.HasMask(AxCryptOptions.EncryptWithoutCompression))
+            {
+                throw new ArgumentException("Invalid options, must specify either with or without compression.");
+            }
+            DocumentHeaders.IsCompressed = options.HasMask(AxCryptOptions.EncryptWithCompression);
+            using (V2HmacStream outputHmacStream = new V2HmacStream(DocumentHeaders.GetHmacKey(), outputStream))
+            {
+                DocumentHeaders.WriteStartWithHmac(outputHmacStream);
+                using (ICryptoTransform encryptor = DocumentHeaders.CreateDataCrypto().CreateEncryptingTransform())
+                {
+                    using (Stream axCryptDataStream = new V2AxCryptDataStream(outputHmacStream))
+                    {
+                        using (Stream encryptingStream = Instance.Portable.CryptoStream(new NonClosingStream(axCryptDataStream), encryptor, CryptoStreamMode.Write))
+                        {
+                            if (DocumentHeaders.IsCompressed)
+                            {
+                                EncryptWithCompressionInternal(inputStream, encryptingStream);
+                            }
+                            else
+                            {
+                                _compressedPlaintextLength = _plaintextLength = StreamExtensions.CopyTo(inputStream, encryptingStream);
+                            }
+                        }
+                    }
+                }
+                DocumentHeaders.WriteEndWithHmac(outputHmacStream, _plaintextLength, _compressedPlaintextLength);
+            }
+        }
+
+        private void EncryptWithCompressionInternal(Stream inputStream, Stream encryptingStream)
+        {
+            using (ZOutputStream deflatingStream = new ZOutputStream(encryptingStream, -1))
+            {
+                deflatingStream.FlushMode = JZlib.Z_SYNC_FLUSH;
+                inputStream.CopyTo(deflatingStream);
+                deflatingStream.FlushMode = JZlib.Z_FINISH;
+                deflatingStream.Finish();
+
+                _plaintextLength = deflatingStream.TotalIn;
+                _compressedPlaintextLength = deflatingStream.TotalOut;
+            }
+        }
+
+        /// <summary>
+        /// Decrypts the encrypted data to the given stream
+        /// </summary>
+        /// <param name="outputPlaintextStream">The resulting plain text stream.</param>
+        public void DecryptTo(Stream outputPlaintextStream)
+        {
+            if (outputPlaintextStream == null)
+            {
+                throw new ArgumentNullException("outputPlaintextStream");
+            }
+
+            if (!PassphraseIsValid)
+            {
+                throw new InternalErrorException("Passsphrase is not valid!");
+            }
+
+            using (ICryptoTransform decryptor = DocumentHeaders.CreateDataCrypto().CreateDecryptingTransform())
+            {
+                using (Stream encryptedDataStream = CreateEncryptedDataStream())
+                {
+                    encryptedDataStream.DecryptTo(outputPlaintextStream, decryptor, DocumentHeaders.IsCompressed);
+                }
+            }
+
+            DocumentHeaders.Trailers(_reader);
+            if (DocumentHeaders.HmacStream.Hmac != DocumentHeaders.Hmac)
+            {
+                throw new Axantum.AxCrypt.Core.Runtime.IncorrectDataException("HMAC validation error.", ErrorStatus.HmacValidationError);
+            }
+        }
+
+        private Stream CreateEncryptedDataStream()
+        {
+            if (_reader.CurrentItemType != AxCryptItemType.Data)
+            {
+                throw new InvalidOperationException("GetEncryptedDataStream() was called when the reader is not positioned at the data.");
+            }
+
+            _reader.SetStartOfData();
+            V2AxCryptDataStream encryptedDataStream = new V2AxCryptDataStream(_reader, DocumentHeaders.HmacStream);
+            return encryptedDataStream;
+        }
+
+        public string FileName
+        {
+            get { return DocumentHeaders.FileName; }
+            set { DocumentHeaders.FileName = value; }
+        }
+
+        public DateTime CreationTimeUtc
+        {
+            get { return DocumentHeaders.CreationTimeUtc; }
+            set { DocumentHeaders.CreationTimeUtc = value; }
+        }
+
+        public DateTime LastAccessTimeUtc
+        {
+            get { return DocumentHeaders.LastAccessTimeUtc; }
+            set { DocumentHeaders.LastAccessTimeUtc = value; }
+        }
+
+        public DateTime LastWriteTimeUtc
+        {
+            get { return DocumentHeaders.LastWriteTimeUtc; }
+            set { DocumentHeaders.LastWriteTimeUtc = value; }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_reader != null)
+            {
+                _reader.Dispose();
+                _reader = null;
+            }
+            if (DocumentHeaders != null)
+            {
+                DocumentHeaders.Dispose();
+                DocumentHeaders = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Core/resources/axcrypticon.ico b/Axantum.AxCrypt.Core/resources/axcrypticon.ico
new file mode 100644
index 0000000..f2e5c7f
Binary files /dev/null and b/Axantum.AxCrypt.Core/resources/axcrypticon.ico differ
diff --git a/Axantum.AxCrypt.Core/resources/bouncycastlelicense.txt b/Axantum.AxCrypt.Core/resources/bouncycastlelicense.txt
new file mode 100644
index 0000000..d12d021
--- /dev/null
+++ b/Axantum.AxCrypt.Core/resources/bouncycastlelicense.txt
@@ -0,0 +1,5 @@
+Copyright (c) 2000 - 2011 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
diff --git a/Axantum.AxCrypt.Core/resources/json.netlicense.txt b/Axantum.AxCrypt.Core/resources/json.netlicense.txt
new file mode 100644
index 0000000..f94610d
--- /dev/null
+++ b/Axantum.AxCrypt.Core/resources/json.netlicense.txt
@@ -0,0 +1,9 @@
+The MIT License (MIT)
+
+Copyright (c) 2007 James Newton-King
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Axantum.AxCrypt.Desktop.Test/Axantum.AxCrypt.Desktop.Test.csproj b/Axantum.AxCrypt.Desktop.Test/Axantum.AxCrypt.Desktop.Test.csproj
new file mode 100644
index 0000000..fd9d05c
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop.Test/Axantum.AxCrypt.Desktop.Test.csproj
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{79C1CBFF-B54E-43FC-A4CB-E6AF0AA1D0FF}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Desktop.Test</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Desktop.Test</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework">
+      <HintPath>..\SolutionItems\nunit.framework.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestFileWatcher.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966e9510-1a1d-46c7-97b5-460a0ff9b89f}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Desktop\Axantum.AxCrypt.Desktop.csproj">
+      <Project>{d64de570-3a36-49d3-95aa-9262647b04ee}</Project>
+      <Name>Axantum.AxCrypt.Desktop</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj">
+      <Project>{ce9e8614-8dc5-4757-9384-3c416ab61a47}</Project>
+      <Name>Axantum.AxCrypt.Mono</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Desktop.Test/AxantumStrongName.pfx b/Axantum.AxCrypt.Desktop.Test/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Desktop.Test/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Desktop.Test/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Desktop.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b5c51a4
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Axantum.AxCrypt.Desktop.Test")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Axantum.AxCrypt.Desktop.Test")]
+[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM components.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("8f52b780-48b7-445b-84cb-ce09c33bfe3a")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers 
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Axantum.AxCrypt.Desktop.Test/TestFileWatcher.cs b/Axantum.AxCrypt.Desktop.Test/TestFileWatcher.cs
new file mode 100644
index 0000000..281c922
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop.Test/TestFileWatcher.cs
@@ -0,0 +1,157 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Desktop.Test
+{
+    [TestFixture]
+    public static class TestFileWatcher
+    {
+        private static string _tempPath;
+
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+
+            _tempPath = Path.Combine(Path.GetTempPath(), @"Axantum.AxCrypt.Mono.Test.TestFileWatcher").NormalizeFolderPath();
+            Directory.CreateDirectory(_tempPath);
+
+            Factory.Instance.Register<string, IFileWatcher>((path) => new FileWatcher(path, new DelayedAction(new DelayTimer(), TimeSpan.FromMilliseconds(1))));
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new RuntimeFileInfo(path));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+            Factory.Instance.Singleton<ILogging>(() => new Logging());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+            Directory.Delete(_tempPath, true);
+        }
+
+        [Test]
+        public static void TestFileWatcherSimple()
+        {
+            bool wasHere = false;
+            using (IFileWatcher fileWatcher = Factory.New<IFileWatcher>(_tempPath))
+            {
+                fileWatcher.FileChanged += (object sender, FileWatcherEventArgs e) =>
+                {
+                    wasHere = true;
+                };
+                IRuntimeFileInfo tempFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(_tempPath, "AxCryptTestTemp.tmp"));
+                try
+                {
+                    using (Stream stream = tempFileInfo.OpenWrite())
+                    {
+                    }
+                    for (int i = 0; !wasHere && i < 20; ++i)
+                    {
+                        new Sleep().Time(new TimeSpan(0, 0, 0, 0, 100));
+                    }
+                    Assert.That(wasHere, "The FileWatcher should have noticed the creation of a file.");
+                }
+                finally
+                {
+                    wasHere = false;
+                    tempFileInfo.Delete();
+                }
+                for (int i = 0; !wasHere && i < 20; ++i)
+                {
+                    new Sleep().Time(new TimeSpan(0, 0, 0, 0, 100));
+                }
+                Assert.That(wasHere, "The FileWatcher should have noticed the deletion of a file.");
+            }
+        }
+
+        [Test]
+        public static void TestCreated()
+        {
+            using (IFileWatcher fileWatcher = Factory.New<IFileWatcher>(_tempPath))
+            {
+                string fileName = String.Empty;
+                fileWatcher.FileChanged += (object sender, FileWatcherEventArgs e) => { fileName = Path.GetFileName(e.FullName); };
+                using (Stream stream = File.Create(Path.Combine(_tempPath, "CreatedFile.txt")))
+                {
+                }
+                for (int i = 0; String.IsNullOrEmpty(fileName) && i < 20; ++i)
+                {
+                    new Sleep().Time(new TimeSpan(0, 0, 0, 0, 100));
+                }
+                Assert.That(fileName, Is.EqualTo("CreatedFile.txt"), "The watcher should detect the newly created file.");
+            }
+        }
+
+        [Test]
+        public static void TestMoved()
+        {
+            using (IFileWatcher fileWatcher = Factory.New<IFileWatcher>(_tempPath))
+            {
+                string fileName = String.Empty;
+                fileWatcher.FileChanged += (object sender, FileWatcherEventArgs e) => { fileName = Path.GetFileName(e.FullName); };
+                using (Stream stream = File.Create(Path.Combine(_tempPath, "NewFile.txt")))
+                {
+                }
+                for (int i = 0; String.IsNullOrEmpty(fileName) && i < 20; ++i)
+                {
+                    new Sleep().Time(new TimeSpan(0, 0, 0, 0, 100));
+                }
+                fileName = String.Empty;
+                File.Move(Path.Combine(_tempPath, "NewFile.txt"), Path.Combine(_tempPath, "MovedFile.txt"));
+                for (int i = 0; String.IsNullOrEmpty(fileName) && i < 20; ++i)
+                {
+                    new Sleep().Time(new TimeSpan(0, 0, 0, 0, 100));
+                }
+                Assert.That(fileName, Is.EqualTo("MovedFile.txt"), "The watcher should detect the newly created file.");
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestDoubleDispose()
+        {
+            Assert.DoesNotThrow(() =>
+            {
+                using (IFileWatcher fileWatcher = Factory.New<IFileWatcher>(_tempPath))
+                {
+                    fileWatcher.Dispose();
+                }
+            });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Desktop/Axantum.AxCrypt.Desktop.csproj b/Axantum.AxCrypt.Desktop/Axantum.AxCrypt.Desktop.csproj
new file mode 100644
index 0000000..6a75baa
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop/Axantum.AxCrypt.Desktop.csproj
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{D64DE570-3A36-49D3-95AA-9262647B04EE}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Desktop</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Desktop</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile />
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Microsoft.CSharp" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DesktopFactory.cs" />
+    <Compile Include="FileWatcher.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+    <None Include="Properties\AssemblyInfo.template" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966e9510-1a1d-46c7-97b5-460a0ff9b89f}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Desktop/AxantumStrongName.pfx b/Axantum.AxCrypt.Desktop/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Desktop/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Desktop/DesktopFactory.cs b/Axantum.AxCrypt.Desktop/DesktopFactory.cs
new file mode 100644
index 0000000..5d810ca
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop/DesktopFactory.cs
@@ -0,0 +1,19 @@
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Desktop
+{
+    public class DesktopFactory
+    {
+        public static void RegisterTypeFactories()
+        {
+            Factory.Instance.Register<string, IFileWatcher>((path) => new FileWatcher(path, new DelayedAction(Factory.New<IDelayTimer>(), Instance.UserSettings.SessionNotificationMinimumIdle)));
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Desktop/FileWatcher.cs b/Axantum.AxCrypt.Desktop/FileWatcher.cs
new file mode 100644
index 0000000..d4295fb
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop/FileWatcher.cs
@@ -0,0 +1,161 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Desktop
+{
+    public class FileWatcher : IFileWatcher
+    {
+        private IRuntimeFileInfo _fileInfo;
+
+        private FileSystemWatcher _fileSystemWatcher;
+
+        private DelayedAction _delayedAction;
+
+        private List<FileWatcherEventArgs> _notifications = new List<FileWatcherEventArgs>();
+
+        public FileWatcher(string path, DelayedAction delayedAction)
+        {
+            _delayedAction = delayedAction;
+            _delayedAction.Action += (sender, e) => { OnDelayedNotification(); };
+
+            _fileInfo = Factory.New<IRuntimeFileInfo>(path);
+            _fileSystemWatcher = new FileSystemWatcher(_fileInfo.FullName);
+            _fileSystemWatcher.Created += (sender, e) => FileSystemChanged(new FileWatcherEventArgs(e.FullPath));
+            _fileSystemWatcher.Deleted += (sender, e) => FileSystemChanged(new FileWatcherEventArgs(e.FullPath));
+            _fileSystemWatcher.Renamed += (sender, e) => FileSystemChanged(new FileWatcherEventArgs(e.OldFullPath, e.FullPath));
+            _fileSystemWatcher.Error += (sender, e) => FileSystemChanged(new FileWatcherEventArgs(_fileInfo.FullName));
+
+            _fileSystemWatcher.Filter = String.Empty;
+            _fileSystemWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime;
+            _fileSystemWatcher.EnableRaisingEvents = true;
+        }
+
+        public bool IncludeSubdirectories
+        {
+            get
+            {
+                return _fileSystemWatcher.IncludeSubdirectories;
+            }
+            set
+            {
+                _fileSystemWatcher.EnableRaisingEvents = false;
+                _fileSystemWatcher.IncludeSubdirectories = value;
+                _fileSystemWatcher.EnableRaisingEvents = true;
+            }
+        }
+
+        protected virtual void OnDelayedNotification()
+        {
+            List<FileWatcherEventArgs> notifications;
+            lock (_notifications)
+            {
+                if (!_notifications.Any())
+                {
+                    return;
+                }
+                notifications = new List<FileWatcherEventArgs>(_notifications);
+                _notifications.Clear();
+            }
+
+            foreach (FileWatcherEventArgs notification in notifications)
+            {
+                OnChanged(notification);
+            }
+        }
+
+        protected virtual void OnChanged(FileWatcherEventArgs eventArgs)
+        {
+            EventHandler<FileWatcherEventArgs> fileChanged = FileChanged;
+            if (fileChanged != null)
+            {
+                fileChanged(null, eventArgs);
+            }
+        }
+
+        private void FileSystemChanged(FileWatcherEventArgs e)
+        {
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Watcher says '{0}' changed.".InvariantFormat(e.FullName));
+            }
+            lock (_notifications)
+            {
+                _notifications.Add(e);
+            }
+            _delayedAction.StartIdleTimer();
+        }
+
+        #region IFileWatcher Members
+
+        public event EventHandler<FileWatcherEventArgs> FileChanged;
+
+        #endregion IFileWatcher Members
+
+        private bool _disposed = false;
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_disposed)
+            {
+                return;
+            }
+            if (disposing)
+            {
+                if (_fileSystemWatcher != null)
+                {
+                    _fileSystemWatcher.Dispose();
+                    _fileSystemWatcher = null;
+                }
+                if (_delayedAction != null)
+                {
+                    _delayedAction.Dispose();
+                    _delayedAction = null;
+                }
+            }
+            _disposed = true;
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..06b5b3f
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.cs
@@ -0,0 +1,76 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is strong named when deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Axantum.AxCrypt.Desktop")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © 2014 Svante Seleborg")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("3e0348ae-f5a7-4900-8897-ad1403a16dae")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+[assembly: InternalsVisibleTo("Axantum.AxCrypt.Desktop.Test")]
+#else
+[assembly: InternalsVisibleTo("Axantum.AxCrypt.Desktop.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f7cdec4989133e4654fa9741b22177f2404b463d1c821033dc73dfa47a5976e1cc69a8d78f4dd551bbf710e54300d7f035636a7502c1f88e0929596c848308e3250f927437f358d053d972744691c79ee6e4d3b151e63f56a331446a3097bf13e21f1feba2b84add6a05ebf2b3d9ca600d5ebf33d9c0ec3ae49956a9f3db3fc8")]
+#endif
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.template b/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.template
new file mode 100644
index 0000000..7d79c17
--- /dev/null
+++ b/Axantum.AxCrypt.Desktop/Properties/AssemblyInfo.template
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyFileVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyInformationalVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyConfiguration("")]
diff --git a/Axantum.AxCrypt.Forms/Axantum.AxCrypt.Forms.csproj b/Axantum.AxCrypt.Forms/Axantum.AxCrypt.Forms.csproj
new file mode 100644
index 0000000..668884d
--- /dev/null
+++ b/Axantum.AxCrypt.Forms/Axantum.AxCrypt.Forms.csproj
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{AC7C1ECD-4543-4CF3-8938-32F3D8CB89D5}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Forms</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Forms</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Security" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="DataProtection.cs" />
+    <Compile Include="ProgressBackground.cs">
+      <SubType>Component</SubType>
+    </Compile>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+    <None Include="Properties\AssemblyInfo.template" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966e9510-1a1d-46c7-97b5-460a0ff9b89f}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Forms/AxantumStrongName.pfx b/Axantum.AxCrypt.Forms/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Forms/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Forms/DataProtection.cs b/Axantum.AxCrypt.Forms/DataProtection.cs
new file mode 100644
index 0000000..b363c20
--- /dev/null
+++ b/Axantum.AxCrypt.Forms/DataProtection.cs
@@ -0,0 +1,54 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace Axantum.AxCrypt.Forms
+{
+    public class DataProtection : IDataProtection
+    {
+        #region IDataProtection Members
+
+        public byte[] Protect(byte[] unprotectedData)
+        {
+            return ProtectedData.Protect(unprotectedData, null, DataProtectionScope.CurrentUser);
+        }
+
+        public byte[] Unprotect(byte[] protectedData)
+        {
+            byte[] bytes = ProtectedData.Unprotect(protectedData, null, DataProtectionScope.CurrentUser);
+            return bytes;
+        }
+
+        #endregion IDataProtection Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Forms/ProgressBackground.cs b/Axantum.AxCrypt.Forms/ProgressBackground.cs
new file mode 100644
index 0000000..aedddb6
--- /dev/null
+++ b/Axantum.AxCrypt.Forms/ProgressBackground.cs
@@ -0,0 +1,195 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt.Forms
+{
+    /// <summary>
+    /// Background thread operations with progress bar support
+    /// </summary>
+    public class ProgressBackground : Component, IProgressBackground
+    {
+        private long _workerCount = 0;
+
+        public ProgressBackground(IContainer container)
+        {
+            container.Add(this);
+        }
+
+        /// <summary>
+        /// Raised when a new progress bar has been created. This is typically a good time
+        /// to add it to a container control. This is raised on the original thread, typically
+        /// the GUI thread.
+        /// </summary>
+        public event EventHandler<ControlEventArgs> ProgressBarCreated;
+
+        protected virtual void OnProgressBarCreated(ControlEventArgs e)
+        {
+            EventHandler<ControlEventArgs> handler = ProgressBarCreated;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when a progress bar is clicked. Use to display a context menu
+        /// or other information. This is raised on the original thread, typically the
+        /// GUI thread.
+        /// </summary>
+        public event EventHandler<MouseEventArgs> ProgressBarClicked;
+
+        protected virtual void OnProgressBarClicked(object sender, MouseEventArgs e)
+        {
+            EventHandler<MouseEventArgs> handler = ProgressBarClicked;
+            if (handler != null)
+            {
+                handler(sender, e);
+            }
+        }
+
+        /// <summary>
+        /// Perform a background operation with support for progress bars and cancel.
+        /// </summary>
+        /// <param name="workFunction">A 'work' delegate, taking a ProgressContext and return a FileOperationStatus. Executed on a background thread. Not the calling/GUI thread.</param>
+        /// <param name="complete">A 'complete' delegate, taking the final status. Executed on the GUI thread.</param>
+        public void Work(Func<IProgressContext, FileOperationContext> workFunction, Action<FileOperationContext> complete)
+        {
+            Instance.UIThread.RunOnUIThread(() =>
+            {
+                BackgroundWorkWithProgressOnUIThread(workFunction, complete);
+            });
+        }
+
+        private void BackgroundWorkWithProgressOnUIThread(Func<IProgressContext, FileOperationContext> work, Action<FileOperationContext> complete)
+        {
+            IProgressContext progress = new CancelProgressContext(new ProgressContext());
+            ProgressBar progressBar = CreateProgressBar(progress);
+            OnProgressBarCreated(new ControlEventArgs(progressBar));
+            progress.Progressing += (object sender, ProgressEventArgs e) =>
+            {
+                progressBar.Value = e.Percent;
+            };
+            IThreadWorker threadWorker = Instance.Portable.ThreadWorker(progress, false);
+            threadWorker.Work += (object sender, ThreadWorkerEventArgs e) =>
+            {
+                e.Result = work(e.Progress);
+            };
+            threadWorker.Completing += (object sender, ThreadWorkerEventArgs e) =>
+            {
+                try
+                {
+                    complete(e.Result);
+                    progressBar.Parent = null;
+                }
+                finally
+                {
+                    progressBar.Dispose();
+                }
+            };
+            threadWorker.Completed += (object sender, ThreadWorkerEventArgs e) =>
+            {
+                IDisposable disposable = sender as IDisposable;
+                if (disposable != null)
+                {
+                    disposable.Dispose();
+                }
+                Interlocked.Decrement(ref _workerCount);
+                OnWorkStatusChanged();
+            };
+            Interlocked.Increment(ref _workerCount);
+            OnWorkStatusChanged();
+            threadWorker.Run();
+        }
+
+        private ProgressBar CreateProgressBar(IProgressContext progress)
+        {
+            ProgressBar progressBar = new ProgressBar();
+            progressBar.Minimum = 0;
+            progressBar.Maximum = 100;
+            progressBar.Dock = DockStyle.Fill;
+            progressBar.Margin = new Padding(0);
+            progressBar.MouseClick += new MouseEventHandler(progressBar_MouseClick);
+            progressBar.Tag = progress;
+
+            return progressBar;
+        }
+
+        private void progressBar_MouseClick(object sender, MouseEventArgs e)
+        {
+            OnProgressBarClicked(sender, e);
+        }
+
+        /// <summary>
+        /// Wait for all operations to complete.
+        /// </summary>
+        public void WaitForIdle()
+        {
+            while (Interlocked.Read(ref _workerCount) > 0)
+            {
+                Application.DoEvents();
+            }
+        }
+
+        public event EventHandler WorkStatusChanged;
+
+        protected virtual void OnWorkStatusChanged()
+        {
+            EventHandler handler = WorkStatusChanged;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+
+        public bool Busy
+        {
+            get
+            {
+                return _workerCount > 0;
+            }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                WaitForIdle();
+            }
+
+            base.Dispose(disposing);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..080ce92
--- /dev/null
+++ b/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.cs
@@ -0,0 +1,72 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is strong named when deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AxCrypt Windows Forms Control Library")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © Svante Seleborg 2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("F35ED469-779F-427C-B8B7-E3A776BC48C1")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+#endif
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.template b/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.template
new file mode 100644
index 0000000..7d79c17
--- /dev/null
+++ b/Axantum.AxCrypt.Forms/Properties/AssemblyInfo.template
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyFileVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyInformationalVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyConfiguration("")]
diff --git a/Axantum.AxCrypt.Mac/AppController.cs b/Axantum.AxCrypt.Mac/AppController.cs
new file mode 100644
index 0000000..72988b3
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/AppController.cs
@@ -0,0 +1,228 @@
+using System;
+using MonoMac.AppKit;
+using MonoMac.Foundation;
+using Axantum.AxCrypt.Core.IO;
+using System.IO;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core;
+using System.Diagnostics;
+using System.Drawing;
+using System.Threading;
+using Axantum.AxCrypt.Mono;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mac.Views;
+using Axantum.AxCrypt.Mac.Windows;
+using Axantum.AxCrypt.Core.MacOsx;
+using Axantum.AxCrypt.Core.Session;
+
+namespace Axantum.AxCrypt.Mac
+{
+	public class AppController
+	{
+		public const string APP_NAME = "AxCrypt for Mac";
+		public const string VERSION = "2.0.2.1";
+		public const string PUBLISH_DATE = "May 2013";
+
+		private static AesKey lastUsedKey;
+		private static FileSystemState fileSystemState;
+
+		public static string FullApplicationName {
+			get {
+				return String.Concat(APP_NAME, ", version ", VERSION);
+			}
+		}
+
+		public static string VersionInformation {
+			get {
+				return String.Concat ("Version ", VERSION, "(", PUBLISH_DATE ,")");
+			}
+		}
+
+		public static string VersionInformationUrl {
+			get {
+				return String.Concat ("http://monodeveloper.org/axcrypt-osx-version-history/#v", VERSION.Replace ('.', '_'));
+			}
+		}
+
+		public static void Initialize()
+		{
+			fileSystemState = new FileSystemState ();
+			fileSystemState.Load (FileSystemState.DefaultPathInfo);
+			OS.Current.KeyWrapIterations = fileSystemState.KeyWrapIterations;
+			OS.Current.ThumbprintSalt = fileSystemState.ThumbprintSalt;
+			fileSystemState.KnownKeys.Changed += delegate { OS.Current.NotifyWorkFolderStateChanged(); };
+		}
+
+		public static void OperationFailureHandler (string message, ProgressContext context)
+		{
+			new NSObject().InvokeOnMainThread(() => {
+				NSAlert alert = NSAlert.WithMessage(message, "OK", null, null, "Check your password and try again");
+				alert.RunModal();
+			});
+		}
+
+		public static void OnlineHelp ()
+		{
+			Process.Start("http://www.axantum.com/AxCrypt/Default.html");
+		}
+
+		static IRuntimeFileInfo GetTargetFileName (string sourceFilePath, string encryptedFileName)
+		{
+			if (String.IsNullOrEmpty (encryptedFileName))
+				encryptedFileName = DateTime.Now.ToString ("yyyyMMddHHmmss");
+
+			if (!encryptedFileName.EndsWith(OS.Current.AxCryptExtension))
+				encryptedFileName += OS.Current.AxCryptExtension;
+
+			return OS.Current.FileInfo(Path.Combine(Path.GetDirectoryName(sourceFilePath), encryptedFileName));
+		}
+
+		public static void EncryptFile (ProgressContext progress, Action<string, ProgressContext> failure)
+		{
+			CreatePassphraseViewController passphraseController = new CreatePassphraseViewController {
+				EncryptedFileName = DateTime.Now.ToString("yyyyMMddHHmmss")
+			};
+
+			NSOpenPanel open = new NSOpenPanel {
+				AccessoryView = passphraseController.View,
+				AllowsMultipleSelection = false,
+				CanChooseDirectories = false,
+				CanChooseFiles = true,
+				CanSelectHiddenExtension = true,
+				CollectionBehavior = NSWindowCollectionBehavior.Transient,
+				ExtensionHidden = true,
+				Message = "Please select the file you would like to encrypt",
+				Prompt = "Encrypt file",
+				Title = "Encrypt",
+				TreatsFilePackagesAsDirectories = false,
+			};
+			
+			open.Begin(result => {
+				if (result == 0 || open.Urls.Length == 0) return;
+				if (!open.Urls[0].IsFileUrl) return;
+				string sourceFilePath = open.Urls[0].Path;
+				open.Close();
+
+				IRuntimeFileInfo sourceFile = OS.Current.FileInfo(sourceFilePath);
+				Passphrase passphrase = passphraseController.VerifiedPassphrase;
+				if (passphrase == null) return;
+
+				IRuntimeFileInfo targetFile = GetTargetFileName(sourceFilePath, passphraseController.EncryptedFileName);
+
+				ThreadPool.QueueUserWorkItem(delegate { 
+					using(new NSAutoreleasePool()) {
+						AxCryptFile.EncryptFileWithBackupAndWipe(sourceFile, targetFile, passphrase.DerivedPassphrase, progress);
+					};
+				});
+			});
+		}
+
+		private static void GetSourceFile (Action<IRuntimeFileInfo, Passphrase> fileSelected)
+		{
+			NSOpenPanel panel = NSOpenPanel.OpenPanel;
+			PasswordViewController passwordController = new PasswordViewController();
+			panel.AccessoryView = passwordController.View;
+
+			panel.Begin (result => {
+				if (result == 0 || panel.Urls.Length == 0) return;
+				if (!panel.Urls[0].IsFileUrl) return;
+				string filePath = panel.Urls[0].Path;
+				Passphrase generatedPassphrase = passwordController.Passphrase;
+				panel.Close();
+
+				ThreadPool.QueueUserWorkItem(delegate { 
+					using(new NSAutoreleasePool()) {
+						fileSelected(OS.Current.FileInfo(filePath), generatedPassphrase); 
+					};
+				});
+			});
+		}
+
+		static void GetTargetPath (Action<string> directorySelected)
+		{
+			NSOpenPanel panel = NSOpenPanel.OpenPanel;
+			panel.CanChooseFiles = false;
+			panel.CanChooseDirectories = true;
+
+			panel.Begin(result => {
+				if (result == 0 || panel.Urls.Length == 0) return;
+				if (!panel.Urls[0].IsFileUrl) return;
+				string filePath = panel.Urls[0].Path;
+				panel.Close();
+
+				directorySelected(filePath);
+			});
+		}
+
+		static bool TryDecrypt (IRuntimeFileInfo file, string filePath, AesKey key, ProgressContext progress, out string encryptedFileName)
+		{
+			encryptedFileName = AxCryptFile.Decrypt(file, filePath, key, AxCryptOptions.EncryptWithCompression, progress);
+			
+			if (encryptedFileName == null) {
+				return false;
+			}
+			return true;
+		}
+
+		public static void DecryptAndOpenFile (ProgressContext progress = null, Action<string, ProgressContext> failure = null)
+		{
+			GetSourceFile((encryptedDocument, passphrase) => {
+				DecryptAndOpenFile(encryptedDocument, passphrase, progress, failure);
+			});
+		}
+
+		public static void DecryptAndOpenFile(IRuntimeFileInfo encryptedDocument, Passphrase passphrase, ProgressContext progress, Action<string, ProgressContext> failure = null) {
+			string tempPath = Path.GetTempPath();
+			string decryptedFileName;
+			lastUsedKey = passphrase.DerivedPassphrase;
+
+			if (!TryDecrypt(encryptedDocument, tempPath, lastUsedKey, progress, out decryptedFileName)) {
+				failure("Could not open file", progress);
+				return;
+			}
+
+			string fullPathToDecryptedFile = Path.Combine(tempPath, decryptedFileName);
+			IRuntimeFileInfo decryptedFile = OS.Current.FileInfo(fullPathToDecryptedFile);
+
+			NSDictionary userInfo = new NSDictionary(Launcher.TargetFileUserInfoKey, decryptedFile.FullName);
+			NSNotification notification = NSNotification.FromName(Launcher.FileDecryptedNotification, new NSObject(), userInfo);
+			NSNotificationCenter.DefaultCenter.PostNotification(notification);
+
+			ILauncher launcher = OS.Current.Launch (fullPathToDecryptedFile);
+			launcher.Exited += (sender, e) => {
+				fileSystemState.CheckActiveFiles(ChangedEventMode.RaiseOnlyOnModified, new ProgressContext());
+			};
+
+			fileSystemState.Add (new ActiveFile(encryptedDocument, decryptedFile, lastUsedKey, ActiveFileStatus.AssumedOpenAndDecrypted, launcher));
+			//fileSystemState.Save ();
+		}
+
+		public static void DecryptFile(ProgressContext progress, Action<string, ProgressContext> failure) {
+			GetSourceFile((file, passphrase) => {
+
+				string targetDirectory = Path.GetDirectoryName(file.FullName);
+				string fileName;
+
+				if (!TryDecrypt(file, targetDirectory, passphrase.DerivedPassphrase, progress, out fileName)) {
+					failure("Decryption failed", progress);
+					return;
+				}
+			});
+		}
+
+		public static void About(object sender)
+		{
+			AboutWindowController controller = new AboutWindowController();
+			controller.ShowWindow((NSObject)sender);
+			controller.SetVersion(VERSION);
+		}
+
+		public static void ShowVersionInfo ()
+		{
+			VersionInformationWindowController versionInfo = new VersionInformationWindowController ();
+			versionInfo.ShowWindow (new NSObject());
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/AppDelegate.cs b/Axantum.AxCrypt.Mac/AppDelegate.cs
new file mode 100644
index 0000000..597955a
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/AppDelegate.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Drawing;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core;
+using System.IO;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.Runtime;
+using System.Diagnostics;
+using Axantum.AxCrypt.Mono;
+using Axantum.AxCrypt.Mac.Windows;
+
+namespace Axantum.AxCrypt.Mac
+{
+	public partial class AppDelegate : NSApplicationDelegate
+	{
+		NSWindowController mainWindowController;
+		OpenFileFromFinderController openFile;
+
+		public AppDelegate ()
+		{
+			OS.Current = new AxCrypt.Core.MacOsx.RuntimeEnvironment();
+
+			UpdateCheck updatecheck = new UpdateCheck(UpdateCheck.VersionUnknown);
+			Uri restApiUri = new Uri("https://www.axantum.com/Xecrets/RestApi.ashx/axcrypt2version/mac");
+			Uri versionUri = new Uri("http://www.axantum.com/");
+			string currentVersion = UpdateCheck.VersionUnknown.ToString();
+
+			updatecheck.VersionUpdate += (sender, versionArguments) => {
+				if (versionArguments.VersionUpdateStatus == VersionUpdateStatus.NewerVersionIsAvailable) {
+					int response = NSAlert.WithMessage("New version available!", "Update now", "Update later", null,
+					                    "A new version of Axantum AxCrypt for Mac is available! " +
+					                    "Would you like to download and install it now?")
+						.RunModal();
+
+					if (response == 1) {
+						Process.Start(versionArguments.UpdateWebpageUrl.AbsoluteUri);
+						NSApplication.SharedApplication.Terminate(this);
+					}
+				}
+			};
+
+			updatecheck.CheckInBackground(DateTime.UtcNow, currentVersion, restApiUri, versionUri);
+		}
+
+		public override void FinishedLaunching (NSObject notification)
+		{
+			AppController.Initialize ();
+			mainWindowController = new MainWindowController ();
+			mainWindowController.ShowWindow (this);
+			if (openFile != null)
+				mainWindowController.Window.Miniaturize (this);
+			else {
+				if (VersionInformationWindowController.ShouldShowVersionInformation) {
+					VersionInformationWindowController versionInfo = new VersionInformationWindowController ();
+					versionInfo.ShowWindow (this);
+				}
+			}
+		}
+
+		partial void about (NSObject sender)
+		{
+			AppController.About(sender);
+		}
+
+		partial void view (NSObject sender)
+		{
+			AppController.DecryptAndOpenFile(new ProgressContext(), AppController.OperationFailureHandler);
+		}
+
+		partial void onlineHelp (NSObject sender)
+		{
+			AppController.OnlineHelp();
+		}
+
+		partial void encrypt (NSObject sender)
+		{
+			AppController.EncryptFile(new ProgressContext(), AppController.OperationFailureHandler);
+		}
+
+		partial void decrypt (NSObject sender)
+		{
+			AppController.DecryptAndOpenFile(new ProgressContext(), AppController.OperationFailureHandler);
+		}
+
+		public override void OpenFiles (NSApplication sender, string[] filenames)
+		{
+			openFile = new OpenFileFromFinderController ();
+			openFile.UserChoseOpen += (string passphrase) => {
+				AppController.DecryptAndOpenFile(
+					OS.Current.FileInfo(filenames[0]),
+					new Passphrase(passphrase),
+					new ProgressContext(),
+					AppController.OperationFailureHandler);
+				ReleaseOpenFileController();
+			};
+			openFile.UserChoseCancel += () => {
+				ReleaseOpenFileController();
+			};
+			openFile.ShowWindow (sender);
+		}
+
+		void ReleaseOpenFileController ()
+		{
+			openFile.Close ();
+			openFile.Dispose ();
+			openFile = null;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Axantum.AxCrypt.Mac.csproj b/Axantum.AxCrypt.Mac/Axantum.AxCrypt.Mac.csproj
new file mode 100644
index 0000000..02e6f76
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Axantum.AxCrypt.Mac.csproj
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0E46C5F6-8B43-4571-AE55-6A65C0B87525}</ProjectGuid>
+    <ProjectTypeGuids>{948B3504-5B70-4649-8FE4-BDE1FB46EC69};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Axantum.AxCrypt.Mac</RootNamespace>
+    <MonoMacResourcePrefix>Resources</MonoMacResourcePrefix>
+    <ReleaseVersion>2.0.1.0</ReleaseVersion>
+    <SynchReleaseVersion>False</SynchReleaseVersion>
+    <AssemblyName>Axantum.AxCrypt.Mac</AssemblyName>
+    <SuppressXamMacUpsell>True</SuppressXamMacUpsell>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\x86\Debug</OutputPath>
+    <WarningLevel>4</WarningLevel>
+    <IncludeMonoRuntime>False</IncludeMonoRuntime>
+    <PlatformTarget>x86</PlatformTarget>
+    <EnableCodeSigning>False</EnableCodeSigning>
+    <EnablePackageSigning>False</EnablePackageSigning>
+    <CreatePackage>False</CreatePackage>
+    <CodeSigningKey>Mac Developer</CodeSigningKey>
+    <PackageSigningKey>3rd Party Mac Developer Installer</PackageSigningKey>
+    <DebugSymbols>True</DebugSymbols>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <UseSGen>false</UseSGen>
+    <I18n />
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\x86\Release</OutputPath>
+    <WarningLevel>4</WarningLevel>
+    <IncludeMonoRuntime>False</IncludeMonoRuntime>
+    <PlatformTarget>x86</PlatformTarget>
+    <EnableCodeSigning>False</EnableCodeSigning>
+    <EnablePackageSigning>False</EnablePackageSigning>
+    <CreatePackage>False</CreatePackage>
+    <DefineConstants>TRACE</DefineConstants>
+    <CodeSigningKey>Mac Developer</CodeSigningKey>
+    <PackageSigningKey>3rd Party Mac Developer Installer</PackageSigningKey>
+    <I18n>west</I18n>
+    <LinkMode>Full</LinkMode>
+    <UseSGen>false</UseSGen>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|x86' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\x86\AppStore</OutputPath>
+    <WarningLevel>4</WarningLevel>
+    <IncludeMonoRuntime>False</IncludeMonoRuntime>
+    <PlatformTarget>x86</PlatformTarget>
+    <EnableCodeSigning>False</EnableCodeSigning>
+    <EnablePackageSigning>False</EnablePackageSigning>
+    <CreatePackage>False</CreatePackage>
+    <DefineConstants>TRACE</DefineConstants>
+    <UseSGen>false</UseSGen>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="MonoMac" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="AppDelegate.cs" />
+    <Compile Include="MainMenu.xib.designer.cs">
+      <DependentUpon>MainMenu.xib</DependentUpon>
+    </Compile>
+    <Compile Include="AppController.cs" />
+    <Compile Include="Views\CreatePassphraseView.cs" />
+    <Compile Include="Views\CreatePassphraseView.designer.cs">
+      <DependentUpon>CreatePassphraseView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Views\PasswordView.cs" />
+    <Compile Include="Views\PasswordView.designer.cs">
+      <DependentUpon>PasswordView.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\AboutWindow.cs" />
+    <Compile Include="Windows\AboutWindow.designer.cs">
+      <DependentUpon>AboutWindow.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\MainWindow.cs" />
+    <Compile Include="Windows\MainWindow.designer.cs">
+      <DependentUpon>MainWindow.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\OpenFileFromFinder.cs" />
+    <Compile Include="Windows\OpenFileFromFinderController.cs" />
+    <Compile Include="Windows\OpenFileFromFinder.designer.cs">
+      <DependentUpon>OpenFileFromFinder.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Windows\MainWindowController.cs" />
+    <Compile Include="Views\PasswordViewController.cs" />
+    <Compile Include="Views\CreatePassphraseViewController.cs" />
+    <Compile Include="Windows\AboutWindowController.cs" />
+    <Compile Include="Windows\VersionInformationWindow.cs" />
+    <Compile Include="Windows\VersionInformationWindowController.cs" />
+    <Compile Include="Windows\VersionInformationWindow.designer.cs">
+      <DependentUpon>VersionInformationWindow.cs</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <InterfaceDefinition Include="MainMenu.xib" />
+    <InterfaceDefinition Include="Views\CreatePassphraseView.xib" />
+    <InterfaceDefinition Include="Views\PasswordView.xib" />
+    <InterfaceDefinition Include="Windows\AboutWindow.xib" />
+    <InterfaceDefinition Include="Windows\MainWindow.xib" />
+    <InterfaceDefinition Include="Windows\OpenFileFromFinder.xib" />
+    <InterfaceDefinition Include="Windows\VersionInformationWindow.xib" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <Import Project="$(MSBuildExtensionsPath)\Mono\MonoMac\v0.0\Mono.MonoMac.targets" />
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj">
+      <Project>{CE9E8614-8DC5-4757-9384-3C416AB61A47}</Project>
+      <Name>Axantum.AxCrypt.Mono</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core.MacOsx\Axantum.AxCrypt.Core.MacOsx.csproj">
+      <Project>{815C4EC9-5A6D-4548-89B3-046A21B20BB9}</Project>
+      <Name>Axantum.AxCrypt.Core.MacOsx</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Views\" />
+    <Folder Include="Windows\" />
+  </ItemGroup>
+  <ItemGroup>
+    <BundleResource Include="Resources\logo_axantum.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </BundleResource>
+    <BundleResource Include="Resources\AxCryptIcon128.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </BundleResource>
+    <BundleResource Include="Resources\tretton37.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </BundleResource>
+    <BundleResource Include="Resources\AxCryptIcon128.icns">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </BundleResource>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mac/Info.plist b/Axantum.AxCrypt.Mac/Info.plist
new file mode 100644
index 0000000..563a1cf
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Info.plist
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeExtensions</key>
+			<array>
+				<string>axx</string>
+			</array>
+			<key>CFBundleTypeIconFile</key>
+			<string>AxCryptIcon128</string>
+			<key>CFBundleTypeName</key>
+			<string>AxCrypt Document</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>com.tretton37.axantum.axcrypt-document</string>
+			</array>
+			<key>CFBundleTypeRole</key>
+			<string>Editor</string>
+			<key>CFBundleTypeMIMETypes</key>
+			<array>
+				<string>application/axcrypt-document</string>
+			</array>
+		</dict>
+	</array>
+	<key>CFBundleIconFile</key>
+	<string>AxCryptIcon128</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>AxCryptIcon128.icns</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>com.tretton37.Axantum.AxCrypt.Mac</string>
+	<key>CFBundleName</key>
+	<string>AxCrypt</string>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+	<key>CFBundleShortVersionString</key>
+	<string>2.0</string>
+	<key>CFBundleURLTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleURLName</key>
+			<string></string>
+		</dict>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>LSApplicationCategoryType</key>
+	<string>public.app-category.productivity</string>
+	<key>LSMinimumSystemVersion</key>
+	<string>10.6</string>
+	<key>NSMainNibFile</key>
+	<string>MainMenu</string>
+	<key>NSPrincipalClass</key>
+	<string>NSApplication</string>
+	<key>UTExportedTypeDeclarations</key>
+	<array>
+		<dict>
+			<key>UTTypeIconFile</key>
+			<string>AxCryptIcon128</string>
+			<key>UTTypeDescription</key>
+			<string>AxCrypt Document</string>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<array>
+					<string>axx</string>
+				</array>
+				<key>public.mime-type</key>
+				<array>
+					<string>application/axcrypt-document</string>
+				</array>
+			</dict>
+			<key>UTTypeIdentifier</key>
+			<string>com.tretton37.axantum.axcrypt-document</string>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.data</string>
+			</array>
+			<key>UTTypeReferenceURL</key>
+			<string>http://www.axantum.com/</string>
+		</dict>
+	</array>
+</dict>
+</plist>
diff --git a/Axantum.AxCrypt.Mac/Main.cs b/Axantum.AxCrypt.Mac/Main.cs
new file mode 100644
index 0000000..6adc123
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Main.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Drawing;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using MonoMac.ObjCRuntime;
+
+namespace Axantum.AxCrypt.Mac
+{
+	class MainClass
+	{
+		static void Main (string[] args)
+		{
+			NSApplication.Init ();
+			NSApplication.Main (args);
+		}
+	}
+}	
+
diff --git a/Axantum.AxCrypt.Mac/MainMenu.xib b/Axantum.AxCrypt.Mac/MainMenu.xib
new file mode 100644
index 0000000..70cc040
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/MainMenu.xib
@@ -0,0 +1,757 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12C54</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2840</string>
+		<string key="IBDocument.AppKitVersion">1187.34</string>
+		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">2840</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSCustomObject</string>
+			<string>NSMenu</string>
+			<string>NSMenuItem</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1048">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1021">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomObject" id="1014">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1050">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSMenu" id="649796088">
+				<string key="NSTitle">AMainMenu</string>
+				<object class="NSMutableArray" key="NSMenuItems">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSMenuItem" id="694149608">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">AxCrypt</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<object class="NSCustomResource" key="NSOnImage" id="35465992">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuCheckmark</string>
+						</object>
+						<object class="NSCustomResource" key="NSMixedImage" id="502551668">
+							<string key="NSClassName">NSImage</string>
+							<string key="NSResourceName">NSMenuMixedState</string>
+						</object>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="110575045">
+							<string key="NSTitle">AxCrypt</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="238522557">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">About</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="481834944">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="1046388886">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Services</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+									<string key="NSAction">submenuAction:</string>
+									<object class="NSMenu" key="NSSubmenu" id="752062318">
+										<string key="NSTitle">Services</string>
+										<object class="NSMutableArray" key="NSMenuItems">
+											<bool key="EncodedWithXMLCoder">YES</bool>
+										</object>
+										<string key="NSName">_NSServicesMenu</string>
+									</object>
+								</object>
+								<object class="NSMenuItem" id="646227648">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="755159360">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide AxCrypt</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="342932134">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Hide Others</string>
+									<string key="NSKeyEquiv">h</string>
+									<int key="NSKeyEquivModMask">1572864</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="908899353">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Show All</string>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="1056857174">
+									<reference key="NSMenu" ref="110575045"/>
+									<bool key="NSIsDisabled">YES</bool>
+									<bool key="NSIsSeparator">YES</bool>
+									<string key="NSTitle"/>
+									<string key="NSKeyEquiv"/>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="632727374">
+									<reference key="NSMenu" ref="110575045"/>
+									<string key="NSTitle">Quit AxCrypt</string>
+									<string key="NSKeyEquiv">q</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+							</object>
+							<string key="NSName">_NSAppleMenu</string>
+						</object>
+						<object class="NSAttributedString" key="NSAttributedTitle">
+							<string key="NSString"/>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="379814623">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">File</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="720053764">
+							<string key="NSTitle">File</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="686298756">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Open</string>
+									<string key="NSKeyEquiv">o</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="678538000">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Encrypt</string>
+									<string key="NSKeyEquiv">e</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+								<object class="NSMenuItem" id="255345490">
+									<reference key="NSMenu" ref="720053764"/>
+									<string key="NSTitle">Decrypt</string>
+									<string key="NSKeyEquiv">d</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+							</object>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="713487014">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Window</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSKeyEquivModMask">1048576</int>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="835318025">
+							<string key="NSTitle">Window</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="1011231497">
+									<reference key="NSMenu" ref="835318025"/>
+									<string key="NSTitle">Minimize</string>
+									<string key="NSKeyEquiv">m</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+							</object>
+							<string key="NSName">_NSWindowsMenu</string>
+						</object>
+					</object>
+					<object class="NSMenuItem" id="448692316">
+						<reference key="NSMenu" ref="649796088"/>
+						<string key="NSTitle">Help</string>
+						<string key="NSKeyEquiv"/>
+						<int key="NSMnemonicLoc">2147483647</int>
+						<reference key="NSOnImage" ref="35465992"/>
+						<reference key="NSMixedImage" ref="502551668"/>
+						<string key="NSAction">submenuAction:</string>
+						<object class="NSMenu" key="NSSubmenu" id="992780483">
+							<string key="NSTitle">Help</string>
+							<object class="NSMutableArray" key="NSMenuItems">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSMenuItem" id="105068016">
+									<reference key="NSMenu" ref="992780483"/>
+									<string key="NSTitle">AxCrypt Online Help</string>
+									<string key="NSKeyEquiv">?</string>
+									<int key="NSKeyEquivModMask">1048576</int>
+									<int key="NSMnemonicLoc">2147483647</int>
+									<reference key="NSOnImage" ref="35465992"/>
+									<reference key="NSMixedImage" ref="502551668"/>
+								</object>
+							</object>
+							<string key="NSName">_NSHelpMenu</string>
+						</object>
+					</object>
+				</object>
+				<string key="NSName">_NSMainMenu</string>
+			</object>
+			<object class="NSCustomObject" id="755631768">
+				<string key="NSClassName">NSFontManager</string>
+			</object>
+			<object class="NSCustomObject" id="947627720">
+				<string key="NSClassName">AppDelegate</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">terminate:</string>
+						<reference key="source" ref="1050"/>
+						<reference key="destination" ref="632727374"/>
+					</object>
+					<int key="connectionID">449</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">delegate</string>
+						<reference key="source" ref="1021"/>
+						<reference key="destination" ref="947627720"/>
+					</object>
+					<int key="connectionID">534</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">performMiniaturize:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="1011231497"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hide:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="755159360"/>
+					</object>
+					<int key="connectionID">367</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">hideOtherApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="342932134"/>
+					</object>
+					<int key="connectionID">368</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">unhideAllApplications:</string>
+						<reference key="source" ref="1014"/>
+						<reference key="destination" ref="908899353"/>
+					</object>
+					<int key="connectionID">370</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">encryptSelected</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="678538000"/>
+					</object>
+					<int key="connectionID">547</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">encrypt:</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="678538000"/>
+					</object>
+					<int key="connectionID">548</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">decrypt:</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="255345490"/>
+					</object>
+					<int key="connectionID">549</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">onlineHelpClicked</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="105068016"/>
+					</object>
+					<int key="connectionID">550</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">view:</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="686298756"/>
+					</object>
+					<int key="connectionID">552</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">onlineHelp:</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="105068016"/>
+					</object>
+					<int key="connectionID">553</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">about:</string>
+						<reference key="source" ref="947627720"/>
+						<reference key="destination" ref="238522557"/>
+					</object>
+					<int key="connectionID">554</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1048"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1021"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1014"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1050"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="649796088"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="379814623"/>
+							<reference ref="713487014"/>
+							<reference ref="694149608"/>
+							<reference ref="448692316"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="713487014"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="835318025"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">56</int>
+						<reference key="object" ref="694149608"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="110575045"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">83</int>
+						<reference key="object" ref="379814623"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="720053764"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">81</int>
+						<reference key="object" ref="720053764"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="678538000"/>
+							<reference ref="255345490"/>
+							<reference ref="686298756"/>
+						</object>
+						<reference key="parent" ref="379814623"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">57</int>
+						<reference key="object" ref="110575045"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="238522557"/>
+							<reference ref="755159360"/>
+							<reference ref="908899353"/>
+							<reference ref="632727374"/>
+							<reference ref="646227648"/>
+							<reference ref="481834944"/>
+							<reference ref="1046388886"/>
+							<reference ref="1056857174"/>
+							<reference ref="342932134"/>
+						</object>
+						<reference key="parent" ref="694149608"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">58</int>
+						<reference key="object" ref="238522557"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">134</int>
+						<reference key="object" ref="755159360"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">150</int>
+						<reference key="object" ref="908899353"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">136</int>
+						<reference key="object" ref="632727374"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">144</int>
+						<reference key="object" ref="646227648"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">143</int>
+						<reference key="object" ref="481834944"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">131</int>
+						<reference key="object" ref="1046388886"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="752062318"/>
+						</object>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">149</int>
+						<reference key="object" ref="1056857174"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">145</int>
+						<reference key="object" ref="342932134"/>
+						<reference key="parent" ref="110575045"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">130</int>
+						<reference key="object" ref="752062318"/>
+						<reference key="parent" ref="1046388886"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="835318025"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1011231497"/>
+						</object>
+						<reference key="parent" ref="713487014"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="1011231497"/>
+						<reference key="parent" ref="835318025"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">420</int>
+						<reference key="object" ref="755631768"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">490</int>
+						<reference key="object" ref="448692316"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="992780483"/>
+						</object>
+						<reference key="parent" ref="649796088"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">491</int>
+						<reference key="object" ref="992780483"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="105068016"/>
+						</object>
+						<reference key="parent" ref="448692316"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">492</int>
+						<reference key="object" ref="105068016"/>
+						<reference key="parent" ref="992780483"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">533</int>
+						<reference key="object" ref="947627720"/>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">535</int>
+						<reference key="object" ref="678538000"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">536</int>
+						<reference key="object" ref="255345490"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">551</int>
+						<reference key="object" ref="686298756"/>
+						<reference key="parent" ref="720053764"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>130.IBPluginDependency</string>
+					<string>131.IBPluginDependency</string>
+					<string>134.IBPluginDependency</string>
+					<string>136.IBPluginDependency</string>
+					<string>143.IBPluginDependency</string>
+					<string>144.IBPluginDependency</string>
+					<string>145.IBPluginDependency</string>
+					<string>149.IBPluginDependency</string>
+					<string>150.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>420.IBPluginDependency</string>
+					<string>490.IBPluginDependency</string>
+					<string>491.IBPluginDependency</string>
+					<string>492.IBPluginDependency</string>
+					<string>533.IBPluginDependency</string>
+					<string>535.IBPluginDependency</string>
+					<string>536.IBPluginDependency</string>
+					<string>551.IBPluginDependency</string>
+					<string>56.IBPluginDependency</string>
+					<string>57.IBPluginDependency</string>
+					<string>58.IBPluginDependency</string>
+					<string>81.IBPluginDependency</string>
+					<string>83.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">554</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">AppDelegate</string>
+					<string key="superclassName">NSObject</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>about:</string>
+							<string>decrypt:</string>
+							<string>encrypt:</string>
+							<string>onlineHelp:</string>
+							<string>view:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>about:</string>
+							<string>decrypt:</string>
+							<string>encrypt:</string>
+							<string>onlineHelp:</string>
+							<string>view:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBActionInfo">
+								<string key="name">about:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">decrypt:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">encrypt:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">onlineHelp:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">view:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/AppDelegate.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>NSMenuCheckmark</string>
+				<string>NSMenuMixedState</string>
+			</object>
+			<object class="NSArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>{11, 11}</string>
+				<string>{10, 3}</string>
+			</object>
+		</object>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/MainMenu.xib.designer.cs b/Axantum.AxCrypt.Mac/MainMenu.xib.designer.cs
new file mode 100644
index 0000000..bfd8f54
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/MainMenu.xib.designer.cs
@@ -0,0 +1,33 @@
+// WARNING
+//
+// This file has been generated automatically by MonoDevelop to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac
+{
+	[Register ("AppDelegate")]
+	partial class AppDelegate
+	{
+		[Action ("about:")]
+		partial void about (MonoMac.Foundation.NSObject sender);
+
+		[Action ("view:")]
+		partial void view (MonoMac.Foundation.NSObject sender);
+
+		[Action ("onlineHelp:")]
+		partial void onlineHelp (MonoMac.Foundation.NSObject sender);
+
+		[Action ("encrypt:")]
+		partial void encrypt (MonoMac.Foundation.NSObject sender);
+
+		[Action ("decrypt:")]
+		partial void decrypt (MonoMac.Foundation.NSObject sender);
+		
+		void ReleaseDesignerOutlets ()
+		{
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.icns b/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.icns
new file mode 100644
index 0000000..47d14aa
Binary files /dev/null and b/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.icns differ
diff --git a/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.png b/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.png
new file mode 100644
index 0000000..2429025
Binary files /dev/null and b/Axantum.AxCrypt.Mac/Resources/AxCryptIcon128.png differ
diff --git a/Axantum.AxCrypt.Mac/Resources/logo_axantum.png b/Axantum.AxCrypt.Mac/Resources/logo_axantum.png
new file mode 100644
index 0000000..b6e73a3
Binary files /dev/null and b/Axantum.AxCrypt.Mac/Resources/logo_axantum.png differ
diff --git a/Axantum.AxCrypt.Mac/Resources/tretton37.png b/Axantum.AxCrypt.Mac/Resources/tretton37.png
new file mode 100644
index 0000000..d9b1b58
Binary files /dev/null and b/Axantum.AxCrypt.Mac/Resources/tretton37.png differ
diff --git a/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.cs b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.cs
new file mode 100644
index 0000000..e027a21
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.cs
@@ -0,0 +1,56 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	public partial class CreatePassphraseView : MonoMac.AppKit.NSView
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public CreatePassphraseView (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public CreatePassphraseView (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+
+		public string VerifiedPassphrase {
+			get {
+				string phraseString = passphrase.StringValue;
+				string verificationString = verification.StringValue;
+				if (String.IsNullOrEmpty(phraseString) || String.IsNullOrEmpty(verificationString) || phraseString != verificationString)
+					return null;
+
+				return phraseString;
+			}
+		}
+
+		public string EncryptedFileName {
+			get {
+				return encryptedFileName.StringValue;
+			}
+			set
+			{
+				encryptedFileName.StringValue = value;
+			}
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.designer.cs b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.designer.cs
new file mode 100644
index 0000000..d4c9da2
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.designer.cs
@@ -0,0 +1,72 @@
+// WARNING
+//
+// This file has been generated automatically by MonoDevelop to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	[Register ("CreatePassphraseView")]
+	partial class CreatePassphraseView
+	{
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField passphrase { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField verification { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSTextField encryptedFileName { get; set; }
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (passphrase != null) {
+				passphrase.Dispose ();
+				passphrase = null;
+			}
+
+			if (verification != null) {
+				verification.Dispose ();
+				verification = null;
+			}
+
+			if (encryptedFileName != null) {
+				encryptedFileName.Dispose ();
+				encryptedFileName = null;
+			}
+		}
+	}
+
+	[Register ("CreatePassphraseViewController")]
+	partial class CreatePassphraseViewController
+	{
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField passphrase { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField verification { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSTextField encryptedFIleName { get; set; }
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (passphrase != null) {
+				passphrase.Dispose ();
+				passphrase = null;
+			}
+
+			if (verification != null) {
+				verification.Dispose ();
+				verification = null;
+			}
+
+			if (encryptedFIleName != null) {
+				encryptedFIleName.Dispose ();
+				encryptedFIleName = null;
+			}
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.xib b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.xib
new file mode 100644
index 0000000..454ea34
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/CreatePassphraseView.xib
@@ -0,0 +1,649 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12C54</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2840</string>
+		<string key="IBDocument.AppKitVersion">1187.34</string>
+		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">2840</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSBox</string>
+			<string>NSCustomObject</string>
+			<string>NSCustomView</string>
+			<string>NSSecureTextField</string>
+			<string>NSSecureTextFieldCell</string>
+			<string>NSTextField</string>
+			<string>NSTextFieldCell</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">CreatePassphraseViewController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomView" id="159381209">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">268</int>
+				<object class="NSMutableArray" key="NSSubviews">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSTextField" id="334390791">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{155, 20}, {221, 22}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="533248275"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="206736322">
+							<int key="NSCellFlags">-1804599231</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents"/>
+							<object class="NSFont" key="NSSupport" id="201005772">
+								<string key="NSName">LucidaGrande</string>
+								<double key="NSSize">13</double>
+								<int key="NSfFlags">1044</int>
+							</object>
+							<string key="NSCellIdentifier">_NS:9</string>
+							<reference key="NSControlView" ref="334390791"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<object class="NSColor" key="NSBackgroundColor" id="124042072">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textBackgroundColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor" id="1052449214">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textColor</string>
+								<object class="NSColor" key="NSColor" id="858868354">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MAA</bytes>
+								</object>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSBox" id="986218626">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">12</int>
+						<string key="NSFrame">{{20, 49}, {391, 5}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="83547112"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<string key="NSOffsets">{0, 0}</string>
+						<object class="NSTextFieldCell" key="NSTitleCell">
+							<int key="NSCellFlags">67108864</int>
+							<int key="NSCellFlags2">0</int>
+							<string key="NSContents">Box</string>
+							<reference key="NSSupport" ref="201005772"/>
+							<reference key="NSBackgroundColor" ref="124042072"/>
+							<object class="NSColor" key="NSTextColor">
+								<int key="NSColorSpace">3</int>
+								<bytes key="NSWhite">MCAwLjgwMDAwMDAxMTkAA</bytes>
+							</object>
+						</object>
+						<int key="NSBorderType">3</int>
+						<int key="NSBoxType">2</int>
+						<int key="NSTitlePosition">0</int>
+						<bool key="NSTransparent">NO</bool>
+					</object>
+					<object class="NSSecureTextField" id="552931828">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{290, 73}, {121, 22}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="986218626"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSSecureTextFieldCell" key="NSCell" id="408465059">
+							<int key="NSCellFlags">342884416</int>
+							<int key="NSCellFlags2">272630848</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:9</string>
+							<reference key="NSControlView" ref="552931828"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="124042072"/>
+							<reference key="NSTextColor" ref="1052449214"/>
+							<object class="NSArray" key="NSAllowedInputLocales">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<string>NSAllRomanInputSourcesLocaleIdentifier</string>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSTextField" id="533248275">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{382, 23}, {32, 17}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<string key="NSReuseIdentifierKey">_NS:1535</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="173161299">
+							<int key="NSCellFlags">68157504</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">.axx</string>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:1535</string>
+							<reference key="NSControlView" ref="533248275"/>
+							<object class="NSColor" key="NSBackgroundColor" id="595143965">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor" id="52779048">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlTextColor</string>
+								<reference key="NSColor" ref="858868354"/>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSTextField" id="83547112">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{17, 23}, {133, 17}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="334390791"/>
+						<string key="NSReuseIdentifierKey">_NS:1535</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="231176691">
+							<int key="NSCellFlags">68157504</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">Encrypted file name:</string>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:1535</string>
+							<reference key="NSControlView" ref="83547112"/>
+							<reference key="NSBackgroundColor" ref="595143965"/>
+							<reference key="NSTextColor" ref="52779048"/>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSTextField" id="357330287">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{17, 75}, {268, 17}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="552931828"/>
+						<string key="NSReuseIdentifierKey">_NS:1535</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="754337949">
+							<int key="NSCellFlags">68157504</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">Please repeat your passphrase to verify it:</string>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:1535</string>
+							<reference key="NSControlView" ref="357330287"/>
+							<reference key="NSBackgroundColor" ref="595143965"/>
+							<reference key="NSTextColor" ref="52779048"/>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSSecureTextField" id="165943790">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{290, 103}, {121, 22}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="357330287"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSSecureTextFieldCell" key="NSCell" id="1023495470">
+							<int key="NSCellFlags">342884416</int>
+							<int key="NSCellFlags2">272630848</int>
+							<string key="NSContents"/>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:9</string>
+							<reference key="NSControlView" ref="165943790"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<reference key="NSBackgroundColor" ref="124042072"/>
+							<reference key="NSTextColor" ref="1052449214"/>
+							<object class="NSArray" key="NSAllowedInputLocales">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<string>NSAllRomanInputSourcesLocaleIdentifier</string>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSTextField" id="275867146">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{72, 105}, {213, 17}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView" ref="165943790"/>
+						<string key="NSReuseIdentifierKey">_NS:1535</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="298740213">
+							<int key="NSCellFlags">68157504</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">Passphrase to lock your file with:</string>
+							<reference key="NSSupport" ref="201005772"/>
+							<string key="NSCellIdentifier">_NS:1535</string>
+							<reference key="NSControlView" ref="275867146"/>
+							<reference key="NSBackgroundColor" ref="595143965"/>
+							<reference key="NSTextColor" ref="52779048"/>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+				</object>
+				<string key="NSFrameSize">{431, 145}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<reference key="NSNextKeyView" ref="275867146"/>
+				<string key="NSClassName">CreatePassphraseView</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="159381209"/>
+					</object>
+					<int key="connectionID">17</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">passphrase</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="165943790"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">verification</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="552931828"/>
+					</object>
+					<int key="connectionID">29</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">encryptedFIleName</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="334390791"/>
+					</object>
+					<int key="connectionID">44</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">passphrase</string>
+						<reference key="source" ref="159381209"/>
+						<reference key="destination" ref="165943790"/>
+					</object>
+					<int key="connectionID">30</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">verification</string>
+						<reference key="source" ref="159381209"/>
+						<reference key="destination" ref="552931828"/>
+					</object>
+					<int key="connectionID">31</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">encryptedFileName</string>
+						<reference key="source" ref="159381209"/>
+						<reference key="destination" ref="334390791"/>
+					</object>
+					<int key="connectionID">45</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="159381209"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="357330287"/>
+							<reference ref="552931828"/>
+							<reference ref="165943790"/>
+							<reference ref="275867146"/>
+							<reference ref="986218626"/>
+							<reference ref="83547112"/>
+							<reference ref="334390791"/>
+							<reference ref="533248275"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="275867146"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="298740213"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="298740213"/>
+						<reference key="parent" ref="275867146"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="165943790"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1023495470"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="1023495470"/>
+						<reference key="parent" ref="165943790"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="357330287"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="754337949"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="552931828"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="408465059"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="408465059"/>
+						<reference key="parent" ref="552931828"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">25</int>
+						<reference key="object" ref="754337949"/>
+						<reference key="parent" ref="357330287"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">37</int>
+						<reference key="object" ref="986218626"/>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">38</int>
+						<reference key="object" ref="83547112"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="231176691"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">39</int>
+						<reference key="object" ref="231176691"/>
+						<reference key="parent" ref="83547112"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">40</int>
+						<reference key="object" ref="334390791"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="206736322"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">41</int>
+						<reference key="object" ref="206736322"/>
+						<reference key="parent" ref="334390791"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">42</int>
+						<reference key="object" ref="533248275"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="173161299"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">43</int>
+						<reference key="object" ref="173161299"/>
+						<reference key="parent" ref="533248275"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>25.IBPluginDependency</string>
+					<string>37.IBPluginDependency</string>
+					<string>38.IBPluginDependency</string>
+					<string>39.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+					<string>40.IBPluginDependency</string>
+					<string>41.IBPluginDependency</string>
+					<string>42.IBPluginDependency</string>
+					<string>43.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">45</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">CreatePassphraseView</string>
+					<string key="superclassName">NSView</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>passphrase</string>
+							<string>removeSourceFile</string>
+							<string>verification</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSSecureTextField</string>
+							<string>NSButton</string>
+							<string>NSSecureTextField</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>passphrase</string>
+							<string>removeSourceFile</string>
+							<string>verification</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">passphrase</string>
+								<string key="candidateClassName">NSSecureTextField</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">removeSourceFile</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">verification</string>
+								<string key="candidateClassName">NSSecureTextField</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/CreatePassphraseView.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">CreatePassphraseViewController</string>
+					<string key="superclassName">NSViewController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>encryptedFIleName</string>
+							<string>passphrase</string>
+							<string>verification</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSTextField</string>
+							<string>NSSecureTextField</string>
+							<string>NSSecureTextField</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>encryptedFIleName</string>
+							<string>passphrase</string>
+							<string>verification</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">encryptedFIleName</string>
+								<string key="candidateClassName">NSTextField</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">passphrase</string>
+								<string key="candidateClassName">NSSecureTextField</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">verification</string>
+								<string key="candidateClassName">NSSecureTextField</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/CreatePassphraseViewController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Views/CreatePassphraseViewController.cs b/Axantum.AxCrypt.Mac/Views/CreatePassphraseViewController.cs
new file mode 100644
index 0000000..7fa2d90
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/CreatePassphraseViewController.cs
@@ -0,0 +1,71 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using Axantum.AxCrypt.Core.Crypto;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	public partial class CreatePassphraseViewController : MonoMac.AppKit.NSViewController
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public CreatePassphraseViewController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public CreatePassphraseViewController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Call to load from the XIB/NIB file
+		public CreatePassphraseViewController () : base ("CreatePassphraseView", NSBundle.MainBundle)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+		
+		//strongly typed view accessor
+		public new CreatePassphraseView View {
+			get {
+				return (CreatePassphraseView)base.View;
+			}
+		}
+
+		public Passphrase VerifiedPassphrase {
+			get {
+				if (View.VerifiedPassphrase == null) {
+					NSAlert
+						.WithMessage("Phrase mismatch", "OK", null, null, "The two phrases you have entered either do not match, or they are empty")
+							.RunModal();
+					return null;
+				}
+
+				return new Passphrase(View.VerifiedPassphrase);
+			}
+		}
+
+		public string EncryptedFileName {
+			get {
+				return View.EncryptedFileName;
+			}
+			set {
+				View.EncryptedFileName = value;
+			}
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Views/PasswordView.cs b/Axantum.AxCrypt.Mac/Views/PasswordView.cs
new file mode 100644
index 0000000..7b137d8
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/PasswordView.cs
@@ -0,0 +1,41 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	public partial class PasswordView : MonoMac.AppKit.NSView
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public PasswordView (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public PasswordView (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+
+		public string EnteredPassphrase {
+			get {
+				return passphrase.StringValue;
+			}
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Views/PasswordView.designer.cs b/Axantum.AxCrypt.Mac/Views/PasswordView.designer.cs
new file mode 100644
index 0000000..c9db160
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/PasswordView.designer.cs
@@ -0,0 +1,34 @@
+// WARNING
+//
+// This file has been generated automatically by MonoDevelop to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	[Register ("PasswordView")]
+	partial class PasswordView
+	{
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField passphrase { get; set; }
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (passphrase != null) {
+				passphrase.Dispose ();
+				passphrase = null;
+			}
+		}
+	}
+
+	[Register ("PasswordViewController")]
+	partial class PasswordViewController
+	{
+		
+		void ReleaseDesignerOutlets ()
+		{
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Views/PasswordView.xib b/Axantum.AxCrypt.Mac/Views/PasswordView.xib
new file mode 100644
index 0000000..d12e055
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/PasswordView.xib
@@ -0,0 +1,302 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12C54</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2840</string>
+		<string key="IBDocument.AppKitVersion">1187.34</string>
+		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">2840</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSCustomObject</string>
+			<string>NSCustomView</string>
+			<string>NSSecureTextField</string>
+			<string>NSSecureTextFieldCell</string>
+			<string>NSTextField</string>
+			<string>NSTextFieldCell</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">PasswordViewController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSCustomView" id="159381209">
+				<reference key="NSNextResponder"/>
+				<int key="NSvFlags">268</int>
+				<object class="NSMutableArray" key="NSSubviews">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="NSSecureTextField" id="862550896">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{396, 13}, {96, 22}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<string key="NSReuseIdentifierKey">_NS:9</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSSecureTextFieldCell" key="NSCell" id="1016513826">
+							<int key="NSCellFlags">342884416</int>
+							<int key="NSCellFlags2">272630848</int>
+							<string key="NSContents"/>
+							<object class="NSFont" key="NSSupport" id="350076285">
+								<string key="NSName">LucidaGrande</string>
+								<double key="NSSize">13</double>
+								<int key="NSfFlags">1044</int>
+							</object>
+							<string key="NSCellIdentifier">_NS:9</string>
+							<reference key="NSControlView" ref="862550896"/>
+							<bool key="NSDrawsBackground">YES</bool>
+							<object class="NSColor" key="NSBackgroundColor">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textBackgroundColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MQA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">textColor</string>
+								<object class="NSColor" key="NSColor" id="179920770">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MAA</bytes>
+								</object>
+							</object>
+							<object class="NSArray" key="NSAllowedInputLocales">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<string>NSAllRomanInputSourcesLocaleIdentifier</string>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+					<object class="NSTextField" id="315394982">
+						<reference key="NSNextResponder" ref="159381209"/>
+						<int key="NSvFlags">268</int>
+						<string key="NSFrame">{{17, 15}, {374, 17}}</string>
+						<reference key="NSSuperview" ref="159381209"/>
+						<reference key="NSWindow"/>
+						<reference key="NSNextKeyView"/>
+						<string key="NSReuseIdentifierKey">_NS:1535</string>
+						<bool key="NSEnabled">YES</bool>
+						<object class="NSTextFieldCell" key="NSCell" id="961753665">
+							<int key="NSCellFlags">68157504</int>
+							<int key="NSCellFlags2">272630784</int>
+							<string key="NSContents">Enter the same passphrase as was used to encrypt the file:</string>
+							<reference key="NSSupport" ref="350076285"/>
+							<string key="NSCellIdentifier">_NS:1535</string>
+							<reference key="NSControlView" ref="315394982"/>
+							<object class="NSColor" key="NSBackgroundColor">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlColor</string>
+								<object class="NSColor" key="NSColor">
+									<int key="NSColorSpace">3</int>
+									<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+								</object>
+							</object>
+							<object class="NSColor" key="NSTextColor">
+								<int key="NSColorSpace">6</int>
+								<string key="NSCatalogName">System</string>
+								<string key="NSColorName">controlTextColor</string>
+								<reference key="NSColor" ref="179920770"/>
+							</object>
+						</object>
+						<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+					</object>
+				</object>
+				<string key="NSFrameSize">{512, 52}</string>
+				<reference key="NSSuperview"/>
+				<reference key="NSWindow"/>
+				<reference key="NSNextKeyView" ref="315394982"/>
+				<string key="NSClassName">PasswordView</string>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">view</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="159381209"/>
+					</object>
+					<int key="connectionID">17</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">passphrase</string>
+						<reference key="source" ref="159381209"/>
+						<reference key="destination" ref="862550896"/>
+					</object>
+					<int key="connectionID">22</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">4</int>
+						<reference key="object" ref="159381209"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="315394982"/>
+							<reference ref="862550896"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="315394982"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="961753665"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="961753665"/>
+						<reference key="parent" ref="315394982"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="862550896"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1016513826"/>
+						</object>
+						<reference key="parent" ref="159381209"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="1016513826"/>
+						<reference key="parent" ref="862550896"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>4.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">22</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">PasswordView</string>
+					<string key="superclassName">NSView</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">passphrase</string>
+						<string key="NS.object.0">NSSecureTextField</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">passphrase</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">passphrase</string>
+							<string key="candidateClassName">NSSecureTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/PasswordView.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">PasswordViewController</string>
+					<string key="superclassName">NSViewController</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/PasswordViewController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Views/PasswordViewController.cs b/Axantum.AxCrypt.Mac/Views/PasswordViewController.cs
new file mode 100644
index 0000000..a0774d2
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Views/PasswordViewController.cs
@@ -0,0 +1,55 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using Axantum.AxCrypt.Core.Crypto;
+
+namespace Axantum.AxCrypt.Mac.Views
+{
+	public partial class PasswordViewController : MonoMac.AppKit.NSViewController
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public PasswordViewController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public PasswordViewController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Call to load from the XIB/NIB file
+		public PasswordViewController () : base ("PasswordView", NSBundle.MainBundle)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+		
+		//strongly typed view accessor
+		public new PasswordView View {
+			get {
+				return (PasswordView)base.View;
+			}
+		}
+
+		public Passphrase Passphrase {
+			get {
+				return new Passphrase(View.EnteredPassphrase);
+			}
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/AboutWindow.cs b/Axantum.AxCrypt.Mac/Windows/AboutWindow.cs
new file mode 100644
index 0000000..53b31bd
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/AboutWindow.cs
@@ -0,0 +1,35 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class AboutWindow : MonoMac.AppKit.NSWindow
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public AboutWindow (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public AboutWindow (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/AboutWindow.designer.cs b/Axantum.AxCrypt.Mac/Windows/AboutWindow.designer.cs
new file mode 100644
index 0000000..1c8f838
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/AboutWindow.designer.cs
@@ -0,0 +1,43 @@
+// WARNING
+//
+// This file has been generated automatically by MonoDevelop to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	[Register ("AboutWindowController")]
+	partial class AboutWindowController
+	{
+		[Outlet]
+		MonoMac.AppKit.NSTextField versionLabel { get; set; }
+
+		[Action ("axantumLogoClicked:")]
+		partial void axantumLogoClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("bouncyLinkClicked:")]
+		partial void bouncyLinkClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("tretton37LogoClicked:")]
+		partial void tretton37LogoClicked (MonoMac.Foundation.NSObject sender);
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (versionLabel != null) {
+				versionLabel.Dispose ();
+				versionLabel = null;
+			}
+		}
+	}
+
+	[Register ("AboutWindow")]
+	partial class AboutWindow
+	{
+		
+		void ReleaseDesignerOutlets ()
+		{
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Windows/AboutWindow.xib b/Axantum.AxCrypt.Mac/Windows/AboutWindow.xib
new file mode 100644
index 0000000..2f135f6
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/AboutWindow.xib
@@ -0,0 +1,659 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12C54</string>
+		<string key="IBDocument.InterfaceBuilderVersion">2840</string>
+		<string key="IBDocument.AppKitVersion">1187.34</string>
+		<string key="IBDocument.HIToolboxVersion">625.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">2840</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSButton</string>
+			<string>NSButtonCell</string>
+			<string>NSCustomObject</string>
+			<string>NSTextField</string>
+			<string>NSTextFieldCell</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">AboutWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="748157544">
+				<int key="NSWindowStyleMask">7</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{131, 74}, {606, 258}}</string>
+				<int key="NSWTFlags">611844096</int>
+				<string key="NSWindowTitle">About AxCrypt for Mac</string>
+				<string key="NSWindowClass">AboutWindow</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<string key="NSWindowContentMaxSize">{606, 258}</string>
+				<string key="NSWindowContentMinSize">{606, 258}</string>
+				<object class="NSView" key="NSWindowView" id="312036702">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="383513293">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{419, 209}, {107, 17}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="605169089"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="230027561">
+								<int key="NSCellFlags">68157504</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">AxCrypt for Mac</string>
+								<object class="NSFont" key="NSSupport" id="403325056">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="383513293"/>
+								<object class="NSColor" key="NSBackgroundColor" id="724641653">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor" id="383106909">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSTextField" id="736144090">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 45}, {87, 17}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="403432662"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="1035097693">
+								<int key="NSCellFlags">68157504</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Produced by:</string>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="736144090"/>
+								<reference key="NSBackgroundColor" ref="724641653"/>
+								<reference key="NSTextColor" ref="383106909"/>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSTextField" id="605169089">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{419, 184}, {52, 17}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="978577603"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="753138317">
+								<int key="NSCellFlags">68157504</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">Version</string>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="605169089"/>
+								<reference key="NSBackgroundColor" ref="724641653"/>
+								<reference key="NSTextColor" ref="383106909"/>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSTextField" id="978577603">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{469, 184}, {50, 17}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="558708290"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="924504650">
+								<int key="NSCellFlags">68157504</int>
+								<int key="NSCellFlags2">272630784</int>
+								<string key="NSContents">1.0.0.0</string>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="978577603"/>
+								<reference key="NSBackgroundColor" ref="724641653"/>
+								<reference key="NSTextColor" ref="383106909"/>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSTextField" id="558708290">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{17, 124}, {572, 40}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="77804073"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="451556452">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">272629760</int>
+								<string key="NSContents">This work is based of the Axantum Open Source File Encryption for Windows and includes software from</string>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="558708290"/>
+								<reference key="NSBackgroundColor" ref="724641653"/>
+								<reference key="NSTextColor" ref="383106909"/>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="369262819">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{20, 172}, {334, 66}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="383513293"/>
+							<string key="NSReuseIdentifierKey">_NS:22</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="481303429">
+								<int key="NSCellFlags">-2080374784</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:22</string>
+								<reference key="NSControlView" ref="369262819"/>
+								<int key="NSButtonFlags">-2041823232</int>
+								<int key="NSButtonFlags2">34</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">logo_axantum</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="403432662">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{343, 20}, {243, 67}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<string key="NSReuseIdentifierKey">_NS:22</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="395582005">
+								<int key="NSCellFlags">-2080374784</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:22</string>
+								<reference key="NSControlView" ref="403432662"/>
+								<int key="NSButtonFlags">-2041823232</int>
+								<int key="NSButtonFlags2">34</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">tretton37</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="77804073">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{107, 127}, {199, 23}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="736144090"/>
+							<string key="NSReuseIdentifierKey">_NS:22</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="851821882">
+								<int key="NSCellFlags">-2080374784</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">http://www.bouncycastle.org/</string>
+								<reference key="NSSupport" ref="403325056"/>
+								<string key="NSCellIdentifier">_NS:22</string>
+								<reference key="NSControlView" ref="77804073"/>
+								<int key="NSButtonFlags">-2041823232</int>
+								<int key="NSButtonFlags2">162</int>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+					</object>
+					<string key="NSFrameSize">{606, 258}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="369262819"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
+				<string key="NSMinSize">{606, 280}</string>
+				<string key="NSMaxSize">{606, 280}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="748157544"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">bouncyCastleLinkClicked</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="77804073"/>
+					</object>
+					<int key="connectionID">44</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">axantumLogoClicked:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="369262819"/>
+					</object>
+					<int key="connectionID">45</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionLabel</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="978577603"/>
+					</object>
+					<int key="connectionID">46</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">bouncyLinkClicked:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="77804073"/>
+					</object>
+					<int key="connectionID">47</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">tretton37LogoClicked:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="403432662"/>
+					</object>
+					<int key="connectionID">48</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="748157544"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="312036702"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="312036702"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="369262819"/>
+							<reference ref="383513293"/>
+							<reference ref="605169089"/>
+							<reference ref="978577603"/>
+							<reference ref="558708290"/>
+							<reference ref="77804073"/>
+							<reference ref="403432662"/>
+							<reference ref="736144090"/>
+						</object>
+						<reference key="parent" ref="748157544"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="383513293"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="230027561"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="230027561"/>
+						<reference key="parent" ref="383513293"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="605169089"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="753138317"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="753138317"/>
+						<reference key="parent" ref="605169089"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="558708290"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="451556452"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="451556452"/>
+						<reference key="parent" ref="558708290"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="369262819"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="481303429"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">28</int>
+						<reference key="object" ref="481303429"/>
+						<reference key="parent" ref="369262819"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">29</int>
+						<reference key="object" ref="978577603"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="924504650"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">30</int>
+						<reference key="object" ref="924504650"/>
+						<reference key="parent" ref="978577603"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="403432662"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="395582005"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">32</int>
+						<reference key="object" ref="395582005"/>
+						<reference key="parent" ref="403432662"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">35</int>
+						<reference key="object" ref="736144090"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1035097693"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">36</int>
+						<reference key="object" ref="1035097693"/>
+						<reference key="parent" ref="736144090"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">42</int>
+						<reference key="object" ref="77804073"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="851821882"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">43</int>
+						<reference key="object" ref="851821882"/>
+						<reference key="parent" ref="77804073"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>2.IBWindowTemplateEditedContentRect</string>
+					<string>2.NSWindowTemplate.visibleAtLaunch</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>27.IBPluginDependency</string>
+					<string>28.IBPluginDependency</string>
+					<string>29.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>30.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+					<string>32.IBPluginDependency</string>
+					<string>35.IBPluginDependency</string>
+					<string>36.IBPluginDependency</string>
+					<string>42.IBPluginDependency</string>
+					<string>43.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{319, 371}, {606, 354}}</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">48</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">AboutWindow</string>
+					<string key="superclassName">NSWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/AboutWindow.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">AboutWindowController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>axantumLogoClicked:</string>
+							<string>bouncyLinkClicked:</string>
+							<string>tretton37LogoClicked:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>axantumLogoClicked:</string>
+							<string>bouncyLinkClicked:</string>
+							<string>tretton37LogoClicked:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBActionInfo">
+								<string key="name">axantumLogoClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">bouncyLinkClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">tretton37LogoClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">versionLabel</string>
+						<string key="NS.object.0">NSTextField</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">versionLabel</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">versionLabel</string>
+							<string key="candidateClassName">NSTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/AboutWindowController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>logo_axantum</string>
+				<string>tretton37</string>
+			</object>
+			<object class="NSArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>{352, 74}</string>
+				<string>{243, 67}</string>
+			</object>
+		</object>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Windows/AboutWindowController.cs b/Axantum.AxCrypt.Mac/Windows/AboutWindowController.cs
new file mode 100644
index 0000000..aedc28d
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/AboutWindowController.cs
@@ -0,0 +1,69 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using System.Diagnostics;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class AboutWindowController : MonoMac.AppKit.NSWindowController
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public AboutWindowController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public AboutWindowController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Call to load from the XIB/NIB file
+		public AboutWindowController () : base ("AboutWindow")
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+		
+		//strongly typed window accessor
+		public new AboutWindow Window {
+			get {
+				return (AboutWindow)base.Window;
+			}
+		}
+
+		partial void axantumLogoClicked (NSObject sender)
+		{
+			Process.Start("http://www.axantum.com/");
+		}
+
+		partial void bouncyLinkClicked (NSObject sender)
+		{
+			Process.Start("http://www.bouncycastle.org/");
+		}
+
+		partial void tretton37LogoClicked (NSObject sender)
+		{
+			Process.Start("http://www.tretton37.com/");
+		}
+
+		public void SetVersion(string version)
+		{
+			versionLabel.StringValue = version;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/MainWindow.cs b/Axantum.AxCrypt.Mac/Windows/MainWindow.cs
new file mode 100644
index 0000000..44a0a64
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/MainWindow.cs
@@ -0,0 +1,83 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+using Axantum.AxCrypt.Core.UI;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class MainWindow : MonoMac.AppKit.NSWindow
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public MainWindow (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public MainWindow (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		
+		#endregion
+
+		partial void urlClicked (NSObject sender)
+		{
+			System.Diagnostics.Process.Start("http://www.axantum.com");
+		}
+		
+		void InvokeWithProgress (Action<ProgressContext, Action<string, ProgressContext>> action, NSProgressIndicator indicator)
+		{
+			ProgressContext progress = new ProgressContext();
+			progress.Progressing += (sender, eventArgs) => {
+				if (eventArgs.Percent < 100) {
+					indicator.StartAnimation(this);
+				}
+				else {
+					indicator.StopAnimation(this);
+				}
+			};
+			action(progress, (message, context) => InvokeOnMainThread((NSAction) delegate {
+				indicator.StopAnimation(this);
+				AppController.OperationFailureHandler(message, context);
+			}));
+		}
+		
+		partial void encryptClicked (NSObject sender)
+		{
+			InvokeWithProgress(AppController.EncryptFile, encryptingIndicator);
+		}
+		
+		partial void viewClicked (NSObject sender)
+		{
+			InvokeWithProgress(AppController.DecryptAndOpenFile, openingIndicator);
+		}
+		
+		partial void decryptClicked (NSObject sender)
+		{
+			InvokeWithProgress(AppController.DecryptFile, decryptingIndicator);
+		}
+		
+		partial void aboutClicked (NSObject sender)
+		{
+			AppController.About(sender);
+		}
+
+		partial void versionClicked (NSObject sender)
+		{
+			AppController.ShowVersionInfo();
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/MainWindow.designer.cs b/Axantum.AxCrypt.Mac/Windows/MainWindow.designer.cs
new file mode 100644
index 0000000..b39495d
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/MainWindow.designer.cs
@@ -0,0 +1,106 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	[Register ("MainWindowController")]
+	partial class MainWindowController
+	{
+		[Outlet]
+		MonoMac.AppKit.NSButton versionInformation { get; set; }
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (versionInformation != null) {
+				versionInformation.Dispose ();
+				versionInformation = null;
+			}
+		}
+	}
+
+	[Register ("MainWindow")]
+	partial class MainWindow
+	{
+		[Outlet]
+		MonoMac.AppKit.NSButton openingButton { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSProgressIndicator openingIndicator { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSButton encryptingButton { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSProgressIndicator encryptingIndicator { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSButton decryptingButton { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSProgressIndicator decryptingIndicator { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSButton versionButton { get; set; }
+
+		[Action ("urlClicked:")]
+		partial void urlClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("encryptClicked:")]
+		partial void encryptClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("viewClicked:")]
+		partial void viewClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("decryptClicked:")]
+		partial void decryptClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("aboutClicked:")]
+		partial void aboutClicked (MonoMac.Foundation.NSObject sender);
+
+		[Action ("versionClicked:")]
+		partial void versionClicked (MonoMac.Foundation.NSObject sender);
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (openingButton != null) {
+				openingButton.Dispose ();
+				openingButton = null;
+			}
+
+			if (openingIndicator != null) {
+				openingIndicator.Dispose ();
+				openingIndicator = null;
+			}
+
+			if (encryptingButton != null) {
+				encryptingButton.Dispose ();
+				encryptingButton = null;
+			}
+
+			if (encryptingIndicator != null) {
+				encryptingIndicator.Dispose ();
+				encryptingIndicator = null;
+			}
+
+			if (decryptingButton != null) {
+				decryptingButton.Dispose ();
+				decryptingButton = null;
+			}
+
+			if (decryptingIndicator != null) {
+				decryptingIndicator.Dispose ();
+				decryptingIndicator = null;
+			}
+
+			if (versionButton != null) {
+				versionButton.Dispose ();
+				versionButton = null;
+			}
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Windows/MainWindow.xib b/Axantum.AxCrypt.Mac/Windows/MainWindow.xib
new file mode 100644
index 0000000..25fbbfb
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/MainWindow.xib
@@ -0,0 +1,928 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">3084</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSButton</string>
+			<string>NSButtonCell</string>
+			<string>NSCustomObject</string>
+			<string>NSImageCell</string>
+			<string>NSImageView</string>
+			<string>NSProgressIndicator</string>
+			<string>NSTextField</string>
+			<string>NSTextFieldCell</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">MainWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="748157544">
+				<int key="NSWindowStyleMask">7</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{131, 74}, {518, 188}}</string>
+				<int key="NSWTFlags">1685585920</int>
+				<string key="NSWindowTitle">Window</string>
+				<string key="NSWindowClass">MainWindow</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<string key="NSWindowContentMaxSize">{518, 188}</string>
+				<string key="NSWindowContentMinSize">{518, 188}</string>
+				<object class="NSView" key="NSWindowView" id="312036702">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSTextField" id="603977312">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">256</int>
+							<string key="NSFrame">{{153, 146}, {179, 22}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="977070247"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="349766066">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">4194304</int>
+								<string key="NSContents">AxCrypt for Mac</string>
+								<object class="NSFont" key="NSSupport">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">18</double>
+									<int key="NSfFlags">16</int>
+								</object>
+								<reference key="NSControlView" ref="603977312"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSImageView" id="404782825">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">256</int>
+							<object class="NSMutableSet" key="NSDragTypes">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSArray" key="set.sortedObjects">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>Apple PDF pasteboard type</string>
+									<string>Apple PICT pasteboard type</string>
+									<string>Apple PNG pasteboard type</string>
+									<string>NSFilenamesPboardType</string>
+									<string>NeXT Encapsulated PostScript v1.2 pasteboard type</string>
+									<string>NeXT TIFF v4.0 pasteboard type</string>
+								</object>
+							</object>
+							<string key="NSFrame">{{20, 40}, {128, 128}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="603977312"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSImageCell" key="NSCell" id="668429967">
+								<int key="NSCellFlags">0</int>
+								<int key="NSCellFlags2">33554432</int>
+								<object class="NSCustomResource" key="NSContents">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">AxCryptIcon128</string>
+								</object>
+								<int key="NSAlign">0</int>
+								<int key="NSScale">0</int>
+								<int key="NSStyle">0</int>
+								<bool key="NSAnimates">YES</bool>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+							<bool key="NSEditable">YES</bool>
+						</object>
+						<object class="NSButton" id="134574392">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{222, 80}, {54, 48}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="288812101"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="776372686">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Encrypt</string>
+								<object class="NSFont" key="NSSupport" id="11819971">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="134574392"/>
+								<int key="NSButtonFlags">-2030813184</int>
+								<int key="NSButtonFlags2">268435590</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">NSLockLockedTemplate</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent">e</string>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="804385609">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{286, 80}, {54, 48}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="281467976"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="20451449">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Decrypt</string>
+								<reference key="NSSupport" ref="11819971"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="804385609"/>
+								<int key="NSButtonFlags">-2030813184</int>
+								<int key="NSButtonFlags2">268435590</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">NSLockUnlockedTemplate</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent">d</string>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="674069552">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{350, 80}, {54, 48}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="272169174"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="531185179">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Decrypt</string>
+								<reference key="NSSupport" ref="11819971"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="674069552"/>
+								<int key="NSButtonFlags">-2030813184</int>
+								<int key="NSButtonFlags2">268435590</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">NSInfo</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent">d</string>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="977070247">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{156, 80}, {54, 48}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="681703206"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="56654767">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Open / Edit</string>
+								<reference key="NSSupport" ref="11819971"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="977070247"/>
+								<int key="NSButtonFlags">-2033958912</int>
+								<int key="NSButtonFlags2">268435590</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">NSQuickLookTemplate</string>
+								</object>
+								<string key="NSAlternateContents">Opens the file in your default file viewer</string>
+								<string key="NSKeyEquivalent">o</string>
+								<int key="NSPeriodicDelay">400</int>
+								<int key="NSPeriodicInterval">75</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="938683507">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{363, 20}, {135, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="836702324">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">67108864</int>
+								<string key="NSContents">www.axantum.com</string>
+								<reference key="NSSupport" ref="11819971"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="938683507"/>
+								<int key="NSButtonFlags">-2046672896</int>
+								<int key="NSButtonFlags2">129</int>
+								<reference key="NSAlternateImage" ref="11819971"/>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="272169174">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{156, 20}, {184, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="938683507"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="1019161514">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">0</int>
+								<string key="NSContents">Version 2.0.2.0 (May 2013)</string>
+								<reference key="NSSupport" ref="11819971"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="272169174"/>
+								<int key="NSButtonFlags">-2046672896</int>
+								<int key="NSButtonFlags2">129</int>
+								<reference key="NSAlternateImage" ref="11819971"/>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSProgressIndicator" id="288812101">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{233, 88}, {32, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="804385609"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="NSHuggingPriority">{250, 250}</string>
+							<int key="NSpiFlags">28687</int>
+							<double key="NSMaxValue">100</double>
+						</object>
+						<object class="NSProgressIndicator" id="681703206">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{168, 88}, {32, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="134574392"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="NSHuggingPriority">{250, 250}</string>
+							<int key="NSpiFlags">28687</int>
+							<double key="NSMaxValue">100</double>
+						</object>
+						<object class="NSProgressIndicator" id="281467976">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{297, 88}, {32, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="674069552"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="NSHuggingPriority">{250, 250}</string>
+							<int key="NSpiFlags">28687</int>
+							<double key="NSMaxValue">100</double>
+						</object>
+					</object>
+					<string key="NSFrameSize">{518, 188}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="404782825"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMinSize">{518, 210}</string>
+				<string key="NSMaxSize">{518, 210}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="748157544"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionInformation</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="272169174"/>
+					</object>
+					<int key="connectionID">43</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">openingButton</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="977070247"/>
+					</object>
+					<int key="connectionID">24</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">openingIndicator</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="681703206"/>
+					</object>
+					<int key="connectionID">25</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">viewClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="977070247"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">encryptingButton</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="134574392"/>
+					</object>
+					<int key="connectionID">27</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">encryptingIndicator</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="288812101"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">decryptingIndicator</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="281467976"/>
+					</object>
+					<int key="connectionID">31</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">decryptingButton</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="804385609"/>
+					</object>
+					<int key="connectionID">33</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">encryptClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="134574392"/>
+					</object>
+					<int key="connectionID">34</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">decryptClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="804385609"/>
+					</object>
+					<int key="connectionID">35</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">aboutClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="674069552"/>
+					</object>
+					<int key="connectionID">36</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">urlClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="938683507"/>
+					</object>
+					<int key="connectionID">37</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">versionClicked:</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="272169174"/>
+					</object>
+					<int key="connectionID">41</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionButton</string>
+						<reference key="source" ref="748157544"/>
+						<reference key="destination" ref="272169174"/>
+					</object>
+					<int key="connectionID">42</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="748157544"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="312036702"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="312036702"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="603977312"/>
+							<reference ref="134574392"/>
+							<reference ref="804385609"/>
+							<reference ref="674069552"/>
+							<reference ref="977070247"/>
+							<reference ref="288812101"/>
+							<reference ref="681703206"/>
+							<reference ref="281467976"/>
+							<reference ref="404782825"/>
+							<reference ref="938683507"/>
+							<reference ref="272169174"/>
+						</object>
+						<reference key="parent" ref="748157544"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="603977312"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="349766066"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="404782825"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="668429967"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">9</int>
+						<reference key="object" ref="134574392"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="776372686"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">10</int>
+						<reference key="object" ref="804385609"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="20451449"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="674069552"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="531185179"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="977070247"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="56654767"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="938683507"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="836702324"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="288812101"/>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="681703206"/>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="281467976"/>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">17</int>
+						<reference key="object" ref="836702324"/>
+						<reference key="parent" ref="938683507"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">18</int>
+						<reference key="object" ref="56654767"/>
+						<reference key="parent" ref="977070247"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">19</int>
+						<reference key="object" ref="531185179"/>
+						<reference key="parent" ref="674069552"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">20</int>
+						<reference key="object" ref="20451449"/>
+						<reference key="parent" ref="804385609"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="776372686"/>
+						<reference key="parent" ref="134574392"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="668429967"/>
+						<reference key="parent" ref="404782825"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="349766066"/>
+						<reference key="parent" ref="603977312"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">38</int>
+						<reference key="object" ref="272169174"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1019161514"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">39</int>
+						<reference key="object" ref="1019161514"/>
+						<reference key="parent" ref="272169174"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>10.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>17.IBPluginDependency</string>
+					<string>18.IBPluginDependency</string>
+					<string>19.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>2.IBWindowTemplateEditedContentRect</string>
+					<string>2.NSWindowTemplate.visibleAtLaunch</string>
+					<string>20.IBPluginDependency</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>38.IBPluginDependency</string>
+					<string>39.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+					<string>9.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{319, 371}, {606, 354}}</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">43</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">MainWindow</string>
+					<string key="superclassName">NSWindow</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>aboutClicked:</string>
+							<string>decryptClicked:</string>
+							<string>encryptClicked:</string>
+							<string>urlClicked:</string>
+							<string>versionClicked:</string>
+							<string>viewClicked:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>aboutClicked:</string>
+							<string>decryptClicked:</string>
+							<string>encryptClicked:</string>
+							<string>urlClicked:</string>
+							<string>versionClicked:</string>
+							<string>viewClicked:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBActionInfo">
+								<string key="name">aboutClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">decryptClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">encryptClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">urlClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">versionClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">viewClicked:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>decryptingButton</string>
+							<string>decryptingIndicator</string>
+							<string>encryptingButton</string>
+							<string>encryptingIndicator</string>
+							<string>openingButton</string>
+							<string>openingIndicator</string>
+							<string>versionButton</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSButton</string>
+							<string>NSProgressIndicator</string>
+							<string>NSButton</string>
+							<string>NSProgressIndicator</string>
+							<string>NSButton</string>
+							<string>NSProgressIndicator</string>
+							<string>NSButton</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>decryptingButton</string>
+							<string>decryptingIndicator</string>
+							<string>encryptingButton</string>
+							<string>encryptingIndicator</string>
+							<string>openingButton</string>
+							<string>openingIndicator</string>
+							<string>versionButton</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">decryptingButton</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">decryptingIndicator</string>
+								<string key="candidateClassName">NSProgressIndicator</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">encryptingButton</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">encryptingIndicator</string>
+								<string key="candidateClassName">NSProgressIndicator</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">openingButton</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">openingIndicator</string>
+								<string key="candidateClassName">NSProgressIndicator</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">versionButton</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/MainWindow.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">MainWindowController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">versionInformation</string>
+						<string key="NS.object.0">NSButton</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">versionInformation</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">versionInformation</string>
+							<string key="candidateClassName">NSButton</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/MainWindowController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>AxCryptIcon128</string>
+				<string>NSInfo</string>
+				<string>NSLockLockedTemplate</string>
+				<string>NSLockUnlockedTemplate</string>
+				<string>NSQuickLookTemplate</string>
+			</object>
+			<object class="NSArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>{128, 128}</string>
+				<string>{32, 32}</string>
+				<string>{9, 12}</string>
+				<string>{9, 12}</string>
+				<string>{21, 16}</string>
+			</object>
+		</object>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Windows/MainWindowController.cs b/Axantum.AxCrypt.Mac/Windows/MainWindowController.cs
new file mode 100644
index 0000000..dff9748
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/MainWindowController.cs
@@ -0,0 +1,50 @@
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class MainWindowController : MonoMac.AppKit.NSWindowController
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public MainWindowController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public MainWindowController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		
+		// Call to load from the XIB/NIB file
+		public MainWindowController () : base ("MainWindow")
+		{
+			Initialize ();
+		}
+		
+		// Shared initialization code
+		void Initialize ()
+		{
+			Window.Title = AppController.FullApplicationName;
+			versionInformation.StringValue = AppController.VersionInformation;
+		}
+		
+		#endregion
+		
+		//strongly typed window accessor
+		public new MainWindow Window {
+			get {
+				return (MainWindow)base.Window;
+			}
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.cs b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.cs
new file mode 100644
index 0000000..e7cc82b
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class OpenFileFromFinder : MonoMac.AppKit.NSWindow
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public OpenFileFromFinder (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public OpenFileFromFinder (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		#endregion
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.designer.cs b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.designer.cs
new file mode 100644
index 0000000..61a1b19
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.designer.cs
@@ -0,0 +1,40 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	[Register ("OpenFileFromFinderController")]
+	partial class OpenFileFromFinderController
+	{
+		[Outlet]
+		MonoMac.AppKit.NSSecureTextField Passphrase { get; set; }
+
+		[Action ("Open:")]
+		partial void Open (MonoMac.Foundation.NSObject sender);
+
+		[Action ("Cancel:")]
+		partial void Cancel (MonoMac.Foundation.NSObject sender);
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (Passphrase != null) {
+				Passphrase.Dispose ();
+				Passphrase = null;
+			}
+		}
+	}
+
+	[Register ("OpenFileFromFinder")]
+	partial class OpenFileFromFinder
+	{
+		
+		void ReleaseDesignerOutlets ()
+		{
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.xib b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.xib
new file mode 100644
index 0000000..8bb9bf4
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinder.xib
@@ -0,0 +1,529 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string key="NS.object.0">3084</string>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSButton</string>
+			<string>NSButtonCell</string>
+			<string>NSCustomObject</string>
+			<string>NSImageCell</string>
+			<string>NSImageView</string>
+			<string>NSSecureTextField</string>
+			<string>NSSecureTextFieldCell</string>
+			<string>NSTextField</string>
+			<string>NSTextFieldCell</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">OpenFileFromFinderController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="748157544">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{131, 74}, {392, 133}}</string>
+				<int key="NSWTFlags">611844096</int>
+				<string key="NSWindowTitle">Open document</string>
+				<string key="NSWindowClass">OpenFileFromFinder</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<object class="NSView" key="NSWindowView" id="312036702">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSImageView" id="85778589">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">256</int>
+							<object class="NSMutableSet" key="NSDragTypes">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSArray" key="set.sortedObjects">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>Apple PDF pasteboard type</string>
+									<string>Apple PICT pasteboard type</string>
+									<string>Apple PNG pasteboard type</string>
+									<string>NSFilenamesPboardType</string>
+									<string>NeXT Encapsulated PostScript v1.2 pasteboard type</string>
+									<string>NeXT TIFF v4.0 pasteboard type</string>
+								</object>
+							</object>
+							<string key="NSFrame">{{20, 33}, {72, 80}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="697134294"/>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSImageCell" key="NSCell" id="478857961">
+								<int key="NSCellFlags">0</int>
+								<int key="NSCellFlags2">33554432</int>
+								<object class="NSCustomResource" key="NSContents">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">AxCryptIcon128</string>
+								</object>
+								<int key="NSAlign">0</int>
+								<int key="NSScale">0</int>
+								<int key="NSStyle">0</int>
+								<bool key="NSAnimates">YES</bool>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+							<bool key="NSEditable">YES</bool>
+						</object>
+						<object class="NSTextField" id="697134294">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{97, 79}, {278, 34}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="397782954"/>
+							<string key="NSReuseIdentifierKey">_NS:1535</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSTextFieldCell" key="NSCell" id="790924092">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">272629760</int>
+								<string key="NSContents">Please enter the same passphrase that 
was used to lock the document:</string>
+								<object class="NSFont" key="NSSupport" id="672024657">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:1535</string>
+								<reference key="NSControlView" ref="697134294"/>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">controlTextColor</string>
+									<object class="NSColor" key="NSColor" id="505464029">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MAA</bytes>
+									</object>
+								</object>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSSecureTextField" id="397782954">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{100, 49}, {272, 22}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="1000243235"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSSecureTextFieldCell" key="NSCell" id="56735834">
+								<int key="NSCellFlags">342884416</int>
+								<int key="NSCellFlags2">268436544</int>
+								<string key="NSContents"/>
+								<reference key="NSSupport" ref="672024657"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="397782954"/>
+								<bool key="NSDrawsBackground">YES</bool>
+								<object class="NSColor" key="NSBackgroundColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textBackgroundColor</string>
+									<object class="NSColor" key="NSColor">
+										<int key="NSColorSpace">3</int>
+										<bytes key="NSWhite">MQA</bytes>
+									</object>
+								</object>
+								<object class="NSColor" key="NSTextColor">
+									<int key="NSColorSpace">6</int>
+									<string key="NSCatalogName">System</string>
+									<string key="NSColorName">textColor</string>
+									<reference key="NSColor" ref="505464029"/>
+								</object>
+								<object class="NSArray" key="NSAllowedInputLocales">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>NSAllRomanInputSourcesLocaleIdentifier</string>
+								</object>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="1000243235">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{94, 13}, {82, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="49566844"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="900122769">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Open</string>
+								<reference key="NSSupport" ref="672024657"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="1000243235"/>
+								<int key="NSButtonFlags">-2038284288</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="49566844">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">268</int>
+							<string key="NSFrame">{{296, 13}, {82, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="168661615">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Cancel</string>
+								<reference key="NSSupport" ref="672024657"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="49566844"/>
+								<int key="NSButtonFlags">-2038284288</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">Gw</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+					</object>
+					<string key="NSFrameSize">{392, 133}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="85778589"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="748157544"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">Passphrase</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="397782954"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">Open:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1000243235"/>
+					</object>
+					<int key="connectionID">27</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">Cancel:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="49566844"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="748157544"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="312036702"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="312036702"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="85778589"/>
+							<reference ref="397782954"/>
+							<reference ref="1000243235"/>
+							<reference ref="697134294"/>
+							<reference ref="49566844"/>
+						</object>
+						<reference key="parent" ref="748157544"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">7</int>
+						<reference key="object" ref="85778589"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="478857961"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">8</int>
+						<reference key="object" ref="478857961"/>
+						<reference key="parent" ref="85778589"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">11</int>
+						<reference key="object" ref="697134294"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="790924092"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">12</int>
+						<reference key="object" ref="790924092"/>
+						<reference key="parent" ref="697134294"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="397782954"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="56735834"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="56735834"/>
+						<reference key="parent" ref="397782954"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">21</int>
+						<reference key="object" ref="1000243235"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="900122769"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">22</int>
+						<reference key="object" ref="900122769"/>
+						<reference key="parent" ref="1000243235"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">23</int>
+						<reference key="object" ref="49566844"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="168661615"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">24</int>
+						<reference key="object" ref="168661615"/>
+						<reference key="parent" ref="49566844"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>11.IBPluginDependency</string>
+					<string>12.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>2.IBWindowTemplateEditedContentRect</string>
+					<string>2.NSWindowTemplate.visibleAtLaunch</string>
+					<string>21.IBPluginDependency</string>
+					<string>22.IBPluginDependency</string>
+					<string>23.IBPluginDependency</string>
+					<string>24.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>7.IBPluginDependency</string>
+					<string>8.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{319, 371}, {606, 354}}</string>
+					<boolean value="YES"/>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">28</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">OpenFileFromFinder</string>
+					<string key="superclassName">NSWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/OpenFileFromFinder.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">OpenFileFromFinderController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>Cancel:</string>
+							<string>Open:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>id</string>
+							<string>id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>Cancel:</string>
+							<string>Open:</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBActionInfo">
+								<string key="name">Cancel:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+							<object class="IBActionInfo">
+								<string key="name">Open:</string>
+								<string key="candidateClassName">id</string>
+							</object>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<string key="NS.key.0">Passphrase</string>
+						<string key="NS.object.0">NSSecureTextField</string>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<string key="NS.key.0">Passphrase</string>
+						<object class="IBToOneOutletInfo" key="NS.object.0">
+							<string key="name">Passphrase</string>
+							<string key="candidateClassName">NSSecureTextField</string>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/OpenFileFromFinderController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<string key="NS.key.0">AxCryptIcon128</string>
+			<string key="NS.object.0">{128, 128}</string>
+		</object>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinderController.cs b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinderController.cs
new file mode 100644
index 0000000..07f09dc
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/OpenFileFromFinderController.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac.Windows
+{
+	public partial class OpenFileFromFinderController : MonoMac.AppKit.NSWindowController
+	{
+		public event Action<string> UserChoseOpen;
+		public event Action UserChoseCancel;
+
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public OpenFileFromFinderController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public OpenFileFromFinderController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		// Call to load from the XIB/NIB file
+		public OpenFileFromFinderController () : base ("OpenFileFromFinder")
+		{
+			Initialize ();
+		}
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		#endregion
+
+		public override void WindowDidLoad ()
+		{
+			base.WindowDidLoad ();
+			Passphrase.EditingEnded += (object sender, EventArgs e) => {
+				Open (sender as NSObject);
+			};
+		}
+		
+		//strongly typed window accessor
+		public new OpenFileFromFinder Window {
+			get {
+				return (OpenFileFromFinder)base.Window;
+			}
+		}
+
+		partial void Open(NSObject sender) {
+			if (UserChoseOpen != null)
+				UserChoseOpen(Passphrase.StringValue);
+			Dispose();
+		}
+
+		partial void Cancel(NSObject sender) {
+			if (UserChoseCancel != null)
+				UserChoseCancel();
+			Dispose ();
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.cs b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.cs
new file mode 100644
index 0000000..e4d9be5
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac
+{
+	public partial class VersionInformationWindow : MonoMac.AppKit.NSWindow
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public VersionInformationWindow (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public VersionInformationWindow (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		// Shared initialization code
+		void Initialize ()
+		{
+		}
+		#endregion
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.designer.cs b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.designer.cs
new file mode 100644
index 0000000..c21d3d4
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.designer.cs
@@ -0,0 +1,61 @@
+// WARNING
+//
+// This file has been generated automatically by Xamarin Studio to store outlets and
+// actions made in the Xcode designer. If it is removed, they will be lost.
+// Manual changes to this file may not be handled correctly.
+//
+using MonoMac.Foundation;
+
+namespace Axantum.AxCrypt.Mac
+{
+	[Register ("VersionInformationWindowController")]
+	partial class VersionInformationWindowController
+	{
+		[Outlet]
+		MonoMac.AppKit.NSTextField versionLabel { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSButton showOnNextExecution { get; set; }
+
+		[Outlet]
+		MonoMac.WebKit.WebView versionInformation { get; set; }
+
+		[Outlet]
+		MonoMac.AppKit.NSProgressIndicator progressIndicator { get; set; }
+
+		[Action ("closeWindow:")]
+		partial void closeWindow (MonoMac.Foundation.NSObject sender);
+		
+		void ReleaseDesignerOutlets ()
+		{
+			if (versionLabel != null) {
+				versionLabel.Dispose ();
+				versionLabel = null;
+			}
+
+			if (showOnNextExecution != null) {
+				showOnNextExecution.Dispose ();
+				showOnNextExecution = null;
+			}
+
+			if (versionInformation != null) {
+				versionInformation.Dispose ();
+				versionInformation = null;
+			}
+
+			if (progressIndicator != null) {
+				progressIndicator.Dispose ();
+				progressIndicator = null;
+			}
+		}
+	}
+
+	[Register ("VersionInformationWindow")]
+	partial class VersionInformationWindow
+	{
+		
+		void ReleaseDesignerOutlets ()
+		{
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.xib b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.xib
new file mode 100644
index 0000000..22bb127
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindow.xib
@@ -0,0 +1,489 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.10">
+	<data>
+		<int key="IBDocument.SystemTarget">1080</int>
+		<string key="IBDocument.SystemVersion">12D78</string>
+		<string key="IBDocument.InterfaceBuilderVersion">3084</string>
+		<string key="IBDocument.AppKitVersion">1187.37</string>
+		<string key="IBDocument.HIToolboxVersion">626.00</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSArray" key="dict.sortedKeys">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				<string>com.apple.WebKitIBPlugin</string>
+			</object>
+			<object class="NSArray" key="dict.values">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<string>3084</string>
+				<string>2053</string>
+			</object>
+		</object>
+		<object class="NSArray" key="IBDocument.IntegratedClassDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>NSButton</string>
+			<string>NSButtonCell</string>
+			<string>NSCustomObject</string>
+			<string>NSProgressIndicator</string>
+			<string>NSView</string>
+			<string>NSWindowTemplate</string>
+			<string>WebView</string>
+		</object>
+		<object class="NSArray" key="IBDocument.PluginDependencies">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+			<string>com.apple.WebKitIBPlugin</string>
+		</object>
+		<object class="NSMutableDictionary" key="IBDocument.Metadata">
+			<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
+			<integer value="1" key="NS.object.0"/>
+		</object>
+		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
+			<bool key="EncodedWithXMLCoder">YES</bool>
+			<object class="NSCustomObject" id="1001">
+				<string key="NSClassName">VersionInformationWindowController</string>
+			</object>
+			<object class="NSCustomObject" id="1003">
+				<string key="NSClassName">FirstResponder</string>
+			</object>
+			<object class="NSCustomObject" id="1004">
+				<string key="NSClassName">NSApplication</string>
+			</object>
+			<object class="NSWindowTemplate" id="748157544">
+				<int key="NSWindowStyleMask">15</int>
+				<int key="NSWindowBacking">2</int>
+				<string key="NSWindowRect">{{131, 74}, {606, 332}}</string>
+				<int key="NSWTFlags">611844096</int>
+				<string key="NSWindowTitle">AxCrypt for Mac - Version Information</string>
+				<string key="NSWindowClass">VersionInformationWindow</string>
+				<nil key="NSViewClass"/>
+				<nil key="NSUserInterfaceItemIdentifier"/>
+				<object class="NSView" key="NSWindowView" id="312036702">
+					<reference key="NSNextResponder"/>
+					<int key="NSvFlags">256</int>
+					<object class="NSMutableArray" key="NSSubviews">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSButton" id="403739627">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">289</int>
+							<string key="NSFrame">{{465, 13}, {127, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="788218779">
+								<int key="NSCellFlags">67108864</int>
+								<int key="NSCellFlags2">134217728</int>
+								<string key="NSContents">Close window</string>
+								<object class="NSFont" key="NSSupport" id="845978989">
+									<string key="NSName">LucidaGrande</string>
+									<double key="NSSize">13</double>
+									<int key="NSfFlags">1044</int>
+								</object>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="403739627"/>
+								<int key="NSButtonFlags">-2038284288</int>
+								<int key="NSButtonFlags2">129</int>
+								<string key="NSAlternateContents"/>
+								<string type="base64-UTF8" key="NSKeyEquivalent">DQ</string>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="NSButton" id="1037379051">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">292</int>
+							<string key="NSFrame">{{18, 21}, {338, 18}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView" ref="403739627"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<bool key="NSEnabled">YES</bool>
+							<object class="NSButtonCell" key="NSCell" id="925835129">
+								<int key="NSCellFlags">-2080374784</int>
+								<int key="NSCellFlags2">268435456</int>
+								<string key="NSContents">Show this window next time I start the application</string>
+								<reference key="NSSupport" ref="845978989"/>
+								<string key="NSCellIdentifier">_NS:9</string>
+								<reference key="NSControlView" ref="1037379051"/>
+								<int key="NSButtonFlags">1211912448</int>
+								<int key="NSButtonFlags2">2</int>
+								<object class="NSCustomResource" key="NSNormalImage">
+									<string key="NSClassName">NSImage</string>
+									<string key="NSResourceName">NSSwitch</string>
+								</object>
+								<object class="NSButtonImageSource" key="NSAlternateImage">
+									<string key="NSImageName">NSSwitch</string>
+								</object>
+								<string key="NSAlternateContents"/>
+								<string key="NSKeyEquivalent"/>
+								<int key="NSPeriodicDelay">200</int>
+								<int key="NSPeriodicInterval">25</int>
+							</object>
+							<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
+						</object>
+						<object class="WebView" id="118254000">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">274</int>
+							<object class="NSMutableSet" key="NSDragTypes">
+								<bool key="EncodedWithXMLCoder">YES</bool>
+								<object class="NSArray" key="set.sortedObjects">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<string>Apple HTML pasteboard type</string>
+									<string>Apple PDF pasteboard type</string>
+									<string>Apple PICT pasteboard type</string>
+									<string>Apple URL pasteboard type</string>
+									<string>Apple Web Archive pasteboard type</string>
+									<string>NSColor pasteboard type</string>
+									<string>NSFilenamesPboardType</string>
+									<string>NSStringPboardType</string>
+									<string>NeXT RTFD pasteboard type</string>
+									<string>NeXT Rich Text Format v1.0 pasteboard type</string>
+									<string>NeXT TIFF v4.0 pasteboard type</string>
+									<string>WebURLsWithTitlesPboardType</string>
+									<string>public.png</string>
+									<string>public.url</string>
+									<string>public.url-name</string>
+								</object>
+							</object>
+							<string key="NSFrame">{{20, 45}, {566, 267}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<reference key="NSNextKeyView"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="FrameName"/>
+							<string key="GroupName"/>
+							<object class="WebPreferences" key="Preferences">
+								<string key="Identifier"/>
+								<object class="NSMutableDictionary" key="Values">
+									<bool key="EncodedWithXMLCoder">YES</bool>
+									<object class="NSArray" key="dict.sortedKeys">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<string>WebKitDefaultFixedFontSize</string>
+										<string>WebKitDefaultFontSize</string>
+										<string>WebKitJavaEnabled</string>
+										<string>WebKitJavaScriptCanOpenWindowsAutomatically</string>
+										<string>WebKitMinimumFontSize</string>
+										<string>WebKitPluginsEnabled</string>
+									</object>
+									<object class="NSArray" key="dict.values">
+										<bool key="EncodedWithXMLCoder">YES</bool>
+										<integer value="12"/>
+										<integer value="12"/>
+										<boolean value="NO"/>
+										<boolean value="NO"/>
+										<integer value="1"/>
+										<boolean value="NO"/>
+									</object>
+								</object>
+							</object>
+							<bool key="UseBackForwardList">YES</bool>
+							<bool key="AllowsUndo">YES</bool>
+						</object>
+						<object class="NSProgressIndicator" id="137277316">
+							<reference key="NSNextResponder" ref="312036702"/>
+							<int key="NSvFlags">8460</int>
+							<string key="NSFrame">{{287, 162}, {32, 32}}</string>
+							<reference key="NSSuperview" ref="312036702"/>
+							<reference key="NSWindow"/>
+							<string key="NSReuseIdentifierKey">_NS:9</string>
+							<string key="NSHuggingPriority">{250, 250}</string>
+							<int key="NSpiFlags">28687</int>
+							<double key="NSMaxValue">100</double>
+						</object>
+					</object>
+					<string key="NSFrameSize">{606, 332}</string>
+					<reference key="NSSuperview"/>
+					<reference key="NSWindow"/>
+					<reference key="NSNextKeyView" ref="118254000"/>
+				</object>
+				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
+				<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
+				<bool key="NSWindowIsRestorable">YES</bool>
+			</object>
+		</object>
+		<object class="IBObjectContainer" key="IBDocument.Objects">
+			<object class="NSMutableArray" key="connectionRecords">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">window</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="748157544"/>
+					</object>
+					<int key="connectionID">6</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">showOnNextExecution</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="1037379051"/>
+					</object>
+					<int key="connectionID">25</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBActionConnection" key="connection">
+						<string key="label">closeWindow:</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="403739627"/>
+					</object>
+					<int key="connectionID">26</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionInformstion</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="118254000"/>
+					</object>
+					<int key="connectionID">28</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">versionInformation</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="118254000"/>
+					</object>
+					<int key="connectionID">29</int>
+				</object>
+				<object class="IBConnectionRecord">
+					<object class="IBOutletConnection" key="connection">
+						<string key="label">progressIndicator</string>
+						<reference key="source" ref="1001"/>
+						<reference key="destination" ref="137277316"/>
+					</object>
+					<int key="connectionID">32</int>
+				</object>
+			</object>
+			<object class="IBMutableOrderedSet" key="objectRecords">
+				<object class="NSArray" key="orderedObjects">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<object class="IBObjectRecord">
+						<int key="objectID">0</int>
+						<object class="NSArray" key="object" id="0">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+						</object>
+						<reference key="children" ref="1000"/>
+						<nil key="parent"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-2</int>
+						<reference key="object" ref="1001"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">File's Owner</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-1</int>
+						<reference key="object" ref="1003"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">First Responder</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">-3</int>
+						<reference key="object" ref="1004"/>
+						<reference key="parent" ref="0"/>
+						<string key="objectName">Application</string>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">2</int>
+						<reference key="object" ref="748157544"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="312036702"/>
+						</object>
+						<reference key="parent" ref="0"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">3</int>
+						<reference key="object" ref="312036702"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="1037379051"/>
+							<reference ref="403739627"/>
+							<reference ref="118254000"/>
+							<reference ref="137277316"/>
+						</object>
+						<reference key="parent" ref="748157544"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">13</int>
+						<reference key="object" ref="403739627"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="788218779"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">14</int>
+						<reference key="object" ref="788218779"/>
+						<reference key="parent" ref="403739627"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">15</int>
+						<reference key="object" ref="1037379051"/>
+						<object class="NSMutableArray" key="children">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<reference ref="925835129"/>
+						</object>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">16</int>
+						<reference key="object" ref="925835129"/>
+						<reference key="parent" ref="1037379051"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">27</int>
+						<reference key="object" ref="118254000"/>
+						<reference key="parent" ref="312036702"/>
+					</object>
+					<object class="IBObjectRecord">
+						<int key="objectID">31</int>
+						<reference key="object" ref="137277316"/>
+						<reference key="parent" ref="312036702"/>
+					</object>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="flattenedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="NSArray" key="dict.sortedKeys">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>-1.IBPluginDependency</string>
+					<string>-2.IBPluginDependency</string>
+					<string>-3.IBPluginDependency</string>
+					<string>13.IBPluginDependency</string>
+					<string>14.IBPluginDependency</string>
+					<string>15.IBPluginDependency</string>
+					<string>16.IBPluginDependency</string>
+					<string>2.IBPluginDependency</string>
+					<string>2.IBWindowTemplateEditedContentRect</string>
+					<string>2.NSWindowTemplate.visibleAtLaunch</string>
+					<string>27.IBPluginDependency</string>
+					<string>3.IBPluginDependency</string>
+					<string>31.IBPluginDependency</string>
+				</object>
+				<object class="NSArray" key="dict.values">
+					<bool key="EncodedWithXMLCoder">YES</bool>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>{{319, 371}, {606, 354}}</string>
+					<boolean value="YES"/>
+					<string>com.apple.WebKitIBPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
+				</object>
+			</object>
+			<object class="NSMutableDictionary" key="unlocalizedProperties">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="activeLocalization"/>
+			<object class="NSMutableDictionary" key="localizations">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<reference key="dict.sortedKeys" ref="0"/>
+				<reference key="dict.values" ref="0"/>
+			</object>
+			<nil key="sourceID"/>
+			<int key="maxID">32</int>
+		</object>
+		<object class="IBClassDescriber" key="IBDocument.Classes">
+			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
+				<bool key="EncodedWithXMLCoder">YES</bool>
+				<object class="IBPartialClassDescription">
+					<string key="className">VersionInformationWindow</string>
+					<string key="superclassName">NSWindow</string>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/VersionInformationWindow.h</string>
+					</object>
+				</object>
+				<object class="IBPartialClassDescription">
+					<string key="className">VersionInformationWindowController</string>
+					<string key="superclassName">NSWindowController</string>
+					<object class="NSMutableDictionary" key="actions">
+						<string key="NS.key.0">closeWindow:</string>
+						<string key="NS.object.0">id</string>
+					</object>
+					<object class="NSMutableDictionary" key="actionInfosByName">
+						<string key="NS.key.0">closeWindow:</string>
+						<object class="IBActionInfo" key="NS.object.0">
+							<string key="name">closeWindow:</string>
+							<string key="candidateClassName">id</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="outlets">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>progressIndicator</string>
+							<string>showOnNextExecution</string>
+							<string>versionInformation</string>
+							<string>versionLabel</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>NSProgressIndicator</string>
+							<string>NSButton</string>
+							<string>WebView</string>
+							<string>NSTextField</string>
+						</object>
+					</object>
+					<object class="NSMutableDictionary" key="toOneOutletInfosByName">
+						<bool key="EncodedWithXMLCoder">YES</bool>
+						<object class="NSArray" key="dict.sortedKeys">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<string>progressIndicator</string>
+							<string>showOnNextExecution</string>
+							<string>versionInformation</string>
+							<string>versionLabel</string>
+						</object>
+						<object class="NSArray" key="dict.values">
+							<bool key="EncodedWithXMLCoder">YES</bool>
+							<object class="IBToOneOutletInfo">
+								<string key="name">progressIndicator</string>
+								<string key="candidateClassName">NSProgressIndicator</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">showOnNextExecution</string>
+								<string key="candidateClassName">NSButton</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">versionInformation</string>
+								<string key="candidateClassName">WebView</string>
+							</object>
+							<object class="IBToOneOutletInfo">
+								<string key="name">versionLabel</string>
+								<string key="candidateClassName">NSTextField</string>
+							</object>
+						</object>
+					</object>
+					<object class="IBClassDescriptionSource" key="sourceIdentifier">
+						<string key="majorKey">IBProjectSource</string>
+						<string key="minorKey">./Classes/VersionInformationWindowController.h</string>
+					</object>
+				</object>
+			</object>
+		</object>
+		<int key="IBDocument.localizationMode">0</int>
+		<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
+		<object class="NSMutableDictionary" key="IBDocument.PluginDeclaredDevelopmentDependencies">
+			<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3</string>
+			<integer value="3000" key="NS.object.0"/>
+		</object>
+		<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
+		<int key="IBDocument.defaultPropertyAccessControl">3</int>
+		<object class="NSMutableDictionary" key="IBDocument.LastKnownImageSizes">
+			<string key="NS.key.0">NSSwitch</string>
+			<string key="NS.object.0">{15, 15}</string>
+		</object>
+	</data>
+</archive>
diff --git a/Axantum.AxCrypt.Mac/Windows/VersionInformationWindowController.cs b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindowController.cs
new file mode 100644
index 0000000..4fb25ff
--- /dev/null
+++ b/Axantum.AxCrypt.Mac/Windows/VersionInformationWindowController.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using MonoMac.Foundation;
+using MonoMac.AppKit;
+
+namespace Axantum.AxCrypt.Mac
+{
+	public partial class VersionInformationWindowController : MonoMac.AppKit.NSWindowController
+	{
+		#region Constructors
+		
+		// Called when created from unmanaged code
+		public VersionInformationWindowController (IntPtr handle) : base (handle)
+		{
+			Initialize ();
+		}
+		// Called when created directly from a XIB file
+		[Export ("initWithCoder:")]
+		public VersionInformationWindowController (NSCoder coder) : base (coder)
+		{
+			Initialize ();
+		}
+		// Call to load from the XIB/NIB file
+		public VersionInformationWindowController () : base ("VersionInformationWindow")
+		{
+			Initialize ();
+		}
+		// Shared initialization code
+		void Initialize ()
+		{
+			// 
+		}
+		#endregion
+
+		public override void WindowDidLoad ()
+		{
+			progressIndicator.StartAnimation (this);
+			versionInformation.CommitedLoad += delegate {
+				progressIndicator.StopAnimation(this);
+			};
+
+			NSUrlRequest request = NSUrlRequest.FromUrl (NSUrl.FromString(AppController.VersionInformationUrl));
+			versionInformation.MainFrame.LoadRequest (request);
+			showOnNextExecution.State = ShouldShowVersionInformation ? NSCellStateValue.On : NSCellStateValue.Off;
+
+			base.WindowDidLoad ();
+		}
+		
+		//strongly typed window accessor
+		public new VersionInformationWindow Window {
+			get {
+				return (VersionInformationWindow)base.Window;
+			}
+		}
+
+		private static string VersionInformationUserDefaultsKey { get { return "Have Seen Version Information For " + AppController.VERSION; } }
+
+		public static bool ShouldShowVersionInformation {
+			get {
+				return !NSUserDefaults.StandardUserDefaults.BoolForKey (VersionInformationUserDefaultsKey);
+			}
+			private set {
+				NSUserDefaults.StandardUserDefaults.SetBool (!value, VersionInformationUserDefaultsKey);
+			}
+		}
+
+		partial void closeWindow (NSObject sender)
+		{
+			ShouldShowVersionInformation = this.showOnNextExecution.State == NSCellStateValue.On;
+			Dispose ();
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.Mono.Test/AboutThisAssembly.txt b/Axantum.AxCrypt.Mono.Test/AboutThisAssembly.txt
new file mode 100644
index 0000000..1313a14
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/AboutThisAssembly.txt
@@ -0,0 +1,10 @@
+About Axantum.AxCrypt.Mono.Test
+
+This assembly contains best-effort tests for Axantum.AxCrypt.Mono . By the very
+nature of things, since these are the implementations that interact directly with
+the platform, it is not always practical to actually design tests. But when this
+is feasible, it should be done.
+
+Code coverage is not required to be 100% .
+
+FxCop should pass without complaint.
diff --git a/Axantum.AxCrypt.Mono.Test/Axantum.AxCrypt.Mono.Test.csproj b/Axantum.AxCrypt.Mono.Test/Axantum.AxCrypt.Mono.Test.csproj
new file mode 100644
index 0000000..65abb0f
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/Axantum.AxCrypt.Mono.Test.csproj
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{79C4901A-BCAA-49AA-A789-6A8F97ACC881}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Mono.Test</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Mono.Test</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+    <Reference Include="nunit.framework">
+      <HintPath>..\SolutionItems\nunit.framework.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="TestDelegateTraceListener.cs" />
+    <Compile Include="TestLogging.cs" />
+    <Compile Include="TestRuntimeEnvironment.cs" />
+    <Compile Include="TestRuntimeFileInfo.cs" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <DependentUpon>Resources.resx</DependentUpon>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959F7F85-C98B-4876-971A-9036224578E4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj">
+      <Project>{CE9E8614-8DC5-4757-9384-3C416AB61A47}</Project>
+      <Name>Axantum.AxCrypt.Mono</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="AboutThisAssembly.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+  <ItemGroup>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono.Test/AxantumStrongName.pfx b/Axantum.AxCrypt.Mono.Test/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Mono.Test/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Mono.Test/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Mono.Test/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0d9c08c
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/Properties/AssemblyInfo.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is only for unit tests and is never deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+
+[assembly: AssemblyTitle("Axantum.AxCrypt.Mono.Test")]
+[assembly: AssemblyDescription("NUnit tests for Axantum.AxCrypt.Mono")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © 2014 Svante Seleborg")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("a213442a-8e64-4466-8ed4-01ee044e4ac0")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: CLSCompliant(true)]
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono.Test/Properties/Resources.Designer.cs b/Axantum.AxCrypt.Mono.Test/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..3fc10c1
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/Properties/Resources.Designer.cs
@@ -0,0 +1,49 @@
+// ------------------------------------------------------------------------------
+//  <autogenerated>
+//      This code was generated by a tool.
+//      Mono Runtime Version: 4.0.30319.17020
+// 
+//      Changes to this file may cause incorrect behavior and will be lost if 
+//      the code is regenerated.
+//  </autogenerated>
+// ------------------------------------------------------------------------------
+
+namespace Axantum.AxCrypt.Mono.Test {
+    using System;
+    
+    
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static System.Resources.ResourceManager resourceMan;
+        
+        private static System.Globalization.CultureInfo resourceCulture;
+        
+        [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.Equals(null, resourceMan)) {
+                    System.Resources.ResourceManager temp = new System.Resources.ResourceManager("Axantum.AxCrypt.Mono.Test.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}
diff --git a/Axantum.AxCrypt.Mono.Test/Properties/Resources.resx b/Axantum.AxCrypt.Mono.Test/Properties/Resources.resx
new file mode 100644
index 0000000..a152c4c
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/Properties/Resources.resx
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+	<resheader name="resmimetype">
+		<value>text/microsoft-resx</value>
+	</resheader>
+	<resheader name="version">
+		<value>2.0</value>
+	</resheader>
+	<resheader name="reader">
+		<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+	</resheader>
+	<resheader name="writer">
+		<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+	</resheader>
+</root>
diff --git a/Axantum.AxCrypt.Mono.Test/TestDelegateTraceListener.cs b/Axantum.AxCrypt.Mono.Test/TestDelegateTraceListener.cs
new file mode 100644
index 0000000..318a72a
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/TestDelegateTraceListener.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono.Test
+{
+    [TestFixture]
+    public static class TestDelegateTraceListener
+    {
+        [SetUp]
+        public static void Setup()
+        {
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+        }
+
+        [Test]
+        public static void TestIt()
+        {
+            string listened = null;
+            DelegateTraceListener listener = new DelegateTraceListener("Test Listener", (string message) => { listened = message; });
+
+            listener.Write(1);
+            Assert.That(listened, Is.Null, "The listener should buffer until a new line is received.");
+
+            listener.WriteLine(String.Empty);
+            Assert.That(listened, Is.EqualTo("1" + Environment.NewLine), "The buffer should be emptied as soon as a New Line is received.");
+
+            listener.Write("Hello" + Environment.NewLine + "New World");
+            Assert.That(listened, Is.EqualTo("Hello" + Environment.NewLine), "The buffer should contain text up to the last new line but not more.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono.Test/TestLogging.cs b/Axantum.AxCrypt.Mono.Test/TestLogging.cs
new file mode 100644
index 0000000..e6af862
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/TestLogging.cs
@@ -0,0 +1,200 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Runtime;
+using NUnit.Framework;
+using System;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono.Test
+{
+    [TestFixture]
+    public static class TestLogging
+    {
+        [SetUp]
+        public static void Setup()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+            Factory.Instance.Singleton<ILogging>(() => new Logging());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+        }
+
+        [Test]
+        public static void TestLoggingLevels()
+        {
+            Instance.Log.SetLevel(LogLevel.Fatal);
+            Assert.That(Instance.Log.IsDebugEnabled, Is.False, "When logging is off, Debug should be off.");
+            Assert.That(Instance.Log.IsInfoEnabled, Is.False, "When logging is off, Info should be off.");
+            Assert.That(Instance.Log.IsWarningEnabled, Is.False, "When logging is off, Warning should be off.");
+            Assert.That(Instance.Log.IsErrorEnabled, Is.False, "When logging is off, Error should be off.");
+
+            Instance.Log.SetLevel(LogLevel.Error);
+            Assert.That(Instance.Log.IsDebugEnabled, Is.False, "When Error is enabled, Debug should be off.");
+            Assert.That(Instance.Log.IsInfoEnabled, Is.False, "When Error is enabled, Info should be off.");
+            Assert.That(Instance.Log.IsWarningEnabled, Is.False, "When Error is enabled, Warning should be off.");
+            Assert.That(Instance.Log.IsErrorEnabled, Is.True, "When Error is enabled, Error should be on.");
+
+            Instance.Log.SetLevel(LogLevel.Warning);
+            Assert.That(Instance.Log.IsDebugEnabled, Is.False, "When Warning is enabled, Debug should be off.");
+            Assert.That(Instance.Log.IsInfoEnabled, Is.False, "When Warning is enabled, Info should be off.");
+            Assert.That(Instance.Log.IsWarningEnabled, Is.True, "When Warning is enabled, Warning should be on.");
+            Assert.That(Instance.Log.IsErrorEnabled, Is.True, "When Warning is enabled, Error should be on.");
+
+            Instance.Log.SetLevel(LogLevel.Info);
+            Assert.That(Instance.Log.IsDebugEnabled, Is.False, "When Info is enabled, Debug should be off.");
+            Assert.That(Instance.Log.IsInfoEnabled, Is.True, "When Info is enabled, Info should be on.");
+            Assert.That(Instance.Log.IsWarningEnabled, Is.True, "When Info is enabled, Warning should be on.");
+            Assert.That(Instance.Log.IsErrorEnabled, Is.True, "When Info is enabled, Error should be on.");
+
+            Instance.Log.SetLevel(LogLevel.Debug);
+            Assert.That(Instance.Log.IsDebugEnabled, Is.True, "When Verbose is enabled, Debug should be on.");
+            Assert.That(Instance.Log.IsInfoEnabled, Is.True, "When Verbose is enabled, Info should be on.");
+            Assert.That(Instance.Log.IsWarningEnabled, Is.True, "When Verbose is enabled, Warning should be on.");
+            Assert.That(Instance.Log.IsErrorEnabled, Is.True, "When Verbose is enabled, Error should be on.");
+        }
+
+        [Test]
+        public static void TestLoggingListenerAndLevels()
+        {
+            string listenerMessage = null;
+
+            DelegateTraceListener traceListener = new DelegateTraceListener("AxCryptTestListener", (string message) =>
+            {
+                listenerMessage = (listenerMessage ?? String.Empty) + message;
+            });
+
+            Trace.Listeners.Add(traceListener);
+            try
+            {
+                Instance.Log.SetLevel(LogLevel.Fatal);
+
+                listenerMessage = null;
+                Instance.Log.LogDebug("Verbose" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is off, Verbose logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogInfo("Info" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is off, Info logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogWarning("Warning" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is off, Warning logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogError("Error" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is off, Error logging should not generate a message.");
+
+                Instance.Log.SetLevel(LogLevel.Error);
+
+                listenerMessage = null;
+                Instance.Log.LogDebug("Verbose" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Error, Verbose logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogInfo("Info" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Error, Info logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogWarning("Warning" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Error, Warning logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogFatal("Fatal" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Fatal"), "When logging is Error, Fatal logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogError("Error" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Error"), "When logging is Error, Error logging should generate a message.");
+
+                Instance.Log.SetLevel(LogLevel.Warning);
+
+                listenerMessage = null;
+                Instance.Log.LogDebug("Verbose" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Warning, Verbose logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogInfo("Info" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Warning, Info logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogWarning("Warning" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Warning"), "When logging is Warning, Warning logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogError("Error" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Error"), "When logging is Warning, Error logging should generate a message.");
+
+                Instance.Log.SetLevel(LogLevel.Info);
+
+                listenerMessage = null;
+                Instance.Log.LogDebug("Verbose" + Environment.NewLine);
+                Assert.That(listenerMessage, Is.EqualTo(null), "When logging is Info, Verbose logging should not generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogInfo("Info" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Info"), "When logging is Info, Info logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogWarning("Warning" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Warning"), "When logging is Info, Warning logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogError("Error" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Error"), "When logging is Info, Error logging should generate a message.");
+
+                Instance.Log.SetLevel(LogLevel.Debug);
+
+                listenerMessage = null;
+                Instance.Log.LogDebug("Verbose" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Verbose"), "When logging is Verbose, Verbose logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogInfo("Info" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Info"), "When logging is Verbose, Info logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogWarning("Warning" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Warning"), "When logging is Verbose, Warning logging should generate a message.");
+
+                listenerMessage = null;
+                Instance.Log.LogError("Error" + Environment.NewLine);
+                Assert.That(listenerMessage.Contains("Error"), "When logging is Verbose, Error logging should generate a message.");
+            }
+            finally
+            {
+                Trace.Listeners.Remove(traceListener);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono.Test/TestRuntimeEnvironment.cs b/Axantum.AxCrypt.Mono.Test/TestRuntimeEnvironment.cs
new file mode 100644
index 0000000..ebc8130
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/TestRuntimeEnvironment.cs
@@ -0,0 +1,131 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono.Test
+{
+    [TestFixture]
+    public static class TestRuntimeEnvironment
+    {
+        private static string _workFolderPath;
+
+        [SetUp]
+        public static void Setup()
+        {
+            _workFolderPath = Path.Combine(Path.GetTempPath(), @"Axantum.AxCrypt.Mono.Test.TestRuntimeEnvironment\");
+            Directory.CreateDirectory(_workFolderPath);
+
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new RuntimeFileInfo(path));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<WorkFolder>(() => new WorkFolder(_workFolderPath));
+            Factory.Instance.Singleton<ILogging>(() => new Logging());
+            Factory.Instance.Singleton<IRandomGenerator>(() => new RandomGenerator());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+            Directory.Delete(_workFolderPath, true);
+        }
+
+        [Test]
+        public static void TestAxCryptExtension()
+        {
+            Assert.That(OS.Current.AxCryptExtension, Is.EqualTo(".axx"), "Checking the standard AxCrypt extension.");
+        }
+
+        [Test]
+        public static void TestIfIsLittleEndian()
+        {
+            Assert.That(OS.Current.IsLittleEndian, Is.EqualTo(BitConverter.IsLittleEndian), "Checking endianess.");
+        }
+
+        [Test]
+        public static void TestRandomBytes()
+        {
+            byte[] randomBytes = Instance.RandomGenerator.Generate(100);
+            Assert.That(randomBytes.Length, Is.EqualTo(100), "Ensuring we really got the right number of bytes.");
+            Assert.That(randomBytes, Is.Not.EquivalentTo(new byte[100]), "It is not in practice possible that all zero bytes are returned by GetRandomBytes().");
+
+            randomBytes = Instance.RandomGenerator.Generate(1000);
+            double average = randomBytes.Average(b => b);
+            Assert.That(average >= 115 && average <= 140, "Unscientific, but the sample sequence should not vary much from a mean of 127.5, but was {0}".InvariantFormat(average));
+        }
+
+        [Test]
+        public static void TestRuntimeFileInfo()
+        {
+            IRuntimeFileInfo runtimeFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetTempPath(), "A File.txt"));
+            Assert.That(runtimeFileInfo is RuntimeFileInfo, "The instance returned should be of type RuntimeFileInfo");
+            Assert.That(runtimeFileInfo.Name, Is.EqualTo("A File.txt"));
+            runtimeFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(Path.GetTempPath(), "A File.txt"));
+            Assert.That(runtimeFileInfo.Name, Is.EqualTo("A File.txt"));
+        }
+
+        [Test]
+        public static void TestTemporaryDirectoryInfo()
+        {
+            IRuntimeFileInfo tempInfo = Factory.Instance.Singleton<WorkFolder>().FileInfo;
+            Assert.That(tempInfo is RuntimeFileInfo, "The instance returned should be of type RuntimeFileInfo");
+            IRuntimeFileInfo tempFileInfo = Factory.New<IRuntimeFileInfo>(Path.Combine(tempInfo.FullName, "AxCryptTestTemp.tmp"));
+            Assert.DoesNotThrow(() =>
+            {
+                try
+                {
+                    using (Stream stream = tempFileInfo.OpenWrite())
+                    {
+                    }
+                }
+                finally
+                {
+                    tempFileInfo.Delete();
+                }
+            }, "Write permissions should always be present in the temp directory.");
+        }
+
+        [Test]
+        public static void TestUtcNow()
+        {
+            DateTime utcNow = DateTime.UtcNow;
+            DateTime utcNowAgain = OS.Current.UtcNow;
+            Assert.That(utcNowAgain - utcNow < new TimeSpan(0, 0, 1), "The difference should not be greater than one second, that's not reasonable.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono.Test/TestRuntimeFileInfo.cs b/Axantum.AxCrypt.Mono.Test/TestRuntimeFileInfo.cs
new file mode 100644
index 0000000..c02e0b0
--- /dev/null
+++ b/Axantum.AxCrypt.Mono.Test/TestRuntimeFileInfo.cs
@@ -0,0 +1,153 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using NUnit.Framework;
+using System;
+using System.Globalization;
+using System.IO;
+
+namespace Axantum.AxCrypt.Mono.Test
+{
+    [TestFixture]
+    public static class TestRuntimeFileInfo
+    {
+        private static string _tempPath;
+
+        [SetUp]
+        public static void Setup()
+        {
+            _tempPath = Path.Combine(Path.GetTempPath(), "Axantum.AxCrypt.Mono.Test.TestRuntimeFileInfo");
+            Directory.CreateDirectory(_tempPath);
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new RuntimeFileInfo(path));
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<WorkFolder>(() => new WorkFolder(_tempPath));
+            Factory.Instance.Singleton<ILogging>(() => new Logging());
+        }
+
+        [TearDown]
+        public static void Teardown()
+        {
+            Factory.Instance.Clear();
+            Directory.Delete(_tempPath, true);
+        }
+
+        [Test]
+        public static void TestBadArguments()
+        {
+            Assert.Throws<ArgumentNullException>(() =>
+            {
+                RuntimeFileInfo rfi = new RuntimeFileInfo(null);
+
+                // Avoid FxCop error
+                Object.Equals(rfi, null);
+            });
+        }
+
+        [Test]
+        public static void TestCreateDirectory()
+        {
+            string testTempFolder = Path.Combine(Path.GetTempPath(), "AxantumTestCreateDirectory" + Path.DirectorySeparatorChar);
+            if (Directory.Exists(testTempFolder))
+            {
+                Directory.Delete(testTempFolder, true);
+            }
+            Assert.That(Directory.Exists(testTempFolder), Is.False, "The test folder should not exist now.");
+            IRuntimeFileInfo directoryInfo = new RuntimeFileInfo(testTempFolder);
+            directoryInfo.CreateFolder();
+            Assert.That(Directory.Exists(testTempFolder), Is.True, "The test folder should exist now.");
+            if (Directory.Exists(testTempFolder))
+            {
+                Directory.Delete(testTempFolder, true);
+            }
+        }
+
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times"), Test]
+        public static void TestMethods()
+        {
+            string tempFileName = Path.GetTempFileName();
+            IRuntimeFileInfo runtimeFileInfo = new RuntimeFileInfo(tempFileName);
+            try
+            {
+                using (Stream writeStream = runtimeFileInfo.OpenWrite())
+                {
+                    using (TextWriter writer = new StreamWriter(writeStream))
+                    {
+                        writer.Write("This is AxCrypt!");
+                    }
+                }
+                using (Stream readStream = runtimeFileInfo.OpenRead())
+                {
+                    using (TextReader reader = new StreamReader(readStream))
+                    {
+                        string text = reader.ReadToEnd();
+
+                        Assert.That(text, Is.EqualTo("This is AxCrypt!"), "What was written should be read.");
+                    }
+                }
+
+                DateTime dateTime = DateTime.Parse("2012-02-29 12:00:00", CultureInfo.GetCultureInfo("sv-SE"), DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
+                runtimeFileInfo.SetFileTimes(dateTime, dateTime + new TimeSpan(3, 0, 0), dateTime + new TimeSpan(5, 0, 0));
+                if (OS.Current.Platform == Platform.WindowsDesktop)
+                {
+                    Assert.That(runtimeFileInfo.CreationTimeUtc, Is.EqualTo(dateTime), "The creation time should be as set.");
+                }
+                else
+                {
+                    Assert.That(runtimeFileInfo.CreationTimeUtc, Is.EqualTo(dateTime + new TimeSpan(5, 0, 0)), "The creation time should be as last write time due to bug in Mono.");
+                }
+                Assert.That(runtimeFileInfo.LastAccessTimeUtc, Is.EqualTo(dateTime + new TimeSpan(3, 0, 0)), "The last access time should be as set.");
+                Assert.That(runtimeFileInfo.LastWriteTimeUtc, Is.EqualTo(dateTime + new TimeSpan(5, 0, 0)), "The last write time should be as set.");
+
+                Assert.That(runtimeFileInfo.FullName, Is.EqualTo(tempFileName), "The FullName should be the same as the underlying FileInfo.FullName.");
+
+                string otherTempFileName = runtimeFileInfo.FullName + ".copy";
+                IRuntimeFileInfo otherTempRuntimeFileInfo = new RuntimeFileInfo(otherTempFileName);
+                Assert.That(otherTempRuntimeFileInfo.IsExistingFile, Is.False, "The new temp file should not exist.");
+                Assert.That(runtimeFileInfo.IsExistingFile, Is.True, "The old temp file should exist.");
+                runtimeFileInfo.MoveTo(otherTempRuntimeFileInfo.FullName);
+                Assert.That(otherTempRuntimeFileInfo.IsExistingFile, Is.True, "The new temp file should exist after moving the old here.");
+                Assert.That(runtimeFileInfo.IsExistingFile, Is.True, "The old temp file should exist still because it has changed to refer to the new file.");
+            }
+            finally
+            {
+                runtimeFileInfo.Delete();
+            }
+            Assert.That(runtimeFileInfo.IsExistingFile, Is.False, "The file should have been deleted now.");
+
+            IRuntimeFileInfo notEncryptedRuntimeFileInfo = new RuntimeFileInfo("file.txt");
+            IRuntimeFileInfo encryptedRuntimeFileInfo = notEncryptedRuntimeFileInfo.CreateEncryptedName();
+            Assert.That(encryptedRuntimeFileInfo.Name, Is.EqualTo("file-txt.axx"), "The encrypted name should be as expected.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/AboutThisAssembly.txt b/Axantum.AxCrypt.Mono/AboutThisAssembly.txt
new file mode 100644
index 0000000..05f4df8
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/AboutThisAssembly.txt
@@ -0,0 +1,14 @@
+About Axantum.AxCrypt.Mono
+
+This assembly contains platform specific implementations for desktop Mono / desktop Windows.
+
+At this time, Mono and Windows are treated to be compatible and use the same implementation.
+
+A platform specific implementation assembly should implement IRuntimeEnvironment, and the
+interfaces exposed by methods and properties in that interface. This is currently:
+
+IFileWatcher, ILauncher, IRuntimeFileInfo, ITiming and IWebCaller.
+
+Code coverage is not required to be 100% here, but what reasonable can be tested should be.
+
+FxCop should pass without complaint.
diff --git a/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.csproj b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.csproj
new file mode 100644
index 0000000..bf8f7db
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.csproj
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{CE9E8614-8DC5-4757-9384-3C416AB61A47}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt.Mono</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt.Mono</AssemblyName>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile />
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="Microsoft.CSharp" />
+    <Reference Include="System.Security" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Portable\AxCryptHMACSHA1.cs" />
+    <Compile Include="DelayTimer.cs" />
+    <Compile Include="DelegateTraceListener.cs" />
+    <Compile Include="HttpRequestClient.cs" />
+    <Compile Include="HttpRequestServer.cs" />
+    <Compile Include="Launcher.cs" />
+    <Compile Include="Logging.cs" />
+    <Compile Include="Portable\CryptographyCryptoTransformWrapper.cs" />
+    <Compile Include="Portable\PortableHashAlgorithmWrapper.cs" />
+    <Compile Include="Portable\PortableHmacWrapper.cs" />
+    <Compile Include="Portable\PortableFactory.cs" />
+    <Compile Include="Portable\PortableCryptoStreamWrapper.cs" />
+    <Compile Include="Portable\PortableCryptoTransformWrapper.cs" />
+    <Compile Include="Portable\PortablePathImplementation.cs" />
+    <Compile Include="Portable\PortableRandomNumberGeneratorWrapper.cs" />
+    <Compile Include="Portable\PortableSymmetricAlgorithmWrapper.cs" />
+    <Compile Include="Portable\PortableSemaphoreWrapper.cs" />
+    <Compile Include="Portable\SingleThread.cs" />
+    <Compile Include="RuntimeEnvironment.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="RuntimeFileInfo.cs" />
+    <Compile Include="Sleep.cs" />
+    <Compile Include="ThreadWorker.cs" />
+    <Compile Include="Timing.cs" />
+    <Compile Include="WebCaller.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959F7F85-C98B-4876-971A-9036224578E4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+    <None Include="Properties\AssemblyInfo.template" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="AboutThisAssembly.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.projitems b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.projitems
new file mode 100644
index 0000000..c5d91ee
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.projitems
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
+    <HasSharedItems>true</HasSharedItems>
+    <SharedGUID>{E012DEFD-DD3A-411F-BDE3-6BCB12D96120}</SharedGUID>
+  </PropertyGroup>
+  <PropertyGroup Label="Configuration">
+    <Import_RootNamespace>Axantum.AxCrypt.Mono</Import_RootNamespace>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildThisFileDirectory)DelayTimer.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)DelegateTraceListener.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)HttpRequestClient.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)HttpRequestServer.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Launcher.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Logging.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)RuntimeEnvironment.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)RuntimeFileInfo.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Sleep.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)ThreadWorker.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Timing.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)WebCaller.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\AxCryptHMACSHA1.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\CryptographyCryptoTransformWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableCryptoStreamWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableCryptoTransformWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableFactory.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableHashAlgorithmWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableHmacWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortablePathImplementation.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableRandomNumberGeneratorWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableSemaphoreWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\PortableSymmetricAlgorithmWrapper.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)Portable\SingleThread.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="$(MSBuildThisFileDirectory)Portable\" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.shproj b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.shproj
new file mode 100644
index 0000000..3067311
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Axantum.AxCrypt.Mono.shproj
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <ProjectGuid>{E012DEFD-DD3A-411F-BDE3-6BCB12D96120}</ProjectGuid>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
+  <Import Project="Axantum.AxCrypt.Mono.projitems" Label="Shared" />
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/AxantumStrongName.pfx b/Axantum.AxCrypt.Mono/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt.Mono/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt.Mono/DelayTimer.cs b/Axantum.AxCrypt.Mono/DelayTimer.cs
new file mode 100644
index 0000000..21f8d80
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/DelayTimer.cs
@@ -0,0 +1,96 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+using System.Timers;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class DelayTimer : IDelayTimer
+    {
+        private Timer _timer = new Timer();
+
+        public DelayTimer()
+        {
+            _timer.AutoReset = false;
+            _timer.Elapsed += HandleTimerElapsedEvent;
+        }
+
+        private void HandleTimerElapsedEvent(object sender, ElapsedEventArgs e)
+        {
+            OnElapsed(new EventArgs());
+        }
+
+        protected virtual void OnElapsed(EventArgs e)
+        {
+            EventHandler<EventArgs> handler = Elapsed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void SetInterval(TimeSpan interval)
+        {
+            _timer.Enabled = false;
+            _timer.Interval = interval.TotalMilliseconds;
+        }
+
+        public event EventHandler<EventArgs> Elapsed;
+
+        public void Start()
+        {
+            _timer.Enabled = false;
+            _timer.Enabled = true;
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_timer != null)
+            {
+                _timer.Dispose();
+                _timer = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/DelegateTraceListener.cs b/Axantum.AxCrypt.Mono/DelegateTraceListener.cs
new file mode 100644
index 0000000..a889ad2
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/DelegateTraceListener.cs
@@ -0,0 +1,64 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class DelegateTraceListener : TraceListener
+    {
+        private Action<string> _trace;
+
+        private StringBuilder _buffer = new StringBuilder();
+
+        public DelegateTraceListener(string name, Action<string> trace)
+            : base(name)
+        {
+            _trace = trace;
+        }
+
+        public override void Write(string message)
+        {
+            int i;
+            while ((i = message.IndexOf(Environment.NewLine, StringComparison.Ordinal)) >= 0)
+            {
+                _buffer.Append(message.Substring(0, i + Environment.NewLine.Length));
+                _trace(_buffer.ToString());
+                _buffer.Length = 0;
+                message = message.Substring(i + Environment.NewLine.Length);
+            }
+            _buffer.Append(message);
+        }
+
+        public override void WriteLine(string message)
+        {
+            Write(message + Environment.NewLine);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/HttpRequestClient.cs b/Axantum.AxCrypt.Mono/HttpRequestClient.cs
new file mode 100644
index 0000000..30e7208
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/HttpRequestClient.cs
@@ -0,0 +1,79 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using Newtonsoft.Json;
+using System;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class HttpRequestClient : IRequestClient
+    {
+        public CommandStatus Dispatch(CommandServiceEventArgs command)
+        {
+            string json = JsonConvert.SerializeObject(command, Formatting.None, new JsonSerializerSettings { DefaultValueHandling = DefaultValueHandling.Include, NullValueHandling = NullValueHandling.Ignore, });
+
+            WebRequest request = HttpWebRequest.Create(HttpRequestServer.Url);
+            try
+            {
+                return DoRequestInternal("POST", json, request);
+            }
+            catch (WebException wex)
+            {
+                if (wex.Status == WebExceptionStatus.ConnectFailure)
+                {
+                    return CommandStatus.NoResponse;
+                }
+                throw;
+            }
+        }
+
+        private static CommandStatus DoRequestInternal(string method, string content, WebRequest request)
+        {
+            request.Method = method;
+            if (method == "POST" || method == "PUT")
+            {
+                using (StreamWriter writer = new StreamWriter(request.GetRequestStream(), Encoding.UTF8))
+                {
+                    writer.Write(content);
+                }
+            }
+            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
+            {
+                if (response.StatusCode == HttpStatusCode.OK)
+                {
+                    return CommandStatus.Success;
+                }
+                return CommandStatus.Error;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/HttpRequestServer.cs b/Axantum.AxCrypt.Mono/HttpRequestServer.cs
new file mode 100644
index 0000000..036cda6
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/HttpRequestServer.cs
@@ -0,0 +1,129 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Ipc;
+using Newtonsoft.Json;
+using System;
+using System.IO;
+using System.Linq;
+using System.Net;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class HttpRequestServer : IRequestServer, IDisposable
+    {
+        internal static readonly Uri Url = new Uri("http://localhost:53414/AxCrypt/");
+
+        private HttpListener _listener = new HttpListener();
+
+        public void Start()
+        {
+            _listener.Prefixes.Add(Url.ToString());
+            _listener.Start();
+            _listener.BeginGetContext(ListenerCallback, _listener);
+        }
+
+        private void ListenerCallback(IAsyncResult result)
+        {
+            HttpListener listener = (HttpListener)result.AsyncState;
+            if (!listener.IsListening)
+            {
+                return;
+            }
+            HttpListenerContext context = null;
+            try
+            {
+                context = listener.EndGetContext(result);
+            }
+            catch (HttpListenerException)
+            {
+                return;
+            }
+            if (listener.IsListening)
+            {
+                listener.BeginGetContext(ListenerCallback, listener);
+            }
+            if (context == null)
+            {
+                return;
+            }
+            HttpListenerRequest request = context.Request;
+            using (TextReader reader = new StreamReader(request.InputStream, Encoding.UTF8))
+            {
+                string requestJson = reader.ReadToEnd();
+                CommandServiceEventArgs requestArgs = JsonConvert.DeserializeObject<CommandServiceEventArgs>(requestJson);
+                RequestCommandEventArgs args = new RequestCommandEventArgs(requestArgs);
+                OnRequest(args);
+            }
+            using (HttpListenerResponse response = context.Response)
+            {
+                response.StatusCode = (int)HttpStatusCode.OK;
+                response.StatusDescription = "OK";
+            }
+        }
+
+        public void Shutdown()
+        {
+            _listener.Stop();
+        }
+
+        public event EventHandler<RequestCommandEventArgs> Request;
+
+        protected virtual void OnRequest(RequestCommandEventArgs e)
+        {
+            EventHandler<RequestCommandEventArgs> handler = Request;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_listener != null)
+            {
+                _listener.Stop();
+                _listener.Close();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Launcher.cs b/Axantum.AxCrypt.Mono/Launcher.cs
new file mode 100644
index 0000000..9ac4685
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Launcher.cs
@@ -0,0 +1,147 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Diagnostics;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono
+{
+    internal class Launcher : ILauncher
+    {
+        private readonly object _disposeLock = new object();
+
+        private Process _process;
+
+        private string _path;
+
+        public Launcher(string path)
+        {
+            _process = Process.Start(path);
+            if (_process == null)
+            {
+                return;
+            }
+            WasStarted = true;
+            _path = _process.StartInfo.FileName;
+            if (OS.Current.CanTrackProcess)
+            {
+                // This causes hang-on-exit on at least Mac OS X
+                _process.EnableRaisingEvents = true;
+                _process.Exited += Process_Exited;
+            }
+            else
+            {
+                _process.Dispose();
+                _process = null;
+            }
+        }
+
+        private void Process_Exited(object sender, EventArgs e)
+        {
+            OnExited(e);
+            _process.Exited -= Process_Exited;
+            _process.WaitForExit();
+            lock (_disposeLock)
+            {
+                _process.Dispose();
+                _process = null;
+            }
+        }
+
+        #region ILauncher Members
+
+        public event EventHandler Exited;
+
+        public bool HasExited
+        {
+            get
+            {
+                lock (_disposeLock)
+                {
+                    return _process == null || _process.HasExited;
+                }
+            }
+        }
+
+        public bool WasStarted
+        {
+            get;
+            private set;
+        }
+
+        #endregion ILauncher Members
+
+        protected virtual void OnExited(EventArgs e)
+        {
+            EventHandler handler = Exited;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            lock (_disposeLock)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_process == null)
+            {
+                return;
+            }
+            _process.Dispose();
+            _process = null;
+        }
+
+        public string Path
+        {
+            get { return _path; }
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Logging.cs b/Axantum.AxCrypt.Mono/Logging.cs
new file mode 100644
index 0000000..3aa5367
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Logging.cs
@@ -0,0 +1,204 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class Logging : ILogging
+    {
+        private TraceSwitch _switch = InitializeTraceSwitch();
+
+        public Logging()
+        {
+            Trace.Listeners.Add(new DelegateTraceListener("ILoggingListener", TraceMessage));
+        }
+
+        private void TraceMessage(string message)
+        {
+            OnLogging(new LoggingEventArgs(message));
+        }
+
+        #region ILogging Members
+
+        public event EventHandler<LoggingEventArgs> Logged;
+
+        protected virtual void OnLogging(LoggingEventArgs e)
+        {
+            EventHandler<LoggingEventArgs> handler = Logged;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        public void SetLevel(LogLevel level)
+        {
+            switch (level)
+            {
+                case LogLevel.Fatal:
+                    _switch.Level = TraceLevel.Off;
+                    break;
+
+                case LogLevel.Error:
+                    _switch.Level = TraceLevel.Error;
+                    break;
+
+                case LogLevel.Warning:
+                    _switch.Level = TraceLevel.Warning;
+                    break;
+
+                case LogLevel.Info:
+                    _switch.Level = TraceLevel.Info;
+                    break;
+
+                case LogLevel.Debug:
+                    _switch.Level = TraceLevel.Verbose;
+                    break;
+
+                default:
+                    throw new ArgumentException("level must be a value form the LogLevel enumeration.");
+            }
+        }
+
+        public bool IsFatalEnabled
+        {
+            get { return _switch != null && _switch.Level >= TraceLevel.Off; }
+        }
+
+        public bool IsErrorEnabled
+        {
+            get { return _switch != null && _switch.Level >= TraceLevel.Error; }
+        }
+
+        public bool IsWarningEnabled
+        {
+            get { return _switch != null && _switch.Level >= TraceLevel.Warning; }
+        }
+
+        public bool IsInfoEnabled
+        {
+            get { return _switch != null && _switch.Level >= TraceLevel.Info; }
+        }
+
+        public bool IsDebugEnabled
+        {
+            get { return _switch != null && _switch.Level >= TraceLevel.Verbose; }
+        }
+
+        public virtual void LogFatal(string message)
+        {
+            if (IsFatalEnabled)
+            {
+                Trace.WriteLine("{1} Fatal: {0}".InvariantFormat(message, AppName));
+            }
+        }
+
+        public void LogError(string message)
+        {
+            if (IsErrorEnabled)
+            {
+                Trace.TraceError(message);
+            }
+        }
+
+        public void LogWarning(string message)
+        {
+            if (IsWarningEnabled)
+            {
+                Trace.TraceWarning(message);
+            }
+        }
+
+        public void LogInfo(string message)
+        {
+            if (IsInfoEnabled)
+            {
+                Trace.TraceInformation(message);
+            }
+        }
+
+        public void LogDebug(string message)
+        {
+            if (IsDebugEnabled)
+            {
+                Trace.WriteLine("{1} Debug: {0}".InvariantFormat(message, AppName));
+            }
+        }
+
+        #endregion ILogging Members
+
+        private static TraceSwitch InitializeTraceSwitch()
+        {
+            TraceSwitch traceSwitch = new TraceSwitch("axCryptSwitch", "Logging levels for AxCrypt");
+            traceSwitch.Level = TraceLevel.Error;
+            return traceSwitch;
+        }
+
+        private static string _appName;
+
+        private static string AppName
+        {
+            get
+            {
+                if (_appName == null)
+                {
+                    _appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
+                }
+                return _appName;
+            }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_switch != null)
+            {
+                Trace.Listeners.Remove("ILoggingListener");
+                _switch = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/AxCryptHMACSHA1.cs b/Axantum.AxCrypt.Mono/Portable/AxCryptHMACSHA1.cs
new file mode 100644
index 0000000..8541f99
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/AxCryptHMACSHA1.cs
@@ -0,0 +1,69 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Crypto;
+using System;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    /// <summary>
+    /// Calculate HMACSHA1 the AxCrypt way.
+    /// </summary>
+    /// <remarks>
+    /// The .NET standard implementation uses a block size of 64, which is really only relevant
+    /// as to how to treat the key. AxCrypt uses a block size of 20. This class is required because
+    /// the .NET implementation has the BlockSizeValue as protected.
+    /// </remarks>
+    [SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", Justification = "Both HMAC and SHA1 are meaningful acronyms and this is the way .NET does the naming.")]
+    internal sealed class AxCryptHMACSHA1 : System.Security.Cryptography.HMACSHA1
+    {
+        private AxCryptHMACSHA1()
+        {
+            // We can't do it all in the constructor because then we need to call virtual methods and that's a bad
+            // idea in a constructor.
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the AxCryptHMACSHA1 class
+        /// with a provided key.
+        /// </summary>
+        /// <param name="key">The key</param>
+        public static System.Security.Cryptography.HMAC Create(SymmetricKey key)
+        {
+            if (key == null)
+            {
+                throw new ArgumentNullException("key");
+            }
+            AxCryptHMACSHA1 hmac = new AxCryptHMACSHA1();
+            hmac.BlockSizeValue = 20;
+            hmac.Key = key.GetBytes();
+
+            return hmac;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/CryptographyCryptoTransformWrapper.cs b/Axantum.AxCrypt.Mono/Portable/CryptographyCryptoTransformWrapper.cs
new file mode 100644
index 0000000..252ba06
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/CryptographyCryptoTransformWrapper.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class CryptographyCryptoTransformWrapper : System.Security.Cryptography.ICryptoTransform
+    {
+        private Axantum.AxCrypt.Core.Portable.ICryptoTransform _cryptoTransform;
+
+        public CryptographyCryptoTransformWrapper(Axantum.AxCrypt.Core.Portable.ICryptoTransform cryptoTransform)
+        {
+            _cryptoTransform = cryptoTransform;
+        }
+
+        public bool CanReuseTransform
+        {
+            get { return _cryptoTransform.CanReuseTransform; }
+        }
+
+        public bool CanTransformMultipleBlocks
+        {
+            get { return _cryptoTransform.CanTransformMultipleBlocks; }
+        }
+
+        public int InputBlockSize
+        {
+            get { return _cryptoTransform.InputBlockSize; }
+        }
+
+        public int OutputBlockSize
+        {
+            get { return _cryptoTransform.OutputBlockSize; }
+        }
+
+        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            return _cryptoTransform.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+        }
+
+        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+        {
+            return _cryptoTransform.TransformFinalBlock(inputBuffer, inputOffset, inputCount);
+        }
+
+        public void Dispose()
+        {
+            _cryptoTransform.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableCryptoStreamWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableCryptoStreamWrapper.cs
new file mode 100644
index 0000000..bcd7b2d
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableCryptoStreamWrapper.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    public class PortableCryptoStreamWrapper : Axantum.AxCrypt.Core.Portable.CryptoStream
+    {
+        private System.Security.Cryptography.CryptoStream _cryptoStream;
+
+        public PortableCryptoStreamWrapper(System.Security.Cryptography.CryptoStream cryptoStream)
+        {
+            _cryptoStream = cryptoStream;
+        }
+
+        public override bool CanRead
+        {
+            get { return _cryptoStream.CanRead; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return _cryptoStream.CanSeek; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return _cryptoStream.CanWrite; }
+        }
+
+        public override void Flush()
+        {
+            _cryptoStream.Flush();
+        }
+
+        public override long Length
+        {
+            get { return _cryptoStream.Length; }
+        }
+
+        public override long Position
+        {
+            get
+            {
+                return _cryptoStream.Position;
+            }
+            set
+            {
+                _cryptoStream.Position = value;
+            }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            return _cryptoStream.Read(buffer, offset, count);
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return _cryptoStream.Seek(offset, origin);
+        }
+
+        public override void SetLength(long value)
+        {
+            _cryptoStream.SetLength(value);
+        }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            _cryptoStream.Write(buffer, offset, count);
+        }
+
+        public override bool CanTimeout
+        {
+            get
+            {
+                return _cryptoStream.CanTimeout;
+            }
+        }
+
+        public override void Close()
+        {
+            _cryptoStream.Close();
+        }
+
+        public override bool Equals(object obj)
+        {
+            return _cryptoStream.Equals(obj);
+        }
+
+        public override int GetHashCode()
+        {
+            return _cryptoStream.GetHashCode();
+        }
+
+        public override int ReadByte()
+        {
+            return _cryptoStream.ReadByte();
+        }
+
+        public override void WriteByte(byte value)
+        {
+            _cryptoStream.WriteByte(value);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableCryptoTransformWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableCryptoTransformWrapper.cs
new file mode 100644
index 0000000..4f59d75
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableCryptoTransformWrapper.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    public class PortableCryptoTransformWrapper : Axantum.AxCrypt.Core.Portable.ICryptoTransform
+    {
+        private System.Security.Cryptography.ICryptoTransform _cryptoTransform;
+
+        public PortableCryptoTransformWrapper(System.Security.Cryptography.ICryptoTransform cryptoTransform)
+        {
+            _cryptoTransform = cryptoTransform;
+        }
+
+        public bool CanReuseTransform
+        {
+            get { return _cryptoTransform.CanReuseTransform; }
+        }
+
+        public bool CanTransformMultipleBlocks
+        {
+            get { return _cryptoTransform.CanTransformMultipleBlocks; }
+        }
+
+        public int InputBlockSize
+        {
+            get { return _cryptoTransform.InputBlockSize; }
+        }
+
+        public int OutputBlockSize
+        {
+            get { return _cryptoTransform.OutputBlockSize; }
+        }
+
+        public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            return _cryptoTransform.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+        }
+
+        public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+        {
+            return _cryptoTransform.TransformFinalBlock(inputBuffer, inputOffset, inputCount);
+        }
+
+        public void Dispose()
+        {
+            _cryptoTransform.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableFactory.cs b/Axantum.AxCrypt.Mono/Portable/PortableFactory.cs
new file mode 100644
index 0000000..24c8f6b
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableFactory.cs
@@ -0,0 +1,78 @@
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    public class PortableFactory : IPortableFactory
+    {
+        public HMAC AxCryptHMACSHA1(SymmetricKey key)
+        {
+            return new PortableHmacWrapper(Axantum.AxCrypt.Mono.Portable.AxCryptHMACSHA1.Create(key));
+        }
+
+        public HMAC HMACSHA512(byte[] key)
+        {
+            return new PortableHmacWrapper(new System.Security.Cryptography.HMACSHA512(key));
+        }
+
+        public SymmetricAlgorithm AesManaged()
+        {
+            return new PortableSymmetricAlgorithmWrapper(new System.Security.Cryptography.AesManaged());
+        }
+
+        public HashAlgorithm SHA1Managed()
+        {
+            return new PortableHashAlgorithmWrapper(new System.Security.Cryptography.SHA1Managed());
+        }
+
+        public RandomNumberGenerator RandomNumberGenerator()
+        {
+            return new PortableRandomNumberGeneratorWrapper(System.Security.Cryptography.RandomNumberGenerator.Create());
+        }
+
+        public Stream CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
+        {
+            System.Security.Cryptography.CryptoStreamMode streamMode;
+            switch (mode)
+            {
+                case CryptoStreamMode.Read:
+                    streamMode = System.Security.Cryptography.CryptoStreamMode.Read;
+                    break;
+
+                case CryptoStreamMode.Write:
+                    streamMode = System.Security.Cryptography.CryptoStreamMode.Write;
+                    break;
+
+                default:
+                    streamMode = (System.Security.Cryptography.CryptoStreamMode)mode;
+                    break;
+            }
+            return new PortableCryptoStreamWrapper(new System.Security.Cryptography.CryptoStream(stream, new CryptographyCryptoTransformWrapper(transform), streamMode));
+        }
+
+        public ISemaphore Semaphore(int initialCount, int maximumCount)
+        {
+            return new PortableSemaphoreWrapper(new System.Threading.Semaphore(initialCount, maximumCount));
+        }
+
+        public IPath Path()
+        {
+            return new PortablePathImplementation();
+        }
+
+        public Core.Runtime.IThreadWorker ThreadWorker(Core.UI.IProgressContext progress, bool startSerializedOnUIThread)
+        {
+            return new ThreadWorker(progress, startSerializedOnUIThread);
+        }
+
+        public ISingleThread SingleThread()
+        {
+            return new SingleThread();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableHashAlgorithmWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableHashAlgorithmWrapper.cs
new file mode 100644
index 0000000..f777708
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableHashAlgorithmWrapper.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortableHashAlgorithmWrapper : Axantum.AxCrypt.Core.Portable.HashAlgorithm
+    {
+        private System.Security.Cryptography.HashAlgorithm _hashAlgorithm;
+
+        public PortableHashAlgorithmWrapper(System.Security.Cryptography.HashAlgorithm hashAlgoritm)
+        {
+            _hashAlgorithm = hashAlgoritm;
+        }
+
+        public override byte[] ComputeHash(byte[] buffer)
+        {
+            return _hashAlgorithm.ComputeHash(buffer);
+        }
+
+        public override byte[] ComputeHash(byte[] buffer, int offset, int count)
+        {
+            return _hashAlgorithm.ComputeHash(buffer, offset, count);
+        }
+
+        public override byte[] ComputeHash(Stream inputStream)
+        {
+            return _hashAlgorithm.ComputeHash(inputStream);
+        }
+
+        public override byte[] Hash
+        {
+            get { return _hashAlgorithm.Hash; }
+        }
+
+        public override int HashSize
+        {
+            get { return _hashAlgorithm.HashSize; }
+        }
+
+        public override void Initialize()
+        {
+            _hashAlgorithm.Initialize();
+        }
+
+        public override bool CanReuseTransform
+        {
+            get { return _hashAlgorithm.CanReuseTransform; }
+        }
+
+        public override bool CanTransformMultipleBlocks
+        {
+            get { return _hashAlgorithm.CanTransformMultipleBlocks; }
+        }
+
+        public override int InputBlockSize
+        {
+            get { return _hashAlgorithm.InputBlockSize; }
+        }
+
+        public override int OutputBlockSize
+        {
+            get { return _hashAlgorithm.OutputBlockSize; }
+        }
+
+        public override int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            return _hashAlgorithm.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+        }
+
+        public override byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+        {
+            return _hashAlgorithm.TransformFinalBlock(inputBuffer, inputOffset, inputCount);
+        }
+
+        public override void Dispose()
+        {
+            _hashAlgorithm.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableHmacWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableHmacWrapper.cs
new file mode 100644
index 0000000..de220e2
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableHmacWrapper.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortableHmacWrapper : Axantum.AxCrypt.Core.Portable.HMAC
+    {
+        private System.Security.Cryptography.HMAC _hmac;
+
+        public PortableHmacWrapper(System.Security.Cryptography.HMAC hmac)
+        {
+            _hmac = hmac;
+        }
+
+        public override string HashName
+        {
+            get
+            {
+                return _hmac.HashName;
+            }
+            set
+            {
+                _hmac.HashName = value;
+            }
+        }
+
+        public override byte[] Key
+        {
+            get
+            {
+                return _hmac.Key;
+            }
+            set
+            {
+                _hmac.Key = value;
+            }
+        }
+
+        public override byte[] ComputeHash(byte[] buffer)
+        {
+            return _hmac.ComputeHash(buffer);
+        }
+
+        public override byte[] ComputeHash(byte[] buffer, int offset, int count)
+        {
+            return _hmac.ComputeHash(buffer, offset, count);
+        }
+
+        public override byte[] ComputeHash(System.IO.Stream inputStream)
+        {
+            return _hmac.ComputeHash(inputStream);
+        }
+
+        public override byte[] Hash
+        {
+            get { return _hmac.Hash; }
+        }
+
+        public override int HashSize
+        {
+            get { return _hmac.HashSize; }
+        }
+
+        public override void Initialize()
+        {
+            _hmac.Initialize();
+        }
+
+        public override bool CanReuseTransform
+        {
+            get { return _hmac.CanReuseTransform; }
+        }
+
+        public override bool CanTransformMultipleBlocks
+        {
+            get { return _hmac.CanTransformMultipleBlocks; }
+        }
+
+        public override int InputBlockSize
+        {
+            get { return _hmac.InputBlockSize; }
+        }
+
+        public override int OutputBlockSize
+        {
+            get { return _hmac.OutputBlockSize; }
+        }
+
+        public override int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+        {
+            return _hmac.TransformBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+        }
+
+        public override byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount)
+        {
+            return _hmac.TransformFinalBlock(inputBuffer, inputOffset, inputCount);
+        }
+
+        public override void Dispose()
+        {
+            _hmac.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortablePathImplementation.cs b/Axantum.AxCrypt.Mono/Portable/PortablePathImplementation.cs
new file mode 100644
index 0000000..6b66cc3
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortablePathImplementation.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortablePathImplementation : Axantum.AxCrypt.Core.Portable.IPath
+    {
+        public string GetFileName(string path)
+        {
+            return Path.GetFileName(path);
+        }
+
+        public string GetDirectoryName(string path)
+        {
+            return Path.GetDirectoryName(path);
+        }
+
+        public string GetExtension(string path)
+        {
+            return Path.GetExtension(path);
+        }
+
+        public string Combine(string left, string right)
+        {
+            return Path.Combine(left, right);
+        }
+
+        public string GetFileNameWithoutExtension(string path)
+        {
+            return Path.GetFileNameWithoutExtension(path);
+        }
+
+        public char DirectorySeparatorChar
+        {
+            get { return Path.DirectorySeparatorChar; }
+        }
+
+        public string GetPathRoot(string path)
+        {
+            return Path.GetPathRoot(path);
+        }
+
+        public string GetRandomFileName()
+        {
+            return Path.GetRandomFileName();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableRandomNumberGeneratorWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableRandomNumberGeneratorWrapper.cs
new file mode 100644
index 0000000..e7d6750
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableRandomNumberGeneratorWrapper.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortableRandomNumberGeneratorWrapper : Axantum.AxCrypt.Core.Portable.RandomNumberGenerator
+    {
+        private System.Security.Cryptography.RandomNumberGenerator _rng;
+
+        public PortableRandomNumberGeneratorWrapper(System.Security.Cryptography.RandomNumberGenerator rng)
+        {
+            _rng = rng;
+        }
+
+        public override void GetBytes(byte[] data)
+        {
+            _rng.GetBytes(data);
+        }
+
+        public override void Dispose()
+        {
+            _rng.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableSemaphoreWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableSemaphoreWrapper.cs
new file mode 100644
index 0000000..0988fd3
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableSemaphoreWrapper.cs
@@ -0,0 +1,33 @@
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortableSemaphoreWrapper : ISemaphore
+    {
+        private System.Threading.Semaphore _semaphore;
+
+        public PortableSemaphoreWrapper(System.Threading.Semaphore semaphore)
+        {
+            _semaphore = semaphore;
+        }
+
+        public void WaitOne()
+        {
+            _semaphore.WaitOne();
+        }
+
+        public void Release()
+        {
+            _semaphore.Release();
+        }
+
+        public void Dispose()
+        {
+            _semaphore.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/PortableSymmetricAlgorithmWrapper.cs b/Axantum.AxCrypt.Mono/Portable/PortableSymmetricAlgorithmWrapper.cs
new file mode 100644
index 0000000..760c4e7
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/PortableSymmetricAlgorithmWrapper.cs
@@ -0,0 +1,237 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    internal class PortableSymmetricAlgorithmWrapper : Axantum.AxCrypt.Core.Portable.SymmetricAlgorithm
+    {
+        private System.Security.Cryptography.SymmetricAlgorithm _symmetricAlgorithm;
+
+        public PortableSymmetricAlgorithmWrapper(System.Security.Cryptography.SymmetricAlgorithm symmetricAlgorithm)
+        {
+            _symmetricAlgorithm = symmetricAlgorithm;
+        }
+
+        public override void Clear()
+        {
+            _symmetricAlgorithm.Clear();
+        }
+
+        public override int BlockSize
+        {
+            get
+            {
+                return _symmetricAlgorithm.BlockSize;
+            }
+            set
+            {
+                _symmetricAlgorithm.BlockSize = value;
+            }
+        }
+
+        public override int FeedbackSize
+        {
+            get
+            {
+                return _symmetricAlgorithm.FeedbackSize;
+            }
+            set
+            {
+                _symmetricAlgorithm.FeedbackSize = value;
+            }
+        }
+
+        public override byte[] IV
+        {
+            get
+            {
+                return _symmetricAlgorithm.IV;
+            }
+            set
+            {
+                _symmetricAlgorithm.IV = value;
+            }
+        }
+
+        public override byte[] Key
+        {
+            get
+            {
+                return _symmetricAlgorithm.Key;
+            }
+            set
+            {
+                _symmetricAlgorithm.Key = value;
+            }
+        }
+
+        public override int KeySize
+        {
+            get
+            {
+                return _symmetricAlgorithm.KeySize;
+            }
+            set
+            {
+                _symmetricAlgorithm.KeySize = value;
+            }
+        }
+
+        public override Core.Portable.KeySizes[] LegalBlockSizes
+        {
+            get { return _symmetricAlgorithm.LegalBlockSizes.Select(k => new Core.Portable.KeySizes() { MaxSize = k.MaxSize, MinSize = k.MinSize, SkipSize = k.SkipSize }).ToArray(); }
+        }
+
+        public override Core.Portable.KeySizes[] LegalKeySizes
+        {
+            get { return _symmetricAlgorithm.LegalKeySizes.Select(k => new Core.Portable.KeySizes() { MaxSize = k.MaxSize, MinSize = k.MinSize, SkipSize = k.SkipSize }).ToArray(); }
+        }
+
+        public override Core.Portable.CipherMode Mode
+        {
+            get
+            {
+                switch (_symmetricAlgorithm.Mode)
+                {
+                    case System.Security.Cryptography.CipherMode.CBC:
+                        return Core.Portable.CipherMode.CBC;
+
+                    case System.Security.Cryptography.CipherMode.CFB:
+                        return Core.Portable.CipherMode.CFB;
+
+                    case System.Security.Cryptography.CipherMode.CTS:
+                        return Core.Portable.CipherMode.CTS;
+
+                    case System.Security.Cryptography.CipherMode.ECB:
+                        return Core.Portable.CipherMode.ECB;
+
+                    case System.Security.Cryptography.CipherMode.OFB:
+                        return Core.Portable.CipherMode.OFB;
+                }
+                return Core.Portable.CipherMode.None;
+            }
+            set
+            {
+                switch (value)
+                {
+                    case Axantum.AxCrypt.Core.Portable.CipherMode.CBC:
+                        _symmetricAlgorithm.Mode = System.Security.Cryptography.CipherMode.CBC;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.CipherMode.ECB:
+                        _symmetricAlgorithm.Mode = System.Security.Cryptography.CipherMode.ECB;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.CipherMode.OFB:
+                        _symmetricAlgorithm.Mode = System.Security.Cryptography.CipherMode.OFB;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.CipherMode.CFB:
+                        _symmetricAlgorithm.Mode = System.Security.Cryptography.CipherMode.CFB;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.CipherMode.CTS:
+                        _symmetricAlgorithm.Mode = System.Security.Cryptography.CipherMode.CTS;
+                        break;
+                }
+            }
+        }
+
+        public override Core.Portable.PaddingMode Padding
+        {
+            get
+            {
+                switch (_symmetricAlgorithm.Padding)
+                {
+                    case System.Security.Cryptography.PaddingMode.ANSIX923:
+                        return Core.Portable.PaddingMode.ANSIX923;
+
+                    case System.Security.Cryptography.PaddingMode.ISO10126:
+                        return Core.Portable.PaddingMode.ISO10126;
+
+                    case System.Security.Cryptography.PaddingMode.None:
+                        return Core.Portable.PaddingMode.None;
+
+                    case System.Security.Cryptography.PaddingMode.PKCS7:
+                        return Core.Portable.PaddingMode.PKCS7;
+
+                    case System.Security.Cryptography.PaddingMode.Zeros:
+                        return Core.Portable.PaddingMode.Zeros;
+                };
+                return Core.Portable.PaddingMode.None;
+            }
+            set
+            {
+                switch (value)
+                {
+                    case Axantum.AxCrypt.Core.Portable.PaddingMode.None:
+                        _symmetricAlgorithm.Padding = System.Security.Cryptography.PaddingMode.None;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.PaddingMode.PKCS7:
+                        _symmetricAlgorithm.Padding = System.Security.Cryptography.PaddingMode.PKCS7;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.PaddingMode.Zeros:
+                        _symmetricAlgorithm.Padding = System.Security.Cryptography.PaddingMode.Zeros;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.PaddingMode.ANSIX923:
+                        _symmetricAlgorithm.Padding = System.Security.Cryptography.PaddingMode.ANSIX923;
+                        break;
+
+                    case Axantum.AxCrypt.Core.Portable.PaddingMode.ISO10126:
+                        _symmetricAlgorithm.Padding = System.Security.Cryptography.PaddingMode.ISO10126;
+                        break;
+                };
+            }
+        }
+
+        public override Core.Portable.ICryptoTransform CreateDecryptor()
+        {
+            return new PortableCryptoTransformWrapper(_symmetricAlgorithm.CreateDecryptor());
+        }
+
+        public override Core.Portable.ICryptoTransform CreateDecryptor(byte[] rgbKey, byte[] rgbIV)
+        {
+            return new PortableCryptoTransformWrapper(_symmetricAlgorithm.CreateDecryptor(rgbKey, rgbIV));
+        }
+
+        public override Core.Portable.ICryptoTransform CreateEncryptor()
+        {
+            return new PortableCryptoTransformWrapper(_symmetricAlgorithm.CreateEncryptor());
+        }
+
+        public override Core.Portable.ICryptoTransform CreateEncryptor(byte[] rgbKey, byte[] rgbIV)
+        {
+            return new PortableCryptoTransformWrapper(_symmetricAlgorithm.CreateEncryptor(rgbKey, rgbIV));
+        }
+
+        public override void GenerateIV()
+        {
+            _symmetricAlgorithm.GenerateIV();
+        }
+
+        public override void GenerateKey()
+        {
+            _symmetricAlgorithm.GenerateKey();
+        }
+
+        public override bool ValidKeySize(int bitLength)
+        {
+            return _symmetricAlgorithm.ValidKeySize(bitLength);
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            _symmetricAlgorithm.Dispose();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Portable/SingleThread.cs b/Axantum.AxCrypt.Mono/Portable/SingleThread.cs
new file mode 100644
index 0000000..d195ec4
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Portable/SingleThread.cs
@@ -0,0 +1,72 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Portable;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Mono.Portable
+{
+    public class SingleThread : ISingleThread
+    {
+        private Semaphore _singleThreadSemaphore = new Semaphore(1, 1);
+
+        public virtual void Enter()
+        {
+            _singleThreadSemaphore.WaitOne();
+        }
+
+        public virtual void Leave()
+        {
+            _singleThreadSemaphore.Release();
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_singleThreadSemaphore != null)
+            {
+                _singleThreadSemaphore.Close();
+                _singleThreadSemaphore = null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..c2bfcce
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.cs
@@ -0,0 +1,78 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is strong named when deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AxCrypt Mono Specific Library")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © 2014 Svante Seleborg")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("086325b4-e6aa-43b6-89da-3651d1419f6b")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+[assembly: InternalsVisibleTo("Axantum.AxCrypt.Mono.Test")]
+#else
+[assembly: InternalsVisibleTo("Axantum.AxCrypt.Mono.Test, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f7cdec4989133e4654fa9741b22177f2404b463d1c821033dc73dfa47a5976e1cc69a8d78f4dd551bbf710e54300d7f035636a7502c1f88e0929596c848308e3250f927437f358d053d972744691c79ee6e4d3b151e63f56a331446a3097bf13e21f1feba2b84add6a05ebf2b3d9ca600d5ebf33d9c0ec3ae49956a9f3db3fc8")]
+#endif
+
+[module: SuppressMessage("Microsoft.Design", "CA1020:AvoidNamespacesWithFewTypes", Scope = "namespace", Target = "Axantum.AxCrypt.Mono", Justification = "There are more types, but they are internal.")]
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.template b/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.template
new file mode 100644
index 0000000..7d79c17
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Properties/AssemblyInfo.template
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyFileVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyInformationalVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyConfiguration("")]
diff --git a/Axantum.AxCrypt.Mono/RuntimeEnvironment.cs b/Axantum.AxCrypt.Mono/RuntimeEnvironment.cs
new file mode 100644
index 0000000..67ef16f
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/RuntimeEnvironment.cs
@@ -0,0 +1,234 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Ipc;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono.Portable;
+using System;
+using System.Net;
+using System.Net.Security;
+using System.Security.Cryptography.X509Certificates;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class RuntimeEnvironment : IRuntimeEnvironment, IDisposable
+    {
+        public static void RegisterTypeFactories()
+        {
+            Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+            Factory.Instance.Singleton<IPortableFactory>(() => new PortableFactory());
+            Factory.Instance.Singleton<ILogging>(() => new Logging());
+            Factory.Instance.Singleton<CommandService>(() => new CommandService(new HttpRequestServer(), new HttpRequestClient()));
+
+            Factory.Instance.Register<ISleep>(() => new Sleep());
+            Factory.Instance.Register<IDelayTimer>(() => new DelayTimer());
+            Factory.Instance.Register<string, IRuntimeFileInfo>((path) => new RuntimeFileInfo(path));
+        }
+
+        public RuntimeEnvironment(string extension)
+        {
+            AxCryptExtension = extension;
+        }
+
+        public bool IsLittleEndian
+        {
+            get
+            {
+                return BitConverter.IsLittleEndian;
+            }
+        }
+
+        public string AxCryptExtension
+        {
+            get;
+            set;
+        }
+
+        public Platform Platform
+        {
+            get
+            {
+                OperatingSystem os = global::System.Environment.OSVersion;
+                PlatformID pid = os.Platform;
+                switch (pid)
+                {
+                    case PlatformID.Win32NT:
+                    case PlatformID.Win32S:
+                    case PlatformID.Win32Windows:
+                        return Platform.WindowsDesktop;
+
+                    case PlatformID.MacOSX:
+                        return Platform.MacOsx;
+
+                    case PlatformID.Unix:
+                        return Platform.Linux;
+
+                    case PlatformID.WinCE:
+                        return Platform.WindowsMobile;
+
+                    case PlatformID.Xbox:
+                        return Platform.Xbox;
+
+                    default:
+                        return Platform.Unknown;
+                }
+            }
+        }
+
+        public int StreamBufferSize
+        {
+            get { return 65536; }
+        }
+
+        public DateTime UtcNow
+        {
+            get { return DateTime.UtcNow; }
+        }
+
+        public virtual ILauncher Launch(string path)
+        {
+            return new Launcher(path);
+        }
+
+        public ITiming StartTiming()
+        {
+            return new Timing();
+        }
+
+        public IWebCaller CreateWebCaller()
+        {
+            return new WebCaller();
+        }
+
+        public bool CanTrackProcess
+        {
+            get { return Platform == Platform.WindowsDesktop; }
+        }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_firstInstanceMutex != null)
+            {
+                _firstInstanceMutex.Close();
+                _firstInstanceMutex = null;
+            }
+            if (_firstInstanceRunning != null)
+            {
+                _firstInstanceRunning.Close();
+                _firstInstanceRunning = null;
+            }
+        }
+
+        public string EnvironmentVariable(string name)
+        {
+            string variable = Environment.GetEnvironmentVariable(name);
+
+            return variable;
+        }
+
+        public int MaxConcurrency
+        {
+            get
+            {
+                return Environment.ProcessorCount > 2 ? Environment.ProcessorCount - 1 : 2;
+            }
+        }
+
+        private EventWaitHandle _firstInstanceRunning = new EventWaitHandle(false, EventResetMode.ManualReset, "Axantum.AxCrypt.NET-FirstInstanceRunning");
+
+        private Mutex _firstInstanceMutex;
+
+        private bool _isFirstInstance;
+
+        public bool IsFirstInstance
+        {
+            get
+            {
+                if (_firstInstanceMutex == null)
+                {
+                    _firstInstanceMutex = new Mutex(true, "Axantum.AxCrypt.NET-FirstInstance", out _isFirstInstance);
+                    if (_isFirstInstance)
+                    {
+                        _firstInstanceRunning.Set();
+                    }
+                }
+                return _isFirstInstance;
+            }
+        }
+
+        public bool FirstInstanceRunning(TimeSpan timeout)
+        {
+            return _firstInstanceRunning.WaitOne(timeout, false);
+        }
+
+        public void ExitApplication(int exitCode)
+        {
+            Environment.Exit(exitCode);
+        }
+
+        public void DebugMode(bool enabled)
+        {
+            if (enabled)
+            {
+                ServicePointManager.ServerCertificateValidationCallback = (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
+                {
+                    return true;
+                };
+            }
+            else
+            {
+                ServicePointManager.ServerCertificateValidationCallback = null;
+            }
+        }
+
+        public SynchronizationContext SynchronizationContext
+        {
+            get
+            {
+                return SynchronizationContext.Current ?? new SynchronizationContext();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/RuntimeFileInfo.cs b/Axantum.AxCrypt.Mono/RuntimeFileInfo.cs
new file mode 100644
index 0000000..887b582
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/RuntimeFileInfo.cs
@@ -0,0 +1,333 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt.Mono
+{
+    /// <summary>
+    /// Provides properties and instance methods for the operations with files, and aids in the creation of Stream objects. The underlying file must not
+    /// necessarily exist.
+    /// </summary>
+    public class RuntimeFileInfo : IRuntimeFileInfo
+    {
+        private FileInfo _file;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="RuntimeFileInfo"/> class.
+        /// </summary>
+        /// <param name="fullName">The full path and name of the file or folder.</param>
+        /// <exception cref="System.ArgumentNullException">fullName</exception>
+        public RuntimeFileInfo(string fullName)
+        {
+            if (fullName == null)
+            {
+                throw new ArgumentNullException("fullName");
+            }
+            _file = new FileInfo(fullName.NormalizeFilePath());
+        }
+
+        private RuntimeFileInfo(FileInfo fileInfo)
+        {
+            _file = fileInfo;
+        }
+
+        /// <summary>
+        /// Opens a stream in read mode for the underlying file.
+        /// </summary>
+        /// <returns>
+        /// A stream opened for reading.
+        /// </returns>
+        public Stream OpenRead()
+        {
+            Stream stream = new FileStream(_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, OS.Current.StreamBufferSize);
+            return new LockingStream(this, stream);
+        }
+
+        /// <summary>
+        /// Opens a stream in write mode for the underlying file.
+        /// </summary>
+        /// <returns>
+        /// A stream opened for writing.
+        /// </returns>
+        public Stream OpenWrite()
+        {
+            Directory.CreateDirectory(Path.GetDirectoryName(_file.FullName));
+            Stream stream = new FileStream(_file.FullName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None, OS.Current.StreamBufferSize);
+            return new LockingStream(this, stream);
+        }
+
+        public bool IsLocked
+        {
+            get
+            {
+                try
+                {
+                    using (Stream stream = _file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None))
+                    {
+                        return false;
+                    }
+                }
+                catch (IOException)
+                {
+                    return true;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Get the Name part without the folder part of the path.
+        /// </summary>
+        public string Name
+        {
+            get
+            {
+                return _file.Name;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the creation time UTC.
+        /// </summary>
+        /// <value>
+        /// The creation time UTC.
+        /// </value>
+        public DateTime CreationTimeUtc
+        {
+            get
+            {
+                _file.Refresh();
+                return _file.CreationTimeUtc;
+            }
+            set
+            {
+                _file.CreationTimeUtc = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the last access time UTC.
+        /// </summary>
+        /// <value>
+        /// The last access time UTC.
+        /// </value>
+        public DateTime LastAccessTimeUtc
+        {
+            get
+            {
+                _file.Refresh();
+                return _file.LastAccessTimeUtc;
+            }
+            set
+            {
+                _file.LastAccessTimeUtc = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the last write time UTC.
+        /// </summary>
+        /// <value>
+        /// The last write time UTC.
+        /// </value>
+        public DateTime LastWriteTimeUtc
+        {
+            get
+            {
+                _file.Refresh();
+                return _file.LastWriteTimeUtc;
+            }
+            set
+            {
+                _file.LastWriteTimeUtc = value;
+            }
+        }
+
+        /// <summary>
+        /// Sets all of the file times of the underlying file.
+        /// </summary>
+        /// <param name="creationTimeUtc">The creation time UTC.</param>
+        /// <param name="lastAccessTimeUtc">The last access time UTC.</param>
+        /// <param name="lastWriteTimeUtc">The last write time UTC.</param>
+        public void SetFileTimes(DateTime creationTimeUtc, DateTime lastAccessTimeUtc, DateTime lastWriteTimeUtc)
+        {
+            CreationTimeUtc = creationTimeUtc;
+            LastAccessTimeUtc = lastAccessTimeUtc;
+            LastWriteTimeUtc = lastWriteTimeUtc;
+        }
+
+        /// <summary>
+        /// Get the full name including drive, directory and file name if any
+        /// </summary>
+        public string FullName
+        {
+            get { return _file.FullName; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether the file this <see cref="IRuntimeFileInfo" /> represents exists in the underlying file system.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if exists; otherwise, <c>false</c>.
+        /// </value>
+        public bool IsExistingFile
+        {
+            get
+            {
+                _file.Refresh();
+                return _file.Exists;
+            }
+        }
+
+        /// <summary>
+        /// Moves the underlying file to a new location.
+        /// </summary>
+        /// <param name="destinationFileName">Name of the destination file.</param>
+        public void MoveTo(string destinationFileName)
+        {
+            IRuntimeFileInfo destination = Factory.New<IRuntimeFileInfo>(destinationFileName);
+            if (destination.IsExistingFile)
+            {
+                try
+                {
+                    File.Replace(_file.FullName, destinationFileName, null);
+                    _file = new FileInfo(destinationFileName);
+                    return;
+                }
+                catch (PlatformNotSupportedException)
+                {
+                }
+                destination.Delete();
+            }
+            _file.MoveTo(destinationFileName);
+        }
+
+        /// <summary>
+        /// Deletes the underlying file this instance refers to.
+        /// </summary>
+        public void Delete()
+        {
+            _file.Delete();
+        }
+
+        /// <summary>
+        /// Creates a folder in the underlying file system with the path of this instance.
+        /// </summary>
+        public void CreateFolder()
+        {
+            Directory.CreateDirectory(_file.FullName);
+        }
+
+        /// <summary>
+        /// Removes a folder in the underlying file system with the path of this instance,
+        /// if the folder is empty. If it is not, nothing happens.
+        /// </summary>
+        public void RemoveFolder()
+        {
+            if (!IsExistingFolder)
+            {
+                return;
+            }
+            DirectoryInfo di = new DirectoryInfo(_file.FullName);
+            if (di.EnumerateFiles().Any() || di.EnumerateDirectories().Any())
+            {
+                return;
+            }
+            di.Delete();
+        }
+
+        /// <summary>
+        /// Creates a file in the underlying system. If it already exists, an AxCryptException is thrown with status FileExists.
+        /// </summary>
+        public void CreateNewFile()
+        {
+            try
+            {
+                using (FileStream stream = new FileStream(_file.FullName, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None))
+                {
+                    return;
+                }
+            }
+            catch (IOException)
+            {
+                throw new InternalErrorException("File exists.", ErrorStatus.FileExists);
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this instance is a folder that exists.
+        /// </summary>
+        /// <value>
+        ///   <c>true</c> if this instance is folder that exists; otherwise, <c>false</c>.
+        /// </value>
+        /// <exception cref="System.NotImplementedException"></exception>
+        public bool IsExistingFolder
+        {
+            get
+            {
+                return (int)_file.Attributes != -1 && (_file.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
+            }
+        }
+
+        /// <summary>
+        /// Enumerate all files (not folders) in this folder, if it's a folder.
+        /// </summary>
+        /// <exception cref="System.NotImplementedException"></exception>
+        public IEnumerable<IRuntimeFileInfo> Files
+        {
+            get
+            {
+                if (!IsExistingFolder)
+                {
+                    return new IRuntimeFileInfo[0];
+                }
+                DirectoryInfo di = new DirectoryInfo(_file.FullName);
+                return di.GetFiles().Select((FileInfo fi) => { return (IRuntimeFileInfo)new RuntimeFileInfo(fi); });
+            }
+        }
+
+        /// <summary>
+        /// Combine the path of this instance with another path, creating a new instance.
+        /// </summary>
+        /// <param name="path">The path to combine with.</param>
+        /// <returns>
+        /// A new instance representing the combined path.
+        /// </returns>
+        /// <exception cref="System.NotImplementedException"></exception>
+        public IRuntimeFileInfo Combine(string path)
+        {
+            return new RuntimeFileInfo(Path.Combine(FullName, path));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Sleep.cs b/Axantum.AxCrypt.Mono/Sleep.cs
new file mode 100644
index 0000000..42fe6cb
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Sleep.cs
@@ -0,0 +1,54 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using System;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Mono
+{
+    public class Sleep : ISleep
+    {
+        public void Time(TimeSpan value)
+        {
+            Thread.Sleep((int)value.TotalMilliseconds);
+            OnElapsed(new SleepEventArgs(value));
+        }
+
+        public event EventHandler<SleepEventArgs> Elapsed;
+
+        protected virtual void OnElapsed(SleepEventArgs e)
+        {
+            EventHandler<SleepEventArgs> handler = Elapsed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/ThreadWorker.cs b/Axantum.AxCrypt.Mono/ThreadWorker.cs
new file mode 100644
index 0000000..055a730
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/ThreadWorker.cs
@@ -0,0 +1,296 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Threading;
+
+namespace Axantum.AxCrypt.Mono
+{
+    /// <summary>
+    /// Perform work on a separate thread.
+    /// </summary>
+    public class ThreadWorker : IThreadWorker
+    {
+        private ManualResetEvent _joined = new ManualResetEvent(false);
+
+        private BackgroundWorker _worker;
+
+        private ThreadWorkerEventArgs _e;
+
+        private bool _startOnUIThread;
+
+        public ThreadWorker(IProgressContext progress)
+            : this(progress, false)
+        {
+        }
+
+        /// <summary>
+        /// Create a thread worker.
+        /// </summary>
+        public ThreadWorker(IProgressContext progress, bool startOnUIThread)
+        {
+            _startOnUIThread = startOnUIThread;
+            _worker = new BackgroundWorker();
+
+            _worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
+            _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
+
+            _e = new ThreadWorkerEventArgs(new ThreadWorkerProgressContext(progress));
+        }
+
+        /// <summary>
+        /// Start the asynchronous execution of the work. The instance will dispose of itself once it has
+        /// completed, thus allowing a fire-and-forget model.
+        /// </summary>
+        public void Run()
+        {
+            if (_disposed)
+            {
+                throw new ObjectDisposedException("ThreadWorker");
+            }
+            if (_startOnUIThread)
+            {
+                _e.Progress.EnterSingleThread();
+            }
+            OnPrepare(_e);
+            _worker.RunWorkerAsync();
+        }
+
+        /// <summary>
+        /// Perform blocking wait until this thread has completed execution. May be called even on a disposed object,
+        /// in which case it will return immediately.
+        /// </summary>
+        public void Join()
+        {
+            while (!HasCompleted)
+            {
+            }
+        }
+
+        /// <summary>
+        /// Abort this thread - can only be called *before* Run() has been called.
+        /// </summary>
+        public void Abort()
+        {
+            _e.Result = new FileOperationContext(String.Empty, FileOperationStatus.Aborted);
+            OnCompleting(_e);
+            CompleteWorker();
+        }
+
+        /// <summary>
+        /// Returns true if the thread has completed execution. May be called even on a disposed
+        /// object.
+        /// </summary>
+        public bool HasCompleted
+        {
+            get
+            {
+                lock (_disposeLock)
+                {
+                    if (_joined == null)
+                    {
+                        return true;
+                    }
+                    return _joined.WaitOne(0, false);
+                }
+            }
+        }
+
+        private void _worker_DoWork(object sender, DoWorkEventArgs e)
+        {
+            try
+            {
+                OnWork(_e);
+                e.Result = _e.Result;
+            }
+            catch (OperationCanceledException)
+            {
+                e.Result = new FileOperationContext(String.Empty, FileOperationStatus.Canceled);
+            }
+            catch (AxCryptException ace)
+            {
+                e.Result = new FileOperationContext(ace.DisplayContext, FileOperationStatus.Exception);
+                throw;
+            }
+        }
+
+        private void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
+        {
+            try
+            {
+                if (e.Error != null)
+                {
+                    AxCryptException ace = e.Error as AxCryptException;
+                    string displayContext = String.Empty;
+                    if (ace != null)
+                    {
+                        displayContext = ace.DisplayContext;
+                    }
+                    _e.Result = new FileOperationContext(displayContext, FileOperationStatus.Exception);
+                }
+                else
+                {
+                    _e.Result = (FileOperationContext)e.Result;
+                }
+                OnCompleting(_e);
+            }
+            finally
+            {
+                CompleteWorker();
+            }
+        }
+
+        /// <summary>
+        /// Raised just before asynchronous execution starts. Runs on the
+        /// original thread, typically the GUI thread.
+        /// </summary>
+        public event EventHandler<ThreadWorkerEventArgs> Prepare;
+
+        protected virtual void OnPrepare(ThreadWorkerEventArgs e)
+        {
+            EventHandler<ThreadWorkerEventArgs> handler = Prepare;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when asynchronous execution starts. Runs on a different
+        /// thread than the caller thread. Do not interact with the GUI here.
+        /// </summary>
+        public event EventHandler<ThreadWorkerEventArgs> Work;
+
+        protected virtual void OnWork(ThreadWorkerEventArgs e)
+        {
+            EventHandler<ThreadWorkerEventArgs> handler = Work;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when all is done. Runs on the original thread, typically
+        /// the GUI thread.
+        /// </summary>
+        public event EventHandler<ThreadWorkerEventArgs> Completing;
+
+        protected virtual void OnCompleting(ThreadWorkerEventArgs e)
+        {
+            EventHandler<ThreadWorkerEventArgs> handler = Completing;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        /// <summary>
+        /// Raised when the underlying worker thread has ended. There is no guarantee on what
+        /// thread this will run.
+        /// </summary>
+        public event EventHandler<ThreadWorkerEventArgs> Completed;
+
+        protected virtual void OnCompleted(ThreadWorkerEventArgs e)
+        {
+            EventHandler<ThreadWorkerEventArgs> handler = Completed;
+            if (handler != null)
+            {
+                handler(this, e);
+            }
+        }
+
+        #region IDisposable Members
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        #endregion IDisposable Members
+
+        private bool _disposed = false;
+
+        private readonly object _disposeLock = new object();
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if (!disposing)
+            {
+                return;
+            }
+            lock (_disposeLock)
+            {
+                DisposeInternal();
+            }
+        }
+
+        private void DisposeInternal()
+        {
+            if (_disposed)
+            {
+                return;
+            }
+            if (_worker != null)
+            {
+                DisposeWorker();
+                _worker = null;
+            }
+            if (_joined != null)
+            {
+                _joined.Set();
+                _joined.Close();
+                _joined = null;
+            }
+            _disposed = true;
+        }
+
+        private void CompleteWorker()
+        {
+            OnCompleted(_e);
+            Dispose(true);
+        }
+
+        private void DisposeWorker()
+        {
+            _worker.DoWork -= _worker_DoWork;
+            _worker.RunWorkerCompleted -= _worker_RunWorkerCompleted;
+            _e.Progress.LeaveSingleThread();
+
+            IDisposable workerAsDisposibleWhichIsPlatformDependent = _worker as IDisposable;
+            if (workerAsDisposibleWhichIsPlatformDependent != null)
+            {
+                workerAsDisposibleWhichIsPlatformDependent.Dispose();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/Timing.cs b/Axantum.AxCrypt.Mono/Timing.cs
new file mode 100644
index 0000000..8df62dd
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/Timing.cs
@@ -0,0 +1,50 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Mono
+{
+    internal class Timing : ITiming
+    {
+        private Stopwatch _stopwatch = Stopwatch.StartNew();
+
+        #region ITiming Members
+
+        public TimeSpan Elapsed
+        {
+            get { return _stopwatch.Elapsed; }
+        }
+
+        #endregion ITiming Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.Mono/WebCaller.cs b/Axantum.AxCrypt.Mono/WebCaller.cs
new file mode 100644
index 0000000..bcbc212
--- /dev/null
+++ b/Axantum.AxCrypt.Mono/WebCaller.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.IO;
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Cache;
+
+namespace Axantum.AxCrypt.Mono
+{
+    internal class WebCaller : IWebCaller
+    {
+        public WebCaller()
+        {
+        }
+
+        #region IWebCaller Members
+
+        public string Go(Uri url)
+        {
+            string response = String.Empty;
+            using (WebClient client = new WebClient())
+            {
+                client.CachePolicy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore);
+                response = client.DownloadString(url);
+            }
+            return response;
+        }
+
+        #endregion IWebCaller Members
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.MonoTouch/AboutThisAssembly.txt b/Axantum.AxCrypt.MonoTouch/AboutThisAssembly.txt
new file mode 100644
index 0000000..9e79f74
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/AboutThisAssembly.txt
@@ -0,0 +1,30 @@
+About Axantum.AxCrypt.MonoTouch
+
+This assembly is the MonoTouch-specific implementation of the various platform-specific interfaces
+defined and used by Axantum.AxCrypt.Core.
+
+Some of the code is identical with the generic Mono implementation, and is thus just linked to
+in the project.
+
+Some of the code is specific for MonoTouch and thus have a custom implementation here.
+
+The main application should configure itself for MonoTouch by a line of code similar to:
+
+            OS.Current = new Axantum.AxCrypt.MonoTouch.RuntimeEnvironment();
+
+NOTE: You must build Axantum.AxCrypt.Core.dll separately for 'Debug' and 'Release' configuration as needed.
+      This is built by the AxCrypt.NET solution, which can be loaded simultaneously into MonoDevelop for
+      a reasonably convenient workspace environment.
+
+FAQ
+
+Q: Why the special handling of Axantum.AxCrypt.Core?
+
+A: There are no really good alternatives. Bringing the code into the solution as a linked project is possible,
+   but requires double maintenance. MonoDevelop does not support Configuration-dependent binary references, so
+   therefore a Pre-Build event is used to copy the appropriate binary from the Axantum.AxCrypt.Core/bin/Configuration
+   directory. Finally, this more closely mirrors the long-term situation where Axantum.AxCrypt.Core really is
+   a binary depedency to the full, with it's own release cycle. This is not the case at this time, where it is
+   still a somewhat moving target. This is why this way to handle it was chosen. Also, MonoDevelop does not work
+   well with XBuild for MonoTouch projects, otherwise a Configuration-dependent conditional dependency manually
+   edited in the .csproj might have been a better choice.
\ No newline at end of file
diff --git a/Axantum.AxCrypt.MonoTouch/Axantum.AxCrypt.MonoTouch.csproj b/Axantum.AxCrypt.MonoTouch/Axantum.AxCrypt.MonoTouch.csproj
new file mode 100644
index 0000000..de211c0
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/Axantum.AxCrypt.MonoTouch.csproj
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{623D0558-31DF-4CDA-9424-934B7AFFFA05}</ProjectGuid>
+    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Library</OutputType>
+    <RootNamespace>Axantum.AxCrypt.MonoTouch</RootNamespace>
+    <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+    <AssemblyName>Axantum.AxCrypt.MonoTouch</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="BeforeBuild" command="mkdir -p ${ProjectDir}/bin" />
+        <Command type="BeforeBuild" command="cp ${SolutionDir}/Axantum.AxCrypt.Core/bin/Debug/Axantum.AxCrypt.Core.dll ${ProjectDir}/bin/Axantum.AxCrypt.Core.dll" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="BeforeBuild" command="mkdir -p ${ProjectDir}/bin" />
+        <Command type="BeforeBuild" command="cp ${SolutionDir}/Axantum.AxCrypt.Core/bin/Release/Axantum.AxCrypt.Core.dll ${ProjectDir}/bin" />
+      </CustomCommands>
+    </CustomCommands>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="monotouch" />
+    <Reference Include="BouncyCastle.Crypto">
+      <HintPath>..\SolutionItems\BouncyCastle.Crypto.dll</HintPath>
+    </Reference>
+    <Reference Include="System.Json" />
+    <Reference Include="System.ServiceModel" />
+    <Reference Include="Axantum.AxCrypt.Core">
+      <HintPath>bin\Axantum.AxCrypt.Core.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Compile Include="FileWatcher.cs" />
+    <Compile Include="DataProtection.cs" />
+    <Compile Include="Logging.cs" />
+    <Compile Include="RuntimeEnvironment.cs" />
+    <Compile Include="..\Axantum.AxCrypt.Mono\RuntimeFileInfo.cs">
+      <Link>Mono\RuntimeFileInfo.cs</Link>
+    </Compile>
+    <Compile Include="..\Axantum.AxCrypt.Mono\Launcher.cs">
+      <Link>Mono\Launcher.cs</Link>
+    </Compile>
+    <Compile Include="..\Axantum.AxCrypt.Mono\Timing.cs">
+      <Link>Mono\Timing.cs</Link>
+    </Compile>
+    <Compile Include="..\Axantum.AxCrypt.Mono\WebCaller.cs">
+      <Link>Mono\WebCaller.cs</Link>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AboutThisAssembly.txt" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Mono\" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.MonoTouch/DataProtection.cs b/Axantum.AxCrypt.MonoTouch/DataProtection.cs
new file mode 100644
index 0000000..63a7a7d
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/DataProtection.cs
@@ -0,0 +1,56 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.MonoTouch
+{
+    /// <summary>
+    /// Flow-through implementation of in-memory DataProtection as its concept is not backed by the platform.
+    /// </summary>
+    public class DataProtection : IDataProtection
+    {
+        public DataProtection ()
+        {
+        }
+        
+#region IDataProtection implementation
+        
+        byte[] IDataProtection.Protect (byte[] unprotectedData)
+        {
+            return unprotectedData;
+        }
+        
+        byte[] IDataProtection.Unprotect (byte[] protectedData)
+        {
+            return protectedData;
+        }
+        
+#endregion
+    }
+}
diff --git a/Axantum.AxCrypt.MonoTouch/FileWatcher.cs b/Axantum.AxCrypt.MonoTouch/FileWatcher.cs
new file mode 100644
index 0000000..fe988f8
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/FileWatcher.cs
@@ -0,0 +1,68 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using Axantum.AxCrypt.Core.IO;
+
+namespace Axantum.AxCrypt.MonoTouch
+{
+    /// <summary>
+    /// Placeholder-implementation of a FileSystemWatcher as its concept is not available on iOS.
+    /// </summary>
+	public class FileWatcher : IFileWatcher
+    {
+        public FileWatcher (string fileToWatch)
+        {
+        }
+        
+#region IFileWatcher implementation
+        
+		public event EventHandler<FileWatcherEventArgs> FileChanged;
+
+		protected virtual void OnFileChanged(FileWatcherEventArgs e)
+		{
+			EventHandler<FileWatcherEventArgs> handler = FileChanged;
+			if (handler != null)
+			{
+				handler(this, e);
+			}
+		}
+
+		public bool IncludeSubdirectories { get; set; }
+        
+#endregion
+        
+#region IDisposable implementation
+        
+        public void Dispose ()
+        {
+        }
+        
+#endregion
+    }
+}
+
diff --git a/Axantum.AxCrypt.MonoTouch/Logging.cs b/Axantum.AxCrypt.MonoTouch/Logging.cs
new file mode 100644
index 0000000..3daf392
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/Logging.cs
@@ -0,0 +1,149 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Text;
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.MonoTouch
+{
+	internal class Logging : ILogging
+    {
+        private LogLevel _level = LogLevel.Error;
+
+        #region ILogging Members
+
+		public event EventHandler<LoggingEventArgs> Logged;
+
+		public void Dispose ()
+		{
+		}
+        
+        public void SetLevel(LogLevel level)
+        {
+            switch (level)
+            {
+            case LogLevel.Fatal:
+            case LogLevel.Error:
+            case LogLevel.Warning:
+            case LogLevel.Info:
+            case LogLevel.Debug:
+                _level = level;
+                break;
+
+            default:
+                throw new ArgumentException("level must be a value form the LogLevel enumeration.");
+            }
+        }
+        
+        public bool IsFatalEnabled
+        {
+            get { return _level >= LogLevel.Fatal; }
+        }
+        
+        public bool IsErrorEnabled
+        {
+            get { return _level >= LogLevel.Error; }
+        }
+        
+        public bool IsWarningEnabled
+        {
+            get { return _level >= LogLevel.Warning; }
+        }
+        
+        public bool IsInfoEnabled
+        {
+            get { return _level >= LogLevel.Info; }
+        }
+        
+        public bool IsDebugEnabled
+        {
+            get { return _level >= LogLevel.Debug; }
+        }
+        
+        public virtual void LogFatal (string message)
+        {
+            if (IsFatalEnabled)
+            {
+                Console.WriteLine("{1} Fatal: {0}".InvariantFormat(message, AppName));
+            }
+        }
+        
+        public void LogError(string message)
+        {
+            if (IsErrorEnabled)
+            {
+                Console.WriteLine("{1} Error: {0}".InvariantFormat(message, AppName));
+            }
+        }
+        
+        public void LogWarning(string message)
+        {
+            if (IsWarningEnabled)
+            {
+                Console.WriteLine("{1} Warning: {0}".InvariantFormat(message, AppName));
+            }
+        }
+        
+        public void LogInfo(string message)
+        {
+            if (IsInfoEnabled)
+            {
+                Console.WriteLine("{1} Info: {0}".InvariantFormat(message, AppName));
+            }
+        }
+        
+        public void LogDebug(string message)
+        {
+            if (IsDebugEnabled)
+            {
+                Console.WriteLine("{1} Debug: {0}".InvariantFormat(message, AppName));
+            }
+        }
+        
+        #endregion ILogging Members
+        
+        private static string _appName;
+        
+        private static string AppName
+        {
+            get
+            {
+                if (_appName == null)
+                {
+                    _appName = Path.GetFileName(Environment.GetCommandLineArgs()[0]);
+                }
+                return _appName;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.MonoTouch/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.MonoTouch/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..fa82031
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/Properties/AssemblyInfo.cs
@@ -0,0 +1,69 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AxCrypt MonoTouch Library")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © Svante Seleborg 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("7f60742b-44b1-4aac-be60-e769378b9161")]
+[assembly: CLSCompliant(true)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+#endif
\ No newline at end of file
diff --git a/Axantum.AxCrypt.MonoTouch/RuntimeEnvironment.cs b/Axantum.AxCrypt.MonoTouch/RuntimeEnvironment.cs
new file mode 100644
index 0000000..063eac9
--- /dev/null
+++ b/Axantum.AxCrypt.MonoTouch/RuntimeEnvironment.cs
@@ -0,0 +1,84 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+using Axantum.AxCrypt.Mono;
+using Axantum.AxCrypt.Core;
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Security.Cryptography;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.MonoTouch
+{
+    public class RuntimeEnvironment : Mono.RuntimeEnvironment
+    {
+        public RuntimeEnvironment() : base(".axx")
+        {
+        }
+        
+        public IFileWatcher FileWatcher(string path)
+        {
+            return new FileWatcher(path);
+        }
+        
+        private IRuntimeFileInfo _temporaryDirectoryInfo;
+        
+        public IRuntimeFileInfo TemporaryDirectoryInfo
+        {
+            get
+            {
+                if (_temporaryDirectoryInfo == null)
+                {
+                    string temporaryFolderPath = Path.Combine(Path.GetTempPath(), @"AxCrypt" + Path.DirectorySeparatorChar);
+					IRuntimeFileInfo temporaryFolderInfo = Factory.New<IRuntimeFileInfo>(temporaryFolderPath);
+					Directory.CreateDirectory (temporaryFolderPath);
+                    _temporaryDirectoryInfo = temporaryFolderInfo;
+                }
+                
+                return _temporaryDirectoryInfo;
+            }
+        }
+        
+        public void NotifyFileChanged()
+        {
+            OnChanged();
+        }
+        
+        protected virtual void OnChanged()
+        {
+            EventHandler<EventArgs> handler = FileChanged;
+            if (handler != null)
+            {
+                handler(this, new EventArgs());
+            }
+        }
+        
+        public event EventHandler<EventArgs> FileChanged;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/AboutThisAssembly.txt b/Axantum.AxCrypt.iOS/AboutThisAssembly.txt
new file mode 100644
index 0000000..f0a5adf
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/AboutThisAssembly.txt
@@ -0,0 +1,8 @@
+About Axantum.AxCrypt.iOS
+
+This assembly contains the source code for the AxCrypt iOS application.
+
+NOTE: You must build Axantum.AxCrypt.Core.dll separately for 'Debug' and 'Release' configuration as needed.
+      This is built by the AxCrypt.NET solution, which can be loaded simultaneously into MonoDevelop for
+      a reasonably convenient workspace environment.
+      
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/AppDelegate.cs b/Axantum.AxCrypt.iOS/AppDelegate.cs
new file mode 100644
index 0000000..256174b
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/AppDelegate.cs
@@ -0,0 +1,279 @@
+using System;
+using System.IO;
+using MonoTouch.Foundation;
+using MonoTouch.MessageUI;
+using MonoTouch.UIKit;
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.iOS.Infrastructure;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Mono;
+
+namespace Axantum.AxCrypt.iOS
+{
+	// The UIApplicationDelegate for the application. This class is responsible for launching the 
+	// User Interface of the application, as well as listening (and optionally responding) to 
+	// application events from iOS.
+	[Register ("AppDelegate")]
+	public partial class AppDelegate : UIApplicationDelegate
+	{
+		public string AppVersion {
+			get {
+				return NSBundle.MainBundle.ObjectForInfoDictionary ("CFBundleVersion").ToString ();
+			}
+		}
+
+		public static AppDelegate Current {
+			get;
+			private set;
+		}
+
+		// class-level declarations
+		MainViewController appViewController;
+		FileListingViewController fileListingViewController;
+		PassphraseController passphraseController;
+		DecryptionViewController decryptionViewController;
+		FilePresenter filePresenter;
+		MFMailComposeViewController feedbackMailViewController;
+		WebViewController webViewController;
+		bool isReceivingFile = false;
+
+		public override UIWindow Window {
+			get;
+			set;
+		}
+
+		//
+		// This method is invoked when the application has loaded and is ready to run. In this 
+		// method you should instantiate the window, load the UI into it and then make the window
+		// visible.
+		//
+		// You have 17 seconds to return from this method, or iOS will terminate your application.
+		//
+		public override bool FinishedLaunching (UIApplication application, NSDictionary launchOptions)
+		{
+			AppDelegate.Current = this;
+			RegisterTypeFactories ();
+			appViewController = new MainViewController();
+			appViewController.OnAboutButtonTapped += ShowAbout;
+			appViewController.OnFaqButtonTapped += ShowFaq;
+			appViewController.OnFeedbackButtonTapped += ShowFeedbackUi;
+			appViewController.OnLocalFilesButtonTapped += ShowLocalFiles;
+			appViewController.OnRecentFilesButtonTapped += ShowRecentFiles;
+			appViewController.OnTroubleshootingButtonTapped += ShowTroubleshooting;
+
+			Window = new UIWindow(UIScreen.MainScreen.Bounds);
+			Window.RootViewController = appViewController;
+			Window.MakeKeyAndVisible ();
+			return true;
+		}
+
+		public void RegisterTypeFactories()
+		{
+			Factory.Instance.Singleton<IRuntimeEnvironment>(() => new RuntimeEnvironment(".axx"));
+		}
+
+		void ShowAbout() {
+			PresentWebViewController ("http://monodeveloper.org/axcrypt-for-ios/");
+		}
+
+		void ShowFaq() {
+			PresentWebViewController ("http://monodeveloper.org/axcrypt-ios-faq/");
+		}
+
+		void ShowTroubleshooting() {
+			PresentWebViewController ("http://monodeveloper.org/axcrypt-ios-troubleshooting/");
+		}
+
+		void FreeWebViewController() {
+			Free (ref webViewController);
+		}
+
+		void PresentWebViewController(string url) {
+			FreeWebViewController ();
+			webViewController = new WebViewController (url);
+			webViewController.Done += FreeWebViewController;
+			appViewController.PresentViewController (this.webViewController, true, null);
+		}
+
+		void ShowFeedbackUi() {
+			if (!MFMailComposeViewController.CanSendMail) {
+				PresentWebViewController ("http://monodeveloper.org/axcrypt-ios-feedback/");
+				return;
+			}
+
+			FreeFeedbackViewController ();
+			feedbackMailViewController = new MFMailComposeViewController ();
+			feedbackMailViewController.SetToRecipients (new[] { "sami.lamti+axcrypt-ios-feedback at tretton37.com" });
+			feedbackMailViewController.SetSubject (String.Concat ("Feedback on AxCrypt for iOS v", AppVersion));
+			feedbackMailViewController.Finished += delegate {
+				FreeFeedbackViewController ();
+			}; 
+
+			appViewController.PresentViewController (feedbackMailViewController, true, null);
+		}
+
+		void ShowLocalFiles() {
+			ShowFileListing ("Transferred documents", BasePath.TransferredFilesId);
+		}
+
+		void ShowRecentFiles() {
+			ShowFileListing("Received documents", BasePath.ReceivedFilesId);
+		}
+
+		UIPopoverController pop;
+		void ShowFileListing(string caption, int basePathId) {
+			FreeFileListingViewController ();
+			fileListingViewController = new FileListingViewController (caption, basePathId);
+			fileListingViewController.OpenFile += HandleOpenFile;
+			fileListingViewController.Done += FreeFileListingViewController;
+
+			if (Utilities.UserInterfaceIdiomIsPhone) {
+				appViewController.PresentViewController (fileListingViewController, true, null);
+			} else {
+				pop = new UIPopoverController (fileListingViewController);
+				pop.PresentFromRect(
+					appViewController.TableView.TableHeaderView.Frame,
+					appViewController.TableView.TableHeaderView,
+					UIPopoverArrowDirection.Up,
+					true);
+
+			}
+		}
+
+		static void Free<T> (ref T viewController) where T: UIViewController
+		{
+			if (viewController == null)
+				return;
+			viewController.RemoveFromParentViewController ();
+			viewController.Dispose ();
+			viewController = null;
+		}
+
+		void FreeFileListingViewController() {
+			if (fileListingViewController == null)
+				return;
+			fileListingViewController.OpenFile -= HandleOpenFile;
+			fileListingViewController.Done -= FreeFileListingViewController;
+			Free (ref fileListingViewController);
+		}
+
+		void FreePassphraseViewController() {
+			if (passphraseController == null)
+				return;
+			passphraseController.Dispose();
+			passphraseController = null;
+		}
+
+		void FreeDecryptionViewController() {
+			Free (ref decryptionViewController);
+		}
+
+		void FreeFilePresenter() {
+			if (filePresenter == null)
+				return;
+			filePresenter.Dispose ();
+			filePresenter = null;
+		}
+		
+		// This method is invoked when the application is about to move from active to inactive state.
+		// OpenGL applications should use this method to pause.
+		public override void OnResignActivation (UIApplication application)
+		{
+			FreePassphraseViewController();
+			FreeDecryptionViewController();
+			if (filePresenter != null)
+				filePresenter.Dismiss ();
+		}
+		
+		// This method should be used to release shared resources and it should store the application state.
+		// If your application supports background exection this method is called instead of WillTerminate
+		// when the user quits.
+		public override void DidEnterBackground (UIApplication application)
+		{
+		}
+
+		public override void OnActivated (UIApplication application)
+		{
+			if (filePresenter != null && !isReceivingFile) {
+				FreeFilePresenter ();
+				isReceivingFile = false;
+			}
+		}
+
+		/// This method is called as part of the transiton from background to active state.
+		public override void WillEnterForeground (UIApplication application)
+		{
+		}
+
+		/// This method is called when the application is about to terminate. Save data, if needed. 
+		public override void WillTerminate (UIApplication application)
+		{
+		}
+
+		void FreeViewControllers() {
+			if (passphraseController != null)
+				FreePassphraseViewController ();
+			if (decryptionViewController != null)
+				FreeDecryptionViewController ();
+		}
+
+		void FreeFeedbackViewController() {
+			if (feedbackMailViewController == null)
+				return;
+			feedbackMailViewController.DismissViewController (false, (NSAction) delegate {
+				Free(ref feedbackMailViewController);
+			});
+		}
+
+		public void HandleOpenFile(string filePath) {
+ 			FreePassphraseViewController ();
+			FreeDecryptionViewController ();
+			FreeFilePresenter ();
+			FreeFeedbackViewController ();
+
+			passphraseController = new PassphraseController (filePath);
+			decryptionViewController = new DecryptionViewController (filePath);
+			filePresenter = new FilePresenter ();
+
+			passphraseController.Done += decryptionViewController.Decrypt;
+			passphraseController.Cancelled += FreeViewControllers;
+			decryptionViewController.Succeeded += targetFileName => {
+				FreeViewControllers();
+
+				if (fileListingViewController != null) {
+					appViewController.DismissViewController(true, (NSAction)delegate { 
+						FreeFileListingViewController();
+						filePresenter.Present (targetFileName, appViewController);
+					});
+					return;
+				}
+				filePresenter.Present (targetFileName, appViewController);
+
+			};
+			decryptionViewController.Failed += passphraseController.AskForPassword;
+			filePresenter.Done += delegate {
+				FreeViewControllers();
+				FreeFilePresenter();
+			};
+
+			passphraseController.AskForPassword ();
+		}
+
+		public override bool OpenUrl (UIApplication application, NSUrl url, string sourceApplication, NSObject annotation)
+		{
+			string targetPath = Path.Combine(
+				Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), 
+				"Recent",
+				Path.GetFileName(url.Path));
+			if (File.Exists (targetPath))
+				File.Delete (targetPath);
+			File.Move(url.Path, targetPath);
+
+			HandleOpenFile(targetPath);
+			isReceivingFile = true;
+
+			return true;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/AxCrypt.Mono/DataProtection.cs b/Axantum.AxCrypt.iOS/AxCrypt.Mono/DataProtection.cs
new file mode 100644
index 0000000..48076a8
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/AxCrypt.Mono/DataProtection.cs
@@ -0,0 +1,19 @@
+using System;
+using Axantum.AxCrypt.Core.Runtime;
+
+namespace Axantum.AxCrypt.Mono
+{
+	internal class DataProtection : IDataProtection
+	{
+		public byte[] Protect(byte[] unprotectedData)
+		{
+			return unprotectedData;
+		}
+		
+		public byte[] Unprotect(byte[] protectedData)
+		{
+			return protectedData;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/AxCrypt.Mono/FileWatcher.cs b/Axantum.AxCrypt.iOS/AxCrypt.Mono/FileWatcher.cs
new file mode 100644
index 0000000..598252f
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/AxCrypt.Mono/FileWatcher.cs
@@ -0,0 +1,24 @@
+using System;
+using Axantum.AxCrypt.Core.IO;
+
+namespace Axantum.AxCrypt.Mono
+{
+	internal class FileWatcher : IFileWatcher, IDisposable
+	{
+		public FileWatcher (string path)
+		{
+		}
+
+		public event EventHandler<FileWatcherEventArgs> FileChanged {
+			add {
+
+			}
+			remove {
+
+			}
+		}
+
+		public void Dispose() {}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.csproj b/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.csproj
new file mode 100644
index 0000000..8890144
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.csproj
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{3773A07A-71B7-474C-A622-21ED8B8492DD}</ProjectGuid>
+    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>Axantum.AxCrypt.iOS</RootNamespace>
+    <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+    <AssemblyName>AxantumAxCryptiOS</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchDebug>True</MtouchDebug>
+    <MtouchLink>None</MtouchLink>
+    <MtouchArch>ARMv7</MtouchArch>
+    <MtouchI18n>west</MtouchI18n>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+    <MtouchUseLlvm>True</MtouchUseLlvm>
+    <MtouchArch>ARMv7</MtouchArch>
+    <MtouchI18n>
+    </MtouchI18n>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchDebug>True</MtouchDebug>
+    <MtouchArch>ARMv7</MtouchArch>
+    <IpaPackageName>
+    </IpaPackageName>
+    <MtouchI18n>west</MtouchI18n>
+    <CodesignProvision>9DA52B33-9272-40CD-9415-64FF17ADC82E</CodesignProvision>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+    <MtouchArch>ARMv7</MtouchArch>
+    <MtouchI18n>west</MtouchI18n>
+    <CustomCommands>
+      <CustomCommands>
+        <Command type="BeforeBuild" command="mkdir -p ${ProjectDir}/bin" />
+        <Command type="BeforeBuild" command="cp ${SolutionDir}/Axantum.AxCrypt.Core/bin/Release/Axantum.AxCrypt.Core.dll ${ProjectDir}/bin" />
+      </CustomCommands>
+    </CustomCommands>
+    <MtouchUseLlvm>True</MtouchUseLlvm>
+    <MtouchLink>Full</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\Ad-Hoc</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <BuildIpa>True</BuildIpa>
+    <CodesignKey>iPhone Developer: Martina Gawell (RYTWD8L3NQ)</CodesignKey>
+    <MtouchArch>ARMv7</MtouchArch>
+    <MtouchI18n>west</MtouchI18n>
+    <IpaPackageName>
+    </IpaPackageName>
+    <CodesignProvision>9DA52B33-9272-40CD-9415-64FF17ADC82E</CodesignProvision>
+    <MtouchUseLlvm>True</MtouchUseLlvm>
+    <MtouchUseThumb>True</MtouchUseThumb>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\AppStore</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+    <CodesignProvision>Automatic:AppStore</CodesignProvision>
+    <MtouchArch>ARMv7</MtouchArch>
+    <MtouchI18n>west</MtouchI18n>
+    <IpaPackageName>
+    </IpaPackageName>
+    <MtouchUseLlvm>True</MtouchUseLlvm>
+    <MtouchUseThumb>True</MtouchUseThumb>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="monotouch" />
+    <Reference Include="MonoTouch.Dialog-1" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="BTProgressHUD">
+      <HintPath>Components\btprogresshud-1.5\lib\ios\BTProgressHUD.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+    <None Include="AboutThisAssembly.txt" />
+    <None Include="Images\AppStore Images\iPad %28Retina%29\About.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPad %28Retina%29\Document with actions.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPad %28Retina%29\Main View.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPad %28Retina%29\Password entry.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 3.5in\Document with actions.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 3.5in\Main View.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 3.5in\Password entry.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 3.5in\Received documents.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 3.5in\Transferred documents.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 4in\Document with actions.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 4in\Main View.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 4in\Password entry.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 4in\Received documents.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+    <None Include="Images\AppStore Images\iPhone 4in\Transferred documents.png">
+      <Gettext-ScanForTranslations>False</Gettext-ScanForTranslations>
+    </None>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="AppDelegate.cs" />
+    <Compile Include="FilePresenter.cs" />
+    <Compile Include="Infrastructure\UIAlertViewOkCancelDelegate.cs" />
+    <Compile Include="Infrastructure\EditableTableViewSource.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="..\Axantum.AxCrypt.MonoTouch\DataProtection.cs">
+      <Link>AxCrypt.MonoTouch\DataProtection.cs</Link>
+    </Compile>
+    <Compile Include="..\Axantum.AxCrypt.MonoTouch\FileWatcher.cs">
+      <Link>AxCrypt.MonoTouch\FileWatcher.cs</Link>
+    </Compile>
+    <Compile Include="FileListingViewController.cs" />
+    <Compile Include="MainViewController.cs" />
+    <Compile Include="Infrastructure\Theme.cs" />
+    <Compile Include="Infrastructure\Utilities.cs" />
+    <Compile Include="Infrastructure\ThemedStringElement.cs" />
+    <Compile Include="DecryptionViewController.cs" />
+    <Compile Include="PassphraseController.cs" />
+    <Compile Include="WebViewController.cs" />
+    <Compile Include="Infrastructure\ThemedFileElement.cs" />
+    <Compile Include="Infrastructure\BasePath.cs" />
+  </ItemGroup>
+  <Import Project="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.projitems" Label="Shared" Condition="Exists('..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.projitems')" />
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <Content Include="Images\logo.png" />
+    <Content Include="Images\App Icons\logo 57x57.png" />
+    <Content Include="Images\App Icons\logo 114x114.png" />
+    <Content Include="Images\App Icons\logo 72x72.png" />
+    <Content Include="Images\App Icons\logo 144x144.png" />
+    <Content Include="Images\Spotlight & Settings Icons\logo 100x100.png" />
+    <Content Include="Images\Spotlight & Settings Icons\logo 29x29.png" />
+    <Content Include="Images\Spotlight & Settings Icons\logo 50x50.png" />
+    <Content Include="Images\Spotlight & Settings Icons\logo 58x58.png" />
+    <Content Include="Images\iTunes Artwork\iTunes Artwork 512x512.png" />
+    <Content Include="Images\iTunes Artwork\iTunes Artwork 1024x1024.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Images\" />
+    <Folder Include="Images\App Icons\" />
+    <Folder Include="Images\Spotlight & Settings Icons\" />
+    <Folder Include="Infrastructure\" />
+    <Folder Include="Images\iTunes Artwork\" />
+    <Folder Include="Properties\" />
+    <Folder Include="AxCrypt.MonoTouch\" />
+    <Folder Include="Images\AppStore Images\" />
+    <Folder Include="Images\AppStore Images\iPad %28Retina%29\" />
+    <Folder Include="Images\AppStore Images\iPhone 3.5in\" />
+    <Folder Include="Images\AppStore Images\iPhone 4in\" />
+  </ItemGroup>
+  <ItemGroup>
+    <ITunesArtwork Include="iTunesArtwork" />
+    <ITunesArtwork Include="iTunesArtwork%402x" />
+  </ItemGroup>
+  <ItemGroup>
+    <BundleResource Include="Resources\Default-568h%402x.png" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959F7F85-C98B-4876-971A-9036224578E4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.sln b/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.sln
new file mode 100644
index 0000000..c5ababa
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Axantum.AxCrypt.iOS.sln
@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Axantum.AxCrypt.iOS", "Axantum.AxCrypt.iOS.csproj", "{3773A07A-71B7-474C-A622-21ED8B8492DD}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Debug|iPhone = Debug|iPhone
+		Release|iPhone = Release|iPhone
+		Ad-Hoc|iPhone = Ad-Hoc|iPhone
+		AppStore|iPhone = AppStore|iPhone
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.AppStore|iPhone.Build.0 = AppStore|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhone.Build.0 = Debug|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhone.ActiveCfg = Release|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhone.Build.0 = Release|iPhone
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{3773A07A-71B7-474C-A622-21ED8B8492DD}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = Axantum.AxCrypt.iOS.csproj
+	EndGlobalSection
+EndGlobal
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.info b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.info
new file mode 100644
index 0000000..9f528b5
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.info
@@ -0,0 +1 @@
+{"Name":"BTProgressHUD","Id":197,"Alias":"btprogresshud","Description":"BTProgressHUD is a HUD - heads up display - for your application. It allows you to show transient information to the user, to keep them informed of longer running tasks and alerts.\n\nBTProgressHUD is based on the iOS [SVProgressHUD](https://github.com/samvermette/SVProgressHUD) project.\n\n```csharp\nusing BigTed;\n...\n\npublic override void ViewDidAppear (bool animated)\n{\n\tbase.ViewDidAppear (animated);\n\t\n\t [...]
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.png
new file mode 100644
index 0000000..21f7c37
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Details.md b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Details.md
new file mode 100644
index 0000000..6f1cff9
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Details.md
@@ -0,0 +1,32 @@
+BTProgressHUD is a HUD - heads up display - for your application. It allows you to show transient information to the user, to keep them informed of longer running tasks and alerts.
+
+BTProgressHUD is based on the iOS [SVProgressHUD](https://github.com/samvermette/SVProgressHUD) project.
+
+```csharp
+using BigTed;
+...
+
+public override void ViewDidAppear (bool animated)
+{
+	base.ViewDidAppear (animated);
+	
+	//Show a HUD with a progress spinner and the text
+	BTProgressHUD.Show("Hello there!");
+	
+	//you will need to hide it somewhere else
+	//BTProgressHUD.Dismiss();
+}
+
+```
+
+There are other forms of HUD: 
+
+* Spinner only
+* Spinner and text
+* Progress
+* Image and text
+* Toast, modelled after the [Android Toast](http://developer.android.com/guide/topics/ui/notifiers/toasts.html) display.
+
+Source code can be found on [GitHub](https://github.com/nicwise/BTProgressHUD/).
+
+Some screenshots assembled with [PlaceIt](http://placeit.breezi.com/).
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/GettingStarted.md b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/GettingStarted.md
new file mode 100644
index 0000000..ee49db6
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/GettingStarted.md
@@ -0,0 +1,69 @@
+#Usage
+
+Have a look at the BTProgressHUDDemo project.
+
+Firstly, you need to use the BigTed namespace
+
+```csharp
+using BigTed;
+```
+
+Then, there are a few main static methods for showing the HUD:
+
+```csharp
+BTProgressHUD.Show(); //shows the spinner
+BTProgressHUD.Show("Oh hai"); //show spinner + text
+BTProgressHUD.ShowSuccessWithStatus("Wow, that worked"); //A big TICK with text
+BTProgressHUD.ShowErrorWithStatus("Fail!"); //A big CROSS with text
+BTProgressHUD.ShowToast("Hello from Toast"); //show an Android-style toast
+```
+All of these can be dismissed, once your processing is finished, with
+
+```csharp
+BTProgressHUD.Dismiss();
+```
+
+ShowToast, ShowSuccessWithStatus, ShowErrorWithStatus, and ShowImage all auto-dismiss.
+
+BTProgressHUD is aware of the thread you are calling from, and ensures that HUDs are always manipulated from the UI thread.
+
+
+#Other Show options
+
+You can call Show with the following parameters
+
+* status: <string> - show status text
+* progress: <float> - show a progress circle with 0.0 - 1.0 of progress. Call again to change the progress.
+* maskType: <BTProgressHUD.MaskType> - show with the background (the whole window) clear, black or gradient. Default is none, which allows interaction with the underlying elements.
+
+```csharp
+public enum MaskType
+{
+	None = 1, // allow user interactions, don't dim background UI (default)
+	Clear, // disable user interactions, don't dim background UI
+	Black, // disable user interactions, dim background UI with 50% translucent black
+	Gradient // disable user interactions, dim background UI with translucent radial gradient (a-la-alertView)
+}
+```
+
+#ShowToast
+The toast can be centered or at the bottom of the screen, like Android. This is controlled by the second parameter.
+
+```csharp
+BTProgressHUD.ShowToast ("Your download finished", showToastCentered: false);
+```
+
+#ShowSuccess/Error/ShowImage
+This method dismisses the activity after 1 second. You can provide your own images if needed - make them 28x28 white PNGs.
+
+```csharp
+BTProgressHUD.ShowSuccessWithStatus ("Wow, that worked"); //A big TICK with text
+BTProgressHUD.ShowErrorWithStatus ("Fail!"); //A big CROSS with text
+BTProgressHUD.ShowImage (UIImage.FromFile("an-image-file.png"), "Nice one Stu!");
+```
+
+You can use the timeout parameter of ShowImage to control the time before it's dismissed.
+
+# Other Resources
+
+* [Source code](https://github.com/nicwise/BTProgressHUD/)
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/License.md b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/License.md
new file mode 100644
index 0000000..2f63d40
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/License.md
@@ -0,0 +1,44 @@
+Copyright 2013 Nic Wise / Big Ted Ltd and Sam Vermette
+
+BTProgressHUD:
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+SVProgressHUD:
+
+Copyright (c) 2011 Sam Vermette
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+A different license may apply to other ressources included in this package, 
+including Joseph Wain's Glyphish Icons. Please consult their 
+respective headers for the terms of their individual licenses.
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Manifest.xml b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Manifest.xml
new file mode 100644
index 0000000..ce0d6ac
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/Manifest.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<component format="1" id="btprogresshud">
+  <name>BTProgressHUD</name>
+  <publisher>Nic Wise / Big Ted Ltd</publisher>
+  <publisher-url>http://fastchicken.co.nz/</publisher-url>
+  <version>1.5</version>
+  <summary>Add awesome HUDs to your iOS apps.</summary>
+  <samples>
+    <sample id="BTProgressHUDSample">
+      <name>iOS Sample.</name>
+      <summary>Demonstrates how to use the component on iOS.</summary>
+    </sample>
+  </samples>
+</component>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_128x128.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_128x128.png
new file mode 100644
index 0000000..21f7c37
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_128x128.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_512x512.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_512x512.png
new file mode 100644
index 0000000..c6c5303
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/component/icons/btprogresshud_512x512.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/lib/ios/BTProgressHUD.dll b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/lib/ios/BTProgressHUD.dll
new file mode 100644
index 0000000..79b0bc1
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/lib/ios/BTProgressHUD.dll differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUD.dll b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUD.dll
new file mode 100644
index 0000000..79b0bc1
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUD.dll differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample.sln b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample.sln
new file mode 100644
index 0000000..f0ddc3b
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample.sln
@@ -0,0 +1,32 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BTProgressHUDDemo", "BTProgressHUDSample\BTProgressHUDDemo.csproj", "{E6E84D09-BE15-460D-A317-45248BE1C56F}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|iPhoneSimulator = Debug|iPhoneSimulator
+		Release|iPhoneSimulator = Release|iPhoneSimulator
+		Debug|iPhone = Debug|iPhone
+		Release|iPhone = Release|iPhone
+		Ad-Hoc|iPhone = Ad-Hoc|iPhone
+		AppStore|iPhone = AppStore|iPhone
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Ad-Hoc|iPhone.ActiveCfg = Ad-Hoc|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Ad-Hoc|iPhone.Build.0 = Ad-Hoc|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.AppStore|iPhone.ActiveCfg = AppStore|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.AppStore|iPhone.Build.0 = AppStore|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Debug|iPhone.ActiveCfg = Debug|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Debug|iPhone.Build.0 = Debug|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Release|iPhone.ActiveCfg = Release|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Release|iPhone.Build.0 = Release|iPhone
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
+		{E6E84D09-BE15-460D-A317-45248BE1C56F}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = BTProgressHUDSample\BTProgressHUDDemo.csproj
+	EndGlobalSection
+EndGlobal
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/AppDelegate.cs b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/AppDelegate.cs
new file mode 100644
index 0000000..71e1a7e
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/AppDelegate.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+
+namespace BTProgressHUDDemo
+{
+	// The UIApplicationDelegate for the application. This class is responsible for launching the 
+	// User Interface of the application, as well as listening (and optionally responding) to 
+	// application events from iOS.
+	[Register ("AppDelegate")]
+	public partial class AppDelegate : UIApplicationDelegate
+	{
+		// class-level declarations
+		UIWindow window;
+
+		//
+		// This method is invoked when the application has loaded and is ready to run. In this 
+		// method you should instantiate the window, load the UI into it and then make the window
+		// visible.
+		//
+		// You have 17 seconds to return from this method, or iOS will terminate your application.
+		//
+
+		MainViewController viewController;
+		public override bool FinishedLaunching (UIApplication app, NSDictionary options)
+		{
+			// create a new window instance based on the screen size
+			window = new UIWindow (UIScreen.MainScreen.Bounds);
+			
+			// If you have defined a root view controller, set it here:
+			// window.RootViewController = myViewController;
+
+			viewController = new MainViewController ();
+			window.RootViewController = viewController;
+
+
+			// make the window visible
+			window.MakeKeyAndVisible ();
+			
+			return true;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/BTProgressHUDDemo.csproj b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/BTProgressHUDDemo.csproj
new file mode 100644
index 0000000..c3b6e8d
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/BTProgressHUDDemo.csproj
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
+    <ProductVersion>10.0.0</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{E6E84D09-BE15-460D-A317-45248BE1C56F}</ProjectGuid>
+    <ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>BTProgressHUDDemo</RootNamespace>
+    <IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
+    <AssemblyName>BTProgressHUDDemo</AssemblyName>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+    <MtouchDebug>True</MtouchDebug>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhoneSimulator\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchLink>None</MtouchLink>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
+    <DebugSymbols>True</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>False</Optimize>
+    <OutputPath>bin\iPhone\Debug</OutputPath>
+    <DefineConstants>DEBUG;</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <MtouchDebug>True</MtouchDebug>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\Release</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Developer</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\Ad-Hoc</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <BuildIpa>True</BuildIpa>
+    <ConsolePause>False</ConsolePause>
+    <CodesignProvision>Automatic:AdHoc</CodesignProvision>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' ">
+    <DebugType>none</DebugType>
+    <Optimize>True</Optimize>
+    <OutputPath>bin\iPhone\AppStore</OutputPath>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <ConsolePause>False</ConsolePause>
+    <CodesignKey>iPhone Distribution</CodesignKey>
+    <CodesignProvision>Automatic:AppStore</CodesignProvision>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Core" />
+    <Reference Include="monotouch" />
+    <Reference Include="BTProgressHUD">
+      <HintPath>../../../lib\/ios/BTProgressHUD.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Resources\" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Info.plist" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Main.cs" />
+    <Compile Include="AppDelegate.cs" />
+    <Compile Include="MainView.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <ItemGroup>
+    <BundleResource Include="Default.png" />
+    <BundleResource Include="Default%402x.png" />
+    <BundleResource Include="Default-568h%402x.png" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default-568h at 2x.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default-568h at 2x.png
new file mode 100644
index 0000000..12bae24
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default-568h at 2x.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default.png
new file mode 100644
index 0000000..d7ada46
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default at 2x.png b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default at 2x.png
new file mode 100644
index 0000000..07d3eea
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Default at 2x.png differ
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Info.plist b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Info.plist
new file mode 100644
index 0000000..f359540
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Info.plist
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+		<integer>2</integer>
+	</array>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>MinimumOSVersion</key>
+	<string>5.0</string>
+</dict>
+</plist>
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Main.cs b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Main.cs
new file mode 100644
index 0000000..95fe1e8
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/Main.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using MonoTouch.Foundation;
+using MonoTouch.UIKit;
+
+namespace BTProgressHUDDemo
+{
+	public class Application
+	{
+		// This is the main entry point of the application.
+		static void Main (string[] args)
+		{
+			// if you want to use a different Application Delegate class from "AppDelegate"
+			// you can specify it here.
+			UIApplication.Main (args, null, "AppDelegate");
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/MainView.cs b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/MainView.cs
new file mode 100644
index 0000000..cf14310
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Components/btprogresshud-1.5/samples/BTProgressHUDSample/BTProgressHUDSample/MainView.cs
@@ -0,0 +1,124 @@
+using System;
+using MonoTouch.UIKit;
+using BigTed;
+using System.Threading;
+using System.Drawing;
+using System.Collections.Generic;
+using MonoTouch.Foundation;
+
+namespace BTProgressHUDDemo
+{
+	public class MainViewController : UIViewController
+	{
+		public MainViewController ()
+		{
+
+		}
+		UITextView text;
+		float progress = -1;
+		NSTimer timer;
+		public override void LoadView ()
+		{
+			base.LoadView ();
+			View.BackgroundColor = UIColor.LightGray;
+
+			MakeButton ("Show", () => {
+				BTProgressHUD.Show (); 
+				KillAfter ();
+			});
+
+			MakeButton ("Show Message", () => {
+				BTProgressHUD.Show (status: "Processing your image"); 
+				KillAfter ();
+			});
+
+			MakeButton ("Show Success", () => {
+				BTProgressHUD.ShowSuccessWithStatus("Great success!") ;
+			});
+
+			MakeButton ("Show Fail", () => {
+				BTProgressHUD.ShowErrorWithStatus("Oh, thats bad") ;
+			});
+
+			MakeButton ("Toast", () => {
+				BTProgressHUD.ShowToast("Hello from the toast", showToastCentered: false) ;
+
+			});
+
+
+			MakeButton ("Dismiss", () => {
+				BTProgressHUD.Dismiss (); 
+			});
+
+			MakeButton ("Progress", () => {
+				progress = 0;
+				BTProgressHUD.Show("Hello!", progress);
+				if (timer != null) 
+				{
+					timer.Invalidate();
+				}
+				timer = NSTimer.CreateRepeatingTimer(0.5f, delegate {
+					progress += 0.1f;
+					if (progress > 1)
+					{
+						timer.Invalidate();
+						timer = null;
+						BTProgressHUD.Dismiss();
+					} else {
+						BTProgressHUD.Show ("Hello!", progress);
+					}
+
+
+				});
+				NSRunLoop.Current.AddTimer(timer, NSRunLoopMode.Common);
+			});
+
+			MakeButton ("Dismiss", () => {
+				BTProgressHUD.Dismiss (); 
+			});
+
+		}
+
+		void KillAfter (float timeout = 1)
+		{
+			if (timer != null) 
+			{
+				timer.Invalidate();
+			}
+			timer = NSTimer.CreateRepeatingTimer(timeout, delegate {
+				BTProgressHUD.Dismiss();
+			});
+			NSRunLoop.Current.AddTimer(timer, NSRunLoopMode.Common);
+		}
+		float y = 20;
+		void MakeButton(string text, Action del)
+		{
+			float x = 20;
+
+			var button = new UIButton (UIButtonType.RoundedRect);
+			button.Frame = new RectangleF (x, y, 280, 40);
+			button.SetTitle (text, UIControlState.Normal);
+			button.TouchUpInside += (o,e) => {
+				del() ;
+			};
+			View.Add (button);
+		
+			
+			y += 45;
+
+		}
+
+		public override void ViewDidLoad ()
+		{
+			base.ViewDidLoad ();
+		
+		}
+
+		public override void ViewDidAppear (bool animated)
+		{
+			base.ViewDidAppear (animated);
+
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/DecryptionViewController.cs b/Axantum.AxCrypt.iOS/DecryptionViewController.cs
new file mode 100644
index 0000000..98fed14
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/DecryptionViewController.cs
@@ -0,0 +1,79 @@
+using System;
+using MonoTouch.UIKit;
+using Axantum.AxCrypt.Core.Crypto;
+using System.IO;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.Runtime;
+using MonoTouch.Foundation;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core;
+using BigTed;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public class DecryptionViewController : UIViewController
+	{
+		public event Action<string> Succeeded = delegate {};
+		public event Action Failed = delegate {};
+
+		ProgressContext context;
+		IThreadWorker worker;
+		IRuntimeFileInfo sourceFile;
+		Passphrase key;
+		string targetFilePath;
+
+		public DecryptionViewController (string sourceFilePath)
+		{
+			this.context = new ProgressContext ();
+			//			context.Progressing += (sender, e) => {
+			//				SetProgress(e.Percent, "Decrypting ...");
+			//			};
+			this.sourceFile = Factory.New<IRuntimeFileInfo>(sourceFilePath);
+		}
+
+		void CreateWorker() {
+			this.worker = Instance.Portable.ThreadWorker(this.context, false);
+			//worker.Prepare += delegate { SetProgress(0, "Unlocking ..."); };
+			worker.Work += Work;
+			worker.Completed += WorkerCompleted;
+		}
+
+		void Work(object sender, ThreadWorkerEventArgs args) {
+			using (NSAutoreleasePool pool = new NSAutoreleasePool()) {
+				string targetDirectory = Path.GetTempPath();
+				string extractedFileName = Factory.New<AxCryptFile>().Decrypt(
+					this.sourceFile, 
+					targetDirectory, 
+					this.key, 
+					AxCryptOptions.None, 
+					this.context);
+
+				if (extractedFileName == null) {
+					args.Result = new FileOperationContext(sourceFile.Name, FileOperationStatus.Canceled);
+					return;
+				}
+
+				this.targetFilePath = Path.Combine(targetDirectory,	extractedFileName);
+				args.Result = new FileOperationContext(sourceFile.Name, FileOperationStatus.Success);
+			}
+		}
+
+		void WorkerCompleted(object sender, ThreadWorkerEventArgs args) {
+			BTProgressHUD.Dismiss ();
+			if (args.Result.Status == FileOperationStatus.Canceled) {
+				Failed();
+				return;
+			}
+
+			Succeeded(this.targetFilePath);
+		}
+
+		public void Decrypt(Passphrase passphrase) {
+			BTProgressHUD.Show ("Opening ...", maskType: BTProgressHUD.MaskType.Gradient);
+			CreateWorker ();
+			this.key = passphrase;
+			worker.Run();
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/FileListingViewController.cs b/Axantum.AxCrypt.iOS/FileListingViewController.cs
new file mode 100644
index 0000000..fb156d9
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/FileListingViewController.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using MonoTouch.Dialog;
+using MonoTouch.UIKit;
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.iOS.Infrastructure;
+using MonoTouch.Foundation;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public partial class FileListingViewController : DialogViewController
+	{
+		public event Action<string> OpenFile = delegate {};
+		public event Action Done = delegate {};
+
+		Section fileSection;
+		int basePathId;
+
+		public FileListingViewController (string title, int pathId) : base (UITableViewStyle.Plain, new RootElement(title), false)
+		{
+			basePathId = pathId;
+			fileSection = new Section ();
+			Root.Add (fileSection);
+
+			if (Utilities.UserInterfaceIdiomIsPhone) {
+				ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
+				ModalTransitionStyle = UIModalTransitionStyle.PartialCurl;
+			} else {
+				ModalPresentationStyle = UIModalPresentationStyle.CurrentContext;
+				ModalTransitionStyle = UIModalTransitionStyle.CoverVertical;
+			}
+		}
+
+		public override void Selected (NSIndexPath indexPath)
+		{
+			base.Selected (indexPath);
+			ThemedFileElement element = (ThemedFileElement)fileSection [indexPath.Row];
+			string targetPath = BasePath.Expand (element.Caption, element.PathId);
+			OpenFile (targetPath);
+		}
+
+		IEnumerable<ThemedFileElement> ReadFileSystem ()
+		{
+			string basePath = BasePath.GetBasePath (basePathId);
+			Directory.CreateDirectory (basePath);
+
+			return Directory.EnumerateFiles (basePath)
+				.Select (file => new { file, accessTime = File.GetLastAccessTime(file) })
+					.OrderByDescending (projection => projection.accessTime)
+					.Select(projection => new ThemedFileElement(projection.file, projection.accessTime, basePathId));
+		}
+
+
+		public override void ViewDidLoad ()
+		{
+			base.ViewDidLoad ();
+			Theme.Configure (Root.Caption, this);
+			TableView.Source = new EditableTableViewSource (this);
+		}
+
+		public override void ViewWillAppear (bool animated)
+		{
+			base.ViewWillAppear (animated);
+			Root [0].Clear ();
+			Root [0].AddAll (ReadFileSystem ());
+		}
+
+		public override void ViewDidDisappear (bool animated)
+		{
+			base.ViewDidDisappear (animated);
+			Done ();
+		}
+
+		public IEnumerable<Element> GetElements() {
+			foreach (ThemedFileElement element in ReadFileSystem ()) {
+				element.Tapped += () => OpenFile(BasePath.Expand(element.Caption, basePathId));
+				yield return element;
+			}
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/FilePresenter.cs b/Axantum.AxCrypt.iOS/FilePresenter.cs
new file mode 100644
index 0000000..5a9fa57
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/FilePresenter.cs
@@ -0,0 +1,77 @@
+using MonoTouch.UIKit;
+using System;
+using MonoTouch.Foundation;
+using System.Drawing;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public class FilePresenter : UIDocumentInteractionControllerDelegate
+	{
+		UIDocumentInteractionController documentInteractionController;
+		WeakReference<UIViewController> owner;
+
+		public event EventHandler ReadyToPresent = delegate {};
+		public event EventHandler Done = delegate {};
+
+		public FilePresenter ()
+		{
+			this.documentInteractionController = new UIDocumentInteractionController ();
+			this.documentInteractionController.Delegate = this;
+		}
+
+		public override UIViewController ViewControllerForPreview (UIDocumentInteractionController controller)
+		{
+			UIViewController value;
+			owner.TryGetTarget(out value);
+			return value;
+		}
+
+		public override void WillBeginPreview (UIDocumentInteractionController controller)
+		{
+			ReadyToPresent (controller, EventArgs.Empty);
+		}
+
+		public override void DidEndPreview (UIDocumentInteractionController controller)
+		{
+			Done (controller, EventArgs.Empty);
+		}
+
+		public override UIView ViewForPreview (UIDocumentInteractionController controller)
+		{
+			UIViewController vc = ViewControllerForPreview (controller);
+			if (vc == null)
+				return null;
+			return vc.View;
+		}
+
+		public override System.Drawing.RectangleF RectangleForPreview (UIDocumentInteractionController controller)
+		{
+			UIView view = ViewForPreview (controller);
+			if (view == null)
+				return RectangleF.Empty;
+			return view.Frame;
+		}
+
+		public void Present(string file, UIViewController owner) {
+			this.owner = new WeakReference<UIViewController>(owner);
+
+			NSUrl url = NSUrl.FromFilename (file);
+			this.documentInteractionController.Url = url;
+			this.documentInteractionController.PresentPreview(true);
+		}
+
+		public void Dismiss() {
+			documentInteractionController.Delegate = null;
+			documentInteractionController.DismissMenu (false);
+			documentInteractionController.DismissPreview (false);
+		}
+
+		protected override void Dispose (bool disposing)
+		{
+			base.Dispose (disposing);
+			documentInteractionController.Dispose ();
+			documentInteractionController = null;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Images/App Icons/logo 114x114.png b/Axantum.AxCrypt.iOS/Images/App Icons/logo 114x114.png
new file mode 100644
index 0000000..ae6e03f
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/App Icons/logo 114x114.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/App Icons/logo 144x144.png b/Axantum.AxCrypt.iOS/Images/App Icons/logo 144x144.png
new file mode 100644
index 0000000..7d9ce86
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/App Icons/logo 144x144.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/App Icons/logo 57x57.png b/Axantum.AxCrypt.iOS/Images/App Icons/logo 57x57.png
new file mode 100644
index 0000000..ad55cde
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/App Icons/logo 57x57.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/App Icons/logo 72x72.png b/Axantum.AxCrypt.iOS/Images/App Icons/logo 72x72.png
new file mode 100644
index 0000000..732895a
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/App Icons/logo 72x72.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/About.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/About.png
new file mode 100644
index 0000000..50a0733
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/About.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Document with actions.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Document with actions.png
new file mode 100644
index 0000000..2422020
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Document with actions.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Main View.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Main View.png
new file mode 100644
index 0000000..8fabe7f
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Main View.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Password entry.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Password entry.png
new file mode 100644
index 0000000..0c5fd44
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPad (Retina)/Password entry.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Document with actions.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Document with actions.png
new file mode 100644
index 0000000..5f66034
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Document with actions.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Main View.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Main View.png
new file mode 100644
index 0000000..764a545
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Main View.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Password entry.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Password entry.png
new file mode 100644
index 0000000..43e23bb
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Password entry.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Received documents.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Received documents.png
new file mode 100644
index 0000000..1b44e56
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Received documents.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Transferred documents.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Transferred documents.png
new file mode 100644
index 0000000..fb9e761
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 3.5in/Transferred documents.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Document with actions.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Document with actions.png
new file mode 100644
index 0000000..86ca931
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Document with actions.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Main View.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Main View.png
new file mode 100644
index 0000000..1537ac5
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Main View.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Password entry.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Password entry.png
new file mode 100644
index 0000000..1df7e25
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Password entry.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Received documents.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Received documents.png
new file mode 100644
index 0000000..44d11ee
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Received documents.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Transferred documents.png b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Transferred documents.png
new file mode 100644
index 0000000..0dc2f85
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/AppStore Images/iPhone 4in/Transferred documents.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 3.5in iOS Simulator Screen shot Oct 16, 2012 2.30.48 PM.png b/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 3.5in iOS Simulator Screen shot Oct 16, 2012 2.30.48 PM.png
new file mode 100644
index 0000000..cd74d36
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 3.5in iOS Simulator Screen shot Oct 16, 2012 2.30.48 PM.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 4in iOS Simulator Screen shot Oct 16, 2012 2.31.47 PM.png b/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 4in iOS Simulator Screen shot Oct 16, 2012 2.31.47 PM.png
new file mode 100644
index 0000000..15fc531
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Screenshots/RenamediPhone Retina 4in iOS Simulator Screen shot Oct 16, 2012 2.31.47 PM.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Screenshots/iPad Retina iOS Simulator Screen shot Oct 16, 2012 2.34.39 PM.png b/Axantum.AxCrypt.iOS/Images/Screenshots/iPad Retina iOS Simulator Screen shot Oct 16, 2012 2.34.39 PM.png
new file mode 100644
index 0000000..5dd649b
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Screenshots/iPad Retina iOS Simulator Screen shot Oct 16, 2012 2.34.39 PM.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Screenshots/iPad iOS Simulator Screen shot Oct 16, 2012 2.32.44 PM.png b/Axantum.AxCrypt.iOS/Images/Screenshots/iPad iOS Simulator Screen shot Oct 16, 2012 2.32.44 PM.png
new file mode 100644
index 0000000..ecf5a08
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Screenshots/iPad iOS Simulator Screen shot Oct 16, 2012 2.32.44 PM.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Screenshots/iPhone iOS Simulator Screen shot.png b/Axantum.AxCrypt.iOS/Images/Screenshots/iPhone iOS Simulator Screen shot.png
new file mode 100644
index 0000000..738592e
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Screenshots/iPhone iOS Simulator Screen shot.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 100x100.png b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 100x100.png
new file mode 100644
index 0000000..bf9c325
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 100x100.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 29x29.png b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 29x29.png
new file mode 100644
index 0000000..28793d2
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 29x29.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 50x50.png b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 50x50.png
new file mode 100644
index 0000000..f53c3e9
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 50x50.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 58x58.png b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 58x58.png
new file mode 100644
index 0000000..bde3ab6
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/Spotlight & Settings Icons/logo 58x58.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 1024x1024.png b/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 1024x1024.png
new file mode 100644
index 0000000..f911d75
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 1024x1024.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 512x512.png b/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 512x512.png
new file mode 100644
index 0000000..20247fa
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/iTunes Artwork/iTunes Artwork 512x512.png differ
diff --git a/Axantum.AxCrypt.iOS/Images/logo.png b/Axantum.AxCrypt.iOS/Images/logo.png
new file mode 100644
index 0000000..bb68330
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Images/logo.png differ
diff --git a/Axantum.AxCrypt.iOS/Info.plist b/Axantum.AxCrypt.iOS/Info.plist
new file mode 100644
index 0000000..f88faca
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Info.plist
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDisplayName</key>
+	<string>AxCrypt</string>
+	<key>CFBundleIconFiles</key>
+	<array>
+		<string>Images/App Icons/logo 57x57.png</string>
+		<string>Images/App Icons/logo 114x114.png</string>
+		<string>Images/App Icons/logo 72x72.png</string>
+		<string>Images/App Icons/logo 144x144.png</string>
+		<string>Images/Spotlight & Settings Icons/logo 29x29.png</string>
+		<string>Images/Spotlight & Settings Icons/logo 58x58.png</string>
+		<string>Images/Spotlight & Settings Icons/logo 50x50.png</string>
+		<string>Images/Spotlight & Settings Icons/logo 100x100.png</string>
+	</array>
+	<key>CFBundleIdentifier</key>
+	<string>com.tretton37.axantum.axcrypt</string>
+	<key>CFBundleVersion</key>
+	<string>1.2</string>
+	<key>MinimumOSVersion</key>
+	<string>5.0</string>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+		<integer>2</integer>
+	</array>
+	<key>UIFileSharingEnabled</key>
+	<true/>
+	<key>UIStatusBarStyle</key>
+	<string>UIStatusBarStyleBlackTranslucent</string>
+	<key>UIStatusBarTintParameters</key>
+	<dict>
+		<key>UINavigationBar</key>
+		<dict>
+			<key>Style</key>
+			<string>UIBarStyleDefault</string>
+			<key>Translucent</key>
+			<false/>
+			<key>BackgroundImage</key>
+			<string>Images/logo</string>
+		</dict>
+	</dict>
+	<key>UISupportedInterfaceOrientations</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+	</array>
+	<key>UISupportedInterfaceOrientations~ipad</key>
+	<array>
+		<string>UIInterfaceOrientationPortrait</string>
+		<string>UIInterfaceOrientationPortraitUpsideDown</string>
+		<string>UIInterfaceOrientationLandscapeLeft</string>
+		<string>UIInterfaceOrientationLandscapeRight</string>
+	</array>
+	<key>UTExportedTypeDeclarations</key>
+	<array>
+		<dict>
+			<key>UTTypeConformsTo</key>
+			<array>
+				<string>public.filename-extension</string>
+			</array>
+			<key>UTTypeDescription</key>
+			<string>AxCrypt document</string>
+			<key>UTTypeIdentifier</key>
+			<string>com.axantum.axcrypt-document</string>
+			<key>UTTypeTagSpecification</key>
+			<dict>
+				<key>public.filename-extension</key>
+				<string>axx</string>
+			</dict>
+		</dict>
+	</array>
+	<key>CFBundleDocumentTypes</key>
+	<array>
+		<dict>
+			<key>CFBundleTypeName</key>
+			<string>AxCrypt document</string>
+			<key>LSItemContentTypes</key>
+			<array>
+				<string>com.axantum.axcrypt-document</string>
+			</array>
+			<key>CFBundleTypeIconFiles</key>
+			<array>
+				<string>Images/Spotlight & Settings Icons/logo 58x58</string>
+			</array>
+		</dict>
+	</array>
+</dict>
+</plist>
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/BasePath.cs b/Axantum.AxCrypt.iOS/Infrastructure/BasePath.cs
new file mode 100644
index 0000000..03031fa
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/BasePath.cs
@@ -0,0 +1,44 @@
+using System;
+using System.IO;
+using Axantum.AxCrypt.Core;
+
+namespace Axantum.AxCrypt.iOS.Infrastructure
+{
+	public static class BasePath
+	{
+		public const int 
+			TransferredFilesId = 1, 
+			ReceivedFilesId = 2;
+
+		public static string TransferredFiles {
+			get {
+				return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
+			}
+		}
+
+		public static string ReceivedFiles {
+			get {
+				return Path.Combine (Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "Recent");
+			}
+		}
+
+		public static string GetBasePath(int pathId) {
+			switch (pathId) {
+			case TransferredFilesId:
+				return TransferredFiles;
+			case ReceivedFilesId:
+				return ReceivedFiles;
+			default:
+				throw new ArgumentException ("Invalid path id: " + pathId);
+			}
+		}
+
+		public static string Expand(string fileName, int pathId) {
+			string basePath = GetBasePath (pathId);
+			if (!fileName.EndsWith (OS.Current.AxCryptExtension))
+				fileName += OS.Current.AxCryptExtension;
+			return Path.Combine (basePath, fileName);
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/EditableTableViewSource.cs b/Axantum.AxCrypt.iOS/Infrastructure/EditableTableViewSource.cs
new file mode 100644
index 0000000..6ff9df7
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/EditableTableViewSource.cs
@@ -0,0 +1,34 @@
+using MonoTouch.Dialog;
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+using System.IO;
+using Axantum.AxCrypt.iOS.Infrastructure;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public class EditableTableViewSource : DialogViewController.Source
+	{
+		public EditableTableViewSource (DialogViewController controller) : base(controller) {
+		}
+
+		public override UITableViewCellEditingStyle EditingStyleForRow (UITableView tableView, NSIndexPath indexPath)
+		{
+			return base.Root [indexPath.Section] [indexPath.Row] is ThemedFileElement ? UITableViewCellEditingStyle.Delete : UITableViewCellEditingStyle.None;
+		}
+
+		public override void CommitEditingStyle (UITableView tableView, UITableViewCellEditingStyle editingStyle, NSIndexPath indexPath)
+		{
+			if (editingStyle != UITableViewCellEditingStyle.Delete)
+				return;
+
+			Section section = Root [indexPath.Section];
+			ThemedFileElement fileElement = section [indexPath.Row] as ThemedFileElement;
+			if (fileElement == null)
+				return;
+			string fullPath = BasePath.Expand (fileElement.Caption, fileElement.PathId);
+			File.Delete (fullPath);
+			section.Remove (indexPath.Row);
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/Theme.cs b/Axantum.AxCrypt.iOS/Infrastructure/Theme.cs
new file mode 100644
index 0000000..87f9acc
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/Theme.cs
@@ -0,0 +1,94 @@
+using MonoTouch.UIKit;
+using System.Drawing;
+using MonoTouch.Dialog;
+using System;
+
+namespace Axantum.AxCrypt.iOS.Infrastructure
+{
+	public static class Theme
+	{
+		public static UIColor HighlightColor = UIColor.FromRGB(96, 170, 13);
+		public const float CornerRadius = 20f;
+		public const float BorderWith = 2.75f;
+		public const float VerticalPadding = 15f;
+
+		const string HeaderImagePath = "Images/logo.png";
+		static UIImage HeaderImage;
+		static UIView headerView;
+
+		static void ConfigureTableView (this UITableView view, DialogViewController owner)
+		{
+			view.Bounces = true;
+			view.ScrollEnabled = true;
+
+			view.TableHeaderView = new UIView (new RectangleF (0, 0, view.Bounds.Width, HeaderImage.Size.Height + 15f)) {
+				BackgroundColor = UIColor.Clear
+			};
+		}
+
+		public static void Configure (UIView view)
+		{
+			view.Layer.CornerRadius = CornerRadius;
+			view.Layer.BorderColor = HighlightColor.CGColor;
+			view.Layer.BorderWidth = BorderWith;
+		}
+
+		static void CreateHeader (string title, UIView view)
+		{
+			const float horizontalPadding = 15f;
+			const float verticalPadding = 10f;
+
+			float viewWidth = view.Bounds.Width;
+			headerView = new UIView ();
+			UIImageView logo = new UIImageView (HeaderImage) {
+				ContentMode = Utilities.UserInterfaceIdiomIsPhone ? UIViewContentMode.TopLeft : UIViewContentMode.Center
+			};
+
+			UILabel logoText = new UILabel {
+				Font = UIFont.SystemFontOfSize (title.Length > 7 ? 28 : 36),
+				Text = Utilities.UserInterfaceIdiomIsPhone ? title.Replace(' ', '\n') : title,
+				TextColor = UIColor.DarkTextColor,
+				ShadowColor = HighlightColor,
+				ShadowOffset = new SizeF (1, 1),
+				BackgroundColor = UIColor.Clear,
+				Lines = Utilities.UserInterfaceIdiomIsPhone && title.Contains(" ") ? 2 : 1
+			};
+
+			logo.SizeToFit ();
+			logoText.SizeToFit ();
+			float requiredWidth = logo.Bounds.Width + horizontalPadding + logoText.Bounds.Width;
+			float requiredHeight = Math.Max (logo.Bounds.Height, logoText.Bounds.Height);
+			headerView.Frame = new RectangleF ((viewWidth - requiredWidth) / 2, verticalPadding, requiredWidth, requiredHeight + verticalPadding);
+			logo.Frame = new RectangleF (0, 0, logo.Bounds.Width, logo.Bounds.Height);
+			logoText.Frame = new RectangleF (logo.Bounds.Width + horizontalPadding / 2, (logo.Bounds.Height - logoText.Bounds.Height) / 2, logoText.Bounds.Width, logoText.Bounds.Height);
+			headerView.Add (logo);
+			headerView.Add (logoText);
+
+			view.Add (headerView);
+		}
+
+		public static void Configure (string text, DialogViewController viewController)
+		{
+			if (HeaderImage == null) {
+				HeaderImage = UIImage.FromFile (HeaderImagePath);
+			}
+			Configure (viewController.View);
+			ConfigureTableView (viewController.TableView, viewController);
+			CreateHeader (text, viewController.View);
+		}
+
+		public static void Configure(UITableViewCell cell) {
+			cell.TextLabel.TextColor = HighlightColor;
+			cell.TextLabel.TextAlignment = UITextAlignment.Center;
+			if (cell.DetailTextLabel != null) {
+				cell.DetailTextLabel.Font = UIFont.SystemFontOfSize (UIFont.SmallSystemFontSize);
+			}
+
+			cell.SelectedBackgroundView = new UIView (cell.Frame) { 
+				BackgroundColor = HighlightColor 
+			};
+			Configure (cell.SelectedBackgroundView);
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/ThemedFileElement.cs b/Axantum.AxCrypt.iOS/Infrastructure/ThemedFileElement.cs
new file mode 100644
index 0000000..9f26799
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/ThemedFileElement.cs
@@ -0,0 +1,51 @@
+using System;
+using MonoTouch.Dialog;
+using System.IO;
+using System.Text;
+using MonoTouch.UIKit;
+
+namespace Axantum.AxCrypt.iOS.Infrastructure
+{
+	public class ThemedFileElement : StyledStringElement
+	{
+		public int PathId {
+			get;
+			private set;
+		}
+
+		public ThemedFileElement (string fileName, DateTime lastAccessTime, int pathId) : base(
+			caption: Path.GetFileNameWithoutExtension(fileName),
+			value: String.Concat("Last opened ", FormatDateTime(lastAccessTime)),
+			style: Utilities.UserInterfaceIdiomIsPhone ? UITableViewCellStyle.Subtitle : UITableViewCellStyle.Value1)
+		{
+			PathId = pathId;
+		}
+
+		static string FormatDateTime(DateTime value) {
+			DateTime now = DateTime.Now;
+			string nowDateString = now.ToShortDateString ();
+			string yesterdayString = now.AddDays (-1).ToShortDateString ();
+			string valueDateString = value.ToShortDateString ();
+			StringBuilder format = new StringBuilder ();
+
+			if (nowDateString == valueDateString) {
+				format.Append ("today at");
+			} else if (yesterdayString == valueDateString) {
+				format.Append ("yesterday at");
+			} else {
+				format.Append (nowDateString);
+			}
+
+			format.Append (" ").Append (now.ToShortTimeString());
+			return format.ToString ();
+		}
+
+		public override UITableViewCell GetCell (UITableView tv)
+		{
+			var cell = base.GetCell (tv);
+			Theme.Configure (cell);
+			return cell;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/ThemedStringElement.cs b/Axantum.AxCrypt.iOS/Infrastructure/ThemedStringElement.cs
new file mode 100644
index 0000000..70ecc3e
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/ThemedStringElement.cs
@@ -0,0 +1,24 @@
+using System;
+using MonoTouch.Dialog;
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+
+namespace Axantum.AxCrypt.iOS.Infrastructure
+{
+	public class ThemedStringElement : StringElement {
+
+		public ThemedStringElement (string caption, Action action) : base(caption, new NSAction(action))
+		{
+		}
+
+		public override UITableViewCell GetCell (UITableView tv)
+		{
+			var cell = base.GetCell (tv);
+
+			Theme.Configure (cell);
+
+			return cell;
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/UIAlertViewOkCancelDelegate.cs b/Axantum.AxCrypt.iOS/Infrastructure/UIAlertViewOkCancelDelegate.cs
new file mode 100644
index 0000000..2b98bc8
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/UIAlertViewOkCancelDelegate.cs
@@ -0,0 +1,33 @@
+using System;
+using MonoTouch.UIKit;
+
+namespace Axantum.AxCrypt.iOS
+{
+	class UIAlertViewOkCancelDelegate : UIAlertViewDelegate
+	{
+		Action okAction, cancelAction;
+		Action<string> okActionOfString;
+
+		public UIAlertViewOkCancelDelegate (Action okAction, Action cancelAction)
+		{
+			this.okAction = okAction;
+			this.cancelAction = cancelAction;
+		}
+
+		public UIAlertViewOkCancelDelegate (Action<string> okAction, Action cancelAction)
+		{
+			okActionOfString = okAction;
+			this.cancelAction = cancelAction;
+		}
+
+		public override void Dismissed (UIAlertView alertView, int buttonIndex)
+		{
+			if (buttonIndex == alertView.CancelButtonIndex)
+				cancelAction();
+			else if (alertView.AlertViewStyle == UIAlertViewStyle.SecureTextInput)
+				okActionOfString(alertView.GetTextField(0).Text);
+			else
+				okAction();
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/Infrastructure/Utilities.cs b/Axantum.AxCrypt.iOS/Infrastructure/Utilities.cs
new file mode 100644
index 0000000..cb1e371
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Infrastructure/Utilities.cs
@@ -0,0 +1,16 @@
+using MonoTouch.UIKit;
+
+namespace Axantum.AxCrypt.iOS.Infrastructure
+{
+	public class Utilities
+	{
+		public static bool UserInterfaceIdiomIsPhone {
+			get { return UIDevice.CurrentDevice.UserInterfaceIdiom == UIUserInterfaceIdiom.Phone; }
+		}
+
+		public static bool iPhone5OrPad {
+			get { return UIScreen.MainScreen.Bounds.Size.Height >= 568; }
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/Main.cs b/Axantum.AxCrypt.iOS/Main.cs
new file mode 100644
index 0000000..9fa8028
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Main.cs
@@ -0,0 +1,15 @@
+using MonoTouch.UIKit;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public class Application
+	{
+		// This is the main entry point of the application.
+		static void Main (string[] args)
+		{
+			// if you want to use a different Application Delegate class from "AppDelegate"
+			// you can specify it here.
+			UIApplication.Main (args, null, "AppDelegate");
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/MainViewController.cs b/Axantum.AxCrypt.iOS/MainViewController.cs
new file mode 100644
index 0000000..a902330
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/MainViewController.cs
@@ -0,0 +1,113 @@
+using System;
+using MonoTouch.Dialog;
+using MonoTouch.UIKit;
+using Axantum.AxCrypt.iOS.Infrastructure;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public partial class MainViewController : DialogViewController
+	{
+		public event Action 
+			OnRecentFilesButtonTapped,
+			OnLocalFilesButtonTapped,
+			OnFaqButtonTapped,
+			OnAboutButtonTapped, 
+			OnTroubleshootingButtonTapped, 
+			OnFeedbackButtonTapped;
+
+		public MainViewController () : base(new RootElement(String.Empty))
+		{
+			
+		}
+
+		public override void ViewDidLoad ()
+		{
+			base.ViewDidLoad ();
+			if (!Utilities.UserInterfaceIdiomIsPhone) {
+				TableView.Source = new EditableTableViewSource (this);
+			}
+		}
+
+		FileListingViewController recent, local;
+		Section receivedDocumentsSection, transferredDocumentsSection;
+		public override void ViewWillAppear (bool animated)
+		{
+			if (Root.Count != 0) {
+				if (!Utilities.UserInterfaceIdiomIsPhone) {
+					if (receivedDocumentsSection != null) {
+						receivedDocumentsSection.Clear ();
+						receivedDocumentsSection.AddAll (recent.GetElements ());
+					}
+					if (transferredDocumentsSection != null) {
+						transferredDocumentsSection.Clear ();
+						transferredDocumentsSection.AddAll (local.GetElements ());
+					}
+				}
+				return;
+			}
+
+			Theme.Configure ("AxCrypt", this);
+
+			receivedDocumentsSection = new Section ();
+			transferredDocumentsSection = new Section();
+
+			if (Utilities.UserInterfaceIdiomIsPhone) {
+				receivedDocumentsSection.Add (new ThemedStringElement ("Received documents", OnRecentFilesButtonTapped));
+				transferredDocumentsSection.Add (new ThemedStringElement("Transferred documents", OnLocalFilesButtonTapped));
+
+				if (Utilities.iPhone5OrPad) {
+					// We've got plenty of vertical space to be a little more verbose
+					receivedDocumentsSection.Footer = "documents received from other apps";
+					transferredDocumentsSection.Footer = "documents transferred from iTunes";
+				}
+			} else {
+
+				receivedDocumentsSection.Caption = "Documents received from other Apps";
+				receivedDocumentsSection.Footer = " ";
+				recent = new FileListingViewController (String.Empty, BasePath.ReceivedFilesId);
+				recent.OpenFile += AppDelegate.Current.HandleOpenFile;
+				receivedDocumentsSection.AddAll (recent.GetElements());
+
+				transferredDocumentsSection.Caption = "Documents transferred via iTunes";
+				transferredDocumentsSection.Footer = " ";
+				local = new FileListingViewController (String.Empty, BasePath.TransferredFilesId);
+				local.OpenFile += AppDelegate.Current.HandleOpenFile;
+				transferredDocumentsSection.AddAll (local.GetElements());
+
+			}
+
+
+			Root.Add (new[] {
+				receivedDocumentsSection,
+				transferredDocumentsSection,
+			});
+
+			if (!Utilities.UserInterfaceIdiomIsPhone) {
+				Root.Add (new Section(String.Empty));
+			}
+
+			Root.Add (new [] { 
+				new Section { 
+					new ThemedStringElement("About", OnAboutButtonTapped),
+					new ThemedStringElement("Frequently Asked Questions", OnFaqButtonTapped),
+					new ThemedStringElement("Troubleshooting", OnTroubleshootingButtonTapped),
+					new ThemedStringElement("Feedback", OnFeedbackButtonTapped)
+				},
+			});
+
+			TableView.ScrollEnabled = receivedDocumentsSection.Count + receivedDocumentsSection.Count > 20;
+			base.ViewWillAppear (animated);
+		}
+
+		public override void ViewWillDisappear (bool animated)
+		{
+			base.ViewWillDisappear (animated);
+		}
+
+		public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
+		{
+			//return (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown);
+			return true;
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/PassphraseController.cs b/Axantum.AxCrypt.iOS/PassphraseController.cs
new file mode 100644
index 0000000..24bd461
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/PassphraseController.cs
@@ -0,0 +1,65 @@
+using System;
+using System.IO;
+using MonoTouch.UIKit;
+using Axantum.AxCrypt.Core.Crypto;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public partial class PassphraseController : IDisposable
+	{
+		public event Action<Passphrase> Done = delegate {}; 
+		public event Action Cancelled = delegate {};
+
+		string path;
+		UIAlertViewDelegate alertViewDelegate;
+		UIAlertView alertView;
+
+		public PassphraseController (string path)
+		{
+			this.path = path;
+		}
+
+		public void AskForPassword ()
+		{
+			string title, message; 
+
+			if (alertViewDelegate == null) {
+				alertViewDelegate = new UIAlertViewOkCancelDelegate(InvokeDone, Cancelled);
+				title = Path.GetFileNameWithoutExtension(path);
+				message = "Enter passphrase";
+			}
+			else {
+				title = "The passphrase you entered could not be used to open file";
+				message = "Try again?";
+			}
+
+			if (alertView == null) {
+				alertView = new UIAlertView (title, message, alertViewDelegate, "Cancel", new string[] { "OK" });
+				alertView.AlertViewStyle = UIAlertViewStyle.SecureTextInput;
+			} 
+			else {
+				alertView.Title = title;
+				alertView.Message = message;
+			}
+			alertView.Show ();
+		}
+
+		void InvokeDone(string passphrase) {
+			Done (new Passphrase(passphrase));
+		}
+
+		public void Dispose ()
+		{
+			if (this.alertViewDelegate != null) {
+				this.alertViewDelegate.Dispose ();
+				this.alertViewDelegate = null;
+			}
+			if (this.alertView != null) {
+				this.alertView.Delegate = null;
+				this.alertView.DismissWithClickedButtonIndex (alertView.CancelButtonIndex, false);
+				this.alertView.Dispose ();
+				this.alertView = null;
+			}
+		}
+	}
+}
diff --git a/Axantum.AxCrypt.iOS/Properties/AssemblyInfo.cs b/Axantum.AxCrypt.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1569f6b
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,69 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2012, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AxCrypt for iOS Devices")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © Svante Seleborg 2012")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("258c0256-6cd2-4604-8bd6-1e9c3df5d88b")]
+[assembly: CLSCompliant(false)]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+#endif
diff --git a/Axantum.AxCrypt.iOS/Resources/Default-568h at 2x.png b/Axantum.AxCrypt.iOS/Resources/Default-568h at 2x.png
new file mode 100644
index 0000000..0891b7a
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Resources/Default-568h at 2x.png differ
diff --git a/Axantum.AxCrypt.iOS/Resources/Default.png b/Axantum.AxCrypt.iOS/Resources/Default.png
new file mode 100644
index 0000000..bc8da1c
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Resources/Default.png differ
diff --git a/Axantum.AxCrypt.iOS/Resources/Default at 2x.png b/Axantum.AxCrypt.iOS/Resources/Default at 2x.png
new file mode 100644
index 0000000..eaf75d3
Binary files /dev/null and b/Axantum.AxCrypt.iOS/Resources/Default at 2x.png differ
diff --git a/Axantum.AxCrypt.iOS/WebViewController.cs b/Axantum.AxCrypt.iOS/WebViewController.cs
new file mode 100644
index 0000000..0c57e9e
--- /dev/null
+++ b/Axantum.AxCrypt.iOS/WebViewController.cs
@@ -0,0 +1,59 @@
+using MonoTouch.UIKit;
+using MonoTouch.Foundation;
+using Axantum.AxCrypt.iOS.Infrastructure;
+using System;
+using BigTed;
+
+namespace Axantum.AxCrypt.iOS
+{
+	public class WebViewController : UIViewController
+	{
+		public event Action Done = delegate {};
+
+		NSUrlRequest request;
+
+		public WebViewController (string url)
+		{
+			this.request = NSUrlRequest.FromUrl(NSUrl.FromString(url));
+			ModalPresentationStyle = UIModalPresentationStyle.FullScreen;
+			ModalTransitionStyle = UIModalTransitionStyle.PartialCurl;
+		}
+
+		new UIWebView View {
+			get {
+				return (UIWebView)base.View;
+			}
+		}
+
+		public override void ViewDidLoad ()
+		{
+			base.View = new UIWebView ();
+			this.View.LoadStarted += delegate {
+				UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
+			};
+			this.View.LoadFinished += delegate {
+				UIApplication.SharedApplication.NetworkActivityIndicatorVisible = false;
+				BTProgressHUD.Dismiss();
+			};
+			this.View.LoadError += delegate {
+				BTProgressHUD.ShowErrorWithStatus("An error occurred loading the web page. Please ensure you're connected to the internet and try again later.", 3000);
+			};
+			base.ViewDidLoad ();
+			Theme.Configure (View);
+		}
+
+		public override void ViewDidAppear (bool animated)
+		{
+			base.ViewDidAppear (animated);
+			BTProgressHUD.Show("Loading ...");
+			View.LoadRequest (this.request);
+		}
+
+		public override void ViewDidDisappear (bool animated)
+		{
+			base.ViewDidDisappear (animated);
+			Done ();
+		}
+	}
+}
+
diff --git a/Axantum.AxCrypt.iOS/iTunesArtwork b/Axantum.AxCrypt.iOS/iTunesArtwork
new file mode 100644
index 0000000..20247fa
Binary files /dev/null and b/Axantum.AxCrypt.iOS/iTunesArtwork differ
diff --git a/Axantum.AxCrypt.iOS/iTunesArtwork at 2x b/Axantum.AxCrypt.iOS/iTunesArtwork at 2x
new file mode 100644
index 0000000..f911d75
Binary files /dev/null and b/Axantum.AxCrypt.iOS/iTunesArtwork at 2x differ
diff --git a/Axantum.AxCrypt/AboutBox.Designer.cs b/Axantum.AxCrypt/AboutBox.Designer.cs
new file mode 100644
index 0000000..43ff4c0
--- /dev/null
+++ b/Axantum.AxCrypt/AboutBox.Designer.cs
@@ -0,0 +1,116 @@
+namespace Axantum.AxCrypt
+{
+    partial class AboutBox
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutBox));
+            this.logoPictureBox = new System.Windows.Forms.PictureBox();
+            this.ProductNameText = new System.Windows.Forms.Label();
+            this.VersionText = new System.Windows.Forms.Label();
+            this.CopyrightText = new System.Windows.Forms.Label();
+            this.CompanyNameText = new System.Windows.Forms.Label();
+            this.Description = new System.Windows.Forms.TextBox();
+            this.okButton = new System.Windows.Forms.Button();
+            ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // logoPictureBox
+            // 
+            this.logoPictureBox.Image = global::Axantum.AxCrypt.Properties.Resources.axcrypticon128;
+            resources.ApplyResources(this.logoPictureBox, "logoPictureBox");
+            this.logoPictureBox.Name = "logoPictureBox";
+            this.logoPictureBox.TabStop = false;
+            // 
+            // ProductNameText
+            // 
+            resources.ApplyResources(this.ProductNameText, "ProductNameText");
+            this.ProductNameText.Name = "ProductNameText";
+            // 
+            // VersionText
+            // 
+            resources.ApplyResources(this.VersionText, "VersionText");
+            this.VersionText.Name = "VersionText";
+            // 
+            // CopyrightText
+            // 
+            resources.ApplyResources(this.CopyrightText, "CopyrightText");
+            this.CopyrightText.Name = "CopyrightText";
+            // 
+            // CompanyNameText
+            // 
+            resources.ApplyResources(this.CompanyNameText, "CompanyNameText");
+            this.CompanyNameText.Name = "CompanyNameText";
+            // 
+            // Description
+            // 
+            resources.ApplyResources(this.Description, "Description");
+            this.Description.Name = "Description";
+            this.Description.ReadOnly = true;
+            this.Description.TabStop = false;
+            // 
+            // okButton
+            // 
+            resources.ApplyResources(this.okButton, "okButton");
+            this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this.okButton.Name = "okButton";
+            // 
+            // AboutBox
+            // 
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this.logoPictureBox);
+            this.Controls.Add(this.ProductNameText);
+            this.Controls.Add(this.VersionText);
+            this.Controls.Add(this.CopyrightText);
+            this.Controls.Add(this.CompanyNameText);
+            this.Controls.Add(this.Description);
+            this.Controls.Add(this.okButton);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "AboutBox";
+            this.ShowIcon = false;
+            this.ShowInTaskbar = false;
+            this.Load += new System.EventHandler(this.AboutBox_Load);
+            ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.PictureBox logoPictureBox;
+        internal System.Windows.Forms.Label ProductNameText;
+        internal System.Windows.Forms.Label VersionText;
+        internal System.Windows.Forms.Label CopyrightText;
+        internal System.Windows.Forms.Label CompanyNameText;
+        internal System.Windows.Forms.TextBox Description;
+        private System.Windows.Forms.Button okButton;
+
+    }
+}
diff --git a/Axantum.AxCrypt/AboutBox.cs b/Axantum.AxCrypt/AboutBox.cs
new file mode 100644
index 0000000..fb7e9f2
--- /dev/null
+++ b/Axantum.AxCrypt/AboutBox.cs
@@ -0,0 +1,112 @@
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    partial class AboutBox : Form
+    {
+        public AboutBox()
+        {
+            InitializeComponent();
+        }
+
+        private void AboutBox_Load(object sender, EventArgs e)
+        {
+            this.Text = Resources.About.InvariantFormat(AssemblyProduct);
+            this.ProductNameText.Text = AssemblyProduct;
+            this.VersionText.Text = AssemblyVersion + (String.IsNullOrEmpty(AssemblyDescription) ? String.Empty : " " + AssemblyDescription);
+            this.CopyrightText.Text = AssemblyCopyright;
+            this.CompanyNameText.Text = AssemblyCompany;
+            this.Description.Text = Resources.AxCryptAboutDescription;
+        }
+
+        #region Assembly Attribute Accessors
+
+        public static string AssemblyTitle
+        {
+            get
+            {
+                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+                if (attributes.Length > 0)
+                {
+                    AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
+                    if (!String.IsNullOrEmpty(titleAttribute.Title))
+                    {
+                        return titleAttribute.Title;
+                    }
+                }
+                return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+            }
+        }
+
+        public static string AssemblyVersion
+        {
+            get
+            {
+                return Application.ProductVersion;
+            }
+        }
+
+        public static string AssemblyDescription
+        {
+            get
+            {
+                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+                if (attributes.Length == 0)
+                {
+                    return "";
+                }
+                return ((AssemblyDescriptionAttribute)attributes[0]).Description;
+            }
+        }
+
+        public static string AssemblyProduct
+        {
+            get
+            {
+                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+                if (attributes.Length == 0)
+                {
+                    return "";
+                }
+                return ((AssemblyProductAttribute)attributes[0]).Product;
+            }
+        }
+
+        public static string AssemblyCopyright
+        {
+            get
+            {
+                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+                if (attributes.Length == 0)
+                {
+                    return "";
+                }
+                return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+            }
+        }
+
+        public static string AssemblyCompany
+        {
+            get
+            {
+                object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+                if (attributes.Length == 0)
+                {
+                    return "";
+                }
+                return ((AssemblyCompanyAttribute)attributes[0]).Company;
+            }
+        }
+
+        #endregion Assembly Attribute Accessors
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AboutBox.resx b/Axantum.AxCrypt/AboutBox.resx
new file mode 100644
index 0000000..a5c763b
--- /dev/null
+++ b/Axantum.AxCrypt/AboutBox.resx
@@ -0,0 +1,745 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="logoPictureBox.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="logoPictureBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>3, 3</value>
+  </data>
+  <data name="logoPictureBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>123, 134</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="logoPictureBox.TabIndex" type="System.Int32, mscorlib">
+    <value>26</value>
+  </data>
+  <data name=">>logoPictureBox.Name" xml:space="preserve">
+    <value>logoPictureBox</value>
+  </data>
+  <data name=">>logoPictureBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>logoPictureBox.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>logoPictureBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="ProductNameText.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="ProductNameText.Location" type="System.Drawing.Point, System.Drawing">
+    <value>143, 6</value>
+  </data>
+  <data name="ProductNameText.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>6, 0, 3, 0</value>
+  </data>
+  <data name="ProductNameText.Size" type="System.Drawing.Size, System.Drawing">
+    <value>271, 17</value>
+  </data>
+  <data name="ProductNameText.TabIndex" type="System.Int32, mscorlib">
+    <value>27</value>
+  </data>
+  <data name="ProductNameText.Text" xml:space="preserve">
+    <value>AxCrypt File Encryption</value>
+  </data>
+  <data name="ProductNameText.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
+    <value>MiddleLeft</value>
+  </data>
+  <data name=">>ProductNameText.Name" xml:space="preserve">
+    <value>ProductNameText</value>
+  </data>
+  <data name=">>ProductNameText.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ProductNameText.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>ProductNameText.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="VersionText.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="VersionText.Location" type="System.Drawing.Point, System.Drawing">
+    <value>143, 30</value>
+  </data>
+  <data name="VersionText.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>6, 0, 3, 0</value>
+  </data>
+  <data name="VersionText.Size" type="System.Drawing.Size, System.Drawing">
+    <value>271, 17</value>
+  </data>
+  <data name="VersionText.TabIndex" type="System.Int32, mscorlib">
+    <value>25</value>
+  </data>
+  <data name="VersionText.Text" xml:space="preserve">
+    <value>Version</value>
+  </data>
+  <data name="VersionText.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
+    <value>MiddleLeft</value>
+  </data>
+  <data name=">>VersionText.Name" xml:space="preserve">
+    <value>VersionText</value>
+  </data>
+  <data name=">>VersionText.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>VersionText.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>VersionText.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="CopyrightText.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="CopyrightText.Location" type="System.Drawing.Point, System.Drawing">
+    <value>143, 54</value>
+  </data>
+  <data name="CopyrightText.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>6, 0, 3, 0</value>
+  </data>
+  <data name="CopyrightText.Size" type="System.Drawing.Size, System.Drawing">
+    <value>271, 17</value>
+  </data>
+  <data name="CopyrightText.TabIndex" type="System.Int32, mscorlib">
+    <value>28</value>
+  </data>
+  <data name="CopyrightText.Text" xml:space="preserve">
+    <value>Copyright 2014 Axantum Software AB</value>
+  </data>
+  <data name="CopyrightText.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
+    <value>MiddleLeft</value>
+  </data>
+  <data name=">>CopyrightText.Name" xml:space="preserve">
+    <value>CopyrightText</value>
+  </data>
+  <data name=">>CopyrightText.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>CopyrightText.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>CopyrightText.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+  <data name="CompanyNameText.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="CompanyNameText.Location" type="System.Drawing.Point, System.Drawing">
+    <value>143, 78</value>
+  </data>
+  <data name="CompanyNameText.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>6, 0, 3, 0</value>
+  </data>
+  <data name="CompanyNameText.Size" type="System.Drawing.Size, System.Drawing">
+    <value>271, 17</value>
+  </data>
+  <data name="CompanyNameText.TabIndex" type="System.Int32, mscorlib">
+    <value>29</value>
+  </data>
+  <data name="CompanyNameText.Text" xml:space="preserve">
+    <value>Axantum Software AB</value>
+  </data>
+  <data name="CompanyNameText.TextAlign" type="System.Drawing.ContentAlignment, System.Drawing">
+    <value>MiddleLeft</value>
+  </data>
+  <data name=">>CompanyNameText.Name" xml:space="preserve">
+    <value>CompanyNameText</value>
+  </data>
+  <data name=">>CompanyNameText.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>CompanyNameText.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>CompanyNameText.ZOrder" xml:space="preserve">
+    <value>4</value>
+  </data>
+  <data name="Description.Location" type="System.Drawing.Point, System.Drawing">
+    <value>143, 107</value>
+  </data>
+  <data name="Description.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>6, 3, 3, 3</value>
+  </data>
+  <data name="Description.Multiline" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="Description.ScrollBars" type="System.Windows.Forms.ScrollBars, System.Windows.Forms">
+    <value>Both</value>
+  </data>
+  <data name="Description.Size" type="System.Drawing.Size, System.Drawing">
+    <value>271, 126</value>
+  </data>
+  <data name="Description.TabIndex" type="System.Int32, mscorlib">
+    <value>30</value>
+  </data>
+  <data name="Description.Text" xml:space="preserve">
+    <value>Description</value>
+  </data>
+  <data name=">>Description.Name" xml:space="preserve">
+    <value>Description</value>
+  </data>
+  <data name=">>Description.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>Description.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>Description.ZOrder" xml:space="preserve">
+    <value>5</value>
+  </data>
+  <data name="okButton.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
+    <value>Bottom, Right</value>
+  </data>
+  <data name="okButton.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="okButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>339, 239</value>
+  </data>
+  <data name="okButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="okButton.TabIndex" type="System.Int32, mscorlib">
+    <value>31</value>
+  </data>
+  <data name="okButton.Text" xml:space="preserve">
+    <value>&OK</value>
+  </data>
+  <data name=">>okButton.Name" xml:space="preserve">
+    <value>okButton</value>
+  </data>
+  <data name=">>okButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>okButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>okButton.ZOrder" xml:space="preserve">
+    <value>6</value>
+  </data>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>435, 283</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>9, 9, 9, 9</value>
+  </data>
+  <data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
+    <value>CenterParent</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>AboutBox</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>AboutBox</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AboutBox.sv.resx b/Axantum.AxCrypt/AboutBox.sv.resx
new file mode 100644
index 0000000..70ed3a8
--- /dev/null
+++ b/Axantum.AxCrypt/AboutBox.sv.resx
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="okButton.Text" xml:space="preserve">
+    <value>&OK</value>
+  </data>
+  <data name="ProductNameText.Text" xml:space="preserve">
+    <value>AxCrypt Dokumentkryptering</value>
+  </data>
+  <data name="Description.Text" xml:space="preserve">
+    <value>Beskrivning</value>
+  </data>
+  <data name="VersionText.Text" xml:space="preserve">
+    <value>Version</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AboutThisProgram.txt b/Axantum.AxCrypt/AboutThisProgram.txt
new file mode 100644
index 0000000..d03fcfe
--- /dev/null
+++ b/Axantum.AxCrypt/AboutThisProgram.txt
@@ -0,0 +1,33 @@
+About Axantum.AxCrypt.exe
+
+This is the reference code GUI for AxCrypt. It is intended to be portable between pure
+Mono desktop platforms such as Linux and Windows. Mac OS X appears to be tougher.
+
+In general a platform-specific GUI should be designed in each case, being as native as
+possible. This GUI may become purely a reference GUI if/when specialized Linux and
+Windows GUI'n are built.
+
+A GUI implementation should only need Axantum.AxCrypt.Core.dll, Axantum.AxCrypt.[Platform].dll
+and BouncyCastle.Crypto.dll as binary dependencies.
+
+No code coverage or Unit Tests are expected to be run against Axantum.AxCrypt.exe, since it is
+intended to be pure GUI-related.
+
+FxCop should pass without complaint.
+
+---
+
+Comments and findings on Mono compatiblity, rationales etc.
+
+- .NET 3.5 is used because for example MonoTouch does not support 4.0
+- The 'resources' folder is all lower case because the designer forces lower case
+  and this blows up on case-sensitive file systems.
+- The build system is extended via 'Axantum.targets' which includes functionality
+  for versioning the assemblies, signing them etc. The intention is for this to be
+  ignored when not building at Axantum or when building in MonoDevelop etc. It should
+  build in Visual Studio 2010 (Express) and MonoDevelop out of the box with no changes.
+- Non-7-bit characters should be avoided in file names due to file system differences
+  causing build problems.
+- Upper case characters should be avoided in files used as resources due to designer quirks
+  causing the names to be lowercased in the resx-file, causing problems on file systems
+  which are case-sensitive.
diff --git a/Axantum.AxCrypt/AxCrypt.ico b/Axantum.AxCrypt/AxCrypt.ico
new file mode 100644
index 0000000..f2e5c7f
Binary files /dev/null and b/Axantum.AxCrypt/AxCrypt.ico differ
diff --git a/Axantum.AxCrypt/AxCryptMainForm.Designer.cs b/Axantum.AxCrypt/AxCryptMainForm.Designer.cs
new file mode 100644
index 0000000..aaaf9e3
--- /dev/null
+++ b/Axantum.AxCrypt/AxCryptMainForm.Designer.cs
@@ -0,0 +1,601 @@
+namespace Axantum.AxCrypt
+{
+    partial class AxCryptMainForm
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AxCryptMainForm));
+            this._mainToolStrip = new System.Windows.Forms.ToolStrip();
+            this._encryptionKeyToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator();
+            this._openEncryptedToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._encryptToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._decryptToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+            this._closeAndRemoveOpenFilesToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
+            this._updateToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._knownFoldersSeparator = new System.Windows.Forms.ToolStripSeparator();
+            this._toolStripSeparator8 = new System.Windows.Forms.ToolStripSeparator();
+            this._helpToolStripButton = new System.Windows.Forms.ToolStripButton();
+            this._mainMenuStrip = new System.Windows.Forms.MenuStrip();
+            this._fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._openEncryptedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._encryptToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._decryptToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.encryptedFoldersToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator();
+            this._closeOpenFilesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator();
+            this._wipeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+            this._optionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._languageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._englishLanguageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._swedishLanguageToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._debugOptionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._clearPassphraseMemoryToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._debugToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._checkVersionNowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._setUpdateCheckUrlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.cryptoPolicyToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.loggingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._viewHelpMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._progressTableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
+            this._recentFilesContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this._removeRecentFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._decryptAndRemoveFromListToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._progressContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this._progressContextCancelToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this._watchedFoldersRemoveMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersdecryptTemporarilyMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersOpenExplorerHereMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersTabPage = new System.Windows.Forms.TabPage();
+            this._watchedFoldersListView = new System.Windows.Forms.ListView();
+            this._watchedFolderColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._recentFilesTabPage = new System.Windows.Forms.TabPage();
+            this._recentFilesListView = new System.Windows.Forms.ListView();
+            this._decryptedFileColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._lastAccessTimeColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._encryptedPathColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._cryptoName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._statusTabControl = new System.Windows.Forms.TabControl();
+            this._progressBackgroundWorker = new Axantum.AxCrypt.Forms.ProgressBackground(this.components);
+            this.createAccountToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._mainToolStrip.SuspendLayout();
+            this._mainMenuStrip.SuspendLayout();
+            this._recentFilesContextMenuStrip.SuspendLayout();
+            this._progressContextMenuStrip.SuspendLayout();
+            this._watchedFoldersContextMenuStrip.SuspendLayout();
+            this._watchedFoldersTabPage.SuspendLayout();
+            this._recentFilesTabPage.SuspendLayout();
+            this._statusTabControl.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // _mainToolStrip
+            // 
+            this._mainToolStrip.AllowDrop = true;
+            this._mainToolStrip.AllowMerge = false;
+            resources.ApplyResources(this._mainToolStrip, "_mainToolStrip");
+            this._mainToolStrip.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+            this._mainToolStrip.ImageScalingSize = new System.Drawing.Size(32, 32);
+            this._mainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._encryptionKeyToolStripButton,
+            this._toolStripSeparator7,
+            this._openEncryptedToolStripButton,
+            this._encryptToolStripButton,
+            this._decryptToolStripButton,
+            this._toolStripSeparator1,
+            this._closeAndRemoveOpenFilesToolStripButton,
+            this._toolStripSeparator4,
+            this._updateToolStripButton,
+            this._knownFoldersSeparator,
+            this._toolStripSeparator8,
+            this._helpToolStripButton});
+            this._mainToolStrip.Name = "_mainToolStrip";
+            this._mainToolStrip.DragDrop += new System.Windows.Forms.DragEventHandler(this.MainToolStrip_DragDrop);
+            // 
+            // _encryptionKeyToolStripButton
+            // 
+            this._encryptionKeyToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._encryptionKeyToolStripButton.Image = global::Axantum.AxCrypt.Properties.Resources.encryptionkeygreen32;
+            resources.ApplyResources(this._encryptionKeyToolStripButton, "_encryptionKeyToolStripButton");
+            this._encryptionKeyToolStripButton.Name = "_encryptionKeyToolStripButton";
+            // 
+            // _toolStripSeparator7
+            // 
+            this._toolStripSeparator7.Name = "_toolStripSeparator7";
+            resources.ApplyResources(this._toolStripSeparator7, "_toolStripSeparator7");
+            // 
+            // _openEncryptedToolStripButton
+            // 
+            resources.ApplyResources(this._openEncryptedToolStripButton, "_openEncryptedToolStripButton");
+            this._openEncryptedToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._openEncryptedToolStripButton.Name = "_openEncryptedToolStripButton";
+            this._openEncryptedToolStripButton.Tag = "";
+            // 
+            // _encryptToolStripButton
+            // 
+            resources.ApplyResources(this._encryptToolStripButton, "_encryptToolStripButton");
+            this._encryptToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._encryptToolStripButton.Image = global::Axantum.AxCrypt.Properties.Resources.encryptlock32;
+            this._encryptToolStripButton.Name = "_encryptToolStripButton";
+            // 
+            // _decryptToolStripButton
+            // 
+            resources.ApplyResources(this._decryptToolStripButton, "_decryptToolStripButton");
+            this._decryptToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._decryptToolStripButton.Name = "_decryptToolStripButton";
+            // 
+            // _toolStripSeparator1
+            // 
+            this._toolStripSeparator1.Name = "_toolStripSeparator1";
+            resources.ApplyResources(this._toolStripSeparator1, "_toolStripSeparator1");
+            // 
+            // _closeAndRemoveOpenFilesToolStripButton
+            // 
+            resources.ApplyResources(this._closeAndRemoveOpenFilesToolStripButton, "_closeAndRemoveOpenFilesToolStripButton");
+            this._closeAndRemoveOpenFilesToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._closeAndRemoveOpenFilesToolStripButton.Image = global::Axantum.AxCrypt.Properties.Resources.closeremovestandbyred32;
+            this._closeAndRemoveOpenFilesToolStripButton.Name = "_closeAndRemoveOpenFilesToolStripButton";
+            this._closeAndRemoveOpenFilesToolStripButton.Click += new System.EventHandler(this.CloseAndRemoveOpenFilesToolStripButton_Click);
+            // 
+            // _toolStripSeparator4
+            // 
+            this._toolStripSeparator4.Name = "_toolStripSeparator4";
+            resources.ApplyResources(this._toolStripSeparator4, "_toolStripSeparator4");
+            // 
+            // _updateToolStripButton
+            // 
+            resources.ApplyResources(this._updateToolStripButton, "_updateToolStripButton");
+            this._updateToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._updateToolStripButton.Image = global::Axantum.AxCrypt.Properties.Resources.refreshgreen;
+            this._updateToolStripButton.Name = "_updateToolStripButton";
+            this._updateToolStripButton.Click += new System.EventHandler(this.UpdateToolStripButton_Click);
+            // 
+            // _knownFoldersSeparator
+            // 
+            this._knownFoldersSeparator.Name = "_knownFoldersSeparator";
+            resources.ApplyResources(this._knownFoldersSeparator, "_knownFoldersSeparator");
+            // 
+            // _toolStripSeparator8
+            // 
+            this._toolStripSeparator8.Name = "_toolStripSeparator8";
+            resources.ApplyResources(this._toolStripSeparator8, "_toolStripSeparator8");
+            // 
+            // _helpToolStripButton
+            // 
+            this._helpToolStripButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+            this._helpToolStripButton.Image = global::Axantum.AxCrypt.Properties.Resources.helpquestiongreen32;
+            resources.ApplyResources(this._helpToolStripButton, "_helpToolStripButton");
+            this._helpToolStripButton.Name = "_helpToolStripButton";
+            this._helpToolStripButton.Click += new System.EventHandler(this.HelpToolStripButton_Click);
+            // 
+            // _mainMenuStrip
+            // 
+            this._mainMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._fileToolStripMenuItem,
+            this._debugToolStripMenuItem,
+            this._helpToolStripMenuItem});
+            resources.ApplyResources(this._mainMenuStrip, "_mainMenuStrip");
+            this._mainMenuStrip.Name = "_mainMenuStrip";
+            // 
+            // _fileToolStripMenuItem
+            // 
+            this._fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._openEncryptedToolStripMenuItem,
+            this._encryptToolStripMenuItem,
+            this._decryptToolStripMenuItem,
+            this.encryptedFoldersToolStripMenuItem,
+            this._toolStripSeparator6,
+            this._closeOpenFilesToolStripMenuItem,
+            this._toolStripSeparator3,
+            this._wipeToolStripMenuItem,
+            this._toolStripSeparator2,
+            this._optionsToolStripMenuItem,
+            this._exitToolStripMenuItem});
+            this._fileToolStripMenuItem.Name = "_fileToolStripMenuItem";
+            resources.ApplyResources(this._fileToolStripMenuItem, "_fileToolStripMenuItem");
+            // 
+            // _openEncryptedToolStripMenuItem
+            // 
+            resources.ApplyResources(this._openEncryptedToolStripMenuItem, "_openEncryptedToolStripMenuItem");
+            this._openEncryptedToolStripMenuItem.Name = "_openEncryptedToolStripMenuItem";
+            // 
+            // _encryptToolStripMenuItem
+            // 
+            resources.ApplyResources(this._encryptToolStripMenuItem, "_encryptToolStripMenuItem");
+            this._encryptToolStripMenuItem.Name = "_encryptToolStripMenuItem";
+            // 
+            // _decryptToolStripMenuItem
+            // 
+            resources.ApplyResources(this._decryptToolStripMenuItem, "_decryptToolStripMenuItem");
+            this._decryptToolStripMenuItem.Name = "_decryptToolStripMenuItem";
+            // 
+            // encryptedFoldersToolStripMenuItem
+            // 
+            this.encryptedFoldersToolStripMenuItem.Name = "encryptedFoldersToolStripMenuItem";
+            resources.ApplyResources(this.encryptedFoldersToolStripMenuItem, "encryptedFoldersToolStripMenuItem");
+            this.encryptedFoldersToolStripMenuItem.Click += new System.EventHandler(this.encryptedFoldersToolStripMenuItem_Click);
+            // 
+            // _toolStripSeparator6
+            // 
+            this._toolStripSeparator6.Name = "_toolStripSeparator6";
+            resources.ApplyResources(this._toolStripSeparator6, "_toolStripSeparator6");
+            // 
+            // _closeOpenFilesToolStripMenuItem
+            // 
+            resources.ApplyResources(this._closeOpenFilesToolStripMenuItem, "_closeOpenFilesToolStripMenuItem");
+            this._closeOpenFilesToolStripMenuItem.Name = "_closeOpenFilesToolStripMenuItem";
+            this._closeOpenFilesToolStripMenuItem.Click += new System.EventHandler(this.CloseOpenFilesToolStripMenuItem_Click);
+            // 
+            // _toolStripSeparator3
+            // 
+            this._toolStripSeparator3.Name = "_toolStripSeparator3";
+            resources.ApplyResources(this._toolStripSeparator3, "_toolStripSeparator3");
+            // 
+            // _wipeToolStripMenuItem
+            // 
+            this._wipeToolStripMenuItem.Image = global::Axantum.AxCrypt.Properties.Resources.trashred16;
+            this._wipeToolStripMenuItem.Name = "_wipeToolStripMenuItem";
+            resources.ApplyResources(this._wipeToolStripMenuItem, "_wipeToolStripMenuItem");
+            // 
+            // _toolStripSeparator2
+            // 
+            this._toolStripSeparator2.Name = "_toolStripSeparator2";
+            resources.ApplyResources(this._toolStripSeparator2, "_toolStripSeparator2");
+            // 
+            // _optionsToolStripMenuItem
+            // 
+            this._optionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._languageToolStripMenuItem,
+            this._debugOptionsToolStripMenuItem,
+            this._clearPassphraseMemoryToolStripMenuItem});
+            resources.ApplyResources(this._optionsToolStripMenuItem, "_optionsToolStripMenuItem");
+            this._optionsToolStripMenuItem.Name = "_optionsToolStripMenuItem";
+            // 
+            // _languageToolStripMenuItem
+            // 
+            this._languageToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._englishLanguageToolStripMenuItem,
+            this._swedishLanguageToolStripMenuItem});
+            this._languageToolStripMenuItem.Name = "_languageToolStripMenuItem";
+            resources.ApplyResources(this._languageToolStripMenuItem, "_languageToolStripMenuItem");
+            this._languageToolStripMenuItem.DropDownOpening += new System.EventHandler(this.LanguageToolStripMenuItem_DropDownOpening);
+            // 
+            // _englishLanguageToolStripMenuItem
+            // 
+            this._englishLanguageToolStripMenuItem.Name = "_englishLanguageToolStripMenuItem";
+            resources.ApplyResources(this._englishLanguageToolStripMenuItem, "_englishLanguageToolStripMenuItem");
+            this._englishLanguageToolStripMenuItem.Tag = "en";
+            this._englishLanguageToolStripMenuItem.Click += new System.EventHandler(this.EnglishLanguageToolStripMenuItem_Click);
+            // 
+            // _swedishLanguageToolStripMenuItem
+            // 
+            this._swedishLanguageToolStripMenuItem.Name = "_swedishLanguageToolStripMenuItem";
+            resources.ApplyResources(this._swedishLanguageToolStripMenuItem, "_swedishLanguageToolStripMenuItem");
+            this._swedishLanguageToolStripMenuItem.Tag = "sv";
+            this._swedishLanguageToolStripMenuItem.Click += new System.EventHandler(this.SwedishLanguageToolStripMenuItem_Click);
+            // 
+            // _debugOptionsToolStripMenuItem
+            // 
+            this._debugOptionsToolStripMenuItem.Name = "_debugOptionsToolStripMenuItem";
+            resources.ApplyResources(this._debugOptionsToolStripMenuItem, "_debugOptionsToolStripMenuItem");
+            // 
+            // _clearPassphraseMemoryToolStripMenuItem
+            // 
+            this._clearPassphraseMemoryToolStripMenuItem.Name = "_clearPassphraseMemoryToolStripMenuItem";
+            resources.ApplyResources(this._clearPassphraseMemoryToolStripMenuItem, "_clearPassphraseMemoryToolStripMenuItem");
+            this._clearPassphraseMemoryToolStripMenuItem.Click += new System.EventHandler(this.ClearPassphraseMemoryToolStripMenuItem_Click);
+            // 
+            // _exitToolStripMenuItem
+            // 
+            this._exitToolStripMenuItem.Name = "_exitToolStripMenuItem";
+            resources.ApplyResources(this._exitToolStripMenuItem, "_exitToolStripMenuItem");
+            this._exitToolStripMenuItem.Click += new System.EventHandler(this.ExitToolStripMenuItem_Click);
+            // 
+            // _debugToolStripMenuItem
+            // 
+            this._debugToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._checkVersionNowToolStripMenuItem,
+            this._setUpdateCheckUrlToolStripMenuItem,
+            this.cryptoPolicyToolStripMenuItem,
+            this.loggingToolStripMenuItem,
+            this.createAccountToolStripMenuItem});
+            this._debugToolStripMenuItem.Name = "_debugToolStripMenuItem";
+            resources.ApplyResources(this._debugToolStripMenuItem, "_debugToolStripMenuItem");
+            // 
+            // _checkVersionNowToolStripMenuItem
+            // 
+            this._checkVersionNowToolStripMenuItem.Name = "_checkVersionNowToolStripMenuItem";
+            resources.ApplyResources(this._checkVersionNowToolStripMenuItem, "_checkVersionNowToolStripMenuItem");
+            // 
+            // _setUpdateCheckUrlToolStripMenuItem
+            // 
+            this._setUpdateCheckUrlToolStripMenuItem.Name = "_setUpdateCheckUrlToolStripMenuItem";
+            resources.ApplyResources(this._setUpdateCheckUrlToolStripMenuItem, "_setUpdateCheckUrlToolStripMenuItem");
+            this._setUpdateCheckUrlToolStripMenuItem.Click += new System.EventHandler(this.SetUpdateCheckUrlToolStripMenuItem_Click);
+            // 
+            // cryptoPolicyToolStripMenuItem
+            // 
+            this.cryptoPolicyToolStripMenuItem.Name = "cryptoPolicyToolStripMenuItem";
+            resources.ApplyResources(this.cryptoPolicyToolStripMenuItem, "cryptoPolicyToolStripMenuItem");
+            this.cryptoPolicyToolStripMenuItem.DropDownOpening += new System.EventHandler(this.CryptoPolicyToolStripMenuItem_DropDownOpening);
+            // 
+            // loggingToolStripMenuItem
+            // 
+            this.loggingToolStripMenuItem.Name = "loggingToolStripMenuItem";
+            resources.ApplyResources(this.loggingToolStripMenuItem, "loggingToolStripMenuItem");
+            this.loggingToolStripMenuItem.Click += new System.EventHandler(this.loggingToolStripMenuItem_Click);
+            // 
+            // _helpToolStripMenuItem
+            // 
+            this._helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._viewHelpMenuItem,
+            this._aboutToolStripMenuItem});
+            this._helpToolStripMenuItem.Name = "_helpToolStripMenuItem";
+            resources.ApplyResources(this._helpToolStripMenuItem, "_helpToolStripMenuItem");
+            // 
+            // _viewHelpMenuItem
+            // 
+            this._viewHelpMenuItem.Name = "_viewHelpMenuItem";
+            resources.ApplyResources(this._viewHelpMenuItem, "_viewHelpMenuItem");
+            this._viewHelpMenuItem.Click += new System.EventHandler(this.ViewHelpMenuItem_Click);
+            // 
+            // _aboutToolStripMenuItem
+            // 
+            this._aboutToolStripMenuItem.Name = "_aboutToolStripMenuItem";
+            resources.ApplyResources(this._aboutToolStripMenuItem, "_aboutToolStripMenuItem");
+            this._aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutToolStripMenuItem_Click);
+            // 
+            // _progressTableLayoutPanel
+            // 
+            resources.ApplyResources(this._progressTableLayoutPanel, "_progressTableLayoutPanel");
+            this._progressTableLayoutPanel.GrowStyle = System.Windows.Forms.TableLayoutPanelGrowStyle.AddColumns;
+            this._progressTableLayoutPanel.Name = "_progressTableLayoutPanel";
+            // 
+            // _recentFilesContextMenuStrip
+            // 
+            this._recentFilesContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._removeRecentFileToolStripMenuItem,
+            this._decryptAndRemoveFromListToolStripMenuItem});
+            this._recentFilesContextMenuStrip.Name = "RecentFilesContextMenu";
+            resources.ApplyResources(this._recentFilesContextMenuStrip, "_recentFilesContextMenuStrip");
+            // 
+            // _removeRecentFileToolStripMenuItem
+            // 
+            this._removeRecentFileToolStripMenuItem.Name = "_removeRecentFileToolStripMenuItem";
+            resources.ApplyResources(this._removeRecentFileToolStripMenuItem, "_removeRecentFileToolStripMenuItem");
+            // 
+            // _decryptAndRemoveFromListToolStripMenuItem
+            // 
+            this._decryptAndRemoveFromListToolStripMenuItem.Name = "_decryptAndRemoveFromListToolStripMenuItem";
+            resources.ApplyResources(this._decryptAndRemoveFromListToolStripMenuItem, "_decryptAndRemoveFromListToolStripMenuItem");
+            // 
+            // _progressContextMenuStrip
+            // 
+            this._progressContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._progressContextCancelToolStripMenuItem});
+            this._progressContextMenuStrip.Name = "ProgressContextMenu";
+            resources.ApplyResources(this._progressContextMenuStrip, "_progressContextMenuStrip");
+            // 
+            // _progressContextCancelToolStripMenuItem
+            // 
+            this._progressContextCancelToolStripMenuItem.Name = "_progressContextCancelToolStripMenuItem";
+            resources.ApplyResources(this._progressContextCancelToolStripMenuItem, "_progressContextCancelToolStripMenuItem");
+            this._progressContextCancelToolStripMenuItem.Click += new System.EventHandler(this.ProgressContextCancelToolStripMenuItem_Click);
+            // 
+            // _watchedFoldersContextMenuStrip
+            // 
+            this._watchedFoldersContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._watchedFoldersRemoveMenuItem,
+            this._watchedFoldersdecryptTemporarilyMenuItem,
+            this._watchedFoldersOpenExplorerHereMenuItem});
+            this._watchedFoldersContextMenuStrip.Name = "watchedFoldersContextMenuStrip";
+            resources.ApplyResources(this._watchedFoldersContextMenuStrip, "_watchedFoldersContextMenuStrip");
+            // 
+            // _watchedFoldersRemoveMenuItem
+            // 
+            this._watchedFoldersRemoveMenuItem.Name = "_watchedFoldersRemoveMenuItem";
+            resources.ApplyResources(this._watchedFoldersRemoveMenuItem, "_watchedFoldersRemoveMenuItem");
+            // 
+            // _watchedFoldersdecryptTemporarilyMenuItem
+            // 
+            this._watchedFoldersdecryptTemporarilyMenuItem.Name = "_watchedFoldersdecryptTemporarilyMenuItem";
+            resources.ApplyResources(this._watchedFoldersdecryptTemporarilyMenuItem, "_watchedFoldersdecryptTemporarilyMenuItem");
+            // 
+            // _watchedFoldersOpenExplorerHereMenuItem
+            // 
+            this._watchedFoldersOpenExplorerHereMenuItem.Name = "_watchedFoldersOpenExplorerHereMenuItem";
+            resources.ApplyResources(this._watchedFoldersOpenExplorerHereMenuItem, "_watchedFoldersOpenExplorerHereMenuItem");
+            // 
+            // _watchedFoldersTabPage
+            // 
+            this._watchedFoldersTabPage.Controls.Add(this._watchedFoldersListView);
+            resources.ApplyResources(this._watchedFoldersTabPage, "_watchedFoldersTabPage");
+            this._watchedFoldersTabPage.Name = "_watchedFoldersTabPage";
+            this._watchedFoldersTabPage.UseVisualStyleBackColor = true;
+            // 
+            // _watchedFoldersListView
+            // 
+            this._watchedFoldersListView.AllowDrop = true;
+            this._watchedFoldersListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this._watchedFolderColumnHeader});
+            resources.ApplyResources(this._watchedFoldersListView, "_watchedFoldersListView");
+            this._watchedFoldersListView.FullRowSelect = true;
+            this._watchedFoldersListView.Name = "_watchedFoldersListView";
+            this._watchedFoldersListView.ShowItemToolTips = true;
+            this._watchedFoldersListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
+            this._watchedFoldersListView.UseCompatibleStateImageBehavior = false;
+            this._watchedFoldersListView.View = System.Windows.Forms.View.Details;
+            // 
+            // _watchedFolderColumnHeader
+            // 
+            resources.ApplyResources(this._watchedFolderColumnHeader, "_watchedFolderColumnHeader");
+            // 
+            // _recentFilesTabPage
+            // 
+            this._recentFilesTabPage.Controls.Add(this._recentFilesListView);
+            resources.ApplyResources(this._recentFilesTabPage, "_recentFilesTabPage");
+            this._recentFilesTabPage.Name = "_recentFilesTabPage";
+            this._recentFilesTabPage.UseVisualStyleBackColor = true;
+            // 
+            // _recentFilesListView
+            // 
+            this._recentFilesListView.AllowDrop = true;
+            this._recentFilesListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this._decryptedFileColumnHeader,
+            this._lastAccessTimeColumnHeader,
+            this._encryptedPathColumnHeader,
+            this._cryptoName});
+            resources.ApplyResources(this._recentFilesListView, "_recentFilesListView");
+            this._recentFilesListView.FullRowSelect = true;
+            this._recentFilesListView.Name = "_recentFilesListView";
+            this._recentFilesListView.ShowItemToolTips = true;
+            this._recentFilesListView.UseCompatibleStateImageBehavior = false;
+            this._recentFilesListView.View = System.Windows.Forms.View.Details;
+            // 
+            // _decryptedFileColumnHeader
+            // 
+            resources.ApplyResources(this._decryptedFileColumnHeader, "_decryptedFileColumnHeader");
+            // 
+            // _lastAccessTimeColumnHeader
+            // 
+            resources.ApplyResources(this._lastAccessTimeColumnHeader, "_lastAccessTimeColumnHeader");
+            // 
+            // _encryptedPathColumnHeader
+            // 
+            resources.ApplyResources(this._encryptedPathColumnHeader, "_encryptedPathColumnHeader");
+            // 
+            // _cryptoName
+            // 
+            resources.ApplyResources(this._cryptoName, "_cryptoName");
+            // 
+            // _statusTabControl
+            // 
+            resources.ApplyResources(this._statusTabControl, "_statusTabControl");
+            this._statusTabControl.Controls.Add(this._recentFilesTabPage);
+            this._statusTabControl.Controls.Add(this._watchedFoldersTabPage);
+            this._statusTabControl.Name = "_statusTabControl";
+            this._statusTabControl.SelectedIndex = 0;
+            // 
+            // _progressBackgroundWorker
+            // 
+            this._progressBackgroundWorker.ProgressBarCreated += new System.EventHandler<System.Windows.Forms.ControlEventArgs>(this.ProgressBackgroundWorker_ProgressBarCreated);
+            this._progressBackgroundWorker.ProgressBarClicked += new System.EventHandler<System.Windows.Forms.MouseEventArgs>(this.ProgressBackgroundWorker_ProgressBarClicked);
+            // 
+            // createAccountToolStripMenuItem
+            // 
+            this.createAccountToolStripMenuItem.Name = "createAccountToolStripMenuItem";
+            resources.ApplyResources(this.createAccountToolStripMenuItem, "createAccountToolStripMenuItem");
+            this.createAccountToolStripMenuItem.Click += new System.EventHandler(this.createAccountToolStripMenuItem_Click);
+            // 
+            // AxCryptMainForm
+            // 
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.Controls.Add(this._progressTableLayoutPanel);
+            this.Controls.Add(this._statusTabControl);
+            this.Controls.Add(this._mainToolStrip);
+            this.Controls.Add(this._mainMenuStrip);
+            this.MainMenuStrip = this._mainMenuStrip;
+            this.Name = "AxCryptMainForm";
+            this.Load += new System.EventHandler(this.AxCryptMainForm_Load);
+            this.Shown += new System.EventHandler(this.AxCryptMainForm_Shown);
+            this._mainToolStrip.ResumeLayout(false);
+            this._mainToolStrip.PerformLayout();
+            this._mainMenuStrip.ResumeLayout(false);
+            this._mainMenuStrip.PerformLayout();
+            this._recentFilesContextMenuStrip.ResumeLayout(false);
+            this._progressContextMenuStrip.ResumeLayout(false);
+            this._watchedFoldersContextMenuStrip.ResumeLayout(false);
+            this._watchedFoldersTabPage.ResumeLayout(false);
+            this._recentFilesTabPage.ResumeLayout(false);
+            this._statusTabControl.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ToolStrip _mainToolStrip;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator1;
+        private System.Windows.Forms.ToolStripButton _helpToolStripButton;
+        private System.Windows.Forms.ToolStripButton _encryptToolStripButton;
+        private System.Windows.Forms.ToolStripButton _decryptToolStripButton;
+        private System.Windows.Forms.MenuStrip _mainMenuStrip;
+        private System.Windows.Forms.ToolStripMenuItem _fileToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _encryptToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _decryptToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _helpToolStripMenuItem;
+        private System.Windows.Forms.ToolStripButton _openEncryptedToolStripButton;
+        private System.Windows.Forms.ToolStripMenuItem _openEncryptedToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _exitToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator2;
+        private System.Windows.Forms.ContextMenuStrip _recentFilesContextMenuStrip;
+        private System.Windows.Forms.ToolStripMenuItem _removeRecentFileToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _closeOpenFilesToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator3;
+        private System.Windows.Forms.ToolStripButton _closeAndRemoveOpenFilesToolStripButton;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator4;
+        private System.Windows.Forms.TableLayoutPanel _progressTableLayoutPanel;
+        private System.Windows.Forms.ContextMenuStrip _progressContextMenuStrip;
+        private System.Windows.Forms.ToolStripMenuItem _progressContextCancelToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _optionsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _languageToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _englishLanguageToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _swedishLanguageToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _knownFoldersSeparator;
+        private System.Windows.Forms.ToolStripButton _updateToolStripButton;
+        private System.Windows.Forms.ToolStripMenuItem _debugToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _setUpdateCheckUrlToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _debugOptionsToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _checkVersionNowToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _aboutToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _viewHelpMenuItem;
+        private Axantum.AxCrypt.Forms.ProgressBackground _progressBackgroundWorker;
+        private System.Windows.Forms.ToolStripButton _encryptionKeyToolStripButton;
+        private System.Windows.Forms.ToolStripMenuItem _decryptAndRemoveFromListToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator6;
+        private System.Windows.Forms.ToolStripMenuItem _wipeToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator7;
+        private System.Windows.Forms.ContextMenuStrip _watchedFoldersContextMenuStrip;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersRemoveMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersdecryptTemporarilyMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersOpenExplorerHereMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _clearPassphraseMemoryToolStripMenuItem;
+        private System.Windows.Forms.ToolStripSeparator _toolStripSeparator8;
+        private System.Windows.Forms.ToolStripMenuItem cryptoPolicyToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem loggingToolStripMenuItem;
+        private System.Windows.Forms.TabPage _watchedFoldersTabPage;
+        private System.Windows.Forms.ListView _watchedFoldersListView;
+        private System.Windows.Forms.ColumnHeader _watchedFolderColumnHeader;
+        private System.Windows.Forms.TabPage _recentFilesTabPage;
+        private System.Windows.Forms.ListView _recentFilesListView;
+        private System.Windows.Forms.ColumnHeader _decryptedFileColumnHeader;
+        private System.Windows.Forms.ColumnHeader _lastAccessTimeColumnHeader;
+        private System.Windows.Forms.ColumnHeader _encryptedPathColumnHeader;
+        private System.Windows.Forms.ColumnHeader _cryptoName;
+        private System.Windows.Forms.TabControl _statusTabControl;
+        private System.Windows.Forms.ToolStripMenuItem encryptedFoldersToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem createAccountToolStripMenuItem;
+    }
+}
+
diff --git a/Axantum.AxCrypt/AxCryptMainForm.cs b/Axantum.AxCrypt/AxCryptMainForm.cs
new file mode 100644
index 0000000..45fe277
--- /dev/null
+++ b/Axantum.AxCrypt/AxCryptMainForm.cs
@@ -0,0 +1,1411 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Ipc;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Drawing;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    /// <summary>
+    /// All code here is expected to execute on the GUI thread. If code may be called on another thread, this call
+    /// must be made through ThreadSafeUi() .
+    /// </summary>
+    public partial class AxCryptMainForm : Form, IStatusChecker
+    {
+        private NotifyIcon _notifyIcon = null;
+
+        private MainViewModel _mainViewModel;
+
+        private FileOperationViewModel _fileOperationViewModel;
+
+        private KnownFoldersViewModel _knownFoldersViewModel;
+
+        public static MessageBoxOptions MessageBoxOptions { get; private set; }
+
+        private DebugLogOutputDialog _debugOutput;
+
+        private TabPage _hiddenWatchedFoldersTabPage;
+
+        public AxCryptMainForm()
+        {
+            InitializeComponent();
+        }
+
+        private void AxCryptMainForm_Load(object sender, EventArgs e)
+        {
+            if (DesignMode)
+            {
+                return;
+            }
+
+            try
+            {
+                InitializeProgram();
+            }
+            catch
+            {
+                ClearAllSettingsAndReinitialize();
+                throw;
+            }
+        }
+
+        private void InitializeProgram()
+        {
+            RegisterTypeFactories();
+            SetupViewModels();
+            AttachLogListener();
+            ConfigureUiOptions();
+            SetupPathFilters();
+            IntializeControls();
+            RestoreUserPreferences();
+            BindToViewModels();
+            BindToFileOperationViewModel();
+            SetupCommandService();
+            SendStartSessionNotification();
+        }
+
+        private void LogOnOrExit()
+        {
+            if (_pendingRequest == null)
+            {
+                return;
+            }
+            _fileOperationViewModel.IdentityViewModel.LogOnLogOff.Execute(Instance.CryptoFactory.Default.Id);
+            if (!_mainViewModel.LoggedOn)
+            {
+                _pendingRequest = null;
+                return;
+            }
+            DoRequest(_pendingRequest);
+            _pendingRequest = null;
+        }
+
+        private static void SendStartSessionNotification()
+        {
+            Instance.SessionNotify.Notify(new SessionNotification(SessionNotificationType.SessionStart));
+        }
+
+        private void SetupCommandService()
+        {
+            Instance.CommandService.Received += Factory.Instance.Singleton<CommandHandler>().RequestReceived;
+            Instance.CommandService.StartListening();
+            Factory.Instance.Singleton<CommandHandler>().CommandComplete += AxCryptMainForm_CommandComplete;
+        }
+
+        private void ConfigureUiOptions()
+        {
+            MessageBoxOptions = RightToLeft == RightToLeft.Yes ? MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading : 0;
+        }
+
+        private void AttachLogListener()
+        {
+            Instance.Log.Logged += (logger, loggingEventArgs) =>
+            {
+                Instance.UIThread.PostOnUIThread(() =>
+                {
+                    if (_debugOutput == null || !_debugOutput.Visible)
+                    {
+                        return;
+                    }
+                    string formatted = "{0} {1}".InvariantFormat(OS.Current.UtcNow.ToString("o", CultureInfo.InvariantCulture), loggingEventArgs.Message.TrimLogMessage());
+                    _debugOutput.AppendText(formatted);
+                });
+            };
+        }
+
+        private void SetupViewModels()
+        {
+            _mainViewModel = Factory.New<MainViewModel>();
+            _fileOperationViewModel = Factory.New<FileOperationViewModel>();
+            _knownFoldersViewModel = Factory.New<KnownFoldersViewModel>();
+        }
+
+        private void AxCryptMainForm_Shown(object sender, EventArgs e)
+        {
+            if (Instance.UserSettings.SettingsVersion < Instance.UserSettings.CurrentSettingsVersion)
+            {
+                Resources.UserSettingsFormatChangeNeedsReset.ShowWarning();
+                ClearPassphraseMemoryToolStripMenuItem_Click(sender, e);
+            }
+        }
+
+        private void RegisterTypeFactories()
+        {
+            Factory.Instance.Singleton<IUIThread>(() => new UIThread(this));
+            Factory.Instance.Singleton<IProgressBackground>(() => _progressBackgroundWorker);
+            Factory.Instance.Singleton<IStatusChecker>(() => this);
+            Factory.Instance.Register<SessionNotificationHandler>(() => new SessionNotificationHandler(Instance.FileSystemState, Instance.KnownKeys, Factory.New<ActiveFileAction>(), Factory.New<AxCryptFile>(), this));
+
+            Factory.Instance.Register<IdentityViewModel>(() => new IdentityViewModel(Instance.FileSystemState, Instance.KnownKeys, Instance.UserSettings));
+            Factory.Instance.Register<FileOperationViewModel>(() => new FileOperationViewModel(Instance.FileSystemState, Instance.SessionNotify, Instance.KnownKeys, Instance.ParallelFileOperation, Factory.Instance.Singleton<IStatusChecker>(), Factory.New<IdentityViewModel>()));
+            Factory.Instance.Register<MainViewModel>(() => new MainViewModel(Instance.FileSystemState));
+            Factory.Instance.Register<KnownFoldersViewModel>(() => new KnownFoldersViewModel(Instance.FileSystemState, Instance.SessionNotify, Instance.KnownKeys));
+            Factory.Instance.Register<WatchedFoldersViewModel>(() => new WatchedFoldersViewModel(Instance.FileSystemState));
+        }
+
+        private static void SetupPathFilters()
+        {
+            if (OS.Current.Platform != Platform.WindowsDesktop)
+            {
+                return;
+            }
+
+            OS.PathFilters.Add(new Regex(@"\\\.dropbox$"));
+            OS.PathFilters.Add(new Regex(@"\\desktop\.ini$"));
+            OS.PathFilters.Add(new Regex(@".*\.tmp$"));
+            AddEnvironmentVariableBasedPathFilter(@"^{0}(?!Temp$)", "SystemRoot");
+            AddEnvironmentVariableBasedPathFilter(@"^{0}(?!Temp$)", "windir");
+            AddEnvironmentVariableBasedPathFilter(@"^{0}", "ProgramFiles");
+            AddEnvironmentVariableBasedPathFilter(@"^{0}", "ProgramFiles(x86)");
+            AddEnvironmentVariableBasedPathFilter(@"^{0}$", "SystemDrive");
+        }
+
+        private static void AddEnvironmentVariableBasedPathFilter(string formatRegularExpression, string name)
+        {
+            string folder = name.FolderFromEnvironment();
+            if (String.IsNullOrEmpty(folder))
+            {
+                return;
+            }
+            folder = folder.Replace(@"\", @"\\");
+            OS.PathFilters.Add(new Regex(formatRegularExpression.InvariantFormat(folder)));
+        }
+
+        private void IntializeControls()
+        {
+            if (OS.Current.Platform == Platform.WindowsDesktop)
+            {
+                InitializeNotifyIcon();
+            }
+
+            ResizeEnd += (sender, e) =>
+            {
+                if (WindowState == FormWindowState.Normal)
+                {
+                    Preferences.MainWindowHeight = Height;
+                    Preferences.MainWindowWidth = Width;
+                }
+            };
+            Move += (sender, e) =>
+            {
+                if (WindowState == FormWindowState.Normal)
+                {
+                    Preferences.MainWindowLocation = Location;
+                }
+            };
+            FormClosing += (sender, e) =>
+            {
+                EncryptPendingFiles();
+                while (_mainViewModel.Working)
+                {
+                    Application.DoEvents();
+                }
+                WarnIfAnyDecryptedFiles();
+            };
+
+            _encryptToolStripButton.Tag = FileInfoTypes.EncryptableFile;
+            _openEncryptedToolStripButton.Tag = FileInfoTypes.EncryptedFile;
+            _decryptToolStripButton.Tag = FileInfoTypes.EncryptedFile;
+
+            _hiddenWatchedFoldersTabPage = _statusTabControl.TabPages["_watchedFoldersTabPage"];
+
+            _recentFilesListView.SmallImageList = CreateSmallImageListToAvoidLocalizationIssuesWithDesignerAndResources();
+            _recentFilesListView.LargeImageList = CreateLargeImageListToAvoidLocalizationIssuesWithDesignerAndResources();
+            _recentFilesListView.ColumnWidthChanged += RecentFilesListView_ColumnWidthChanged;
+
+            InitializePolicyMenu();
+        }
+
+        private void InitializePolicyMenu()
+        {
+            string currentPolicyName = Factory.Instance.Singleton<ICryptoPolicy>().Name;
+            foreach (string policyName in Factory.Instance.Singleton<CryptoPolicy>().PolicyNames)
+            {
+                ToolStripMenuItem item = new ToolStripMenuItem();
+                item.Text = policyName;
+                item.Checked = policyName == currentPolicyName;
+                item.Click += PolicyMenuItem_Click;
+                cryptoPolicyToolStripMenuItem.DropDownItems.Add(item);
+            }
+        }
+
+        private void InitializeNotifyIcon()
+        {
+            _notifyIcon = new NotifyIcon(components);
+            _notifyIcon.Icon = Resources.axcrypticon;
+            _notifyIcon.Text = Resources.AxCryptFileEncryption;
+            _notifyIcon.BalloonTipTitle = Resources.AxCryptFileEncryption;
+            _notifyIcon.BalloonTipText = Resources.TrayBalloonTooltip;
+            _notifyIcon.Visible = true;
+
+            _notifyIcon.MouseClick += (sender, e) =>
+            {
+                Show();
+                WindowState = FormWindowState.Normal;
+            };
+
+            Resize += (sender, e) =>
+            {
+                switch (WindowState)
+                {
+                    case FormWindowState.Minimized:
+                        _notifyIcon.Visible = true;
+                        _notifyIcon.ShowBalloonTip(500);
+                        Hide();
+                        break;
+
+                    case FormWindowState.Normal:
+                        _notifyIcon.Visible = false;
+                        break;
+                }
+            };
+        }
+
+        private static ImageList CreateSmallImageListToAvoidLocalizationIssuesWithDesignerAndResources()
+        {
+            ImageList smallImageList = new ImageList();
+
+            smallImageList.Images.Add("ActiveFile", Resources.activefilegreen16);
+            smallImageList.Images.Add("Exclamation", Resources.exclamationgreen16);
+            smallImageList.Images.Add("DecryptedFile", Resources.decryptedfilered16);
+            smallImageList.Images.Add("DecryptedUnknownKeyFile", Resources.decryptedunknownkeyfilered16);
+            smallImageList.Images.Add("ActiveFileKnownKey", Resources.fileknownkeygreen16);
+            smallImageList.TransparentColor = System.Drawing.Color.Transparent;
+
+            return smallImageList;
+        }
+
+        private static ImageList CreateLargeImageListToAvoidLocalizationIssuesWithDesignerAndResources()
+        {
+            ImageList largeImageList = new ImageList();
+
+            largeImageList.Images.Add("ActiveFile", Resources.opendocument32);
+            largeImageList.Images.Add("Exclamation", Resources.exclamationgreen32);
+            largeImageList.TransparentColor = System.Drawing.Color.Transparent;
+
+            return largeImageList;
+        }
+
+        private void RecentFilesListView_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
+        {
+            switch (e.ColumnIndex)
+            {
+                case 0:
+                    Preferences.RecentFilesDocumentWidth = _recentFilesListView.Columns[e.ColumnIndex].Width;
+                    break;
+
+                case 1:
+                    Preferences.RecentFilesDateTimeWidth = _recentFilesListView.Columns[e.ColumnIndex].Width;
+                    break;
+
+                case 2:
+                    Preferences.RecentFilesEncryptedPathWidth = _recentFilesListView.Columns[e.ColumnIndex].Width;
+                    break;
+
+                case 3:
+                    Preferences.RecentFilesCryptoNameWidth = _recentFilesListView.Columns[e.ColumnIndex].Width;
+                    break;
+            }
+        }
+
+        private void RestoreUserPreferences()
+        {
+            Preferences.RecentFilesMaxNumber = 100;
+
+            if (WindowState == FormWindowState.Normal)
+            {
+                Height = Preferences.MainWindowHeight.Fallback(Height);
+                Width = Preferences.MainWindowWidth.Fallback(Width);
+                Location = Preferences.MainWindowLocation.Fallback(Location);
+            }
+
+            _recentFilesListView.Columns[0].Width = Preferences.RecentFilesDocumentWidth.Fallback(_recentFilesListView.Columns[0].Width);
+            _recentFilesListView.Columns[1].Width = Preferences.RecentFilesDateTimeWidth.Fallback(_recentFilesListView.Columns[1].Width);
+            _recentFilesListView.Columns[2].Width = Preferences.RecentFilesEncryptedPathWidth.Fallback(_recentFilesListView.Columns[2].Width);
+            _recentFilesListView.Columns[3].Width = Preferences.RecentFilesCryptoNameWidth.Fallback(_recentFilesListView.Columns[3].Width);
+
+            _mainViewModel.RecentFilesComparer = GetComparer(Preferences.RecentFilesSortColumn, !Preferences.RecentFilesAscending);
+        }
+
+        private void BindToViewModels()
+        {
+            _mainViewModel.Title = "{0} {1}{2}".InvariantFormat(Application.ProductName, Application.ProductVersion, String.IsNullOrEmpty(AboutBox.AssemblyDescription) ? String.Empty : " " + AboutBox.AssemblyDescription);
+            _mainViewModel.CurrentVersion = Assembly.GetExecutingAssembly().GetName().Version;
+
+            _mainViewModel.BindPropertyChanged("LoggedOn", (bool loggedOn) => { _encryptionKeyToolStripButton.Image = loggedOn ? Resources.encryptionkeyred32 : Resources.encryptionkeygreen32; });
+            _mainViewModel.BindPropertyChanged("LoggedOn", (bool loggedOn) => { _encryptionKeyToolStripButton.ToolTipText = loggedOn ? Resources.DefaultEncryptionKeyIsIsetToolTip : Resources.NoDefaultEncryptionKeySetToolTip; });
+            _mainViewModel.BindPropertyChanged("LoggedOn", (bool loggedOn) => { SetWindowTextWithLogonStatus(loggedOn); });
+            _mainViewModel.BindPropertyChanged("EncryptFileEnabled", (bool enabled) => { _encryptToolStripButton.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("EncryptFileEnabled", (bool enabled) => { _encryptToolStripMenuItem.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("DecryptFileEnabled", (bool enabled) => { _decryptToolStripButton.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("DecryptFileEnabled", (bool enabled) => { _decryptToolStripMenuItem.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("OpenEncryptedEnabled", (bool enabled) => { _openEncryptedToolStripButton.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("OpenEncryptedEnabled", (bool enabled) => { _openEncryptedToolStripMenuItem.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("FilesArePending", (bool filesArePending) => { _closeAndRemoveOpenFilesToolStripButton.Enabled = filesArePending; });
+            _mainViewModel.BindPropertyChanged("WatchedFolders", (IEnumerable<string> folders) => { UpdateWatchedFolders(folders); });
+            _mainViewModel.BindPropertyChanged("WatchedFoldersEnabled", (bool enabled) => { if (enabled) _statusTabControl.TabPages.Add(_hiddenWatchedFoldersTabPage); else _statusTabControl.TabPages.Remove(_hiddenWatchedFoldersTabPage); });
+            _mainViewModel.BindPropertyChanged("WatchedFoldersEnabled", (bool enabled) => { encryptedFoldersToolStripMenuItem.Enabled = enabled; });
+            _mainViewModel.BindPropertyChanged("RecentFiles", (IEnumerable<ActiveFile> files) => { UpdateRecentFiles(files); });
+            _mainViewModel.BindPropertyChanged("VersionUpdateStatus", (VersionUpdateStatus vus) => { UpdateVersionStatus(vus); });
+            _mainViewModel.BindPropertyChanged("DebugMode", (bool enabled) => { UpdateDebugMode(enabled); });
+
+            _checkVersionNowToolStripMenuItem.Click += (sender, e) => { _mainViewModel.UpdateCheck.Execute(DateTime.MinValue); };
+            _clearPassphraseMemoryToolStripMenuItem.Click += (sender, e) => { _mainViewModel.ClearPassphraseMemory.Execute(null); };
+            _debugOptionsToolStripMenuItem.Click += (sender, e) => { _mainViewModel.DebugMode = !_mainViewModel.DebugMode; };
+            _removeRecentFileToolStripMenuItem.Click += (sender, e) => { _mainViewModel.RemoveRecentFiles.Execute(_mainViewModel.SelectedRecentFiles); };
+
+            _watchedFoldersListView.SelectedIndexChanged += (sender, e) => { _mainViewModel.SelectedWatchedFolders = _watchedFoldersListView.SelectedItems.Cast<ListViewItem>().Select(lvi => lvi.Text); };
+            _watchedFoldersListView.MouseClick += (sender, e) => { if (e.Button == MouseButtons.Right) _watchedFoldersContextMenuStrip.Show((Control)sender, e.Location); };
+            _watchedFoldersListView.DragOver += (sender, e) => { _mainViewModel.DragAndDropFiles = e.GetDragged(); e.Effect = GetEffectsForWatchedFolders(e); };
+            _watchedFoldersListView.DragDrop += (sender, e) => { _mainViewModel.AddWatchedFolders.Execute(_mainViewModel.DragAndDropFiles); };
+            _watchedFoldersOpenExplorerHereMenuItem.Click += (sender, e) => { _mainViewModel.OpenSelectedFolder.Execute(_mainViewModel.SelectedWatchedFolders.First()); };
+            _watchedFoldersRemoveMenuItem.Click += (sender, e) => { _mainViewModel.RemoveWatchedFolders.Execute(_mainViewModel.SelectedWatchedFolders); };
+
+            _recentFilesListView.ColumnClick += (sender, e) => { SetSortOrder(e.Column); };
+            _recentFilesListView.SelectedIndexChanged += (sender, e) => { _mainViewModel.SelectedRecentFiles = _recentFilesListView.SelectedItems.Cast<ListViewItem>().Select(lvi => lvi.SubItems["EncryptedPath"].Text); };
+            _recentFilesListView.MouseClick += (sender, e) => { if (e.Button == MouseButtons.Right) _recentFilesContextMenuStrip.Show((Control)sender, e.Location); };
+            _recentFilesListView.DragOver += (sender, e) => { _mainViewModel.DragAndDropFiles = e.GetDragged(); e.Effect = GetEffectsForRecentFiles(e); };
+
+            _mainToolStrip.DragOver += (sender, e) => { _mainViewModel.DragAndDropFiles = e.GetDragged(); e.Effect = GetEffectsForMainToolStrip(e); };
+
+            _knownFoldersViewModel.BindPropertyChanged("KnownFolders", (IEnumerable<KnownFolder> folders) => UpdateKnownFolders(folders));
+            _knownFoldersViewModel.KnownFolders = KnownFoldersDiscovery.Discover();
+        }
+
+        private void BindToWatchedFoldersViewModel()
+        {
+        }
+
+        private void BindToFileOperationViewModel()
+        {
+            _decryptAndRemoveFromListToolStripMenuItem.Click += (sender, e) => { _fileOperationViewModel.DecryptFiles.Execute(_mainViewModel.SelectedRecentFiles); };
+            _decryptToolStripButton.Click += (sender, e) => { _fileOperationViewModel.DecryptFiles.Execute(null); };
+            _decryptToolStripMenuItem.Click += (sender, e) => { _fileOperationViewModel.DecryptFiles.Execute(null); };
+            _encryptionKeyToolStripButton.Click += (sender, e) => { _fileOperationViewModel.IdentityViewModel.LogOnLogOff.Execute(Instance.CryptoFactory.Default.Id); };
+            _encryptToolStripButton.Click += (sender, e) => { _fileOperationViewModel.EncryptFiles.Execute(null); };
+            _encryptToolStripMenuItem.Click += (sender, e) => { _fileOperationViewModel.EncryptFiles.Execute(null); };
+            _openEncryptedToolStripButton.Click += (sender, e) => { _fileOperationViewModel.OpenFilesFromFolder.Execute(String.Empty); };
+            _openEncryptedToolStripMenuItem.Click += (sender, e) => { _fileOperationViewModel.OpenFilesFromFolder.Execute(String.Empty); };
+            _wipeToolStripMenuItem.Click += (sender, e) => { _fileOperationViewModel.WipeFiles.Execute(null); };
+
+            _watchedFoldersListView.MouseDoubleClick += (sender, e) => { _fileOperationViewModel.OpenFilesFromFolder.Execute(_mainViewModel.SelectedWatchedFolders.FirstOrDefault()); };
+            _watchedFoldersdecryptTemporarilyMenuItem.Click += (sender, e) => { _fileOperationViewModel.DecryptFolders.Execute(_mainViewModel.SelectedWatchedFolders); };
+
+            _recentFilesListView.MouseDoubleClick += (sender, e) => { _fileOperationViewModel.OpenFiles.Execute(_mainViewModel.SelectedRecentFiles); };
+            _recentFilesListView.DragDrop += (sender, e) => { DropFilesOrFoldersInRecentFilesListView(); };
+
+            _fileOperationViewModel.IdentityViewModel.LoggingOn += (sender, e) => { HandleLogOn(e); };
+            _fileOperationViewModel.SelectingFiles += (sender, e) => { HandleFileSelection(e); };
+
+            _decryptToolStripButton.Tag = _fileOperationViewModel.DecryptFiles;
+            _openEncryptedToolStripButton.Tag = _fileOperationViewModel.OpenFiles;
+            _encryptToolStripButton.Tag = _fileOperationViewModel.EncryptFiles;
+        }
+
+        private void DropFilesOrFoldersInRecentFilesListView()
+        {
+            if (_mainViewModel.DroppableAsRecent)
+            {
+                _fileOperationViewModel.AddRecentFiles.Execute(_mainViewModel.DragAndDropFiles);
+            }
+            if (_mainViewModel.DroppableAsWatchedFolder)
+            {
+                //_mainViewModel.AddWatchedFolders.Execute(_mainViewModel.DragAndDropFiles);
+                //_statusTabControl.SelectedTab = _watchedFoldersTabPage;
+                ShowWatchedFolders(_mainViewModel.DragAndDropFiles);
+            }
+        }
+
+        private void HandleLogOn(LogOnEventArgs e)
+        {
+            if (e.CreateNew)
+            {
+                HandleCreateNewLogOn(e);
+            }
+            else
+            {
+                HandleExistingLogOn(e);
+            }
+        }
+
+        private void HandleCreateNewLogOn(LogOnEventArgs e)
+        {
+            RestoreWindowWithFocus();
+            using (NewPassphraseDialog passphraseDialog = new NewPassphraseDialog(this, e.Passphrase, e.EncryptedFileFullName))
+            {
+                passphraseDialog.ShowPassphraseCheckBox.Checked = e.DisplayPassphrase;
+                DialogResult dialogResult = passphraseDialog.ShowDialog(this);
+                if (dialogResult != DialogResult.OK || passphraseDialog.PassphraseTextBox.Text.Length == 0)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                e.DisplayPassphrase = passphraseDialog.ShowPassphraseCheckBox.Checked;
+                e.Passphrase = passphraseDialog.PassphraseTextBox.Text;
+                e.Name = String.Empty;
+            }
+            return;
+        }
+
+        private void HandleExistingLogOn(LogOnEventArgs e)
+        {
+            RestoreWindowWithFocus();
+            if (!String.IsNullOrEmpty(e.EncryptedFileFullName))
+            {
+                HandleExistingLogOnForEncryptedFile(e);
+            }
+            else
+            {
+                HandleExistingAccountLogOn(e);
+            }
+        }
+
+        private void HandleExistingLogOnForEncryptedFile(LogOnEventArgs e)
+        {
+            using (LogOnDialog logOnDialog = new LogOnDialog(this, e.EncryptedFileFullName))
+            {
+                logOnDialog.ShowPassphraseCheckBox.Checked = e.DisplayPassphrase;
+                DialogResult dialogResult = logOnDialog.ShowDialog(this);
+                if (dialogResult == DialogResult.Retry)
+                {
+                    e.Passphrase = logOnDialog.PassphraseTextBox.Text;
+                    e.CreateNew = true;
+                    return;
+                }
+
+                if (dialogResult != DialogResult.OK || logOnDialog.PassphraseTextBox.Text.Length == 0)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                e.DisplayPassphrase = logOnDialog.ShowPassphraseCheckBox.Checked;
+                e.Passphrase = logOnDialog.PassphraseTextBox.Text;
+            }
+            return;
+        }
+
+        private void HandleExistingAccountLogOn(LogOnEventArgs e)
+        {
+            using (LogOnAccountDialog logOnDialog = new LogOnAccountDialog(this))
+            {
+                logOnDialog.ShowPassphraseCheckBox.Checked = e.DisplayPassphrase;
+                DialogResult dialogResult = logOnDialog.ShowDialog(this);
+                if (dialogResult == DialogResult.Retry)
+                {
+                    e.Passphrase = logOnDialog.PassphraseTextBox.Text;
+                    e.UserEmail = logOnDialog.EmailTextBox.Text;
+                    e.CreateNew = true;
+                    return;
+                }
+
+                if (dialogResult != DialogResult.OK || logOnDialog.PassphraseTextBox.Text.Length == 0)
+                {
+                    e.Cancel = true;
+                    return;
+                }
+                e.DisplayPassphrase = logOnDialog.ShowPassphraseCheckBox.Checked;
+                e.Passphrase = logOnDialog.PassphraseTextBox.Text;
+            }
+            return;
+        }
+
+        private static void HandleFileSelection(FileSelectionEventArgs e)
+        {
+            switch (e.FileSelectionType)
+            {
+                case FileSelectionType.SaveAsEncrypted:
+                case FileSelectionType.SaveAsDecrypted:
+                    HandleSaveAsFileSelection(e);
+                    break;
+
+                case FileSelectionType.WipeConfirm:
+                    HandleWipeConfirm(e);
+                    break;
+
+                default:
+                    HandleOpenFileSelection(e);
+                    break;
+            }
+        }
+
+        private static void HandleWipeConfirm(FileSelectionEventArgs e)
+        {
+            using (ConfirmWipeDialog cwd = new ConfirmWipeDialog())
+            {
+                cwd.FileNameLabel.Text = Path.GetFileName(e.SelectedFiles[0]);
+                e.Skip = false;
+                DialogResult confirmResult = cwd.ShowDialog();
+                e.ConfirmAll = cwd.ConfirmAllCheckBox.Checked;
+                e.Skip = confirmResult == DialogResult.No;
+                e.Cancel = confirmResult == DialogResult.Cancel;
+            }
+        }
+
+        private static void HandleOpenFileSelection(FileSelectionEventArgs e)
+        {
+            using (OpenFileDialog ofd = new OpenFileDialog())
+            {
+                if (e.SelectedFiles != null && e.SelectedFiles.Count > 0 && !String.IsNullOrEmpty(e.SelectedFiles[0]))
+                {
+                    IRuntimeFileInfo initialFolder = Factory.New<IRuntimeFileInfo>(e.SelectedFiles[0]);
+                    if (initialFolder.IsExistingFolder)
+                    {
+                        ofd.InitialDirectory = initialFolder.FullName;
+                    }
+                }
+                switch (e.FileSelectionType)
+                {
+                    case FileSelectionType.Decrypt:
+                        ofd.Title = Resources.DecryptFileOpenDialogTitle;
+                        ofd.Multiselect = true;
+                        ofd.CheckFileExists = true;
+                        ofd.CheckPathExists = true;
+                        ofd.DefaultExt = OS.Current.AxCryptExtension;
+                        ofd.Filter = Resources.EncryptedFileDialogFilterPattern.InvariantFormat("{0}".InvariantFormat(OS.Current.AxCryptExtension));
+                        ofd.Multiselect = true;
+                        break;
+
+                    case FileSelectionType.Encrypt:
+                        ofd.Title = Resources.EncryptFileOpenDialogTitle;
+                        ofd.Multiselect = true;
+                        ofd.CheckFileExists = true;
+                        ofd.CheckPathExists = true;
+                        break;
+
+                    case FileSelectionType.Open:
+                        ofd.Title = Resources.OpenEncryptedFileOpenDialogTitle;
+                        ofd.Multiselect = false;
+                        ofd.CheckFileExists = true;
+                        ofd.CheckPathExists = true;
+                        ofd.DefaultExt = OS.Current.AxCryptExtension;
+                        ofd.Filter = Resources.EncryptedFileDialogFilterPattern.InvariantFormat("{0}".InvariantFormat(OS.Current.AxCryptExtension));
+                        break;
+
+                    case FileSelectionType.Wipe:
+                        ofd.Title = Resources.WipeFileSelectFileDialogTitle;
+                        ofd.Multiselect = true;
+                        ofd.CheckFileExists = true;
+                        ofd.CheckPathExists = true;
+                        break;
+
+                    default:
+                        break;
+                }
+                DialogResult result = ofd.ShowDialog();
+                e.Cancel = result != DialogResult.OK;
+                e.SelectedFiles.Clear();
+                foreach (string fileName in ofd.FileNames)
+                {
+                    e.SelectedFiles.Add(fileName);
+                }
+            }
+        }
+
+        private static void HandleSaveAsFileSelection(FileSelectionEventArgs e)
+        {
+            using (SaveFileDialog sfd = new SaveFileDialog())
+            {
+                switch (e.FileSelectionType)
+                {
+                    case FileSelectionType.SaveAsEncrypted:
+                        sfd.Title = Resources.EncryptFileSaveAsDialogTitle;
+                        sfd.DefaultExt = OS.Current.AxCryptExtension;
+                        sfd.AddExtension = true;
+                        sfd.Filter = Resources.EncryptedFileDialogFilterPattern.InvariantFormat(OS.Current.AxCryptExtension);
+                        break;
+
+                    case FileSelectionType.SaveAsDecrypted:
+                        string extension = Path.GetExtension(e.SelectedFiles[0]);
+                        sfd.Title = Resources.DecryptedSaveAsFileDialogTitle;
+                        sfd.DefaultExt = extension;
+                        sfd.AddExtension = !String.IsNullOrEmpty(extension);
+                        sfd.Filter = Resources.DecryptedSaveAsFileDialogFilterPattern.InvariantFormat(extension);
+                        break;
+                }
+                sfd.CheckPathExists = true;
+                sfd.FileName = Path.GetFileName(e.SelectedFiles[0]);
+                sfd.InitialDirectory = Path.GetDirectoryName(e.SelectedFiles[0]);
+                sfd.ValidateNames = true;
+                sfd.OverwritePrompt = true;
+                sfd.RestoreDirectory = true;
+                DialogResult saveAsResult = sfd.ShowDialog();
+                e.Cancel = saveAsResult != DialogResult.OK;
+                e.SelectedFiles[0] = sfd.FileName;
+            }
+        }
+
+        private void AxCryptMainForm_CommandComplete(object sender, CommandCompleteEventArgs e)
+        {
+            Instance.UIThread.RunOnUIThread(() => DoRequest(e));
+        }
+
+        private CommandCompleteEventArgs _pendingRequest;
+
+        private void DoRequest(CommandCompleteEventArgs e)
+        {
+            if ((e.Verb == CommandVerb.Encrypt) && !Instance.KnownKeys.IsLoggedOn)
+            {
+                RestoreWindowWithFocus();
+                _pendingRequest = e;
+                LogOnOrExit();
+                return;
+            }
+            switch (e.Verb)
+            {
+                case CommandVerb.Encrypt:
+                    _fileOperationViewModel.EncryptFiles.Execute(e.Arguments);
+                    break;
+
+                case CommandVerb.Decrypt:
+                    _fileOperationViewModel.DecryptFiles.Execute(e.Arguments);
+                    break;
+
+                case CommandVerb.Open:
+                    _fileOperationViewModel.OpenFiles.Execute(e.Arguments);
+                    break;
+
+                case CommandVerb.Wipe:
+                    _fileOperationViewModel.WipeFiles.Execute(e.Arguments);
+                    break;
+
+                case CommandVerb.RandomRename:
+                    _fileOperationViewModel.RandomRenameFiles.Execute(e.Arguments);
+                    break;
+
+                case CommandVerb.Exit:
+                    Application.Exit();
+                    break;
+
+                case CommandVerb.Show:
+                    RestoreWindowWithFocus();
+                    break;
+
+                case CommandVerb.Register:
+                    Process.Start("https://www.axantum.com/Xecrets/LoggedOff/Register.aspx");
+                    break;
+
+                case CommandVerb.About:
+                    RestoreWindowWithFocus();
+                    using (AboutBox aboutBox = new AboutBox())
+                    {
+                        aboutBox.ShowDialog();
+                    }
+                    break;
+            }
+        }
+
+        private static bool IsImmediate(CommandVerb verb)
+        {
+            switch (verb)
+            {
+                case CommandVerb.Wipe:
+                case CommandVerb.Show:
+                case CommandVerb.Exit:
+                case CommandVerb.About:
+                case CommandVerb.Register:
+                    return true;
+            }
+            return false;
+        }
+
+        private void RestoreWindowWithFocus()
+        {
+            if (ContainsFocus)
+            {
+                return;
+            }
+            if (ContainsFocus && !OwnedForms.Any())
+            {
+                return;
+            }
+            if (!ContainsFocus)
+            {
+                if (WindowState == FormWindowState.Normal)
+                {
+                    WindowState = FormWindowState.Minimized;
+                }
+                Show();
+                WindowState = FormWindowState.Normal;
+                Activate();
+            }
+            if (OwnedForms.Any())
+            {
+                OwnedForms.First().Focus();
+            }
+        }
+
+        private DragDropEffects GetEffectsForMainToolStrip(DragEventArgs e)
+        {
+            if (_mainViewModel.DragAndDropFiles.Count() != 1)
+            {
+                return DragDropEffects.None;
+            }
+            Point point = _mainToolStrip.PointToClient(new Point(e.X, e.Y));
+            ToolStripButton button = _mainToolStrip.GetItemAt(point) as ToolStripButton;
+            if (button == null)
+            {
+                return DragDropEffects.None;
+            }
+            if (!button.Enabled)
+            {
+                return DragDropEffects.None;
+            }
+            if (button == _encryptToolStripButton)
+            {
+                if ((_mainViewModel.DragAndDropFilesTypes & FileInfoTypes.EncryptableFile) == FileInfoTypes.EncryptableFile)
+                {
+                    return (DragDropEffects.Link | DragDropEffects.Copy) & e.AllowedEffect;
+                }
+            }
+            if (button == _decryptToolStripButton || button == _openEncryptedToolStripButton)
+            {
+                if ((_mainViewModel.DragAndDropFilesTypes & FileInfoTypes.EncryptedFile) == FileInfoTypes.EncryptedFile)
+                {
+                    return (DragDropEffects.Link | DragDropEffects.Copy) & e.AllowedEffect;
+                }
+            }
+            return DragDropEffects.None;
+        }
+
+        private DragDropEffects GetEffectsForRecentFiles(DragEventArgs e)
+        {
+            if (!_mainViewModel.DroppableAsRecent && !_mainViewModel.DroppableAsWatchedFolder)
+            {
+                return DragDropEffects.None;
+            }
+            return (DragDropEffects.Link | DragDropEffects.Copy) & e.AllowedEffect;
+        }
+
+        public DragDropEffects GetEffectsForWatchedFolders(DragEventArgs e)
+        {
+            if (!_mainViewModel.DroppableAsWatchedFolder)
+            {
+                return DragDropEffects.None;
+            }
+            return (DragDropEffects.Link | DragDropEffects.Copy) & e.AllowedEffect;
+        }
+
+        private void SetWindowTextWithLogonStatus(bool isLoggedOn)
+        {
+            string logonStatus;
+            if (isLoggedOn)
+            {
+                logonStatus = Resources.LoggedOnStatusText.InvariantFormat(String.Empty);
+            }
+            else
+            {
+                logonStatus = Resources.LoggedOffStatusText;
+            }
+            Text = "{0} - {1}".InvariantFormat(_mainViewModel.Title, logonStatus);
+        }
+
+        private void UpdateVersionStatus(VersionUpdateStatus status)
+        {
+            switch (status)
+            {
+                case VersionUpdateStatus.IsUpToDateOrRecentlyChecked:
+                    _updateToolStripButton.ToolTipText = Axantum.AxCrypt.Properties.Resources.NoNeedToCheckForUpdatesTooltip;
+                    _updateToolStripButton.Enabled = false;
+                    break;
+
+                case VersionUpdateStatus.LongTimeSinceLastSuccessfulCheck:
+                    _updateToolStripButton.ToolTipText = Axantum.AxCrypt.Properties.Resources.OldVersionTooltip;
+                    _updateToolStripButton.Image = Resources.refreshred;
+                    _updateToolStripButton.Enabled = true;
+                    break;
+
+                case VersionUpdateStatus.NewerVersionIsAvailable:
+                    _updateToolStripButton.ToolTipText = Axantum.AxCrypt.Properties.Resources.NewVersionIsAvailableTooltip.InvariantFormat(_mainViewModel.UpdatedVersion);
+                    _updateToolStripButton.Image = Resources.refreshred;
+                    _updateToolStripButton.Enabled = true;
+                    break;
+
+                case VersionUpdateStatus.Unknown:
+                case VersionUpdateStatus.ShortTimeSinceLastSuccessfulCheck:
+                    _updateToolStripButton.ToolTipText = Axantum.AxCrypt.Properties.Resources.ClickToCheckForNewerVersionTooltip;
+                    _updateToolStripButton.Image = Resources.refreshgreen;
+                    _updateToolStripButton.Enabled = true;
+                    break;
+            }
+        }
+
+        private void UpdateDebugMode(bool enabled)
+        {
+            _debugOptionsToolStripMenuItem.Checked = enabled;
+            _debugToolStripMenuItem.Visible = enabled;
+        }
+
+        private void UpdateWatchedFolders(IEnumerable<string> watchedFolders)
+        {
+            _watchedFoldersListView.BeginUpdate();
+            try
+            {
+                _watchedFoldersListView.Items.Clear();
+                foreach (string folder in watchedFolders)
+                {
+                    ListViewItem item = _watchedFoldersListView.Items.Add(folder);
+                    item.Name = folder;
+                }
+            }
+            finally
+            {
+                _watchedFoldersListView.EndUpdate();
+            }
+        }
+
+        private void UpdateRecentFiles(IEnumerable<ActiveFile> files)
+        {
+            _recentFilesListView.BeginUpdate();
+            try
+            {
+                HashSet<string> newFiles = new HashSet<string>(files.Select(f => f.DecryptedFileInfo.FullName));
+                Dictionary<string, int> currentFiles = new Dictionary<string, int>();
+                for (int i = 0; i < _recentFilesListView.Items.Count; )
+                {
+                    if (!newFiles.Contains(_recentFilesListView.Items[i].Name))
+                    {
+                        _recentFilesListView.Items.RemoveAt(i);
+                        continue;
+                    }
+                    ++i;
+                    currentFiles.Add(_recentFilesListView.Items[i].Name, i);
+                }
+                List<ListViewItem> newItems = new List<ListViewItem>();
+                foreach (ActiveFile file in files)
+                {
+                    string text = Path.GetFileName(file.DecryptedFileInfo.FullName);
+                    ListViewItem item = new ListViewItem(text);
+                    item.Name = file.EncryptedFileInfo.FullName;
+
+                    ListViewItem.ListViewSubItem dateColumn = item.SubItems.Add(String.Empty);
+                    dateColumn.Name = "Date";
+
+                    ListViewItem.ListViewSubItem encryptedPathColumn = item.SubItems.Add(String.Empty);
+                    encryptedPathColumn.Name = "EncryptedPath";
+
+                    ListViewItem.ListViewSubItem cryptoNameColumn = item.SubItems.Add(String.Empty);
+                    cryptoNameColumn.Name = "CryptoName";
+
+                    UpdateListViewItem(item, file);
+                    int i;
+                    if (currentFiles.TryGetValue(item.Name, out i))
+                    {
+                        _recentFilesListView.Items[i] = item;
+                    }
+                    else
+                    {
+                        newItems.Add(item);
+                    }
+                }
+                _recentFilesListView.Items.AddRange(newItems.ToArray());
+                while (_recentFilesListView.Items.Count > Preferences.RecentFilesMaxNumber)
+                {
+                    _recentFilesListView.Items.RemoveAt(_recentFilesListView.Items.Count - 1);
+                }
+            }
+            finally
+            {
+                _recentFilesListView.EndUpdate();
+            }
+        }
+
+        private void UpdateKnownFolders(IEnumerable<KnownFolder> folders)
+        {
+            GetKnownFoldersToolItems().Skip(1).ToList().ForEach(f => _mainToolStrip.Items.Remove(f));
+
+            bool anyFolders = folders.Any();
+            GetKnownFoldersToolItems().First().Visible = anyFolders;
+
+            if (!anyFolders)
+            {
+                return;
+            }
+
+            int i = _mainToolStrip.Items.IndexOf(GetKnownFoldersToolItems().First()) + 1;
+            foreach (KnownFolder knownFolder in folders)
+            {
+                ToolStripButton button = new ToolStripButton((Image)knownFolder.Image);
+                button.Tag = knownFolder;
+                button.Click += (sender, e) =>
+                {
+                    ToolStripItem item = sender as ToolStripItem;
+                    _fileOperationViewModel.OpenFilesFromFolder.Execute(((KnownFolder)item.Tag).MyFullPath.FullName);
+                };
+                button.Image = (Image)knownFolder.Image;
+                button.Enabled = knownFolder.Enabled;
+                _mainToolStrip.Items.Insert(i, button);
+                ++i;
+            }
+        }
+
+        private List<ToolStripItem> GetKnownFoldersToolItems()
+        {
+            List<ToolStripItem> buttons = new List<ToolStripItem>();
+            int i = _mainToolStrip.Items.IndexOf(_knownFoldersSeparator);
+            buttons.Add(_mainToolStrip.Items[i++]);
+            while (_mainToolStrip.Items[i] is ToolStripButton)
+            {
+                buttons.Add(_mainToolStrip.Items[i++]);
+            }
+            return buttons;
+        }
+
+        private static void UpdateListViewItem(ListViewItem item, ActiveFile activeFile)
+        {
+            UpdateStatusDependentPropertiesOfListViewItem(item, activeFile);
+
+            item.SubItems["EncryptedPath"].Text = activeFile.EncryptedFileInfo.FullName;
+            item.SubItems["Date"].Text = activeFile.Properties.LastActivityTimeUtc.ToLocalTime().ToString(CultureInfo.CurrentCulture);
+            item.SubItems["Date"].Tag = activeFile.Properties.LastActivityTimeUtc;
+
+            item.SubItems["CryptoName"].Text = Resources.UnknownCrypto;
+            try
+            {
+                if (activeFile.Properties.CryptoId != Guid.Empty)
+                {
+                    item.SubItems["CryptoName"].Text = Instance.CryptoFactory.Create(activeFile.Properties.CryptoId).Name;
+                }
+            }
+            catch (ArgumentException)
+            {
+            }
+        }
+
+        private static void UpdateStatusDependentPropertiesOfListViewItem(ListViewItem item, ActiveFile activeFile)
+        {
+            switch (activeFile.VisualState)
+            {
+                case ActiveFileVisualState.DecryptedWithKnownKey:
+                    item.ImageKey = "DecryptedFile";
+                    item.ToolTipText = Resources.DecryptedFileToolTip;
+                    break;
+
+                case ActiveFileVisualState.DecryptedWithoutKnownKey:
+                    item.ImageKey = "DecryptedUnknownKeyFile";
+                    item.ToolTipText = Resources.DecryptedUnknownKeyFileToolTip;
+                    break;
+
+                case ActiveFileVisualState.EncryptedWithoutKnownKey:
+                    item.ImageKey = "ActiveFile";
+                    item.ToolTipText = Resources.ActiveFileToolTip;
+                    break;
+
+                case ActiveFileVisualState.EncryptedWithKnownKey:
+                    item.ImageKey = "ActiveFileKnownKey";
+                    item.ToolTipText = Resources.ActiveFileKnownKeyToolTip;
+                    break;
+
+                default:
+                    throw new InvalidOperationException("Unexpected ActiveFileVisualState value.");
+            }
+        }
+
+        public bool CheckStatusAndShowMessage(FileOperationStatus status, string displayContext)
+        {
+            switch (status)
+            {
+                case FileOperationStatus.Success:
+                    return true;
+
+                case FileOperationStatus.UnspecifiedError:
+                    Resources.FileOperationFailed.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.FileAlreadyExists:
+                    Resources.FileAlreadyExists.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.FileDoesNotExist:
+                    Resources.FileDoesNotExist.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.CannotWriteDestination:
+                    Resources.CannotWrite.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.CannotStartApplication:
+                    Resources.CannotStartApplication.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.InconsistentState:
+                    Resources.InconsistentState.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.InvalidKey:
+                    Resources.InvalidKey.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.Canceled:
+                    break;
+
+                case FileOperationStatus.Exception:
+                    Resources.Exception.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.InvalidPath:
+                    Resources.InvalidPath.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.FolderAlreadyWatched:
+                    Resources.FolderAlreadyWatched.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                case FileOperationStatus.FileLocked:
+                    Resources.FileIsLockedWarning.InvariantFormat(displayContext).ShowWarning();
+                    break;
+
+                default:
+                    Resources.UnrecognizedError.InvariantFormat(displayContext).ShowWarning();
+                    break;
+            }
+            return false;
+        }
+
+        private void ExitToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            if (_debugOutput != null)
+            {
+                _debugOutput.AllowClose = true;
+            }
+            Application.Exit();
+        }
+
+        #region ToolStrip
+
+        private void MainToolStrip_DragDrop(object sender, DragEventArgs e)
+        {
+            Point point = _mainToolStrip.PointToClient(new Point(e.X, e.Y));
+            ToolStripButton button = _mainToolStrip.GetItemAt(point) as ToolStripButton;
+            if (button == null)
+            {
+                return;
+            }
+            if (!button.Enabled)
+            {
+                return;
+            }
+
+            ((IAction)button.Tag).Execute(_mainViewModel.DragAndDropFiles);
+        }
+
+        #endregion ToolStrip
+
+        private void EncryptPendingFiles()
+        {
+            _mainViewModel.EncryptPendingFiles.Execute(null);
+        }
+
+        private void WarnIfAnyDecryptedFiles()
+        {
+            IEnumerable<ActiveFile> openFiles = _mainViewModel.DecryptedFiles;
+            if (!openFiles.Any())
+            {
+                return;
+            }
+            StringBuilder sb = new StringBuilder();
+            foreach (ActiveFile openFile in openFiles)
+            {
+                sb.Append("{0}{1}".InvariantFormat(Path.GetFileName(openFile.DecryptedFileInfo.FullName), Environment.NewLine));
+            }
+            sb.ToString().ShowWarning();
+        }
+
+        private void SetSortOrder(int column)
+        {
+            ActiveFileComparer comparer = GetComparer(column, Preferences.RecentFilesSortColumn == column ? Preferences.RecentFilesAscending : false);
+            Preferences.RecentFilesAscending = !comparer.ReverseSort;
+            Preferences.RecentFilesSortColumn = column;
+            _mainViewModel.RecentFilesComparer = comparer;
+        }
+
+        private static ActiveFileComparer GetComparer(int column, bool reverseSort)
+        {
+            ActiveFileComparer comparer;
+            switch (column)
+            {
+                case 0:
+                    comparer = ActiveFileComparer.DecryptedNameComparer;
+                    break;
+
+                case 1:
+                    comparer = ActiveFileComparer.DateComparer;
+                    break;
+
+                case 2:
+                    comparer = ActiveFileComparer.EncryptedNameComparer;
+                    break;
+
+                case 3:
+                    comparer = ActiveFileComparer.CryptoNameComparer;
+                    break;
+
+                default:
+                    throw new ArgumentException("column is wrong.");
+            }
+            comparer.ReverseSort = reverseSort;
+            return comparer;
+        }
+
+        private static ActiveFileComparer ChooseComparer(ActiveFileComparer current, ActiveFileComparer comparer)
+        {
+            if (current != null && current.GetType() == comparer.GetType())
+            {
+                comparer.ReverseSort = !current.ReverseSort;
+            }
+            return comparer;
+        }
+
+        private void CloseOpenFilesToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            EncryptPendingFiles();
+        }
+
+        private void CloseAndRemoveOpenFilesToolStripButton_Click(object sender, EventArgs e)
+        {
+            EncryptPendingFiles();
+        }
+
+        private void ProgressBackgroundWorker_ProgressBarClicked(object sender, MouseEventArgs e)
+        {
+            if (e.Button != MouseButtons.Right)
+            {
+                return;
+            }
+            _progressContextMenuStrip.Tag = sender;
+            _progressContextMenuStrip.Show((Control)sender, e.Location);
+        }
+
+        private void ProgressBackgroundWorker_ProgressBarCreated(object sender, ControlEventArgs e)
+        {
+            _progressTableLayoutPanel.Controls.Add(e.Control);
+        }
+
+        private void ProgressContextCancelToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ToolStripMenuItem menuItem = (ToolStripMenuItem)sender;
+            ContextMenuStrip menuStrip = (ContextMenuStrip)menuItem.GetCurrentParent();
+            ProgressBar progressBar = (ProgressBar)menuStrip.Tag;
+            IProgressContext progress = (IProgressContext)progressBar.Tag;
+            progress.Cancel = true;
+        }
+
+        private void EnglishLanguageToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            SetLanguage("en-US");
+        }
+
+        private void SwedishLanguageToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            SetLanguage("sv-SE");
+        }
+
+        private static void SetLanguage(string cultureName)
+        {
+            Instance.UserSettings.CultureName = cultureName;
+            if (Instance.Log.IsInfoEnabled)
+            {
+                Instance.Log.LogInfo("Set new UI language culture to '{0}'.".InvariantFormat(Instance.UserSettings.CultureName));
+            }
+            Resources.LanguageChangeRestartPrompt.ShowWarning();
+            Application.Exit();
+        }
+
+        private void LanguageToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
+        {
+            ToolStripMenuItem languageMenu = (ToolStripMenuItem)sender;
+            CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture;
+            if (!currentUICulture.IsNeutralCulture)
+            {
+                currentUICulture = currentUICulture.Parent;
+            }
+            string currentLanguage = currentUICulture.Name;
+            foreach (ToolStripItem item in languageMenu.DropDownItems)
+            {
+                string languageName = item.Tag as string;
+                if (String.IsNullOrEmpty(languageName))
+                {
+                    continue;
+                }
+                if (languageName == currentLanguage)
+                {
+                    ((ToolStripMenuItem)item).Checked = true;
+                    break;
+                }
+            }
+        }
+
+        private void UpdateToolStripButton_Click(object sender, EventArgs e)
+        {
+            Instance.UserSettings.LastUpdateCheckUtc = OS.Current.UtcNow;
+            Process.Start(Instance.UserSettings.UpdateUrl.ToString());
+        }
+
+        private void SetUpdateCheckUrlToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            using (DebugOptionsDialog dialog = new DebugOptionsDialog())
+            {
+                dialog.UpdateCheckServiceUrl.Text = Instance.UserSettings.AxCrypt2VersionCheckUrl.ToString();
+                DialogResult result = dialog.ShowDialog();
+                if (result != DialogResult.OK)
+                {
+                    return;
+                }
+                Instance.UserSettings.AxCrypt2VersionCheckUrl = new Uri(dialog.UpdateCheckServiceUrl.Text);
+            }
+        }
+
+        private void AboutToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            using (AboutBox aboutBox = new AboutBox())
+            {
+                aboutBox.ShowDialog();
+            }
+        }
+
+        private void HelpToolStripButton_Click(object sender, EventArgs e)
+        {
+            Process.Start(Instance.UserSettings.AxCrypt2HelpUrl.ToString());
+        }
+
+        private void ViewHelpMenuItem_Click(object sender, EventArgs e)
+        {
+            Process.Start(Instance.UserSettings.AxCrypt2HelpUrl.ToString());
+        }
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                DisposeInternal();
+            }
+            base.Dispose(disposing);
+        }
+
+        private void DisposeInternal()
+        {
+            if (components != null)
+            {
+                components.Dispose();
+            }
+            if (_mainViewModel != null)
+            {
+                _mainViewModel.Dispose();
+                _mainViewModel = null;
+            }
+        }
+
+        private void ClearPassphraseMemoryToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ClearAllSettingsAndReinitialize();
+            Application.Exit();
+        }
+
+        private static void ClearAllSettingsAndReinitialize()
+        {
+            Instance.UserSettings.Delete();
+            Instance.FileSystemState.Delete();
+            Instance.UserSettings.SettingsVersion = Instance.UserSettings.CurrentSettingsVersion;
+        }
+
+        private void PolicyMenuItem_Click(object sender, EventArgs e)
+        {
+            ToolStripMenuItem item = sender as ToolStripMenuItem;
+            SetCheckedToolStripMenuItem(item);
+            Factory.Instance.Singleton<ICryptoPolicy>(() => Factory.Instance.Singleton<CryptoPolicy>().Create(item.Text));
+        }
+
+        private static void SetCheckedToolStripMenuItem(ToolStripMenuItem item)
+        {
+            foreach (ToolStripItem tsi in item.GetCurrentParent().Items)
+            {
+                ((ToolStripMenuItem)tsi).Checked = false;
+            }
+            item.Checked = true;
+        }
+
+        private void CryptoPolicyToolStripMenuItem_DropDownOpening(object sender, EventArgs e)
+        {
+        }
+
+        private void loggingToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ToolStripMenuItem item = sender as ToolStripMenuItem;
+            item.Checked = !item.Checked;
+            if (_debugOutput == null)
+            {
+                _debugOutput = new DebugLogOutputDialog();
+            }
+            _debugOutput.Visible = item.Checked;
+        }
+
+        private void encryptedFoldersToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            ShowWatchedFolders(new string[0]);
+        }
+
+        private void ShowWatchedFolders(IEnumerable<string> additional)
+        {
+            using (WatchedFoldersDialog dialog = new WatchedFoldersDialog(this, additional))
+            {
+                dialog.ShowDialog();
+            }
+        }
+
+        private void createAccountToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            using (CreateNewAccountDialog dialog = new CreateNewAccountDialog(this, String.Empty))
+            {
+                dialog.ShowDialog();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AxCryptMainForm.resx b/Axantum.AxCrypt/AxCryptMainForm.resx
new file mode 100644
index 0000000..58e3a07
--- /dev/null
+++ b/Axantum.AxCrypt/AxCryptMainForm.resx
@@ -0,0 +1,1501 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_mainToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_mainToolStrip.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="_encryptionKeyToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_encryptionKeyToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_toolStripSeparator7.Size" type="System.Drawing.Size, System.Drawing">
+    <value>6, 50</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAOvSURBVFhHvZZJTxRRFIX5N3ZNP6D7l4Du/AeuABUVZ2Vo
+        UEBBZFJAEBxwlkUnhSZuTLtuFkYlunBg1UjEcD236t2q16+rqukYOMm3IaHPOe/eelUt7qpb9F55paZ5
+        CZ4ZPPVK7mM35hFYViyBBY17bsmet4stwY+tepTJa8Ur8FLxAjwHz8BTxROP3BWXYE4wJ/cBWAZL4D5Y
+        BAtg3iVnziFr1iplB9CNxZyNTXPT+CHQzcX4HlDmzl0EmM4KsE+tndnQ3JlJC7DPrZ07obkzjQC3zQB7
+        aQ3jGnPTuEFrNnamwKQeIKP1h80PtFdVd6rU8a4jvbUydibAbQQY1QOktG5Wu7u71FvuTW3Nxs44uKUH
+        yJi16Ih/uOGsj705Rls7W0GInvc9ia3Z2B6zyR61yRrmAHyhpM16JQ6w11kfXT1K23+3gxDtfntsrFqz
+        sX0T3JAAfIOxsWEuSybK3HA5bjXrrrddwf9U/1RjY9Waje0RMIwAgxLAaK0/WqJmN1zkjNW2ZmN7CFzX
+        Axit9VmLxHjt6xptbm/W4G/4tbNGa1FkrFqzsX0NDCJAHwLAsGS21o9bJK3XN9fVX2JVflVqZ43jFpmt
+        2dgeAEUtQKK5Om6RzNqb9aiwWKDCApgHcwXyJr3aWaO1yGzNxna/xeZk9XIAfmWmbTiWTJQ4a6N1NGsc
+        tyihNRuT1QOucAB+Vxut9Q0XyYavbagd+F2P/8kPZ43jFklrK25N1tXAnKzLEsBorW+4SFrzvNNU+VGJ
+        Zi2qay3ml8AFDsBfJ0Zr/bkWyYZ7E9iBGcx+GkwVKD+Zp/wEGM+TO+RGsxYltA7NL4IogNFaf2WK0mYd
+        bbgsmZq1qK51aEzWeYty3blSC38Wma0Dc/NCURvuf/ZrZ78V43/0o1mLElqTdQ6c1QKYrfUNF0nrys+M
+        HfheiWYtMltr5pQ7wwHuIgCba9eo3GbcWiS3mTviUv4WZj4GRsENMAKG8+T04RWrjlsUmNcbU+406OIA
+        +C5Leq7l5SFqW2pLnHXdhuO4W2da1X8hQJr5KQkwhQBGa7nNuPX/qs44NqfcSQ6A7zKztb7h5W9l9VPN
+        q/ylnNSajUM6OcA4Ahit5TaL7nA5brnN9EdL3/Cs49bNTyiCAPgua/hc9yfPOnnD8cNZrdn4uCIIcBMB
+        Dqp1bCwgAL7LDri1EWAIAZppnXyhNNNap9QC4yJ/m1kDAF8oAfhQgGkIXpkwjTkPuq0SjENwm8EwBo9W
+        AH68EYc6DxX/AZAD8t0ezXpaAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Click to select encrypted documents to open</value>
+  </data>
+  <data name="_encryptToolStripButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_encryptToolStripButton.ImageScaling" type="System.Windows.Forms.ToolStripItemImageScaling, System.Windows.Forms">
+    <value>None</value>
+  </data>
+  <data name="_encryptToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_encryptToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Click to select documents to encrypt</value>
+  </data>
+  <data name="_decryptToolStripButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_decryptToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
+        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAR1SURBVFhHvZbbTxRnGMb5b9yZ2Y2RC40HBi+MxES48A9Q
+        403hQq+88YBUaukByqIc5NgFCizLHlhQykGasSZNGktsbGJJs0STBhLSBsxCW1Kq+/Z5d75v59thdoFY
+        +yW/CwaY3/PMfIcp8T/yBwOzAWvfzIApFw8Dln/C75AEcUEMRBRG/ZYe1oMl2Zs9ClBR5gSzYEYwDb4G
+        U+Ch4EGA/JN+gpwgJ38CxEEMRMEYiICwn4wRg7RhzSoeQBVLOYvdcrd4HKhyKR4FQm4MIcBAsQDvqbUx
+        bMuNwUIB3nNr4ytbbgwgQJ87wF5aQ1wxX0G1P9ZS62IrBV8E6fL3l+nwxOE9tWax0Q9CaoA9tj7zzRmy
+        Vi3KZDLkHpvbm9TxooMORQ8Vbi3ExpegDwG61AC7tL7w3QXa2N4QusLj2W/P6Ej0SMHWLDZ6QY8aYJd3
+        zY88vZ0WCso+gYXfF2g4NUyJlwla+WNF/MYej5cfF2zNYr1bJ71LJ62dA/CGUqB1YNKeaHMrc+LW9qO+
+        9O2lvHd9MHKQQj+HxF/Y44p1xZZLsWjNYr0T3JcBeAdjsUsuZ/jJmZP0JvNG3JaobqFu5wwXj3v+13na
+        +HuD1rfWqed5jy2XYtGaxXoHaEeAuzKAu7WytK4+vSrURFv/bFFprHT3Ga627s5vzWK9DbSqAVyt1XXd
+        +FOj0BMtpZd2tPZ812prKRatWazfA3cR4AsEgNByt1Y3lKbnTUJPtLi+uMfWEBRozWK9BQSVAJ5yTLLT
+        U6ep/5d+oSd6lX5FVQ+qqGoSTIAkGAcJEAcxEK2iyrFKqhwF4Uo6NXgqrzWL9WaN5aQ1cQA+Mt3bKOTH
+        k8c9N5z9Dr7H0a6jamsWk9YIPuMAfFYrreUML0+Wi1u8+zC7TdKc1qR9npWT9qkMoO7hYpKVJ/7DAJ0I
+        IFtL+SfgYw7AXyce69qMm+LfvUdqLUVnI2ez73ppfUlc9R7mfQRwWtvyBjWAenjwDMfSMqPFA9Q/qc8t
+        rYYnDeKq9zDbEUC2tsWk3dHId9tnlfBnkde6NiPFA0ynpnNLazY1K656D7MNAVT5R6BeCSBbq+vaDBcP
+        wKNioILOjZwTPxUe5j0EEK0VOfk+5ABDCMBy9cjEpmKOFA/wNvOWSttLqayrTFwpPMwWBMgXk68O1HIA
+        fJd57WbmUPEAy+nl3Lp+/ddrcdV7mEEEcMtvyQD9COCxh5uDxQOsbq5S3w991Pu0l9b+XBNXvUdZc5kj
+        duTku8kB8F0mW+eOTOzhJ0InxL+/+zjWeMwttrnGAXoRwOvkwgy/mLhINZM1VDMBkmC8hqoT1VQdF8RA
+        FIyBiGAUhMEI8wGdD523xar8hiAbAN9luZNLHpm8vOThwXt4s2sP500lf0NRZjhuvPNdO61ZfF2QDdCJ
+        AErr3MklDw+5h6vbqCrfubQcsbu1I5YgAL7L/ufWrgBtCLCf1t4byn5aq1glEAf520xrAfhCyYIPBUht
+        cGRC6nAH3NYsiG2wm0HogKWVBTffjQPXDgT/BWCVpIV9t7BJAAAAAElFTkSuQmCC
+</value>
+  </data>
+  <data name="_decryptToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_decryptToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_decryptToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Click to select documents to decrypt</value>
+  </data>
+  <data name="_toolStripSeparator1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>6, 50</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.Enabled" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Click to clean and remove any open decrypted files, but ensure they are not in use first.</value>
+  </data>
+  <data name="_toolStripSeparator4.Size" type="System.Drawing.Size, System.Drawing">
+    <value>6, 50</value>
+  </data>
+  <data name="_updateToolStripButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_updateToolStripButton.Enabled" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_updateToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_updateToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_knownFoldersSeparator.Size" type="System.Drawing.Size, System.Drawing">
+    <value>6, 50</value>
+  </data>
+  <data name="_knownFoldersSeparator.Visible" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="_toolStripSeparator8.Size" type="System.Drawing.Size, System.Drawing">
+    <value>6, 50</value>
+  </data>
+  <data name="_helpToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_helpToolStripButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>36, 47</value>
+  </data>
+  <data name="_mainToolStrip.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 24</value>
+  </data>
+  <data name="_mainToolStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>824, 50</value>
+  </data>
+  <data name="_mainToolStrip.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name=">>_mainToolStrip.Name" xml:space="preserve">
+    <value>_mainToolStrip</value>
+  </data>
+  <data name=">>_mainToolStrip.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_mainToolStrip.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_mainToolStrip.ZOrder" xml:space="preserve">
+    <value>5</value>
+  </data>
+  <metadata name="_mainMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>150, 17</value>
+  </metadata>
+  <data name="_openEncryptedToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAghJREFUOE9t
+        kslTE0EUh/lzprtnSE0KihPF3+W+4RoLkE2RJYqABmRTNvGYq1VeuHdVuHpQ54BK9Pm97iQm6qv6TtPv
+        9/V7PX3Z+6wOvsNxiyM4hH3Yy3z6JvXpDmzCBtRS79ZcXQO0UQLH8A6O4AD2M0nfppLuwja8hvVU3Csn
+        bhVeOB8DtLHdfBgbsQpWwSrpFmxAjeaXNK7Ac6hqgF63y1qcF/J3NX81pfKx0raKewZLTuy8JSDO2rFq
+        De0N9ViHt4bl5NOJVD4QUqV5geanVuxjDTggoGtWrf/MKiO1EWn+bKpV7BOYhSkCaNQNx1k3WwFYT4tT
+        OTs/k8bXRstqwzesYqdh0ooZNwTsEtC1YS21llZLUl4pS6la6li1sIqdoHnMiKloQHzXuOE1Fw7phtWs
+        Nwi3+NIIVi2sYh7CA7inAev8EO1Zl1sBi9xgkRsslCWfy6V/pj9YtbCKuQ93jSSjie/D6rveNRyyczZY
+        ww1+cIPPjWDVwirmNtwi4IYGLBOg74pVZ9UanB8M1nw6l3wyl2wsk4HxgfDNjNJ4M5HkOlzVgCXnLRtW
+        q264+P7vj9Su4luhVkmuwRW4TAA/hA/vOgO9G46z3oFea2y+BBc1YJYAfddH4V3/bJglxVk52GvVRkku
+        BAiYsnUzYTxWr++K1WP1WD1Wj9XrrDR7rF6t2hhJ6r8Bi9c8pZqh570AAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="_openEncryptedToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_openEncryptedToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Open Encrypted</value>
+  </data>
+  <data name="_encryptToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAlxJREFUOE99
+        kktPU1EUhfk591UmhDAhDBi1PwBCmDMgzJpAovWFYrUqFi2tgHBaX0UQQawULCTGtE2DYeADtYwOMAAT
+        STtQUw2py3XuvS3WgSf5Bic569t3732bPOueLJF1Mi5rZJWskBceaT23pPWMPCVPyJwlzaSZVQIVhE2G
+        vCRrJE1WPLBSFqxlskQWyLwF87EJ8xF5YEpHoIK18KoTbEm3oDfbi65XXWheagarglVhzjL4kNwjcSVQ
+        n/tPVf+WH6VfJdTO3rc99GR6alVhJogwYdw1KHB6tYPsFd2vu3FcPcZ2aRv+gh+BzQAOvh+g/LOM9rl2
+        VRXmNMNTBow7SpCm4K9eF+QCqr+r6Ex11nvt2+izvyRYCKqqMCZIjEQoYFBNGJwwOGHkv+RxVDkCJ1zv
+        tWO2wxYk3iVUVRjj5LYBPaxTsEyBO+GB3AAOfxyiclxBcieJZJF8SmJxZ9EWFL8W0Z/qhzHG8E0d+nUl
+        cPZqTzj+OW4//N8RWwL6DYavkatKMM8fwu1VfBTuM+cMbgxiaH3IvTlHvKEgxPAVHdqIJpvYq6z1Kj40
+        CkK5EEbzo+7NOWKTgssUXKJgWAnuU6D2OkPB+0ZBOBdGtBB1b84RBQHtogbtAjmnBMKUxjSnOmlAvG0U
+        7JZ3sV/ed2/OmcnPQDvP8FlyhgL+ENLea9RA22QbfAkffMIH77QX3ikyQWJknES8aA22OuEAOa0EMQrU
+        Xm/Zez2ZMIfk9MqHw+SkqgpCO2VDQcTI6mO65F6l2isnLPUgGdEle5XsVapeGZasKlVVFXTQsn8A1Gtv
+        qsw7YvUAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="_encryptToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_encryptToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Encrypt</value>
+  </data>
+  <data name="_decryptToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAlFJREFUOE91
+        kktPU1EUhfk591UmhDBgxoR2xAhC+AeEWRNItL5QRKvWoqUVkJ7iq0qtQagULCbGtE2D6cBI8TE6pJM6
+        IO1ATTVNXa5z7y0PE3fyDU5y17e7926XZ8eTJ/KInMs22SKb5JVHWhuWtF6SF+Q5WbWkmTTzSqCCsMmR
+        12SbZMmmB1bGgrVO1kiapCyYz0yYT8gjUzoCFeyEt5xgT7YHY/kxDL8dRvdaN9gV7ArzKYOPyQOSUAL1
+        c//p6i/7Uf9dR6eq36sYzY12usJcIcKEcd+gwJnVDnJWjLwbQavdQqVegb/kR2A3gNqPGhq/Guhf7Vdd
+        YS4zvGTAuKcEWQpOzJqWabT/tDGQGTiadWhjCKFyCIOpQdUVxgKJkQgFDKoNgxsGN4zityIOm4fghk/O
+        yq4MLNpdYcyTuwb0sE7BOgXuhicKE6j9rKHZaiL5NYnkF/KJ7JMK2UtiPDMOY47h2zr0m0rg3NXecOJz
+        wl3b/0uUBfRbDN8g15UgxT+EO6vYF+5nTk2+mcTUzpT7ckq8pyDI8DUd2owmuzir7Mwq9k4LgoUgQsWQ
+        +3JK7FJwlYIrFEwrwUMK1F3jFHw8LQgXwoiWou7LKVES0C5r0C6RC0ogTGm4GxYfTgsOGgeoNqruy6l4
+        MQ7tIsPnyTkK+IeQ9l2jBvoW++Bb8cEnfPAue+FdIgskRuZJxIve2V4nHCBnlSBGgbrrHfuuxxvmkpxZ
+        +eE0Oe6qgtDO2FAQMfL6nC55V6nuyg1LfZbM6JKzSs4q1awMS3aVqqsKOmj5v9iLaPnp2/2xAAAAAElF
+        TkSuQmCC
+</value>
+  </data>
+  <data name="_decryptToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_decryptToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Decrypt</value>
+  </data>
+  <data name="encryptedFoldersToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="encryptedFoldersToolStripMenuItem.Text" xml:space="preserve">
+    <value>Encrypted &Folders</value>
+  </data>
+  <data name="_toolStripSeparator6.Size" type="System.Drawing.Size, System.Drawing">
+    <value>165, 6</value>
+  </data>
+  <data name="_closeOpenFilesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAohJREFUOE9d
+        kstPE1EYxflzZu7MlJISuiBdEHaE7ljAjiV7Vr5foCI+QEZsa3kIyFu0tdDyMJI0JLrBIEpsXFyJCZFY
+        SIOACCbHc+9Qrd7kl3ndc85833fLnEUnS+QfFk7JkDSZJSlH2klb2s/JUzJFJmxpjVpZZaCE0CyQeZIh
+        c2TWgf3Chp0gz8g0mbRhjVuwnpBhS3oGSlgUpz1h3as65I/yGt+MD0wFU2GNUThCHpMBZaB+97/Uljct
+        CL8Mo7jKp8rRutJaTIU1SPotiEeCBl6tWuhL+TC9OY2DkwOEF0oMxsv1NS3T8A36YMUpjgmIh8pgjgan
+        tXa+79QbN3Y3EM78NXBGHKx/W9f3kdUIRITiXtJDAwpVh+FP+LF7tKvTa5O1CM+WGAw6CI2EsPdzD/vH
+        +whEAxD3Bcx7Jg0SNGCHG5Ya9OalL0u61vpEvX5Wy4k7OjWZS+rnpokmmHdNmJ3KwJsrGhcb9cfM54zu
+        cPVoNWJvY4iuRlWtEK7A2Lsxvad5shnmLRrcVAaTPBCca+VEJQ5PDlE4KqBqqEp12Kv1ga4VftePrb0t
+        HP86RrA7CPOGCaPNkGU8TbI41+EPwzpheXMZVX00YaroFgi4AWRyGf1tZm0GZjvTr9HgijIYooGaax//
+        YqASa1/X9MbCjwLmP80j9TGFnYMd/S63nUPwThDGVQPGZXJRGfRbUsSZFCWstSJSAfe1i+3v21qkVn4/
+        j9hKDIGOgEqFcYlcIOdpwAMhS2sVXRyP12GE3BBq3BqIdlGa6onPkbPKoJcGp7VyrjBvE9VhNsmrlRv/
+        TVVCGGc0NOgRWbPLlEyVaq5mB7lO2kzJVMlUqWqlWDJVqlQl9DCyvwHO+VecZoqTtAAAAABJRU5ErkJg
+        gg==
+</value>
+  </data>
+  <data name="_closeOpenFilesToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_closeOpenFilesToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Clean Decrypted</value>
+  </data>
+  <data name="_toolStripSeparator3.Size" type="System.Drawing.Size, System.Drawing">
+    <value>165, 6</value>
+  </data>
+  <data name="_wipeToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_wipeToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Secure Delete</value>
+  </data>
+  <data name="_toolStripSeparator2.Size" type="System.Drawing.Size, System.Drawing">
+    <value>165, 6</value>
+  </data>
+  <data name="_englishLanguageToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>116, 22</value>
+  </data>
+  <data name="_englishLanguageToolStripMenuItem.Text" xml:space="preserve">
+    <value>&English</value>
+  </data>
+  <data name="_swedishLanguageToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>116, 22</value>
+  </data>
+  <data name="_swedishLanguageToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Svenska</value>
+  </data>
+  <data name="_languageToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>207, 22</value>
+  </data>
+  <data name="_languageToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Language</value>
+  </data>
+  <data name="_debugOptionsToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>207, 22</value>
+  </data>
+  <data name="_debugOptionsToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Debug</value>
+  </data>
+  <data name="_clearPassphraseMemoryToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>207, 22</value>
+  </data>
+  <data name="_clearPassphraseMemoryToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Clear All Settings and Exit</value>
+  </data>
+  <data name="_optionsToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAoNJREFUOE9t
+        kllPU1EUhfk599wBShsSEtI/wCshbXjjN0BS6jygojhUULQUCyKVSavIVAEjofHNEBJNVAw54Yk0oEDT
+        Btoiy3XOvTgknORLbm72WuvsvU+Vs+hkifzDgkeGzJNZMuNI+40t7dfkJZkk47a0nltZZaCE0CyQtyRD
+        5sisA3vahj1FXpEXZMKGNWbBSpFnlnQNlPBEPO8KmYrwShih5RDsNIWTZJziUQpHyFMyqAzUdf9J9c35
+        UD9fr1M3C5vYK+3p1IZ0A/xjfpUKa4gkLZgJkwZurzq1ZqYGaz/XsHO4g/jXOI6Pj6HO4JdB5Et5rOZW
+        4Qw5sAYo7jdhPlIGczTweg1MB7B9sK1Fp53dg134k36YjynuI700oFBNGJwwOGH0fO7RxbliDtEPUUSz
+        Uf2tzsinEVTHq2E+oLjHhLgnaDBFA064aakJxUpRF6rTttLm9vrEQuR9xPsLFMtFNI82Q9wVEN3KwN0r
+        wothlI5KXhnQvtzOXpkUN9HxrsP7C5QqJbROtELcokGXMpjgg/D26kv5kP6e1oVbhS20L7UhshRBruC2
+        kPmWgXPHgbhJ8Q0Bo9OQVXxN8mSvwdEgCuWCLj7tVI4qaOxvhLhGg6s0uKwMhmng9VqbrMX6j3XsH+4j
+        8THhyYDUagr5wzw2djZQ110H44oB4xK5oAySljS9XrlXBOIBBBNBODEb5aMyKr8qMLtMNMT4kLr8KhXG
+        RXKenKMBH4TUe31IekmM63EnjNBwCC3DLRCdvO7fVFd8lpxRBn00UHu9r/cKcZuoCXNIbq8s/D9VCWFE
+        NTToNbMiJiRTpdorJyzFddIpJFMlU6XqlWLJVKlSldDFyP4GDMhi3CpAsUkAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="_optionsToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_optionsToolStripMenuItem.Text" xml:space="preserve">
+    <value>O&ptions</value>
+  </data>
+  <data name="_exitToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>168, 22</value>
+  </data>
+  <data name="_exitToolStripMenuItem.Text" xml:space="preserve">
+    <value>E&xit</value>
+  </data>
+  <data name="_fileToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>37, 20</value>
+  </data>
+  <data name="_fileToolStripMenuItem.Text" xml:space="preserve">
+    <value>&File</value>
+  </data>
+  <data name="_checkVersionNowToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>177, 22</value>
+  </data>
+  <data name="_checkVersionNowToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Check Version Now</value>
+  </data>
+  <data name="_setUpdateCheckUrlToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>177, 22</value>
+  </data>
+  <data name="_setUpdateCheckUrlToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Options</value>
+  </data>
+  <data name="cryptoPolicyToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>177, 22</value>
+  </data>
+  <data name="cryptoPolicyToolStripMenuItem.Text" xml:space="preserve">
+    <value>Crypto &Policy</value>
+  </data>
+  <data name="loggingToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>177, 22</value>
+  </data>
+  <data name="loggingToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Logging</value>
+  </data>
+  <data name="createAccountToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>177, 22</value>
+  </data>
+  <data name="createAccountToolStripMenuItem.Text" xml:space="preserve">
+    <value>Create &Account</value>
+  </data>
+  <data name="_debugToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>54, 20</value>
+  </data>
+  <data name="_debugToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Debug</value>
+  </data>
+  <data name="_viewHelpMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>127, 22</value>
+  </data>
+  <data name="_viewHelpMenuItem.Text" xml:space="preserve">
+    <value>&View Help</value>
+  </data>
+  <data name="_aboutToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>127, 22</value>
+  </data>
+  <data name="_aboutToolStripMenuItem.Text" xml:space="preserve">
+    <value>&About</value>
+  </data>
+  <data name="_helpToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>44, 20</value>
+  </data>
+  <data name="_helpToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Help</value>
+  </data>
+  <data name="_mainMenuStrip.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 0</value>
+  </data>
+  <data name="_mainMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>824, 24</value>
+  </data>
+  <data name="_mainMenuStrip.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name=">>_mainMenuStrip.Name" xml:space="preserve">
+    <value>_mainMenuStrip</value>
+  </data>
+  <data name=">>_mainMenuStrip.Type" xml:space="preserve">
+    <value>System.Windows.Forms.MenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_mainMenuStrip.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_mainMenuStrip.ZOrder" xml:space="preserve">
+    <value>6</value>
+  </data>
+  <data name="_progressTableLayoutPanel.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
+    <value>Bottom, Left, Right</value>
+  </data>
+  <data name="_progressTableLayoutPanel.ColumnCount" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name="_progressTableLayoutPanel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 262</value>
+  </data>
+  <data name="_progressTableLayoutPanel.RowCount" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name="_progressTableLayoutPanel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>824, 20</value>
+  </data>
+  <data name="_progressTableLayoutPanel.TabIndex" type="System.Int32, mscorlib">
+    <value>3</value>
+  </data>
+  <data name=">>_progressTableLayoutPanel.Name" xml:space="preserve">
+    <value>_progressTableLayoutPanel</value>
+  </data>
+  <data name=">>_progressTableLayoutPanel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TableLayoutPanel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_progressTableLayoutPanel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_progressTableLayoutPanel.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+  <data name="_progressTableLayoutPanel.LayoutSettings" type="System.Windows.Forms.TableLayoutSettings, System.Windows.Forms">
+    <value><?xml version="1.0" encoding="utf-16"?><TableLayoutSettings><Controls /><Columns Styles="Percent,50,Percent,50" /><Rows Styles="Percent,50,Percent,50" /></TableLayoutSettings></value>
+  </data>
+  <metadata name="_recentFilesContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>290, 17</value>
+  </metadata>
+  <data name="_removeRecentFileToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>326, 22</value>
+  </data>
+  <data name="_removeRecentFileToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Remove from list without decrypting document</value>
+  </data>
+  <data name="_decryptAndRemoveFromListToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>326, 22</value>
+  </data>
+  <data name="_decryptAndRemoveFromListToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Decrypt and remove from list</value>
+  </data>
+  <data name="_recentFilesContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>327, 48</value>
+  </data>
+  <data name=">>_recentFilesContextMenuStrip.Name" xml:space="preserve">
+    <value>_recentFilesContextMenuStrip</value>
+  </data>
+  <data name=">>_recentFilesContextMenuStrip.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <metadata name="_progressContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>712, 17</value>
+  </metadata>
+  <data name="_progressContextCancelToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>110, 22</value>
+  </data>
+  <data name="_progressContextCancelToolStripMenuItem.Text" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name="_progressContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>111, 26</value>
+  </data>
+  <data name=">>_progressContextMenuStrip.Name" xml:space="preserve">
+    <value>_progressContextMenuStrip</value>
+  </data>
+  <data name=">>_progressContextMenuStrip.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <metadata name="_watchedFoldersContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>915, 17</value>
+  </metadata>
+  <data name="_watchedFoldersRemoveMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>185, 22</value>
+  </data>
+  <data name="_watchedFoldersRemoveMenuItem.Text" xml:space="preserve">
+    <value>&Decrypt Permanently</value>
+  </data>
+  <data name="_watchedFoldersdecryptTemporarilyMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>185, 22</value>
+  </data>
+  <data name="_watchedFoldersdecryptTemporarilyMenuItem.Text" xml:space="preserve">
+    <value>Decrypt &Temporarily</value>
+  </data>
+  <data name="_watchedFoldersOpenExplorerHereMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>185, 22</value>
+  </data>
+  <data name="_watchedFoldersOpenExplorerHereMenuItem.Text" xml:space="preserve">
+    <value>Open &Explorer Here</value>
+  </data>
+  <data name="_watchedFoldersContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>186, 70</value>
+  </data>
+  <data name=">>_watchedFoldersContextMenuStrip.Name" xml:space="preserve">
+    <value>_watchedFoldersContextMenuStrip</value>
+  </data>
+  <data name=">>_watchedFoldersContextMenuStrip.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ContextMenuStrip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name="_watchedFolderColumnHeader.Text" xml:space="preserve">
+    <value>Folder</value>
+  </data>
+  <data name="_watchedFolderColumnHeader.Width" type="System.Int32, mscorlib">
+    <value>368</value>
+  </data>
+  <data name="_watchedFoldersListView.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Fill</value>
+  </data>
+  <data name="_watchedFoldersListView.Location" type="System.Drawing.Point, System.Drawing">
+    <value>3, 3</value>
+  </data>
+  <data name="_watchedFoldersListView.Size" type="System.Drawing.Size, System.Drawing">
+    <value>810, 154</value>
+  </data>
+  <data name="_watchedFoldersListView.TabIndex" type="System.Int32, mscorlib">
+    <value>2</value>
+  </data>
+  <data name=">>_watchedFoldersListView.Name" xml:space="preserve">
+    <value>_watchedFoldersListView</value>
+  </data>
+  <data name=">>_watchedFoldersListView.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFoldersListView.Parent" xml:space="preserve">
+    <value>_watchedFoldersTabPage</value>
+  </data>
+  <data name=">>_watchedFoldersListView.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_watchedFoldersTabPage.Location" type="System.Drawing.Point, System.Drawing">
+    <value>4, 22</value>
+  </data>
+  <data name="_watchedFoldersTabPage.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>3, 3, 3, 3</value>
+  </data>
+  <data name="_watchedFoldersTabPage.Size" type="System.Drawing.Size, System.Drawing">
+    <value>816, 160</value>
+  </data>
+  <data name="_watchedFoldersTabPage.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name="_watchedFoldersTabPage.Text" xml:space="preserve">
+    <value>Encrypted Folders</value>
+  </data>
+  <data name=">>_watchedFoldersTabPage.Name" xml:space="preserve">
+    <value>_watchedFoldersTabPage</value>
+  </data>
+  <data name=">>_watchedFoldersTabPage.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFoldersTabPage.Parent" xml:space="preserve">
+    <value>_statusTabControl</value>
+  </data>
+  <data name=">>_watchedFoldersTabPage.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="_decryptedFileColumnHeader.Text" xml:space="preserve">
+    <value>Document</value>
+  </data>
+  <data name="_decryptedFileColumnHeader.Width" type="System.Int32, mscorlib">
+    <value>159</value>
+  </data>
+  <data name="_lastAccessTimeColumnHeader.Text" xml:space="preserve">
+    <value>Time</value>
+  </data>
+  <data name="_lastAccessTimeColumnHeader.Width" type="System.Int32, mscorlib">
+    <value>180</value>
+  </data>
+  <data name="_encryptedPathColumnHeader.Text" xml:space="preserve">
+    <value>Encrypted</value>
+  </data>
+  <data name="_encryptedPathColumnHeader.Width" type="System.Int32, mscorlib">
+    <value>169</value>
+  </data>
+  <data name="_cryptoName.Text" xml:space="preserve">
+    <value>Algorithm</value>
+  </data>
+  <data name="_recentFilesListView.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Fill</value>
+  </data>
+  <data name="_recentFilesListView.Location" type="System.Drawing.Point, System.Drawing">
+    <value>3, 3</value>
+  </data>
+  <data name="_recentFilesListView.Size" type="System.Drawing.Size, System.Drawing">
+    <value>810, 154</value>
+  </data>
+  <data name="_recentFilesListView.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name=">>_recentFilesListView.Name" xml:space="preserve">
+    <value>_recentFilesListView</value>
+  </data>
+  <data name=">>_recentFilesListView.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ListView, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_recentFilesListView.Parent" xml:space="preserve">
+    <value>_recentFilesTabPage</value>
+  </data>
+  <data name=">>_recentFilesListView.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_recentFilesTabPage.Location" type="System.Drawing.Point, System.Drawing">
+    <value>4, 22</value>
+  </data>
+  <data name="_recentFilesTabPage.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>3, 3, 3, 3</value>
+  </data>
+  <data name="_recentFilesTabPage.Size" type="System.Drawing.Size, System.Drawing">
+    <value>816, 160</value>
+  </data>
+  <data name="_recentFilesTabPage.TabIndex" type="System.Int32, mscorlib">
+    <value>2</value>
+  </data>
+  <data name="_recentFilesTabPage.Text" xml:space="preserve">
+    <value>Recent Files</value>
+  </data>
+  <data name=">>_recentFilesTabPage.Name" xml:space="preserve">
+    <value>_recentFilesTabPage</value>
+  </data>
+  <data name=">>_recentFilesTabPage.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TabPage, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_recentFilesTabPage.Parent" xml:space="preserve">
+    <value>_statusTabControl</value>
+  </data>
+  <data name=">>_recentFilesTabPage.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_statusTabControl.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
+    <value>Top, Bottom, Left, Right</value>
+  </data>
+  <data name="_statusTabControl.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 77</value>
+  </data>
+  <data name="_statusTabControl.Size" type="System.Drawing.Size, System.Drawing">
+    <value>824, 186</value>
+  </data>
+  <data name="_statusTabControl.TabIndex" type="System.Int32, mscorlib">
+    <value>2</value>
+  </data>
+  <data name=">>_statusTabControl.Name" xml:space="preserve">
+    <value>_statusTabControl</value>
+  </data>
+  <data name=">>_statusTabControl.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TabControl, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_statusTabControl.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_statusTabControl.ZOrder" xml:space="preserve">
+    <value>4</value>
+  </data>
+  <metadata name="_progressBackgroundWorker.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>1156, 17</value>
+  </metadata>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>121</value>
+  </metadata>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>824, 279</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>AxCrypt</value>
+  </data>
+  <data name=">>_encryptionKeyToolStripButton.Name" xml:space="preserve">
+    <value>_encryptionKeyToolStripButton</value>
+  </data>
+  <data name=">>_encryptionKeyToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator7.Name" xml:space="preserve">
+    <value>_toolStripSeparator7</value>
+  </data>
+  <data name=">>_toolStripSeparator7.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_openEncryptedToolStripButton.Name" xml:space="preserve">
+    <value>_openEncryptedToolStripButton</value>
+  </data>
+  <data name=">>_openEncryptedToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_encryptToolStripButton.Name" xml:space="preserve">
+    <value>_encryptToolStripButton</value>
+  </data>
+  <data name=">>_encryptToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_decryptToolStripButton.Name" xml:space="preserve">
+    <value>_decryptToolStripButton</value>
+  </data>
+  <data name=">>_decryptToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator1.Name" xml:space="preserve">
+    <value>_toolStripSeparator1</value>
+  </data>
+  <data name=">>_toolStripSeparator1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_closeAndRemoveOpenFilesToolStripButton.Name" xml:space="preserve">
+    <value>_closeAndRemoveOpenFilesToolStripButton</value>
+  </data>
+  <data name=">>_closeAndRemoveOpenFilesToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator4.Name" xml:space="preserve">
+    <value>_toolStripSeparator4</value>
+  </data>
+  <data name=">>_toolStripSeparator4.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_updateToolStripButton.Name" xml:space="preserve">
+    <value>_updateToolStripButton</value>
+  </data>
+  <data name=">>_updateToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_knownFoldersSeparator.Name" xml:space="preserve">
+    <value>_knownFoldersSeparator</value>
+  </data>
+  <data name=">>_knownFoldersSeparator.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator8.Name" xml:space="preserve">
+    <value>_toolStripSeparator8</value>
+  </data>
+  <data name=">>_toolStripSeparator8.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_helpToolStripButton.Name" xml:space="preserve">
+    <value>_helpToolStripButton</value>
+  </data>
+  <data name=">>_helpToolStripButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripButton, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_fileToolStripMenuItem.Name" xml:space="preserve">
+    <value>_fileToolStripMenuItem</value>
+  </data>
+  <data name=">>_fileToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_openEncryptedToolStripMenuItem.Name" xml:space="preserve">
+    <value>_openEncryptedToolStripMenuItem</value>
+  </data>
+  <data name=">>_openEncryptedToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_encryptToolStripMenuItem.Name" xml:space="preserve">
+    <value>_encryptToolStripMenuItem</value>
+  </data>
+  <data name=">>_encryptToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_decryptToolStripMenuItem.Name" xml:space="preserve">
+    <value>_decryptToolStripMenuItem</value>
+  </data>
+  <data name=">>_decryptToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>encryptedFoldersToolStripMenuItem.Name" xml:space="preserve">
+    <value>encryptedFoldersToolStripMenuItem</value>
+  </data>
+  <data name=">>encryptedFoldersToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator6.Name" xml:space="preserve">
+    <value>_toolStripSeparator6</value>
+  </data>
+  <data name=">>_toolStripSeparator6.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_closeOpenFilesToolStripMenuItem.Name" xml:space="preserve">
+    <value>_closeOpenFilesToolStripMenuItem</value>
+  </data>
+  <data name=">>_closeOpenFilesToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator3.Name" xml:space="preserve">
+    <value>_toolStripSeparator3</value>
+  </data>
+  <data name=">>_toolStripSeparator3.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_wipeToolStripMenuItem.Name" xml:space="preserve">
+    <value>_wipeToolStripMenuItem</value>
+  </data>
+  <data name=">>_wipeToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_toolStripSeparator2.Name" xml:space="preserve">
+    <value>_toolStripSeparator2</value>
+  </data>
+  <data name=">>_toolStripSeparator2.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripSeparator, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_optionsToolStripMenuItem.Name" xml:space="preserve">
+    <value>_optionsToolStripMenuItem</value>
+  </data>
+  <data name=">>_optionsToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_languageToolStripMenuItem.Name" xml:space="preserve">
+    <value>_languageToolStripMenuItem</value>
+  </data>
+  <data name=">>_languageToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_englishLanguageToolStripMenuItem.Name" xml:space="preserve">
+    <value>_englishLanguageToolStripMenuItem</value>
+  </data>
+  <data name=">>_englishLanguageToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_swedishLanguageToolStripMenuItem.Name" xml:space="preserve">
+    <value>_swedishLanguageToolStripMenuItem</value>
+  </data>
+  <data name=">>_swedishLanguageToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_debugOptionsToolStripMenuItem.Name" xml:space="preserve">
+    <value>_debugOptionsToolStripMenuItem</value>
+  </data>
+  <data name=">>_debugOptionsToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_clearPassphraseMemoryToolStripMenuItem.Name" xml:space="preserve">
+    <value>_clearPassphraseMemoryToolStripMenuItem</value>
+  </data>
+  <data name=">>_clearPassphraseMemoryToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_exitToolStripMenuItem.Name" xml:space="preserve">
+    <value>_exitToolStripMenuItem</value>
+  </data>
+  <data name=">>_exitToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_debugToolStripMenuItem.Name" xml:space="preserve">
+    <value>_debugToolStripMenuItem</value>
+  </data>
+  <data name=">>_debugToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_checkVersionNowToolStripMenuItem.Name" xml:space="preserve">
+    <value>_checkVersionNowToolStripMenuItem</value>
+  </data>
+  <data name=">>_checkVersionNowToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_setUpdateCheckUrlToolStripMenuItem.Name" xml:space="preserve">
+    <value>_setUpdateCheckUrlToolStripMenuItem</value>
+  </data>
+  <data name=">>_setUpdateCheckUrlToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>cryptoPolicyToolStripMenuItem.Name" xml:space="preserve">
+    <value>cryptoPolicyToolStripMenuItem</value>
+  </data>
+  <data name=">>cryptoPolicyToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>loggingToolStripMenuItem.Name" xml:space="preserve">
+    <value>loggingToolStripMenuItem</value>
+  </data>
+  <data name=">>loggingToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_helpToolStripMenuItem.Name" xml:space="preserve">
+    <value>_helpToolStripMenuItem</value>
+  </data>
+  <data name=">>_helpToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_viewHelpMenuItem.Name" xml:space="preserve">
+    <value>_viewHelpMenuItem</value>
+  </data>
+  <data name=">>_viewHelpMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_aboutToolStripMenuItem.Name" xml:space="preserve">
+    <value>_aboutToolStripMenuItem</value>
+  </data>
+  <data name=">>_aboutToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_removeRecentFileToolStripMenuItem.Name" xml:space="preserve">
+    <value>_removeRecentFileToolStripMenuItem</value>
+  </data>
+  <data name=">>_removeRecentFileToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_decryptAndRemoveFromListToolStripMenuItem.Name" xml:space="preserve">
+    <value>_decryptAndRemoveFromListToolStripMenuItem</value>
+  </data>
+  <data name=">>_decryptAndRemoveFromListToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_progressContextCancelToolStripMenuItem.Name" xml:space="preserve">
+    <value>_progressContextCancelToolStripMenuItem</value>
+  </data>
+  <data name=">>_progressContextCancelToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFoldersRemoveMenuItem.Name" xml:space="preserve">
+    <value>_watchedFoldersRemoveMenuItem</value>
+  </data>
+  <data name=">>_watchedFoldersRemoveMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFoldersdecryptTemporarilyMenuItem.Name" xml:space="preserve">
+    <value>_watchedFoldersdecryptTemporarilyMenuItem</value>
+  </data>
+  <data name=">>_watchedFoldersdecryptTemporarilyMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFoldersOpenExplorerHereMenuItem.Name" xml:space="preserve">
+    <value>_watchedFoldersOpenExplorerHereMenuItem</value>
+  </data>
+  <data name=">>_watchedFoldersOpenExplorerHereMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_watchedFolderColumnHeader.Name" xml:space="preserve">
+    <value>_watchedFolderColumnHeader</value>
+  </data>
+  <data name=">>_watchedFolderColumnHeader.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_decryptedFileColumnHeader.Name" xml:space="preserve">
+    <value>_decryptedFileColumnHeader</value>
+  </data>
+  <data name=">>_decryptedFileColumnHeader.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_lastAccessTimeColumnHeader.Name" xml:space="preserve">
+    <value>_lastAccessTimeColumnHeader</value>
+  </data>
+  <data name=">>_lastAccessTimeColumnHeader.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_encryptedPathColumnHeader.Name" xml:space="preserve">
+    <value>_encryptedPathColumnHeader</value>
+  </data>
+  <data name=">>_encryptedPathColumnHeader.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_cryptoName.Name" xml:space="preserve">
+    <value>_cryptoName</value>
+  </data>
+  <data name=">>_cryptoName.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ColumnHeader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_progressBackgroundWorker.Name" xml:space="preserve">
+    <value>_progressBackgroundWorker</value>
+  </data>
+  <data name=">>_progressBackgroundWorker.Type" xml:space="preserve">
+    <value>Axantum.AxCrypt.Forms.ProgressBackground, Axantum.AxCrypt.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=7a861c36d7a69820</value>
+  </data>
+  <data name=">>createAccountToolStripMenuItem.Name" xml:space="preserve">
+    <value>createAccountToolStripMenuItem</value>
+  </data>
+  <data name=">>createAccountToolStripMenuItem.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>AxCryptMainForm</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AxCryptMainForm.sv.resx b/Axantum.AxCrypt/AxCryptMainForm.sv.resx
new file mode 100644
index 0000000..8867da4
--- /dev/null
+++ b/Axantum.AxCrypt/AxCryptMainForm.sv.resx
@@ -0,0 +1,2204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="openEncryptedToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wwAADsMBx2+oZAAAA69JREFUWEe9lklPFFEUhfk3dk0/oPuXgO78B64AFRVnZWhQQEFkUkAQHHCWRSeF
+        Jm5Mu24WRiW6cGDVSMRwPbfq3arXr6uq6Rg4ybchoc857956VS3uqlv0XnmlpnkJnhk89UruYzfmEVhW
+        LIEFjXtuyZ63iy3Bj616lMlrxSvwUvECPAfPwFPFE4/cFZdgTjAn9wFYBkvgPlgEC2DeJWfOIWvWKmUH
+        0I3FnI1Nc9P4IdDNxfgeUObOXQSYzgqwT62d2dDcmUkLsM+tnTuhuTONALfNAHtpDeMac9O4QWs2dqbA
+        pB4go/WHzQ+0V1V3qtTxriO9tTJ2JsBtBBjVA6S0bla7u7vUW+5Nbc3Gzji4pQfImLXoiH+44ayPvTlG
+        WztbQYie9z2JrdnYHrPJHrXJGuYAfKGkzXolDrDXWR9dPUrbf7eDEO1+e2ysWrOxfRPckAB8g7GxYS5L
+        JsrccDluNeuut13B/1T/VGNj1ZqN7REwjACDEsBorT9aomY3XOSM1bZmY3sIXNcDGK31WYvEeO3rGm1u
+        b9bgb/i1s0ZrUWSsWrOxfQ0MIkAfAsCwZLbWj1skrdc319VfYlV+VWpnjeMWma3Z2B4ARS1Aork6bpHM
+        2pv1qLBYoMICmAdzBfImvdpZo7XIbM3Gdr/F5mT1cgB+ZaZtOJZMlDhro3U0axy3KKE1G5PVA65wAH5X
+        G631DRfJhq9tqB34XY//yQ9njeMWSWsrbk3W1cCcrMsSwGitb7hIWvO801T5UYlmLaprLeaXwAUOwF8n
+        Rmv9uRbJhnsT2IEZzH4aTBUoP5mn/AQYz5M75EazFiW0Ds0vgiiA0Vp/ZYrSZh1tuCyZmrWornVoTNZ5
+        i3LduVILfxaZrQNz80JRG+5/9mtnvxXjf/SjWYsSWpN1DpzVApit9Q0XSevKz4wd+F6JZi0yW2vmlDvD
+        Ae4iAJtr16jcZtxaJLeZO+JS/hZmPgZGwQ0wAobz5PThFauOWxSY1xtT7jTo4gD4Lkt6ruXlIWpbakuc
+        dd2G47hbZ1rVfyFAmvkpCTCFAEZruc249f+qzjg2p9xJDoDvMrO1vuHlb2X1U82r/KWc1JqNQzo5wDgC
+        GK3lNovucDluuc30R0vf8Kzj1s1PKIIA+C5r+Fz3J886ecPxw1mt2fi4IghwEwEOqnVsLCAAvssOuLUR
+        YAgBmmmdfKE001qn1ALjIn+bWQMAXygB+FCAaQhemTCNOQ+6rRKMQ3CbwTAGj1YAfrwRhzoPFf8BkAPy
+        3R7NeloAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="_openEncryptedToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Klicka för att välja krypterade dokument att öppna</value>
+  </data>
+  <data name="encryptToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wwAADsMBx2+oZAAACSJJREFUaEO9WFtvVFUD9dfQmTkzXt40PhgTEhLBxKRPJj5gGl5Q44sPIJcD1pZC
+        bcGW0s60lIG2FLnUMgO9QUtLBez3aZvUUuKlihes+sWEL4rxw7D3t9aevWf2OXPO9AwknGRlVg+ndK21
+        1+zLecK57NQ5E84xhUv6M4zb9/wY8+FiCPIWchrDFs75cEbjlA8ngUGn7gmKSh5PCiJ1KSUrcfue+nlC
+        /5wFHwfHZ/IY+Bh4LziQGgE/Ct4DfgG8GzwDngNPg59PymRnUjidjkh+nJROhyOI5DnwdvA28DPgH4If
+        Aj8F3gpOwMSjG6BoGqBoiFeiR8EpGkhdBId4Ck/lwSG+KLwLn8MQdARigOQQ+GFwCE+eBYd4Ck9+BA7x
+        zkHwQfAW8A+AAW2AwiIDootA6goQrwDhCkhdAeKZugLEKwM5CKd4AuKZOoUrIHUKZ+IKpwGIZ+oUrsSf
+        dCSES6cf6Kt2BKzKPErqxbo8TOoQnmhOiMSBhIhn4xENaOHqU4sP7DpFh3Xd1AXii8Kjd10q8RCO1GVi
+        Pww0WQYoNhTV1MVURtdFiTeVMXUxlWFd7MqYutiVsetSqIx0TgDHgSzQW6lCVl3MDGNX5lFSZ2VMXapN
+        neIT+8AbMQK9lSpk1cUIVz2n+JCuP939tNgytEX0fN0j++f7xfnF8+Lar9dkx40O4Y644sWRFwt1Yd+1
+        8ChdZ+oUT+GY/WWiARyIH6UBLEKhdQmrjF0X4JmLz8iGLxrk6l+rstL1z4N/5NiPY3LT6KbyGeYkxHtn
+        mFJdTGUgHrWRzlGgx5Hxbm2gUuqqKkyeiVuVMalv6NsgRm+OCgq8c+eOINbiKz+siL2f7ZXJg/h/qkn9
+        fXCIT9SDv4cR6LINUDS7TtEhM4yqDHuuu75papOcX5mPJNrPH4gH0p1whUp+ja4zdYqncKcbfC84UDCA
+        fUvFuvgro2eY50afk7f/uE1NZZcQQt7931258t8VuXpvVd5/cF//i/ficztv7AyeYUxdrMpQvJNJyEQa
+        6ErI+BFtoFLqKnk9w1C4ml2AthttgekOfDYgXp16VT51+KnCgoSuv9D1gnAvuuLu33fLnv/z/p9y/eH1
+        0VLfA0B83I0LBY8Bq+thq6maHjE1vtz/svj+p+89BpimO+mKVHuqfGrEDMOpcWN+o1z4ZsFjgJ9t020V
+        u+5kwCneBTotAx00gC2upzJ2XUxlfAtS9uss/67nml2dlamzeI6zS4UZpu5ynWT/7eve/Xvy2YFnA+oC
+        4VZlKD5xBOgADsNIuzZQKXV7D0Pxqc6UuP7VdU+KxGtTrwWmrlZT9SUF2PMDjsgv5D0jwM+3+9/2pQ6R
+        AalTfHEEDpkRiJC62Qo8f+F5NZ/b1+9//17VvN7872b9m6UrvZCOlHqiHWgroGigUur+neMrJ15Ridvp
+        jSyOeFIvbQMKqXNe5/RovqRb+7aWjUDXTFek1JVwzeOtNICjnZnXK+5huH/B5qu2r7bMwJn5M6UFiUDq
+        gQsSpkfOMK/3vl5mIPtJ1jPDMPUiR+pF/mGAgWJlmLqpDHeNhNk5ctcI1F6q5d/0XLM/z3p3jqxL2LyO
+        nm8e2ax/s3SNr4yX6hJUGQhPHAIOarTGZbyFBnCorpS6Z+eIntceLx+B05+fXjN1To/mS7q5Z3PwCERI
+        PdFa4rHmGAwMw4Cv656Dht45vnX2LfHpr5/KyZuTZQa+vP2lmPtlTg4vDIvh+WExtwqOzyL/HByY+7nA
+        Z5Zmygwsf7ss5n6ak0P/GhJbu7d6us7EDUfqisfcmGXAVMbUxX/QAHLf5fi3HsuVu5XzVoapU/gHGs3A
+        AaCJFeK7l5DU7Xk9cz1TTMvA/vlhedC9zFQmNHUKV+kTTRwBGvB13exh7IPGYzdgdZ2pG9Hx/ZaBRm3A
+        zDDFypgFSS9KnNfz3+X5/z+WK38rX6qMqQsB8aiNjO/TaGSF+NouJPXiQQMzTPpa2pOWnZifc2PXcaVD
+        vHTwJbHx1EbZeaUz9Pmge5nJTGjqFG54rIEjwPeMAXsY/2pajYGl35Zkck+yMINgaky5KXFl8Urg80H3
+        lAGr60y9yBstA/XaQNkehguSvShhXs+tRJ+FBpcGy/YwQ8tD+l/XvvI3USFTF1MZCI83aLwP1MOIMaAS
+        96SORYd7GB7v9B4m/Un0EVj+z7JKXY0AxD/pPimmF6cDnw+6l7mMEQhJneINj+2hAb6mtroedqhOz1b3
+        HXDPuwUDWJAaLjSEPh90Txmwus7Ui5zJa14wMAB5vroE7WFy31S3kM3eni3uYZZ/W9Z3o135JVTIVIZ1
+        0ZWJv1dAbG9MQjwBA33OsdBXGdYeJn01+giQt4y1FEYAq2l2Jhv6fNC9zCWMgJ06RZdSlzVujSDW7V6n
+        DVhdp/igQ3W1BtxBXSEsSO7HbujzQfcyEzBgdT3OxI0BVxvYbQxkYSAkdftQnZ6pzsCWji3KABekd3re
+        CX0+6J4y4Es9plNXBiC+ZhcM7NIG/Pt1dajWB2tzvMt9Vd13oH6yXr45/KZ8Y/gN2XK1Rd+NduUX8R1g
+        6qWu04yM7dbYpbGD34FejABfZQSkbh/v0tPVjUBUHnQvM57xdN1OncJrdoID63ZwBGCgmDoP1Vbq9qF6
+        6Fb0hehRr3ML58JT36mxQwEGujECEV5lbDiwQTRebZTuR65QOOWK/TP71ZeVaJpuku5JcKBpCnwAvB98
+        ErwPHGi6DH4CHGiaAD+uP7O4B+wb3yfdXlesd9eHpk7hNTvA38UIbMMI8BW1eVmqUjei7eMdXyLx034j
+        wJ8jbHnXWpDCZhimTvHKABJXBiBcGYD4koEuGLDr4tvDeA7VUU5JEfYwAQsSTRQQXhcZe9fCdmAbKqQM
+        mETt1AMO1Z5TEvGQqSuUkg9PnVXxpU7hNdvBt5kROBI/ZgSFvUBi6urTqowShNSNoCibr6AVFXzNrjNx
+        JRpQBiDeY6BYF39l7LoU3sOU18VUxtTF3sOwLqYy9rxu1yVKZViXIKgKtVsjEJC6gj5U24kTD5u6XZdq
+        U7d5YQRsA7rrigfMMPYpSf1cRdc9daEBLTxK1ysbaIvX8S1vEa0aLUCzhSYfcKBWaNCoLwFJe7Hbwi4N
+        LEIeoA7VIr49Xvd/J7BihXZSGqYAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="encryptToolStripButton.ImageTransparentColor" type="System.Drawing.Color, System.Drawing">
+    <value>Magenta</value>
+  </data>
+  <data name="_encryptToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Klicka för att välja dokument att kryptera</value>
+  </data>
+  <data name="decryptToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wwAADsMBx2+oZAAABHVJREFUWEe9lttPFGcYxvlv3JnZjZELjQcGL4zERLjwD1DjTeFCr7zxgFRq6QHK
+        ohzk2AUKLMseWFDKQZqxJk0aS2xsYkmzRJMGEtIGzEJbUqr79nl3vm/n22F2gVj7Jb8LBpjf88x8hynx
+        P/IHA7MBa9/MgCkXDwOWf8LvkARxQQxEFEb9lh7WgyXZmz0KUFHmBLNgRjANvgZT4KHgQYD8k36CnCAn
+        fwLEQQxEwRiIgLCfjBGDtGHNKh5AFUs5i91yt3gcqHIpHgVCbgwhwECxAO+ptTFsy43BQgHec2vjK1tu
+        DCBAnzvAXlpDXDFfQbU/1lLrYisFXwTp8veX6fDE4T21ZrHRD0JqgD22PvPNGbJWLcpkMuQem9ub1PGi
+        gw5FDxVuLcTGl6APAbrUALu0vvDdBdrY3hC6wuPZb8/oSPRIwdYsNnpBjxpgl3fNjzy9nRYKyj6Bhd8X
+        aDg1TImXCVr5Y0X8xh6Plx8XbM1ivVsnvUsnrZ0D8IZSoHVg0p5ocytz4tb2o7707aW8d30wcpBCP4fE
+        X9jjinXFlkuxaM1ivRPclwF4B2OxSy5n+MmZk/Qm80bclqhuoW7nDBePe/7Xedr4e4PWt9ap53mPLZdi
+        0ZrFegdoR4C7MoC7tbK0rj69KtREW/9sUWmsdPcZrrbuzm/NYr0NtKoBXK3Vdd34U6PQEy2ll3a09nzX
+        amspFq1ZrN8DdxHgCwSA0HK3VjeUpudNQk+0uL64x9YQFGjNYr0FBJUAnnJMstNTp6n/l36hJ3qVfkVV
+        D6qoahJMgCQYBwkQBzEQraLKsUqqHAXhSjo1eCqvNYv1Zo3lpDVxAD4y3dso5MeTxz03nP0OvsfRrqNq
+        axaT1gg+4wB8Viut5QwvT5aLW7z7MLtN0pzWpH2elZP2qQyg7uFikpUn/sMAnQggW0v5J+BjDsBfJx7r
+        2oyb4t+9R2otRWcjZ7Pveml9SVz1HuZ9BHBa2/IGNYB6ePAMx9Iyo8UD1D+pzy2thicN4qr3MNsRQLa2
+        xaTd0ch322eV8GeR17o2I8UDTKemc0trNjUrrnoPsw0BVPlHoF4JIFur69oMFw/Ao2Kggs6NnBM/FR7m
+        PQQQrRU5+T7kAEMIwHL1yMSmYo4UD/A285ZK20uprKtMXCk8zBYEyBeTrw7UcgB8l3ntZuZQ8QDL6eXc
+        un7912tx1XuYQQRwy2/JAP0I4LGHm4PFA6xurlLfD33U+7SX1v5cE1e9R1lzmSN25OS7yQHwXSZb545M
+        7OEnQifEv7/7ONZ4zC22ucYBehHA6+TCDL+YuEg1kzVUMwGSYLyGqhPVVB0XxEAUjIGIYBSEwQjzAZ0P
+        nbfFqvyGIBsA32W5k0semby85OHBe3izaw/nTSV/Q1FmOG688107rVl8XZAN0IkASuvcySUPD7mHq9uo
+        Kt+5tByxu7UjliAAvsv+59auAG0IsJ/W3hvKflqrWCUQB/nbTGsB+ELJgg8FSG1wZELqcAfc1iyIbbCb
+        QeiApZUFN9+NA9cOBP8FYJWkhX23sEkAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="_decryptToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Klicka för att välja dokument att dekryptera</value>
+  </data>
+  <data name="closeAndRemoveOpenFilesToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wwAADsMBx2+oZAAABPVJREFUWEe9lttPU1kUxvmH1HqPl0Sj8cFEXzRREx80MRqfTDTx9qCJxpiYMIPM
+        hdEBlbkwwgzDTSjlYrcgHSwUQa4K6gyJyRAsmKFcLWXNt/bZq+weDm3nZVbye2l7zvd9e6+9dnN6fL68
+        V+vXq3T0WHS5iBjCFi9AyNBi8dSiGTRBO0eLbNhA6egxdBtegi4QAZ2GDhAGL8AfoA08BxCmZ0CBIIA4
+        QZwaQQO0MxrwErbFbeF2EAIs3ApscRFuAiweAHXpDNipWTjb1G5hSS3CSK3F/WBVA5lSvz5zhmZGRpYZ
+        Hqa2LVtSxO3ltlPXAxavBdVuA5lSc2Jm+MIFctdzGMgytRZ/Aqp9PpXDnZ1Nar3cGzfq5X7jYaBl82Yt
+        rrZuTZuahWsA0tPvYiCb1G+vXqVYb6/e6yEPAwoGgps20cLEBA3eukUN+J07tQhX+XxUCbQBPsvpUndu
+        20bRQECLLESjusMHPAwEYaAZBqSi4TA17d6dkroKsHCFI05lYmC11B1Yzn86OswrYeDjR91k/R4GmmGg
+        0TLANYUGDezalUwtwuXgN9vAir0GvNdjZWXmVU7Nj4/rRuvzMNAIAwH0SOLzZ/OJU2NtbVSJZ1hchH91
+        xKmEDfAYtYVFvO/ECVpaWjKvIf3igStXdIf3ehgIwADvdfvp0xSfnjafOhW+dEmLi3ApeCwGeHbbqWWa
+        TbS2Ok+bGr5zJ3muezwM+GFA9rrz8mXzqVOfhoa0uAj/4ojTD2LAPc3a9+yhpcVF8zhRDHv5FJ/L0er2
+        MFALA/ZeR7u7zTdO+Q8dktT0M/gJaAN8c6XMcLzE3WQj+flaXAbKSw8DNTAgHc7LHbl503zjVPjGDS3O
+        wj8CiNODNWtUDl+Z7hk+kptrHnMqcvZsyjSLeBiowgmQDuflDhw+bL5x6lVBgaSmYvAIaAMQVZyaxWWM
+        vkViu8KnTqVMs87z5803TnGzVuAESIfzXlft22e+dWqwpESLs/DDdevoASgSA/YM5yYbuH7dPOZU/+3b
+        KdOsBqtVu3Mn1WzfTtWgEsPK7nBusmacBru6EErEi0AhuM8G0NnKfXOFXMs3HgotTzO8xN5rO7V0ODfZ
+        69JS87RTfqyiTm3Evwf3xIB9echex96/N49iiRMJajl+fMU0c6eWDq/Yv5/is7PmaaK5yUl6iFUT4fss
+        Dr5lAxBXdofLXvdh2e2KjY5S3d69aVNzkz3esYOi/f3mKae6CwuXU4PvQIEYgLBicRGWveZzPfXunXmF
+        U9MfPlAQE9IrNR+tJ0eO0CT+nNg1iwusGP0iqZPi4Bs2gNSKxe0/CrLXQbwwPjNjXuUUd/zf7e0UwWTk
+        Rms4eZJC167RaDBICWt4cSXicarDEV4hDL4G+WwAwsrucPfN9QzNszA1ZV6ZfS3Oz1PTxYurin8FtAEI
+        q0wdXnvgAI1Z13KmGh8cpPKjR1cXNtxlA/y/zOu+9urwJiz5n/X1tBCLGanlis/N0V9KUeDcObqH36YT
+        vwvywBdsAMIqm3Ntz/BiGC4/eJDqsD1+/EOuOHaMijCK0y63QcS/BNoAEqtM5zopDPQMx8P2QPHscOCV
+        OinOsAEIq0ypRTg5w4EepeC/pk6KM2wAidX/mtqGDUBYZZs6W+G0qW3YABLnAQVxhcQaiCu+qxm+MvnW
+        EvgC4REq8DTj8yzw0eIXZ0Pu2rV5/wL6UMOXbeGRgQAAAABJRU5ErkJggg==
+</value>
+  </data>
+  <data name="_closeAndRemoveOpenFilesToolStripButton.ToolTipText" xml:space="preserve">
+    <value>Klicka här för att stänga och ta bort öppna dekrypterade dokument, men säkerställ först att de inte används.</value>
+  </data>
+  <data name="helpToolStripButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO
+        wwAADsMBx2+oZAAAA81JREFUWEe9lklPFEEYhvk3Ti8T5oAxHvgD4MUTV46awMV4cBcXVAaZAVncQFHZ
+        NxEE2SdEo0aCGqNeCago8UCAhASE+Xy/qeruopmeKQ5Q5j3gYZ736f6qunLscTseHg0n9pwRZMiXl+GE
+        /cL20o/0yvQgnUo67ITZbsZzUj82HqaMGZMZRUZkXiHDyBDyUmYwTPaATYAT4GT3Ib1ID9KNdCGdSLtN
+        VptFRquRyFxABTtwBvvhfvBzRIU74A5Ewq0WFHiSqcA+WVutAm49DSqwz9bWMwG3nqBAk7+AjjXAO+B+
+        cBZrBlvNyGO1wEFZS7D1CGlCgftqAQ3ro8NH6eS7E1T7vZb65/tpanGKJn9NUt9cH0U/R+nY8LGs1gy2
+        GpGHagEN6zOzZ2hze5Myre3kNg3ODVJeR16gNYPNByaZ900y6rkAHyhB1gPykeNxx77FJCb7Gpsf86wd
+        sLRmsHkPuesU4BOMwVnedeyrV2BlY4Xe/3lPEz8maGFtQf6vt5LJJBX2FQq4A5bWDDYbkHoUqHEK+K3T
+        DFnll0r6+PcjlbwpoUhXxH3XuW25NLs0K9HeOjV1SsAf7LRmsFmH1KoFAqzVCY/0AKpOuDNkeNdDc0MS
+        663SsVJh7YClNYPNO0gNClShAICJIGudfV08WkwbWxsSKxb/nf80P601g81qJK4USAtXwWmsGX56+jSt
+        /1uXWG/VzdQFWjPYjBkMJ+M2F+BPZpC1eqD49nXFh4rUtlNXEv+6vnWRdRfvPdiawWRUIhVcgL/Ve7Dm
+        rVU6WZqadHVtJbco+jYqrB2wYm141mREU3AybjkFMlk7YGVfz/yekVhvlb8u17N24DeRci7AtxMNa/c0
+        w9b6ufpTYsXip3Hk4RFdawG/gbgFNKzd0wxbq6CjgIp6i6ioB+kuouPtx/WtBZiM6waFroQSOXwt0rF2
+        TzNsrbLpMmqYaRD50EDVb6vJvmPvtFbBO63JuIZcVQroWLunGYZscXVRPnyx+BUcrj+829oPhrUCp1AZ
+        F2hBAYY74ABrd19jyNIWqM0Ltt4NptBl5CIXwL0snbX78ZDW7oRjyNIVyKtBAT1rAb/kFGhGAQ1rd8Ix
+        ZJ8WP9Hy+rKbpbUlilRF9Kw9OIUucAHcy3Ss9zrhAg7IbmsGi5zlAo0ooGGtNeGZHrcKPy+TKoB7WVbr
+        WBrrwHeNH85kzeBzMqkC91DgoKw9sBMUwL3sgK19BepQYC/W2bZWdms1iRyA43w3M6oR3FBSwUUBUBF8
+        MgH1ch25YiQAFsFpBqAXbK1U8OPZcujsofh/LYxz4KyJsdgAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="openEncryptedToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAghJREFUOE9t
+        kslTE0EUh/lzprtnSE0KihPF3+W+4RoLkE2RJYqABmRTNvGYq1VeuHdVuHpQ54BK9Pm97iQm6qv6TtPv
+        9/V7PX3Z+6wOvsNxiyM4hH3Yy3z6JvXpDmzCBtRS79ZcXQO0UQLH8A6O4AD2M0nfppLuwja8hvVU3Csn
+        bhVeOB8DtLHdfBgbsQpWwSrpFmxAjeaXNK7Ac6hqgF63y1qcF/J3NX81pfKx0raKewZLTuy8JSDO2rFq
+        De0N9ViHt4bl5NOJVD4QUqV5geanVuxjDTggoGtWrf/MKiO1EWn+bKpV7BOYhSkCaNQNx1k3WwFYT4tT
+        OTs/k8bXRstqwzesYqdh0ooZNwTsEtC1YS21llZLUl4pS6la6li1sIqdoHnMiKloQHzXuOE1Fw7phtWs
+        Nwi3+NIIVi2sYh7CA7inAev8EO1Zl1sBi9xgkRsslCWfy6V/pj9YtbCKuQ93jSSjie/D6rveNRyyczZY
+        ww1+cIPPjWDVwirmNtwi4IYGLBOg74pVZ9UanB8M1nw6l3wyl2wsk4HxgfDNjNJ4M5HkOlzVgCXnLRtW
+        q264+P7vj9Su4luhVkmuwRW4TAA/hA/vOgO9G46z3oFea2y+BBc1YJYAfddH4V3/bJglxVk52GvVRkku
+        BAiYsnUzYTxWr++K1WP1WD1Wj9XrrDR7rF6t2hhJ6r8Bi9c8pZqh570AAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="openEncryptedToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_openEncryptedToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Öppna Krypterat</value>
+  </data>
+  <data name="encryptToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAlxJREFUOE99
+        kktPU1EUhfk591UmhDAhDBi1PwBCmDMgzJpAovWFYrUqFi2tgHBaX0UQQawULCTGtE2DYeADtYwOMAAT
+        STtQUw2py3XuvS3WgSf5Bic569t3732bPOueLJF1Mi5rZJWskBceaT23pPWMPCVPyJwlzaSZVQIVhE2G
+        vCRrJE1WPLBSFqxlskQWyLwF87EJ8xF5YEpHoIK18KoTbEm3oDfbi65XXWheagarglVhzjL4kNwjcSVQ
+        n/tPVf+WH6VfJdTO3rc99GR6alVhJogwYdw1KHB6tYPsFd2vu3FcPcZ2aRv+gh+BzQAOvh+g/LOM9rl2
+        VRXmNMNTBow7SpCm4K9eF+QCqr+r6Ex11nvt2+izvyRYCKqqMCZIjEQoYFBNGJwwOGHkv+RxVDkCJ1zv
+        tWO2wxYk3iVUVRjj5LYBPaxTsEyBO+GB3AAOfxyiclxBcieJZJF8SmJxZ9EWFL8W0Z/qhzHG8E0d+nUl
+        cPZqTzj+OW4//N8RWwL6DYavkatKMM8fwu1VfBTuM+cMbgxiaH3IvTlHvKEgxPAVHdqIJpvYq6z1Kj40
+        CkK5EEbzo+7NOWKTgssUXKJgWAnuU6D2OkPB+0ZBOBdGtBB1b84RBQHtogbtAjmnBMKUxjSnOmlAvG0U
+        7JZ3sV/ed2/OmcnPQDvP8FlyhgL+ENLea9RA22QbfAkffMIH77QX3ikyQWJknES8aA22OuEAOa0EMQrU
+        Xm/Zez2ZMIfk9MqHw+SkqgpCO2VDQcTI6mO65F6l2isnLPUgGdEle5XsVapeGZasKlVVFXTQsn8A1Gtv
+        qsw7YvUAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="encryptToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_encryptToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Kryptera</value>
+  </data>
+  <data name="decryptToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAlFJREFUOE91
+        kktPU1EUhfk591UmhDBgxoR2xAhC+AeEWRNItL5QRKvWoqUVkJ7iq0qtQagULCbGtE2D6cBI8TE6pJM6
+        IO1ATTVNXa5z7y0PE3fyDU5y17e7926XZ8eTJ/KInMs22SKb5JVHWhuWtF6SF+Q5WbWkmTTzSqCCsMmR
+        12SbZMmmB1bGgrVO1kiapCyYz0yYT8gjUzoCFeyEt5xgT7YHY/kxDL8dRvdaN9gV7ArzKYOPyQOSUAL1
+        c//p6i/7Uf9dR6eq36sYzY12usJcIcKEcd+gwJnVDnJWjLwbQavdQqVegb/kR2A3gNqPGhq/Guhf7Vdd
+        YS4zvGTAuKcEWQpOzJqWabT/tDGQGTiadWhjCKFyCIOpQdUVxgKJkQgFDKoNgxsGN4zityIOm4fghk/O
+        yq4MLNpdYcyTuwb0sE7BOgXuhicKE6j9rKHZaiL5NYnkF/KJ7JMK2UtiPDMOY47h2zr0m0rg3NXecOJz
+        wl3b/0uUBfRbDN8g15UgxT+EO6vYF+5nTk2+mcTUzpT7ckq8pyDI8DUd2owmuzir7Mwq9k4LgoUgQsWQ
+        +3JK7FJwlYIrFEwrwUMK1F3jFHw8LQgXwoiWou7LKVES0C5r0C6RC0ogTGm4GxYfTgsOGgeoNqruy6l4
+        MQ7tIsPnyTkK+IeQ9l2jBvoW++Bb8cEnfPAue+FdIgskRuZJxIve2V4nHCBnlSBGgbrrHfuuxxvmkpxZ
+        +eE0Oe6qgtDO2FAQMfL6nC55V6nuyg1LfZbM6JKzSs4q1awMS3aVqqsKOmj5v9iLaPnp2/2xAAAAAElF
+        TkSuQmCC
+</value>
+  </data>
+  <data name="decryptToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_decryptToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Dekryptera</value>
+  </data>
+  <data name="toolStripSeparator2.Size" type="System.Drawing.Size, System.Drawing">
+    <value>158, 6</value>
+  </data>
+  <data name="closeOpenFilesToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAohJREFUOE9d
+        kstPE1EYxflzZu7MlJISuiBdEHaE7ljAjiV7Vr5foCI+QEZsa3kIyFu0tdDyMJI0JLrBIEpsXFyJCZFY
+        SIOACCbHc+9Qrd7kl3ndc85833fLnEUnS+QfFk7JkDSZJSlH2klb2s/JUzJFJmxpjVpZZaCE0CyQeZIh
+        c2TWgf3Chp0gz8g0mbRhjVuwnpBhS3oGSlgUpz1h3as65I/yGt+MD0wFU2GNUThCHpMBZaB+97/Uljct
+        CL8Mo7jKp8rRutJaTIU1SPotiEeCBl6tWuhL+TC9OY2DkwOEF0oMxsv1NS3T8A36YMUpjgmIh8pgjgan
+        tXa+79QbN3Y3EM78NXBGHKx/W9f3kdUIRITiXtJDAwpVh+FP+LF7tKvTa5O1CM+WGAw6CI2EsPdzD/vH
+        +whEAxD3Bcx7Jg0SNGCHG5Ya9OalL0u61vpEvX5Wy4k7OjWZS+rnpokmmHdNmJ3KwJsrGhcb9cfM54zu
+        cPVoNWJvY4iuRlWtEK7A2Lsxvad5shnmLRrcVAaTPBCca+VEJQ5PDlE4KqBqqEp12Kv1ga4VftePrb0t
+        HP86RrA7CPOGCaPNkGU8TbI41+EPwzpheXMZVX00YaroFgi4AWRyGf1tZm0GZjvTr9HgijIYooGaax//
+        YqASa1/X9MbCjwLmP80j9TGFnYMd/S63nUPwThDGVQPGZXJRGfRbUsSZFCWstSJSAfe1i+3v21qkVn4/
+        j9hKDIGOgEqFcYlcIOdpwAMhS2sVXRyP12GE3BBq3BqIdlGa6onPkbPKoJcGp7VyrjBvE9VhNsmrlRv/
+        TVVCGGc0NOgRWbPLlEyVaq5mB7lO2kzJVMlUqWqlWDJVqlQl9DCyvwHO+VecZoqTtAAAAABJRU5ErkJg
+        gg==
+</value>
+  </data>
+  <data name="closeOpenFilesToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_closeOpenFilesToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Rensa och Stäng Öppna</value>
+  </data>
+  <data name="toolStripSeparator3.Size" type="System.Drawing.Size, System.Drawing">
+    <value>158, 6</value>
+  </data>
+  <data name="languageToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>109, 22</value>
+  </data>
+  <data name="_languageToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Språk</value>
+  </data>
+  <data name="debugOptionsToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>109, 22</value>
+  </data>
+  <data name="optionsToolStripMenuItem.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAoNJREFUOE9t
+        kllPU1EUhfk599wBShsSEtI/wCshbXjjN0BS6jygojhUULQUCyKVSavIVAEjofHNEBJNVAw54Yk0oEDT
+        Btoiy3XOvTgknORLbm72WuvsvU+Vs+hkifzDgkeGzJNZMuNI+40t7dfkJZkk47a0nltZZaCE0CyQtyRD
+        5sisA3vahj1FXpEXZMKGNWbBSpFnlnQNlPBEPO8KmYrwShih5RDsNIWTZJziUQpHyFMyqAzUdf9J9c35
+        UD9fr1M3C5vYK+3p1IZ0A/xjfpUKa4gkLZgJkwZurzq1ZqYGaz/XsHO4g/jXOI6Pj6HO4JdB5Et5rOZW
+        4Qw5sAYo7jdhPlIGczTweg1MB7B9sK1Fp53dg134k36YjynuI700oFBNGJwwOGH0fO7RxbliDtEPUUSz
+        Uf2tzsinEVTHq2E+oLjHhLgnaDBFA064aakJxUpRF6rTttLm9vrEQuR9xPsLFMtFNI82Q9wVEN3KwN0r
+        wothlI5KXhnQvtzOXpkUN9HxrsP7C5QqJbROtELcokGXMpjgg/D26kv5kP6e1oVbhS20L7UhshRBruC2
+        kPmWgXPHgbhJ8Q0Bo9OQVXxN8mSvwdEgCuWCLj7tVI4qaOxvhLhGg6s0uKwMhmng9VqbrMX6j3XsH+4j
+        8THhyYDUagr5wzw2djZQ110H44oB4xK5oAySljS9XrlXBOIBBBNBODEb5aMyKr8qMLtMNMT4kLr8KhXG
+        RXKenKMBH4TUe31IekmM63EnjNBwCC3DLRCdvO7fVFd8lpxRBn00UHu9r/cKcZuoCXNIbq8s/D9VCWFE
+        NTToNbMiJiRTpdorJyzFddIpJFMlU6XqlWLJVKlSldDFyP4GDMhi3CpAsUkAAAAASUVORK5CYII=
+</value>
+  </data>
+  <data name="optionsToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_optionsToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Alternativ</value>
+  </data>
+  <data name="exitToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>161, 22</value>
+  </data>
+  <data name="_exitToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Avsluta</value>
+  </data>
+  <data name="fileToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>46, 20</value>
+  </data>
+  <data name="_fileToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Arkiv</value>
+  </data>
+  <data name="checkVersionNowToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>162, 22</value>
+  </data>
+  <data name="_checkVersionNowToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Sök Uppdatering</value>
+  </data>
+  <data name="setUpdateCheckUrlToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>162, 22</value>
+  </data>
+  <data name="_setUpdateCheckUrlToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Alternativ</value>
+  </data>
+  <data name="viewHelpMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>126, 22</value>
+  </data>
+  <data name="_viewHelpMenuItem.Text" xml:space="preserve">
+    <value>&Visa Hjälp</value>
+  </data>
+  <data name="aboutToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>126, 22</value>
+  </data>
+  <data name="_aboutToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Om</value>
+  </data>
+  <data name="helpToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>47, 20</value>
+  </data>
+  <data name="_helpToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Hjälp</value>
+  </data>
+  <data name="largeImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
+    <value>
+        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
+        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAS
+        wwAAAk1TRnQBSQFMAgEBAwEAAZQBAwGYAQMBMAEAATABAAT/ASEBEAj/AUIBTQE2BwABNgMAASgDAAHA
+        AwABMAMAAQEBAAEgBgABkBIAAzsBYwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAzsBYwM7AWMBUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwM7AWMDOwFjAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8DOwFjwAABUAFRAVABnwEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGO
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+
+        ASgBfwEoAf4BAAGHAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGD
+        AQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGBAQAB/wEoAX8BKAH+AScBfwEnAf4BAAEYAQAB/wEnAX4BJwH+
+        AScBfgEnAf4BAAEWAQAB/wEnAXwBJwH+AQABFQEAAf8BJwF7AScB/gEnAXsBJwH+AQABFAEAAf8BJwF6
+        AScB/gEnAXoBJwH+AQABEgEAAf8BJwF5AScB/gEnAXgBJwH+AQABEgEAAf8BJwF4AScB/gEnAXgBJwH+
+        AQABEgEAAf8BJwF4AScB/gEnAXgBJwH+AVABUQFQAZ8BUAFRAVABnwEpAX8BKQH+ASkBfwEpAf4BAAGR
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+
+        AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+ASgBfwEoAf4BAAGHAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGF
+        AQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGDAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGBAQAB/wEoAX8BKAH+
+        AScBfwEnAf4BAAEZAQAB/wEnAX4BJwH+AScBfgEnAf4BAAEXAQAB/wEnAXwBJwH+AQABFgEAAf8BJwF7
+        AScB/gEnAXsBJwH+AQABFQEAAf8BJwF6AScB/gEnAXoBJwH+AQABEwEAAf8BJwF5AScB/gEnAXgBJwH+
+        AQABEwEAAf8BJwF4AScB/gEnAXgBJwH+AQABEwEAAf8BJwF4AScB/gEnAXgBJwH+AVABUQFQAZ8BUAFR
+        AVABnwEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEpAX8BKQH+
+        ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+ASgBfwEoAf4BAAGH
+        AQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGDAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGBAQAB/wEoAX8BKAH+AScBfwEnAf4BAAEjAQAB/wEnAX4BJwH+AScBfgEnAf4BAAEh
+        AQAB/wEnAXwBJwH+AQABIAEAAf8BJwF7AScB/gEnAXsBJwH+AQABHwEAAf8BJwF6AScB/gEnAXoBJwH+
+        AQABHQEAAf8BJwF5AScB/gEnAXgBJwH+AQABHQEAAf8BJwF4AScB/gEnAXgBJwH+AQABHQEAAf8BJwF4
+        AScB/gEnAXgBJwH+AVABUQFQAZ/AAAFQAVEBUAGfASkBfwEpAf4BKQF/ASkB/gEAAZIBAAH/ASkBfwEp
+        Af4BKQF/ASkB/gEAAZABAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY0BAAH/ASkBfwEpAf4BAAGLAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BKAF/ASgB/gEAAYgBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYYBAAH/ASgBfwEo
+        Af4BKAF/ASgB/gEAAYQBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYIBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYABAAH/AScBfwEnAf4BJwF+AScB/gEAARcBAAH/AScBfQEnAf4BAAEWAQAB/wEnAXwBJwH+AScBfAEn
+        Af4BAAEUAQAB/wEnAXsBJwH+AScBegEnAf4BAAETAQAB/wEnAXkBJwH+AScBeQEnAf4BAAESAQAB/wEn
+        AXgBJwH+AScBeAEnAf4BAAESAQAB/wEnAXgBJwH+AScBeAEnAf4BUAFRAVABnwFQAVEBUAGfASkBfwEp
+        Af4BKQF/ASkB/gEAAZIBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZABAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AY0BAAH/ASkBfwEpAf4BAAGLAQAB/wEoAX8BKAH+ASgBfwEoAf4BKAF/ASgB/gEAAYgBAAH/ASgBfwEo
+        Af4BKAF/ASgB/gEAAYYBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYQBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYIBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYABAAH/AScBfwEnAf4BJwF+AScB/gEAARgBAAH/AScBfQEn
+        Af4BAAEXAQAB/wEnAXwBJwH+AScBfAEnAf4BAAEVAQAB/wEnAXsBJwH+AScBegEnAf4BAAEUAQAB/wEn
+        AXkBJwH+AScBeQEnAf4BAAETAQAB/wEnAXgBJwH+AScBeAEnAf4BAAETAQAB/wEnAXgBJwH+AScBeAEn
+        Af4BUAFRAVABnwFQAVEBUAGfASkBfwEpAf4BKQF/ASkB/gEAAZIBAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AZABAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY0BAAH/ASkBfwEpAf4BAAGLAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BKAF/ASgB/gEAAYgBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYYBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYQBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYIBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYABAAH/AScBfwEn
+        Af4BJwF+AScB/gEAASIBAAH/AScBfQEnAf4BAAEhAQAB/wEnAXwBJwH+AScBfAEnAf4BAAEfAQAB/wEn
+        AXsBJwH+AScBegEnAf4BAAEeAQAB/wEnAXkBJwH+AScBeQEnAf4BAAEdAQAB/wEnAXgBJwH+AScBeAEn
+        Af4BAAEdAQAB/wEnAXgBJwH+AScBeAEnAf4BUAFRAVABn8AAAVABUQFQAZ8BAAGVAQAB/wEAAZQBAAH/
+        AQABlAEAAf8BAAGTAQAB/wEAAZIBAAH/AQABkQEAAf8BAAGQAQAB/wEAAY8BAAH/AQABjgEAAf8BAAGO
+        AQAB/wEAAY0BAAH/AQABjAEAAf8BAAGLAQAB/wEAAYoBAAH/AQABiQEAAf8BAAGJAQAB/wEAAYgBAAH/
+        AQABhwEAAf8BAAGGAQAB/wEAAYYBAAH/AQABhQEAAf8BAAGEAQAB/wEAAYMBAAH/AQABgwEAAf8BAAGC
+        AQAB/wEAAYEBAAH/AQABgQEAAf8BAAGAAQAB/wEAARgBAAH/AQABGAEAAf8BAAEXAQAB/wEAARcBAAH/
+        AQABFgEAAf8BAAEWAQAB/wEAARUBAAH/AQABFQEAAf8BAAEUAQAB/wEAARQBAAH/AQABEwEAAf8BAAET
+        AQAB/wEAARIBAAH/AQABEgEAAf8BAAESAQAB/wEAARIBAAH/AQABEgEAAf8BAAESAQAB/wFQAVEBUAGf
+        AVABUQFQAZ8BAAGVAQAB/wEAAZQBAAH/AQABlAEAAf8BAAGTAQAB/wEAAZIBAAH/AQABkQEAAf8BAAGQ
+        AQAB/wEAAY8BAAH/AQABjgEAAf8BAAGOAQAB/wEAAY0BAAH/AQABjAEAAf8BAAGLAQAB/wEAAYoBAAH/
+        AQABiQEAAf8BAAGJAQAB/wEAAYgBAAH/AQABhwEAAf8BAAGGAQAB/wEAAYYBAAH/AQABhQEAAf8BAAGE
+        AQAB/wEAAYMBAAH/AQABgwEAAf8BAAGCAQAB/wEAAYEBAAH/AQABgQEAAf8BAAGAAQAB/wEAARkBAAH/
+        AQABGQEAAf8BAAEYAQAB/wEAARgBAAH/AQABFwEAAf8BAAEXAQAB/wEAARYBAAH/AQABFgEAAf8BAAEV
+        AQAB/wEAARUBAAH/AQABFAEAAf8BAAEUAQAB/wEAARMBAAH/AQABEwEAAf8BAAETAQAB/wEAARMBAAH/
+        AQABEwEAAf8BAAETAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGVAQAB/wEAAZQBAAH/AQABlAEAAf8BAAGT
+        AQAB/wEAAZIBAAH/AQABkQEAAf8BAAGQAQAB/wEAAY8BAAH/AQABjgEAAf8BAAGOAQAB/wEAAY0BAAH/
+        AQABjAEAAf8BAAGLAQAB/wEAAYoBAAH/AQABiQEAAf8BAAGJAQAB/wEAAYgBAAH/AQABhwEAAf8BAAGG
+        AQAB/wEAAYYBAAH/AQABhQEAAf8BAAGEAQAB/wEAAYMBAAH/AQABgwEAAf8BAAGCAQAB/wEAAYEBAAH/
+        AQABgQEAAf8BAAGAAQAB/wEAASMBAAH/AQABIwEAAf8BAAEiAQAB/wEAASIBAAH/AQABIQEAAf8BAAEh
+        AQAB/wEAASABAAH/AQABIAEAAf8BAAEfAQAB/wEAAR8BAAH/AQABHgEAAf8BAAEeAQAB/wEAAR0BAAH/
+        AQABHQEAAf8BAAEdAQAB/wEAAR0BAAH/AQABHQEAAf8BAAEdAQAB/wFQAVEBUAGfwAABUAFRAVABnwEp
+        AX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGSAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGQAQAB/wEpAX8BKQH+AQABjgEAAf8BKQF/ASkB/gEpAX8BKQH+ASgBfwEoAf4BAAGLAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGEAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGCAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGAAQAB/wEn
+        AX8BJwH+AQABGAEAAf8BJwF+AScB/gEnAX0BJwH+AQABFgEAAf8BJwF8AScB/gEnAXwBJwH+AQABFAEA
+        Af8BJwF7AScB/gEnAXoBJwH+AQABEwEAAf8BJwF5AScB/gEnAXkBJwH+AQABEgEAAf8BJwF4AScB/gEn
+        AXgBJwH+AVABUQFQAZ8BUAFRAVABnwEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGSAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGQAQAB/wEpAX8BKQH+AQABjgEAAf8BKQF/ASkB/gEp
+        AX8BKQH+ASgBfwEoAf4BAAGLAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGIAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGEAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGCAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGAAQAB/wEnAX8BJwH+AQABGQEAAf8BJwF+AScB/gEnAX0BJwH+AQABFwEA
+        Af8BJwF8AScB/gEnAXwBJwH+AQABFQEAAf8BJwF7AScB/gEnAXoBJwH+AQABFAEAAf8BJwF5AScB/gEn
+        AXkBJwH+AQABEwEAAf8BJwF4AScB/gEnAXgBJwH+AVABUQFQAZ8BUAFRAVABnwEpAX8BKQH+ASkBfwEp
+        Af4BAAGVAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGSAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGQAQAB/wEp
+        AX8BKQH+AQABjgEAAf8BKQF/ASkB/gEpAX8BKQH+ASgBfwEoAf4BAAGLAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGEAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGCAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGAAQAB/wEnAX8BJwH+AQABIwEA
+        Af8BJwF+AScB/gEnAX0BJwH+AQABIQEAAf8BJwF8AScB/gEnAXwBJwH+AQABHwEAAf8BJwF7AScB/gEn
+        AXoBJwH+AQABHgEAAf8BJwF5AScB/gEnAXkBJwH+AQABHQEAAf8BJwF4AScB/gEnAXgBJwH+AVABUQFQ
+        AZ/AAAFQAVEBUAGfASkBfwEqAf4BKQF/ASkB/gEAAZYBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/
+        ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BAAGPAQAB/wEpAX8BKQH+ASkBfwEpAf4BKQF/
+        ASkB/gEAAYwBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYcBAAH/
+        ASgBfwEoAf4BKAF/ASgB/gEAAYUBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYMBAAH/ASgBfwEoAf4BKAF/
+        ASgB/gEAAYEBAAH/ASgBfwEoAf4BAAEYAQAB/wEnAX8BJwH+AScBfgEnAf4BAAEXAQAB/wEnAX0BJwH+
+        AScBfQEnAf4BAAEVAQAB/wEnAXsBJwH+AScBewEnAf4BAAEUAQAB/wEnAXoBJwH+AScBegEnAf4BAAES
+        AQAB/wEnAXkBJwH+AScBeAEnAf4BUAFRAVABnwFQAVEBUAGfASkBfwEqAf4BKQF/ASkB/gEAAZYBAAH/
+        ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BAAGP
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BKQF/ASkB/gEAAYwBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/
+        ASgBfwEoAf4BKAF/ASgB/gEAAYcBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYUBAAH/ASgBfwEoAf4BKAF/
+        ASgB/gEAAYMBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYEBAAH/ASgBfwEoAf4BAAEZAQAB/wEnAX8BJwH+
+        AScBfgEnAf4BAAEYAQAB/wEnAX0BJwH+AScBfQEnAf4BAAEWAQAB/wEnAXsBJwH+AScBewEnAf4BAAEV
+        AQAB/wEnAXoBJwH+AScBegEnAf4BAAETAQAB/wEnAXkBJwH+AScBeAEnAf4BUAFRAVABnwFQAVEBUAGf
+        ASkBfwEqAf4BKQF/ASkB/gEAAZYBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/ASkBfwEpAf4BKQF/
+        ASkB/gEAAZEBAAH/ASkBfwEpAf4BAAGPAQAB/wEpAX8BKQH+ASkBfwEpAf4BKQF/ASkB/gEAAYwBAAH/
+        ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYcBAAH/ASgBfwEoAf4BKAF/
+        ASgB/gEAAYUBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYMBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYEBAAH/
+        ASgBfwEoAf4BAAEjAQAB/wEnAX8BJwH+AScBfgEnAf4BAAEiAQAB/wEnAX0BJwH+AScBfQEnAf4BAAEg
+        AQAB/wEnAXsBJwH+AScBewEnAf4BAAEfAQAB/wEnAXoBJwH+AScBegEnAf4BAAEdAQAB/wEnAXkBJwH+
+        AScBeAEnAf4BUAFRAVABn8AAAVABUQFQAZ8BAAGZAQAB/wEAAZgBAAH/AQABlwEAAf8BAAGXAQAB/wEA
+        AZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZEBAAH/AQABkAEA
+        Af8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYwBAAH/AQABiwEAAf8BAAGKAQAB/wEA
+        AYkBAAH/AQABiAEAAf8BAAGIAQAB/wEAAYcBAAH/AQABhgEAAf8BAAGFAQAB/wEAAYUBAAH/AQABhAEA
+        Af8BAAGDAQAB/wEAAYIBAAH/AQABggEAAf8BAAGBAQAB/wEAAYABAAH/AQABgAEAAf8BAAEYAQAB/wEA
+        ARgBAAH/AQABFwEAAf8BAAEWAQAB/wEAARYBAAH/AQABFQEAAf8BAAEVAQAB/wEAARQBAAH/AQABFAEA
+        Af8BAAETAQAB/wEAARMBAAH/AQABEwEAAf8BAAESAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGZAQAB/wEA
+        AZgBAAH/AQABlwEAAf8BAAGXAQAB/wEAAZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEA
+        Af8BAAGRAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEA
+        AYwBAAH/AQABiwEAAf8BAAGKAQAB/wEAAYkBAAH/AQABiAEAAf8BAAGIAQAB/wEAAYcBAAH/AQABhgEA
+        Af8BAAGFAQAB/wEAAYUBAAH/AQABhAEAAf8BAAGDAQAB/wEAAYIBAAH/AQABggEAAf8BAAGBAQAB/wEA
+        AYABAAH/AQABgAEAAf8BAAEZAQAB/wEAARkBAAH/AQABGAEAAf8BAAEXAQAB/wEAARcBAAH/AQABFgEA
+        Af8BAAEWAQAB/wEAARUBAAH/AQABFQEAAf8BAAEUAQAB/wEAARQBAAH/AQABFAEAAf8BAAETAQAB/wFQ
+        AVEBUAGfAVABUQFQAZ8BAAGZAQAB/wEAAZgBAAH/AQABlwEAAf8BAAGXAQAB/wEAAZYBAAH/AQABlQEA
+        Af8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGPAQAB/wEA
+        AY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYwBAAH/AQABiwEAAf8BAAGKAQAB/wEAAY0BAAH/AR4BtQEe
+        Af8BvQHaAb0B/wHaAeoB2gH/Ad4B7AHeAf8BygHgAcoB/wGTAcEBkwH/AQABkQEAAf8BAAGDAQAB/wEA
+        AYIBAAH/AQABggEAAf8BAAGBAQAB/wEAAYABAAH/AQABgAEAAf8BAAEjAQAB/wEAASMBAAH/AQABIgEA
+        Af8BAAEhAQAB/wEAASEBAAH/AQABIAEAAf8BAAEgAQAB/wEAAR8BAAH/AQABHwEAAf8BAAEeAQAB/wEA
+        AR4BAAH/AQABHgEAAf8BAAEdAQAB/wFQAVEBUAGfwAABUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGZ
+        AQAB/wEpAX8BKgH+ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGUAQAB/wEpAX8BKQH+
+        AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGM
+        AQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGJAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGHAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGDAQAB/wEoAX8BKAH+AQABgQEAAf8BKAF/
+        ASgB/gEoAX8BKAH+AQABGAEAAf8BJwF/AScB/gEnAX4BJwH+AQABFwEAAf8BJwF9AScB/gEnAX0BJwH+
+        AQABFQEAAf8BJwF8AScB/gEnAXsBJwH+AQABFAEAAf8BJwF6AScB/gEnAXoBJwH+AVABUQFQAZ8BUAFR
+        AVABnwEqAX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEpAX8BKgH+ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+
+        ASkBfwEpAf4BAAGUAQAB/wEpAX8BKQH+AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+ASkBfwEpAf4BAAGO
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGJAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGHAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGD
+        AQAB/wEoAX8BKAH+AQABgQEAAf8BKAF/ASgB/gEoAX8BKAH+AQABGQEAAf8BJwF/AScB/gEnAX4BJwH+
+        AQABGAEAAf8BJwF9AScB/gEnAX0BJwH+AQABFgEAAf8BJwF8AScB/gEnAXsBJwH+AQABFQEAAf8BJwF6
+        AScB/gEnAXoBJwH+AVABUQFQAZ8BUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEpAX8BKgH+
+        ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGUAQAB/wEpAX8BKQH+AQABkgEAAf8BKQF/
+        ASkB/gEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGMAQAB/wFPAX8BTwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+AfMB+AHzAf8BewF/AXsB/gEpAX8BKQH+AQABgwEAAf8BKAF/
+        ASgB/gEAAYEBAAH/ASgBfwEoAf4BKAF/ASgB/gEAASMBAAH/AScBfwEnAf4BJwF+AScB/gEAASIBAAH/
+        AScBfQEnAf4BJwF9AScB/gEAASABAAH/AScBfAEnAf4BJwF7AScB/gEAAR8BAAH/AScBegEnAf4BJwF6
+        AScB/gFQAVEBUAGfwAABUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGXAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+AQABkwEAAf8BKQF/ASkB/gEp
+        AX8BKQH+ASkBfwEpAf4BAAGQAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGNAQAB/wEpAX8BKQH+ASgBfwEo
+        Af4BAAGLAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGEAQAB/wEoAX8BKAH+AQABggEAAf8BKAF/ASgB/gEoAX8BKAH+AQABgAEA
+        Af8BJwF/AScB/gEnAX8BJwH+AQABGAEAAf8BJwF+AScB/gEnAX0BJwH+AQABFgEAAf8BJwF8AScB/gEn
+        AXwBJwH+AQABFAEAAf8BJwF7AScB/gEnAXoBJwH+AVABUQFQAZ8BUAFRAVABnwEqAX8BKgH+ASoBfwEq
+        Af4BAAGaAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEp
+        AX8BKQH+AQABkwEAAf8BKQF/ASkB/gEpAX8BKQH+ASkBfwEpAf4BAAGQAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGNAQAB/wEpAX8BKQH+ASgBfwEoAf4BAAGLAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGIAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGEAQAB/wEoAX8BKAH+AQABggEA
+        Af8BKAF/ASgB/gEoAX8BKAH+AQABgAEAAf8BJwF/AScB/gEnAX8BJwH+AQABGQEAAf8BJwF+AScB/gEn
+        AX0BJwH+AQABFwEAAf8BJwF8AScB/gEnAXwBJwH+AQABFQEAAf8BJwF7AScB/gEnAXoBJwH+AVABUQFQ
+        AZ8BUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGXAQAB/wEp
+        AX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+AQABkwEAAf8BKQF/ASkB/gEpAX8BKQH+ASkBfwEp
+        Af4BAAGQAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/
+        Af4E/wN/Af4BZgF/AWYB/gEAAYQBAAH/ASgBfwEoAf4BAAGCAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGA
+        AQAB/wEnAX8BJwH+AScBfwEnAf4BAAEjAQAB/wEnAX4BJwH+AScBfQEnAf4BAAEhAQAB/wEnAXwBJwH+
+        AScBfAEnAf4BAAEfAQAB/wEnAXsBJwH+AScBegEnAf4BUAFRAVABn8AAAVABUQFQAZ8BAAGdAQAB/wEA
+        AZwBAAH/AQABmwEAAf8BAAGbAQAB/wEAAZoBAAH/AQABmQEAAf8BAAGYAQAB/wEAAZcBAAH/AQABlgEA
+        Af8BAAGVAQAB/wEAAZQBAAH/AZsBzQGbAf8B+wH9AftR/wH7AfwB+wH/AZsBxAGbAf8BAAGBAQAB/wEA
+        AYABAAH/AQABgAEAAf8BAAEYAQAB/wEAARcBAAH/AQABFwEAAf8BAAEWAQAB/wEAARYBAAH/AQABFQEA
+        Af8BAAEVAQAB/wEAARQBAAH/AVABUQFQAZ8BUAFRAVABnwEAAZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEA
+        AZsBAAH/AQABmgEAAf8BAAGZAQAB/wEAAZgBAAH/AQABlwEAAf8BAAGWAQAB/wEAAZUBAAH/AQABlAEA
+        Af8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZABAAH/AQABjwEAAf8BAAGOAQAB/wEA
+        AY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYsBAAH/AQABigEAAf8BAAGKAQAB/wEAAYkBAAH/AQABiAEA
+        Af8BAAGHAQAB/wEAAYYBAAH/AQABhgEAAf8BAAGFAQAB/wEAAYQBAAH/AQABgwEAAf8BAAGDAQAB/wEA
+        AYIBAAH/AQABgQEAAf8BAAGBAQAB/wEAAYABAAH/AQABgAEAAf8BAAEZAQAB/wEAARgBAAH/AQABGAEA
+        Af8BAAEXAQAB/wEAARcBAAH/AQABFgEAAf8BAAEWAQAB/wEAARUBAAH/AVABUQFQAZ8BUAFRAVABnwEA
+        AZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEAAZsBAAH/AQABmgEAAf8BAAGZAQAB/wEAAZgBAAH/AQABlwEA
+        Af8BAAGWAQAB/wEAAZUBAAH/AQABlAEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEA
+        AZABAAH/AQABjwEAAf8BgAG8AYAp/wHBAdwBwQH/AQABhQEAAf8BAAGEAQAB/wEAAYMBAAH/AQABgwEA
+        Af8BAAGCAQAB/wEAAYEBAAH/AQABgQEAAf8BAAGAAQAB/wEAAYABAAH/AQABIwEAAf8BAAEiAQAB/wEA
+        ASIBAAH/AQABIQEAAf8BAAEhAQAB/wEAASABAAH/AQABIAEAAf8BAAEfAQAB/wFQAVEBUAGfwAABUAFR
+        AVABnwEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+
+        ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+AQABlgEAAf8DfwH+A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gT/A38B/gN/Af4B+wH8AfsB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGAAQAB/wEnAX8BJwH+AScBfwEnAf4BAAEYAQAB/wEnAX4BJwH+AScBfQEn
+        Af4BAAEWAQAB/wEnAXwBJwH+AScBfAEnAf4BUAFRAVABnwFQAVEBUAGfASoBfwEqAf4BKgF/ASoB/gEA
+        AZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZoBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZcBAAH/ASkBfwEp
+        Af4BAAGWAQAB/wEpAX8BKQH+ASkBfwEpAf4BKQF/ASkB/gEAAZIBAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AZABAAH/ATYBfwE2Af4BegF/AXoB/gEXAbkBFwH/AXwBfwF8Af4BfAF/AXwB/gEWAbgBFgH/AXwBfwF8
+        Af4BcAF/AXAB/gEAAYkBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYYBAAH/ASgBfwEoAf4BAAGFAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGCAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGAAQAB/wEnAX8BJwH+AScBfwEn
+        Af4BAAEZAQAB/wEnAX4BJwH+AScBfQEnAf4BAAEXAQAB/wEnAXwBJwH+AScBfAEnAf4BUAFRAVABnwFQ
+        AVEBUAGfASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZoBAAH/ASoBfwEq
+        Af4BKgF/ASoB/gEAAZcBAAH/ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+ASkBfwEpAf4BKQF/ASkB/gEA
+        AZIBAAH/ASkBfwEpAf4BKQF/ASkB/gGPAcQBjwH/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/
+        A38B/gN/Af4BAAGGAQAB/wEoAX8BKAH+AQABhQEAAf8BKAF/ASgB/gEoAX8BKAH+AQABggEAAf8BKAF/
+        ASgB/gEoAX8BKAH+AQABgAEAAf8BJwF/AScB/gEnAX8BJwH+AQABIwEAAf8BJwF+AScB/gEnAX0BJwH+
+        AQABIQEAAf8BJwF8AScB/gEnAXwBJwH+AVABUQFQAZ/AAAFQAVEBUAGfAQABoAEAAf8BAAGfAQAB/wEA
+        AZ4BAAH/AQABnQEAAf8BAAGcAQAB/wEAAZwBAAH/AQABmwEAAf8BAAGaAQAB/wEAAZkBAAH/AQABmAEA
+        Af8BAAGXAQBh/wEAAYMBAAH/AQABggEAAf8BAAGBAQAB/wEAAYEBAAH/AQABgAEAAf8BAAGAAQAB/wEA
+        ARgBAAH/AQABFwEAAf8BAAEXAQAB/wEAARYBAAH/AQABFgEAAf8BUAFRAVABnwFQAVEBUAGfAQABoAEA
+        Af8BAAGfAQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGcAQAB/wEAAZwBAAH/AQABmwEAAf8BAAGaAQAB/wEA
+        AZkBAAH/AQABmAEAAf8BAAGXAQAB/wEAAZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZQBAAH/AQABkwEA
+        Af8BAAGSAQAB/wEAAZEBAAH/AQcBswEHGf8B/QH+Af0B/wEAAZIBAAH/AQABiQEAAf8BAAGIAQAB/wEA
+        AYcBAAH/AQABhgEAAf8BAAGGAQAB/wEAAYUBAAH/AQABhAEAAf8BAAGEAQAB/wEAAYMBAAH/AQABggEA
+        Af8BAAGBAQAB/wEAAYEBAAH/AQABgAEAAf8BAAGAAQAB/wEAARkBAAH/AQABGAEAAf8BAAEYAQAB/wEA
+        ARcBAAH/AQABFwEAAf8BUAFRAVABnwFQAVEBUAGfAQABoAEAAf8BAAGfAQAB/wEAAZ4BAAH/AQABnQEA
+        Af8BAAGcAQAB/wEAAZwBAAH/AQABmwEAAf8BAAGaAQAB/wEAAZkBAAH/AQABmAEAAf8BAAGXAQAB/wEA
+        AZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZQBAAH/AQABkwEAAf8BAAGSAQAB/wEAAakBAAH/Af0B/gH9
+        Jf8BmwHHAZsB/wEAAYcBAAH/AQABhgEAAf8BAAGGAQAB/wEAAYUBAAH/AQABhAEAAf8BAAGEAQAB/wEA
+        AYMBAAH/AQABggEAAf8BAAGBAQAB/wEAAYEBAAH/AQABgAEAAf8BAAGAAQAB/wEAASMBAAH/AQABIgEA
+        Af8BAAEiAQAB/wEAASEBAAH/AQABIQEAAf8BUAFRAVABn8AAAVABUQFQAZ8BKgF/ASoB/gEqAX8BKgH+
+        AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+AQABnQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmgEAAf8BKgF/
+        ASoB/gEAAZgBAAH/A38B/gN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4E/wN/Af4DfwT+Af8BKAF/ASgB/gEoAX8BKAH+AQABggEAAf8BKAF/
+        ASgB/gEoAX8BKAH+AQABgAEAAf8BJwF/ASgB/gEnAX8BJwH+AQABGAEAAf8BJwF+AScB/gEnAX0BJwH+
+        AVABUQFQAZ8BUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGfAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGd
+        AQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+AQABmAEAAf8BKQF/ASkB/gEpAX8BKQH+
+        ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGSAQAB/wFvAX8BbwH+A38B/gT/A38B/gN/
+        Af4E/wN/Af4DfwH+AQABlAEAAf8BKAF/ASgB/gEoAX8BKAH+AQABiAEAAf8BKAF/ASgB/gEAAYcBAAH/
+        ASgBfwEoAf4BKAF/ASgB/gEAAYUBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYIBAAH/ASgBfwEoAf4BKAF/
+        ASgB/gEAAYABAAH/AScBfwEoAf4BJwF/AScB/gEAARkBAAH/AScBfgEnAf4BJwF9AScB/gFQAVEBUAGf
+        AVABUQFQAZ8BKgF/ASoB/gEqAX8BKgH+AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+AQABnQEAAf8BKgF/
+        ASoB/gEqAX8BKgH+AQABmgEAAf8BKgF/ASoB/gEAAZgBAAH/ASkBfwEpAf4BKQF/ASkB/gEpAX8BKQH+
+        AQABlQEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkgEAAf8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+
+        BP8DfwH+ATUBfwE1Af4BAAGIAQAB/wEoAX8BKAH+AQABhwEAAf8BKAF/ASgB/gEoAX8BKAH+AQABhQEA
+        Af8BKAF/ASgB/gEoAX8BKAH+AQABggEAAf8BKAF/ASgB/gEoAX8BKAH+AQABgAEAAf8BJwF/ASgB/gEn
+        AX8BJwH+AQABIwEAAf8BJwF+AScB/gEnAX0BJwH+AVABUQFQAZ/AAAFQAVEBUAGfASoBfwEqAf4BKgF/
+        ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZsBAAH/
+        ASoBfwEqAf4BAAGaAQAB/wN/Af4DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/
+        A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+BP8DfwH+A38E/gH/ASgBfwEoAf4BKAF/ASgB/gEAAYQBAAH/
+        ASgBfwEoAf4BKAF/ASgB/gEAAYEBAAH/ASgBfwEoAf4BKAF/ASgB/gEAARgBAAH/AScBfwEnAf4BJwF+
+        AScB/gFQAVEBUAGfAVABUQFQAZ8BKgF/ASoB/gEqAX8BKgH+AQABoQEAAf8BKgF/ASoB/gEqAX8BKgH+
+        AQABngEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmwEAAf8BKgF/ASoB/gEAAZoBAAH/ASoBfwEqAf4BKQF/
+        ASoB/gEpAX8BKQH+AQABlgEAAf8BKQF/ASkB/gEpAX8BKQH+AQABlAEAAf8BbwF/AW8B/gN/Af4E/wN/
+        Af4DfwH+BP8DfwH+A38B/gEAAZUBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYoBAAH/ASgBfwEoAf4BAAGI
+        AQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGEAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGBAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAEZAQAB/wEnAX8BJwH+AScBfgEnAf4BUAFR
+        AVABnwFQAVEBUAGfASoBfwEqAf4BKgF/ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ4BAAH/
+        ASoBfwEqAf4BKgF/ASoB/gEAAZsBAAH/ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+ASkBfwEqAf4BKQF/
+        ASkB/gEAAZYBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZQBAAH/ASoBfwEqAf4BdQF/AXUB/gHbAewB2wH/
+        A38B/gN/Af4E/wN/Af4DfwH+AZcBxwGXAf8BMgF/ATIB/gEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEA
+        AYgBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYYBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYQBAAH/ASgBfwEo
+        Af4BKAF/ASgB/gEAAYEBAAH/ASgBfwEoAf4BKAF/ASgB/gEAASMBAAH/AScBfwEnAf4BJwF+AScB/gFQ
+        AVEBUAGfwAABUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGiAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGf
+        AQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+AQABmwEAAf8DfwH+A38B/gN/Af4E/wN/
+        Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gT/A38B/gN/
+        BP4B/wEoAX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGCAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGAAQAB/wEnAX8BJwH+AScBfwEnAf4BUAFRAVABnwFQAVEBUAGfASoBfwEqAf4BKgF/
+        ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ8BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/
+        ASoBfwEqAf4BAAGbAQAB/wEqAX8BKgH+ASoBfwEqAf4BKgF/ASoB/gEAAZgBAAH/ASkBfwEpAf4BKQF/
+        ASkB/gEAAZUBAAH/AW8BfwFvAf4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4BAAGWAQAB/wEpAX8BKQH+
+        ASgBfwEoAf4BAAGLAQAB/wEoAX8BKAH+AQABiQEAAf8BKAF/ASgB/gEoAX8BKAH+AQABhwEAAf8BKAF/
+        ASgB/gEoAX8BKAH+AQABhQEAAf8BKAF/ASgB/gEoAX8BKAH+AQABggEAAf8BKAF/ASgB/gEoAX8BKAH+
+        AQABgAEAAf8BJwF/AScB/gEnAX8BJwH+AVABUQFQAZ8BUAFRAVABnwEqAX8BKgH+ASoBfwEqAf4BAAGi
+        AQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGfAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+
+        AQABmwEAAf8BKgF/ASoB/gEqAX8BKgH+ASoBfwEqAf4BAAGYAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGV
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGUAQAB/wFJAX8BSQH+AWcBfwFnAf4BDwGyAQ8B/wFVAX8BVQH+
+        ATEBfwExAf4BAAGNAQAB/wEpAX8BKQH+ASgBfwEoAf4BAAGLAQAB/wEoAX8BKAH+AQABiQEAAf8BKAF/
+        ASgB/gEoAX8BKAH+AQABhwEAAf8BKAF/ASgB/gEoAX8BKAH+AQABhQEAAf8BKAF/ASgB/gEoAX8BKAH+
+        AQABggEAAf8BKAF/ASgB/gEoAX8BKAH+AQABgAEAAf8BJwF/AScB/gEnAX8BJwH+AVABUQFQAZ/AAAFQ
+        AVEBUAGfAQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEAAf8BAAGiAQAB/wEAAaEBAAH/AQABoAEA
+        Af8BAAGfAQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGcAQAR/wHeAe8B3gH/AQABpQEAAf8BAAGWAQAB/wEA
+        AZUBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZABAAH/AQABjwEA
+        Af8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGcAQAB/wHeAe0B3hH/AQABhwEAAf8BAAGGAQAB/wEA
+        AYYBAAH/AQABhQEAAf8BAAGEAQAB/wEAAYQBAAH/AQABgwEAAf8BAAGCAQAB/wEAAYIBAAH/AQABgQEA
+        Af8BAAGAAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGlAQAB/wEAAaQBAAH/AQABowEAAf8BAAGiAQAB/wEA
+        AaIBAAH/AQABoQEAAf8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/AQABmwEA
+        Af8BAAGbAQAB/wEAAZoBAAH/AQABmQEAAf8BAAGYAQAB/wEAAZcBAAH/AQABlgEAAf8BCQG4AQkZ/wP+
+        Af8BAAGYAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYsBAAH/AQABigEAAf8BAAGKAQAB/wEA
+        AYkBAAH/AQABiAEAAf8BAAGHAQAB/wEAAYYBAAH/AQABhgEAAf8BAAGFAQAB/wEAAYQBAAH/AQABhAEA
+        Af8BAAGDAQAB/wEAAYIBAAH/AQABggEAAf8BAAGBAQAB/wEAAYABAAH/AVABUQFQAZ8BUAFRAVABnwEA
+        AaUBAAH/AQABpAEAAf8BAAGjAQAB/wEAAaIBAAH/AQABogEAAf8BAAGhAQAB/wEAAaABAAH/AQABnwEA
+        Af8BAAGeAQAB/wEAAZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEAAZsBAAH/AQABmgEAAf8BAAGZAQAB/wEA
+        AZgBAAH/AQABlwEAAf8BAAGWAQAB/wEAAZUBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEA
+        Af8BAAGRAQAB/wEAAZABAAH/AQABjwEAAf8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEA
+        AYsBAAH/AQABigEAAf8BAAGKAQAB/wEAAYkBAAH/AQABiAEAAf8BAAGHAQAB/wEAAYYBAAH/AQABhgEA
+        Af8BAAGFAQAB/wEAAYQBAAH/AQABhAEAAf8BAAGDAQAB/wEAAYIBAAH/AQABggEAAf8BAAGBAQAB/wEA
+        AYABAAH/AVABUQFQAZ/AAAFQAVEBUAGfASsBfwErAf4BKwF/ASsB/gEAAaUBAAH/ASoBfwEqAf4BKgF/
+        ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ8BAAH/ASoBfwEqAf4BAAGeAQAB/wN/Af4DfwH+
+        A38B/gT/A38B/gEqAX8BKgH+AQABmAEAAf8BKQF/ASkB/gEpAX8BKQH+AQABlQEAAf8BKQF/ASkB/gEp
+        AX8BKQH+AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkAEAAf8BKQF/ASkB/gEpAX8BKQH+AQABjQEA
+        Af8DfwH+BP8DfwH+A38E/gH/ASgBfwEoAf4BKAF/ASgB/gEAAYcBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYUBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYMBAAH/ASgBfwEoAf4BKAF/ASgB/gFQAVEBUAGfAVABUQFQ
+        AZ8BKwF/ASsB/gErAX8BKwH+AQABpQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABogEAAf8BKgF/ASoB/gEq
+        AX8BKgH+AQABnwEAAf8BKgF/ASoB/gEAAZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEqAX8BKgH+AQABmgEA
+        Af8BKgF/ASoB/gEqAX8BKgH+AQABmAEAAf8BagF/AWoB/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gEA
+        AZcBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY0BAAH/ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGJAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGHAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGDAQAB/wEoAX8BKAH+ASgBfwEoAf4BUAFRAVABnwFQAVEBUAGfASsBfwEr
+        Af4BKwF/ASsB/gEAAaUBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEA
+        AZ8BAAH/ASoBfwEqAf4BAAGeAQAB/wEqAX8BKgH+ASoBfwEqAf4BKgF/ASoB/gEAAZoBAAH/ASoBfwEq
+        Af4BKgF/ASoB/gEAAZgBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZUBAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AZIBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZABAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY0BAAH/ASkBfwEp
+        Af4BAAGMAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGJAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGHAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGFAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGDAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BUAFRAVABn8AAAVABUQFQAZ8BKwF/ASsB/gErAX8BKwH+AQABpgEAAf8BKwF/ASsB/gEqAX8BKwH+
+        AQABowEAAf8BKgF/ASoB/gEqAX8BKgH+AQABoQEAAf8BKgF/ASoB/gEAAZ8BAAH/A38B/gN/Af4DfwH+
+        BP8DfwH+AUcBfwFHAf4BAAGZAQAB/wEpAX8BKgH+ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGUAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGeAQAB/wN/
+        Af4E/wN/Af4DfwT+Af8BKAF/ASgB/gEoAX8BKAH+AQABiAEAAf8BKAF/ASgB/gEoAX8BKAH+AQABhgEA
+        Af8BKAF/ASgB/gEoAX8BKAH+AQABhAEAAf8BKAF/ASgB/gEoAX8BKAH+AVABUQFQAZ8BUAFRAVABnwEr
+        AX8BKwH+ASsBfwErAf4BAAGmAQAB/wErAX8BKwH+ASoBfwErAf4BAAGjAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGhAQAB/wEqAX8BKgH+AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+ASoBfwEqAf4BAAGcAQAB/wEq
+        AX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEwAX8BMAH+AV8BfwFfAf4BAAGyAQAB/wFiAX8BYgH+AWIBfwFi
+        Af4BAAGwAQAB/wFiAX8BYgH+AVYBfwFWAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGPAQAB/wEp
+        AX8BKQH+AQABjQEAAf8BKAF/ASkB/gEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+AQABiAEA
+        Af8BKAF/ASgB/gEoAX8BKAH+AQABhgEAAf8BKAF/ASgB/gEoAX8BKAH+AQABhAEAAf8BKAF/ASgB/gEo
+        AX8BKAH+AVABUQFQAZ8BUAFRAVABnwErAX8BKwH+ASsBfwErAf4BAAGmAQAB/wErAX8BKwH+ASoBfwEr
+        Af4BAAGjAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGhAQAB/wEqAX8BKgH+AQABnwEAAf8BKgF/ASoB/gEq
+        AX8BKgH+ASoBfwEqAf4BAAGcAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEpAX8BKgH+ASkBfwEp
+        Af4BAAGWAQAB/wFMAX8BTAH+A38B/gHoAfMB6AH/AWoBfwFqAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEp
+        Af4BKQF/ASkB/gEAAY8BAAH/ASkBfwEpAf4BAAGNAQAB/wEoAX8BKQH+ASgBfwEoAf4BAAGKAQAB/wEo
+        AX8BKAH+ASgBfwEoAf4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGEAQAB/wEoAX8BKAH+ASgBfwEoAf4BUAFRAVABn8AAAVABUQFQAZ8BAAGpAQAB/wEAAagBAAH/
+        AQABpwEAAf8BAAGmAQAB/wEAAaUBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEAAf8BAAGh
+        AQAB/wEAAaABAGH/AQABiwEAAf8BAAGKAQAB/wEAAYkBAAH/AQABiAEAAf8BAAGIAQAB/wEAAYcBAAH/
+        AQABhgEAAf8BAAGFAQAB/wEAAYUBAAH/AQABhAEAAf8BAAGDAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGp
+        AQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaUBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/
+        AQABogEAAf8BAAGhAQAB/wEAAaABAAH/AQABnwEAAf8BAAGfAQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGc
+        AQAB/wEAAZsBAAH/AQABmgEAAf8BAAGZAQAB/wEAAZkBAAH/AQABmAEAAf8BAAGXAQAB/wEAAZYBAAH/
+        AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGP
+        AQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYwBAAH/AQABiwEAAf8BAAGKAQAB/wEAAYkBAAH/
+        AQABiAEAAf8BAAGIAQAB/wEAAYcBAAH/AQABhgEAAf8BAAGFAQAB/wEAAYUBAAH/AQABhAEAAf8BAAGD
+        AQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGpAQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaUBAAH/
+        AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEAAf8BAAGhAQAB/wEAAaABAAH/AQABnwEAAf8BAAGf
+        AQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGcAQAB/wEAAZsBAAH/AQABmgEAAf8BAAGZAQAB/wEAAZgBAAH/
+        AQABmAEAAf8BIQG/ASEJ/wGmAdIBpgH/AQABkwEAAf8BAAGSAQAB/wEAAZEBAAH/AQABkQEAAf8BAAGQ
+        AQAB/wEAAY8BAAH/AQABjgEAAf8BAAGNAQAB/wEAAYwBAAH/AQABjAEAAf8BAAGLAQAB/wEAAYoBAAH/
+        AQABiQEAAf8BAAGIAQAB/wEAAYgBAAH/AQABhwEAAf8BAAGGAQAB/wEAAYUBAAH/AQABhQEAAf8BAAGE
+        AQAB/wEAAYMBAAH/AVABUQFQAZ/AAAFQAVEBUAGfASsBfwErAf4BKwF/ASsB/gEAAagBAAH/ASsBfwEr
+        Af4BKwF/ASsB/gEAAaYBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaMBAAH/ASoBfwEqAf4BAAGiAQAB/wN/
+        Af4DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+
+        BP8DfwH+BP8DfwH+A38E/gH/ASkBfwEpAf4BKAF/ASgB/gEAAYoBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYgBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYYBAAH/ASgBfwEoAf4BKAF/ASgB/gFQAVEBUAGfAVABUQFQ
+        AZ8BKwF/ASsB/gErAX8BKwH+AQABqAEAAf8BKwF/ASsB/gErAX8BKwH+AQABpgEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABowEAAf8BKgF/ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEqAX8BKgH+AQABngEA
+        Af8BKgF/ASoB/gEqAX8BKgH+AQABnAEAAf8BUgF/AVIB/gN/Af4B1wHsAdcB/wN/Af4DfwH+AdcB6wHX
+        Af8DfwH+A38B/gEAAZcBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BAAGPAQAB/wEp
+        AX8BKQH+ASkBfwEpAf4BAAGNAQAB/wEpAX8BKQH+ASgBfwEoAf4BAAGKAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BUAFRAVABnwFQ
+        AVEBUAGfASsBfwErAf4BKwF/ASsB/gEAAagBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaYBAAH/ASsBfwEr
+        Af4BKwF/ASsB/gEAAaMBAAH/ASoBfwEqAf4BAAGiAQAB/wEqAX8BKgH+ASoBfwEqAf4BKgF/ASoB/gEA
+        AZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZwBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZkBAAH/A38B/gN/
+        Af4E/wN/Af4BKQF/ASkB/gEAAZQBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BAAGP
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGNAQAB/wEpAX8BKQH+ASgBfwEoAf4BAAGKAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BAAGIAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGGAQAB/wEoAX8BKAH+ASgBfwEoAf4BUAFR
+        AVABn8AAAVABUQFQAZ8BKwF/ASsB/gErAX8BKwH+AQABqgEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABpQEAAf8BKgF/ASoB/gEAAaMBAAH/A38B/gN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4E/wN/Af4DfwT+
+        Af8BKQF/ASkB/gEpAX8BKQH+AQABjAEAAf8BKAF/ASgB/gEoAX8BKAH+AQABiQEAAf8BKAF/ASgB/gEo
+        AX8BKAH+AQABhwEAAf8BKAF/ASgB/gEoAX8BKAH+AVABUQFQAZ8BUAFRAVABnwErAX8BKwH+ASsBfwEr
+        Af4BAAGqAQAB/wErAX8BKwH+ASsBfwErAf4BAAGnAQAB/wErAX8BKwH+ASsBfwErAf4BAAGlAQAB/wEq
+        AX8BKgH+AQABowEAAf8BKgF/ASoB/gEqAX8BKgH+ASoBfwEqAf4BAAGfAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGdAQAB/wFuAX8BbgH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+AQABoQEAAf8BKQF/ASkB/gEp
+        AX8BKQH+AQABkgEAAf8BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY4BAAH/ASkBfwEp
+        Af4BKQF/ASkB/gEAAYwBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/ASgBfwEoAf4BKAF/ASgB/gEA
+        AYcBAAH/ASgBfwEoAf4BKAF/ASgB/gFQAVEBUAGfAVABUQFQAZ8BKwF/ASsB/gErAX8BKwH+AQABqgEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+AQABpQEAAf8BKgF/ASoB/gEA
+        AaMBAAH/ASoBfwEqAf4BKgF/ASoB/gEqAX8BKgH+AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+AQABnQEA
+        Af8BKgF/ASoB/gEqAX8BKgH+AQABmgEAAf8DfwH+A38B/gT/A38B/gEqAX8BKgH+AQABlQEAAf8BKQF/
+        ASkB/gEpAX8BKQH+AQABkgEAAf8BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY4BAAH/
+        ASkBfwEpAf4BKQF/ASkB/gEAAYwBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/ASgBfwEoAf4BKAF/
+        ASgB/gEAAYcBAAH/ASgBfwEoAf4BKAF/ASgB/gFQAVEBUAGfwAABUAFRAVABnwEAAawBAAH/AQABrAEA
+        Af8BAAGrAQAB/wEAAaoBAAH/AQABqQEAAf8BAAGoAQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEA
+        AaUBAAH/AQABpAEAEf8B3gHwAd4B/wEAAawBAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/AQABnAEA
+        Af8BAAGbAQAB/wEAAZoBAAH/AQABmQEAAf8BAAGYAQAB/wEAAZcBAAH/AQABlgEAAf8BAAGVAQAB/wEA
+        AZUBAAH/AQABogEAAf8B3gHuAd4R/wEAAY8BAAH/AQABjgEAAf8BAAGNAQAB/wEAAYwBAAH/AQABiwEA
+        Af8BAAGKAQAB/wEAAYoBAAH/AQABiQEAAf8BAAGIAQAB/wEAAYcBAAH/AQABhwEAAf8BUAFRAVABnwFQ
+        AVEBUAGfAQABrAEAAf8BAAGsAQAB/wEAAasBAAH/AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/AQABqAEA
+        Af8BAAGnAQAB/wEAAaYBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABowEAAf8BAAGiAQAB/wEA
+        AaEBAAH/AQABoAEAAf8BAAGfAQAB/wEAAZ4BAAH/AQABsgEAAf8D/hn/AYoBxQGKAf8BAAGVAQAB/wEA
+        AZUBAAH/AQABlAEAAf8BAAGTAQAB/wEAAZIBAAH/AQABkQEAAf8BAAGQAQAB/wEAAY8BAAH/AQABjwEA
+        Af8BAAGOAQAB/wEAAY0BAAH/AQABjAEAAf8BAAGLAQAB/wEAAYoBAAH/AQABigEAAf8BAAGJAQAB/wEA
+        AYgBAAH/AQABhwEAAf8BAAGHAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGsAQAB/wEAAawBAAH/AQABqwEA
+        Af8BAAGqAQAB/wEAAakBAAH/AQABqAEAAf8BAAGoAQAB/wEAAacBAAH/AQABpgEAAf8BAAGlAQAB/wEA
+        AaQBAAH/AQABowEAAf8BAAGjAQAB/wEAAaIBAAH/AQABoQEAAf8BAAGgAQAB/wEAAZ8BAAH/AQABngEA
+        Af8BAAGdAQAB/wEAAZwBAAH/AQABnQEAAf8B5QHzAeUJ/wH4AfwB+AH/AQABnQEAAf8BAAGWAQAB/wEA
+        AZUBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGRAQAB/wEAAZABAAH/AQABjwEA
+        Af8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYsBAAH/AQABigEAAf8BAAGKAQAB/wEA
+        AYkBAAH/AQABiAEAAf8BAAGHAQAB/wEAAYcBAAH/AVABUQFQAZ/AAAFQAVEBUAGfASsBfwErAf4BKwF/
+        ASsB/gEAAawBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaoBAAH/ASsBfwErAf4BKwF/ASsB/gEAAacBAAH/
+        ASsBfwErAf4BAAGmAQAB/wN/Af4DfwH+A38B/gT/A38B/gEqAX8BKgH+AQABoAEAAf8BKgF/ASoB/gEq
+        AX8BKgH+AQABnQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmgEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmAEA
+        Af8BKQF/ASkB/gEpAX8BKQH+AQABlQEAAf8DfwH+BP8DfwH+A38E/gH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AY4BAAH/ASkBfwEpAf4BKQF/ASkB/gEAAYwBAAH/ASgBfwEoAf4BKAF/ASgB/gEAAYkBAAH/ASgBfwEo
+        Af4BKAF/ASgB/gFQAVEBUAGfAVABUQFQAZ8BKwF/ASsB/gErAX8BKwH+AQABrAEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABqgEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gEAAaYBAAH/ASsBfwEr
+        Af4BKgF/ASoB/gEqAX8BKgH+AQABogEAAf8BKgF/ASoB/gEqAX8BKgH+AQABoAEAAf8BMQF/ATEB/gN/
+        Af4E/wN/Af4DfwH+BP8DfwH+A38B/gH3AfsB9wH/AXIBfwFyAf4BKgF/ASoB/gEAAZUBAAH/ASkBfwEp
+        Af4BAAGTAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEp
+        AX8BKQH+ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGJAQAB/wEoAX8BKAH+ASgBfwEo
+        Af4BUAFRAVABnwFQAVEBUAGfASsBfwErAf4BKwF/ASsB/gEAAawBAAH/ASsBfwErAf4BKwF/ASsB/gEA
+        AaoBAAH/ASsBfwErAf4BKwF/ASsB/gEAAacBAAH/ASsBfwErAf4BAAGmAQAB/wErAX8BKwH+ASoBfwEq
+        Af4BKgF/ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaABAAH/ASoBfwEqAf4BKgF/ASoB/gEA
+        AagBAAH/A38B/gN/Af4E/wN/Af4BVgF/AVYB/gEAAZgBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZUBAAH/
+        ASkBfwEpAf4BAAGTAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGO
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGMAQAB/wEoAX8BKAH+ASgBfwEoAf4BAAGJAQAB/wEoAX8BKAH+
+        ASgBfwEoAf4BUAFRAVABn8AAAVABUQFQAZ8BKwF/ASsB/gErAX8BKwH+AQABrQEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABqwEAAf8BKwF/ASsB/gErAX8BKwH+AQABqAEAAf8BKwF/ASsB/gEAAacBAAH/A38B/gN/
+        Af4DfwH+BP8DfwH+AUcBfwFHAf4BAAGhAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGeAQAB/wEqAX8BKgH+
+        ASoBfwEqAf4BAAGcAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEqAX8BKgH+ASkBfwEpAf4BAAGk
+        AQAB/wN/Af4E/wN/Af4DfwT+Af8BKQF/ASkB/gEpAX8BKQH+AQABjwEAAf8BKQF/ASkB/gEpAX8BKQH+
+        AQABjQEAAf8BKQF/ASkB/gEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+AVABUQFQAZ8BUAFR
+        AVABnwErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGoAQAB/wErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+ASsBfwErAf4BAAGj
+        AQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGhAQAB/wEqAX8BKgH+AW0BfwFtAf4B/QH+Af0B/wN/Af4DfwH+
+        BP8DfwH+A38B/gT/A38B/gN/Af4BAAGXAQAB/wEpAX8BKQH+AQABlQEAAf8BKQF/ASkB/gEpAX8BKQH+
+        AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+AQABjwEAAf8BKQF/ASkB/gEpAX8BKQH+AQABjQEAAf8BKQF/
+        ASkB/gEoAX8BKAH+AQABigEAAf8BKAF/ASgB/gEoAX8BKAH+AVABUQFQAZ8BUAFRAVABnwErAX8BKwH+
+        ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+ASsBfwErAf4BAAGo
+        AQAB/wErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+ASsBfwErAf4BAAGjAQAB/wEqAX8BKgH+
+        ASoBfwEqAf4BAAGhAQAB/wEqAX8BKgH+ASoBfwEqAf4BGwHBARsB/wN/Af4DfwH+BP8DfwH+A38B/gEA
+        AZkBAAH/ASoBfwEqAf4BKQF/ASkB/gEAAZYBAAH/ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGSAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGPAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGNAQAB/wEp
+        AX8BKQH+ASgBfwEoAf4BAAGKAQAB/wEoAX8BKAH+ASgBfwEoAf4BUAFRAVABn8AAAVABUQFQAZ8BAAGw
+        AQAB/wEAAa8BAAH/AQABrgEAAf8BAAGtAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGrAQAB/wEAAaoBAAH/
+        AQABqgEAAf8BAAGpAQAB/wEAAagBAGH/AQABkgEAAf8BAAGSAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGP
+        AQAB/wEAAY4BAAH/AQABjQEAAf8BAAGMAQAB/wEAAYwBAAH/AQABiwEAAf8BAAGKAQAB/wFQAVEBUAGf
+        AVABUQFQAZ8BAAGwAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGtAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGr
+        AQAB/wEAAaoBAAH/AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaYBAAH/
+        AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEAAf8BAAGhAQAB/wEAAaABAAH/AYUByAGFAf8B/AH9
+        AfwZ/wH+Af8B/gH/AbAB2AGwAf8BAAGaAQAB/wEAAZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/
+        AQABkgEAAf8BAAGSAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGPAQAB/wEAAY4BAAH/AQABjQEAAf8BAAGM
+        AQAB/wEAAYwBAAH/AQABiwEAAf8BAAGKAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAGwAQAB/wEAAa8BAAH/
+        AQABrgEAAf8BAAGtAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGrAQAB/wEAAaoBAAH/AQABqgEAAf8BAAGp
+        AQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaYBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/
+        AQABogEAAf8BAAGhAQAB/wEAAaABAAH/AbQB3QG0Ef8BuQHeAbkB/wEAAZoBAAH/AQABmQEAAf8BAAGZ
+        AQAB/wEAAZgBAAH/AQABlwEAAf8BAAGWAQAB/wEAAZUBAAH/AQABlAEAAf8BAAGTAQAB/wEAAZIBAAH/
+        AQABkgEAAf8BAAGRAQAB/wEAAZABAAH/AQABjwEAAf8BAAGOAQAB/wEAAY0BAAH/AQABjAEAAf8BAAGM
+        AQAB/wEAAYsBAAH/AQABigEAAf8BUAFRAVABn8AAAVABUQFQAZ8BLAF/ASwB/gErAX8BKwH+AQABrwEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABrQEAAf8BKwF/ASsB/gErAX8BKwH+AQABqwEAAf8BKwF/ASsB/gEA
+        AakBAAH/A38B/gN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/
+        A38B/gN/Af4E/wN/Af4E/wN/Af4DfwT+Af8BKQF/ASkB/gEpAX8BKQH+AQABkgEAAf8BKQF/ASkB/gEp
+        AX8BKQH+AQABjwEAAf8BKQF/ASkB/gEpAX8BKQH+AQABjQEAAf8BKQF/ASkB/gEoAX8BKAH+AVABUQFQ
+        AZ8BUAFRAVABnwEsAX8BLAH+ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+AQABqQEAAf8BKwF/ASsB/gErAX8BKwH+ASsBfwEr
+        Af4BAAGmAQAB/wErAX8BKwH+ASsBfwErAf4BAAGjAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGhAQAB/wF7
+        AX8BewH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwT+Af8DfwH+AQABmQEAAf8BKQF/ASkB/gEpAX8BKQH+
+        AQABlQEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+AQABjwEAAf8BKQF/
+        ASkB/gEpAX8BKQH+AQABjQEAAf8BKQF/ASkB/gEoAX8BKAH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+
+        ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGr
+        AQAB/wErAX8BKwH+AQABqQEAAf8BKwF/ASsB/gErAX8BKwH+ASsBfwErAf4BAAGmAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGjAQAB/wEqAX8BKgH+ASwBfwEsAf4B7QH3Ae0B/wN/Af4DfwH+BP8DfwH+A38B/gEA
+        AZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZkBAAH/ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGVAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGSAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGPAQAB/wEp
+        AX8BKQH+ASkBfwEpAf4BAAGNAQAB/wEpAX8BKQH+ASgBfwEoAf4BUAFRAVABn8AAAVABUQFQAZ8BLAF/
+        ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABrAEAAf8BKwF/ASsB/gEAAaoBAAH/A38B/gN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/
+        Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4E/wN/Af4DfwL+Af8B/gH/ASkBfwEpAf4BKQF/
+        ASkB/gEAAZMBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY4BAAH/
+        ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/
+        ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+AQABrAEAAf8BKwF/ASsB/gEAAaoBAAH/
+        ASsBfwErAf4BKwF/ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+AQABpQEAAf8BKgF/
+        ASoB/gEqAX8BKgH+AQABogEAAf8BKwF/ASsB/gFfAX8BXwH+AewB9gHsAf8DfwH+A38B/gT/A38B/gN/
+        Af4E/wN/Af4BhwHFAYcB/wEpAX8BKQH+ASkBfwEpAf4BAAGWAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGT
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGRAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGOAQAB/wEpAX8BKQH+
+        ASkBfwEpAf4BUAFRAVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbABAAH/ASsBfwErAf4BKwF/
+        ASsB/gEAAa4BAAH/ASsBfwErAf4BKwF/ASsB/gEAAawBAAH/ASsBfwErAf4BAAGqAQAB/wErAX8BKwH+
+        ASsBfwErAf4BKwF/ASsB/gEAAacBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaUBAAH/ASoBfwEqAf4BUwF/
+        AVMB/gT/A38B/gN/Af4E/wN/Af4DfwH+AQABswEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmgEAAf8BKgF/
+        ASoB/gEAAZkBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZYBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/
+        ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAY4BAAH/ASkBfwEpAf4BKQF/
+        ASkB/gFQAVEBUAGfwAABUAFRAVABnwEAAbMBAAH/AQABsgEAAf8BAAGxAQAB/wEAAbEBAAH/AQABsAEA
+        Af8BAAGvAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGtAQAB/wEAAawBAAH/AQABrAEAEf8B3gHxAd4B/wEA
+        AbMBAAH/AQABpgEAAf8BAAGlAQAB/wEAAaQBAAH/AQABowEAAf8BAAGjAQAB/wEAAaIBAAH/AQABoQEA
+        Af8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZ0BAAH/AQABqQEAAf8B3gHwAd4R/wEA
+        AZYBAAH/AQABlgEAAf8BAAGVAQAB/wEAAZQBAAH/AQABkwEAAf8BAAGSAQAB/wEAAZEBAAH/AQABkAEA
+        Af8BAAGPAQAB/wEAAY8BAAH/AQABjgEAAf8BUAFRAVABnwFQAVEBUAGfAQABswEAAf8BAAGyAQAB/wEA
+        AbEBAAH/AQABsQEAAf8BAAGwAQAB/wEAAa8BAAH/AQABrwEAAf8BAAGuAQAB/wEAAa0BAAH/AQABrAEA
+        Af8BAAGsAQAB/wEAAasBAAH/AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/AQABqAEAAf8BAAGnAQAB/wEA
+        AaYBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABowEAAf8BAAGiAQAB/wEAAbABAAH/AecB9AHn
+        Gf8B8QH4AfIB/wEAAZ8BAAH/AQABmAEAAf8BAAGXAQAB/wEAAZYBAAH/AQABlgEAAf8BAAGVAQAB/wEA
+        AZQBAAH/AQABkwEAAf8BAAGSAQAB/wEAAZEBAAH/AQABkAEAAf8BAAGPAQAB/wEAAY8BAAH/AQABjgEA
+        Af8BUAFRAVABnwFQAVEBUAGfAQABswEAAf8BAAGyAQAB/wEAAbEBAAH/AQABsQEAAf8BAAGwAQAB/wEA
+        Aa8BAAH/AQABrwEAAf8BAAGuAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGsAQAB/wEAAasBAAH/AQABqgEA
+        Af8BAAGpAQAB/wEAAagBAAH/AQABqAEAAf8BAAGnAQAB/wEAAaYBAAH/AQABpQEAAf8BjAHOAYwZ/wGV
+        Ac8BlQH/AQABnQEAAf8BAAGdAQAB/wEAAZwBAAH/AQABmwEAAf8BAAGaAQAB/wEAAZkBAAH/AQABmAEA
+        Af8BAAGXAQAB/wEAAZYBAAH/AQABlgEAAf8BAAGVAQAB/wEAAZQBAAH/AQABkwEAAf8BAAGSAQAB/wEA
+        AZEBAAH/AQABkAEAAf8BAAGPAQAB/wEAAY8BAAH/AQABjgEAAf8BUAFRAVABn8AAAVABUQFQAZ8BLAF/
+        ASwB/gEsAX8BLAH+AQABsgEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABrgEAAf8BKwF/ASsB/gEAAa0BAAH/A38B/gN/Af4DfwH+BP8DfwH+ASsBfwErAf4BAAGnAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGlAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGiAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGgAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wN/Af4E/wN/Af4DfwL+Af8B/gH/ASkBfwEp
+        Af4BKQF/ASkB/gEAAZYBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AZEBAAH/ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABsgEA
+        Af8BLAF/ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gEA
+        Aa0BAAH/ASsBfwErAf4BKwF/ASsB/gErAX8BKwH+AQABqgEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABpQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABogEAAf8BZQF/AWUB/gN/
+        Af4E/wN/Af4DfwH+BP8DfwH+BP8BcgF/AXIB/gEqAX8BKgH+AQABmQEAAf8BKQF/ASkB/gEpAX8BKQH+
+        AQABlgEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkwEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkQEAAf8BKQF/
+        ASkB/gEpAX8BKQH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAGwAQAB/wErAX8BKwH+ASsBfwErAf4BAAGuAQAB/wErAX8BKwH+AQABrQEAAf8BKwF/
+        ASsB/gErAX8BKwH+ASsBfwErAf4BAAGqAQAB/wErAX8BKwH+ASsBfwErAf4BAAGnAQAB/wErAX8BKwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+AdAB6QHQAf8BKgF/ASoB/gEqAX8BKgH+AQABnQEAAf8BKgF/
+        ASoB/gEAAZsBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZkBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZYBAAH/
+        ASkBfwEpAf4BKQF/ASkB/gEAAZMBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZEBAAH/ASkBfwEpAf4BKQF/
+        ASkB/gFQAVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAGxAQAB/wEsAX8BLAH+ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+AQABrgEAAf8DfwH+A38B/gN/
+        Af4E/wN/Af4BSAF/AUgB/gEAAagBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaYBAAH/ASsBfwErAf4BKwF/
+        ASsB/gEAAaMBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAasBAAH/
+        A38B/gT/A38B/gN/Av4B/wH+Af8BKgF/ASoB/gEqAX8BKgH+AQABlwEAAf8BKQF/ASkB/gEpAX8BKQH+
+        AQABlQEAAf8BKQF/ASkB/gEpAX8BKQH+AQABkgEAAf8BKQF/ASkB/gEpAX8BKQH+AVABUQFQAZ8BUAFR
+        AVABnwEsAX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+
+        ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+ASsBfwErAf4BAAGr
+        AQAB/wE1AX8BNQH+ASwBfwEsAf4BAAGoAQAB/wErAX8BKwH+ASsBfwErAf4BAAGmAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGjAQAB/wEuAX8BLgH+A38B/gT/A38B/gN/Af4E/wN/Af4E/wN/Af4BKgF/ASoB/gEA
+        AZoBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZcBAAH/ASkBfwEpAf4BKQF/ASkB/gEAAZUBAAH/ASkBfwEp
+        Af4BKQF/ASkB/gEAAZIBAAH/ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEs
+        AX8BLAH+AQABswEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsQEAAf8BLAF/ASwB/gErAX8BKwH+AQABrwEA
+        Af8BKwF/ASsB/gEAAa4BAAH/ASsBfwErAf4BKwF/ASsB/gErAX8BKwH+AQABqwEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABqAEAAf8BNQF/ATUB/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gH5AfwB+QH/ATwBfwE8
+        Af4BKgF/ASoB/gEAAZ4BAAH/ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEq
+        AX8BKgH+ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEp
+        Af4BAAGSAQAB/wEpAX8BKQH+ASkBfwEpAf4BUAFRAVABn8AAAVABUQFQAZ8BAAG1AQAB/wEAAbUBAAH/
+        AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/AQABsgEAAf8BAAGyAQAB/wEAAbEBAAH/AQABsAEAAf8BAAGw
+        AQAB/wEAAa8BAGH/AQABmgEAAf8BAAGaAQAB/wEAAZkBAAH/AQABmAEAAf8BAAGXAQAB/wEAAZYBAAH/
+        AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/AQABkgEAAf8BAAGSAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG1
+        AQAB/wEAAbUBAAH/AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/AQABsgEAAf8BAAGyAQAB/wEAAbEBAAH/
+        AQABsAEAAf8BAAGwAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGuAQAB/wEAAa0BAAH/AQABuwEAAf8B8wH6
+        AfMB/wGbAdcBmwH/AQABsgEAAf8BAAGpAQAB/wEAAagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaYBAAH/
+        AQABpQEAAf8BAAGrAQAB/wHzAfkB8xn/AZsB0QGbAf8BAAGcAQAB/wEAAZsBAAH/AQABmgEAAf8BAAGa
+        AQAB/wEAAZkBAAH/AQABmAEAAf8BAAGXAQAB/wEAAZYBAAH/AQABlQEAAf8BAAGUAQAB/wEAAZMBAAH/
+        AQABkgEAAf8BAAGSAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG1AQAB/wEAAbUBAAH/AQABtAEAAf8BAAG0
+        AQAB/wEAAbMBAAH/AQABsgEAAf8BAAGyAQAB/wEAAbEBAAH/AQABsAEAAf8BAAGwAQAB/wEAAa8BAAH/
+        AQABrgEAAf8BAAGuAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGrAQAB/wEAAaoBAAH/AQABqgEAAf8BCAHA
+        AQgh/wEWAcEBFgH/AQABoAEAAf8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/
+        AQABmwEAAf8BAAGaAQAB/wEAAZoBAAH/AQABmQEAAf8BAAGYAQAB/wEAAZcBAAH/AQABlgEAAf8BAAGV
+        AQAB/wEAAZQBAAH/AQABkwEAAf8BAAGSAQAB/wEAAZIBAAH/AVABUQFQAZ/AAAFQAVEBUAGfASwBfwEs
+        Af4BLAF/ASwB/gEAAbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbMBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbEBAAH/ASwBfwEsAf4BAAGwAQAB/wN/Af4DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+BP8DfwH+A38C/gH/Af4B/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGaAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEp
+        AX8BKQH+ASkBfwEpAf4BUAFRAVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEs
+        Af4BLAF/ASwB/gEAAbMBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbEBAAH/ASwBfwEsAf4BAAGwAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BKwF/ASsB/gEAAb4BAAH/A38B/gN/Af4B9gH7AfYB/wN/Af4BeQF/AXkB/gEA
+        AbUBAAH/ATkBfwE5Af4BOQF/ATkB/gEAAbkBAAH/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+BP8DfwH+
+        ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGX
+        AQAB/wEpAX8BKQH+ASkBfwEpAf4BAAGVAQAB/wEpAX8BKQH+ASkBfwEpAf4BUAFRAVABnwFQAVEBUAGf
+        ASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbMBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbEBAAH/ASwBfwEsAf4BAAGwAQAB/wErAX8BKwH+ASsBfwErAf4BKwF/ASsB/gEAAa0BAAH/
+        ASsBfwErAf4BKwF/ASsB/gEAAasBAAH/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gEq
+        AX8BKgH+AQABoQEAAf8BKgF/ASoB/gEAAZ8BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/ASoBfwEq
+        Af4BKgF/ASoB/gEAAZoBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZcBAAH/ASkBfwEpAf4BKQF/ASkB/gEA
+        AZUBAAH/ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfwAABUAFRAVABnwEAAbcBAAH/AQABtwEAAf8BAAG2
+        AQAB/wEAAbUBAAH/AQABtQEAAf8BAAG0AQAB/wEAAbQBAAH/AQABswEAAf8BAAGyAQAB/wEAAbIBAAH/
+        AQABsQEAXf8B6gH1AeoB/wEAAZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEAAZoBAAH/AQABmgEAAf8BAAGZ
+        AQAB/wEAAZgBAAH/AQABlwEAAf8BAAGWAQAB/wEAAZUBAAH/AQABlAEAAf8BUAFRAVABnwFQAVEBUAGf
+        AQABtwEAAf8BAAG3AQAB/wEAAbYBAAH/AQABtQEAAf8BAAG1AQAB/wEAAbQBAAH/AQABtAEAAf8BAAGz
+        AQAB/wEAAbIBAAH/AQABsgEAAf8BAAGxAQAB/wEAAbABAAH/AQABsAEAAf8BAAGvAQAB/wEAAb8BABX/
+        Af0B/gH9Af8B9wH8AfcB/wH4AfwB+AH/A/4d/wH9Af4B/QH/AQABrwEAAf8BAAGfAQAB/wEAAZ4BAAH/
+        AQABnQEAAf8BAAGcAQAB/wEAAZsBAAH/AQABmgEAAf8BAAGaAQAB/wEAAZkBAAH/AQABmAEAAf8BAAGX
+        AQAB/wEAAZYBAAH/AQABlQEAAf8BAAGUAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG3AQAB/wEAAbcBAAH/
+        AQABtgEAAf8BAAG1AQAB/wEAAbUBAAH/AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/AQABsgEAAf8BAAGy
+        AQAB/wEAAbEBAAH/AQABsAEAAf8BAAGwAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGuAQAB/wEAAa0BAAH/
+        AQABrQEAAf8B3gHyAd4h/wHtAfcB7QH/AQABpgEAAf8BAAGiAQAB/wEAAaEBAAH/AQABoQEAAf8BAAGg
+        AQAB/wEAAZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/AQABmwEAAf8BAAGaAQAB/wEAAZoBAAH/
+        AQABmQEAAf8BAAGYAQAB/wEAAZcBAAH/AQABlgEAAf8BAAGVAQAB/wEAAZQBAAH/AVABUQFQAZ/AAAFQ
+        AVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbcBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEs
+        Af4BLAF/ASwB/gEAAbMBAAH/ASwBfwEsAf4BAAGyAQAB/wN/Af4DfwH+A38B/gT/A38B/gN/Af4E/wN/
+        Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+BP8DfwH+A38B/gEAAbkBAAH/
+        ASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZoBAAH/ASoBfwEqAf4BKgF/
+        ASoB/gEAAZcBAAH/ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+
+        AQABtwEAAf8BLAF/ASwB/gEsAX8BLAH+AQABtQEAAf8BLAF/ASwB/gEsAX8BLAH+AQABswEAAf8BLAF/
+        ASwB/gEAAbIBAAH/ASwBfwEsAf4BLAF/ASwB/gErAX8BKwH+AQABwAEAAf8DfwH+A38B/gT/A38B/gN/
+        Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4BvAHiAbwB/wErAX8BKwH+ASoBfwEq
+        Af4BAAGfAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGaAQAB/wEq
+        AX8BKgH+ASoBfwEqAf4BAAGXAQAB/wEpAX8BKQH+ASkBfwEpAf4BUAFRAVABnwFQAVEBUAGfASwBfwEs
+        Af4BLAF/ASwB/gEAAbcBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbMBAAH/ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+ASwBfwEsAf4BKwF/ASsB/gEAAa8BAAH/ASsBfwEr
+        Af4BKwF/ASsB/gEAAbcBAAH/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gFYAX8BWAH+
+        AQABpAEAAf8BKgF/ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ8BAAH/ASoBfwEqAf4BKgF/
+        ASoB/gEAAZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZoBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZcBAAH/
+        ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEs
+        AX8BLAH+ASwBfwEsAf4BAAG2AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG0AQAB/wEsAX8BLAH+AQABswEA
+        Af8DfwH+A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gT/A38B/gN/Af4BAAGhAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGeAQAB/wEqAX8BKgH+
+        ASoBfwEqAf4BAAGbAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGZAQAB/wEpAX8BKQH+ASkBfwEpAf4BUAFR
+        AVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbYBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEAAbQBAAH/ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEsAf4BLAF/
+        ASwB/gEAAcABAAH/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+
+        BP8DfwH+AQABrAEAAf8BKgF/ASoB/gEqAX8BKgH+AQABoQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABngEA
+        Af8BKgF/ASoB/gEqAX8BKgH+AQABmwEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmQEAAf8BKQF/ASkB/gEp
+        AX8BKQH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAG2AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG0AQAB/wEsAX8BLAH+AQABswEAAf8BLAF/ASwB/gEs
+        AX8BLAH+ASwBfwEsAf4BAAGwAQAB/wErAX8BKwH+ASsBfwErAf4BFgHJARYB/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+AQABpQEAAf8BKgF/ASoB/gEAAaMBAAH/ASoBfwEqAf4BKgF/
+        ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZsBAAH/
+        ASoBfwEqAf4BKgF/ASoB/gEAAZkBAAH/ASkBfwEpAf4BKQF/ASkB/gFQAVEBUAGfwAABUAFRAVABnwEA
+        AbkBAAH/AQABuQEAAf8BAAG4AQAB/wEAAbgBAAH/AQABtwEAAf8BAAG3AQAB/wEAAbYBAAH/AQABtgEA
+        Af8BAAG1AQAB/wEAAbUBAAH/AQABtAEAUf8D/gH/AYoBzAGKAf8BAAGjAQAB/wEAAaIBAAH/AQABoQEA
+        Af8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGeAQAB/wEAAZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEA
+        AZoBAAH/AQABmQEAAf8BAAGYAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG5AQAB/wEAAbkBAAH/AQABuAEA
+        Af8BAAG4AQAB/wEAAbcBAAH/AQABtwEAAf8BAAG2AQAB/wEAAbYBAAH/AQABtQEAAf8BAAG1AQAB/wEA
+        AbQBAAH/AQABswEAAf8BAAGzAQAB/wEAAbIBAAH/AQABuQEAAf8B2QHxAdkB/wH9Af4B/S3/AfsB/QH7
+        Af8BsAHeAbAB/wEAAa0BAAH/AQABpAEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEAAf8BAAGhAQAB/wEA
+        AaABAAH/AQABnwEAAf8BAAGeAQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGcAQAB/wEAAZsBAAH/AQABmgEA
+        Af8BAAGZAQAB/wEAAZgBAAH/AVABUQFQAZ8BUAFRAVABnwEAAbkBAAH/AQABuQEAAf8BAAG4AQAB/wEA
+        AbgBAAH/AQABtwEAAf8BAAG3AQAB/wEAAbYBAAH/AQABtgEAAf8BAAG1AQAB/wEAAbUBAAH/AQABtAEA
+        Af8BAAGzAQAB/wEAAbMBAAH/AQABsgEAAf8BAAGxAQAB/wEAAbEBAAH/AQABsAEAAf8BlwHYAZcp/wG1
+        AeABtQH/AQABpgEAAf8BAAGlAQAB/wEAAaQBAAH/AQABpAEAAf8BAAGjAQAB/wEAAaIBAAH/AQABoQEA
+        Af8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGeAQAB/wEAAZ0BAAH/AQABnAEAAf8BAAGbAQAB/wEA
+        AZoBAAH/AQABmQEAAf8BAAGYAQAB/wFQAVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG5
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG2AQAB/wEsAX8BLAH+
+        AQABtQEAAf8DfwH+A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+
+        BP8DfwH+A38B/gT/A38B/gGKAc4BigH/ASsBfwErAf4BKgF/ASsB/gEAAaMBAAH/ASoBfwEqAf4BKgF/
+        ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZsBAAH/
+        ASoBfwEqAf4BKgF/ASoB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABuQEAAf8BLAF/
+        ASwB/gEsAX8BLAH+AQABuAEAAf8BLAF/ASwB/gEsAX8BLAH+AQABtgEAAf8BLAF/ASwB/gEAAbUBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEsAX8BLAH+AQABsgEAAf8BLQF/AS0B/gFHAX8BRwH+ARUBzgEVAf8DfwH+
+        A38B/gHqAfcB6gH/A38B/gN/Af4B+AH8AfgB/wN/Af4DfwH+AcUB6AHFAf8DfwH+AUoBfwFKAf4BAAGn
+        AQAB/wErAX8BKwH+AQABpgEAAf8BKwF/ASsB/gEqAX8BKwH+AQABowEAAf8BKgF/ASoB/gEqAX8BKgH+
+        AQABoQEAAf8BKgF/ASoB/gEqAX8BKgH+AQABngEAAf8BKgF/ASoB/gEqAX8BKgH+AQABmwEAAf8BKgF/
+        ASoB/gEqAX8BKgH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG5AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG2AQAB/wEsAX8BLAH+AQABtQEAAf8BLAF/
+        ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+ASwBfwEsAf4BsQHiAbEB/wN/Af4DfwH+
+        BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+AQABpwEAAf8BKwF/ASsB/gEAAaYBAAH/ASsBfwEr
+        Af4BKgF/ASsB/gEAAaMBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gEA
+        AZ4BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZsBAAH/ASoBfwEqAf4BKgF/ASoB/gFQAVEBUAGfwAABUAFR
+        AVABnwEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG3AQAB/wEsAX8BLAH+AQABtgEAAf8DfwH+A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+
+        A38B/gT/A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gH6Af0B+gH/A38B/gEAAacBAAH/ASsBfwEr
+        Af4BKwF/ASsB/gEAAaQBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEA
+        AZ8BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/ASoBfwEqAf4BKgF/ASoB/gFQAVEBUAGfAVABUQFQ
+        AZ8BLAF/ASwB/gEsAX8BLAH+AQABugEAAf8BLAF/ASwB/gEsAX8BLAH+AQABuAEAAf8BLAF/ASwB/gEs
+        AX8BLAH+AQABtwEAAf8BLAF/ASwB/gEAAbYBAAH/ASwBfwEsAf4BLAF/ASwB/gEsAX8BLAH+AQABswEA
+        Af8BLAF/ASwB/gEsAX8BLAH+AQABsQEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsQEAAf8BNwF/ATcB/gE7
+        AX8BOwH+AQABswEAAf8BNgF/ATYB/gEuAX8BLgH+AQABqwEAAf8BKwF/ASsB/gErAX8BKwH+AQABqQEA
+        Af8BKwF/ASsB/gEAAacBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaQBAAH/ASoBfwEqAf4BKgF/ASoB/gEA
+        AaIBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ8BAAH/ASoBfwEqAf4BKgF/ASoB/gEAAZ0BAAH/ASoBfwEq
+        Af4BKgF/ASoB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABugEAAf8BLAF/ASwB/gEs
+        AX8BLAH+AQABuAEAAf8BLAF/ASwB/gEsAX8BLAH+AQABtwEAAf8BLAF/ASwB/gEAAbYBAAH/ASwBfwEs
+        Af4BLAF/ASwB/gEsAX8BLAH+AQABswEAAf8BLAF/ASwB/gEsAX8BLAH+AbsB5gG7Af8DfwH+A38B/gT/
+        A38B/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gEAAakBAAH/ASsBfwErAf4BAAGnAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGkAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGiAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGf
+        AQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGdAQAB/wEqAX8BKgH+ASoBfwEqAf4BUAFRAVABn8AAAVABUQFQ
+        AZ8BAAG7AQAB/wEAAbsBAAH/AQABugEAAf8BAAG6AQAB/wEAAbkBAAH/AQABuQEAAf8BAAG5AQAB/wEA
+        AbgBAAH/AQABuAEAAf8BAAG3AQAB/wEAAbcBAAH/AZ0B3QGdAf8B+wH9AfsB/wH+Af8B/gX/Af4B/wH+
+        Af8B/gH/Af4F/wH+Af8B/gH/Af4B/wH+Bf8B/gH/Af4B/wH+Af8B/gX/Af4B/wH+Af8B/gH/Af4F/wH+
+        Af8B/gH/AeoB9gHqAf8BAAHBAQAB/wEAAakBAAH/AQABqAEAAf8BAAGnAQAB/wEAAaYBAAH/AQABpgEA
+        Af8BAAGlAQAB/wEAAaQBAAH/AQABowEAAf8BAAGiAQAB/wEAAaEBAAH/AQABoQEAAf8BAAGgAQAB/wEA
+        AZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/AVABUQFQAZ8BUAFRAVABnwEAAbsBAAH/AQABuwEA
+        Af8BAAG6AQAB/wEAAboBAAH/AQABuQEAAf8BAAG5AQAB/wEAAbkBAAH/AQABuAEAAf8BAAG4AQAB/wEA
+        AbcBAAH/AQABtwEAAf8BAAG2AQAB/wEAAbUBAAH/AQABtQEAAf8BAAG0AQAB/wEAAbQBAAH/AQABswEA
+        Af8BAAGyAQAB/wEAAbIBAAH/AQABsQEAAf8BAAGwAQAB/wEAAbABAAH/AQABrwEAAf8BAAGuAQAB/wEA
+        Aa4BAAH/AQABrQEAAf8BAAGsAQAB/wEAAasBAAH/AQABqwEAAf8BAAGqAQAB/wEAAakBAAH/AQABqAEA
+        Af8BAAGnAQAB/wEAAaYBAAH/AQABpgEAAf8BAAGlAQAB/wEAAaQBAAH/AQABowEAAf8BAAGiAQAB/wEA
+        AaEBAAH/AQABoQEAAf8BAAGgAQAB/wEAAZ8BAAH/AQABngEAAf8BAAGdAQAB/wEAAZwBAAH/AVABUQFQ
+        AZ8BUAFRAVABnwEAAbsBAAH/AQABuwEAAf8BAAG6AQAB/wEAAboBAAH/AQABuQEAAf8BAAG5AQAB/wEA
+        AbkBAAH/AQABuAEAAf8BAAG4AQAB/wEAAbcBAAH/AQABtwEAAf8BAAG2AQAB/wEAAbUBAAH/AQABtQEA
+        Af8BAAG0AQAB/wEAAbQBAAH/AQABswEAAf8BoQHdAaEp/wHIAekByAH/AQABqgEAAf8BAAGpAQAB/wEA
+        AagBAAH/AQABpwEAAf8BAAGmAQAB/wEAAaYBAAH/AQABpQEAAf8BAAGkAQAB/wEAAaMBAAH/AQABogEA
+        Af8BAAGhAQAB/wEAAaEBAAH/AQABoAEAAf8BAAGfAQAB/wEAAZ4BAAH/AQABnQEAAf8BAAGcAQAB/wFQ
+        AVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG6
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+AQABtwEAAf8BLAF/ASwB/gEsAX8BLAH+
+        ASwBfwEsAf4BAAG1AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGx
+        AQAB/wEsAX8BLAH+ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+AQABqQEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/
+        ASsB/gErAX8BKwH+AQABpAEAAf8BKgF/ASoB/gEqAX8BKgH+AQABogEAAf8BKgF/ASoB/gEqAX8BKgH+
+        AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+
+        AQABtwEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG1AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGz
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+AQABqQEAAf8BKwF/
+        ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+AQABpAEAAf8BKgF/ASoB/gEqAX8BKgH+
+        AQABogEAAf8BKgF/ASoB/gEqAX8BKgH+AQABnwEAAf8BKgF/ASoB/gEqAX8BKgH+AVABUQFQAZ8BUAFR
+        AVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+AQABtwEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG1
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAHAAQAB/wN/Af4DfwH+BP8DfwH+A38B/gT/A38B/gN/Af4E/wN/
+        Af4BagF/AWoB/gEAAasBAAH/ASsBfwErAf4BAAGpAQAB/wErAX8BKwH+ASsBfwErAf4BAAGnAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGkAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGiAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BAAGfAQAB/wEqAX8BKgH+ASoBfwEqAf4BUAFRAVABn8AAAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+
+        AQABuwEAAf8BLAF/ASwB/gEsAX8BLAH+AQABugEAAf8BLAF/ASwB/gEsAX8BLAH+AQABuQEAAf8BLAF/
+        ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEsAX8BLAH+AQABtgEAAf8BLAF/ASwB/gEsAX8BLAH+
+        AQABtAEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsgEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/
+        ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+AQABrAEAAf8BKwF/ASsB/gEAAasBAAH/
+        ASsBfwErAf4BKwF/ASsB/gEAAagBAAH/ASsBfwErAf4BKwF/ASsB/gEAAaYBAAH/ASsBfwErAf4BKgF/
+        ASsB/gEAAaMBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaEBAAH/ASoBfwEqAf4BKgF/ASoB/gFQAVEBUAGf
+        AVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABuwEAAf8BLAF/ASwB/gEsAX8BLAH+AQABugEAAf8BLAF/
+        ASwB/gEsAX8BLAH+AQABuQEAAf8BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEsAX8BLAH+
+        AQABtgEAAf8BLAF/ASwB/gEsAX8BLAH+AQABtAEAAf8BLAF/ASwB/gEsAX8BLAH+AQABsgEAAf8BLAF/
+        ASwB/gEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABrAEAAf8BKwF/ASsB/gEAAasBAAH/ASsBfwErAf4BKwF/ASsB/gEAAagBAAH/ASsBfwErAf4BKwF/
+        ASsB/gEAAaYBAAH/ASsBfwErAf4BKgF/ASsB/gEAAaMBAAH/ASoBfwEqAf4BKgF/ASoB/gEAAaEBAAH/
+        ASoBfwEqAf4BKgF/ASoB/gFQAVEBUAGfAVABUQFQAZ8BLAF/ASwB/gEsAX8BLAH+AQABuwEAAf8BLAF/
+        ASwB/gEsAX8BLAH+AQABugEAAf8BLAF/ASwB/gEsAX8BLAH+AQABuQEAAf8BLAF/ASwB/gEAAbgBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEsAX8BLAH+AQABtgEAAf8BLAF/ASwB/gEsAX8BLAH+AQABtAEAAf8BaQF/
+        AWkB/gN/Af4E/wN/Af4DfwH+BP8DfwH+A38B/gHzAfoB8wH/AXwBfwF8Af4BLAF/ASwB/gEAAawBAAH/
+        ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+ASsBfwErAf4BAAGoAQAB/wErAX8BKwH+ASsBfwErAf4BAAGm
+        AQAB/wErAX8BKwH+ASoBfwErAf4BAAGjAQAB/wEqAX8BKgH+ASoBfwEqAf4BAAGhAQAB/wEqAX8BKgH+
+        ASoBfwEqAf4BUAFRAVABn8AAAVABUQFQAZ8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEA
+        AbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAboBAAH/AQABugEAAf8BAAG5AQAB/wEAAbkBAAH/AQABuAEA
+        Af8BAAG4AQAB/wEAAbcBAAH/AQABtwEAAf8BAAG2AQAB/wEAAbYBAAH/AQABtQEAAf8BAAG1AQAB/wEA
+        AbQBAAH/AQABswEAAf8BAAGzAQAB/wEAAbIBAAH/AQABsgEAAf8BAAGxAQAB/wEAAbABAAH/AQABrwEA
+        Af8BAAGvAQAB/wEAAa4BAAH/AQABrQEAAf8BAAGtAQAB/wEAAawBAAH/AQABqwEAAf8BAAGqAQAB/wEA
+        AakBAAH/AQABqQEAAf8BAAGoAQAB/wEAAacBAAH/AQABpgEAAf8BAAGlAQAB/wEAAaQBAAH/AQABpAEA
+        Af8BAAGjAQAB/wEAAaIBAAH/AQABoQEAAf8BAAGgAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG7AQAB/wEA
+        AbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAboBAAH/AQABugEA
+        Af8BAAG5AQAB/wEAAbkBAAH/AQABuAEAAf8BAAG4AQAB/wEAAbcBAAH/AQABtwEAAf8BAAG2AQAB/wEA
+        AbYBAAH/AQABtQEAAf8BAAG1AQAB/wEAAbQBAAH/AQABswEAAf8BAAGzAQAB/wEAAbIBAAH/AQABsgEA
+        Af8BAAGxAQAB/wEAAbABAAH/AQABrwEAAf8BAAGvAQAB/wEAAa4BAAH/AQABrQEAAf8BAAGtAQAB/wEA
+        AawBAAH/AQABqwEAAf8BAAGqAQAB/wEAAakBAAH/AQABqQEAAf8BAAGoAQAB/wEAAacBAAH/AQABpgEA
+        Af8BAAGlAQAB/wEAAaQBAAH/AQABpAEAAf8BAAGjAQAB/wEAAaIBAAH/AQABoQEAAf8BAAGgAQAB/wFQ
+        AVEBUAGfAVABUQFQAZ8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABuwEA
+        Af8BAAG7AQAB/wEAAboBAAH/AQABugEAAf8BAAG5AQAB/wEAAbkBAAH/AQABuAEAAf8BAAG4AQAB/wEA
+        AbcBAAH/AQABtwEAAf8BAAG2AQAB/wEAAbYBAAH/AQABtQEAAf8BAAG1AQAB/wEAAbkBAAH/AYYB0wGG
+        Af8BuQHmAbkB/wHRAe4B0QH/AdMB7wHTAf8BvQHmAb0B/wGMAdQBjAH/AQABtwEAAf8BAAGvAQAB/wEA
+        Aa4BAAH/AQABrQEAAf8BAAGtAQAB/wEAAawBAAH/AQABqwEAAf8BAAGqAQAB/wEAAakBAAH/AQABqQEA
+        Af8BAAGoAQAB/wEAAacBAAH/AQABpgEAAf8BAAGlAQAB/wEAAaQBAAH/AQABpAEAAf8BAAGjAQAB/wEA
+        AaIBAAH/AQABoQEAAf8BAAGgAQAB/wFQAVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+
+        AQABugEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG2
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG0AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAGwAQAB/wErAX8BKwH+ASsBfwErAf4BAAGuAQAB/wErAX8BKwH+AQABrQEAAf8BKwF/
+        ASsB/gErAX8BKwH+AQABqwEAAf8BKwF/ASsB/gErAX8BKwH+AQABqAEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABpgEAAf8BKwF/ASsB/gEqAX8BKwH+AQABowEAAf8BKgF/ASoB/gEqAX8BKgH+AVABUQFQAZ8BUAFR
+        AVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+AQABugEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG4
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG2AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG0AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGwAQAB/wErAX8BKwH+ASsBfwErAf4BAAGu
+        AQAB/wErAX8BKwH+AQABrQEAAf8BKwF/ASsB/gErAX8BKwH+AQABqwEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABqAEAAf8BKwF/ASsB/gErAX8BKwH+AQABpgEAAf8BKwF/ASsB/gEqAX8BKwH+AQABowEAAf8BKgF/
+        ASoB/gEqAX8BKgH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+AQABugEAAf8BLAF/
+        ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG2AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BAAG0AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGyAQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGw
+        AQAB/wErAX8BKwH+ASsBfwErAf4BAAGuAQAB/wErAX8BKwH+AQABrQEAAf8BKwF/ASsB/gErAX8BKwH+
+        AQABqwEAAf8BKwF/ASsB/gErAX8BKwH+AQABqAEAAf8BKwF/ASsB/gErAX8BKwH+AQABpgEAAf8BKwF/
+        ASsB/gEqAX8BKwH+AQABowEAAf8BKgF/ASoB/gEqAX8BKgH+AVABUQFQAZ/AAAFQAVEBUAGfASwBfwEs
+        Af4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbsBAAH/ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BLAF/ASwB/gEAAbgBAAH/ASwBfwEs
+        Af4BLAF/ASwB/gEAAbcBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbMBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbEBAAH/ASwBfwEsAf4BKwF/ASsB/gEAAa8BAAH/ASsBfwEr
+        Af4BAAGuAQAB/wErAX8BKwH+ASsBfwErAf4BAAGsAQAB/wErAX8BKwH+ASsBfwErAf4BAAGpAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGnAQAB/wErAX8BKwH+ASsBfwErAf4BAAGkAQAB/wEqAX8BKgH+ASoBfwEq
+        Af4BUAFRAVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbcBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbMBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbEBAAH/ASwBfwEs
+        Af4BKwF/ASsB/gEAAa8BAAH/ASsBfwErAf4BAAGuAQAB/wErAX8BKwH+ASsBfwErAf4BAAGsAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGpAQAB/wErAX8BKwH+ASsBfwErAf4BAAGnAQAB/wErAX8BKwH+ASsBfwEr
+        Af4BAAGkAQAB/wEqAX8BKgH+ASoBfwEqAf4BUAFRAVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEA
+        AbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEs
+        Af4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEA
+        AbcBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbUBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbMBAAH/ASwBfwEs
+        Af4BLAF/ASwB/gEAAbEBAAH/ASwBfwEsAf4BKwF/ASsB/gEAAa8BAAH/ASsBfwErAf4BAAGuAQAB/wEr
+        AX8BKwH+ASsBfwErAf4BAAGsAQAB/wErAX8BKwH+ASsBfwErAf4BAAGpAQAB/wErAX8BKwH+ASsBfwEr
+        Af4BAAGnAQAB/wErAX8BKwH+ASsBfwErAf4BAAGkAQAB/wEqAX8BKgH+ASoBfwEqAf4BUAFRAVABn8AA
+        AVABUQFQAZ8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7
+        AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABugEAAf8BAAG6AQAB/wEAAboBAAH/
+        AQABuQEAAf8BAAG5AQAB/wEAAbgBAAH/AQABuAEAAf8BAAG3AQAB/wEAAbcBAAH/AQABtgEAAf8BAAG2
+        AQAB/wEAAbUBAAH/AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/AQABswEAAf8BAAGyAQAB/wEAAbEBAAH/
+        AQABsQEAAf8BAAGwAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGuAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGr
+        AQAB/wEAAasBAAH/AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/AQABpwEAAf8BAAGnAQAB/wEAAaYBAAH/
+        AQABpQEAAf8BAAGkAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7
+        AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/
+        AQABugEAAf8BAAG6AQAB/wEAAboBAAH/AQABuQEAAf8BAAG5AQAB/wEAAbgBAAH/AQABuAEAAf8BAAG3
+        AQAB/wEAAbcBAAH/AQABtgEAAf8BAAG2AQAB/wEAAbUBAAH/AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/
+        AQABswEAAf8BAAGyAQAB/wEAAbEBAAH/AQABsQEAAf8BAAGwAQAB/wEAAa8BAAH/AQABrgEAAf8BAAGu
+        AQAB/wEAAa0BAAH/AQABrAEAAf8BAAGrAQAB/wEAAasBAAH/AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/
+        AQABpwEAAf8BAAGnAQAB/wEAAaYBAAH/AQABpQEAAf8BAAGkAQAB/wFQAVEBUAGfAVABUQFQAZ8BAAG7
+        AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/
+        AQABuwEAAf8BAAG7AQAB/wEAAbsBAAH/AQABugEAAf8BAAG6AQAB/wEAAboBAAH/AQABuQEAAf8BAAG5
+        AQAB/wEAAbgBAAH/AQABuAEAAf8BAAG3AQAB/wEAAbcBAAH/AQABtgEAAf8BAAG2AQAB/wEAAbUBAAH/
+        AQABtAEAAf8BAAG0AQAB/wEAAbMBAAH/AQABswEAAf8BAAGyAQAB/wEAAbEBAAH/AQABsQEAAf8BAAGw
+        AQAB/wEAAa8BAAH/AQABrgEAAf8BAAGuAQAB/wEAAa0BAAH/AQABrAEAAf8BAAGrAQAB/wEAAasBAAH/
+        AQABqgEAAf8BAAGpAQAB/wEAAagBAAH/AQABpwEAAf8BAAGnAQAB/wEAAaYBAAH/AQABpQEAAf8BAAGk
+        AQAB/wFQAVEBUAGfwAABUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+AQABuwEAAf8BLAF/ASwB/gEs
+        AX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAG3AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG1AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEs
+        AX8BLAH+ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+AQABrgEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABrAEAAf8BKwF/ASsB/gErAX8BKwH+AQABqQEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+AVABUQFQAZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEs
+        Af4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEs
+        AX8BLAH+AQABuwEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEsAf4BAAG6AQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG3AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG1AQAB/wEs
+        AX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+AQABsAEA
+        Af8BKwF/ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gErAX8BKwH+AQABrAEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABqQEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEAAf8BKwF/ASsB/gErAX8BKwH+AVABUQFQ
+        AZ8BUAFRAVABnwEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEs
+        AX8BLAH+ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+AQABuwEAAf8BLAF/ASwB/gEsAX8BLAH+ASwBfwEs
+        Af4BAAG6AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG4AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAG3AQAB/wEs
+        AX8BLAH+ASwBfwEsAf4BAAG1AQAB/wEsAX8BLAH+ASwBfwEsAf4BAAGzAQAB/wEsAX8BLAH+ASwBfwEs
+        Af4BAAGxAQAB/wEsAX8BLAH+AQABsAEAAf8BKwF/ASsB/gErAX8BKwH+AQABrgEAAf8BKwF/ASsB/gEr
+        AX8BKwH+AQABrAEAAf8BKwF/ASsB/gErAX8BKwH+AQABqQEAAf8BKwF/ASsB/gErAX8BKwH+AQABpwEA
+        Af8BKwF/ASsB/gErAX8BKwH+AVABUQFQAZ/AAAFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BAAG7
+        AQAB/wEsAX8BLAH+ASwBfwEsAf4BLAF/ASwB/gEAAboBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbkBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbYBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbQBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbIBAAH/ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+
+        ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGr
+        AQAB/wErAX8BKwH+ASsBfwErAf4BAAGoAQAB/wErAX8BKwH+ASsBfwErAf4BUAFRAVABnwFQAVEBUAGf
+        ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbsBAAH/ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+ASwBfwEsAf4BLAF/ASwB/gEAAboBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEAAbkBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbYBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbQBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbIBAAH/
+        ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+ASsBfwErAf4BAAGvAQAB/wErAX8BKwH+ASsBfwErAf4BAAGt
+        AQAB/wErAX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+ASsBfwErAf4BAAGoAQAB/wErAX8BKwH+
+        ASsBfwErAf4BUAFRAVABnwFQAVEBUAGfASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbsBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbsBAAH/ASwBfwEsAf4BAAG7AQAB/wEsAX8BLAH+
+        ASwBfwEsAf4BLAF/ASwB/gEAAboBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbkBAAH/ASwBfwEsAf4BLAF/
+        ASwB/gEAAbgBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbYBAAH/ASwBfwEsAf4BLAF/ASwB/gEAAbQBAAH/
+        ASwBfwEsAf4BLAF/ASwB/gEAAbIBAAH/ASwBfwEsAf4BAAGxAQAB/wEsAX8BLAH+ASsBfwErAf4BAAGv
+        AQAB/wErAX8BKwH+ASsBfwErAf4BAAGtAQAB/wErAX8BKwH+ASsBfwErAf4BAAGrAQAB/wErAX8BKwH+
+        ASsBfwErAf4BAAGoAQAB/wErAX8BKwH+ASsBfwErAf4BUAFRAVABn8AAAzsBYwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAzsBYwM7
+        AWMBUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwM7AWMDOwFjAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQ
+        AVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQ
+        AZ8BUAFRAVABnwFQAVEBUAGfAVABUQFQAZ8DOwFjwAABQgFNAT4HAAE+AwABKAMAAcADAAEwAwABAQEA
+        AQEFAAGAAQQWAAP//wD/AP8A/wCbAAs=
+</value>
+  </data>
+  <data name="smallImageList.ImageStream" mimetype="application/x-microsoft.net.object.binary.base64">
+    <value>
+        AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj0yLjAuMC4w
+        LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+        ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAABO
+        FgAAAk1TRnQBSQFMAgEBAwEAAZQBAwGYAQMBEAEAARABAAT/ASEBEAj/AUIBTQE2BwABNgMAASgDAAFA
+        AwABEAMAAQEBAAEgBgABEBIAAVkBWwFZAcMBVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFX
+        AVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFX
+        Ad8BVwFcAVcB3wFXAVwBVwHfAVkBWwFZAcMBWQFbAVkBwwFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFX
+        AVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFX
+        Ad8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BWQFbAVkBwwFZAVsBWQHDAVcBXAFXAd8BVwFcAVcB3wFX
+        AVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFX
+        Ad8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFZAVsBWQHDQAABVwFcAVcB3wEAAZQBAAH/
+        AQABkQEAAf8BAAGPAQAB/wEAAYwBAAH/AQABigEAAf8BAAGHAQAB/wEAAYUBAAH/AQABgwEAAf8BAAGB
+        AQAB/wEAARgBAAH/AQABFgEAAf8BAAEVAQAB/wEAARMBAAH/AQABEgEAAf8BVwFcAVcB3wFXAVwBVwHf
+        AQABlAEAAf8BAAGRAQAB/wEAAY8BAAH/AQABjAEAAf8BAAGKAQAB/wEAAYcBAAH/AQABhQEAAf8BAAGD
+        AQAB/wEAAYEBAAH/AQABGQEAAf8BAAEXAQAB/wEAARYBAAH/AQABFAEAAf8BAAETAQAB/wFXAVwBVwHf
+        AVcBXAFXAd8BAAGUAQAB/wEAAZEBAAH/AQABjwEAAf8BAAGMAQAB/wEAAYoBAAH/AQABhwEAAf8BAAGF
+        AQAB/wEAAYMBAAH/AQABgQEAAf8BAAEjAQAB/wEAASEBAAH/AQABIAEAAf8BAAEeAQAB/wEAAR0BAAH/
+        AVcBXAFXAd9AAAFXAVwBVwHfAQABmAEAAf8BAAGVAQAB/wEAAZMBAAH/AQABkAEAAf8BAAGOAQAB/wEA
+        AYsBAAH/AQABiQEAAf8BAAGGAQAB/wEAAYQBAAH/AQABggEAAf8BAAGAAQAB/wEAARcBAAH/AQABFgEA
+        Af8BAAEUAQAB/wFXAVwBVwHfAVcBXAFXAd8BAAGYAQAB/wEAAZUBAAH/AQABkwEAAf8BAAGQAQAB/wEA
+        AY4BAAH/AQABiwEAAf8BAAGJAQAB/wEAAYYBAAH/AQABhAEAAf8BAAGCAQAB/wEAAYABAAH/AQABGAEA
+        Af8BAAEXAQAB/wEAARUBAAH/AVcBXAFXAd8BVwFcAVcB3wEAAZgBAAH/AQABlQEAAf8BAAGTAQAB/wEA
+        AZABAAH/AQABjgEAAf8BFAGyARQB/wHkAfAB5AH/AekB8gHpAf8BgQG2AYEB/wEAAYIBAAH/AQABgAEA
+        Af8BAAEiAQAB/wEAASEBAAH/AQABHwEAAf8BVwFcAVcB30AAAVcBXAFXAd8BAAGcAQAB/wEAAZkBAAH/
+        AQABlwEAAf8B8wH5AfMZ/wHzAfgB8wH/AQABgQEAAf8BAAEYAQAB/wEAARYBAAH/AVcBXAFXAd8BVwFc
+        AVcB3wEAAZwBAAH/AQABmQEAAf8BAAGXAQAB/wEAAZQBAAH/AQABkQEAAf8BAAGkAQAB/wGMAcEBjAH/
+        AYoBvwGKAf8BAAGJAQAB/wEAAYUBAAH/AQABgwEAAf8BAAGBAQAB/wEAARkBAAH/AQABFwEAAf8BVwFc
+        AVcB3wFXAVwBVwHfAQABnAEAAf8BAAGZAQAB/wEAAZcBAAH/AQABlAEAAf8BAAGRAQAB/wHRAecB0Qn/
+        AegB8gHoAf8BAAGFAQAB/wEAAYMBAAH/AQABgQEAAf8BAAEjAQAB/wEAASEBAAH/AVcBXAFXAd9AAAFX
+        AVwBVwHfAQABoAEAAf8BAAGdAQAB/wEAAZsBACH/AQABhAEAAf8BAAGCAQAB/wEAAYABAAH/AVcBXAFX
+        Ad8BVwFcAVcB3wEAAaABAAH/AQABnQEAAf8BAAGbAQAB/wEAAZgBAAH/AQABlQEAAf8BiAHDAYgF/wP+
+        Af8BAAGOAQAB/wEAAYkBAAH/AQABhgEAAf8BAAGEAQAB/wEAAYIBAAH/AQABgAEAAf8BVwFcAVcB3wFX
+        AVwBVwHfAQABoAEAAf8BAAGdAQAB/wEAAZsBAAH/AQABmAEAAf8BAAGVAQAB/wEAAaoBAAH/Ab4B3gG+
+        Af8BwgHfAcIB/wEGAaoBBgH/AQABiQEAAf8BAAGGAQAB/wEAAYQBAAH/AQABggEAAf8BAAGAAQAB/wFX
+        AVwBVwHfQAABVwFcAVcB3wEAAaQBAAH/AQABoQEAAf8BAAGfAQAF/wGsAdcBrAH/AQABlwEAAf8BAAGU
+        AQAB/wEAAZEBAAH/AQABjwEAAf8BrAHSAawF/wEAAYgBAAH/AQABhQEAAf8BAAGDAQAB/wFXAVwBVwHf
+        AVcBXAFXAd8BAAGkAQAB/wEAAaEBAAH/AQABnwEAAf8BAAGcAQAB/wEAAZkBAAH/AQgBuQEIAf8BygHl
+        AcoB/wHJAeMByQH/AQABkQEAAf8BAAGMAQAB/wEAAYoBAAH/AQABiAEAAf8BAAGFAQAB/wEAAYMBAAH/
+        AVcBXAFXAd8BVwFcAVcB3wEAAaQBAAH/AQABoQEAAf8BAAGfAQAB/wEAAZwBAAH/AQABmQEAAf8BAAGX
+        AQAB/wEAAaABAAH/AQABoAEAAf8BAAGPAQAB/wEAAYwBAAH/AQABigEAAf8BAAGIAQAB/wEAAYUBAAH/
+        AQABgwEAAf8BVwFcAVcB30AAAVcBXAFXAd8BAAGoAQAB/wEAAaUBAAH/AQABogEAIf8BAAGLAQAB/wEA
+        AYkBAAH/AQABhwEAAf8BVwFcAVcB3wFXAVwBVwHfAQABqAEAAf8BAAGlAQAB/wEAAaIBAAH/AQABoAEA
+        Af8BAAGdAQAB/wEAAbQBAAH/AasB1gGrAf8BqQHUAakB/wEAAZQBAAH/AQABkAEAAf8BAAGOAQAB/wEA
+        AYsBAAH/AQABiQEAAf8BAAGHAQAB/wFXAVwBVwHfAVcBXAFXAd8BAAGoAQAB/wEAAaUBAAH/AQABogEA
+        Af8BAAGgAQAB/wEAAZ0BAAH/AQABmwEAAf8BlwHNAZcB/wGkAdEBpAH/AQABkwEAAf8BAAGQAQAB/wEA
+        AY4BAAH/AQABiwEAAf8BAAGJAQAB/wEAAYcBAAH/AVcBXAFXAd9AAAFXAVwBVwHfAQABqwEAAf8BAAGp
+        AQAB/wEAAaYBAAX/AawB2gGsAf8BAAGfAQAB/wEAAZwBAAH/AQABmQEAAf8BAAGXAQAB/wGsAdUBrAX/
+        AQABjwEAAf8BAAGMAQAB/wEAAYoBAAH/AVcBXAFXAd8BVwFcAVcB3wEAAasBAAH/AQABqQEAAf8BAAGm
+        AQAB/wEAAaQBAAH/AQABoQEAAf8BAAG5AQAB/wP+Bf8BjQHHAY0B/wEAAZQBAAH/AQABkgEAAf8BAAGP
+        AQAB/wEAAYwBAAH/AQABigEAAf8BVwFcAVcB3wFXAVwBVwHfAQABqwEAAf8BAAGpAQAB/wEAAaYBAAH/
+        AQABpAEAAf8BAAGhAQAB/wEAAZ8BAAH/AcAB4gHAAf8BxwHkAccB/wEAAZcBAAH/AQABlAEAAf8BAAGS
+        AQAB/wEAAY8BAAH/AQABjAEAAf8BAAGKAQAB/wFXAVwBVwHfQAABVwFcAVcB3wEAAa8BAAH/AQABrAEA
+        Af8BAAGqAQAh/wEAAZMBAAH/AQABkAEAAf8BAAGOAQAB/wFXAVwBVwHfAVcBXAFXAd8BAAGvAQAB/wEA
+        AawBAAH/AQABqgEAAf8BAAGoAQAB/wEAAaUBAAH/AQABowEAAf8BiQHLAYkB/wH8Af4B/AH/Af4B/wH+
+        Af8BmgHOAZoB/wEAAZUBAAH/AQABkwEAAf8BAAGQAQAB/wEAAY4BAAH/AVcBXAFXAd8BVwFcAVcB3wEA
+        Aa8BAAH/AQABrAEAAf8BAAGqAQAB/wEAAagBAAH/AQABpQEAAf8BAAGlAQAB/wH0AfoB9AH/AfUB+gH1
+        Af8BAAGdAQAB/wEAAZgBAAH/AQABlQEAAf8BAAGTAQAB/wEAAZABAAH/AQABjgEAAf8BVwFcAVcB30AA
+        AVcBXAFXAd8BAAGyAQAB/wEAAbABAAH/AQABrQEABf8BrAHdAawB/wEAAaYBAAH/AQABpAEAAf8BAAGh
+        AQAB/wEAAZ8BAAH/AawB2QGsBf8BAAGXAQAB/wEAAZQBAAH/AQABkgEAAf8BVwFcAVcB3wFXAVwBVwHf
+        AQABsgEAAf8BAAGwAQAB/wEAAa0BAAH/AQABqwEAAf8BAAGpAQAB/wEAAaYBAAH/AQABpAEAAf8BjgHO
+        AY4F/wH9Af4B/QH/AQABowEAAf8BAAGXAQAB/wEAAZQBAAH/AQABkgEAAf8BVwFcAVcB3wFXAVwBVwHf
+        AQABsgEAAf8BAAGwAQAB/wEAAa0BAAH/AQABqwEAAf8BAAGpAQAB/wECAbwBAwn/AQYBtwEGAf8BAAGc
+        AQAB/wEAAZkBAAH/AQABlwEAAf8BAAGUAQAB/wEAAZIBAAH/AVcBXAFXAd9AAAFXAVwBVwHfAQABtQEA
+        Af8BAAGzAQAB/wEAAbEBAB3/AfwB/QH8Af8BAAGbAQAB/wEAAZgBAAH/AQABlgEAAf8BVwFcAVcB3wFX
+        AVwBVwHfAQABtQEAAf8BAAGzAQAB/wEAAbEBAAH/AQABrwEAAf8BugHkAboB/wGjAdkBowH/AREBxgER
+        Af8BtwHgAbcF/wP+Af8BAAGpAQAB/wEAAZsBAAH/AQABmAEAAf8BAAGWAQAB/wFXAVwBVwHfAVcBXAFX
+        Ad8BAAG1AQAB/wEAAbMBAAH/AQABsQEAAf8BAAGvAQAB/wEAAawBAAH/AZoB1gGaCf8BnwHVAZ8B/wEA
+        AaABAAH/AQABnQEAAf8BAAGbAQAB/wEAAZgBAAH/AQABlgEAAf8BVwFcAVcB30AAAVcBXAFXAd8BAAG3
+        AQAB/wEAAbUBAAH/AQABtAEAGf8D/gH/AYsBzAGLAf8BAAGfAQAB/wEAAZwBAAH/AQABmgEAAf8BVwFc
+        AVcB3wFXAVwBVwHfAQABtwEAAf8BAAG1AQAB/wEAAbQBAAH/AQABsgEAAf8BwAHnAcAN/wP+Af8BqAHa
+        AagB/wEAAaEBAAH/AQABnwEAAf8BAAGcAQAB/wEAAZoBAAH/AVcBXAFXAd8BVwFcAVcB3wEAAbcBAAH/
+        AQABtQEAAf8BAAG0AQAB/wEAAbIBAAH/AQABsAEAAf8BzgHsAc4J/wHXAe4B1wH/AQABpAEAAf8BAAGh
+        AQAB/wEAAZ8BAAH/AQABnAEAAf8BAAGaAQAB/wFXAVwBVwHfQAABVwFcAVcB3wEAAbkBAAH/AQABuAEA
+        Af8BAAG2AQAB/wHzAfsB8xH/AfwB/gH8Af8BiwHPAYsB/wEAAaUBAAH/AQABowEAAf8BAAGgAQAB/wEA
+        AZ4BAAH/AVcBXAFXAd8BVwFcAVcB3wEAAbkBAAH/AQABuAEAAf8BAAG2AQAB/wEAAbUBAAH/AQABtAEA
+        Af8BAAHAAQAB/wELAckBCwH/AQoByAEKAf8BAAG3AQAB/wEAAagBAAH/AQABpQEAAf8BAAGjAQAB/wEA
+        AaABAAH/AQABngEAAf8BVwFcAVcB3wFXAVwBVwHfAQABuQEAAf8BAAG4AQAB/wEAAbYBAAH/AQABtQEA
+        Af8BAAGzAQAB/wHkAfUB5An/AfEB+QHxAf8BAAGoAQAB/wEAAaUBAAH/AQABowEAAf8BAAGgAQAB/wEA
+        AZ4BAAH/AVcBXAFXAd9AAAFXAVwBVwHfAQABugEAAf8BAAG6AQAB/wEAAbkBAAH/AQABtwEAAf8BAAG1
+        AQAB/wEAAbQBAAH/AQABsgEAAf8BAAGwAQAB/wEAAa4BAAH/AQABqwEAAf8BAAGpAQAB/wEAAacBAAH/
+        AQABpAEAAf8BAAGhAQAB/wFXAVwBVwHfAVcBXAFXAd8BAAG6AQAB/wEAAboBAAH/AQABuQEAAf8BAAG3
+        AQAB/wEAAbUBAAH/AQABtAEAAf8BAAGyAQAB/wEAAbABAAH/AQABrgEAAf8BAAGrAQAB/wEAAakBAAH/
+        AQABpwEAAf8BAAGkAQAB/wEAAaEBAAH/AVcBXAFXAd8BVwFcAVcB3wEAAboBAAH/AQABugEAAf8BAAG5
+        AQAB/wEAAbcBAAH/AQABtQEAAf8BHwHQAR8B/wHkAfUB5AH/AeYB9QHmAf8BggHPAYIB/wEAAasBAAH/
+        AQABqQEAAf8BAAGnAQAB/wEAAaQBAAH/AQABoQEAAf8BVwFcAVcB30AAAVcBXAFXAd8BAAG7AQAB/wEA
+        AbsBAAH/AQABugEAAf8BAAG5AQAB/wEAAbgBAAH/AQABtgEAAf8BAAG1AQAB/wEAAbMBAAH/AQABsQEA
+        Af8BAAGvAQAB/wEAAawBAAH/AQABqgEAAf8BAAGoAQAB/wEAAaUBAAH/AVcBXAFXAd8BVwFcAVcB3wEA
+        AbsBAAH/AQABuwEAAf8BAAG6AQAB/wEAAbkBAAH/AQABuAEAAf8BAAG2AQAB/wEAAbUBAAH/AQABswEA
+        Af8BAAGxAQAB/wEAAa8BAAH/AQABrAEAAf8BAAGqAQAB/wEAAagBAAH/AQABpQEAAf8BVwFcAVcB3wFX
+        AVwBVwHfAQABuwEAAf8BAAG7AQAB/wEAAboBAAH/AQABuQEAAf8BAAG4AQAB/wEAAbYBAAH/AQABtQEA
+        Af8BAAGzAQAB/wEAAbEBAAH/AQABrwEAAf8BAAGsAQAB/wEAAaoBAAH/AQABqAEAAf8BAAGlAQAB/wFX
+        AVwBVwHfQAABWQFbAVkBwwFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFc
+        AVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHf
+        AVcBXAFXAd8BWQFbAVkBwwFZAVsBWQHDAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFc
+        AVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHf
+        AVcBXAFXAd8BVwFcAVcB3wFZAVsBWQHDAVkBWwFZAcMBVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFc
+        AVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHf
+        AVcBXAFXAd8BVwFcAVcB3wFXAVwBVwHfAVkBWwFZAcNAAAFCAU0BPgcAAT4DAAEoAwABQAMAARADAAEB
+        AQABAQUAAYAXAAP/lwAL
+</value>
+  </data>
+  <data name="_decryptedFileColumnHeader.Text" xml:space="preserve">
+    <value>Dokument</value>
+  </data>
+  <data name="_lastAccessTimeColumnHeader.Text" xml:space="preserve">
+    <value>Tid</value>
+  </data>
+  <data name="_encryptedPathColumnHeader.Text" xml:space="preserve">
+    <value>Krypterat</value>
+  </data>
+  <data name="_recentFilesTabPage.Text" xml:space="preserve">
+    <value>Aktuella</value>
+  </data>
+  <data name="_watchedFoldersTabPage.Text" xml:space="preserve">
+    <value>Krypterade Mappar</value>
+  </data>
+  <data name="removeRecentFileToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>112, 22</value>
+  </data>
+  <data name="_removeRecentFileToolStripMenuItem.Text" xml:space="preserve">
+    <value>Ta bort från listan utan att dekryptera dokumentet</value>
+  </data>
+  <data name="recentFilesContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>113, 26</value>
+  </data>
+  <data name="enterPassphraseToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>154, 22</value>
+  </data>
+  <data name="_enterPassphraseToolStripMenuItem.Text" xml:space="preserve">
+    <value>Ange &Lösenord</value>
+  </data>
+  <data name="openFilesContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>155, 26</value>
+  </data>
+  <data name="progressContextCancelToolStripMenuItem.Size" type="System.Drawing.Size, System.Drawing">
+    <value>109, 22</value>
+  </data>
+  <data name="_progressContextCancelToolStripMenuItem.Text" xml:space="preserve">
+    <value>Avbryt</value>
+  </data>
+  <data name="progressContextMenuStrip.Size" type="System.Drawing.Size, System.Drawing">
+    <value>110, 26</value>
+  </data>
+  <data name="trayNotifyIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="_decryptTemporarilyToolStripMenuItem.Text" xml:space="preserve">
+    <value>Dekryptera &Tillfälligt</value>
+  </data>
+  <data name="_deleteToolStripMenuItem.Text" xml:space="preserve">
+    <value>Dekryptera &Permanent</value>
+  </data>
+  <data name="_openExplorerHereToolStripMenuItem.Text" xml:space="preserve">
+    <value>Öppna &Utforskaren Här</value>
+  </data>
+  <data name="_watchedFolderColumnHeader.Text" xml:space="preserve">
+    <value>Mapp</value>
+  </data>
+  <data name="_wipeToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Säker Radering</value>
+  </data>
+  <data name="_decryptAndRemoveFromListToolStripMenuItem.Text" xml:space="preserve">
+    <value>&Dekryptera och ta bort från listan</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Axantum.AxCrypt.csproj b/Axantum.AxCrypt/Axantum.AxCrypt.csproj
new file mode 100644
index 0000000..131c5c6
--- /dev/null
+++ b/Axantum.AxCrypt/Axantum.AxCrypt.csproj
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{0998224C-F45E-4EBF-A944-7FFBCB2DB134}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Axantum.AxCrypt</RootNamespace>
+    <AssemblyName>Axantum.AxCrypt</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
+    <RestorePackages>true</RestorePackages>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>AxCrypt.ico</ApplicationIcon>
+  </PropertyGroup>
+  <PropertyGroup>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
+    <DebugSymbols>True</DebugSymbols>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisIgnoreBuiltInRuleSets>false</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
+    <WarningLevel>4</WarningLevel>
+    <Optimize>False</Optimize>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>True</Optimize>
+    <TreatWarningsAsErrors>True</TreatWarningsAsErrors>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisIgnoreBuiltInRuleSets>true</CodeAnalysisIgnoreBuiltInRuleSets>
+    <CodeAnalysisIgnoreBuiltInRules>true</CodeAnalysisIgnoreBuiltInRules>
+    <CodeAnalysisFailOnMissingRules>true</CodeAnalysisFailOnMissingRules>
+    <WarningLevel>4</WarningLevel>
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AboutBox.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="AboutBox.Designer.cs">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </Compile>
+    <Compile Include="AxCryptMainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="AxCryptMainForm.Designer.cs">
+      <DependentUpon>AxCryptMainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="ConfirmWipeDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="ConfirmWipeDialog.Designer.cs">
+      <DependentUpon>ConfirmWipeDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="CreateNewAccountDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="CreateNewAccountDialog.Designer.cs">
+      <DependentUpon>CreateNewAccountDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DebugLogOutputDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DebugLogOutputDialog.Designer.cs">
+      <DependentUpon>DebugLogOutputDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="LogOnAccountDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="LogOnAccountDialog.Designer.cs">
+      <DependentUpon>LogOnAccountDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="WatchedFoldersDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="WatchedFoldersDialog.Designer.cs">
+      <DependentUpon>WatchedFoldersDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="KnownFoldersDiscovery.cs" />
+    <Compile Include="LogOnDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="LogOnDialog.Designer.cs">
+      <DependentUpon>LogOnDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DebugOptionsDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DebugOptionsDialog.Designer.cs">
+      <DependentUpon>DebugOptionsDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="NewPassphraseDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="NewPassphraseDialog.Designer.cs">
+      <DependentUpon>NewPassphraseDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="DecryptPassphraseDialog.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="DecryptPassphraseDialog.Designer.cs">
+      <DependentUpon>DecryptPassphraseDialog.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Extensions.cs" />
+    <Compile Include="Preferences.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\Settings.Designer.cs">
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+      <AutoGen>True</AutoGen>
+    </Compile>
+    <Compile Include="UIThread.cs" />
+    <EmbeddedResource Include="ConfirmWipeDialog.resx">
+      <DependentUpon>ConfirmWipeDialog.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="ConfirmWipeDialog.sv.resx">
+      <DependentUpon>ConfirmWipeDialog.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="CreateNewAccountDialog.resx">
+      <DependentUpon>CreateNewAccountDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DebugLogOutputDialog.resx">
+      <DependentUpon>DebugLogOutputDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="LogOnAccountDialog.resx">
+      <DependentUpon>LogOnAccountDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="WatchedFoldersDialog.resx">
+      <DependentUpon>WatchedFoldersDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="LogOnDialog.resx">
+      <DependentUpon>LogOnDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="LogOnDialog.sv.resx">
+      <DependentUpon>LogOnDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <SubType>Designer</SubType>
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.sv.resx">
+      <DependentUpon>Resources.resx</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <None Include="Properties\AssemblyInfo.template" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="AboutBox.resx">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="AboutBox.sv.resx">
+      <DependentUpon>AboutBox.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="AxCryptMainForm.resx">
+      <DependentUpon>AxCryptMainForm.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="AxCryptMainForm.sv.resx">
+      <DependentUpon>AxCryptMainForm.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DebugOptionsDialog.resx">
+      <DependentUpon>DebugOptionsDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DebugOptionsDialog.sv.resx">
+      <DependentUpon>DebugOptionsDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DecryptPassphraseDialog.sv.resx">
+      <DependentUpon>DecryptPassphraseDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="NewPassphraseDialog.resx">
+      <DependentUpon>NewPassphraseDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="DecryptPassphraseDialog.resx">
+      <DependentUpon>DecryptPassphraseDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="NewPassphraseDialog.sv.resx">
+      <DependentUpon>NewPassphraseDialog.cs</DependentUpon>
+    </EmbeddedResource>
+    <None Include="app.config" />
+    <None Include="AxantumStrongName.pfx" />
+    <Compile Include="Properties\Resources.Designer.cs">
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+      <AutoGen>True</AutoGen>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\Axantum.AxCrypt.Core\Axantum.AxCrypt.Core.csproj">
+      <Project>{966E9510-1A1D-46C7-97B5-460A0FF9B89F}</Project>
+      <Name>Axantum.AxCrypt.Core</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Desktop\Axantum.AxCrypt.Desktop.csproj">
+      <Project>{d64de570-3a36-49d3-95aa-9262647b04ee}</Project>
+      <Name>Axantum.AxCrypt.Desktop</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Forms\Axantum.AxCrypt.Forms.csproj">
+      <Project>{ac7c1ecd-4543-4cf3-8938-32f3d8cb89d5}</Project>
+      <Name>Axantum.AxCrypt.Forms</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Axantum.AxCrypt.Mono\Axantum.AxCrypt.Mono.csproj">
+      <Project>{CE9E8614-8DC5-4757-9384-3C416AB61A47}</Project>
+      <Name>Axantum.AxCrypt.Mono</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\BouncyCastle.AxCrypt\BouncyCastle.AxCrypt.csproj">
+      <Project>{3680c939-b21f-4444-b646-42fb4b29a786}</Project>
+      <Name>BouncyCastle.AxCrypt</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\Newtonsoft.Json\Newtonsoft.Json.Portable40.csproj">
+      <Project>{959f7f85-c98b-4876-971a-9036224578e4}</Project>
+      <Name>Newtonsoft.Json.Portable40</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup />
+  <ItemGroup>
+    <Content Include="AboutThisProgram.txt" />
+    <Content Include="Axantum.AxCrypt_ml.xml" />
+    <Content Include="AxCrypt.ico" />
+    <Content Include="resources\activefilegreen16.png" />
+    <Content Include="resources\activefileknownkeygreen16.png" />
+    <Content Include="resources\axcrypticon.ico" />
+    <Content Include="resources\closeremovestandbygreen32.png" />
+    <Content Include="resources\closeremovestandbyred32.png" />
+    <None Include="resources\SkyDrive.ico" />
+    <None Include="resources\trashred16.png" />
+    <None Include="resources\encryptlock32.png" />
+    <None Include="resources\opendocument32.png" />
+    <None Include="resources\decryptlockopen32.png" />
+    <Content Include="resources\decryptedfilered16.png" />
+    <Content Include="resources\decryptedunknownkeyfilered16.png" />
+    <None Include="resources\DocumentsLibrary.ico" />
+    <Content Include="resources\exclamationgreen16.png" />
+    <None Include="resources\exclamationgreen32.png" />
+    <Content Include="resources\fileknownkeygreen16.png" />
+    <None Include="resources\GoogleDrive.ico" />
+    <Content Include="resources\helpquestiongreen32.png" />
+    <None Include="resources\encryptionkeygreen32.png" />
+    <None Include="resources\encryptionkeyred32.png" />
+    <None Include="resources\DropBox.ico" />
+    <Content Include="resources\inactivefilegreen16.png" />
+    <Content Include="resources\refreshred.png" />
+    <Content Include="resources\axcrypticon128.png" />
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <None Include="resources\refreshgreen.png" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
+       Other similar extension points exist, see Microsoft.Common.targets.
+  -->
+  <!--<TargetName="BeforeBuild">
+  </TargetName>-->
+  <!--<Target Name="AfterBuild">
+  </Target>-->
+</Project>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Axantum.AxCrypt_ml.xml b/Axantum.AxCrypt/Axantum.AxCrypt_ml.xml
new file mode 100644
index 0000000..c786dd6
--- /dev/null
+++ b/Axantum.AxCrypt/Axantum.AxCrypt_ml.xml
@@ -0,0 +1,3352 @@
+<?xml version="1.0" standalone="yes"?>
+<MdbTranslationStore xmlns="http://tempuri.org/MdbTranslationStore.xsd">
+  <GeneralIds>
+    <StringID>1</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>2</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>3</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>4</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>5</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>6</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>7</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>8</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>9</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>10</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>11</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>12</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>13</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>14</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>15</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>16</StringID>
+    <Comment>Previous text: &Close</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>17</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>18</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>19</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>20</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>21</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>22</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>23</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>24</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>25</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>26</StringID>
+    <Comment>Previous text: Encrypted Folders</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>27</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>28</StringID>
+    <Comment>Previous text: Remove</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>29</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>30</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>31</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>32</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>33</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>34</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>35</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>36</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>37</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>38</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>39</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>40</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>41</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>42</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>43</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>44</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>45</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>46</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>47</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>48</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>49</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>50</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>51</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>52</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>53</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>54</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>55</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>56</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>57</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>58</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>59</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>60</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>61</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>62</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>63</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>64</StringID>
+    <Comment>Previous text: Click to remove any open decrypted files left, but
+first ensure they are not used in an application. See
+the Open Files tab to see the list of files.</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>65</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>66</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>67</StringID>
+    <Comment>The menu text for language selection.</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>68</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>69</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>70</StringID>
+    <Comment>Previous text: Double-click to restore the AxCrypt application window.</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>71</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>72</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>73</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>74</StringID>
+    <Comment>Previous text: Double-click to restore the AxCrypt application window.</Comment>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>75</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>76</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>77</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>78</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>79</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>80</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>81</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>82</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>83</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>84</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>85</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>86</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>87</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>88</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>89</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>90</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>91</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>92</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>93</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>94</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>95</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>96</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>97</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>98</StringID>
+    <Comment />
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>99</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>100</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>101</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>102</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>103</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>104</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>105</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>106</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>107</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>108</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>109</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>110</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>111</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>112</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>113</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>114</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>115</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>116</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>117</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>118</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>119</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>120</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>121</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>122</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>123</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>124</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>125</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>126</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>127</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>128</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>129</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>130</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>131</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>132</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>133</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>134</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>135</StringID>
+  </GeneralIds>
+  <GeneralIds>
+    <StringID>136</StringID>
+  </GeneralIds>
+  <Languages>
+    <LanguageID>29</LanguageID>
+    <LanguageName>Swedish</LanguageName>
+    <IetfLanguageTag>sv</IetfLanguageTag>
+    <ColumnNumber>5</ColumnNumber>
+  </Languages>
+  <Languages>
+    <LanguageID>9</LanguageID>
+    <LanguageName>English</LanguageName>
+    <IetfLanguageTag>en</IetfLanguageTag>
+    <ColumnNumber>4</ColumnNumber>
+  </Languages>
+  <GeneralTexts>
+    <StringID>15</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Dekryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>23</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Krypterat</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>14</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Kryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>17</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Avsluta</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>18</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Arkiv</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>19</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Hjälp</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>13</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Öppna Krypterat</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>22</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokument</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>21</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Öppna Dokument</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>24</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Nyligen Öppnade</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>26</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Krypterade Mappar</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>16</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Stäng</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>10</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Hjälp</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>11</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Hjälp</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>30</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Avbryt</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>6</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dekryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>4</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Kryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>5</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Klicka eller dra och släpp filer här för att kryptera valda filer</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>2</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Öppna krypterat dokument</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>3</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Klicka eller dra och släpp filer här för att dekrypera och öppna i sin applikation</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>32</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>OK</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>45</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Arkiv</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>25</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Tid</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>27</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Log Output</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>29</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Ange &Lösenord</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>31</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Ange Lösenord</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>34</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Verifiera Lösenord</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>35</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att kryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>36</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet finns redan, spara som</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>37</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att dekryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>38</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet finns redan, spara som</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>39</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att dekryptera och öppna</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>40</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Lösenorden är inte lika</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>51</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Fel med '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>50</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Lösenorden är inte lika</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>49</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet finns redan, spara som</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>48</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokument (*{0})|*{0}|Alla dokument (*.*)|*.*</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>47</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet finns redan, spara som</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>46</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt Krypterade (*{0})|*{0}|Alla dokument (*.*)|*.*</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>44</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att dekryptera och öppna</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>43</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att kryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>41</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Välj dokument att dekryptera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>42</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Krypterat Dokument</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>16</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Clean Decrypted</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>22</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Document</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>15</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Decrypt</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>23</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Encrypted</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>14</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Encrypt</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>29</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Enter &Passphrase</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>17</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>E&xit</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>18</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&File</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>10</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>He&lp</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>11</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Help</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>19</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Help</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>25</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Time</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>27</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Log Output</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>13</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Open Encrypted</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>21</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Open Files</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>30</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Cancel</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>24</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Recent Files</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>6</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Decrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>4</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Encrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>5</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click and select or drag and drop files to encrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>2</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Open Encrypted</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>3</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click and select or drag and drop files to decrypt temporarily and open in the associated application</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>26</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Watched Folders</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>32</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>OK</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>31</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Enter Passphrase</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>34</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Verify Passphrase</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>35</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to encrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>36</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File Exists, Save As</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>37</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to decrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>38</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File exists, choose a new name to save as</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>39</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select file to decrypt and open</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>40</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Passphrases do not match</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>41</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to decrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>42</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Encrypted File</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>43</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to encrypt</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>44</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select file to decrypt and open</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>45</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>46</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt Files (*{0})|*{0}|All files (*.*)|*.*</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>47</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File Exists, Save As</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>48</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Documents (*{0})|*{0}|All files (*.*)|*.*</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>49</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File exists, choose a new name to save as</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>50</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Passphrases do not match</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>51</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Failed '{0}'.</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>52</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File '{0}' already exists.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>53</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>File '{0}' does not exist.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>54</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Cannot write '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>55</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Cannot start application for '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>56</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Inconsistent state with '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>57</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Invalid key for '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>58</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Canceled '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>59</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Unrecognized error code failing with '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>52</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet '{0}' finns redan.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>53</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dokumentet '{0}' finns inte.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>54</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Kan inte skriva till '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>55</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Kan inte starta applikation för '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>56</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Internt fel med '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>57</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Felaktig krypteringsnyckel för '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>58</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Avbröt '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>59</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Okänt fel med '{0}'.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>1</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>20</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>menuStrip1</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>28</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Leave Encrypted But &Remove From List</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>12</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>toolStrip1</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>8</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Update</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>9</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Close and remove open files</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>7</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click and select or drag and drop files to decrypt permanently</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>33</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>EncryptPassphraseDialog</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>28</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Ta Bort</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>9</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Stäng och ta bort öppna dokument</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>7</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Klicka och välj eller dra och släpp dokument för att dekryptera permanent</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>60</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Updating Status</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>60</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Uppdaterar Status</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>61</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Purging Active Files</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>61</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Rensar Aktiva Dokument</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>63</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Rensar Aktiva Dokument</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>62</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Uppdaterar Status</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>63</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Purging Active Files</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>62</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Updating Status</LanguageText>
+    <Status>6</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>64</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to clean and remove any open decrypted files, but 
+ensure they are not in use.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>65</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&English</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>66</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Svenska</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>67</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Language</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>68</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>O&ptions</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>68</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Alternativ</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>69</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt File Encryption</LanguageText>
+    <Status>0</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>69</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt Dokumentkryptering</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>70</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to restore the AxCrypt application window.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>70</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dubbelklicka ikonen för att öppa AxCrypt</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>72</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>You must restart AxCrypt in order for the language change to take effect.</LanguageText>
+    <Status>0</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>72</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt måste startas om för att slutföra språkändringen.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>73</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt File Encryption</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>74</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to restore the AxCrypt application window.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>71</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt File Encryption</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>73</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt Dokumentkryptering</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>74</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Dubbelklicka ikonen för att öppa AxCrypt</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>71</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt Dokumentkryptering</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>67</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Språk</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>64</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Det finns öppna, dekrypterade filer. Klicka här för att stänga och ta brot de, men säkerställ först att de inte används. Fliken 'Öppna Dokument' visar vilka det gäller.</LanguageText>
+    <Status>7</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>75</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>en</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>76</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>sv</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>77</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>No need to check for updates.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>77</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Inget uppdateringsbehov.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>78</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Your version is old. Please click to check for a newer version.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>78</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Du har en gammal version. Klicka för att kontrollera om det finns en nyare.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>79</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Version {0} is available! Click to download.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>79</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Version {0} finns tillgänglig! Klicka för att komma till nedladdningssidan.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>80</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to check for a newer version.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>80</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Klicka för att kontrollera om det finns en ny version.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>8</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Uppdatera</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>81</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>No need to check for updates.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>82</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Your version is old. Please click to check for a newer version.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>83</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to check for a newer version.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>81</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Inget uppdateringsbehov.</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>82</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Du har en gammal version. Klicka för att kontrollera om det finns en nyare.</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>83</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Klicka för att kontrollera om det finns en ny version.</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>84</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AboutBox</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>85</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Version</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>86</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Copyright 2012 Axantum Software AB</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>87</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Axantum Software AB</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>88</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Description</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>89</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&OK</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>90</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Debug</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>91</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Check Version Now</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>92</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Options</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>93</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&View Help</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>94</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&About</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>95</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Debugging Options</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>96</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Update Check Service Url</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>97</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Show Passphrase</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>89</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&OK</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>94</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Om</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>92</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Alternativ</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>91</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Sök Uppdatering</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>97</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Visa Lösenord</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>93</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Visa Hjälp</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>98</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Cancel</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>98</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Cancel</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>99</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>toolStripButton1</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>101</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>About {0}</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>102</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Open Source File Encryption for Windows
+
+Includes software from http://www.bouncycastle.org/ .</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>103</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Exception during processing of '{0}'.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>100</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Open Source File Encryption for Windows
+
+Includes software from http://www.bouncycastle.org/ .</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>104</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Invalid URL.</LanguageText>
+    <Status>0</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>105</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Click to select files to encrypt</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>106</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Secure Delete</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>107</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Decrypt And Remove From List</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>108</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Are you sure want to permanently delete this file? This action cannot be undone.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>109</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>A file.ext</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>110</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&No</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>111</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Yes</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>112</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Do this for &all remaining files?</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>113</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>&Cancel All</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>114</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>AxCrypt Secure Delete</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>125</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Double-click to Open</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>126</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Double-click to enter passphrase and Open</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>127</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Assumed open. Try to Close the application, or use the Clean function to remove it</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>128</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>The passphrase has not been entered yet. Double-click to enter passphrase and Open, or right-click for options</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>129</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Inactive file</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>130</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>You are Logged On to AxCrypt. Click to Log Out.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>131</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>The file '{0}' is already encrypted.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>132</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>The file or path '{0}' is invalid for this.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>133</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>You are Logged Out of AxCrypt. Click to Log On.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>134</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to securely delete</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>135</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Logged Off</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>136</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Logged On</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>115</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Logged Off</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>116</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Logged On</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>117</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>You are Logged Out of AxCrypt. Click to Log On.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>118</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>You are Logged On to AxCrypt. Click to Log Out.</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>119</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Assumed open. Try to Close the application, or use the Clean function to remove it</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>120</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>The passphrase has not been entered yet. Double-click to enter passphrase and Open, or right-click for options</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>121</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Inactive file</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>122</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Double-click to enter passphrase and Open</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>123</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Double-click to Open</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>124</StringID>
+    <LanguageID>9</LanguageID>
+    <LanguageText>Select files to securely delete</LanguageText>
+    <Status>1</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>110</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Nej</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>111</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Ja</LanguageText>
+    <Status>3</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>114</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>AxCrypt Säker Radering</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>113</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>&Avbryt allt</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>112</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Gör detta för &alla återstående filer?</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>108</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Är du säker att du vill radera filen? Detta går inte att ångra.</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>115</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Avloggad</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <GeneralTexts>
+    <StringID>116</StringID>
+    <LanguageID>29</LanguageID>
+    <LanguageText>Inloggad</LanguageText>
+    <Status>2</Status>
+  </GeneralTexts>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>AxCryptMainForm.Text</Name>
+    <StringID>1</StringID>
+    <Selected>true</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonOpenEncrypted.Text</Name>
+    <StringID>2</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonOpenEncrypted.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonOpenEncrypted.ToolTipText</Name>
+    <StringID>3</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonOpenEncrypted.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonEncrypt.Text</Name>
+    <StringID>4</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonEncrypt.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonEncrypt.ToolTipText</Name>
+    <StringID>5</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonEncrypt.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonDecrypt.Text</Name>
+    <StringID>6</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonDecrypt.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButtonDecrypt.ToolTipText</Name>
+    <StringID>7</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonDecrypt.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButton1.Text</Name>
+    <StringID>8</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButton1.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStripButton1.ToolTipText</Name>
+    <StringID>9</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButton1.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>helpToolStripButton.Text</Name>
+    <StringID>10</StringID>
+    <Selected>true</Selected>
+    <ResourceName>helpToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>helpToolStripButton.ToolTipText</Name>
+    <StringID>11</StringID>
+    <Selected>true</Selected>
+    <ResourceName>helpToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>toolStrip1.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>toolStrip1.Text</ResourceName>
+    <Hidden>true</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>openEncryptedToolStripMenuItem.Text</Name>
+    <StringID>13</StringID>
+    <Selected>true</Selected>
+    <ResourceName>openEncryptedToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>encryptToolStripMenuItem.Text</Name>
+    <StringID>14</StringID>
+    <Selected>true</Selected>
+    <ResourceName>encryptToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>decryptToolStripMenuItem.Text</Name>
+    <StringID>15</StringID>
+    <Selected>true</Selected>
+    <ResourceName>decryptToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>CloseStripMenuItem.Text</Name>
+    <StringID>16</StringID>
+    <Selected>true</Selected>
+    <ResourceName>CloseStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>exitToolStripMenuItem.Text</Name>
+    <StringID>17</StringID>
+    <Selected>true</Selected>
+    <ResourceName>exitToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>fileToolStripMenuItem.Text</Name>
+    <StringID>18</StringID>
+    <Selected>true</Selected>
+    <ResourceName>fileToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>helpToolStripMenuItem.Text</Name>
+    <StringID>19</StringID>
+    <Selected>true</Selected>
+    <ResourceName>helpToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>menuStripMain.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>menuStripMain.Text</ResourceName>
+    <Hidden>true</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>OpenFilesTab.Text</Name>
+    <StringID>21</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OpenFilesTab.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>OpenFile.Text</Name>
+    <StringID>22</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OpenFile.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>EncryptedSource.Text</Name>
+    <StringID>23</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptedSource.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>RecentFilesTab.Text</Name>
+    <StringID>24</StringID>
+    <Selected>true</Selected>
+    <ResourceName>RecentFilesTab.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>DecryptedFile.Text</Name>
+    <StringID>22</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedFile.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>LastAccessTime.Text</Name>
+    <StringID>25</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LastAccessTime.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>EncryptedPath.Text</Name>
+    <StringID>23</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptedPath.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>WatchedFoldersTab.Text</Name>
+    <StringID>26</StringID>
+    <Selected>true</Selected>
+    <ResourceName>WatchedFoldersTab.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>LogTab.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>LogTab.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>removeToolStripMenuItem.Text</Name>
+    <StringID>28</StringID>
+    <Selected>true</Selected>
+    <ResourceName>removeToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>EnterPassphraseMenuItem.Text</Name>
+    <StringID>29</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EnterPassphraseMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>ProgressContextCancelMenu.Text</Name>
+    <StringID>30</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ProgressContextCancelMenu.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DecryptPassphraseDialog.cs</Component>
+    <Name>DecryptPassphraseDialog.Text</Name>
+    <StringID>1</StringID>
+    <Selected>true</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DecryptPassphraseDialog.cs</Component>
+    <Name>PassphraseGroupBox.Text</Name>
+    <StringID>31</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PassphraseGroupBox.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DecryptPassphraseDialog.cs</Component>
+    <Name>buttonCancel.Text</Name>
+    <StringID>30</StringID>
+    <Selected>true</Selected>
+    <ResourceName>buttonCancel.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DecryptPassphraseDialog.cs</Component>
+    <Name>buttonOk.Text</Name>
+    <StringID>32</StringID>
+    <Selected>true</Selected>
+    <ResourceName>buttonOk.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>EncryptPassphraseDialog.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>true</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>buttonCancel.Text</Name>
+    <StringID>30</StringID>
+    <Selected>true</Selected>
+    <ResourceName>buttonCancel.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>buttonOk.Text</Name>
+    <StringID>32</StringID>
+    <Selected>true</Selected>
+    <ResourceName>buttonOk.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>PassphraseGroupBox.Text</Name>
+    <StringID>31</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PassphraseGroupBox.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>label1.Text</Name>
+    <StringID>34</StringID>
+    <Selected>true</Selected>
+    <ResourceName>label1.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.EncryptFileOpenDialogTitle</Name>
+    <StringID>35</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.EncryptFileSaveAsDialogTitle</Name>
+    <StringID>36</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptFileSaveAsDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.DecryptFileOpenDialogTitle</Name>
+    <StringID>37</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.DecryptedSaveAsFileDialogTitle</Name>
+    <StringID>38</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedSaveAsFileDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.OpenEncryptedFileOpenDialogTitle</Name>
+    <StringID>39</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OpenEncryptedFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.PassphraseVerificationMismatch</Name>
+    <StringID>40</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PassphraseVerificationMismatch</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DecryptFileOpenDialogTitle</Name>
+    <StringID>41</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.EncryptedSourceColumnHeader</Name>
+    <StringID>42</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptedSourceColumnHeader</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.EncryptFileOpenDialogTitle</Name>
+    <StringID>43</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.OpenEncryptedFileOpenDialogTitle</Name>
+    <StringID>44</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OpenEncryptedFileOpenDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.OpenFileColumnHeader</Name>
+    <StringID>45</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OpenFileColumnHeader</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.EncryptedFileDialogFilterPattern</Name>
+    <StringID>46</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptedFileDialogFilterPattern</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.EncryptFileSaveAsDialogTitle</Name>
+    <StringID>47</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EncryptFileSaveAsDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DecryptedSaveAsFileDialogFilterPattern</Name>
+    <StringID>48</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedSaveAsFileDialogFilterPattern</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DecryptedSaveAsFileDialogTitle</Name>
+    <StringID>49</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedSaveAsFileDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.PassphraseVerificationMismatch</Name>
+    <StringID>50</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PassphraseVerificationMismatch</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.FileOperationFailed</Name>
+    <StringID>51</StringID>
+    <Selected>true</Selected>
+    <ResourceName>FileOperationFailed</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.FileAlreadyExists</Name>
+    <StringID>52</StringID>
+    <Selected>true</Selected>
+    <ResourceName>FileAlreadyExists</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.FileDoesNotExist</Name>
+    <StringID>53</StringID>
+    <Selected>true</Selected>
+    <ResourceName>FileDoesNotExist</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.CannotWrite</Name>
+    <StringID>54</StringID>
+    <Selected>true</Selected>
+    <ResourceName>CannotWrite</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.CannotStartApplication</Name>
+    <StringID>55</StringID>
+    <Selected>true</Selected>
+    <ResourceName>CannotStartApplication</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.InconsistentState</Name>
+    <StringID>56</StringID>
+    <Selected>true</Selected>
+    <ResourceName>InconsistentState</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.InvalidKey</Name>
+    <StringID>57</StringID>
+    <Selected>true</Selected>
+    <ResourceName>InvalidKey</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.Canceled</Name>
+    <StringID>58</StringID>
+    <Selected>true</Selected>
+    <ResourceName>Canceled</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.UnrecognizedError</Name>
+    <StringID>59</StringID>
+    <Selected>true</Selected>
+    <ResourceName>UnrecognizedError</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.UpdatingStatus</Name>
+    <StringID>60</StringID>
+    <Selected>true</Selected>
+    <ResourceName>UpdatingStatus</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.PurgingActiveFiles</Name>
+    <StringID>61</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PurgingActiveFiles</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.UpdatingStatus</Name>
+    <StringID>62</StringID>
+    <Selected>true</Selected>
+    <ResourceName>UpdatingStatus</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.PurgingActiveFiles</Name>
+    <StringID>63</StringID>
+    <Selected>true</Selected>
+    <ResourceName>PurgingActiveFiles</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>CloseAndRemoveOpenFilesButton.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>CloseAndRemoveOpenFilesButton.Text</ResourceName>
+    <Hidden>true</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>CloseAndRemoveOpenFilesButton.ToolTipText</Name>
+    <StringID>64</StringID>
+    <Selected>true</Selected>
+    <ResourceName>CloseAndRemoveOpenFilesButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>EnglishMenuItem.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>EnglishMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>SwedishMenuItem.Text</Name>
+    <StringID>66</StringID>
+    <Selected>true</Selected>
+    <ResourceName>SwedishMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>LanguageMenuItem.Text</Name>
+    <StringID>67</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LanguageMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>OptionsMenuItem.Text</Name>
+    <StringID>68</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OptionsMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>TrayNotifyIcon.Text</Name>
+    <StringID>1</StringID>
+    <Selected>true</Selected>
+    <ResourceName>TrayNotifyIcon.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.AxCryptFileEncryption</Name>
+    <StringID>71</StringID>
+    <Selected>true</Selected>
+    <ResourceName>AxCryptFileEncryption</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.AxCryptFileEncryption</Name>
+    <StringID>73</StringID>
+    <Selected>true</Selected>
+    <ResourceName>AxCryptFileEncryption</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.TrayBalloonTooltip</Name>
+    <StringID>74</StringID>
+    <Selected>true</Selected>
+    <ResourceName>TrayBalloonTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.TrayBalloonTooltip</Name>
+    <StringID>70</StringID>
+    <Selected>true</Selected>
+    <ResourceName>TrayBalloonTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.LanguageChangeRestartPrompt</Name>
+    <StringID>72</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LanguageChangeRestartPrompt</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>EnglishMenuItem.Tag</Name>
+    <StringID>75</StringID>
+    <Selected>true</Selected>
+    <ResourceName>EnglishMenuItem.Tag</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>SwedishMenuItem.Tag</Name>
+    <StringID>76</StringID>
+    <Selected>true</Selected>
+    <ResourceName>SwedishMenuItem.Tag</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>UpdateToolStripButton.Text</Name>
+    <StringID>8</StringID>
+    <Selected>true</Selected>
+    <ResourceName>UpdateToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>CloseOpenFilesMenuItem.Text</Name>
+    <StringID>16</StringID>
+    <Selected>true</Selected>
+    <ResourceName>CloseOpenFilesMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>RemoveRecentFileMenuItem.Text</Name>
+    <StringID>28</StringID>
+    <Selected>true</Selected>
+    <ResourceName>RemoveRecentFileMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.NoNeedToCheckForUpdatesTooltip</Name>
+    <StringID>81</StringID>
+    <Selected>true</Selected>
+    <ResourceName>NoNeedToCheckForUpdatesTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.OldVersionTooltip</Name>
+    <StringID>82</StringID>
+    <Selected>true</Selected>
+    <ResourceName>OldVersionTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.ClickToCheckForNewerVersionTooltip</Name>
+    <StringID>83</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ClickToCheckForNewerVersionTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.NewVersionIsAvailableTooltip</Name>
+    <StringID>79</StringID>
+    <Selected>true</Selected>
+    <ResourceName>NewVersionIsAvailableTooltip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>AboutBox.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>ProductNameText.Text</Name>
+    <StringID>69</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ProductNameText.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>VersionText.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>VersionText.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>CopyrightText.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>CopyrightText.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>CompanyNameText.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>CompanyNameText.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>Description.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>Description.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>Description.Lines[0]</Name>
+    <Selected>false</Selected>
+    <ResourceName>Description.Lines[0]</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AboutBox.cs</Component>
+    <Name>okButton.Text</Name>
+    <StringID>89</StringID>
+    <Selected>true</Selected>
+    <ResourceName>okButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>UpdateToolStripButton.ToolTipText</Name>
+    <StringID>8</StringID>
+    <Selected>true</Selected>
+    <ResourceName>UpdateToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>helpButton.Text</Name>
+    <StringID>10</StringID>
+    <Selected>true</Selected>
+    <ResourceName>helpButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>helpButton.ToolTipText</Name>
+    <StringID>11</StringID>
+    <Selected>true</Selected>
+    <ResourceName>helpButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>debugToolStripMenuItem1.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>debugToolStripMenuItem1.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>checkVersionNow.Text</Name>
+    <StringID>91</StringID>
+    <Selected>true</Selected>
+    <ResourceName>checkVersionNow.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>setUpdateCheckUrlToolStripMenuItem.Text</Name>
+    <StringID>92</StringID>
+    <Selected>true</Selected>
+    <ResourceName>setUpdateCheckUrlToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>DebugToolStripMenuItem.Text</Name>
+    <StringID>90</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DebugToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>viewHelpMenuItem.Text</Name>
+    <StringID>93</StringID>
+    <Selected>true</Selected>
+    <ResourceName>viewHelpMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>about.Text</Name>
+    <StringID>94</StringID>
+    <Selected>true</Selected>
+    <ResourceName>about.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DebugOptionsDialog.cs</Component>
+    <Name>DebugOptionsDialog.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DebugOptionsDialog.cs</Component>
+    <Name>label1.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>label1.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DebugOptionsDialog.cs</Component>
+    <Name>okButton.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>okButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DebugOptionsDialog.cs</Component>
+    <Name>cancelButton.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>cancelButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>EncryptPassphraseDialog.cs</Component>
+    <Name>ShowPassphraseCheckBox.Text</Name>
+    <StringID>97</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ShowPassphraseCheckBox.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>DecryptPassphraseDialog.cs</Component>
+    <Name>ShowPassphraseCheckBox.Text</Name>
+    <StringID>97</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ShowPassphraseCheckBox.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>openEncryptedToolStripButton.Text</Name>
+    <StringID>2</StringID>
+    <Selected>true</Selected>
+    <ResourceName>openEncryptedToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>openEncryptedToolStripButton.ToolTipText</Name>
+    <StringID>3</StringID>
+    <Selected>true</Selected>
+    <ResourceName>openEncryptedToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>decryptToolStripButton.Text</Name>
+    <StringID>6</StringID>
+    <Selected>true</Selected>
+    <ResourceName>decryptToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>decryptToolStripButton.ToolTipText</Name>
+    <StringID>7</StringID>
+    <Selected>true</Selected>
+    <ResourceName>decryptToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>closeAndRemoveOpenFilesToolStripButton.Text</Name>
+    <StringID>99</StringID>
+    <Selected>true</Selected>
+    <ResourceName>closeAndRemoveOpenFilesToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>closeAndRemoveOpenFilesToolStripButton.ToolTipText</Name>
+    <StringID>64</StringID>
+    <Selected>true</Selected>
+    <ResourceName>closeAndRemoveOpenFilesToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>mainToolStrip.Text</Name>
+    <StringID>12</StringID>
+    <Selected>true</Selected>
+    <ResourceName>mainToolStrip.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>closeOpenFilesToolStripMenuItem.Text</Name>
+    <StringID>16</StringID>
+    <Selected>true</Selected>
+    <ResourceName>closeOpenFilesToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>englishLanguageToolStripMenuItem.Text</Name>
+    <StringID>65</StringID>
+    <Selected>true</Selected>
+    <ResourceName>englishLanguageToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>swedishLanguageToolStripMenuItem.Text</Name>
+    <StringID>66</StringID>
+    <Selected>true</Selected>
+    <ResourceName>swedishLanguageToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>languageToolStripMenuItem.Text</Name>
+    <StringID>67</StringID>
+    <Selected>true</Selected>
+    <ResourceName>languageToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>debugOptionsToolStripMenuItem.Text</Name>
+    <StringID>90</StringID>
+    <Selected>true</Selected>
+    <ResourceName>debugOptionsToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>optionsToolStripMenuItem.Text</Name>
+    <StringID>68</StringID>
+    <Selected>true</Selected>
+    <ResourceName>optionsToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>checkVersionNowToolStripMenuItem.Text</Name>
+    <StringID>91</StringID>
+    <Selected>true</Selected>
+    <ResourceName>checkVersionNowToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>aboutToolStripMenuItem.Text</Name>
+    <StringID>94</StringID>
+    <Selected>true</Selected>
+    <ResourceName>aboutToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>mainMenuStrip.Text</Name>
+    <StringID>20</StringID>
+    <Selected>true</Selected>
+    <ResourceName>mainMenuStrip.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>openFilesTabPage.Text</Name>
+    <StringID>21</StringID>
+    <Selected>true</Selected>
+    <ResourceName>openFilesTabPage.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>openFileColumnHeader.Text</Name>
+    <StringID>22</StringID>
+    <Selected>true</Selected>
+    <ResourceName>openFileColumnHeader.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>encryptedSourceColumnHeader.Text</Name>
+    <StringID>23</StringID>
+    <Selected>true</Selected>
+    <ResourceName>encryptedSourceColumnHeader.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>recentFilesTabPage.Text</Name>
+    <StringID>24</StringID>
+    <Selected>true</Selected>
+    <ResourceName>recentFilesTabPage.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>decryptedFileColumnHeader.Text</Name>
+    <StringID>22</StringID>
+    <Selected>true</Selected>
+    <ResourceName>decryptedFileColumnHeader.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>lastAccessTimeColumnHeader.Text</Name>
+    <StringID>25</StringID>
+    <Selected>true</Selected>
+    <ResourceName>lastAccessTimeColumnHeader.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>encryptedPathColumnHeader.Text</Name>
+    <StringID>23</StringID>
+    <Selected>true</Selected>
+    <ResourceName>encryptedPathColumnHeader.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>watchedFoldersTabPage.Text</Name>
+    <StringID>26</StringID>
+    <Selected>true</Selected>
+    <ResourceName>watchedFoldersTabPage.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>logTabPage.Text</Name>
+    <StringID>27</StringID>
+    <Selected>true</Selected>
+    <ResourceName>logTabPage.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>removeRecentFileToolStripMenuItem.Text</Name>
+    <StringID>28</StringID>
+    <Selected>true</Selected>
+    <ResourceName>removeRecentFileToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>enterPassphraseToolStripMenuItem.Text</Name>
+    <StringID>29</StringID>
+    <Selected>true</Selected>
+    <ResourceName>enterPassphraseToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>progressContextCancelToolStripMenuItem.Text</Name>
+    <StringID>30</StringID>
+    <Selected>true</Selected>
+    <ResourceName>progressContextCancelToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.AxCryptAboutDescription</Name>
+    <StringID>100</StringID>
+    <Selected>true</Selected>
+    <ResourceName>AxCryptAboutDescription</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.About</Name>
+    <StringID>101</StringID>
+    <Selected>true</Selected>
+    <ResourceName>About</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.AxCryptAboutDescription</Name>
+    <StringID>102</StringID>
+    <Selected>true</Selected>
+    <ResourceName>AxCryptAboutDescription</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.Exception</Name>
+    <StringID>103</StringID>
+    <Selected>true</Selected>
+    <ResourceName>Exception</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.updateToolStripButton.Text</Name>
+    <StringID>8</StringID>
+    <Selected>true</Selected>
+    <ResourceName>updateToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.toolStripButtonEncrypt.ToolTipText</Name>
+    <StringID>5</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonEncrypt.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.debugToolStripMenuItem.Text</Name>
+    <StringID>90</StringID>
+    <Selected>true</Selected>
+    <ResourceName>debugToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.trayNotifyIcon.Text</Name>
+    <StringID>1</StringID>
+    <Selected>true</Selected>
+    <ResourceName>trayNotifyIcon.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.toolStripButtonEncrypt.Text</Name>
+    <StringID>4</StringID>
+    <Selected>true</Selected>
+    <ResourceName>toolStripButtonEncrypt.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.Invalid_URL</Name>
+    <StringID>104</StringID>
+    <Selected>true</Selected>
+    <ResourceName>Invalid_URL</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>englishLanguageToolStripMenuItem.Tag</Name>
+    <StringID>75</StringID>
+    <Selected>true</Selected>
+    <ResourceName>englishLanguageToolStripMenuItem.Tag</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>swedishLanguageToolStripMenuItem.Tag</Name>
+    <StringID>76</StringID>
+    <Selected>true</Selected>
+    <ResourceName>swedishLanguageToolStripMenuItem.Tag</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>encryptionKeyToolStripButton.Text</Name>
+    <StringID>99</StringID>
+    <Selected>true</Selected>
+    <ResourceName>encryptionKeyToolStripButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>encryptToolStripButton.ToolTipText</Name>
+    <StringID>105</StringID>
+    <Selected>true</Selected>
+    <ResourceName>encryptToolStripButton.ToolTipText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>wipeToolStripMenuItem.Text</Name>
+    <StringID>106</StringID>
+    <Selected>true</Selected>
+    <ResourceName>wipeToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>AxCryptMainForm.cs</Component>
+    <Name>decryptAndRemoveFromListToolStripMenuItem.Text</Name>
+    <StringID>107</StringID>
+    <Selected>true</Selected>
+    <ResourceName>decryptAndRemoveFromListToolStripMenuItem.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>promptLabel.Text</Name>
+    <StringID>108</StringID>
+    <Selected>true</Selected>
+    <ResourceName>promptLabel.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>FileNameLabel.Text</Name>
+    <Selected>false</Selected>
+    <ResourceName>FileNameLabel.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>noButton.Text</Name>
+    <StringID>110</StringID>
+    <Selected>true</Selected>
+    <ResourceName>noButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>yesButton.Text</Name>
+    <StringID>111</StringID>
+    <Selected>true</Selected>
+    <ResourceName>yesButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>ConfirmAllCheckBox.Text</Name>
+    <StringID>112</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ConfirmAllCheckBox.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>cancelButton.Text</Name>
+    <StringID>113</StringID>
+    <Selected>true</Selected>
+    <ResourceName>cancelButton.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>ConfirmWipeDialog.cs</Component>
+    <Name>ConfirmWipeDialog.Text</Name>
+    <StringID>114</StringID>
+    <Selected>true</Selected>
+    <ResourceName>$this.Text</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.LoggedOffStatusText</Name>
+    <StringID>115</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LoggedOffStatusText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.LoggedOnStatusText</Name>
+    <StringID>116</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LoggedOnStatusText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.NoDefaultEncryptionKeySetToolTip</Name>
+    <StringID>117</StringID>
+    <Selected>true</Selected>
+    <ResourceName>NoDefaultEncryptionKeySetToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.DefaultEncryptionKeyIsIsetToolTip</Name>
+    <StringID>118</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DefaultEncryptionKeyIsIsetToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.DecryptedFileToolTip</Name>
+    <StringID>119</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.DecryptedUnknownKeyFileToolTip</Name>
+    <StringID>120</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedUnknownKeyFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.InactiveFileToolTip</Name>
+    <StringID>121</StringID>
+    <Selected>true</Selected>
+    <ResourceName>InactiveFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.ActiveFileToolTip</Name>
+    <StringID>122</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ActiveFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.ActiveFileKnownKeyToolTip</Name>
+    <StringID>123</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ActiveFileKnownKeyToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Resources.WipeFileSelectFileDialogTitle</Name>
+    <StringID>124</StringID>
+    <Selected>true</Selected>
+    <ResourceName>WipeFileSelectFileDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.ActiveFileKnownKeyToolTip</Name>
+    <StringID>125</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ActiveFileKnownKeyToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.ActiveFileToolTip</Name>
+    <StringID>126</StringID>
+    <Selected>true</Selected>
+    <ResourceName>ActiveFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DecryptedFileToolTip</Name>
+    <StringID>127</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DecryptedUnknownKeyFileToolTip</Name>
+    <StringID>128</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DecryptedUnknownKeyFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.InactiveFileToolTip</Name>
+    <StringID>129</StringID>
+    <Selected>true</Selected>
+    <ResourceName>InactiveFileToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.DefaultEncryptionKeyIsIsetToolTip</Name>
+    <StringID>130</StringID>
+    <Selected>true</Selected>
+    <ResourceName>DefaultEncryptionKeyIsIsetToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.FileAlreadyEncrypted</Name>
+    <StringID>131</StringID>
+    <Selected>true</Selected>
+    <ResourceName>FileAlreadyEncrypted</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.InvalidPath</Name>
+    <StringID>132</StringID>
+    <Selected>true</Selected>
+    <ResourceName>InvalidPath</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.NoDefaultEncryptionKeySetToolTip</Name>
+    <StringID>133</StringID>
+    <Selected>true</Selected>
+    <ResourceName>NoDefaultEncryptionKeySetToolTip</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.WipeFileSelectFileDialogTitle</Name>
+    <StringID>134</StringID>
+    <Selected>true</Selected>
+    <ResourceName>WipeFileSelectFileDialogTitle</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.LoggedOffStatusText</Name>
+    <StringID>135</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LoggedOffStatusText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <Properties>
+    <Component>Resources.resx</Component>
+    <Name>Axantum.AxCrypt.Properties.Resources.LoggedOnStatusText</Name>
+    <StringID>136</StringID>
+    <Selected>true</Selected>
+    <ResourceName>LoggedOnStatusText</ResourceName>
+    <Hidden>false</Hidden>
+  </Properties>
+  <GeneralAttributes>
+    <Name>StatusHash</Name>
+    <TextValue>KeJGQ6YyjLTqiTc4uJxjuELOJOc=</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>XmlDatabaseVersion</Name>
+    <TextValue>1</TextValue>
+    <NumValue>1</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>Dirty</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>OriginalLanguageIetfTag</Name>
+    <TextValue>en</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>GenerateMultilangResx</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>UseNamedResources</Name>
+    <TextValue>True</TextValue>
+    <NumValue>1</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>ResxForOriginalLang</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>MlHideCommentString</Name>
+    <TextValue>MLHIDE</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>AlwaysRescanSource</Name>
+    <TextValue>True</TextValue>
+    <NumValue>1</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>AlwaysRescanControls</Name>
+    <TextValue>True</TextValue>
+    <NumValue>1</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>ScanInitializeComponents</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>HandleCppCliAsManaged</Name>
+    <TextValue>True</TextValue>
+    <NumValue>1</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>MfcSatelliteDlls</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>MfcPerLanguageRcFile</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>MfcSatForOriginalLang</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+  <GeneralAttributes>
+    <Name>AlternativeSupport</Name>
+    <TextValue>False</TextValue>
+    <NumValue>0</NumValue>
+  </GeneralAttributes>
+</MdbTranslationStore>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/AxantumStrongName.pfx b/Axantum.AxCrypt/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Axantum.AxCrypt/AxantumStrongName.pfx differ
diff --git a/Axantum.AxCrypt/ConfirmWipeDialog.Designer.cs b/Axantum.AxCrypt/ConfirmWipeDialog.Designer.cs
new file mode 100644
index 0000000..a0c5d29
--- /dev/null
+++ b/Axantum.AxCrypt/ConfirmWipeDialog.Designer.cs
@@ -0,0 +1,120 @@
+namespace Axantum.AxCrypt
+{
+    partial class ConfirmWipeDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ConfirmWipeDialog));
+            this._promptLabel = new System.Windows.Forms.Label();
+            this.FileNameLabel = new System.Windows.Forms.Label();
+            this._iconPictureBox = new System.Windows.Forms.PictureBox();
+            this._noButton = new System.Windows.Forms.Button();
+            this._yesButton = new System.Windows.Forms.Button();
+            this.ConfirmAllCheckBox = new System.Windows.Forms.CheckBox();
+            this._cancelButton = new System.Windows.Forms.Button();
+            ((System.ComponentModel.ISupportInitialize)(this._iconPictureBox)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // promptLabel
+            // 
+            this._promptLabel.CausesValidation = false;
+            resources.ApplyResources(this._promptLabel, "promptLabel");
+            this._promptLabel.Name = "promptLabel";
+            this._promptLabel.Click += new System.EventHandler(this.promptLabel_Click);
+            // 
+            // FileNameLabel
+            // 
+            this.FileNameLabel.AutoEllipsis = true;
+            resources.ApplyResources(this.FileNameLabel, "FileNameLabel");
+            this.FileNameLabel.Name = "FileNameLabel";
+            // 
+            // iconPictureBox
+            // 
+            resources.ApplyResources(this._iconPictureBox, "iconPictureBox");
+            this._iconPictureBox.Name = "iconPictureBox";
+            this._iconPictureBox.TabStop = false;
+            // 
+            // noButton
+            // 
+            resources.ApplyResources(this._noButton, "noButton");
+            this._noButton.DialogResult = System.Windows.Forms.DialogResult.No;
+            this._noButton.Name = "noButton";
+            this._noButton.UseVisualStyleBackColor = true;
+            // 
+            // yesButton
+            // 
+            resources.ApplyResources(this._yesButton, "yesButton");
+            this._yesButton.DialogResult = System.Windows.Forms.DialogResult.Yes;
+            this._yesButton.Name = "yesButton";
+            this._yesButton.UseVisualStyleBackColor = true;
+            // 
+            // ConfirmAllCheckBox
+            // 
+            resources.ApplyResources(this.ConfirmAllCheckBox, "ConfirmAllCheckBox");
+            this.ConfirmAllCheckBox.Name = "ConfirmAllCheckBox";
+            this.ConfirmAllCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // cancelButton
+            // 
+            resources.ApplyResources(this._cancelButton, "cancelButton");
+            this._cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this._cancelButton.Name = "cancelButton";
+            this._cancelButton.UseVisualStyleBackColor = true;
+            // 
+            // ConfirmWipeDialog
+            // 
+            this.AcceptButton = this._cancelButton;
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this._cancelButton;
+            this.Controls.Add(this._cancelButton);
+            this.Controls.Add(this.ConfirmAllCheckBox);
+            this.Controls.Add(this._yesButton);
+            this.Controls.Add(this._noButton);
+            this.Controls.Add(this._iconPictureBox);
+            this.Controls.Add(this.FileNameLabel);
+            this.Controls.Add(this._promptLabel);
+            this.Name = "ConfirmWipeDialog";
+            this.Load += new System.EventHandler(this.ConfirmWipeDialog_Load);
+            ((System.ComponentModel.ISupportInitialize)(this._iconPictureBox)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label _promptLabel;
+        private System.Windows.Forms.PictureBox _iconPictureBox;
+        private System.Windows.Forms.Button _noButton;
+        private System.Windows.Forms.Button _yesButton;
+        private System.Windows.Forms.Button _cancelButton;
+        internal System.Windows.Forms.CheckBox ConfirmAllCheckBox;
+        internal System.Windows.Forms.Label FileNameLabel;
+
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/ConfirmWipeDialog.cs b/Axantum.AxCrypt/ConfirmWipeDialog.cs
new file mode 100644
index 0000000..7652442
--- /dev/null
+++ b/Axantum.AxCrypt/ConfirmWipeDialog.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Drawing;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class ConfirmWipeDialog : Form
+    {
+        public ConfirmWipeDialog()
+        {
+            InitializeComponent();
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void ConfirmWipeDialog_Load(object sender, EventArgs e)
+        {
+            _iconPictureBox.Image = SystemIcons.Warning.ToBitmap();
+        }
+
+        private void promptLabel_Click(object sender, EventArgs e)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/ConfirmWipeDialog.resx b/Axantum.AxCrypt/ConfirmWipeDialog.resx
new file mode 100644
index 0000000..fefff7d
--- /dev/null
+++ b/Axantum.AxCrypt/ConfirmWipeDialog.resx
@@ -0,0 +1,705 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="promptLabel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>75, 9</value>
+  </data>
+  <data name="promptLabel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>387, 45</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="promptLabel.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="promptLabel.Text" xml:space="preserve">
+    <value>Are you sure want to permanently delete this document? This action cannot be undone.</value>
+  </data>
+  <data name=">>promptLabel.Name" xml:space="preserve">
+    <value>promptLabel</value>
+  </data>
+  <data name=">>promptLabel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>promptLabel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>promptLabel.ZOrder" xml:space="preserve">
+    <value>6</value>
+  </data>
+  <data name="FileNameLabel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>75, 54</value>
+  </data>
+  <data name="FileNameLabel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>387, 24</value>
+  </data>
+  <data name="FileNameLabel.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name="FileNameLabel.Text" xml:space="preserve">
+    <value>A Document.ext</value>
+  </data>
+  <data name=">>FileNameLabel.Name" xml:space="preserve">
+    <value>FileNameLabel</value>
+  </data>
+  <data name=">>FileNameLabel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNameLabel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>FileNameLabel.ZOrder" xml:space="preserve">
+    <value>5</value>
+  </data>
+  <data name="iconPictureBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>13, 9</value>
+  </data>
+  <data name="iconPictureBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>48, 48</value>
+  </data>
+  <data name="iconPictureBox.TabIndex" type="System.Int32, mscorlib">
+    <value>2</value>
+  </data>
+  <data name=">>iconPictureBox.Name" xml:space="preserve">
+    <value>iconPictureBox</value>
+  </data>
+  <data name=">>iconPictureBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.PictureBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>iconPictureBox.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>iconPictureBox.ZOrder" xml:space="preserve">
+    <value>4</value>
+  </data>
+  <data name="noButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="noButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>306, 116</value>
+  </data>
+  <data name="noButton.MinimumSize" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="noButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="noButton.TabIndex" type="System.Int32, mscorlib">
+    <value>3</value>
+  </data>
+  <data name="noButton.Text" xml:space="preserve">
+    <value>&No</value>
+  </data>
+  <data name=">>noButton.Name" xml:space="preserve">
+    <value>noButton</value>
+  </data>
+  <data name=">>noButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>noButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>noButton.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+  <data name="yesButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="yesButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>225, 116</value>
+  </data>
+  <data name="yesButton.MinimumSize" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="yesButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="yesButton.TabIndex" type="System.Int32, mscorlib">
+    <value>4</value>
+  </data>
+  <data name="yesButton.Text" xml:space="preserve">
+    <value>&Yes</value>
+  </data>
+  <data name=">>yesButton.Name" xml:space="preserve">
+    <value>yesButton</value>
+  </data>
+  <data name=">>yesButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>yesButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>yesButton.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="ConfirmAllCheckBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="ConfirmAllCheckBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>78, 81</value>
+  </data>
+  <data name="ConfirmAllCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>162, 17</value>
+  </data>
+  <data name="ConfirmAllCheckBox.TabIndex" type="System.Int32, mscorlib">
+    <value>5</value>
+  </data>
+  <data name="ConfirmAllCheckBox.Text" xml:space="preserve">
+    <value>Do this for &all remaining documents?</value>
+  </data>
+  <data name=">>ConfirmAllCheckBox.Name" xml:space="preserve">
+    <value>ConfirmAllCheckBox</value>
+  </data>
+  <data name=">>ConfirmAllCheckBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ConfirmAllCheckBox.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>ConfirmAllCheckBox.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="cancelButton.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="cancelButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>387, 116</value>
+  </data>
+  <data name="cancelButton.MinimumSize" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="cancelButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="cancelButton.TabIndex" type="System.Int32, mscorlib">
+    <value>6</value>
+  </data>
+  <data name="cancelButton.Text" xml:space="preserve">
+    <value>&Cancel All</value>
+  </data>
+  <data name=">>cancelButton.Name" xml:space="preserve">
+    <value>cancelButton</value>
+  </data>
+  <data name=">>cancelButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>cancelButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>cancelButton.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>474, 151</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>AxCrypt Secure Delete</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>ConfirmWipeDialog</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/ConfirmWipeDialog.sv.resx b/Axantum.AxCrypt/ConfirmWipeDialog.sv.resx
new file mode 100644
index 0000000..0e905ec
--- /dev/null
+++ b/Axantum.AxCrypt/ConfirmWipeDialog.sv.resx
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="cancelButton.Text" xml:space="preserve">
+    <value>&Avbryt allt</value>
+  </data>
+  <data name="ConfirmAllCheckBox.Text" xml:space="preserve">
+    <value>Gör detta för &alla återstående dokument?</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>AxCrypt Säker Radering</value>
+  </data>
+  <data name="noButton.Text" xml:space="preserve">
+    <value>&Nej</value>
+  </data>
+  <data name="promptLabel.Text" xml:space="preserve">
+    <value>Är du säker att du vill radera dokumentet? Detta går inte att ångra.</value>
+  </data>
+  <data name="yesButton.Text" xml:space="preserve">
+    <value>&Ja</value>
+  </data>
+  <data name="FileNameLabel.Text" xml:space="preserve">
+    <value>Ett Dokument.ext</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/CreateNewAccountDialog.Designer.cs b/Axantum.AxCrypt/CreateNewAccountDialog.Designer.cs
new file mode 100644
index 0000000..c024ec3
--- /dev/null
+++ b/Axantum.AxCrypt/CreateNewAccountDialog.Designer.cs
@@ -0,0 +1,207 @@
+namespace Axantum.AxCrypt
+{
+    partial class CreateNewAccountDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.PassphraseTextBox = new System.Windows.Forms.TextBox();
+            this.PassphraseGroupBox = new System.Windows.Forms.GroupBox();
+            this.ShowPassphraseCheckBox = new System.Windows.Forms.CheckBox();
+            this.VerifyPassphraseTextbox = new System.Windows.Forms.TextBox();
+            this._label1 = new System.Windows.Forms.Label();
+            this._panel1 = new System.Windows.Forms.Panel();
+            this._buttonCancel = new System.Windows.Forms.Button();
+            this._buttonOk = new System.Windows.Forms.Button();
+            this.EmailTextBox = new System.Windows.Forms.TextBox();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this._errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this._errorProvider2 = new System.Windows.Forms.ErrorProvider(this.components);
+            this._errorProvider3 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.PassphraseGroupBox.SuspendLayout();
+            this._panel1.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider3)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // PassphraseTextBox
+            // 
+            this.PassphraseTextBox.CausesValidation = false;
+            this.PassphraseTextBox.Location = new System.Drawing.Point(7, 20);
+            this.PassphraseTextBox.Name = "PassphraseTextBox";
+            this.PassphraseTextBox.Size = new System.Drawing.Size(242, 20);
+            this.PassphraseTextBox.TabIndex = 0;
+            // 
+            // PassphraseGroupBox
+            // 
+            this.PassphraseGroupBox.AutoSize = true;
+            this.PassphraseGroupBox.Controls.Add(this.ShowPassphraseCheckBox);
+            this.PassphraseGroupBox.Controls.Add(this.VerifyPassphraseTextbox);
+            this.PassphraseGroupBox.Controls.Add(this._label1);
+            this.PassphraseGroupBox.Controls.Add(this.PassphraseTextBox);
+            this.PassphraseGroupBox.Location = new System.Drawing.Point(2, 47);
+            this.PassphraseGroupBox.Name = "PassphraseGroupBox";
+            this.PassphraseGroupBox.Size = new System.Drawing.Size(280, 125);
+            this.PassphraseGroupBox.TabIndex = 1;
+            this.PassphraseGroupBox.TabStop = false;
+            this.PassphraseGroupBox.Text = "Enter Passphrase";
+            // 
+            // ShowPassphraseCheckBox
+            // 
+            this.ShowPassphraseCheckBox.AutoSize = true;
+            this.ShowPassphraseCheckBox.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this.ShowPassphraseCheckBox.Location = new System.Drawing.Point(7, 89);
+            this.ShowPassphraseCheckBox.Name = "ShowPassphraseCheckBox";
+            this.ShowPassphraseCheckBox.Size = new System.Drawing.Size(111, 17);
+            this.ShowPassphraseCheckBox.TabIndex = 3;
+            this.ShowPassphraseCheckBox.Text = "Show Passphrase";
+            this.ShowPassphraseCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // VerifyPassphraseTextbox
+            // 
+            this.VerifyPassphraseTextbox.Location = new System.Drawing.Point(6, 59);
+            this.VerifyPassphraseTextbox.Name = "VerifyPassphraseTextbox";
+            this.VerifyPassphraseTextbox.Size = new System.Drawing.Size(243, 20);
+            this.VerifyPassphraseTextbox.TabIndex = 2;
+            // 
+            // _label1
+            // 
+            this._label1.AutoSize = true;
+            this._label1.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._label1.Location = new System.Drawing.Point(6, 43);
+            this._label1.Name = "_label1";
+            this._label1.Size = new System.Drawing.Size(91, 13);
+            this._label1.TabIndex = 1;
+            this._label1.Text = "Verify Passphrase";
+            // 
+            // _panel1
+            // 
+            this._panel1.Controls.Add(this._buttonCancel);
+            this._panel1.Controls.Add(this._buttonOk);
+            this._panel1.Location = new System.Drawing.Point(42, 177);
+            this._panel1.Name = "_panel1";
+            this._panel1.Size = new System.Drawing.Size(200, 37);
+            this._panel1.TabIndex = 1;
+            // 
+            // _buttonCancel
+            // 
+            this._buttonCancel.CausesValidation = false;
+            this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this._buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._buttonCancel.Location = new System.Drawing.Point(103, 11);
+            this._buttonCancel.Name = "_buttonCancel";
+            this._buttonCancel.Size = new System.Drawing.Size(75, 23);
+            this._buttonCancel.TabIndex = 0;
+            this._buttonCancel.Text = "Cancel";
+            this._buttonCancel.UseVisualStyleBackColor = true;
+            // 
+            // _buttonOk
+            // 
+            this._buttonOk.CausesValidation = false;
+            this._buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
+            this._buttonOk.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._buttonOk.Location = new System.Drawing.Point(22, 11);
+            this._buttonOk.Name = "_buttonOk";
+            this._buttonOk.Size = new System.Drawing.Size(75, 23);
+            this._buttonOk.TabIndex = 0;
+            this._buttonOk.Text = "OK";
+            this._buttonOk.UseVisualStyleBackColor = true;
+            this._buttonOk.Click += new System.EventHandler(this._buttonOk_Click);
+            // 
+            // EmailTextBox
+            // 
+            this.EmailTextBox.Location = new System.Drawing.Point(9, 18);
+            this.EmailTextBox.Name = "EmailTextBox";
+            this.EmailTextBox.Size = new System.Drawing.Size(242, 20);
+            this.EmailTextBox.TabIndex = 0;
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.EmailTextBox);
+            this.groupBox1.Location = new System.Drawing.Point(2, 2);
+            this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 3, 13, 3);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(280, 44);
+            this.groupBox1.TabIndex = 0;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "Email";
+            // 
+            // _errorProvider1
+            // 
+            this._errorProvider1.ContainerControl = this;
+            // 
+            // _errorProvider2
+            // 
+            this._errorProvider2.ContainerControl = this;
+            // 
+            // _errorProvider3
+            // 
+            this._errorProvider3.ContainerControl = this;
+            // 
+            // CreateNewAccountDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(284, 237);
+            this.Controls.Add(this.groupBox1);
+            this.Controls.Add(this.PassphraseGroupBox);
+            this.Controls.Add(this._panel1);
+            this.Name = "CreateNewAccountDialog";
+            this.Text = "Create Account";
+            this.Load += new System.EventHandler(this.CreateNewAccountDialog_Load);
+            this.PassphraseGroupBox.ResumeLayout(false);
+            this.PassphraseGroupBox.PerformLayout();
+            this._panel1.ResumeLayout(false);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider3)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        internal System.Windows.Forms.TextBox PassphraseTextBox;
+        internal System.Windows.Forms.GroupBox PassphraseGroupBox;
+        internal System.Windows.Forms.CheckBox ShowPassphraseCheckBox;
+        private System.Windows.Forms.TextBox VerifyPassphraseTextbox;
+        private System.Windows.Forms.Label _label1;
+        private System.Windows.Forms.Panel _panel1;
+        private System.Windows.Forms.Button _buttonCancel;
+        private System.Windows.Forms.Button _buttonOk;
+        internal System.Windows.Forms.TextBox EmailTextBox;
+        private System.Windows.Forms.GroupBox groupBox1;
+        private System.Windows.Forms.ErrorProvider _errorProvider1;
+        private System.Windows.Forms.ErrorProvider _errorProvider2;
+        private System.Windows.Forms.ErrorProvider _errorProvider3;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/CreateNewAccountDialog.cs b/Axantum.AxCrypt/CreateNewAccountDialog.cs
new file mode 100644
index 0000000..0c180bd
--- /dev/null
+++ b/Axantum.AxCrypt/CreateNewAccountDialog.cs
@@ -0,0 +1,90 @@
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class CreateNewAccountDialog : Form
+    {
+        private CreateNewAccountViewModel _viewModel;
+
+        public CreateNewAccountDialog(Form parent, string passphrase)
+        {
+            InitializeComponent();
+            _viewModel = new CreateNewAccountViewModel(Instance.AsymmetricKeysStore, passphrase);
+            PassphraseTextBox.TextChanged += (sender, e) => { _viewModel.Passphrase = PassphraseTextBox.Text; };
+            VerifyPassphraseTextbox.TextChanged += (sender, e) => { _viewModel.Verification = VerifyPassphraseTextbox.Text; };
+            EmailTextBox.TextChanged += (sender, e) => { _viewModel.UserEmail = EmailTextBox.Text; };
+            ShowPassphraseCheckBox.CheckedChanged += (sender, e) => { _viewModel.ShowPassphrase = ShowPassphraseCheckBox.Checked; };
+
+            Owner = parent;
+            Owner.Activated += (sender, e) => Activate();
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void CreateNewAccountDialog_Load(object sender, EventArgs e)
+        {
+            if (DesignMode)
+            {
+                return;
+            }
+
+            _viewModel.BindPropertyChanged("ShowPassphrase", (bool show) => { PassphraseTextBox.UseSystemPasswordChar = VerifyPassphraseTextbox.UseSystemPasswordChar = !(ShowPassphraseCheckBox.Checked = show); });
+            _viewModel.BindPropertyChanged("Passphrase", (string p) => { PassphraseTextBox.Text = p; });
+            _viewModel.BindPropertyChanged("Verification", (string v) => { VerifyPassphraseTextbox.Text = v; });
+
+            EmailTextBox.Focus();
+        }
+
+        private void _buttonOk_Click(object sender, EventArgs e)
+        {
+            if (!AdHocValidationDueToMonoLimitations())
+            {
+                DialogResult = DialogResult.None;
+                return;
+            }
+            _viewModel.CreateAccount.Execute(null);
+        }
+
+        private bool AdHocValidationDueToMonoLimitations()
+        {
+            bool validated = true;
+            if (_viewModel["Passphrase"].Length > 0)
+            {
+                _errorProvider1.SetError(PassphraseTextBox, Resources.WrongPassphrase);
+                validated = false;
+            }
+            else
+            {
+                _errorProvider1.Clear();
+            }
+            if (_viewModel["Verification"].Length > 0)
+            {
+                _errorProvider2.SetError(VerifyPassphraseTextbox, Resources.PassphraseVerificationMismatch);
+                validated = false;
+            }
+            else
+            {
+                _errorProvider2.Clear();
+            }
+            if (_viewModel["UserEmail"].Length > 0)
+            {
+                _errorProvider3.SetError(EmailTextBox, Resources.BadEmail);
+                validated = false;
+            }
+            else
+            {
+                _errorProvider3.Clear();
+            }
+            return validated;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/CreateNewAccountDialog.resx b/Axantum.AxCrypt/CreateNewAccountDialog.resx
new file mode 100644
index 0000000..925d82c
--- /dev/null
+++ b/Axantum.AxCrypt/CreateNewAccountDialog.resx
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>287, 17</value>
+  </metadata>
+  <metadata name="_errorProvider2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>422, 17</value>
+  </metadata>
+  <metadata name="_errorProvider3.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>557, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugLogOutputDialog.Designer.cs b/Axantum.AxCrypt/DebugLogOutputDialog.Designer.cs
new file mode 100644
index 0000000..9ca0aab
--- /dev/null
+++ b/Axantum.AxCrypt/DebugLogOutputDialog.Designer.cs
@@ -0,0 +1,62 @@
+namespace Axantum.AxCrypt
+{
+    partial class DebugLogOutputDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this._logOutputTextBox = new System.Windows.Forms.TextBox();
+            this.SuspendLayout();
+            // 
+            // _logOutputTextBox
+            // 
+            this._logOutputTextBox.Dock = System.Windows.Forms.DockStyle.Fill;
+            this._logOutputTextBox.Location = new System.Drawing.Point(0, 0);
+            this._logOutputTextBox.Multiline = true;
+            this._logOutputTextBox.Name = "_logOutputTextBox";
+            this._logOutputTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+            this._logOutputTextBox.Size = new System.Drawing.Size(773, 261);
+            this._logOutputTextBox.TabIndex = 0;
+            // 
+            // DebugLogOutputDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(773, 261);
+            this.Controls.Add(this._logOutputTextBox);
+            this.Name = "DebugLogOutputDialog";
+            this.Text = "Debug Log Output";
+            this.Load += new System.EventHandler(this.DebugLogOutputDialog_Load);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.TextBox _logOutputTextBox;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugLogOutputDialog.cs b/Axantum.AxCrypt/DebugLogOutputDialog.cs
new file mode 100644
index 0000000..765ff8e
--- /dev/null
+++ b/Axantum.AxCrypt/DebugLogOutputDialog.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class DebugLogOutputDialog : Form
+    {
+        public DebugLogOutputDialog()
+        {
+            InitializeComponent();
+        }
+
+        private void DebugLogOutputDialog_Load(object sender, EventArgs e)
+        {
+            FormClosing += (fsender, fe) => { if (!AllowClose) { Visible = false; fe.Cancel = true; } };
+        }
+
+        public void AppendText(string text)
+        {
+            _logOutputTextBox.AppendText(text);
+        }
+
+        public bool AllowClose { get; set; }
+    }
+}
diff --git a/Axantum.AxCrypt/DebugLogOutputDialog.resx b/Axantum.AxCrypt/DebugLogOutputDialog.resx
new file mode 100644
index 0000000..29dcb1b
--- /dev/null
+++ b/Axantum.AxCrypt/DebugLogOutputDialog.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugOptionsDialog.Designer.cs b/Axantum.AxCrypt/DebugOptionsDialog.Designer.cs
new file mode 100644
index 0000000..f46e902
--- /dev/null
+++ b/Axantum.AxCrypt/DebugOptionsDialog.Designer.cs
@@ -0,0 +1,97 @@
+namespace Axantum.AxCrypt
+{
+    partial class DebugOptionsDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DebugOptionsDialog));
+            this._label1 = new System.Windows.Forms.Label();
+            this.UpdateCheckServiceUrl = new System.Windows.Forms.TextBox();
+            this._okButton = new System.Windows.Forms.Button();
+            this._cancelButton = new System.Windows.Forms.Button();
+            this._errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // label1
+            // 
+            resources.ApplyResources(this._label1, "label1");
+            this._label1.Name = "label1";
+            // 
+            // UpdateCheckServiceUrl
+            // 
+            resources.ApplyResources(this.UpdateCheckServiceUrl, "UpdateCheckServiceUrl");
+            this.UpdateCheckServiceUrl.Name = "UpdateCheckServiceUrl";
+            this.UpdateCheckServiceUrl.Validating += new System.ComponentModel.CancelEventHandler(this.UpdateCheckServiceUrl_Validating);
+            this.UpdateCheckServiceUrl.Validated += new System.EventHandler(this.UpdateCheckServiceUrl_Validated);
+            // 
+            // okButton
+            // 
+            this._okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
+            resources.ApplyResources(this._okButton, "okButton");
+            this._okButton.Name = "okButton";
+            this._okButton.UseVisualStyleBackColor = true;
+            // 
+            // cancelButton
+            // 
+            this._cancelButton.CausesValidation = false;
+            this._cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            resources.ApplyResources(this._cancelButton, "cancelButton");
+            this._cancelButton.Name = "cancelButton";
+            this._cancelButton.UseVisualStyleBackColor = true;
+            // 
+            // errorProvider1
+            // 
+            this._errorProvider1.ContainerControl = this;
+            // 
+            // DebugOptionsDialog
+            // 
+            this.AcceptButton = this._okButton;
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this._cancelButton;
+            this.Controls.Add(this._cancelButton);
+            this.Controls.Add(this._okButton);
+            this.Controls.Add(this.UpdateCheckServiceUrl);
+            this.Controls.Add(this._label1);
+            this.Name = "DebugOptionsDialog";
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Label _label1;
+        internal System.Windows.Forms.TextBox UpdateCheckServiceUrl;
+        private System.Windows.Forms.Button _okButton;
+        private System.Windows.Forms.Button _cancelButton;
+        private System.Windows.Forms.ErrorProvider _errorProvider1;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugOptionsDialog.cs b/Axantum.AxCrypt/DebugOptionsDialog.cs
new file mode 100644
index 0000000..9958667
--- /dev/null
+++ b/Axantum.AxCrypt/DebugOptionsDialog.cs
@@ -0,0 +1,30 @@
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class DebugOptionsDialog : Form
+    {
+        public DebugOptionsDialog()
+        {
+            InitializeComponent();
+        }
+
+        private void UpdateCheckServiceUrl_Validating(object sender, CancelEventArgs e)
+        {
+            if (!Uri.IsWellFormedUriString(UpdateCheckServiceUrl.Text, UriKind.Absolute))
+            {
+                e.Cancel = true;
+                UpdateCheckServiceUrl.SelectAll();
+                _errorProvider1.SetError(UpdateCheckServiceUrl, Axantum.AxCrypt.Properties.Resources.Invalid_URL);
+            }
+        }
+
+        private void UpdateCheckServiceUrl_Validated(object sender, EventArgs e)
+        {
+            _errorProvider1.SetError(UpdateCheckServiceUrl, String.Empty);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugOptionsDialog.resx b/Axantum.AxCrypt/DebugOptionsDialog.resx
new file mode 100644
index 0000000..9b09c9a
--- /dev/null
+++ b/Axantum.AxCrypt/DebugOptionsDialog.resx
@@ -0,0 +1,245 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="label1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="label1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 17</value>
+  </data>
+  <data name="label1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>131, 13</value>
+  </data>
+  <data name="label1.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="label1.Text" xml:space="preserve">
+    <value>Update Check Service Url</value>
+  <comment>@Invariant</comment></data>
+  <data name=">>label1.Name" xml:space="preserve">
+    <value>label1</value>
+  </data>
+  <data name=">>label1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>label1.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>label1.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+  <data name="UpdateCheckServiceUrl.Location" type="System.Drawing.Point, System.Drawing">
+    <value>149, 14</value>
+  </data>
+  <data name="UpdateCheckServiceUrl.Size" type="System.Drawing.Size, System.Drawing">
+    <value>441, 20</value>
+  </data>
+  <data name="UpdateCheckServiceUrl.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name=">>UpdateCheckServiceUrl.Name" xml:space="preserve">
+    <value>UpdateCheckServiceUrl</value>
+  </data>
+  <data name=">>UpdateCheckServiceUrl.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>UpdateCheckServiceUrl.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>UpdateCheckServiceUrl.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="okButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>231, 52</value>
+  </data>
+  <data name="okButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="okButton.TabIndex" type="System.Int32, mscorlib">
+    <value>2</value>
+  </data>
+  <data name="okButton.Text" xml:space="preserve">
+    <value>OK</value>
+  <comment>@Invariant</comment></data>
+  <data name=">>okButton.Name" xml:space="preserve">
+    <value>okButton</value>
+  </data>
+  <data name=">>okButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>okButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>okButton.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="cancelButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>322, 52</value>
+  </data>
+  <data name="cancelButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="cancelButton.TabIndex" type="System.Int32, mscorlib">
+    <value>3</value>
+  </data>
+  <data name="cancelButton.Text" xml:space="preserve">
+    <value>Cancel</value>
+  <comment>@Invariant</comment></data>
+  <data name=">>cancelButton.Name" xml:space="preserve">
+    <value>cancelButton</value>
+  </data>
+  <data name=">>cancelButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>cancelButton.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>cancelButton.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <metadata name="errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>628, 102</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>Debugging Options</value>
+  <comment>@Invariant</comment></data>
+  <data name=">>errorProvider1.Name" xml:space="preserve">
+    <value>errorProvider1</value>
+  </data>
+  <data name=">>errorProvider1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ErrorProvider, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>DebugOptionsDialog</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DebugOptionsDialog.sv.resx b/Axantum.AxCrypt/DebugOptionsDialog.sv.resx
new file mode 100644
index 0000000..5ea0895
--- /dev/null
+++ b/Axantum.AxCrypt/DebugOptionsDialog.sv.resx
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DecryptPassphraseDialog.Designer.cs b/Axantum.AxCrypt/DecryptPassphraseDialog.Designer.cs
new file mode 100644
index 0000000..144e9ae
--- /dev/null
+++ b/Axantum.AxCrypt/DecryptPassphraseDialog.Designer.cs
@@ -0,0 +1,119 @@
+namespace Axantum.AxCrypt
+{
+    partial class DecryptPassphraseDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DecryptPassphraseDialog));
+            this.PassphraseGroupBox = new System.Windows.Forms.GroupBox();
+            this.ShowPassphraseCheckBox = new System.Windows.Forms.CheckBox();
+            this.Passphrase = new System.Windows.Forms.TextBox();
+            this._panel1 = new System.Windows.Forms.Panel();
+            this._buttonCancel = new System.Windows.Forms.Button();
+            this._buttonOk = new System.Windows.Forms.Button();
+            this._fileNameLabel = new System.Windows.Forms.Label();
+            this.PassphraseGroupBox.SuspendLayout();
+            this._panel1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // PassphraseGroupBox
+            // 
+            resources.ApplyResources(this.PassphraseGroupBox, "PassphraseGroupBox");
+            this.PassphraseGroupBox.Controls.Add(this.ShowPassphraseCheckBox);
+            this.PassphraseGroupBox.Controls.Add(this.Passphrase);
+            this.PassphraseGroupBox.Name = "PassphraseGroupBox";
+            this.PassphraseGroupBox.TabStop = false;
+            // 
+            // ShowPassphraseCheckBox
+            // 
+            resources.ApplyResources(this.ShowPassphraseCheckBox, "ShowPassphraseCheckBox");
+            this.ShowPassphraseCheckBox.Name = "ShowPassphraseCheckBox";
+            this.ShowPassphraseCheckBox.UseVisualStyleBackColor = true;
+            this.ShowPassphraseCheckBox.CheckedChanged += new System.EventHandler(this.ShowPassphraseCheckBox_CheckedChanged);
+            // 
+            // Passphrase
+            // 
+            resources.ApplyResources(this.Passphrase, "Passphrase");
+            this.Passphrase.Name = "Passphrase";
+            // 
+            // _panel1
+            // 
+            this._panel1.Controls.Add(this._buttonCancel);
+            this._panel1.Controls.Add(this._buttonOk);
+            resources.ApplyResources(this._panel1, "_panel1");
+            this._panel1.Name = "_panel1";
+            // 
+            // _buttonCancel
+            // 
+            this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            resources.ApplyResources(this._buttonCancel, "_buttonCancel");
+            this._buttonCancel.Name = "_buttonCancel";
+            this._buttonCancel.UseVisualStyleBackColor = true;
+            // 
+            // _buttonOk
+            // 
+            this._buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
+            resources.ApplyResources(this._buttonOk, "_buttonOk");
+            this._buttonOk.Name = "_buttonOk";
+            this._buttonOk.UseVisualStyleBackColor = true;
+            // 
+            // _fileNameLabel
+            // 
+            resources.ApplyResources(this._fileNameLabel, "_fileNameLabel");
+            this._fileNameLabel.Name = "_fileNameLabel";
+            this._fileNameLabel.Click += new System.EventHandler(this._fileNameLabel_Click);
+            // 
+            // DecryptPassphraseDialog
+            // 
+            this.AcceptButton = this._buttonOk;
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this._buttonCancel;
+            this.Controls.Add(this._fileNameLabel);
+            this.Controls.Add(this._panel1);
+            this.Controls.Add(this.PassphraseGroupBox);
+            this.Name = "DecryptPassphraseDialog";
+            this.Load += new System.EventHandler(this.DecryptPassphraseDialog_Load);
+            this.PassphraseGroupBox.ResumeLayout(false);
+            this.PassphraseGroupBox.PerformLayout();
+            this._panel1.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        internal System.Windows.Forms.TextBox Passphrase;
+        private System.Windows.Forms.Panel _panel1;
+        private System.Windows.Forms.Button _buttonCancel;
+        private System.Windows.Forms.Button _buttonOk;
+        internal System.Windows.Forms.GroupBox PassphraseGroupBox;
+        internal System.Windows.Forms.CheckBox ShowPassphraseCheckBox;
+        private System.Windows.Forms.Label _fileNameLabel;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DecryptPassphraseDialog.cs b/Axantum.AxCrypt/DecryptPassphraseDialog.cs
new file mode 100644
index 0000000..3e05f2a
--- /dev/null
+++ b/Axantum.AxCrypt/DecryptPassphraseDialog.cs
@@ -0,0 +1,61 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.IO;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class DecryptPassphraseDialog : Form
+    {
+        public DecryptPassphraseDialog(string fullName)
+        {
+            InitializeComponent();
+            StartPosition = FormStartPosition.CenterParent;
+            _fileNameLabel.Text = Path.GetFileName(fullName);
+        }
+
+        private void DecryptPassphraseDialog_Load(object sender, System.EventArgs e)
+        {
+            ShowHidePassphrase();
+        }
+
+        private void ShowHidePassphrase()
+        {
+            Passphrase.UseSystemPasswordChar = !ShowPassphraseCheckBox.Checked;
+        }
+
+        private void ShowPassphraseCheckBox_CheckedChanged(object sender, System.EventArgs e)
+        {
+            ShowHidePassphrase();
+        }
+
+        private void _fileNameLabel_Click(object sender, System.EventArgs e)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DecryptPassphraseDialog.resx b/Axantum.AxCrypt/DecryptPassphraseDialog.resx
new file mode 100644
index 0000000..f85017b
--- /dev/null
+++ b/Axantum.AxCrypt/DecryptPassphraseDialog.resx
@@ -0,0 +1,727 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="PassphraseGroupBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="ShowPassphraseCheckBox.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="ShowPassphraseCheckBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 51</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>111, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.TabIndex" type="System.Int32, mscorlib">
+    <value>9</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Show Passphrase</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Name" xml:space="preserve">
+    <value>ShowPassphraseCheckBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="Passphrase.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 20</value>
+  </data>
+  <data name="Passphrase.Size" type="System.Drawing.Size, System.Drawing">
+    <value>242, 20</value>
+  </data>
+  <data name="Passphrase.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name=">>Passphrase.Name" xml:space="preserve">
+    <value>Passphrase</value>
+  </data>
+  <data name=">>Passphrase.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>Passphrase.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>Passphrase.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="PassphraseGroupBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 33</value>
+  </data>
+  <data name="PassphraseGroupBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>259, 87</value>
+  </data>
+  <data name="PassphraseGroupBox.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Enter Passphrase</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Name" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>PassphraseGroupBox.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name=">>_buttonCancel.Name" xml:space="preserve">
+    <value>_buttonCancel</value>
+  </data>
+  <data name=">>_buttonCancel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonCancel.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonCancel.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name=">>_buttonOk.Name" xml:space="preserve">
+    <value>_buttonOk</value>
+  </data>
+  <data name=">>_buttonOk.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonOk.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonOk.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="_panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>40, 121</value>
+  </data>
+  <data name="_panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>200, 46</value>
+  </data>
+  <data name="_panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>3</value>
+  </data>
+  <data name=">>_panel1.Name" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_panel1.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_panel1.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="_buttonCancel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>103, 11</value>
+  </data>
+  <data name="_buttonCancel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonCancel.TabIndex" type="System.Int32, mscorlib">
+    <value>9</value>
+  </data>
+  <data name="_buttonCancel.Text" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name=">>_buttonCancel.Name" xml:space="preserve">
+    <value>_buttonCancel</value>
+  </data>
+  <data name=">>_buttonCancel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonCancel.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonCancel.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_buttonOk.Location" type="System.Drawing.Point, System.Drawing">
+    <value>22, 11</value>
+  </data>
+  <data name="_buttonOk.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonOk.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="_buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name=">>_buttonOk.Name" xml:space="preserve">
+    <value>_buttonOk</value>
+  </data>
+  <data name=">>_buttonOk.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonOk.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonOk.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="_fileNameLabel.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="_fileNameLabel.Font" type="System.Drawing.Font, System.Drawing">
+    <value>Microsoft Sans Serif, 8.25pt, style=Bold</value>
+  </data>
+  <data name="_fileNameLabel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>9, 9</value>
+  </data>
+  <data name="_fileNameLabel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>41, 13</value>
+  </data>
+  <data name="_fileNameLabel.TabIndex" type="System.Int32, mscorlib">
+    <value>4</value>
+  </data>
+  <data name="_fileNameLabel.Text" xml:space="preserve">
+    <value>label1</value>
+  </data>
+  <data name=">>_fileNameLabel.Name" xml:space="preserve">
+    <value>_fileNameLabel</value>
+  </data>
+  <data name=">>_fileNameLabel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_fileNameLabel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>_fileNameLabel.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>281, 175</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
+    <value>CenterParent</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>AxCrypt</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>DecryptPassphraseDialog</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/DecryptPassphraseDialog.sv.resx b/Axantum.AxCrypt/DecryptPassphraseDialog.sv.resx
new file mode 100644
index 0000000..b3c2b1f
--- /dev/null
+++ b/Axantum.AxCrypt/DecryptPassphraseDialog.sv.resx
@@ -0,0 +1,553 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>93, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Visa Lösenord</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Ange Lösenord</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_panel1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_buttonCancel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_buttonCancel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>103, 11</value>
+  </data>
+  <data name="_buttonCancel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonCancel.TabIndex" type="System.Int32, mscorlib">
+    <value>9</value>
+  </data>
+  <data name="_buttonCancel.Text" xml:space="preserve">
+    <value>Avbryt</value>
+  </data>
+  <data name="_buttonOk.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_buttonOk.Location" type="System.Drawing.Point, System.Drawing">
+    <value>22, 11</value>
+  </data>
+  <data name="_buttonOk.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonOk.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="_buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name="_panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>40, 102</value>
+  </data>
+  <data name="_panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>200, 45</value>
+  </data>
+  <data name="_panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>3</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Extensions.cs b/Axantum.AxCrypt/Extensions.cs
new file mode 100644
index 0000000..38851c3
--- /dev/null
+++ b/Axantum.AxCrypt/Extensions.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    internal static class Extensions
+    {
+        public static void ShowWarning(this string message)
+        {
+            MessageBox.Show(message, "AxCrypt", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1, AxCryptMainForm.MessageBoxOptions);
+        }
+
+        public static Point Fallback(this Point value, Point fallback)
+        {
+            return value != default(Point) ? value : fallback;
+        }
+
+        public static IEnumerable<string> GetDragged(this DragEventArgs e)
+        {
+            IList<string> dropped = e.Data.GetData(DataFormats.FileDrop) as IList<string>;
+            if (dropped == null)
+            {
+                return new string[0];
+            }
+
+            return dropped;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/KnownFoldersDiscovery.cs b/Axantum.AxCrypt/KnownFoldersDiscovery.cs
new file mode 100644
index 0000000..1f154a9
--- /dev/null
+++ b/Axantum.AxCrypt/KnownFoldersDiscovery.cs
@@ -0,0 +1,140 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Properties;
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+
+namespace Axantum.AxCrypt
+{
+    internal static class KnownFoldersDiscovery
+    {
+        public static IEnumerable<KnownFolder> Discover()
+        {
+            List<KnownFolder> knownFolders = new List<KnownFolder>();
+            if (OS.Current.Platform != Platform.WindowsDesktop)
+            {
+                return knownFolders;
+            }
+
+            CheckDocumentsLibrary(knownFolders);
+            CheckDropBox(knownFolders);
+            CheckSkyDrive(knownFolders);
+            CheckGoogleDrive(knownFolders);
+
+            return knownFolders;
+        }
+
+        private static void CheckDocumentsLibrary(IList<KnownFolder> knownFolders)
+        {
+            Icon icon = Resources.DocumentsLibrary;
+            KnownFolder windowsDesktopFolder = new KnownFolder(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Resources.MyAxCryptFolderName, icon.ToBitmap(), null);
+            knownFolders.Add(windowsDesktopFolder);
+        }
+
+        private static void CheckDropBox(IList<KnownFolder> knownFolders)
+        {
+            RegistryKey dropBoxKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Uninstall\Dropbox");
+            if (dropBoxKey == null)
+            {
+                return;
+            }
+
+            string dropBoxFolder = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE") + Environment.GetEnvironmentVariable("HOMEPATH"), "DropBox");
+            if (!Directory.Exists(dropBoxFolder))
+            {
+                return;
+            }
+
+            Uri url = null;
+            string urlInfoAbout = dropBoxKey.GetValue(@"URLInfoAbout") as string;
+            if (!String.IsNullOrEmpty(urlInfoAbout))
+            {
+                Uri.TryCreate(urlInfoAbout, UriKind.Absolute, out url);
+            }
+
+            Icon icon = Resources.DropBox;
+            KnownFolder knownFolder = new KnownFolder(dropBoxFolder, Resources.MyAxCryptFolderName, icon.ToBitmap(), url);
+
+            knownFolders.Add(knownFolder);
+        }
+
+        private static void CheckSkyDrive(IList<KnownFolder> knownFolders)
+        {
+            RegistryKey skyDriveKey = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\SkyDrive");
+            if (skyDriveKey == null)
+            {
+                return;
+            }
+
+            string skyDriveFolder = skyDriveKey.GetValue("UserFolder") as string;
+            if (String.IsNullOrEmpty(skyDriveFolder) || !Directory.Exists(skyDriveFolder))
+            {
+                return;
+            }
+
+            Uri url = new Uri("https://skydrive.live.com/");
+
+            Icon icon = Resources.SkyDrive;
+            KnownFolder knownFolder = new KnownFolder(skyDriveFolder, Resources.MyAxCryptFolderName, icon.ToBitmap(), url);
+
+            knownFolders.Add(knownFolder);
+        }
+
+        private static void CheckGoogleDrive(IList<KnownFolder> knownFolders)
+        {
+            RegistryKey googleDriveKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{56D4499E-AC3E-4B8D-91C9-C700C148C44B}");
+            if (googleDriveKey == null)
+            {
+                googleDriveKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{56D4499E-AC3E-4B8D-91C9-C700C148C44B}");
+            }
+            if (googleDriveKey == null)
+            {
+                return;
+            }
+
+            string googleDriveFolder = Path.Combine(Environment.GetEnvironmentVariable("HOMEDRIVE") + Environment.GetEnvironmentVariable("HOMEPATH"), "Google Drive");
+            if (String.IsNullOrEmpty(googleDriveFolder) || !Directory.Exists(googleDriveFolder))
+            {
+                return;
+            }
+
+            Uri url = new Uri("https://drive.google.com/");
+
+            Icon icon = Resources.GoogleDrive;
+            KnownFolder knownFolder = new KnownFolder(googleDriveFolder, Resources.MyAxCryptFolderName, icon.ToBitmap(), url);
+            knownFolders.Add(knownFolder);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnAccountDialog.Designer.cs b/Axantum.AxCrypt/LogOnAccountDialog.Designer.cs
new file mode 100644
index 0000000..535cdc9
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnAccountDialog.Designer.cs
@@ -0,0 +1,222 @@
+namespace Axantum.AxCrypt
+{
+    partial class LogOnAccountDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.PassphraseGroupBox = new System.Windows.Forms.GroupBox();
+            this.ShowPassphraseCheckBox = new System.Windows.Forms.CheckBox();
+            this._panel1 = new System.Windows.Forms.Panel();
+            this._newButton = new System.Windows.Forms.Button();
+            this._buttonCancel = new System.Windows.Forms.Button();
+            this._buttonOk = new System.Windows.Forms.Button();
+            this.PassphraseTextBox = new System.Windows.Forms.TextBox();
+            this._errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.EmailPanel = new System.Windows.Forms.Panel();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.EmailTextBox = new System.Windows.Forms.TextBox();
+            this._errorProvider2 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.panel1.SuspendLayout();
+            this.PassphraseGroupBox.SuspendLayout();
+            this._panel1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).BeginInit();
+            this.EmailPanel.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).BeginInit();
+            this.SuspendLayout();
+            // 
+            // panel1
+            // 
+            this.panel1.AutoSize = true;
+            this.panel1.Controls.Add(this.PassphraseGroupBox);
+            this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+            this.panel1.Location = new System.Drawing.Point(0, 59);
+            this.panel1.Name = "panel1";
+            this.panel1.Size = new System.Drawing.Size(337, 154);
+            this.panel1.TabIndex = 1;
+            // 
+            // PassphraseGroupBox
+            // 
+            this.PassphraseGroupBox.Controls.Add(this.ShowPassphraseCheckBox);
+            this.PassphraseGroupBox.Controls.Add(this._panel1);
+            this.PassphraseGroupBox.Controls.Add(this.PassphraseTextBox);
+            this.PassphraseGroupBox.Location = new System.Drawing.Point(12, 6);
+            this.PassphraseGroupBox.Margin = new System.Windows.Forms.Padding(3, 3, 13, 13);
+            this.PassphraseGroupBox.Name = "PassphraseGroupBox";
+            this.PassphraseGroupBox.Size = new System.Drawing.Size(298, 131);
+            this.PassphraseGroupBox.TabIndex = 6;
+            this.PassphraseGroupBox.TabStop = false;
+            this.PassphraseGroupBox.Text = "Enter Passphrase";
+            // 
+            // ShowPassphraseCheckBox
+            // 
+            this.ShowPassphraseCheckBox.AutoSize = true;
+            this.ShowPassphraseCheckBox.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this.ShowPassphraseCheckBox.Location = new System.Drawing.Point(7, 53);
+            this.ShowPassphraseCheckBox.Name = "ShowPassphraseCheckBox";
+            this.ShowPassphraseCheckBox.Size = new System.Drawing.Size(111, 17);
+            this.ShowPassphraseCheckBox.TabIndex = 1;
+            this.ShowPassphraseCheckBox.Text = "Show Passphrase";
+            this.ShowPassphraseCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // _panel1
+            // 
+            this._panel1.AutoSize = true;
+            this._panel1.Controls.Add(this._newButton);
+            this._panel1.Controls.Add(this._buttonCancel);
+            this._panel1.Controls.Add(this._buttonOk);
+            this._panel1.Location = new System.Drawing.Point(7, 85);
+            this._panel1.Name = "_panel1";
+            this._panel1.Size = new System.Drawing.Size(273, 37);
+            this._panel1.TabIndex = 2;
+            // 
+            // _newButton
+            // 
+            this._newButton.DialogResult = System.Windows.Forms.DialogResult.Retry;
+            this._newButton.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._newButton.Location = new System.Drawing.Point(180, 7);
+            this._newButton.Name = "_newButton";
+            this._newButton.Size = new System.Drawing.Size(75, 23);
+            this._newButton.TabIndex = 2;
+            this._newButton.Text = "&New";
+            this._newButton.UseVisualStyleBackColor = true;
+            this._newButton.Click += new System.EventHandler(this.NewButton_Click);
+            // 
+            // _buttonCancel
+            // 
+            this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            this._buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._buttonCancel.Location = new System.Drawing.Point(98, 7);
+            this._buttonCancel.Name = "_buttonCancel";
+            this._buttonCancel.Size = new System.Drawing.Size(75, 23);
+            this._buttonCancel.TabIndex = 1;
+            this._buttonCancel.Text = "Cancel";
+            this._buttonCancel.UseVisualStyleBackColor = true;
+            // 
+            // _buttonOk
+            // 
+            this._buttonOk.ImeMode = System.Windows.Forms.ImeMode.NoControl;
+            this._buttonOk.Location = new System.Drawing.Point(17, 7);
+            this._buttonOk.Name = "_buttonOk";
+            this._buttonOk.Size = new System.Drawing.Size(75, 23);
+            this._buttonOk.TabIndex = 0;
+            this._buttonOk.Text = "OK";
+            this._buttonOk.UseVisualStyleBackColor = true;
+            this._buttonOk.Click += new System.EventHandler(this.ButtonOk_Click);
+            // 
+            // PassphraseTextBox
+            // 
+            this.PassphraseTextBox.Location = new System.Drawing.Point(7, 20);
+            this.PassphraseTextBox.Name = "PassphraseTextBox";
+            this.PassphraseTextBox.Size = new System.Drawing.Size(242, 20);
+            this.PassphraseTextBox.TabIndex = 0;
+            this.PassphraseTextBox.Enter += new System.EventHandler(this.PassphraseTextBox_Enter);
+            // 
+            // _errorProvider1
+            // 
+            this._errorProvider1.ContainerControl = this;
+            // 
+            // EmailPanel
+            // 
+            this.EmailPanel.AutoSize = true;
+            this.EmailPanel.Controls.Add(this.groupBox1);
+            this.EmailPanel.Dock = System.Windows.Forms.DockStyle.Top;
+            this.EmailPanel.Location = new System.Drawing.Point(0, 0);
+            this.EmailPanel.Name = "EmailPanel";
+            this.EmailPanel.Size = new System.Drawing.Size(337, 59);
+            this.EmailPanel.TabIndex = 0;
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.EmailTextBox);
+            this.groupBox1.Location = new System.Drawing.Point(12, 12);
+            this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 3, 13, 3);
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.Size = new System.Drawing.Size(298, 44);
+            this.groupBox1.TabIndex = 0;
+            this.groupBox1.TabStop = false;
+            this.groupBox1.Text = "E-Mail";
+            // 
+            // EmailTextBox
+            // 
+            this.EmailTextBox.Location = new System.Drawing.Point(9, 18);
+            this.EmailTextBox.Name = "EmailTextBox";
+            this.EmailTextBox.Size = new System.Drawing.Size(242, 20);
+            this.EmailTextBox.TabIndex = 1;
+            this.EmailTextBox.TextChanged += new System.EventHandler(this.EmailTextBox_TextChanged);
+            // 
+            // _errorProvider2
+            // 
+            this._errorProvider2.ContainerControl = this;
+            // 
+            // LogOnAccountDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.AutoSize = true;
+            this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
+            this.ClientSize = new System.Drawing.Size(337, 213);
+            this.Controls.Add(this.panel1);
+            this.Controls.Add(this.EmailPanel);
+            this.Name = "LogOnAccountDialog";
+            this.Text = "Log On";
+            this.Activated += new System.EventHandler(this.LogOnAccountDialog_Activated);
+            this.Load += new System.EventHandler(this.LogOnAccountDialog_Load);
+            this.panel1.ResumeLayout(false);
+            this.PassphraseGroupBox.ResumeLayout(false);
+            this.PassphraseGroupBox.PerformLayout();
+            this._panel1.ResumeLayout(false);
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).EndInit();
+            this.EmailPanel.ResumeLayout(false);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).EndInit();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.Panel panel1;
+        internal System.Windows.Forms.GroupBox PassphraseGroupBox;
+        internal System.Windows.Forms.CheckBox ShowPassphraseCheckBox;
+        private System.Windows.Forms.Panel _panel1;
+        private System.Windows.Forms.Button _newButton;
+        private System.Windows.Forms.Button _buttonCancel;
+        private System.Windows.Forms.Button _buttonOk;
+        internal System.Windows.Forms.TextBox PassphraseTextBox;
+        private System.Windows.Forms.ErrorProvider _errorProvider1;
+        private System.Windows.Forms.Panel EmailPanel;
+        private System.Windows.Forms.GroupBox groupBox1;
+        internal System.Windows.Forms.TextBox EmailTextBox;
+        private System.Windows.Forms.ErrorProvider _errorProvider2;
+
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnAccountDialog.cs b/Axantum.AxCrypt/LogOnAccountDialog.cs
new file mode 100644
index 0000000..29077b0
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnAccountDialog.cs
@@ -0,0 +1,98 @@
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class LogOnAccountDialog : Form
+    {
+        public LogOnAccountDialog()
+        {
+            InitializeComponent();
+        }
+
+        private LogOnAccountViewModel _viewModel;
+
+        public LogOnAccountDialog(Form parent)
+        {
+            InitializeComponent();
+
+            _viewModel = new LogOnAccountViewModel(String.Empty);
+
+            PassphraseTextBox.TextChanged += (sender, e) => { _viewModel.Passphrase = PassphraseTextBox.Text; };
+            ShowPassphraseCheckBox.CheckedChanged += (sender, e) => { _viewModel.ShowPassphrase = ShowPassphraseCheckBox.Checked; };
+            EmailTextBox.TextChanged += (sender, e) => { _viewModel.UserEmail = EmailTextBox.Text; };
+
+            Owner = parent;
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void LogOnAccountDialog_Load(object sender, EventArgs e)
+        {
+            if (DesignMode)
+            {
+                return;
+            }
+
+            _viewModel.BindPropertyChanged("ShowPassphrase", (bool show) => { PassphraseTextBox.UseSystemPasswordChar = !(ShowPassphraseCheckBox.Checked = show); });
+            _viewModel.BindPropertyChanged("ShowEmail", (bool show) => { EmailPanel.Visible = show; });
+        }
+
+        private void ButtonOk_Click(object sender, EventArgs e)
+        {
+            if (!AdHocValidationDueToMonoLimitations())
+            {
+                DialogResult = DialogResult.None;
+                return;
+            }
+            DialogResult = DialogResult.OK;
+        }
+
+        private bool AdHocValidationDueToMonoLimitations()
+        {
+            bool validated = true;
+            _errorProvider1.Clear();
+            _errorProvider2.Clear();
+
+            if (_viewModel["Passphrase"].Length != 0)
+            {
+                _errorProvider1.SetError(PassphraseTextBox, EmailTextBox.Text.Length > 0 ? Resources.WrongPassphrase : Resources.UnkownLogOn);
+                validated = false;
+            }
+            if (_viewModel["UserEmail"].Length != 0)
+            {
+                _errorProvider2.SetError(EmailTextBox, Resources.BadEmail);
+                validated = false;
+            }
+            return validated;
+        }
+
+        private void NewButton_Click(object sender, EventArgs e)
+        {
+            DialogResult = DialogResult.Retry;
+        }
+
+        private void LogOnAccountDialog_Activated(object sender, EventArgs e)
+        {
+            TopMost = true;
+            BringToFront();
+            Focus();
+        }
+
+        private void PassphraseTextBox_Enter(object sender, EventArgs e)
+        {
+            _errorProvider1.Clear();
+        }
+
+        private void EmailTextBox_TextChanged(object sender, EventArgs e)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnAccountDialog.resx b/Axantum.AxCrypt/LogOnAccountDialog.resx
new file mode 100644
index 0000000..b0d7168
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnAccountDialog.resx
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="_errorProvider2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>152, 17</value>
+  </metadata>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnDialog.Designer.cs b/Axantum.AxCrypt/LogOnDialog.Designer.cs
new file mode 100644
index 0000000..47b4032
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnDialog.Designer.cs
@@ -0,0 +1,176 @@
+namespace Axantum.AxCrypt
+{
+    partial class LogOnDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(LogOnDialog));
+            this._errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.panel1 = new System.Windows.Forms.Panel();
+            this.PassphraseGroupBox = new System.Windows.Forms.GroupBox();
+            this.ShowPassphraseCheckBox = new System.Windows.Forms.CheckBox();
+            this._panel1 = new System.Windows.Forms.Panel();
+            this._newButton = new System.Windows.Forms.Button();
+            this._buttonCancel = new System.Windows.Forms.Button();
+            this._buttonOk = new System.Windows.Forms.Button();
+            this.PassphraseTextBox = new System.Windows.Forms.TextBox();
+            this.FileNamePanel = new System.Windows.Forms.Panel();
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.FileNameTextBox = new System.Windows.Forms.TextBox();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).BeginInit();
+            this.panel1.SuspendLayout();
+            this.PassphraseGroupBox.SuspendLayout();
+            this._panel1.SuspendLayout();
+            this.FileNamePanel.SuspendLayout();
+            this.groupBox1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // _errorProvider1
+            // 
+            this._errorProvider1.ContainerControl = this;
+            // 
+            // panel1
+            // 
+            resources.ApplyResources(this.panel1, "panel1");
+            this.panel1.Controls.Add(this.PassphraseGroupBox);
+            this.panel1.Name = "panel1";
+            // 
+            // PassphraseGroupBox
+            // 
+            this.PassphraseGroupBox.Controls.Add(this.ShowPassphraseCheckBox);
+            this.PassphraseGroupBox.Controls.Add(this._panel1);
+            this.PassphraseGroupBox.Controls.Add(this.PassphraseTextBox);
+            resources.ApplyResources(this.PassphraseGroupBox, "PassphraseGroupBox");
+            this.PassphraseGroupBox.Name = "PassphraseGroupBox";
+            this.PassphraseGroupBox.TabStop = false;
+            // 
+            // ShowPassphraseCheckBox
+            // 
+            resources.ApplyResources(this.ShowPassphraseCheckBox, "ShowPassphraseCheckBox");
+            this.ShowPassphraseCheckBox.Name = "ShowPassphraseCheckBox";
+            this.ShowPassphraseCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // _panel1
+            // 
+            resources.ApplyResources(this._panel1, "_panel1");
+            this._panel1.Controls.Add(this._newButton);
+            this._panel1.Controls.Add(this._buttonCancel);
+            this._panel1.Controls.Add(this._buttonOk);
+            this._panel1.Name = "_panel1";
+            // 
+            // _newButton
+            // 
+            this._newButton.DialogResult = System.Windows.Forms.DialogResult.Retry;
+            resources.ApplyResources(this._newButton, "_newButton");
+            this._newButton.Name = "_newButton";
+            this._newButton.UseVisualStyleBackColor = true;
+            this._newButton.Click += new System.EventHandler(this.newButton_Click);
+            // 
+            // _buttonCancel
+            // 
+            this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            resources.ApplyResources(this._buttonCancel, "_buttonCancel");
+            this._buttonCancel.Name = "_buttonCancel";
+            this._buttonCancel.UseVisualStyleBackColor = true;
+            // 
+            // _buttonOk
+            // 
+            resources.ApplyResources(this._buttonOk, "_buttonOk");
+            this._buttonOk.Name = "_buttonOk";
+            this._buttonOk.UseVisualStyleBackColor = true;
+            this._buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
+            // 
+            // PassphraseTextBox
+            // 
+            resources.ApplyResources(this.PassphraseTextBox, "PassphraseTextBox");
+            this.PassphraseTextBox.Name = "PassphraseTextBox";
+            this.PassphraseTextBox.Enter += new System.EventHandler(this.PassphraseTextBox_Enter);
+            // 
+            // FileNamePanel
+            // 
+            resources.ApplyResources(this.FileNamePanel, "FileNamePanel");
+            this.FileNamePanel.Controls.Add(this.groupBox1);
+            this.FileNamePanel.Name = "FileNamePanel";
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.FileNameTextBox);
+            resources.ApplyResources(this.groupBox1, "groupBox1");
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.TabStop = false;
+            // 
+            // FileNameTextBox
+            // 
+            resources.ApplyResources(this.FileNameTextBox, "FileNameTextBox");
+            this.FileNameTextBox.Name = "FileNameTextBox";
+            // 
+            // LogOnDialog
+            // 
+            this.AcceptButton = this._buttonOk;
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this._buttonCancel;
+            this.Controls.Add(this.panel1);
+            this.Controls.Add(this.FileNamePanel);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.MaximizeBox = false;
+            this.MinimizeBox = false;
+            this.Name = "LogOnDialog";
+            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+            this.TopMost = true;
+            this.Activated += new System.EventHandler(this.LogOnDialog_Activated);
+            this.Load += new System.EventHandler(this.EncryptPassphraseDialog_Load);
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).EndInit();
+            this.panel1.ResumeLayout(false);
+            this.PassphraseGroupBox.ResumeLayout(false);
+            this.PassphraseGroupBox.PerformLayout();
+            this._panel1.ResumeLayout(false);
+            this.FileNamePanel.ResumeLayout(false);
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ErrorProvider _errorProvider1;
+        private System.Windows.Forms.Panel panel1;
+        internal System.Windows.Forms.GroupBox PassphraseGroupBox;
+        internal System.Windows.Forms.CheckBox ShowPassphraseCheckBox;
+        internal System.Windows.Forms.TextBox PassphraseTextBox;
+        private System.Windows.Forms.Panel _panel1;
+        private System.Windows.Forms.Button _newButton;
+        private System.Windows.Forms.Button _buttonCancel;
+        private System.Windows.Forms.Button _buttonOk;
+        private System.Windows.Forms.Panel FileNamePanel;
+        private System.Windows.Forms.GroupBox groupBox1;
+        internal System.Windows.Forms.TextBox FileNameTextBox;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnDialog.cs b/Axantum.AxCrypt/LogOnDialog.cs
new file mode 100644
index 0000000..5a41e63
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnDialog.cs
@@ -0,0 +1,111 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.Extensions;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class LogOnDialog : Form
+    {
+        private LogOnViewModel _viewModel;
+
+        public LogOnDialog(Form parent, string encryptedFileFullName)
+        {
+            InitializeComponent();
+
+            _viewModel = new LogOnViewModel(encryptedFileFullName);
+            PassphraseTextBox.TextChanged += (sender, e) => { _viewModel.Passphrase = PassphraseTextBox.Text; };
+            ShowPassphraseCheckBox.CheckedChanged += (sender, e) => { _viewModel.ShowPassphrase = ShowPassphraseCheckBox.Checked; };
+            _newButton.Enabled = String.IsNullOrEmpty(encryptedFileFullName);
+
+            Owner = parent;
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void EncryptPassphraseDialog_Load(object s, EventArgs ea)
+        {
+            if (DesignMode)
+            {
+                return;
+            }
+
+            _viewModel.BindPropertyChanged("IdentityName", (string id) => { PassphraseGroupBox.Text = !String.IsNullOrEmpty(id) ? Resources.EnterPassphraseForIdentityPrompt.InvariantFormat(id) : Resources.PassphrasePrompt; });
+            _viewModel.BindPropertyChanged("ShowPassphrase", (bool show) => { PassphraseTextBox.UseSystemPasswordChar = !show; });
+            _viewModel.BindPropertyChanged("FileName", (string fileName) => { FileNameTextBox.Text = fileName; FileNamePanel.Visible = !String.IsNullOrEmpty(fileName); });
+        }
+
+        private void buttonOk_Click(object sender, EventArgs e)
+        {
+            if (!AdHocValidationDueToMonoLimitations())
+            {
+                DialogResult = DialogResult.None;
+                return;
+            }
+            DialogResult = DialogResult.OK;
+        }
+
+        private bool AdHocValidationDueToMonoLimitations()
+        {
+            if (_viewModel["Passphrase"].Length == 0)
+            {
+                _errorProvider1.Clear();
+                return true;
+            }
+            if (String.IsNullOrEmpty(_viewModel.FileName))
+            {
+                _errorProvider1.SetError(PassphraseTextBox, Resources.UnkownLogOn);
+            }
+            else
+            {
+                _errorProvider1.SetError(PassphraseTextBox, Resources.WrongPassphrase);
+            }
+            return false;
+        }
+
+        private void newButton_Click(object sender, EventArgs e)
+        {
+            DialogResult = DialogResult.Retry;
+        }
+
+        private void LogOnDialog_Activated(object sender, EventArgs e)
+        {
+            TopMost = true;
+            BringToFront();
+            Focus();
+        }
+
+        private void PassphraseTextBox_Enter(object sender, EventArgs e)
+        {
+            _errorProvider1.Clear();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnDialog.resx b/Axantum.AxCrypt/LogOnDialog.resx
new file mode 100644
index 0000000..f644601
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnDialog.resx
@@ -0,0 +1,823 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_buttonOk.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="_buttonOk.Location" type="System.Drawing.Point, System.Drawing">
+    <value>17, 7</value>
+  </data>
+  <data name="_buttonOk.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_buttonOk.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="_buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name=">>_buttonOk.Name" xml:space="preserve">
+    <value>_buttonOk</value>
+  </data>
+  <data name=">>_buttonOk.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonOk.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonOk.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="$this.AutoSizeMode" type="System.Windows.Forms.AutoSizeMode, System.Windows.Forms">
+    <value>GrowAndShrink</value>
+  </data>
+  <data name="_buttonCancel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_buttonCancel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>98, 7</value>
+  </data>
+  <data name="_buttonCancel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonCancel.TabIndex" type="System.Int32, mscorlib">
+    <value>9</value>
+  </data>
+  <data name="_buttonCancel.Text" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name=">>_buttonCancel.Name" xml:space="preserve">
+    <value>_buttonCancel</value>
+  </data>
+  <data name=">>_buttonCancel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonCancel.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonCancel.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>376, 220</value>
+  </data>
+  <data name="panel1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 53</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>111, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Show Passphrase</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Name" xml:space="preserve">
+    <value>ShowPassphraseCheckBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_panel1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="_newButton.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_newButton.Location" type="System.Drawing.Point, System.Drawing">
+    <value>180, 7</value>
+  </data>
+  <data name="_newButton.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_newButton.TabIndex" type="System.Int32, mscorlib">
+    <value>10</value>
+  </data>
+  <data name="_newButton.Text" xml:space="preserve">
+    <value>&New</value>
+  </data>
+  <data name=">>_newButton.Name" xml:space="preserve">
+    <value>_newButton</value>
+  </data>
+  <data name=">>_newButton.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_newButton.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_newButton.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 85</value>
+  </data>
+  <data name="_panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>273, 37</value>
+  </data>
+  <data name="_panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>7</value>
+  </data>
+  <data name=">>_panel1.Name" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_panel1.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>_panel1.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="PassphraseTextBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 20</value>
+  </data>
+  <data name="PassphraseTextBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>242, 20</value>
+  </data>
+  <data name="PassphraseTextBox.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name=">>PassphraseTextBox.Name" xml:space="preserve">
+    <value>PassphraseTextBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseTextBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="PassphraseGroupBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 6</value>
+  </data>
+  <data name="PassphraseGroupBox.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>3, 3, 13, 13</value>
+  </data>
+  <data name="PassphraseGroupBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>298, 131</value>
+  </data>
+  <data name="PassphraseGroupBox.TabIndex" type="System.Int32, mscorlib">
+    <value>6</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Enter Passphrase</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Name" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Parent" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>PassphraseGroupBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="panel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Fill</value>
+  </data>
+  <data name="panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 59</value>
+  </data>
+  <data name="panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>376, 161</value>
+  </data>
+  <data name="panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>6</value>
+  </data>
+  <data name=">>panel1.Name" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>panel1.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>panel1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="FileNamePanel.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="FileNameTextBox.Enabled" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="FileNameTextBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>9, 18</value>
+  </data>
+  <data name="FileNameTextBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>242, 20</value>
+  </data>
+  <data name="FileNameTextBox.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name=">>FileNameTextBox.Name" xml:space="preserve">
+    <value>FileNameTextBox</value>
+  </data>
+  <data name=">>FileNameTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNameTextBox.Parent" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>FileNameTextBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="groupBox1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 12</value>
+  </data>
+  <data name="groupBox1.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>3, 3, 13, 3</value>
+  </data>
+  <data name="groupBox1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>298, 44</value>
+  </data>
+  <data name="groupBox1.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="groupBox1.Text" xml:space="preserve">
+    <value>File</value>
+  </data>
+  <data name=">>groupBox1.Name" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>groupBox1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>groupBox1.Parent" xml:space="preserve">
+    <value>FileNamePanel</value>
+  </data>
+  <data name=">>groupBox1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="FileNamePanel.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Top</value>
+  </data>
+  <data name="FileNamePanel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 0</value>
+  </data>
+  <data name="FileNamePanel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>376, 59</value>
+  </data>
+  <data name="FileNamePanel.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name=">>FileNamePanel.Name" xml:space="preserve">
+    <value>FileNamePanel</value>
+  </data>
+  <data name=">>FileNamePanel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNamePanel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>FileNamePanel.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>Log On</value>
+  </data>
+  <data name=">>_errorProvider1.Name" xml:space="preserve">
+    <value>_errorProvider1</value>
+  </data>
+  <data name=">>_errorProvider1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ErrorProvider, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>LogOnDialog</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/LogOnDialog.sv.resx b/Axantum.AxCrypt/LogOnDialog.sv.resx
new file mode 100644
index 0000000..c29e1c7
--- /dev/null
+++ b/Axantum.AxCrypt/LogOnDialog.sv.resx
@@ -0,0 +1,574 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="buttonOk.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="buttonOk.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>93, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Visa Lösenord</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="label1.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="label1.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="label1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>92, 13</value>
+  </data>
+  <data name="PassphraseTextBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="PassphraseTextBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="PassphraseGroupBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="PassphraseGroupBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Ange Lösenord</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="buttonCancel.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="buttonCancel.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="buttonCancel.Text" xml:space="preserve">
+    <value>Avbryt</value>
+  </data>
+  <data name="panel1.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="panel1.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="newButton.Text" xml:space="preserve">
+    <value>&Ny</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>Logga På</value>
+  </data>
+  <data name="buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/NewPassphraseDialog.Designer.cs b/Axantum.AxCrypt/NewPassphraseDialog.Designer.cs
new file mode 100644
index 0000000..c95dd83
--- /dev/null
+++ b/Axantum.AxCrypt/NewPassphraseDialog.Designer.cs
@@ -0,0 +1,192 @@
+namespace Axantum.AxCrypt
+{
+    partial class NewPassphraseDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NewPassphraseDialog));
+            this._errorProvider1 = new System.Windows.Forms.ErrorProvider(this.components);
+            this._errorProvider2 = new System.Windows.Forms.ErrorProvider(this.components);
+            this.groupBox1 = new System.Windows.Forms.GroupBox();
+            this.FileNameTextBox = new System.Windows.Forms.TextBox();
+            this.FileNamePanel = new System.Windows.Forms.Panel();
+            this.panel1 = new System.Windows.Forms.Panel();
+            this._panel1 = new System.Windows.Forms.Panel();
+            this._buttonCancel = new System.Windows.Forms.Button();
+            this._buttonOk = new System.Windows.Forms.Button();
+            this.PassphraseGroupBox = new System.Windows.Forms.GroupBox();
+            this.ShowPassphraseCheckBox = new System.Windows.Forms.CheckBox();
+            this.VerifyPassphraseTextbox = new System.Windows.Forms.TextBox();
+            this._label1 = new System.Windows.Forms.Label();
+            this.PassphraseTextBox = new System.Windows.Forms.TextBox();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).BeginInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).BeginInit();
+            this.groupBox1.SuspendLayout();
+            this.FileNamePanel.SuspendLayout();
+            this.panel1.SuspendLayout();
+            this._panel1.SuspendLayout();
+            this.PassphraseGroupBox.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // _errorProvider1
+            // 
+            this._errorProvider1.ContainerControl = this;
+            // 
+            // _errorProvider2
+            // 
+            this._errorProvider2.ContainerControl = this;
+            // 
+            // groupBox1
+            // 
+            this.groupBox1.Controls.Add(this.FileNameTextBox);
+            resources.ApplyResources(this.groupBox1, "groupBox1");
+            this.groupBox1.Name = "groupBox1";
+            this.groupBox1.TabStop = false;
+            // 
+            // FileNameTextBox
+            // 
+            resources.ApplyResources(this.FileNameTextBox, "FileNameTextBox");
+            this.FileNameTextBox.Name = "FileNameTextBox";
+            // 
+            // FileNamePanel
+            // 
+            resources.ApplyResources(this.FileNamePanel, "FileNamePanel");
+            this.FileNamePanel.Controls.Add(this.groupBox1);
+            this.FileNamePanel.Name = "FileNamePanel";
+            // 
+            // panel1
+            // 
+            resources.ApplyResources(this.panel1, "panel1");
+            this.panel1.Controls.Add(this._panel1);
+            this.panel1.Controls.Add(this.PassphraseGroupBox);
+            this.panel1.Name = "panel1";
+            this.panel1.Paint += new System.Windows.Forms.PaintEventHandler(this.panel1_Paint);
+            // 
+            // _panel1
+            // 
+            this._panel1.Controls.Add(this._buttonCancel);
+            this._panel1.Controls.Add(this._buttonOk);
+            resources.ApplyResources(this._panel1, "_panel1");
+            this._panel1.Name = "_panel1";
+            // 
+            // _buttonCancel
+            // 
+            this._buttonCancel.CausesValidation = false;
+            this._buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+            resources.ApplyResources(this._buttonCancel, "_buttonCancel");
+            this._buttonCancel.Name = "_buttonCancel";
+            this._buttonCancel.UseVisualStyleBackColor = true;
+            // 
+            // _buttonOk
+            // 
+            this._buttonOk.CausesValidation = false;
+            this._buttonOk.DialogResult = System.Windows.Forms.DialogResult.OK;
+            resources.ApplyResources(this._buttonOk, "_buttonOk");
+            this._buttonOk.Name = "_buttonOk";
+            this._buttonOk.UseVisualStyleBackColor = true;
+            this._buttonOk.Click += new System.EventHandler(this.buttonOk_Click);
+            // 
+            // PassphraseGroupBox
+            // 
+            resources.ApplyResources(this.PassphraseGroupBox, "PassphraseGroupBox");
+            this.PassphraseGroupBox.Controls.Add(this.ShowPassphraseCheckBox);
+            this.PassphraseGroupBox.Controls.Add(this.VerifyPassphraseTextbox);
+            this.PassphraseGroupBox.Controls.Add(this._label1);
+            this.PassphraseGroupBox.Controls.Add(this.PassphraseTextBox);
+            this.PassphraseGroupBox.Name = "PassphraseGroupBox";
+            this.PassphraseGroupBox.TabStop = false;
+            // 
+            // ShowPassphraseCheckBox
+            // 
+            resources.ApplyResources(this.ShowPassphraseCheckBox, "ShowPassphraseCheckBox");
+            this.ShowPassphraseCheckBox.Name = "ShowPassphraseCheckBox";
+            this.ShowPassphraseCheckBox.UseVisualStyleBackColor = true;
+            // 
+            // VerifyPassphraseTextbox
+            // 
+            resources.ApplyResources(this.VerifyPassphraseTextbox, "VerifyPassphraseTextbox");
+            this.VerifyPassphraseTextbox.Name = "VerifyPassphraseTextbox";
+            this.VerifyPassphraseTextbox.Validating += new System.ComponentModel.CancelEventHandler(this.VerifyPassphraseTextbox_Validating);
+            this.VerifyPassphraseTextbox.Validated += new System.EventHandler(this.VerifyPassphraseTextbox_Validated);
+            // 
+            // _label1
+            // 
+            resources.ApplyResources(this._label1, "_label1");
+            this._label1.Name = "_label1";
+            // 
+            // PassphraseTextBox
+            // 
+            this.PassphraseTextBox.CausesValidation = false;
+            resources.ApplyResources(this.PassphraseTextBox, "PassphraseTextBox");
+            this.PassphraseTextBox.Name = "PassphraseTextBox";
+            // 
+            // NewPassphraseDialog
+            // 
+            this.AcceptButton = this._buttonOk;
+            resources.ApplyResources(this, "$this");
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.CancelButton = this._buttonCancel;
+            this.Controls.Add(this.panel1);
+            this.Controls.Add(this.FileNamePanel);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.Name = "NewPassphraseDialog";
+            this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
+            this.Load += new System.EventHandler(this.EncryptPassphraseDialog_Load);
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider1)).EndInit();
+            ((System.ComponentModel.ISupportInitialize)(this._errorProvider2)).EndInit();
+            this.groupBox1.ResumeLayout(false);
+            this.groupBox1.PerformLayout();
+            this.FileNamePanel.ResumeLayout(false);
+            this.panel1.ResumeLayout(false);
+            this.panel1.PerformLayout();
+            this._panel1.ResumeLayout(false);
+            this.PassphraseGroupBox.ResumeLayout(false);
+            this.PassphraseGroupBox.PerformLayout();
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ErrorProvider _errorProvider1;
+        private System.Windows.Forms.ErrorProvider _errorProvider2;
+        private System.Windows.Forms.Panel panel1;
+        private System.Windows.Forms.Panel _panel1;
+        private System.Windows.Forms.Button _buttonCancel;
+        private System.Windows.Forms.Button _buttonOk;
+        internal System.Windows.Forms.GroupBox PassphraseGroupBox;
+        internal System.Windows.Forms.CheckBox ShowPassphraseCheckBox;
+        private System.Windows.Forms.TextBox VerifyPassphraseTextbox;
+        private System.Windows.Forms.Label _label1;
+        internal System.Windows.Forms.TextBox PassphraseTextBox;
+        private System.Windows.Forms.Panel FileNamePanel;
+        private System.Windows.Forms.GroupBox groupBox1;
+        internal System.Windows.Forms.TextBox FileNameTextBox;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/NewPassphraseDialog.cs b/Axantum.AxCrypt/NewPassphraseDialog.cs
new file mode 100644
index 0000000..f995ff2
--- /dev/null
+++ b/Axantum.AxCrypt/NewPassphraseDialog.cs
@@ -0,0 +1,120 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using Axantum.AxCrypt.Properties;
+using System;
+using System.ComponentModel;
+using System.Linq;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class NewPassphraseDialog : Form
+    {
+        private NewPassphraseViewModel _viewModel;
+
+        public NewPassphraseDialog(Form parent, string passphrase, string encryptedFileFullName)
+        {
+            InitializeComponent();
+
+            _viewModel = new NewPassphraseViewModel(passphrase, encryptedFileFullName);
+            PassphraseTextBox.TextChanged += (sender, e) => { _viewModel.Passphrase = PassphraseTextBox.Text; };
+            VerifyPassphraseTextbox.TextChanged += (sender, e) => { _viewModel.Verification = VerifyPassphraseTextbox.Text; };
+            ShowPassphraseCheckBox.CheckedChanged += (sender, e) => { _viewModel.ShowPassphrase = ShowPassphraseCheckBox.Checked; };
+
+            Owner = parent;
+            Owner.Activated += (sender, e) => Activate();
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void EncryptPassphraseDialog_Load(object s, EventArgs ee)
+        {
+            if (DesignMode)
+            {
+                return;
+            }
+
+            _viewModel.BindPropertyChanged("ShowPassphrase", (bool show) => { PassphraseTextBox.UseSystemPasswordChar = VerifyPassphraseTextbox.UseSystemPasswordChar = !show; });
+            _viewModel.BindPropertyChanged("FileName", (string fileName) => { FileNameTextBox.Text = fileName; FileNamePanel.Visible = !String.IsNullOrEmpty(fileName); });
+            _viewModel.BindPropertyChanged("Passphrase", (string p) => { PassphraseTextBox.Text = p; });
+            _viewModel.BindPropertyChanged("Verification", (string p) => { VerifyPassphraseTextbox.Text = p; });
+
+            PassphraseTextBox.Focus();
+        }
+
+        private void buttonOk_Click(object sender, EventArgs e)
+        {
+            if (!AdHocValidationDueToMonoLimitations())
+            {
+                DialogResult = DialogResult.None;
+            }
+        }
+
+        private bool AdHocValidationDueToMonoLimitations()
+        {
+            bool validated = true;
+            if (_viewModel["Verification"].Length > 0)
+            {
+                _errorProvider1.SetError(VerifyPassphraseTextbox, Resources.PassphraseVerificationMismatch);
+                validated = false;
+            }
+            if (_viewModel["Passphrase"].Length > 0)
+            {
+                _errorProvider1.SetError(PassphraseTextBox, Resources.WrongPassphrase);
+                validated = false;
+            }
+            if (validated)
+            {
+                _errorProvider1.Clear();
+            }
+            _errorProvider2.Clear();
+            return validated;
+        }
+
+        private void VerifyPassphraseTextbox_Validating(object sender, CancelEventArgs e)
+        {
+        }
+
+        private void VerifyPassphraseTextbox_Validated(object sender, EventArgs e)
+        {
+        }
+
+        private void NameTextBox_Validating(object sender, CancelEventArgs e)
+        {
+        }
+
+        private void NameTextBox_Validated(object sender, EventArgs e)
+        {
+        }
+
+        private void panel1_Paint(object sender, PaintEventArgs e)
+        {
+
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/NewPassphraseDialog.resx b/Axantum.AxCrypt/NewPassphraseDialog.resx
new file mode 100644
index 0000000..47653fd
--- /dev/null
+++ b/Axantum.AxCrypt/NewPassphraseDialog.resx
@@ -0,0 +1,949 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_errorProvider1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>True</value>
+  </metadata>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_buttonOk.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="_buttonOk.Location" type="System.Drawing.Point, System.Drawing">
+    <value>22, 11</value>
+  </data>
+  <data name="_buttonOk.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="_buttonOk.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="_buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name=">>_buttonOk.Name" xml:space="preserve">
+    <value>_buttonOk</value>
+  </data>
+  <data name=">>_buttonOk.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonOk.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonOk.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
+    <value>6, 13</value>
+  </data>
+  <data name="$this.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="$this.AutoSizeMode" type="System.Windows.Forms.AutoSizeMode, System.Windows.Forms">
+    <value>GrowAndShrink</value>
+  </data>
+  <data name="_buttonCancel.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_buttonCancel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>103, 11</value>
+  </data>
+  <data name="_buttonCancel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>75, 23</value>
+  </data>
+  <data name="_buttonCancel.TabIndex" type="System.Int32, mscorlib">
+    <value>9</value>
+  </data>
+  <data name="_buttonCancel.Text" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name=">>_buttonCancel.Name" xml:space="preserve">
+    <value>_buttonCancel</value>
+  </data>
+  <data name=">>_buttonCancel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_buttonCancel.Parent" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_buttonCancel.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
+    <value>315, 246</value>
+  </data>
+  <data name="panel1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name=">>_panel1.Name" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_panel1.Parent" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>_panel1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Name" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Parent" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>PassphraseGroupBox.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="panel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Fill</value>
+  </data>
+  <data name="panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 59</value>
+  </data>
+  <data name="panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>315, 187</value>
+  </data>
+  <data name="panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name=">>panel1.Name" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>panel1.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>panel1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="FileNamePanel.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name=">>groupBox1.Name" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>groupBox1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>groupBox1.Parent" xml:space="preserve">
+    <value>FileNamePanel</value>
+  </data>
+  <data name=">>groupBox1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="FileNamePanel.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
+    <value>Top</value>
+  </data>
+  <data name="FileNamePanel.Location" type="System.Drawing.Point, System.Drawing">
+    <value>0, 0</value>
+  </data>
+  <data name="FileNamePanel.Size" type="System.Drawing.Size, System.Drawing">
+    <value>315, 59</value>
+  </data>
+  <data name="FileNamePanel.TabIndex" type="System.Int32, mscorlib">
+    <value>7</value>
+  </data>
+  <data name=">>FileNamePanel.Name" xml:space="preserve">
+    <value>FileNamePanel</value>
+  </data>
+  <data name=">>FileNamePanel.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNamePanel.Parent" xml:space="preserve">
+    <value>$this</value>
+  </data>
+  <data name=">>FileNamePanel.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>Create New Passphrase</value>
+  </data>
+  <data name=">>_errorProvider1.Name" xml:space="preserve">
+    <value>_errorProvider1</value>
+  </data>
+  <data name=">>_errorProvider1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ErrorProvider, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_errorProvider2.Name" xml:space="preserve">
+    <value>_errorProvider2</value>
+  </data>
+  <data name=">>_errorProvider2.Type" xml:space="preserve">
+    <value>System.Windows.Forms.ErrorProvider, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>$this.Name" xml:space="preserve">
+    <value>NewPassphraseDialog</value>
+  </data>
+  <data name=">>$this.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Form, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <metadata name="_errorProvider2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>152, 17</value>
+  </metadata>
+  <data name=">>FileNameTextBox.Name" xml:space="preserve">
+    <value>FileNameTextBox</value>
+  </data>
+  <data name=">>FileNameTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNameTextBox.Parent" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>FileNameTextBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="groupBox1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 12</value>
+  </data>
+  <data name="groupBox1.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
+    <value>3, 3, 13, 3</value>
+  </data>
+  <data name="groupBox1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>280, 44</value>
+  </data>
+  <data name="groupBox1.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="groupBox1.Text" xml:space="preserve">
+    <value>File</value>
+  </data>
+  <data name=">>groupBox1.Name" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>groupBox1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>groupBox1.Parent" xml:space="preserve">
+    <value>FileNamePanel</value>
+  </data>
+  <data name=">>groupBox1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="FileNameTextBox.Enabled" type="System.Boolean, mscorlib">
+    <value>False</value>
+  </data>
+  <data name="FileNameTextBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>9, 18</value>
+  </data>
+  <data name="FileNameTextBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>242, 20</value>
+  </data>
+  <data name="FileNameTextBox.TabIndex" type="System.Int32, mscorlib">
+    <value>1</value>
+  </data>
+  <data name=">>FileNameTextBox.Name" xml:space="preserve">
+    <value>FileNameTextBox</value>
+  </data>
+  <data name=">>FileNameTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>FileNameTextBox.Parent" xml:space="preserve">
+    <value>groupBox1</value>
+  </data>
+  <data name=">>FileNameTextBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="_panel1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>52, 141</value>
+  </data>
+  <data name="_panel1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>200, 37</value>
+  </data>
+  <data name="_panel1.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name=">>_panel1.Name" xml:space="preserve">
+    <value>_panel1</value>
+  </data>
+  <data name=">>_panel1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Panel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_panel1.Parent" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>_panel1.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="PassphraseGroupBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Name" xml:space="preserve">
+    <value>ShowPassphraseCheckBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Name" xml:space="preserve">
+    <value>VerifyPassphraseTextbox</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name=">>_label1.Name" xml:space="preserve">
+    <value>_label1</value>
+  </data>
+  <data name=">>_label1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_label1.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>_label1.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name=">>PassphraseTextBox.Name" xml:space="preserve">
+    <value>PassphraseTextBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseTextBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+  <data name="PassphraseGroupBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>12, 11</value>
+  </data>
+  <data name="PassphraseGroupBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>280, 125</value>
+  </data>
+  <data name="PassphraseGroupBox.TabIndex" type="System.Int32, mscorlib">
+    <value>7</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Enter Passphrase</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Name" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseGroupBox.Parent" xml:space="preserve">
+    <value>panel1</value>
+  </data>
+  <data name=">>PassphraseGroupBox.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 89</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>111, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.TabIndex" type="System.Int32, mscorlib">
+    <value>8</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Show Passphrase</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Name" xml:space="preserve">
+    <value>ShowPassphraseCheckBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>ShowPassphraseCheckBox.ZOrder" xml:space="preserve">
+    <value>0</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>6, 59</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>243, 20</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.TabIndex" type="System.Int32, mscorlib">
+    <value>7</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Name" xml:space="preserve">
+    <value>VerifyPassphraseTextbox</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>VerifyPassphraseTextbox.ZOrder" xml:space="preserve">
+    <value>1</value>
+  </data>
+  <data name="_label1.AutoSize" type="System.Boolean, mscorlib">
+    <value>True</value>
+  </data>
+  <data name="_label1.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
+    <value>NoControl</value>
+  </data>
+  <data name="_label1.Location" type="System.Drawing.Point, System.Drawing">
+    <value>6, 43</value>
+  </data>
+  <data name="_label1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>91, 13</value>
+  </data>
+  <data name="_label1.TabIndex" type="System.Int32, mscorlib">
+    <value>6</value>
+  </data>
+  <data name="_label1.Text" xml:space="preserve">
+    <value>Verify Passphrase</value>
+  </data>
+  <data name=">>_label1.Name" xml:space="preserve">
+    <value>_label1</value>
+  </data>
+  <data name=">>_label1.Type" xml:space="preserve">
+    <value>System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>_label1.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>_label1.ZOrder" xml:space="preserve">
+    <value>2</value>
+  </data>
+  <data name="PassphraseTextBox.Location" type="System.Drawing.Point, System.Drawing">
+    <value>7, 20</value>
+  </data>
+  <data name="PassphraseTextBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>242, 20</value>
+  </data>
+  <data name="PassphraseTextBox.TabIndex" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name=">>PassphraseTextBox.Name" xml:space="preserve">
+    <value>PassphraseTextBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.Type" xml:space="preserve">
+    <value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </data>
+  <data name=">>PassphraseTextBox.Parent" xml:space="preserve">
+    <value>PassphraseGroupBox</value>
+  </data>
+  <data name=">>PassphraseTextBox.ZOrder" xml:space="preserve">
+    <value>3</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/NewPassphraseDialog.sv.resx b/Axantum.AxCrypt/NewPassphraseDialog.sv.resx
new file mode 100644
index 0000000..4df87f4
--- /dev/null
+++ b/Axantum.AxCrypt/NewPassphraseDialog.sv.resx
@@ -0,0 +1,577 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="buttonOk.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="buttonOk.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="ShowPassphraseCheckBox.Size" type="System.Drawing.Size, System.Drawing">
+    <value>93, 17</value>
+  </data>
+  <data name="ShowPassphraseCheckBox.Text" xml:space="preserve">
+    <value>Visa Lösenord</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="VerifyPassphraseTextbox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="label1.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="label1.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="label1.Size" type="System.Drawing.Size, System.Drawing">
+    <value>92, 13</value>
+  </data>
+  <data name="label1.Text" xml:space="preserve">
+    <value>Verifiera Lösenord</value>
+  </data>
+  <data name="PassphraseTextBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="PassphraseTextBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="PassphraseGroupBox.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="PassphraseGroupBox.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="PassphraseGroupBox.Text" xml:space="preserve">
+    <value>Ange Lösenord</value>
+  </data>
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+  <data name="buttonCancel.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="buttonCancel.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="buttonCancel.Text" xml:space="preserve">
+    <value>Avbryt</value>
+  </data>
+  <data name="panel1.IconAlignment" type="System.Windows.Forms.ErrorIconAlignment, System.Windows.Forms">
+    <value>MiddleRight</value>
+  </data>
+  <data name="panel1.IconPadding" type="System.Int32, mscorlib">
+    <value>0</value>
+  </data>
+  <data name="$this.Text" xml:space="preserve">
+    <value>Skapa ny identitet</value>
+  </data>
+  <data name="buttonOk.Text" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name="groupBox1.Text" xml:space="preserve">
+    <value>Identitet</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Preferences.cs b/Axantum.AxCrypt/Preferences.cs
new file mode 100644
index 0000000..1b26ab7
--- /dev/null
+++ b/Axantum.AxCrypt/Preferences.cs
@@ -0,0 +1,57 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Drawing;
+using System.Linq;
+using Axantum.AxCrypt.Core;
+
+namespace Axantum.AxCrypt
+{
+    internal static class Preferences
+    {
+        public static int MainWindowWidth { get { return Instance.UserSettings.Load<int>("MainWindowWidth"); } set { Instance.UserSettings.Store("MainWindowWidth", value); } }
+
+        public static int MainWindowHeight { get { return Instance.UserSettings.Load<int>("MainWindowHeight"); } set { Instance.UserSettings.Store("MainWindowHeight", value); } }
+
+        public static Point MainWindowLocation { get { return new Point(Instance.UserSettings.Load<int>("MainWindowLocationX"), Instance.UserSettings.Load<int>("MainWindowLocationY")); } set { Instance.UserSettings.Store("MainWindowLocationX", value.X); Instance.UserSettings.Store("MainWindowLocationY", value.Y); } }
+
+        public static int RecentFilesMaxNumber { get { return Instance.UserSettings.Load<int>("RecentFilesMaxNumber", 250); } set { Instance.UserSettings.Store("RecentFilesMaxNumber", value); } }
+
+        public static int RecentFilesDocumentWidth { get { return Instance.UserSettings.Load<int>("RecentFilesDocumentWidth"); } set { Instance.UserSettings.Store("RecentFilesDocumentWidth", value); } }
+
+        public static int RecentFilesDateTimeWidth { get { return Instance.UserSettings.Load<int>("RecentFilesDateTimeWidth"); } set { Instance.UserSettings.Store("RecentFilesDateTimeWidth", value); } }
+
+        public static int RecentFilesEncryptedPathWidth { get { return Instance.UserSettings.Load<int>("RecentFilesEncryptedPathWidth"); } set { Instance.UserSettings.Store("RecentFilesEncryptedPathWidth", value); } }
+
+        public static int RecentFilesCryptoNameWidth { get { return Instance.UserSettings.Load<int>("RecentFilesCryptoNameWidth"); } set { Instance.UserSettings.Store("RecentFilesCryptoNameWidth", value); } }
+
+        public static bool RecentFilesAscending { get { return Instance.UserSettings.Load<bool>("RecentFilesAscending", true); } set { Instance.UserSettings.Store("RecentFilesAscending", value); } }
+
+        public static int RecentFilesSortColumn { get { return Instance.UserSettings.Load<int>("RecentFilesSortColumn", 0); } set { Instance.UserSettings.Store("RecentFilesSortColumn", value); } }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Program.cs b/Axantum.AxCrypt/Program.cs
new file mode 100644
index 0000000..9c38c00
--- /dev/null
+++ b/Axantum.AxCrypt/Program.cs
@@ -0,0 +1,160 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.Crypto;
+using Axantum.AxCrypt.Core.Crypto.Asymmetric;
+using Axantum.AxCrypt.Core.IO;
+using Axantum.AxCrypt.Core.Ipc;
+using Axantum.AxCrypt.Core.Portable;
+using Axantum.AxCrypt.Core.Runtime;
+using Axantum.AxCrypt.Core.Session;
+using Axantum.AxCrypt.Core.UI;
+using Axantum.AxCrypt.Desktop;
+using Axantum.AxCrypt.Forms;
+using Axantum.AxCrypt.Mono;
+using Axantum.AxCrypt.Mono.Portable;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    internal static class Program
+    {
+        /// <summary>
+        /// The main entry point for the application.
+        /// </summary>
+        [STAThread]
+        private static void Main()
+        {
+            string[] commandLineArgs = Environment.GetCommandLineArgs();
+
+            RegisterTypeFactories(commandLineArgs[0]);
+            WireupEvents();
+            SetCulture();
+
+            if (commandLineArgs.Length == 1)
+            {
+                RunInteractive();
+            }
+            else
+            {
+                new CommandLine(commandLineArgs[0], commandLineArgs.Skip(1)).Execute();
+            }
+
+            Instance.CommandService.Dispose();
+            Factory.Instance.Clear();
+        }
+
+        private static void RegisterTypeFactories(string startPath)
+        {
+            string workFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"AxCrypt" + Path.DirectorySeparatorChar);
+
+            Instance.RegisterTypeFactories(workFolderPath);
+            RuntimeEnvironment.RegisterTypeFactories();
+
+            Factory.Instance.Singleton<CryptoFactory>(() => CreateCryptoFactory(startPath));
+            Factory.Instance.Singleton<CryptoPolicy>(() => CreateCryptoPolicy(startPath));
+            Factory.Instance.Singleton<ICryptoPolicy>(() => Factory.Instance.Singleton<CryptoPolicy>().CreateDefault());
+
+            Factory.Instance.Register<IDataProtection>(() => new DataProtection());
+        }
+
+        private static CryptoFactory CreateCryptoFactory(string startPath)
+        {
+            IEnumerable<Assembly> extraAssemblies = LoadFromFiles(new DirectoryInfo(Path.GetDirectoryName(startPath)).GetFiles("*.dll"));
+            IEnumerable<Type> types = TypeDiscovery.Interface(typeof(ICryptoFactory), extraAssemblies);
+
+            CryptoFactory factory = new CryptoFactory();
+            foreach (Type type in types)
+            {
+                factory.Add(() => Activator.CreateInstance(type) as ICryptoFactory);
+            }
+            return factory;
+        }
+
+        private static CryptoPolicy CreateCryptoPolicy(string startPath)
+        {
+            IEnumerable<Assembly> extraAssemblies = LoadFromFiles(new DirectoryInfo(Path.GetDirectoryName(startPath)).GetFiles("*.dll"));
+            return new CryptoPolicy(extraAssemblies);
+        }
+
+        private static IEnumerable<Assembly> LoadFromFiles(IEnumerable<FileInfo> files)
+        {
+            List<Assembly> assemblies = new List<Assembly>();
+            foreach (FileInfo file in files)
+            {
+                try
+                {
+                    assemblies.Add(Assembly.LoadFrom(file.FullName));
+                }
+                catch (BadImageFormatException)
+                {
+                    continue;
+                }
+                catch (FileLoadException)
+                {
+                    continue;
+                }
+            }
+            return assemblies;
+        }
+
+        private static void WireupEvents()
+        {
+            Instance.SessionNotify.Notification += (sender, e) => Factory.New<SessionNotificationHandler>().HandleNotification(e.Notification);
+        }
+
+        private static void SetCulture()
+        {
+            if (String.IsNullOrEmpty(Instance.UserSettings.CultureName))
+            {
+                return;
+            }
+            Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(Instance.UserSettings.CultureName);
+        }
+
+        private static void RunInteractive()
+        {
+            if (!OS.Current.IsFirstInstance)
+            {
+                Instance.CommandService.Call(CommandVerb.Show, -1);
+                return;
+            }
+            Application.EnableVisualStyles();
+            Application.SetCompatibleTextRenderingDefault(false);
+
+            Application.Run(new AxCryptMainForm());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Properties/AssemblyInfo.cs b/Axantum.AxCrypt/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..d661dda
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/AssemblyInfo.cs
@@ -0,0 +1,72 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+[module: SuppressMessage("Microsoft.Design", "CA2210:AssembliesShouldHaveValidStrongNames", Justification = "The assembly is strong named when deployed.")]
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("File Encryption for .NET and Mono")]
+[assembly: AssemblyCompany("Axantum Software AB")]
+[assembly: AssemblyDescription("Beta")]
+[assembly: AssemblyProduct("AxCrypt")]
+[assembly: AssemblyCopyright("Copyright © 2014 Svante Seleborg")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("00087451-fc52-4cda-8fab-bacbf0fb7faa")]
+[assembly: NeutralResourcesLanguageAttribute("en-US")]
+[assembly: CLSCompliant(true)]
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+#if !AXANTUM
+[assembly: AssemblyVersion("2.0.0.0")]
+[assembly: AssemblyFileVersion("2.0.0.0")]
+[assembly: AssemblyInformationalVersion("2.0.0.0")]
+[assembly: AssemblyConfiguration("GPL")]
+#endif
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Properties/AssemblyInfo.template b/Axantum.AxCrypt/Properties/AssemblyInfo.template
new file mode 100644
index 0000000..7d79c17
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/AssemblyInfo.template
@@ -0,0 +1,46 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Reflection;
+using System.Resources;
+using System.Runtime.InteropServices;
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyFileVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyInformationalVersion("2.0.$REVNUM$.$DIRTY$")]
+[assembly: AssemblyConfiguration("")]
diff --git a/Axantum.AxCrypt/Properties/Resources.Designer.cs b/Axantum.AxCrypt/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..947fc2e
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/Resources.Designer.cs
@@ -0,0 +1,791 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Axantum.AxCrypt.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Axantum.AxCrypt.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to About {0}.
+        /// </summary>
+        internal static string About {
+            get {
+                return ResourceManager.GetString("About", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap activefilegreen16 {
+            get {
+                object obj = ResourceManager.GetObject("activefilegreen16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Double-click decrypts and opens the document.
+        /// </summary>
+        internal static string ActiveFileKnownKeyToolTip {
+            get {
+                return ResourceManager.GetString("ActiveFileKnownKeyToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Double-click opens a passphrase dialog before decrypting and opening the document..
+        /// </summary>
+        internal static string ActiveFileToolTip {
+            get {
+                return ResourceManager.GetString("ActiveFileToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Open Source Document Encryption by Axantum Software AB
+        ///
+        ///Includes software from http://www.bouncycastle.org/ ..
+        /// </summary>
+        internal static string AxCryptAboutDescription {
+            get {
+                return ResourceManager.GetString("AxCryptAboutDescription", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to AxCrypt Document Encryption.
+        /// </summary>
+        internal static string AxCryptFileEncryption {
+            get {
+                return ResourceManager.GetString("AxCryptFileEncryption", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+        /// </summary>
+        internal static System.Drawing.Icon axcrypticon {
+            get {
+                object obj = ResourceManager.GetObject("axcrypticon", resourceCulture);
+                return ((System.Drawing.Icon)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap axcrypticon128 {
+            get {
+                object obj = ResourceManager.GetObject("axcrypticon128", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Incorrect e-mail address.
+        /// </summary>
+        internal static string BadEmail {
+            get {
+                return ResourceManager.GetString("BadEmail", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Canceled '{0}'..
+        /// </summary>
+        internal static string Canceled {
+            get {
+                return ResourceManager.GetString("Canceled", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cannot start application for '{0}'..
+        /// </summary>
+        internal static string CannotStartApplication {
+            get {
+                return ResourceManager.GetString("CannotStartApplication", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cannot write '{0}'..
+        /// </summary>
+        internal static string CannotWrite {
+            get {
+                return ResourceManager.GetString("CannotWrite", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Click to check for a newer version..
+        /// </summary>
+        internal static string ClickToCheckForNewerVersionTooltip {
+            get {
+                return ResourceManager.GetString("ClickToCheckForNewerVersionTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap closeremovestandbygreen32 {
+            get {
+                object obj = ResourceManager.GetObject("closeremovestandbygreen32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap closeremovestandbyred32 {
+            get {
+                object obj = ResourceManager.GetObject("closeremovestandbyred32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap decryptedfilered16 {
+            get {
+                object obj = ResourceManager.GetObject("decryptedfilered16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Assumed open. Try to Close the application, or use the Clean function to remove it.
+        /// </summary>
+        internal static string DecryptedFileToolTip {
+            get {
+                return ResourceManager.GetString("DecryptedFileToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Documents (*{0})|*{0}|All files (*.*)|*.*.
+        /// </summary>
+        internal static string DecryptedSaveAsFileDialogFilterPattern {
+            get {
+                return ResourceManager.GetString("DecryptedSaveAsFileDialogFilterPattern", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Document exists, choose a new name to save as.
+        /// </summary>
+        internal static string DecryptedSaveAsFileDialogTitle {
+            get {
+                return ResourceManager.GetString("DecryptedSaveAsFileDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap decryptedunknownkeyfilered16 {
+            get {
+                object obj = ResourceManager.GetObject("decryptedunknownkeyfilered16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The passphrase has not been entered yet. Double-click to enter passphrase and Open, or right-click for options.
+        /// </summary>
+        internal static string DecryptedUnknownKeyFileToolTip {
+            get {
+                return ResourceManager.GetString("DecryptedUnknownKeyFileToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select document to decrypt.
+        /// </summary>
+        internal static string DecryptFileOpenDialogTitle {
+            get {
+                return ResourceManager.GetString("DecryptFileOpenDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap decryptlockopen32 {
+            get {
+                object obj = ResourceManager.GetObject("decryptlockopen32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to You are Logged On. Click to Log Out..
+        /// </summary>
+        internal static string DefaultEncryptionKeyIsIsetToolTip {
+            get {
+                return ResourceManager.GetString("DefaultEncryptionKeyIsIsetToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+        /// </summary>
+        internal static System.Drawing.Icon DocumentsLibrary {
+            get {
+                object obj = ResourceManager.GetObject("DocumentsLibrary", resourceCulture);
+                return ((System.Drawing.Icon)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+        /// </summary>
+        internal static System.Drawing.Icon DropBox {
+            get {
+                object obj = ResourceManager.GetObject("DropBox", resourceCulture);
+                return ((System.Drawing.Icon)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to AxCrypt Documents (*{0})|*{0}|All files (*.*)|*.*.
+        /// </summary>
+        internal static string EncryptedFileDialogFilterPattern {
+            get {
+                return ResourceManager.GetString("EncryptedFileDialogFilterPattern", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Encrypted Document.
+        /// </summary>
+        internal static string EncryptedSourceColumnHeader {
+            get {
+                return ResourceManager.GetString("EncryptedSourceColumnHeader", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select documents to encrypt.
+        /// </summary>
+        internal static string EncryptFileOpenDialogTitle {
+            get {
+                return ResourceManager.GetString("EncryptFileOpenDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Document Exists, Save As.
+        /// </summary>
+        internal static string EncryptFileSaveAsDialogTitle {
+            get {
+                return ResourceManager.GetString("EncryptFileSaveAsDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap encryptionkeygreen32 {
+            get {
+                object obj = ResourceManager.GetObject("encryptionkeygreen32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap encryptionkeyred32 {
+            get {
+                object obj = ResourceManager.GetObject("encryptionkeyred32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap encryptlock32 {
+            get {
+                object obj = ResourceManager.GetObject("encryptlock32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Identity '{0}' passphrase.
+        /// </summary>
+        internal static string EnterPassphraseForIdentityPrompt {
+            get {
+                return ResourceManager.GetString("EnterPassphraseForIdentityPrompt", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Exception during processing of '{0}'..
+        /// </summary>
+        internal static string Exception {
+            get {
+                return ResourceManager.GetString("Exception", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap exclamationgreen16 {
+            get {
+                object obj = ResourceManager.GetObject("exclamationgreen16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap exclamationgreen32 {
+            get {
+                object obj = ResourceManager.GetObject("exclamationgreen32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The document '{0}' is already encrypted..
+        /// </summary>
+        internal static string FileAlreadyEncrypted {
+            get {
+                return ResourceManager.GetString("FileAlreadyEncrypted", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Document '{0}' already exists..
+        /// </summary>
+        internal static string FileAlreadyExists {
+            get {
+                return ResourceManager.GetString("FileAlreadyExists", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Document '{0}' does not exist..
+        /// </summary>
+        internal static string FileDoesNotExist {
+            get {
+                return ResourceManager.GetString("FileDoesNotExist", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to '{0}' is open in another application. Please close it and try again..
+        /// </summary>
+        internal static string FileIsLockedWarning {
+            get {
+                return ResourceManager.GetString("FileIsLockedWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap fileknownkeygreen16 {
+            get {
+                object obj = ResourceManager.GetObject("fileknownkeygreen16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Failed '{0}'..
+        /// </summary>
+        internal static string FileOperationFailed {
+            get {
+                return ResourceManager.GetString("FileOperationFailed", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Folder '{0}' already watched..
+        /// </summary>
+        internal static string FolderAlreadyWatched {
+            get {
+                return ResourceManager.GetString("FolderAlreadyWatched", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+        /// </summary>
+        internal static System.Drawing.Icon GoogleDrive {
+            get {
+                object obj = ResourceManager.GetObject("GoogleDrive", resourceCulture);
+                return ((System.Drawing.Icon)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap helpquestiongreen32 {
+            get {
+                object obj = ResourceManager.GetObject("helpquestiongreen32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap inactivefilegreen16 {
+            get {
+                object obj = ResourceManager.GetObject("inactivefilegreen16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Inconsistent state with '{0}'..
+        /// </summary>
+        internal static string InconsistentState {
+            get {
+                return ResourceManager.GetString("InconsistentState", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Invalid URL..
+        /// </summary>
+        internal static string Invalid_URL {
+            get {
+                return ResourceManager.GetString("Invalid_URL", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Invalid key for '{0}'..
+        /// </summary>
+        internal static string InvalidKey {
+            get {
+                return ResourceManager.GetString("InvalidKey", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The file or path '{0}' is invalid for this..
+        /// </summary>
+        internal static string InvalidPath {
+            get {
+                return ResourceManager.GetString("InvalidPath", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to AxCrypt must be restarted in order for the language change to take effect..
+        /// </summary>
+        internal static string LanguageChangeRestartPrompt {
+            get {
+                return ResourceManager.GetString("LanguageChangeRestartPrompt", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Logged Off.
+        /// </summary>
+        internal static string LoggedOffStatusText {
+            get {
+                return ResourceManager.GetString("LoggedOffStatusText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Logged On.
+        /// </summary>
+        internal static string LoggedOnStatusText {
+            get {
+                return ResourceManager.GetString("LoggedOnStatusText", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to This AxCrypt Identity already exists.
+        /// </summary>
+        internal static string LogOnExists {
+            get {
+                return ResourceManager.GetString("LogOnExists", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to My AxCrypt.
+        /// </summary>
+        internal static string MyAxCryptFolderName {
+            get {
+                return ResourceManager.GetString("MyAxCryptFolderName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Version {0} is available! Click to download..
+        /// </summary>
+        internal static string NewVersionIsAvailableTooltip {
+            get {
+                return ResourceManager.GetString("NewVersionIsAvailableTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to You are Logged Out. Click to Log On..
+        /// </summary>
+        internal static string NoDefaultEncryptionKeySetToolTip {
+            get {
+                return ResourceManager.GetString("NoDefaultEncryptionKeySetToolTip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to No need to check for updates..
+        /// </summary>
+        internal static string NoNeedToCheckForUpdatesTooltip {
+            get {
+                return ResourceManager.GetString("NoNeedToCheckForUpdatesTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Your version is old. Please click to check for a newer version..
+        /// </summary>
+        internal static string OldVersionTooltip {
+            get {
+                return ResourceManager.GetString("OldVersionTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap opendocument32 {
+            get {
+                object obj = ResourceManager.GetObject("opendocument32", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select encrypted document to open.
+        /// </summary>
+        internal static string OpenEncryptedFileOpenDialogTitle {
+            get {
+                return ResourceManager.GetString("OpenEncryptedFileOpenDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to File.
+        /// </summary>
+        internal static string OpenFileColumnHeader {
+            get {
+                return ResourceManager.GetString("OpenFileColumnHeader", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Enter Passphrase.
+        /// </summary>
+        internal static string PassphrasePrompt {
+            get {
+                return ResourceManager.GetString("PassphrasePrompt", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Passphrases do not match.
+        /// </summary>
+        internal static string PassphraseVerificationMismatch {
+            get {
+                return ResourceManager.GetString("PassphraseVerificationMismatch", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Purging Active Files.
+        /// </summary>
+        internal static string PurgingActiveFiles {
+            get {
+                return ResourceManager.GetString("PurgingActiveFiles", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap refreshgreen {
+            get {
+                object obj = ResourceManager.GetObject("refreshgreen", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap refreshred {
+            get {
+                object obj = ResourceManager.GetObject("refreshred", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Icon similar to (Icon).
+        /// </summary>
+        internal static System.Drawing.Icon SkyDrive {
+            get {
+                object obj = ResourceManager.GetObject("SkyDrive", resourceCulture);
+                return ((System.Drawing.Icon)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized resource of type System.Drawing.Bitmap.
+        /// </summary>
+        internal static System.Drawing.Bitmap trashred16 {
+            get {
+                object obj = ResourceManager.GetObject("trashred16", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Click to restore the AxCrypt application window..
+        /// </summary>
+        internal static string TrayBalloonTooltip {
+            get {
+                return ResourceManager.GetString("TrayBalloonTooltip", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Unknown.
+        /// </summary>
+        internal static string UnknownCrypto {
+            get {
+                return ResourceManager.GetString("UnknownCrypto", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Passphrase is not previously known. Click 'New' to create a new Log On..
+        /// </summary>
+        internal static string UnkownLogOn {
+            get {
+                return ResourceManager.GetString("UnkownLogOn", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Unrecognized error code failing with '{0}'..
+        /// </summary>
+        internal static string UnrecognizedError {
+            get {
+                return ResourceManager.GetString("UnrecognizedError", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Updating Status.
+        /// </summary>
+        internal static string UpdatingStatus {
+            get {
+                return ResourceManager.GetString("UpdatingStatus", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to You have updated AxCrypt. Unfortunately, your configuration must be reset. After restarting, your preferences and settings will unfortunately be lost. We apologize for the inconvenience. Your encrypted files are still safe and ok..
+        /// </summary>
+        internal static string UserSettingsFormatChangeNeedsReset {
+            get {
+                return ResourceManager.GetString("UserSettingsFormatChangeNeedsReset", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select documents to securely delete.
+        /// </summary>
+        internal static string WipeFileSelectFileDialogTitle {
+            get {
+                return ResourceManager.GetString("WipeFileSelectFileDialogTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Wrong Passphrase. Please try again..
+        /// </summary>
+        internal static string WrongPassphrase {
+            get {
+                return ResourceManager.GetString("WrongPassphrase", resourceCulture);
+            }
+        }
+    }
+}
diff --git a/Axantum.AxCrypt/Properties/Resources.resx b/Axantum.AxCrypt/Properties/Resources.resx
new file mode 100644
index 0000000..6f6a4f0
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/Resources.resx
@@ -0,0 +1,363 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="About" xml:space="preserve">
+    <value>About {0}</value>
+  </data>
+  <data name="ActiveFileKnownKeyToolTip" xml:space="preserve">
+    <value>Double-click decrypts and opens the document</value>
+  </data>
+  <data name="ActiveFileToolTip" xml:space="preserve">
+    <value>Double-click opens a passphrase dialog before decrypting and opening the document.</value>
+  </data>
+  <data name="AxCryptAboutDescription" xml:space="preserve">
+    <value>Open Source Document Encryption by Axantum Software AB
+
+Includes software from http://www.bouncycastle.org/ .</value>
+  </data>
+  <data name="AxCryptFileEncryption" xml:space="preserve">
+    <value>AxCrypt Document Encryption</value>
+  </data>
+  <data name="Canceled" xml:space="preserve">
+    <value>Canceled '{0}'.</value>
+  </data>
+  <data name="CannotStartApplication" xml:space="preserve">
+    <value>Cannot start application for '{0}'.</value>
+  </data>
+  <data name="CannotWrite" xml:space="preserve">
+    <value>Cannot write '{0}'.</value>
+  </data>
+  <data name="ClickToCheckForNewerVersionTooltip" xml:space="preserve">
+    <value>Click to check for a newer version.</value>
+  </data>
+  <data name="DecryptedFileToolTip" xml:space="preserve">
+    <value>Assumed open. Try to Close the application, or use the Clean function to remove it</value>
+  </data>
+  <data name="DecryptedSaveAsFileDialogFilterPattern" xml:space="preserve">
+    <value>Documents (*{0})|*{0}|All files (*.*)|*.*</value>
+  </data>
+  <data name="DecryptedSaveAsFileDialogTitle" xml:space="preserve">
+    <value>Document exists, choose a new name to save as</value>
+  </data>
+  <data name="DecryptedUnknownKeyFileToolTip" xml:space="preserve">
+    <value>The passphrase has not been entered yet. Double-click to enter passphrase and Open, or right-click for options</value>
+  </data>
+  <data name="DecryptFileOpenDialogTitle" xml:space="preserve">
+    <value>Select document to decrypt</value>
+  </data>
+  <data name="DefaultEncryptionKeyIsIsetToolTip" xml:space="preserve">
+    <value>You are Logged On. Click to Log Out.</value>
+  </data>
+  <data name="EncryptedFileDialogFilterPattern" xml:space="preserve">
+    <value>AxCrypt Documents (*{0})|*{0}|All files (*.*)|*.*</value>
+  </data>
+  <data name="EncryptedSourceColumnHeader" xml:space="preserve">
+    <value>Encrypted Document</value>
+  </data>
+  <data name="EncryptFileOpenDialogTitle" xml:space="preserve">
+    <value>Select documents to encrypt</value>
+  </data>
+  <data name="EncryptFileSaveAsDialogTitle" xml:space="preserve">
+    <value>Document Exists, Save As</value>
+  </data>
+  <data name="Exception" xml:space="preserve">
+    <value>Exception during processing of '{0}'.</value>
+    <comment>@Invariant</comment>
+  </data>
+  <data name="FileAlreadyEncrypted" xml:space="preserve">
+    <value>The document '{0}' is already encrypted.</value>
+  </data>
+  <data name="FileAlreadyExists" xml:space="preserve">
+    <value>Document '{0}' already exists.</value>
+  </data>
+  <data name="FileDoesNotExist" xml:space="preserve">
+    <value>Document '{0}' does not exist.</value>
+  </data>
+  <data name="FileOperationFailed" xml:space="preserve">
+    <value>Failed '{0}'.</value>
+  </data>
+  <data name="InconsistentState" xml:space="preserve">
+    <value>Inconsistent state with '{0}'.</value>
+  </data>
+  <data name="Invalid_URL" xml:space="preserve">
+    <value>Invalid URL.</value>
+  </data>
+  <data name="InvalidKey" xml:space="preserve">
+    <value>Invalid key for '{0}'.</value>
+  </data>
+  <data name="InvalidPath" xml:space="preserve">
+    <value>The file or path '{0}' is invalid for this.</value>
+  </data>
+  <data name="LanguageChangeRestartPrompt" xml:space="preserve">
+    <value>AxCrypt must be restarted in order for the language change to take effect.</value>
+  </data>
+  <data name="LoggedOffStatusText" xml:space="preserve">
+    <value>Logged Off</value>
+  </data>
+  <data name="LoggedOnStatusText" xml:space="preserve">
+    <value>Logged On</value>
+    <comment>Shown in the title bar to display the log on status.</comment>
+  </data>
+  <data name="NewVersionIsAvailableTooltip" xml:space="preserve">
+    <value>Version {0} is available! Click to download.</value>
+  </data>
+  <data name="NoDefaultEncryptionKeySetToolTip" xml:space="preserve">
+    <value>You are Logged Out. Click to Log On.</value>
+  </data>
+  <data name="NoNeedToCheckForUpdatesTooltip" xml:space="preserve">
+    <value>No need to check for updates.</value>
+  </data>
+  <data name="OldVersionTooltip" xml:space="preserve">
+    <value>Your version is old. Please click to check for a newer version.</value>
+  </data>
+  <data name="OpenEncryptedFileOpenDialogTitle" xml:space="preserve">
+    <value>Select encrypted document to open</value>
+  </data>
+  <data name="OpenFileColumnHeader" xml:space="preserve">
+    <value>File</value>
+  </data>
+  <data name="PassphraseVerificationMismatch" xml:space="preserve">
+    <value>Passphrases do not match</value>
+  </data>
+  <data name="PurgingActiveFiles" xml:space="preserve">
+    <value>Purging Active Files</value>
+  </data>
+  <data name="TrayBalloonTooltip" xml:space="preserve">
+    <value>Click to restore the AxCrypt application window.</value>
+    <comment>Previous text: Double-click to restore the AxCrypt application window.</comment>
+  </data>
+  <data name="UnrecognizedError" xml:space="preserve">
+    <value>Unrecognized error code failing with '{0}'.</value>
+  </data>
+  <data name="UpdatingStatus" xml:space="preserve">
+    <value>Updating Status</value>
+  </data>
+  <data name="WipeFileSelectFileDialogTitle" xml:space="preserve">
+    <value>Select documents to securely delete</value>
+  </data>
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <data name="refreshgreen" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\refreshgreen.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="refreshred" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\refreshred.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="axcrypticon128" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\axcrypticon128.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="decryptlockopen32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\decryptlockopen32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="encryptlock32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\encryptlock32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="opendocument32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\opendocument32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="closeremovestandbygreen32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\closeremovestandbygreen32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="closeremovestandbyred32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\closeremovestandbyred32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="helpquestiongreen32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\helpquestiongreen32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="axcrypticon" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\axcrypticon.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="encryptionkeygreen32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\encryptionkeygreen32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="encryptionkeyred32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\encryptionkeyred32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="trashred16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\trashred16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="activefilegreen16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\activefilegreen16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="decryptedfilered16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\decryptedfilered16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="decryptedunknownkeyfilered16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\decryptedunknownkeyfilered16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="exclamationgreen16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\exclamationgreen16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="inactivefilegreen16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\inactivefilegreen16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="exclamationgreen32" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\exclamationgreen32.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="fileknownkeygreen16" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\fileknownkeygreen16.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="UnkownLogOn" xml:space="preserve">
+    <value>Passphrase is not previously known. Click 'New' to create a new Log On.</value>
+  </data>
+  <data name="LogOnExists" xml:space="preserve">
+    <value>This AxCrypt Identity already exists</value>
+  </data>
+  <data name="EnterPassphraseForIdentityPrompt" xml:space="preserve">
+    <value>Identity '{0}' passphrase</value>
+  </data>
+  <data name="DocumentsLibrary" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\DocumentsLibrary.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="DropBox" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\DropBox.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="GoogleDrive" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\GoogleDrive.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="MyAxCryptFolderName" xml:space="preserve">
+    <value>My AxCrypt</value>
+    <comment>The folder name used for default watching</comment>
+  </data>
+  <data name="SkyDrive" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>..\resources\SkyDrive.ico;System.Drawing.Icon, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
+  <data name="WrongPassphrase" xml:space="preserve">
+    <value>Wrong Passphrase. Please try again.</value>
+  </data>
+  <data name="PassphrasePrompt" xml:space="preserve">
+    <value>Enter Passphrase</value>
+  </data>
+  <data name="FolderAlreadyWatched" xml:space="preserve">
+    <value>Folder '{0}' already watched.</value>
+  </data>
+  <data name="UserSettingsFormatChangeNeedsReset" xml:space="preserve">
+    <value>You have updated AxCrypt. Unfortunately, your configuration must be reset. After restarting, your preferences and settings will unfortunately be lost. We apologize for the inconvenience. Your encrypted files are still safe and ok.</value>
+  </data>
+  <data name="FileIsLockedWarning" xml:space="preserve">
+    <value>'{0}' is open in another application. Please close it and try again.</value>
+  </data>
+  <data name="UnknownCrypto" xml:space="preserve">
+    <value>Unknown</value>
+    <comment>Displayed when an unknown CryptoId is encountered.</comment>
+  </data>
+  <data name="BadEmail" xml:space="preserve">
+    <value>Incorrect e-mail address</value>
+    <comment>Displayed when e-mail format validation fails.</comment>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Properties/Resources.sv.resx b/Axantum.AxCrypt/Properties/Resources.sv.resx
new file mode 100644
index 0000000..f1115b9
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/Resources.sv.resx
@@ -0,0 +1,261 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="AxCryptFileEncryption" xml:space="preserve">
+    <value>AxCrypt Dokumentkryptering</value>
+  </data>
+  <data name="Canceled" xml:space="preserve">
+    <value>Avbröt '{0}'.</value>
+  </data>
+  <data name="CannotStartApplication" xml:space="preserve">
+    <value>Kan inte starta applikation för '{0}'.</value>
+  </data>
+  <data name="CannotWrite" xml:space="preserve">
+    <value>Kan inte skriva till '{0}'.</value>
+  </data>
+  <data name="ClickToCheckForNewerVersionTooltip" xml:space="preserve">
+    <value>Klicka för att kontrollera om det finns en ny version.</value>
+  </data>
+  <data name="DecryptedSaveAsFileDialogFilterPattern" xml:space="preserve">
+    <value>Dokument (*{0})|*{0}|Alla dokument (*.*)|*.*</value>
+  </data>
+  <data name="DecryptedSaveAsFileDialogTitle" xml:space="preserve">
+    <value>Dokumentet finns redan, spara som</value>
+  </data>
+  <data name="DecryptFileOpenDialogTitle" xml:space="preserve">
+    <value>Välj dokument att dekryptera</value>
+  </data>
+  <data name="EncryptedFileDialogFilterPattern" xml:space="preserve">
+    <value>AxCrypt Dokument (*{0})|*{0}|Alla dokument (*.*)|*.*</value>
+  </data>
+  <data name="EncryptedSourceColumnHeader" xml:space="preserve">
+    <value>Krypterat Dokument</value>
+  </data>
+  <data name="EncryptFileOpenDialogTitle" xml:space="preserve">
+    <value>Välj dokument att kryptera</value>
+  </data>
+  <data name="EncryptFileSaveAsDialogTitle" xml:space="preserve">
+    <value>Dokumentet finns redan, spara som</value>
+  </data>
+  <data name="FileAlreadyExists" xml:space="preserve">
+    <value>Dokumentet '{0}' finns redan.</value>
+  </data>
+  <data name="FileDoesNotExist" xml:space="preserve">
+    <value>Dokumentet '{0}' finns inte.</value>
+  </data>
+  <data name="FileOperationFailed" xml:space="preserve">
+    <value>Fel med '{0}'.</value>
+  </data>
+  <data name="InconsistentState" xml:space="preserve">
+    <value>Internt fel med '{0}'.</value>
+  </data>
+  <data name="InvalidKey" xml:space="preserve">
+    <value>Felaktig krypteringsnyckel för '{0}'.</value>
+  </data>
+  <data name="LanguageChangeRestartPrompt" xml:space="preserve">
+    <value>AxCrypt måste startas om för att slutföra språkändringen.</value>
+  </data>
+  <data name="NewVersionIsAvailableTooltip" xml:space="preserve">
+    <value>Version {0} finns tillgänglig! Klicka för att komma till nedladdningssidan.</value>
+  </data>
+  <data name="NoNeedToCheckForUpdatesTooltip" xml:space="preserve">
+    <value>Inget uppdateringsbehov.</value>
+  </data>
+  <data name="OldVersionTooltip" xml:space="preserve">
+    <value>Du har en gammal version. Klicka för att kontrollera om det finns en nyare.</value>
+  </data>
+  <data name="OpenEncryptedFileOpenDialogTitle" xml:space="preserve">
+    <value>Välj dokument att dekryptera och öppna</value>
+  </data>
+  <data name="OpenFileColumnHeader" xml:space="preserve">
+    <value>Arkiv</value>
+  </data>
+  <data name="PassphraseVerificationMismatch" xml:space="preserve">
+    <value>Lösenorden är inte lika</value>
+  </data>
+  <data name="PurgingActiveFiles" xml:space="preserve">
+    <value>Rensar Aktiva Dokument</value>
+  </data>
+  <data name="TrayBalloonTooltip" xml:space="preserve">
+    <value>Dubbelklicka för att öppa AxCrypt</value>
+    <comment>Previous text: Double-click to restore the AxCrypt application window.</comment>
+  </data>
+  <data name="UnrecognizedError" xml:space="preserve">
+    <value>Okänt fel med '{0}'.</value>
+  </data>
+  <data name="UpdatingStatus" xml:space="preserve">
+    <value>Uppdaterar Status</value>
+  </data>
+  <data name="About" xml:space="preserve">
+    <value>Om {0}</value>
+  </data>
+  <data name="ActiveFileKnownKeyToolTip" xml:space="preserve">
+    <value>Dubbelklick dekrypterar och öppnar dokumentet</value>
+  </data>
+  <data name="ActiveFileToolTip" xml:space="preserve">
+    <value>Dubbelklick öppnar en dialog där du kan ange lösenord innan dokumentet kan dekrypteras och öppnas</value>
+  </data>
+  <data name="AxCryptAboutDescription" xml:space="preserve">
+    <value>Öppen och Fri Dokumentkrypering från Axantum Software AB
+
+Innehåller programvara från http://www.bouncycastle.org/ .</value>
+  </data>
+  <data name="DecryptedFileToolTip" xml:space="preserve">
+    <value>Dokumentet troligen öppnat i sin applikation. Stäng applikationen eller använda Rensa-knappen.</value>
+  </data>
+  <data name="DecryptedUnknownKeyFileToolTip" xml:space="preserve">
+    <value>Okänt lösenord. Dubbelklicka eller Högerklicka för alternativ.</value>
+  </data>
+  <data name="DefaultEncryptionKeyIsIsetToolTip" xml:space="preserve">
+    <value>Du är påloggad. Klicka för att logga ut.</value>
+  </data>
+  <data name="EnterPassphraseForIdentityPrompt" xml:space="preserve">
+    <value>Ange lösenord för '{0}'</value>
+  </data>
+  <data name="FileAlreadyEncrypted" xml:space="preserve">
+    <value>Dokumentet '{0}' är redan krypterat.</value>
+  </data>
+  <data name="InactiveFileToolTip" xml:space="preserve">
+    <value>Inaktivt dokument</value>
+  </data>
+  <data name="Invalid_URL" xml:space="preserve">
+    <value>Felaktig sökväg.</value>
+  </data>
+  <data name="InvalidPath" xml:space="preserve">
+    <value>Sökvägen '{0}' är ogiltig.</value>
+  </data>
+  <data name="LoggedOffStatusText" xml:space="preserve">
+    <value>Avloggad</value>
+  </data>
+  <data name="LoggedOnStatusText" xml:space="preserve">
+    <value>'{0}' är påloggad</value>
+  </data>
+  <data name="LogOnExists" xml:space="preserve">
+    <value>Denna AxCrypt-Identitet finns redan.</value>
+  </data>
+  <data name="NoDefaultEncryptionKeySetToolTip" xml:space="preserve">
+    <value>Du är utloggad. Klicka för att logga på.</value>
+  </data>
+  <data name="UnkownLogOn" xml:space="preserve">
+    <value>Okänt lösenord. Klicka 'Ny' för att skapa en ny identitet.</value>
+  </data>
+  <data name="WipeFileSelectFileDialogTitle" xml:space="preserve">
+    <value>Välj dokument för säker radering</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/Properties/Settings.Designer.cs b/Axantum.AxCrypt/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..eabf5e7
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.34014
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Axantum.AxCrypt.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}
diff --git a/Axantum.AxCrypt/Properties/Settings.settings b/Axantum.AxCrypt/Properties/Settings.settings
new file mode 100644
index 0000000..2bd17f0
--- /dev/null
+++ b/Axantum.AxCrypt/Properties/Settings.settings
@@ -0,0 +1,5 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles />
+  <Settings />
+</SettingsFile>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/UIThread.cs b/Axantum.AxCrypt/UIThread.cs
new file mode 100644
index 0000000..ab5c0d2
--- /dev/null
+++ b/Axantum.AxCrypt/UIThread.cs
@@ -0,0 +1,80 @@
+#region Coypright and License
+
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+*/
+
+#endregion Coypright and License
+
+using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Linq;
+using System.Threading;
+using System.Windows.Forms;
+using Axantum.AxCrypt.Core.UI;
+
+namespace Axantum.AxCrypt
+{
+    public class UIThread : IUIThread
+    {
+        private Control _control;
+
+        private SynchronizationContext _context;
+
+        public UIThread(Control control)
+        {
+            _control = control;
+            _context = SynchronizationContext.Current;
+        }
+
+        public bool IsOnUIThread
+        {
+            get { return !_control.InvokeRequired; }
+        }
+
+        public void RunOnUIThread(Action action)
+        {
+            DoOnUIThreadInternal(action, _context.Send);
+        }
+
+        public void PostOnUIThread(Action action)
+        {
+            DoOnUIThreadInternal(action, _context.Post);
+        }
+
+        [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This is to marshal the exception possibly between threads and then throw a new one.")]
+        private void DoOnUIThreadInternal(Action action, Action<SendOrPostCallback, object> method)
+        {
+            if (IsOnUIThread)
+            {
+                action();
+                return;
+            }
+            Exception exception = null;
+            method((state) => { try { action(); } catch (Exception ex) { exception = ex; } }, null);
+            if (exception != null)
+            {
+                throw new InvalidOperationException("Exception on UI Thread", exception);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/WatchedFoldersDialog.Designer.cs b/Axantum.AxCrypt/WatchedFoldersDialog.Designer.cs
new file mode 100644
index 0000000..2ba4b6c
--- /dev/null
+++ b/Axantum.AxCrypt/WatchedFoldersDialog.Designer.cs
@@ -0,0 +1,111 @@
+namespace Axantum.AxCrypt
+{
+    partial class WatchedFoldersDialog
+    {
+        /// <summary>
+        /// Required designer variable.
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// Clean up any resources being used.
+        /// </summary>
+        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows Form Designer generated code
+
+        /// <summary>
+        /// Required method for Designer support - do not modify
+        /// the contents of this method with the code editor.
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(WatchedFoldersDialog));
+            this._watchedFoldersListView = new System.Windows.Forms.ListView();
+            this._watchedFolderColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
+            this._watchedFoldersContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this._watchedFoldersRemoveMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersdecryptTemporarilyMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersOpenExplorerHereMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this._watchedFoldersContextMenuStrip.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // _watchedFoldersListView
+            // 
+            this._watchedFoldersListView.AllowDrop = true;
+            this._watchedFoldersListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+            this._watchedFolderColumnHeader});
+            this._watchedFoldersListView.Dock = System.Windows.Forms.DockStyle.Fill;
+            this._watchedFoldersListView.Location = new System.Drawing.Point(0, 0);
+            this._watchedFoldersListView.Name = "_watchedFoldersListView";
+            this._watchedFoldersListView.Size = new System.Drawing.Size(658, 160);
+            this._watchedFoldersListView.TabIndex = 0;
+            this._watchedFoldersListView.UseCompatibleStateImageBehavior = false;
+            this._watchedFoldersListView.View = System.Windows.Forms.View.Details;
+            // 
+            // _watchedFolderColumnHeader
+            // 
+            this._watchedFolderColumnHeader.Text = "Folder";
+            this._watchedFolderColumnHeader.Width = 325;
+            // 
+            // _watchedFoldersContextMenuStrip
+            // 
+            this._watchedFoldersContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this._watchedFoldersRemoveMenuItem,
+            this._watchedFoldersdecryptTemporarilyMenuItem,
+            this._watchedFoldersOpenExplorerHereMenuItem});
+            this._watchedFoldersContextMenuStrip.Name = "watchedFoldersContextMenuStrip";
+            this._watchedFoldersContextMenuStrip.Size = new System.Drawing.Size(186, 92);
+            // 
+            // _watchedFoldersRemoveMenuItem
+            // 
+            this._watchedFoldersRemoveMenuItem.Name = "_watchedFoldersRemoveMenuItem";
+            this._watchedFoldersRemoveMenuItem.Size = new System.Drawing.Size(185, 22);
+            this._watchedFoldersRemoveMenuItem.Text = "&Decrypt Permanently";
+            // 
+            // _watchedFoldersdecryptTemporarilyMenuItem
+            // 
+            this._watchedFoldersdecryptTemporarilyMenuItem.Name = "_watchedFoldersdecryptTemporarilyMenuItem";
+            this._watchedFoldersdecryptTemporarilyMenuItem.Size = new System.Drawing.Size(185, 22);
+            this._watchedFoldersdecryptTemporarilyMenuItem.Text = "Decrypt &Temporarily";
+            // 
+            // _watchedFoldersOpenExplorerHereMenuItem
+            // 
+            this._watchedFoldersOpenExplorerHereMenuItem.Name = "_watchedFoldersOpenExplorerHereMenuItem";
+            this._watchedFoldersOpenExplorerHereMenuItem.Size = new System.Drawing.Size(185, 22);
+            this._watchedFoldersOpenExplorerHereMenuItem.Text = "Open &Explorer Here";
+            // 
+            // WatchedFoldersDialog
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.ClientSize = new System.Drawing.Size(658, 160);
+            this.Controls.Add(this._watchedFoldersListView);
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.Name = "WatchedFoldersDialog";
+            this.Text = "Encrypted Folders";
+            this.Load += new System.EventHandler(this.WatchedFoldersDialog_Load);
+            this._watchedFoldersContextMenuStrip.ResumeLayout(false);
+            this.ResumeLayout(false);
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.ListView _watchedFoldersListView;
+        private System.Windows.Forms.ColumnHeader _watchedFolderColumnHeader;
+        private System.Windows.Forms.ContextMenuStrip _watchedFoldersContextMenuStrip;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersRemoveMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersdecryptTemporarilyMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem _watchedFoldersOpenExplorerHereMenuItem;
+    }
+}
\ No newline at end of file
diff --git a/Axantum.AxCrypt/WatchedFoldersDialog.cs b/Axantum.AxCrypt/WatchedFoldersDialog.cs
new file mode 100644
index 0000000..36616d9
--- /dev/null
+++ b/Axantum.AxCrypt/WatchedFoldersDialog.cs
@@ -0,0 +1,77 @@
+using Axantum.AxCrypt.Core;
+using Axantum.AxCrypt.Core.UI.ViewModel;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+
+namespace Axantum.AxCrypt
+{
+    public partial class WatchedFoldersDialog : Form
+    {
+        private WatchedFoldersViewModel _viewModel;
+
+        private IEnumerable<string> _additional;
+
+        public WatchedFoldersDialog(Form parent, IEnumerable<string> additional)
+        {
+            InitializeComponent();
+
+            _additional = additional;
+            _viewModel = Factory.New<WatchedFoldersViewModel>();
+
+            Owner = parent;
+            StartPosition = FormStartPosition.CenterParent;
+        }
+
+        private void WatchedFoldersDialog_Load(object sender, EventArgs e)
+        {
+            BindToViewModel();
+            _viewModel.AddWatchedFolders.Execute(_additional);
+            _additional = new string[0];
+        }
+
+        private void BindToViewModel()
+        {
+            _viewModel.BindPropertyChanged("WatchedFolders", (IEnumerable<string> folders) => { UpdateWatchedFolders(folders); });
+
+            _watchedFoldersListView.SelectedIndexChanged += (sender, e) => { _viewModel.SelectedWatchedFolders = _watchedFoldersListView.SelectedItems.Cast<ListViewItem>().Select(lvi => lvi.Text); };
+            _watchedFoldersListView.MouseClick += (sender, e) => { if (e.Button == MouseButtons.Right) _watchedFoldersContextMenuStrip.Show((Control)sender, e.Location); };
+            _watchedFoldersListView.DragOver += (sender, e) => { _viewModel.DragAndDropFiles = e.GetDragged(); e.Effect = GetEffectsForWatchedFolders(e); };
+            _watchedFoldersListView.DragDrop += (sender, e) => { _viewModel.AddWatchedFolders.Execute(_viewModel.DragAndDropFiles); };
+            _watchedFoldersOpenExplorerHereMenuItem.Click += (sender, e) => { _viewModel.OpenSelectedFolder.Execute(_viewModel.SelectedWatchedFolders.First()); };
+            _watchedFoldersRemoveMenuItem.Click += (sender, e) => { _viewModel.RemoveWatchedFolders.Execute(_viewModel.SelectedWatchedFolders); };
+        }
+
+        private void UpdateWatchedFolders(IEnumerable<string> watchedFolders)
+        {
+            _watchedFoldersListView.BeginUpdate();
+            try
+            {
+                _watchedFoldersListView.Items.Clear();
+                foreach (string folder in watchedFolders)
+                {
+                    ListViewItem item = _watchedFoldersListView.Items.Add(folder);
+                    item.Name = folder;
+                }
+            }
+            finally
+            {
+                _watchedFoldersListView.EndUpdate();
+            }
+        }
+
+        public DragDropEffects GetEffectsForWatchedFolders(DragEventArgs e)
+        {
+            if (!_viewModel.DroppableAsWatchedFolder)
+            {
+                return DragDropEffects.None;
+            }
+            return (DragDropEffects.Link | DragDropEffects.Copy) & e.AllowedEffect;
+        }
+    }
+}
diff --git a/Axantum.AxCrypt/WatchedFoldersDialog.resx b/Axantum.AxCrypt/WatchedFoldersDialog.resx
new file mode 100644
index 0000000..d44c772
--- /dev/null
+++ b/Axantum.AxCrypt/WatchedFoldersDialog.resx
@@ -0,0 +1,503 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="_watchedFoldersContextMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
+  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
+  <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+    <value>
+        AAABAAYAMDAAAAAACACoDgAAZgAAACAgAAAAAAgAqAgAAA4PAAAQEAAAAAAIAGgFAAC2FwAAMDAAAAAA
+        IACoJQAAHh0AACAgAAAAACAAqBAAAMZCAAAQEAAAAAAgAGgEAABuUwAAKAAAADAAAABgAAAAAQAIAAAA
+        AAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAAAMclUADXBZAIB+fgAQjlwADpVeAAqZXgAYgm8AC5xhABKX
+        YQATnGQAHJpmAB2baAAZg3QAJJ5sAC+PcAAxj3QAL51yAAyjZQAMp2gADKtqABCjZgAQpGgAG6NrAA2x
+        bgAQsG0ADrVwAA66cwARtHEAELx1ABm5dwAXt3oAF755ACyseAAyp3cAOqV5ADOoeAA/qH0ALLV9ADKy
+        fQBBp34AD8F4ABDAdwAQw3kAGcR+ABHKfQAiwH8AHHyCABZqoQAVcK4AImm2ACxytAAffMYAJXTFACly
+        xgAud8gALXzIACh00QAnetMAIYCUADeKkwA0nZgAMqaJAC67gQAztoAAPLCBADG+hAA9uIYAPbuIADuv
+        kAA4uJkAK4SmADeGqQArn6oAMZSnADyCtQApkrkANqKjAD6tuABIqYIAV6uKAE6zigBHvY0AWbCNAE68
+        kABWtpAAWrmSAGKqjgBirpEAeKWUAGSzlABgu5YAb7OYAHK0mgB7sp0AcL2fAEKPtwBJmbUARaGpAEa5
+        qQB7uqIAH8WBABHOgAAdy4MAEtODABLYhgAe1YkAE9yJAC3DhQAxx4kAI9KKADLQjwA6x5MALtiSADTY
+        lQAT4owANuKbAELAjQBAxKAAWsunAFfEuQB/wqgAYMqwAHXUuwAriMoAOIfLAC2cwgAynsIAKYHUADuQ
+        1QAwntAAOpPaAD+Y2gA3tcYAM6PUADSr0gA/tN4ALYfmACqT6gA1k+QAM53mAD+V6wAplPUAN6vrADen
+        9gBBiMMARZTEAECP0QBAmt4AV5LYAEWmzQBDusEAVafQAEW53QBZutsAR7LhAFG87ABTqvEASLn0AFu2
+        9gBipuoAdaDgAGy46wBrr/MAYrb0AHa89ABKwd0AU8feAGfIywB1zcsAdNHCAGLL0wBzytMAedLSAFvG
+        5ABLyfEAT8L4AFfJ+QBb1P4Ae8bsAGnK+gB1w/cAZdf9AHfb/QBo4P4AhIODAISIiACMjIwAi5KRAJOU
+        lACUmJcAlZmZAJqcnACgn58AhqSZAJOhnQCEsJ8AnaGhAJqvqQCDtKIAjbOlAIW8pwCMuKcAjb+sAJWy
+        qQCcsqsAnrivAJm9sACjpaUAqKamAKWpqQCqra0AprOvAKG3sACtsbEAoryzAKu6tQCuvbkAsbSzALW6
+        uQC5vLwAg8CpAI7HsQCXyLYAq8i9ALzAvwCH1c8AgM7dAITU2ACT3dIAvcLBAJrh0gCGx/kAl8PyAIvR
+        +gCY1/oAo8/0AKzT9AC53vgApeXuALnq6gC05v0AwcTEAMPIxwDFyckAys3NAM7R0QDS1dUA1tjYANrc
+        3ADI5voAyfT+ANb0/QDg9/4AAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLSAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANLQwMC+u73QAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAADW09PYZFVVZNK7vdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAANbW2VseGxoZGRdd0Lm+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29zJLisb
+        GxoYGRkSIsy5uwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAObc5lZmLSsrGxsaGBkSEgrHu7oA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8vLmRGhoZi0rKxwZGBkZEhIIXru6AAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAD29OZCaGhoaGYtHEkCEhgZExIICMe7ugAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAD19ERoaGhoaGgcO48yARkYGRISCArIub0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPX1UWhoaWlpaGiF
+        N4w5MBIaGRkSCAgMxgO/AAAAAAAAAAAAAAAAAAAAAAAAAAAA9vZdaGhpaWtra2iHN4w6MRIaGBkSEggI
+        I9C50gAAAAAAAAAAAAAAAAAAAAAAAAD59dgraGhpa2tra2iCNq+AShobGhkZEggICFy7vQAAAAAAAAAA
+        AAAAAAAAAAAAAAD29UBoaGhpa2tra2mGNa9IBSsbGxgZExIICAnNucAAAAAAAAAAAAAAAAAAAAAAAPj1
+        Xi1oaGhpa2trc2umOLCBLxwrGxoYGRISCAhPwLsAAAAAAAAAAAAAAAAAAAAAAPbyHmZoaGhra2tzc2uZ
+        fbCBTBgrKxsYGRkSCAgFzLnAAAAAAAAAAAAAAAAAAAAA+PVdLS1oaGhra2tzc2uZfbCUTSstKxsaGBkS
+        EggIT8C+AAAAAAAAAAAAAAAAAAAA9fIeLS1maGhpa3Nzc3OZfZ6UDSstLSsbGhkZEggIBc270gAAAAAA
+        AAAAAAAAAAAA8scrKy1maGhpa3Nzc3OIfbCBfhxoLSsbGxgZEhIICFi+wAAAAAAAAAAAAAAAAAD38igr
+        Ky0taGhpa3Nzc3OIfbCBfhtoZi0rGxoZGRIICAvWvwAAAAAAAAAAAAAAAADy2BwqKy0taGhpa3Nzc3OZ
+        fbGBfxtoaC0rGxsYGRISCAjIvtIAAAAAAAAAAAAAAADyXhsbKystZmhpa2tzc3OmfbGBfxtpaGgtKxsa
+        GRkSCAhTwNAAAAAAAAAAAAAAAPncUxsbKystZmhoa2tzc3OnfbCTfxtraWgtKxsbGBkSEggO1tAAAAAA
+        AAAAAAAAAPXbQy4bGystLWhoaWtzc3OmOLF9fitra2hoLSsbGhgZEhII1NIAAAAAAAAAAAAAAObUP2xs
+        KysrLWhoaWtzc3OmNLF9TBlra2loLSsqGxgZEhIIx8AAAAAAAAAAAAAAANzIP2xsbWUrLWZoaWtzc3On
+        sLKcmz0ra2toaC0rGxoYGRISU9LSAAAAAAAAAAAAANZePz9sbW1tLS1oaGtraR+usraysq4ELWtpaC0r
+        GxsYGRMSI9bSAAAAAAAAAAAAANNaPz9sbG1tbW5oaGktRrO3uLi2srEzDRtpaGgtKxsaGBkSF9zSAAAA
+        AAAAAAAAANNTPz9CbG1tbW9xai1Otbe4uLi2srGLiS8baGgtKxsbGBkTFdvTAAAAAAAAAAAAANNPPz8/
+        bG1tbW9vb2OktLi4uLi2srGxnooHLWhoLSsbGhkZEtfWAAAAAAAAAAAA+NIlJj8/bGxtbW1vcKK1tLKy
+        trKysbK2spB8FmhoLSsbGxgZE8/WAAAAAAAAAAAA99IlJj8/P2xtbW1teLWfn7S0tLKxsbKysZ6ODWho
+        Zi0rGxoZGcvbAAAAAAAAAAAA99IlJj8/P0JsbW1trKWd6vv8/Pz8/PHrsZ6KOy1oaC0rGxoYGd3cAAAA
+        AAAAAAAA99IjJiY/Pz9sbG1t46WY4uXn5+Xn5eKtq5uNRy1oaC0rGxsaGd3cAAAAAAAAAAAAANAoJiY/
+        Pz8/bG1t46U8bW9ycnR0dHR0dJegYW9xbm5nLCAbHHnmAAAAAAAAAAAAANBPJiYmPz8/bGxtretIQG9y
+        dHR0dHR0dJajYnJ0cm9vbW1tQt7yAAAAAAAAAAAAAMBQJiYmPz8/P2xtevGVD21ycnR0dHR0RqCkRXR0
+        cm9vbW1tbN/yAAAAAAAAAAAAAMBXJiYmJj8/Pz9sbe/tSxFtb3J0dHJtkuiYbXR0cm9vb21tbN/yAAAA
+        AAAAAAAAAMBZIyEhJiY/Pz9sbHf77GAQJ21tbD6R6aRGdHR0cnJvb21tRODcAAAAAAAAAAAAANa+vr1Z
+        UCQmJj9CbGx7/PqzkkhIS6HspGNydHR0cm9vdV/X8/X0AAAAAAAAAAAAAAAA9tzSvr5ZKCY/P2xtd/D9
+        /Pru8eqadnJ0dHRybVvP9Pb3+QAAAAAAAAAAAAAAAAAAAAAAAPLSwFkoJj9sbW13qqmoeHZvcnJ0cm9a
+        2PX3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9dK/VyY/bG1tbW1vb29vcnJyVNf19gAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAADywFknP21tbW1tb29vb29c4fX5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAA99LCQz9sbW1tb29vcMry9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWw08/
+        bG1tbW1Sz+b3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3MDCV1FRWsTW3AAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPXTwdLS0db1AAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf3+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///5///8AAP//
+        8A///wAA///AA///AAD//4AB//8AAP//AAD//wAA//wAAH//AAD/+AAAP/8AAP/wAAAf/wAA//AAAA//
+        AAD/4AAAB/8AAP/AAAAD/wAA/4AAAAP/AAD/gAAAAf8AAP8AAAAB/wAA/wAAAAD/AAD+AAAAAP8AAP4A
+        AAAAfwAA/gAAAAB/AAD8AAAAAH8AAPwAAAAAPwAA/AAAAAA/AAD4AAAAAD8AAPgAAAAAPwAA+AAAAAA/
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA8AAAAAAfAADwAAAAAB8AAPAA
+        AAAAHwAA8AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAfAAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAf
+        AAD+AAAAAH8AAP/gAAAD/wAA//gAAB//AAD//gAAP/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//
+        8A///wAA///+P///AAAoAAAAIAAAAEAAAAABAAgAAAAAAAAEAAAAAAAAAAAAAAABAAAAAQAAAAAAAF9i
+        YgBhZGQAZmlpAGlsbABtcHAAb3d1AHB0dAB1eHgAe35+AAyXXQAKmV4ADYtlAAudYQASmWEAEp9vAB2e
+        aQATnXEAIZ5rAAyjZAAMqWgADa1qAA2ubAASpmkADrFuABSkdAATrXIAFqd5ABasegAOtnAADrt0ABK1
+        cwAQuXMAEbp0ABC9dQAYuXYAHbl4AC2ldAAjrnUAMqBzADaqegA6qn0ALLV9AC25fwA0sn8AQaN7AA/A
+        dwAPw3gAEMB3ABHEeQAfwH4AEct9ACDCfwAWaIIAIXyMACl/mwAjc9UAHYyXADSOigA0l48ANJecADaa
+        nAAuvIIAP7ODADO8hwAkgbYAOKWlAH2AgABtmogAeJyOAE+nhABFrIIAT62HAFalhgBQqoYAXaeKAFyt
+        jQBOuo0AVLONAF+1kgBTvZIAW7mTAGurkgB1oZAAca2WAHqrmABjtJUAa7aYAGC+mABsu5sAcrGYAHq0
+        nQBCiKoAUpW7AEO0rgBYpLwATr24AHS/oQB7vaMAH8WAABPMgQAfzoUAEtOCABLZhQAS3YgAI8aCAC/B
+        hQAjy4UAL8eIACDKiAAvyokAMcOGADLEiQAxy4sAKtSNADHRjgA2yZAAPMyQAC7bkwAz1JEANNqVADXe
+        mAAT4osANeOaAD7DtABFxpcATMGRAEXHmQBSwZQAR8G2AHHEowB4xKYAfdi/AC+dxgAuks4APZfMADKf
+        ygAnh9UAK4PXADGM2wA1ktYAM5vRADyl2AA7m+IAOpHrADqc6wA6pOAAP6riAD2t9wBCrsMATqnIAFi8
+        xQBTuM0AQKvWAEGq2ABbqNwARrDYAEiy2ABRs9oAZbTbAEOr5QBBpugARazoAF+n7wBLuuMASrPpAEe8
+        9gBYtPUAebbyAHXUwwBVyOYAUsLyAFnJ9gBVzf4AW835AFnU/wBc2P4Af8vpAHbT4QBrw/gAe8T1AGPW
+        /gBs0/sAZ97/AG/a+QBi4P8AaOH/AIKGhgCEh4cAhomJAIaMigCLjY0AjpGQAIiXkQCPlpQAjJyXAIqf
+        mACTlZUAmJqaAJqdnQCDoJUAiqOaAIarnQCQoZwAgbGeAJ2ioQCarKYAjbOkAIK+pgCNvaoAl7msAJ69
+        sQChpaUApKamAKaqqgCorKwAorGsAKe3sgCtsLAApLmxAKu7tgCytLQAtbm5ALO+ugC7vr4AmMGxALbC
+        vgC5wL4Ah73yALXGwAC+wsEAu8jEAKjo3wCbyu8AldzhAIjL+ACD0vsAhtv9AJPf/QCn2/oAstr1AJ7j
+        4ACm5OEAq+ngAKbh9QC+5/wAwsXFAMXKyQDLzc0AzNDPAM7R0QDR2NYA1NrZAMPr7wAAAAAA////AAAA
+        AAAAAAAAAAAAAAAACAcEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAu9XOWlTLvgEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAMfZUCEdFhdMwgcAAAAAAAAAAAAAAAAAAAAAAAAAAN/f0WMxMSEYFhMlwwnCAAAA
+        AAAAAAAAAAAAAAAAAADi5mJmZjMxGhMWFhMQyQnCAAAAAAAAAAAAAAAAAAAAAPdiZmZmZhyFNRMWEw0S
+        wwkAAAAAAAAAAAAAAAAAAAD34WZnZ2dmiIs4DBgWEwsnwgQAAAAAAAAAAAAAAAAA9udjZmdoaGeGkooP
+        IRYTDQtLvgQAAAAAAAAAAAAAAAD6TWZmZ2hoaI2TNxghGBYTDQrJQwAAAAAAAAAAAAAA99MzZmZnaHpo
+        maCPETEhGBYTCy3CBAAAAAAAAAAAAAD4PzNmZmdoenqaoocfMyEdFhMNCslDAAAAAAAAAAAA99sxM2Rm
+        Z2h6eo6hjxkzMSEYFhMLRsW+AAAAAAAAAADmTzEzM2ZnaHp6jqKPG2YzMR0WEw0OzQMAAAAAAAAAAPYm
+        ITEzZmdoenqcpY8cZ2YxIRgWEwtVuwAAAAAAAAD32CQhLzNmZ2h6ep6ljxxoZjMxHRYTDUrNAAAAAAAA
+        AODMamMvMzNmaHp6maCMGWhnZjEhGBYTEte+AAAAAAAA31Zqb2MxM2ZnemiqrquVMWhmMzEdFhMN2AcA
+        AAAAAADaTmpvbHFlZmdkYLi3sKw2H2dmMSEYFhPPBwAAAAAAAN9HampvbnNybZ62urmwrZFBH2YzMR0W
+        E1sJAAAAAAAA2ilqam9xbnOXs7WwsK+ttZQ5ZmYxIRgWV7sAAAAAAADaKCtqam9ubrSn7O7u7e22pokh
+        ZjMhHRZWxQAAAAAAANcoK2pqb2x/tJ/x8/Ly6rKkkBpmMzEhGFHHAAAAAAAA1ikrK2pqb33rO3d4eXt7
+        e3yjQHZyazQkWMcAAAAAAADVRysrK2pvbPRcb3h4e3t5lpt3eHdzbm+CwgAAAAAAAM1KKysrampvqek6
+        b3d4d0KoXnl4eHdubIPCAAAAAAAA18JESSgramps8/BfPTxd5Jh3eXh4boDQ580AAAAAAAAA99/VzUVH
+        K2pshP3177GBd3h4dWHl+Pn7AAAAAAAAAAAAAAAA39VTLGpsbmx0d3h4d1nm9/wAAAAAAAAAAAAAAAAA
+        AAAAAN/LP29ubm53d3XS9vwAAAAAAAAAAAAAAAAAAAAAAAAAAOPNSGpsbm5+3OYAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAPfXyFJSyt/2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADg39/gAAAAAAAAAAAAAAAA
+        AAD//D////AP///gB///gAH//wAA//8AAP/+AAB//AAAP/wAAD/4AAAf+AAAH/AAAA/wAAAP8AAAD+AA
+        AA/gAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH4AAAB/AAAA//AAB//8AB///g
+        B///8A////w//ygAAAAQAAAAIAAAAAEACAAAAAAAAAEAAAAAAAAAAAAAAAEAAAABAAAAAAAAen9/AAub
+        XwANnGEAD5duADSecwA7n3cAC6BiAAuiZAAMo2QADKZnAAyqaAAOrGoADbBtAA60bwAPu3QAD751ABC5
+        cwAQvXUANq9+ADmufgAtuH8AMbB8AEmcewBxhH0AeoB+AEmifgAPw3gAEsB4ABHHewAcwn0AEch8ABHM
+        fQAhmZcAFbSAABW5gwAasIsAP66BAC27gQAuv4QANbOAADaulAA7t58APLacABuIoAAon6oAJ6KlACGg
+        qQApoq4Aeo+HAH+OiQB2lYkAXKKGAFKohQBBsoQARbeJAEi/jgBWsIwAWraRAG6ljwBIt7gAEs+AABzL
+        ggAR0YAAEtWCABLXhQAS2YYAE9yHABPbiAAT3YgALsCEAC7EhgAqyocALM2KADDGiAAwy4sAMc+NADjL
+        jgA6zJAANcuaACLQkwAv2JIANdqVADPclgA40ZwAE+KLABPjjAA14poAPcysAErAjwBBxZUAQ8iVAFnH
+        mgBC0pcAc8SiAHnEpgAymNQAPabbAD+o5QBErt8AYrTVAECn4ABFruAAW8bEAGnMwwBj0MAAetjBAFLE
+        6gBcxu0AV9H+AHfH6gBjyPMAYdP1AGHc/gCCh4YAj5eVAJSZmACGqZwAl66mAIC6owCYsqkAoK+qAKm1
+        sACtu7YAsb25AIzFrwCrwLkArMC5AIrG0wC1xcAAvcrFAL7OyAC/08wAkt3vAJ3j7wDAyscAwNLLAMfQ
+        zQDG19AAxdjTAMnY0wDI2dQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8AAAAAAAAA
+        fjEYdAAAAAAAAAAAAAAAeVkRDBoZAAAAAAAAAAAAfkk9JAQKBQEAAAAAAAAAiU1CPWAsDQoXcgAAAAAA
+        AF49RERhIQ8MAjMAAAAAAIcePURVZS4dDQoGcwAAAAB3Gz1CVWYwPQ8MAzIAAAAAOh0gQlVjLUIgDQo7
+        AAAAijdHPj1QcGsiPREMNQAAAIkoR0tPb3FtYiMgDSV6AACDFiZHZ26GhWwvPREoewAAgxMVJmgpU1dY
+        PFFIOHwAAIQ0FBVagCsrZFRTTl8AAAAAAIJ1NltqaVRdfYwAAAAAAAAAAIE5SktcgwAAAAAAAAAAAAAA
+        jHZ4iwAAAAAAAPw/AAD4HwAA8A8AAOAHAADgBwAAwAMAAMADAADAAwAAgAMAAIABAACAAQAAgAEAAIAD
+        AADgBwAA+B8AAPw/AAAoAAAAMAAAAGAAAAABACAAAAAAAIAlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAA8Pz8DLC0tF0NGRl5eY2OPXGFhkjw/P2QPDw8fCwwMChITEwQAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAVFdXAkRGRitwdXWdmp+f8Zmbm/6Zmpr+lZaW/42Ojv6Kj4/zY2hooBsc
+        HDAKCgoKFBUVAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABRU1MScXV1j6arq/eoq6v+qLez+3i7ovpTto/5U7SO+nq3
+        ofuirav9jIyM/4iNjfdYXV2QCgoKFhITEwYPEBABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAd3l5AmBiYkSjqKjfsLGx/628uPpdu5X5F7l2/BC4
+        c/8Ps3D/Dq9t/w2qaf8Zpmz+b7Wa/Z2lo/6Dg4P/fIOD2CMkJDwMDAwJFBUVAQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACBhIQDe35+d7a5ufm6vb39gbqk9h/A
+        ffsRxHr+Eb93/xC7df4PtnL+DrJu/w2ta/4NqGj+DKRl/zKnd/6Xsqr+h4aG/4WKivM7Pj5gBwgIChUW
+        FgIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAI2QkAWTl5eWvL6+/r7E
+        w/tUt4/2E82A/hLLfv4Sx3z+EcN5/xC+d/4QuXT+D7Vx/w6wbf4Nq2r+DaZn/wyiZP4Wn2f+hrSk/o2N
+        jf6Dh4f7RkpKcAgICAsWFxcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmJubBZ2h
+        oaDCw8P/uMTB+ji7hfgT04P/E9GC/xPOgP8Sy37/Ecd8/xHBef8QsnD/Dqpq/w+yb/8Ormz/Dalp/wyl
+        Zv8MoGP/D5xi/3uwnf6Njo7/hIiI/UZJSW8LCwsKFRYWAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACtsLABq6+vksbIyP68xsP6Mr6E+RPWhf4T1YT+E9OE/xLRgv4SzoD+Esh9/xC1cv4rn6r+DXBZ/w6l
+        Z/4OsW7+Daxr/wynaP4Mo2T+C55i/w+bYf6AsqD/i4qK/oSIiPo1ODhXEBERCAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACusbFsyczM/sXLyvs4uoX4E9aG/xPXhv4T1ob+E9WF/xLUhP4S0IH+FbZ3/yKA
+        k/43q+v+Imm2/wxyVf4OrGv+DrBt/w2qav4Mpmb+DKFj/wucYP4RmmH/j7On/oSDg/6GjIzxHB0dMhcY
+        GAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uDnLzs74zM/P/Um0iPYT1oX/FNeG/xTYh/8U2If/E9iH/xPX
+        hv8S0YL/N7XG/y53yP80nuf/KHTR/xZqof8NoGP/DrNw/w2ubP8MqWj/DKNl/wufYv8Lm1//HZto/5qv
+        qf+Afn7/e4KC0AoLCxUZGxsCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAury8DcXJydjP0dH/cLGX9RPTg/4T1ob+FNiH/xPZ
+        h/4T2oj+FNqI/xPZiP4S1IT+NKvS/y53yP4znOb+J3rT/xVwrv4NomX+D7dy/w6ybv4NrGr+DKZn/wyi
+        ZP4LnWH/Cple/jqieP6coaH/goKC/lZaWooODw8JAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAub29is7Pz/+mvbX3Fsd+/RPV
+        hf8T14b/FNmH/xTaiP8U24n/FNyJ/xPcif8T14b/MJ7Q/ylyxv9Jy/H/KYHU/zGUp/8PtHD/D7t0/w61
+        cP8Nr2z/DKlp/wykZv8Mn2P/C5tg/wqYXf9wr5f/jYyM/4mOjvcfICA1HB0dBAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC4urooztHR+crO
+        zvwws334EtKD/hLUhP4T14b+E9mH/xPbif4T3Yr+FN6L/xPei/4T2Yf+M6PU/yV0xf5OyPL+NYKv/w+S
+        Xf4QwHj+EL92/w+5cv4Osm/+Da1r/wynaP4MomT/C51h/gqZX/4Sl2H/nLGr/oOBgf5yeHi4DQ0NChUW
+        FgEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AADEx8erzc7O/3iym/YSzX//EtGC/hLUhP4S14b+E9mH/xPcif4T3or+FN+L/xPgjP4T3In+RsDa/y18
+        yP5QxPP+OZDY/xp+hP4QtHH+EMJ5/w+9df4OtnH+DbBt/wyqaf4MpWb/C6Bj/gucYP4KmF7/TKaD/pia
+        mv6Mj4/+KiwsQx0fHwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALu9vS3N0ND6v8bF+x62d/oSzoD/EtCC/hLUhP4S14b+E9qI/xPcif4T34v+FOCM/xPi
+        jf4U3or+Rr3b/zWDy/5QwfX+PZbd/y2Uv/4PsG3+EcZ7/xDAeP4PunP+DrRv/w2ua/4MqGj/C6Nl/gue
+        Yf4Lml//DZde/pSyqP6HhYX/cXh4tBAREQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAL/Dw57Jysr/bbGW9hHIfP8RzX//EtCB/xPTg/8T1oX/E9qI/xPd
+        if8T34v/FOGN/xTjjf8U34v/Rrvd/zmHzP9Pv/f/QJre/zaio/8Rwnj/Ect9/xDEev8QvXb/Drdy/w6x
+        bv8Nq2r/DKZn/wygY/8LnGD/Cphe/0imgf+bnZ3/kJSU+x8gIDEhIiICAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuLu7E8jLy/LCxsX7HrF0+hDIfP4Ry37/Es+B/hLS
+        g/4S1oX+E9qH/xLdif4T4Iv+FOKN/xTkjv4U4Iz+Qrje/zmIzP5Luvj+P5ja/xmCd/4RwXj+Es5//xHI
+        fP4QwXj+D7t0/w61cP4Nr2z/DKlp/gujZf4LnmL/C5pf/g6XX/6cs6z/i4qK/lxhYY0ZGxsHAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvMDAZcbGxv6Ds6H3EMF4/xDH
+        e/4Ryn3/Ec6A/hLSgv4S1oX+E9mH/xLdif4T4Iv+FOON/xTkjv4U4Yz+P7Xe/zSFy/5Juff+OpTa/yyb
+        wv4Qt3L+EtGC/xHMfv4RxXr+EL52/w+4c/4Osm7/Daxq/gymZ/4MoWT/C5xg/gqZXv5irpH/lpWV/ouQ
+        kOEQEBAQGRoaAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMTEusPF
+        xf47qn33EMF4/xDFev8RyX3/Ec1//xHRgv8S1YT/E9mH/xPdif8T4Iv/FOON/xXlj/8U4o3/P7Te/zKE
+        y/9Pwvj/OJHX/y2cwv8QuXP/E9SE/xLPgP8RyXz/EMJ5/w+7df8OtXH/Da9s/wypaf8MpGX/C59i/wub
+        X/8cmmb/q7Gw/5WYmP8tLi5FJSYmAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC3uroPw8bG+a65tvkSs3D9D8B3/xDDef4RyHz/Ecx+/hHQgf4S1IT+E9mG/xPcif4T4Iv+FOON/xTl
+        j/4U4o3+Rbze/zmJzP5azvn+PZHV/zKewv4Ru3T+E9eG/xLSg/4SzH/+EcZ7/xC/d/4PuXP/DrJu/g2s
+        av4Mp2f/DKFk/gudYf4KmV7/jbSm/pOSkv5dYmKNIiMjBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAC2urpMwMHB/3uxnPkOuXP+D792/w/CeP4Qx3v/Ect+/hHPgP4S04P+E9iG/xPc
+        if4T34v+FOON/xTlj/4U443+TcTe/zuLzP5azfr+PpDT/zKew/4RvXb+E9mH/xLVhf4S0IH+Ecl9/xDC
+        ef4PvHX/DrZw/g2vbP4MqWn/DKRm/gyfYv4Lm2D/Wq2M/p6env6HjIzOGBkZCQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8wcGMurq6/1KvifgPuXP/Dr11/w/BeP8QxXr/Ecp9/xHO
+        gP8S04L/E9eF/xPbiP8T34v/FOKN/xTljv8U443/UMfe/zmJzP9Txfn/QI/R/zKew/8Rv3f/E9yJ/xPY
+        hv8S04P/Es1//xHGe/8Qv3f/D7ly/w6ybv8NrGv/DKdn/wyiZP8LnWH/JJ5s/66ysv+coaH8GxwcGCIj
+        IwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7v7/Ctrm5/TqwgPonv4H+Eb12/w+/
+        dv4Pw3n/EMl8/hHNf/4S0YL+EtaF/xLah/4S3or+E+KM/xPkjv4U4o3+TcPe/y6CyP5by/j+Po3P/y6e
+        w/4RwXj+E96K/xPaiP4S1oX+EtCB/xHKff4Qw3n/D7x1/g62cf4NsG3/DKpp/gykZv4MoGP/DZth/qG3
+        sP6go6P/MjMzSy4vLwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALW4uAS5vLzspbKu+i64
+        gP4wwYb+LMOF/xbAev4Pwnj/EMd7/hDMfv4R0IH+EtWE/xLZh/4S3Yn+E+GM/xPkjv4T4oz+SsDe/x98
+        xv5byvf+OYbF/yWRtP4QsG3+E9yJ/xPdif4S2If+EtOD/xLNf/4Rxnz/EMB3/g+5c/4Os2//Da1r/gyn
+        Z/4MomT/C51h/oC2ov6fn5//VFhYeTEyMgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK1
+        tRy4urr8i7Gj+i+6gP8wwIX/MMOH/y/HiP8fxYH/EMV6/xDKff8Rz4D/EtSD/xLYhv8T3Ij/E+CL/xPj
+        jf8T4Iv/Vsje/0q98P9g0Pz/Ubzs/0ey4f80nZj/EcF4/xPeiv8T24j/E9aF/xLQgf8Ryn7/EMN5/w+8
+        df8OtnH/DbBt/w2qaf8MpWb/DKBj/1ywj/6mpqb/cHV1oSwuLgYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALK1tTuztLT+drKc+y+6gf4vv4T+MMKG/zDFiP4xyYr/KcuI/hXKf/4QzX/+EdKC/xLW
+        hf4S24j+E92J/xLYhv4Xt3r+X8nh/2XX/v5o2v7+XdX//1fR/v5XxOj+EI5c/xLMf/4T24j+E9iH/xLT
+        g/4SzX//Ecd7/hC/d/4PuXP/DrJv/g2ta/4Np2j/DKJk/jqnev6ytLT/hoqKwycoKAcAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALK2tlaurq7+ZLCS/C66gf4vvoP+MMGF/zDDh/4xyIn/McuM/jHP
+        jf4i0If+EtGC/xHVg/4S2Ib+Esx//zezn/55zev+ed/+/2zg/v5k3v7+X9v//1rU/v5cxvb+LHK0/x2A
+        cv4RuXT+E9iG/xLWhf4S0IL/Ecp9/hDDef4QvHX/D7Zx/g6wbf4Nqmr/DKVm/h6ha/64vbz+m5+f4CUm
+        JgkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uWqsrq7/Va2K+i66gP8vvIP/ML+E/zDC
+        hv8wxon/McqL/zLOjf8y0o//L9WQ/x7Vif8Syn//Pq24/2/E+P912Pz/bOH//2bi//9j4P//X9v//1nT
+        //9Vyfz/NZPk/yuB4P8eeoD/Ebp0/xPWhf8T04P/Es1//xHGe/8Qv3f/D7lz/w6zb/8NrWv/Dado/xCj
+        Zv+yv7v+pqqq8igpKQ8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS5uXuqrKz+RqiA/C65
+        gP4vu4L+L76D/y/Bhf4wxIj/MciJ/jHMjP4y0I/+M9SR/zLUkf5Muq/+YLLz/2XP/P5k3P7+Y97//2Hf
+        /v5g3f7+Xdj//1jS/v5Syv7+WMz+/0ex9P4qk+r+GIJv/xLKfv4T1YX/EtCB/hLJff4Rwnn/ELt1/g+1
+        cf4Or23/Dapp/gylZv6lv7f+rrOz+S8wMB0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALG2
+        toanqKj+P6h9/i23f/4uu4H+L72D/y/AhP4wwof/MMaI/jHKiv4yzo7+MtKP/zrHkf5suOv+cMP3/2nQ
+        /P5k1f7+Xtf+/13Y/v5c1/7+WtT//1XP/v5c0P7+aNn+/17T/P43p/b+KY/N/xCkaP4T1YX/EtKD/hLM
+        f/4RxXv/EL53/g+4c/4Osm//Da1r/gynaP6XvrD+s7a2/ScoKCcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAALG2toukp6f/Pah8/C23f/8uuYD/L7yC/y++g/8wwYX/MMSI/zDJif8xzIz/Ms6O/1rE
+        tP97w/j/W7b2/1/A+f9py/v/b9P9/2zU/f9j0v7/Wc3+/17P/f9l1vz/W9D7/1PJ+v9FuPX/KZT1/xeI
+        c/8T0YL/E9SE/xLOgP8SyHz/EcF4/xC7dP8PtXD/Dq9t/w2qaf+Nv6z9trm5/zExMS8vMTEBAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALC1tYmipKT+PKh7+y22fv4uuID+LrqB/y+8gv4wv4T/L8KG/jDH
+        iP4xyor+McyM/3PK0/52v/b+U6rx/4vR+v7K8f7+2Pf+/9r4/v7W9f7+1PL+/9Hw/v656P7+l9z9/1/I
+        +v5DuPP+L47t/yGBlf4Sy37/E9WF/hLQgf4Syn7/EcN6/hC9dv4Pt3L/DrJu/g2sa/6FwKr+ub29/jY3
+        NzQ1NjYBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6zs4SgoqL/Pad7/S21fv8ut3//LrmA/y+7
+        gv8vvoP/MMGF/zDEh/8wyIn/MciK/4DO3f9zuvP/WabQ/4fVz/+S3tH/m+HS/5ri0v+V39L/mN7T/5Db
+        0/+F19P/dtLT/2LL0/9Jtd7/P5Xr/yuEpv8SyH3/E9eF/xPSgv8SzH//EcZ7/xG/d/8QunT/D7Rw/w6v
+        bf+Bwaj/vL+//zg4ODU4OTkBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK60tHueoKD+Qad+/i21
+        ff4tt3/+LriA/y66gf4vvIL/L7+E/i/Chv4wxYj+MceJ/4TR3f56vfP+N4qT/zLHif4z15P+NNqV/zXd
+        l/4135n+NuGa/zbjm/425Jz+N+Wd/zfim/5DusH+YKfv/0mZtf4x0ZD/LdyU/ifXjv4i0Yn/HcuD/hnE
+        fv4Xvnn/FLh0/hGycP5/wqj/vsHB/kRFRTIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK6z
+        s2yeoKD+SqaB/C2zff4ttn7+Lrd//y65gP4vu4L/L72D/i/Ahf4ww4f+MMaI/33S0f6a0/f+OYGn/zG3
+        gP4z15P+NNuW/zXemP414Jn+NuOb/zbknP425Z3+N+ae/zbemf5Fps3+a6/z/0Whqf412JX/Nd6Y/jXa
+        lv401pP/NNGQ/jPNjv4yyIv/MsOI/jG+hf6Ox7H+wMPD/j09PSkAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKuwsFiam5v/VaqJ/S2zfP8utX7/Lrd+/y64f/8uuoH/L7yC/y+/hP8wwYb/MMOI/2DK
+        sP+y6v7/V5LY/y+PcP8yzY3/NNiU/zTblv813pj/NeCZ/zbimv8245z/NuKb/ze+mP9lpeb/YrH2/zuv
+        kP823pj/Nt6Z/zXalv8115T/NNOR/zPOj/8zyoz/M8WJ/zLBhv+TyLT9wMPD+zU1NSEAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKisrECbnJz+YauP/Sywe/4ttH3+LbZ+/y23f/4uuYD/LruB/i+8
+        g/4vv4T+MMKG/zbBi/6l5e7+rNP0/zyEsf4vnXL+M8yM/zTXk/4025b+NN2Y/zXfmf413Zf+NMSO/0SR
+        yf6GwPX+UanR/zXNjv4235n/Nt6Y/jbalv4115T/NNSS/jTQj/4zzI3/MsiK/jLCh/6bybf7vsLC9j0+
+        PhYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKirqyWdn5/+eaeW/Tilef4tq3f+LK55/yyy
+        e/4ttX7/LrmA/i+7gv4vvYP+MMGF/zDCh/5dy6r+yff+/6XP8v5Cj7f+MY90/zGzff4yxon+MsqM/zLD
+        h/4ypon+QYjD/5fD8v5huPP+O7mU/zbdmP4335n/Nt2Y/jbalv422JT/NdST/jTQkP4zy4z/McOI/j24
+        hv6ryL39tbi47kVGRgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqurg2ts7P1k5GR/5GT
+        k/+JlpL/dKCQ/1enh/8zqHj/LLB6/y22fv8vu4H/ML+D/zDBhv8wwof/ddS7/9n7/P/L6Pr/fcDu/0aY
+        wP85jaj/Noin/zyBuf91oOD/os/3/2e+9f9BuaT/NtqW/zffmf833pn/N92Y/zbalv8115T/NNCQ/0DA
+        jPxwvZ/+oL6z/sPIx//Nz8//vMDA2YGDgwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACqra03sLa2abC2tpussLDZpKam+5eXl/6UmJf/d6KS/keogf4tsXv+Lrl//y++hP4wwob+McOI/1vL
+        pv656ur+4Pf+/9rx/f7G5fr+ud74/7Pg/P6Gz/3+Wbrb/z3Bmv412ZX+Nt6Y/zbemP423Zj/NtuX/jbN
+        j/1cuZP4mryv+sbJyf7P0tL/ztHR8cnNzbPFyMhxt7m5MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqysIrG2tnGytrbIpaam/ZiZmP5/opX+QauA/y22
+        fv4vvoP+MMKH/zHGiP40xYr+Vsum/3TRwv51zcv+Z8jL/1XFvv5AxKD+NdGR/zXZlf4125f+NtyY/zbc
+        l/42z5D9YrST96q4tPnLzc3/ztHR88jMzKjDxsZNxcjIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACusrIBrrKyN7W7
+        u7OnqKj+l5ua/2Snjf4utH3+L72D/zDDh/8xx4n/MsmL/zPMjf8zzY7/M9CP/zPTkf801ZL/NNeU/zXZ
+        lf822pb/NdmV/0q7jfigtq74yMrK/8rNzerDx8Z8w8bGFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAACwtLRAtbq615+env59pZb+M7J+/i+9g/4xxIj+MsiJ/zLLjP4yzY3+M8+P/zPS
+        kP4z1JL+NNaT/zTXlP4105H+arGV9rzAv/3Jy8v4v8PCh7/BwQ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAr7KyDLa7u5ump6f+iaSb/jqwgP0vvIP+McWH/zLJ
+        iv4yy4z+M86O/zLQj/4z0pH+M9OR/zjKjvyJtqX4wMLC/8LGxtO6vb0zAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC0tAGyt7dqra+v+pOh
+        nf5NrIb9LrqB/zDBhf8yxon/MsqL/zLMjP8xzIz/RLyL+p23rvq/wMD/vMHAp7i7uw4AAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAsLW1RbO3t+uen5/+gqSX/F+tjvxNrof8TbGI/V6zkfqCr576sLOy/by+vvm2u7t4t7q6AQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAALCzsyC4vb22ra6u/qCfn/6hoaH+pKSk/6impv60tbX+vMDA0LK2
+        tj4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACztrYBsrS0Mre8vHu4vLybuLy8n7m9
+        vYSztrZDtbi4BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///wB///AAD//8AB//8AAP//gAB//wAA//4AAD//
+        AAD//AAAH/8AAP/4AAAP/wAA//AAAAf/AAD/4AAAB/8AAP/gAAAD/wAA/8AAAAH/AAD/gAAAAf8AAP+A
+        AAAA/wAA/wAAAAB/AAD/AAAAAH8AAP4AAAAAfwAA/gAAAAA/AAD8AAAAAD8AAPwAAAAAHwAA/AAAAAAf
+        AAD4AAAAAB8AAPgAAAAAHwAA+AAAAAAPAAD4AAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAA
+        AAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA8AAAAAAHAADwAAAAAAcAAPAAAAAABwAA8AAAAAAP
+        AADwAAAAAA8AAPAAAAAADwAA8AAAAAAPAADwAAAAAA8AAPAAAAAADwAA+AAAAAAfAAD/gAAAAP8AAP/g
+        AAAH/wAA//wAAB//AAD//gAAf/8AAP//AAD//wAA///AAf//AAD//+AH//8AAP//8A///wAAKAAAACAA
+        AABAAAAAAQAgAAAAAACAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAEqefgVFZlpGVVlZzmhra/ZlaGj3QUVF1B8nJFQdOC4QAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABTaGEXbXRz26Clpf+arKb/crGY/3Gtlv+RoZz/hoqK/0dK
+        St0UIRwjGzUsAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbYF6f5uenv2nt7L/U72S/xO6df8PtHD/Dq1r/xKm
+        af9crY3/j5aU/29zc/wgISF4GS4mBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVcOWAYOVj5y0t7f/jb2q/x/FgP8Sx3v/EcB3/xC5
+        c/8Psm7/Datp/wyjZf8tpXT/ip+Y/3t+fv8kJyeEHDYsBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACVpqCuv8LC/3i9of8U0IL/E9CB/xLM
+        fv8Rxnr/E690/w6hZv8Or2z/Daho/wyhY/8dnmn/iaGZ/31/f/8lJyeLGy8nBgAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAorWueMXIyP9+vqX/E9SD/xPW
+        hf8T1IP/EtCB/xWvev8vncb/FmiC/w2kZf8NrWv/DKVm/wyeYf8gnmr/jJyX/3h8fP4ZIh5HOYNlAQAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ++sjzGyMj+mMGx/xXR
+        gv8T2IX/E9mG/xPYhv8S04P/Mp/K/zGM2/8jc9X/DYtl/w6ybv8Nqmn/DKJk/wubX/8yoHP/jpKR/2Ro
+        aPcfNCsiAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv8LC7LzI
+        xP8gxYD/E9aF/xPZhv8T24j/E9yI/xPYhf8uks7/OqTg/yuD1/8Sn2//D7hy/w2vbP8Mpmb/DJ9i/wqZ
+        Xv9dp4r/h4iI/zc6OrwbKiQFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALK/
+        unvO0dH/TrqN/xPSgv8T1oT/E9qH/xPcif8T3or/E9yI/zOb0f8/quL/KX+b/w+xbv8QvXX/DrRv/w2r
+        af8Mo2X/C5xg/w6XXv+Lo5r/fYCA/hslIi0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AABywqIKxMjI9p69sf8Synz/EtKB/xPWhP8T2of/E96J/xPgi/8T34r/QKvW/0Wq5f87meX/E51x/xHD
+        ef8PunP/DrBt/wyoaP8LoGL/C5le/0Gje/+PkJD/QUdGyR8zKwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAKm+tnfLzc3/P7aF/xHLff8S0ID/E9WE/xPah/8T34r/E+KM/xPhi/9Bqtj/Raro/z2X
+        zP8Us3P/Ecp8/xC/d/8OtnD/Da1q/wykZf8LnWD/C5dd/4qmnP98f3/9LFJEKQAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAv8PD5aS5sf8QwHf/Ecp8/xHPgP8S1YP/E9qH/xPfiv8T44z/E+KM/zyl
+        2f9Bpuj/OZzi/xOlc/8Sz3//EcV6/w+7dP8Osm7/DKlo/wyhY/8Lml//T6eE/5OUlP80OzmWAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHG+nwO/wcH+X7WS/xDBd/8QyHv/Ec5//xLUgv8T2ob/E9+K/xPj
+        jf8T443/PKXY/0av6P85nOT/Fqd5/xLUg/8Ry33/EMB3/w+3cf8NrWv/DKVm/wudYf8SmWH/naWj/1lc
+        XOokQjcGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArbm2ZMHExP8jrnX/D792/xDFef8RzH3/EtOC/xPZ
+        hv8T34n/E+OM/xPkjf9GsNj/Tbfq/z6c4v8Xqnr/E9iF/xLQgP8Rxnr/D7x1/w6ybv8MqWj/DKFj/wua
+        X/96q5j/g4aG/iAwKhEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC1v73JorKs/xi5dv8OvXX/D8N4/xHL
+        fP8S0YH/E9iF/xPeif8T44z/E+SN/0iy2P9IsOn/P5vg/xesfP8T24j/EtWD/xLMff8QwXj/D7dx/w2u
+        a/8MpWb/C55h/1Cqhv+eoKD/KjUxRQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALS6ue6BsZ7/Lr+E/x/A
+        fv8PwHf/EMh7/xHPf/8S1oT/E9yI/xPii/8T44z/QazX/0Kt5f81ktb/FqN2/xPdif8T2Yb/EtGA/xHH
+        e/8QvHT/DrNu/w2qaP8MomT/I59s/6msrP9CTEmjPJhyAQAAAAAAAAAAAAAAAAAAAAB4uJ4Ms7W1+2ey
+        lf8uvoP/L8OG/yfHhP8Ux3z/Ec1+/xLUgv8S24f/E+CK/xLciP9VyOb/W835/1LC8v9CrsP/EcN5/xPc
+        iP8T1YP/Es1+/xDBeP8Pt3L/Da5s/wymZv8MnmL/o7Cs/1ReW9Y6m3QCAAAAAAAAAAAAAAAAAAAAAHa3
+        nRmvsbH+VLON/y68gv8vwYX/MMeI/y/Mi/8fzoX/EtKB/xLYhf8WyoP/Tr24/2/a+f9n3v//XNj//1nJ
+        9v8hfIz/Erd0/xPYhf8S0YH/Ecd7/xC8df8Osm//Dapp/wyiZP+Ns6T/ZWpp7C5VRQQAAAAAAAAAAAAA
+        AAAAAAAAdbedJbCzs/9Er4P/LruB/y++hP8vxIf/MMqK/zHQjv8s1Y//IMqI/1Gz2v9v1fz/aOH//2Lg
+        //9c2f//VMz+/zqc6/8kgbb/ErZy/xPUg/8SzH7/EMF4/w+3cf8Ormv/DaZm/3q0nf94e3v2MVpJCgAA
+        AAAAAAAAAAAAAAAAAAB7tJ4vrrGx/zmsff8tuYD/Lr2C/y/Bhf8vyIj/Mc2M/zHSj/9YvMX/a8P4/2PW
+        /v9d2f7/Xdn//1nU//9Wzv7/ZNf+/z2t9/8djJf/EtGB/xLQgP8Rxnr/ELt0/w6ybv8Nqmn/a7aY/4KF
+        hfoyX00RAAAAAAAAAAAAAAAAAAAAAIGynzqrsLD/Nqx7/y23f/8uu4H/Lr+D/y/Eh/8wy4r/NMiN/3zF
+        8/9YtPX/g9L7/5bf/f+Q3/7/htr+/4fd/f9q0vv/R7z2/yeH1f8RvHT/E9OC/xLKff8Rv3f/D7Zx/w6t
+        a/9gt5X/k5WV/DdpVRYAAAAAAAAAAAAAAAAAAAAAf7CdMqitrf83qnv/LbZ+/y25gP8uvIL/L8GF/y/H
+        iP9Fx5n/esT3/2W02/+e4+D/q+ng/6bm4f+m4+H/ldzh/3bT4f9LuuP/OpHr/xOscP8T1YT/Es1+/xHD
+        ef8QuXP/DrFu/1u5k/+Ym5v8PnBbGAAAAAAAAAAAAAAAAAAAAAB6sZsnpqqq/zupff8ttX3/Lbd//y66
+        gf8uvoP/L8OG/0XGl/+Iy/j/NJeP/zLVkf8z25X/NN+Y/zXimv815Jv/NuWc/z7DtP9fp+//M7yH/y7b
+        k/8o1Iz/I8uF/yDCf/8duXj/YL6Y/5eZmfxHc2EVAAAAAAAAAAAAAAAAAAAAAHmwmx+ipaX/RauC/y20
+        ff8ttn7/Lbl//y68gv8vwIX/MsGI/6bh9f9CiKr/McWH/zPZlP803pf/NeGZ/zXkm/8135j/TqnI/1uo
+        3P800pD/Nd2X/zTXk/8z0Y//MsuL/zLDh/9xxKP/i42N+kVzYQ8AAAAAAAAAAAAAAAAAAAAAeK2ZEp+h
+        of1Qqof/LLB6/yy0fP8tt37/LrqB/y69g/8vwYX/ddTD/5vK7/80jor/McOG/zPXk/8z25X/M9WS/zil
+        pf95tvL/Q7Su/zXemP813Zf/NNiU/zPTkf8yzY3/McWI/3jEpv+Ii4v2SnlmCAAAAAAAAAAAAAAAAAAA
+        AAB6rZkHpqqq94iXkf9tmoj/VqWG/zWqev8ss3v/LrqA/y+/g/8zwYn/qOjf/7La9f9YpLz/Npqc/zSX
+        nP9Slbv/h73y/1O4zf811pP/Nt+Y/zbcl/812JT/NM+O/1LBlP+Cvqb/usnE/5abmu5ZqYgBAAAAAAAA
+        AAAAAAAAAAAAAAAAAACfsKtCqLOwq6eureOkpqb8n6Ki/3icjv9HqoP/LbZ+/y6/hP8zw4n/fdi//8Pr
+        7/++5/z/p9v6/3/L6f9Hwbb/NdaT/zXdl/813Jf/O8yQ/3S/of+1xsD/y87O/8nNzO+/yca3qbu1OgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHexmxSatKxrr7Oz6qSmpv91oZD/NLJ//y+/
+        hP8wxoj/MsiK/zfGj/82yZD/M9KQ/zPYk/802pX/NdWT/2y7m/+8w8L/xsnJ+8DIxqmMxLIpecSmAgAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAo7SvS6+y
+        sviQopz/P7CC/y/Ahf8xyIn/McyM/zLPjv8y05D/M9aS/z3MkP+Xuaz/xMfH/rfCv5Z6xq4DAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAfLajFK62tNqcpqP/T62H/y6+g/8xxoj/McyL/zHOjP9MwZH/q7u2/7zAwPOiwLc3AAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAK22tK6prKz/g6CV/2upkP9srZT/hqud/7W3t/+0u7rTAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcLqgA524sFW0t7fisLGx+bGysvq2ubnpo7yzbXLE
+        qAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/8A///+AD///A
+        Af//AAD//wAAf/4AAD/8AAA//AAAH/gAAB/wAAAP8AAAD/AAAA/gAAAH4AAAB+AAAAfgAAADwAAAA8AA
+        AAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAf8AAAf/4AA///AA///8A////AP/ygA
+        AAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEec
+        ggVkin6JcoiA8Gp+d/JCTEmQK3VfCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFWx
+        lSeSpJ7eSsCP/xC5c/8PrGr/SaJ+/2VsatwtdWEkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3B
+        mR6lu7PqLM2K/xLQgP8asIv/D5du/wymZ/80nnP/aW9u4Sh1VxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AAC4xMDJOMuO/xPZhv8S14X/MpjU/xuIoP8NsG3/C6Bi/0mce/9QV1W1LpJpAQAAAAAAAAAAAAAAAAAA
+        AACMw61ec8Si/xLUgv8T24j/E96J/z2m2/8hmZf/D7t0/wypaP8Lm1//dpWJ/i5lTz8AAAAAAAAAAAAA
+        AAAAAAAAtcG91hzCff8S0oH/E9yI/xPii/9Ap+D/J6Kl/xHHe/8OtG//C6Jk/zufd/9baGSuAAAAAAAA
+        AAAAAAAAZcCbGYC6o/4Pw3j/EdCA/xPch/8T44z/Ra7g/ymirv8S0YH/D751/wyraf8NnGH/fIyH+St/
+        XQUAAAAAAAAAAH++pW1atpH/EsB4/xHMff8S2ob/E+OM/0Su3/8on6r/EtmG/xHJfP8OtW//DKNk/26l
+        j/8ycFc6AAAAAAAAAACUtaiHRbeJ/y3Ehf8cy4L/EtaD/yLQk/9h0/X/UsTq/xW0gP8S0oH/EL52/w2s
+        av9SqIX/RoVrcgAAAAAAAAAAk7OnlDazgP8uwIT/MMuL/zXLmv9jyPP/Ydz+/1fR/v8/qOX/FbmD/xHI
+        fP8OtG//P66B/1duZYIAAAAAAAAAAJSvppoxsHz/LbuB/y/Fh/9bxsT/d8fq/53j7/+S3e//XMbt/yGg
+        qf8Sz4D/ELx1/zWzgP9ogniJAAAAAAAAAACOrKGRNq9+/y24f/8uv4T/aczD/zaulP8z3Jb/NeKa/z3M
+        rP9It7j/L9iS/yrKh/9Iv47/a4N6hgAAAAAAAAAAhKucg1yihv85rn7/Lbl//0HFlf+KxtP/PLac/zu3
+        n/9itNX/ONGc/zXalf86zJD/ecSm/2yVhXsAAAAAAAAAAGiylRCAs6JjlaujnoSnmvlBsoT/Q8iV/3rY
+        wf9j0MD/ONKc/0LSl/+Mxa/+s8jBtIrDsmplupkOAAAAAAAAAAAAAAAAAAAAAAAAAABuuKESmrCpuVaw
+        jP8wxoj/Mc+N/1nHmv+uwLrJb8KpJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+        AACTtauBlKyj9pawp/iavLKRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+B8AAPAPAADgBwAA4AMAAMAD
+        AADAAwAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAIABAADwDwAA/D8AAA==
+</value>
+  </data>
+</root>
\ No newline at end of file
diff --git a/Axantum.AxCrypt/app.config b/Axantum.AxCrypt/app.config
new file mode 100644
index 0000000..dee8667
--- /dev/null
+++ b/Axantum.AxCrypt/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<configuration>
+    <configSections>
+    </configSections>
+    <startup>
+        
+    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup>
+    <appSettings>
+        <add key="LocalizedPerfCounter" value="true"/>
+    </appSettings>
+</configuration>
diff --git a/Axantum.AxCrypt/resources/DocumentsLibrary.ico b/Axantum.AxCrypt/resources/DocumentsLibrary.ico
new file mode 100644
index 0000000..87cd906
Binary files /dev/null and b/Axantum.AxCrypt/resources/DocumentsLibrary.ico differ
diff --git a/Axantum.AxCrypt/resources/DropBox.ico b/Axantum.AxCrypt/resources/DropBox.ico
new file mode 100644
index 0000000..787e9a9
Binary files /dev/null and b/Axantum.AxCrypt/resources/DropBox.ico differ
diff --git a/Axantum.AxCrypt/resources/GoogleDrive.ico b/Axantum.AxCrypt/resources/GoogleDrive.ico
new file mode 100644
index 0000000..c3aad5b
Binary files /dev/null and b/Axantum.AxCrypt/resources/GoogleDrive.ico differ
diff --git a/Axantum.AxCrypt/resources/SkyDrive.ico b/Axantum.AxCrypt/resources/SkyDrive.ico
new file mode 100644
index 0000000..3389ea2
Binary files /dev/null and b/Axantum.AxCrypt/resources/SkyDrive.ico differ
diff --git a/Axantum.AxCrypt/resources/activefilegreen16.png b/Axantum.AxCrypt/resources/activefilegreen16.png
new file mode 100644
index 0000000..ecb4526
Binary files /dev/null and b/Axantum.AxCrypt/resources/activefilegreen16.png differ
diff --git a/Axantum.AxCrypt/resources/activefileknownkeygreen16.png b/Axantum.AxCrypt/resources/activefileknownkeygreen16.png
new file mode 100644
index 0000000..31410c0
Binary files /dev/null and b/Axantum.AxCrypt/resources/activefileknownkeygreen16.png differ
diff --git a/Axantum.AxCrypt/resources/axcrypticon.ico b/Axantum.AxCrypt/resources/axcrypticon.ico
new file mode 100644
index 0000000..f2e5c7f
Binary files /dev/null and b/Axantum.AxCrypt/resources/axcrypticon.ico differ
diff --git a/Axantum.AxCrypt/resources/axcrypticon128.png b/Axantum.AxCrypt/resources/axcrypticon128.png
new file mode 100644
index 0000000..2429025
Binary files /dev/null and b/Axantum.AxCrypt/resources/axcrypticon128.png differ
diff --git a/Axantum.AxCrypt/resources/closeremovestandbygreen32.png b/Axantum.AxCrypt/resources/closeremovestandbygreen32.png
new file mode 100644
index 0000000..68612dd
Binary files /dev/null and b/Axantum.AxCrypt/resources/closeremovestandbygreen32.png differ
diff --git a/Axantum.AxCrypt/resources/closeremovestandbyred32.png b/Axantum.AxCrypt/resources/closeremovestandbyred32.png
new file mode 100644
index 0000000..a44e304
Binary files /dev/null and b/Axantum.AxCrypt/resources/closeremovestandbyred32.png differ
diff --git a/Axantum.AxCrypt/resources/decryptedfilered16.png b/Axantum.AxCrypt/resources/decryptedfilered16.png
new file mode 100644
index 0000000..52f03cf
Binary files /dev/null and b/Axantum.AxCrypt/resources/decryptedfilered16.png differ
diff --git a/Axantum.AxCrypt/resources/decryptedunknownkeyfilered16.png b/Axantum.AxCrypt/resources/decryptedunknownkeyfilered16.png
new file mode 100644
index 0000000..763b808
Binary files /dev/null and b/Axantum.AxCrypt/resources/decryptedunknownkeyfilered16.png differ
diff --git a/Axantum.AxCrypt/resources/decryptlockopen32.png b/Axantum.AxCrypt/resources/decryptlockopen32.png
new file mode 100644
index 0000000..d1a326a
Binary files /dev/null and b/Axantum.AxCrypt/resources/decryptlockopen32.png differ
diff --git a/Axantum.AxCrypt/resources/encryptionkeygreen32.png b/Axantum.AxCrypt/resources/encryptionkeygreen32.png
new file mode 100644
index 0000000..28ff49b
Binary files /dev/null and b/Axantum.AxCrypt/resources/encryptionkeygreen32.png differ
diff --git a/Axantum.AxCrypt/resources/encryptionkeyred32.png b/Axantum.AxCrypt/resources/encryptionkeyred32.png
new file mode 100644
index 0000000..9ce5260
Binary files /dev/null and b/Axantum.AxCrypt/resources/encryptionkeyred32.png differ
diff --git a/Axantum.AxCrypt/resources/encryptlock32.png b/Axantum.AxCrypt/resources/encryptlock32.png
new file mode 100644
index 0000000..84a60b1
Binary files /dev/null and b/Axantum.AxCrypt/resources/encryptlock32.png differ
diff --git a/Axantum.AxCrypt/resources/exclamationgreen16.png b/Axantum.AxCrypt/resources/exclamationgreen16.png
new file mode 100644
index 0000000..bc56f90
Binary files /dev/null and b/Axantum.AxCrypt/resources/exclamationgreen16.png differ
diff --git a/Axantum.AxCrypt/resources/exclamationgreen32.png b/Axantum.AxCrypt/resources/exclamationgreen32.png
new file mode 100644
index 0000000..da7d6e5
Binary files /dev/null and b/Axantum.AxCrypt/resources/exclamationgreen32.png differ
diff --git a/Axantum.AxCrypt/resources/fileknownkeygreen16.png b/Axantum.AxCrypt/resources/fileknownkeygreen16.png
new file mode 100644
index 0000000..31410c0
Binary files /dev/null and b/Axantum.AxCrypt/resources/fileknownkeygreen16.png differ
diff --git a/Axantum.AxCrypt/resources/helpquestiongreen32.png b/Axantum.AxCrypt/resources/helpquestiongreen32.png
new file mode 100644
index 0000000..304613f
Binary files /dev/null and b/Axantum.AxCrypt/resources/helpquestiongreen32.png differ
diff --git a/Axantum.AxCrypt/resources/inactivefilegreen16.png b/Axantum.AxCrypt/resources/inactivefilegreen16.png
new file mode 100644
index 0000000..b957851
Binary files /dev/null and b/Axantum.AxCrypt/resources/inactivefilegreen16.png differ
diff --git a/Axantum.AxCrypt/resources/opendocument32.png b/Axantum.AxCrypt/resources/opendocument32.png
new file mode 100644
index 0000000..fc6a492
Binary files /dev/null and b/Axantum.AxCrypt/resources/opendocument32.png differ
diff --git a/Axantum.AxCrypt/resources/refreshgreen.png b/Axantum.AxCrypt/resources/refreshgreen.png
new file mode 100644
index 0000000..94e1707
Binary files /dev/null and b/Axantum.AxCrypt/resources/refreshgreen.png differ
diff --git a/Axantum.AxCrypt/resources/refreshred.png b/Axantum.AxCrypt/resources/refreshred.png
new file mode 100644
index 0000000..05a0938
Binary files /dev/null and b/Axantum.AxCrypt/resources/refreshred.png differ
diff --git a/Axantum.AxCrypt/resources/trashred16.png b/Axantum.AxCrypt/resources/trashred16.png
new file mode 100644
index 0000000..2d56344
Binary files /dev/null and b/Axantum.AxCrypt/resources/trashred16.png differ
diff --git a/BouncyCastle.AxCrypt/AxantumStrongName.pfx b/BouncyCastle.AxCrypt/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/BouncyCastle.AxCrypt/AxantumStrongName.pfx differ
diff --git a/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.csproj b/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.csproj
new file mode 100644
index 0000000..240f37e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.csproj
@@ -0,0 +1,1370 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{3680C939-B21F-4444-B646-42FB4B29A786}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>BouncyCastle.AxCrypt</RootNamespace>
+    <AssemblyName>BouncyCastle.AxCrypt</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;SILVERLIGHT;PCL</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <NoWarn>618</NoWarn>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE;SILVERLIGHT;PCL</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+    <NoWarn>618</NoWarn>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .NET Framework is automatically included -->
+    <None Include="AxantumStrongName.pfx" />
+    <None Include="NBuild.build" />
+    <None Include="testcfg.nunit" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="bzip2\src\BZip2Constants.cs" />
+    <Compile Include="bzip2\src\CBZip2InputStream.cs" />
+    <Compile Include="bzip2\src\CBZip2OutputStream.cs" />
+    <Compile Include="bzip2\src\CRC.cs" />
+    <Compile Include="src\asn1\Asn1Encodable.cs" />
+    <Compile Include="src\asn1\Asn1EncodableVector.cs" />
+    <Compile Include="src\asn1\Asn1Exception.cs" />
+    <Compile Include="src\asn1\ASN1Generator.cs" />
+    <Compile Include="src\asn1\Asn1InputStream.cs" />
+    <Compile Include="src\asn1\Asn1Null.cs" />
+    <Compile Include="src\asn1\Asn1Object.cs" />
+    <Compile Include="src\asn1\Asn1OctetString.cs" />
+    <Compile Include="src\asn1\ASN1OctetStringParser.cs" />
+    <Compile Include="src\asn1\Asn1OutputStream.cs" />
+    <Compile Include="src\asn1\Asn1ParsingException.cs" />
+    <Compile Include="src\asn1\Asn1Sequence.cs" />
+    <Compile Include="src\asn1\ASN1SequenceParser.cs" />
+    <Compile Include="src\asn1\Asn1Set.cs" />
+    <Compile Include="src\asn1\ASN1SetParser.cs" />
+    <Compile Include="src\asn1\ASN1StreamParser.cs" />
+    <Compile Include="src\asn1\Asn1TaggedObject.cs" />
+    <Compile Include="src\asn1\ASN1TaggedObjectParser.cs" />
+    <Compile Include="src\asn1\Asn1Tags.cs" />
+    <Compile Include="src\asn1\bc\BCObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\BerApplicationSpecific.cs" />
+    <Compile Include="src\asn1\BerApplicationSpecificParser.cs" />
+    <Compile Include="src\asn1\BERGenerator.cs" />
+    <Compile Include="src\asn1\BerNull.cs" />
+    <Compile Include="src\asn1\BerOctetString.cs" />
+    <Compile Include="src\asn1\BEROctetStringGenerator.cs" />
+    <Compile Include="src\asn1\BEROctetStringParser.cs" />
+    <Compile Include="src\asn1\BerOutputStream.cs" />
+    <Compile Include="src\asn1\BerSequence.cs" />
+    <Compile Include="src\asn1\BERSequenceGenerator.cs" />
+    <Compile Include="src\asn1\BERSequenceParser.cs" />
+    <Compile Include="src\asn1\BerSet.cs" />
+    <Compile Include="src\asn1\BERSetGenerator.cs" />
+    <Compile Include="src\asn1\BERSetParser.cs" />
+    <Compile Include="src\asn1\BerTaggedObject.cs" />
+    <Compile Include="src\asn1\BERTaggedObjectParser.cs" />
+    <Compile Include="src\asn1\cmp\CAKeyUpdAnnContent.cs" />
+    <Compile Include="src\asn1\cmp\CertConfirmContent.cs" />
+    <Compile Include="src\asn1\cmp\CertifiedKeyPair.cs" />
+    <Compile Include="src\asn1\cmp\CertOrEncCert.cs" />
+    <Compile Include="src\asn1\cmp\CertRepMessage.cs" />
+    <Compile Include="src\asn1\cmp\CertResponse.cs" />
+    <Compile Include="src\asn1\cmp\CertStatus.cs" />
+    <Compile Include="src\asn1\cmp\Challenge.cs" />
+    <Compile Include="src\asn1\cmp\CmpCertificate.cs" />
+    <Compile Include="src\asn1\cmp\CmpObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\cmp\CrlAnnContent.cs" />
+    <Compile Include="src\asn1\cmp\ErrorMsgContent.cs" />
+    <Compile Include="src\asn1\cmp\GenMsgContent.cs" />
+    <Compile Include="src\asn1\cmp\GenRepContent.cs" />
+    <Compile Include="src\asn1\cmp\InfoTypeAndValue.cs" />
+    <Compile Include="src\asn1\cmp\KeyRecRepContent.cs" />
+    <Compile Include="src\asn1\cmp\OobCertHash.cs" />
+    <Compile Include="src\asn1\cmp\PbmParameter.cs" />
+    <Compile Include="src\asn1\cmp\PKIBody.cs" />
+    <Compile Include="src\asn1\cmp\PKIConfirmContent.cs" />
+    <Compile Include="src\asn1\cmp\PKIFailureInfo.cs" />
+    <Compile Include="src\asn1\cmp\PKIFreeText.cs" />
+    <Compile Include="src\asn1\cmp\PKIHeader.cs" />
+    <Compile Include="src\asn1\cmp\PKIHeaderBuilder.cs" />
+    <Compile Include="src\asn1\cmp\PKIMessage.cs" />
+    <Compile Include="src\asn1\cmp\PKIMessages.cs" />
+    <Compile Include="src\asn1\cmp\PKIStatus.cs" />
+    <Compile Include="src\asn1\cmp\PKIStatusInfo.cs" />
+    <Compile Include="src\asn1\cmp\PollRepContent.cs" />
+    <Compile Include="src\asn1\cmp\PollReqContent.cs" />
+    <Compile Include="src\asn1\cmp\PopoDecKeyChallContent.cs" />
+    <Compile Include="src\asn1\cmp\PopoDecKeyRespContent.cs" />
+    <Compile Include="src\asn1\cmp\ProtectedPart.cs" />
+    <Compile Include="src\asn1\cmp\RevAnnContent.cs" />
+    <Compile Include="src\asn1\cmp\RevDetails.cs" />
+    <Compile Include="src\asn1\cmp\RevRepContent.cs" />
+    <Compile Include="src\asn1\cmp\RevRepContentBuilder.cs" />
+    <Compile Include="src\asn1\cmp\RevReqContent.cs" />
+    <Compile Include="src\asn1\cms\Attribute.cs" />
+    <Compile Include="src\asn1\cms\Attributes.cs" />
+    <Compile Include="src\asn1\cms\AttributeTable.cs" />
+    <Compile Include="src\asn1\cms\AuthenticatedData.cs" />
+    <Compile Include="src\asn1\cms\AuthenticatedDataParser.cs" />
+    <Compile Include="src\asn1\cms\AuthEnvelopedData.cs" />
+    <Compile Include="src\asn1\cms\AuthEnvelopedDataParser.cs" />
+    <Compile Include="src\asn1\cms\CMSAttributes.cs" />
+    <Compile Include="src\asn1\cms\CMSObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\cms\CompressedData.cs" />
+    <Compile Include="src\asn1\cms\CompressedDataParser.cs" />
+    <Compile Include="src\asn1\cms\ContentInfo.cs" />
+    <Compile Include="src\asn1\cms\ContentInfoParser.cs" />
+    <Compile Include="src\asn1\cms\ecc\MQVuserKeyingMaterial.cs" />
+    <Compile Include="src\asn1\cms\EncryptedContentInfo.cs" />
+    <Compile Include="src\asn1\cms\EncryptedContentInfoParser.cs" />
+    <Compile Include="src\asn1\cms\EncryptedData.cs" />
+    <Compile Include="src\asn1\cms\EnvelopedData.cs" />
+    <Compile Include="src\asn1\cms\EnvelopedDataParser.cs" />
+    <Compile Include="src\asn1\cms\Evidence.cs" />
+    <Compile Include="src\asn1\cms\IssuerAndSerialNumber.cs" />
+    <Compile Include="src\asn1\cms\KEKIdentifier.cs" />
+    <Compile Include="src\asn1\cms\KEKRecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\KeyAgreeRecipientIdentifier.cs" />
+    <Compile Include="src\asn1\cms\KeyAgreeRecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\KeyTransRecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\MetaData.cs" />
+    <Compile Include="src\asn1\cms\OriginatorIdentifierOrKey.cs" />
+    <Compile Include="src\asn1\cms\OriginatorInfo.cs" />
+    <Compile Include="src\asn1\cms\OriginatorPublicKey.cs" />
+    <Compile Include="src\asn1\cms\OtherKeyAttribute.cs" />
+    <Compile Include="src\asn1\cms\OtherRecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\OtherRevocationInfoFormat.cs" />
+    <Compile Include="src\asn1\cms\PasswordRecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\RecipientEncryptedKey.cs" />
+    <Compile Include="src\asn1\cms\RecipientIdentifier.cs" />
+    <Compile Include="src\asn1\cms\RecipientInfo.cs" />
+    <Compile Include="src\asn1\cms\RecipientKeyIdentifier.cs" />
+    <Compile Include="src\asn1\cms\SCVPReqRes.cs" />
+    <Compile Include="src\asn1\cms\SignedData.cs" />
+    <Compile Include="src\asn1\cms\SignedDataParser.cs" />
+    <Compile Include="src\asn1\cms\SignerIdentifier.cs" />
+    <Compile Include="src\asn1\cms\SignerInfo.cs" />
+    <Compile Include="src\asn1\cms\Time.cs" />
+    <Compile Include="src\asn1\cms\TimeStampAndCRL.cs" />
+    <Compile Include="src\asn1\cms\TimeStampedData.cs" />
+    <Compile Include="src\asn1\cms\TimeStampedDataParser.cs" />
+    <Compile Include="src\asn1\cms\TimeStampTokenEvidence.cs" />
+    <Compile Include="src\asn1\ConstructedOctetStream.cs" />
+    <Compile Include="src\asn1\crmf\AttributeTypeAndValue.cs" />
+    <Compile Include="src\asn1\crmf\CertId.cs" />
+    <Compile Include="src\asn1\crmf\CertReqMessages.cs" />
+    <Compile Include="src\asn1\crmf\CertReqMsg.cs" />
+    <Compile Include="src\asn1\crmf\CertRequest.cs" />
+    <Compile Include="src\asn1\crmf\CertTemplate.cs" />
+    <Compile Include="src\asn1\crmf\CertTemplateBuilder.cs" />
+    <Compile Include="src\asn1\crmf\Controls.cs" />
+    <Compile Include="src\asn1\crmf\CrmfObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\crmf\EncKeyWithID.cs" />
+    <Compile Include="src\asn1\crmf\EncryptedKey.cs" />
+    <Compile Include="src\asn1\crmf\EncryptedValue.cs" />
+    <Compile Include="src\asn1\crmf\OptionalValidity.cs" />
+    <Compile Include="src\asn1\crmf\PKIArchiveOptions.cs" />
+    <Compile Include="src\asn1\crmf\PKIPublicationInfo.cs" />
+    <Compile Include="src\asn1\crmf\PKMacValue.cs" />
+    <Compile Include="src\asn1\crmf\PopoPrivKey.cs" />
+    <Compile Include="src\asn1\crmf\PopoSigningKey.cs" />
+    <Compile Include="src\asn1\crmf\PopoSigningKeyInput.cs" />
+    <Compile Include="src\asn1\crmf\ProofOfPossession.cs" />
+    <Compile Include="src\asn1\crmf\SinglePubInfo.cs" />
+    <Compile Include="src\asn1\crmf\SubsequentMessage.cs" />
+    <Compile Include="src\asn1\cryptopro\CryptoProObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\cryptopro\ECGOST3410NamedCurves.cs" />
+    <Compile Include="src\asn1\cryptopro\ECGOST3410ParamSetParameters.cs" />
+    <Compile Include="src\asn1\cryptopro\GOST28147Parameters.cs" />
+    <Compile Include="src\asn1\cryptopro\GOST3410NamedParameters.cs" />
+    <Compile Include="src\asn1\cryptopro\GOST3410ParamSetParameters.cs" />
+    <Compile Include="src\asn1\cryptopro\GOST3410PublicKeyAlgParameters.cs" />
+    <Compile Include="src\asn1\DefiniteLengthInputStream.cs" />
+    <Compile Include="src\asn1\DerApplicationSpecific.cs" />
+    <Compile Include="src\asn1\DerBitString.cs" />
+    <Compile Include="src\asn1\DerBMPString.cs" />
+    <Compile Include="src\asn1\DerBoolean.cs" />
+    <Compile Include="src\asn1\DerEnumerated.cs" />
+    <Compile Include="src\asn1\DERExternal.cs" />
+    <Compile Include="src\asn1\DERExternalParser.cs" />
+    <Compile Include="src\asn1\DerGeneralizedTime.cs" />
+    <Compile Include="src\asn1\DerGeneralString.cs" />
+    <Compile Include="src\asn1\DERGenerator.cs" />
+    <Compile Include="src\asn1\DerIA5String.cs" />
+    <Compile Include="src\asn1\DerInteger.cs" />
+    <Compile Include="src\asn1\DerNull.cs" />
+    <Compile Include="src\asn1\DerNumericString.cs" />
+    <Compile Include="src\asn1\DerObjectIdentifier.cs" />
+    <Compile Include="src\asn1\DerOctetString.cs" />
+    <Compile Include="src\asn1\DEROctetStringParser.cs" />
+    <Compile Include="src\asn1\DerOutputStream.cs" />
+    <Compile Include="src\asn1\DerPrintableString.cs" />
+    <Compile Include="src\asn1\DerSequence.cs" />
+    <Compile Include="src\asn1\DERSequenceGenerator.cs" />
+    <Compile Include="src\asn1\DERSequenceParser.cs" />
+    <Compile Include="src\asn1\DerSet.cs" />
+    <Compile Include="src\asn1\DERSetGenerator.cs" />
+    <Compile Include="src\asn1\DERSetParser.cs" />
+    <Compile Include="src\asn1\DerStringBase.cs" />
+    <Compile Include="src\asn1\DerT61String.cs" />
+    <Compile Include="src\asn1\DerTaggedObject.cs" />
+    <Compile Include="src\asn1\DerUniversalString.cs" />
+    <Compile Include="src\asn1\DerUnknownTag.cs" />
+    <Compile Include="src\asn1\DerUTCTime.cs" />
+    <Compile Include="src\asn1\DerUTF8String.cs" />
+    <Compile Include="src\asn1\DerVisibleString.cs" />
+    <Compile Include="src\asn1\eac\EACObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\esf\CertificateValues.cs" />
+    <Compile Include="src\asn1\esf\CommitmentTypeIdentifier.cs" />
+    <Compile Include="src\asn1\esf\CommitmentTypeIndication.cs" />
+    <Compile Include="src\asn1\esf\CommitmentTypeQualifier.cs" />
+    <Compile Include="src\asn1\esf\CompleteCertificateRefs.cs" />
+    <Compile Include="src\asn1\esf\CompleteRevocationRefs.cs" />
+    <Compile Include="src\asn1\esf\CrlIdentifier.cs" />
+    <Compile Include="src\asn1\esf\CrlListID.cs" />
+    <Compile Include="src\asn1\esf\CrlOcspRef.cs" />
+    <Compile Include="src\asn1\esf\CrlValidatedID.cs" />
+    <Compile Include="src\asn1\esf\ESFAttributes.cs" />
+    <Compile Include="src\asn1\esf\OcspIdentifier.cs" />
+    <Compile Include="src\asn1\esf\OcspListID.cs" />
+    <Compile Include="src\asn1\esf\OcspResponsesID.cs" />
+    <Compile Include="src\asn1\esf\OtherCertID.cs" />
+    <Compile Include="src\asn1\esf\OtherHash.cs" />
+    <Compile Include="src\asn1\esf\OtherHashAlgAndValue.cs" />
+    <Compile Include="src\asn1\esf\OtherRevRefs.cs" />
+    <Compile Include="src\asn1\esf\OtherRevVals.cs" />
+    <Compile Include="src\asn1\esf\OtherSigningCertificate.cs" />
+    <Compile Include="src\asn1\esf\RevocationValues.cs" />
+    <Compile Include="src\asn1\esf\SignaturePolicyId.cs" />
+    <Compile Include="src\asn1\esf\SignaturePolicyIdentifier.cs" />
+    <Compile Include="src\asn1\esf\SignerAttribute.cs" />
+    <Compile Include="src\asn1\esf\SignerLocation.cs" />
+    <Compile Include="src\asn1\esf\SigPolicyQualifierInfo.cs" />
+    <Compile Include="src\asn1\ess\ContentHints.cs" />
+    <Compile Include="src\asn1\ess\ContentIdentifier.cs" />
+    <Compile Include="src\asn1\ess\ESSCertID.cs" />
+    <Compile Include="src\asn1\ess\ESSCertIDv2.cs" />
+    <Compile Include="src\asn1\ess\OtherCertID.cs" />
+    <Compile Include="src\asn1\ess\OtherSigningCertificate.cs" />
+    <Compile Include="src\asn1\ess\SigningCertificate.cs" />
+    <Compile Include="src\asn1\ess\SigningCertificateV2.cs" />
+    <Compile Include="src\asn1\gnu\GNUObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\iana\IANAObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\IAsn1ApplicationSpecificParser.cs" />
+    <Compile Include="src\asn1\IAsn1Choice.cs" />
+    <Compile Include="src\asn1\IAsn1Convertible.cs" />
+    <Compile Include="src\asn1\IAsn1String.cs" />
+    <Compile Include="src\asn1\icao\CscaMasterList.cs" />
+    <Compile Include="src\asn1\icao\DataGroupHash.cs" />
+    <Compile Include="src\asn1\icao\ICAOObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\icao\LDSSecurityObject.cs" />
+    <Compile Include="src\asn1\icao\LDSVersionInfo.cs" />
+    <Compile Include="src\asn1\IndefiniteLengthInputStream.cs" />
+    <Compile Include="src\asn1\isismtt\ISISMTTObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\isismtt\ocsp\CertHash.cs" />
+    <Compile Include="src\asn1\isismtt\ocsp\RequestedCertificate.cs" />
+    <Compile Include="src\asn1\isismtt\x509\AdditionalInformationSyntax.cs" />
+    <Compile Include="src\asn1\isismtt\x509\Admissions.cs" />
+    <Compile Include="src\asn1\isismtt\x509\AdmissionSyntax.cs" />
+    <Compile Include="src\asn1\isismtt\x509\DeclarationOfMajority.cs" />
+    <Compile Include="src\asn1\isismtt\x509\MonetaryLimit.cs" />
+    <Compile Include="src\asn1\isismtt\x509\NamingAuthority.cs" />
+    <Compile Include="src\asn1\isismtt\x509\ProcurationSyntax.cs" />
+    <Compile Include="src\asn1\isismtt\x509\ProfessionInfo.cs" />
+    <Compile Include="src\asn1\isismtt\x509\Restriction.cs" />
+    <Compile Include="src\asn1\kisa\KISAObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\LazyASN1InputStream.cs" />
+    <Compile Include="src\asn1\LazyDERSequence.cs" />
+    <Compile Include="src\asn1\LazyDERSet.cs" />
+    <Compile Include="src\asn1\LimitedInputStream.cs" />
+    <Compile Include="src\asn1\microsoft\MicrosoftObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\misc\CAST5CBCParameters.cs" />
+    <Compile Include="src\asn1\misc\IDEACBCPar.cs" />
+    <Compile Include="src\asn1\misc\MiscObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\misc\NetscapeCertType.cs" />
+    <Compile Include="src\asn1\misc\NetscapeRevocationURL.cs" />
+    <Compile Include="src\asn1\misc\VerisignCzagExtension.cs" />
+    <Compile Include="src\asn1\mozilla\PublicKeyAndChallenge.cs" />
+    <Compile Include="src\asn1\nist\NISTNamedCurves.cs" />
+    <Compile Include="src\asn1\nist\NISTObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\ntt\NTTObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\ocsp\BasicOCSPResponse.cs" />
+    <Compile Include="src\asn1\ocsp\CertID.cs" />
+    <Compile Include="src\asn1\ocsp\CertStatus.cs" />
+    <Compile Include="src\asn1\ocsp\CrlID.cs" />
+    <Compile Include="src\asn1\ocsp\OCSPObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\ocsp\OCSPRequest.cs" />
+    <Compile Include="src\asn1\ocsp\OCSPResponse.cs" />
+    <Compile Include="src\asn1\ocsp\OCSPResponseStatus.cs" />
+    <Compile Include="src\asn1\ocsp\Request.cs" />
+    <Compile Include="src\asn1\ocsp\ResponderID.cs" />
+    <Compile Include="src\asn1\ocsp\ResponseBytes.cs" />
+    <Compile Include="src\asn1\ocsp\ResponseData.cs" />
+    <Compile Include="src\asn1\ocsp\RevokedInfo.cs" />
+    <Compile Include="src\asn1\ocsp\ServiceLocator.cs" />
+    <Compile Include="src\asn1\ocsp\Signature.cs" />
+    <Compile Include="src\asn1\ocsp\SingleResponse.cs" />
+    <Compile Include="src\asn1\ocsp\TBSRequest.cs" />
+    <Compile Include="src\asn1\OidTokenizer.cs" />
+    <Compile Include="src\asn1\oiw\ElGamalParameter.cs" />
+    <Compile Include="src\asn1\oiw\OIWObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\pkcs\Attribute.cs" />
+    <Compile Include="src\asn1\pkcs\AuthenticatedSafe.cs" />
+    <Compile Include="src\asn1\pkcs\CertBag.cs" />
+    <Compile Include="src\asn1\pkcs\CertificationRequest.cs" />
+    <Compile Include="src\asn1\pkcs\CertificationRequestInfo.cs" />
+    <Compile Include="src\asn1\pkcs\ContentInfo.cs" />
+    <Compile Include="src\asn1\pkcs\DHParameter.cs" />
+    <Compile Include="src\asn1\pkcs\EncryptedData.cs" />
+    <Compile Include="src\asn1\pkcs\EncryptedPrivateKeyInfo.cs" />
+    <Compile Include="src\asn1\pkcs\EncryptionScheme.cs" />
+    <Compile Include="src\asn1\pkcs\IssuerAndSerialNumber.cs" />
+    <Compile Include="src\asn1\pkcs\KeyDerivationFunc.cs" />
+    <Compile Include="src\asn1\pkcs\MacData.cs" />
+    <Compile Include="src\asn1\pkcs\PBEParameter.cs" />
+    <Compile Include="src\asn1\pkcs\PBES2Parameters.cs" />
+    <Compile Include="src\asn1\pkcs\PBKDF2Params.cs" />
+    <Compile Include="src\asn1\pkcs\Pfx.cs" />
+    <Compile Include="src\asn1\pkcs\PKCS12PBEParams.cs" />
+    <Compile Include="src\asn1\pkcs\PKCSObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\pkcs\PrivateKeyInfo.cs" />
+    <Compile Include="src\asn1\pkcs\RC2CBCParameter.cs" />
+    <Compile Include="src\asn1\pkcs\RSAESOAEPparams.cs" />
+    <Compile Include="src\asn1\pkcs\RSAPrivateKeyStructure.cs" />
+    <Compile Include="src\asn1\pkcs\RSASSAPSSparams.cs" />
+    <Compile Include="src\asn1\pkcs\SafeBag.cs" />
+    <Compile Include="src\asn1\pkcs\SignedData.cs" />
+    <Compile Include="src\asn1\pkcs\SignerInfo.cs" />
+    <Compile Include="src\asn1\sec\ECPrivateKeyStructure.cs" />
+    <Compile Include="src\asn1\sec\SECNamedCurves.cs" />
+    <Compile Include="src\asn1\sec\SECObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\smime\SMIMEAttributes.cs" />
+    <Compile Include="src\asn1\smime\SMIMECapabilities.cs" />
+    <Compile Include="src\asn1\smime\SMIMECapabilitiesAttribute.cs" />
+    <Compile Include="src\asn1\smime\SMIMECapability.cs" />
+    <Compile Include="src\asn1\smime\SMIMECapabilityVector.cs" />
+    <Compile Include="src\asn1\smime\SMIMEEncryptionKeyPreferenceAttribute.cs" />
+    <Compile Include="src\asn1\teletrust\TeleTrusTNamedCurves.cs" />
+    <Compile Include="src\asn1\teletrust\TeleTrusTObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\tsp\Accuracy.cs" />
+    <Compile Include="src\asn1\tsp\MessageImprint.cs" />
+    <Compile Include="src\asn1\tsp\TimeStampReq.cs" />
+    <Compile Include="src\asn1\tsp\TimeStampResp.cs" />
+    <Compile Include="src\asn1\tsp\TSTInfo.cs" />
+    <Compile Include="src\asn1\util\Asn1Dump.cs" />
+    <Compile Include="src\asn1\util\Dump.cs" />
+    <Compile Include="src\asn1\util\FilterStream.cs" />
+    <Compile Include="src\asn1\x500\DirectoryString.cs" />
+    <Compile Include="src\asn1\x509\AccessDescription.cs" />
+    <Compile Include="src\asn1\x509\AlgorithmIdentifier.cs" />
+    <Compile Include="src\asn1\x509\AttCertIssuer.cs" />
+    <Compile Include="src\asn1\x509\AttCertValidityPeriod.cs" />
+    <Compile Include="src\asn1\x509\Attribute.cs" />
+    <Compile Include="src\asn1\x509\AttributeCertificate.cs" />
+    <Compile Include="src\asn1\x509\AttributeCertificateInfo.cs" />
+    <Compile Include="src\asn1\x509\AttributeTable.cs" />
+    <Compile Include="src\asn1\x509\AuthorityInformationAccess.cs" />
+    <Compile Include="src\asn1\x509\AuthorityKeyIdentifier.cs" />
+    <Compile Include="src\asn1\x509\BasicConstraints.cs" />
+    <Compile Include="src\asn1\x509\CertificateList.cs" />
+    <Compile Include="src\asn1\x509\CertificatePair.cs" />
+    <Compile Include="src\asn1\x509\CertificatePolicies.cs" />
+    <Compile Include="src\asn1\x509\CertPolicyId.cs" />
+    <Compile Include="src\asn1\x509\CRLDistPoint.cs" />
+    <Compile Include="src\asn1\x509\CRLNumber.cs" />
+    <Compile Include="src\asn1\x509\CRLReason.cs" />
+    <Compile Include="src\asn1\x509\DigestInfo.cs" />
+    <Compile Include="src\asn1\x509\DisplayText.cs" />
+    <Compile Include="src\asn1\x509\DistributionPoint.cs" />
+    <Compile Include="src\asn1\x509\DistributionPointName.cs" />
+    <Compile Include="src\asn1\x509\DSAParameter.cs" />
+    <Compile Include="src\asn1\x509\ExtendedKeyUsage.cs" />
+    <Compile Include="src\asn1\x509\GeneralName.cs" />
+    <Compile Include="src\asn1\x509\GeneralNames.cs" />
+    <Compile Include="src\asn1\x509\GeneralSubtree.cs" />
+    <Compile Include="src\asn1\x509\Holder.cs" />
+    <Compile Include="src\asn1\x509\IetfAttrSyntax.cs" />
+    <Compile Include="src\asn1\x509\IssuerSerial.cs" />
+    <Compile Include="src\asn1\x509\IssuingDistributionPoint.cs" />
+    <Compile Include="src\asn1\x509\KeyPurposeId.cs" />
+    <Compile Include="src\asn1\x509\KeyUsage.cs" />
+    <Compile Include="src\asn1\x509\NameConstraints.cs" />
+    <Compile Include="src\asn1\x509\NoticeReference.cs" />
+    <Compile Include="src\asn1\x509\ObjectDigestInfo.cs" />
+    <Compile Include="src\asn1\x509\PolicyInformation.cs" />
+    <Compile Include="src\asn1\x509\PolicyMappings.cs" />
+    <Compile Include="src\asn1\x509\PolicyQualifierId.cs" />
+    <Compile Include="src\asn1\x509\PolicyQualifierInfo.cs" />
+    <Compile Include="src\asn1\x509\PrivateKeyUsagePeriod.cs" />
+    <Compile Include="src\asn1\x509\qualified\BiometricData.cs" />
+    <Compile Include="src\asn1\x509\qualified\ETSIQCObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\x509\qualified\Iso4217CurrencyCode.cs" />
+    <Compile Include="src\asn1\x509\qualified\MonetaryValue.cs" />
+    <Compile Include="src\asn1\x509\qualified\QCStatement.cs" />
+    <Compile Include="src\asn1\x509\qualified\RFC3739QCObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\x509\qualified\SemanticsInformation.cs" />
+    <Compile Include="src\asn1\x509\qualified\TypeOfBiometricData.cs" />
+    <Compile Include="src\asn1\x509\ReasonFlags.cs" />
+    <Compile Include="src\asn1\x509\RoleSyntax.cs" />
+    <Compile Include="src\asn1\x509\RSAPublicKeyStructure.cs" />
+    <Compile Include="src\asn1\x509\sigi\NameOrPseudonym.cs" />
+    <Compile Include="src\asn1\x509\sigi\PersonalData.cs" />
+    <Compile Include="src\asn1\x509\sigi\SigIObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\x509\SubjectDirectoryAttributes.cs" />
+    <Compile Include="src\asn1\x509\SubjectKeyIdentifier.cs" />
+    <Compile Include="src\asn1\x509\SubjectPublicKeyInfo.cs" />
+    <Compile Include="src\asn1\x509\Target.cs" />
+    <Compile Include="src\asn1\x509\TargetInformation.cs" />
+    <Compile Include="src\asn1\x509\Targets.cs" />
+    <Compile Include="src\asn1\x509\TBSCertificateStructure.cs" />
+    <Compile Include="src\asn1\x509\TBSCertList.cs" />
+    <Compile Include="src\asn1\x509\Time.cs" />
+    <Compile Include="src\asn1\x509\UserNotice.cs" />
+    <Compile Include="src\asn1\x509\V1TBSCertificateGenerator.cs" />
+    <Compile Include="src\asn1\x509\V2AttributeCertificateInfoGenerator.cs" />
+    <Compile Include="src\asn1\x509\V2Form.cs" />
+    <Compile Include="src\asn1\x509\V2TBSCertListGenerator.cs" />
+    <Compile Include="src\asn1\x509\V3TBSCertificateGenerator.cs" />
+    <Compile Include="src\asn1\x509\X509Attributes.cs" />
+    <Compile Include="src\asn1\x509\X509CertificateStructure.cs" />
+    <Compile Include="src\asn1\x509\X509DefaultEntryConverter.cs" />
+    <Compile Include="src\asn1\x509\X509Extension.cs" />
+    <Compile Include="src\asn1\x509\X509Extensions.cs" />
+    <Compile Include="src\asn1\x509\X509ExtensionsGenerator.cs" />
+    <Compile Include="src\asn1\x509\X509Name.cs" />
+    <Compile Include="src\asn1\x509\X509NameEntryConverter.cs" />
+    <Compile Include="src\asn1\x509\X509NameTokenizer.cs" />
+    <Compile Include="src\asn1\x509\X509ObjectIdentifiers.cs" />
+    <Compile Include="src\asn1\x9\DHDomainParameters.cs" />
+    <Compile Include="src\asn1\x9\DHPublicKey.cs" />
+    <Compile Include="src\asn1\x9\DHValidationParms.cs" />
+    <Compile Include="src\asn1\x9\ECNamedCurveTable.cs" />
+    <Compile Include="src\asn1\x9\KeySpecificInfo.cs" />
+    <Compile Include="src\asn1\x9\OtherInfo.cs" />
+    <Compile Include="src\asn1\x9\X962NamedCurves.cs" />
+    <Compile Include="src\asn1\x9\X962Parameters.cs" />
+    <Compile Include="src\asn1\x9\X9Curve.cs" />
+    <Compile Include="src\asn1\x9\X9ECParameters.cs" />
+    <Compile Include="src\asn1\x9\X9ECParametersHolder.cs" />
+    <Compile Include="src\asn1\x9\X9ECPoint.cs" />
+    <Compile Include="src\asn1\x9\X9FieldElement.cs" />
+    <Compile Include="src\asn1\x9\X9FieldID.cs" />
+    <Compile Include="src\asn1\x9\X9IntegerConverter.cs" />
+    <Compile Include="src\asn1\x9\X9ObjectIdentifiers.cs" />
+    <Compile Include="src\AssemblyInfo.cs" />
+    <Compile Include="src\bcpg\ArmoredInputStream.cs" />
+    <Compile Include="src\bcpg\ArmoredOutputStream.cs" />
+    <Compile Include="src\bcpg\attr\ImageAttrib.cs" />
+    <Compile Include="src\bcpg\BcpgInputStream.cs" />
+    <Compile Include="src\bcpg\BcpgObject.cs" />
+    <Compile Include="src\bcpg\BcpgOutputStream.cs" />
+    <Compile Include="src\bcpg\CompressedDataPacket.cs" />
+    <Compile Include="src\bcpg\CompressionAlgorithmTags.cs" />
+    <Compile Include="src\bcpg\ContainedPacket.cs" />
+    <Compile Include="src\bcpg\Crc24.cs" />
+    <Compile Include="src\bcpg\DsaPublicBcpgKey.cs" />
+    <Compile Include="src\bcpg\DsaSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\ElGamalPublicBcpgKey.cs" />
+    <Compile Include="src\bcpg\ElGamalSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\ExperimentalPacket.cs" />
+    <Compile Include="src\bcpg\HashAlgorithmTags.cs" />
+    <Compile Include="src\bcpg\IBcpgKey.cs" />
+    <Compile Include="src\bcpg\InputStreamPacket.cs" />
+    <Compile Include="src\bcpg\LiteralDataPacket.cs" />
+    <Compile Include="src\bcpg\MarkerPacket.cs" />
+    <Compile Include="src\bcpg\ModDetectionCodePacket.cs" />
+    <Compile Include="src\bcpg\MPInteger.cs" />
+    <Compile Include="src\bcpg\OnePassSignaturePacket.cs" />
+    <Compile Include="src\bcpg\OutputStreamPacket.cs" />
+    <Compile Include="src\bcpg\Packet.cs" />
+    <Compile Include="src\bcpg\PacketTags.cs" />
+    <Compile Include="src\bcpg\PublicKeyAlgorithmTags.cs" />
+    <Compile Include="src\bcpg\PublicKeyEncSessionPacket.cs" />
+    <Compile Include="src\bcpg\PublicKeyPacket.cs" />
+    <Compile Include="src\bcpg\PublicSubkeyPacket.cs" />
+    <Compile Include="src\bcpg\RsaPublicBcpgKey.cs" />
+    <Compile Include="src\bcpg\RsaSecretBcpgKey.cs" />
+    <Compile Include="src\bcpg\S2k.cs" />
+    <Compile Include="src\bcpg\SecretKeyPacket.cs" />
+    <Compile Include="src\bcpg\SecretSubkeyPacket.cs" />
+    <Compile Include="src\bcpg\SignaturePacket.cs" />
+    <Compile Include="src\bcpg\SignatureSubpacket.cs" />
+    <Compile Include="src\bcpg\SignatureSubpacketsReader.cs" />
+    <Compile Include="src\bcpg\SignatureSubpacketTags.cs" />
+    <Compile Include="src\bcpg\sig\EmbeddedSignature.cs" />
+    <Compile Include="src\bcpg\sig\Exportable.cs" />
+    <Compile Include="src\bcpg\sig\IssuerKeyId.cs" />
+    <Compile Include="src\bcpg\sig\KeyExpirationTime.cs" />
+    <Compile Include="src\bcpg\sig\KeyFlags.cs" />
+    <Compile Include="src\bcpg\sig\NotationData.cs" />
+    <Compile Include="src\bcpg\sig\PreferredAlgorithms.cs" />
+    <Compile Include="src\bcpg\sig\PrimaryUserId.cs" />
+    <Compile Include="src\bcpg\sig\Revocable.cs" />
+    <Compile Include="src\bcpg\sig\RevocationKey.cs" />
+    <Compile Include="src\bcpg\sig\RevocationKeyTags.cs" />
+    <Compile Include="src\bcpg\sig\RevocationReason.cs" />
+    <Compile Include="src\bcpg\sig\RevocationReasonTags.cs" />
+    <Compile Include="src\bcpg\sig\SignatureCreationTime.cs" />
+    <Compile Include="src\bcpg\sig\SignatureExpirationTime.cs" />
+    <Compile Include="src\bcpg\sig\SignerUserId.cs" />
+    <Compile Include="src\bcpg\sig\TrustSignature.cs" />
+    <Compile Include="src\bcpg\SymmetricEncDataPacket.cs" />
+    <Compile Include="src\bcpg\SymmetricEncIntegrityPacket.cs" />
+    <Compile Include="src\bcpg\SymmetricKeyAlgorithmTags.cs" />
+    <Compile Include="src\bcpg\SymmetricKeyEncSessionPacket.cs" />
+    <Compile Include="src\bcpg\TrustPacket.cs" />
+    <Compile Include="src\bcpg\UserAttributePacket.cs" />
+    <Compile Include="src\bcpg\UserAttributeSubpacket.cs" />
+    <Compile Include="src\bcpg\UserAttributeSubpacketsReader.cs" />
+    <Compile Include="src\bcpg\UserAttributeSubpacketTags.cs" />
+    <Compile Include="src\bcpg\UserIdPacket.cs" />
+    <Compile Include="src\cms\BaseDigestCalculator.cs" />
+    <Compile Include="src\cms\CMSAttributeTableGenerationException.cs" />
+    <Compile Include="src\cms\CMSAttributeTableGenerator.cs" />
+    <Compile Include="src\cms\CMSAuthenticatedData.cs" />
+    <Compile Include="src\cms\CMSAuthenticatedDataGenerator.cs" />
+    <Compile Include="src\cms\CMSAuthenticatedDataParser.cs" />
+    <Compile Include="src\cms\CMSAuthenticatedDataStreamGenerator.cs" />
+    <Compile Include="src\cms\CMSAuthenticatedGenerator.cs" />
+    <Compile Include="src\cms\CMSAuthEnvelopedData.cs" />
+    <Compile Include="src\cms\CMSAuthEnvelopedGenerator.cs" />
+    <Compile Include="src\cms\CMSCompressedData.cs" />
+    <Compile Include="src\cms\CMSCompressedDataGenerator.cs" />
+    <Compile Include="src\cms\CMSCompressedDataParser.cs" />
+    <Compile Include="src\cms\CMSCompressedDataStreamGenerator.cs" />
+    <Compile Include="src\cms\CMSContentInfoParser.cs" />
+    <Compile Include="src\cms\CMSEnvelopedData.cs" />
+    <Compile Include="src\cms\CMSEnvelopedDataGenerator.cs" />
+    <Compile Include="src\cms\CMSEnvelopedDataParser.cs" />
+    <Compile Include="src\cms\CMSEnvelopedDataStreamGenerator.cs" />
+    <Compile Include="src\cms\CMSEnvelopedGenerator.cs" />
+    <Compile Include="src\cms\CMSEnvelopedHelper.cs" />
+    <Compile Include="src\cms\CMSException.cs" />
+    <Compile Include="src\cms\CMSPBEKey.cs" />
+    <Compile Include="src\cms\CMSProcessable.cs" />
+    <Compile Include="src\cms\CMSProcessableByteArray.cs" />
+    <Compile Include="src\cms\CMSProcessableFile.cs" />
+    <Compile Include="src\cms\CMSProcessableInputStream.cs" />
+    <Compile Include="src\cms\CMSReadable.cs" />
+    <Compile Include="src\cms\CMSSecureReadable.cs" />
+    <Compile Include="src\cms\CMSSignedData.cs" />
+    <Compile Include="src\cms\CMSSignedDataGenerator.cs" />
+    <Compile Include="src\cms\CMSSignedDataParser.cs" />
+    <Compile Include="src\cms\CMSSignedDataStreamGenerator.cs" />
+    <Compile Include="src\cms\CMSSignedGenerator.cs" />
+    <Compile Include="src\cms\CMSSignedHelper.cs" />
+    <Compile Include="src\cms\CMSStreamException.cs" />
+    <Compile Include="src\cms\CMSTypedStream.cs" />
+    <Compile Include="src\cms\CMSUtils.cs" />
+    <Compile Include="src\cms\CounterSignatureDigestCalculator.cs" />
+    <Compile Include="src\cms\DefaultAuthenticatedAttributeTableGenerator.cs" />
+    <Compile Include="src\cms\DefaultSignedAttributeTableGenerator.cs" />
+    <Compile Include="src\cms\DigOutputStream.cs" />
+    <Compile Include="src\cms\IDigestCalculator.cs" />
+    <Compile Include="src\cms\KEKRecipientInfoGenerator.cs" />
+    <Compile Include="src\cms\KEKRecipientInformation.cs" />
+    <Compile Include="src\cms\KeyAgreeRecipientInfoGenerator.cs" />
+    <Compile Include="src\cms\KeyAgreeRecipientInformation.cs" />
+    <Compile Include="src\cms\KeyTransRecipientInfoGenerator.cs" />
+    <Compile Include="src\cms\KeyTransRecipientInformation.cs" />
+    <Compile Include="src\cms\MacOutputStream.cs" />
+    <Compile Include="src\cms\NullOutputStream.cs" />
+    <Compile Include="src\cms\OriginatorId.cs" />
+    <Compile Include="src\cms\OriginatorInfoGenerator.cs" />
+    <Compile Include="src\cms\OriginatorInformation.cs" />
+    <Compile Include="src\cms\PasswordRecipientInfoGenerator.cs" />
+    <Compile Include="src\cms\PasswordRecipientInformation.cs" />
+    <Compile Include="src\cms\PKCS5Scheme2PBEKey.cs" />
+    <Compile Include="src\cms\PKCS5Scheme2UTF8PBEKey.cs" />
+    <Compile Include="src\cms\RecipientId.cs" />
+    <Compile Include="src\cms\RecipientInfoGenerator.cs" />
+    <Compile Include="src\cms\RecipientInformation.cs" />
+    <Compile Include="src\cms\RecipientInformationStore.cs" />
+    <Compile Include="src\cms\SignerId.cs" />
+    <Compile Include="src\cms\SignerInfoGenerator.cs" />
+    <Compile Include="src\cms\SignerInformation.cs" />
+    <Compile Include="src\cms\SignerInformationStore.cs" />
+    <Compile Include="src\cms\SigOutputStream.cs" />
+    <Compile Include="src\cms\SimpleAttributeTableGenerator.cs" />
+    <Compile Include="src\crypto\agreement\DHAgreement.cs" />
+    <Compile Include="src\crypto\agreement\DHBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\DHStandardGroups.cs" />
+    <Compile Include="src\crypto\agreement\ECDHBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\ECDHCBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\ECDHWithKdfBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\ECMqvBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\ECMqvWithKdfBasicAgreement.cs" />
+    <Compile Include="src\crypto\agreement\kdf\DHKdfParameters.cs" />
+    <Compile Include="src\crypto\agreement\kdf\DHKekGenerator.cs" />
+    <Compile Include="src\crypto\agreement\kdf\ECDHKekGenerator.cs" />
+    <Compile Include="src\crypto\agreement\srp\SRP6Client.cs" />
+    <Compile Include="src\crypto\agreement\srp\SRP6Server.cs" />
+    <Compile Include="src\crypto\agreement\srp\SRP6Utilities.cs" />
+    <Compile Include="src\crypto\agreement\srp\SRP6VerifierGenerator.cs" />
+    <Compile Include="src\crypto\AsymmetricCipherKeyPair.cs" />
+    <Compile Include="src\crypto\AsymmetricKeyParameter.cs" />
+    <Compile Include="src\crypto\BufferedAeadBlockCipher.cs" />
+    <Compile Include="src\crypto\BufferedAsymmetricBlockCipher.cs" />
+    <Compile Include="src\crypto\BufferedBlockCipher.cs" />
+    <Compile Include="src\crypto\BufferedCipherBase.cs" />
+    <Compile Include="src\crypto\BufferedIesCipher.cs" />
+    <Compile Include="src\crypto\BufferedStreamCipher.cs" />
+    <Compile Include="src\crypto\CipherKeyGenerator.cs" />
+    <Compile Include="src\crypto\CryptoException.cs" />
+    <Compile Include="src\crypto\DataLengthException.cs" />
+    <Compile Include="src\crypto\digests\GeneralDigest.cs" />
+    <Compile Include="src\crypto\digests\GOST3411Digest.cs" />
+    <Compile Include="src\crypto\digests\LongDigest.cs" />
+    <Compile Include="src\crypto\digests\MD2Digest.cs" />
+    <Compile Include="src\crypto\digests\MD4Digest.cs" />
+    <Compile Include="src\crypto\digests\MD5Digest.cs" />
+    <Compile Include="src\crypto\digests\NullDigest.cs" />
+    <Compile Include="src\crypto\digests\RipeMD128Digest.cs" />
+    <Compile Include="src\crypto\digests\RipeMD160Digest.cs" />
+    <Compile Include="src\crypto\digests\RipeMD256Digest.cs" />
+    <Compile Include="src\crypto\digests\RipeMD320Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha1Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha224Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha256Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha384Digest.cs" />
+    <Compile Include="src\crypto\digests\SHA3Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha512Digest.cs" />
+    <Compile Include="src\crypto\digests\Sha512tDigest.cs" />
+    <Compile Include="src\crypto\digests\ShortenedDigest.cs" />
+    <Compile Include="src\crypto\digests\SkeinDigest.cs" />
+    <Compile Include="src\crypto\digests\SkeinEngine.cs" />
+    <Compile Include="src\crypto\digests\SM3Digest.cs" />
+    <Compile Include="src\crypto\digests\TigerDigest.cs" />
+    <Compile Include="src\crypto\digests\WhirlpoolDigest.cs" />
+    <Compile Include="src\crypto\ec\CustomNamedCurves.cs" />
+    <Compile Include="src\crypto\encodings\ISO9796d1Encoding.cs" />
+    <Compile Include="src\crypto\encodings\OaepEncoding.cs" />
+    <Compile Include="src\crypto\encodings\Pkcs1Encoding.cs" />
+    <Compile Include="src\crypto\engines\AesEngine.cs" />
+    <Compile Include="src\crypto\engines\AesFastEngine.cs" />
+    <Compile Include="src\crypto\engines\AesLightEngine.cs" />
+    <Compile Include="src\crypto\engines\AesWrapEngine.cs" />
+    <Compile Include="src\crypto\engines\BlowfishEngine.cs" />
+    <Compile Include="src\crypto\engines\CamelliaEngine.cs" />
+    <Compile Include="src\crypto\engines\CamelliaLightEngine.cs" />
+    <Compile Include="src\crypto\engines\CamelliaWrapEngine.cs" />
+    <Compile Include="src\crypto\engines\Cast5Engine.cs" />
+    <Compile Include="src\crypto\engines\Cast6Engine.cs" />
+    <Compile Include="src\crypto\engines\ChaChaEngine.cs" />
+    <Compile Include="src\crypto\engines\DesEdeEngine.cs" />
+    <Compile Include="src\crypto\engines\DesEdeWrapEngine.cs" />
+    <Compile Include="src\crypto\engines\DesEngine.cs" />
+    <Compile Include="src\crypto\engines\ElGamalEngine.cs" />
+    <Compile Include="src\crypto\engines\GOST28147Engine.cs" />
+    <Compile Include="src\crypto\engines\HC128Engine.cs" />
+    <Compile Include="src\crypto\engines\HC256Engine.cs" />
+    <Compile Include="src\crypto\engines\IdeaEngine.cs" />
+    <Compile Include="src\crypto\engines\IesEngine.cs" />
+    <Compile Include="src\crypto\engines\ISAACEngine.cs" />
+    <Compile Include="src\crypto\engines\NaccacheSternEngine.cs" />
+    <Compile Include="src\crypto\engines\NoekeonEngine.cs" />
+    <Compile Include="src\crypto\engines\NullEngine.cs" />
+    <Compile Include="src\crypto\engines\RC2Engine.cs" />
+    <Compile Include="src\crypto\engines\RC2WrapEngine.cs" />
+    <Compile Include="src\crypto\engines\RC4Engine.cs" />
+    <Compile Include="src\crypto\engines\RC532Engine.cs" />
+    <Compile Include="src\crypto\engines\RC564Engine.cs" />
+    <Compile Include="src\crypto\engines\RC6Engine.cs" />
+    <Compile Include="src\crypto\engines\RFC3211WrapEngine.cs" />
+    <Compile Include="src\crypto\engines\RFC3394WrapEngine.cs" />
+    <Compile Include="src\crypto\engines\RijndaelEngine.cs" />
+    <Compile Include="src\crypto\engines\RSABlindedEngine.cs" />
+    <Compile Include="src\crypto\engines\RSABlindingEngine.cs" />
+    <Compile Include="src\crypto\engines\RSACoreEngine.cs" />
+    <Compile Include="src\crypto\engines\RsaEngine.cs" />
+    <Compile Include="src\crypto\engines\Salsa20Engine.cs" />
+    <Compile Include="src\crypto\engines\SEEDEngine.cs" />
+    <Compile Include="src\crypto\engines\SEEDWrapEngine.cs" />
+    <Compile Include="src\crypto\engines\SerpentEngine.cs" />
+    <Compile Include="src\crypto\engines\SkipjackEngine.cs" />
+    <Compile Include="src\crypto\engines\TEAEngine.cs" />
+    <Compile Include="src\crypto\engines\ThreefishEngine.cs" />
+    <Compile Include="src\crypto\engines\TwofishEngine.cs" />
+    <Compile Include="src\crypto\engines\VMPCEngine.cs" />
+    <Compile Include="src\crypto\engines\VMPCKSA3Engine.cs" />
+    <Compile Include="src\crypto\engines\XSalsa20Engine.cs" />
+    <Compile Include="src\crypto\engines\XTEAEngine.cs" />
+    <Compile Include="src\crypto\generators\BaseKdfBytesGenerator.cs" />
+    <Compile Include="src\crypto\generators\DesEdeKeyGenerator.cs" />
+    <Compile Include="src\crypto\generators\DesKeyGenerator.cs" />
+    <Compile Include="src\crypto\generators\DHBasicKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\DHKeyGeneratorHelper.cs" />
+    <Compile Include="src\crypto\generators\DHKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\DHParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\DHParametersHelper.cs" />
+    <Compile Include="src\crypto\generators\DsaKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\DsaParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\ECKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\ElGamalKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\ElGamalParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\GOST3410KeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\GOST3410ParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\Kdf1BytesGenerator.cs" />
+    <Compile Include="src\crypto\generators\Kdf2BytesGenerator.cs" />
+    <Compile Include="src\crypto\generators\Mgf1BytesGenerator.cs" />
+    <Compile Include="src\crypto\generators\NaccacheSternKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\OpenSSLPBEParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\Pkcs12ParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\Pkcs5S1ParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\Pkcs5S2ParametersGenerator.cs" />
+    <Compile Include="src\crypto\generators\Poly1305KeyGenerator.cs" />
+    <Compile Include="src\crypto\generators\RSABlindingFactorGenerator.cs" />
+    <Compile Include="src\crypto\generators\RsaKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\generators\SCrypt.cs" />
+    <Compile Include="src\crypto\IAsymmetricBlockCipher.cs" />
+    <Compile Include="src\crypto\IAsymmetricCipherKeyPairGenerator.cs" />
+    <Compile Include="src\crypto\IBasicAgreement.cs" />
+    <Compile Include="src\crypto\IBlockCipher.cs" />
+    <Compile Include="src\crypto\IBufferedCipher.cs" />
+    <Compile Include="src\crypto\ICipherParameters.cs" />
+    <Compile Include="src\crypto\IDerivationFunction.cs" />
+    <Compile Include="src\crypto\IDerivationParameters.cs" />
+    <Compile Include="src\crypto\IDigest.cs" />
+    <Compile Include="src\crypto\IDSA.cs" />
+    <Compile Include="src\crypto\IMac.cs" />
+    <Compile Include="src\crypto\InvalidCipherTextException.cs" />
+    <Compile Include="src\crypto\io\CipherStream.cs" />
+    <Compile Include="src\crypto\io\DigestStream.cs" />
+    <Compile Include="src\crypto\io\MacStream.cs" />
+    <Compile Include="src\crypto\io\SignerStream.cs" />
+    <Compile Include="src\crypto\ISigner.cs" />
+    <Compile Include="src\crypto\ISignerWithRecovery.cs" />
+    <Compile Include="src\crypto\IStreamCipher.cs" />
+    <Compile Include="src\crypto\IWrapper.cs" />
+    <Compile Include="src\crypto\KeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\macs\CbcBlockCipherMac.cs" />
+    <Compile Include="src\crypto\macs\CfbBlockCipherMac.cs" />
+    <Compile Include="src\crypto\macs\CMac.cs" />
+    <Compile Include="src\crypto\macs\GMac.cs" />
+    <Compile Include="src\crypto\macs\GOST28147Mac.cs" />
+    <Compile Include="src\crypto\macs\HMac.cs" />
+    <Compile Include="src\crypto\macs\ISO9797Alg3Mac.cs" />
+    <Compile Include="src\crypto\macs\Poly1305.cs" />
+    <Compile Include="src\crypto\macs\SipHash.cs" />
+    <Compile Include="src\crypto\macs\SkeinMac.cs" />
+    <Compile Include="src\crypto\macs\VMPCMac.cs" />
+    <Compile Include="src\crypto\MaxBytesExceededException.cs" />
+    <Compile Include="src\crypto\modes\CbcBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\CcmBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\CfbBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\CtsBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\EAXBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\GCMBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\gcm\BasicGcmExponentiator.cs" />
+    <Compile Include="src\crypto\modes\gcm\BasicGcmMultiplier.cs" />
+    <Compile Include="src\crypto\modes\gcm\GcmUtilities.cs" />
+    <Compile Include="src\crypto\modes\gcm\IGcmExponentiator.cs" />
+    <Compile Include="src\crypto\modes\gcm\IGcmMultiplier.cs" />
+    <Compile Include="src\crypto\modes\gcm\Tables1kGcmExponentiator.cs" />
+    <Compile Include="src\crypto\modes\gcm\Tables64kGcmMultiplier.cs" />
+    <Compile Include="src\crypto\modes\gcm\Tables8kGcmMultiplier.cs" />
+    <Compile Include="src\crypto\modes\GOFBBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\IAeadBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\OCBBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\OfbBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\OpenPgpCfbBlockCipher.cs" />
+    <Compile Include="src\crypto\modes\SicBlockCipher.cs" />
+    <Compile Include="src\crypto\paddings\BlockCipherPadding.cs" />
+    <Compile Include="src\crypto\paddings\ISO10126d2Padding.cs" />
+    <Compile Include="src\crypto\paddings\ISO7816d4Padding.cs" />
+    <Compile Include="src\crypto\paddings\PaddedBufferedBlockCipher.cs" />
+    <Compile Include="src\crypto\paddings\Pkcs7Padding.cs" />
+    <Compile Include="src\crypto\paddings\TbcPadding.cs" />
+    <Compile Include="src\crypto\paddings\X923Padding.cs" />
+    <Compile Include="src\crypto\paddings\ZeroBytePadding.cs" />
+    <Compile Include="src\crypto\parameters\AEADParameters.cs" />
+    <Compile Include="src\crypto\parameters\CcmParameters.cs" />
+    <Compile Include="src\crypto\parameters\DesEdeParameters.cs" />
+    <Compile Include="src\crypto\parameters\DesParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHPrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHPublicKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DHValidationParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DSAParameterGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaPrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaPublicKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\DsaValidationParameters.cs" />
+    <Compile Include="src\crypto\parameters\ECDomainParameters.cs" />
+    <Compile Include="src\crypto\parameters\ECKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\ECKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ECPrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ECPublicKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ElGamalKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\ElGamalKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ElGamalParameters.cs" />
+    <Compile Include="src\crypto\parameters\ElGamalPrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ElGamalPublicKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410KeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410KeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410Parameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410PrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410PublicKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\GOST3410ValidationParameters.cs" />
+    <Compile Include="src\crypto\parameters\IesParameters.cs" />
+    <Compile Include="src\crypto\parameters\IesWithCipherParameters.cs" />
+    <Compile Include="src\crypto\parameters\ISO18033KDFParameters.cs" />
+    <Compile Include="src\crypto\parameters\KdfParameters.cs" />
+    <Compile Include="src\crypto\parameters\KeyParameter.cs" />
+    <Compile Include="src\crypto\parameters\MgfParameters.cs" />
+    <Compile Include="src\crypto\parameters\MqvPrivateParameters.cs" />
+    <Compile Include="src\crypto\parameters\MqvPublicParameters.cs" />
+    <Compile Include="src\crypto\parameters\NaccacheSternKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\NaccacheSternKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\NaccacheSternPrivateKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\ParametersWithIV.cs" />
+    <Compile Include="src\crypto\parameters\ParametersWithRandom.cs" />
+    <Compile Include="src\crypto\parameters\ParametersWithSalt.cs" />
+    <Compile Include="src\crypto\parameters\ParametersWithSBox.cs" />
+    <Compile Include="src\crypto\parameters\RC2Parameters.cs" />
+    <Compile Include="src\crypto\parameters\RC5Parameters.cs" />
+    <Compile Include="src\crypto\parameters\RSABlindingParameters.cs" />
+    <Compile Include="src\crypto\parameters\RsaKeyGenerationParameters.cs" />
+    <Compile Include="src\crypto\parameters\RsaKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\RsaPrivateCrtKeyParameters.cs" />
+    <Compile Include="src\crypto\parameters\SkeinParameters.cs" />
+    <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs" />
+    <Compile Include="src\crypto\PbeParametersGenerator.cs" />
+    <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs" />
+    <Compile Include="src\crypto\prng\DigestRandomGenerator.cs" />
+    <Compile Include="src\crypto\prng\IRandomGenerator.cs" />
+    <Compile Include="src\crypto\prng\ReversedWindowGenerator.cs" />
+    <Compile Include="src\crypto\prng\ThreadedSeedGenerator.cs" />
+    <Compile Include="src\crypto\prng\VMPCRandomGenerator.cs" />
+    <Compile Include="src\crypto\signers\DsaDigestSigner.cs" />
+    <Compile Include="src\crypto\signers\DsaSigner.cs" />
+    <Compile Include="src\crypto\signers\ECDsaSigner.cs" />
+    <Compile Include="src\crypto\signers\ECGOST3410Signer.cs" />
+    <Compile Include="src\crypto\signers\ECNRSigner.cs" />
+    <Compile Include="src\crypto\signers\GenericSigner.cs" />
+    <Compile Include="src\crypto\signers\GOST3410DigestSigner.cs" />
+    <Compile Include="src\crypto\signers\GOST3410Signer.cs" />
+    <Compile Include="src\crypto\signers\HMacDsaKCalculator.cs" />
+    <Compile Include="src\crypto\signers\IDsaKCalculator.cs" />
+    <Compile Include="src\crypto\signers\Iso9796d2PssSigner.cs" />
+    <Compile Include="src\crypto\signers\Iso9796d2Signer.cs" />
+    <Compile Include="src\crypto\signers\PssSigner.cs" />
+    <Compile Include="src\crypto\signers\RandomDsaKCalculator.cs" />
+    <Compile Include="src\crypto\signers\RsaDigestSigner.cs" />
+    <Compile Include="src\crypto\StreamBlockCipher.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsAgreementCredentials.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsCipherFactory.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsClient.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsContext.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsCredentials.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsEncryptionCredentials.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsPeer.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsServer.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsSigner.cs" />
+    <Compile Include="src\crypto\tls\AbstractTlsSignerCredentials.cs" />
+    <Compile Include="src\crypto\tls\AlertDescription.cs" />
+    <Compile Include="src\crypto\tls\AlertLevel.cs" />
+    <Compile Include="src\crypto\tls\AlwaysValidVerifyer.cs" />
+    <Compile Include="src\crypto\tls\BulkCipherAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\ByteQueue.cs" />
+    <Compile Include="src\crypto\tls\CertChainType.cs" />
+    <Compile Include="src\crypto\tls\Certificate.cs" />
+    <Compile Include="src\crypto\tls\CertificateRequest.cs" />
+    <Compile Include="src\crypto\tls\CertificateStatus.cs" />
+    <Compile Include="src\crypto\tls\CertificateStatusRequest.cs" />
+    <Compile Include="src\crypto\tls\CertificateStatusType.cs" />
+    <Compile Include="src\crypto\tls\CertificateUrl.cs" />
+    <Compile Include="src\crypto\tls\Chacha20Poly1305.cs" />
+    <Compile Include="src\crypto\tls\ChangeCipherSpec.cs" />
+    <Compile Include="src\crypto\tls\CipherSuite.cs" />
+    <Compile Include="src\crypto\tls\CipherType.cs" />
+    <Compile Include="src\crypto\tls\ClientAuthenticationType.cs" />
+    <Compile Include="src\crypto\tls\ClientCertificateType.cs" />
+    <Compile Include="src\crypto\tls\CombinedHash.cs" />
+    <Compile Include="src\crypto\tls\CompressionMethod.cs" />
+    <Compile Include="src\crypto\tls\ConnectionEnd.cs" />
+    <Compile Include="src\crypto\tls\ContentType.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsAgreementCredentials.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsCipherFactory.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsClient.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsServer.cs" />
+    <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs" />
+    <Compile Include="src\crypto\tls\DeferredHash.cs" />
+    <Compile Include="src\crypto\tls\DigestAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\DigestInputBuffer.cs" />
+    <Compile Include="src\crypto\tls\DigitallySigned.cs" />
+    <Compile Include="src\crypto\tls\ECBasisType.cs" />
+    <Compile Include="src\crypto\tls\ECCurveType.cs" />
+    <Compile Include="src\crypto\tls\ECPointFormat.cs" />
+    <Compile Include="src\crypto\tls\EncryptionAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\ExporterLabel.cs" />
+    <Compile Include="src\crypto\tls\ExtensionType.cs" />
+    <Compile Include="src\crypto\tls\HandshakeType.cs" />
+    <Compile Include="src\crypto\tls\HashAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\HeartbeatExtension.cs" />
+    <Compile Include="src\crypto\tls\HeartbeatMessage.cs" />
+    <Compile Include="src\crypto\tls\HeartbeatMessageType.cs" />
+    <Compile Include="src\crypto\tls\HeartbeatMode.cs" />
+    <Compile Include="src\crypto\tls\ICertificateVerifyer.cs" />
+    <Compile Include="src\crypto\tls\KeyExchangeAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\MacAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\MaxFragmentLength.cs" />
+    <Compile Include="src\crypto\tls\NamedCurve.cs" />
+    <Compile Include="src\crypto\tls\NameType.cs" />
+    <Compile Include="src\crypto\tls\NewSessionTicket.cs" />
+    <Compile Include="src\crypto\tls\OcspStatusRequest.cs" />
+    <Compile Include="src\crypto\tls\PrfAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\ProtocolVersion.cs" />
+    <Compile Include="src\crypto\tls\PskTlsClient.cs" />
+    <Compile Include="src\crypto\tls\RecordStream.cs" />
+    <Compile Include="src\crypto\tls\SecurityParameters.cs" />
+    <Compile Include="src\crypto\tls\ServerDHParams.cs" />
+    <Compile Include="src\crypto\tls\ServerName.cs" />
+    <Compile Include="src\crypto\tls\ServerNameList.cs" />
+    <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs" />
+    <Compile Include="src\crypto\tls\SessionParameters.cs" />
+    <Compile Include="src\crypto\tls\SignatureAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\SignatureAndHashAlgorithm.cs" />
+    <Compile Include="src\crypto\tls\SignerInputBuffer.cs" />
+    <Compile Include="src\crypto\tls\SrpTlsClient.cs" />
+    <Compile Include="src\crypto\tls\SrtpProtectionProfile.cs" />
+    <Compile Include="src\crypto\tls\Ssl3Mac.cs" />
+    <Compile Include="src\crypto\tls\SupplementalDataEntry.cs" />
+    <Compile Include="src\crypto\tls\SupplementalDataType.cs" />
+    <Compile Include="src\crypto\tls\TlsAeadCipher.cs" />
+    <Compile Include="src\crypto\tls\TlsAgreementCredentials.cs" />
+    <Compile Include="src\crypto\tls\TlsAuthentication.cs" />
+    <Compile Include="src\crypto\tls\TlsBlockCipher.cs" />
+    <Compile Include="src\crypto\tls\TlsCipher.cs" />
+    <Compile Include="src\crypto\tls\TlsCipherFactory.cs" />
+    <Compile Include="src\crypto\tls\TlsClient.cs" />
+    <Compile Include="src\crypto\tls\TlsClientContext.cs" />
+    <Compile Include="src\crypto\tls\TlsClientContextImpl.cs" />
+    <Compile Include="src\crypto\tls\TlsClientProtocol.cs" />
+    <Compile Include="src\crypto\tls\TlsCompression.cs" />
+    <Compile Include="src\crypto\tls\TlsContext.cs" />
+    <Compile Include="src\crypto\tls\TlsCredentials.cs" />
+    <Compile Include="src\crypto\tls\TlsDeflateCompression.cs" />
+    <Compile Include="src\crypto\tls\TlsDheKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsDHKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsDHUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsDsaSigner.cs" />
+    <Compile Include="src\crypto\tls\TlsDssSigner.cs" />
+    <Compile Include="src\crypto\tls\TlsEccUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsECDheKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsECDHKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsECDsaSigner.cs" />
+    <Compile Include="src\crypto\tls\TlsEncryptionCredentials.cs" />
+    <Compile Include="src\crypto\tls\TlsException.cs" />
+    <Compile Include="src\crypto\tls\TlsExtensionsUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsFatalAlert.cs" />
+    <Compile Include="src\crypto\tls\TlsHandshakeHash.cs" />
+    <Compile Include="src\crypto\tls\TlsKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsMac.cs" />
+    <Compile Include="src\crypto\tls\TlsNullCipher.cs" />
+    <Compile Include="src\crypto\tls\TlsNullCompression.cs" />
+    <Compile Include="src\crypto\tls\TlsPeer.cs" />
+    <Compile Include="src\crypto\tls\TlsProtocol.cs" />
+    <Compile Include="src\crypto\tls\TlsProtocolHandler.cs" />
+    <Compile Include="src\crypto\tls\TlsPskIdentity.cs" />
+    <Compile Include="src\crypto\tls\TlsPskKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsRsaKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsRsaSigner.cs" />
+    <Compile Include="src\crypto\tls\TlsRsaUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsServer.cs" />
+    <Compile Include="src\crypto\tls\TlsServerContext.cs" />
+    <Compile Include="src\crypto\tls\TlsServerContextImpl.cs" />
+    <Compile Include="src\crypto\tls\TlsServerProtocol.cs" />
+    <Compile Include="src\crypto\tls\TlsSession.cs" />
+    <Compile Include="src\crypto\tls\TlsSessionImpl.cs" />
+    <Compile Include="src\crypto\tls\TlsSigner.cs" />
+    <Compile Include="src\crypto\tls\TlsSignerCredentials.cs" />
+    <Compile Include="src\crypto\tls\TlsSrpKeyExchange.cs" />
+    <Compile Include="src\crypto\tls\TlsSrpUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsSrtpUtilities.cs" />
+    <Compile Include="src\crypto\tls\TlsStream.cs" />
+    <Compile Include="src\crypto\tls\TlsStreamCipher.cs" />
+    <Compile Include="src\crypto\tls\TlsUtilities.cs" />
+    <Compile Include="src\crypto\tls\UrlAndHash.cs" />
+    <Compile Include="src\crypto\tls\UserMappingType.cs" />
+    <Compile Include="src\crypto\tls\UseSrtpData.cs" />
+    <Compile Include="src\crypto\util\Pack.cs" />
+    <Compile Include="src\math\BigInteger.cs" />
+    <Compile Include="src\math\ec\abc\SimpleBigDecimal.cs" />
+    <Compile Include="src\math\ec\abc\Tnaf.cs" />
+    <Compile Include="src\math\ec\abc\ZTauElement.cs" />
+    <Compile Include="src\math\ec\custom\djb\Curve25519.cs" />
+    <Compile Include="src\math\ec\custom\djb\Curve25519Field.cs" />
+    <Compile Include="src\math\ec\custom\djb\Curve25519FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\djb\Curve25519Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\Nat192.cs" />
+    <Compile Include="src\math\ec\custom\sec\Nat224.cs" />
+    <Compile Include="src\math\ec\custom\sec\Nat256.cs" />
+    <Compile Include="src\math\ec\custom\sec\Nat384.cs" />
+    <Compile Include="src\math\ec\custom\sec\Nat512.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192K1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192R1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224K1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224R1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256K1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256R1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP384R1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Point.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Curve.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Field.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP521R1FieldElement.cs" />
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Point.cs" />
+    <Compile Include="src\math\ec\ECAlgorithms.cs" />
+    <Compile Include="src\math\ec\ECCurve.cs" />
+    <Compile Include="src\math\ec\ECFieldElement.cs" />
+    <Compile Include="src\math\ec\ECPoint.cs" />
+    <Compile Include="src\math\ec\ECPointMap.cs" />
+    <Compile Include="src\math\ec\endo\ECEndomorphism.cs" />
+    <Compile Include="src\math\ec\endo\GlvEndomorphism.cs" />
+    <Compile Include="src\math\ec\endo\GlvTypeBEndomorphism.cs" />
+    <Compile Include="src\math\ec\endo\GlvTypeBParameters.cs" />
+    <Compile Include="src\math\ec\IntArray.cs" />
+    <Compile Include="src\math\ec\LongArray.cs" />
+    <Compile Include="src\math\ec\Mod.cs" />
+    <Compile Include="src\math\ec\multiplier\AbstractECMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\DoubleAddMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\ECMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\FixedPointCombMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\FixedPointPreCompInfo.cs" />
+    <Compile Include="src\math\ec\multiplier\FixedPointUtilities.cs" />
+    <Compile Include="src\math\ec\multiplier\GlvMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\MixedNafR2LMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\MontgomeryLadderMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\NafL2RMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\NafR2LMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\PreCompInfo.cs" />
+    <Compile Include="src\math\ec\multiplier\ReferenceMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\WNafL2RMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\WNafPreCompInfo.cs" />
+    <Compile Include="src\math\ec\multiplier\WNafUtilities.cs" />
+    <Compile Include="src\math\ec\multiplier\WTauNafMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\WTauNafPreCompInfo.cs" />
+    <Compile Include="src\math\ec\multiplier\ZSignedDigitL2RMultiplier.cs" />
+    <Compile Include="src\math\ec\multiplier\ZSignedDigitR2LMultiplier.cs" />
+    <Compile Include="src\math\ec\Nat.cs" />
+    <Compile Include="src\math\ec\ScaleXPointMap.cs" />
+    <Compile Include="src\math\ec\ScaleYPointMap.cs" />
+    <Compile Include="src\math\field\FiniteFields.cs" />
+    <Compile Include="src\math\field\GenericPolynomialExtensionField.cs" />
+    <Compile Include="src\math\field\GF2Polynomial.cs" />
+    <Compile Include="src\math\field\IExtensionField.cs" />
+    <Compile Include="src\math\field\IFiniteField.cs" />
+    <Compile Include="src\math\field\IPolynomial.cs" />
+    <Compile Include="src\math\field\IPolynomialExtensionField.cs" />
+    <Compile Include="src\math\field\PrimeField.cs" />
+    <Compile Include="src\ocsp\BasicOCSPResp.cs" />
+    <Compile Include="src\ocsp\BasicOCSPRespGenerator.cs" />
+    <Compile Include="src\ocsp\CertificateID.cs" />
+    <Compile Include="src\ocsp\CertificateStatus.cs" />
+    <Compile Include="src\ocsp\OCSPException.cs" />
+    <Compile Include="src\ocsp\OCSPReq.cs" />
+    <Compile Include="src\ocsp\OCSPReqGenerator.cs" />
+    <Compile Include="src\ocsp\OCSPResp.cs" />
+    <Compile Include="src\ocsp\OCSPRespGenerator.cs" />
+    <Compile Include="src\ocsp\OCSPRespStatus.cs" />
+    <Compile Include="src\ocsp\OCSPUtil.cs" />
+    <Compile Include="src\ocsp\Req.cs" />
+    <Compile Include="src\ocsp\RespData.cs" />
+    <Compile Include="src\ocsp\RespID.cs" />
+    <Compile Include="src\ocsp\RevokedStatus.cs" />
+    <Compile Include="src\ocsp\SingleResp.cs" />
+    <Compile Include="src\ocsp\UnknownStatus.cs" />
+    <Compile Include="src\openpgp\IStreamGenerator.cs" />
+    <Compile Include="src\openpgp\PgpCompressedData.cs" />
+    <Compile Include="src\openpgp\PgpCompressedDataGenerator.cs" />
+    <Compile Include="src\openpgp\PgpDataValidationException.cs" />
+    <Compile Include="src\openpgp\PgpEncryptedData.cs" />
+    <Compile Include="src\openpgp\PgpEncryptedDataGenerator.cs" />
+    <Compile Include="src\openpgp\PgpEncryptedDataList.cs" />
+    <Compile Include="src\openpgp\PgpException.cs" />
+    <Compile Include="src\openpgp\PgpExperimental.cs" />
+    <Compile Include="src\openpgp\PgpKeyFlags.cs" />
+    <Compile Include="src\openpgp\PgpKeyPair.cs" />
+    <Compile Include="src\openpgp\PGPKeyRing.cs" />
+    <Compile Include="src\openpgp\PgpKeyRingGenerator.cs" />
+    <Compile Include="src\openpgp\PgpKeyValidationException.cs" />
+    <Compile Include="src\openpgp\PgpLiteralData.cs" />
+    <Compile Include="src\openpgp\PgpLiteralDataGenerator.cs" />
+    <Compile Include="src\openpgp\PgpMarker.cs" />
+    <Compile Include="src\openpgp\PGPObject.cs" />
+    <Compile Include="src\openpgp\PgpObjectFactory.cs" />
+    <Compile Include="src\openpgp\PgpOnePassSignature.cs" />
+    <Compile Include="src\openpgp\PgpOnePassSignatureList.cs" />
+    <Compile Include="src\openpgp\PgpPbeEncryptedData.cs" />
+    <Compile Include="src\openpgp\PgpPrivateKey.cs" />
+    <Compile Include="src\openpgp\PgpPublicKey.cs" />
+    <Compile Include="src\openpgp\PgpPublicKeyEncryptedData.cs" />
+    <Compile Include="src\openpgp\PgpPublicKeyRing.cs" />
+    <Compile Include="src\openpgp\PgpPublicKeyRingBundle.cs" />
+    <Compile Include="src\openpgp\PgpSecretKey.cs" />
+    <Compile Include="src\openpgp\PgpSecretKeyRing.cs" />
+    <Compile Include="src\openpgp\PgpSecretKeyRingBundle.cs" />
+    <Compile Include="src\openpgp\PgpSignature.cs" />
+    <Compile Include="src\openpgp\PgpSignatureGenerator.cs" />
+    <Compile Include="src\openpgp\PgpSignatureList.cs" />
+    <Compile Include="src\openpgp\PgpSignatureSubpacketGenerator.cs" />
+    <Compile Include="src\openpgp\PgpSignatureSubpacketVector.cs" />
+    <Compile Include="src\openpgp\PgpUserAttributeSubpacketVector.cs" />
+    <Compile Include="src\openpgp\PGPUserAttributeSubpacketVectorGenerator.cs" />
+    <Compile Include="src\openpgp\PgpUtilities.cs" />
+    <Compile Include="src\openpgp\PgpV3SignatureGenerator.cs" />
+    <Compile Include="src\openpgp\WrappedGeneratorStream.cs" />
+    <Compile Include="src\openssl\EncryptionException.cs" />
+    <Compile Include="src\openssl\IPasswordFinder.cs" />
+    <Compile Include="src\openssl\MiscPemGenerator.cs" />
+    <Compile Include="src\openssl\PasswordException.cs" />
+    <Compile Include="src\openssl\PEMException.cs" />
+    <Compile Include="src\openssl\PEMReader.cs" />
+    <Compile Include="src\openssl\PEMUtilities.cs" />
+    <Compile Include="src\openssl\PEMWriter.cs" />
+    <Compile Include="src\openssl\Pkcs8Generator.cs" />
+    <Compile Include="src\pkcs\AsymmetricKeyEntry.cs" />
+    <Compile Include="src\pkcs\EncryptedPrivateKeyInfoFactory.cs" />
+    <Compile Include="src\pkcs\Pkcs10CertificationRequest.cs" />
+    <Compile Include="src\pkcs\Pkcs10CertificationRequestDelaySigned.cs" />
+    <Compile Include="src\pkcs\Pkcs12Entry.cs" />
+    <Compile Include="src\pkcs\Pkcs12Store.cs" />
+    <Compile Include="src\pkcs\PKCS12StoreBuilder.cs" />
+    <Compile Include="src\pkcs\Pkcs12Utilities.cs" />
+    <Compile Include="src\pkcs\PrivateKeyInfoFactory.cs" />
+    <Compile Include="src\pkcs\X509CertificateEntry.cs" />
+    <Compile Include="src\pkix\CertStatus.cs" />
+    <Compile Include="src\pkix\PkixAttrCertChecker.cs" />
+    <Compile Include="src\pkix\PkixAttrCertPathBuilder.cs" />
+    <Compile Include="src\pkix\PkixAttrCertPathValidator.cs" />
+    <Compile Include="src\pkix\PkixBuilderParameters.cs" />
+    <Compile Include="src\pkix\PkixCertPath.cs" />
+    <Compile Include="src\pkix\PkixCertPathBuilder.cs" />
+    <Compile Include="src\pkix\PkixCertPathBuilderException.cs" />
+    <Compile Include="src\pkix\PkixCertPathBuilderResult.cs" />
+    <Compile Include="src\pkix\PkixCertPathChecker.cs" />
+    <Compile Include="src\pkix\PkixCertPathValidator.cs" />
+    <Compile Include="src\pkix\PkixCertPathValidatorException.cs" />
+    <Compile Include="src\pkix\PkixCertPathValidatorResult.cs" />
+    <Compile Include="src\pkix\PkixCertPathValidatorUtilities.cs" />
+    <Compile Include="src\pkix\PkixCrlUtilities.cs" />
+    <Compile Include="src\pkix\PkixNameConstraintValidator.cs" />
+    <Compile Include="src\pkix\PkixNameConstraintValidatorException.cs" />
+    <Compile Include="src\pkix\PkixParameters.cs" />
+    <Compile Include="src\pkix\PkixPolicyNode.cs" />
+    <Compile Include="src\pkix\ReasonsMask.cs" />
+    <Compile Include="src\pkix\Rfc3280CertPathUtilities.cs" />
+    <Compile Include="src\pkix\Rfc3281CertPathUtilities.cs" />
+    <Compile Include="src\pkix\TrustAnchor.cs" />
+    <Compile Include="src\security\AgreementUtilities.cs" />
+    <Compile Include="src\security\cert\CertificateEncodingException.cs" />
+    <Compile Include="src\security\cert\CertificateException.cs" />
+    <Compile Include="src\security\cert\CertificateExpiredException.cs" />
+    <Compile Include="src\security\cert\CertificateNotYetValidException.cs" />
+    <Compile Include="src\security\cert\CertificateParsingException.cs" />
+    <Compile Include="src\security\cert\CrlException.cs" />
+    <Compile Include="src\security\CipherUtilities.cs" />
+    <Compile Include="src\security\DigestUtilities.cs" />
+    <Compile Include="src\security\DotNetUtilities.cs" />
+    <Compile Include="src\security\GeneralSecurityException.cs" />
+    <Compile Include="src\security\GeneratorUtilities.cs" />
+    <Compile Include="src\security\InvalidKeyException.cs" />
+    <Compile Include="src\security\InvalidParameterException.cs" />
+    <Compile Include="src\security\KeyException.cs" />
+    <Compile Include="src\security\MacUtilities.cs" />
+    <Compile Include="src\security\NoSuchAlgorithmException.cs" />
+    <Compile Include="src\security\ParameterUtilities.cs" />
+    <Compile Include="src\security\PbeUtilities.cs" />
+    <Compile Include="src\security\PrivateKeyFactory.cs" />
+    <Compile Include="src\security\PublicKeyFactory.cs" />
+    <Compile Include="src\security\SecureRandom.cs" />
+    <Compile Include="src\security\SecurityUtilityException.cs" />
+    <Compile Include="src\security\SignatureException.cs" />
+    <Compile Include="src\security\SignerUtilities.cs" />
+    <Compile Include="src\security\WrapperUtilities.cs" />
+    <Compile Include="src\tsp\GenTimeAccuracy.cs" />
+    <Compile Include="src\tsp\TimeStampRequest.cs" />
+    <Compile Include="src\tsp\TimeStampRequestGenerator.cs" />
+    <Compile Include="src\tsp\TimeStampResponse.cs" />
+    <Compile Include="src\tsp\TimeStampResponseGenerator.cs" />
+    <Compile Include="src\tsp\TimeStampToken.cs" />
+    <Compile Include="src\tsp\TimeStampTokenGenerator.cs" />
+    <Compile Include="src\tsp\TimeStampTokenInfo.cs" />
+    <Compile Include="src\tsp\TSPAlgorithms.cs" />
+    <Compile Include="src\tsp\TSPException.cs" />
+    <Compile Include="src\tsp\TSPUtil.cs" />
+    <Compile Include="src\tsp\TSPValidationException.cs" />
+    <Compile Include="src\util\Arrays.cs" />
+    <Compile Include="src\util\BigIntegers.cs" />
+    <Compile Include="src\util\collections\CollectionUtilities.cs" />
+    <Compile Include="src\util\collections\EmptyEnumerable.cs" />
+    <Compile Include="src\util\collections\EnumerableProxy.cs" />
+    <Compile Include="src\util\collections\HashSet.cs" />
+    <Compile Include="src\util\collections\ISet.cs" />
+    <Compile Include="src\util\collections\LinkedDictionary.cs" />
+    <Compile Include="src\util\collections\UnmodifiableDictionary.cs" />
+    <Compile Include="src\util\collections\UnmodifiableDictionaryProxy.cs" />
+    <Compile Include="src\util\collections\UnmodifiableList.cs" />
+    <Compile Include="src\util\collections\UnmodifiableListProxy.cs" />
+    <Compile Include="src\util\collections\UnmodifiableSet.cs" />
+    <Compile Include="src\util\collections\UnmodifiableSetProxy.cs" />
+    <Compile Include="src\util\date\DateTimeObject.cs" />
+    <Compile Include="src\util\date\DateTimeUtilities.cs" />
+    <Compile Include="src\util\encoders\Base64.cs" />
+    <Compile Include="src\util\encoders\Base64Encoder.cs" />
+    <Compile Include="src\util\encoders\BufferedDecoder.cs" />
+    <Compile Include="src\util\encoders\BufferedEncoder.cs" />
+    <Compile Include="src\util\encoders\Hex.cs" />
+    <Compile Include="src\util\encoders\HexEncoder.cs" />
+    <Compile Include="src\util\encoders\HexTranslator.cs" />
+    <Compile Include="src\util\encoders\IEncoder.cs" />
+    <Compile Include="src\util\encoders\Translator.cs" />
+    <Compile Include="src\util\encoders\UrlBase64.cs" />
+    <Compile Include="src\util\encoders\UrlBase64Encoder.cs" />
+    <Compile Include="src\util\Enums.cs" />
+    <Compile Include="src\util\IMemoable.cs" />
+    <Compile Include="src\util\Integers.cs" />
+    <Compile Include="src\util\io\BaseInputStream.cs" />
+    <Compile Include="src\util\io\BaseOutputStream.cs" />
+    <Compile Include="src\util\io\NullOutputStream.cs" />
+    <Compile Include="src\util\io\pem\PemGenerationException.cs" />
+    <Compile Include="src\util\io\pem\PemHeader.cs" />
+    <Compile Include="src\util\io\pem\PemObject.cs" />
+    <Compile Include="src\util\io\pem\PemObjectGenerator.cs" />
+    <Compile Include="src\util\io\pem\PemObjectParser.cs" />
+    <Compile Include="src\util\io\pem\PemReader.cs" />
+    <Compile Include="src\util\io\pem\PemWriter.cs" />
+    <Compile Include="src\util\io\PushbackStream.cs" />
+    <Compile Include="src\util\io\StreamOverflowException.cs" />
+    <Compile Include="src\util\io\Streams.cs" />
+    <Compile Include="src\util\io\TeeInputStream.cs" />
+    <Compile Include="src\util\io\TeeOutputStream.cs" />
+    <Compile Include="src\util\MemoableResetException.cs" />
+    <Compile Include="src\util\net\IPAddress.cs" />
+    <Compile Include="src\util\Platform.cs" />
+    <Compile Include="src\util\Strings.cs" />
+    <Compile Include="src\util\Times.cs" />
+    <Compile Include="src\util\zlib\Adler32.cs" />
+    <Compile Include="src\util\zlib\Deflate.cs" />
+    <Compile Include="src\util\zlib\InfBlocks.cs" />
+    <Compile Include="src\util\zlib\InfCodes.cs" />
+    <Compile Include="src\util\zlib\Inflate.cs" />
+    <Compile Include="src\util\zlib\InfTree.cs" />
+    <Compile Include="src\util\zlib\JZlib.cs" />
+    <Compile Include="src\util\zlib\StaticTree.cs" />
+    <Compile Include="src\util\zlib\Tree.cs" />
+    <Compile Include="src\util\zlib\ZDeflaterOutputStream.cs" />
+    <Compile Include="src\util\zlib\ZInflaterInputStream.cs" />
+    <Compile Include="src\util\zlib\ZInputStream.cs" />
+    <Compile Include="src\util\zlib\ZOutputStream.cs" />
+    <Compile Include="src\util\zlib\ZStream.cs" />
+    <Compile Include="src\x509\AttributeCertificateHolder.cs" />
+    <Compile Include="src\x509\AttributeCertificateIssuer.cs" />
+    <Compile Include="src\x509\extension\AuthorityKeyIdentifierStructure.cs" />
+    <Compile Include="src\x509\extension\SubjectKeyIdentifierStructure.cs" />
+    <Compile Include="src\x509\extension\X509ExtensionUtil.cs" />
+    <Compile Include="src\x509\IX509AttributeCertificate.cs" />
+    <Compile Include="src\x509\IX509Extension.cs" />
+    <Compile Include="src\x509\PEMParser.cs" />
+    <Compile Include="src\x509\PrincipalUtil.cs" />
+    <Compile Include="src\x509\store\IX509Selector.cs" />
+    <Compile Include="src\x509\store\IX509Store.cs" />
+    <Compile Include="src\x509\store\IX509StoreParameters.cs" />
+    <Compile Include="src\x509\store\NoSuchStoreException.cs" />
+    <Compile Include="src\x509\store\X509AttrCertStoreSelector.cs" />
+    <Compile Include="src\x509\store\X509CertPairStoreSelector.cs" />
+    <Compile Include="src\x509\store\X509CertStoreSelector.cs" />
+    <Compile Include="src\x509\store\X509CollectionStore.cs" />
+    <Compile Include="src\x509\store\X509CollectionStoreParameters.cs" />
+    <Compile Include="src\x509\store\X509CrlStoreSelector.cs" />
+    <Compile Include="src\x509\store\X509StoreException.cs" />
+    <Compile Include="src\x509\store\X509StoreFactory.cs" />
+    <Compile Include="src\x509\SubjectPublicKeyInfoFactory.cs" />
+    <Compile Include="src\x509\X509AttrCertParser.cs" />
+    <Compile Include="src\x509\X509Attribute.cs" />
+    <Compile Include="src\x509\X509Certificate.cs" />
+    <Compile Include="src\x509\X509CertificatePair.cs" />
+    <Compile Include="src\x509\X509CertificateParser.cs" />
+    <Compile Include="src\x509\X509CertPairParser.cs" />
+    <Compile Include="src\x509\X509Crl.cs" />
+    <Compile Include="src\x509\X509CrlEntry.cs" />
+    <Compile Include="src\x509\X509CrlParser.cs" />
+    <Compile Include="src\x509\X509ExtensionBase.cs" />
+    <Compile Include="src\x509\X509KeyUsage.cs" />
+    <Compile Include="src\x509\X509SignatureUtil.cs" />
+    <Compile Include="src\x509\X509Utilities.cs" />
+    <Compile Include="src\x509\X509V1CertificateGenerator.cs" />
+    <Compile Include="src\x509\X509V2AttributeCertificate.cs" />
+    <Compile Include="src\x509\X509V2AttributeCertificateGenerator.cs" />
+    <Compile Include="src\x509\X509V2CRLGenerator.cs" />
+    <Compile Include="src\x509\X509V3CertificateGenerator.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="checklist.txt" />
+    <Content Include="Contributors.html" />
+    <Content Include="License.html" />
+    <Content Include="ReadMe-AxCrypt.txt" />
+    <Content Include="Readme.html" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.sln b/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.sln
new file mode 100644
index 0000000..346d32f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/BouncyCastle.AxCrypt.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BouncyCastle.AxCrypt", "src\BouncyCastle.AxCrypt.csproj", "{3B5CDE2B-9418-4873-9E13-B0594D7483A3}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{3B5CDE2B-9418-4873-9E13-B0594D7483A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{3B5CDE2B-9418-4873-9E13-B0594D7483A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{3B5CDE2B-9418-4873-9E13-B0594D7483A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{3B5CDE2B-9418-4873-9E13-B0594D7483A3}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
diff --git a/BouncyCastle.AxCrypt/Contributors.html b/BouncyCastle.AxCrypt/Contributors.html
new file mode 100644
index 0000000..68ca699
--- /dev/null
+++ b/BouncyCastle.AxCrypt/Contributors.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+	<head>
+		<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+		<title>Contributors</title>
+	</head>
+	<body>
+		<h2>The Bouncy Castle Cryptographic C#® API</h2>
+		<h3>Contributors:</h3>
+		<p>The following people have contributed to the C# Bouncy Castle Cryptography 
+			Package.</p>
+		<p>Thanks, may your castles never deflate!</p>
+		<ul>
+			<li>
+				<p>Kaiser Yang <kaiseryang&#064yahoo.com> - initial port of the lightweight 
+					API and ASN.1 library. Finding BigInteger loop problem.</p>
+			</li>
+			<li>
+				<p>Asier Murciego <a.murciego&#064captiva-sys.es> - Further patching to 
+					BigInteger library.</p>
+			</li>
+			<li>
+				<p>Megan Woods <megan.woods&#064widestreet.com.au> - X509 certificate 
+					generation, RSA/DSA digest signature classes.</p>
+			</li>
+			<li>
+				<p>David Del Vecchio <ddelvecc&#064virginia.edu> - patches to RSA Pkcs1 
+					Signature generation OID issues, help with clarifications on DateTime and 
+					certificates.</p>
+			</li>
+			<li>
+				<p>Nelson Fernandez <nelson-bc&#064kpanic.com.ar> - patches to allow 
+					compilation under mono.</p>
+			</li>
+			<li>
+				<p>Paulo Soares <psoares&#064consiste.pt> - patches to X509CertificateParser, 
+					C# port of JZlib plus inflater/deflater streams, C# port of Apache BZip2 
+					classes.</p>
+			</li>
+			<li>
+				<p>Pawel Niewiadomski <11110000b&#064gmail.com> - patches for X509 and CMS, 
+					unit test for time classes.</p>
+			</li>
+			<li>
+				<p>Jesper Johansen <jesper&#064hc.jay.net> - bug fix for DerT61String 
+					encodings.</p>
+			</li>
+			<li>
+				<p>Adam Sternberg <agsternberg&#064gmail.com> - identified problem with 
+					generation of PGP public keyrings.</p>
+			</li>
+			<li>
+				<p>Kirill Zhuklinets <zhuklinets_k&#064gaz-is.ru> - initial submission of 
+					bulk of Asn1.Esf classes (RFC 3126).</p>
+			</li>
+			<li>
+				<p>Dr Andrew Gray <andrew.gray&#064rcrt.co.uk> - identified problem with 
+					BigInteger.ModPow for negative exponents.</p>
+			</li>
+			<li>
+				<p>Mauricio Ulate <mulate&#064gmail.com> - identified problem with non-ASCII 
+					pass phrases in PGP.</p>
+			</li>
+			<li>
+				<p>John Allberg <John.Allberg&#064teliasonera.com> - initial implementation 
+					of CryptoApiRandomGenerator.</p>
+			</li>
+			<li>
+				<p>Mattias Öhrn <mattias.ohrn&#064gmail.com> - identified problem with 
+					Pkcs12Store.Save and provided fix.</p>
+			</li>
+			<li>
+				<p>Jen Andre <jandre&#064gmail.com> - initial implementation of 
+					case-insensitive searches for PGP keyrings.</p>
+			</li>
+			<li>
+				<p>#Cyrille37# <cyrille37&#064gmail.com> - identified problem with 
+					BigInteger.ModInverse for negative values.</p>
+			</li>
+			<li>
+				<p>David Reis Jr <davidreis&#064yahoo.com> - bug fix for X509CrlStoreSelector 
+					handling of NextUpdate, fix handling of null parameters for DSA in key 
+					factories, initial port of Pkix namespace and supporting tests.
+				</p>
+			</li>
+			<li>
+				<p>Ivan Peev <ivan.peev&#064cozyroc.com> - bug fix for version string 
+					displayed in PGP armored output.</p>
+			</li>
+			<li>
+				<p>Hector Ornelas Aciga <hector.ornelas&#064sat.gob.mx> - patch to add support for PKCS#5 Scheme 2 keys.</p>
+			</li>
+			<li>
+				<p>Tom Van Holle <tvh&#064dsoft.be> - patch to add new class: Pkcs10CertificationRequestDelaySigned.</p>
+			</li>
+			<li>
+				<p>Kalev Lember <kalev&#064smartlink.ee> - patch to fix compilation problem under Mono 2.8+.</p>
+			</li>
+			<li>
+				<p>Kyle Hamilton <kyanha.bouncycastle&#064kyanha.net> - identified problem with BigInteger.Multiply, patch for MiscPemGenerator infinite recursion.</p>
+			</li>
+			<li>
+				<p>Atanas Krachev <akrachev&#064gmail.com> - added support for revocation signatures in OpenPGP.</p>
+			</li>
+			<li>
+				<p>Torsten Moschny <t.moschny&#064web.de> - identified problem where PrivateKeyFactory/PublicKeyFactory failed to preserve publicKeyParamSet for EC keys.</p>
+			</li>
+			<li>
+				<p>Thomas Heggelund <the&#064dips.no> - identified problem with RSAParameters fields requiring zero-byte padding to satisfy .NET.</p>
+			</li>
+			<li>
+				<p>Laszlo Magyar <lmagyar1973&#064gmail.com> - patch to fix problem with SubjectDirectoryAttributes constructor.</p>
+			</li>
+			<li>
+				<p>Tim Whittington (https://github.com/timw) - ports of ChaCha, GMAC, Memoable, Poly1305, Skein, SM3, Threefish, XSalsa20. Registerised Salsa20 core.</p>
+			</li>
+			<li>
+				<p>Oscar Jacobsson (https://github.com/OscarAyoy) - patch to fix DerEnumerated constructor (including test coverage).</p>
+			</li>
+		</ul>
+	</body>
+</html>
diff --git a/BouncyCastle.AxCrypt/License.html b/BouncyCastle.AxCrypt/License.html
new file mode 100644
index 0000000..1c5c7b0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/License.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <meta content="text/html; charset=ISO-8859-1"
+ http-equiv="content-type">
+  <title>License</title>
+</head>
+<body>
+<h2>The Bouncy Castle Cryptographic C#® API</h2>
+<h3>License:</h3>
+The Bouncy Castle License<br>
+Copyright (c) 2000-2014 The Legion of the Bouncy Castle Inc.
+(http://www.bouncycastle.org)<br>
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"), to deal in the
+Software without restriction, including without limitation the rights to use, copy, modify, merge,
+publish, distribute, sub license, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:<br>
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.<br>
+<span style="font-weight: bold;">THE SOFTWARE IS PROVIDED "AS IS",
+WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">PURPOSE AND NONINFRINGEMENT. IN NO
+EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER</span><br
+ style="font-weight: bold;">
+<span style="font-weight: bold;">DEALINGS IN THE SOFTWARE.<br>
+<br>
+</span>
+</body>
+</html>
diff --git a/BouncyCastle.AxCrypt/NBuild.build b/BouncyCastle.AxCrypt/NBuild.build
new file mode 100644
index 0000000..e22c35d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/NBuild.build
@@ -0,0 +1,247 @@
+<?xml version="1.0"?>
+<project name="bccrypto-csharp" default="compile-release" basedir=".">
+
+  <!-- Source control properties -->
+  <property name="GITURL" value="bcgit at git.bouncycastle.org:bc-csharp" />
+  <property name="GITCMD" value="C:/Program Files (x86)/Git/bin/git.exe" />
+
+  <property name="api-debugpath" value="./api/bin/debug" />
+  <property name="api-releasepath" value="./api/bin/release" />
+  <property name="api-srcpath" value="./src" />
+  <property name="bzip2-srcpath" value="./bzip2/src" />
+  <property name="test-srcpath" value="./test/src" />
+  <property name="test-datapath" value="./test/data" />
+  <property name="test-libpath" value="./test/lib" />
+  <property name="test-binpath" value="./test/bin"/>
+  <property name="dist-path" value="./dist"/>
+
+  <!-- Version -->
+  <property name="version" value="1.8.0-beta.4"/>
+  <property name="name" value="BouncyCastle.Crypto"/>
+
+  <property name="OPTIONAL_STRONG_NAME" value="" />
+  <if test="${property::exists('use-strong-name') and use-strong-name}">
+    <echo>Compile targets will be signed using keyfile ../BouncyCastle.snk</echo>
+    <property name="OPTIONAL_STRONG_NAME" value=";STRONG_NAME" />
+  </if>
+
+  <target name="init">
+    <call target="set-framework-props" />
+  </target>
+
+  <target name="set-framework-props">
+    <if test="${not(target::exists('set-'+framework::get-target-framework()+'-framework-props'))}">
+      <fail message="Unsupported framework: '${framework::get-target-framework()}'." />
+    </if>
+    <call target="set-${framework::get-target-framework()}-framework-props" />
+  </target>
+  <target name="set-mono-1.0-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="dll.mdb" />
+    <property name="enable-nostdlib" value="false" />
+    <property name="nunit-console" value="nunit-console" />
+    <property name="switch" value="-" />
+  </target>
+  <target name="set-mono-2.0-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="dll.mdb" />
+    <property name="enable-nostdlib" value="false" />
+    <property name="nunit-console" value="nunit-console" />
+    <property name="switch" value="-" />
+  </target>
+  <target name="set-mono-3.5-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="dll.mdb" />
+    <property name="enable-nostdlib" value="false" />
+    <property name="nunit-console" value="nunit-console" />
+    <property name="switch" value="-" />
+  </target>
+  <target name="set-mono-4.0-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="dll.mdb" />
+    <property name="enable-nostdlib" value="false" />
+    <property name="nunit-console" value="nunit-console" />
+    <property name="switch" value="-" />
+  </target>
+  <target name="set-net-1.1-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-net-2.0-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-net-3.5-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-net-4.0-framework-props">
+    <property name="compile-defines" value="NET_1_1" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-netcf-1.0-framework-props">
+    <property name="compile-defines" value="NETCF_1_0" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-netcf-2.0-framework-props">
+    <property name="compile-defines" value="NETCF_2_0" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-silverlight-2.0-framework-props">
+    <property name="compile-defines" value="SILVERLIGHT" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-silverlight-3.0-framework-props">
+    <property name="compile-defines" value="SILVERLIGHT" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+  <target name="set-silverlight-4.0-framework-props">
+    <property name="compile-defines" value="SILVERLIGHT" />
+    <property name="debug-extension" value="pdb" />
+    <property name="enable-nostdlib" value="true" />
+    <property name="nunit-console" value="nunit-console.exe" />
+    <property name="switch" value="/" />
+  </target>
+
+  <target name="clean">
+    <delete failonerror="false" dir="./api" />
+    <delete failonerror="false" dir="${dist-path}" />
+    <delete failonerror="false" dir="${test-binpath}" />
+    <delete failonerror="false" file="./TestResult.xml" />
+  </target>
+
+  <!-- Compile api in debug mode and compile tests -->
+  <target name="compile-debug" depends="init">
+    <echo message="Compiling Debug"/>
+    <echo message="Compiling API in debug mode."/>
+    <mkdir dir="${api-debugpath}"/>
+    <csc target="library" noconfig="true" nostdlib="${enable-nostdlib}" output="${api-debugpath}/${name}.dll"
+      verbose="false" debug="true" define="${compile-defines}${OPTIONAL_STRONG_NAME}">
+      <sources>
+        <include name="${api-srcpath}/**/*.cs"/>
+        <include name="${bzip2-srcpath}/**/*.cs"/>
+      </sources>
+      <references>
+        <include name="mscorlib.dll"/>
+        <include name="System.dll"/>
+      </references>
+    </csc>
+
+    <copy todir="${test-binpath}">
+      <fileset basedir="${test-libpath}">
+        <include name="*.dll" />
+      </fileset>
+    </copy>
+    <copy file="${api-debugpath}/${name}.dll" tofile="${test-binpath}/${name}.dll" />
+    <copy file="${api-debugpath}/${name}.${debug-extension}"
+        tofile="${test-binpath}/${name}.${debug-extension}" />
+
+    <echo message="Compiling Tests."/>
+    <mkdir dir="${api-debugpath}"/>
+    <csc target="library" noconfig="true" nostdlib="${enable-nostdlib}" output="${test-binpath}/BCTest.dll"
+      verbose="false" debug="true" define="${compile-defines}${OPTIONAL_STRONG_NAME}">
+      <sources>
+        <include name="${test-srcpath}/**/*.cs"/>
+      </sources>
+      <resources prefix="crypto" dynamicprefix="true">
+        <include name="${test-datapath}/**/*.*"/>
+        <exclude name="${test-datapath}/**/README.txt"/>
+        <exclude name="${test-datapath}/tls/*.tmpl"/>
+      </resources>
+      <references>
+        <include name="mscorlib.dll"/>
+        <include name="System.dll"/>
+        <include name="${test-libpath}/*.dll"/>
+        <include name="${test-binpath}/${name}.dll"/>
+      </references>
+    </csc>
+  </target>
+
+  <!-- Compile Release.-->
+  <target name="compile-release" depends="init">
+    <echo message="Compiling Release"/>
+    <echo message="Compiling API in release mode."/>
+    <mkdir dir="${api-releasepath}"/>
+    <csc target="library" noconfig="true" nostdlib="${enable-nostdlib}" output="${api-releasepath}/${name}.dll"
+      verbose="false" debug="false" optimize="true" define="${compile-defines}${OPTIONAL_STRONG_NAME}">
+      <sources>
+        <include name="${api-srcpath}/**/*.cs"/>
+        <include name="${bzip2-srcpath}/**/*.cs"/>
+      </sources>
+      <references>
+        <include name="mscorlib.dll"/>
+        <include name="System.dll"/>
+      </references>
+    </csc>
+  </target>
+
+  <!-- Make distribution.-->
+  <target name="dist" depends="init">
+    <echo message="Building signed assemblies for release ${version}"/>
+    <mkdir dir="${dist-path}"/>
+
+    <exec program="${GITCMD}" verbose="true" workingdir="..">
+      <arg value="archive" />
+      <arg line="--format zip" />
+      <arg value="--output" />
+      <arg path="${dist-path}/bccrypto-csharp-${version}-src.zip" />
+      <arg value="--prefix" />
+      <arg value="bccrypto-csharp-${version}/" />
+      <arg value="--remote" />
+      <arg value="${GITURL}" />
+      <arg value="release-${version}" />
+      <arg value="-9" />
+    </exec>
+
+    <unzip zipfile="${dist-path}/bccrypto-csharp-${version}-src.zip" todir="${dist-path}/src" />
+
+    <csc target="library" noconfig="true" nostdlib="${enable-nostdlib}" output="${dist-path}/${name}.dll"
+      verbose="false" debug="false" optimize="true" define="${compile-defines};STRONG_NAME">
+      <sources>
+        <include name="${dist-path}/src/bccrypto-csharp-${version}/crypto/${api-srcpath}/**/*.cs"/>
+        <include name="${dist-path}/src/bccrypto-csharp-${version}/crypto/${bzip2-srcpath}/**/*.cs"/>
+      </sources>
+      <references>
+        <include name="mscorlib.dll"/>
+        <include name="System.dll"/>
+      </references>
+    </csc>
+    <zip zipfile="${dist-path}/bccrypto-csharp-${version}-bin.zip" ziplevel="9">
+      <fileset basedir="${dist-path}">
+        <include name="${name}.dll" />
+      </fileset>
+    </zip>
+
+  </target>
+
+  <target name="all" depends="compile-debug, compile-release"/>
+
+  <target name="test" depends="compile-debug">
+    <exec program="${nunit-console}" commandline="${switch}labels testcfg.nunit" workingdir="${nant.project.basedir}"></exec>
+  </target>
+
+</project>
diff --git a/BouncyCastle.AxCrypt/ReadMe-AxCrypt.txt b/BouncyCastle.AxCrypt/ReadMe-AxCrypt.txt
new file mode 100644
index 0000000..e69de29
diff --git a/BouncyCastle.AxCrypt/Readme.html b/BouncyCastle.AxCrypt/Readme.html
new file mode 100644
index 0000000..2660d4a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/Readme.html
@@ -0,0 +1,455 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+	<head>
+		<title>Notes</title>
+		<meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">
+	</head>
+	<body>
+		<h2><a class="mozTocH2" name="mozTocId533031"></a>The Bouncy Castle Cryptographic 
+			C#� API</h2>
+		<h3><a class="mozTocH3" name="mozTocId685176"></a>Contents:<br>
+		</h3>
+		<ol id="mozToc">
+			<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId533031">The Bouncy 
+					Castle Cryptographic C#� API</a>
+		<ol>
+			<li>
+		<ol>
+			<li>
+				<a href="#mozTocId685176">Contents: </a>
+			<li>
+				<a href="#mozTocId66345">License & Contributors:</a>
+			<li>
+				<a href="#mozTocId575388">Features:</a>
+			<li>
+				<a href="#mozTocId211208">How To Build.</a>
+			<li>
+				<a href="#mozTocId245743">The Source:</a>
+			<li>
+				<a href="#mozTocId326820">Documentation:</a>
+			<li>
+				<a href="#mozTocId358608">For first time users.</a>
+			<li>
+				<a href="#mozTocId3413">Notes:</a>
+		<ol>
+			<li>
+				<a href="#mozTocId85313">Release 1.7</a>
+			<li>
+				<a href="#mozTocId85312">Release 1.6.1</a>
+			<li>
+				<a href="#mozTocId85311">Release 1.6</a>
+			<li>
+				<a href="#mozTocId85310">Release 1.5</a>
+			<li>
+				<a href="#mozTocId85309">Release 1.4</a>
+			<li>
+				<a href="#mozTocId85308">Release 1.3</a>
+			<li>
+				<a href="#mozTocId85307">Release 1.2</a>
+			<li>
+				<a href="#mozTocId85306">Release 1.1</a>
+			<li>
+				<a href="#mozTocId85305">Release 1.0</a>
+			<li>
+				<a href="#mozTocId85304">Tuesday Febuary 1, 2005</a>
+			<li>
+				<a href="#mozTocId498363">Sunday December 12, 2004</a></li>
+		</ol>
+		<li>
+			<a href="#mozTocId948186">Trademarks. </a>
+		</li>
+		</ol> </li> </ol> </li> </ol>
+		<br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<h3><a class="mozTocH3" name="mozTocId66345"></a>License & Contributors:</h3>
+		See <a href="License.html">License</a> & <a href="Contributors.html">Contributors</a>
+		files.<br>
+		 <br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<br>
+		<h3><a class="mozTocH3" name="mozTocId575388"></a>Features:</h3>
+		<ul>
+			<li>
+			Generation and parsing of PKCS-12 files.
+			<li>
+			X.509: Generators and parsers for V1 and V3 certificates, V2 CRLs and attribute 
+			certificates.
+			<li>
+			PBE algorithms supported by PbeUtilities: PBEwithMD2andDES-CBC, 
+			PBEwithMD2andRC2-CBC, PBEwithMD5andDES-CBC, PBEwithMD5andRC2-CBC, 
+			PBEwithSHA1andDES-CBC, PBEwithSHA1andRC2-CBC, PBEwithSHA-1and128bitRC4, 
+			PBEwithSHA-1and40bitRC4, PBEwithSHA-1and3-keyDESEDE-CBC, 
+			PBEwithSHA-1and2-keyDESEDE-CBC, PBEwithSHA-1and128bitRC2-CBC, 
+			PBEwithSHA-1and40bitRC2-CBC, PBEwithHmacSHA-1, PBEwithHmacSHA-224, 
+			PBEwithHmacSHA-256, PBEwithHmacRIPEMD128, PBEwithHmacRIPEMD160, and 
+			PBEwithHmacRIPEMD256.
+			<li>
+			Signature algorithms supported by SignerUtilities: MD2withRSA, MD4withRSA, 
+			MD5withRSA, RIPEMD128withRSA, RIPEMD160withECDSA, RIPEMD160withRSA, 
+			RIPEMD256withRSA, SHA-1withRSA, SHA-224withRSA, SHA-256withRSAandMGF1, 
+			SHA-384withRSAandMGF1, SHA-512withRSAandMGF1, SHA-1withDSA, and SHA-1withECDSA.
+			<li>
+			Symmetric key algorithms: AES, Blowfish, Camellia, CAST5, CAST6, DESede, DES, 
+			GOST28147, HC-128, HC-256, IDEA, ISAAC, NaccacheStern, Noekeon, RC2, RC4, 
+			RC5-32, RC5-64, RC6, Rijndael, Salsa20, SEED, Serpent, Skipjack, TEA/XTEA,
+			Twofish and VMPC.
+			<li>
+			Symmetric key modes: CBC, CFB, CTS, GOFB, OFB, OpenPGPCFB, and SIC (or CTR).
+			<li>
+			Symmetric key paddings: ISO10126d2, ISO7816d4, PKCS-5/7, TBC, X.923, and Zero 
+			Byte.
+			<li>
+			Asymmetric key algorithms: RSA (with blinding), ElGamal, DSA, and ECDSA.
+			<li>
+			Asymmetric key paddings/encodings: ISO9796d1, OAEP, and PKCS-1.
+			<li>
+			AEAD block cipher modes: CCM, EAX, and GCM.
+			<li>
+			Digests: GOST3411, MD2, MD4, MD5, RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320, 
+			SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, Tiger, and Whirlpool.
+			<li>
+			Signer mechanisms: DSA, ECDSA, ECGOST3410, GOST3410, ISO9796d2, PSS, RSA.
+			<li>
+			Key Agreement: Diffie-Hellman, EC-DH, SRP-6a.
+			<li>
+			Macs: CBCBlockCipher, CFBBlockCipher, GOST28147, HMac, ISO9797 Alg. 3, SipHash, VMPCMAC.
+			<li>
+			PBE generators: PKCS-12, and PKCS-5 - schemes 1 and 2.
+			<li>
+			OpenPGP (RFC 2440)
+			<li>
+			Cryptographic Message Syntax (CMS, RFC 3852), including streaming API.
+			<li>
+			Online Certificate Status Protocol (OCSP, RFC 2560).
+			<li>
+			Time Stamp Protocol (TSP, RFC 3161).
+			<li>
+			Elliptic Curve Cryptography (support for F2m and Fp curves).
+			<li>
+				Reading/writing of PEM files, including RSA and DSA keys, with a variety of 
+				encryptions.
+			</li>
+			<li>PKIX certificate path validation</li>
+		</ul>
+		<br>
+		<p><b>Porting notes from the old ASN.1 library</b> For the most part code using the 
+			old subset of ASN.1 classes should be easy to transfer, providing the following 
+			changes are made:
+		</p>
+		<ul>
+			<li>
+			DERObject becomes Asn1Object
+			<li>
+			DEREncodable becomes Asn1Encodable
+			<li>
+			GetDERObject() becomes ToAsn1Object()
+			<li>
+			BERConstructedOctetString becomes BerOctetString
+			<li>
+			If you were using the older mutable DERConstructedSequence/Set and 
+			BERConstructedSequence, use an Asn1EncodableVector in conjunction with 
+			DerSequence/Set and BerSequence
+			<li>
+			BERInputStream and DERInputStream are replaced with Asn1InputStream
+			<li>
+				AsymmetricKeyParameter is now in the Org.Bouncycastle.Crypto namespace</li>
+		</ul>
+		<br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<h3><a class="mozTocH3" name="mozTocId211208"></a>How To Build.</h3>
+		<p>
+			The BC C# API uses NAnt (<a href="http://nant.sourceforge.net/">http://nant.sourceforge.net</a>) 
+			to provide a platform independent build environment (suggested version NAnt 0.90).
+			There is also a solution file for Visual Studio, and for MonoDevelop. The API works
+			with .NET Framework 1.1 and above. It has been successfully built and tested with Mono
+			versions from 1.1.13 onwards. The source code can be built for .NET Compact Framework 1.0
+			by setting the compilation flag NETCF_1_0, or .NET Compact Framework 2.0 by setting NETCF_2_0,
+			or Silverlight 2 by setting SILVERLIGHT.
+		</p>
+		Using a command prompt (DOS window), cd into the 'crypto' folder of this 
+		distribution.<br>
+		<br>
+		<span style="FONT-WEIGHT: bold">Use,</span><br>
+		<ul>
+			<li>
+				'<span style="FONT-WEIGHT: bold">nant</span>' without arguments to compile 
+			debug code, the tests and run the tests.
+			<li>
+				'<span style="FONT-WEIGHT: bold">nant compile-release</span>' to compile 
+			release code.
+			<li>
+				'<span style="FONT-WEIGHT: bold">nant compile-debug</span>' to compile 
+			debug code.
+			<LI>
+				'<SPAN style="FONT-WEIGHT: bold">nant test</SPAN>' to run the included unit 
+				tests (using NUnit; you may need to edit the build file to set the location 
+				where NUnit is installed).</LI>
+		</ul>
+		<P>
+			<span style="FONT-WEIGHT: bold">Output:</span><br>
+			<br>
+			    The compiled API can be found in the 'api/bin/release' & 
+			'api/bin/debug' directories.<br>
+			    The compiled tests can be found in the 'test/bin' directory 
+			(by default a debug build is used for testing).<br>
+		<P>
+			<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<P></P>
+		<h3><a class="mozTocH3" name="mozTocId245743"></a><span style="FONT-WEIGHT: bold">The Source:</span></h3>
+		Source code can be found in the 'src'directory.<br>
+		<br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<h3><a class="mozTocH3" name="mozTocId326820"></a><span style="FONT-WEIGHT: bold"></span>Documentation:</h3>
+		<P>There is limited documentation available at the moment. Some of the source 
+			contains XML comments, but this is a work in progress. We will be working to 
+			improve this now that 1.0 is out the door.</P>
+		<P>
+			<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<P></P>
+		<h3><a class="mozTocH3" name="mozTocId358608"></a>For first time users.</h3>
+		 <span style="FONT-WEIGHT: bold">Java� heritage,</span><br>
+		<br>
+		The Bouncy Castle C# API is a port of the Bouncy Castle Java APIs. 
+		Approximately %80 of the functionality in the Java build has now been ported. 
+		For the most part, the naming conventions of the .NET platform have been 
+		adopted. The C# API is constantly kept uptodate with bug fixes and new test 
+		cases from the Java build (and vice versa sometimes), thus benefitting from the 
+		large user base and real-world use the Java version has seen.<br>
+		<br>
+		<span style="FONT-WEIGHT: bold">Please consider.</span><br>
+		<br>
+		The Bouncy Castle C# API is a library of transformations that when combined 
+		properly will enable developers to create standard conforming cryptographic 
+		systems. In order to use this API you must have some knowledge of how to build 
+		cryptographic systems, namely what transformations to use and the when, where 
+		and why of their use.<br>
+		Developing good cryptographic systems takes practice and understanding.<br>
+		<br>
+		There are many resources available online and in book shops; please use those 
+		to your advantage.<br>
+		<br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<h3><a class="mozTocH3" name="mozTocId3413"></a>Notes:</h3>
+		<H4><A class="mozTocH4" name="mozTocId85313"></A>Release 1.7, Thursday April 7, 2011</H4>
+<h5>Additional Features and Functionality</h5>
+<ul>
+<li>TLS now supports client authentication.</li>
+<li>TLS now supports compression.</li>
+<li>TLS now supports ECC cipher suites (RFC 4492).</li>
+<li>Library can now be built for Silverlight (2.0 and above).</li>
+<li>ASN.1 classes for CRMF (RFC 4211) and CMP (RFC 4210) have been added.</li>
+<li>Further performance improvements to GCM mode.</li>
+<li>BufferedBlockCipher will now always reset after a DoFinal().</li>
+<li>An IV can now be passed to an Iso9797Alg3Mac</li>
+</ul>
+<h5>Additional Notes</h5>
+<ul>
+<li>See list of resolved issues at
+<a href="http://www.bouncycastle.org/jira/secure/IssueNavigator.jspa?reset=true&&pid=10001&fixfor=10110&sorter/field=issuekey&sorter/order=DESC">
+Bouncy Castle JIRA C# 1.7</a></li>
+</ul>
+		<H4><A class="mozTocH4" name="mozTocId85312"></A>Release 1.6.1, Monday February 8, 2010</H4>
+<ul>
+<li>A point release to rectify some problems with the released assembly of 1.6 version.</li>
+</ul>
+		<H4><A class="mozTocH4" name="mozTocId85311"></A>Release 1.6, Thursday February 4, 2010</H4>
+<h5>Defects Fixed</h5>
+<ul>
+<li>X509DefaultEntryConverter was not recognising telephone number as a PrintableString field. This has been fixed.</li>
+<li>OpenPGP now supports UTF-8 in file names for literal data.</li>
+</ul>
+<h5>Security Advisory</h5>
+<ul>
+<li>This version has been specifically reviewed to eliminate possible timing attacks on algorithms such as GCM and CCM mode.</li>
+</ul>
+<h5>Additional Features and Functionality</h5>
+<ul>
+<li>Support for PSS signatures has been added to CMS.</li>
+<li>SubjectKeyIdentifier now supports both methods specified in RFC 3280, section 4.2.1.2 for generating the identifier.</li>
+<li>Performance of GCM mode has been greatly improved (on average 10x).</li>
+<li>Support for mac lengths of 96, 104, 112, and 120 bits has been added to existing support for 128 bits in GCMBlockCipher.</li>
+<li>Support for raw signatures has been extended to RSA, RSA-PSS and ECDSA. RSA support can be used in CmsSignedDataStreamGenerator to support signatures without signed attributes.</li>
+<li>Support for EC MQV has been added to the light weight API and the CMS library.</li>
+</ul>
+<h5>Additional Notes</h5>
+<ul>
+<li>See list of resolved issues at
+<a href="http://www.bouncycastle.org/jira/secure/IssueNavigator.jspa?reset=true&&pid=10001&fixfor=10100&sorter/field=issuekey&sorter/order=DESC">
+Bouncy Castle JIRA C# 1.6</a></li>
+</ul>
+		<H4><A class="mozTocH4" name="mozTocId85310"></A>Release 1.5, Tuesday August 18, 2009</H4>
+<h5>Defects Fixed</h5>
+<ul>
+<li>Correct the ASN.1 class for AuthorityInformationAccess.</li>
+<li>In the Bcpg libs, armored output now inserts the correct version string.</li>
+<li>EssCertIDv2 encoding now complies with RFC 5035.</li>
+<li>ECDSA now computes correct signatures for oversized hashes when the order of the base point is not a multiple of 8 in compliance with X9.62-2005.</li>
+<li>Standard name "DiffieHellman" is now supported in factory classes.</li>
+<li>Better support for equality tests for '#' encoded entries has been added to X509Name.</li>
+<li>'=' inside a X509Name was not being properly escaped. This has been fixed.</li>
+<li>ApplicationSpecific ASN.1 tags are now recognised in BER data. The GetObject() method now handles processing of arbitrary tags.</li>
+<li>Multiplication by negative powers of two is fixed in BigInteger.</li>
+<li>Multiple countersignature attributes are now correctly collected.</li>
+<li>Two bugs in HC-128 and HC-256 related to sign extension and byte swapping have been fixed. The implementations now pass the latest ecrypt vector tests.</li>
+</ul>
+<h5>Security Advisory</h5>
+<ul>
+<li>The effect of the sign extension bug was to decrease the key space the HC-128 and HC-256 ciphers were operating in and the byte swapping inverted every 32 bits of the generated stream. If you are using either HC-128 or HC-256 you must upgrade to this release.</li>
+</ul>
+<h5>Additional Features and Functionality</h5>
+<ul>
+<li>PKIX certificate path validation</li>
+<li>Accept duplicate PKCS#9 FriendlyName attributes in PKCS#12 keystore.</li>
+<li>Add support for PKCS#5 Scheme 2 keys.</li>
+<li>Camellia performance improved.</li>
+<li>A smaller version of Camellia, CamelliaLightEngine has also been added.</li>
+<li>CmsSignedData generation now supports SubjectKeyIdentifier as well as use of issuer/serial.</li>
+<li>A CMS PBE key holder for UTF8 keys has been added to the CMS API.</li>
+<li>Salt and iteration count can now be recovered from PasswordRecipientInformation.</li>
+<li>Support for reading and extracting personalised certificates in PGP Secret Key rings has been added.</li>
+<li>Support for EAC algorithms has been added to CMS.</li>
+<li>Asn1Dump now supports a verbose mode for displaying the contents of octet and bit strings.</li>
+<li>Support for the SRP-6a protocol has been added.</li>
+</ul>
+<h5>Additional Notes</h5>
+<ul>
+<li>See also the list of resolved issues at
+<a href="http://www.bouncycastle.org/jira/secure/IssueNavigator.jspa?reset=true&&pid=10001&fixfor=10080&sorter/field=issuekey&sorter/order=DESC">
+Bouncy Castle JIRA C# 1.5</a></li>
+</ul>
+		<H4><A class="mozTocH4" name="mozTocId85309"></A>Release 1.4, Thursday August 8, 2008</H4>
+<h5>Defects Fixed</h5>
+<ul>
+<li>The GeneralName string constructor now supports IPv4 and IPv6 address parsing.</li>
+<li>EAX mode was not handling non-zero offsetted data correctly and failing. This has been fixed.</li>
+<li>EAX mode ciphers were not resetting correctly after a DoFinal/Reset. This has been fixed.</li>
+<li>Some boolean parameters to IssuingDistributionPoint were being reversed. This has been fixed.</li><li>A zero length RDN would cause an exception in an X509Name. This has been fixed.</li>
+<li>Specifying a greater than 32bit length for a stream and relying on the default BcpgOutputStream resulted in corrupted data. This has been fixed.</li>
+<li>Pkcs7Padding validation would not fail if pad length was 0. This has been fixed.</li>
+<li>Signature creation time was not being properly initialised in new V4 PGP signature objects although the encoding was correct. This has been fixed.</li>
+<li>The '+' character can now be escaped or quoted in the constructor for X509Name.</li>
+<li>IV handling in CMS for SEED and Camellia was incorrect. This has been fixed.</li>
+<li>ASN.1 stream parser now throws exceptions for unterminated sequences.</li>
+<li>X509CertificateParser/X509CrlParser now handle multiple certificates/CRLs in streams that don't support seeking.</li>
+<li>The CertID class used by the TSP library was incomplete. This has been fixed</li>
+<li>\# is now properly recognised in the X509Name class.</li>
+<li>BigInteger.ModInverse was failing for negative values. This has been fixed.</li>
+<li>CMS API now supports RSASSA-PSS signatures with explicit salt length.</li>
+</ul>
+<h5>Additional Features and Functionality</h5>
+<ul>
+<li>ASN.1 libs now support high tag numbers.</li>
+<li>Galois/Counter Mode (GCM) has been added.</li>
+<li>The TSP API now supports parsing and validation of responses with V2 signing certificate entries.</li>
+<li>Unnecessary local ID attributes on certificates in PKCS12 files are now automatically removed.</li>
+<li>New Pkcs12StoreBuilder class supports generation of PKCS12 files with both certificates and keys protected by 3DES.</li>
+<li>Certifications associated with user attributes can now be created, verified and removed in OpenPGP.</li>
+<li>API support now exists for CMS countersignature reading and production.</li>
+<li>A new class LazyAsn1InputStream supports lazy evaluation of DER sequences and sets, considerably reducing memory requirements in some scenarios.</li>
+<li>KeyPurposeId class has been updated for RFC 4945.</li>
+<li>Initial support has been added for HP_CERTIFICATE_REQUEST in the TLS API.</li>
+<li>PGP example programs now handle blank names in literal data objects.</li>
+<li>The ProofOfPossession class now better supports the underlying ASN.1 structure.</li>
+</ul>
+<h5>Additional Notes</h5>
+<ul>
+<li>Due to problems for some users caused by the presence of the IDEA algorithm, an implementation is no
+longer included in the default assembly. Only the assembly named BouncyCastle.CryptoExt now includes IDEA.</li>
+<li>See also the list of resolved issues at
+<a href="http://www.bouncycastle.org/jira/secure/IssueNavigator.jspa?reset=true&&pid=10001&fixfor=10050&sorter/field=issuekey&sorter/order=DESC">
+Bouncy Castle JIRA C# 1.4</a></li>
+</ul>
+		<H4><A class="mozTocH4" name="mozTocId85308"></A>Release 1.3, Saturday December 8, 2007</H4>
+		<P>
+			ASN.1 stream parsing now handles definite length encodings efficiently.<br>
+			Buffering in the streaming CMS has been reworked. Throughput is now usually higher and the behaviour is more predictable.<br>
+			BcpgInputStream now handles data blocks in the 2**31->2**32-1 range.<br>
+			Some confusion over the parameters J and L in connection with Diffie-Hellman has been resolved.<br>
+			Added CryptoApiRandomGenerator, a wrapper for RNGCryptoServiceProvider.<br>
+			Added VMPC stream cipher, VMPCMAC and a VMPC-based implementation of IRandomGenerator.<br>
+			Added support in OpenPGP for fetching keyrings by case-insensitive user ID [#BMA-8].<br>
+			Fixed a vulnerability of CMS signatures that do not use signed attributes (Bleichenbacher RSA forgery).<br>
+			Fixed a bug causing second and later encrypted objects to be ignored in KeyBasedFileProcessor example.<br>
+			Fixed case-sensitivity issue with deletion from a PKCS#12 file.<br>
+			Fixed problem overwriting entities in a PKCS#12 file.<br>
+			Fixed PgpUtilities.MakeKeyFromPassPhrase for 8-bit characters [#BMA-13].<br>
+			Fixed duplicate certificate problem in Pkcs12Store.Save [#BMA-12].<br>
+			Fixed NAnt build under Mono [#BMA-10].<br>
+			Fixed BigInteger.ModPow for negative exponents [#BMA-7].<br>
+		</P>
+		<H4><A class="mozTocH4" name="mozTocId85307"></A>Release 1.2, Thursday July 5, 2007</H4>
+		<P>
+			Source now builds on .NET Compact Framework 1.0 (compilation flag NETCF_1_0).<br>
+			Release assembly now signed with a strong name.<br>
+			Added CCM and EAX block cipher modes.<br>
+			Added Noekeon block cipher.<br>
+			Added HC-128, HC-256, and ISAAC stream ciphers.<br>
+			Added RIPEMD160withECDSA signature algorithm.<br>
+			Added support for notation data signature subpackets to OpenPGP.<br>
+			Added support for parsing of experimental signatures to OpenPGP.<br>
+			Added the complete set of SEC-2 EC curves.<br>
+			Added support for implicit tagging to DerApplicationSpecific.<br>
+			Added remaining ASN.1 structures from RFC 3126 to Asn1.Esf namespace.<br>
+			Performance of ECDSA improved.<br>
+			Performance of ASN.1 stream parsing improved.<br>
+			Fixed default private key length for Diffie-Hellman parameters.<br>
+			Fixed DerT61String to correctly support 8-bit characters.<br>
+			Fixed duplicate attribute problem in Pkcs12Store.Save.<br>
+			Fixed a problem writing public keys in OpenPGP [#BMA-5].<br>
+		</P>
+		<H4><A class="mozTocH4" name="mozTocId85306"></A>Release 1.1, Friday May 4, 2007</H4>
+		<P>
+			Added support for writing DSA private keys, and more encodings, in OpenSsl 
+			(PemReader/PemWriter).<br>
+			Removed SharpZipLib dependency.<br>
+			Added RSA blinded signature classes.<br>
+			Added Asn1.IsisMtt namespace (ISIS-MTT ASN.1 classes).<br>
+			Added SEED block cipher engine.<br>
+			Added Salsa20 stream cipher engine.<br>
+			Performance optimisations for F2m elliptic curves.<br>
+			Fixed OpenPGP bug decrypting files with multiple types of encryption on the 
+			session key.<br>
+		</P>
+		<H4><A class="mozTocH4" name="mozTocId85305"></A>Release 1.0, Thursday January 18, 
+			2007</H4>
+		<P>
+			Implementations of CMS, OCSP, OpenPGP, and TSP.<br>
+			Elliptic Curves (F2m and Fp).<br>
+			A basic TLS client.<br>
+			PEM file reading and writing.<br>
+			Symmetric key algorithms: Camellia, GOST28147, NaccacheStern, and TEA/XTEA.<br>
+			Symmetric key modes: GOFB and OpenPGPCFB.<br>
+			Symmetric key paddings: ISO7816d4.<br>
+			Asymmetric key algorithms: RSA blinding.<br>
+			Digests: GOST3411 and Whirlpool.<br>
+			Macs: GOST28147 and ISO9797 Alg 3.<br>
+			Signer mechanisms: ECDSA, ECGOST3410, and GOST3410.<br>
+			...and many more features, bug fixes, and performance improvements.<br>
+		</P>
+		<H4><A class="mozTocH4" name="mozTocId85304"></A>Tuesday Febuary 1, 2005</H4>
+		<P>This is the second beta release of the Bouncy Castle API C# implementation.<BR>
+			Reliability improvement to ASN1InputStream.<BR>
+			The OID entries in SignerUtilities for RSA signature algorithms for SHA-256,<BR>
+			SHA-384, and SHA-512 were pointing creating the wrong signature objects.</P>
+		<h4><a class="mozTocH4" name="mozTocId498363"></a>Sunday December 12, 2004</h4>
+		This is the first beta release of the Bouncy Castle Cryptographic API C# 
+		implementation.<br>
+		The Legion of the Bouncy Castle would like to extend their thanks to all those 
+		who contributed to this API during the alpha stages of its development.<br>
+		Keep up the good work folks.<br>
+		Please send any questions or bug reports to <a href="mailto:%5Cdev-crypto-csharp at bouncycastle.org">
+			dev-crypto-csharp at bouncycastle.org</a><br>
+		<br>
+		<hr style="WIDTH: 100%; HEIGHT: 2px">
+		<h3><a class="mozTocH3" name="mozTocId948186"></a>Trademarks.<br>
+		</h3>
+		C#, .NET, and MSDN are Registered Trademarks of Microsoft. <a href="http://www.microsoft.com">
+			Microsoft.com</a><br>
+		Java is a Registered Trademark of Sun Microsystems. <a href="http://www.sun.com">Sun 
+			Microsystems</a><br>
+		<br>
+		<br>
+		<div style="TEXT-ALIGN: center">� 2007 Legion of the Bouncy Castle<br>
+		</div>
+	</body>
+</html>
diff --git a/BouncyCastle.AxCrypt/bzip2/src/BZip2Constants.cs b/BouncyCastle.AxCrypt/bzip2/src/BZip2Constants.cs
new file mode 100644
index 0000000..4a5442d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/bzip2/src/BZip2Constants.cs
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron at aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+using System;
+
+namespace Org.BouncyCastle.Apache.Bzip2
+{
+    /**
+    * Base class for both the compress and decompress classes.
+    * Holds common arrays, and static data.
+    *
+    * @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+    */
+    public class BZip2Constants {
+
+        public const int baseBlockSize = 100000;
+        public const int MAX_ALPHA_SIZE = 258;
+        public const int MAX_CODE_LEN = 23;
+        public const int RUNA = 0;
+        public const int RUNB = 1;
+        public const int N_GROUPS = 6;
+        public const int G_SIZE = 50;
+        public const int N_ITERS = 4;
+        public const int MAX_SELECTORS = (2 + (900000 / G_SIZE));
+        public const int NUM_OVERSHOOT_BYTES = 20;
+
+        public static readonly int[] rNums = {
+            619, 720, 127, 481, 931, 816, 813, 233, 566, 247,
+            985, 724, 205, 454, 863, 491, 741, 242, 949, 214,
+            733, 859, 335, 708, 621, 574, 73, 654, 730, 472,
+            419, 436, 278, 496, 867, 210, 399, 680, 480, 51,
+            878, 465, 811, 169, 869, 675, 611, 697, 867, 561,
+            862, 687, 507, 283, 482, 129, 807, 591, 733, 623,
+            150, 238, 59, 379, 684, 877, 625, 169, 643, 105,
+            170, 607, 520, 932, 727, 476, 693, 425, 174, 647,
+            73, 122, 335, 530, 442, 853, 695, 249, 445, 515,
+            909, 545, 703, 919, 874, 474, 882, 500, 594, 612,
+            641, 801, 220, 162, 819, 984, 589, 513, 495, 799,
+            161, 604, 958, 533, 221, 400, 386, 867, 600, 782,
+            382, 596, 414, 171, 516, 375, 682, 485, 911, 276,
+            98, 553, 163, 354, 666, 933, 424, 341, 533, 870,
+            227, 730, 475, 186, 263, 647, 537, 686, 600, 224,
+            469, 68, 770, 919, 190, 373, 294, 822, 808, 206,
+            184, 943, 795, 384, 383, 461, 404, 758, 839, 887,
+            715, 67, 618, 276, 204, 918, 873, 777, 604, 560,
+            951, 160, 578, 722, 79, 804, 96, 409, 713, 940,
+            652, 934, 970, 447, 318, 353, 859, 672, 112, 785,
+            645, 863, 803, 350, 139, 93, 354, 99, 820, 908,
+            609, 772, 154, 274, 580, 184, 79, 626, 630, 742,
+            653, 282, 762, 623, 680, 81, 927, 626, 789, 125,
+            411, 521, 938, 300, 821, 78, 343, 175, 128, 250,
+            170, 774, 972, 275, 999, 639, 495, 78, 352, 126,
+            857, 956, 358, 619, 580, 124, 737, 594, 701, 612,
+            669, 112, 134, 694, 363, 992, 809, 743, 168, 974,
+            944, 375, 748, 52, 600, 747, 642, 182, 862, 81,
+            344, 805, 988, 739, 511, 655, 814, 334, 249, 515,
+            897, 955, 664, 981, 649, 113, 974, 459, 893, 228,
+            433, 837, 553, 268, 926, 240, 102, 654, 459, 51,
+            686, 754, 806, 760, 493, 403, 415, 394, 687, 700,
+            946, 670, 656, 610, 738, 392, 760, 799, 887, 653,
+            978, 321, 576, 617, 626, 502, 894, 679, 243, 440,
+            680, 879, 194, 572, 640, 724, 926, 56, 204, 700,
+            707, 151, 457, 449, 797, 195, 791, 558, 945, 679,
+            297, 59, 87, 824, 713, 663, 412, 693, 342, 606,
+            134, 108, 571, 364, 631, 212, 174, 643, 304, 329,
+            343, 97, 430, 751, 497, 314, 983, 374, 822, 928,
+            140, 206, 73, 263, 980, 736, 876, 478, 430, 305,
+            170, 514, 364, 692, 829, 82, 855, 953, 676, 246,
+            369, 970, 294, 750, 807, 827, 150, 790, 288, 923,
+            804, 378, 215, 828, 592, 281, 565, 555, 710, 82,
+            896, 831, 547, 261, 524, 462, 293, 465, 502, 56,
+            661, 821, 976, 991, 658, 869, 905, 758, 745, 193,
+            768, 550, 608, 933, 378, 286, 215, 979, 792, 961,
+            61, 688, 793, 644, 986, 403, 106, 366, 905, 644,
+            372, 567, 466, 434, 645, 210, 389, 550, 919, 135,
+            780, 773, 635, 389, 707, 100, 626, 958, 165, 504,
+            920, 176, 193, 713, 857, 265, 203, 50, 668, 108,
+            645, 990, 626, 197, 510, 357, 358, 850, 858, 364,
+            936, 638
+        };
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/bzip2/src/CBZip2InputStream.cs b/BouncyCastle.AxCrypt/bzip2/src/CBZip2InputStream.cs
new file mode 100644
index 0000000..7411f0a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/bzip2/src/CBZip2InputStream.cs
@@ -0,0 +1,919 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron at aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Apache.Bzip2
+{
+	/**
+    * An input stream that decompresses from the BZip2 format (with the file
+    * header chars) to be read as any other stream.
+    *
+    * @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+    *
+    * <b>NB:</b> note this class has been modified to read the leading BZ from the
+    * start of the BZIP2 stream to make it compatible with other PGP programs.
+    */
+    public class CBZip2InputStream : Stream 
+	{
+        private static void Cadvise() {
+            //System.out.Println("CRC Error");
+            //throw new CCoruptionError();
+        }
+
+//        private static void BadBGLengths() {
+//            Cadvise();
+//        }
+//
+//        private static void BitStreamEOF() {
+//            Cadvise();
+//        }
+
+        private static void CompressedStreamEOF() {
+            Cadvise();
+        }
+
+        private void MakeMaps() {
+            int i;
+            nInUse = 0;
+            for (i = 0; i < 256; i++) {
+                if (inUse[i]) {
+                    seqToUnseq[nInUse] = (char) i;
+                    unseqToSeq[i] = (char) nInUse;
+                    nInUse++;
+                }
+            }
+        }
+
+        /*
+        index of the last char in the block, so
+        the block size == last + 1.
+        */
+        private int  last;
+
+        /*
+        index in zptr[] of original string after sorting.
+        */
+        private int  origPtr;
+
+        /*
+        always: in the range 0 .. 9.
+        The current block size is 100000 * this number.
+        */
+        private int blockSize100k;
+
+        private bool blockRandomised;
+
+        private int bsBuff;
+        private int bsLive;
+        private CRC mCrc = new CRC();
+
+        private bool[] inUse = new bool[256];
+        private int nInUse;
+
+        private char[] seqToUnseq = new char[256];
+        private char[] unseqToSeq = new char[256];
+
+        private char[] selector = new char[BZip2Constants.MAX_SELECTORS];
+        private char[] selectorMtf = new char[BZip2Constants.MAX_SELECTORS];
+
+        private int[] tt;
+        private char[] ll8;
+
+        /*
+        freq table collected to save a pass over the data
+        during decompression.
+        */
+        private int[] unzftab = new int[256];
+
+        private int[][] limit = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+        private int[][] basev = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+        private int[][] perm = InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+        private int[] minLens = new int[BZip2Constants.N_GROUPS];
+
+        private Stream bsStream;
+
+        private bool streamEnd = false;
+
+        private int currentChar = -1;
+
+        private const int START_BLOCK_STATE = 1;
+        private const int RAND_PART_A_STATE = 2;
+        private const int RAND_PART_B_STATE = 3;
+        private const int RAND_PART_C_STATE = 4;
+        private const int NO_RAND_PART_A_STATE = 5;
+        private const int NO_RAND_PART_B_STATE = 6;
+        private const int NO_RAND_PART_C_STATE = 7;
+
+        private int currentState = START_BLOCK_STATE;
+
+        private int storedBlockCRC, storedCombinedCRC;
+        private int computedBlockCRC, computedCombinedCRC;
+
+        int i2, count, chPrev, ch2;
+        int i, tPos;
+        int rNToGo = 0;
+        int rTPos  = 0;
+        int j2;
+        char z;
+
+        public CBZip2InputStream(Stream zStream) {
+            ll8 = null;
+            tt = null;
+            BsSetStream(zStream);
+            Initialize();
+            InitBlock();
+            SetupBlock();
+        }
+
+        internal static int[][] InitIntArray(int n1, int n2) {
+            int[][] a = new int[n1][];
+            for (int k = 0; k < n1; ++k) {
+                a[k] = new int[n2];
+            }
+            return a;
+        }
+
+        internal static char[][] InitCharArray(int n1, int n2) {
+            char[][] a = new char[n1][];
+            for (int k = 0; k < n1; ++k) {
+                a[k] = new char[n2];
+            }
+            return a;
+        }
+
+        public override int ReadByte() {
+            if (streamEnd) {
+                return -1;
+            } else {
+                int retChar = currentChar;
+                switch (currentState) {
+                case START_BLOCK_STATE:
+                    break;
+                case RAND_PART_A_STATE:
+                    break;
+                case RAND_PART_B_STATE:
+                    SetupRandPartB();
+                    break;
+                case RAND_PART_C_STATE:
+                    SetupRandPartC();
+                    break;
+                case NO_RAND_PART_A_STATE:
+                    break;
+                case NO_RAND_PART_B_STATE:
+                    SetupNoRandPartB();
+                    break;
+                case NO_RAND_PART_C_STATE:
+                    SetupNoRandPartC();
+                    break;
+                default:
+                    break;
+                }
+                return retChar;
+            }
+        }
+
+        private void Initialize() {
+            char magic3, magic4;
+            magic3 = BsGetUChar();
+            magic4 = BsGetUChar();
+            if (magic3 != 'B' && magic4 != 'Z')
+            {
+                throw new IOException("Not a BZIP2 marked stream");
+            }
+            magic3 = BsGetUChar();
+            magic4 = BsGetUChar();
+            if (magic3 != 'h' || magic4 < '1' || magic4 > '9') {
+                BsFinishedWithStream();
+                streamEnd = true;
+                return;
+            }
+
+            SetDecompressStructureSizes(magic4 - '0');
+            computedCombinedCRC = 0;
+        }
+
+        private void InitBlock() {
+            char magic1, magic2, magic3, magic4;
+            char magic5, magic6;
+            magic1 = BsGetUChar();
+            magic2 = BsGetUChar();
+            magic3 = BsGetUChar();
+            magic4 = BsGetUChar();
+            magic5 = BsGetUChar();
+            magic6 = BsGetUChar();
+            if (magic1 == 0x17 && magic2 == 0x72 && magic3 == 0x45
+                && magic4 == 0x38 && magic5 == 0x50 && magic6 == 0x90) {
+                Complete();
+                return;
+            }
+
+            if (magic1 != 0x31 || magic2 != 0x41 || magic3 != 0x59
+                || magic4 != 0x26 || magic5 != 0x53 || magic6 != 0x59) {
+                BadBlockHeader();
+                streamEnd = true;
+                return;
+            }
+
+            storedBlockCRC = BsGetInt32();
+
+            if (BsR(1) == 1) {
+                blockRandomised = true;
+            } else {
+                blockRandomised = false;
+            }
+
+            //        currBlockNo++;
+            GetAndMoveToFrontDecode();
+
+            mCrc.InitialiseCRC();
+            currentState = START_BLOCK_STATE;
+        }
+
+        private void EndBlock() {
+            computedBlockCRC = mCrc.GetFinalCRC();
+            /* A bad CRC is considered a fatal error. */
+            if (storedBlockCRC != computedBlockCRC) {
+                CrcError();
+            }
+
+            computedCombinedCRC = (computedCombinedCRC << 1)
+                | (int)(((uint)computedCombinedCRC) >> 31);
+            computedCombinedCRC ^= computedBlockCRC;
+        }
+
+        private void Complete() {
+            storedCombinedCRC = BsGetInt32();
+            if (storedCombinedCRC != computedCombinedCRC) {
+                CrcError();
+            }
+
+            BsFinishedWithStream();
+            streamEnd = true;
+        }
+
+        private static void BlockOverrun() {
+            Cadvise();
+        }
+
+        private static void BadBlockHeader() {
+            Cadvise();
+        }
+
+        private static void CrcError() {
+            Cadvise();
+        }
+
+		private void BsFinishedWithStream() {
+            try {
+                if (this.bsStream != null) {
+                    this.bsStream.Dispose();
+                    this.bsStream = null;
+                }
+            } catch {
+                //ignore
+            }
+        }
+
+		private void BsSetStream(Stream f) {
+            bsStream = f;
+            bsLive = 0;
+            bsBuff = 0;
+        }
+
+        private int BsR(int n) {
+            int v;
+            while (bsLive < n) {
+                int zzi;
+                char thech = '\0';
+                try {
+                    thech = (char) bsStream.ReadByte();
+                } catch (IOException) {
+                    CompressedStreamEOF();
+                }
+                if (thech == '\uffff') {
+                    CompressedStreamEOF();
+                }
+                zzi = thech;
+                bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                bsLive += 8;
+            }
+
+            v = (bsBuff >> (bsLive - n)) & ((1 << n) - 1);
+            bsLive -= n;
+            return v;
+        }
+
+        private char BsGetUChar() {
+            return (char) BsR(8);
+        }
+
+        private int BsGetint() {
+            int u = 0;
+            u = (u << 8) | BsR(8);
+            u = (u << 8) | BsR(8);
+            u = (u << 8) | BsR(8);
+            u = (u << 8) | BsR(8);
+            return u;
+        }
+
+        private int BsGetIntVS(int numBits) {
+            return (int) BsR(numBits);
+        }
+
+        private int BsGetInt32() {
+            return (int) BsGetint();
+        }
+
+        private void HbCreateDecodeTables(int[] limit, int[] basev,
+                                        int[] perm, char[] length,
+                                        int minLen, int maxLen, int alphaSize) {
+            int pp, i, j, vec;
+
+            pp = 0;
+            for (i = minLen; i <= maxLen; i++) {
+                for (j = 0; j < alphaSize; j++) {
+                    if (length[j] == i) {
+                        perm[pp] = j;
+                        pp++;
+                    }
+                }
+            }
+
+            for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++) {
+                basev[i] = 0;
+            }
+            for (i = 0; i < alphaSize; i++) {
+                basev[length[i] + 1]++;
+            }
+
+            for (i = 1; i < BZip2Constants.MAX_CODE_LEN; i++) {
+                basev[i] += basev[i - 1];
+            }
+
+            for (i = 0; i < BZip2Constants.MAX_CODE_LEN; i++) {
+                limit[i] = 0;
+            }
+            vec = 0;
+
+            for (i = minLen; i <= maxLen; i++) {
+                vec += (basev[i + 1] - basev[i]);
+                limit[i] = vec - 1;
+                vec <<= 1;
+            }
+            for (i = minLen + 1; i <= maxLen; i++) {
+                basev[i] = ((limit[i - 1] + 1) << 1) - basev[i];
+            }
+        }
+
+        private void RecvDecodingTables() {
+            char[][] len = InitCharArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+            int i, j, t, nGroups, nSelectors, alphaSize;
+            int minLen, maxLen;
+            bool[] inUse16 = new bool[16];
+
+            /* Receive the mapping table */
+            for (i = 0; i < 16; i++) {
+                if (BsR(1) == 1) {
+                    inUse16[i] = true;
+                } else {
+                    inUse16[i] = false;
+                }
+            }
+
+            for (i = 0; i < 256; i++) {
+                inUse[i] = false;
+            }
+
+            for (i = 0; i < 16; i++) {
+                if (inUse16[i]) {
+                    for (j = 0; j < 16; j++) {
+                        if (BsR(1) == 1) {
+                            inUse[i * 16 + j] = true;
+                        }
+                    }
+                }
+            }
+
+            MakeMaps();
+            alphaSize = nInUse + 2;
+
+            /* Now the selectors */
+            nGroups = BsR(3);
+            nSelectors = BsR(15);
+            for (i = 0; i < nSelectors; i++) {
+                j = 0;
+                while (BsR(1) == 1) {
+                    j++;
+                }
+                selectorMtf[i] = (char) j;
+            }
+
+            /* Undo the MTF values for the selectors. */
+            {
+                char[] pos = new char[BZip2Constants.N_GROUPS];
+                char tmp, v;
+                for (v = '\0'; v < nGroups; v++) {
+                    pos[v] = v;
+                }
+
+                for (i = 0; i < nSelectors; i++) {
+                    v = selectorMtf[i];
+                    tmp = pos[v];
+                    while (v > 0) {
+                        pos[v] = pos[v - 1];
+                        v--;
+                    }
+                    pos[0] = tmp;
+                    selector[i] = tmp;
+                }
+            }
+
+            /* Now the coding tables */
+            for (t = 0; t < nGroups; t++) {
+                int curr = BsR(5);
+                for (i = 0; i < alphaSize; i++) {
+                    while (BsR(1) == 1) {
+                        if (BsR(1) == 0) {
+                            curr++;
+                        } else {
+                            curr--;
+                        }
+                    }
+                    len[t][i] = (char) curr;
+                }
+            }
+
+            /* Create the Huffman decoding tables */
+            for (t = 0; t < nGroups; t++) {
+                minLen = 32;
+                maxLen = 0;
+                for (i = 0; i < alphaSize; i++) {
+                    if (len[t][i] > maxLen) {
+                        maxLen = len[t][i];
+                    }
+                    if (len[t][i] < minLen) {
+                        minLen = len[t][i];
+                    }
+                }
+                HbCreateDecodeTables(limit[t], basev[t], perm[t], len[t], minLen,
+                                    maxLen, alphaSize);
+                minLens[t] = minLen;
+            }
+        }
+
+        private void GetAndMoveToFrontDecode() {
+            char[] yy = new char[256];
+            int i, j, nextSym, limitLast;
+            int EOB, groupNo, groupPos;
+
+            limitLast = BZip2Constants.baseBlockSize * blockSize100k;
+            origPtr = BsGetIntVS(24);
+
+            RecvDecodingTables();
+            EOB = nInUse + 1;
+            groupNo = -1;
+            groupPos = 0;
+
+            /*
+            Setting up the unzftab entries here is not strictly
+            necessary, but it does save having to do it later
+            in a separate pass, and so saves a block's worth of
+            cache misses.
+            */
+            for (i = 0; i <= 255; i++) {
+                unzftab[i] = 0;
+            }
+
+            for (i = 0; i <= 255; i++) {
+                yy[i] = (char) i;
+            }
+
+            last = -1;
+
+            {
+                int zt, zn, zvec, zj;
+                if (groupPos == 0) {
+                    groupNo++;
+                    groupPos = BZip2Constants.G_SIZE;
+                }
+                groupPos--;
+                zt = selector[groupNo];
+                zn = minLens[zt];
+                zvec = BsR(zn);
+                while (zvec > limit[zt][zn]) {
+                    zn++;
+                    {
+                        {
+                            while (bsLive < 1) {
+                                int zzi;
+                                char thech = '\0';
+                                try {
+                                    thech = (char) bsStream.ReadByte();
+                                } catch (IOException) {
+                                    CompressedStreamEOF();
+                                }
+                                if (thech == '\uffff') {
+                                    CompressedStreamEOF();
+                                }
+                                zzi = thech;
+                                bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                                bsLive += 8;
+                            }
+                        }
+                        zj = (bsBuff >> (bsLive - 1)) & 1;
+                        bsLive--;
+                    }
+                    zvec = (zvec << 1) | zj;
+                }
+                nextSym = perm[zt][zvec - basev[zt][zn]];
+            }
+
+            while (true) {
+
+                if (nextSym == EOB) {
+                    break;
+                }
+
+                if (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB) {
+                    char ch;
+                    int s = -1;
+                    int N = 1;
+                    do {
+                        if (nextSym == BZip2Constants.RUNA) {
+                            s = s + (0 + 1) * N;
+                        } else if (nextSym == BZip2Constants.RUNB) {
+                            s = s + (1 + 1) * N;
+                            }
+                        N = N * 2;
+                        {
+                            int zt, zn, zvec, zj;
+                            if (groupPos == 0) {
+                                groupNo++;
+                                groupPos = BZip2Constants.G_SIZE;
+                            }
+                            groupPos--;
+                            zt = selector[groupNo];
+                            zn = minLens[zt];
+                            zvec = BsR(zn);
+                            while (zvec > limit[zt][zn]) {
+                                zn++;
+                                {
+                                    {
+                                        while (bsLive < 1) {
+                                            int zzi;
+                                            char thech = '\0';
+                                            try {
+                                                thech = (char) bsStream.ReadByte();
+                                            } catch (IOException) {
+                                                CompressedStreamEOF();
+                                            }
+                                            if (thech == '\uffff') {
+                                                CompressedStreamEOF();
+                                            }
+                                            zzi = thech;
+                                            bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                                            bsLive += 8;
+                                        }
+                                    }
+                                    zj = (bsBuff >> (bsLive - 1)) & 1;
+                                    bsLive--;
+                                }
+                                zvec = (zvec << 1) | zj;
+                            }
+                            nextSym = perm[zt][zvec - basev[zt][zn]];
+                        }
+                    } while (nextSym == BZip2Constants.RUNA || nextSym == BZip2Constants.RUNB);
+
+                    s++;
+                    ch = seqToUnseq[yy[0]];
+                    unzftab[ch] += s;
+
+                    while (s > 0) {
+                        last++;
+                        ll8[last] = ch;
+                        s--;
+                    }
+
+                    if (last >= limitLast) {
+                        BlockOverrun();
+                    }
+                    continue;
+                } else {
+                    char tmp;
+                    last++;
+                    if (last >= limitLast) {
+                        BlockOverrun();
+                    }
+
+                    tmp = yy[nextSym - 1];
+                    unzftab[seqToUnseq[tmp]]++;
+                    ll8[last] = seqToUnseq[tmp];
+
+                    /*
+                    This loop is hammered during decompression,
+                    hence the unrolling.
+
+                    for (j = nextSym-1; j > 0; j--) yy[j] = yy[j-1];
+                    */
+
+                    j = nextSym - 1;
+                    for (; j > 3; j -= 4) {
+                        yy[j]     = yy[j - 1];
+                        yy[j - 1] = yy[j - 2];
+                        yy[j - 2] = yy[j - 3];
+                        yy[j - 3] = yy[j - 4];
+                    }
+                    for (; j > 0; j--) {
+                        yy[j] = yy[j - 1];
+                    }
+
+                    yy[0] = tmp;
+                    {
+                        int zt, zn, zvec, zj;
+                        if (groupPos == 0) {
+                            groupNo++;
+                            groupPos = BZip2Constants.G_SIZE;
+                        }
+                        groupPos--;
+                        zt = selector[groupNo];
+                        zn = minLens[zt];
+                        zvec = BsR(zn);
+                        while (zvec > limit[zt][zn]) {
+                            zn++;
+                            {
+                                {
+                                    while (bsLive < 1) {
+                                        int zzi;
+                                        char thech = '\0';
+                                        try {
+                                            thech = (char) bsStream.ReadByte();
+                                        } catch (IOException) {
+                                            CompressedStreamEOF();
+                                        }
+                                        zzi = thech;
+                                        bsBuff = (bsBuff << 8) | (zzi & 0xff);
+                                        bsLive += 8;
+                                    }
+                                }
+                                zj = (bsBuff >> (bsLive - 1)) & 1;
+                                bsLive--;
+                            }
+                            zvec = (zvec << 1) | zj;
+                        }
+                        nextSym = perm[zt][zvec - basev[zt][zn]];
+                    }
+                    continue;
+                }
+            }
+        }
+
+        private void SetupBlock() {
+            int[] cftab = new int[257];
+            char ch;
+
+            cftab[0] = 0;
+            for (i = 1; i <= 256; i++) {
+                cftab[i] = unzftab[i - 1];
+            }
+            for (i = 1; i <= 256; i++) {
+                cftab[i] += cftab[i - 1];
+            }
+
+            for (i = 0; i <= last; i++) {
+                ch = (char) ll8[i];
+                tt[cftab[ch]] = i;
+                cftab[ch]++;
+            }
+            cftab = null;
+
+            tPos = tt[origPtr];
+
+            count = 0;
+            i2 = 0;
+            ch2 = 256;   /* not a char and not EOF */
+
+            if (blockRandomised) {
+                rNToGo = 0;
+                rTPos = 0;
+                SetupRandPartA();
+            } else {
+                SetupNoRandPartA();
+            }
+        }
+
+        private void SetupRandPartA() {
+            if (i2 <= last) {
+                chPrev = ch2;
+                ch2 = ll8[tPos];
+                tPos = tt[tPos];
+                if (rNToGo == 0) {
+                    rNToGo = BZip2Constants.rNums[rTPos];
+                    rTPos++;
+                    if (rTPos == 512) {
+                        rTPos = 0;
+                    }
+                }
+                rNToGo--;
+                ch2 ^= (int) ((rNToGo == 1) ? 1 : 0);
+                i2++;
+
+                currentChar = ch2;
+                currentState = RAND_PART_B_STATE;
+                mCrc.UpdateCRC(ch2);
+            } else {
+                EndBlock();
+                InitBlock();
+                SetupBlock();
+            }
+        }
+
+        private void SetupNoRandPartA() {
+            if (i2 <= last) {
+                chPrev = ch2;
+                ch2 = ll8[tPos];
+                tPos = tt[tPos];
+                i2++;
+
+                currentChar = ch2;
+                currentState = NO_RAND_PART_B_STATE;
+                mCrc.UpdateCRC(ch2);
+            } else {
+                EndBlock();
+                InitBlock();
+                SetupBlock();
+            }
+        }
+
+        private void SetupRandPartB() {
+            if (ch2 != chPrev) {
+                currentState = RAND_PART_A_STATE;
+                count = 1;
+                SetupRandPartA();
+            } else {
+                count++;
+                if (count >= 4) {
+                    z = ll8[tPos];
+                    tPos = tt[tPos];
+                    if (rNToGo == 0) {
+                        rNToGo = BZip2Constants.rNums[rTPos];
+                        rTPos++;
+                        if (rTPos == 512) {
+                            rTPos = 0;
+                        }
+                    }
+                    rNToGo--;
+                    z ^= (char)((rNToGo == 1) ? 1 : 0);
+                    j2 = 0;
+                    currentState = RAND_PART_C_STATE;
+                    SetupRandPartC();
+                } else {
+                    currentState = RAND_PART_A_STATE;
+                    SetupRandPartA();
+                }
+            }
+        }
+
+        private void SetupRandPartC() {
+            if (j2 < (int) z) {
+                currentChar = ch2;
+                mCrc.UpdateCRC(ch2);
+                j2++;
+            } else {
+                currentState = RAND_PART_A_STATE;
+                i2++;
+                count = 0;
+                SetupRandPartA();
+            }
+        }
+
+        private void SetupNoRandPartB() {
+            if (ch2 != chPrev) {
+                currentState = NO_RAND_PART_A_STATE;
+                count = 1;
+                SetupNoRandPartA();
+            } else {
+                count++;
+                if (count >= 4) {
+                    z = ll8[tPos];
+                    tPos = tt[tPos];
+                    currentState = NO_RAND_PART_C_STATE;
+                    j2 = 0;
+                    SetupNoRandPartC();
+                } else {
+                    currentState = NO_RAND_PART_A_STATE;
+                    SetupNoRandPartA();
+                }
+            }
+        }
+
+        private void SetupNoRandPartC() {
+            if (j2 < (int) z) {
+                currentChar = ch2;
+                mCrc.UpdateCRC(ch2);
+                j2++;
+            } else {
+                currentState = NO_RAND_PART_A_STATE;
+                i2++;
+                count = 0;
+                SetupNoRandPartA();
+            }
+        }
+
+        private void SetDecompressStructureSizes(int newSize100k) {
+            if (!(0 <= newSize100k && newSize100k <= 9 && 0 <= blockSize100k
+                && blockSize100k <= 9)) {
+                // throw new IOException("Invalid block size");
+            }
+
+            blockSize100k = newSize100k;
+
+            if (newSize100k == 0) {
+                return;
+            }
+
+            int n = BZip2Constants.baseBlockSize * newSize100k;
+            ll8 = new char[n];
+            tt = new int[n];
+        }
+    
+        public override void Flush() {
+        }
+    
+        public override int Read(byte[] buffer, int offset, int count) {
+            int c = -1;
+            int k;
+            for (k = 0; k < count; ++k) {
+                c = ReadByte();
+                if (c == -1)
+                    break;
+                buffer[k + offset] = (byte)c;
+            }
+            return k;
+        }
+    
+        public override long Seek(long offset, SeekOrigin origin) {
+            return 0;
+        }
+    
+        public override void SetLength(long value) {
+        }
+    
+        public override void Write(byte[] buffer, int offset, int count) {
+        }
+    
+        public override bool CanRead {
+            get {
+                return true;
+            }
+        }
+    
+        public override bool CanSeek {
+            get {
+                return false;
+            }
+        }
+    
+        public override bool CanWrite {
+            get {
+                return false;
+            }
+        }
+    
+        public override long Length {
+            get {
+                return 0;
+            }
+        }
+    
+        public override long Position {
+            get {
+                return 0;
+            }
+            set {
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/bzip2/src/CBZip2OutputStream.cs b/BouncyCastle.AxCrypt/bzip2/src/CBZip2OutputStream.cs
new file mode 100644
index 0000000..690c8a0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/bzip2/src/CBZip2OutputStream.cs
@@ -0,0 +1,1697 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle, Aftex Software
+ * <keiron at aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Apache.Bzip2
+{
+	/**
+    * An output stream that compresses into the BZip2 format (with the file
+    * header chars) into another stream.
+    *
+    * @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+    *
+    * TODO:    Update to BZip2 1.0.1
+    * <b>NB:</b> note this class has been modified to add a leading BZ to the
+    * start of the BZIP2 stream to make it compatible with other PGP programs.
+    */
+    public class CBZip2OutputStream : Stream 
+	{
+        protected const int SETMASK = (1 << 21);
+        protected const int CLEARMASK = (~SETMASK);
+        protected const int GREATER_ICOST = 15;
+        protected const int LESSER_ICOST = 0;
+        protected const int SMALL_THRESH = 20;
+        protected const int DEPTH_THRESH = 10;
+
+        /*
+        If you are ever unlucky/improbable enough
+        to get a stack overflow whilst sorting,
+        increase the following constant and try
+        again.  In practice I have never seen the
+        stack go above 27 elems, so the following
+        limit seems very generous.
+        */
+        protected const int QSORT_STACK_SIZE = 1000;
+        private bool finished;
+
+        private static void Panic() {
+            //System.out.Println("panic");
+            //throw new CError();
+        }
+
+        private void MakeMaps() {
+            int i;
+            nInUse = 0;
+            for (i = 0; i < 256; i++) {
+                if (inUse[i]) {
+                    seqToUnseq[nInUse] = (char) i;
+                    unseqToSeq[i] = (char) nInUse;
+                    nInUse++;
+                }
+            }
+        }
+
+        protected static void HbMakeCodeLengths(char[] len, int[] freq,
+                                                int alphaSize, int maxLen) {
+            /*
+            Nodes and heap entries run from 1.  Entry 0
+            for both the heap and nodes is a sentinel.
+            */
+            int nNodes, nHeap, n1, n2, i, j, k;
+            bool  tooLong;
+
+            int[] heap = new int[BZip2Constants.MAX_ALPHA_SIZE + 2];
+            int[] weight = new int[BZip2Constants.MAX_ALPHA_SIZE * 2];
+            int[] parent = new int[BZip2Constants.MAX_ALPHA_SIZE * 2];
+
+            for (i = 0; i < alphaSize; i++) {
+                weight[i + 1] = (freq[i] == 0 ? 1 : freq[i]) << 8;
+            }
+
+            while (true) {
+                nNodes = alphaSize;
+                nHeap = 0;
+
+                heap[0] = 0;
+                weight[0] = 0;
+                parent[0] = -2;
+
+                for (i = 1; i <= alphaSize; i++) {
+                    parent[i] = -1;
+                    nHeap++;
+                    heap[nHeap] = i;
+                    {
+                        int zz, tmp;
+                        zz = nHeap;
+                        tmp = heap[zz];
+                        while (weight[tmp] < weight[heap[zz >> 1]]) {
+                            heap[zz] = heap[zz >> 1];
+                            zz >>= 1;
+                        }
+                        heap[zz] = tmp;
+                    }
+                }
+                if (!(nHeap < (BZip2Constants.MAX_ALPHA_SIZE + 2))) {
+                    Panic();
+                }
+
+                while (nHeap > 1) {
+                    n1 = heap[1];
+                    heap[1] = heap[nHeap];
+                    nHeap--;
+                    {
+                        int zz = 0, yy = 0, tmp = 0;
+                        zz = 1;
+                        tmp = heap[zz];
+                        while (true) {
+                            yy = zz << 1;
+                            if (yy > nHeap) {
+                                break;
+                            }
+                            if (yy < nHeap
+                                && weight[heap[yy + 1]] < weight[heap[yy]]) {
+                                yy++;
+                            }
+                            if (weight[tmp] < weight[heap[yy]]) {
+                                break;
+                            }
+                            heap[zz] = heap[yy];
+                            zz = yy;
+                        }
+                        heap[zz] = tmp;
+                    }
+                    n2 = heap[1];
+                    heap[1] = heap[nHeap];
+                    nHeap--;
+                    {
+                        int zz = 0, yy = 0, tmp = 0;
+                        zz = 1;
+                        tmp = heap[zz];
+                        while (true) {
+                            yy = zz << 1;
+                            if (yy > nHeap) {
+                                break;
+                            }
+                            if (yy < nHeap
+                                && weight[heap[yy + 1]] < weight[heap[yy]]) {
+                                yy++;
+                            }
+                            if (weight[tmp] < weight[heap[yy]]) {
+                                break;
+                            }
+                            heap[zz] = heap[yy];
+                            zz = yy;
+                        }
+                        heap[zz] = tmp;
+                    }
+                    nNodes++;
+                    parent[n1] = parent[n2] = nNodes;
+
+                    weight[nNodes] = (int)((uint)((weight[n1] & 0xffffff00)
+                                    + (weight[n2] & 0xffffff00))
+                        | (uint)(1 + (((weight[n1] & 0x000000ff) >
+                                (weight[n2] & 0x000000ff)) ?
+                                (weight[n1] & 0x000000ff) :
+                                (weight[n2] & 0x000000ff))));
+
+                    parent[nNodes] = -1;
+                    nHeap++;
+                    heap[nHeap] = nNodes;
+                    {
+                        int zz = 0, tmp = 0;
+                        zz = nHeap;
+                        tmp = heap[zz];
+                        while (weight[tmp] < weight[heap[zz >> 1]]) {
+                            heap[zz] = heap[zz >> 1];
+                            zz >>= 1;
+                        }
+                        heap[zz] = tmp;
+                    }
+                }
+                if (!(nNodes < (BZip2Constants.MAX_ALPHA_SIZE * 2))) {
+                    Panic();
+                }
+
+                tooLong = false;
+                for (i = 1; i <= alphaSize; i++) {
+                    j = 0;
+                    k = i;
+                    while (parent[k] >= 0) {
+                        k = parent[k];
+                        j++;
+                    }
+                    len[i - 1] = (char) j;
+                    if (j > maxLen) {
+                        tooLong = true;
+                    }
+                }
+
+                if (!tooLong) {
+                    break;
+                }
+
+                for (i = 1; i < alphaSize; i++) {
+                    j = weight[i] >> 8;
+                    j = 1 + (j / 2);
+                    weight[i] = j << 8;
+                }
+            }
+        }
+
+        /*
+        index of the last char in the block, so
+        the block size == last + 1.
+        */
+        int last;
+
+        /*
+        index in zptr[] of original string after sorting.
+        */
+        int origPtr;
+
+        /*
+        always: in the range 0 .. 9.
+        The current block size is 100000 * this number.
+        */
+        int blockSize100k;
+
+        bool blockRandomised;
+
+        int bytesOut;
+        int bsBuff;
+        int bsLive;
+        CRC mCrc = new CRC();
+
+        private bool[] inUse = new bool[256];
+        private int nInUse;
+
+        private char[] seqToUnseq = new char[256];
+        private char[] unseqToSeq = new char[256];
+
+        private char[] selector = new char[BZip2Constants.MAX_SELECTORS];
+        private char[] selectorMtf = new char[BZip2Constants.MAX_SELECTORS];
+
+        private char[] block;
+        private int[] quadrant;
+        private int[] zptr;
+        private short[] szptr;
+        private int[] ftab;
+
+        private int nMTF;
+
+        private int[] mtfFreq = new int[BZip2Constants.MAX_ALPHA_SIZE];
+
+        /*
+        * Used when sorting.  If too many long comparisons
+        * happen, we stop sorting, randomise the block
+        * slightly, and try again.
+        */
+        private int workFactor;
+        private int workDone;
+        private int workLimit;
+        private bool firstAttempt;
+        private int nBlocksRandomised;
+
+        private int currentChar = -1;
+        private int runLength = 0;
+
+        public CBZip2OutputStream(Stream inStream) : this(inStream, 9) {
+        }
+
+        public CBZip2OutputStream(Stream inStream, int inBlockSize)
+            {
+            block = null;
+            quadrant = null;
+            zptr = null;
+            ftab = null;
+
+            inStream.WriteByte((byte)'B');
+            inStream.WriteByte((byte)'Z');
+
+            BsSetStream(inStream);
+
+            workFactor = 50;
+            if (inBlockSize > 9) {
+                inBlockSize = 9;
+            }
+            if (inBlockSize < 1) {
+                inBlockSize = 1;
+            }
+            blockSize100k = inBlockSize;
+            AllocateCompressStructures();
+            Initialize();
+            InitBlock();
+        }
+
+        /**
+        *
+        * modified by Oliver Merkel, 010128
+        *
+        */
+        public override void WriteByte(byte bv) {
+            int b = (256 + bv) % 256;
+            if (currentChar != -1) {
+                if (currentChar == b) {
+                    runLength++;
+                    if (runLength > 254) {
+                        WriteRun();
+                        currentChar = -1;
+                        runLength = 0;
+                    }
+                } else {
+                    WriteRun();
+                    runLength = 1;
+                    currentChar = b;
+                }
+            } else {
+                currentChar = b;
+                runLength++;
+            }
+        }
+
+        private void WriteRun() {
+            if (last < allowableBlockSize) {
+                inUse[currentChar] = true;
+                for (int i = 0; i < runLength; i++) {
+                    mCrc.UpdateCRC((char) currentChar);
+                }
+                switch (runLength) {
+                case 1:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                case 2:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                case 3:
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    break;
+                default:
+                    inUse[runLength - 4] = true;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) currentChar;
+                    last++;
+                    block[last + 1] = (char) (runLength - 4);
+                    break;
+                }
+            } else {
+                EndBlock();
+                InitBlock();
+                WriteRun();
+            }
+        }
+
+        bool closed = false;
+
+//        protected void Finalize() {
+//            Close();
+//        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (closed)
+                {
+                    return;
+                }
+
+                Finish();
+
+                closed = true;
+                
+                bsStream.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        public void Finish() {
+            if (finished) {
+                return;
+            }
+
+            if (runLength > 0) {
+                WriteRun();
+            }
+            currentChar = -1;
+            EndBlock();
+            EndCompression();
+            finished = true;
+            Flush();
+        }
+        
+        public override void Flush() {
+            bsStream.Flush();
+        }
+
+        private int blockCRC, combinedCRC;
+
+        private void Initialize() {
+            bytesOut = 0;
+            nBlocksRandomised = 0;
+
+            /* Write `magic' bytes h indicating file-format == huffmanised,
+            followed by a digit indicating blockSize100k.
+            */
+            BsPutUChar('h');
+            BsPutUChar('0' + blockSize100k);
+
+            combinedCRC = 0;
+        }
+
+        private int allowableBlockSize;
+
+        private void InitBlock() {
+            //        blockNo++;
+            mCrc.InitialiseCRC();
+            last = -1;
+            //        ch = 0;
+
+            for (int i = 0; i < 256; i++) {
+                inUse[i] = false;
+            }
+
+            /* 20 is just a paranoia constant */
+            allowableBlockSize = BZip2Constants.baseBlockSize * blockSize100k - 20;
+        }
+
+        private void EndBlock() {
+            blockCRC = mCrc.GetFinalCRC();
+            combinedCRC = (combinedCRC << 1) | (int)(((uint)combinedCRC) >> 31);
+            combinedCRC ^= blockCRC;
+
+            /* sort the block and establish posn of original string */
+            DoReversibleTransformation();
+
+            /*
+            A 6-byte block header, the value chosen arbitrarily
+            as 0x314159265359 :-).  A 32 bit value does not really
+            give a strong enough guarantee that the value will not
+            appear by chance in the compressed datastream.  Worst-case
+            probability of this event, for a 900k block, is about
+            2.0e-3 for 32 bits, 1.0e-5 for 40 bits and 4.0e-8 for 48 bits.
+            For a compressed file of size 100Gb -- about 100000 blocks --
+            only a 48-bit marker will do.  NB: normal compression/
+            decompression do *not* rely on these statistical properties.
+            They are only important when trying to recover blocks from
+            damaged files.
+            */
+            BsPutUChar(0x31);
+            BsPutUChar(0x41);
+            BsPutUChar(0x59);
+            BsPutUChar(0x26);
+            BsPutUChar(0x53);
+            BsPutUChar(0x59);
+
+            /* Now the block's CRC, so it is in a known place. */
+            BsPutint(blockCRC);
+
+            /* Now a single bit indicating randomisation. */
+            if (blockRandomised) {
+                BsW(1, 1);
+                nBlocksRandomised++;
+            } else {
+                BsW(1, 0);
+            }
+
+            /* Finally, block's contents proper. */
+            MoveToFrontCodeAndSend();
+        }
+
+        private void EndCompression() {
+            /*
+            Now another magic 48-bit number, 0x177245385090, to
+            indicate the end of the last block.  (Sqrt(pi), if
+            you want to know.  I did want to use e, but it contains
+            too much repetition -- 27 18 28 18 28 46 -- for me
+            to feel statistically comfortable.  Call me paranoid.)
+            */
+            BsPutUChar(0x17);
+            BsPutUChar(0x72);
+            BsPutUChar(0x45);
+            BsPutUChar(0x38);
+            BsPutUChar(0x50);
+            BsPutUChar(0x90);
+
+            BsPutint(combinedCRC);
+
+            BsFinishedWithStream();
+        }
+
+        private void HbAssignCodes(int[] code, char[] length, int minLen,
+                                    int maxLen, int alphaSize) {
+            int n, vec, i;
+
+            vec = 0;
+            for (n = minLen; n <= maxLen; n++) {
+                for (i = 0; i < alphaSize; i++) {
+                    if (length[i] == n) {
+                        code[i] = vec;
+                        vec++;
+                    }
+                };
+                vec <<= 1;
+            }
+        }
+
+        private void BsSetStream(Stream f) {
+            bsStream = f;
+            bsLive = 0;
+            bsBuff = 0;
+            bytesOut = 0;
+        }
+
+        private void BsFinishedWithStream() {
+            while (bsLive > 0) {
+                int ch = (bsBuff >> 24);
+                try {
+                    bsStream.WriteByte((byte)ch); // write 8-bit
+                } catch (IOException e) {
+                    throw  e;
+                }
+                bsBuff <<= 8;
+                bsLive -= 8;
+                bytesOut++;
+            }
+        }
+
+        private void BsW(int n, int v) {
+            while (bsLive >= 8) {
+                int ch = (bsBuff >> 24);
+                try {
+                    bsStream.WriteByte((byte)ch); // write 8-bit
+                } catch (IOException e) {
+                    throw e;
+                }
+                bsBuff <<= 8;
+                bsLive -= 8;
+                bytesOut++;
+            }
+            bsBuff |= (v << (32 - bsLive - n));
+            bsLive += n;
+        }
+
+        private void BsPutUChar(int c) {
+            BsW(8, c);
+        }
+
+        private void BsPutint(int u) {
+            BsW(8, (u >> 24) & 0xff);
+            BsW(8, (u >> 16) & 0xff);
+            BsW(8, (u >>  8) & 0xff);
+            BsW(8,  u        & 0xff);
+        }
+
+        private void BsPutIntVS(int numBits, int c) {
+            BsW(numBits, c);
+        }
+
+        private void SendMTFValues() {
+            char[][] len = CBZip2InputStream.InitCharArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+
+            int v, t, i, j, gs, ge, totc, bt, bc, iter;
+            int nSelectors = 0, alphaSize, minLen, maxLen, selCtr;
+            int nGroups;
+
+            alphaSize = nInUse + 2;
+            for (t = 0; t < BZip2Constants.N_GROUPS; t++) {
+                for (v = 0; v < alphaSize; v++) {
+                    len[t][v] = (char) GREATER_ICOST;
+                }
+            }
+
+            /* Decide how many coding tables to use */
+            if (nMTF <= 0) {
+                Panic();
+            }
+
+            if (nMTF < 200) {
+                nGroups = 2;
+            } else if (nMTF < 600) {
+                nGroups = 3;
+            } else if (nMTF < 1200) {
+                nGroups = 4;
+            } else if (nMTF < 2400) {
+                nGroups = 5;
+            } else {
+                nGroups = 6;
+            }
+
+            /* Generate an initial set of coding tables */ {
+                int nPart, remF, tFreq, aFreq;
+
+                nPart = nGroups;
+                remF  = nMTF;
+                gs = 0;
+                while (nPart > 0) {
+                    tFreq = remF / nPart;
+                    ge = gs - 1;
+                    aFreq = 0;
+                    while (aFreq < tFreq && ge < alphaSize - 1) {
+                        ge++;
+                        aFreq += mtfFreq[ge];
+                    }
+
+                    if (ge > gs && nPart != nGroups && nPart != 1
+                        && ((nGroups - nPart) % 2 == 1)) {
+                        aFreq -= mtfFreq[ge];
+                        ge--;
+                    }
+
+                    for (v = 0; v < alphaSize; v++) {
+                        if (v >= gs && v <= ge) {
+                            len[nPart - 1][v] = (char) LESSER_ICOST;
+                        } else {
+                            len[nPart - 1][v] = (char) GREATER_ICOST;
+                        }
+                    }
+
+                    nPart--;
+                    gs = ge + 1;
+                    remF -= aFreq;
+                }
+            }
+
+            int[][] rfreq = CBZip2InputStream.InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+            int[] fave = new int[BZip2Constants.N_GROUPS];
+            short[] cost = new short[BZip2Constants.N_GROUPS];
+            /*
+            Iterate up to N_ITERS times to improve the tables.
+            */
+            for (iter = 0; iter < BZip2Constants.N_ITERS; iter++) {
+                for (t = 0; t < nGroups; t++) {
+                    fave[t] = 0;
+                }
+
+                for (t = 0; t < nGroups; t++) {
+                    for (v = 0; v < alphaSize; v++) {
+                        rfreq[t][v] = 0;
+                    }
+                }
+
+                nSelectors = 0;
+                totc = 0;
+                gs = 0;
+                while (true) {
+
+                    /* Set group start & end marks. */
+                    if (gs >= nMTF) {
+                        break;
+                    }
+                    ge = gs + BZip2Constants.G_SIZE - 1;
+                    if (ge >= nMTF) {
+                        ge = nMTF - 1;
+                    }
+
+                    /*
+                    Calculate the cost of this group as coded
+                    by each of the coding tables.
+                    */
+                    for (t = 0; t < nGroups; t++) {
+                        cost[t] = 0;
+                    }
+
+                    if (nGroups == 6) {
+                        short cost0, cost1, cost2, cost3, cost4, cost5;
+                        cost0 = cost1 = cost2 = cost3 = cost4 = cost5 = 0;
+                        for (i = gs; i <= ge; i++) {
+                            short icv = szptr[i];
+                            cost0 += (short)len[0][icv];
+                            cost1 += (short)len[1][icv];
+                            cost2 += (short)len[2][icv];
+                            cost3 += (short)len[3][icv];
+                            cost4 += (short)len[4][icv];
+                            cost5 += (short)len[5][icv];
+                        }
+                        cost[0] = cost0;
+                        cost[1] = cost1;
+                        cost[2] = cost2;
+                        cost[3] = cost3;
+                        cost[4] = cost4;
+                        cost[5] = cost5;
+                    } else {
+                        for (i = gs; i <= ge; i++) {
+                            short icv = szptr[i];
+                            for (t = 0; t < nGroups; t++) {
+                                cost[t] += (short)len[t][icv];
+                            }
+                        }
+                    }
+
+                    /*
+                    Find the coding table which is best for this group,
+                    and record its identity in the selector table.
+                    */
+                    bc = 999999999;
+                    bt = -1;
+                    for (t = 0; t < nGroups; t++) {
+                        if (cost[t] < bc) {
+                            bc = cost[t];
+                            bt = t;
+                        }
+                    };
+                    totc += bc;
+                    fave[bt]++;
+                    selector[nSelectors] = (char) bt;
+                    nSelectors++;
+
+                    /*
+                    Increment the symbol frequencies for the selected table.
+                    */
+                    for (i = gs; i <= ge; i++) {
+                        rfreq[bt][szptr[i]]++;
+                    }
+
+                    gs = ge + 1;
+                }
+
+                /*
+                Recompute the tables based on the accumulated frequencies.
+                */
+                for (t = 0; t < nGroups; t++) {
+                    HbMakeCodeLengths(len[t], rfreq[t], alphaSize, 20);
+                }
+            }
+
+            rfreq = null;
+            fave = null;
+            cost = null;
+
+            if (!(nGroups < 8)) {
+                Panic();
+            }
+            if (!(nSelectors < 32768 && nSelectors <= (2 + (900000 / BZip2Constants.G_SIZE)))) {
+                Panic();
+            }
+
+
+            /* Compute MTF values for the selectors. */
+            {
+                char[] pos = new char[BZip2Constants.N_GROUPS];
+                char ll_i, tmp2, tmp;
+                for (i = 0; i < nGroups; i++) {
+                    pos[i] = (char) i;
+                }
+                for (i = 0; i < nSelectors; i++) {
+                    ll_i = selector[i];
+                    j = 0;
+                    tmp = pos[j];
+                    while (ll_i != tmp) {
+                        j++;
+                        tmp2 = tmp;
+                        tmp = pos[j];
+                        pos[j] = tmp2;
+                    }
+                    pos[0] = tmp;
+                    selectorMtf[i] = (char) j;
+                }
+            }
+
+            int[][] code = CBZip2InputStream.InitIntArray(BZip2Constants.N_GROUPS, BZip2Constants.MAX_ALPHA_SIZE);
+
+            /* Assign actual codes for the tables. */
+            for (t = 0; t < nGroups; t++) {
+                minLen = 32;
+                maxLen = 0;
+                for (i = 0; i < alphaSize; i++) {
+                    if (len[t][i] > maxLen) {
+                        maxLen = len[t][i];
+                    }
+                    if (len[t][i] < minLen) {
+                        minLen = len[t][i];
+                    }
+                }
+                if (maxLen > 20) {
+                    Panic();
+                }
+                if (minLen < 1) {
+                    Panic();
+                }
+                HbAssignCodes(code[t], len[t], minLen, maxLen, alphaSize);
+            }
+
+            /* Transmit the mapping table. */
+            {
+                bool[] inUse16 = new bool[16];
+                for (i = 0; i < 16; i++) {
+                    inUse16[i] = false;
+                    for (j = 0; j < 16; j++) {
+                        if (inUse[i * 16 + j]) {
+                            inUse16[i] = true;
+                        }
+                    }
+                }
+
+				for (i = 0; i < 16; i++) {
+                    if (inUse16[i]) {
+                        BsW(1, 1);
+                    } else {
+                        BsW(1, 0);
+                    }
+                }
+
+                for (i = 0; i < 16; i++) {
+                    if (inUse16[i]) {
+                        for (j = 0; j < 16; j++) {
+                            if (inUse[i * 16 + j]) {
+                                BsW(1, 1);
+                            } else {
+                                BsW(1, 0);
+                            }
+                        }
+                    }
+                }
+
+            }
+
+            /* Now the selectors. */
+            BsW(3, nGroups);
+            BsW(15, nSelectors);
+            for (i = 0; i < nSelectors; i++) {
+                for (j = 0; j < selectorMtf[i]; j++) {
+                    BsW(1, 1);
+                }
+                BsW(1, 0);
+            }
+
+            /* Now the coding tables. */
+            for (t = 0; t < nGroups; t++) {
+                int curr = len[t][0];
+                BsW(5, curr);
+                for (i = 0; i < alphaSize; i++) {
+                    while (curr < len[t][i]) {
+                        BsW(2, 2);
+                        curr++; /* 10 */
+                    }
+                    while (curr > len[t][i]) {
+                        BsW(2, 3);
+                        curr--; /* 11 */
+                    }
+                    BsW(1, 0);
+                }
+            }
+
+            /* And finally, the block data proper */
+            selCtr = 0;
+            gs = 0;
+            while (true) {
+                if (gs >= nMTF) {
+                    break;
+                }
+                ge = gs + BZip2Constants.G_SIZE - 1;
+                if (ge >= nMTF) {
+                    ge = nMTF - 1;
+                }
+                for (i = gs; i <= ge; i++) {
+                    BsW(len[selector[selCtr]][szptr[i]],
+                        code[selector[selCtr]][szptr[i]]);
+                }
+
+                gs = ge + 1;
+                selCtr++;
+            }
+            if (!(selCtr == nSelectors)) {
+                Panic();
+            }
+        }
+
+        private void MoveToFrontCodeAndSend() {
+            BsPutIntVS(24, origPtr);
+            GenerateMTFValues();
+            SendMTFValues();
+        }
+
+        private Stream bsStream;
+
+        private void SimpleSort(int lo, int hi, int d) {
+            int i, j, h, bigN, hp;
+            int v;
+
+            bigN = hi - lo + 1;
+            if (bigN < 2) {
+                return;
+            }
+
+            hp = 0;
+            while (incs[hp] < bigN) {
+                hp++;
+            }
+            hp--;
+
+            for (; hp >= 0; hp--) {
+                h = incs[hp];
+
+                i = lo + h;
+                while (true) {
+                    /* copy 1 */
+                    if (i > hi) {
+                        break;
+                    }
+                    v = zptr[i];
+                    j = i;
+                    while (FullGtU(zptr[j - h] + d, v + d)) {
+                        zptr[j] = zptr[j - h];
+                        j = j - h;
+                        if (j <= (lo + h - 1)) {
+                            break;
+                        }
+                    }
+                    zptr[j] = v;
+                    i++;
+
+                    /* copy 2 */
+                    if (i > hi) {
+                        break;
+                    }
+                    v = zptr[i];
+                    j = i;
+                    while (FullGtU(zptr[j - h] + d, v + d)) {
+                        zptr[j] = zptr[j - h];
+                        j = j - h;
+                        if (j <= (lo + h - 1)) {
+                            break;
+                        }
+                    }
+                    zptr[j] = v;
+                    i++;
+
+                    /* copy 3 */
+                    if (i > hi) {
+                        break;
+                    }
+                    v = zptr[i];
+                    j = i;
+                    while (FullGtU(zptr[j - h] + d, v + d)) {
+                        zptr[j] = zptr[j - h];
+                        j = j - h;
+                        if (j <= (lo + h - 1)) {
+                            break;
+                        }
+                    }
+                    zptr[j] = v;
+                    i++;
+
+                    if (workDone > workLimit && firstAttempt) {
+                        return;
+                    }
+                }
+            }
+        }
+
+        private void Vswap(int p1, int p2, int n) {
+            int temp = 0;
+            while (n > 0) {
+                temp = zptr[p1];
+                zptr[p1] = zptr[p2];
+                zptr[p2] = temp;
+                p1++;
+                p2++;
+                n--;
+            }
+        }
+
+        private char Med3(char a, char b, char c) {
+            char t;
+            if (a > b) {
+                t = a;
+                a = b;
+                b = t;
+            }
+            if (b > c) {
+                t = b;
+                b = c;
+                c = t;
+            }
+            if (a > b) {
+                b = a;
+            }
+            return b;
+        }
+
+        internal class StackElem {
+            internal int ll;
+            internal int hh;
+            internal int dd;
+        }
+
+        private void QSort3(int loSt, int hiSt, int dSt) {
+            int unLo, unHi, ltLo, gtHi, med, n, m;
+            int sp, lo, hi, d;
+            StackElem[] stack = new StackElem[QSORT_STACK_SIZE];
+            for (int count = 0; count < QSORT_STACK_SIZE; count++) {
+                stack[count] = new StackElem();
+            }
+
+            sp = 0;
+
+            stack[sp].ll = loSt;
+            stack[sp].hh = hiSt;
+            stack[sp].dd = dSt;
+            sp++;
+
+            while (sp > 0) {
+                if (sp >= QSORT_STACK_SIZE) {
+                    Panic();
+                }
+
+                sp--;
+                lo = stack[sp].ll;
+                hi = stack[sp].hh;
+                d = stack[sp].dd;
+
+                if (hi - lo < SMALL_THRESH || d > DEPTH_THRESH) {
+                    SimpleSort(lo, hi, d);
+                    if (workDone > workLimit && firstAttempt) {
+                        return;
+                    }
+                    continue;
+                }
+
+                med = Med3(block[zptr[lo] + d + 1],
+                        block[zptr[hi            ] + d  + 1],
+                        block[zptr[(lo + hi) >> 1] + d + 1]);
+
+                unLo = ltLo = lo;
+                unHi = gtHi = hi;
+
+                while (true) {
+                    while (true) {
+                        if (unLo > unHi) {
+                            break;
+                        }
+                        n = ((int) block[zptr[unLo] + d + 1]) - med;
+                        if (n == 0) {
+                            int temp = 0;
+                            temp = zptr[unLo];
+                            zptr[unLo] = zptr[ltLo];
+                            zptr[ltLo] = temp;
+                            ltLo++;
+                            unLo++;
+                            continue;
+                        };
+                        if (n >  0) {
+                            break;
+                        }
+                        unLo++;
+                    }
+                    while (true) {
+                        if (unLo > unHi) {
+                            break;
+                        }
+                        n = ((int) block[zptr[unHi] + d + 1]) - med;
+                        if (n == 0) {
+                            int temp = 0;
+                            temp = zptr[unHi];
+                            zptr[unHi] = zptr[gtHi];
+                            zptr[gtHi] = temp;
+                            gtHi--;
+                            unHi--;
+                            continue;
+                        };
+                        if (n <  0) {
+                            break;
+                        }
+                        unHi--;
+                    }
+                    if (unLo > unHi) {
+                        break;
+                    }
+                    int tempx = zptr[unLo];
+                    zptr[unLo] = zptr[unHi];
+                    zptr[unHi] = tempx;
+                    unLo++;
+                    unHi--;
+                }
+
+                if (gtHi < ltLo) {
+                    stack[sp].ll = lo;
+                    stack[sp].hh = hi;
+                    stack[sp].dd = d + 1;
+                    sp++;
+                    continue;
+                }
+
+                n = ((ltLo - lo) < (unLo - ltLo)) ? (ltLo - lo) : (unLo - ltLo);
+                Vswap(lo, unLo - n, n);
+                m = ((hi - gtHi) < (gtHi - unHi)) ? (hi - gtHi) : (gtHi - unHi);
+                Vswap(unLo, hi - m + 1, m);
+
+                n = lo + unLo - ltLo - 1;
+                m = hi - (gtHi - unHi) + 1;
+
+                stack[sp].ll = lo;
+                stack[sp].hh = n;
+                stack[sp].dd = d;
+                sp++;
+
+                stack[sp].ll = n + 1;
+                stack[sp].hh = m - 1;
+                stack[sp].dd = d + 1;
+                sp++;
+
+                stack[sp].ll = m;
+                stack[sp].hh = hi;
+                stack[sp].dd = d;
+                sp++;
+            }
+        }
+
+        private void MainSort() {
+            int i, j, ss, sb;
+            int[] runningOrder = new int[256];
+            int[] copy = new int[256];
+            bool[] bigDone = new bool[256];
+            int c1, c2;
+            int numQSorted;
+
+            /*
+            In the various block-sized structures, live data runs
+            from 0 to last+NUM_OVERSHOOT_BYTES inclusive.  First,
+            set up the overshoot area for block.
+            */
+
+            //   if (verbosity >= 4) fprintf ( stderr, "   sort initialise ...\n" );
+            for (i = 0; i < BZip2Constants.NUM_OVERSHOOT_BYTES; i++) {
+                block[last + i + 2] = block[(i % (last + 1)) + 1];
+            }
+            for (i = 0; i <= last + BZip2Constants.NUM_OVERSHOOT_BYTES; i++) {
+                quadrant[i] = 0;
+            }
+
+            block[0] = (char) (block[last + 1]);
+
+            if (last < 4000) {
+                /*
+                Use SimpleSort(), since the full sorting mechanism
+                has quite a large constant overhead.
+                */
+                for (i = 0; i <= last; i++) {
+                    zptr[i] = i;
+                }
+                firstAttempt = false;
+                workDone = workLimit = 0;
+                SimpleSort(0, last, 0);
+            } else {
+                numQSorted = 0;
+                for (i = 0; i <= 255; i++) {
+                    bigDone[i] = false;
+                }
+
+                for (i = 0; i <= 65536; i++) {
+                    ftab[i] = 0;
+                }
+
+                c1 = block[0];
+                for (i = 0; i <= last; i++) {
+                    c2 = block[i + 1];
+                    ftab[(c1 << 8) + c2]++;
+                    c1 = c2;
+                }
+
+                for (i = 1; i <= 65536; i++) {
+                    ftab[i] += ftab[i - 1];
+                }
+
+                c1 = block[1];
+                for (i = 0; i < last; i++) {
+                    c2 = block[i + 2];
+                    j = (c1 << 8) + c2;
+                    c1 = c2;
+                    ftab[j]--;
+                    zptr[ftab[j]] = i;
+                }
+
+                j = ((block[last + 1]) << 8) + (block[1]);
+                ftab[j]--;
+                zptr[ftab[j]] = last;
+
+                /*
+                Now ftab contains the first loc of every small bucket.
+                Calculate the running order, from smallest to largest
+                big bucket.
+                */
+
+                for (i = 0; i <= 255; i++) {
+                    runningOrder[i] = i;
+                }
+
+                {
+                    int vv;
+                    int h = 1;
+                    do {
+                        h = 3 * h + 1;
+                    }
+                    while (h <= 256);
+                    do {
+                        h = h / 3;
+                        for (i = h; i <= 255; i++) {
+                            vv = runningOrder[i];
+                            j = i;
+                            while ((ftab[((runningOrder[j - h]) + 1) << 8]
+                                    - ftab[(runningOrder[j - h]) << 8]) >
+                                (ftab[((vv) + 1) << 8] - ftab[(vv) << 8])) {
+                                runningOrder[j] = runningOrder[j - h];
+                                j = j - h;
+                                if (j <= (h - 1)) {
+                                    break;
+                                }
+                            }
+                            runningOrder[j] = vv;
+                        }
+                    } while (h != 1);
+                }
+
+                /*
+                The main sorting loop.
+                */
+                for (i = 0; i <= 255; i++) {
+
+                    /*
+                    Process big buckets, starting with the least full.
+                    */
+                    ss = runningOrder[i];
+
+                    /*
+                    Complete the big bucket [ss] by quicksorting
+                    any unsorted small buckets [ss, j].  Hopefully
+                    previous pointer-scanning phases have already
+                    completed many of the small buckets [ss, j], so
+                    we don't have to sort them at all.
+                    */
+                    for (j = 0; j <= 255; j++) {
+                        sb = (ss << 8) + j;
+                        if (!((ftab[sb] & SETMASK) == SETMASK)) {
+                            int lo = ftab[sb] & CLEARMASK;
+                            int hi = (ftab[sb + 1] & CLEARMASK) - 1;
+                            if (hi > lo) {
+                                QSort3(lo, hi, 2);
+                                numQSorted += (hi - lo + 1);
+                                if (workDone > workLimit && firstAttempt) {
+                                    return;
+                                }
+                            }
+                            ftab[sb] |= SETMASK;
+                        }
+                    }
+
+                    /*
+                    The ss big bucket is now done.  Record this fact,
+                    and update the quadrant descriptors.  Remember to
+                    update quadrants in the overshoot area too, if
+                    necessary.  The "if (i < 255)" test merely skips
+                    this updating for the last bucket processed, since
+                    updating for the last bucket is pointless.
+                    */
+                    bigDone[ss] = true;
+
+                    if (i < 255) {
+                        int bbStart  = ftab[ss << 8] & CLEARMASK;
+                        int bbSize   = (ftab[(ss + 1) << 8] & CLEARMASK) - bbStart;
+                        int shifts   = 0;
+
+                        while ((bbSize >> shifts) > 65534) {
+                            shifts++;
+                        }
+
+                        for (j = 0; j < bbSize; j++) {
+                            int a2update = zptr[bbStart + j];
+                            int qVal = (j >> shifts);
+                            quadrant[a2update] = qVal;
+                            if (a2update < BZip2Constants.NUM_OVERSHOOT_BYTES) {
+                                quadrant[a2update + last + 1] = qVal;
+                            }
+                        }
+
+                        if (!(((bbSize - 1) >> shifts) <= 65535)) {
+                            Panic();
+                        }
+                    }
+
+                    /*
+                    Now scan this big bucket so as to synthesise the
+                    sorted order for small buckets [t, ss] for all t != ss.
+                    */
+                    for (j = 0; j <= 255; j++) {
+                        copy[j] = ftab[(j << 8) + ss] & CLEARMASK;
+                    }
+
+                    for (j = ftab[ss << 8] & CLEARMASK;
+                        j < (ftab[(ss + 1) << 8] & CLEARMASK); j++) {
+                        c1 = block[zptr[j]];
+                        if (!bigDone[c1]) {
+                            zptr[copy[c1]] = zptr[j] == 0 ? last : zptr[j] - 1;
+                            copy[c1]++;
+                        }
+                    }
+
+                    for (j = 0; j <= 255; j++) {
+                        ftab[(j << 8) + ss] |= SETMASK;
+                    }
+                }
+            }
+        }
+
+        private void RandomiseBlock() {
+            int i;
+            int rNToGo = 0;
+            int rTPos  = 0;
+            for (i = 0; i < 256; i++) {
+                inUse[i] = false;
+            }
+
+            for (i = 0; i <= last; i++) {
+                if (rNToGo == 0) {
+                    rNToGo = (char) BZip2Constants.rNums[rTPos];
+                    rTPos++;
+                    if (rTPos == 512) {
+                        rTPos = 0;
+                    }
+                }
+                rNToGo--;
+                block[i + 1] ^= (char)((rNToGo == 1) ? 1 : 0);
+                // handle 16 bit signed numbers
+                block[i + 1] &= (char)0xFF;
+
+                inUse[block[i + 1]] = true;
+            }
+        }
+
+        private void DoReversibleTransformation() {
+            int i;
+
+            workLimit = workFactor * last;
+            workDone = 0;
+            blockRandomised = false;
+            firstAttempt = true;
+
+            MainSort();
+
+            if (workDone > workLimit && firstAttempt) {
+                RandomiseBlock();
+                workLimit = workDone = 0;
+                blockRandomised = true;
+                firstAttempt = false;
+                MainSort();
+            }
+
+            origPtr = -1;
+            for (i = 0; i <= last; i++) {
+                if (zptr[i] == 0) {
+                    origPtr = i;
+                    break;
+                }
+            };
+
+            if (origPtr == -1) {
+                Panic();
+            }
+        }
+
+        private bool FullGtU(int i1, int i2) {
+            int k;
+            char c1, c2;
+            int s1, s2;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            c1 = block[i1 + 1];
+            c2 = block[i2 + 1];
+            if (c1 != c2) {
+                return (c1 > c2);
+            }
+            i1++;
+            i2++;
+
+            k = last + 1;
+
+            do {
+                c1 = block[i1 + 1];
+                c2 = block[i2 + 1];
+                if (c1 != c2) {
+                    return (c1 > c2);
+                }
+                s1 = quadrant[i1];
+                s2 = quadrant[i2];
+                if (s1 != s2) {
+                    return (s1 > s2);
+                }
+                i1++;
+                i2++;
+
+                c1 = block[i1 + 1];
+                c2 = block[i2 + 1];
+                if (c1 != c2) {
+                    return (c1 > c2);
+                }
+                s1 = quadrant[i1];
+                s2 = quadrant[i2];
+                if (s1 != s2) {
+                    return (s1 > s2);
+                }
+                i1++;
+                i2++;
+
+                c1 = block[i1 + 1];
+                c2 = block[i2 + 1];
+                if (c1 != c2) {
+                    return (c1 > c2);
+                }
+                s1 = quadrant[i1];
+                s2 = quadrant[i2];
+                if (s1 != s2) {
+                    return (s1 > s2);
+                }
+                i1++;
+                i2++;
+
+                c1 = block[i1 + 1];
+                c2 = block[i2 + 1];
+                if (c1 != c2) {
+                    return (c1 > c2);
+                }
+                s1 = quadrant[i1];
+                s2 = quadrant[i2];
+                if (s1 != s2) {
+                    return (s1 > s2);
+                }
+                i1++;
+                i2++;
+
+                if (i1 > last) {
+                    i1 -= last;
+                    i1--;
+                };
+                if (i2 > last) {
+                    i2 -= last;
+                    i2--;
+                };
+
+                k -= 4;
+                workDone++;
+            } while (k >= 0);
+
+            return false;
+        }
+
+        /*
+        Knuth's increments seem to work better
+        than Incerpi-Sedgewick here.  Possibly
+        because the number of elems to sort is
+        usually small, typically <= 20.
+        */
+        private int[] incs = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                            9841, 29524, 88573, 265720,
+                            797161, 2391484 };
+
+        private void AllocateCompressStructures() {
+            int n = BZip2Constants.baseBlockSize * blockSize100k;
+            block = new char[(n + 1 + BZip2Constants.NUM_OVERSHOOT_BYTES)];
+            quadrant = new int[(n + BZip2Constants.NUM_OVERSHOOT_BYTES)];
+            zptr = new int[n];
+            ftab = new int[65537];
+
+            if (block == null || quadrant == null || zptr == null
+                || ftab == null) {
+                //int totalDraw = (n + 1 + NUM_OVERSHOOT_BYTES) + (n + NUM_OVERSHOOT_BYTES) + n + 65537;
+                //compressOutOfMemory ( totalDraw, n );
+            }
+
+            /*
+            The back end needs a place to store the MTF values
+            whilst it calculates the coding tables.  We could
+            put them in the zptr array.  However, these values
+            will fit in a short, so we overlay szptr at the
+            start of zptr, in the hope of reducing the number
+            of cache misses induced by the multiple traversals
+            of the MTF values when calculating coding tables.
+            Seems to improve compression speed by about 1%.
+            */
+            //    szptr = zptr;
+
+
+            szptr = new short[2 * n];
+        }
+
+        private void GenerateMTFValues() {
+            char[] yy = new char[256];
+            int  i, j;
+            char tmp;
+            char tmp2;
+            int zPend;
+            int wr;
+            int EOB;
+
+            MakeMaps();
+            EOB = nInUse + 1;
+
+            for (i = 0; i <= EOB; i++) {
+                mtfFreq[i] = 0;
+            }
+
+            wr = 0;
+            zPend = 0;
+            for (i = 0; i < nInUse; i++) {
+                yy[i] = (char) i;
+            }
+
+
+            for (i = 0; i <= last; i++) {
+                char ll_i;
+
+                ll_i = unseqToSeq[block[zptr[i]]];
+
+                j = 0;
+                tmp = yy[j];
+                while (ll_i != tmp) {
+                    j++;
+                    tmp2 = tmp;
+                    tmp = yy[j];
+                    yy[j] = tmp2;
+                };
+                yy[0] = tmp;
+
+                if (j == 0) {
+                    zPend++;
+                } else {
+                    if (zPend > 0) {
+                        zPend--;
+                        while (true) {
+                            switch (zPend % 2) {
+                            case 0:
+                                szptr[wr] = (short) BZip2Constants.RUNA;
+                                wr++;
+                                mtfFreq[BZip2Constants.RUNA]++;
+                                break;
+                            case 1:
+                                szptr[wr] = (short) BZip2Constants.RUNB;
+                                wr++;
+                                mtfFreq[BZip2Constants.RUNB]++;
+                                break;
+                            };
+                            if (zPend < 2) {
+                                break;
+                            }
+                            zPend = (zPend - 2) / 2;
+                        };
+                        zPend = 0;
+                    }
+                    szptr[wr] = (short) (j + 1);
+                    wr++;
+                    mtfFreq[j + 1]++;
+                }
+            }
+
+            if (zPend > 0) {
+                zPend--;
+                while (true) {
+                    switch (zPend % 2) {
+                    case 0:
+                        szptr[wr] = (short) BZip2Constants.RUNA;
+                        wr++;
+                        mtfFreq[BZip2Constants.RUNA]++;
+                        break;
+                    case 1:
+                        szptr[wr] = (short) BZip2Constants.RUNB;
+                        wr++;
+                        mtfFreq[BZip2Constants.RUNB]++;
+                        break;
+                    }
+                    if (zPend < 2) {
+                        break;
+                    }
+                    zPend = (zPend - 2) / 2;
+                }
+            }
+
+            szptr[wr] = (short) EOB;
+            wr++;
+            mtfFreq[EOB]++;
+
+            nMTF = wr;
+        }
+
+        public override int Read(byte[] buffer, int offset, int count) {
+            return 0;
+        }
+    
+        public override long Seek(long offset, SeekOrigin origin) {
+            return 0;
+        }
+    
+        public override void SetLength(long value) {
+        }
+    
+        public override void Write(byte[] buffer, int offset, int count) {
+            for (int k = 0; k < count; ++k) {
+                WriteByte(buffer[k + offset]);
+            }
+        }
+    
+        public override bool CanRead {
+            get {
+                return false;
+            }
+        }
+    
+        public override bool CanSeek {
+            get {
+                return false;
+            }
+        }
+    
+        public override bool CanWrite {
+            get {
+                return true;
+            }
+        }
+    
+        public override long Length {
+            get {
+                return 0;
+            }
+        }
+    
+        public override long Position {
+            get {
+                return 0;
+            }
+            set {
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/bzip2/src/CRC.cs b/BouncyCastle.AxCrypt/bzip2/src/CRC.cs
new file mode 100644
index 0000000..278a9f3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/bzip2/src/CRC.cs
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*
+ * This package is based on the work done by Keiron Liddle), Aftex Software
+ * <keiron at aftexsw.com> to whom the Ant project is very grateful for his
+ * great code.
+ */
+
+using System;
+
+namespace Org.BouncyCastle.Apache.Bzip2
+{
+	/**
+    * A simple class the hold and calculate the CRC for sanity checking
+    * of the data.
+    *
+    * @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+    */
+    internal class CRC 
+	{
+        public static readonly int[] crc32Table = {
+            unchecked((int)0x00000000), unchecked((int)0x04c11db7), unchecked((int)0x09823b6e), unchecked((int)0x0d4326d9),
+            unchecked((int)0x130476dc), unchecked((int)0x17c56b6b), unchecked((int)0x1a864db2), unchecked((int)0x1e475005),
+            unchecked((int)0x2608edb8), unchecked((int)0x22c9f00f), unchecked((int)0x2f8ad6d6), unchecked((int)0x2b4bcb61),
+            unchecked((int)0x350c9b64), unchecked((int)0x31cd86d3), unchecked((int)0x3c8ea00a), unchecked((int)0x384fbdbd),
+            unchecked((int)0x4c11db70), unchecked((int)0x48d0c6c7), unchecked((int)0x4593e01e), unchecked((int)0x4152fda9),
+            unchecked((int)0x5f15adac), unchecked((int)0x5bd4b01b), unchecked((int)0x569796c2), unchecked((int)0x52568b75),
+            unchecked((int)0x6a1936c8), unchecked((int)0x6ed82b7f), unchecked((int)0x639b0da6), unchecked((int)0x675a1011),
+            unchecked((int)0x791d4014), unchecked((int)0x7ddc5da3), unchecked((int)0x709f7b7a), unchecked((int)0x745e66cd),
+            unchecked((int)0x9823b6e0), unchecked((int)0x9ce2ab57), unchecked((int)0x91a18d8e), unchecked((int)0x95609039),
+            unchecked((int)0x8b27c03c), unchecked((int)0x8fe6dd8b), unchecked((int)0x82a5fb52), unchecked((int)0x8664e6e5),
+            unchecked((int)0xbe2b5b58), unchecked((int)0xbaea46ef), unchecked((int)0xb7a96036), unchecked((int)0xb3687d81),
+            unchecked((int)0xad2f2d84), unchecked((int)0xa9ee3033), unchecked((int)0xa4ad16ea), unchecked((int)0xa06c0b5d),
+            unchecked((int)0xd4326d90), unchecked((int)0xd0f37027), unchecked((int)0xddb056fe), unchecked((int)0xd9714b49),
+            unchecked((int)0xc7361b4c), unchecked((int)0xc3f706fb), unchecked((int)0xceb42022), unchecked((int)0xca753d95),
+            unchecked((int)0xf23a8028), unchecked((int)0xf6fb9d9f), unchecked((int)0xfbb8bb46), unchecked((int)0xff79a6f1),
+            unchecked((int)0xe13ef6f4), unchecked((int)0xe5ffeb43), unchecked((int)0xe8bccd9a), unchecked((int)0xec7dd02d),
+            unchecked((int)0x34867077), unchecked((int)0x30476dc0), unchecked((int)0x3d044b19), unchecked((int)0x39c556ae),
+            unchecked((int)0x278206ab), unchecked((int)0x23431b1c), unchecked((int)0x2e003dc5), unchecked((int)0x2ac12072),
+            unchecked((int)0x128e9dcf), unchecked((int)0x164f8078), unchecked((int)0x1b0ca6a1), unchecked((int)0x1fcdbb16),
+            unchecked((int)0x018aeb13), unchecked((int)0x054bf6a4), unchecked((int)0x0808d07d), unchecked((int)0x0cc9cdca),
+            unchecked((int)0x7897ab07), unchecked((int)0x7c56b6b0), unchecked((int)0x71159069), unchecked((int)0x75d48dde),
+            unchecked((int)0x6b93dddb), unchecked((int)0x6f52c06c), unchecked((int)0x6211e6b5), unchecked((int)0x66d0fb02),
+            unchecked((int)0x5e9f46bf), unchecked((int)0x5a5e5b08), unchecked((int)0x571d7dd1), unchecked((int)0x53dc6066),
+            unchecked((int)0x4d9b3063), unchecked((int)0x495a2dd4), unchecked((int)0x44190b0d), unchecked((int)0x40d816ba),
+            unchecked((int)0xaca5c697), unchecked((int)0xa864db20), unchecked((int)0xa527fdf9), unchecked((int)0xa1e6e04e),
+            unchecked((int)0xbfa1b04b), unchecked((int)0xbb60adfc), unchecked((int)0xb6238b25), unchecked((int)0xb2e29692),
+            unchecked((int)0x8aad2b2f), unchecked((int)0x8e6c3698), unchecked((int)0x832f1041), unchecked((int)0x87ee0df6),
+            unchecked((int)0x99a95df3), unchecked((int)0x9d684044), unchecked((int)0x902b669d), unchecked((int)0x94ea7b2a),
+            unchecked((int)0xe0b41de7), unchecked((int)0xe4750050), unchecked((int)0xe9362689), unchecked((int)0xedf73b3e),
+            unchecked((int)0xf3b06b3b), unchecked((int)0xf771768c), unchecked((int)0xfa325055), unchecked((int)0xfef34de2),
+            unchecked((int)0xc6bcf05f), unchecked((int)0xc27dede8), unchecked((int)0xcf3ecb31), unchecked((int)0xcbffd686),
+            unchecked((int)0xd5b88683), unchecked((int)0xd1799b34), unchecked((int)0xdc3abded), unchecked((int)0xd8fba05a),
+            unchecked((int)0x690ce0ee), unchecked((int)0x6dcdfd59), unchecked((int)0x608edb80), unchecked((int)0x644fc637),
+            unchecked((int)0x7a089632), unchecked((int)0x7ec98b85), unchecked((int)0x738aad5c), unchecked((int)0x774bb0eb),
+            unchecked((int)0x4f040d56), unchecked((int)0x4bc510e1), unchecked((int)0x46863638), unchecked((int)0x42472b8f),
+            unchecked((int)0x5c007b8a), unchecked((int)0x58c1663d), unchecked((int)0x558240e4), unchecked((int)0x51435d53),
+            unchecked((int)0x251d3b9e), unchecked((int)0x21dc2629), unchecked((int)0x2c9f00f0), unchecked((int)0x285e1d47),
+            unchecked((int)0x36194d42), unchecked((int)0x32d850f5), unchecked((int)0x3f9b762c), unchecked((int)0x3b5a6b9b),
+            unchecked((int)0x0315d626), unchecked((int)0x07d4cb91), unchecked((int)0x0a97ed48), unchecked((int)0x0e56f0ff),
+            unchecked((int)0x1011a0fa), unchecked((int)0x14d0bd4d), unchecked((int)0x19939b94), unchecked((int)0x1d528623),
+            unchecked((int)0xf12f560e), unchecked((int)0xf5ee4bb9), unchecked((int)0xf8ad6d60), unchecked((int)0xfc6c70d7),
+            unchecked((int)0xe22b20d2), unchecked((int)0xe6ea3d65), unchecked((int)0xeba91bbc), unchecked((int)0xef68060b),
+            unchecked((int)0xd727bbb6), unchecked((int)0xd3e6a601), unchecked((int)0xdea580d8), unchecked((int)0xda649d6f),
+            unchecked((int)0xc423cd6a), unchecked((int)0xc0e2d0dd), unchecked((int)0xcda1f604), unchecked((int)0xc960ebb3),
+            unchecked((int)0xbd3e8d7e), unchecked((int)0xb9ff90c9), unchecked((int)0xb4bcb610), unchecked((int)0xb07daba7),
+            unchecked((int)0xae3afba2), unchecked((int)0xaafbe615), unchecked((int)0xa7b8c0cc), unchecked((int)0xa379dd7b),
+            unchecked((int)0x9b3660c6), unchecked((int)0x9ff77d71), unchecked((int)0x92b45ba8), unchecked((int)0x9675461f),
+            unchecked((int)0x8832161a), unchecked((int)0x8cf30bad), unchecked((int)0x81b02d74), unchecked((int)0x857130c3),
+            unchecked((int)0x5d8a9099), unchecked((int)0x594b8d2e), unchecked((int)0x5408abf7), unchecked((int)0x50c9b640),
+            unchecked((int)0x4e8ee645), unchecked((int)0x4a4ffbf2), unchecked((int)0x470cdd2b), unchecked((int)0x43cdc09c),
+            unchecked((int)0x7b827d21), unchecked((int)0x7f436096), unchecked((int)0x7200464f), unchecked((int)0x76c15bf8),
+            unchecked((int)0x68860bfd), unchecked((int)0x6c47164a), unchecked((int)0x61043093), unchecked((int)0x65c52d24),
+            unchecked((int)0x119b4be9), unchecked((int)0x155a565e), unchecked((int)0x18197087), unchecked((int)0x1cd86d30),
+            unchecked((int)0x029f3d35), unchecked((int)0x065e2082), unchecked((int)0x0b1d065b), unchecked((int)0x0fdc1bec),
+            unchecked((int)0x3793a651), unchecked((int)0x3352bbe6), unchecked((int)0x3e119d3f), unchecked((int)0x3ad08088),
+            unchecked((int)0x2497d08d), unchecked((int)0x2056cd3a), unchecked((int)0x2d15ebe3), unchecked((int)0x29d4f654),
+            unchecked((int)0xc5a92679), unchecked((int)0xc1683bce), unchecked((int)0xcc2b1d17), unchecked((int)0xc8ea00a0),
+            unchecked((int)0xd6ad50a5), unchecked((int)0xd26c4d12), unchecked((int)0xdf2f6bcb), unchecked((int)0xdbee767c),
+            unchecked((int)0xe3a1cbc1), unchecked((int)0xe760d676), unchecked((int)0xea23f0af), unchecked((int)0xeee2ed18),
+            unchecked((int)0xf0a5bd1d), unchecked((int)0xf464a0aa), unchecked((int)0xf9278673), unchecked((int)0xfde69bc4),
+            unchecked((int)0x89b8fd09), unchecked((int)0x8d79e0be), unchecked((int)0x803ac667), unchecked((int)0x84fbdbd0),
+            unchecked((int)0x9abc8bd5), unchecked((int)0x9e7d9662), unchecked((int)0x933eb0bb), unchecked((int)0x97ffad0c),
+            unchecked((int)0xafb010b1), unchecked((int)0xab710d06), unchecked((int)0xa6322bdf), unchecked((int)0xa2f33668),
+            unchecked((int)0xbcb4666d), unchecked((int)0xb8757bda), unchecked((int)0xb5365d03), unchecked((int)0xb1f740b4)
+        };
+
+        public CRC() {
+            InitialiseCRC();
+        }
+
+        internal void InitialiseCRC() {
+            globalCrc = unchecked((int)0xffffffff);
+        }
+
+        internal int GetFinalCRC() {
+            return ~globalCrc;
+        }
+
+        internal int GetGlobalCRC() {
+            return globalCrc;
+        }
+
+        internal void SetGlobalCRC(int newCrc) {
+            globalCrc = newCrc;
+        }
+
+        internal void UpdateCRC(int inCh) {
+            int temp = (globalCrc >> 24) ^ inCh;
+            if (temp < 0) {
+                temp = 256 + temp;
+            }
+            globalCrc = (globalCrc << 8) ^ CRC.crc32Table[temp];
+        }
+
+        internal int globalCrc;
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/checklist.txt b/BouncyCastle.AxCrypt/checklist.txt
new file mode 100644
index 0000000..0057b6e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/checklist.txt
@@ -0,0 +1,16 @@
+-----------------
+Release Checklist
+-----------------
+
+- Update to latest from git
+- Run 'nant -t:net-1.1 clean test'
+- Run 'nant -t:netcf-1.0 clean compile-release'
+- Edit AssemblyInfo.cs: Change version and check copyright
+- Edit NBuild.build: Change version
+- Edit License.html: Check copyright
+- Edit Readme.html: Add release notes
+- Commit changes to git
+- Tag git repository with "release-${version}" 
+- Push changes/tag to git
+- Place BouncyCastle.snk in parent directory
+- Run 'nant -t:net-1.1 clean dist'
diff --git a/BouncyCastle.AxCrypt/crypto.csproj b/BouncyCastle.AxCrypt/crypto.csproj
new file mode 100644
index 0000000..1c6a63a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/crypto.csproj
@@ -0,0 +1,3994 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
+  <PropertyGroup>
+    <ProjectType>Local</ProjectType>
+    <ProductVersion>7.10.3077</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{38872A5F-E87E-4FAD-B109-8EB7B2E6A4A0}</ProjectGuid>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ApplicationIcon />
+    <AssemblyKeyContainerName />
+    <AssemblyName>Portable.BouncyCastle</AssemblyName>
+    <DefaultClientScript>JScript</DefaultClientScript>
+    <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
+    <DefaultTargetSchema>IE50</DefaultTargetSchema>
+    <DelaySign>false</DelaySign>
+    <OutputType>Library</OutputType>
+    <RootNamespace>crypto</RootNamespace>
+    <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
+    <StartupObject />
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>12.0</OldToolsVersion>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <OutputPath>bin\Debug\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile />
+    <DefineConstants>TRACE;DEBUG;SILVERLIGHT;PCL</DefineConstants>
+    <DocumentationFile>doc\crypto.xml</DocumentationFile>
+    <DebugSymbols>true</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>1591</NoWarn>
+    <Optimize>false</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>full</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <OutputPath>bin\Release\</OutputPath>
+    <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+    <BaseAddress>285212672</BaseAddress>
+    <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+    <ConfigurationOverrideFile />
+    <DefineConstants>TRACE;SILVERLIGHT;PCL</DefineConstants>
+    <DocumentationFile>doc\crypto.xml</DocumentationFile>
+    <DebugSymbols>true</DebugSymbols>
+    <FileAlignment>4096</FileAlignment>
+    <NoStdLib>false</NoStdLib>
+    <NoWarn>1591</NoWarn>
+    <Optimize>true</Optimize>
+    <RegisterForComInterop>false</RegisterForComInterop>
+    <RemoveIntegerChecks>false</RemoveIntegerChecks>
+    <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+    <WarningLevel>4</WarningLevel>
+    <DebugType>pdbonly</DebugType>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="bzip2\src\BZip2Constants.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="bzip2\src\CBZip2InputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="bzip2\src\CBZip2OutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="bzip2\src\CRC.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Encodable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1EncodableVector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\Asn1Exception.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Generator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1InputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Null.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Object.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1OctetString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1OctetStringParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1OutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\Asn1ParsingException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Sequence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1SequenceParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Set.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1SetParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1StreamParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1TaggedObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1TaggedObjectParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ASN1Tags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\bc\BCObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERApplicationSpecific.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERApplicationSpecificParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERNull.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BEROctetString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BEROctetStringGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BEROctetStringParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BEROutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSequence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSequenceGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSequenceParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSetGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERSetParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERTaggedObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\BERTaggedObjectParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CAKeyUpdAnnContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertConfirmContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertifiedKeyPair.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertOrEncCert.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertRepMessage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertResponse.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CertStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\Challenge.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CmpCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CmpObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\CrlAnnContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\ErrorMsgContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\GenMsgContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\GenRepContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\InfoTypeAndValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\KeyRecRepContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\OobCertHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PbmParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIBody.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIConfirmContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIFailureInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIFreeText.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIHeader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIHeaderBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIMessage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIMessages.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PKIStatusInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PollRepContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PollReqContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PopoDecKeyChallContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\PopoDecKeyRespContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\ProtectedPart.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\RevAnnContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\RevDetails.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\RevRepContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\RevRepContentBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cmp\RevReqContent.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\Attribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\Attributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\AttributeTable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\AuthenticatedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\AuthenticatedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\AuthEnvelopedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\AuthEnvelopedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\CMSAttributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\CMSObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\CompressedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\CompressedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\ContentInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\ContentInfoParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\ecc\MQVuserKeyingMaterial.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\EncryptedContentInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\EncryptedContentInfoParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\EncryptedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\EnvelopedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\EnvelopedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\Evidence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\IssuerAndSerialNumber.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\KEKIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\KEKRecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\KeyAgreeRecipientIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\KeyAgreeRecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\KeyTransRecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\MetaData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OriginatorIdentifierOrKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OriginatorInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OriginatorPublicKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OtherKeyAttribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OtherRecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\OtherRevocationInfoFormat.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\PasswordRecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\RecipientEncryptedKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\RecipientIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\RecipientInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\RecipientKeyIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\SCVPReqRes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\SignedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\SignedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\SignerIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\SignerInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\Time.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\TimeStampAndCRL.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\TimeStampedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\TimeStampedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cms\TimeStampTokenEvidence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ConstructedOctetStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\AttributeTypeAndValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertReqMessages.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertReqMsg.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertTemplate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CertTemplateBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\Controls.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\CrmfObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\EncKeyWithID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\EncryptedKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\EncryptedValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\OptionalValidity.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PKIArchiveOptions.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PKIPublicationInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PKMacValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PopoPrivKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PopoSigningKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\PopoSigningKeyInput.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\ProofOfPossession.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\SinglePubInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\crmf\SubsequentMessage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\CryptoProObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\ECGOST3410NamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\ECGOST3410ParamSetParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\GOST28147Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\GOST3410NamedParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\GOST3410ParamSetParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\cryptopro\GOST3410PublicKeyAlgParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DefiniteLengthInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERApplicationSpecific.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERBitString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERBMPString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERBoolean.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DEREnumerated.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERExternal.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERExternalParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERGeneralizedTime.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERGeneralString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERIA5String.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERInteger.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERNull.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERNumericString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERObjectIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DEROctetString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DEROctetStringParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DEROutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERPrintableString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSequence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSequenceGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSequenceParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSetGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERSetParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DerStringBase.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERT61String.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERTaggedObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERUniversalString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERUTCTime.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERUTF8String.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\DERVisibleString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\eac\EACObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CertificateValues.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CommitmentTypeIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CommitmentTypeIndication.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CommitmentTypeQualifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CompleteCertificateRefs.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CompleteRevocationRefs.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CrlIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CrlListID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CrlOcspRef.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\CrlValidatedID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\ESFAttributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OcspIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OcspListID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OcspResponsesID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherCertID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherHashAlgAndValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherRevRefs.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherRevVals.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\OtherSigningCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\RevocationValues.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\SignaturePolicyId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\SignaturePolicyIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\SignerAttribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\SignerLocation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\esf\SigPolicyQualifierInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\ContentHints.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\ContentIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\ESSCertID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\ESSCertIDv2.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\OtherCertID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\OtherSigningCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\SigningCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ess\SigningCertificateV2.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\gnu\GNUObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\iana\IANAObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\IAsn1ApplicationSpecificParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\IAsn1Choice.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\IAsn1Convertible.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\IAsn1String.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\icao\CscaMasterList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\icao\DataGroupHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\icao\ICAOObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\icao\LDSSecurityObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\icao\LDSVersionInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\IndefiniteLengthInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\ISISMTTObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\ocsp\CertHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\ocsp\RequestedCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\AdditionalInformationSyntax.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\Admissions.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\AdmissionSyntax.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\DeclarationOfMajority.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\MonetaryLimit.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\NamingAuthority.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\ProcurationSyntax.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\ProfessionInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\isismtt\x509\Restriction.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\kisa\KISAObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\LazyASN1InputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\LazyDERSequence.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\LazyDERSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\LimitedInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\microsoft\MicrosoftObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\CAST5CBCParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\IDEACBCPar.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\MiscObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\NetscapeCertType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\NetscapeRevocationURL.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\misc\VerisignCzagExtension.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\mozilla\PublicKeyAndChallenge.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\nist\NISTNamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\nist\NISTObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ntt\NTTObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\BasicOCSPResponse.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\CertID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\CertStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\CrlID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\OCSPObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\OCSPRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\OCSPResponse.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\OCSPResponseStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\Request.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\ResponderID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\ResponseBytes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\ResponseData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\RevokedInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\ServiceLocator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\Signature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\SingleResponse.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\ocsp\TBSRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\OIDTokenizer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\oiw\ElGamalParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\oiw\OIWObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\Attribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\AuthenticatedSafe.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\CertBag.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\CertificationRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\CertificationRequestInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\ContentInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\DHParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\EncryptedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\EncryptedPrivateKeyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\EncryptionScheme.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\IssuerAndSerialNumber.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\KeyDerivationFunc.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\MacData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PBEParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PBES2Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PBKDF2Params.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\Pfx.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PKCS12PBEParams.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PKCSObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\PrivateKeyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\RC2CBCParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\RSAESOAEPparams.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\RSAPrivateKeyStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\RSASSAPSSparams.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\SafeBag.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\SignedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\pkcs\SignerInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\sec\ECPrivateKeyStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\sec\SECNamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\sec\SECObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMEAttributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMECapabilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMECapabilitiesAttribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMECapability.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMECapabilityVector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\smime\SMIMEEncryptionKeyPreferenceAttribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\teletrust\TeleTrusTNamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\teletrust\TeleTrusTObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\tsp\Accuracy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\tsp\MessageImprint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\tsp\TimeStampReq.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\tsp\TimeStampResp.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\tsp\TSTInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\util\ASN1Dump.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\util\Dump.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\util\FilterStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x500\DirectoryString.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AccessDescription.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AlgorithmIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AttCertIssuer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AttCertValidityPeriod.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\Attribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AttributeCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AttributeCertificateInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AttributeTable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AuthorityInformationAccess.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\AuthorityKeyIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\BasicConstraints.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CertificateList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CertificatePair.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CertificatePolicies.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CertPolicyId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CRLDistPoint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CRLNumber.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\CRLReason.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\DigestInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\DisplayText.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\DistributionPoint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\DistributionPointName.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\DSAParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\ExtendedKeyUsage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\GeneralName.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\GeneralNames.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\GeneralSubtree.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\Holder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\IetfAttrSyntax.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\IssuerSerial.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\IssuingDistributionPoint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\KeyPurposeId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\KeyUsage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\NameConstraints.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\NoticeReference.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\ObjectDigestInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\PolicyInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\PolicyMappings.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\PolicyQualifierId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\PolicyQualifierInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\PrivateKeyUsagePeriod.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\BiometricData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\ETSIQCObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\Iso4217CurrencyCode.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\MonetaryValue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\QCStatement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\RFC3739QCObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\SemanticsInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\qualified\TypeOfBiometricData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\ReasonFlags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\RoleSyntax.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\RSAPublicKeyStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\sigi\NameOrPseudonym.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\sigi\PersonalData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\sigi\SigIObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\SubjectDirectoryAttributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\SubjectKeyIdentifier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\SubjectPublicKeyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\Target.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\TargetInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\Targets.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\TBSCertificateStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\TBSCertList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\Time.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\UserNotice.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\V1TBSCertificateGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\V2AttributeCertificateInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\V2Form.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\V2TBSCertListGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\V3TBSCertificateGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509Attributes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509CertificateStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509DefaultEntryConverter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509Extension.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509Extensions.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509ExtensionsGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509Name.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509NameEntryConverter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509NameTokenizer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x509\X509ObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\DHDomainParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\DHPublicKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\DHValidationParms.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\ECNamedCurveTable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\KeySpecificInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\OtherInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X962NamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X962Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9ECParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9ECParametersHolder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9ECPoint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9FieldID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9IntegerConverter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\asn1\x9\X9ObjectIdentifiers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ArmoredInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ArmoredOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\attr\ImageAttrib.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\BCPGInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\BCPGObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\BCPGOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\CompressedDataPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\CompressionAlgorithmTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ContainedPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\CRC24.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\DSAPublicBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\DSASecretBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ElGamalPublicBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ElGamalSecretBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ExperimentalPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\HashAlgorithmTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\IBcpgKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\InputStreamPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\LiteralDataPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\MarkerPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\ModDetectionCodePacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\MPInteger.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\OnePassSignaturePacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\OutputStreamPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\Packet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\PacketTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\PublicKeyAlgorithmTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\PublicKeyEncSessionPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\PublicKeyPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\PublicSubkeyPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\RSAPublicBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\RSASecretBCPGKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\S2K.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SecretKeyPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SecretSubkeyPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SignaturePacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SignatureSubpacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SignatureSubpacketsReader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SignatureSubpacketTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\EmbeddedSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\Exportable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\IssuerKeyID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\KeyExpirationTime.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\KeyFlags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\NotationData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\PreferredAlgorithms.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\PrimaryUserID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\Revocable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\RevocationKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\RevocationKeyTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\RevocationReason.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\RevocationReasonTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\SignatureCreationTime.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\SignatureExpirationTime.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\SignerUserID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\sig\TrustSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SymmetricEncDataPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SymmetricEncIntegrityPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SymmetricKeyAlgorithmTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\SymmetricKeyEncSessionPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\TrustPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\UserAttributePacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\UserAttributeSubpacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\UserAttributeSubpacketsReader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\UserAttributeSubpacketTags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\bcpg\UserIDPacket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\BaseDigestCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAttributeTableGenerationException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAttributeTableGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthenticatedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthenticatedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthenticatedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthenticatedDataStreamGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthenticatedGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthEnvelopedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSAuthEnvelopedGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSCompressedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSCompressedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSCompressedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSCompressedDataStreamGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSContentInfoParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedDataStreamGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSEnvelopedHelper.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSPBEKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSProcessable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSProcessableByteArray.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSProcessableFile.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSProcessableInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSReadable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSecureReadable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedDataParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedDataStreamGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSSignedHelper.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSStreamException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSTypedStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CMSUtils.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\CounterSignatureDigestCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\DefaultAuthenticatedAttributeTableGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\DefaultSignedAttributeTableGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\DigOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\IDigestCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KEKRecipientInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KEKRecipientInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KeyAgreeRecipientInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KeyAgreeRecipientInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KeyTransRecipientInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\KeyTransRecipientInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\MacOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\OriginatorId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\OriginatorInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\OriginatorInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\PasswordRecipientInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\PasswordRecipientInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\PKCS5Scheme2PBEKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\PKCS5Scheme2UTF8PBEKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\RecipientId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\RecipientInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\RecipientInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\RecipientInformationStore.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SignerId.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SignerInfoGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SignerInformation.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SignerInformationStore.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SigOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\cms\SimpleAttributeTableGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\DHAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\DHBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\DHStandardGroups.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\ECDHBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\ECDHCBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\ECDHWithKdfBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\ECMqvBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\ECMqvWithKdfBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\kdf\DHKdfParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\kdf\DHKekGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\kdf\ECDHKekGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\srp\SRP6Client.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\srp\SRP6Server.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\srp\SRP6Utilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\agreement\srp\SRP6VerifierGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\AsymmetricCipherKeyPair.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\AsymmetricKeyParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedAeadBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedAsymmetricBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedCipherBase.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedIesCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\BufferedStreamCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\CipherKeyGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\CryptoException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\DataLengthException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\GeneralDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\GOST3411Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\LongDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\MD2Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\MD4Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\MD5Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\NullDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\RIPEMD128Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\RIPEMD160Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\RIPEMD256Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\RIPEMD320Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha1Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha224Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha256Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha384Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha3Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha512Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\Sha512tDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\ShortenedDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\SkeinDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\SkeinEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\SM3Digest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\TigerDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\digests\WhirlpoolDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\ec\CustomNamedCurves.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\encodings\ISO9796d1Encoding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\encodings\OAEPEncoding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\encodings\PKCS1Encoding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\AESEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\AESFastEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\AESLightEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\AESWrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\BlowfishEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\CamelliaEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\CamelliaLightEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\CamelliaWrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\CAST5Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\CAST6Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\ChaChaEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\DESedeEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\DESedeWrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\DesEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\ElGamalEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\GOST28147Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\HC128Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\HC256Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\IDEAEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\IESEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\ISAACEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\NaccacheSternEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\NoekeonEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\NullEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC2Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC2WrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC4Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC532Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC564Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RC6Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RFC3211WrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RFC3394WrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RijndaelEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RSABlindedEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RSABlindingEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RSACoreEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\RSAEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\Salsa20Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\SEEDEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\SEEDWrapEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\SerpentEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\SkipjackEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\TEAEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\ThreefishEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\TwofishEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\VMPCEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\VMPCKSA3Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\XSalsa20Engine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\engines\XTEAEngine.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\BaseKDFBytesGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DESedeKeyGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DESKeyGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DHBasicKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DHKeyGeneratorHelper.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DHKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DHParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DHParametersHelper.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DSAKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\DSAParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\ECKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\ElGamalKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\ElGamalParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\GOST3410KeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\GOST3410ParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\KDF1BytesGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\KDF2BytesGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\MGF1BytesGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\NaccacheSternKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\OpenSSLPBEParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\PKCS12ParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\PKCS5S1ParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\PKCS5S2ParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\Poly1305KeyGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\RSABlindingFactorGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\RSAKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\generators\SCrypt.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IAsymmetricBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IAsymmetricCipherKeyPairGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IBasicAgreement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IBufferedCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\ICipherParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IDerivationFunction.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IDerivationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IDigest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IDSA.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\InvalidCipherTextException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\io\CipherStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\io\DigestStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\io\MacStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\io\SignerStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\ISigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\ISignerWithRecovery.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IStreamCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\IWrapper.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\KeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\CBCBlockCipherMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\CFBBlockCipherMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\CMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\GMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\GOST28147Mac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\HMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\ISO9797Alg3Mac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\Poly1305.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\SipHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\SkeinMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\macs\VMPCMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\MaxBytesExceededException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\CBCBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\CCMBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\CFBBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\CTSBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\EAXBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\GCMBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\BasicGcmExponentiator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\BasicGcmMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\GcmUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\IGcmExponentiator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\IGcmMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\Tables1kGcmExponentiator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\Tables64kGcmMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\gcm\Tables8kGcmMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\GOFBBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\IAeadBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\OCBBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\OFBBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\OpenPGPCFBBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\modes\SICBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\BlockCipherPadding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\ISO10126d2Padding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\ISO7816d4Padding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\PaddedBufferedBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\PKCS7Padding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\TBCPadding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\X923Padding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\paddings\ZeroBytePadding.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\AEADParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\CCMParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DESedeParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DESParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHPrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHPublicKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DHValidationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAParameterGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAPrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAPublicKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\DSAValidationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ECDomainParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ECKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ECKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ECPrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ECPublicKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ElGamalKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ElGamalKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ElGamalParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ElGamalPrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ElGamalPublicKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410KeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410KeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410PrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410PublicKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\GOST3410ValidationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\IESParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\IESWithCipherParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ISO18033KDFParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\KDFParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\KeyParameter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\MGFParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\MqvPrivateParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\MqvPublicParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\NaccacheSternKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\NaccacheSternKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\NaccacheSternPrivateKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ParametersWithIV.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ParametersWithRandom.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ParametersWithSalt.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\ParametersWithSBox.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RC2Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RC5Parameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RSABlindingParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RSAKeyGenerationParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RSAKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\RSAPrivateCrtKeyParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\SkeinParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\parameters\TweakableBlockCipherParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\PBEParametersGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\CryptoApiRandomGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\DigestRandomGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\IRandomGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\ReversedWindowGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\ThreadedSeedGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\prng\VMPCRandomGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\DSADigestSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\DSASigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\ECDSASigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\ECGOST3410Signer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\ECNRSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\GenericSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\GOST3410DigestSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\GOST3410Signer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\HMacDsaKCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\IDsaKCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\ISO9796d2PSSSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\ISO9796d2Signer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\PSSSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\RandomDsaKCalculator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\signers\RSADigestSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\StreamBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsAgreementCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsCipherFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsClient.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsContext.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsEncryptionCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsPeer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsServer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AbstractTlsSignerCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AlertDescription.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\AlertLevel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\BulkCipherAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ByteQueue.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertChainType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\Certificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertificateRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertificateStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertificateStatusRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertificateStatusType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CertificateUrl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\Chacha20Poly1305.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ChangeCipherSpec.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CipherSuite.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CipherType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ClientAuthenticationType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ClientCertificateType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CombinedHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\CompressionMethod.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ConnectionEnd.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ContentType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsAgreementCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsCipherFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsClient.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsEncryptionCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsServer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DefaultTlsSignerCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DeferredHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DigestInputBuffer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\DigitallySigned.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ECBasisType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ECCurveType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ECPointFormat.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\EncryptionAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ExporterLabel.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ExtensionType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HandshakeType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HashAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HeartbeatExtension.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HeartbeatMessage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HeartbeatMessageType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\HeartbeatMode.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\KeyExchangeAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\MacAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\MaxFragmentLength.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\NamedCurve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\NameType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\NewSessionTicket.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\OcspStatusRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\PrfAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ProtocolVersion.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\PskTlsClient.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\RecordStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SecurityParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ServerDHParams.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ServerName.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ServerNameList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\ServerOnlyTlsAuthentication.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SessionParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SignatureAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SignatureAndHashAlgorithm.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SignerInputBuffer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SrpTlsClient.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SrtpProtectionProfile.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\Ssl3Mac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SupplementalDataEntry.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\SupplementalDataType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsAeadCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsAgreementCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsAuthentication.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsBlockCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsCipherFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsClient.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsClientContext.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsClientContextImpl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsClientProtocol.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsCompression.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsContext.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDeflateCompression.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDheKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDHKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDHUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDsaSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsDssSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsEccUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsECDheKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsECDHKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsECDsaSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsEncryptionCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsExtensionsUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsFatalAlert.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsHandshakeHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsMac.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsNullCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsNullCompression.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsPeer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsProtocol.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsProtocolHandler.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsPskIdentity.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsPskKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsRsaKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsRsaSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsRsaUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsServer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsServerContext.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsServerContextImpl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsServerProtocol.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSession.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSessionImpl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSigner.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSignerCredentials.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSrpKeyExchange.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSrpUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsSrtpUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsStreamCipher.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\TlsUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\UrlAndHash.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\UserMappingType.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\tls\UseSrtpData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\crypto\util\Pack.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\BigInteger.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\abc\SimpleBigDecimal.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\abc\Tnaf.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\abc\ZTauElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\djb\Curve25519.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\djb\Curve25519Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\djb\Curve25519FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\djb\Curve25519Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\Nat192.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\Nat224.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\Nat256.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\Nat384.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\Nat512.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192K1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192K1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192R1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP192R1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224K1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224K1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224R1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP224R1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256K1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256K1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256R1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP256R1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP384R1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP384R1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Curve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Field.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP521R1FieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\custom\sec\SecP521R1Point.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ECAlgorithms.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ECCurve.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ECFieldElement.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ECPoint.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ECPointMap.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\endo\ECEndomorphism.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\endo\GlvEndomorphism.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\endo\GlvTypeBEndomorphism.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\endo\GlvTypeBParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\LongArray.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\Mod.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\AbstractECMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\DoubleAddMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\ECMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\FixedPointCombMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\FixedPointPreCompInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\FixedPointUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\GlvMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\MixedNafR2LMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\MontgomeryLadderMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\NafL2RMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\NafR2LMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\PreCompInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\ReferenceMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\WNafL2RMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\WNafPreCompInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\WNafUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\WTauNafMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\WTauNafPreCompInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\ZSignedDigitL2RMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\multiplier\ZSignedDigitR2LMultiplier.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\Nat.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ScaleXPointMap.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\ec\ScaleYPointMap.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\FiniteFields.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\GenericPolynomialExtensionField.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\GF2Polynomial.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\IExtensionField.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\IFiniteField.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\IPolynomial.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\IPolynomialExtensionField.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\math\field\PrimeField.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\BasicOCSPResp.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\BasicOCSPRespGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\CertificateID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\CertificateStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPReq.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPReqGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPResp.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPRespGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPRespStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\OCSPUtil.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\Req.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\RespData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\RespID.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\RevokedStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\SingleResp.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\ocsp\UnknownStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\IStreamGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPCompressedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPCompressedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPDataValidationException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPEncryptedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPEncryptedDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPEncryptedDataList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PgpExperimental.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPKeyFlags.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPKeyPair.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPKeyRing.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPKeyRingGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPKeyValidationException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPLiteralData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPLiteralDataGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPMarker.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPObjectFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPOnePassSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPOnePassSignatureList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPPBEEncryptedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPPrivateKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPPublicKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPPublicKeyEncryptedData.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPPublicKeyRing.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PgpPublicKeyRingBundle.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSecretKey.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSecretKeyRing.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PgpSecretKeyRingBundle.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSignature.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSignatureGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSignatureList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSignatureSubpacketGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPSignatureSubpacketVector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPUserAttributeSubpacketVector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPUserAttributeSubpacketVectorGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PgpUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\PGPV3SignatureGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openpgp\WrappedGeneratorStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\EncryptionException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\IPasswordFinder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\MiscPemGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\PasswordException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\PEMException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\PEMReader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\PEMUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\PEMWriter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\openssl\Pkcs8Generator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\AsymmetricKeyEntry.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\EncryptedPrivateKeyInfoFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PKCS10CertificationRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\Pkcs10CertificationRequestDelaySigned.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PKCS12Entry.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PKCS12Store.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PKCS12StoreBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PKCS12Utilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\PrivateKeyInfoFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkcs\X509CertificateEntry.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\CertStatus.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixAttrCertChecker.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixAttrCertPathBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixAttrCertPathValidator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixBuilderParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPath.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathBuilder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathBuilderException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathBuilderResult.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathChecker.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathValidator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathValidatorException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathValidatorResult.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCertPathValidatorUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixCrlUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixNameConstraintValidator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixNameConstraintValidatorException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\PkixPolicyNode.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\ReasonsMask.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\Rfc3280CertPathUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\Rfc3281CertPathUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\pkix\TrustAnchor.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\AgreementUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CertificateEncodingException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CertificateException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CertificateExpiredException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CertificateNotYetValidException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CertificateParsingException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\cert\CrlException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\CipherUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\DigestUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\DotNetUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\GeneralSecurityException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\GeneratorUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\InvalidKeyException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\InvalidParameterException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\KeyException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\MacUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\NoSuchAlgorithmException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\ParameterUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\PbeUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\PrivateKeyFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\PublicKeyFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\SecureRandom.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\SecurityUtilityException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\SignatureException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\SignerUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\security\WrapperUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\GenTimeAccuracy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampRequest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampRequestGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampResponse.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampResponseGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampToken.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampTokenGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TimeStampTokenInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TSPAlgorithms.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TSPException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TSPUtil.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\tsp\TSPValidationException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Arrays.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\BigIntegers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\CollectionUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\EmptyEnumerable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\EnumerableProxy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\HashSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\ISet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\LinkedDictionary.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableDictionary.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableDictionaryProxy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableList.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableListProxy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableSet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\collections\UnmodifiableSetProxy.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\date\DateTimeObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\date\DateTimeUtilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\Base64.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\Base64Encoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\BufferedDecoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\BufferedEncoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\Hex.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\HexEncoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\HexTranslator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\IEncoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\Translator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\UrlBase64.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\encoders\UrlBase64Encoder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Enums.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\IMemoable.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Integers.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\BaseInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\BaseOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\NullOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemGenerationException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemHeader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemObject.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemObjectGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemObjectParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemReader.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\pem\PemWriter.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\PushbackStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\StreamOverflowException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\Streams.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\TeeInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\io\TeeOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\MemoableResetException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\net\IPAddress.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Platform.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Strings.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\Times.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\Adler32.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\Deflate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\InfBlocks.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\InfCodes.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\Inflate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\InfTree.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\JZlib.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\StaticTree.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\Tree.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\ZDeflaterOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\ZInflaterInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\ZInputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\ZOutputStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\util\zlib\ZStream.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\AttributeCertificateHolder.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\AttributeCertificateIssuer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\extension\AuthorityKeyIdentifierStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\extension\SubjectKeyIdentifierStructure.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\extension\X509ExtensionUtil.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\IX509AttributeCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\IX509Extension.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\PEMParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\PrincipalUtil.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\IX509Selector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\IX509Store.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\IX509StoreParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\NoSuchStoreException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509AttrCertStoreSelector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509CertPairStoreSelector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509CertStoreSelector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509CollectionStore.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509CollectionStoreParameters.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509CrlStoreSelector.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509StoreException.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\store\X509StoreFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\SubjectPublicKeyInfoFactory.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509AttrCertParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509Attribute.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509Certificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509CertificatePair.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509CertificateParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509CertPairParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509Crl.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509CrlEntry.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509CrlParser.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509ExtensionBase.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509KeyUsage.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509SignatureUtil.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509Utilities.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509V1CertificateGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509V2AttributeCertificate.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509V2AttributeCertificateGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509V2CRLGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="src\x509\X509V3CertificateGenerator.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Content Include="Contributors.html" />
+    <Content Include="License.html" />
+    <Content Include="Readme.html" />
+    <None Include="NBuild.build" />
+    <None Include="testcfg.nunit" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <PropertyGroup>
+    <PreBuildEvent />
+    <PostBuildEvent />
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/doc/crypto.xml b/BouncyCastle.AxCrypt/doc/crypto.xml
new file mode 100644
index 0000000..f1e39f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/doc/crypto.xml
@@ -0,0 +1,21747 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>Portable.BouncyCastle</name>
+    </assembly>
+    <members>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.BZip2Constants">
+             Base class for both the compress and decompress classes.
+             Holds common arrays, and static data.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CBZip2InputStream">
+             An input stream that decompresses from the BZip2 format (with the file
+             header chars) to be read as any other stream.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+            
+             <b>NB:</b> note this class has been modified to read the leading BZ from the
+             start of the BZIP2 stream to make it compatible with other PGP programs.
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CBZip2OutputStream">
+             An output stream that compresses into the BZip2 format (with the file
+             header chars) into another stream.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+            
+             TODO:    Update to BZip2 1.0.1
+             <b>NB:</b> note this class has been modified to add a leading BZ to the
+             start of the BZIP2 stream to make it compatible with other PGP programs.
+        </member>
+        <member name="M:Org.BouncyCastle.Apache.Bzip2.CBZip2OutputStream.WriteByte(System.Byte)">
+            
+             modified by Oliver Merkel, 010128
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CRC">
+             A simple class the hold and calculate the CRC for sanity checking
+             of the data.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Encodable.GetDerEncoded">
+             Return the DER encoding of the object, null if the DER encoding can not be made.
+            
+             @return a DER byte array, null otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1InputStream">
+            a general purpose ASN.1 decoder - note: this class differs from the
+            others in that it returns null after it has read the last object in
+            the stream. If an ASN.1 Null is encountered a Der/BER Null object is
+            returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.#ctor(System.IO.Stream,System.Int32)">
+             Create an ASN1InputStream where no DER object will be longer than limit.
+            
+             @param input stream containing ASN.1 encoded data.
+             @param limit maximum size of a DER encoded object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.#ctor(System.Byte[])">
+             Create an ASN1InputStream based on the input byte array. The length of DER objects in
+             the stream is automatically limited to the length of the input array.
+            
+             @param input array containing ASN.1 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.BuildObject(System.Int32,System.Int32,System.Int32)">
+            build an object given its tag and the number of bytes to construct it from.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1Null">
+            A Null object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Object.FromByteArray(System.Byte[])">
+            <summary>Create a base ASN.1 object from a byte array.</summary>
+            <param name="data">The byte array to parse.</param>
+            <returns>The base ASN.1 object represented by the byte array.</returns>
+            <exception cref="T:System.IO.IOException">If there is a problem parsing the data.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Object.FromStream(System.IO.Stream)">
+            <summary>Read a base ASN.1 object from a stream.</summary>
+            <param name="inStr">The stream to parse.</param>
+            <returns>The base ASN.1 object represented by the byte array.</returns>
+            <exception cref="T:System.IO.IOException">If there is a problem parsing the data.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Octet string from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                          be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.GetInstance(System.Object)">
+             return an Octet string from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.#ctor(System.Byte[])">
+            @param string the octets making up the octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(System.Object)">
+             return an Asn1Sequence from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return an ASN1 sequence from a tagged object. There is a special
+             case here, if an object appears to have been explicitly tagged on
+             reading but we were expecting it to be implicitly tagged in the
+             normal course of events it indicates that we lost the surrounding
+             sequence - so we need to add it back (this will happen if the tagged
+             object is a sequence that contains other sequences). If you are
+             dealing with implicitly tagged sequences you really <b>should</b>
+             be using this method.
+            
+             @param obj the tagged object.
+             @param explicitly true if the object is meant to be explicitly tagged,
+                      false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                      be converted.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Asn1Sequence.Item(System.Int32)">
+             return the object at the sequence position indicated by index.
+            
+             @param index the sequence number (starting at zero) of the object
+             @return the object at the sequence position indicated by index.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.GetInstance(System.Object)">
+             return an ASN1Set from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return an ASN1 set from a tagged object. There is a special
+             case here, if an object appears to have been explicitly tagged on
+             reading but we were expecting it to be implicitly tagged in the
+             normal course of events it indicates that we lost the surrounding
+             set - so we need to add it back (this will happen if the tagged
+             object is a sequence that contains other sequences). If you are
+             dealing with implicitly tagged sets you really <b>should</b>
+             be using this method.
+            
+             @param obj the tagged object.
+             @param explicitly true if the object is meant to be explicitly tagged
+                      false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                      be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.LessThanOrEqual(System.Byte[],System.Byte[])">
+            return true if a <= b (arrays are assumed padded with zeros).
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Asn1Set.Item(System.Int32)">
+             return the object at the set position indicated by index.
+            
+             @param index the set number (starting at zero) of the object
+             @return the object at the set position indicated by index.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1TaggedObject">
+            ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if the object is explicitly tagged.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.IsExplicit">
+            return whether or not the object may be explicitly tagged.
+            <p>
+            Note: if the object has been read from an input stream, the only
+            time you can be sure if isExplicit is returning the true state of
+            affairs is if it returns false. An implicitly tagged object may appear
+            to be explicitly tagged, so you need to understand the context under
+            which the reading was done as well, see GetObject below.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.GetObject">
+            return whatever was following the tag.
+            <p>
+            Note: tagged objects are generally context dependent if you're
+            trying to extract a tagged object you should be going via the
+            appropriate GetInstance method.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.GetObjectParser(System.Int32,System.Boolean)">
+            Return the object held in this tagged object as a parser assuming it has
+            the type of the passed in tag. If the object doesn't have a parser
+            associated with it, the base object is returned.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerApplicationSpecific">
+            Base class for an application specific object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerApplicationSpecific.GetObject">
+             Return the enclosed object assuming explicit tagging.
+            
+             @return  the resulting object
+             @throws IOException if reconstruction fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerApplicationSpecific.GetObject(System.Int32)">
+             Return the enclosed object assuming implicit tagging.
+            
+             @param derTagNo the type tag that should be applied to the object's contents.
+             @return  the resulting object
+             @throws IOException if reconstruction fails.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.BerNull">
+            A BER Null object.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerNull">
+            A Null object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerOctetString.#ctor(System.Byte[])">
+            <param name="str">The octets making up the octet string.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.ToBytes(System.Collections.IEnumerable)">
+            convert a vector of octet strings into a single byte string
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.#ctor(System.Byte[])">
+            <param name="str">The octets making up the octet string.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.GetEnumerator">
+            return the DER octets that make up this string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a sequence containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a sequence containing a vector of objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a sequence containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a sequence containing a vector of objects.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerSet">
+            A Der encoded set object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor">
+            create an empty set
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param obj - a single object that makes up the set.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            @param v - a vector of objects making up the set.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a set containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a set containing a vector of objects.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.BerTaggedObject">
+            BER TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerTaggedObject">
+            DER TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if an explicitly tagged object.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Int32)">
+            create an implicitly tagged object that contains a zero
+            length sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if an explicitly tagged object.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Int32)">
+            create an implicitly tagged object that contains a zero
+            length sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CAKeyUpdAnnContent.ToAsn1Object">
+            <pre>
+            CAKeyUpdAnnContent ::= SEQUENCE {
+                                        oldWithNew   CmpCertificate, -- old pub signed with new priv
+                                        newWithOld   CmpCertificate, -- new pub signed with old priv
+                                        newWithNew   CmpCertificate  -- new pub signed with new priv
+             }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertConfirmContent.ToAsn1Object">
+            <pre>
+            CertConfirmContent ::= SEQUENCE OF CertStatus
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertifiedKeyPair.ToAsn1Object">
+            <pre>
+            CertifiedKeyPair ::= SEQUENCE {
+                                             certOrEncCert       CertOrEncCert,
+                                             privateKey      [0] EncryptedValue      OPTIONAL,
+                                             -- see [CRMF] for comment on encoding
+                                             publicationInfo [1] PKIPublicationInfo  OPTIONAL
+                  }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IAsn1Choice">
+            Marker interface for CHOICE objects - if you implement this in a roll-your-own
+            object, any attempt to tag the object implicitly will convert the tag to an
+            explicit one as the encoding rules require.
+            <p>
+            If you use this interface your class should also implement the getInstance
+            pattern which takes a tag object and the tagging mode used. 
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertOrEncCert.ToAsn1Object">
+            <pre>
+            CertOrEncCert ::= CHOICE {
+                                 certificate     [0] CMPCertificate,
+                                 encryptedCert   [1] EncryptedValue
+                      }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertRepMessage.ToAsn1Object">
+            <pre>
+            CertRepMessage ::= SEQUENCE {
+                                     caPubs       [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+                                                                                        OPTIONAL,
+                                     response         SEQUENCE OF CertResponse
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertResponse.ToAsn1Object">
+            <pre>
+            CertResponse ::= SEQUENCE {
+                                       certReqId           INTEGER,
+                                       -- to match this response with corresponding request (a value
+                                       -- of -1 is to be used if certReqId is not specified in the
+                                       -- corresponding request)
+                                       status              PKIStatusInfo,
+                                       certifiedKeyPair    CertifiedKeyPair    OPTIONAL,
+                                       rspInfo             OCTET STRING        OPTIONAL
+                                       -- analogous to the id-regInfo-utf8Pairs string defined
+                                       -- for regInfo in CertReqMsg [CRMF]
+                        }
+            </pre> 
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertStatus.ToAsn1Object">
+            <pre>
+            CertStatus ::= SEQUENCE {
+                              certHash    OCTET STRING,
+                              -- the hash of the certificate, using the same hash algorithm
+                              -- as is used to create and verify the certificate signature
+                              certReqId   INTEGER,
+                              -- to match this confirmation with the corresponding req/rep
+                              statusInfo  PKIStatusInfo OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.Challenge.ToAsn1Object">
+             <pre>
+             Challenge ::= SEQUENCE {
+                             owf                 AlgorithmIdentifier  OPTIONAL,
+            
+                             -- MUST be present in the first Challenge; MAY be omitted in
+                             -- any subsequent Challenge in POPODecKeyChallContent (if
+                             -- omitted, then the owf used in the immediately preceding
+                             -- Challenge is to be used).
+            
+                             witness             OCTET STRING,
+                             -- the result of applying the one-way function (owf) to a
+                             -- randomly-generated INTEGER, A.  [Note that a different
+                             -- INTEGER MUST be used for each Challenge.]
+                             challenge           OCTET STRING
+                             -- the encryption (under the public key for which the cert.
+                             -- request is being made) of Rand, where Rand is specified as
+                             --   Rand ::= SEQUENCE {
+                             --      int      INTEGER,
+                             --       - the randomly-generated INTEGER A (above)
+                             --      sender   GeneralName
+                             --       - the sender's name (as included in PKIHeader)
+                             --   }
+                  }
+             </pre>
+             @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CmpCertificate.#ctor(Org.BouncyCastle.Asn1.X509.AttributeCertificate)">
+            Note: the addition of attribute certificates is a BC extension.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CmpCertificate.ToAsn1Object">
+             <pre>
+             CMPCertificate ::= CHOICE {
+                        x509v3PKCert        Certificate
+                        x509v2AttrCert      [1] AttributeCertificate
+              }
+             </pre>
+             Note: the addition of attribute certificates is a BC extension.
+            
+             @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CrlAnnContent.ToAsn1Object">
+            <pre>
+            CrlAnnContent ::= SEQUENCE OF CertificateList
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.ErrorMsgContent.ToAsn1Object">
+            <pre>
+            ErrorMsgContent ::= SEQUENCE {
+                                   pKIStatusInfo          PKIStatusInfo,
+                                   errorCode              INTEGER           OPTIONAL,
+                                   -- implementation-specific error codes
+                                   errorDetails           PKIFreeText       OPTIONAL
+                                   -- implementation-specific error details
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.GenMsgContent.ToAsn1Object">
+            <pre>
+            GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.GenRepContent.ToAsn1Object">
+            <pre>
+            GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cmp.InfoTypeAndValue">
+             Example InfoTypeAndValue contents include, but are not limited
+             to, the following (un-comment in this ASN.1 module and use as
+             appropriate for a given environment):
+             <pre>
+               id-it-caProtEncCert    OBJECT IDENTIFIER ::= {id-it 1}
+                  CAProtEncCertValue      ::= CMPCertificate
+               id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+                 SignKeyPairTypesValue   ::= SEQUENCE OF AlgorithmIdentifier
+               id-it-encKeyPairTypes  OBJECT IDENTIFIER ::= {id-it 3}
+                 EncKeyPairTypesValue    ::= SEQUENCE OF AlgorithmIdentifier
+               id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+                  PreferredSymmAlgValue   ::= AlgorithmIdentifier
+               id-it-caKeyUpdateInfo  OBJECT IDENTIFIER ::= {id-it 5}
+                  CAKeyUpdateInfoValue    ::= CAKeyUpdAnnContent
+               id-it-currentCRL       OBJECT IDENTIFIER ::= {id-it 6}
+                  CurrentCRLValue         ::= CertificateList
+               id-it-unsupportedOIDs  OBJECT IDENTIFIER ::= {id-it 7}
+                  UnsupportedOIDsValue    ::= SEQUENCE OF OBJECT IDENTIFIER
+               id-it-keyPairParamReq  OBJECT IDENTIFIER ::= {id-it 10}
+                  KeyPairParamReqValue    ::= OBJECT IDENTIFIER
+               id-it-keyPairParamRep  OBJECT IDENTIFIER ::= {id-it 11}
+                  KeyPairParamRepValue    ::= AlgorithmIdentifer
+               id-it-revPassphrase    OBJECT IDENTIFIER ::= {id-it 12}
+                  RevPassphraseValue      ::= EncryptedValue
+               id-it-implicitConfirm  OBJECT IDENTIFIER ::= {id-it 13}
+                  ImplicitConfirmValue    ::= NULL
+               id-it-confirmWaitTime  OBJECT IDENTIFIER ::= {id-it 14}
+                  ConfirmWaitTimeValue    ::= GeneralizedTime
+               id-it-origPKIMessage   OBJECT IDENTIFIER ::= {id-it 15}
+                  OrigPKIMessageValue     ::= PKIMessages
+               id-it-suppLangTags     OBJECT IDENTIFIER ::= {id-it 16}
+                  SuppLangTagsValue       ::= SEQUENCE OF UTF8String
+            
+             where
+            
+               id-pkix OBJECT IDENTIFIER ::= {
+                  iso(1) identified-organization(3)
+                  dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+             and
+                  id-it   OBJECT IDENTIFIER ::= {id-pkix 4}
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.InfoTypeAndValue.ToAsn1Object">
+            <pre>
+            InfoTypeAndValue ::= SEQUENCE {
+                                    infoType               OBJECT IDENTIFIER,
+                                    infoValue              ANY DEFINED BY infoType  OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.KeyRecRepContent.ToAsn1Object">
+            <pre>
+            KeyRecRepContent ::= SEQUENCE {
+                                    status                  PKIStatusInfo,
+                                    newSigCert          [0] CMPCertificate OPTIONAL,
+                                    caCerts             [1] SEQUENCE SIZE (1..MAX) OF
+                                                                      CMPCertificate OPTIONAL,
+                                    keyPairHist         [2] SEQUENCE SIZE (1..MAX) OF
+                                                                      CertifiedKeyPair OPTIONAL
+                         }
+            </pre> 
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.OobCertHash.ToAsn1Object">
+            <pre>
+            OobCertHash ::= SEQUENCE {
+                                 hashAlg     [0] AlgorithmIdentifier     OPTIONAL,
+                                 certId      [1] CertId                  OPTIONAL,
+                                 hashVal         BIT STRING
+                                 -- hashVal is calculated over the Der encoding of the
+                                 -- self-signed certificate with the identifier certID.
+                  }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PbmParameter.ToAsn1Object">
+            <pre>
+             PbmParameter ::= SEQUENCE {
+                                   salt                OCTET STRING,
+                                   -- note:  implementations MAY wish to limit acceptable sizes
+                                   -- of this string to values appropriate for their environment
+                                   -- in order to reduce the risk of denial-of-service attacks
+                                   owf                 AlgorithmIdentifier,
+                                   -- AlgId for a One-Way Function (SHA-1 recommended)
+                                   iterationCount      INTEGER,
+                                   -- number of times the OWF is applied
+                                   -- note:  implementations MAY wish to limit acceptable sizes
+                                   -- of this integer to values appropriate for their environment
+                                   -- in order to reduce the risk of denial-of-service attacks
+                                   mac                 AlgorithmIdentifier
+                                   -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+               }   -- or HMAC [RFC2104, RFC2202])
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiBody.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            Creates a new PkiBody.
+            @param type one of the TYPE_* constants
+            @param content message content
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiBody.ToAsn1Object">
+            <pre>
+            PkiBody ::= CHOICE {       -- message-specific body elements
+                   ir       [0]  CertReqMessages,        --Initialization Request
+                   ip       [1]  CertRepMessage,         --Initialization Response
+                   cr       [2]  CertReqMessages,        --Certification Request
+                   cp       [3]  CertRepMessage,         --Certification Response
+                   p10cr    [4]  CertificationRequest,   --imported from [PKCS10]
+                   popdecc  [5]  POPODecKeyChallContent, --pop Challenge
+                   popdecr  [6]  POPODecKeyRespContent,  --pop Response
+                   kur      [7]  CertReqMessages,        --Key Update Request
+                   kup      [8]  CertRepMessage,         --Key Update Response
+                   krr      [9]  CertReqMessages,        --Key Recovery Request
+                   krp      [10] KeyRecRepContent,       --Key Recovery Response
+                   rr       [11] RevReqContent,          --Revocation Request
+                   rp       [12] RevRepContent,          --Revocation Response
+                   ccr      [13] CertReqMessages,        --Cross-Cert. Request
+                   ccp      [14] CertRepMessage,         --Cross-Cert. Response
+                   ckuann   [15] CAKeyUpdAnnContent,     --CA Key Update Ann.
+                   cann     [16] CertAnnContent,         --Certificate Ann.
+                   rann     [17] RevAnnContent,          --Revocation Ann.
+                   crlann   [18] CRLAnnContent,          --CRL Announcement
+                   pkiconf  [19] PKIConfirmContent,      --Confirmation
+                   nested   [20] NestedMessageContent,   --Nested Message
+                   genm     [21] GenMsgContent,          --General Message
+                   genp     [22] GenRepContent,          --General Response
+                   error    [23] ErrorMsgContent,        --Error Message
+                   certConf [24] CertConfirmContent,     --Certificate confirm
+                   pollReq  [25] PollReqContent,         --Polling request
+                   pollRep  [26] PollRepContent          --Polling response
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiConfirmContent.ToAsn1Object">
+            <pre>
+            PkiConfirmContent ::= NULL
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cmp.PkiFailureInfo">
+            <pre>
+            PKIFailureInfo ::= BIT STRING {
+            badAlg               (0),
+              -- unrecognized or unsupported Algorithm Identifier
+            badMessageCheck      (1), -- integrity check failed (e.g., signature did not verify)
+            badRequest           (2),
+              -- transaction not permitted or supported
+            badTime              (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+            badCertId            (4), -- no certificate could be found matching the provided criteria
+            badDataFormat        (5),
+              -- the data submitted has the wrong format
+            wrongAuthority       (6), -- the authority indicated in the request is different from the one creating the response token
+            incorrectData        (7), -- the requester's data is incorrect (for notary services)
+            missingTimeStamp     (8), -- when the timestamp is missing but should be there (by policy)
+            badPOP               (9)  -- the proof-of-possession failed
+            timeNotAvailable    (14),
+              -- the TSA's time source is not available
+            unacceptedPolicy    (15),
+              -- the requested TSA policy is not supported by the TSA
+            unacceptedExtension (16),
+              -- the requested extension is not supported by the TSA
+             addInfoNotAvailable (17)
+               -- the additional information requested could not be understood
+               -- or is not available
+             systemFailure       (25)
+               -- the request cannot be handled due to system failure
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IAsn1String">
+            basic interface for Der string objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetPadBits(System.Int32)">
+            return the correct number of pad bits for a bit string defined in
+            a 32 bit constant
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetBytes(System.Int32)">
+            return the correct number of bytes for a bit string defined in
+            a 32 bit constant
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetInstance(System.Object)">
+             return a Bit string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Bit string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.#ctor(System.Byte[],System.Int32)">
+            @param data the octets making up the bit string.
+            @param padBits the number of extra bits at the end of the string.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerBitString.IntValue">
+            @return the value of the bit string as an int (truncating if necessary)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiFailureInfo.#ctor(System.Int32)">
+            Basic constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.ToAsn1Object">
+            <pre>
+            PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.Size">
+             Return the number of string elements present.
+            
+             @return number of elements present.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.Item(System.Int32)">
+             Return the UTF8STRING at index.
+            
+             @param index index of the string of interest
+             @return the string at index.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Cmp.PkiHeader.NULL_NAME">
+            Value for a "null" recipient or sender.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiHeader.ToAsn1Object">
+            <pre>
+             PkiHeader ::= SEQUENCE {
+                       pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+                       sender              GeneralName,
+                       -- identifies the sender
+                       recipient           GeneralName,
+                       -- identifies the intended recipient
+                       messageTime     [0] GeneralizedTime         OPTIONAL,
+                       -- time of production of this message (used when sender
+                       -- believes that the transport will be "suitable"; i.e.,
+                       -- that the time will still be meaningful upon receipt)
+                       protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+                       -- algorithm used for calculation of protection bits
+                       senderKID       [2] KeyIdentifier           OPTIONAL,
+                       recipKID        [3] KeyIdentifier           OPTIONAL,
+                       -- to identify specific keys used for protection
+                       transactionID   [4] OCTET STRING            OPTIONAL,
+                       -- identifies the transaction; i.e., this will be the same in
+                       -- corresponding request, response, certConf, and PKIConf
+                       -- messages
+                       senderNonce     [5] OCTET STRING            OPTIONAL,
+                       recipNonce      [6] OCTET STRING            OPTIONAL,
+                       -- nonces used to provide replay protection, senderNonce
+                       -- is inserted by the creator of this message; recipNonce
+                       -- is a nonce previously inserted in a related message by
+                       -- the intended recipient of this message
+                       freeText        [7] PKIFreeText             OPTIONAL,
+                       -- this may be used to indicate context-specific instructions
+                       -- (this field is intended for human consumption)
+                       generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+                                            InfoTypeAndValue     OPTIONAL
+                       -- this may be used to convey context-specific information
+                       -- (this field not primarily intended for human consumption)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiHeaderBuilder.Build">
+            <pre>
+             PKIHeader ::= SEQUENCE {
+                       pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+                       sender              GeneralName,
+                       -- identifies the sender
+                       recipient           GeneralName,
+                       -- identifies the intended recipient
+                       messageTime     [0] GeneralizedTime         OPTIONAL,
+                       -- time of production of this message (used when sender
+                       -- believes that the transport will be "suitable"; i.e.,
+                       -- that the time will still be meaningful upon receipt)
+                       protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+                       -- algorithm used for calculation of protection bits
+                       senderKID       [2] KeyIdentifier           OPTIONAL,
+                       recipKID        [3] KeyIdentifier           OPTIONAL,
+                       -- to identify specific keys used for protection
+                       transactionID   [4] OCTET STRING            OPTIONAL,
+                       -- identifies the transaction; i.e., this will be the same in
+                       -- corresponding request, response, certConf, and PKIConf
+                       -- messages
+                       senderNonce     [5] OCTET STRING            OPTIONAL,
+                       recipNonce      [6] OCTET STRING            OPTIONAL,
+                       -- nonces used to provide replay protection, senderNonce
+                       -- is inserted by the creator of this message; recipNonce
+                       -- is a nonce previously inserted in a related message by
+                       -- the intended recipient of this message
+                       freeText        [7] PKIFreeText             OPTIONAL,
+                       -- this may be used to indicate context-specific instructions
+                       -- (this field is intended for human consumption)
+                       generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+                                            InfoTypeAndValue     OPTIONAL
+                       -- this may be used to convey context-specific information
+                       -- (this field not primarily intended for human consumption)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessage.#ctor(Org.BouncyCastle.Asn1.Cmp.PkiHeader,Org.BouncyCastle.Asn1.Cmp.PkiBody,Org.BouncyCastle.Asn1.DerBitString,Org.BouncyCastle.Asn1.Cmp.CmpCertificate[])">
+             Creates a new PkiMessage.
+            
+             @param header message header
+             @param body message body
+             @param protection message protection (may be null)
+             @param extraCerts extra certificates (may be null)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessage.ToAsn1Object">
+            <pre>
+            PkiMessage ::= SEQUENCE {
+                             header           PKIHeader,
+                             body             PKIBody,
+                             protection   [0] PKIProtection OPTIONAL,
+                             extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+                                                                                OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessages.ToAsn1Object">
+            <pre>
+            PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.#ctor(System.Int32)">
+            @param status
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.#ctor(System.Int32,Org.BouncyCastle.Asn1.Cmp.PkiFreeText)">
+            @param status
+            @param statusString
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.ToAsn1Object">
+             <pre>
+             PkiStatusInfo ::= SEQUENCE {
+                 status        PKIStatus,                (INTEGER)
+                 statusString  PkiFreeText     OPTIONAL,
+                 failInfo      PkiFailureInfo  OPTIONAL  (BIT STRING)
+             }
+            
+             PKIStatus:
+               granted                (0), -- you got exactly what you asked for
+               grantedWithMods        (1), -- you got something like what you asked for
+               rejection              (2), -- you don't get it, more information elsewhere in the message
+               waiting                (3), -- the request body part has not yet been processed, expect to hear more later
+               revocationWarning      (4), -- this message contains a warning that a revocation is imminent
+               revocationNotification (5), -- notification that a revocation has occurred
+               keyUpdateWarning       (6)  -- update already done for the oldCertId specified in CertReqMsg
+            
+             PkiFailureInfo:
+               badAlg           (0), -- unrecognized or unsupported Algorithm Identifier
+               badMessageCheck  (1), -- integrity check failed (e.g., signature did not verify)
+               badRequest       (2), -- transaction not permitted or supported
+               badTime          (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+               badCertId        (4), -- no certificate could be found matching the provided criteria
+               badDataFormat    (5), -- the data submitted has the wrong format
+               wrongAuthority   (6), -- the authority indicated in the request is different from the one creating the response token
+               incorrectData    (7), -- the requester's data is incorrect (for notary services)
+               missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+               badPOP           (9)  -- the proof-of-possession failed
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PollRepContent.ToAsn1Object">
+            <pre>
+            PollRepContent ::= SEQUENCE OF SEQUENCE {
+                    certReqId              INTEGER,
+                    checkAfter             INTEGER,  -- time in seconds
+                    reason                 PKIFreeText OPTIONAL
+                }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PollReqContent.ToAsn1Object">
+            <pre>
+            PollReqContent ::= SEQUENCE OF SEQUENCE {
+                                   certReqId              INTEGER
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PopoDecKeyChallContent.ToAsn1Object">
+            <pre>
+            PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PopoDecKeyRespContent.ToAsn1Object">
+            <pre>
+            PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.ProtectedPart.ToAsn1Object">
+            <pre>
+            ProtectedPart ::= SEQUENCE {
+                               header    PKIHeader,
+                               body      PKIBody
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevAnnContent.ToAsn1Object">
+            <pre>
+            RevAnnContent ::= SEQUENCE {
+                  status              PKIStatus,
+                  certId              CertId,
+                  willBeRevokedAt     GeneralizedTime,
+                  badSinceDate        GeneralizedTime,
+                  crlDetails          Extensions  OPTIONAL
+                   -- extra CRL details (e.g., crl number, reason, location, etc.)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevDetails.ToAsn1Object">
+            <pre>
+            RevDetails ::= SEQUENCE {
+                             certDetails         CertTemplate,
+                              -- allows requester to specify as much as they can about
+                              -- the cert. for which revocation is requested
+                              -- (e.g., for cases in which serialNumber is not available)
+                              crlEntryDetails     Extensions       OPTIONAL
+                              -- requested crlEntryExtensions
+                        }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevRepContent.ToAsn1Object">
+            <pre>
+            RevRepContent ::= SEQUENCE {
+                   status       SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+                   -- in same order as was sent in RevReqContent
+                   revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+                   -- IDs for which revocation was requested
+                   -- (same order as status)
+                   crls     [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+                   -- the resulting CRLs (there may be more than one)
+              }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevReqContent.ToAsn1Object">
+            <pre>
+            RevReqContent ::= SEQUENCE OF RevDetails
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attribute.GetInstance(System.Object)">
+             return an Attribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attribute.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attribute ::= SEQUENCE {
+                attrType OBJECT IDENTIFIER,
+                attrValues SET OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attributes.ToAsn1Object">
+            <pre>
+            Attributes ::=
+              SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AttributeTable.GetAll(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+             empty if there are no attributes of the required type present.
+            
+             @param oid type of attribute required.
+             @return a vector of all the attributes found of type oid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AttributeTable.Add(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Return a new table with the passed in attribute added.
+            
+             @param attrType
+             @param attrValue
+             @return
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cms.AttributeTable.Item(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthenticatedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.GetInstance(System.Object)">
+             return an AuthenticatedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             AuthenticatedData ::= SEQUENCE {
+                   version CMSVersion,
+                   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                   recipientInfos RecipientInfos,
+                   macAlgorithm MessageAuthenticationCodeAlgorithm,
+                   digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+                   encapContentInfo EncapsulatedContentInfo,
+                   authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+                   mac MessageAuthenticationCode,
+                   unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+            
+             AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             MessageAuthenticationCode ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.AuthenticatedDataParser">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             AuthenticatedData ::= SEQUENCE {
+                   version CMSVersion,
+                   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                   recipientInfos RecipientInfos,
+                   macAlgorithm MessageAuthenticationCodeAlgorithm,
+                   digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+                   encapContentInfo EncapsulatedContentInfo,
+                   authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+                   mac MessageAuthenticationCode,
+                   unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+            
+             AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             MessageAuthenticationCode ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthEnvelopedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.GetInstance(System.Object)">
+             return an AuthEnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            AuthEnvelopedData ::= SEQUENCE {
+              version CMSVersion,
+              originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+              recipientInfos RecipientInfos,
+              authEncryptedContentInfo EncryptedContentInfo,
+              authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+              mac MessageAuthenticationCode,
+              unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedDataParser">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            <pre>
+            AuthEnvelopedData ::= SEQUENCE {
+              version CMSVersion,
+              originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+              recipientInfos RecipientInfos,
+              authEncryptedContentInfo EncryptedContentInfo,
+              authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+              mac MessageAuthenticationCode,
+              unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+            </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Cms.CmsObjectIdentifiers.id_ri">
+            The other Revocation Info arc
+            id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+                                              dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.CompressedData">
+            RFC 3274 - CMS Compressed Data.
+            <pre>
+            CompressedData ::= Sequence {
+             version CMSVersion,
+             compressionAlgorithm CompressionAlgorithmIdentifier,
+             encapContentInfo EncapsulatedContentInfo
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.CompressedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a CompressedData object from a tagged object.
+            
+             @param ato the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.CompressedData.GetInstance(System.Object)">
+             return a CompressedData object from the given object.
+            
+             @param _obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.CompressedDataParser">
+            RFC 3274 - CMS Compressed Data.
+            <pre>
+            CompressedData ::= SEQUENCE {
+             version CMSVersion,
+             compressionAlgorithm CompressionAlgorithmIdentifier,
+             encapContentInfo EncapsulatedContentInfo
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.ContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= Sequence {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.ContentInfoParser">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= SEQUENCE {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthEnvelopedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.GetInstance(System.Object)">
+             return an AuthEnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            MQVuserKeyingMaterial ::= SEQUENCE {
+              ephemeralPublicKey OriginatorPublicKey,
+              addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfo.GetInstance(System.Object)">
+             return an EncryptedContentInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EncryptedContentInfo ::= Sequence {
+                contentType ContentType,
+                contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+                encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfoParser">
+            <pre>
+            EncryptedContentInfo ::= SEQUENCE {
+                contentType ContentType,
+                contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+                encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedData.ToAsn1Object">
+            <pre>
+                  EncryptedData ::= SEQUENCE {
+                                version CMSVersion,
+                                encryptedContentInfo EncryptedContentInfo,
+                                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an EnvelopedData object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(System.Object)">
+             return an EnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EnvelopedData ::= Sequence {
+                version CMSVersion,
+                originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                recipientInfos RecipientInfos,
+                encryptedContentInfo EncryptedContentInfo,
+                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.EnvelopedDataParser">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EnvelopedData ::= SEQUENCE {
+                version CMSVersion,
+                originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                recipientInfos RecipientInfos,
+                encryptedContentInfo EncryptedContentInfo,
+                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KekIdentifier object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.GetInstance(System.Object)">
+             return a KekIdentifier object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KekIdentifier ::= Sequence {
+                keyIdentifier OCTET STRING,
+                date GeneralizedTime OPTIONAL,
+                other OtherKeyAttribute OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KekRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.GetInstance(System.Object)">
+             return a KekRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KekRecipientInfo ::= Sequence {
+                version CMSVersion,  -- always set to 4
+                kekID KekIdentifier,
+                keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an KeyAgreeRecipientIdentifier object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.GetInstance(System.Object)">
+             return an KeyAgreeRecipientIdentifier object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KeyAgreeRecipientIdentifier ::= CHOICE {
+                issuerAndSerialNumber IssuerAndSerialNumber,
+                rKeyId [0] IMPLICIT RecipientKeyIdentifier
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KeyAgreeRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.GetInstance(System.Object)">
+             return a KeyAgreeRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.ToAsn1Object">
+                     * Produce an object suitable for an Asn1OutputStream.
+                     * <pre>
+                     * KeyAgreeRecipientInfo ::= Sequence {
+                     *     version CMSVersion,  -- always set to 3
+                     *     originator [0] EXPLICIT OriginatorIdentifierOrKey,
+                     *     ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+                     *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                     *     recipientEncryptedKeys RecipientEncryptedKeys
+                     * }
+            		 *
+            		 * UserKeyingMaterial ::= OCTET STRING
+                     * </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyTransRecipientInfo.GetInstance(System.Object)">
+             return a KeyTransRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyTransRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KeyTransRecipientInfo ::= Sequence {
+                version CMSVersion,  -- always set to 0 or 2
+                rid RecipientIdentifier,
+                keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.MetaData.ToAsn1Object">
+            <pre>
+            MetaData ::= SEQUENCE {
+              hashProtected        BOOLEAN,
+              fileName             UTF8String OPTIONAL,
+              mediaType            IA5String OPTIONAL,
+              otherMetaData        Attributes OPTIONAL
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorIdentifierOrKey object from a tagged object.
+            
+             @param o the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.GetInstance(System.Object)">
+             return an OriginatorIdentifierOrKey object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             OriginatorIdentifierOrKey ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier,
+                 originatorKey [1] OriginatorPublicKey
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.GetInstance(System.Object)">
+             return an OriginatorInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OriginatorInfo ::= Sequence {
+                certs [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorPublicKey object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.GetInstance(System.Object)">
+             return an OriginatorPublicKey object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OriginatorPublicKey ::= Sequence {
+                algorithm AlgorithmIdentifier,
+                publicKey BIT STRING
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherKeyAttribute.GetInstance(System.Object)">
+             return an OtherKeyAttribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherKeyAttribute.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OtherKeyAttribute ::= Sequence {
+                keyAttrId OBJECT IDENTIFIER,
+                keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a OtherRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.GetInstance(System.Object)">
+             return a OtherRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OtherRecipientInfo ::= Sequence {
+               oriType OBJECT IDENTIFIER,
+               oriValue ANY DEFINED BY oriType }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRevocationInfoFormat.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a OtherRevocationInfoFormat object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception IllegalArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRevocationInfoFormat.GetInstance(System.Object)">
+             return a OtherRevocationInfoFormat object from the given object.
+            
+             @param obj the object we want converted.
+             @exception IllegalArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRevocationInfoFormat.ToAsn1Object">
+            Produce an object suitable for an ASN1OutputStream.
+            <pre>
+            OtherRevocationInfoFormat ::= SEQUENCE {
+                 otherRevInfoFormat OBJECT IDENTIFIER,
+                 otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a PasswordRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.GetInstance(System.Object)">
+             return a PasswordRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            PasswordRecipientInfo ::= Sequence {
+              version CMSVersion,   -- Always set to 0
+              keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+                                        OPTIONAL,
+             keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+             encryptedKey EncryptedKey }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an RecipientEncryptedKey object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.GetInstance(System.Object)">
+             return a RecipientEncryptedKey object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RecipientEncryptedKey ::= SEQUENCE {
+                rid KeyAgreeRecipientIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientIdentifier.GetInstance(System.Object)">
+             return a RecipientIdentifier object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             RecipientIdentifier ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RecipientInfo ::= CHOICE {
+                ktri KeyTransRecipientInfo,
+                kari [1] KeyAgreeRecipientInfo,
+                kekri [2] KekRecipientInfo,
+                pwri [3] PasswordRecipientInfo,
+                ori [4] OtherRecipientInfo }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a RecipientKeyIdentifier object from a tagged object.
+            
+             @param _ato the tagged object holding the object we want.
+             @param _explicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.GetInstance(System.Object)">
+             return a RecipientKeyIdentifier object from the given object.
+            
+             @param _obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             RecipientKeyIdentifier ::= Sequence {
+                 subjectKeyIdentifier SubjectKeyIdentifier,
+                 date GeneralizedTime OPTIONAL,
+                 other OtherKeyAttribute OPTIONAL
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.ScvpReqRes.ToAsn1Object">
+            <pre>
+               ScvpReqRes ::= SEQUENCE {
+               request  [0] EXPLICIT ContentInfo OPTIONAL,
+               response     ContentInfo }
+            </pre>
+            @return  the ASN.1 primitive representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.SignedData">
+            a signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SignedData ::= Sequence {
+                version CMSVersion,
+                digestAlgorithms DigestAlgorithmIdentifiers,
+                encapContentInfo EncapsulatedContentInfo,
+                certificates [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                signerInfos SignerInfos
+              }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.SignedDataParser">
+            <pre>
+            SignedData ::= SEQUENCE {
+                version CMSVersion,
+                digestAlgorithms DigestAlgorithmIdentifiers,
+                encapContentInfo EncapsulatedContentInfo,
+                certificates [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                signerInfos SignerInfos
+              }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerIdentifier.GetInstance(System.Object)">
+             return a SignerIdentifier object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             SignerIdentifier ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              SignerInfo ::= Sequence {
+                  version Version,
+                  SignerIdentifier sid,
+                  digestAlgorithm DigestAlgorithmIdentifier,
+                  authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+                  digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+                  encryptedDigest EncryptedDigest,
+                  unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+              }
+            
+              EncryptedDigest ::= OCTET STRING
+            
+              DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+            
+              DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Time.#ctor(System.DateTime)">
+            creates a time object from a given date - if the date is between 1950
+            and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+            is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Time.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Time ::= CHOICE {
+                        utcTime        UTCTime,
+                        generalTime    GeneralizedTime }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampAndCrl.ToAsn1Object">
+            <pre>
+            TimeStampAndCRL ::= SEQUENCE {
+                timeStamp   TimeStampToken,          -- according to RFC 3161
+                crl         CertificateList OPTIONAL -- according to RFC 5280
+             }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampedData.ToAsn1Object">
+            <pre>
+            TimeStampedData ::= SEQUENCE {
+              version              INTEGER { v1(1) },
+              dataUri              IA5String OPTIONAL,
+              metaData             MetaData OPTIONAL,
+              content              OCTET STRING OPTIONAL,
+              temporalEvidence     Evidence
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampTokenEvidence.ToAsn1Object">
+            <pre>
+            TimeStampTokenEvidence ::=
+               SEQUENCE SIZE(1..MAX) OF TimeStampAndCrl
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.AttributeTypeAndValue.ToAsn1Object">
+            <pre>
+            AttributeTypeAndValue ::= SEQUENCE {
+                      type         OBJECT IDENTIFIER,
+                      value        ANY DEFINED BY type }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertId.ToAsn1Object">
+            <pre>
+            CertId ::= SEQUENCE {
+                            issuer           GeneralName,
+                            serialNumber     INTEGER }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMessages.ToAsn1Object">
+            <pre>
+            CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMsg.#ctor(Org.BouncyCastle.Asn1.Crmf.CertRequest,Org.BouncyCastle.Asn1.Crmf.ProofOfPossession,Org.BouncyCastle.Asn1.Crmf.AttributeTypeAndValue[])">
+            Creates a new CertReqMsg.
+            @param certReq CertRequest
+            @param popo may be null
+            @param regInfo may be null
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMsg.ToAsn1Object">
+            <pre>
+            CertReqMsg ::= SEQUENCE {
+                               certReq   CertRequest,
+                               pop       ProofOfPossession  OPTIONAL,
+                               -- content depends upon key type
+                               regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertRequest.ToAsn1Object">
+            <pre>
+            CertRequest ::= SEQUENCE {
+                                 certReqId     INTEGER,          -- ID for matching request and reply
+                                 certTemplate  CertTemplate,  -- Selected fields of cert to be issued
+                                 controls      Controls OPTIONAL }   -- Attributes affecting issuance
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplate.ToAsn1Object">
+            <pre>
+             CertTemplate ::= SEQUENCE {
+                 version      [0] Version               OPTIONAL,
+                 serialNumber [1] INTEGER               OPTIONAL,
+                 signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+                 issuer       [3] Name                  OPTIONAL,
+                 validity     [4] OptionalValidity      OPTIONAL,
+                 subject      [5] Name                  OPTIONAL,
+                 publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+                 issuerUID    [7] UniqueIdentifier      OPTIONAL,
+                 subjectUID   [8] UniqueIdentifier      OPTIONAL,
+                 extensions   [9] Extensions            OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetVersion(System.Int32)">
+            Sets the X.509 version. Note: for X509v3, use 2 here. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetIssuerUID(Org.BouncyCastle.Asn1.DerBitString)">
+            Sets the issuer unique ID (deprecated in X.509v3) 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetSubjectUID(Org.BouncyCastle.Asn1.DerBitString)">
+            Sets the subject unique ID (deprecated in X.509v3) 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.Build">
+            <pre>
+             CertTemplate ::= SEQUENCE {
+                 version      [0] Version               OPTIONAL,
+                 serialNumber [1] INTEGER               OPTIONAL,
+                 signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+                 issuer       [3] Name                  OPTIONAL,
+                 validity     [4] OptionalValidity      OPTIONAL,
+                 subject      [5] Name                  OPTIONAL,
+                 publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+                 issuerUID    [7] UniqueIdentifier      OPTIONAL,
+                 subjectUID   [8] UniqueIdentifier      OPTIONAL,
+                 extensions   [9] Extensions            OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.Controls.ToAsn1Object">
+            <pre>
+            Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncKeyWithID.ToAsn1Object">
+            <pre>
+            EncKeyWithID ::= SEQUENCE {
+                 privateKey           PrivateKeyInfo,
+                 identifier CHOICE {
+                    string               UTF8String,
+                    generalName          GeneralName
+                } OPTIONAL
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncryptedKey.ToAsn1Object">
+            <pre>
+               EncryptedKey ::= CHOICE {
+                   encryptedValue        EncryptedValue, -- deprecated
+                   envelopedData     [0] EnvelopedData }
+                   -- The encrypted private key MUST be placed in the envelopedData
+                   -- encryptedContentInfo encryptedContent OCTET STRING.
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncryptedValue.ToAsn1Object">
+            <pre>
+            EncryptedValue ::= SEQUENCE {
+                                intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
+                                -- the intended algorithm for which the value will be used
+                                symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
+                                -- the symmetric algorithm used to encrypt the value
+                                encSymmKey    [2] BIT STRING           OPTIONAL,
+                                -- the (encrypted) symmetric key used to encrypt the value
+                                keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
+                                -- algorithm used to encrypt the symmetric key
+                                valueHint     [4] OCTET STRING         OPTIONAL,
+                                -- a brief description or identifier of the encValue content
+                                -- (may be meaningful only to the sending entity, and used only
+                                -- if EncryptedValue might be re-examined by the sending entity
+                                -- in the future)
+                                encValue       BIT STRING }
+                                -- the encrypted value itself
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.OptionalValidity.ToAsn1Object">
+            <pre>
+            OptionalValidity ::= SEQUENCE {
+                                   notBefore  [0] Time OPTIONAL,
+                                   notAfter   [1] Time OPTIONAL } --at least one MUST be present
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PkiArchiveOptions.ToAsn1Object">
+            <pre>
+             PkiArchiveOptions ::= CHOICE {
+                 encryptedPrivKey     [0] EncryptedKey,
+                 -- the actual value of the private key
+                 keyGenParameters     [1] KeyGenParameters,
+                 -- parameters which allow the private key to be re-generated
+                 archiveRemGenPrivKey [2] BOOLEAN }
+                 -- set to TRUE if sender wishes receiver to archive the private
+                 -- key of a key pair that the receiver generates in response to
+                 -- this request; set to FALSE if no archival is desired.
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PkiPublicationInfo.ToAsn1Object">
+            <pre>
+            PkiPublicationInfo ::= SEQUENCE {
+                             action     INTEGER {
+                                            dontPublish (0),
+                                            pleasePublish (1) },
+                             pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+            -- pubInfos MUST NOT be present if action is "dontPublish"
+            -- (if action is "pleasePublish" and pubInfos is omitted,
+            -- "dontCare" is assumed)
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Crmf.PKMacValue">
+            Password-based MAC value for use with POPOSigningKeyInput.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.#ctor(Org.BouncyCastle.Asn1.Cmp.PbmParameter,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new PKMACValue.
+            @param params parameters for password-based MAC
+            @param value MAC of the DER-encoded SubjectPublicKeyInfo
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.#ctor(Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new PKMACValue.
+            @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+            @param value MAC of the DER-encoded SubjectPublicKeyInfo
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.ToAsn1Object">
+            <pre>
+            PKMACValue ::= SEQUENCE {
+                 algId  AlgorithmIdentifier,
+                 -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+                 -- parameter value is PBMParameter
+                 value  BIT STRING }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoPrivKey.ToAsn1Object">
+            <pre>
+            PopoPrivKey ::= CHOICE {
+                   thisMessage       [0] BIT STRING,         -- Deprecated
+                    -- possession is proven in this message (which contains the private
+                    -- key itself (encrypted for the CA))
+                   subsequentMessage [1] SubsequentMessage,
+                    -- possession will be proven in a subsequent message
+                   dhMAC             [2] BIT STRING,         -- Deprecated
+                   agreeMAC          [3] PKMACValue,
+                   encryptedKey      [4] EnvelopedData }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKey.#ctor(Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput,Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new Proof of Possession object for a signing key.
+            @param poposkIn the PopoSigningKeyInput structure, or null if the
+                CertTemplate includes both subject and publicKey values.
+            @param aid the AlgorithmIdentifier used to sign the proof of possession.
+            @param signature a signature over the DER-encoded value of poposkIn,
+                or the DER-encoded value of certReq if poposkIn is null.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKey.ToAsn1Object">
+            <pre>
+            PopoSigningKey ::= SEQUENCE {
+                                 poposkInput           [0] PopoSigningKeyInput OPTIONAL,
+                                 algorithmIdentifier   AlgorithmIdentifier,
+                                 signature             BIT STRING }
+             -- The signature (using "algorithmIdentifier") is on the
+             -- DER-encoded value of poposkInput.  NOTE: If the CertReqMsg
+             -- certReq CertTemplate contains the subject and publicKey values,
+             -- then poposkInput MUST be omitted and the signature MUST be
+             -- computed on the DER-encoded value of CertReqMsg certReq.  If
+             -- the CertReqMsg certReq CertTemplate does not contain the public
+             -- key and subject values, then poposkInput MUST be present and
+             -- MUST be signed.  This strategy ensures that the public key is
+             -- not present in both the poposkInput and CertReqMsg certReq
+             -- CertTemplate fields.
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Creates a new PopoSigningKeyInput with sender name as authInfo. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.#ctor(Org.BouncyCastle.Asn1.Crmf.PKMacValue,Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Creates a new PopoSigningKeyInput using password-based MAC. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.ToAsn1Object">
+            <pre>
+            PopoSigningKeyInput ::= SEQUENCE {
+                   authInfo             CHOICE {
+                                            sender              [0] GeneralName,
+                                            -- used only if an authenticated identity has been
+                                            -- established for the sender (e.g., a DN from a
+                                            -- previously-issued and currently-valid certificate
+                                            publicKeyMac        PKMacValue },
+                                            -- used if no authenticated GeneralName currently exists for
+                                            -- the sender; publicKeyMac contains a password-based MAC
+                                            -- on the DER-encoded value of publicKey
+                   publicKey           SubjectPublicKeyInfo }  -- from CertTemplate
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.Sender">
+            Returns the sender field, or null if authInfo is publicKeyMac 
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.PublicKeyMac">
+            Returns the publicKeyMac field, or null if authInfo is sender 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor">
+            Creates a ProofOfPossession with type raVerified. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor(Org.BouncyCastle.Asn1.Crmf.PopoSigningKey)">
+            Creates a ProofOfPossession for a signing key. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor(System.Int32,Org.BouncyCastle.Asn1.Crmf.PopoPrivKey)">
+            Creates a ProofOfPossession for key encipherment or agreement.
+            @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.ToAsn1Object">
+            <pre>
+            ProofOfPossession ::= CHOICE {
+                                      raVerified        [0] NULL,
+                                      -- used if the RA has already verified that the requester is in
+                                      -- possession of the private key
+                                      signature         [1] PopoSigningKey,
+                                      keyEncipherment   [2] PopoPrivKey,
+                                      keyAgreement      [3] PopoPrivKey }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.SinglePubInfo.ToAsn1Object">
+            <pre>
+            SinglePubInfo ::= SEQUENCE {
+                   pubMethod    INTEGER {
+                      dontCare    (0),
+                      x500        (1),
+                      web         (2),
+                      ldap        (3) },
+                  pubLocation  GeneralName OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerInteger.GetInstance(System.Object)">
+             return an integer from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerInteger.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Integer from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerInteger.PositiveValue">
+            in some cases positive values Get crammed into a space,
+            that's not quite big enough...
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves">
+            table of the available named parameters for GOST 3410-2001.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the ECDomainParameters object for the given OID, null if it
+             isn't present.
+            
+             @param oid an object identifier representing a named parameters, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.Gost28147Parameters.ToAsn1Object">
+             <pre>
+             Gost28147-89-Parameters ::=
+                           SEQUENCE {
+                                   iv                   Gost28147-89-IV,
+                                   encryptionParamSet   OBJECT IDENTIFIER
+                            }
+            
+               Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters">
+            table of the available named parameters for GOST 3410-94.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the GOST3410ParamSetParameters object for the given OID, null if it
+             isn't present.
+            
+             @param oid an object identifier representing a named parameters, if present.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters.Names">
+            returns an enumeration containing the name strings for parameters
+            contained in this structure.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerBmpString">
+            Der BMPString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.GetInstance(System.Object)">
+             return a BMP string from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a BMP string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                          be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(System.Object)">
+             return a bool from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(System.Boolean)">
+            return a DerBoolean from the passed in bool.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Boolean from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerEnumerated.GetInstance(System.Object)">
+             return an integer from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerEnumerated.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Enumerated from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerExternal">
+            Class representing the DER-type External
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerExternal.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.DerInteger,Org.BouncyCastle.Asn1.Asn1Object,Org.BouncyCastle.Asn1.DerTaggedObject)">
+            Creates a new instance of DerExternal
+            See X.690 for more informations about the meaning of these parameters
+            @param directReference The direct reference or <code>null</code> if not set.
+            @param indirectReference The indirect reference or <code>null</code> if not set.
+            @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+            @param externalData The external data in its encoded form.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerExternal.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.DerInteger,Org.BouncyCastle.Asn1.Asn1Object,System.Int32,Org.BouncyCastle.Asn1.Asn1Object)">
+            Creates a new instance of DerExternal.
+            See X.690 for more informations about the meaning of these parameters
+            @param directReference The direct reference or <code>null</code> if not set.
+            @param indirectReference The indirect reference or <code>null</code> if not set.
+            @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+            @param encoding The encoding to be used for the external data
+            @param externalData The external data
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerExternal.Encoding">
+            The encoding of the content. Valid values are
+            <ul>
+            <li><code>0</code> single-ASN1-type</li>
+            <li><code>1</code> OCTET STRING</li>
+            <li><code>2</code> BIT STRING</li>
+            </ul>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerGeneralizedTime">
+            Generalized time object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetInstance(System.Object)">
+             return a generalized time from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Generalized Time object from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.#ctor(System.String)">
+             The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+             for local time, or Z+-HHMM on the end, for difference between local
+             time and UTC time. The fractional second amount f must consist of at
+             least one number with trailing zeroes removed.
+            
+             @param time the time string.
+             @exception ArgumentException if string is an illegal format.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.#ctor(System.DateTime)">
+            base constructor from a local time object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetTime">
+            return the time - always in the form of
+             YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+            <p>
+            Normally in a certificate we would expect "Z" rather than "GMT",
+            however adding the "GMT" means we can just use:
+            <pre>
+                dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+            </pre>
+            To read in the time and Get a date which is compatible with our local
+            time zone.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerGeneralizedTime.TimeString">
+            Return the time.
+            @return The time string as it appeared in the encoded object.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerIA5String">
+            Der IA5String object - this is an ascii string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.GetInstance(System.Object)">
+             return a IA5 string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an IA5 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.String)">
+            basic constructor - without validation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in an IA5String.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.IsIA5String(System.String)">
+             return true if the passed in String can be represented without
+             loss as an IA5String, false otherwise.
+            
+             @return true if in printable set, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerNumericString">
+            Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.GetInstance(System.Object)">
+             return a Numeric string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Numeric string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.String)">
+            basic constructor -  without validation..
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in a NumericString.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.IsNumericString(System.String)">
+             Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+            
+             @param str string to validate.
+             @return true if numeric, fale otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.GetInstance(System.Object)">
+             return an Oid from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an object Identifier from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.On(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            Return  true if this oid is an extension of the passed in branch, stem.
+            @param stem the arc or branch that is a possible parent.
+            @return  true if the branch is on the passed in stem, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerPrintableString">
+            Der PrintableString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.GetInstance(System.Object)">
+             return a printable string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Printable string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.String)">
+            basic constructor - this does not validate the string
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in a PrintableString.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.IsPrintableString(System.String)">
+             return true if the passed in String can be represented without
+             loss as a PrintableString, false otherwise.
+            
+             @return true if in printable set, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerT61String">
+            Der T61String (also the teletex string) - 8-bit characters
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.GetInstance(System.Object)">
+             return a T61 string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an T61 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.#ctor(System.String)">
+            basic constructor - with string.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUniversalString">
+            Der UniversalString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.GetInstance(System.Object)">
+             return a Universal string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Universal string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUtcTime">
+            UTC time object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.GetInstance(System.Object)">
+             return an UTC Time from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an UTC Time from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.#ctor(System.String)">
+            The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+            never encoded. When you're creating one of these objects from scratch, that's
+            what you want to use, otherwise we'll try to deal with whatever Gets read from
+            the input stream... (this is why the input format is different from the GetTime()
+            method output).
+            <p>
+            @param time the time string.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.#ctor(System.DateTime)">
+            base constructor from a DateTime object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.ToDateTime">
+             return the time as a date based on whatever a 2 digit year will return. For
+             standardised processing use ToAdjustedDateTime().
+            
+             @return the resulting date
+             @exception ParseException if the date string cannot be parsed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.ToAdjustedDateTime">
+             return the time as an adjusted date
+             in the range of 1950 - 2049.
+            
+             @return a date in the range of 1950 to 2049.
+             @exception ParseException if the date string cannot be parsed.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerUtcTime.TimeString">
+            return the time - always in the form of
+             YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+            <p>
+            Normally in a certificate we would expect "Z" rather than "GMT",
+            however adding the "GMT" means we can just use:
+            <pre>
+                dateF = new SimpleDateFormat("yyMMddHHmmssz");
+            </pre>
+            To read in the time and Get a date which is compatible with our local
+            time zone.</p>
+            <p>
+            <b>Note:</b> In some cases, due to the local date processing, this
+            may lead to unexpected results. If you want to stick the normal
+            convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerUtcTime.AdjustedTimeString">
+            <summary>
+            Return a time string as an adjusted date with a 4 digit year.
+            This goes in the range of 1950 - 2049.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUtf8String">
+            Der UTF8String object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.GetInstance(System.Object)">
+             return an UTF8 string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an UTF8 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerVisibleString">
+            Der VisibleString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.GetInstance(System.Object)">
+             return a Visible string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Visible string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CertificateValues">
+            <remarks>
+            RFC 3126: 4.3.1 Certificate Values Attribute Definition
+            <code>
+            CertificateValues ::= SEQUENCE OF Certificate
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeIndication.ToAsn1Object">
+            <pre>
+            CommitmentTypeIndication ::= SEQUENCE {
+                 commitmentTypeId   CommitmentTypeIdentifier,
+                 commitmentTypeQualifier   SEQUENCE SIZE (1..MAX) OF
+                         CommitmentTypeQualifier OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier">
+             Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+            
+             <pre>
+               CommitmentTypeQualifier ::= SEQUENCE {
+                   commitmentTypeIdentifier  CommitmentTypeIdentifier,
+                   qualifier          ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+             @param qualifier the qualifier, defined by the above field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param as <code>CommitmentTypeQualifier</code> structure
+             encoded as an Asn1Sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.ToAsn1Object">
+             Returns a DER-encodable representation of this instance.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CompleteCertificateRefs">
+            <remarks>
+            RFC 3126: 4.2.1 Complete Certificate Refs Attribute Definition
+            <code>
+            CompleteCertificateRefs ::= SEQUENCE OF OtherCertID
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CompleteRevocationRefs">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlIdentifier">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlIdentifier ::= SEQUENCE 
+            {
+            	crlissuer		Name,
+            	crlIssuedTime	UTCTime,
+            	crlNumber		INTEGER OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlListID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CRLListID ::= SEQUENCE 
+            {
+            	crls	SEQUENCE OF CrlValidatedID
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlOcspRef">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlOcspRef ::= SEQUENCE {
+            	crlids		[0] CRLListID		OPTIONAL,
+            	ocspids		[1] OcspListID		OPTIONAL,
+            	otherRev	[2] OtherRevRefs	OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlValidatedID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlValidatedID ::= SEQUENCE {
+            	crlHash			OtherHash,
+            	crlIdentifier	CrlIdentifier OPTIONAL}
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspIdentifier">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspIdentifier ::= SEQUENCE {
+            	ocspResponderID		ResponderID,
+            		-- As in OCSP response data
+            	producedAt			GeneralizedTime
+            		-- As in OCSP response data
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspListID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspListID ::=  SEQUENCE {
+            	ocspResponses	SEQUENCE OF OcspResponsesID
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspResponsesID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspResponsesID ::= SEQUENCE {
+            	ocspIdentifier	OcspIdentifier,
+            	ocspRepHash		OtherHash OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherCertID">
+            <remarks>
+            <code>
+            OtherCertID ::= SEQUENCE {
+            	otherCertHash	OtherHash,
+            	issuerSerial	IssuerSerial OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherHash">
+            <remarks>
+            <code>
+            OtherHash ::= CHOICE {
+            	sha1Hash	OtherHashValue, -- This contains a SHA-1 hash
+            	otherHash	OtherHashAlgAndValue
+            }
+            
+            OtherHashValue ::= OCTET STRING
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherHashAlgAndValue">
+            <summary>
+            Summary description for OtherHashAlgAndValue.
+            </summary>
+            <remarks>
+            <code>
+            OtherHashAlgAndValue ::= SEQUENCE {
+            	hashAlgorithm	AlgorithmIdentifier,
+            	hashValue		OtherHashValue
+            }
+            
+            OtherHashValue ::= OCTET STRING
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherRevRefs">
+             <remarks>
+             RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+             <code>
+             OtherRevRefs ::= SEQUENCE 
+             {
+            		otherRevRefType      OtherRevRefType,
+            		otherRevRefs         ANY DEFINED BY otherRevRefType
+             }
+            
+             OtherRevRefType ::= OBJECT IDENTIFIER
+             </code>
+             </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherRevVals">
+             <remarks>
+             RFC 3126: 4.3.2 Revocation Values Attribute Definition
+             <code>
+             OtherRevVals ::= SEQUENCE 
+             {
+            		otherRevValType      OtherRevValType,
+            		otherRevVals         ANY DEFINED BY otherRevValType
+             }
+            
+             OtherRevValType ::= OBJECT IDENTIFIER
+             </code>
+             </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherSigningCertificate">
+            <remarks>
+            <code>
+            OtherSigningCertificate ::= SEQUENCE {
+            	certs		SEQUENCE OF OtherCertID,
+            	policies	SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.RevocationValues">
+            <remarks>
+            RFC 5126: 6.3.4.  revocation-values Attribute Definition
+            <code>
+            RevocationValues ::=  SEQUENCE {
+            	crlVals			[0] SEQUENCE OF CertificateList     OPTIONAL,
+            	ocspVals		[1] SEQUENCE OF BasicOCSPResponse   OPTIONAL,
+            	otherRevVals	[2] OtherRevVals OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignaturePolicyId">
+            <remarks>
+            <code>
+            SignaturePolicyId ::= SEQUENCE {
+            	sigPolicyIdentifier		SigPolicyId,
+            	sigPolicyHash			SigPolicyHash,
+            	sigPolicyQualifiers		SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL
+            }
+            
+            SigPolicyId ::= OBJECT IDENTIFIER
+            
+            SigPolicyHash ::= OtherHashAlgAndValue
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignaturePolicyIdentifier">
+            <remarks>
+            <code>
+            SignaturePolicyIdentifier ::= CHOICE {
+            	SignaturePolicyId		SignaturePolicyId,
+            	SignaturePolicyImplied	SignaturePolicyImplied
+            }
+            
+            SignaturePolicyImplied ::= NULL
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.SignerAttribute.ToAsn1Object">
+            
+             <pre>
+              SignerAttribute ::= SEQUENCE OF CHOICE {
+                  claimedAttributes   [0] ClaimedAttributes,
+                  certifiedAttributes [1] CertifiedAttributes }
+            
+              ClaimedAttributes ::= SEQUENCE OF Attribute
+              CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignerLocation">
+             Signer-Location attribute (RFC3126).
+            
+             <pre>
+               SignerLocation ::= SEQUENCE {
+                   countryName        [0] DirectoryString OPTIONAL,
+                   localityName       [1] DirectoryString OPTIONAL,
+                   postalAddress      [2] PostalAddress OPTIONAL }
+            
+               PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.SignerLocation.ToAsn1Object">
+             <pre>
+               SignerLocation ::= SEQUENCE {
+                   countryName        [0] DirectoryString OPTIONAL,
+                   localityName       [1] DirectoryString OPTIONAL,
+                   postalAddress      [2] PostalAddress OPTIONAL }
+            
+               PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+            
+               DirectoryString ::= CHOICE {
+                     teletexString           TeletexString (SIZE (1..MAX)),
+                     printableString         PrintableString (SIZE (1..MAX)),
+                     universalString         UniversalString (SIZE (1..MAX)),
+                     utf8String              UTF8String (SIZE (1.. MAX)),
+                     bmpString               BMPString (SIZE (1..MAX)) }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SigPolicyQualifierInfo">
+            <remarks>
+            <code>
+            SigPolicyQualifierInfo ::= SEQUENCE {
+            	sigPolicyQualifierId  SigPolicyQualifierId,
+            	sigQualifier          ANY DEFINED BY sigPolicyQualifierId
+            }
+            
+            SigPolicyQualifierId ::= OBJECT IDENTIFIER
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentHints.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentHints.ToAsn1Object">
+            <pre>
+            ContentHints ::= SEQUENCE {
+              contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+              contentType ContentType }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+            Create from OCTET STRING whose octets represent the identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.#ctor(System.Byte[])">
+            Create from byte array representing the identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.ToAsn1Object">
+            The definition of ContentIdentifier is
+            <pre>
+            ContentIdentifier ::=  OCTET STRING
+            </pre>
+            id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 7 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertID.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertID.ToAsn1Object">
+            <pre>
+            EssCertID ::= SEQUENCE {
+                certHash Hash,
+                issuerSerial IssuerSerial OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertIDv2.ToAsn1Object">
+             <pre>
+             EssCertIDv2 ::=  SEQUENCE {
+                 hashAlgorithm     AlgorithmIdentifier
+                          DEFAULT {algorithm id-sha256},
+                 certHash          Hash,
+                 issuerSerial      IssuerSerial OPTIONAL
+             }
+            
+             Hash ::= OCTET STRING
+            
+             IssuerSerial ::= SEQUENCE {
+                 issuer         GeneralNames,
+                 serialNumber   CertificateSerialNumber
+             }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherCertID.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherCertID.ToAsn1Object">
+             <pre>
+             OtherCertID ::= SEQUENCE {
+                 otherCertHash    OtherHash,
+                 issuerSerial     IssuerSerial OPTIONAL }
+            
+             OtherHash ::= CHOICE {
+                 sha1Hash     OCTET STRING,
+                 otherHash    OtherHashAlgAndValue }
+            
+             OtherHashAlgAndValue ::= SEQUENCE {
+                 hashAlgorithm    AlgorithmIdentifier,
+                 hashValue        OCTET STRING }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherSigningCertificate.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructors
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherSigningCertificate.ToAsn1Object">
+            The definition of OtherSigningCertificate is
+            <pre>
+            OtherSigningCertificate ::=  SEQUENCE {
+                 certs        SEQUENCE OF OtherCertID,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 19 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificate.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructors
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificate.ToAsn1Object">
+            The definition of SigningCertificate is
+            <pre>
+            SigningCertificate ::=  SEQUENCE {
+                 certs        SEQUENCE OF EssCertID,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 12 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificateV2.ToAsn1Object">
+            The definition of SigningCertificateV2 is
+            <pre>
+            SigningCertificateV2 ::=  SEQUENCE {
+                 certs        SEQUENCE OF EssCertIDv2,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+               member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+               smime(16) id-aa(2) 47 }
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.CscaMasterList">
+             The CscaMasterList object. This object can be wrapped in a
+             CMSSignedData to be published in LDAP.
+            
+             <pre>
+             CscaMasterList ::= SEQUENCE {
+               version                CscaMasterListVersion,
+               certList               SET OF Certificate }
+               
+             CscaMasterListVersion :: INTEGER {v0(0)}
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.DataGroupHash">
+             The DataGroupHash object.
+             <pre>
+             DataGroupHash  ::=  SEQUENCE {
+                  dataGroupNumber         DataGroupNumber,
+                  dataGroupHashValue     OCTET STRING }
+            
+             DataGroupNumber ::= INTEGER {
+                     dataGroup1    (1),
+                     dataGroup1    (2),
+                     dataGroup1    (3),
+                     dataGroup1    (4),
+                     dataGroup1    (5),
+                     dataGroup1    (6),
+                     dataGroup1    (7),
+                     dataGroup1    (8),
+                     dataGroup1    (9),
+                     dataGroup1    (10),
+                     dataGroup1    (11),
+                     dataGroup1    (12),
+                     dataGroup1    (13),
+                     dataGroup1    (14),
+                     dataGroup1    (15),
+                     dataGroup1    (16) }
+            
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.LdsSecurityObject">
+             The LDSSecurityObject object (V1.8).
+             <pre>
+             LDSSecurityObject ::= SEQUENCE {
+               version                LDSSecurityObjectVersion,
+               hashAlgorithm          DigestAlgorithmIdentifier,
+               dataGroupHashValues    SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+               ldsVersionInfo         LDSVersionInfo OPTIONAL
+                 -- if present, version MUST be v1 }
+            
+             DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+            
+             LDSSecurityObjectVersion :: INTEGER {V0(0)}
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Icao.LdsVersionInfo.ToAsn1Object">
+            <pre>
+            LDSVersionInfo ::= SEQUENCE {
+               ldsVersion PRINTABLE STRING
+               unicodeVersion PRINTABLE STRING
+             }
+            </pre>
+            @return
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttCPAccredited">
+            The id-isismtt-cp-accredited OID indicates that the certificate is a
+            qualified certificate according to Directive 1999/93/EC of the European
+            Parliament and of the Council of 13 December 1999 on a Community
+            Framework for Electronic Signatures, which additionally conforms the
+            special requirements of the SigG and has been issued by an accredited CA.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen">
+             Certificate extensionDate of certificate generation
+             
+             <pre>
+            		DateOfCertGenSyntax ::= GeneralizedTime
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATProcuration">
+            Attribute to indicate that the certificate holder may sign in the name of
+            a third person. May also be used as extension in a certificate.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATAdmission">
+            Attribute to indicate admissions to certain professions. May be used as
+            attribute in attribute certificate or as extension in a certificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATMonetaryLimit">
+            Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+            be used in new certificates in place of the extension/attribute
+            MonetaryLimit since January 1, 2004. For the sake of backward
+            compatibility with certificates already in use, SigG conforming
+            components MUST support MonetaryLimit (as well as QcEuLimitValue).
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATDeclarationOfMajority">
+            A declaration of majority. May be used as attribute in attribute
+            certificate or as extension in a certificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATIccsn">
+             
+             Serial number of the smart card containing the corresponding private key
+             
+             <pre>
+            		ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATPKReference">
+             
+             Reference for a file of a smartcard that stores the public key of this
+             certificate and that is used as �security anchor�.
+             
+             <pre>
+            		PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRestriction">
+             Some other restriction regarding the usage of this certificate. May be
+             used as attribute in attribute certificate or as extension in a
+             certificate.
+             
+             <pre>
+            		RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             </pre>
+             
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRetrieveIfAllowed">
+             
+             (Single)Request extension: Clients may include this extension in a
+             (single) Request to request the responder to send the certificate in the
+             response message along with the status information. Besides the LDAP
+             service, this extension provides another mechanism for the distribution
+             of certificates, which MAY optionally be provided by certificate
+             repositories.
+             
+             <pre>
+            		RetrieveIfAllowed ::= BOOLEAN
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRequestedCertificate">
+            SingleOCSPResponse extension: The certificate requested by the client by
+            inserting the RetrieveIfAllowed extension in the request, will be
+            returned in this extension.
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATNamingAuthorities">
+            Base ObjectIdentifier for naming authorities
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATCertInDirSince">
+             SingleOCSPResponse extension: Date, when certificate has been published
+             in the directory and status information has become available. Currently,
+             accrediting authorities enforce that SigG-conforming OCSP servers include
+             this extension in the responses.
+             
+             <pre>
+            		CertInDirSince ::= GeneralizedTime
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATCertHash">
+             Hash of a certificate in OCSP.
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATNameAtBirth">
+             <pre>
+            		NameAtBirth ::= DirectoryString(SIZE(1..64)
+             </pre>
+             
+             Used in
+             {@link Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATAdditionalInformation">
+            Some other information of non-restrictive nature regarding the usage of
+            this certificate. May be used as attribute in atribute certificate or as
+            extension in a certificate.
+            
+            <pre>
+                          AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+            </pre>
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATLiabilityLimitationFlag">
+             Indicates that an attribute certificate exists, which limits the
+             usability of this public key certificate. Whenever verifying a signature
+             with the help of this certificate, the content of the corresponding
+             attribute certificate should be concerned. This extension MUST be
+             included in a PKC, if a corresponding attribute certificate (having the
+             PKC as base certificate) contains some attribute that restricts the
+             usability of the PKC too. Attribute certificates with restricting content
+             MUST always be included in the signed document.
+             
+             <pre>
+            		LiabilityLimitationFlagSyntax ::= BOOLEAN
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash">
+            ISIS-MTT PROFILE: The responder may include this extension in a response to
+            send the hash of the requested certificate to the responder. This hash is
+            cryptographically bound to the certificate and serves as evidence that the
+            certificate is known to the responder (i.e. it has been issued and is present
+            in the directory). Hence, this extension is a means to provide a positive
+            statement of availability as described in T8.[8]. As explained in T13.[1],
+            clients may rely on this information to be able to validate signatures after
+            the expiry of the corresponding certificate. Hence, clients MUST support this
+            extension. If a positive statement of availability is to be delivered, this
+            extension syntax and OID MUST be used.
+            <p/>
+            <p/>
+            <pre>
+                CertHash ::= SEQUENCE {
+                  hashAlgorithm AlgorithmIdentifier,
+                  certificateHash OCTET STRING
+                }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type CertHash:
+             <p/>
+             <pre>
+                 CertHash ::= SEQUENCE {
+                   hashAlgorithm AlgorithmIdentifier,
+                   certificateHash OCTET STRING
+                 }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.#ctor(Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,System.Byte[])">
+             Constructor from a given details.
+            
+             @param hashAlgorithm   The hash algorithm identifier.
+             @param certificateHash The hash of the whole DER encoding of the certificate.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 CertHash ::= SEQUENCE {
+                   hashAlgorithm AlgorithmIdentifier,
+                   certificateHash OCTET STRING
+                 }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate">
+            ISIS-MTT-Optional: The certificate requested by the client by inserting the
+            RetrieveIfAllowed extension in the request, will be returned in this
+            extension.
+            <p/>
+            ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+            when the certificate owner gives his isExplicit permission. Accordingly, there
+            may be �nondownloadable� certificates, about which the responder must provide
+            status information, but MUST NOT include them in the response. Clients may
+            get therefore the following three kind of answers on a single request
+            including the RetrieveIfAllowed extension:
+            <ul>
+            <li> a) the responder supports the extension and is allowed to publish the
+            certificate: RequestedCertificate returned including the requested
+            certificate</li>
+            <li>b) the responder supports the extension but is NOT allowed to publish
+            the certificate: RequestedCertificate returned including an empty OCTET
+            STRING</li>
+            <li>c) the responder does not support the extension: RequestedCertificate is
+            not included in the response</li>
+            </ul>
+            Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+            any of the OCTET STRING options is used, it MUST contain the DER encoding of
+            the requested certificate.
+            <p/>
+            <pre>
+                       RequestedCertificate ::= CHOICE {
+                         Certificate Certificate,
+                         publicKeyCertificate [0] EXPLICIT OCTET STRING,
+                         attributeCertificate [1] EXPLICIT OCTET STRING
+                       }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate.#ctor(Org.BouncyCastle.Asn1.X509.X509CertificateStructure)">
+             Constructor from a given details.
+             <p/>
+             Only one parameter can be given. All other must be <code>null</code>.
+            
+             @param certificate Given as Certificate
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                        RequestedCertificate ::= CHOICE {
+                          Certificate Certificate,
+                          publicKeyCertificate [0] EXPLICIT OCTET STRING,
+                          attributeCertificate [1] EXPLICIT OCTET STRING
+                        }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax">
+            Some other information of non-restrictive nature regarding the usage of this
+            certificate.
+            
+            <pre>
+               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param information The describtion of the information.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions">
+             An Admissions structure.
+             <p/>
+             <pre>
+                        Admissions ::= SEQUENCE
+                        {
+                          admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                          namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                          professionInfos SEQUENCE OF ProfessionInfo
+                        }
+             <p/>
+             </pre>
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                        Admissions ::= SEQUENCE
+                        {
+                          admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                          namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                          professionInfos SEQUENCE OF ProfessionInfo
+                        }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority,Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo[])">
+             Constructor from a given details.
+             <p/>
+             Parameter <code>professionInfos</code> is mandatory.
+            
+             @param admissionAuthority The admission authority.
+             @param namingAuthority    The naming authority.
+             @param professionInfos    The profession infos.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   Admissions ::= SEQUENCE
+                   {
+                     admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                     namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                     professionInfos SEQUENCE OF ProfessionInfo
+                   }
+             <p/>
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax">
+             Attribute to indicate admissions to certain professions.
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+             <p/>
+             <p/>
+             ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
+             supports the following concepts and requirements:
+             <ul>
+             <li> External institutions (e.g. professional associations, chambers, unions,
+             administrative bodies, companies, etc.), which are responsible for granting
+             and verifying professional admissions, are indicated by means of the data
+             field admissionAuthority. An admission authority is indicated by a
+             GeneralName object. Here an X.501 directory name (distinguished name) can be
+             indicated in the field directoryName, a URL address can be indicated in the
+             field uniformResourceIdentifier, and an object identifier can be indicated in
+             the field registeredId.</li>
+             <li> The names of authorities which are responsible for the administration of
+             title registers are indicated in the data field namingAuthority. The name of
+             the authority can be identified by an object identifier in the field
+             namingAuthorityId, by means of a text string in the field
+             namingAuthorityText, by means of a URL address in the field
+             namingAuthorityUrl, or by a combination of them. For example, the text string
+             can contain the name of the authority, the country and the name of the title
+             register. The URL-option refers to a web page which contains lists with
+             officially registered professions (text and possibly OID) as well as
+             further information on these professions. Object identifiers for the
+             component namingAuthorityId are grouped under the OID-branch
+             id-isis-at-namingAuthorities and must be applied for.</li>
+             <li>See http://www.teletrust.de/anwend.asp?Id=30200&Sprache=E_&HomePG=0
+             for an application form and http://www.teletrust.de/links.asp?id=30220,11
+             for an overview of registered naming authorities.</li>
+             <li> By means of the data type ProfessionInfo certain professions,
+             specializations, disciplines, fields of activity, etc. are identified. A
+             profession is represented by one or more text strings, resp. profession OIDs
+             in the fields professionItems and professionOIDs and by a registration number
+             in the field registrationNumber. An indication in text form must always be
+             present, whereas the other indications are optional. The component
+             addProfessionInfo may contain additional applicationspecific information in
+             DER-encoded form.</li>
+             </ul>
+             <p/>
+             By means of different namingAuthority-OIDs or profession OIDs hierarchies of
+             professions, specializations, disciplines, fields of activity, etc. can be
+             expressed. The issuing admission authority should always be indicated (field
+             admissionAuthority), whenever a registration number is presented. Still,
+             information on admissions can be given without indicating an admission or a
+             naming authority by the exclusive use of the component professionItems. In
+             this case the certification authority is responsible for the verification of
+             the admission information.
+             <p/>
+             <p/>
+             <p/>
+             This attribute is single-valued. Still, several admissions can be captured in
+             the sequence structure of the component contentsOfAdmissions of
+             AdmissionSyntax or in the component professionInfos of Admissions. The
+             component admissionAuthority of AdmissionSyntax serves as default value for
+             the component admissionAuthority of Admissions. Within the latter component
+             the default value can be overwritten, in case that another authority is
+             responsible. The component namingAuthority of Admissions serves as a default
+             value for the component namingAuthority of ProfessionInfo. Within the latter
+             component the default value can be overwritten, in case that another naming
+             authority needs to be recorded.
+             <p/>
+             The length of the string objects is limited to 128 characters. It is
+             recommended to indicate a namingAuthorityURL in all issued attribute
+             certificates. If a namingAuthorityURL is indicated, the field professionItems
+             of ProfessionInfo should contain only registered titles. If the field
+             professionOIDs exists, it has to contain the OIDs of the professions listed
+             in professionItems in the same order. In general, the field professionInfos
+             should contain only one entry, unless the admissions that are to be listed
+             are logically connected (e.g. they have been issued under the same admission
+             number).
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from given details.
+            
+             @param admissionAuthority   The admission authority.
+             @param contentsOfAdmissions The admissions.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.GetContentsOfAdmissions">
+            @return Returns the contentsOfAdmissions.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.AdmissionAuthority">
+            @return Returns the admissionAuthority if present, null otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority">
+            A declaration of majority.
+            <p/>
+            <pre>
+                      DeclarationOfMajoritySyntax ::= CHOICE
+                      {
+                        notYoungerThan [0] IMPLICIT INTEGER,
+                        fullAgeAtCountry [1] IMPLICIT SEQUENCE
+                        {
+                          fullAge BOOLEAN DEFAULT TRUE,
+                          country PrintableString (SIZE(2))
+                        }
+                        dateOfBirth [2] IMPLICIT GeneralizedTime
+                      }
+            </pre>
+            <p/>
+            fullAgeAtCountry indicates the majority of the owner with respect to the laws
+            of a specific country.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                       DeclarationOfMajoritySyntax ::= CHOICE
+                       {
+                         notYoungerThan [0] IMPLICIT INTEGER,
+                         fullAgeAtCountry [1] IMPLICIT SEQUENCE
+                         {
+                           fullAge BOOLEAN DEFAULT TRUE,
+                           country PrintableString (SIZE(2))
+                         }
+                         dateOfBirth [2] IMPLICIT GeneralizedTime
+                       }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority.NotYoungerThan">
+            @return notYoungerThan if that's what we are, -1 otherwise
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit">
+            Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+            used in new certificates in place of the extension/attribute MonetaryLimit
+            since January 1, 2004. For the sake of backward compatibility with
+            certificates already in use, components SHOULD support MonetaryLimit (as well
+            as QcEuLimitValue).
+            <p/>
+            Indicates a monetary limit within which the certificate holder is authorized
+            to act. (This value DOES NOT express a limit on the liability of the
+            certification authority).
+            <p/>
+            <pre>
+               MonetaryLimitSyntax ::= SEQUENCE
+               {
+                 currency PrintableString (SIZE(3)),
+                 amount INTEGER,
+                 exponent INTEGER
+               }
+            </pre>
+            <p/>
+            currency must be the ISO code.
+            <p/>
+            value = amount�10*exponent
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit.#ctor(System.String,System.Int32,System.Int32)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             value = amount�10^exponent
+            
+             @param currency The currency. Must be the ISO code.
+             @param amount   The amount
+             @param exponent The exponent
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                MonetaryLimitSyntax ::= SEQUENCE
+                {
+                  currency PrintableString (SIZE(3)),
+                  amount INTEGER,
+                  exponent INTEGER
+                }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority">
+            Names of authorities which are responsible for the administration of title
+            registers.
+            
+            <pre>
+                        NamingAuthority ::= SEQUENCE 
+                        {
+                          namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                          namingAuthorityUrl IA5String OPTIONAL,
+                          namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                        }
+            </pre>
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern">
+            Profession OIDs should always be defined under the OID branch of the
+            responsible naming authority. At the time of this writing, the work group
+            �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+            first naming authority under the OID id-isismtt-at-namingAuthorities.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             <p/>
+             <pre>
+                         NamingAuthority ::= SEQUENCE
+                         {
+                           namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                           namingAuthorityUrl IA5String OPTIONAL,
+                           namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                         }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String,Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from given details.
+             <p/>
+             All parameters can be combined.
+            
+             @param namingAuthorityID   ObjectIdentifier for naming authority.
+             @param namingAuthorityUrl  URL for naming authority.
+             @param namingAuthorityText Textual representation of naming authority.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                         NamingAuthority ::= SEQUENCE
+                         {
+                           namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                           namingAuthorityUrl IA5String OPTIONAL,
+                           namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                         }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityID">
+            @return Returns the namingAuthorityID.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityText">
+            @return Returns the namingAuthorityText.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityUrl">
+            @return Returns the namingAuthorityUrl.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax">
+            Attribute to indicate that the certificate holder may sign in the name of a
+            third person.
+            <p>
+            ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+            name of the person who is represented (subcomponent thirdPerson) or a
+            reference to his/her base certificate (in the component signingFor,
+            subcomponent certRef), furthermore the optional components country and
+            typeSubstitution to indicate the country whose laws apply, and respectively
+            the type of procuration (e.g. manager, procuration, custody).
+            </p>
+            <p>
+            ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+            contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+            surname, givenName, serialNumber, organizationName, organizationalUnitName,
+            stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+            attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+            countryOfResidence and NameAtBirth).
+            </p>
+            <pre>
+                          ProcurationSyntax ::= SEQUENCE {
+                            country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                            typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                            signingFor [3] EXPLICIT SigningFor 
+                          }
+                          
+                          SigningFor ::= CHOICE 
+                          { 
+                            thirdPerson GeneralName,
+                            certRef IssuerSerial 
+                          }
+            </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                           ProcurationSyntax ::= SEQUENCE {
+                             country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                             typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                             signingFor [3] EXPLICIT SigningFor
+                           }
+             <p/>
+                           SigningFor ::= CHOICE
+                           {
+                             thirdPerson GeneralName,
+                             certRef IssuerSerial
+                           }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(System.String,Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.X509.IssuerSerial)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             Either <code>generalName</code> or <code>certRef</code> MUST be
+             <code>null</code>.
+            
+             @param country            The country code whose laws apply.
+             @param typeOfSubstitution The type of procuration.
+             @param certRef            Reference to certificate of the person who is represented.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(System.String,Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             Either <code>generalName</code> or <code>certRef</code> MUST be
+             <code>null</code>.
+            
+             @param country            The country code whose laws apply.
+             @param typeOfSubstitution The type of procuration.
+             @param thirdPerson        The GeneralName of the person who is represented.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                           ProcurationSyntax ::= SEQUENCE {
+                             country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                             typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                             signingFor [3] EXPLICIT SigningFor
+                           }
+             <p/>
+                           SigningFor ::= CHOICE
+                           {
+                             thirdPerson GeneralName,
+                             certRef IssuerSerial
+                           }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo">
+            Professions, specializations, disciplines, fields of activity, etc.
+            
+            <pre>
+                          ProfessionInfo ::= SEQUENCE 
+                          {
+                            namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                            professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                            professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                            registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                            addProfessionInfo OCTET STRING OPTIONAL 
+                          }
+            </pre>
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsanwltin">
+            Rechtsanw�ltin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsanwalt">
+            Rechtsanwalt
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsbeistand">
+            Rechtsbeistand
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerberaterin">
+            Steuerberaterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerberater">
+            Steuerberater
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerbevollmchtigte">
+            Steuerbevollm�chtigte
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerbevollmchtigter">
+            Steuerbevollm�chtigter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarin">
+            Notarin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notar">
+            Notar
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarvertreterin">
+            Notarvertreterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarvertreter">
+            Notarvertreter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notariatsverwalterin">
+            Notariatsverwalterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notariatsverwalter">
+            Notariatsverwalter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Wirtschaftsprferin">
+            Wirtschaftspr�ferin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Wirtschaftsprfer">
+            Wirtschaftspr�fer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.VereidigteBuchprferin">
+            Vereidigte Buchpr�ferin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.VereidigterBuchprfer">
+            Vereidigter Buchpr�fer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Patentanwltin">
+            Patentanw�ltin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Patentanwalt">
+            Patentanwalt
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             <p/>
+             <pre>
+                           ProfessionInfo ::= SEQUENCE
+                           {
+                             namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                             professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                             professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                             registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                             addProfessionInfo OCTET STRING OPTIONAL
+                           }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.#ctor(Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority,Org.BouncyCastle.Asn1.X500.DirectoryString[],Org.BouncyCastle.Asn1.DerObjectIdentifier[],System.String,Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor from given details.
+             <p/>
+             <code>professionItems</code> is mandatory, all other parameters are
+             optional.
+            
+             @param namingAuthority    The naming authority.
+             @param professionItems    Directory strings of the profession.
+             @param professionOids     DERObjectIdentfier objects for the
+                                       profession.
+             @param registrationNumber Registration number.
+             @param addProfessionInfo  Additional infos in encoded form.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                           ProfessionInfo ::= SEQUENCE
+                           {
+                             namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                             professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                             professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                             registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                             addProfessionInfo OCTET STRING OPTIONAL
+                           }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.GetProfessionItems">
+            @return Returns the professionItems.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.GetProfessionOids">
+            @return Returns the professionOids.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.AddProfessionInfo">
+            @return Returns the addProfessionInfo.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.NamingAuthority">
+            @return Returns the namingAuthority.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.RegistrationNumber">
+            @return Returns the registrationNumber.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction">
+            Some other restriction regarding the usage of this certificate.
+            <p/>
+            <pre>
+             RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from DirectoryString.
+             <p/>
+             The DirectoryString is of type RestrictionSyntax:
+             <p/>
+             <pre>
+                  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             </pre>
+            
+             @param restriction A IAsn1String.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param restriction The description of the restriction.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             <p/>
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.Cast5CbcParameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            cast5CBCParameters ::= Sequence {
+                                      iv         OCTET STRING DEFAULT 0,
+                                             -- Initialization vector
+                                      keyLength  Integer
+                                             -- Key length, in bits
+                                 }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.IdeaCbcPar.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            IDEA-CBCPar ::= Sequence {
+                                 iv    OCTET STRING OPTIONAL -- exactly 8 octets
+                             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Misc.NetscapeCertType">
+            The NetscapeCertType object.
+            <pre>
+               NetscapeCertType ::= BIT STRING {
+                    SSLClient               (0),
+                    SSLServer               (1),
+                    S/MIME                  (2),
+                    Object Signing          (3),
+                    Reserved                (4),
+                    SSL CA                  (5),
+                    S/MIME CA               (6),
+                    Object Signing CA       (7) }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.NetscapeCertType.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Mozilla.PublicKeyAndChallenge">
+             This is designed to parse
+             the PublicKeyAndChallenge created by the KEYGEN tag included by
+             Mozilla based browsers.
+              <pre>
+              PublicKeyAndChallenge ::= SEQUENCE {
+                spki SubjectPublicKeyInfo,
+                challenge IA5STRING
+              }
+            
+              </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Nist.NistNamedCurves">
+            Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-3
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Ntt.NttObjectIdentifiers">
+            <summary>From RFC 3657</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.BasicOcspResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            BasicOcspResponse       ::= Sequence {
+                 tbsResponseData      ResponseData,
+                 signatureAlgorithm   AlgorithmIdentifier,
+                 signature            BIT STRING,
+                 certs                [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CertID          ::=     Sequence {
+                hashAlgorithm       AlgorithmIdentifier,
+                issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+                issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+                serialNumber        CertificateSerialNumber }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertStatus.#ctor">
+            create a CertStatus object with a tag of zero.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertStatus.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             CertStatus ::= CHOICE {
+                             good        [0]     IMPLICIT Null,
+                             revoked     [1]     IMPLICIT RevokedInfo,
+                             unknown     [2]     IMPLICIT UnknownInfo }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CrlID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CrlID ::= Sequence {
+                crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+                crlNum               [1]     EXPLICIT Integer OPTIONAL,
+                crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspRequest.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OcspRequest     ::=     Sequence {
+                tbsRequest                  TBSRequest,
+                optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OcspResponse ::= Sequence {
+                responseStatus         OcspResponseStatus,
+                responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspResponseStatus.#ctor(System.Int32)">
+            The OcspResponseStatus enumeration.
+            <pre>
+            OcspResponseStatus ::= Enumerated {
+                successful            (0),  --Response has valid confirmations
+                malformedRequest      (1),  --Illegal confirmation request
+                internalError         (2),  --Internal error in issuer
+                tryLater              (3),  --Try again later
+                                            --(4) is not used
+                sigRequired           (5),  --Must sign the request
+                unauthorized          (6)   --Request unauthorized
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.Request.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Request         ::=     Sequence {
+                reqCert                     CertID,
+                singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponderID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponderID ::= CHOICE {
+                 byName          [1] Name,
+                 byKey           [2] KeyHash }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponseBytes.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponseBytes ::=       Sequence {
+                responseType   OBJECT IDENTIFIER,
+                response       OCTET STRING }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponseData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponseData ::= Sequence {
+                version              [0] EXPLICIT Version DEFAULT v1,
+                responderID              ResponderID,
+                producedAt               GeneralizedTime,
+                responses                Sequence OF SingleResponse,
+                responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.RevokedInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RevokedInfo ::= Sequence {
+                 revocationTime              GeneralizedTime,
+                 revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ServiceLocator.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ServiceLocator ::= Sequence {
+                issuer    Name,
+                locator   AuthorityInfoAccessSyntax OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.Signature.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Signature       ::=     Sequence {
+                signatureAlgorithm      AlgorithmIdentifier,
+                signature               BIT STRING,
+                certs               [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.SingleResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             SingleResponse ::= Sequence {
+                     certID                       CertID,
+                     certStatus                   CertStatus,
+                     thisUpdate                   GeneralizedTime,
+                     nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
+                     singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.TbsRequest.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            TBSRequest      ::=     Sequence {
+                version             [0]     EXPLICIT Version DEFAULT v1,
+                requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+                requestList                 Sequence OF Request,
+                requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.OidTokenizer">
+            class for breaking up an Oid into it's component tokens, ala
+            java.util.StringTokenizer. We need this class as some of the
+            lightweight Java environment don't support classes like
+            StringTokenizer.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.AttributePkcs.GetInstance(System.Object)">
+             return an Attribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.AttributePkcs.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attr ::= Sequence {
+                attrType OBJECT IDENTIFIER,
+                attrValues Set OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.CertificationRequest">
+            Pkcs10 Certfication request object.
+            <pre>
+            CertificationRequest ::= Sequence {
+              certificationRequestInfo  CertificationRequestInfo,
+              signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+              signature                 BIT STRING
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.CertificationRequestInfo">
+             Pkcs10 CertificationRequestInfo object.
+             <pre>
+              CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.ContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= Sequence {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.EncryptedData">
+             The EncryptedData object.
+             <pre>
+                  EncryptedData ::= Sequence {
+                       version Version,
+                       encryptedContentInfo EncryptedContentInfo
+                  }
+            
+            
+                  EncryptedContentInfo ::= Sequence {
+                      contentType ContentType,
+                      contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
+                      encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+                }
+            
+                EncryptedContent ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             EncryptedPrivateKeyInfo ::= Sequence {
+                  encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+                  encryptedData EncryptedData
+             }
+            
+             EncryptedData ::= OCTET STRING
+            
+             KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+                      ... -- For local profiles
+             }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+                 AlgorithmIdentifier ::= Sequence {
+                                       algorithm OBJECT IDENTIFIER,
+                                       parameters ANY DEFINED BY algorithm OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.MacData.ToAsn1Object">
+            <pre>
+            MacData ::= SEQUENCE {
+                mac      DigestInfo,
+                macSalt  OCTET STRING,
+                iterations INTEGER DEFAULT 1
+                -- Note: The default is for historic reasons and its use is deprecated. A
+                -- higher value, like 1024 is recommended.
+            </pre>
+            @return the basic DERObject construction.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.Pfx">
+            the infamous Pfx from Pkcs12
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo.ToAsn1Object">
+             write out an RSA private key with its associated information
+             as described in Pkcs8.
+             <pre>
+                  PrivateKeyInfo ::= Sequence {
+                                          version Version,
+                                          privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+                                          privateKey PrivateKey,
+                                          attributes [0] IMPLICIT Attributes OPTIONAL
+                                      }
+                  Version ::= Integer {v1(0)} (v1,...)
+            
+                  PrivateKey ::= OCTET STRING
+            
+                  Attributes ::= Set OF Attr
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaesOaepParameters.#ctor">
+            The default version
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaesOaepParameters.ToAsn1Object">
+             <pre>
+              RSAES-OAEP-params ::= SEQUENCE {
+                 hashAlgorithm      [0] OAEP-PSSDigestAlgorithms     DEFAULT sha1,
+                 maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+                 pSourceAlgorithm   [2] PKCS1PSourceAlgorithms  DEFAULT pSpecifiedEmpty
+               }
+            
+               OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-sha1 PARAMETERS NULL   }|
+                 { OID id-sha256 PARAMETERS NULL }|
+                 { OID id-sha384 PARAMETERS NULL }|
+                 { OID id-sha512 PARAMETERS NULL },
+                 ...  -- Allows for future expansion --
+               }
+               PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+                ...  -- Allows for future expansion --
+               }
+               PKCS1PSourceAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-pSpecified PARAMETERS OCTET STRING },
+                 ...  -- Allows for future expansion --
+              }
+             </pre>
+             @return the asn1 primitive representing the parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaPrivateKeyStructure.ToAsn1Object">
+             This outputs the key in Pkcs1v2 format.
+             <pre>
+                  RsaPrivateKey ::= Sequence {
+                                      version Version,
+                                      modulus Integer, -- n
+                                      publicExponent Integer, -- e
+                                      privateExponent Integer, -- d
+                                      prime1 Integer, -- p
+                                      prime2 Integer, -- q
+                                      exponent1 Integer, -- d mod (p-1)
+                                      exponent2 Integer, -- d mod (q-1)
+                                      coefficient Integer -- (inverse of q) mod p
+                                  }
+            
+                  Version ::= Integer
+             </pre>
+             <p>This routine is written to output Pkcs1 version 0, private keys.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters.#ctor">
+            The default version
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters.ToAsn1Object">
+             <pre>
+             RSASSA-PSS-params ::= SEQUENCE {
+               hashAlgorithm      [0] OAEP-PSSDigestAlgorithms  DEFAULT sha1,
+                maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+                saltLength         [2] INTEGER  DEFAULT 20,
+                trailerField       [3] TrailerField  DEFAULT trailerFieldBC
+              }
+            
+             OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                { OID id-sha1 PARAMETERS NULL   }|
+                { OID id-sha256 PARAMETERS NULL }|
+                { OID id-sha384 PARAMETERS NULL }|
+                { OID id-sha512 PARAMETERS NULL },
+                ...  -- Allows for future expansion --
+             }
+            
+             PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+               { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+                ...  -- Allows for future expansion --
+             }
+            
+             TrailerField ::= INTEGER { trailerFieldBC(1) }
+             </pre>
+             @return the asn1 primitive representing the parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.SignedData">
+            a Pkcs#7 signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.SignedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             SignedData ::= Sequence {
+                 version Version,
+                 digestAlgorithms DigestAlgorithmIdentifiers,
+                 contentInfo ContentInfo,
+                 certificates
+                     [0] IMPLICIT ExtendedCertificatesAndCertificates
+                              OPTIONAL,
+                 crls
+                     [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                 signerInfos SignerInfos }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.SignerInfo">
+            a Pkcs#7 signer info object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.SignerInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              SignerInfo ::= Sequence {
+                  version Version,
+                  issuerAndSerialNumber IssuerAndSerialNumber,
+                  digestAlgorithm DigestAlgorithmIdentifier,
+                  authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+                  digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+                  encryptedDigest EncryptedDigest,
+                  unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+              }
+            
+              EncryptedDigest ::= OCTET STRING
+            
+              DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+            
+              DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Sec.ECPrivateKeyStructure">
+            the elliptic curve private key object from SEC 1
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.ECPrivateKeyStructure.ToAsn1Object">
+            ECPrivateKey ::= SEQUENCE {
+                version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+                privateKey OCTET STRING,
+                parameters [0] Parameters OPTIONAL,
+                publicKey [1] BIT STRING OPTIONAL }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Sec.SecObjectIdentifiers.EllipticCurve">
+            EllipticCurve OBJECT IDENTIFIER ::= {
+                  iso(1) identified-organization(3) certicom(132) curve(0)
+            }
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities">
+            Handler class for dealing with S/MIME Capabilities
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.PreferSignedData">
+            general preferences
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.DesCbc">
+            encryption algorithms preferences
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.GetInstance(System.Object)">
+             return an Attr object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.GetCapabilitiesForOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            returns an ArrayList with 0 or more objects of all the capabilities
+            matching the passed in capability Oid. If the Oid passed is null the
+            entire set is returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SMIMECapabilities ::= Sequence OF SMIMECapability
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeX509.GetInstance(System.Object)">
+             return an Attr object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeX509.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attr ::= Sequence {
+                attrType OBJECT IDENTIFIER,
+                attrValues Set OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapability.PreferSignedData">
+            general preferences
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapability.DesCbc">
+            encryption algorithms preferences
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapability.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SMIMECapability ::= Sequence {
+                capabilityID OBJECT IDENTIFIER,
+                parameters ANY DEFINED BY capabilityID OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeCapabilityVector">
+            Handler for creating a vector S/MIME Capabilities
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeEncryptionKeyPreferenceAttribute">
+            The SmimeEncryptionKeyPreference object.
+            <pre>
+            SmimeEncryptionKeyPreference ::= CHOICE {
+                issuerAndSerialNumber   [0] IssuerAndSerialNumber,
+                receipentKeyId          [1] RecipientKeyIdentifier,
+                subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeEncryptionKeyPreferenceAttribute.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+            @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves">
+            elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+            http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.Accuracy.ToAsn1Object">
+            <pre>
+            Accuracy ::= SEQUENCE {
+                        seconds        INTEGER              OPTIONAL,
+                        millis     [0] INTEGER  (1..999)    OPTIONAL,
+                        micros     [1] INTEGER  (1..999)    OPTIONAL
+                        }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.MessageImprint.GetInstance(System.Object)">
+            @param o
+            @return a MessageImprint object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.MessageImprint.ToAsn1Object">
+            <pre>
+               MessageImprint ::= SEQUENCE  {
+                  hashAlgorithm                AlgorithmIdentifier,
+                  hashedMessage                OCTET STRING  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TimeStampReq.ToAsn1Object">
+            <pre>
+            TimeStampReq ::= SEQUENCE  {
+             version                      INTEGER  { v1(1) },
+             messageImprint               MessageImprint,
+               --a hash algorithm OID and the hash value of the data to be
+               --time-stamped
+             reqPolicy             TSAPolicyId              OPTIONAL,
+             nonce                 INTEGER                  OPTIONAL,
+             certReq               BOOLEAN                  DEFAULT FALSE,
+             extensions            [0] IMPLICIT Extensions  OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TimeStampResp.ToAsn1Object">
+            <pre>
+            TimeStampResp ::= SEQUENCE  {
+              status                  PkiStatusInfo,
+              timeStampToken          TimeStampToken     OPTIONAL  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TstInfo.ToAsn1Object">
+             <pre>
+            
+                 TstInfo ::= SEQUENCE  {
+                    version                      INTEGER  { v1(1) },
+                    policy                       TSAPolicyId,
+                    messageImprint               MessageImprint,
+                      -- MUST have the same value as the similar field in
+                      -- TimeStampReq
+                    serialNumber                 INTEGER,
+                     -- Time-Stamping users MUST be ready to accommodate integers
+                     -- up to 160 bits.
+                    genTime                      GeneralizedTime,
+                    accuracy                     Accuracy                 OPTIONAL,
+                    ordering                     BOOLEAN             DEFAULT FALSE,
+                    nonce                        INTEGER                  OPTIONAL,
+                      -- MUST be present if the similar field was present
+                      -- in TimeStampReq.  In that case it MUST have the same value.
+                    tsa                          [0] GeneralName          OPTIONAL,
+                    extensions                   [1] IMPLICIT Extensions   OPTIONAL  }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.AsString(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Object,System.Text.StringBuilder)">
+             dump a Der object as a formatted string with indentation
+            
+             @param obj the Asn1Object to be dumped out.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.DumpAsString(Org.BouncyCastle.Asn1.Asn1Encodable)">
+             dump out a DER object as a formatted string, in non-verbose mode
+            
+             @param obj the Asn1Encodable to be dumped out.
+             @return  the resulting string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.DumpAsString(Org.BouncyCastle.Asn1.Asn1Encodable,System.Boolean)">
+             Dump out the object as a string
+            
+             @param obj the Asn1Encodable to be dumped out.
+             @param verbose  if true, dump out the contents of octet and bit strings.
+             @return  the resulting string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X500.DirectoryString.ToAsn1Object">
+            <pre>
+             DirectoryString ::= CHOICE {
+               teletexString               TeletexString (SIZE (1..MAX)),
+               printableString             PrintableString (SIZE (1..MAX)),
+               universalString             UniversalString (SIZE (1..MAX)),
+               utf8String                  UTF8String (SIZE (1..MAX)),
+               bmpString                   BMPString (SIZE (1..MAX))  }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AccessDescription">
+            The AccessDescription object.
+            <pre>
+            AccessDescription  ::=  SEQUENCE {
+                  accessMethod          OBJECT IDENTIFIER,
+                  accessLocation        GeneralName  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AccessDescription.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            create an AccessDescription with the oid and location provided.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.AccessDescription.AccessMethod">
+            
+             @return the access method.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.AccessDescription.AccessLocation">
+            
+             @return the access location
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertIssuer.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames)">
+            <summary>
+            Don't use this one if you are trying to be RFC 3281 compliant.
+            Use it for v1 attribute certificates only.
+            </summary>
+            <param name="names">Our GeneralNames structure</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertIssuer.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttCertIssuer ::= CHOICE {
+                  v1Form   GeneralNames,  -- MUST NOT be used in this
+                                          -- profile
+                  v2Form   [0] V2Form     -- v2 only
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertValidityPeriod.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttCertValidityPeriod  ::= Sequence {
+                  notBeforeTime  GeneralizedTime,
+                  notAfterTime   GeneralizedTime
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificate.GetInstance(System.Object)">
+            @param obj
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificate.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttributeCertificate ::= Sequence {
+                  acinfo               AttributeCertificateInfo,
+                  signatureAlgorithm   AlgorithmIdentifier,
+                  signatureValue       BIT STRING
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificateInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              AttributeCertificateInfo ::= Sequence {
+                   version              AttCertVersion -- version is v2,
+                   holder               Holder,
+                   issuer               AttCertIssuer,
+                   signature            AlgorithmIdentifier,
+                   serialNumber         CertificateSerialNumber,
+                   attrCertValidityPeriod   AttCertValidityPeriod,
+                   attributes           Sequence OF Attr,
+                   issuerUniqueID       UniqueIdentifier OPTIONAL,
+                   extensions           Extensions OPTIONAL
+              }
+            
+              AttCertVersion ::= Integer { v2(1) }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AuthorityInformationAccess">
+             The AuthorityInformationAccess object.
+             <pre>
+             id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+            
+             AuthorityInfoAccessSyntax  ::=
+                  Sequence SIZE (1..MAX) OF AccessDescription
+             AccessDescription  ::=  Sequence {
+                   accessMethod          OBJECT IDENTIFIER,
+                   accessLocation        GeneralName  }
+            
+             id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+             id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+             id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityInformationAccess.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            create an AuthorityInformationAccess with the oid and location provided.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier">
+             The AuthorityKeyIdentifier object.
+             <pre>
+             id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
+            
+               AuthorityKeyIdentifier ::= Sequence {
+                  keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
+                  authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
+                  authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
+            
+               KeyIdentifier ::= OCTET STRING
+             </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+                     *
+                     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+                     * from SubjectPublicKeyInfo as defined in RFC2459.
+                     *
+                     * Example of making a AuthorityKeyIdentifier:
+                     * <pre>
+            	     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+            		 *       publicKey.getEncoded()).readObject());
+                     *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+                     * </pre>
+                     *
+                     *
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo,Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with the GeneralNames tag and
+            the serial number provided as well.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with the GeneralNames tag and
+            the serial number provided.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(System.Byte[])">
+            create an AuthorityKeyIdentifier with a precomputed key identifier
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(System.Byte[],Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with a precomupted key identifier
+            and the GeneralNames tag and the serial number provided as well.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.BasicConstraints.#ctor(System.Int32)">
+             create a cA=true object for the given path length constraint.
+            
+             @param pathLenConstraint
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.BasicConstraints.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            BasicConstraints := Sequence {
+               cA                  Boolean DEFAULT FALSE,
+               pathLenConstraint   Integer (0..MAX) OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertificateList">
+             PKIX RFC-2459
+            
+             The X.509 v2 CRL syntax is as follows.  For signature calculation,
+             the data that is to be signed is ASN.1 Der encoded.
+            
+             <pre>
+             CertificateList  ::=  Sequence  {
+                  tbsCertList          TbsCertList,
+                  signatureAlgorithm   AlgorithmIdentifier,
+                  signatureValue       BIT STRING  }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertificatePair">
+             This class helps to support crossCerfificatePairs in a LDAP directory
+             according RFC 2587
+            
+             <pre>
+                 crossCertificatePairATTRIBUTE::={
+                   WITH SYNTAX   CertificatePair
+                   EQUALITY MATCHING RULE certificatePairExactMatch
+                   ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+             </pre>
+            
+             <blockquote> The forward elements of the crossCertificatePair attribute of a
+             CA's directory entry shall be used to store all, except self-issued
+             certificates issued to this CA. Optionally, the reverse elements of the
+             crossCertificatePair attribute, of a CA's directory entry may contain a
+             subset of certificates issued by this CA to other CAs. When both the forward
+             and the reverse elements are present in a single attribute value, issuer name
+             in one certificate shall match the subject name in the other and vice versa,
+             and the subject public key in one certificate shall be capable of verifying
+             the digital signature on the other certificate and vice versa.
+            
+             When a reverse element is present, the forward element value and the reverse
+             element value need not be stored in the same attribute value; in other words,
+             they can be stored in either a single attribute value or two attribute
+             values. </blockquote>
+            
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type CertificatePair:
+             <p/>
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.#ctor(Org.BouncyCastle.Asn1.X509.X509CertificateStructure,Org.BouncyCastle.Asn1.X509.X509CertificateStructure)">
+             Constructor from a given details.
+            
+             @param forward Certificates issued to this CA.
+             @param reverse Certificates issued by this CA to other CAs.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.CertificatePair.Forward">
+            @return Returns the forward.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.CertificatePair.Reverse">
+            @return Returns the reverse.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePolicies.#ctor(Org.BouncyCastle.Asn1.X509.PolicyInformation)">
+            Construct a CertificatePolicies object containing one PolicyInformation.
+            
+            @param name the name to be contained.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePolicies.ToAsn1Object">
+            Produce an object suitable for an ASN1OutputStream.
+            <pre>
+            CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertPolicyID">
+             CertPolicyId, used in the CertificatePolicies and PolicyMappings
+             X509V3 Extensions.
+            
+             <pre>
+                 CertPolicyId ::= OBJECT IDENTIFIER
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CrlDistPoint.GetDistributionPoints">
+             Return the distribution points making up the sequence.
+            
+             @return DistributionPoint[]
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CrlDistPoint.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CrlDistPoint ::= Sequence SIZE {1..MAX} OF DistributionPoint
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CrlNumber">
+            The CRLNumber object.
+            <pre>
+            CRLNumber::= Integer(0..MAX)
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CrlReason">
+            The CRLReason enumeration.
+            <pre>
+            CRLReason ::= Enumerated {
+             unspecified             (0),
+             keyCompromise           (1),
+             cACompromise            (2),
+             affiliationChanged      (3),
+             superseded              (4),
+             cessationOfOperation    (5),
+             certificateHold         (6),
+             removeFromCRL           (8),
+             privilegeWithdrawn      (9),
+             aACompromise           (10)
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DigestInfo">
+            The DigestInfo object.
+            <pre>
+            DigestInfo::=Sequence{
+                     digestAlgorithm  AlgorithmIdentifier,
+                     digest OCTET STRING }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DisplayText">
+             <code>DisplayText</code> class, used in
+             <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
+            
+             <p>It stores a string in a chosen encoding.
+             <pre>
+             DisplayText ::= CHOICE {
+                  ia5String        IA5String      (SIZE (1..200)),
+                  visibleString    VisibleString  (SIZE (1..200)),
+                  bmpString        BMPString      (SIZE (1..200)),
+                  utf8String       UTF8String     (SIZE (1..200)) }
+             </pre></p>
+             @see PolicyQualifierInfo
+             @see PolicyInformation
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeIA5String">
+             Constant corresponding to ia5String encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeBmpString">
+             Constant corresponding to bmpString encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeUtf8String">
+             Constant corresponding to utf8String encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeVisibleString">
+             Constant corresponding to visibleString encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.DisplayTextMaximumSize">
+             Describe constant <code>DisplayTextMaximumSize</code> here.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(System.Int32,System.String)">
+             Creates a new <code>DisplayText</code> instance.
+            
+             @param type the desired encoding type for the text.
+             @param text the text to store. Strings longer than 200
+             characters are truncated.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(System.String)">
+             Creates a new <code>DisplayText</code> instance.
+            
+             @param text the text to encapsulate. Strings longer than 200
+             characters are truncated.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(Org.BouncyCastle.Asn1.IAsn1String)">
+             Creates a new <code>DisplayText</code> instance.
+             <p>Useful when reading back a <code>DisplayText</code> class
+             from it's Asn1Encodable form.</p>
+            
+             @param contents an <code>Asn1Encodable</code> instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.GetString">
+             Returns the stored <code>string</code> object.
+            
+             @return the stored text as a <code>string</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DistributionPoint">
+            The DistributionPoint object.
+            <pre>
+            DistributionPoint ::= Sequence {
+                 distributionPoint [0] DistributionPointName OPTIONAL,
+                 reasons           [1] ReasonFlags OPTIONAL,
+                 cRLIssuer         [2] GeneralNames OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DistributionPointName">
+            The DistributionPointName object.
+            <pre>
+            DistributionPointName ::= CHOICE {
+                fullName                 [0] GeneralNames,
+                nameRelativeToCRLIssuer  [1] RDN
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage">
+            The extendedKeyUsage object.
+            <pre>
+                 extendedKeyUsage ::= Sequence SIZE (1..MAX) OF KeyPurposeId
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage.GetAllUsages">
+            Returns all extended key usages.
+            The returned ArrayList contains DerObjectIdentifier instances.
+            @return An ArrayList with all key purposes.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.GeneralName">
+             The GeneralName object.
+             <pre>
+             GeneralName ::= CHOICE {
+                  otherName                       [0]     OtherName,
+                  rfc822Name                      [1]     IA5String,
+                  dNSName                         [2]     IA5String,
+                  x400Address                     [3]     ORAddress,
+                  directoryName                   [4]     Name,
+                  ediPartyName                    [5]     EDIPartyName,
+                  uniformResourceIdentifier       [6]     IA5String,
+                  iPAddress                       [7]     OCTET STRING,
+                  registeredID                    [8]     OBJECT IDENTIFIER}
+            
+             OtherName ::= Sequence {
+                  type-id    OBJECT IDENTIFIER,
+                  value      [0] EXPLICIT ANY DEFINED BY type-id }
+            
+             EDIPartyName ::= Sequence {
+                  nameAssigner            [0]     DirectoryString OPTIONAL,
+                  partyName               [1]     DirectoryString }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralName.#ctor(Org.BouncyCastle.Asn1.Asn1Object,System.Int32)">
+             When the subjectAltName extension contains an Internet mail address,
+             the address MUST be included as an rfc822Name. The format of an
+             rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+            
+             When the subjectAltName extension contains a domain name service
+             label, the domain name MUST be stored in the dNSName (an IA5String).
+             The name MUST be in the "preferred name syntax," as specified by RFC
+             1034 [RFC 1034].
+            
+             When the subjectAltName extension contains a URI, the name MUST be
+             stored in the uniformResourceIdentifier (an IA5String). The name MUST
+             be a non-relative URL, and MUST follow the URL syntax and encoding
+             rules specified in [RFC 1738].  The name must include both a scheme
+             (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
+             specific-part must include a fully qualified domain name or IP
+             address as the host.
+            
+             When the subjectAltName extension contains a iPAddress, the address
+             MUST be stored in the octet string in "network byte order," as
+             specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+             each octet is the LSB of the corresponding byte in the network
+             address. For IP Version 4, as specified in RFC 791, the octet string
+             MUST contain exactly four octets.  For IP Version 6, as specified in
+             RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+             1883].
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralName.#ctor(System.Int32,System.String)">
+             Create a GeneralName for the given tag from the passed in string.
+             <p>
+             This constructor can handle:
+             <ul>
+             <li>rfc822Name</li>
+             <li>iPAddress</li>
+             <li>directoryName</li>
+             <li>dNSName</li>
+             <li>uniformResourceIdentifier</li>
+             <li>registeredID</li>
+             </ul>
+             For x400Address, otherName and ediPartyName there is no common string
+             format defined.
+             </p><p>
+             Note: A directory name can be encoded in different ways into a byte
+             representation. Be aware of this if the byte representation is used for
+             comparing results.
+             </p>
+            
+             @param tag tag number
+             @param name string representation of name
+             @throws ArgumentException if the string encoding is not correct or
+                         not supported.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralNames.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName)">
+            <summary>Construct a GeneralNames object containing one GeneralName.</summary>
+            <param name="name">The name to be contained.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralNames.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.GeneralSubtree">
+             Class for containing a restriction object subtrees in NameConstraints. See
+             RFC 3280.
+            
+             <pre>
+            
+                   GeneralSubtree ::= SEQUENCE
+                   {
+                     baseName                    GeneralName,
+                     minimum         [0]     BaseDistance DEFAULT 0,
+                     maximum         [1]     BaseDistance OPTIONAL
+                   }
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.NameConstraints
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralSubtree.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             Constructor from a given details.
+            
+             According RFC 3280, the minimum and maximum fields are not used with any
+             name forms, thus minimum MUST be zero, and maximum MUST be absent.
+             <p>
+             If minimum is <code>null</code>, zero is assumed, if
+             maximum is <code>null</code>, maximum is absent.</p>
+            
+             @param baseName
+                        A restriction.
+             @param minimum
+                        Minimum
+            
+             @param maximum
+                        Maximum
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralSubtree.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+            
+             Returns:
+            
+             <pre>
+                   GeneralSubtree ::= SEQUENCE
+                   {
+                     baseName                    GeneralName,
+                     minimum         [0]     BaseDistance DEFAULT 0,
+                     maximum         [1]     BaseDistance OPTIONAL
+                   }
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Holder">
+            The Holder object.
+            <p>
+            For an v2 attribute certificate this is:
+            
+            <pre>
+                       Holder ::= SEQUENCE {
+                             baseCertificateID   [0] IssuerSerial OPTIONAL,
+                                      -- the issuer and serial number of
+                                      -- the holder's Public Key Certificate
+                             entityName          [1] GeneralNames OPTIONAL,
+                                      -- the name of the claimant or role
+                             objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+                                      -- used to directly authenticate the holder,
+                                      -- for example, an executable
+                       }
+            </pre>
+            </p>
+            <p>
+            For an v1 attribute certificate this is:
+            
+            <pre>
+                    subject CHOICE {
+                     baseCertificateID [0] IssuerSerial,
+                     -- associated with a Public Key Certificate
+                     subjectName [1] GeneralNames },
+                     -- associated with a name
+            </pre>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.Asn1TaggedObject)">
+            Constructor for a holder for an v1 attribute certificate.
+            
+            @param tagObj The ASN.1 tagged holder object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor for a holder for an v2 attribute certificate. *
+            
+            @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.IssuerSerial,System.Int32)">
+            Constructs a holder from a IssuerSerial.
+            @param baseCertificateID The IssuerSerial.
+            @param version The version of the attribute certificate. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames)">
+            Constructs a holder with an entityName for v2 attribute certificates or
+            with a subjectName for v1 attribute certificates.
+            
+            @param entityName The entity or subject name.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,System.Int32)">
+            Constructs a holder with an entityName for v2 attribute certificates or
+            with a subjectName for v1 attribute certificates.
+            
+            @param entityName The entity or subject name.
+            @param version The version of the attribute certificate. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.ObjectDigestInfo)">
+            Constructs a holder from an object digest info.
+            
+            @param objectDigestInfo The object digest info object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.ToAsn1Object">
+            The Holder object.
+            <pre>
+             Holder ::= Sequence {
+                   baseCertificateID   [0] IssuerSerial OPTIONAL,
+                            -- the issuer and serial number of
+                            -- the holder's Public Key Certificate
+                   entityName          [1] GeneralNames OPTIONAL,
+                            -- the name of the claimant or role
+                   objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+                            -- used to directly authenticate the holder,
+                            -- for example, an executable
+             }
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Holder.Version">
+            Returns 1 for v2 attribute certificates or 0 for v1 attribute
+            certificates. 
+            @return The version of the attribute certificate.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Holder.EntityName">
+            Returns the entityName for an v2 attribute certificate or the subjectName
+            for an v1 attribute certificate.
+            
+            @return The entityname or subjectname.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax">
+            Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax.ToAsn1Object">
+            
+             <pre>
+            
+              IetfAttrSyntax ::= Sequence {
+                policyAuthority [0] GeneralNames OPTIONAL,
+                values Sequence OF CHOICE {
+                  octets OCTET STRING,
+                  oid OBJECT IDENTIFIER,
+                  string UTF8String
+                }
+              }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuerSerial.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             IssuerSerial  ::=  Sequence {
+                  issuer         GeneralNames,
+                  serial         CertificateSerialNumber,
+                  issuerUid      UniqueIdentifier OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint">
+            <pre>
+            IssuingDistributionPoint ::= SEQUENCE { 
+              distributionPoint          [0] DistributionPointName OPTIONAL, 
+              onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE, 
+              onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE, 
+              onlySomeReasons            [3] ReasonFlags OPTIONAL, 
+              indirectCRL                [4] BOOLEAN DEFAULT FALSE,
+              onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.#ctor(Org.BouncyCastle.Asn1.X509.DistributionPointName,System.Boolean,System.Boolean,Org.BouncyCastle.Asn1.X509.ReasonFlags,System.Boolean,System.Boolean)">
+            Constructor from given details.
+            
+            @param distributionPoint
+                       May contain an URI as pointer to most current CRL.
+            @param onlyContainsUserCerts Covers revocation information for end certificates.
+            @param onlyContainsCACerts Covers revocation information for CA certificates.
+            
+            @param onlySomeReasons
+                       Which revocation reasons does this point cover.
+            @param indirectCRL
+                       If <code>true</code> then the CRL contains revocation
+                       information about certificates ssued by other CAs.
+            @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from Asn1Sequence
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.DistributionPoint">
+            @return Returns the distributionPoint.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.OnlySomeReasons">
+            @return Returns the onlySomeReasons.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.KeyPurposeID">
+            The KeyPurposeID object.
+            <pre>
+                KeyPurposeID ::= OBJECT IDENTIFIER
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.KeyUsage">
+             The KeyUsage object.
+             <pre>
+                id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+            
+                KeyUsage ::= BIT STRING {
+                     digitalSignature        (0),
+                     nonRepudiation          (1),
+                     keyEncipherment         (2),
+                     dataEncipherment        (3),
+                     keyAgreement            (4),
+                     keyCertSign             (5),
+                     cRLSign                 (6),
+                     encipherOnly            (7),
+                     decipherOnly            (8) }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.KeyUsage.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NameConstraints.#ctor(System.Collections.IList,System.Collections.IList)">
+             Constructor from a given details.
+            
+             <p>permitted and excluded are Vectors of GeneralSubtree objects.</p>
+            
+             @param permitted Permitted subtrees
+             @param excluded Excluded subtrees
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.NoticeReference">
+             <code>NoticeReference</code> class, used in
+             <code>CertificatePolicies</code> X509 V3 extensions
+             (in policy qualifiers).
+            
+             <pre>
+              NoticeReference ::= Sequence {
+                  organization     DisplayText,
+                  noticeNumbers    Sequence OF Integer }
+            
+             </pre>
+            
+             @see PolicyQualifierInfo
+             @see PolicyInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(System.String,System.Collections.IList)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param organization a <code>String</code> value
+             @param numbers a <code>Vector</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param organization a <code>String</code> value
+             @param noticeNumbers an <code>ASN1EncodableVector</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(Org.BouncyCastle.Asn1.X509.DisplayText,Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param organization displayText
+             @param noticeNumbers an <code>ASN1EncodableVector</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>NoticeReference</code> instance.
+             <p>Useful for reconstructing a <code>NoticeReference</code>
+             instance from its encodable/encoded form.</p>
+            
+             @param as an <code>Asn1Sequence</code> value obtained from either
+             calling @{link ToAsn1Object()} for a <code>NoticeReference</code>
+             instance or from parsing it from a Der-encoded stream.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.ToAsn1Object">
+             Describe <code>ToAsn1Object</code> method here.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo">
+            ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+            
+            <pre>
+             
+               ObjectDigestInfo ::= SEQUENCE {
+                    digestedObjectType  ENUMERATED {
+                            publicKey            (0),
+                            publicKeyCert        (1),
+                            otherObjectTypes     (2) },
+                                    -- otherObjectTypes MUST NOT
+                                    -- be used in this profile
+                    otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+                    digestAlgorithm     AlgorithmIdentifier,
+                    objectDigest        BIT STRING
+               }
+              
+            </pre>
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.PublicKey">
+            The public key is hashed.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.PublicKeyCert">
+            The public key certificate is hashed.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.OtherObjectDigest">
+            An other object is hashed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.#ctor(System.Int32,System.String,Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,System.Byte[])">
+            Constructor from given details.
+            <p>
+            If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
+            {@link #publicKey} <code>otherObjectTypeID</code> must be given,
+            otherwise it is ignored.</p>
+            
+            @param digestedObjectType The digest object type.
+            @param otherObjectTypeID The object type ID for
+                       <code>otherObjectDigest</code>.
+            @param digestAlgorithm The algorithm identifier for the hash.
+            @param objectDigest The hash value.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            <pre>
+             
+               ObjectDigestInfo ::= SEQUENCE {
+                    digestedObjectType  ENUMERATED {
+                            publicKey            (0),
+                            publicKeyCert        (1),
+                            otherObjectTypes     (2) },
+                                    -- otherObjectTypes MUST NOT
+                                    -- be used in this profile
+                    otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+                    digestAlgorithm     AlgorithmIdentifier,
+                    objectDigest        BIT STRING
+               }
+              
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyMappings">
+             PolicyMappings V3 extension, described in RFC3280.
+             <pre>
+                PolicyMappings ::= Sequence SIZE (1..MAX) OF Sequence {
+                  issuerDomainPolicy      CertPolicyId,
+                  subjectDomainPolicy     CertPolicyId }
+             </pre>
+            
+             @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyMappings.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>PolicyMappings</code> instance.
+            
+             @param seq an <code>Asn1Sequence</code> constructed as specified
+             in RFC 3280
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyMappings.#ctor(System.Collections.IDictionary)">
+             Creates a new <code>PolicyMappings</code> instance.
+            
+             @param mappings a <code>HashMap</code> value that maps
+             <code>string</code> oids
+             to other <code>string</code> oids.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyQualifierID">
+             PolicyQualifierId, used in the CertificatePolicies
+             X509V3 extension.
+            
+             <pre>
+                id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
+                id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+                id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+              PolicyQualifierId ::=
+                   OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo">
+             Policy qualifiers, used in the X509V3 CertificatePolicies
+             extension.
+            
+             <pre>
+               PolicyQualifierInfo ::= Sequence {
+                   policyQualifierId  PolicyQualifierId,
+                   qualifier          ANY DEFINED BY policyQualifierId }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Creates a new <code>PolicyQualifierInfo</code> instance.
+            
+             @param policyQualifierId a <code>PolicyQualifierId</code> value
+             @param qualifier the qualifier, defined by the above field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(System.String)">
+             Creates a new <code>PolicyQualifierInfo</code> containing a
+             cPSuri qualifier.
+            
+             @param cps the CPS (certification practice statement) uri as a
+             <code>string</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>PolicyQualifierInfo</code> instance.
+            
+             @param as <code>PolicyQualifierInfo</code> X509 structure
+             encoded as an Asn1Sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.ToAsn1Object">
+             Returns a Der-encodable representation of this instance.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PrivateKeyUsagePeriod">
+            <remarks>
+            <pre>
+            PrivateKeyUsagePeriod ::= SEQUENCE
+            {
+            notBefore       [0]     GeneralizedTime OPTIONAL,
+            notAfter        [1]     GeneralizedTime OPTIONAL }
+            </pre>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.BiometricData">
+            The BiometricData object.
+            <pre>
+            BiometricData  ::=  SEQUENCE {
+                  typeOfBiometricData  TypeOfBiometricData,
+                  hashAlgorithm        AlgorithmIdentifier,
+                  biometricDataHash    OCTET STRING,
+                  sourceDataUri        IA5String OPTIONAL  }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.Iso4217CurrencyCode">
+            The Iso4217CurrencyCode object.
+            <pre>
+            Iso4217CurrencyCode  ::=  CHOICE {
+                  alphabetic              PrintableString (SIZE 3), --Recommended
+                  numeric              INTEGER (1..999) }
+            -- Alphabetic or numeric currency code as defined in ISO 4217
+            -- It is recommended that the Alphabetic form is used
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.MonetaryValue">
+            The MonetaryValue object.
+            <pre>
+            MonetaryValue  ::=  SEQUENCE {
+                  currency              Iso4217CurrencyCode,
+                  amount               INTEGER,
+                  exponent             INTEGER }
+            -- value = amount * 10^exponent
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.QCStatement">
+            The QCStatement object.
+            <pre>
+            QCStatement ::= SEQUENCE {
+              statementId        OBJECT IDENTIFIER,
+              statementInfo      ANY DEFINED BY statementId OPTIONAL}
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.SemanticsInformation">
+             The SemanticsInformation object.
+             <pre>
+                   SemanticsInformation ::= SEQUENCE {
+                     semanticsIdentifier        OBJECT IDENTIFIER   OPTIONAL,
+                     nameRegistrationAuthorities NameRegistrationAuthorities
+                                                                     OPTIONAL }
+                     (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+                      WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+            
+                 NameRegistrationAuthorities ::=  SEQUENCE SIZE (1..MAX) OF
+                     GeneralName
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.TypeOfBiometricData">
+             The TypeOfBiometricData object.
+             <pre>
+             TypeOfBiometricData ::= CHOICE {
+               predefinedBiometricType   PredefinedBiometricType,
+               biometricDataOid          OBJECT IDENTIFIER }
+            
+             PredefinedBiometricType ::= INTEGER {
+               picture(0),handwritten-signature(1)}
+               (picture|handwritten-signature)
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ReasonFlags">
+            The ReasonFlags object.
+            <pre>
+            ReasonFlags ::= BIT STRING {
+               unused(0),
+               keyCompromise(1),
+               cACompromise(2),
+               affiliationChanged(3),
+               superseded(4),
+               cessationOfOperation(5),
+               certficateHold(6)
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ReasonFlags.#ctor(System.Int32)">
+            @param reasons - the bitwise OR of the Key Reason flags giving the
+            allowed uses for the key.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.RoleSyntax">
+             Implementation of the RoleSyntax object as specified by the RFC3281.
+            
+             <pre>
+             RoleSyntax ::= SEQUENCE {
+                             roleAuthority  [0] GeneralNames OPTIONAL,
+                             roleName       [1] GeneralName
+                       }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetInstance(System.Object)">
+            RoleSyntax factory method.
+            @param obj the object used to construct an instance of <code>
+            RoleSyntax</code>. It must be an instance of <code>RoleSyntax
+            </code> or <code>Asn1Sequence</code>.
+            @return the instance of <code>RoleSyntax</code> built from the
+            supplied object.
+            @throws java.lang.ArgumentException if the object passed
+            to the factory is not an instance of <code>RoleSyntax</code> or
+            <code>Asn1Sequence</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            Constructor.
+            @param roleAuthority the role authority of this RoleSyntax.
+            @param roleName    the role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName)">
+            Constructor. Invoking this constructor is the same as invoking
+            <code>new RoleSyntax(null, roleName)</code>.
+            @param roleName    the role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(System.String)">
+            Utility constructor. Takes a <code>string</code> argument representing
+            the role name, builds a <code>GeneralName</code> to hold the role name
+            and calls the constructor that takes a <code>GeneralName</code>.
+            @param roleName
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor that builds an instance of <code>RoleSyntax</code> by
+            extracting the encoded elements from the <code>Asn1Sequence</code>
+            object supplied.
+            @param seq    an instance of <code>Asn1Sequence</code> that holds
+            the encoded elements used to build this <code>RoleSyntax</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetRoleNameAsString">
+            Gets the role name as a <code>java.lang.string</code> object.
+            @return    the role name of this RoleSyntax represented as a
+            <code>string</code> object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetRoleAuthorityAsString">
+            Gets the role authority as a <code>string[]</code> object.
+            @return the role authority of this RoleSyntax represented as a
+            <code>string[]</code> array.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.ToAsn1Object">
+             Implementation of the method <code>ToAsn1Object</code> as
+             required by the superclass <code>ASN1Encodable</code>.
+            
+             <pre>
+             RoleSyntax ::= SEQUENCE {
+                             roleAuthority  [0] GeneralNames OPTIONAL,
+                             roleName       [1] GeneralName
+                       }
+             </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.RoleSyntax.RoleAuthority">
+            Gets the role authority of this RoleSyntax.
+            @return    an instance of <code>GeneralNames</code> holding the
+            role authority of this RoleSyntax.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.RoleSyntax.RoleName">
+            Gets the role name of this RoleSyntax.
+            @return    an instance of <code>GeneralName</code> holding the
+            role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RsaPublicKeyStructure.ToAsn1Object">
+            This outputs the key in Pkcs1v2 format.
+            <pre>
+                 RSAPublicKey ::= Sequence {
+                                     modulus Integer, -- n
+                                     publicExponent Integer, -- e
+                                 }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym">
+            Structure for a name or pseudonym.
+            
+            <pre>
+                  NameOrPseudonym ::= CHOICE {
+                	   surAndGivenName SEQUENCE {
+                	     surName DirectoryString,
+                	     givenName SEQUENCE OF DirectoryString 
+                    },
+                	   pseudonym DirectoryString 
+                  }
+            </pre>
+            
+            @see org.bouncycastle.asn1.x509.sigi.PersonalData
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString)">
+            Constructor from DERString.
+            <p/>
+            The sequence is of type NameOrPseudonym:
+            <p/>
+            <pre>
+                  NameOrPseudonym ::= CHOICE {
+                	   surAndGivenName SEQUENCE {
+                	     surName DirectoryString,
+                	     givenName SEQUENCE OF DirectoryString
+                    },
+                	   pseudonym DirectoryString
+                  }
+            </pre>
+            @param pseudonym pseudonym value to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type NameOrPseudonym:
+             <p/>
+             <pre>
+                   NameOrPseudonym ::= CHOICE {
+                 	   surAndGivenName SEQUENCE {
+                 	     surName DirectoryString,
+                 	     givenName SEQUENCE OF DirectoryString
+                     },
+                 	   pseudonym DirectoryString
+                   }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param pseudonym The pseudonym.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from a given details.
+            
+             @param surname   The surname.
+             @param givenName A sequence of directory strings making up the givenName
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   NameOrPseudonym ::= CHOICE {
+                 	   surAndGivenName SEQUENCE {
+                 	     surName DirectoryString,
+                 	     givenName SEQUENCE OF DirectoryString
+                     },
+                 	   pseudonym DirectoryString
+                   }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.PersonalData">
+             Contains personal data for the otherName field in the subjectAltNames
+             extension.
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
+             @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type NameOrPseudonym:
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.#ctor(Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Asn1.DerGeneralizedTime,Org.BouncyCastle.Asn1.X500.DirectoryString,System.String,Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from a given details.
+            
+             @param nameOrPseudonym  Name or pseudonym.
+             @param nameDistinguisher Name distinguisher.
+             @param dateOfBirth      Date of birth.
+             @param placeOfBirth     Place of birth.
+             @param gender           Gender.
+             @param postalAddress    Postal Address.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers">
+            Object Identifiers of SigI specifciation (German Signature Law
+            Interoperability specification).
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIKP">
+            Key purpose IDs for German SigI (Signature Interoperability
+            Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigICP">
+            Certificate policy IDs for German SigI (Signature Interoperability
+            Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigION">
+            Other Name IDs for German SigI (Signature Interoperability Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIKPDirectoryService">
+            To be used for for the generation of directory service certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIONPersonalData">
+            ID for PersonalData
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigICPSigConform">
+            Certificate is conform to german signature law.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes">
+             This extension may contain further X.500 attributes of the subject. See also
+             RFC 3039.
+            
+             <pre>
+                 SubjectDirectoryAttributes ::= Attributes
+                 Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                 Attribute ::= SEQUENCE
+                 {
+                   type AttributeType
+                   values SET OF AttributeValue
+                 }
+            
+                 AttributeType ::= OBJECT IDENTIFIER
+                 AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+            
+             The sequence is of type SubjectDirectoryAttributes:
+            
+             <pre>
+                  SubjectDirectoryAttributes ::= Attributes
+                  Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                  Attribute ::= SEQUENCE
+                  {
+                    type AttributeType
+                    values SET OF AttributeValue
+                  }
+            
+                  AttributeType ::= OBJECT IDENTIFIER
+                  AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @param seq
+                        The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.#ctor(System.Collections.IList)">
+             Constructor from an ArrayList of attributes.
+            
+             The ArrayList consists of attributes of type {@link Attribute Attribute}
+            
+             @param attributes The attributes.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+            
+             Returns:
+            
+             <pre>
+                  SubjectDirectoryAttributes ::= Attributes
+                  Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                  Attribute ::= SEQUENCE
+                  {
+                    type AttributeType
+                    values SET OF AttributeValue
+                  }
+            
+                  AttributeType ::= OBJECT IDENTIFIER
+                  AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.Attributes">
+            @return Returns the attributes.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier">
+            The SubjectKeyIdentifier object.
+            <pre>
+            SubjectKeyIdentifier::= OCTET STRING
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+             Calculates the keyIdentifier using a SHA1 hash over the BIT STRING
+             from SubjectPublicKeyInfo as defined in RFC3280.
+            
+             @param spki the subject public key info.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.CreateSha1KeyIdentifier(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Return a RFC 3280 type 1 key identifier. As in:
+            <pre>
+            (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+            value of the BIT STRING subjectPublicKey (excluding the tag,
+            length, and number of unused bits).
+            </pre>
+            @param keyInfo the key info object containing the subjectPublicKey field.
+            @return the key identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.CreateTruncatedSha1KeyIdentifier(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Return a RFC 3280 type 2 key identifier. As in:
+            <pre>
+            (2) The keyIdentifier is composed of a four bit type field with
+            the value 0100 followed by the least significant 60 bits of the
+            SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+            </pre>
+            @param keyInfo the key info object containing the subjectPublicKey field.
+            @return the key identifier.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo">
+            The object that contains the public key stored in a certficate.
+            <p>
+            The GetEncoded() method in the public keys in the JCE produces a DER
+            encoded one of these.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.GetPublicKey">
+             for when the public key is an encoded object - if the bitstring
+             can't be decoded this routine raises an IOException.
+            
+             @exception IOException - if the bit string doesn't represent a Der
+             encoded object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SubjectPublicKeyInfo ::= Sequence {
+                                     algorithm AlgorithmIdentifier,
+                                     publicKey BIT STRING }
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.PublicKeyData">
+            for when the public key is raw bits...
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Target">
+            Target structure used in target information extension for attribute
+            certificates from RFC 3281.
+            
+            <pre>
+                Target  ::= CHOICE {
+                  targetName          [0] GeneralName,
+                  targetGroup         [1] GeneralName,
+                  targetCert          [2] TargetCert
+                }
+            </pre>
+            
+            <p>
+            The targetCert field is currently not supported and must not be used
+            according to RFC 3281.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.GetInstance(System.Object)">
+            Creates an instance of a Target from the given object.
+            <p>
+            <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
+            
+            @param obj The object.
+            @return A Target instance.
+            @throws ArgumentException if the given object cannot be
+                        interpreted as Target.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.#ctor(Org.BouncyCastle.Asn1.Asn1TaggedObject)">
+            Constructor from Asn1TaggedObject.
+            
+            @param tagObj The tagged object.
+            @throws ArgumentException if the encoding is wrong.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.#ctor(Org.BouncyCastle.Asn1.X509.Target.Choice,Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Constructor from given details.
+             <p>
+             Exactly one of the parameters must be not <code>null</code>.</p>
+            
+             @param type the choice type to apply to the name.
+             @param name the general name.
+             @throws ArgumentException if type is invalid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                Target  ::= CHOICE {
+                  targetName          [0] GeneralName,
+                  targetGroup         [1] GeneralName,
+                  targetCert          [2] TargetCert
+                }
+            </pre>
+            
+            @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Target.TargetGroup">
+            @return Returns the targetGroup.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Target.TargetName">
+            @return Returns the targetName.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TargetInformation">
+            Target information extension for attributes certificates according to RFC
+            3281.
+            
+            <pre>
+                      SEQUENCE OF Targets
+            </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.GetInstance(System.Object)">
+            Creates an instance of a TargetInformation from the given object.
+            <p>
+            <code>obj</code> can be a TargetInformation or a {@link Asn1Sequence}</p>
+            
+            @param obj The object.
+            @return A TargetInformation instance.
+            @throws ArgumentException if the given object cannot be interpreted as TargetInformation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from a Asn1Sequence.
+            
+            @param seq The Asn1Sequence.
+            @throws ArgumentException if the sequence does not contain
+                        correctly encoded Targets elements.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.GetTargetsObjects">
+            Returns the targets in this target information extension.
+            <p>
+            The ArrayList is cloned before it is returned.</p>
+            
+            @return Returns the targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.X509.Targets)">
+            Constructs a target information from a single targets element. 
+            According to RFC 3281 only one targets element must be produced.
+            
+            @param targets A Targets instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.X509.Target[])">
+             According to RFC 3281 only one targets element must be produced. If
+             multiple targets are given they must be merged in
+             into one targets element.
+            
+             @param targets An array with {@link Targets}.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                     SEQUENCE OF Targets
+            </pre>
+            
+            <p>
+            According to RFC 3281 only one targets element must be produced. If
+            multiple targets are given in the constructor they are merged into one
+            targets element. If this was produced from a
+            {@link Org.BouncyCastle.Asn1.Asn1Sequence} the encoding is kept.</p>
+            
+            @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Targets">
+            Targets structure used in target information extension for attribute
+            certificates from RFC 3281.
+            
+            <pre>
+                       Targets ::= SEQUENCE OF Target
+                      
+                       Target  ::= CHOICE {
+                         targetName          [0] GeneralName,
+                         targetGroup         [1] GeneralName,
+                         targetCert          [2] TargetCert
+                       }
+                      
+                       TargetCert  ::= SEQUENCE {
+                         targetCertificate    IssuerSerial,
+                         targetName           GeneralName OPTIONAL,
+                         certDigestInfo       ObjectDigestInfo OPTIONAL
+                       }
+            </pre>
+            
+            @see org.bouncycastle.asn1.x509.Target
+            @see org.bouncycastle.asn1.x509.TargetInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.GetInstance(System.Object)">
+            Creates an instance of a Targets from the given object.
+            <p>
+            <code>obj</code> can be a Targets or a {@link Asn1Sequence}</p>
+            
+            @param obj The object.
+            @return A Targets instance.
+            @throws ArgumentException if the given object cannot be interpreted as Target.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from Asn1Sequence.
+            
+            @param targets The ASN.1 SEQUENCE.
+            @throws ArgumentException if the contents of the sequence are
+                        invalid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.#ctor(Org.BouncyCastle.Asn1.X509.Target[])">
+            Constructor from given targets.
+            <p>
+            The ArrayList is copied.</p>
+            
+            @param targets An <code>ArrayList</code> of {@link Target}s.
+            @see Target
+            @throws ArgumentException if the ArrayList contains not only Targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.GetTargets">
+            Returns the targets in an <code>ArrayList</code>.
+            <p>
+            The ArrayList is cloned before it is returned.</p>
+            
+            @return Returns the targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                       Targets ::= SEQUENCE OF Target
+            </pre>
+            
+            @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TbsCertificateStructure">
+            The TbsCertificate object.
+            <pre>
+            TbsCertificate ::= Sequence {
+                 version          [ 0 ]  Version DEFAULT v1(0),
+                 serialNumber            CertificateSerialNumber,
+                 signature               AlgorithmIdentifier,
+                 issuer                  Name,
+                 validity                Validity,
+                 subject                 Name,
+                 subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                 issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                 subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                 extensions        [ 3 ] Extensions OPTIONAL
+                 }
+            </pre>
+            <p>
+            Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+            will parse them, but you really shouldn't be creating new ones.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TbsCertificateList">
+            PKIX RFC-2459 - TbsCertList object.
+            <pre>
+            TbsCertList  ::=  Sequence  {
+                 version                 Version OPTIONAL,
+                                              -- if present, shall be v2
+                 signature               AlgorithmIdentifier,
+                 issuer                  Name,
+                 thisUpdate              Time,
+                 nextUpdate              Time OPTIONAL,
+                 revokedCertificates     Sequence OF Sequence  {
+                      userCertificate         CertificateSerialNumber,
+                      revocationDate          Time,
+                      crlEntryExtensions      Extensions OPTIONAL
+                                                    -- if present, shall be v2
+                                           }  OPTIONAL,
+                 crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+                                                    -- if present, shall be v2
+                                           }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.#ctor(System.DateTime)">
+            creates a time object from a given date - if the date is between 1950
+            and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+            is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.ToDateTime">
+            <summary>
+            Return our time as DateTime.
+            </summary>
+            <returns>A date time.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Time ::= CHOICE {
+                        utcTime        UTCTime,
+                        generalTime    GeneralizedTime }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.UserNotice">
+             <code>UserNotice</code> class, used in
+             <code>CertificatePolicies</code> X509 extensions (in policy
+             qualifiers).
+             <pre>
+             UserNotice ::= Sequence {
+                  noticeRef        NoticeReference OPTIONAL,
+                  explicitText     DisplayText OPTIONAL}
+            
+             </pre>
+            
+             @see PolicyQualifierId
+             @see PolicyInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.X509.NoticeReference,Org.BouncyCastle.Asn1.X509.DisplayText)">
+             Creates a new <code>UserNotice</code> instance.
+            
+             @param noticeRef a <code>NoticeReference</code> value
+             @param explicitText a <code>DisplayText</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.X509.NoticeReference,System.String)">
+             Creates a new <code>UserNotice</code> instance.
+            
+             @param noticeRef a <code>NoticeReference</code> value
+             @param str the explicitText field as a string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>UserNotice</code> instance.
+             <p>Useful from reconstructing a <code>UserNotice</code> instance
+             from its encodable/encoded form.
+            
+             @param as an <code>ASN1Sequence</code> value obtained from either
+             calling @{link toASN1Object()} for a <code>UserNotice</code>
+             instance or from parsing it from a DER-encoded stream.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V1TbsCertificateGenerator">
+             Generator for Version 1 TbsCertificateStructures.
+             <pre>
+             TbsCertificate ::= Sequence {
+                  version          [ 0 ]  Version DEFAULT v1(0),
+                  serialNumber            CertificateSerialNumber,
+                  signature               AlgorithmIdentifier,
+                  issuer                  Name,
+                  validity                Validity,
+                  subject                 Name,
+                  subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                  }
+             </pre>
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V2AttributeCertificateInfoGenerator">
+             Generator for Version 2 AttributeCertificateInfo
+             <pre>
+             AttributeCertificateInfo ::= Sequence {
+                   version              AttCertVersion -- version is v2,
+                   holder               Holder,
+                   issuer               AttCertIssuer,
+                   signature            AlgorithmIdentifier,
+                   serialNumber         CertificateSerialNumber,
+                   attrCertValidityPeriod   AttCertValidityPeriod,
+                   attributes           Sequence OF Attr,
+                   issuerUniqueID       UniqueIdentifier OPTIONAL,
+                   extensions           Extensions OPTIONAL
+             }
+             </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.V2AttributeCertificateInfoGenerator.AddAttribute(Org.BouncyCastle.Asn1.X509.AttributeX509)">
+            @param attribute
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.V2Form.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             V2Form ::= Sequence {
+                  issuerName            GeneralNames  OPTIONAL,
+                  baseCertificateID     [0] IssuerSerial  OPTIONAL,
+                  objectDigestInfo      [1] ObjectDigestInfo  OPTIONAL
+                    -- issuerName MUST be present in this profile
+                    -- baseCertificateID and objectDigestInfo MUST NOT
+                    -- be present in this profile
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V2TbsCertListGenerator">
+             Generator for Version 2 TbsCertList structures.
+             <pre>
+              TbsCertList  ::=  Sequence  {
+                   version                 Version OPTIONAL,
+                                                -- if present, shall be v2
+                   signature               AlgorithmIdentifier,
+                   issuer                  Name,
+                   thisUpdate              Time,
+                   nextUpdate              Time OPTIONAL,
+                   revokedCertificates     Sequence OF Sequence  {
+                        userCertificate         CertificateSerialNumber,
+                        revocationDate          Time,
+                        crlEntryExtensions      Extensions OPTIONAL
+                                                      -- if present, shall be v2
+                                             }  OPTIONAL,
+                   crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+                                                      -- if present, shall be v2
+                                             }
+             </pre>
+            
+             <b>Note: This class may be subject to change</b>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V3TbsCertificateGenerator">
+             Generator for Version 3 TbsCertificateStructures.
+             <pre>
+             TbsCertificate ::= Sequence {
+                  version          [ 0 ]  Version DEFAULT v1(0),
+                  serialNumber            CertificateSerialNumber,
+                  signature               AlgorithmIdentifier,
+                  issuer                  Name,
+                  validity                Validity,
+                  subject                 Name,
+                  subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                  issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                  subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                  extensions        [ 3 ] Extensions OPTIONAL
+                  }
+             </pre>
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509CertificateStructure">
+            an X509Certificate structure.
+            <pre>
+             Certificate ::= Sequence {
+                 tbsCertificate          TbsCertificate,
+                 signatureAlgorithm      AlgorithmIdentifier,
+                 signature               BIT STRING
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509DefaultEntryConverter">
+            The default converter for X509 DN entries when going from their
+            string value to ASN.1 strings.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter">
+                 * It turns out that the number of standard ways the fields in a DN should be
+                 * encoded into their ASN.1 counterparts is rapidly approaching the
+                 * number of machines on the internet. By default the X509Name class
+                 * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+                 * <p>
+                 * An example of an encoder look like below:
+                 * <pre>
+                 * public class X509DirEntryConverter
+                 *     : X509NameEntryConverter
+                 * {
+                 *     public Asn1Object GetConvertedValue(
+                 *         DerObjectIdentifier  oid,
+                 *         string               value)
+                 *     {
+                 *         if (str.Length() != 0 && str.charAt(0) == '#')
+                 *         {
+                 *             return ConvertHexEncoded(str, 1);
+                 *         }
+                 *         if (oid.Equals(EmailAddress))
+                 *         {
+                 *             return new DerIA5String(str);
+                 *         }
+                 *         else if (CanBePrintable(str))
+                 *         {
+                 *             return new DerPrintableString(str);
+                 *         }
+                 *         else if (CanBeUTF8(str))
+                 *         {
+                 *             return new DerUtf8String(str);
+                 *         }
+                 *         else
+                 *         {
+                 *             return new DerBmpString(str);
+                 *         }
+                 *     }
+                 * }
+            	 * </pre>
+            	 * </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.ConvertHexEncoded(System.String,System.Int32)">
+             Convert an inline encoded hex string rendition of an ASN.1
+             object back into its corresponding ASN.1 object.
+            
+             @param str the hex encoded object
+             @param off the index at which the encoding starts
+             @return the decoded object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.CanBePrintable(System.String)">
+            return true if the passed in string can be represented without
+            loss as a PrintableString, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.GetConvertedValue(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String)">
+             Convert the passed in string value into the appropriate ASN.1
+             encoded object.
+            
+             @param oid the oid associated with the value in the DN.
+             @param value the value of the particular DN component.
+             @return the ASN.1 equivalent for the value.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509DefaultEntryConverter.GetConvertedValue(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String)">
+             Apply default conversion for the given value depending on the oid
+             and the character range of the value.
+            
+             @param oid the object identifier for the DN entry
+             @param value the value associated with it
+             @return the ASN.1 equivalent for the string value.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509Extension">
+            an object for the elements in the X.509 V3 extension block.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extension.ConvertValueToObject(Org.BouncyCastle.Asn1.X509.X509Extension)">
+            <sumary>Convert the value of the passed in extension to an object.</sumary>
+            <param name="ext">The extension to parse.</param>
+            <returns>The object the value string contains.</returns>
+            <exception cref="T:System.ArgumentException">If conversion is not possible.</exception>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectDirectoryAttributes">
+            Subject Directory Attributes
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier">
+            Subject Key Identifier
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage">
+            Key Usage
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PrivateKeyUsagePeriod">
+            Private Key Usage Period
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName">
+            Subject Alternative Name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.IssuerAlternativeName">
+            Issuer Alternative Name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints">
+            Basic Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CrlNumber">
+            CRL Number
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.ReasonCode">
+            Reason code
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InstructionCode">
+            Hold Instruction Code
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InvalidityDate">
+            Invalidity Date
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.DeltaCrlIndicator">
+            Delta CRL indicator
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.IssuingDistributionPoint">
+            Issuing Distribution Point
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CertificateIssuer">
+            Certificate Issuer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.NameConstraints">
+            Name Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CrlDistributionPoints">
+            CRL Distribution Points
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CertificatePolicies">
+            Certificate Policies
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PolicyMappings">
+            Policy Mappings
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier">
+            Authority Key Identifier
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PolicyConstraints">
+            Policy Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage">
+            Extended Key Usage
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.FreshestCrl">
+            Freshest CRL
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InhibitAnyPolicy">
+            Inhibit Any Policy
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityInfoAccess">
+            Authority Info Access
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectInfoAccess">
+            Subject Info Access
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.LogoType">
+            Logo Type
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.BiometricInfo">
+            BiometricInfo
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.QCStatements">
+            QCStatements
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuditIdentity">
+            Audit identity extension in attribute certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.NoRevAvail">
+            NoRevAvail extension in attribute certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.TargetInformation">
+            TargetInformation extension in attribute certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+            
+             the extensions are a list of constructed sequences, either with (Oid, OctetString) or (Oid, Boolean, OctetString)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IDictionary)">
+            constructor from a table of extensions.
+            <p>
+            it's is assumed the table contains Oid/string pairs.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IList,System.Collections.IDictionary)">
+            Constructor from a table of extensions with ordering.
+            <p>
+            It's is assumed the table contains Oid/string pairs.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IList,System.Collections.IList)">
+             Constructor from two vectors
+            
+             @param objectIDs an ArrayList of the object identifiers.
+             @param values an ArrayList of the extension values.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.GetExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the extension represented by the object identifier
+             passed in.
+            
+             @return the extension if it's present, null otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.ToAsn1Object">
+             <pre>
+                 Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
+            
+                 Extension         ::=   SEQUENCE {
+                    extnId            EXTENSION.&id ({ExtensionSet}),
+                    critical          BOOLEAN DEFAULT FALSE,
+                    extnValue         OCTET STRING }
+             </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509Extensions.ExtensionOids">
+            return an Enumeration of the extension field's object ids.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator">
+            <remarks>Generator for X.509 extensions</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.Reset">
+            <summary>Reset the generator</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add an extension with the given oid and the passed in value to be included
+            in the OCTET STRING associated with the extension.
+            </summary>
+            <param name="oid">OID for the extension.</param>
+            <param name="critical">True if critical, false otherwise.</param>
+            <param name="extValue">The ASN.1 object to be included in the extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension with the given oid and the passed in byte array to be wrapped
+            in the OCTET STRING associated with the extension.
+            </summary>
+            <param name="oid">OID for the extension.</param>
+            <param name="critical">True if critical, false otherwise.</param>
+            <param name="extValue">The byte array to be wrapped.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.Generate">
+            <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
+            <returns>An <c>X509Extensions</c> object</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.IsEmpty">
+            <summary>Return true if there are no extension present in this generator.</summary>
+            <returns>True if empty, false otherwise</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509Name">
+             <pre>
+                 RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+            
+                 RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+            
+                 AttributeTypeAndValue ::= SEQUENCE {
+                                               type  OBJECT IDENTIFIER,
+                                               value ANY }
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.C">
+            country code - StringType(SIZE(2))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.O">
+            organization - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.OU">
+            organizational unit name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.T">
+            Title
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CN">
+            common name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Street">
+            street - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.SerialNumber">
+            device serial number name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.L">
+            locality name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.ST">
+            state, or province name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Surname">
+            Naming attributes of type X520name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.BusinessCategory">
+            businessCategory - DirectoryString(SIZE(1..128)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PostalCode">
+            postalCode - DirectoryString(SIZE(1..40)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DnQualifier">
+            dnQualifier - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Pseudonym">
+            RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DateOfBirth">
+            RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PlaceOfBirth">
+            RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Gender">
+            RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CountryOfCitizenship">
+            RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+            codes only
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CountryOfResidence">
+            RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+            codes only
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.NameAtBirth">
+            ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PostalAddress">
+            RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+            DirectoryString(SIZE(1..30))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DmdName">
+            RFC 2256 dmdName
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.TelephoneNumber">
+            id-at-telephoneNumber
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Name">
+            id-at-name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.EmailAddress">
+            Email address (RSA PKCS#9 extension) - IA5String.
+            <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.</p>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.UnstructuredName">
+            more from PKCS#9
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.E">
+            email address in Verisign certificates
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.UID">
+            LDAP User id.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DefaultSymbols">
+            default look up table translating OID values into their common symbols following
+            the convention in RFC 2253 with a few extras
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.RFC2253Symbols">
+            look up table translating OID values into their common symbols following the convention in RFC 2253
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.RFC1779Symbols">
+             look up table translating OID values into their common symbols following the convention in RFC 1779
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DefaultLookup">
+            look up table translating common symbols into their OIDS.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return a X509Name based on the passed in tagged object.
+            
+             @param obj tag object holding name.
+             @param explicitly true if explicitly tagged false otherwise.
+             @return the X509Name
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence
+            
+             the principal will be a list of constructed sets, each containing an (OID, string) pair.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IDictionary)">
+            Constructor from a table of attributes with ordering.
+            <p>
+            it's is assumed the table contains OID/string pairs, and the contents
+            of the table are copied into an internal table as part of the
+            construction process. The ordering ArrayList should contain the OIDs
+            in the order they are meant to be encoded or printed in ToString.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IDictionary,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Constructor from a table of attributes with ordering.
+            <p>
+            it's is assumed the table contains OID/string pairs, and the contents
+            of the table are copied into an internal table as part of the
+            construction process. The ordering ArrayList should contain the OIDs
+            in the order they are meant to be encoded or printed in ToString.</p>
+            <p>
+            The passed in converter will be used to convert the strings into their
+            ASN.1 counterparts.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IList)">
+            Takes two vectors one of the oids and the other of the values.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IList,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes two vectors one of the oids and the other of the values.
+            <p>
+            The passed in converter will be used to convert the strings into their
+            ASN.1 counterparts.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes with each
+            string value being converted to its associated ASN.1 type using the passed
+            in converter.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. If reverse
+            is true, create the encoded version of the sequence starting from the
+            last element in the string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes with each
+            string value being converted to its associated ASN.1 type using the passed
+            in converter. If reverse is true the ASN.1 sequence representing the DN will
+            be built by starting at the end of the string, rather than the start.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.Collections.IDictionary,System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. lookUp
+            should provide a table of lookups, indexed by lowercase only strings and
+            yielding a DerObjectIdentifier, other than that OID. and numeric oids
+            will be processed automatically.
+            <br/>
+            If reverse is true, create the encoded version of the sequence
+            starting from the last element in the string.
+            @param reverse true if we should start scanning from the end (RFC 2553).
+            @param lookUp table of names and their oids.
+            @param dirName the X.500 string to be parsed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.Collections.IDictionary,System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. lookUp
+            should provide a table of lookups, indexed by lowercase only strings and
+            yielding a DerObjectIdentifier, other than that OID. and numeric oids
+            will be processed automatically. The passed in converter is used to convert the
+            string values to the right of each equals sign to their ASN.1 counterparts.
+            <br/>
+            @param reverse true if we should start scanning from the end, false otherwise.
+            @param lookUp table of names and oids.
+            @param dirName the string dirName
+            @param converter the converter to convert string values into their ASN.1 equivalents
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetOidList">
+            return an IList of the oids in the name, in the order they were found.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetValueList">
+            return an IList of the values found in the name, in the order they
+            were found.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetValueList(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return an IList of the values found in the name, in the order they
+            were found, with the DN label corresponding to passed in oid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.Equivalent(Org.BouncyCastle.Asn1.X509.X509Name,System.Boolean)">
+            <param name="other">The X509Name object to test equivalency against.</param>
+            <param name="inOrder">If true, the order of elements must be the same,
+            as well as the values associated with each element.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.Equivalent(Org.BouncyCastle.Asn1.X509.X509Name)">
+            test for equivalence - note: case is ignored.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.ToString(System.Boolean,System.Collections.IDictionary)">
+             convert the structure to a string - if reverse is true the
+             oids and values are listed out starting with the last element
+             in the sequence (ala RFC 2253), otherwise the string will begin
+             with the first element of the structure. If no string definition
+             for the oid is found in oidSymbols the string value of the oid is
+             added. Two standard symbol tables are provided DefaultSymbols, and
+             RFC2253Symbols as part of this class.
+            
+             @param reverse if true start at the end of the sequence and work back.
+             @param oidSymbols look up table strings for oids.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509Name.DefaultReverse">
+            determines whether or not strings should be processed and printed
+            from back to front.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509NameTokenizer">
+            class for breaking up an X500 Name into it's component tokens, ala
+            java.util.StringTokenizer. We need this class as some of the
+            lightweight Java environment don't support classes like
+            StringTokenizer.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.ECNamedCurveTable">
+            A general class that reads all X9.62 style EC curve tables.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.ECNamedCurveTable.GetByName(System.String)">
+             return a X9ECParameters object representing the passed in named
+             curve. The routine returns null if the curve is not present.
+            
+             @param name the name of the curve requested
+             @return an X9ECParameters object or null if the curve is not available.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.ECNamedCurveTable.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.ECNamedCurveTable.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return a X9ECParameters object representing the passed in named
+             curve.
+            
+             @param oid the object id of the curve requested
+             @return an X9ECParameters object or null if the curve is not available.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X9.ECNamedCurveTable.Names">
+             return an enumeration of the names of the available curves.
+            
+             @return an enumeration of the names of the available curves.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.KeySpecificInfo">
+            ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+            RFC 2631, or X9.42, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.KeySpecificInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             KeySpecificInfo ::= Sequence {
+                 algorithm OBJECT IDENTIFIER,
+                 counter OCTET STRING SIZE (4..4)
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.OtherInfo">
+            ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+            RFC 2631, or X9.42, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.OtherInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             OtherInfo ::= Sequence {
+                 keyInfo KeySpecificInfo,
+                 partyAInfo [0] OCTET STRING OPTIONAL,
+                 suppPubInfo [2] OCTET STRING
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X962NamedCurves">
+            table of the current named curves defined in X.962 EC-DSA.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X9.X962NamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962Parameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Parameters ::= CHOICE {
+               ecParameters ECParameters,
+               namedCurve   CURVES.&id({CurveNames}),
+               implicitlyCA Null
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9Curve">
+            ASN.1 def for Elliptic-Curve Curve structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9Curve.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             Curve ::= Sequence {
+                 a               FieldElement,
+                 b               FieldElement,
+                 seed            BIT STRING      OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9ECParameters">
+            ASN.1 def for Elliptic-Curve ECParameters structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9ECParameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             ECParameters ::= Sequence {
+                 version         Integer { ecpVer1(1) } (ecpVer1),
+                 fieldID         FieldID {{FieldTypes}},
+                 curve           X9Curve,
+                 base            X9ECPoint,
+                 order           Integer,
+                 cofactor        Integer OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9ECPoint">
+            class for describing an ECPoint as a Der object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9ECPoint.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             ECPoint ::= OCTET STRING
+            </pre>
+            <p>
+            Octet string produced using ECPoint.GetEncoded().</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9FieldElement">
+            Class for processing an ECFieldElement as a DER object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldElement.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             FieldElement ::= OCTET STRING
+            </pre>
+            <p>
+            <ol>
+            <li> if <i>q</i> is an odd prime then the field element is
+            processed as an Integer and converted to an octet string
+            according to x 9.62 4.3.1.</li>
+            <li> if <i>q</i> is 2<sup>m</sup> then the bit string
+            contained in the field element is converted into an octet
+            string with the same ordering padded at the front if necessary.
+            </li>
+            </ol>
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9FieldID">
+            ASN.1 def for Elliptic-Curve Field ID structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.#ctor(Org.BouncyCastle.Math.BigInteger)">
+            Constructor for elliptic curves over prime fields
+            <code>F<sub>2</sub></code>.
+            @param primeP The prime <code>p</code> defining the prime field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.#ctor(System.Int32,System.Int32)">
+            Constructor for elliptic curves over binary fields
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.#ctor(System.Int32,System.Int32,System.Int32,System.Int32)">
+            Constructor for elliptic curves over binary fields
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>..
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.ToAsn1Object">
+            Produce a Der encoding of the following structure.
+            <pre>
+             FieldID ::= Sequence {
+                 fieldType       FIELD-ID.&id({IOSet}),
+                 parameters      FIELD-ID.&Type({IOSet}{@fieldType})
+             }
+            </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.IdDsaWithSha1">
+            id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
+                  us(840) x9-57 (10040) x9cm(4) 3 }
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.X9x63Scheme">
+            X9.63
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.ansi_x9_42">
+            X9.42
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ArmoredInputStream">
+            reader for Base64 armored objects - read the headers and then start returning
+            bytes when the data is reached. An IOException is thrown if the CRC check
+            fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.Decode(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32[])">
+             decode the base 64 encoded input data.
+            
+             @return the offset the data starts in out.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.#ctor(System.IO.Stream)">
+             Create a stream for reading a PGP armoured message, parsing up to a header
+             and then reading the data that follows.
+            
+             @param input
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.#ctor(System.IO.Stream,System.Boolean)">
+             Create an armoured input stream which will assume the data starts
+             straight away, or parse for headers first depending on the value of
+             hasHeaders.
+            
+             @param input
+             @param hasHeaders true if headers are to be looked for, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.IsClearText">
+            @return true if we are inside the clear text section of a PGP
+            signed message.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.IsEndOfStream">
+            @return true if the stream is actually at end of file.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.GetArmorHeaderLine">
+            Return the armor header line (if there is one)
+            @return the armor header line, null if none present.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.GetArmorHeaders">
+            Return the armor headers (the lines after the armor header line),
+            @return an array of armor headers, null if there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ArmoredOutputStream">
+            Basic output stream.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.Encode(System.IO.Stream,System.Int32[],System.Int32)">
+            encode the input data producing a base 64 encoded byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.SetHeader(System.String,System.String)">
+             Set an additional header entry.
+            
+             @param name the name of the header entry.
+             @param v the value of the header entry.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.ResetHeaders">
+            Reset the headers to only contain a Version string.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.BeginClearText(Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            Start a clear text signed message.
+            @param hashAlgorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.Dispose(System.Boolean)">
+            <b>Note</b>: close does nor close the underlying stream. So it is possible to write
+            multiple objects using armoring to a single stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Attr.ImageAttrib">
+            <remarks>Basic type for a image attribute packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacket">
+            Basic type for a user attribute sub-packet.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.UserAttributeSubpacket.GetData">
+            return the generic data making up the packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgInputStream">
+            <remarks>Reader for PGP objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgInputStream.NextPacketTag">
+            <summary>Returns the next packet tag in the stream.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgInputStream.PartialInputStream">
+            <summary>
+            A stream that overlays our input stream, allowing the user to only read a segment of it.
+            NB: dataLength will be negative if the segment length is in the upper range above 2**31.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgObject">
+            <remarks>Base class for a PGP object.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgOutputStream">
+            <remarks>Basic output stream.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream)">
+            <summary>Create a stream representing a general packet.</summary>
+            <param name="outStr">Output stream to write to.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag)">
+            <summary>Create a stream representing an old style partial object.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">The packet tag for the object.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Int64,System.Boolean)">
+            <summary>Create a stream representing a general packet.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="length">Size of chunks making up the packet.</param>
+            <param name="oldFormat">If true, the header is written out in old format.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Int64)">
+            <summary>Create a new style partial input stream buffered into chunks.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="length">Size of chunks making up the packet.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Byte[])">
+            <summary>Create a new style partial input stream buffered into chunks.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="buffer">Buffer to use for collecting chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.Flush">
+            <summary>Flush the underlying stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.Finish">
+            <summary>Finish writing out the current packet without closing the underlying stream.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.CompressedDataPacket">
+            <remarks>Generic compressed data object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.InputStreamPacket.GetInputStream">
+            <summary>Note: you can only read from this once...</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.CompressedDataPacket.Algorithm">
+            <summary>The algorithm tag value.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.CompressionAlgorithmTag">
+            <remarks>Basic tags for compression algorithms.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ContainedPacket">
+            <remarks>Basic type for a PGP packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey">
+            <remarks>Base class for a DSA public key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.IBcpgKey">
+            <remarks>Base interface for a PGP key.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.IBcpgKey.Format">
+            <summary>
+            The base format for this key - in the case of the symmetric keys it will generally
+            be raw indicating that the key is just a straight byte representation, for an asymmetric
+            key the format will be PGP, indicating the key is a string of MPIs encoded in PGP format.
+            </summary>
+            <returns>"RAW" or "PGP".</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            <param name="bcpgIn">The stream to read the packet from.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey">
+            <remarks>Base class for a DSA secret key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            @param in
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.X">
+            @return x
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey">
+            <remarks>Base class for an ElGamal public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey">
+            <remarks>Base class for an ElGamal secret key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            @param in
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.#ctor(Org.BouncyCastle.Math.BigInteger)">
+            @param x
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ExperimentalPacket">
+            <remarks>Basic packet for an experimental packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.HashAlgorithmTag">
+            <remarks>Basic tags for hash algorithms.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.LiteralDataPacket">
+            <remarks>Generic literal data packet.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.LiteralDataPacket.Format">
+            <summary>The format tag value.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.LiteralDataPacket.ModificationTime">
+            <summary>The modification time of the file in milli-seconds (since Jan 1, 1970 UTC)</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.MarkerPacket">
+            <remarks>Basic type for a marker packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ModDetectionCodePacket">
+            <remarks>Basic packet for a modification detection code packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.MPInteger">
+            <remarks>A multiple precision integer</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OnePassSignaturePacket">
+            <remarks>Generic signature object</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OnePassSignaturePacket.KeyAlgorithm">
+            <summary>The encryption algorithm tag.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OnePassSignaturePacket.HashAlgorithm">
+            <summary>The hash algorithm tag.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PacketTag">
+            <remarks>Basic PGP packet tag types.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag">
+            <remarks>Public Key Algorithm tag numbers.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyEncSessionPacket">
+            <remarks>Basic packet for a PGP public key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyPacket">
+            <remarks>Basic packet for a PGP public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.PublicKeyPacket.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.DateTime,Org.BouncyCastle.Bcpg.IBcpgKey)">
+            <summary>Construct a version 4 public key packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicSubkeyPacket">
+            <remarks>Basic packet for a PGP public subkey</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.PublicSubkeyPacket.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.DateTime,Org.BouncyCastle.Bcpg.IBcpgKey)">
+            <summary>Construct a version 4 public subkey packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey">
+            <remarks>Base class for an RSA public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            <summary>Construct an RSA public key from the passed in stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            <param name="n">The modulus.</param>
+            <param name="e">The public exponent.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey">
+            <remarks>Base class for an RSA secret (or priate) key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.S2k">
+            <remarks>The string to key specifier class.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.S2k.GetIV">
+            <summary>The IV for the key generation algorithm.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.HashAlgorithm">
+            <summary>The hash algorithm.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.IterationCount">
+            <summary>The iteration count</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.ProtectionMode">
+            <summary>The protection mode - only if GnuDummyS2K</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SecretKeyPacket">
+            <remarks>Basic packet for a PGP secret key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SecretSubkeyPacket">
+            <remarks>Basic packet for a PGP secret key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignaturePacket">
+            <remarks>Generic signature packet.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.#ctor(System.Int32,System.Int64,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag,Org.BouncyCastle.Bcpg.SignatureSubpacket[],Org.BouncyCastle.Bcpg.SignatureSubpacket[],System.Byte[],Org.BouncyCastle.Bcpg.MPInteger[])">
+             Generate a version 4 signature packet.
+            
+             @param signatureType
+             @param keyAlgorithm
+             @param hashAlgorithm
+             @param hashedData
+             @param unhashedData
+             @param fingerprint
+             @param signature
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.#ctor(System.Int32,System.Int32,System.Int64,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag,System.Int64,System.Byte[],Org.BouncyCastle.Bcpg.MPInteger[])">
+             Generate a version 2/3 signature packet.
+            
+             @param signatureType
+             @param keyAlgorithm
+             @param hashAlgorithm
+             @param fingerprint
+             @param signature
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignatureTrailer">
+             return the signature trailer that must be included with the data
+             to reconstruct the signature
+            
+             @return byte[]
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignature">
+            		* return the signature as a set of integers - note this is normalised to be the
+                    * ASN.1 encoding of what appears in the signature packet.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignatureBytes">
+            Return the byte encoding of the signature section.
+            @return uninterpreted signature bytes.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SignaturePacket.KeyId">
+            return the keyId
+            @return the keyId that created the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SignaturePacket.CreationTime">
+            <summary>Return the creation time in milliseconds since 1 Jan., 1970 UTC.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacket">
+            <remarks>Basic type for a PGP Signature sub-packet.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignatureSubpacket.GetData">
+            <summary>Return the generic data making up the packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacketsParser">
+            reader for signature sub-packets
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacketTag">
+            Basic PGP signature sub-packet tag types.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.EmbeddedSignature">
+            Packet embedded signature
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.Exportable">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.IssuerKeyId">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.KeyExpirationTime">
+            packet giving time after creation at which the key expires.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.KeyExpirationTime.Time">
+             Return the number of seconds after creation time a key is valid for.
+            
+             @return second count for key validity.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.KeyFlags">
+            Packet holding the key flag values.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.KeyFlags.Flags">
+            <summary>
+            Return the flag values contained in the first 4 octets (note: at the moment
+            the standard only uses the first one).
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.NotationData">
+            Class provided a NotationData object according to
+            RFC2440, Chapter 5.2.3.15. Notation Data
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.PreferredAlgorithms">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.PrimaryUserId">
+            packet giving whether or not the signature is signed using the primary user ID for the key.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.Revocable">
+            packet giving whether or not is revocable.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RevocationKey">
+            <summary>
+            Represents revocation key OpenPGP signature sub packet.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RevocationReason">
+            <summary>
+            Represents revocation reason OpenPGP signature sub packet.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignatureCreationTime">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignatureExpirationTime">
+            packet giving signature expiration time.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.SignatureExpirationTime.Time">
+            return time in seconds before signature expires after creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignerUserId">
+            packet giving the User ID of the signer.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.TrustSignature">
+            packet giving trust.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricEncDataPacket">
+            <remarks>Basic type for a symmetric key encrypted packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag">
+            Basic tags for symmetric key algorithms
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket">
+            Basic type for a symmetric encrypted session key packet
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.GetSecKeyData">
+            @return byte[]
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.EncAlgorithm">
+            @return int
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.S2k">
+            @return S2k
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.Version">
+            @return int
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.TrustPacket">
+            <summary>Basic type for a trust packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributePacket">
+            Basic type for a user attribute packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacketsParser">
+            reader for user attribute sub-packets
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacketTag">
+            Basic PGP user attribute sub-packet tag types.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserIdPacket">
+            Basic type for a user ID packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAttributeTableParameter">
+            <remarks>
+            The 'Signature' parameter is only available when generating unsigned attributes.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedData">
+            containing class for an CMS Authenticated Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetAuthAttrs">
+            return a table of the digested attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetUnauthAttrs">
+            return a table of the undigested attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedData.MacAlgOid">
+            return the object identifier for the content MAC algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator">
+             General class for generating a CMS authenticated-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CMSAuthenticatedDataGenerator  fact = new CMSAuthenticatedDataGenerator();
+            
+                  fact.addKeyTransRecipient(cert);
+            
+                  CMSAuthenticatedData         data = fact.generate(content, algorithm, "BC");
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedGenerator">
+             General class for generating a CMS enveloped-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CMSEnvelopedDataGenerator  fact = new CMSEnvelopedDataGenerator();
+            
+                  fact.addKeyTransRecipient(cert);
+            
+                  CMSEnvelopedData         data = fact.generate(content, algorithm, "BC");
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyTransRecipient(Org.BouncyCastle.X509.X509Certificate)">
+             add a recipient.
+            
+             @param cert recipient's public key certificate
+             @exception ArgumentException if there is a problem with the certificate
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyTransRecipient(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+             add a recipient
+            
+             @param key the public key used by the recipient
+             @param subKeyId the identifier for the recipient's public key
+             @exception ArgumentException if there is a problem with the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKekRecipient(System.String,Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Byte[])">
+            add a KEK recipient.
+            @param key the secret key to use for wrapping
+            @param keyIdentifier the byte string that identifies the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKekRecipient(System.String,Org.BouncyCastle.Crypto.Parameters.KeyParameter,Org.BouncyCastle.Asn1.Cms.KekIdentifier)">
+            add a KEK recipient.
+            @param key the secret key to use for wrapping
+            @param keyIdentifier the byte string that identifies the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyAgreementRecipient(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+             Add a key agreement based recipient.
+            
+             @param agreementAlgorithm key agreement algorithm to use.
+             @param senderPrivateKey private key to initialise sender side of agreement with.
+             @param senderPublicKey sender public key to include with message.
+             @param recipientCert recipient's public key certificate.
+             @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+             @exception SecurityUtilityException if the algorithm requested cannot be found
+             @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyAgreementRecipients(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Collections.ICollection,System.String)">
+             Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
+            
+             @param agreementAlgorithm key agreement algorithm to use.
+             @param senderPrivateKey private key to initialise sender side of agreement with.
+             @param senderPublicKey sender public key to include with message.
+             @param recipientCerts recipients' public key certificates.
+             @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+             @exception SecurityUtilityException if the algorithm requested cannot be found
+             @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+             constructor allowing specific source of randomness
+            
+             @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            constructor allowing specific source of randomness
+            @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            generate an enveloped object that contains an CMS Enveloped Data
+            object using the given provider and the passed in key generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            generate an authenticated object that contains an CMS Authenticated Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser">
+             Parsing class for an CMS Authenticated Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one recipient can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             Example of use - assuming the first recipient matches the private key we have.
+             <pre>
+                  CMSAuthenticatedDataParser     ad = new CMSAuthenticatedDataParser(inputStream);
+            
+                  RecipientInformationStore  recipients = ad.getRecipientInfos();
+            
+                  Collection  c = recipients.getRecipients();
+                  Iterator    it = c.iterator();
+            
+                  if (it.hasNext())
+                  {
+                      RecipientInformation   recipient = (RecipientInformation)it.next();
+            
+                      CMSTypedStream recData = recipient.getContentStream(privateKey, "BC");
+            
+                      processDataStream(recData.getContentStream());
+            
+                      if (!Arrays.equals(ad.getMac(), recipient.getMac())
+                      {
+                          System.err.println("Data corrupted!!!!");
+                      }
+                  }
+              </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsContentInfoParser.Close">
+            Close the underlying data stream.
+            @throws IOException if the close fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetAuthAttrs">
+            return a table of the unauthenticated attributes indexed by
+            the OID of the attribute.
+            @exception java.io.IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetUnauthAttrs">
+            return a table of the unauthenticated attributes indexed by
+            the OID of the attribute.
+            @exception java.io.IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.MacAlgOid">
+            return the object identifier for the mac algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.MacAlgParams">
+            return the ASN.1 encoded encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator">
+             General class for generating a CMS authenticated-data message stream.
+             <p>
+             A simple example of usage.
+             <pre>
+                  CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
+            
+                  edGen.addKeyTransRecipient(cert);
+            
+                  ByteArrayOutputStream  bOut = new ByteArrayOutputStream();
+            
+                  OutputStream out = edGen.open(
+                                          bOut, CMSAuthenticatedDataGenerator.AES128_CBC, "BC");*
+                  out.write(data);
+            
+                  out.close();
+             </pre>
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            constructor allowing specific source of randomness
+            @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.SetBerEncodeRecipients(System.Boolean)">
+            Use a BER Set to store the recipient information
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            generate an enveloped object that contains an CMS Enveloped Data
+            object using the given provider and the passed in key generator.
+            @throws java.io.IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Int32)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthEnvelopedData">
+            containing class for an CMS AuthEnveloped Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedData">
+            containing class for an CMS Compressed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetContent">
+             Return the uncompressed content.
+            
+             @return the uncompressed content
+             @throws CmsException if there is an exception uncompressing the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetContent(System.Int32)">
+             Return the uncompressed content, throwing an exception if the data size
+             is greater than the passed in limit. If the content is exceeded getCause()
+             on the CMSException will contain a StreamOverflowException
+            
+             @param limit maximum number of bytes to read
+             @return the content read
+             @throws CMSException if there is an exception uncompressing the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsCompressedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataGenerator">
+                * General class for generating a compressed CMS message.
+                * <p>
+                * A simple example of usage.</p>
+                * <p>
+                * <pre>
+                *      CMSCompressedDataGenerator fact = new CMSCompressedDataGenerator();
+                *      CMSCompressedData data = fact.Generate(content, algorithm);
+                * </pre>
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            Generate an object that contains an CMS Compressed Data
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataParser">
+             Class for reading a CMS Compressed Data stream.
+             <pre>
+                 CMSCompressedDataParser cp = new CMSCompressedDataParser(inputStream);
+            
+                 process(cp.GetContent().GetContentStream());
+             </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                  CMSCompressedDataParser     ep = new CMSCompressedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator">
+             General class for generating a compressed CMS message stream.
+             <p>
+             A simple example of usage.
+             </p>
+             <pre>
+                  CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
+            
+                  Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
+            
+                  cOut.Write(data);
+            
+                  cOut.Close();
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedData">
+            containing class for an CMS Enveloped Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetUnprotectedAttributes">
+            return a table of the unprotected attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedData.EncryptionAlgOid">
+            return the object identifier for the content encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator">
+             <remarks>
+             General class for generating a CMS enveloped-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CmsEnvelopedDataGenerator  fact = new CmsEnvelopedDataGenerator();
+            
+                  fact.AddKeyTransRecipient(cert);
+            
+                  CmsEnvelopedData         data = fact.Generate(content, algorithm);
+             </pre>
+             </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            <summary>
+            Generate an enveloped object that contains a CMS Enveloped Data
+            object using the passed in key generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,System.Int32)">
+            <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataParser">
+             Parsing class for an CMS Enveloped Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one recipient can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             Example of use - assuming the first recipient matches the private key we have.
+             <pre>
+                  CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(inputStream);
+            
+                  RecipientInformationStore  recipients = ep.GetRecipientInfos();
+            
+                  Collection  c = recipients.getRecipients();
+                  Iterator    it = c.iterator();
+            
+                  if (it.hasNext())
+                  {
+                      RecipientInformation   recipient = (RecipientInformation)it.next();
+            
+                      CMSTypedStream recData = recipient.getContentStream(privateKey);
+            
+                      processDataStream(recData.getContentStream());
+                  }
+              </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.GetUnprotectedAttributes">
+            return a table of the unprotected attributes indexed by
+            the OID of the attribute.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.EncryptionAlgOid">
+            return the object identifier for the content encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.EncryptionAlgParams">
+            return the ASN.1 encoded encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator">
+             General class for generating a CMS enveloped-data message stream.
+             <p>
+             A simple example of usage.
+             <pre>
+                  CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+            
+                  edGen.AddKeyTransRecipient(cert);
+            
+                  MemoryStream  bOut = new MemoryStream();
+            
+                  Stream out = edGen.Open(
+                                          bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
+                  out.Write(data);
+            
+                  out.Close();
+             </pre>
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.SetBufferSize(System.Int32)">
+            <summary>Set the underlying string size for encapsulated data.</summary>
+            <param name="bufferSize">Length of octet strings to buffer the data.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.SetBerEncodeRecipients(System.Boolean)">
+            <summary>Use a BER Set to store the recipient information.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            <summary>
+            Generate an enveloped object that contains an CMS Enveloped Data
+            object using the passed in key generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Int32)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+            @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.ICipherParameters">
+            all parameter classes implement this.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsProcessable.Write(System.IO.Stream)">
+            <summary>
+            Generic routine to copy out the data we want processed.
+            </summary>
+            <remarks>
+            This routine may be called multiple times.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsProcessableByteArray">
+            a holding class for a byte array of data to be processed.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsProcessableByteArray.GetContent">
+            <returns>A clone of the byte array</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedData">
+             general class for handling a pkcs7-signature message.
+            
+             A simple example of usage - note, in the example below the validity of
+             the certificate isn't verified, just the fact that one of the certs
+             matches the given signer...
+            
+             <pre>
+              IX509Store              certs = s.GetCertificates();
+              SignerInformationStore  signers = s.GetSignerInfos();
+            
+              foreach (SignerInformation signer in signers.GetSigners())
+              {
+                  ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+                  X509Certificate cert = (X509Certificate) certList[0];
+            
+                  if (signer.Verify(cert.GetPublicKey()))
+                  {
+                      verified++;
+                  }
+              }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(System.Collections.IDictionary,System.Byte[])">
+             Content with detached signature, digests precomputed
+            
+             @param hashes a map of precomputed digests for content indexed by name of hash.
+             @param sigBlock the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(Org.BouncyCastle.Cms.CmsProcessable,System.IO.Stream)">
+             base constructor - content with detached signature.
+            
+             @param signedContent the content that was signed.
+             @param sigData the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(System.IO.Stream)">
+            base constructor - with encapsulated content
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetSignerInfos">
+            return the collection of signers that are associated with the
+            signatures for the message.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetAttributeCertificates(System.String)">
+             return a X509Store containing the attribute certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of attribute certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetCertificates(System.String)">
+             return a X509Store containing the public key certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of public key certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetCrls(System.String)">
+             return a X509Store containing CRLs, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of CRLs
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.ReplaceSigners(Org.BouncyCastle.Cms.CmsSignedData,Org.BouncyCastle.Cms.SignerInformationStore)">
+             Replace the signerinformation store associated with this
+             CmsSignedData object with the new one passed in. You would
+             probably only want to do this if you wanted to change the unsigned
+             attributes associated with a signer, or perhaps delete one.
+            
+             @param signedData the signed data object to be used as a base.
+             @param signerInformationStore the new signer information store to use.
+             @return a new signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.ReplaceCertificatesAndCrls(Org.BouncyCastle.Cms.CmsSignedData,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store)">
+             Replace the certificate and CRL information associated with this
+             CmsSignedData object with the new one passed in.
+            
+             @param signedData the signed data object to be used as a base.
+             @param x509Certs the new certificates to be used.
+             @param x509Crls the new CRLs to be used.
+             @return a new signed data object.
+             @exception CmsException if there is an error processing the stores
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.Version">
+            <summary>Return the version number for this object.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.SignedContentType">
+            <summary>
+            Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+            content info structure carried in the signed data.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.ContentInfo">
+            return the ContentInfo
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataGenerator">
+                 * general class for generating a pkcs7-signature message.
+                 * <p>
+                 * A simple example of usage.
+                 *
+                 * <pre>
+                 *      IX509Store certs...
+                 *      IX509Store crls...
+                 *      CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+                 *
+                 *      gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
+                 *      gen.AddCertificates(certs);
+                 *      gen.AddCrls(crls);
+                 *
+                 *      CmsSignedData data = gen.Generate(content);
+                 * </pre>
+            	 * </p>
+        </member>
+        <member name="F:Org.BouncyCastle.Cms.CmsSignedGenerator.Data">
+            Default type for the signed data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.AddAttributeCertificates(Org.BouncyCastle.X509.Store.IX509Store)">
+             Add the attribute certificates contained in the passed in store to the
+             generator.
+            
+             @param store a store of Version 2 attribute certificates
+             @throws CmsException if an error occurse processing the store.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.AddSigners(Org.BouncyCastle.Cms.SignerInformationStore)">
+             Add a store of precalculated signers to the generator.
+            
+             @param signerStore store of signers
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.GetGeneratedDigests">
+             Return a map of oids and byte arrays representing the digests calculated on the content during
+             the last generate.
+            
+             @return a map of oids (as String objects) and byte[] representing digests.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+                    * add a signer - no attributes other than the default ones will be
+                    * provided here.
+            		*
+            		* @param key signing key to use
+            		* @param cert certificate containing corresponding public key
+            		* @param digestOID digest algorithm OID
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+             add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+             provided here.
+            
+             @param key signing key to use
+             @param cert certificate containing corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String)">
+            add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+            provided here.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+                    * add a signer with extra signed/unsigned attributes.
+            		*
+            		* @param key signing key to use
+            		* @param cert certificate containing corresponding public key
+            		* @param digestOID digest algorithm OID
+            		* @param signedAttr table of attributes to be included in signature
+            		* @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+            
+             @param key signing key to use
+             @param cert certificate containing corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+             @param signedAttr table of attributes to be included in signature
+             @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            	     * add a signer with extra signed/unsigned attributes.
+            		 *
+            		 * @param key signing key to use
+            		 * @param subjectKeyID subjectKeyID of corresponding public key
+            		 * @param digestOID digest algorithm OID
+            		 * @param signedAttr table of attributes to be included in signature
+            		 * @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+            
+             @param key signing key to use
+             @param subjectKeyID subjectKeyID of corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+             @param signedAttr table of attributes to be included in signature
+             @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable)">
+            generate a signed object that for a CMS Signed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(System.String,Org.BouncyCastle.Cms.CmsProcessable,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object  - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data".
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.GenerateCounterSigners(Org.BouncyCastle.Cms.SignerInformation)">
+             generate a set of one or more SignerInformation objects representing counter signatures on
+             the passed in SignerInformation object.
+            
+             @param signer the signer to be countersigned
+             @param sigProvider the provider to be used for counter signing.
+             @return a store containing the signers.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataParser">
+             Parsing class for an CMS Signed Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one signer can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             A simple example of usage for an encapsulated signature.
+             </p>
+             <p>
+             Two notes: first, in the example below the validity of
+             the certificate isn't verified, just the fact that one of the certs
+             matches the given signer, and, second, because we are in a streaming
+             mode the order of the operations is important.
+             </p>
+             <pre>
+                  CmsSignedDataParser     sp = new CmsSignedDataParser(encapSigData);
+            
+                  sp.GetSignedContent().Drain();
+            
+                  IX509Store              certs = sp.GetCertificates();
+                  SignerInformationStore  signers = sp.GetSignerInfos();
+            
+                  foreach (SignerInformation signer in signers.GetSigners())
+                  {
+                      ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+                      X509Certificate cert = (X509Certificate) certList[0];
+            
+                      Console.WriteLine("verify returns: " + signer.Verify(cert));
+                  }
+             </pre>
+              Note also: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CmsSignedDataParser     ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.#ctor(System.IO.Stream)">
+            base constructor - with encapsulated content
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.#ctor(Org.BouncyCastle.Cms.CmsTypedStream,System.IO.Stream)">
+             base constructor
+            
+             @param signedContent the content that was signed.
+             @param sigData the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetSignerInfos">
+            return the collection of signers that are associated with the
+            signatures for the message.
+            @throws CmsException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetAttributeCertificates(System.String)">
+             return a X509Store containing the attribute certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of attribute certificates
+             @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetCertificates(System.String)">
+             return a X509Store containing the public key certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of public key certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetCrls(System.String)">
+             return a X509Store containing CRLs, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of CRLs
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.ReplaceSigners(System.IO.Stream,Org.BouncyCastle.Cms.SignerInformationStore,System.IO.Stream)">
+            Replace the signerinformation store associated with the passed
+            in message contained in the stream original with the new one passed in.
+            You would probably only want to do this if you wanted to change the unsigned
+            attributes associated with a signer, or perhaps delete one.
+            <p>
+            The output stream is returned unclosed.
+            </p>
+            @param original the signed data stream to be used as a base.
+            @param signerInformationStore the new signer information store to use.
+            @param out the stream to Write the new signed data object to.
+            @return out.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.ReplaceCertificatesAndCrls(System.IO.Stream,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,System.IO.Stream)">
+            Replace the certificate and CRL information associated with this
+            CMSSignedData object with the new one passed in.
+            <p>
+            The output stream is returned unclosed.
+            </p>
+            @param original the signed data stream to be used as a base.
+            @param certsAndCrls the new certificates and CRLs to be used.
+            @param out the stream to Write the new signed data object to.
+            @return out.
+            @exception CmsException if there is an error processing the CertStore
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedDataParser.Version">
+             Return the version number for the SignedData object
+            
+             @return the version number
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedDataParser.SignedContentType">
+            <summary>
+            Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+            content info structure carried in the signed data.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator">
+             General class for generating a pkcs7-signature message stream.
+             <p>
+             A simple example of usage.
+             </p>
+             <pre>
+                  IX509Store                   certs...
+                  CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            
+                  gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
+            
+                  gen.AddCertificates(certs);
+            
+                  Stream sigOut = gen.Open(bOut);
+            
+                  sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
+            
+                  sigOut.Close();
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+            add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes - specifying digest
+            encryption algorithm.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data".
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.Boolean,System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data
+            object using the given provider - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data". If dataOutputStream is non null the data
+            being signed will be written to the stream as it is processed.
+            @param out stream the CMS object is to be written to.
+            @param encapsulate true if data should be encapsulated.
+            @param dataOutputStream output stream to copy the data being signed to.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Boolean,System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data
+            object using the given provider - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+            @param out stream the CMS object is to be written to.
+            @param signedContentType OID for data to be signed.
+            @param encapsulate true if data should be encapsulated.
+            @param dataOutputStream output stream to copy the data being signed to.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedHelper.GetDigestAlgName(System.String)">
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedHelper.GetEncryptionAlgName(System.String)">
+            Return the digest encryption algorithm using one of the standard
+            JCA string representations rather than the algorithm identifier (if
+            possible).
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator">
+            Default authenticated attributes generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.#ctor">
+            Initialise to use all defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.#ctor(Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Initialise with some extra attributes or overrides.
+            
+             @param attributeTable initial attribute table to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.CreateStandardAttributeTable(System.Collections.IDictionary)">
+             Create a standard attribute table from the passed in parameters - this will
+             normally include contentType and messageDigest. If the constructor
+             using an AttributeTable was used, entries in it for contentType and
+             messageDigest will override the generated ones.
+            
+             @param parameters source parameters for table generation.
+            
+             @return a filled in IDictionary of attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.GetAttributes(System.Collections.IDictionary)">
+            @param parameters source parameters
+            @return the populated attribute table
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator">
+            Default signed attributes generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.#ctor">
+            Initialise to use all defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.#ctor(Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Initialise with some extra attributes or overrides.
+            
+             @param attributeTable initial attribute table to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.createStandardAttributeTable(System.Collections.IDictionary)">
+             Create a standard attribute table from the passed in parameters - this will
+             normally include contentType, signingTime, and messageDigest. If the constructor
+             using an AttributeTable was used, entries in it for contentType, signingTime, and
+             messageDigest will override the generated ones.
+            
+             @param parameters source parameters for table generation.
+            
+             @return a filled in Hashtable of attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.GetAttributes(System.Collections.IDictionary)">
+            @param parameters source parameters
+            @return the populated attribute table
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInfoGenerator.Generate(Org.BouncyCastle.Crypto.Parameters.KeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate a RecipientInfo object for the given key.
+            </summary>
+            <param name="contentEncryptionKey">
+            A <see cref="T:Org.BouncyCastle.Crypto.Parameters.KeyParameter"/>
+            </param>
+            <param name="random">
+            A <see cref="T:Org.BouncyCastle.Security.SecureRandom"/>
+            </param>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Asn1.Cms.RecipientInfo"/>
+            </returns>
+            <exception cref="T:Org.BouncyCastle.Security.GeneralSecurityException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KekRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using a secret key known to the other side.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformation.GetMac">
+             Return the MAC calculated for the content stream. Note: this call is only meaningful once all
+             the content has been read.
+            
+             @return  byte array containing the mac.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformation.KeyEncryptionAlgOid">
+                    * return the object identifier for the key encryption algorithm.
+                    * 
+            		* @return OID for key encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformation.KeyEncryptionAlgParams">
+                    * return the ASN.1 encoded key encryption algorithm parameters, or null if
+                    * there aren't any.
+                    * 
+            		* @return ASN.1 encoding of key encryption algorithm parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KekRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KeyAgreeRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using key agreement.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KeyTransRecipientInformation">
+            the KeyTransRecipientInformation class for a recipient who has been sent a secret
+            key encrypted using their public key that needs to be used to
+            extract the message.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KeyTransRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return it as a byte array.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.OriginatorID">
+            a basic index for an originator.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertStoreSelector.Policy">
+            <summary>
+            An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.OriginatorInformation.GetCertificates">
+             Return the certificates stored in the underlying OriginatorInfo object.
+            
+             @return a Store of X509CertificateHolder objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.OriginatorInformation.GetCrls">
+             Return the CRLs stored in the underlying OriginatorInfo object.
+            
+             @return a Store of X509CRLHolder objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.OriginatorInformation.ToAsn1Structure">
+             Return the underlying ASN.1 object defining this SignerInformation object.
+            
+             @return a OriginatorInfo.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.PasswordRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using a password.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.PasswordRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.PasswordRecipientInformation.KeyDerivationAlgorithm">
+             return the object identifier for the key derivation algorithm, or null
+             if there is none present.
+            
+             @return OID for key derivation algorithm, if present.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.Pkcs5Scheme2PbeKey">
+            <summary>
+            PKCS5 scheme-2 - password converted to bytes assuming ASCII.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.Pkcs5Scheme2Utf8PbeKey">
+            PKCS5 scheme-2 - password converted to bytes using UTF-8.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetFirstRecipient(Org.BouncyCastle.Cms.RecipientID)">
+             Return the first RecipientInformation object that matches the
+             passed in selector. Null if there are no matches.
+            
+             @param selector to identify a recipient
+             @return a single RecipientInformation object. Null if none matches.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetRecipients">
+             Return all recipients in the collection
+            
+             @return a collection of recipients.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetRecipients(Org.BouncyCastle.Cms.RecipientID)">
+             Return possible empty collection with recipients matching the passed in RecipientID
+            
+             @param selector a recipient id to select against.
+             @return a collection of RecipientInformation objects.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformationStore.Count">
+             Return the number of recipients in the collection.
+            
+             @return number of recipients identified.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SignerID">
+            a basic index for a signer.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SignerInformation">
+            an expanded SignerInfo block from a CMS Signed message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetContentDigest">
+            return the content digest that was calculated during verification.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetSignature">
+            return the encoded signature
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetCounterSignatures">
+            Return a SignerInformationStore containing the counter signatures attached to this
+            signer. If no counter signatures are present an empty store is returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetEncodedSignedAttributes">
+            return the DER encoding of the signed attributes.
+            @throws IOException if an encoding error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            verify that the given public key successfully handles and confirms the
+            signature associated with this signer.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.Verify(Org.BouncyCastle.X509.X509Certificate)">
+            verify that the given certificate successfully handles and confirms
+            the signature associated with this signer and, if a signingTime
+            attribute is available, that the certificate was valid at the time the
+            signature was generated.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.ToSignerInfo">
+             Return the base ASN.1 CMS structure that this object contains.
+            
+             @return an object containing a CMS SignerInfo structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.ReplaceUnsignedAttributes(Org.BouncyCastle.Cms.SignerInformation,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Return a signer information object with the passed in unsigned
+             attributes replacing the ones that are current associated with
+             the object passed in.
+            
+             @param signerInformation the signerInfo to be used as the basis.
+             @param unsignedAttributes the unsigned attributes to add.
+             @return a copy of the original SignerInformationObject with the changed attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.AddCounterSigners(Org.BouncyCastle.Cms.SignerInformation,Org.BouncyCastle.Cms.SignerInformationStore)">
+             Return a signer information object with passed in SignerInformationStore representing counter
+             signatures attached as an unsigned attribute.
+            
+             @param signerInformation the signerInfo to be used as the basis.
+             @param counterSigners signer info objects carrying counter signature.
+             @return a copy of the original SignerInformationObject with the changed attributes.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.Version">
+            return the version number for this objects underlying SignerInfo structure.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.DigestAlgOid">
+            return the object identifier for the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.DigestAlgParams">
+            return the signature parameters, or null if there aren't any.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.EncryptionAlgOid">
+            return the object identifier for the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.EncryptionAlgParams">
+            return the signature/encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.SignedAttributes">
+            return a table of the signed attributes - indexed by
+            the OID of the attribute.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.UnsignedAttributes">
+            return a table of the unsigned attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetFirstSigner(Org.BouncyCastle.Cms.SignerID)">
+             Return the first SignerInformation object that matches the
+             passed in selector. Null if there are no matches.
+            
+             @param selector to identify a signer
+             @return a single SignerInformation object. Null if none matches.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetSigners">
+            <returns>An ICollection of all signers in the collection</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetSigners(Org.BouncyCastle.Cms.SignerID)">
+             Return possible empty collection with signers matching the passed in SignerID
+            
+             @param selector a signer id to select against.
+             @return a collection of SignerInformation objects.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformationStore.Count">
+            <summary>The number of signers in the collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SimpleAttributeTableGenerator">
+            Basic generator that just returns a preconstructed attribute table
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.DHAgreement">
+            a Diffie-Hellman key exchange engine.
+            <p>
+            note: This uses MTI/A0 key agreement in order to make the key agreement
+            secure against passive attacks. If you're doing Diffie-Hellman and both
+            parties have long term public keys you should look at using this. For
+            further information have a look at RFC 2631.</p>
+            <p>
+            It's possible to extend this to more than two parties as well, for the moment
+            that is left as an exercise for the reader.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHAgreement.CalculateMessage">
+            calculate our initial message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.Parameters.DHPublicKeyParameters,Org.BouncyCastle.Math.BigInteger)">
+            given a message from a given party and the corresponding public key
+            calculate the next message in the agreement sequence. In this case
+            this will represent the shared secret.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.DHBasicAgreement">
+            a Diffie-Hellman key agreement class.
+            <p>
+            note: This is only the basic algorithm, it doesn't take advantage of
+            long term public keys if they are available. See the DHAgreement class
+            for a "better" implementation.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBasicAgreement">
+            The basic interface that basic Diffie-Hellman implementations
+            conforms to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBasicAgreement.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+            initialise the agreement engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBasicAgreement.GetFieldSize">
+            return the field size for the agreement algorithm in bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBasicAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.ICipherParameters)">
+            given a public key from a given party calculate the next
+            message in the agreement sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHBasicAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.ICipherParameters)">
+            given a short term public key from a given party calculate the next
+            message in the agreement sequence.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.DHStandardGroups">
+            <summary>Standard Diffie-Hellman groups from various IETF specifications.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement">
+             P1363 7.2.1 ECSVDP-DH
+            
+             ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
+             Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
+             and [Kob87]. This primitive derives a shared secret value from one
+             party's private key and another party's public key, where both have
+             the same set of EC domain parameters. If two parties correctly
+             execute this primitive, they will produce the same output. This
+             primitive can be invoked by a scheme to derive a shared secret key;
+             specifically, it may be used with the schemes ECKAS-DH1 and
+             DL/ECKAS-DH2. It assumes that the input keys are valid (see also
+             Section 7.2.2).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.ECDHCBasicAgreement">
+             P1363 7.2.2 ECSVDP-DHC
+            
+             ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
+             Diffie-Hellman version with cofactor multiplication. It is based on
+             the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
+             primitive derives a shared secret value from one party's private key
+             and another party's public key, where both have the same set of EC
+             domain parameters. If two parties correctly execute this primitive,
+             they will produce the same output. This primitive can be invoked by a
+             scheme to derive a shared secret key; specifically, it may be used
+             with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
+             validity of the input public key (see also Section 7.2.1).
+             <p>
+             Note: As stated P1363 compatibility mode with ECDH can be preset, and
+             in this case the implementation doesn't have a ECDH compatibility mode
+             (if you want that just use ECDHBasicAgreement and note they both implement
+             BasicAgreement!).</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDerivationParameters">
+            Parameters for key/byte stream derivation classes
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Kdf.DHKekGenerator">
+            RFC 2631 Diffie-hellman KEK derivation function.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDerivationFunction">
+            base interface for general purpose byte derivation functions.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IDerivationFunction.Digest">
+            return the message digest used as the basis for the function
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Kdf.ECDHKekGenerator">
+            X9.63 based key derivation function for ECDH CMS.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client">
+            Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+            This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+            "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Security.SecureRandom)">
+            Initialises the client to begin new authentication attempt
+            @param N The safe prime associated with the client's verifier
+            @param g The group parameter associated with the client's verifier
+            @param digest The digest algorithm associated with the client's verifier
+            @param random For key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.GenerateClientCredentials(System.Byte[],System.Byte[],System.Byte[])">
+            Generates client's credentials given the client's salt, identity and password
+            @param salt The salt used in the client's verifier.
+            @param identity The user's identity (eg. username)
+            @param password The user's password
+            @return Client's public value to send to server
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.CalculateSecret(Org.BouncyCastle.Math.BigInteger)">
+            Generates client's verification message given the server's credentials
+            @param serverB The server's credentials
+            @return Client's verification message for the server
+            @throws CryptoException If server's credentials are invalid
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server">
+            Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+            This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+            "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Security.SecureRandom)">
+            Initialises the server to accept a new client authentication attempt
+            @param N The safe prime associated with the client's verifier
+            @param g The group parameter associated with the client's verifier
+            @param v The client's verifier
+            @param digest The digest algorithm associated with the client's verifier
+            @param random For key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.GenerateServerCredentials">
+            Generates the server's credentials that are to be sent to the client.
+            @return The server's public value to the client
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.CalculateSecret(Org.BouncyCastle.Math.BigInteger)">
+            Processes the client's credentials. If valid the shared secret is generated and returned.
+            @param clientA The client's credentials
+            @return A shared secret BigInteger
+            @throws CryptoException If client's credentials are invalid
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator">
+            Generates new SRP verifier for user
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest)">
+            Initialises generator to create new verifiers
+            @param N The safe prime to use (see DHParametersGenerator)
+            @param g The group parameter to use (see DHParametersGenerator)
+            @param digest The digest to use. The same digest type will need to be used later for the actual authentication
+            attempt. Also note that the final session key size is dependent on the chosen digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator.GenerateVerifier(System.Byte[],System.Byte[],System.Byte[])">
+            Creates a new SRP verifier
+            @param salt The salt to use, generally should be large and random
+            @param identity The user's identifying information (eg. username)
+            @param password The user's password
+            @return A new verifier for use in future SRP authentication
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair">
+            a holding class for public/private parameter pairs.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             basic constructor.
+            
+             @param publicParam a public key parameters object.
+             @param privateParam the corresponding private key parameters.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.Public">
+             return the public key parameters.
+            
+             @return the public key parameters.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.Private">
+             return the private key parameters.
+            
+             @return the private key parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher">
+            The AEAD block ciphers already handle buffering internally, so this class
+            just takes care of implementing IBufferedCipher methods.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBufferedCipher">
+            <remarks>Block cipher engines are expected to conform to this interface.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBufferedCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">If true the cipher is initialised for encryption,
+            if false for decryption.</param>
+            <param name="parameters">The key and other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBufferedCipher.Reset">
+            <summary>
+            Reset the cipher. After resetting the cipher is in the same state
+            as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBufferedCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetBlockSize">
+             return the blocksize for the underlying cipher.
+            
+             @return the blocksize for the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output, or the input is not block size aligned and should be.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+             @exception DataLengthException if the input is not block size
+             aligned.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.Reset">
+            Reset the buffer and cipher. After resetting the object is in the same
+            state as it was after the last init (if there was one).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher">
+            a buffer wrapper for an asymmetric block cipher, allowing input
+            to be accumulated in a piecemeal fashion until final processing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher)">
+             base constructor.
+            
+             @param cipher the cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.GetBufferPosition">
+             return the amount of data sitting in the buffer.
+            
+             @return the amount of data sitting in the buffer.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the buffer and the underlying cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.DoFinal">
+             process the contents of the buffer using the underlying
+             cipher.
+            
+             @return the result of the encryption/decryption process on the
+             buffer.
+             @exception InvalidCipherTextException if we are given a garbage block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.Reset">
+            <summary>Reset the buffer</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedBlockCipher">
+            A wrapper class that allows block ciphers to be used to process data in
+            a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+            buffer is full and more data is being added, or on a doFinal.
+            <p>
+            Note: in the case where the underlying cipher is either a CFB cipher or an
+            OFB one the last block may not be a multiple of the block size.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.#ctor">
+            constructor for subclasses
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher without padding.
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+             false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetBlockSize">
+             return the blocksize for the underlying cipher.
+            
+             @return the blocksize for the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output, or the input is not block size aligned and should be.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+             @exception DataLengthException if the input is not block size
+             aligned.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.Reset">
+            Reset the buffer and cipher. After resetting the object is in the same
+            state as it was after the last init (if there was one).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.CipherKeyGenerator">
+            The base class for symmetric, or secret, cipher key generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.CipherKeyGenerator.Init(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator.
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.CipherKeyGenerator.GenerateKey">
+             Generate a secret key.
+            
+             @return a byte array containing the key value.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.DataLengthException">
+            this exception is thrown if a buffer that is meant to have output
+            copied into it turns out to be too short, or if we've been given
+            insufficient input. In general this exception will Get thrown rather
+            than an ArrayOutOfBounds exception.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.DataLengthException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.DataLengthException.#ctor(System.String)">
+             create a DataLengthException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.GeneralDigest">
+            base implementation of MD4 family style digest as outlined in
+            "Handbook of Applied Cryptography", pages 344 - 347.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDigest">
+            interface that a message digest conforms to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.GetDigestSize">
+             return the size, in bytes, of the digest produced by this message digest.
+            
+             @return the size, in bytes, of the digest produced by this message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.GetByteLength">
+             return the size, in bytes, of the internal buffer used by this digest.
+            
+             @return the size, in bytes, of the internal buffer used by this digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.Update(System.Byte)">
+             update the message digest with a single byte.
+            
+             @param inByte the input byte to be entered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+             update the message digest with a block of bytes.
+            
+             @param input the byte array containing the data.
+             @param inOff the offset into the byte array where the data starts.
+             @param len the length of the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.DoFinal(System.Byte[],System.Int32)">
+             Close the digest, producing the final digest value. The doFinal
+             call leaves the digest reset.
+            
+             @param output the array the digest is to be copied into.
+             @param outOff the offset into the out array the digest is to start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.Reset">
+            reset the digest back to it's initial state.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IDigest.AlgorithmName">
+             return the algorithm name
+            
+             @return the algorithm name
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IMemoable.Copy">
+            <summary>
+            Produce a copy of this object with its configuration and in its current state.
+            </summary>
+            <remarks>
+            The returned object may be used simply to store the state, or may be used as a similar object
+            starting from the copied state.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IMemoable.Reset(Org.BouncyCastle.Utilities.IMemoable)">
+            <summary>
+            Restore a copied object state into this object.
+            </summary>
+            <remarks>
+            Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
+            </remarks>
+            <param name="other">an object originally {@link #copy() copied} from an object of the same type as this instance.</param>
+            <exception cref="T:System.InvalidCastException">if the provided object is not of the correct type.</exception>
+            <exception cref="T:Org.BouncyCastle.Utilities.MemoableResetException">if the <b>other</b> parameter is in some other way invalid.</exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Gost3411Digest">
+            implementation of GOST R 34.11-94
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor(System.Byte[])">
+            Constructor to allow use of a particular sbox with GOST28147
+            @see GOST28147Engine#getSBox(String)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Gost3411Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.C2">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.LongDigest">
+            Base class for SHA-384 and SHA-512.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.#ctor">
+            Constructor for variable length word
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.#ctor(Org.BouncyCastle.Crypto.Digests.LongDigest)">
+            Copy constructor.  We are using copy constructors in place
+            of the object.Clone() interface as this interface is not
+            supported by J2ME.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.AdjustByteCounts">
+            adjust the byte counts so that byteCount2 represents the
+            upper long (less 3 bits) word of the byte count.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD2Digest">
+            implementation of MD2
+            as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.DoFinal(System.Byte[],System.Int32)">
+             Close the digest, producing the final digest value. The doFinal
+             call leaves the digest reset.
+            
+             @param out the array the digest is to be copied into.
+             @param outOff the offset into the out array the digest is to start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.Reset">
+            reset the digest back to it's initial state.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.Update(System.Byte)">
+             update the message digest with a single byte.
+            
+             @param in the input byte to be entered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+             update the message digest with a block of bytes.
+            
+             @param in the byte array containing the data.
+             @param inOff the offset into the byte array where the data starts.
+             @param len the length of the data.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Digests.MD2Digest.AlgorithmName">
+             return the algorithm name
+            
+             @return the algorithm name
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD4Digest">
+            implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
+            Computer Science and RSA Data Security, Inc.
+            <p>
+            <b>NOTE</b>: This algorithm is only included for backwards compatibility
+            with legacy applications, it's not secure, don't use it for anything new!</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.#ctor(Org.BouncyCastle.Crypto.Digests.MD4Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD5Digest">
+            implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD5Digest.#ctor(Org.BouncyCastle.Crypto.Digests.MD5Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD5Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest">
+            implementation of RipeMD128
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD128Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest">
+            implementation of RipeMD see,
+            http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD160Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest">
+            <remarks>
+            <p>Implementation of RipeMD256.</p>
+            <p><b>Note:</b> this algorithm offers the same level of security as RipeMD128.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.#ctor">
+            <summary> Standard constructor</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD256Digest)">
+            <summary> Copy constructor.  This will copy the state of the provided
+            message digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.Reset">
+            <summary> reset the chaining variables to the IV values.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest">
+            <remarks>
+            <p>Implementation of RipeMD 320.</p>
+            <p><b>Note:</b> this algorithm offers the same level of security as RipeMD160.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.#ctor">
+            <summary> Standard constructor</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD320Digest)">
+            <summary> Copy constructor.  This will copy the state of the provided
+            message digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.Reset">
+            <summary> reset the chaining variables to the IV values.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha1Digest">
+             implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+            
+             It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+             is the "endianness" of the word processing!
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha1Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha1Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha1Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha224Digest">
+            SHA-224 as described in RFC 3874
+            <pre>
+                    block  word  digest
+            SHA-1   512    32    160
+            SHA-224 512    32    224
+            SHA-256 512    32    256
+            SHA-384 1024   64    384
+            SHA-512 1024   64    512
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha224Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha256Digest">
+             Draft FIPS 180-2 implementation of SHA-256. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha256Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha256Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha256Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha384Digest">
+             Draft FIPS 180-2 implementation of SHA-384. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha384Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha384Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha384Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha3Digest">
+            <summary>
+            Implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
+            </summary>
+            <remarks>
+            Following the naming conventions used in the C source code to enable easy review of the implementation.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha3Digest.GetByteLength">
+             Return the size of block that the compression function is applied to in bytes.
+            
+             @return internal byte length of a block.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha512Digest">
+             Draft FIPS 180-2 implementation of SHA-512. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha512Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha512tDigest">
+            FIPS 180-4 implementation of SHA-512/t
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512tDigest.#ctor(System.Int32)">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512tDigest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha512tDigest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512tDigest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.ShortenedDigest">
+            Wrapper class that reduces the output length of a particular digest to
+            only the first n bytes of the digest function.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.ShortenedDigest.#ctor(Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+             Base constructor.
+            
+             @param baseDigest underlying digest to use.
+             @param length length in bytes of the output of doFinal.
+             @exception ArgumentException if baseDigest is null, or length is greater than baseDigest.GetDigestSize().
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.SkeinDigest">
+            <summary>
+            Implementation of the Skein parameterised hash function in 256, 512 and 1024 bit block sizes,
+            based on the <see cref="T:Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+            </summary>
+            <remarks>
+            This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+            competition in October 2010.
+            <p/>
+            Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+            Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_256">
+            <summary>
+            256 bit block size - Skein-256
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_512">
+            <summary>
+            512 bit block size - Skein-512
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_1024">
+            <summary>
+            1024 bit block size - Skein-1024
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinDigest.#ctor(System.Int32,System.Int32)">
+            <summary>
+            Constructs a Skein digest with an internal state size and output size.
+            </summary>
+            <param name="stateSizeBits">the internal state size in bits - one of <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_256"/> <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_512"/> or
+                                  <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinDigest.SKEIN_1024"/>.</param>
+            <param name="digestSizeBits">the output/digest size to produce in bits, which must be an integral number of
+                                 bytes.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinDigest.Init(Org.BouncyCastle.Crypto.Parameters.SkeinParameters)">
+            <summary>
+            Optionally initialises the Skein digest with the provided parameters.
+            </summary>
+            See <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+            <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.SkeinEngine">
+            <summary>
+            Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block
+            sizes, based on the <see cref="T:Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+            </summary>
+            <remarks>
+            This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+            competition in October 2010.
+            <p/>
+            Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+            Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+            <p/>
+            This implementation is the basis for <see cref="T:Org.BouncyCastle.Crypto.Digests.SkeinDigest"/> and <see cref="T:Org.BouncyCastle.Crypto.Macs.SkeinMac"/>, implementing the
+            parameter based configuration system that allows Skein to be adapted to multiple applications. <br/>
+            Initialising the engine with <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> allows standard and arbitrary parameters to
+            be applied during the Skein hash function.
+            <p/>
+            Implemented:
+            <ul>
+            <li>256, 512 and 1024 bit internal states.</li>
+            <li>Full 96 bit input length.</li>
+            <li>Parameters defined in the Skein specification, and arbitrary other pre and post message
+            parameters.</li>
+            <li>Arbitrary output size in 1 byte intervals.</li>
+            </ul>
+            <p/>
+            Not implemented:
+            <ul>
+            <li>Sub-byte length input (bit padding).</li>
+            <li>Tree hashing.</li>
+            </ul>
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_256">
+            <summary>
+            256 bit block size - Skein-256
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_512">
+            <summary>
+            512 bit block size - Skein-512
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_1024">
+            <summary>
+            1024 bit block size - Skein-1024
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.PARAM_TYPE_KEY">
+            The parameter type for the Skein key.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.PARAM_TYPE_CONFIG">
+            The parameter type for the Skein configuration block.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.PARAM_TYPE_MESSAGE">
+            The parameter type for the message.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.PARAM_TYPE_OUTPUT">
+            The parameter type for the output transformation.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.INITIAL_STATES">
+            Precalculated UBI(CFG) states for common state/output combinations without key or other
+            pre-message params.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.threefish">
+            Underlying Threefish tweakable block cipher
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.outputSizeBytes">
+            Size of the digest output, in bytes
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.chain">
+            The current chaining/state value
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.initialState">
+            The initial state value
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.key">
+            The (optional) key parameter
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.preMessageParameters">
+            Parameters to apply prior to the message
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.postMessageParameters">
+            Parameters to apply after the message, but prior to output
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.ubi">
+            The current UBI operation
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.singleByte">
+            Buffer for single byte update method
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.#ctor(System.Int32,System.Int32)">
+            <summary>
+            Constructs a Skein digest with an internal state size and output size.
+            </summary>
+            <param name="blockSizeBits">the internal state size in bits - one of <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_256"/> <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_512"/> or
+                                  <see cref="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.SKEIN_1024"/>.</param>
+            <param name="outputSizeBits">the output/digest size to produce in bits, which must be an integral number of
+                                 bytes.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.#ctor(Org.BouncyCastle.Crypto.Digests.SkeinEngine)">
+            <summary>
+            Creates a SkeinEngine as an exact copy of an existing instance.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.Init(Org.BouncyCastle.Crypto.Parameters.SkeinParameters)">
+            <summary>
+            Initialises the Skein engine with the provided parameters. See <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> for
+            details on the parameterisation of the Skein hash function.
+            </summary>
+            <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.CreateInitialState">
+            Calculate the initial (pre message block) chaining state.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.Reset">
+            <summary>
+            Reset the engine to the initial state (with the key and any pre-message parameters , ready to
+            accept message input.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.LOW_RANGE">
+            Point at which position might overflow long, so switch to add with carry logic
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.T1_FINAL">
+            Bit 127 = final
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.T1_FIRST">
+            Bit 126 = first
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.tweak">
+            UBI uses a 128 bit tweak
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.extendedPosition">
+            Whether 64 bit position exceeded
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UbiTweak.AdvancePosition(System.Int32)">
+            Advances the position in the tweak by the specified value.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UBI">
+            The Unique Block Iteration chaining mode.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UBI.currentBlock">
+            Buffer for the current block of message data
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UBI.currentOffset">
+            Offset into the current message block
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.SkeinEngine.UBI.message">
+            Buffer for message words for feedback into encrypted block
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.SM3Digest">
+            <summary>
+            Implementation of Chinese SM3 digest as described at
+            http://tools.ietf.org/html/draft-shen-sm3-hash-00
+            and at .... ( Chinese PDF )
+            </summary>
+            <remarks>
+            The specification says "process a bit stream",
+            but this is written to process bytes in blocks of 4,
+            meaning this will process 32-bit word groups.
+            But so do also most other digest specifications,
+            including the SHA-256 which was a origin for
+            this specification.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SM3Digest.#ctor">
+            <summary>
+            Standard constructor
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SM3Digest.#ctor(Org.BouncyCastle.Crypto.Digests.SM3Digest)">
+            <summary>
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.SM3Digest.Reset">
+            <summary>
+            reset the chaining variables
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.TigerDigest">
+            implementation of Tiger based on:
+            <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
+             http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.#ctor(Org.BouncyCastle.Crypto.Digests.TigerDigest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest">
+             Implementation of WhirlpoolDigest, based on Java source published by Barreto
+             and Rijmen.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest.#ctor(Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest)">
+            Copy constructor. This will copy the state of the provided message
+            digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest.Reset">
+            Reset the chaining variables
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.EC.CustomNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.EC.CustomNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.EC.CustomNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.EC.CustomNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding">
+            ISO 9796-1 padding. Note in the light of recent results you should
+            only use this with RSA (rather than the "simpler" Rabin keys) and you
+            should never use it with anything other than a hash (ie. even if the
+            message is small don't sign the message, sign it's hash) or some "random"
+            value. See your favorite search engine for details.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher">
+            <remarks>Base interface for a public/private key block cipher.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.GetInputBlockSize">
+            <returns>The maximum size, in bytes, an input block may be.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.GetOutputBlockSize">
+            <returns>The maximum size, in bytes, an output block will be.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+            <summary>Process a block.</summary>
+            <param name="inBuf">The input buffer.</param>
+            <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+            <param name="inLen">The length of the input block.</param>
+            <exception cref="T:Org.BouncyCastle.Crypto.InvalidCipherTextException">Input decrypts improperly.</exception>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">Input is too large for the cipher.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetInputBlockSize">
+            return the input block size. The largest message we can process
+            is (key_size_in_bits + 3)/16, which in our world comes to
+            key_size_in_bytes / 2.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetOutputBlockSize">
+            return the maximum possible size for the output.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.SetPadBits(System.Int32)">
+            set the number of bits in the next message to be treated as
+            pad bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetPadBits">
+            retrieve the number of pad bits in the last decoded message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.DecodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.OaepEncoding">
+            Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.DecodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block turns out to
+            be badly formatted.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.ItoOSP(System.Int32,System.Byte[])">
+            int to octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.maskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            mask generator function, as described in PKCS1v2.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding">
+            this does your basic Pkcs 1 v1.5 padding - whether or not you should be using this
+            depends on your application - see Pkcs1 Version 2 for details.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabledProperty">
+            some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+            work with one of these set the system property Org.BouncyCastle.Pkcs1.Strict to false.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher)">
+            Basic constructor.
+            @param cipher
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,System.Int32)">
+            Constructor for decryption with a fixed plaintext length.
+            
+            @param cipher The cipher to use for cryptographic operation.
+            @param pLen Length of the expected plaintext.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,System.Byte[])">
+            Constructor for decryption with a fixed plaintext length and a fallback
+            value that is returned, if the padding is incorrect.
+            
+            @param cipher
+                       The cipher to use for cryptographic operation.
+            @param fallback
+                       The fallback value, we don't to a arraycopy here.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.CheckPkcs1Encoding(System.Byte[],System.Int32)">
+            Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+            for encryption.
+            
+            @param encoded The Plaintext.
+            @param pLen Expected length of the plaintext.
+            @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.DecodeBlockOrRandom(System.Byte[],System.Int32,System.Int32)">
+            Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+            
+            @param in The encrypted block.
+            @param inOff Offset in the encrypted block.
+            @param inLen Length of the encrypted block.
+            @param pLen Length of the desired output.
+            @return The plaintext without padding, or a random value if the padding was incorrect.
+            
+            @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.DecodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabled">
+            The same effect can be achieved by setting the static property directly
+            <p>
+            The static property is checked during construction of the encoding object, it is set to
+            true by default.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesEngine">
+             an implementation of the AES (Rijndael), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor, they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first.
+            
+             The slowest version uses no static tables at all and computes the values in each round.
+             </p>
+             <p>
+             This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+             </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBlockCipher">
+            <remarks>Base interface for a symmetric key block cipher.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.GetBlockSize">
+            <returns>The block size for this cipher, in bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            <summary>Process a block.</summary>
+            <param name="inBuf">The input buffer.</param>
+            <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+            <param name="outBuf">The output buffer.</param>
+            <param name="outOff">The offset into <paramref>outBuf</paramref> to write the output block.</param>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">If input block is wrong size, or outBuf too small.</exception>
+            <returns>The number of bytes processed and produced.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBlockCipher.IsPartialBlockOkay">
+            <summary>Indicates whether this cipher can handle partial blocks.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesFastEngine">
+             an implementation of the AES (Rijndael)), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor), they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations), 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each), for a total of 2Kbytes),
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first
+            
+             The slowest version uses no static tables at all and computes the values in each round
+             </p>
+             <p>
+             This file contains the fast version with 8Kbytes of static tables for round precomputation
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesLightEngine">
+             an implementation of the AES (Rijndael), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor, they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first
+            
+             The slowest version uses no static tables at all and computes the values
+             in each round.
+             </p>
+             <p>
+             This file contains the slowest performance version with no static tables
+             for round precomputation, but it has the smallest foot print.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesWrapEngine">
+            <remarks>
+            An implementation of the AES Key Wrapper from the NIST Key Wrap Specification.
+            <p/>
+            For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Rfc3394WrapEngine">
+            <remarks>
+            An implementation of the AES Key Wrapper from the NIST Key Wrap
+            Specification as described in RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
+            and  <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+            </remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IWrapper.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.BlowfishEngine">
+            A class that provides Blowfish key encryption operations,
+            such as encoding data and generating keys.
+            All the algorithms herein are from Applied Cryptography
+            and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Blowfish cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.ProcessTable(System.UInt32,System.UInt32,System.UInt32[])">
+            apply the encryption cycle to each value pair in the table.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Encrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Decrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaEngine">
+            Camellia - based on RFC 3713.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaLightEngine">
+            Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaWrapEngine">
+            <remarks>
+            An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc3657.txt">http://www.ietf.org/rfc/rfc3657.txt</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Cast5Engine">
+             A class that provides CAST key encryption operations,
+             such as encoding data and generating keys.
+            
+             All the algorithms herein are from the Internet RFC's
+            
+             RFC2144 - Cast5 (64bit block, 40-128bit key)
+             RFC2612 - CAST6 (128bit block, 128-256bit key)
+            
+             and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a CAST cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F1(System.UInt32,System.UInt32,System.Int32)">
+             The first of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F2(System.UInt32,System.UInt32,System.Int32)">
+             The second of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F3(System.UInt32,System.UInt32,System.Int32)">
+             The third of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.CAST_Encipher(System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 16 rounds to encrypt the block.
+            
+             @param L0    the LH-32bits of the plaintext block
+             @param R0    the RH-32bits of the plaintext block
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Cast6Engine">
+             A class that provides CAST6 key encryption operations,
+             such as encoding data and generating keys.
+            
+             All the algorithms herein are from the Internet RFC
+            
+             RFC2612 - CAST6 (128bit block, 128-256bit key)
+            
+             and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.CAST_Encipher(System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 12 quad rounds rounds to encrypt the block.
+            
+             @param A    the 00-31  bits of the plaintext block
+             @param B    the 32-63  bits of the plaintext block
+             @param C    the 64-95  bits of the plaintext block
+             @param D    the 96-127 bits of the plaintext block
+             @param result the resulting ciphertext
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.CAST_Decipher(System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 12 quad rounds rounds to decrypt the block.
+            
+             @param A    the 00-31  bits of the ciphertext block
+             @param B    the 32-63  bits of the ciphertext block
+             @param C    the 64-95  bits of the ciphertext block
+             @param D    the 96-127 bits of the ciphertext block
+             @param result the resulting plaintext
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.ChaChaEngine">
+            <summary>
+            Implementation of Daniel J. Bernstein's ChaCha stream cipher.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Salsa20Engine">
+            <summary>
+            Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IStreamCipher">
+            <summary>The interface stream ciphers conform to.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">If true the cipher is initialised for encryption,
+            if false for decryption.</param>
+            <param name="parameters">The key and other data required by the cipher.</param>
+            <exception cref="T:System.ArgumentException">
+            If the parameters argument is inappropriate.
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.ReturnByte(System.Byte)">
+            <summary>encrypt/decrypt a single byte returning the result.</summary>
+            <param name="input">the byte to be processed.</param>
+            <returns>the result of processing the input byte.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process a block of bytes from <c>input</c> putting the result into <c>output</c>.
+            </summary>
+            <param name="input">The input byte array.</param>
+            <param name="inOff">
+            The offset into <c>input</c> where the data to be processed starts.
+            </param>
+            <param name="length">The number of bytes to be processed.</param>
+            <param name="output">The output buffer the processed bytes go into.</param>
+            <param name="outOff">
+            The offset into <c>output</c> the processed data starts at.
+            </param>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">If the output buffer is too small.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IStreamCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.StateSize">
+            Constants 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.#ctor">
+            <summary>
+            Creates a 20 round Salsa20 engine.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.#ctor(System.Int32)">
+            <summary>
+            Creates a Salsa20 engine with a specific number of rounds.
+            </summary>
+            <param name="rounds">the number of rounds (must be an even number).</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.R(System.UInt32,System.Int32)">
+             Rotate left
+            
+             @param   x   value to rotate
+             @param   y   amount to rotate x
+            
+             @return  rotated x
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ChaChaEngine.#ctor">
+            <summary>
+            Creates a 20 rounds ChaCha engine.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ChaChaEngine.#ctor(System.Int32)">
+            <summary>
+            Creates a ChaCha engine with a specific number of rounds.
+            </summary>
+            <param name="rounds">the number of rounds (must be an even number).</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ChaChaEngine.ChachaCore(System.Int32,System.UInt32[],System.UInt32[])">
+            <summary>
+            ChacCha function.
+            </summary>
+            <param name="rounds">The number of ChaCha rounds to execute</param>
+            <param name="input">The input words.</param>
+            <param name="x">The ChaCha state to modify.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEdeEngine">
+            <remarks>A class that provides a basic DESede (or Triple DES) engine.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEngine">
+            <remarks>A class that provides a basic DES engine.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a DES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEngine.bytebit">
+            what follows is mainly taken from "Applied Cryptography", by
+            Bruce Schneier, however it also bears great resemblance to Richard
+            Outerbridge's D3DES...
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.GenerateWorkingKey(System.Boolean,System.Byte[])">
+             Generate an integer based working key based on our secret key
+             and what we processing we are planning to do.
+            
+             Acknowledgements for this routine go to James Gillogly and Phil Karn.
+                     (whoever, and wherever they are!).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.DesFunc(System.Int32[],System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            the DES engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a DESede cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine">
+                * Wrap keys according to
+                * <a href="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
+                * draft-ietf-smime-key-wrap-01.txt</a>.
+                * <p>
+                * Note:
+                * <ul>
+                * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.</li>
+                * <li>if you are using this to wrap triple-des keys you need to set the
+                * parity bits on the key and, if it's a two-key triple-des key, pad it
+                * yourself.</li>
+                * </ul>
+            	* </p>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.engine">
+            Field engine 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.param">
+            Field param 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.paramPlusIV">
+            Field paramPlusIV 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.iv">
+            Field iv 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.forWrapping">
+            Field forWrapping 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.IV2">
+            Field IV2           
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Method init
+            
+             @param forWrapping
+             @param param
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Wrap(System.Byte[],System.Int32,System.Int32)">
+             Method wrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Unwrap(System.Byte[],System.Int32,System.Int32)">
+             Method unwrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.CalculateCmsKeyChecksum(System.Byte[])">
+             Some key wrap algorithms make use of the Key Checksum defined
+             in CMS [CMS-Algorithms]. This is used to provide an integrity
+             check value for the key being wrapped. The algorithm is
+            
+             - Compute the 20 octet SHA-1 hash on the key being wrapped.
+             - Use the first 8 octets of this hash as the checksum value.
+            
+             @param key
+             @return
+             @throws Exception
+             @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.CheckCmsKeyChecksum(System.Byte[],System.Byte[])">
+            @param key
+            @param checksum
+            @return
+            @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.AlgorithmName">
+             Method GetAlgorithmName
+            
+             @return
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.ElGamalEngine">
+            this does your basic ElGamal algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the ElGamal engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary ElGamal key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For ElGamal this is always one byte less than the size of P on
+             encryption, and twice the length as the size of P on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For ElGamal this is always one byte less than the size of P on
+             decryption, and twice the length as the size of P on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic ElGamal algorithm.
+            
+             @param in the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param length the length of the data to be processed.
+             @return the result of the ElGamal process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Gost28147Engine">
+            implementation of GOST 28147-89
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.#ctor">
+            standard constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an Gost28147 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.GetSBox(System.String)">
+            Return the S-Box associated with SBoxName
+            @param sBoxName name of the S-Box
+            @return byte array representing the S-Box
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.HC128Engine">
+             HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
+             generates keystream from a 128-bit secret key and a 128-bit initialization
+             vector.
+             <p>
+             http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+             </p><p>
+             It is a third phase candidate in the eStream contest, and is patent-free.
+             No attacks are known as of today (April 2007). See
+            
+             http://www.ecrypt.eu.org/stream/hcp3.html
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.HC128Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise a HC-128 cipher.
+            
+             @param forEncryption whether or not we are for encryption. Irrelevant, as
+                                  encryption and decryption are the same.
+             @param params        the parameters required to set up the cipher.
+             @throws ArgumentException if the params argument is
+                                              inappropriate (ie. the key is not 128 bit long).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.HC256Engine">
+            HC-256 is a software-efficient stream cipher created by Hongjun Wu. It 
+            generates keystream from a 256-bit secret key and a 256-bit initialization 
+            vector.
+            <p>
+            http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+            </p><p>
+            Its brother, HC-128, is a third phase candidate in the eStream contest.
+            The algorithm is patent-free. No attacks are known as of today (April 2007). 
+            See
+            
+            http://www.ecrypt.eu.org/stream/hcp3.html
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.HC256Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise a HC-256 cipher.
+            
+             @param forEncryption whether or not we are for encryption. Irrelevant, as
+                                  encryption and decryption are the same.
+             @param params        the parameters required to set up the cipher.
+             @throws ArgumentException if the params argument is
+                                              inappropriate (ie. the key is not 256 bit long).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.IdeaEngine">
+            A class that provides a basic International Data Encryption Algorithm (IDEA) engine.
+            <p>
+            This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
+            implementation summary by Fauzan Mirza (F.U.Mirza at sheffield.ac.uk). (baring 1 typo at the
+            end of the mulinv function!).
+            </p>
+            <p>
+            It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
+            </p>
+            <p>
+            Note 1: This algorithm is patented in the USA, Japan, and Europe including
+            at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland
+            and the United Kingdom. Non-commercial use is free, however any commercial
+            products are liable for royalties. Please see
+            <a href="http://www.mediacrypt.com">www.mediacrypt.com</a> for
+            further details. This announcement has been included at the request of
+            the patent holders.
+            </p>
+            <p>
+            Note 2: Due to the requests concerning the above, this algorithm is now only
+            included in the extended assembly. It is not included in the default distributions.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.#ctor">
+            standard constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an IDEA cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.Mul(System.Int32,System.Int32)">
+             return x = x * y where the multiplication is done modulo
+             65537 (0x10001) (as defined in the IDEA specification) and
+             a zero input is taken to be 65536 (0x10000).
+            
+             @param x the x value
+             @param y the y value
+             @return x = x * y
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.ExpandKey(System.Byte[])">
+            The following function is used to expand the user key to the encryption
+            subkey. The first 16 bytes are the user key, and the rest of the subkey
+            is calculated by rotating the previous 16 bytes by 25 bits to the left,
+            and so on until the subkey is completed.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.MulInv(System.Int32)">
+            This function computes multiplicative inverse using Euclid's Greatest
+            Common Divisor algorithm. Zero and one are self inverse.
+            <p>
+            i.e. x * MulInv(x) == 1 (modulo BASE)
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.AddInv(System.Int32)">
+            Return the additive inverse of x.
+            <p>
+            i.e. x + AddInv(x) == 0
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IdeaEngine.InvertKey(System.Int32[])">
+            The function to invert the encryption subkey to the decryption subkey.
+            It also involves the multiplicative inverse and the additive inverse functions.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.IesEngine">
+            support class for constructing intergrated encryption ciphers
+            for doing basic message exchanges on top of key agreement ciphers
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.#ctor(Org.BouncyCastle.Crypto.IBasicAgreement,Org.BouncyCastle.Crypto.IDerivationFunction,Org.BouncyCastle.Crypto.IMac)">
+             set up for use with stream mode, where the key derivation function
+             is used to provide a stream of bytes to xor with the message.
+            
+             @param agree the key agreement used as the basis for the encryption
+             @param kdf the key derivation function used for byte generation
+             @param mac the message authentication code generator for the message
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.#ctor(Org.BouncyCastle.Crypto.IBasicAgreement,Org.BouncyCastle.Crypto.IDerivationFunction,Org.BouncyCastle.Crypto.IMac,Org.BouncyCastle.Crypto.BufferedBlockCipher)">
+             set up for use in conjunction with a block cipher to handle the
+             message.
+            
+             @param agree the key agreement used as the basis for the encryption
+             @param kdf the key derivation function used for byte generation
+             @param mac the message authentication code generator for the message
+             @param cipher the cipher to used for encrypting the message
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters,Org.BouncyCastle.Crypto.ICipherParameters,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the encryptor.
+            
+             @param forEncryption whether or not this is encryption/decryption.
+             @param privParam our private key parameters
+             @param pubParam the recipient's/sender's public key parameters
+             @param param encoding and derivation parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.IsaacEngine">
+            Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
+            see: http://www.burtleburtle.net/bob/rand/isaacafa.html
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IsaacEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an ISAAC cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine">
+            NaccacheStern Engine. For details on this cipher, please see
+            http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initializes this algorithm. Must be called before all other Functions.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool,
+                  org.bouncycastle.crypto.CipherParameters)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.GetInputBlockSize">
+             Returns the input block size of this algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetInputBlockSize()
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.GetOutputBlockSize">
+             Returns the output block size of this algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetOutputBlockSize()
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single Block using the Naccache-Stern algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#ProcessBlock(byte[],
+                  int, int)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.Encrypt(Org.BouncyCastle.Math.BigInteger)">
+             Encrypts a BigInteger aka Plaintext with the public key.
+            
+             @param plain
+                        The BigInteger to encrypt
+             @return The byte[] representation of the encrypted BigInteger (i.e.
+                     crypted.toByteArray())
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.AddCryptedBlocks(System.Byte[],System.Byte[])">
+             Adds the contents of two encrypted blocks mod sigma
+            
+             @param block1
+                        the first encrypted block
+             @param block2
+                        the second encrypted block
+             @return encrypt((block1 + block2) mod sigma)
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.ProcessData(System.Byte[])">
+             Convenience Method for data exchange with the cipher.
+            
+             Determines blocksize and splits data to blocksize.
+            
+             @param data the data to be processed
+             @return the data after it went through the NaccacheSternEngine.
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.chineseRemainder(System.Collections.IList,System.Collections.IList)">
+             Computes the integer x that is expressed through the given primes and the
+             congruences with the chinese remainder theorem (CRT).
+            
+             @param congruences
+                        the congruences c_i
+             @param primes
+                        the primes p_i
+             @return an integer x for that x % p_i == c_i
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NoekeonEngine">
+            A Noekeon engine, using direct-key mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.#ctor">
+            Create an instance of the Noekeon encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NullEngine">
+            The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+            Provided for the sake of completeness.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC2Engine">
+            an implementation of RC2 as described in RFC 2268
+                 "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC2 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2Engine.RotateWordLeft(System.Int32,System.Int32)">
+            return the result rotating the 16 bit number in x left by y
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine">
+            Wrap keys according to RFC 3217 - RC2 mechanism
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.engine">
+            Field engine 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.parameters">
+            Field param 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.paramPlusIV">
+            Field paramPlusIV 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.iv">
+            Field iv 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.forWrapping">
+            Field forWrapping 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.IV2">
+            Field IV2           
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Method init
+            
+             @param forWrapping
+             @param param
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Wrap(System.Byte[],System.Int32,System.Int32)">
+             Method wrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Unwrap(System.Byte[],System.Int32,System.Int32)">
+             Method unwrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.CalculateCmsKeyChecksum(System.Byte[])">
+             Some key wrap algorithms make use of the Key Checksum defined
+             in CMS [CMS-Algorithms]. This is used to provide an integrity
+             check value for the key being wrapped. The algorithm is
+            
+             - Compute the 20 octet SHA-1 hash on the key being wrapped.
+             - Use the first 8 octets of this hash as the checksum value.
+            
+             @param key
+             @return
+             @throws Exception
+             @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.CheckCmsKeyChecksum(System.Byte[],System.Byte[])">
+            @param key
+            @param checksum
+            @return
+            @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.AlgorithmName">
+             Method GetAlgorithmName
+            
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC4Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC4 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC532Engine">
+            The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+            publication in RSA CryptoBytes, Spring of 1995.
+            <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+            <p>
+            This implementation has a word size of 32 bits.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.#ctor">
+            Create an instance of the RC5 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-32 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given block starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param  in     in byte buffer containing data to encrypt
+             @param  inOff  offset into src buffer
+             @param  out     out buffer where encrypted data is written
+             @param  outOff  offset into out buffer
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.RotateLeft(System.Int32,System.Int32)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(32)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % 32
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.RotateRight(System.Int32,System.Int32)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(32)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % 32
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC564Engine">
+            The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+            publication in RSA CryptoBytes, Spring of 1995.
+            <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+            <p>
+            This implementation is set to work with a 64 bit word size.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.#ctor">
+            Create an instance of the RC5 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-64 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given block starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param  in      in byte buffer containing data to encrypt
+             @param  inOff   offset into src buffer
+             @param  out     out buffer where encrypted data is written
+             @param  outOff  offset into out buffer
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.RotateLeft(System.Int64,System.Int64)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % wordSize
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.RotateRight(System.Int64,System.Int64)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC6Engine">
+            An RC6 engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.#ctor">
+            Create an instance of the RC6 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-32 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param inKey the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.RotateLeft(System.Int32,System.Int32)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.RotateRight(System.Int32,System.Int32)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Rfc3211WrapEngine">
+            an implementation of the RFC 3211 Key Wrap
+            Specification.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RijndaelEngine">
+            an implementation of Rijndael, based on the documentation and reference implementation
+            by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
+            <p>
+            Note: this implementation is based on information prior to readonly NIST publication.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Mul0x2(System.Int32)">
+            multiply two elements of GF(2^m)
+            needed for MixColumn and InvMixColumn
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.KeyAddition(System.Int64[])">
+            xor corresponding text input and round key input bytes
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.ShiftRow(System.Byte[])">
+            Row 0 remains unchanged
+            The other three rows are shifted a variable amount
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Substitution(System.Byte[])">
+            Replace every byte of the input by the byte at that place
+            in the nonlinear S-box
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.MixColumn">
+            Mix the bytes of every column in a linear way
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.InvMixColumn">
+            Mix the bytes of every column in a linear way
+            This is the opposite operation of Mixcolumn
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.GenerateWorkingKey(System.Byte[])">
+            Calculate the necessary round keys
+            The number of calculations depends on keyBits and blockBits
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.#ctor(System.Int32)">
+             basic constructor - set the cipher up for a given blocksize
+            
+             @param blocksize the blocksize in bits, must be 128, 192, or 256.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Rijndael cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine">
+            this does your basic RSA algorithm with blinding
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic RSA algorithm.
+            
+             @param inBuf the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine">
+            This does your basic RSA Chaum's blinding and unblinding as outlined in
+            "Handbook of Applied Cryptography", page 475. You need to use this if you are
+            trying to get another party to generate signatures without them being aware
+            of the message they are signing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the blinding engine.
+            
+             @param forEncryption true if we are encrypting (blinding), false otherwise.
+             @param param         the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the RSA blinding algorithm.
+            
+             @param in    the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @throws DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine">
+            this does your basic RSA algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaEngine">
+            this does your basic RSA algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic RSA algorithm.
+            
+             @param inBuf the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SeedEngine">
+            Implementation of the SEED algorithm as described in RFC 4009
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SeedWrapEngine">
+            <remarks>
+            An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc4010.txt">http://www.ietf.org/rfc/rfc4010.txt</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SerpentEngine">
+                * Serpent is a 128-bit 32-round block cipher with variable key lengths,
+                * including 128, 192 and 256 bit keys conjectured to be at least as
+                * secure as three-key triple-DES.
+                * <p>
+                * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
+                * candidate algorithm for the NIST AES Quest.>
+            	* </p>
+                * <p>
+                * For full details see the <a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">The Serpent home page</a>
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Serpent cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.MakeWorkingKey(System.Byte[])">
+             Expand a user-supplied key material into a session key.
+            
+             @param key  The user-key bytes (multiples of 4) to use.
+             @exception ArgumentException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt one block of plaintext.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt one block of ciphertext.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb0(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib0(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb1(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib1(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb2(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib2(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb3(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib3(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb4(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib4(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb5(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib5(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb6(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib6(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb7(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib7(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.LT">
+            Apply the linear transformation to the register set.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.InverseLT">
+            Apply the inverse of the linear transformation to the register set.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SkipjackEngine">
+            a class that provides a basic SKIPJACK engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a SKIPJACK cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.G(System.Int32,System.Int32)">
+            The G permutation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.H(System.Int32,System.Int32)">
+            the inverse of the G permutation.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.TeaEngine">
+            An TEA engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.#ctor">
+            Create an instance of the TEA encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.ThreefishEngine">
+            <summary>
+            Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block
+            sizes.
+            </summary>
+            <remarks>
+            This is the 1.3 version of Threefish defined in the Skein hash function submission to the NIST
+            SHA-3 competition in October 2010.
+            <p/>
+            Threefish was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+            Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+            <p/>
+            This implementation inlines all round functions, unrolls 8 rounds, and uses 1.2k of static tables
+            to speed up key schedule injection. <br/>
+            2 x block size state is retained by each cipher instance.
+            </remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_256">
+            <summary>
+            256 bit block size - Threefish-256
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_512">
+            <summary>
+            512 bit block size - Threefish-512
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_1024">
+            <summary>
+            1024 bit block size - Threefish-1024
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.TWEAK_SIZE_BYTES">
+            Size of the tweak in bytes (always 128 bit/16 bytes)
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ROUNDS_256">
+            Rounds in Threefish-256
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ROUNDS_512">
+            Rounds in Threefish-512
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ROUNDS_1024">
+            Rounds in Threefish-1024
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.MAX_ROUNDS">
+            Max rounds of any of the variants
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.C_240">
+            Key schedule parity constant
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.blocksizeBytes">
+            Block size in bytes
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.blocksizeWords">
+            Block size in 64 bit words
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.currentBlock">
+            Buffer for byte oriented processBytes to call internal word API
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.t">
+            Tweak bytes (2 byte t1,t2, calculated t3 and repeat of t1,t2 for modulo free lookup
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.kw">
+            Key schedule words
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.cipher">
+            The internal cipher implementation (varies by blocksize)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.#ctor(System.Int32)">
+            <summary>
+            Constructs a new Threefish cipher, with a specified block size.
+            </summary>
+            <param name="blocksizeBits">the block size in bits, one of <see cref="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_256"/>, <see cref="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_512"/>,
+                                 <see cref="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BLOCKSIZE_1024"/> .</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>
+            Initialise the engine.
+            </summary>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">an instance of <see cref="T:Org.BouncyCastle.Crypto.Parameters.TweakableBlockCipherParameters"/> or <see cref="T:Org.BouncyCastle.Crypto.Parameters.KeyParameter"/> (to
+                          use a 0 tweak)</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Init(System.Boolean,System.UInt64[],System.UInt64[])">
+            <summary>
+            Initialise the engine, specifying the key and tweak directly.
+            </summary>
+            <param name="forEncryption">the cipher mode.</param>
+            <param name="key">the words of the key, or <code>null</code> to use the current key.</param>
+            <param name="tweak">the 2 word (128 bit) tweak, or <code>null</code> to use the current tweak.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ProcessBlock(System.UInt64[],System.UInt64[])">
+            <summary>
+            Process a block of data represented as 64 bit words.
+            </summary>
+            <returns>the number of 8 byte words processed (which will be the same as the block size).</returns>
+            <param name="inWords">a block sized buffer of words to process.</param>
+            <param name="outWords">a block sized buffer of words to receive the output of the operation.</param>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">if either the input or output is not block sized</exception>
+            <exception cref="T:System.InvalidOperationException">if this engine is not initialised</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.BytesToWord(System.Byte[],System.Int32)">
+            <summary>
+            Read a single 64 bit word from input in LSB first order.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.WordToBytes(System.UInt64,System.Byte[],System.Int32)">
+            <summary>
+            Write a 64 bit word to output in LSB first order.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.RotlXor(System.UInt64,System.Int32,System.UInt64)">
+            Rotate left + xor part of the mix operation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.XorRotr(System.UInt64,System.Int32,System.UInt64)">
+            Rotate xor + rotate right part of the unmix operation.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ThreefishCipher.t">
+            The extended + repeated tweak words
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.ThreefishCipher.kw">
+            The extended + repeated key words
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish256Cipher.ROTATION_0_0">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish256Cipher.ROTATION_0_1">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish512Cipher.ROTATION_0_0">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish512Cipher.ROTATION_0_1">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish512Cipher.ROTATION_0_2">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish512Cipher.ROTATION_0_3">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish1024Cipher.ROTATION_0_0">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish1024Cipher.ROTATION_0_1">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish1024Cipher.ROTATION_0_2">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.ThreefishEngine.Threefish1024Cipher.ROTATION_0_3">
+            Mix rotation constants defined in Skein 1.3 specification
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.TwofishEngine">
+             A class that provides Twofish encryption operations.
+            
+             This Java implementation is based on the Java reference
+             implementation provided by Bruce Schneier and developed
+             by Raif S. Naffah.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.TwofishEngine.P_00">
+            Define the fixed p0/p1 permutations used in keyed S-box lookup.
+            By changing the following constant definitions, the S-boxes will
+            automatically Get changed in the Twofish engine.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.TwofishEngine.gSubKeys">
+            gSubKeys[] and gSBox[] are eventually used in the
+            encryption and decryption methods.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Twofish cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+             The input will be an exact multiple of our blocksize.
+            
+             encryptBlock uses the pre-calculated gSBox[] and subKey[]
+             arrays.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Decrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.RS_MDS_Encode(System.Int32,System.Int32)">
+             Use (12, 8) Reed-Solomon code over GF(256) to produce
+             a key S-box 32-bit entity from 2 key material 32-bit
+             entities.
+            
+             @param    k0 first 32-bit entity
+             @param    k1 second 32-bit entity
+             @return     Remainder polynomial Generated using RS code
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.RS_rem(System.Int32)">
+                    * Reed-Solomon code parameters: (12,8) reversible code:
+            		* <p>
+                    * <pre>
+                    * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+                    * </pre>
+                    * where a = primitive root of field generator 0x14D
+            		* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.VmpcEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            initialise a VMPC cipher.
+            
+            @param forEncryption
+               whether or not we are for encryption.
+            @param params
+               the parameters required to set up the cipher.
+            @exception ArgumentException
+               if the params argument is inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.XSalsa20Engine">
+            <summary>
+            Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce.
+            </summary>
+            <remarks>
+            XSalsa20 requires a 256 bit key, and a 192 bit nonce.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XSalsa20Engine.SetKey(System.Byte[],System.Byte[])">
+            <summary>
+            XSalsa20 key generation: process 256 bit input key and 128 bits of the input nonce
+            using a core Salsa20 function without input addition to produce 256 bit working key
+            and use that with the remaining 64 bits of nonce to initialize a standard Salsa20 engine state.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.XteaEngine">
+            An XTEA engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.#ctor">
+            Create an instance of the TEA encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator">
+            Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on ISO 18033/P1363a.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.#ctor(System.Int32,Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF Parameters generator.
+            
+             @param counterStart value of counter.
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.GenerateBytes(System.Byte[],System.Int32,System.Int32)">
+             fill len bytes of the output buffer with bytes generated from
+             the derivation function.
+            
+             @throws ArgumentException if the size of the request will cause an overflow.
+             @throws DataLengthException if the out buffer is too small.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.Digest">
+            return the underlying digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DesKeyGenerator.engineInit(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator - if strength is set to zero
+             the key generated will be 64 bits in size, otherwise
+             strength can be 64 or 56 bits (if you don't count the parity bits).
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DesEdeKeyGenerator.engineInit(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator - if strength is set to zero
+             the key Generated will be 192 bits in size, otherwise
+             strength can be 128 or 192 (or 112 or 168 if you don't count
+             parity bits), depending on whether you wish to do 2-key or 3-key
+             triple DES.
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DHBasicKeyPairGenerator">
+             a basic Diffie-Hellman key pair generator.
+            
+             This generates keys consistent for use with the basic algorithm for
+             Diffie-Hellman.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator">
+            interface that a public/private key pair generator should conform to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator.Init(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             intialise the key pair generator.
+            
+             @param the parameters the key pair is to be initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator.GenerateKeyPair">
+             return an AsymmetricCipherKeyPair containing the Generated keys.
+            
+             @return an AsymmetricCipherKeyPair containing the Generated keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DHKeyPairGenerator">
+             a Diffie-Hellman key pair generator.
+            
+             This generates keys consistent for use in the MTI/A0 key agreement protocol
+             as described in "Handbook of Applied Cryptography", Pages 516-519.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DHParametersGenerator.GenerateParameters">
+            which Generates the p and g values from the given parameters,
+            returning the DHParameters object.
+            <p>
+            Note: can take a while...</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DsaKeyPairGenerator">
+             a DSA key pair generator.
+            
+             This Generates DSA keys in line with the method described
+             in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator">
+            Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.Init(System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom)">
+             initialise the key generator.
+            
+             @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
+             @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
+             @param random random byte source.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.Init(Org.BouncyCastle.Crypto.Parameters.DsaParameterGenerationParameters)">
+             Initialise the key generator for DSA 2.
+             <p>
+                 Use this init method if you need to generate parameters for DSA 2 keys.
+             </p>
+            
+             @param params  DSA 2 key generation parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.GenerateParameters">
+            which Generates the p and g values from the given parameters,
+            returning the DsaParameters object.
+            <p>
+            Note: can take a while...</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.GenerateParameters_FIPS186_3">
+            generate suitable parameters for DSA, in line with
+            <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator.GenerateKeyPair">
+            Given the domain parameters this routine generates an EC key
+            pair in accordance with X9.62 section 5.2.1 pages 26, 27.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.ElGamalKeyPairGenerator">
+            a ElGamal key pair generator.
+            <p>
+            This Generates keys consistent for use with ElGamal as described in
+            page 164 of "Handbook of Applied Cryptography".</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.ElGamalParametersGenerator.GenerateParameters">
+                     * which Generates the p and g values from the given parameters,
+                     * returning the ElGamalParameters object.
+                     * <p>
+                     * Note: can take a while...
+            		 * </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Gost3410KeyPairGenerator">
+            a GOST3410 key pair generator.
+            This generates GOST3410 keys in line with the method described
+            in GOST R 34.10-94.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator">
+            generate suitable parameters for GOST3410.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.Init(System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom)">
+             initialise the key generator.
+            
+             @param size size of the key
+             @param typeProcedure type procedure A,B = 1;  A',B' - else
+             @param random random byte source.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.procedure_C(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Procedure C
+            procedure generates the a value from the given p,q,
+            returning the a value.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.GenerateParameters">
+            which generates the p , q and a values from the given parameters,
+            returning the Gost3410Parameters object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Kdf1BytesGenerator">
+            KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on IEEE P1363/ISO 18033.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Kdf1BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF1 byte generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Kdf2BytesGenerator">
+            KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on IEEE P1363/ISO 18033.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Kdf2BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF2 bytes generator. Generates key material
+             according to IEEE P1363 or ISO 18033 depending on the initialisation.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator">
+            Generator for MGF1 as defined in Pkcs 1v2
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+            @param digest the digest to be used as the source of Generated bytes
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.ItoOSP(System.Int32,System.Byte[])">
+            int to octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.GenerateBytes(System.Byte[],System.Int32,System.Int32)">
+             fill len bytes of the output buffer with bytes Generated from
+             the derivation function.
+            
+             @throws DataLengthException if the out buffer is too small.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.Digest">
+            return the underlying digest.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator">
+             Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator.permuteList(System.Collections.IList,Org.BouncyCastle.Security.SecureRandom)">
+             Generates a permuted ArrayList from the original one. The original List
+             is not modified
+            
+             @param arr
+                        the ArrayList to be permuted
+             @param rand
+                        the source of Randomness for permutation
+             @return a new IList with the permuted elements.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator.findFirstPrimes(System.Int32)">
+             Finds the first 'count' primes starting with 3
+            
+             @param count
+                        the number of primes to find
+             @return a vector containing the found primes as Integer
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator">
+            Generator for PBE derived keys and ivs as usd by OpenSSL.
+            <p>
+            The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+            iteration count of 1.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.PbeParametersGenerator">
+            super class for all Password Based Encyrption (Pbe) parameter generator classes.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Init(System.Byte[],System.Byte[],System.Int32)">
+             initialise the Pbe generator.
+            
+             @param password the password converted into bytes (see below).
+             @param salt the salt to be mixed with the password.
+             @param iterationCount the number of iterations the "mixing" function
+             is to be applied for.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GetPassword">
+             return the password byte array.
+            
+             @return the password byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GetSalt">
+             return the salt byte array.
+            
+             @return the salt byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate derived parameters for a key of length keySize.
+            
+             @param keySize the length, in bits, of the key required.
+             @return a parameters object representing a key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate derived parameters for a key of length keySize, and
+             an initialisation vector (IV) of length ivSize.
+            
+             @param keySize the length, in bits, of the key required.
+             @param ivSize the length, in bits, of the iv required.
+             @return a parameters object representing a key and an IV.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate derived parameters for a key of length keySize, specifically
+             for use with a MAC.
+            
+             @param keySize the length, in bits, of the key required.
+             @return a parameters object representing a key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs5PasswordToBytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             Pkcs5 (ascii, no padding)
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             PKCS5 (UTF-8, no padding)
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs12PasswordToBytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             Pkcs12 (unicode, big endian, 2 zero pad bytes at the end).
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.PbeParametersGenerator.IterationCount">
+             return the iteration count.
+            
+             @return the iteration count.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.#ctor">
+            Construct a OpenSSL Parameters generator. 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.Init(System.Byte[],System.Byte[])">
+            Initialise - note the iteration count for this algorithm is fixed at 1.
+            
+            @param password password to use.
+            @param salt salt to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedKey(System.Int32)">
+            the derived key function, the ith hash of the password and the salt.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+             @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 12 V1.0.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html">
+            RSA's Pkcs12 Page</a>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a Pkcs 12 Parameters generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+             @exception ArgumentException if an unknown digest is passed in.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.Adjust(System.Byte[],System.Int32,System.Byte[])">
+            add a + b + 1, returning the result in a. The a value is treated
+            as a BigInteger of length (b.Length * 8) bits. The result is
+            modulo 2^b.Length in case of overflow.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedKey(System.Int32,System.Int32)">
+            generation of a derived key ala Pkcs12 V1.0.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 1.
+            Note this generator is limited to the size of the hash produced by the
+            digest used to drive it.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+            RSA's Pkcs5 Page</a>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a Pkcs 5 Scheme 1 Parameters generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedKey">
+            the derived key function, the ith hash of the mPassword and the mSalt.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the mPassword, mSalt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the mPassword, mSalt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+             @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the mPassword,
+             mSalt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 2.
+            This generator uses a SHA-1 HMac as the calculation function.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+            RSA's Pkcs5 Page</a></p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.#ctor">
+            construct a Pkcs5 Scheme 2 Parameters generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator">
+            <summary>
+            Generates keys for the Poly1305 MAC.
+            </summary>
+            <remarks>
+            Poly1305 keys are 256 bit keys consisting of a 128 bit secret key used for the underlying block
+            cipher followed by a 128 bit {@code r} value used for the polynomial portion of the Mac. <br/>
+            The {@code r} value has a specific format with some bits required to be cleared, resulting in an
+            effective 106 bit key. <br/>
+            A separately generated 256 bit key can be modified to fit the Poly1305 key format by using the
+            {@link #clamp(byte[])} method to clear the required bits.
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Macs.Poly1305"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.engineInit(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+            <summary>
+            Initialises the key generator.
+            </summary>
+            <remarks>
+            Poly1305 keys are always 256 bits, so the key length in the provided parameters is ignored.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.engineGenerateKey">
+            <summary>
+            Generates a 256 bit key in the format required for Poly1305 - e.g.
+            <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+            as per <see cref="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.Clamp(System.Byte[])"/>.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.Clamp(System.Byte[])">
+            <summary>
+            Modifies an existing 32 byte key value to comply with the requirements of the Poly1305 key by
+            clearing required bits in the <code>r</code> (second 16 bytes) portion of the key.<br/>
+            Specifically:
+            <ul>
+            <li>r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})</li>
+            <li>r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252})</li>
+            </ul>
+            </summary>
+            <param name="key">a 32 byte key value <code>k[0] ... k[15], r[0] ... r[15]</code></param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.CheckKey(System.Byte[])">
+            <summary>
+            Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
+            <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+            as per <see cref="M:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator.Clamp(System.Byte[])"/>.
+            </summary>
+            <param name="key">Key.</param>
+            <exception cref="T:System.ArgumentException">if the key is of the wrong length, or has invalid bits set
+                      in the <code>r</code> portion of the key.</exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator">
+            Generate a random factor suitable for use with RSA blind signatures
+            as outlined in Chaum's blinding and unblinding as outlined in
+            "Handbook of Applied Cryptography", page 475.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the factor generator
+            
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator.GenerateBlindingFactor">
+             Generate a suitable blind factor for the public key the generator was initialised with.
+            
+             @return a random blind factor
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator">
+            an RSA key pair generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator.ChooseRandomPrime(System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            <summary>Choose a random prime value for use with RSA</summary>
+            <param name="bitlength">the bit-length of the returned prime</param>
+            <param name="e">the RSA public exponent</param>
+            <returns>a prime p, with (p-1) relatively prime to e</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDsa">
+            interface for classes implementing the Digital Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the signer for signature generation or signature
+             verification.
+            
+             @param forSigning true if we are generating a signature, false
+             otherwise.
+             @param param key parameters for signature generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.GenerateSignature(System.Byte[])">
+             sign the passed in message (usually the output of a hash function).
+            
+             @param message the message to be signed.
+             @return two big integers representing the r and s values respectively.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             verify the message message against the signature values r and s.
+            
+             @param message the message that was supposed to have been signed.
+             @param r the r signature value.
+             @param s the s signature value.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IMac">
+            The base interface for implementations of message authentication codes (MACs).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the MAC.
+            
+             @param param the key and other data required by the MAC.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.GetMacSize">
+             Return the block size for this MAC (in bytes).
+            
+             @return the block size for this MAC in bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Update(System.Byte)">
+             add a single byte to the mac for processing.
+            
+             @param in the byte to be processed.
+             @exception InvalidOperationException if the MAC is not initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            @param in the array containing the input.
+            @param inOff the index in the array the data begins at.
+            @param len the length of the input starting at inOff.
+            @exception InvalidOperationException if the MAC is not initialised.
+            @exception DataLengthException if there isn't enough data in in.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.DoFinal(System.Byte[],System.Int32)">
+            Compute the final stage of the MAC writing the output to the out
+            parameter.
+            <p>
+            doFinal leaves the MAC in the same state it was after the last init.
+            </p>
+            @param out the array the MAC is to be output to.
+            @param outOff the offset into the out buffer the output is to start at.
+            @exception DataLengthException if there isn't enough space in out.
+            @exception InvalidOperationException if the MAC is not initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Reset">
+            Reset the MAC. At the end of resetting the MAC should be in the
+            in the same state it was after the last init (if there was one).
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IMac.AlgorithmName">
+             Return the name of the algorithm the MAC implements.
+            
+             @return the name of the algorithm the MAC implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.InvalidCipherTextException">
+            this exception is thrown whenever we find something we don't expect in a
+            message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.InvalidCipherTextException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.InvalidCipherTextException.#ctor(System.String)">
+             create a InvalidCipherTextException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the signer for signing or verification.
+            
+             @param forSigning true if for signing, false otherwise
+             @param param necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described
+            in the passed in array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Reset">
+            reset the internal state
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.ISigner.AlgorithmName">
+             Return the name of the algorithm the signer implements.
+            
+             @return the name of the algorithm the signer implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.ISignerWithRecovery">
+            Signer with message recovery.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage">
+             Returns true if the signer has recovered the full message as
+             part of signature verification.
+            
+             @return true if full message recovered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage">
+             Returns a reference to what message was recovered (if any).
+            
+             @return full/partial message, null if nothing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.UpdateWithRecoveredMessage(System.Byte[])">
+             Perform an update with the recovered message before adding any other data. This must
+             be the first update method called, and calling it will result in the signer assuming
+             that further calls to update will include message content past what is recoverable.
+            
+             @param signature the signature that we are in the process of verifying.
+             @throws IllegalStateException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.KeyGenerationParameters">
+            The base class for parameters to key generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.KeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32)">
+             initialise the generator with a source of randomness
+             and a strength (in bits).
+            
+             @param random the random byte source.
+             @param strength the size, in bits, of the keys we want to produce.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.KeyGenerationParameters.Random">
+             return the random source associated with this
+             generator.
+            
+             @return the generators random source.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.KeyGenerationParameters.Strength">
+             return the bit strength for keys produced by this generator,
+            
+             @return the strength of the keys this generator produces (in bits).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac">
+            standard CBC Block Cipher MAC - if no padding is specified the default of
+            pad of zeroes is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CBC block cipher. This will produce an
+             authentication code half the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a standard MAC based on a CBC block cipher. This will produce an
+             authentication code half the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher">
+            implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CFB"
+             and the block size in bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CFB block cipher. This will produce an
+             authentication code half the length of the block size of the cipher, with
+             the CFB mode set to 8 bits.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a standard MAC based on a CFB block cipher. This will produce an
+             authentication code half the length of the block size of the cipher, with
+             the CFB mode set to 8 bits.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,System.Int32)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CFB mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param cfbBitSize the size of an output block produced by the CFB mode.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CFB mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param cfbBitSize the size of an output block produced by the CFB mode.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding a padding to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.CMac">
+            CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+            <p>
+            CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+            </p><p>
+            CMAC is a NIST recomendation - see 
+            csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+            </p><p>
+            CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+            analyzed by Tetsu Iwata and Kaoru Kurosawa.
+            </p><p>
+            CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message 
+            Authentication Code). OMAC stands for One-Key CBC MAC.
+            </p><p>
+            It supports 128- or 64-bits block ciphers, with any key size, and returns
+            a MAC with dimension less or equal to the block size of the underlying 
+            cipher.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+             This will produce an authentication code the length of the block size
+             of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             create a standard MAC based on a block cipher with the size of the
+             MAC been given in bits.
+             <p/>
+             Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+             or 16 bits if being used as a data authenticator (FIPS Publication 113),
+             and in general should be less than the size of the block cipher as it reduces
+             the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            
+             @param cipher        the cipher to be used as the basis of the MAC generation.
+             @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and @lt;= 128.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.GMac">
+            <summary>
+            The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
+            800-38D.
+            </summary>
+            <remarks>
+            GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
+            is processed as additional authenticated data with the underlying GCM block cipher).
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.GMac.#ctor(Org.BouncyCastle.Crypto.Modes.GcmBlockCipher)">
+            <summary>
+            Creates a GMAC based on the operation of a block cipher in GCM mode.
+            </summary>
+            <remarks>
+            This will produce an authentication code the length of the block size of the cipher.
+            </remarks>
+            <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.GMac.#ctor(Org.BouncyCastle.Crypto.Modes.GcmBlockCipher,System.Int32)">
+            <summary>
+            Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
+            </summary>
+            <remarks>
+            This will produce an authentication code the length of the block size of the cipher.
+            </remarks>
+            <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+            <param name="macSizeBits">the mac size to generate, in bits. Must be a multiple of 8, between 32 and 128 (inclusive).
+            Sizes less than 96 are not recommended, but are supported for specialized applications.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.GMac.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>
+            Initialises the GMAC - requires a <see cref="T:Org.BouncyCastle.Crypto.Parameters.ParametersWithIV"/> 
+            providing a <see cref="T:Org.BouncyCastle.Crypto.Parameters.KeyParameter"/> and a nonce.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.Gost28147Mac">
+            implementation of GOST 28147-89 MAC
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.HMac">
+             HMAC implementation based on RFC2104
+            
+             H(K XOR opad, H(K XOR ipad, text))
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.HMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac">
+             DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
+            
+             This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
+             class must be changed to protected
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a Retail-MAC based on a CBC block cipher. This will produce an
+             authentication code of the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation. This must
+             be DESEngine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a Retail-MAC based on a CBC block cipher. This will produce an
+             authentication code of the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+            create a Retail-MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses single DES CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses single DES CBC mode as the basis for the
+            MAC generation. The final block is decrypted and then encrypted using the
+            middle and right part of the key.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.Poly1305">
+            <summary>
+            Poly1305 message authentication code, designed by D. J. Bernstein.
+            </summary>
+            <remarks>
+            Poly1305 computes a 128-bit (16 bytes) authenticator, using a 128 bit nonce and a 256 bit key
+            consisting of a 128 bit key applied to an underlying cipher, and a 128 bit key (with 106
+            effective key bits) used in the authenticator.
+            
+            The polynomial calculation in this implementation is adapted from the public domain <a href="https://github.com/floodyberry/poly1305-donna">poly1305-donna-unrolled</a> C implementation
+            by Andrew M (@floodyberry).
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator"/>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.r0">
+            Polynomial key 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.r1">
+            Polynomial key 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.r2">
+            Polynomial key 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.r3">
+            Polynomial key 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.r4">
+            Polynomial key 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.s1">
+            Precomputed 5 * r[1..4] 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.s2">
+            Precomputed 5 * r[1..4] 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.s3">
+            Precomputed 5 * r[1..4] 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.s4">
+            Precomputed 5 * r[1..4] 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.k0">
+            Encrypted nonce 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.k1">
+            Encrypted nonce 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.k2">
+            Encrypted nonce 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.k3">
+            Encrypted nonce 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.currentBlock">
+            Current block of buffered input 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.currentBlockOffset">
+            Current offset in input buffer 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.h0">
+            Polynomial accumulator 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.h1">
+            Polynomial accumulator 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.h2">
+            Polynomial accumulator 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.h3">
+            Polynomial accumulator 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.Poly1305.h4">
+            Polynomial accumulator 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.Poly1305.#ctor">
+            Constructs a Poly1305 MAC, where the key passed to init() will be used directly.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.Poly1305.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+            Constructs a Poly1305 MAC, using a 128 bit block cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.Poly1305.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>
+            Initialises the Poly1305 MAC.
+            </summary>
+            <param name="parameters">a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with
+                     a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.SipHash">
+            <summary>
+            Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
+            Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
+            </summary>
+            <remarks>
+            "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
+            compression rounds and the number of finalization rounds. A compression round is identical to a
+            finalization round and this round function is called SipRound. Given a 128-bit key k and a
+            (possibly empty) byte string m, SipHash-c-d returns a 64-bit value..."
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.SipHash.#ctor">
+            <summary>SipHash-2-4</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.SipHash.#ctor(System.Int32,System.Int32)">
+            <summary>SipHash-c-d</summary>
+            <param name="c">the number of compression rounds</param>
+            <param name="d">the number of finalization rounds</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.SkeinMac">
+            <summary>
+            Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
+            based on the <see cref="T:Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+            </summary>
+            <remarks>
+            This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+            competition in October 2010.
+            <p/>
+            Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+            Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_256">
+            <summary>
+            256 bit block size - Skein-256
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_512">
+            <summary>
+            512 bit block size - Skein-512
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_1024">
+            <summary>
+            1024 bit block size - Skein-1024
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.SkeinMac.#ctor(System.Int32,System.Int32)">
+            <summary>
+            Constructs a Skein MAC with an internal state size and output size.
+            </summary>
+            <param name="stateSizeBits">the internal state size in bits - one of <see cref="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_256"/> <see cref="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_512"/> or
+                                  <see cref="F:Org.BouncyCastle.Crypto.Macs.SkeinMac.SKEIN_1024"/>.</param>
+            <param name="digestSizeBits">the output/MAC size to produce in bits, which must be an integral number of
+                                 bytes.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.SkeinMac.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>
+            Optionally initialises the Skein digest with the provided parameters.
+            </summary>
+            See <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+            <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.MaxBytesExceededException">
+            <summary>
+            This exception is thrown whenever a cipher requires a change of key, iv
+            or similar after x amount of bytes enciphered
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher">
+            implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of chaining.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.GetBlockSize">
+             return the block size of the underlying cipher.
+            
+             @return the block size of the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate chaining step for CBC mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate chaining step for CBC mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the decrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CBC".
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher">
+            Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+            NIST Special Publication 800-38C.
+            <p>
+            <b>Note</b>: this mode is a packet mode - it needs all the data up front.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher">
+            <summary>
+            A block cipher mode that includes authenticated encryption with a streaming mode
+            and optional associated data.</summary>
+            <see cref="T:Org.BouncyCastle.Crypto.Parameters.AeadParameters"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetUnderlyingCipher">
+            <summary>The block cipher underlying this algorithm.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <remarks>Parameter can either be an AeadParameters or a ParametersWithIV object.</remarks>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetBlockSize">
+            <returns>The block size for this cipher, in bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessAadByte(System.Byte)">
+            <summary>Add a single byte to the associated data check.</summary>
+            <remarks>If the implementation supports it, this will be an online operation and will not retain the associated data.</remarks>
+            <param name="input">The byte to be processed.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessAadBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>Add a sequence of bytes to the associated data check.</summary>
+            <remarks>If the implementation supports it, this will be an online operation and will not retain the associated data.</remarks>
+            <param name="inBytes">The input byte array.</param>
+            <param name="inOff">The offset into the input array where the data to be processed starts.</param>
+            <param name="len">The number of bytes to be processed.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             Encrypt/decrypt a single byte.
+            
+             @param input the byte to be processed.
+             @param outBytes the output buffer the processed byte goes into.
+             @param outOff the offset into the output byte array the processed data starts at.
+             @return the number of bytes written to out.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             Process a block of bytes from in putting the result into out.
+            
+             @param inBytes the input byte array.
+             @param inOff the offset into the in array where the data to be processed starts.
+             @param len the number of bytes to be processed.
+             @param outBytes the output buffer the processed bytes go into.
+             @param outOff the offset into the output byte array the processed data starts at.
+             @return the number of bytes written to out.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Finish the operation either appending or verifying the MAC at the end of the data.
+            
+             @param outBytes space for any resulting output data.
+             @param outOff offset into out to start copying the data at.
+             @return number of bytes written into out.
+             @throws InvalidOperationException if the cipher is in an inappropriate state.
+             @throws InvalidCipherTextException if the MAC fails to match.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetMac">
+             Return the value of the MAC associated with the last stream processed.
+            
+             @return MAC for plaintext data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetUpdateOutputSize(System.Int32)">
+             Return the size of the output buffer required for a ProcessBytes
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to ProcessBytes
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetOutputSize(System.Int32)">
+             Return the size of the output buffer required for a ProcessBytes plus a
+             DoFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to ProcessBytes and DoFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.GetMac">
+             Returns a byte array containing the mac calculated as part of the
+             last encrypt or decrypt operation.
+            
+             @return the last mac calculated.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher">
+            implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CFB"
+             and the block size in bits.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher">
+            A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+            be used to produce cipher text which is the same outLength as the plain text.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher that uses Cipher Text Stealing
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update of 'length' bytes.
+            
+             @param length the outLength of the input.
+             @return the space required to accommodate a call to update
+             with length bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of length bytes.
+            
+             @param length the outLength of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with length bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param length the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if cipher text decrypts wrongly (in
+             case the exception will never Get thrown).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.EaxBlockCipher">
+            A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and 
+            Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
+            
+            http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
+            
+            EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block 
+            cipher to encrypt and authenticate data. It's on-line (the length of a 
+            message isn't needed to begin processing it), has good performances, it's
+            simple and provably secure (provided the underlying block cipher is secure).
+            
+            Of course, this implementations is NOT thread-safe.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.EaxBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Constructor that accepts an instance of a block cipher engine.
+            
+             @param cipher the engine to use
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.GcmBlockCipher">
+            <summary>
+            Implements the Galois/Counter mode (GCM) detailed in
+            NIST Special Publication 800-38D.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GcmBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <remarks>
+            MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
+            Sizes less than 96 are not recommended, but are supported for specialized applications.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher">
+            implements the GOST 28147 OFB counter mode (GCTR).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             counter mode (must have a 64 bit block size).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param encrypting if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param parameters the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.GetBlockSize">
+             return the block size we are operating at (in bytes).
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.Reset">
+            reset the feedback vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/GCTR"
+             and the block size in bits
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.OcbBlockCipher">
+            An implementation of <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
+            Authenticated-Encryption Algorithm</a>, licensed per:
+            
+            <blockquote><p><a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
+            Open-Source Software Implementations of OCB</a> (Jan 9, 2013) - 'License 1'<br/>
+            Under this license, you are authorized to make, use, and distribute open-source software
+            implementations of OCB. This license terminates for you if you sue someone over their open-source
+            software implementation of OCB claiming that you have a patent covering their implementation.
+            </p><p>
+            This is a non-binding summary of a legal document (the link above). The parameters of the license
+            are specified in the license document and that document is controlling.</p></blockquote>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher">
+            implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.GetBlockSize">
+             return the block size we are operating at (in bytes).
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.Reset">
+            reset the feedback vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/OFB"
+             and the block size in bits
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher">
+                * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
+                * on top of a simple cipher. This class assumes the IV has been prepended
+                * to the data stream already, and just accomodates the reset after
+                * (blockSize + 2) bytes have been read.
+                * <p>
+                * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param parameters the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.EncryptByte(System.Byte,System.Int32)">
+            Encrypt one byte of data according to CFB mode.
+            @param data the byte to encrypt
+            @param blockOff offset in the current block
+            @returns the encrypted byte
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB IV mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB IV mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/PGPCFB"
+             and the block size in bits.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.SicBlockCipher">
+            Implements the Segmented Integer Counter (SIC) mode on top of a simple
+            block cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.SicBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param c the block cipher to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.SicBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding">
+            Block cipher padders are expected to conform to this interface
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param param parameters, if any required.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+            @exception InvalidCipherTextException if the padding is badly formed
+            or invalid.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding">
+            A padder that adds ISO10126-2 padding to a block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding">
+            A padder that adds the padding according to the scheme referenced in
+            ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random - a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.PaddingName">
+             Return the name of the algorithm the padder implements.
+            
+             @return the name of the algorithm the padder implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher">
+            A wrapper class that allows block ciphers to be used to process data in
+            a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+            outputs a block only when the buffer is full and more data is being added,
+            or on a doFinal (unless the current block in the buffer is a pad block).
+            The default padding mechanism used is the one outlined in Pkcs5/Pkcs7.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             Create a buffered block cipher with the desired padding.
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+             @param padding the padding type.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher Pkcs7 padding
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.GetOutputSize(System.Int32)">
+             return the minimum size of the output buffer required for an update
+             plus a doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer. If the buffer is currently
+             full and padding needs to be added a call to doFinal will produce
+             2 * GetBlockSize() bytes.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output or we are decrypting and the input is not block size aligned.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding">
+            A padder that adds Pkcs7/Pkcs5 padding to a block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random - a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.TbcPadding">
+            <summary> A padder that adds Trailing-Bit-Compliment padding to a block.
+            <p>
+            This padding pads the block out compliment of the last bit
+            of the plain text.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+            <summary> Initialise the padder.</summary>
+            <param name="random">- a SecureRandom if available.
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.AddPadding(System.Byte[],System.Int32)">
+            <summary> add the pad bytes to the passed in block, returning the
+            number of bytes added.
+            <p>
+            Note: this assumes that the last block of plain text is always
+            passed to it inside in. i.e. if inOff is zero, indicating the
+            entire block is to be overwritten with padding the value of in
+            should be the same as the last block of plain text.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.PadCount(System.Byte[])">
+            <summary> return the number of pad bytes present in the block.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.TbcPadding.PaddingName">
+            <summary> Return the name of the algorithm the cipher implements.</summary>
+            <returns> the name of the algorithm the cipher implements.
+            </returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.X923Padding">
+            A padder that adds X9.23 padding to a block - if a SecureRandom is
+            passed in random padding is assumed, otherwise padding with zeros is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random a SecureRandom if one is available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.X923Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding">
+            <summary> A padder that adds Null byte padding to a block.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             <summary> Initialise the padder.
+            
+             </summary>
+             <param name="random">- a SecureRandom if available.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.AddPadding(System.Byte[],System.Int32)">
+            <summary> add the pad bytes to the passed in block, returning the
+            number of bytes added.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.PadCount(System.Byte[])">
+            <summary> return the number of pad bytes present in the block.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.PaddingName">
+             <summary> Return the name of the algorithm the cipher implements.
+            
+             </summary>
+             <returns> the name of the algorithm the cipher implements.
+             </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.AeadParameters.#ctor(Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Int32,System.Byte[])">
+             Base constructor.
+            
+             @param key key to be used by underlying cipher
+             @param macSize macSize in bits
+             @param nonce nonce to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.AeadParameters.#ctor(Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Int32,System.Byte[],System.Byte[])">
+             Base constructor.
+            
+             @param key key to be used by underlying cipher
+             @param macSize macSize in bits
+             @param nonce nonce to be used
+             @param associatedText associated text, if any
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.CcmParameters.#ctor(Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Int32,System.Byte[],System.Byte[])">
+            Base constructor.
+            
+            @param key key to be used by underlying cipher
+            @param macSize macSize in bits
+            @param nonce nonce to be used
+            @param associatedText associated text, if any
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesParameters.IsWeakKey(System.Byte[],System.Int32)">
+            DES has 16 weak keys.  This method will check
+            if the given DES key material is weak or semi-weak.
+            Key material that is too short is regarded as weak.
+            <p>
+            See <a href="http://www.counterpane.com/applied.html">"Applied
+            Cryptography"</a> by Bruce Schneier for more information.
+            </p>
+            @return true if the given DES key material is weak or semi-weak,
+                false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesParameters.SetOddParity(System.Byte[])">
+             DES Keys use the LSB as the odd parity bit.  This can
+             be used to check for corrupt keys.
+            
+             @param bytes the byte array to set the parity on.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesEdeParameters.IsWeakKey(System.Byte[],System.Int32,System.Int32)">
+             return true if the passed in key is a DES-EDE weak key.
+            
+             @param key bytes making up the key
+             @param offset offset into the byte array the key starts at
+             @param length number of bytes making up the key
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesEdeParameters.IsWeakKey(System.Byte[],System.Int32)">
+             return true if the passed in key is a DES-EDE weak key.
+            
+             @param key bytes making up the key
+             @param offset offset into the byte array the key starts at
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.DHParameters.M">
+            <summary>The minimum bitlength of the private value.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.DHParameters.L">
+            <summary>The bitlength of the private value.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DsaParameterGenerationParameters.#ctor(System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom)">
+             Construct without a usage index, this will do a random construction of G.
+            
+             @param L desired length of prime P in bits (the effective key size).
+             @param N desired length of prime Q in bits.
+             @param certainty certainty level for prime number generation.
+             @param random the source of randomness to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DsaParameterGenerationParameters.#ctor(System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom,System.Int32)">
+             Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+            
+             @param L desired length of prime P in bits (the effective key size).
+             @param N desired length of prime Q in bits.
+             @param certainty certainty level for prime number generation.
+             @param random the source of randomness to use.
+             @param usageIndex a valid usage index.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.ElGamalParameters.G">
+            return the generator - g
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.ElGamalParameters.L">
+            return private value limit - l
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.IesParameters">
+            parameters for using an integrated cipher in stream mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.IesParameters.#ctor(System.Byte[],System.Byte[],System.Int32)">
+            @param derivation the derivation parameter for the KDF function.
+            @param encoding the encoding parameter for the KDF function.
+            @param macKeySize the size of the MAC key (in bits).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.IesWithCipherParameters.#ctor(System.Byte[],System.Byte[],System.Int32,System.Int32)">
+            @param derivation the derivation parameter for the KDF function.
+            @param encoding the encoding parameter for the KDF function.
+            @param macKeySize the size of the MAC key (in bits).
+            @param cipherKeySize the size of the associated Cipher key (in bits).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.Iso18033KdfParameters">
+            parameters for Key derivation functions for ISO-18033
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.KdfParameters">
+            parameters for Key derivation functions for IEEE P1363a
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.MgfParameters">
+            <remarks>Parameters for mask derivation functions.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters">
+             Parameters for NaccacheStern public private key generation. For details on
+             this cipher, please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32,System.Int32,System.Int32)">
+             Parameters for generating a NaccacheStern KeyPair.
+            
+             @param random
+                        The source of randomness
+             @param strength
+                        The desired strength of the Key in Bits
+             @param certainty
+                        the probability that the generated primes are not really prime
+                        as integer: 2^(-certainty) is then the probability
+             @param countSmallPrimes
+                        How many small key factors are desired
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32,System.Int32,System.Int32,System.Boolean)">
+             Parameters for a NaccacheStern KeyPair.
+            
+             @param random
+                        The source of randomness
+             @param strength
+                        The desired strength of the Key in Bits
+             @param certainty
+                        the probability that the generated primes are not really prime
+                        as integer: 2^(-certainty) is then the probability
+             @param cntSmallPrimes
+                        How many small key factors are desired
+             @param debug
+                        Turn debugging on or off (reveals secret information, use with
+                        caution)
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.Certainty">
+            @return Returns the certainty.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.CountSmallPrimes">
+            @return Returns the countSmallPrimes.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters">
+             Public key parameters for NaccacheStern cipher. For details on this cipher,
+             please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.#ctor(System.Boolean,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            @param privateKey
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.G">
+            @return Returns the g.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.LowerSigmaBound">
+            @return Returns the lowerSigmaBound.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.Modulus">
+            @return Returns the n.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternPrivateKeyParameters">
+             Private key parameters for NaccacheStern cipher. For details on this cipher,
+             please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternPrivateKeyParameters.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.Int32,System.Collections.IList,Org.BouncyCastle.Math.BigInteger)">
+             Constructs a NaccacheSternPrivateKey
+            
+             @param g
+                        the public enryption parameter g
+             @param n
+                        the public modulus n = p*q
+             @param lowerSigmaBound
+                        the public lower sigma bound up to which data can be encrypted
+             @param smallPrimes
+                        the small primes, of which sigma is constructed in the right
+                        order
+             @param phi_n
+                        the private modulus phi(n) = (p-1)(q-1)
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.ParametersWithSalt">
+            <summary> Cipher parameters with a fixed salt value associated with them.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters">
+            <summary>
+            Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
+            </summary>
+            <remarks>
+            Parameterised Skein can be used for:
+            <ul> 
+            <li>MAC generation, by providing a <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetKey(System.Byte[])">key</see>.</li>
+            <li>Randomised hashing, by providing a <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetNonce(System.Byte[])">nonce</see>.</li>
+            <li>A hash function for digital signatures, associating a
+            <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPublicKey(System.Byte[])">public key</see> with the message digest.</li>
+            <li>A key derivation function, by providing a
+            <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetKeyIdentifier(System.Byte[])">key identifier</see>.</li>
+            <li>Personalised hashing, by providing a
+            <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPersonalisation(System.DateTime,System.String,System.String)">recommended format</see> or
+            <see cref="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPersonalisation(System.Byte[])">arbitrary</see> personalisation string.</li>
+            </ul>
+            </remarks>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Digests.SkeinDigest"/>
+            <seealso cref="T:Org.BouncyCastle.Crypto.Macs.SkeinMac"/>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY">
+            <summary>
+            The parameter type for a secret key, supporting MAC or KDF functions: 0
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_CONFIG">
+            <summary>
+            The parameter type for the Skein configuration block: 4
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_PERSONALISATION">
+            <summary>
+            The parameter type for a personalisation string: 8
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_PUBLIC_KEY">
+            <summary>
+            The parameter type for a public key: 12
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER">
+            <summary>
+            The parameter type for a key identifier string: 16
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_NONCE">
+            <summary>
+            The parameter type for a nonce: 20
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_MESSAGE">
+            <summary>
+            The parameter type for the message: 48
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_OUTPUT">
+            <summary>
+            The parameter type for the output transformation: 63
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetParameters">
+            <summary>
+            Obtains a map of type (int) to value (byte[]) for the parameters tracked in this object.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetKey">
+            <summary>
+            Obtains the value of the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY">key parameter</see>, or <code>null</code> if not
+            set.
+            </summary>
+            <returns>The key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetPersonalisation">
+            <summary>
+            Obtains the value of the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_PERSONALISATION">personalisation parameter</see>, or
+            <code>null</code> if not set.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetPublicKey">
+            <summary>
+            Obtains the value of the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_PUBLIC_KEY">public key parameter</see>, or
+            <code>null</code> if not set.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetKeyIdentifier">
+            <summary>
+            Obtains the value of the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER">key identifier parameter</see>, or
+            <code>null</code> if not set.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.GetNonce">
+            <summary>
+            Obtains the value of the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_NONCE">nonce parameter</see>, or <code>null</code> if
+            not set.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder">
+            <summary>
+            A builder for <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.Set(System.Int32,System.Byte[])">
+            <summary>
+            Sets a parameters to apply to the Skein hash function.
+            </summary>
+            <remarks>
+            Parameter types must be in the range 0,5..62, and cannot use the value 48
+            (reserved for message body).
+            <p/>
+            Parameters with type < 48 are processed before
+            the message content, parameters with type > 48
+            are processed after the message and prior to output.
+            </remarks>
+            <param name="type">the type of the parameter, in the range 5..62.</param>
+            <param name="value">the byte sequence of the parameter.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetKey(System.Byte[])">
+            <summary>
+            Sets the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY"/> parameter.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPersonalisation(System.Byte[])">
+            <summary>
+            Sets the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_PERSONALISATION"/> parameter.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPersonalisation(System.DateTime,System.String,System.String)">
+            <summary>
+            Implements the recommended personalisation format for Skein defined in Section 4.11 of
+            the Skein 1.3 specification.
+            </summary>
+            <remarks>
+            The format is <code>YYYYMMDD email at address distinguisher</code>, encoded to a byte
+            sequence using UTF-8 encoding.
+            </remarks>
+            <param name="date">the date the personalised application of the Skein was defined.</param>
+            <param name="emailAddress">the email address of the creation of the personalised application.</param>
+            <param name="distinguisher">an arbitrary personalisation string distinguishing the application.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetPublicKey(System.Byte[])">
+            <summary>
+            Sets the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetKeyIdentifier(System.Byte[])">
+            <summary>
+            Sets the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.SetNonce(System.Byte[])">
+            <summary>
+            Sets the <see cref="F:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.PARAM_TYPE_NONCE"/> parameter.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.SkeinParameters.Builder.Build">
+            <summary>
+            Constructs a new <see cref="T:Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> instance with the parameters provided to this
+            builder.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.TweakableBlockCipherParameters">
+            <summary>
+            Parameters for tweakable block ciphers.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.TweakableBlockCipherParameters.Key">
+            <summary>
+            Gets the key.
+            </summary>
+            <value>the key to use, or <code>null</code> to use the current key.</value>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.TweakableBlockCipherParameters.Tweak">
+            <summary>
+            Gets the tweak value.
+            </summary>
+            <value>The tweak to use, or <code>null</code> to use the current tweak.</value>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.DigestRandomGenerator">
+            Random generation based on the digest with counter. Calling AddSeedMaterial will
+            always increase the entropy of the hash.
+            <p>
+            Internal access to the digest is synchronized so a single one of these can be shared.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.IRandomGenerator">
+            <remarks>Generic interface for objects generating random bytes.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.AddSeedMaterial(System.Byte[])">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A byte array to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.AddSeedMaterial(System.Int64)">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A long value to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.NextBytes(System.Byte[])">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to be filled.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.NextBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to receive bytes.</param>
+            <param name="start">Index to start filling at.</param>
+            <param name="len">Length of segment to fill.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator">
+            <remarks>
+            Takes bytes generated by an underling RandomGenerator and reverses the order in
+            each small window (of configurable size).
+            <p>
+            Access to internals is synchronized so a single one of these can be shared.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.AddSeedMaterial(System.Byte[])">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A byte array to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.AddSeedMaterial(System.Int64)">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A long value to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.NextBytes(System.Byte[])">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to be filled.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.NextBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to receive bytes.</param>
+            <param name="start">Index to start filling at.</param>
+            <param name="len">Length of segment to fill.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.ThreadedSeedGenerator">
+            A thread based seed generator - one source of randomness.
+            <p>
+            Based on an idea from Marcus Lippert.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ThreadedSeedGenerator.GenerateSeed(System.Int32,System.Boolean)">
+            Generate seed bytes. Set fast to false for best quality.
+            <p>
+            If fast is set to true, the code should be round about 8 times faster when
+            generating a long sequence of random bytes. 20 bytes of random values using
+            the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+            it takes round about 2500 ms.
+            </p>
+            @param numBytes the number of bytes to generate
+            @param fast true if fast mode should be used
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator.P">
+            <remarks>
+            Permutation generated by code:
+            <code>
+            // First 1850 fractional digit of Pi number. 
+            byte[] key = new BigInteger("14159265358979323846...5068006422512520511").ToByteArray();
+            s = 0;
+            P = new byte[256];
+            for (int i = 0; i < 256; i++) 
+            {
+                P[i] = (byte) i;
+            }
+            for (int m = 0; m < 768; m++) 
+            {
+                s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
+                byte temp = P[m & 0xff];
+                P[m & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+            } </code>
+            </remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator.s">
+            <remarks>Value generated in the same way as <c>P</c>.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.VerifySignature(System.Byte[])">
+            <returns>true if the internal state represents the signature described in the passed in array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.Reset">
+            <summary>Reset the internal state</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.DsaSigner">
+            The Digital Signature Algorithm - as described in "Handbook of Applied
+            Cryptography", pages 452 - 453.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.#ctor">
+            Default configuration, random K values.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.#ctor(Org.BouncyCastle.Crypto.Signers.IDsaKCalculator)">
+             Configuration with an alternate, possibly deterministic calculator of K.
+            
+             @param kCalculator a K value calculator.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.GenerateSignature(System.Byte[])">
+             Generate a signature for the given message using the key we were
+             initialised with. For conventional DSA the message should be a SHA-1
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a DSA signature for
+            the passed in message for standard DSA the message should be a
+            SHA-1 hash of the real message to be verified.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECDsaSigner">
+            EC-DSA as described in X9.62
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.#ctor">
+            Default configuration, random K values.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.#ctor(Org.BouncyCastle.Crypto.Signers.IDsaKCalculator)">
+             Configuration with an alternate, possibly deterministic calculator of K.
+            
+             @param kCalculator a K value calculator.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.GenerateSignature(System.Byte[])">
+             Generate a signature for the given message using the key we were
+             initialised with. For conventional DSA the message should be a SHA-1
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a DSA signature for
+            the passed in message (for standard DSA the message should be
+            a SHA-1 hash of the real message to be verified).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer">
+            GOST R 34.10-2001 Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with. For conventional GOST3410 the message should be a GOST3411
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a GOST3410 signature for
+            the passed in message (for standard GOST3410 the message should be
+            a GOST3411 hash of the real message to be verified).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECNRSigner">
+            EC-NR as described in IEEE 1363-2000
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECNRSigner.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with.  Generally, the order of the curve should be at
+             least as long as the hash of the message of interest, and with
+             ECNR it *must* be at least as long.
+            
+             @param digest  the digest to be signed.
+             @exception DataLengthException if the digest is longer than the key allows
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECNRSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             return true if the value r and s represent a signature for the
+             message passed in. Generally, the order of the curve should be at
+             least as long as the hash of the message of interest, and with
+             ECNR, it *must* be at least as long.  But just in case the signer
+             applied mod(n) to the longer digest, this implementation will
+             apply mod(n) during verification.
+            
+             @param digest  the digest to be verified.
+             @param r       the r value of the signature.
+             @param s       the s value of the signature.
+             @exception DataLengthException if the digest is longer than the key allows
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the signer for signing or verification.
+            
+             @param forSigning
+                        true if for signing, false otherwise
+             @param parameters
+                        necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using the key
+            we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described in
+            the passed in array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.VerifySignature(System.Byte[])">
+            <returns>true if the internal state represents the signature described in the passed in array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.Reset">
+            <summary>Reset the internal state</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Gost3410Signer">
+            Gost R 34.10-94 Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410Signer.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with. For conventional Gost3410 the message should be a Gost3411
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410Signer.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a Gost3410 signature for
+            the passed in message for standard Gost3410 the message should be a
+            Gost3411 hash of the real message to be verified.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.HMacDsaKCalculator">
+            A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.IDsaKCalculator">
+            Interface define calculators of K values for DSA/ECDSA.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.IDsaKCalculator.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Security.SecureRandom)">
+             Non-deterministic initialiser.
+            
+             @param n the order of the DSA group.
+             @param random a source of randomness.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.IDsaKCalculator.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.Byte[])">
+             Deterministic initialiser.
+            
+             @param n the order of the DSA group.
+             @param d the DSA private value.
+             @param message the message being signed.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.IDsaKCalculator.NextK">
+             Return the next valid value of K.
+            
+             @return a K value.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Signers.IDsaKCalculator.IsDeterministic">
+             Return true if this calculator is deterministic, false otherwise.
+            
+             @return true if deterministic, otherwise false.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.HMacDsaKCalculator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Base constructor.
+            
+             @param digest digest to build the HMAC on.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner">
+            <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
+            <p>
+            Note: the usual length for the salt is the length of the hash
+            function used in bytes.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.GetRecoveredMessage">
+            <summary>
+            Return a reference to the recoveredMessage message.
+            </summary>
+            <returns>The full/partial recoveredMessage message.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32,System.Boolean)">
+            <summary>
+            Generate a signer for the with either implicit or explicit trailers
+            for ISO9796-2, scheme 2 or 3.
+            </summary>
+            <param name="cipher">base cipher to use for signature creation/verification</param>
+            <param name="digest">digest to use.</param>
+            <param name="saltLength">length of salt in bytes.</param>
+            <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+             <summary> Constructor for a signer with an explicit digest trailer.
+            
+             </summary>
+             <param name="cipher">cipher to use.
+             </param>
+             <param name="digest">digest to sign with.
+             </param>
+             <param name="saltLength">length of salt in bytes.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the signer.</summary>
+            <param name="forSigning">true if for signing, false if for verification.</param>
+            <param name="parameters">parameters for signature generation/verification. If the
+            parameters are for generation they should be a ParametersWithRandom,
+            a ParametersWithSalt, or just an RsaKeyParameters object. If RsaKeyParameters
+            are passed in a SecureRandom will be created.
+            </param>
+            <exception cref="T:System.ArgumentException">if wrong parameter type or a fixed
+            salt is passed in which is the wrong length.
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.IsSameAs(System.Byte[],System.Byte[])">
+            <summary> compare two byte arrays - constant time.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.GenerateSignature">
+            <summary> Generate a signature for the loaded message using the key we were
+            initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.VerifySignature(System.Byte[])">
+            <summary> return true if the signature represents a ISO9796-2 signature
+            for the passed in message.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.HasFullMessage">
+            <summary>
+            Return true if the full message was recoveredMessage.
+            </summary>
+            <returns>true on full message recovery, false otherwise, or if not sure.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.ItoOSP(System.Int32,System.Byte[])">
+            <summary> int to octet string.</summary>
+            <summary> int to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.LtoOSP(System.Int64,System.Byte[])">
+            <summary> long to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.MaskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary> mask generator function, as described in Pkcs1v2.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer">
+            <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 1)</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.GetRecoveredMessage">
+            <summary>
+            Return a reference to the recoveredMessage message.
+            </summary>
+            <returns>The full/partial recoveredMessage message.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Boolean)">
+            <summary>
+            Generate a signer for the with either implicit or explicit trailers
+            for ISO9796-2.
+            </summary>
+            <param name="cipher">base cipher to use for signature creation/verification</param>
+            <param name="digest">digest to use.</param>
+            <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest)">
+             <summary> Constructor for a signer with an explicit digest trailer.
+            
+             </summary>
+             <param name="cipher">cipher to use.
+             </param>
+             <param name="digest">digest to sign with.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.IsSameAs(System.Byte[],System.Byte[])">
+            <summary> compare two byte arrays - constant time.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.GenerateSignature">
+            <summary> Generate a signature for the loaded message using the key we were
+            initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.VerifySignature(System.Byte[])">
+            <summary> return true if the signature represents a ISO9796-2 signature
+            for the passed in message.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.HasFullMessage">
+            <summary>
+            Return true if the full message was recoveredMessage.
+            </summary>
+            <returns> true on full message recovery, false otherwise.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage"/>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.PssSigner">
+            <summary> RSA-PSS as described in Pkcs# 1 v 2.1.
+            <p>
+            Note: the usual value for the salt length is the number of
+            bytes in the hash function.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+            <summary>Basic constructor</summary>
+            <param name="cipher">the asymmetric cipher to use.</param>
+            <param name="digest">the digest to use.</param>
+            <param name="saltLen">the length of the salt to use (in bytes).</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.GenerateSignature">
+            <summary> Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.VerifySignature(System.Byte[])">
+            <summary> return true if the internal state represents the signature described
+            in the passed in array.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.ItoOSP(System.Int32,System.Byte[])">
+            <summary> int to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.MaskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary> mask generator function, as described in Pkcs1v2.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.#cctor">
+            <summary>
+            Load oid table.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the signer for signing or verification.
+            
+             @param forSigning true if for signing, false otherwise
+             @param param necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described
+            in the passed in array.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.StreamBlockCipher">
+            a wrapper for block ciphers with a single byte block size, so that they
+            can be treated like stream ciphers.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             basic constructor.
+            
+             @param cipher the block cipher to be wrapped.
+             @exception ArgumentException if the cipher has a block size other than
+             one.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the underlying cipher.
+            
+             @param forEncryption true if we are setting up for encryption, false otherwise.
+             @param param the necessary parameters for the underlying cipher to be initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.ReturnByte(System.Byte)">
+             encrypt/decrypt a single byte returning the result.
+            
+             @param in the byte to be processed.
+             @return the result of processing the input byte.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process a block of bytes from in putting the result into out.
+            
+             @param in the input byte array.
+             @param inOff the offset into the in array where the data to be processed starts.
+             @param len the number of bytes to be processed.
+             @param out the output buffer the processed bytes go into.
+             @param outOff the offset into the output byte array the processed data stars at.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.Reset">
+            reset the underlying cipher. This leaves it in the same state
+            it was at after the last init (if there was one).
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.StreamBlockCipher.AlgorithmName">
+             return the name of the algorithm we are wrapping.
+            
+             @return the name of the algorithm we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAgreementCredentials.GenerateAgreement(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.AbstractTlsAgreementCredentials.GenerateAgreement(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipherFactory.CreateCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.AbstractTlsCipherFactory.CreateCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.ShouldUseGmtUnixTime">
+            <summary>
+            draft-mathewson-no-gmtunixtime-00 2. "If existing users of a TLS implementation may rely on
+            gmt_unix_time containing the current time, we recommend that implementors MAY provide the
+            ability to set gmt_unix_time as an option only, off by default."
+            </summary>
+            <returns>
+            <code>true</code> if the current time should be used in the gmt_unix_time field of
+            Random, or <code>false</code> if gmt_unix_time should contain a cryptographically
+            random value.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.NotifySecureRenegotiation(System.Boolean)">
+            <summary>
+            Report whether the server supports secure renegotiation
+            </summary>
+            <remarks>
+            The protocol handler automatically processes the relevant extensions
+            </remarks>
+            <param name="secureRenegotiation">
+            A <see cref="T:System.Boolean"/>, true if the server supports secure renegotiation
+            </param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.GetCompression">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCompression"/> to handle record compression.
+            </summary>
+            <returns>A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCompression"/></returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.GetCipher">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCipher"/> to use for encryption/decryption.
+            </summary>
+            <returns>A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCipher"/></returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.NotifyAlertRaised(System.Byte,System.Byte,System.String,System.Exception)">
+            <summary>This method will be called when an alert is raised by the protocol.</summary>
+            <param name="alertLevel"><see cref="T:Org.BouncyCastle.Crypto.Tls.AlertLevel"/></param>
+            <param name="alertDescription"><see cref="T:Org.BouncyCastle.Crypto.Tls.AlertDescription"/></param>
+            <param name="message">A human-readable message explaining what caused this alert. May be null.</param>
+            <param name="cause">The <c>Exception</c> that caused this alert to be raised. May be null.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.NotifyAlertReceived(System.Byte,System.Byte)">
+            <summary>This method will be called when an alert is received from the remote peer.</summary>
+            <param name="alertLevel"><see cref="T:Org.BouncyCastle.Crypto.Tls.AlertLevel"/></param>
+            <param name="alertDescription"><see cref="T:Org.BouncyCastle.Crypto.Tls.AlertDescription"/></param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsPeer.NotifyHandshakeComplete">
+            <summary>Notifies the peer that the handshake has been successfully completed.</summary>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.Init(Org.BouncyCastle.Crypto.Tls.TlsClientContext)">
+            <summary>
+            Called at the start of a new TLS session, before any other methods.
+            </summary>
+            <param name="context">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetSessionToResume">
+            <summary>Return the session this client wants to resume, if any.</summary>
+            <remarks>Note that the peer's certificate chain for the session (if any) may need to be periodically revalidated.</remarks>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsSession"/> representing the resumable session to be used for this connection,
+            or null to use a new session.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCipherSuites">
+            <summary>
+            Get the list of cipher suites that this client supports.
+            </summary>
+            <returns>
+            An array of <see cref="T:Org.BouncyCastle.Crypto.Tls.CipherSuite"/> values, each specifying a supported cipher suite.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCompressionMethods">
+            <summary>
+            Get the list of compression methods that this client supports.
+            </summary>
+            <returns>
+            An array of <see cref="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod"/> values, each specifying a supported compression method.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetClientExtensions">
+            <summary>
+            Get the (optional) table of client extensions to be included in (extended) client hello.
+            </summary>
+            <returns>
+            A <see cref="T:System.Collections.IDictionary"/> (Int32 -> byte[]). May be null.
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifyServerVersion(Org.BouncyCastle.Crypto.Tls.ProtocolVersion)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySessionID(System.Byte[])">
+            <summary>
+            Notifies the client of the session_id sent in the ServerHello.
+            </summary>
+            <param name="sessionID">An array of <see cref="T:System.Byte"/></param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySelectedCipherSuite(System.Int32)">
+            <summary>
+            Report the cipher suite that was selected by the server.
+            </summary>
+            <remarks>
+            The protocol handler validates this value against the offered cipher suites
+            <seealso cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCipherSuites"/>
+            </remarks>
+            <param name="selectedCipherSuite">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CipherSuite"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySelectedCompressionMethod(System.Byte)">
+            <summary>
+            Report the compression method that was selected by the server.
+            </summary>
+            <remarks>
+            The protocol handler validates this value against the offered compression methods
+            <seealso cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCompressionMethods"/>
+            </remarks>
+            <param name="selectedCompressionMethod">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.ProcessServerExtensions(System.Collections.IDictionary)">
+            <summary>
+            Report the extensions from an extended server hello.
+            </summary>
+            <remarks>
+            Will only be called if we returned a non-null result from <see cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetClientExtensions"/>.
+            </remarks>
+            <param name="serverExtensions">
+            A <see cref="T:System.Collections.IDictionary"/>  (Int32 -> byte[])
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.ProcessServerSupplementalData(System.Collections.IList)">
+            <param name="serverSupplementalData">A <see cref="T:System.Collections.IList">list</see> of <see cref="T:Org.BouncyCastle.Crypto.Tls.SupplementalDataEntry"/></param>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetKeyExchange">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange"/> to negotiate the key exchange
+            part of the protocol.
+            </summary>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetAuthentication">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsAuthentication"/> to handle authentication
+            part of the protocol.
+            </summary>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetClientSupplementalData">
+            <returns>A <see cref="T:System.Collections.IList">list</see> of <see cref="T:Org.BouncyCastle.Crypto.Tls.SupplementalDataEntry"/></returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifyNewSessionTicket(Org.BouncyCastle.Crypto.Tls.NewSessionTicket)">
+            <summary>RFC 5077 3.3. NewSessionTicket Handshake Message</summary>
+            <remarks>
+            This method will be called (only) when a NewSessionTicket handshake message is received. The
+            ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption
+            that it complies with e.g. <i>RFC 5077 4. Recommended Ticket Construction</i>.
+            </remarks>
+            <param name="newSessionTicket">The <see cref="T:Org.BouncyCastle.Crypto.Tls.NewSessionTicket">ticket</see></param>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.AbstractTlsClient.ClientHelloRecordLayerVersion">
+            RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value
+            {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest
+            version number supported by the client, and the value of ClientHello.client_version. No
+            single value will guarantee interoperability with all old servers, but this is a complex
+            topic beyond the scope of this document."
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsContext.ExportKeyingMaterial(System.String,System.Byte[],System.Int32)">
+             Export keying material according to RFC 5705: "Keying Material Exporters for TLS".
+            
+             @param asciiLabel    indicates which application will use the exported keys.
+             @param context_value allows the application using the exporter to mix its own data with the TLS PRF for
+                                  the exporter output.
+             @param length        the number of bytes to generate
+             @return a pseudorandom bit string of 'length' bytes generated from the master_secret.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsContext.ResumableSession">
+            Used to get the resumable session, if any, used by this connection. Only available after the
+            handshake has successfully completed.
+            
+            @return A {@link TlsSession} representing the resumable session used by this connection, or
+                    null if no resumable session available.
+            @see TlsPeer#NotifyHandshakeComplete()
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsEncryptionCredentials.DecryptPreMasterSecret(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.AbstractTlsEncryptionCredentials.DecryptPreMasterSecret(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange">
+            <summary>
+            A generic interface for key exchange implementations in (D)TLS.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipServerCredentials">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessServerCredentials(Org.BouncyCastle.Crypto.Tls.TlsCredentials)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessServerCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.GenerateServerKeyExchange">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipServerKeyExchange">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessServerKeyExchange(System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ValidateCertificateRequest(Org.BouncyCastle.Crypto.Tls.CertificateRequest)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipClientCredentials">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessClientCredentials(Org.BouncyCastle.Crypto.Tls.TlsCredentials)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessClientCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.GenerateClientKeyExchange(System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessClientKeyExchange(System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.GeneratePremasterSecret">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.NotifyClientVersion(Org.BouncyCastle.Crypto.Tls.ProtocolVersion)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.NotifyOfferedCipherSuites(System.Int32[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.NotifyOfferedCompressionMethods(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.ProcessClientExtensions(System.Collections.IDictionary)">
+            <param name="clientExtensions">A <see cref="T:System.Collections.IDictionary"/> (Int32 -> byte[]). Will never be null.</param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetServerVersion">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetSelectedCipherSuite">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetSelectedCompressionMethod">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetServerExtensions">
+            <summary>
+            Get the (optional) table of server extensions to be included in (extended) server hello.
+            </summary>
+            <returns>
+            A <see cref="T:System.Collections.IDictionary"/> (Int32 -> byte[]). May be null.
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetServerSupplementalData">
+            <returns>
+            A <see cref="T:System.Collections.IList"/> (<see cref="T:Org.BouncyCastle.Crypto.Tls.SupplementalDataEntry"/>). May be null.
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetCredentials">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetCertificateStatus">
+            <remarks>
+            This method will be called (only) if the server included an extension of type
+            "status_request" with empty "extension_data" in the extended server hello. See <i>RFC 3546
+            3.6. Certificate Status Request</i>. If a non-null <see cref="T:Org.BouncyCastle.Crypto.Tls.CertificateStatus"/> is returned, it
+            is sent to the client as a handshake message of type "certificate_status".
+            </remarks>
+            <returns>A <see cref="T:Org.BouncyCastle.Crypto.Tls.CertificateStatus"/> to be sent to the client (or null for none).</returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetKeyExchange">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetCertificateRequest">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.ProcessClientSupplementalData(System.Collections.IList)">
+            <param name="clientSupplementalData"><see cref="T:System.Collections.IList"/> (<see cref="T:Org.BouncyCastle.Crypto.Tls.SupplementalDataEntry"/>)</param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.NotifyClientCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <summary>
+            Called by the protocol handler to report the client certificate, only if <c>GetCertificateRequest</c>
+            returned non-null.
+            </summary>
+            <remarks>Note: this method is responsible for certificate verification and validation.</remarks>
+            <param name="clientCertificate">the effective client certificate (may be an empty chain).</param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServer.GetNewSessionTicket">
+            <summary>RFC 5077 3.3. NewSessionTicket Handshake Message.</summary>
+            <remarks>
+            This method will be called (only) if a NewSessionTicket extension was sent by the server. See
+            <i>RFC 5077 4. Recommended Ticket Construction</i> for recommended format and protection.
+            </remarks>
+            <returns>The <see cref="T:Org.BouncyCastle.Crypto.Tls.NewSessionTicket">ticket</see>)</returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsSignerCredentials.GenerateCertificateSignature(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.AbstractTlsSignerCredentials.GenerateCertificateSignature(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.AlertDescription">
+            <summary>
+            RFC 5246 7.2
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.close_notify">
+            This message notifies the recipient that the sender will not send any more messages on this
+            connection. Note that as of TLS 1.1, failure to properly close a connection no longer
+            requires that a session not be resumed. This is a change from TLS 1.0 ("The session becomes
+            unresumable if any connection is terminated without proper close_notify messages with level
+            equal to warning.") to conform with widespread implementation practice.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unexpected_message">
+            An inappropriate message was received. This alert is always fatal and should never be
+            observed in communication between proper implementations.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.bad_record_mac">
+            This alert is returned if a record is received with an incorrect MAC. This alert also MUST be
+            returned if an alert is sent because a TLSCiphertext decrypted in an invalid way: either it
+            wasn't an even multiple of the block length, or its padding values, when checked, weren't
+            correct. This message is always fatal and should never be observed in communication between
+            proper implementations (except when messages were corrupted in the network).
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.decryption_failed">
+            This alert was used in some earlier versions of TLS, and may have permitted certain attacks
+            against the CBC mode [CBCATT]. It MUST NOT be sent by compliant implementations.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.record_overflow">
+            A TLSCiphertext record was received that had a length more than 2^14+2048 bytes, or a record
+            decrypted to a TLSCompressed record with more than 2^14+1024 bytes. This message is always
+            fatal and should never be observed in communication between proper implementations (except
+            when messages were corrupted in the network).
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.decompression_failure">
+            The decompression function received improper input (e.g., data that would expand to excessive
+            length). This message is always fatal and should never be observed in communication between
+            proper implementations.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.handshake_failure">
+            Reception of a handshake_failure alert message indicates that the sender was unable to
+            negotiate an acceptable set of security parameters given the options available. This is a
+            fatal error.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.no_certificate">
+            This alert was used in SSLv3 but not any version of TLS. It MUST NOT be sent by compliant
+            implementations.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.bad_certificate">
+            A certificate was corrupt, contained signatures that did not verify correctly, etc.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unsupported_certificate">
+            A certificate was of an unsupported type.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.certificate_revoked">
+            A certificate was revoked by its signer.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.certificate_expired">
+            A certificate has expired or is not currently valid.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.certificate_unknown">
+            Some other (unspecified) issue arose in processing the certificate, rendering it
+            unacceptable.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.illegal_parameter">
+            A field in the handshake was out of range or inconsistent with other fields. This message is
+            always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unknown_ca">
+            A valid certificate chain or partial chain was received, but the certificate was not accepted
+            because the CA certificate could not be located or couldn't be matched with a known, trusted
+            CA. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.access_denied">
+            A valid certificate was received, but when access control was applied, the sender decided not
+            to proceed with negotiation. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.decode_error">
+            A message could not be decoded because some field was out of the specified range or the
+            length of the message was incorrect. This message is always fatal and should never be
+            observed in communication between proper implementations (except when messages were corrupted
+            in the network).
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.decrypt_error">
+            A handshake cryptographic operation failed, including being unable to correctly verify a
+            signature or validate a Finished message. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.export_restriction">
+            This alert was used in some earlier versions of TLS. It MUST NOT be sent by compliant
+            implementations.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.protocol_version">
+            The protocol version the client has attempted to negotiate is recognized but not supported.
+            (For example, old protocol versions might be avoided for security reasons.) This message is
+            always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.insufficient_security">
+            Returned instead of handshake_failure when a negotiation has failed specifically because the
+            server requires ciphers more secure than those supported by the client. This message is
+            always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.internal_error">
+            An internal error unrelated to the peer or the correctness of the protocol (such as a memory
+            allocation failure) makes it impossible to continue. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.user_canceled">
+            This handshake is being canceled for some reason unrelated to a protocol failure. If the user
+            cancels an operation after the handshake is complete, just closing the connection by sending
+            a close_notify is more appropriate. This alert should be followed by a close_notify. This
+            message is generally a warning.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.no_renegotiation">
+            Sent by the client in response to a hello request or by the server in response to a client
+            hello after initial handshaking. Either of these would normally lead to renegotiation; when
+            that is not appropriate, the recipient should respond with this alert. At that point, the
+            original requester can decide whether to proceed with the connection. One case where this
+            would be appropriate is where a server has spawned a process to satisfy a request; the
+            process might receive security parameters (key length, authentication, etc.) at startup, and
+            it might be difficult to communicate changes to these parameters after that point. This
+            message is always a warning.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unsupported_extension">
+            Sent by clients that receive an extended server hello containing an extension that they did
+            not put in the corresponding client hello. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.certificate_unobtainable">
+            This alert is sent by servers who are unable to retrieve a certificate chain from the URL
+            supplied by the client (see Section 3.3). This message MAY be fatal - for example if client
+            authentication is required by the server for the handshake to continue and the server is
+            unable to retrieve the certificate chain, it may send a fatal alert.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unrecognized_name">
+            This alert is sent by servers that receive a server_name extension request, but do not
+            recognize the server name. This message MAY be fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.bad_certificate_status_response">
+            This alert is sent by clients that receive an invalid certificate status response (see
+            Section 3.6). This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.bad_certificate_hash_value">
+            This alert is sent by servers when a certificate hash does not match a client provided
+            certificate_hash. This message is always fatal.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.AlertDescription.unknown_psk_identity">
+            If the server does not recognize the PSK identity, it MAY respond with an
+            "unknown_psk_identity" alert message.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.AlertLevel">
+            <summary>
+            RFC 5246 7.2
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.BulkCipherAlgorithm">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ByteQueue">
+            <remarks>
+            A queue for bytes.
+            <p>
+            This file could be more optimized.
+            </p>
+            </remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.DefaultCapacity">
+            The initial size for our buffer.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.NextTwoPow(System.Int32)">
+            <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.databuf">
+            The buffer where we store our data.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.skipped">
+            How many bytes at the beginning of the buffer are skipped.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.available">
+            How many bytes in the buffer are valid data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.Read(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary>Read data from the buffer.</summary>
+            <param name="buf">The buffer where the read data will be copied to.</param>
+            <param name="offset">How many bytes to skip at the beginning of buf.</param>
+            <param name="len">How many bytes to read at all.</param>
+            <param name="skip">How many bytes from our data to skip.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.AddData(System.Byte[],System.Int32,System.Int32)">
+            <summary>Add some data to our buffer.</summary>
+            <param name="data">A byte-array to read data from.</param>
+            <param name="offset">How many bytes to skip at the beginning of the array.</param>
+            <param name="len">How many bytes to read from the array.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.RemoveData(System.Int32)">
+            <summary>Remove some bytes from our data from the beginning.</summary>
+            <param name="i">How many bytes to remove.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.ByteQueue.Available">
+            <summary>The number of bytes which are available in this buffer.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.Certificate">
+             Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
+             <p/>
+             <pre>
+             opaque ASN.1Cert<2^24-1>;
+            
+             struct {
+                 ASN.1Cert certificate_list<0..2^24-1>;
+             } Certificate;
+             </pre>
+            
+             @see Org.BouncyCastle.Asn1.X509.X509CertificateStructure
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.Certificate.mCertificateList">
+            The certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.GetCertificateList">
+            @return an array of {@link org.bouncycastle.asn1.x509.Certificate} representing a certificate
+                    chain.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.Encode(System.IO.Stream)">
+             Encode this {@link Certificate} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.Parse(System.IO.Stream)">
+             Parse a {@link Certificate} from a {@link Stream}.
+            
+             @param input the {@link Stream} to parse from.
+             @return a {@link Certificate} object.
+             @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.Certificate.IsEmpty">
+            @return <code>true</code> if this certificate chain contains no certificates, or
+                    <code>false</code> otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CertificateRequest">
+             Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
+             <p/>
+             <pre>
+             struct {
+                 ClientCertificateType certificate_types<1..2^8-1>;
+                 DistinguishedName certificate_authorities<3..2^16-1>
+             } CertificateRequest;
+             </pre>
+            
+             @see ClientCertificateType
+             @see X509Name
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateRequest.#ctor(System.Byte[],System.Collections.IList,System.Collections.IList)">
+            @param certificateTypes       see {@link ClientCertificateType} for valid constants.
+            @param certificateAuthorities an {@link IList} of {@link X509Name}.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateRequest.Encode(System.IO.Stream)">
+             Encode this {@link CertificateRequest} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateRequest.Parse(Org.BouncyCastle.Crypto.Tls.TlsContext,System.IO.Stream)">
+            Parse a {@link CertificateRequest} from a {@link Stream}.
+            
+            @param context
+                       the {@link TlsContext} of the current connection.
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link CertificateRequest} object.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateRequest.CertificateTypes">
+            @return an array of certificate types
+            @see {@link ClientCertificateType}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateRequest.SupportedSignatureAlgorithms">
+            @return an {@link IList} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateRequest.CertificateAuthorities">
+            @return an {@link IList} of {@link X509Name}
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateStatus.Encode(System.IO.Stream)">
+            Encode this {@link CertificateStatus} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateStatus.Parse(System.IO.Stream)">
+            Parse a {@link CertificateStatus} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link CertificateStatus} object.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateStatusRequest.Encode(System.IO.Stream)">
+            Encode this {@link CertificateStatusRequest} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateStatusRequest.Parse(System.IO.Stream)">
+            Parse a {@link CertificateStatusRequest} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link CertificateStatusRequest} object.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateUrl.#ctor(System.Byte,System.Collections.IList)">
+            @param type
+                       see {@link CertChainType} for valid constants.
+            @param urlAndHashList
+                       a {@link IList} of {@link UrlAndHash}.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateUrl.Encode(System.IO.Stream)">
+             Encode this {@link CertificateUrl} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CertificateUrl.parse(Org.BouncyCastle.Crypto.Tls.TlsContext,System.IO.Stream)">
+            Parse a {@link CertificateUrl} from a {@link Stream}.
+            
+            @param context
+                       the {@link TlsContext} of the current connection.
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link CertificateUrl} object.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateUrl.Type">
+            @return {@link CertChainType}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateUrl.UrlAndHashList">
+            @return an {@link IList} of {@link UrlAndHash} 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipher.EncodePlaintext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipher.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Chacha20Poly1305.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Chacha20Poly1305.EncodePlaintext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Chacha20Poly1305.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Chacha20Poly1305.GetAdditionalData(System.Int64,System.Byte,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CipherSuite">
+            <summary>
+            RFC 2246 A.5
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CipherType">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CombinedHash">
+            A combined hash, which implements md5(m) || sha1(m).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            @see org.bouncycastle.crypto.Digest#update(byte[], int, int)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.DoFinal(System.Byte[],System.Int32)">
+            @see org.bouncycastle.crypto.Digest#doFinal(byte[], int)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.Reset">
+            @see org.bouncycastle.crypto.Digest#reset()
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod">
+            <summary>
+            RFC 2246 6.1
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ConnectionEnd">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ContentType">
+            RFC 2246 6.2.1
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsAgreementCredentials.GenerateAgreement(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateAESCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateCamelliaCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateChaCha20Poly1305(Org.BouncyCastle.Crypto.Tls.TlsContext)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateCipher_Aes_Ccm(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateCipher_Aes_Gcm(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateCipher_Camellia_Gcm(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateDesEdeCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateNullCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateRC4Cipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateSalsa20Cipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateSeedCipher(Org.BouncyCastle.Crypto.Tls.TlsContext,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateHMacDigest(System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsEncryptionCredentials.DecryptPreMasterSecret(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsSignerCredentials.GenerateCertificateSignature(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.DeferredHash">
+            Buffers input until the hash algorithm is determined.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DigitallySigned.Encode(System.IO.Stream)">
+            Encode this {@link DigitallySigned} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DigitallySigned.Parse(Org.BouncyCastle.Crypto.Tls.TlsContext,System.IO.Stream)">
+            Parse a {@link DigitallySigned} from a {@link Stream}.
+            
+            @param context
+                       the {@link TlsContext} of the current connection.
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link DigitallySigned} object.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.DigitallySigned.Algorithm">
+            @return a {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ECBasisType">
+            <summary>RFC 4492 5.4. (Errata ID: 2389)</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ECCurveType">
+            <summary>
+            RFC 4492 5.4
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.explicit_prime">
+            Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+            underlying finite field is a prime field.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.explicit_char2">
+            Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+            underlying finite field is a characteristic-2 field.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.named_curve">
+            Indicates that a named curve is used. This option SHOULD be used when applicable.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ECPointFormat">
+            <summary>
+            RFC 4492 5.1.2
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.EncryptionAlgorithm">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ExporterLabel">
+            <summary>RFC 5705</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.HashAlgorithm">
+            <summary>RFC 5246 7.4.1.4.1</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.HeartbeatExtension.Encode(System.IO.Stream)">
+            Encode this {@link HeartbeatExtension} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.HeartbeatExtension.Parse(System.IO.Stream)">
+            Parse a {@link HeartbeatExtension} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link HeartbeatExtension} object.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.HeartbeatMessage.Encode(Org.BouncyCastle.Crypto.Tls.TlsContext,System.IO.Stream)">
+            Encode this {@link HeartbeatMessage} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.HeartbeatMessage.Parse(System.IO.Stream)">
+            Parse a {@link HeartbeatMessage} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link HeartbeatMessage} object.
+            @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.KeyExchangeAlgorithm">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.MacAlgorithm">
+            <summary>RFC 2246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.NamedCurve">
+            <summary>
+            RFC 4492 5.1.1
+            The named curves defined here are those specified in SEC 2 [13]. Note that many of
+            these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
+            through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
+            client supports arbitrary prime and characteristic-2 curves, respectively (the curve
+            parameters must be encoded explicitly in ECParameters).
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.NewSessionTicket.Encode(System.IO.Stream)">
+             Encode this {@link NewSessionTicket} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.NewSessionTicket.Parse(System.IO.Stream)">
+             Parse a {@link NewSessionTicket} from a {@link Stream}.
+            
+             @param input the {@link Stream} to parse from.
+             @return a {@link NewSessionTicket} object.
+             @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest">
+            RFC 3546 3.6
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest.#ctor(System.Collections.IList,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+            @param responderIDList
+                       an {@link IList} of {@link ResponderID}, specifying the list of trusted OCSP
+                       responders. An empty list has the special meaning that the responders are
+                       implicitly known to the server - e.g., by prior arrangement.
+            @param requestExtensions
+                       OCSP request extensions. A null value means that there are no extensions.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest.Encode(System.IO.Stream)">
+            Encode this {@link OcspStatusRequest} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest.Parse(System.IO.Stream)">
+            Parse a {@link OcspStatusRequest} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return an {@link OcspStatusRequest} object.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest.ResponderIDList">
+            @return an {@link IList} of {@link ResponderID}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.OcspStatusRequest.RequestExtensions">
+            @return OCSP request extensions
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.PrfAlgorithm">
+            <summary>RFC 5246</summary>
+            <remarks>
+            Note that the values here are implementation-specific and arbitrary. It is recommended not to
+            depend on the particular values (e.g. serialization).
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ProtocolVersion.Get(System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.RecordStream">
+            <summary>An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.RecordStream.SetRestrictReadVersion(System.Boolean)">
+            RFC 5246 E.1. "Earlier versions of the TLS specification were not fully clear on what the
+            record layer version number (TLSPlaintext.version) should contain when sending ClientHello
+            (i.e., before it is known which version of the protocol will be employed). Thus, TLS servers
+            compliant with this specification MUST accept any value {03,XX} as the record layer version
+            number for ClientHello."
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SecurityParameters.Entity">
+            @return {@link ConnectionEnd}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SecurityParameters.CipherSuite">
+            @return {@link CipherSuite}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SecurityParameters.CompressionAlgorithm">
+            @return {@link CompressionMethod}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SecurityParameters.PrfAlgorithm">
+            @return {@link PRFAlgorithm}
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerDHParams.Encode(System.IO.Stream)">
+            Encode this {@link ServerDHParams} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerDHParams.Parse(System.IO.Stream)">
+            Parse a {@link ServerDHParams} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link ServerDHParams} object.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerName.Encode(System.IO.Stream)">
+            Encode this {@link ServerName} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerName.Parse(System.IO.Stream)">
+            Parse a {@link ServerName} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link ServerName} object.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerNameList.#ctor(System.Collections.IList)">
+            @param serverNameList an {@link IList} of {@link ServerName}.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerNameList.Encode(System.IO.Stream)">
+            Encode this {@link ServerNameList} to a {@link Stream}.
+            
+            @param output
+                       the {@link Stream} to encode to.
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ServerNameList.Parse(System.IO.Stream)">
+            Parse a {@link ServerNameList} from a {@link Stream}.
+            
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link ServerNameList} object.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.ServerNameList.ServerNames">
+            @return an {@link IList} of {@link ServerName}.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAuthentication.NotifyServerCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <summary>
+            Called by the protocol handler to report the server certificate.
+            </summary>
+            <remarks>
+            This method is responsible for certificate verification and validation
+            </remarks>
+            <param name="serverCertificate">The server <see cref="T:Org.BouncyCastle.Crypto.Tls.Certificate"/> received</param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAuthentication.GetClientCredentials(Org.BouncyCastle.Crypto.Tls.CertificateRequest)">
+            <summary>
+            Return client credentials in response to server's certificate request
+            </summary>
+            <param name="certificateRequest">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CertificateRequest"/> containing server certificate request details
+            </param>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCredentials"/> to be used for client authentication
+            (or <c>null</c> for no client authentication)
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.SignatureAlgorithm">
+            RFC 5246 7.4.1.4.1 (in RFC 2246, there were no specific values assigned)
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm">
+            RFC 5246 7.4.1.4.1
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm.#ctor(System.Byte,System.Byte)">
+            @param hash      {@link HashAlgorithm}
+            @param signature {@link SignatureAlgorithm}
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm.Encode(System.IO.Stream)">
+             Encode this {@link SignatureAndHashAlgorithm} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm.Parse(System.IO.Stream)">
+             Parse a {@link SignatureAndHashAlgorithm} from a {@link Stream}.
+            
+             @param input the {@link Stream} to parse from.
+             @return a {@link SignatureAndHashAlgorithm} object.
+             @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm.Hash">
+            @return {@link HashAlgorithm}
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.SignatureAndHashAlgorithm.Signature">
+            @return {@link SignatureAlgorithm}
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.Ssl3Mac">
+            HMAC implementation based on original internet draft for HMAC (RFC 2104)
+            
+            The difference is that padding is concatentated versus XORed with the key
+            
+            H(K + opad, H(K + ipad, text))
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Ssl3Mac.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+            Base constructor for one of the standard digest algorithms that the byteLength of
+            the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
+            
+            @param digest the digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Ssl3Mac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.SupplementalDataType">
+            <summary>RFC 4680</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAeadCipher.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher,Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher,System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAeadCipher.EncodePlaintext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAeadCipher.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAeadCipher.GetAdditionalData(System.Int64,System.Byte,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsBlockCipher">
+            <summary>
+            A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsBlockCipher.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsBlockCipher.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.ProcessChangeCipherSpec(System.Byte[],System.Int32,System.Int32)">
+             This method is called, when a change cipher spec message is received.
+            
+             @throws IOException If the message has an invalid content or the handshake is not in the correct
+             state.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.ReadApplicationData(System.Byte[],System.Int32,System.Int32)">
+             Read data from the network. The method will return immediately, if there is still some data
+             left in the buffer, or block until some application data has been read from the network.
+            
+             @param buf    The buffer where the data will be copied to.
+             @param offset The position where the data will be placed in the buffer.
+             @param len    The maximum number of bytes to read.
+             @return The number of bytes read.
+             @throws IOException If something goes wrong during reading data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.WriteData(System.Byte[],System.Int32,System.Int32)">
+             Send some application data to the remote system.
+             <p/>
+             The method will handle fragmentation internally.
+            
+             @param buf    The buffer with the data.
+             @param offset The position in the buffer where the data is placed.
+             @param len    The length of the data.
+             @throws IOException If something goes wrong during sending.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.FailWithError(System.Byte,System.Byte,System.String,System.Exception)">
+            Terminate this connection with an alert. Can be used for normal closure too.
+            
+            @param alertLevel
+                       See {@link AlertLevel} for values.
+            @param alertDescription
+                       See {@link AlertDescription} for values.
+            @throws IOException
+                        If alert was fatal.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.Close">
+             Closes this connection.
+            
+             @throws IOException If something goes wrong during closing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.AssertEmpty(System.IO.MemoryStream)">
+             Make sure the InputStream 'buf' now empty. Fail otherwise.
+            
+             @param buf The InputStream to check.
+             @throws IOException If 'buf' is not empty.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocol.GetCurrentPrfHash(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.Tls.TlsHandshakeHash,System.Byte[])">
+            'sender' only relevant to SSLv3
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsProtocol.Stream">
+            <summary>The secure bidirectional stream for this connection</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClientProtocol.Connect(Org.BouncyCastle.Crypto.Tls.TlsClient)">
+             Initiates a TLS handshake in the role of client
+            
+             @param tlsClient The {@link TlsClient} to use for the handshake.
+             @throws IOException If handshake was not successful.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsDHKeyExchange">
+            <summary>(D)TLS DH key exchange.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsECDheKeyExchange">
+            <summary>(D)TLS ECDHE key exchange (see RFC 4492).</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsECDHKeyExchange">
+            <summary>(D)TLS ECDH key exchange (see RFC 4492).</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.AddHeartbeatExtension(System.Collections.IDictionary,Org.BouncyCastle.Crypto.Tls.HeartbeatExtension)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.AddMaxFragmentLengthExtension(System.Collections.IDictionary,System.Byte)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.AddServerNameExtension(System.Collections.IDictionary,Org.BouncyCastle.Crypto.Tls.ServerNameList)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.AddStatusRequestExtension(System.Collections.IDictionary,Org.BouncyCastle.Crypto.Tls.CertificateStatusRequest)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.GetHeartbeatExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.GetMaxFragmentLengthExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.GetServerNameExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.GetStatusRequestExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.HasEncryptThenMacExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.HasTruncatedHMacExtension(System.Collections.IDictionary)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.CreateHeartbeatExtension(Org.BouncyCastle.Crypto.Tls.HeartbeatExtension)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.CreateMaxFragmentLengthExtension(System.Byte)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.CreateServerNameExtension(Org.BouncyCastle.Crypto.Tls.ServerNameList)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.CreateStatusRequestExtension(Org.BouncyCastle.Crypto.Tls.CertificateStatusRequest)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadEmptyExtensionData(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadEncryptThenMacExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadHeartbeatExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadMaxFragmentLengthExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadServerNameExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadStatusRequestExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsExtensionsUtilities.ReadTruncatedHMacExtension(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsMac">
+            <summary>
+            A generic TLS MAC implementation, acting as an HMAC based on some underlying Digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.IDigest,System.Byte[],System.Int32,System.Int32)">
+             Generate a new instance of an TlsMac.
+            
+             @param context the TLS client context
+             @param digest  The digest to use.
+             @param key     A byte-array where the key for this MAC is located.
+             @param keyOff  The number of bytes to skip, before the key starts in the buffer.
+             @param keyLen  The length of the key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.CalculateMac(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+             Calculate the MAC for some given data.
+            
+             @param type    The message type of the message.
+             @param message A byte-buffer containing the message.
+             @param offset  The number of bytes to skip, before the message starts.
+             @param length  The length of the message.
+             @return A new byte-buffer containing the MAC value.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsMac.MacSecret">
+            @return the MAC write secret
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsMac.Size">
+            @return The output length of this MAC.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsNullCipher">
+            <summary>
+            A NULL CipherSuite, with optional MAC.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsNullCipher.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Crypto.IDigest)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsNullCipher.EncodePlaintext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsNullCipher.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.#ctor(System.IO.Stream,System.IO.Stream,Org.BouncyCastle.Security.SecureRandom)">
+            <remarks>Both streams can be the same object</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsPskKeyExchange">
+            <summary>(D)TLS PSK key exchange (RFC 4279).</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsRsaKeyExchange">
+            <summary>(D)TLS and SSLv3 RSA key exchange.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsRsaUtilities.GenerateEncryptedPreMasterSecret(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.Parameters.RsaKeyParameters,System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsServerProtocol.Accept(Org.BouncyCastle.Crypto.Tls.TlsServer)">
+             Receives a TLS handshake in the role of server
+            
+             @param mTlsServer
+             @throws IOException If handshake was not successful.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsSrpKeyExchange">
+            <summary>(D)TLS SRP key exchange (RFC 5054).</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsSRTPUtils">
+            RFC 5764 DTLS Extension to Establish Keys for SRTP.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsStreamCipher.#ctor(Org.BouncyCastle.Crypto.Tls.TlsContext,Org.BouncyCastle.Crypto.IStreamCipher,Org.BouncyCastle.Crypto.IStreamCipher,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Crypto.IDigest,System.Int32,System.Boolean)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsStreamCipher.DecodeCiphertext(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsStreamCipher.CheckMac(System.Int64,System.Byte,System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsUtilities">
+            <remarks>Some helper functions for MicroTLS.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsUtilities.AddSignatureAlgorithmsExtension(System.Collections.IDictionary,System.Collections.IList)">
+             Add a 'signature_algorithms' extension to existing extensions.
+            
+             @param extensions                   A {@link Hashtable} to add the extension to.
+             @param supportedSignatureAlgorithms {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsUtilities.GetSignatureAlgorithmsExtension(System.Collections.IDictionary)">
+             Get a 'signature_algorithms' extension from extensions.
+            
+             @param extensions A {@link Hashtable} to get the extension from, if it is present.
+             @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}, or null.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsUtilities.CreateSignatureAlgorithmsExtension(System.Collections.IList)">
+             Create a 'signature_algorithms' extension value.
+            
+             @param supportedSignatureAlgorithms A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+             @return A byte array suitable for use as an extension value.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsUtilities.ReadSignatureAlgorithmsExtension(System.Byte[])">
+             Read 'signature_algorithms' extension data.
+            
+             @param extensionData The extension data.
+             @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+             @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.UrlAndHash">
+            RFC 6066 5.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.UrlAndHash.Encode(System.IO.Stream)">
+             Encode this {@link UrlAndHash} to a {@link Stream}.
+            
+             @param output the {@link Stream} to encode to.
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.UrlAndHash.Parse(Org.BouncyCastle.Crypto.Tls.TlsContext,System.IO.Stream)">
+            Parse a {@link UrlAndHash} from a {@link Stream}.
+            
+            @param context
+                       the {@link TlsContext} of the current connection.
+            @param input
+                       the {@link Stream} to parse from.
+            @return a {@link UrlAndHash} object.
+            @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.UserMappingType">
+            <remarks>RFC 4681</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.UseSrtpData">
+            RFC 5764 4.1.1
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.UseSrtpData.#ctor(System.Int32[],System.Byte[])">
+            @param protectionProfiles see {@link SrtpProtectionProfile} for valid constants.
+            @param mki                valid lengths from 0 to 255.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.UseSrtpData.ProtectionProfiles">
+            @return see {@link SrtpProtectionProfile} for valid constants.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.UseSrtpData.Mki">
+            @return valid lengths from 0 to 255.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.AddMagnitudes(System.Int32[],System.Int32[])">
+            return a = a + b - b preserved.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.CompareTo(System.Int32,System.Int32[],System.Int32,System.Int32[])">
+            unsigned comparison on two arrays - note the arrays may
+            start with leading zeros.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Divide(System.Int32[],System.Int32[])">
+            return z = x / y - done in place (z value preserved, x contains the
+            remainder)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.IsProbablePrime(System.Int32)">
+            return whether or not a BigInteger is probably prime with a
+            probability of 1 - (1/2)**certainty.
+            <p>From Knuth Vol 2, pg 395.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ExtEuclid(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger@)">
+             Calculate the numbers u1, u2, and u3 such that:
+            
+             u1 * a + u2 * b = u3
+            
+             where u3 is the greatest common divider of a and b.
+             a and b using the extended Euclid algorithm (refer p. 323
+             of The Art of Computer Programming vol 2, 2nd ed).
+             This also seems to have the side effect of calculating
+             some form of multiplicative inverse.
+            
+             @param a    First number to calculate gcd for
+             @param b    Second number to calculate gcd for
+             @param u1Out      the return object for the u1 value
+             @return     The greatest common divisor of a and b
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Square(System.Int32[],System.Int32[])">
+            return w with w = x * x - w is assumed to have enough space.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Multiply(System.Int32[],System.Int32[],System.Int32[])">
+            return x with x = y * z - x is assumed to have enough space.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.GetMQuote">
+            Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.MultiplyMonty(System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.UInt32,System.Boolean)">
+            Montgomery multiplication: a = x * y * R^(-1) mod m
+            <br/>
+            Based algorithm 14.36 of Handbook of Applied Cryptography.
+            <br/>
+            <li> m, x, y should have length n </li>
+            <li> a should have length (n + 1) </li>
+            <li> b = 2^32, R = b^n </li>
+            <br/>
+            The result is put in x
+            <br/>
+            NOTE: the indices of x, y, m, a different in HAC and in Java
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Remainder(System.Int32[],System.Int32[])">
+            return x = x % y - done in place (y value preserved)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftLeft(System.Int32[],System.Int32)">
+            do a left shift - this returns a new array.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftRightInPlace(System.Int32,System.Int32[],System.Int32)">
+            do a right shift - this does it in place.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftRightOneInPlace(System.Int32,System.Int32[])">
+            do a right shift by one - this does it in place.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Subtract(System.Int32,System.Int32[],System.Int32,System.Int32[])">
+            returns x = x - y - we assume x is >= y
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal">
+            Class representing a simple version of a big decimal. A
+            <code>SimpleBigDecimal</code> is basically a
+            {@link java.math.BigInteger BigInteger} with a few digits on the right of
+            the decimal point. The number of (binary) digits on the right of the decimal
+            point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
+            Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
+            automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
+            taking part in the same arithmetic operation must have equal scale. The
+            result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
+            <code>SimpleBigDecimal</code> with double scale.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal.GetInstance(Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            Returns a <code>SimpleBigDecimal</code> representing the same numerical
+            value as <code>value</code>.
+            @param value The value of the <code>SimpleBigDecimal</code> to be
+            created. 
+            @param scale The scale of the <code>SimpleBigDecimal</code> to be
+            created. 
+            @return The such created <code>SimpleBigDecimal</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal.#ctor(Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            Constructor for <code>SimpleBigDecimal</code>. The value of the
+            constructed <code>SimpleBigDecimal</code> Equals <code>bigInt / 
+            2<sup>scale</sup></code>.
+            @param bigInt The <code>bigInt</code> value parameter.
+            @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.Tnaf">
+            Class holding methods for point multiplication based on the window
+            τ-adic nonadjacent form (WTNAF). The algorithms are based on the
+            paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
+            by Jerome A. Solinas. The paper first appeared in the Proceedings of
+            Crypto 1997.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Width">
+            The window width of WTNAF. The standard value of 4 is slightly less
+            than optimal for running time, but keeps space requirements for
+            precomputation low. For typical curves, a value of 5 or 6 results in
+            a better running time. When changing this value, the
+            <code>α<sub>u</sub></code>'s must be computed differently, see
+            e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
+            Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
+            p. 121-122
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Pow2Width">
+            2<sup>4</sup>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha0">
+            The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+            of <code>ZTauElement</code>s.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha0Tnaf">
+            The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+            of TNAFs.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha1">
+            The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+            of <code>ZTauElement</code>s.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha1Tnaf">
+            The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+            of TNAFs.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Norm(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Computes the norm of an element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return The norm of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Norm(System.SByte,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal)">
+            Computes the norm of an element <code>λ</code> of
+            <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code>
+            and <code>u</code> and <code>u</code> are real numbers (elements of
+            <code><b>R</b></code>). 
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param u The real part of the element <code>λ</code> of
+            <code><b>R</b>[τ]</code>.
+            @param v The <code>τ</code>-adic part of the element
+            <code>λ</code> of <code><b>R</b>[τ]</code>.
+            @return The norm of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Round(Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,System.SByte)">
+            Rounds an element <code>λ</code> of <code><b>R</b>[τ]</code>
+            to an element of <code><b>Z</b>[τ]</code>, such that their difference
+            has minimal norm. <code>λ</code> is given as
+            <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>.
+            @param lambda0 The component <code>λ<sub>0</sub></code>.
+            @param lambda1 The component <code>λ<sub>1</sub></code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve. Must
+            equal 1 or -1.
+            @return The rounded element of <code><b>Z</b>[τ]</code>.
+            @throws ArgumentException if <code>lambda0</code> and
+            <code>lambda1</code> do not have same scale.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.ApproximateDivisionByN(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.SByte,System.Int32,System.Int32)">
+            Approximate division by <code>n</code>. For an integer
+            <code>k</code>, the value <code>λ = s k / n</code> is
+            computed to <code>c</code> bits of accuracy.
+            @param k The parameter <code>k</code>.
+            @param s The curve parameter <code>s<sub>0</sub></code> or
+            <code>s<sub>1</sub></code>.
+            @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @param m The bit length of the finite field
+            <code><b>F</b><sub>m</sub></code>.
+            @param c The number of bits of accuracy, i.e. the scale of the returned
+            <code>SimpleBigDecimal</code>.
+            @return The value <code>λ = s k / n</code> computed to
+            <code>c</code> bits of accuracy.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.TauAdicNaf(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Computes the <code>τ</code>-adic NAF (non-adjacent form) of an
+            element <code>λ</code> of <code><b>Z</b>[τ]</code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return The <code>τ</code>-adic NAF of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Tau(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Applies the operation <code>τ()</code> to an
+            <code>F2mPoint</code>. 
+            @param p The F2mPoint to which <code>τ()</code> is applied.
+            @return <code>τ(p)</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetMu(Org.BouncyCastle.Math.EC.F2mCurve)">
+            Returns the parameter <code>μ</code> of the elliptic curve.
+            @param curve The elliptic curve from which to obtain <code>μ</code>.
+            The curve must be a Koblitz curve, i.e. <code>a</code> Equals
+            <code>0</code> or <code>1</code> and <code>b</code> Equals
+            <code>1</code>. 
+            @return <code>μ</code> of the elliptic curve.
+            @throws ArgumentException if the given ECCurve is not a Koblitz
+            curve.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetLucas(System.SByte,System.Int32,System.Boolean)">
+            Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
+            <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
+            <code>V<sub>k</sub></code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param k The index of the second element of the Lucas Sequence to be
+            returned.
+            @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
+            <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
+            <code>U<sub>k</sub></code>.
+            @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
+            and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
+            and <code>V<sub>k</sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetTw(System.SByte,System.Int32)">
+            Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
+            4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
+            <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code> 
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param w The window width of the WTNAF.
+            @return the auxiliary value <code>t<sub>w</sub></code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetSi(Org.BouncyCastle.Math.EC.F2mCurve)">
+            Computes the auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction. 
+            @param curve The elliptic curve for which to compute
+            <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
+            @throws ArgumentException if <code>curve</code> is not a
+            Koblitz curve (Anomalous Binary Curve, ABC).
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.PartModReduction(Org.BouncyCastle.Math.BigInteger,System.Int32,System.SByte,Org.BouncyCastle.Math.BigInteger[],System.SByte,System.SByte)">
+            Partial modular reduction modulo
+            <code>(τ<sup>m</sup> - 1)/(τ - 1)</code>.
+            @param k The integer to be reduced.
+            @param m The bitlength of the underlying finite field.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @param s The auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code>.
+            @param mu The parameter μ of the elliptic curve.
+            @param c The precision (number of bits of accuracy) of the partial
+            modular reduction.
+            @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 1)</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyRTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.BigInteger)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by a <code>BigInteger</code> using the reduced <code>τ</code>-adic
+            NAF (RTNAF) method.
+            @param p The F2mPoint to Multiply.
+            @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
+            @return <code>k * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the <code>τ</code>-adic NAF (TNAF) method.
+            @param p The F2mPoint to Multiply.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return <code>λ * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyFromTnaf(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte[])">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
+            of <code>λ</code>.
+            @param p The F2mPoint to Multiply.
+            @param u The the TNAF of <code>λ</code>..
+            @return <code>λ * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.TauAdicWNaf(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement,System.SByte,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Abc.ZTauElement[])">
+            Computes the <code>[τ]</code>-adic window NAF of an element
+            <code>λ</code> of <code><b>Z</b>[τ]</code>.
+            @param mu The parameter μ of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code> of which to compute the
+            <code>[τ]</code>-adic NAF.
+            @param width The window width of the resulting WNAF.
+            @param pow2w 2<sup>width</sup>.
+            @param tw The auxiliary value <code>t<sub>w</sub></code>.
+            @param alpha The <code>α<sub>u</sub></code>'s for the window width.
+            @return The <code>[τ]</code>-adic window NAF of
+            <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetPreComp(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte)">
+            Does the precomputation for WTNAF multiplication.
+            @param p The <code>ECPoint</code> for which to do the precomputation.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @return The precomputation array for <code>p</code>. 
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.ZTauElement">
+            Class representing an element of <code><b>Z</b>[τ]</code>. Let
+            <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then
+            <code>λ</code> is given as <code>λ = u + vτ</code>. The
+            components <code>u</code> and <code>v</code> may be used directly, there
+            are no accessor methods.
+            Immutable class.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.ZTauElement.u">
+            The "real" part of <code>λ</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.ZTauElement.v">
+            The "<code>τ</code>-adic" part of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.ZTauElement.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for an element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @param u The "real" part of <code>λ</code>.
+            @param v The "<code>τ</code>-adic" part of
+            <code>λ</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.ECCurve">
+            <remarks>Base class for an elliptic curve.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECCurve.SetPreCompInfo(Org.BouncyCastle.Math.EC.ECPoint,System.String,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
+            <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
+            by subsequent multiplication.
+            
+            @param point
+                       The <code>ECPoint</code> to store precomputations for.
+            @param name
+                       A <code>String</code> used to index precomputations of different types.
+            @param preCompInfo
+                       The values precomputed by the <code>ECMultiplier</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECCurve.NormalizeAll(Org.BouncyCastle.Math.EC.ECPoint[])">
+            Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+            coordinates reflect those of the equivalent point in an affine coordinate system. Where more
+            than one point is to be normalized, this method will generally be more efficient than
+            normalizing each point separately.
+            
+            @param points
+                       An array of points that will be updated in place with their normalized versions,
+                       where necessary
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECCurve.GetMultiplier">
+            Sets the default <code>ECMultiplier</code>, unless already set. 
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECCurve.DecodePoint(System.Byte[])">
+            Decode a point on this curve from its ASN.1 encoding. The different
+            encodings are taken account of, including point compression for
+            <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
+            @return The decoded point.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Djb.Curve25519FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.ECPoint">
+            base class for points on elliptic curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPoint.Normalize">
+            Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+            coordinates reflect those of the equivalent point in an affine coordinate system.
+            
+            @return a new ECPoint instance representing the same point, but with normalized coordinates
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.X">
+            Normalizes this point, and then returns the affine x-coordinate.
+            
+            Note: normalization can be expensive, this method is deprecated in favour
+            of caller-controlled normalization.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.Y">
+            Normalizes this point, and then returns the affine y-coordinate.
+            
+            Note: normalization can be expensive, this method is deprecated in favour
+            of caller-controlled normalization.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.AffineXCoord">
+            Returns the affine x-coordinate after checking that this point is normalized.
+            
+            @return The affine x-coordinate of this point
+            @throws IllegalStateException if the point is not normalized
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.AffineYCoord">
+            Returns the affine y-coordinate after checking that this point is normalized
+            
+            @return The affine y-coordinate of this point
+            @throws IllegalStateException if the point is not normalized
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.XCoord">
+            Returns the x-coordinate.
+            
+            Caution: depending on the curve's coordinate system, this may not be the same value as in an
+            affine coordinate system; use Normalize() to get a point where the coordinates have their
+            affine values, or use AffineXCoord if you expect the point to already have been normalized.
+            
+            @return the x-coordinate of this point
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.ECPoint.YCoord">
+            Returns the y-coordinate.
+            
+            Caution: depending on the curve's coordinate system, this may not be the same value as in an
+            affine coordinate system; use Normalize() to get a point where the coordinates have their
+            affine values, or use AffineYCoord if you expect the point to already have been normalized.
+            
+            @return the y-coordinate of this point
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPointBase.GetEncoded(System.Boolean)">
+            return the field element encoded with point compression. (S 4.3.6)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPointBase.Multiply(Org.BouncyCastle.Math.BigInteger)">
+            Multiplies this <code>ECPoint</code> by the given number.
+            @param k The multiplicator.
+            @return <code>k * this</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Djb.Curve25519Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve the curve to use
+            @param x affine x co-ordinate
+            @param y affine y co-ordinate
+            
+            @deprecated Use ECCurve.CreatePoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Djb.Curve25519Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve the curve to use
+            @param x affine x co-ordinate
+            @param y affine y co-ordinate
+            @param withCompression if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192K1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192R1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP192R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224K1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224R1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP224R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256K1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256K1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256R1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP256R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP384R1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP384R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP384R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP521R1FieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation returns the right value - if
+            none exists it returns null.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP521R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Create a point which encodes with point compression.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            
+            @deprecated Use ECCurve.createPoint to construct points
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Custom.Sec.SecP521R1Point.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            Create a point that encodes with or without point compresion.
+            
+            @param curve
+                       the curve to use
+            @param x
+                       affine x co-ordinate
+            @param y
+                       affine y co-ordinate
+            @param withCompression
+                       if true encode with point compression
+            
+            @deprecated per-point compression property will be removed, refer
+                        {@link #getEncoded(bool)}
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECAlgorithms.ReferenceMultiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Simple shift-and-add multiplication. Serves as reference implementation
+            to verify (possibly faster) implementations, and for very small scalars.
+            
+            @param p
+                       The point to multiply.
+            @param k
+                       The multiplier.
+            @return The result of the point multiplication <code>kP</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.FpCurve">
+            Elliptic curve over Fp
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mCurve">
+            Elliptic curves over F2m. The Weierstrass equation is given by
+            <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.m">
+            The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k1">
+            TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction polynomial
+            <code>f(z)</code>.<br/>
+            PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k2">
+            TPB: Always set to <code>0</code><br/>
+            PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k3">
+            TPB: Always set to <code>0</code><br/>
+            PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.m_infinity">
+            The point at infinity on this curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.mu">
+            The parameter <code>μ</code> of the elliptic curve if this is
+            a Koblitz curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.si">
+            The auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction for
+            Koblitz curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Trinomial Polynomial Basis (TPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Trinomial Polynomial Basis (TPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param order The order of the main subgroup of the elliptic curve.
+            @param cofactor The cofactor of the elliptic curve, i.e.
+            <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Pentanomial Polynomial Basis (PPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Pentanomial Polynomial Basis (PPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param order The order of the main subgroup of the elliptic curve.
+            @param cofactor The cofactor of the elliptic curve, i.e.
+            <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.GetMu">
+            Returns the parameter <code>μ</code> of the elliptic curve.
+            @return <code>μ</code> of the elliptic curve.
+            @throws ArgumentException if the given ECCurve is not a
+            Koblitz curve.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.GetSi">
+            @return the auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction for
+            Koblitz curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.SolveQuadradicEquation(Org.BouncyCastle.Math.EC.ECFieldElement)">
+             Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+             D.1.6) The other solution is <code>z + 1</code>.
+            
+             @param beta
+                        The value to solve the qradratic equation for.
+             @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+                     <code>null</code> if no solution exists.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.IsTrinomial">
+             Return true if curve uses a Trinomial basis.
+            
+             @return true if curve Trinomial, false otherwise.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mCurve.IsKoblitz">
+            Returns true if this is a Koblitz curve (ABC curve).
+            @return true if this is a Koblitz curve (ABC curve), false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpFieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation
+            returns the right value - if none exists it returns null.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.FpFieldElement.FieldName">
+             return the field name for this field.
+            
+             @return the string "Fp".
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mFieldElement">
+            Class representing the Elements of the finite field
+            <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
+            representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
+            basis representations are supported. Gaussian normal basis (GNB)
+            representation is not supported.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Gnb">
+            Indicates gaussian normal basis representation (GNB). Number chosen
+            according to X9.62. GNB is not implemented at present.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Tpb">
+            Indicates trinomial basis representation (Tpb). Number chosen
+            according to X9.62.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Ppb">
+            Indicates pentanomial basis representation (Ppb). Number chosen
+            according to X9.62.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.representation">
+            Tpb or Ppb.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.m">
+            The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.x">
+            The <code>LongArray</code> holding the bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Ppb.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param x The BigInteger representing the value of the field element.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Tpb.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param x The BigInteger representing the value of the field element.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.CheckFieldElements(Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Checks, if the ECFieldElements <code>a</code> and <code>b</code>
+            are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
+            (having the same representation).
+            @param a field element.
+            @param b field element to be compared.
+            @throws ArgumentException if <code>a</code> and <code>b</code>
+            are not elements of the same field
+            <code>F<sub>2<sup>m</sup></sub></code> (having the same
+            representation).
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.Representation">
+            @return the representation of the field
+            <code>F<sub>2<sup>m</sup></sub></code>, either of
+            {@link F2mFieldElement.Tpb} (trinomial
+            basis representation) or
+            {@link F2mFieldElement.Ppb} (pentanomial
+            basis representation).
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.M">
+            @return the degree <code>m</code> of the reduction polynomial
+            <code>f(z)</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K1">
+            @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction polynomial
+            <code>f(z)</code>.<br/>
+            Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K2">
+            @return Tpb: Always returns <code>0</code><br/>
+            Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K3">
+            @return Tpb: Always set to <code>0</code><br/>
+            Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.FpPoint">
+            Elliptic curve points over Fp
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+             Create a point which encodes without point compression.
+            
+             @param curve the curve to use
+             @param x affine x co-ordinate
+             @param y affine y co-ordinate
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+             Create a point that encodes with or without point compression.
+            
+             @param curve the curve to use
+             @param x affine x co-ordinate
+             @param y affine y co-ordinate
+             @param withCompression if true encode with point compression
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mPoint">
+            Elliptic curve points over F2m
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            @param curve base curve
+            @param x x point
+            @param y y point
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            @param curve base curve
+            @param x x point
+            @param y y point
+            @param withCompression true if encode with point compression.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve)">
+            Constructor for point at infinity
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.CheckPoints(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.EC.ECPoint)">
+            Check, if two <code>ECPoint</code>s can be added or subtracted.
+            @param a The first <code>ECPoint</code> to check.
+            @param b The second <code>ECPoint</code> to check.
+            @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+            cannot be added.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.AddSimple(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Adds another <code>ECPoints.F2m</code> to <code>this</code> without
+            checking if both points are on the same curve. Used by multiplication
+            algorithms, because there all points are a multiple of the same point
+            and hence the checks can be omitted.
+            @param b The other <code>ECPoints.F2m</code> to add to
+            <code>this</code>.
+            @return <code>this + b</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.SubtractSimple(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
+            without checking if both points are on the same curve. Used by
+            multiplication algorithms, because there all points are a multiple
+            of the same point and hence the checks can be omitted.
+            @param b The other <code>ECPoints.F2m</code> to subtract from
+            <code>this</code>.
+            @return <code>this - b</code>
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.ECMultiplier">
+            Interface for classes encapsulating a point multiplication algorithm
+            for <code>ECPoint</code>s.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.ECMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
+            <code>p</code> is added <code>k</code> times to itself.
+            @param p The <code>ECPoint</code> to be multiplied.
+            @param k The factor by which <code>p</code> is multiplied.
+            @return <code>p</code> multiplied by <code>k</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.DoubleAddMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Joye's double-add algorithm.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.FixedPointPreCompInfo">
+            Class holding precomputation data for fixed-point multiplications.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo">
+            Interface for classes storing precomputation data for multiplication
+            algorithms. Used as a Memento (see GOF patterns) for
+            <code>WNafMultiplier</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.FixedPointPreCompInfo.m_preComp">
+            Array holding the precomputed <code>ECPoint</code>s used for a fixed
+            point multiplication.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.FixedPointPreCompInfo.m_width">
+            The width used for the precomputation. If a larger width precomputation
+            is already available this may be larger than was requested, so calling
+            code should refer to the actual width.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.MixedNafR2LMultiplier">
+            Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using
+            mixed coordinates.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.MixedNafR2LMultiplier.#ctor">
+            By default, addition will be done in Jacobian coordinates, and doubling will be done in
+            Modified Jacobian coordinates (independent of the original coordinate system of each point).
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.MontgomeryLadderMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Montgomery ladder.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.NafL2RMultiplier">
+            Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right).
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.NafR2LMultiplier">
+            Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left).
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WNafL2RMultiplier">
+            Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+            algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafL2RMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Multiplies <code>this</code> by an integer <code>k</code> using the
+            Window NAF method.
+            @param k The integer by which <code>this</code> is multiplied.
+            @return A new <code>ECPoint</code> which equals <code>this</code>
+            multiplied by <code>k</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafL2RMultiplier.GetWindowSize(System.Int32)">
+            Determine window width to use for a scalar multiplication of the given size.
+            
+            @param bits the bit-length of the scalar to multiply by
+            @return the window size to use
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo">
+            Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
+            algorithm.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo.m_preComp">
+            Array holding the precomputed <code>ECPoint</code>s used for a Window
+            NAF multiplication.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo.m_preCompNeg">
+            Array holding the negations of the precomputed <code>ECPoint</code>s used
+            for a Window NAF multiplication.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo.m_twice">
+            Holds an <code>ECPoint</code> representing Twice(this). Used for the
+            Window NAF multiplication to create or extend the precomputed values.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafUtilities.GenerateWindowNaf(System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            Computes the Window NAF (non-adjacent Form) of an integer.
+            @param width The width <code>w</code> of the Window NAF. The width is
+            defined as the minimal number <code>w</code>, such that for any
+            <code>w</code> consecutive digits in the resulting representation, at
+            most one is non-zero.
+            @param k The integer of which the Window NAF is computed.
+            @return The Window NAF of the given width, such that the following holds:
+            <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+            </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+            returned <code>byte[]</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafUtilities.GetWindowSize(System.Int32)">
+            Determine window width to use for a scalar multiplication of the given size.
+            
+            @param bits the bit-length of the scalar to multiply by
+            @return the window size to use
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafUtilities.GetWindowSize(System.Int32,System.Int32[])">
+            Determine window width to use for a scalar multiplication of the given size.
+            
+            @param bits the bit-length of the scalar to multiply by
+            @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
+            @return the window size to use
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier">
+            Class implementing the WTNAF (Window
+            <code>τ</code>-adic Non-Adjacent Form) algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by <code>k</code> using the reduced <code>τ</code>-adic NAF (RTNAF)
+            method.
+            @param p The F2mPoint to multiply.
+            @param k The integer by which to multiply <code>k</code>.
+            @return <code>p</code> multiplied by <code>k</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.MultiplyWTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.EC.Abc.ZTauElement,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo,System.SByte,System.SByte)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code> using
+            the <code>τ</code>-adic NAF (TNAF) method.
+            @param p The F2mPoint to multiply.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code> of which to compute the
+            <code>[τ]</code>-adic NAF.
+            @return <code>p</code> multiplied by <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.MultiplyFromWTnaf(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte[],Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the window <code>τ</code>-adic NAF (TNAF) method, given the
+            WTNAF of <code>λ</code>.
+            @param p The F2mPoint to multiply.
+            @param u The the WTNAF of <code>λ</code>..
+            @return <code>λ * p</code>
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo">
+            Class holding precomputation data for the WTNAF (Window
+            <code>τ</code>-adic Non-Adjacent Form) algorithm.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo.m_preComp">
+            Array holding the precomputed <code>F2mPoint</code>s used for the
+            WTNAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+            WTauNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.ZSignedDigitL2RMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            'Zeroless' Signed Digit Left-to-Right.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.ZSignedDigitR2LMultiplier.MultiplyPositive(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger)">
+            'Zeroless' Signed Digit Right-to-Left.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.BasicOcspResp">
+            <remarks>
+            <code>
+            BasicOcspResponse ::= SEQUENCE {
+            	tbsResponseData		ResponseData,
+            	signatureAlgorithm	AlgorithmIdentifier,
+            	signature			BIT STRING,
+            	certs				[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509Extension.GetCriticalExtensionOids">
+            <summary>
+            Get all critical extension values, by oid
+            </summary>
+            <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509Extension.GetNonCriticalExtensionOids">
+            <summary>
+            Get all non-critical extension values, by oid
+            </summary>
+            <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetNonCriticalExtensionOids">
+            <summary>
+            Get non critical extensions.
+            </summary>
+            <returns>A set of non critical extension oids.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetCriticalExtensionOids">
+            <summary>
+            Get any critical extensions.
+            </summary>
+            <returns>A sorted list of critical entension.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetExtensionValue(System.String)">
+            <summary>
+            Get the value of a given extension.
+            </summary>
+            <param name="oid">The object ID of the extension. </param>
+            <returns>An Asn1OctetString object if that extension is found or null if not.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetTbsResponseData">
+            <returns>The DER encoding of the tbsResponseData field.</returns>
+            <exception cref="T:Org.BouncyCastle.Ocsp.OcspException">In the event of an encoding error.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetCertificates(System.String)">
+            <returns>The certificates, if any, associated with the response.</returns>
+            <exception cref="T:Org.BouncyCastle.Ocsp.OcspException">In the event of an encoding error.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Verify the signature against the tbsResponseData object we contain.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetEncoded">
+            <returns>The ASN.1 encoded representation of this object.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator">
+            Generator for basic OCSP response objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.#ctor(Org.BouncyCastle.Ocsp.RespID)">
+            basic constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            construct with the responderID to be the SHA-1 keyHash of the passed in public key.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param certStatus status of the certificate - null if okay
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param nextUpdate date when next update should be requested
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,System.DateTime,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param thisUpdate date this response was valid on
+             @param nextUpdate date when next update should be requested
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.SetResponseExtensions(Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Set the extensions for the response.
+            
+             @param responseExtensions the extension object to carry.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.SignatureAlgNames">
+             Return an IEnumerable of the signature names supported by the generator.
+            
+             @return an IEnumerable containing recognised names.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.CertificateID.#ctor(System.String,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Math.BigInteger)">
+            create from an issuer certificate and the serial number of the
+            certificate it signed.
+            @exception OcspException if any problems occur creating the id fields.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.CertificateID.DeriveCertificateID(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Math.BigInteger)">
+             Create a new CertificateID for a new serial number derived from a previous one
+             calculated for the same CA certificate.
+            
+             @param original the previously calculated CertificateID for the CA.
+             @param newSerialNumber the serial number for the new certificate of interest.
+            
+             @return a new CertificateID for newSerialNumber
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.CertificateID.SerialNumber">
+            return the serial number for the certificate associated
+            with this request.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.OcspReq">
+             <pre>
+             OcspRequest     ::=     SEQUENCE {
+                   tbsRequest                  TBSRequest,
+                   optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+            
+               TBSRequest      ::=     SEQUENCE {
+                   version             [0]     EXPLICIT Version DEFAULT v1,
+                   requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+                   requestList                 SEQUENCE OF Request,
+                   requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+            
+               Signature       ::=     SEQUENCE {
+                   signatureAlgorithm      AlgorithmIdentifier,
+                   signature               BIT STRING,
+                   certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+            
+               Version         ::=             INTEGER  {  v1(0) }
+            
+               Request         ::=     SEQUENCE {
+                   reqCert                     CertID,
+                   singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+            
+               CertID          ::=     SEQUENCE {
+                   hashAlgorithm       AlgorithmIdentifier,
+                   issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+                   issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+                   serialNumber        CertificateSerialNumber }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetTbsRequest">
+            Return the DER encoding of the tbsRequest field.
+            @return DER encoding of tbsRequest
+            @throws OcspException in the event of an encoding error.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetCertificates(System.String)">
+             If the request is signed return a possibly empty CertStore containing the certificates in the
+             request. If the request is not signed the method returns null.
+            
+             @return null if not signed, a CertStore otherwise
+             @throws OcspException
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            Verify the signature against the TBSRequest object we contain.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReq.SignatureAlgOid">
+            return the object identifier representing the signature algorithm
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReq.IsSigned">
+             Return whether or not this request is signed.
+            
+             @return true if signed false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.AddRequest(Org.BouncyCastle.Ocsp.CertificateID)">
+             Add a request for the given CertificateID.
+            
+             @param certId certificate ID of interest
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.AddRequest(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a request with extensions
+            
+             @param certId certificate ID of interest
+             @param singleRequestExtensions the extensions to attach to the request
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.SetRequestorName(Org.BouncyCastle.Asn1.X509.X509Name)">
+             Set the requestor name to the passed in X509Principal
+            
+             @param requestorName a X509Principal representing the requestor name.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.Generate">
+             Generate an unsigned request
+            
+             @return the OcspReq
+             @throws OcspException
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReqGenerator.SignatureAlgNames">
+             Return an IEnumerable of the signature names supported by the generator.
+            
+             @return an IEnumerable containing recognised names.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspResp.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.OCSPRespGenerator">
+            base generator for an OCSP response - at the moment this only supports the
+            generation of responses containing BasicOCSP responses.
+        </member>
+        <member name="F:Org.BouncyCastle.Ocsp.OcspRespStatus.Successful">
+            note 4 is not used.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.RespID">
+            Carrier for a ResponderID.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.RevokedStatus">
+            wrapper for the RevokedInfo object
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.RevokedStatus.RevocationReason">
+            return the revocation reason. Note: this field is optional, test for it
+            with hasRevocationReason() first.
+            @exception InvalidOperationException if a reason is asked for and none is avaliable
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.SingleResp.GetCertStatus">
+             Return the status object for the response - null indicates good.
+            
+             @return the status object for the response, null if it is good.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.SingleResp.NextUpdate">
+             return the NextUpdate value - note: this is an optional field so may
+             be returned as null.
+            
+             @return nextUpdate, or null if not present.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.UnknownStatus">
+            wrapper for the UnknownInfo object
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData">
+            <remarks>Compressed data objects</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.GetInputStream">
+            <summary>Get the raw input stream contained in the object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.GetDataStream">
+            <summary>Return an uncompressed input stream which allows reading of the compressed data.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.Algorithm">
+            <summary>The algorithm used for compression</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator">
+            <remarks>Class for producing compressed data packets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Open(System.IO.Stream)">
+            <summary>
+            <p>
+            Return an output stream which will save the data being written to
+            the compressed object.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+            <param name="outStr">Stream to be used for output.</param>
+            <returns>A Stream for output of the compressed data.</returns>
+            <exception cref="T:System.ArgumentNullException"></exception>
+            <exception cref="T:System.InvalidOperationException"></exception>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Open(System.IO.Stream,System.Byte[])">
+            <summary>
+            <p>
+            Return an output stream which will compress the data as it is written to it.
+            The stream will be written out in chunks according to the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.
+            </p>
+            <p>
+            <b>Note</b>: using this may break compatibility with RFC 1991 compliant tools.
+            Only recent OpenPGP implementations are capable of accepting these streams.
+            </p>
+            </summary>
+            <param name="outStr">Stream to be used for output.</param>
+            <param name="buffer">The buffer to use.</param>
+            <returns>A Stream for output of the compressed data.</returns>
+            <exception cref="T:System.ArgumentNullException"></exception>
+            <exception cref="T:System.InvalidOperationException"></exception>
+            <exception cref="T:System.IO.IOException"></exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Close">
+            <summary>Close the compressed object.</summary>summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpDataValidationException">
+            <remarks>
+            Thrown if the IV at the start of a data stream indicates the wrong key is being used.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
+            <remarks>Generic exception class for PGP encoding/decoding problems.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.GetInputStream">
+            <summary>Return the raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.IsIntegrityProtected">
+            <summary>Return true if the message is integrity protected.</summary>
+            <returns>True, if there is a modification detection code namespace associated
+            with this stream.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.Verify">
+            <summary>Note: This can only be called after the message has been read.</summary>
+            <returns>True, if the message verifies, false otherwise</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator">
+            <remarks>Generator for encrypted objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Existing SecureRandom constructor.</summary>
+            <param name="encAlgorithm">The symmetric algorithm to use.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Boolean,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Creates a cipher stream which will have an integrity packet associated with it.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom,System.Boolean)">
+            <summary>Base constructor.</summary>
+            <param name="encAlgorithm">The symmetric algorithm to use.</param>
+            <param name="rand">Source of randomness.</param>
+            <param name="oldFormat">PGP 2.6.x compatibility required.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(System.Char[])">
+            <summary>
+            Add a PBE encryption method to the encrypted object using the default algorithm (S2K_SHA1).
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(System.Char[],Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Add a PBE encryption method to the encrypted object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Add a public key encrypted session key to the encrypted object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Int64,System.Byte[])">
+            <summary>
+            <p>
+            If buffer is non null stream assumed to be partial, otherwise the length will be used
+            to output a fixed length packet.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Int64)">
+            <summary>
+            <p>
+            Return an output stream which will encrypt the data as it is written to it.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Byte[])">
+            <summary>
+            <p>
+            Return an output stream which will encrypt the data as it is written to it.
+            The stream will be written out in chunks according to the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Close">
+            <summary>
+            <p>
+            Close off the encrypted object - this is equivalent to calling Close() on the stream
+            returned by the Open() method.
+            </p>
+            <p>
+            <b>Note</b>: This does not close the underlying output stream, only the stream on top of
+            it created by the Open() method.
+            </p>
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataList">
+            <remarks>A holder for a list of PGP encryption method packets.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyFlags">
+            <remarks>Key flag values for the KeyFlags subpacket.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair">
+            <remarks>
+            General class to handle JCA key pairs and convert them into OpenPGP ones.
+            <p>
+            A word for the unwary, the KeyId for an OpenPGP public key is calculated from
+            a hash that includes the time of creation, if you pass a different date to the
+            constructor below with the same public private key pair the KeyIs will not be the
+            same as for previous generations of the key, so ideally you only want to do
+            this once.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair.#ctor(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
+            <param name="pub">The public key.</param>
+            <param name="priv">The private key.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair.KeyId">
+            <summary>The keyId associated with this key pair.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator">
+            <remarks>
+            Generator for a PGP master and subkey ring.
+            This class will generate both the secret and public key rings
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.#ctor(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,System.String,Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Char[],Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Create a new key ring generator using old style checksumming. It is recommended to use
+            SHA1 checksumming where possible.
+            </summary>
+            <param name="certificationLevel">The certification level for keys on this ring.</param>
+            <param name="masterKey">The master key pair.</param>
+            <param name="id">The id to be associated with the ring.</param>
+            <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+            <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+            <param name="hashedPackets">Packets to be included in the certification hash.</param>
+            <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+            <param name="rand">input secured random.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.#ctor(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,System.String,Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Char[],System.Boolean,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Create a new key ring generator.
+            </summary>
+            <param name="certificationLevel">The certification level for keys on this ring.</param>
+            <param name="masterKey">The master key pair.</param>
+            <param name="id">The id to be associated with the ring.</param>
+            <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+            <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+            <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
+            <param name="hashedPackets">Packets to be included in the certification hash.</param>
+            <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+            <param name="rand">input secured random.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.AddSubKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair)">
+            <summary>Add a subkey to the key ring to be generated with default certification.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.AddSubKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector)">
+            <summary>
+            Add a subkey with specific hashed and unhashed packets associated with it and
+            default certification.
+            </summary>
+            <param name="keyPair">Public/private key pair.</param>
+            <param name="hashedPackets">Hashed packet values to be included in certification.</param>
+            <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.GenerateSecretKeyRing">
+            <summary>Return the secret key ring.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.GeneratePublicKeyRing">
+            <summary>Return the public key ring that corresponds to the secret key ring.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyValidationException">
+            <remarks>
+            Thrown if the key checksum is invalid.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData">
+            <summary>Class for processing literal data objects.</summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Console">
+            <summary>The special name indicating a "for your eyes only" packet.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetRawFileName">
+            Return the file name as an unintrepreted byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetInputStream">
+            <summary>The raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetDataStream">
+            <summary>The input stream representing the data stream.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Format">
+            <summary>The format of the data stream - Binary or Text</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.FileName">
+            <summary>The file name that's associated with the data stream.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.ModificationTime">
+            <summary>The modification time for the file.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator">
+            <remarks>Class for producing literal data packets.</remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Console">
+            <summary>The special name indicating a "for your eyes only" packet.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.#ctor(System.Boolean)">
+            <summary>
+            Generates literal data objects in the old format.
+            This is important if you need compatibility with PGP 2.6.x.
+            </summary>
+            <param name="oldFormat">If true, uses old format.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Open(System.IO.Stream,System.Char,System.String,System.Int64,System.DateTime)">
+            <summary>
+            <p>
+            Open a literal data packet, returning a stream to store the data inside the packet.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+            <param name="outStr">The stream we want the packet in.</param>
+            <param name="format">The format we are using.</param>
+            <param name="name">The name of the 'file'.</param>
+            <param name="length">The length of the data we will write.</param>
+            <param name="modificationTime">The time of last modification we want stored.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Open(System.IO.Stream,System.Char,System.String,System.DateTime,System.Byte[])">
+            <summary>
+            <p>
+            Open a literal data packet, returning a stream to store the data inside the packet,
+            as an indefinite length stream. The stream is written out as a series of partial
+            packets with a chunk size determined by the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.</p>
+            </summary>
+            <param name="outStr">The stream we want the packet in.</param>
+            <param name="format">The format we are using.</param>
+            <param name="name">The name of the 'file'.</param>
+            <param name="modificationTime">The time of last modification we want stored.</param>
+            <param name="buffer">The buffer to use for collecting data to put into chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Close">
+            <summary>
+            Close the literal data packet - this is equivalent to calling Close()
+            on the stream returned by the Open() method.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpMarker">
+            <remarks>
+            A PGP marker packet - in general these should be ignored other than where
+            the idea is to preserve the original input stream.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory">
+            <remarks>
+            General class for reading a PGP object stream.
+            <p>
+            Note: if this class finds a PgpPublicKey or a PgpSecretKey it
+            will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each
+            key found. If all you are trying to do is read a key ring file use
+            either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory.NextPgpObject">
+            <summary>Return the next object in the stream, or null if the end is reached.</summary>
+            <exception cref="T:System.IO.IOException">On a parse error</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory.AllPgpObjects">
+            <summary>
+            Return all available objects in a list.
+            </summary>
+            <returns>An <c>IList</c> containing all objects from this factory, in order.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature">
+            <remarks>A one pass signature object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature.InitVerify(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Initialise the signature object for verification.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature.Verify(Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignatureList">
+            <remarks>Holder for a list of PgpOnePassSignature objects.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData">
+            <remarks>A password based encryption object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData.GetInputStream">
+            <summary>Return the raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData.GetDataStream(System.Char[])">
+            <summary>Return the decrypted input stream, using the passed in passphrase.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey">
+            <remarks>General class to contain a private key for use with other OpenPGP objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Int64)">
+            <summary>
+            Create a PgpPrivateKey from a regular private key and the ID of its
+            associated public key.
+            </summary>
+            <param name="privateKey">Private key to use.</param>
+            <param name="keyId">ID of the corresponding public key.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.KeyId">
+            <summary>The keyId associated with the contained private key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.Key">
+            <summary>The contained private key.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey">
+            <remarks>General class to handle a PGP public key object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.DateTime)">
+            <summary>
+            Create a PgpPublicKey from the passed in lightweight one.
+            </summary>
+            <remarks>
+            Note: the time passed in affects the value of the key's keyId, so you probably only want
+            to do this once for a lightweight key, or make sure you keep track of the time you used.
+            </remarks>
+            <param name="algorithm">Asymmetric algorithm type representing the public key.</param>
+            <param name="pubKey">Actual public key to associate.</param>
+            <param name="time">Date of creation.</param>
+            <exception cref="T:System.ArgumentException">If <c>pubKey</c> is not public.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">On key creation problem.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.PublicKeyPacket,Org.BouncyCastle.Bcpg.TrustPacket,System.Collections.IList)">
+            <summary>Constructor for a sub-key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Copy constructor.</summary>
+            <param name="pubKey">The public key to copy.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetTrustData">
+            <summary>Return the trust data associated with the public key, if present.</summary>
+            <returns>A byte array with trust data, null otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetValidSeconds">
+            <summary>The number of valid seconds from creation time - zero means no expiry.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetFingerprint">
+            <summary>The fingerprint of the key</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetKey">
+            <summary>The public key contained in the object.</summary>
+            <returns>A lightweight public key.</returns>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If the key algorithm is not recognised.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetUserIds">
+            <summary>Allows enumeration of any user IDs associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetUserAttributes">
+            <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesForId(System.String)">
+            <summary>Allows enumeration of any signatures associated with the passed in id.</summary>
+            <param name="id">The ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesForUserAttribute(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector)">
+            <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary>
+            <param name="userAttributes">The vector of user attributes to be matched.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesOfType(System.Int32)">
+            <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary>
+            <param name="signatureType">The type of the signature to be returned.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignatures">
+            <summary>Allows enumeration of all signatures/certifications associated with this key.</summary>
+            <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsRevoked">
+            <summary>Check whether this (sub)key has a revocation signature on it.</summary>
+            <returns>True, if this (sub)key has been revoked.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a certification for an id to the given public key.</summary>
+            <param name="key">The key the certification is to be added to.</param>
+            <param name="id">The ID the certification is associated with.</param>
+            <param name="certification">The new certification.</param>
+            <returns>The re-certified key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary>
+            <param name="key">The key the certification is to be added to.</param>
+            <param name="userAttributes">The attributes the certification is associated with.</param>
+            <param name="certification">The new certification.</param>
+            <returns>The re-certified key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector)">
+            <summary>
+            Remove any certifications associated with a user attribute subpacket on a key.
+            </summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="userAttributes">The attributes to be removed.</param>
+            <returns>
+            The re-certified key, or null if the user attribute subpacket was not found on the key.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String)">
+            <summary>Remove any certifications associated with a given ID on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="id">The ID that is to be removed.</param>
+            <returns>The re-certified key, or null if the ID was not found on the key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification associated with a given ID on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="id">The ID that the certfication is to be removed from.</param>
+            <param name="certification">The certfication to be removed.</param>
+            <returns>The re-certified key, or null if the certification was not found.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification associated with a given user attributes on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
+            <param name="certification">The certification to be removed.</param>
+            <returns>The re-certified key, or null if the certification was not found.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a revocation or some other key certification to a key.</summary>
+            <param name="key">The key the revocation is to be added to.</param>
+            <param name="certification">The key signature to be added.</param>
+            <returns>The new changed public key object.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification from the key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="certification">The certfication to be removed.</param>
+            <returns>The modified key, null if the certification was not found.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.Version">
+            <summary>The version of this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.CreationTime">
+            <summary>The creation time of this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.ValidDays">
+            <summary>The number of valid days from creation time - zero means no expiry.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.KeyId">
+            <summary>The keyId associated with the public key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsEncryptionKey">
+            <summary>
+            Check if this key has an algorithm type that makes it suitable to use for encryption.
+            </summary>
+            <remarks>
+            Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+            determining the preferred use of the key.
+            </remarks>
+            <returns>
+            <c>true</c> if this key algorithm is suitable for encryption.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsMasterKey">
+            <summary>True, if this is a master key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.Algorithm">
+            <summary>The algorithm code associated with the public key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.BitStrength">
+            <summary>The strength of the key in bits.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData">
+            <remarks>A public key encrypted data object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.GetSymmetricAlgorithm(Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>
+            Return the algorithm code for the symmetric algorithm used to encrypt the data.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.GetDataStream(Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Return the decrypted data stream for the packet.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.KeyId">
+            <summary>The key ID for the key used to encrypt the data.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing">
+            <remarks>
+            Class to hold a single master public key and its subkeys.
+            <p>
+            Often PGP keyring files consist of multiple master keys, if you are trying to process
+            or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKey">
+            <summary>Return the first public key in the ring.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKey(System.Int64)">
+            <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKeys">
+            <summary>Allows enumeration of all the public keys.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.InsertPublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Returns a new key ring with the public key passed in either added or
+            replacing an existing one.
+            </summary>
+            <param name="pubRing">The public key ring to be modified.</param>
+            <param name="pubKey">The public key to be inserted.</param>
+            <returns>A new <c>PgpPublicKeyRing</c></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.RemovePublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
+            <param name="pubRing">The public key ring to be modified.</param>
+            <param name="pubKey">The public key to be removed.</param>
+            <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle">
+            <remarks>
+            Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+            If you want to read an entire public key file in one hit this is the class for you.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.#ctor(System.IO.Stream)">
+            <summary>Build a PgpPublicKeyRingBundle from the passed in input stream.</summary>
+            <param name="inputStream">Input stream containing data.</param>
+            <exception cref="T:System.IO.IOException">If a problem parsing the stream occurs.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If an object is encountered which isn't a PgpPublicKeyRing.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings">
+            <summary>Allow enumeration of the public key rings making up this collection.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String,System.Boolean,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetPublicKey(System.Int64)">
+            <summary>Return the PGP public key associated with the given key id.</summary>
+            <param name="keyId">The ID of the public key to return.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetPublicKeyRing(System.Int64)">
+            <summary>Return the public key ring which contains the key referred to by keyId</summary>
+            <param name="keyId">key ID to match against</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.Contains(System.Int64)">
+            <summary>
+            Return true if a key matching the passed in key ID is present, false otherwise.
+            </summary>
+            <param name="keyID">key ID to look for.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.AddPublicKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle and
+            the passed in public key ring.
+            </summary>
+            <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
+            <param name="publicKeyRing">The key ring to be added.</param>
+            <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.RemovePublicKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle with
+            the passed in public key ring removed.
+            </summary>
+            <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be removed from.</param>
+            <param name="publicKeyRing">The key ring to be removed.</param>
+            <returns>A new <c>PgpPublicKeyRingBundle</c> not containing the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.Count">
+            <summary>Return the number of key rings in this collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey">
+            <remarks>General class to handle a PGP secret key object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ExtractPrivateKey(System.Char[])">
+            <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.CopyWithNewPassword(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey,System.Char[],System.Char[],Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Return a copy of the passed in secret key, encrypted using a new password
+            and the passed in algorithm.
+            </summary>
+            <param name="key">The PgpSecretKey to be copied.</param>
+            <param name="oldPassPhrase">The current password for the key.</param>
+            <param name="newPassPhrase">The new password for the key.</param>
+            <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ReplacePublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Replace the passed the public key on the passed in secret key.</summary>
+            <param name="secretKey">Secret key to change.</param>
+            <param name="publicKey">New public key.</param>
+            <returns>A new secret key.</returns>
+            <exception cref="T:System.ArgumentException">If KeyId's do not match.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.IsSigningKey">
+            <summary>
+            Check if this key has an algorithm type that makes it suitable to use for signing.
+            </summary>
+            <remarks>
+            Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+            determining the preferred use of the key.
+            </remarks>
+            <returns>
+            <c>true</c> if this key algorithm is suitable for use with signing.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.IsMasterKey">
+            <summary>True, if this is a master key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.IsPrivateKeyEmpty">
+            <summary>Detect if the Secret Key's Private Key is empty or not</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.KeyEncryptionAlgorithm">
+            <summary>The algorithm the key is encrypted with.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.KeyId">
+            <summary>The key ID of the public key associated with this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.PublicKey">
+            <summary>The public key associated with this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.UserIds">
+            <summary>Allows enumeration of any user IDs associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.UserAttributes">
+            <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing">
+            <remarks>
+            Class to hold a single master secret key and its subkeys.
+            <p>
+            Often PGP keyring files consist of multiple master keys, if you are trying to process
+            or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetPublicKey">
+            <summary>Return the public key for the master key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetSecretKey">
+            <summary>Return the master private key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetSecretKeys">
+            <summary>Allows enumeration of the secret keys.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetExtraPublicKeys">
+            <summary>
+            Return an iterator of the public keys in the secret key ring that
+            have no matching private key. At the moment only personal certificate data
+            appears in this fashion.
+            </summary>
+            <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.ReplacePublicKeys(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Replace the public key set on the secret ring with the corresponding key off the public ring.
+            </summary>
+            <param name="secretRing">Secret ring to be changed.</param>
+            <param name="publicRing">Public ring containing the new public key set.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.CopyWithNewPassword(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,System.Char[],System.Char[],Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Return a copy of the passed in secret key ring, with the master key and sub keys encrypted
+            using a new password and the passed in algorithm.
+            </summary>
+            <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param>
+            <param name="oldPassPhrase">The current password for key.</param>
+            <param name="newPassPhrase">The new password for the key.</param>
+            <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.InsertSecretKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey)">
+            <summary>
+            Returns a new key ring with the secret key passed in either added or
+            replacing an existing one with the same key ID.
+            </summary>
+            <param name="secRing">The secret key ring to be modified.</param>
+            <param name="secKey">The secret key to be inserted.</param>
+            <returns>A new <c>PgpSecretKeyRing</c></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.RemoveSecretKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey)">
+            <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
+            <param name="secRing">The secret key ring to be modified.</param>
+            <param name="secKey">The secret key to be removed.</param>
+            <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle">
+            <remarks>
+            Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+            If you want to read an entire secret key file in one hit this is the class for you.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.#ctor(System.IO.Stream)">
+            <summary>Build a PgpSecretKeyRingBundle from the passed in input stream.</summary>
+            <param name="inputStream">Input stream containing data.</param>
+            <exception cref="T:System.IO.IOException">If a problem parsing the stream occurs.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If an object is encountered which isn't a PgpSecretKeyRing.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings">
+            <summary>Allow enumeration of the secret key rings making up this collection.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String,System.Boolean,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetSecretKey(System.Int64)">
+            <summary>Return the PGP secret key associated with the given key id.</summary>
+            <param name="keyId">The ID of the secret key to return.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetSecretKeyRing(System.Int64)">
+            <summary>Return the secret key ring which contains the key referred to by keyId</summary>
+            <param name="keyId">The ID of the secret key</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.Contains(System.Int64)">
+            <summary>
+            Return true if a key matching the passed in key ID is present, false otherwise.
+            </summary>
+            <param name="keyID">key ID to look for.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.AddSecretKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle and
+            the passed in secret key ring.
+            </summary>
+            <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be added to.</param>
+            <param name="secretKeyRing">The key ring to be added.</param>
+            <returns>A new <c>PgpSecretKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.RemoveSecretKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle with
+            the passed in secret key ring removed.
+            </summary>
+            <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be removed from.</param>
+            <param name="secretKeyRing">The key ring to be removed.</param>
+            <returns>A new <c>PgpSecretKeyRingBundle</c> not containing the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.Count">
+            <summary>Return the number of rings in this collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature">
+            <remarks>A PGP signature object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Verify the signature as certifying the passed in public key as associated
+            with the passed in user attributes.
+            </summary>
+            <param name="userAttributes">User attributes the key was stored under.</param>
+            <param name="key">The key to be verified.</param>
+            <returns>True, if the signature matches, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Verify the signature as certifying the passed in public key as associated
+            with the passed in ID.
+            </summary>
+            <param name="id">ID the key was stored under.</param>
+            <param name="key">The key to be verified.</param>
+            <returns>True, if the signature matches, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Verify a certification for the passed in key against the passed in master key.</summary>
+            <param name="masterKey">The key we are verifying against.</param>
+            <param name="pubKey">The key we are verifying.</param>
+            <returns>True, if the certification is valid, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
+            <param name="pubKey">The key we are checking.</param>
+            <returns>True, if the certification is valid, false otherwise.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.Version">
+            <summary>The OpenPGP version number for this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.KeyAlgorithm">
+            <summary>The key algorithm associated with this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.HashAlgorithm">
+            <summary>The hash algorithm associated with this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.KeyId">
+            <summary>The ID of the key that created the signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.CreationTime">
+            <summary>The creation time of this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.HasSubpackets">
+            <summary>
+            Return true if the signature has either hashed or unhashed subpackets.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator">
+            <remarks>Generator for PGP signatures.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateOnePassVersion(System.Boolean)">
+            <summary>Return the one pass header associated with the current signature.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.Generate">
+            <summary>Return a signature object containing the current signature state.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in ID and key.</summary>
+            <param name="id">The ID we are certifying against the public key.</param>
+            <param name="pubKey">The key we are certifying against the ID.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in userAttributes.</summary>
+            <param name="userAttributes">The ID we are certifying against the public key.</param>
+            <param name="pubKey">The key we are certifying against the ID.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in key against the passed in master key.</summary>
+            <param name="masterKey">The key we are certifying against.</param>
+            <param name="pubKey">The key we are certifying.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification, such as a revocation, for the passed in key.</summary>
+            <param name="pubKey">The key we are certifying.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureList">
+            <remarks>A list of PGP signatures - normally in the signature block after literal data.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator">
+            <remarks>Generator for signature subpackets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetTrust(System.Boolean,System.Int32,System.Int32)">
+            <summary>
+            Add a TrustSignature packet to the signature. The values for depth and trust are largely
+            installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
+            </summary>
+            <param name="isCritical">true if the packet is critical.</param>
+            <param name="depth">depth level.</param>
+            <param name="trustAmount">trust amount.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetKeyExpirationTime(System.Boolean,System.Int64)">
+            <summary>
+            Set the number of seconds a key is valid for after the time of its creation.
+            A value of zero means the key never expires.
+            </summary>
+            <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+            <param name="seconds">The number of seconds the key is valid, or zero if no expiry.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetSignatureExpirationTime(System.Boolean,System.Int64)">
+            <summary>
+            Set the number of seconds a signature is valid for after the time of its creation.
+            A value of zero means the signature never expires.
+            </summary>
+            <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+            <param name="seconds">The number of seconds the signature is valid, or zero if no expiry.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetSignatureCreationTime(System.Boolean,System.DateTime)">
+            <summary>
+            Set the creation time for the signature.
+            <p>
+            Note: this overrides the generation of a creation time when the signature
+            is generated.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetRevocationReason(System.Boolean,Org.BouncyCastle.Bcpg.RevocationReasonTag,System.String)">
+            <summary>
+            Sets revocation reason sub packet
+            </summary>	    
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetRevocationKey(System.Boolean,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.Byte[])">
+            <summary>
+            Sets revocation key sub packet
+            </summary>	
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetIssuerKeyID(System.Boolean,System.Int64)">
+            <summary>
+            Sets issuer key sub packet
+            </summary>	
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector">
+            <remarks>Container for a list of signature subpackets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.HasSubpacket(Org.BouncyCastle.Bcpg.SignatureSubpacketTag)">
+             Return true if a particular subpacket type exists.
+            
+             @param type type to look for.
+             @return true if present, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetSubpackets(Org.BouncyCastle.Bcpg.SignatureSubpacketTag)">
+            Return all signature subpackets of the passed in type.
+            @param type subpacket type code
+            @return an array of zero or more matching subpackets.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetSignatureExpirationTime">
+            <summary>
+            Return the number of seconds a signature is valid for after its creation date.
+            A value of zero means the signature never expires.
+            </summary>
+            <returns>Seconds a signature is valid for.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetKeyExpirationTime">
+            <summary>
+            Return the number of seconds a key is valid for after its creation date.
+            A value of zero means the key never expires.
+            </summary>
+            <returns>Seconds a signature is valid for.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.Count">
+            <summary>Return the number of packets this vector contains.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector">
+            <remarks>Container for a list of user attribute subpackets.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpUtilities">
+            <remarks>Basic utility class.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(System.IO.Stream)">
+            <summary>
+            Return either an ArmoredInputStream or a BcpgInputStream based on whether
+            the initial characters of the stream are binary PGP encodings or not.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator">
+            <remarks>Generator for old style PGP V3 Signatures.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.GenerateOnePassVersion(System.Boolean)">
+            <summary>Return the one pass header associated with the current signature.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.Generate">
+            <summary>Return a V3 signature object containing the current signature state.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.MiscPemGenerator">
+            PEM generator for the original set of PEM objects used in Open SSL.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemObjectGenerator.Generate">
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </returns>
+            <exception cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemGenerationException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.PemReader">
+            Class for reading OpenSSL PEM encoded streams containing 
+            X509 certificates, PKCS8 encoded keys and PKCS7 objects.
+            <p>
+            In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
+            Certificates will be returned using the appropriate java.security type.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemReader.ReadPemObject">
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.#ctor(System.IO.TextReader)">
+             Create a new PemReader
+            
+             @param reader the Reader
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.#ctor(System.IO.TextReader,Org.BouncyCastle.OpenSsl.IPasswordFinder)">
+             Create a new PemReader with a password finder
+            
+             @param reader the Reader
+             @param pFinder the password finder
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCertificate(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509Certificate.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCrl(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509CRL.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCertificateRequest(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a PKCS10 certification request.
+            
+             @return the certificate request.
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadAttributeCertificate(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509 Attribute Certificate.
+            
+             @return the X509 Attribute Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadPkcs7(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
+             API.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadPrivateKey(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+            Read a Key Pair
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.PemWriter">
+            <remarks>General purpose writer for OpenSSL PEM objects.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.IO.Pem.PemWriter">
+            A generic PEM writer, based on RFC 1421
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemWriter.#ctor(System.IO.TextWriter)">
+             Base constructor.
+            
+             @param out output stream to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemWriter.GetOutputSize(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Return the number of bytes or characters required to contain the
+             passed in object if it is PEM encoded.
+            
+             @param obj pem object to be output
+             @return an estimate of the number of bytes
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemWriter.#ctor(System.IO.TextWriter)">
+            <param name="writer">The TextWriter object to write the output to.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.Pkcs8Generator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             Constructor for an unencrypted private key PEM object.
+            
+             @param key private key to be encoded.
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.Pkcs8Generator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.String)">
+             Constructor for an encrypted private key PEM object.
+            
+             @param key       private key to be encoded
+             @param algorithm encryption algorithm to use
+             @param provider  provider to use
+             @throws NoSuchAlgorithmException if algorithm/mode cannot be found
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest">
+             <remarks>
+             A class for verifying and creating Pkcs10 Certification requests.
+             </remarks>
+             <code>
+             CertificationRequest ::= Sequence {
+               certificationRequestInfo  CertificationRequestInfo,
+               signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+               signature                 BIT STRING
+             }
+            
+             CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </code>
+             see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Asn1.Asn1Set,Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             <summary>
+             Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+             </summary>
+            <param name="signatureAlgorithm">Name of Sig Alg.</param>
+             <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+             <param name="publicKey">Public Key to be included in cert reqest.</param>
+             <param name="attributes">ASN1Set of Attributes.</param>
+             <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.GetPublicKey">
+            <summary>
+            Get the public key.
+            </summary>
+            <returns>The public key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.Verify">
+            <summary>
+            Verify Pkcs10 Cert Request is valid.
+            </summary>
+            <returns>true = valid.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned">
+             <remarks>
+             A class for creating and verifying Pkcs10 Certification requests (this is an extension on <see cref="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest"/>).
+             The requests are made using delay signing. This is useful for situations where
+             the private key is in another environment and not directly accessible (e.g. HSM)
+             So the first step creates the request, then the signing is done outside this
+             object and the signature is then used to complete the request.
+             </remarks>
+             <code>
+             CertificationRequest ::= Sequence {
+               certificationRequestInfo  CertificationRequestInfo,
+               signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+               signature                 BIT STRING
+             }
+            
+             CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </code>
+             see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Asn1.Asn1Set)">
+            <summary>
+            Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+            </summary>
+            <param name="signatureAlgorithm">Name of Sig Alg.</param>
+            <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+            <param name="publicKey">Public Key to be included in cert reqest.</param>
+            <param name="attributes">ASN1Set of Attributes.</param>
+            <remarks>
+            After the object is constructed use the <see cref="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned.GetDataToSign"/> and finally the
+            SignRequest methods to finalize the request.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Store.GetCertificate(System.String)">
+            simply return the cert entry for the private key
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs12Utilities">
+            Utility class for reencoding PKCS#12 files to definite length.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(System.Byte[])">
+             Just re-encode the outer layer of the PKCS#12 file to definite length encoding.
+            
+             @param berPKCS12File - original PKCS#12 file
+             @return a byte array representing the DER encoding of the PFX structure
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(System.Byte[],System.Char[])">
+             Re-encode the PKCS#12 structure to definite length encoding at the inner layer
+             as well, recomputing the MAC accordingly.
+            
+             @param berPKCS12File - original PKCS12 file.
+             @param provider - provider to use for MAC calculation.
+             @return a byte array representing the DER encoding of the PFX structure.
+             @throws IOException on parsing, encoding errors.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.CertStatus.RevocationDate">
+            <summary>
+            Returns the revocationDate.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.CertStatus.Status">
+            <summary>
+            Returns the certStatus.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.GetSupportedExtensions">
+            Returns an immutable <code>Set</code> of X.509 attribute certificate
+            extensions that this <code>PkixAttrCertChecker</code> supports or
+            <code>null</code> if no extensions are supported.
+            <p>
+            Each element of the set is a <code>String</code> representing the
+            Object Identifier (OID) of the X.509 extension that is supported.
+            </p>
+            <p>
+            All X.509 attribute certificate extensions that a
+            <code>PkixAttrCertChecker</code> might possibly be able to process
+            should be included in the set.
+            </p>
+            
+            @return an immutable <code>Set</code> of X.509 extension OIDs (in
+                    <code>String</code> format) supported by this
+                    <code>PkixAttrCertChecker</code>, or <code>null</code> if no
+                    extensions are supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.Check(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixCertPath,Org.BouncyCastle.Pkix.PkixCertPath,System.Collections.ICollection)">
+            Performs checks on the specified attribute certificate. Every handled
+            extension is rmeoved from the <code>unresolvedCritExts</code>
+            collection.
+            
+            @param attrCert The attribute certificate to be checked.
+            @param certPath The certificate path which belongs to the attribute
+                       certificate issuer public key certificate.
+            @param holderCertPath The certificate path which belongs to the holder
+                       certificate.
+            @param unresolvedCritExts a <code>Collection</code> of OID strings
+                       representing the current set of unresolved critical extensions
+            @throws CertPathValidatorException if the specified attribute certificate
+                        does not pass the check.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.Clone">
+            Returns a clone of this object.
+            
+            @return a copy of this <code>PkixAttrCertChecker</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertPathBuilder.Build(Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Build and validate a CertPath using the given parameter.
+            
+             @param params PKIXBuilderParameters object containing all information to
+                        build the CertPath
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixAttrCertPathValidator">
+            CertPathValidatorSpi implementation for X.509 Attribute Certificates la RFC 3281.
+            
+            @see org.bouncycastle.x509.ExtendedPkixParameters
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertPathValidator.Validate(Org.BouncyCastle.Pkix.PkixCertPath,Org.BouncyCastle.Pkix.PkixParameters)">
+            Validates an attribute certificate with the given certificate path.
+            
+            <p>
+            <code>params</code> must be an instance of
+            <code>ExtendedPkixParameters</code>.
+            </p><p>
+            The target constraints in the <code>params</code> must be an
+            <code>X509AttrCertStoreSelector</code> with at least the attribute
+            certificate criterion set. Obey that also target informations may be
+            necessary to correctly validate this attribute certificate.
+            </p><p>
+            The attribute certificate issuer must be added to the trusted attribute
+            issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
+            </p>
+            @param certPath The certificate path which belongs to the attribute
+                       certificate issuer public key certificate.
+            @param params The PKIX parameters.
+            @return A <code>PKIXCertPathValidatorResult</code> of the result of
+                    validating the <code>certPath</code>.
+            @throws InvalidAlgorithmParameterException if <code>params</code> is
+                        inappropriate for this validator.
+            @throws CertPathValidatorException if the verification fails.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixBuilderParameters">
+            <summary>
+            Summary description for PkixBuilderParameters.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixParameters">
+            <summary>
+            Summary description for PkixParameters.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixParameters.PkixValidityModel">
+            This is the default PKIX validity model. Actually there are two variants
+            of this: The PKIX model and the modified PKIX model. The PKIX model
+            verifies that all involved certificates must have been valid at the
+            current time. The modified PKIX model verifies that all involved
+            certificates were valid at the signing time. Both are indirectly choosen
+            with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
+            methods sets the Date when <em>all</em> certificates must have been
+            valid.
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixParameters.ChainValidityModel">
+            This model uses the following validity model. Each certificate must have
+            been valid at the moment where is was used. That means the end
+            certificate must have been valid at the time the signature was done. The
+            CA certificate which signed the end certificate must have been valid,
+            when the end certificate was signed. The CA (or Root CA) certificate must
+            have been valid, when the CA certificate was signed and so on. So the
+            {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
+            the <em>end certificate</em> must have been valid. <p/> It is used e.g.
+            in the German signature law.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.#ctor(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Creates an instance of PKIXParameters with the specified Set of
+             most-trusted CAs. Each element of the set is a TrustAnchor.<br />
+             <br />
+             Note that the Set is copied to protect against subsequent modifications.
+            
+             @param trustAnchors
+                        a Set of TrustAnchors
+            
+             @exception InvalidAlgorithmParameterException
+                            if the specified Set is empty
+                            <code>(trustAnchors.isEmpty() == true)</code>
+             @exception NullPointerException
+                            if the specified Set is <code>null</code>
+             @exception ClassCastException
+                            if any of the elements in the Set are not of type
+                            <code>java.security.cert.TrustAnchor</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTargetCertConstraints">
+             Returns the required constraints on the target certificate. The
+             constraints are returned as an instance of CertSelector. If
+             <code>null</code>, no constraints are defined.<br />
+             <br />
+             Note that the CertSelector returned is cloned to protect against
+             subsequent modifications.
+            
+             @return a CertSelector specifying the constraints on the target
+                     certificate (or <code>null</code>)
+            
+             @see #setTargetCertConstraints(CertSelector)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTargetCertConstraints(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Sets the required constraints on the target certificate. The constraints
+             are specified as an instance of CertSelector. If null, no constraints are
+             defined.<br />
+             <br />
+             Note that the CertSelector specified is cloned to protect against
+             subsequent modifications.
+            
+             @param selector
+                        a CertSelector specifying the constraints on the target
+                        certificate (or <code>null</code>)
+            
+             @see #getTargetCertConstraints()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetInitialPolicies">
+             Returns an immutable Set of initial policy identifiers (OID strings),
+             indicating that any one of these policies would be acceptable to the
+             certificate user for the purposes of certification path processing. The
+             default return value is an empty <code>Set</code>, which is
+             interpreted as meaning that any policy would be acceptable.
+            
+             @return an immutable <code>Set</code> of initial policy OIDs in String
+                     format, or an empty <code>Set</code> (implying any policy is
+                     acceptable). Never returns <code>null</code>.
+            
+             @see #setInitialPolicies(java.util.Set)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetInitialPolicies(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the <code>Set</code> of initial policy identifiers (OID strings),
+             indicating that any one of these policies would be acceptable to the
+             certificate user for the purposes of certification path processing. By
+             default, any policy is acceptable (i.e. all policies), so a user that
+             wants to allow any policy as acceptable does not need to call this
+             method, or can call it with an empty <code>Set</code> (or
+             <code>null</code>).<br />
+             <br />
+             Note that the Set is copied to protect against subsequent modifications.<br />
+             <br />
+            
+             @param initialPolicies
+                        a Set of initial policy OIDs in String format (or
+                        <code>null</code>)
+            
+             @exception ClassCastException
+                            if any of the elements in the set are not of type String
+            
+             @see #getInitialPolicies()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetCertPathCheckers(System.Collections.IList)">
+             Sets a <code>List</code> of additional certification path checkers. If
+             the specified List contains an object that is not a PKIXCertPathChecker,
+             it is ignored.<br />
+             <br />
+             Each <code>PKIXCertPathChecker</code> specified implements additional
+             checks on a certificate. Typically, these are checks to process and
+             verify private extensions contained in certificates. Each
+             <code>PKIXCertPathChecker</code> should be instantiated with any
+             initialization parameters needed to execute the check.<br />
+             <br />
+             This method allows sophisticated applications to extend a PKIX
+             <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each
+             of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX
+             <code>CertPathValidator</code> or <code>CertPathBuilder</code> for
+             each certificate processed or validated.<br />
+             <br />
+             Regardless of whether these additional PKIXCertPathCheckers are set, a
+             PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code>
+             must perform all of the required PKIX checks on each certificate. The one
+             exception to this rule is if the RevocationEnabled flag is set to false
+             (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled}
+             method).<br />
+             <br />
+             Note that the List supplied here is copied and each PKIXCertPathChecker
+             in the list is cloned to protect against subsequent modifications.
+            
+             @param checkers
+                        a List of PKIXCertPathCheckers. May be null, in which case no
+                        additional checkers will be used.
+             @exception ClassCastException
+                            if any of the elements in the list are not of type
+                            <code>java.security.cert.PKIXCertPathChecker</code>
+             @see #getCertPathCheckers()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetCertPathCheckers">
+             Returns the List of certification path checkers. Each PKIXCertPathChecker
+             in the returned IList is cloned to protect against subsequent modifications.
+            
+             @return an immutable List of PKIXCertPathCheckers (may be empty, but not
+                     <code>null</code>)
+            
+             @see #setCertPathCheckers(java.util.List)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddCertPathChecker(Org.BouncyCastle.Pkix.PkixCertPathChecker)">
+             Adds a <code>PKIXCertPathChecker</code> to the list of certification
+             path checkers. See the {@link #setCertPathCheckers setCertPathCheckers}
+             method for more details.
+             <p>
+             Note that the <code>PKIXCertPathChecker</code> is cloned to protect
+             against subsequent modifications.</p>
+            
+             @param checker a <code>PKIXCertPathChecker</code> to add to the list of
+             checks. If <code>null</code>, the checker is ignored (not added to list).
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetParams(Org.BouncyCastle.Pkix.PkixParameters)">
+             Method to support <code>Clone()</code> under J2ME.
+             <code>super.Clone()</code> does not exist and fields are not copied.
+            
+             @param params Parameters to set. If this are
+                        <code>ExtendedPkixParameters</code> they are copied to.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetStores(System.Collections.IList)">
+             Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+             <p>
+             The <code>IList</code> is cloned.
+             </p>
+            
+             @param stores A list of stores to use.
+             @see #getStores
+             @throws ClassCastException if an element of <code>stores</code> is not
+                         a {@link Store}.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddStore(Org.BouncyCastle.X509.Store.IX509Store)">
+             Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
+             certificates or cross certificates.
+             <p>
+             This method should be used to add local stores, like collection based
+             X.509 stores, if available. Local stores should be considered first,
+             before trying to use additional (remote) locations, because they do not
+             need possible additional network traffic.
+             </p><p>
+             If <code>store</code> is <code>null</code> it is ignored.
+             </p>
+            
+             @param store The store to add.
+             @see #getStores
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddAdditionalStore(Org.BouncyCastle.X509.Store.IX509Store)">
+             Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates,
+             attribute certificates or cross certificates.
+             <p>
+             You should not use this method. This method is used for adding additional
+             X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
+             during X.509 object processing, e.g. in certificates or CRLs. This method
+             is used in PKIX certification path processing.
+             </p><p>
+             If <code>store</code> is <code>null</code> it is ignored.
+             </p>
+            
+             @param store The store to add.
+             @see #getStores()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetAdditionalStores">
+             Returns an <code>IList</code> of additional Bouncy Castle
+             <code>Store</code>s used for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+            
+             @return an immutable <code>IList</code> of additional Bouncy Castle
+                     <code>Store</code>s. Never <code>null</code>.
+            
+             @see #addAddionalStore(Store)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetStores">
+             Returns an <code>IList</code> of Bouncy Castle
+             <code>Store</code>s used for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+            
+             @return an immutable <code>IList</code> of Bouncy Castle
+                     <code>Store</code>s. Never <code>null</code>.
+            
+             @see #setStores(IList)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetAdditionalLocationsEnabled(System.Boolean)">
+             Sets if additional {@link X509Store}s for locations like LDAP found in
+             certificates or CRLs should be used.
+            
+             @param enabled <code>true</code> if additional stores are used.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTargetConstraints">
+             Returns the required constraints on the target certificate or attribute
+             certificate. The constraints are returned as an instance of
+             <code>IX509Selector</code>. If <code>null</code>, no constraints are
+             defined.
+            
+             <p>
+             The target certificate in a PKIX path may be a certificate or an
+             attribute certificate.
+             </p><p>
+             Note that the <code>IX509Selector</code> returned is cloned to protect
+             against subsequent modifications.
+             </p>
+             @return a <code>IX509Selector</code> specifying the constraints on the
+                     target certificate or attribute certificate (or <code>null</code>)
+             @see #setTargetConstraints
+             @see X509CertStoreSelector
+             @see X509AttributeCertStoreSelector
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTargetConstraints(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Sets the required constraints on the target certificate or attribute
+             certificate. The constraints are specified as an instance of
+             <code>IX509Selector</code>. If <code>null</code>, no constraints are
+             defined.
+             <p>
+             The target certificate in a PKIX path may be a certificate or an
+             attribute certificate.
+             </p><p>
+             Note that the <code>IX509Selector</code> specified is cloned to protect
+             against subsequent modifications.
+             </p>
+            
+             @param selector a <code>IX509Selector</code> specifying the constraints on
+                        the target certificate or attribute certificate (or
+                        <code>null</code>)
+             @see #getTargetConstraints
+             @see X509CertStoreSelector
+             @see X509AttributeCertStoreSelector
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTrustedACIssuers">
+             Returns the trusted attribute certificate issuers. If attribute
+             certificates is verified the trusted AC issuers must be set.
+             <p>
+             The returned <code>ISet</code> consists of <code>TrustAnchor</code>s.
+             </p><p>
+             The returned <code>ISet</code> is immutable. Never <code>null</code>
+             </p>
+            
+             @return Returns an immutable set of the trusted AC issuers.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTrustedACIssuers(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the trusted attribute certificate issuers. If attribute certificates
+             is verified the trusted AC issuers must be set.
+             <p>
+             The <code>trustedACIssuers</code> must be a <code>ISet</code> of
+             <code>TrustAnchor</code>
+             </p><p>
+             The given set is cloned.
+             </p>
+            
+             @param trustedACIssuers The trusted AC issuers to set. Is never
+                        <code>null</code>.
+             @throws ClassCastException if an element of <code>stores</code> is not
+                         a <code>TrustAnchor</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetNecessaryACAttributes">
+             Returns the neccessary attributes which must be contained in an attribute
+             certificate.
+             <p>
+             The returned <code>ISet</code> is immutable and contains
+             <code>String</code>s with the OIDs.
+             </p>
+            
+             @return Returns the necessary AC attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetNecessaryACAttributes(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the neccessary which must be contained in an attribute certificate.
+             <p>
+             The <code>ISet</code> must contain <code>String</code>s with the
+             OIDs.
+             </p><p>
+             The set is cloned.
+             </p>
+            
+             @param necessaryACAttributes The necessary AC attributes to set.
+             @throws ClassCastException if an element of
+                         <code>necessaryACAttributes</code> is not a
+                         <code>String</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetProhibitedACAttributes">
+             Returns the attribute certificates which are not allowed.
+             <p>
+             The returned <code>ISet</code> is immutable and contains
+             <code>String</code>s with the OIDs.
+             </p>
+            
+             @return Returns the prohibited AC attributes. Is never <code>null</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetProhibitedACAttributes(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the attribute certificates which are not allowed.
+             <p>
+             The <code>ISet</code> must contain <code>String</code>s with the
+             OIDs.
+             </p><p>
+             The set is cloned.
+             </p>
+            
+             @param prohibitedACAttributes The prohibited AC attributes to set.
+             @throws ClassCastException if an element of
+                         <code>prohibitedACAttributes</code> is not a
+                         <code>String</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetAttrCertCheckers">
+             Returns the attribute certificate checker. The returned set contains
+             {@link PKIXAttrCertChecker}s and is immutable.
+            
+             @return Returns the attribute certificate checker. Is never
+                     <code>null</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetAttrCertCheckers(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the attribute certificate checkers.
+             <p>
+             All elements in the <code>ISet</code> must a {@link PKIXAttrCertChecker}.
+             </p>
+             <p>
+             The given set is cloned.
+             </p>
+            
+             @param attrCertCheckers The attribute certificate checkers to set. Is
+                        never <code>null</code>.
+             @throws ClassCastException if an element of <code>attrCertCheckers</code>
+                         is not a <code>PKIXAttrCertChecker</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.IsUseDeltasEnabled">
+            Whether delta CRLs should be used for checking the revocation status.
+            Defaults to <code>false</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.ValidityModel">
+            The validity model.
+            @see #CHAIN_VALIDITY_MODEL
+            @see #PKIX_VALIDITY_MODEL
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.IsAdditionalLocationsEnabled">
+             Returns if additional {@link X509Store}s for locations like LDAP found
+             in certificates or CRLs should be used.
+            
+             @return Returns <code>true</code> if additional stores are used.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.GetInstance(Org.BouncyCastle.Pkix.PkixParameters)">
+             Returns an instance of <code>PkixBuilderParameters</code>.
+             <p>
+             This method can be used to get a copy from other
+             <code>PKIXBuilderParameters</code>, <code>PKIXParameters</code>,
+             and <code>ExtendedPKIXParameters</code> instances.
+             </p>
+            
+             @param pkixParams The PKIX parameters to create a copy of.
+             @return An <code>PkixBuilderParameters</code> instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.GetExcludedCerts">
+            <summary>
+            Excluded certificates are not used for building a certification path.
+            </summary>
+            <returns>the excluded certificates.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.SetExcludedCerts(Org.BouncyCastle.Utilities.Collections.ISet)">
+            <summary>
+            Sets the excluded certificates which are not used for building a
+            certification path. If the <code>ISet</code> is <code>null</code> an
+            empty set is assumed.
+            </summary>
+            <remarks>
+            The given set is cloned to protect it against subsequent modifications.
+            </remarks>
+            <param name="excludedCerts">The excluded certificates to set.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.SetParams(Org.BouncyCastle.Pkix.PkixParameters)">
+            Can alse handle <code>ExtendedPKIXBuilderParameters</code> and
+            <code>PKIXBuilderParameters</code>.
+            
+            @param params Parameters to set.
+            @see org.bouncycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.Clone">
+             Makes a copy of this <code>PKIXParameters</code> object. Changes to the
+             copy will not affect the original and vice versa.
+            
+             @return a copy of this <code>PKIXParameters</code> object
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPath">
+             An immutable sequence of certificates (a certification path).<br />
+             <br />
+             This is an abstract class that defines the methods common to all CertPaths.
+             Subclasses can handle different kinds of certificates (X.509, PGP, etc.).<br />
+             <br />
+             All CertPath objects have a type, a list of Certificates, and one or more
+             supported encodings. Because the CertPath class is immutable, a CertPath
+             cannot change in any externally visible way after being constructed. This
+             stipulation applies to all public fields and methods of this class and any
+             added or overridden by subclasses.<br />
+             <br />
+             The type is a string that identifies the type of Certificates in the
+             certification path. For each certificate cert in a certification path
+             certPath, cert.getType().equals(certPath.getType()) must be true.<br />
+             <br />
+             The list of Certificates is an ordered List of zero or more Certificates.
+             This List and all of the Certificates contained in it must be immutable.<br />
+             <br />
+             Each CertPath object must support one or more encodings so that the object
+             can be translated into a byte array for storage or transmission to other
+             parties. Preferably, these encodings should be well-documented standards
+             (such as PKCS#7). One of the encodings supported by a CertPath is considered
+             the default encoding. This encoding is used if no encoding is explicitly
+             requested (for the {@link #getEncoded()} method, for instance).<br />
+             <br />
+             All CertPath objects are also Serializable. CertPath objects are resolved
+             into an alternate {@link CertPathRep} object during serialization. This
+             allows a CertPath object to be serialized into an equivalent representation
+             regardless of its underlying implementation.<br />
+             <br />
+             CertPath objects can be created with a CertificateFactory or they can be
+             returned by other classes, such as a CertPathBuilder.<br />
+             <br />
+             By convention, X.509 CertPaths (consisting of X509Certificates), are ordered
+             starting with the target certificate and ending with a certificate issued by
+             the trust anchor. That is, the issuer of one certificate is the subject of
+             the following one. The certificate representing the
+             {@link TrustAnchor TrustAnchor} should not be included in the certification
+             path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX
+             CertPathValidators will detect any departure from these conventions that
+             cause the certification path to be invalid and throw a
+             CertPathValidatorException.<br />
+             <br />
+             <strong>Concurrent Access</strong><br />
+             <br />
+             All CertPath objects must be thread-safe. That is, multiple threads may
+             concurrently invoke the methods defined in this class on a single CertPath
+             object (or more than one) with no ill effects. This is also true for the List
+             returned by CertPath.getCertificates.<br />
+             <br />
+             Requiring CertPath objects to be immutable and thread-safe allows them to be
+             passed around to various pieces of code without worrying about coordinating
+             access. Providing this thread-safety is generally not difficult, since the
+             CertPath and List objects in question are immutable.
+            
+             @see CertificateFactory
+             @see CertPathBuilder
+            <summary>
+            CertPath implementation for X.509 certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.SortCerts(System.Collections.IList)">
+            @param certs
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.#ctor(System.Collections.ICollection)">
+             Creates a CertPath of the specified type.
+             This constructor is protected because most users should use
+             a CertificateFactory to create CertPaths.
+             @param type the standard name of the type of Certificatesin this path
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.#ctor(System.IO.Stream,System.String)">
+             Creates a CertPath of the specified type.
+             This constructor is protected because most users should use
+             a CertificateFactory to create CertPaths.
+            
+             @param type the standard name of the type of Certificatesin this path
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.Equals(System.Object)">
+             Compares this certification path for equality with the specified object.
+             Two CertPaths are equal if and only if their types are equal and their
+             certificate Lists (and by implication the Certificates in those Lists)
+             are equal. A CertPath is never equal to an object that is not a CertPath.<br />
+             <br />
+             This algorithm is implemented by this method. If it is overridden, the
+             behavior specified here must be maintained.
+            
+             @param other
+                        the object to test for equality with this certification path
+            
+             @return true if the specified object is equal to this certification path,
+                     false otherwise
+            
+             @see Object#hashCode() Object.hashCode()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.GetEncoded">
+             Returns the encoded form of this certification path, using
+             the default encoding.
+            
+             @return the encoded bytes
+             @exception CertificateEncodingException if an encoding error occurs
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.GetEncoded(System.String)">
+             Returns the encoded form of this certification path, using
+             the specified encoding.
+            
+             @param encoding the name of the encoding to use
+             @return the encoded bytes
+             @exception CertificateEncodingException if an encoding error
+             occurs or the encoding requested is not supported
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.ToAsn1Object(Org.BouncyCastle.X509.X509Certificate)">
+             Return a DERObject containing the encoded certificate.
+            
+             @param cert the X509Certificate object to be encoded
+            
+             @return the DERObject
+            
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPath.Encodings">
+             Returns an iteration of the encodings supported by this
+             certification path, with the default encoding
+             first. Attempts to modify the returned Iterator via its
+             remove method result in an UnsupportedOperationException.
+            
+             @return an Iterator over the names of the supported encodings (as Strings)
+            
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPath.Certificates">
+            <summary>
+            Returns the list of certificates in this certification
+            path.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilder">
+             Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
+            
+             @see CertPathBuilderSpi
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathBuilder.Build(Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Build and validate a CertPath using the given parameter.
+            
+             @param params PKIXBuilderParameters object containing all information to
+                        build the CertPath
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilderException">
+            <summary>
+            Summary description for PkixCertPathBuilderException.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilderResult">
+            <summary>
+            Summary description for PkixCertPathBuilderResult.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorResult">
+            <summary>
+            Summary description for PkixCertPathValidatorResult.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Init(System.Boolean)">
+                     * Initializes the internal state of this <code>PKIXCertPathChecker</code>.
+                     * <p>
+                     * The <code>forward</code> flag specifies the order that certificates
+                     * will be passed to the {@link #check check} method (forward or reverse). A
+                     * <code>PKIXCertPathChecker</code> <b>must</b> support reverse checking
+                     * and <b>may</b> support forward checking.
+            		 * </p>
+                     * 
+                     * @param forward
+                     *            the order that certificates are presented to the
+                     *            <code>check</code> method. If <code>true</code>,
+                     *            certificates are presented from target to most-trusted CA
+                     *            (forward); if <code>false</code>, from most-trusted CA to
+                     *            target (reverse).
+                     * @exception CertPathValidatorException
+                     *                if this <code>PKIXCertPathChecker</code> is unable to
+                     *                check certificates in the specified order; it should never
+                     *                be thrown if the forward flag is false since reverse
+                     *                checking must be supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.IsForwardCheckingSupported">
+            Indicates if forward checking is supported. Forward checking refers to
+            the ability of the <code>PKIXCertPathChecker</code> to perform its
+            checks when certificates are presented to the <code>check</code> method
+            in the forward direction (from target to most-trusted CA).
+            
+            @return <code>true</code> if forward checking is supported,
+                    <code>false</code> otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.GetSupportedExtensions">
+                     * Returns an immutable <code>Set</code> of X.509 certificate extensions
+                     * that this <code>PKIXCertPathChecker</code> supports (i.e. recognizes,
+                     * is able to process), or <code>null</code> if no extensions are
+                     * supported.
+                     * <p>
+                     * Each element of the set is a <code>String</code> representing the
+                     * Object Identifier (OID) of the X.509 extension that is supported. The OID
+                     * is represented by a set of nonnegative integers separated by periods.
+                     * </p><p>
+                     * All X.509 certificate extensions that a <code>PKIXCertPathChecker</code>
+                     * might possibly be able to process should be included in the set.
+            		 * </p>
+                     * 
+                     * @return an immutable <code>Set</code> of X.509 extension OIDs (in
+                     *         <code>String</code> format) supported by this
+                     *         <code>PKIXCertPathChecker</code>, or <code>null</code> if no
+                     *         extensions are supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Check(Org.BouncyCastle.X509.X509Certificate,System.Collections.ICollection)">
+            Performs the check(s) on the specified certificate using its internal
+            state and removes any critical extensions that it processes from the
+            specified collection of OID strings that represent the unresolved
+            critical extensions. The certificates are presented in the order
+            specified by the <code>init</code> method.
+            
+            @param cert
+                       the <code>Certificate</code> to be checked
+            @param unresolvedCritExts
+                       a <code>Collection</code> of OID strings representing the
+                       current set of unresolved critical extensions
+            @exception CertPathValidatorException
+                           if the specified certificate does not pass the check
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Clone">
+            Returns a clone of this object. Calls the <code>Object.clone()</code>
+            method. All subclasses which maintain state must support and override
+            this method, if necessary.
+            
+            @return a copy of this <code>PKIXCertPathChecker</code>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidator">
+            The <i>Service Provider Interface</i> (<b>SPI</b>)
+            for the {@link CertPathValidator CertPathValidator} class. All
+            <code>CertPathValidator</code> implementations must include a class (the
+            SPI class) that extends this class (<code>CertPathValidatorSpi</code>)
+            and implements all of its methods. In general, instances of this class
+            should only be accessed through the <code>CertPathValidator</code> class.
+            For details, see the Java Cryptography Architecture.<br />
+            <br />
+            <b>Concurrent Access</b><br />
+            <br />
+            Instances of this class need not be protected against concurrent
+            access from multiple threads. Threads that need to access a single
+            <code>CertPathValidatorSpi</code> instance concurrently should synchronize
+            amongst themselves and provide the necessary locking before calling the
+            wrapping <code>CertPathValidator</code> object.<br />
+            <br />
+            However, implementations of <code>CertPathValidatorSpi</code> may still
+            encounter concurrency issues, since multiple threads each
+            manipulating a different <code>CertPathValidatorSpi</code> instance need not
+            synchronize.
+            <summary>
+            CertPathValidatorSpi implementation for X.509 Certificate validation a la RFC
+            3280.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorException">
+             An exception indicating one of a variety of problems encountered when 
+             validating a certification path. <br />
+             <br />
+             A <code>CertPathValidatorException</code> provides support for wrapping
+             exceptions. The {@link #getCause getCause} method returns the throwable, 
+             if any, that caused this exception to be thrown. <br />
+             <br />
+             A <code>CertPathValidatorException</code> may also include the 
+             certification path that was being validated when the exception was thrown 
+             and the index of the certificate in the certification path that caused the 
+             exception to be thrown. Use the {@link #getCertPath getCertPath} and
+             {@link #getIndex getIndex} methods to retrieve this information.<br />
+             <br />
+             <b>Concurrent Access</b><br />
+             <br />
+             Unless otherwise specified, the methods defined in this class are not
+             thread-safe. Multiple threads that need to access a single
+             object concurrently should synchronize amongst themselves and
+             provide the necessary locking. Multiple threads each manipulating
+             separate objects need not synchronize.
+            
+             @see CertPathValidator
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the given detail
+            message. A detail message is a <code>String</code> that describes this
+            particular exception. 
+            </summary>
+            <param name="message">the detail message</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String,System.Exception)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the specified
+            detail message and cause.
+            </summary>
+            <param name="message">the detail message</param>
+            <param name="cause">the cause (which is saved for later retrieval by the
+            {@link #getCause getCause()} method). (A <code>null</code>
+            value is permitted, and indicates that the cause is
+            nonexistent or unknown.)</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String,System.Exception,Org.BouncyCastle.Pkix.PkixCertPath,System.Int32)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the specified
+            detail message, cause, certification path, and index.
+            </summary>
+            <param name="message">the detail message (or <code>null</code> if none)</param>
+            <param name="cause">the cause (or <code>null</code> if none)</param>
+            <param name="certPath">the certification path that was in the process of being
+            validated when the error was encountered</param>
+            <param name="index">the index of the certificate in the certification path that</param>																																																																																   * 
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.Message">
+            <summary>
+            Returns the detail message for this <code>CertPathValidatorException</code>.
+            </summary>
+            <returns>the detail message, or <code>null</code> if neither the message nor cause were specified</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.CertPath">
+            Returns the certification path that was being validated when the
+            exception was thrown.
+            
+            @return the <code>CertPath</code> that was being validated when the
+                    exception was thrown (or <code>null</code> if not specified)
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.Index">
+            Returns the index of the certificate in the certification path that
+            caused the exception to be thrown. Note that the list of certificates in
+            a <code>CertPath</code> is zero based. If no index has been set, -1 is
+            returned.
+            
+            @return the index that has been set, or -1 if none has been set
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities">
+            <summary>
+            Summary description for PkixCertPathValidatorUtilities.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.KEY_CERT_SIGN">
+            <summary>
+            key usage bits
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindTrustAnchor(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Utilities.Collections.ISet)">
+            <summary>
+            Search the given Set of TrustAnchor's for one that is the
+            issuer of the given X509 certificate.
+            </summary>
+            <param name="cert">the X509 certificate</param>
+            <param name="trustAnchors">a Set of TrustAnchor's</param>
+            <returns>the <code>TrustAnchor</code> object if found or
+            <code>null</code> if not.
+            </returns>
+            @exception
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetIssuerPrincipal(System.Object)">
+            <summary>
+            Returns the issuer of an attribute certificate or certificate.
+            </summary>
+            <param name="cert">The attribute certificate or certificate.</param>
+            <returns>The issuer as <code>X500Principal</code>.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetNextWorkingKey(System.Collections.IList,System.Int32)">
+             Return the next working key inheriting DSA parameters if necessary.
+             <p>
+             This methods inherits DSA parameters from the indexed certificate or
+             previous certificates in the certificate chain to the returned
+             <code>PublicKey</code>. The list is searched upwards, meaning the end
+             certificate is at position 0 and previous certificates are following.
+             </p>
+             <p>
+             If the indexed certificate does not contain a DSA key this method simply
+             returns the public key. If the DSA key already contains DSA parameters
+             the key is also only returned.
+             </p>
+            
+             @param certs The certification path.
+             @param index The index of the certificate which contains the public key
+                        which should be extended with DSA parameters.
+             @return The public key of the certificate in list position
+                     <code>index</code> extended with DSA parameters if applicable.
+             @throws Exception if DSA parameters cannot be inherited.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindCertificates(Org.BouncyCastle.X509.Store.X509CertStoreSelector,System.Collections.IList)">
+            <summary>
+            Return a Collection of all certificates or attribute certificates found
+            in the X509Store's that are matching the certSelect criteriums.
+            </summary>
+            <param name="certSelect">a {@link Selector} object that will be used to select
+            the certificates</param>
+            <param name="certStores">a List containing only X509Store objects. These
+            are used to search for certificates.</param>
+            <returns>a Collection of all found <see cref="T:Org.BouncyCastle.X509.X509Certificate"/> or
+            <see cref="T:Org.BouncyCastle.X509.IX509AttributeCertificate"/> objects.
+            May be empty but never <code>null</code>.</returns>
+            <exception cref="T:System.Exception"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetCrlIssuersFromDistributionPoint(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Collections.ICollection,Org.BouncyCastle.X509.Store.X509CrlStoreSelector,Org.BouncyCastle.Pkix.PkixParameters)">
+             Add the CRL issuers from the cRLIssuer field of the distribution point or
+             from the certificate if not given to the issuer criterion of the
+             <code>selector</code>.
+             <p>
+             The <code>issuerPrincipals</code> are a collection with a single
+             <code>X500Principal</code> for <code>X509Certificate</code>s. For
+             {@link X509AttributeCertificate}s the issuer may contain more than one
+             <code>X500Principal</code>.
+             </p>
+            
+             @param dp The distribution point.
+             @param issuerPrincipals The issuers of the certificate or attribute
+                        certificate which contains the distribution point.
+             @param selector The CRL selector.
+             @param pkixParams The PKIX parameters containing the cert stores.
+             @throws Exception if an exception occurs while processing.
+             @throws ClassCastException if <code>issuerPrincipals</code> does not
+             contain only <code>X500Principal</code>s.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetCompleteCrls(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,System.DateTime,Org.BouncyCastle.Pkix.PkixParameters)">
+             Fetches complete CRLs according to RFC 3280.
+            
+             @param dp The distribution point for which the complete CRL
+             @param cert The <code>X509Certificate</code> or
+                        {@link org.bouncycastle.x509.X509AttributeCertificate} for
+                        which the CRL should be searched.
+             @param currentDate The date for which the delta CRLs must be valid.
+             @param paramsPKIX The extended PKIX parameters.
+             @return A <code>Set</code> of <code>X509CRL</code>s with complete
+                     CRLs.
+             @throws Exception if an exception occurs while picking the CRLs
+                         or no CRLs are found.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetDeltaCrls(System.DateTime,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Crl)">
+             Fetches delta CRLs according to RFC 3280 section 5.2.4.
+            
+             @param currentDate The date for which the delta CRLs must be valid.
+             @param paramsPKIX The extended PKIX parameters.
+             @param completeCRL The complete CRL the delta CRL is for.
+             @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
+             @throws Exception if an exception occurs while picking the delta
+                         CRLs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindIssuerCerts(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Find the issuer certificates of a given certificate.
+            
+             @param cert
+                        The certificate for which an issuer should be found.
+             @param pkixParams
+             @return A <code>Collection</code> object containing the issuer
+                     <code>X509Certificate</code>s. Never <code>null</code>.
+            
+             @exception Exception
+                            if an error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetExtensionValue(Org.BouncyCastle.X509.IX509Extension,Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            <summary>
+            Extract the value of the given extension, if it exists.
+            </summary>
+            <param name="ext">The extension object.</param>
+            <param name="oid">The object identifier to obtain.</param>
+            <returns>Asn1Object</returns>
+            <exception cref="T:System.Exception">if the extension cannot be read.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCrlUtilities.FindCrls(Org.BouncyCastle.X509.Store.X509CrlStoreSelector,System.Collections.IList)">
+            <summary>
+            crl checking
+            Return a Collection of all CRLs found in the X509Store's that are
+            matching the crlSelect criteriums.
+            </summary>
+            <param name="crlSelect">a {@link X509CRLStoreSelector} object that will be used
+            to select the CRLs</param>
+            <param name="crlStores">a List containing only {@link org.bouncycastle.x509.X509Store
+            X509Store} objects. These are used to search for CRLs</param>
+            <returns>a Collection of all found {@link X509CRL X509CRL} objects. May be
+            empty but never <code>null</code>.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectIP(Org.BouncyCastle.Utilities.Collections.ISet,Org.BouncyCastle.Utilities.Collections.ISet)">
+             Returns the intersection of the permitted IP ranges in
+             <code>permitted</code> with <code>ip</code>.
+            
+             @param permitted A <code>Set</code> of permitted IP addresses with
+                              their subnet mask as byte arrays.
+             @param ips       The IP address with its subnet mask.
+             @return The <code>Set</code> of permitted IP ranges intersected with
+                     <code>ip</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.UnionIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Returns the union of the excluded IP ranges in <code>excluded</code>
+             with <code>ip</code>.
+            
+             @param excluded A <code>Set</code> of excluded IP addresses with their
+                             subnet mask as byte arrays.
+             @param ip       The IP address with its subnet mask.
+             @return The <code>Set</code> of excluded IP ranges unified with
+                     <code>ip</code> as byte arrays.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.UnionIPRange(System.Byte[],System.Byte[])">
+             Calculates the union if two IP ranges.
+            
+             @param ipWithSubmask1 The first IP address with its subnet mask.
+             @param ipWithSubmask2 The second IP address with its subnet mask.
+             @return A <code>Set</code> with the union of both addresses.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectIPRange(System.Byte[],System.Byte[])">
+             Calculates the interesction if two IP ranges.
+            
+             @param ipWithSubmask1 The first IP address with its subnet mask.
+             @param ipWithSubmask2 The second IP address with its subnet mask.
+             @return A <code>Set</code> with the single IP address with its subnet
+                     mask as a byte array or an empty <code>Set</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IpWithSubnetMask(System.Byte[],System.Byte[])">
+             Concatenates the IP address with its subnet mask.
+            
+             @param ip         The IP address.
+             @param subnetMask Its subnet mask.
+             @return The concatenated IP address with its subnet mask.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.ExtractIPsAndSubnetMasks(System.Byte[],System.Byte[])">
+             Splits the IP addresses and their subnet mask.
+            
+             @param ipWithSubmask1 The first IP address with the subnet mask.
+             @param ipWithSubmask2 The second IP address with the subnet mask.
+             @return An array with two elements. Each element contains the IP address
+                     and the subnet mask in this order.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.MinMaxIPs(System.Byte[],System.Byte[],System.Byte[],System.Byte[])">
+             Based on the two IP addresses and their subnet masks the IP range is
+             computed for each IP address - subnet mask pair and returned as the
+             minimum IP address and the maximum address of the range.
+            
+             @param ip1         The first IP address.
+             @param subnetmask1 The subnet mask of the first IP address.
+             @param ip2         The second IP address.
+             @param subnetmask2 The subnet mask of the second IP address.
+             @return A array with two elements. The first/second element contains the
+                     min and max IP address of the first/second IP address and its
+                     subnet mask.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.CheckPermittedIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Checks if the IP <code>ip</code> is included in the permitted ISet
+             <code>permitted</code>.
+            
+             @param permitted A <code>Set</code> of permitted IP addresses with
+                              their subnet mask as byte arrays.
+             @param ip        The IP address.
+             @throws PkixNameConstraintValidatorException
+                      if the IP is not permitted.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkExcludedIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Checks if the IP <code>ip</code> is included in the excluded ISet
+             <code>excluded</code>.
+            
+             @param excluded A <code>Set</code> of excluded IP addresses with their
+                             subnet mask as byte arrays.
+             @param ip       The IP address.
+             @throws PkixNameConstraintValidatorException
+                      if the IP is excluded.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IsIPConstrained(System.Byte[],System.Byte[])">
+             Checks if the IP address <code>ip</code> is constrained by
+             <code>constraint</code>.
+            
+             @param ip         The IP address.
+             @param constraint The constraint. This is an IP address concatenated with
+                               its subnetmask.
+             @return <code>true</code> if constrained, <code>false</code>
+                     otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.unionEmail(System.String,System.String,Org.BouncyCastle.Utilities.Collections.ISet)">
+             The common part of <code>email1</code> and <code>email2</code> is
+             added to the union <code>union</code>. If <code>email1</code> and
+             <code>email2</code> have nothing in common they are added both.
+            
+             @param email1 Email address constraint 1.
+             @param email2 Email address constraint 2.
+             @param union  The union.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.intersectEmail(System.String,System.String,Org.BouncyCastle.Utilities.Collections.ISet)">
+             The most restricting part from <code>email1</code> and
+             <code>email2</code> is added to the intersection <code>intersect</code>.
+            
+             @param email1    Email address constraint 1.
+             @param email2    Email address constraint 2.
+             @param intersect The intersection.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkPermitted(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Checks if the given GeneralName is in the permitted ISet.
+            
+             @param name The GeneralName
+             @throws PkixNameConstraintValidatorException
+                      If the <code>name</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkExcluded(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Check if the given GeneralName is contained in the excluded ISet.
+            
+             @param name The GeneralName.
+             @throws PkixNameConstraintValidatorException
+                      If the <code>name</code> is
+                      excluded.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectPermittedSubtree(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Updates the permitted ISet of these name constraints with the intersection
+             with the given subtree.
+            
+             @param permitted The permitted subtrees
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.AddExcludedSubtree(Org.BouncyCastle.Asn1.X509.GeneralSubtree)">
+             Adds a subtree to the excluded ISet of these name constraints.
+            
+             @param subtree A subtree with an excluded GeneralName.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Max(System.Byte[],System.Byte[])">
+             Returns the maximum IP address.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The maximum IP address.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Min(System.Byte[],System.Byte[])">
+             Returns the minimum IP address.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The minimum IP address.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.CompareTo(System.Byte[],System.Byte[])">
+             Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1
+             is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1
+             otherwise.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Or(System.Byte[],System.Byte[])">
+             Returns the logical OR of the IP addresses <code>ip1</code> and
+             <code>ip2</code>.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The OR of <code>ip1</code> and <code>ip2</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.StringifyIP(System.Byte[])">
+             Stringifies an IPv4 or v6 address with subnet mask.
+            
+             @param ip The IP with subnet mask.
+             @return The stringified IP address.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixPolicyNode">
+            <summary>
+            Summary description for PkixPolicyNode.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixPolicyNode.#ctor(System.Collections.IList,System.Int32,Org.BouncyCastle.Utilities.Collections.ISet,Org.BouncyCastle.Pkix.PkixPolicyNode,Org.BouncyCastle.Utilities.Collections.ISet,System.String,System.Boolean)">
+            Constructors
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.ReasonsMask">
+            <summary>
+            This class helps to handle CRL revocation reasons mask. Each CRL handles a
+            certain set of revocation reasons.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.#ctor(System.Int32)">
+            <summary>
+            Constructs are reason mask with the reasons.
+            </summary>
+            <param name="reasons">The reasons.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.#ctor">
+            <summary>
+            A reason mask with no reason.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.ReasonsMask.AllReasons">
+            <summary>
+            A mask with all revocation reasons.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.AddReasons(Org.BouncyCastle.Pkix.ReasonsMask)">
+             Adds all reasons from the reasons mask to this mask.
+            
+             @param mask The reasons mask to add.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.Intersect(Org.BouncyCastle.Pkix.ReasonsMask)">
+            <summary>
+            Intersects this mask with the given reasons mask.
+            </summary>
+            <param name="mask">mask The mask to intersect with.</param>
+            <returns>The intersection of this and teh given mask.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.HasNewReasons(Org.BouncyCastle.Pkix.ReasonsMask)">
+            <summary>
+            Returns <c>true</c> if the passed reasons mask has new reasons.
+            </summary>
+            <param name="mask">The reasons mask which should be tested for new reasons.</param>
+            <returns><c>true</c> if the passed reasons mask has new reasons.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.ReasonsMask.IsAllReasons">
+            <summary>
+            Returns <code>true</code> if this reasons mask contains all possible
+            reasons.
+            </summary>
+            <returns>true if this reasons mask contains all possible reasons.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.ReasonsMask.Reasons">
+            <summary>
+            Returns the reasons in this mask.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlB2(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,Org.BouncyCastle.X509.X509Crl)">
+             If the complete CRL includes an issuing distribution point (IDP) CRL
+             extension check the following:
+             <p>
+             (i) If the distribution point name is present in the IDP CRL extension
+             and the distribution field is present in the DP, then verify that one of
+             the names in the IDP matches one of the names in the DP. If the
+             distribution point name is present in the IDP CRL extension and the
+             distribution field is omitted from the DP, then verify that one of the
+             names in the IDP matches one of the names in the cRLIssuer field of the
+             DP.
+             </p>
+             <p>
+             (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
+             extension, verify that the certificate does not include the basic
+             constraints extension with the cA boolean asserted.
+             </p>
+             <p>
+             (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
+             extension, verify that the certificate includes the basic constraints
+             extension with the cA boolean asserted.
+             </p>
+             <p>
+             (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
+             </p>
+            
+             @param dp   The distribution point.
+             @param cert The certificate.
+             @param crl  The CRL.
+             @throws AnnotatedException if one of the conditions is not met or an error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlB1(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,Org.BouncyCastle.X509.X509Crl)">
+             If the DP includes cRLIssuer, then verify that the issuer field in the
+             complete CRL matches cRLIssuer in the DP and that the complete CRL
+             contains an
+                  g distribution point extension with the indirectCRL
+             boolean asserted. Otherwise, verify that the CRL issuer matches the
+             certificate issuer.
+            
+             @param dp   The distribution point.
+             @param cert The certificate ot attribute certificate.
+             @param crl  The CRL for <code>cert</code>.
+             @throws AnnotatedException if one of the above conditions does not apply or an error
+                                        occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlF(Org.BouncyCastle.X509.X509Crl,System.Object,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Pkix.PkixParameters,System.Collections.IList)">
+             Obtain and validate the certification path for the complete CRL issuer.
+             If a key usage extension is present in the CRL issuer's certificate,
+             verify that the cRLSign bit is set.
+            
+             @param crl                CRL which contains revocation information for the certificate
+                                       <code>cert</code>.
+             @param cert               The attribute certificate or certificate to check if it is
+                                       revoked.
+             @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+             @param defaultCRLSignKey  The public key of the issuer certificate
+                                       <code>defaultCRLSignCert</code>.
+             @param paramsPKIX         paramsPKIX PKIX parameters.
+             @param certPathCerts      The certificates on the certification path.
+             @return A <code>Set</code> with all keys of possible CRL issuer
+                     certificates.
+             @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
+                                        some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.CheckCrl(Org.BouncyCastle.Asn1.X509.DistributionPoint,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Pkix.CertStatus,Org.BouncyCastle.Pkix.ReasonsMask,System.Collections.IList)">
+             Checks a distribution point for revocation information for the
+             certificate <code>cert</code>.
+            
+             @param dp                 The distribution point to consider.
+             @param paramsPKIX         PKIX parameters.
+             @param cert               Certificate to check if it is revoked.
+             @param validDate          The date when the certificate revocation status should be
+                                       checked.
+             @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+             @param defaultCRLSignKey  The public key of the issuer certificate
+                                       <code>defaultCRLSignCert</code>.
+             @param certStatus         The current certificate revocation status.
+             @param reasonMask         The reasons mask which is already checked.
+             @param certPathCerts      The certificates of the certification path.
+             @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+                                        or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.CheckCrls(Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Collections.IList)">
+             Checks a certificate if it is revoked.
+            
+             @param paramsPKIX       PKIX parameters.
+             @param cert             Certificate to check if it is revoked.
+             @param validDate        The date when the certificate revocation status should be
+                                     checked.
+             @param sign             The issuer certificate of the certificate <code>cert</code>.
+             @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
+             @param certPathCerts    The certificates of the certification path.
+             @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+                                        or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlC(Org.BouncyCastle.X509.X509Crl,Org.BouncyCastle.X509.X509Crl,Org.BouncyCastle.Pkix.PkixParameters)">
+             If use-deltas is set, verify the issuer and scope of the delta CRL.
+            
+             @param deltaCRL    The delta CRL.
+             @param completeCRL The complete CRL.
+             @param pkixParams  The PKIX paramaters.
+             @throws AnnotatedException if an exception occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.CheckCrls(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,System.Collections.IList)">
+            Checks if an attribute certificate is revoked.
+            
+            @param attrCert Attribute certificate to check if it is revoked.
+            @param paramsPKIX PKIX parameters.
+            @param issuerCert The issuer certificate of the attribute certificate
+                       <code>attrCert</code>.
+            @param validDate The date when the certificate revocation status should
+                       be checked.
+            @param certPathCerts The certificates of the certification path to be
+                       checked.
+            
+            @throws CertPathValidatorException if the certificate is revoked or the
+                        status cannot be checked or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.ProcessAttrCert1(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters)">
+            Searches for a holder public key certificate and verifies its
+            certification path.
+            
+            @param attrCert the attribute certificate.
+            @param pkixParams The PKIX parameters.
+            @return The certificate path of the holder certificate.
+            @throws Exception if
+                        <ul>
+                        <li>no public key certificate can be found although holder
+                        information is given by an entity name or a base certificate
+                        ID</li>
+                        <li>support classes cannot be created</li>
+                        <li>no certification path for the public key certificate can
+                        be built</li>
+                        </ul>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.CheckCrl(Org.BouncyCastle.Asn1.X509.DistributionPoint,Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Pkix.CertStatus,Org.BouncyCastle.Pkix.ReasonsMask,System.Collections.IList)">
+            
+            Checks a distribution point for revocation information for the
+            certificate <code>attrCert</code>.
+            
+            @param dp The distribution point to consider.
+            @param attrCert The attribute certificate which should be checked.
+            @param paramsPKIX PKIX parameters.
+            @param validDate The date when the certificate revocation status should
+                       be checked.
+            @param issuerCert Certificate to check if it is revoked.
+            @param reasonMask The reasons mask which is already checked.
+            @param certPathCerts The certificates of the certification path to be
+                       checked.
+            @throws Exception if the certificate is revoked or the status
+                        cannot be checked or some error occurs.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.TrustAnchor">
+            <summary>
+            A trust anchor or most-trusted Certification Authority (CA).
+            
+            This class represents a "most-trusted CA", which is used as a trust anchor
+            for validating X.509 certification paths. A most-trusted CA includes the
+            public key of the CA, the CA's name, and any constraints upon the set of
+            paths which may be validated using this key. These parameters can be
+            specified in the form of a trusted X509Certificate or as individual
+            parameters.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(Org.BouncyCastle.X509.X509Certificate,System.Byte[])">
+             <summary>
+             Creates an instance of TrustAnchor with the specified X509Certificate and
+             optional name constraints, which are intended to be used as additional
+             constraints when validating an X.509 certification path.
+            	The name constraints are specified as a byte array. This byte array
+            	should contain the DER encoded form of the name constraints, as they
+            	would appear in the NameConstraints structure defined in RFC 2459 and
+            	X.509. The ASN.1 definition of this structure appears below.
+            	
+            	<pre>
+            	NameConstraints ::= SEQUENCE {
+            		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+            		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+            	   
+             GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+             
+            		GeneralSubtree ::= SEQUENCE {
+            		base                    GeneralName,
+            		minimum         [0]     BaseDistance DEFAULT 0,
+            		maximum         [1]     BaseDistance OPTIONAL }
+            		
+            		BaseDistance ::= INTEGER (0..MAX)
+            
+            		GeneralName ::= CHOICE {
+            		otherName                       [0]     OtherName,
+            		rfc822Name                      [1]     IA5String,
+            		dNSName                         [2]     IA5String,
+            		x400Address                     [3]     ORAddress,
+            		directoryName                   [4]     Name,
+            		ediPartyName                    [5]     EDIPartyName,
+            		uniformResourceIdentifier       [6]     IA5String,
+            		iPAddress                       [7]     OCTET STRING,
+            		registeredID                    [8]     OBJECT IDENTIFIER}
+            	</pre>
+            	
+            	Note that the name constraints byte array supplied is cloned to protect
+            	against subsequent modifications.
+             </summary>
+             <param name="trustedCert">a trusted X509Certificate</param>
+             <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+             NameConstraints extension to be used for checking name
+             constraints. Only the value of the extension is included, not
+             the OID or criticality flag. Specify null to omit the
+             parameter.</param>
+             <exception cref="T:System.ArgumentNullException">if the specified X509Certificate is null</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+            <summary>
+            Creates an instance of <c>TrustAnchor</c> where the
+            most-trusted CA is specified as an X500Principal and public key.
+            </summary>
+            <remarks>
+            <p>
+            Name constraints are an optional parameter, and are intended to be used
+            as additional constraints when validating an X.509 certification path.
+            </p><p>
+            The name constraints are specified as a byte array. This byte array
+            contains the DER encoded form of the name constraints, as they
+            would appear in the NameConstraints structure defined in RFC 2459
+            and X.509. The ASN.1 notation for this structure is supplied in the
+            documentation for the other constructors.
+            </p><p>
+            Note that the name constraints byte array supplied here is cloned to
+            protect against subsequent modifications.
+            </p>
+            </remarks>
+            <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
+            <param name="pubKey">the public key of the most-trusted CA</param>
+            <param name="nameConstraints">
+            a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
+            be used for checking name constraints. Only the value of the extension is included,
+            not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
+            </param>
+            <exception cref="T:System.ArgumentNullException">
+            if <c>caPrincipal</c> or <c>pubKey</c> is null
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+            <summary>
+            Creates an instance of <code>TrustAnchor</code> where the most-trusted
+            CA is specified as a distinguished name and public key. Name constraints
+            are an optional parameter, and are intended to be used as additional
+            constraints when validating an X.509 certification path.
+            <br/>
+            The name constraints are specified as a byte array. This byte array
+            contains the DER encoded form of the name constraints, as they would
+            appear in the NameConstraints structure defined in RFC 2459 and X.509.
+            </summary>
+            <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
+            2253 string format</param>
+            <param name="pubKey">the public key of the most-trusted CA</param>
+            <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+            NameConstraints extension to be used for checking name
+            constraints. Only the value of the extension is included, not 
+            the OID or criticality flag. Specify null to omit the 
+            parameter.</param>
+            throws NullPointerException, IllegalArgumentException
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.setNameConstraints(System.Byte[])">
+            <summary>
+            Decode the name constraints and clone them if not null.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.ToString">
+            <summary>
+            Returns a formatted string describing the <code>TrustAnchor</code>.
+            </summary>
+            <returns>a formatted string describing the <code>TrustAnchor</code></returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.TrustedCert">
+            <summary>
+            Returns the most-trusted CA certificate.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CA">
+            <summary>
+            Returns the name of the most-trusted CA as an X509Name.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CAName">
+            <summary>
+            Returns the name of the most-trusted CA in RFC 2253 string format.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CAPublicKey">
+            <summary>
+            Returns the public key of the most-trusted CA.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.AgreementUtilities">
+            <remarks>
+             Utility class for creating IBasicAgreement objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.CipherUtilities">
+            <remarks>
+             Cipher Utility class contains methods that can not be specifically grouped into other classes.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.CipherUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.DigestUtilities">
+            <remarks>
+             Utility class for creating IDigest objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.DigestUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a given digest mechanism.
+            </summary>
+            <param name="mechanism">A string representation of the digest meanism.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.MacUtilities">
+            <remarks>
+             Utility class for creating HMac object from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.PbeUtilities">
+             <summary>
+            
+             </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.PbeUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecureRandom.#ctor(Org.BouncyCastle.Crypto.Prng.IRandomGenerator)">
+            <summary>Use the specified instance of IRandomGenerator as random source.</summary>
+            <remarks>
+            This constructor performs no seeding of either the <c>IRandomGenerator</c> or the
+            constructed <c>SecureRandom</c>. It is the responsibility of the client to provide
+            proper seed material as necessary/appropriate for the given <c>IRandomGenerator</c>
+            implementation.
+            </remarks>
+            <param name="generator">The source to generate all random bytes from.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecurityUtilityException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecurityUtilityException.#ctor(System.String)">
+             create a SecurityUtilityException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="T:Org.BouncyCastle.Security.SignerUtilities">
+            <summary>
+             Signer Utility class contains methods that can not be specifically grouped into other classes.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SignerUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.WrapperUtilities">
+            <remarks>
+             Utility class for creating IWrapper objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampRequest">
+            Base class for an RFC 3161 Time Stamp Request.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.#ctor(System.Byte[])">
+             Create a TimeStampRequest from the past in byte array.
+            
+             @param req byte array containing the request.
+             @throws IOException if the request is malformed.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.#ctor(System.IO.Stream)">
+             Create a TimeStampRequest from the past in input stream.
+            
+             @param in input stream containing the request.
+             @throws IOException if the request is malformed.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.Validate(System.Collections.IList,System.Collections.IList,System.Collections.IList)">
+             Validate the timestamp request, checking the digest to see if it is of an
+             accepted type and whether it is of the correct length for the algorithm specified.
+            
+             @param algorithms a set of string OIDS giving accepted algorithms.
+             @param policies if non-null a set of policies we are willing to sign under.
+             @param extensions if non-null a set of extensions we are willing to accept.
+             @throws TspException if the request is invalid, or processing fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampRequestGenerator">
+            Generator for RFC 3161 Time Stamp Request objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 3)
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 3)
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampResponse">
+            Base class for an RFC 3161 Time Stamp Response object.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.#ctor(System.Byte[])">
+             Create a TimeStampResponse from a byte array containing an ASN.1 encoding.
+            
+             @param resp the byte array containing the encoded response.
+             @throws TspException if the response is malformed.
+             @throws IOException if the byte array doesn't represent an ASN.1 encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.#ctor(System.IO.Stream)">
+             Create a TimeStampResponse from an input stream containing an ASN.1 encoding.
+            
+             @param input the input stream containing the encoded response.
+             @throws TspException if the response is malformed.
+             @throws IOException if the stream doesn't represent an ASN.1 encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.Validate(Org.BouncyCastle.Tsp.TimeStampRequest)">
+             Check this response against to see if it a well formed response for
+             the passed in request. Validation will include checking the time stamp
+             token if the response status is GRANTED or GRANTED_WITH_MODS.
+            
+             @param request the request to be checked against
+             @throws TspException if the request can not match this response.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampResponseGenerator">
+            Generator for RFC 3161 Time Stamp Responses.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponseGenerator.Generate(Org.BouncyCastle.Tsp.TimeStampRequest,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Utilities.Date.DateTimeObject)">
+             Return an appropriate TimeStampResponse.
+             <p>
+             If genTime is null a timeNotAvailable error response will be returned.
+            
+             @param request the request this response is for.
+             @param serialNumber serial number for the response token.
+             @param genTime generation time for the response token.
+             @param provider provider to use for signature calculation.
+             @return
+             @throws NoSuchAlgorithmException
+             @throws NoSuchProviderException
+             @throws TSPException
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponseGenerator.GenerateFailResponse(Org.BouncyCastle.Asn1.Cmp.PkiStatus,System.Int32,System.String)">
+             Generate a TimeStampResponse with chosen status and FailInfoField.
+            
+             @param status the PKIStatus to set.
+             @param failInfoField the FailInfoField to set.
+             @param statusString an optional string describing the failure.
+             @return a TimeStampResponse with a failInfoField and optional statusString
+             @throws TSPException in case the response could not be created
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.Validate(Org.BouncyCastle.X509.X509Certificate)">
+            Validate the time stamp token.
+            <p>
+            To be valid the token must be signed by the passed in certificate and
+            the certificate must be the one referred to by the SigningCertificate
+            attribute included in the hashed attributes of the token. The
+            certificate must also have the ExtendedKeyUsageExtension with only
+            KeyPurposeID.IdKPTimeStamping and have been valid at the time the
+            timestamp was created.
+            </p>
+            <p>
+            A successful call to validate means all the above are true.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.ToCmsSignedData">
+             Return the underlying CmsSignedData object.
+            
+             @return the underlying CMS structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.GetEncoded">
+             Return a ASN.1 encoded byte stream representing the encoded object.
+            
+             @throws IOException if encoding fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampTokenGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+            basic creation - only the default attributes will be included here.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampTokenGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            create with a signer with extra signed/unsigned attributes.
+        </member>
+        <member name="P:Org.BouncyCastle.Tsp.TimeStampTokenInfo.Nonce">
+            @return the nonce value, null if there isn't one.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TspAlgorithms">
+            Recognised hash algorithms for the time stamp protocol.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.GetSignatureTimestamps(Org.BouncyCastle.Cms.SignerInformation)">
+             Fetches the signature time-stamp attributes from a SignerInformation object.
+             Checks that the MessageImprint for each time-stamp matches the signature field.
+             (see RFC 3161 Appendix A).
+            
+             @param signerInfo a SignerInformation to search for time-stamps
+             @return a collection of TimeStampToken objects
+             @throws TSPValidationException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.ValidateCertificate(Org.BouncyCastle.X509.X509Certificate)">
+             Validate the passed in certificate as being of the correct type to be used
+             for time stamping. To be valid it must have an ExtendedKeyUsage extension
+             which has a key purpose identifier of id-kp-timeStamping.
+            
+             @param cert the certificate of interest.
+             @throws TspValidationException if the certicate fails on one of the check points.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.GetDigestAlgName(System.String)">
+            <summary>
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TspValidationException">
+            Exception thrown if a TSP request or response fails to validate.
+            <p>
+            If a failure code is associated with the exception it can be retrieved using
+            the getFailureCode() method.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Tsp.TspValidationException.FailureCode">
+             Return the failure code associated with this exception - if one is set.
+            
+             @return the failure code if set, -1 otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Arrays">
+            <summary> General array utilities.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Arrays.AreEqual(System.Byte[],System.Byte[])">
+            <summary>
+            Are two arrays equal.
+            </summary>
+            <param name="a">Left side.</param>
+            <param name="b">Right side.</param>
+            <returns>True if equal.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Arrays.ConstantTimeAreEqual(System.Byte[],System.Byte[])">
+            <summary>
+            A constant time equals comparison - does not terminate early if
+            test will fail.
+            </summary>
+            <param name="a">first array</param>
+            <param name="b">second array</param>
+            <returns>true if arrays equal, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Arrays.CopyOfRange(System.Byte[],System.Int32,System.Int32)">
+             Make a copy of a range of bytes from the passed in data array. The range can
+             extend beyond the end of the input array, in which case the return array will
+             be padded with zeroes.
+            
+             @param data the array from which the data is to be copied.
+             @param from the start index at which the copying should take place.
+             @param to the final index of the range (exclusive).
+            
+             @return a new byte array containing the range given.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.BigIntegers">
+            BigInteger utilities.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.BigIntegers.AsUnsignedByteArray(Org.BouncyCastle.Math.BigInteger)">
+             Return the passed in value as an unsigned byte array.
+            
+             @param value value to be converted.
+             @return a byte array without a leading zero byte if present in the signed encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.BigIntegers.AsUnsignedByteArray(System.Int32,Org.BouncyCastle.Math.BigInteger)">
+             Return the passed in value as an unsigned byte array of specified length, zero-extended as necessary.
+            
+             @param length desired length of result array.
+             @param n value to be converted.
+             @return a byte array of specified length, with leading zeroes as necessary given the size of n.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Security.SecureRandom)">
+            Return a random BigInteger not less than 'min' and not greater than 'max'
+            
+            @param min the least value that may be generated
+            @param max the greatest value that may be generated
+            @param random the source of randomness
+            @return a random BigInteger value in the range [min,max]
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.DateTimeToUnixMs(System.DateTime)">
+            <summary>
+            Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
+            </summary>
+            <param name="dateTime">A UTC DateTime value not before epoch.</param>
+            <returns>Number of whole milliseconds after epoch.</returns>
+            <exception cref="T:System.ArgumentException">'dateTime' is before epoch.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.UnixMsToDateTime(System.Int64)">
+            <summary>
+            Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+            </summary>
+            <param name="unixMs">Number of milliseconds since the epoch.</param>
+            <returns>A UTC DateTime value</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.CurrentUnixMs">
+            <summary>
+            Return the current number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[])">
+             encode the input data producing a base 64 encoded byte array.
+            
+             @return a byte array containing the base 64 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[],System.Int32,System.Int32)">
+             encode the input data producing a base 64 encoded byte array.
+            
+             @return a byte array containing the base 64 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[],System.IO.Stream)">
+             Encode the byte data to base 64 writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             Encode the byte data to base 64 writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.Byte[])">
+             decode the base 64 encoded input data. It is assumed the input data is valid.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.String)">
+             decode the base 64 encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.String,System.IO.Stream)">
+             decode the base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.IEncoder">
+            Encode and decode byte arrays (typically from binary to 7-bit ASCII
+            encodings).
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             encode the input data producing a base 64 output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.Decode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             decode the base 64 encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.DecodeString(System.String,System.IO.Stream)">
+             decode the base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder">
+            <summary>
+             A buffering class to allow translation from one format to another to
+                be done in discrete chunks.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.#ctor(Org.BouncyCastle.Utilities.Encoders.ITranslator,System.Int32)">
+            <summary>
+            Create a buffered Decoder.
+            </summary>
+            <param name="translator">The translater to use.</param>
+            <param name="bufferSize">The size of the buffer.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+            <summary>
+            Process one byte of data.
+            </summary>
+            <param name="input">Data in.</param>
+            <param name="output">Byte array for the output.</param>
+            <param name="outOff">The offset in the output byte array to start writing from.</param>
+            <returns>The amount of output bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process data from a byte array.
+            </summary>
+            <param name="input">The input data.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="len">Amount of data to process from input data array.</param>
+            <param name="outBytes">Array to store output.</param>
+            <param name="outOff">Position in output array to start writing from.</param>
+            <returns>The amount of output bytes.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder">
+            <summary>
+            A class that allows encoding of data using a specific encoder to be processed in chunks.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.#ctor(Org.BouncyCastle.Utilities.Encoders.ITranslator,System.Int32)">
+            <summary>
+            Create.
+            </summary>
+            <param name="translator">The translator to use.</param>
+            <param name="bufferSize">Size of the chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+            <summary>
+            Process one byte of data.
+            </summary>
+            <param name="input">The byte.</param>
+            <param name="outBytes">An array to store output in.</param>
+            <param name="outOff">Offset within output array to start writing from.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process data from a byte array.
+            </summary>
+            <param name="input">Input data Byte array containing data to be processed.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="len">Amount of input data to be processed.</param>
+            <param name="outBytes">Output data array.</param>
+            <param name="outOff">Offset within output data array to start writing to.</param>
+            <returns>The amount of data written.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.Hex">
+            <summary>
+            Class to decode and encode Hex.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[])">
+             encode the input data producing a Hex encoded byte array.
+            
+             @return a byte array containing the Hex encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.Int32,System.Int32)">
+             encode the input data producing a Hex encoded byte array.
+            
+             @return a byte array containing the Hex encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.IO.Stream)">
+             Hex encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             Hex encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.Byte[])">
+             decode the Hex encoded input data. It is assumed the input data is valid.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.String)">
+             decode the Hex encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.String,System.IO.Stream)">
+             decode the Hex encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             encode the input data producing a Hex output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.Decode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             decode the Hex encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.DecodeString(System.String,System.IO.Stream)">
+             decode the Hex encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.HexTranslator">
+            <summary>
+            A hex translator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.ITranslator">
+            <summary>
+            Translator interface.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.GetEncodedBlockSize">
+            <summary>
+            Return encoded block size.
+            </summary>
+            <returns>2</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.Encode(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Encode some data.
+            </summary>
+            <param name="input">Input data array.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="length">The amount of data to process.</param>
+            <param name="outBytes">The output data array.</param>
+            <param name="outOff">The offset within the output data array to start writing from.</param>
+            <returns>Amount of data encoded.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.GetDecodedBlockSize">
+            <summary>
+            Returns the decoded block size.
+            </summary>
+            <returns>1</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.Decode(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Decode data from a byte array.
+            </summary>
+            <param name="input">The input data array.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="length">The amounty of data to process.</param>
+            <param name="outBytes">The output data array.</param>
+            <param name="outOff">The position within the output data array to start writing from.</param>
+            <returns>The amount of data written.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.UrlBase64">
+            Convert binary data to and from UrlBase64 encoding.  This is identical to
+            Base64 encoding, except that the padding character is "." and the other 
+            non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+            <p>
+            The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+            data that is safe for use as an URL parameter. Base64 encoding does not
+            produce encoded values that are safe for use in URLs, since "/" can be 
+            interpreted as a path delimiter; "+" is the encoded form of a space; and
+            "=" is used to separate a name from the corresponding value in an URL 
+            parameter.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Encode(System.Byte[])">
+             Encode the input data producing a URL safe base 64 encoded byte array.
+            
+             @return a byte array containing the URL safe base 64 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Encode(System.Byte[],System.IO.Stream)">
+             Encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.Byte[])">
+             Decode the URL safe base 64 encoded input data - white space will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.Byte[],System.IO.Stream)">
+             decode the URL safe base 64 encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.String)">
+             decode the URL safe base 64 encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.String,System.IO.Stream)">
+             Decode the URL safe base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.UrlBase64Encoder">
+            Convert binary data to and from UrlBase64 encoding.  This is identical to
+            Base64 encoding, except that the padding character is "." and the other 
+            non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+            <p>
+            The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+            data that is safe for use as an URL parameter. Base64 encoding does not
+            produce encoded values that are safe for use in URLs, since "/" can be 
+            interpreted as a path delimiter; "+" is the encoded form of a space; and
+            "=" is used to separate a name from the corresponding value in an URL 
+            parameter.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemObjectParser.ParseObject(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+            <param name="obj">
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </param>
+            <returns>
+            A <see cref="T:System.Object"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Streams.PipeAllLimited(System.IO.Stream,System.Int64,System.IO.Stream)">
+            <summary>
+            Pipe all bytes from <c>inStr</c> to <c>outStr</c>, throwing <c>StreamFlowException</c> if greater
+            than <c>limit</c> bytes in <c>inStr</c>.
+            </summary>
+            <param name="inStr">
+            A <see cref="T:System.IO.Stream"/>
+            </param>
+            <param name="limit">
+            A <see cref="T:System.Int64"/>
+            </param>
+            <param name="outStr">
+            A <see cref="T:System.IO.Stream"/>
+            </param>
+            <returns>The number of bytes actually transferred, if not greater than <c>limit</c></returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.MemoableResetException">
+            Exception to be thrown on a failure to reset an object implementing Memoable.
+            <p>
+            The exception extends InvalidCastException to enable users to have a single handling case,
+            only introducing specific handling of this one if required.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.MemoableResetException.#ctor(System.String)">
+             Basic Constructor.
+            
+             @param msg message to be associated with this exception.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValid(System.String)">
+             Validate the given IPv4 or IPv6 address.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid address, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidWithNetMask(System.String)">
+             Validate the given IPv4 or IPv6 address and netmask.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid address with netmask, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv4(System.String)">
+             Validate the given IPv4 address.
+             
+             @param address the IP address as a string.
+            
+             @return true if a valid IPv4 address, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv6(System.String)">
+             Validate the given IPv6 address.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid IPv4 address, false otherwise
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Strings">
+            <summary> General string utilities.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Zlib.ZDeflaterOutputStream">
+            <summary>
+            Summary description for DeflaterOutputStream.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Zlib.ZInflaterInputStream">
+            <summary>
+            Summary description for DeflaterOutputStream.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.AttributeCertificateHolder">
+            <remarks>
+            The Holder object.
+            <pre>
+            Holder ::= SEQUENCE {
+            	baseCertificateID   [0] IssuerSerial OPTIONAL,
+            		-- the issuer and serial number of
+            		-- the holder's Public Key Certificate
+            	entityName          [1] GeneralNames OPTIONAL,
+            		-- the name of the claimant or role
+            	objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+            		-- used to directly authenticate the holder,
+            		-- for example, an executable
+            }
+            </pre>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.#ctor(System.Int32,System.String,System.String,System.Byte[])">
+             Constructs a holder for v2 attribute certificates with a hash value for
+             some type of object.
+             <p>
+             <code>digestedObjectType</code> can be one of the following:
+             <ul>
+             <li>0 - publicKey - A hash of the public key of the holder must be
+             passed.</li>
+             <li>1 - publicKeyCert - A hash of the public key certificate of the
+             holder must be passed.</li>
+             <li>2 - otherObjectDigest - A hash of some other object type must be
+             passed. <code>otherObjectTypeID</code> must not be empty.</li>
+             </ul>
+             </p>
+             <p>This cannot be used if a v1 attribute certificate is used.</p>
+            
+             @param digestedObjectType The digest object type.
+             @param digestAlgorithm The algorithm identifier for the hash.
+             @param otherObjectTypeID The object type ID if
+                        <code>digestedObjectType</code> is
+                        <code>otherObjectDigest</code>.
+             @param objectDigest The hash value.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetObjectDigest">
+             Returns the hash if an object digest info is used.
+            
+             @return The hash or <code>null</code> if no object digest info is set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetEntityNames">
+             Return any principal objects inside the attribute certificate holder entity names field.
+            
+             @return an array of IPrincipal objects (usually X509Name), null if no entity names field is set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetIssuer">
+             Return the principals associated with the issuer attached to this holder
+            
+             @return an array of principals, null if no BaseCertificateID is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.DigestedObjectType">
+             Returns the digest object type if an object digest info is used.
+             <p>
+             <ul>
+             <li>0 - publicKey - A hash of the public key of the holder must be
+             passed.</li>
+             <li>1 - publicKeyCert - A hash of the public key certificate of the
+             holder must be passed.</li>
+             <li>2 - otherObjectDigest - A hash of some other object type must be
+             passed. <code>otherObjectTypeID</code> must not be empty.</li>
+             </ul>
+             </p>
+            
+             @return The digest object type or -1 if no object digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.DigestAlgorithm">
+             Returns the other object type ID if an object digest info is used.
+            
+             @return The other object type ID or <code>null</code> if no object
+                     digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.OtherObjectTypeID">
+             Returns the digest algorithm ID if an object digest info is used.
+            
+             @return The digest algorithm ID or <code>null</code> if no object
+                     digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.SerialNumber">
+             Return the serial number associated with the issuer attached to this holder.
+            
+             @return the certificate serial number, null if no BaseCertificateID is set.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.AttributeCertificateIssuer">
+            Carrying class for an attribute certificate issuer.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateIssuer.#ctor(Org.BouncyCastle.Asn1.X509.AttCertIssuer)">
+             Set the issuer directly with the ASN.1 structure.
+            
+             @param issuer The issuer
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateIssuer.GetPrincipals">
+            <summary>Return any principal objects inside the attribute certificate issuer object.</summary>
+            <returns>An array of IPrincipal objects (usually X509Principal).</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure">
+            <remarks>A high level authority key identifier.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor which will take the byte[] returned from getExtensionValue()
+            
+             @param encodedValue a DER octet encoded string with the extension structure in it.
+             @throws IOException on parsing errors.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.X509.X509Certificate)">
+             Create an AuthorityKeyIdentifier using the passed in certificate's public
+             key, issuer and serial number.
+            
+             @param certificate the certificate providing the information.
+             @throws CertificateParsingException if there is a problem processing the certificate
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             Create an AuthorityKeyIdentifier using just the hash of the
+             public key.
+            
+             @param pubKey the key to generate the hash from.
+             @throws InvalidKeyException if there is a problem using the key.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Extension.SubjectKeyIdentifierStructure">
+            A high level subject key identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.SubjectKeyIdentifierStructure.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor which will take the byte[] returned from getExtensionValue()
+            
+             @param encodedValue a DER octet encoded string with the extension structure in it.
+             @throws IOException on parsing errors.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.IX509AttributeCertificate">
+            <remarks>Interface for an X.509 Attribute Certificate.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetAttributes">
+            <summary>Return the attributes contained in the attribute block in the certificate.</summary>
+            <returns>An array of attributes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetAttributes(System.String)">
+            <summary>Return the attributes with the same type as the passed in oid.</summary>
+            <param name="oid">The object identifier we wish to match.</param>
+            <returns>An array of matched attributes, null if there is no match.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetEncoded">
+            <summary>Return an ASN.1 encoded byte array representing the attribute certificate.</summary>
+            <returns>An ASN.1 encoded byte array.</returns>
+            <exception cref="T:System.IO.IOException">If the certificate cannot be encoded.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Version">
+            <summary>The version number for the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.SerialNumber">
+            <summary>The serial number for the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.NotBefore">
+            <summary>The UTC DateTime before which the certificate is not valid.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.NotAfter">
+            <summary>The UTC DateTime after which the certificate is not valid.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Holder">
+            <summary>The holder of the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Issuer">
+            <summary>The issuer details for the certificate.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.PrincipalUtilities">
+            <remarks>
+            A utility class that will extract X509Principal objects from X.509 certificates.
+            <p>
+            Use this in preference to trying to recreate a principal from a string, not all
+            DNs are what they should be, so it's best to leave them encoded where they
+            can be.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetIssuerX509Principal(Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Return the issuer of the given cert as an X509Principal.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetSubjectX509Principal(Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Return the subject of the given cert as an X509Principal.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetIssuerX509Principal(Org.BouncyCastle.X509.X509Crl)">
+            <summary>Return the issuer of the given CRL as an X509Principal.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector">
+             This class is an <code>Selector</code> like implementation to select
+             attribute certificates from a given set of criteria.
+            
+             @see org.bouncycastle.x509.X509AttributeCertificate
+             @see org.bouncycastle.x509.X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Match(System.Object)">
+            <summary>
+            Decides if the given attribute certificate should be selected.
+            </summary>
+            <param name="obj">The attribute certificate to be checked.</param>
+            <returns><code>true</code> if the object matches this selector.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetName(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Adds a target name criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target names.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name The name as a GeneralName (not <code>null</code>)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetName(System.Byte[])">
+             Adds a target name criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target names.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
+             @throws IOException if a parsing error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SetTargetNames(System.Collections.IEnumerable)">
+            Adds a collection with target names criteria. If <code>null</code> is
+            given any will do.
+            <p>
+            The collection consists of either GeneralName objects or byte[] arrays representing
+            DER encoded GeneralName structures.
+            </p>
+            
+            @param names A collection of target names.
+            @throws IOException if a parsing error occurs.
+            @see #AddTargetName(byte[])
+            @see #AddTargetName(GeneralName)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.GetTargetNames">
+            Gets the target names. The collection consists of <code>List</code>s
+            made up of an <code>Integer</code> in the first entry and a DER encoded
+            byte array or a <code>String</code> in the second entry.
+            <p>The returned collection is immutable.</p>
+            
+            @return The collection of target names
+            @see #setTargetNames(Collection)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetGroup(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Adds a target group criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target groups.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param group The group as GeneralName form (not <code>null</code>)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetGroup(System.Byte[])">
+             Adds a target group criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target groups.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
+             @throws IOException if a parsing error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SetTargetGroups(System.Collections.IEnumerable)">
+             Adds a collection with target groups criteria. If <code>null</code> is
+             given any will do.
+             <p>
+             The collection consists of <code>GeneralName</code> objects or <code>byte[]</code>
+             representing DER encoded GeneralNames.
+             </p>
+            
+             @param names A collection of target groups.
+             @throws IOException if a parsing error occurs.
+             @see #AddTargetGroup(byte[])
+             @see #AddTargetGroup(GeneralName)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.GetTargetGroups">
+             Gets the target groups. The collection consists of <code>List</code>s
+             made up of an <code>Integer</code> in the first entry and a DER encoded
+             byte array or a <code>String</code> in the second entry.
+             <p>The returned collection is immutable.</p>
+            
+             @return The collection of target groups.
+             @see #setTargetGroups(Collection)
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AttributeCert">
+            <summary>The attribute certificate which must be matched.</summary>
+            <remarks>If <c>null</c> is given, any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AttributeCertificateValid">
+            <summary>The criteria for validity</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Holder">
+            <summary>The holder.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Issuer">
+            <summary>The issuer.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SerialNumber">
+            <summary>The serial number.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector">
+            <remarks>
+            This class is an <code>IX509Selector</code> implementation to select
+            certificate pairs, which are e.g. used for cross certificates. The set of
+            criteria is given from two <code>X509CertStoreSelector</code> objects,
+            each of which, if present, must match the respective component of a pair.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.Match(System.Object)">
+            <summary>
+            Decides if the given certificate pair should be selected. If
+            <c>obj</c> is not a <code>X509CertificatePair</code>, this method
+            returns <code>false</code>.
+            </summary>
+            <param name="obj">The <code>X509CertificatePair</code> to be tested.</param>
+            <returns><code>true</code> if the object matches this selector.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.CertPair">
+            <summary>The certificate pair which is used for testing on equality.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.ForwardSelector">
+            <summary>The certificate selector for the forward part.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.ReverseSelector">
+            <summary>The certificate selector for the reverse part.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CollectionStore">
+            A simple collection backed store.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStore.#ctor(System.Collections.ICollection)">
+             Basic constructor.
+            
+             @param collection - initial contents for the store, this is copied.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStore.GetMatches(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Return the matches in the collection for the passed in selector.
+            
+             @param selector the selector to match against.
+             @return a possibly empty collection of matching objects.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters">
+            <remarks>This class contains a collection for collection based <code>X509Store</code>s.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.#ctor(System.Collections.ICollection)">
+            <summary>
+            Constructor.
+            <p>
+            The collection is copied.
+            </p>
+            </summary>
+            <param name="collection">The collection containing X.509 object types.</param>
+            <exception cref="T:System.ArgumentNullException">If collection is null.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.GetCollection">
+            <summary>Returns a copy of the <code>ICollection</code>.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.ToString">
+            <summary>Returns a formatted string describing the parameters.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.Issuers">
+            <summary>
+            An <code>ICollection</code> of <code>X509Name</code> objects
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.AttrCertChecking">
+             The attribute certificate being checked. This is not a criterion.
+             Rather, it is optional information that may help a {@link X509Store} find
+             CRLs that would be relevant when checking revocation for the specified
+             attribute certificate. If <code>null</code> is specified, then no such
+             optional information is provided.
+            
+             @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
+                         <code>null</code>)
+             @see #getAttrCertificateChecking()
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.CompleteCrlEnabled">
+             If <code>true</code> only complete CRLs are returned. Defaults to
+             <code>false</code>.
+            
+             @return <code>true</code> if only complete CRLs are returned.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.DeltaCrlIndicatorEnabled">
+             Returns if this selector must match CRLs with the delta CRL indicator
+             extension set. Defaults to <code>false</code>.
+            
+             @return Returns <code>true</code> if only CRLs with the delta CRL
+                     indicator extension are selected.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.IssuingDistributionPoint">
+             The issuing distribution point.
+             <p>
+             The issuing distribution point extension is a CRL extension which
+             identifies the scope and the distribution point of a CRL. The scope
+             contains among others information about revocation reasons contained in
+             the CRL. Delta CRLs and complete CRLs must have matching issuing
+             distribution points.</p>
+             <p>
+             The byte array is cloned to protect against subsequent modifications.</p>
+             <p>
+             You must also enable or disable this criteria with
+             {@link #setIssuingDistributionPointEnabled(bool)}.</p>
+            
+             @param issuingDistributionPoint The issuing distribution point to set.
+                                             This is the DER encoded OCTET STRING extension value.
+             @see #getIssuingDistributionPoint()
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.IssuingDistributionPointEnabled">
+             Whether the issuing distribution point criteria should be applied.
+             Defaults to <code>false</code>.
+             <p>
+             You may also set the issuing distribution point criteria if not a missing
+             issuing distribution point should be assumed.</p>
+            
+             @return Returns if the issuing distribution point check is enabled.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.MaxBaseCrlNumber">
+             The maximum base CRL number. Defaults to <code>null</code>.
+            
+             @return Returns the maximum base CRL number.
+             @see #setMaxBaseCRLNumber(BigInteger)
+        </member>
+        <member name="T:Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory">
+            <summary>
+            A factory to produce Public Key Info Objects.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Create a Subject Public Key Info object for a given public key.
+            </summary>
+            <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
+            <returns>A subject public key info object.</returns>
+            <exception cref="T:System.Exception">Throw exception if object provided is not one of the above.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCert(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCerts(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCert(System.IO.Stream)">
+            Generates a certificate object and initializes it with the data
+            read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCerts(System.IO.Stream)">
+            Returns a (possibly empty) collection view of the certificates
+            read from the given input stream inStream.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Attribute">
+            Class for carrying the values in an X.509 Attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param at an object representing an attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Create an X.509 Attribute with the type given by the passed in oid and
+             the value represented by an ASN.1 Set containing value.
+            
+             @param oid type of the attribute
+             @param value value object to go into the atribute's value set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+             Create an X.59 Attribute with the type given by the passed in oid and the
+             value represented by an ASN.1 Set containing the objects in value.
+            
+             @param oid type of the attribute
+             @param value vector of values to go in the attribute's value set.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Certificate">
+            <summary>
+            An Object representing an X509 Certificate.
+            Has static methods for loading Certificates encoded in many forms that return X509Certificate Objects.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.IsValid(System.DateTime)">
+            <summary>
+            Return true if the nominated time is within the start and end times nominated on the certificate.
+            </summary>
+            <param name="time">The time to test validity against.</param>
+            <returns>True if certificate is valid for nominated time.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.CheckValidity">
+            <summary>
+            Checks if the current date is within certificate's validity period.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.CheckValidity(System.DateTime)">
+            <summary>
+            Checks if the given date is within certificate's validity period.
+            </summary>
+            <exception cref="T:Org.BouncyCastle.Security.Certificates.CertificateExpiredException">if the certificate is expired by given date</exception>
+            <exception cref="T:Org.BouncyCastle.Security.Certificates.CertificateNotYetValidException">if the certificate is not yet valid on given date</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetTbsCertificate">
+            <summary>
+            Return the Der encoded TbsCertificate data.
+            This is the certificate component less the signature.
+            To Get the whole certificate call the GetEncoded() member.
+            </summary>
+            <returns>A byte array containing the Der encoded Certificate component.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetSignature">
+            <summary>
+            The signature.
+            </summary>
+            <returns>A byte array containg the signature of the certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetSigAlgParams">
+            <summary>
+            Get the signature algorithms parameters. (EG DSA Parameters)
+            </summary>
+            <returns>A byte array containing the Der encoded version of the parameters or null if there are none.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetKeyUsage">
+            <summary>
+            Get a key usage guidlines.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetPublicKey">
+            <summary>
+            Get the public key of the subject of the certificate.
+            </summary>
+            <returns>The public key parameters.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetEncoded">
+            <summary>
+            Return a Der encoded version of this certificate.
+            </summary>
+            <returns>A byte array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Verify the certificate's signature using the nominated public key.
+            </summary>
+            <param name="key">An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters</param>
+            <returns>True if the signature is valid.</returns>
+            <exception cref="T:System.Exception">If key submitted is not of the above nominated types.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IsValidNow">
+            <summary>
+            Return true if the current time is within the start and end times nominated on the certificate.
+            </summary>
+            <returns>true id certificate is valid for the current time.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.Version">
+            <summary>
+            Return the certificate's version.
+            </summary>
+            <returns>An integer whose value Equals the version of the cerficate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SerialNumber">
+            <summary>
+            Return a <see cref="T:Org.BouncyCastle.Math.BigInteger">BigInteger</see> containing the serial number.
+            </summary>
+            <returns>The Serial number.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IssuerDN">
+            <summary>
+            Get the Issuer Distinguished Name. (Who signed the certificate.)
+            </summary>
+            <returns>And X509Object containing name and value pairs.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SubjectDN">
+            <summary>
+            Get the subject of this certificate.
+            </summary>
+            <returns>An X509Name object containing name and value pairs.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.NotBefore">
+            <summary>
+            The time that this certificate is valid from.
+            </summary>
+            <returns>A DateTime object representing that time in the local time zone.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.NotAfter">
+            <summary>
+            The time that this certificate is valid up to.
+            </summary>
+            <returns>A DateTime object representing that time in the local time zone.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SigAlgName">
+            <summary>
+            A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA)
+            </summary>
+            <returns>A sting representing the signature algorithm.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SigAlgOid">
+            <summary>
+            Get the Signature Algorithms Object ID.
+            </summary>
+            <returns>A string containg a '.' separated object id.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IssuerUniqueID">
+            <summary>
+            Get the issuers UID.
+            </summary>
+            <returns>A DerBitString.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SubjectUniqueID">
+            <summary>
+            Get the subjects UID.
+            </summary>
+            <returns>A DerBitString.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CertificatePair">
+            <remarks>
+            This class contains a cross certificate pair. Cross certificates pairs may
+            contain two cross signed certificates from two CAs. A certificate from the
+            other CA to this CA is contained in the forward certificate, the certificate
+            from this CA to the other CA is contained in the reverse certificate.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificatePair.#ctor(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Constructor</summary>
+            <param name="forward">Certificate from the other CA to this CA.</param>
+            <param name="reverse">Certificate from this CA to the other CA.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificatePair.#ctor(Org.BouncyCastle.Asn1.X509.CertificatePair)">
+            <summary>Constructor from a ASN.1 CertificatePair structure.</summary>
+            <param name="pair">The <c>CertificatePair</c> ASN.1 object.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509CertificatePair.Forward">
+            <summary>Returns the certificate from the other CA to this CA.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509CertificatePair.Reverse">
+            <summary>Returns the certificate from this CA to the other CA.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CertificateParser">
+            class for dealing with X509 certificates.
+            <p>
+            At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
+            base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
+            objects.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificate(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificates(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificate(System.IO.Stream)">
+            Generates a certificate object and initializes it with the data
+            read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificates(System.IO.Stream)">
+            Returns a (possibly empty) collection view of the certificates
+            read from the given input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertPairParser.ReadCertPair(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertPairParser.ReadCertPairs(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Crl">
+             The following extensions are listed in RFC 2459 as relevant to CRLs
+            
+             Authority Key Identifier
+             Issuer Alternative Name
+             CRL Number
+             Delta CRL Indicator (critical)
+             Issuing Distribution Point (critical)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Crl.ToString">
+             Returns a string representation of this CRL.
+            
+             @return a string representation of this CRL.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Crl.IsRevoked(Org.BouncyCastle.X509.X509Certificate)">
+             Checks whether the given certificate is on this CRL.
+            
+             @param cert the certificate to check for.
+             @return true if the given certificate is on this CRL,
+             false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CrlEntry">
+             The following extensions are listed in RFC 2459 as relevant to CRL Entries
+            
+             ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
+             (critical)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlEntry.#ctor(Org.BouncyCastle.Asn1.X509.CrlEntry,System.Boolean,Org.BouncyCastle.Asn1.X509.X509Name)">
+             Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
+             is <code>false</code> {@link #getCertificateIssuer()} will always
+             return <code>null</code>, <code>previousCertificateIssuer</code> is
+             ignored. If this <code>isIndirect</code> is specified and this CrlEntry
+             has no certificate issuer CRL entry extension
+             <code>previousCertificateIssuer</code> is returned by
+             {@link #getCertificateIssuer()}.
+            
+             @param c
+                        TbsCertificateList.CrlEntry object.
+             @param isIndirect
+                        <code>true</code> if the corresponding CRL is a indirect
+                        CRL.
+             @param previousCertificateIssuer
+                        Certificate issuer of the previous CrlEntry.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrl(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrls(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrl(System.IO.Stream)">
+            Generates a certificate revocation list (CRL) object and initializes
+            it with the data read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrls(System.IO.Stream)">
+             Returns a (possibly empty) collection view of the CRLs read from
+             the given input stream inStream.
+            
+             The inStream may contain a sequence of DER-encoded CRLs, or
+             a PKCS#7 CRL set.  This is a PKCS#7 SignedData object, with the
+             only significant field being crls.  In particular the signature
+             and the contents are ignored.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509KeyUsage">
+             A holding class for constructing an X509 Key Usage extension.
+            
+             <pre>
+                id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+            
+                KeyUsage ::= BIT STRING {
+                     digitalSignature        (0),
+                     nonRepudiation          (1),
+                     keyEncipherment         (2),
+                     dataEncipherment        (3),
+                     keyAgreement            (4),
+                     keyCertSign             (5),
+                     cRLSign                 (6),
+                     encipherOnly            (7),
+                     decipherOnly            (8) }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509KeyUsage.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509SignatureUtilities.GetDigestAlgName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V1CertificateGenerator">
+            <summary>
+            Class to Generate X509V1 Certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.#ctor">
+            <summary>
+            Default Constructor.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Reset">
+            <summary>
+            Reset the generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>
+            Set the certificate's serial number.
+            </summary>
+            <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+            You will be surprised how ugly a serial number collision can get.</remarks>
+            <param name="serialNumber">The serial number.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the issuer distinguished name.
+            The issuer is the entity whose private key is used to sign the certificate.
+            </summary>
+            <param name="issuer">The issuers DN.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetNotBefore(System.DateTime)">
+            <summary>
+            Set the date that this certificate is to be valid from.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetNotAfter(System.DateTime)">
+            <summary>
+            Set the date after which this certificate will no longer be valid.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSubjectDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the subject distinguished name.
+            The subject describes the entity associated with the public key.
+            </summary>
+            <param name="subject"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetPublicKey(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Set the public key that this certificate identifies.
+            </summary>
+            <param name="publicKey"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm that will be used to sign this certificate.
+            This can be either a name or an OID, names are treated as case insensitive.
+            </summary>
+            <param name="signatureAlgorithm">string representation of the algorithm name</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate a new X509Certificate.
+            </summary>
+            <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate a new X509Certificate specifying a SecureRandom instance that you would like to use.
+            </summary>
+            <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+            <param name="random">The Secure Random you want to use.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V1CertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2AttributeCertificate">
+            <summary>An implementation of a version 2 X.509 Attribute Certificate.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator">
+            <remarks>Class to produce an X.509 Version 2 AttributeCertificate.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Reset">
+            <summary>Reset the generator</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetHolder(Org.BouncyCastle.X509.AttributeCertificateHolder)">
+            <summary>Set the Holder of this Attribute Certificate.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetIssuer(Org.BouncyCastle.X509.AttributeCertificateIssuer)">
+            <summary>Set the issuer.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>Set the serial number for the certificate.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm. This can be either a name or an OID, names
+            are treated as case insensitive.
+            </summary>
+            <param name="signatureAlgorithm">The algorithm name.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddAttribute(Org.BouncyCastle.X509.X509Attribute)">
+            <summary>Add an attribute.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>Add a given extension field for the standard extensions tag.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            <summary>
+            Add a given extension field for the standard extensions tag.
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate an X509 certificate, based on the current issuer and subject.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate an X509 certificate, based on the current issuer and subject,
+            using the supplied source of randomness, if required.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2CrlGenerator">
+            class to produce an X.509 Version 2 CRL.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Reset">
+            reset the generator
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
+            certificate.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,System.Int32)">
+             Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+             or 0 if CrlReason is not to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,System.Int32,System.DateTime)">
+             Add a CRL entry with an Invalidity Date extension as well as a CrlReason extension.
+             Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+             or 0 if CrlReason is not to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a CRL entry with extensions.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrl(Org.BouncyCastle.X509.X509Crl)">
+             Add the CRLEntry objects contained in a previous CRL.
+            
+             @param other the X509Crl to source the other entries from.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.SetSignatureAlgorithm(System.String)">
+             Set the signature algorithm. This can be either a name or an oid, names
+             are treated as case insensitive.
+            
+             @param signatureAlgorithm string representation of the algorithm name.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+            <param name="privateKey">The key used for signing.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+            <param name="privateKey">The key used for signing.</param>
+            <param name="random">A user-defined source of randomness.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V2CrlGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V3CertificateGenerator">
+            <summary>
+            A class to Generate Version 3 X509Certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Reset">
+            <summary>
+            Reset the Generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>
+            Set the certificate's serial number.
+            </summary>
+            <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+            You will be surprised how ugly a serial number collision can Get.</remarks>
+            <param name="serialNumber">The serial number.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the distinguished name of the issuer.
+            The issuer is the entity which is signing the certificate.
+            </summary>
+            <param name="issuer">The issuer's DN.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetNotBefore(System.DateTime)">
+            <summary>
+            Set the date that this certificate is to be valid from.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetNotAfter(System.DateTime)">
+            <summary>
+            Set the date after which this certificate will no longer be valid.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSubjectDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the DN of the entity that this certificate is about.
+            </summary>
+            <param name="subject"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetPublicKey(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Set the public key that this certificate identifies.
+            </summary>
+            <param name="publicKey"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm that will be used to sign this certificate.
+            </summary>
+            <param name="signatureAlgorithm"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSubjectUniqueID(System.Boolean[])">
+            <summary>
+            Set the subject unique ID - note: it is very rare that it is correct to do this.
+            </summary>
+            <param name="uniqueID"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetIssuerUniqueID(System.Boolean[])">
+            <summary>
+            Set the issuer unique ID - note: it is very rare that it is correct to do this.
+            </summary>
+            <param name="uniqueID"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add a given extension field for the standard extensions tag (tag 3).
+            </summary>
+            <param name="oid">string containing a dotted decimal Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">The value.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add an extension to this certificate.
+            </summary>
+            <param name="oid">Its Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">The value.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension using a string with a dotted decimal OID.
+            </summary>
+            <param name="oid">string containing a dotted decimal Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">byte[] containing the value of this extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension to this certificate.
+            </summary>
+            <param name="oid">Its Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">byte[] containing the value of this extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.CopyAndAddExtension(System.String,System.Boolean,Org.BouncyCastle.X509.X509Certificate)">
+            <summary>
+            Add a given extension field for the standard extensions tag (tag 3),
+            copying the extension value from another certificate.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.CopyAndAddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.X509.X509Certificate)">
+            add a given extension field for the standard extensions tag (tag 3)
+            copying the extension value from another certificate.
+            @throws CertificateParsingException if the extension cannot be extracted.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate an X509Certificate.
+            </summary>
+            <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate an X509Certificate using your own SecureRandom.
+            </summary>
+            <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+            <param name="random">You Secure Random instance.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V3CertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+    </members>
+</doc>
diff --git a/BouncyCastle.AxCrypt/doc/wp7/crypto.xml b/BouncyCastle.AxCrypt/doc/wp7/crypto.xml
new file mode 100644
index 0000000..f1cf2f3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/doc/wp7/crypto.xml
@@ -0,0 +1,19296 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>crypto</name>
+    </assembly>
+    <members>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.BZip2Constants">
+             Base class for both the compress and decompress classes.
+             Holds common arrays, and static data.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CBZip2InputStream">
+             An input stream that decompresses from the BZip2 format (with the file
+             header chars) to be read as any other stream.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+            
+             <b>NB:</b> note this class has been modified to read the leading BZ from the
+             start of the BZIP2 stream to make it compatible with other PGP programs.
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CBZip2OutputStream">
+             An output stream that compresses into the BZip2 format (with the file
+             header chars) into another stream.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+            
+             TODO:    Update to BZip2 1.0.1
+             <b>NB:</b> note this class has been modified to add a leading BZ to the
+             start of the BZIP2 stream to make it compatible with other PGP programs.
+        </member>
+        <member name="M:Org.BouncyCastle.Apache.Bzip2.CBZip2OutputStream.WriteByte(System.Byte)">
+            
+             modified by Oliver Merkel, 010128
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Apache.Bzip2.CRC">
+             A simple class the hold and calculate the CRC for sanity checking
+             of the data.
+            
+             @author <a href="mailto:keiron at aftexsw.com">Keiron Liddle</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Encodable.GetDerEncoded">
+             Return the DER encoding of the object, null if the DER encoding can not be made.
+            
+             @return a DER byte array, null otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1InputStream">
+            a general purpose ASN.1 decoder - note: this class differs from the
+            others in that it returns null after it has read the last object in
+            the stream. If an ASN.1 Null is encountered a Der/BER Null object is
+            returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.#ctor(System.IO.Stream,System.Int32)">
+             Create an ASN1InputStream where no DER object will be longer than limit.
+            
+             @param input stream containing ASN.1 encoded data.
+             @param limit maximum size of a DER encoded object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.#ctor(System.Byte[])">
+             Create an ASN1InputStream based on the input byte array. The length of DER objects in
+             the stream is automatically limited to the length of the input array.
+            
+             @param input array containing ASN.1 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1InputStream.BuildObject(System.Int32,System.Int32,System.Int32)">
+            build an object given its tag and the number of bytes to construct it from.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1Null">
+            A Null object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Object.FromByteArray(System.Byte[])">
+            <summary>Create a base ASN.1 object from a byte array.</summary>
+            <param name="data">The byte array to parse.</param>
+            <returns>The base ASN.1 object represented by the byte array.</returns>
+            <exception cref="T:System.IO.IOException">If there is a problem parsing the data.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Object.FromStream(System.IO.Stream)">
+            <summary>Read a base ASN.1 object from a stream.</summary>
+            <param name="inStr">The stream to parse.</param>
+            <returns>The base ASN.1 object represented by the byte array.</returns>
+            <exception cref="T:System.IO.IOException">If there is a problem parsing the data.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Octet string from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                          be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.GetInstance(System.Object)">
+             return an Octet string from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1OctetString.#ctor(System.Byte[])">
+            @param string the octets making up the octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(System.Object)">
+             return an Asn1Sequence from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Sequence.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return an ASN1 sequence from a tagged object. There is a special
+             case here, if an object appears to have been explicitly tagged on
+             reading but we were expecting it to be implicitly tagged in the
+             normal course of events it indicates that we lost the surrounding
+             sequence - so we need to add it back (this will happen if the tagged
+             object is a sequence that contains other sequences). If you are
+             dealing with implicitly tagged sequences you really <b>should</b>
+             be using this method.
+            
+             @param obj the tagged object.
+             @param explicitly true if the object is meant to be explicitly tagged,
+                      false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                      be converted.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Asn1Sequence.Item(System.Int32)">
+             return the object at the sequence position indicated by index.
+            
+             @param index the sequence number (starting at zero) of the object
+             @return the object at the sequence position indicated by index.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.GetInstance(System.Object)">
+             return an ASN1Set from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return an ASN1 set from a tagged object. There is a special
+             case here, if an object appears to have been explicitly tagged on
+             reading but we were expecting it to be implicitly tagged in the
+             normal course of events it indicates that we lost the surrounding
+             set - so we need to add it back (this will happen if the tagged
+             object is a sequence that contains other sequences). If you are
+             dealing with implicitly tagged sets you really <b>should</b>
+             be using this method.
+            
+             @param obj the tagged object.
+             @param explicitly true if the object is meant to be explicitly tagged
+                      false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                      be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1Set.LessThanOrEqual(System.Byte[],System.Byte[])">
+            return true if a <= b (arrays are assumed padded with zeros).
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Asn1Set.Item(System.Int32)">
+             return the object at the set position indicated by index.
+            
+             @param index the set number (starting at zero) of the object
+             @return the object at the set position indicated by index.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Asn1TaggedObject">
+            ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if the object is explicitly tagged.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.IsExplicit">
+            return whether or not the object may be explicitly tagged.
+            <p>
+            Note: if the object has been read from an input stream, the only
+            time you can be sure if isExplicit is returning the true state of
+            affairs is if it returns false. An implicitly tagged object may appear
+            to be explicitly tagged, so you need to understand the context under
+            which the reading was done as well, see GetObject below.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.GetObject">
+            return whatever was following the tag.
+            <p>
+            Note: tagged objects are generally context dependent if you're
+            trying to extract a tagged object you should be going via the
+            appropriate GetInstance method.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Asn1TaggedObject.GetObjectParser(System.Int32,System.Boolean)">
+            Return the object held in this tagged object as a parser assuming it has
+            the type of the passed in tag. If the object doesn't have a parser
+            associated with it, the base object is returned.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerApplicationSpecific">
+            Base class for an application specific object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerApplicationSpecific.GetObject">
+             Return the enclosed object assuming explicit tagging.
+            
+             @return  the resulting object
+             @throws IOException if reconstruction fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerApplicationSpecific.GetObject(System.Int32)">
+             Return the enclosed object assuming implicit tagging.
+            
+             @param derTagNo the type tag that should be applied to the object's contents.
+             @return  the resulting object
+             @throws IOException if reconstruction fails.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.BerNull">
+            A BER Null object.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerNull">
+            A Null object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerOctetString.#ctor(System.Byte[])">
+            <param name="str">The octets making up the octet string.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.ToBytes(System.Collections.IEnumerable)">
+            convert a vector of octet strings into a single byte string
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.#ctor(System.Byte[])">
+            <param name="str">The octets making up the octet string.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerOctetString.GetEnumerator">
+            return the DER octets that make up this string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a sequence containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a sequence containing a vector of objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a sequence containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSequence.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a sequence containing a vector of objects.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerSet">
+            A Der encoded set object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor">
+            create an empty set
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param obj - a single object that makes up the set.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerSet.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            @param v - a vector of objects making up the set.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor">
+            create an empty sequence
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            create a set containing one object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerSet.#ctor(Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+            create a set containing a vector of objects.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.BerTaggedObject">
+            BER TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerTaggedObject">
+            DER TaggedObject - in ASN.1 notation this is any object preceded by
+            a [n] where n is some number - these are assumed to follow the construction
+            rules (as with sequences).
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if an explicitly tagged object.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerTaggedObject.#ctor(System.Int32)">
+            create an implicitly tagged object that contains a zero
+            length sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Boolean,System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param explicitly true if an explicitly tagged object.
+            @param tagNo the tag number for this object.
+            @param obj the tagged object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.BerTaggedObject.#ctor(System.Int32)">
+            create an implicitly tagged object that contains a zero
+            length sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CAKeyUpdAnnContent.ToAsn1Object">
+            <pre>
+            CAKeyUpdAnnContent ::= SEQUENCE {
+                                        oldWithNew   CmpCertificate, -- old pub signed with new priv
+                                        newWithOld   CmpCertificate, -- new pub signed with old priv
+                                        newWithNew   CmpCertificate  -- new pub signed with new priv
+             }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertConfirmContent.ToAsn1Object">
+            <pre>
+            CertConfirmContent ::= SEQUENCE OF CertStatus
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertifiedKeyPair.ToAsn1Object">
+            <pre>
+            CertifiedKeyPair ::= SEQUENCE {
+                                             certOrEncCert       CertOrEncCert,
+                                             privateKey      [0] EncryptedValue      OPTIONAL,
+                                             -- see [CRMF] for comment on encoding
+                                             publicationInfo [1] PKIPublicationInfo  OPTIONAL
+                  }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IAsn1Choice">
+            Marker interface for CHOICE objects - if you implement this in a roll-your-own
+            object, any attempt to tag the object implicitly will convert the tag to an
+            explicit one as the encoding rules require.
+            <p>
+            If you use this interface your class should also implement the getInstance
+            pattern which takes a tag object and the tagging mode used. 
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertOrEncCert.ToAsn1Object">
+            <pre>
+            CertOrEncCert ::= CHOICE {
+                                 certificate     [0] CMPCertificate,
+                                 encryptedCert   [1] EncryptedValue
+                      }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertRepMessage.ToAsn1Object">
+            <pre>
+            CertRepMessage ::= SEQUENCE {
+                                     caPubs       [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+                                                                                        OPTIONAL,
+                                     response         SEQUENCE OF CertResponse
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertResponse.ToAsn1Object">
+            <pre>
+            CertResponse ::= SEQUENCE {
+                                       certReqId           INTEGER,
+                                       -- to match this response with corresponding request (a value
+                                       -- of -1 is to be used if certReqId is not specified in the
+                                       -- corresponding request)
+                                       status              PKIStatusInfo,
+                                       certifiedKeyPair    CertifiedKeyPair    OPTIONAL,
+                                       rspInfo             OCTET STRING        OPTIONAL
+                                       -- analogous to the id-regInfo-utf8Pairs string defined
+                                       -- for regInfo in CertReqMsg [CRMF]
+                        }
+            </pre> 
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CertStatus.ToAsn1Object">
+            <pre>
+            CertStatus ::= SEQUENCE {
+                              certHash    OCTET STRING,
+                              -- the hash of the certificate, using the same hash algorithm
+                              -- as is used to create and verify the certificate signature
+                              certReqId   INTEGER,
+                              -- to match this confirmation with the corresponding req/rep
+                              statusInfo  PKIStatusInfo OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.Challenge.ToAsn1Object">
+             <pre>
+             Challenge ::= SEQUENCE {
+                             owf                 AlgorithmIdentifier  OPTIONAL,
+            
+                             -- MUST be present in the first Challenge; MAY be omitted in
+                             -- any subsequent Challenge in POPODecKeyChallContent (if
+                             -- omitted, then the owf used in the immediately preceding
+                             -- Challenge is to be used).
+            
+                             witness             OCTET STRING,
+                             -- the result of applying the one-way function (owf) to a
+                             -- randomly-generated INTEGER, A.  [Note that a different
+                             -- INTEGER MUST be used for each Challenge.]
+                             challenge           OCTET STRING
+                             -- the encryption (under the public key for which the cert.
+                             -- request is being made) of Rand, where Rand is specified as
+                             --   Rand ::= SEQUENCE {
+                             --      int      INTEGER,
+                             --       - the randomly-generated INTEGER A (above)
+                             --      sender   GeneralName
+                             --       - the sender's name (as included in PKIHeader)
+                             --   }
+                  }
+             </pre>
+             @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CmpCertificate.#ctor(Org.BouncyCastle.Asn1.X509.AttributeCertificate)">
+            Note: the addition of attribute certificates is a BC extension.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CmpCertificate.ToAsn1Object">
+             <pre>
+             CMPCertificate ::= CHOICE {
+                        x509v3PKCert        Certificate
+                        x509v2AttrCert      [1] AttributeCertificate
+              }
+             </pre>
+             Note: the addition of attribute certificates is a BC extension.
+            
+             @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.CrlAnnContent.ToAsn1Object">
+            <pre>
+            CrlAnnContent ::= SEQUENCE OF CertificateList
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.ErrorMsgContent.ToAsn1Object">
+            <pre>
+            ErrorMsgContent ::= SEQUENCE {
+                                   pKIStatusInfo          PKIStatusInfo,
+                                   errorCode              INTEGER           OPTIONAL,
+                                   -- implementation-specific error codes
+                                   errorDetails           PKIFreeText       OPTIONAL
+                                   -- implementation-specific error details
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.GenMsgContent.ToAsn1Object">
+            <pre>
+            GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.GenRepContent.ToAsn1Object">
+            <pre>
+            GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cmp.InfoTypeAndValue">
+             Example InfoTypeAndValue contents include, but are not limited
+             to, the following (un-comment in this ASN.1 module and use as
+             appropriate for a given environment):
+             <pre>
+               id-it-caProtEncCert    OBJECT IDENTIFIER ::= {id-it 1}
+                  CAProtEncCertValue      ::= CMPCertificate
+               id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+                 SignKeyPairTypesValue   ::= SEQUENCE OF AlgorithmIdentifier
+               id-it-encKeyPairTypes  OBJECT IDENTIFIER ::= {id-it 3}
+                 EncKeyPairTypesValue    ::= SEQUENCE OF AlgorithmIdentifier
+               id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+                  PreferredSymmAlgValue   ::= AlgorithmIdentifier
+               id-it-caKeyUpdateInfo  OBJECT IDENTIFIER ::= {id-it 5}
+                  CAKeyUpdateInfoValue    ::= CAKeyUpdAnnContent
+               id-it-currentCRL       OBJECT IDENTIFIER ::= {id-it 6}
+                  CurrentCRLValue         ::= CertificateList
+               id-it-unsupportedOIDs  OBJECT IDENTIFIER ::= {id-it 7}
+                  UnsupportedOIDsValue    ::= SEQUENCE OF OBJECT IDENTIFIER
+               id-it-keyPairParamReq  OBJECT IDENTIFIER ::= {id-it 10}
+                  KeyPairParamReqValue    ::= OBJECT IDENTIFIER
+               id-it-keyPairParamRep  OBJECT IDENTIFIER ::= {id-it 11}
+                  KeyPairParamRepValue    ::= AlgorithmIdentifer
+               id-it-revPassphrase    OBJECT IDENTIFIER ::= {id-it 12}
+                  RevPassphraseValue      ::= EncryptedValue
+               id-it-implicitConfirm  OBJECT IDENTIFIER ::= {id-it 13}
+                  ImplicitConfirmValue    ::= NULL
+               id-it-confirmWaitTime  OBJECT IDENTIFIER ::= {id-it 14}
+                  ConfirmWaitTimeValue    ::= GeneralizedTime
+               id-it-origPKIMessage   OBJECT IDENTIFIER ::= {id-it 15}
+                  OrigPKIMessageValue     ::= PKIMessages
+               id-it-suppLangTags     OBJECT IDENTIFIER ::= {id-it 16}
+                  SuppLangTagsValue       ::= SEQUENCE OF UTF8String
+            
+             where
+            
+               id-pkix OBJECT IDENTIFIER ::= {
+                  iso(1) identified-organization(3)
+                  dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+             and
+                  id-it   OBJECT IDENTIFIER ::= {id-pkix 4}
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.InfoTypeAndValue.ToAsn1Object">
+            <pre>
+            InfoTypeAndValue ::= SEQUENCE {
+                                    infoType               OBJECT IDENTIFIER,
+                                    infoValue              ANY DEFINED BY infoType  OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.KeyRecRepContent.ToAsn1Object">
+            <pre>
+            KeyRecRepContent ::= SEQUENCE {
+                                    status                  PKIStatusInfo,
+                                    newSigCert          [0] CMPCertificate OPTIONAL,
+                                    caCerts             [1] SEQUENCE SIZE (1..MAX) OF
+                                                                      CMPCertificate OPTIONAL,
+                                    keyPairHist         [2] SEQUENCE SIZE (1..MAX) OF
+                                                                      CertifiedKeyPair OPTIONAL
+                         }
+            </pre> 
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.OobCertHash.ToAsn1Object">
+            <pre>
+            OobCertHash ::= SEQUENCE {
+                                 hashAlg     [0] AlgorithmIdentifier     OPTIONAL,
+                                 certId      [1] CertId                  OPTIONAL,
+                                 hashVal         BIT STRING
+                                 -- hashVal is calculated over the Der encoding of the
+                                 -- self-signed certificate with the identifier certID.
+                  }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PbmParameter.ToAsn1Object">
+            <pre>
+             PbmParameter ::= SEQUENCE {
+                                   salt                OCTET STRING,
+                                   -- note:  implementations MAY wish to limit acceptable sizes
+                                   -- of this string to values appropriate for their environment
+                                   -- in order to reduce the risk of denial-of-service attacks
+                                   owf                 AlgorithmIdentifier,
+                                   -- AlgId for a One-Way Function (SHA-1 recommended)
+                                   iterationCount      INTEGER,
+                                   -- number of times the OWF is applied
+                                   -- note:  implementations MAY wish to limit acceptable sizes
+                                   -- of this integer to values appropriate for their environment
+                                   -- in order to reduce the risk of denial-of-service attacks
+                                   mac                 AlgorithmIdentifier
+                                   -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+               }   -- or HMAC [RFC2104, RFC2202])
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiBody.#ctor(System.Int32,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            Creates a new PkiBody.
+            @param type one of the TYPE_* constants
+            @param content message content
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiBody.ToAsn1Object">
+            <pre>
+            PkiBody ::= CHOICE {       -- message-specific body elements
+                   ir       [0]  CertReqMessages,        --Initialization Request
+                   ip       [1]  CertRepMessage,         --Initialization Response
+                   cr       [2]  CertReqMessages,        --Certification Request
+                   cp       [3]  CertRepMessage,         --Certification Response
+                   p10cr    [4]  CertificationRequest,   --imported from [PKCS10]
+                   popdecc  [5]  POPODecKeyChallContent, --pop Challenge
+                   popdecr  [6]  POPODecKeyRespContent,  --pop Response
+                   kur      [7]  CertReqMessages,        --Key Update Request
+                   kup      [8]  CertRepMessage,         --Key Update Response
+                   krr      [9]  CertReqMessages,        --Key Recovery Request
+                   krp      [10] KeyRecRepContent,       --Key Recovery Response
+                   rr       [11] RevReqContent,          --Revocation Request
+                   rp       [12] RevRepContent,          --Revocation Response
+                   ccr      [13] CertReqMessages,        --Cross-Cert. Request
+                   ccp      [14] CertRepMessage,         --Cross-Cert. Response
+                   ckuann   [15] CAKeyUpdAnnContent,     --CA Key Update Ann.
+                   cann     [16] CertAnnContent,         --Certificate Ann.
+                   rann     [17] RevAnnContent,          --Revocation Ann.
+                   crlann   [18] CRLAnnContent,          --CRL Announcement
+                   pkiconf  [19] PKIConfirmContent,      --Confirmation
+                   nested   [20] NestedMessageContent,   --Nested Message
+                   genm     [21] GenMsgContent,          --General Message
+                   genp     [22] GenRepContent,          --General Response
+                   error    [23] ErrorMsgContent,        --Error Message
+                   certConf [24] CertConfirmContent,     --Certificate confirm
+                   pollReq  [25] PollReqContent,         --Polling request
+                   pollRep  [26] PollRepContent          --Polling response
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiConfirmContent.ToAsn1Object">
+            <pre>
+            PkiConfirmContent ::= NULL
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cmp.PkiFailureInfo">
+            <pre>
+            PKIFailureInfo ::= BIT STRING {
+            badAlg               (0),
+              -- unrecognized or unsupported Algorithm Identifier
+            badMessageCheck      (1), -- integrity check failed (e.g., signature did not verify)
+            badRequest           (2),
+              -- transaction not permitted or supported
+            badTime              (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+            badCertId            (4), -- no certificate could be found matching the provided criteria
+            badDataFormat        (5),
+              -- the data submitted has the wrong format
+            wrongAuthority       (6), -- the authority indicated in the request is different from the one creating the response token
+            incorrectData        (7), -- the requester's data is incorrect (for notary services)
+            missingTimeStamp     (8), -- when the timestamp is missing but should be there (by policy)
+            badPOP               (9)  -- the proof-of-possession failed
+            timeNotAvailable    (14),
+              -- the TSA's time source is not available
+            unacceptedPolicy    (15),
+              -- the requested TSA policy is not supported by the TSA
+            unacceptedExtension (16),
+              -- the requested extension is not supported by the TSA
+             addInfoNotAvailable (17)
+               -- the additional information requested could not be understood
+               -- or is not available
+             systemFailure       (25)
+               -- the request cannot be handled due to system failure
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IAsn1String">
+            basic interface for Der string objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetPadBits(System.Int32)">
+            return the correct number of pad bits for a bit string defined in
+            a 32 bit constant
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetBytes(System.Int32)">
+            return the correct number of bytes for a bit string defined in
+            a 32 bit constant
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetInstance(System.Object)">
+             return a Bit string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Bit string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBitString.#ctor(System.Byte[],System.Int32)">
+            @param data the octets making up the bit string.
+            @param padBits the number of extra bits at the end of the string.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerBitString.IntValue">
+            @return the value of the bit string as an int (truncating if necessary)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiFailureInfo.#ctor(System.Int32)">
+            Basic constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.ToAsn1Object">
+            <pre>
+            PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.Size">
+             Return the number of string elements present.
+            
+             @return number of elements present.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cmp.PkiFreeText.Item(System.Int32)">
+             Return the UTF8STRING at index.
+            
+             @param index index of the string of interest
+             @return the string at index.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Cmp.PkiHeader.NULL_NAME">
+            Value for a "null" recipient or sender.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiHeader.ToAsn1Object">
+            <pre>
+             PkiHeader ::= SEQUENCE {
+                       pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+                       sender              GeneralName,
+                       -- identifies the sender
+                       recipient           GeneralName,
+                       -- identifies the intended recipient
+                       messageTime     [0] GeneralizedTime         OPTIONAL,
+                       -- time of production of this message (used when sender
+                       -- believes that the transport will be "suitable"; i.e.,
+                       -- that the time will still be meaningful upon receipt)
+                       protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+                       -- algorithm used for calculation of protection bits
+                       senderKID       [2] KeyIdentifier           OPTIONAL,
+                       recipKID        [3] KeyIdentifier           OPTIONAL,
+                       -- to identify specific keys used for protection
+                       transactionID   [4] OCTET STRING            OPTIONAL,
+                       -- identifies the transaction; i.e., this will be the same in
+                       -- corresponding request, response, certConf, and PKIConf
+                       -- messages
+                       senderNonce     [5] OCTET STRING            OPTIONAL,
+                       recipNonce      [6] OCTET STRING            OPTIONAL,
+                       -- nonces used to provide replay protection, senderNonce
+                       -- is inserted by the creator of this message; recipNonce
+                       -- is a nonce previously inserted in a related message by
+                       -- the intended recipient of this message
+                       freeText        [7] PKIFreeText             OPTIONAL,
+                       -- this may be used to indicate context-specific instructions
+                       -- (this field is intended for human consumption)
+                       generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+                                            InfoTypeAndValue     OPTIONAL
+                       -- this may be used to convey context-specific information
+                       -- (this field not primarily intended for human consumption)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiHeaderBuilder.Build">
+            <pre>
+             PKIHeader ::= SEQUENCE {
+                       pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+                       sender              GeneralName,
+                       -- identifies the sender
+                       recipient           GeneralName,
+                       -- identifies the intended recipient
+                       messageTime     [0] GeneralizedTime         OPTIONAL,
+                       -- time of production of this message (used when sender
+                       -- believes that the transport will be "suitable"; i.e.,
+                       -- that the time will still be meaningful upon receipt)
+                       protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+                       -- algorithm used for calculation of protection bits
+                       senderKID       [2] KeyIdentifier           OPTIONAL,
+                       recipKID        [3] KeyIdentifier           OPTIONAL,
+                       -- to identify specific keys used for protection
+                       transactionID   [4] OCTET STRING            OPTIONAL,
+                       -- identifies the transaction; i.e., this will be the same in
+                       -- corresponding request, response, certConf, and PKIConf
+                       -- messages
+                       senderNonce     [5] OCTET STRING            OPTIONAL,
+                       recipNonce      [6] OCTET STRING            OPTIONAL,
+                       -- nonces used to provide replay protection, senderNonce
+                       -- is inserted by the creator of this message; recipNonce
+                       -- is a nonce previously inserted in a related message by
+                       -- the intended recipient of this message
+                       freeText        [7] PKIFreeText             OPTIONAL,
+                       -- this may be used to indicate context-specific instructions
+                       -- (this field is intended for human consumption)
+                       generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+                                            InfoTypeAndValue     OPTIONAL
+                       -- this may be used to convey context-specific information
+                       -- (this field not primarily intended for human consumption)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessage.#ctor(Org.BouncyCastle.Asn1.Cmp.PkiHeader,Org.BouncyCastle.Asn1.Cmp.PkiBody,Org.BouncyCastle.Asn1.DerBitString,Org.BouncyCastle.Asn1.Cmp.CmpCertificate[])">
+             Creates a new PkiMessage.
+            
+             @param header message header
+             @param body message body
+             @param protection message protection (may be null)
+             @param extraCerts extra certificates (may be null)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessage.ToAsn1Object">
+            <pre>
+            PkiMessage ::= SEQUENCE {
+                             header           PKIHeader,
+                             body             PKIBody,
+                             protection   [0] PKIProtection OPTIONAL,
+                             extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+                                                                                OPTIONAL
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiMessages.ToAsn1Object">
+            <pre>
+            PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.#ctor(System.Int32)">
+            @param status
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.#ctor(System.Int32,Org.BouncyCastle.Asn1.Cmp.PkiFreeText)">
+            @param status
+            @param statusString
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PkiStatusInfo.ToAsn1Object">
+             <pre>
+             PkiStatusInfo ::= SEQUENCE {
+                 status        PKIStatus,                (INTEGER)
+                 statusString  PkiFreeText     OPTIONAL,
+                 failInfo      PkiFailureInfo  OPTIONAL  (BIT STRING)
+             }
+            
+             PKIStatus:
+               granted                (0), -- you got exactly what you asked for
+               grantedWithMods        (1), -- you got something like what you asked for
+               rejection              (2), -- you don't get it, more information elsewhere in the message
+               waiting                (3), -- the request body part has not yet been processed, expect to hear more later
+               revocationWarning      (4), -- this message contains a warning that a revocation is imminent
+               revocationNotification (5), -- notification that a revocation has occurred
+               keyUpdateWarning       (6)  -- update already done for the oldCertId specified in CertReqMsg
+            
+             PkiFailureInfo:
+               badAlg           (0), -- unrecognized or unsupported Algorithm Identifier
+               badMessageCheck  (1), -- integrity check failed (e.g., signature did not verify)
+               badRequest       (2), -- transaction not permitted or supported
+               badTime          (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+               badCertId        (4), -- no certificate could be found matching the provided criteria
+               badDataFormat    (5), -- the data submitted has the wrong format
+               wrongAuthority   (6), -- the authority indicated in the request is different from the one creating the response token
+               incorrectData    (7), -- the requester's data is incorrect (for notary services)
+               missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+               badPOP           (9)  -- the proof-of-possession failed
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PollRepContent.ToAsn1Object">
+            <pre>
+            PollRepContent ::= SEQUENCE OF SEQUENCE {
+                    certReqId              INTEGER,
+                    checkAfter             INTEGER,  -- time in seconds
+                    reason                 PKIFreeText OPTIONAL
+                }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PollReqContent.ToAsn1Object">
+            <pre>
+            PollReqContent ::= SEQUENCE OF SEQUENCE {
+                                   certReqId              INTEGER
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PopoDecKeyChallContent.ToAsn1Object">
+            <pre>
+            PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.PopoDecKeyRespContent.ToAsn1Object">
+            <pre>
+            PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.ProtectedPart.ToAsn1Object">
+            <pre>
+            ProtectedPart ::= SEQUENCE {
+                               header    PKIHeader,
+                               body      PKIBody
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevAnnContent.ToAsn1Object">
+            <pre>
+            RevAnnContent ::= SEQUENCE {
+                  status              PKIStatus,
+                  certId              CertId,
+                  willBeRevokedAt     GeneralizedTime,
+                  badSinceDate        GeneralizedTime,
+                  crlDetails          Extensions  OPTIONAL
+                   -- extra CRL details (e.g., crl number, reason, location, etc.)
+            }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevDetails.ToAsn1Object">
+            <pre>
+            RevDetails ::= SEQUENCE {
+                             certDetails         CertTemplate,
+                              -- allows requester to specify as much as they can about
+                              -- the cert. for which revocation is requested
+                              -- (e.g., for cases in which serialNumber is not available)
+                              crlEntryDetails     Extensions       OPTIONAL
+                              -- requested crlEntryExtensions
+                        }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevRepContent.ToAsn1Object">
+            <pre>
+            RevRepContent ::= SEQUENCE {
+                   status       SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+                   -- in same order as was sent in RevReqContent
+                   revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+                   -- IDs for which revocation was requested
+                   -- (same order as status)
+                   crls     [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+                   -- the resulting CRLs (there may be more than one)
+              }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cmp.RevReqContent.ToAsn1Object">
+            <pre>
+            RevReqContent ::= SEQUENCE OF RevDetails
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attribute.GetInstance(System.Object)">
+             return an Attribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attribute.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attribute ::= SEQUENCE {
+                attrType OBJECT IDENTIFIER,
+                attrValues SET OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Attributes.ToAsn1Object">
+            <pre>
+            Attributes ::=
+              SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AttributeTable.GetAll(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+             empty if there are no attributes of the required type present.
+            
+             @param oid type of attribute required.
+             @return a vector of all the attributes found of type oid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AttributeTable.Add(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Return a new table with the passed in attribute added.
+            
+             @param attrType
+             @param attrValue
+             @return
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Cms.AttributeTable.Item(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthenticatedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.GetInstance(System.Object)">
+             return an AuthenticatedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthenticatedData.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             AuthenticatedData ::= SEQUENCE {
+                   version CMSVersion,
+                   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                   recipientInfos RecipientInfos,
+                   macAlgorithm MessageAuthenticationCodeAlgorithm,
+                   digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+                   encapContentInfo EncapsulatedContentInfo,
+                   authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+                   mac MessageAuthenticationCode,
+                   unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+            
+             AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             MessageAuthenticationCode ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.AuthenticatedDataParser">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             AuthenticatedData ::= SEQUENCE {
+                   version CMSVersion,
+                   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                   recipientInfos RecipientInfos,
+                   macAlgorithm MessageAuthenticationCodeAlgorithm,
+                   digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+                   encapContentInfo EncapsulatedContentInfo,
+                   authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+                   mac MessageAuthenticationCode,
+                   unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+            
+             AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+            
+             MessageAuthenticationCode ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthEnvelopedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.GetInstance(System.Object)">
+             return an AuthEnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            AuthEnvelopedData ::= SEQUENCE {
+              version CMSVersion,
+              originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+              recipientInfos RecipientInfos,
+              authEncryptedContentInfo EncryptedContentInfo,
+              authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+              mac MessageAuthenticationCode,
+              unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.AuthEnvelopedDataParser">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            <pre>
+            AuthEnvelopedData ::= SEQUENCE {
+              version CMSVersion,
+              originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+              recipientInfos RecipientInfos,
+              authEncryptedContentInfo EncryptedContentInfo,
+              authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+              mac MessageAuthenticationCode,
+              unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.CompressedData">
+            RFC 3274 - CMS Compressed Data.
+            <pre>
+            CompressedData ::= Sequence {
+             version CMSVersion,
+             compressionAlgorithm CompressionAlgorithmIdentifier,
+             encapContentInfo EncapsulatedContentInfo
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.CompressedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a CompressedData object from a tagged object.
+            
+             @param ato the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.CompressedData.GetInstance(System.Object)">
+             return a CompressedData object from the given object.
+            
+             @param _obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.CompressedDataParser">
+            RFC 3274 - CMS Compressed Data.
+            <pre>
+            CompressedData ::= SEQUENCE {
+             version CMSVersion,
+             compressionAlgorithm CompressionAlgorithmIdentifier,
+             encapContentInfo EncapsulatedContentInfo
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.ContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= Sequence {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.ContentInfoParser">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= SEQUENCE {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an AuthEnvelopedData object from a tagged object.
+            
+             @param obj      the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                             tagged false otherwise.
+             @throws ArgumentException if the object held by the
+                                              tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.GetInstance(System.Object)">
+             return an AuthEnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @throws ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Ecc.MQVuserKeyingMaterial.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            MQVuserKeyingMaterial ::= SEQUENCE {
+              ephemeralPublicKey OriginatorPublicKey,
+              addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfo.GetInstance(System.Object)">
+             return an EncryptedContentInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EncryptedContentInfo ::= Sequence {
+                contentType ContentType,
+                contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+                encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.EncryptedContentInfoParser">
+            <pre>
+            EncryptedContentInfo ::= SEQUENCE {
+                contentType ContentType,
+                contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+                encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EncryptedData.ToAsn1Object">
+            <pre>
+                  EncryptedData ::= SEQUENCE {
+                                version CMSVersion,
+                                encryptedContentInfo EncryptedContentInfo,
+                                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an EnvelopedData object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.GetInstance(System.Object)">
+             return an EnvelopedData object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.EnvelopedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EnvelopedData ::= Sequence {
+                version CMSVersion,
+                originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                recipientInfos RecipientInfos,
+                encryptedContentInfo EncryptedContentInfo,
+                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.EnvelopedDataParser">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            EnvelopedData ::= SEQUENCE {
+                version CMSVersion,
+                originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+                recipientInfos RecipientInfos,
+                encryptedContentInfo EncryptedContentInfo,
+                unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KekIdentifier object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.GetInstance(System.Object)">
+             return a KekIdentifier object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KekIdentifier ::= Sequence {
+                keyIdentifier OCTET STRING,
+                date GeneralizedTime OPTIONAL,
+                other OtherKeyAttribute OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KekRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.GetInstance(System.Object)">
+             return a KekRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KekRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KekRecipientInfo ::= Sequence {
+                version CMSVersion,  -- always set to 4
+                kekID KekIdentifier,
+                keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an KeyAgreeRecipientIdentifier object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.GetInstance(System.Object)">
+             return an KeyAgreeRecipientIdentifier object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KeyAgreeRecipientIdentifier ::= CHOICE {
+                issuerAndSerialNumber IssuerAndSerialNumber,
+                rKeyId [0] IMPLICIT RecipientKeyIdentifier
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a KeyAgreeRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.GetInstance(System.Object)">
+             return a KeyAgreeRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyAgreeRecipientInfo.ToAsn1Object">
+                     * Produce an object suitable for an Asn1OutputStream.
+                     * <pre>
+                     * KeyAgreeRecipientInfo ::= Sequence {
+                     *     version CMSVersion,  -- always set to 3
+                     *     originator [0] EXPLICIT OriginatorIdentifierOrKey,
+                     *     ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+                     *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                     *     recipientEncryptedKeys RecipientEncryptedKeys
+                     * }
+            		 *
+            		 * UserKeyingMaterial ::= OCTET STRING
+                     * </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyTransRecipientInfo.GetInstance(System.Object)">
+             return a KeyTransRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.KeyTransRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            KeyTransRecipientInfo ::= Sequence {
+                version CMSVersion,  -- always set to 0 or 2
+                rid RecipientIdentifier,
+                keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.MetaData.ToAsn1Object">
+            <pre>
+            MetaData ::= SEQUENCE {
+              hashProtected        BOOLEAN,
+              fileName             UTF8String OPTIONAL,
+              mediaType            IA5String OPTIONAL,
+              otherMetaData        Attributes OPTIONAL
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorIdentifierOrKey object from a tagged object.
+            
+             @param o the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.GetInstance(System.Object)">
+             return an OriginatorIdentifierOrKey object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorIdentifierOrKey.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             OriginatorIdentifierOrKey ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier,
+                 originatorKey [1] OriginatorPublicKey
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.GetInstance(System.Object)">
+             return an OriginatorInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OriginatorInfo ::= Sequence {
+                certs [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an OriginatorPublicKey object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.GetInstance(System.Object)">
+             return an OriginatorPublicKey object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OriginatorPublicKey.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OriginatorPublicKey ::= Sequence {
+                algorithm AlgorithmIdentifier,
+                publicKey BIT STRING
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherKeyAttribute.GetInstance(System.Object)">
+             return an OtherKeyAttribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherKeyAttribute.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OtherKeyAttribute ::= Sequence {
+                keyAttrId OBJECT IDENTIFIER,
+                keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a OtherRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.GetInstance(System.Object)">
+             return a OtherRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.OtherRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OtherRecipientInfo ::= Sequence {
+               oriType OBJECT IDENTIFIER,
+               oriValue ANY DEFINED BY oriType }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a PasswordRecipientInfo object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.GetInstance(System.Object)">
+             return a PasswordRecipientInfo object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.PasswordRecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            PasswordRecipientInfo ::= Sequence {
+              version CMSVersion,   -- Always set to 0
+              keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+                                        OPTIONAL,
+             keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+             encryptedKey EncryptedKey }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an RecipientEncryptedKey object from a tagged object.
+            
+             @param obj the tagged object holding the object we want.
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.GetInstance(System.Object)">
+             return a RecipientEncryptedKey object from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientEncryptedKey.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RecipientEncryptedKey ::= SEQUENCE {
+                rid KeyAgreeRecipientIdentifier,
+                encryptedKey EncryptedKey
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientIdentifier.GetInstance(System.Object)">
+             return a RecipientIdentifier object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             RecipientIdentifier ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RecipientInfo ::= CHOICE {
+                ktri KeyTransRecipientInfo,
+                kari [1] KeyAgreeRecipientInfo,
+                kekri [2] KekRecipientInfo,
+                pwri [3] PasswordRecipientInfo,
+                ori [4] OtherRecipientInfo }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a RecipientKeyIdentifier object from a tagged object.
+            
+             @param _ato the tagged object holding the object we want.
+             @param _explicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the object held by the
+                      tagged object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.GetInstance(System.Object)">
+             return a RecipientKeyIdentifier object from the given object.
+            
+             @param _obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.RecipientKeyIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             RecipientKeyIdentifier ::= Sequence {
+                 subjectKeyIdentifier SubjectKeyIdentifier,
+                 date GeneralizedTime OPTIONAL,
+                 other OtherKeyAttribute OPTIONAL
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.SignedData">
+            a signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SignedData ::= Sequence {
+                version CMSVersion,
+                digestAlgorithms DigestAlgorithmIdentifiers,
+                encapContentInfo EncapsulatedContentInfo,
+                certificates [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                signerInfos SignerInfos
+              }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Cms.SignedDataParser">
+            <pre>
+            SignedData ::= SEQUENCE {
+                version CMSVersion,
+                digestAlgorithms DigestAlgorithmIdentifiers,
+                encapContentInfo EncapsulatedContentInfo,
+                certificates [0] IMPLICIT CertificateSet OPTIONAL,
+                crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                signerInfos SignerInfos
+              }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerIdentifier.GetInstance(System.Object)">
+             return a SignerIdentifier object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerIdentifier.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             SignerIdentifier ::= CHOICE {
+                 issuerAndSerialNumber IssuerAndSerialNumber,
+                 subjectKeyIdentifier [0] SubjectKeyIdentifier
+             }
+            
+             SubjectKeyIdentifier ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.SignerInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              SignerInfo ::= Sequence {
+                  version Version,
+                  SignerIdentifier sid,
+                  digestAlgorithm DigestAlgorithmIdentifier,
+                  authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+                  digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+                  encryptedDigest EncryptedDigest,
+                  unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+              }
+            
+              EncryptedDigest ::= OCTET STRING
+            
+              DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+            
+              DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Time.#ctor(System.DateTime)">
+            creates a time object from a given date - if the date is between 1950
+            and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+            is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.Time.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Time ::= CHOICE {
+                        utcTime        UTCTime,
+                        generalTime    GeneralizedTime }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampAndCrl.ToAsn1Object">
+            <pre>
+            TimeStampAndCRL ::= SEQUENCE {
+                timeStamp   TimeStampToken,          -- according to RFC 3161
+                crl         CertificateList OPTIONAL -- according to RFC 5280
+             }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampedData.ToAsn1Object">
+            <pre>
+            TimeStampedData ::= SEQUENCE {
+              version              INTEGER { v1(1) },
+              dataUri              IA5String OPTIONAL,
+              metaData             MetaData OPTIONAL,
+              content              OCTET STRING OPTIONAL,
+              temporalEvidence     Evidence
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Cms.TimeStampTokenEvidence.ToAsn1Object">
+            <pre>
+            TimeStampTokenEvidence ::=
+               SEQUENCE SIZE(1..MAX) OF TimeStampAndCrl
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.AttributeTypeAndValue.ToAsn1Object">
+            <pre>
+            AttributeTypeAndValue ::= SEQUENCE {
+                      type         OBJECT IDENTIFIER,
+                      value        ANY DEFINED BY type }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertId.ToAsn1Object">
+            <pre>
+            CertId ::= SEQUENCE {
+                            issuer           GeneralName,
+                            serialNumber     INTEGER }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMessages.ToAsn1Object">
+            <pre>
+            CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMsg.#ctor(Org.BouncyCastle.Asn1.Crmf.CertRequest,Org.BouncyCastle.Asn1.Crmf.ProofOfPossession,Org.BouncyCastle.Asn1.Crmf.AttributeTypeAndValue[])">
+            Creates a new CertReqMsg.
+            @param certReq CertRequest
+            @param popo may be null
+            @param regInfo may be null
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertReqMsg.ToAsn1Object">
+            <pre>
+            CertReqMsg ::= SEQUENCE {
+                               certReq   CertRequest,
+                               pop       ProofOfPossession  OPTIONAL,
+                               -- content depends upon key type
+                               regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertRequest.ToAsn1Object">
+            <pre>
+            CertRequest ::= SEQUENCE {
+                                 certReqId     INTEGER,          -- ID for matching request and reply
+                                 certTemplate  CertTemplate,  -- Selected fields of cert to be issued
+                                 controls      Controls OPTIONAL }   -- Attributes affecting issuance
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplate.ToAsn1Object">
+            <pre>
+             CertTemplate ::= SEQUENCE {
+                 version      [0] Version               OPTIONAL,
+                 serialNumber [1] INTEGER               OPTIONAL,
+                 signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+                 issuer       [3] Name                  OPTIONAL,
+                 validity     [4] OptionalValidity      OPTIONAL,
+                 subject      [5] Name                  OPTIONAL,
+                 publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+                 issuerUID    [7] UniqueIdentifier      OPTIONAL,
+                 subjectUID   [8] UniqueIdentifier      OPTIONAL,
+                 extensions   [9] Extensions            OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetVersion(System.Int32)">
+            Sets the X.509 version. Note: for X509v3, use 2 here. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetIssuerUID(Org.BouncyCastle.Asn1.DerBitString)">
+            Sets the issuer unique ID (deprecated in X.509v3) 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.SetSubjectUID(Org.BouncyCastle.Asn1.DerBitString)">
+            Sets the subject unique ID (deprecated in X.509v3) 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.CertTemplateBuilder.Build">
+            <pre>
+             CertTemplate ::= SEQUENCE {
+                 version      [0] Version               OPTIONAL,
+                 serialNumber [1] INTEGER               OPTIONAL,
+                 signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+                 issuer       [3] Name                  OPTIONAL,
+                 validity     [4] OptionalValidity      OPTIONAL,
+                 subject      [5] Name                  OPTIONAL,
+                 publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+                 issuerUID    [7] UniqueIdentifier      OPTIONAL,
+                 subjectUID   [8] UniqueIdentifier      OPTIONAL,
+                 extensions   [9] Extensions            OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.Controls.ToAsn1Object">
+            <pre>
+            Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncKeyWithID.ToAsn1Object">
+            <pre>
+            EncKeyWithID ::= SEQUENCE {
+                 privateKey           PrivateKeyInfo,
+                 identifier CHOICE {
+                    string               UTF8String,
+                    generalName          GeneralName
+                } OPTIONAL
+            }
+            </pre>
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncryptedKey.ToAsn1Object">
+            <pre>
+               EncryptedKey ::= CHOICE {
+                   encryptedValue        EncryptedValue, -- deprecated
+                   envelopedData     [0] EnvelopedData }
+                   -- The encrypted private key MUST be placed in the envelopedData
+                   -- encryptedContentInfo encryptedContent OCTET STRING.
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.EncryptedValue.ToAsn1Object">
+            <pre>
+            EncryptedValue ::= SEQUENCE {
+                                intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
+                                -- the intended algorithm for which the value will be used
+                                symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
+                                -- the symmetric algorithm used to encrypt the value
+                                encSymmKey    [2] BIT STRING           OPTIONAL,
+                                -- the (encrypted) symmetric key used to encrypt the value
+                                keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
+                                -- algorithm used to encrypt the symmetric key
+                                valueHint     [4] OCTET STRING         OPTIONAL,
+                                -- a brief description or identifier of the encValue content
+                                -- (may be meaningful only to the sending entity, and used only
+                                -- if EncryptedValue might be re-examined by the sending entity
+                                -- in the future)
+                                encValue       BIT STRING }
+                                -- the encrypted value itself
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.OptionalValidity.ToAsn1Object">
+            <pre>
+            OptionalValidity ::= SEQUENCE {
+                                   notBefore  [0] Time OPTIONAL,
+                                   notAfter   [1] Time OPTIONAL } --at least one MUST be present
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PkiArchiveOptions.ToAsn1Object">
+            <pre>
+             PkiArchiveOptions ::= CHOICE {
+                 encryptedPrivKey     [0] EncryptedKey,
+                 -- the actual value of the private key
+                 keyGenParameters     [1] KeyGenParameters,
+                 -- parameters which allow the private key to be re-generated
+                 archiveRemGenPrivKey [2] BOOLEAN }
+                 -- set to TRUE if sender wishes receiver to archive the private
+                 -- key of a key pair that the receiver generates in response to
+                 -- this request; set to FALSE if no archival is desired.
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PkiPublicationInfo.ToAsn1Object">
+            <pre>
+            PkiPublicationInfo ::= SEQUENCE {
+                             action     INTEGER {
+                                            dontPublish (0),
+                                            pleasePublish (1) },
+                             pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+            -- pubInfos MUST NOT be present if action is "dontPublish"
+            -- (if action is "pleasePublish" and pubInfos is omitted,
+            -- "dontCare" is assumed)
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Crmf.PKMacValue">
+            Password-based MAC value for use with POPOSigningKeyInput.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.#ctor(Org.BouncyCastle.Asn1.Cmp.PbmParameter,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new PKMACValue.
+            @param params parameters for password-based MAC
+            @param value MAC of the DER-encoded SubjectPublicKeyInfo
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.#ctor(Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new PKMACValue.
+            @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+            @param value MAC of the DER-encoded SubjectPublicKeyInfo
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PKMacValue.ToAsn1Object">
+            <pre>
+            PKMACValue ::= SEQUENCE {
+                 algId  AlgorithmIdentifier,
+                 -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+                 -- parameter value is PBMParameter
+                 value  BIT STRING }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoPrivKey.ToAsn1Object">
+            <pre>
+            PopoPrivKey ::= CHOICE {
+                   thisMessage       [0] BIT STRING,         -- Deprecated
+                    -- possession is proven in this message (which contains the private
+                    -- key itself (encrypted for the CA))
+                   subsequentMessage [1] SubsequentMessage,
+                    -- possession will be proven in a subsequent message
+                   dhMAC             [2] BIT STRING,         -- Deprecated
+                   agreeMAC          [3] PKMACValue,
+                   encryptedKey      [4] EnvelopedData }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKey.#ctor(Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput,Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,Org.BouncyCastle.Asn1.DerBitString)">
+            Creates a new Proof of Possession object for a signing key.
+            @param poposkIn the PopoSigningKeyInput structure, or null if the
+                CertTemplate includes both subject and publicKey values.
+            @param aid the AlgorithmIdentifier used to sign the proof of possession.
+            @param signature a signature over the DER-encoded value of poposkIn,
+                or the DER-encoded value of certReq if poposkIn is null.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKey.ToAsn1Object">
+            <pre>
+            PopoSigningKey ::= SEQUENCE {
+                                 poposkInput           [0] PopoSigningKeyInput OPTIONAL,
+                                 algorithmIdentifier   AlgorithmIdentifier,
+                                 signature             BIT STRING }
+             -- The signature (using "algorithmIdentifier") is on the
+             -- DER-encoded value of poposkInput.  NOTE: If the CertReqMsg
+             -- certReq CertTemplate contains the subject and publicKey values,
+             -- then poposkInput MUST be omitted and the signature MUST be
+             -- computed on the DER-encoded value of CertReqMsg certReq.  If
+             -- the CertReqMsg certReq CertTemplate does not contain the public
+             -- key and subject values, then poposkInput MUST be present and
+             -- MUST be signed.  This strategy ensures that the public key is
+             -- not present in both the poposkInput and CertReqMsg certReq
+             -- CertTemplate fields.
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Creates a new PopoSigningKeyInput with sender name as authInfo. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.#ctor(Org.BouncyCastle.Asn1.Crmf.PKMacValue,Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Creates a new PopoSigningKeyInput using password-based MAC. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.ToAsn1Object">
+            <pre>
+            PopoSigningKeyInput ::= SEQUENCE {
+                   authInfo             CHOICE {
+                                            sender              [0] GeneralName,
+                                            -- used only if an authenticated identity has been
+                                            -- established for the sender (e.g., a DN from a
+                                            -- previously-issued and currently-valid certificate
+                                            publicKeyMac        PKMacValue },
+                                            -- used if no authenticated GeneralName currently exists for
+                                            -- the sender; publicKeyMac contains a password-based MAC
+                                            -- on the DER-encoded value of publicKey
+                   publicKey           SubjectPublicKeyInfo }  -- from CertTemplate
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.Sender">
+            Returns the sender field, or null if authInfo is publicKeyMac 
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Crmf.PopoSigningKeyInput.PublicKeyMac">
+            Returns the publicKeyMac field, or null if authInfo is sender 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor">
+            Creates a ProofOfPossession with type raVerified. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor(Org.BouncyCastle.Asn1.Crmf.PopoSigningKey)">
+            Creates a ProofOfPossession for a signing key. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.#ctor(System.Int32,Org.BouncyCastle.Asn1.Crmf.PopoPrivKey)">
+            Creates a ProofOfPossession for key encipherment or agreement.
+            @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.ProofOfPossession.ToAsn1Object">
+            <pre>
+            ProofOfPossession ::= CHOICE {
+                                      raVerified        [0] NULL,
+                                      -- used if the RA has already verified that the requester is in
+                                      -- possession of the private key
+                                      signature         [1] PopoSigningKey,
+                                      keyEncipherment   [2] PopoPrivKey,
+                                      keyAgreement      [3] PopoPrivKey }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Crmf.SinglePubInfo.ToAsn1Object">
+            <pre>
+            SinglePubInfo ::= SEQUENCE {
+                   pubMethod    INTEGER {
+                      dontCare    (0),
+                      x500        (1),
+                      web         (2),
+                      ldap        (3) },
+                  pubLocation  GeneralName OPTIONAL }
+            </pre>
+            @return a basic ASN.1 object representation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerInteger.GetInstance(System.Object)">
+             return an integer from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerInteger.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Integer from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param isExplicit true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerInteger.PositiveValue">
+            in some cases positive values Get crammed into a space,
+            that's not quite big enough...
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves">
+            table of the available named parameters for GOST 3410-2001.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the ECDomainParameters object for the given OID, null if it
+             isn't present.
+            
+             @param oid an object identifier representing a named parameters, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.CryptoPro.ECGost3410NamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.Gost28147Parameters.ToAsn1Object">
+             <pre>
+             Gost28147-89-Parameters ::=
+                           SEQUENCE {
+                                   iv                   Gost28147-89-IV,
+                                   encryptionParamSet   OBJECT IDENTIFIER
+                            }
+            
+               Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters">
+            table of the available named parameters for GOST 3410-94.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the GOST3410ParamSetParameters object for the given OID, null if it
+             isn't present.
+            
+             @param oid an object identifier representing a named parameters, if present.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.CryptoPro.Gost3410NamedParameters.Names">
+            returns an enumeration containing the name strings for parameters
+            contained in this structure.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerBmpString">
+            Der BMPString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.GetInstance(System.Object)">
+             return a BMP string from the given object.
+            
+             @param obj the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a BMP string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                          be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBmpString.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(System.Object)">
+             return a bool from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(System.Boolean)">
+            return a DerBoolean from the passed in bool.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerBoolean.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Boolean from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerEnumerated.GetInstance(System.Object)">
+             return an integer from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerEnumerated.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Enumerated from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerExternal">
+            Class representing the DER-type External
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerExternal.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.DerInteger,Org.BouncyCastle.Asn1.Asn1Object,Org.BouncyCastle.Asn1.DerTaggedObject)">
+            Creates a new instance of DerExternal
+            See X.690 for more informations about the meaning of these parameters
+            @param directReference The direct reference or <code>null</code> if not set.
+            @param indirectReference The indirect reference or <code>null</code> if not set.
+            @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+            @param externalData The external data in its encoded form.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerExternal.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.DerInteger,Org.BouncyCastle.Asn1.Asn1Object,System.Int32,Org.BouncyCastle.Asn1.Asn1Object)">
+            Creates a new instance of DerExternal.
+            See X.690 for more informations about the meaning of these parameters
+            @param directReference The direct reference or <code>null</code> if not set.
+            @param indirectReference The indirect reference or <code>null</code> if not set.
+            @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+            @param encoding The encoding to be used for the external data
+            @param externalData The external data
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerExternal.Encoding">
+            The encoding of the content. Valid values are
+            <ul>
+            <li><code>0</code> single-ASN1-type</li>
+            <li><code>1</code> OCTET STRING</li>
+            <li><code>2</code> BIT STRING</li>
+            </ul>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerGeneralizedTime">
+            Generalized time object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetInstance(System.Object)">
+             return a generalized time from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Generalized Time object from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.#ctor(System.String)">
+             The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+             for local time, or Z+-HHMM on the end, for difference between local
+             time and UTC time. The fractional second amount f must consist of at
+             least one number with trailing zeroes removed.
+            
+             @param time the time string.
+             @exception ArgumentException if string is an illegal format.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.#ctor(System.DateTime)">
+            base constructor from a local time object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerGeneralizedTime.GetTime">
+            return the time - always in the form of
+             YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+            <p>
+            Normally in a certificate we would expect "Z" rather than "GMT",
+            however adding the "GMT" means we can just use:
+            <pre>
+                dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+            </pre>
+            To read in the time and Get a date which is compatible with our local
+            time zone.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerGeneralizedTime.TimeString">
+            Return the time.
+            @return The time string as it appeared in the encoded object.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerIA5String">
+            Der IA5String object - this is an ascii string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.GetInstance(System.Object)">
+             return a IA5 string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an IA5 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.String)">
+            basic constructor - without validation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in an IA5String.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerIA5String.IsIA5String(System.String)">
+             return true if the passed in String can be represented without
+             loss as an IA5String, false otherwise.
+            
+             @return true if in printable set, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerNumericString">
+            Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.GetInstance(System.Object)">
+             return a Numeric string from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an Numeric string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.String)">
+            basic constructor -  without validation..
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in a NumericString.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerNumericString.IsNumericString(System.String)">
+             Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+            
+             @param str string to validate.
+             @return true if numeric, fale otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.GetInstance(System.Object)">
+             return an Oid from the passed in object
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an object Identifier from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerObjectIdentifier.On(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            Return  true if this oid is an extension of the passed in branch, stem.
+            @param stem the arc or branch that is a possible parent.
+            @return  true if the branch is on the passed in stem, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerPrintableString">
+            Der PrintableString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.GetInstance(System.Object)">
+             return a printable string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Printable string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.String)">
+            basic constructor - this does not validate the string
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.#ctor(System.String,System.Boolean)">
+             Constructor with optional validation.
+            
+             @param string the base string to wrap.
+             @param validate whether or not to check the string.
+             @throws ArgumentException if validate is true and the string
+             contains characters that should not be in a PrintableString.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerPrintableString.IsPrintableString(System.String)">
+             return true if the passed in String can be represented without
+             loss as a PrintableString, false otherwise.
+            
+             @return true if in printable set, false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerT61String">
+            Der T61String (also the teletex string) - 8-bit characters
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.GetInstance(System.Object)">
+             return a T61 string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an T61 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.#ctor(System.Byte[])">
+            basic constructor - with bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerT61String.#ctor(System.String)">
+            basic constructor - with string.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUniversalString">
+            Der UniversalString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.GetInstance(System.Object)">
+             return a Universal string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Universal string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUniversalString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUnknownTag">
+            We insert one of these when we find a tag we don't recognise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUnknownTag.#ctor(System.Int32,System.Byte[])">
+            @param tag the tag value.
+            @param data the contents octets.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUtcTime">
+            UTC time object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.GetInstance(System.Object)">
+             return an UTC Time from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an UTC Time from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.#ctor(System.String)">
+            The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+            never encoded. When you're creating one of these objects from scratch, that's
+            what you want to use, otherwise we'll try to deal with whatever Gets read from
+            the input stream... (this is why the input format is different from the GetTime()
+            method output).
+            <p>
+            @param time the time string.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.#ctor(System.DateTime)">
+            base constructor from a DateTime object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.ToDateTime">
+             return the time as a date based on whatever a 2 digit year will return. For
+             standardised processing use ToAdjustedDateTime().
+            
+             @return the resulting date
+             @exception ParseException if the date string cannot be parsed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtcTime.ToAdjustedDateTime">
+             return the time as an adjusted date
+             in the range of 1950 - 2049.
+            
+             @return a date in the range of 1950 to 2049.
+             @exception ParseException if the date string cannot be parsed.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerUtcTime.TimeString">
+            return the time - always in the form of
+             YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+            <p>
+            Normally in a certificate we would expect "Z" rather than "GMT",
+            however adding the "GMT" means we can just use:
+            <pre>
+                dateF = new SimpleDateFormat("yyMMddHHmmssz");
+            </pre>
+            To read in the time and Get a date which is compatible with our local
+            time zone.</p>
+            <p>
+            <b>Note:</b> In some cases, due to the local date processing, this
+            may lead to unexpected results. If you want to stick the normal
+            convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.DerUtcTime.AdjustedTimeString">
+            <summary>
+            Return a time string as an adjusted date with a 4 digit year.
+            This goes in the range of 1950 - 2049.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerUtf8String">
+            Der UTF8String object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.GetInstance(System.Object)">
+             return an UTF8 string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return an UTF8 string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerUtf8String.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.DerVisibleString">
+            Der VisibleString object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.GetInstance(System.Object)">
+             return a Visible string from the passed in object.
+            
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             return a Visible string from a tagged object.
+            
+             @param obj the tagged object holding the object we want
+             @param explicitly true if the object is meant to be explicitly
+                          tagged false otherwise.
+             @exception ArgumentException if the tagged object cannot
+                           be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.#ctor(System.Byte[])">
+            basic constructor - byte encoded string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.DerVisibleString.#ctor(System.String)">
+            basic constructor
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CertificateValues">
+            <remarks>
+            RFC 3126: 4.3.1 Certificate Values Attribute Definition
+            <code>
+            CertificateValues ::= SEQUENCE OF Certificate
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeIndication.ToAsn1Object">
+            <pre>
+            CommitmentTypeIndication ::= SEQUENCE {
+                 commitmentTypeId   CommitmentTypeIdentifier,
+                 commitmentTypeQualifier   SEQUENCE SIZE (1..MAX) OF
+                         CommitmentTypeQualifier OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier">
+             Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+            
+             <pre>
+               CommitmentTypeQualifier ::= SEQUENCE {
+                   commitmentTypeIdentifier  CommitmentTypeIdentifier,
+                   qualifier          ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+             @param qualifier the qualifier, defined by the above field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>CommitmentTypeQualifier</code> instance.
+            
+             @param as <code>CommitmentTypeQualifier</code> structure
+             encoded as an Asn1Sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.CommitmentTypeQualifier.ToAsn1Object">
+             Returns a DER-encodable representation of this instance.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CompleteCertificateRefs">
+            <remarks>
+            RFC 3126: 4.2.1 Complete Certificate Refs Attribute Definition
+            <code>
+            CompleteCertificateRefs ::= SEQUENCE OF OtherCertID
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CompleteRevocationRefs">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlIdentifier">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlIdentifier ::= SEQUENCE 
+            {
+            	crlissuer		Name,
+            	crlIssuedTime	UTCTime,
+            	crlNumber		INTEGER OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlListID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CRLListID ::= SEQUENCE 
+            {
+            	crls	SEQUENCE OF CrlValidatedID
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlOcspRef">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlOcspRef ::= SEQUENCE {
+            	crlids		[0] CRLListID		OPTIONAL,
+            	ocspids		[1] OcspListID		OPTIONAL,
+            	otherRev	[2] OtherRevRefs	OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.CrlValidatedID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            CrlValidatedID ::= SEQUENCE {
+            	crlHash			OtherHash,
+            	crlIdentifier	CrlIdentifier OPTIONAL}
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspIdentifier">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspIdentifier ::= SEQUENCE {
+            	ocspResponderID		ResponderID,
+            		-- As in OCSP response data
+            	producedAt			GeneralizedTime
+            		-- As in OCSP response data
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspListID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspListID ::=  SEQUENCE {
+            	ocspResponses	SEQUENCE OF OcspResponsesID
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OcspResponsesID">
+            <remarks>
+            RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+            <code>
+            OcspResponsesID ::= SEQUENCE {
+            	ocspIdentifier	OcspIdentifier,
+            	ocspRepHash		OtherHash OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherCertID">
+            <remarks>
+            <code>
+            OtherCertID ::= SEQUENCE {
+            	otherCertHash	OtherHash,
+            	issuerSerial	IssuerSerial OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherHash">
+            <remarks>
+            <code>
+            OtherHash ::= CHOICE {
+            	sha1Hash	OtherHashValue, -- This contains a SHA-1 hash
+            	otherHash	OtherHashAlgAndValue
+            }
+            
+            OtherHashValue ::= OCTET STRING
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherHashAlgAndValue">
+            <summary>
+            Summary description for OtherHashAlgAndValue.
+            </summary>
+            <remarks>
+            <code>
+            OtherHashAlgAndValue ::= SEQUENCE {
+            	hashAlgorithm	AlgorithmIdentifier,
+            	hashValue		OtherHashValue
+            }
+            
+            OtherHashValue ::= OCTET STRING
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherRevRefs">
+             <remarks>
+             RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+             <code>
+             OtherRevRefs ::= SEQUENCE 
+             {
+            		otherRevRefType      OtherRevRefType,
+            		otherRevRefs         ANY DEFINED BY otherRevRefType
+             }
+            
+             OtherRevRefType ::= OBJECT IDENTIFIER
+             </code>
+             </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherRevVals">
+             <remarks>
+             RFC 3126: 4.3.2 Revocation Values Attribute Definition
+             <code>
+             OtherRevVals ::= SEQUENCE 
+             {
+            		otherRevValType      OtherRevValType,
+            		otherRevVals         ANY DEFINED BY otherRevValType
+             }
+            
+             OtherRevValType ::= OBJECT IDENTIFIER
+             </code>
+             </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.OtherSigningCertificate">
+            <remarks>
+            <code>
+            OtherSigningCertificate ::= SEQUENCE {
+            	certs		SEQUENCE OF OtherCertID,
+            	policies	SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.RevocationValues">
+            <remarks>
+            RFC 5126: 6.3.4.  revocation-values Attribute Definition
+            <code>
+            RevocationValues ::=  SEQUENCE {
+            	crlVals			[0] SEQUENCE OF CertificateList     OPTIONAL,
+            	ocspVals		[1] SEQUENCE OF BasicOCSPResponse   OPTIONAL,
+            	otherRevVals	[2] OtherRevVals OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignaturePolicyId">
+            <remarks>
+            <code>
+            SignaturePolicyId ::= SEQUENCE {
+            	sigPolicyIdentifier		SigPolicyId,
+            	sigPolicyHash			SigPolicyHash,
+            	sigPolicyQualifiers		SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL
+            }
+            
+            SigPolicyId ::= OBJECT IDENTIFIER
+            
+            SigPolicyHash ::= OtherHashAlgAndValue
+            </code>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignaturePolicyIdentifier">
+            <remarks>
+            <code>
+            SignaturePolicyIdentifier ::= CHOICE {
+            	SignaturePolicyId		SignaturePolicyId,
+            	SignaturePolicyImplied	SignaturePolicyImplied
+            }
+            
+            SignaturePolicyImplied ::= NULL
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.SignerAttribute.ToAsn1Object">
+            
+             <pre>
+              SignerAttribute ::= SEQUENCE OF CHOICE {
+                  claimedAttributes   [0] ClaimedAttributes,
+                  certifiedAttributes [1] CertifiedAttributes }
+            
+              ClaimedAttributes ::= SEQUENCE OF Attribute
+              CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SignerLocation">
+             Signer-Location attribute (RFC3126).
+            
+             <pre>
+               SignerLocation ::= SEQUENCE {
+                   countryName        [0] DirectoryString OPTIONAL,
+                   localityName       [1] DirectoryString OPTIONAL,
+                   postalAddress      [2] PostalAddress OPTIONAL }
+            
+               PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Esf.SignerLocation.ToAsn1Object">
+             <pre>
+               SignerLocation ::= SEQUENCE {
+                   countryName        [0] DirectoryString OPTIONAL,
+                   localityName       [1] DirectoryString OPTIONAL,
+                   postalAddress      [2] PostalAddress OPTIONAL }
+            
+               PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+            
+               DirectoryString ::= CHOICE {
+                     teletexString           TeletexString (SIZE (1..MAX)),
+                     printableString         PrintableString (SIZE (1..MAX)),
+                     universalString         UniversalString (SIZE (1..MAX)),
+                     utf8String              UTF8String (SIZE (1.. MAX)),
+                     bmpString               BMPString (SIZE (1..MAX)) }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Esf.SigPolicyQualifierInfo">
+            <remarks>
+            <code>
+            SigPolicyQualifierInfo ::= SEQUENCE {
+            	sigPolicyQualifierId  SigPolicyQualifierId,
+            	sigQualifier          ANY DEFINED BY sigPolicyQualifierId
+            }
+            
+            SigPolicyQualifierId ::= OBJECT IDENTIFIER
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentHints.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentHints.ToAsn1Object">
+            <pre>
+            ContentHints ::= SEQUENCE {
+              contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+              contentType ContentType }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+            Create from OCTET STRING whose octets represent the identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.#ctor(System.Byte[])">
+            Create from byte array representing the identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.ContentIdentifier.ToAsn1Object">
+            The definition of ContentIdentifier is
+            <pre>
+            ContentIdentifier ::=  OCTET STRING
+            </pre>
+            id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 7 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertID.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertID.ToAsn1Object">
+            <pre>
+            EssCertID ::= SEQUENCE {
+                certHash Hash,
+                issuerSerial IssuerSerial OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.EssCertIDv2.ToAsn1Object">
+             <pre>
+             EssCertIDv2 ::=  SEQUENCE {
+                 hashAlgorithm     AlgorithmIdentifier
+                          DEFAULT {algorithm id-sha256},
+                 certHash          Hash,
+                 issuerSerial      IssuerSerial OPTIONAL
+             }
+            
+             Hash ::= OCTET STRING
+            
+             IssuerSerial ::= SEQUENCE {
+                 issuer         GeneralNames,
+                 serialNumber   CertificateSerialNumber
+             }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherCertID.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherCertID.ToAsn1Object">
+             <pre>
+             OtherCertID ::= SEQUENCE {
+                 otherCertHash    OtherHash,
+                 issuerSerial     IssuerSerial OPTIONAL }
+            
+             OtherHash ::= CHOICE {
+                 sha1Hash     OCTET STRING,
+                 otherHash    OtherHashAlgAndValue }
+            
+             OtherHashAlgAndValue ::= SEQUENCE {
+                 hashAlgorithm    AlgorithmIdentifier,
+                 hashValue        OCTET STRING }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherSigningCertificate.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructors
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.OtherSigningCertificate.ToAsn1Object">
+            The definition of OtherSigningCertificate is
+            <pre>
+            OtherSigningCertificate ::=  SEQUENCE {
+                 certs        SEQUENCE OF OtherCertID,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 19 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificate.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            constructors
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificate.ToAsn1Object">
+            The definition of SigningCertificate is
+            <pre>
+            SigningCertificate ::=  SEQUENCE {
+                 certs        SEQUENCE OF EssCertID,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+             member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+             smime(16) id-aa(2) 12 }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ess.SigningCertificateV2.ToAsn1Object">
+            The definition of SigningCertificateV2 is
+            <pre>
+            SigningCertificateV2 ::=  SEQUENCE {
+                 certs        SEQUENCE OF EssCertIDv2,
+                 policies     SEQUENCE OF PolicyInformation OPTIONAL
+            }
+            </pre>
+            id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+               member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+               smime(16) id-aa(2) 47 }
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.CscaMasterList">
+             The CscaMasterList object. This object can be wrapped in a
+             CMSSignedData to be published in LDAP.
+            
+             <pre>
+             CscaMasterList ::= SEQUENCE {
+               version                CscaMasterListVersion,
+               certList               SET OF Certificate }
+               
+             CscaMasterListVersion :: INTEGER {v0(0)}
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.DataGroupHash">
+             The DataGroupHash object.
+             <pre>
+             DataGroupHash  ::=  SEQUENCE {
+                  dataGroupNumber         DataGroupNumber,
+                  dataGroupHashValue     OCTET STRING }
+            
+             DataGroupNumber ::= INTEGER {
+                     dataGroup1    (1),
+                     dataGroup1    (2),
+                     dataGroup1    (3),
+                     dataGroup1    (4),
+                     dataGroup1    (5),
+                     dataGroup1    (6),
+                     dataGroup1    (7),
+                     dataGroup1    (8),
+                     dataGroup1    (9),
+                     dataGroup1    (10),
+                     dataGroup1    (11),
+                     dataGroup1    (12),
+                     dataGroup1    (13),
+                     dataGroup1    (14),
+                     dataGroup1    (15),
+                     dataGroup1    (16) }
+            
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Icao.LdsSecurityObject">
+             The LDSSecurityObject object (V1.8).
+             <pre>
+             LDSSecurityObject ::= SEQUENCE {
+               version                LDSSecurityObjectVersion,
+               hashAlgorithm          DigestAlgorithmIdentifier,
+               dataGroupHashValues    SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+               ldsVersionInfo         LDSVersionInfo OPTIONAL
+                 -- if present, version MUST be v1 }
+            
+             DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+            
+             LDSSecurityObjectVersion :: INTEGER {V0(0)}
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Icao.LdsVersionInfo.ToAsn1Object">
+            <pre>
+            LDSVersionInfo ::= SEQUENCE {
+               ldsVersion PRINTABLE STRING
+               unicodeVersion PRINTABLE STRING
+             }
+            </pre>
+            @return
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttCPAccredited">
+            The id-isismtt-cp-accredited OID indicates that the certificate is a
+            qualified certificate according to Directive 1999/93/EC of the European
+            Parliament and of the Council of 13 December 1999 on a Community
+            Framework for Electronic Signatures, which additionally conforms the
+            special requirements of the SigG and has been issued by an accredited CA.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen">
+             Certificate extensionDate of certificate generation
+             
+             <pre>
+            		DateOfCertGenSyntax ::= GeneralizedTime
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATProcuration">
+            Attribute to indicate that the certificate holder may sign in the name of
+            a third person. May also be used as extension in a certificate.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATAdmission">
+            Attribute to indicate admissions to certain professions. May be used as
+            attribute in attribute certificate or as extension in a certificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATMonetaryLimit">
+            Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+            be used in new certificates in place of the extension/attribute
+            MonetaryLimit since January 1, 2004. For the sake of backward
+            compatibility with certificates already in use, SigG conforming
+            components MUST support MonetaryLimit (as well as QcEuLimitValue).
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATDeclarationOfMajority">
+            A declaration of majority. May be used as attribute in attribute
+            certificate or as extension in a certificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATIccsn">
+             
+             Serial number of the smart card containing the corresponding private key
+             
+             <pre>
+            		ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATPKReference">
+             
+             Reference for a file of a smartcard that stores the public key of this
+             certificate and that is used as �security anchor�.
+             
+             <pre>
+            		PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRestriction">
+             Some other restriction regarding the usage of this certificate. May be
+             used as attribute in attribute certificate or as extension in a
+             certificate.
+             
+             <pre>
+            		RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             </pre>
+             
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRetrieveIfAllowed">
+             
+             (Single)Request extension: Clients may include this extension in a
+             (single) Request to request the responder to send the certificate in the
+             response message along with the status information. Besides the LDAP
+             service, this extension provides another mechanism for the distribution
+             of certificates, which MAY optionally be provided by certificate
+             repositories.
+             
+             <pre>
+            		RetrieveIfAllowed ::= BOOLEAN
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATRequestedCertificate">
+            SingleOCSPResponse extension: The certificate requested by the client by
+            inserting the RetrieveIfAllowed extension in the request, will be
+            returned in this extension.
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATNamingAuthorities">
+            Base ObjectIdentifier for naming authorities
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATCertInDirSince">
+             SingleOCSPResponse extension: Date, when certificate has been published
+             in the directory and status information has become available. Currently,
+             accrediting authorities enforce that SigG-conforming OCSP servers include
+             this extension in the responses.
+             
+             <pre>
+            		CertInDirSince ::= GeneralizedTime
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATCertHash">
+             Hash of a certificate in OCSP.
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATNameAtBirth">
+             <pre>
+            		NameAtBirth ::= DirectoryString(SIZE(1..64)
+             </pre>
+             
+             Used in
+             {@link Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATAdditionalInformation">
+            Some other information of non-restrictive nature regarding the usage of
+            this certificate. May be used as attribute in atribute certificate or as
+            extension in a certificate.
+            
+            <pre>
+                          AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+            </pre>
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.IsisMttObjectIdentifiers.IdIsisMttATLiabilityLimitationFlag">
+             Indicates that an attribute certificate exists, which limits the
+             usability of this public key certificate. Whenever verifying a signature
+             with the help of this certificate, the content of the corresponding
+             attribute certificate should be concerned. This extension MUST be
+             included in a PKC, if a corresponding attribute certificate (having the
+             PKC as base certificate) contains some attribute that restricts the
+             usability of the PKC too. Attribute certificates with restricting content
+             MUST always be included in the signed document.
+             
+             <pre>
+            		LiabilityLimitationFlagSyntax ::= BOOLEAN
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash">
+            ISIS-MTT PROFILE: The responder may include this extension in a response to
+            send the hash of the requested certificate to the responder. This hash is
+            cryptographically bound to the certificate and serves as evidence that the
+            certificate is known to the responder (i.e. it has been issued and is present
+            in the directory). Hence, this extension is a means to provide a positive
+            statement of availability as described in T8.[8]. As explained in T13.[1],
+            clients may rely on this information to be able to validate signatures after
+            the expiry of the corresponding certificate. Hence, clients MUST support this
+            extension. If a positive statement of availability is to be delivered, this
+            extension syntax and OID MUST be used.
+            <p/>
+            <p/>
+            <pre>
+                CertHash ::= SEQUENCE {
+                  hashAlgorithm AlgorithmIdentifier,
+                  certificateHash OCTET STRING
+                }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type CertHash:
+             <p/>
+             <pre>
+                 CertHash ::= SEQUENCE {
+                   hashAlgorithm AlgorithmIdentifier,
+                   certificateHash OCTET STRING
+                 }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.#ctor(Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,System.Byte[])">
+             Constructor from a given details.
+            
+             @param hashAlgorithm   The hash algorithm identifier.
+             @param certificateHash The hash of the whole DER encoding of the certificate.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 CertHash ::= SEQUENCE {
+                   hashAlgorithm AlgorithmIdentifier,
+                   certificateHash OCTET STRING
+                 }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate">
+            ISIS-MTT-Optional: The certificate requested by the client by inserting the
+            RetrieveIfAllowed extension in the request, will be returned in this
+            extension.
+            <p/>
+            ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+            when the certificate owner gives his isExplicit permission. Accordingly, there
+            may be �nondownloadable� certificates, about which the responder must provide
+            status information, but MUST NOT include them in the response. Clients may
+            get therefore the following three kind of answers on a single request
+            including the RetrieveIfAllowed extension:
+            <ul>
+            <li> a) the responder supports the extension and is allowed to publish the
+            certificate: RequestedCertificate returned including the requested
+            certificate</li>
+            <li>b) the responder supports the extension but is NOT allowed to publish
+            the certificate: RequestedCertificate returned including an empty OCTET
+            STRING</li>
+            <li>c) the responder does not support the extension: RequestedCertificate is
+            not included in the response</li>
+            </ul>
+            Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+            any of the OCTET STRING options is used, it MUST contain the DER encoding of
+            the requested certificate.
+            <p/>
+            <pre>
+                       RequestedCertificate ::= CHOICE {
+                         Certificate Certificate,
+                         publicKeyCertificate [0] EXPLICIT OCTET STRING,
+                         attributeCertificate [1] EXPLICIT OCTET STRING
+                       }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate.#ctor(Org.BouncyCastle.Asn1.X509.X509CertificateStructure)">
+             Constructor from a given details.
+             <p/>
+             Only one parameter can be given. All other must be <code>null</code>.
+            
+             @param certificate Given as Certificate
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                        RequestedCertificate ::= CHOICE {
+                          Certificate Certificate,
+                          publicKeyCertificate [0] EXPLICIT OCTET STRING,
+                          attributeCertificate [1] EXPLICIT OCTET STRING
+                        }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax">
+            Some other information of non-restrictive nature regarding the usage of this
+            certificate.
+            
+            <pre>
+               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param information The describtion of the information.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions">
+             An Admissions structure.
+             <p/>
+             <pre>
+                        Admissions ::= SEQUENCE
+                        {
+                          admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                          namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                          professionInfos SEQUENCE OF ProfessionInfo
+                        }
+             <p/>
+             </pre>
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                        Admissions ::= SEQUENCE
+                        {
+                          admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                          namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                          professionInfos SEQUENCE OF ProfessionInfo
+                        }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority,Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo[])">
+             Constructor from a given details.
+             <p/>
+             Parameter <code>professionInfos</code> is mandatory.
+            
+             @param admissionAuthority The admission authority.
+             @param namingAuthority    The naming authority.
+             @param professionInfos    The profession infos.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   Admissions ::= SEQUENCE
+                   {
+                     admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                     namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                     professionInfos SEQUENCE OF ProfessionInfo
+                   }
+             <p/>
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax">
+             Attribute to indicate admissions to certain professions.
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+             <p/>
+             <p/>
+             ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
+             supports the following concepts and requirements:
+             <ul>
+             <li> External institutions (e.g. professional associations, chambers, unions,
+             administrative bodies, companies, etc.), which are responsible for granting
+             and verifying professional admissions, are indicated by means of the data
+             field admissionAuthority. An admission authority is indicated by a
+             GeneralName object. Here an X.501 directory name (distinguished name) can be
+             indicated in the field directoryName, a URL address can be indicated in the
+             field uniformResourceIdentifier, and an object identifier can be indicated in
+             the field registeredId.</li>
+             <li> The names of authorities which are responsible for the administration of
+             title registers are indicated in the data field namingAuthority. The name of
+             the authority can be identified by an object identifier in the field
+             namingAuthorityId, by means of a text string in the field
+             namingAuthorityText, by means of a URL address in the field
+             namingAuthorityUrl, or by a combination of them. For example, the text string
+             can contain the name of the authority, the country and the name of the title
+             register. The URL-option refers to a web page which contains lists with
+             �officially� registered professions (text and possibly OID) as well as
+             further information on these professions. Object identifiers for the
+             component namingAuthorityId are grouped under the OID-branch
+             id-isis-at-namingAuthorities and must be applied for.</li>
+             <li>See http://www.teletrust.de/anwend.asp?Id=30200&Sprache=E_&HomePG=0
+             for an application form and http://www.teletrust.de/links.asp?id=30220,11
+             for an overview of registered naming authorities.</li>
+             <li> By means of the data type ProfessionInfo certain professions,
+             specializations, disciplines, fields of activity, etc. are identified. A
+             profession is represented by one or more text strings, resp. profession OIDs
+             in the fields professionItems and professionOIDs and by a registration number
+             in the field registrationNumber. An indication in text form must always be
+             present, whereas the other indications are optional. The component
+             addProfessionInfo may contain additional applicationspecific information in
+             DER-encoded form.</li>
+             </ul>
+             <p/>
+             By means of different namingAuthority-OIDs or profession OIDs hierarchies of
+             professions, specializations, disciplines, fields of activity, etc. can be
+             expressed. The issuing admission authority should always be indicated (field
+             admissionAuthority), whenever a registration number is presented. Still,
+             information on admissions can be given without indicating an admission or a
+             naming authority by the exclusive use of the component professionItems. In
+             this case the certification authority is responsible for the verification of
+             the admission information.
+             <p/>
+             <p/>
+             <p/>
+             This attribute is single-valued. Still, several admissions can be captured in
+             the sequence structure of the component contentsOfAdmissions of
+             AdmissionSyntax or in the component professionInfos of Admissions. The
+             component admissionAuthority of AdmissionSyntax serves as default value for
+             the component admissionAuthority of Admissions. Within the latter component
+             the default value can be overwritten, in case that another authority is
+             responsible. The component namingAuthority of Admissions serves as a default
+             value for the component namingAuthority of ProfessionInfo. Within the latter
+             component the default value can be overwritten, in case that another naming
+             authority needs to be recorded.
+             <p/>
+             The length of the string objects is limited to 128 characters. It is
+             recommended to indicate a namingAuthorityURL in all issued attribute
+             certificates. If a namingAuthorityURL is indicated, the field professionItems
+             of ProfessionInfo should contain only registered titles. If the field
+             professionOIDs exists, it has to contain the OIDs of the professions listed
+             in professionItems in the same order. In general, the field professionInfos
+             should contain only one entry, unless the admissions that are to be listed
+             are logically connected (e.g. they have been issued under the same admission
+             number).
+            
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+             @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from given details.
+            
+             @param admissionAuthority   The admission authority.
+             @param contentsOfAdmissions The admissions.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 AdmissionSyntax ::= SEQUENCE
+                 {
+                   admissionAuthority GeneralName OPTIONAL,
+                   contentsOfAdmissions SEQUENCE OF Admissions
+                 }
+             <p/>
+                 Admissions ::= SEQUENCE
+                 {
+                   admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+                   namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+                   professionInfos SEQUENCE OF ProfessionInfo
+                 }
+             <p/>
+                 NamingAuthority ::= SEQUENCE
+                 {
+                   namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+                   namingAuthorityUrl IA5String OPTIONAL,
+                   namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                 }
+             <p/>
+                 ProfessionInfo ::= SEQUENCE
+                 {
+                   namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                   professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                   professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                   registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                   addProfessionInfo OCTET STRING OPTIONAL
+                 }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.GetContentsOfAdmissions">
+            @return Returns the contentsOfAdmissions.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax.AdmissionAuthority">
+            @return Returns the admissionAuthority if present, null otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority">
+            A declaration of majority.
+            <p/>
+            <pre>
+                      DeclarationOfMajoritySyntax ::= CHOICE
+                      {
+                        notYoungerThan [0] IMPLICIT INTEGER,
+                        fullAgeAtCountry [1] IMPLICIT SEQUENCE
+                        {
+                          fullAge BOOLEAN DEFAULT TRUE,
+                          country PrintableString (SIZE(2))
+                        }
+                        dateOfBirth [2] IMPLICIT GeneralizedTime
+                      }
+            </pre>
+            <p/>
+            fullAgeAtCountry indicates the majority of the owner with respect to the laws
+            of a specific country.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                       DeclarationOfMajoritySyntax ::= CHOICE
+                       {
+                         notYoungerThan [0] IMPLICIT INTEGER,
+                         fullAgeAtCountry [1] IMPLICIT SEQUENCE
+                         {
+                           fullAge BOOLEAN DEFAULT TRUE,
+                           country PrintableString (SIZE(2))
+                         }
+                         dateOfBirth [2] IMPLICIT GeneralizedTime
+                       }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.DeclarationOfMajority.NotYoungerThan">
+            @return notYoungerThan if that's what we are, -1 otherwise
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit">
+            Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+            used in new certificates in place of the extension/attribute MonetaryLimit
+            since January 1, 2004. For the sake of backward compatibility with
+            certificates already in use, components SHOULD support MonetaryLimit (as well
+            as QcEuLimitValue).
+            <p/>
+            Indicates a monetary limit within which the certificate holder is authorized
+            to act. (This value DOES NOT express a limit on the liability of the
+            certification authority).
+            <p/>
+            <pre>
+               MonetaryLimitSyntax ::= SEQUENCE
+               {
+                 currency PrintableString (SIZE(3)),
+                 amount INTEGER,
+                 exponent INTEGER
+               }
+            </pre>
+            <p/>
+            currency must be the ISO code.
+            <p/>
+            value = amount�10*exponent
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit.#ctor(System.String,System.Int32,System.Int32)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             value = amount�10^exponent
+            
+             @param currency The currency. Must be the ISO code.
+             @param amount   The amount
+             @param exponent The exponent
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.MonetaryLimit.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                MonetaryLimitSyntax ::= SEQUENCE
+                {
+                  currency PrintableString (SIZE(3)),
+                  amount INTEGER,
+                  exponent INTEGER
+                }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority">
+            Names of authorities which are responsible for the administration of title
+            registers.
+            
+            <pre>
+                        NamingAuthority ::= SEQUENCE 
+                        {
+                          namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                          namingAuthorityUrl IA5String OPTIONAL,
+                          namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                        }
+            </pre>
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern">
+            Profession OIDs should always be defined under the OID branch of the
+            responsible naming authority. At the time of this writing, the work group
+            �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+            first naming authority under the OID id-isismtt-at-namingAuthorities.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             <p/>
+             <pre>
+                         NamingAuthority ::= SEQUENCE
+                         {
+                           namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                           namingAuthorityUrl IA5String OPTIONAL,
+                           namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                         }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String,Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from given details.
+             <p/>
+             All parameters can be combined.
+            
+             @param namingAuthorityID   ObjectIdentifier for naming authority.
+             @param namingAuthorityUrl  URL for naming authority.
+             @param namingAuthorityText Textual representation of naming authority.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                         NamingAuthority ::= SEQUENCE
+                         {
+                           namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+                           namingAuthorityUrl IA5String OPTIONAL,
+                           namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+                         }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityID">
+            @return Returns the namingAuthorityID.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityText">
+            @return Returns the namingAuthorityText.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority.NamingAuthorityUrl">
+            @return Returns the namingAuthorityUrl.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax">
+            Attribute to indicate that the certificate holder may sign in the name of a
+            third person.
+            <p>
+            ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+            name of the person who is represented (subcomponent thirdPerson) or a
+            reference to his/her base certificate (in the component signingFor,
+            subcomponent certRef), furthermore the optional components country and
+            typeSubstitution to indicate the country whose laws apply, and respectively
+            the type of procuration (e.g. manager, procuration, custody).
+            </p>
+            <p>
+            ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+            contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+            surname, givenName, serialNumber, organizationName, organizationalUnitName,
+            stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+            attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+            countryOfResidence and NameAtBirth).
+            </p>
+            <pre>
+                          ProcurationSyntax ::= SEQUENCE {
+                            country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                            typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                            signingFor [3] EXPLICIT SigningFor 
+                          }
+                          
+                          SigningFor ::= CHOICE 
+                          { 
+                            thirdPerson GeneralName,
+                            certRef IssuerSerial 
+                          }
+            </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type ProcurationSyntax:
+             <p/>
+             <pre>
+                           ProcurationSyntax ::= SEQUENCE {
+                             country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                             typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                             signingFor [3] EXPLICIT SigningFor
+                           }
+             <p/>
+                           SigningFor ::= CHOICE
+                           {
+                             thirdPerson GeneralName,
+                             certRef IssuerSerial
+                           }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(System.String,Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.X509.IssuerSerial)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             Either <code>generalName</code> or <code>certRef</code> MUST be
+             <code>null</code>.
+            
+             @param country            The country code whose laws apply.
+             @param typeOfSubstitution The type of procuration.
+             @param certRef            Reference to certificate of the person who is represented.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.#ctor(System.String,Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Constructor from a given details.
+             <p/>
+             <p/>
+             Either <code>generalName</code> or <code>certRef</code> MUST be
+             <code>null</code>.
+            
+             @param country            The country code whose laws apply.
+             @param typeOfSubstitution The type of procuration.
+             @param thirdPerson        The GeneralName of the person who is represented.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProcurationSyntax.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                           ProcurationSyntax ::= SEQUENCE {
+                             country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+                             typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+                             signingFor [3] EXPLICIT SigningFor
+                           }
+             <p/>
+                           SigningFor ::= CHOICE
+                           {
+                             thirdPerson GeneralName,
+                             certRef IssuerSerial
+                           }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo">
+            Professions, specializations, disciplines, fields of activity, etc.
+            
+            <pre>
+                          ProfessionInfo ::= SEQUENCE 
+                          {
+                            namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                            professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                            professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                            registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                            addProfessionInfo OCTET STRING OPTIONAL 
+                          }
+            </pre>
+            
+            @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsanwltin">
+            Rechtsanw�ltin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsanwalt">
+            Rechtsanwalt
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Rechtsbeistand">
+            Rechtsbeistand
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerberaterin">
+            Steuerberaterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerberater">
+            Steuerberater
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerbevollmchtigte">
+            Steuerbevollm�chtigte
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Steuerbevollmchtigter">
+            Steuerbevollm�chtigter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarin">
+            Notarin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notar">
+            Notar
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarvertreterin">
+            Notarvertreterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notarvertreter">
+            Notarvertreter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notariatsverwalterin">
+            Notariatsverwalterin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Notariatsverwalter">
+            Notariatsverwalter
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Wirtschaftsprferin">
+            Wirtschaftspr�ferin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Wirtschaftsprfer">
+            Wirtschaftspr�fer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.VereidigteBuchprferin">
+            Vereidigte Buchpr�ferin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.VereidigterBuchprfer">
+            Vereidigter Buchpr�fer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Patentanwltin">
+            Patentanw�ltin
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.Patentanwalt">
+            Patentanwalt
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             <p/>
+             <pre>
+                           ProfessionInfo ::= SEQUENCE
+                           {
+                             namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                             professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                             professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                             registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                             addProfessionInfo OCTET STRING OPTIONAL
+                           }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.#ctor(Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority,Org.BouncyCastle.Asn1.X500.DirectoryString[],Org.BouncyCastle.Asn1.DerObjectIdentifier[],System.String,Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor from given details.
+             <p/>
+             <code>professionItems</code> is mandatory, all other parameters are
+             optional.
+            
+             @param namingAuthority    The naming authority.
+             @param professionItems    Directory strings of the profession.
+             @param professionOids     DERObjectIdentfier objects for the
+                                       profession.
+             @param registrationNumber Registration number.
+             @param addProfessionInfo  Additional infos in encoded form.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                           ProfessionInfo ::= SEQUENCE
+                           {
+                             namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+                             professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+                             professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+                             registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+                             addProfessionInfo OCTET STRING OPTIONAL
+                           }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.GetProfessionItems">
+            @return Returns the professionItems.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.GetProfessionOids">
+            @return Returns the professionOids.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.AddProfessionInfo">
+            @return Returns the addProfessionInfo.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.NamingAuthority">
+            @return Returns the namingAuthority.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo.RegistrationNumber">
+            @return Returns the registrationNumber.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction">
+            Some other restriction regarding the usage of this certificate.
+            <p/>
+            <pre>
+             RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from DirectoryString.
+             <p/>
+             The DirectoryString is of type RestrictionSyntax:
+             <p/>
+             <pre>
+                  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             </pre>
+            
+             @param restriction A IAsn1String.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param restriction The description of the restriction.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+             <p/>
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.Cast5CbcParameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            cast5CBCParameters ::= Sequence {
+                                      iv         OCTET STRING DEFAULT 0,
+                                             -- Initialization vector
+                                      keyLength  Integer
+                                             -- Key length, in bits
+                                 }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.IdeaCbcPar.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            IDEA-CBCPar ::= Sequence {
+                                 iv    OCTET STRING OPTIONAL -- exactly 8 octets
+                             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Misc.NetscapeCertType">
+            The NetscapeCertType object.
+            <pre>
+               NetscapeCertType ::= BIT STRING {
+                    SSLClient               (0),
+                    SSLServer               (1),
+                    S/MIME                  (2),
+                    Object Signing          (3),
+                    Reserved                (4),
+                    SSL CA                  (5),
+                    S/MIME CA               (6),
+                    Object Signing CA       (7) }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Misc.NetscapeCertType.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Mozilla.PublicKeyAndChallenge">
+             This is designed to parse
+             the PublicKeyAndChallenge created by the KEYGEN tag included by
+             Mozilla based browsers.
+              <pre>
+              PublicKeyAndChallenge ::= SEQUENCE {
+                spki SubjectPublicKeyInfo,
+                challenge IA5STRING
+              }
+            
+              </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Nist.NistNamedCurves">
+            Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-2
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Nist.NistNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Ntt.NttObjectIdentifiers">
+            <summary>From RFC 3657</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.BasicOcspResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            BasicOcspResponse       ::= Sequence {
+                 tbsResponseData      ResponseData,
+                 signatureAlgorithm   AlgorithmIdentifier,
+                 signature            BIT STRING,
+                 certs                [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CertID          ::=     Sequence {
+                hashAlgorithm       AlgorithmIdentifier,
+                issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+                issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+                serialNumber        CertificateSerialNumber }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertStatus.#ctor">
+            create a CertStatus object with a tag of zero.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CertStatus.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             CertStatus ::= CHOICE {
+                             good        [0]     IMPLICIT Null,
+                             revoked     [1]     IMPLICIT RevokedInfo,
+                             unknown     [2]     IMPLICIT UnknownInfo }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.CrlID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CrlID ::= Sequence {
+                crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+                crlNum               [1]     EXPLICIT Integer OPTIONAL,
+                crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspRequest.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OcspRequest     ::=     Sequence {
+                tbsRequest                  TBSRequest,
+                optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            OcspResponse ::= Sequence {
+                responseStatus         OcspResponseStatus,
+                responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.OcspResponseStatus.#ctor(System.Int32)">
+            The OcspResponseStatus enumeration.
+            <pre>
+            OcspResponseStatus ::= Enumerated {
+                successful            (0),  --Response has valid confirmations
+                malformedRequest      (1),  --Illegal confirmation request
+                internalError         (2),  --Internal error in issuer
+                tryLater              (3),  --Try again later
+                                            --(4) is not used
+                sigRequired           (5),  --Must sign the request
+                unauthorized          (6)   --Request unauthorized
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.Request.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Request         ::=     Sequence {
+                reqCert                     CertID,
+                singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponderID.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponderID ::= CHOICE {
+                 byName          [1] Name,
+                 byKey           [2] KeyHash }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponseBytes.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponseBytes ::=       Sequence {
+                responseType   OBJECT IDENTIFIER,
+                response       OCTET STRING }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ResponseData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ResponseData ::= Sequence {
+                version              [0] EXPLICIT Version DEFAULT v1,
+                responderID              ResponderID,
+                producedAt               GeneralizedTime,
+                responses                Sequence OF SingleResponse,
+                responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.RevokedInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            RevokedInfo ::= Sequence {
+                 revocationTime              GeneralizedTime,
+                 revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.ServiceLocator.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ServiceLocator ::= Sequence {
+                issuer    Name,
+                locator   AuthorityInfoAccessSyntax OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.Signature.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Signature       ::=     Sequence {
+                signatureAlgorithm      AlgorithmIdentifier,
+                signature               BIT STRING,
+                certs               [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.SingleResponse.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             SingleResponse ::= Sequence {
+                     certID                       CertID,
+                     certStatus                   CertStatus,
+                     thisUpdate                   GeneralizedTime,
+                     nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
+                     singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Ocsp.TbsRequest.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            TBSRequest      ::=     Sequence {
+                version             [0]     EXPLICIT Version DEFAULT v1,
+                requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+                requestList                 Sequence OF Request,
+                requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.OidTokenizer">
+            class for breaking up an Oid into it's component tokens, ala
+            java.util.StringTokenizer. We need this class as some of the
+            lightweight Java environment don't support classes like
+            StringTokenizer.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.AttributePkcs.GetInstance(System.Object)">
+             return an Attribute object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.AttributePkcs.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attr ::= Sequence {
+                attrType OBJECT IDENTIFIER,
+                attrValues Set OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.CertificationRequest">
+            Pkcs10 Certfication request object.
+            <pre>
+            CertificationRequest ::= Sequence {
+              certificationRequestInfo  CertificationRequestInfo,
+              signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+              signature                 BIT STRING
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.CertificationRequestInfo">
+             Pkcs10 CertificationRequestInfo object.
+             <pre>
+              CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.ContentInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            ContentInfo ::= Sequence {
+                     contentType ContentType,
+                     content
+                     [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.EncryptedData">
+             The EncryptedData object.
+             <pre>
+                  EncryptedData ::= Sequence {
+                       version Version,
+                       encryptedContentInfo EncryptedContentInfo
+                  }
+            
+            
+                  EncryptedContentInfo ::= Sequence {
+                      contentType ContentType,
+                      contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
+                      encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+                }
+            
+                EncryptedContent ::= OCTET STRING
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.EncryptedPrivateKeyInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+             EncryptedPrivateKeyInfo ::= Sequence {
+                  encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+                  encryptedData EncryptedData
+             }
+            
+             EncryptedData ::= OCTET STRING
+            
+             KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+                      ... -- For local profiles
+             }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+                 AlgorithmIdentifier ::= Sequence {
+                                       algorithm OBJECT IDENTIFIER,
+                                       parameters ANY DEFINED BY algorithm OPTIONAL }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.MacData.ToAsn1Object">
+            <pre>
+            MacData ::= SEQUENCE {
+                mac      DigestInfo,
+                macSalt  OCTET STRING,
+                iterations INTEGER DEFAULT 1
+                -- Note: The default is for historic reasons and its use is deprecated. A
+                -- higher value, like 1024 is recommended.
+            </pre>
+            @return the basic DERObject construction.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.Pfx">
+            the infamous Pfx from Pkcs12
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.PrivateKeyInfo.ToAsn1Object">
+             write out an RSA private key with its associated information
+             as described in Pkcs8.
+             <pre>
+                  PrivateKeyInfo ::= Sequence {
+                                          version Version,
+                                          privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+                                          privateKey PrivateKey,
+                                          attributes [0] IMPLICIT Attributes OPTIONAL
+                                      }
+                  Version ::= Integer {v1(0)} (v1,...)
+            
+                  PrivateKey ::= OCTET STRING
+            
+                  Attributes ::= Set OF Attr
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaesOaepParameters.#ctor">
+            The default version
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaesOaepParameters.ToAsn1Object">
+             <pre>
+              RSAES-OAEP-params ::= SEQUENCE {
+                 hashAlgorithm      [0] OAEP-PSSDigestAlgorithms     DEFAULT sha1,
+                 maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+                 pSourceAlgorithm   [2] PKCS1PSourceAlgorithms  DEFAULT pSpecifiedEmpty
+               }
+            
+               OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-sha1 PARAMETERS NULL   }|
+                 { OID id-sha256 PARAMETERS NULL }|
+                 { OID id-sha384 PARAMETERS NULL }|
+                 { OID id-sha512 PARAMETERS NULL },
+                 ...  -- Allows for future expansion --
+               }
+               PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+                ...  -- Allows for future expansion --
+               }
+               PKCS1PSourceAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                 { OID id-pSpecified PARAMETERS OCTET STRING },
+                 ...  -- Allows for future expansion --
+              }
+             </pre>
+             @return the asn1 primitive representing the parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsaPrivateKeyStructure.ToAsn1Object">
+             This outputs the key in Pkcs1v2 format.
+             <pre>
+                  RsaPrivateKey ::= Sequence {
+                                      version Version,
+                                      modulus Integer, -- n
+                                      publicExponent Integer, -- e
+                                      privateExponent Integer, -- d
+                                      prime1 Integer, -- p
+                                      prime2 Integer, -- q
+                                      exponent1 Integer, -- d mod (p-1)
+                                      exponent2 Integer, -- d mod (q-1)
+                                      coefficient Integer -- (inverse of q) mod p
+                                  }
+            
+                  Version ::= Integer
+             </pre>
+             <p>This routine is written to output Pkcs1 version 0, private keys.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters.#ctor">
+            The default version
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.RsassaPssParameters.ToAsn1Object">
+             <pre>
+             RSASSA-PSS-params ::= SEQUENCE {
+               hashAlgorithm      [0] OAEP-PSSDigestAlgorithms  DEFAULT sha1,
+                maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+                saltLength         [2] INTEGER  DEFAULT 20,
+                trailerField       [3] TrailerField  DEFAULT trailerFieldBC
+              }
+            
+             OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+                { OID id-sha1 PARAMETERS NULL   }|
+                { OID id-sha256 PARAMETERS NULL }|
+                { OID id-sha384 PARAMETERS NULL }|
+                { OID id-sha512 PARAMETERS NULL },
+                ...  -- Allows for future expansion --
+             }
+            
+             PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+               { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+                ...  -- Allows for future expansion --
+             }
+            
+             TrailerField ::= INTEGER { trailerFieldBC(1) }
+             </pre>
+             @return the asn1 primitive representing the parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.SignedData">
+            a Pkcs#7 signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.SignedData.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             SignedData ::= Sequence {
+                 version Version,
+                 digestAlgorithms DigestAlgorithmIdentifiers,
+                 contentInfo ContentInfo,
+                 certificates
+                     [0] IMPLICIT ExtendedCertificatesAndCertificates
+                              OPTIONAL,
+                 crls
+                     [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+                 signerInfos SignerInfos }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Pkcs.SignerInfo">
+            a Pkcs#7 signer info object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Pkcs.SignerInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              SignerInfo ::= Sequence {
+                  version Version,
+                  issuerAndSerialNumber IssuerAndSerialNumber,
+                  digestAlgorithm DigestAlgorithmIdentifier,
+                  authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+                  digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+                  encryptedDigest EncryptedDigest,
+                  unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+              }
+            
+              EncryptedDigest ::= OCTET STRING
+            
+              DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+            
+              DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Sec.ECPrivateKeyStructure">
+            the elliptic curve private key object from SEC 1
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.ECPrivateKeyStructure.ToAsn1Object">
+            ECPrivateKey ::= SEQUENCE {
+                version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+                privateKey OCTET STRING,
+                parameters [0] Parameters OPTIONAL,
+                publicKey [1] BIT STRING OPTIONAL }
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.Sec.SecNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Sec.SecObjectIdentifiers.EllipticCurve">
+            EllipticCurve OBJECT IDENTIFIER ::= {
+                  iso(1) identified-organization(3) certicom(132) curve(0)
+            }
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities">
+            Handler class for dealing with S/MIME Capabilities
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.PreferSignedData">
+            general preferences
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.DesCbc">
+            encryption algorithms preferences
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.GetInstance(System.Object)">
+             return an Attr object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.GetCapabilitiesForOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            returns an ArrayList with 0 or more objects of all the capabilities
+            matching the passed in capability Oid. If the Oid passed is null the
+            entire set is returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapabilities.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SMIMECapabilities ::= Sequence OF SMIMECapability
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeX509.GetInstance(System.Object)">
+             return an Attr object from the given object.
+            
+             @param o the object we want converted.
+             @exception ArgumentException if the object cannot be converted.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeX509.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Attr ::= Sequence {
+                attrType OBJECT IDENTIFIER,
+                attrValues Set OF AttributeValue
+            }
+            </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapability.PreferSignedData">
+            general preferences
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.Smime.SmimeCapability.DesCbc">
+            encryption algorithms preferences
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeCapability.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SMIMECapability ::= Sequence {
+                capabilityID OBJECT IDENTIFIER,
+                parameters ANY DEFINED BY capabilityID OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeCapabilityVector">
+            Handler for creating a vector S/MIME Capabilities
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.Smime.SmimeEncryptionKeyPreferenceAttribute">
+            The SmimeEncryptionKeyPreference object.
+            <pre>
+            SmimeEncryptionKeyPreference ::= CHOICE {
+                issuerAndSerialNumber   [0] IssuerAndSerialNumber,
+                receipentKeyId          [1] RecipientKeyIdentifier,
+                subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Smime.SmimeEncryptionKeyPreferenceAttribute.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+            @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves">
+            elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+            http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.TeleTrust.TeleTrusTNamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.Accuracy.ToAsn1Object">
+            <pre>
+            Accuracy ::= SEQUENCE {
+                        seconds        INTEGER              OPTIONAL,
+                        millis     [0] INTEGER  (1..999)    OPTIONAL,
+                        micros     [1] INTEGER  (1..999)    OPTIONAL
+                        }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.MessageImprint.GetInstance(System.Object)">
+            @param o
+            @return a MessageImprint object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.MessageImprint.ToAsn1Object">
+            <pre>
+               MessageImprint ::= SEQUENCE  {
+                  hashAlgorithm                AlgorithmIdentifier,
+                  hashedMessage                OCTET STRING  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TimeStampReq.ToAsn1Object">
+            <pre>
+            TimeStampReq ::= SEQUENCE  {
+             version                      INTEGER  { v1(1) },
+             messageImprint               MessageImprint,
+               --a hash algorithm OID and the hash value of the data to be
+               --time-stamped
+             reqPolicy             TSAPolicyId              OPTIONAL,
+             nonce                 INTEGER                  OPTIONAL,
+             certReq               BOOLEAN                  DEFAULT FALSE,
+             extensions            [0] IMPLICIT Extensions  OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TimeStampResp.ToAsn1Object">
+            <pre>
+            TimeStampResp ::= SEQUENCE  {
+              status                  PkiStatusInfo,
+              timeStampToken          TimeStampToken     OPTIONAL  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Tsp.TstInfo.ToAsn1Object">
+             <pre>
+            
+                 TstInfo ::= SEQUENCE  {
+                    version                      INTEGER  { v1(1) },
+                    policy                       TSAPolicyId,
+                    messageImprint               MessageImprint,
+                      -- MUST have the same value as the similar field in
+                      -- TimeStampReq
+                    serialNumber                 INTEGER,
+                     -- Time-Stamping users MUST be ready to accommodate integers
+                     -- up to 160 bits.
+                    genTime                      GeneralizedTime,
+                    accuracy                     Accuracy                 OPTIONAL,
+                    ordering                     BOOLEAN             DEFAULT FALSE,
+                    nonce                        INTEGER                  OPTIONAL,
+                      -- MUST be present if the similar field was present
+                      -- in TimeStampReq.  In that case it MUST have the same value.
+                    tsa                          [0] GeneralName          OPTIONAL,
+                    extensions                   [1] IMPLICIT Extensions   OPTIONAL  }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.AsString(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Object,System.Text.StringBuilder)">
+             dump a Der object as a formatted string with indentation
+            
+             @param obj the Asn1Object to be dumped out.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.DumpAsString(Org.BouncyCastle.Asn1.Asn1Encodable)">
+             dump out a DER object as a formatted string, in non-verbose mode
+            
+             @param obj the Asn1Encodable to be dumped out.
+             @return  the resulting string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.Utilities.Asn1Dump.DumpAsString(Org.BouncyCastle.Asn1.Asn1Encodable,System.Boolean)">
+             Dump out the object as a string
+            
+             @param obj the Asn1Encodable to be dumped out.
+             @param verbose  if true, dump out the contents of octet and bit strings.
+             @return  the resulting string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X500.DirectoryString.ToAsn1Object">
+            <pre>
+             DirectoryString ::= CHOICE {
+               teletexString               TeletexString (SIZE (1..MAX)),
+               printableString             PrintableString (SIZE (1..MAX)),
+               universalString             UniversalString (SIZE (1..MAX)),
+               utf8String                  UTF8String (SIZE (1..MAX)),
+               bmpString                   BMPString (SIZE (1..MAX))  }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AccessDescription">
+            The AccessDescription object.
+            <pre>
+            AccessDescription  ::=  SEQUENCE {
+                  accessMethod          OBJECT IDENTIFIER,
+                  accessLocation        GeneralName  }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AccessDescription.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            create an AccessDescription with the oid and location provided.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.AccessDescription.AccessMethod">
+            
+             @return the access method.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.AccessDescription.AccessLocation">
+            
+             @return the access location
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertIssuer.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames)">
+            <summary>
+            Don't use this one if you are trying to be RFC 3281 compliant.
+            Use it for v1 attribute certificates only.
+            </summary>
+            <param name="names">Our GeneralNames structure</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertIssuer.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttCertIssuer ::= CHOICE {
+                  v1Form   GeneralNames,  -- MUST NOT be used in this
+                                          -- profile
+                  v2Form   [0] V2Form     -- v2 only
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttCertValidityPeriod.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttCertValidityPeriod  ::= Sequence {
+                  notBeforeTime  GeneralizedTime,
+                  notAfterTime   GeneralizedTime
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificate.GetInstance(System.Object)">
+            @param obj
+            @return
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificate.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             AttributeCertificate ::= Sequence {
+                  acinfo               AttributeCertificateInfo,
+                  signatureAlgorithm   AlgorithmIdentifier,
+                  signatureValue       BIT STRING
+             }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AttributeCertificateInfo.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <pre>
+              AttributeCertificateInfo ::= Sequence {
+                   version              AttCertVersion -- version is v2,
+                   holder               Holder,
+                   issuer               AttCertIssuer,
+                   signature            AlgorithmIdentifier,
+                   serialNumber         CertificateSerialNumber,
+                   attrCertValidityPeriod   AttCertValidityPeriod,
+                   attributes           Sequence OF Attr,
+                   issuerUniqueID       UniqueIdentifier OPTIONAL,
+                   extensions           Extensions OPTIONAL
+              }
+            
+              AttCertVersion ::= Integer { v2(1) }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AuthorityInformationAccess">
+             The AuthorityInformationAccess object.
+             <pre>
+             id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+            
+             AuthorityInfoAccessSyntax  ::=
+                  Sequence SIZE (1..MAX) OF AccessDescription
+             AccessDescription  ::=  Sequence {
+                   accessMethod          OBJECT IDENTIFIER,
+                   accessLocation        GeneralName  }
+            
+             id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+             id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+             id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityInformationAccess.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            create an AuthorityInformationAccess with the oid and location provided.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier">
+             The AuthorityKeyIdentifier object.
+             <pre>
+             id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
+            
+               AuthorityKeyIdentifier ::= Sequence {
+                  keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
+                  authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
+                  authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
+            
+               KeyIdentifier ::= OCTET STRING
+             </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+                     *
+                     * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+                     * from SubjectPublicKeyInfo as defined in RFC2459.
+                     *
+                     * Example of making a AuthorityKeyIdentifier:
+                     * <pre>
+            	     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+            		 *       publicKey.getEncoded()).readObject());
+                     *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+                     * </pre>
+                     *
+                     *
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo,Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with the GeneralNames tag and
+            the serial number provided as well.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with the GeneralNames tag and
+            the serial number provided.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(System.Byte[])">
+            create an AuthorityKeyIdentifier with a precomputed key identifier
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.#ctor(System.Byte[],Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Math.BigInteger)">
+            create an AuthorityKeyIdentifier with a precomupted key identifier
+            and the GeneralNames tag and the serial number provided as well.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.AuthorityKeyIdentifier.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.BasicConstraints.#ctor(System.Int32)">
+             create a cA=true object for the given path length constraint.
+            
+             @param pathLenConstraint
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.BasicConstraints.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            BasicConstraints := Sequence {
+               cA                  Boolean DEFAULT FALSE,
+               pathLenConstraint   Integer (0..MAX) OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertificateList">
+             PKIX RFC-2459
+            
+             The X.509 v2 CRL syntax is as follows.  For signature calculation,
+             the data that is to be signed is ASN.1 Der encoded.
+            
+             <pre>
+             CertificateList  ::=  Sequence  {
+                  tbsCertList          TbsCertList,
+                  signatureAlgorithm   AlgorithmIdentifier,
+                  signatureValue       BIT STRING  }
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertificatePair">
+             This class helps to support crossCerfificatePairs in a LDAP directory
+             according RFC 2587
+            
+             <pre>
+                 crossCertificatePairATTRIBUTE::={
+                   WITH SYNTAX   CertificatePair
+                   EQUALITY MATCHING RULE certificatePairExactMatch
+                   ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+             </pre>
+            
+             <blockquote> The forward elements of the crossCertificatePair attribute of a
+             CA's directory entry shall be used to store all, except self-issued
+             certificates issued to this CA. Optionally, the reverse elements of the
+             crossCertificatePair attribute, of a CA's directory entry may contain a
+             subset of certificates issued by this CA to other CAs. When both the forward
+             and the reverse elements are present in a single attribute value, issuer name
+             in one certificate shall match the subject name in the other and vice versa,
+             and the subject public key in one certificate shall be capable of verifying
+             the digital signature on the other certificate and vice versa.
+            
+             When a reverse element is present, the forward element value and the reverse
+             element value need not be stored in the same attribute value; in other words,
+             they can be stored in either a single attribute value or two attribute
+             values. </blockquote>
+            
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type CertificatePair:
+             <p/>
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.#ctor(Org.BouncyCastle.Asn1.X509.X509CertificateStructure,Org.BouncyCastle.Asn1.X509.X509CertificateStructure)">
+             Constructor from a given details.
+            
+             @param forward Certificates issued to this CA.
+             @param reverse Certificates issued by this CA to other CAs.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CertificatePair.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   CertificatePair ::= SEQUENCE {
+                     forward		[0]	Certificate OPTIONAL,
+                     reverse		[1]	Certificate OPTIONAL,
+                     -- at least one of the pair shall be present -- }
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.CertificatePair.Forward">
+            @return Returns the forward.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.CertificatePair.Reverse">
+            @return Returns the reverse.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CertPolicyID">
+             CertPolicyId, used in the CertificatePolicies and PolicyMappings
+             X509V3 Extensions.
+            
+             <pre>
+                 CertPolicyId ::= OBJECT IDENTIFIER
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CrlDistPoint.GetDistributionPoints">
+             Return the distribution points making up the sequence.
+            
+             @return DistributionPoint[]
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.CrlDistPoint.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            CrlDistPoint ::= Sequence SIZE {1..MAX} OF DistributionPoint
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CrlNumber">
+            The CRLNumber object.
+            <pre>
+            CRLNumber::= Integer(0..MAX)
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.CrlReason">
+            The CRLReason enumeration.
+            <pre>
+            CRLReason ::= Enumerated {
+             unspecified             (0),
+             keyCompromise           (1),
+             cACompromise            (2),
+             affiliationChanged      (3),
+             superseded              (4),
+             cessationOfOperation    (5),
+             certificateHold         (6),
+             removeFromCRL           (8),
+             privilegeWithdrawn      (9),
+             aACompromise           (10)
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DigestInfo">
+            The DigestInfo object.
+            <pre>
+            DigestInfo::=Sequence{
+                     digestAlgorithm  AlgorithmIdentifier,
+                     digest OCTET STRING }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DisplayText">
+             <code>DisplayText</code> class, used in
+             <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
+            
+             <p>It stores a string in a chosen encoding.
+             <pre>
+             DisplayText ::= CHOICE {
+                  ia5String        IA5String      (SIZE (1..200)),
+                  visibleString    VisibleString  (SIZE (1..200)),
+                  bmpString        BMPString      (SIZE (1..200)),
+                  utf8String       UTF8String     (SIZE (1..200)) }
+             </pre></p>
+             @see PolicyQualifierInfo
+             @see PolicyInformation
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeIA5String">
+             Constant corresponding to ia5String encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeBmpString">
+             Constant corresponding to bmpString encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeUtf8String">
+             Constant corresponding to utf8String encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.ContentTypeVisibleString">
+             Constant corresponding to visibleString encoding.
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.DisplayText.DisplayTextMaximumSize">
+             Describe constant <code>DisplayTextMaximumSize</code> here.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(System.Int32,System.String)">
+             Creates a new <code>DisplayText</code> instance.
+            
+             @param type the desired encoding type for the text.
+             @param text the text to store. Strings longer than 200
+             characters are truncated.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(System.String)">
+             Creates a new <code>DisplayText</code> instance.
+            
+             @param text the text to encapsulate. Strings longer than 200
+             characters are truncated.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.#ctor(Org.BouncyCastle.Asn1.IAsn1String)">
+             Creates a new <code>DisplayText</code> instance.
+             <p>Useful when reading back a <code>DisplayText</code> class
+             from it's Asn1Encodable form.</p>
+            
+             @param contents an <code>Asn1Encodable</code> instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.DisplayText.GetString">
+             Returns the stored <code>string</code> object.
+            
+             @return the stored text as a <code>string</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DistributionPoint">
+            The DistributionPoint object.
+            <pre>
+            DistributionPoint ::= Sequence {
+                 distributionPoint [0] DistributionPointName OPTIONAL,
+                 reasons           [1] ReasonFlags OPTIONAL,
+                 cRLIssuer         [2] GeneralNames OPTIONAL
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.DistributionPointName">
+            The DistributionPointName object.
+            <pre>
+            DistributionPointName ::= CHOICE {
+                fullName                 [0] GeneralNames,
+                nameRelativeToCRLIssuer  [1] RDN
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage">
+            The extendedKeyUsage object.
+            <pre>
+                 extendedKeyUsage ::= Sequence SIZE (1..MAX) OF KeyPurposeId
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ExtendedKeyUsage.GetAllUsages">
+            Returns all extended key usages.
+            The returned ArrayList contains DerObjectIdentifier instances.
+            @return An ArrayList with all key purposes.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.GeneralName">
+             The GeneralName object.
+             <pre>
+             GeneralName ::= CHOICE {
+                  otherName                       [0]     OtherName,
+                  rfc822Name                      [1]     IA5String,
+                  dNSName                         [2]     IA5String,
+                  x400Address                     [3]     ORAddress,
+                  directoryName                   [4]     Name,
+                  ediPartyName                    [5]     EDIPartyName,
+                  uniformResourceIdentifier       [6]     IA5String,
+                  iPAddress                       [7]     OCTET STRING,
+                  registeredID                    [8]     OBJECT IDENTIFIER}
+            
+             OtherName ::= Sequence {
+                  type-id    OBJECT IDENTIFIER,
+                  value      [0] EXPLICIT ANY DEFINED BY type-id }
+            
+             EDIPartyName ::= Sequence {
+                  nameAssigner            [0]     DirectoryString OPTIONAL,
+                  partyName               [1]     DirectoryString }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralName.#ctor(Org.BouncyCastle.Asn1.Asn1Object,System.Int32)">
+             When the subjectAltName extension contains an Internet mail address,
+             the address MUST be included as an rfc822Name. The format of an
+             rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+            
+             When the subjectAltName extension contains a domain name service
+             label, the domain name MUST be stored in the dNSName (an IA5String).
+             The name MUST be in the "preferred name syntax," as specified by RFC
+             1034 [RFC 1034].
+            
+             When the subjectAltName extension contains a URI, the name MUST be
+             stored in the uniformResourceIdentifier (an IA5String). The name MUST
+             be a non-relative URL, and MUST follow the URL syntax and encoding
+             rules specified in [RFC 1738].  The name must include both a scheme
+             (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
+             specific-part must include a fully qualified domain name or IP
+             address as the host.
+            
+             When the subjectAltName extension contains a iPAddress, the address
+             MUST be stored in the octet string in "network byte order," as
+             specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+             each octet is the LSB of the corresponding byte in the network
+             address. For IP Version 4, as specified in RFC 791, the octet string
+             MUST contain exactly four octets.  For IP Version 6, as specified in
+             RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+             1883].
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralName.#ctor(System.Int32,System.String)">
+             Create a GeneralName for the given tag from the passed in string.
+             <p>
+             This constructor can handle:
+             <ul>
+             <li>rfc822Name</li>
+             <li>iPAddress</li>
+             <li>directoryName</li>
+             <li>dNSName</li>
+             <li>uniformResourceIdentifier</li>
+             <li>registeredID</li>
+             </ul>
+             For x400Address, otherName and ediPartyName there is no common string
+             format defined.
+             </p><p>
+             Note: A directory name can be encoded in different ways into a byte
+             representation. Be aware of this if the byte representation is used for
+             comparing results.
+             </p>
+            
+             @param tag tag number
+             @param name string representation of name
+             @throws ArgumentException if the string encoding is not correct or
+                         not supported.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralNames.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName)">
+            <summary>Construct a GeneralNames object containing one GeneralName.</summary>
+            <param name="name">The name to be contained.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralNames.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.GeneralSubtree">
+             Class for containing a restriction object subtrees in NameConstraints. See
+             RFC 3280.
+            
+             <pre>
+            
+                   GeneralSubtree ::= SEQUENCE
+                   {
+                     baseName                    GeneralName,
+                     minimum         [0]     BaseDistance DEFAULT 0,
+                     maximum         [1]     BaseDistance OPTIONAL
+                   }
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.NameConstraints
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralSubtree.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             Constructor from a given details.
+            
+             According RFC 3280, the minimum and maximum fields are not used with any
+             name forms, thus minimum MUST be zero, and maximum MUST be absent.
+             <p>
+             If minimum is <code>null</code>, zero is assumed, if
+             maximum is <code>null</code>, maximum is absent.</p>
+            
+             @param baseName
+                        A restriction.
+             @param minimum
+                        Minimum
+            
+             @param maximum
+                        Maximum
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.GeneralSubtree.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+            
+             Returns:
+            
+             <pre>
+                   GeneralSubtree ::= SEQUENCE
+                   {
+                     baseName                    GeneralName,
+                     minimum         [0]     BaseDistance DEFAULT 0,
+                     maximum         [1]     BaseDistance OPTIONAL
+                   }
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Holder">
+            The Holder object.
+            <p>
+            For an v2 attribute certificate this is:
+            
+            <pre>
+                       Holder ::= SEQUENCE {
+                             baseCertificateID   [0] IssuerSerial OPTIONAL,
+                                      -- the issuer and serial number of
+                                      -- the holder's Public Key Certificate
+                             entityName          [1] GeneralNames OPTIONAL,
+                                      -- the name of the claimant or role
+                             objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+                                      -- used to directly authenticate the holder,
+                                      -- for example, an executable
+                       }
+            </pre>
+            </p>
+            <p>
+            For an v1 attribute certificate this is:
+            
+            <pre>
+                    subject CHOICE {
+                     baseCertificateID [0] IssuerSerial,
+                     -- associated with a Public Key Certificate
+                     subjectName [1] GeneralNames },
+                     -- associated with a name
+            </pre>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.Asn1TaggedObject)">
+            Constructor for a holder for an v1 attribute certificate.
+            
+            @param tagObj The ASN.1 tagged holder object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor for a holder for an v2 attribute certificate. *
+            
+            @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.IssuerSerial,System.Int32)">
+            Constructs a holder from a IssuerSerial.
+            @param baseCertificateID The IssuerSerial.
+            @param version The version of the attribute certificate. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames)">
+            Constructs a holder with an entityName for v2 attribute certificates or
+            with a subjectName for v1 attribute certificates.
+            
+            @param entityName The entity or subject name.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,System.Int32)">
+            Constructs a holder with an entityName for v2 attribute certificates or
+            with a subjectName for v1 attribute certificates.
+            
+            @param entityName The entity or subject name.
+            @param version The version of the attribute certificate. 
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.#ctor(Org.BouncyCastle.Asn1.X509.ObjectDigestInfo)">
+            Constructs a holder from an object digest info.
+            
+            @param objectDigestInfo The object digest info object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Holder.ToAsn1Object">
+            The Holder object.
+            <pre>
+             Holder ::= Sequence {
+                   baseCertificateID   [0] IssuerSerial OPTIONAL,
+                            -- the issuer and serial number of
+                            -- the holder's Public Key Certificate
+                   entityName          [1] GeneralNames OPTIONAL,
+                            -- the name of the claimant or role
+                   objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+                            -- used to directly authenticate the holder,
+                            -- for example, an executable
+             }
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Holder.Version">
+            Returns 1 for v2 attribute certificates or 0 for v1 attribute
+            certificates. 
+            @return The version of the attribute certificate.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Holder.EntityName">
+            Returns the entityName for an v2 attribute certificate or the subjectName
+            for an v1 attribute certificate.
+            
+            @return The entityname or subjectname.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax">
+            Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IetfAttrSyntax.ToAsn1Object">
+            
+             <pre>
+            
+              IetfAttrSyntax ::= Sequence {
+                policyAuthority [0] GeneralNames OPTIONAL,
+                values Sequence OF CHOICE {
+                  octets OCTET STRING,
+                  oid OBJECT IDENTIFIER,
+                  string UTF8String
+                }
+              }
+            
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuerSerial.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             IssuerSerial  ::=  Sequence {
+                  issuer         GeneralNames,
+                  serial         CertificateSerialNumber,
+                  issuerUid      UniqueIdentifier OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint">
+            <pre>
+            IssuingDistributionPoint ::= SEQUENCE { 
+              distributionPoint          [0] DistributionPointName OPTIONAL, 
+              onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE, 
+              onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE, 
+              onlySomeReasons            [3] ReasonFlags OPTIONAL, 
+              indirectCRL                [4] BOOLEAN DEFAULT FALSE,
+              onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.#ctor(Org.BouncyCastle.Asn1.X509.DistributionPointName,System.Boolean,System.Boolean,Org.BouncyCastle.Asn1.X509.ReasonFlags,System.Boolean,System.Boolean)">
+            Constructor from given details.
+            
+            @param distributionPoint
+                       May contain an URI as pointer to most current CRL.
+            @param onlyContainsUserCerts Covers revocation information for end certificates.
+            @param onlyContainsCACerts Covers revocation information for CA certificates.
+            
+            @param onlySomeReasons
+                       Which revocation reasons does this point cover.
+            @param indirectCRL
+                       If <code>true</code> then the CRL contains revocation
+                       information about certificates ssued by other CAs.
+            @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from Asn1Sequence
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.DistributionPoint">
+            @return Returns the distributionPoint.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.IssuingDistributionPoint.OnlySomeReasons">
+            @return Returns the onlySomeReasons.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.KeyPurposeID">
+            The KeyPurposeID object.
+            <pre>
+                KeyPurposeID ::= OBJECT IDENTIFIER
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.KeyUsage">
+             The KeyUsage object.
+             <pre>
+                id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+            
+                KeyUsage ::= BIT STRING {
+                     digitalSignature        (0),
+                     nonRepudiation          (1),
+                     keyEncipherment         (2),
+                     dataEncipherment        (3),
+                     keyAgreement            (4),
+                     keyCertSign             (5),
+                     cRLSign                 (6),
+                     encipherOnly            (7),
+                     decipherOnly            (8) }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.KeyUsage.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NameConstraints.#ctor(System.Collections.IList,System.Collections.IList)">
+             Constructor from a given details.
+            
+             <p>permitted and excluded are Vectors of GeneralSubtree objects.</p>
+            
+             @param permitted Permitted subtrees
+             @param excluded Excluded subtrees
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.NoticeReference">
+             <code>NoticeReference</code> class, used in
+             <code>CertificatePolicies</code> X509 V3 extensions
+             (in policy qualifiers).
+            
+             <pre>
+              NoticeReference ::= Sequence {
+                  organization     DisplayText,
+                  noticeNumbers    Sequence OF Integer }
+            
+             </pre>
+            
+             @see PolicyQualifierInfo
+             @see PolicyInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(System.String,System.Collections.IList)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param orgName a <code>string</code> value
+             @param numbers a <code>ArrayList</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param orgName a <code>string</code> value
+             @param numbers an <code>Asn1Sequence</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(System.Int32,System.String,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>NoticeReference</code> instance.
+            
+             @param displayTextType an <code>int</code> value
+             @param orgName a <code>string</code> value
+             @param numbers an <code>Asn1Sequence</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>NoticeReference</code> instance.
+             <p>Useful for reconstructing a <code>NoticeReference</code>
+             instance from its encodable/encoded form.</p>
+            
+             @param as an <code>Asn1Sequence</code> value obtained from either
+             calling @{link ToAsn1Object()} for a <code>NoticeReference</code>
+             instance or from parsing it from a Der-encoded stream.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.NoticeReference.ToAsn1Object">
+             Describe <code>ToAsn1Object</code> method here.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo">
+            ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+            
+            <pre>
+             
+               ObjectDigestInfo ::= SEQUENCE {
+                    digestedObjectType  ENUMERATED {
+                            publicKey            (0),
+                            publicKeyCert        (1),
+                            otherObjectTypes     (2) },
+                                    -- otherObjectTypes MUST NOT
+                                    -- be used in this profile
+                    otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+                    digestAlgorithm     AlgorithmIdentifier,
+                    objectDigest        BIT STRING
+               }
+              
+            </pre>
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.PublicKey">
+            The public key is hashed.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.PublicKeyCert">
+            The public key certificate is hashed.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.OtherObjectDigest">
+            An other object is hashed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.#ctor(System.Int32,System.String,Org.BouncyCastle.Asn1.X509.AlgorithmIdentifier,System.Byte[])">
+            Constructor from given details.
+            <p>
+            If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
+            {@link #publicKey} <code>otherObjectTypeID</code> must be given,
+            otherwise it is ignored.</p>
+            
+            @param digestedObjectType The digest object type.
+            @param otherObjectTypeID The object type ID for
+                       <code>otherObjectDigest</code>.
+            @param digestAlgorithm The algorithm identifier for the hash.
+            @param objectDigest The hash value.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ObjectDigestInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            <pre>
+             
+               ObjectDigestInfo ::= SEQUENCE {
+                    digestedObjectType  ENUMERATED {
+                            publicKey            (0),
+                            publicKeyCert        (1),
+                            otherObjectTypes     (2) },
+                                    -- otherObjectTypes MUST NOT
+                                    -- be used in this profile
+                    otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+                    digestAlgorithm     AlgorithmIdentifier,
+                    objectDigest        BIT STRING
+               }
+              
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyMappings">
+             PolicyMappings V3 extension, described in RFC3280.
+             <pre>
+                PolicyMappings ::= Sequence SIZE (1..MAX) OF Sequence {
+                  issuerDomainPolicy      CertPolicyId,
+                  subjectDomainPolicy     CertPolicyId }
+             </pre>
+            
+             @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyMappings.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>PolicyMappings</code> instance.
+            
+             @param seq an <code>Asn1Sequence</code> constructed as specified
+             in RFC 3280
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyMappings.#ctor(System.Collections.IDictionary)">
+             Creates a new <code>PolicyMappings</code> instance.
+            
+             @param mappings a <code>HashMap</code> value that maps
+             <code>string</code> oids
+             to other <code>string</code> oids.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyQualifierID">
+             PolicyQualifierId, used in the CertificatePolicies
+             X509V3 extension.
+            
+             <pre>
+                id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
+                id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+                id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+              PolicyQualifierId ::=
+                   OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo">
+             Policy qualifiers, used in the X509V3 CertificatePolicies
+             extension.
+            
+             <pre>
+               PolicyQualifierInfo ::= Sequence {
+                   policyQualifierId  PolicyQualifierId,
+                   qualifier          ANY DEFINED BY policyQualifierId }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(Org.BouncyCastle.Asn1.DerObjectIdentifier,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Creates a new <code>PolicyQualifierInfo</code> instance.
+            
+             @param policyQualifierId a <code>PolicyQualifierId</code> value
+             @param qualifier the qualifier, defined by the above field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(System.String)">
+             Creates a new <code>PolicyQualifierInfo</code> containing a
+             cPSuri qualifier.
+            
+             @param cps the CPS (certification practice statement) uri as a
+             <code>string</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>PolicyQualifierInfo</code> instance.
+            
+             @param as <code>PolicyQualifierInfo</code> X509 structure
+             encoded as an Asn1Sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.PolicyQualifierInfo.ToAsn1Object">
+             Returns a Der-encodable representation of this instance.
+            
+             @return a <code>Asn1Object</code> value
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.PrivateKeyUsagePeriod">
+            <remarks>
+            <pre>
+            PrivateKeyUsagePeriod ::= SEQUENCE
+            {
+            notBefore       [0]     GeneralizedTime OPTIONAL,
+            notAfter        [1]     GeneralizedTime OPTIONAL }
+            </pre>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.BiometricData">
+            The BiometricData object.
+            <pre>
+            BiometricData  ::=  SEQUENCE {
+                  typeOfBiometricData  TypeOfBiometricData,
+                  hashAlgorithm        AlgorithmIdentifier,
+                  biometricDataHash    OCTET STRING,
+                  sourceDataUri        IA5String OPTIONAL  }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.Iso4217CurrencyCode">
+            The Iso4217CurrencyCode object.
+            <pre>
+            Iso4217CurrencyCode  ::=  CHOICE {
+                  alphabetic              PrintableString (SIZE 3), --Recommended
+                  numeric              INTEGER (1..999) }
+            -- Alphabetic or numeric currency code as defined in ISO 4217
+            -- It is recommended that the Alphabetic form is used
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.MonetaryValue">
+            The MonetaryValue object.
+            <pre>
+            MonetaryValue  ::=  SEQUENCE {
+                  currency              Iso4217CurrencyCode,
+                  amount               INTEGER,
+                  exponent             INTEGER }
+            -- value = amount * 10^exponent
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.QCStatement">
+            The QCStatement object.
+            <pre>
+            QCStatement ::= SEQUENCE {
+              statementId        OBJECT IDENTIFIER,
+              statementInfo      ANY DEFINED BY statementId OPTIONAL}
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.SemanticsInformation">
+             The SemanticsInformation object.
+             <pre>
+                   SemanticsInformation ::= SEQUENCE {
+                     semanticsIdentifier        OBJECT IDENTIFIER   OPTIONAL,
+                     nameRegistrationAuthorities NameRegistrationAuthorities
+                                                                     OPTIONAL }
+                     (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+                      WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+            
+                 NameRegistrationAuthorities ::=  SEQUENCE SIZE (1..MAX) OF
+                     GeneralName
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Qualified.TypeOfBiometricData">
+             The TypeOfBiometricData object.
+             <pre>
+             TypeOfBiometricData ::= CHOICE {
+               predefinedBiometricType   PredefinedBiometricType,
+               biometricDataOid          OBJECT IDENTIFIER }
+            
+             PredefinedBiometricType ::= INTEGER {
+               picture(0),handwritten-signature(1)}
+               (picture|handwritten-signature)
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.ReasonFlags">
+            The ReasonFlags object.
+            <pre>
+            ReasonFlags ::= BIT STRING {
+               unused(0),
+               keyCompromise(1),
+               cACompromise(2),
+               affiliationChanged(3),
+               superseded(4),
+               cessationOfOperation(5),
+               certficateHold(6)
+            }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.ReasonFlags.#ctor(System.Int32)">
+            @param reasons - the bitwise OR of the Key Reason flags giving the
+            allowed uses for the key.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.RoleSyntax">
+             Implementation of the RoleSyntax object as specified by the RFC3281.
+            
+             <pre>
+             RoleSyntax ::= SEQUENCE {
+                             roleAuthority  [0] GeneralNames OPTIONAL,
+                             roleName       [1] GeneralName
+                       }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetInstance(System.Object)">
+            RoleSyntax factory method.
+            @param obj the object used to construct an instance of <code>
+            RoleSyntax</code>. It must be an instance of <code>RoleSyntax
+            </code> or <code>Asn1Sequence</code>.
+            @return the instance of <code>RoleSyntax</code> built from the
+            supplied object.
+            @throws java.lang.ArgumentException if the object passed
+            to the factory is not an instance of <code>RoleSyntax</code> or
+            <code>Asn1Sequence</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralNames,Org.BouncyCastle.Asn1.X509.GeneralName)">
+            Constructor.
+            @param roleAuthority the role authority of this RoleSyntax.
+            @param roleName    the role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.X509.GeneralName)">
+            Constructor. Invoking this constructor is the same as invoking
+            <code>new RoleSyntax(null, roleName)</code>.
+            @param roleName    the role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(System.String)">
+            Utility constructor. Takes a <code>string</code> argument representing
+            the role name, builds a <code>GeneralName</code> to hold the role name
+            and calls the constructor that takes a <code>GeneralName</code>.
+            @param roleName
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor that builds an instance of <code>RoleSyntax</code> by
+            extracting the encoded elements from the <code>Asn1Sequence</code>
+            object supplied.
+            @param seq    an instance of <code>Asn1Sequence</code> that holds
+            the encoded elements used to build this <code>RoleSyntax</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetRoleNameAsString">
+            Gets the role name as a <code>java.lang.string</code> object.
+            @return    the role name of this RoleSyntax represented as a
+            <code>string</code> object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.GetRoleAuthorityAsString">
+            Gets the role authority as a <code>string[]</code> object.
+            @return the role authority of this RoleSyntax represented as a
+            <code>string[]</code> array.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RoleSyntax.ToAsn1Object">
+             Implementation of the method <code>ToAsn1Object</code> as
+             required by the superclass <code>ASN1Encodable</code>.
+            
+             <pre>
+             RoleSyntax ::= SEQUENCE {
+                             roleAuthority  [0] GeneralNames OPTIONAL,
+                             roleName       [1] GeneralName
+                       }
+             </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.RoleSyntax.RoleAuthority">
+            Gets the role authority of this RoleSyntax.
+            @return    an instance of <code>GeneralNames</code> holding the
+            role authority of this RoleSyntax.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.RoleSyntax.RoleName">
+            Gets the role name of this RoleSyntax.
+            @return    an instance of <code>GeneralName</code> holding the
+            role name of this RoleSyntax.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.RsaPublicKeyStructure.ToAsn1Object">
+            This outputs the key in Pkcs1v2 format.
+            <pre>
+                 RSAPublicKey ::= Sequence {
+                                     modulus Integer, -- n
+                                     publicExponent Integer, -- e
+                                 }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym">
+            Structure for a name or pseudonym.
+            
+            <pre>
+                  NameOrPseudonym ::= CHOICE {
+                	   surAndGivenName SEQUENCE {
+                	     surName DirectoryString,
+                	     givenName SEQUENCE OF DirectoryString 
+                    },
+                	   pseudonym DirectoryString 
+                  }
+            </pre>
+            
+            @see org.bouncycastle.asn1.x509.sigi.PersonalData
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString)">
+            Constructor from DERString.
+            <p/>
+            The sequence is of type NameOrPseudonym:
+            <p/>
+            <pre>
+                  NameOrPseudonym ::= CHOICE {
+                	   surAndGivenName SEQUENCE {
+                	     surName DirectoryString,
+                	     givenName SEQUENCE OF DirectoryString
+                    },
+                	   pseudonym DirectoryString
+                  }
+            </pre>
+            @param pseudonym pseudonym value to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type NameOrPseudonym:
+             <p/>
+             <pre>
+                   NameOrPseudonym ::= CHOICE {
+                 	   surAndGivenName SEQUENCE {
+                 	     surName DirectoryString,
+                 	     givenName SEQUENCE OF DirectoryString
+                     },
+                 	   pseudonym DirectoryString
+                   }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(System.String)">
+             Constructor from a given details.
+            
+             @param pseudonym The pseudonym.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.#ctor(Org.BouncyCastle.Asn1.X500.DirectoryString,Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from a given details.
+            
+             @param surname   The surname.
+             @param givenName A sequence of directory strings making up the givenName
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                   NameOrPseudonym ::= CHOICE {
+                 	   surAndGivenName SEQUENCE {
+                 	     surName DirectoryString,
+                 	     givenName SEQUENCE OF DirectoryString
+                     },
+                 	   pseudonym DirectoryString
+                   }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.PersonalData">
+             Contains personal data for the otherName field in the subjectAltNames
+             extension.
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
+             @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+             <p/>
+             The sequence is of type NameOrPseudonym:
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @param seq The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.#ctor(Org.BouncyCastle.Asn1.X509.SigI.NameOrPseudonym,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Asn1.DerGeneralizedTime,Org.BouncyCastle.Asn1.X500.DirectoryString,System.String,Org.BouncyCastle.Asn1.X500.DirectoryString)">
+             Constructor from a given details.
+            
+             @param nameOrPseudonym  Name or pseudonym.
+             @param nameDistinguisher Name distinguisher.
+             @param dateOfBirth      Date of birth.
+             @param placeOfBirth     Place of birth.
+             @param gender           Gender.
+             @param postalAddress    Postal Address.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SigI.PersonalData.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+             <p/>
+             Returns:
+             <p/>
+             <pre>
+                 PersonalData ::= SEQUENCE {
+                   nameOrPseudonym NameOrPseudonym,
+                   nameDistinguisher [0] INTEGER OPTIONAL,
+                   dateOfBirth [1] GeneralizedTime OPTIONAL,
+                   placeOfBirth [2] DirectoryString OPTIONAL,
+                   gender [3] PrintableString OPTIONAL,
+                   postalAddress [4] DirectoryString OPTIONAL
+                   }
+             </pre>
+            
+             @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers">
+            Object Identifiers of SigI specifciation (German Signature Law
+            Interoperability specification).
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIKP">
+            Key purpose IDs for German SigI (Signature Interoperability
+            Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigICP">
+            Certificate policy IDs for German SigI (Signature Interoperability
+            Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigION">
+            Other Name IDs for German SigI (Signature Interoperability Specification)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIKPDirectoryService">
+            To be used for for the generation of directory service certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigIONPersonalData">
+            ID for PersonalData
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.SigI.SigIObjectIdentifiers.IdSigICPSigConform">
+            Certificate is conform to german signature law.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes">
+             This extension may contain further X.500 attributes of the subject. See also
+             RFC 3039.
+            
+             <pre>
+                 SubjectDirectoryAttributes ::= Attributes
+                 Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                 Attribute ::= SEQUENCE
+                 {
+                   type AttributeType
+                   values SET OF AttributeValue
+                 }
+            
+                 AttributeType ::= OBJECT IDENTIFIER
+                 AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+            
+             The sequence is of type SubjectDirectoryAttributes:
+            
+             <pre>
+                  SubjectDirectoryAttributes ::= Attributes
+                  Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                  Attribute ::= SEQUENCE
+                  {
+                    type AttributeType
+                    values SET OF AttributeValue
+                  }
+            
+                  AttributeType ::= OBJECT IDENTIFIER
+                  AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @param seq
+                        The ASN.1 sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.#ctor(System.Collections.IList)">
+             Constructor from an ArrayList of attributes.
+            
+             The ArrayList consists of attributes of type {@link Attribute Attribute}
+            
+             @param attributes The attributes.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.ToAsn1Object">
+             Produce an object suitable for an Asn1OutputStream.
+            
+             Returns:
+            
+             <pre>
+                  SubjectDirectoryAttributes ::= Attributes
+                  Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+                  Attribute ::= SEQUENCE
+                  {
+                    type AttributeType
+                    values SET OF AttributeValue
+                  }
+            
+                  AttributeType ::= OBJECT IDENTIFIER
+                  AttributeValue ::= ANY DEFINED BY AttributeType
+             </pre>
+            
+             @return a DERObject
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes.Attributes">
+            @return Returns the attributes.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier">
+            The SubjectKeyIdentifier object.
+            <pre>
+            SubjectKeyIdentifier::= OCTET STRING
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.#ctor(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+             Calculates the keyIdentifier using a SHA1 hash over the BIT STRING
+             from SubjectPublicKeyInfo as defined in RFC3280.
+            
+             @param spki the subject public key info.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.CreateSha1KeyIdentifier(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Return a RFC 3280 type 1 key identifier. As in:
+            <pre>
+            (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+            value of the BIT STRING subjectPublicKey (excluding the tag,
+            length, and number of unused bits).
+            </pre>
+            @param keyInfo the key info object containing the subjectPublicKey field.
+            @return the key identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectKeyIdentifier.CreateTruncatedSha1KeyIdentifier(Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo)">
+            Return a RFC 3280 type 2 key identifier. As in:
+            <pre>
+            (2) The keyIdentifier is composed of a four bit type field with
+            the value 0100 followed by the least significant 60 bits of the
+            SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+            </pre>
+            @param keyInfo the key info object containing the subjectPublicKey field.
+            @return the key identifier.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo">
+            The object that contains the public key stored in a certficate.
+            <p>
+            The GetEncoded() method in the public keys in the JCE produces a DER
+            encoded one of these.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.GetPublicKey">
+             for when the public key is an encoded object - if the bitstring
+             can't be decoded this routine raises an IOException.
+            
+             @exception IOException - if the bit string doesn't represent a Der
+             encoded object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            SubjectPublicKeyInfo ::= Sequence {
+                                     algorithm AlgorithmIdentifier,
+                                     publicKey BIT STRING }
+            </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.SubjectPublicKeyInfo.PublicKeyData">
+            for when the public key is raw bits...
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Target">
+            Target structure used in target information extension for attribute
+            certificates from RFC 3281.
+            
+            <pre>
+                Target  ::= CHOICE {
+                  targetName          [0] GeneralName,
+                  targetGroup         [1] GeneralName,
+                  targetCert          [2] TargetCert
+                }
+            </pre>
+            
+            <p>
+            The targetCert field is currently not supported and must not be used
+            according to RFC 3281.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.GetInstance(System.Object)">
+            Creates an instance of a Target from the given object.
+            <p>
+            <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
+            
+            @param obj The object.
+            @return A Target instance.
+            @throws ArgumentException if the given object cannot be
+                        interpreted as Target.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.#ctor(Org.BouncyCastle.Asn1.Asn1TaggedObject)">
+            Constructor from Asn1TaggedObject.
+            
+            @param tagObj The tagged object.
+            @throws ArgumentException if the encoding is wrong.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.#ctor(Org.BouncyCastle.Asn1.X509.Target.Choice,Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Constructor from given details.
+             <p>
+             Exactly one of the parameters must be not <code>null</code>.</p>
+            
+             @param type the choice type to apply to the name.
+             @param name the general name.
+             @throws ArgumentException if type is invalid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Target.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                Target  ::= CHOICE {
+                  targetName          [0] GeneralName,
+                  targetGroup         [1] GeneralName,
+                  targetCert          [2] TargetCert
+                }
+            </pre>
+            
+            @return an Asn1Object
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Target.TargetGroup">
+            @return Returns the targetGroup.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.Target.TargetName">
+            @return Returns the targetName.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TargetInformation">
+            Target information extension for attributes certificates according to RFC
+            3281.
+            
+            <pre>
+                      SEQUENCE OF Targets
+            </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.GetInstance(System.Object)">
+            Creates an instance of a TargetInformation from the given object.
+            <p>
+            <code>obj</code> can be a TargetInformation or a {@link Asn1Sequence}</p>
+            
+            @param obj The object.
+            @return A TargetInformation instance.
+            @throws ArgumentException if the given object cannot be interpreted as TargetInformation.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from a Asn1Sequence.
+            
+            @param seq The Asn1Sequence.
+            @throws ArgumentException if the sequence does not contain
+                        correctly encoded Targets elements.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.GetTargetsObjects">
+            Returns the targets in this target information extension.
+            <p>
+            The ArrayList is cloned before it is returned.</p>
+            
+            @return Returns the targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.X509.Targets)">
+            Constructs a target information from a single targets element. 
+            According to RFC 3281 only one targets element must be produced.
+            
+            @param targets A Targets instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.#ctor(Org.BouncyCastle.Asn1.X509.Target[])">
+             According to RFC 3281 only one targets element must be produced. If
+             multiple targets are given they must be merged in
+             into one targets element.
+            
+             @param targets An array with {@link Targets}.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.TargetInformation.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                     SEQUENCE OF Targets
+            </pre>
+            
+            <p>
+            According to RFC 3281 only one targets element must be produced. If
+            multiple targets are given in the constructor they are merged into one
+            targets element. If this was produced from a
+            {@link Org.BouncyCastle.Asn1.Asn1Sequence} the encoding is kept.</p>
+            
+            @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.Targets">
+            Targets structure used in target information extension for attribute
+            certificates from RFC 3281.
+            
+            <pre>
+                       Targets ::= SEQUENCE OF Target
+                      
+                       Target  ::= CHOICE {
+                         targetName          [0] GeneralName,
+                         targetGroup         [1] GeneralName,
+                         targetCert          [2] TargetCert
+                       }
+                      
+                       TargetCert  ::= SEQUENCE {
+                         targetCertificate    IssuerSerial,
+                         targetName           GeneralName OPTIONAL,
+                         certDigestInfo       ObjectDigestInfo OPTIONAL
+                       }
+            </pre>
+            
+            @see org.bouncycastle.asn1.x509.Target
+            @see org.bouncycastle.asn1.x509.TargetInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.GetInstance(System.Object)">
+            Creates an instance of a Targets from the given object.
+            <p>
+            <code>obj</code> can be a Targets or a {@link Asn1Sequence}</p>
+            
+            @param obj The object.
+            @return A Targets instance.
+            @throws ArgumentException if the given object cannot be interpreted as Target.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+            Constructor from Asn1Sequence.
+            
+            @param targets The ASN.1 SEQUENCE.
+            @throws ArgumentException if the contents of the sequence are
+                        invalid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.#ctor(Org.BouncyCastle.Asn1.X509.Target[])">
+            Constructor from given targets.
+            <p>
+            The ArrayList is copied.</p>
+            
+            @param targets An <code>ArrayList</code> of {@link Target}s.
+            @see Target
+            @throws ArgumentException if the ArrayList contains not only Targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.GetTargets">
+            Returns the targets in an <code>ArrayList</code>.
+            <p>
+            The ArrayList is cloned before it is returned.</p>
+            
+            @return Returns the targets.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Targets.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            
+            Returns:
+            
+            <pre>
+                       Targets ::= SEQUENCE OF Target
+            </pre>
+            
+            @return an Asn1Object
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TbsCertificateStructure">
+            The TbsCertificate object.
+            <pre>
+            TbsCertificate ::= Sequence {
+                 version          [ 0 ]  Version DEFAULT v1(0),
+                 serialNumber            CertificateSerialNumber,
+                 signature               AlgorithmIdentifier,
+                 issuer                  Name,
+                 validity                Validity,
+                 subject                 Name,
+                 subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                 issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                 subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                 extensions        [ 3 ] Extensions OPTIONAL
+                 }
+            </pre>
+            <p>
+            Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+            will parse them, but you really shouldn't be creating new ones.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.TbsCertificateList">
+            PKIX RFC-2459 - TbsCertList object.
+            <pre>
+            TbsCertList  ::=  Sequence  {
+                 version                 Version OPTIONAL,
+                                              -- if present, shall be v2
+                 signature               AlgorithmIdentifier,
+                 issuer                  Name,
+                 thisUpdate              Time,
+                 nextUpdate              Time OPTIONAL,
+                 revokedCertificates     Sequence OF Sequence  {
+                      userCertificate         CertificateSerialNumber,
+                      revocationDate          Time,
+                      crlEntryExtensions      Extensions OPTIONAL
+                                                    -- if present, shall be v2
+                                           }  OPTIONAL,
+                 crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+                                                    -- if present, shall be v2
+                                           }
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.#ctor(System.DateTime)">
+            creates a time object from a given date - if the date is between 1950
+            and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+            is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.ToDateTime">
+            <summary>
+            Return our time as DateTime.
+            </summary>
+            <returns>A date time.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.Time.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Time ::= CHOICE {
+                        utcTime        UTCTime,
+                        generalTime    GeneralizedTime }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.UserNotice">
+             <code>UserNotice</code> class, used in
+             <code>CertificatePolicies</code> X509 extensions (in policy
+             qualifiers).
+             <pre>
+             UserNotice ::= Sequence {
+                  noticeRef        NoticeReference OPTIONAL,
+                  explicitText     DisplayText OPTIONAL}
+            
+             </pre>
+            
+             @see PolicyQualifierId
+             @see PolicyInformation
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.X509.NoticeReference,Org.BouncyCastle.Asn1.X509.DisplayText)">
+             Creates a new <code>UserNotice</code> instance.
+            
+             @param noticeRef a <code>NoticeReference</code> value
+             @param explicitText a <code>DisplayText</code> value
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.X509.NoticeReference,System.String)">
+             Creates a new <code>UserNotice</code> instance.
+            
+             @param noticeRef a <code>NoticeReference</code> value
+             @param str the explicitText field as a string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.UserNotice.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Creates a new <code>UserNotice</code> instance.
+             <p>Useful from reconstructing a <code>UserNotice</code> instance
+             from its encodable/encoded form.
+            
+             @param as an <code>ASN1Sequence</code> value obtained from either
+             calling @{link toASN1Object()} for a <code>UserNotice</code>
+             instance or from parsing it from a DER-encoded stream.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V1TbsCertificateGenerator">
+             Generator for Version 1 TbsCertificateStructures.
+             <pre>
+             TbsCertificate ::= Sequence {
+                  version          [ 0 ]  Version DEFAULT v1(0),
+                  serialNumber            CertificateSerialNumber,
+                  signature               AlgorithmIdentifier,
+                  issuer                  Name,
+                  validity                Validity,
+                  subject                 Name,
+                  subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                  }
+             </pre>
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V2AttributeCertificateInfoGenerator">
+             Generator for Version 2 AttributeCertificateInfo
+             <pre>
+             AttributeCertificateInfo ::= Sequence {
+                   version              AttCertVersion -- version is v2,
+                   holder               Holder,
+                   issuer               AttCertIssuer,
+                   signature            AlgorithmIdentifier,
+                   serialNumber         CertificateSerialNumber,
+                   attrCertValidityPeriod   AttCertValidityPeriod,
+                   attributes           Sequence OF Attr,
+                   issuerUniqueID       UniqueIdentifier OPTIONAL,
+                   extensions           Extensions OPTIONAL
+             }
+             </pre>
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.V2AttributeCertificateInfoGenerator.AddAttribute(Org.BouncyCastle.Asn1.X509.AttributeX509)">
+            @param attribute
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.V2Form.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             V2Form ::= Sequence {
+                  issuerName            GeneralNames  OPTIONAL,
+                  baseCertificateID     [0] IssuerSerial  OPTIONAL,
+                  objectDigestInfo      [1] ObjectDigestInfo  OPTIONAL
+                    -- issuerName MUST be present in this profile
+                    -- baseCertificateID and objectDigestInfo MUST NOT
+                    -- be present in this profile
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V2TbsCertListGenerator">
+             Generator for Version 2 TbsCertList structures.
+             <pre>
+              TbsCertList  ::=  Sequence  {
+                   version                 Version OPTIONAL,
+                                                -- if present, shall be v2
+                   signature               AlgorithmIdentifier,
+                   issuer                  Name,
+                   thisUpdate              Time,
+                   nextUpdate              Time OPTIONAL,
+                   revokedCertificates     Sequence OF Sequence  {
+                        userCertificate         CertificateSerialNumber,
+                        revocationDate          Time,
+                        crlEntryExtensions      Extensions OPTIONAL
+                                                      -- if present, shall be v2
+                                             }  OPTIONAL,
+                   crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+                                                      -- if present, shall be v2
+                                             }
+             </pre>
+            
+             <b>Note: This class may be subject to change</b>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.V3TbsCertificateGenerator">
+             Generator for Version 3 TbsCertificateStructures.
+             <pre>
+             TbsCertificate ::= Sequence {
+                  version          [ 0 ]  Version DEFAULT v1(0),
+                  serialNumber            CertificateSerialNumber,
+                  signature               AlgorithmIdentifier,
+                  issuer                  Name,
+                  validity                Validity,
+                  subject                 Name,
+                  subjectPublicKeyInfo    SubjectPublicKeyInfo,
+                  issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                  subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+                  extensions        [ 3 ] Extensions OPTIONAL
+                  }
+             </pre>
+            
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509CertificateStructure">
+            an X509Certificate structure.
+            <pre>
+             Certificate ::= Sequence {
+                 tbsCertificate          TbsCertificate,
+                 signatureAlgorithm      AlgorithmIdentifier,
+                 signature               BIT STRING
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509DefaultEntryConverter">
+            The default converter for X509 DN entries when going from their
+            string value to ASN.1 strings.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter">
+                 * It turns out that the number of standard ways the fields in a DN should be
+                 * encoded into their ASN.1 counterparts is rapidly approaching the
+                 * number of machines on the internet. By default the X509Name class
+                 * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+                 * <p>
+                 * An example of an encoder look like below:
+                 * <pre>
+                 * public class X509DirEntryConverter
+                 *     : X509NameEntryConverter
+                 * {
+                 *     public Asn1Object GetConvertedValue(
+                 *         DerObjectIdentifier  oid,
+                 *         string               value)
+                 *     {
+                 *         if (str.Length() != 0 && str.charAt(0) == '#')
+                 *         {
+                 *             return ConvertHexEncoded(str, 1);
+                 *         }
+                 *         if (oid.Equals(EmailAddress))
+                 *         {
+                 *             return new DerIA5String(str);
+                 *         }
+                 *         else if (CanBePrintable(str))
+                 *         {
+                 *             return new DerPrintableString(str);
+                 *         }
+                 *         else if (CanBeUTF8(str))
+                 *         {
+                 *             return new DerUtf8String(str);
+                 *         }
+                 *         else
+                 *         {
+                 *             return new DerBmpString(str);
+                 *         }
+                 *     }
+                 * }
+            	 * </pre>
+            	 * </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.ConvertHexEncoded(System.String,System.Int32)">
+             Convert an inline encoded hex string rendition of an ASN.1
+             object back into its corresponding ASN.1 object.
+            
+             @param str the hex encoded object
+             @param off the index at which the encoding starts
+             @return the decoded object
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.CanBePrintable(System.String)">
+            return true if the passed in string can be represented without
+            loss as a PrintableString, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509NameEntryConverter.GetConvertedValue(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String)">
+             Convert the passed in string value into the appropriate ASN.1
+             encoded object.
+            
+             @param oid the oid associated with the value in the DN.
+             @param value the value of the particular DN component.
+             @return the ASN.1 equivalent for the value.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509DefaultEntryConverter.GetConvertedValue(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.String)">
+             Apply default conversion for the given value depending on the oid
+             and the character range of the value.
+            
+             @param oid the object identifier for the DN entry
+             @param value the value associated with it
+             @return the ASN.1 equivalent for the string value.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509Extension">
+            an object for the elements in the X.509 V3 extension block.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extension.ConvertValueToObject(Org.BouncyCastle.Asn1.X509.X509Extension)">
+            <sumary>Convert the value of the passed in extension to an object.</sumary>
+            <param name="ext">The extension to parse.</param>
+            <returns>The object the value string contains.</returns>
+            <exception cref="T:System.ArgumentException">If conversion is not possible.</exception>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectDirectoryAttributes">
+            Subject Directory Attributes
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectKeyIdentifier">
+            Subject Key Identifier
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.KeyUsage">
+            Key Usage
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PrivateKeyUsagePeriod">
+            Private Key Usage Period
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectAlternativeName">
+            Subject Alternative Name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.IssuerAlternativeName">
+            Issuer Alternative Name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.BasicConstraints">
+            Basic Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CrlNumber">
+            CRL Number
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.ReasonCode">
+            Reason code
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InstructionCode">
+            Hold Instruction Code
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InvalidityDate">
+            Invalidity Date
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.DeltaCrlIndicator">
+            Delta CRL indicator
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.IssuingDistributionPoint">
+            Issuing Distribution Point
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CertificateIssuer">
+            Certificate Issuer
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.NameConstraints">
+            Name Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CrlDistributionPoints">
+            CRL Distribution Points
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.CertificatePolicies">
+            Certificate Policies
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PolicyMappings">
+            Policy Mappings
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityKeyIdentifier">
+            Authority Key Identifier
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.PolicyConstraints">
+            Policy Constraints
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.ExtendedKeyUsage">
+            Extended Key Usage
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.FreshestCrl">
+            Freshest CRL
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.InhibitAnyPolicy">
+            Inhibit Any Policy
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuthorityInfoAccess">
+            Authority Info Access
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.SubjectInfoAccess">
+            Subject Info Access
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.LogoType">
+            Logo Type
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.BiometricInfo">
+            BiometricInfo
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.QCStatements">
+            QCStatements
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.AuditIdentity">
+            Audit identity extension in attribute certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.NoRevAvail">
+            NoRevAvail extension in attribute certificates.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Extensions.TargetInformation">
+            TargetInformation extension in attribute certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence.
+            
+             the extensions are a list of constructed sequences, either with (Oid, OctetString) or (Oid, Boolean, OctetString)
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IDictionary)">
+            constructor from a table of extensions.
+            <p>
+            it's is assumed the table contains Oid/string pairs.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IList,System.Collections.IDictionary)">
+            Constructor from a table of extensions with ordering.
+            <p>
+            It's is assumed the table contains Oid/string pairs.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.#ctor(System.Collections.IList,System.Collections.IList)">
+             Constructor from two vectors
+            
+             @param objectIDs an ArrayList of the object identifiers.
+             @param values an ArrayList of the extension values.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.GetExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the extension represented by the object identifier
+             passed in.
+            
+             @return the extension if it's present, null otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Extensions.ToAsn1Object">
+             <pre>
+                 Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
+            
+                 Extension         ::=   SEQUENCE {
+                    extnId            EXTENSION.&id ({ExtensionSet}),
+                    critical          BOOLEAN DEFAULT FALSE,
+                    extnValue         OCTET STRING }
+             </pre>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509Extensions.ExtensionOids">
+            return an Enumeration of the extension field's object ids.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator">
+            <remarks>Generator for X.509 extensions</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.Reset">
+            <summary>Reset the generator</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add an extension with the given oid and the passed in value to be included
+            in the OCTET STRING associated with the extension.
+            </summary>
+            <param name="oid">OID for the extension.</param>
+            <param name="critical">True if critical, false otherwise.</param>
+            <param name="extValue">The ASN.1 object to be included in the extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension with the given oid and the passed in byte array to be wrapped
+            in the OCTET STRING associated with the extension.
+            </summary>
+            <param name="oid">OID for the extension.</param>
+            <param name="critical">True if critical, false otherwise.</param>
+            <param name="extValue">The byte array to be wrapped.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.Generate">
+            <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
+            <returns>An <c>X509Extensions</c> object</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509ExtensionsGenerator.IsEmpty">
+            <summary>Return true if there are no extension present in this generator.</summary>
+            <returns>True if empty, false otherwise</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509Name">
+             <pre>
+                 RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+            
+                 RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+            
+                 AttributeTypeAndValue ::= SEQUENCE {
+                                               type  OBJECT IDENTIFIER,
+                                               value ANY }
+             </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.C">
+            country code - StringType(SIZE(2))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.O">
+            organization - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.OU">
+            organizational unit name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.T">
+            Title
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CN">
+            common name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Street">
+            street - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.SerialNumber">
+            device serial number name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.L">
+            locality name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.ST">
+            state, or province name - StringType(SIZE(1..64))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Surname">
+            Naming attributes of type X520name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.BusinessCategory">
+            businessCategory - DirectoryString(SIZE(1..128)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PostalCode">
+            postalCode - DirectoryString(SIZE(1..40)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DnQualifier">
+            dnQualifier - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Pseudonym">
+            RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DateOfBirth">
+            RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PlaceOfBirth">
+            RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Gender">
+            RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CountryOfCitizenship">
+            RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+            codes only
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.CountryOfResidence">
+            RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+            codes only
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.NameAtBirth">
+            ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.PostalAddress">
+            RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+            DirectoryString(SIZE(1..30))
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DmdName">
+            RFC 2256 dmdName
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.TelephoneNumber">
+            id-at-telephoneNumber
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.Name">
+            id-at-name
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.EmailAddress">
+            Email address (RSA PKCS#9 extension) - IA5String.
+            <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.</p>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.UnstructuredName">
+            more from PKCS#9
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.E">
+            email address in Verisign certificates
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.UID">
+            LDAP User id.
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DefaultSymbols">
+            default look up table translating OID values into their common symbols following
+            the convention in RFC 2253 with a few extras
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.RFC2253Symbols">
+            look up table translating OID values into their common symbols following the convention in RFC 2253
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.RFC1779Symbols">
+             look up table translating OID values into their common symbols following the convention in RFC 1779
+            
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X509.X509Name.DefaultLookup">
+            look up table translating common symbols into their OIDS.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetInstance(Org.BouncyCastle.Asn1.Asn1TaggedObject,System.Boolean)">
+             Return a X509Name based on the passed in tagged object.
+            
+             @param obj tag object holding name.
+             @param explicitly true if explicitly tagged false otherwise.
+             @return the X509Name
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Constructor from Asn1Sequence
+            
+             the principal will be a list of constructed sets, each containing an (OID, string) pair.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IDictionary)">
+            Constructor from a table of attributes with ordering.
+            <p>
+            it's is assumed the table contains OID/string pairs, and the contents
+            of the table are copied into an internal table as part of the
+            construction process. The ordering ArrayList should contain the OIDs
+            in the order they are meant to be encoded or printed in ToString.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IDictionary,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Constructor from a table of attributes with ordering.
+            <p>
+            it's is assumed the table contains OID/string pairs, and the contents
+            of the table are copied into an internal table as part of the
+            construction process. The ordering ArrayList should contain the OIDs
+            in the order they are meant to be encoded or printed in ToString.</p>
+            <p>
+            The passed in converter will be used to convert the strings into their
+            ASN.1 counterparts.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IList)">
+            Takes two vectors one of the oids and the other of the values.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Collections.IList,System.Collections.IList,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes two vectors one of the oids and the other of the values.
+            <p>
+            The passed in converter will be used to convert the strings into their
+            ASN.1 counterparts.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes with each
+            string value being converted to its associated ASN.1 type using the passed
+            in converter.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. If reverse
+            is true, create the encoded version of the sequence starting from the
+            last element in the string.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes with each
+            string value being converted to its associated ASN.1 type using the passed
+            in converter. If reverse is true the ASN.1 sequence representing the DN will
+            be built by starting at the end of the string, rather than the start.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.Collections.IDictionary,System.String)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. lookUp
+            should provide a table of lookups, indexed by lowercase only strings and
+            yielding a DerObjectIdentifier, other than that OID. and numeric oids
+            will be processed automatically.
+            <br/>
+            If reverse is true, create the encoded version of the sequence
+            starting from the last element in the string.
+            @param reverse true if we should start scanning from the end (RFC 2553).
+            @param lookUp table of names and their oids.
+            @param dirName the X.500 string to be parsed.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.#ctor(System.Boolean,System.Collections.IDictionary,System.String,Org.BouncyCastle.Asn1.X509.X509NameEntryConverter)">
+            Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+            some such, converting it into an ordered set of name attributes. lookUp
+            should provide a table of lookups, indexed by lowercase only strings and
+            yielding a DerObjectIdentifier, other than that OID. and numeric oids
+            will be processed automatically. The passed in converter is used to convert the
+            string values to the right of each equals sign to their ASN.1 counterparts.
+            <br/>
+            @param reverse true if we should start scanning from the end, false otherwise.
+            @param lookUp table of names and oids.
+            @param dirName the string dirName
+            @param converter the converter to convert string values into their ASN.1 equivalents
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetOidList">
+            return an IList of the oids in the name, in the order they were found.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetValueList">
+            return an IList of the values found in the name, in the order they
+            were found.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.GetValueList(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return an IList of the values found in the name, in the order they
+            were found, with the DN label corresponding to passed in oid.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.Equivalent(Org.BouncyCastle.Asn1.X509.X509Name,System.Boolean)">
+            <param name="other">The X509Name object to test equivalency against.</param>
+            <param name="inOrder">If true, the order of elements must be the same,
+            as well as the values associated with each element.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.Equivalent(Org.BouncyCastle.Asn1.X509.X509Name)">
+            test for equivalence - note: case is ignored.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X509.X509Name.ToString(System.Boolean,System.Collections.IDictionary)">
+             convert the structure to a string - if reverse is true the
+             oids and values are listed out starting with the last element
+             in the sequence (ala RFC 2253), otherwise the string will begin
+             with the first element of the structure. If no string definition
+             for the oid is found in oidSymbols the string value of the oid is
+             added. Two standard symbol tables are provided DefaultSymbols, and
+             RFC2253Symbols as part of this class.
+            
+             @param reverse if true start at the end of the sequence and work back.
+             @param oidSymbols look up table strings for oids.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X509.X509Name.DefaultReverse">
+            determines whether or not strings should be processed and printed
+            from back to front.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X509.X509NameTokenizer">
+            class for breaking up an X500 Name into it's component tokens, ala
+            java.util.StringTokenizer. We need this class as some of the
+            lightweight Java environment don't support classes like
+            StringTokenizer.
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.KeySpecificInfo">
+            ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+            RFC 2631, or X9.42, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.KeySpecificInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             KeySpecificInfo ::= Sequence {
+                 algorithm OBJECT IDENTIFIER,
+                 counter OCTET STRING SIZE (4..4)
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.OtherInfo">
+            ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+            RFC 2631, or X9.42, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.OtherInfo.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             OtherInfo ::= Sequence {
+                 keyInfo KeySpecificInfo,
+                 partyAInfo [0] OCTET STRING OPTIONAL,
+                 suppPubInfo [2] OCTET STRING
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X962NamedCurves">
+            table of the current named curves defined in X.962 EC-DSA.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetByOid(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+             return the X9ECParameters object for the named curve represented by
+             the passed in object identifier. Null if the curve isn't present.
+            
+             @param oid an object identifier representing a named curve, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetOid(System.String)">
+             return the object identifier signified by the passed in name. Null
+             if there is no object identifier associated with name.
+            
+             @return the object identifier associated with name, if present.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962NamedCurves.GetName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            return the named curve name represented by the given object identifier.
+        </member>
+        <member name="P:Org.BouncyCastle.Asn1.X9.X962NamedCurves.Names">
+            returns an enumeration containing the name strings for curves
+            contained in this structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X962Parameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+            Parameters ::= CHOICE {
+               ecParameters ECParameters,
+               namedCurve   CURVES.&id({CurveNames}),
+               implicitlyCA Null
+            }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9Curve">
+            ASN.1 def for Elliptic-Curve Curve structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9Curve.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             Curve ::= Sequence {
+                 a               FieldElement,
+                 b               FieldElement,
+                 seed            BIT STRING      OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9ECParameters">
+            ASN.1 def for Elliptic-Curve ECParameters structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9ECParameters.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             ECParameters ::= Sequence {
+                 version         Integer { ecpVer1(1) } (ecpVer1),
+                 fieldID         FieldID {{FieldTypes}},
+                 curve           X9Curve,
+                 base            X9ECPoint,
+                 order           Integer,
+                 cofactor        Integer OPTIONAL
+             }
+            </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9ECPoint">
+            class for describing an ECPoint as a Der object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9ECPoint.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             ECPoint ::= OCTET STRING
+            </pre>
+            <p>
+            Octet string produced using ECPoint.GetEncoded().</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9FieldElement">
+            Class for processing an ECFieldElement as a DER object.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldElement.ToAsn1Object">
+            Produce an object suitable for an Asn1OutputStream.
+            <pre>
+             FieldElement ::= OCTET STRING
+            </pre>
+            <p>
+            <ol>
+            <li> if <i>q</i> is an odd prime then the field element is
+            processed as an Integer and converted to an octet string
+            according to x 9.62 4.3.1.</li>
+            <li> if <i>q</i> is 2<sup>m</sup> then the bit string
+            contained in the field element is converted into an octet
+            string with the same ordering padded at the front if necessary.
+            </li>
+            </ol>
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Asn1.X9.X9FieldID">
+            ASN.1 def for Elliptic-Curve Field ID structure. See
+            X9.62, for further details.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.#ctor(Org.BouncyCastle.Math.BigInteger)">
+            Constructor for elliptic curves over prime fields
+            <code>F<sub>2</sub></code>.
+            @param primeP The prime <code>p</code> defining the prime field.
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.#ctor(System.Int32,System.Int32,System.Int32,System.Int32)">
+            Constructor for elliptic curves over binary fields
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>..
+        </member>
+        <member name="M:Org.BouncyCastle.Asn1.X9.X9FieldID.ToAsn1Object">
+            Produce a Der encoding of the following structure.
+            <pre>
+             FieldID ::= Sequence {
+                 fieldType       FIELD-ID.&id({IOSet}),
+                 parameters      FIELD-ID.&Type({IOSet}{@fieldType})
+             }
+            </pre>
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.AnsiX942">
+            X9.42
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.IdDsaWithSha1">
+            id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
+                  us(840) x9-57 (10040) x9cm(4) 3 }
+        </member>
+        <member name="F:Org.BouncyCastle.Asn1.X9.X9ObjectIdentifiers.X9x63Scheme">
+            X9.63
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ArmoredInputStream">
+            reader for Base64 armored objects - read the headers and then start returning
+            bytes when the data is reached. An IOException is thrown if the CRC check
+            fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.Decode(System.Int32,System.Int32,System.Int32,System.Int32,System.Int32[])">
+             decode the base 64 encoded input data.
+            
+             @return the offset the data starts in out.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.#ctor(System.IO.Stream)">
+             Create a stream for reading a PGP armoured message, parsing up to a header
+             and then reading the data that follows.
+            
+             @param input
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.#ctor(System.IO.Stream,System.Boolean)">
+             Create an armoured input stream which will assume the data starts
+             straight away, or parse for headers first depending on the value of
+             hasHeaders.
+            
+             @param input
+             @param hasHeaders true if headers are to be looked for, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.IsClearText">
+            @return true if we are inside the clear text section of a PGP
+            signed message.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.IsEndOfStream">
+            @return true if the stream is actually at end of file.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.GetArmorHeaderLine">
+            Return the armor header line (if there is one)
+            @return the armor header line, null if none present.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredInputStream.GetArmorHeaders">
+            Return the armor headers (the lines after the armor header line),
+            @return an array of armor headers, null if there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ArmoredOutputStream">
+            Basic output stream.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.Encode(System.IO.Stream,System.Int32[],System.Int32)">
+            encode the input data producing a base 64 encoded byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.SetHeader(System.String,System.String)">
+             Set an additional header entry.
+            
+             @param name the name of the header entry.
+             @param v the value of the header entry.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.ResetHeaders">
+            Reset the headers to only contain a Version string.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.BeginClearText(Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            Start a clear text signed message.
+            @param hashAlgorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ArmoredOutputStream.Dispose(System.Boolean)">
+            <b>Note</b>: Dispose does nor Dispose the underlying stream. So it is possible to write
+            multiple objects using armoring to a single stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Attr.ImageAttrib">
+            <remarks>Basic type for a image attribute packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacket">
+            Basic type for a user attribute sub-packet.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.UserAttributeSubpacket.GetData">
+            return the generic data making up the packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgInputStream">
+            <remarks>Reader for PGP objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgInputStream.NextPacketTag">
+            <summary>Returns the next packet tag in the stream.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgInputStream.PartialInputStream">
+            <summary>
+            A stream that overlays our input stream, allowing the user to only read a segment of it.
+            NB: dataLength will be negative if the segment length is in the upper range above 2**31.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgObject">
+            <remarks>Base class for a PGP object.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.BcpgOutputStream">
+            <remarks>Basic output stream.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream)">
+            <summary>Create a stream representing a general packet.</summary>
+            <param name="outStr">Output stream to write to.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag)">
+            <summary>Create a stream representing an old style partial object.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">The packet tag for the object.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Int64,System.Boolean)">
+            <summary>Create a stream representing a general packet.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="length">Size of chunks making up the packet.</param>
+            <param name="oldFormat">If true, the header is written out in old format.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Int64)">
+            <summary>Create a new style partial input stream buffered into chunks.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="length">Size of chunks making up the packet.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.#ctor(System.IO.Stream,Org.BouncyCastle.Bcpg.PacketTag,System.Byte[])">
+            <summary>Create a new style partial input stream buffered into chunks.</summary>
+            <param name="outStr">Output stream to write to.</param>
+            <param name="tag">Packet tag.</param>
+            <param name="buffer">Buffer to use for collecting chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.Flush">
+            <summary>Flush the underlying stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.BcpgOutputStream.Finish">
+            <summary>Finish writing out the current packet without closing the underlying stream.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.CompressedDataPacket">
+            <remarks>Generic compressed data object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.InputStreamPacket.GetInputStream">
+            <summary>Note: you can only read from this once...</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.CompressedDataPacket.Algorithm">
+            <summary>The algorithm tag value.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.CompressionAlgorithmTag">
+            <remarks>Basic tags for compression algorithms.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ContainedPacket">
+            <remarks>Basic type for a PGP packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey">
+            <remarks>Base class for a DSA public key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.IBcpgKey">
+            <remarks>Base interface for a PGP key.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.IBcpgKey.Format">
+            <summary>
+            The base format for this key - in the case of the symmetric keys it will generally
+            be raw indicating that the key is just a straight byte representation, for an asymmetric
+            key the format will be PGP, indicating the key is a string of MPIs encoded in PGP format.
+            </summary>
+            <returns>"RAW" or "PGP".</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            <param name="bcpgIn">The stream to read the packet from.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey">
+            <remarks>Base class for a DSA secret key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            @param in
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.DsaSecretBcpgKey.X">
+            @return x
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey">
+            <remarks>Base class for an ElGamal public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.ElGamalPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey">
+            <remarks>Base class for an ElGamal secret key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            @param in
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.#ctor(Org.BouncyCastle.Math.BigInteger)">
+            @param x
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.ElGamalSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ExperimentalPacket">
+            <remarks>Basic packet for an experimental packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.HashAlgorithmTag">
+            <remarks>Basic tags for hash algorithms.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.LiteralDataPacket">
+            <remarks>Generic literal data packet.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.LiteralDataPacket.Format">
+            <summary>The format tag value.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.LiteralDataPacket.ModificationTime">
+            <summary>The modification time of the file in milli-seconds (since Jan 1, 1970 UTC)</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.MarkerPacket">
+            <remarks>Basic type for a marker packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.ModDetectionCodePacket">
+            <remarks>Basic packet for a modification detection code packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.MPInteger">
+            <remarks>A multiple precision integer</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OnePassSignaturePacket">
+            <remarks>Generic signature object</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OnePassSignaturePacket.KeyAlgorithm">
+            <summary>The encryption algorithm tag.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OnePassSignaturePacket.HashAlgorithm">
+            <summary>The hash algorithm tag.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PacketTag">
+            <remarks>Basic PGP packet tag types.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag">
+            <remarks>Public Key Algorithm tag numbers.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyEncSessionPacket">
+            <remarks>Basic packet for a PGP public key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicKeyPacket">
+            <remarks>Basic packet for a PGP public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.PublicKeyPacket.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.DateTime,Org.BouncyCastle.Bcpg.IBcpgKey)">
+            <summary>Construct a version 4 public key packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.PublicSubkeyPacket">
+            <remarks>Basic packet for a PGP public subkey</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.PublicSubkeyPacket.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.DateTime,Org.BouncyCastle.Bcpg.IBcpgKey)">
+            <summary>Construct a version 4 public subkey packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey">
+            <remarks>Base class for an RSA public key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.#ctor(Org.BouncyCastle.Bcpg.BcpgInputStream)">
+            <summary>Construct an RSA public key from the passed in stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            <param name="n">The modulus.</param>
+            <param name="e">The public exponent.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.RsaPublicBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey">
+            <remarks>Base class for an RSA secret (or priate) key.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey.GetEncoded">
+            <summary>Return the standard PGP encoding of the key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.RsaSecretBcpgKey.Format">
+            <summary>The format, as a string, always "PGP".</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.S2k">
+            <remarks>The string to key specifier class.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.S2k.GetIV">
+            <summary>The IV for the key generation algorithm.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.HashAlgorithm">
+            <summary>The hash algorithm.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.IterationCount">
+            <summary>The iteration count</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.S2k.ProtectionMode">
+            <summary>The protection mode - only if GnuDummyS2K</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SecretKeyPacket">
+            <remarks>Basic packet for a PGP secret key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SecretSubkeyPacket">
+            <remarks>Basic packet for a PGP secret key.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignaturePacket">
+            <remarks>Generic signature packet.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.#ctor(System.Int32,System.Int64,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag,Org.BouncyCastle.Bcpg.SignatureSubpacket[],Org.BouncyCastle.Bcpg.SignatureSubpacket[],System.Byte[],Org.BouncyCastle.Bcpg.MPInteger[])">
+             Generate a version 4 signature packet.
+            
+             @param signatureType
+             @param keyAlgorithm
+             @param hashAlgorithm
+             @param hashedData
+             @param unhashedData
+             @param fingerprint
+             @param signature
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.#ctor(System.Int32,System.Int32,System.Int64,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag,System.Int64,System.Byte[],Org.BouncyCastle.Bcpg.MPInteger[])">
+             Generate a version 2/3 signature packet.
+            
+             @param signatureType
+             @param keyAlgorithm
+             @param hashAlgorithm
+             @param fingerprint
+             @param signature
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignatureTrailer">
+             return the signature trailer that must be included with the data
+             to reconstruct the signature
+            
+             @return byte[]
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignature">
+            		* return the signature as a set of integers - note this is normalised to be the
+                    * ASN.1 encoding of what appears in the signature packet.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignaturePacket.GetSignatureBytes">
+            Return the byte encoding of the signature section.
+            @return uninterpreted signature bytes.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SignaturePacket.KeyId">
+            return the keyId
+            @return the keyId that created the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SignaturePacket.CreationTime">
+            <summary>Return the creation time in milliseconds since 1 Jan., 1970 UTC.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacket">
+            <remarks>Basic type for a PGP Signature sub-packet.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SignatureSubpacket.GetData">
+            <summary>Return the generic data making up the packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacketsParser">
+            reader for signature sub-packets
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SignatureSubpacketTag">
+            Basic PGP signature sub-packet tag types.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.EmbeddedSignature">
+            Packet embedded signature
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.Exportable">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.IssuerKeyId">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.KeyExpirationTime">
+            packet giving time after creation at which the key expires.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.KeyExpirationTime.Time">
+             Return the number of seconds after creation time a key is valid for.
+            
+             @return second count for key validity.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.KeyFlags">
+            Packet holding the key flag values.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.KeyFlags.Flags">
+            <summary>
+            Return the flag values contained in the first 4 octets (note: at the moment
+            the standard only uses the first one).
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.NotationData">
+            Class provided a NotationData object according to
+            RFC2440, Chapter 5.2.3.15. Notation Data
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.PreferredAlgorithms">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.PrimaryUserId">
+            packet giving whether or not the signature is signed using the primary user ID for the key.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.Revocable">
+            packet giving whether or not is revocable.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RevocationKey">
+            <summary>
+            Represents revocation key OpenPGP signature sub packet.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.RevocationReason">
+            <summary>
+            Represents revocation reason OpenPGP signature sub packet.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignatureCreationTime">
+            packet giving signature creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignatureExpirationTime">
+            packet giving signature expiration time.
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.Sig.SignatureExpirationTime.Time">
+            return time in seconds before signature expires after creation time.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.SignerUserId">
+            packet giving the User ID of the signer.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.Sig.TrustSignature">
+            packet giving trust.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricEncDataPacket">
+            <remarks>Basic type for a symmetric key encrypted packet.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag">
+            Basic tags for symmetric key algorithms
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket">
+            Basic type for a symmetric encrypted session key packet
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.GetSecKeyData">
+            @return byte[]
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.EncAlgorithm">
+            @return int
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.S2k">
+            @return S2k
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.SymmetricKeyEncSessionPacket.Version">
+            @return int
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.TrustPacket">
+            <summary>Basic type for a trust packet.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributePacket">
+            Basic type for a user attribute packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacketsParser">
+            reader for user attribute sub-packets
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserAttributeSubpacketTag">
+            Basic PGP user attribute sub-packet tag types.
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.UserIdPacket">
+            Basic type for a user ID packet.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAttributeTableParameter">
+            <remarks>
+            The 'Signature' parameter is only available when generating unsigned attributes.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedData">
+            containing class for an CMS Authenticated Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetAuthAttrs">
+            return a table of the digested attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetUnauthAttrs">
+            return a table of the undigested attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedData.MacAlgOid">
+            return the object identifier for the content MAC algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator">
+             General class for generating a CMS authenticated-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CMSAuthenticatedDataGenerator  fact = new CMSAuthenticatedDataGenerator();
+            
+                  fact.addKeyTransRecipient(cert);
+            
+                  CMSAuthenticatedData         data = fact.generate(content, algorithm, "BC");
+             </pre>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedGenerator">
+             General class for generating a CMS enveloped-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CMSEnvelopedDataGenerator  fact = new CMSEnvelopedDataGenerator();
+            
+                  fact.addKeyTransRecipient(cert);
+            
+                  CMSEnvelopedData         data = fact.generate(content, algorithm, "BC");
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyTransRecipient(Org.BouncyCastle.X509.X509Certificate)">
+             add a recipient.
+            
+             @param cert recipient's public key certificate
+             @exception ArgumentException if there is a problem with the certificate
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyTransRecipient(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+             add a recipient
+            
+             @param key the public key used by the recipient
+             @param subKeyId the identifier for the recipient's public key
+             @exception ArgumentException if there is a problem with the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKekRecipient(System.String,Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Byte[])">
+            add a KEK recipient.
+            @param key the secret key to use for wrapping
+            @param keyIdentifier the byte string that identifies the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKekRecipient(System.String,Org.BouncyCastle.Crypto.Parameters.KeyParameter,Org.BouncyCastle.Asn1.Cms.KekIdentifier)">
+            add a KEK recipient.
+            @param key the secret key to use for wrapping
+            @param keyIdentifier the byte string that identifies the key
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyAgreementRecipient(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+             Add a key agreement based recipient.
+            
+             @param agreementAlgorithm key agreement algorithm to use.
+             @param senderPrivateKey private key to initialise sender side of agreement with.
+             @param senderPublicKey sender public key to include with message.
+             @param recipientCert recipient's public key certificate.
+             @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+             @exception SecurityUtilityException if the algorithm requested cannot be found
+             @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedGenerator.AddKeyAgreementRecipients(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Collections.ICollection,System.String)">
+             Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
+            
+             @param agreementAlgorithm key agreement algorithm to use.
+             @param senderPrivateKey private key to initialise sender side of agreement with.
+             @param senderPublicKey sender public key to include with message.
+             @param recipientCerts recipients' public key certificates.
+             @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+             @exception SecurityUtilityException if the algorithm requested cannot be found
+             @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+             constructor allowing specific source of randomness
+            
+             @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            constructor allowing specific source of randomness
+            @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            generate an enveloped object that contains an CMS Enveloped Data
+            object using the given provider and the passed in key generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            generate an authenticated object that contains an CMS Authenticated Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser">
+             Parsing class for an CMS Authenticated Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one recipient can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             Example of use - assuming the first recipient matches the private key we have.
+             <pre>
+                  CMSAuthenticatedDataParser     ad = new CMSAuthenticatedDataParser(inputStream);
+            
+                  RecipientInformationStore  recipients = ad.getRecipientInfos();
+            
+                  Collection  c = recipients.getRecipients();
+                  Iterator    it = c.iterator();
+            
+                  if (it.hasNext())
+                  {
+                      RecipientInformation   recipient = (RecipientInformation)it.next();
+            
+                      CMSTypedStream recData = recipient.getContentStream(privateKey, "BC");
+            
+                      processDataStream(recData.getContentStream());
+            
+                      if (!Arrays.equals(ad.getMac(), recipient.getMac())
+                      {
+                          System.err.println("Data corrupted!!!!");
+                      }
+                  }
+              </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsContentInfoParser.Close">
+            Close the underlying data stream.
+            @throws IOException if the close fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetAuthAttrs">
+            return a table of the unauthenticated attributes indexed by
+            the OID of the attribute.
+            @exception java.io.IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.GetUnauthAttrs">
+            return a table of the unauthenticated attributes indexed by
+            the OID of the attribute.
+            @exception java.io.IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.MacAlgOid">
+            return the object identifier for the mac algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsAuthenticatedDataParser.MacAlgParams">
+            return the ASN.1 encoded encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator">
+             General class for generating a CMS authenticated-data message stream.
+             <p>
+             A simple example of usage.
+             <pre>
+                  CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
+            
+                  edGen.addKeyTransRecipient(cert);
+            
+                  ByteArrayOutputStream  bOut = new ByteArrayOutputStream();
+            
+                  OutputStream out = edGen.open(
+                                          bOut, CMSAuthenticatedDataGenerator.AES128_CBC, "BC");*
+                  out.write(data);
+            
+                  out.close();
+             </pre>
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            constructor allowing specific source of randomness
+            @param rand instance of SecureRandom to use
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.SetBerEncodeRecipients(System.Boolean)">
+            Use a BER Set to store the recipient information
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            generate an enveloped object that contains an CMS Enveloped Data
+            object using the given provider and the passed in key generator.
+            @throws java.io.IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsAuthenticatedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Int32)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsAuthEnvelopedData">
+            containing class for an CMS AuthEnveloped Data object
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedData">
+            containing class for an CMS Compressed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetContent">
+             Return the uncompressed content.
+            
+             @return the uncompressed content
+             @throws CmsException if there is an exception uncompressing the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetContent(System.Int32)">
+             Return the uncompressed content, throwing an exception if the data size
+             is greater than the passed in limit. If the content is exceeded getCause()
+             on the CMSException will contain a StreamOverflowException
+            
+             @param limit maximum number of bytes to read
+             @return the content read
+             @throws CMSException if there is an exception uncompressing the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsCompressedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataGenerator">
+                * General class for generating a compressed CMS message.
+                * <p>
+                * A simple example of usage.</p>
+                * <p>
+                * <pre>
+                *      CMSCompressedDataGenerator fact = new CMSCompressedDataGenerator();
+                *      CMSCompressedData data = fact.Generate(content, algorithm);
+                * </pre>
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            Generate an object that contains an CMS Compressed Data
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataParser">
+             Class for reading a CMS Compressed Data stream.
+             <pre>
+                 CMSCompressedDataParser cp = new CMSCompressedDataParser(inputStream);
+            
+                 process(cp.GetContent().GetContentStream());
+             </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                  CMSCompressedDataParser     ep = new CMSCompressedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator">
+             General class for generating a compressed CMS message stream.
+             <p>
+             A simple example of usage.
+             </p>
+             <pre>
+                  CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
+            
+                  Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
+            
+                  cOut.Write(data);
+            
+                  cOut.Close();
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator.#ctor">
+            base constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsCompressedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedData">
+            containing class for an CMS Enveloped Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetUnprotectedAttributes">
+            return a table of the unprotected attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedData.EncryptionAlgOid">
+            return the object identifier for the content encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedData.ContentInfo">
+            return the ContentInfo 
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator">
+             <remarks>
+             General class for generating a CMS enveloped-data message.
+            
+             A simple example of usage.
+            
+             <pre>
+                  CmsEnvelopedDataGenerator  fact = new CmsEnvelopedDataGenerator();
+            
+                  fact.AddKeyTransRecipient(cert);
+            
+                  CmsEnvelopedData         data = fact.Generate(content, algorithm);
+             </pre>
+             </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            <summary>
+            Generate an enveloped object that contains a CMS Enveloped Data
+            object using the passed in key generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String)">
+            <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.String,System.Int32)">
+            <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataParser">
+             Parsing class for an CMS Enveloped Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one recipient can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             Example of use - assuming the first recipient matches the private key we have.
+             <pre>
+                  CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(inputStream);
+            
+                  RecipientInformationStore  recipients = ep.GetRecipientInfos();
+            
+                  Collection  c = recipients.getRecipients();
+                  Iterator    it = c.iterator();
+            
+                  if (it.hasNext())
+                  {
+                      RecipientInformation   recipient = (RecipientInformation)it.next();
+            
+                      CMSTypedStream recData = recipient.getContentStream(privateKey);
+            
+                      processDataStream(recData.getContentStream());
+                  }
+              </pre>
+              Note: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(new BufferedInputStream(inputStream, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.GetRecipientInfos">
+            return a store of the intended recipients for this message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.GetUnprotectedAttributes">
+            return a table of the unprotected attributes indexed by
+            the OID of the attribute.
+            @throws IOException
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.EncryptionAlgOid">
+            return the object identifier for the content encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsEnvelopedDataParser.EncryptionAlgParams">
+            return the ASN.1 encoded encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator">
+             General class for generating a CMS enveloped-data message stream.
+             <p>
+             A simple example of usage.
+             <pre>
+                  CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+            
+                  edGen.AddKeyTransRecipient(cert);
+            
+                  MemoryStream  bOut = new MemoryStream();
+            
+                  Stream out = edGen.Open(
+                                          bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
+                  out.Write(data);
+            
+                  out.Close();
+             </pre>
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.SetBufferSize(System.Int32)">
+            <summary>Set the underlying string size for encapsulated data.</summary>
+            <param name="bufferSize">Length of octet strings to buffer the data.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.SetBerEncodeRecipients(System.Boolean)">
+            <summary>Use a BER Set to store the recipient information.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String,Org.BouncyCastle.Crypto.CipherKeyGenerator)">
+            <summary>
+            Generate an enveloped object that contains an CMS Enveloped Data
+            object using the passed in key generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsEnvelopedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Int32)">
+            generate an enveloped object that contains an CMS Enveloped Data object
+            @throws IOException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.ICipherParameters">
+            all parameter classes implement this.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsProcessable.Write(System.IO.Stream)">
+            <summary>
+            Generic routine to copy out the data we want processed.
+            </summary>
+            <remarks>
+            This routine may be called multiple times.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsProcessableByteArray">
+            a holding class for a byte array of data to be processed.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsProcessableByteArray.GetContent">
+            <returns>A clone of the byte array</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedData">
+             general class for handling a pkcs7-signature message.
+            
+             A simple example of usage - note, in the example below the validity of
+             the certificate isn't verified, just the fact that one of the certs
+             matches the given signer...
+            
+             <pre>
+              IX509Store              certs = s.GetCertificates();
+              SignerInformationStore  signers = s.GetSignerInfos();
+            
+              foreach (SignerInformation signer in signers.GetSigners())
+              {
+                  ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+                  X509Certificate cert = (X509Certificate) certList[0];
+            
+                  if (signer.Verify(cert.GetPublicKey()))
+                  {
+                      verified++;
+                  }
+              }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(System.Collections.IDictionary,System.Byte[])">
+             Content with detached signature, digests precomputed
+            
+             @param hashes a map of precomputed digests for content indexed by name of hash.
+             @param sigBlock the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(Org.BouncyCastle.Cms.CmsProcessable,System.IO.Stream)">
+             base constructor - content with detached signature.
+            
+             @param signedContent the content that was signed.
+             @param sigData the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.#ctor(System.IO.Stream)">
+            base constructor - with encapsulated content
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetSignerInfos">
+            return the collection of signers that are associated with the
+            signatures for the message.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetAttributeCertificates(System.String)">
+             return a X509Store containing the attribute certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of attribute certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetCertificates(System.String)">
+             return a X509Store containing the public key certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of public key certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetCrls(System.String)">
+             return a X509Store containing CRLs, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of CRLs
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.ReplaceSigners(Org.BouncyCastle.Cms.CmsSignedData,Org.BouncyCastle.Cms.SignerInformationStore)">
+             Replace the signerinformation store associated with this
+             CmsSignedData object with the new one passed in. You would
+             probably only want to do this if you wanted to change the unsigned
+             attributes associated with a signer, or perhaps delete one.
+            
+             @param signedData the signed data object to be used as a base.
+             @param signerInformationStore the new signer information store to use.
+             @return a new signed data object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedData.ReplaceCertificatesAndCrls(Org.BouncyCastle.Cms.CmsSignedData,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store)">
+             Replace the certificate and CRL information associated with this
+             CmsSignedData object with the new one passed in.
+            
+             @param signedData the signed data object to be used as a base.
+             @param x509Certs the new certificates to be used.
+             @param x509Crls the new CRLs to be used.
+             @return a new signed data object.
+             @exception CmsException if there is an error processing the stores
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.Version">
+            <summary>Return the version number for this object.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.SignedContentType">
+            <summary>
+            Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+            content info structure carried in the signed data.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedData.ContentInfo">
+            return the ContentInfo
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataGenerator">
+                 * general class for generating a pkcs7-signature message.
+                 * <p>
+                 * A simple example of usage.
+                 *
+                 * <pre>
+                 *      IX509Store certs...
+                 *      IX509Store crls...
+                 *      CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+                 *
+                 *      gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
+                 *      gen.AddCertificates(certs);
+                 *      gen.AddCrls(crls);
+                 *
+                 *      CmsSignedData data = gen.Generate(content);
+                 * </pre>
+            	 * </p>
+        </member>
+        <member name="F:Org.BouncyCastle.Cms.CmsSignedGenerator.Data">
+            Default type for the signed data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.AddAttributeCertificates(Org.BouncyCastle.X509.Store.IX509Store)">
+             Add the attribute certificates contained in the passed in store to the
+             generator.
+            
+             @param store a store of Version 2 attribute certificates
+             @throws CmsException if an error occurse processing the store.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.AddSigners(Org.BouncyCastle.Cms.SignerInformationStore)">
+             Add a store of precalculated signers to the generator.
+            
+             @param signerStore store of signers
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedGenerator.GetGeneratedDigests">
+             Return a map of oids and byte arrays representing the digests calculated on the content during
+             the last generate.
+            
+             @return a map of oids (as String objects) and byte[] representing digests.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+                    * add a signer - no attributes other than the default ones will be
+                    * provided here.
+            		*
+            		* @param key signing key to use
+            		* @param cert certificate containing corresponding public key
+            		* @param digestOID digest algorithm OID
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+             add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+             provided here.
+            
+             @param key signing key to use
+             @param cert certificate containing corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String)">
+            add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+            provided here.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+                    * add a signer with extra signed/unsigned attributes.
+            		*
+            		* @param key signing key to use
+            		* @param cert certificate containing corresponding public key
+            		* @param digestOID digest algorithm OID
+            		* @param signedAttr table of attributes to be included in signature
+            		* @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+            
+             @param key signing key to use
+             @param cert certificate containing corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+             @param signedAttr table of attributes to be included in signature
+             @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            	     * add a signer with extra signed/unsigned attributes.
+            		 *
+            		 * @param key signing key to use
+            		 * @param subjectKeyID subjectKeyID of corresponding public key
+            		 * @param digestOID digest algorithm OID
+            		 * @param signedAttr table of attributes to be included in signature
+            		 * @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+            
+             @param key signing key to use
+             @param subjectKeyID subjectKeyID of corresponding public key
+             @param encryptionOID digest encryption algorithm OID
+             @param digestOID digest algorithm OID
+             @param signedAttr table of attributes to be included in signature
+             @param unsignedAttr table of attributes to be included as unsigned
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String,Org.BouncyCastle.Cms.CmsAttributeTableGenerator,Org.BouncyCastle.Cms.CmsAttributeTableGenerator)">
+            add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable)">
+            generate a signed object that for a CMS Signed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(System.String,Org.BouncyCastle.Cms.CmsProcessable,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object  - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.Generate(Org.BouncyCastle.Cms.CmsProcessable,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data".
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataGenerator.GenerateCounterSigners(Org.BouncyCastle.Cms.SignerInformation)">
+             generate a set of one or more SignerInformation objects representing counter signatures on
+             the passed in SignerInformation object.
+            
+             @param signer the signer to be countersigned
+             @param sigProvider the provider to be used for counter signing.
+             @return a store containing the signers.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataParser">
+             Parsing class for an CMS Signed Data object from an input stream.
+             <p>
+             Note: that because we are in a streaming mode only one signer can be tried and it is important
+             that the methods on the parser are called in the appropriate order.
+             </p>
+             <p>
+             A simple example of usage for an encapsulated signature.
+             </p>
+             <p>
+             Two notes: first, in the example below the validity of
+             the certificate isn't verified, just the fact that one of the certs
+             matches the given signer, and, second, because we are in a streaming
+             mode the order of the operations is important.
+             </p>
+             <pre>
+                  CmsSignedDataParser     sp = new CmsSignedDataParser(encapSigData);
+            
+                  sp.GetSignedContent().Drain();
+            
+                  IX509Store              certs = sp.GetCertificates();
+                  SignerInformationStore  signers = sp.GetSignerInfos();
+            
+                  foreach (SignerInformation signer in signers.GetSigners())
+                  {
+                      ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+                      X509Certificate cert = (X509Certificate) certList[0];
+            
+                      Console.WriteLine("verify returns: " + signer.Verify(cert));
+                  }
+             </pre>
+              Note also: this class does not introduce buffering - if you are processing large files you should create
+              the parser with:
+              <pre>
+                      CmsSignedDataParser     ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+              </pre>
+              where bufSize is a suitably large buffer size.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.#ctor(System.IO.Stream)">
+            base constructor - with encapsulated content
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.#ctor(Org.BouncyCastle.Cms.CmsTypedStream,System.IO.Stream)">
+             base constructor
+            
+             @param signedContent the content that was signed.
+             @param sigData the signature object.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetSignerInfos">
+            return the collection of signers that are associated with the
+            signatures for the message.
+            @throws CmsException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetAttributeCertificates(System.String)">
+             return a X509Store containing the attribute certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of attribute certificates
+             @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetCertificates(System.String)">
+             return a X509Store containing the public key certificates, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of public key certificates
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.GetCrls(System.String)">
+             return a X509Store containing CRLs, if any, contained
+             in this message.
+            
+             @param type type of store to create
+             @return a store of CRLs
+             @exception NoSuchStoreException if the store type isn't available.
+             @exception CmsException if a general exception prevents creation of the X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.ReplaceSigners(System.IO.Stream,Org.BouncyCastle.Cms.SignerInformationStore,System.IO.Stream)">
+            Replace the signerinformation store associated with the passed
+            in message contained in the stream original with the new one passed in.
+            You would probably only want to do this if you wanted to change the unsigned
+            attributes associated with a signer, or perhaps delete one.
+            <p>
+            The output stream is returned unclosed.
+            </p>
+            @param original the signed data stream to be used as a base.
+            @param signerInformationStore the new signer information store to use.
+            @param out the stream to Write the new signed data object to.
+            @return out.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataParser.ReplaceCertificatesAndCrls(System.IO.Stream,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,Org.BouncyCastle.X509.Store.IX509Store,System.IO.Stream)">
+            Replace the certificate and CRL information associated with this
+            CMSSignedData object with the new one passed in.
+            <p>
+            The output stream is returned unclosed.
+            </p>
+            @param original the signed data stream to be used as a base.
+            @param certsAndCrls the new certificates and CRLs to be used.
+            @param out the stream to Write the new signed data object to.
+            @return out.
+            @exception CmsException if there is an error processing the CertStore
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedDataParser.Version">
+             Return the version number for the SignedData object
+            
+             @return the version number
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.CmsSignedDataParser.SignedContentType">
+            <summary>
+            Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+            content info structure carried in the signed data.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator">
+             General class for generating a pkcs7-signature message stream.
+             <p>
+             A simple example of usage.
+             </p>
+             <pre>
+                  IX509Store                   certs...
+                  CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            
+                  gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
+            
+                  gen.AddCertificates(certs);
+            
+                  Stream sigOut = gen.Open(bOut);
+            
+                  sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
+            
+                  sigOut.Close();
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.#ctor(Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Constructor allowing specific source of randomness</summary>
+            <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.SetBufferSize(System.Int32)">
+             Set the underlying string size for encapsulated data
+            
+             @param bufferSize length of octet strings to buffer the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+            add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes - specifying digest
+            encryption algorithm.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,System.String)">
+            add a signer - no attributes other than the default ones will be
+            provided here.
+            @throws NoSuchProviderException
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.AddSigner(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[],System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            add a signer with extra signed/unsigned attributes.
+            @throws NoSuchAlgorithmException
+            @throws InvalidKeyException
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data object
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data".
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.Boolean,System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data
+            object using the given provider - if encapsulate is true a copy
+            of the message will be included in the signature with the
+            default content type "data". If dataOutputStream is non null the data
+            being signed will be written to the stream as it is processed.
+            @param out stream the CMS object is to be written to.
+            @param encapsulate true if data should be encapsulated.
+            @param dataOutputStream output stream to copy the data being signed to.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Boolean)">
+            generate a signed object that for a CMS Signed Data
+            object - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedDataStreamGenerator.Open(System.IO.Stream,System.String,System.Boolean,System.IO.Stream)">
+            generate a signed object that for a CMS Signed Data
+            object using the given provider - if encapsulate is true a copy
+            of the message will be included in the signature. The content type
+            is set according to the OID represented by the string signedContentType.
+            @param out stream the CMS object is to be written to.
+            @param signedContentType OID for data to be signed.
+            @param encapsulate true if data should be encapsulated.
+            @param dataOutputStream output stream to copy the data being signed to.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedHelper.GetDigestAlgName(System.String)">
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.CmsSignedHelper.GetEncryptionAlgName(System.String)">
+            Return the digest encryption algorithm using one of the standard
+            JCA string representations rather than the algorithm identifier (if
+            possible).
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator">
+            Default authenticated attributes generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.#ctor">
+            Initialise to use all defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.#ctor(Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Initialise with some extra attributes or overrides.
+            
+             @param attributeTable initial attribute table to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.CreateStandardAttributeTable(System.Collections.IDictionary)">
+             Create a standard attribute table from the passed in parameters - this will
+             normally include contentType and messageDigest. If the constructor
+             using an AttributeTable was used, entries in it for contentType and
+             messageDigest will override the generated ones.
+            
+             @param parameters source parameters for table generation.
+            
+             @return a filled in IDictionary of attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultAuthenticatedAttributeTableGenerator.GetAttributes(System.Collections.IDictionary)">
+            @param parameters source parameters
+            @return the populated attribute table
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator">
+            Default signed attributes generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.#ctor">
+            Initialise to use all defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.#ctor(Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Initialise with some extra attributes or overrides.
+            
+             @param attributeTable initial attribute table to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.createStandardAttributeTable(System.Collections.IDictionary)">
+             Create a standard attribute table from the passed in parameters - this will
+             normally include contentType, signingTime, and messageDigest. If the constructor
+             using an AttributeTable was used, entries in it for contentType, signingTime, and
+             messageDigest will override the generated ones.
+            
+             @param parameters source parameters for table generation.
+            
+             @return a filled in Hashtable of attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.DefaultSignedAttributeTableGenerator.GetAttributes(System.Collections.IDictionary)">
+            @param parameters source parameters
+            @return the populated attribute table
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInfoGenerator.Generate(Org.BouncyCastle.Crypto.Parameters.KeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate a RecipientInfo object for the given key.
+            </summary>
+            <param name="contentEncryptionKey">
+            A <see cref="T:Org.BouncyCastle.Crypto.Parameters.KeyParameter"/>
+            </param>
+            <param name="random">
+            A <see cref="T:Org.BouncyCastle.Security.SecureRandom"/>
+            </param>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Asn1.Cms.RecipientInfo"/>
+            </returns>
+            <exception cref="T:Org.BouncyCastle.Security.GeneralSecurityException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KekRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using a secret key known to the other side.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformation.GetMac">
+             Return the MAC calculated for the content stream. Note: this call is only meaningful once all
+             the content has been read.
+            
+             @return  byte array containing the mac.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformation.KeyEncryptionAlgOid">
+                    * return the object identifier for the key encryption algorithm.
+                    * 
+            		* @return OID for key encryption algorithm.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformation.KeyEncryptionAlgParams">
+                    * return the ASN.1 encoded key encryption algorithm parameters, or null if
+                    * there aren't any.
+                    * 
+            		* @return ASN.1 encoding of key encryption algorithm parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KekRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KeyAgreeRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using key agreement.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KeyAgreeRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.KeyTransRecipientInformation">
+            the KeyTransRecipientInformation class for a recipient who has been sent a secret
+            key encrypted using their public key that needs to be used to
+            extract the message.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.KeyTransRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return it as a byte array.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.OriginatorID">
+            a basic index for an originator.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertStoreSelector.Policy">
+            <summary>
+            An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.PasswordRecipientInformation">
+            the RecipientInfo class for a recipient who has been sent a message
+            encrypted using a password.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.PasswordRecipientInformation.GetContentStream(Org.BouncyCastle.Crypto.ICipherParameters)">
+            decrypt the content and return an input stream.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.PasswordRecipientInformation.KeyDerivationAlgorithm">
+             return the object identifier for the key derivation algorithm, or null
+             if there is none present.
+            
+             @return OID for key derivation algorithm, if present.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.Pkcs5Scheme2PbeKey">
+            <summary>
+            PKCS5 scheme-2 - password converted to bytes assuming ASCII.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.Pkcs5Scheme2Utf8PbeKey">
+            PKCS5 scheme-2 - password converted to bytes using UTF-8.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetFirstRecipient(Org.BouncyCastle.Cms.RecipientID)">
+             Return the first RecipientInformation object that matches the
+             passed in selector. Null if there are no matches.
+            
+             @param selector to identify a recipient
+             @return a single RecipientInformation object. Null if none matches.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetRecipients">
+             Return all recipients in the collection
+            
+             @return a collection of recipients.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.RecipientInformationStore.GetRecipients(Org.BouncyCastle.Cms.RecipientID)">
+             Return possible empty collection with recipients matching the passed in RecipientID
+            
+             @param selector a recipient id to select against.
+             @return a collection of RecipientInformation objects.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.RecipientInformationStore.Count">
+             Return the number of recipients in the collection.
+            
+             @return number of recipients identified.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SignerID">
+            a basic index for a signer.
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SignerInformation">
+            an expanded SignerInfo block from a CMS Signed message
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetContentDigest">
+            return the content digest that was calculated during verification.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetSignature">
+            return the encoded signature
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetCounterSignatures">
+            Return a SignerInformationStore containing the counter signatures attached to this
+            signer. If no counter signatures are present an empty store is returned.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.GetEncodedSignedAttributes">
+            return the DER encoding of the signed attributes.
+            @throws IOException if an encoding error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            verify that the given public key successfully handles and confirms the
+            signature associated with this signer.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.Verify(Org.BouncyCastle.X509.X509Certificate)">
+            verify that the given certificate successfully handles and confirms
+            the signature associated with this signer and, if a signingTime
+            attribute is available, that the certificate was valid at the time the
+            signature was generated.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.ToSignerInfo">
+             Return the base ASN.1 CMS structure that this object contains.
+            
+             @return an object containing a CMS SignerInfo structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.ReplaceUnsignedAttributes(Org.BouncyCastle.Cms.SignerInformation,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+             Return a signer information object with the passed in unsigned
+             attributes replacing the ones that are current associated with
+             the object passed in.
+            
+             @param signerInformation the signerInfo to be used as the basis.
+             @param unsignedAttributes the unsigned attributes to add.
+             @return a copy of the original SignerInformationObject with the changed attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformation.AddCounterSigners(Org.BouncyCastle.Cms.SignerInformation,Org.BouncyCastle.Cms.SignerInformationStore)">
+             Return a signer information object with passed in SignerInformationStore representing counter
+             signatures attached as an unsigned attribute.
+            
+             @param signerInformation the signerInfo to be used as the basis.
+             @param counterSigners signer info objects carrying counter signature.
+             @return a copy of the original SignerInformationObject with the changed attributes.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.Version">
+            return the version number for this objects underlying SignerInfo structure.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.DigestAlgOid">
+            return the object identifier for the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.DigestAlgParams">
+            return the signature parameters, or null if there aren't any.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.EncryptionAlgOid">
+            return the object identifier for the signature.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.EncryptionAlgParams">
+            return the signature/encryption algorithm parameters, or null if
+            there aren't any.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.SignedAttributes">
+            return a table of the signed attributes - indexed by
+            the OID of the attribute.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformation.UnsignedAttributes">
+            return a table of the unsigned attributes indexed by
+            the OID of the attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetFirstSigner(Org.BouncyCastle.Cms.SignerID)">
+             Return the first SignerInformation object that matches the
+             passed in selector. Null if there are no matches.
+            
+             @param selector to identify a signer
+             @return a single SignerInformation object. Null if none matches.
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetSigners">
+            <returns>An ICollection of all signers in the collection</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Cms.SignerInformationStore.GetSigners(Org.BouncyCastle.Cms.SignerID)">
+             Return possible empty collection with signers matching the passed in SignerID
+            
+             @param selector a signer id to select against.
+             @return a collection of SignerInformation objects.
+        </member>
+        <member name="P:Org.BouncyCastle.Cms.SignerInformationStore.Count">
+            <summary>The number of signers in the collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Cms.SimpleAttributeTableGenerator">
+            Basic generator that just returns a preconstructed attribute table
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.DHAgreement">
+            a Diffie-Hellman key exchange engine.
+            <p>
+            note: This uses MTI/A0 key agreement in order to make the key agreement
+            secure against passive attacks. If you're doing Diffie-Hellman and both
+            parties have long term public keys you should look at using this. For
+            further information have a look at RFC 2631.</p>
+            <p>
+            It's possible to extend this to more than two parties as well, for the moment
+            that is left as an exercise for the reader.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHAgreement.CalculateMessage">
+            calculate our initial message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.Parameters.DHPublicKeyParameters,Org.BouncyCastle.Math.BigInteger)">
+            given a message from a given party and the corresponding public key
+            calculate the next message in the agreement sequence. In this case
+            this will represent the shared secret.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.DHBasicAgreement">
+            a Diffie-Hellman key agreement class.
+            <p>
+            note: This is only the basic algorithm, it doesn't take advantage of
+            long term public keys if they are available. See the DHAgreement class
+            for a "better" implementation.</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBasicAgreement">
+            The basic interface that basic Diffie-Hellman implementations
+            conforms to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBasicAgreement.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+            initialise the agreement engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBasicAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.ICipherParameters)">
+            given a public key from a given party calculate the next
+            message in the agreement sequence.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.DHBasicAgreement.CalculateAgreement(Org.BouncyCastle.Crypto.ICipherParameters)">
+            given a short term public key from a given party calculate the next
+            message in the agreement sequence.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.ECDHBasicAgreement">
+             P1363 7.2.1 ECSVDP-DH
+            
+             ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
+             Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
+             and [Kob87]. This primitive derives a shared secret value from one
+             party's private key and another party's public key, where both have
+             the same set of EC domain parameters. If two parties correctly
+             execute this primitive, they will produce the same output. This
+             primitive can be invoked by a scheme to derive a shared secret key;
+             specifically, it may be used with the schemes ECKAS-DH1 and
+             DL/ECKAS-DH2. It assumes that the input keys are valid (see also
+             Section 7.2.2).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.ECDHCBasicAgreement">
+             P1363 7.2.2 ECSVDP-DHC
+            
+             ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
+             Diffie-Hellman version with cofactor multiplication. It is based on
+             the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
+             primitive derives a shared secret value from one party's private key
+             and another party's public key, where both have the same set of EC
+             domain parameters. If two parties correctly execute this primitive,
+             they will produce the same output. This primitive can be invoked by a
+             scheme to derive a shared secret key; specifically, it may be used
+             with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
+             validity of the input public key (see also Section 7.2.1).
+             <p>
+             Note: As stated P1363 compatibility mode with ECDH can be preset, and
+             in this case the implementation doesn't have a ECDH compatibility mode
+             (if you want that just use ECDHBasicAgreement and note they both implement
+             BasicAgreement!).</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDerivationParameters">
+            Parameters for key/byte stream derivation classes
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Kdf.DHKekGenerator">
+            RFC 2631 Diffie-hellman KEK derivation function.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDerivationFunction">
+            base interface for general purpose byte derivation functions.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IDerivationFunction.Digest">
+            return the message digest used as the basis for the function
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Kdf.ECDHKekGenerator">
+            X9.63 based key derivation function for ECDH CMS.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client">
+            Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+            This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+            "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Security.SecureRandom)">
+            Initialises the client to begin new authentication attempt
+            @param N The safe prime associated with the client's verifier
+            @param g The group parameter associated with the client's verifier
+            @param digest The digest algorithm associated with the client's verifier
+            @param random For key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.GenerateClientCredentials(System.Byte[],System.Byte[],System.Byte[])">
+            Generates client's credentials given the client's salt, identity and password
+            @param salt The salt used in the client's verifier.
+            @param identity The user's identity (eg. username)
+            @param password The user's password
+            @return Client's public value to send to server
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Client.CalculateSecret(Org.BouncyCastle.Math.BigInteger)">
+            Generates client's verification message given the server's credentials
+            @param serverB The server's credentials
+            @return Client's verification message for the server
+            @throws CryptoException If server's credentials are invalid
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server">
+            Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+            This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+            "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest,Org.BouncyCastle.Security.SecureRandom)">
+            Initialises the server to accept a new client authentication attempt
+            @param N The safe prime associated with the client's verifier
+            @param g The group parameter associated with the client's verifier
+            @param v The client's verifier
+            @param digest The digest algorithm associated with the client's verifier
+            @param random For key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.GenerateServerCredentials">
+            Generates the server's credentials that are to be sent to the client.
+            @return The server's public value to the client
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6Server.CalculateSecret(Org.BouncyCastle.Math.BigInteger)">
+            Processes the client's credentials. If valid the shared secret is generated and returned.
+            @param clientA The client's credentials
+            @return A shared secret BigInteger
+            @throws CryptoException If client's credentials are invalid
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator">
+            Generates new SRP verifier for user
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator.Init(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Crypto.IDigest)">
+            Initialises generator to create new verifiers
+            @param N The safe prime to use (see DHParametersGenerator)
+            @param g The group parameter to use (see DHParametersGenerator)
+            @param digest The digest to use. The same digest type will need to be used later for the actual authentication
+            attempt. Also note that the final session key size is dependent on the chosen digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Agreement.Srp.Srp6VerifierGenerator.GenerateVerifier(System.Byte[],System.Byte[],System.Byte[])">
+            Creates a new SRP verifier
+            @param salt The salt to use, generally should be large and random
+            @param identity The user's identifying information (eg. username)
+            @param password The user's password
+            @return A new verifier for use in future SRP authentication
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair">
+            a holding class for public/private parameter pairs.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             basic constructor.
+            
+             @param publicParam a public key parameters object.
+             @param privateParam the corresponding private key parameters.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.Public">
+             return the public key parameters.
+            
+             @return the public key parameters.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.AsymmetricCipherKeyPair.Private">
+             return the private key parameters.
+            
+             @return the private key parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher">
+            The AEAD block ciphers already handle buffering internally, so this class
+            just takes care of implementing IBufferedCipher methods.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBufferedCipher">
+            <remarks>Block cipher engines are expected to conform to this interface.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBufferedCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">If true the cipher is initialised for encryption,
+            if false for decryption.</param>
+            <param name="parameters">The key and other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBufferedCipher.Reset">
+            <summary>
+            Reset the cipher. After resetting the cipher is in the same state
+            as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBufferedCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetBlockSize">
+             return the blocksize for the underlying cipher.
+            
+             @return the blocksize for the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output, or the input is not block size aligned and should be.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+             @exception DataLengthException if the input is not block size
+             aligned.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAeadBlockCipher.Reset">
+            Reset the buffer and cipher. After resetting the object is in the same
+            state as it was after the last init (if there was one).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher">
+            a buffer wrapper for an asymmetric block cipher, allowing input
+            to be accumulated in a piecemeal fashion until final processing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher)">
+             base constructor.
+            
+             @param cipher the cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.GetBufferPosition">
+             return the amount of data sitting in the buffer.
+            
+             @return the amount of data sitting in the buffer.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the buffer and the underlying cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.DoFinal">
+             process the contents of the buffer using the underlying
+             cipher.
+            
+             @return the result of the encryption/decryption process on the
+             buffer.
+             @exception InvalidCipherTextException if we are given a garbage block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedAsymmetricBlockCipher.Reset">
+            <summary>Reset the buffer</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.BufferedBlockCipher">
+            A wrapper class that allows block ciphers to be used to process data in
+            a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+            buffer is full and more data is being added, or on a doFinal.
+            <p>
+            Note: in the case where the underlying cipher is either a CFB cipher or an
+            OFB one the last block may not be a multiple of the block size.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.#ctor">
+            constructor for subclasses
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher without padding.
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+             false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetBlockSize">
+             return the blocksize for the underlying cipher.
+            
+             @return the blocksize for the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output, or the input is not block size aligned and should be.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+             @exception DataLengthException if the input is not block size
+             aligned.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.BufferedBlockCipher.Reset">
+            Reset the buffer and cipher. After resetting the object is in the same
+            state as it was after the last init (if there was one).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.CipherKeyGenerator">
+            The base class for symmetric, or secret, cipher key generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.CipherKeyGenerator.Init(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator.
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.CipherKeyGenerator.GenerateKey">
+             Generate a secret key.
+            
+             @return a byte array containing the key value.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.DataLengthException">
+            this exception is thrown if a buffer that is meant to have output
+            copied into it turns out to be too short, or if we've been given
+            insufficient input. In general this exception will Get thrown rather
+            than an ArrayOutOfBounds exception.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.DataLengthException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.DataLengthException.#ctor(System.String)">
+             create a DataLengthException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.GeneralDigest">
+            base implementation of MD4 family style digest as outlined in
+            "Handbook of Applied Cryptography", pages 344 - 347.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDigest">
+            interface that a message digest conforms to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.GetDigestSize">
+             return the size, in bytes, of the digest produced by this message digest.
+            
+             @return the size, in bytes, of the digest produced by this message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.GetByteLength">
+             return the size, in bytes, of the internal buffer used by this digest.
+            
+             @return the size, in bytes, of the internal buffer used by this digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.Update(System.Byte)">
+             update the message digest with a single byte.
+            
+             @param inByte the input byte to be entered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+             update the message digest with a block of bytes.
+            
+             @param input the byte array containing the data.
+             @param inOff the offset into the byte array where the data starts.
+             @param len the length of the data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.DoFinal(System.Byte[],System.Int32)">
+             Close the digest, producing the final digest value. The doFinal
+             call leaves the digest reset.
+            
+             @param output the array the digest is to be copied into.
+             @param outOff the offset into the out array the digest is to start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDigest.Reset">
+            reset the digest back to it's initial state.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IDigest.AlgorithmName">
+             return the algorithm name
+            
+             @return the algorithm name
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Gost3411Digest">
+            implementation of GOST R 34.11-94
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor(System.Byte[])">
+            Constructor to allow use of a particular sbox with GOST28147
+            @see GOST28147Engine#getSBox(String)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Gost3411Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Digests.Gost3411Digest.C2">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.LongDigest">
+            Base class for SHA-384 and SHA-512.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.#ctor">
+            Constructor for variable length word
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.#ctor(Org.BouncyCastle.Crypto.Digests.LongDigest)">
+            Copy constructor.  We are using copy constructors in place
+            of the object.Clone() interface as this interface is not
+            supported by J2ME.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.LongDigest.AdjustByteCounts">
+            adjust the byte counts so that byteCount2 represents the
+            upper long (less 3 bits) word of the byte count.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD2Digest">
+            implementation of MD2
+            as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.DoFinal(System.Byte[],System.Int32)">
+             Close the digest, producing the final digest value. The doFinal
+             call leaves the digest reset.
+            
+             @param out the array the digest is to be copied into.
+             @param outOff the offset into the out array the digest is to start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.Reset">
+            reset the digest back to it's initial state.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.Update(System.Byte)">
+             update the message digest with a single byte.
+            
+             @param in the input byte to be entered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD2Digest.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+             update the message digest with a block of bytes.
+            
+             @param in the byte array containing the data.
+             @param inOff the offset into the byte array where the data starts.
+             @param len the length of the data.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Digests.MD2Digest.AlgorithmName">
+             return the algorithm name
+            
+             @return the algorithm name
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD4Digest">
+            implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
+            Computer Science and RSA Data Security, Inc.
+            <p>
+            <b>NOTE</b>: This algorithm is only included for backwards compatibility
+            with legacy applications, it's not secure, don't use it for anything new!</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.#ctor(Org.BouncyCastle.Crypto.Digests.MD4Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD4Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.MD5Digest">
+            implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD5Digest.#ctor(Org.BouncyCastle.Crypto.Digests.MD5Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.MD5Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest">
+            implementation of RipeMD128
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD128Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD128Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest">
+            implementation of RipeMD see,
+            http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD160Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD160Digest.Reset">
+            reset the chaining variables to the IV values.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest">
+            <remarks>
+            <p>Implementation of RipeMD256.</p>
+            <p><b>Note:</b> this algorithm offers the same level of security as RipeMD128.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.#ctor">
+            <summary> Standard constructor</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD256Digest)">
+            <summary> Copy constructor.  This will copy the state of the provided
+            message digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD256Digest.Reset">
+            <summary> reset the chaining variables to the IV values.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest">
+            <remarks>
+            <p>Implementation of RipeMD 320.</p>
+            <p><b>Note:</b> this algorithm offers the same level of security as RipeMD160.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.#ctor">
+            <summary> Standard constructor</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.#ctor(Org.BouncyCastle.Crypto.Digests.RipeMD320Digest)">
+            <summary> Copy constructor.  This will copy the state of the provided
+            message digest.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.RipeMD320Digest.Reset">
+            <summary> reset the chaining variables to the IV values.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha1Digest">
+             implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+            
+             It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+             is the "endienness" of the word processing!
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha1Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha1Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha1Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha224Digest">
+            SHA-224 as described in RFC 3874
+            <pre>
+                    block  word  digest
+            SHA-1   512    32    160
+            SHA-224 512    32    224
+            SHA-256 512    32    256
+            SHA-384 1024   64    384
+            SHA-512 1024   64    512
+            </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha224Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha224Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha256Digest">
+             Draft FIPS 180-2 implementation of SHA-256. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha256Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha256Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha256Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha384Digest">
+             Draft FIPS 180-2 implementation of SHA-384. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha384Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha384Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha384Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.Sha512Digest">
+             Draft FIPS 180-2 implementation of SHA-512. <b>Note:</b> As this is
+             based on a draft this implementation is subject to change.
+            
+             <pre>
+                     block  word  digest
+             SHA-1   512    32    160
+             SHA-256 512    32    256
+             SHA-384 1024   64    384
+             SHA-512 1024   64    512
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512Digest.#ctor(Org.BouncyCastle.Crypto.Digests.Sha512Digest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.Sha512Digest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.ShortenedDigest">
+            Wrapper class that reduces the output length of a particular digest to
+            only the first n bytes of the digest function.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.ShortenedDigest.#ctor(Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+             Base constructor.
+            
+             @param baseDigest underlying digest to use.
+             @param length length in bytes of the output of doFinal.
+             @exception ArgumentException if baseDigest is null, or length is greater than baseDigest.GetDigestSize().
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.TigerDigest">
+            implementation of Tiger based on:
+            <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
+             http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.#ctor">
+            Standard constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.#ctor(Org.BouncyCastle.Crypto.Digests.TigerDigest)">
+            Copy constructor.  This will copy the state of the provided
+            message digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.TigerDigest.Reset">
+            reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest">
+             Implementation of WhirlpoolDigest, based on Java source published by Barreto
+             and Rijmen.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest.#ctor(Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest)">
+            Copy constructor. This will copy the state of the provided message
+            digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Digests.WhirlpoolDigest.Reset">
+            Reset the chaining variables
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding">
+            ISO 9796-1 padding. Note in the light of recent results you should
+            only use this with RSA (rather than the "simpler" Rabin keys) and you
+            should never use it with anything other than a hash (ie. even if the
+            message is small don't sign the message, sign it's hash) or some "random"
+            value. See your favorite search engine for details.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher">
+            <remarks>Base interface for a public/private key block cipher.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.GetInputBlockSize">
+            <returns>The maximum size, in bytes, an input block may be.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.GetOutputBlockSize">
+            <returns>The maximum size, in bytes, an output block will be.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+            <summary>Process a block.</summary>
+            <param name="inBuf">The input buffer.</param>
+            <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+            <param name="inLen">The length of the input block.</param>
+            <exception cref="T:Org.BouncyCastle.Crypto.InvalidCipherTextException">Input decrypts improperly.</exception>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">Input is too large for the cipher.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IAsymmetricBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetInputBlockSize">
+            return the input block size. The largest message we can process
+            is (key_size_in_bits + 3)/16, which in our world comes to
+            key_size_in_bytes / 2.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetOutputBlockSize">
+            return the maximum possible size for the output.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.SetPadBits(System.Int32)">
+            set the number of bits in the next message to be treated as
+            pad bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.GetPadBits">
+            retrieve the number of pad bits in the last decoded message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.ISO9796d1Encoding.DecodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.OaepEncoding">
+            Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.decodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block turns out to
+            be badly formatted.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.ItoOSP(System.Int32,System.Byte[])">
+            int to octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.OaepEncoding.maskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            mask generator function, as described in PKCS1v2.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding">
+            this does your basic Pkcs 1 v1.5 padding - whether or not you should be using this
+            depends on your application - see Pkcs1 Version 2 for details.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabledProperty">
+            some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+            work with one of these set the system property Org.BouncyCastle.Pkcs1.Strict to false.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher)">
+            Basic constructor.
+            @param cipher
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.DecodeBlock(System.Byte[],System.Int32,System.Int32)">
+            @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabled">
+            The same effect can be achieved by setting the static property directly
+            <p>
+            The static property is checked during construction of the encoding object, it is set to
+            true by default.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesEngine">
+             an implementation of the AES (Rijndael), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor, they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first.
+            
+             The slowest version uses no static tables at all and computes the values in each round.
+             </p>
+             <p>
+             This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+             </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IBlockCipher">
+            <remarks>Base interface for a symmetric key block cipher.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.GetBlockSize">
+            <returns>The block size for this cipher, in bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            <summary>Process a block.</summary>
+            <param name="inBuf">The input buffer.</param>
+            <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+            <param name="outBuf">The output buffer.</param>
+            <param name="outOff">The offset into <paramref>outBuf</paramref> to write the output block.</param>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">If input block is wrong size, or outBuf too small.</exception>
+            <returns>The number of bytes processed and produced.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IBlockCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IBlockCipher.IsPartialBlockOkay">
+            <summary>Indicates whether this cipher can handle partial blocks.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesFastEngine">
+             an implementation of the AES (Rijndael)), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor), they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations), 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each), for a total of 2Kbytes),
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first
+            
+             The slowest version uses no static tables at all and computes the values in each round
+             </p>
+             <p>
+             This file contains the fast version with 8Kbytes of static tables for round precomputation
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesFastEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesLightEngine">
+             an implementation of the AES (Rijndael), from FIPS-197.
+             <p>
+             For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+            
+             This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+             <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+            
+             There are three levels of tradeoff of speed vs memory
+             Because java has no preprocessor, they are written as three separate classes from which to choose
+            
+             The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+             and 4 for decryption.
+            
+             The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+             adding 12 rotate operations per round to compute the values contained in the other tables from
+             the contents of the first
+            
+             The slowest version uses no static tables at all and computes the values
+             in each round.
+             </p>
+             <p>
+             This file contains the slowest performance version with no static tables
+             for round precomputation, but it has the smallest foot print.
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.GenerateWorkingKey(System.Byte[],System.Boolean)">
+            Calculate the necessary round keys
+            The number of calculations depends on key size and block size
+            AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+            This code is written assuming those are the only possible values
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.AesLightEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an AES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.AesWrapEngine">
+            <remarks>
+            An implementation of the AES Key Wrapper from the NIST Key Wrap Specification.
+            <p/>
+            For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Rfc3394WrapEngine">
+            <remarks>
+            An implementation of the AES Key Wrapper from the NIST Key Wrap
+            Specification as described in RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
+            and  <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+            </remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IWrapper.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.BlowfishEngine">
+            A class that provides Blowfish key encryption operations,
+            such as encoding data and generating keys.
+            All the algorithms herein are from Applied Cryptography
+            and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Blowfish cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.ProcessTable(System.UInt32,System.UInt32,System.UInt32[])">
+            apply the encryption cycle to each value pair in the table.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Encrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.BlowfishEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Decrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaEngine">
+            Camellia - based on RFC 3713.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaLightEngine">
+            Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.CamelliaWrapEngine">
+            <remarks>
+            An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc3657.txt">http://www.ietf.org/rfc/rfc3657.txt</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Cast5Engine">
+             A class that provides CAST key encryption operations,
+             such as encoding data and generating keys.
+            
+             All the algorithms herein are from the Internet RFC's
+            
+             RFC2144 - Cast5 (64bit block, 40-128bit key)
+             RFC2612 - CAST6 (128bit block, 128-256bit key)
+            
+             and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a CAST cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F1(System.UInt32,System.UInt32,System.Int32)">
+             The first of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F2(System.UInt32,System.UInt32,System.Int32)">
+             The second of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.F3(System.UInt32,System.UInt32,System.Int32)">
+             The third of the three processing functions for the
+             encryption and decryption.
+            
+             @param D            the input to be processed
+             @param Kmi        the mask to be used from Km[n]
+             @param Kri        the rotation value to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast5Engine.CAST_Encipher(System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 16 rounds to encrypt the block.
+            
+             @param L0    the LH-32bits of the plaintext block
+             @param R0    the RH-32bits of the plaintext block
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Cast6Engine">
+             A class that provides CAST6 key encryption operations,
+             such as encoding data and generating keys.
+            
+             All the algorithms herein are from the Internet RFC
+            
+             RFC2612 - CAST6 (128bit block, 128-256bit key)
+            
+             and implement a simplified cryptography interface.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param src        The plaintext buffer
+             @param srcIndex    An offset into src
+             @param dst        The ciphertext buffer
+             @param dstIndex    An offset into dst
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.CAST_Encipher(System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 12 quad rounds rounds to encrypt the block.
+            
+             @param A    the 00-31  bits of the plaintext block
+             @param B    the 32-63  bits of the plaintext block
+             @param C    the 64-95  bits of the plaintext block
+             @param D    the 96-127 bits of the plaintext block
+             @param result the resulting ciphertext
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Cast6Engine.CAST_Decipher(System.UInt32,System.UInt32,System.UInt32,System.UInt32,System.UInt32[])">
+             Does the 12 quad rounds rounds to decrypt the block.
+            
+             @param A    the 00-31  bits of the ciphertext block
+             @param B    the 32-63  bits of the ciphertext block
+             @param C    the 64-95  bits of the ciphertext block
+             @param D    the 96-127 bits of the ciphertext block
+             @param result the resulting plaintext
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEdeEngine">
+            <remarks>A class that provides a basic DESede (or Triple DES) engine.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEngine">
+            <remarks>A class that provides a basic DES engine.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a DES cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEngine.bytebit">
+            what follows is mainly taken from "Applied Cryptography", by
+            Bruce Schneier, however it also bears great resemblance to Richard
+            Outerbridge's D3DES...
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.GenerateWorkingKey(System.Boolean,System.Byte[])">
+             Generate an integer based working key based on our secret key
+             and what we processing we are planning to do.
+            
+             Acknowledgements for this routine go to James Gillogly and Phil Karn.
+                     (whoever, and wherever they are!).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEngine.DesFunc(System.Int32[],System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            the DES engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a DESede cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine">
+                * Wrap keys according to
+                * <a href="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
+                * draft-ietf-smime-key-wrap-01.txt</a>.
+                * <p>
+                * Note:
+                * <ul>
+                * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.</li>
+                * <li>if you are using this to wrap triple-des keys you need to set the
+                * parity bits on the key and, if it's a two-key triple-des key, pad it
+                * yourself.</li>
+                * </ul>
+            	* </p>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.engine">
+            Field engine 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.param">
+            Field param 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.paramPlusIV">
+            Field paramPlusIV 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.iv">
+            Field iv 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.forWrapping">
+            Field forWrapping 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.IV2">
+            Field IV2           
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Method init
+            
+             @param forWrapping
+             @param param
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Wrap(System.Byte[],System.Int32,System.Int32)">
+             Method wrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.Unwrap(System.Byte[],System.Int32,System.Int32)">
+             Method unwrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.CalculateCmsKeyChecksum(System.Byte[])">
+             Some key wrap algorithms make use of the Key Checksum defined
+             in CMS [CMS-Algorithms]. This is used to provide an integrity
+             check value for the key being wrapped. The algorithm is
+            
+             - Compute the 20 octet SHA-1 hash on the key being wrapped.
+             - Use the first 8 octets of this hash as the checksum value.
+            
+             @param key
+             @return
+             @throws Exception
+             @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.CheckCmsKeyChecksum(System.Byte[],System.Byte[])">
+            @param key
+            @param checksum
+            @return
+            @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Engines.DesEdeWrapEngine.AlgorithmName">
+             Method GetAlgorithmName
+            
+             @return
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.ElGamalEngine">
+            this does your basic ElGamal algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the ElGamal engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary ElGamal key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For ElGamal this is always one byte less than the size of P on
+             encryption, and twice the length as the size of P on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For ElGamal this is always one byte less than the size of P on
+             decryption, and twice the length as the size of P on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.ElGamalEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic ElGamal algorithm.
+            
+             @param in the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param length the length of the data to be processed.
+             @return the result of the ElGamal process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Gost28147Engine">
+            implementation of GOST 28147-89
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.#ctor">
+            standard constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an Gost28147 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Gost28147Engine.GetSBox(System.String)">
+            Return the S-Box associated with SBoxName
+            @param sBoxName name of the S-Box
+            @return byte array representing the S-Box
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.HC128Engine">
+             HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
+             generates keystream from a 128-bit secret key and a 128-bit initialization
+             vector.
+             <p>
+             http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+             </p><p>
+             It is a third phase candidate in the eStream contest, and is patent-free.
+             No attacks are known as of today (April 2007). See
+            
+             http://www.ecrypt.eu.org/stream/hcp3.html
+             </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IStreamCipher">
+            <summary>The interface stream ciphers conform to.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <param name="forEncryption">If true the cipher is initialised for encryption,
+            if false for decryption.</param>
+            <param name="parameters">The key and other data required by the cipher.</param>
+            <exception cref="T:System.ArgumentException">
+            If the parameters argument is inappropriate.
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.ReturnByte(System.Byte)">
+            <summary>encrypt/decrypt a single byte returning the result.</summary>
+            <param name="input">the byte to be processed.</param>
+            <returns>the result of processing the input byte.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process a block of bytes from <c>input</c> putting the result into <c>output</c>.
+            </summary>
+            <param name="input">The input byte array.</param>
+            <param name="inOff">
+            The offset into <c>input</c> where the data to be processed starts.
+            </param>
+            <param name="length">The number of bytes to be processed.</param>
+            <param name="output">The output buffer the processed bytes go into.</param>
+            <param name="outOff">
+            The offset into <c>output</c> the processed data starts at.
+            </param>
+            <exception cref="T:Org.BouncyCastle.Crypto.DataLengthException">If the output buffer is too small.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IStreamCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IStreamCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.HC128Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise a HC-128 cipher.
+            
+             @param forEncryption whether or not we are for encryption. Irrelevant, as
+                                  encryption and decryption are the same.
+             @param params        the parameters required to set up the cipher.
+             @throws ArgumentException if the params argument is
+                                              inappropriate (ie. the key is not 128 bit long).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.HC256Engine">
+            HC-256 is a software-efficient stream cipher created by Hongjun Wu. It 
+            generates keystream from a 256-bit secret key and a 256-bit initialization 
+            vector.
+            <p>
+            http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+            </p><p>
+            Its brother, HC-128, is a third phase candidate in the eStream contest.
+            The algorithm is patent-free. No attacks are known as of today (April 2007). 
+            See
+            
+            http://www.ecrypt.eu.org/stream/hcp3.html
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.HC256Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise a HC-256 cipher.
+            
+             @param forEncryption whether or not we are for encryption. Irrelevant, as
+                                  encryption and decryption are the same.
+             @param params        the parameters required to set up the cipher.
+             @throws ArgumentException if the params argument is
+                                              inappropriate (ie. the key is not 256 bit long).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.IesEngine">
+            support class for constructing intergrated encryption ciphers
+            for doing basic message exchanges on top of key agreement ciphers
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.#ctor(Org.BouncyCastle.Crypto.IBasicAgreement,Org.BouncyCastle.Crypto.IDerivationFunction,Org.BouncyCastle.Crypto.IMac)">
+             set up for use with stream mode, where the key derivation function
+             is used to provide a stream of bytes to xor with the message.
+            
+             @param agree the key agreement used as the basis for the encryption
+             @param kdf the key derivation function used for byte generation
+             @param mac the message authentication code generator for the message
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.#ctor(Org.BouncyCastle.Crypto.IBasicAgreement,Org.BouncyCastle.Crypto.IDerivationFunction,Org.BouncyCastle.Crypto.IMac,Org.BouncyCastle.Crypto.BufferedBlockCipher)">
+             set up for use in conjunction with a block cipher to handle the
+             message.
+            
+             @param agree the key agreement used as the basis for the encryption
+             @param kdf the key derivation function used for byte generation
+             @param mac the message authentication code generator for the message
+             @param cipher the cipher to used for encrypting the message
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IesEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters,Org.BouncyCastle.Crypto.ICipherParameters,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the encryptor.
+            
+             @param forEncryption whether or not this is encryption/decryption.
+             @param privParam our private key parameters
+             @param pubParam the recipient's/sender's public key parameters
+             @param param encoding and derivation parameters.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.IsaacEngine">
+            Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
+            see: http://www.burtleburtle.net/bob/rand/isaacafa.html
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.IsaacEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise an ISAAC cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine">
+            NaccacheStern Engine. For details on this cipher, please see
+            http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initializes this algorithm. Must be called before all other Functions.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool,
+                  org.bouncycastle.crypto.CipherParameters)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.GetInputBlockSize">
+             Returns the input block size of this algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetInputBlockSize()
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.GetOutputBlockSize">
+             Returns the output block size of this algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetOutputBlockSize()
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single Block using the Naccache-Stern algorithm.
+            
+             @see org.bouncycastle.crypto.AsymmetricBlockCipher#ProcessBlock(byte[],
+                  int, int)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.Encrypt(Org.BouncyCastle.Math.BigInteger)">
+             Encrypts a BigInteger aka Plaintext with the public key.
+            
+             @param plain
+                        The BigInteger to encrypt
+             @return The byte[] representation of the encrypted BigInteger (i.e.
+                     crypted.toByteArray())
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.AddCryptedBlocks(System.Byte[],System.Byte[])">
+             Adds the contents of two encrypted blocks mod sigma
+            
+             @param block1
+                        the first encrypted block
+             @param block2
+                        the second encrypted block
+             @return encrypt((block1 + block2) mod sigma)
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.ProcessData(System.Byte[])">
+             Convenience Method for data exchange with the cipher.
+            
+             Determines blocksize and splits data to blocksize.
+            
+             @param data the data to be processed
+             @return the data after it went through the NaccacheSternEngine.
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NaccacheSternEngine.chineseRemainder(System.Collections.IList,System.Collections.IList)">
+             Computes the integer x that is expressed through the given primes and the
+             congruences with the chinese remainder theorem (CRT).
+            
+             @param congruences
+                        the congruences c_i
+             @param primes
+                        the primes p_i
+             @return an integer x for that x % p_i == c_i
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NoekeonEngine">
+            A Noekeon engine, using direct-key mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.#ctor">
+            Create an instance of the Noekeon encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.NoekeonEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.NullEngine">
+            The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+            Provided for the sake of completeness.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC2Engine">
+            an implementation of RC2 as described in RFC 2268
+                 "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC2 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2Engine.RotateWordLeft(System.Int32,System.Int32)">
+            return the result rotating the 16 bit number in x left by y
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine">
+            Wrap keys according to RFC 3217 - RC2 mechanism
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.engine">
+            Field engine 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.parameters">
+            Field param 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.paramPlusIV">
+            Field paramPlusIV 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.iv">
+            Field iv 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.forWrapping">
+            Field forWrapping 
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.IV2">
+            Field IV2           
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Method init
+            
+             @param forWrapping
+             @param param
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Wrap(System.Byte[],System.Int32,System.Int32)">
+             Method wrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.Unwrap(System.Byte[],System.Int32,System.Int32)">
+             Method unwrap
+            
+             @param in
+             @param inOff
+             @param inLen
+             @return
+             @throws InvalidCipherTextException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.CalculateCmsKeyChecksum(System.Byte[])">
+             Some key wrap algorithms make use of the Key Checksum defined
+             in CMS [CMS-Algorithms]. This is used to provide an integrity
+             check value for the key being wrapped. The algorithm is
+            
+             - Compute the 20 octet SHA-1 hash on the key being wrapped.
+             - Use the first 8 octets of this hash as the checksum value.
+            
+             @param key
+             @return
+             @throws Exception
+             @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.CheckCmsKeyChecksum(System.Byte[],System.Byte[])">
+            @param key
+            @param checksum
+            @return
+            @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Engines.RC2WrapEngine.AlgorithmName">
+             Method GetAlgorithmName
+            
+             @return
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC4Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC4 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC532Engine">
+            The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+            publication in RSA CryptoBytes, Spring of 1995.
+            <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+            <p>
+            This implementation has a word size of 32 bits.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.#ctor">
+            Create an instance of the RC5 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-32 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given block starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param  in     in byte buffer containing data to encrypt
+             @param  inOff  offset into src buffer
+             @param  out     out buffer where encrypted data is written
+             @param  outOff  offset into out buffer
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.RotateLeft(System.Int32,System.Int32)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(32)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % 32
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC532Engine.RotateRight(System.Int32,System.Int32)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(32)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % 32
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC564Engine">
+            The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+            publication in RSA CryptoBytes, Spring of 1995.
+            <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+            <p>
+            This implementation is set to work with a 64 bit word size.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.#ctor">
+            Create an instance of the RC5 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-64 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given block starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+            
+             @param  in      in byte buffer containing data to encrypt
+             @param  inOff   offset into src buffer
+             @param  out     out buffer where encrypted data is written
+             @param  outOff  offset into out buffer
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.RotateLeft(System.Int64,System.Int64)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param  x  word to rotate
+             @param  y    number of bits to rotate % wordSize
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC564Engine.RotateRight(System.Int64,System.Int64)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RC6Engine">
+            An RC6 engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.#ctor">
+            Create an instance of the RC6 encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a RC5-32 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.SetKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param inKey the key to be used
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.RotateLeft(System.Int32,System.Int32)">
+             Perform a left "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RC6Engine.RotateRight(System.Int32,System.Int32)">
+             Perform a right "spin" of the word. The rotation of the given
+             word <em>x</em> is rotated left by <em>y</em> bits.
+             Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+             are used to determine the rotation amount. Here it is
+             assumed that the wordsize used is a power of 2.
+            
+             @param x word to rotate
+             @param y number of bits to rotate % wordSize
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Rfc3211WrapEngine">
+            an implementation of the RFC 3211 Key Wrap
+            Specification.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RijndaelEngine">
+            an implementation of Rijndael, based on the documentation and reference implementation
+            by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
+            <p>
+            Note: this implementation is based on information prior to readonly NIST publication.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Mul0x2(System.Int32)">
+            multiply two elements of GF(2^m)
+            needed for MixColumn and InvMixColumn
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.KeyAddition(System.Int64[])">
+            xor corresponding text input and round key input bytes
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.ShiftRow(System.Byte[])">
+            Row 0 remains unchanged
+            The other three rows are shifted a variable amount
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Substitution(System.Byte[])">
+            Replace every byte of the input by the byte at that place
+            in the nonlinear S-box
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.MixColumn">
+            Mix the bytes of every column in a linear way
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.InvMixColumn">
+            Mix the bytes of every column in a linear way
+            This is the opposite operation of Mixcolumn
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.GenerateWorkingKey(System.Byte[])">
+            Calculate the necessary round keys
+            The number of calculations depends on keyBits and blockBits
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.#ctor">
+            default constructor - 128 bit block size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.#ctor(System.Int32)">
+             basic constructor - set the cipher up for a given blocksize
+            
+             @param blocksize the blocksize in bits, must be 128, 192, or 256.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RijndaelEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Rijndael cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine">
+            this does your basic RSA algorithm with blinding
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindedEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic RSA algorithm.
+            
+             @param inBuf the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine">
+            This does your basic RSA Chaum's blinding and unblinding as outlined in
+            "Handbook of Applied Cryptography", page 475. You need to use this if you are
+            trying to get another party to generate signatures without them being aware
+            of the message they are signing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the blinding engine.
+            
+             @param forEncryption true if we are encrypting (blinding), false otherwise.
+             @param param         the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaBlindingEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the RSA blinding algorithm.
+            
+             @param in    the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @throws DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine">
+            this does your basic RSA algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaCoreEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.RsaEngine">
+            this does your basic RSA algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the RSA engine.
+            
+             @param forEncryption true if we are encrypting, false otherwise.
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.GetInputBlockSize">
+             Return the maximum size for an input block to this engine.
+             For RSA this is always one byte less than the key size on
+             encryption, and the same length as the key size on decryption.
+            
+             @return maximum size for an input block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.GetOutputBlockSize">
+             Return the maximum size for an output block to this engine.
+             For RSA this is always one byte less than the key size on
+             decryption, and the same length as the key size on encryption.
+            
+             @return maximum size for an output block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.RsaEngine.ProcessBlock(System.Byte[],System.Int32,System.Int32)">
+             Process a single block using the basic RSA algorithm.
+            
+             @param inBuf the input array.
+             @param inOff the offset into the input buffer where the data starts.
+             @param inLen the length of the data to be processed.
+             @return the result of the RSA process.
+             @exception DataLengthException the input block is too large.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.Salsa20Engine">
+            Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.StateSize">
+            Constants 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.Salsa20Engine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Salsa20 cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SeedEngine">
+            Implementation of the SEED algorithm as described in RFC 4009
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SeedWrapEngine">
+            <remarks>
+            An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
+            <p/>
+            For further details see: <a href="http://www.ietf.org/rfc/rfc4010.txt">http://www.ietf.org/rfc/rfc4010.txt</a>.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SerpentEngine">
+                * Serpent is a 128-bit 32-round block cipher with variable key lengths,
+                * including 128, 192 and 256 bit keys conjectured to be at least as
+                * secure as three-key triple-DES.
+                * <p>
+                * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
+                * candidate algorithm for the NIST AES Quest.>
+            	* </p>
+                * <p>
+                * For full details see the <a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">The Serpent home page</a>
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Serpent cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.MakeWorkingKey(System.Byte[])">
+             Expand a user-supplied key material into a session key.
+            
+             @param key  The user-key bytes (multiples of 4) to use.
+             @exception ArgumentException
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt one block of plaintext.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Decrypt one block of ciphertext.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb0(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib0(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb1(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib1(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb2(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib2(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb3(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib3(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb4(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib4(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb5(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib5(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb6(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib6(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Sb7(System.Int32,System.Int32,System.Int32,System.Int32)">
+            S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.Ib7(System.Int32,System.Int32,System.Int32,System.Int32)">
+            InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.LT">
+            Apply the linear transformation to the register set.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SerpentEngine.InverseLT">
+            Apply the inverse of the linear transformation to the register set.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.SkipjackEngine">
+            a class that provides a basic SKIPJACK engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a SKIPJACK cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.G(System.Int32,System.Int32)">
+            The G permutation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.SkipjackEngine.H(System.Int32,System.Int32)">
+            the inverse of the G permutation.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.TeaEngine">
+            An TEA engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.#ctor">
+            Create an instance of the TEA encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TeaEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.TwofishEngine">
+             A class that provides Twofish encryption operations.
+            
+             This Java implementation is based on the Java reference
+             implementation provided by Bruce Schneier and developed
+             by Raif S. Naffah.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.TwofishEngine.P_00">
+            Define the fixed p0/p1 permutations used in keyed S-box lookup.
+            By changing the following constant definitions, the S-boxes will
+            automatically Get changed in the Twofish engine.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Engines.TwofishEngine.gSubKeys">
+            gSubKeys[] and gSBox[] are eventually used in the
+            encryption and decryption methods.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise a Twofish cipher.
+            
+             @param forEncryption whether or not we are for encryption.
+             @param parameters the parameters required to set up the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Encrypt the given input starting at the given offset and place
+             the result in the provided buffer starting at the given offset.
+             The input will be an exact multiple of our blocksize.
+            
+             encryptBlock uses the pre-calculated gSBox[] and subKey[]
+             arrays.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+            Decrypt the given input starting at the given offset and place
+            the result in the provided buffer starting at the given offset.
+            The input will be an exact multiple of our blocksize.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.RS_MDS_Encode(System.Int32,System.Int32)">
+             Use (12, 8) Reed-Solomon code over GF(256) to produce
+             a key S-box 32-bit entity from 2 key material 32-bit
+             entities.
+            
+             @param    k0 first 32-bit entity
+             @param    k1 second 32-bit entity
+             @return     Remainder polynomial Generated using RS code
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.TwofishEngine.RS_rem(System.Int32)">
+                    * Reed-Solomon code parameters: (12,8) reversible code:
+            		* <p>
+                    * <pre>
+                    * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+                    * </pre>
+                    * where a = primitive root of field generator 0x14D
+            		* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.VmpcEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            initialise a VMPC cipher.
+            
+            @param forEncryption
+               whether or not we are for encryption.
+            @param params
+               the parameters required to set up the cipher.
+            @exception ArgumentException
+               if the params argument is inappropriate.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Engines.XteaEngine">
+            An XTEA engine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.#ctor">
+            Create an instance of the TEA encryption algorithm
+            and set some defaults
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise
+            
+             @param forEncryption whether or not we are for encryption.
+             @param params the parameters required to set up the cipher.
+             @exception ArgumentException if the params argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Engines.XteaEngine.setKey(System.Byte[])">
+             Re-key the cipher.
+            
+             @param  key  the key to be used
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator">
+            Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on ISO 18033/P1363a.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.#ctor(System.Int32,Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF Parameters generator.
+            
+             @param counterStart value of counter.
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.GenerateBytes(System.Byte[],System.Int32,System.Int32)">
+             fill len bytes of the output buffer with bytes generated from
+             the derivation function.
+            
+             @throws ArgumentException if the size of the request will cause an overflow.
+             @throws DataLengthException if the out buffer is too small.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Generators.BaseKdfBytesGenerator.Digest">
+            return the underlying digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DesKeyGenerator.engineInit(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator - if strength is set to zero
+             the key generated will be 64 bits in size, otherwise
+             strength can be 64 or 56 bits (if you don't count the parity bits).
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DesEdeKeyGenerator.engineInit(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             initialise the key generator - if strength is set to zero
+             the key Generated will be 192 bits in size, otherwise
+             strength can be 128 or 192 (or 112 or 168 if you don't count
+             parity bits), depending on whether you wish to do 2-key or 3-key
+             triple DES.
+            
+             @param param the parameters to be used for key generation
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DHBasicKeyPairGenerator">
+             a basic Diffie-Hellman key pair generator.
+            
+             This generates keys consistent for use with the basic algorithm for
+             Diffie-Hellman.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator">
+            interface that a public/private key pair generator should conform to.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator.Init(Org.BouncyCastle.Crypto.KeyGenerationParameters)">
+             intialise the key pair generator.
+            
+             @param the parameters the key pair is to be initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IAsymmetricCipherKeyPairGenerator.GenerateKeyPair">
+             return an AsymmetricCipherKeyPair containing the Generated keys.
+            
+             @return an AsymmetricCipherKeyPair containing the Generated keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DHKeyPairGenerator">
+             a Diffie-Hellman key pair generator.
+            
+             This generates keys consistent for use in the MTI/A0 key agreement protocol
+             as described in "Handbook of Applied Cryptography", Pages 516-519.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DHParametersGenerator.GenerateParameters">
+            which Generates the p and g values from the given parameters,
+            returning the DHParameters object.
+            <p>
+            Note: can take a while...</p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DsaKeyPairGenerator">
+                 * a DSA key pair generator.
+                 *
+                 * This Generates DSA keys in line with the method described
+            	 * in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator">
+            Generate suitable parameters for DSA, in line with FIPS 186-2.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.Init(System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom)">
+             initialise the key generator.
+            
+             @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
+             @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
+             @param random random byte source.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.GenerateParameters">
+            which Generates the p and g values from the given parameters,
+            returning the DsaParameters object.
+            <p>
+            Note: can take a while...</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.DsaParametersGenerator.GenerateParameters_FIPS186_3">
+            generate suitable parameters for DSA, in line with
+            <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.ECKeyPairGenerator.GenerateKeyPair">
+            Given the domain parameters this routine Generates an EC key
+            pair in accordance with X9.62 section 5.2.1 pages 26, 27.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.ElGamalKeyPairGenerator">
+            a ElGamal key pair generator.
+            <p>
+            This Generates keys consistent for use with ElGamal as described in
+            page 164 of "Handbook of Applied Cryptography".</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.ElGamalParametersGenerator.GenerateParameters">
+                     * which Generates the p and g values from the given parameters,
+                     * returning the ElGamalParameters object.
+                     * <p>
+                     * Note: can take a while...
+            		 * </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Gost3410KeyPairGenerator">
+            a GOST3410 key pair generator.
+            This generates GOST3410 keys in line with the method described
+            in GOST R 34.10-94.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator">
+            generate suitable parameters for GOST3410.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.Init(System.Int32,System.Int32,Org.BouncyCastle.Security.SecureRandom)">
+             initialise the key generator.
+            
+             @param size size of the key
+             @param typeProcedure type procedure A,B = 1;  A',B' - else
+             @param random random byte source.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.procedure_C(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Procedure C
+            procedure generates the a value from the given p,q,
+            returning the a value.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Gost3410ParametersGenerator.GenerateParameters">
+            which generates the p , q and a values from the given parameters,
+            returning the Gost3410Parameters object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Kdf1BytesGenerator">
+            KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on IEEE P1363/ISO 18033.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Kdf1BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF1 byte generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Kdf2BytesGenerator">
+            KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+            <br/>
+            This implementation is based on IEEE P1363/ISO 18033.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Kdf2BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a KDF2 bytes generator. Generates key material
+             according to IEEE P1363 or ISO 18033 depending on the initialisation.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator">
+            Generator for MGF1 as defined in Pkcs 1v2
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+            @param digest the digest to be used as the source of Generated bytes
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.ItoOSP(System.Int32,System.Byte[])">
+            int to octet string.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.GenerateBytes(System.Byte[],System.Int32,System.Int32)">
+             fill len bytes of the output buffer with bytes Generated from
+             the derivation function.
+            
+             @throws DataLengthException if the out buffer is too small.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Generators.Mgf1BytesGenerator.Digest">
+            return the underlying digest.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator">
+             Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator.permuteList(System.Collections.IList,Org.BouncyCastle.Security.SecureRandom)">
+             Generates a permuted ArrayList from the original one. The original List
+             is not modified
+            
+             @param arr
+                        the ArrayList to be permuted
+             @param rand
+                        the source of Randomness for permutation
+             @return a new ArrayList with the permuted elements.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.NaccacheSternKeyPairGenerator.findFirstPrimes(System.Int32)">
+             Finds the first 'count' primes starting with 3
+            
+             @param count
+                        the number of primes to find
+             @return a vector containing the found primes as Integer
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator">
+            Generator for PBE derived keys and ivs as usd by OpenSSL.
+            <p>
+            The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+            iteration count of 1.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.PbeParametersGenerator">
+            super class for all Password Based Encyrption (Pbe) parameter generator classes.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Init(System.Byte[],System.Byte[],System.Int32)">
+             initialise the Pbe generator.
+            
+             @param password the password converted into bytes (see below).
+             @param salt the salt to be mixed with the password.
+             @param iterationCount the number of iterations the "mixing" function
+             is to be applied for.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GetPassword">
+             return the password byte array.
+            
+             @return the password byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GetSalt">
+             return the salt byte array.
+            
+             @return the salt byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate derived parameters for a key of length keySize.
+            
+             @param keySize the length, in bits, of the key required.
+             @return a parameters object representing a key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate derived parameters for a key of length keySize, and
+             an initialisation vector (IV) of length ivSize.
+            
+             @param keySize the length, in bits, of the key required.
+             @param ivSize the length, in bits, of the iv required.
+             @return a parameters object representing a key and an IV.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate derived parameters for a key of length keySize, specifically
+             for use with a MAC.
+            
+             @param keySize the length, in bits, of the key required.
+             @return a parameters object representing a key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs5PasswordToBytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             Pkcs5 (ascii, no padding)
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             PKCS5 (UTF-8, no padding)
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.PbeParametersGenerator.Pkcs12PasswordToBytes(System.Char[])">
+             converts a password to a byte array according to the scheme in
+             Pkcs12 (unicode, big endian, 2 zero pad bytes at the end).
+            
+             @param password a character array representing the password.
+             @return a byte array representing the password.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.PbeParametersGenerator.IterationCount">
+             return the iteration count.
+            
+             @return the iteration count.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.#ctor">
+            Construct a OpenSSL Parameters generator. 
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.Init(System.Byte[],System.Byte[])">
+            Initialise - note the iteration count for this algorithm is fixed at 1.
+            
+            @param password password to use.
+            @param salt salt to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedKey(System.Int32)">
+            the derived key function, the ith hash of the password and the salt.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+             @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.OpenSslPbeParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 12 V1.0.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html">
+            RSA's Pkcs12 Page</a>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a Pkcs 12 Parameters generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+             @exception ArgumentException if an unknown digest is passed in.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.Adjust(System.Byte[],System.Int32,System.Byte[])">
+            add a + b + 1, returning the result in a. The a value is treated
+            as a BigInteger of length (b.Length * 8) bits. The result is
+            modulo 2^b.Length in case of overflow.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedKey(System.Int32,System.Int32)">
+            generation of a derived key ala Pkcs12 V1.0.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs12ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 1.
+            Note this generator is limited to the size of the hash produced by the
+            digest used to drive it.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+            RSA's Pkcs5 Page</a>
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+             Construct a Pkcs 5 Scheme 1 Parameters generator.
+            
+             @param digest the digest to be used as the source of derived keys.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedKey">
+            the derived key function, the ith hash of the mPassword and the mSalt.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the mPassword, mSalt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the mPassword, mSalt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+             @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S1ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the mPassword,
+             mSalt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+             @exception ArgumentException if the key length larger than the base hash size.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator">
+            Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 2.
+            This generator uses a SHA-1 HMac as the calculation function.
+            <p>
+            The document this implementation is based on can be found at
+            <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+            RSA's Pkcs5 Page</a></p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.#ctor">
+            construct a Pkcs5 Scheme 2 Parameters generator.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedParameters(System.Int32)">
+             Generate a key parameter derived from the password, salt, and iteration
+             count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedParameters(System.Int32,System.Int32)">
+             Generate a key with initialisation vector parameter derived from
+             the password, salt, and iteration count we are currently initialised
+             with.
+            
+             @param keySize the size of the key we want (in bits)
+             @param ivSize the size of the iv we want (in bits)
+             @return a ParametersWithIV object.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.Pkcs5S2ParametersGenerator.GenerateDerivedMacParameters(System.Int32)">
+             Generate a key parameter for use with a MAC derived from the password,
+             salt, and iteration count we are currently initialised with.
+            
+             @param keySize the size of the key we want (in bits)
+             @return a KeyParameter object.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator">
+            Generate a random factor suitable for use with RSA blind signatures
+            as outlined in Chaum's blinding and unblinding as outlined in
+            "Handbook of Applied Cryptography", page 475.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the factor generator
+            
+             @param param the necessary RSA key parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Generators.RsaBlindingFactorGenerator.GenerateBlindingFactor">
+             Generate a suitable blind factor for the public key the generator was initialised with.
+            
+             @return a random blind factor
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Generators.RsaKeyPairGenerator">
+            an RSA key pair generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IDsa">
+            interface for classes implementing the Digital Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the signer for signature generation or signature
+             verification.
+            
+             @param forSigning true if we are generating a signature, false
+             otherwise.
+             @param param key parameters for signature generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.GenerateSignature(System.Byte[])">
+             sign the passed in message (usually the output of a hash function).
+            
+             @param message the message to be signed.
+             @return two big integers representing the r and s values respectively.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IDsa.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             verify the message message against the signature values r and s.
+            
+             @param message the message that was supposed to have been signed.
+             @param r the r signature value.
+             @param s the s signature value.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.IMac">
+            The base interface for implementations of message authentication codes (MACs).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Init(Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the MAC.
+            
+             @param param the key and other data required by the MAC.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.GetMacSize">
+             Return the block size for this MAC (in bytes).
+            
+             @return the block size for this MAC in bytes.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Update(System.Byte)">
+             add a single byte to the mac for processing.
+            
+             @param in the byte to be processed.
+             @exception InvalidOperationException if the MAC is not initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            @param in the array containing the input.
+            @param inOff the index in the array the data begins at.
+            @param len the length of the input starting at inOff.
+            @exception InvalidOperationException if the MAC is not initialised.
+            @exception DataLengthException if there isn't enough data in in.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.DoFinal(System.Byte[],System.Int32)">
+            Compute the final stage of the MAC writing the output to the out
+            parameter.
+            <p>
+            doFinal leaves the MAC in the same state it was after the last init.
+            </p>
+            @param out the array the MAC is to be output to.
+            @param outOff the offset into the out buffer the output is to start at.
+            @exception DataLengthException if there isn't enough space in out.
+            @exception InvalidOperationException if the MAC is not initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.IMac.Reset">
+            Reset the MAC. At the end of resetting the MAC should be in the
+            in the same state it was after the last init (if there was one).
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.IMac.AlgorithmName">
+             Return the name of the algorithm the MAC implements.
+            
+             @return the name of the algorithm the MAC implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.InvalidCipherTextException">
+            this exception is thrown whenever we find something we don't expect in a
+            message.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.InvalidCipherTextException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.InvalidCipherTextException.#ctor(System.String)">
+             create a InvalidCipherTextException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the signer for signing or verification.
+            
+             @param forSigning true if for signing, false otherwise
+             @param param necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described
+            in the passed in array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISigner.Reset">
+            reset the internal state
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.ISigner.AlgorithmName">
+             Return the name of the algorithm the signer implements.
+            
+             @return the name of the algorithm the signer implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.ISignerWithRecovery">
+            Signer with message recovery.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage">
+             Returns true if the signer has recovered the full message as
+             part of signature verification.
+            
+             @return true if full message recovered.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage">
+             Returns a reference to what message was recovered (if any).
+            
+             @return full/partial message, null if nothing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.UpdateWithRecoveredMessage(System.Byte[])">
+             Perform an update with the recovered message before adding any other data. This must
+             be the first update method called, and calling it will result in the signer assuming
+             that further calls to update will include message content past what is recoverable.
+            
+             @param signature the signature that we are in the process of verifying.
+             @throws IllegalStateException
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.KeyGenerationParameters">
+            The base class for parameters to key generators.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.KeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32)">
+             initialise the generator with a source of randomness
+             and a strength (in bits).
+            
+             @param random the random byte source.
+             @param strength the size, in bits, of the keys we want to produce.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.KeyGenerationParameters.Random">
+             return the random source associated with this
+             generator.
+            
+             @return the generators random source.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.KeyGenerationParameters.Strength">
+             return the bit strength for keys produced by this generator,
+            
+             @return the strength of the keys this generator produces (in bits).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac">
+            standard CBC Block Cipher MAC - if no padding is specified the default of
+            pad of zeroes is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CBC block cipher. This will produce an
+             authentication code half the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a standard MAC based on a CBC block cipher. This will produce an
+             authentication code half the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CbcBlockCipherMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher">
+            implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Macs.MacCFBBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CFB"
+             and the block size in bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CFB block cipher. This will produce an
+             authentication code half the length of the block size of the cipher, with
+             the CFB mode set to 8 bits.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a standard MAC based on a CFB block cipher. This will produce an
+             authentication code half the length of the block size of the cipher, with
+             the CFB mode set to 8 bits.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,System.Int32)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CFB mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param cfbBitSize the size of an output block produced by the CFB mode.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses CFB mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param cfbBitSize the size of an output block produced by the CFB mode.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding a padding to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CfbBlockCipherMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.CMac">
+            CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+            <p>
+            CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+            </p><p>
+            CMAC is a NIST recomendation - see 
+            csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+            </p><p>
+            CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+            analyzed by Tetsu Iwata and Kaoru Kurosawa.
+            </p><p>
+            CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message 
+            Authentication Code). OMAC stands for One-Key CBC MAC.
+            </p><p>
+            It supports 128- or 64-bits block ciphers, with any key size, and returns
+            a MAC with dimension less or equal to the block size of the underlying 
+            cipher.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+             This will produce an authentication code the length of the block size
+             of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             create a standard MAC based on a block cipher with the size of the
+             MAC been given in bits.
+             <p/>
+             Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+             or 16 bits if being used as a data authenticator (FIPS Publication 113),
+             and in general should be less than the size of the block cipher as it reduces
+             the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            
+             @param cipher        the cipher to be used as the basis of the MAC generation.
+             @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and @lt;= 128.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.CMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.Gost28147Mac">
+            implementation of GOST 28147-89 MAC
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.HMac">
+             HMAC implementation based on RFC2104
+            
+             H(K XOR opad, H(K XOR ipad, text))
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.HMac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac">
+             DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
+            
+             This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
+             class must be changed to protected
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             create a Retail-MAC based on a CBC block cipher. This will produce an
+             authentication code of the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation. This must
+             be DESEngine.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             create a Retail-MAC based on a CBC block cipher. This will produce an
+             authentication code of the length of the block size of the cipher.
+            
+             @param cipher the cipher to be used as the basis of the MAC generation.
+             @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+            create a Retail-MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses single DES CBC mode as the basis for the
+            MAC generation.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+            create a standard MAC based on a block cipher with the size of the
+            MAC been given in bits. This class uses single DES CBC mode as the basis for the
+            MAC generation. The final block is decrypted and then encrypted using the
+            middle and right part of the key.
+            <p>
+            Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+            or 16 bits if being used as a data authenticator (FIPS Publication 113),
+            and in general should be less than the size of the block cipher as it reduces
+            the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+            </p>
+            @param cipher the cipher to be used as the basis of the MAC generation.
+            @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+            @param padding the padding to be used to complete the last block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Macs.ISO9797Alg3Mac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.MaxBytesExceededException">
+            <summary>
+            This exception is thrown whenever a cipher requires a change of key, iv
+            or similar after x amount of bytes enciphered
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher">
+            implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of chaining.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.GetBlockSize">
+             return the block size of the underlying cipher.
+            
+             @return the block size of the underlying cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate chaining step for CBC mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate chaining step for CBC mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the decrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.CbcBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CBC".
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher">
+                * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+                * NIST Special Publication 800-38C.
+                * <p>
+                * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
+            	* </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher">
+            <summary>
+            A block cipher mode that includes authenticated encryption with a streaming mode
+            and optional associated data.</summary>
+            <see cref="T:Org.BouncyCastle.Crypto.Parameters.AeadParameters"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the cipher.</summary>
+            <remarks>Parameter can either be an AeadParameters or a ParametersWithIV object.</remarks>
+            <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+            <param name="parameters">The key or other data required by the cipher.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetBlockSize">
+            <returns>The block size for this cipher, in bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             Encrypt/decrypt a single byte.
+            
+             @param input the byte to be processed.
+             @param outBytes the output buffer the processed byte goes into.
+             @param outOff the offset into the output byte array the processed data starts at.
+             @return the number of bytes written to out.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             Process a block of bytes from in putting the result into out.
+            
+             @param inBytes the input byte array.
+             @param inOff the offset into the in array where the data to be processed starts.
+             @param len the number of bytes to be processed.
+             @param outBytes the output buffer the processed bytes go into.
+             @param outOff the offset into the output byte array the processed data starts at.
+             @return the number of bytes written to out.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Finish the operation either appending or verifying the MAC at the end of the data.
+            
+             @param outBytes space for any resulting output data.
+             @param outOff offset into out to start copying the data at.
+             @return number of bytes written into out.
+             @throws InvalidOperationException if the cipher is in an inappropriate state.
+             @throws InvalidCipherTextException if the MAC fails to match.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetMac">
+             Return the value of the MAC associated with the last stream processed.
+            
+             @return MAC for plaintext data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetUpdateOutputSize(System.Int32)">
+             Return the size of the output buffer required for a ProcessBytes
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to ProcessBytes
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.GetOutputSize(System.Int32)">
+             Return the size of the output buffer required for a ProcessBytes plus a
+             DoFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to ProcessBytes and DoFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.Reset">
+            <summary>
+            Reset the cipher to the same state as it was after the last init (if there was one).
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.IAeadBlockCipher.AlgorithmName">
+            <summary>The name of the algorithm this cipher implements.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CcmBlockCipher.GetMac">
+             Returns a byte array containing the mac calculated as part of the
+             last encrypt or decrypt operation.
+            
+             @return the last mac calculated.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher">
+            implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.CfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/CFB"
+             and the block size in bits.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher">
+            A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+            be used to produce cipher text which is the same outLength as the plain text.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher that uses Cipher Text Stealing
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update of 'length' bytes.
+            
+             @param length the outLength of the input.
+             @return the space required to accommodate a call to update
+             with length bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.GetOutputSize(System.Int32)">
+             return the size of the output buffer required for an update plus a
+             doFinal with an input of length bytes.
+            
+             @param length the outLength of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with length bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param length the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.CtsBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if cipher text decrypts wrongly (in
+             case the exception will never Get thrown).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.EaxBlockCipher">
+            A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and 
+            Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
+            
+            http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
+            
+            EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block 
+            cipher to encrypt and authenticate data. It's on-line (the length of a 
+            message isn't needed to begin processing it), has good performances, it's
+            simple and provably secure (provided the underlying block cipher is secure).
+            
+            Of course, this implementations is NOT thread-safe.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.EaxBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Constructor that accepts an instance of a block cipher engine.
+            
+             @param cipher the engine to use
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.GcmBlockCipher">
+            <summary>
+            Implements the Galois/Counter mode (GCM) detailed in
+            NIST Special Publication 800-38D.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher">
+            implements the GOST 28147 OFB counter mode (GCTR).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             counter mode (must have a 64 bit block size).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param encrypting if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param parameters the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.GetBlockSize">
+             return the block size we are operating at (in bytes).
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.Reset">
+            reset the feedback vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.GOfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/GCTR"
+             and the block size in bits
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher">
+            implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,System.Int32)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+             @param blockSize the block size in bits (note: a multiple of 8)
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.GetBlockSize">
+             return the block size we are operating at (in bytes).
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.Reset">
+            reset the feedback vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.OfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/OFB"
+             and the block size in bits
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher">
+                * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
+                * on top of a simple cipher. This class assumes the IV has been prepended
+                * to the data stream already, and just accomodates the reset after
+                * (blockSize + 2) bytes have been read.
+                * <p>
+                * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
+            	* </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param cipher the block cipher to be used as the basis of the
+             feedback mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.GetBlockSize">
+             return the block size we are operating at.
+            
+             @return the block size we are operating at (in bytes).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.ProcessBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Process one block of input from the array in and write it to
+             the out array.
+            
+             @param in the array containing the input data.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the output data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.Reset">
+            reset the chaining vector back to the IV and reset the underlying
+            cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the cipher and, possibly, the initialisation vector (IV).
+             If an IV isn't passed as part of the parameter, the IV will be all zeros.
+             An IV which is too short is handled in FIPS compliant fashion.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param parameters the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.EncryptByte(System.Byte,System.Int32)">
+            Encrypt one byte of data according to CFB mode.
+            @param data the byte to encrypt
+            @param blockOff offset in the current block
+            @returns the encrypted byte
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.EncryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB IV mode encryption.
+            
+             @param in the array containing the data to be encrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.DecryptBlock(System.Byte[],System.Int32,System.Byte[],System.Int32)">
+             Do the appropriate processing for CFB IV mode decryption.
+            
+             @param in the array containing the data to be decrypted.
+             @param inOff offset into the in array the data starts at.
+             @param out the array the encrypted data will be copied into.
+             @param outOff the offset into the out array the output will start at.
+             @exception DataLengthException if there isn't enough data in in, or
+             space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+             @return the number of bytes processed and produced.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Modes.OpenPgpCfbBlockCipher.AlgorithmName">
+             return the algorithm name and mode.
+            
+             @return the name of the underlying algorithm followed by "/PGPCFB"
+             and the block size in bits.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Modes.SicBlockCipher">
+            Implements the Segmented Integer Counter (SIC) mode on top of a simple
+            block cipher.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.SicBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Basic constructor.
+            
+             @param c the block cipher to be used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Modes.SicBlockCipher.GetUnderlyingCipher">
+             return the underlying block cipher that we are wrapping.
+            
+             @return the underlying block cipher that we are wrapping.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding">
+            Block cipher padders are expected to conform to this interface
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param param parameters, if any required.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+            @exception InvalidCipherTextException if the padding is badly formed
+            or invalid.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding">
+            A padder that adds ISO10126-2 padding to a block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ISO10126d2Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding">
+            A padder that adds the padding according to the scheme referenced in
+            ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random - a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ISO7816d4Padding.PaddingName">
+             Return the name of the algorithm the padder implements.
+            
+             @return the name of the algorithm the padder implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher">
+            A wrapper class that allows block ciphers to be used to process data in
+            a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+            outputs a block only when the buffer is full and more data is being added,
+            or on a doFinal (unless the current block in the buffer is a pad block).
+            The default padding mechanism used is the one outlined in Pkcs5/Pkcs7.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher,Org.BouncyCastle.Crypto.Paddings.IBlockCipherPadding)">
+             Create a buffered block cipher with the desired padding.
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+             @param padding the padding type.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             Create a buffered block cipher Pkcs7 padding
+            
+             @param cipher the underlying block cipher this buffering object wraps.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the cipher.
+            
+             @param forEncryption if true the cipher is initialised for
+              encryption, if false for decryption.
+             @param param the key and other data required by the cipher.
+             @exception ArgumentException if the parameters argument is
+             inappropriate.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.GetOutputSize(System.Int32)">
+             return the minimum size of the output buffer required for an update
+             plus a doFinal with an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update and doFinal
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.GetUpdateOutputSize(System.Int32)">
+             return the size of the output buffer required for an update
+             an input of len bytes.
+            
+             @param len the length of the input.
+             @return the space required to accommodate a call to update
+             with len bytes of input.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+             process a single byte, producing an output block if neccessary.
+            
+             @param in the input byte.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process an array of bytes, producing output if necessary.
+            
+             @param in the input byte array.
+             @param inOff the offset at which the input data starts.
+             @param len the number of bytes to be copied out of the input array.
+             @param out the space for any output that might be produced.
+             @param outOff the offset from which the output will be copied.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there isn't enough space in out.
+             @exception InvalidOperationException if the cipher isn't initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.PaddedBufferedBlockCipher.DoFinal(System.Byte[],System.Int32)">
+             Process the last block in the buffer. If the buffer is currently
+             full and padding needs to be added a call to doFinal will produce
+             2 * GetBlockSize() bytes.
+            
+             @param out the array the block currently being held is copied into.
+             @param outOff the offset at which the copying starts.
+             @return the number of output bytes copied to out.
+             @exception DataLengthException if there is insufficient space in out for
+             the output or we are decrypting and the input is not block size aligned.
+             @exception InvalidOperationException if the underlying cipher is not
+             initialised.
+             @exception InvalidCipherTextException if padding is expected and not found.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding">
+            A padder that adds Pkcs7/Pkcs5 padding to a block.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random - a SecureRandom if available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.Pkcs7Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.TbcPadding">
+            <summary> A padder that adds Trailing-Bit-Compliment padding to a block.
+            <p>
+            This padding pads the block out compliment of the last bit
+            of the plain text.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+            <summary> Initialise the padder.</summary>
+            <param name="random">- a SecureRandom if available.
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.AddPadding(System.Byte[],System.Int32)">
+            <summary> add the pad bytes to the passed in block, returning the
+            number of bytes added.
+            <p>
+            Note: this assumes that the last block of plain text is always
+            passed to it inside in. i.e. if inOff is zero, indicating the
+            entire block is to be overwritten with padding the value of in
+            should be the same as the last block of plain text.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.TbcPadding.PadCount(System.Byte[])">
+            <summary> return the number of pad bytes present in the block.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.TbcPadding.PaddingName">
+            <summary> Return the name of the algorithm the cipher implements.</summary>
+            <returns> the name of the algorithm the cipher implements.
+            </returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.X923Padding">
+            A padder that adds X9.23 padding to a block - if a SecureRandom is
+            passed in random padding is assumed, otherwise padding with zeros is used.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             Initialise the padder.
+            
+             @param random a SecureRandom if one is available.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.AddPadding(System.Byte[],System.Int32)">
+            add the pad bytes to the passed in block, returning the
+            number of bytes added.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.X923Padding.PadCount(System.Byte[])">
+            return the number of pad bytes present in the block.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.X923Padding.PaddingName">
+             Return the name of the algorithm the cipher implements.
+            
+             @return the name of the algorithm the cipher implements.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding">
+            <summary> A padder that adds Null byte padding to a block.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.Init(Org.BouncyCastle.Security.SecureRandom)">
+             <summary> Initialise the padder.
+            
+             </summary>
+             <param name="random">- a SecureRandom if available.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.AddPadding(System.Byte[],System.Int32)">
+            <summary> add the pad bytes to the passed in block, returning the
+            number of bytes added.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.PadCount(System.Byte[])">
+            <summary> return the number of pad bytes present in the block.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Paddings.ZeroBytePadding.PaddingName">
+             <summary> Return the name of the algorithm the cipher implements.
+            
+             </summary>
+             <returns> the name of the algorithm the cipher implements.
+             </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.AeadParameters.#ctor(Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Int32,System.Byte[],System.Byte[])">
+             Base constructor.
+            
+             @param key key to be used by underlying cipher
+             @param macSize macSize in bits
+             @param nonce nonce to be used
+             @param associatedText associated text, if any
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.CcmParameters.#ctor(Org.BouncyCastle.Crypto.Parameters.KeyParameter,System.Int32,System.Byte[],System.Byte[])">
+            Base constructor.
+            
+            @param key key to be used by underlying cipher
+            @param macSize macSize in bits
+            @param nonce nonce to be used
+            @param associatedText associated text, if any
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesParameters.IsWeakKey(System.Byte[],System.Int32)">
+            DES has 16 weak keys.  This method will check
+            if the given DES key material is weak or semi-weak.
+            Key material that is too short is regarded as weak.
+            <p>
+            See <a href="http://www.counterpane.com/applied.html">"Applied
+            Cryptography"</a> by Bruce Schneier for more information.
+            </p>
+            @return true if the given DES key material is weak or semi-weak,
+                false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesParameters.SetOddParity(System.Byte[])">
+             DES Keys use the LSB as the odd parity bit.  This can
+             be used to check for corrupt keys.
+            
+             @param bytes the byte array to set the parity on.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesEdeParameters.IsWeakKey(System.Byte[],System.Int32,System.Int32)">
+             return true if the passed in key is a DES-EDE weak key.
+            
+             @param key bytes making up the key
+             @param offset offset into the byte array the key starts at
+             @param length number of bytes making up the key
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.DesEdeParameters.IsWeakKey(System.Byte[],System.Int32)">
+             return true if the passed in key is a DES-EDE weak key.
+            
+             @param key bytes making up the key
+             @param offset offset into the byte array the key starts at
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.DHParameters.M">
+            <summary>The minimum bitlength of the private value.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.DHParameters.L">
+            <summary>The bitlength of the private value.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.ElGamalParameters.G">
+            return the generator - g
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.ElGamalParameters.L">
+            return private value limit - l
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.IesParameters">
+            parameters for using an integrated cipher in stream mode.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.IesParameters.#ctor(System.Byte[],System.Byte[],System.Int32)">
+            @param derivation the derivation parameter for the KDF function.
+            @param encoding the encoding parameter for the KDF function.
+            @param macKeySize the size of the MAC key (in bits).
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.IesWithCipherParameters.#ctor(System.Byte[],System.Byte[],System.Int32,System.Int32)">
+            @param derivation the derivation parameter for the KDF function.
+            @param encoding the encoding parameter for the KDF function.
+            @param macKeySize the size of the MAC key (in bits).
+            @param cipherKeySize the size of the associated Cipher key (in bits).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.Iso18033KdfParameters">
+            parameters for Key derivation functions for ISO-18033
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.KdfParameters">
+            parameters for Key derivation functions for IEEE P1363a
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.MgfParameters">
+            <remarks>Parameters for mask derivation functions.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters">
+             Parameters for NaccacheStern public private key generation. For details on
+             this cipher, please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32,System.Int32,System.Int32)">
+             Parameters for generating a NaccacheStern KeyPair.
+            
+             @param random
+                        The source of randomness
+             @param strength
+                        The desired strength of the Key in Bits
+             @param certainty
+                        the probability that the generated primes are not really prime
+                        as integer: 2^(-certainty) is then the probability
+             @param countSmallPrimes
+                        How many small key factors are desired
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.#ctor(Org.BouncyCastle.Security.SecureRandom,System.Int32,System.Int32,System.Int32,System.Boolean)">
+             Parameters for a NaccacheStern KeyPair.
+            
+             @param random
+                        The source of randomness
+             @param strength
+                        The desired strength of the Key in Bits
+             @param certainty
+                        the probability that the generated primes are not really prime
+                        as integer: 2^(-certainty) is then the probability
+             @param cntSmallPrimes
+                        How many small key factors are desired
+             @param debug
+                        Turn debugging on or off (reveals secret information, use with
+                        caution)
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.Certainty">
+            @return Returns the certainty.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyGenerationParameters.CountSmallPrimes">
+            @return Returns the countSmallPrimes.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters">
+             Public key parameters for NaccacheStern cipher. For details on this cipher,
+             please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.#ctor(System.Boolean,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            @param privateKey
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.G">
+            @return Returns the g.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.LowerSigmaBound">
+            @return Returns the lowerSigmaBound.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Parameters.NaccacheSternKeyParameters.Modulus">
+            @return Returns the n.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.NaccacheSternPrivateKeyParameters">
+             Private key parameters for NaccacheStern cipher. For details on this cipher,
+             please see
+            
+             http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Parameters.NaccacheSternPrivateKeyParameters.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.Int32,System.Collections.IList,Org.BouncyCastle.Math.BigInteger)">
+             Constructs a NaccacheSternPrivateKey
+            
+             @param g
+                        the public enryption parameter g
+             @param n
+                        the public modulus n = p*q
+             @param lowerSigmaBound
+                        the public lower sigma bound up to which data can be encrypted
+             @param smallPrimes
+                        the small primes, of which sigma is constructed in the right
+                        order
+             @param phi_n
+                        the private modulus phi(n) = (p-1)(q-1)
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Parameters.ParametersWithSalt">
+            <summary> Cipher parameters with a fixed salt value associated with them.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.DigestRandomGenerator">
+            Random generation based on the digest with counter. Calling AddSeedMaterial will
+            always increase the entropy of the hash.
+            <p>
+            Internal access to the digest is synchronized so a single one of these can be shared.
+            </p>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.IRandomGenerator">
+            <remarks>Generic interface for objects generating random bytes.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.AddSeedMaterial(System.Byte[])">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A byte array to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.AddSeedMaterial(System.Int64)">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A long value to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.NextBytes(System.Byte[])">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to be filled.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.IRandomGenerator.NextBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to receive bytes.</param>
+            <param name="start">Index to start filling at.</param>
+            <param name="len">Length of segment to fill.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator">
+            <remarks>
+            Takes bytes generated by an underling RandomGenerator and reverses the order in
+            each small window (of configurable size).
+            <p>
+            Access to internals is synchronized so a single one of these can be shared.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.AddSeedMaterial(System.Byte[])">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A byte array to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.AddSeedMaterial(System.Int64)">
+            <summary>Add more seed material to the generator.</summary>
+            <param name="seed">A long value to be mixed into the generator's state.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.NextBytes(System.Byte[])">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to be filled.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ReversedWindowGenerator.NextBytes(System.Byte[],System.Int32,System.Int32)">
+            <summary>Fill byte array with random values.</summary>
+            <param name="bytes">Array to receive bytes.</param>
+            <param name="start">Index to start filling at.</param>
+            <param name="len">Length of segment to fill.</param>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Prng.ThreadedSeedGenerator">
+            A thread based seed generator - one source of randomness.
+            <p>
+            Based on an idea from Marcus Lippert.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Prng.ThreadedSeedGenerator.GenerateSeed(System.Int32,System.Boolean)">
+            Generate seed bytes. Set fast to false for best quality.
+            <p>
+            If fast is set to true, the code should be round about 8 times faster when
+            generating a long sequence of random bytes. 20 bytes of random values using
+            the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+            it takes round about 2500 ms.
+            </p>
+            @param numBytes the number of bytes to generate
+            @param fast true if fast mode should be used
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator.P">
+            <remarks>
+            Permutation generated by code:
+            <code>
+            // First 1850 fractional digit of Pi number. 
+            byte[] key = new BigInteger("14159265358979323846...5068006422512520511").ToByteArray();
+            s = 0;
+            P = new byte[256];
+            for (int i = 0; i < 256; i++) 
+            {
+                P[i] = (byte) i;
+            }
+            for (int m = 0; m < 768; m++) 
+            {
+                s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
+                byte temp = P[m & 0xff];
+                P[m & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+            } </code>
+            </remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Prng.VmpcRandomGenerator.s">
+            <remarks>Value generated in the same way as <c>P</c>.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.VerifySignature(System.Byte[])">
+            <returns>true if the internal state represents the signature described in the passed in array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaDigestSigner.Reset">
+            <summary>Reset the internal state</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.DsaSigner">
+            The Digital Signature Algorithm - as described in "Handbook of Applied
+            Cryptography", pages 452 - 453.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.GenerateSignature(System.Byte[])">
+             Generate a signature for the given message using the key we were
+             initialised with. For conventional DSA the message should be a SHA-1
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.DsaSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a DSA signature for
+            the passed in message for standard DSA the message should be a
+            SHA-1 hash of the real message to be verified.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECDsaSigner">
+            EC-DSA as described in X9.62
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.GenerateSignature(System.Byte[])">
+             Generate a signature for the given message using the key we were
+             initialised with. For conventional DSA the message should be a SHA-1
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECDsaSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a DSA signature for
+            the passed in message (for standard DSA the message should be
+            a SHA-1 hash of the real message to be verified).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer">
+            GOST R 34.10-2001 Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with. For conventional GOST3410 the message should be a GOST3411
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECGost3410Signer.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a GOST3410 signature for
+            the passed in message (for standard GOST3410 the message should be
+            a GOST3411 hash of the real message to be verified).
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.ECNRSigner">
+            EC-NR as described in IEEE 1363-2000
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECNRSigner.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with.  Generally, the order of the curve should be at
+             least as long as the hash of the message of interest, and with
+             ECNR it *must* be at least as long.
+            
+             @param digest  the digest to be signed.
+             @exception DataLengthException if the digest is longer than the key allows
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.ECNRSigner.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+             return true if the value r and s represent a signature for the
+             message passed in. Generally, the order of the curve should be at
+             least as long as the hash of the message of interest, and with
+             ECNR, it *must* be at least as long.  But just in case the signer
+             applied mod(n) to the longer digest, this implementation will
+             apply mod(n) during verification.
+            
+             @param digest  the digest to be verified.
+             @param r       the r value of the signature.
+             @param s       the s value of the signature.
+             @exception DataLengthException if the digest is longer than the key allows
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the signer for signing or verification.
+            
+             @param forSigning
+                        true if for signing, false otherwise
+             @param parameters
+                        necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using the key
+            we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.GenericSigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described in
+            the passed in array.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.VerifySignature(System.Byte[])">
+            <returns>true if the internal state represents the signature described in the passed in array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410DigestSigner.Reset">
+            <summary>Reset the internal state</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Gost3410Signer">
+            Gost R 34.10-94 Signature Algorithm
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410Signer.GenerateSignature(System.Byte[])">
+             generate a signature for the given message using the key we were
+             initialised with. For conventional Gost3410 the message should be a Gost3411
+             hash of the message of interest.
+            
+             @param message the message that will be verified later.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Gost3410Signer.VerifySignature(System.Byte[],Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            return true if the value r and s represent a Gost3410 signature for
+            the passed in message for standard Gost3410 the message should be a
+            Gost3411 hash of the real message to be verified.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner">
+            <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
+            <p>
+            Note: the usual length for the salt is the length of the hash
+            function used in bytes.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.GetRecoveredMessage">
+            <summary>
+            Return a reference to the recoveredMessage message.
+            </summary>
+            <returns>The full/partial recoveredMessage message.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32,System.Boolean)">
+            <summary>
+            Generate a signer for the with either implicit or explicit trailers
+            for ISO9796-2, scheme 2 or 3.
+            </summary>
+            <param name="cipher">base cipher to use for signature creation/verification</param>
+            <param name="digest">digest to use.</param>
+            <param name="saltLength">length of salt in bytes.</param>
+            <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+             <summary> Constructor for a signer with an explicit digest trailer.
+            
+             </summary>
+             <param name="cipher">cipher to use.
+             </param>
+             <param name="digest">digest to sign with.
+             </param>
+             <param name="saltLength">length of salt in bytes.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+            <summary>Initialise the signer.</summary>
+            <param name="forSigning">true if for signing, false if for verification.</param>
+            <param name="parameters">parameters for signature generation/verification. If the
+            parameters are for generation they should be a ParametersWithRandom,
+            a ParametersWithSalt, or just an RsaKeyParameters object. If RsaKeyParameters
+            are passed in a SecureRandom will be created.
+            </param>
+            <exception cref="T:System.ArgumentException">if wrong parameter type or a fixed
+            salt is passed in which is the wrong length.
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.IsSameAs(System.Byte[],System.Byte[])">
+            <summary> compare two byte arrays - constant time.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.GenerateSignature">
+            <summary> Generate a signature for the loaded message using the key we were
+            initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.VerifySignature(System.Byte[])">
+            <summary> return true if the signature represents a ISO9796-2 signature
+            for the passed in message.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.HasFullMessage">
+            <summary>
+            Return true if the full message was recoveredMessage.
+            </summary>
+            <returns>true on full message recovery, false otherwise, or if not sure.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.ItoOSP(System.Int32,System.Byte[])">
+            <summary> int to octet string.</summary>
+            <summary> int to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.LtoOSP(System.Int64,System.Byte[])">
+            <summary> long to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2PssSigner.MaskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary> mask generator function, as described in Pkcs1v2.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer">
+            <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 1)</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.GetRecoveredMessage">
+            <summary>
+            Return a reference to the recoveredMessage message.
+            </summary>
+            <returns>The full/partial recoveredMessage message.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.GetRecoveredMessage"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Boolean)">
+            <summary>
+            Generate a signer for the with either implicit or explicit trailers
+            for ISO9796-2.
+            </summary>
+            <param name="cipher">base cipher to use for signature creation/verification</param>
+            <param name="digest">digest to use.</param>
+            <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest)">
+             <summary> Constructor for a signer with an explicit digest trailer.
+            
+             </summary>
+             <param name="cipher">cipher to use.
+             </param>
+             <param name="digest">digest to sign with.
+             </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.IsSameAs(System.Byte[],System.Byte[])">
+            <summary> compare two byte arrays - constant time.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.GenerateSignature">
+            <summary> Generate a signature for the loaded message using the key we were
+            initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.VerifySignature(System.Byte[])">
+            <summary> return true if the signature represents a ISO9796-2 signature
+            for the passed in message.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.Iso9796d2Signer.HasFullMessage">
+            <summary>
+            Return true if the full message was recoveredMessage.
+            </summary>
+            <returns> true on full message recovery, false otherwise.</returns>
+            <seealso cref="M:Org.BouncyCastle.Crypto.ISignerWithRecovery.HasFullMessage"/>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Signers.PssSigner">
+            <summary> RSA-PSS as described in Pkcs# 1 v 2.1.
+            <p>
+            Note: the usual value for the salt length is the number of
+            bytes in the hash function.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.#ctor(Org.BouncyCastle.Crypto.IAsymmetricBlockCipher,Org.BouncyCastle.Crypto.IDigest,System.Int32)">
+            <summary>Basic constructor</summary>
+            <param name="cipher">the asymmetric cipher to use.</param>
+            <param name="digest">the digest to use.</param>
+            <param name="saltLen">the length of the salt to use (in bytes).</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.ClearBlock(System.Byte[])">
+            <summary> clear possible sensitive data</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.Update(System.Byte)">
+            <summary> update the internal digest with the byte b</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <summary> update the internal digest with the byte array in</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.Reset">
+            <summary> reset the internal state</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.GenerateSignature">
+            <summary> Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.VerifySignature(System.Byte[])">
+            <summary> return true if the internal state represents the signature described
+            in the passed in array.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.ItoOSP(System.Int32,System.Byte[])">
+            <summary> int to octet string.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.PssSigner.MaskGeneratorFunction1(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary> mask generator function, as described in Pkcs1v2.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.#cctor">
+            <summary>
+            Load oid table.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             Initialise the signer for signing or verification.
+            
+             @param forSigning true if for signing, false otherwise
+             @param param necessary parameters.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.Update(System.Byte)">
+            update the internal digest with the byte b
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            update the internal digest with the byte array in
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.GenerateSignature">
+            Generate a signature for the message we've been loaded with using
+            the key we were initialised with.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Signers.RsaDigestSigner.VerifySignature(System.Byte[])">
+            return true if the internal state represents the signature described
+            in the passed in array.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.StreamBlockCipher">
+            a wrapper for block ciphers with a single byte block size, so that they
+            can be treated like stream ciphers.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.#ctor(Org.BouncyCastle.Crypto.IBlockCipher)">
+             basic constructor.
+            
+             @param cipher the block cipher to be wrapped.
+             @exception ArgumentException if the cipher has a block size other than
+             one.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.Init(System.Boolean,Org.BouncyCastle.Crypto.ICipherParameters)">
+             initialise the underlying cipher.
+            
+             @param forEncryption true if we are setting up for encryption, false otherwise.
+             @param param the necessary parameters for the underlying cipher to be initialised.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.ReturnByte(System.Byte)">
+             encrypt/decrypt a single byte returning the result.
+            
+             @param in the byte to be processed.
+             @return the result of processing the input byte.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+             process a block of bytes from in putting the result into out.
+            
+             @param in the input byte array.
+             @param inOff the offset into the in array where the data to be processed starts.
+             @param len the number of bytes to be processed.
+             @param out the output buffer the processed bytes go into.
+             @param outOff the offset into the output byte array the processed data stars at.
+             @exception DataLengthException if the output buffer is too small.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.StreamBlockCipher.Reset">
+            reset the underlying cipher. This leaves it in the same state
+            it was at after the last init (if there was one).
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.StreamBlockCipher.AlgorithmName">
+             return the name of the algorithm we are wrapping.
+            
+             @return the name of the algorithm we are wrapping.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.AlertDescription">
+            <summary>
+            RFC 2246 7.2
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.AlertLevel">
+            <summary>
+            RFC 2246 7.2
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.AlwaysValidVerifyer">
+            <remarks>
+            A certificate verifyer, that will always return true.
+            <pre>
+            DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
+            </pre>
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ICertificateVerifyer">
+            <remarks>
+            This should be implemented by any class which can find out, if a given
+            certificate chain is being accepted by an client.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ICertificateVerifyer.IsValid(Org.BouncyCastle.Asn1.X509.X509CertificateStructure[])">
+            <param name="certs">The certs, which are part of the chain.</param>
+            <returns>True, if the chain is accepted, false otherwise</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.AlwaysValidVerifyer.IsValid(Org.BouncyCastle.Asn1.X509.X509CertificateStructure[])">
+            <summary>Return true.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ByteQueue">
+            <remarks>
+            A queue for bytes.
+            <p>
+            This file could be more optimized.
+            </p>
+            </remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.InitBufSize">
+            The initial size for our buffer.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.NextTwoPow(System.Int32)">
+            <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.databuf">
+            The buffer where we store our data.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.skipped">
+            How many bytes at the beginning of the buffer are skipped.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ByteQueue.available">
+            How many bytes in the buffer are valid data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.Read(System.Byte[],System.Int32,System.Int32,System.Int32)">
+            <summary>Read data from the buffer.</summary>
+            <param name="buf">The buffer where the read data will be copied to.</param>
+            <param name="offset">How many bytes to skip at the beginning of buf.</param>
+            <param name="len">How many bytes to read at all.</param>
+            <param name="skip">How many bytes from our data to skip.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.AddData(System.Byte[],System.Int32,System.Int32)">
+            <summary>Add some data to our buffer.</summary>
+            <param name="data">A byte-array to read data from.</param>
+            <param name="offset">How many bytes to skip at the beginning of the array.</param>
+            <param name="len">How many bytes to read from the array.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.ByteQueue.RemoveData(System.Int32)">
+            <summary>Remove some bytes from our data from the beginning.</summary>
+            <param name="i">How many bytes to remove.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.ByteQueue.Available">
+            <summary>The number of bytes which are available in this buffer.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.Certificate">
+            A representation for a certificate chain.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.Certificate.certs">
+            The certificates.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.Parse(System.IO.Stream)">
+             Parse the ServerCertificate message.
+            
+             @param inStr The stream where to parse from.
+             @return A Certificate object with the certs, the server has sended.
+             @throws IOException If something goes wrong during parsing.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.Encode(System.IO.Stream)">
+             Encodes version of the ClientCertificate message
+            
+             @param outStr stream to write the message to
+             @throws IOException If something goes wrong
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.#ctor(Org.BouncyCastle.Asn1.X509.X509CertificateStructure[])">
+             Private constructor from a cert array.
+            
+             @param certs The certs the chain should contain.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Certificate.GetCerts">
+            <returns>An array which contains the certs, this chain contains.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CertificateRequest.CertificateAuthorities">
+            <returns>A <see cref="T:System.Collections.IList"/> of X509Name</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CipherSuite">
+            <summary>
+            RFC 2246 A.5
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ClientCertificateType">
+            <summary>
+            RFC 2246 7.4.4
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CombinedHash">
+            <remarks>A combined hash, which implements md5(m) || sha1(m).</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.GetByteLength">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.GetByteLength"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.GetDigestSize">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.GetDigestSize"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.Update(System.Byte)">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.Update(System.Byte)"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.BlockUpdate(System.Byte[],System.Int32,System.Int32)">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.BlockUpdate(System.Byte[],System.Int32,System.Int32)"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.DoFinal(System.Byte[],System.Int32)">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.DoFinal(System.Byte[],System.Int32)"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.CombinedHash.Reset">
+            <seealso cref="M:Org.BouncyCastle.Crypto.IDigest.Reset"/>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.CombinedHash.AlgorithmName">
+            <seealso cref="P:Org.BouncyCastle.Crypto.IDigest.AlgorithmName"/>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod">
+            <summary>
+            RFC 2246 6.1
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ContentType">
+            <summary>
+            RFC 2246 6.2.1
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAgreementCredentials.GenerateAgreement(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipherFactory.CreateCipher(Org.BouncyCastle.Crypto.Tls.TlsClientContext,Org.BouncyCastle.Crypto.Tls.EncryptionAlgorithm,Org.BouncyCastle.Crypto.Tls.DigestAlgorithm)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateAesCipher(Org.BouncyCastle.Crypto.Tls.TlsClientContext,System.Int32,Org.BouncyCastle.Crypto.Tls.DigestAlgorithm)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateDesEdeCipher(Org.BouncyCastle.Crypto.Tls.TlsClientContext,System.Int32,Org.BouncyCastle.Crypto.Tls.DigestAlgorithm)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.DefaultTlsCipherFactory.CreateDigest(Org.BouncyCastle.Crypto.Tls.DigestAlgorithm)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.Init(Org.BouncyCastle.Crypto.Tls.TlsClientContext)">
+            <summary>
+            Called at the start of a new TLS session, before any other methods.
+            </summary>
+            <param name="context">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCipherSuites">
+            <summary>
+            Get the list of cipher suites that this client supports.
+            </summary>
+            <returns>
+            An array of <see cref="T:Org.BouncyCastle.Crypto.Tls.CipherSuite"/>, each specifying a supported cipher suite.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCompressionMethods">
+            <summary>
+            Get the list of compression methods that this client supports.
+            </summary>
+            <returns>
+            An array of <see cref="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod"/>, each specifying a supported compression method.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetClientExtensions">
+            <summary>
+            Get the (optional) table of client extensions to be included in (extended) client hello.
+            </summary>
+            <returns>
+            A <see cref="T:System.Collections.IDictionary"/> (<see cref="T:Org.BouncyCastle.Crypto.Tls.ExtensionType"/> -> byte[]). May be null.
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySessionID(System.Byte[])">
+            <summary>
+            Reports the session ID once it has been determined.
+            </summary>
+            <param name="sessionID">
+            A <see cref="T:System.Byte"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySelectedCipherSuite(Org.BouncyCastle.Crypto.Tls.CipherSuite)">
+            <summary>
+            Report the cipher suite that was selected by the server.
+            </summary>
+            <remarks>
+            The protocol handler validates this value against the offered cipher suites
+            <seealso cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCipherSuites"/>
+            </remarks>
+            <param name="selectedCipherSuite">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CipherSuite"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySelectedCompressionMethod(Org.BouncyCastle.Crypto.Tls.CompressionMethod)">
+            <summary>
+            Report the compression method that was selected by the server.
+            </summary>
+            <remarks>
+            The protocol handler validates this value against the offered compression methods
+            <seealso cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCompressionMethods"/>
+            </remarks>
+            <param name="selectedCompressionMethod">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CompressionMethod"/>
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.NotifySecureRenegotiation(System.Boolean)">
+            <summary>
+            Report whether the server supports secure renegotiation
+            </summary>
+            <remarks>
+            The protocol handler automatically processes the relevant extensions
+            </remarks>
+            <param name="secureRenegotiation">
+            A <see cref="T:System.Boolean"/>, true if the server supports secure renegotiation
+            </param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.ProcessServerExtensions(System.Collections.IDictionary)">
+            <summary>
+            Report the extensions from an extended server hello.
+            </summary>
+            <remarks>
+            Will only be called if we returned a non-null result from <see cref="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetClientExtensions"/>.
+            </remarks>
+            <param name="serverExtensions">
+            A <see cref="T:System.Collections.IDictionary"/>  (<see cref="T:Org.BouncyCastle.Crypto.Tls.ExtensionType"/> -> byte[])
+            </param>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetKeyExchange">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange"/> to negotiate the key exchange
+            part of the protocol.
+            </summary>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetAuthentication">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsAuthentication"/> to handle authentication
+            part of the protocol.
+            </summary>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCompression">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCompression"/> to handle record compression.
+            </summary>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsClient.GetCipher">
+            <summary>
+            Return an implementation of <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCipher"/> to use for encryption/decryption.
+            </summary>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCipher"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsSignerCredentials.GenerateCertificateSignature(System.Byte[])">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ECCurveType">
+            <summary>
+            RFC 4492 5.4
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.explicit_prime">
+            Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+            underlying finite field is a prime field.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.explicit_char2">
+            Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+            underlying finite field is a characteristic-2 field.
+        </member>
+        <member name="F:Org.BouncyCastle.Crypto.Tls.ECCurveType.named_curve">
+            Indicates that a named curve is used. This option SHOULD be used when applicable.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ECPointFormat">
+            <summary>
+            RFC 4492 5.1.2
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.ExtensionType">
+            <summary>
+            RFC 4366 2.3
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.HandshakeType">
+            <summary>
+            RFC 2246 7.4
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.LegacyTlsAuthentication">
+            <summary>
+            A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAuthentication.NotifyServerCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <summary>
+            Called by the protocol handler to report the server certificate.
+            </summary>
+            <remarks>
+            This method is responsible for certificate verification and validation
+            </remarks>
+            <param name="serverCertificate">The server <see cref="T:Org.BouncyCastle.Crypto.Tls.Certificate"/> received</param>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsAuthentication.GetClientCredentials(Org.BouncyCastle.Crypto.Tls.CertificateRequest)">
+            <summary>
+            Return client credentials in response to server's certificate request
+            </summary>
+            <param name="certificateRequest">
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.CertificateRequest"/> containing server certificate request details
+            </param>
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Crypto.Tls.TlsCredentials"/> to be used for client authentication
+            (or <c>null</c> for no client authentication)
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.LegacyTlsClient">
+            <summary>
+            A temporary class to use LegacyTlsAuthentication 
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.NamedCurve">
+            <summary>
+            RFC 4492 5.1.1
+            The named curves defined here are those specified in SEC 2 [13]. Note that many of
+            these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
+            through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
+            client supports arbitrary prime and characteristic-2 curves, respectively (the curve
+            parameters must be encoded explicitly in ECParameters).
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.RecordStream">
+            <remarks>An implementation of the TLS 1.0 record layer.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.Ssl3Mac">
+            HMAC implementation based on original internet draft for HMAC (RFC 2104)
+            
+            The difference is that padding is concatentated versus XORed with the key
+            
+            H(K + opad, H(K + ipad, text))
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Ssl3Mac.#ctor(Org.BouncyCastle.Crypto.IDigest)">
+            Base constructor for one of the standard digest algorithms that the byteLength of
+            the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
+            
+            @param digest the digest.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.Ssl3Mac.Reset">
+            Reset the mac generator.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsBlockCipher">
+            <summary>
+            A generic TLS 1.0 block cipher. This can be used for AES or 3DES for example.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipher.EncodePlaintext(Org.BouncyCastle.Crypto.Tls.ContentType,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsCipher.DecodeCiphertext(Org.BouncyCastle.Crypto.Tls.ContentType,System.Byte[],System.Int32,System.Int32)">
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsDHKeyExchange">
+            <summary>
+            TLS 1.0 DH key exchange.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange">
+            <summary>
+            A generic interface for key exchange implementations in TLS 1.0.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipServerCertificate">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessServerCertificate(Org.BouncyCastle.Crypto.Tls.Certificate)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipServerKeyExchange">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessServerKeyExchange(System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ValidateCertificateRequest(Org.BouncyCastle.Crypto.Tls.CertificateRequest)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.SkipClientCredentials">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.ProcessClientCredentials(Org.BouncyCastle.Crypto.Tls.TlsCredentials)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.GenerateClientKeyExchange(System.IO.Stream)">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsKeyExchange.GeneratePremasterSecret">
+            <exception cref="T:System.IO.IOException"/>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsECDheKeyExchange">
+            ECDHE key exchange (see RFC 4492)
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsECDHKeyExchange">
+            ECDH key exchange (see RFC 4492)
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsMac">
+            <remarks>
+            A generic TLS MAC implementation, which can be used with any kind of
+            IDigest to act as an HMAC.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.#ctor(Org.BouncyCastle.Crypto.IDigest,System.Byte[],System.Int32,System.Int32)">
+             Generate a new instance of an TlsMac.
+            
+             @param digest    The digest to use.
+             @param key_block A byte-array where the key for this mac is located.
+             @param offset    The number of bytes to skip, before the key starts in the buffer.
+             @param len       The length of the key.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.GetMacSecret">
+            @return the MAC write secret
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.IncSequenceNumber">
+            Increment the current write sequence number
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsMac.CalculateMac(Org.BouncyCastle.Crypto.Tls.ContentType,System.Byte[],System.Int32,System.Int32)">
+             Calculate the mac for some given data.
+             <p/>
+             TlsMac will keep track of the sequence number internally.
+            
+             @param type    The message type of the message.
+             @param message A byte-buffer containing the message.
+             @param offset  The number of bytes to skip, before the message starts.
+             @param len     The length of the message.
+             @return A new byte-buffer containing the mac value.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsMac.SequenceNumber">
+            @return the current write sequence number
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsMac.Size">
+            @return The Keysize of the mac.
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsNullCipher">
+            <summary>
+            A NULL cipher suite, for use during handshake.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler">
+            <remarks>An implementation of all high level protocols in TLS 1.0.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.#ctor(System.IO.Stream,System.IO.Stream)">
+            <remarks>Both streams can be the same object</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.#ctor(System.IO.Stream,System.IO.Stream,Org.BouncyCastle.Security.SecureRandom)">
+            <remarks>Both streams can be the same object</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.ProcessChangeCipherSpec">
+             This method is called, when a change cipher spec message is received.
+            
+             @throws IOException If the message has an invalid content or the
+                                 handshake is not in the correct state.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.Connect(Org.BouncyCastle.Crypto.Tls.ICertificateVerifyer)">
+            <summary>Connects to the remote system.</summary>
+            <param name="verifyer">Will be used when a certificate is received to verify
+            that this certificate is accepted by the client.</param>
+            <exception cref="T:System.IO.IOException">If handshake was not successful</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.ReadApplicationData(System.Byte[],System.Int32,System.Int32)">
+             Read data from the network. The method will return immediately, if there is
+             still some data left in the buffer, or block until some application
+             data has been read from the network.
+            
+             @param buf    The buffer where the data will be copied to.
+             @param offset The position where the data will be placed in the buffer.
+             @param len    The maximum number of bytes to read.
+             @return The number of bytes read.
+             @throws IOException If something goes wrong during reading data.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.WriteData(System.Byte[],System.Int32,System.Int32)">
+             Send some application data to the remote system.
+             <p/>
+             The method will handle fragmentation internally.
+            
+             @param buf    The buffer with the data.
+             @param offset The position in the buffer where the data is placed.
+             @param len    The length of the data.
+             @throws IOException If something goes wrong during sending.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.FailWithError(Org.BouncyCastle.Crypto.Tls.AlertLevel,Org.BouncyCastle.Crypto.Tls.AlertDescription)">
+             Terminate this connection with an alert.
+             <p/>
+             Can be used for normal closure too.
+            
+             @param alertLevel       The level of the alert, an be AlertLevel.fatal or AL_warning.
+             @param alertDescription The exact alert message.
+             @throws IOException If alert was fatal.
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.Close">
+            <summary>Closes this connection</summary>
+            <exception cref="T:System.IO.IOException">If something goes wrong during closing.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.AssertEmpty(System.IO.MemoryStream)">
+             Make sure the Stream is now empty. Fail otherwise.
+            
+             @param is The Stream to check.
+             @throws IOException If is is not empty.
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.OutputStream">
+            <summary>A Stream which can be used to send data.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.InputStream">
+            <summary>A Stream which can be used to read data.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Crypto.Tls.TlsProtocolHandler.Stream">
+            <summary>The secure bidirectional stream for this connection</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsRsaKeyExchange">
+            <summary>
+            TLS 1.0 RSA key exchange.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsSrpKeyExchange">
+            <summary>
+            TLS 1.1 SRP key exchange.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Crypto.Tls.TlsUtilities">
+            <remarks>Some helper fuctions for MicroTLS.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.AddMagnitudes(System.Int32[],System.Int32[])">
+            return a = a + b - b preserved.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.CompareTo(System.Int32,System.Int32[],System.Int32,System.Int32[])">
+            unsigned comparison on two arrays - note the arrays may
+            start with leading zeros.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Divide(System.Int32[],System.Int32[])">
+            return z = x / y - done in place (z value preserved, x contains the
+            remainder)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.IsProbablePrime(System.Int32)">
+            return whether or not a BigInteger is probably prime with a
+            probability of 1 - (1/2)**certainty.
+            <p>From Knuth Vol 2, pg 395.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ExtEuclid(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger@)">
+             Calculate the numbers u1, u2, and u3 such that:
+            
+             u1 * a + u2 * b = u3
+            
+             where u3 is the greatest common divider of a and b.
+             a and b using the extended Euclid algorithm (refer p. 323
+             of The Art of Computer Programming vol 2, 2nd ed).
+             This also seems to have the side effect of calculating
+             some form of multiplicative inverse.
+            
+             @param a    First number to calculate gcd for
+             @param b    Second number to calculate gcd for
+             @param u1Out      the return object for the u1 value
+             @param u2Out      the return object for the u2 value
+             @return     The greatest common divisor of a and b
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Square(System.Int32[],System.Int32[])">
+            return w with w = x * x - w is assumed to have enough space.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Multiply(System.Int32[],System.Int32[],System.Int32[])">
+            return x with x = y * z - x is assumed to have enough space.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.GetMQuote">
+            Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.MultiplyMonty(System.Int32[],System.Int32[],System.Int32[],System.Int32[],System.Int64)">
+            Montgomery multiplication: a = x * y * R^(-1) mod m
+            <br/>
+            Based algorithm 14.36 of Handbook of Applied Cryptography.
+            <br/>
+            <li> m, x, y should have length n </li>
+            <li> a should have length (n + 1) </li>
+            <li> b = 2^32, R = b^n </li>
+            <br/>
+            The result is put in x
+            <br/>
+            NOTE: the indices of x, y, m, a different in HAC and in Java
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Remainder(System.Int32[],System.Int32[])">
+            return x = x % y - done in place (y value preserved)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftLeft(System.Int32[],System.Int32)">
+            do a left shift - this returns a new array.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftRightInPlace(System.Int32,System.Int32[],System.Int32)">
+            do a right shift - this does it in place.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.ShiftRightOneInPlace(System.Int32,System.Int32[])">
+            do a right shift by one - this does it in place.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.BigInteger.Subtract(System.Int32,System.Int32[],System.Int32,System.Int32[])">
+            returns x = x - y - we assume x is >= y
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal">
+            Class representing a simple version of a big decimal. A
+            <code>SimpleBigDecimal</code> is basically a
+            {@link java.math.BigInteger BigInteger} with a few digits on the right of
+            the decimal point. The number of (binary) digits on the right of the decimal
+            point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
+            Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
+            automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
+            taking part in the same arithmetic operation must have equal scale. The
+            result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
+            <code>SimpleBigDecimal</code> with double scale.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal.GetInstance(Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            Returns a <code>SimpleBigDecimal</code> representing the same numerical
+            value as <code>value</code>.
+            @param value The value of the <code>SimpleBigDecimal</code> to be
+            created. 
+            @param scale The scale of the <code>SimpleBigDecimal</code> to be
+            created. 
+            @return The such created <code>SimpleBigDecimal</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal.#ctor(Org.BouncyCastle.Math.BigInteger,System.Int32)">
+            Constructor for <code>SimpleBigDecimal</code>. The value of the
+            constructed <code>SimpleBigDecimal</code> Equals <code>bigInt / 
+            2<sup>scale</sup></code>.
+            @param bigInt The <code>bigInt</code> value parameter.
+            @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.Tnaf">
+            Class holding methods for point multiplication based on the window
+            τ-adic nonadjacent form (WTNAF). The algorithms are based on the
+            paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
+            by Jerome A. Solinas. The paper first appeared in the Proceedings of
+            Crypto 1997.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Width">
+            The window width of WTNAF. The standard value of 4 is slightly less
+            than optimal for running time, but keeps space requirements for
+            precomputation low. For typical curves, a value of 5 or 6 results in
+            a better running time. When changing this value, the
+            <code>α<sub>u</sub></code>'s must be computed differently, see
+            e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
+            Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
+            p. 121-122
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Pow2Width">
+            2<sup>4</sup>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha0">
+            The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+            of <code>ZTauElement</code>s.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha0Tnaf">
+            The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+            of TNAFs.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha1">
+            The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+            of <code>ZTauElement</code>s.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.Tnaf.Alpha1Tnaf">
+            The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+            of TNAFs.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Norm(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Computes the norm of an element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return The norm of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Norm(System.SByte,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal)">
+            Computes the norm of an element <code>λ</code> of
+            <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code>
+            and <code>u</code> and <code>u</code> are real numbers (elements of
+            <code><b>R</b></code>). 
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param u The real part of the element <code>λ</code> of
+            <code><b>R</b>[τ]</code>.
+            @param v The <code>τ</code>-adic part of the element
+            <code>λ</code> of <code><b>R</b>[τ]</code>.
+            @return The norm of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Round(Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,Org.BouncyCastle.Math.EC.Abc.SimpleBigDecimal,System.SByte)">
+            Rounds an element <code>λ</code> of <code><b>R</b>[τ]</code>
+            to an element of <code><b>Z</b>[τ]</code>, such that their difference
+            has minimal norm. <code>λ</code> is given as
+            <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>.
+            @param lambda0 The component <code>λ<sub>0</sub></code>.
+            @param lambda1 The component <code>λ<sub>1</sub></code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve. Must
+            equal 1 or -1.
+            @return The rounded element of <code><b>Z</b>[τ]</code>.
+            @throws ArgumentException if <code>lambda0</code> and
+            <code>lambda1</code> do not have same scale.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.ApproximateDivisionByN(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,System.SByte,System.Int32,System.Int32)">
+            Approximate division by <code>n</code>. For an integer
+            <code>k</code>, the value <code>λ = s k / n</code> is
+            computed to <code>c</code> bits of accuracy.
+            @param k The parameter <code>k</code>.
+            @param s The curve parameter <code>s<sub>0</sub></code> or
+            <code>s<sub>1</sub></code>.
+            @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @param m The bit length of the finite field
+            <code><b>F</b><sub>m</sub></code>.
+            @param c The number of bits of accuracy, i.e. the scale of the returned
+            <code>SimpleBigDecimal</code>.
+            @return The value <code>λ = s k / n</code> computed to
+            <code>c</code> bits of accuracy.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.TauAdicNaf(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Computes the <code>τ</code>-adic NAF (non-adjacent form) of an
+            element <code>λ</code> of <code><b>Z</b>[τ]</code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return The <code>τ</code>-adic NAF of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.Tau(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Applies the operation <code>τ()</code> to an
+            <code>F2mPoint</code>. 
+            @param p The F2mPoint to which <code>τ()</code> is applied.
+            @return <code>τ(p)</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetMu(Org.BouncyCastle.Math.EC.F2mCurve)">
+            Returns the parameter <code>μ</code> of the elliptic curve.
+            @param curve The elliptic curve from which to obtain <code>μ</code>.
+            The curve must be a Koblitz curve, i.e. <code>a</code> Equals
+            <code>0</code> or <code>1</code> and <code>b</code> Equals
+            <code>1</code>. 
+            @return <code>μ</code> of the elliptic curve.
+            @throws ArgumentException if the given ECCurve is not a Koblitz
+            curve.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetLucas(System.SByte,System.Int32,System.Boolean)">
+            Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
+            <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
+            <code>V<sub>k</sub></code>.
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param k The index of the second element of the Lucas Sequence to be
+            returned.
+            @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
+            <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
+            <code>U<sub>k</sub></code>.
+            @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
+            and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
+            and <code>V<sub>k</sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetTw(System.SByte,System.Int32)">
+            Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
+            4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
+            <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code> 
+            @param mu The parameter <code>μ</code> of the elliptic curve.
+            @param w The window width of the WTNAF.
+            @return the auxiliary value <code>t<sub>w</sub></code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetSi(Org.BouncyCastle.Math.EC.F2mCurve)">
+            Computes the auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction. 
+            @param curve The elliptic curve for which to compute
+            <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
+            @throws ArgumentException if <code>curve</code> is not a
+            Koblitz curve (Anomalous Binary Curve, ABC).
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.PartModReduction(Org.BouncyCastle.Math.BigInteger,System.Int32,System.SByte,Org.BouncyCastle.Math.BigInteger[],System.SByte,System.SByte)">
+            Partial modular reduction modulo
+            <code>(τ<sup>m</sup> - 1)/(τ - 1)</code>.
+            @param k The integer to be reduced.
+            @param m The bitlength of the underlying finite field.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @param s The auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code>.
+            @param mu The parameter μ of the elliptic curve.
+            @param c The precision (number of bits of accuracy) of the partial
+            modular reduction.
+            @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 1)</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyRTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.BigInteger)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by a <code>BigInteger</code> using the reduced <code>τ</code>-adic
+            NAF (RTNAF) method.
+            @param p The F2mPoint to Multiply.
+            @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
+            @return <code>k * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.EC.Abc.ZTauElement)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the <code>τ</code>-adic NAF (TNAF) method.
+            @param p The F2mPoint to Multiply.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @return <code>λ * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.MultiplyFromTnaf(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte[])">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
+            of <code>λ</code>.
+            @param p The F2mPoint to Multiply.
+            @param u The the TNAF of <code>λ</code>..
+            @return <code>λ * p</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.TauAdicWNaf(System.SByte,Org.BouncyCastle.Math.EC.Abc.ZTauElement,System.SByte,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Abc.ZTauElement[])">
+            Computes the <code>[τ]</code>-adic window NAF of an element
+            <code>λ</code> of <code><b>Z</b>[τ]</code>.
+            @param mu The parameter μ of the elliptic curve.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code> of which to compute the
+            <code>[τ]</code>-adic NAF.
+            @param width The window width of the resulting WNAF.
+            @param pow2w 2<sup>width</sup>.
+            @param tw The auxiliary value <code>t<sub>w</sub></code>.
+            @param alpha The <code>α<sub>u</sub></code>'s for the window width.
+            @return The <code>[τ]</code>-adic window NAF of
+            <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.Tnaf.GetPreComp(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte)">
+            Does the precomputation for WTNAF multiplication.
+            @param p The <code>ECPoint</code> for which to do the precomputation.
+            @param a The parameter <code>a</code> of the elliptic curve.
+            @return The precomputation array for <code>p</code>. 
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Abc.ZTauElement">
+            Class representing an element of <code><b>Z</b>[τ]</code>. Let
+            <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then
+            <code>λ</code> is given as <code>λ = u + vτ</code>. The
+            components <code>u</code> and <code>v</code> may be used directly, there
+            are no accessor methods.
+            Immutable class.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.ZTauElement.u">
+            The "real" part of <code>λ</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Abc.ZTauElement.v">
+            The "<code>τ</code>-adic" part of <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Abc.ZTauElement.#ctor(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for an element <code>λ</code> of
+            <code><b>Z</b>[τ]</code>.
+            @param u The "real" part of <code>λ</code>.
+            @param v The "<code>τ</code>-adic" part of
+            <code>λ</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.ECCurve">
+            <remarks>Base class for an elliptic curve.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECCurveBase.DecodePoint(System.Byte[])">
+            Decode a point on this curve from its ASN.1 encoding. The different
+            encodings are taken account of, including point compression for
+            <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
+            @return The decoded point.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.FpCurve">
+            Elliptic curve over Fp
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mCurve">
+            Elliptic curves over F2m. The Weierstrass equation is given by
+            <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.m">
+            The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k1">
+            TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction polynomial
+            <code>f(z)</code>.<br/>
+            PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k2">
+            TPB: Always set to <code>0</code><br/>
+            PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.k3">
+            TPB: Always set to <code>0</code><br/>
+            PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.n">
+            The order of the base point of the curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.h">
+            The cofactor of the curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.infinity">
+            The point at infinity on this curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.mu">
+            The parameter <code>μ</code> of the elliptic curve if this is
+            a Koblitz curve.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mCurve.si">
+            The auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction for
+            Koblitz curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Trinomial Polynomial Basis (TPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Trinomial Polynomial Basis (TPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param n The order of the main subgroup of the elliptic curve.
+            @param h The cofactor of the elliptic curve, i.e.
+            <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Pentanomial Polynomial Basis (PPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Pentanomial Polynomial Basis (PPB).
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param a The coefficient <code>a</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param b The coefficient <code>b</code> in the Weierstrass equation
+            for non-supersingular elliptic curves over
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param n The order of the main subgroup of the elliptic curve.
+            @param h The cofactor of the elliptic curve, i.e.
+            <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.GetMu">
+            Returns the parameter <code>μ</code> of the elliptic curve.
+            @return <code>μ</code> of the elliptic curve.
+            @throws ArgumentException if the given ECCurve is not a
+            Koblitz curve.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.GetSi">
+            @return the auxiliary values <code>s<sub>0</sub></code> and
+            <code>s<sub>1</sub></code> used for partial modular reduction for
+            Koblitz curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.solveQuadradicEquation(Org.BouncyCastle.Math.EC.ECFieldElement)">
+             Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+             D.1.6) The other solution is <code>z + 1</code>.
+            
+             @param beta
+                        The value to solve the qradratic equation for.
+             @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+                     <code>null</code> if no solution exists.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mCurve.IsTrinomial">
+             Return true if curve uses a Trinomial basis.
+            
+             @return true if curve Trinomial, false otherwise.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mCurve.IsKoblitz">
+            Returns true if this is a Koblitz curve (ABC curve).
+            @return true if this is a Koblitz curve (ABC curve), false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpFieldElement.Sqrt">
+            return a sqrt root - the routine verifies that the calculation
+            returns the right value - if none exists it returns null.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.FpFieldElement.FieldName">
+             return the field name for this field.
+            
+             @return the string "Fp".
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mFieldElement">
+            Class representing the Elements of the finite field
+            <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
+            representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
+            basis representations are supported. Gaussian normal basis (GNB)
+            representation is not supported.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Gnb">
+            Indicates gaussian normal basis representation (GNB). Number chosen
+            according to X9.62. GNB is not implemented at present.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Tpb">
+            Indicates trinomial basis representation (Tpb). Number chosen
+            according to X9.62.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.Ppb">
+            Indicates pentanomial basis representation (Ppb). Number chosen
+            according to X9.62.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.representation">
+            Tpb or Ppb.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.m">
+            The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.k1">
+            Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction polynomial
+            <code>f(z)</code>.<br/>
+            Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.k2">
+            Tpb: Always set to <code>0</code><br/>
+            Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.k3">
+            Tpb: Always set to <code>0</code><br/>
+            Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.x">
+            The <code>IntArray</code> holding the bits.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.F2mFieldElement.t">
+            The number of <code>int</code>s required to hold <code>m</code> bits.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.#ctor(System.Int32,System.Int32,System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Ppb.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.
+            @param x The BigInteger representing the value of the field element.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.#ctor(System.Int32,System.Int32,Org.BouncyCastle.Math.BigInteger)">
+            Constructor for Tpb.
+            @param m  The exponent <code>m</code> of
+            <code>F<sub>2<sup>m</sup></sub></code>.
+            @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction
+            polynomial <code>f(z)</code>.
+            @param x The BigInteger representing the value of the field element.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mFieldElement.CheckFieldElements(Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            Checks, if the ECFieldElements <code>a</code> and <code>b</code>
+            are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
+            (having the same representation).
+            @param a field element.
+            @param b field element to be compared.
+            @throws ArgumentException if <code>a</code> and <code>b</code>
+            are not elements of the same field
+            <code>F<sub>2<sup>m</sup></sub></code> (having the same
+            representation).
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.Representation">
+            @return the representation of the field
+            <code>F<sub>2<sup>m</sup></sub></code>, either of
+            {@link F2mFieldElement.Tpb} (trinomial
+            basis representation) or
+            {@link F2mFieldElement.Ppb} (pentanomial
+            basis representation).
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.M">
+            @return the degree <code>m</code> of the reduction polynomial
+            <code>f(z)</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K1">
+            @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
+            x<sup>k</sup> + 1</code> represents the reduction polynomial
+            <code>f(z)</code>.<br/>
+            Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K2">
+            @return Tpb: Always returns <code>0</code><br/>
+            Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="P:Org.BouncyCastle.Math.EC.F2mFieldElement.K3">
+            @return Tpb: Always set to <code>0</code><br/>
+            Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            represents the reduction polynomial <code>f(z)</code>.<br/>
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.ECPoint">
+            base class for points on elliptic curves.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPoint.SetPreCompInfo(Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Sets the <code>PreCompInfo</code>. Used by <code>ECMultiplier</code>s
+            to save the precomputation for this <code>ECPoint</code> to store the
+            precomputation result for use by subsequent multiplication.
+            @param preCompInfo The values precomputed by the
+            <code>ECMultiplier</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPoint.AssertECMultiplier">
+            Sets the appropriate <code>ECMultiplier</code>, unless already set. 
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPointBase.GetEncoded">
+            return the field element encoded with point compression. (S 4.3.6)
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.ECPointBase.Multiply(Org.BouncyCastle.Math.BigInteger)">
+            Multiplies this <code>ECPoint</code> by the given number.
+            @param k The multiplicator.
+            @return <code>k * this</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.FpPoint">
+            Elliptic curve points over Fp
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+             Create a point which encodes with point compression.
+            
+             @param curve the curve to use
+             @param x affine x co-ordinate
+             @param y affine y co-ordinate
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+             Create a point that encodes with or without point compresion.
+            
+             @param curve the curve to use
+             @param x affine x co-ordinate
+             @param y affine y co-ordinate
+             @param withCompression if true encode with point compression
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.FpPoint.AssertECMultiplier">
+            Sets the default <code>ECMultiplier</code>, unless already set. 
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.F2mPoint">
+            Elliptic curve points over F2m
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement)">
+            @param curve base curve
+            @param x x point
+            @param y y point
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve,Org.BouncyCastle.Math.EC.ECFieldElement,Org.BouncyCastle.Math.EC.ECFieldElement,System.Boolean)">
+            @param curve base curve
+            @param x x point
+            @param y y point
+            @param withCompression true if encode with point compression.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.#ctor(Org.BouncyCastle.Math.EC.ECCurve)">
+            Constructor for point at infinity
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.CheckPoints(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.EC.ECPoint)">
+            Check, if two <code>ECPoint</code>s can be added or subtracted.
+            @param a The first <code>ECPoint</code> to check.
+            @param b The second <code>ECPoint</code> to check.
+            @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+            cannot be added.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.AddSimple(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Adds another <code>ECPoints.F2m</code> to <code>this</code> without
+            checking if both points are on the same curve. Used by multiplication
+            algorithms, because there all points are a multiple of the same point
+            and hence the checks can be omitted.
+            @param b The other <code>ECPoints.F2m</code> to add to
+            <code>this</code>.
+            @return <code>this + b</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.SubtractSimple(Org.BouncyCastle.Math.EC.F2mPoint)">
+            Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
+            without checking if both points are on the same curve. Used by
+            multiplication algorithms, because there all points are a multiple
+            of the same point and hence the checks can be omitted.
+            @param b The other <code>ECPoints.F2m</code> to subtract from
+            <code>this</code>.
+            @return <code>this - b</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.F2mPoint.AssertECMultiplier">
+            Sets the appropriate <code>ECMultiplier</code>, unless already set. 
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.ECMultiplier">
+            Interface for classes encapsulating a point multiplication algorithm
+            for <code>ECPoint</code>s.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.ECMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
+            <code>p</code> is added <code>k</code> times to itself.
+            @param p The <code>ECPoint</code> to be multiplied.
+            @param k The factor by which <code>p</code> i multiplied.
+            @return <code>p</code> multiplied by <code>k</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.FpNafMultiplier">
+            Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.FpNafMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            D.3.2 pg 101
+            @see org.bouncycastle.math.ec.multiplier.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo">
+            Interface for classes storing precomputation data for multiplication
+            algorithms. Used as a Memento (see GOF patterns) for
+            <code>WNafMultiplier</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.ReferenceMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Simple shift-and-add multiplication. Serves as reference implementation
+            to verify (possibly faster) implementations in
+            {@link org.bouncycastle.math.ec.ECPoint ECPoint}.
+            
+            @param p The point to multiply.
+            @param k The factor by which to multiply.
+            @return The result of the point multiplication <code>k * p</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WNafMultiplier">
+            Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+            algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafMultiplier.WindowNaf(System.SByte,Org.BouncyCastle.Math.BigInteger)">
+            Computes the Window NAF (non-adjacent Form) of an integer.
+            @param width The width <code>w</code> of the Window NAF. The width is
+            defined as the minimal number <code>w</code>, such that for any
+            <code>w</code> consecutive digits in the resulting representation, at
+            most one is non-zero.
+            @param k The integer of which the Window NAF is computed.
+            @return The Window NAF of the given width, such that the following holds:
+            <code>k = −<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+            </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+            returned <code>sbyte[]</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WNafMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Multiplies <code>this</code> by an integer <code>k</code> using the
+            Window NAF method.
+            @param k The integer by which <code>this</code> is multiplied.
+            @return A new <code>ECPoint</code> which equals <code>this</code>
+            multiplied by <code>k</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo">
+            Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
+            algorithm.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo.preComp">
+            Array holding the precomputed <code>ECPoint</code>s used for the Window
+            NAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
+            WNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WNafPreCompInfo.twiceP">
+            Holds an <code>ECPoint</code> representing twice(this). Used for the
+            Window NAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WNafMultiplier.multiply()
+            WNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier">
+            Class implementing the WTNAF (Window
+            <code>τ</code>-adic Non-Adjacent Form) algorithm.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.Multiply(Org.BouncyCastle.Math.EC.ECPoint,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by <code>k</code> using the reduced <code>τ</code>-adic NAF (RTNAF)
+            method.
+            @param p The F2mPoint to multiply.
+            @param k The integer by which to multiply <code>k</code>.
+            @return <code>p</code> multiplied by <code>k</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.MultiplyWTnaf(Org.BouncyCastle.Math.EC.F2mPoint,Org.BouncyCastle.Math.EC.Abc.ZTauElement,Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo,System.SByte,System.SByte)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code> using
+            the <code>τ</code>-adic NAF (TNAF) method.
+            @param p The F2mPoint to multiply.
+            @param lambda The element <code>λ</code> of
+            <code><b>Z</b>[τ]</code> of which to compute the
+            <code>[τ]</code>-adic NAF.
+            @return <code>p</code> multiplied by <code>λ</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafMultiplier.MultiplyFromWTnaf(Org.BouncyCastle.Math.EC.F2mPoint,System.SByte[],Org.BouncyCastle.Math.EC.Multiplier.PreCompInfo)">
+            Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+            by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+            using the window <code>τ</code>-adic NAF (TNAF) method, given the
+            WTNAF of <code>λ</code>.
+            @param p The F2mPoint to multiply.
+            @param u The the WTNAF of <code>λ</code>..
+            @return <code>λ * p</code>
+        </member>
+        <member name="T:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo">
+            Class holding precomputation data for the WTNAF (Window
+            <code>τ</code>-adic Non-Adjacent Form) algorithm.
+        </member>
+        <member name="F:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo.preComp">
+            Array holding the precomputed <code>F2mPoint</code>s used for the
+            WTNAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+            WTauNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo.#ctor(Org.BouncyCastle.Math.EC.F2mPoint[])">
+            Constructor for <code>WTauNafPreCompInfo</code>
+            @param preComp Array holding the precomputed <code>F2mPoint</code>s
+            used for the WTNAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+            WTauNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Math.EC.Multiplier.WTauNafPreCompInfo.GetPreComp">
+            @return the array holding the precomputed <code>F2mPoint</code>s
+            used for the WTNAF multiplication in <code>
+            {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+            WTauNafMultiplier.multiply()}</code>.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.BasicOcspResp">
+            <remarks>
+            <code>
+            BasicOcspResponse ::= SEQUENCE {
+            	tbsResponseData		ResponseData,
+            	signatureAlgorithm	AlgorithmIdentifier,
+            	signature			BIT STRING,
+            	certs				[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+            }
+            </code>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509Extension.GetCriticalExtensionOids">
+            <summary>
+            Get all critical extension values, by oid
+            </summary>
+            <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509Extension.GetNonCriticalExtensionOids">
+            <summary>
+            Get all non-critical extension values, by oid
+            </summary>
+            <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetNonCriticalExtensionOids">
+            <summary>
+            Get non critical extensions.
+            </summary>
+            <returns>A set of non critical extension oids.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetCriticalExtensionOids">
+            <summary>
+            Get any critical extensions.
+            </summary>
+            <returns>A sorted list of critical entension.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509ExtensionBase.GetExtensionValue(System.String)">
+            <summary>
+            Get the value of a given extension.
+            </summary>
+            <param name="oid">The object ID of the extension. </param>
+            <returns>An Asn1OctetString object if that extension is found or null if not.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetTbsResponseData">
+            <returns>The DER encoding of the tbsResponseData field.</returns>
+            <exception cref="T:Org.BouncyCastle.Ocsp.OcspException">In the event of an encoding error.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetCertificates(System.String)">
+            <returns>The certificates, if any, associated with the response.</returns>
+            <exception cref="T:Org.BouncyCastle.Ocsp.OcspException">In the event of an encoding error.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Verify the signature against the tbsResponseData object we contain.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspResp.GetEncoded">
+            <returns>The ASN.1 encoded representation of this object.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator">
+            Generator for basic OCSP response objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.#ctor(Org.BouncyCastle.Ocsp.RespID)">
+            basic constructor
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            construct with the responderID to be the SHA-1 keyHash of the passed in public key.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param certStatus status of the certificate - null if okay
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param nextUpdate date when next update should be requested
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.AddResponse(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Ocsp.CertificateStatus,System.DateTime,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a response for a particular Certificate ID.
+            
+             @param certID certificate ID details
+             @param thisUpdate date this response was valid on
+             @param nextUpdate date when next update should be requested
+             @param certStatus status of the certificate - null if okay
+             @param singleExtensions optional extensions
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.SetResponseExtensions(Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Set the extensions for the response.
+            
+             @param responseExtensions the extension object to carry.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.BasicOcspRespGenerator.SignatureAlgNames">
+             Return an IEnumerable of the signature names supported by the generator.
+            
+             @return an IEnumerable containing recognised names.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.CertificateID.#ctor(System.String,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Math.BigInteger)">
+            create from an issuer certificate and the serial number of the
+            certificate it signed.
+            @exception OcspException if any problems occur creating the id fields.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.CertificateID.DeriveCertificateID(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Math.BigInteger)">
+             Create a new CertificateID for a new serial number derived from a previous one
+             calculated for the same CA certificate.
+            
+             @param original the previously calculated CertificateID for the CA.
+             @param newSerialNumber the serial number for the new certificate of interest.
+            
+             @return a new CertificateID for newSerialNumber
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.CertificateID.SerialNumber">
+            return the serial number for the certificate associated
+            with this request.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.OcspReq">
+             <pre>
+             OcspRequest     ::=     SEQUENCE {
+                   tbsRequest                  TBSRequest,
+                   optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+            
+               TBSRequest      ::=     SEQUENCE {
+                   version             [0]     EXPLICIT Version DEFAULT v1,
+                   requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+                   requestList                 SEQUENCE OF Request,
+                   requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+            
+               Signature       ::=     SEQUENCE {
+                   signatureAlgorithm      AlgorithmIdentifier,
+                   signature               BIT STRING,
+                   certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+            
+               Version         ::=             INTEGER  {  v1(0) }
+            
+               Request         ::=     SEQUENCE {
+                   reqCert                     CertID,
+                   singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+            
+               CertID          ::=     SEQUENCE {
+                   hashAlgorithm       AlgorithmIdentifier,
+                   issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+                   issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+                   serialNumber        CertificateSerialNumber }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetTbsRequest">
+            Return the DER encoding of the tbsRequest field.
+            @return DER encoding of tbsRequest
+            @throws OcspException in the event of an encoding error.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetCertificates(System.String)">
+             If the request is signed return a possibly empty CertStore containing the certificates in the
+             request. If the request is not signed the method returns null.
+            
+             @return null if not signed, a CertStore otherwise
+             @throws OcspException
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            Verify the signature against the TBSRequest object we contain.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReq.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReq.SignatureAlgOid">
+            return the object identifier representing the signature algorithm
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReq.IsSigned">
+             Return whether or not this request is signed.
+            
+             @return true if signed false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.AddRequest(Org.BouncyCastle.Ocsp.CertificateID)">
+             Add a request for the given CertificateID.
+            
+             @param certId certificate ID of interest
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.AddRequest(Org.BouncyCastle.Ocsp.CertificateID,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a request with extensions
+            
+             @param certId certificate ID of interest
+             @param singleRequestExtensions the extensions to attach to the request
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.SetRequestorName(Org.BouncyCastle.Asn1.X509.X509Name)">
+             Set the requestor name to the passed in X509Principal
+            
+             @param requestorName a X509Principal representing the requestor name.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspReqGenerator.Generate">
+             Generate an unsigned request
+            
+             @return the OcspReq
+             @throws OcspException
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.OcspReqGenerator.SignatureAlgNames">
+             Return an IEnumerable of the signature names supported by the generator.
+            
+             @return an IEnumerable containing recognised names.
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.OcspResp.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.OCSPRespGenerator">
+            base generator for an OCSP response - at the moment this only supports the
+            generation of responses containing BasicOCSP responses.
+        </member>
+        <member name="F:Org.BouncyCastle.Ocsp.OcspRespStatus.Successful">
+            note 4 is not used.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.RespID">
+            Carrier for a ResponderID.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.RevokedStatus">
+            wrapper for the RevokedInfo object
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.RevokedStatus.RevocationReason">
+            return the revocation reason. Note: this field is optional, test for it
+            with hasRevocationReason() first.
+            @exception InvalidOperationException if a reason is asked for and none is avaliable
+        </member>
+        <member name="M:Org.BouncyCastle.Ocsp.SingleResp.GetCertStatus">
+             Return the status object for the response - null indicates good.
+            
+             @return the status object for the response, null if it is good.
+        </member>
+        <member name="P:Org.BouncyCastle.Ocsp.SingleResp.NextUpdate">
+             return the NextUpdate value - note: this is an optional field so may
+             be returned as null.
+            
+             @return nextUpdate, or null if not present.
+        </member>
+        <member name="T:Org.BouncyCastle.Ocsp.UnknownStatus">
+            wrapper for the UnknownInfo object
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData">
+            <remarks>Compressed data objects</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.GetInputStream">
+            <summary>Get the raw input stream contained in the object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.GetDataStream">
+            <summary>Return an uncompressed input stream which allows reading of the compressed data.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedData.Algorithm">
+            <summary>The algorithm used for compression</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator">
+            <remarks>Class for producing compressed data packets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Open(System.IO.Stream)">
+            <summary>
+            <p>
+            Return an output stream which will save the data being written to
+            the compressed object.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+            <param name="outStr">Stream to be used for output.</param>
+            <returns>A Stream for output of the compressed data.</returns>
+            <exception cref="T:System.ArgumentNullException"></exception>
+            <exception cref="T:System.InvalidOperationException"></exception>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Open(System.IO.Stream,System.Byte[])">
+            <summary>
+            <p>
+            Return an output stream which will compress the data as it is written to it.
+            The stream will be written out in chunks according to the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.
+            </p>
+            <p>
+            <b>Note</b>: using this may break compatibility with RFC 1991 compliant tools.
+            Only recent OpenPGP implementations are capable of accepting these streams.
+            </p>
+            </summary>
+            <param name="outStr">Stream to be used for output.</param>
+            <param name="buffer">The buffer to use.</param>
+            <returns>A Stream for output of the compressed data.</returns>
+            <exception cref="T:System.ArgumentNullException"></exception>
+            <exception cref="T:System.InvalidOperationException"></exception>
+            <exception cref="T:System.IO.IOException"></exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpCompressedDataGenerator.Close">
+            <summary>Close the compressed object.</summary>summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpDataValidationException">
+            <remarks>
+            Thrown if the IV at the start of a data stream indicates the wrong key is being used.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">
+            <remarks>Generic exception class for PGP encoding/decoding problems.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.GetInputStream">
+            <summary>Return the raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.IsIntegrityProtected">
+            <summary>Return true if the message is integrity protected.</summary>
+            <returns>True, if there is a modification detection code namespace associated
+            with this stream.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedData.Verify">
+            <summary>Note: This can only be called after the message has been read.</summary>
+            <returns>True, if the message verifies, false otherwise</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator">
+            <remarks>Generator for encrypted objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Existing SecureRandom constructor.</summary>
+            <param name="encAlgorithm">The symmetric algorithm to use.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Boolean,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Creates a cipher stream which will have an integrity packet associated with it.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.#ctor(Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom,System.Boolean)">
+            <summary>Base constructor.</summary>
+            <param name="encAlgorithm">The symmetric algorithm to use.</param>
+            <param name="rand">Source of randomness.</param>
+            <param name="oldFormat">PGP 2.6.x compatibility required.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(System.Char[])">
+            <summary>
+            Add a PBE encryption method to the encrypted object using the default algorithm (S2K_SHA1).
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(System.Char[],Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Add a PBE encryption method to the encrypted object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.AddMethod(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Add a public key encrypted session key to the encrypted object.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Int64,System.Byte[])">
+            <summary>
+            <p>
+            If buffer is non null stream assumed to be partial, otherwise the length will be used
+            to output a fixed length packet.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Int64)">
+            <summary>
+            <p>
+            Return an output stream which will encrypt the data as it is written to it.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Open(System.IO.Stream,System.Byte[])">
+            <summary>
+            <p>
+            Return an output stream which will encrypt the data as it is written to it.
+            The stream will be written out in chunks according to the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.
+            </p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataGenerator.Close">
+            <summary>
+            <p>
+            Close off the encrypted object - this is equivalent to calling Close() on the stream
+            returned by the Open() method.
+            </p>
+            <p>
+            <b>Note</b>: This does not close the underlying output stream, only the stream on top of
+            it created by the Open() method.
+            </p>
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpEncryptedDataList">
+            <remarks>A holder for a list of PGP encryption method packets.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyFlags">
+            <remarks>Key flag values for the KeyFlags subpacket.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair">
+            <remarks>
+            General class to handle JCA key pairs and convert them into OpenPGP ones.
+            <p>
+            A word for the unwary, the KeyId for an OpenPGP public key is calculated from
+            a hash that includes the time of creation, if you pass a different date to the
+            constructor below with the same public private key pair the KeyIs will not be the
+            same as for previous generations of the key, so ideally you only want to do
+            this once.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair.#ctor(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
+            <param name="pub">The public key.</param>
+            <param name="priv">The private key.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair.KeyId">
+            <summary>The keyId associated with this key pair.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator">
+            <remarks>
+            Generator for a PGP master and subkey ring.
+            This class will generate both the secret and public key rings
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.#ctor(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,System.String,Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Char[],Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Create a new key ring generator using old style checksumming. It is recommended to use
+            SHA1 checksumming where possible.
+            </summary>
+            <param name="certificationLevel">The certification level for keys on this ring.</param>
+            <param name="masterKey">The master key pair.</param>
+            <param name="id">The id to be associated with the ring.</param>
+            <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+            <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+            <param name="hashedPackets">Packets to be included in the certification hash.</param>
+            <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+            <param name="rand">input secured random.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.#ctor(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,System.String,Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,System.Char[],System.Boolean,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Create a new key ring generator.
+            </summary>
+            <param name="certificationLevel">The certification level for keys on this ring.</param>
+            <param name="masterKey">The master key pair.</param>
+            <param name="id">The id to be associated with the ring.</param>
+            <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+            <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+            <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
+            <param name="hashedPackets">Packets to be included in the certification hash.</param>
+            <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+            <param name="rand">input secured random.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.AddSubKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair)">
+            <summary>Add a subkey to the key ring to be generated with default certification.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.AddSubKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyPair,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector)">
+            <summary>
+            Add a subkey with specific hashed and unhashed packets associated with it and
+            default certification.
+            </summary>
+            <param name="keyPair">Public/private key pair.</param>
+            <param name="hashedPackets">Hashed packet values to be included in certification.</param>
+            <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.GenerateSecretKeyRing">
+            <summary>Return the secret key ring.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyRingGenerator.GeneratePublicKeyRing">
+            <summary>Return the public key ring that corresponds to the secret key ring.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpKeyValidationException">
+            <remarks>
+            Thrown if the key checksum is invalid.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData">
+            <summary>Class for processing literal data objects.</summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Console">
+            <summary>The special name indicating a "for your eyes only" packet.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetRawFileName">
+            Return the file name as an unintrepreted byte array.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetInputStream">
+            <summary>The raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.GetDataStream">
+            <summary>The input stream representing the data stream.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.Format">
+            <summary>The format of the data stream - Binary or Text</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.FileName">
+            <summary>The file name that's associated with the data stream.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralData.ModificationTime">
+            <summary>The modification time for the file.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator">
+            <remarks>Class for producing literal data packets.</remarks>
+        </member>
+        <member name="F:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Console">
+            <summary>The special name indicating a "for your eyes only" packet.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.#ctor(System.Boolean)">
+            <summary>
+            Generates literal data objects in the old format.
+            This is important if you need compatibility with PGP 2.6.x.
+            </summary>
+            <param name="oldFormat">If true, uses old format.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Open(System.IO.Stream,System.Char,System.String,System.Int64,System.DateTime)">
+            <summary>
+            <p>
+            Open a literal data packet, returning a stream to store the data inside the packet.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            </summary>
+            <param name="outStr">The stream we want the packet in.</param>
+            <param name="format">The format we are using.</param>
+            <param name="name">The name of the 'file'.</param>
+            <param name="length">The length of the data we will write.</param>
+            <param name="modificationTime">The time of last modification we want stored.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Open(System.IO.Stream,System.Char,System.String,System.DateTime,System.Byte[])">
+            <summary>
+            <p>
+            Open a literal data packet, returning a stream to store the data inside the packet,
+            as an indefinite length stream. The stream is written out as a series of partial
+            packets with a chunk size determined by the size of the passed in buffer.
+            </p>
+            <p>
+            The stream created can be closed off by either calling Close()
+            on the stream or Close() on the generator. Closing the returned
+            stream does not close off the Stream parameter <c>outStr</c>.
+            </p>
+            <p>
+            <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+            bytes worth of the buffer will be used.</p>
+            </summary>
+            <param name="outStr">The stream we want the packet in.</param>
+            <param name="format">The format we are using.</param>
+            <param name="name">The name of the 'file'.</param>
+            <param name="modificationTime">The time of last modification we want stored.</param>
+            <param name="buffer">The buffer to use for collecting data to put into chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpLiteralDataGenerator.Close">
+            <summary>
+            Close the literal data packet - this is equivalent to calling Close()
+            on the stream returned by the Open() method.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpMarker">
+            <remarks>
+            A PGP marker packet - in general these should be ignored other than where
+            the idea is to preserve the original input stream.
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory">
+            <remarks>
+            General class for reading a PGP object stream.
+            <p>
+            Note: if this class finds a PgpPublicKey or a PgpSecretKey it
+            will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each
+            key found. If all you are trying to do is read a key ring file use
+            either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory.NextPgpObject">
+            <summary>Return the next object in the stream, or null if the end is reached.</summary>
+            <exception cref="T:System.IO.IOException">On a parse error</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpObjectFactory.AllPgpObjects">
+            <summary>
+            Return all available objects in a list.
+            </summary>
+            <returns>An <c>IList</c> containing all objects from this factory, in order.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature">
+            <remarks>A one pass signature object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature.InitVerify(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Initialise the signature object for verification.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignature.Verify(Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpOnePassSignatureList">
+            <remarks>Holder for a list of PgpOnePassSignature objects.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData">
+            <remarks>A password based encryption object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData.GetInputStream">
+            <summary>Return the raw input stream for the data stream.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPbeEncryptedData.GetDataStream(System.Char[])">
+            <summary>Return the decrypted input stream, using the passed in passphrase.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey">
+            <remarks>General class to contain a private key for use with other OpenPGP objects.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Int64)">
+            <summary>
+            Create a PgpPrivateKey from a regular private key and the ID of its
+            associated public key.
+            </summary>
+            <param name="privateKey">Private key to use.</param>
+            <param name="keyId">ID of the corresponding public key.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.KeyId">
+            <summary>The keyId associated with the contained private key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey.Key">
+            <summary>The contained private key.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey">
+            <remarks>General class to handle a PGP public key object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.DateTime)">
+            <summary>
+            Create a PgpPublicKey from the passed in lightweight one.
+            </summary>
+            <remarks>
+            Note: the time passed in affects the value of the key's keyId, so you probably only want
+            to do this once for a lightweight key, or make sure you keep track of the time you used.
+            </remarks>
+            <param name="algorithm">Asymmetric algorithm type representing the public key.</param>
+            <param name="pubKey">Actual public key to associate.</param>
+            <param name="time">Date of creation.</param>
+            <exception cref="T:System.ArgumentException">If <c>pubKey</c> is not public.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">On key creation problem.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.PublicKeyPacket,Org.BouncyCastle.Bcpg.TrustPacket,System.Collections.IList)">
+            <summary>Constructor for a sub-key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.#ctor(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Copy constructor.</summary>
+            <param name="pubKey">The public key to copy.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetTrustData">
+            <summary>Return the trust data associated with the public key, if present.</summary>
+            <returns>A byte array with trust data, null otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetValidSeconds">
+            <summary>The number of valid seconds from creation time - zero means no expiry.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetFingerprint">
+            <summary>The fingerprint of the key</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetKey">
+            <summary>The public key contained in the object.</summary>
+            <returns>A lightweight public key.</returns>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If the key algorithm is not recognised.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetUserIds">
+            <summary>Allows enumeration of any user IDs associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetUserAttributes">
+            <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesForId(System.String)">
+            <summary>Allows enumeration of any signatures associated with the passed in id.</summary>
+            <param name="id">The ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesForUserAttribute(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector)">
+            <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary>
+            <param name="userAttributes">The vector of user attributes to be matched.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignaturesOfType(System.Int32)">
+            <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary>
+            <param name="signatureType">The type of the signature to be returned.</param>
+            <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.GetSignatures">
+            <summary>Allows enumeration of all signatures/certifications associated with this key.</summary>
+            <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsRevoked">
+            <summary>Check whether this (sub)key has a revocation signature on it.</summary>
+            <returns>True, if this (sub)key has been revoked.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a certification for an id to the given public key.</summary>
+            <param name="key">The key the certification is to be added to.</param>
+            <param name="id">The ID the certification is associated with.</param>
+            <param name="certification">The new certification.</param>
+            <returns>The re-certified key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary>
+            <param name="key">The key the certification is to be added to.</param>
+            <param name="userAttributes">The attributes the certification is associated with.</param>
+            <param name="certification">The new certification.</param>
+            <returns>The re-certified key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector)">
+            <summary>
+            Remove any certifications associated with a user attribute subpacket on a key.
+            </summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="userAttributes">The attributes to be removed.</param>
+            <returns>
+            The re-certified key, or null if the user attribute subpacket was not found on the key.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String)">
+            <summary>Remove any certifications associated with a given ID on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="id">The ID that is to be removed.</param>
+            <returns>The re-certified key, or null if the ID was not found on the key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification associated with a given ID on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="id">The ID that the certfication is to be removed from.</param>
+            <param name="certification">The certfication to be removed.</param>
+            <returns>The re-certified key, or null if the certification was not found.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification associated with a given user attributes on a key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
+            <param name="certification">The certification to be removed.</param>
+            <returns>The re-certified key, or null if the certification was not found.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.AddCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Add a revocation or some other key certification to a key.</summary>
+            <param name="key">The key the revocation is to be added to.</param>
+            <param name="certification">The key signature to be added.</param>
+            <returns>The new changed public key object.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.RemoveCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature)">
+            <summary>Remove a certification from the key.</summary>
+            <param name="key">The key the certifications are to be removed from.</param>
+            <param name="certification">The certfication to be removed.</param>
+            <returns>The modified key, null if the certification was not found.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.Version">
+            <summary>The version of this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.CreationTime">
+            <summary>The creation time of this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.ValidDays">
+            <summary>The number of valid days from creation time - zero means no expiry.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.KeyId">
+            <summary>The keyId associated with the public key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsEncryptionKey">
+            <summary>
+            Check if this key has an algorithm type that makes it suitable to use for encryption.
+            </summary>
+            <remarks>
+            Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+            determining the preferred use of the key.
+            </remarks>
+            <returns>
+            <c>true</c> if this key algorithm is suitable for encryption.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.IsMasterKey">
+            <summary>True, if this is a master key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.Algorithm">
+            <summary>The algorithm code associated with the public key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey.BitStrength">
+            <summary>The strength of the key in bits.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData">
+            <remarks>A public key encrypted data object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.GetSymmetricAlgorithm(Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>
+            Return the algorithm code for the symmetric algorithm used to encrypt the data.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.GetDataStream(Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Return the decrypted data stream for the packet.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyEncryptedData.KeyId">
+            <summary>The key ID for the key used to encrypt the data.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing">
+            <remarks>
+            Class to hold a single master public key and its subkeys.
+            <p>
+            Often PGP keyring files consist of multiple master keys, if you are trying to process
+            or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKey">
+            <summary>Return the first public key in the ring.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKey(System.Int64)">
+            <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.GetPublicKeys">
+            <summary>Allows enumeration of all the public keys.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.InsertPublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Returns a new key ring with the public key passed in either added or
+            replacing an existing one.
+            </summary>
+            <param name="pubRing">The public key ring to be modified.</param>
+            <param name="pubKey">The public key to be inserted.</param>
+            <returns>A new <c>PgpPublicKeyRing</c></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing.RemovePublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
+            <param name="pubRing">The public key ring to be modified.</param>
+            <param name="pubKey">The public key to be removed.</param>
+            <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle">
+            <remarks>
+            Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+            If you want to read an entire public key file in one hit this is the class for you.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.#ctor(System.IO.Stream)">
+            <summary>Build a PgpPublicKeyRingBundle from the passed in input stream.</summary>
+            <param name="inputStream">Input stream containing data.</param>
+            <exception cref="T:System.IO.IOException">If a problem parsing the stream occurs.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If an object is encountered which isn't a PgpPublicKeyRing.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings">
+            <summary>Allow enumeration of the public key rings making up this collection.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetKeyRings(System.String,System.Boolean,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetPublicKey(System.Int64)">
+            <summary>Return the PGP public key associated with the given key id.</summary>
+            <param name="keyId">The ID of the public key to return.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.GetPublicKeyRing(System.Int64)">
+            <summary>Return the public key ring which contains the key referred to by keyId</summary>
+            <param name="keyId">key ID to match against</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.Contains(System.Int64)">
+            <summary>
+            Return true if a key matching the passed in key ID is present, false otherwise.
+            </summary>
+            <param name="keyID">key ID to look for.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.AddPublicKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle and
+            the passed in public key ring.
+            </summary>
+            <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
+            <param name="publicKeyRing">The key ring to be added.</param>
+            <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.RemovePublicKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle with
+            the passed in public key ring removed.
+            </summary>
+            <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be removed from.</param>
+            <param name="publicKeyRing">The key ring to be removed.</param>
+            <returns>A new <c>PgpPublicKeyRingBundle</c> not containing the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRingBundle.Count">
+            <summary>Return the number of key rings in this collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey">
+            <remarks>General class to handle a PGP secret key object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ExtractPrivateKey(System.Char[])">
+            <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.CopyWithNewPassword(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey,System.Char[],System.Char[],Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Return a copy of the passed in secret key, encrypted using a new password
+            and the passed in algorithm.
+            </summary>
+            <param name="key">The PgpSecretKey to be copied.</param>
+            <param name="oldPassPhrase">The current password for the key.</param>
+            <param name="newPassPhrase">The new password for the key.</param>
+            <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.ReplacePublicKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Replace the passed the public key on the passed in secret key.</summary>
+            <param name="secretKey">Secret key to change.</param>
+            <param name="publicKey">New public key.</param>
+            <returns>A new secret key.</returns>
+            <exception cref="T:System.ArgumentException">If KeyId's do not match.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.IsSigningKey">
+            <summary>
+            Check if this key has an algorithm type that makes it suitable to use for signing.
+            </summary>
+            <remarks>
+            Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+            determining the preferred use of the key.
+            </remarks>
+            <returns>
+            <c>true</c> if this key algorithm is suitable for use with signing.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.IsMasterKey">
+            <summary>True, if this is a master key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.KeyEncryptionAlgorithm">
+            <summary>The algorithm the key is encrypted with.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.KeyId">
+            <summary>The key ID of the public key associated with this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.PublicKey">
+            <summary>The public key associated with this key.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.UserIds">
+            <summary>Allows enumeration of any user IDs associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey.UserAttributes">
+            <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+            <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing">
+            <remarks>
+            Class to hold a single master secret key and its subkeys.
+            <p>
+            Often PGP keyring files consist of multiple master keys, if you are trying to process
+            or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class.
+            </p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetPublicKey">
+            <summary>Return the public key for the master key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetSecretKey">
+            <summary>Return the master private key.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetSecretKeys">
+            <summary>Allows enumeration of the secret keys.</summary>
+            <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.GetExtraPublicKeys">
+            <summary>
+            Return an iterator of the public keys in the secret key ring that
+            have no matching private key. At the moment only personal certificate data
+            appears in this fashion.
+            </summary>
+            <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.ReplacePublicKeys(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKeyRing)">
+            <summary>
+            Replace the public key set on the secret ring with the corresponding key off the public ring.
+            </summary>
+            <param name="secretRing">Secret ring to be changed.</param>
+            <param name="publicRing">Public ring containing the new public key set.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.CopyWithNewPassword(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,System.Char[],System.Char[],Org.BouncyCastle.Bcpg.SymmetricKeyAlgorithmTag,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Return a copy of the passed in secret key ring, with the master key and sub keys encrypted
+            using a new password and the passed in algorithm.
+            </summary>
+            <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param>
+            <param name="oldPassPhrase">The current password for key.</param>
+            <param name="newPassPhrase">The new password for the key.</param>
+            <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+            <param name="rand">Source of randomness.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.InsertSecretKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey)">
+            <summary>
+            Returns a new key ring with the secret key passed in either added or
+            replacing an existing one with the same key ID.
+            </summary>
+            <param name="secRing">The secret key ring to be modified.</param>
+            <param name="secKey">The secret key to be inserted.</param>
+            <returns>A new <c>PgpSecretKeyRing</c></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing.RemoveSecretKey(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKey)">
+            <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
+            <param name="secRing">The secret key ring to be modified.</param>
+            <param name="secKey">The secret key to be removed.</param>
+            <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle">
+            <remarks>
+            Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+            If you want to read an entire secret key file in one hit this is the class for you.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.#ctor(System.IO.Stream)">
+            <summary>Build a PgpSecretKeyRingBundle from the passed in input stream.</summary>
+            <param name="inputStream">Input stream containing data.</param>
+            <exception cref="T:System.IO.IOException">If a problem parsing the stream occurs.</exception>
+            <exception cref="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpException">If an object is encountered which isn't a PgpSecretKeyRing.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings">
+            <summary>Allow enumeration of the secret key rings making up this collection.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetKeyRings(System.String,System.Boolean,System.Boolean)">
+            <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+            <param name="userId">The user ID to be matched.</param>
+            <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+            <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+            <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetSecretKey(System.Int64)">
+            <summary>Return the PGP secret key associated with the given key id.</summary>
+            <param name="keyId">The ID of the secret key to return.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.GetSecretKeyRing(System.Int64)">
+            <summary>Return the secret key ring which contains the key referred to by keyId</summary>
+            <param name="keyId">The ID of the secret key</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.Contains(System.Int64)">
+            <summary>
+            Return true if a key matching the passed in key ID is present, false otherwise.
+            </summary>
+            <param name="keyID">key ID to look for.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.AddSecretKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle and
+            the passed in secret key ring.
+            </summary>
+            <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be added to.</param>
+            <param name="secretKeyRing">The key ring to be added.</param>
+            <returns>A new <c>PgpSecretKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.RemoveSecretKeyRing(Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle,Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRing)">
+            <summary>
+            Return a new bundle containing the contents of the passed in bundle with
+            the passed in secret key ring removed.
+            </summary>
+            <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be removed from.</param>
+            <param name="secretKeyRing">The key ring to be removed.</param>
+            <returns>A new <c>PgpSecretKeyRingBundle</c> not containing the passed in key ring.</returns>
+            <exception cref="T:System.ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSecretKeyRingBundle.Count">
+            <summary>Return the number of rings in this collection.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature">
+            <remarks>A PGP signature object.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Verify the signature as certifying the passed in public key as associated
+            with the passed in user attributes.
+            </summary>
+            <param name="userAttributes">User attributes the key was stored under.</param>
+            <param name="key">The key to be verified.</param>
+            <returns>True, if the signature matches, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>
+            Verify the signature as certifying the passed in public key as associated
+            with the passed in ID.
+            </summary>
+            <param name="id">ID the key was stored under.</param>
+            <param name="key">The key to be verified.</param>
+            <returns>True, if the signature matches, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Verify a certification for the passed in key against the passed in master key.</summary>
+            <param name="masterKey">The key we are verifying against.</param>
+            <param name="pubKey">The key we are verifying.</param>
+            <returns>True, if the certification is valid, false otherwise.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.VerifyCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
+            <param name="pubKey">The key we are checking.</param>
+            <returns>True, if the certification is valid, false otherwise.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.Version">
+            <summary>The OpenPGP version number for this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.KeyAlgorithm">
+            <summary>The key algorithm associated with this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.HashAlgorithm">
+            <summary>The hash algorithm associated with this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.KeyId">
+            <summary>The ID of the key that created the signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.CreationTime">
+            <summary>The creation time of this signature.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignature.HasSubpackets">
+            <summary>
+            Return true if the signature has either hashed or unhashed subpackets.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator">
+            <remarks>Generator for PGP signatures.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateOnePassVersion(System.Boolean)">
+            <summary>Return the one pass header associated with the current signature.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.Generate">
+            <summary>Return a signature object containing the current signature state.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(System.String,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in ID and key.</summary>
+            <param name="id">The ID we are certifying against the public key.</param>
+            <param name="pubKey">The key we are certifying against the ID.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in userAttributes.</summary>
+            <param name="userAttributes">The ID we are certifying against the public key.</param>
+            <param name="pubKey">The key we are certifying against the ID.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey,Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification for the passed in key against the passed in master key.</summary>
+            <param name="masterKey">The key we are certifying against.</param>
+            <param name="pubKey">The key we are certifying.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureGenerator.GenerateCertification(Org.BouncyCastle.Bcpg.OpenPgp.PgpPublicKey)">
+            <summary>Generate a certification, such as a revocation, for the passed in key.</summary>
+            <param name="pubKey">The key we are certifying.</param>
+            <returns>The certification.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureList">
+            <remarks>A list of PGP signatures - normally in the signature block after literal data.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator">
+            <remarks>Generator for signature subpackets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetTrust(System.Boolean,System.Int32,System.Int32)">
+            <summary>
+            Add a TrustSignature packet to the signature. The values for depth and trust are largely
+            installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
+            </summary>
+            <param name="isCritical">true if the packet is critical.</param>
+            <param name="depth">depth level.</param>
+            <param name="trustAmount">trust amount.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetKeyExpirationTime(System.Boolean,System.Int64)">
+            <summary>
+            Set the number of seconds a key is valid for after the time of its creation.
+            A value of zero means the key never expires.
+            </summary>
+            <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+            <param name="seconds">The number of seconds the key is valid, or zero if no expiry.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetSignatureExpirationTime(System.Boolean,System.Int64)">
+            <summary>
+            Set the number of seconds a signature is valid for after the time of its creation.
+            A value of zero means the signature never expires.
+            </summary>
+            <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+            <param name="seconds">The number of seconds the signature is valid, or zero if no expiry.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetSignatureCreationTime(System.Boolean,System.DateTime)">
+            <summary>
+            Set the creation time for the signature.
+            <p>
+            Note: this overrides the generation of a creation time when the signature
+            is generated.</p>
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetRevocationReason(System.Boolean,Org.BouncyCastle.Bcpg.RevocationReasonTag,System.String)">
+            <summary>
+            Sets revocation reason sub packet
+            </summary>	    
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetRevocationKey(System.Boolean,Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,System.Byte[])">
+            <summary>
+            Sets revocation key sub packet
+            </summary>	
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketGenerator.SetIssuerKeyID(System.Boolean,System.Int64)">
+            <summary>
+            Sets issuer key sub packet
+            </summary>	
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector">
+            <remarks>Container for a list of signature subpackets.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.HasSubpacket(Org.BouncyCastle.Bcpg.SignatureSubpacketTag)">
+             Return true if a particular subpacket type exists.
+            
+             @param type type to look for.
+             @return true if present, false otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetSubpackets(Org.BouncyCastle.Bcpg.SignatureSubpacketTag)">
+            Return all signature subpackets of the passed in type.
+            @param type subpacket type code
+            @return an array of zero or more matching subpackets.
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetSignatureExpirationTime">
+            <summary>
+            Return the number of seconds a signature is valid for after its creation date.
+            A value of zero means the signature never expires.
+            </summary>
+            <returns>Seconds a signature is valid for.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.GetKeyExpirationTime">
+            <summary>
+            Return the number of seconds a key is valid for after its creation date.
+            A value of zero means the key never expires.
+            </summary>
+            <returns>Seconds a signature is valid for.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Bcpg.OpenPgp.PgpSignatureSubpacketVector.Count">
+            <summary>Return the number of packets this vector contains.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpUserAttributeSubpacketVector">
+            <remarks>Container for a list of user attribute subpackets.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpUtilities">
+            <remarks>Basic utility class.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpUtilities.GetDecoderStream(System.IO.Stream)">
+            <summary>
+            Return either an ArmoredInputStream or a BcpgInputStream based on whether
+            the initial characters of the stream are binary PGP encodings or not.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator">
+            <remarks>Generator for old style PGP V3 Signatures.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.#ctor(Org.BouncyCastle.Bcpg.PublicKeyAlgorithmTag,Org.BouncyCastle.Bcpg.HashAlgorithmTag)">
+            <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.InitSign(System.Int32,Org.BouncyCastle.Bcpg.OpenPgp.PgpPrivateKey,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Initialise the generator for signing.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.GenerateOnePassVersion(System.Boolean)">
+            <summary>Return the one pass header associated with the current signature.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Bcpg.OpenPgp.PgpV3SignatureGenerator.Generate">
+            <summary>Return a V3 signature object containing the current signature state.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.MiscPemGenerator">
+            PEM generator for the original set of PEM objects used in Open SSL.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemObjectGenerator.Generate">
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </returns>
+            <exception cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemGenerationException"></exception>
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.PemReader">
+            Class for reading OpenSSL PEM encoded streams containing 
+            X509 certificates, PKCS8 encoded keys and PKCS7 objects.
+            <p>
+            In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
+            Certificates will be returned using the appropriate java.security type.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemReader.ReadPemObject">
+            <returns>
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.#ctor(System.IO.TextReader)">
+             Create a new PemReader
+            
+             @param reader the Reader
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.#ctor(System.IO.TextReader,Org.BouncyCastle.OpenSsl.IPasswordFinder)">
+             Create a new PemReader with a password finder
+            
+             @param reader the Reader
+             @param pFinder the password finder
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCertificate(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509Certificate.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCrl(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509CRL.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadCertificateRequest(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a PKCS10 certification request.
+            
+             @return the certificate request.
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadAttributeCertificate(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a X509 Attribute Certificate.
+            
+             @return the X509 Attribute Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadPkcs7(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
+             API.
+            
+             @return the X509Certificate
+             @throws IOException if an I/O error occured
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemReader.ReadPrivateKey(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+            Read a Key Pair
+        </member>
+        <member name="T:Org.BouncyCastle.OpenSsl.PemWriter">
+            <remarks>General purpose writer for OpenSSL PEM objects.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.IO.Pem.PemWriter">
+            A generic PEM writer, based on RFC 1421
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemWriter.#ctor(System.IO.TextWriter)">
+             Base constructor.
+            
+             @param out output stream to use.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemWriter.GetOutputSize(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+             Return the number of bytes or characters required to contain the
+             passed in object if it is PEM encoded.
+            
+             @param obj pem object to be output
+             @return an estimate of the number of bytes
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.PemWriter.#ctor(System.IO.TextWriter)">
+            <param name="writer">The TextWriter object to write the output to.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.Pkcs8Generator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             Constructor for an unencrypted private key PEM object.
+            
+             @param key private key to be encoded.
+        </member>
+        <member name="M:Org.BouncyCastle.OpenSsl.Pkcs8Generator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.String)">
+             Constructor for an encrypted private key PEM object.
+            
+             @param key       private key to be encoded
+             @param algorithm encryption algorithm to use
+             @param provider  provider to use
+             @throws NoSuchAlgorithmException if algorithm/mode cannot be found
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest">
+             <remarks>
+             A class for verifying and creating Pkcs10 Certification requests.
+             </remarks>
+             <code>
+             CertificationRequest ::= Sequence {
+               certificationRequestInfo  CertificationRequestInfo,
+               signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+               signature                 BIT STRING
+             }
+            
+             CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </code>
+             see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Asn1.Asn1Set,Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             <summary>
+             Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+             </summary>
+            <param name="signatureAlgorithm">Name of Sig Alg.</param>
+             <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+             <param name="publicKey">Public Key to be included in cert reqest.</param>
+             <param name="attributes">ASN1Set of Attributes.</param>
+             <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.GetPublicKey">
+            <summary>
+            Get the public key.
+            </summary>
+            <returns>The public key.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest.Verify">
+            <summary>
+            Verify Pkcs10 Cert Request is valid.
+            </summary>
+            <returns>true = valid.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned">
+             <remarks>
+             A class for creating and verifying Pkcs10 Certification requests (this is an extension on <see cref="T:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequest"/>).
+             The requests are made using delay signing. This is useful for situations where
+             the private key is in another environment and not directly accessible (e.g. HSM)
+             So the first step creates the request, then the signing is done outside this
+             object and the signature is then used to complete the request.
+             </remarks>
+             <code>
+             CertificationRequest ::= Sequence {
+               certificationRequestInfo  CertificationRequestInfo,
+               signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+               signature                 BIT STRING
+             }
+            
+             CertificationRequestInfo ::= Sequence {
+               version             Integer { v1(0) } (v1,...),
+               subject             Name,
+               subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+               attributes          [0] Attributes{{ CRIAttributes }}
+              }
+            
+              Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+            
+              Attr { ATTRIBUTE:IOSet } ::= Sequence {
+                type    ATTRIBUTE.&id({IOSet}),
+                values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+              }
+             </code>
+             see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned.#ctor(System.String,Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Asn1.Asn1Set)">
+            <summary>
+            Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+            </summary>
+            <param name="signatureAlgorithm">Name of Sig Alg.</param>
+            <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+            <param name="publicKey">Public Key to be included in cert reqest.</param>
+            <param name="attributes">ASN1Set of Attributes.</param>
+            <remarks>
+            After the object is constructed use the <see cref="M:Org.BouncyCastle.Pkcs.Pkcs10CertificationRequestDelaySigned.GetDataToSign"/> and finally the
+            SignRequest methods to finalize the request.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Store.GetCertificate(System.String)">
+            simply return the cert entry for the private key
+        </member>
+        <member name="T:Org.BouncyCastle.Pkcs.Pkcs12Utilities">
+            Utility class for reencoding PKCS#12 files to definite length.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(System.Byte[])">
+             Just re-encode the outer layer of the PKCS#12 file to definite length encoding.
+            
+             @param berPKCS12File - original PKCS#12 file
+             @return a byte array representing the DER encoding of the PFX structure
+             @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Pkcs.Pkcs12Utilities.ConvertToDefiniteLength(System.Byte[],System.Char[])">
+             Re-encode the PKCS#12 structure to definite length encoding at the inner layer
+             as well, recomputing the MAC accordingly.
+            
+             @param berPKCS12File - original PKCS12 file.
+             @param provider - provider to use for MAC calculation.
+             @return a byte array representing the DER encoding of the PFX structure.
+             @throws IOException on parsing, encoding errors.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.CertStatus.RevocationDate">
+            <summary>
+            Returns the revocationDate.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.CertStatus.Status">
+            <summary>
+            Returns the certStatus.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.GetSupportedExtensions">
+            Returns an immutable <code>Set</code> of X.509 attribute certificate
+            extensions that this <code>PkixAttrCertChecker</code> supports or
+            <code>null</code> if no extensions are supported.
+            <p>
+            Each element of the set is a <code>String</code> representing the
+            Object Identifier (OID) of the X.509 extension that is supported.
+            </p>
+            <p>
+            All X.509 attribute certificate extensions that a
+            <code>PkixAttrCertChecker</code> might possibly be able to process
+            should be included in the set.
+            </p>
+            
+            @return an immutable <code>Set</code> of X.509 extension OIDs (in
+                    <code>String</code> format) supported by this
+                    <code>PkixAttrCertChecker</code>, or <code>null</code> if no
+                    extensions are supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.Check(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixCertPath,Org.BouncyCastle.Pkix.PkixCertPath,System.Collections.ICollection)">
+            Performs checks on the specified attribute certificate. Every handled
+            extension is rmeoved from the <code>unresolvedCritExts</code>
+            collection.
+            
+            @param attrCert The attribute certificate to be checked.
+            @param certPath The certificate path which belongs to the attribute
+                       certificate issuer public key certificate.
+            @param holderCertPath The certificate path which belongs to the holder
+                       certificate.
+            @param unresolvedCritExts a <code>Collection</code> of OID strings
+                       representing the current set of unresolved critical extensions
+            @throws CertPathValidatorException if the specified attribute certificate
+                        does not pass the check.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertChecker.Clone">
+            Returns a clone of this object.
+            
+            @return a copy of this <code>PkixAttrCertChecker</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertPathBuilder.Build(Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Build and validate a CertPath using the given parameter.
+            
+             @param params PKIXBuilderParameters object containing all information to
+                        build the CertPath
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixAttrCertPathValidator">
+            CertPathValidatorSpi implementation for X.509 Attribute Certificates la RFC 3281.
+            
+            @see org.bouncycastle.x509.ExtendedPkixParameters
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixAttrCertPathValidator.Validate(Org.BouncyCastle.Pkix.PkixCertPath,Org.BouncyCastle.Pkix.PkixParameters)">
+            Validates an attribute certificate with the given certificate path.
+            
+            <p>
+            <code>params</code> must be an instance of
+            <code>ExtendedPkixParameters</code>.
+            </p><p>
+            The target constraints in the <code>params</code> must be an
+            <code>X509AttrCertStoreSelector</code> with at least the attribute
+            certificate criterion set. Obey that also target informations may be
+            necessary to correctly validate this attribute certificate.
+            </p><p>
+            The attribute certificate issuer must be added to the trusted attribute
+            issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
+            </p>
+            @param certPath The certificate path which belongs to the attribute
+                       certificate issuer public key certificate.
+            @param params The PKIX parameters.
+            @return A <code>PKIXCertPathValidatorResult</code> of the result of
+                    validating the <code>certPath</code>.
+            @throws InvalidAlgorithmParameterException if <code>params</code> is
+                        inappropriate for this validator.
+            @throws CertPathValidatorException if the verification fails.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixBuilderParameters">
+            <summary>
+            Summary description for PkixBuilderParameters.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixParameters">
+            <summary>
+            Summary description for PkixParameters.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixParameters.PkixValidityModel">
+            This is the default PKIX validity model. Actually there are two variants
+            of this: The PKIX model and the modified PKIX model. The PKIX model
+            verifies that all involved certificates must have been valid at the
+            current time. The modified PKIX model verifies that all involved
+            certificates were valid at the signing time. Both are indirectly choosen
+            with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
+            methods sets the Date when <em>all</em> certificates must have been
+            valid.
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixParameters.ChainValidityModel">
+            This model uses the following validity model. Each certificate must have
+            been valid at the moment where is was used. That means the end
+            certificate must have been valid at the time the signature was done. The
+            CA certificate which signed the end certificate must have been valid,
+            when the end certificate was signed. The CA (or Root CA) certificate must
+            have been valid, when the CA certificate was signed and so on. So the
+            {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
+            the <em>end certificate</em> must have been valid. <p/> It is used e.g.
+            in the German signature law.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.#ctor(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Creates an instance of PKIXParameters with the specified Set of
+             most-trusted CAs. Each element of the set is a TrustAnchor.<br />
+             <br />
+             Note that the Set is copied to protect against subsequent modifications.
+            
+             @param trustAnchors
+                        a Set of TrustAnchors
+            
+             @exception InvalidAlgorithmParameterException
+                            if the specified Set is empty
+                            <code>(trustAnchors.isEmpty() == true)</code>
+             @exception NullPointerException
+                            if the specified Set is <code>null</code>
+             @exception ClassCastException
+                            if any of the elements in the Set are not of type
+                            <code>java.security.cert.TrustAnchor</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTargetCertConstraints">
+             Returns the required constraints on the target certificate. The
+             constraints are returned as an instance of CertSelector. If
+             <code>null</code>, no constraints are defined.<br />
+             <br />
+             Note that the CertSelector returned is cloned to protect against
+             subsequent modifications.
+            
+             @return a CertSelector specifying the constraints on the target
+                     certificate (or <code>null</code>)
+            
+             @see #setTargetCertConstraints(CertSelector)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTargetCertConstraints(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Sets the required constraints on the target certificate. The constraints
+             are specified as an instance of CertSelector. If null, no constraints are
+             defined.<br />
+             <br />
+             Note that the CertSelector specified is cloned to protect against
+             subsequent modifications.
+            
+             @param selector
+                        a CertSelector specifying the constraints on the target
+                        certificate (or <code>null</code>)
+            
+             @see #getTargetCertConstraints()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetInitialPolicies">
+             Returns an immutable Set of initial policy identifiers (OID strings),
+             indicating that any one of these policies would be acceptable to the
+             certificate user for the purposes of certification path processing. The
+             default return value is an empty <code>Set</code>, which is
+             interpreted as meaning that any policy would be acceptable.
+            
+             @return an immutable <code>Set</code> of initial policy OIDs in String
+                     format, or an empty <code>Set</code> (implying any policy is
+                     acceptable). Never returns <code>null</code>.
+            
+             @see #setInitialPolicies(java.util.Set)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetInitialPolicies(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the <code>Set</code> of initial policy identifiers (OID strings),
+             indicating that any one of these policies would be acceptable to the
+             certificate user for the purposes of certification path processing. By
+             default, any policy is acceptable (i.e. all policies), so a user that
+             wants to allow any policy as acceptable does not need to call this
+             method, or can call it with an empty <code>Set</code> (or
+             <code>null</code>).<br />
+             <br />
+             Note that the Set is copied to protect against subsequent modifications.<br />
+             <br />
+            
+             @param initialPolicies
+                        a Set of initial policy OIDs in String format (or
+                        <code>null</code>)
+            
+             @exception ClassCastException
+                            if any of the elements in the set are not of type String
+            
+             @see #getInitialPolicies()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetCertPathCheckers(System.Collections.IList)">
+             Sets a <code>List</code> of additional certification path checkers. If
+             the specified List contains an object that is not a PKIXCertPathChecker,
+             it is ignored.<br />
+             <br />
+             Each <code>PKIXCertPathChecker</code> specified implements additional
+             checks on a certificate. Typically, these are checks to process and
+             verify private extensions contained in certificates. Each
+             <code>PKIXCertPathChecker</code> should be instantiated with any
+             initialization parameters needed to execute the check.<br />
+             <br />
+             This method allows sophisticated applications to extend a PKIX
+             <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each
+             of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX
+             <code>CertPathValidator</code> or <code>CertPathBuilder</code> for
+             each certificate processed or validated.<br />
+             <br />
+             Regardless of whether these additional PKIXCertPathCheckers are set, a
+             PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code>
+             must perform all of the required PKIX checks on each certificate. The one
+             exception to this rule is if the RevocationEnabled flag is set to false
+             (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled}
+             method).<br />
+             <br />
+             Note that the List supplied here is copied and each PKIXCertPathChecker
+             in the list is cloned to protect against subsequent modifications.
+            
+             @param checkers
+                        a List of PKIXCertPathCheckers. May be null, in which case no
+                        additional checkers will be used.
+             @exception ClassCastException
+                            if any of the elements in the list are not of type
+                            <code>java.security.cert.PKIXCertPathChecker</code>
+             @see #getCertPathCheckers()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetCertPathCheckers">
+             Returns the List of certification path checkers. Each PKIXCertPathChecker
+             in the returned IList is cloned to protect against subsequent modifications.
+            
+             @return an immutable List of PKIXCertPathCheckers (may be empty, but not
+                     <code>null</code>)
+            
+             @see #setCertPathCheckers(java.util.List)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddCertPathChecker(Org.BouncyCastle.Pkix.PkixCertPathChecker)">
+             Adds a <code>PKIXCertPathChecker</code> to the list of certification
+             path checkers. See the {@link #setCertPathCheckers setCertPathCheckers}
+             method for more details.
+             <p>
+             Note that the <code>PKIXCertPathChecker</code> is cloned to protect
+             against subsequent modifications.</p>
+            
+             @param checker a <code>PKIXCertPathChecker</code> to add to the list of
+             checks. If <code>null</code>, the checker is ignored (not added to list).
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetParams(Org.BouncyCastle.Pkix.PkixParameters)">
+             Method to support <code>Clone()</code> under J2ME.
+             <code>super.Clone()</code> does not exist and fields are not copied.
+            
+             @param params Parameters to set. If this are
+                        <code>ExtendedPkixParameters</code> they are copied to.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetStores(System.Collections.IList)">
+             Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+             <p>
+             The <code>IList</code> is cloned.
+             </p>
+            
+             @param stores A list of stores to use.
+             @see #getStores
+             @throws ClassCastException if an element of <code>stores</code> is not
+                         a {@link Store}.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddStore(Org.BouncyCastle.X509.Store.IX509Store)">
+             Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
+             certificates or cross certificates.
+             <p>
+             This method should be used to add local stores, like collection based
+             X.509 stores, if available. Local stores should be considered first,
+             before trying to use additional (remote) locations, because they do not
+             need possible additional network traffic.
+             </p><p>
+             If <code>store</code> is <code>null</code> it is ignored.
+             </p>
+            
+             @param store The store to add.
+             @see #getStores
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.AddAdditionalStore(Org.BouncyCastle.X509.Store.IX509Store)">
+             Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates,
+             attribute certificates or cross certificates.
+             <p>
+             You should not use this method. This method is used for adding additional
+             X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
+             during X.509 object processing, e.g. in certificates or CRLs. This method
+             is used in PKIX certification path processing.
+             </p><p>
+             If <code>store</code> is <code>null</code> it is ignored.
+             </p>
+            
+             @param store The store to add.
+             @see #getStores()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetAdditionalStores">
+             Returns an <code>IList</code> of additional Bouncy Castle
+             <code>Store</code>s used for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+            
+             @return an immutable <code>IList</code> of additional Bouncy Castle
+                     <code>Store</code>s. Never <code>null</code>.
+            
+             @see #addAddionalStore(Store)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetStores">
+             Returns an <code>IList</code> of Bouncy Castle
+             <code>Store</code>s used for finding CRLs, certificates, attribute
+             certificates or cross certificates.
+            
+             @return an immutable <code>IList</code> of Bouncy Castle
+                     <code>Store</code>s. Never <code>null</code>.
+            
+             @see #setStores(IList)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetAdditionalLocationsEnabled(System.Boolean)">
+             Sets if additional {@link X509Store}s for locations like LDAP found in
+             certificates or CRLs should be used.
+            
+             @param enabled <code>true</code> if additional stores are used.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTargetConstraints">
+             Returns the required constraints on the target certificate or attribute
+             certificate. The constraints are returned as an instance of
+             <code>IX509Selector</code>. If <code>null</code>, no constraints are
+             defined.
+            
+             <p>
+             The target certificate in a PKIX path may be a certificate or an
+             attribute certificate.
+             </p><p>
+             Note that the <code>IX509Selector</code> returned is cloned to protect
+             against subsequent modifications.
+             </p>
+             @return a <code>IX509Selector</code> specifying the constraints on the
+                     target certificate or attribute certificate (or <code>null</code>)
+             @see #setTargetConstraints
+             @see X509CertStoreSelector
+             @see X509AttributeCertStoreSelector
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTargetConstraints(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Sets the required constraints on the target certificate or attribute
+             certificate. The constraints are specified as an instance of
+             <code>IX509Selector</code>. If <code>null</code>, no constraints are
+             defined.
+             <p>
+             The target certificate in a PKIX path may be a certificate or an
+             attribute certificate.
+             </p><p>
+             Note that the <code>IX509Selector</code> specified is cloned to protect
+             against subsequent modifications.
+             </p>
+            
+             @param selector a <code>IX509Selector</code> specifying the constraints on
+                        the target certificate or attribute certificate (or
+                        <code>null</code>)
+             @see #getTargetConstraints
+             @see X509CertStoreSelector
+             @see X509AttributeCertStoreSelector
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetTrustedACIssuers">
+             Returns the trusted attribute certificate issuers. If attribute
+             certificates is verified the trusted AC issuers must be set.
+             <p>
+             The returned <code>ISet</code> consists of <code>TrustAnchor</code>s.
+             </p><p>
+             The returned <code>ISet</code> is immutable. Never <code>null</code>
+             </p>
+            
+             @return Returns an immutable set of the trusted AC issuers.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetTrustedACIssuers(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the trusted attribute certificate issuers. If attribute certificates
+             is verified the trusted AC issuers must be set.
+             <p>
+             The <code>trustedACIssuers</code> must be a <code>ISet</code> of
+             <code>TrustAnchor</code>
+             </p><p>
+             The given set is cloned.
+             </p>
+            
+             @param trustedACIssuers The trusted AC issuers to set. Is never
+                        <code>null</code>.
+             @throws ClassCastException if an element of <code>stores</code> is not
+                         a <code>TrustAnchor</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetNecessaryACAttributes">
+             Returns the neccessary attributes which must be contained in an attribute
+             certificate.
+             <p>
+             The returned <code>ISet</code> is immutable and contains
+             <code>String</code>s with the OIDs.
+             </p>
+            
+             @return Returns the necessary AC attributes.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetNecessaryACAttributes(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the neccessary which must be contained in an attribute certificate.
+             <p>
+             The <code>ISet</code> must contain <code>String</code>s with the
+             OIDs.
+             </p><p>
+             The set is cloned.
+             </p>
+            
+             @param necessaryACAttributes The necessary AC attributes to set.
+             @throws ClassCastException if an element of
+                         <code>necessaryACAttributes</code> is not a
+                         <code>String</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetProhibitedACAttributes">
+             Returns the attribute certificates which are not allowed.
+             <p>
+             The returned <code>ISet</code> is immutable and contains
+             <code>String</code>s with the OIDs.
+             </p>
+            
+             @return Returns the prohibited AC attributes. Is never <code>null</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetProhibitedACAttributes(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the attribute certificates which are not allowed.
+             <p>
+             The <code>ISet</code> must contain <code>String</code>s with the
+             OIDs.
+             </p><p>
+             The set is cloned.
+             </p>
+            
+             @param prohibitedACAttributes The prohibited AC attributes to set.
+             @throws ClassCastException if an element of
+                         <code>prohibitedACAttributes</code> is not a
+                         <code>String</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.GetAttrCertCheckers">
+             Returns the attribute certificate checker. The returned set contains
+             {@link PKIXAttrCertChecker}s and is immutable.
+            
+             @return Returns the attribute certificate checker. Is never
+                     <code>null</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixParameters.SetAttrCertCheckers(Org.BouncyCastle.Utilities.Collections.ISet)">
+             Sets the attribute certificate checkers.
+             <p>
+             All elements in the <code>ISet</code> must a {@link PKIXAttrCertChecker}.
+             </p>
+             <p>
+             The given set is cloned.
+             </p>
+            
+             @param attrCertCheckers The attribute certificate checkers to set. Is
+                        never <code>null</code>.
+             @throws ClassCastException if an element of <code>attrCertCheckers</code>
+                         is not a <code>PKIXAttrCertChecker</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.IsUseDeltasEnabled">
+            Whether delta CRLs should be used for checking the revocation status.
+            Defaults to <code>false</code>.
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.ValidityModel">
+            The validity model.
+            @see #CHAIN_VALIDITY_MODEL
+            @see #PKIX_VALIDITY_MODEL
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixParameters.IsAdditionalLocationsEnabled">
+             Returns if additional {@link X509Store}s for locations like LDAP found
+             in certificates or CRLs should be used.
+            
+             @return Returns <code>true</code> if additional stores are used.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.GetInstance(Org.BouncyCastle.Pkix.PkixParameters)">
+             Returns an instance of <code>PkixBuilderParameters</code>.
+             <p>
+             This method can be used to get a copy from other
+             <code>PKIXBuilderParameters</code>, <code>PKIXParameters</code>,
+             and <code>ExtendedPKIXParameters</code> instances.
+             </p>
+            
+             @param pkixParams The PKIX parameters to create a copy of.
+             @return An <code>PkixBuilderParameters</code> instance.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.GetExcludedCerts">
+            <summary>
+            Excluded certificates are not used for building a certification path.
+            </summary>
+            <returns>the excluded certificates.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.SetExcludedCerts(Org.BouncyCastle.Utilities.Collections.ISet)">
+            <summary>
+            Sets the excluded certificates which are not used for building a
+            certification path. If the <code>ISet</code> is <code>null</code> an
+            empty set is assumed.
+            </summary>
+            <remarks>
+            The given set is cloned to protect it against subsequent modifications.
+            </remarks>
+            <param name="excludedCerts">The excluded certificates to set.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.SetParams(Org.BouncyCastle.Pkix.PkixParameters)">
+            Can alse handle <code>ExtendedPKIXBuilderParameters</code> and
+            <code>PKIXBuilderParameters</code>.
+            
+            @param params Parameters to set.
+            @see org.bouncycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters)
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixBuilderParameters.Clone">
+             Makes a copy of this <code>PKIXParameters</code> object. Changes to the
+             copy will not affect the original and vice versa.
+            
+             @return a copy of this <code>PKIXParameters</code> object
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPath">
+             An immutable sequence of certificates (a certification path).<br />
+             <br />
+             This is an abstract class that defines the methods common to all CertPaths.
+             Subclasses can handle different kinds of certificates (X.509, PGP, etc.).<br />
+             <br />
+             All CertPath objects have a type, a list of Certificates, and one or more
+             supported encodings. Because the CertPath class is immutable, a CertPath
+             cannot change in any externally visible way after being constructed. This
+             stipulation applies to all public fields and methods of this class and any
+             added or overridden by subclasses.<br />
+             <br />
+             The type is a string that identifies the type of Certificates in the
+             certification path. For each certificate cert in a certification path
+             certPath, cert.getType().equals(certPath.getType()) must be true.<br />
+             <br />
+             The list of Certificates is an ordered List of zero or more Certificates.
+             This List and all of the Certificates contained in it must be immutable.<br />
+             <br />
+             Each CertPath object must support one or more encodings so that the object
+             can be translated into a byte array for storage or transmission to other
+             parties. Preferably, these encodings should be well-documented standards
+             (such as PKCS#7). One of the encodings supported by a CertPath is considered
+             the default encoding. This encoding is used if no encoding is explicitly
+             requested (for the {@link #getEncoded()} method, for instance).<br />
+             <br />
+             All CertPath objects are also Serializable. CertPath objects are resolved
+             into an alternate {@link CertPathRep} object during serialization. This
+             allows a CertPath object to be serialized into an equivalent representation
+             regardless of its underlying implementation.<br />
+             <br />
+             CertPath objects can be created with a CertificateFactory or they can be
+             returned by other classes, such as a CertPathBuilder.<br />
+             <br />
+             By convention, X.509 CertPaths (consisting of X509Certificates), are ordered
+             starting with the target certificate and ending with a certificate issued by
+             the trust anchor. That is, the issuer of one certificate is the subject of
+             the following one. The certificate representing the
+             {@link TrustAnchor TrustAnchor} should not be included in the certification
+             path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX
+             CertPathValidators will detect any departure from these conventions that
+             cause the certification path to be invalid and throw a
+             CertPathValidatorException.<br />
+             <br />
+             <strong>Concurrent Access</strong><br />
+             <br />
+             All CertPath objects must be thread-safe. That is, multiple threads may
+             concurrently invoke the methods defined in this class on a single CertPath
+             object (or more than one) with no ill effects. This is also true for the List
+             returned by CertPath.getCertificates.<br />
+             <br />
+             Requiring CertPath objects to be immutable and thread-safe allows them to be
+             passed around to various pieces of code without worrying about coordinating
+             access. Providing this thread-safety is generally not difficult, since the
+             CertPath and List objects in question are immutable.
+            
+             @see CertificateFactory
+             @see CertPathBuilder
+            <summary>
+            CertPath implementation for X.509 certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.SortCerts(System.Collections.IList)">
+            @param certs
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.#ctor(System.Collections.ICollection)">
+             Creates a CertPath of the specified type.
+             This constructor is protected because most users should use
+             a CertificateFactory to create CertPaths.
+             @param type the standard name of the type of Certificatesin this path
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.#ctor(System.IO.Stream,System.String)">
+             Creates a CertPath of the specified type.
+             This constructor is protected because most users should use
+             a CertificateFactory to create CertPaths.
+            
+             @param type the standard name of the type of Certificatesin this path
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.Equals(System.Object)">
+             Compares this certification path for equality with the specified object.
+             Two CertPaths are equal if and only if their types are equal and their
+             certificate Lists (and by implication the Certificates in those Lists)
+             are equal. A CertPath is never equal to an object that is not a CertPath.<br />
+             <br />
+             This algorithm is implemented by this method. If it is overridden, the
+             behavior specified here must be maintained.
+            
+             @param other
+                        the object to test for equality with this certification path
+            
+             @return true if the specified object is equal to this certification path,
+                     false otherwise
+            
+             @see Object#hashCode() Object.hashCode()
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.GetEncoded">
+             Returns the encoded form of this certification path, using
+             the default encoding.
+            
+             @return the encoded bytes
+             @exception CertificateEncodingException if an encoding error occurs
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.GetEncoded(System.String)">
+             Returns the encoded form of this certification path, using
+             the specified encoding.
+            
+             @param encoding the name of the encoding to use
+             @return the encoded bytes
+             @exception CertificateEncodingException if an encoding error
+             occurs or the encoding requested is not supported
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPath.ToAsn1Object(Org.BouncyCastle.X509.X509Certificate)">
+             Return a DERObject containing the encoded certificate.
+            
+             @param cert the X509Certificate object to be encoded
+            
+             @return the DERObject
+            
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPath.Encodings">
+             Returns an iteration of the encodings supported by this
+             certification path, with the default encoding
+             first. Attempts to modify the returned Iterator via its
+             remove method result in an UnsupportedOperationException.
+            
+             @return an Iterator over the names of the supported encodings (as Strings)
+            
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPath.Certificates">
+            <summary>
+            Returns the list of certificates in this certification
+            path.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilder">
+             Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
+            
+             @see CertPathBuilderSpi
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathBuilder.Build(Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Build and validate a CertPath using the given parameter.
+            
+             @param params PKIXBuilderParameters object containing all information to
+                        build the CertPath
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilderException">
+            <summary>
+            Summary description for PkixCertPathBuilderException.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathBuilderResult">
+            <summary>
+            Summary description for PkixCertPathBuilderResult.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorResult">
+            <summary>
+            Summary description for PkixCertPathValidatorResult.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Init(System.Boolean)">
+                     * Initializes the internal state of this <code>PKIXCertPathChecker</code>.
+                     * <p>
+                     * The <code>forward</code> flag specifies the order that certificates
+                     * will be passed to the {@link #check check} method (forward or reverse). A
+                     * <code>PKIXCertPathChecker</code> <b>must</b> support reverse checking
+                     * and <b>may</b> support forward checking.
+            		 * </p>
+                     * 
+                     * @param forward
+                     *            the order that certificates are presented to the
+                     *            <code>check</code> method. If <code>true</code>,
+                     *            certificates are presented from target to most-trusted CA
+                     *            (forward); if <code>false</code>, from most-trusted CA to
+                     *            target (reverse).
+                     * @exception CertPathValidatorException
+                     *                if this <code>PKIXCertPathChecker</code> is unable to
+                     *                check certificates in the specified order; it should never
+                     *                be thrown if the forward flag is false since reverse
+                     *                checking must be supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.IsForwardCheckingSupported">
+            Indicates if forward checking is supported. Forward checking refers to
+            the ability of the <code>PKIXCertPathChecker</code> to perform its
+            checks when certificates are presented to the <code>check</code> method
+            in the forward direction (from target to most-trusted CA).
+            
+            @return <code>true</code> if forward checking is supported,
+                    <code>false</code> otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.GetSupportedExtensions">
+                     * Returns an immutable <code>Set</code> of X.509 certificate extensions
+                     * that this <code>PKIXCertPathChecker</code> supports (i.e. recognizes,
+                     * is able to process), or <code>null</code> if no extensions are
+                     * supported.
+                     * <p>
+                     * Each element of the set is a <code>String</code> representing the
+                     * Object Identifier (OID) of the X.509 extension that is supported. The OID
+                     * is represented by a set of nonnegative integers separated by periods.
+                     * </p><p>
+                     * All X.509 certificate extensions that a <code>PKIXCertPathChecker</code>
+                     * might possibly be able to process should be included in the set.
+            		 * </p>
+                     * 
+                     * @return an immutable <code>Set</code> of X.509 extension OIDs (in
+                     *         <code>String</code> format) supported by this
+                     *         <code>PKIXCertPathChecker</code>, or <code>null</code> if no
+                     *         extensions are supported
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Check(Org.BouncyCastle.X509.X509Certificate,System.Collections.ICollection)">
+            Performs the check(s) on the specified certificate using its internal
+            state and removes any critical extensions that it processes from the
+            specified collection of OID strings that represent the unresolved
+            critical extensions. The certificates are presented in the order
+            specified by the <code>init</code> method.
+            
+            @param cert
+                       the <code>Certificate</code> to be checked
+            @param unresolvedCritExts
+                       a <code>Collection</code> of OID strings representing the
+                       current set of unresolved critical extensions
+            @exception CertPathValidatorException
+                           if the specified certificate does not pass the check
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathChecker.Clone">
+            Returns a clone of this object. Calls the <code>Object.clone()</code>
+            method. All subclasses which maintain state must support and override
+            this method, if necessary.
+            
+            @return a copy of this <code>PKIXCertPathChecker</code>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidator">
+            The <i>Service Provider Interface</i> (<b>SPI</b>)
+            for the {@link CertPathValidator CertPathValidator} class. All
+            <code>CertPathValidator</code> implementations must include a class (the
+            SPI class) that extends this class (<code>CertPathValidatorSpi</code>)
+            and implements all of its methods. In general, instances of this class
+            should only be accessed through the <code>CertPathValidator</code> class.
+            For details, see the Java Cryptography Architecture.<br />
+            <br />
+            <b>Concurrent Access</b><br />
+            <br />
+            Instances of this class need not be protected against concurrent
+            access from multiple threads. Threads that need to access a single
+            <code>CertPathValidatorSpi</code> instance concurrently should synchronize
+            amongst themselves and provide the necessary locking before calling the
+            wrapping <code>CertPathValidator</code> object.<br />
+            <br />
+            However, implementations of <code>CertPathValidatorSpi</code> may still
+            encounter concurrency issues, since multiple threads each
+            manipulating a different <code>CertPathValidatorSpi</code> instance need not
+            synchronize.
+            <summary>
+            CertPathValidatorSpi implementation for X.509 Certificate validation a la RFC
+            3280.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorException">
+             An exception indicating one of a variety of problems encountered when 
+             validating a certification path. <br />
+             <br />
+             A <code>CertPathValidatorException</code> provides support for wrapping
+             exceptions. The {@link #getCause getCause} method returns the throwable, 
+             if any, that caused this exception to be thrown. <br />
+             <br />
+             A <code>CertPathValidatorException</code> may also include the 
+             certification path that was being validated when the exception was thrown 
+             and the index of the certificate in the certification path that caused the 
+             exception to be thrown. Use the {@link #getCertPath getCertPath} and
+             {@link #getIndex getIndex} methods to retrieve this information.<br />
+             <br />
+             <b>Concurrent Access</b><br />
+             <br />
+             Unless otherwise specified, the methods defined in this class are not
+             thread-safe. Multiple threads that need to access a single
+             object concurrently should synchronize amongst themselves and
+             provide the necessary locking. Multiple threads each manipulating
+             separate objects need not synchronize.
+            
+             @see CertPathValidator
+            
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the given detail
+            message. A detail message is a <code>String</code> that describes this
+            particular exception. 
+            </summary>
+            <param name="message">the detail message</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String,System.Exception)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the specified
+            detail message and cause.
+            </summary>
+            <param name="message">the detail message</param>
+            <param name="cause">the cause (which is saved for later retrieval by the
+            {@link #getCause getCause()} method). (A <code>null</code>
+            value is permitted, and indicates that the cause is
+            nonexistent or unknown.)</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.#ctor(System.String,System.Exception,Org.BouncyCastle.Pkix.PkixCertPath,System.Int32)">
+            <summary>
+            Creates a <code>PkixCertPathValidatorException</code> with the specified
+            detail message, cause, certification path, and index.
+            </summary>
+            <param name="message">the detail message (or <code>null</code> if none)</param>
+            <param name="cause">the cause (or <code>null</code> if none)</param>
+            <param name="certPath">the certification path that was in the process of being
+            validated when the error was encountered</param>
+            <param name="index">the index of the certificate in the certification path that</param>																																																																																   * 
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.Message">
+            <summary>
+            Returns the detail message for this <code>CertPathValidatorException</code>.
+            </summary>
+            <returns>the detail message, or <code>null</code> if neither the message nor cause were specified</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.CertPath">
+            Returns the certification path that was being validated when the
+            exception was thrown.
+            
+            @return the <code>CertPath</code> that was being validated when the
+                    exception was thrown (or <code>null</code> if not specified)
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.PkixCertPathValidatorException.Index">
+            Returns the index of the certificate in the certification path that
+            caused the exception to be thrown. Note that the list of certificates in
+            a <code>CertPath</code> is zero based. If no index has been set, -1 is
+            returned.
+            
+            @return the index that has been set, or -1 if none has been set
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities">
+            <summary>
+            Summary description for PkixCertPathValidatorUtilities.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.KEY_CERT_SIGN">
+            <summary>
+            key usage bits
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindTrustAnchor(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Utilities.Collections.ISet)">
+            <summary>
+            Search the given Set of TrustAnchor's for one that is the
+            issuer of the given X509 certificate.
+            </summary>
+            <param name="cert">the X509 certificate</param>
+            <param name="trustAnchors">a Set of TrustAnchor's</param>
+            <returns>the <code>TrustAnchor</code> object if found or
+            <code>null</code> if not.
+            </returns>
+            @exception
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetIssuerPrincipal(System.Object)">
+            <summary>
+            Returns the issuer of an attribute certificate or certificate.
+            </summary>
+            <param name="cert">The attribute certificate or certificate.</param>
+            <returns>The issuer as <code>X500Principal</code>.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetNextWorkingKey(System.Collections.IList,System.Int32)">
+             Return the next working key inheriting DSA parameters if necessary.
+             <p>
+             This methods inherits DSA parameters from the indexed certificate or
+             previous certificates in the certificate chain to the returned
+             <code>PublicKey</code>. The list is searched upwards, meaning the end
+             certificate is at position 0 and previous certificates are following.
+             </p>
+             <p>
+             If the indexed certificate does not contain a DSA key this method simply
+             returns the public key. If the DSA key already contains DSA parameters
+             the key is also only returned.
+             </p>
+            
+             @param certs The certification path.
+             @param index The index of the certificate which contains the public key
+                        which should be extended with DSA parameters.
+             @return The public key of the certificate in list position
+                     <code>index</code> extended with DSA parameters if applicable.
+             @throws Exception if DSA parameters cannot be inherited.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindCertificates(Org.BouncyCastle.X509.Store.X509CertStoreSelector,System.Collections.IList)">
+            <summary>
+            Return a Collection of all certificates or attribute certificates found
+            in the X509Store's that are matching the certSelect criteriums.
+            </summary>
+            <param name="certSelect">a {@link Selector} object that will be used to select
+            the certificates</param>
+            <param name="certStores">a List containing only X509Store objects. These
+            are used to search for certificates.</param>
+            <returns>a Collection of all found <see cref="T:Org.BouncyCastle.X509.X509Certificate"/> or
+            org.bouncycastle.x509.X509AttributeCertificate objects.
+            May be empty but never <code>null</code>.</returns>
+            <exception cref="T:System.Exception"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetCrlIssuersFromDistributionPoint(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Collections.ICollection,Org.BouncyCastle.X509.Store.X509CrlStoreSelector,Org.BouncyCastle.Pkix.PkixParameters)">
+             Add the CRL issuers from the cRLIssuer field of the distribution point or
+             from the certificate if not given to the issuer criterion of the
+             <code>selector</code>.
+             <p>
+             The <code>issuerPrincipals</code> are a collection with a single
+             <code>X500Principal</code> for <code>X509Certificate</code>s. For
+             {@link X509AttributeCertificate}s the issuer may contain more than one
+             <code>X500Principal</code>.
+             </p>
+            
+             @param dp The distribution point.
+             @param issuerPrincipals The issuers of the certificate or attribute
+                        certificate which contains the distribution point.
+             @param selector The CRL selector.
+             @param pkixParams The PKIX parameters containing the cert stores.
+             @throws Exception if an exception occurs while processing.
+             @throws ClassCastException if <code>issuerPrincipals</code> does not
+             contain only <code>X500Principal</code>s.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetCompleteCrls(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,System.DateTime,Org.BouncyCastle.Pkix.PkixParameters)">
+             Fetches complete CRLs according to RFC 3280.
+            
+             @param dp The distribution point for which the complete CRL
+             @param cert The <code>X509Certificate</code> or
+                        {@link org.bouncycastle.x509.X509AttributeCertificate} for
+                        which the CRL should be searched.
+             @param currentDate The date for which the delta CRLs must be valid.
+             @param paramsPKIX The extended PKIX parameters.
+             @return A <code>Set</code> of <code>X509CRL</code>s with complete
+                     CRLs.
+             @throws Exception if an exception occurs while picking the CRLs
+                         or no CRLs are found.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetDeltaCrls(System.DateTime,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Crl)">
+             Fetches delta CRLs according to RFC 3280 section 5.2.4.
+            
+             @param currentDate The date for which the delta CRLs must be valid.
+             @param paramsPKIX The extended PKIX parameters.
+             @param completeCRL The complete CRL the delta CRL is for.
+             @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
+             @throws Exception if an exception occurs while picking the delta
+                         CRLs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.FindIssuerCerts(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Pkix.PkixBuilderParameters)">
+             Find the issuer certificates of a given certificate.
+            
+             @param cert
+                        The certificate for which an issuer should be found.
+             @param pkixParams
+             @return A <code>Collection</code> object containing the issuer
+                     <code>X509Certificate</code>s. Never <code>null</code>.
+            
+             @exception Exception
+                            if an error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCertPathValidatorUtilities.GetExtensionValue(Org.BouncyCastle.X509.IX509Extension,Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            <summary>
+            Extract the value of the given extension, if it exists.
+            </summary>
+            <param name="ext">The extension object.</param>
+            <param name="oid">The object identifier to obtain.</param>
+            <returns>Asn1Object</returns>
+            <exception cref="T:System.Exception">if the extension cannot be read.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixCrlUtilities.FindCrls(Org.BouncyCastle.X509.Store.X509CrlStoreSelector,System.Collections.IList)">
+            <summary>
+            crl checking
+            Return a Collection of all CRLs found in the X509Store's that are
+            matching the crlSelect criteriums.
+            </summary>
+            <param name="crlSelect">a {@link X509CRLStoreSelector} object that will be used
+            to select the CRLs</param>
+            <param name="crlStores">a List containing only {@link org.bouncycastle.x509.X509Store
+            X509Store} objects. These are used to search for CRLs</param>
+            <returns>a Collection of all found {@link X509CRL X509CRL} objects. May be
+            empty but never <code>null</code>.
+            </returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectIP(Org.BouncyCastle.Utilities.Collections.ISet,Org.BouncyCastle.Utilities.Collections.ISet)">
+             Returns the intersection of the permitted IP ranges in
+             <code>permitted</code> with <code>ip</code>.
+            
+             @param permitted A <code>Set</code> of permitted IP addresses with
+                              their subnet mask as byte arrays.
+             @param ips       The IP address with its subnet mask.
+             @return The <code>Set</code> of permitted IP ranges intersected with
+                     <code>ip</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.UnionIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Returns the union of the excluded IP ranges in <code>excluded</code>
+             with <code>ip</code>.
+            
+             @param excluded A <code>Set</code> of excluded IP addresses with their
+                             subnet mask as byte arrays.
+             @param ip       The IP address with its subnet mask.
+             @return The <code>Set</code> of excluded IP ranges unified with
+                     <code>ip</code> as byte arrays.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.UnionIPRange(System.Byte[],System.Byte[])">
+             Calculates the union if two IP ranges.
+            
+             @param ipWithSubmask1 The first IP address with its subnet mask.
+             @param ipWithSubmask2 The second IP address with its subnet mask.
+             @return A <code>Set</code> with the union of both addresses.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectIPRange(System.Byte[],System.Byte[])">
+             Calculates the interesction if two IP ranges.
+            
+             @param ipWithSubmask1 The first IP address with its subnet mask.
+             @param ipWithSubmask2 The second IP address with its subnet mask.
+             @return A <code>Set</code> with the single IP address with its subnet
+                     mask as a byte array or an empty <code>Set</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IpWithSubnetMask(System.Byte[],System.Byte[])">
+             Concatenates the IP address with its subnet mask.
+            
+             @param ip         The IP address.
+             @param subnetMask Its subnet mask.
+             @return The concatenated IP address with its subnet mask.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.ExtractIPsAndSubnetMasks(System.Byte[],System.Byte[])">
+             Splits the IP addresses and their subnet mask.
+            
+             @param ipWithSubmask1 The first IP address with the subnet mask.
+             @param ipWithSubmask2 The second IP address with the subnet mask.
+             @return An array with two elements. Each element contains the IP address
+                     and the subnet mask in this order.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.MinMaxIPs(System.Byte[],System.Byte[],System.Byte[],System.Byte[])">
+             Based on the two IP addresses and their subnet masks the IP range is
+             computed for each IP address - subnet mask pair and returned as the
+             minimum IP address and the maximum address of the range.
+            
+             @param ip1         The first IP address.
+             @param subnetmask1 The subnet mask of the first IP address.
+             @param ip2         The second IP address.
+             @param subnetmask2 The subnet mask of the second IP address.
+             @return A array with two elements. The first/second element contains the
+                     min and max IP address of the first/second IP address and its
+                     subnet mask.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.CheckPermittedIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Checks if the IP <code>ip</code> is included in the permitted ISet
+             <code>permitted</code>.
+            
+             @param permitted A <code>Set</code> of permitted IP addresses with
+                              their subnet mask as byte arrays.
+             @param ip        The IP address.
+             @throws PkixNameConstraintValidatorException
+                      if the IP is not permitted.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkExcludedIP(Org.BouncyCastle.Utilities.Collections.ISet,System.Byte[])">
+             Checks if the IP <code>ip</code> is included in the excluded ISet
+             <code>excluded</code>.
+            
+             @param excluded A <code>Set</code> of excluded IP addresses with their
+                             subnet mask as byte arrays.
+             @param ip       The IP address.
+             @throws PkixNameConstraintValidatorException
+                      if the IP is excluded.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IsIPConstrained(System.Byte[],System.Byte[])">
+             Checks if the IP address <code>ip</code> is constrained by
+             <code>constraint</code>.
+            
+             @param ip         The IP address.
+             @param constraint The constraint. This is an IP address concatenated with
+                               its subnetmask.
+             @return <code>true</code> if constrained, <code>false</code>
+                     otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.unionEmail(System.String,System.String,Org.BouncyCastle.Utilities.Collections.ISet)">
+             The common part of <code>email1</code> and <code>email2</code> is
+             added to the union <code>union</code>. If <code>email1</code> and
+             <code>email2</code> have nothing in common they are added both.
+            
+             @param email1 Email address constraint 1.
+             @param email2 Email address constraint 2.
+             @param union  The union.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.intersectEmail(System.String,System.String,Org.BouncyCastle.Utilities.Collections.ISet)">
+             The most restricting part from <code>email1</code> and
+             <code>email2</code> is added to the intersection <code>intersect</code>.
+            
+             @param email1    Email address constraint 1.
+             @param email2    Email address constraint 2.
+             @param intersect The intersection.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkPermitted(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Checks if the given GeneralName is in the permitted ISet.
+            
+             @param name The GeneralName
+             @throws PkixNameConstraintValidatorException
+                      If the <code>name</code>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.checkExcluded(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Check if the given GeneralName is contained in the excluded ISet.
+            
+             @param name The GeneralName.
+             @throws PkixNameConstraintValidatorException
+                      If the <code>name</code> is
+                      excluded.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.IntersectPermittedSubtree(Org.BouncyCastle.Asn1.Asn1Sequence)">
+             Updates the permitted ISet of these name constraints with the intersection
+             with the given subtree.
+            
+             @param permitted The permitted subtrees
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.AddExcludedSubtree(Org.BouncyCastle.Asn1.X509.GeneralSubtree)">
+             Adds a subtree to the excluded ISet of these name constraints.
+            
+             @param subtree A subtree with an excluded GeneralName.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Max(System.Byte[],System.Byte[])">
+             Returns the maximum IP address.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The maximum IP address.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Min(System.Byte[],System.Byte[])">
+             Returns the minimum IP address.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The minimum IP address.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.CompareTo(System.Byte[],System.Byte[])">
+             Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1
+             is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1
+             otherwise.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.Or(System.Byte[],System.Byte[])">
+             Returns the logical OR of the IP addresses <code>ip1</code> and
+             <code>ip2</code>.
+            
+             @param ip1 The first IP address.
+             @param ip2 The second IP address.
+             @return The OR of <code>ip1</code> and <code>ip2</code>.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixNameConstraintValidator.StringifyIP(System.Byte[])">
+             Stringifies an IPv4 or v6 address with subnet mask.
+            
+             @param ip The IP with subnet mask.
+             @return The stringified IP address.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.PkixPolicyNode">
+            <summary>
+            Summary description for PkixPolicyNode.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.PkixPolicyNode.#ctor(System.Collections.IList,System.Int32,Org.BouncyCastle.Utilities.Collections.ISet,Org.BouncyCastle.Pkix.PkixPolicyNode,Org.BouncyCastle.Utilities.Collections.ISet,System.String,System.Boolean)">
+            Constructors
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.ReasonsMask">
+            <summary>
+            This class helps to handle CRL revocation reasons mask. Each CRL handles a
+            certain set of revocation reasons.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.#ctor(System.Int32)">
+            <summary>
+            Constructs are reason mask with the reasons.
+            </summary>
+            <param name="reasons">The reasons.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.#ctor">
+            <summary>
+            A reason mask with no reason.
+            </summary>
+        </member>
+        <member name="F:Org.BouncyCastle.Pkix.ReasonsMask.AllReasons">
+            <summary>
+            A mask with all revocation reasons.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.AddReasons(Org.BouncyCastle.Pkix.ReasonsMask)">
+             Adds all reasons from the reasons mask to this mask.
+            
+             @param mask The reasons mask to add.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.Intersect(Org.BouncyCastle.Pkix.ReasonsMask)">
+            <summary>
+            Intersects this mask with the given reasons mask.
+            </summary>
+            <param name="mask">mask The mask to intersect with.</param>
+            <returns>The intersection of this and teh given mask.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.ReasonsMask.HasNewReasons(Org.BouncyCastle.Pkix.ReasonsMask)">
+            <summary>
+            Returns <c>true</c> if the passed reasons mask has new reasons.
+            </summary>
+            <param name="mask">The reasons mask which should be tested for new reasons.</param>
+            <returns><c>true</c> if the passed reasons mask has new reasons.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.ReasonsMask.IsAllReasons">
+            <summary>
+            Returns <code>true</code> if this reasons mask contains all possible
+            reasons.
+            </summary>
+            <returns>true if this reasons mask contains all possible reasons.
+            </returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.ReasonsMask.Reasons">
+            <summary>
+            Returns the reasons in this mask.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlB2(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,Org.BouncyCastle.X509.X509Crl)">
+             If the complete CRL includes an issuing distribution point (IDP) CRL
+             extension check the following:
+             <p>
+             (i) If the distribution point name is present in the IDP CRL extension
+             and the distribution field is present in the DP, then verify that one of
+             the names in the IDP matches one of the names in the DP. If the
+             distribution point name is present in the IDP CRL extension and the
+             distribution field is omitted from the DP, then verify that one of the
+             names in the IDP matches one of the names in the cRLIssuer field of the
+             DP.
+             </p>
+             <p>
+             (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
+             extension, verify that the certificate does not include the basic
+             constraints extension with the cA boolean asserted.
+             </p>
+             <p>
+             (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
+             extension, verify that the certificate includes the basic constraints
+             extension with the cA boolean asserted.
+             </p>
+             <p>
+             (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
+             </p>
+            
+             @param dp   The distribution point.
+             @param cert The certificate.
+             @param crl  The CRL.
+             @throws AnnotatedException if one of the conditions is not met or an error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlB1(Org.BouncyCastle.Asn1.X509.DistributionPoint,System.Object,Org.BouncyCastle.X509.X509Crl)">
+             If the DP includes cRLIssuer, then verify that the issuer field in the
+             complete CRL matches cRLIssuer in the DP and that the complete CRL
+             contains an
+                  g distribution point extension with the indirectCRL
+             boolean asserted. Otherwise, verify that the CRL issuer matches the
+             certificate issuer.
+            
+             @param dp   The distribution point.
+             @param cert The certificate ot attribute certificate.
+             @param crl  The CRL for <code>cert</code>.
+             @throws AnnotatedException if one of the above conditions does not apply or an error
+                                        occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlF(Org.BouncyCastle.X509.X509Crl,System.Object,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Pkix.PkixParameters,System.Collections.IList)">
+             Obtain and validate the certification path for the complete CRL issuer.
+             If a key usage extension is present in the CRL issuer's certificate,
+             verify that the cRLSign bit is set.
+            
+             @param crl                CRL which contains revocation information for the certificate
+                                       <code>cert</code>.
+             @param cert               The attribute certificate or certificate to check if it is
+                                       revoked.
+             @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+             @param defaultCRLSignKey  The public key of the issuer certificate
+                                       <code>defaultCRLSignCert</code>.
+             @param paramsPKIX         paramsPKIX PKIX parameters.
+             @param certPathCerts      The certificates on the certification path.
+             @return A <code>Set</code> with all keys of possible CRL issuer
+                     certificates.
+             @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
+                                        some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.CheckCrl(Org.BouncyCastle.Asn1.X509.DistributionPoint,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Pkix.CertStatus,Org.BouncyCastle.Pkix.ReasonsMask,System.Collections.IList)">
+             Checks a distribution point for revocation information for the
+             certificate <code>cert</code>.
+            
+             @param dp                 The distribution point to consider.
+             @param paramsPKIX         PKIX parameters.
+             @param cert               Certificate to check if it is revoked.
+             @param validDate          The date when the certificate revocation status should be
+                                       checked.
+             @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+             @param defaultCRLSignKey  The public key of the issuer certificate
+                                       <code>defaultCRLSignCert</code>.
+             @param certStatus         The current certificate revocation status.
+             @param reasonMask         The reasons mask which is already checked.
+             @param certPathCerts      The certificates of the certification path.
+             @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+                                        or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.CheckCrls(Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Collections.IList)">
+             Checks a certificate if it is revoked.
+            
+             @param paramsPKIX       PKIX parameters.
+             @param cert             Certificate to check if it is revoked.
+             @param validDate        The date when the certificate revocation status should be
+                                     checked.
+             @param sign             The issuer certificate of the certificate <code>cert</code>.
+             @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
+             @param certPathCerts    The certificates of the certification path.
+             @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+                                        or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3280CertPathUtilities.ProcessCrlC(Org.BouncyCastle.X509.X509Crl,Org.BouncyCastle.X509.X509Crl,Org.BouncyCastle.Pkix.PkixParameters)">
+             If use-deltas is set, verify the issuer and scope of the delta CRL.
+            
+             @param deltaCRL    The delta CRL.
+             @param completeCRL The complete CRL.
+             @param pkixParams  The PKIX paramaters.
+             @throws AnnotatedException if an exception occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.CheckCrls(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters,Org.BouncyCastle.X509.X509Certificate,System.DateTime,System.Collections.IList)">
+            Checks if an attribute certificate is revoked.
+            
+            @param attrCert Attribute certificate to check if it is revoked.
+            @param paramsPKIX PKIX parameters.
+            @param issuerCert The issuer certificate of the attribute certificate
+                       <code>attrCert</code>.
+            @param validDate The date when the certificate revocation status should
+                       be checked.
+            @param certPathCerts The certificates of the certification path to be
+                       checked.
+            
+            @throws CertPathValidatorException if the certificate is revoked or the
+                        status cannot be checked or some error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.ProcessAttrCert1(Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters)">
+            Searches for a holder public key certificate and verifies its
+            certification path.
+            
+            @param attrCert the attribute certificate.
+            @param pkixParams The PKIX parameters.
+            @return The certificate path of the holder certificate.
+            @throws Exception if
+                        <ul>
+                        <li>no public key certificate can be found although holder
+                        information is given by an entity name or a base certificate
+                        ID</li>
+                        <li>support classes cannot be created</li>
+                        <li>no certification path for the public key certificate can
+                        be built</li>
+                        </ul>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.Rfc3281CertPathUtilities.CheckCrl(Org.BouncyCastle.Asn1.X509.DistributionPoint,Org.BouncyCastle.X509.IX509AttributeCertificate,Org.BouncyCastle.Pkix.PkixParameters,System.DateTime,Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.Pkix.CertStatus,Org.BouncyCastle.Pkix.ReasonsMask,System.Collections.IList)">
+            
+            Checks a distribution point for revocation information for the
+            certificate <code>attrCert</code>.
+            
+            @param dp The distribution point to consider.
+            @param attrCert The attribute certificate which should be checked.
+            @param paramsPKIX PKIX parameters.
+            @param validDate The date when the certificate revocation status should
+                       be checked.
+            @param issuerCert Certificate to check if it is revoked.
+            @param reasonMask The reasons mask which is already checked.
+            @param certPathCerts The certificates of the certification path to be
+                       checked.
+            @throws Exception if the certificate is revoked or the status
+                        cannot be checked or some error occurs.
+        </member>
+        <member name="T:Org.BouncyCastle.Pkix.TrustAnchor">
+            <summary>
+            A trust anchor or most-trusted Certification Authority (CA).
+            
+            This class represents a "most-trusted CA", which is used as a trust anchor
+            for validating X.509 certification paths. A most-trusted CA includes the
+            public key of the CA, the CA's name, and any constraints upon the set of
+            paths which may be validated using this key. These parameters can be
+            specified in the form of a trusted X509Certificate or as individual
+            parameters.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(Org.BouncyCastle.X509.X509Certificate,System.Byte[])">
+             <summary>
+             Creates an instance of TrustAnchor with the specified X509Certificate and
+             optional name constraints, which are intended to be used as additional
+             constraints when validating an X.509 certification path.
+            	The name constraints are specified as a byte array. This byte array
+            	should contain the DER encoded form of the name constraints, as they
+            	would appear in the NameConstraints structure defined in RFC 2459 and
+            	X.509. The ASN.1 definition of this structure appears below.
+            	
+            	<pre>
+            	NameConstraints ::= SEQUENCE {
+            		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+            		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+            	   
+             GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+             
+            		GeneralSubtree ::= SEQUENCE {
+            		base                    GeneralName,
+            		minimum         [0]     BaseDistance DEFAULT 0,
+            		maximum         [1]     BaseDistance OPTIONAL }
+            		
+            		BaseDistance ::= INTEGER (0..MAX)
+            
+            		GeneralName ::= CHOICE {
+            		otherName                       [0]     OtherName,
+            		rfc822Name                      [1]     IA5String,
+            		dNSName                         [2]     IA5String,
+            		x400Address                     [3]     ORAddress,
+            		directoryName                   [4]     Name,
+            		ediPartyName                    [5]     EDIPartyName,
+            		uniformResourceIdentifier       [6]     IA5String,
+            		iPAddress                       [7]     OCTET STRING,
+            		registeredID                    [8]     OBJECT IDENTIFIER}
+            	</pre>
+            	
+            	Note that the name constraints byte array supplied is cloned to protect
+            	against subsequent modifications.
+             </summary>
+             <param name="trustedCert">a trusted X509Certificate</param>
+             <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+             NameConstraints extension to be used for checking name
+             constraints. Only the value of the extension is included, not
+             the OID or criticality flag. Specify null to omit the
+             parameter.</param>
+             <exception cref="T:System.ArgumentNullException">if the specified X509Certificate is null</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(Org.BouncyCastle.Asn1.X509.X509Name,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+            <summary>
+            Creates an instance of <c>TrustAnchor</c> where the
+            most-trusted CA is specified as an X500Principal and public key.
+            </summary>
+            <remarks>
+            <p>
+            Name constraints are an optional parameter, and are intended to be used
+            as additional constraints when validating an X.509 certification path.
+            </p><p>
+            The name constraints are specified as a byte array. This byte array
+            contains the DER encoded form of the name constraints, as they
+            would appear in the NameConstraints structure defined in RFC 2459
+            and X.509. The ASN.1 notation for this structure is supplied in the
+            documentation for the other constructors.
+            </p><p>
+            Note that the name constraints byte array supplied here is cloned to
+            protect against subsequent modifications.
+            </p>
+            </remarks>
+            <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
+            <param name="pubKey">the public key of the most-trusted CA</param>
+            <param name="nameConstraints">
+            a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
+            be used for checking name constraints. Only the value of the extension is included,
+            not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
+            </param>
+            <exception cref="T:System.ArgumentNullException">
+            if <c>caPrincipal</c> or <c>pubKey</c> is null
+            </exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.#ctor(System.String,Org.BouncyCastle.Crypto.AsymmetricKeyParameter,System.Byte[])">
+            <summary>
+            Creates an instance of <code>TrustAnchor</code> where the most-trusted
+            CA is specified as a distinguished name and public key. Name constraints
+            are an optional parameter, and are intended to be used as additional
+            constraints when validating an X.509 certification path.
+            <br/>
+            The name constraints are specified as a byte array. This byte array
+            contains the DER encoded form of the name constraints, as they would
+            appear in the NameConstraints structure defined in RFC 2459 and X.509.
+            </summary>
+            <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
+            2253 string format</param>
+            <param name="pubKey">the public key of the most-trusted CA</param>
+            <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+            NameConstraints extension to be used for checking name
+            constraints. Only the value of the extension is included, not 
+            the OID or criticality flag. Specify null to omit the 
+            parameter.</param>
+            throws NullPointerException, IllegalArgumentException
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.setNameConstraints(System.Byte[])">
+            <summary>
+            Decode the name constraints and clone them if not null.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Pkix.TrustAnchor.ToString">
+            <summary>
+            Returns a formatted string describing the <code>TrustAnchor</code>.
+            </summary>
+            <returns>a formatted string describing the <code>TrustAnchor</code></returns>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.TrustedCert">
+            <summary>
+            Returns the most-trusted CA certificate.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CA">
+            <summary>
+            Returns the name of the most-trusted CA as an X509Name.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CAName">
+            <summary>
+            Returns the name of the most-trusted CA in RFC 2253 string format.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.Pkix.TrustAnchor.CAPublicKey">
+            <summary>
+            Returns the public key of the most-trusted CA.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.AgreementUtilities">
+            <remarks>
+             Utility class for creating IBasicAgreement objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.CipherUtilities">
+            <remarks>
+             Cipher Utility class contains methods that can not be specifically grouped into other classes.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.CipherUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.DigestUtilities">
+            <remarks>
+             Utility class for creating IDigest objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.DigestUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a given digest mechanism.
+            </summary>
+            <param name="mechanism">A string representation of the digest meanism.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.MacUtilities">
+            <remarks>
+             Utility class for creating HMac object from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.PbeUtilities">
+             <summary>
+            
+             </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.PbeUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecureRandom.#ctor(Org.BouncyCastle.Crypto.Prng.IRandomGenerator)">
+            <summary>Use the specified instance of IRandomGenerator as random source.</summary>
+            <remarks>
+            This constructor performs no seeding of either the <c>IRandomGenerator</c> or the
+            constructed <c>SecureRandom</c>. It is the responsibility of the client to provide
+            proper seed material as necessary/appropriate for the given <c>IRandomGenerator</c>
+            implementation.
+            </remarks>
+            <param name="generator">The source to generate all random bytes from.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecurityUtilityException.#ctor">
+            base constructor.
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SecurityUtilityException.#ctor(System.String)">
+             create a SecurityUtilityException with the given message.
+            
+             @param message the message to be carried with the exception.
+        </member>
+        <member name="T:Org.BouncyCastle.Security.SignerUtilities">
+            <summary>
+             Signer Utility class contains methods that can not be specifically grouped into other classes.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Security.SignerUtilities.GetObjectIdentifier(System.String)">
+            <summary>
+            Returns a ObjectIdentifier for a give encoding.
+            </summary>
+            <param name="mechanism">A string representation of the encoding.</param>
+            <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Security.WrapperUtilities">
+            <remarks>
+             Utility class for creating IWrapper objects from their names/Oids
+            </remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampRequest">
+            Base class for an RFC 3161 Time Stamp Request.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.#ctor(System.Byte[])">
+             Create a TimeStampRequest from the past in byte array.
+            
+             @param req byte array containing the request.
+             @throws IOException if the request is malformed.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.#ctor(System.IO.Stream)">
+             Create a TimeStampRequest from the past in input stream.
+            
+             @param in input stream containing the request.
+             @throws IOException if the request is malformed.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.Validate(System.Collections.IList,System.Collections.IList,System.Collections.IList)">
+             Validate the timestamp request, checking the digest to see if it is of an
+             accepted type and whether it is of the correct length for the algorithm specified.
+            
+             @param algorithms a set of string OIDS giving accepted algorithms.
+             @param policies if non-null a set of policies we are willing to sign under.
+             @param extensions if non-null a set of extensions we are willing to accept.
+             @throws TspException if the request is invalid, or processing fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequest.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampRequestGenerator">
+            Generator for RFC 3161 Time Stamp Request objects.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 3)
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 3)
+            @throws IOException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampRequestGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampResponse">
+            Base class for an RFC 3161 Time Stamp Response object.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.#ctor(System.Byte[])">
+             Create a TimeStampResponse from a byte array containing an ASN.1 encoding.
+            
+             @param resp the byte array containing the encoded response.
+             @throws TspException if the response is malformed.
+             @throws IOException if the byte array doesn't represent an ASN.1 encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.#ctor(System.IO.Stream)">
+             Create a TimeStampResponse from an input stream containing an ASN.1 encoding.
+            
+             @param input the input stream containing the encoded response.
+             @throws TspException if the response is malformed.
+             @throws IOException if the stream doesn't represent an ASN.1 encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.Validate(Org.BouncyCastle.Tsp.TimeStampRequest)">
+             Check this response against to see if it a well formed response for
+             the passed in request. Validation will include checking the time stamp
+             token if the response status is GRANTED or GRANTED_WITH_MODS.
+            
+             @param request the request to be checked against
+             @throws TspException if the request can not match this response.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponse.GetEncoded">
+            return the ASN.1 encoded representation of this object.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TimeStampResponseGenerator">
+            Generator for RFC 3161 Time Stamp Responses.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponseGenerator.Generate(Org.BouncyCastle.Tsp.TimeStampRequest,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Utilities.Date.DateTimeObject)">
+             Return an appropriate TimeStampResponse.
+             <p>
+             If genTime is null a timeNotAvailable error response will be returned.
+            
+             @param request the request this response is for.
+             @param serialNumber serial number for the response token.
+             @param genTime generation time for the response token.
+             @param provider provider to use for signature calculation.
+             @return
+             @throws NoSuchAlgorithmException
+             @throws NoSuchProviderException
+             @throws TSPException
+             </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampResponseGenerator.GenerateFailResponse(Org.BouncyCastle.Asn1.Cmp.PkiStatus,System.Int32,System.String)">
+             Generate a TimeStampResponse with chosen status and FailInfoField.
+            
+             @param status the PKIStatus to set.
+             @param failInfoField the FailInfoField to set.
+             @param statusString an optional string describing the failure.
+             @return a TimeStampResponse with a failInfoField and optional statusString
+             @throws TSPException in case the response could not be created
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.Validate(Org.BouncyCastle.X509.X509Certificate)">
+            Validate the time stamp token.
+            <p>
+            To be valid the token must be signed by the passed in certificate and
+            the certificate must be the one referred to by the SigningCertificate
+            attribute included in the hashed attributes of the token. The
+            certificate must also have the ExtendedKeyUsageExtension with only
+            KeyPurposeID.IdKPTimeStamping and have been valid at the time the
+            timestamp was created.
+            </p>
+            <p>
+            A successful call to validate means all the above are true.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.ToCmsSignedData">
+             Return the underlying CmsSignedData object.
+            
+             @return the underlying CMS structure.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampToken.GetEncoded">
+             Return a ASN.1 encoded byte stream representing the encoded object.
+            
+             @throws IOException if encoding fails.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampTokenGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String)">
+            basic creation - only the default attributes will be included here.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TimeStampTokenGenerator.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.X509.X509Certificate,System.String,System.String,Org.BouncyCastle.Asn1.Cms.AttributeTable,Org.BouncyCastle.Asn1.Cms.AttributeTable)">
+            create with a signer with extra signed/unsigned attributes.
+        </member>
+        <member name="P:Org.BouncyCastle.Tsp.TimeStampTokenInfo.Nonce">
+            @return the nonce value, null if there isn't one.
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TspAlgorithms">
+            Recognised hash algorithms for the time stamp protocol.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.GetSignatureTimestamps(Org.BouncyCastle.Cms.SignerInformation)">
+             Fetches the signature time-stamp attributes from a SignerInformation object.
+             Checks that the MessageImprint for each time-stamp matches the signature field.
+             (see RFC 3161 Appendix A).
+            
+             @param signerInfo a SignerInformation to search for time-stamps
+             @return a collection of TimeStampToken objects
+             @throws TSPValidationException
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.ValidateCertificate(Org.BouncyCastle.X509.X509Certificate)">
+             Validate the passed in certificate as being of the correct type to be used
+             for time stamping. To be valid it must have an ExtendedKeyUsage extension
+             which has a key purpose identifier of id-kp-timeStamping.
+            
+             @param cert the certificate of interest.
+             @throws TspValidationException if the certicate fails on one of the check points.
+        </member>
+        <member name="M:Org.BouncyCastle.Tsp.TspUtil.GetDigestAlgName(System.String)">
+            <summary>
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Tsp.TspValidationException">
+            Exception thrown if a TSP request or response fails to validate.
+            <p>
+            If a failure code is associated with the exception it can be retrieved using
+            the getFailureCode() method.</p>
+        </member>
+        <member name="P:Org.BouncyCastle.Tsp.TspValidationException.FailureCode">
+             Return the failure code associated with this exception - if one is set.
+            
+             @return the failure code if set, -1 otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Arrays">
+            <summary> General array utilities.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Arrays.AreEqual(System.Byte[],System.Byte[])">
+            <summary>
+            Are two arrays equal.
+            </summary>
+            <param name="a">Left side.</param>
+            <param name="b">Right side.</param>
+            <returns>True if equal.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Arrays.ConstantTimeAreEqual(System.Byte[],System.Byte[])">
+            <summary>
+            A constant time equals comparison - does not terminate early if
+            test will fail.
+            </summary>
+            <param name="a">first array</param>
+            <param name="b">second array</param>
+            <returns>true if arrays equal, false otherwise.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.BigIntegers">
+            BigInteger utilities.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.BigIntegers.AsUnsignedByteArray(Org.BouncyCastle.Math.BigInteger)">
+             Return the passed in value as an unsigned byte array.
+            
+             @param value value to be converted.
+             @return a byte array without a leading zero byte if present in the signed encoding.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.BigIntegers.CreateRandomInRange(Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Math.BigInteger,Org.BouncyCastle.Security.SecureRandom)">
+            Return a random BigInteger not less than 'min' and not greater than 'max'
+            
+            @param min the least value that may be generated
+            @param max the greatest value that may be generated
+            @param random the source of randomness
+            @return a random BigInteger value in the range [min,max]
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.DateTimeToUnixMs(System.DateTime)">
+            <summary>
+            Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
+            </summary>
+            <param name="dateTime">A UTC DateTime value not before epoch.</param>
+            <returns>Number of whole milliseconds after epoch.</returns>
+            <exception cref="T:System.ArgumentException">'dateTime' is before epoch.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.UnixMsToDateTime(System.Int64)">
+            <summary>
+            Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+            </summary>
+            <param name="unixMs">Number of milliseconds since the epoch.</param>
+            <returns>A UTC DateTime value</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Date.DateTimeUtilities.CurrentUnixMs">
+            <summary>
+            Return the current number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[])">
+             encode the input data producing a base 64 encoded byte array.
+            
+             @return a byte array containing the base 64 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[],System.IO.Stream)">
+             Encode the byte data to base 64 writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             Encode the byte data to base 64 writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.Byte[])">
+             decode the base 64 encoded input data. It is assumed the input data is valid.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.String)">
+             decode the base 64 encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64.Decode(System.String,System.IO.Stream)">
+             decode the base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.IEncoder">
+            Encode and decode byte arrays (typically from binary to 7-bit ASCII
+            encodings).
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             encode the input data producing a base 64 output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.Decode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             decode the base 64 encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Base64Encoder.DecodeString(System.String,System.IO.Stream)">
+             decode the base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder">
+            <summary>
+             A buffering class to allow translation from one format to another to
+                be done in discrete chunks.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.#ctor(Org.BouncyCastle.Utilities.Encoders.ITranslator,System.Int32)">
+            <summary>
+            Create a buffered Decoder.
+            </summary>
+            <param name="translator">The translater to use.</param>
+            <param name="bufferSize">The size of the buffer.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+            <summary>
+            Process one byte of data.
+            </summary>
+            <param name="input">Data in.</param>
+            <param name="output">Byte array for the output.</param>
+            <param name="outOff">The offset in the output byte array to start writing from.</param>
+            <returns>The amount of output bytes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedDecoder.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process data from a byte array.
+            </summary>
+            <param name="input">The input data.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="len">Amount of data to process from input data array.</param>
+            <param name="outBytes">Array to store output.</param>
+            <param name="outOff">Position in output array to start writing from.</param>
+            <returns>The amount of output bytes.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder">
+            <summary>
+            A class that allows encoding of data using a specific encoder to be processed in chunks.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.#ctor(Org.BouncyCastle.Utilities.Encoders.ITranslator,System.Int32)">
+            <summary>
+            Create.
+            </summary>
+            <param name="translator">The translator to use.</param>
+            <param name="bufferSize">Size of the chunks.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.ProcessByte(System.Byte,System.Byte[],System.Int32)">
+            <summary>
+            Process one byte of data.
+            </summary>
+            <param name="input">The byte.</param>
+            <param name="outBytes">An array to store output in.</param>
+            <param name="outOff">Offset within output array to start writing from.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.BufferedEncoder.ProcessBytes(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Process data from a byte array.
+            </summary>
+            <param name="input">Input data Byte array containing data to be processed.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="len">Amount of input data to be processed.</param>
+            <param name="outBytes">Output data array.</param>
+            <param name="outOff">Offset within output data array to start writing to.</param>
+            <returns>The amount of data written.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.Hex">
+            <summary>
+            Class to decode and encode Hex.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[])">
+             encode the input data producing a Hex encoded byte array.
+            
+             @return a byte array containing the Hex encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.Int32,System.Int32)">
+             encode the input data producing a Hex encoded byte array.
+            
+             @return a byte array containing the Hex encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.IO.Stream)">
+             Hex encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             Hex encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.Byte[])">
+             decode the Hex encoded input data. It is assumed the input data is valid.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.String)">
+             decode the Hex encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.Hex.Decode(System.String,System.IO.Stream)">
+             decode the Hex encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.Encode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             encode the input data producing a Hex output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.Decode(System.Byte[],System.Int32,System.Int32,System.IO.Stream)">
+             decode the Hex encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexEncoder.DecodeString(System.String,System.IO.Stream)">
+             decode the Hex encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.HexTranslator">
+            <summary>
+            A hex translator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.ITranslator">
+            <summary>
+            Translator interface.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.GetEncodedBlockSize">
+            <summary>
+            Return encoded block size.
+            </summary>
+            <returns>2</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.Encode(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Encode some data.
+            </summary>
+            <param name="input">Input data array.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="length">The amount of data to process.</param>
+            <param name="outBytes">The output data array.</param>
+            <param name="outOff">The offset within the output data array to start writing from.</param>
+            <returns>Amount of data encoded.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.GetDecodedBlockSize">
+            <summary>
+            Returns the decoded block size.
+            </summary>
+            <returns>1</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.HexTranslator.Decode(System.Byte[],System.Int32,System.Int32,System.Byte[],System.Int32)">
+            <summary>
+            Decode data from a byte array.
+            </summary>
+            <param name="input">The input data array.</param>
+            <param name="inOff">Start position within input data array.</param>
+            <param name="length">The amounty of data to process.</param>
+            <param name="outBytes">The output data array.</param>
+            <param name="outOff">The position within the output data array to start writing from.</param>
+            <returns>The amount of data written.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.UrlBase64">
+            Convert binary data to and from UrlBase64 encoding.  This is identical to
+            Base64 encoding, except that the padding character is "." and the other 
+            non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+            <p>
+            The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+            data that is safe for use as an URL parameter. Base64 encoding does not
+            produce encoded values that are safe for use in URLs, since "/" can be 
+            interpreted as a path delimiter; "+" is the encoded form of a space; and
+            "=" is used to separate a name from the corresponding value in an URL 
+            parameter.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Encode(System.Byte[])">
+             Encode the input data producing a URL safe base 64 encoded byte array.
+            
+             @return a byte array containing the URL safe base 64 encoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Encode(System.Byte[],System.IO.Stream)">
+             Encode the byte data writing it to the given output stream.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.Byte[])">
+             Decode the URL safe base 64 encoded input data - white space will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.Byte[],System.IO.Stream)">
+             decode the URL safe base 64 encoded byte data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.String)">
+             decode the URL safe base 64 encoded string data - whitespace will be ignored.
+            
+             @return a byte array representing the decoded data.
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Encoders.UrlBase64.Decode(System.String,System.IO.Stream)">
+             Decode the URL safe base 64 encoded string data writing it to the given output stream,
+             whitespace characters will be ignored.
+            
+             @return the number of bytes produced.
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Encoders.UrlBase64Encoder">
+            Convert binary data to and from UrlBase64 encoding.  This is identical to
+            Base64 encoding, except that the padding character is "." and the other 
+            non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+            <p>
+            The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+            data that is safe for use as an URL parameter. Base64 encoding does not
+            produce encoded values that are safe for use in URLs, since "/" can be 
+            interpreted as a path delimiter; "+" is the encoded form of a space; and
+            "=" is used to separate a name from the corresponding value in an URL 
+            parameter.
+            </p>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Pem.PemObjectParser.ParseObject(Org.BouncyCastle.Utilities.IO.Pem.PemObject)">
+            <param name="obj">
+            A <see cref="T:Org.BouncyCastle.Utilities.IO.Pem.PemObject"/>
+            </param>
+            <returns>
+            A <see cref="T:System.Object"/>
+            </returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.IO.Streams.PipeAllLimited(System.IO.Stream,System.Int64,System.IO.Stream)">
+            <summary>
+            Pipe all bytes from <c>inStr</c> to <c>outStr</c>, throwing <c>StreamFlowException</c> if greater
+            than <c>limit</c> bytes in <c>inStr</c>.
+            </summary>
+            <param name="inStr">
+            A <see cref="T:System.IO.Stream"/>
+            </param>
+            <param name="limit">
+            A <see cref="T:System.Int64"/>
+            </param>
+            <param name="outStr">
+            A <see cref="T:System.IO.Stream"/>
+            </param>
+            <returns>The number of bytes actually transferred, if not greater than <c>limit</c></returns>
+            <exception cref="T:System.IO.IOException"></exception>
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValid(System.String)">
+             Validate the given IPv4 or IPv6 address.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid address, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidWithNetMask(System.String)">
+             Validate the given IPv4 or IPv6 address and netmask.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid address with netmask, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv4(System.String)">
+             Validate the given IPv4 address.
+             
+             @param address the IP address as a string.
+            
+             @return true if a valid IPv4 address, false otherwise
+        </member>
+        <member name="M:Org.BouncyCastle.Utilities.Net.IPAddress.IsValidIPv6(System.String)">
+             Validate the given IPv6 address.
+            
+             @param address the IP address as a string.
+            
+             @return true if a valid IPv4 address, false otherwise
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Strings">
+            <summary> General string utilities.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Zlib.ZDeflaterOutputStream">
+            <summary>
+            Summary description for DeflaterOutputStream.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.Utilities.Zlib.ZInflaterInputStream">
+            <summary>
+            Summary description for DeflaterOutputStream.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.AttributeCertificateHolder">
+            <remarks>
+            The Holder object.
+            <pre>
+            Holder ::= SEQUENCE {
+            	baseCertificateID   [0] IssuerSerial OPTIONAL,
+            		-- the issuer and serial number of
+            		-- the holder's Public Key Certificate
+            	entityName          [1] GeneralNames OPTIONAL,
+            		-- the name of the claimant or role
+            	objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+            		-- used to directly authenticate the holder,
+            		-- for example, an executable
+            }
+            </pre>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.#ctor(System.Int32,System.String,System.String,System.Byte[])">
+             Constructs a holder for v2 attribute certificates with a hash value for
+             some type of object.
+             <p>
+             <code>digestedObjectType</code> can be one of the following:
+             <ul>
+             <li>0 - publicKey - A hash of the public key of the holder must be
+             passed.</li>
+             <li>1 - publicKeyCert - A hash of the public key certificate of the
+             holder must be passed.</li>
+             <li>2 - otherObjectDigest - A hash of some other object type must be
+             passed. <code>otherObjectTypeID</code> must not be empty.</li>
+             </ul>
+             </p>
+             <p>This cannot be used if a v1 attribute certificate is used.</p>
+            
+             @param digestedObjectType The digest object type.
+             @param digestAlgorithm The algorithm identifier for the hash.
+             @param otherObjectTypeID The object type ID if
+                        <code>digestedObjectType</code> is
+                        <code>otherObjectDigest</code>.
+             @param objectDigest The hash value.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetObjectDigest">
+             Returns the hash if an object digest info is used.
+            
+             @return The hash or <code>null</code> if no object digest info is set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetEntityNames">
+             Return any principal objects inside the attribute certificate holder entity names field.
+            
+             @return an array of IPrincipal objects (usually X509Name), null if no entity names field is set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateHolder.GetIssuer">
+             Return the principals associated with the issuer attached to this holder
+            
+             @return an array of principals, null if no BaseCertificateID is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.DigestedObjectType">
+             Returns the digest object type if an object digest info is used.
+             <p>
+             <ul>
+             <li>0 - publicKey - A hash of the public key of the holder must be
+             passed.</li>
+             <li>1 - publicKeyCert - A hash of the public key certificate of the
+             holder must be passed.</li>
+             <li>2 - otherObjectDigest - A hash of some other object type must be
+             passed. <code>otherObjectTypeID</code> must not be empty.</li>
+             </ul>
+             </p>
+            
+             @return The digest object type or -1 if no object digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.DigestAlgorithm">
+             Returns the other object type ID if an object digest info is used.
+            
+             @return The other object type ID or <code>null</code> if no object
+                     digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.OtherObjectTypeID">
+             Returns the digest algorithm ID if an object digest info is used.
+            
+             @return The digest algorithm ID or <code>null</code> if no object
+                     digest info is set.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.AttributeCertificateHolder.SerialNumber">
+             Return the serial number associated with the issuer attached to this holder.
+            
+             @return the certificate serial number, null if no BaseCertificateID is set.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.AttributeCertificateIssuer">
+            Carrying class for an attribute certificate issuer.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateIssuer.#ctor(Org.BouncyCastle.Asn1.X509.AttCertIssuer)">
+             Set the issuer directly with the ASN.1 structure.
+            
+             @param issuer The issuer
+        </member>
+        <member name="M:Org.BouncyCastle.X509.AttributeCertificateIssuer.GetPrincipals">
+            <summary>Return any principal objects inside the attribute certificate issuer object.</summary>
+            <returns>An array of IPrincipal objects (usually X509Principal).</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure">
+            <remarks>A high level authority key identifier.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor which will take the byte[] returned from getExtensionValue()
+            
+             @param encodedValue a DER octet encoded string with the extension structure in it.
+             @throws IOException on parsing errors.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.X509.X509Certificate)">
+             Create an AuthorityKeyIdentifier using the passed in certificate's public
+             key, issuer and serial number.
+            
+             @param certificate the certificate providing the information.
+             @throws CertificateParsingException if there is a problem processing the certificate
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.AuthorityKeyIdentifierStructure.#ctor(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+             Create an AuthorityKeyIdentifier using just the hash of the
+             public key.
+            
+             @param pubKey the key to generate the hash from.
+             @throws InvalidKeyException if there is a problem using the key.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Extension.SubjectKeyIdentifierStructure">
+            A high level subject key identifier.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Extension.SubjectKeyIdentifierStructure.#ctor(Org.BouncyCastle.Asn1.Asn1OctetString)">
+             Constructor which will take the byte[] returned from getExtensionValue()
+            
+             @param encodedValue a DER octet encoded string with the extension structure in it.
+             @throws IOException on parsing errors.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.IX509AttributeCertificate">
+            <remarks>Interface for an X.509 Attribute Certificate.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetAttributes">
+            <summary>Return the attributes contained in the attribute block in the certificate.</summary>
+            <returns>An array of attributes.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetAttributes(System.String)">
+            <summary>Return the attributes with the same type as the passed in oid.</summary>
+            <param name="oid">The object identifier we wish to match.</param>
+            <returns>An array of matched attributes, null if there is no match.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.IX509AttributeCertificate.GetEncoded">
+            <summary>Return an ASN.1 encoded byte array representing the attribute certificate.</summary>
+            <returns>An ASN.1 encoded byte array.</returns>
+            <exception cref="T:System.IO.IOException">If the certificate cannot be encoded.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Version">
+            <summary>The version number for the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.SerialNumber">
+            <summary>The serial number for the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.NotBefore">
+            <summary>The UTC DateTime before which the certificate is not valid.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.NotAfter">
+            <summary>The UTC DateTime after which the certificate is not valid.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Holder">
+            <summary>The holder of the certificate.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.IX509AttributeCertificate.Issuer">
+            <summary>The issuer details for the certificate.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.PrincipalUtilities">
+            <remarks>
+            A utility class that will extract X509Principal objects from X.509 certificates.
+            <p>
+            Use this in preference to trying to recreate a principal from a string, not all
+            DNs are what they should be, so it's best to leave them encoded where they
+            can be.</p>
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetIssuerX509Principal(Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Return the issuer of the given cert as an X509Principal.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetSubjectX509Principal(Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Return the subject of the given cert as an X509Principal.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.PrincipalUtilities.GetIssuerX509Principal(Org.BouncyCastle.X509.X509Crl)">
+            <summary>Return the issuer of the given CRL as an X509Principal.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector">
+             This class is an <code>Selector</code> like implementation to select
+             attribute certificates from a given set of criteria.
+            
+             @see org.bouncycastle.x509.X509AttributeCertificate
+             @see org.bouncycastle.x509.X509Store
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Match(System.Object)">
+            <summary>
+            Decides if the given attribute certificate should be selected.
+            </summary>
+            <param name="obj">The attribute certificate to be checked.</param>
+            <returns><code>true</code> if the object matches this selector.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetName(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Adds a target name criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target names.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name The name as a GeneralName (not <code>null</code>)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetName(System.Byte[])">
+             Adds a target name criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target names.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
+             @throws IOException if a parsing error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SetTargetNames(System.Collections.IEnumerable)">
+            Adds a collection with target names criteria. If <code>null</code> is
+            given any will do.
+            <p>
+            The collection consists of either GeneralName objects or byte[] arrays representing
+            DER encoded GeneralName structures.
+            </p>
+            
+            @param names A collection of target names.
+            @throws IOException if a parsing error occurs.
+            @see #AddTargetName(byte[])
+            @see #AddTargetName(GeneralName)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.GetTargetNames">
+            Gets the target names. The collection consists of <code>List</code>s
+            made up of an <code>Integer</code> in the first entry and a DER encoded
+            byte array or a <code>String</code> in the second entry.
+            <p>The returned collection is immutable.</p>
+            
+            @return The collection of target names
+            @see #setTargetNames(Collection)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetGroup(Org.BouncyCastle.Asn1.X509.GeneralName)">
+             Adds a target group criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target groups.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param group The group as GeneralName form (not <code>null</code>)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AddTargetGroup(System.Byte[])">
+             Adds a target group criterion for the attribute certificate to the target
+             information extension criteria. The <code>X509AttributeCertificate</code>
+             must contain at least one of the specified target groups.
+             <p>
+             Each attribute certificate may contain a target information extension
+             limiting the servers where this attribute certificate can be used. If
+             this extension is not present, the attribute certificate is not targeted
+             and may be accepted by any server.
+             </p>
+            
+             @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
+             @throws IOException if a parsing error occurs.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SetTargetGroups(System.Collections.IEnumerable)">
+             Adds a collection with target groups criteria. If <code>null</code> is
+             given any will do.
+             <p>
+             The collection consists of <code>GeneralName</code> objects or <code>byte[]</code>
+             representing DER encoded GeneralNames.
+             </p>
+            
+             @param names A collection of target groups.
+             @throws IOException if a parsing error occurs.
+             @see #AddTargetGroup(byte[])
+             @see #AddTargetGroup(GeneralName)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.GetTargetGroups">
+             Gets the target groups. The collection consists of <code>List</code>s
+             made up of an <code>Integer</code> in the first entry and a DER encoded
+             byte array or a <code>String</code> in the second entry.
+             <p>The returned collection is immutable.</p>
+            
+             @return The collection of target groups.
+             @see #setTargetGroups(Collection)
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AttributeCert">
+            <summary>The attribute certificate which must be matched.</summary>
+            <remarks>If <c>null</c> is given, any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.AttributeCertificateValid">
+            <summary>The criteria for validity</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Holder">
+            <summary>The holder.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.Issuer">
+            <summary>The issuer.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509AttrCertStoreSelector.SerialNumber">
+            <summary>The serial number.</summary>
+            <remarks>If <c>null</c> is given any will do.</remarks>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector">
+            <remarks>
+            This class is an <code>IX509Selector</code> implementation to select
+            certificate pairs, which are e.g. used for cross certificates. The set of
+            criteria is given from two <code>X509CertStoreSelector</code> objects,
+            each of which, if present, must match the respective component of a pair.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.Match(System.Object)">
+            <summary>
+            Decides if the given certificate pair should be selected. If
+            <c>obj</c> is not a <code>X509CertificatePair</code>, this method
+            returns <code>false</code>.
+            </summary>
+            <param name="obj">The <code>X509CertificatePair</code> to be tested.</param>
+            <returns><code>true</code> if the object matches this selector.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.CertPair">
+            <summary>The certificate pair which is used for testing on equality.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.ForwardSelector">
+            <summary>The certificate selector for the forward part.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CertPairStoreSelector.ReverseSelector">
+            <summary>The certificate selector for the reverse part.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CollectionStore">
+            A simple collection backed store.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStore.#ctor(System.Collections.ICollection)">
+             Basic constructor.
+            
+             @param collection - initial contents for the store, this is copied.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStore.GetMatches(Org.BouncyCastle.X509.Store.IX509Selector)">
+             Return the matches in the collection for the passed in selector.
+            
+             @param selector the selector to match against.
+             @return a possibly empty collection of matching objects.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters">
+            <remarks>This class contains a collection for collection based <code>X509Store</code>s.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.#ctor(System.Collections.ICollection)">
+            <summary>
+            Constructor.
+            <p>
+            The collection is copied.
+            </p>
+            </summary>
+            <param name="collection">The collection containing X.509 object types.</param>
+            <exception cref="T:System.ArgumentNullException">If collection is null.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.GetCollection">
+            <summary>Returns a copy of the <code>ICollection</code>.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.Store.X509CollectionStoreParameters.ToString">
+            <summary>Returns a formatted string describing the parameters.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.Issuers">
+            <summary>
+            An <code>ICollection</code> of <code>X509Name</code> objects
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.AttrCertChecking">
+             The attribute certificate being checked. This is not a criterion.
+             Rather, it is optional information that may help a {@link X509Store} find
+             CRLs that would be relevant when checking revocation for the specified
+             attribute certificate. If <code>null</code> is specified, then no such
+             optional information is provided.
+            
+             @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
+                         <code>null</code>)
+             @see #getAttrCertificateChecking()
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.CompleteCrlEnabled">
+             If <code>true</code> only complete CRLs are returned. Defaults to
+             <code>false</code>.
+            
+             @return <code>true</code> if only complete CRLs are returned.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.DeltaCrlIndicatorEnabled">
+             Returns if this selector must match CRLs with the delta CRL indicator
+             extension set. Defaults to <code>false</code>.
+            
+             @return Returns <code>true</code> if only CRLs with the delta CRL
+                     indicator extension are selected.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.IssuingDistributionPoint">
+             The issuing distribution point.
+             <p>
+             The issuing distribution point extension is a CRL extension which
+             identifies the scope and the distribution point of a CRL. The scope
+             contains among others information about revocation reasons contained in
+             the CRL. Delta CRLs and complete CRLs must have matching issuing
+             distribution points.</p>
+             <p>
+             The byte array is cloned to protect against subsequent modifications.</p>
+             <p>
+             You must also enable or disable this criteria with
+             {@link #setIssuingDistributionPointEnabled(bool)}.</p>
+            
+             @param issuingDistributionPoint The issuing distribution point to set.
+                                             This is the DER encoded OCTET STRING extension value.
+             @see #getIssuingDistributionPoint()
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.IssuingDistributionPointEnabled">
+             Whether the issuing distribution point criteria should be applied.
+             Defaults to <code>false</code>.
+             <p>
+             You may also set the issuing distribution point criteria if not a missing
+             issuing distribution point should be assumed.</p>
+            
+             @return Returns if the issuing distribution point check is enabled.
+        </member>
+        <member name="P:Org.BouncyCastle.X509.Store.X509CrlStoreSelector.MaxBaseCrlNumber">
+             The maximum base CRL number. Defaults to <code>null</code>.
+            
+             @return Returns the maximum base CRL number.
+             @see #setMaxBaseCRLNumber(BigInteger)
+        </member>
+        <member name="T:Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory">
+            <summary>
+            A factory to produce Public Key Info Objects.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Create a Subject Public Key Info object for a given public key.
+            </summary>
+            <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
+            <returns>A subject public key info object.</returns>
+            <exception cref="T:System.Exception">Throw exception if object provided is not one of the above.</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCert(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCerts(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCert(System.IO.Stream)">
+            Generates a certificate object and initializes it with the data
+            read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509AttrCertParser.ReadAttrCerts(System.IO.Stream)">
+            Returns a (possibly empty) collection view of the certificates
+            read from the given input stream inStream.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Attribute">
+            Class for carrying the values in an X.509 Attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(Org.BouncyCastle.Asn1.Asn1Encodable)">
+            @param at an object representing an attribute.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1Encodable)">
+             Create an X.509 Attribute with the type given by the passed in oid and
+             the value represented by an ASN.1 Set containing value.
+            
+             @param oid type of the attribute
+             @param value value object to go into the atribute's value set.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Attribute.#ctor(System.String,Org.BouncyCastle.Asn1.Asn1EncodableVector)">
+             Create an X.59 Attribute with the type given by the passed in oid and the
+             value represented by an ASN.1 Set containing the objects in value.
+            
+             @param oid type of the attribute
+             @param value vector of values to go in the attribute's value set.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Certificate">
+            <summary>
+            An Object representing an X509 Certificate.
+            Has static methods for loading Certificates encoded in many forms that return X509Certificate Objects.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.IsValid(System.DateTime)">
+            <summary>
+            Return true if the nominated time is within the start and end times nominated on the certificate.
+            </summary>
+            <param name="time">The time to test validity against.</param>
+            <returns>True if certificate is valid for nominated time.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.CheckValidity">
+            <summary>
+            Checks if the current date is within certificate's validity period.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.CheckValidity(System.DateTime)">
+            <summary>
+            Checks if the given date is within certificate's validity period.
+            </summary>
+            <exception cref="T:Org.BouncyCastle.Security.Certificates.CertificateExpiredException">if the certificate is expired by given date</exception>
+            <exception cref="T:Org.BouncyCastle.Security.Certificates.CertificateNotYetValidException">if the certificate is not yet valid on given date</exception>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetTbsCertificate">
+            <summary>
+            Return the Der encoded TbsCertificate data.
+            This is the certificate component less the signature.
+            To Get the whole certificate call the GetEncoded() member.
+            </summary>
+            <returns>A byte array containing the Der encoded Certificate component.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetSignature">
+            <summary>
+            The signature.
+            </summary>
+            <returns>A byte array containg the signature of the certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetSigAlgParams">
+            <summary>
+            Get the signature algorithms parameters. (EG DSA Parameters)
+            </summary>
+            <returns>A byte array containing the Der encoded version of the parameters or null if there are none.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetKeyUsage">
+            <summary>
+            Get a key usage guidlines.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetPublicKey">
+            <summary>
+            Get the public key of the subject of the certificate.
+            </summary>
+            <returns>The public key parameters.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.GetEncoded">
+            <summary>
+            Return a Der encoded version of this certificate.
+            </summary>
+            <returns>A byte array.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Certificate.Verify(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Verify the certificate's signature using the nominated public key.
+            </summary>
+            <param name="key">An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters</param>
+            <returns>True if the signature is valid.</returns>
+            <exception cref="T:System.Exception">If key submitted is not of the above nominated types.</exception>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IsValidNow">
+            <summary>
+            Return true if the current time is within the start and end times nominated on the certificate.
+            </summary>
+            <returns>true id certificate is valid for the current time.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.Version">
+            <summary>
+            Return the certificate's version.
+            </summary>
+            <returns>An integer whose value Equals the version of the cerficate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SerialNumber">
+            <summary>
+            Return a <see cref="T:Org.BouncyCastle.Math.BigInteger">BigInteger</see> containing the serial number.
+            </summary>
+            <returns>The Serial number.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IssuerDN">
+            <summary>
+            Get the Issuer Distinguished Name. (Who signed the certificate.)
+            </summary>
+            <returns>And X509Object containing name and value pairs.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SubjectDN">
+            <summary>
+            Get the subject of this certificate.
+            </summary>
+            <returns>An X509Name object containing name and value pairs.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.NotBefore">
+            <summary>
+            The time that this certificate is valid from.
+            </summary>
+            <returns>A DateTime object representing that time in the local time zone.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.NotAfter">
+            <summary>
+            The time that this certificate is valid up to.
+            </summary>
+            <returns>A DateTime object representing that time in the local time zone.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SigAlgName">
+            <summary>
+            A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA)
+            </summary>
+            <returns>A sting representing the signature algorithm.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SigAlgOid">
+            <summary>
+            Get the Signature Algorithms Object ID.
+            </summary>
+            <returns>A string containg a '.' separated object id.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.IssuerUniqueID">
+            <summary>
+            Get the issuers UID.
+            </summary>
+            <returns>A DerBitString.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509Certificate.SubjectUniqueID">
+            <summary>
+            Get the subjects UID.
+            </summary>
+            <returns>A DerBitString.</returns>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CertificatePair">
+            <remarks>
+            This class contains a cross certificate pair. Cross certificates pairs may
+            contain two cross signed certificates from two CAs. A certificate from the
+            other CA to this CA is contained in the forward certificate, the certificate
+            from this CA to the other CA is contained in the reverse certificate.
+            </remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificatePair.#ctor(Org.BouncyCastle.X509.X509Certificate,Org.BouncyCastle.X509.X509Certificate)">
+            <summary>Constructor</summary>
+            <param name="forward">Certificate from the other CA to this CA.</param>
+            <param name="reverse">Certificate from this CA to the other CA.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificatePair.#ctor(Org.BouncyCastle.Asn1.X509.CertificatePair)">
+            <summary>Constructor from a ASN.1 CertificatePair structure.</summary>
+            <param name="pair">The <c>CertificatePair</c> ASN.1 object.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509CertificatePair.Forward">
+            <summary>Returns the certificate from the other CA to this CA.</summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509CertificatePair.Reverse">
+            <summary>Returns the certificate from this CA to the other CA.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CertificateParser">
+            class for dealing with X509 certificates.
+            <p>
+            At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
+            base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
+            objects.</p>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificate(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificates(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificate(System.IO.Stream)">
+            Generates a certificate object and initializes it with the data
+            read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertificateParser.ReadCertificates(System.IO.Stream)">
+            Returns a (possibly empty) collection view of the certificates
+            read from the given input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertPairParser.ReadCertPair(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CertPairParser.ReadCertPairs(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509Crl">
+             The following extensions are listed in RFC 2459 as relevant to CRLs
+            
+             Authority Key Identifier
+             Issuer Alternative Name
+             CRL Number
+             Delta CRL Indicator (critical)
+             Issuing Distribution Point (critical)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Crl.ToString">
+             Returns a string representation of this CRL.
+            
+             @return a string representation of this CRL.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509Crl.IsRevoked(Org.BouncyCastle.X509.X509Certificate)">
+             Checks whether the given certificate is on this CRL.
+            
+             @param cert the certificate to check for.
+             @return true if the given certificate is on this CRL,
+             false otherwise.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509CrlEntry">
+             The following extensions are listed in RFC 2459 as relevant to CRL Entries
+            
+             ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
+             (critical)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlEntry.#ctor(Org.BouncyCastle.Asn1.X509.CrlEntry,System.Boolean,Org.BouncyCastle.Asn1.X509.X509Name)">
+             Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
+             is <code>false</code> {@link #getCertificateIssuer()} will always
+             return <code>null</code>, <code>previousCertificateIssuer</code> is
+             ignored. If this <code>isIndirect</code> is specified and this CrlEntry
+             has no certificate issuer CRL entry extension
+             <code>previousCertificateIssuer</code> is returned by
+             {@link #getCertificateIssuer()}.
+            
+             @param c
+                        TbsCertificateList.CrlEntry object.
+             @param isIndirect
+                        <code>true</code> if the corresponding CRL is a indirect
+                        CRL.
+             @param previousCertificateIssuer
+                        Certificate issuer of the previous CrlEntry.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrl(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrls(System.Byte[])">
+            <summary>
+            Create loading data from byte array.
+            </summary>
+            <param name="input"></param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrl(System.IO.Stream)">
+            Generates a certificate revocation list (CRL) object and initializes
+            it with the data read from the input stream inStream.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509CrlParser.ReadCrls(System.IO.Stream)">
+             Returns a (possibly empty) collection view of the CRLs read from
+             the given input stream inStream.
+            
+             The inStream may contain a sequence of DER-encoded CRLs, or
+             a PKCS#7 CRL set.  This is a PKCS#7 SignedData object, with the
+             only significant field being crls.  In particular the signature
+             and the contents are ignored.
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509KeyUsage">
+             A holding class for constructing an X509 Key Usage extension.
+            
+             <pre>
+                id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+            
+                KeyUsage ::= BIT STRING {
+                     digitalSignature        (0),
+                     nonRepudiation          (1),
+                     keyEncipherment         (2),
+                     dataEncipherment        (3),
+                     keyAgreement            (4),
+                     keyCertSign             (5),
+                     cRLSign                 (6),
+                     encipherOnly            (7),
+                     decipherOnly            (8) }
+             </pre>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509KeyUsage.#ctor(System.Int32)">
+             Basic constructor.
+            
+             @param usage - the bitwise OR of the Key Usage flags giving the
+             allowed uses for the key.
+             e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509SignatureUtilities.GetDigestAlgName(Org.BouncyCastle.Asn1.DerObjectIdentifier)">
+            Return the digest algorithm using one of the standard JCA string
+            representations rather than the algorithm identifier (if possible).
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V1CertificateGenerator">
+            <summary>
+            Class to Generate X509V1 Certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.#ctor">
+            <summary>
+            Default Constructor.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Reset">
+            <summary>
+            Reset the generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>
+            Set the certificate's serial number.
+            </summary>
+            <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+            You will be surprised how ugly a serial number collision can get.</remarks>
+            <param name="serialNumber">The serial number.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the issuer distinguished name.
+            The issuer is the entity whose private key is used to sign the certificate.
+            </summary>
+            <param name="issuer">The issuers DN.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetNotBefore(System.DateTime)">
+            <summary>
+            Set the date that this certificate is to be valid from.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetNotAfter(System.DateTime)">
+            <summary>
+            Set the date after which this certificate will no longer be valid.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSubjectDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the subject distinguished name.
+            The subject describes the entity associated with the public key.
+            </summary>
+            <param name="subject"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetPublicKey(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Set the public key that this certificate identifies.
+            </summary>
+            <param name="publicKey"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm that will be used to sign this certificate.
+            This can be either a name or an OID, names are treated as case insensitive.
+            </summary>
+            <param name="signatureAlgorithm">string representation of the algorithm name</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate a new X509Certificate.
+            </summary>
+            <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V1CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate a new X509Certificate specifying a SecureRandom instance that you would like to use.
+            </summary>
+            <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+            <param name="random">The Secure Random you want to use.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V1CertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2AttributeCertificate">
+            <summary>An implementation of a version 2 X.509 Attribute Certificate.</summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator">
+            <remarks>Class to produce an X.509 Version 2 AttributeCertificate.</remarks>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Reset">
+            <summary>Reset the generator</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetHolder(Org.BouncyCastle.X509.AttributeCertificateHolder)">
+            <summary>Set the Holder of this Attribute Certificate.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetIssuer(Org.BouncyCastle.X509.AttributeCertificateIssuer)">
+            <summary>Set the issuer.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>Set the serial number for the certificate.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm. This can be either a name or an OID, names
+            are treated as case insensitive.
+            </summary>
+            <param name="signatureAlgorithm">The algorithm name.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddAttribute(Org.BouncyCastle.X509.X509Attribute)">
+            <summary>Add an attribute.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>Add a given extension field for the standard extensions tag.</summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            <summary>
+            Add a given extension field for the standard extensions tag.
+            The value parameter becomes the contents of the octet string associated
+            with the extension.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate an X509 certificate, based on the current issuer and subject.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate an X509 certificate, based on the current issuer and subject,
+            using the supplied source of randomness, if required.
+            </summary>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V2AttributeCertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V2CrlGenerator">
+            class to produce an X.509 Version 2 CRL.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Reset">
+            reset the generator
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
+            certificate.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,System.Int32)">
+             Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+             or 0 if CrlReason is not to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,System.Int32,System.DateTime)">
+             Add a CRL entry with an Invalidity Date extension as well as a CrlReason extension.
+             Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+             or 0 if CrlReason is not to be used
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrlEntry(Org.BouncyCastle.Math.BigInteger,System.DateTime,Org.BouncyCastle.Asn1.X509.X509Extensions)">
+             Add a CRL entry with extensions.
+            
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddCrl(Org.BouncyCastle.X509.X509Crl)">
+             Add the CRLEntry objects contained in a previous CRL.
+            
+             @param other the X509Crl to source the other entries from.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.SetSignatureAlgorithm(System.String)">
+             Set the signature algorithm. This can be either a name or an oid, names
+             are treated as case insensitive.
+            
+             @param signatureAlgorithm string representation of the algorithm name.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            add a given extension field for the standard extensions tag (tag 0)
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+            <param name="privateKey">The key used for signing.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V2CrlGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+            <param name="privateKey">The key used for signing.</param>
+            <param name="random">A user-defined source of randomness.</param>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V2CrlGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+        <member name="T:Org.BouncyCastle.X509.X509V3CertificateGenerator">
+            <summary>
+            A class to Generate Version 3 X509Certificates.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Reset">
+            <summary>
+            Reset the Generator.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSerialNumber(Org.BouncyCastle.Math.BigInteger)">
+            <summary>
+            Set the certificate's serial number.
+            </summary>
+            <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+            You will be surprised how ugly a serial number collision can Get.</remarks>
+            <param name="serialNumber">The serial number.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetIssuerDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the distinguished name of the issuer.
+            The issuer is the entity which is signing the certificate.
+            </summary>
+            <param name="issuer">The issuer's DN.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetNotBefore(System.DateTime)">
+            <summary>
+            Set the date that this certificate is to be valid from.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetNotAfter(System.DateTime)">
+            <summary>
+            Set the date after which this certificate will no longer be valid.
+            </summary>
+            <param name="date"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSubjectDN(Org.BouncyCastle.Asn1.X509.X509Name)">
+            <summary>
+            Set the DN of the entity that this certificate is about.
+            </summary>
+            <param name="subject"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetPublicKey(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Set the public key that this certificate identifies.
+            </summary>
+            <param name="publicKey"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSignatureAlgorithm(System.String)">
+            <summary>
+            Set the signature algorithm that will be used to sign this certificate.
+            </summary>
+            <param name="signatureAlgorithm"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetSubjectUniqueID(System.Boolean[])">
+            <summary>
+            Set the subject unique ID - note: it is very rare that it is correct to do this.
+            </summary>
+            <param name="uniqueID"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.SetIssuerUniqueID(System.Boolean[])">
+            <summary>
+            Set the issuer unique ID - note: it is very rare that it is correct to do this.
+            </summary>
+            <param name="uniqueID"/>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(System.String,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add a given extension field for the standard extensions tag (tag 3).
+            </summary>
+            <param name="oid">string containing a dotted decimal Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">The value.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.Asn1.Asn1Encodable)">
+            <summary>
+            Add an extension to this certificate.
+            </summary>
+            <param name="oid">Its Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">The value.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(System.String,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension using a string with a dotted decimal OID.
+            </summary>
+            <param name="oid">string containing a dotted decimal Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">byte[] containing the value of this extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.AddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,System.Byte[])">
+            <summary>
+            Add an extension to this certificate.
+            </summary>
+            <param name="oid">Its Object Identifier.</param>
+            <param name="critical">Is it critical.</param>
+            <param name="extensionValue">byte[] containing the value of this extension.</param>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.CopyAndAddExtension(System.String,System.Boolean,Org.BouncyCastle.X509.X509Certificate)">
+            <summary>
+            Add a given extension field for the standard extensions tag (tag 3),
+            copying the extension value from another certificate.
+            </summary>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.CopyAndAddExtension(Org.BouncyCastle.Asn1.DerObjectIdentifier,System.Boolean,Org.BouncyCastle.X509.X509Certificate)">
+            add a given extension field for the standard extensions tag (tag 3)
+            copying the extension value from another certificate.
+            @throws CertificateParsingException if the extension cannot be extracted.
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter)">
+            <summary>
+            Generate an X509Certificate.
+            </summary>
+            <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="M:Org.BouncyCastle.X509.X509V3CertificateGenerator.Generate(Org.BouncyCastle.Crypto.AsymmetricKeyParameter,Org.BouncyCastle.Security.SecureRandom)">
+            <summary>
+            Generate an X509Certificate using your own SecureRandom.
+            </summary>
+            <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+            <param name="random">You Secure Random instance.</param>
+            <returns>An X509Certificate.</returns>
+        </member>
+        <member name="P:Org.BouncyCastle.X509.X509V3CertificateGenerator.SignatureAlgNames">
+            <summary>
+            Allows enumeration of the signature names supported by the generator.
+            </summary>
+        </member>
+    </members>
+</doc>
diff --git a/BouncyCastle.AxCrypt/src/AssemblyInfo.cs b/BouncyCastle.AxCrypt/src/AssemblyInfo.cs
new file mode 100644
index 0000000..53d7bb1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/AssemblyInfo.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+//using System.Security.Permissions;
+
+//
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("BouncyCastle.Crypto")]
+[assembly: AssemblyDescription("Bouncy Castle Cryptography API")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("The Legion of the Bouncy Castle Inc.")]
+[assembly: AssemblyProduct("Bouncy Castle for .NET")]
+[assembly: AssemblyCopyright("Copyright (C) 2000-2014")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.8.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing.
+//
+// Notes:
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+
+[assembly: CLSCompliant(true)]
+#if !PCL
+[assembly: ComVisible(false)]
+#endif
+// Start with no permissions
+//[assembly: PermissionSet(SecurityAction.RequestOptional, Unrestricted=false)]
+//...and explicitly add those we need
+
+// see Org.BouncyCastle.Crypto.Encodings.Pkcs1Encoding.StrictLengthEnabledProperty
+//[assembly: EnvironmentPermission(SecurityAction.RequestOptional, Read="Org.BouncyCastle.Pkcs1.Strict")]
+internal class AssemblyInfo
+{
+    private static string version;
+
+    public static string Version
+    {
+        get
+        {
+            if (version == null)
+            {
+                var ver = (AssemblyVersionAttribute)typeof(AssemblyInfo).Assembly.GetCustomAttributes(typeof(AssemblyVersionAttribute), false).FirstOrDefault();
+                if (ver != null)
+                {
+                    version = ver.Version;
+                }
+
+                // if we're still here, then don't try again
+                if (version == null)
+                    version = string.Empty;
+            }
+
+            return version;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1Generator.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1Generator.cs
new file mode 100644
index 0000000..e560517
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1Generator.cs
@@ -0,0 +1,27 @@
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public abstract class Asn1Generator
+    {
+		private Stream _out;
+
+		protected Asn1Generator(
+			Stream outStream)
+        {
+            _out = outStream;
+        }
+
+		protected Stream Out
+		{
+			get { return _out; }
+		}
+
+		public abstract void AddObject(Asn1Encodable obj);
+
+		public abstract Stream GetRawOutputStream();
+
+		public abstract void Close();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1OctetStringParser.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1OctetStringParser.cs
new file mode 100644
index 0000000..5815aa4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1OctetStringParser.cs
@@ -0,0 +1,10 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public interface Asn1OctetStringParser
+		: IAsn1Convertible
+	{
+		Stream GetOctetStream();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1SequenceParser.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1SequenceParser.cs
new file mode 100644
index 0000000..9e88ac7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1SequenceParser.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public interface Asn1SequenceParser
+		: IAsn1Convertible
+	{
+		IAsn1Convertible ReadObject();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1SetParser.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1SetParser.cs
new file mode 100644
index 0000000..d1b9c64
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1SetParser.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public interface Asn1SetParser
+		: IAsn1Convertible
+	{
+		IAsn1Convertible ReadObject();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1StreamParser.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1StreamParser.cs
new file mode 100644
index 0000000..0c6b441
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1StreamParser.cs
@@ -0,0 +1,234 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class Asn1StreamParser
+	{
+		private readonly Stream _in;
+		private readonly int _limit;
+
+        private readonly byte[][] tmpBuffers;
+
+        public Asn1StreamParser(
+			Stream inStream)
+			: this(inStream, Asn1InputStream.FindLimit(inStream))
+		{
+		}
+
+		public Asn1StreamParser(
+			Stream	inStream,
+			int		limit)
+		{
+			if (!inStream.CanRead)
+				throw new ArgumentException("Expected stream to be readable", "inStream");
+
+			this._in = inStream;
+			this._limit = limit;
+            this.tmpBuffers = new byte[16][];
+        }
+
+		public Asn1StreamParser(
+			byte[] encoding)
+			: this(new MemoryStream(encoding, false), encoding.Length)
+		{
+		}
+
+		internal IAsn1Convertible ReadIndef(int tagValue)
+		{
+			// Note: INDEF => CONSTRUCTED
+
+			// TODO There are other tags that may be constructed (e.g. BIT_STRING)
+			switch (tagValue)
+			{
+				case Asn1Tags.External:
+					return new DerExternalParser(this);
+				case Asn1Tags.OctetString:
+					return new BerOctetStringParser(this);
+				case Asn1Tags.Sequence:
+					return new BerSequenceParser(this);
+				case Asn1Tags.Set:
+					return new BerSetParser(this);
+				default:
+					throw new Asn1Exception("unknown BER object encountered: 0x" + tagValue.ToString("X"));
+			}
+		}
+
+		internal IAsn1Convertible ReadImplicit(bool constructed, int tag)
+		{
+			if (_in is IndefiniteLengthInputStream)
+			{
+				if (!constructed)
+					throw new IOException("indefinite length primitive encoding encountered");
+
+				return ReadIndef(tag);
+			}
+
+			if (constructed)
+			{
+				switch (tag)
+				{
+					case Asn1Tags.Set:
+						return new DerSetParser(this);
+					case Asn1Tags.Sequence:
+						return new DerSequenceParser(this);
+					case Asn1Tags.OctetString:
+						return new BerOctetStringParser(this);
+				}
+			}
+			else
+			{
+				switch (tag)
+				{
+					case Asn1Tags.Set:
+						throw new Asn1Exception("sequences must use constructed encoding (see X.690 8.9.1/8.10.1)");
+					case Asn1Tags.Sequence:
+						throw new Asn1Exception("sets must use constructed encoding (see X.690 8.11.1/8.12.1)");
+					case Asn1Tags.OctetString:
+						return new DerOctetStringParser((DefiniteLengthInputStream)_in);
+				}
+			}
+
+			throw new Asn1Exception("implicit tagging not implemented");
+		}
+
+		internal Asn1Object ReadTaggedObject(bool constructed, int tag)
+		{
+			if (!constructed)
+			{
+				// Note: !CONSTRUCTED => IMPLICIT
+				DefiniteLengthInputStream defIn = (DefiniteLengthInputStream)_in;
+				return new DerTaggedObject(false, tag, new DerOctetString(defIn.ToArray()));
+			}
+
+			Asn1EncodableVector v = ReadVector();
+
+			if (_in is IndefiniteLengthInputStream)
+			{
+				return v.Count == 1
+					?   new BerTaggedObject(true, tag, v[0])
+					:   new BerTaggedObject(false, tag, BerSequence.FromVector(v));
+			}
+
+			return v.Count == 1
+				?   new DerTaggedObject(true, tag, v[0])
+				:   new DerTaggedObject(false, tag, DerSequence.FromVector(v));
+		}
+
+		public virtual IAsn1Convertible ReadObject()
+		{
+			int tag = _in.ReadByte();
+			if (tag == -1)
+				return null;
+
+			// turn of looking for "00" while we resolve the tag
+			Set00Check(false);
+
+			//
+			// calculate tag number
+			//
+			int tagNo = Asn1InputStream.ReadTagNumber(_in, tag);
+
+			bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+			//
+			// calculate length
+			//
+			int length = Asn1InputStream.ReadLength(_in, _limit);
+
+			if (length < 0) // indefinite length method
+			{
+				if (!isConstructed)
+					throw new IOException("indefinite length primitive encoding encountered");
+
+				IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(_in, _limit);
+				Asn1StreamParser sp = new Asn1StreamParser(indIn, _limit);
+
+				if ((tag & Asn1Tags.Application) != 0)
+				{
+					return new BerApplicationSpecificParser(tagNo, sp);
+				}
+
+				if ((tag & Asn1Tags.Tagged) != 0)
+				{
+					return new BerTaggedObjectParser(true, tagNo, sp);
+				}
+
+				return sp.ReadIndef(tagNo);
+			}
+			else
+			{
+				DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(_in, length);
+
+				if ((tag & Asn1Tags.Application) != 0)
+				{
+					return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+				}
+
+				if ((tag & Asn1Tags.Tagged) != 0)
+				{
+					return new BerTaggedObjectParser(isConstructed, tagNo, new Asn1StreamParser(defIn));
+				}
+
+				if (isConstructed)
+				{
+					// TODO There are other tags that may be constructed (e.g. BitString)
+					switch (tagNo)
+					{
+						case Asn1Tags.OctetString:
+							//
+							// yes, people actually do this...
+							//
+							return new BerOctetStringParser(new Asn1StreamParser(defIn));
+						case Asn1Tags.Sequence:
+							return new DerSequenceParser(new Asn1StreamParser(defIn));
+						case Asn1Tags.Set:
+							return new DerSetParser(new Asn1StreamParser(defIn));
+						case Asn1Tags.External:
+							return new DerExternalParser(new Asn1StreamParser(defIn));
+						default:
+                            throw new IOException("unknown tag " + tagNo + " encountered");
+                    }
+				}
+
+				// Some primitive encodings can be handled by parsers too...
+				switch (tagNo)
+				{
+					case Asn1Tags.OctetString:
+						return new DerOctetStringParser(defIn);
+				}
+
+				try
+				{
+					return Asn1InputStream.CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
+				}
+				catch (ArgumentException e)
+				{
+					throw new Asn1Exception("corrupted stream detected", e);
+				}
+			}
+		}
+
+		private void Set00Check(
+			bool enabled)
+		{
+			if (_in is IndefiniteLengthInputStream)
+			{
+				((IndefiniteLengthInputStream) _in).SetEofOn00(enabled);
+			}
+		}
+
+		internal Asn1EncodableVector ReadVector()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			IAsn1Convertible obj;
+			while ((obj = ReadObject()) != null)
+			{
+				v.Add(obj.ToAsn1Object());
+			}
+
+			return v;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ASN1TaggedObjectParser.cs b/BouncyCastle.AxCrypt/src/asn1/ASN1TaggedObjectParser.cs
new file mode 100644
index 0000000..32327a2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ASN1TaggedObjectParser.cs
@@ -0,0 +1,10 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public interface Asn1TaggedObjectParser
+		: IAsn1Convertible
+	{
+		int TagNo { get; }
+
+		IAsn1Convertible GetObjectParser(int tag, bool isExplicit);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Encodable.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Encodable.cs
new file mode 100644
index 0000000..e3dd9a1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Encodable.cs
@@ -0,0 +1,78 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public abstract class Asn1Encodable
+		: IAsn1Convertible
+    {
+		public const string Der = "DER";
+		public const string Ber = "BER";
+
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+            Asn1OutputStream aOut = new Asn1OutputStream(bOut);
+
+			aOut.WriteObject(this);
+
+			return bOut.ToArray();
+        }
+
+		public byte[] GetEncoded(
+			string encoding)
+		{
+			if (encoding.Equals(Der))
+			{
+				MemoryStream bOut = new MemoryStream();
+				DerOutputStream dOut = new DerOutputStream(bOut);
+
+				dOut.WriteObject(this);
+
+				return bOut.ToArray();
+			}
+
+			return GetEncoded();
+		}
+
+		/**
+		* Return the DER encoding of the object, null if the DER encoding can not be made.
+		*
+		* @return a DER byte array, null otherwise.
+		*/
+		public byte[] GetDerEncoded()
+		{
+			try
+			{
+				return GetEncoded(Der);
+			}
+			catch (IOException)
+			{
+				return null;
+			}
+		}
+
+		public sealed override int GetHashCode()
+		{
+			return ToAsn1Object().CallAsn1GetHashCode();
+		}
+
+		public sealed override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			IAsn1Convertible other = obj as IAsn1Convertible;
+
+			if (other == null)
+				return false;
+
+			Asn1Object o1 = ToAsn1Object();
+			Asn1Object o2 = other.ToAsn1Object();
+
+			return o1 == o2 || o1.CallAsn1Equals(o2);
+		}
+
+		public abstract Asn1Object ToAsn1Object();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1EncodableVector.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1EncodableVector.cs
new file mode 100644
index 0000000..49532fe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1EncodableVector.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class Asn1EncodableVector
+		: IEnumerable
+    {
+        private IList v = Platform.CreateArrayList();
+
+		public static Asn1EncodableVector FromEnumerable(
+			IEnumerable e)
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+			foreach (Asn1Encodable obj in e)
+			{
+				v.Add(obj);
+			}
+			return v;
+		}
+
+//		public Asn1EncodableVector()
+//		{
+//		}
+
+		public Asn1EncodableVector(
+			params Asn1Encodable[] v)
+		{
+			Add(v);
+		}
+
+//		public void Add(
+//			Asn1Encodable obj)
+//		{
+//			v.Add(obj);
+//		}
+
+		public void Add(
+			params Asn1Encodable[] objs)
+		{
+			foreach (Asn1Encodable obj in objs)
+			{
+				v.Add(obj);
+			}
+		}
+
+		public void AddOptional(
+			params Asn1Encodable[] objs)
+		{
+			if (objs != null)
+			{
+				foreach (Asn1Encodable obj in objs)
+				{
+					if (obj != null)
+					{
+						v.Add(obj);
+					}
+				}
+			}
+		}
+
+		public Asn1Encodable this[
+			int index]
+		{
+			get { return (Asn1Encodable) v[index]; }
+		}
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public Asn1Encodable Get(
+            int index)
+        {
+            return this[index];
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+		{
+			get { return v.Count; }
+		}
+
+		public int Count
+		{
+			get { return v.Count; }
+		}
+
+		public IEnumerator GetEnumerator()
+		{
+			return v.GetEnumerator();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Exception.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Exception.cs
new file mode 100644
index 0000000..806cc95
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Exception.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class Asn1Exception
+		: IOException
+	{
+		public Asn1Exception()
+			: base()
+		{
+		}
+
+		public Asn1Exception(
+			string message)
+			: base(message)
+		{
+		}
+
+		public Asn1Exception(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1InputStream.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1InputStream.cs
new file mode 100644
index 0000000..18d13c3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1InputStream.cs
@@ -0,0 +1,368 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * a general purpose ASN.1 decoder - note: this class differs from the
+     * others in that it returns null after it has read the last object in
+     * the stream. If an ASN.1 Null is encountered a Der/BER Null object is
+     * returned.
+     */
+    public class Asn1InputStream
+        : FilterStream
+    {
+        private readonly int limit;
+
+        private readonly byte[][] tmpBuffers;
+
+        internal static int FindLimit(Stream input)
+        {
+            if (input is LimitedInputStream)
+            {
+                return ((LimitedInputStream)input).GetRemaining();
+            }
+            else if (input is MemoryStream)
+            {
+                MemoryStream mem = (MemoryStream)input;
+                return (int)(mem.Length - mem.Position);
+            }
+
+            return int.MaxValue;
+        }
+
+        public Asn1InputStream(
+            Stream inputStream)
+            : this(inputStream, FindLimit(inputStream))
+        {
+        }
+
+        /**
+         * Create an ASN1InputStream where no DER object will be longer than limit.
+         *
+         * @param input stream containing ASN.1 encoded data.
+         * @param limit maximum size of a DER encoded object.
+         */
+        public Asn1InputStream(
+            Stream	inputStream,
+            int		limit)
+            : base(inputStream)
+        {
+            this.limit = limit;
+            this.tmpBuffers = new byte[16][];
+        }
+
+        /**
+         * Create an ASN1InputStream based on the input byte array. The length of DER objects in
+         * the stream is automatically limited to the length of the input array.
+         *
+         * @param input array containing ASN.1 encoded data.
+         */
+        public Asn1InputStream(
+            byte[] input)
+            : this(new MemoryStream(input, false), input.Length)
+        {
+        }
+
+        /**
+        * build an object given its tag and the number of bytes to construct it from.
+        */
+        private Asn1Object BuildObject(
+            int	tag,
+            int	tagNo,
+            int	length)
+        {
+            bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+            DefiniteLengthInputStream defIn = new DefiniteLengthInputStream(this.s, length);
+
+            if ((tag & Asn1Tags.Application) != 0)
+            {
+                return new DerApplicationSpecific(isConstructed, tagNo, defIn.ToArray());
+            }
+
+            if ((tag & Asn1Tags.Tagged) != 0)
+            {
+                return new Asn1StreamParser(defIn).ReadTaggedObject(isConstructed, tagNo);
+            }
+
+            if (isConstructed)
+            {
+                // TODO There are other tags that may be constructed (e.g. BitString)
+                switch (tagNo)
+                {
+                    case Asn1Tags.OctetString:
+                        //
+                        // yes, people actually do this...
+                        //
+                        return new BerOctetString(BuildDerEncodableVector(defIn));
+                    case Asn1Tags.Sequence:
+                        return CreateDerSequence(defIn);
+                    case Asn1Tags.Set:
+                        return CreateDerSet(defIn);
+                    case Asn1Tags.External:
+                        return new DerExternal(BuildDerEncodableVector(defIn));                
+                    default:
+                        throw new IOException("unknown tag " + tagNo + " encountered");
+                }
+            }
+
+            return CreatePrimitiveDerObject(tagNo, defIn, tmpBuffers);
+        }
+
+        internal Asn1EncodableVector BuildEncodableVector()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            Asn1Object o;
+            while ((o = ReadObject()) != null)
+            {
+                v.Add(o);
+            }
+
+            return v;
+        }
+
+        internal virtual Asn1EncodableVector BuildDerEncodableVector(
+            DefiniteLengthInputStream dIn)
+        {
+            return new Asn1InputStream(dIn).BuildEncodableVector();
+        }
+
+        internal virtual DerSequence CreateDerSequence(
+            DefiniteLengthInputStream dIn)
+        {
+            return DerSequence.FromVector(BuildDerEncodableVector(dIn));
+        }
+
+        internal virtual DerSet CreateDerSet(
+            DefiniteLengthInputStream dIn)
+        {
+            return DerSet.FromVector(BuildDerEncodableVector(dIn), false);
+        }
+
+        public Asn1Object ReadObject()
+        {
+            int tag = ReadByte();
+            if (tag <= 0)
+            {
+                if (tag == 0)
+                    throw new IOException("unexpected end-of-contents marker");
+
+                return null;
+            }
+
+            //
+            // calculate tag number
+            //
+            int tagNo = ReadTagNumber(this.s, tag);
+
+            bool isConstructed = (tag & Asn1Tags.Constructed) != 0;
+
+            //
+            // calculate length
+            //
+            int length = ReadLength(this.s, limit);
+
+            if (length < 0) // indefinite length method
+            {
+                if (!isConstructed)
+                    throw new IOException("indefinite length primitive encoding encountered");
+
+                IndefiniteLengthInputStream indIn = new IndefiniteLengthInputStream(this.s, limit);
+                Asn1StreamParser sp = new Asn1StreamParser(indIn, limit);
+
+                if ((tag & Asn1Tags.Application) != 0)
+                {
+                    return new BerApplicationSpecificParser(tagNo, sp).ToAsn1Object();
+                }
+
+                if ((tag & Asn1Tags.Tagged) != 0)
+                {
+                    return new BerTaggedObjectParser(true, tagNo, sp).ToAsn1Object();
+                }
+
+                // TODO There are other tags that may be constructed (e.g. BitString)
+                switch (tagNo)
+                {
+                    case Asn1Tags.OctetString:
+                        return new BerOctetStringParser(sp).ToAsn1Object();
+                    case Asn1Tags.Sequence:
+                        return new BerSequenceParser(sp).ToAsn1Object();
+                    case Asn1Tags.Set:
+                        return new BerSetParser(sp).ToAsn1Object();
+                    case Asn1Tags.External:
+                        return new DerExternalParser(sp).ToAsn1Object();
+                    default:
+                        throw new IOException("unknown BER object encountered");
+                }
+            }
+            else
+            {
+                try
+                {
+                    return BuildObject(tag, tagNo, length);
+                }
+                catch (ArgumentException e)
+                {
+                    throw new Asn1Exception("corrupted stream detected", e);
+                }
+            }
+        }
+
+        internal static int ReadTagNumber(
+            Stream	s,
+            int		tag)
+        {
+            int tagNo = tag & 0x1f;
+
+            //
+            // with tagged object tag number is bottom 5 bits, or stored at the start of the content
+            //
+            if (tagNo == 0x1f)
+            {
+                tagNo = 0;
+
+                int b = s.ReadByte();
+
+                // X.690-0207 8.1.2.4.2
+                // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+                if ((b & 0x7f) == 0) // Note: -1 will pass
+                {
+                    throw new IOException("Corrupted stream - invalid high tag number found");
+                }
+
+                while ((b >= 0) && ((b & 0x80) != 0))
+                {
+                    tagNo |= (b & 0x7f);
+                    tagNo <<= 7;
+                    b = s.ReadByte();
+                }
+
+                if (b < 0)
+                    throw new EndOfStreamException("EOF found inside tag value.");
+
+                tagNo |= (b & 0x7f);
+            }
+
+            return tagNo;
+        }
+
+        internal static int ReadLength(
+            Stream	s,
+            int		limit)
+        {
+            int length = s.ReadByte();
+            if (length < 0)
+                throw new EndOfStreamException("EOF found when length expected");
+
+            if (length == 0x80)
+                return -1;      // indefinite-length encoding
+
+            if (length > 127)
+            {
+                int size = length & 0x7f;
+
+                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+                if (size > 4)
+                    throw new IOException("DER length more than 4 bytes: " + size);
+
+                length = 0;
+                for (int i = 0; i < size; i++)
+                {
+                    int next = s.ReadByte();
+
+                    if (next < 0)
+                        throw new EndOfStreamException("EOF found reading length");
+
+                    length = (length << 8) + next;
+                }
+
+                if (length < 0)
+                    throw new IOException("Corrupted stream - negative length found");
+
+                if (length >= limit)   // after all we must have read at least 1 byte
+                    throw new IOException("Corrupted stream - out of bounds length found");
+            }
+
+            return length;
+        }
+
+        internal static byte[] GetBuffer(DefiniteLengthInputStream defIn, byte[][] tmpBuffers)
+        {
+            int len = defIn.GetRemaining();
+            if (len >= tmpBuffers.Length)
+            {
+                return defIn.ToArray();
+            }
+
+            byte[] buf = tmpBuffers[len];
+            if (buf == null)
+            {
+                buf = tmpBuffers[len] = new byte[len];
+            }
+
+            defIn.ReadAllIntoByteArray(buf);
+
+            return buf;
+        }
+
+        internal static Asn1Object CreatePrimitiveDerObject(
+            int                         tagNo,
+            DefiniteLengthInputStream   defIn,
+            byte[][]                    tmpBuffers)
+        {
+            switch (tagNo)
+            {
+                case Asn1Tags.Boolean:
+                    return DerBoolean.FromOctetString(GetBuffer(defIn, tmpBuffers));
+                case Asn1Tags.Enumerated:
+                    return DerEnumerated.FromOctetString(GetBuffer(defIn, tmpBuffers));
+                case Asn1Tags.ObjectIdentifier:
+                    return DerObjectIdentifier.FromOctetString(GetBuffer(defIn, tmpBuffers));
+            }
+
+            byte[] bytes = defIn.ToArray();
+
+            switch (tagNo)
+            {
+                case Asn1Tags.BitString:
+                    return DerBitString.FromAsn1Octets(bytes);
+                case Asn1Tags.BmpString:
+                    return new DerBmpString(bytes);
+                case Asn1Tags.GeneralizedTime:
+                    return new DerGeneralizedTime(bytes);
+                case Asn1Tags.GeneralString:
+                    return new DerGeneralString(bytes);
+                case Asn1Tags.IA5String:
+                    return new DerIA5String(bytes);
+                case Asn1Tags.Integer:
+                    return new DerInteger(bytes);
+                case Asn1Tags.Null:
+                    return DerNull.Instance;   // actual content is ignored (enforce 0 length?)
+                case Asn1Tags.NumericString:
+                    return new DerNumericString(bytes);
+                case Asn1Tags.OctetString:
+                    return new DerOctetString(bytes);
+                case Asn1Tags.PrintableString:
+                    return new DerPrintableString(bytes);
+                case Asn1Tags.T61String:
+                    return new DerT61String(bytes);
+                case Asn1Tags.UniversalString:
+                    return new DerUniversalString(bytes);
+                case Asn1Tags.UtcTime:
+                    return new DerUtcTime(bytes);
+                case Asn1Tags.Utf8String:
+                    return new DerUtf8String(bytes);
+                case Asn1Tags.VisibleString:
+                    return new DerVisibleString(bytes);
+                default:
+                    throw new IOException("unknown tag " + tagNo + " encountered");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Null.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Null.cs
new file mode 100644
index 0000000..d54019f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Null.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * A Null object.
+     */
+    public abstract class Asn1Null
+        : Asn1Object
+    {
+        internal Asn1Null()
+        {
+        }
+
+		public override string ToString()
+		{
+			return "NULL";
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Object.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Object.cs
new file mode 100644
index 0000000..08bd599
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Object.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public abstract class Asn1Object
+		: Asn1Encodable
+    {
+		/// <summary>Create a base ASN.1 object from a byte array.</summary>
+		/// <param name="data">The byte array to parse.</param>
+		/// <returns>The base ASN.1 object represented by the byte array.</returns>
+		/// <exception cref="IOException">If there is a problem parsing the data.</exception>
+		public static Asn1Object FromByteArray(
+			byte[] data)
+		{
+			try
+			{
+				return new Asn1InputStream(data).ReadObject();
+			}
+			catch (InvalidCastException)
+			{
+				throw new IOException("cannot recognise object in stream");    
+			}
+		}
+
+		/// <summary>Read a base ASN.1 object from a stream.</summary>
+		/// <param name="inStr">The stream to parse.</param>
+		/// <returns>The base ASN.1 object represented by the byte array.</returns>
+		/// <exception cref="IOException">If there is a problem parsing the data.</exception>
+		public static Asn1Object FromStream(
+			Stream inStr)
+		{
+			try
+			{
+				return new Asn1InputStream(inStr).ReadObject();
+			}
+			catch (InvalidCastException)
+			{
+				throw new IOException("cannot recognise object in stream");    
+			}
+		}
+
+		public sealed override Asn1Object ToAsn1Object()
+        {
+            return this;
+        }
+
+		internal abstract void Encode(DerOutputStream derOut);
+
+		protected abstract bool Asn1Equals(Asn1Object asn1Object);
+		protected abstract int Asn1GetHashCode();
+
+		internal bool CallAsn1Equals(Asn1Object obj)
+		{
+			return Asn1Equals(obj);
+		}
+
+		internal int CallAsn1GetHashCode()
+		{
+			return Asn1GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1OctetString.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1OctetString.cs
new file mode 100644
index 0000000..9c738a8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1OctetString.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public abstract class Asn1OctetString
+        : Asn1Object, Asn1OctetStringParser
+    {
+        internal byte[] str;
+
+		/**
+         * return an Octet string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *              be converted.
+         */
+		public static Asn1OctetString GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is Asn1OctetString)
+			{
+				return GetInstance(o);
+			}
+
+			return BerOctetString.FromSequence(Asn1Sequence.GetInstance(o));
+		}
+
+        /**
+         * return an Octet string from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+		public static Asn1OctetString GetInstance(object obj)
+		{
+			if (obj == null || obj is Asn1OctetString)
+			{
+				return (Asn1OctetString)obj;
+			}
+
+			// TODO: this needs to be deleted in V2
+			if (obj is Asn1TaggedObject)
+				return GetInstance(((Asn1TaggedObject)obj).GetObject());
+
+			throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+		}
+
+        /**
+         * @param string the octets making up the octet string.
+         */
+        internal Asn1OctetString(
+            byte[] str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+        internal Asn1OctetString(
+            Asn1Encodable obj)
+        {
+            try
+            {
+				this.str = obj.GetEncoded(Asn1Encodable.Der);
+            }
+            catch (IOException e)
+            {
+                throw new ArgumentException("Error processing object : " + e.ToString());
+            }
+        }
+
+		public Stream GetOctetStream()
+		{
+			return new MemoryStream(str, false);
+		}
+
+		public Asn1OctetStringParser Parser
+		{
+			get { return this; }
+		}
+
+		public virtual byte[] GetOctets()
+        {
+            return str;
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+			return Arrays.GetHashCode(GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerOctetString other = asn1Object as DerOctetString;
+
+			if (other == null)
+				return false;
+
+			return Arrays.AreEqual(GetOctets(), other.GetOctets());
+		}
+
+		public override string ToString()
+		{
+			return "#" + Hex.ToHexString(str);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1OutputStream.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1OutputStream.cs
new file mode 100644
index 0000000..39c8b1e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1OutputStream.cs
@@ -0,0 +1,35 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class Asn1OutputStream
+        : DerOutputStream
+    {
+        public Asn1OutputStream(Stream os) : base(os)
+        {
+        }
+
+		[Obsolete("Use version taking an Asn1Encodable arg instead")]
+        public override void WriteObject(
+            object    obj)
+        {
+            if (obj == null)
+            {
+                WriteNull();
+            }
+            else if (obj is Asn1Object)
+            {
+                ((Asn1Object)obj).Encode(this);
+            }
+            else if (obj is Asn1Encodable)
+            {
+                ((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+            }
+            else
+            {
+                throw new IOException("object not Asn1Encodable");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1ParsingException.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1ParsingException.cs
new file mode 100644
index 0000000..40e5da4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1ParsingException.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class Asn1ParsingException
+		: InvalidOperationException
+	{
+		public Asn1ParsingException()
+			: base()
+		{
+		}
+
+		public Asn1ParsingException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public Asn1ParsingException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Sequence.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Sequence.cs
new file mode 100644
index 0000000..5f9ea44
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Sequence.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public abstract class Asn1Sequence
+        : Asn1Object, IEnumerable
+    {
+        private readonly IList seq;
+
+        /**
+         * return an Asn1Sequence from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static Asn1Sequence GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Asn1Sequence)
+            {
+                return (Asn1Sequence)obj;
+            }
+            else if (obj is Asn1SequenceParser)
+            {
+                return Asn1Sequence.GetInstance(((Asn1SequenceParser)obj).ToAsn1Object());
+            }
+            else if (obj is byte[])
+            {
+                try
+                {
+                    return Asn1Sequence.GetInstance(FromByteArray((byte[])obj));
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("failed to construct sequence from byte[]: " + e.Message);
+                }
+            }
+            else if (obj is Asn1Encodable)
+            {
+                Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object();
+                
+                if (primitive is Asn1Sequence)
+                {
+                    return (Asn1Sequence)primitive;
+                }
+            }
+
+            throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+        }
+
+        /**
+         * Return an ASN1 sequence from a tagged object. There is a special
+         * case here, if an object appears to have been explicitly tagged on
+         * reading but we were expecting it to be implicitly tagged in the
+         * normal course of events it indicates that we lost the surrounding
+         * sequence - so we need to add it back (this will happen if the tagged
+         * object is a sequence that contains other sequences). If you are
+         * dealing with implicitly tagged sequences you really <b>should</b>
+         * be using this method.
+         *
+         * @param obj the tagged object.
+         * @param explicitly true if the object is meant to be explicitly tagged,
+         *          false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *          be converted.
+         */
+        public static Asn1Sequence GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            Asn1Object inner = obj.GetObject();
+
+            if (explicitly)
+            {
+                if (!obj.IsExplicit())
+                    throw new ArgumentException("object implicit - explicit expected.");
+
+                return (Asn1Sequence) inner;
+            }
+
+            //
+            // constructed object which appears to be explicitly tagged
+            // when it should be implicit means we have to add the
+            // surrounding sequence.
+            //
+            if (obj.IsExplicit())
+            {
+                if (obj is BerTaggedObject)
+                {
+                    return new BerSequence(inner);
+                }
+
+                return new DerSequence(inner);
+            }
+
+            if (inner is Asn1Sequence)
+            {
+                return (Asn1Sequence) inner;
+            }
+
+            throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+        }
+
+        protected internal Asn1Sequence(
+            int capacity)
+        {
+            seq = Platform.CreateArrayList(capacity);
+        }
+
+        public virtual IEnumerator GetEnumerator()
+        {
+            return seq.GetEnumerator();
+        }
+
+        [Obsolete("Use GetEnumerator() instead")]
+        public IEnumerator GetObjects()
+        {
+            return GetEnumerator();
+        }
+
+        private class Asn1SequenceParserImpl
+            : Asn1SequenceParser
+        {
+            private readonly Asn1Sequence outer;
+            private readonly int max;
+            private int index;
+
+            public Asn1SequenceParserImpl(
+                Asn1Sequence outer)
+            {
+                this.outer = outer;
+                this.max = outer.Count;
+            }
+
+            public IAsn1Convertible ReadObject()
+            {
+                if (index == max)
+                    return null;
+
+                Asn1Encodable obj = outer[index++];
+
+                if (obj is Asn1Sequence)
+                    return ((Asn1Sequence)obj).Parser;
+
+                if (obj is Asn1Set)
+                    return ((Asn1Set)obj).Parser;
+
+                // NB: Asn1OctetString implements Asn1OctetStringParser directly
+//				if (obj is Asn1OctetString)
+//					return ((Asn1OctetString)obj).Parser;
+
+                return obj;
+            }
+
+            public Asn1Object ToAsn1Object()
+            {
+                return outer;
+            }
+        }
+
+        public virtual Asn1SequenceParser Parser
+        {
+            get { return new Asn1SequenceParserImpl(this); }
+        }
+
+        /**
+         * return the object at the sequence position indicated by index.
+         *
+         * @param index the sequence number (starting at zero) of the object
+         * @return the object at the sequence position indicated by index.
+         */
+        public virtual Asn1Encodable this[int index]
+        {
+            get { return (Asn1Encodable) seq[index]; }
+        }
+
+        [Obsolete("Use 'object[index]' syntax instead")]
+        public Asn1Encodable GetObjectAt(
+            int index)
+        {
+             return this[index];
+        }
+
+        [Obsolete("Use 'Count' property instead")]
+        public int Size
+        {
+            get { return Count; }
+        }
+
+        public virtual int Count
+        {
+            get { return seq.Count; }
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            int hc = Count;
+
+            foreach (object o in this)
+            {
+                hc *= 17;
+                if (o == null)
+                {
+                    hc ^= DerNull.Instance.GetHashCode();
+                }
+                else
+                {
+                    hc ^= o.GetHashCode();
+                }
+            }
+
+            return hc;
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            Asn1Sequence other = asn1Object as Asn1Sequence;
+
+            if (other == null)
+                return false;
+
+            if (Count != other.Count)
+                return false;
+
+            IEnumerator s1 = GetEnumerator();
+            IEnumerator s2 = other.GetEnumerator();
+
+            while (s1.MoveNext() && s2.MoveNext())
+            {
+                Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
+                Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+
+                if (!o1.Equals(o2))
+                    return false;
+            }
+
+            return true;
+        }
+
+        private Asn1Encodable GetCurrent(IEnumerator e)
+        {
+            Asn1Encodable encObj = (Asn1Encodable)e.Current;
+
+            // unfortunately null was allowed as a substitute for DER null
+            if (encObj == null)
+                return DerNull.Instance;
+
+            return encObj;
+        }
+
+        protected internal void AddObject(
+            Asn1Encodable obj)
+        {
+            seq.Add(obj);
+        }
+
+        public override string ToString()
+        {
+            return CollectionUtilities.ToString(seq);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Set.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Set.cs
new file mode 100644
index 0000000..2e77ca2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Set.cs
@@ -0,0 +1,351 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1
+{
+    abstract public class Asn1Set
+        : Asn1Object, IEnumerable
+    {
+        private readonly IList _set;
+
+        /**
+         * return an ASN1Set from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static Asn1Set GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Asn1Set)
+            {
+                return (Asn1Set)obj;
+            }
+            else if (obj is Asn1SetParser)
+            {
+                return Asn1Set.GetInstance(((Asn1SetParser)obj).ToAsn1Object());
+            }
+            else if (obj is byte[])
+            {
+                try
+                {
+                    return Asn1Set.GetInstance(FromByteArray((byte[])obj));
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("failed to construct set from byte[]: " + e.Message);
+                }
+            }
+            else if (obj is Asn1Encodable)
+            {
+                Asn1Object primitive = ((Asn1Encodable)obj).ToAsn1Object();
+
+                if (primitive is Asn1Set)
+                {
+                    return (Asn1Set)primitive;
+                }
+            }
+
+            throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+        }
+
+        /**
+         * Return an ASN1 set from a tagged object. There is a special
+         * case here, if an object appears to have been explicitly tagged on
+         * reading but we were expecting it to be implicitly tagged in the
+         * normal course of events it indicates that we lost the surrounding
+         * set - so we need to add it back (this will happen if the tagged
+         * object is a sequence that contains other sequences). If you are
+         * dealing with implicitly tagged sets you really <b>should</b>
+         * be using this method.
+         *
+         * @param obj the tagged object.
+         * @param explicitly true if the object is meant to be explicitly tagged
+         *          false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *          be converted.
+         */
+        public static Asn1Set GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            Asn1Object inner = obj.GetObject();
+
+            if (explicitly)
+            {
+                if (!obj.IsExplicit())
+                    throw new ArgumentException("object implicit - explicit expected.");
+
+                return (Asn1Set) inner;
+            }
+
+            //
+            // constructed object which appears to be explicitly tagged
+            // and it's really implicit means we have to add the
+            // surrounding sequence.
+            //
+            if (obj.IsExplicit())
+            {
+                return new DerSet(inner);
+            }
+
+            if (inner is Asn1Set)
+            {
+                return (Asn1Set) inner;
+            }
+
+            //
+            // in this case the parser returns a sequence, convert it
+            // into a set.
+            //
+            if (inner is Asn1Sequence)
+            {
+                Asn1EncodableVector v = new Asn1EncodableVector();
+                Asn1Sequence s = (Asn1Sequence) inner;
+
+                foreach (Asn1Encodable ae in s)
+                {
+                    v.Add(ae);
+                }
+
+                // TODO Should be able to construct set directly from sequence?
+                return new DerSet(v, false);
+            }
+
+            throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+        }
+
+        protected internal Asn1Set(
+            int capacity)
+        {
+            _set = Platform.CreateArrayList(capacity);
+        }
+
+        public virtual IEnumerator GetEnumerator()
+        {
+            return _set.GetEnumerator();
+        }
+
+        [Obsolete("Use GetEnumerator() instead")]
+        public IEnumerator GetObjects()
+        {
+            return GetEnumerator();
+        }
+
+        /**
+         * return the object at the set position indicated by index.
+         *
+         * @param index the set number (starting at zero) of the object
+         * @return the object at the set position indicated by index.
+         */
+        public virtual Asn1Encodable this[int index]
+        {
+            get { return (Asn1Encodable) _set[index]; }
+        }
+
+        [Obsolete("Use 'object[index]' syntax instead")]
+        public Asn1Encodable GetObjectAt(
+            int index)
+        {
+             return this[index];
+        }
+
+        [Obsolete("Use 'Count' property instead")]
+        public int Size
+        {
+            get { return Count; }
+        }
+
+        public virtual int Count
+        {
+            get { return _set.Count; }
+        }
+
+        public virtual Asn1Encodable[] ToArray()
+        {
+            Asn1Encodable[] values = new Asn1Encodable[this.Count];
+            for (int i = 0; i < this.Count; ++i)
+            {
+                values[i] = this[i];
+            }
+            return values;
+        }
+
+        private class Asn1SetParserImpl
+            : Asn1SetParser
+        {
+            private readonly Asn1Set outer;
+            private readonly int max;
+            private int index;
+
+            public Asn1SetParserImpl(
+                Asn1Set outer)
+            {
+                this.outer = outer;
+                this.max = outer.Count;
+            }
+
+            public IAsn1Convertible ReadObject()
+            {
+                if (index == max)
+                    return null;
+
+                Asn1Encodable obj = outer[index++];
+                if (obj is Asn1Sequence)
+                    return ((Asn1Sequence)obj).Parser;
+
+                if (obj is Asn1Set)
+                    return ((Asn1Set)obj).Parser;
+
+                // NB: Asn1OctetString implements Asn1OctetStringParser directly
+//				if (obj is Asn1OctetString)
+//					return ((Asn1OctetString)obj).Parser;
+
+                return obj;
+            }
+
+            public virtual Asn1Object ToAsn1Object()
+            {
+                return outer;
+            }
+        }
+
+        public Asn1SetParser Parser
+        {
+            get { return new Asn1SetParserImpl(this); }
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            int hc = Count;
+
+            foreach (object o in this)
+            {
+                hc *= 17;
+                if (o == null)
+                {
+                    hc ^= DerNull.Instance.GetHashCode();
+                }
+                else
+                {
+                    hc ^= o.GetHashCode();
+                }
+            }
+
+            return hc;
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            Asn1Set other = asn1Object as Asn1Set;
+
+            if (other == null)
+                return false;
+
+            if (Count != other.Count)
+            {
+                return false;
+            }
+
+            IEnumerator s1 = GetEnumerator();
+            IEnumerator s2 = other.GetEnumerator();
+
+            while (s1.MoveNext() && s2.MoveNext())
+            {
+                Asn1Object o1 = GetCurrent(s1).ToAsn1Object();
+                Asn1Object o2 = GetCurrent(s2).ToAsn1Object();
+
+                if (!o1.Equals(o2))
+                    return false;
+            }
+
+            return true;
+        }
+
+        private Asn1Encodable GetCurrent(IEnumerator e)
+        {
+            Asn1Encodable encObj = (Asn1Encodable)e.Current;
+
+            // unfortunately null was allowed as a substitute for DER null
+            if (encObj == null)
+                return DerNull.Instance;
+
+            return encObj;
+        }
+
+        /**
+         * return true if a <= b (arrays are assumed padded with zeros).
+         */
+        private bool LessThanOrEqual(
+             byte[] a,
+             byte[] b)
+        {
+            int len = System.Math.Min(a.Length, b.Length);
+            for (int i = 0; i != len; ++i)
+            {
+                if (a[i] != b[i])
+                {
+                    return a[i] < b[i];
+                }
+            }
+            return len == a.Length;
+        }
+
+        protected internal void Sort()
+        {
+            if (_set.Count > 1)
+            {
+                bool swapped = true;
+                int lastSwap = _set.Count - 1;
+
+                while (swapped)
+                {
+                    int index = 0;
+                    int swapIndex = 0;
+                    byte[] a = ((Asn1Encodable) _set[0]).GetEncoded();
+
+                    swapped = false;
+
+                    while (index != lastSwap)
+                    {
+                        byte[] b = ((Asn1Encodable) _set[index + 1]).GetEncoded();
+
+                        if (LessThanOrEqual(a, b))
+                        {
+                            a = b;
+                        }
+                        else
+                        {
+                            object o = _set[index];
+                            _set[index] = _set[index + 1];
+                            _set[index + 1] = o;
+
+                            swapped = true;
+                            swapIndex = index;
+                        }
+
+                        index++;
+                    }
+
+                    lastSwap = swapIndex;
+                }
+            }
+        }
+
+        protected internal void AddObject(
+            Asn1Encodable obj)
+        {
+            _set.Add(obj);
+        }
+
+        public override string ToString()
+        {
+            return CollectionUtilities.ToString(_set);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1TaggedObject.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1TaggedObject.cs
new file mode 100644
index 0000000..2e48073
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1TaggedObject.cs
@@ -0,0 +1,178 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * ASN.1 TaggedObject - in ASN.1 notation this is any object preceded by
+     * a [n] where n is some number - these are assumed to follow the construction
+     * rules (as with sequences).
+     */
+    public abstract class Asn1TaggedObject
+		: Asn1Object, Asn1TaggedObjectParser
+    {
+        internal int            tagNo;
+//        internal bool           empty;
+        internal bool           explicitly = true;
+        internal Asn1Encodable  obj;
+
+		static public Asn1TaggedObject GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            if (explicitly)
+            {
+                return (Asn1TaggedObject) obj.GetObject();
+            }
+
+            throw new ArgumentException("implicitly tagged tagged object");
+        }
+
+		static public Asn1TaggedObject GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is Asn1TaggedObject)
+			{
+				return (Asn1TaggedObject) obj;
+			}
+
+			throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		/**
+         * @param tagNo the tag number for this object.
+         * @param obj the tagged object.
+         */
+        protected Asn1TaggedObject(
+            int             tagNo,
+            Asn1Encodable   obj)
+        {
+            this.explicitly = true;
+            this.tagNo = tagNo;
+            this.obj = obj;
+        }
+
+		/**
+         * @param explicitly true if the object is explicitly tagged.
+         * @param tagNo the tag number for this object.
+         * @param obj the tagged object.
+         */
+        protected Asn1TaggedObject(
+            bool            explicitly,
+            int             tagNo,
+            Asn1Encodable   obj)
+        {
+			// IAsn1Choice marker interface 'insists' on explicit tagging
+            this.explicitly = explicitly || (obj is IAsn1Choice);
+            this.tagNo = tagNo;
+            this.obj = obj;
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+        {
+			Asn1TaggedObject other = asn1Object as Asn1TaggedObject;
+
+			if (other == null)
+				return false;
+
+			return this.tagNo == other.tagNo
+//				&& this.empty == other.empty
+				&& this.explicitly == other.explicitly   // TODO Should this be part of equality?
+				&& Platform.Equals(GetObject(), other.GetObject());
+		}
+
+		protected override int Asn1GetHashCode()
+		{
+            int code = tagNo.GetHashCode();
+
+			// TODO: actually this is wrong - the problem is that a re-encoded
+			// object may end up with a different hashCode due to implicit
+			// tagging. As implicit tagging is ambiguous if a sequence is involved
+			// it seems the only correct method for both equals and hashCode is to
+			// compare the encodings...
+//			code ^= explicitly.GetHashCode();
+
+			if (obj != null)
+            {
+                code ^= obj.GetHashCode();
+            }
+
+			return code;
+        }
+
+		public int TagNo
+        {
+			get { return tagNo; }
+        }
+
+		/**
+         * return whether or not the object may be explicitly tagged.
+         * <p>
+         * Note: if the object has been read from an input stream, the only
+         * time you can be sure if isExplicit is returning the true state of
+         * affairs is if it returns false. An implicitly tagged object may appear
+         * to be explicitly tagged, so you need to understand the context under
+         * which the reading was done as well, see GetObject below.</p>
+         */
+        public bool IsExplicit()
+        {
+            return explicitly;
+        }
+
+        public bool IsEmpty()
+        {
+            return false; //empty;
+        }
+
+		/**
+         * return whatever was following the tag.
+         * <p>
+         * Note: tagged objects are generally context dependent if you're
+         * trying to extract a tagged object you should be going via the
+         * appropriate GetInstance method.</p>
+         */
+        public Asn1Object GetObject()
+        {
+            if (obj != null)
+            {
+                return obj.ToAsn1Object();
+            }
+
+			return null;
+        }
+
+		/**
+		* Return the object held in this tagged object as a parser assuming it has
+		* the type of the passed in tag. If the object doesn't have a parser
+		* associated with it, the base object is returned.
+		*/
+		public IAsn1Convertible GetObjectParser(
+			int		tag,
+			bool	isExplicit)
+		{
+			switch (tag)
+			{
+				case Asn1Tags.Set:
+					return Asn1Set.GetInstance(this, isExplicit).Parser;
+				case Asn1Tags.Sequence:
+					return Asn1Sequence.GetInstance(this, isExplicit).Parser;
+				case Asn1Tags.OctetString:
+					return Asn1OctetString.GetInstance(this, isExplicit).Parser;
+			}
+
+			if (isExplicit)
+			{
+				return GetObject();
+			}
+
+			throw Platform.CreateNotImplementedException("implicit tagging for tag: " + tag);
+		}
+
+		public override string ToString()
+		{
+			return "[" + tagNo + "]" + obj;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/Asn1Tags.cs b/BouncyCastle.AxCrypt/src/asn1/Asn1Tags.cs
new file mode 100644
index 0000000..32ac6bc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/Asn1Tags.cs
@@ -0,0 +1,36 @@
+namespace Org.BouncyCastle.Asn1
+{
+    public class Asn1Tags
+    {
+        public const int Boolean = 0x01;
+        public const int Integer = 0x02;
+        public const int BitString = 0x03;
+        public const int OctetString = 0x04;
+        public const int Null = 0x05;
+        public const int ObjectIdentifier = 0x06;
+        public const int External = 0x08;
+        public const int Enumerated = 0x0a;
+        public const int Sequence = 0x10;
+        public const int SequenceOf = 0x10; // for completeness
+        public const int Set = 0x11;
+        public const int SetOf = 0x11; // for completeness
+
+        public const int NumericString = 0x12;
+        public const int PrintableString = 0x13;
+        public const int T61String = 0x14;
+        public const int VideotexString = 0x15;
+        public const int IA5String = 0x16;
+        public const int UtcTime = 0x17;
+        public const int GeneralizedTime = 0x18;
+        public const int GraphicString = 0x19;
+        public const int VisibleString = 0x1a;
+        public const int GeneralString = 0x1b;
+        public const int UniversalString = 0x1c;
+        public const int BmpString = 0x1e;
+        public const int Utf8String = 0x0c;
+
+        public const int Constructed = 0x20;
+        public const int Application = 0x40;
+        public const int Tagged = 0x80;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/BERGenerator.cs
new file mode 100644
index 0000000..271572c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERGenerator.cs
@@ -0,0 +1,102 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class BerGenerator
+        : Asn1Generator
+    {
+        private bool      _tagged = false;
+        private bool      _isExplicit;
+        private int          _tagNo;
+
+        protected BerGenerator(
+            Stream outStream)
+            : base(outStream)
+        {
+        }
+
+        public BerGenerator(
+            Stream outStream,
+            int tagNo,
+            bool isExplicit)
+            : base(outStream)
+        {
+            _tagged = true;
+            _isExplicit = isExplicit;
+            _tagNo = tagNo;
+        }
+
+		public override void AddObject(
+			Asn1Encodable obj)
+		{
+			new BerOutputStream(Out).WriteObject(obj);
+		}
+
+		public override Stream GetRawOutputStream()
+        {
+            return Out;
+        }
+
+		public override void Close()
+		{
+			WriteBerEnd();
+		}
+
+        private void WriteHdr(
+            int tag)
+        {
+            Out.WriteByte((byte) tag);
+            Out.WriteByte(0x80);
+        }
+
+        protected void WriteBerHeader(
+            int tag)
+        {
+            if (_tagged)
+            {
+                int tagNum = _tagNo | Asn1Tags.Tagged;
+
+                if (_isExplicit)
+                {
+                    WriteHdr(tagNum | Asn1Tags.Constructed);
+                    WriteHdr(tag);
+                }
+                else
+                {
+                    if ((tag & Asn1Tags.Constructed) != 0)
+                    {
+                        WriteHdr(tagNum | Asn1Tags.Constructed);
+                    }
+                    else
+                    {
+                        WriteHdr(tagNum);
+                    }
+                }
+            }
+            else
+            {
+                WriteHdr(tag);
+            }
+        }
+
+		protected void WriteBerBody(
+            Stream contentStream)
+        {
+			Streams.PipeAll(contentStream, Out);
+        }
+
+		protected void WriteBerEnd()
+        {
+            Out.WriteByte(0x00);
+            Out.WriteByte(0x00);
+
+            if (_tagged && _isExplicit)  // write extra end for tag header
+            {
+                Out.WriteByte(0x00);
+                Out.WriteByte(0x00);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BEROctetStringGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/BEROctetStringGenerator.cs
new file mode 100644
index 0000000..6d7d1b6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BEROctetStringGenerator.cs
@@ -0,0 +1,120 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerOctetStringGenerator
+		: BerGenerator
+	{
+		public BerOctetStringGenerator(Stream outStream)
+			: base(outStream)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+		}
+
+		public BerOctetStringGenerator(
+			Stream	outStream,
+			int		tagNo,
+			bool	isExplicit)
+			: base(outStream, tagNo, isExplicit)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.OctetString);
+		}
+
+		public Stream GetOctetOutputStream()
+		{
+			return GetOctetOutputStream(new byte[1000]); // limit for CER encoding.
+		}
+
+		public Stream GetOctetOutputStream(
+			int bufSize)
+		{
+			return bufSize < 1
+				?	GetOctetOutputStream()
+				:	GetOctetOutputStream(new byte[bufSize]);
+		}
+
+		public Stream GetOctetOutputStream(
+			byte[] buf)
+		{
+			return new BufferedBerOctetStream(this, buf);
+		}
+
+		private class BufferedBerOctetStream
+			: BaseOutputStream
+		{
+			private byte[] _buf;
+			private int    _off;
+			private readonly BerOctetStringGenerator _gen;
+			private readonly DerOutputStream _derOut;
+
+			internal BufferedBerOctetStream(
+				BerOctetStringGenerator	gen,
+				byte[]					buf)
+			{
+				_gen = gen;
+				_buf = buf;
+				_off = 0;
+				_derOut = new DerOutputStream(_gen.Out);
+			}
+
+			public override void WriteByte(
+				byte b)
+			{
+				_buf[_off++] = b;
+
+				if (_off == _buf.Length)
+				{
+					DerOctetString.Encode(_derOut, _buf, 0, _off);
+					_off = 0;
+				}
+			}
+
+			public override void Write(
+				byte[] buf,
+				int    offset,
+				int    len)
+			{
+				while (len > 0)
+				{
+					int numToCopy = System.Math.Min(len, _buf.Length - _off);
+
+					if (numToCopy == _buf.Length)
+					{
+						DerOctetString.Encode(_derOut, buf, offset, numToCopy);
+					}
+					else
+					{
+						Array.Copy(buf, offset, _buf, _off, numToCopy);
+
+						_off += numToCopy;
+						if (_off < _buf.Length)
+							break;
+
+						DerOctetString.Encode(_derOut, _buf, 0, _off);
+						_off = 0;
+					}
+
+					offset += numToCopy;
+					len -= numToCopy;
+				}
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+                    if (_off != 0)
+                    {
+                        DerOctetString.Encode(_derOut, _buf, 0, _off);
+                    }
+
+                    _gen.WriteBerEnd();
+		        }
+		        base.Dispose(disposing);
+		    }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BEROctetStringParser.cs b/BouncyCastle.AxCrypt/src/asn1/BEROctetStringParser.cs
new file mode 100644
index 0000000..3bfd2a9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BEROctetStringParser.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerOctetStringParser
+		: Asn1OctetStringParser
+	{
+		private readonly Asn1StreamParser _parser;
+
+		internal BerOctetStringParser(
+			Asn1StreamParser parser)
+		{
+			_parser = parser;
+		}
+
+		public Stream GetOctetStream()
+		{
+			return new ConstructedOctetStream(_parser);
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			try
+			{
+				return new BerOctetString(Streams.ReadAll(GetOctetStream()));
+			}
+			catch (IOException e)
+			{
+				throw new Asn1ParsingException("IOException converting stream to byte array: " + e.Message, e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERSequenceGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/BERSequenceGenerator.cs
new file mode 100644
index 0000000..5ea2c9b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERSequenceGenerator.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerSequenceGenerator
+		: BerGenerator
+	{
+		public BerSequenceGenerator(
+			Stream outStream)
+			: base(outStream)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
+		}
+
+		public BerSequenceGenerator(
+			Stream	outStream,
+			int		tagNo,
+			bool	isExplicit)
+			: base(outStream, tagNo, isExplicit)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Sequence);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERSequenceParser.cs b/BouncyCastle.AxCrypt/src/asn1/BERSequenceParser.cs
new file mode 100644
index 0000000..8474b8d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERSequenceParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerSequenceParser
+		: Asn1SequenceParser
+	{
+		private readonly Asn1StreamParser _parser;
+
+		internal BerSequenceParser(
+			Asn1StreamParser parser)
+		{
+			this._parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return _parser.ReadObject();
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			return new BerSequence(_parser.ReadVector());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERSetGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/BERSetGenerator.cs
new file mode 100644
index 0000000..72b1f90
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERSetGenerator.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerSetGenerator
+		: BerGenerator
+	{
+		public BerSetGenerator(
+			Stream outStream)
+			: base(outStream)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
+		}
+
+		public BerSetGenerator(
+			Stream	outStream,
+			int		tagNo,
+			bool	isExplicit)
+			: base(outStream, tagNo, isExplicit)
+		{
+			WriteBerHeader(Asn1Tags.Constructed | Asn1Tags.Set);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERSetParser.cs b/BouncyCastle.AxCrypt/src/asn1/BERSetParser.cs
new file mode 100644
index 0000000..aa9ccbc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERSetParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerSetParser
+		: Asn1SetParser
+	{
+		private readonly Asn1StreamParser _parser;
+
+		internal BerSetParser(
+			Asn1StreamParser parser)
+		{
+			this._parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return _parser.ReadObject();
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			return new BerSet(_parser.ReadVector(), false);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BERTaggedObjectParser.cs b/BouncyCastle.AxCrypt/src/asn1/BERTaggedObjectParser.cs
new file mode 100644
index 0000000..354437a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BERTaggedObjectParser.cs
@@ -0,0 +1,71 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerTaggedObjectParser
+		: Asn1TaggedObjectParser
+	{
+		private bool				_constructed;
+		private int					_tagNumber;
+		private Asn1StreamParser	_parser;
+
+		[Obsolete]
+		internal BerTaggedObjectParser(
+			int		baseTag,
+			int		tagNumber,
+			Stream	contentStream)
+			: this((baseTag & Asn1Tags.Constructed) != 0, tagNumber, new Asn1StreamParser(contentStream))
+		{
+		}
+
+		internal BerTaggedObjectParser(
+			bool				constructed,
+			int					tagNumber,
+			Asn1StreamParser	parser)
+		{
+			_constructed = constructed;
+			_tagNumber = tagNumber;
+			_parser = parser;
+		}
+
+		public bool IsConstructed
+		{
+			get { return _constructed; }
+		}
+
+		public int TagNo
+		{
+			get { return _tagNumber; }
+		}
+
+		public IAsn1Convertible GetObjectParser(
+			int		tag,
+			bool	isExplicit)
+		{
+			if (isExplicit)
+			{
+				if (!_constructed)
+					throw new IOException("Explicit tags must be constructed (see X.690 8.14.2)");
+
+				return _parser.ReadObject();
+			}
+
+			return _parser.ReadImplicit(_constructed, tag);
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			try
+			{
+				return _parser.ReadTaggedObject(_constructed, _tagNumber);
+			}
+			catch (IOException e)
+			{
+				throw new Asn1ParsingException(e.Message);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecific.cs b/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecific.cs
new file mode 100644
index 0000000..65fbecb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecific.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerApplicationSpecific
+		: DerApplicationSpecific
+	{
+		public BerApplicationSpecific(
+			int					tagNo,
+			Asn1EncodableVector	vec)
+			: base(tagNo, vec)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecificParser.cs b/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecificParser.cs
new file mode 100644
index 0000000..7d2c4b3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerApplicationSpecificParser.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerApplicationSpecificParser
+		: IAsn1ApplicationSpecificParser
+	{
+		private readonly int tag;
+		private readonly Asn1StreamParser parser;
+
+		internal BerApplicationSpecificParser(
+			int					tag,
+			Asn1StreamParser	parser)
+		{
+			this.tag = tag;
+			this.parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return parser.ReadObject();
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			return new BerApplicationSpecific(tag, parser.ReadVector());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerNull.cs b/BouncyCastle.AxCrypt/src/asn1/BerNull.cs
new file mode 100644
index 0000000..0751bba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerNull.cs
@@ -0,0 +1,35 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * A BER Null object.
+	 */
+	public class BerNull
+		: DerNull
+	{
+		public static new readonly BerNull Instance = new BerNull(0);
+
+		[Obsolete("Use static Instance object")]
+		public BerNull()
+		{
+		}
+
+		private BerNull(int dummy) : base(dummy)
+		{
+		}
+
+		internal override void Encode(
+			DerOutputStream  derOut)
+		{
+			if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+			{
+				derOut.WriteByte(Asn1Tags.Null);
+			}
+			else
+			{
+				base.Encode(derOut);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerOctetString.cs b/BouncyCastle.AxCrypt/src/asn1/BerOctetString.cs
new file mode 100644
index 0000000..a7c8ad3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerOctetString.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class BerOctetString
+        : DerOctetString, IEnumerable
+    {
+		public static BerOctetString FromSequence(Asn1Sequence seq)
+		{
+			IList v = Platform.CreateArrayList();
+
+			foreach (Asn1Encodable obj in seq)
+			{
+				v.Add(obj);
+			}
+
+			return new BerOctetString(v);
+		}
+
+		private const int MaxLength = 1000;
+
+		/**
+         * convert a vector of octet strings into a single byte string
+         */
+        private static byte[] ToBytes(
+            IEnumerable octs)
+        {
+            MemoryStream bOut = new MemoryStream();
+			foreach (DerOctetString o in octs)
+			{
+                byte[] octets = o.GetOctets();
+                bOut.Write(octets, 0, octets.Length);
+            }
+			return bOut.ToArray();
+        }
+
+		private readonly IEnumerable octs;
+
+		/// <param name="str">The octets making up the octet string.</param>
+		public BerOctetString(
+			byte[] str)
+			: base(str)
+		{
+		}
+
+		public BerOctetString(
+			IEnumerable octets)
+			: base(ToBytes(octets))
+        {
+            this.octs = octets;
+        }
+
+        public BerOctetString(
+			Asn1Object obj)
+			: base(obj)
+        {
+        }
+
+        public BerOctetString(
+			Asn1Encodable obj)
+			: base(obj.ToAsn1Object())
+        {
+        }
+
+        public override byte[] GetOctets()
+        {
+            return str;
+        }
+
+        /**
+         * return the DER octets that make up this string.
+         */
+		public IEnumerator GetEnumerator()
+		{
+			if (octs == null)
+			{
+				return GenerateOcts().GetEnumerator();
+			}
+
+			return octs.GetEnumerator();
+		}
+
+		[Obsolete("Use GetEnumerator() instead")]
+        public IEnumerator GetObjects()
+        {
+			return GetEnumerator();
+		}
+
+		private IList GenerateOcts()
+        {
+            IList vec = Platform.CreateArrayList();
+			for (int i = 0; i < str.Length; i += MaxLength)
+			{
+				int end = System.Math.Min(str.Length, i + MaxLength);
+
+				byte[] nStr = new byte[end - i];
+
+				Array.Copy(str, i, nStr, 0, nStr.Length);
+
+				vec.Add(new DerOctetString(nStr));
+			}
+			return vec;
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+            {
+                derOut.WriteByte(Asn1Tags.Constructed | Asn1Tags.OctetString);
+
+                derOut.WriteByte(0x80);
+
+                //
+                // write out the octet array
+                //
+                foreach (DerOctetString oct in this)
+                {
+                    derOut.WriteObject(oct);
+                }
+
+				derOut.WriteByte(0x00);
+                derOut.WriteByte(0x00);
+            }
+            else
+            {
+                base.Encode(derOut);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerOutputStream.cs b/BouncyCastle.AxCrypt/src/asn1/BerOutputStream.cs
new file mode 100644
index 0000000..b3ece10
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerOutputStream.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	// TODO Make Obsolete in favour of Asn1OutputStream?
+    public class BerOutputStream
+        : DerOutputStream
+    {
+        public BerOutputStream(Stream os) : base(os)
+        {
+        }
+
+		[Obsolete("Use version taking an Asn1Encodable arg instead")]
+        public override void WriteObject(
+            object    obj)
+        {
+            if (obj == null)
+            {
+                WriteNull();
+            }
+            else if (obj is Asn1Object)
+            {
+                ((Asn1Object)obj).Encode(this);
+            }
+            else if (obj is Asn1Encodable)
+            {
+                ((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+            }
+            else
+            {
+                throw new IOException("object not BerEncodable");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerSequence.cs b/BouncyCastle.AxCrypt/src/asn1/BerSequence.cs
new file mode 100644
index 0000000..70b43fc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerSequence.cs
@@ -0,0 +1,69 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public class BerSequence
+		: DerSequence
+	{
+		public static new readonly BerSequence Empty = new BerSequence();
+
+		public static new BerSequence FromVector(
+			Asn1EncodableVector v)
+		{
+			return v.Count < 1 ? Empty : new BerSequence(v);
+		}
+
+		/**
+		 * create an empty sequence
+		 */
+		public BerSequence()
+		{
+		}
+
+		/**
+		 * create a sequence containing one object
+		 */
+		public BerSequence(
+			Asn1Encodable obj)
+			: base(obj)
+		{
+		}
+
+		public BerSequence(
+			params Asn1Encodable[] v)
+			: base(v)
+		{
+		}
+
+		/**
+		 * create a sequence containing a vector of objects.
+		 */
+		public BerSequence(
+			Asn1EncodableVector v)
+			: base(v)
+		{
+		}
+
+		/*
+		 */
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+			{
+				derOut.WriteByte(Asn1Tags.Sequence | Asn1Tags.Constructed);
+				derOut.WriteByte(0x80);
+
+				foreach (Asn1Encodable o in this)
+				{
+					derOut.WriteObject(o);
+				}
+
+				derOut.WriteByte(0x00);
+				derOut.WriteByte(0x00);
+			}
+			else
+			{
+				base.Encode(derOut);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerSet.cs b/BouncyCastle.AxCrypt/src/asn1/BerSet.cs
new file mode 100644
index 0000000..a181e17
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerSet.cs
@@ -0,0 +1,70 @@
+namespace Org.BouncyCastle.Asn1
+{
+    public class BerSet
+        : DerSet
+    {
+		public static new readonly BerSet Empty = new BerSet();
+
+		public static new BerSet FromVector(
+			Asn1EncodableVector v)
+		{
+			return v.Count < 1 ? Empty : new BerSet(v);
+		}
+
+		internal static new BerSet FromVector(
+			Asn1EncodableVector v,
+			bool				needsSorting)
+		{
+			return v.Count < 1 ? Empty : new BerSet(v, needsSorting);
+		}
+
+		/**
+         * create an empty sequence
+         */
+        public BerSet()
+        {
+        }
+
+        /**
+         * create a set containing one object
+         */
+        public BerSet(Asn1Encodable obj) : base(obj)
+        {
+        }
+
+        /**
+         * create a set containing a vector of objects.
+         */
+        public BerSet(Asn1EncodableVector v) : base(v, false)
+        {
+        }
+
+        internal BerSet(Asn1EncodableVector v, bool needsSorting) : base(v, needsSorting)
+        {
+        }
+
+        /*
+         */
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+            {
+                derOut.WriteByte(Asn1Tags.Set | Asn1Tags.Constructed);
+                derOut.WriteByte(0x80);
+
+                foreach (Asn1Encodable o in this)
+				{
+                    derOut.WriteObject(o);
+                }
+
+                derOut.WriteByte(0x00);
+                derOut.WriteByte(0x00);
+            }
+            else
+            {
+                base.Encode(derOut);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/BerTaggedObject.cs b/BouncyCastle.AxCrypt/src/asn1/BerTaggedObject.cs
new file mode 100644
index 0000000..228b136
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/BerTaggedObject.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * BER TaggedObject - in ASN.1 notation this is any object preceded by
+	 * a [n] where n is some number - these are assumed to follow the construction
+	 * rules (as with sequences).
+	 */
+	public class BerTaggedObject
+		: DerTaggedObject
+	{
+		/**
+		 * @param tagNo the tag number for this object.
+		 * @param obj the tagged object.
+		 */
+		public BerTaggedObject(
+			int				tagNo,
+			Asn1Encodable	obj)
+			: base(tagNo, obj)
+		{
+		}
+
+		/**
+		 * @param explicitly true if an explicitly tagged object.
+		 * @param tagNo the tag number for this object.
+		 * @param obj the tagged object.
+		 */
+		public BerTaggedObject(
+			bool			explicitly,
+			int				tagNo,
+			Asn1Encodable	obj)
+			: base(explicitly, tagNo, obj)
+		{
+		}
+
+		/**
+		 * create an implicitly tagged object that contains a zero
+		 * length sequence.
+		 */
+		public BerTaggedObject(
+			int tagNo)
+			: base(false, tagNo, BerSequence.Empty)
+		{
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			if (derOut is Asn1OutputStream || derOut is BerOutputStream)
+			{
+				derOut.WriteTag((byte)(Asn1Tags.Constructed | Asn1Tags.Tagged), tagNo);
+				derOut.WriteByte(0x80);
+
+				if (!IsEmpty())
+				{
+					if (!explicitly)
+					{
+						IEnumerable eObj;
+						if (obj is Asn1OctetString)
+						{
+							if (obj is BerOctetString)
+							{
+								eObj = (BerOctetString) obj;
+							}
+							else
+							{
+								Asn1OctetString octs = (Asn1OctetString)obj;
+								eObj = new BerOctetString(octs.GetOctets());
+							}
+						}
+						else if (obj is Asn1Sequence)
+						{
+							eObj = (Asn1Sequence) obj;
+						}
+						else if (obj is Asn1Set)
+						{
+							eObj = (Asn1Set) obj;
+						}
+						else
+						{
+							throw Platform.CreateNotImplementedException(obj.GetType().Name);
+						}
+
+						foreach (Asn1Encodable o in eObj)
+						{
+							derOut.WriteObject(o);
+						}
+					}
+					else
+					{
+						derOut.WriteObject(obj);
+					}
+				}
+
+				derOut.WriteByte(0x00);
+				derOut.WriteByte(0x00);
+			}
+			else
+			{
+				base.Encode(derOut);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ConstructedOctetStream.cs b/BouncyCastle.AxCrypt/src/asn1/ConstructedOctetStream.cs
new file mode 100644
index 0000000..1773b22
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ConstructedOctetStream.cs
@@ -0,0 +1,102 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	internal class ConstructedOctetStream
+		: BaseInputStream
+	{
+		private readonly Asn1StreamParser _parser;
+
+		private bool _first = true;
+		private Stream _currentStream;
+
+		internal ConstructedOctetStream(
+			Asn1StreamParser parser)
+		{
+			_parser = parser;
+		}
+
+		public override int Read(byte[] buffer, int offset, int count)
+		{
+			if (_currentStream == null)
+			{
+				if (!_first)
+					return 0;
+
+				Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
+
+				if (s == null)
+					return 0;
+
+				_first = false;
+				_currentStream = s.GetOctetStream();
+			}
+
+			int totalRead = 0;
+
+			for (;;)
+			{
+				int numRead = _currentStream.Read(buffer, offset + totalRead, count - totalRead);
+
+				if (numRead > 0)
+				{
+					totalRead += numRead;
+
+					if (totalRead == count)
+						return totalRead;
+				}
+				else
+				{
+					Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
+
+					if (aos == null)
+					{
+						_currentStream = null;
+						return totalRead;
+					}
+
+					_currentStream = aos.GetOctetStream();
+				}
+			}
+		}
+
+		public override int ReadByte()
+		{
+			if (_currentStream == null)
+			{
+				if (!_first)
+					return 0;
+
+				Asn1OctetStringParser s = (Asn1OctetStringParser)_parser.ReadObject();
+
+				if (s == null)
+					return 0;
+
+				_first = false;
+				_currentStream = s.GetOctetStream();
+			}
+
+			for (;;)
+			{
+				int b = _currentStream.ReadByte();
+
+				if (b >= 0)
+				{
+					return b;
+				}
+
+				Asn1OctetStringParser aos = (Asn1OctetStringParser)_parser.ReadObject();
+
+				if (aos == null)
+				{
+					_currentStream = null;
+					return -1;
+				}
+
+				_currentStream = aos.GetOctetStream();
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERExternal.cs b/BouncyCastle.AxCrypt/src/asn1/DERExternal.cs
new file mode 100644
index 0000000..a342d65
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERExternal.cs
@@ -0,0 +1,207 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	* Class representing the DER-type External
+	*/
+	public class DerExternal
+		: Asn1Object
+	{
+		private DerObjectIdentifier	directReference;
+		private DerInteger			indirectReference;
+		private Asn1Object			dataValueDescriptor;
+		private int					encoding;
+		private Asn1Object			externalContent;
+
+		public DerExternal(
+			Asn1EncodableVector vector)
+		{
+			int offset = 0;
+			Asn1Object enc = GetObjFromVector(vector, offset);
+			if (enc is DerObjectIdentifier)
+			{
+				directReference = (DerObjectIdentifier)enc;
+				offset++;
+				enc = GetObjFromVector(vector, offset);
+			}
+			if (enc is DerInteger)
+			{
+				indirectReference = (DerInteger) enc;
+				offset++;
+				enc = GetObjFromVector(vector, offset);
+			}
+			if (!(enc is DerTaggedObject))
+			{
+				dataValueDescriptor = (Asn1Object) enc;
+				offset++;
+				enc = GetObjFromVector(vector, offset);
+			}
+			if (!(enc is DerTaggedObject))
+			{
+				throw new InvalidOperationException(
+					"No tagged object found in vector. Structure doesn't seem to be of type External");
+			}
+
+			if (vector.Count != offset + 1)
+				throw new ArgumentException("input vector too large", "vector");
+
+			if (!(enc is DerTaggedObject))
+				throw new ArgumentException("No tagged object found in vector. Structure doesn't seem to be of type External", "vector");
+
+			DerTaggedObject obj = (DerTaggedObject)enc;
+
+			// Use property accessor to include check on value
+			Encoding = obj.TagNo;
+
+			if (encoding < 0 || encoding > 2)
+				throw new InvalidOperationException("invalid encoding value");
+
+			externalContent = obj.GetObject();
+		}
+
+		/**
+		* Creates a new instance of DerExternal
+		* See X.690 for more informations about the meaning of these parameters
+		* @param directReference The direct reference or <code>null</code> if not set.
+		* @param indirectReference The indirect reference or <code>null</code> if not set.
+		* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+		* @param externalData The external data in its encoded form.
+		*/
+		public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, DerTaggedObject externalData)
+			: this(directReference, indirectReference, dataValueDescriptor, externalData.TagNo, externalData.ToAsn1Object())
+		{
+		}
+
+		/**
+		* Creates a new instance of DerExternal.
+		* See X.690 for more informations about the meaning of these parameters
+		* @param directReference The direct reference or <code>null</code> if not set.
+		* @param indirectReference The indirect reference or <code>null</code> if not set.
+		* @param dataValueDescriptor The data value descriptor or <code>null</code> if not set.
+		* @param encoding The encoding to be used for the external data
+		* @param externalData The external data
+		*/
+		public DerExternal(DerObjectIdentifier directReference, DerInteger indirectReference, Asn1Object dataValueDescriptor, int encoding, Asn1Object externalData)
+		{
+			DirectReference = directReference;
+			IndirectReference = indirectReference;
+			DataValueDescriptor = dataValueDescriptor;
+			Encoding = encoding;
+			ExternalContent = externalData.ToAsn1Object();
+		}
+
+		internal override void Encode(DerOutputStream derOut)
+		{
+			MemoryStream ms = new MemoryStream();
+			WriteEncodable(ms, directReference);
+			WriteEncodable(ms, indirectReference);
+			WriteEncodable(ms, dataValueDescriptor);
+			WriteEncodable(ms, new DerTaggedObject(Asn1Tags.External, externalContent));
+
+			derOut.WriteEncoded(Asn1Tags.Constructed, Asn1Tags.External, ms.ToArray());
+		}
+
+		protected override int Asn1GetHashCode()
+		{
+			int ret = externalContent.GetHashCode();
+			if (directReference != null)
+			{
+				ret ^= directReference.GetHashCode();
+			}
+			if (indirectReference != null)
+			{
+				ret ^= indirectReference.GetHashCode();
+			}
+			if (dataValueDescriptor != null)
+			{
+				ret ^= dataValueDescriptor.GetHashCode();
+			}
+			return ret;
+		}
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			if (this == asn1Object)
+				return true;
+
+			DerExternal other = asn1Object as DerExternal;
+
+			if (other == null)
+				return false;
+
+			return Platform.Equals(directReference, other.directReference)
+				&& Platform.Equals(indirectReference, other.indirectReference)
+				&& Platform.Equals(dataValueDescriptor, other.dataValueDescriptor)
+				&& externalContent.Equals(other.externalContent);
+		}
+
+		public Asn1Object DataValueDescriptor
+		{
+			get { return dataValueDescriptor; }
+			set { this.dataValueDescriptor = value; }
+		}
+
+		public DerObjectIdentifier DirectReference
+		{
+			get { return directReference; }
+			set { this.directReference = value; }
+		}
+
+		/**
+		* The encoding of the content. Valid values are
+		* <ul>
+		* <li><code>0</code> single-ASN1-type</li>
+		* <li><code>1</code> OCTET STRING</li>
+		* <li><code>2</code> BIT STRING</li>
+		* </ul>
+		*/
+		public int Encoding
+		{
+			get
+			{
+				return encoding;
+			}
+			set
+			{
+				if (encoding < 0 || encoding > 2)
+					throw new InvalidOperationException("invalid encoding value: " + encoding);
+
+				this.encoding = value;
+			}
+		}
+
+		public Asn1Object ExternalContent
+		{
+			get { return externalContent; }
+			set { this.externalContent = value; }
+		}
+
+		public DerInteger IndirectReference
+		{
+			get { return indirectReference; }
+			set { this.indirectReference = value; }
+		}
+
+		private static Asn1Object GetObjFromVector(Asn1EncodableVector v, int index)
+		{
+			if (v.Count <= index)
+				throw new ArgumentException("too few objects in input vector", "v");
+
+			return v[index].ToAsn1Object();
+		}
+
+		private static void WriteEncodable(MemoryStream ms, Asn1Encodable e)
+		{
+			if (e != null)
+			{
+				byte[] bs = e.GetDerEncoded();
+				ms.Write(bs, 0, bs.Length);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERExternalParser.cs b/BouncyCastle.AxCrypt/src/asn1/DERExternalParser.cs
new file mode 100644
index 0000000..70e426f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERExternalParser.cs
@@ -0,0 +1,26 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerExternalParser
+		: Asn1Encodable
+	{
+		private readonly Asn1StreamParser _parser;
+
+		public DerExternalParser(Asn1StreamParser parser)
+		{
+			this._parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return _parser.ReadObject();
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerExternal(_parser.ReadVector());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/DERGenerator.cs
new file mode 100644
index 0000000..aab40fe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERGenerator.cs
@@ -0,0 +1,107 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public abstract class DerGenerator
+        : Asn1Generator
+    {
+        private bool _tagged = false;
+        private bool _isExplicit;
+        private int _tagNo;
+
+		protected DerGenerator(
+            Stream outStream)
+            : base(outStream)
+		{
+        }
+
+        protected DerGenerator(
+            Stream outStream,
+            int tagNo,
+            bool isExplicit)
+            : base(outStream)
+        {
+            _tagged = true;
+            _isExplicit = isExplicit;
+            _tagNo = tagNo;
+        }
+
+		private static void WriteLength(
+            Stream	outStr,
+            int		length)
+        {
+            if (length > 127)
+            {
+                int size = 1;
+                int val = length;
+
+				while ((val >>= 8) != 0)
+                {
+                    size++;
+                }
+
+				outStr.WriteByte((byte)(size | 0x80));
+
+				for (int i = (size - 1) * 8; i >= 0; i -= 8)
+                {
+                    outStr.WriteByte((byte)(length >> i));
+                }
+            }
+            else
+            {
+                outStr.WriteByte((byte)length);
+            }
+        }
+
+		internal static void WriteDerEncoded(
+            Stream	outStream,
+            int		tag,
+            byte[]	bytes)
+        {
+            outStream.WriteByte((byte) tag);
+            WriteLength(outStream, bytes.Length);
+            outStream.Write(bytes, 0, bytes.Length);
+        }
+
+		internal void WriteDerEncoded(
+            int		tag,
+            byte[]	bytes)
+        {
+            if (_tagged)
+            {
+                int tagNum = _tagNo | Asn1Tags.Tagged;
+
+                if (_isExplicit)
+                {
+                    int newTag = _tagNo | Asn1Tags.Constructed | Asn1Tags.Tagged;
+					MemoryStream bOut = new MemoryStream();
+                    WriteDerEncoded(bOut, tag, bytes);
+                    WriteDerEncoded(Out, newTag, bOut.ToArray());
+                }
+                else
+                {
+					if ((tag & Asn1Tags.Constructed) != 0)
+					{
+						tagNum |= Asn1Tags.Constructed;
+					}
+
+					WriteDerEncoded(Out, tagNum, bytes);
+                }
+            }
+            else
+            {
+                WriteDerEncoded(Out, tag, bytes);
+            }
+        }
+
+		internal static void WriteDerEncoded(
+            Stream	outStr,
+            int		tag,
+            Stream	inStr)
+        {
+			WriteDerEncoded(outStr, tag, Streams.ReadAll(inStr));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DEROctetStringParser.cs b/BouncyCastle.AxCrypt/src/asn1/DEROctetStringParser.cs
new file mode 100644
index 0000000..b0d3ad8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DEROctetStringParser.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerOctetStringParser
+		: Asn1OctetStringParser
+	{
+		private readonly DefiniteLengthInputStream stream;
+
+		internal DerOctetStringParser(
+			DefiniteLengthInputStream stream)
+		{
+			this.stream = stream;
+		}
+
+		public Stream GetOctetStream()
+		{
+			return stream;
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			try
+			{
+				return new DerOctetString(stream.ToArray());
+			}
+			catch (IOException e)
+			{
+				throw new InvalidOperationException("IOException converting stream to byte array: " + e.Message, e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERSequenceGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/DERSequenceGenerator.cs
new file mode 100644
index 0000000..4c2bfd0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERSequenceGenerator.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerSequenceGenerator
+		: DerGenerator
+	{
+		private readonly MemoryStream _bOut = new MemoryStream();
+
+		public DerSequenceGenerator(
+			Stream outStream)
+			: base(outStream)
+		{
+		}
+
+		public DerSequenceGenerator(
+			Stream	outStream,
+			int		tagNo,
+			bool	isExplicit)
+			: base(outStream, tagNo, isExplicit)
+		{
+		}
+
+		public override void AddObject(
+			Asn1Encodable obj)
+		{
+			new DerOutputStream(_bOut).WriteObject(obj);
+		}
+
+		public override Stream GetRawOutputStream()
+		{
+			return _bOut;
+		}
+
+		public override void Close()
+		{
+			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Sequence, _bOut.ToArray());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERSequenceParser.cs b/BouncyCastle.AxCrypt/src/asn1/DERSequenceParser.cs
new file mode 100644
index 0000000..69c2b9b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERSequenceParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerSequenceParser
+		: Asn1SequenceParser
+	{
+		private readonly Asn1StreamParser _parser;
+
+		internal DerSequenceParser(
+			Asn1StreamParser parser)
+		{
+			this._parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return _parser.ReadObject();
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(_parser.ReadVector());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERSetGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/DERSetGenerator.cs
new file mode 100644
index 0000000..455ca88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERSetGenerator.cs
@@ -0,0 +1,40 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerSetGenerator
+		: DerGenerator
+	{
+		private readonly MemoryStream _bOut = new MemoryStream();
+
+		public DerSetGenerator(
+			Stream outStream)
+			: base(outStream)
+		{
+		}
+
+		public DerSetGenerator(
+			Stream	outStream,
+			int		tagNo,
+			bool	isExplicit)
+			: base(outStream, tagNo, isExplicit)
+		{
+		}
+
+		public override void AddObject(
+			Asn1Encodable obj)
+		{
+			new DerOutputStream(_bOut).WriteObject(obj);
+		}
+
+		public override Stream GetRawOutputStream()
+		{
+			return _bOut;
+		}
+
+		public override void Close()
+		{
+			WriteDerEncoded(Asn1Tags.Constructed | Asn1Tags.Set, _bOut.ToArray());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DERSetParser.cs b/BouncyCastle.AxCrypt/src/asn1/DERSetParser.cs
new file mode 100644
index 0000000..d67f135
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DERSetParser.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerSetParser
+		: Asn1SetParser
+	{
+		private readonly Asn1StreamParser _parser;
+
+		internal DerSetParser(
+			Asn1StreamParser parser)
+		{
+			this._parser = parser;
+		}
+
+		public IAsn1Convertible ReadObject()
+		{
+			return _parser.ReadObject();
+		}
+
+		public Asn1Object ToAsn1Object()
+		{
+			return new DerSet(_parser.ReadVector(), false);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DefiniteLengthInputStream.cs b/BouncyCastle.AxCrypt/src/asn1/DefiniteLengthInputStream.cs
new file mode 100644
index 0000000..4ae803c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DefiniteLengthInputStream.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    class DefiniteLengthInputStream
+        : LimitedInputStream
+    {
+		private static readonly byte[] EmptyBytes = new byte[0];
+
+		private readonly int _originalLength;
+		private int _remaining;
+
+        internal DefiniteLengthInputStream(
+            Stream	inStream,
+            int		length)
+            : base(inStream, length)
+        {
+			if (length < 0)
+				throw new ArgumentException("negative lengths not allowed", "length");
+
+			this._originalLength = length;
+			this._remaining = length;
+
+			if (length == 0)
+			{
+				SetParentEofDetect(true);
+			}
+        }
+
+		internal int Remaining
+		{
+			get { return _remaining; }
+		}
+
+		public override int ReadByte()
+        {
+			if (_remaining == 0)
+				return -1;
+
+			int b = _in.ReadByte();
+
+			if (b < 0)
+				throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+
+			if (--_remaining == 0)
+			{
+				SetParentEofDetect(true);
+			}
+
+			return b;
+        }
+
+		public override int Read(
+			byte[]	buf,
+			int		off,
+			int		len)
+		{
+			if (_remaining == 0)
+				return 0;
+
+			int toRead = System.Math.Min(len, _remaining);
+			int numRead = _in.Read(buf, off, toRead);
+
+			if (numRead < 1)
+				throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+
+			if ((_remaining -= numRead) == 0)
+			{
+				SetParentEofDetect(true);
+			}
+
+			return numRead;
+		}
+
+        internal void ReadAllIntoByteArray(byte[] buf)
+        {
+            if (_remaining != buf.Length)
+                throw new ArgumentException("buffer length not right for data");
+
+            if ((_remaining -= Streams.ReadFully(_in, buf)) != 0)
+                throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+            SetParentEofDetect(true);
+        }
+
+        internal byte[] ToArray()
+		{
+			if (_remaining == 0)
+				return EmptyBytes;
+
+			byte[] bytes = new byte[_remaining];
+			if ((_remaining -= Streams.ReadFully(_in, bytes)) != 0)
+				throw new EndOfStreamException("DEF length " + _originalLength + " object truncated by " + _remaining);
+			SetParentEofDetect(true);
+			return bytes;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerApplicationSpecific.cs b/BouncyCastle.AxCrypt/src/asn1/DerApplicationSpecific.cs
new file mode 100644
index 0000000..394c743
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerApplicationSpecific.cs
@@ -0,0 +1,237 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Base class for an application specific object
+     */
+    public class DerApplicationSpecific
+        : Asn1Object
+    {
+		private readonly bool	isConstructed;
+        private readonly int	tag;
+        private readonly byte[]	octets;
+
+		internal DerApplicationSpecific(
+			bool	isConstructed,
+			int		tag,
+			byte[]	octets)
+		{
+			this.isConstructed = isConstructed;
+			this.tag = tag;
+			this.octets = octets;
+		}
+
+		public DerApplicationSpecific(
+            int		tag,
+            byte[]	octets)
+			: this(false, tag, octets)
+        {
+        }
+
+		public DerApplicationSpecific(
+			int				tag, 
+			Asn1Encodable	obj) 
+			: this(true, tag, obj)
+		{
+		}
+
+		public DerApplicationSpecific(
+			bool			isExplicit,
+			int				tag,
+			Asn1Encodable	obj)
+		{
+            Asn1Object asn1Obj = obj.ToAsn1Object();
+
+            byte[] data = asn1Obj.GetDerEncoded();
+
+			this.isConstructed = isExplicit || asn1Obj is Asn1Set || asn1Obj is Asn1Sequence;
+			this.tag = tag;
+
+			if (isExplicit)
+			{
+				this.octets = data;
+			}
+			else
+			{
+				int lenBytes = GetLengthOfHeader(data);
+				byte[] tmp = new byte[data.Length - lenBytes];
+				Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
+				this.octets = tmp;
+			}
+		}
+
+		public DerApplicationSpecific(
+			int					tagNo,
+			Asn1EncodableVector	vec)
+		{
+			this.tag = tagNo;
+			this.isConstructed = true;
+			MemoryStream bOut = new MemoryStream();
+
+			for (int i = 0; i != vec.Count; i++)
+			{
+				try
+				{
+					byte[] bs = vec[i].GetDerEncoded();
+					bOut.Write(bs, 0, bs.Length);
+                }
+				catch (IOException e)
+				{
+					throw new InvalidOperationException("malformed object", e);
+				}
+			}
+			this.octets = bOut.ToArray();
+		}
+
+		private int GetLengthOfHeader(
+			byte[] data)
+		{
+            int length = data[1]; // TODO: assumes 1 byte tag
+
+            if (length == 0x80)
+            {
+                return 2;      // indefinite-length encoding
+            }
+
+            if (length > 127)
+            {
+                int size = length & 0x7f;
+
+                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
+                if (size > 4)
+                {
+                    throw new InvalidOperationException("DER length more than 4 bytes: " + size);
+                }
+
+                return size + 2;
+            }
+
+            return 2;
+        }
+
+		public bool IsConstructed()
+        {
+			return isConstructed;
+        }
+
+		public byte[] GetContents()
+        {
+            return octets;
+        }
+
+		public int ApplicationTag
+        {
+            get { return tag; }
+        }
+
+		/**
+		 * Return the enclosed object assuming explicit tagging.
+		 *
+		 * @return  the resulting object
+		 * @throws IOException if reconstruction fails.
+		 */
+		public Asn1Object GetObject()
+        {
+			return FromByteArray(GetContents());
+		}
+
+		/**
+		 * Return the enclosed object assuming implicit tagging.
+		 *
+		 * @param derTagNo the type tag that should be applied to the object's contents.
+		 * @return  the resulting object
+		 * @throws IOException if reconstruction fails.
+		 */
+		public Asn1Object GetObject(
+			int derTagNo)
+		{
+			if (derTagNo >= 0x1f)
+				throw new IOException("unsupported tag number");
+
+			byte[] orig = this.GetEncoded();
+			byte[] tmp = ReplaceTagNumber(derTagNo, orig);
+
+			if ((orig[0] & Asn1Tags.Constructed) != 0)
+			{
+				tmp[0] |= Asn1Tags.Constructed;
+			}
+
+			return FromByteArray(tmp);;
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+        {
+			int classBits = Asn1Tags.Application;
+			if (isConstructed)
+			{
+				classBits |= Asn1Tags.Constructed; 
+			}
+
+			derOut.WriteEncoded(classBits, tag, octets);
+		}
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+        {
+			DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
+
+			if (other == null)
+				return false;
+
+			return this.isConstructed == other.isConstructed
+				&& this.tag == other.tag
+				&& Arrays.AreEqual(this.octets, other.octets);
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+			return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
+        }
+
+		private byte[] ReplaceTagNumber(
+			int		newTag,
+			byte[]	input)
+		{
+			int tagNo = input[0] & 0x1f;
+			int index = 1;
+			//
+			// with tagged object tag number is bottom 5 bits, or stored at the start of the content
+			//
+			if (tagNo == 0x1f)
+			{
+				tagNo = 0;
+
+				int b = input[index++] & 0xff;
+
+				// X.690-0207 8.1.2.4.2
+				// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+				if ((b & 0x7f) == 0) // Note: -1 will pass
+				{
+					throw new InvalidOperationException("corrupted stream - invalid high tag number found");
+				}
+
+				while ((b >= 0) && ((b & 0x80) != 0))
+				{
+					tagNo |= (b & 0x7f);
+					tagNo <<= 7;
+					b = input[index++] & 0xff;
+				}
+
+				tagNo |= (b & 0x7f);
+			}
+
+			byte[] tmp = new byte[input.Length - index + 1];
+
+			Array.Copy(input, index, tmp, 1, tmp.Length - 1);
+
+			tmp[0] = (byte)newTag;
+
+			return tmp;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerBMPString.cs b/BouncyCastle.AxCrypt/src/asn1/DerBMPString.cs
new file mode 100644
index 0000000..4f7e0a6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerBMPString.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der BMPString object.
+     */
+    public class DerBmpString
+		: DerStringBase
+    {
+        private readonly string str;
+
+		/**
+         * return a BMP string from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerBmpString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerBmpString)
+            {
+                return (DerBmpString)obj;
+            }
+
+			throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return a BMP string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *              be converted.
+         */
+        public static DerBmpString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerBmpString)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerBmpString(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+		/**
+         * basic constructor - byte encoded string.
+         */
+        public DerBmpString(
+            byte[] str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+            char[] cs = new char[str.Length / 2];
+
+			for (int i = 0; i != cs.Length; i++)
+            {
+                cs[i] = (char)((str[2 * i] << 8) | (str[2 * i + 1] & 0xff));
+            }
+
+			this.str = new string(cs);
+        }
+
+        /**
+         * basic constructor
+         */
+        public DerBmpString(
+            string str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+        public override string GetString()
+        {
+            return str;
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+        {
+			DerBmpString other = asn1Object as DerBmpString;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            char[] c = str.ToCharArray();
+            byte[] b = new byte[c.Length * 2];
+
+			for (int i = 0; i != c.Length; i++)
+            {
+                b[2 * i] = (byte)(c[i] >> 8);
+                b[2 * i + 1] = (byte)c[i];
+            }
+
+            derOut.WriteEncoded(Asn1Tags.BmpString, b);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerBitString.cs b/BouncyCastle.AxCrypt/src/asn1/DerBitString.cs
new file mode 100644
index 0000000..d5cb872
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerBitString.cs
@@ -0,0 +1,248 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerBitString
+		: DerStringBase
+	{
+		private static readonly char[] table
+			= { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+		private readonly byte[]	data;
+		private readonly int	padBits;
+
+		/**
+		 * return the correct number of pad bits for a bit string defined in
+		 * a 32 bit constant
+		 */
+		static internal int GetPadBits(
+			int bitString)
+		{
+			int val = 0;
+			for (int i = 3; i >= 0; i--)
+			{
+				//
+				// this may look a little odd, but if it isn't done like this pre jdk1.2
+				// JVM's break!
+				//
+				if (i != 0)
+				{
+					if ((bitString >> (i * 8)) != 0)
+					{
+						val = (bitString >> (i * 8)) & 0xFF;
+						break;
+					}
+				}
+				else
+				{
+					if (bitString != 0)
+					{
+						val = bitString & 0xFF;
+						break;
+					}
+				}
+			}
+
+			if (val == 0)
+			{
+				return 7;
+			}
+
+			int bits = 1;
+
+			while (((val <<= 1) & 0xFF) != 0)
+			{
+				bits++;
+			}
+
+			return 8 - bits;
+		}
+
+		/**
+		 * return the correct number of bytes for a bit string defined in
+		 * a 32 bit constant
+		 */
+		static internal byte[] GetBytes(
+			int bitString)
+		{
+			int bytes = 4;
+			for (int i = 3; i >= 1; i--)
+			{
+				if ((bitString & (0xFF << (i * 8))) != 0)
+				{
+					break;
+				}
+				bytes--;
+			}
+
+			byte[] result = new byte[bytes];
+			for (int i = 0; i < bytes; i++)
+			{
+				result[i] = (byte) ((bitString >> (i * 8)) & 0xFF);
+			}
+
+			return result;
+		}
+
+		/**
+		 * return a Bit string from the passed in object
+		 *
+		 * @exception ArgumentException if the object cannot be converted.
+		 */
+		public static DerBitString GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is DerBitString)
+			{
+				return (DerBitString) obj;
+			}
+
+			throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+		}
+
+		/**
+		 * return a Bit string from a tagged object.
+		 *
+		 * @param obj the tagged object holding the object we want
+		 * @param explicitly true if the object is meant to be explicitly
+		 *              tagged false otherwise.
+		 * @exception ArgumentException if the tagged object cannot
+		 *               be converted.
+		 */
+		public static DerBitString GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerBitString)
+			{
+				return GetInstance(o);
+			}
+
+			return FromAsn1Octets(((Asn1OctetString)o).GetOctets());
+		}
+
+		internal DerBitString(
+			byte	data,
+			int		padBits)
+		{
+			this.data = new byte[]{ data };
+			this.padBits = padBits;
+		}
+
+		/**
+		 * @param data the octets making up the bit string.
+		 * @param padBits the number of extra bits at the end of the string.
+		 */
+		public DerBitString(
+			byte[]	data,
+			int		padBits)
+		{
+			// TODO Deep copy?
+			this.data = data;
+			this.padBits = padBits;
+		}
+
+		public DerBitString(
+			byte[] data)
+		{
+			// TODO Deep copy?
+			this.data = data;
+		}
+
+		public DerBitString(
+			Asn1Encodable obj)
+		{
+			this.data = obj.GetDerEncoded();
+			//this.padBits = 0;
+		}
+
+		public byte[] GetBytes()
+		{
+			return data;
+		}
+
+		public int PadBits
+		{
+			get { return padBits; }
+		}
+
+		/**
+		 * @return the value of the bit string as an int (truncating if necessary)
+		 */
+		public int IntValue
+		{
+			get
+			{
+				int value = 0;
+
+				for (int i = 0; i != data.Length && i != 4; i++)
+				{
+					value |= (data[i] & 0xff) << (8 * i);
+				}
+
+				return value;
+			}
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			byte[] bytes = new byte[GetBytes().Length + 1];
+
+			bytes[0] = (byte) PadBits;
+			Array.Copy(GetBytes(), 0, bytes, 1, bytes.Length - 1);
+
+			derOut.WriteEncoded(Asn1Tags.BitString, bytes);
+		}
+
+		protected override int Asn1GetHashCode()
+		{
+			return padBits.GetHashCode() ^ Arrays.GetHashCode(data);
+		}
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerBitString other = asn1Object as DerBitString;
+
+			if (other == null)
+				return false;
+
+			return this.padBits == other.padBits
+				&& Arrays.AreEqual(this.data, other.data);
+		}
+
+		public override string GetString()
+		{
+			StringBuilder buffer = new StringBuilder("#");
+
+			byte[] str = GetDerEncoded();
+
+			for (int i = 0; i != str.Length; i++)
+			{
+				uint ubyte = str[i];
+				buffer.Append(table[(ubyte >> 4) & 0xf]);
+				buffer.Append(table[str[i] & 0xf]);
+			}
+
+			return buffer.ToString();
+		}
+
+		internal static DerBitString FromAsn1Octets(byte[] octets)
+		{
+	        if (octets.Length < 1)
+	            throw new ArgumentException("truncated BIT STRING detected");
+
+			int padBits = octets[0];
+			byte[] data = new byte[octets.Length - 1];
+			Array.Copy(octets, 1, data, 0, data.Length);
+			return new DerBitString(data, padBits);
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerBoolean.cs b/BouncyCastle.AxCrypt/src/asn1/DerBoolean.cs
new file mode 100644
index 0000000..66791d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerBoolean.cs
@@ -0,0 +1,122 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerBoolean
+        : Asn1Object
+    {
+        private readonly byte value;
+
+        public static readonly DerBoolean False = new DerBoolean(false);
+        public static readonly DerBoolean True  = new DerBoolean(true);
+
+        /**
+         * return a bool from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerBoolean GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerBoolean)
+            {
+                return (DerBoolean) obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return a DerBoolean from the passed in bool.
+         */
+        public static DerBoolean GetInstance(
+            bool value)
+        {
+            return value ? True : False;
+        }
+
+        /**
+         * return a Boolean from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerBoolean GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            Asn1Object o = obj.GetObject();
+
+            if (isExplicit || o is DerBoolean)
+            {
+                return GetInstance(o);
+            }
+
+            return FromOctetString(((Asn1OctetString)o).GetOctets());
+        }
+
+        public DerBoolean(
+            byte[] val)
+        {
+            if (val.Length != 1)
+                throw new ArgumentException("byte value should have 1 byte in it", "val");
+
+            // TODO Are there any constraints on the possible byte values?
+            this.value = val[0];
+        }
+
+        private DerBoolean(
+            bool value)
+        {
+            this.value = value ? (byte)0xff : (byte)0;
+        }
+
+        public bool IsTrue
+        {
+            get { return value != 0; }
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            // TODO Should we make sure the byte value is one of '0' or '0xff' here?
+            derOut.WriteEncoded(Asn1Tags.Boolean, new byte[]{ value });
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            DerBoolean other = asn1Object as DerBoolean;
+
+            if (other == null)
+                return false;
+
+            return IsTrue == other.IsTrue;
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            return IsTrue.GetHashCode();
+        }
+
+        public override string ToString()
+        {
+            return IsTrue ? "TRUE" : "FALSE";
+        }
+
+        internal static DerBoolean FromOctetString(byte[] value)
+        {
+            if (value.Length != 1)
+            {
+                throw new ArgumentException("BOOLEAN value should have 1 byte in it", "value");
+            }
+
+            byte b = value[0];
+
+            return b == 0 ? False : b == 0xFF ? True : new DerBoolean(value);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerEnumerated.cs b/BouncyCastle.AxCrypt/src/asn1/DerEnumerated.cs
new file mode 100644
index 0000000..2638b02
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerEnumerated.cs
@@ -0,0 +1,124 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerEnumerated
+        : Asn1Object
+    {
+        private readonly byte[] bytes;
+
+        /**
+         * return an integer from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerEnumerated GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerEnumerated)
+            {
+                return (DerEnumerated)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an Enumerated from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerEnumerated GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            Asn1Object o = obj.GetObject();
+
+            if (isExplicit || o is DerEnumerated)
+            {
+                return GetInstance(o);
+            }
+
+            return FromOctetString(((Asn1OctetString)o).GetOctets());
+        }
+
+        public DerEnumerated(
+            int val)
+        {
+            bytes = BigInteger.ValueOf(val).ToByteArray();
+        }
+
+        public DerEnumerated(
+            BigInteger val)
+        {
+            bytes = val.ToByteArray();
+        }
+
+        public DerEnumerated(
+            byte[]   bytes)
+        {
+            this.bytes = bytes;
+        }
+
+        public BigInteger Value
+        {
+            get { return new BigInteger(bytes); }
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.Enumerated, bytes);
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            DerEnumerated other = asn1Object as DerEnumerated;
+
+            if (other == null)
+                return false;
+
+            return Arrays.AreEqual(this.bytes, other.bytes);
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            return Arrays.GetHashCode(bytes);
+        }
+
+        private static readonly DerEnumerated[] cache = new DerEnumerated[12];
+
+        internal static DerEnumerated FromOctetString(byte[] enc)
+        {
+            if (enc.Length == 0)
+            {
+                throw new ArgumentException("ENUMERATED has zero length", "enc");
+            }
+
+            if (enc.Length == 1)
+            {
+                int value = enc[0];
+                if (value < cache.Length)
+                {
+                    DerEnumerated cached = cache[value];
+                    if (cached != null)
+                    {
+                        return cached;
+                    }
+
+                    return cache[value] = new DerEnumerated(Arrays.Clone(enc));
+                }
+            }
+
+            return new DerEnumerated(Arrays.Clone(enc));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerGeneralString.cs b/BouncyCastle.AxCrypt/src/asn1/DerGeneralString.cs
new file mode 100644
index 0000000..0e20b53
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerGeneralString.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerGeneralString
+        : DerStringBase
+    {
+        private readonly string str;
+
+        public static DerGeneralString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerGeneralString)
+            {
+                return (DerGeneralString) obj;
+            }
+
+			throw new ArgumentException("illegal object in GetInstance: "
+                    + obj.GetType().Name);
+        }
+
+        public static DerGeneralString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerGeneralString)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerGeneralString(((Asn1OctetString)o).GetOctets());
+        }
+
+        public DerGeneralString(
+			byte[] str)
+			: this(Strings.FromAsciiByteArray(str))
+        {
+        }
+
+		public DerGeneralString(
+			string str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+        public override string GetString()
+        {
+            return str;
+        }
+
+		public byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(str);
+        }
+
+		internal override void Encode(
+			DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.GeneralString, GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+        {
+			DerGeneralString other = asn1Object as DerGeneralString;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerGeneralizedTime.cs b/BouncyCastle.AxCrypt/src/asn1/DerGeneralizedTime.cs
new file mode 100644
index 0000000..ceb1a4f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerGeneralizedTime.cs
@@ -0,0 +1,308 @@
+using System;
+using System.Globalization;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Generalized time object.
+     */
+    public class DerGeneralizedTime
+        : Asn1Object
+    {
+        private readonly string time;
+
+        /**
+         * return a generalized time from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerGeneralizedTime GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerGeneralizedTime)
+            {
+                return (DerGeneralizedTime)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
+        }
+
+        /**
+         * return a Generalized Time object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerGeneralizedTime GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            Asn1Object o = obj.GetObject();
+
+            if (isExplicit || o is DerGeneralizedTime)
+            {
+                return GetInstance(o);
+            }
+
+            return new DerGeneralizedTime(((Asn1OctetString)o).GetOctets());
+        }
+
+        /**
+         * The correct format for this is YYYYMMDDHHMMSS[.f]Z, or without the Z
+         * for local time, or Z+-HHMM on the end, for difference between local
+         * time and UTC time. The fractional second amount f must consist of at
+         * least one number with trailing zeroes removed.
+         *
+         * @param time the time string.
+         * @exception ArgumentException if string is an illegal format.
+         */
+        public DerGeneralizedTime(
+            string time)
+        {
+            this.time = time;
+
+            try
+            {
+                ToDateTime();
+            }
+            catch (FormatException e)
+            {
+                throw new ArgumentException("invalid date string: " + e.Message);
+            }
+        }
+
+        /**
+         * base constructor from a local time object
+         */
+        public DerGeneralizedTime(
+            DateTime time)
+        {
+            this.time = time.ToUniversalTime().ToString(@"yyyyMMddHHmmss\Z");
+        }
+
+        internal DerGeneralizedTime(
+            byte[] bytes)
+        {
+            //
+            // explicitly convert to characters
+            //
+            this.time = Strings.FromAsciiByteArray(bytes);
+        }
+
+        /**
+         * Return the time.
+         * @return The time string as it appeared in the encoded object.
+         */
+        public string TimeString
+        {
+            get { return time; }
+        }
+
+        /**
+         * return the time - always in the form of
+         *  YYYYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+         * <p>
+         * Normally in a certificate we would expect "Z" rather than "GMT",
+         * however adding the "GMT" means we can just use:
+         * <pre>
+         *     dateF = new SimpleDateFormat("yyyyMMddHHmmssz");
+         * </pre>
+         * To read in the time and Get a date which is compatible with our local
+         * time zone.</p>
+         */
+        public string GetTime()
+        {
+            //
+            // standardise the format.
+            //
+            if (time[time.Length - 1] == 'Z')
+            {
+                return time.Substring(0, time.Length - 1) + "GMT+00:00";
+            }
+            else
+            {
+                int signPos = time.Length - 5;
+                char sign = time[signPos];
+                if (sign == '-' || sign == '+')
+                {
+                    return time.Substring(0, signPos)
+                        + "GMT"
+                        + time.Substring(signPos, 3)
+                        + ":"
+                        + time.Substring(signPos + 3);
+                }
+                else
+                {
+                    signPos = time.Length - 3;
+                    sign = time[signPos];
+                    if (sign == '-' || sign == '+')
+                    {
+                        return time.Substring(0, signPos)
+                            + "GMT"
+                            + time.Substring(signPos)
+                            + ":00";
+                    }
+                }
+            }
+
+            return time + CalculateGmtOffset();
+        }
+
+        private string CalculateGmtOffset()
+        {
+            char sign = '+';
+            DateTime time = ToDateTime();
+
+#if SILVERLIGHT
+            long offset = time.Ticks - time.ToUniversalTime().Ticks;
+            if (offset < 0)
+            {
+                sign = '-';
+                offset = -offset;
+            }
+            int hours = (int)(offset / TimeSpan.TicksPerHour);
+            int minutes = (int)(offset / TimeSpan.TicksPerMinute) % 60;
+#else
+            // Note: GetUtcOffset incorporates Daylight Savings offset
+            TimeSpan offset =  TimeZone.CurrentTimeZone.GetUtcOffset(time);
+            if (offset.CompareTo(TimeSpan.Zero) < 0)
+            {
+                sign = '-';
+                offset = offset.Duration();
+            }
+            int hours = offset.Hours;
+            int minutes = offset.Minutes;
+#endif
+
+            return "GMT" + sign + Convert(hours) + ":" + Convert(minutes);
+        }
+
+        private static string Convert(
+            int time)
+        {
+            if (time < 10)
+            {
+                return "0" + time;
+            }
+
+            return time.ToString();
+        }
+
+        public DateTime ToDateTime()
+        {
+            string formatStr;
+            string d = time;
+            bool makeUniversal = false;
+
+            if (d.EndsWith("Z"))
+            {
+                if (HasFractionalSeconds)
+                {
+                    int fCount = d.Length - d.IndexOf('.') - 2;
+                    formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"\Z";
+                }
+                else
+                {
+                    formatStr = @"yyyyMMddHHmmss\Z";
+                }
+            }
+            else if (time.IndexOf('-') > 0 || time.IndexOf('+') > 0)
+            {
+                d = GetTime();
+                makeUniversal = true;
+
+                if (HasFractionalSeconds)
+                {
+                    int fCount = d.IndexOf("GMT") - 1 - d.IndexOf('.');
+                    formatStr = @"yyyyMMddHHmmss." + FString(fCount) + @"'GMT'zzz";
+                }
+                else
+                {
+                    formatStr = @"yyyyMMddHHmmss'GMT'zzz";
+                }
+            }
+            else
+            {
+                if (HasFractionalSeconds)
+                {
+                    int fCount = d.Length - 1 - d.IndexOf('.');
+                    formatStr = @"yyyyMMddHHmmss." + FString(fCount);
+                }
+                else
+                {
+                    formatStr = @"yyyyMMddHHmmss";
+                }
+
+                // TODO?
+//				dateF.setTimeZone(new SimpleTimeZone(0, TimeZone.getDefault().getID()));
+            }
+
+            return ParseDateString(d, formatStr, makeUniversal);
+        }
+
+        private string FString(
+            int count)
+        {
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < count; ++i)
+            {
+                sb.Append('f');
+            }
+            return sb.ToString();
+        }
+
+        private DateTime ParseDateString(string	s, string format, bool makeUniversal)
+        {
+            DateTimeStyles style = DateTimeStyles.None;
+            if (format.EndsWith("Z"))
+            {
+                style = DateTimeStyles.AssumeUniversal;
+                
+
+                style |= DateTimeStyles.AdjustToUniversal;
+            }
+
+            DateTime dt = DateTime.ParseExact(s, format, DateTimeFormatInfo.InvariantInfo, style);
+
+            return makeUniversal ? dt.ToUniversalTime() : dt;
+        }
+
+        private bool HasFractionalSeconds
+        {
+            get { return time.IndexOf('.') == 14; }
+        }
+
+        private byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(time);
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.GeneralizedTime, GetOctets());
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            DerGeneralizedTime other = asn1Object as DerGeneralizedTime;
+
+            if (other == null)
+                return false;
+
+            return this.time.Equals(other.time);
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            return time.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerIA5String.cs b/BouncyCastle.AxCrypt/src/asn1/DerIA5String.cs
new file mode 100644
index 0000000..9fa2cba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerIA5String.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der IA5String object - this is an ascii string.
+     */
+    public class DerIA5String
+        : DerStringBase
+    {
+        private readonly string str;
+
+        /**
+         * return a IA5 string from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerIA5String GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerIA5String)
+            {
+                return (DerIA5String)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an IA5 string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerIA5String GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerIA5String)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerIA5String(((Asn1OctetString)o).GetOctets());
+        }
+
+        /**
+         * basic constructor - with bytes.
+         */
+        public DerIA5String(
+            byte[] str)
+            : this(Strings.FromAsciiByteArray(str), false)
+        {
+        }
+
+		/**
+		* basic constructor - without validation.
+		*/
+		public DerIA5String(
+			string str)
+			: this(str, false)
+		{
+		}
+
+		/**
+		* Constructor with optional validation.
+		*
+		* @param string the base string to wrap.
+		* @param validate whether or not to check the string.
+		* @throws ArgumentException if validate is true and the string
+		* contains characters that should not be in an IA5String.
+		*/
+		public DerIA5String(
+			string	str,
+			bool	validate)
+		{
+			if (str == null)
+				throw new ArgumentNullException("str");
+			if (validate && !IsIA5String(str))
+				throw new ArgumentException("string contains illegal characters", "str");
+
+			this.str = str;
+		}
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+		public byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(str);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.IA5String, GetOctets());
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+            return this.str.GetHashCode();
+        }
+
+		protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+			DerIA5String other = asn1Object as DerIA5String;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		/**
+		 * return true if the passed in String can be represented without
+		 * loss as an IA5String, false otherwise.
+		 *
+		 * @return true if in printable set, false otherwise.
+		 */
+		public static bool IsIA5String(
+			string str)
+		{
+			foreach (char ch in str)
+			{
+				if (ch > 0x007f)
+				{
+					return false;
+				}
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerInteger.cs b/BouncyCastle.AxCrypt/src/asn1/DerInteger.cs
new file mode 100644
index 0000000..eb06145
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerInteger.cs
@@ -0,0 +1,117 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerInteger
+        : Asn1Object
+    {
+        private readonly byte[] bytes;
+
+        /**
+         * return an integer from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerInteger GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerInteger)
+            {
+                return (DerInteger)obj;
+            }
+
+			throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an Integer from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param isExplicit true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerInteger GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            if (obj == null)
+                throw new ArgumentNullException("obj");
+
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerInteger)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerInteger(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+		public DerInteger(
+            int value)
+        {
+            bytes = BigInteger.ValueOf(value).ToByteArray();
+        }
+
+		public DerInteger(
+            BigInteger value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+			bytes = value.ToByteArray();
+        }
+
+		public DerInteger(
+            byte[] bytes)
+        {
+            this.bytes = bytes;
+        }
+
+		public BigInteger Value
+        {
+            get { return new BigInteger(bytes); }
+        }
+
+		/**
+         * in some cases positive values Get crammed into a space,
+         * that's not quite big enough...
+         */
+        public BigInteger PositiveValue
+        {
+            get { return new BigInteger(1, bytes); }
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.Integer, bytes);
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+			return Arrays.GetHashCode(bytes);
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerInteger other = asn1Object as DerInteger;
+
+			if (other == null)
+				return false;
+
+			return Arrays.AreEqual(this.bytes, other.bytes);
+        }
+
+		public override string ToString()
+		{
+			return Value.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerNull.cs b/BouncyCastle.AxCrypt/src/asn1/DerNull.cs
new file mode 100644
index 0000000..a802f64
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerNull.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * A Null object.
+	 */
+	public class DerNull
+		: Asn1Null
+	{
+		public static readonly DerNull Instance = new DerNull(0);
+
+		byte[] zeroBytes = new byte[0];
+
+		[Obsolete("Use static Instance object")]
+		public DerNull()
+		{
+		}
+
+		protected internal DerNull(int dummy)
+		{
+		}
+
+		internal override void Encode(
+			DerOutputStream  derOut)
+		{
+			derOut.WriteEncoded(Asn1Tags.Null, zeroBytes);
+		}
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			return asn1Object is DerNull;
+		}
+
+		protected override int Asn1GetHashCode()
+		{
+			return -1;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerNumericString.cs b/BouncyCastle.AxCrypt/src/asn1/DerNumericString.cs
new file mode 100644
index 0000000..6e2715a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerNumericString.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der NumericString object - this is an ascii string of characters {0,1,2,3,4,5,6,7,8,9, }.
+     */
+    public class DerNumericString
+        : DerStringBase
+    {
+        private readonly string str;
+
+        /**
+         * return a Numeric string from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerNumericString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerNumericString)
+            {
+                return (DerNumericString)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an Numeric string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerNumericString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerNumericString)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerNumericString(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+		/**
+		 * basic constructor - with bytes.
+		 */
+		public DerNumericString(
+			byte[] str)
+            : this(Strings.FromAsciiByteArray(str), false)
+		{
+		}
+
+		/**
+		 * basic constructor -  without validation..
+		 */
+		public DerNumericString(
+			string str)
+			: this(str, false)
+		{
+		}
+
+		/**
+		* Constructor with optional validation.
+		*
+		* @param string the base string to wrap.
+		* @param validate whether or not to check the string.
+		* @throws ArgumentException if validate is true and the string
+		* contains characters that should not be in a NumericString.
+		*/
+		public DerNumericString(
+			string	str,
+			bool	validate)
+		{
+			if (str == null)
+				throw new ArgumentNullException("str");
+			if (validate && !IsNumericString(str))
+				throw new ArgumentException("string contains illegal characters", "str");
+
+			this.str = str;
+		}
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+		public byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(str);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.NumericString, GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerNumericString other = asn1Object as DerNumericString;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		/**
+		 * Return true if the string can be represented as a NumericString ('0'..'9', ' ')
+		 *
+		 * @param str string to validate.
+		 * @return true if numeric, fale otherwise.
+		 */
+		public static bool IsNumericString(
+			string str)
+		{
+			foreach (char ch in str)
+			{
+				if (ch > 0x007f || (ch != ' ' && !char.IsDigit(ch)))
+					return false;
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerObjectIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/DerObjectIdentifier.cs
new file mode 100644
index 0000000..f9f6a79
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerObjectIdentifier.cs
@@ -0,0 +1,347 @@
+using System;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerObjectIdentifier
+        : Asn1Object
+    {
+        private readonly string identifier;
+
+        private byte[] body = null;
+
+        /**
+         * return an Oid from the passed in object
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerObjectIdentifier GetInstance(object obj)
+        {
+            if (obj == null || obj is DerObjectIdentifier)
+                return (DerObjectIdentifier) obj;
+            if (obj is byte[])
+                return FromOctetString((byte[])obj);
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name, "obj");
+        }
+
+        /**
+         * return an object Identifier from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerObjectIdentifier GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(obj.GetObject());
+        }
+
+        public DerObjectIdentifier(
+            string identifier)
+        {
+            if (identifier == null)
+                throw new ArgumentNullException("identifier");
+            if (!IsValidIdentifier(identifier))
+                throw new FormatException("string " + identifier + " not an OID");
+
+            this.identifier = identifier;
+        }
+
+        internal DerObjectIdentifier(DerObjectIdentifier oid, string branchID)
+        {
+            if (!IsValidBranchID(branchID, 0))
+                throw new ArgumentException("string " + branchID + " not a valid OID branch", "branchID");
+
+            this.identifier = oid.Id + "." + branchID;
+        }
+
+        // TODO Change to ID?
+        public string Id
+        {
+            get { return identifier; }
+        }
+
+        public virtual DerObjectIdentifier Branch(string branchID)
+        {
+            return new DerObjectIdentifier(this, branchID);
+        }
+
+        /**
+         * Return  true if this oid is an extension of the passed in branch, stem.
+         * @param stem the arc or branch that is a possible parent.
+         * @return  true if the branch is on the passed in stem, false otherwise.
+         */
+        public virtual bool On(DerObjectIdentifier stem)
+        {
+            string id = Id, stemId = stem.Id;
+            return id.Length > stemId.Length && id[stemId.Length] == '.' && id.StartsWith(stemId);
+        }
+
+        internal DerObjectIdentifier(byte[] bytes)
+        {
+            this.identifier = MakeOidStringFromBytes(bytes);
+            this.body = Arrays.Clone(bytes);
+        }
+
+        private void WriteField(
+            Stream	outputStream,
+            long	fieldValue)
+        {
+            byte[] result = new byte[9];
+            int pos = 8;
+            result[pos] = (byte)(fieldValue & 0x7f);
+            while (fieldValue >= (1L << 7))
+            {
+                fieldValue >>= 7;
+                result[--pos] = (byte)((fieldValue & 0x7f) | 0x80);
+            }
+            outputStream.Write(result, pos, 9 - pos);
+        }
+
+        private void WriteField(
+            Stream		outputStream,
+            BigInteger	fieldValue)
+        {
+            int byteCount = (fieldValue.BitLength + 6) / 7;
+            if (byteCount == 0)
+            {
+                outputStream.WriteByte(0);
+            }
+            else
+            {
+                BigInteger tmpValue = fieldValue;
+                byte[] tmp = new byte[byteCount];
+                for (int i = byteCount-1; i >= 0; i--)
+                {
+                    tmp[i] = (byte) ((tmpValue.IntValue & 0x7f) | 0x80);
+                    tmpValue = tmpValue.ShiftRight(7);
+                }
+                tmp[byteCount-1] &= 0x7f;
+                outputStream.Write(tmp, 0, tmp.Length);
+            }
+        }
+
+        private void DoOutput(MemoryStream bOut)
+        {
+            OidTokenizer tok = new OidTokenizer(identifier);
+
+            string token = tok.NextToken();
+            int first = int.Parse(token) * 40;
+
+            token = tok.NextToken();
+            if (token.Length <= 18)
+            {
+                WriteField(bOut, first + Int64.Parse(token));
+            }
+            else
+            {
+                WriteField(bOut, new BigInteger(token).Add(BigInteger.ValueOf(first)));
+            }
+
+            while (tok.HasMoreTokens)
+            {
+                token = tok.NextToken();
+                if (token.Length <= 18)
+                {
+                    WriteField(bOut, Int64.Parse(token));
+                }
+                else
+                {
+                    WriteField(bOut, new BigInteger(token));
+                }
+            }
+        }
+
+        internal byte[] GetBody()
+        {
+            lock (this)
+            {
+                if (body == null)
+                {
+                    MemoryStream bOut = new MemoryStream();
+                    DoOutput(bOut);
+                    body = bOut.ToArray();
+                }
+            }
+
+            return body;
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.ObjectIdentifier, GetBody());
+        }
+
+        protected override int Asn1GetHashCode()
+        {
+            return identifier.GetHashCode();
+        }
+
+        protected override bool Asn1Equals(
+            Asn1Object asn1Object)
+        {
+            DerObjectIdentifier other = asn1Object as DerObjectIdentifier;
+
+            if (other == null)
+                return false;
+
+            return this.identifier.Equals(other.identifier);
+        }
+
+        public override string ToString()
+        {
+            return identifier;
+        }
+
+        private static bool IsValidBranchID(
+            String branchID, int start)
+        {
+            bool periodAllowed = false;
+
+            int pos = branchID.Length;
+            while (--pos >= start)
+            {
+                char ch = branchID[pos];
+
+                // TODO Leading zeroes?
+                if ('0' <= ch && ch <= '9')
+                {
+                    periodAllowed = true;
+                    continue;
+                }
+
+                if (ch == '.')
+                {
+                    if (!periodAllowed)
+                        return false;
+
+                    periodAllowed = false;
+                    continue;
+                }
+
+                return false;
+            }
+
+            return periodAllowed;
+        }
+
+        private static bool IsValidIdentifier(string identifier)
+        {
+            if (identifier.Length < 3 || identifier[1] != '.')
+                return false;
+
+            char first = identifier[0];
+            if (first < '0' || first > '2')
+                return false;
+
+            return IsValidBranchID(identifier, 2);
+        }
+
+        private const long LONG_LIMIT = (long.MaxValue >> 7) - 0x7f;
+
+        private static string MakeOidStringFromBytes(
+            byte[] bytes)
+        {
+            StringBuilder	objId = new StringBuilder();
+            long			value = 0;
+            BigInteger		bigValue = null;
+            bool			first = true;
+
+            for (int i = 0; i != bytes.Length; i++)
+            {
+                int b = bytes[i];
+
+                if (value <= LONG_LIMIT)
+                {
+                    value += (b & 0x7f);
+                    if ((b & 0x80) == 0)             // end of number reached
+                    {
+                        if (first)
+                        {
+                            if (value < 40)
+                            {
+                                objId.Append('0');
+                            }
+                            else if (value < 80)
+                            {
+                                objId.Append('1');
+                                value -= 40;
+                            }
+                            else
+                            {
+                                objId.Append('2');
+                                value -= 80;
+                            }
+                            first = false;
+                        }
+
+                        objId.Append('.');
+                        objId.Append(value);
+                        value = 0;
+                    }
+                    else
+                    {
+                        value <<= 7;
+                    }
+                }
+                else
+                {
+                    if (bigValue == null)
+                    {
+                        bigValue = BigInteger.ValueOf(value);
+                    }
+                    bigValue = bigValue.Or(BigInteger.ValueOf(b & 0x7f));
+                    if ((b & 0x80) == 0)
+                    {
+                        if (first)
+                        {
+                            objId.Append('2');
+                            bigValue = bigValue.Subtract(BigInteger.ValueOf(80));
+                            first = false;
+                        }
+
+                        objId.Append('.');
+                        objId.Append(bigValue);
+                        bigValue = null;
+                        value = 0;
+                    }
+                    else
+                    {
+                        bigValue = bigValue.ShiftLeft(7);
+                    }
+                }
+            }
+
+            return objId.ToString();
+        }
+
+        private static readonly DerObjectIdentifier[] cache = new DerObjectIdentifier[1024];
+
+        internal static DerObjectIdentifier FromOctetString(byte[] enc)
+        {
+            int hashCode = Arrays.GetHashCode(enc);
+            int first = hashCode & 1023;
+
+            lock (cache)
+            {
+                DerObjectIdentifier entry = cache[first];
+                if (entry != null && Arrays.AreEqual(enc, entry.GetBody()))
+                {
+                    return entry;
+                }
+
+                return cache[first] = new DerObjectIdentifier(enc);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerOctetString.cs b/BouncyCastle.AxCrypt/src/asn1/DerOctetString.cs
new file mode 100644
index 0000000..c046c94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerOctetString.cs
@@ -0,0 +1,34 @@
+namespace Org.BouncyCastle.Asn1
+{
+    public class DerOctetString
+        : Asn1OctetString
+    {
+		/// <param name="str">The octets making up the octet string.</param>
+        public DerOctetString(
+			byte[] str)
+			: base(str)
+        {
+        }
+
+		public DerOctetString(
+			Asn1Encodable obj)
+			: base(obj)
+        {
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.OctetString, str);
+        }
+
+		internal static void Encode(
+			DerOutputStream	derOut,
+			byte[]			bytes,
+			int				offset,
+			int				length)
+		{
+			derOut.WriteEncoded(Asn1Tags.OctetString, bytes, offset, length);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerOutputStream.cs b/BouncyCastle.AxCrypt/src/asn1/DerOutputStream.cs
new file mode 100644
index 0000000..f95d123
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerOutputStream.cs
@@ -0,0 +1,160 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerOutputStream
+		: FilterStream
+	{
+		public DerOutputStream(Stream os)
+			: base(os)
+		{
+		}
+
+		private void WriteLength(
+			int length)
+		{
+			if (length > 127)
+			{
+				int size = 1;
+				uint val = (uint) length;
+
+				while ((val >>= 8) != 0)
+				{
+					size++;
+				}
+
+				WriteByte((byte)(size | 0x80));
+
+				for (int i = (size - 1) * 8; i >= 0; i -= 8)
+				{
+					WriteByte((byte)(length >> i));
+				}
+			}
+			else
+			{
+				WriteByte((byte)length);
+			}
+		}
+
+		internal void WriteEncoded(
+			int		tag,
+			byte[]	bytes)
+		{
+			WriteByte((byte) tag);
+			WriteLength(bytes.Length);
+			Write(bytes, 0, bytes.Length);
+		}
+
+		internal void WriteEncoded(
+			int		tag,
+			byte[]	bytes,
+			int		offset,
+			int		length)
+		{
+			WriteByte((byte) tag);
+			WriteLength(length);
+			Write(bytes, offset, length);
+		}
+
+		internal void WriteTag(
+			int	flags,
+			int	tagNo)
+		{
+			if (tagNo < 31)
+			{
+				WriteByte((byte)(flags | tagNo));
+			}
+			else
+			{
+				WriteByte((byte)(flags | 0x1f));
+				if (tagNo < 128)
+				{
+					WriteByte((byte)tagNo);
+				}
+				else
+				{
+					byte[] stack = new byte[5];
+					int pos = stack.Length;
+
+					stack[--pos] = (byte)(tagNo & 0x7F);
+
+					do
+					{
+						tagNo >>= 7;
+						stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
+					}
+					while (tagNo > 127);
+
+					Write(stack, pos, stack.Length - pos);
+				}
+			}
+		}
+
+		internal void WriteEncoded(
+			int		flags,
+			int		tagNo,
+			byte[]	bytes)
+		{
+			WriteTag(flags, tagNo);
+			WriteLength(bytes.Length);
+			Write(bytes, 0, bytes.Length);
+		}
+
+		protected void WriteNull()
+		{
+			WriteByte(Asn1Tags.Null);
+			WriteByte(0x00);
+		}
+
+		[Obsolete("Use version taking an Asn1Encodable arg instead")]
+		public virtual void WriteObject(
+			object obj)
+		{
+			if (obj == null)
+			{
+				WriteNull();
+			}
+			else if (obj is Asn1Object)
+			{
+				((Asn1Object)obj).Encode(this);
+			}
+			else if (obj is Asn1Encodable)
+			{
+				((Asn1Encodable)obj).ToAsn1Object().Encode(this);
+			}
+			else
+			{
+				throw new IOException("object not Asn1Object");
+			}
+		}
+
+		public virtual void WriteObject(
+			Asn1Encodable obj)
+		{
+			if (obj == null)
+			{
+				WriteNull();
+			}
+			else
+			{
+				obj.ToAsn1Object().Encode(this);
+			}
+		}
+
+		public virtual void WriteObject(
+			Asn1Object obj)
+		{
+			if (obj == null)
+			{
+				WriteNull();
+			}
+			else
+			{
+				obj.Encode(this);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerPrintableString.cs b/BouncyCastle.AxCrypt/src/asn1/DerPrintableString.cs
new file mode 100644
index 0000000..cd2f46b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerPrintableString.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der PrintableString object.
+     */
+    public class DerPrintableString
+        : DerStringBase
+    {
+        private readonly string str;
+
+		/**
+         * return a printable string from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerPrintableString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerPrintableString)
+            {
+                return (DerPrintableString)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return a Printable string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerPrintableString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerPrintableString)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerPrintableString(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+        /**
+         * basic constructor - byte encoded string.
+         */
+        public DerPrintableString(
+            byte[] str)
+            : this(Strings.FromAsciiByteArray(str), false)
+        {
+        }
+
+		/**
+		 * basic constructor - this does not validate the string
+		 */
+		public DerPrintableString(
+			string str)
+			: this(str, false)
+		{
+		}
+
+		/**
+		* Constructor with optional validation.
+		*
+		* @param string the base string to wrap.
+		* @param validate whether or not to check the string.
+		* @throws ArgumentException if validate is true and the string
+		* contains characters that should not be in a PrintableString.
+		*/
+		public DerPrintableString(
+			string	str,
+			bool	validate)
+		{
+			if (str == null)
+				throw new ArgumentNullException("str");
+			if (validate && !IsPrintableString(str))
+				throw new ArgumentException("string contains illegal characters", "str");
+
+			this.str = str;
+		}
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+		public byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(str);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.PrintableString, GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerPrintableString other = asn1Object as DerPrintableString;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		/**
+		 * return true if the passed in String can be represented without
+		 * loss as a PrintableString, false otherwise.
+		 *
+		 * @return true if in printable set, false otherwise.
+		 */
+		public static bool IsPrintableString(
+			string str)
+		{
+			foreach (char ch in str)
+			{
+				if (ch > 0x007f)
+					return false;
+
+				if (char.IsLetterOrDigit(ch))
+					continue;
+
+//				if (char.IsPunctuation(ch))
+//					continue;
+
+				switch (ch)
+				{
+					case ' ':
+					case '\'':
+					case '(':
+					case ')':
+					case '+':
+					case '-':
+					case '.':
+					case ':':
+					case '=':
+					case '?':
+					case '/':
+					case ',':
+						continue;
+				}
+
+				return false;
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerSequence.cs b/BouncyCastle.AxCrypt/src/asn1/DerSequence.cs
new file mode 100644
index 0000000..1a86dc4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerSequence.cs
@@ -0,0 +1,85 @@
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class DerSequence
+		: Asn1Sequence
+	{
+		public static readonly DerSequence Empty = new DerSequence();
+
+		public static DerSequence FromVector(
+			Asn1EncodableVector v)
+		{
+			return v.Count < 1 ? Empty : new DerSequence(v);
+		}
+
+		/**
+		 * create an empty sequence
+		 */
+		public DerSequence()
+			: base(0)
+		{
+		}
+
+		/**
+		 * create a sequence containing one object
+		 */
+		public DerSequence(
+			Asn1Encodable obj)
+			: base(1)
+		{
+			AddObject(obj);
+		}
+
+		public DerSequence(
+			params Asn1Encodable[] v)
+			: base(v.Length)
+		{
+			foreach (Asn1Encodable ae in v)
+			{
+				AddObject(ae);
+			}
+		}
+
+		/**
+		 * create a sequence containing a vector of objects.
+		 */
+		public DerSequence(
+			Asn1EncodableVector v)
+			: base(v.Count)
+		{
+			foreach (Asn1Encodable ae in v)
+			{
+				AddObject(ae);
+			}
+		}
+
+		/*
+		 * A note on the implementation:
+		 * <p>
+		 * As Der requires the constructed, definite-length model to
+		 * be used for structured types, this varies slightly from the
+		 * ASN.1 descriptions given. Rather than just outputing Sequence,
+		 * we also have to specify Constructed, and the objects length.
+		 */
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			// TODO Intermediate buffer could be avoided if we could calculate expected length
+			MemoryStream bOut = new MemoryStream();
+			DerOutputStream dOut = new DerOutputStream(bOut);
+
+			foreach (Asn1Encodable obj in this)
+			{
+				dOut.WriteObject(obj);
+			}
+
+            dOut.Dispose();
+
+			byte[] bytes = bOut.ToArray();
+
+			derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, bytes);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerSet.cs b/BouncyCastle.AxCrypt/src/asn1/DerSet.cs
new file mode 100644
index 0000000..6d3f438
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerSet.cs
@@ -0,0 +1,108 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * A Der encoded set object
+	 */
+	public class DerSet
+		: Asn1Set
+	{
+		public static readonly DerSet Empty = new DerSet();
+
+		public static DerSet FromVector(
+			Asn1EncodableVector v)
+		{
+			return v.Count < 1 ? Empty : new DerSet(v);
+		}
+
+		internal static DerSet FromVector(
+			Asn1EncodableVector	v,
+			bool				needsSorting)
+		{
+			return v.Count < 1 ? Empty : new DerSet(v, needsSorting);
+		}
+
+		/**
+		 * create an empty set
+		 */
+		public DerSet()
+			: base(0)
+		{
+		}
+
+		/**
+		 * @param obj - a single object that makes up the set.
+		 */
+		public DerSet(
+			Asn1Encodable obj)
+			: base(1)
+		{
+			AddObject(obj);
+		}
+
+		public DerSet(
+			params Asn1Encodable[] v)
+			: base(v.Length)
+		{
+			foreach (Asn1Encodable o in v)
+			{
+				AddObject(o);
+			}
+
+			Sort();
+		}
+
+		/**
+		 * @param v - a vector of objects making up the set.
+		 */
+		public DerSet(
+			Asn1EncodableVector v)
+			: this(v, true)
+		{
+		}
+
+		internal DerSet(
+			Asn1EncodableVector	v,
+			bool				needsSorting)
+			: base(v.Count)
+		{
+			foreach (Asn1Encodable o in v)
+			{
+				AddObject(o);
+			}
+
+			if (needsSorting)
+			{
+				Sort();
+			}
+		}
+
+		/*
+		 * A note on the implementation:
+		 * <p>
+		 * As Der requires the constructed, definite-length model to
+		 * be used for structured types, this varies slightly from the
+		 * ASN.1 descriptions given. Rather than just outputing Set,
+		 * we also have to specify Constructed, and the objects length.
+		 */
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			// TODO Intermediate buffer could be avoided if we could calculate expected length
+			MemoryStream bOut = new MemoryStream();
+			DerOutputStream dOut = new DerOutputStream(bOut);
+
+			foreach (Asn1Encodable obj in this)
+			{
+				dOut.WriteObject(obj);
+			}
+
+            dOut.Dispose();
+
+			byte[] bytes = bOut.ToArray();
+
+			derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, bytes);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerStringBase.cs b/BouncyCastle.AxCrypt/src/asn1/DerStringBase.cs
new file mode 100644
index 0000000..2a5fb04
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerStringBase.cs
@@ -0,0 +1,22 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public abstract class DerStringBase
+		: Asn1Object, IAsn1String
+	{
+		protected DerStringBase()
+		{
+		}
+
+		public abstract string GetString();
+
+		public override string ToString()
+		{
+			return GetString();
+		}
+
+		protected override int Asn1GetHashCode()
+		{
+			return GetString().GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerT61String.cs b/BouncyCastle.AxCrypt/src/asn1/DerT61String.cs
new file mode 100644
index 0000000..4dee6f3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerT61String.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der T61String (also the teletex string) - 8-bit characters
+     */
+    public class DerT61String
+        : DerStringBase
+    {
+		private readonly string str;
+
+		/**
+         * return a T61 string from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerT61String GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerT61String)
+            {
+                return (DerT61String)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an T61 string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerT61String GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerT61String)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerT61String(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+        /**
+         * basic constructor - with bytes.
+         */
+        public DerT61String(
+            byte[] str)
+			: this(Strings.FromByteArray(str))
+		{
+        }
+
+		/**
+         * basic constructor - with string.
+         */
+        public DerT61String(
+            string str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.T61String, GetOctets());
+        }
+
+        public byte[] GetOctets()
+        {
+			return Strings.ToByteArray(str);
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerT61String other = asn1Object as DerT61String;
+
+			if (other == null)
+				return false;
+
+            return this.str.Equals(other.str);
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerTaggedObject.cs b/BouncyCastle.AxCrypt/src/asn1/DerTaggedObject.cs
new file mode 100644
index 0000000..717d724
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerTaggedObject.cs
@@ -0,0 +1,72 @@
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * DER TaggedObject - in ASN.1 notation this is any object preceded by
+	 * a [n] where n is some number - these are assumed to follow the construction
+	 * rules (as with sequences).
+	 */
+	public class DerTaggedObject
+		: Asn1TaggedObject
+	{
+		/**
+		 * @param tagNo the tag number for this object.
+		 * @param obj the tagged object.
+		 */
+		public DerTaggedObject(
+			int				tagNo,
+			Asn1Encodable	obj)
+			: base(tagNo, obj)
+		{
+		}
+
+		/**
+		 * @param explicitly true if an explicitly tagged object.
+		 * @param tagNo the tag number for this object.
+		 * @param obj the tagged object.
+		 */
+		public DerTaggedObject(
+			bool			explicitly,
+			int				tagNo,
+			Asn1Encodable	obj)
+			: base(explicitly, tagNo, obj)
+		{
+		}
+
+		/**
+		 * create an implicitly tagged object that contains a zero
+		 * length sequence.
+		 */
+		public DerTaggedObject(
+			int tagNo)
+			: base(false, tagNo, DerSequence.Empty)
+		{
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			if (!IsEmpty())
+			{
+				byte[] bytes = obj.GetDerEncoded();
+
+				if (explicitly)
+				{
+					derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, bytes);
+				}
+				else
+				{
+					//
+					// need to mark constructed types... (preserve Constructed tag)
+					//
+					int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
+					derOut.WriteTag(flags, tagNo);
+					derOut.Write(bytes, 1, bytes.Length - 1);
+				}
+			}
+			else
+			{
+				derOut.WriteEncoded(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo, new byte[0]);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerUTCTime.cs b/BouncyCastle.AxCrypt/src/asn1/DerUTCTime.cs
new file mode 100644
index 0000000..812d91d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerUTCTime.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Globalization;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * UTC time object.
+     */
+    public class DerUtcTime
+        : Asn1Object
+    {
+        private readonly string time;
+
+		/**
+         * return an UTC Time from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerUtcTime GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerUtcTime)
+            {
+                return (DerUtcTime)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an UTC Time from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerUtcTime GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerUtcTime)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerUtcTime(((Asn1OctetString)o).GetOctets());
+        }
+
+        /**
+         * The correct format for this is YYMMDDHHMMSSZ (it used to be that seconds were
+         * never encoded. When you're creating one of these objects from scratch, that's
+         * what you want to use, otherwise we'll try to deal with whatever Gets read from
+         * the input stream... (this is why the input format is different from the GetTime()
+         * method output).
+         * <p>
+         * @param time the time string.</p>
+         */
+        public DerUtcTime(
+            string time)
+        {
+			if (time == null)
+				throw new ArgumentNullException("time");
+
+			this.time = time;
+
+			try
+			{
+				ToDateTime();
+			}
+			catch (FormatException e)
+			{
+				throw new ArgumentException("invalid date string: " + e.Message);
+			}
+        }
+
+		/**
+         * base constructor from a DateTime object
+         */
+        public DerUtcTime(
+            DateTime time)
+        {
+            this.time = time.ToUniversalTime().ToString("yyMMddHHmmss") + "Z";
+        }
+
+		internal DerUtcTime(
+            byte[] bytes)
+        {
+            //
+            // explicitly convert to characters
+            //
+            this.time = Strings.FromAsciiByteArray(bytes);
+        }
+
+//		public DateTime ToDateTime()
+//		{
+//			string tm = this.AdjustedTimeString;
+//
+//			return new DateTime(
+//				Int16.Parse(tm.Substring(0, 4)),
+//				Int16.Parse(tm.Substring(4, 2)),
+//				Int16.Parse(tm.Substring(6, 2)),
+//				Int16.Parse(tm.Substring(8, 2)),
+//				Int16.Parse(tm.Substring(10, 2)),
+//				Int16.Parse(tm.Substring(12, 2)));
+//		}
+
+		/**
+		 * return the time as a date based on whatever a 2 digit year will return. For
+		 * standardised processing use ToAdjustedDateTime().
+		 *
+		 * @return the resulting date
+		 * @exception ParseException if the date string cannot be parsed.
+		 */
+		public DateTime ToDateTime()
+		{
+			return ParseDateString(TimeString, @"yyMMddHHmmss'GMT'zzz");
+		}
+
+		/**
+		* return the time as an adjusted date
+		* in the range of 1950 - 2049.
+		*
+		* @return a date in the range of 1950 to 2049.
+		* @exception ParseException if the date string cannot be parsed.
+		*/
+		public DateTime ToAdjustedDateTime()
+		{
+			return ParseDateString(AdjustedTimeString, @"yyyyMMddHHmmss'GMT'zzz");
+		}
+
+		private DateTime ParseDateString(
+			string	dateStr,
+			string	formatStr)
+		{
+			DateTime dt = DateTime.ParseExact(
+				dateStr,
+				formatStr,
+				DateTimeFormatInfo.InvariantInfo);
+
+			return dt.ToUniversalTime();
+		}
+
+		/**
+         * return the time - always in the form of
+         *  YYMMDDhhmmssGMT(+hh:mm|-hh:mm).
+         * <p>
+         * Normally in a certificate we would expect "Z" rather than "GMT",
+         * however adding the "GMT" means we can just use:
+         * <pre>
+         *     dateF = new SimpleDateFormat("yyMMddHHmmssz");
+         * </pre>
+         * To read in the time and Get a date which is compatible with our local
+         * time zone.</p>
+         * <p>
+         * <b>Note:</b> In some cases, due to the local date processing, this
+         * may lead to unexpected results. If you want to stick the normal
+         * convention of 1950 to 2049 use the GetAdjustedTime() method.</p>
+         */
+        public string TimeString
+        {
+			get
+			{
+				//
+				// standardise the format.
+				//
+				if (time.IndexOf('-') < 0 && time.IndexOf('+') < 0)
+				{
+					if (time.Length == 11)
+					{
+						return time.Substring(0, 10) + "00GMT+00:00";
+					}
+					else
+					{
+						return time.Substring(0, 12) + "GMT+00:00";
+					}
+				}
+				else
+				{
+					int index = time.IndexOf('-');
+					if (index < 0)
+					{
+						index = time.IndexOf('+');
+					}
+					string d = time;
+
+					if (index == time.Length - 3)
+					{
+						d += "00";
+					}
+
+					if (index == 10)
+					{
+						return d.Substring(0, 10) + "00GMT" + d.Substring(10, 3) + ":" + d.Substring(13, 2);
+					}
+					else
+					{
+						return d.Substring(0, 12) + "GMT" + d.Substring(12, 3) + ":" +  d.Substring(15, 2);
+					}
+				}
+			}
+        }
+
+		[Obsolete("Use 'AdjustedTimeString' property instead")]
+		public string AdjustedTime
+		{
+			get { return AdjustedTimeString; }
+		}
+
+		/// <summary>
+		/// Return a time string as an adjusted date with a 4 digit year.
+		/// This goes in the range of 1950 - 2049.
+		/// </summary>
+		public string AdjustedTimeString
+		{
+			get
+			{
+				string d = TimeString;
+				string c = d[0] < '5' ? "20" : "19";
+
+				return c + d;
+			}
+		}
+
+        private byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(time);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.UtcTime, GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerUtcTime other = asn1Object as DerUtcTime;
+
+			if (other == null)
+				return false;
+
+			return this.time.Equals(other.time);
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+            return time.GetHashCode();
+        }
+
+		public override string ToString()
+		{
+			return time;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerUTF8String.cs b/BouncyCastle.AxCrypt/src/asn1/DerUTF8String.cs
new file mode 100644
index 0000000..92a50e8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerUTF8String.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der UTF8String object.
+     */
+    public class DerUtf8String
+        : DerStringBase
+    {
+        private readonly string str;
+
+		/**
+         * return an UTF8 string from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerUtf8String GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerUtf8String)
+            {
+                return (DerUtf8String)obj;
+            }
+
+			throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return an UTF8 string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerUtf8String GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerUtf8String)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerUtf8String(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+        /**
+         * basic constructor - byte encoded string.
+         */
+        public DerUtf8String(
+            byte[] str)
+			: this(Encoding.UTF8.GetString(str, 0, str.Length))
+        {
+        }
+
+		/**
+         * basic constructor
+         */
+        public DerUtf8String(
+            string str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerUtf8String other = asn1Object as DerUtf8String;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		internal override void Encode(
+			DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.Utf8String, Encoding.UTF8.GetBytes(str));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerUniversalString.cs b/BouncyCastle.AxCrypt/src/asn1/DerUniversalString.cs
new file mode 100644
index 0000000..305102f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerUniversalString.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der UniversalString object.
+     */
+    public class DerUniversalString
+        : DerStringBase
+    {
+        private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+		private readonly byte[] str;
+
+		/**
+         * return a Universal string from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerUniversalString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerUniversalString)
+            {
+                return (DerUniversalString)obj;
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return a Universal string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerUniversalString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+			Asn1Object o = obj.GetObject();
+
+			if (isExplicit || o is DerUniversalString)
+			{
+				return GetInstance(o);
+			}
+
+			return new DerUniversalString(Asn1OctetString.GetInstance(o).GetOctets());
+        }
+
+        /**
+         * basic constructor - byte encoded string.
+         */
+        public DerUniversalString(
+            byte[] str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+        public override string GetString()
+        {
+			StringBuilder buffer = new StringBuilder("#");
+			byte[] enc = GetDerEncoded();
+
+			for (int i = 0; i != enc.Length; i++)
+			{
+				uint ubyte = enc[i];
+				buffer.Append(table[(ubyte >> 4) & 0xf]);
+				buffer.Append(table[enc[i] & 0xf]);
+			}
+
+            return buffer.ToString();
+        }
+
+		public byte[] GetOctets()
+        {
+            return (byte[]) str.Clone();
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.UniversalString, this.str);
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerUniversalString other = asn1Object as DerUniversalString;
+
+			if (other == null)
+				return false;
+
+//			return this.GetString().Equals(other.GetString());
+			return Arrays.AreEqual(this.str, other.str);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerUnknownTag.cs b/BouncyCastle.AxCrypt/src/asn1/DerUnknownTag.cs
new file mode 100644
index 0000000..1e0e614
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerUnknownTag.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * We insert one of these when we find a tag we don't recognise.
+     */
+    public class DerUnknownTag
+        : Asn1Object
+    {
+		private readonly bool	isConstructed;
+        private readonly int	tag;
+        private readonly byte[]	data;
+
+        /**
+         * @param tag the tag value.
+         * @param data the contents octets.
+         */
+        public DerUnknownTag(
+            int		tag,
+            byte[]	data)
+			: this(false, tag, data)
+        {
+        }
+
+		public DerUnknownTag(
+			bool	isConstructed,
+			int		tag,
+			byte[]	data)
+		{
+			if (data == null)
+				throw new ArgumentNullException("data");
+
+			this.isConstructed = isConstructed;
+			this.tag = tag;
+			this.data = data;
+		}
+
+		public bool IsConstructed
+		{
+			get { return isConstructed; }
+		}
+
+		public int Tag
+        {
+			get { return tag; }
+        }
+
+		public byte[] GetData()
+        {
+            return data;
+        }
+
+        internal override void Encode(
+            DerOutputStream derOut)
+        {
+			derOut.WriteEncoded(isConstructed ? Asn1Tags.Constructed : 0, tag, data);
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerUnknownTag other = asn1Object as DerUnknownTag;
+
+			if (other == null)
+				return false;
+
+			return this.isConstructed == other.isConstructed
+				&& this.tag == other.tag
+				&& Arrays.AreEqual(this.data, other.data);
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+			return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(data);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/DerVisibleString.cs b/BouncyCastle.AxCrypt/src/asn1/DerVisibleString.cs
new file mode 100644
index 0000000..84c9caa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/DerVisibleString.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * Der VisibleString object.
+     */
+    public class DerVisibleString
+        : DerStringBase
+    {
+        private readonly string str;
+
+        /**
+         * return a Visible string from the passed in object.
+         *
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static DerVisibleString GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DerVisibleString)
+            {
+                return (DerVisibleString)obj;
+            }
+
+            if (obj is Asn1OctetString)
+            {
+                return new DerVisibleString(((Asn1OctetString)obj).GetOctets());
+            }
+
+            if (obj is Asn1TaggedObject)
+            {
+                return GetInstance(((Asn1TaggedObject)obj).GetObject());
+            }
+
+            throw new ArgumentException("illegal object in GetInstance: " + obj.GetType().Name);
+        }
+
+        /**
+         * return a Visible string from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the tagged object cannot
+         *               be converted.
+         */
+        public static DerVisibleString GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(obj.GetObject());
+        }
+
+        /**
+         * basic constructor - byte encoded string.
+         */
+        public DerVisibleString(
+            byte[] str)
+			: this(Strings.FromAsciiByteArray(str))
+        {
+        }
+
+		/**
+         * basic constructor
+         */
+        public DerVisibleString(
+            string str)
+        {
+			if (str == null)
+				throw new ArgumentNullException("str");
+
+			this.str = str;
+        }
+
+		public override string GetString()
+        {
+            return str;
+        }
+
+		public byte[] GetOctets()
+        {
+            return Strings.ToAsciiByteArray(str);
+        }
+
+		internal override void Encode(
+            DerOutputStream derOut)
+        {
+            derOut.WriteEncoded(Asn1Tags.VisibleString, GetOctets());
+        }
+
+		protected override bool Asn1Equals(
+			Asn1Object asn1Object)
+		{
+			DerVisibleString other = asn1Object as DerVisibleString;
+
+			if (other == null)
+				return false;
+
+			return this.str.Equals(other.str);
+        }
+
+		protected override int Asn1GetHashCode()
+		{
+            return this.str.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/IAsn1ApplicationSpecificParser.cs b/BouncyCastle.AxCrypt/src/asn1/IAsn1ApplicationSpecificParser.cs
new file mode 100644
index 0000000..89cf64c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/IAsn1ApplicationSpecificParser.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public interface IAsn1ApplicationSpecificParser
+    	: IAsn1Convertible
+	{
+    	IAsn1Convertible ReadObject();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/IAsn1Choice.cs b/BouncyCastle.AxCrypt/src/asn1/IAsn1Choice.cs
new file mode 100644
index 0000000..ecd76e4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/IAsn1Choice.cs
@@ -0,0 +1,17 @@
+
+namespace Org.BouncyCastle.Asn1
+{
+	/**
+	 * Marker interface for CHOICE objects - if you implement this in a roll-your-own
+	 * object, any attempt to tag the object implicitly will convert the tag to an
+	 * explicit one as the encoding rules require.
+	 * <p>
+	 * If you use this interface your class should also implement the getInstance
+	 * pattern which takes a tag object and the tagging mode used. 
+	 * </p>
+	 */
+	public interface IAsn1Choice
+	{
+		// marker interface
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/IAsn1Convertible.cs b/BouncyCastle.AxCrypt/src/asn1/IAsn1Convertible.cs
new file mode 100644
index 0000000..d3f83af
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/IAsn1Convertible.cs
@@ -0,0 +1,7 @@
+namespace Org.BouncyCastle.Asn1
+{
+	public interface IAsn1Convertible
+	{
+		Asn1Object ToAsn1Object();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/IAsn1String.cs b/BouncyCastle.AxCrypt/src/asn1/IAsn1String.cs
new file mode 100644
index 0000000..cbc2635
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/IAsn1String.cs
@@ -0,0 +1,10 @@
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * basic interface for Der string objects.
+     */
+    public interface IAsn1String
+    {
+        string GetString();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/IndefiniteLengthInputStream.cs b/BouncyCastle.AxCrypt/src/asn1/IndefiniteLengthInputStream.cs
new file mode 100644
index 0000000..09d0e3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/IndefiniteLengthInputStream.cs
@@ -0,0 +1,170 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	class IndefiniteLengthInputStream
+		: LimitedInputStream
+	{
+        private int _lookAhead;
+        private bool _eofOn00 = true;
+
+		internal IndefiniteLengthInputStream(
+			Stream	inStream,
+			int		limit)
+			: base(inStream, limit)
+		{
+            _lookAhead = RequireByte();
+            CheckForEof();
+		}
+
+		internal void SetEofOn00(
+			bool eofOn00)
+		{
+			_eofOn00 = eofOn00;
+            if (_eofOn00)
+            {
+                CheckForEof();
+            }
+        }
+
+        private bool CheckForEof()
+		{
+            if (_lookAhead == 0x00)
+            {
+                int extra = RequireByte();
+                if (extra != 0)
+                {
+                    throw new IOException("malformed end-of-contents marker");
+                }
+
+                _lookAhead = -1;
+                SetParentEofDetect(true);
+                return true;
+            }
+            return _lookAhead < 0;
+        }
+
+		public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			// Only use this optimisation if we aren't checking for 00
+			if (_eofOn00 || count <= 1)
+				return base.Read(buffer, offset, count);
+
+			if (_lookAhead < 0)
+				return 0;
+
+			int numRead = _in.Read(buffer, offset + 1, count - 1);
+
+			if (numRead <= 0)
+			{
+				// Corrupted stream
+				throw new EndOfStreamException();
+			}
+
+			buffer[offset] = (byte)_lookAhead;
+			_lookAhead = RequireByte();
+
+			return numRead + 1;
+		}
+
+		public override int ReadByte()
+		{
+            if (_eofOn00 && CheckForEof())
+				return -1;
+
+            int result = _lookAhead;
+            _lookAhead = RequireByte();
+            return result;
+		}
+
+        private int RequireByte()
+        {
+            int b = _in.ReadByte();
+            if (b < 0)
+            {
+                // Corrupted stream
+                throw new EndOfStreamException();
+            }
+            return b;
+        }
+	}
+}
+
+//using System;
+//using System.IO;
+
+//namespace Org.BouncyCastle.Asn1
+//{
+//    class IndefiniteLengthInputStream
+//        : LimitedInputStream
+//    {
+//        private bool _eofReached = false;
+//        private bool _eofOn00 = true;
+
+//        internal IndefiniteLengthInputStream(
+//            Stream	inStream,
+//            int		limit)
+//            : base(inStream, limit)
+//        {
+//        }
+
+//        internal void SetEofOn00(
+//            bool eofOn00)
+//        {
+//            _eofOn00 = eofOn00;
+//        }
+
+//        public override int Read(
+//            byte[]	buffer,
+//            int		offset,
+//            int		count)
+//        {
+//            if (_eofReached)
+//                return 0;
+
+//            if (_eofOn00)
+//                return base.Read(buffer, offset, count);
+
+//            int numRead = _in.Read(buffer, offset, count);
+
+//            if (numRead <= 0)
+//                throw new EndOfStreamException();
+
+//            return numRead;
+//        }
+
+//        public override int ReadByte()
+//        {
+//            if (_eofReached)
+//                return -1;
+
+//            int b1 = _in.ReadByte();
+
+//            if (b1 < 0)
+//                throw new EndOfStreamException();
+
+//            if (b1 == 0 && _eofOn00)
+//            {
+//                int b2 = _in.ReadByte();
+
+//                if (b2 < 0)
+//                    throw new EndOfStreamException();
+
+//                if (b2 == 0)
+//                {
+//                    _eofReached = true;
+//                    SetParentEofDetect(true);
+//                    return -1;
+//                }
+
+//                throw new InvalidDataException();
+//            }
+
+//            return b1;
+//        }
+//    }
+//}
diff --git a/BouncyCastle.AxCrypt/src/asn1/LazyASN1InputStream.cs b/BouncyCastle.AxCrypt/src/asn1/LazyASN1InputStream.cs
new file mode 100644
index 0000000..4cf2305
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/LazyASN1InputStream.cs
@@ -0,0 +1,33 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+	public class LazyAsn1InputStream
+		: Asn1InputStream
+	{
+		public LazyAsn1InputStream(
+			byte[] input)
+			: base(input)
+		{
+		}
+
+		public LazyAsn1InputStream(
+			Stream inputStream)
+			: base(inputStream)
+		{
+		}
+
+		internal override DerSequence CreateDerSequence(
+			DefiniteLengthInputStream dIn)
+		{
+			return new LazyDerSequence(dIn.ToArray());
+		}
+
+		internal override DerSet CreateDerSet(
+			DefiniteLengthInputStream dIn)
+		{
+			return new LazyDerSet(dIn.ToArray());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/LazyDERSequence.cs b/BouncyCastle.AxCrypt/src/asn1/LazyDERSequence.cs
new file mode 100644
index 0000000..7301bc1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/LazyDERSequence.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Asn1
+{
+	internal class LazyDerSequence
+		: DerSequence
+	{
+		private byte[] encoded;
+
+        internal LazyDerSequence(
+			byte[] encoded)
+		{
+			this.encoded = encoded;
+		}
+
+		private void Parse()
+		{
+			lock (this)
+			{
+				if (encoded != null)
+				{
+					Asn1InputStream e = new LazyAsn1InputStream(encoded);
+
+					Asn1Object o;
+					while ((o = e.ReadObject()) != null)
+					{
+						AddObject(o);
+					}
+
+					encoded = null;
+				}
+			}
+		}
+
+		public override Asn1Encodable this[int index]
+		{
+			get
+			{
+				Parse();
+
+				return base[index];
+			}
+		}
+
+		public override IEnumerator GetEnumerator()
+		{
+			Parse();
+
+			return base.GetEnumerator();
+		}
+
+		public override int Count
+		{
+			get
+			{
+				Parse();
+
+				return base.Count;
+			}
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			lock (this)
+			{
+				if (encoded == null)
+				{
+					base.Encode(derOut);
+				}
+				else
+				{
+					derOut.WriteEncoded(Asn1Tags.Sequence | Asn1Tags.Constructed, encoded);
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/LazyDERSet.cs b/BouncyCastle.AxCrypt/src/asn1/LazyDERSet.cs
new file mode 100644
index 0000000..e6c9319
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/LazyDERSet.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Asn1
+{
+	internal class LazyDerSet
+		: DerSet
+	{
+		private byte[] encoded;
+
+        internal LazyDerSet(
+			byte[] encoded)
+		{
+			this.encoded = encoded;
+		}
+
+		private void Parse()
+		{
+			lock (this)
+			{
+				if (encoded != null)
+				{
+					Asn1InputStream e = new LazyAsn1InputStream(encoded);
+
+					Asn1Object o;
+					while ((o = e.ReadObject()) != null)
+					{
+						AddObject(o);
+					}
+
+					encoded = null;
+				}
+			}
+		}
+
+		public override Asn1Encodable this[int index]
+		{
+			get
+			{
+				Parse();
+
+				return base[index];
+			}
+		}
+
+		public override IEnumerator GetEnumerator()
+		{
+			Parse();
+
+			return base.GetEnumerator();
+		}
+
+		public override int Count
+		{
+			get
+			{
+				Parse();
+
+				return base.Count;
+			}
+		}
+
+		internal override void Encode(
+			DerOutputStream derOut)
+		{
+			lock (this)
+			{
+				if (encoded == null)
+				{
+					base.Encode(derOut);
+				}
+				else
+				{
+					derOut.WriteEncoded(Asn1Tags.Set | Asn1Tags.Constructed, encoded);
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/LimitedInputStream.cs b/BouncyCastle.AxCrypt/src/asn1/LimitedInputStream.cs
new file mode 100644
index 0000000..62486aa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/LimitedInputStream.cs
@@ -0,0 +1,35 @@
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Asn1
+{
+    internal abstract class LimitedInputStream
+        : BaseInputStream
+    {
+        protected readonly Stream _in;
+		private int _limit;
+
+        internal LimitedInputStream(
+            Stream	inStream,
+			int		limit)
+        {
+            this._in = inStream;
+			this._limit = limit;
+        }
+
+	    internal virtual int GetRemaining()
+	    {
+	        // TODO: maybe one day this can become more accurate
+	        return _limit;
+	    }
+
+		protected virtual void SetParentEofDetect(bool on)
+        {
+            if (_in is IndefiniteLengthInputStream)
+            {
+                ((IndefiniteLengthInputStream)_in).SetEofOn00(on);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/OidTokenizer.cs b/BouncyCastle.AxCrypt/src/asn1/OidTokenizer.cs
new file mode 100644
index 0000000..6e76e8c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/OidTokenizer.cs
@@ -0,0 +1,45 @@
+namespace Org.BouncyCastle.Asn1
+{
+    /**
+     * class for breaking up an Oid into it's component tokens, ala
+     * java.util.StringTokenizer. We need this class as some of the
+     * lightweight Java environment don't support classes like
+     * StringTokenizer.
+     */
+    public class OidTokenizer
+    {
+        private string  oid;
+        private int     index;
+
+		public OidTokenizer(
+            string oid)
+        {
+            this.oid = oid;
+        }
+
+		public bool HasMoreTokens
+        {
+			get { return index != -1; }
+        }
+
+		public string NextToken()
+        {
+            if (index == -1)
+            {
+                return null;
+            }
+
+            int end = oid.IndexOf('.', index);
+            if (end == -1)
+            {
+                string lastToken = oid.Substring(index);
+                index = -1;
+                return lastToken;
+            }
+
+            string nextToken = oid.Substring(index, end - index);
+			index = end + 1;
+            return nextToken;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/bc/BCObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/bc/BCObjectIdentifiers.cs
new file mode 100644
index 0000000..075e538
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/bc/BCObjectIdentifiers.cs
@@ -0,0 +1,39 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.BC
+{
+	public abstract class BCObjectIdentifiers
+	{
+		// iso.org.dod.internet.private.enterprise.legion-of-the-bouncy-castle
+		// 1.3.6.1.4.1.22554
+		public static readonly DerObjectIdentifier bc = new DerObjectIdentifier("1.3.6.1.4.1.22554");
+
+		// pbe(1) algorithms
+		public static readonly DerObjectIdentifier bc_pbe = new DerObjectIdentifier(bc + ".1");
+
+		// SHA-1(1)
+		public static readonly DerObjectIdentifier bc_pbe_sha1 = new DerObjectIdentifier(bc_pbe + ".1");
+
+		// SHA-2(2) . (SHA-256(1)|SHA-384(2)|SHA-512(3)|SHA-224(4))
+		public static readonly DerObjectIdentifier bc_pbe_sha256 = new DerObjectIdentifier(bc_pbe + ".2.1");
+		public static readonly DerObjectIdentifier bc_pbe_sha384 = new DerObjectIdentifier(bc_pbe + ".2.2");
+		public static readonly DerObjectIdentifier bc_pbe_sha512 = new DerObjectIdentifier(bc_pbe + ".2.3");
+		public static readonly DerObjectIdentifier bc_pbe_sha224 = new DerObjectIdentifier(bc_pbe + ".2.4");
+		
+		// PKCS-5(1)|PKCS-12(2)
+		public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs5 = new DerObjectIdentifier(bc_pbe_sha1 + ".1");
+		public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12 = new DerObjectIdentifier(bc_pbe_sha1 + ".2");
+		
+		public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs5 = new DerObjectIdentifier(bc_pbe_sha256 + ".1");
+		public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12 = new DerObjectIdentifier(bc_pbe_sha256 + ".2");
+
+		// AES(1) . (CBC-128(2)|CBC-192(22)|CBC-256(42))
+		public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.2");
+		public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.22");
+		public static readonly DerObjectIdentifier bc_pbe_sha1_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha1_pkcs12 + ".1.42");
+
+		public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes128_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.2");
+		public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes192_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.22");
+		public static readonly DerObjectIdentifier bc_pbe_sha256_pkcs12_aes256_cbc = new DerObjectIdentifier(bc_pbe_sha256_pkcs12 + ".1.42");
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CAKeyUpdAnnContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CAKeyUpdAnnContent.cs
new file mode 100644
index 0000000..3cdb128
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CAKeyUpdAnnContent.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CAKeyUpdAnnContent
+		: Asn1Encodable
+	{
+		private readonly CmpCertificate oldWithNew;
+		private readonly CmpCertificate newWithOld;
+		private readonly CmpCertificate newWithNew;
+
+		private CAKeyUpdAnnContent(Asn1Sequence seq)
+		{
+			oldWithNew = CmpCertificate.GetInstance(seq[0]);
+			newWithOld = CmpCertificate.GetInstance(seq[1]);
+			newWithNew = CmpCertificate.GetInstance(seq[2]);
+		}
+
+		public static CAKeyUpdAnnContent GetInstance(object obj)
+		{
+			if (obj is CAKeyUpdAnnContent)
+				return (CAKeyUpdAnnContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new CAKeyUpdAnnContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual CmpCertificate OldWithNew
+		{
+			get { return oldWithNew; }
+		}
+		
+		public virtual CmpCertificate NewWithOld
+		{
+			get { return newWithOld; }
+		}
+
+		public virtual CmpCertificate NewWithNew
+		{
+			get { return newWithNew; }
+		}
+
+		/**
+		 * <pre>
+		 * CAKeyUpdAnnContent ::= SEQUENCE {
+		 *                             oldWithNew   CmpCertificate, -- old pub signed with new priv
+		 *                             newWithOld   CmpCertificate, -- new pub signed with old priv
+		 *                             newWithNew   CmpCertificate  -- new pub signed with new priv
+		 *  }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(oldWithNew, newWithOld, newWithNew);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertConfirmContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertConfirmContent.cs
new file mode 100644
index 0000000..f4016d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertConfirmContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertConfirmContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private CertConfirmContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static CertConfirmContent GetInstance(object obj)
+		{
+			if (obj is CertConfirmContent)
+				return (CertConfirmContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new CertConfirmContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual CertStatus[] ToCertStatusArray()
+		{
+			CertStatus[] result = new CertStatus[content.Count];
+			for (int i = 0; i != result.Length; i++)
+			{
+				result[i] = CertStatus.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * CertConfirmContent ::= SEQUENCE OF CertStatus
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertOrEncCert.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertOrEncCert.cs
new file mode 100644
index 0000000..4c049c1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertOrEncCert.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertOrEncCert
+		: Asn1Encodable, IAsn1Choice
+	{
+		private readonly CmpCertificate certificate;
+		private readonly EncryptedValue encryptedCert;
+
+		private CertOrEncCert(Asn1TaggedObject tagged)
+		{
+			if (tagged.TagNo == 0)
+			{
+				certificate = CmpCertificate.GetInstance(tagged.GetObject());
+			}
+			else if (tagged.TagNo == 1)
+			{
+				encryptedCert = EncryptedValue.GetInstance(tagged.GetObject());
+			}
+			else
+			{
+				throw new ArgumentException("unknown tag: " + tagged.TagNo, "tagged");
+			}
+		}
+		
+		public static CertOrEncCert GetInstance(object obj)
+		{
+			if (obj is CertOrEncCert)
+				return (CertOrEncCert)obj;
+
+			if (obj is Asn1TaggedObject)
+				return new CertOrEncCert((Asn1TaggedObject)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public CertOrEncCert(CmpCertificate certificate)
+		{
+			if (certificate == null)
+				throw new ArgumentNullException("certificate");
+
+			this.certificate = certificate;
+		}
+
+		public CertOrEncCert(EncryptedValue encryptedCert)
+		{
+			if (encryptedCert == null)
+				throw new ArgumentNullException("encryptedCert");
+
+			this.encryptedCert = encryptedCert;
+		}
+
+		public virtual CmpCertificate Certificate
+		{
+			get { return certificate; }
+		}
+
+		public virtual EncryptedValue EncryptedCert
+		{
+			get { return encryptedCert; }
+		}
+
+		/**
+		 * <pre>
+		 * CertOrEncCert ::= CHOICE {
+		 *                      certificate     [0] CMPCertificate,
+		 *                      encryptedCert   [1] EncryptedValue
+		 *           }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			if (certificate != null)
+			{
+				return new DerTaggedObject(true, 0, certificate);
+			}
+
+			return new DerTaggedObject(true, 1, encryptedCert);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertRepMessage.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertRepMessage.cs
new file mode 100644
index 0000000..c22b079
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertRepMessage.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertRepMessage
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence caPubs;
+		private readonly Asn1Sequence response;
+		
+		private CertRepMessage(Asn1Sequence seq)
+		{
+			int index = 0;
+
+			if (seq.Count > 1)
+			{
+				caPubs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[index++], true);
+			}
+
+			response = Asn1Sequence.GetInstance(seq[index]);
+		}
+
+		public static CertRepMessage GetInstance(object obj)
+		{
+			if (obj is CertRepMessage)
+				return (CertRepMessage)obj;
+
+			if (obj is Asn1Sequence)
+				return new CertRepMessage((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public CertRepMessage(CmpCertificate[] caPubs, CertResponse[] response)
+		{
+			if (response == null)
+				throw new ArgumentNullException("response");
+
+			if (caPubs != null)
+			{
+				this.caPubs = new DerSequence(caPubs);
+			}
+
+			this.response = new DerSequence(response);
+		}
+
+		public virtual CmpCertificate[] GetCAPubs()
+		{
+			if (caPubs == null)
+				return null;
+
+			CmpCertificate[] results = new CmpCertificate[caPubs.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CmpCertificate.GetInstance(caPubs[i]);
+			}
+			return results;
+		}
+
+		public virtual CertResponse[] GetResponse()
+		{
+			CertResponse[] results = new CertResponse[response.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CertResponse.GetInstance(response[i]);
+			}
+			return results;
+		}
+
+		/**
+		 * <pre>
+		 * CertRepMessage ::= SEQUENCE {
+		 *                          caPubs       [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+		 *                                                                             OPTIONAL,
+		 *                          response         SEQUENCE OF CertResponse
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (caPubs != null)
+			{
+				v.Add(new DerTaggedObject(true, 1, caPubs));
+			}
+
+			v.Add(response);
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertResponse.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertResponse.cs
new file mode 100644
index 0000000..246b8ce
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertResponse.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertResponse
+		: Asn1Encodable
+	{
+		private readonly DerInteger certReqId;
+		private readonly PkiStatusInfo status;
+		private readonly CertifiedKeyPair certifiedKeyPair;
+		private readonly Asn1OctetString rspInfo;
+
+		private CertResponse(Asn1Sequence seq)
+		{
+			certReqId = DerInteger.GetInstance(seq[0]);
+			status = PkiStatusInfo.GetInstance(seq[1]);
+
+			if (seq.Count >= 3)
+			{
+				if (seq.Count == 3)
+				{
+					Asn1Encodable o = seq[2];
+					if (o is Asn1OctetString)
+					{
+						rspInfo = Asn1OctetString.GetInstance(o);
+					}
+					else
+					{
+						certifiedKeyPair = CertifiedKeyPair.GetInstance(o);
+					}
+				}
+				else
+				{
+					certifiedKeyPair = CertifiedKeyPair.GetInstance(seq[2]);
+					rspInfo = Asn1OctetString.GetInstance(seq[3]);
+				}
+			}
+		}
+
+		public static CertResponse GetInstance(object obj)
+		{
+			if (obj is CertResponse)
+				return (CertResponse)obj;
+
+			if (obj is Asn1Sequence)
+				return new CertResponse((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public CertResponse(
+			DerInteger certReqId,
+			PkiStatusInfo status)
+			: this(certReqId, status, null, null)
+		{
+		}
+
+		public CertResponse(
+			DerInteger			certReqId,
+			PkiStatusInfo		status,
+			CertifiedKeyPair	certifiedKeyPair,
+			Asn1OctetString		rspInfo)
+		{
+			if (certReqId == null)
+				throw new ArgumentNullException("certReqId");
+
+			if (status == null)
+				throw new ArgumentNullException("status");
+
+			this.certReqId = certReqId;
+			this.status = status;
+			this.certifiedKeyPair = certifiedKeyPair;
+			this.rspInfo = rspInfo;
+		}
+
+		public virtual DerInteger CertReqID
+		{
+			get { return certReqId; }
+		}
+
+		public virtual PkiStatusInfo Status
+		{
+			get { return status; }
+		}
+
+		public virtual CertifiedKeyPair CertifiedKeyPair
+		{
+			get { return certifiedKeyPair; }
+		}
+
+		/**
+		 * <pre>
+		 * CertResponse ::= SEQUENCE {
+		 *                            certReqId           INTEGER,
+		 *                            -- to match this response with corresponding request (a value
+		 *                            -- of -1 is to be used if certReqId is not specified in the
+		 *                            -- corresponding request)
+		 *                            status              PKIStatusInfo,
+		 *                            certifiedKeyPair    CertifiedKeyPair    OPTIONAL,
+		 *                            rspInfo             OCTET STRING        OPTIONAL
+		 *                            -- analogous to the id-regInfo-utf8Pairs string defined
+		 *                            -- for regInfo in CertReqMsg [CRMF]
+		 *             }
+		 * </pre> 
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certReqId, status);
+			v.AddOptional(certifiedKeyPair);
+			v.AddOptional(rspInfo);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertStatus.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertStatus.cs
new file mode 100644
index 0000000..52d5ac5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertStatus.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertStatus
+		: Asn1Encodable
+	{
+		private readonly Asn1OctetString certHash;
+		private readonly DerInteger certReqId;
+		private readonly PkiStatusInfo statusInfo;
+
+		private CertStatus(Asn1Sequence seq)
+		{
+			certHash = Asn1OctetString.GetInstance(seq[0]);
+			certReqId = DerInteger.GetInstance(seq[1]);
+
+			if (seq.Count > 2)
+			{
+				statusInfo = PkiStatusInfo.GetInstance(seq[2]);
+			}
+		}
+
+		public CertStatus(byte[] certHash, BigInteger certReqId)
+		{
+			this.certHash = new DerOctetString(certHash);
+			this.certReqId = new DerInteger(certReqId);
+		}
+
+		public CertStatus(byte[] certHash, BigInteger certReqId, PkiStatusInfo statusInfo)
+		{
+			this.certHash = new DerOctetString(certHash);
+			this.certReqId = new DerInteger(certReqId);
+			this.statusInfo = statusInfo;
+		}
+
+		public static CertStatus GetInstance(object obj)
+		{
+			if (obj is CertStatus)
+				return (CertStatus)obj;
+
+			if (obj is Asn1Sequence)
+				return new CertStatus((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual Asn1OctetString CertHash
+		{
+			get { return certHash; }
+		}
+
+		public virtual DerInteger CertReqID
+		{
+			get { return certReqId; }
+		}
+
+		public virtual PkiStatusInfo StatusInfo
+		{
+			get { return statusInfo; }
+		}
+
+		/**
+		 * <pre>
+		 * CertStatus ::= SEQUENCE {
+		 *                   certHash    OCTET STRING,
+		 *                   -- the hash of the certificate, using the same hash algorithm
+		 *                   -- as is used to create and verify the certificate signature
+		 *                   certReqId   INTEGER,
+		 *                   -- to match this confirmation with the corresponding req/rep
+		 *                   statusInfo  PKIStatusInfo OPTIONAL
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certHash, certReqId);
+			v.AddOptional(statusInfo);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CertifiedKeyPair.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CertifiedKeyPair.cs
new file mode 100644
index 0000000..655dde0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CertifiedKeyPair.cs
@@ -0,0 +1,114 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CertifiedKeyPair
+		: Asn1Encodable
+	{
+		private readonly CertOrEncCert certOrEncCert;
+		private readonly EncryptedValue privateKey;
+		private readonly PkiPublicationInfo publicationInfo;
+
+		private CertifiedKeyPair(Asn1Sequence seq)
+		{
+			certOrEncCert = CertOrEncCert.GetInstance(seq[0]);
+
+			if (seq.Count >= 2)
+			{
+				if (seq.Count == 2)
+				{
+					Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1]);
+					if (tagged.TagNo == 0)
+					{
+						privateKey = EncryptedValue.GetInstance(tagged.GetObject());
+					}
+					else
+					{
+						publicationInfo = PkiPublicationInfo.GetInstance(tagged.GetObject());
+					}
+				}
+				else
+				{
+					privateKey = EncryptedValue.GetInstance(Asn1TaggedObject.GetInstance(seq[1]));
+					publicationInfo = PkiPublicationInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[2]));
+				}
+			}
+		}
+
+		public static CertifiedKeyPair GetInstance(object obj)
+		{
+			if (obj is CertifiedKeyPair)
+				return (CertifiedKeyPair)obj;
+
+			if (obj is Asn1Sequence)
+				return new CertifiedKeyPair((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public CertifiedKeyPair(
+			CertOrEncCert certOrEncCert)
+			: this(certOrEncCert, null, null)
+		{
+		}
+
+		public CertifiedKeyPair(
+			CertOrEncCert		certOrEncCert,
+			EncryptedValue		privateKey,
+			PkiPublicationInfo	publicationInfo
+		)
+		{
+			if (certOrEncCert == null)
+				throw new ArgumentNullException("certOrEncCert");
+
+			this.certOrEncCert = certOrEncCert;
+			this.privateKey = privateKey;
+			this.publicationInfo = publicationInfo;
+		}
+
+		public virtual CertOrEncCert CertOrEncCert
+		{
+			get { return certOrEncCert; }
+		}
+
+		public virtual EncryptedValue PrivateKey
+		{
+			get { return privateKey; }
+		}
+
+		public virtual PkiPublicationInfo PublicationInfo
+		{
+			get { return publicationInfo; }
+		}
+
+		/**
+		 * <pre>
+		 * CertifiedKeyPair ::= SEQUENCE {
+		 *                                  certOrEncCert       CertOrEncCert,
+		 *                                  privateKey      [0] EncryptedValue      OPTIONAL,
+		 *                                  -- see [CRMF] for comment on encoding
+		 *                                  publicationInfo [1] PKIPublicationInfo  OPTIONAL
+		 *       }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certOrEncCert);
+
+			if (privateKey != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, privateKey));
+			}
+
+			if (publicationInfo != null)
+			{
+				v.Add(new DerTaggedObject(true, 1, publicationInfo));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/Challenge.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/Challenge.cs
new file mode 100644
index 0000000..bee5f96
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/Challenge.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class Challenge
+		: Asn1Encodable
+	{
+		private readonly AlgorithmIdentifier owf;
+		private readonly Asn1OctetString witness;
+		private readonly Asn1OctetString challenge;
+
+		private Challenge(Asn1Sequence seq)
+		{
+			int index = 0;
+
+			if (seq.Count == 3)
+			{
+				owf = AlgorithmIdentifier.GetInstance(seq[index++]);
+			}
+
+			witness = Asn1OctetString.GetInstance(seq[index++]);
+			challenge = Asn1OctetString.GetInstance(seq[index]);
+		}
+
+		public static Challenge GetInstance(object obj)
+		{
+			if (obj is Challenge)
+				return (Challenge)obj;
+
+			if (obj is Asn1Sequence)
+				return new Challenge((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual AlgorithmIdentifier Owf
+		{
+			get { return owf; }
+		}
+
+		/**
+		 * <pre>
+		 * Challenge ::= SEQUENCE {
+		 *                 owf                 AlgorithmIdentifier  OPTIONAL,
+		 *
+		 *                 -- MUST be present in the first Challenge; MAY be omitted in
+		 *                 -- any subsequent Challenge in POPODecKeyChallContent (if
+		 *                 -- omitted, then the owf used in the immediately preceding
+		 *                 -- Challenge is to be used).
+		 *
+		 *                 witness             OCTET STRING,
+		 *                 -- the result of applying the one-way function (owf) to a
+		 *                 -- randomly-generated INTEGER, A.  [Note that a different
+		 *                 -- INTEGER MUST be used for each Challenge.]
+		 *                 challenge           OCTET STRING
+		 *                 -- the encryption (under the public key for which the cert.
+		 *                 -- request is being made) of Rand, where Rand is specified as
+		 *                 --   Rand ::= SEQUENCE {
+		 *                 --      int      INTEGER,
+		 *                 --       - the randomly-generated INTEGER A (above)
+		 *                 --      sender   GeneralName
+		 *                 --       - the sender's name (as included in PKIHeader)
+		 *                 --   }
+		 *      }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+			v.AddOptional(owf);
+			v.Add(witness);
+			v.Add(challenge);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CmpCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CmpCertificate.cs
new file mode 100644
index 0000000..16ee300
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CmpCertificate.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class CmpCertificate
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly X509CertificateStructure x509v3PKCert;
+        private readonly AttributeCertificate x509v2AttrCert;
+
+        /**
+         * Note: the addition of attribute certificates is a BC extension.
+         */
+        public CmpCertificate(AttributeCertificate x509v2AttrCert)
+        {
+            this.x509v2AttrCert = x509v2AttrCert;
+        }
+
+        public CmpCertificate(X509CertificateStructure x509v3PKCert)
+        {
+            if (x509v3PKCert.Version != 3)
+                throw new ArgumentException("only version 3 certificates allowed", "x509v3PKCert");
+
+            this.x509v3PKCert = x509v3PKCert;
+        }
+
+        public static CmpCertificate GetInstance(object obj)
+        {
+            if (obj is CmpCertificate)
+                return (CmpCertificate)obj;
+
+            if (obj is Asn1Sequence)
+                return new CmpCertificate(X509CertificateStructure.GetInstance(obj));
+
+            if (obj is Asn1TaggedObject)
+                return new CmpCertificate(AttributeCertificate.GetInstance(((Asn1TaggedObject)obj).GetObject()));
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public virtual bool IsX509v3PKCert
+        {
+            get { return x509v3PKCert != null; }
+        }
+
+        public virtual X509CertificateStructure X509v3PKCert
+        {
+            get { return x509v3PKCert; }
+        }
+
+        public virtual AttributeCertificate X509v2AttrCert
+        {
+            get { return x509v2AttrCert; }
+        }
+
+        /**
+         * <pre>
+         * CMPCertificate ::= CHOICE {
+         *            x509v3PKCert        Certificate
+         *            x509v2AttrCert      [1] AttributeCertificate
+         *  }
+         * </pre>
+         * Note: the addition of attribute certificates is a BC extension.
+         *
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            if (x509v2AttrCert != null)
+            {
+                // explicit following CMP conventions
+                return new DerTaggedObject(true, 1, x509v2AttrCert);
+            }
+
+            return x509v3PKCert.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CmpObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CmpObjectIdentifiers.cs
new file mode 100644
index 0000000..7e82741
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CmpObjectIdentifiers.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public abstract class CmpObjectIdentifiers
+	{
+		// RFC 4210
+
+		// id-PasswordBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 13}
+		public static readonly DerObjectIdentifier passwordBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.13");
+
+		// id-DHBasedMac OBJECT IDENTIFIER ::= {1 2 840 113533 7 66 30}
+		public static readonly DerObjectIdentifier dhBasedMac = new DerObjectIdentifier("1.2.840.113533.7.66.30");
+
+		// Example InfoTypeAndValue contents include, but are not limited
+		// to, the following (un-comment in this ASN.1 module and use as
+		// appropriate for a given environment):
+		//
+		// id-it-caProtEncCert OBJECT IDENTIFIER ::= {id-it 1}
+		// CAProtEncCertValue ::= CMPCertificate
+		// id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+		// SignKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+		// id-it-encKeyPairTypes OBJECT IDENTIFIER ::= {id-it 3}
+		// EncKeyPairTypesValue ::= SEQUENCE OF AlgorithmIdentifier
+		// id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+		// PreferredSymmAlgValue ::= AlgorithmIdentifier
+		// id-it-caKeyUpdateInfo OBJECT IDENTIFIER ::= {id-it 5}
+		// CAKeyUpdateInfoValue ::= CAKeyUpdAnnContent
+		// id-it-currentCRL OBJECT IDENTIFIER ::= {id-it 6}
+		// CurrentCRLValue ::= CertificateList
+		// id-it-unsupportedOIDs OBJECT IDENTIFIER ::= {id-it 7}
+		// UnsupportedOIDsValue ::= SEQUENCE OF OBJECT IDENTIFIER
+		// id-it-keyPairParamReq OBJECT IDENTIFIER ::= {id-it 10}
+		// KeyPairParamReqValue ::= OBJECT IDENTIFIER
+		// id-it-keyPairParamRep OBJECT IDENTIFIER ::= {id-it 11}
+		// KeyPairParamRepValue ::= AlgorithmIdentifer
+		// id-it-revPassphrase OBJECT IDENTIFIER ::= {id-it 12}
+		// RevPassphraseValue ::= EncryptedValue
+		// id-it-implicitConfirm OBJECT IDENTIFIER ::= {id-it 13}
+		// ImplicitConfirmValue ::= NULL
+		// id-it-confirmWaitTime OBJECT IDENTIFIER ::= {id-it 14}
+		// ConfirmWaitTimeValue ::= GeneralizedTime
+		// id-it-origPKIMessage OBJECT IDENTIFIER ::= {id-it 15}
+		// OrigPKIMessageValue ::= PKIMessages
+		// id-it-suppLangTags OBJECT IDENTIFIER ::= {id-it 16}
+		// SuppLangTagsValue ::= SEQUENCE OF UTF8String
+		//
+		// where
+		//
+		// id-pkix OBJECT IDENTIFIER ::= {
+		// iso(1) identified-organization(3)
+		// dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+		// and
+		// id-it OBJECT IDENTIFIER ::= {id-pkix 4}
+		public static readonly DerObjectIdentifier it_caProtEncCert = new DerObjectIdentifier("1.3.6.1.5.5.7.4.1");
+		public static readonly DerObjectIdentifier it_signKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.2");
+		public static readonly DerObjectIdentifier it_encKeyPairTypes = new DerObjectIdentifier("1.3.6.1.5.5.7.4.3");
+		public static readonly DerObjectIdentifier it_preferredSymAlg = new DerObjectIdentifier("1.3.6.1.5.5.7.4.4");
+		public static readonly DerObjectIdentifier it_caKeyUpdateInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.4.5");
+		public static readonly DerObjectIdentifier it_currentCRL = new DerObjectIdentifier("1.3.6.1.5.5.7.4.6");
+		public static readonly DerObjectIdentifier it_unsupportedOIDs = new DerObjectIdentifier("1.3.6.1.5.5.7.4.7");
+		public static readonly DerObjectIdentifier it_keyPairParamReq = new DerObjectIdentifier("1.3.6.1.5.5.7.4.10");
+		public static readonly DerObjectIdentifier it_keyPairParamRep = new DerObjectIdentifier("1.3.6.1.5.5.7.4.11");
+		public static readonly DerObjectIdentifier it_revPassphrase = new DerObjectIdentifier("1.3.6.1.5.5.7.4.12");
+		public static readonly DerObjectIdentifier it_implicitConfirm = new DerObjectIdentifier("1.3.6.1.5.5.7.4.13");
+		public static readonly DerObjectIdentifier it_confirmWaitTime = new DerObjectIdentifier("1.3.6.1.5.5.7.4.14");
+		public static readonly DerObjectIdentifier it_origPKIMessage = new DerObjectIdentifier("1.3.6.1.5.5.7.4.15");
+		public static readonly DerObjectIdentifier it_suppLangTags = new DerObjectIdentifier("1.3.6.1.5.5.7.4.16");
+
+		// RFC 4211
+
+		// id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+		// dod(6) internet(1) security(5) mechanisms(5) pkix(7) }
+		//
+		// arc for Internet X.509 PKI protocols and their components
+		// id-pkip OBJECT IDENTIFIER :: { id-pkix pkip(5) }
+		//
+		// arc for Registration Controls in CRMF
+		// id-regCtrl OBJECT IDENTIFIER ::= { id-pkip regCtrl(1) }
+		//
+		// arc for Registration Info in CRMF
+		// id-regInfo OBJECT IDENTIFIER ::= { id-pkip id-regInfo(2) }
+
+		public static readonly DerObjectIdentifier regCtrl_regToken = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.1");
+		public static readonly DerObjectIdentifier regCtrl_authenticator = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.2");
+		public static readonly DerObjectIdentifier regCtrl_pkiPublicationInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.3");
+		public static readonly DerObjectIdentifier regCtrl_pkiArchiveOptions = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.4");
+		public static readonly DerObjectIdentifier regCtrl_oldCertID = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.5");
+		public static readonly DerObjectIdentifier regCtrl_protocolEncrKey = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.6");
+
+		// From RFC4210:
+		// id-regCtrl-altCertTemplate OBJECT IDENTIFIER ::= {id-regCtrl 7}
+		public static readonly DerObjectIdentifier regCtrl_altCertTemplate = new DerObjectIdentifier("1.3.6.1.5.5.7.5.1.7");
+
+		public static readonly DerObjectIdentifier regInfo_utf8Pairs = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.1");
+		public static readonly DerObjectIdentifier regInfo_certReq = new DerObjectIdentifier("1.3.6.1.5.5.7.5.2.2");
+
+		// id-smime OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+		// us(840) rsadsi(113549) pkcs(1) pkcs9(9) 16 }
+		//
+		// id-ct OBJECT IDENTIFIER ::= { id-smime 1 } -- content types
+		//
+		// id-ct-encKeyWithID OBJECT IDENTIFIER ::= {id-ct 21}
+		public static readonly DerObjectIdentifier ct_encKeyWithID = new DerObjectIdentifier("1.2.840.113549.1.9.16.1.21");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/CrlAnnContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/CrlAnnContent.cs
new file mode 100644
index 0000000..3dc11d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/CrlAnnContent.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class CrlAnnContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private CrlAnnContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static CrlAnnContent GetInstance(object obj)
+		{
+			if (obj is CrlAnnContent)
+				return (CrlAnnContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new CrlAnnContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual CertificateList[] ToCertificateListArray()
+		{
+			CertificateList[] result = new CertificateList[content.Count];
+			for (int i = 0; i != result.Length; ++ i)
+			{
+				result[i] = CertificateList.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * CrlAnnContent ::= SEQUENCE OF CertificateList
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/ErrorMsgContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/ErrorMsgContent.cs
new file mode 100644
index 0000000..f4dc584
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/ErrorMsgContent.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class ErrorMsgContent
+		: Asn1Encodable
+	{
+		private readonly PkiStatusInfo pkiStatusInfo;
+		private readonly DerInteger errorCode;
+		private readonly PkiFreeText errorDetails;
+
+		private ErrorMsgContent(Asn1Sequence seq)
+		{
+			pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+
+			for (int pos = 1; pos < seq.Count; ++pos)
+			{
+				Asn1Encodable ae = seq[pos];
+				if (ae is DerInteger)
+				{
+					errorCode = DerInteger.GetInstance(ae);
+				}
+				else
+				{
+					errorDetails = PkiFreeText.GetInstance(ae);
+				}
+			}
+		}
+
+		public static ErrorMsgContent GetInstance(object obj)
+		{
+			if (obj is ErrorMsgContent)
+				return (ErrorMsgContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new ErrorMsgContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public ErrorMsgContent(PkiStatusInfo pkiStatusInfo)
+			: this(pkiStatusInfo, null, null)
+		{
+		}
+
+		public ErrorMsgContent(
+			PkiStatusInfo	pkiStatusInfo,
+			DerInteger		errorCode,
+			PkiFreeText		errorDetails)
+		{
+			if (pkiStatusInfo == null)
+				throw new ArgumentNullException("pkiStatusInfo");
+
+			this.pkiStatusInfo = pkiStatusInfo;
+			this.errorCode = errorCode;
+			this.errorDetails = errorDetails;
+		}
+		
+		public virtual PkiStatusInfo PkiStatusInfo
+		{
+			get { return pkiStatusInfo; }
+		}
+
+		public virtual DerInteger ErrorCode
+		{
+			get { return errorCode; }
+		}
+
+		public virtual PkiFreeText ErrorDetails
+		{
+			get { return errorDetails; }
+		}
+
+		/**
+		 * <pre>
+		 * ErrorMsgContent ::= SEQUENCE {
+		 *                        pKIStatusInfo          PKIStatusInfo,
+		 *                        errorCode              INTEGER           OPTIONAL,
+		 *                        -- implementation-specific error codes
+		 *                        errorDetails           PKIFreeText       OPTIONAL
+		 *                        -- implementation-specific error details
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
+			v.AddOptional(errorCode);
+			v.AddOptional(errorDetails);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/GenMsgContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/GenMsgContent.cs
new file mode 100644
index 0000000..9f04249
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/GenMsgContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class GenMsgContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private GenMsgContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static GenMsgContent GetInstance(object obj)
+		{
+			if (obj is GenMsgContent)
+				return (GenMsgContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new GenMsgContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public GenMsgContent(params InfoTypeAndValue[] itv)
+		{
+			content = new DerSequence(itv);
+		}
+
+		public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+		{
+			InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = InfoTypeAndValue.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * GenMsgContent ::= SEQUENCE OF InfoTypeAndValue
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/GenRepContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/GenRepContent.cs
new file mode 100644
index 0000000..5bdc555
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/GenRepContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class GenRepContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private GenRepContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static GenRepContent GetInstance(object obj)
+		{
+			if (obj is GenRepContent)
+				return (GenRepContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new GenRepContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public GenRepContent(params InfoTypeAndValue[] itv)
+		{
+			content = new DerSequence(itv);
+		}
+
+		public virtual InfoTypeAndValue[] ToInfoTypeAndValueArray()
+		{
+			InfoTypeAndValue[] result = new InfoTypeAndValue[content.Count];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = InfoTypeAndValue.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * GenRepContent ::= SEQUENCE OF InfoTypeAndValue
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/InfoTypeAndValue.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/InfoTypeAndValue.cs
new file mode 100644
index 0000000..9b51dba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/InfoTypeAndValue.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    /**
+     * Example InfoTypeAndValue contents include, but are not limited
+     * to, the following (un-comment in this ASN.1 module and use as
+     * appropriate for a given environment):
+     * <pre>
+     *   id-it-caProtEncCert    OBJECT IDENTIFIER ::= {id-it 1}
+     *      CAProtEncCertValue      ::= CMPCertificate
+     *   id-it-signKeyPairTypes OBJECT IDENTIFIER ::= {id-it 2}
+     *     SignKeyPairTypesValue   ::= SEQUENCE OF AlgorithmIdentifier
+     *   id-it-encKeyPairTypes  OBJECT IDENTIFIER ::= {id-it 3}
+     *     EncKeyPairTypesValue    ::= SEQUENCE OF AlgorithmIdentifier
+     *   id-it-preferredSymmAlg OBJECT IDENTIFIER ::= {id-it 4}
+     *      PreferredSymmAlgValue   ::= AlgorithmIdentifier
+     *   id-it-caKeyUpdateInfo  OBJECT IDENTIFIER ::= {id-it 5}
+     *      CAKeyUpdateInfoValue    ::= CAKeyUpdAnnContent
+     *   id-it-currentCRL       OBJECT IDENTIFIER ::= {id-it 6}
+     *      CurrentCRLValue         ::= CertificateList
+     *   id-it-unsupportedOIDs  OBJECT IDENTIFIER ::= {id-it 7}
+     *      UnsupportedOIDsValue    ::= SEQUENCE OF OBJECT IDENTIFIER
+     *   id-it-keyPairParamReq  OBJECT IDENTIFIER ::= {id-it 10}
+     *      KeyPairParamReqValue    ::= OBJECT IDENTIFIER
+     *   id-it-keyPairParamRep  OBJECT IDENTIFIER ::= {id-it 11}
+     *      KeyPairParamRepValue    ::= AlgorithmIdentifer
+     *   id-it-revPassphrase    OBJECT IDENTIFIER ::= {id-it 12}
+     *      RevPassphraseValue      ::= EncryptedValue
+     *   id-it-implicitConfirm  OBJECT IDENTIFIER ::= {id-it 13}
+     *      ImplicitConfirmValue    ::= NULL
+     *   id-it-confirmWaitTime  OBJECT IDENTIFIER ::= {id-it 14}
+     *      ConfirmWaitTimeValue    ::= GeneralizedTime
+     *   id-it-origPKIMessage   OBJECT IDENTIFIER ::= {id-it 15}
+     *      OrigPKIMessageValue     ::= PKIMessages
+     *   id-it-suppLangTags     OBJECT IDENTIFIER ::= {id-it 16}
+     *      SuppLangTagsValue       ::= SEQUENCE OF UTF8String
+     *
+     * where
+     *
+     *   id-pkix OBJECT IDENTIFIER ::= {
+     *      iso(1) identified-organization(3)
+     *      dod(6) internet(1) security(5) mechanisms(5) pkix(7)}
+     * and
+     *      id-it   OBJECT IDENTIFIER ::= {id-pkix 4}
+     * </pre>
+     */
+    public class InfoTypeAndValue
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier infoType;
+        private readonly Asn1Encodable infoValue;
+
+        private InfoTypeAndValue(Asn1Sequence seq)
+        {
+            infoType = DerObjectIdentifier.GetInstance(seq[0]);
+
+            if (seq.Count > 1)
+            {
+                infoValue = (Asn1Encodable)seq[1];
+            }
+        }
+
+        public static InfoTypeAndValue GetInstance(object obj)
+        {
+            if (obj is InfoTypeAndValue)
+                return (InfoTypeAndValue)obj;
+
+            if (obj is Asn1Sequence)
+                return new InfoTypeAndValue((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public InfoTypeAndValue(
+            DerObjectIdentifier infoType)
+        {
+            this.infoType = infoType;
+            this.infoValue = null;
+        }
+
+        public InfoTypeAndValue(
+            DerObjectIdentifier infoType,
+            Asn1Encodable       optionalValue)
+        {
+            this.infoType = infoType;
+            this.infoValue = optionalValue;
+        }
+
+        public virtual DerObjectIdentifier InfoType
+        {
+            get { return infoType; }
+        }
+
+        public virtual Asn1Encodable InfoValue
+        {
+            get { return infoValue; }
+        }
+
+        /**
+         * <pre>
+         * InfoTypeAndValue ::= SEQUENCE {
+         *                         infoType               OBJECT IDENTIFIER,
+         *                         infoValue              ANY DEFINED BY infoType  OPTIONAL
+         * }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(infoType);
+
+            if (infoValue != null)
+            {
+                v.Add(infoValue);
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/KeyRecRepContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/KeyRecRepContent.cs
new file mode 100644
index 0000000..b0352f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/KeyRecRepContent.cs
@@ -0,0 +1,115 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class KeyRecRepContent
+		: Asn1Encodable
+	{
+		private readonly PkiStatusInfo status;
+		private readonly CmpCertificate newSigCert;
+		private readonly Asn1Sequence caCerts;
+		private readonly Asn1Sequence keyPairHist;
+
+		private KeyRecRepContent(Asn1Sequence seq)
+		{
+			status = PkiStatusInfo.GetInstance(seq[0]);
+
+			for (int pos = 1; pos < seq.Count; ++pos)
+			{
+				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+				switch (tObj.TagNo)
+				{
+					case 0:
+						newSigCert = CmpCertificate.GetInstance(tObj.GetObject());
+						break;
+					case 1:
+						caCerts = Asn1Sequence.GetInstance(tObj.GetObject());
+						break;
+					case 2:
+						keyPairHist = Asn1Sequence.GetInstance(tObj.GetObject());
+						break;
+					default:
+						throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+				}
+			}
+		}
+
+		public static KeyRecRepContent GetInstance(object obj)
+		{
+			if (obj is KeyRecRepContent)
+				return (KeyRecRepContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new KeyRecRepContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual PkiStatusInfo Status
+		{
+			get { return status; }
+		}
+
+		public virtual CmpCertificate NewSigCert
+		{
+			get { return newSigCert; }
+		}
+
+		public virtual CmpCertificate[] GetCACerts()
+		{
+			if (caCerts == null)
+				return null;
+
+			CmpCertificate[] results = new CmpCertificate[caCerts.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CmpCertificate.GetInstance(caCerts[i]);
+			}
+			return results;
+		}
+
+		public virtual CertifiedKeyPair[] GetKeyPairHist()
+		{
+			if (keyPairHist == null)
+				return null;
+
+			CertifiedKeyPair[] results = new CertifiedKeyPair[keyPairHist.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CertifiedKeyPair.GetInstance(keyPairHist[i]);
+			}
+			return results;
+		}
+
+		/**
+		 * <pre>
+		 * KeyRecRepContent ::= SEQUENCE {
+		 *                         status                  PKIStatusInfo,
+		 *                         newSigCert          [0] CMPCertificate OPTIONAL,
+		 *                         caCerts             [1] SEQUENCE SIZE (1..MAX) OF
+		 *                                                           CMPCertificate OPTIONAL,
+		 *                         keyPairHist         [2] SEQUENCE SIZE (1..MAX) OF
+		 *                                                           CertifiedKeyPair OPTIONAL
+		 *              }
+		 * </pre> 
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(status);
+			AddOptional(v, 0, newSigCert);
+			AddOptional(v, 1, caCerts);
+			AddOptional(v, 2, keyPairHist);
+			return new DerSequence(v);
+		}
+
+		private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+		{
+			if (obj != null)
+			{
+				v.Add(new DerTaggedObject(true, tagNo, obj));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/OobCertHash.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/OobCertHash.cs
new file mode 100644
index 0000000..63ddff7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/OobCertHash.cs
@@ -0,0 +1,87 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class OobCertHash
+		: Asn1Encodable
+	{
+		private readonly AlgorithmIdentifier hashAlg;
+		private readonly CertId certId;
+		private readonly DerBitString  hashVal;
+
+		private OobCertHash(Asn1Sequence seq)
+		{
+			int index = seq.Count - 1;
+
+			hashVal = DerBitString.GetInstance(seq[index--]);
+
+			for (int i = index; i >= 0; i--)
+			{
+				Asn1TaggedObject tObj = (Asn1TaggedObject)seq[i];
+
+				if (tObj.TagNo == 0)
+				{
+					hashAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+				}
+				else
+				{
+					certId = CertId.GetInstance(tObj, true);
+				}
+			}
+		}
+
+		public static OobCertHash GetInstance(object obj)
+		{
+			if (obj is OobCertHash)
+				return (OobCertHash)obj;
+
+			if (obj is Asn1Sequence)
+				return new OobCertHash((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+		
+		public virtual AlgorithmIdentifier HashAlg
+		{
+			get { return hashAlg; }
+		}
+		
+		public virtual CertId CertID
+		{
+			get { return certId; }
+		}
+		
+		/**
+		 * <pre>
+		 * OobCertHash ::= SEQUENCE {
+		 *                      hashAlg     [0] AlgorithmIdentifier     OPTIONAL,
+		 *                      certId      [1] CertId                  OPTIONAL,
+		 *                      hashVal         BIT STRING
+		 *                      -- hashVal is calculated over the Der encoding of the
+		 *                      -- self-signed certificate with the identifier certID.
+		 *       }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+			AddOptional(v, 0, hashAlg);
+			AddOptional(v, 1, certId);
+			v.Add(hashVal);
+			return new DerSequence(v);
+		}
+
+		private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+		{
+			if (obj != null)
+			{
+				v.Add(new DerTaggedObject(true, tagNo, obj));
+			}
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIBody.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIBody.cs
new file mode 100644
index 0000000..3205a90
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIBody.cs
@@ -0,0 +1,186 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class PkiBody
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int TYPE_INIT_REQ = 0;
+        public const int TYPE_INIT_REP = 1;
+        public const int TYPE_CERT_REQ = 2;
+        public const int TYPE_CERT_REP = 3;
+        public const int TYPE_P10_CERT_REQ = 4;
+        public const int TYPE_POPO_CHALL = 5;
+        public const int TYPE_POPO_REP = 6;
+        public const int TYPE_KEY_UPDATE_REQ = 7;
+        public const int TYPE_KEY_UPDATE_REP = 8;
+        public const int TYPE_KEY_RECOVERY_REQ = 9;
+        public const int TYPE_KEY_RECOVERY_REP = 10;
+        public const int TYPE_REVOCATION_REQ = 11;
+        public const int TYPE_REVOCATION_REP = 12;
+        public const int TYPE_CROSS_CERT_REQ = 13;
+        public const int TYPE_CROSS_CERT_REP = 14;
+        public const int TYPE_CA_KEY_UPDATE_ANN = 15;
+        public const int TYPE_CERT_ANN = 16;
+        public const int TYPE_REVOCATION_ANN = 17;
+        public const int TYPE_CRL_ANN = 18;
+        public const int TYPE_CONFIRM = 19;
+        public const int TYPE_NESTED = 20;
+        public const int TYPE_GEN_MSG = 21;
+        public const int TYPE_GEN_REP = 22;
+        public const int TYPE_ERROR = 23;
+        public const int TYPE_CERT_CONFIRM = 24;
+        public const int TYPE_POLL_REQ = 25;
+        public const int TYPE_POLL_REP = 26;
+
+        private int tagNo;
+        private Asn1Encodable body;
+
+        public static PkiBody GetInstance(object obj)
+        {
+            if (obj is PkiBody)
+                return (PkiBody)obj;
+
+            if (obj is Asn1TaggedObject)
+                return new PkiBody((Asn1TaggedObject)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        private PkiBody(Asn1TaggedObject tagged)
+        {
+            tagNo = tagged.TagNo;
+            body = GetBodyForType(tagNo, tagged.GetObject());
+        }
+
+        /**
+         * Creates a new PkiBody.
+         * @param type one of the TYPE_* constants
+         * @param content message content
+         */
+        public PkiBody(
+            int type,
+            Asn1Encodable content)
+        {
+            tagNo = type;
+            body = GetBodyForType(type, content);
+        }
+
+        private static Asn1Encodable GetBodyForType(
+            int type,
+            Asn1Encodable o)
+        {
+            switch (type)
+            {
+                case TYPE_INIT_REQ:
+                    return CertReqMessages.GetInstance(o);
+	            case TYPE_INIT_REP:
+	                return CertRepMessage.GetInstance(o);
+                case TYPE_CERT_REQ:
+                    return CertReqMessages.GetInstance(o);
+	            case TYPE_CERT_REP:
+	                return CertRepMessage.GetInstance(o);
+	            case TYPE_P10_CERT_REQ:
+	                return CertificationRequest.GetInstance(o);
+	            case TYPE_POPO_CHALL:
+	                return PopoDecKeyChallContent.GetInstance(o);
+	            case TYPE_POPO_REP:
+	                return PopoDecKeyRespContent.GetInstance(o);
+                case TYPE_KEY_UPDATE_REQ:
+                    return CertReqMessages.GetInstance(o);
+	            case TYPE_KEY_UPDATE_REP:
+	                return CertRepMessage.GetInstance(o);
+                case TYPE_KEY_RECOVERY_REQ:
+                    return CertReqMessages.GetInstance(o);
+	            case TYPE_KEY_RECOVERY_REP:
+	                return KeyRecRepContent.GetInstance(o);
+	            case TYPE_REVOCATION_REQ:
+	                return RevReqContent.GetInstance(o);
+	            case TYPE_REVOCATION_REP:
+	                return RevRepContent.GetInstance(o);
+                case TYPE_CROSS_CERT_REQ:
+                    return CertReqMessages.GetInstance(o);
+	            case TYPE_CROSS_CERT_REP:
+	                return CertRepMessage.GetInstance(o);
+	            case TYPE_CA_KEY_UPDATE_ANN:
+	                return CAKeyUpdAnnContent.GetInstance(o);
+	            case TYPE_CERT_ANN:
+	                return CmpCertificate.GetInstance(o);
+	            case TYPE_REVOCATION_ANN:
+	                return RevAnnContent.GetInstance(o);
+	            case TYPE_CRL_ANN:
+	                return CrlAnnContent.GetInstance(o);
+	            case TYPE_CONFIRM:
+	                return PkiConfirmContent.GetInstance(o);
+                case TYPE_NESTED:
+                    return PkiMessages.GetInstance(o);
+	            case TYPE_GEN_MSG:
+	                return GenMsgContent.GetInstance(o);
+	            case TYPE_GEN_REP:
+	                return GenRepContent.GetInstance(o);
+	            case TYPE_ERROR:
+	                return ErrorMsgContent.GetInstance(o);
+	            case TYPE_CERT_CONFIRM:
+	                return CertConfirmContent.GetInstance(o);
+	            case TYPE_POLL_REQ:
+	                return PollReqContent.GetInstance(o);
+	            case TYPE_POLL_REP:
+	                return PollRepContent.GetInstance(o);
+	            default:
+	                throw new ArgumentException("unknown tag number: " + type, "type");
+            }
+        }
+
+        public virtual int Type
+        {
+            get { return tagNo; }
+        }
+
+        public virtual Asn1Encodable Content
+        {
+            get { return body; }
+        }
+
+        /**
+         * <pre>
+         * PkiBody ::= CHOICE {       -- message-specific body elements
+         *        ir       [0]  CertReqMessages,        --Initialization Request
+         *        ip       [1]  CertRepMessage,         --Initialization Response
+         *        cr       [2]  CertReqMessages,        --Certification Request
+         *        cp       [3]  CertRepMessage,         --Certification Response
+         *        p10cr    [4]  CertificationRequest,   --imported from [PKCS10]
+         *        popdecc  [5]  POPODecKeyChallContent, --pop Challenge
+         *        popdecr  [6]  POPODecKeyRespContent,  --pop Response
+         *        kur      [7]  CertReqMessages,        --Key Update Request
+         *        kup      [8]  CertRepMessage,         --Key Update Response
+         *        krr      [9]  CertReqMessages,        --Key Recovery Request
+         *        krp      [10] KeyRecRepContent,       --Key Recovery Response
+         *        rr       [11] RevReqContent,          --Revocation Request
+         *        rp       [12] RevRepContent,          --Revocation Response
+         *        ccr      [13] CertReqMessages,        --Cross-Cert. Request
+         *        ccp      [14] CertRepMessage,         --Cross-Cert. Response
+         *        ckuann   [15] CAKeyUpdAnnContent,     --CA Key Update Ann.
+         *        cann     [16] CertAnnContent,         --Certificate Ann.
+         *        rann     [17] RevAnnContent,          --Revocation Ann.
+         *        crlann   [18] CRLAnnContent,          --CRL Announcement
+         *        pkiconf  [19] PKIConfirmContent,      --Confirmation
+         *        nested   [20] NestedMessageContent,   --Nested Message
+         *        genm     [21] GenMsgContent,          --General Message
+         *        genp     [22] GenRepContent,          --General Response
+         *        error    [23] ErrorMsgContent,        --Error Message
+         *        certConf [24] CertConfirmContent,     --Certificate confirm
+         *        pollReq  [25] PollReqContent,         --Polling request
+         *        pollRep  [26] PollRepContent          --Polling response
+         * }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(true, tagNo, body);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIConfirmContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIConfirmContent.cs
new file mode 100644
index 0000000..9864576
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIConfirmContent.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PkiConfirmContent
+		: Asn1Encodable
+	{
+		public static PkiConfirmContent GetInstance(object obj)
+		{
+			if (obj is PkiConfirmContent)
+				return (PkiConfirmContent)obj;
+
+			if (obj is Asn1Null)
+				return new PkiConfirmContent();
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public PkiConfirmContent()
+		{
+		}
+
+		/**
+		 * <pre>
+		 * PkiConfirmContent ::= NULL
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return DerNull.Instance;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFailureInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFailureInfo.cs
new file mode 100644
index 0000000..1df0e06
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFailureInfo.cs
@@ -0,0 +1,73 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	/**
+	 * <pre>
+	 * PKIFailureInfo ::= BIT STRING {
+	 * badAlg               (0),
+	 *   -- unrecognized or unsupported Algorithm Identifier
+	 * badMessageCheck      (1), -- integrity check failed (e.g., signature did not verify)
+	 * badRequest           (2),
+	 *   -- transaction not permitted or supported
+	 * badTime              (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+	 * badCertId            (4), -- no certificate could be found matching the provided criteria
+	 * badDataFormat        (5),
+	 *   -- the data submitted has the wrong format
+	 * wrongAuthority       (6), -- the authority indicated in the request is different from the one creating the response token
+	 * incorrectData        (7), -- the requester's data is incorrect (for notary services)
+	 * missingTimeStamp     (8), -- when the timestamp is missing but should be there (by policy)
+	 * badPOP               (9)  -- the proof-of-possession failed
+	 * timeNotAvailable    (14),
+	 *   -- the TSA's time source is not available
+	 * unacceptedPolicy    (15),
+	 *   -- the requested TSA policy is not supported by the TSA
+	 * unacceptedExtension (16),
+	 *   -- the requested extension is not supported by the TSA
+	 *  addInfoNotAvailable (17)
+	 *    -- the additional information requested could not be understood
+	 *    -- or is not available
+	 *  systemFailure       (25)
+	 *    -- the request cannot be handled due to system failure
+	 * </pre>
+	 */
+	public class PkiFailureInfo
+		: DerBitString
+	{
+		public const int BadAlg               = (1 << 7); // unrecognized or unsupported Algorithm Identifier
+		public const int BadMessageCheck      = (1 << 6); // integrity check failed (e.g., signature did not verify)
+		public const int BadRequest           = (1 << 5);
+		public const int BadTime              = (1 << 4); // -- messageTime was not sufficiently close to the system time, as defined by local policy
+		public const int BadCertId            = (1 << 3); // no certificate could be found matching the provided criteria
+		public const int BadDataFormat        = (1 << 2);
+		public const int WrongAuthority       = (1 << 1); // the authority indicated in the request is different from the one creating the response token
+		public const int IncorrectData        = 1;        // the requester's data is incorrect (for notary services)
+		public const int MissingTimeStamp     = (1 << 15); // when the timestamp is missing but should be there (by policy)
+		public const int BadPop               = (1 << 14); // the proof-of-possession failed
+		public const int TimeNotAvailable     = (1 << 9); // the TSA's time source is not available
+		public const int UnacceptedPolicy     = (1 << 8); // the requested TSA policy is not supported by the TSA
+		public const int UnacceptedExtension  = (1 << 23); //the requested extension is not supported by the TSA
+		public const int AddInfoNotAvailable  = (1 << 22); //the additional information requested could not be understood or is not available
+		public const int SystemFailure        = (1 << 30); //the request cannot be handled due to system failure
+
+		/**
+		 * Basic constructor.
+		 */
+		public PkiFailureInfo(
+			int info)
+			:	base(GetBytes(info), GetPadBits(info))
+		{
+		}
+
+		public PkiFailureInfo(
+			DerBitString info)
+			:	base(info.GetBytes(), info.PadBits)
+		{
+		}
+
+		public override string ToString()
+		{
+			return "PkiFailureInfo: 0x" + this.IntValue.ToString("X");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFreeText.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFreeText.cs
new file mode 100644
index 0000000..571c8d9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIFreeText.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PkiFreeText
+		: Asn1Encodable
+	{
+		internal Asn1Sequence strings;
+
+		public static PkiFreeText GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		public static PkiFreeText GetInstance(
+			object obj)
+		{
+			if (obj is PkiFreeText)
+			{
+				return (PkiFreeText)obj;
+			}
+			else if (obj is Asn1Sequence)
+			{
+				return new PkiFreeText((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public PkiFreeText(
+			Asn1Sequence seq)
+		{
+			foreach (object o in seq)
+			{
+				if (!(o is DerUtf8String))
+				{
+					throw new ArgumentException("attempt to insert non UTF8 STRING into PkiFreeText");
+				}
+			}
+
+			this.strings = seq;
+		}
+
+		public PkiFreeText(
+			DerUtf8String p)
+		{
+			strings = new DerSequence(p);
+		}
+
+		/**
+		 * Return the number of string elements present.
+		 *
+		 * @return number of elements present.
+		 */
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+		{
+			get { return strings.Count; }
+		}
+
+		public int Count
+		{
+			get { return strings.Count; }
+		}
+
+		/**
+		 * Return the UTF8STRING at index.
+		 *
+		 * @param index index of the string of interest
+		 * @return the string at index.
+		 */
+		public DerUtf8String this[int index]
+		{
+			get { return (DerUtf8String) strings[index]; }
+		}
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public DerUtf8String GetStringAt(
+			int index)
+		{
+			return this[index];
+		}
+
+		/**
+		 * <pre>
+		 * PkiFreeText ::= SEQUENCE SIZE (1..MAX) OF UTF8String
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return strings;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeader.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeader.cs
new file mode 100644
index 0000000..e758e9f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeader.cs
@@ -0,0 +1,237 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class PkiHeader
+        : Asn1Encodable
+    {
+        /**
+         * Value for a "null" recipient or sender.
+         */
+        public static readonly GeneralName NULL_NAME = new GeneralName(X509Name.GetInstance(new DerSequence()));
+
+        public static readonly int CMP_1999 = 1;
+        public static readonly int CMP_2000 = 2;
+
+        private readonly DerInteger pvno;
+        private readonly GeneralName sender;
+        private readonly GeneralName recipient;
+        private readonly DerGeneralizedTime messageTime;
+        private readonly AlgorithmIdentifier protectionAlg;
+        private readonly Asn1OctetString senderKID;       // KeyIdentifier
+        private readonly Asn1OctetString recipKID;        // KeyIdentifier
+        private readonly Asn1OctetString transactionID;
+        private readonly Asn1OctetString senderNonce;
+        private readonly Asn1OctetString recipNonce;
+        private readonly PkiFreeText freeText;
+        private readonly Asn1Sequence generalInfo;
+
+        private PkiHeader(Asn1Sequence seq)
+        {
+            pvno = DerInteger.GetInstance(seq[0]);
+            sender = GeneralName.GetInstance(seq[1]);
+            recipient = GeneralName.GetInstance(seq[2]);
+
+            for (int pos = 3; pos < seq.Count; ++pos)
+            {
+                Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos];
+
+                switch (tObj.TagNo)
+                {
+                    case 0:
+                        messageTime = DerGeneralizedTime.GetInstance(tObj, true);
+                        break;
+                    case 1:
+                        protectionAlg = AlgorithmIdentifier.GetInstance(tObj, true);
+                        break;
+                    case 2:
+                        senderKID = Asn1OctetString.GetInstance(tObj, true);
+                        break;
+                    case 3:
+                        recipKID = Asn1OctetString.GetInstance(tObj, true);
+                        break;
+                    case 4:
+                        transactionID = Asn1OctetString.GetInstance(tObj, true);
+                        break;
+                    case 5:
+                        senderNonce = Asn1OctetString.GetInstance(tObj, true);
+                        break;
+                    case 6:
+                        recipNonce = Asn1OctetString.GetInstance(tObj, true);
+                        break;
+                    case 7:
+                        freeText = PkiFreeText.GetInstance(tObj, true);
+                        break;
+                    case 8:
+                        generalInfo = Asn1Sequence.GetInstance(tObj, true);
+                        break;
+                    default:
+                        throw new ArgumentException("unknown tag number: " + tObj.TagNo, "seq");
+                }
+            }
+        }
+
+        public static PkiHeader GetInstance(object obj)
+        {
+            if (obj is PkiHeader)
+                return (PkiHeader)obj;
+
+            if (obj is Asn1Sequence)
+                return new PkiHeader((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public PkiHeader(
+            int pvno,
+            GeneralName sender,
+            GeneralName recipient)
+            : this(new DerInteger(pvno), sender, recipient)
+        {
+        }
+
+        private PkiHeader(
+            DerInteger pvno,
+            GeneralName sender,
+            GeneralName recipient)
+        {
+            this.pvno = pvno;
+            this.sender = sender;
+            this.recipient = recipient;
+        }
+
+        public virtual DerInteger Pvno
+        {
+            get { return pvno; }
+        }
+
+        public virtual GeneralName Sender
+        {
+            get { return sender; }
+        }
+
+        public virtual GeneralName Recipient
+        {
+            get { return recipient; }
+        }
+
+        public virtual DerGeneralizedTime MessageTime
+        {
+            get { return messageTime; }
+        }
+
+        public virtual AlgorithmIdentifier ProtectionAlg
+        {
+            get { return protectionAlg; }
+        }
+
+        public virtual Asn1OctetString SenderKID
+        {   
+            get { return senderKID; }
+        }
+
+        public virtual Asn1OctetString RecipKID
+        {   
+            get { return recipKID; }
+        }
+
+        public virtual Asn1OctetString TransactionID
+        {   
+            get { return transactionID; }
+        }
+
+        public virtual Asn1OctetString SenderNonce
+        {   
+            get { return senderNonce; }
+        }
+
+        public virtual Asn1OctetString RecipNonce
+        {   
+            get { return recipNonce; }
+        }
+
+        public virtual PkiFreeText FreeText
+        {
+            get { return freeText; }
+        }
+
+        public virtual InfoTypeAndValue[] GetGeneralInfo()
+        {
+            if (generalInfo == null)
+            {
+                return null;
+            }
+            InfoTypeAndValue[] results = new InfoTypeAndValue[generalInfo.Count];
+            for (int i = 0; i < results.Length; i++)
+            {
+                results[i] = InfoTypeAndValue.GetInstance(generalInfo[i]);
+            }
+            return results;
+        }
+
+        /**
+         * <pre>
+         *  PkiHeader ::= SEQUENCE {
+         *            pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+         *            sender              GeneralName,
+         *            -- identifies the sender
+         *            recipient           GeneralName,
+         *            -- identifies the intended recipient
+         *            messageTime     [0] GeneralizedTime         OPTIONAL,
+         *            -- time of production of this message (used when sender
+         *            -- believes that the transport will be "suitable"; i.e.,
+         *            -- that the time will still be meaningful upon receipt)
+         *            protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+         *            -- algorithm used for calculation of protection bits
+         *            senderKID       [2] KeyIdentifier           OPTIONAL,
+         *            recipKID        [3] KeyIdentifier           OPTIONAL,
+         *            -- to identify specific keys used for protection
+         *            transactionID   [4] OCTET STRING            OPTIONAL,
+         *            -- identifies the transaction; i.e., this will be the same in
+         *            -- corresponding request, response, certConf, and PKIConf
+         *            -- messages
+         *            senderNonce     [5] OCTET STRING            OPTIONAL,
+         *            recipNonce      [6] OCTET STRING            OPTIONAL,
+         *            -- nonces used to provide replay protection, senderNonce
+         *            -- is inserted by the creator of this message; recipNonce
+         *            -- is a nonce previously inserted in a related message by
+         *            -- the intended recipient of this message
+         *            freeText        [7] PKIFreeText             OPTIONAL,
+         *            -- this may be used to indicate context-specific instructions
+         *            -- (this field is intended for human consumption)
+         *            generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+         *                                 InfoTypeAndValue     OPTIONAL
+         *            -- this may be used to convey context-specific information
+         *            -- (this field not primarily intended for human consumption)
+         * }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+
+            AddOptional(v, 0, messageTime);
+            AddOptional(v, 1, protectionAlg);
+            AddOptional(v, 2, senderKID);
+            AddOptional(v, 3, recipKID);
+            AddOptional(v, 4, transactionID);
+            AddOptional(v, 5, senderNonce);
+            AddOptional(v, 6, recipNonce);
+            AddOptional(v, 7, freeText);
+            AddOptional(v, 8, generalInfo);
+
+            return new DerSequence(v);
+        }
+
+        private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+        {
+            if (obj != null)
+            {
+                v.Add(new DerTaggedObject(true, tagNo, obj));
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeaderBuilder.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeaderBuilder.cs
new file mode 100644
index 0000000..00073c0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIHeaderBuilder.cs
@@ -0,0 +1,223 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PkiHeaderBuilder
+	{
+		private DerInteger pvno;
+		private GeneralName sender;
+		private GeneralName recipient;
+		private DerGeneralizedTime messageTime;
+		private AlgorithmIdentifier protectionAlg;
+		private Asn1OctetString senderKID;       // KeyIdentifier
+		private Asn1OctetString recipKID;        // KeyIdentifier
+		private Asn1OctetString transactionID;
+		private Asn1OctetString senderNonce;
+		private Asn1OctetString recipNonce;
+		private PkiFreeText     freeText;
+		private Asn1Sequence    generalInfo;
+
+		public PkiHeaderBuilder(
+			int			pvno,
+			GeneralName	sender,
+			GeneralName	recipient)
+			: this(new DerInteger(pvno), sender, recipient)
+		{
+		}
+
+		private PkiHeaderBuilder(
+			DerInteger	pvno,
+			GeneralName	sender,
+			GeneralName	recipient)
+		{
+			this.pvno = pvno;
+			this.sender = sender;
+			this.recipient = recipient;
+		}
+
+		public virtual PkiHeaderBuilder SetMessageTime(DerGeneralizedTime time)
+		{
+			messageTime = time;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetProtectionAlg(AlgorithmIdentifier aid)
+		{
+			protectionAlg = aid;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetSenderKID(byte[] kid)
+		{
+            return SetSenderKID(kid == null ? null : new DerOctetString(kid));
+		}
+
+		public virtual PkiHeaderBuilder SetSenderKID(Asn1OctetString kid)
+		{
+			senderKID = kid;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetRecipKID(byte[] kid)
+		{
+            return SetRecipKID(kid == null ? null : new DerOctetString(kid));
+		}
+		
+		public virtual PkiHeaderBuilder SetRecipKID(DerOctetString kid)
+		{
+			recipKID = kid;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetTransactionID(byte[] tid)
+		{
+			return SetTransactionID(tid == null ? null : new DerOctetString(tid));
+		}
+
+		public virtual PkiHeaderBuilder SetTransactionID(Asn1OctetString tid)
+		{
+			transactionID = tid;
+			return this;
+		}
+		
+		public virtual PkiHeaderBuilder SetSenderNonce(byte[] nonce)
+		{
+            return SetSenderNonce(nonce == null ? null : new DerOctetString(nonce));
+		}
+
+		public virtual PkiHeaderBuilder SetSenderNonce(Asn1OctetString nonce)
+		{
+			senderNonce = nonce;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetRecipNonce(byte[] nonce)
+		{
+            return SetRecipNonce(nonce == null ? null : new DerOctetString(nonce));
+		}
+
+		public virtual PkiHeaderBuilder SetRecipNonce(Asn1OctetString nonce)
+		{
+			recipNonce = nonce;
+			return this;
+		}
+
+		public virtual PkiHeaderBuilder SetFreeText(PkiFreeText text)
+		{
+			freeText = text;
+			return this;
+		}
+		
+		public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue genInfo)
+		{
+			return SetGeneralInfo(MakeGeneralInfoSeq(genInfo));
+		}
+		
+		public virtual PkiHeaderBuilder SetGeneralInfo(InfoTypeAndValue[] genInfos)
+		{
+			return SetGeneralInfo(MakeGeneralInfoSeq(genInfos));
+		}
+		
+		public virtual PkiHeaderBuilder SetGeneralInfo(Asn1Sequence seqOfInfoTypeAndValue)
+		{
+			generalInfo = seqOfInfoTypeAndValue;
+			return this;
+		}
+
+		private static Asn1Sequence MakeGeneralInfoSeq(
+			InfoTypeAndValue generalInfo)
+		{
+			return new DerSequence(generalInfo);
+		}
+		
+		private static Asn1Sequence MakeGeneralInfoSeq(
+			InfoTypeAndValue[] generalInfos)
+		{
+			Asn1Sequence genInfoSeq = null;
+			if (generalInfos != null)
+			{
+				Asn1EncodableVector v = new Asn1EncodableVector();
+				for (int i = 0; i < generalInfos.Length; ++i)
+				{
+					v.Add(generalInfos[i]);
+				}
+				genInfoSeq = new DerSequence(v);
+			}
+			return genInfoSeq;
+		}
+
+		/**
+		 * <pre>
+		 *  PKIHeader ::= SEQUENCE {
+		 *            pvno                INTEGER     { cmp1999(1), cmp2000(2) },
+		 *            sender              GeneralName,
+		 *            -- identifies the sender
+		 *            recipient           GeneralName,
+		 *            -- identifies the intended recipient
+		 *            messageTime     [0] GeneralizedTime         OPTIONAL,
+		 *            -- time of production of this message (used when sender
+		 *            -- believes that the transport will be "suitable"; i.e.,
+		 *            -- that the time will still be meaningful upon receipt)
+		 *            protectionAlg   [1] AlgorithmIdentifier     OPTIONAL,
+		 *            -- algorithm used for calculation of protection bits
+		 *            senderKID       [2] KeyIdentifier           OPTIONAL,
+		 *            recipKID        [3] KeyIdentifier           OPTIONAL,
+		 *            -- to identify specific keys used for protection
+		 *            transactionID   [4] OCTET STRING            OPTIONAL,
+		 *            -- identifies the transaction; i.e., this will be the same in
+		 *            -- corresponding request, response, certConf, and PKIConf
+		 *            -- messages
+		 *            senderNonce     [5] OCTET STRING            OPTIONAL,
+		 *            recipNonce      [6] OCTET STRING            OPTIONAL,
+		 *            -- nonces used to provide replay protection, senderNonce
+		 *            -- is inserted by the creator of this message; recipNonce
+		 *            -- is a nonce previously inserted in a related message by
+		 *            -- the intended recipient of this message
+		 *            freeText        [7] PKIFreeText             OPTIONAL,
+		 *            -- this may be used to indicate context-specific instructions
+		 *            -- (this field is intended for human consumption)
+		 *            generalInfo     [8] SEQUENCE SIZE (1..MAX) OF
+		 *                                 InfoTypeAndValue     OPTIONAL
+		 *            -- this may be used to convey context-specific information
+		 *            -- (this field not primarily intended for human consumption)
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public virtual PkiHeader Build()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(pvno, sender, recipient);
+			AddOptional(v, 0, messageTime);
+			AddOptional(v, 1, protectionAlg);
+			AddOptional(v, 2, senderKID);
+			AddOptional(v, 3, recipKID);
+			AddOptional(v, 4, transactionID);
+			AddOptional(v, 5, senderNonce);
+			AddOptional(v, 6, recipNonce);
+			AddOptional(v, 7, freeText);
+			AddOptional(v, 8, generalInfo);
+
+			messageTime = null;
+			protectionAlg = null;
+			senderKID = null;
+			recipKID = null;
+			transactionID = null;
+			senderNonce = null;
+			recipNonce = null;
+			freeText = null;
+			generalInfo = null;
+
+			return PkiHeader.GetInstance(new DerSequence(v));
+		}
+
+		private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+		{
+			if (obj != null)
+			{
+				v.Add(new DerTaggedObject(true, tagNo, obj));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessage.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessage.cs
new file mode 100644
index 0000000..086a2d9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessage.cs
@@ -0,0 +1,140 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class PkiMessage
+        : Asn1Encodable
+    {
+        private readonly PkiHeader header;
+        private readonly PkiBody body;
+        private readonly DerBitString protection;
+        private readonly Asn1Sequence extraCerts;
+
+        private PkiMessage(Asn1Sequence seq)
+        {
+            header = PkiHeader.GetInstance(seq[0]);
+            body = PkiBody.GetInstance(seq[1]);
+
+            for (int pos = 2; pos < seq.Count; ++pos)
+            {
+                Asn1TaggedObject tObj = (Asn1TaggedObject)seq[pos].ToAsn1Object();
+
+                if (tObj.TagNo == 0)
+                {
+                    protection = DerBitString.GetInstance(tObj, true);
+                }
+                else
+                {
+                    extraCerts = Asn1Sequence.GetInstance(tObj, true);
+                }
+            }
+        }
+
+        public static PkiMessage GetInstance(object obj)
+        {
+            if (obj is PkiMessage)
+                return (PkiMessage)obj;
+
+            if (obj != null)
+                return new PkiMessage(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        /**
+         * Creates a new PkiMessage.
+         *
+         * @param header message header
+         * @param body message body
+         * @param protection message protection (may be null)
+         * @param extraCerts extra certificates (may be null)
+         */
+        public PkiMessage(
+            PkiHeader header,
+            PkiBody body,
+            DerBitString protection,
+            CmpCertificate[] extraCerts)
+        {
+            this.header = header;
+            this.body = body;
+            this.protection = protection;
+            if (extraCerts != null)
+            {
+                this.extraCerts = new DerSequence(extraCerts);
+            }
+        }
+
+        public PkiMessage(
+            PkiHeader header,
+            PkiBody body,
+            DerBitString protection)
+            : this(header, body, protection, null)
+        {
+        }
+
+        public PkiMessage(
+            PkiHeader header,
+            PkiBody body)
+            : this(header, body, null, null)
+        {
+        }
+
+        public virtual PkiHeader Header
+        {
+            get { return header; }
+        }
+
+        public virtual PkiBody Body
+        {
+            get { return body; }
+        }
+
+        public virtual DerBitString Protection
+        {
+            get { return protection; }
+        }
+
+        public virtual CmpCertificate[] GetExtraCerts()
+        {
+            if (extraCerts == null)
+                return null;
+
+            CmpCertificate[] results = new CmpCertificate[extraCerts.Count];
+            for (int i = 0; i < results.Length; ++i)
+            {
+                results[i] = CmpCertificate.GetInstance(extraCerts[i]);
+            }
+            return results;
+        }
+
+        /**
+         * <pre>
+         * PkiMessage ::= SEQUENCE {
+         *                  header           PKIHeader,
+         *                  body             PKIBody,
+         *                  protection   [0] PKIProtection OPTIONAL,
+         *                  extraCerts   [1] SEQUENCE SIZE (1..MAX) OF CMPCertificate
+         *                                                                     OPTIONAL
+         * }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(header, body);
+
+            AddOptional(v, 0, protection);
+            AddOptional(v, 1, extraCerts);
+
+            return new DerSequence(v);
+        }
+
+        private static void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+        {
+            if (obj != null)
+            {
+                v.Add(new DerTaggedObject(true, tagNo, obj));
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessages.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessages.cs
new file mode 100644
index 0000000..ddabdf4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class PkiMessages
+        : Asn1Encodable
+    {
+        private Asn1Sequence content;
+
+        private PkiMessages(Asn1Sequence seq)
+        {
+            content = seq;
+        }
+
+        public static PkiMessages GetInstance(object obj)
+        {
+            if (obj is PkiMessages)
+                return (PkiMessages)obj;
+
+            if (obj is Asn1Sequence)
+                return new PkiMessages((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+		public PkiMessages(params PkiMessage[] msgs)
+        {
+            content = new DerSequence(msgs);
+        }
+
+        public virtual PkiMessage[] ToPkiMessageArray()
+        {
+            PkiMessage[] result = new PkiMessage[content.Count];
+            for (int i = 0; i != result.Length; ++i)
+            {
+                result[i] = PkiMessage.GetInstance(content[i]);
+            }
+            return result;
+        }
+
+        /**
+         * <pre>
+         * PkiMessages ::= SEQUENCE SIZE (1..MAX) OF PkiMessage
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return content;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatus.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatus.cs
new file mode 100644
index 0000000..b03dd3d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatus.cs
@@ -0,0 +1,62 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public enum PkiStatus
+	{
+		Granted					= 0,
+		GrantedWithMods			= 1,
+		Rejection				= 2,
+		Waiting					= 3,
+		RevocationWarning		= 4,
+		RevocationNotification	= 5,
+    	KeyUpdateWarning		= 6,
+	}
+
+	public class PkiStatusEncodable
+		: Asn1Encodable
+	{
+		public static readonly PkiStatusEncodable granted = new PkiStatusEncodable(PkiStatus.Granted);
+		public static readonly PkiStatusEncodable grantedWithMods = new PkiStatusEncodable(PkiStatus.GrantedWithMods);
+		public static readonly PkiStatusEncodable rejection = new PkiStatusEncodable(PkiStatus.Rejection);
+		public static readonly PkiStatusEncodable waiting = new PkiStatusEncodable(PkiStatus.Waiting);
+		public static readonly PkiStatusEncodable revocationWarning = new PkiStatusEncodable(PkiStatus.RevocationWarning);
+		public static readonly PkiStatusEncodable revocationNotification = new PkiStatusEncodable(PkiStatus.RevocationNotification);
+		public static readonly PkiStatusEncodable keyUpdateWaiting = new PkiStatusEncodable(PkiStatus.KeyUpdateWarning);
+
+		private readonly DerInteger status;
+
+		private PkiStatusEncodable(PkiStatus status)
+			: this(new DerInteger((int)status))
+		{
+		}
+
+		private PkiStatusEncodable(DerInteger status)
+		{
+			this.status = status;
+		}
+
+		public static PkiStatusEncodable GetInstance(object obj)
+		{
+			if (obj is PkiStatusEncodable)
+				return (PkiStatusEncodable)obj;
+
+			if (obj is DerInteger)
+				return new PkiStatusEncodable((DerInteger)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual BigInteger Value
+		{
+			get { return status.Value; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return status;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatusInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatusInfo.cs
new file mode 100644
index 0000000..2463e00
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PKIStatusInfo.cs
@@ -0,0 +1,165 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PkiStatusInfo
+		: Asn1Encodable
+	{
+		DerInteger      status;
+		PkiFreeText     statusString;
+		DerBitString    failInfo;
+
+		public static PkiStatusInfo GetInstance(
+			Asn1TaggedObject obj,
+			bool isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		public static PkiStatusInfo GetInstance(
+			object obj)
+		{
+			if (obj is PkiStatusInfo)
+			{
+				return (PkiStatusInfo)obj;
+			}
+			else if (obj is Asn1Sequence)
+			{
+				return new PkiStatusInfo((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public PkiStatusInfo(
+			Asn1Sequence seq)
+		{
+			this.status = DerInteger.GetInstance(seq[0]);
+
+			this.statusString = null;
+			this.failInfo = null;
+
+			if (seq.Count > 2)
+			{
+				this.statusString = PkiFreeText.GetInstance(seq[1]);
+				this.failInfo = DerBitString.GetInstance(seq[2]);
+			}
+			else if (seq.Count > 1)
+			{
+				object obj = seq[1];
+				if (obj is DerBitString)
+				{
+					this.failInfo = DerBitString.GetInstance(obj);
+				}
+				else
+				{
+					this.statusString = PkiFreeText.GetInstance(obj);
+				}
+			}
+		}
+
+		/**
+		 * @param status
+		 */
+		public PkiStatusInfo(int status)
+		{
+			this.status = new DerInteger(status);
+		}
+
+		/**
+		 * @param status
+		 * @param statusString
+		 */
+		public PkiStatusInfo(
+			int			status,
+			PkiFreeText	statusString)
+		{
+			this.status = new DerInteger(status);
+			this.statusString = statusString;
+		}
+
+		public PkiStatusInfo(
+			int				status,
+			PkiFreeText		statusString,
+			PkiFailureInfo	failInfo)
+		{
+			this.status = new DerInteger(status);
+			this.statusString = statusString;
+			this.failInfo = failInfo;
+		}
+
+		public BigInteger Status
+		{
+			get
+			{
+				return status.Value;
+			}
+		}
+
+		public PkiFreeText StatusString
+		{
+			get
+			{
+				return statusString;
+			}
+		}
+
+		public DerBitString FailInfo
+		{
+			get
+			{
+				return failInfo;
+			}
+		}
+
+		/**
+		 * <pre>
+		 * PkiStatusInfo ::= SEQUENCE {
+		 *     status        PKIStatus,                (INTEGER)
+		 *     statusString  PkiFreeText     OPTIONAL,
+		 *     failInfo      PkiFailureInfo  OPTIONAL  (BIT STRING)
+		 * }
+		 *
+		 * PKIStatus:
+		 *   granted                (0), -- you got exactly what you asked for
+		 *   grantedWithMods        (1), -- you got something like what you asked for
+		 *   rejection              (2), -- you don't get it, more information elsewhere in the message
+		 *   waiting                (3), -- the request body part has not yet been processed, expect to hear more later
+		 *   revocationWarning      (4), -- this message contains a warning that a revocation is imminent
+		 *   revocationNotification (5), -- notification that a revocation has occurred
+		 *   keyUpdateWarning       (6)  -- update already done for the oldCertId specified in CertReqMsg
+		 *
+		 * PkiFailureInfo:
+		 *   badAlg           (0), -- unrecognized or unsupported Algorithm Identifier
+		 *   badMessageCheck  (1), -- integrity check failed (e.g., signature did not verify)
+		 *   badRequest       (2), -- transaction not permitted or supported
+		 *   badTime          (3), -- messageTime was not sufficiently close to the system time, as defined by local policy
+		 *   badCertId        (4), -- no certificate could be found matching the provided criteria
+		 *   badDataFormat    (5), -- the data submitted has the wrong format
+		 *   wrongAuthority   (6), -- the authority indicated in the request is different from the one creating the response token
+		 *   incorrectData    (7), -- the requester's data is incorrect (for notary services)
+		 *   missingTimeStamp (8), -- when the timestamp is missing but should be there (by policy)
+		 *   badPOP           (9)  -- the proof-of-possession failed
+		 *
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(status);
+
+			if (statusString != null)
+			{
+				v.Add(statusString);
+			}
+
+			if (failInfo!= null)
+			{
+				v.Add(failInfo);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PbmParameter.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PbmParameter.cs
new file mode 100644
index 0000000..59b1bd7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PbmParameter.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+    public class PbmParameter
+        : Asn1Encodable
+    {
+        private Asn1OctetString salt;
+        private AlgorithmIdentifier owf;
+        private DerInteger iterationCount;
+        private AlgorithmIdentifier mac;
+
+        private PbmParameter(Asn1Sequence seq)
+        {
+            salt = Asn1OctetString.GetInstance(seq[0]);
+            owf = AlgorithmIdentifier.GetInstance(seq[1]);
+            iterationCount = DerInteger.GetInstance(seq[2]);
+            mac = AlgorithmIdentifier.GetInstance(seq[3]);
+        }
+
+        public static PbmParameter GetInstance(object obj)
+        {
+            if (obj is PbmParameter)
+                return (PbmParameter)obj;
+
+            if (obj is Asn1Sequence)
+                return new PbmParameter((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public PbmParameter(
+            byte[] salt,
+            AlgorithmIdentifier owf,
+            int iterationCount,
+            AlgorithmIdentifier mac)
+            : this(new DerOctetString(salt), owf, new DerInteger(iterationCount), mac)
+        {
+        }
+
+        public PbmParameter(
+            Asn1OctetString salt,
+            AlgorithmIdentifier owf,
+            DerInteger iterationCount,
+            AlgorithmIdentifier mac)
+        {
+            this.salt = salt;
+            this.owf = owf;
+            this.iterationCount = iterationCount;
+            this.mac = mac;
+        }
+
+        public virtual Asn1OctetString Salt
+        {
+            get { return salt; }
+        }
+
+        public virtual AlgorithmIdentifier Owf
+        {
+            get { return owf; }
+        }
+
+        public virtual DerInteger IterationCount
+        {
+            get { return iterationCount; }
+        }
+
+        public virtual AlgorithmIdentifier Mac
+        {
+            get { return mac; }
+        }
+
+        /**
+         * <pre>
+         *  PbmParameter ::= SEQUENCE {
+         *                        salt                OCTET STRING,
+         *                        -- note:  implementations MAY wish to limit acceptable sizes
+         *                        -- of this string to values appropriate for their environment
+         *                        -- in order to reduce the risk of denial-of-service attacks
+         *                        owf                 AlgorithmIdentifier,
+         *                        -- AlgId for a One-Way Function (SHA-1 recommended)
+         *                        iterationCount      INTEGER,
+         *                        -- number of times the OWF is applied
+         *                        -- note:  implementations MAY wish to limit acceptable sizes
+         *                        -- of this integer to values appropriate for their environment
+         *                        -- in order to reduce the risk of denial-of-service attacks
+         *                        mac                 AlgorithmIdentifier
+         *                        -- the MAC AlgId (e.g., DES-MAC, Triple-DES-MAC [PKCS11],
+         *    }   -- or HMAC [RFC2104, RFC2202])
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(salt, owf, iterationCount, mac);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PollRepContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PollRepContent.cs
new file mode 100644
index 0000000..4045ac7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PollRepContent.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PollRepContent
+		: Asn1Encodable
+	{
+		private readonly DerInteger certReqId;
+		private readonly DerInteger checkAfter;
+		private readonly PkiFreeText reason;
+
+		private PollRepContent(Asn1Sequence seq)
+		{
+			certReqId = DerInteger.GetInstance(seq[0]);
+			checkAfter = DerInteger.GetInstance(seq[1]);
+
+			if (seq.Count > 2)
+			{
+				reason = PkiFreeText.GetInstance(seq[2]);
+			}
+		}
+
+		public static PollRepContent GetInstance(object obj)
+		{
+			if (obj is PollRepContent)
+				return (PollRepContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new PollRepContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual DerInteger CertReqID
+		{
+			get { return certReqId; }
+		}
+
+		public virtual DerInteger CheckAfter
+		{
+			get { return checkAfter; }
+		}
+
+		public virtual PkiFreeText Reason
+		{
+			get { return reason; }
+		}
+
+		/**
+		 * <pre>
+		 * PollRepContent ::= SEQUENCE OF SEQUENCE {
+		 *         certReqId              INTEGER,
+		 *         checkAfter             INTEGER,  -- time in seconds
+		 *         reason                 PKIFreeText OPTIONAL
+		 *     }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certReqId, checkAfter);
+			v.AddOptional(reason);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PollReqContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PollReqContent.cs
new file mode 100644
index 0000000..ca21641
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PollReqContent.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PollReqContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private PollReqContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static PollReqContent GetInstance(object obj)
+		{
+			if (obj is PollReqContent)
+				return (PollReqContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new PollReqContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual DerInteger[][] GetCertReqIDs()
+		{
+			DerInteger[][] result = new DerInteger[content.Count][];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = SequenceToDerIntegerArray((Asn1Sequence)content[i]);
+			}
+			return result;
+		}
+
+		private static DerInteger[] SequenceToDerIntegerArray(Asn1Sequence seq)
+		{
+			DerInteger[] result = new DerInteger[seq.Count];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = DerInteger.GetInstance(seq[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * PollReqContent ::= SEQUENCE OF SEQUENCE {
+		 *                        certReqId              INTEGER
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyChallContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyChallContent.cs
new file mode 100644
index 0000000..20b173b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyChallContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PopoDecKeyChallContent
+	    : Asn1Encodable
+	{
+	    private readonly Asn1Sequence content;
+
+	    private PopoDecKeyChallContent(Asn1Sequence seq)
+	    {
+	        content = seq;
+	    }
+
+	    public static PopoDecKeyChallContent GetInstance(object obj)
+	    {
+	        if (obj is PopoDecKeyChallContent)
+	            return (PopoDecKeyChallContent)obj;
+
+			if (obj is Asn1Sequence)
+	            return new PopoDecKeyChallContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+	    }
+
+	    public virtual Challenge[] ToChallengeArray()
+	    {
+	        Challenge[] result = new Challenge[content.Count];
+	        for (int i = 0; i != result.Length; ++i)
+	        {
+	            result[i] = Challenge.GetInstance(content[i]);
+	        }
+	        return result;
+	    }
+
+	    /**
+	     * <pre>
+	     * PopoDecKeyChallContent ::= SEQUENCE OF Challenge
+	     * </pre>
+	     * @return a basic ASN.1 object representation.
+	     */
+	    public override Asn1Object ToAsn1Object()
+	    {
+	        return content;
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyRespContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyRespContent.cs
new file mode 100644
index 0000000..8c322e4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/PopoDecKeyRespContent.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class PopoDecKeyRespContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+
+		private PopoDecKeyRespContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static PopoDecKeyRespContent GetInstance(object obj)
+		{
+			if (obj is PopoDecKeyRespContent)
+				return (PopoDecKeyRespContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new PopoDecKeyRespContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual DerInteger[] ToDerIntegerArray()
+		{
+			DerInteger[] result = new DerInteger[content.Count];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = DerInteger.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * PopoDecKeyRespContent ::= SEQUENCE OF INTEGER
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/ProtectedPart.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/ProtectedPart.cs
new file mode 100644
index 0000000..db6798f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/ProtectedPart.cs
@@ -0,0 +1,58 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class ProtectedPart
+		: Asn1Encodable
+	{
+		private readonly PkiHeader header;
+		private readonly PkiBody body;
+		
+		private ProtectedPart(Asn1Sequence seq)
+		{
+			header = PkiHeader.GetInstance(seq[0]);
+			body = PkiBody.GetInstance(seq[1]);
+		}
+
+		public static ProtectedPart GetInstance(object obj)
+		{
+			if (obj is ProtectedPart)
+				return (ProtectedPart)obj;
+
+			if (obj is Asn1Sequence)
+				return new ProtectedPart((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public ProtectedPart(PkiHeader header, PkiBody body)
+		{
+			this.header = header;
+			this.body = body;
+		}
+
+		public virtual PkiHeader Header
+		{
+			get { return header; }
+		}
+
+		public virtual PkiBody Body
+		{
+			get { return body; }
+		}
+
+		/**
+		 * <pre>
+		 * ProtectedPart ::= SEQUENCE {
+		 *                    header    PKIHeader,
+		 *                    body      PKIBody
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(header, body);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/RevAnnContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/RevAnnContent.cs
new file mode 100644
index 0000000..2c3bd5f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/RevAnnContent.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class RevAnnContent
+		: Asn1Encodable
+	{
+		private readonly PkiStatusEncodable status;
+		private readonly CertId certId;
+		private readonly DerGeneralizedTime willBeRevokedAt;
+		private readonly DerGeneralizedTime badSinceDate;
+		private readonly X509Extensions crlDetails;
+
+		private RevAnnContent(Asn1Sequence seq)
+		{
+			status = PkiStatusEncodable.GetInstance(seq[0]);
+			certId = CertId.GetInstance(seq[1]);
+			willBeRevokedAt = DerGeneralizedTime.GetInstance(seq[2]);
+			badSinceDate = DerGeneralizedTime.GetInstance(seq[3]);
+
+			if (seq.Count > 4)
+			{
+				crlDetails = X509Extensions.GetInstance(seq[4]);
+			}
+		}
+
+		public static RevAnnContent GetInstance(object obj)
+		{
+			if (obj is RevAnnContent)
+				return (RevAnnContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new RevAnnContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public virtual PkiStatusEncodable Status
+		{
+			get { return status; }
+		}
+
+		public virtual CertId CertID
+		{
+			get { return certId; }
+		}
+
+		public virtual DerGeneralizedTime WillBeRevokedAt
+		{
+			get { return willBeRevokedAt; }
+		}
+
+		public virtual DerGeneralizedTime BadSinceDate
+		{
+			get { return badSinceDate; }
+		}
+
+		public virtual X509Extensions CrlDetails
+		{
+			get { return crlDetails; }
+		}
+
+		/**
+		 * <pre>
+		 * RevAnnContent ::= SEQUENCE {
+		 *       status              PKIStatus,
+		 *       certId              CertId,
+		 *       willBeRevokedAt     GeneralizedTime,
+		 *       badSinceDate        GeneralizedTime,
+		 *       crlDetails          Extensions  OPTIONAL
+		 *        -- extra CRL details (e.g., crl number, reason, location, etc.)
+		 * }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(status, certId, willBeRevokedAt, badSinceDate);
+			v.AddOptional(crlDetails);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/RevDetails.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/RevDetails.cs
new file mode 100644
index 0000000..1bd95f1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/RevDetails.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class RevDetails
+		: Asn1Encodable
+	{
+		private readonly CertTemplate certDetails;
+		private readonly X509Extensions crlEntryDetails;
+
+		private RevDetails(Asn1Sequence seq)
+		{
+			certDetails = CertTemplate.GetInstance(seq[0]);
+
+			if  (seq.Count > 1)
+			{
+				crlEntryDetails = X509Extensions.GetInstance(seq[1]);
+			}
+		}
+
+		public static RevDetails GetInstance(object obj)
+		{
+			if (obj is RevDetails)
+				return (RevDetails)obj;
+
+			if (obj is Asn1Sequence)
+				return new RevDetails((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public RevDetails(CertTemplate certDetails)
+		{
+			this.certDetails = certDetails;
+		}
+		
+		public RevDetails(CertTemplate certDetails, X509Extensions crlEntryDetails)
+		{
+			this.crlEntryDetails = crlEntryDetails;
+		}
+
+		public virtual CertTemplate CertDetails
+		{
+			get { return certDetails; }
+		}
+
+		public virtual X509Extensions CrlEntryDetails
+		{
+			get { return crlEntryDetails; }
+		}
+
+		/**
+		* <pre>
+		* RevDetails ::= SEQUENCE {
+		*                  certDetails         CertTemplate,
+		*                   -- allows requester to specify as much as they can about
+		*                   -- the cert. for which revocation is requested
+		*                   -- (e.g., for cases in which serialNumber is not available)
+		*                   crlEntryDetails     Extensions       OPTIONAL
+		*                   -- requested crlEntryExtensions
+		*             }
+		* </pre>
+		* @return a basic ASN.1 object representation.
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certDetails);
+			v.AddOptional(crlEntryDetails);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContent.cs
new file mode 100644
index 0000000..4798726
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContent.cs
@@ -0,0 +1,112 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class RevRepContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence status;
+		private readonly Asn1Sequence revCerts;
+		private readonly Asn1Sequence crls;
+
+		private RevRepContent(Asn1Sequence seq)
+		{
+			status = Asn1Sequence.GetInstance(seq[0]);
+
+			for (int pos = 1; pos < seq.Count; ++pos)
+			{
+				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[pos]);
+
+				if (tObj.TagNo == 0)
+				{
+					revCerts = Asn1Sequence.GetInstance(tObj, true);
+				}
+				else
+				{
+					crls = Asn1Sequence.GetInstance(tObj, true);
+				}
+			}
+		}
+
+		public static RevRepContent GetInstance(object obj)
+		{
+			if (obj is RevRepContent)
+				return (RevRepContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new RevRepContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+		
+		public virtual PkiStatusInfo[] GetStatus()
+		{
+			PkiStatusInfo[] results = new PkiStatusInfo[status.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = PkiStatusInfo.GetInstance(status[i]);
+			}
+			return results;
+		}
+
+		public virtual CertId[] GetRevCerts()
+		{
+			if (revCerts == null)
+				return null;
+
+			CertId[] results = new CertId[revCerts.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CertId.GetInstance(revCerts[i]);
+			}
+			return results;
+		}
+
+		public virtual CertificateList[] GetCrls()
+		{
+			if (crls == null)
+				return null;
+
+			CertificateList[] results = new CertificateList[crls.Count];
+			for (int i = 0; i != results.Length; ++i)
+			{
+				results[i] = CertificateList.GetInstance(crls[i]);
+			}
+			return results;
+		}
+
+		/**
+		 * <pre>
+		 * RevRepContent ::= SEQUENCE {
+		 *        status       SEQUENCE SIZE (1..MAX) OF PKIStatusInfo,
+		 *        -- in same order as was sent in RevReqContent
+		 *        revCerts [0] SEQUENCE SIZE (1..MAX) OF CertId OPTIONAL,
+		 *        -- IDs for which revocation was requested
+		 *        -- (same order as status)
+		 *        crls     [1] SEQUENCE SIZE (1..MAX) OF CertificateList OPTIONAL
+		 *        -- the resulting CRLs (there may be more than one)
+		 *   }
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(status);
+			AddOptional(v, 0, revCerts);
+			AddOptional(v, 1, crls);
+			return new DerSequence(v);
+		}
+
+		private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+		{
+			if (obj != null)
+			{
+				v.Add(new DerTaggedObject(true, tagNo, obj));
+			}
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContentBuilder.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContentBuilder.cs
new file mode 100644
index 0000000..cc17d1d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/RevRepContentBuilder.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Crmf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class RevRepContentBuilder
+	{
+		private readonly Asn1EncodableVector status = new Asn1EncodableVector();
+		private readonly Asn1EncodableVector revCerts = new Asn1EncodableVector();
+		private readonly Asn1EncodableVector crls = new Asn1EncodableVector();
+
+		public virtual RevRepContentBuilder Add(PkiStatusInfo status)
+		{
+			this.status.Add(status);
+			return this;
+		}
+
+		public virtual RevRepContentBuilder Add(PkiStatusInfo status, CertId certId)
+		{
+			if (this.status.Count != this.revCerts.Count)
+				throw new InvalidOperationException("status and revCerts sequence must be in common order");
+
+			this.status.Add(status);
+			this.revCerts.Add(certId);
+			return this;
+		}
+
+		public virtual RevRepContentBuilder AddCrl(CertificateList crl)
+		{
+			this.crls.Add(crl);
+			return this;
+		}
+
+		public virtual RevRepContent Build()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			v.Add(new DerSequence(status));
+
+			if (revCerts.Count != 0)
+			{
+				v.Add(new DerTaggedObject(true, 0, new DerSequence(revCerts)));
+			}
+
+			if (crls.Count != 0)
+			{
+				v.Add(new DerTaggedObject(true, 1, new DerSequence(crls)));
+			}
+
+			return RevRepContent.GetInstance(new DerSequence(v));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cmp/RevReqContent.cs b/BouncyCastle.AxCrypt/src/asn1/cmp/RevReqContent.cs
new file mode 100644
index 0000000..fbf8692
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cmp/RevReqContent.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cmp
+{
+	public class RevReqContent
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence content;
+		
+		private RevReqContent(Asn1Sequence seq)
+		{
+			content = seq;
+		}
+
+		public static RevReqContent GetInstance(object obj)
+		{
+			if (obj is RevReqContent)
+				return (RevReqContent)obj;
+
+			if (obj is Asn1Sequence)
+				return new RevReqContent((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+		}
+
+		public RevReqContent(params RevDetails[] revDetails)
+		{
+			this.content = new DerSequence(revDetails);
+		}
+
+		public virtual RevDetails[] ToRevDetailsArray()
+		{
+			RevDetails[] result = new RevDetails[content.Count];
+			for (int i = 0; i != result.Length; ++i)
+			{
+				result[i] = RevDetails.GetInstance(content[i]);
+			}
+			return result;
+		}
+
+		/**
+		 * <pre>
+		 * RevReqContent ::= SEQUENCE OF RevDetails
+		 * </pre>
+		 * @return a basic ASN.1 object representation.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return content;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/Attribute.cs b/BouncyCastle.AxCrypt/src/asn1/cms/Attribute.cs
new file mode 100644
index 0000000..c4a104a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/Attribute.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class Attribute
+        : Asn1Encodable
+    {
+        private DerObjectIdentifier	attrType;
+        private Asn1Set				attrValues;
+
+		/**
+        * return an Attribute object from the given object.
+        *
+        * @param o the object we want converted.
+        * @exception ArgumentException if the object cannot be converted.
+        */
+        public static Attribute GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Attribute)
+				return (Attribute) obj;
+
+			if (obj is Asn1Sequence)
+                return new Attribute((Asn1Sequence) obj);
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public Attribute(
+            Asn1Sequence seq)
+        {
+            attrType = (DerObjectIdentifier)seq[0];
+            attrValues = (Asn1Set)seq[1];
+        }
+
+		public Attribute(
+            DerObjectIdentifier attrType,
+            Asn1Set             attrValues)
+        {
+            this.attrType = attrType;
+            this.attrValues = attrValues;
+        }
+
+        public DerObjectIdentifier AttrType
+		{
+			get { return attrType; }
+		}
+
+		public Asn1Set AttrValues
+		{
+			get { return attrValues; }
+		}
+
+		/**
+        * Produce an object suitable for an Asn1OutputStream.
+        * <pre>
+        * Attribute ::= SEQUENCE {
+        *     attrType OBJECT IDENTIFIER,
+        *     attrValues SET OF AttributeValue
+        * }
+        * </pre>
+        */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(attrType, attrValues);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/AttributeTable.cs b/BouncyCastle.AxCrypt/src/asn1/cms/AttributeTable.cs
new file mode 100644
index 0000000..8a3ee5d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/AttributeTable.cs
@@ -0,0 +1,231 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class AttributeTable
+    {
+        private readonly IDictionary attributes;
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public AttributeTable(
+            Hashtable attrs)
+        {
+            this.attributes = Platform.CreateHashtable(attrs);
+        }
+#endif
+
+        public AttributeTable(
+            IDictionary attrs)
+        {
+            this.attributes = Platform.CreateHashtable(attrs);
+        }
+
+        public AttributeTable(
+            Asn1EncodableVector v)
+        {
+            this.attributes = Platform.CreateHashtable(v.Count);
+
+			foreach (Asn1Encodable o in v)
+            {
+                Attribute a = Attribute.GetInstance(o);
+
+				AddAttribute(a);
+            }
+        }
+
+        public AttributeTable(
+            Asn1Set s)
+        {
+            this.attributes = Platform.CreateHashtable(s.Count);
+
+			for (int i = 0; i != s.Count; i++)
+            {
+                Attribute a = Attribute.GetInstance(s[i]);
+
+                AddAttribute(a);
+            }
+        }
+
+		public AttributeTable(
+			Attributes attrs)
+			: this(Asn1Set.GetInstance(attrs.ToAsn1Object()))
+		{
+		}
+
+		private void AddAttribute(
+            Attribute a)
+        {
+			DerObjectIdentifier oid = a.AttrType;
+            object obj = attributes[oid];
+
+            if (obj == null)
+            {
+                attributes[oid] = a;
+            }
+            else
+            {
+                IList v;
+
+                if (obj is Attribute)
+                {
+                    v = Platform.CreateArrayList();
+
+                    v.Add(obj);
+                    v.Add(a);
+                }
+                else
+                {
+                    v = (IList) obj;
+
+                    v.Add(a);
+                }
+
+                attributes[oid] = v;
+            }
+        }
+
+		/// <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary>
+		public Attribute this[DerObjectIdentifier oid]
+		{
+			get
+			{
+				object obj = attributes[oid];
+
+				if (obj is IList)
+				{
+					return (Attribute)((IList)obj)[0];
+				}
+
+				return (Attribute) obj;
+			}
+		}
+
+		[Obsolete("Use 'object[oid]' syntax instead")]
+        public Attribute Get(
+            DerObjectIdentifier oid)
+        {
+			return this[oid];
+        }
+
+		/**
+        * Return all the attributes matching the OBJECT IDENTIFIER oid. The vector will be
+        * empty if there are no attributes of the required type present.
+        *
+        * @param oid type of attribute required.
+        * @return a vector of all the attributes found of type oid.
+        */
+        public Asn1EncodableVector GetAll(
+            DerObjectIdentifier oid)
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            object obj = attributes[oid];
+
+			if (obj is IList)
+            {
+                foreach (Attribute a in (IList)obj)
+                {
+                    v.Add(a);
+                }
+            }
+            else if (obj != null)
+            {
+                v.Add((Attribute) obj);
+            }
+
+			return v;
+        }
+
+		public int Count
+		{
+			get
+			{
+				int total = 0;
+
+				foreach (object o in attributes.Values)
+				{
+					if (o is IList)
+					{
+						total += ((IList)o).Count;
+					}
+					else
+					{
+						++total;
+					}
+				}
+
+				return total;
+			}
+		}
+
+        public IDictionary ToDictionary()
+        {
+            return Platform.CreateHashtable(attributes);
+        }
+
+#if !SILVERLIGHT
+        [Obsolete("Use 'ToDictionary' instead")]
+		public Hashtable ToHashtable()
+        {
+            return new Hashtable(attributes);
+        }
+#endif
+
+		public Asn1EncodableVector ToAsn1EncodableVector()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			foreach (object obj in attributes.Values)
+            {
+                if (obj is IList)
+                {
+                    foreach (object el in (IList)obj)
+                    {
+                        v.Add(Attribute.GetInstance(el));
+                    }
+                }
+                else
+                {
+                    v.Add(Attribute.GetInstance(obj));
+                }
+            }
+
+			return v;
+        }
+
+		public Attributes ToAttributes()
+		{
+			return new Attributes(this.ToAsn1EncodableVector());
+		}
+
+		/**
+		 * Return a new table with the passed in attribute added.
+		 *
+		 * @param attrType
+		 * @param attrValue
+		 * @return
+		 */
+		public AttributeTable Add(DerObjectIdentifier attrType, Asn1Encodable attrValue)
+		{
+			AttributeTable newTable = new AttributeTable(attributes);
+
+			newTable.AddAttribute(new Attribute(attrType, new DerSet(attrValue)));
+
+			return newTable;
+		}
+
+		public AttributeTable Remove(DerObjectIdentifier attrType)
+		{
+			AttributeTable newTable = new AttributeTable(attributes);
+
+			newTable.attributes.Remove(attrType);
+
+			return newTable;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/Attributes.cs b/BouncyCastle.AxCrypt/src/asn1/cms/Attributes.cs
new file mode 100644
index 0000000..5b6b130
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/Attributes.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class Attributes
+        : Asn1Encodable
+    {
+        private readonly Asn1Set attributes;
+
+        private Attributes(Asn1Set attributes)
+        {
+            this.attributes = attributes;
+        }
+
+        public Attributes(Asn1EncodableVector v)
+        {
+            attributes = new BerSet(v);
+        }
+
+        public static Attributes GetInstance(object obj)
+        {
+            if (obj is Attributes)
+                return (Attributes)obj;
+
+            if (obj != null)
+                return new Attributes(Asn1Set.GetInstance(obj));
+
+            return null;
+        }
+
+        public virtual Attribute[] GetAttributes()
+        {
+            Attribute[] rv = new Attribute[attributes.Count];
+
+            for (int i = 0; i != rv.Length; i++)
+            {
+                rv[i] = Attribute.GetInstance(attributes[i]);
+            }
+
+            return rv;
+        }
+
+        /**
+         * <pre>
+         * Attributes ::=
+         *   SET SIZE(1..MAX) OF Attribute -- according to RFC 5652
+         * </pre>
+         * @return
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return attributes;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedData.cs
new file mode 100644
index 0000000..4260d80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedData.cs
@@ -0,0 +1,203 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class AuthEnvelopedData
+		: Asn1Encodable
+	{
+		private DerInteger				version;
+		private OriginatorInfo			originatorInfo;
+		private Asn1Set					recipientInfos;
+		private EncryptedContentInfo	authEncryptedContentInfo;
+		private Asn1Set					authAttrs;
+		private Asn1OctetString			mac;
+		private Asn1Set					unauthAttrs;
+
+		public AuthEnvelopedData(
+			OriginatorInfo			originatorInfo,
+			Asn1Set					recipientInfos,
+			EncryptedContentInfo	authEncryptedContentInfo,
+			Asn1Set					authAttrs,
+			Asn1OctetString			mac,
+			Asn1Set					unauthAttrs)
+		{
+			// "It MUST be set to 0."
+			this.version = new DerInteger(0);
+
+			this.originatorInfo = originatorInfo;
+
+			// TODO
+			// "There MUST be at least one element in the collection."
+			this.recipientInfos = recipientInfos;
+
+			this.authEncryptedContentInfo = authEncryptedContentInfo;
+
+			// TODO
+			// "The authAttrs MUST be present if the content type carried in
+			// EncryptedContentInfo is not id-data."
+			this.authAttrs = authAttrs;
+
+			this.mac = mac;
+
+			this.unauthAttrs = unauthAttrs;
+	    }
+
+		private AuthEnvelopedData(
+			Asn1Sequence	seq)
+		{
+			int index = 0;
+
+			// TODO
+			// "It MUST be set to 0."
+			Asn1Object tmp = seq[index++].ToAsn1Object();
+			version = (DerInteger)tmp;
+
+			tmp = seq[index++].ToAsn1Object();
+			if (tmp is Asn1TaggedObject)
+			{
+				originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false);
+				tmp = seq[index++].ToAsn1Object();
+			}
+
+			// TODO
+			// "There MUST be at least one element in the collection."
+			recipientInfos = Asn1Set.GetInstance(tmp);
+
+			tmp = seq[index++].ToAsn1Object();
+			authEncryptedContentInfo = EncryptedContentInfo.GetInstance(tmp);
+
+			tmp = seq[index++].ToAsn1Object();
+			if (tmp is Asn1TaggedObject)
+			{
+				authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+				tmp = seq[index++].ToAsn1Object();
+			}
+			else
+			{
+				// TODO
+				// "The authAttrs MUST be present if the content type carried in
+				// EncryptedContentInfo is not id-data."
+			}
+
+			mac = Asn1OctetString.GetInstance(tmp);
+
+			if (seq.Count > index)
+			{
+				tmp = seq[index++].ToAsn1Object();
+				unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+			}
+		}
+
+		/**
+		 * return an AuthEnvelopedData object from a tagged object.
+		 *
+		 * @param obj      the tagged object holding the object we want.
+		 * @param isExplicit true if the object is meant to be explicitly
+		 *                 tagged false otherwise.
+		 * @throws ArgumentException if the object held by the
+		 *                                  tagged object cannot be converted.
+		 */
+		public static AuthEnvelopedData GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		/**
+		 * return an AuthEnvelopedData object from the given object.
+		 *
+		 * @param obj the object we want converted.
+		 * @throws ArgumentException if the object cannot be converted.
+		 */
+		public static AuthEnvelopedData GetInstance(
+			object	obj)
+		{
+			if (obj == null || obj is AuthEnvelopedData)
+				return (AuthEnvelopedData)obj;
+
+			if (obj is Asn1Sequence)
+				return new AuthEnvelopedData((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid AuthEnvelopedData: " + obj.GetType().Name);
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public OriginatorInfo OriginatorInfo
+		{
+			get { return originatorInfo; }
+		}
+
+		public Asn1Set RecipientInfos
+		{
+			get { return recipientInfos; }
+		}
+
+		public EncryptedContentInfo AuthEncryptedContentInfo
+		{
+			get { return authEncryptedContentInfo; }
+		}
+
+		public Asn1Set AuthAttrs
+		{
+			get { return authAttrs; }
+		}
+
+		public Asn1OctetString Mac
+		{
+			get { return mac; }
+		}
+
+		public Asn1Set UnauthAttrs
+		{
+			get { return unauthAttrs; }
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * <pre>
+		 * AuthEnvelopedData ::= SEQUENCE {
+		 *   version CMSVersion,
+		 *   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+		 *   recipientInfos RecipientInfos,
+		 *   authEncryptedContentInfo EncryptedContentInfo,
+		 *   authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+		 *   mac MessageAuthenticationCode,
+		 *   unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+		 * </pre>
+		 */
+	    public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+			if (originatorInfo != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, originatorInfo));
+			}
+
+			v.Add(recipientInfos, authEncryptedContentInfo);
+
+			// "authAttrs optionally contains the authenticated attributes."
+			if (authAttrs != null)
+			{
+				// "AuthAttributes MUST be DER encoded, even if the rest of the
+				// AuthEnvelopedData structure is BER encoded."
+				v.Add(new DerTaggedObject(false, 1, authAttrs));
+			}
+
+			v.Add(mac);
+
+			// "unauthAttrs optionally contains the unauthenticated attributes."
+			if (unauthAttrs != null)
+			{
+				v.Add(new DerTaggedObject(false, 2, unauthAttrs));
+			}
+
+			return new BerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedDataParser.cs
new file mode 100644
index 0000000..35cb3bf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/AuthEnvelopedDataParser.cs
@@ -0,0 +1,145 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	 * Produce an object suitable for an Asn1OutputStream.
+	 * 
+	 * <pre>
+	 * AuthEnvelopedData ::= SEQUENCE {
+	 *   version CMSVersion,
+	 *   originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+	 *   recipientInfos RecipientInfos,
+	 *   authEncryptedContentInfo EncryptedContentInfo,
+	 *   authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
+	 *   mac MessageAuthenticationCode,
+	 *   unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL }
+	 * </pre>
+	*/
+	public class AuthEnvelopedDataParser
+	{
+		private Asn1SequenceParser	seq;
+		private DerInteger			version;
+		private IAsn1Convertible	nextObject;
+		private bool				originatorInfoCalled;
+
+		public AuthEnvelopedDataParser(
+			Asn1SequenceParser	seq)
+		{
+			this.seq = seq;
+
+			// TODO
+			// "It MUST be set to 0."
+			this.version = (DerInteger)seq.ReadObject();
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public OriginatorInfo GetOriginatorInfo()
+		{
+			originatorInfoCalled = true;
+
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0)
+			{
+				Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+				nextObject = null;
+				return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+			}
+
+			return null;
+		}
+
+		public Asn1SetParser GetRecipientInfos()
+		{
+			if (!originatorInfoCalled)
+			{
+				GetOriginatorInfo();
+			}
+
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			Asn1SetParser recipientInfos = (Asn1SetParser)nextObject;
+			nextObject = null;
+			return recipientInfos;
+		}
+
+		public EncryptedContentInfoParser GetAuthEncryptedContentInfo() 
+		{
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			if (nextObject != null)
+			{
+				Asn1SequenceParser o = (Asn1SequenceParser) nextObject;
+				nextObject = null;
+				return new EncryptedContentInfoParser(o);
+			}
+
+			return null;
+		}
+		
+		public Asn1SetParser GetAuthAttrs()
+		{
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			if (nextObject is Asn1TaggedObjectParser)
+			{
+				IAsn1Convertible o = nextObject;
+				nextObject = null;
+				return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+			}
+
+			// TODO
+			// "The authAttrs MUST be present if the content type carried in
+			// EncryptedContentInfo is not id-data."
+
+			return null;
+		}
+		
+		public Asn1OctetString GetMac()
+		{
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			IAsn1Convertible o = nextObject;
+			nextObject = null;
+
+			return Asn1OctetString.GetInstance(o.ToAsn1Object());
+		}
+		
+		public Asn1SetParser GetUnauthAttrs()
+		{
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			if (nextObject != null)
+			{
+				IAsn1Convertible o = nextObject;
+				nextObject = null;
+				return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+			}
+
+			return null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedData.cs
new file mode 100644
index 0000000..15286d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedData.cs
@@ -0,0 +1,270 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class AuthenticatedData
+		: Asn1Encodable
+	{
+		private DerInteger version;
+		private OriginatorInfo originatorInfo;
+		private Asn1Set recipientInfos;
+		private AlgorithmIdentifier macAlgorithm;
+		private AlgorithmIdentifier digestAlgorithm;
+		private ContentInfo encapsulatedContentInfo;
+		private Asn1Set authAttrs;
+		private Asn1OctetString mac;
+		private Asn1Set unauthAttrs;
+
+		public AuthenticatedData(
+			OriginatorInfo		originatorInfo,
+			Asn1Set				recipientInfos,
+			AlgorithmIdentifier	macAlgorithm,
+			AlgorithmIdentifier	digestAlgorithm,
+			ContentInfo			encapsulatedContent,
+			Asn1Set				authAttrs,
+			Asn1OctetString		mac,
+			Asn1Set				unauthAttrs)
+		{
+			if (digestAlgorithm != null || authAttrs != null)
+			{
+				if (digestAlgorithm == null || authAttrs == null)
+				{
+					throw new ArgumentException("digestAlgorithm and authAttrs must be set together");
+				}
+			}
+
+			version = new DerInteger(CalculateVersion(originatorInfo));
+
+			this.originatorInfo = originatorInfo;
+			this.macAlgorithm = macAlgorithm;
+			this.digestAlgorithm = digestAlgorithm;
+			this.recipientInfos = recipientInfos;
+			this.encapsulatedContentInfo = encapsulatedContent;
+			this.authAttrs = authAttrs;
+			this.mac = mac;
+			this.unauthAttrs = unauthAttrs;
+		}
+
+		private AuthenticatedData(
+			Asn1Sequence	seq)
+		{
+			int index = 0;
+
+			version = (DerInteger)seq[index++];
+
+			Asn1Encodable tmp = seq[index++];
+			if (tmp is Asn1TaggedObject)
+			{
+				originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject)tmp, false);
+				tmp = seq[index++];
+			}
+
+			recipientInfos = Asn1Set.GetInstance(tmp);
+			macAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]);
+
+			tmp = seq[index++];
+			if (tmp is Asn1TaggedObject)
+			{
+				digestAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject)tmp, false);
+				tmp = seq[index++];
+			}
+
+			encapsulatedContentInfo = ContentInfo.GetInstance(tmp);
+
+			tmp = seq[index++];
+			if (tmp is Asn1TaggedObject)
+			{
+				authAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false);
+				tmp = seq[index++];
+			}
+
+			mac = Asn1OctetString.GetInstance(tmp);
+
+			if (seq.Count > index)
+			{
+				unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false);
+			}
+		}
+
+		/**
+		 * return an AuthenticatedData object from a tagged object.
+		 *
+		 * @param obj      the tagged object holding the object we want.
+		 * @param isExplicit true if the object is meant to be explicitly
+		 *                 tagged false otherwise.
+		 * @throws ArgumentException if the object held by the
+		 *                                  tagged object cannot be converted.
+		 */
+		public static AuthenticatedData GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		/**
+		 * return an AuthenticatedData object from the given object.
+		 *
+		 * @param obj the object we want converted.
+		 * @throws ArgumentException if the object cannot be converted.
+		 */
+		public static AuthenticatedData GetInstance(
+			object	obj)
+		{
+			if (obj == null || obj is AuthenticatedData)
+			{
+				return (AuthenticatedData)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new AuthenticatedData((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Invalid AuthenticatedData: " + obj.GetType().Name);
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public OriginatorInfo OriginatorInfo
+		{
+			get { return originatorInfo; }
+		}
+
+		public Asn1Set RecipientInfos
+		{
+			get { return recipientInfos; }
+		}
+
+		public AlgorithmIdentifier MacAlgorithm
+		{
+			get { return macAlgorithm; }
+		}
+
+        public AlgorithmIdentifier DigestAlgorithm
+        {
+            get { return digestAlgorithm; }
+        }
+
+		public ContentInfo EncapsulatedContentInfo
+		{
+			get { return encapsulatedContentInfo; }
+		}
+
+		public Asn1Set AuthAttrs
+		{
+			get { return authAttrs; }
+		}
+
+		public Asn1OctetString Mac
+		{
+			get { return mac; }
+		}
+
+		public Asn1Set UnauthAttrs
+		{
+			get { return unauthAttrs; }
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * <pre>
+		 * AuthenticatedData ::= SEQUENCE {
+		 *       version CMSVersion,
+		 *       originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+		 *       recipientInfos RecipientInfos,
+		 *       macAlgorithm MessageAuthenticationCodeAlgorithm,
+		 *       digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+		 *       encapContentInfo EncapsulatedContentInfo,
+		 *       authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+		 *       mac MessageAuthenticationCode,
+		 *       unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+		 *
+		 * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+		 *
+		 * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+		 *
+		 * MessageAuthenticationCode ::= OCTET STRING
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+			if (originatorInfo != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, originatorInfo));
+			}
+
+			v.Add(recipientInfos, macAlgorithm);
+
+			if (digestAlgorithm != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, digestAlgorithm));
+			}
+
+			v.Add(encapsulatedContentInfo);
+
+			if (authAttrs != null)
+			{
+				v.Add(new DerTaggedObject(false, 2, authAttrs));
+			}
+
+			v.Add(mac);
+
+			if (unauthAttrs != null)
+			{
+				v.Add(new DerTaggedObject(false, 3, unauthAttrs));
+			}
+
+			return new BerSequence(v);
+		}
+
+		public static int CalculateVersion(OriginatorInfo origInfo)
+		{
+			if (origInfo == null)
+				return 0;
+
+			int ver = 0;
+
+			foreach (object obj in origInfo.Certificates)
+			{
+				if (obj is Asn1TaggedObject)
+				{
+					Asn1TaggedObject tag = (Asn1TaggedObject)obj;
+
+					if (tag.TagNo == 2)
+					{
+						ver = 1;
+					}
+					else if (tag.TagNo == 3)
+					{
+						ver = 3;
+						break;
+					}
+				}
+			}
+
+			foreach (object obj in origInfo.Crls)
+			{
+				if (obj is Asn1TaggedObject)
+				{
+					Asn1TaggedObject tag = (Asn1TaggedObject)obj;
+
+					if (tag.TagNo == 1)
+					{
+						ver = 3;
+						break;
+					}
+				}
+			}
+
+			return ver;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedDataParser.cs
new file mode 100644
index 0000000..4b80d1b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/AuthenticatedDataParser.cs
@@ -0,0 +1,182 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	 * Produce an object suitable for an Asn1OutputStream.
+	 * <pre>
+	 * AuthenticatedData ::= SEQUENCE {
+	 *       version CMSVersion,
+	 *       originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+	 *       recipientInfos RecipientInfos,
+	 *       macAlgorithm MessageAuthenticationCodeAlgorithm,
+	 *       digestAlgorithm [1] DigestAlgorithmIdentifier OPTIONAL,
+	 *       encapContentInfo EncapsulatedContentInfo,
+	 *       authAttrs [2] IMPLICIT AuthAttributes OPTIONAL,
+	 *       mac MessageAuthenticationCode,
+	 *       unauthAttrs [3] IMPLICIT UnauthAttributes OPTIONAL }
+	 *
+	 * AuthAttributes ::= SET SIZE (1..MAX) OF Attribute
+	 *
+	 * UnauthAttributes ::= SET SIZE (1..MAX) OF Attribute
+	 *
+	 * MessageAuthenticationCode ::= OCTET STRING
+	 * </pre>
+	 */
+	public class AuthenticatedDataParser
+	{
+	    private Asn1SequenceParser	seq;
+	    private DerInteger			version;
+	    private IAsn1Convertible	nextObject;
+	    private bool				originatorInfoCalled;
+
+	    public AuthenticatedDataParser(
+	        Asn1SequenceParser	seq)
+	    {
+	        this.seq = seq;
+	        this.version = (DerInteger)seq.ReadObject();
+	    }
+
+	    public DerInteger Version
+	    {
+	        get { return version; }
+	    }
+
+	    public OriginatorInfo GetOriginatorInfo()
+	    {
+	        originatorInfoCalled = true;
+
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        if (nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)nextObject).TagNo == 0)
+	        {
+	            Asn1SequenceParser originatorInfo = (Asn1SequenceParser) ((Asn1TaggedObjectParser)nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+	            nextObject = null;
+	            return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+	        }
+
+	        return null;
+	    }
+
+	    public Asn1SetParser GetRecipientInfos()
+	    {
+	        if (!originatorInfoCalled)
+	        {
+	            GetOriginatorInfo();
+	        }
+
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        Asn1SetParser recipientInfos = (Asn1SetParser)nextObject;
+	        nextObject = null;
+	        return recipientInfos;
+	    }
+
+	    public AlgorithmIdentifier GetMacAlgorithm()
+	    {
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        if (nextObject != null)
+	        {
+	            Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
+	            nextObject = null;
+	            return AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
+	        }
+
+	        return null;
+	    }
+
+		public AlgorithmIdentifier GetDigestAlgorithm()
+		{
+			if (nextObject == null)
+			{
+				nextObject = seq.ReadObject();
+			}
+
+			if (nextObject is Asn1TaggedObjectParser)
+			{
+				AlgorithmIdentifier obj = AlgorithmIdentifier.GetInstance(
+					(Asn1TaggedObject)nextObject.ToAsn1Object(), false);
+				nextObject = null;
+				return obj;
+			}
+
+			return null;
+		}
+
+	    public ContentInfoParser GetEnapsulatedContentInfo()
+	    {
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        if (nextObject != null)
+	        {
+	            Asn1SequenceParser o = (Asn1SequenceParser)nextObject;
+	            nextObject = null;
+	            return new ContentInfoParser(o);
+	        }
+
+	        return null;
+	    }
+
+	    public Asn1SetParser GetAuthAttrs()
+	    {
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        if (nextObject is Asn1TaggedObjectParser)
+	        {
+	            IAsn1Convertible o = nextObject;
+	            nextObject = null;
+	            return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+	        }
+
+	        return null;
+	    }
+
+	    public Asn1OctetString GetMac()
+	    {
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        IAsn1Convertible o = nextObject;
+	        nextObject = null;
+
+	        return Asn1OctetString.GetInstance(o.ToAsn1Object());
+	    }
+
+	    public Asn1SetParser GetUnauthAttrs()
+	    {
+	        if (nextObject == null)
+	        {
+	            nextObject = seq.ReadObject();
+	        }
+
+	        if (nextObject != null)
+	        {
+	            IAsn1Convertible o = nextObject;
+	            nextObject = null;
+	            return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+	        }
+
+	        return null;
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/CMSAttributes.cs b/BouncyCastle.AxCrypt/src/asn1/cms/CMSAttributes.cs
new file mode 100644
index 0000000..fca2b67
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/CMSAttributes.cs
@@ -0,0 +1,14 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public abstract class CmsAttributes
+    {
+        public static readonly DerObjectIdentifier ContentType		= PkcsObjectIdentifiers.Pkcs9AtContentType;
+        public static readonly DerObjectIdentifier MessageDigest	= PkcsObjectIdentifiers.Pkcs9AtMessageDigest;
+        public static readonly DerObjectIdentifier SigningTime		= PkcsObjectIdentifiers.Pkcs9AtSigningTime;
+		public static readonly DerObjectIdentifier CounterSignature = PkcsObjectIdentifiers.Pkcs9AtCounterSignature;
+		public static readonly DerObjectIdentifier ContentHint		= PkcsObjectIdentifiers.IdAAContentHint;
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/CMSObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/cms/CMSObjectIdentifiers.cs
new file mode 100644
index 0000000..2ad0a3c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/CMSObjectIdentifiers.cs
@@ -0,0 +1,28 @@
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public abstract class CmsObjectIdentifiers
+    {
+        public static readonly DerObjectIdentifier Data = PkcsObjectIdentifiers.Data;
+        public static readonly DerObjectIdentifier SignedData = PkcsObjectIdentifiers.SignedData;
+        public static readonly DerObjectIdentifier EnvelopedData = PkcsObjectIdentifiers.EnvelopedData;
+        public static readonly DerObjectIdentifier SignedAndEnvelopedData = PkcsObjectIdentifiers.SignedAndEnvelopedData;
+        public static readonly DerObjectIdentifier DigestedData = PkcsObjectIdentifiers.DigestedData;
+        public static readonly DerObjectIdentifier EncryptedData = PkcsObjectIdentifiers.EncryptedData;
+        public static readonly DerObjectIdentifier AuthenticatedData = PkcsObjectIdentifiers.IdCTAuthData;
+        public static readonly DerObjectIdentifier CompressedData = PkcsObjectIdentifiers.IdCTCompressedData;
+        public static readonly DerObjectIdentifier AuthEnvelopedData = PkcsObjectIdentifiers.IdCTAuthEnvelopedData;
+        public static readonly DerObjectIdentifier timestampedData = PkcsObjectIdentifiers.IdCTTimestampedData;
+
+        /**
+         * The other Revocation Info arc
+         * id-ri OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
+         *                                   dod(6) internet(1) security(5) mechanisms(5) pkix(7) ri(16) }
+         */
+        public static readonly DerObjectIdentifier id_ri = new DerObjectIdentifier("1.3.6.1.5.5.7.16");
+
+        public static readonly DerObjectIdentifier id_ri_ocsp_response = id_ri.Branch("2");
+        public static readonly DerObjectIdentifier id_ri_scvp = id_ri.Branch("4");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/CompressedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/CompressedData.cs
new file mode 100644
index 0000000..5a2869b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/CompressedData.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    /**
+     * RFC 3274 - CMS Compressed Data.
+     * <pre>
+     * CompressedData ::= Sequence {
+     *  version CMSVersion,
+     *  compressionAlgorithm CompressionAlgorithmIdentifier,
+     *  encapContentInfo EncapsulatedContentInfo
+     * }
+     * </pre>
+     */
+    public class CompressedData
+        : Asn1Encodable
+    {
+        private DerInteger			version;
+        private AlgorithmIdentifier	compressionAlgorithm;
+        private ContentInfo			encapContentInfo;
+
+		public CompressedData(
+            AlgorithmIdentifier	compressionAlgorithm,
+            ContentInfo			encapContentInfo)
+        {
+            this.version = new DerInteger(0);
+            this.compressionAlgorithm = compressionAlgorithm;
+            this.encapContentInfo = encapContentInfo;
+        }
+
+		public CompressedData(
+            Asn1Sequence seq)
+        {
+            this.version = (DerInteger) seq[0];
+            this.compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+            this.encapContentInfo = ContentInfo.GetInstance(seq[2]);
+        }
+
+		/**
+         * return a CompressedData object from a tagged object.
+         *
+         * @param ato the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static CompressedData GetInstance(
+            Asn1TaggedObject ato,
+            bool explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(ato, explicitly));
+        }
+
+        /**
+         * return a CompressedData object from the given object.
+         *
+         * @param _obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static CompressedData GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is CompressedData)
+                return (CompressedData)obj;
+
+			if (obj is Asn1Sequence)
+                return new CompressedData((Asn1Sequence) obj);
+
+			throw new ArgumentException("Invalid CompressedData: " + obj.GetType().Name);
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public AlgorithmIdentifier CompressionAlgorithmIdentifier
+		{
+			get { return compressionAlgorithm; }
+		}
+
+		public ContentInfo EncapContentInfo
+		{
+			get { return encapContentInfo; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new BerSequence(version, compressionAlgorithm, encapContentInfo);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/CompressedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/CompressedDataParser.cs
new file mode 100644
index 0000000..7c53453
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/CompressedDataParser.cs
@@ -0,0 +1,47 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	* RFC 3274 - CMS Compressed Data.
+	* <pre>
+	* CompressedData ::= SEQUENCE {
+	*  version CMSVersion,
+	*  compressionAlgorithm CompressionAlgorithmIdentifier,
+	*  encapContentInfo EncapsulatedContentInfo
+	* }
+	* </pre>
+	*/
+	public class CompressedDataParser
+	{
+		private DerInteger			_version;
+		private AlgorithmIdentifier	_compressionAlgorithm;
+		private ContentInfoParser	_encapContentInfo;
+
+		public CompressedDataParser(
+			Asn1SequenceParser seq)
+		{
+			this._version = (DerInteger)seq.ReadObject();
+			this._compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
+			this._encapContentInfo = new ContentInfoParser((Asn1SequenceParser)seq.ReadObject());
+		}
+
+		public DerInteger Version
+		{
+			get { return _version; }
+		}
+
+		public AlgorithmIdentifier CompressionAlgorithmIdentifier
+		{
+			get { return _compressionAlgorithm; }
+		}
+
+		public ContentInfoParser GetEncapContentInfo()
+		{
+			return _encapContentInfo;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfo.cs
new file mode 100644
index 0000000..278ceca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfo.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class ContentInfo
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	contentType;
+        private readonly Asn1Encodable			content;
+
+        public static ContentInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is ContentInfo)
+                return (ContentInfo) obj;
+
+            if (obj is Asn1Sequence)
+                return new ContentInfo((Asn1Sequence) obj);
+
+            throw new ArgumentException("unknown object in factory: " + obj.GetType().Name);
+        }
+
+        public static ContentInfo GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        private ContentInfo(
+            Asn1Sequence seq)
+        {
+            if (seq.Count < 1 || seq.Count > 2)
+                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            contentType = (DerObjectIdentifier) seq[0];
+
+            if (seq.Count > 1)
+            {
+                Asn1TaggedObject tagged = (Asn1TaggedObject) seq[1];
+                if (!tagged.IsExplicit() || tagged.TagNo != 0)
+                    throw new ArgumentException("Bad tag for 'content'", "seq");
+
+                content = tagged.GetObject();
+            }
+        }
+
+        public ContentInfo(
+            DerObjectIdentifier	contentType,
+            Asn1Encodable		content)
+        {
+            this.contentType = contentType;
+            this.content = content;
+        }
+
+        public DerObjectIdentifier ContentType
+        {
+            get { return contentType; }
+        }
+
+        public Asn1Encodable Content
+        {
+            get { return content; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ContentInfo ::= Sequence {
+         *          contentType ContentType,
+         *          content
+         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(contentType);
+
+            if (content != null)
+            {
+                v.Add(new BerTaggedObject(0, content));
+            }
+
+            return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfoParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfoParser.cs
new file mode 100644
index 0000000..541cc0f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/ContentInfoParser.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	* Produce an object suitable for an Asn1OutputStream.
+	* <pre>
+	* ContentInfo ::= SEQUENCE {
+	*          contentType ContentType,
+	*          content
+	*          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+	* </pre>
+	*/
+	public class ContentInfoParser
+	{
+		private DerObjectIdentifier		contentType;
+		private Asn1TaggedObjectParser	content;
+
+		public ContentInfoParser(
+			Asn1SequenceParser seq)
+		{
+			contentType = (DerObjectIdentifier)seq.ReadObject();
+			content = (Asn1TaggedObjectParser)seq.ReadObject();
+		}
+
+		public DerObjectIdentifier ContentType
+		{
+			get { return contentType; }
+		}
+
+		public IAsn1Convertible GetContent(
+			int tag)
+		{
+			if (content == null)
+				return null;
+
+			return content.GetObjectParser(tag, true);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfo.cs
new file mode 100644
index 0000000..4fdc471
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfo.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class EncryptedContentInfo
+        : Asn1Encodable
+    {
+        private DerObjectIdentifier	contentType;
+        private AlgorithmIdentifier	contentEncryptionAlgorithm;
+        private Asn1OctetString		encryptedContent;
+
+		public EncryptedContentInfo(
+            DerObjectIdentifier	contentType,
+            AlgorithmIdentifier	contentEncryptionAlgorithm,
+            Asn1OctetString		encryptedContent)
+        {
+            this.contentType = contentType;
+            this.contentEncryptionAlgorithm = contentEncryptionAlgorithm;
+            this.encryptedContent = encryptedContent;
+        }
+
+		public EncryptedContentInfo(
+            Asn1Sequence seq)
+        {
+            contentType = (DerObjectIdentifier) seq[0];
+            contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+
+			if (seq.Count > 2)
+            {
+                encryptedContent = Asn1OctetString.GetInstance(
+					(Asn1TaggedObject) seq[2], false);
+            }
+        }
+
+		/**
+         * return an EncryptedContentInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static EncryptedContentInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is EncryptedContentInfo)
+                return (EncryptedContentInfo)obj;
+
+			if (obj is Asn1Sequence)
+                return new EncryptedContentInfo((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid EncryptedContentInfo: " + obj.GetType().Name);
+        }
+
+        public DerObjectIdentifier ContentType
+        {
+            get { return contentType; }
+        }
+
+		public AlgorithmIdentifier ContentEncryptionAlgorithm
+        {
+			get { return contentEncryptionAlgorithm; }
+        }
+
+		public Asn1OctetString EncryptedContent
+        {
+			get { return encryptedContent; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * EncryptedContentInfo ::= Sequence {
+         *     contentType ContentType,
+         *     contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+         *     encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				contentType, contentEncryptionAlgorithm);
+
+			if (encryptedContent != null)
+            {
+                v.Add(new BerTaggedObject(false, 0, encryptedContent));
+            }
+
+			return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfoParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfoParser.cs
new file mode 100644
index 0000000..af748b1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedContentInfoParser.cs
@@ -0,0 +1,46 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	* <pre>
+	* EncryptedContentInfo ::= SEQUENCE {
+	*     contentType ContentType,
+	*     contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
+	*     encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+	* }
+	* </pre>
+	*/
+	public class EncryptedContentInfoParser
+	{
+		private DerObjectIdentifier		_contentType;
+		private AlgorithmIdentifier		_contentEncryptionAlgorithm;
+		private Asn1TaggedObjectParser	_encryptedContent;
+
+		public EncryptedContentInfoParser(
+			Asn1SequenceParser seq)
+		{
+			_contentType = (DerObjectIdentifier)seq.ReadObject();
+			_contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq.ReadObject().ToAsn1Object());
+			_encryptedContent = (Asn1TaggedObjectParser)seq.ReadObject();
+		}
+
+		public DerObjectIdentifier ContentType
+		{
+			get { return _contentType; }
+		}
+
+		public AlgorithmIdentifier ContentEncryptionAlgorithm
+		{
+			get { return _contentEncryptionAlgorithm; }
+		}
+
+		public IAsn1Convertible GetEncryptedContent(
+			int tag)
+		{
+			return _encryptedContent.GetObjectParser(tag, false);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedData.cs
new file mode 100644
index 0000000..5b83782
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/EncryptedData.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class EncryptedData
+		: Asn1Encodable
+	{
+		private readonly DerInteger				version;
+		private readonly EncryptedContentInfo	encryptedContentInfo;
+		private readonly Asn1Set				unprotectedAttrs;
+
+		public static EncryptedData GetInstance(
+			object obj)
+		{
+			if (obj is EncryptedData)
+				return (EncryptedData) obj;
+
+			if (obj is Asn1Sequence)
+				return new EncryptedData((Asn1Sequence) obj);
+
+			throw new ArgumentException("Invalid EncryptedData: " + obj.GetType().Name);
+		}
+
+		public EncryptedData(
+			EncryptedContentInfo encInfo)
+			: this(encInfo, null)
+		{
+		}
+
+		public EncryptedData(
+			EncryptedContentInfo	encInfo,
+			Asn1Set					unprotectedAttrs)
+		{
+			if (encInfo == null)
+				throw new ArgumentNullException("encInfo");
+
+			this.version = new DerInteger((unprotectedAttrs == null) ? 0 : 2);
+			this.encryptedContentInfo = encInfo;
+			this.unprotectedAttrs = unprotectedAttrs;
+		}
+
+		private EncryptedData(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 2 || seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.version = DerInteger.GetInstance(seq[0]);
+			this.encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[1]);
+
+			if (seq.Count > 2)
+			{
+				this.unprotectedAttrs = Asn1Set.GetInstance(seq[2]);
+			}
+		}
+
+		public virtual DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public virtual EncryptedContentInfo EncryptedContentInfo
+		{
+			get { return encryptedContentInfo; }
+		}
+
+		public virtual Asn1Set UnprotectedAttrs
+		{
+			get { return unprotectedAttrs; }
+		}
+
+		/**
+		* <pre>
+		*       EncryptedData ::= SEQUENCE {
+		*                     version CMSVersion,
+		*                     encryptedContentInfo EncryptedContentInfo,
+		*                     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
+		* </pre>
+		* @return a basic ASN.1 object representation.
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(version, encryptedContentInfo);
+
+			if (unprotectedAttrs != null)
+			{
+				v.Add(new BerTaggedObject(false, 1, unprotectedAttrs));
+			}
+
+			return new BerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedData.cs
new file mode 100644
index 0000000..09f291a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedData.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class EnvelopedData
+        : Asn1Encodable
+    {
+        private DerInteger				version;
+        private OriginatorInfo			originatorInfo;
+        private Asn1Set					recipientInfos;
+        private EncryptedContentInfo	encryptedContentInfo;
+        private Asn1Set					unprotectedAttrs;
+
+        public EnvelopedData(
+            OriginatorInfo			originatorInfo,
+            Asn1Set					recipientInfos,
+            EncryptedContentInfo	encryptedContentInfo,
+            Asn1Set					unprotectedAttrs)
+        {
+            this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
+            this.originatorInfo = originatorInfo;
+            this.recipientInfos = recipientInfos;
+            this.encryptedContentInfo = encryptedContentInfo;
+            this.unprotectedAttrs = unprotectedAttrs;
+        }
+
+        public EnvelopedData(
+            OriginatorInfo originatorInfo,
+            Asn1Set recipientInfos,
+            EncryptedContentInfo encryptedContentInfo,
+            Attributes unprotectedAttrs)
+        {
+            this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, Asn1Set.GetInstance(unprotectedAttrs)));
+            this.originatorInfo = originatorInfo;
+            this.recipientInfos = recipientInfos;
+            this.encryptedContentInfo = encryptedContentInfo;
+            this.unprotectedAttrs = Asn1Set.GetInstance(unprotectedAttrs);
+        }
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public EnvelopedData(
+            Asn1Sequence seq)
+        {
+            int index = 0;
+
+            version = (DerInteger) seq[index++];
+
+            object tmp = seq[index++];
+
+            if (tmp is Asn1TaggedObject)
+            {
+                originatorInfo = OriginatorInfo.GetInstance((Asn1TaggedObject) tmp, false);
+                tmp = seq[index++];
+            }
+
+            recipientInfos = Asn1Set.GetInstance(tmp);
+            encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[index++]);
+
+            if (seq.Count > index)
+            {
+                unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject) seq[index], false);
+            }
+        }
+
+        /**
+         * return an EnvelopedData object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static EnvelopedData GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        /**
+         * return an EnvelopedData object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static EnvelopedData GetInstance(
+            object obj)
+        {
+            if (obj is EnvelopedData)
+                return (EnvelopedData)obj;
+            if (obj == null)
+                return null;
+            return new EnvelopedData(Asn1Sequence.GetInstance(obj));
+        }
+
+        public DerInteger Version
+        {
+            get { return version; }
+        }
+
+        public OriginatorInfo OriginatorInfo
+        {
+            get { return originatorInfo; }
+        }
+
+        public Asn1Set RecipientInfos
+        {
+            get { return recipientInfos; }
+        }
+
+        public EncryptedContentInfo EncryptedContentInfo
+        {
+            get { return encryptedContentInfo; }
+        }
+
+        public Asn1Set UnprotectedAttrs
+        {
+            get { return unprotectedAttrs; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * EnvelopedData ::= Sequence {
+         *     version CMSVersion,
+         *     originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+         *     recipientInfos RecipientInfos,
+         *     encryptedContentInfo EncryptedContentInfo,
+         *     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+            if (originatorInfo != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, originatorInfo));
+            }
+
+            v.Add(recipientInfos, encryptedContentInfo);
+
+            if (unprotectedAttrs != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, unprotectedAttrs));
+            }
+
+            return new BerSequence(v);
+        }
+
+        public static int CalculateVersion(OriginatorInfo originatorInfo, Asn1Set recipientInfos, Asn1Set unprotectedAttrs)
+        {
+            if (originatorInfo != null || unprotectedAttrs != null)
+            {
+                return 2;
+            }
+
+            foreach (object o in recipientInfos)
+            {
+                RecipientInfo ri = RecipientInfo.GetInstance(o);
+
+                if (ri.Version.Value.IntValue != 0)
+                {
+                    return 2;
+                }
+            }
+
+            return 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedDataParser.cs
new file mode 100644
index 0000000..5993537
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/EnvelopedDataParser.cs
@@ -0,0 +1,107 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	* Produce an object suitable for an Asn1OutputStream.
+	* <pre>
+	* EnvelopedData ::= SEQUENCE {
+	*     version CMSVersion,
+	*     originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
+	*     recipientInfos RecipientInfos,
+	*     encryptedContentInfo EncryptedContentInfo,
+	*     unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL
+	* }
+	* </pre>
+	*/
+	public class EnvelopedDataParser
+	{
+		private Asn1SequenceParser	_seq;
+		private DerInteger			_version;
+		private IAsn1Convertible	_nextObject;
+		private bool				_originatorInfoCalled;
+
+		public EnvelopedDataParser(
+			Asn1SequenceParser seq)
+		{
+			this._seq = seq;
+			this._version = (DerInteger)seq.ReadObject();
+		}
+
+		public DerInteger Version
+		{
+			get { return _version; }
+		}
+
+		public OriginatorInfo GetOriginatorInfo() 
+		{
+			_originatorInfoCalled = true; 
+
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0)
+			{
+				Asn1SequenceParser originatorInfo = (Asn1SequenceParser)
+					((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Sequence, false);
+				_nextObject = null;
+				return OriginatorInfo.GetInstance(originatorInfo.ToAsn1Object());
+			}
+
+			return null;
+		}
+
+		public Asn1SetParser GetRecipientInfos()
+		{
+			if (!_originatorInfoCalled)
+			{
+				GetOriginatorInfo();
+			}
+
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			Asn1SetParser recipientInfos = (Asn1SetParser)_nextObject;
+			_nextObject = null;
+			return recipientInfos;
+		}
+
+		public EncryptedContentInfoParser GetEncryptedContentInfo()
+		{
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			if (_nextObject != null)
+			{
+				Asn1SequenceParser o = (Asn1SequenceParser) _nextObject;
+				_nextObject = null;
+				return new EncryptedContentInfoParser(o);
+			}
+
+			return null;
+		}
+
+		public Asn1SetParser GetUnprotectedAttrs()
+		{
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			if (_nextObject != null)
+			{
+				IAsn1Convertible o = _nextObject;
+				_nextObject = null;
+				return (Asn1SetParser)((Asn1TaggedObjectParser)o).GetObjectParser(Asn1Tags.Set, false);
+			}
+        
+			return null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/Evidence.cs b/BouncyCastle.AxCrypt/src/asn1/cms/Evidence.cs
new file mode 100644
index 0000000..4745e56
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/Evidence.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class Evidence
+		: Asn1Encodable, IAsn1Choice
+	{
+		private TimeStampTokenEvidence tstEvidence;
+
+		public Evidence(TimeStampTokenEvidence tstEvidence)
+		{
+			this.tstEvidence = tstEvidence;
+		}
+
+		private Evidence(Asn1TaggedObject tagged)
+		{
+			if (tagged.TagNo == 0)
+			{
+				this.tstEvidence = TimeStampTokenEvidence.GetInstance(tagged, false);
+			}
+		}
+
+		public static Evidence GetInstance(object obj)
+		{
+			if (obj is Evidence)
+				return (Evidence)obj;
+
+			if (obj is Asn1TaggedObject)
+				return new Evidence(Asn1TaggedObject.GetInstance(obj));
+
+			throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		public virtual TimeStampTokenEvidence TstEvidence
+		{
+			get { return tstEvidence; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			if (tstEvidence != null)
+				return new DerTaggedObject(false, 0, tstEvidence);
+
+			return null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/IssuerAndSerialNumber.cs b/BouncyCastle.AxCrypt/src/asn1/cms/IssuerAndSerialNumber.cs
new file mode 100644
index 0000000..b509e7e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/IssuerAndSerialNumber.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class IssuerAndSerialNumber
+        : Asn1Encodable
+    {
+        private X509Name	name;
+        private DerInteger	serialNumber;
+
+        public static IssuerAndSerialNumber GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            IssuerAndSerialNumber existing = obj as IssuerAndSerialNumber;
+            if (existing != null)
+                return existing;
+            return new IssuerAndSerialNumber(Asn1Sequence.GetInstance(obj));
+        }
+
+        [Obsolete("Use GetInstance() instead")]
+        public IssuerAndSerialNumber(
+            Asn1Sequence seq)
+        {
+            this.name = X509Name.GetInstance(seq[0]);
+            this.serialNumber = (DerInteger) seq[1];
+        }
+
+        public IssuerAndSerialNumber(
+            X509Name	name,
+            BigInteger	serialNumber)
+        {
+            this.name = name;
+            this.serialNumber = new DerInteger(serialNumber);
+        }
+
+        public IssuerAndSerialNumber(
+            X509Name	name,
+            DerInteger	serialNumber)
+        {
+            this.name = name;
+            this.serialNumber = serialNumber;
+        }
+
+        public X509Name Name
+        {
+            get { return name; }
+        }
+
+        public DerInteger SerialNumber
+        {
+            get { return serialNumber; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(name, serialNumber);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/KEKIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/cms/KEKIdentifier.cs
new file mode 100644
index 0000000..e5d1d90
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/KEKIdentifier.cs
@@ -0,0 +1,119 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class KekIdentifier
+        : Asn1Encodable
+    {
+        private Asn1OctetString		keyIdentifier;
+        private DerGeneralizedTime	date;
+        private OtherKeyAttribute	other;
+
+		public KekIdentifier(
+            byte[]              keyIdentifier,
+            DerGeneralizedTime  date,
+            OtherKeyAttribute   other)
+        {
+            this.keyIdentifier = new DerOctetString(keyIdentifier);
+            this.date = date;
+            this.other = other;
+        }
+
+		public KekIdentifier(
+            Asn1Sequence seq)
+        {
+            keyIdentifier = (Asn1OctetString) seq[0];
+
+			switch (seq.Count)
+            {
+            case 1:
+				break;
+            case 2:
+				if (seq[1] is DerGeneralizedTime)
+				{
+					date = (DerGeneralizedTime) seq[1];
+				}
+				else
+				{
+					other = OtherKeyAttribute.GetInstance(seq[2]);
+				}
+				break;
+            case 3:
+				date  = (DerGeneralizedTime) seq[1];
+				other = OtherKeyAttribute.GetInstance(seq[2]);
+				break;
+            default:
+				throw new ArgumentException("Invalid KekIdentifier");
+            }
+        }
+
+		/**
+         * return a KekIdentifier object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static KekIdentifier GetInstance(
+            Asn1TaggedObject obj,
+            bool explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        /**
+         * return a KekIdentifier object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static KekIdentifier GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is KekIdentifier)
+                return (KekIdentifier)obj;
+
+			if (obj is Asn1Sequence)
+                return new KekIdentifier((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid KekIdentifier: " + obj.GetType().Name);
+        }
+
+		public Asn1OctetString KeyIdentifier
+		{
+			get { return keyIdentifier; }
+		}
+
+		public DerGeneralizedTime Date
+		{
+			get { return date; }
+		}
+
+		public OtherKeyAttribute Other
+		{
+			get { return other; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * KekIdentifier ::= Sequence {
+         *     keyIdentifier OCTET STRING,
+         *     date GeneralizedTime OPTIONAL,
+         *     other OtherKeyAttribute OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(keyIdentifier);
+			v.AddOptional(date, other);
+			return new DerSequence(v);
+        }
+    }
+}
+
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/KEKRecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/KEKRecipientInfo.cs
new file mode 100644
index 0000000..d847b50
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/KEKRecipientInfo.cs
@@ -0,0 +1,106 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class KekRecipientInfo
+        : Asn1Encodable
+    {
+        private DerInteger			version;
+        private KekIdentifier       kekID;
+        private AlgorithmIdentifier keyEncryptionAlgorithm;
+        private Asn1OctetString     encryptedKey;
+
+		public KekRecipientInfo(
+            KekIdentifier       kekID,
+            AlgorithmIdentifier keyEncryptionAlgorithm,
+            Asn1OctetString     encryptedKey)
+        {
+            this.version = new DerInteger(4);
+            this.kekID = kekID;
+            this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+            this.encryptedKey = encryptedKey;
+        }
+
+		public KekRecipientInfo(
+            Asn1Sequence seq)
+        {
+            version = (DerInteger) seq[0];
+            kekID = KekIdentifier.GetInstance(seq[1]);
+            keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+            encryptedKey = (Asn1OctetString) seq[3];
+        }
+
+		/**
+         * return a KekRecipientInfo object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static KekRecipientInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        /**
+         * return a KekRecipientInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static KekRecipientInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is KekRecipientInfo)
+                return (KekRecipientInfo)obj;
+
+			if(obj is Asn1Sequence)
+                return new KekRecipientInfo((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid KekRecipientInfo: " + obj.GetType().Name);
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public KekIdentifier KekID
+		{
+			get { return kekID; }
+		}
+
+		public AlgorithmIdentifier KeyEncryptionAlgorithm
+		{
+			get { return keyEncryptionAlgorithm; }
+		}
+
+		public Asn1OctetString EncryptedKey
+		{
+			get { return encryptedKey; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * KekRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 4
+         *     kekID KekIdentifier,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     encryptedKey EncryptedKey
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(version, kekID, keyEncryptionAlgorithm, encryptedKey);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
new file mode 100644
index 0000000..fa6fdb0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientIdentifier.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class KeyAgreeRecipientIdentifier
+		: Asn1Encodable, IAsn1Choice
+	{
+		/**
+		 * return an KeyAgreeRecipientIdentifier object from a tagged object.
+		 *
+		 * @param obj the tagged object holding the object we want.
+		 * @param isExplicit true if the object is meant to be explicitly
+		 *              tagged false otherwise.
+		 * @exception ArgumentException if the object held by the
+		 *          tagged object cannot be converted.
+		 */
+		public static KeyAgreeRecipientIdentifier GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+    
+		/**
+		 * return an KeyAgreeRecipientIdentifier object from the given object.
+		 *
+		 * @param obj the object we want converted.
+		 * @exception ArgumentException if the object cannot be converted.
+		 */
+		public static KeyAgreeRecipientIdentifier GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is KeyAgreeRecipientIdentifier)
+				return (KeyAgreeRecipientIdentifier)obj;
+
+			if (obj is Asn1Sequence)
+				return new KeyAgreeRecipientIdentifier(IssuerAndSerialNumber.GetInstance(obj));
+
+			if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 0)
+			{
+				return new KeyAgreeRecipientIdentifier(RecipientKeyIdentifier.GetInstance(
+					(Asn1TaggedObject)obj, false));
+			}
+
+			throw new ArgumentException("Invalid KeyAgreeRecipientIdentifier: " + obj.GetType().FullName, "obj");
+		} 
+
+		private readonly IssuerAndSerialNumber issuerSerial;
+		private readonly RecipientKeyIdentifier rKeyID;
+
+		public KeyAgreeRecipientIdentifier(
+			IssuerAndSerialNumber issuerSerial)
+		{
+			this.issuerSerial = issuerSerial;
+		}
+
+		public KeyAgreeRecipientIdentifier(
+			RecipientKeyIdentifier rKeyID)
+		{
+			this.rKeyID = rKeyID;
+		}
+
+		public IssuerAndSerialNumber IssuerAndSerialNumber
+		{
+			get { return issuerSerial; }
+		}
+
+		public RecipientKeyIdentifier RKeyID
+		{
+			get { return rKeyID; }
+		}
+
+		/** 
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * <pre>
+		 * KeyAgreeRecipientIdentifier ::= CHOICE {
+		 *     issuerAndSerialNumber IssuerAndSerialNumber,
+		 *     rKeyId [0] IMPLICIT RecipientKeyIdentifier
+		 * }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			if (issuerSerial != null)
+			{
+				return issuerSerial.ToAsn1Object();
+			}
+
+			return new DerTaggedObject(false, 0, rKeyID);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientInfo.cs
new file mode 100644
index 0000000..aafb008
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/KeyAgreeRecipientInfo.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class KeyAgreeRecipientInfo
+        : Asn1Encodable
+    {
+        private DerInteger                  version;
+        private OriginatorIdentifierOrKey   originator;
+        private Asn1OctetString             ukm;
+        private AlgorithmIdentifier         keyEncryptionAlgorithm;
+        private Asn1Sequence                recipientEncryptedKeys;
+
+		public KeyAgreeRecipientInfo(
+            OriginatorIdentifierOrKey   originator,
+            Asn1OctetString             ukm,
+            AlgorithmIdentifier         keyEncryptionAlgorithm,
+            Asn1Sequence                recipientEncryptedKeys)
+        {
+            this.version = new DerInteger(3);
+            this.originator = originator;
+            this.ukm = ukm;
+            this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+            this.recipientEncryptedKeys = recipientEncryptedKeys;
+        }
+
+		public KeyAgreeRecipientInfo(
+            Asn1Sequence seq)
+        {
+            int index = 0;
+
+            version = (DerInteger) seq[index++];
+            originator = OriginatorIdentifierOrKey.GetInstance(
+				(Asn1TaggedObject) seq[index++], true);
+
+			if (seq[index] is Asn1TaggedObject)
+            {
+                ukm = Asn1OctetString.GetInstance(
+					(Asn1TaggedObject) seq[index++], true);
+            }
+
+			keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(
+				seq[index++]);
+
+			recipientEncryptedKeys = (Asn1Sequence) seq[index++];
+        }
+
+		/**
+         * return a KeyAgreeRecipientInfo object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static KeyAgreeRecipientInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		/**
+         * return a KeyAgreeRecipientInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static KeyAgreeRecipientInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is KeyAgreeRecipientInfo)
+                return (KeyAgreeRecipientInfo)obj;
+
+			if (obj is Asn1Sequence)
+                return new KeyAgreeRecipientInfo((Asn1Sequence)obj);
+
+			throw new ArgumentException(
+                "Illegal object in KeyAgreeRecipientInfo: " + obj.GetType().Name);
+
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public OriginatorIdentifierOrKey Originator
+		{
+			get { return originator; }
+		}
+
+		public Asn1OctetString UserKeyingMaterial
+		{
+			get { return ukm; }
+		}
+
+		public AlgorithmIdentifier KeyEncryptionAlgorithm
+		{
+			get { return keyEncryptionAlgorithm; }
+		}
+
+		public Asn1Sequence RecipientEncryptedKeys
+		{
+			get { return recipientEncryptedKeys; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * KeyAgreeRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 3
+         *     originator [0] EXPLICIT OriginatorIdentifierOrKey,
+         *     ukm [1] EXPLICIT UserKeyingMaterial OPTIONAL,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     recipientEncryptedKeys RecipientEncryptedKeys
+         * }
+		 *
+		 * UserKeyingMaterial ::= OCTET STRING
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				version, new DerTaggedObject(true, 0, originator));
+
+			if (ukm != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, ukm));
+            }
+
+			v.Add(keyEncryptionAlgorithm, recipientEncryptedKeys);
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/KeyTransRecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/KeyTransRecipientInfo.cs
new file mode 100644
index 0000000..aae18c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/KeyTransRecipientInfo.cs
@@ -0,0 +1,99 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class KeyTransRecipientInfo
+        : Asn1Encodable
+    {
+        private DerInteger          version;
+        private RecipientIdentifier rid;
+        private AlgorithmIdentifier keyEncryptionAlgorithm;
+        private Asn1OctetString     encryptedKey;
+
+		public KeyTransRecipientInfo(
+            RecipientIdentifier rid,
+            AlgorithmIdentifier keyEncryptionAlgorithm,
+            Asn1OctetString     encryptedKey)
+        {
+            if (rid.ToAsn1Object() is Asn1TaggedObject)
+            {
+                this.version = new DerInteger(2);
+            }
+            else
+            {
+                this.version = new DerInteger(0);
+            }
+
+			this.rid = rid;
+            this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+            this.encryptedKey = encryptedKey;
+        }
+
+		public KeyTransRecipientInfo(
+            Asn1Sequence seq)
+        {
+            this.version = (DerInteger) seq[0];
+            this.rid = RecipientIdentifier.GetInstance(seq[1]);
+            this.keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+            this.encryptedKey = (Asn1OctetString) seq[3];
+        }
+
+		/**
+         * return a KeyTransRecipientInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static KeyTransRecipientInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is KeyTransRecipientInfo)
+                return (KeyTransRecipientInfo) obj;
+
+			if(obj is Asn1Sequence)
+                return new KeyTransRecipientInfo((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Illegal object in KeyTransRecipientInfo: " + obj.GetType().Name);
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public RecipientIdentifier RecipientIdentifier
+		{
+			get { return rid; }
+		}
+
+		public AlgorithmIdentifier KeyEncryptionAlgorithm
+		{
+			get { return keyEncryptionAlgorithm; }
+		}
+
+		public Asn1OctetString EncryptedKey
+		{
+			get { return encryptedKey; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * KeyTransRecipientInfo ::= Sequence {
+         *     version CMSVersion,  -- always set to 0 or 2
+         *     rid RecipientIdentifier,
+         *     keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *     encryptedKey EncryptedKey
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(version, rid, keyEncryptionAlgorithm, encryptedKey);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/MetaData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/MetaData.cs
new file mode 100644
index 0000000..ad2b5c4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/MetaData.cs
@@ -0,0 +1,94 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class MetaData
+		: Asn1Encodable
+	{
+		private DerBoolean hashProtected;
+		private DerUtf8String fileName;
+		private DerIA5String  mediaType;
+		private Attributes otherMetaData;
+
+		public MetaData(
+			DerBoolean		hashProtected,
+			DerUtf8String	fileName,
+			DerIA5String	mediaType,
+			Attributes		otherMetaData)
+		{
+			this.hashProtected = hashProtected;
+			this.fileName = fileName;
+			this.mediaType = mediaType;
+			this.otherMetaData = otherMetaData;
+		}
+
+		private MetaData(Asn1Sequence seq)
+		{
+			this.hashProtected = DerBoolean.GetInstance(seq[0]);
+
+			int index = 1;
+
+			if (index < seq.Count && seq[index] is DerUtf8String)
+			{
+				this.fileName = DerUtf8String.GetInstance(seq[index++]);
+			}
+			if (index < seq.Count && seq[index] is DerIA5String)
+			{
+				this.mediaType = DerIA5String.GetInstance(seq[index++]);
+			}
+			if (index < seq.Count)
+			{
+				this.otherMetaData = Attributes.GetInstance(seq[index++]);
+			}
+		}
+
+		public static MetaData GetInstance(object obj)
+		{
+			if (obj is MetaData)
+				return (MetaData)obj;
+
+			if (obj != null)
+				return new MetaData(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		/**
+		 * <pre>
+		 * MetaData ::= SEQUENCE {
+		 *   hashProtected        BOOLEAN,
+		 *   fileName             UTF8String OPTIONAL,
+		 *   mediaType            IA5String OPTIONAL,
+		 *   otherMetaData        Attributes OPTIONAL
+		 * }
+		 * </pre>
+		 * @return
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(hashProtected);
+			v.AddOptional(fileName, mediaType, otherMetaData);
+			return new DerSequence(v);
+		}
+
+		public virtual bool IsHashProtected
+		{
+			get { return hashProtected.IsTrue; }
+		}
+
+		public virtual DerUtf8String FileName
+		{
+			get { return fileName; }
+		}
+
+		public virtual DerIA5String MediaType
+		{
+			get { return mediaType; }
+		}
+
+		public virtual Attributes OtherMetaData
+		{
+			get { return otherMetaData; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorIdentifierOrKey.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorIdentifierOrKey.cs
new file mode 100644
index 0000000..d33a117
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorIdentifierOrKey.cs
@@ -0,0 +1,168 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OriginatorIdentifierOrKey
+        : Asn1Encodable, IAsn1Choice
+    {
+        private Asn1Encodable id;
+
+        public OriginatorIdentifierOrKey(
+            IssuerAndSerialNumber id)
+        {
+            this.id = id;
+        }
+
+		[Obsolete("Use version taking a 'SubjectKeyIdentifier'")]
+        public OriginatorIdentifierOrKey(
+            Asn1OctetString id)
+			: this(new SubjectKeyIdentifier(id))
+        {
+        }
+
+        public OriginatorIdentifierOrKey(
+            SubjectKeyIdentifier id)
+        {
+            this.id = new DerTaggedObject(false, 0, id);
+        }
+
+        public OriginatorIdentifierOrKey(
+            OriginatorPublicKey id)
+        {
+            this.id = new DerTaggedObject(false, 1, id);
+        }
+
+		[Obsolete("Use more specific version")]
+        public OriginatorIdentifierOrKey(
+            Asn1Object id)
+        {
+            this.id = id;
+        }
+
+		private OriginatorIdentifierOrKey(
+			Asn1TaggedObject id)
+		{
+			// TODO Add validation
+			this.id = id;
+		}
+
+		/**
+         * return an OriginatorIdentifierOrKey object from a tagged object.
+         *
+         * @param o the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static OriginatorIdentifierOrKey GetInstance(
+            Asn1TaggedObject	o,
+            bool				explicitly)
+        {
+            if (!explicitly)
+            {
+                throw new ArgumentException(
+                        "Can't implicitly tag OriginatorIdentifierOrKey");
+            }
+
+			return GetInstance(o.GetObject());
+        }
+
+        /**
+         * return an OriginatorIdentifierOrKey object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static OriginatorIdentifierOrKey GetInstance(
+            object o)
+        {
+            if (o == null || o is OriginatorIdentifierOrKey)
+                return (OriginatorIdentifierOrKey)o;
+
+			if (o is IssuerAndSerialNumber)
+				return new OriginatorIdentifierOrKey((IssuerAndSerialNumber)o);
+
+			if (o is SubjectKeyIdentifier)
+				return new OriginatorIdentifierOrKey((SubjectKeyIdentifier)o);
+
+			if (o is OriginatorPublicKey)
+				return new OriginatorIdentifierOrKey((OriginatorPublicKey)o);
+
+			if (o is Asn1TaggedObject)
+				return new OriginatorIdentifierOrKey((Asn1TaggedObject)o);
+
+			throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + o.GetType().Name);
+        }
+
+		public Asn1Encodable ID
+		{
+			get { return id; }
+		}
+
+		public IssuerAndSerialNumber IssuerAndSerialNumber
+		{
+			get
+			{
+				if (id is IssuerAndSerialNumber)
+				{
+					return (IssuerAndSerialNumber)id;
+				}
+
+				return null;
+			}
+		}
+
+		public SubjectKeyIdentifier SubjectKeyIdentifier
+		{
+			get
+			{
+				if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 0)
+				{
+					return SubjectKeyIdentifier.GetInstance((Asn1TaggedObject)id, false);
+				}
+
+				return null;
+			}
+		}
+
+		[Obsolete("Use 'OriginatorPublicKey' property")]
+		public OriginatorPublicKey OriginatorKey
+		{
+			get { return OriginatorPublicKey; }
+		}
+
+		public OriginatorPublicKey OriginatorPublicKey
+		{
+			get
+			{
+				if (id is Asn1TaggedObject && ((Asn1TaggedObject)id).TagNo == 1)
+				{
+					return OriginatorPublicKey.GetInstance((Asn1TaggedObject)id, false);
+				}
+
+				return null;
+			}
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OriginatorIdentifierOrKey ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier,
+         *     originatorKey [1] OriginatorPublicKey
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return id.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorInfo.cs
new file mode 100644
index 0000000..b4549bc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorInfo.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OriginatorInfo
+        : Asn1Encodable
+    {
+        private Asn1Set certs;
+        private Asn1Set crls;
+
+        public OriginatorInfo(
+            Asn1Set certs,
+            Asn1Set crls)
+        {
+            this.certs = certs;
+            this.crls = crls;
+        }
+
+		public OriginatorInfo(
+            Asn1Sequence seq)
+        {
+            switch (seq.Count)
+            {
+            case 0:     // empty
+                break;
+            case 1:
+                Asn1TaggedObject o = (Asn1TaggedObject) seq[0];
+                switch (o.TagNo)
+                {
+                case 0 :
+                    certs = Asn1Set.GetInstance(o, false);
+                    break;
+                case 1 :
+                    crls = Asn1Set.GetInstance(o, false);
+                    break;
+                default:
+                    throw new ArgumentException("Bad tag in OriginatorInfo: " + o.TagNo);
+                }
+                break;
+            case 2:
+                certs = Asn1Set.GetInstance((Asn1TaggedObject) seq[0], false);
+                crls  = Asn1Set.GetInstance((Asn1TaggedObject) seq[1], false);
+                break;
+            default:
+                throw new ArgumentException("OriginatorInfo too big");
+            }
+        }
+
+		/**
+         * return an OriginatorInfo object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static OriginatorInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		/**
+         * return an OriginatorInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static OriginatorInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is OriginatorInfo)
+                return (OriginatorInfo)obj;
+
+			if (obj is Asn1Sequence)
+                return new OriginatorInfo((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid OriginatorInfo: " + obj.GetType().Name);
+        }
+
+		public Asn1Set Certificates
+		{
+			get { return certs; }
+		}
+
+		public Asn1Set Crls
+		{
+			get { return crls; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OriginatorInfo ::= Sequence {
+         *     certs [0] IMPLICIT CertificateSet OPTIONAL,
+         *     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (certs != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, certs));
+            }
+
+			if (crls != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, crls));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorPublicKey.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorPublicKey.cs
new file mode 100644
index 0000000..aabaf43
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OriginatorPublicKey.cs
@@ -0,0 +1,87 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OriginatorPublicKey
+        : Asn1Encodable
+    {
+        private AlgorithmIdentifier algorithm;
+        private DerBitString        publicKey;
+
+		public OriginatorPublicKey(
+            AlgorithmIdentifier algorithm,
+            byte[]              publicKey)
+        {
+            this.algorithm = algorithm;
+            this.publicKey = new DerBitString(publicKey);
+        }
+
+		public OriginatorPublicKey(
+            Asn1Sequence seq)
+        {
+            algorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            publicKey = (DerBitString) seq[1];
+        }
+
+		/**
+         * return an OriginatorPublicKey object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static OriginatorPublicKey GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		/**
+         * return an OriginatorPublicKey object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static OriginatorPublicKey GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is OriginatorPublicKey)
+                return (OriginatorPublicKey)obj;
+
+			if (obj is Asn1Sequence)
+                return new OriginatorPublicKey((Asn1Sequence) obj);
+
+			throw new ArgumentException("Invalid OriginatorPublicKey: " + obj.GetType().Name);
+        }
+
+		public AlgorithmIdentifier Algorithm
+		{
+			get { return algorithm; }
+		}
+
+		public DerBitString PublicKey
+		{
+			get { return publicKey; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OriginatorPublicKey ::= Sequence {
+         *     algorithm AlgorithmIdentifier,
+         *     publicKey BIT STRING
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(algorithm, publicKey);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OtherKeyAttribute.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OtherKeyAttribute.cs
new file mode 100644
index 0000000..2710591
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OtherKeyAttribute.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OtherKeyAttribute
+        : Asn1Encodable
+    {
+        private DerObjectIdentifier	keyAttrId;
+        private Asn1Encodable		keyAttr;
+
+		/**
+         * return an OtherKeyAttribute object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static OtherKeyAttribute GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is OtherKeyAttribute)
+                return (OtherKeyAttribute) obj;
+
+			if (obj is Asn1Sequence)
+                return new OtherKeyAttribute((Asn1Sequence) obj);
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public OtherKeyAttribute(
+            Asn1Sequence seq)
+        {
+            keyAttrId = (DerObjectIdentifier) seq[0];
+            keyAttr = seq[1];
+        }
+
+		public OtherKeyAttribute(
+            DerObjectIdentifier	keyAttrId,
+            Asn1Encodable		keyAttr)
+        {
+            this.keyAttrId = keyAttrId;
+            this.keyAttr = keyAttr;
+        }
+
+		public DerObjectIdentifier KeyAttrId
+		{
+			get { return keyAttrId; }
+		}
+
+		public Asn1Encodable KeyAttr
+		{
+			get { return keyAttr; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OtherKeyAttribute ::= Sequence {
+         *     keyAttrId OBJECT IDENTIFIER,
+         *     keyAttr ANY DEFINED BY keyAttrId OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(keyAttrId, keyAttr);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OtherRecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OtherRecipientInfo.cs
new file mode 100644
index 0000000..80dd68e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OtherRecipientInfo.cs
@@ -0,0 +1,83 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OtherRecipientInfo
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier oriType;
+        private readonly Asn1Encodable oriValue;
+
+        public OtherRecipientInfo(
+            DerObjectIdentifier	oriType,
+            Asn1Encodable		oriValue)
+        {
+            this.oriType = oriType;
+            this.oriValue = oriValue;
+        }
+
+        [Obsolete("Use GetInstance() instead")]
+        public OtherRecipientInfo(
+            Asn1Sequence seq)
+        {
+            oriType = DerObjectIdentifier.GetInstance(seq[0]);
+            oriValue = seq[1];
+        }
+
+        /**
+         * return a OtherRecipientInfo object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static OtherRecipientInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        /**
+         * return a OtherRecipientInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static OtherRecipientInfo GetInstance(
+            object obj)
+        {
+            if (obj == null)
+                return null;
+            OtherRecipientInfo existing = obj as OtherRecipientInfo;
+            if (existing != null)
+                return existing;
+            return new OtherRecipientInfo(Asn1Sequence.GetInstance(obj));
+        }
+
+        public virtual DerObjectIdentifier OriType
+        {
+            get { return oriType; }
+        }
+
+        public virtual Asn1Encodable OriValue
+        {
+            get { return oriValue; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OtherRecipientInfo ::= Sequence {
+         *    oriType OBJECT IDENTIFIER,
+         *    oriValue ANY DEFINED BY oriType }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(oriType, oriValue);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/OtherRevocationInfoFormat.cs b/BouncyCastle.AxCrypt/src/asn1/cms/OtherRevocationInfoFormat.cs
new file mode 100644
index 0000000..7835489
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/OtherRevocationInfoFormat.cs
@@ -0,0 +1,77 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class OtherRevocationInfoFormat
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier otherRevInfoFormat;
+        private readonly Asn1Encodable otherRevInfo;
+
+        public OtherRevocationInfoFormat(
+            DerObjectIdentifier otherRevInfoFormat,
+            Asn1Encodable otherRevInfo)
+        {
+            this.otherRevInfoFormat = otherRevInfoFormat;
+            this.otherRevInfo = otherRevInfo;
+        }
+
+        private OtherRevocationInfoFormat(Asn1Sequence seq)
+        {
+            otherRevInfoFormat = DerObjectIdentifier.GetInstance(seq[0]);
+            otherRevInfo = seq[1];
+        }
+
+        /**
+         * return a OtherRevocationInfoFormat object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicit true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception IllegalArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static OtherRevocationInfoFormat GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        /**
+         * return a OtherRevocationInfoFormat object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception IllegalArgumentException if the object cannot be converted.
+         */
+        public static OtherRevocationInfoFormat GetInstance(object obj)
+        {
+            if (obj is OtherRevocationInfoFormat)
+                return (OtherRevocationInfoFormat)obj;
+            if (obj != null)
+                return new OtherRevocationInfoFormat(Asn1Sequence.GetInstance(obj));
+            return null;
+        }
+
+        public virtual DerObjectIdentifier InfoFormat
+        {
+            get { return otherRevInfoFormat; }
+        }
+
+        public virtual Asn1Encodable Info
+        {
+            get { return otherRevInfo; }
+        }
+
+        /** 
+         * Produce an object suitable for an ASN1OutputStream.
+         * <pre>
+         * OtherRevocationInfoFormat ::= SEQUENCE {
+         *      otherRevInfoFormat OBJECT IDENTIFIER,
+         *      otherRevInfo ANY DEFINED BY otherRevInfoFormat }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(otherRevInfoFormat, otherRevInfo);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/PasswordRecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/PasswordRecipientInfo.cs
new file mode 100644
index 0000000..800b579
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/PasswordRecipientInfo.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class PasswordRecipientInfo
+        : Asn1Encodable
+    {
+        private readonly DerInteger				version;
+        private readonly AlgorithmIdentifier	keyDerivationAlgorithm;
+        private readonly AlgorithmIdentifier	keyEncryptionAlgorithm;
+        private readonly Asn1OctetString		encryptedKey;
+
+		public PasswordRecipientInfo(
+            AlgorithmIdentifier	keyEncryptionAlgorithm,
+            Asn1OctetString		encryptedKey)
+        {
+            this.version = new DerInteger(0);
+            this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+            this.encryptedKey = encryptedKey;
+        }
+
+		public PasswordRecipientInfo(
+			AlgorithmIdentifier	keyDerivationAlgorithm,
+			AlgorithmIdentifier	keyEncryptionAlgorithm,
+			Asn1OctetString		encryptedKey)
+		{
+			this.version = new DerInteger(0);
+			this.keyDerivationAlgorithm = keyDerivationAlgorithm;
+			this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
+			this.encryptedKey = encryptedKey;
+		}
+
+		public PasswordRecipientInfo(
+            Asn1Sequence seq)
+        {
+            version = (DerInteger) seq[0];
+
+			if (seq[1] is Asn1TaggedObject)
+            {
+                keyDerivationAlgorithm = AlgorithmIdentifier.GetInstance((Asn1TaggedObject) seq[1], false);
+                keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+                encryptedKey = (Asn1OctetString) seq[3];
+            }
+            else
+            {
+                keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+                encryptedKey = (Asn1OctetString) seq[2];
+            }
+        }
+
+		/**
+         * return a PasswordRecipientInfo object from a tagged object.
+         *
+         * @param obj the tagged object holding the object we want.
+         * @param explicitly true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static PasswordRecipientInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		/**
+         * return a PasswordRecipientInfo object from the given object.
+         *
+         * @param obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static PasswordRecipientInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is PasswordRecipientInfo)
+                return (PasswordRecipientInfo) obj;
+
+			if (obj is Asn1Sequence)
+                return new PasswordRecipientInfo((Asn1Sequence) obj);
+
+			throw new ArgumentException("Invalid PasswordRecipientInfo: " + obj.GetType().Name);
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public AlgorithmIdentifier KeyDerivationAlgorithm
+		{
+			get { return keyDerivationAlgorithm; }
+		}
+
+		public AlgorithmIdentifier KeyEncryptionAlgorithm
+		{
+			get { return keyEncryptionAlgorithm; }
+		}
+
+		public Asn1OctetString EncryptedKey
+		{
+			get { return encryptedKey; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * PasswordRecipientInfo ::= Sequence {
+         *   version CMSVersion,   -- Always set to 0
+         *   keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier
+         *                             OPTIONAL,
+         *  keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
+         *  encryptedKey EncryptedKey }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(version);
+
+			if (keyDerivationAlgorithm != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, keyDerivationAlgorithm));
+            }
+
+			v.Add(keyEncryptionAlgorithm, encryptedKey);
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/RecipientEncryptedKey.cs b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientEncryptedKey.cs
new file mode 100644
index 0000000..5ba25a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientEncryptedKey.cs
@@ -0,0 +1,88 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class RecipientEncryptedKey
+		: Asn1Encodable
+	{
+		private readonly KeyAgreeRecipientIdentifier identifier;
+		private readonly Asn1OctetString encryptedKey;
+
+		private RecipientEncryptedKey(
+			Asn1Sequence seq)
+		{
+			identifier = KeyAgreeRecipientIdentifier.GetInstance(seq[0]);
+			encryptedKey = (Asn1OctetString) seq[1];
+		}
+
+		/**
+		 * return an RecipientEncryptedKey object from a tagged object.
+		 *
+		 * @param obj the tagged object holding the object we want.
+		 * @param isExplicit true if the object is meant to be explicitly
+		 *              tagged false otherwise.
+		 * @exception ArgumentException if the object held by the
+		 *          tagged object cannot be converted.
+		 */
+		public static RecipientEncryptedKey GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		/**
+		 * return a RecipientEncryptedKey object from the given object.
+		 *
+		 * @param obj the object we want converted.
+		 * @exception ArgumentException if the object cannot be converted.
+		 */
+		public static RecipientEncryptedKey GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RecipientEncryptedKey)
+			{
+				return (RecipientEncryptedKey) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new RecipientEncryptedKey((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("Invalid RecipientEncryptedKey: " + obj.GetType().FullName, "obj");
+		}
+
+		public RecipientEncryptedKey(
+			KeyAgreeRecipientIdentifier	id,
+			Asn1OctetString				encryptedKey)
+		{
+			this.identifier = id;
+			this.encryptedKey = encryptedKey;
+		}
+
+		public KeyAgreeRecipientIdentifier Identifier
+		{
+			get { return identifier; }
+		}
+
+		public Asn1OctetString EncryptedKey
+		{
+			get { return encryptedKey; }
+		}
+
+		/** 
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * <pre>
+		 * RecipientEncryptedKey ::= SEQUENCE {
+		 *     rid KeyAgreeRecipientIdentifier,
+		 *     encryptedKey EncryptedKey
+		 * }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(identifier, encryptedKey);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/RecipientIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientIdentifier.cs
new file mode 100644
index 0000000..4982bc1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientIdentifier.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class RecipientIdentifier
+        : Asn1Encodable, IAsn1Choice
+    {
+        private Asn1Encodable id;
+
+		public RecipientIdentifier(
+            IssuerAndSerialNumber id)
+        {
+            this.id = id;
+        }
+
+		public RecipientIdentifier(
+            Asn1OctetString id)
+        {
+            this.id = new DerTaggedObject(false, 0, id);
+        }
+
+		public RecipientIdentifier(
+            Asn1Object id)
+        {
+            this.id = id;
+        }
+
+		/**
+         * return a RecipientIdentifier object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static RecipientIdentifier GetInstance(
+            object o)
+        {
+            if (o == null || o is RecipientIdentifier)
+                return (RecipientIdentifier)o;
+
+			if (o is IssuerAndSerialNumber)
+                return new RecipientIdentifier((IssuerAndSerialNumber) o);
+
+			if (o is Asn1OctetString)
+                return new RecipientIdentifier((Asn1OctetString) o);
+
+			if (o is Asn1Object)
+                return new RecipientIdentifier((Asn1Object) o);
+
+			throw new ArgumentException(
+              "Illegal object in RecipientIdentifier: " + o.GetType().Name);
+        }
+
+		public bool IsTagged
+		{
+			get { return (id is Asn1TaggedObject); }
+		}
+
+		public Asn1Encodable ID
+        {
+            get
+            {
+                if (id is Asn1TaggedObject)
+                {
+                    return Asn1OctetString.GetInstance((Asn1TaggedObject) id, false);
+                }
+
+				return IssuerAndSerialNumber.GetInstance(id);
+            }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * RecipientIdentifier ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return id.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/RecipientInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientInfo.cs
new file mode 100644
index 0000000..daaf5a5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientInfo.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class RecipientInfo
+        : Asn1Encodable, IAsn1Choice
+    {
+        internal Asn1Encodable info;
+
+		public RecipientInfo(
+            KeyTransRecipientInfo info)
+        {
+            this.info = info;
+        }
+
+		public RecipientInfo(
+            KeyAgreeRecipientInfo info)
+        {
+            this.info = new DerTaggedObject(false, 1, info);
+        }
+
+		public RecipientInfo(
+            KekRecipientInfo info)
+        {
+            this.info = new DerTaggedObject(false, 2, info);
+        }
+
+		public RecipientInfo(
+            PasswordRecipientInfo info)
+        {
+            this.info = new DerTaggedObject(false, 3, info);
+        }
+
+		public RecipientInfo(
+            OtherRecipientInfo info)
+        {
+            this.info = new DerTaggedObject(false, 4, info);
+        }
+
+		public RecipientInfo(
+            Asn1Object   info)
+        {
+            this.info = info;
+        }
+
+		public static RecipientInfo GetInstance(
+            object o)
+        {
+            if (o == null || o is RecipientInfo)
+                return (RecipientInfo) o;
+
+			if (o is Asn1Sequence)
+                return new RecipientInfo((Asn1Sequence) o);
+
+			if (o is Asn1TaggedObject)
+                return new RecipientInfo((Asn1TaggedObject) o);
+
+			throw new ArgumentException("unknown object in factory: " + o.GetType().Name);
+        }
+
+		public DerInteger Version
+        {
+			get
+			{
+				if (info is Asn1TaggedObject)
+				{
+					Asn1TaggedObject o = (Asn1TaggedObject) info;
+
+					switch (o.TagNo)
+					{
+						case 1:
+							return KeyAgreeRecipientInfo.GetInstance(o, false).Version;
+						case 2:
+							return GetKekInfo(o).Version;
+						case 3:
+							return PasswordRecipientInfo.GetInstance(o, false).Version;
+						case 4:
+							return new DerInteger(0);    // no syntax version for OtherRecipientInfo
+						default:
+							throw new InvalidOperationException("unknown tag");
+					}
+				}
+
+				return KeyTransRecipientInfo.GetInstance(info).Version;
+			}
+        }
+
+		public bool IsTagged
+		{
+			get { return info is Asn1TaggedObject; }
+		}
+
+		public Asn1Encodable Info
+        {
+			get
+			{
+				if (info is Asn1TaggedObject)
+				{
+					Asn1TaggedObject o = (Asn1TaggedObject) info;
+
+					switch (o.TagNo)
+					{
+						case 1:
+							return KeyAgreeRecipientInfo.GetInstance(o, false);
+						case 2:
+							return GetKekInfo(o);
+						case 3:
+							return PasswordRecipientInfo.GetInstance(o, false);
+						case 4:
+							return OtherRecipientInfo.GetInstance(o, false);
+						default:
+							throw new InvalidOperationException("unknown tag");
+					}
+				}
+
+				return KeyTransRecipientInfo.GetInstance(info);
+			}
+        }
+
+		private KekRecipientInfo GetKekInfo(
+			Asn1TaggedObject o)
+		{
+			// For compatibility with erroneous version, we don't always pass 'false' here
+			return KekRecipientInfo.GetInstance(o, o.IsExplicit());
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * RecipientInfo ::= CHOICE {
+         *     ktri KeyTransRecipientInfo,
+         *     kari [1] KeyAgreeRecipientInfo,
+         *     kekri [2] KekRecipientInfo,
+         *     pwri [3] PasswordRecipientInfo,
+         *     ori [4] OtherRecipientInfo }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return info.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/RecipientKeyIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientKeyIdentifier.cs
new file mode 100644
index 0000000..f3e4564
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/RecipientKeyIdentifier.cs
@@ -0,0 +1,137 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class RecipientKeyIdentifier
+        : Asn1Encodable
+    {
+        private Asn1OctetString      subjectKeyIdentifier;
+        private DerGeneralizedTime   date;
+        private OtherKeyAttribute    other;
+
+		public RecipientKeyIdentifier(
+            Asn1OctetString         subjectKeyIdentifier,
+            DerGeneralizedTime      date,
+            OtherKeyAttribute       other)
+        {
+            this.subjectKeyIdentifier = subjectKeyIdentifier;
+            this.date = date;
+            this.other = other;
+        }
+		
+		public RecipientKeyIdentifier(
+			byte[] subjectKeyIdentifier)
+			: this(subjectKeyIdentifier, null, null)
+		{
+		}
+
+		public RecipientKeyIdentifier(
+			byte[]				subjectKeyIdentifier,
+			DerGeneralizedTime	date,
+			OtherKeyAttribute	other)
+		{
+			this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier);
+			this.date = date;
+			this.other = other;
+		}
+
+		public RecipientKeyIdentifier(
+            Asn1Sequence seq)
+        {
+            subjectKeyIdentifier = Asn1OctetString.GetInstance(
+				seq[0]);
+
+			switch(seq.Count)
+            {
+				case 1:
+					break;
+				case 2:
+					if (seq[1] is DerGeneralizedTime)
+					{
+						date = (DerGeneralizedTime) seq[1];
+					}
+					else
+					{
+						other = OtherKeyAttribute.GetInstance(seq[2]);
+					}
+					break;
+				case 3:
+					date  = (DerGeneralizedTime) seq[1];
+					other = OtherKeyAttribute.GetInstance(seq[2]);
+					break;
+				default:
+					throw new ArgumentException("Invalid RecipientKeyIdentifier");
+            }
+        }
+
+		/**
+         * return a RecipientKeyIdentifier object from a tagged object.
+         *
+         * @param _ato the tagged object holding the object we want.
+         * @param _explicit true if the object is meant to be explicitly
+         *              tagged false otherwise.
+         * @exception ArgumentException if the object held by the
+         *          tagged object cannot be converted.
+         */
+        public static RecipientKeyIdentifier GetInstance(
+			Asn1TaggedObject	ato,
+			bool				explicitly)
+		{
+            return GetInstance(Asn1Sequence.GetInstance(ato, explicitly));
+        }
+
+		/**
+         * return a RecipientKeyIdentifier object from the given object.
+         *
+         * @param _obj the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static RecipientKeyIdentifier GetInstance(
+			object obj)
+		{
+            if (obj == null || obj is RecipientKeyIdentifier)
+                return (RecipientKeyIdentifier) obj;
+
+			if (obj is Asn1Sequence)
+				return new RecipientKeyIdentifier((Asn1Sequence) obj);
+
+			throw new ArgumentException("Invalid RecipientKeyIdentifier: " + obj.GetType().Name);
+        }
+
+		public Asn1OctetString SubjectKeyIdentifier
+		{
+			get { return subjectKeyIdentifier; }
+		}
+
+		public DerGeneralizedTime Date
+		{
+			get { return date; }
+		}
+
+		public OtherKeyAttribute OtherKeyAttribute
+		{
+			get { return other; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * RecipientKeyIdentifier ::= Sequence {
+         *     subjectKeyIdentifier SubjectKeyIdentifier,
+         *     date GeneralizedTime OPTIONAL,
+         *     other OtherKeyAttribute OPTIONAL
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(subjectKeyIdentifier);
+			v.AddOptional(date, other);
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/SCVPReqRes.cs b/BouncyCastle.AxCrypt/src/asn1/cms/SCVPReqRes.cs
new file mode 100644
index 0000000..486979a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/SCVPReqRes.cs
@@ -0,0 +1,77 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class ScvpReqRes
+        : Asn1Encodable
+    {
+        private readonly ContentInfo request;
+        private readonly ContentInfo response;
+
+        public static ScvpReqRes GetInstance(object  obj)
+        {
+            if (obj is ScvpReqRes)
+                return (ScvpReqRes)obj;
+            if (obj != null)
+                return new ScvpReqRes(Asn1Sequence.GetInstance(obj));
+            return null;
+        }
+
+        private ScvpReqRes(Asn1Sequence seq)
+        {
+            if (seq[0] is Asn1TaggedObject)
+            {
+                this.request = ContentInfo.GetInstance(Asn1TaggedObject.GetInstance(seq[0]), true);
+                this.response = ContentInfo.GetInstance(seq[1]);
+            }
+            else
+            {
+                this.request = null;
+                this.response = ContentInfo.GetInstance(seq[0]);
+            }
+        }
+
+        public ScvpReqRes(ContentInfo response)
+            : this(null, response)
+        {
+        }
+
+        public ScvpReqRes(ContentInfo request, ContentInfo response)
+        {
+            this.request = request;
+            this.response = response;
+        }
+
+        public virtual ContentInfo Request
+        {
+            get { return request; }
+        }
+
+        public virtual ContentInfo Response
+        {
+            get { return response; }
+        }
+
+        /**
+         * <pre>
+         *    ScvpReqRes ::= SEQUENCE {
+         *    request  [0] EXPLICIT ContentInfo OPTIONAL,
+         *    response     ContentInfo }
+         * </pre>
+         * @return  the ASN.1 primitive representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (request != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, request));
+            }
+
+            v.Add(response);
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/SignedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/SignedData.cs
new file mode 100644
index 0000000..6cea79a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/SignedData.cs
@@ -0,0 +1,287 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    /**
+     * a signed data object.
+     */
+    public class SignedData
+        : Asn1Encodable
+    {
+        private static readonly DerInteger Version1 = new DerInteger(1);
+        private static readonly DerInteger Version3 = new DerInteger(3);
+        private static readonly DerInteger Version4 = new DerInteger(4);
+        private static readonly DerInteger Version5 = new DerInteger(5);
+
+        private readonly DerInteger		version;
+        private readonly Asn1Set		digestAlgorithms;
+        private readonly ContentInfo	contentInfo;
+        private readonly Asn1Set		certificates;
+        private readonly Asn1Set		crls;
+        private readonly Asn1Set		signerInfos;
+        private readonly bool			certsBer;
+        private readonly bool		    crlsBer;
+
+        public static SignedData GetInstance(
+            object obj)
+        {
+            if (obj is SignedData)
+                return (SignedData) obj;
+
+            if (obj is Asn1Sequence)
+                return new SignedData((Asn1Sequence) obj);
+
+            throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+        }
+
+        public SignedData(
+            Asn1Set     digestAlgorithms,
+            ContentInfo contentInfo,
+            Asn1Set     certificates,
+            Asn1Set     crls,
+            Asn1Set     signerInfos)
+        {
+            this.version = CalculateVersion(contentInfo.ContentType, certificates, crls, signerInfos);
+            this.digestAlgorithms = digestAlgorithms;
+            this.contentInfo = contentInfo;
+            this.certificates = certificates;
+            this.crls = crls;
+            this.signerInfos = signerInfos;
+            this.crlsBer = crls is BerSet;
+            this.certsBer = certificates is BerSet;
+        }
+
+        // RFC3852, section 5.1:
+        // IF ((certificates is present) AND
+        //    (any certificates with a type of other are present)) OR
+        //    ((crls is present) AND
+        //    (any crls with a type of other are present))
+        // THEN version MUST be 5
+        // ELSE
+        //    IF (certificates is present) AND
+        //       (any version 2 attribute certificates are present)
+        //    THEN version MUST be 4
+        //    ELSE
+        //       IF ((certificates is present) AND
+        //          (any version 1 attribute certificates are present)) OR
+        //          (any SignerInfo structures are version 3) OR
+        //          (encapContentInfo eContentType is other than id-data)
+        //       THEN version MUST be 3
+        //       ELSE version MUST be 1
+        //
+        private DerInteger CalculateVersion(
+            DerObjectIdentifier	contentOid,
+            Asn1Set				certs,
+            Asn1Set				crls,
+            Asn1Set				signerInfs)
+        {
+            bool otherCert = false;
+            bool otherCrl = false;
+            bool attrCertV1Found = false;
+            bool attrCertV2Found = false;
+
+            if (certs != null)
+            {
+                foreach (object obj in certs)
+                {
+                    if (obj is Asn1TaggedObject)
+                    {
+                        Asn1TaggedObject tagged = (Asn1TaggedObject)obj;
+
+                        if (tagged.TagNo == 1)
+                        {
+                            attrCertV1Found = true;
+                        }
+                        else if (tagged.TagNo == 2)
+                        {
+                            attrCertV2Found = true;
+                        }
+                        else if (tagged.TagNo == 3)
+                        {
+                            otherCert = true;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (otherCert)
+            {
+                return Version5;
+            }
+
+            if (crls != null)
+            {
+                foreach (object obj in crls)
+                {
+                    if (obj is Asn1TaggedObject)
+                    {
+                        otherCrl = true;
+                        break;
+                    }
+                }
+            }
+
+            if (otherCrl)
+            {
+                return Version5;
+            }
+
+            if (attrCertV2Found)
+            {
+                return Version4;
+            }
+
+            if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
+            {
+                return Version3;
+            }
+
+            return Version1;
+        }
+
+        private bool CheckForVersion3(
+            Asn1Set signerInfs)
+        {
+            foreach (object obj in signerInfs)
+            {
+                SignerInfo s = SignerInfo.GetInstance(obj);
+
+                if (s.Version.Value.IntValue == 3)
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        private SignedData(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+            e.MoveNext();
+            version = (DerInteger)e.Current;
+
+            e.MoveNext();
+            digestAlgorithms = ((Asn1Set)e.Current);
+
+            e.MoveNext();
+            contentInfo = ContentInfo.GetInstance(e.Current);
+
+            while (e.MoveNext())
+            {
+                Asn1Object o = (Asn1Object)e.Current;
+
+                //
+                // an interesting feature of SignedData is that there appear
+                // to be varying implementations...
+                // for the moment we ignore anything which doesn't fit.
+                //
+                if (o is Asn1TaggedObject)
+                {
+                    Asn1TaggedObject tagged = (Asn1TaggedObject)o;
+
+                    switch (tagged.TagNo)
+                    {
+                        case 0:
+                            certsBer = tagged is BerTaggedObject;
+                            certificates = Asn1Set.GetInstance(tagged, false);
+                            break;
+                        case 1:
+                            crlsBer = tagged is BerTaggedObject;
+                            crls = Asn1Set.GetInstance(tagged, false);
+                            break;
+                        default:
+                            throw new ArgumentException("unknown tag value " + tagged.TagNo);
+                    }
+                }
+                else
+                {
+                    signerInfos = (Asn1Set) o;
+                }
+            }
+        }
+
+        public DerInteger Version
+        {
+            get { return version; }
+        }
+
+        public Asn1Set DigestAlgorithms
+        {
+            get { return digestAlgorithms; }
+        }
+
+        public ContentInfo EncapContentInfo
+        {
+            get { return contentInfo; }
+        }
+
+        public Asn1Set Certificates
+        {
+            get { return certificates; }
+        }
+
+        public Asn1Set CRLs
+        {
+            get { return crls; }
+        }
+
+        public Asn1Set SignerInfos
+        {
+            get { return signerInfos; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SignedData ::= Sequence {
+         *     version CMSVersion,
+         *     digestAlgorithms DigestAlgorithmIdentifiers,
+         *     encapContentInfo EncapsulatedContentInfo,
+         *     certificates [0] IMPLICIT CertificateSet OPTIONAL,
+         *     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+         *     signerInfos SignerInfos
+         *   }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                version, digestAlgorithms, contentInfo);
+
+            if (certificates != null)
+            {
+                if (certsBer)
+                {
+                    v.Add(new BerTaggedObject(false, 0, certificates));
+                }
+                else
+                {
+                    v.Add(new DerTaggedObject(false, 0, certificates));
+                }
+            }
+
+            if (crls != null)
+            {
+                if (crlsBer)
+                {
+                    v.Add(new BerTaggedObject(false, 1, crls));
+                }
+                else
+                {
+                    v.Add(new DerTaggedObject(false, 1, crls));
+                }
+            }
+
+            v.Add(signerInfos);
+
+            return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/SignedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/SignedDataParser.cs
new file mode 100644
index 0000000..3413092
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/SignedDataParser.cs
@@ -0,0 +1,112 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	/**
+	* <pre>
+	* SignedData ::= SEQUENCE {
+	*     version CMSVersion,
+	*     digestAlgorithms DigestAlgorithmIdentifiers,
+	*     encapContentInfo EncapsulatedContentInfo,
+	*     certificates [0] IMPLICIT CertificateSet OPTIONAL,
+	*     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+	*     signerInfos SignerInfos
+	*   }
+	* </pre>
+	*/
+	public class SignedDataParser
+	{
+		private Asn1SequenceParser	_seq;
+		private DerInteger			_version;
+		private object				_nextObject;
+		private bool				_certsCalled;
+		private bool				_crlsCalled;
+
+		public static SignedDataParser GetInstance(
+			object o)
+		{
+			if (o is Asn1Sequence)
+				return new SignedDataParser(((Asn1Sequence)o).Parser);
+
+			if (o is Asn1SequenceParser)
+				return new SignedDataParser((Asn1SequenceParser)o);
+
+			throw new IOException("unknown object encountered: " + o.GetType().Name);
+		}
+
+		public SignedDataParser(
+			Asn1SequenceParser seq)
+		{
+			this._seq = seq;
+			this._version = (DerInteger)seq.ReadObject();
+		}
+
+		public DerInteger Version
+		{
+			get { return _version; }
+		}
+
+		public Asn1SetParser GetDigestAlgorithms()
+		{
+			return (Asn1SetParser)_seq.ReadObject();
+		}
+
+		public ContentInfoParser GetEncapContentInfo()
+		{
+			return new ContentInfoParser((Asn1SequenceParser)_seq.ReadObject());
+		}
+
+		public Asn1SetParser GetCertificates()
+		{
+			_certsCalled = true;
+			_nextObject = _seq.ReadObject();
+
+			if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 0)
+			{
+				Asn1SetParser certs = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false);
+				_nextObject = null;
+
+				return certs;
+			}
+
+			return null;
+		}
+
+		public Asn1SetParser GetCrls()
+		{
+			if (!_certsCalled)
+				throw new IOException("GetCerts() has not been called.");
+
+			_crlsCalled = true;
+
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			if (_nextObject is Asn1TaggedObjectParser && ((Asn1TaggedObjectParser)_nextObject).TagNo == 1)
+			{
+				Asn1SetParser crls = (Asn1SetParser)((Asn1TaggedObjectParser)_nextObject).GetObjectParser(Asn1Tags.Set, false);
+				_nextObject = null;
+
+				return crls;
+			}
+
+			return null;
+		}
+
+		public Asn1SetParser GetSignerInfos()
+		{
+			if (!_certsCalled || !_crlsCalled)
+				throw new IOException("GetCerts() and/or GetCrls() has not been called.");
+
+			if (_nextObject == null)
+			{
+				_nextObject = _seq.ReadObject();
+			}
+
+			return (Asn1SetParser)_nextObject;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/SignerIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/cms/SignerIdentifier.cs
new file mode 100644
index 0000000..5742cee
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/SignerIdentifier.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class SignerIdentifier
+        : Asn1Encodable, IAsn1Choice
+    {
+        private Asn1Encodable id;
+
+		public SignerIdentifier(
+            IssuerAndSerialNumber id)
+        {
+            this.id = id;
+        }
+
+		public SignerIdentifier(
+            Asn1OctetString id)
+        {
+            this.id = new DerTaggedObject(false, 0, id);
+        }
+
+		public SignerIdentifier(
+            Asn1Object id)
+        {
+            this.id = id;
+        }
+
+		/**
+         * return a SignerIdentifier object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static SignerIdentifier GetInstance(
+            object o)
+        {
+            if (o == null || o is SignerIdentifier)
+                return (SignerIdentifier) o;
+
+			if (o is IssuerAndSerialNumber)
+                return new SignerIdentifier((IssuerAndSerialNumber) o);
+
+			if (o is Asn1OctetString)
+                return new SignerIdentifier((Asn1OctetString) o);
+
+			if (o is Asn1Object)
+                return new SignerIdentifier((Asn1Object) o);
+
+			throw new ArgumentException(
+				"Illegal object in SignerIdentifier: " + o.GetType().Name);
+        }
+
+		public bool IsTagged
+		{
+			get { return (id is Asn1TaggedObject); }
+		}
+
+		public Asn1Encodable ID
+        {
+            get
+            {
+                if (id is Asn1TaggedObject)
+                {
+                    return Asn1OctetString.GetInstance((Asn1TaggedObject)id, false);
+                }
+
+				return id;
+            }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SignerIdentifier ::= CHOICE {
+         *     issuerAndSerialNumber IssuerAndSerialNumber,
+         *     subjectKeyIdentifier [0] SubjectKeyIdentifier
+         * }
+         *
+         * SubjectKeyIdentifier ::= OCTET STRING
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return id.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/SignerInfo.cs b/BouncyCastle.AxCrypt/src/asn1/cms/SignerInfo.cs
new file mode 100644
index 0000000..a4e893d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/SignerInfo.cs
@@ -0,0 +1,185 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class SignerInfo
+        : Asn1Encodable
+    {
+        private DerInteger              version;
+        private SignerIdentifier        sid;
+        private AlgorithmIdentifier     digAlgorithm;
+        private Asn1Set                 authenticatedAttributes;
+        private AlgorithmIdentifier     digEncryptionAlgorithm;
+        private Asn1OctetString         encryptedDigest;
+        private Asn1Set                 unauthenticatedAttributes;
+
+        public static SignerInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is SignerInfo)
+                return (SignerInfo) obj;
+
+            if (obj is Asn1Sequence)
+                return new SignerInfo((Asn1Sequence) obj);
+
+            throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+        }
+
+        public SignerInfo(
+            SignerIdentifier        sid,
+            AlgorithmIdentifier     digAlgorithm,
+            Asn1Set                 authenticatedAttributes,
+            AlgorithmIdentifier     digEncryptionAlgorithm,
+            Asn1OctetString         encryptedDigest,
+            Asn1Set                 unauthenticatedAttributes)
+        {
+            this.version = new DerInteger(sid.IsTagged ? 3 : 1);
+            this.sid = sid;
+            this.digAlgorithm = digAlgorithm;
+            this.authenticatedAttributes = authenticatedAttributes;
+            this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+            this.encryptedDigest = encryptedDigest;
+            this.unauthenticatedAttributes = unauthenticatedAttributes;
+        }
+
+        public SignerInfo(
+            SignerIdentifier        sid,
+            AlgorithmIdentifier     digAlgorithm,
+            Attributes              authenticatedAttributes,
+            AlgorithmIdentifier     digEncryptionAlgorithm,
+            Asn1OctetString         encryptedDigest,
+            Attributes              unauthenticatedAttributes)
+        {
+            this.version = new DerInteger(sid.IsTagged ? 3 : 1);
+            this.sid = sid;
+            this.digAlgorithm = digAlgorithm;
+            this.authenticatedAttributes = Asn1Set.GetInstance(authenticatedAttributes);
+            this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+            this.encryptedDigest = encryptedDigest;
+            this.unauthenticatedAttributes = Asn1Set.GetInstance(unauthenticatedAttributes);
+        }
+
+        [Obsolete("Use 'GetInstance' instead")]
+        public SignerInfo(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+            e.MoveNext();
+            version = (DerInteger) e.Current;
+
+            e.MoveNext();
+            sid = SignerIdentifier.GetInstance(e.Current);
+
+            e.MoveNext();
+            digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+
+            e.MoveNext();
+            object obj = e.Current;
+
+            if (obj is Asn1TaggedObject)
+            {
+                authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false);
+
+                e.MoveNext();
+                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+            }
+            else
+            {
+                authenticatedAttributes = null;
+                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj);
+            }
+
+            e.MoveNext();
+            encryptedDigest = DerOctetString.GetInstance(e.Current);
+
+            if (e.MoveNext())
+            {
+                unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) e.Current, false);
+            }
+            else
+            {
+                unauthenticatedAttributes = null;
+            }
+        }
+
+        public DerInteger Version
+        {
+            get { return version; }
+        }
+
+        public SignerIdentifier SignerID
+        {
+            get { return sid; }
+        }
+
+        public Asn1Set AuthenticatedAttributes
+        {
+            get { return authenticatedAttributes; }
+        }
+
+        public AlgorithmIdentifier DigestAlgorithm
+        {
+            get { return digAlgorithm; }
+        }
+
+        public Asn1OctetString EncryptedDigest
+        {
+            get { return encryptedDigest; }
+        }
+
+        public AlgorithmIdentifier DigestEncryptionAlgorithm
+        {
+            get { return digEncryptionAlgorithm; }
+        }
+
+        public Asn1Set UnauthenticatedAttributes
+        {
+            get { return unauthenticatedAttributes; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  SignerInfo ::= Sequence {
+         *      version Version,
+         *      SignerIdentifier sid,
+         *      digestAlgorithm DigestAlgorithmIdentifier,
+         *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+         *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+         *      encryptedDigest EncryptedDigest,
+         *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+         *  }
+         *
+         *  EncryptedDigest ::= OCTET STRING
+         *
+         *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                version, sid, digAlgorithm);
+
+            if (authenticatedAttributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, authenticatedAttributes));
+            }
+
+            v.Add(digEncryptionAlgorithm, encryptedDigest);
+
+            if (unauthenticatedAttributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/Time.cs b/BouncyCastle.AxCrypt/src/asn1/cms/Time.cs
new file mode 100644
index 0000000..d113bfa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/Time.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    public class Time
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly Asn1Object time;
+
+		public static Time GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(obj.GetObject());
+        }
+
+		public Time(
+            Asn1Object time)
+        {
+            if (!(time is DerUtcTime)
+                && !(time is DerGeneralizedTime))
+            {
+                throw new ArgumentException("unknown object passed to Time");
+            }
+
+			this.time = time;
+        }
+
+		/**
+         * creates a time object from a given date - if the date is between 1950
+         * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+         * is used.
+         */
+        public Time(
+            DateTime date)
+        {
+            string d = date.ToString("yyyyMMddHHmmss") + "Z";
+
+			int year = int.Parse(d.Substring(0, 4));
+
+			if (year < 1950 || year > 2049)
+            {
+                time = new DerGeneralizedTime(d);
+            }
+            else
+            {
+                time = new DerUtcTime(d.Substring(2));
+            }
+        }
+
+		public static Time GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Time)
+                return (Time)obj;
+
+			if (obj is DerUtcTime)
+                return new Time((DerUtcTime)obj);
+
+			if (obj is DerGeneralizedTime)
+                return new Time((DerGeneralizedTime)obj);
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public string TimeString
+        {
+			get
+			{
+				if (time is DerUtcTime)
+				{
+					return ((DerUtcTime)time).AdjustedTimeString;
+				}
+				else
+				{
+					return ((DerGeneralizedTime)time).GetTime();
+				}
+			}
+        }
+
+		public DateTime Date
+        {
+			get
+			{
+				try
+				{
+					if (time is DerUtcTime)
+					{
+						return ((DerUtcTime)time).ToAdjustedDateTime();
+					}
+
+					return ((DerGeneralizedTime)time).ToDateTime();
+				}
+				catch (FormatException e)
+				{
+					// this should never happen
+					throw new InvalidOperationException("invalid date string: " + e.Message);
+				}
+			}
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Time ::= CHOICE {
+         *             utcTime        UTCTime,
+         *             generalTime    GeneralizedTime }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return time;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampAndCRL.cs b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampAndCRL.cs
new file mode 100644
index 0000000..4cb5f2a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampAndCRL.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class TimeStampAndCrl
+		: Asn1Encodable
+	{
+		private ContentInfo timeStamp;
+		private X509.CertificateList crl;
+
+		public TimeStampAndCrl(ContentInfo timeStamp)
+		{
+			this.timeStamp = timeStamp;
+		}
+
+		private TimeStampAndCrl(Asn1Sequence seq)
+		{
+			this.timeStamp = ContentInfo.GetInstance(seq[0]);
+			if (seq.Count == 2)
+			{
+				this.crl = X509.CertificateList.GetInstance(seq[1]);
+			}
+		}
+
+		public static TimeStampAndCrl GetInstance(object obj)
+		{
+			if (obj is TimeStampAndCrl)
+				return (TimeStampAndCrl)obj;
+
+			if (obj != null)
+				return new TimeStampAndCrl(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		public virtual ContentInfo TimeStampToken
+		{
+			get { return this.timeStamp; }
+		}
+
+		public virtual X509.CertificateList Crl
+		{
+			get { return this.crl; }
+		}
+
+		/**
+		 * <pre>
+		 * TimeStampAndCRL ::= SEQUENCE {
+		 *     timeStamp   TimeStampToken,          -- according to RFC 3161
+		 *     crl         CertificateList OPTIONAL -- according to RFC 5280
+		 *  }
+		 * </pre>
+		 * @return
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(timeStamp);
+			v.AddOptional(crl);
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampTokenEvidence.cs b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampTokenEvidence.cs
new file mode 100644
index 0000000..8625d05
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampTokenEvidence.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class TimeStampTokenEvidence
+		: Asn1Encodable
+	{
+		private TimeStampAndCrl[] timeStampAndCrls;
+
+		public TimeStampTokenEvidence(TimeStampAndCrl[] timeStampAndCrls)
+		{
+			this.timeStampAndCrls = timeStampAndCrls;
+		}
+
+		public TimeStampTokenEvidence(TimeStampAndCrl timeStampAndCrl)
+		{
+			this.timeStampAndCrls = new TimeStampAndCrl[]{ timeStampAndCrl };
+		}
+
+		private TimeStampTokenEvidence(Asn1Sequence seq)
+		{
+			this.timeStampAndCrls = new TimeStampAndCrl[seq.Count];
+
+			int count = 0;
+
+			foreach (Asn1Encodable ae in seq)
+			{
+				this.timeStampAndCrls[count++] = TimeStampAndCrl.GetInstance(ae.ToAsn1Object());
+			}
+		}
+
+		public static TimeStampTokenEvidence GetInstance(Asn1TaggedObject tagged, bool isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(tagged, isExplicit));
+		}
+
+		public static TimeStampTokenEvidence GetInstance(object obj)
+		{
+			if (obj is TimeStampTokenEvidence)
+				return (TimeStampTokenEvidence)obj;
+
+			if (obj != null)
+				return new TimeStampTokenEvidence(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		public virtual TimeStampAndCrl[] ToTimeStampAndCrlArray()
+		{
+			return (TimeStampAndCrl[])timeStampAndCrls.Clone();
+		}
+
+		/**
+		 * <pre>
+		 * TimeStampTokenEvidence ::=
+		 *    SEQUENCE SIZE(1..MAX) OF TimeStampAndCrl
+		 * </pre>
+		 * @return
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(timeStampAndCrls);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedData.cs b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedData.cs
new file mode 100644
index 0000000..15448a9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedData.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class TimeStampedData
+		: Asn1Encodable
+	{
+		private DerInteger version;
+		private DerIA5String dataUri;
+		private MetaData metaData;
+		private Asn1OctetString content;
+		private Evidence temporalEvidence;
+
+		public TimeStampedData(DerIA5String dataUri, MetaData metaData, Asn1OctetString content,
+			Evidence temporalEvidence)
+		{
+			this.version = new DerInteger(1);
+			this.dataUri = dataUri;
+			this.metaData = metaData;
+			this.content = content;
+			this.temporalEvidence = temporalEvidence;
+		}
+
+		private TimeStampedData(Asn1Sequence seq)
+		{
+			this.version = DerInteger.GetInstance(seq[0]);
+			
+			int index = 1;
+			if (seq[index] is DerIA5String)
+			{
+				this.dataUri = DerIA5String.GetInstance(seq[index++]);
+			}
+			if (seq[index] is MetaData || seq[index] is Asn1Sequence)
+			{
+				this.metaData = MetaData.GetInstance(seq[index++]);
+			}
+			if (seq[index] is Asn1OctetString)
+			{
+				this.content = Asn1OctetString.GetInstance(seq[index++]);
+			}
+			this.temporalEvidence = Evidence.GetInstance(seq[index]);
+		}
+
+		public static TimeStampedData GetInstance(object obj)
+		{
+			if (obj is TimeStampedData)
+				return (TimeStampedData)obj;
+
+			if (obj != null)
+				return new TimeStampedData(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		public virtual DerIA5String DataUri
+		{
+			get { return dataUri; }
+		}
+
+		public MetaData MetaData
+		{
+			get { return metaData; }
+		}
+
+		public Asn1OctetString Content
+		{
+			get { return content; }
+		}
+
+		public Evidence TemporalEvidence
+		{
+			get { return temporalEvidence; }
+		}
+
+		/**
+		 * <pre>
+		 * TimeStampedData ::= SEQUENCE {
+		 *   version              INTEGER { v1(1) },
+		 *   dataUri              IA5String OPTIONAL,
+		 *   metaData             MetaData OPTIONAL,
+		 *   content              OCTET STRING OPTIONAL,
+		 *   temporalEvidence     Evidence
+		 * }
+		 * </pre>
+		 * @return
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(version);
+			v.AddOptional(dataUri, metaData, content);
+			v.Add(temporalEvidence);
+			return new BerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedDataParser.cs b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedDataParser.cs
new file mode 100644
index 0000000..37ab4fd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/TimeStampedDataParser.cs
@@ -0,0 +1,74 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+	public class TimeStampedDataParser
+	{
+		private DerIA5String dataUri;
+		private MetaData metaData;
+		private Asn1OctetStringParser content;
+		private Evidence temporalEvidence;
+		private Asn1SequenceParser parser;
+		
+		private TimeStampedDataParser(Asn1SequenceParser parser)
+		{
+			this.parser = parser;
+
+			Asn1Object obj = parser.ReadObject().ToAsn1Object();
+
+			if (obj is DerIA5String)
+			{
+				this.dataUri = DerIA5String.GetInstance(obj);
+				obj = parser.ReadObject().ToAsn1Object();
+			}
+
+            if (//obj is MetaData ||
+                obj is Asn1SequenceParser)
+			{
+				this.metaData = MetaData.GetInstance(obj.ToAsn1Object());
+				obj = parser.ReadObject().ToAsn1Object();
+			}
+
+			if (obj is Asn1OctetStringParser)
+			{
+				this.content = (Asn1OctetStringParser)obj;
+			}
+		}
+
+		public static TimeStampedDataParser GetInstance(object obj)
+		{
+			if (obj is Asn1Sequence)
+				return new TimeStampedDataParser(((Asn1Sequence)obj).Parser);
+
+			if (obj is Asn1SequenceParser)
+				return new TimeStampedDataParser((Asn1SequenceParser)obj);
+
+			return null;
+		}
+		
+		public virtual DerIA5String DataUri
+		{
+			get { return dataUri; }
+		}
+
+		public virtual MetaData MetaData
+		{
+			get { return metaData; }
+		}
+
+		public virtual Asn1OctetStringParser Content
+		{
+			get { return content; }
+		}
+
+		public virtual Evidence GetTemporalEvidence()
+		{
+			if (temporalEvidence == null)
+			{
+				temporalEvidence = Evidence.GetInstance(parser.ReadObject().ToAsn1Object());
+			}
+
+			return temporalEvidence;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs b/BouncyCastle.AxCrypt/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
new file mode 100644
index 0000000..53c5c70
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cms/ecc/MQVuserKeyingMaterial.cs
@@ -0,0 +1,103 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Cms.Ecc
+{
+	public class MQVuserKeyingMaterial
+		: Asn1Encodable
+	{
+		private OriginatorPublicKey	ephemeralPublicKey;
+		private Asn1OctetString		addedukm;
+
+		public MQVuserKeyingMaterial(
+			OriginatorPublicKey	ephemeralPublicKey,
+			Asn1OctetString		addedukm)
+		{
+			// TODO Check ephemeralPublicKey not null
+
+			this.ephemeralPublicKey = ephemeralPublicKey;
+			this.addedukm = addedukm;
+		}
+
+		private MQVuserKeyingMaterial(
+			Asn1Sequence seq)
+		{
+			// TODO Check seq has either 1 or 2 elements
+
+			this.ephemeralPublicKey = OriginatorPublicKey.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.addedukm = Asn1OctetString.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+			}
+		}
+
+		/**
+		 * return an AuthEnvelopedData object from a tagged object.
+		 *
+		 * @param obj      the tagged object holding the object we want.
+		 * @param isExplicit true if the object is meant to be explicitly
+		 *                 tagged false otherwise.
+		 * @throws ArgumentException if the object held by the
+		 *                                  tagged object cannot be converted.
+		 */
+		public static MQVuserKeyingMaterial GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		/**
+		 * return an AuthEnvelopedData object from the given object.
+		 *
+		 * @param obj the object we want converted.
+		 * @throws ArgumentException if the object cannot be converted.
+		 */
+		public static MQVuserKeyingMaterial GetInstance(
+			object	obj)
+		{
+			if (obj == null || obj is MQVuserKeyingMaterial)
+			{
+				return (MQVuserKeyingMaterial)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new MQVuserKeyingMaterial((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Invalid MQVuserKeyingMaterial: " + obj.GetType().Name);
+		}
+		
+		public OriginatorPublicKey EphemeralPublicKey
+		{
+			get { return ephemeralPublicKey; }
+		}
+
+		public Asn1OctetString AddedUkm
+		{
+			get { return addedukm; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <pre>
+		* MQVuserKeyingMaterial ::= SEQUENCE {
+		*   ephemeralPublicKey OriginatorPublicKey,
+		*   addedukm [0] EXPLICIT UserKeyingMaterial OPTIONAL  }
+		* </pre>
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(ephemeralPublicKey);
+
+			if (addedukm != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, addedukm));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/AttributeTypeAndValue.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/AttributeTypeAndValue.cs
new file mode 100644
index 0000000..8236689
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/AttributeTypeAndValue.cs
@@ -0,0 +1,66 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class AttributeTypeAndValue
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier type;
+        private readonly Asn1Encodable value;
+
+        private AttributeTypeAndValue(Asn1Sequence seq)
+        {
+            type = (DerObjectIdentifier)seq[0];
+            value = (Asn1Encodable)seq[1];
+        }
+
+        public static AttributeTypeAndValue GetInstance(object obj)
+        {
+            if (obj is AttributeTypeAndValue)
+                return (AttributeTypeAndValue)obj;
+
+            if (obj is Asn1Sequence)
+                return new AttributeTypeAndValue((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public AttributeTypeAndValue(
+            String oid,
+            Asn1Encodable value)
+            : this(new DerObjectIdentifier(oid), value)
+        {
+        }
+
+        public AttributeTypeAndValue(
+            DerObjectIdentifier type,
+            Asn1Encodable value)
+        {
+            this.type = type;
+            this.value = value;
+        }
+
+        public virtual DerObjectIdentifier Type
+        {
+            get { return type; }
+        }
+
+        public virtual Asn1Encodable Value
+        {
+            get { return value; }
+        }
+
+        /**
+         * <pre>
+         * AttributeTypeAndValue ::= SEQUENCE {
+         *           type         OBJECT IDENTIFIER,
+         *           value        ANY DEFINED BY type }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(type, value);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertId.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertId.cs
new file mode 100644
index 0000000..10c2cc8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertId.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertId
+        : Asn1Encodable
+    {
+        private readonly GeneralName issuer;
+        private readonly DerInteger serialNumber;
+
+        private CertId(Asn1Sequence seq)
+        {
+            issuer = GeneralName.GetInstance(seq[0]);
+            serialNumber = DerInteger.GetInstance(seq[1]);
+        }
+
+        public static CertId GetInstance(object obj)
+        {
+            if (obj is CertId)
+                return (CertId)obj;
+
+            if (obj is Asn1Sequence)
+                return new CertId((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public static CertId GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        public virtual GeneralName Issuer
+        {
+            get { return issuer; }
+        }
+
+        public virtual DerInteger SerialNumber
+        {
+            get { return serialNumber; }
+        }
+
+        /**
+         * <pre>
+         * CertId ::= SEQUENCE {
+         *                 issuer           GeneralName,
+         *                 serialNumber     INTEGER }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(issuer, serialNumber);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMessages.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMessages.cs
new file mode 100644
index 0000000..9247281
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMessages.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertReqMessages
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence content;
+
+        private CertReqMessages(Asn1Sequence seq)
+        {
+            content = seq;
+        }
+
+        public static CertReqMessages GetInstance(object obj)
+        {
+            if (obj is CertReqMessages)
+                return (CertReqMessages)obj;
+
+            if (obj is Asn1Sequence)
+                return new CertReqMessages((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+		public CertReqMessages(params CertReqMsg[] msgs)
+        {
+            content = new DerSequence(msgs);
+        }
+
+        public virtual CertReqMsg[] ToCertReqMsgArray()
+        {
+            CertReqMsg[] result = new CertReqMsg[content.Count];
+            for (int i = 0; i != result.Length; ++i)
+            {
+                result[i] = CertReqMsg.GetInstance(content[i]);
+            }
+            return result;
+        }
+
+        /**
+         * <pre>
+         * CertReqMessages ::= SEQUENCE SIZE (1..MAX) OF CertReqMsg
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return content;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMsg.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMsg.cs
new file mode 100644
index 0000000..2ca319a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertReqMsg.cs
@@ -0,0 +1,106 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertReqMsg
+        : Asn1Encodable
+    {
+        private readonly CertRequest certReq;
+        private readonly ProofOfPossession popo;
+        private readonly Asn1Sequence regInfo;
+
+        private CertReqMsg(Asn1Sequence seq)
+        {
+            certReq = CertRequest.GetInstance(seq[0]);
+
+            for (int pos = 1; pos < seq.Count; ++pos)
+            {
+                object o = seq[pos];
+
+                if (o is Asn1TaggedObject || o is ProofOfPossession)
+                {
+                    popo = ProofOfPossession.GetInstance(o);
+                }
+                else
+                {
+                    regInfo = Asn1Sequence.GetInstance(o);
+                }
+            }
+        }
+
+        public static CertReqMsg GetInstance(object obj)
+        {
+            if (obj is CertReqMsg)
+                return (CertReqMsg)obj;
+
+            if (obj != null)
+                return new CertReqMsg(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        /**
+         * Creates a new CertReqMsg.
+         * @param certReq CertRequest
+         * @param popo may be null
+         * @param regInfo may be null
+         */
+        public CertReqMsg(
+            CertRequest				certReq,
+            ProofOfPossession		popo,
+            AttributeTypeAndValue[]	regInfo)
+        {
+            if (certReq == null)
+                throw new ArgumentNullException("certReq");
+
+            this.certReq = certReq;
+            this.popo = popo;
+
+            if (regInfo != null)
+            {
+                this.regInfo = new DerSequence(regInfo);
+            }
+        }
+
+        public virtual CertRequest CertReq
+        {
+            get { return certReq; }
+        }
+
+        public virtual ProofOfPossession Popo
+        {
+            get { return popo; }
+        }
+
+        public virtual AttributeTypeAndValue[] GetRegInfo()
+        {
+            if (regInfo == null)
+                return null;
+
+            AttributeTypeAndValue[] results = new AttributeTypeAndValue[regInfo.Count];
+            for (int i = 0; i != results.Length; ++i)
+            {
+                results[i] = AttributeTypeAndValue.GetInstance(regInfo[i]);
+            }
+            return results;
+        }
+
+        /**
+         * <pre>
+         * CertReqMsg ::= SEQUENCE {
+         *                    certReq   CertRequest,
+         *                    pop       ProofOfPossession  OPTIONAL,
+         *                    -- content depends upon key type
+         *                    regInfo   SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue OPTIONAL }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(certReq);
+            v.AddOptional(popo);
+            v.AddOptional(regInfo);
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertRequest.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertRequest.cs
new file mode 100644
index 0000000..625a9b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertRequest.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertRequest
+        : Asn1Encodable
+    {
+        private readonly DerInteger certReqId;
+        private readonly CertTemplate certTemplate;
+        private readonly Controls controls;
+
+        private CertRequest(Asn1Sequence seq)
+        {
+            certReqId = DerInteger.GetInstance(seq[0]);
+            certTemplate = CertTemplate.GetInstance(seq[1]);
+            if (seq.Count > 2)
+            {
+                controls = Controls.GetInstance(seq[2]);
+            }
+        }
+
+        public static CertRequest GetInstance(object obj)
+        {
+            if (obj is CertRequest)
+                return (CertRequest)obj;
+
+            if (obj != null)
+                return new CertRequest(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        public CertRequest(
+            int certReqId,
+            CertTemplate certTemplate,
+            Controls controls)
+            : this(new DerInteger(certReqId), certTemplate, controls)
+        {
+        }
+
+        public CertRequest(
+            DerInteger certReqId,
+            CertTemplate certTemplate,
+            Controls controls)
+        {
+            this.certReqId = certReqId;
+            this.certTemplate = certTemplate;
+            this.controls = controls;
+        }
+
+        public virtual DerInteger CertReqID
+        {
+            get { return certReqId; }
+        }
+
+        public virtual CertTemplate CertTemplate
+        {
+            get { return certTemplate; }
+        }
+
+        public virtual Controls Controls
+        {
+            get { return controls; }
+        }
+
+        /**
+         * <pre>
+         * CertRequest ::= SEQUENCE {
+         *                      certReqId     INTEGER,          -- ID for matching request and reply
+         *                      certTemplate  CertTemplate,  -- Selected fields of cert to be issued
+         *                      controls      Controls OPTIONAL }   -- Attributes affecting issuance
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(certReqId, certTemplate);
+            v.AddOptional(controls);
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplate.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplate.cs
new file mode 100644
index 0000000..3de9f1d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplate.cs
@@ -0,0 +1,149 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertTemplate
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence seq;
+
+        private readonly DerInteger version;
+        private readonly DerInteger serialNumber;
+        private readonly AlgorithmIdentifier signingAlg;
+        private readonly X509Name issuer;
+        private readonly OptionalValidity validity;
+        private readonly X509Name subject;
+        private readonly SubjectPublicKeyInfo publicKey;
+        private readonly DerBitString issuerUID;
+        private readonly DerBitString subjectUID;
+        private readonly X509Extensions extensions;
+
+        private CertTemplate(Asn1Sequence seq)
+        {
+            this.seq = seq;
+
+            foreach (Asn1TaggedObject tObj in seq)
+            {
+                switch (tObj.TagNo)
+                {
+                case 0:
+                    version = DerInteger.GetInstance(tObj, false);
+                    break;
+                case 1:
+                    serialNumber = DerInteger.GetInstance(tObj, false);
+                    break;
+                case 2:
+                    signingAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+                    break;
+                case 3:
+                    issuer = X509Name.GetInstance(tObj, true); // CHOICE
+                    break;
+                case 4:
+                    validity = OptionalValidity.GetInstance(Asn1Sequence.GetInstance(tObj, false));
+                    break;
+                case 5:
+                    subject = X509Name.GetInstance(tObj, true); // CHOICE
+                    break;
+                case 6:
+                    publicKey = SubjectPublicKeyInfo.GetInstance(tObj, false);
+                    break;
+                case 7:
+                    issuerUID = DerBitString.GetInstance(tObj, false);
+                    break;
+                case 8:
+                    subjectUID = DerBitString.GetInstance(tObj, false);
+                    break;
+                case 9:
+                    extensions = X509Extensions.GetInstance(tObj, false);
+                    break;
+                default:
+                    throw new ArgumentException("unknown tag: " + tObj.TagNo, "seq");
+                }
+            }
+        }
+
+        public static CertTemplate GetInstance(object obj)
+        {
+            if (obj is CertTemplate)
+                return (CertTemplate)obj;
+
+            if (obj != null)
+                return new CertTemplate(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        public virtual int Version
+        {
+            get { return version.Value.IntValue; }
+        }
+
+        public virtual DerInteger SerialNumber
+        {
+            get { return serialNumber; }
+        }
+
+        public virtual AlgorithmIdentifier SigningAlg
+        {
+            get { return signingAlg; }
+        }
+
+        public virtual X509Name Issuer
+        {
+            get { return issuer; }
+        }
+
+        public virtual OptionalValidity Validity
+        {
+            get { return validity; }
+        }
+
+        public virtual X509Name Subject
+        {
+            get { return subject; }
+        }
+
+        public virtual SubjectPublicKeyInfo PublicKey
+        {
+            get { return publicKey; }
+        }
+
+        public virtual DerBitString IssuerUID
+        {
+            get { return issuerUID; }
+        }
+
+        public virtual DerBitString SubjectUID
+        {
+            get { return subjectUID; }
+        }
+
+        public virtual X509Extensions Extensions
+        {
+            get { return extensions; }
+        }
+
+        /**
+         * <pre>
+         *  CertTemplate ::= SEQUENCE {
+         *      version      [0] Version               OPTIONAL,
+         *      serialNumber [1] INTEGER               OPTIONAL,
+         *      signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+         *      issuer       [3] Name                  OPTIONAL,
+         *      validity     [4] OptionalValidity      OPTIONAL,
+         *      subject      [5] Name                  OPTIONAL,
+         *      publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+         *      issuerUID    [7] UniqueIdentifier      OPTIONAL,
+         *      subjectUID   [8] UniqueIdentifier      OPTIONAL,
+         *      extensions   [9] Extensions            OPTIONAL }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplateBuilder.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplateBuilder.cs
new file mode 100644
index 0000000..51c73c4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CertTemplateBuilder.cs
@@ -0,0 +1,125 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class CertTemplateBuilder
+    {
+        private DerInteger version;
+        private DerInteger serialNumber;
+        private AlgorithmIdentifier signingAlg;
+        private X509Name issuer;
+        private OptionalValidity validity;
+        private X509Name subject;
+        private SubjectPublicKeyInfo publicKey;
+        private DerBitString issuerUID;
+        private DerBitString subjectUID;
+        private X509Extensions extensions;
+
+        /** Sets the X.509 version. Note: for X509v3, use 2 here. */
+        public virtual CertTemplateBuilder SetVersion(int ver)
+        {
+            version = new DerInteger(ver);
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetSerialNumber(DerInteger ser)
+        {
+            serialNumber = ser;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetSigningAlg(AlgorithmIdentifier aid)
+        {
+            signingAlg = aid;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetIssuer(X509Name name)
+        {
+            issuer = name;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetValidity(OptionalValidity v)
+        {
+            validity = v;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetSubject(X509Name name)
+        {
+            subject = name;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetPublicKey(SubjectPublicKeyInfo spki)
+        {
+            publicKey = spki;
+            return this;
+        }
+
+        /** Sets the issuer unique ID (deprecated in X.509v3) */
+        public virtual CertTemplateBuilder SetIssuerUID(DerBitString uid)
+        {
+            issuerUID = uid;
+            return this;
+        }
+
+        /** Sets the subject unique ID (deprecated in X.509v3) */
+        public virtual CertTemplateBuilder SetSubjectUID(DerBitString uid)
+        {
+            subjectUID = uid;
+            return this;
+        }
+
+        public virtual CertTemplateBuilder SetExtensions(X509Extensions extens)
+        {
+            extensions = extens;
+            return this;
+        }
+
+        /**
+         * <pre>
+         *  CertTemplate ::= SEQUENCE {
+         *      version      [0] Version               OPTIONAL,
+         *      serialNumber [1] INTEGER               OPTIONAL,
+         *      signingAlg   [2] AlgorithmIdentifier   OPTIONAL,
+         *      issuer       [3] Name                  OPTIONAL,
+         *      validity     [4] OptionalValidity      OPTIONAL,
+         *      subject      [5] Name                  OPTIONAL,
+         *      publicKey    [6] SubjectPublicKeyInfo  OPTIONAL,
+         *      issuerUID    [7] UniqueIdentifier      OPTIONAL,
+         *      subjectUID   [8] UniqueIdentifier      OPTIONAL,
+         *      extensions   [9] Extensions            OPTIONAL }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public virtual CertTemplate Build()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            AddOptional(v, 0, false, version);
+            AddOptional(v, 1, false, serialNumber);
+            AddOptional(v, 2, false, signingAlg);
+            AddOptional(v, 3, true, issuer); // CHOICE
+            AddOptional(v, 4, false, validity);
+            AddOptional(v, 5, true, subject); // CHOICE
+            AddOptional(v, 6, false, publicKey);
+            AddOptional(v, 7, false, issuerUID);
+            AddOptional(v, 8, false, subjectUID);
+            AddOptional(v, 9, false, extensions);
+
+            return CertTemplate.GetInstance(new DerSequence(v));
+        }
+
+        private void AddOptional(Asn1EncodableVector v, int tagNo, bool isExplicit, Asn1Encodable obj)
+        {
+            if (obj != null)
+            {
+                v.Add(new DerTaggedObject(isExplicit, tagNo, obj));
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/Controls.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/Controls.cs
new file mode 100644
index 0000000..cc52ea4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/Controls.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class Controls
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence content;
+
+        private Controls(Asn1Sequence seq)
+        {
+            content = seq;
+        }
+
+        public static Controls GetInstance(object obj)
+        {
+            if (obj is Controls)
+                return (Controls)obj;
+
+            if (obj is Asn1Sequence)
+                return new Controls((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+		public Controls(params AttributeTypeAndValue[] atvs)
+        {
+            content = new DerSequence(atvs);
+        }
+
+        public virtual AttributeTypeAndValue[] ToAttributeTypeAndValueArray()
+        {
+            AttributeTypeAndValue[] result = new AttributeTypeAndValue[content.Count];
+            for (int i = 0; i != result.Length; ++i)
+            {
+                result[i] = AttributeTypeAndValue.GetInstance(content[i]);
+            }
+            return result;
+        }
+
+        /**
+         * <pre>
+         * Controls  ::= SEQUENCE SIZE(1..MAX) OF AttributeTypeAndValue
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return content;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/CrmfObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/CrmfObjectIdentifiers.cs
new file mode 100644
index 0000000..eaa1f7b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/CrmfObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public abstract class CrmfObjectIdentifiers
+    {
+        public static readonly DerObjectIdentifier id_pkix = new DerObjectIdentifier("1.3.6.1.5.5.7");
+
+        // arc for Internet X.509 PKI protocols and their components
+
+        public static readonly DerObjectIdentifier id_pkip  = id_pkix.Branch("5");
+
+        public static readonly DerObjectIdentifier id_regCtrl = id_pkip.Branch("1");
+        public static readonly DerObjectIdentifier id_regCtrl_regToken = id_regCtrl.Branch("1");
+        public static readonly DerObjectIdentifier id_regCtrl_authenticator = id_regCtrl.Branch("2");
+        public static readonly DerObjectIdentifier id_regCtrl_pkiPublicationInfo = id_regCtrl.Branch("3");
+        public static readonly DerObjectIdentifier id_regCtrl_pkiArchiveOptions = id_regCtrl.Branch("4");
+
+        public static readonly DerObjectIdentifier id_ct_encKeyWithID = new DerObjectIdentifier(PkcsObjectIdentifiers.IdCT + ".21");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/EncKeyWithID.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/EncKeyWithID.cs
new file mode 100644
index 0000000..6de56fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/EncKeyWithID.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class EncKeyWithID
+        : Asn1Encodable
+    {
+        private readonly PrivateKeyInfo privKeyInfo;
+        private readonly Asn1Encodable identifier;
+
+        public static EncKeyWithID GetInstance(object obj)
+        {
+            if (obj is EncKeyWithID)
+                return (EncKeyWithID)obj;
+
+            if (obj != null)
+                return new EncKeyWithID(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        private EncKeyWithID(Asn1Sequence seq)
+        {
+            this.privKeyInfo = PrivateKeyInfo.GetInstance(seq[0]);
+
+            if (seq.Count > 1)
+            {
+                if (!(seq[1] is DerUtf8String))
+                {
+                    this.identifier = GeneralName.GetInstance(seq[1]);
+                }
+                else
+                {
+                    this.identifier = (Asn1Encodable)seq[1];
+                }
+            }
+            else
+            {
+                this.identifier = null;
+            }
+        }
+
+        public EncKeyWithID(PrivateKeyInfo privKeyInfo)
+        {
+            this.privKeyInfo = privKeyInfo;
+            this.identifier = null;
+        }
+
+        public EncKeyWithID(PrivateKeyInfo privKeyInfo, DerUtf8String str)
+        {
+            this.privKeyInfo = privKeyInfo;
+            this.identifier = str;
+        }
+
+        public EncKeyWithID(PrivateKeyInfo privKeyInfo, GeneralName generalName)
+        {
+            this.privKeyInfo = privKeyInfo;
+            this.identifier = generalName;
+        }
+
+        public virtual PrivateKeyInfo PrivateKey
+        {
+            get { return privKeyInfo; }
+        }
+
+        public virtual bool HasIdentifier
+        {
+            get { return identifier != null; }
+        }
+
+        public virtual bool IsIdentifierUtf8String
+        {
+            get { return identifier is DerUtf8String; }
+        }
+
+        public virtual Asn1Encodable Identifier
+        {
+            get { return identifier; }
+        }
+
+        /**
+         * <pre>
+         * EncKeyWithID ::= SEQUENCE {
+         *      privateKey           PrivateKeyInfo,
+         *      identifier CHOICE {
+         *         string               UTF8String,
+         *         generalName          GeneralName
+         *     } OPTIONAL
+         * }
+         * </pre>
+         * @return
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(privKeyInfo);
+            v.AddOptional(identifier);
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedKey.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedKey.cs
new file mode 100644
index 0000000..850fbd2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedKey.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class EncryptedKey
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly EnvelopedData envelopedData;
+        private readonly EncryptedValue encryptedValue;
+
+        public static EncryptedKey GetInstance(object o)
+        {
+            if (o is EncryptedKey)
+            {
+                return (EncryptedKey)o;
+            }
+            else if (o is Asn1TaggedObject)
+            {
+                return new EncryptedKey(EnvelopedData.GetInstance((Asn1TaggedObject)o, false));
+            }
+            else if (o is EncryptedValue)
+            {
+                return new EncryptedKey((EncryptedValue)o);
+            }
+            else
+            {
+                return new EncryptedKey(EncryptedValue.GetInstance(o));
+            }
+        }
+
+        public EncryptedKey(EnvelopedData envelopedData)
+        {
+            this.envelopedData = envelopedData;
+        }
+
+        public EncryptedKey(EncryptedValue encryptedValue)
+        {
+            this.encryptedValue = encryptedValue;
+        }
+
+        public virtual bool IsEncryptedValue
+        {
+            get { return encryptedValue != null; }
+        }
+
+        public virtual Asn1Encodable Value
+        {
+            get
+            {
+                if (encryptedValue != null)
+                    return encryptedValue;
+
+                return envelopedData;
+            }
+        }
+
+        /**
+         * <pre>
+         *    EncryptedKey ::= CHOICE {
+         *        encryptedValue        EncryptedValue, -- deprecated
+         *        envelopedData     [0] EnvelopedData }
+         *        -- The encrypted private key MUST be placed in the envelopedData
+         *        -- encryptedContentInfo encryptedContent OCTET STRING.
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            if (encryptedValue != null)
+            {
+                return encryptedValue.ToAsn1Object();
+            }
+
+            return new DerTaggedObject(false, 0, envelopedData);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedValue.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedValue.cs
new file mode 100644
index 0000000..83122e2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/EncryptedValue.cs
@@ -0,0 +1,154 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class EncryptedValue
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier intendedAlg;
+        private readonly AlgorithmIdentifier symmAlg;
+        private readonly DerBitString encSymmKey;
+        private readonly AlgorithmIdentifier keyAlg;
+        private readonly Asn1OctetString valueHint;
+        private readonly DerBitString encValue;
+
+        private EncryptedValue(Asn1Sequence seq)
+        {
+            int index = 0;
+            while (seq[index] is Asn1TaggedObject)
+            {
+                Asn1TaggedObject tObj = (Asn1TaggedObject)seq[index];
+
+                switch (tObj.TagNo)
+                {
+                    case 0:
+                        intendedAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+                        break;
+                    case 1:
+                        symmAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+                        break;
+                    case 2:
+                        encSymmKey = DerBitString.GetInstance(tObj, false);
+                        break;
+                    case 3:
+                        keyAlg = AlgorithmIdentifier.GetInstance(tObj, false);
+                        break;
+                    case 4:
+                        valueHint = Asn1OctetString.GetInstance(tObj, false);
+                        break;
+                }
+                ++index;
+            }
+
+            encValue = DerBitString.GetInstance(seq[index]);
+        }
+
+        public static EncryptedValue GetInstance(object obj)
+        {
+            if (obj is EncryptedValue)
+                return (EncryptedValue)obj;
+
+            if (obj != null)
+                return new EncryptedValue(Asn1Sequence.GetInstance(obj));
+
+            return null;
+        }
+
+        public EncryptedValue(
+            AlgorithmIdentifier intendedAlg,
+            AlgorithmIdentifier symmAlg,
+            DerBitString encSymmKey,
+            AlgorithmIdentifier keyAlg,
+            Asn1OctetString valueHint,
+            DerBitString encValue)
+        {
+            if (encValue == null)
+            {
+                throw new ArgumentNullException("encValue");
+            }
+
+            this.intendedAlg = intendedAlg;
+            this.symmAlg = symmAlg;
+            this.encSymmKey = encSymmKey;
+            this.keyAlg = keyAlg;
+            this.valueHint = valueHint;
+            this.encValue = encValue;
+        }
+
+        public virtual AlgorithmIdentifier IntendedAlg
+        {
+            get { return intendedAlg; }
+        }
+
+        public virtual AlgorithmIdentifier SymmAlg
+        {
+            get { return symmAlg; }
+        }
+
+        public virtual DerBitString EncSymmKey
+        {
+            get { return encSymmKey; }
+        }
+
+        public virtual AlgorithmIdentifier KeyAlg
+        {
+            get { return keyAlg; }
+        }
+
+        public virtual Asn1OctetString ValueHint
+        {
+            get { return valueHint; }
+        }
+
+        public virtual DerBitString EncValue
+        {
+            get { return encValue; }
+        }
+
+        /**
+         * <pre>
+         * EncryptedValue ::= SEQUENCE {
+         *                     intendedAlg   [0] AlgorithmIdentifier  OPTIONAL,
+         *                     -- the intended algorithm for which the value will be used
+         *                     symmAlg       [1] AlgorithmIdentifier  OPTIONAL,
+         *                     -- the symmetric algorithm used to encrypt the value
+         *                     encSymmKey    [2] BIT STRING           OPTIONAL,
+         *                     -- the (encrypted) symmetric key used to encrypt the value
+         *                     keyAlg        [3] AlgorithmIdentifier  OPTIONAL,
+         *                     -- algorithm used to encrypt the symmetric key
+         *                     valueHint     [4] OCTET STRING         OPTIONAL,
+         *                     -- a brief description or identifier of the encValue content
+         *                     -- (may be meaningful only to the sending entity, and used only
+         *                     -- if EncryptedValue might be re-examined by the sending entity
+         *                     -- in the future)
+         *                     encValue       BIT STRING }
+         *                     -- the encrypted value itself
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            AddOptional(v, 0, intendedAlg);
+            AddOptional(v, 1, symmAlg);
+            AddOptional(v, 2, encSymmKey);
+            AddOptional(v, 3, keyAlg);
+            AddOptional(v, 4, valueHint);
+
+            v.Add(encValue);
+
+            return new DerSequence(v);
+        }
+
+        private void AddOptional(Asn1EncodableVector v, int tagNo, Asn1Encodable obj)
+        {
+            if (obj != null)
+            {
+                v.Add(new DerTaggedObject(false, tagNo, obj));
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/OptionalValidity.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/OptionalValidity.cs
new file mode 100644
index 0000000..d1a0f7f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/OptionalValidity.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class OptionalValidity
+        : Asn1Encodable
+    {
+        private readonly Time notBefore;
+        private readonly Time notAfter;
+
+        private OptionalValidity(Asn1Sequence seq)
+        {
+            foreach (Asn1TaggedObject tObj in seq)
+            {
+                if (tObj.TagNo == 0)
+                {
+                    notBefore = Time.GetInstance(tObj, true);
+                }
+                else
+                {
+                    notAfter = Time.GetInstance(tObj, true);
+                }
+            }
+        }
+
+        public static OptionalValidity GetInstance(object obj)
+        {
+            if (obj == null || obj is OptionalValidity)
+                return (OptionalValidity)obj;
+
+            return new OptionalValidity(Asn1Sequence.GetInstance(obj));
+        }
+
+        public virtual Time NotBefore
+        {
+            get { return notBefore; }
+        }
+
+        public virtual Time NotAfter
+        {
+            get { return notAfter; }
+        }
+
+        /**
+         * <pre>
+         * OptionalValidity ::= SEQUENCE {
+         *                        notBefore  [0] Time OPTIONAL,
+         *                        notAfter   [1] Time OPTIONAL } --at least one MUST be present
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (notBefore != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, notBefore));
+            }
+
+            if (notAfter != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, notAfter));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PKIArchiveOptions.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PKIArchiveOptions.cs
new file mode 100644
index 0000000..910f73b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PKIArchiveOptions.cs
@@ -0,0 +1,105 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class PkiArchiveOptions
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int encryptedPrivKey = 0;
+        public const int keyGenParameters = 1;
+        public const int archiveRemGenPrivKey = 2;
+
+        private readonly Asn1Encodable value;
+
+        public static PkiArchiveOptions GetInstance(object obj)
+        {
+            if (obj is PkiArchiveOptions)
+                return (PkiArchiveOptions)obj;
+
+            if (obj is Asn1TaggedObject)
+                return new PkiArchiveOptions((Asn1TaggedObject)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        private PkiArchiveOptions(Asn1TaggedObject tagged)
+        {
+            switch (tagged.TagNo)
+            {
+                case encryptedPrivKey:
+                    value = EncryptedKey.GetInstance(tagged.GetObject());
+                    break;
+                case keyGenParameters:
+                    value = Asn1OctetString.GetInstance(tagged, false);
+                    break;
+                case archiveRemGenPrivKey:
+                    value = DerBoolean.GetInstance(tagged, false);
+                    break;
+                default:
+                    throw new ArgumentException("unknown tag number: " + tagged.TagNo, "tagged");
+            }
+        }
+
+        public PkiArchiveOptions(EncryptedKey encKey)
+        {
+            this.value = encKey;
+        }
+
+        public PkiArchiveOptions(Asn1OctetString keyGenParameters)
+        {
+            this.value = keyGenParameters;
+        }
+
+        public PkiArchiveOptions(bool archiveRemGenPrivKey)
+        {
+            this.value = DerBoolean.GetInstance(archiveRemGenPrivKey);
+        }
+
+        public virtual int Type
+        {
+            get
+            {
+                if (value is EncryptedKey)
+                    return encryptedPrivKey;
+
+                if (value is Asn1OctetString)
+                    return keyGenParameters;
+
+                return archiveRemGenPrivKey;
+            }
+        }
+
+        public virtual Asn1Encodable Value
+        {
+            get { return value; }
+        }
+
+        /**
+         * <pre>
+         *  PkiArchiveOptions ::= CHOICE {
+         *      encryptedPrivKey     [0] EncryptedKey,
+         *      -- the actual value of the private key
+         *      keyGenParameters     [1] KeyGenParameters,
+         *      -- parameters which allow the private key to be re-generated
+         *      archiveRemGenPrivKey [2] BOOLEAN }
+         *      -- set to TRUE if sender wishes receiver to archive the private
+         *      -- key of a key pair that the receiver generates in response to
+         *      -- this request; set to FALSE if no archival is desired.
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            if (value is EncryptedKey)
+            {
+                return new DerTaggedObject(true, encryptedPrivKey, value);  // choice
+            }
+
+            if (value is Asn1OctetString)
+            {
+                return new DerTaggedObject(false, keyGenParameters, value);
+            }
+
+            return new DerTaggedObject(false, archiveRemGenPrivKey, value);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PKIPublicationInfo.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PKIPublicationInfo.cs
new file mode 100644
index 0000000..c8bc140
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PKIPublicationInfo.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class PkiPublicationInfo
+        : Asn1Encodable
+    {
+        private readonly DerInteger action;
+        private readonly Asn1Sequence pubInfos;
+
+        private PkiPublicationInfo(Asn1Sequence seq)
+        {
+            action = DerInteger.GetInstance(seq[0]);
+            pubInfos = Asn1Sequence.GetInstance(seq[1]);
+        }
+
+        public static PkiPublicationInfo GetInstance(object obj)
+        {
+            if (obj is PkiPublicationInfo)
+                return (PkiPublicationInfo)obj;
+
+            if (obj is Asn1Sequence)
+                return new PkiPublicationInfo((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public virtual DerInteger Action
+        {
+            get { return action; }
+        }
+
+        public virtual SinglePubInfo[] GetPubInfos()
+        {
+            if (pubInfos == null)
+                return null;
+
+            SinglePubInfo[] results = new SinglePubInfo[pubInfos.Count];
+            for (int i = 0; i != results.Length; ++i)
+            {
+                results[i] = SinglePubInfo.GetInstance(pubInfos[i]);
+            }
+            return results;
+        }
+
+        /**
+         * <pre>
+         * PkiPublicationInfo ::= SEQUENCE {
+         *                  action     INTEGER {
+         *                                 dontPublish (0),
+         *                                 pleasePublish (1) },
+         *                  pubInfos  SEQUENCE SIZE (1..MAX) OF SinglePubInfo OPTIONAL }
+         * -- pubInfos MUST NOT be present if action is "dontPublish"
+         * -- (if action is "pleasePublish" and pubInfos is omitted,
+         * -- "dontCare" is assumed)
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(action, pubInfos);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PKMacValue.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PKMacValue.cs
new file mode 100644
index 0000000..20a08fd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PKMacValue.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    /**
+     * Password-based MAC value for use with POPOSigningKeyInput.
+     */
+    public class PKMacValue
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier  algID;
+        private readonly DerBitString         macValue;
+
+        private PKMacValue(Asn1Sequence seq)
+        {
+            this.algID = AlgorithmIdentifier.GetInstance(seq[0]);
+            this.macValue = DerBitString.GetInstance(seq[1]);
+        }
+
+        public static PKMacValue GetInstance(object obj)
+        {
+            if (obj is PKMacValue)
+                return (PKMacValue)obj;
+
+            if (obj is Asn1Sequence)
+                return new PKMacValue((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public static PKMacValue GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        /**
+         * Creates a new PKMACValue.
+         * @param params parameters for password-based MAC
+         * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+         */
+        public PKMacValue(
+            PbmParameter pbmParams,
+            DerBitString macValue)
+            : this(new AlgorithmIdentifier(CmpObjectIdentifiers.passwordBasedMac, pbmParams), macValue)
+        {
+        }
+
+        /**
+         * Creates a new PKMACValue.
+         * @param aid CMPObjectIdentifiers.passwordBasedMAC, with PBMParameter
+         * @param value MAC of the DER-encoded SubjectPublicKeyInfo
+         */
+        public PKMacValue(
+            AlgorithmIdentifier algID,
+            DerBitString        macValue)
+        {
+            this.algID = algID;
+            this.macValue = macValue;
+        }
+
+        public virtual AlgorithmIdentifier AlgID
+        {
+            get { return algID; }
+        }
+
+        public virtual DerBitString MacValue
+        {
+            get { return macValue; }
+        }
+
+        /**
+         * <pre>
+         * PKMACValue ::= SEQUENCE {
+         *      algId  AlgorithmIdentifier,
+         *      -- algorithm value shall be PasswordBasedMac 1.2.840.113533.7.66.13
+         *      -- parameter value is PBMParameter
+         *      value  BIT STRING }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(algID, macValue);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PopoPrivKey.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoPrivKey.cs
new file mode 100644
index 0000000..0cedc51
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoPrivKey.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class PopoPrivKey
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int thisMessage = 0;
+        public const int subsequentMessage = 1;
+        public const int dhMAC = 2;
+        public const int agreeMAC = 3;
+        public const int encryptedKey = 4;
+
+        private readonly int tagNo;
+        private readonly Asn1Encodable obj;
+
+        private PopoPrivKey(Asn1TaggedObject obj)
+        {
+            this.tagNo = obj.TagNo;
+
+            switch (tagNo)
+            {
+            case thisMessage:
+                this.obj = DerBitString.GetInstance(obj, false);
+                break;
+            case subsequentMessage:
+                this.obj = SubsequentMessage.ValueOf(DerInteger.GetInstance(obj, false).Value.IntValue);
+                break;
+            case dhMAC:
+                this.obj = DerBitString.GetInstance(obj, false);
+                break;
+            case agreeMAC:
+                this.obj = PKMacValue.GetInstance(obj, false);
+                break;
+            case encryptedKey:
+                this.obj = EnvelopedData.GetInstance(obj, false);
+                break;
+            default:
+                throw new ArgumentException("unknown tag in PopoPrivKey", "obj");
+            }
+        }
+
+        public static PopoPrivKey GetInstance(Asn1TaggedObject tagged, bool isExplicit)
+        {
+            return new PopoPrivKey(Asn1TaggedObject.GetInstance(tagged.GetObject()));
+        }
+
+        public PopoPrivKey(SubsequentMessage msg)
+        {
+            this.tagNo = subsequentMessage;
+            this.obj = msg;
+        }
+
+        public virtual int Type
+        {
+            get { return tagNo; }
+        }
+
+        public virtual Asn1Encodable Value
+        {
+            get { return obj; }
+        }
+
+        /**
+         * <pre>
+         * PopoPrivKey ::= CHOICE {
+         *        thisMessage       [0] BIT STRING,         -- Deprecated
+         *         -- possession is proven in this message (which contains the private
+         *         -- key itself (encrypted for the CA))
+         *        subsequentMessage [1] SubsequentMessage,
+         *         -- possession will be proven in a subsequent message
+         *        dhMAC             [2] BIT STRING,         -- Deprecated
+         *        agreeMAC          [3] PKMACValue,
+         *        encryptedKey      [4] EnvelopedData }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(false, tagNo, obj);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKey.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKey.cs
new file mode 100644
index 0000000..614278e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKey.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class PopoSigningKey
+        : Asn1Encodable
+    {
+        private readonly PopoSigningKeyInput poposkInput;
+        private readonly AlgorithmIdentifier algorithmIdentifier;
+        private readonly DerBitString signature;
+
+        private PopoSigningKey(Asn1Sequence seq)
+        {
+            int index = 0;
+
+            if (seq[index] is Asn1TaggedObject)
+            {
+                Asn1TaggedObject tagObj
+                    = (Asn1TaggedObject) seq[index++];
+                if (tagObj.TagNo != 0)
+                {
+                    throw new ArgumentException( "Unknown PopoSigningKeyInput tag: " + tagObj.TagNo, "seq");
+                }
+                poposkInput = PopoSigningKeyInput.GetInstance(tagObj.GetObject());
+            }
+            algorithmIdentifier = AlgorithmIdentifier.GetInstance(seq[index++]);
+            signature = DerBitString.GetInstance(seq[index]);
+        }
+
+        public static PopoSigningKey GetInstance(object obj)
+        {
+            if (obj is PopoSigningKey)
+                return (PopoSigningKey)obj;
+
+            if (obj is Asn1Sequence)
+                return new PopoSigningKey((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public static PopoSigningKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        /**
+         * Creates a new Proof of Possession object for a signing key.
+         * @param poposkIn the PopoSigningKeyInput structure, or null if the
+         *     CertTemplate includes both subject and publicKey values.
+         * @param aid the AlgorithmIdentifier used to sign the proof of possession.
+         * @param signature a signature over the DER-encoded value of poposkIn,
+         *     or the DER-encoded value of certReq if poposkIn is null.
+         */
+        public PopoSigningKey(
+            PopoSigningKeyInput poposkIn,
+            AlgorithmIdentifier aid,
+            DerBitString signature)
+        {
+            this.poposkInput = poposkIn;
+            this.algorithmIdentifier = aid;
+            this.signature = signature;
+        }
+
+        public virtual PopoSigningKeyInput PoposkInput
+        {
+            get { return poposkInput; }
+        }
+
+        public virtual AlgorithmIdentifier AlgorithmIdentifier
+        {
+            get { return algorithmIdentifier; }
+        }
+
+        public virtual DerBitString Signature
+        {
+            get { return signature; }
+        }
+
+        /**
+         * <pre>
+         * PopoSigningKey ::= SEQUENCE {
+         *                      poposkInput           [0] PopoSigningKeyInput OPTIONAL,
+         *                      algorithmIdentifier   AlgorithmIdentifier,
+         *                      signature             BIT STRING }
+         *  -- The signature (using "algorithmIdentifier") is on the
+         *  -- DER-encoded value of poposkInput.  NOTE: If the CertReqMsg
+         *  -- certReq CertTemplate contains the subject and publicKey values,
+         *  -- then poposkInput MUST be omitted and the signature MUST be
+         *  -- computed on the DER-encoded value of CertReqMsg certReq.  If
+         *  -- the CertReqMsg certReq CertTemplate does not contain the public
+         *  -- key and subject values, then poposkInput MUST be present and
+         *  -- MUST be signed.  This strategy ensures that the public key is
+         *  -- not present in both the poposkInput and CertReqMsg certReq
+         *  -- CertTemplate fields.
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (poposkInput != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, poposkInput));
+            }
+
+            v.Add(algorithmIdentifier);
+            v.Add(signature);
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKeyInput.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKeyInput.cs
new file mode 100644
index 0000000..6369526
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/PopoSigningKeyInput.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class PopoSigningKeyInput
+        : Asn1Encodable
+    {
+        private readonly GeneralName            sender;
+        private readonly PKMacValue             publicKeyMac;
+        private readonly SubjectPublicKeyInfo   publicKey;
+
+        private PopoSigningKeyInput(Asn1Sequence seq)
+        {
+            Asn1Encodable authInfo = (Asn1Encodable)seq[0];
+
+            if (authInfo is Asn1TaggedObject)
+            {
+                Asn1TaggedObject tagObj = (Asn1TaggedObject)authInfo;
+                if (tagObj.TagNo != 0)
+                {
+                    throw new ArgumentException("Unknown authInfo tag: " + tagObj.TagNo, "seq");
+                }
+                sender = GeneralName.GetInstance(tagObj.GetObject());
+            }
+            else
+            {
+                publicKeyMac = PKMacValue.GetInstance(authInfo);
+            }
+
+            publicKey = SubjectPublicKeyInfo.GetInstance(seq[1]);
+        }
+
+        public static PopoSigningKeyInput GetInstance(object obj)
+        {
+            if (obj is PopoSigningKeyInput)
+                return (PopoSigningKeyInput)obj;
+
+            if (obj is Asn1Sequence)
+                return new PopoSigningKeyInput((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        /** Creates a new PopoSigningKeyInput with sender name as authInfo. */
+        public PopoSigningKeyInput(
+            GeneralName sender,
+            SubjectPublicKeyInfo spki)
+        {
+            this.sender = sender;
+            this.publicKey = spki;
+        }
+
+        /** Creates a new PopoSigningKeyInput using password-based MAC. */
+        public PopoSigningKeyInput(
+            PKMacValue pkmac,
+            SubjectPublicKeyInfo spki)
+        {
+            this.publicKeyMac = pkmac;
+            this.publicKey = spki;
+        }
+
+        /** Returns the sender field, or null if authInfo is publicKeyMac */
+        public virtual GeneralName Sender
+        {
+            get { return sender; }
+        }
+
+        /** Returns the publicKeyMac field, or null if authInfo is sender */
+        public virtual PKMacValue PublicKeyMac
+        {
+            get { return publicKeyMac; }
+        }
+
+        public virtual SubjectPublicKeyInfo PublicKey
+        {
+            get { return publicKey; }
+        }
+
+        /**
+         * <pre>
+         * PopoSigningKeyInput ::= SEQUENCE {
+         *        authInfo             CHOICE {
+         *                                 sender              [0] GeneralName,
+         *                                 -- used only if an authenticated identity has been
+         *                                 -- established for the sender (e.g., a DN from a
+         *                                 -- previously-issued and currently-valid certificate
+         *                                 publicKeyMac        PKMacValue },
+         *                                 -- used if no authenticated GeneralName currently exists for
+         *                                 -- the sender; publicKeyMac contains a password-based MAC
+         *                                 -- on the DER-encoded value of publicKey
+         *        publicKey           SubjectPublicKeyInfo }  -- from CertTemplate
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (sender != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, sender));
+            }
+            else
+            {
+                v.Add(publicKeyMac);
+            }
+
+            v.Add(publicKey);
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/ProofOfPossession.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/ProofOfPossession.cs
new file mode 100644
index 0000000..fc00edb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/ProofOfPossession.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class ProofOfPossession
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int TYPE_RA_VERIFIED = 0;
+        public const int TYPE_SIGNING_KEY = 1;
+        public const int TYPE_KEY_ENCIPHERMENT = 2;
+        public const int TYPE_KEY_AGREEMENT = 3;
+
+        private readonly int tagNo;
+        private readonly Asn1Encodable obj;
+
+        private ProofOfPossession(Asn1TaggedObject tagged)
+        {
+            tagNo = tagged.TagNo;
+            switch (tagNo)
+            {
+            case 0:
+                obj = DerNull.Instance;
+                break;
+            case 1:
+                obj = PopoSigningKey.GetInstance(tagged, false);
+                break;
+            case 2:
+            case 3:
+                obj = PopoPrivKey.GetInstance(tagged, false);
+                break;
+            default:
+                throw new ArgumentException("unknown tag: " + tagNo, "tagged");
+            }
+        }
+
+        public static ProofOfPossession GetInstance(object obj)
+        {
+            if (obj is ProofOfPossession)
+                return (ProofOfPossession)obj;
+
+            if (obj is Asn1TaggedObject)
+                return new ProofOfPossession((Asn1TaggedObject)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        /** Creates a ProofOfPossession with type raVerified. */
+        public ProofOfPossession()
+        {
+            tagNo = TYPE_RA_VERIFIED;
+            obj = DerNull.Instance;
+        }
+
+        /** Creates a ProofOfPossession for a signing key. */
+        public ProofOfPossession(PopoSigningKey Poposk)
+        {
+            tagNo = TYPE_SIGNING_KEY;
+            obj = Poposk;
+        }
+
+        /**
+         * Creates a ProofOfPossession for key encipherment or agreement.
+         * @param type one of TYPE_KEY_ENCIPHERMENT or TYPE_KEY_AGREEMENT
+         */
+        public ProofOfPossession(int type, PopoPrivKey privkey)
+        {
+            tagNo = type;
+            obj = privkey;
+        }
+
+        public virtual int Type
+        {
+            get { return tagNo; }
+        }
+
+        public virtual Asn1Encodable Object
+        {
+            get { return obj; }
+        }
+
+        /**
+         * <pre>
+         * ProofOfPossession ::= CHOICE {
+         *                           raVerified        [0] NULL,
+         *                           -- used if the RA has already verified that the requester is in
+         *                           -- possession of the private key
+         *                           signature         [1] PopoSigningKey,
+         *                           keyEncipherment   [2] PopoPrivKey,
+         *                           keyAgreement      [3] PopoPrivKey }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(false, tagNo, obj);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/SinglePubInfo.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/SinglePubInfo.cs
new file mode 100644
index 0000000..eaf8a3e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/SinglePubInfo.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class SinglePubInfo
+        : Asn1Encodable
+    {
+        private readonly DerInteger pubMethod;
+        private readonly GeneralName pubLocation;
+
+        private SinglePubInfo(Asn1Sequence seq)
+        {
+            pubMethod = DerInteger.GetInstance(seq[0]);
+
+            if (seq.Count == 2)
+            {
+                pubLocation = GeneralName.GetInstance(seq[1]);
+            }
+        }
+
+        public static SinglePubInfo GetInstance(object obj)
+        {
+            if (obj is SinglePubInfo)
+                return (SinglePubInfo)obj;
+
+            if (obj is Asn1Sequence)
+                return new SinglePubInfo((Asn1Sequence)obj);
+
+            throw new ArgumentException("Invalid object: " + obj.GetType().Name, "obj");
+        }
+
+        public virtual GeneralName PubLocation
+        {
+            get { return pubLocation; }
+        }
+
+        /**
+         * <pre>
+         * SinglePubInfo ::= SEQUENCE {
+         *        pubMethod    INTEGER {
+         *           dontCare    (0),
+         *           x500        (1),
+         *           web         (2),
+         *           ldap        (3) },
+         *       pubLocation  GeneralName OPTIONAL }
+         * </pre>
+         * @return a basic ASN.1 object representation.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(pubMethod);
+            v.AddOptional(pubLocation);
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/crmf/SubsequentMessage.cs b/BouncyCastle.AxCrypt/src/asn1/crmf/SubsequentMessage.cs
new file mode 100644
index 0000000..cc1c164
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/crmf/SubsequentMessage.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Crmf
+{
+    public class SubsequentMessage
+        : DerInteger
+    {
+        public static readonly SubsequentMessage encrCert = new SubsequentMessage(0);
+        public static readonly SubsequentMessage challengeResp = new SubsequentMessage(1);
+    
+        private SubsequentMessage(int value)
+            : base(value)
+        {
+        }
+
+        public static SubsequentMessage ValueOf(int value)
+        {
+            if (value == 0)
+                return encrCert;
+
+            if (value == 1)
+                return challengeResp;
+
+            throw new ArgumentException("unknown value: " + value, "value");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs
new file mode 100644
index 0000000..e2f2c18
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/CryptoProObjectIdentifiers.cs
@@ -0,0 +1,51 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    public abstract class CryptoProObjectIdentifiers
+    {
+        // GOST Algorithms OBJECT IDENTIFIERS :
+        // { iso(1) member-body(2) ru(643) rans(2) cryptopro(2)}
+        public const string GostID = "1.2.643.2.2";
+
+		public static readonly DerObjectIdentifier GostR3411 = new DerObjectIdentifier(GostID + ".9");
+        public static readonly DerObjectIdentifier GostR3411Hmac = new DerObjectIdentifier(GostID + ".10");
+
+        public static readonly DerObjectIdentifier GostR28147Cbc = new DerObjectIdentifier(GostID + ".21");
+
+        public static readonly DerObjectIdentifier ID_Gost28147_89_CryptoPro_A_ParamSet = new DerObjectIdentifier(GostID + ".31.1");
+
+        public static readonly DerObjectIdentifier GostR3410x94 = new DerObjectIdentifier(GostID + ".20");
+        public static readonly DerObjectIdentifier GostR3410x2001 = new DerObjectIdentifier(GostID + ".19");
+        public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x94 = new DerObjectIdentifier(GostID + ".4");
+        public static readonly DerObjectIdentifier GostR3411x94WithGostR3410x2001 = new DerObjectIdentifier(GostID + ".3");
+
+		// { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) hashes(30) }
+        public static readonly DerObjectIdentifier GostR3411x94CryptoProParamSet = new DerObjectIdentifier(GostID + ".30.1");
+
+		// { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) signs(32) }
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProA = new DerObjectIdentifier(GostID + ".32.2");
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProB = new DerObjectIdentifier(GostID + ".32.3");
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProC = new DerObjectIdentifier(GostID + ".32.4");
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProD = new DerObjectIdentifier(GostID + ".32.5");
+
+		// { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) exchanges(33) }
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProXchA = new DerObjectIdentifier(GostID + ".33.1");
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProXchB = new DerObjectIdentifier(GostID + ".33.2");
+        public static readonly DerObjectIdentifier GostR3410x94CryptoProXchC = new DerObjectIdentifier(GostID + ".33.3");
+
+		//{ iso(1) member-body(2)ru(643) rans(2) cryptopro(2) ecc-signs(35) }
+        public static readonly DerObjectIdentifier GostR3410x2001CryptoProA = new DerObjectIdentifier(GostID + ".35.1");
+        public static readonly DerObjectIdentifier GostR3410x2001CryptoProB = new DerObjectIdentifier(GostID + ".35.2");
+        public static readonly DerObjectIdentifier GostR3410x2001CryptoProC = new DerObjectIdentifier(GostID + ".35.3");
+
+		// { iso(1) member-body(2) ru(643) rans(2) cryptopro(2) ecc-exchanges(36) }
+        public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchA  = new DerObjectIdentifier(GostID + ".36.0");
+        public static readonly DerObjectIdentifier GostR3410x2001CryptoProXchB  = new DerObjectIdentifier(GostID + ".36.1");
+
+		public static readonly DerObjectIdentifier GostElSgDH3410Default = new DerObjectIdentifier(GostID + ".36.0");
+        public static readonly DerObjectIdentifier GostElSgDH3410x1 = new DerObjectIdentifier(GostID + ".36.1");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410NamedCurves.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
new file mode 100644
index 0000000..ca57c28
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410NamedCurves.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    /**
+    * table of the available named parameters for GOST 3410-2001.
+    */
+    public sealed class ECGost3410NamedCurves
+    {
+        private ECGost3410NamedCurves()
+        {
+        }
+
+        internal static readonly IDictionary objIds = Platform.CreateHashtable();
+        internal static readonly IDictionary parameters = Platform.CreateHashtable();
+        internal static readonly IDictionary names = Platform.CreateHashtable();
+
+        static ECGost3410NamedCurves()
+        {
+            BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+            BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+                new BigInteger("166"), // b
+                mod_q,
+                BigInteger.One);
+
+            ECDomainParameters ecParams = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("1"), // x
+                    new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+                mod_q);
+
+            parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = ecParams;
+
+            mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319");
+            mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+            curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"),
+                new BigInteger("166"),
+                mod_q,
+                BigInteger.One);
+
+            ecParams = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("1"), // x
+                    new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+                mod_q);
+
+            parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = ecParams;
+
+            mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
+            mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703"); //q
+
+            curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
+                new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
+                mod_q,
+                BigInteger.One);
+
+            ecParams = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("1"), // x
+                    new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
+                mod_q); // q
+
+            parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = ecParams;
+
+            mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619");
+            mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
+
+            curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"),
+                new BigInteger("32858"),
+                mod_q,
+                BigInteger.One);
+
+            ecParams = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("0"),
+                    new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")),
+                mod_q);
+
+            parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = ecParams;
+
+            mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
+            mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601"); //q
+            curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+                new BigInteger("32858"), // b
+                mod_q,
+                BigInteger.One);
+
+            ecParams = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("0"), // x
+                    new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
+                mod_q); // q
+
+            parameters[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = ecParams;
+
+            objIds["GostR3410-2001-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProA;
+            objIds["GostR3410-2001-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProB;
+            objIds["GostR3410-2001-CryptoPro-C"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProC;
+            objIds["GostR3410-2001-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA;
+            objIds["GostR3410-2001-CryptoPro-XchB"] = CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB;
+
+            names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProA] = "GostR3410-2001-CryptoPro-A";
+            names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProB] = "GostR3410-2001-CryptoPro-B";
+            names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProC] = "GostR3410-2001-CryptoPro-C";
+            names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchA] = "GostR3410-2001-CryptoPro-XchA";
+            names[CryptoProObjectIdentifiers.GostR3410x2001CryptoProXchB] = "GostR3410-2001-CryptoPro-XchB";
+        }
+
+        /**
+        * return the ECDomainParameters object for the given OID, null if it
+        * isn't present.
+        *
+        * @param oid an object identifier representing a named parameters, if present.
+        */
+        public static ECDomainParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            return (ECDomainParameters) parameters[oid];
+        }
+
+        /**
+         * returns an enumeration containing the name strings for curves
+         * contained in this structure.
+         */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(objIds.Keys); }
+        }
+
+        public static ECDomainParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name];
+
+            if (oid != null)
+            {
+                return (ECDomainParameters) parameters[oid];
+            }
+
+            return null;
+        }
+
+        /**
+        * return the named curve name represented by the given object identifier.
+        */
+        public static string GetName(
+            DerObjectIdentifier oid)
+        {
+            return (string) names[oid];
+        }
+
+        public static DerObjectIdentifier GetOid(
+            string name)
+        {
+            return (DerObjectIdentifier) objIds[name];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs
new file mode 100644
index 0000000..6f4435d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/ECGOST3410ParamSetParameters.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    public class ECGost3410ParamSetParameters
+        : Asn1Encodable
+    {
+        internal readonly DerInteger p, q, a, b, x, y;
+
+        public static ECGost3410ParamSetParameters GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static ECGost3410ParamSetParameters GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is ECGost3410ParamSetParameters)
+            {
+                return (ECGost3410ParamSetParameters) obj;
+            }
+
+            if (obj is Asn1Sequence)
+            {
+                return new ECGost3410ParamSetParameters((Asn1Sequence) obj);
+            }
+
+            throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+        }
+
+        public ECGost3410ParamSetParameters(
+            BigInteger a,
+            BigInteger b,
+            BigInteger p,
+            BigInteger q,
+            int        x,
+            BigInteger y)
+        {
+            this.a = new DerInteger(a);
+            this.b = new DerInteger(b);
+            this.p = new DerInteger(p);
+            this.q = new DerInteger(q);
+            this.x = new DerInteger(x);
+            this.y = new DerInteger(y);
+        }
+
+        public ECGost3410ParamSetParameters(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 6)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.a = DerInteger.GetInstance(seq[0]);
+			this.b = DerInteger.GetInstance(seq[1]);
+			this.p = DerInteger.GetInstance(seq[2]);
+			this.q = DerInteger.GetInstance(seq[3]);
+			this.x = DerInteger.GetInstance(seq[4]);
+			this.y = DerInteger.GetInstance(seq[5]);
+        }
+
+		public BigInteger P
+		{
+			get { return p.PositiveValue; }
+		}
+
+		public BigInteger Q
+		{
+			get { return q.PositiveValue; }
+		}
+
+		public BigInteger A
+		{
+			get { return a.PositiveValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(a, b, p, q, x, y);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST28147Parameters.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST28147Parameters.cs
new file mode 100644
index 0000000..eb7e0e3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST28147Parameters.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    public class Gost28147Parameters
+        : Asn1Encodable
+    {
+        private readonly Asn1OctetString iv;
+        private readonly DerObjectIdentifier paramSet;
+
+		public static Gost28147Parameters GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static Gost28147Parameters GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Gost28147Parameters)
+            {
+                return (Gost28147Parameters) obj;
+            }
+
+            if (obj is Asn1Sequence)
+            {
+                return new Gost28147Parameters((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+        }
+
+        private Gost28147Parameters(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.iv = Asn1OctetString.GetInstance(seq[0]);
+			this.paramSet = DerObjectIdentifier.GetInstance(seq[1]);
+        }
+
+		/**
+         * <pre>
+         * Gost28147-89-Parameters ::=
+         *               SEQUENCE {
+         *                       iv                   Gost28147-89-IV,
+         *                       encryptionParamSet   OBJECT IDENTIFIER
+         *                }
+         *
+         *   Gost28147-89-IV ::= OCTET STRING (SIZE (8))
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(iv, paramSet);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410NamedParameters.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410NamedParameters.cs
new file mode 100644
index 0000000..66dba51
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410NamedParameters.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    /**
+    * table of the available named parameters for GOST 3410-94.
+    */
+    public sealed class Gost3410NamedParameters
+    {
+		private Gost3410NamedParameters()
+		{
+		}
+
+        private static readonly IDictionary objIds = Platform.CreateHashtable();
+        private static readonly IDictionary parameters = Platform.CreateHashtable();
+
+        private static readonly Gost3410ParamSetParameters cryptoProA = new Gost3410ParamSetParameters(
+            1024,
+            new BigInteger("127021248288932417465907042777176443525787653508916535812817507265705031260985098497423188333483401180925999995120988934130659205614996724254121049274349357074920312769561451689224110579311248812610229678534638401693520013288995000362260684222750813532307004517341633685004541062586971416883686778842537820383"),
+            new BigInteger("68363196144955700784444165611827252895102170888761442055095051287550314083023"),
+            new BigInteger("100997906755055304772081815535925224869841082572053457874823515875577147990529272777244152852699298796483356699682842027972896052747173175480590485607134746852141928680912561502802222185647539190902656116367847270145019066794290930185446216399730872221732889830323194097355403213400972588322876850946740663962")
+            //            validationAlgorithm {
+            //                    algorithm
+            //                        id-GostR3410-94-bBis,
+            //                    parameters
+            //                        GostR3410-94-ValidationBisParameters: {
+            //                            x0      1376285941,
+            //                            c       3996757427
+            //                        }
+            //                }
+
+            );
+
+        private static readonly Gost3410ParamSetParameters cryptoProB = new Gost3410ParamSetParameters(
+            1024,
+            new BigInteger("139454871199115825601409655107690713107041707059928031797758001454375765357722984094124368522288239833039114681648076688236921220737322672160740747771700911134550432053804647694904686120113087816240740184800477047157336662926249423571248823968542221753660143391485680840520336859458494803187341288580489525163"),
+            new BigInteger("79885141663410976897627118935756323747307951916507639758300472692338873533959"),
+            new BigInteger("42941826148615804143873447737955502392672345968607143066798112994089471231420027060385216699563848719957657284814898909770759462613437669456364882730370838934791080835932647976778601915343474400961034231316672578686920482194932878633360203384797092684342247621055760235016132614780652761028509445403338652341")
+            //    validationAlgorithm {
+            //            algorithm
+            //                id-GostR3410-94-bBis,
+            //            parameters
+            //                GostR3410-94-ValidationBisParameters: {
+            //                    x0      1536654555,
+            //                    c       1855361757,
+            //                    d       14408629386140014567655
+            //4902939282056547857802241461782996702017713059974755104394739915140
+            //6115284791024439062735788342744854120601660303926203867703556828005
+            //8957203818114895398976594425537561271800850306
+            //                }
+            //        }
+            //}
+            );
+
+        private static readonly Gost3410ParamSetParameters cryptoProXchA = new Gost3410ParamSetParameters(
+            1024,
+            new BigInteger("142011741597563481196368286022318089743276138395243738762872573441927459393512718973631166078467600360848946623567625795282774719212241929071046134208380636394084512691828894000571524625445295769349356752728956831541775441763139384457191755096847107846595662547942312293338483924514339614727760681880609734239"),
+            new BigInteger("91771529896554605945588149018382750217296858393520724172743325725474374979801"),
+            new BigInteger("133531813272720673433859519948319001217942375967847486899482359599369642528734712461590403327731821410328012529253871914788598993103310567744136196364803064721377826656898686468463277710150809401182608770201615324990468332931294920912776241137878030224355746606283971659376426832674269780880061631528163475887")
+            );
+
+		static Gost3410NamedParameters()
+        {
+            parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProA] = cryptoProA;
+            parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProB] = cryptoProB;
+            //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProC] = cryptoProC;
+            //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProD] = cryptoProD;
+            parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA] = cryptoProXchA;
+            //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchB] = cryptoProXchA;
+            //parameters[CryptoProObjectIdentifiers.GostR3410x94CryptoProXchC] = cryptoProXchA;
+
+			objIds["GostR3410-94-CryptoPro-A"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProA;
+            objIds["GostR3410-94-CryptoPro-B"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProB;
+            objIds["GostR3410-94-CryptoPro-XchA"] = CryptoProObjectIdentifiers.GostR3410x94CryptoProXchA;
+        }
+
+		/**
+        * return the GOST3410ParamSetParameters object for the given OID, null if it
+        * isn't present.
+        *
+        * @param oid an object identifier representing a named parameters, if present.
+        */
+        public static Gost3410ParamSetParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            return (Gost3410ParamSetParameters) parameters[oid];
+        }
+
+		/**
+        * returns an enumeration containing the name strings for parameters
+        * contained in this structure.
+        */
+        public static IEnumerable Names
+        {
+			get { return new EnumerableProxy(objIds.Keys); }
+        }
+
+		public static Gost3410ParamSetParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier) objIds[name];
+
+            if (oid != null)
+            {
+                return (Gost3410ParamSetParameters) parameters[oid];
+            }
+
+            return null;
+        }
+
+        public static DerObjectIdentifier GetOid(
+			string name)
+        {
+            return (DerObjectIdentifier) objIds[name];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410ParamSetParameters.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
new file mode 100644
index 0000000..f133cdf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410ParamSetParameters.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    public class Gost3410ParamSetParameters
+        : Asn1Encodable
+    {
+        private readonly int keySize;
+        private readonly DerInteger	p, q, a;
+
+		public static Gost3410ParamSetParameters GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static Gost3410ParamSetParameters GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Gost3410ParamSetParameters)
+            {
+                return (Gost3410ParamSetParameters) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new Gost3410ParamSetParameters((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+        }
+
+		public Gost3410ParamSetParameters(
+            int			keySize,
+            BigInteger	p,
+            BigInteger	q,
+            BigInteger	a)
+        {
+            this.keySize = keySize;
+            this.p = new DerInteger(p);
+            this.q = new DerInteger(q);
+            this.a = new DerInteger(a);
+        }
+
+		private Gost3410ParamSetParameters(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 4)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.keySize = DerInteger.GetInstance(seq[0]).Value.IntValue;
+			this.p = DerInteger.GetInstance(seq[1]);
+            this.q = DerInteger.GetInstance(seq[2]);
+			this.a = DerInteger.GetInstance(seq[3]);
+        }
+
+		public int KeySize
+		{
+			get { return keySize; }
+		}
+
+		public BigInteger P
+		{
+			get { return p.PositiveValue; }
+		}
+
+		public BigInteger Q
+		{
+			get { return q.PositiveValue; }
+		}
+
+		public BigInteger A
+		{
+			get { return a.PositiveValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(new DerInteger(keySize), p, q, a);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
new file mode 100644
index 0000000..8bc1460
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/cryptopro/GOST3410PublicKeyAlgParameters.cs
@@ -0,0 +1,99 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.CryptoPro
+{
+    public class Gost3410PublicKeyAlgParameters
+        : Asn1Encodable
+    {
+        private DerObjectIdentifier	publicKeyParamSet;
+        private DerObjectIdentifier	digestParamSet;
+        private DerObjectIdentifier	encryptionParamSet;
+
+		public static Gost3410PublicKeyAlgParameters GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static Gost3410PublicKeyAlgParameters GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Gost3410PublicKeyAlgParameters)
+            {
+                return (Gost3410PublicKeyAlgParameters) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new Gost3410PublicKeyAlgParameters((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid GOST3410Parameter: " + obj.GetType().Name);
+        }
+
+		public Gost3410PublicKeyAlgParameters(
+            DerObjectIdentifier	publicKeyParamSet,
+            DerObjectIdentifier	digestParamSet)
+			: this (publicKeyParamSet, digestParamSet, null)
+        {
+        }
+
+		public Gost3410PublicKeyAlgParameters(
+            DerObjectIdentifier  publicKeyParamSet,
+            DerObjectIdentifier  digestParamSet,
+            DerObjectIdentifier  encryptionParamSet)
+        {
+			if (publicKeyParamSet == null)
+				throw new ArgumentNullException("publicKeyParamSet");
+			if (digestParamSet == null)
+				throw new ArgumentNullException("digestParamSet");
+
+			this.publicKeyParamSet = publicKeyParamSet;
+            this.digestParamSet = digestParamSet;
+            this.encryptionParamSet = encryptionParamSet;
+        }
+
+		public Gost3410PublicKeyAlgParameters(
+            Asn1Sequence seq)
+        {
+            this.publicKeyParamSet = (DerObjectIdentifier) seq[0];
+            this.digestParamSet = (DerObjectIdentifier) seq[1];
+
+			if (seq.Count > 2)
+            {
+                this.encryptionParamSet = (DerObjectIdentifier) seq[2];
+            }
+        }
+
+		public DerObjectIdentifier PublicKeyParamSet
+		{
+			get { return publicKeyParamSet; }
+		}
+
+		public DerObjectIdentifier DigestParamSet
+		{
+			get { return digestParamSet; }
+		}
+
+		public DerObjectIdentifier EncryptionParamSet
+		{
+			get { return encryptionParamSet; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				publicKeyParamSet, digestParamSet);
+
+			if (encryptionParamSet != null)
+            {
+                v.Add(encryptionParamSet);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/eac/EACObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/eac/EACObjectIdentifiers.cs
new file mode 100644
index 0000000..d54ef0e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/eac/EACObjectIdentifiers.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Eac
+{
+	public abstract class EacObjectIdentifiers
+	{
+		// bsi-de OBJECT IDENTIFIER ::= {
+		//         itu-t(0) identified-organization(4) etsi(0)
+		//         reserved(127) etsi-identified-organization(0) 7
+		//     }
+		public static readonly DerObjectIdentifier bsi_de = new DerObjectIdentifier("0.4.0.127.0.7");
+
+		// id-PK OBJECT IDENTIFIER ::= {
+		//         bsi-de protocols(2) smartcard(2) 1
+		//     }
+		public static readonly DerObjectIdentifier id_PK = new DerObjectIdentifier(bsi_de + ".2.2.1");
+
+		public static readonly DerObjectIdentifier id_PK_DH = new DerObjectIdentifier(id_PK + ".1");
+		public static readonly DerObjectIdentifier id_PK_ECDH = new DerObjectIdentifier(id_PK + ".2");
+
+		// id-CA OBJECT IDENTIFIER ::= {
+		//         bsi-de protocols(2) smartcard(2) 3
+		//     }
+		public static readonly DerObjectIdentifier id_CA = new DerObjectIdentifier(bsi_de + ".2.2.3");
+		public static readonly DerObjectIdentifier id_CA_DH = new DerObjectIdentifier(id_CA + ".1");
+		public static readonly DerObjectIdentifier id_CA_DH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_DH + ".1");
+		public static readonly DerObjectIdentifier id_CA_ECDH = new DerObjectIdentifier(id_CA + ".2");
+		public static readonly DerObjectIdentifier id_CA_ECDH_3DES_CBC_CBC = new DerObjectIdentifier(id_CA_ECDH + ".1");
+
+		//
+		// id-TA OBJECT IDENTIFIER ::= {
+		//     bsi-de protocols(2) smartcard(2) 2
+		// }
+		public static readonly DerObjectIdentifier id_TA = new DerObjectIdentifier(bsi_de + ".2.2.2");
+
+		public static readonly DerObjectIdentifier id_TA_RSA = new DerObjectIdentifier(id_TA + ".1");
+		public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".1");
+		public static readonly DerObjectIdentifier id_TA_RSA_v1_5_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".2");
+		public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_1 = new DerObjectIdentifier(id_TA_RSA + ".3");
+		public static readonly DerObjectIdentifier id_TA_RSA_PSS_SHA_256 = new DerObjectIdentifier(id_TA_RSA + ".4");
+		public static readonly DerObjectIdentifier id_TA_ECDSA = new DerObjectIdentifier(id_TA + ".2");
+		public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_1 = new DerObjectIdentifier(id_TA_ECDSA + ".1");
+		public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_224 = new DerObjectIdentifier(id_TA_ECDSA + ".2");
+		public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_256 = new DerObjectIdentifier(id_TA_ECDSA + ".3");
+		public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_384 = new DerObjectIdentifier(id_TA_ECDSA + ".4");
+		public static readonly DerObjectIdentifier id_TA_ECDSA_SHA_512 = new DerObjectIdentifier(id_TA_ECDSA + ".5");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CertificateValues.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CertificateValues.cs
new file mode 100644
index 0000000..e0fb39b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CertificateValues.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.3.1 Certificate Values Attribute Definition
+	/// <code>
+	/// CertificateValues ::= SEQUENCE OF Certificate
+	/// </code>
+	/// </remarks>
+	public class CertificateValues
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence certificates;
+
+		public static CertificateValues GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CertificateValues)
+				return (CertificateValues) obj;
+
+			if (obj is Asn1Sequence)
+				return new CertificateValues((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CertificateValues' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CertificateValues(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+
+			foreach (Asn1Encodable ae in seq)
+			{
+				X509CertificateStructure.GetInstance(ae.ToAsn1Object());
+			}
+
+			this.certificates = seq;
+		}
+
+		public CertificateValues(
+			params X509CertificateStructure[] certificates)
+		{
+			if (certificates == null)
+				throw new ArgumentNullException("certificates");
+
+			this.certificates = new DerSequence(certificates);
+		}
+
+		public CertificateValues(
+			IEnumerable certificates)
+		{
+			if (certificates == null)
+				throw new ArgumentNullException("certificates");
+			if (!CollectionUtilities.CheckElementsAreOfType(certificates, typeof(X509CertificateStructure)))
+				throw new ArgumentException("Must contain only 'X509CertificateStructure' objects", "certificates");
+
+			this.certificates = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(certificates));
+		}
+
+		public X509CertificateStructure[] GetCertificates()
+		{
+			X509CertificateStructure[] result = new X509CertificateStructure[certificates.Count];
+			for (int i = 0; i < certificates.Count; ++i)
+			{
+				result[i] = X509CertificateStructure.GetInstance(certificates[i]);
+			}
+			return result;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return certificates;
+		}
+ 	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIdentifier.cs
new file mode 100644
index 0000000..65cd45b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIdentifier.cs
@@ -0,0 +1,17 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+    public abstract class CommitmentTypeIdentifier
+    {
+        public static readonly DerObjectIdentifier ProofOfOrigin = PkcsObjectIdentifiers.IdCtiEtsProofOfOrigin;
+        public static readonly DerObjectIdentifier ProofOfReceipt = PkcsObjectIdentifiers.IdCtiEtsProofOfReceipt;
+        public static readonly DerObjectIdentifier ProofOfDelivery = PkcsObjectIdentifiers.IdCtiEtsProofOfDelivery;
+        public static readonly DerObjectIdentifier ProofOfSender = PkcsObjectIdentifiers.IdCtiEtsProofOfSender;
+        public static readonly DerObjectIdentifier ProofOfApproval = PkcsObjectIdentifiers.IdCtiEtsProofOfApproval;
+        public static readonly DerObjectIdentifier ProofOfCreation = PkcsObjectIdentifiers.IdCtiEtsProofOfCreation;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIndication.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIndication.cs
new file mode 100644
index 0000000..8342cbf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeIndication.cs
@@ -0,0 +1,95 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+    public class CommitmentTypeIndication
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	commitmentTypeId;
+        private readonly Asn1Sequence			commitmentTypeQualifier;
+
+		public static CommitmentTypeIndication GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CommitmentTypeIndication)
+				return (CommitmentTypeIndication) obj;
+
+			if (obj is Asn1Sequence)
+				return new CommitmentTypeIndication((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CommitmentTypeIndication' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		public CommitmentTypeIndication(
+            Asn1Sequence seq)
+        {
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.commitmentTypeId = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+			if (seq.Count > 1)
+            {
+                this.commitmentTypeQualifier = (Asn1Sequence) seq[1].ToAsn1Object();
+            }
+        }
+
+		public CommitmentTypeIndication(
+            DerObjectIdentifier commitmentTypeId)
+			: this(commitmentTypeId, null)
+        {
+        }
+
+		public CommitmentTypeIndication(
+            DerObjectIdentifier	commitmentTypeId,
+            Asn1Sequence		commitmentTypeQualifier)
+        {
+			if (commitmentTypeId == null)
+				throw new ArgumentNullException("commitmentTypeId");
+
+			this.commitmentTypeId = commitmentTypeId;
+
+			if (commitmentTypeQualifier != null)
+			{
+				this.commitmentTypeQualifier = commitmentTypeQualifier;
+			}
+        }
+
+		public DerObjectIdentifier CommitmentTypeID
+		{
+			get { return commitmentTypeId; }
+		}
+
+		public Asn1Sequence CommitmentTypeQualifier
+		{
+			get { return commitmentTypeQualifier; }
+		}
+
+		/**
+        * <pre>
+        * CommitmentTypeIndication ::= SEQUENCE {
+        *      commitmentTypeId   CommitmentTypeIdentifier,
+        *      commitmentTypeQualifier   SEQUENCE SIZE (1..MAX) OF
+        *              CommitmentTypeQualifier OPTIONAL }
+        * </pre>
+        */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(commitmentTypeId);
+
+			if (commitmentTypeQualifier != null)
+            {
+                v.Add(commitmentTypeQualifier);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeQualifier.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeQualifier.cs
new file mode 100644
index 0000000..09ff707
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CommitmentTypeQualifier.cs
@@ -0,0 +1,119 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+    /**
+    * Commitment type qualifiers, used in the Commitment-Type-Indication attribute (RFC3126).
+    *
+    * <pre>
+    *   CommitmentTypeQualifier ::= SEQUENCE {
+    *       commitmentTypeIdentifier  CommitmentTypeIdentifier,
+    *       qualifier          ANY DEFINED BY commitmentTypeIdentifier OPTIONAL }
+    * </pre>
+    */
+    public class CommitmentTypeQualifier
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	commitmentTypeIdentifier;
+        private readonly Asn1Object				qualifier;
+
+        /**
+        * Creates a new <code>CommitmentTypeQualifier</code> instance.
+        *
+        * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+        */
+        public CommitmentTypeQualifier(
+            DerObjectIdentifier commitmentTypeIdentifier)
+            : this(commitmentTypeIdentifier, null)
+        {
+        }
+
+    /**
+        * Creates a new <code>CommitmentTypeQualifier</code> instance.
+        *
+        * @param commitmentTypeIdentifier a <code>CommitmentTypeIdentifier</code> value
+        * @param qualifier the qualifier, defined by the above field.
+        */
+        public CommitmentTypeQualifier(
+            DerObjectIdentifier	commitmentTypeIdentifier,
+            Asn1Encodable		qualifier)
+        {
+			if (commitmentTypeIdentifier == null)
+				throw new ArgumentNullException("commitmentTypeIdentifier");
+
+			this.commitmentTypeIdentifier = commitmentTypeIdentifier;
+
+			if (qualifier != null)
+			{
+				this.qualifier = qualifier.ToAsn1Object();
+			}
+        }
+
+        /**
+        * Creates a new <code>CommitmentTypeQualifier</code> instance.
+        *
+        * @param as <code>CommitmentTypeQualifier</code> structure
+        * encoded as an Asn1Sequence.
+        */
+        public CommitmentTypeQualifier(
+            Asn1Sequence seq)
+        {
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			commitmentTypeIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+			if (seq.Count > 1)
+            {
+                qualifier = seq[1].ToAsn1Object();
+            }
+        }
+
+		public static CommitmentTypeQualifier GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CommitmentTypeQualifier)
+				return (CommitmentTypeQualifier) obj;
+
+			if (obj is Asn1Sequence)
+				return new CommitmentTypeQualifier((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CommitmentTypeQualifier' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		public DerObjectIdentifier CommitmentTypeIdentifier
+		{
+			get { return commitmentTypeIdentifier; }
+		}
+
+		public Asn1Object Qualifier
+		{
+			get { return qualifier; }
+		}
+
+		/**
+        * Returns a DER-encodable representation of this instance.
+        *
+        * @return a <code>Asn1Object</code> value
+        */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				commitmentTypeIdentifier);
+
+			if (qualifier != null)
+			{
+				v.Add(qualifier);
+			}
+
+			return new DerSequence(v);
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CompleteCertificateRefs.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CompleteCertificateRefs.cs
new file mode 100644
index 0000000..7f1c835
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CompleteCertificateRefs.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.1 Complete Certificate Refs Attribute Definition
+	/// <code>
+	/// CompleteCertificateRefs ::= SEQUENCE OF OtherCertID
+	/// </code>
+	/// </remarks>
+	public class CompleteCertificateRefs
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence otherCertIDs;
+
+		public static CompleteCertificateRefs GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CompleteCertificateRefs)
+				return (CompleteCertificateRefs) obj;
+
+			if (obj is Asn1Sequence)
+				return new CompleteCertificateRefs((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CompleteCertificateRefs' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CompleteCertificateRefs(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+
+			foreach (Asn1Encodable ae in seq)
+			{
+				OtherCertID.GetInstance(ae.ToAsn1Object());
+			}
+
+			this.otherCertIDs = seq;
+		}
+
+		public CompleteCertificateRefs(
+			params OtherCertID[] otherCertIDs)
+		{
+			if (otherCertIDs == null)
+				throw new ArgumentNullException("otherCertIDs");
+
+			this.otherCertIDs = new DerSequence(otherCertIDs);
+		}
+
+		public CompleteCertificateRefs(
+			IEnumerable otherCertIDs)
+		{
+			if (otherCertIDs == null)
+				throw new ArgumentNullException("otherCertIDs");
+			if (!CollectionUtilities.CheckElementsAreOfType(otherCertIDs, typeof(OtherCertID)))
+				throw new ArgumentException("Must contain only 'OtherCertID' objects", "otherCertIDs");
+
+			this.otherCertIDs = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(otherCertIDs));
+		}
+
+		public OtherCertID[] GetOtherCertIDs()
+		{
+			OtherCertID[] result = new OtherCertID[otherCertIDs.Count];
+			for (int i = 0; i < otherCertIDs.Count; ++i)
+			{
+				result[i] = OtherCertID.GetInstance(otherCertIDs[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return otherCertIDs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CompleteRevocationRefs.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CompleteRevocationRefs.cs
new file mode 100644
index 0000000..4e1fb40
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CompleteRevocationRefs.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// CompleteRevocationRefs ::= SEQUENCE OF CrlOcspRef
+	/// </code>
+	/// </remarks>
+	public class CompleteRevocationRefs
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence crlOcspRefs;
+
+		public static CompleteRevocationRefs GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CompleteRevocationRefs)
+				return (CompleteRevocationRefs) obj;
+
+			if (obj is Asn1Sequence)
+				return new CompleteRevocationRefs((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CompleteRevocationRefs' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CompleteRevocationRefs(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+
+			foreach (Asn1Encodable ae in seq)
+			{
+				CrlOcspRef.GetInstance(ae.ToAsn1Object());
+			}
+
+			this.crlOcspRefs = seq;
+		}
+
+		public CompleteRevocationRefs(
+			params CrlOcspRef[] crlOcspRefs)
+		{
+			if (crlOcspRefs == null)
+				throw new ArgumentNullException("crlOcspRefs");
+
+			this.crlOcspRefs = new DerSequence(crlOcspRefs);
+		}
+
+		public CompleteRevocationRefs(
+			IEnumerable crlOcspRefs)
+		{
+			if (crlOcspRefs == null)
+				throw new ArgumentNullException("crlOcspRefs");
+			if (!CollectionUtilities.CheckElementsAreOfType(crlOcspRefs, typeof(CrlOcspRef)))
+				throw new ArgumentException("Must contain only 'CrlOcspRef' objects", "crlOcspRefs");
+
+			this.crlOcspRefs = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(crlOcspRefs));
+		}
+
+		public CrlOcspRef[] GetCrlOcspRefs()
+		{
+			CrlOcspRef[] result = new CrlOcspRef[crlOcspRefs.Count];
+			for (int i = 0; i < crlOcspRefs.Count; ++i)
+			{
+				result[i] = CrlOcspRef.GetInstance(crlOcspRefs[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return crlOcspRefs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CrlIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CrlIdentifier.cs
new file mode 100644
index 0000000..dfff7d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CrlIdentifier.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// CrlIdentifier ::= SEQUENCE 
+	/// {
+	/// 	crlissuer		Name,
+	/// 	crlIssuedTime	UTCTime,
+	/// 	crlNumber		INTEGER OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class CrlIdentifier
+		: Asn1Encodable
+	{
+		private readonly X509Name	crlIssuer;
+		private readonly DerUtcTime	crlIssuedTime;
+		private readonly DerInteger	crlNumber;
+
+		public static CrlIdentifier GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CrlIdentifier)
+				return (CrlIdentifier) obj;
+
+			if (obj is Asn1Sequence)
+				return new CrlIdentifier((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CrlIdentifier' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CrlIdentifier(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 2 || seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.crlIssuer = X509Name.GetInstance(seq[0]);
+			this.crlIssuedTime = DerUtcTime.GetInstance(seq[1]);
+
+			if (seq.Count > 2)
+			{
+				this.crlNumber = DerInteger.GetInstance(seq[2]);
+			}
+		}
+
+		public CrlIdentifier(
+			X509Name	crlIssuer,
+			DateTime	crlIssuedTime)
+			: this(crlIssuer, crlIssuedTime, null)
+		{
+		}
+
+		public CrlIdentifier(
+			X509Name	crlIssuer,
+			DateTime	crlIssuedTime,
+			BigInteger	crlNumber)
+		{
+			if (crlIssuer == null)
+				throw new ArgumentNullException("crlIssuer");
+
+			this.crlIssuer = crlIssuer;
+			this.crlIssuedTime = new DerUtcTime(crlIssuedTime);
+
+			if (crlNumber != null)
+			{
+				this.crlNumber = new DerInteger(crlNumber);
+			}
+		}
+
+		public X509Name CrlIssuer
+		{
+			get { return crlIssuer; }
+		}
+
+		public DateTime CrlIssuedTime
+		{
+			get { return crlIssuedTime.ToAdjustedDateTime(); }
+		}
+
+		public BigInteger CrlNumber
+		{
+			get { return crlNumber == null ? null : crlNumber.Value; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				crlIssuer.ToAsn1Object(), crlIssuedTime);
+
+			if (crlNumber != null)
+			{
+				v.Add(crlNumber);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CrlListID.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CrlListID.cs
new file mode 100644
index 0000000..2aae9b9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CrlListID.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// CRLListID ::= SEQUENCE 
+	/// {
+	///		crls	SEQUENCE OF CrlValidatedID
+	/// }
+	/// </code>
+	/// </remarks>
+	public class CrlListID
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence crls;
+
+		public static CrlListID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CrlListID)
+				return (CrlListID) obj;
+
+			if (obj is Asn1Sequence)
+				return new CrlListID((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CrlListID' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CrlListID(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 1)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.crls = (Asn1Sequence) seq[0].ToAsn1Object();
+
+			foreach (Asn1Encodable ae in this.crls)
+			{
+				CrlValidatedID.GetInstance(ae.ToAsn1Object());
+			}
+		}
+
+		public CrlListID(
+			params CrlValidatedID[] crls)
+		{
+			if (crls == null)
+				throw new ArgumentNullException("crls");
+
+			this.crls = new DerSequence(crls);
+		}
+
+		public CrlListID(
+			IEnumerable crls)
+		{
+			if (crls == null)
+				throw new ArgumentNullException("crls");
+			if (!CollectionUtilities.CheckElementsAreOfType(crls, typeof(CrlValidatedID)))
+				throw new ArgumentException("Must contain only 'CrlValidatedID' objects", "crls");
+
+			this.crls = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(crls));
+		}
+
+		public CrlValidatedID[] GetCrls()
+		{
+			CrlValidatedID[] result = new CrlValidatedID[crls.Count];
+			for (int i = 0; i < crls.Count; ++i)
+			{
+				result[i] = CrlValidatedID.GetInstance(crls[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(crls);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CrlOcspRef.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CrlOcspRef.cs
new file mode 100644
index 0000000..c8e10d5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CrlOcspRef.cs
@@ -0,0 +1,111 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// CrlOcspRef ::= SEQUENCE {
+	///		crlids		[0] CRLListID		OPTIONAL,
+	/// 	ocspids		[1] OcspListID		OPTIONAL,
+	/// 	otherRev	[2] OtherRevRefs	OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class CrlOcspRef
+		: Asn1Encodable
+	{
+		private readonly CrlListID		crlids;
+		private readonly OcspListID		ocspids;
+		private readonly OtherRevRefs	otherRev;
+
+		public static CrlOcspRef GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CrlOcspRef)
+				return (CrlOcspRef) obj;
+
+			if (obj is Asn1Sequence)
+				return new CrlOcspRef((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CrlOcspRef' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CrlOcspRef(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+
+			foreach (Asn1TaggedObject taggedObj in seq)
+			{
+				Asn1Object asn1Obj = taggedObj.GetObject();
+
+				switch (taggedObj.TagNo)
+				{
+					case 0:
+						this.crlids = CrlListID.GetInstance(asn1Obj);
+						break;
+					case 1:
+						this.ocspids = OcspListID.GetInstance(asn1Obj);
+						break;
+					case 2:
+						this.otherRev = OtherRevRefs.GetInstance(asn1Obj);
+						break;
+					default:
+						throw new ArgumentException("Illegal tag in CrlOcspRef", "seq");
+				}
+			}
+		}
+
+		public CrlOcspRef(
+			CrlListID		crlids,
+			OcspListID		ocspids,
+			OtherRevRefs	otherRev)
+		{
+			this.crlids = crlids;
+			this.ocspids = ocspids;
+			this.otherRev = otherRev;
+		}
+
+		public CrlListID CrlIDs
+		{
+			get { return crlids; }
+		}
+
+		public OcspListID OcspIDs
+		{
+			get { return ocspids; }
+		}
+
+		public OtherRevRefs OtherRev
+		{
+			get { return otherRev; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (crlids != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, crlids.ToAsn1Object()));
+			}
+
+			if (ocspids != null)
+			{
+				v.Add(new DerTaggedObject(true, 1, ocspids.ToAsn1Object()));
+			}
+
+			if (otherRev != null)
+			{
+				v.Add(new DerTaggedObject(true, 2, otherRev.ToAsn1Object()));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/CrlValidatedID.cs b/BouncyCastle.AxCrypt/src/asn1/esf/CrlValidatedID.cs
new file mode 100644
index 0000000..165f547
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/CrlValidatedID.cs
@@ -0,0 +1,89 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// CrlValidatedID ::= SEQUENCE {
+	///		crlHash			OtherHash,
+	///		crlIdentifier	CrlIdentifier OPTIONAL}
+	/// </code>
+	/// </remarks>
+	public class CrlValidatedID
+		: Asn1Encodable
+	{
+		private readonly OtherHash		crlHash;
+		private readonly CrlIdentifier	crlIdentifier;
+
+		public static CrlValidatedID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CrlValidatedID)
+				return (CrlValidatedID) obj;
+
+			if (obj is Asn1Sequence)
+				return new CrlValidatedID((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'CrlValidatedID' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private CrlValidatedID(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.crlHash = OtherHash.GetInstance(seq[0].ToAsn1Object());
+
+			if (seq.Count > 1)
+			{
+				this.crlIdentifier = CrlIdentifier.GetInstance(seq[1].ToAsn1Object());
+			}
+		}
+
+		public CrlValidatedID(
+			OtherHash crlHash)
+			: this(crlHash, null)
+		{
+		}
+
+		public CrlValidatedID(
+			OtherHash		crlHash,
+			CrlIdentifier	crlIdentifier)
+		{
+			if (crlHash == null)
+				throw new ArgumentNullException("crlHash");
+
+			this.crlHash = crlHash;
+			this.crlIdentifier = crlIdentifier;
+		}
+
+		public OtherHash CrlHash
+		{
+			get { return crlHash; }
+		}
+
+		public CrlIdentifier CrlIdentifier
+		{
+			get { return crlIdentifier; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(crlHash.ToAsn1Object());
+
+			if (crlIdentifier != null)
+			{
+				v.Add(crlIdentifier.ToAsn1Object());
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/ESFAttributes.cs b/BouncyCastle.AxCrypt/src/asn1/esf/ESFAttributes.cs
new file mode 100644
index 0000000..9401ffb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/ESFAttributes.cs
@@ -0,0 +1,25 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+    public abstract class EsfAttributes
+    {
+        public static readonly DerObjectIdentifier SigPolicyId = PkcsObjectIdentifiers.IdAAEtsSigPolicyID;
+        public static readonly DerObjectIdentifier CommitmentType = PkcsObjectIdentifiers.IdAAEtsCommitmentType;
+        public static readonly DerObjectIdentifier SignerLocation = PkcsObjectIdentifiers.IdAAEtsSignerLocation;
+		public static readonly DerObjectIdentifier SignerAttr = PkcsObjectIdentifiers.IdAAEtsSignerAttr;
+		public static readonly DerObjectIdentifier OtherSigCert = PkcsObjectIdentifiers.IdAAEtsOtherSigCert;
+		public static readonly DerObjectIdentifier ContentTimestamp = PkcsObjectIdentifiers.IdAAEtsContentTimestamp;
+		public static readonly DerObjectIdentifier CertificateRefs = PkcsObjectIdentifiers.IdAAEtsCertificateRefs;
+		public static readonly DerObjectIdentifier RevocationRefs = PkcsObjectIdentifiers.IdAAEtsRevocationRefs;
+		public static readonly DerObjectIdentifier CertValues = PkcsObjectIdentifiers.IdAAEtsCertValues;
+		public static readonly DerObjectIdentifier RevocationValues = PkcsObjectIdentifiers.IdAAEtsRevocationValues;
+		public static readonly DerObjectIdentifier EscTimeStamp = PkcsObjectIdentifiers.IdAAEtsEscTimeStamp;
+		public static readonly DerObjectIdentifier CertCrlTimestamp = PkcsObjectIdentifiers.IdAAEtsCertCrlTimestamp;
+		public static readonly DerObjectIdentifier ArchiveTimestamp = PkcsObjectIdentifiers.IdAAEtsArchiveTimestamp;
+		public static readonly DerObjectIdentifier ArchiveTimestampV2 = new DerObjectIdentifier(PkcsObjectIdentifiers.IdAA + ".48");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OcspIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OcspIdentifier.cs
new file mode 100644
index 0000000..949b682
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OcspIdentifier.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// OcspIdentifier ::= SEQUENCE {
+	///		ocspResponderID		ResponderID,
+	///			-- As in OCSP response data
+	///		producedAt			GeneralizedTime
+	///			-- As in OCSP response data
+	/// }
+	/// </code>
+	/// </remarks>
+	public class OcspIdentifier
+		: Asn1Encodable
+	{
+		private readonly ResponderID		ocspResponderID;
+		private readonly DerGeneralizedTime	producedAt;
+
+		public static OcspIdentifier GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspIdentifier)
+				return (OcspIdentifier) obj;
+
+			if (obj is Asn1Sequence)
+				return new OcspIdentifier((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OcspIdentifier' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OcspIdentifier(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.ocspResponderID = ResponderID.GetInstance(seq[0].ToAsn1Object());
+			this.producedAt = (DerGeneralizedTime) seq[1].ToAsn1Object();
+		}
+
+		public OcspIdentifier(
+			ResponderID	ocspResponderID,
+			DateTime	producedAt)
+		{
+			if (ocspResponderID == null)
+				throw new ArgumentNullException();
+
+			this.ocspResponderID = ocspResponderID;
+			this.producedAt = new DerGeneralizedTime(producedAt);
+		}
+
+		public ResponderID OcspResponderID
+		{
+			get { return ocspResponderID; }
+		}
+
+		public DateTime ProducedAt
+		{
+			get { return producedAt.ToDateTime(); }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(ocspResponderID, producedAt);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OcspListID.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OcspListID.cs
new file mode 100644
index 0000000..1f3f3a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OcspListID.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// OcspListID ::=  SEQUENCE {
+	///		ocspResponses	SEQUENCE OF OcspResponsesID
+	/// }
+	/// </code>
+	/// </remarks>
+	public class OcspListID
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence ocspResponses;
+
+		public static OcspListID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspListID)
+				return (OcspListID) obj;
+
+			if (obj is Asn1Sequence)
+				return new OcspListID((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OcspListID' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OcspListID(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 1)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.ocspResponses = (Asn1Sequence) seq[0].ToAsn1Object();
+
+			foreach (Asn1Encodable ae in this.ocspResponses)
+			{
+				OcspResponsesID.GetInstance(ae.ToAsn1Object());
+			}
+		}
+
+		public OcspListID(
+			params OcspResponsesID[] ocspResponses)
+		{
+			if (ocspResponses == null)
+				throw new ArgumentNullException("ocspResponses");
+
+			this.ocspResponses = new DerSequence(ocspResponses);
+		}
+
+		public OcspListID(
+			IEnumerable ocspResponses)
+		{
+			if (ocspResponses == null)
+				throw new ArgumentNullException("ocspResponses");
+			if (!CollectionUtilities.CheckElementsAreOfType(ocspResponses, typeof(OcspResponsesID)))
+				throw new ArgumentException("Must contain only 'OcspResponsesID' objects", "ocspResponses");
+
+			this.ocspResponses = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(ocspResponses));
+		}
+
+		public OcspResponsesID[] GetOcspResponses()
+		{
+			OcspResponsesID[] result = new OcspResponsesID[ocspResponses.Count];
+			for (int i = 0; i < ocspResponses.Count; ++i)
+			{
+				result[i] = OcspResponsesID.GetInstance(ocspResponses[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(ocspResponses);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OcspResponsesID.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OcspResponsesID.cs
new file mode 100644
index 0000000..e09508a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OcspResponsesID.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// OcspResponsesID ::= SEQUENCE {
+	///		ocspIdentifier	OcspIdentifier,
+	///		ocspRepHash		OtherHash OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class OcspResponsesID
+		: Asn1Encodable
+	{
+		private readonly OcspIdentifier	ocspIdentifier;
+		private readonly OtherHash		ocspRepHash;
+
+		public static OcspResponsesID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspResponsesID)
+				return (OcspResponsesID) obj;
+
+			if (obj is Asn1Sequence)
+				return new OcspResponsesID((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OcspResponsesID' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OcspResponsesID(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.ocspIdentifier = OcspIdentifier.GetInstance(seq[0].ToAsn1Object());
+
+			if (seq.Count > 1)
+			{
+				this.ocspRepHash = OtherHash.GetInstance(seq[1].ToAsn1Object());
+			}
+		}
+
+		public OcspResponsesID(
+			OcspIdentifier ocspIdentifier)
+			: this(ocspIdentifier, null)
+		{
+		}
+
+		public OcspResponsesID(
+			OcspIdentifier	ocspIdentifier,
+			OtherHash		ocspRepHash)
+		{
+			if (ocspIdentifier == null)
+				throw new ArgumentNullException("ocspIdentifier");
+
+			this.ocspIdentifier = ocspIdentifier;
+			this.ocspRepHash = ocspRepHash;
+		}
+
+		public OcspIdentifier OcspIdentifier
+		{
+			get { return ocspIdentifier; }
+		}
+
+		public OtherHash OcspRepHash
+		{
+			get { return ocspRepHash; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				ocspIdentifier.ToAsn1Object());
+
+			if (ocspRepHash != null)
+			{
+				v.Add(ocspRepHash.ToAsn1Object());
+			}
+
+			return new DerSequence(v);
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherCertID.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherCertID.cs
new file mode 100644
index 0000000..6d12555
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherCertID.cs
@@ -0,0 +1,93 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// OtherCertID ::= SEQUENCE {
+	/// 	otherCertHash	OtherHash,
+	/// 	issuerSerial	IssuerSerial OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class OtherCertID
+		: Asn1Encodable
+	{
+		private readonly OtherHash		otherCertHash;
+		private readonly IssuerSerial	issuerSerial;
+
+		public static OtherCertID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherCertID)
+				return (OtherCertID) obj;
+
+			if (obj is Asn1Sequence)
+				return new OtherCertID((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OtherCertID' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OtherCertID(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.otherCertHash = OtherHash.GetInstance(seq[0].ToAsn1Object());
+
+			if (seq.Count > 1)
+			{
+				this.issuerSerial = IssuerSerial.GetInstance(seq[1].ToAsn1Object());
+			}
+		}
+
+		public OtherCertID(
+			OtherHash otherCertHash)
+			: this(otherCertHash, null)
+		{
+		}
+
+		public OtherCertID(
+			OtherHash		otherCertHash,
+			IssuerSerial	issuerSerial)
+		{
+			if (otherCertHash == null)
+				throw new ArgumentNullException("otherCertHash");
+
+			this.otherCertHash = otherCertHash;
+			this.issuerSerial = issuerSerial;
+		}
+
+		public OtherHash OtherCertHash
+		{
+			get { return otherCertHash; }
+		}
+
+		public IssuerSerial IssuerSerial
+		{
+			get { return issuerSerial; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				otherCertHash.ToAsn1Object());
+
+			if (issuerSerial != null)
+			{
+				v.Add(issuerSerial.ToAsn1Object());
+			}
+
+			return new DerSequence(v);
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherHash.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherHash.cs
new file mode 100644
index 0000000..2ee1624
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherHash.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// OtherHash ::= CHOICE {
+	///		sha1Hash	OtherHashValue, -- This contains a SHA-1 hash
+	/// 	otherHash	OtherHashAlgAndValue
+	///	}
+	///	
+	///	OtherHashValue ::= OCTET STRING
+	/// </code>
+	/// </remarks>
+	public class OtherHash
+		: Asn1Encodable, IAsn1Choice
+	{
+		private readonly Asn1OctetString		sha1Hash;
+		private readonly OtherHashAlgAndValue	otherHash;
+
+		public static OtherHash GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherHash)
+				return (OtherHash) obj;
+
+			if (obj is Asn1OctetString)
+				return new OtherHash((Asn1OctetString) obj);
+
+			return new OtherHash(
+				OtherHashAlgAndValue.GetInstance(obj));
+		}
+
+		public OtherHash(
+			byte[] sha1Hash)
+		{
+			if (sha1Hash == null)
+				throw new ArgumentNullException("sha1Hash");
+
+			this.sha1Hash = new DerOctetString(sha1Hash);
+		}
+
+		public OtherHash(
+			Asn1OctetString sha1Hash)
+		{
+			if (sha1Hash == null)
+				throw new ArgumentNullException("sha1Hash");
+
+			this.sha1Hash = sha1Hash;
+		}
+
+		public OtherHash(
+			OtherHashAlgAndValue otherHash)
+		{
+			if (otherHash == null)
+				throw new ArgumentNullException("otherHash");
+
+			this.otherHash = otherHash;
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get
+			{
+				return otherHash == null
+					?	new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
+					:	otherHash.HashAlgorithm;
+			}
+		}
+
+		public byte[] GetHashValue()
+		{
+			return otherHash == null
+				?	sha1Hash.GetOctets()
+				:	otherHash.GetHashValue();
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return otherHash == null
+				?	sha1Hash
+				:	otherHash.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherHashAlgAndValue.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherHashAlgAndValue.cs
new file mode 100644
index 0000000..b6bd4f4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherHashAlgAndValue.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <summary>
+	/// Summary description for OtherHashAlgAndValue.
+	/// </summary>
+	/// <remarks>
+	/// <code>
+	/// OtherHashAlgAndValue ::= SEQUENCE {
+	///		hashAlgorithm	AlgorithmIdentifier,
+	/// 	hashValue		OtherHashValue
+	/// }
+	/// 
+	/// OtherHashValue ::= OCTET STRING
+	/// </code>
+	/// </remarks>
+	public class OtherHashAlgAndValue
+		: Asn1Encodable
+	{
+		private readonly AlgorithmIdentifier	hashAlgorithm;
+		private readonly Asn1OctetString		hashValue;
+
+		public static OtherHashAlgAndValue GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherHashAlgAndValue)
+				return (OtherHashAlgAndValue) obj;
+
+			if (obj is Asn1Sequence)
+				return new OtherHashAlgAndValue((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OtherHashAlgAndValue' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OtherHashAlgAndValue(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0].ToAsn1Object());
+			this.hashValue = (Asn1OctetString) seq[1].ToAsn1Object();
+		}
+
+		public OtherHashAlgAndValue(
+			AlgorithmIdentifier	hashAlgorithm,
+			byte[]				hashValue)
+		{
+			if (hashAlgorithm == null)
+				throw new ArgumentNullException("hashAlgorithm");
+			if (hashValue == null)
+				throw new ArgumentNullException("hashValue");
+
+			this.hashAlgorithm = hashAlgorithm;
+			this.hashValue = new DerOctetString(hashValue);
+		}
+
+		public OtherHashAlgAndValue(
+			AlgorithmIdentifier	hashAlgorithm,
+			Asn1OctetString		hashValue)
+		{
+			if (hashAlgorithm == null)
+				throw new ArgumentNullException("hashAlgorithm");
+			if (hashValue == null)
+				throw new ArgumentNullException("hashValue");
+
+			this.hashAlgorithm = hashAlgorithm;
+			this.hashValue = hashValue;
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public byte[] GetHashValue()
+		{
+			return hashValue.GetOctets();
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(hashAlgorithm, hashValue);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevRefs.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevRefs.cs
new file mode 100644
index 0000000..56713e3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevRefs.cs
@@ -0,0 +1,78 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.2.2 Complete Revocation Refs Attribute Definition
+	/// <code>
+	/// OtherRevRefs ::= SEQUENCE 
+	/// {
+	///		otherRevRefType      OtherRevRefType,
+	///		otherRevRefs         ANY DEFINED BY otherRevRefType
+	/// }
+	///
+	/// OtherRevRefType ::= OBJECT IDENTIFIER
+	/// </code>
+	/// </remarks>
+	public class OtherRevRefs
+		: Asn1Encodable
+	{
+		private readonly DerObjectIdentifier	otherRevRefType;
+		private readonly Asn1Object				otherRevRefs;
+
+		public static OtherRevRefs GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherRevRefs)
+				return (OtherRevRefs) obj;
+
+			if (obj is Asn1Sequence)
+				return new OtherRevRefs((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OtherRevRefs' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OtherRevRefs(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.otherRevRefType = (DerObjectIdentifier) seq[0].ToAsn1Object();
+			this.otherRevRefs = seq[1].ToAsn1Object();
+		}
+
+		public OtherRevRefs(
+			DerObjectIdentifier	otherRevRefType,
+			Asn1Encodable		otherRevRefs)
+		{
+			if (otherRevRefType == null)
+				throw new ArgumentNullException("otherRevRefType");
+			if (otherRevRefs == null)
+				throw new ArgumentNullException("otherRevRefs");
+
+			this.otherRevRefType = otherRevRefType;
+			this.otherRevRefs = otherRevRefs.ToAsn1Object();
+		}
+
+		public DerObjectIdentifier OtherRevRefType
+		{
+			get { return otherRevRefType; }
+		}
+
+		public Asn1Object OtherRevRefsObject
+		{
+			get { return otherRevRefs; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(otherRevRefType, otherRevRefs);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevVals.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevVals.cs
new file mode 100644
index 0000000..b88a1a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherRevVals.cs
@@ -0,0 +1,78 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 3126: 4.3.2 Revocation Values Attribute Definition
+	/// <code>
+	/// OtherRevVals ::= SEQUENCE 
+	/// {
+	///		otherRevValType      OtherRevValType,
+	///		otherRevVals         ANY DEFINED BY otherRevValType
+	/// }
+	///
+	/// OtherRevValType ::= OBJECT IDENTIFIER
+	/// </code>
+	/// </remarks>
+	public class OtherRevVals
+		: Asn1Encodable
+	{
+		private readonly DerObjectIdentifier	otherRevValType;
+		private readonly Asn1Object				otherRevVals;
+
+		public static OtherRevVals GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherRevVals)
+				return (OtherRevVals) obj;
+
+			if (obj is Asn1Sequence)
+				return new OtherRevVals((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OtherRevVals' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OtherRevVals(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.otherRevValType = (DerObjectIdentifier) seq[0].ToAsn1Object();
+			this.otherRevVals = seq[1].ToAsn1Object();
+		}
+
+		public OtherRevVals(
+			DerObjectIdentifier	otherRevValType,
+			Asn1Encodable		otherRevVals)
+		{
+			if (otherRevValType == null)
+				throw new ArgumentNullException("otherRevValType");
+			if (otherRevVals == null)
+				throw new ArgumentNullException("otherRevVals");
+
+			this.otherRevValType = otherRevValType;
+			this.otherRevVals = otherRevVals.ToAsn1Object();
+		}
+
+		public DerObjectIdentifier OtherRevValType
+		{
+			get { return otherRevValType; }
+		}
+
+		public Asn1Object OtherRevValsObject
+		{
+			get { return otherRevVals; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(otherRevValType, otherRevVals);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/OtherSigningCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/esf/OtherSigningCertificate.cs
new file mode 100644
index 0000000..90e385a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/OtherSigningCertificate.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// OtherSigningCertificate ::= SEQUENCE {
+	/// 	certs		SEQUENCE OF OtherCertID,
+	/// 	policies	SEQUENCE OF PolicyInformation OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class OtherSigningCertificate
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence	certs;
+		private readonly Asn1Sequence	policies;
+
+		public static OtherSigningCertificate GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OtherSigningCertificate)
+				return (OtherSigningCertificate) obj;
+
+			if (obj is Asn1Sequence)
+				return new OtherSigningCertificate((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'OtherSigningCertificate' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private OtherSigningCertificate(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 1 || seq.Count > 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object());
+
+			if (seq.Count > 1)
+			{
+				this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object());
+			}
+		}
+
+		public OtherSigningCertificate(
+			params OtherCertID[] certs)
+			: this(certs, null)
+		{
+		}
+
+		public OtherSigningCertificate(
+			OtherCertID[]				certs,
+			params PolicyInformation[]	policies)
+		{
+			if (certs == null)
+				throw new ArgumentNullException("certs");
+
+			this.certs = new DerSequence(certs);
+
+			if (policies != null)
+			{
+				this.policies = new DerSequence(policies);
+			}
+		}
+
+		public OtherSigningCertificate(
+			IEnumerable certs)
+			: this(certs, null)
+		{
+		}
+
+		public OtherSigningCertificate(
+			IEnumerable	certs,
+			IEnumerable	policies)
+		{
+			if (certs == null)
+				throw new ArgumentNullException("certs");
+			if (!CollectionUtilities.CheckElementsAreOfType(certs, typeof(OtherCertID)))
+				throw new ArgumentException("Must contain only 'OtherCertID' objects", "certs");
+
+			this.certs = new DerSequence(
+				Asn1EncodableVector.FromEnumerable(certs));
+
+			if (policies != null)
+			{
+				if (!CollectionUtilities.CheckElementsAreOfType(policies, typeof(PolicyInformation)))
+					throw new ArgumentException("Must contain only 'PolicyInformation' objects", "policies");
+
+				this.policies = new DerSequence(
+					Asn1EncodableVector.FromEnumerable(policies));
+			}
+		}
+
+		public OtherCertID[] GetCerts()
+		{
+			OtherCertID[] cs = new OtherCertID[certs.Count];
+			for (int i = 0; i < certs.Count; ++i)
+			{
+				cs[i] = OtherCertID.GetInstance(certs[i].ToAsn1Object());
+			}
+			return cs;
+		}
+
+		public PolicyInformation[] GetPolicies()
+		{
+			if (policies == null)
+				return null;
+
+			PolicyInformation[] ps = new PolicyInformation[policies.Count];
+			for (int i = 0; i < policies.Count; ++i)
+			{
+				ps[i] = PolicyInformation.GetInstance(policies[i].ToAsn1Object());
+			}
+			return ps;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+			if (policies != null)
+			{
+				v.Add(policies);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/RevocationValues.cs b/BouncyCastle.AxCrypt/src/asn1/esf/RevocationValues.cs
new file mode 100644
index 0000000..a7b47b4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/RevocationValues.cs
@@ -0,0 +1,165 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// RFC 5126: 6.3.4.  revocation-values Attribute Definition
+	/// <code>
+	/// RevocationValues ::=  SEQUENCE {
+	///		crlVals			[0] SEQUENCE OF CertificateList     OPTIONAL,
+	///		ocspVals		[1] SEQUENCE OF BasicOCSPResponse   OPTIONAL,
+	///		otherRevVals	[2] OtherRevVals OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class RevocationValues
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence	crlVals;
+		private readonly Asn1Sequence	ocspVals;
+		private readonly OtherRevVals	otherRevVals;
+
+		public static RevocationValues GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RevocationValues)
+				return (RevocationValues) obj;
+
+			return new RevocationValues(Asn1Sequence.GetInstance(obj));
+		}
+
+		private RevocationValues(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			foreach (Asn1TaggedObject taggedObj in seq)
+			{
+				Asn1Object asn1Obj = taggedObj.GetObject();
+				switch (taggedObj.TagNo)
+				{
+					case 0:
+						Asn1Sequence crlValsSeq = (Asn1Sequence) asn1Obj;
+						foreach (Asn1Encodable ae in crlValsSeq)
+						{
+							CertificateList.GetInstance(ae.ToAsn1Object());
+						}
+						this.crlVals = crlValsSeq;
+						break;
+					case 1:
+						Asn1Sequence ocspValsSeq = (Asn1Sequence) asn1Obj;
+						foreach (Asn1Encodable ae in ocspValsSeq)
+						{
+							BasicOcspResponse.GetInstance(ae.ToAsn1Object());
+						}
+						this.ocspVals = ocspValsSeq;
+						break;
+					case 2:
+						this.otherRevVals = OtherRevVals.GetInstance(asn1Obj);
+						break;
+					default:
+						throw new ArgumentException("Illegal tag in RevocationValues", "seq");
+				}
+			}
+		}
+
+		public RevocationValues(
+			CertificateList[]	crlVals,
+			BasicOcspResponse[]	ocspVals,
+			OtherRevVals		otherRevVals)
+		{
+			if (crlVals != null)
+			{
+				this.crlVals = new DerSequence(crlVals);
+			}
+
+			if (ocspVals != null)
+			{
+				this.ocspVals = new DerSequence(ocspVals);
+			}
+
+			this.otherRevVals = otherRevVals;
+		}
+
+		public RevocationValues(
+			IEnumerable			crlVals,
+			IEnumerable			ocspVals,
+			OtherRevVals		otherRevVals)
+		{
+			if (crlVals != null)
+			{
+				if (!CollectionUtilities.CheckElementsAreOfType(crlVals, typeof(CertificateList)))
+					throw new ArgumentException("Must contain only 'CertificateList' objects", "crlVals");
+
+				this.crlVals = new DerSequence(
+					Asn1EncodableVector.FromEnumerable(crlVals));
+			}
+
+			if (ocspVals != null)
+			{
+				if (!CollectionUtilities.CheckElementsAreOfType(ocspVals, typeof(BasicOcspResponse)))
+					throw new ArgumentException("Must contain only 'BasicOcspResponse' objects", "ocspVals");
+
+				this.ocspVals = new DerSequence(
+					Asn1EncodableVector.FromEnumerable(ocspVals));
+			}
+
+			this.otherRevVals = otherRevVals;
+		}
+
+		public CertificateList[] GetCrlVals()
+		{
+			CertificateList[] result = new CertificateList[crlVals.Count];
+			for (int i = 0; i < crlVals.Count; ++i)
+			{
+				result[i] = CertificateList.GetInstance(crlVals[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public BasicOcspResponse[] GetOcspVals()
+		{
+			BasicOcspResponse[] result = new BasicOcspResponse[ocspVals.Count];
+			for (int i = 0; i < ocspVals.Count; ++i)
+			{
+				result[i] = BasicOcspResponse.GetInstance(ocspVals[i].ToAsn1Object());
+			}
+			return result;
+		}
+
+		public OtherRevVals OtherRevVals
+		{
+			get { return otherRevVals; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (crlVals != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, crlVals));
+			}
+
+			if (ocspVals != null)
+			{
+				v.Add(new DerTaggedObject(true, 1, ocspVals));
+			}
+
+			if (otherRevVals != null)
+			{
+				v.Add(new DerTaggedObject(true, 2, otherRevVals.ToAsn1Object()));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/SigPolicyQualifierInfo.cs b/BouncyCastle.AxCrypt/src/asn1/esf/SigPolicyQualifierInfo.cs
new file mode 100644
index 0000000..2d36bc7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/SigPolicyQualifierInfo.cs
@@ -0,0 +1,71 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// SigPolicyQualifierInfo ::= SEQUENCE {
+    ///		sigPolicyQualifierId  SigPolicyQualifierId,
+	///		sigQualifier          ANY DEFINED BY sigPolicyQualifierId
+	/// }
+	/// 
+	/// SigPolicyQualifierId ::= OBJECT IDENTIFIER
+	/// </code>
+	/// </remarks>
+	public class SigPolicyQualifierInfo
+		: Asn1Encodable
+	{
+		private readonly DerObjectIdentifier	sigPolicyQualifierId;
+		private readonly Asn1Object				sigQualifier;
+
+		public static SigPolicyQualifierInfo GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SigPolicyQualifierInfo)
+				return (SigPolicyQualifierInfo) obj;
+
+			if (obj is Asn1Sequence)
+				return new SigPolicyQualifierInfo((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'SigPolicyQualifierInfo' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private SigPolicyQualifierInfo(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.sigPolicyQualifierId = (DerObjectIdentifier) seq[0].ToAsn1Object();
+			this.sigQualifier = seq[1].ToAsn1Object();
+		}
+
+		public SigPolicyQualifierInfo(
+			DerObjectIdentifier	sigPolicyQualifierId,
+			Asn1Encodable		sigQualifier)
+		{
+			this.sigPolicyQualifierId = sigPolicyQualifierId;
+			this.sigQualifier = sigQualifier.ToAsn1Object();
+		}
+
+		public DerObjectIdentifier SigPolicyQualifierId
+		{
+			get { return sigPolicyQualifierId; }
+		}
+
+		public Asn1Object SigQualifier
+		{
+			get { return sigQualifier; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(sigPolicyQualifierId, sigQualifier);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyId.cs b/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyId.cs
new file mode 100644
index 0000000..545be2c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyId.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// SignaturePolicyId ::= SEQUENCE {
+	/// 	sigPolicyIdentifier		SigPolicyId,
+	/// 	sigPolicyHash			SigPolicyHash,
+	/// 	sigPolicyQualifiers		SEQUENCE SIZE (1..MAX) OF SigPolicyQualifierInfo OPTIONAL
+	/// }
+	/// 
+	/// SigPolicyId ::= OBJECT IDENTIFIER
+	/// 
+	/// SigPolicyHash ::= OtherHashAlgAndValue
+	/// </code>
+	/// </remarks>
+	public class SignaturePolicyId
+		: Asn1Encodable
+	{
+		private readonly DerObjectIdentifier	sigPolicyIdentifier;
+		private readonly OtherHashAlgAndValue	sigPolicyHash;
+		private readonly Asn1Sequence			sigPolicyQualifiers;
+
+		public static SignaturePolicyId GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SignaturePolicyId)
+				return (SignaturePolicyId) obj;
+
+			if (obj is Asn1Sequence)
+				return new SignaturePolicyId((Asn1Sequence) obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'SignaturePolicyId' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		private SignaturePolicyId(
+			Asn1Sequence seq)
+		{
+			if (seq == null)
+				throw new ArgumentNullException("seq");
+			if (seq.Count < 2 || seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.sigPolicyIdentifier = (DerObjectIdentifier) seq[0].ToAsn1Object();
+			this.sigPolicyHash = OtherHashAlgAndValue.GetInstance(seq[1].ToAsn1Object());
+
+			if (seq.Count > 2)
+			{
+				this.sigPolicyQualifiers = (Asn1Sequence) seq[2].ToAsn1Object();
+			}
+		}
+
+		public SignaturePolicyId(
+			DerObjectIdentifier		sigPolicyIdentifier,
+			OtherHashAlgAndValue	sigPolicyHash)
+			: this(sigPolicyIdentifier, sigPolicyHash, null)
+		{
+		}
+
+		public SignaturePolicyId(
+			DerObjectIdentifier				sigPolicyIdentifier,
+			OtherHashAlgAndValue			sigPolicyHash,
+			params SigPolicyQualifierInfo[]	sigPolicyQualifiers)
+		{
+			if (sigPolicyIdentifier == null)
+				throw new ArgumentNullException("sigPolicyIdentifier");
+			if (sigPolicyHash == null)
+				throw new ArgumentNullException("sigPolicyHash");
+
+			this.sigPolicyIdentifier = sigPolicyIdentifier;
+			this.sigPolicyHash = sigPolicyHash;
+
+			if (sigPolicyQualifiers != null)
+			{
+				this.sigPolicyQualifiers = new DerSequence(sigPolicyQualifiers);
+			}
+		}
+
+		public SignaturePolicyId(
+			DerObjectIdentifier		sigPolicyIdentifier,
+			OtherHashAlgAndValue	sigPolicyHash,
+			IEnumerable				sigPolicyQualifiers)
+		{
+			if (sigPolicyIdentifier == null)
+				throw new ArgumentNullException("sigPolicyIdentifier");
+			if (sigPolicyHash == null)
+				throw new ArgumentNullException("sigPolicyHash");
+
+			this.sigPolicyIdentifier = sigPolicyIdentifier;
+			this.sigPolicyHash = sigPolicyHash;
+
+			if (sigPolicyQualifiers != null)
+			{
+				if (!CollectionUtilities.CheckElementsAreOfType(sigPolicyQualifiers, typeof(SigPolicyQualifierInfo)))
+					throw new ArgumentException("Must contain only 'SigPolicyQualifierInfo' objects", "sigPolicyQualifiers");
+
+				this.sigPolicyQualifiers = new DerSequence(
+					Asn1EncodableVector.FromEnumerable(sigPolicyQualifiers));
+			}
+		}
+
+		public DerObjectIdentifier SigPolicyIdentifier
+		{
+			get { return sigPolicyIdentifier; }
+		}
+
+		public OtherHashAlgAndValue SigPolicyHash
+		{
+			get { return sigPolicyHash; }
+		}
+
+		public SigPolicyQualifierInfo[] GetSigPolicyQualifiers()
+		{
+			if (sigPolicyQualifiers == null)
+				return null;
+
+			SigPolicyQualifierInfo[] infos = new SigPolicyQualifierInfo[sigPolicyQualifiers.Count];
+			for (int i = 0; i < sigPolicyQualifiers.Count; ++i)
+			{
+				infos[i] = SigPolicyQualifierInfo.GetInstance(sigPolicyQualifiers[i]);
+			}
+			return infos;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				sigPolicyIdentifier, sigPolicyHash.ToAsn1Object());
+
+			if (sigPolicyQualifiers != null)
+			{
+				v.Add(sigPolicyQualifiers.ToAsn1Object());
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyIdentifier.cs
new file mode 100644
index 0000000..3a639f4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/SignaturePolicyIdentifier.cs
@@ -0,0 +1,64 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/// <remarks>
+	/// <code>
+	/// SignaturePolicyIdentifier ::= CHOICE {
+	///		SignaturePolicyId		SignaturePolicyId,
+	///		SignaturePolicyImplied	SignaturePolicyImplied
+	/// }
+	/// 
+	/// SignaturePolicyImplied ::= NULL
+	/// </code>
+	/// </remarks>
+	public class SignaturePolicyIdentifier
+		: Asn1Encodable, IAsn1Choice
+	{
+		private readonly SignaturePolicyId sigPolicy;
+
+		public static SignaturePolicyIdentifier GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SignaturePolicyIdentifier)
+				return (SignaturePolicyIdentifier) obj;
+
+			if (obj is SignaturePolicyId)
+				return new SignaturePolicyIdentifier((SignaturePolicyId) obj);
+
+			if (obj is Asn1Null)
+				return new SignaturePolicyIdentifier();
+
+			throw new ArgumentException(
+				"Unknown object in 'SignaturePolicyIdentifier' factory: "
+					+ obj.GetType().Name,
+				"obj");
+		}
+
+		public SignaturePolicyIdentifier()
+		{
+			this.sigPolicy = null;
+		}
+
+		public SignaturePolicyIdentifier(
+			SignaturePolicyId signaturePolicyId)
+		{
+			if (signaturePolicyId == null)
+				throw new ArgumentNullException("signaturePolicyId");
+
+			this.sigPolicy = signaturePolicyId;
+		}
+
+		public SignaturePolicyId SignaturePolicyId
+		{
+			get { return sigPolicy; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return sigPolicy == null
+				?	DerNull.Instance
+				:	sigPolicy.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/SignerAttribute.cs b/BouncyCastle.AxCrypt/src/asn1/esf/SignerAttribute.cs
new file mode 100644
index 0000000..ddee53c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/SignerAttribute.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	public class SignerAttribute
+		: Asn1Encodable
+	{
+		private Asn1Sequence			claimedAttributes;
+		private AttributeCertificate	certifiedAttributes;
+
+		public static SignerAttribute GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SignerAttribute)
+				return (SignerAttribute) obj;
+
+			if (obj is Asn1Sequence)
+				return new SignerAttribute(obj);
+
+			throw new ArgumentException(
+				"Unknown object in 'SignerAttribute' factory: "
+				+ obj.GetType().Name,
+				"obj");
+		}
+
+		private SignerAttribute(
+			object obj)
+		{
+			Asn1Sequence seq = (Asn1Sequence) obj;
+			DerTaggedObject taggedObject = (DerTaggedObject) seq[0];
+			if (taggedObject.TagNo == 0)
+			{
+				claimedAttributes = Asn1Sequence.GetInstance(taggedObject, true);
+			}
+			else if (taggedObject.TagNo == 1)
+			{
+				certifiedAttributes = AttributeCertificate.GetInstance(taggedObject);
+			}
+			else
+			{
+				throw new ArgumentException("illegal tag.", "obj");
+			}
+		}
+
+		public SignerAttribute(
+			Asn1Sequence claimedAttributes)
+		{
+			this.claimedAttributes = claimedAttributes;
+		}
+
+		public SignerAttribute(
+			AttributeCertificate certifiedAttributes)
+		{
+			this.certifiedAttributes = certifiedAttributes;
+		}
+
+		public virtual Asn1Sequence ClaimedAttributes
+		{
+			get { return claimedAttributes; }
+		}
+
+		public virtual AttributeCertificate CertifiedAttributes
+		{
+			get { return certifiedAttributes; }
+		}
+
+		/**
+		*
+		* <pre>
+		*  SignerAttribute ::= SEQUENCE OF CHOICE {
+		*      claimedAttributes   [0] ClaimedAttributes,
+		*      certifiedAttributes [1] CertifiedAttributes }
+		*
+		*  ClaimedAttributes ::= SEQUENCE OF Attribute
+		*  CertifiedAttributes ::= AttributeCertificate -- as defined in RFC 3281: see clause 4.1.
+		* </pre>
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (claimedAttributes != null)
+			{
+				v.Add(new DerTaggedObject(0, claimedAttributes));
+			}
+			else
+			{
+				v.Add(new DerTaggedObject(1, certifiedAttributes));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/esf/SignerLocation.cs b/BouncyCastle.AxCrypt/src/asn1/esf/SignerLocation.cs
new file mode 100644
index 0000000..d2cef51
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/esf/SignerLocation.cs
@@ -0,0 +1,144 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Esf
+{
+	/**
+	* Signer-Location attribute (RFC3126).
+	*
+	* <pre>
+	*   SignerLocation ::= SEQUENCE {
+	*       countryName        [0] DirectoryString OPTIONAL,
+	*       localityName       [1] DirectoryString OPTIONAL,
+	*       postalAddress      [2] PostalAddress OPTIONAL }
+	*
+	*   PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+	* </pre>
+	*/
+	public class SignerLocation
+		: Asn1Encodable
+	{
+		// TODO Should these be using DirectoryString?
+		private DerUtf8String	countryName;
+		private DerUtf8String	localityName;
+		private Asn1Sequence	postalAddress;
+
+		public SignerLocation(
+			Asn1Sequence seq)
+		{
+			foreach (Asn1TaggedObject obj in seq)
+			{
+				switch (obj.TagNo)
+				{
+					case 0:
+						this.countryName = DerUtf8String.GetInstance(obj, true);
+						break;
+					case 1:
+						this.localityName = DerUtf8String.GetInstance(obj, true);
+						break;
+					case 2:
+						bool isExplicit = obj.IsExplicit();	// handle erroneous implicitly tagged sequences
+						this.postalAddress = Asn1Sequence.GetInstance(obj, isExplicit);
+						if (postalAddress != null && postalAddress.Count > 6)
+							throw new ArgumentException("postal address must contain less than 6 strings");
+						break;
+					default:
+						throw new ArgumentException("illegal tag");
+				}
+			}
+		}
+
+		public SignerLocation(
+			DerUtf8String	countryName,
+			DerUtf8String	localityName,
+			Asn1Sequence	postalAddress)
+		{
+			if (postalAddress != null && postalAddress.Count > 6)
+			{
+				throw new ArgumentException("postal address must contain less than 6 strings");
+			}
+
+			if (countryName != null)
+			{
+				this.countryName = DerUtf8String.GetInstance(countryName.ToAsn1Object());
+			}
+
+			if (localityName != null)
+			{
+				this.localityName = DerUtf8String.GetInstance(localityName.ToAsn1Object());
+			}
+
+			if (postalAddress != null)
+			{
+				this.postalAddress = (Asn1Sequence) postalAddress.ToAsn1Object();
+			}
+		}
+
+		public static SignerLocation GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SignerLocation)
+			{
+				return (SignerLocation) obj;
+			}
+
+			return new SignerLocation(Asn1Sequence.GetInstance(obj));
+		}
+
+		public DerUtf8String CountryName
+		{
+			get { return countryName; }
+		}
+
+		public DerUtf8String LocalityName
+		{
+			get { return localityName; }
+		}
+
+		public Asn1Sequence PostalAddress
+		{
+			get { return postalAddress; }
+		}
+
+		/**
+		* <pre>
+		*   SignerLocation ::= SEQUENCE {
+		*       countryName        [0] DirectoryString OPTIONAL,
+		*       localityName       [1] DirectoryString OPTIONAL,
+		*       postalAddress      [2] PostalAddress OPTIONAL }
+		*
+		*   PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
+		*
+		*   DirectoryString ::= CHOICE {
+		*         teletexString           TeletexString (SIZE (1..MAX)),
+		*         printableString         PrintableString (SIZE (1..MAX)),
+		*         universalString         UniversalString (SIZE (1..MAX)),
+		*         utf8String              UTF8String (SIZE (1.. MAX)),
+		*         bmpString               BMPString (SIZE (1..MAX)) }
+		* </pre>
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (countryName != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, countryName));
+			}
+
+			if (localityName != null)
+			{
+				v.Add(new DerTaggedObject(true, 1, localityName));
+			}
+
+			if (postalAddress != null)
+			{
+				v.Add(new DerTaggedObject(true, 2, postalAddress));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/ContentHints.cs b/BouncyCastle.AxCrypt/src/asn1/ess/ContentHints.cs
new file mode 100644
index 0000000..a430fea
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/ContentHints.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	public class ContentHints
+		: Asn1Encodable
+	{
+		private readonly DerUtf8String contentDescription;
+		private readonly DerObjectIdentifier contentType;
+
+		public static ContentHints GetInstance(
+			object o)
+		{
+			if (o == null || o is ContentHints)
+			{
+				return (ContentHints)o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new ContentHints((Asn1Sequence)o);
+			}
+
+			throw new ArgumentException("unknown object in 'ContentHints' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * constructor
+		 */
+		private ContentHints(
+			Asn1Sequence seq)
+		{
+			IAsn1Convertible field = seq[0];
+			if (field.ToAsn1Object() is DerUtf8String)
+			{
+				contentDescription = DerUtf8String.GetInstance(field);
+				contentType = DerObjectIdentifier.GetInstance(seq[1]);
+			}
+			else
+			{
+				contentType = DerObjectIdentifier.GetInstance(seq[0]);
+			}
+		}
+
+		public ContentHints(
+			DerObjectIdentifier contentType)
+		{
+			this.contentType = contentType;
+			this.contentDescription = null;
+		}
+
+		public ContentHints(
+			DerObjectIdentifier	contentType,
+			DerUtf8String		contentDescription)
+		{
+			this.contentType = contentType;
+			this.contentDescription = contentDescription;
+		}
+
+		public DerObjectIdentifier ContentType
+		{
+			get { return contentType; }
+		}
+
+		public DerUtf8String ContentDescription
+		{
+			get { return contentDescription; }
+		}
+
+		/**
+		 * <pre>
+		 * ContentHints ::= SEQUENCE {
+		 *   contentDescription UTF8String (SIZE (1..MAX)) OPTIONAL,
+		 *   contentType ContentType }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (contentDescription != null)
+			{
+				v.Add(contentDescription);
+			}
+
+			v.Add(contentType);
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/ContentIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/ess/ContentIdentifier.cs
new file mode 100644
index 0000000..8058dcc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/ContentIdentifier.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	public class ContentIdentifier
+		: Asn1Encodable
+	{
+		private Asn1OctetString value;
+
+		public static ContentIdentifier GetInstance(
+			object o)
+		{
+			if (o == null || o is ContentIdentifier)
+			{
+				return (ContentIdentifier) o;
+			}
+
+			if (o is Asn1OctetString)
+			{
+				return new ContentIdentifier((Asn1OctetString) o);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'ContentIdentifier' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * Create from OCTET STRING whose octets represent the identifier.
+		 */
+		public ContentIdentifier(
+			Asn1OctetString value)
+		{
+			this.value = value;
+		}
+
+		/**
+		 * Create from byte array representing the identifier.
+		 */
+		public ContentIdentifier(
+			byte[] value)
+			: this(new DerOctetString(value))
+		{
+		}
+
+		public Asn1OctetString Value
+		{
+			get { return value; }
+		}
+
+		/**
+		 * The definition of ContentIdentifier is
+		 * <pre>
+		 * ContentIdentifier ::=  OCTET STRING
+		 * </pre>
+		 * id-aa-contentIdentifier OBJECT IDENTIFIER ::= { iso(1)
+		 *  member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+		 *  smime(16) id-aa(2) 7 }
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return value;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertID.cs b/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertID.cs
new file mode 100644
index 0000000..4d449a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertID.cs
@@ -0,0 +1,93 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	public class EssCertID
+		: Asn1Encodable
+	{
+		private Asn1OctetString certHash;
+		private IssuerSerial issuerSerial;
+
+		public static EssCertID GetInstance(
+			object o)
+		{
+			if (o == null || o is EssCertID)
+			{
+				return (EssCertID) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new EssCertID((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'EssCertID' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * constructor
+		 */
+		public EssCertID(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			this.certHash = Asn1OctetString.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				issuerSerial = IssuerSerial.GetInstance(seq[1]);
+			}
+		}
+
+		public EssCertID(
+			byte[] hash)
+		{
+			certHash = new DerOctetString(hash);
+		}
+
+		public EssCertID(
+			byte[]			hash,
+			IssuerSerial	issuerSerial)
+		{
+			this.certHash = new DerOctetString(hash);
+			this.issuerSerial = issuerSerial;
+		}
+
+		public byte[] GetCertHash()
+		{
+			return certHash.GetOctets();
+		}
+
+		public IssuerSerial IssuerSerial
+		{
+			get { return issuerSerial; }
+		}
+
+		/**
+		 * <pre>
+		 * EssCertID ::= SEQUENCE {
+		 *     certHash Hash,
+		 *     issuerSerial IssuerSerial OPTIONAL }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certHash);
+
+			if (issuerSerial != null)
+			{
+				v.Add(issuerSerial);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertIDv2.cs b/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertIDv2.cs
new file mode 100644
index 0000000..35ce699
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/ESSCertIDv2.cs
@@ -0,0 +1,146 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+    public class EssCertIDv2
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier hashAlgorithm;
+        private readonly byte[]              certHash;
+        private readonly IssuerSerial        issuerSerial;
+
+        private static readonly AlgorithmIdentifier DefaultAlgID = new AlgorithmIdentifier(
+            NistObjectIdentifiers.IdSha256);
+
+        public static EssCertIDv2 GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            EssCertIDv2 existing = obj as EssCertIDv2;
+            if (existing != null)
+                return existing;
+            return new EssCertIDv2(Asn1Sequence.GetInstance(obj));
+        }
+
+        private EssCertIDv2(
+            Asn1Sequence seq)
+        {
+            if (seq.Count > 3)
+                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            int count = 0;
+
+            if (seq[0] is Asn1OctetString)
+            {
+                // Default value
+                this.hashAlgorithm = DefaultAlgID;
+            }
+            else
+            {
+                this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[count++].ToAsn1Object());
+            }
+
+            this.certHash = Asn1OctetString.GetInstance(seq[count++].ToAsn1Object()).GetOctets();
+
+            if (seq.Count > count)
+            {
+                this.issuerSerial = IssuerSerial.GetInstance(
+                    Asn1Sequence.GetInstance(seq[count].ToAsn1Object()));
+            }
+        }
+
+        public EssCertIDv2(byte[] certHash)
+            : this(null, certHash, null)
+        {
+        }
+
+        public EssCertIDv2(
+            AlgorithmIdentifier	algId,
+            byte[]				certHash)
+            : this(algId, certHash, null)
+        {
+        }
+
+        public EssCertIDv2(
+            byte[]              certHash,
+            IssuerSerial        issuerSerial)
+            : this(null, certHash, issuerSerial)
+        {
+        }
+
+        public EssCertIDv2(
+            AlgorithmIdentifier	algId,
+            byte[]				certHash,
+            IssuerSerial		issuerSerial)
+        {
+            if (algId == null)
+            {
+                // Default value
+                this.hashAlgorithm = DefaultAlgID;
+            }
+            else
+            {
+                this.hashAlgorithm = algId;
+            }
+
+            this.certHash = certHash;
+            this.issuerSerial = issuerSerial;
+        }
+
+        public AlgorithmIdentifier HashAlgorithm
+        {
+            get { return this.hashAlgorithm; }
+        }
+
+        public byte[] GetCertHash()
+        {
+            return Arrays.Clone(certHash);
+        }
+
+        public IssuerSerial IssuerSerial
+        {
+            get { return issuerSerial; }
+        }
+
+        /**
+         * <pre>
+         * EssCertIDv2 ::=  SEQUENCE {
+         *     hashAlgorithm     AlgorithmIdentifier
+         *              DEFAULT {algorithm id-sha256},
+         *     certHash          Hash,
+         *     issuerSerial      IssuerSerial OPTIONAL
+         * }
+         *
+         * Hash ::= OCTET STRING
+         *
+         * IssuerSerial ::= SEQUENCE {
+         *     issuer         GeneralNames,
+         *     serialNumber   CertificateSerialNumber
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (!hashAlgorithm.Equals(DefaultAlgID))
+            {
+                v.Add(hashAlgorithm);
+            }
+
+            v.Add(new DerOctetString(certHash).ToAsn1Object());
+
+            if (issuerSerial != null)
+            {
+                v.Add(issuerSerial);
+            }
+
+            return new DerSequence(v);
+        }
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/OtherCertID.cs b/BouncyCastle.AxCrypt/src/asn1/ess/OtherCertID.cs
new file mode 100644
index 0000000..972ef8c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/OtherCertID.cs
@@ -0,0 +1,132 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	[Obsolete("Use version in Asn1.Esf instead")]
+	public class OtherCertID
+		: Asn1Encodable
+	{
+		private Asn1Encodable otherCertHash;
+		private IssuerSerial issuerSerial;
+
+		public static OtherCertID GetInstance(
+			object o)
+		{
+			if (o == null || o is OtherCertID)
+			{
+				return (OtherCertID) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new OtherCertID((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'OtherCertID' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * constructor
+		 */
+		public OtherCertID(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			if (seq[0].ToAsn1Object() is Asn1OctetString)
+			{
+				otherCertHash = Asn1OctetString.GetInstance(seq[0]);
+			}
+			else
+			{
+				otherCertHash = DigestInfo.GetInstance(seq[0]);
+			}
+
+			if (seq.Count > 1)
+			{
+				issuerSerial = IssuerSerial.GetInstance(Asn1Sequence.GetInstance(seq[1]));
+			}
+		}
+
+		public OtherCertID(
+			AlgorithmIdentifier	algId,
+			byte[]				digest)
+		{
+			this.otherCertHash = new DigestInfo(algId, digest);
+		}
+
+		public OtherCertID(
+			AlgorithmIdentifier	algId,
+			byte[]				digest,
+			IssuerSerial		issuerSerial)
+		{
+			this.otherCertHash = new DigestInfo(algId, digest);
+			this.issuerSerial = issuerSerial;
+		}
+
+		public AlgorithmIdentifier AlgorithmHash
+		{
+			get
+			{
+				if (otherCertHash.ToAsn1Object() is Asn1OctetString)
+				{
+					// SHA-1
+					return new AlgorithmIdentifier("1.3.14.3.2.26");
+				}
+
+				return DigestInfo.GetInstance(otherCertHash).AlgorithmID;
+			}
+		}
+
+		public byte[] GetCertHash()
+		{
+			if (otherCertHash.ToAsn1Object() is Asn1OctetString)
+			{
+				// SHA-1
+				return ((Asn1OctetString) otherCertHash.ToAsn1Object()).GetOctets();
+			}
+
+			return DigestInfo.GetInstance(otherCertHash).GetDigest();
+		}
+
+		public IssuerSerial IssuerSerial
+		{
+			get { return issuerSerial; }
+		}
+
+		/**
+		 * <pre>
+		 * OtherCertID ::= SEQUENCE {
+		 *     otherCertHash    OtherHash,
+		 *     issuerSerial     IssuerSerial OPTIONAL }
+		 *
+		 * OtherHash ::= CHOICE {
+		 *     sha1Hash     OCTET STRING,
+		 *     otherHash    OtherHashAlgAndValue }
+		 *
+		 * OtherHashAlgAndValue ::= SEQUENCE {
+		 *     hashAlgorithm    AlgorithmIdentifier,
+		 *     hashValue        OCTET STRING }
+		 *
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(otherCertHash);
+
+			if (issuerSerial != null)
+			{
+				v.Add(issuerSerial);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/OtherSigningCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/ess/OtherSigningCertificate.cs
new file mode 100644
index 0000000..c165fec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/OtherSigningCertificate.cs
@@ -0,0 +1,109 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	[Obsolete("Use version in Asn1.Esf instead")]
+	public class OtherSigningCertificate
+		: Asn1Encodable
+	{
+		private Asn1Sequence certs, policies;
+
+		public static OtherSigningCertificate GetInstance(
+			object o)
+		{
+			if (o == null || o is OtherSigningCertificate)
+			{
+				return (OtherSigningCertificate) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new OtherSigningCertificate((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'OtherSigningCertificate' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * constructors
+		 */
+		public OtherSigningCertificate(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			this.certs = Asn1Sequence.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.policies = Asn1Sequence.GetInstance(seq[1]);
+			}
+		}
+
+		public OtherSigningCertificate(
+			OtherCertID otherCertID)
+		{
+			certs = new DerSequence(otherCertID);
+		}
+
+		public OtherCertID[] GetCerts()
+		{
+			OtherCertID[] cs = new OtherCertID[certs.Count];
+
+			for (int i = 0; i != certs.Count; ++i)
+			{
+				cs[i] = OtherCertID.GetInstance(certs[i]);
+			}
+
+			return cs;
+		}
+
+		public PolicyInformation[] GetPolicies()
+		{
+			if (policies == null)
+			{
+				return null;
+			}
+
+			PolicyInformation[] ps = new PolicyInformation[policies.Count];
+
+			for (int i = 0; i != policies.Count; i++)
+			{
+				ps[i] = PolicyInformation.GetInstance(policies[i]);
+			}
+
+			return ps;
+		}
+
+		/**
+		 * The definition of OtherSigningCertificate is
+		 * <pre>
+		 * OtherSigningCertificate ::=  SEQUENCE {
+		 *      certs        SEQUENCE OF OtherCertID,
+		 *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+		 * }
+		 * </pre>
+		 * id-aa-ets-otherSigCert OBJECT IDENTIFIER ::= { iso(1)
+		 *  member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+		 *  smime(16) id-aa(2) 19 }
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+			if (policies != null)
+			{
+				v.Add(policies);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificate.cs
new file mode 100644
index 0000000..366749b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificate.cs
@@ -0,0 +1,108 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+	public class SigningCertificate
+		: Asn1Encodable
+	{
+		private Asn1Sequence certs, policies;
+
+		public static SigningCertificate GetInstance(
+			object o)
+		{
+			if (o == null || o is SigningCertificate)
+			{
+				return (SigningCertificate) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new SigningCertificate((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'SigningCertificate' factory : "
+				+ o.GetType().Name + ".");
+		}
+
+		/**
+		 * constructors
+		 */
+		public SigningCertificate(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			this.certs = Asn1Sequence.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.policies = Asn1Sequence.GetInstance(seq[1]);
+			}
+		}
+
+		public SigningCertificate(
+			EssCertID essCertID)
+		{
+			certs = new DerSequence(essCertID);
+		}
+
+		public EssCertID[] GetCerts()
+		{
+			EssCertID[] cs = new EssCertID[certs.Count];
+
+			for (int i = 0; i != certs.Count; i++)
+			{
+				cs[i] = EssCertID.GetInstance(certs[i]);
+			}
+
+			return cs;
+		}
+
+		public PolicyInformation[] GetPolicies()
+		{
+			if (policies == null)
+			{
+				return null;
+			}
+
+			PolicyInformation[] ps = new PolicyInformation[policies.Count];
+
+			for (int i = 0; i != policies.Count; i++)
+			{
+				ps[i] = PolicyInformation.GetInstance(policies[i]);
+			}
+
+			return ps;
+		}
+
+		/**
+		 * The definition of SigningCertificate is
+		 * <pre>
+		 * SigningCertificate ::=  SEQUENCE {
+		 *      certs        SEQUENCE OF EssCertID,
+		 *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+		 * }
+		 * </pre>
+		 * id-aa-signingCertificate OBJECT IDENTIFIER ::= { iso(1)
+		 *  member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+		 *  smime(16) id-aa(2) 12 }
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+			if (policies != null)
+			{
+				v.Add(policies);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificateV2.cs b/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificateV2.cs
new file mode 100644
index 0000000..cabecc1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ess/SigningCertificateV2.cs
@@ -0,0 +1,112 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ess
+{
+    public class SigningCertificateV2
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence certs;
+        private readonly Asn1Sequence policies;
+
+        public static SigningCertificateV2 GetInstance(
+            object o)
+        {
+            if (o == null || o is SigningCertificateV2)
+                return (SigningCertificateV2) o;
+
+            if (o is Asn1Sequence)
+                return new SigningCertificateV2((Asn1Sequence) o);
+
+            throw new ArgumentException(
+                "unknown object in 'SigningCertificateV2' factory : "
+                + o.GetType().Name + ".");
+        }
+
+        private SigningCertificateV2(
+            Asn1Sequence seq)
+        {
+            if (seq.Count < 1 || seq.Count > 2)
+                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            this.certs = Asn1Sequence.GetInstance(seq[0].ToAsn1Object());
+
+            if (seq.Count > 1)
+            {
+                this.policies = Asn1Sequence.GetInstance(seq[1].ToAsn1Object());
+            }
+        }
+
+        public SigningCertificateV2(
+            EssCertIDv2 cert)
+        {
+            this.certs = new DerSequence(cert);
+        }
+
+        public SigningCertificateV2(
+            EssCertIDv2[] certs)
+        {
+            this.certs = new DerSequence(certs);
+        }
+
+        public SigningCertificateV2(
+            EssCertIDv2[]		certs,
+            PolicyInformation[]	policies)
+        {
+            this.certs = new DerSequence(certs);
+
+            if (policies != null)
+            {
+                this.policies = new DerSequence(policies);
+            }
+        }
+
+        public EssCertIDv2[] GetCerts()
+        {
+            EssCertIDv2[] certIds = new EssCertIDv2[certs.Count];
+            for (int i = 0; i != certs.Count; i++)
+            {
+                certIds[i] = EssCertIDv2.GetInstance(certs[i]);
+            }
+            return certIds;
+        }
+
+        public PolicyInformation[] GetPolicies()
+        {
+            if (policies == null)
+                return null;
+
+            PolicyInformation[] policyInformations = new PolicyInformation[policies.Count];
+            for (int i = 0; i != policies.Count; i++)
+            {
+                policyInformations[i] = PolicyInformation.GetInstance(policies[i]);
+            }
+            return policyInformations;
+        }
+
+        /**
+         * The definition of SigningCertificateV2 is
+         * <pre>
+         * SigningCertificateV2 ::=  SEQUENCE {
+         *      certs        SEQUENCE OF EssCertIDv2,
+         *      policies     SEQUENCE OF PolicyInformation OPTIONAL
+         * }
+         * </pre>
+         * id-aa-signingCertificateV2 OBJECT IDENTIFIER ::= { iso(1)
+         *    member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs9(9)
+         *    smime(16) id-aa(2) 47 }
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(certs);
+
+            if (policies != null)
+            {
+                v.Add(policies);
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/gnu/GNUObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/gnu/GNUObjectIdentifiers.cs
new file mode 100644
index 0000000..9311a3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/gnu/GNUObjectIdentifiers.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Gnu
+{
+	public abstract class GnuObjectIdentifiers
+	{
+		public static readonly DerObjectIdentifier Gnu					= new DerObjectIdentifier("1.3.6.1.4.1.11591.1"); // GNU Radius
+		public static readonly DerObjectIdentifier GnuPG				= new DerObjectIdentifier("1.3.6.1.4.1.11591.2"); // GnuPG (Ägypten)
+		public static readonly DerObjectIdentifier Notation				= new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1"); // notation
+		public static readonly DerObjectIdentifier PkaAddress			= new DerObjectIdentifier("1.3.6.1.4.1.11591.2.1.1"); // pkaAddress
+		public static readonly DerObjectIdentifier GnuRadar				= new DerObjectIdentifier("1.3.6.1.4.1.11591.3"); // GNU Radar
+		public static readonly DerObjectIdentifier DigestAlgorithm		= new DerObjectIdentifier("1.3.6.1.4.1.11591.12"); // digestAlgorithm
+		public static readonly DerObjectIdentifier Tiger192				= new DerObjectIdentifier("1.3.6.1.4.1.11591.12.2"); // TIGER/192
+		public static readonly DerObjectIdentifier EncryptionAlgorithm	= new DerObjectIdentifier("1.3.6.1.4.1.11591.13"); // encryptionAlgorithm
+		public static readonly DerObjectIdentifier Serpent				= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2"); // Serpent
+		public static readonly DerObjectIdentifier Serpent128Ecb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.1"); // Serpent-128-ECB
+		public static readonly DerObjectIdentifier Serpent128Cbc		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.2"); // Serpent-128-CBC
+		public static readonly DerObjectIdentifier Serpent128Ofb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.3"); // Serpent-128-OFB
+		public static readonly DerObjectIdentifier Serpent128Cfb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.4"); // Serpent-128-CFB
+		public static readonly DerObjectIdentifier Serpent192Ecb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.21"); // Serpent-192-ECB
+		public static readonly DerObjectIdentifier Serpent192Cbc		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.22"); // Serpent-192-CBC
+		public static readonly DerObjectIdentifier Serpent192Ofb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.23"); // Serpent-192-OFB
+		public static readonly DerObjectIdentifier Serpent192Cfb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.24"); // Serpent-192-CFB
+		public static readonly DerObjectIdentifier Serpent256Ecb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.41"); // Serpent-256-ECB
+		public static readonly DerObjectIdentifier Serpent256Cbc		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.42"); // Serpent-256-CBC
+		public static readonly DerObjectIdentifier Serpent256Ofb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.43"); // Serpent-256-OFB
+		public static readonly DerObjectIdentifier Serpent256Cfb		= new DerObjectIdentifier("1.3.6.1.4.1.11591.13.2.44"); // Serpent-256-CFB
+		public static readonly DerObjectIdentifier Crc					= new DerObjectIdentifier("1.3.6.1.4.1.11591.14"); // CRC algorithms
+		public static readonly DerObjectIdentifier Crc32				= new DerObjectIdentifier("1.3.6.1.4.1.11591.14.1"); // CRC 32
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/iana/IANAObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/iana/IANAObjectIdentifiers.cs
new file mode 100644
index 0000000..63343f5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/iana/IANAObjectIdentifiers.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Asn1.Iana
+{
+	public abstract class IanaObjectIdentifiers
+	{
+		// id-SHA1 OBJECT IDENTIFIER ::=
+		// {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ipsec(8) isakmpOakley(1)}
+		//
+
+		public static readonly DerObjectIdentifier IsakmpOakley = new DerObjectIdentifier("1.3.6.1.5.5.8.1");
+
+		public static readonly DerObjectIdentifier HmacMD5 = new DerObjectIdentifier(IsakmpOakley + ".1");
+		public static readonly DerObjectIdentifier HmacSha1 = new DerObjectIdentifier(IsakmpOakley + ".2");
+
+		public static readonly DerObjectIdentifier HmacTiger = new DerObjectIdentifier(IsakmpOakley + ".3");
+
+		public static readonly DerObjectIdentifier HmacRipeMD160 = new DerObjectIdentifier(IsakmpOakley + ".4");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/icao/CscaMasterList.cs b/BouncyCastle.AxCrypt/src/asn1/icao/CscaMasterList.cs
new file mode 100644
index 0000000..6890d8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/icao/CscaMasterList.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+	/**
+	 * The CscaMasterList object. This object can be wrapped in a
+	 * CMSSignedData to be published in LDAP.
+	 *
+	 * <pre>
+	 * CscaMasterList ::= SEQUENCE {
+	 *   version                CscaMasterListVersion,
+	 *   certList               SET OF Certificate }
+	 *   
+	 * CscaMasterListVersion :: INTEGER {v0(0)}
+	 * </pre>
+	 */
+	public class CscaMasterList 
+		: Asn1Encodable 
+	{
+		private DerInteger version = new DerInteger(0);
+		private X509CertificateStructure[] certList;
+
+		public static CscaMasterList GetInstance(
+			object obj)
+		{
+			if (obj is CscaMasterList)
+				return (CscaMasterList)obj;
+
+			if (obj != null)
+				return new CscaMasterList(Asn1Sequence.GetInstance(obj));            
+
+			return null;
+		}
+
+		private CscaMasterList(
+			Asn1Sequence seq)
+		{
+			if (seq == null || seq.Count == 0)
+				throw new ArgumentException("null or empty sequence passed.");
+
+			if (seq.Count != 2)
+				throw new ArgumentException("Incorrect sequence size: " + seq.Count);
+
+			this.version = DerInteger.GetInstance(seq[0]);
+
+			Asn1Set certSet = Asn1Set.GetInstance(seq[1]);
+
+			this.certList = new X509CertificateStructure[certSet.Count];
+			for (int i = 0; i < certList.Length; i++)
+			{
+				certList[i] = X509CertificateStructure.GetInstance(certSet[i]);
+			}
+		}
+
+		public CscaMasterList(
+			X509CertificateStructure[] certStructs)
+		{
+			certList = CopyCertList(certStructs);
+		}
+
+		public virtual int Version
+		{
+			get { return version.Value.IntValue; }
+		}
+
+		public X509CertificateStructure[] GetCertStructs()
+		{
+			return CopyCertList(certList);
+		}
+
+		private static X509CertificateStructure[] CopyCertList(X509CertificateStructure[] orig)
+		{
+			return (X509CertificateStructure[])orig.Clone();
+		}
+
+		public override Asn1Object ToAsn1Object() 
+		{
+			return new DerSequence(version, new DerSet(certList));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/icao/DataGroupHash.cs b/BouncyCastle.AxCrypt/src/asn1/icao/DataGroupHash.cs
new file mode 100644
index 0000000..e0d7eee
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/icao/DataGroupHash.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+    /**
+    * The DataGroupHash object.
+    * <pre>
+    * DataGroupHash  ::=  SEQUENCE {
+    *      dataGroupNumber         DataGroupNumber,
+    *      dataGroupHashValue     OCTET STRING }
+    *
+    * DataGroupNumber ::= INTEGER {
+    *         dataGroup1    (1),
+    *         dataGroup1    (2),
+    *         dataGroup1    (3),
+    *         dataGroup1    (4),
+    *         dataGroup1    (5),
+    *         dataGroup1    (6),
+    *         dataGroup1    (7),
+    *         dataGroup1    (8),
+    *         dataGroup1    (9),
+    *         dataGroup1    (10),
+    *         dataGroup1    (11),
+    *         dataGroup1    (12),
+    *         dataGroup1    (13),
+    *         dataGroup1    (14),
+    *         dataGroup1    (15),
+    *         dataGroup1    (16) }
+    *
+    * </pre>
+    */
+    public class DataGroupHash
+        : Asn1Encodable
+    {
+        private readonly DerInteger dataGroupNumber;
+        private readonly Asn1OctetString dataGroupHashValue;
+
+		public static DataGroupHash GetInstance(
+            object obj)
+        {
+            if (obj is DataGroupHash)
+                return (DataGroupHash)obj;
+
+			if (obj != null)
+				return new DataGroupHash(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		private DataGroupHash(
+			Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.dataGroupNumber = DerInteger.GetInstance(seq[0]);
+            this.dataGroupHashValue = Asn1OctetString.GetInstance(seq[1]);
+        }
+
+		public DataGroupHash(
+            int				dataGroupNumber,
+            Asn1OctetString	dataGroupHashValue)
+        {
+            this.dataGroupNumber = new DerInteger(dataGroupNumber);
+            this.dataGroupHashValue = dataGroupHashValue;
+        }
+
+		public int DataGroupNumber
+		{
+			get { return dataGroupNumber.Value.IntValue; }
+		}
+
+		public Asn1OctetString DataGroupHashValue
+		{
+			get { return dataGroupHashValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(dataGroupNumber, dataGroupHashValue);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/icao/ICAOObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/icao/ICAOObjectIdentifiers.cs
new file mode 100644
index 0000000..389d4da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/icao/ICAOObjectIdentifiers.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+	public abstract class IcaoObjectIdentifiers
+	{
+		//
+		// base id
+		//
+		public static readonly DerObjectIdentifier IdIcao = new DerObjectIdentifier("2.23.136");
+
+		public static readonly DerObjectIdentifier IdIcaoMrtd = IdIcao.Branch("1");
+		public static readonly DerObjectIdentifier IdIcaoMrtdSecurity = IdIcaoMrtd.Branch("1");
+
+		// LDS security object, see ICAO Doc 9303-Volume 2-Section IV-A3.2
+		public static readonly DerObjectIdentifier IdIcaoLdsSecurityObject = IdIcaoMrtdSecurity.Branch("1");
+
+		// CSCA master list, see TR CSCA Countersigning and Master List issuance
+		public static readonly DerObjectIdentifier IdIcaoCscaMasterList = IdIcaoMrtdSecurity.Branch("2");
+		public static readonly DerObjectIdentifier IdIcaoCscaMasterListSigningKey = IdIcaoMrtdSecurity.Branch("3");
+
+		// document type list, see draft TR LDS and PKI Maintenance, par. 3.2.1
+		public static readonly DerObjectIdentifier IdIcaoDocumentTypeList = IdIcaoMrtdSecurity.Branch("4");
+
+		// Active Authentication protocol, see draft TR LDS and PKI Maintenance,
+		// par. 5.2.2
+		public static readonly DerObjectIdentifier IdIcaoAAProtocolObject = IdIcaoMrtdSecurity.Branch("5");
+
+		// CSCA name change and key reoll-over, see draft TR LDS and PKI
+		// Maintenance, par. 3.2.1
+		public static readonly DerObjectIdentifier IdIcaoExtensions = IdIcaoMrtdSecurity.Branch("6");
+		public static readonly DerObjectIdentifier IdIcaoExtensionsNamechangekeyrollover = IdIcaoExtensions.Branch("1");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/icao/LDSSecurityObject.cs b/BouncyCastle.AxCrypt/src/asn1/icao/LDSSecurityObject.cs
new file mode 100644
index 0000000..c33ca68
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/icao/LDSSecurityObject.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+	/**
+	 * The LDSSecurityObject object (V1.8).
+	 * <pre>
+	 * LDSSecurityObject ::= SEQUENCE {
+	 *   version                LDSSecurityObjectVersion,
+	 *   hashAlgorithm          DigestAlgorithmIdentifier,
+	 *   dataGroupHashValues    SEQUENCE SIZE (2..ub-DataGroups) OF DataHashGroup,
+	 *   ldsVersionInfo         LDSVersionInfo OPTIONAL
+	 *     -- if present, version MUST be v1 }
+	 *
+	 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier,
+	 *
+	 * LDSSecurityObjectVersion :: INTEGER {V0(0)}
+	 * </pre>
+	 */
+	public class LdsSecurityObject
+		: Asn1Encodable
+	{
+		public const int UBDataGroups = 16;
+
+		private DerInteger version = new DerInteger(0);
+		private AlgorithmIdentifier digestAlgorithmIdentifier;
+		private DataGroupHash[] datagroupHash;
+		private LdsVersionInfo versionInfo;
+
+		public static LdsSecurityObject GetInstance(
+			object obj)
+		{
+			if (obj is LdsSecurityObject)
+				return (LdsSecurityObject)obj;
+
+			if (obj != null)
+				return new LdsSecurityObject(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		private LdsSecurityObject(
+			Asn1Sequence seq)
+		{
+			if (seq == null || seq.Count == 0)
+				throw new ArgumentException("null or empty sequence passed.");
+
+			IEnumerator e = seq.GetEnumerator();
+
+			// version
+			e.MoveNext();
+			version = DerInteger.GetInstance(e.Current);
+			// digestAlgorithmIdentifier
+			e.MoveNext();
+			digestAlgorithmIdentifier = AlgorithmIdentifier.GetInstance(e.Current);
+
+			e.MoveNext();
+			Asn1Sequence datagroupHashSeq = Asn1Sequence.GetInstance(e.Current);
+
+			if (version.Value.Equals(BigInteger.One))
+			{
+				e.MoveNext();
+				versionInfo = LdsVersionInfo.GetInstance(e.Current);
+			}
+
+			CheckDatagroupHashSeqSize(datagroupHashSeq.Count);
+
+			datagroupHash = new DataGroupHash[datagroupHashSeq.Count];
+			for (int i= 0; i< datagroupHashSeq.Count; i++)
+			{
+				datagroupHash[i] = DataGroupHash.GetInstance(datagroupHashSeq[i]);
+			}
+		}
+
+		public LdsSecurityObject(
+			AlgorithmIdentifier	digestAlgorithmIdentifier,
+			DataGroupHash[]		datagroupHash)
+		{
+			this.version = new DerInteger(0);
+			this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+			this.datagroupHash = datagroupHash;
+
+			CheckDatagroupHashSeqSize(datagroupHash.Length);
+		}
+
+
+		public LdsSecurityObject(
+			AlgorithmIdentifier	digestAlgorithmIdentifier,
+			DataGroupHash[]		datagroupHash,
+			LdsVersionInfo		versionInfo)
+		{
+			this.version = new DerInteger(1);
+			this.digestAlgorithmIdentifier = digestAlgorithmIdentifier;
+			this.datagroupHash = datagroupHash;
+			this.versionInfo = versionInfo;
+
+			CheckDatagroupHashSeqSize(datagroupHash.Length);
+		}
+
+		private void CheckDatagroupHashSeqSize(int size)
+		{
+			if (size < 2 || size > UBDataGroups)
+				throw new ArgumentException("wrong size in DataGroupHashValues : not in (2.."+ UBDataGroups +")");
+		}
+
+		public BigInteger Version
+		{
+			get { return version.Value; }
+		}
+
+		public AlgorithmIdentifier DigestAlgorithmIdentifier
+		{
+			get { return digestAlgorithmIdentifier; }
+		}
+
+		public DataGroupHash[] GetDatagroupHash()
+		{
+			return datagroupHash;
+		}
+
+		public LdsVersionInfo VersionInfo
+		{
+			get { return versionInfo; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			DerSequence hashSeq = new DerSequence(datagroupHash);
+
+			Asn1EncodableVector v = new Asn1EncodableVector(version, digestAlgorithmIdentifier, hashSeq);
+
+			if (versionInfo != null)
+			{
+				v.Add(versionInfo);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/icao/LDSVersionInfo.cs b/BouncyCastle.AxCrypt/src/asn1/icao/LDSVersionInfo.cs
new file mode 100644
index 0000000..2cdcad2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/icao/LDSVersionInfo.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Icao
+{
+	public class LdsVersionInfo
+		: Asn1Encodable
+	{
+		private DerPrintableString ldsVersion;
+		private DerPrintableString unicodeVersion;
+
+		public LdsVersionInfo(string ldsVersion, string unicodeVersion)
+		{
+			this.ldsVersion = new DerPrintableString(ldsVersion);
+			this.unicodeVersion = new DerPrintableString(unicodeVersion);
+		}
+
+		private LdsVersionInfo(Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("sequence wrong size for LDSVersionInfo", "seq");
+
+			this.ldsVersion = DerPrintableString.GetInstance(seq[0]);
+			this.unicodeVersion = DerPrintableString.GetInstance(seq[1]);
+		}
+
+		public static LdsVersionInfo GetInstance(object obj)
+		{
+			if (obj is LdsVersionInfo)
+				return (LdsVersionInfo)obj;
+
+			if (obj != null)
+				return new LdsVersionInfo(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		public virtual string GetLdsVersion()
+		{
+			return ldsVersion.GetString();
+		}
+
+		public virtual string GetUnicodeVersion()
+		{
+			return unicodeVersion.GetString();
+		}
+
+		/**
+		 * <pre>
+		 * LDSVersionInfo ::= SEQUENCE {
+		 *    ldsVersion PRINTABLE STRING
+		 *    unicodeVersion PRINTABLE STRING
+		 *  }
+		 * </pre>
+		 * @return
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(ldsVersion, unicodeVersion);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs
new file mode 100644
index 0000000..af60b03
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/ISISMTTObjectIdentifiers.cs
@@ -0,0 +1,177 @@
+namespace Org.BouncyCastle.Asn1.IsisMtt
+{
+	public abstract class IsisMttObjectIdentifiers
+	{
+		public static readonly DerObjectIdentifier IdIsisMtt = new DerObjectIdentifier("1.3.36.8");
+
+		public static readonly DerObjectIdentifier IdIsisMttCP = new DerObjectIdentifier(IdIsisMtt + ".1");
+
+		/**
+		 * The id-isismtt-cp-accredited OID indicates that the certificate is a
+		 * qualified certificate according to Directive 1999/93/EC of the European
+		 * Parliament and of the Council of 13 December 1999 on a Community
+		 * Framework for Electronic Signatures, which additionally conforms the
+		 * special requirements of the SigG and has been issued by an accredited CA.
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttCPAccredited = new DerObjectIdentifier(IdIsisMttCP + ".1");
+
+		public static readonly DerObjectIdentifier IdIsisMttAT = new DerObjectIdentifier(IdIsisMtt + ".3");
+
+		/**
+		 * Certificate extensionDate of certificate generation
+		 * 
+		 * <pre>
+		 *		DateOfCertGenSyntax ::= GeneralizedTime
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATDateOfCertGen = new DerObjectIdentifier(IdIsisMttAT + ".1");
+
+		/**
+		 * Attribute to indicate that the certificate holder may sign in the name of
+		 * a third person. May also be used as extension in a certificate.
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATProcuration = new DerObjectIdentifier(IdIsisMttAT + ".2");
+
+		/**
+		 * Attribute to indicate admissions to certain professions. May be used as
+		 * attribute in attribute certificate or as extension in a certificate
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATAdmission = new DerObjectIdentifier(IdIsisMttAT + ".3");
+
+		/**
+		 * Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST
+		 * be used in new certificates in place of the extension/attribute
+		 * MonetaryLimit since January 1, 2004. For the sake of backward
+		 * compatibility with certificates already in use, SigG conforming
+		 * components MUST support MonetaryLimit (as well as QcEuLimitValue).
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATMonetaryLimit = new DerObjectIdentifier(IdIsisMttAT + ".4");
+
+		/**
+		 * A declaration of majority. May be used as attribute in attribute
+		 * certificate or as extension in a certificate
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATDeclarationOfMajority = new DerObjectIdentifier(IdIsisMttAT + ".5");
+
+		/**
+		 * 
+		 * Serial number of the smart card containing the corresponding private key
+		 * 
+		 * <pre>
+		 *		ICCSNSyntax ::= OCTET STRING (SIZE(8..20))
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATIccsn = new DerObjectIdentifier(IdIsisMttAT + ".6");
+
+		/**
+		 * 
+		 * Reference for a file of a smartcard that stores the public key of this
+		 * certificate and that is used as �security anchor�.
+		 * 
+		 * <pre>
+		 *		PKReferenceSyntax ::= OCTET STRING (SIZE(20))
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATPKReference = new DerObjectIdentifier(IdIsisMttAT + ".7");
+
+		/**
+		 * Some other restriction regarding the usage of this certificate. May be
+		 * used as attribute in attribute certificate or as extension in a
+		 * certificate.
+		 * 
+		 * <pre>
+		 *		RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		 * </pre>
+		 * 
+		 * @see Org.BouncyCastle.Asn1.IsisMtt.X509.Restriction
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATRestriction = new DerObjectIdentifier(IdIsisMttAT + ".8");
+
+		/**
+		 * 
+		 * (Single)Request extension: Clients may include this extension in a
+		 * (single) Request to request the responder to send the certificate in the
+		 * response message along with the status information. Besides the LDAP
+		 * service, this extension provides another mechanism for the distribution
+		 * of certificates, which MAY optionally be provided by certificate
+		 * repositories.
+		 * 
+		 * <pre>
+		 *		RetrieveIfAllowed ::= BOOLEAN
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATRetrieveIfAllowed = new DerObjectIdentifier(IdIsisMttAT + ".9");
+
+		/**
+		 * SingleOCSPResponse extension: The certificate requested by the client by
+		 * inserting the RetrieveIfAllowed extension in the request, will be
+		 * returned in this extension.
+		 * 
+		 * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.RequestedCertificate
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATRequestedCertificate = new DerObjectIdentifier(IdIsisMttAT + ".10");
+
+		/**
+		 * Base ObjectIdentifier for naming authorities
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATNamingAuthorities = new DerObjectIdentifier(IdIsisMttAT + ".11");
+
+		/**
+		 * SingleOCSPResponse extension: Date, when certificate has been published
+		 * in the directory and status information has become available. Currently,
+		 * accrediting authorities enforce that SigG-conforming OCSP servers include
+		 * this extension in the responses.
+		 * 
+		 * <pre>
+		 *		CertInDirSince ::= GeneralizedTime
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATCertInDirSince = new DerObjectIdentifier(IdIsisMttAT + ".12");
+
+		/**
+		 * Hash of a certificate in OCSP.
+		 *
+		 * @see Org.BouncyCastle.Asn1.IsisMtt.Ocsp.CertHash
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATCertHash = new DerObjectIdentifier(IdIsisMttAT + ".13");
+
+		/**
+		 * <pre>
+		 *		NameAtBirth ::= DirectoryString(SIZE(1..64)
+		 * </pre>
+		 * 
+		 * Used in
+		 * {@link Org.BouncyCastle.Asn1.X509.SubjectDirectoryAttributes SubjectDirectoryAttributes}
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATNameAtBirth = new DerObjectIdentifier(IdIsisMttAT + ".14");
+
+		/**
+		 * Some other information of non-restrictive nature regarding the usage of
+		 * this certificate. May be used as attribute in atribute certificate or as
+		 * extension in a certificate.
+		 * 
+		 * <pre>
+		 *               AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+		 * </pre>
+		 * 
+		 * @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdditionalInformationSyntax
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATAdditionalInformation = new DerObjectIdentifier(IdIsisMttAT + ".15");
+
+		/**
+		 * Indicates that an attribute certificate exists, which limits the
+		 * usability of this public key certificate. Whenever verifying a signature
+		 * with the help of this certificate, the content of the corresponding
+		 * attribute certificate should be concerned. This extension MUST be
+		 * included in a PKC, if a corresponding attribute certificate (having the
+		 * PKC as base certificate) contains some attribute that restricts the
+		 * usability of the PKC too. Attribute certificates with restricting content
+		 * MUST always be included in the signed document.
+		 * 
+		 * <pre>
+		 *		LiabilityLimitationFlagSyntax ::= BOOLEAN
+		 * </pre>
+		 */
+		public static readonly DerObjectIdentifier IdIsisMttATLiabilityLimitationFlag = new DerObjectIdentifier("0.2.262.1.10.12.0");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/CertHash.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/CertHash.cs
new file mode 100644
index 0000000..da5b530
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/CertHash.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
+{
+	/**
+	* ISIS-MTT PROFILE: The responder may include this extension in a response to
+	* send the hash of the requested certificate to the responder. This hash is
+	* cryptographically bound to the certificate and serves as evidence that the
+	* certificate is known to the responder (i.e. it has been issued and is present
+	* in the directory). Hence, this extension is a means to provide a positive
+	* statement of availability as described in T8.[8]. As explained in T13.[1],
+	* clients may rely on this information to be able to validate signatures after
+	* the expiry of the corresponding certificate. Hence, clients MUST support this
+	* extension. If a positive statement of availability is to be delivered, this
+	* extension syntax and OID MUST be used.
+	* <p/>
+	* <p/>
+	* <pre>
+	*     CertHash ::= SEQUENCE {
+	*       hashAlgorithm AlgorithmIdentifier,
+	*       certificateHash OCTET STRING
+	*     }
+	* </pre>
+	*/
+	public class CertHash
+		: Asn1Encodable
+	{
+		private readonly AlgorithmIdentifier	hashAlgorithm;
+		private readonly byte[]					certificateHash;
+
+		public static CertHash GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CertHash)
+			{
+				return (CertHash) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new CertHash((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type CertHash:
+		* <p/>
+		* <pre>
+		*     CertHash ::= SEQUENCE {
+		*       hashAlgorithm AlgorithmIdentifier,
+		*       certificateHash OCTET STRING
+		*     }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private CertHash(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+			this.certificateHash = DerOctetString.GetInstance(seq[1]).GetOctets();
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param hashAlgorithm   The hash algorithm identifier.
+		* @param certificateHash The hash of the whole DER encoding of the certificate.
+		*/
+		public CertHash(
+			AlgorithmIdentifier	hashAlgorithm,
+			byte[]				certificateHash)
+		{
+			if (hashAlgorithm == null)
+				throw new ArgumentNullException("hashAlgorithm");
+			if (certificateHash == null)
+				throw new ArgumentNullException("certificateHash");
+
+			this.hashAlgorithm = hashAlgorithm;
+			this.certificateHash = (byte[]) certificateHash.Clone();
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public byte[] CertificateHash
+		{
+			get { return (byte[]) certificateHash.Clone(); }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*     CertHash ::= SEQUENCE {
+		*       hashAlgorithm AlgorithmIdentifier,
+		*       certificateHash OCTET STRING
+		*     }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(hashAlgorithm, new DerOctetString(certificateHash));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/RequestedCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/RequestedCertificate.cs
new file mode 100644
index 0000000..7724bfe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/ocsp/RequestedCertificate.cs
@@ -0,0 +1,186 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.Ocsp
+{
+	/**
+	* ISIS-MTT-Optional: The certificate requested by the client by inserting the
+	* RetrieveIfAllowed extension in the request, will be returned in this
+	* extension.
+	* <p/>
+	* ISIS-MTT-SigG: The signature act allows publishing certificates only then,
+	* when the certificate owner gives his isExplicit permission. Accordingly, there
+	* may be �nondownloadable� certificates, about which the responder must provide
+	* status information, but MUST NOT include them in the response. Clients may
+	* get therefore the following three kind of answers on a single request
+	* including the RetrieveIfAllowed extension:
+	* <ul>
+	* <li> a) the responder supports the extension and is allowed to publish the
+	* certificate: RequestedCertificate returned including the requested
+	* certificate</li>
+	* <li>b) the responder supports the extension but is NOT allowed to publish
+	* the certificate: RequestedCertificate returned including an empty OCTET
+	* STRING</li>
+	* <li>c) the responder does not support the extension: RequestedCertificate is
+	* not included in the response</li>
+	* </ul>
+	* Clients requesting RetrieveIfAllowed MUST be able to handle these cases. If
+	* any of the OCTET STRING options is used, it MUST contain the DER encoding of
+	* the requested certificate.
+	* <p/>
+	* <pre>
+	*            RequestedCertificate ::= CHOICE {
+	*              Certificate Certificate,
+	*              publicKeyCertificate [0] EXPLICIT OCTET STRING,
+	*              attributeCertificate [1] EXPLICIT OCTET STRING
+	*            }
+	* </pre>
+	*/
+	public class RequestedCertificate
+		: Asn1Encodable, IAsn1Choice
+	{
+		public enum Choice
+		{
+			Certificate = -1,
+			PublicKeyCertificate = 0,
+			AttributeCertificate = 1
+		}
+
+		private readonly X509CertificateStructure	cert;
+		private readonly byte[]						publicKeyCert;
+		private readonly byte[]						attributeCert;
+
+		public static RequestedCertificate GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RequestedCertificate)
+			{
+				return (RequestedCertificate) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new RequestedCertificate(X509CertificateStructure.GetInstance(obj));
+			}
+
+			if (obj is Asn1TaggedObject)
+			{
+				return new RequestedCertificate((Asn1TaggedObject) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static RequestedCertificate GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			if (!isExplicit)
+				throw new ArgumentException("choice item must be explicitly tagged");
+
+			return GetInstance(obj.GetObject());
+		}
+
+		private RequestedCertificate(
+			Asn1TaggedObject tagged)
+		{
+			switch ((Choice) tagged.TagNo)
+			{
+				case Choice.AttributeCertificate:
+					this.attributeCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+					break;
+				case Choice.PublicKeyCertificate:
+					this.publicKeyCert = Asn1OctetString.GetInstance(tagged, true).GetOctets();
+					break;
+				default:
+					throw new ArgumentException("unknown tag number: " + tagged.TagNo);
+			}
+		}
+
+		/**
+		* Constructor from a given details.
+		* <p/>
+		* Only one parameter can be given. All other must be <code>null</code>.
+		*
+		* @param certificate Given as Certificate
+		*/
+		public RequestedCertificate(
+			X509CertificateStructure certificate)
+		{
+			this.cert = certificate;
+		}
+
+		public RequestedCertificate(
+			Choice	type,
+			byte[]	certificateOctets)
+			: this(new DerTaggedObject((int) type, new DerOctetString(certificateOctets)))
+		{
+		}
+
+		public Choice Type
+		{
+			get
+			{
+				if (cert != null)
+					return Choice.Certificate;
+
+				if (publicKeyCert != null)
+					return Choice.PublicKeyCertificate;
+
+				return Choice.AttributeCertificate;
+			}
+		}
+
+		public byte[] GetCertificateBytes()
+		{
+			if (cert != null)
+			{
+				try
+				{
+					return cert.GetEncoded();
+				}
+				catch (IOException e)
+				{
+					throw new InvalidOperationException("can't decode certificate: " + e);
+				}
+			}
+
+			if (publicKeyCert != null)
+				return publicKeyCert;
+
+			return attributeCert;
+		}
+    
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*            RequestedCertificate ::= CHOICE {
+		*              Certificate Certificate,
+		*              publicKeyCertificate [0] EXPLICIT OCTET STRING,
+		*              attributeCertificate [1] EXPLICIT OCTET STRING
+		*            }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			if (publicKeyCert != null)
+			{
+				return new DerTaggedObject(0, new DerOctetString(publicKeyCert));
+			}
+
+			if (attributeCert != null)
+			{
+				return new DerTaggedObject(1, new DerOctetString(attributeCert));
+			}
+
+			return cert.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs
new file mode 100644
index 0000000..f81d459
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdditionalInformationSyntax.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Some other information of non-restrictive nature regarding the usage of this
+	* certificate.
+	* 
+	* <pre>
+	*    AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+	* </pre>
+	*/
+	public class AdditionalInformationSyntax
+		: Asn1Encodable
+	{
+		private readonly DirectoryString information;
+
+		public static AdditionalInformationSyntax GetInstance(
+			object obj)
+		{
+			if (obj is AdditionalInformationSyntax)
+				return (AdditionalInformationSyntax) obj;
+
+			if (obj is IAsn1String)
+				return new AdditionalInformationSyntax(DirectoryString.GetInstance(obj));
+
+			throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj");
+		}
+
+		private AdditionalInformationSyntax(
+			DirectoryString information)
+		{
+			this.information = information;
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param information The describtion of the information.
+		*/
+		public AdditionalInformationSyntax(
+			string information)
+		{
+			this.information = new DirectoryString(information);
+		}
+
+		public virtual DirectoryString Information
+		{
+			get { return information; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*   AdditionalInformationSyntax ::= DirectoryString (SIZE(1..2048))
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			return information.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdmissionSyntax.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdmissionSyntax.cs
new file mode 100644
index 0000000..64b5dbe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/AdmissionSyntax.cs
@@ -0,0 +1,277 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+    /**
+    * Attribute to indicate admissions to certain professions.
+    * <p/>
+    * <pre>
+    *     AdmissionSyntax ::= SEQUENCE
+    *     {
+    *       admissionAuthority GeneralName OPTIONAL,
+    *       contentsOfAdmissions SEQUENCE OF Admissions
+    *     }
+    * <p/>
+    *     Admissions ::= SEQUENCE
+    *     {
+    *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+    *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+    *       professionInfos SEQUENCE OF ProfessionInfo
+    *     }
+    * <p/>
+    *     NamingAuthority ::= SEQUENCE
+    *     {
+    *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+    *       namingAuthorityUrl IA5String OPTIONAL,
+    *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+    *     }
+    * <p/>
+    *     ProfessionInfo ::= SEQUENCE
+    *     {
+    *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+    *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+    *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+    *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+    *       addProfessionInfo OCTET STRING OPTIONAL
+    *     }
+    * </pre>
+    * <p/>
+    * <p/>
+    * ISIS-MTT PROFILE: The relatively complex structure of AdmissionSyntax
+    * supports the following concepts and requirements:
+    * <ul>
+    * <li> External institutions (e.g. professional associations, chambers, unions,
+    * administrative bodies, companies, etc.), which are responsible for granting
+    * and verifying professional admissions, are indicated by means of the data
+    * field admissionAuthority. An admission authority is indicated by a
+    * GeneralName object. Here an X.501 directory name (distinguished name) can be
+    * indicated in the field directoryName, a URL address can be indicated in the
+    * field uniformResourceIdentifier, and an object identifier can be indicated in
+    * the field registeredId.</li>
+    * <li> The names of authorities which are responsible for the administration of
+    * title registers are indicated in the data field namingAuthority. The name of
+    * the authority can be identified by an object identifier in the field
+    * namingAuthorityId, by means of a text string in the field
+    * namingAuthorityText, by means of a URL address in the field
+    * namingAuthorityUrl, or by a combination of them. For example, the text string
+    * can contain the name of the authority, the country and the name of the title
+    * register. The URL-option refers to a web page which contains lists with
+    * officially registered professions (text and possibly OID) as well as
+    * further information on these professions. Object identifiers for the
+    * component namingAuthorityId are grouped under the OID-branch
+    * id-isis-at-namingAuthorities and must be applied for.</li>
+    * <li>See http://www.teletrust.de/anwend.asp?Id=30200&Sprache=E_&HomePG=0
+    * for an application form and http://www.teletrust.de/links.asp?id=30220,11
+    * for an overview of registered naming authorities.</li>
+    * <li> By means of the data type ProfessionInfo certain professions,
+    * specializations, disciplines, fields of activity, etc. are identified. A
+    * profession is represented by one or more text strings, resp. profession OIDs
+    * in the fields professionItems and professionOIDs and by a registration number
+    * in the field registrationNumber. An indication in text form must always be
+    * present, whereas the other indications are optional. The component
+    * addProfessionInfo may contain additional applicationspecific information in
+    * DER-encoded form.</li>
+    * </ul>
+    * <p/>
+    * By means of different namingAuthority-OIDs or profession OIDs hierarchies of
+    * professions, specializations, disciplines, fields of activity, etc. can be
+    * expressed. The issuing admission authority should always be indicated (field
+    * admissionAuthority), whenever a registration number is presented. Still,
+    * information on admissions can be given without indicating an admission or a
+    * naming authority by the exclusive use of the component professionItems. In
+    * this case the certification authority is responsible for the verification of
+    * the admission information.
+    * <p/>
+    * <p/>
+    * <p/>
+    * This attribute is single-valued. Still, several admissions can be captured in
+    * the sequence structure of the component contentsOfAdmissions of
+    * AdmissionSyntax or in the component professionInfos of Admissions. The
+    * component admissionAuthority of AdmissionSyntax serves as default value for
+    * the component admissionAuthority of Admissions. Within the latter component
+    * the default value can be overwritten, in case that another authority is
+    * responsible. The component namingAuthority of Admissions serves as a default
+    * value for the component namingAuthority of ProfessionInfo. Within the latter
+    * component the default value can be overwritten, in case that another naming
+    * authority needs to be recorded.
+    * <p/>
+    * The length of the string objects is limited to 128 characters. It is
+    * recommended to indicate a namingAuthorityURL in all issued attribute
+    * certificates. If a namingAuthorityURL is indicated, the field professionItems
+    * of ProfessionInfo should contain only registered titles. If the field
+    * professionOIDs exists, it has to contain the OIDs of the professions listed
+    * in professionItems in the same order. In general, the field professionInfos
+    * should contain only one entry, unless the admissions that are to be listed
+    * are logically connected (e.g. they have been issued under the same admission
+    * number).
+    *
+    * @see Org.BouncyCastle.Asn1.IsisMtt.X509.Admissions
+    * @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+    * @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+    */
+    public class AdmissionSyntax
+        : Asn1Encodable
+    {
+        private readonly GeneralName admissionAuthority;
+        private readonly Asn1Sequence contentsOfAdmissions;
+
+        public static AdmissionSyntax GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is AdmissionSyntax)
+            {
+                return (AdmissionSyntax)obj;
+            }
+
+            if (obj is Asn1Sequence)
+            {
+                return new AdmissionSyntax((Asn1Sequence)obj);
+            }
+
+            throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+        /**
+        * Constructor from Asn1Sequence.
+        * <p/>
+        * The sequence is of type ProcurationSyntax:
+        * <p/>
+        * <pre>
+        *     AdmissionSyntax ::= SEQUENCE
+        *     {
+        *       admissionAuthority GeneralName OPTIONAL,
+        *       contentsOfAdmissions SEQUENCE OF Admissions
+        *     }
+        * <p/>
+        *     Admissions ::= SEQUENCE
+        *     {
+        *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+        *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+        *       professionInfos SEQUENCE OF ProfessionInfo
+        *     }
+        * <p/>
+        *     NamingAuthority ::= SEQUENCE
+        *     {
+        *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+        *       namingAuthorityUrl IA5String OPTIONAL,
+        *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+        *     }
+        * <p/>
+        *     ProfessionInfo ::= SEQUENCE
+        *     {
+        *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+        *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+        *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+        *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+        *       addProfessionInfo OCTET STRING OPTIONAL
+        *     }
+        * </pre>
+        *
+        * @param seq The ASN.1 sequence.
+        */
+        private AdmissionSyntax(
+            Asn1Sequence seq)
+        {
+            switch (seq.Count)
+            {
+                case 1:
+                    this.contentsOfAdmissions = DerSequence.GetInstance(seq[0]);
+                    break;
+                case 2:
+                    admissionAuthority = GeneralName.GetInstance(seq[0]);
+                    contentsOfAdmissions = DerSequence.GetInstance(seq[1]);
+                    break;
+                default:
+                    throw new ArgumentException("Bad sequence size: " + seq.Count);
+            }
+        }
+
+        /**
+        * Constructor from given details.
+        *
+        * @param admissionAuthority   The admission authority.
+        * @param contentsOfAdmissions The admissions.
+        */
+        public AdmissionSyntax(
+            GeneralName admissionAuthority,
+            Asn1Sequence contentsOfAdmissions)
+        {
+            this.admissionAuthority = admissionAuthority;
+            this.contentsOfAdmissions = contentsOfAdmissions;
+        }
+
+        /**
+        * Produce an object suitable for an Asn1OutputStream.
+        * <p/>
+        * Returns:
+        * <p/>
+        * <pre>
+        *     AdmissionSyntax ::= SEQUENCE
+        *     {
+        *       admissionAuthority GeneralName OPTIONAL,
+        *       contentsOfAdmissions SEQUENCE OF Admissions
+        *     }
+        * <p/>
+        *     Admissions ::= SEQUENCE
+        *     {
+        *       admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+        *       namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+        *       professionInfos SEQUENCE OF ProfessionInfo
+        *     }
+        * <p/>
+        *     NamingAuthority ::= SEQUENCE
+        *     {
+        *       namingAuthorityId OBJECT IDENTIFIER OPTIONAL,
+        *       namingAuthorityUrl IA5String OPTIONAL,
+        *       namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+        *     }
+        * <p/>
+        *     ProfessionInfo ::= SEQUENCE
+        *     {
+        *       namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+        *       professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+        *       professionOIDs SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+        *       registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+        *       addProfessionInfo OCTET STRING OPTIONAL
+        *     }
+        * </pre>
+        *
+        * @return an Asn1Object
+        */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector vec = new Asn1EncodableVector();
+            if (admissionAuthority != null)
+            {
+                vec.Add(admissionAuthority);
+            }
+            vec.Add(contentsOfAdmissions);
+            return new DerSequence(vec);
+        }
+
+        /**
+        * @return Returns the admissionAuthority if present, null otherwise.
+        */
+        public virtual GeneralName AdmissionAuthority
+        {
+            get { return admissionAuthority; }
+        }
+
+        /**
+        * @return Returns the contentsOfAdmissions.
+        */
+        public virtual Admissions[] GetContentsOfAdmissions()
+        {
+            Admissions[] result = new Admissions[contentsOfAdmissions.Count];
+
+            for (int i = 0; i < contentsOfAdmissions.Count; ++i)
+            {
+                result[i] = Admissions.GetInstance(contentsOfAdmissions[i]);
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Admissions.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Admissions.cs
new file mode 100644
index 0000000..40290c6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Admissions.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* An Admissions structure.
+	* <p/>
+	* <pre>
+	*            Admissions ::= SEQUENCE
+	*            {
+	*              admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+	*              namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+	*              professionInfos SEQUENCE OF ProfessionInfo
+	*            }
+	* <p/>
+	* </pre>
+	*
+	* @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+	* @see Org.BouncyCastle.Asn1.IsisMtt.X509.ProfessionInfo
+	* @see Org.BouncyCastle.Asn1.IsisMtt.X509.NamingAuthority
+	*/
+	public class Admissions
+		: Asn1Encodable
+	{
+		private readonly GeneralName		admissionAuthority;
+		private readonly NamingAuthority	namingAuthority;
+		private readonly Asn1Sequence		professionInfos;
+
+		public static Admissions GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is Admissions)
+			{
+				return (Admissions) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Admissions((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type ProcurationSyntax:
+		* <p/>
+		* <pre>
+		*            Admissions ::= SEQUENCE
+		*            {
+		*              admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+		*              namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+		*              professionInfos SEQUENCE OF ProfessionInfo
+		*            }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private Admissions(
+			Asn1Sequence seq)
+		{
+			if (seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+			Asn1Encodable o = (Asn1Encodable) e.Current;
+			if (o is Asn1TaggedObject)
+			{
+				switch (((Asn1TaggedObject)o).TagNo)
+				{
+					case 0:
+						admissionAuthority = GeneralName.GetInstance((Asn1TaggedObject)o, true);
+						break;
+					case 1:
+						namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true);
+						break;
+					default:
+						throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo);
+				}
+				e.MoveNext();
+				o = (Asn1Encodable) e.Current;
+			}
+			if (o is Asn1TaggedObject)
+			{
+				switch (((Asn1TaggedObject)o).TagNo)
+				{
+					case 1:
+						namingAuthority = NamingAuthority.GetInstance((Asn1TaggedObject)o, true);
+						break;
+					default:
+						throw new ArgumentException("Bad tag number: " + ((Asn1TaggedObject)o).TagNo);
+				}
+				e.MoveNext();
+				o = (Asn1Encodable) e.Current;
+			}
+			professionInfos = Asn1Sequence.GetInstance(o);
+			if (e.MoveNext())
+			{
+				throw new ArgumentException("Bad object encountered: " + e.Current.GetType().Name);
+			}
+		}
+
+		/**
+		* Constructor from a given details.
+		* <p/>
+		* Parameter <code>professionInfos</code> is mandatory.
+		*
+		* @param admissionAuthority The admission authority.
+		* @param namingAuthority    The naming authority.
+		* @param professionInfos    The profession infos.
+		*/
+		public Admissions(
+			GeneralName			admissionAuthority,
+			NamingAuthority		namingAuthority,
+			ProfessionInfo[]	professionInfos)
+		{
+			this.admissionAuthority = admissionAuthority;
+			this.namingAuthority = namingAuthority;
+			this.professionInfos = new DerSequence(professionInfos);
+		}
+
+		public virtual GeneralName AdmissionAuthority
+		{
+			get { return admissionAuthority; }
+		}
+
+		public virtual NamingAuthority NamingAuthority
+		{
+			get { return namingAuthority; }
+		}
+
+		public ProfessionInfo[] GetProfessionInfos()
+		{
+			ProfessionInfo[] infos = new ProfessionInfo[professionInfos.Count];
+			int count = 0;
+			foreach (Asn1Encodable ae in professionInfos)
+			{
+				infos[count++] = ProfessionInfo.GetInstance(ae);
+			}
+			return infos;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*       Admissions ::= SEQUENCE
+		*       {
+		*         admissionAuthority [0] EXPLICIT GeneralName OPTIONAL
+		*         namingAuthority [1] EXPLICIT NamingAuthority OPTIONAL
+		*         professionInfos SEQUENCE OF ProfessionInfo
+		*       }
+		* <p/>
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+
+			if (admissionAuthority != null)
+			{
+				vec.Add(new DerTaggedObject(true, 0, admissionAuthority));
+			}
+
+			if (namingAuthority != null)
+			{
+				vec.Add(new DerTaggedObject(true, 1, namingAuthority));
+			}
+
+			vec.Add(professionInfos);
+
+			return new DerSequence(vec);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/DeclarationOfMajority.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/DeclarationOfMajority.cs
new file mode 100644
index 0000000..dfac650
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/DeclarationOfMajority.cs
@@ -0,0 +1,170 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* A declaration of majority.
+	* <p/>
+	* <pre>
+	*           DeclarationOfMajoritySyntax ::= CHOICE
+	*           {
+	*             notYoungerThan [0] IMPLICIT INTEGER,
+	*             fullAgeAtCountry [1] IMPLICIT SEQUENCE
+	*             {
+	*               fullAge BOOLEAN DEFAULT TRUE,
+	*               country PrintableString (SIZE(2))
+	*             }
+	*             dateOfBirth [2] IMPLICIT GeneralizedTime
+	*           }
+	* </pre>
+	* <p/>
+	* fullAgeAtCountry indicates the majority of the owner with respect to the laws
+	* of a specific country.
+	*/
+	public class DeclarationOfMajority
+		: Asn1Encodable, IAsn1Choice
+	{
+		public enum Choice
+		{
+			NotYoungerThan = 0,
+			FullAgeAtCountry = 1,
+			DateOfBirth = 2
+		};
+
+		private readonly Asn1TaggedObject declaration;
+
+		public DeclarationOfMajority(
+			int notYoungerThan)
+		{
+			declaration = new DerTaggedObject(false, 0, new DerInteger(notYoungerThan));
+		}
+
+		public DeclarationOfMajority(
+			bool	fullAge,
+			string	country)
+		{
+			if (country.Length > 2)
+				throw new ArgumentException("country can only be 2 characters");
+
+			DerPrintableString countryString = new DerPrintableString(country, true);
+
+			DerSequence seq;
+			if (fullAge)
+			{
+				seq = new DerSequence(countryString);
+			}
+			else
+			{
+				seq = new DerSequence(DerBoolean.False, countryString);
+			}
+
+			this.declaration = new DerTaggedObject(false, 1, seq);
+		}
+
+		public DeclarationOfMajority(
+			DerGeneralizedTime dateOfBirth)
+		{
+			this.declaration = new DerTaggedObject(false, 2, dateOfBirth);
+		}
+
+		public static DeclarationOfMajority GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is DeclarationOfMajority)
+			{
+				return (DeclarationOfMajority) obj;
+			}
+
+			if (obj is Asn1TaggedObject)
+			{
+				return new DeclarationOfMajority((Asn1TaggedObject) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private DeclarationOfMajority(
+			Asn1TaggedObject o)
+		{
+			if (o.TagNo > 2)
+				throw new ArgumentException("Bad tag number: " + o.TagNo);
+
+			this.declaration = o;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*           DeclarationOfMajoritySyntax ::= CHOICE
+		*           {
+		*             notYoungerThan [0] IMPLICIT INTEGER,
+		*             fullAgeAtCountry [1] IMPLICIT SEQUENCE
+		*             {
+		*               fullAge BOOLEAN DEFAULT TRUE,
+		*               country PrintableString (SIZE(2))
+		*             }
+		*             dateOfBirth [2] IMPLICIT GeneralizedTime
+		*           }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			return declaration;
+		}
+
+		public Choice Type
+		{
+			get { return (Choice) declaration.TagNo; }
+		}
+
+		/**
+		* @return notYoungerThan if that's what we are, -1 otherwise
+		*/
+		public virtual int NotYoungerThan
+		{
+			get
+			{
+				switch ((Choice) declaration.TagNo)
+				{
+					case Choice.NotYoungerThan:
+						return DerInteger.GetInstance(declaration, false).Value.IntValue;
+					default:
+						return -1;
+				}
+			}
+		}
+
+		public virtual Asn1Sequence FullAgeAtCountry
+		{
+			get
+			{
+				switch ((Choice) declaration.TagNo)
+				{
+					case Choice.FullAgeAtCountry:
+						return Asn1Sequence.GetInstance(declaration, false);
+					default:
+						return null;
+				}
+			}
+		}
+
+		public virtual DerGeneralizedTime DateOfBirth
+		{
+			get
+			{
+				switch ((Choice) declaration.TagNo)
+				{
+					case Choice.DateOfBirth:
+						return DerGeneralizedTime.GetInstance(declaration, false);
+					default:
+						return null;
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/MonetaryLimit.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/MonetaryLimit.cs
new file mode 100644
index 0000000..80b6b68
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/MonetaryLimit.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Monetary limit for transactions. The QcEuMonetaryLimit QC statement MUST be
+	* used in new certificates in place of the extension/attribute MonetaryLimit
+	* since January 1, 2004. For the sake of backward compatibility with
+	* certificates already in use, components SHOULD support MonetaryLimit (as well
+	* as QcEuLimitValue).
+	* <p/>
+	* Indicates a monetary limit within which the certificate holder is authorized
+	* to act. (This value DOES NOT express a limit on the liability of the
+	* certification authority).
+	* <p/>
+	* <pre>
+	*    MonetaryLimitSyntax ::= SEQUENCE
+	*    {
+	*      currency PrintableString (SIZE(3)),
+	*      amount INTEGER,
+	*      exponent INTEGER
+	*    }
+	* </pre>
+	* <p/>
+	* currency must be the ISO code.
+	* <p/>
+	* value = amount�10*exponent
+	*/
+	public class MonetaryLimit
+		: Asn1Encodable
+	{
+		private readonly DerPrintableString	currency;
+		private readonly DerInteger			amount;
+		private readonly DerInteger			exponent;
+
+		public static MonetaryLimit GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is MonetaryLimit)
+			{
+				return (MonetaryLimit) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new MonetaryLimit(Asn1Sequence.GetInstance(obj));
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private MonetaryLimit(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			currency = DerPrintableString.GetInstance(seq[0]);
+			amount = DerInteger.GetInstance(seq[1]);
+			exponent = DerInteger.GetInstance(seq[2]);
+		}
+
+		/**
+		* Constructor from a given details.
+		* <p/>
+		* <p/>
+		* value = amount�10^exponent
+		*
+		* @param currency The currency. Must be the ISO code.
+		* @param amount   The amount
+		* @param exponent The exponent
+		*/
+		public MonetaryLimit(
+			string	currency,
+			int		amount,
+			int		exponent)
+		{
+			this.currency = new DerPrintableString(currency, true);
+			this.amount = new DerInteger(amount);
+			this.exponent = new DerInteger(exponent);
+		}
+
+		public virtual string Currency
+		{
+			get { return currency.GetString(); }
+		}
+
+		public virtual BigInteger Amount
+		{
+			get { return amount.Value; }
+		}
+
+		public virtual BigInteger Exponent
+		{
+			get { return exponent.Value; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*    MonetaryLimitSyntax ::= SEQUENCE
+		*    {
+		*      currency PrintableString (SIZE(3)),
+		*      amount INTEGER,
+		*      exponent INTEGER
+		*    }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(currency, amount, exponent);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/NamingAuthority.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/NamingAuthority.cs
new file mode 100644
index 0000000..4262fd0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/NamingAuthority.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Names of authorities which are responsible for the administration of title
+	* registers.
+	* 
+	* <pre>
+	*             NamingAuthority ::= SEQUENCE 
+	*             {
+	*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+	*               namingAuthorityUrl IA5String OPTIONAL,
+	*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+	*             }
+	* </pre>
+	* @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+	* 
+	*/
+	public class NamingAuthority
+		: Asn1Encodable
+	{
+		/**
+		* Profession OIDs should always be defined under the OID branch of the
+		* responsible naming authority. At the time of this writing, the work group
+		* �Recht, Wirtschaft, Steuern� (�Law, Economy, Taxes�) is registered as the
+		* first naming authority under the OID id-isismtt-at-namingAuthorities.
+		*/
+		public static readonly DerObjectIdentifier IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern
+			= new DerObjectIdentifier(IsisMttObjectIdentifiers.IdIsisMttATNamingAuthorities + ".1");
+
+		private readonly DerObjectIdentifier	namingAuthorityID;
+		private readonly string					namingAuthorityUrl;
+		private readonly DirectoryString		namingAuthorityText;
+
+		public static NamingAuthority GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is NamingAuthority)
+			{
+				return (NamingAuthority) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new NamingAuthority((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static NamingAuthority GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* <p/>
+		* <pre>
+		*             NamingAuthority ::= SEQUENCE
+		*             {
+		*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+		*               namingAuthorityUrl IA5String OPTIONAL,
+		*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+		*             }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private NamingAuthority(
+			Asn1Sequence seq)
+		{
+			if (seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			IEnumerator e = seq.GetEnumerator();
+
+			if (e.MoveNext())
+			{
+				Asn1Encodable o = (Asn1Encodable) e.Current;
+				if (o is DerObjectIdentifier)
+				{
+					namingAuthorityID = (DerObjectIdentifier) o;
+				}
+				else if (o is DerIA5String)
+				{
+					namingAuthorityUrl = DerIA5String.GetInstance(o).GetString();
+				}
+				else if (o is IAsn1String)
+				{
+					namingAuthorityText = DirectoryString.GetInstance(o);
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+
+			if (e.MoveNext())
+			{
+				Asn1Encodable o = (Asn1Encodable) e.Current;
+				if (o is DerIA5String)
+				{
+					namingAuthorityUrl = DerIA5String.GetInstance(o).GetString();
+				}
+				else if (o is IAsn1String)
+				{
+					namingAuthorityText = DirectoryString.GetInstance(o);
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+
+			if (e.MoveNext())
+			{
+				Asn1Encodable o = (Asn1Encodable) e.Current;
+				if (o is IAsn1String)
+				{
+					namingAuthorityText = DirectoryString.GetInstance(o);
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+		}
+
+		/**
+		* @return Returns the namingAuthorityID.
+		*/
+		public virtual DerObjectIdentifier NamingAuthorityID
+		{
+			get { return namingAuthorityID; }
+		}
+
+		/**
+		* @return Returns the namingAuthorityText.
+		*/
+		public virtual DirectoryString NamingAuthorityText
+		{
+			get { return namingAuthorityText; }
+		}
+
+		/**
+		* @return Returns the namingAuthorityUrl.
+		*/
+		public virtual string NamingAuthorityUrl
+		{
+			get { return namingAuthorityUrl; }
+		}
+
+		/**
+		* Constructor from given details.
+		* <p/>
+		* All parameters can be combined.
+		*
+		* @param namingAuthorityID   ObjectIdentifier for naming authority.
+		* @param namingAuthorityUrl  URL for naming authority.
+		* @param namingAuthorityText Textual representation of naming authority.
+		*/
+		public NamingAuthority(
+			DerObjectIdentifier	namingAuthorityID,
+			string				namingAuthorityUrl,
+			DirectoryString		namingAuthorityText)
+		{
+			this.namingAuthorityID = namingAuthorityID;
+			this.namingAuthorityUrl = namingAuthorityUrl;
+			this.namingAuthorityText = namingAuthorityText;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*             NamingAuthority ::= SEQUENCE
+		*             {
+		*               namingAuthorityID OBJECT IDENTIFIER OPTIONAL,
+		*               namingAuthorityUrl IA5String OPTIONAL,
+		*               namingAuthorityText DirectoryString(SIZE(1..128)) OPTIONAL
+		*             }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+			if (namingAuthorityID != null)
+			{
+				vec.Add(namingAuthorityID);
+			}
+			if (namingAuthorityUrl != null)
+			{
+				vec.Add(new DerIA5String(namingAuthorityUrl, true));
+			}
+			if (namingAuthorityText != null)
+			{
+				vec.Add(namingAuthorityText);
+			}
+			return new DerSequence(vec);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProcurationSyntax.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProcurationSyntax.cs
new file mode 100644
index 0000000..a25df22
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProcurationSyntax.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Attribute to indicate that the certificate holder may sign in the name of a
+	* third person.
+	* <p>
+	* ISIS-MTT PROFILE: The corresponding ProcurationSyntax contains either the
+	* name of the person who is represented (subcomponent thirdPerson) or a
+	* reference to his/her base certificate (in the component signingFor,
+	* subcomponent certRef), furthermore the optional components country and
+	* typeSubstitution to indicate the country whose laws apply, and respectively
+	* the type of procuration (e.g. manager, procuration, custody).
+	* </p>
+	* <p>
+	* ISIS-MTT PROFILE: The GeneralName MUST be of type directoryName and MAY only
+	* contain: - RFC3039 attributes, except pseudonym (countryName, commonName,
+	* surname, givenName, serialNumber, organizationName, organizationalUnitName,
+	* stateOrProvincename, localityName, postalAddress) and - SubjectDirectoryName
+	* attributes (title, dateOfBirth, placeOfBirth, gender, countryOfCitizenship,
+	* countryOfResidence and NameAtBirth).
+	* </p>
+	* <pre>
+	*               ProcurationSyntax ::= SEQUENCE {
+	*                 country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+	*                 typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+	*                 signingFor [3] EXPLICIT SigningFor 
+	*               }
+	*               
+	*               SigningFor ::= CHOICE 
+	*               { 
+	*                 thirdPerson GeneralName,
+	*                 certRef IssuerSerial 
+	*               }
+	* </pre>
+	* 
+	*/
+	public class ProcurationSyntax
+		: Asn1Encodable
+	{
+		private readonly string				country;
+		private readonly DirectoryString	typeOfSubstitution;
+		private readonly GeneralName		thirdPerson;
+		private readonly IssuerSerial		certRef;
+
+		public static ProcurationSyntax GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ProcurationSyntax)
+			{
+				return (ProcurationSyntax) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ProcurationSyntax((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type ProcurationSyntax:
+		* <p/>
+		* <pre>
+		*               ProcurationSyntax ::= SEQUENCE {
+		*                 country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+		*                 typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+		*                 signingFor [3] EXPLICIT SigningFor
+		*               }
+		* <p/>
+		*               SigningFor ::= CHOICE
+		*               {
+		*                 thirdPerson GeneralName,
+		*                 certRef IssuerSerial
+		*               }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private ProcurationSyntax(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			IEnumerator e = seq.GetEnumerator();
+
+			while (e.MoveNext())
+			{
+				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current);
+				switch (o.TagNo)
+				{
+					case 1:
+						country = DerPrintableString.GetInstance(o, true).GetString();
+						break;
+					case 2:
+						typeOfSubstitution = DirectoryString.GetInstance(o, true);
+						break;
+					case 3:
+						Asn1Object signingFor = o.GetObject();
+						if (signingFor is Asn1TaggedObject)
+						{
+							thirdPerson = GeneralName.GetInstance(signingFor);
+						}
+						else
+						{
+							certRef = IssuerSerial.GetInstance(signingFor);
+						}
+						break;
+					default:
+						throw new ArgumentException("Bad tag number: " + o.TagNo);
+				}
+			}
+		}
+
+		/**
+		* Constructor from a given details.
+		* <p/>
+		* <p/>
+		* Either <code>generalName</code> or <code>certRef</code> MUST be
+		* <code>null</code>.
+		*
+		* @param country            The country code whose laws apply.
+		* @param typeOfSubstitution The type of procuration.
+		* @param certRef            Reference to certificate of the person who is represented.
+		*/
+		public ProcurationSyntax(
+			string			country,
+			DirectoryString	typeOfSubstitution,
+			IssuerSerial	certRef)
+		{
+			this.country = country;
+			this.typeOfSubstitution = typeOfSubstitution;
+			this.thirdPerson = null;
+			this.certRef = certRef;
+		}
+
+		/**
+		 * Constructor from a given details.
+		 * <p/>
+		 * <p/>
+		 * Either <code>generalName</code> or <code>certRef</code> MUST be
+		 * <code>null</code>.
+		 *
+		 * @param country            The country code whose laws apply.
+		 * @param typeOfSubstitution The type of procuration.
+		 * @param thirdPerson        The GeneralName of the person who is represented.
+		 */
+		public ProcurationSyntax(
+			string			country,
+			DirectoryString	typeOfSubstitution,
+			GeneralName		thirdPerson)
+		{
+			this.country = country;
+			this.typeOfSubstitution = typeOfSubstitution;
+			this.thirdPerson = thirdPerson;
+			this.certRef = null;
+		}
+
+		public virtual string Country
+		{
+			get { return country; }
+		}
+
+		public virtual DirectoryString TypeOfSubstitution
+		{
+			get { return typeOfSubstitution; }
+		}
+
+		public virtual GeneralName ThirdPerson
+		{
+			get { return thirdPerson; }
+		}
+
+		public virtual IssuerSerial CertRef
+		{
+			get { return certRef; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*               ProcurationSyntax ::= SEQUENCE {
+		*                 country [1] EXPLICIT PrintableString(SIZE(2)) OPTIONAL,
+		*                 typeOfSubstitution [2] EXPLICIT DirectoryString (SIZE(1..128)) OPTIONAL,
+		*                 signingFor [3] EXPLICIT SigningFor
+		*               }
+		* <p/>
+		*               SigningFor ::= CHOICE
+		*               {
+		*                 thirdPerson GeneralName,
+		*                 certRef IssuerSerial
+		*               }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+			if (country != null)
+			{
+				vec.Add(new DerTaggedObject(true, 1, new DerPrintableString(country, true)));
+			}
+			if (typeOfSubstitution != null)
+			{
+				vec.Add(new DerTaggedObject(true, 2, typeOfSubstitution));
+			}
+			if (thirdPerson != null)
+			{
+				vec.Add(new DerTaggedObject(true, 3, thirdPerson));
+			}
+			else
+			{
+				vec.Add(new DerTaggedObject(true, 3, certRef));
+			}
+
+			return new DerSequence(vec);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProfessionInfo.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProfessionInfo.cs
new file mode 100644
index 0000000..3bad2cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/ProfessionInfo.cs
@@ -0,0 +1,386 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Professions, specializations, disciplines, fields of activity, etc.
+	* 
+	* <pre>
+	*               ProfessionInfo ::= SEQUENCE 
+	*               {
+	*                 namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+	*                 professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+	*                 professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+	*                 registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+	*                 addProfessionInfo OCTET STRING OPTIONAL 
+	*               }
+	* </pre>
+	* 
+	* @see Org.BouncyCastle.Asn1.IsisMtt.X509.AdmissionSyntax
+	*/
+	public class ProfessionInfo
+		: Asn1Encodable
+	{
+		/**
+		* Rechtsanw�ltin
+		*/
+		public static readonly DerObjectIdentifier Rechtsanwltin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".1");
+
+		/**
+		* Rechtsanwalt
+		*/
+		public static readonly DerObjectIdentifier Rechtsanwalt = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".2");
+
+		/**
+		* Rechtsbeistand
+		*/
+		public static readonly DerObjectIdentifier Rechtsbeistand = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".3");
+
+		/**
+		* Steuerberaterin
+		*/
+		public static readonly DerObjectIdentifier Steuerberaterin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".4");
+
+		/**
+		* Steuerberater
+		*/
+		public static readonly DerObjectIdentifier Steuerberater = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".5");
+
+		/**
+		* Steuerbevollm�chtigte
+		*/
+		public static readonly DerObjectIdentifier Steuerbevollmchtigte = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".6");
+
+		/**
+		* Steuerbevollm�chtigter
+		*/
+		public static readonly DerObjectIdentifier Steuerbevollmchtigter = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".7");
+
+		/**
+		* Notarin
+		*/
+		public static readonly DerObjectIdentifier Notarin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".8");
+
+		/**
+		* Notar
+		*/
+		public static readonly DerObjectIdentifier Notar = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".9");
+
+		/**
+		* Notarvertreterin
+		*/
+		public static readonly DerObjectIdentifier Notarvertreterin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".10");
+
+		/**
+		* Notarvertreter
+		*/
+		public static readonly DerObjectIdentifier Notarvertreter = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".11");
+
+		/**
+		* Notariatsverwalterin
+		*/
+		public static readonly DerObjectIdentifier Notariatsverwalterin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".12");
+
+		/**
+		* Notariatsverwalter
+		*/
+		public static readonly DerObjectIdentifier Notariatsverwalter = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".13");
+
+		/**
+		* Wirtschaftspr�ferin
+		*/
+		public static readonly DerObjectIdentifier Wirtschaftsprferin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".14");
+
+		/**
+		* Wirtschaftspr�fer
+		*/
+		public static readonly DerObjectIdentifier Wirtschaftsprfer = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".15");
+
+		/**
+		* Vereidigte Buchpr�ferin
+		*/
+		public static readonly DerObjectIdentifier VereidigteBuchprferin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".16");
+
+		/**
+		* Vereidigter Buchpr�fer
+		*/
+		public static readonly DerObjectIdentifier VereidigterBuchprfer = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".17");
+
+		/**
+		* Patentanw�ltin
+		*/
+		public static readonly DerObjectIdentifier Patentanwltin = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".18");
+
+		/**
+		* Patentanwalt
+		*/
+		public static readonly DerObjectIdentifier Patentanwalt = new DerObjectIdentifier(
+			NamingAuthority.IdIsisMttATNamingAuthoritiesRechtWirtschaftSteuern + ".19");
+
+		private readonly NamingAuthority	namingAuthority;
+		private readonly Asn1Sequence		professionItems;
+		private readonly Asn1Sequence		professionOids;
+		private readonly string				registrationNumber;
+		private readonly Asn1OctetString	addProfessionInfo;
+
+		public static ProfessionInfo GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ProfessionInfo)
+			{
+				return (ProfessionInfo) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ProfessionInfo((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* <p/>
+		* <pre>
+		*               ProfessionInfo ::= SEQUENCE
+		*               {
+		*                 namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+		*                 professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+		*                 professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+		*                 registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+		*                 addProfessionInfo OCTET STRING OPTIONAL
+		*               }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private ProfessionInfo(
+			Asn1Sequence seq)
+		{
+			if (seq.Count > 5)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+			Asn1Encodable o = (Asn1Encodable) e.Current;
+
+			if (o is Asn1TaggedObject)
+			{
+				Asn1TaggedObject ato = (Asn1TaggedObject) o;
+				if (ato.TagNo != 0)
+					throw new ArgumentException("Bad tag number: " + ato.TagNo);
+
+				namingAuthority = NamingAuthority.GetInstance(ato, true);
+				e.MoveNext();
+				o = (Asn1Encodable) e.Current;
+			}
+
+			professionItems = Asn1Sequence.GetInstance(o);
+
+			if (e.MoveNext())
+			{
+				o = (Asn1Encodable) e.Current;
+				if (o is Asn1Sequence)
+				{
+					professionOids = Asn1Sequence.GetInstance(o);
+				}
+				else if (o is DerPrintableString)
+				{
+					registrationNumber = DerPrintableString.GetInstance(o).GetString();
+				}
+				else if (o is Asn1OctetString)
+				{
+					addProfessionInfo = Asn1OctetString.GetInstance(o);
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+
+			if (e.MoveNext())
+			{
+				o = (Asn1Encodable) e.Current;
+				if (o is DerPrintableString)
+				{
+					registrationNumber = DerPrintableString.GetInstance(o).GetString();
+				}
+				else if (o is DerOctetString)
+				{
+					addProfessionInfo = (DerOctetString) o;
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+
+			if (e.MoveNext())
+			{
+				o = (Asn1Encodable) e.Current;
+				if (o is DerOctetString)
+				{
+					addProfessionInfo = (DerOctetString) o;
+				}
+				else
+				{
+					throw new ArgumentException("Bad object encountered: " + o.GetType().Name);
+				}
+			}
+		}
+
+		/**
+		* Constructor from given details.
+		* <p/>
+		* <code>professionItems</code> is mandatory, all other parameters are
+		* optional.
+		*
+		* @param namingAuthority    The naming authority.
+		* @param professionItems    Directory strings of the profession.
+		* @param professionOids     DERObjectIdentfier objects for the
+		*                           profession.
+		* @param registrationNumber Registration number.
+		* @param addProfessionInfo  Additional infos in encoded form.
+		*/
+		public ProfessionInfo(
+			NamingAuthority			namingAuthority,
+			DirectoryString[]		professionItems,
+			DerObjectIdentifier[]	professionOids,
+			string					registrationNumber,
+			Asn1OctetString			addProfessionInfo)
+		{
+			this.namingAuthority = namingAuthority;
+			this.professionItems = new DerSequence(professionItems);
+			if (professionOids != null)
+			{
+				this.professionOids = new DerSequence(professionOids);
+			}
+			this.registrationNumber = registrationNumber;
+			this.addProfessionInfo = addProfessionInfo;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*               ProfessionInfo ::= SEQUENCE
+		*               {
+		*                 namingAuthority [0] EXPLICIT NamingAuthority OPTIONAL,
+		*                 professionItems SEQUENCE OF DirectoryString (SIZE(1..128)),
+		*                 professionOids SEQUENCE OF OBJECT IDENTIFIER OPTIONAL,
+		*                 registrationNumber PrintableString(SIZE(1..128)) OPTIONAL,
+		*                 addProfessionInfo OCTET STRING OPTIONAL
+		*               }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+			if (namingAuthority != null)
+			{
+				vec.Add(new DerTaggedObject(true, 0, namingAuthority));
+			}
+			vec.Add(professionItems);
+			if (professionOids != null)
+			{
+				vec.Add(professionOids);
+			}
+			if (registrationNumber != null)
+			{
+				vec.Add(new DerPrintableString(registrationNumber, true));
+			}
+			if (addProfessionInfo != null)
+			{
+				vec.Add(addProfessionInfo);
+			}
+			return new DerSequence(vec);
+		}
+
+		/**
+		* @return Returns the addProfessionInfo.
+		*/
+		public virtual Asn1OctetString AddProfessionInfo
+		{
+			get { return addProfessionInfo; }
+		}
+
+		/**
+		* @return Returns the namingAuthority.
+		*/
+		public virtual NamingAuthority NamingAuthority
+		{
+			get { return namingAuthority; }
+		}
+
+		/**
+		* @return Returns the professionItems.
+		*/
+		public virtual DirectoryString[] GetProfessionItems()
+		{
+			DirectoryString[] result = new DirectoryString[professionItems.Count];
+
+			for (int i = 0; i < professionItems.Count; ++i)
+			{
+				result[i] = DirectoryString.GetInstance(professionItems[i]);
+			}
+
+			return result;
+		}
+
+		/**
+		* @return Returns the professionOids.
+		*/
+		public virtual DerObjectIdentifier[] GetProfessionOids()
+		{
+			if (professionOids == null)
+			{
+				return new DerObjectIdentifier[0];
+			}
+
+			DerObjectIdentifier[] result = new DerObjectIdentifier[professionOids.Count];
+
+			for (int i = 0; i < professionOids.Count; ++i)
+			{
+				result[i] = DerObjectIdentifier.GetInstance(professionOids[i]);
+			}
+
+			return result;
+		}
+
+		/**
+		* @return Returns the registrationNumber.
+		*/
+		public virtual string RegistrationNumber
+		{
+			get { return registrationNumber; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Restriction.cs b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Restriction.cs
new file mode 100644
index 0000000..c977669
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/isismtt/x509/Restriction.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.IsisMtt.X509
+{
+	/**
+	* Some other restriction regarding the usage of this certificate.
+	* <p/>
+	* <pre>
+	*  RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+	* </pre>
+	*/
+	public class Restriction
+		: Asn1Encodable
+	{
+		private readonly DirectoryString restriction;
+
+		public static Restriction GetInstance(
+			object obj)
+		{
+			if (obj is Restriction)
+				return (Restriction) obj;
+
+			if (obj is IAsn1String)
+				return new Restriction(DirectoryString.GetInstance(obj));
+
+			throw new ArgumentException("Unknown object in GetInstance: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from DirectoryString.
+		* <p/>
+		* The DirectoryString is of type RestrictionSyntax:
+		* <p/>
+		* <pre>
+		*      RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		* </pre>
+		*
+		* @param restriction A IAsn1String.
+		*/
+		private Restriction(
+			DirectoryString restriction)
+		{
+			this.restriction = restriction;
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param restriction The description of the restriction.
+		*/
+		public Restriction(
+			string restriction)
+		{
+			this.restriction = new DirectoryString(restriction);
+		}
+
+		public virtual DirectoryString RestrictionString
+		{
+			get { return restriction; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*      RestrictionSyntax ::= DirectoryString (SIZE(1..1024))
+		* <p/>
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			return restriction.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/kisa/KISAObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/kisa/KISAObjectIdentifiers.cs
new file mode 100644
index 0000000..05351ec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/kisa/KISAObjectIdentifiers.cs
@@ -0,0 +1,8 @@
+namespace Org.BouncyCastle.Asn1.Kisa
+{
+	public abstract class KisaObjectIdentifiers
+	{
+		public static readonly DerObjectIdentifier IdSeedCbc = new DerObjectIdentifier("1.2.410.200004.1.4");
+		public static readonly DerObjectIdentifier IdNpkiAppCmsSeedWrap = new DerObjectIdentifier("1.2.410.200004.7.1.1.1");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs
new file mode 100644
index 0000000..b8aba7e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/microsoft/MicrosoftObjectIdentifiers.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Microsoft
+{
+	public abstract class MicrosoftObjectIdentifiers
+	{
+		//
+		// Microsoft
+		//       iso(1) identified-organization(3) dod(6) internet(1) private(4) enterprise(1) Microsoft(311)
+		//
+		public static readonly DerObjectIdentifier Microsoft               = new DerObjectIdentifier("1.3.6.1.4.1.311");
+		public static readonly DerObjectIdentifier MicrosoftCertTemplateV1 = new DerObjectIdentifier(Microsoft + ".20.2");
+		public static readonly DerObjectIdentifier MicrosoftCAVersion      = new DerObjectIdentifier(Microsoft + ".21.1");
+		public static readonly DerObjectIdentifier MicrosoftPrevCACertHash = new DerObjectIdentifier(Microsoft + ".21.2");
+		public static readonly DerObjectIdentifier MicrosoftCertTemplateV2 = new DerObjectIdentifier(Microsoft + ".21.7");
+		public static readonly DerObjectIdentifier MicrosoftAppPolicies    = new DerObjectIdentifier(Microsoft + ".21.10");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/CAST5CBCParameters.cs b/BouncyCastle.AxCrypt/src/asn1/misc/CAST5CBCParameters.cs
new file mode 100644
index 0000000..51fd660
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/CAST5CBCParameters.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    public class Cast5CbcParameters
+        : Asn1Encodable
+    {
+        private readonly DerInteger keyLength;
+        private readonly Asn1OctetString iv;
+
+		public static Cast5CbcParameters GetInstance(
+            object o)
+        {
+            if (o is Cast5CbcParameters)
+            {
+                return (Cast5CbcParameters) o;
+            }
+
+			if (o is Asn1Sequence)
+            {
+                return new Cast5CbcParameters((Asn1Sequence) o);
+            }
+
+			throw new ArgumentException("unknown object in Cast5CbcParameters factory");
+        }
+
+		public Cast5CbcParameters(
+            byte[]	iv,
+            int		keyLength)
+        {
+            this.iv = new DerOctetString(iv);
+            this.keyLength = new DerInteger(keyLength);
+        }
+
+		private Cast5CbcParameters(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			iv = (Asn1OctetString) seq[0];
+            keyLength = (DerInteger) seq[1];
+        }
+
+		public byte[] GetIV()
+        {
+			return Arrays.Clone(iv.GetOctets());
+		}
+
+		public int KeyLength
+		{
+			get { return keyLength.Value.IntValue; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * cast5CBCParameters ::= Sequence {
+         *                           iv         OCTET STRING DEFAULT 0,
+         *                                  -- Initialization vector
+         *                           keyLength  Integer
+         *                                  -- Key length, in bits
+         *                      }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(iv, keyLength);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/IDEACBCPar.cs b/BouncyCastle.AxCrypt/src/asn1/misc/IDEACBCPar.cs
new file mode 100644
index 0000000..72a60b9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/IDEACBCPar.cs
@@ -0,0 +1,68 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    public class IdeaCbcPar
+        : Asn1Encodable
+    {
+        internal Asn1OctetString iv;
+
+		public static IdeaCbcPar GetInstance(
+            object o)
+        {
+            if (o is IdeaCbcPar)
+            {
+                return (IdeaCbcPar) o;
+            }
+
+			if (o is Asn1Sequence)
+            {
+                return new IdeaCbcPar((Asn1Sequence) o);
+            }
+
+			throw new ArgumentException("unknown object in IDEACBCPar factory");
+        }
+
+		public IdeaCbcPar(
+            byte[] iv)
+        {
+            this.iv = new DerOctetString(iv);
+        }
+
+		private IdeaCbcPar(
+            Asn1Sequence seq)
+        {
+			if (seq.Count == 1)
+			{
+				iv = (Asn1OctetString) seq[0];
+			}
+        }
+
+		public byte[] GetIV()
+        {
+			return iv == null ? null : iv.GetOctets();
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * IDEA-CBCPar ::= Sequence {
+         *                      iv    OCTET STRING OPTIONAL -- exactly 8 octets
+         *                  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (iv != null)
+            {
+                v.Add(iv);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/MiscObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/misc/MiscObjectIdentifiers.cs
new file mode 100644
index 0000000..01004d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/MiscObjectIdentifiers.cs
@@ -0,0 +1,48 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    public abstract class MiscObjectIdentifiers
+    {
+        //
+        // Netscape
+        //       iso/itu(2) joint-assign(16) us(840) uscompany(1) Netscape(113730) cert-extensions(1) }
+        //
+        public static readonly DerObjectIdentifier Netscape                = new DerObjectIdentifier("2.16.840.1.113730.1");
+        public static readonly DerObjectIdentifier NetscapeCertType        = new DerObjectIdentifier(Netscape + ".1");
+        public static readonly DerObjectIdentifier NetscapeBaseUrl         = new DerObjectIdentifier(Netscape + ".2");
+        public static readonly DerObjectIdentifier NetscapeRevocationUrl   = new DerObjectIdentifier(Netscape + ".3");
+        public static readonly DerObjectIdentifier NetscapeCARevocationUrl = new DerObjectIdentifier(Netscape + ".4");
+        public static readonly DerObjectIdentifier NetscapeRenewalUrl      = new DerObjectIdentifier(Netscape + ".7");
+        public static readonly DerObjectIdentifier NetscapeCAPolicyUrl     = new DerObjectIdentifier(Netscape + ".8");
+        public static readonly DerObjectIdentifier NetscapeSslServerName   = new DerObjectIdentifier(Netscape + ".12");
+        public static readonly DerObjectIdentifier NetscapeCertComment     = new DerObjectIdentifier(Netscape + ".13");
+        //
+        // Verisign
+        //       iso/itu(2) joint-assign(16) us(840) uscompany(1) verisign(113733) cert-extensions(1) }
+        //
+        internal const string Verisign = "2.16.840.1.113733.1";
+
+		//
+        // CZAG - country, zip, age, and gender
+        //
+        public static readonly DerObjectIdentifier VerisignCzagExtension = new DerObjectIdentifier(Verisign + ".6.3");
+
+		// D&B D-U-N-S number
+		public static readonly DerObjectIdentifier VerisignDnbDunsNumber = new DerObjectIdentifier(Verisign + ".6.15");
+
+		//
+		// Novell
+		//       iso/itu(2) country(16) us(840) organization(1) novell(113719)
+		//
+		public static readonly string				Novell					= "2.16.840.1.113719";
+		public static readonly DerObjectIdentifier	NovellSecurityAttribs	= new DerObjectIdentifier(Novell + ".1.9.4.1");
+
+		//
+		// Entrust
+		//       iso(1) member-body(16) us(840) nortelnetworks(113533) entrust(7)
+		//
+		public static readonly string				Entrust					= "1.2.840.113533.7";
+		public static readonly DerObjectIdentifier	EntrustVersionExtension = new DerObjectIdentifier(Entrust + ".65.0");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeCertType.cs b/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeCertType.cs
new file mode 100644
index 0000000..d5db652
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeCertType.cs
@@ -0,0 +1,54 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    /**
+     * The NetscapeCertType object.
+     * <pre>
+     *    NetscapeCertType ::= BIT STRING {
+     *         SSLClient               (0),
+     *         SSLServer               (1),
+     *         S/MIME                  (2),
+     *         Object Signing          (3),
+     *         Reserved                (4),
+     *         SSL CA                  (5),
+     *         S/MIME CA               (6),
+     *         Object Signing CA       (7) }
+     * </pre>
+     */
+    public class NetscapeCertType
+        : DerBitString
+    {
+        public const int SslClient        = (1 << 7);
+        public const int SslServer        = (1 << 6);
+        public const int Smime            = (1 << 5);
+        public const int ObjectSigning    = (1 << 4);
+        public const int Reserved         = (1 << 3);
+        public const int SslCA            = (1 << 2);
+        public const int SmimeCA          = (1 << 1);
+        public const int ObjectSigningCA  = (1 << 0);
+
+		/**
+         * Basic constructor.
+         *
+         * @param usage - the bitwise OR of the Key Usage flags giving the
+         * allowed uses for the key.
+         * e.g. (X509NetscapeCertType.sslCA | X509NetscapeCertType.smimeCA)
+         */
+        public NetscapeCertType(int usage)
+			: base(GetBytes(usage), GetPadBits(usage))
+        {
+        }
+
+		public NetscapeCertType(DerBitString usage)
+			: base(usage.GetBytes(), usage.PadBits)
+        {
+        }
+
+		public override string ToString()
+        {
+			byte[] data = GetBytes();
+			return "NetscapeCertType: 0x" + (data[0] & 0xff).ToString("X");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeRevocationURL.cs b/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeRevocationURL.cs
new file mode 100644
index 0000000..6cac031
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/NetscapeRevocationURL.cs
@@ -0,0 +1,18 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    public class NetscapeRevocationUrl
+        : DerIA5String
+    {
+        public NetscapeRevocationUrl(DerIA5String str)
+			: base(str.GetString())
+        {
+        }
+
+        public override string ToString()
+        {
+            return "NetscapeRevocationUrl: " + this.GetString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/misc/VerisignCzagExtension.cs b/BouncyCastle.AxCrypt/src/asn1/misc/VerisignCzagExtension.cs
new file mode 100644
index 0000000..1c3054b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/misc/VerisignCzagExtension.cs
@@ -0,0 +1,18 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Misc
+{
+    public class VerisignCzagExtension
+        : DerIA5String
+    {
+        public VerisignCzagExtension(DerIA5String str)
+			: base(str.GetString())
+        {
+        }
+
+        public override string ToString()
+        {
+            return "VerisignCzagExtension: " + this.GetString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/mozilla/PublicKeyAndChallenge.cs b/BouncyCastle.AxCrypt/src/asn1/mozilla/PublicKeyAndChallenge.cs
new file mode 100644
index 0000000..1e08b80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/mozilla/PublicKeyAndChallenge.cs
@@ -0,0 +1,67 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Mozilla
+{
+	/**
+	 * This is designed to parse
+	 * the PublicKeyAndChallenge created by the KEYGEN tag included by
+	 * Mozilla based browsers.
+	 *  <pre>
+	 *  PublicKeyAndChallenge ::= SEQUENCE {
+	 *    spki SubjectPublicKeyInfo,
+	 *    challenge IA5STRING
+	 *  }
+	 *
+	 *  </pre>
+	 */
+	public class PublicKeyAndChallenge
+		: Asn1Encodable
+	{
+		private Asn1Sequence			pkacSeq;
+		private SubjectPublicKeyInfo	spki;
+		private DerIA5String			challenge;
+
+		public static PublicKeyAndChallenge GetInstance(
+			object obj)
+		{
+			if (obj is PublicKeyAndChallenge)
+			{
+				return (PublicKeyAndChallenge) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new PublicKeyAndChallenge((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException(
+				"unknown object in 'PublicKeyAndChallenge' factory : "
+				+ obj.GetType().Name + ".");
+		}
+
+		public PublicKeyAndChallenge(
+			Asn1Sequence seq)
+		{
+			pkacSeq = seq;
+			spki = SubjectPublicKeyInfo.GetInstance(seq[0]);
+			challenge = DerIA5String.GetInstance(seq[1]);
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return pkacSeq;
+		}
+
+		public SubjectPublicKeyInfo SubjectPublicKeyInfo
+		{
+			get { return spki; }
+		}
+
+		public DerIA5String Challenge
+		{
+			get { return challenge; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/nist/NISTNamedCurves.cs b/BouncyCastle.AxCrypt/src/asn1/nist/NISTNamedCurves.cs
new file mode 100644
index 0000000..0e82dda
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/nist/NISTNamedCurves.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Nist
+{
+    /**
+    * Utility class for fetching curves using their NIST names as published in FIPS-PUB 186-3
+    */
+    public sealed class NistNamedCurves
+    {
+        private NistNamedCurves()
+        {
+        }
+
+        private static readonly IDictionary objIds = Platform.CreateHashtable();
+        private static readonly IDictionary names = Platform.CreateHashtable();
+
+        private static void DefineCurve(
+            string				name,
+            DerObjectIdentifier	oid)
+        {
+            objIds.Add(name, oid);
+            names.Add(oid, name);
+        }
+
+        static NistNamedCurves()
+        {
+            DefineCurve("B-571", SecObjectIdentifiers.SecT571r1);
+            DefineCurve("B-409", SecObjectIdentifiers.SecT409r1);
+            DefineCurve("B-283", SecObjectIdentifiers.SecT283r1);
+            DefineCurve("B-233", SecObjectIdentifiers.SecT233r1);
+            DefineCurve("B-163", SecObjectIdentifiers.SecT163r2);
+            DefineCurve("K-571", SecObjectIdentifiers.SecT571k1);
+            DefineCurve("K-409", SecObjectIdentifiers.SecT409k1);
+            DefineCurve("K-283", SecObjectIdentifiers.SecT283k1);
+            DefineCurve("K-233", SecObjectIdentifiers.SecT233k1);
+            DefineCurve("K-163", SecObjectIdentifiers.SecT163k1);
+            DefineCurve("P-521", SecObjectIdentifiers.SecP521r1);
+            DefineCurve("P-384", SecObjectIdentifiers.SecP384r1);
+            DefineCurve("P-256", SecObjectIdentifiers.SecP256r1);
+            DefineCurve("P-224", SecObjectIdentifiers.SecP224r1);
+            DefineCurve("P-192", SecObjectIdentifiers.SecP192r1);
+        }
+
+        public static X9ECParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier) objIds[
+                Platform.ToUpperInvariant(name)];
+
+            if (oid != null)
+            {
+                return GetByOid(oid);
+            }
+
+            return null;
+        }
+
+        /**
+        * return the X9ECParameters object for the named curve represented by
+        * the passed in object identifier. Null if the curve isn't present.
+        *
+        * @param oid an object identifier representing a named curve, if present.
+        */
+        public static X9ECParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            return SecNamedCurves.GetByOid(oid);
+        }
+
+        /**
+        * return the object identifier signified by the passed in name. Null
+        * if there is no object identifier associated with name.
+        *
+        * @return the object identifier associated with name, if present.
+        */
+        public static DerObjectIdentifier GetOid(
+            string name)
+        {
+            return (DerObjectIdentifier) objIds[
+                Platform.ToUpperInvariant(name)];
+        }
+
+        /**
+        * return the named curve name represented by the given object identifier.
+        */
+        public static string GetName(
+            DerObjectIdentifier  oid)
+        {
+            return (string) names[oid];
+        }
+
+        /**
+        * returns an enumeration containing the name strings for curves
+        * contained in this structure.
+        */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(objIds.Keys); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/nist/NISTObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/nist/NISTObjectIdentifiers.cs
new file mode 100644
index 0000000..8eb5ed4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/nist/NISTObjectIdentifiers.cs
@@ -0,0 +1,65 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Nist
+{
+    public sealed class NistObjectIdentifiers
+    {
+        private NistObjectIdentifiers()
+        {
+        }
+
+        //
+        // NIST
+        //     iso/itu(2) joint-assign(16) us(840) organization(1) gov(101) csor(3)
+
+        //
+        // nistalgorithms(4)
+        //
+        public static readonly DerObjectIdentifier NistAlgorithm = new DerObjectIdentifier("2.16.840.1.101.3.4");
+
+        public static readonly DerObjectIdentifier HashAlgs = NistAlgorithm.Branch("2");
+
+        public static readonly DerObjectIdentifier IdSha256 = HashAlgs.Branch("1");
+        public static readonly DerObjectIdentifier IdSha384 = HashAlgs.Branch("2");
+        public static readonly DerObjectIdentifier IdSha512 = HashAlgs.Branch("3");
+        public static readonly DerObjectIdentifier IdSha224 = HashAlgs.Branch("4");
+        public static readonly DerObjectIdentifier IdSha512_224 = HashAlgs.Branch("5");
+        public static readonly DerObjectIdentifier IdSha512_256 = HashAlgs.Branch("6");
+
+        public static readonly DerObjectIdentifier Aes = new DerObjectIdentifier(NistAlgorithm + ".1");
+
+        public static readonly DerObjectIdentifier IdAes128Ecb	= new DerObjectIdentifier(Aes + ".1");
+        public static readonly DerObjectIdentifier IdAes128Cbc	= new DerObjectIdentifier(Aes + ".2");
+        public static readonly DerObjectIdentifier IdAes128Ofb	= new DerObjectIdentifier(Aes + ".3");
+        public static readonly DerObjectIdentifier IdAes128Cfb	= new DerObjectIdentifier(Aes + ".4");
+        public static readonly DerObjectIdentifier IdAes128Wrap	= new DerObjectIdentifier(Aes + ".5");
+        public static readonly DerObjectIdentifier IdAes128Gcm	= new DerObjectIdentifier(Aes + ".6");
+        public static readonly DerObjectIdentifier IdAes128Ccm	= new DerObjectIdentifier(Aes + ".7");
+
+        public static readonly DerObjectIdentifier IdAes192Ecb	= new DerObjectIdentifier(Aes + ".21");
+        public static readonly DerObjectIdentifier IdAes192Cbc	= new DerObjectIdentifier(Aes + ".22");
+        public static readonly DerObjectIdentifier IdAes192Ofb	= new DerObjectIdentifier(Aes + ".23");
+        public static readonly DerObjectIdentifier IdAes192Cfb	= new DerObjectIdentifier(Aes + ".24");
+        public static readonly DerObjectIdentifier IdAes192Wrap	= new DerObjectIdentifier(Aes + ".25");
+        public static readonly DerObjectIdentifier IdAes192Gcm	= new DerObjectIdentifier(Aes + ".26");
+        public static readonly DerObjectIdentifier IdAes192Ccm	= new DerObjectIdentifier(Aes + ".27");
+
+        public static readonly DerObjectIdentifier IdAes256Ecb	= new DerObjectIdentifier(Aes + ".41");
+        public static readonly DerObjectIdentifier IdAes256Cbc	= new DerObjectIdentifier(Aes + ".42");
+        public static readonly DerObjectIdentifier IdAes256Ofb	= new DerObjectIdentifier(Aes + ".43");
+        public static readonly DerObjectIdentifier IdAes256Cfb	= new DerObjectIdentifier(Aes + ".44");
+        public static readonly DerObjectIdentifier IdAes256Wrap	= new DerObjectIdentifier(Aes + ".45");
+        public static readonly DerObjectIdentifier IdAes256Gcm	= new DerObjectIdentifier(Aes + ".46");
+        public static readonly DerObjectIdentifier IdAes256Ccm	= new DerObjectIdentifier(Aes + ".47");
+
+        //
+        // signatures
+        //
+        public static readonly DerObjectIdentifier IdDsaWithSha2 = new DerObjectIdentifier(NistAlgorithm + ".3");
+
+        public static readonly DerObjectIdentifier DsaWithSha224 = new DerObjectIdentifier(IdDsaWithSha2 + ".1");
+        public static readonly DerObjectIdentifier DsaWithSha256 = new DerObjectIdentifier(IdDsaWithSha2 + ".2");
+        public static readonly DerObjectIdentifier DsaWithSha384 = new DerObjectIdentifier(IdDsaWithSha2 + ".3");
+        public static readonly DerObjectIdentifier DsaWithSha512 = new DerObjectIdentifier(IdDsaWithSha2 + ".4"); 
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ntt/NTTObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/ntt/NTTObjectIdentifiers.cs
new file mode 100644
index 0000000..cd25956
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ntt/NTTObjectIdentifiers.cs
@@ -0,0 +1,14 @@
+namespace Org.BouncyCastle.Asn1.Ntt
+{
+	/// <summary>From RFC 3657</summary>
+	public abstract class NttObjectIdentifiers
+	{
+		public static readonly DerObjectIdentifier IdCamellia128Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.2");
+		public static readonly DerObjectIdentifier IdCamellia192Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.3");
+		public static readonly DerObjectIdentifier IdCamellia256Cbc = new DerObjectIdentifier("1.2.392.200011.61.1.1.1.4");
+
+		public static readonly DerObjectIdentifier IdCamellia128Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.2");
+		public static readonly DerObjectIdentifier IdCamellia192Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.3");
+		public static readonly DerObjectIdentifier IdCamellia256Wrap = new DerObjectIdentifier("1.2.392.200011.61.1.1.3.4");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/BasicOCSPResponse.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/BasicOCSPResponse.cs
new file mode 100644
index 0000000..dd666ad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/BasicOCSPResponse.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class BasicOcspResponse
+        : Asn1Encodable
+    {
+        private readonly ResponseData			tbsResponseData;
+        private readonly AlgorithmIdentifier	signatureAlgorithm;
+        private readonly DerBitString			signature;
+        private readonly Asn1Sequence			certs;
+
+		public static BasicOcspResponse GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static BasicOcspResponse GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is BasicOcspResponse)
+			{
+				return (BasicOcspResponse)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new BasicOcspResponse((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public BasicOcspResponse(
+            ResponseData		tbsResponseData,
+            AlgorithmIdentifier	signatureAlgorithm,
+            DerBitString		signature,
+            Asn1Sequence		certs)
+        {
+            this.tbsResponseData = tbsResponseData;
+            this.signatureAlgorithm = signatureAlgorithm;
+            this.signature = signature;
+            this.certs = certs;
+        }
+
+		private BasicOcspResponse(
+            Asn1Sequence seq)
+        {
+            this.tbsResponseData = ResponseData.GetInstance(seq[0]);
+            this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+            this.signature = (DerBitString)seq[2];
+
+			if (seq.Count > 3)
+            {
+                this.certs = Asn1Sequence.GetInstance((Asn1TaggedObject)seq[3], true);
+            }
+        }
+
+		[Obsolete("Use TbsResponseData property instead")]
+		public ResponseData GetTbsResponseData()
+        {
+            return tbsResponseData;
+        }
+
+		public ResponseData TbsResponseData
+		{
+			get { return tbsResponseData; }
+		}
+
+		[Obsolete("Use SignatureAlgorithm property instead")]
+		public AlgorithmIdentifier GetSignatureAlgorithm()
+        {
+            return signatureAlgorithm;
+        }
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return signatureAlgorithm; }
+		}
+
+		[Obsolete("Use Signature property instead")]
+		public DerBitString GetSignature()
+        {
+            return signature;
+        }
+
+		public DerBitString Signature
+		{
+			get { return signature; }
+		}
+
+		[Obsolete("Use Certs property instead")]
+		public Asn1Sequence GetCerts()
+        {
+            return certs;
+        }
+
+		public Asn1Sequence Certs
+		{
+			get { return certs; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * BasicOcspResponse       ::= Sequence {
+         *      tbsResponseData      ResponseData,
+         *      signatureAlgorithm   AlgorithmIdentifier,
+         *      signature            BIT STRING,
+         *      certs                [0] EXPLICIT Sequence OF Certificate OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				tbsResponseData, signatureAlgorithm, signature);
+
+			if (certs != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, certs));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/CertID.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/CertID.cs
new file mode 100644
index 0000000..4b25109
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/CertID.cs
@@ -0,0 +1,98 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CertID
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier    hashAlgorithm;
+        private readonly Asn1OctetString        issuerNameHash;
+        private readonly Asn1OctetString        issuerKeyHash;
+        private readonly DerInteger             serialNumber;
+
+		public static CertID GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static CertID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CertID)
+			{
+				return (CertID)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new CertID((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public CertID(
+            AlgorithmIdentifier hashAlgorithm,
+            Asn1OctetString     issuerNameHash,
+            Asn1OctetString     issuerKeyHash,
+            DerInteger          serialNumber)
+        {
+            this.hashAlgorithm = hashAlgorithm;
+            this.issuerNameHash = issuerNameHash;
+            this.issuerKeyHash = issuerKeyHash;
+            this.serialNumber = serialNumber;
+        }
+
+		private CertID(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 4)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            this.issuerNameHash = Asn1OctetString.GetInstance(seq[1]);
+            this.issuerKeyHash = Asn1OctetString.GetInstance(seq[2]);
+            this.serialNumber = DerInteger.GetInstance(seq[3]);
+        }
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public Asn1OctetString IssuerNameHash
+		{
+			get { return issuerNameHash; }
+		}
+
+		public Asn1OctetString IssuerKeyHash
+		{
+			get { return issuerKeyHash; }
+		}
+
+		public DerInteger SerialNumber
+		{
+			get { return serialNumber; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * CertID          ::=     Sequence {
+         *     hashAlgorithm       AlgorithmIdentifier,
+         *     issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+         *     issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+         *     serialNumber        CertificateSerialNumber }
+         * </pre>
+         */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(hashAlgorithm, issuerNameHash, issuerKeyHash, serialNumber);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/CertStatus.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/CertStatus.cs
new file mode 100644
index 0000000..d5b1a94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/CertStatus.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CertStatus
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly int			tagNo;
+        private readonly Asn1Encodable	value;
+
+		/**
+         * create a CertStatus object with a tag of zero.
+         */
+        public CertStatus()
+        {
+            tagNo = 0;
+            value = DerNull.Instance;
+        }
+
+		public CertStatus(
+            RevokedInfo info)
+        {
+            tagNo = 1;
+            value = info;
+        }
+
+		public CertStatus(
+            int				tagNo,
+            Asn1Encodable	value)
+        {
+            this.tagNo = tagNo;
+            this.value = value;
+        }
+
+		public CertStatus(
+            Asn1TaggedObject choice)
+        {
+            this.tagNo = choice.TagNo;
+
+			switch (choice.TagNo)
+            {
+				case 1:
+					value = RevokedInfo.GetInstance(choice, false);
+					break;
+				case 0:
+				case 2:
+					value = DerNull.Instance;
+					break;
+            }
+        }
+
+		public static CertStatus GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is CertStatus)
+            {
+                return (CertStatus)obj;
+            }
+
+			if (obj is Asn1TaggedObject)
+            {
+                return new CertStatus((Asn1TaggedObject)obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public int TagNo
+		{
+			get { return tagNo; }
+		}
+
+		public Asn1Encodable Status
+		{
+			get { return value; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  CertStatus ::= CHOICE {
+         *                  good        [0]     IMPLICIT Null,
+         *                  revoked     [1]     IMPLICIT RevokedInfo,
+         *                  unknown     [2]     IMPLICIT UnknownInfo }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(false, tagNo, value);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/CrlID.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/CrlID.cs
new file mode 100644
index 0000000..cfb3d6f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/CrlID.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class CrlID
+        : Asn1Encodable
+    {
+        private readonly DerIA5String		crlUrl;
+        private readonly DerInteger			crlNum;
+        private readonly DerGeneralizedTime	crlTime;
+
+		// TODO Add GetInstance method(s) and amke this private?
+		public CrlID(
+            Asn1Sequence seq)
+        {
+			foreach (Asn1TaggedObject o in seq)
+			{
+				switch (o.TagNo)
+                {
+                case 0:
+                    crlUrl = DerIA5String.GetInstance(o, true);
+                    break;
+                case 1:
+                    crlNum = DerInteger.GetInstance(o, true);
+                    break;
+                case 2:
+                    crlTime = DerGeneralizedTime.GetInstance(o, true);
+                    break;
+                default:
+                    throw new ArgumentException("unknown tag number: " + o.TagNo);
+                }
+            }
+        }
+
+		public DerIA5String CrlUrl
+		{
+			get { return crlUrl; }
+		}
+
+		public DerInteger CrlNum
+		{
+			get { return crlNum; }
+		}
+
+		public DerGeneralizedTime CrlTime
+		{
+			get { return crlTime; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * CrlID ::= Sequence {
+         *     crlUrl               [0]     EXPLICIT IA5String OPTIONAL,
+         *     crlNum               [1]     EXPLICIT Integer OPTIONAL,
+         *     crlTime              [2]     EXPLICIT GeneralizedTime OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (crlUrl != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, crlUrl));
+            }
+
+			if (crlNum != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, crlNum));
+            }
+
+			if (crlTime != null)
+            {
+                v.Add(new DerTaggedObject(true, 2, crlTime));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPObjectIdentifiers.cs
new file mode 100644
index 0000000..a37c855
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPObjectIdentifiers.cs
@@ -0,0 +1,23 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public abstract class OcspObjectIdentifiers
+    {
+        internal const string PkixOcspId = "1.3.6.1.5.5.7.48.1";
+
+		public static readonly DerObjectIdentifier PkixOcsp = new DerObjectIdentifier(PkixOcspId);
+        public static readonly DerObjectIdentifier PkixOcspBasic = new DerObjectIdentifier(PkixOcspId + ".1");
+
+		//
+		// extensions
+		//
+		public static readonly DerObjectIdentifier PkixOcspNonce = new DerObjectIdentifier(PkixOcsp + ".2");
+		public static readonly DerObjectIdentifier PkixOcspCrl = new DerObjectIdentifier(PkixOcsp + ".3");
+
+		public static readonly DerObjectIdentifier PkixOcspResponse = new DerObjectIdentifier(PkixOcsp + ".4");
+		public static readonly DerObjectIdentifier PkixOcspNocheck = new DerObjectIdentifier(PkixOcsp + ".5");
+		public static readonly DerObjectIdentifier PkixOcspArchiveCutoff = new DerObjectIdentifier(PkixOcsp + ".6");
+		public static readonly DerObjectIdentifier PkixOcspServiceLocator = new DerObjectIdentifier(PkixOcsp + ".7");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPRequest.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPRequest.cs
new file mode 100644
index 0000000..1e804d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPRequest.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspRequest
+        : Asn1Encodable
+    {
+        private readonly TbsRequest	tbsRequest;
+        private readonly Signature	optionalSignature;
+
+		public static OcspRequest GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static OcspRequest GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspRequest)
+			{
+				return (OcspRequest)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new OcspRequest((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public OcspRequest(
+            TbsRequest	tbsRequest,
+            Signature	optionalSignature)
+        {
+			if (tbsRequest == null)
+				throw new ArgumentNullException("tbsRequest");
+
+			this.tbsRequest = tbsRequest;
+            this.optionalSignature = optionalSignature;
+        }
+
+		private OcspRequest(
+            Asn1Sequence seq)
+        {
+            tbsRequest = TbsRequest.GetInstance(seq[0]);
+
+			if (seq.Count == 2)
+            {
+                optionalSignature = Signature.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public TbsRequest TbsRequest
+		{
+			get { return tbsRequest; }
+		}
+
+		public Signature OptionalSignature
+		{
+			get { return optionalSignature; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OcspRequest     ::=     Sequence {
+         *     tbsRequest                  TBSRequest,
+         *     optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(tbsRequest);
+
+			if (optionalSignature != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, optionalSignature));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponse.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponse.cs
new file mode 100644
index 0000000..e9aad81
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponse.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspResponse
+        : Asn1Encodable
+    {
+        private readonly OcspResponseStatus	responseStatus;
+        private readonly ResponseBytes		responseBytes;
+
+		public static OcspResponse GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static OcspResponse GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is OcspResponse)
+			{
+				return (OcspResponse)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new OcspResponse((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public OcspResponse(
+            OcspResponseStatus	responseStatus,
+            ResponseBytes		responseBytes)
+        {
+			if (responseStatus == null)
+				throw new ArgumentNullException("responseStatus");
+
+			this.responseStatus = responseStatus;
+            this.responseBytes = responseBytes;
+        }
+
+		private OcspResponse(
+            Asn1Sequence seq)
+        {
+            responseStatus = new OcspResponseStatus(
+				DerEnumerated.GetInstance(seq[0]));
+
+			if (seq.Count == 2)
+            {
+                responseBytes = ResponseBytes.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public OcspResponseStatus ResponseStatus
+		{
+			get { return responseStatus; }
+		}
+
+		public ResponseBytes ResponseBytes
+		{
+			get { return responseBytes; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * OcspResponse ::= Sequence {
+         *     responseStatus         OcspResponseStatus,
+         *     responseBytes          [0] EXPLICIT ResponseBytes OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(responseStatus);
+
+			if (responseBytes != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, responseBytes));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponseStatus.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponseStatus.cs
new file mode 100644
index 0000000..653317e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/OCSPResponseStatus.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class OcspResponseStatus
+        : DerEnumerated
+    {
+        public const int Successful = 0;
+        public const int MalformedRequest = 1;
+        public const int InternalError = 2;
+        public const int TryLater = 3;
+        public const int SignatureRequired = 5;
+        public const int Unauthorized = 6;
+
+		/**
+         * The OcspResponseStatus enumeration.
+         * <pre>
+         * OcspResponseStatus ::= Enumerated {
+         *     successful            (0),  --Response has valid confirmations
+         *     malformedRequest      (1),  --Illegal confirmation request
+         *     internalError         (2),  --Internal error in issuer
+         *     tryLater              (3),  --Try again later
+         *                                 --(4) is not used
+         *     sigRequired           (5),  --Must sign the request
+         *     unauthorized          (6)   --Request unauthorized
+         * }
+         * </pre>
+         */
+        public OcspResponseStatus(int value)
+			: base(value)
+        {
+        }
+
+		public OcspResponseStatus(DerEnumerated value)
+			: base(value.Value.IntValue)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/Request.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/Request.cs
new file mode 100644
index 0000000..116c15e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/Request.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class Request
+        : Asn1Encodable
+    {
+        private readonly CertID			reqCert;
+        private readonly X509Extensions	singleRequestExtensions;
+
+		public static Request GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static Request GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is Request)
+			{
+				return (Request)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Request((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public Request(
+            CertID			reqCert,
+            X509Extensions	singleRequestExtensions)
+        {
+			if (reqCert == null)
+				throw new ArgumentNullException("reqCert");
+
+			this.reqCert = reqCert;
+            this.singleRequestExtensions = singleRequestExtensions;
+        }
+
+		private Request(
+			Asn1Sequence seq)
+        {
+			reqCert = CertID.GetInstance(seq[0]);
+
+			if (seq.Count == 2)
+            {
+                singleRequestExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject)seq[1], true);
+            }
+        }
+
+		public CertID ReqCert
+		{
+			get { return reqCert; }
+		}
+
+		public X509Extensions SingleRequestExtensions
+		{
+			get { return singleRequestExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Request         ::=     Sequence {
+         *     reqCert                     CertID,
+         *     singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(reqCert);
+
+			if (singleRequestExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, singleRequestExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponderID.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponderID.cs
new file mode 100644
index 0000000..143b173
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponderID.cs
@@ -0,0 +1,107 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ResponderID
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly Asn1Encodable id;
+
+		public static ResponderID GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ResponderID)
+			{
+				return (ResponderID)obj;
+			}
+
+			if (obj is DerOctetString)
+			{
+				return new ResponderID((DerOctetString)obj);
+			}
+
+			if (obj is Asn1TaggedObject)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)obj;
+
+				if (o.TagNo == 1)
+				{
+					return new ResponderID(X509Name.GetInstance(o, true));
+				}
+
+				return new ResponderID(Asn1OctetString.GetInstance(o, true));
+			}
+
+			return new ResponderID(X509Name.GetInstance(obj));
+		}
+
+		public ResponderID(
+            Asn1OctetString id)
+        {
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+        }
+
+		public ResponderID(
+            X509Name id)
+        {
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+        }
+
+		public static ResponderID GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(obj.GetObject()); // must be explicitly tagged
+		}
+
+		public virtual byte[] GetKeyHash()
+		{
+			if (id is Asn1OctetString)
+			{
+				return ((Asn1OctetString)id).GetOctets();
+			}
+
+			return null;
+		}
+
+		public virtual X509Name Name
+		{
+			get
+			{
+				if (id is Asn1OctetString)
+				{
+					return null;
+				}
+
+				return X509Name.GetInstance(id);
+			}
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponderID ::= CHOICE {
+         *      byName          [1] Name,
+         *      byKey           [2] KeyHash }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            if (id is Asn1OctetString)
+            {
+                return new DerTaggedObject(true, 2, id);
+            }
+
+			return new DerTaggedObject(true, 1, id);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseBytes.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseBytes.cs
new file mode 100644
index 0000000..2ce59fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseBytes.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ResponseBytes
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier responseType;
+        private readonly Asn1OctetString response;
+
+		public static ResponseBytes GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ResponseBytes GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ResponseBytes)
+			{
+				return (ResponseBytes)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ResponseBytes((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ResponseBytes(
+            DerObjectIdentifier	responseType,
+            Asn1OctetString		response)
+        {
+			if (responseType == null)
+				throw new ArgumentNullException("responseType");
+			if (response == null)
+				throw new ArgumentNullException("response");
+
+			this.responseType = responseType;
+            this.response = response;
+        }
+
+		private ResponseBytes(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.responseType = DerObjectIdentifier.GetInstance(seq[0]);
+            this.response = Asn1OctetString.GetInstance(seq[1]);
+        }
+
+		public DerObjectIdentifier ResponseType
+		{
+			get { return responseType; }
+		}
+
+		public Asn1OctetString Response
+		{
+			get { return response; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponseBytes ::=       Sequence {
+         *     responseType   OBJECT IDENTIFIER,
+         *     response       OCTET STRING }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(responseType, response);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseData.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseData.cs
new file mode 100644
index 0000000..173829d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/ResponseData.cs
@@ -0,0 +1,158 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+	public class ResponseData
+		: Asn1Encodable
+	{
+		private static readonly DerInteger V1 = new DerInteger(0);
+
+		private readonly bool                versionPresent;
+		private readonly DerInteger          version;
+		private readonly ResponderID         responderID;
+		private readonly DerGeneralizedTime  producedAt;
+		private readonly Asn1Sequence        responses;
+		private readonly X509Extensions      responseExtensions;
+
+		public static ResponseData GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ResponseData GetInstance(
+			object  obj)
+		{
+			if (obj == null || obj is ResponseData)
+			{
+				return (ResponseData)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ResponseData((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ResponseData(
+			DerInteger          version,
+			ResponderID         responderID,
+			DerGeneralizedTime  producedAt,
+			Asn1Sequence        responses,
+			X509Extensions      responseExtensions)
+		{
+			this.version = version;
+			this.responderID = responderID;
+			this.producedAt = producedAt;
+			this.responses = responses;
+			this.responseExtensions = responseExtensions;
+		}
+
+		public ResponseData(
+			ResponderID         responderID,
+			DerGeneralizedTime  producedAt,
+			Asn1Sequence        responses,
+			X509Extensions      responseExtensions)
+			: this(V1, responderID, producedAt, responses, responseExtensions)
+		{
+		}
+
+		private ResponseData(
+			Asn1Sequence seq)
+		{
+			int index = 0;
+
+			Asn1Encodable enc = seq[0];
+			if (enc is Asn1TaggedObject)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)enc;
+
+				if (o.TagNo == 0)
+				{
+					this.versionPresent = true;
+					this.version = DerInteger.GetInstance(o, true);
+					index++;
+				}
+				else
+				{
+					this.version = V1;
+				}
+			}
+			else
+			{
+				this.version = V1;
+			}
+
+			this.responderID = ResponderID.GetInstance(seq[index++]);
+			this.producedAt = (DerGeneralizedTime)seq[index++];
+			this.responses = (Asn1Sequence)seq[index++];
+
+			if (seq.Count > index)
+			{
+				this.responseExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject)seq[index], true);
+			}
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public ResponderID ResponderID
+		{
+			get { return responderID; }
+		}
+
+		public DerGeneralizedTime ProducedAt
+		{
+			get { return producedAt; }
+		}
+
+		public Asn1Sequence Responses
+		{
+			get { return responses; }
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return responseExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ResponseData ::= Sequence {
+         *     version              [0] EXPLICIT Version DEFAULT v1,
+         *     responderID              ResponderID,
+         *     producedAt               GeneralizedTime,
+         *     responses                Sequence OF SingleResponse,
+         *     responseExtensions   [1] EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (versionPresent || !version.Equals(V1))
+			{
+				v.Add(new DerTaggedObject(true, 0, version));
+			}
+
+			v.Add(responderID, producedAt, responses);
+
+			if (responseExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, responseExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/RevokedInfo.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/RevokedInfo.cs
new file mode 100644
index 0000000..7d9d590
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/RevokedInfo.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class RevokedInfo
+        : Asn1Encodable
+    {
+        private readonly DerGeneralizedTime revocationTime;
+        private readonly CrlReason revocationReason;
+
+		public static RevokedInfo GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static RevokedInfo GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RevokedInfo)
+			{
+				return (RevokedInfo) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new RevokedInfo((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public RevokedInfo(
+			DerGeneralizedTime revocationTime)
+			: this(revocationTime, null)
+		{
+		}
+
+		public RevokedInfo(
+            DerGeneralizedTime  revocationTime,
+            CrlReason           revocationReason)
+        {
+			if (revocationTime == null)
+				throw new ArgumentNullException("revocationTime");
+
+			this.revocationTime = revocationTime;
+            this.revocationReason = revocationReason;
+        }
+
+		private RevokedInfo(
+            Asn1Sequence seq)
+        {
+            this.revocationTime = (DerGeneralizedTime) seq[0];
+
+			if (seq.Count > 1)
+            {
+                this.revocationReason = new CrlReason(
+					DerEnumerated.GetInstance((Asn1TaggedObject) seq[1], true));
+            }
+        }
+
+		public DerGeneralizedTime RevocationTime
+		{
+			get { return revocationTime; }
+		}
+
+		public CrlReason RevocationReason
+		{
+			get { return revocationReason; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * RevokedInfo ::= Sequence {
+         *      revocationTime              GeneralizedTime,
+         *      revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			Asn1EncodableVector v = new Asn1EncodableVector(revocationTime);
+
+			if (revocationReason != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, revocationReason));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/ServiceLocator.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/ServiceLocator.cs
new file mode 100644
index 0000000..56bc49d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/ServiceLocator.cs
@@ -0,0 +1,95 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class ServiceLocator
+        : Asn1Encodable
+    {
+        private readonly X509Name issuer;
+        private readonly Asn1Object locator;
+
+		public static ServiceLocator GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static ServiceLocator GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is ServiceLocator)
+			{
+				return (ServiceLocator) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new ServiceLocator((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public ServiceLocator(
+			X509Name	issuer)
+			: this(issuer, null)
+		{
+		}
+
+		public ServiceLocator(
+			X509Name	issuer,
+			Asn1Object	locator)
+		{
+			if (issuer == null)
+				throw new ArgumentNullException("issuer");
+
+			this.issuer = issuer;
+			this.locator = locator;
+		}
+
+		private ServiceLocator(
+			Asn1Sequence seq)
+		{
+			this.issuer = X509Name.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.locator = seq[1].ToAsn1Object();
+			}
+		}
+
+		public X509Name Issuer
+		{
+			get { return issuer; }
+		}
+
+		public Asn1Object Locator
+		{
+			get { return locator; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ServiceLocator ::= Sequence {
+         *     issuer    Name,
+         *     locator   AuthorityInfoAccessSyntax OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(issuer);
+
+			if (locator != null)
+            {
+                v.Add(locator);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/Signature.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/Signature.cs
new file mode 100644
index 0000000..a07e7a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/Signature.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class Signature
+        : Asn1Encodable
+    {
+        internal AlgorithmIdentifier	signatureAlgorithm;
+        internal DerBitString			signatureValue;
+        internal Asn1Sequence			certs;
+
+		public static Signature GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static Signature GetInstance(
+			object  obj)
+		{
+			if (obj == null || obj is Signature)
+			{
+				return (Signature)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Signature((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public Signature(
+            AlgorithmIdentifier signatureAlgorithm,
+            DerBitString        signatureValue)
+			: this(signatureAlgorithm, signatureValue, null)
+        {
+        }
+
+		public Signature(
+            AlgorithmIdentifier	signatureAlgorithm,
+            DerBitString		signatureValue,
+            Asn1Sequence		certs)
+        {
+			if (signatureAlgorithm == null)
+				throw new ArgumentException("signatureAlgorithm");
+			if (signatureValue == null)
+				throw new ArgumentException("signatureValue");
+
+			this.signatureAlgorithm = signatureAlgorithm;
+            this.signatureValue = signatureValue;
+            this.certs = certs;
+        }
+
+		private Signature(
+            Asn1Sequence seq)
+        {
+            signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+            signatureValue = (DerBitString)seq[1];
+
+			if (seq.Count == 3)
+            {
+                certs = Asn1Sequence.GetInstance(
+					(Asn1TaggedObject)seq[2], true);
+            }
+        }
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return signatureAlgorithm; }
+		}
+
+		public DerBitString SignatureValue
+		{
+			get { return signatureValue; }
+		}
+
+		public Asn1Sequence Certs
+		{
+			get { return certs; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Signature       ::=     Sequence {
+         *     signatureAlgorithm      AlgorithmIdentifier,
+         *     signature               BIT STRING,
+         *     certs               [0] EXPLICIT Sequence OF Certificate OPTIONAL}
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				signatureAlgorithm, signatureValue);
+
+			if (certs != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, certs));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/SingleResponse.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/SingleResponse.cs
new file mode 100644
index 0000000..93d4c21
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/SingleResponse.cs
@@ -0,0 +1,137 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class SingleResponse
+        : Asn1Encodable
+    {
+        private readonly CertID              certID;
+        private readonly CertStatus          certStatus;
+        private readonly DerGeneralizedTime  thisUpdate;
+        private readonly DerGeneralizedTime  nextUpdate;
+        private readonly X509Extensions      singleExtensions;
+
+		public SingleResponse(
+            CertID              certID,
+            CertStatus          certStatus,
+            DerGeneralizedTime  thisUpdate,
+            DerGeneralizedTime  nextUpdate,
+            X509Extensions      singleExtensions)
+        {
+            this.certID = certID;
+            this.certStatus = certStatus;
+            this.thisUpdate = thisUpdate;
+            this.nextUpdate = nextUpdate;
+            this.singleExtensions = singleExtensions;
+        }
+
+		public SingleResponse(
+            Asn1Sequence seq)
+        {
+            this.certID = CertID.GetInstance(seq[0]);
+            this.certStatus = CertStatus.GetInstance(seq[1]);
+            this.thisUpdate = (DerGeneralizedTime)seq[2];
+
+			if (seq.Count > 4)
+            {
+                this.nextUpdate = DerGeneralizedTime.GetInstance(
+					(Asn1TaggedObject) seq[3], true);
+                this.singleExtensions = X509Extensions.GetInstance(
+					(Asn1TaggedObject) seq[4], true);
+            }
+            else if (seq.Count > 3)
+            {
+                Asn1TaggedObject o = (Asn1TaggedObject) seq[3];
+
+				if (o.TagNo == 0)
+                {
+                    this.nextUpdate = DerGeneralizedTime.GetInstance(o, true);
+                }
+                else
+                {
+                    this.singleExtensions = X509Extensions.GetInstance(o, true);
+                }
+            }
+        }
+
+		public static SingleResponse GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static SingleResponse GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is SingleResponse)
+            {
+                return (SingleResponse)obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SingleResponse((Asn1Sequence)obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public CertID CertId
+		{
+			get { return certID; }
+		}
+
+		public CertStatus CertStatus
+		{
+			get { return certStatus; }
+		}
+
+		public DerGeneralizedTime ThisUpdate
+		{
+			get { return thisUpdate; }
+		}
+
+		public DerGeneralizedTime NextUpdate
+		{
+			get { return nextUpdate; }
+		}
+
+		public X509Extensions SingleExtensions
+		{
+			get { return singleExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  SingleResponse ::= Sequence {
+         *          certID                       CertID,
+         *          certStatus                   CertStatus,
+         *          thisUpdate                   GeneralizedTime,
+         *          nextUpdate         [0]       EXPLICIT GeneralizedTime OPTIONAL,
+         *          singleExtensions   [1]       EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				certID, certStatus, thisUpdate);
+
+			if (nextUpdate != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, nextUpdate));
+            }
+
+			if (singleExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, singleExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/ocsp/TBSRequest.cs b/BouncyCastle.AxCrypt/src/asn1/ocsp/TBSRequest.cs
new file mode 100644
index 0000000..6bf75eb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/ocsp/TBSRequest.cs
@@ -0,0 +1,151 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+using System;
+
+namespace Org.BouncyCastle.Asn1.Ocsp
+{
+    public class TbsRequest
+        : Asn1Encodable
+    {
+		private static readonly DerInteger V1 = new DerInteger(0);
+
+		private readonly DerInteger      version;
+        private readonly GeneralName     requestorName;
+        private readonly Asn1Sequence    requestList;
+        private readonly X509Extensions  requestExtensions;
+
+		private bool versionSet;
+
+		public static TbsRequest GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static TbsRequest GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is TbsRequest)
+			{
+				return (TbsRequest)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new TbsRequest((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public TbsRequest(
+            GeneralName     requestorName,
+            Asn1Sequence    requestList,
+            X509Extensions  requestExtensions)
+        {
+            this.version = V1;
+            this.requestorName = requestorName;
+            this.requestList = requestList;
+            this.requestExtensions = requestExtensions;
+        }
+
+		private TbsRequest(
+            Asn1Sequence seq)
+        {
+            int index = 0;
+
+			Asn1Encodable enc = seq[0];
+			if (enc is Asn1TaggedObject)
+            {
+                Asn1TaggedObject o = (Asn1TaggedObject) enc;
+
+				if (o.TagNo == 0)
+                {
+					versionSet = true;
+					version = DerInteger.GetInstance(o, true);
+                    index++;
+                }
+                else
+                {
+                    version = V1;
+                }
+            }
+            else
+            {
+                version = V1;
+            }
+
+			if (seq[index] is Asn1TaggedObject)
+            {
+                requestorName = GeneralName.GetInstance((Asn1TaggedObject) seq[index++], true);
+            }
+
+			requestList = (Asn1Sequence) seq[index++];
+
+			if (seq.Count == (index + 1))
+            {
+                requestExtensions = X509Extensions.GetInstance((Asn1TaggedObject) seq[index], true);
+            }
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public GeneralName RequestorName
+		{
+			get { return requestorName; }
+		}
+
+		public Asn1Sequence RequestList
+		{
+			get { return requestList; }
+		}
+
+		public X509Extensions RequestExtensions
+		{
+			get { return requestExtensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * TBSRequest      ::=     Sequence {
+         *     version             [0]     EXPLICIT Version DEFAULT v1,
+         *     requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+         *     requestList                 Sequence OF Request,
+         *     requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			//
+			// if default don't include - unless explicitly provided. Not strictly correct
+			// but required for some requests
+			//
+			if (!version.Equals(V1) || versionSet)
+			{
+                v.Add(new DerTaggedObject(true, 0, version));
+            }
+
+			if (requestorName != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, requestorName));
+            }
+
+			v.Add(requestList);
+
+			if (requestExtensions != null)
+            {
+                v.Add(new DerTaggedObject(true, 2, requestExtensions));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/oiw/ElGamalParameter.cs b/BouncyCastle.AxCrypt/src/asn1/oiw/ElGamalParameter.cs
new file mode 100644
index 0000000..3e020f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/oiw/ElGamalParameter.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Oiw
+{
+    public class ElGamalParameter
+        : Asn1Encodable
+    {
+        internal DerInteger p, g;
+
+		public ElGamalParameter(
+            BigInteger	p,
+            BigInteger	g)
+        {
+            this.p = new DerInteger(p);
+            this.g = new DerInteger(g);
+        }
+
+		public ElGamalParameter(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			p = DerInteger.GetInstance(seq[0]);
+			g = DerInteger.GetInstance(seq[1]);
+        }
+
+		public BigInteger P
+		{
+			get { return p.PositiveValue; }
+		}
+
+		public BigInteger G
+		{
+			get { return g.PositiveValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(p, g);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/oiw/OIWObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/oiw/OIWObjectIdentifiers.cs
new file mode 100644
index 0000000..3da2263
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/oiw/OIWObjectIdentifiers.cs
@@ -0,0 +1,29 @@
+namespace Org.BouncyCastle.Asn1.Oiw
+{
+	public abstract class OiwObjectIdentifiers
+	{
+		public static readonly DerObjectIdentifier MD4WithRsa			= new DerObjectIdentifier("1.3.14.3.2.2");
+		public static readonly DerObjectIdentifier MD5WithRsa			= new DerObjectIdentifier("1.3.14.3.2.3");
+		public static readonly DerObjectIdentifier MD4WithRsaEncryption	= new DerObjectIdentifier("1.3.14.3.2.4");
+
+		public static readonly DerObjectIdentifier DesEcb				= new DerObjectIdentifier("1.3.14.3.2.6");
+		public static readonly DerObjectIdentifier DesCbc				= new DerObjectIdentifier("1.3.14.3.2.7");
+		public static readonly DerObjectIdentifier DesOfb				= new DerObjectIdentifier("1.3.14.3.2.8");
+		public static readonly DerObjectIdentifier DesCfb				= new DerObjectIdentifier("1.3.14.3.2.9");
+
+		public static readonly DerObjectIdentifier DesEde				= new DerObjectIdentifier("1.3.14.3.2.17");
+
+		// id-SHA1 OBJECT IDENTIFIER ::=
+		//   {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }    //
+		public static readonly DerObjectIdentifier IdSha1				= new DerObjectIdentifier("1.3.14.3.2.26");
+
+		public static readonly DerObjectIdentifier DsaWithSha1			= new DerObjectIdentifier("1.3.14.3.2.27");
+
+		public static readonly DerObjectIdentifier Sha1WithRsa			= new DerObjectIdentifier("1.3.14.3.2.29");
+
+		// ElGamal Algorithm OBJECT IDENTIFIER ::=
+		// {iso(1) identified-organization(3) oiw(14) dirservsig(7) algorithm(2) encryption(1) 1 }
+		//
+		public static readonly DerObjectIdentifier ElGamalAlgorithm		= new DerObjectIdentifier("1.3.14.7.2.1.1");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/Attribute.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/Attribute.cs
new file mode 100644
index 0000000..ceec115
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/Attribute.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class AttributePkcs
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier attrType;
+        private readonly Asn1Set attrValues;
+
+		/**
+         * return an Attribute object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static AttributePkcs GetInstance(
+            object obj)
+        {
+            AttributePkcs attr = obj as AttributePkcs;
+            if (obj == null || attr != null)
+            {
+                return attr;
+            }
+
+			Asn1Sequence seq = obj as Asn1Sequence;
+            if (seq != null)
+            {
+                return new AttributePkcs(seq);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		private AttributePkcs(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			attrType = DerObjectIdentifier.GetInstance(seq[0]);
+            attrValues = Asn1Set.GetInstance(seq[1]);
+        }
+
+		public AttributePkcs(
+            DerObjectIdentifier	attrType,
+            Asn1Set				attrValues)
+        {
+            this.attrType = attrType;
+            this.attrValues = attrValues;
+        }
+
+		public DerObjectIdentifier AttrType
+		{
+			get { return attrType; }
+		}
+
+		public Asn1Set AttrValues
+		{
+			get { return attrValues; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Attr ::= Sequence {
+         *     attrType OBJECT IDENTIFIER,
+         *     attrValues Set OF AttributeValue
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(attrType, attrValues);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/AuthenticatedSafe.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/AuthenticatedSafe.cs
new file mode 100644
index 0000000..f3dabb8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/AuthenticatedSafe.cs
@@ -0,0 +1,37 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class AuthenticatedSafe
+        : Asn1Encodable
+    {
+        private readonly ContentInfo[] info;
+
+		public AuthenticatedSafe(
+            Asn1Sequence seq)
+        {
+            info = new ContentInfo[seq.Count];
+
+			for (int i = 0; i != info.Length; i++)
+            {
+                info[i] = ContentInfo.GetInstance(seq[i]);
+            }
+        }
+
+		public AuthenticatedSafe(
+            ContentInfo[] info)
+        {
+            this.info = (ContentInfo[]) info.Clone();
+        }
+
+		public ContentInfo[] GetContentInfo()
+        {
+            return (ContentInfo[]) info.Clone();
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new BerSequence(info);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/CertBag.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertBag.cs
new file mode 100644
index 0000000..b6f4c8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertBag.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class CertBag
+        : Asn1Encodable
+    {
+//		private readonly Asn1Sequence seq;
+        private readonly DerObjectIdentifier certID;
+        private readonly Asn1Object certValue;
+
+		public CertBag(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+//			this.seq = seq;
+            this.certID = DerObjectIdentifier.GetInstance(seq[0]);
+            this.certValue = DerTaggedObject.GetInstance(seq[1]).GetObject();
+        }
+
+		public CertBag(
+            DerObjectIdentifier	certID,
+            Asn1Object			certValue)
+        {
+            this.certID = certID;
+            this.certValue = certValue;
+        }
+
+		public DerObjectIdentifier CertID
+		{
+			get { return certID; }
+		}
+
+		public Asn1Object CertValue
+		{
+			get { return certValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(certID, new DerTaggedObject(0, certValue));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequest.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequest.cs
new file mode 100644
index 0000000..32b1612
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequest.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * Pkcs10 Certfication request object.
+     * <pre>
+     * CertificationRequest ::= Sequence {
+     *   certificationRequestInfo  CertificationRequestInfo,
+     *   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+     *   signature                 BIT STRING
+     * }
+     * </pre>
+     */
+    public class CertificationRequest
+        : Asn1Encodable
+    {
+        protected CertificationRequestInfo	reqInfo;
+        protected AlgorithmIdentifier		sigAlgId;
+        protected DerBitString				sigBits;
+
+		public static CertificationRequest GetInstance(
+			object obj)
+		{
+			if (obj is CertificationRequest)
+				return (CertificationRequest)obj;
+
+			if (obj != null)
+				return new CertificationRequest((Asn1Sequence)obj);
+
+			return null;
+		}
+
+		protected CertificationRequest()
+        {
+        }
+
+		public CertificationRequest(
+            CertificationRequestInfo	requestInfo,
+            AlgorithmIdentifier			algorithm,
+            DerBitString				signature)
+        {
+            this.reqInfo = requestInfo;
+            this.sigAlgId = algorithm;
+            this.sigBits = signature;
+        }
+
+		public CertificationRequest(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 3)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			reqInfo = CertificationRequestInfo.GetInstance(seq[0]);
+            sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]);
+            sigBits = DerBitString.GetInstance(seq[2]);
+        }
+
+		public CertificationRequestInfo GetCertificationRequestInfo()
+        {
+            return reqInfo;
+        }
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return sigAlgId; }
+		}
+
+		public DerBitString Signature
+		{
+			get { return sigBits; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(reqInfo, sigAlgId, sigBits);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequestInfo.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequestInfo.cs
new file mode 100644
index 0000000..690d068
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/CertificationRequestInfo.cs
@@ -0,0 +1,123 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * Pkcs10 CertificationRequestInfo object.
+     * <pre>
+     *  CertificationRequestInfo ::= Sequence {
+     *   version             Integer { v1(0) } (v1,...),
+     *   subject             Name,
+     *   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+     *   attributes          [0] Attributes{{ CRIAttributes }}
+     *  }
+     *
+     *  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+     *
+     *  Attr { ATTRIBUTE:IOSet } ::= Sequence {
+     *    type    ATTRIBUTE.&id({IOSet}),
+     *    values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+     *  }
+     * </pre>
+     */
+    public class CertificationRequestInfo
+        : Asn1Encodable
+    {
+        internal DerInteger				version = new DerInteger(0);
+        internal X509Name				subject;
+        internal SubjectPublicKeyInfo	subjectPKInfo;
+        internal Asn1Set				attributes;
+
+		public static CertificationRequestInfo GetInstance(
+            object  obj)
+        {
+            if (obj is CertificationRequestInfo)
+            {
+                return (CertificationRequestInfo) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new CertificationRequestInfo((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public CertificationRequestInfo(
+            X509Name				subject,
+            SubjectPublicKeyInfo	pkInfo,
+            Asn1Set					attributes)
+        {
+            this.subject = subject;
+            this.subjectPKInfo = pkInfo;
+            this.attributes = attributes;
+
+			if (subject == null || version == null || subjectPKInfo == null)
+            {
+                throw new ArgumentException(
+					"Not all mandatory fields set in CertificationRequestInfo generator.");
+            }
+        }
+
+		private CertificationRequestInfo(
+            Asn1Sequence seq)
+        {
+            version = (DerInteger) seq[0];
+
+			subject = X509Name.GetInstance(seq[1]);
+            subjectPKInfo = SubjectPublicKeyInfo.GetInstance(seq[2]);
+
+			//
+            // some CertificationRequestInfo objects seem to treat this field
+            // as optional.
+            //
+            if (seq.Count > 3)
+            {
+                DerTaggedObject tagobj = (DerTaggedObject) seq[3];
+                attributes = Asn1Set.GetInstance(tagobj, false);
+            }
+
+			if (subject == null || version == null || subjectPKInfo == null)
+            {
+                throw new ArgumentException(
+					"Not all mandatory fields set in CertificationRequestInfo generator.");
+            }
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public X509Name Subject
+		{
+			get { return subject; }
+		}
+
+		public SubjectPublicKeyInfo SubjectPublicKeyInfo
+		{
+			get { return subjectPKInfo; }
+		}
+
+		public Asn1Set Attributes
+		{
+			get { return attributes; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				version, subject, subjectPKInfo);
+
+			if (attributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, attributes));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/ContentInfo.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/ContentInfo.cs
new file mode 100644
index 0000000..526a3c4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/ContentInfo.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class ContentInfo
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	contentType;
+        private readonly Asn1Encodable			content;
+
+        public static ContentInfo GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            ContentInfo existing = obj as ContentInfo;
+            if (existing != null)
+                return existing;
+            return new ContentInfo(Asn1Sequence.GetInstance(obj));
+        }
+
+        private ContentInfo(
+            Asn1Sequence seq)
+        {
+            contentType = (DerObjectIdentifier) seq[0];
+
+            if (seq.Count > 1)
+            {
+                content = ((Asn1TaggedObject) seq[1]).GetObject();
+            }
+        }
+
+        public ContentInfo(
+            DerObjectIdentifier	contentType,
+            Asn1Encodable		content)
+        {
+            this.contentType = contentType;
+            this.content = content;
+        }
+
+        public DerObjectIdentifier ContentType
+        {
+            get { return contentType; }
+        }
+
+        public Asn1Encodable Content
+        {
+            get { return content; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * ContentInfo ::= Sequence {
+         *          contentType ContentType,
+         *          content
+         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(contentType);
+
+            if (content != null)
+            {
+                v.Add(new BerTaggedObject(0, content));
+            }
+
+            return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/DHParameter.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/DHParameter.cs
new file mode 100644
index 0000000..25a091a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/DHParameter.cs
@@ -0,0 +1,72 @@
+using Org.BouncyCastle.Asn1;
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class DHParameter
+        : Asn1Encodable
+    {
+        internal DerInteger p, g, l;
+
+		public DHParameter(
+            BigInteger	p,
+            BigInteger	g,
+            int			l)
+        {
+            this.p = new DerInteger(p);
+            this.g = new DerInteger(g);
+
+			if (l != 0)
+            {
+                this.l = new DerInteger(l);
+            }
+        }
+
+		public DHParameter(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+            p = (DerInteger)e.Current;
+
+			e.MoveNext();
+            g = (DerInteger)e.Current;
+
+			if (e.MoveNext())
+            {
+                l = (DerInteger) e.Current;
+            }
+        }
+
+		public BigInteger P
+		{
+			get { return p.PositiveValue; }
+		}
+
+		public BigInteger G
+		{
+			get { return g.PositiveValue; }
+		}
+
+		public BigInteger L
+		{
+            get { return l == null ? null : l.PositiveValue; }
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(p, g);
+
+			if (this.l != null)
+            {
+                v.Add(l);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedData.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedData.cs
new file mode 100644
index 0000000..912064a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedData.cs
@@ -0,0 +1,104 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * The EncryptedData object.
+     * <pre>
+     *      EncryptedData ::= Sequence {
+     *           version Version,
+     *           encryptedContentInfo EncryptedContentInfo
+     *      }
+     *
+     *
+     *      EncryptedContentInfo ::= Sequence {
+     *          contentType ContentType,
+     *          contentEncryptionAlgorithm  ContentEncryptionAlgorithmIdentifier,
+     *          encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
+     *    }
+     *
+     *    EncryptedContent ::= OCTET STRING
+     * </pre>
+     */
+    public class EncryptedData
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence data;
+//        private readonly DerObjectIdentifier bagId;
+//        private readonly Asn1Object bagValue;
+
+		public static EncryptedData GetInstance(
+             object obj)
+        {
+			if (obj is EncryptedData)
+			{
+				return (EncryptedData) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new EncryptedData((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		private EncryptedData(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			int version = ((DerInteger) seq[0]).Value.IntValue;
+			if (version != 0)
+            {
+                throw new ArgumentException("sequence not version 0");
+            }
+
+			this.data = (Asn1Sequence) seq[1];
+        }
+
+		public EncryptedData(
+            DerObjectIdentifier	contentType,
+            AlgorithmIdentifier	encryptionAlgorithm,
+            Asn1Encodable		content)
+        {
+			data = new BerSequence(
+				contentType,
+				encryptionAlgorithm.ToAsn1Object(),
+				new BerTaggedObject(false, 0, content));
+        }
+
+		public DerObjectIdentifier ContentType
+        {
+            get { return (DerObjectIdentifier) data[0]; }
+        }
+
+		public AlgorithmIdentifier EncryptionAlgorithm
+        {
+			get { return AlgorithmIdentifier.GetInstance(data[1]); }
+        }
+
+		public Asn1OctetString Content
+        {
+			get
+			{
+				if (data.Count == 3)
+				{
+					DerTaggedObject o = (DerTaggedObject) data[2];
+
+					return Asn1OctetString.GetInstance(o, false);
+				}
+
+				return null;
+			}
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new BerSequence(new DerInteger(0), data);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
new file mode 100644
index 0000000..b97b8f5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptedPrivateKeyInfo.cs
@@ -0,0 +1,78 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class EncryptedPrivateKeyInfo
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier algId;
+        private readonly Asn1OctetString data;
+
+		private EncryptedPrivateKeyInfo(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+            algId = AlgorithmIdentifier.GetInstance(seq[0]);
+            data = Asn1OctetString.GetInstance(seq[1]);
+        }
+
+		public EncryptedPrivateKeyInfo(
+            AlgorithmIdentifier	algId,
+            byte[]				encoding)
+        {
+            this.algId = algId;
+            this.data = new DerOctetString(encoding);
+        }
+
+		public static EncryptedPrivateKeyInfo GetInstance(
+             object obj)
+        {
+			if (obj is EncryptedPrivateKeyInfo)
+			{
+				return (EncryptedPrivateKeyInfo) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new EncryptedPrivateKeyInfo((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public AlgorithmIdentifier EncryptionAlgorithm
+		{
+			get { return algId; }
+		}
+
+		public byte[] GetEncryptedData()
+        {
+            return data.GetOctets();
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * EncryptedPrivateKeyInfo ::= Sequence {
+         *      encryptionAlgorithm AlgorithmIdentifier {{KeyEncryptionAlgorithms}},
+         *      encryptedData EncryptedData
+         * }
+         *
+         * EncryptedData ::= OCTET STRING
+         *
+         * KeyEncryptionAlgorithms ALGORITHM-IDENTIFIER ::= {
+         *          ... -- For local profiles
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(algId, data);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptionScheme.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptionScheme.cs
new file mode 100644
index 0000000..5b64d6f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/EncryptionScheme.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class EncryptionScheme
+        : AlgorithmIdentifier
+    {
+		public EncryptionScheme(
+            DerObjectIdentifier	objectID,
+            Asn1Encodable		parameters)
+			: base(objectID, parameters)
+		{
+		}
+
+		internal EncryptionScheme(
+			Asn1Sequence seq)
+			: this((DerObjectIdentifier)seq[0], seq[1])
+        {
+        }
+
+		public new static EncryptionScheme GetInstance(object obj)
+		{
+			if (obj is EncryptionScheme)
+			{
+				return (EncryptionScheme)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new EncryptionScheme((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public Asn1Object Asn1Object
+		{
+			get { return Parameters.ToAsn1Object(); }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(ObjectID, Parameters);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/IssuerAndSerialNumber.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/IssuerAndSerialNumber.cs
new file mode 100644
index 0000000..ff608f1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/IssuerAndSerialNumber.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class IssuerAndSerialNumber
+        : Asn1Encodable
+    {
+        private readonly X509Name name;
+        private readonly DerInteger certSerialNumber;
+
+		public static IssuerAndSerialNumber GetInstance(
+            object obj)
+        {
+            if (obj is IssuerAndSerialNumber)
+            {
+                return (IssuerAndSerialNumber) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new IssuerAndSerialNumber((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		private IssuerAndSerialNumber(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.name = X509Name.GetInstance(seq[0]);
+            this.certSerialNumber = DerInteger.GetInstance(seq[1]);
+        }
+
+		public IssuerAndSerialNumber(
+            X509Name	name,
+            BigInteger	certSerialNumber)
+        {
+            this.name = name;
+            this.certSerialNumber = new DerInteger(certSerialNumber);
+        }
+
+		public IssuerAndSerialNumber(
+            X509Name	name,
+            DerInteger	certSerialNumber)
+        {
+            this.name = name;
+            this.certSerialNumber = certSerialNumber;
+        }
+
+		public X509Name Name
+		{
+			get { return name; }
+		}
+
+		public DerInteger CertificateSerialNumber
+		{
+			get { return certSerialNumber; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(name, certSerialNumber);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/KeyDerivationFunc.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/KeyDerivationFunc.cs
new file mode 100644
index 0000000..9fc8985
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/KeyDerivationFunc.cs
@@ -0,0 +1,21 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+	public class KeyDerivationFunc
+		: AlgorithmIdentifier
+	{
+		internal KeyDerivationFunc(Asn1Sequence seq)
+			: base(seq)
+		{
+		}
+
+		public KeyDerivationFunc(
+			DerObjectIdentifier	id,
+			Asn1Encodable		parameters)
+			: base(id, parameters)
+		{
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/MacData.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/MacData.cs
new file mode 100644
index 0000000..780b241
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/MacData.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class MacData
+        : Asn1Encodable
+    {
+        internal DigestInfo	digInfo;
+        internal byte[]		salt;
+        internal BigInteger	iterationCount;
+
+		public static MacData GetInstance(
+            object obj)
+        {
+            if (obj is MacData)
+            {
+                return (MacData) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new MacData((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		private MacData(
+            Asn1Sequence seq)
+        {
+            this.digInfo = DigestInfo.GetInstance(seq[0]);
+            this.salt = ((Asn1OctetString) seq[1]).GetOctets();
+
+			if (seq.Count == 3)
+            {
+                this.iterationCount = ((DerInteger) seq[2]).Value;
+            }
+            else
+            {
+                this.iterationCount = BigInteger.One;
+            }
+        }
+
+		public MacData(
+            DigestInfo	digInfo,
+            byte[]		salt,
+            int			iterationCount)
+        {
+            this.digInfo = digInfo;
+            this.salt = (byte[]) salt.Clone();
+            this.iterationCount = BigInteger.ValueOf(iterationCount);
+        }
+
+		public DigestInfo Mac
+		{
+			get { return digInfo; }
+		}
+
+		public byte[] GetSalt()
+        {
+            return (byte[]) salt.Clone();
+        }
+
+		public BigInteger IterationCount
+		{
+			get { return iterationCount; }
+		}
+
+		/**
+		 * <pre>
+		 * MacData ::= SEQUENCE {
+		 *     mac      DigestInfo,
+		 *     macSalt  OCTET STRING,
+		 *     iterations INTEGER DEFAULT 1
+		 *     -- Note: The default is for historic reasons and its use is deprecated. A
+		 *     -- higher value, like 1024 is recommended.
+		 * </pre>
+		 * @return the basic DERObject construction.
+		 */
+		public override Asn1Object ToAsn1Object()
+        {
+			Asn1EncodableVector v = new Asn1EncodableVector(digInfo, new DerOctetString(salt));
+
+			if (!iterationCount.Equals(BigInteger.One))
+			{
+				v.Add(new DerInteger(iterationCount));
+			}
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PBEParameter.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBEParameter.cs
new file mode 100644
index 0000000..80d5ec3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBEParameter.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+	public class PbeParameter
+		: Asn1Encodable
+	{
+		private readonly Asn1OctetString	salt;
+		private readonly DerInteger			iterationCount;
+
+		public static PbeParameter GetInstance(object obj)
+		{
+			if (obj is PbeParameter || obj == null)
+			{
+				return (PbeParameter) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new PbeParameter((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		private PbeParameter(Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			salt = Asn1OctetString.GetInstance(seq[0]);
+			iterationCount = DerInteger.GetInstance(seq[1]);
+		}
+
+		public PbeParameter(byte[] salt, int iterationCount)
+		{
+			this.salt = new DerOctetString(salt);
+			this.iterationCount = new DerInteger(iterationCount);
+		}
+
+		public byte[] GetSalt()
+		{
+			return salt.GetOctets();
+		}
+
+		public BigInteger IterationCount
+		{
+			get { return iterationCount.Value; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(salt, iterationCount);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PBES2Parameters.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBES2Parameters.cs
new file mode 100644
index 0000000..fc6904e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBES2Parameters.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class PbeS2Parameters
+        : Asn1Encodable
+    {
+        private readonly KeyDerivationFunc func;
+        private readonly EncryptionScheme scheme;
+
+        public static PbeS2Parameters GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            PbeS2Parameters existing = obj as PbeS2Parameters;
+            if (existing != null)
+                return existing;
+            return new PbeS2Parameters(Asn1Sequence.GetInstance(obj));
+        }
+
+        public PbeS2Parameters(KeyDerivationFunc keyDevFunc, EncryptionScheme encScheme)
+        {
+            this.func = keyDevFunc;
+            this.scheme = encScheme;
+        }
+
+        [Obsolete("Use GetInstance() instead")]
+        public PbeS2Parameters(
+            Asn1Sequence seq)
+        {
+            if (seq.Count != 2)
+                throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+            Asn1Sequence funcSeq = (Asn1Sequence)seq[0].ToAsn1Object();
+
+            // TODO Not sure if this special case is really necessary/appropriate
+            if (funcSeq[0].Equals(PkcsObjectIdentifiers.IdPbkdf2))
+            {
+                func = new KeyDerivationFunc(PkcsObjectIdentifiers.IdPbkdf2,
+                    Pbkdf2Params.GetInstance(funcSeq[1]));
+            }
+            else
+            {
+                func = new KeyDerivationFunc(funcSeq);
+            }
+
+            scheme = EncryptionScheme.GetInstance(seq[1].ToAsn1Object());
+        }
+
+        public KeyDerivationFunc KeyDerivationFunc
+        {
+            get { return func; }
+        }
+
+        public EncryptionScheme EncryptionScheme
+        {
+            get { return scheme; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(func, scheme);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PBKDF2Params.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBKDF2Params.cs
new file mode 100644
index 0000000..1351b94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PBKDF2Params.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+	public class Pbkdf2Params
+		: Asn1Encodable
+	{
+		private readonly Asn1OctetString	octStr;
+		private readonly DerInteger			iterationCount;
+		private readonly DerInteger			keyLength;
+
+		public static Pbkdf2Params GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is Pbkdf2Params)
+				return (Pbkdf2Params)obj;
+
+			if (obj is Asn1Sequence)
+				return new Pbkdf2Params((Asn1Sequence)obj);
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public Pbkdf2Params(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 2 || seq.Count > 3)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			octStr = (Asn1OctetString)seq[0];
+			iterationCount = (DerInteger)seq[1];
+
+			if (seq.Count > 2)
+			{
+				keyLength = (DerInteger)seq[2];
+			}
+		}
+
+		public Pbkdf2Params(
+			byte[] salt,
+			int iterationCount)
+		{
+			this.octStr = new DerOctetString(salt);
+			this.iterationCount = new DerInteger(iterationCount);
+		}
+
+        public Pbkdf2Params(
+            byte[]  salt,
+            int     iterationCount,
+            int     keyLength)
+            : this(salt, iterationCount)
+        {
+            this.keyLength = new DerInteger(keyLength);
+        }
+
+		public byte[] GetSalt()
+		{
+			return octStr.GetOctets();
+		}
+
+		public BigInteger IterationCount
+		{
+			get { return iterationCount.Value; }
+		}
+
+		public BigInteger KeyLength
+		{
+			get { return keyLength == null ? null : keyLength.Value; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				octStr, iterationCount);
+
+			if (keyLength != null)
+			{
+				v.Add(keyLength);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCS12PBEParams.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCS12PBEParams.cs
new file mode 100644
index 0000000..7521f93
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCS12PBEParams.cs
@@ -0,0 +1,63 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class Pkcs12PbeParams
+        : Asn1Encodable
+    {
+        private readonly DerInteger iterations;
+        private readonly Asn1OctetString iv;
+
+		public Pkcs12PbeParams(
+            byte[]	salt,
+            int		iterations)
+        {
+            this.iv = new DerOctetString(salt);
+            this.iterations = new DerInteger(iterations);
+        }
+
+		private Pkcs12PbeParams(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			iv = Asn1OctetString.GetInstance(seq[0]);
+            iterations = DerInteger.GetInstance(seq[1]);
+        }
+
+		public static Pkcs12PbeParams GetInstance(
+            object obj)
+        {
+            if (obj is Pkcs12PbeParams)
+            {
+                return (Pkcs12PbeParams) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new Pkcs12PbeParams((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public BigInteger Iterations
+		{
+			get { return iterations.Value; }
+		}
+
+		public byte[] GetIV()
+        {
+            return iv.GetOctets();
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(iv, iterations);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCSObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCSObjectIdentifiers.cs
new file mode 100644
index 0000000..0b2ffa0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PKCSObjectIdentifiers.cs
@@ -0,0 +1,256 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public abstract class PkcsObjectIdentifiers
+    {
+        //
+        // pkcs-1 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
+        //
+        public const string Pkcs1 = "1.2.840.113549.1.1";
+
+		public static readonly DerObjectIdentifier RsaEncryption			= new DerObjectIdentifier(Pkcs1 + ".1");
+        public static readonly DerObjectIdentifier MD2WithRsaEncryption		= new DerObjectIdentifier(Pkcs1 + ".2");
+        public static readonly DerObjectIdentifier MD4WithRsaEncryption		= new DerObjectIdentifier(Pkcs1 + ".3");
+        public static readonly DerObjectIdentifier MD5WithRsaEncryption		= new DerObjectIdentifier(Pkcs1 + ".4");
+        public static readonly DerObjectIdentifier Sha1WithRsaEncryption	= new DerObjectIdentifier(Pkcs1 + ".5");
+        public static readonly DerObjectIdentifier SrsaOaepEncryptionSet	= new DerObjectIdentifier(Pkcs1 + ".6");
+        public static readonly DerObjectIdentifier IdRsaesOaep				= new DerObjectIdentifier(Pkcs1 + ".7");
+        public static readonly DerObjectIdentifier IdMgf1					= new DerObjectIdentifier(Pkcs1 + ".8");
+        public static readonly DerObjectIdentifier IdPSpecified				= new DerObjectIdentifier(Pkcs1 + ".9");
+        public static readonly DerObjectIdentifier IdRsassaPss				= new DerObjectIdentifier(Pkcs1 + ".10");
+        public static readonly DerObjectIdentifier Sha256WithRsaEncryption	= new DerObjectIdentifier(Pkcs1 + ".11");
+        public static readonly DerObjectIdentifier Sha384WithRsaEncryption	= new DerObjectIdentifier(Pkcs1 + ".12");
+        public static readonly DerObjectIdentifier Sha512WithRsaEncryption	= new DerObjectIdentifier(Pkcs1 + ".13");
+        public static readonly DerObjectIdentifier Sha224WithRsaEncryption	= new DerObjectIdentifier(Pkcs1 + ".14");
+
+		//
+        // pkcs-3 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 3 }
+        //
+        public const string Pkcs3 = "1.2.840.113549.1.3";
+
+		public static readonly DerObjectIdentifier    DhKeyAgreement          = new DerObjectIdentifier(Pkcs3 + ".1");
+
+		//
+        // pkcs-5 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 }
+        //
+        public const string Pkcs5 = "1.2.840.113549.1.5";
+
+		public static readonly DerObjectIdentifier PbeWithMD2AndDesCbc    = new DerObjectIdentifier(Pkcs5 + ".1");
+        public static readonly DerObjectIdentifier PbeWithMD2AndRC2Cbc    = new DerObjectIdentifier(Pkcs5 + ".4");
+        public static readonly DerObjectIdentifier PbeWithMD5AndDesCbc    = new DerObjectIdentifier(Pkcs5 + ".3");
+        public static readonly DerObjectIdentifier PbeWithMD5AndRC2Cbc    = new DerObjectIdentifier(Pkcs5 + ".6");
+        public static readonly DerObjectIdentifier PbeWithSha1AndDesCbc   = new DerObjectIdentifier(Pkcs5 + ".10");
+        public static readonly DerObjectIdentifier PbeWithSha1AndRC2Cbc   = new DerObjectIdentifier(Pkcs5 + ".11");
+
+        public static readonly DerObjectIdentifier IdPbeS2 = new DerObjectIdentifier(Pkcs5 + ".13");
+        public static readonly DerObjectIdentifier IdPbkdf2	= new DerObjectIdentifier(Pkcs5 + ".12");
+
+		//
+        // encryptionAlgorithm OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) 3 }
+        //
+        public const string EncryptionAlgorithm = "1.2.840.113549.3";
+
+		public static readonly DerObjectIdentifier DesEde3Cbc	= new DerObjectIdentifier(EncryptionAlgorithm + ".7");
+        public static readonly DerObjectIdentifier RC2Cbc		= new DerObjectIdentifier(EncryptionAlgorithm + ".2");
+
+		//
+        // object identifiers for digests
+        //
+        public const string DigestAlgorithm = "1.2.840.113549.2";
+
+		//
+        // md2 OBJECT IDENTIFIER ::=
+        //      {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 2}
+        //
+        public static readonly DerObjectIdentifier MD2 = new DerObjectIdentifier(DigestAlgorithm + ".2");
+
+        //
+        // md4 OBJECT IDENTIFIER ::=
+        //      {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 4}
+        //
+        public static readonly DerObjectIdentifier MD4 = new DerObjectIdentifier(DigestAlgorithm + ".4");
+
+        //
+        // md5 OBJECT IDENTIFIER ::=
+        //      {iso(1) member-body(2) US(840) rsadsi(113549) DigestAlgorithm(2) 5}
+        //
+        public static readonly DerObjectIdentifier MD5 = new DerObjectIdentifier(DigestAlgorithm + ".5");
+
+		public static readonly DerObjectIdentifier IdHmacWithSha1	= new DerObjectIdentifier(DigestAlgorithm + ".7");
+        public static readonly DerObjectIdentifier IdHmacWithSha224	= new DerObjectIdentifier(DigestAlgorithm + ".8");
+        public static readonly DerObjectIdentifier IdHmacWithSha256	= new DerObjectIdentifier(DigestAlgorithm + ".9");
+        public static readonly DerObjectIdentifier IdHmacWithSha384	= new DerObjectIdentifier(DigestAlgorithm + ".10");
+        public static readonly DerObjectIdentifier IdHmacWithSha512	= new DerObjectIdentifier(DigestAlgorithm + ".11");
+
+		//
+        // pkcs-7 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 7 }
+        //
+        public const string Pkcs7 = "1.2.840.113549.1.7";
+
+		public static readonly DerObjectIdentifier Data                    = new DerObjectIdentifier(Pkcs7 + ".1");
+        public static readonly DerObjectIdentifier SignedData              = new DerObjectIdentifier(Pkcs7 + ".2");
+        public static readonly DerObjectIdentifier EnvelopedData           = new DerObjectIdentifier(Pkcs7 + ".3");
+        public static readonly DerObjectIdentifier SignedAndEnvelopedData  = new DerObjectIdentifier(Pkcs7 + ".4");
+        public static readonly DerObjectIdentifier DigestedData            = new DerObjectIdentifier(Pkcs7 + ".5");
+        public static readonly DerObjectIdentifier EncryptedData           = new DerObjectIdentifier(Pkcs7 + ".6");
+
+        //
+        // pkcs-9 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 }
+        //
+        public const string Pkcs9 = "1.2.840.113549.1.9";
+
+		public static readonly DerObjectIdentifier Pkcs9AtEmailAddress					= new DerObjectIdentifier(Pkcs9 + ".1");
+        public static readonly DerObjectIdentifier Pkcs9AtUnstructuredName				= new DerObjectIdentifier(Pkcs9 + ".2");
+        public static readonly DerObjectIdentifier Pkcs9AtContentType					= new DerObjectIdentifier(Pkcs9 + ".3");
+        public static readonly DerObjectIdentifier Pkcs9AtMessageDigest					= new DerObjectIdentifier(Pkcs9 + ".4");
+        public static readonly DerObjectIdentifier Pkcs9AtSigningTime					= new DerObjectIdentifier(Pkcs9 + ".5");
+        public static readonly DerObjectIdentifier Pkcs9AtCounterSignature				= new DerObjectIdentifier(Pkcs9 + ".6");
+        public static readonly DerObjectIdentifier Pkcs9AtChallengePassword				= new DerObjectIdentifier(Pkcs9 + ".7");
+        public static readonly DerObjectIdentifier Pkcs9AtUnstructuredAddress			= new DerObjectIdentifier(Pkcs9 + ".8");
+        public static readonly DerObjectIdentifier Pkcs9AtExtendedCertificateAttributes	= new DerObjectIdentifier(Pkcs9 + ".9");
+        public static readonly DerObjectIdentifier Pkcs9AtSigningDescription			= new DerObjectIdentifier(Pkcs9 + ".13");
+        public static readonly DerObjectIdentifier Pkcs9AtExtensionRequest				= new DerObjectIdentifier(Pkcs9 + ".14");
+        public static readonly DerObjectIdentifier Pkcs9AtSmimeCapabilities				= new DerObjectIdentifier(Pkcs9 + ".15");
+        public static readonly DerObjectIdentifier Pkcs9AtFriendlyName					= new DerObjectIdentifier(Pkcs9 + ".20");
+        public static readonly DerObjectIdentifier Pkcs9AtLocalKeyID					= new DerObjectIdentifier(Pkcs9 + ".21");
+
+		[Obsolete("Use X509Certificate instead")]
+        public static readonly DerObjectIdentifier X509CertType = new DerObjectIdentifier(Pkcs9 + ".22.1");
+
+		public const string CertTypes = Pkcs9 + ".22";
+		public static readonly DerObjectIdentifier X509Certificate = new DerObjectIdentifier(CertTypes + ".1");
+		public static readonly DerObjectIdentifier SdsiCertificate = new DerObjectIdentifier(CertTypes + ".2");
+
+		public const string CrlTypes = Pkcs9 + ".23";
+		public static readonly DerObjectIdentifier X509Crl = new DerObjectIdentifier(CrlTypes + ".1");
+
+		public static readonly DerObjectIdentifier IdAlgPwriKek = new DerObjectIdentifier(Pkcs9 + ".16.3.9");
+
+        //
+        // SMIME capability sub oids.
+        //
+        public static readonly DerObjectIdentifier PreferSignedData				= new DerObjectIdentifier(Pkcs9 + ".15.1");
+        public static readonly DerObjectIdentifier CannotDecryptAny				= new DerObjectIdentifier(Pkcs9 + ".15.2");
+        public static readonly DerObjectIdentifier SmimeCapabilitiesVersions	= new DerObjectIdentifier(Pkcs9 + ".15.3");
+
+        //
+        // other SMIME attributes
+        //
+		public static readonly DerObjectIdentifier IdAAReceiptRequest = new DerObjectIdentifier(Pkcs9 + ".16.2.1");
+
+        //
+        // id-ct OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+        // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1)}
+        //
+        public const string IdCT = "1.2.840.113549.1.9.16.1";
+
+        public static readonly DerObjectIdentifier IdCTAuthData          = new DerObjectIdentifier(IdCT + ".2");
+        public static readonly DerObjectIdentifier IdCTTstInfo           = new DerObjectIdentifier(IdCT + ".4");
+        public static readonly DerObjectIdentifier IdCTCompressedData    = new DerObjectIdentifier(IdCT + ".9");
+		public static readonly DerObjectIdentifier IdCTAuthEnvelopedData = new DerObjectIdentifier(IdCT + ".23");
+		public static readonly DerObjectIdentifier IdCTTimestampedData   = new DerObjectIdentifier(IdCT + ".31");
+
+        //
+        // id-cti OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+        // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) cti(6)}
+        //
+        public const string IdCti = "1.2.840.113549.1.9.16.6";
+
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfOrigin	= new DerObjectIdentifier(IdCti + ".1");
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfReceipt	= new DerObjectIdentifier(IdCti + ".2");
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfDelivery	= new DerObjectIdentifier(IdCti + ".3");
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfSender	= new DerObjectIdentifier(IdCti + ".4");
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfApproval	= new DerObjectIdentifier(IdCti + ".5");
+        public static readonly DerObjectIdentifier IdCtiEtsProofOfCreation	= new DerObjectIdentifier(IdCti + ".6");
+
+        //
+        // id-aa OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+        // rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) attributes(2)}
+        //
+        public const string IdAA = "1.2.840.113549.1.9.16.2";
+
+		public static readonly DerObjectIdentifier IdAAContentHint = new DerObjectIdentifier(IdAA + ".4"); // See RFC 2634
+    	public static readonly DerObjectIdentifier IdAAMsgSigDigest = new DerObjectIdentifier(IdAA + ".5");
+    	public static readonly DerObjectIdentifier IdAAContentReference = new DerObjectIdentifier(IdAA + ".10");
+
+		/*
+        * id-aa-encrypKeyPref OBJECT IDENTIFIER ::= {id-aa 11}
+        *
+        */
+        public static readonly DerObjectIdentifier IdAAEncrypKeyPref = new DerObjectIdentifier(IdAA + ".11");
+        public static readonly DerObjectIdentifier IdAASigningCertificate = new DerObjectIdentifier(IdAA + ".12");
+		public static readonly DerObjectIdentifier IdAASigningCertificateV2 = new DerObjectIdentifier(IdAA + ".47");
+
+		public static readonly DerObjectIdentifier IdAAContentIdentifier = new DerObjectIdentifier(IdAA + ".7"); // See RFC 2634
+
+		/*
+		 * RFC 3126
+		 */
+		public static readonly DerObjectIdentifier IdAASignatureTimeStampToken = new DerObjectIdentifier(IdAA + ".14");
+
+		public static readonly DerObjectIdentifier IdAAEtsSigPolicyID = new DerObjectIdentifier(IdAA + ".15");
+		public static readonly DerObjectIdentifier IdAAEtsCommitmentType = new DerObjectIdentifier(IdAA + ".16");
+		public static readonly DerObjectIdentifier IdAAEtsSignerLocation = new DerObjectIdentifier(IdAA + ".17");
+		public static readonly DerObjectIdentifier IdAAEtsSignerAttr = new DerObjectIdentifier(IdAA + ".18");
+		public static readonly DerObjectIdentifier IdAAEtsOtherSigCert = new DerObjectIdentifier(IdAA + ".19");
+		public static readonly DerObjectIdentifier IdAAEtsContentTimestamp = new DerObjectIdentifier(IdAA + ".20");
+		public static readonly DerObjectIdentifier IdAAEtsCertificateRefs = new DerObjectIdentifier(IdAA + ".21");
+		public static readonly DerObjectIdentifier IdAAEtsRevocationRefs = new DerObjectIdentifier(IdAA + ".22");
+		public static readonly DerObjectIdentifier IdAAEtsCertValues = new DerObjectIdentifier(IdAA + ".23");
+		public static readonly DerObjectIdentifier IdAAEtsRevocationValues = new DerObjectIdentifier(IdAA + ".24");
+		public static readonly DerObjectIdentifier IdAAEtsEscTimeStamp = new DerObjectIdentifier(IdAA + ".25");
+		public static readonly DerObjectIdentifier IdAAEtsCertCrlTimestamp = new DerObjectIdentifier(IdAA + ".26");
+		public static readonly DerObjectIdentifier IdAAEtsArchiveTimestamp = new DerObjectIdentifier(IdAA + ".27");
+
+		[Obsolete("Use 'IdAAEtsSigPolicyID' instead")]
+		public static readonly DerObjectIdentifier IdAASigPolicyID = IdAAEtsSigPolicyID;
+		[Obsolete("Use 'IdAAEtsCommitmentType' instead")]
+		public static readonly DerObjectIdentifier IdAACommitmentType = IdAAEtsCommitmentType;
+		[Obsolete("Use 'IdAAEtsSignerLocation' instead")]
+		public static readonly DerObjectIdentifier IdAASignerLocation = IdAAEtsSignerLocation;
+		[Obsolete("Use 'IdAAEtsOtherSigCert' instead")]
+		public static readonly DerObjectIdentifier IdAAOtherSigCert = IdAAEtsOtherSigCert;
+
+		//
+		// id-spq OBJECT IDENTIFIER ::= {iso(1) member-body(2) usa(840)
+		// rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) id-spq(5)}
+		//
+		public const string IdSpq = "1.2.840.113549.1.9.16.5";
+
+		public static readonly DerObjectIdentifier IdSpqEtsUri = new DerObjectIdentifier(IdSpq + ".1");
+		public static readonly DerObjectIdentifier IdSpqEtsUNotice = new DerObjectIdentifier(IdSpq + ".2");
+
+		//
+        // pkcs-12 OBJECT IDENTIFIER ::= {
+        //       iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 }
+        //
+        public const string Pkcs12 = "1.2.840.113549.1.12";
+        public const string BagTypes = Pkcs12 + ".10.1";
+
+        public static readonly DerObjectIdentifier KeyBag				= new DerObjectIdentifier(BagTypes + ".1");
+        public static readonly DerObjectIdentifier Pkcs8ShroudedKeyBag	= new DerObjectIdentifier(BagTypes + ".2");
+        public static readonly DerObjectIdentifier CertBag				= new DerObjectIdentifier(BagTypes + ".3");
+        public static readonly DerObjectIdentifier CrlBag				= new DerObjectIdentifier(BagTypes + ".4");
+        public static readonly DerObjectIdentifier SecretBag			= new DerObjectIdentifier(BagTypes + ".5");
+        public static readonly DerObjectIdentifier SafeContentsBag		= new DerObjectIdentifier(BagTypes + ".6");
+
+        public const string Pkcs12PbeIds = Pkcs12 + ".1";
+
+        public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC4			= new DerObjectIdentifier(Pkcs12PbeIds + ".1");
+        public static readonly DerObjectIdentifier PbeWithShaAnd40BitRC4			= new DerObjectIdentifier(Pkcs12PbeIds + ".2");
+        public static readonly DerObjectIdentifier PbeWithShaAnd3KeyTripleDesCbc	= new DerObjectIdentifier(Pkcs12PbeIds + ".3");
+        public static readonly DerObjectIdentifier PbeWithShaAnd2KeyTripleDesCbc	= new DerObjectIdentifier(Pkcs12PbeIds + ".4");
+        public static readonly DerObjectIdentifier PbeWithShaAnd128BitRC2Cbc		= new DerObjectIdentifier(Pkcs12PbeIds + ".5");
+        public static readonly DerObjectIdentifier PbewithShaAnd40BitRC2Cbc			= new DerObjectIdentifier(Pkcs12PbeIds + ".6");
+
+		public static readonly DerObjectIdentifier IdAlgCms3DesWrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6");
+		public static readonly DerObjectIdentifier IdAlgCmsRC2Wrap = new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/Pfx.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/Pfx.cs
new file mode 100644
index 0000000..9676f64
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/Pfx.cs
@@ -0,0 +1,65 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * the infamous Pfx from Pkcs12
+     */
+    public class Pfx
+        : Asn1Encodable
+    {
+        private ContentInfo	contentInfo;
+        private MacData		macData;
+
+		public Pfx(
+            Asn1Sequence seq)
+        {
+            BigInteger version = ((DerInteger) seq[0]).Value;
+            if (version.IntValue != 3)
+            {
+                throw new ArgumentException("wrong version for PFX PDU");
+            }
+
+			contentInfo = ContentInfo.GetInstance(seq[1]);
+
+			if (seq.Count == 3)
+            {
+                macData = MacData.GetInstance(seq[2]);
+            }
+        }
+
+		public Pfx(
+            ContentInfo	contentInfo,
+            MacData		macData)
+        {
+            this.contentInfo = contentInfo;
+            this.macData = macData;
+        }
+
+		public ContentInfo AuthSafe
+		{
+			get { return contentInfo; }
+		}
+
+		public MacData MacData
+		{
+			get { return macData; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				new DerInteger(3), contentInfo);
+
+			if (macData != null)
+            {
+                v.Add(macData);
+            }
+
+			return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/PrivateKeyInfo.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/PrivateKeyInfo.cs
new file mode 100644
index 0000000..404277b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/PrivateKeyInfo.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class PrivateKeyInfo
+        : Asn1Encodable
+    {
+        private readonly Asn1OctetString        privKey;
+        private readonly AlgorithmIdentifier	algID;
+        private readonly Asn1Set				attributes;
+
+        public static PrivateKeyInfo GetInstance(Asn1TaggedObject obj, bool explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static PrivateKeyInfo GetInstance(
+            object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is PrivateKeyInfo)
+                return (PrivateKeyInfo) obj;
+            return new PrivateKeyInfo(Asn1Sequence.GetInstance(obj));
+        }
+
+        public PrivateKeyInfo(AlgorithmIdentifier algID, Asn1Object privateKey)
+            : this(algID, privateKey, null)
+        {
+        }
+
+        public PrivateKeyInfo(
+            AlgorithmIdentifier	algID,
+            Asn1Object			privateKey,
+            Asn1Set				attributes)
+        {
+            this.algID = algID;
+            this.privKey = new DerOctetString(privateKey.GetEncoded(Asn1Encodable.Der));
+            this.attributes = attributes;
+        }
+
+        private PrivateKeyInfo(Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+            e.MoveNext();
+            BigInteger version = ((DerInteger)e.Current).Value;
+            if (version.IntValue != 0)
+            {
+                throw new ArgumentException("wrong version for private key info: " + version.IntValue);
+            }
+
+            e.MoveNext();
+            algID = AlgorithmIdentifier.GetInstance(e.Current);
+            e.MoveNext();
+            privKey = Asn1OctetString.GetInstance(e.Current);
+
+            if (e.MoveNext())
+            {
+                attributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false);
+            }
+        }
+
+        public virtual AlgorithmIdentifier PrivateKeyAlgorithm
+        {
+            get { return algID; }
+        }
+
+        [Obsolete("Use 'PrivateKeyAlgorithm' property instead")]
+        public virtual AlgorithmIdentifier AlgorithmID
+        {
+            get { return algID; }
+        }
+
+        public virtual Asn1Object ParsePrivateKey()
+        {
+            return Asn1Object.FromByteArray(privKey.GetOctets());
+        }
+
+        [Obsolete("Use 'ParsePrivateKey' instead")]
+        public virtual Asn1Object PrivateKey
+        {
+            get
+            {
+                try
+                {
+                    return ParsePrivateKey();
+                }
+                catch (IOException)
+                {
+                    throw new InvalidOperationException("unable to parse private key");
+                }
+            }
+        }
+
+        public virtual Asn1Set Attributes
+        {
+            get { return attributes; }
+        }
+
+        /**
+         * write out an RSA private key with its associated information
+         * as described in Pkcs8.
+         * <pre>
+         *      PrivateKeyInfo ::= Sequence {
+         *                              version Version,
+         *                              privateKeyAlgorithm AlgorithmIdentifier {{PrivateKeyAlgorithms}},
+         *                              privateKey PrivateKey,
+         *                              attributes [0] IMPLICIT Attributes OPTIONAL
+         *                          }
+         *      Version ::= Integer {v1(0)} (v1,...)
+         *
+         *      PrivateKey ::= OCTET STRING
+         *
+         *      Attributes ::= Set OF Attr
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(new DerInteger(0), algID, privKey);
+
+            if (attributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, attributes));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/RC2CBCParameter.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/RC2CBCParameter.cs
new file mode 100644
index 0000000..f5355d0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/RC2CBCParameter.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class RC2CbcParameter
+        : Asn1Encodable
+    {
+        internal DerInteger			version;
+        internal Asn1OctetString	iv;
+
+		public static RC2CbcParameter GetInstance(
+            object obj)
+        {
+            if (obj is Asn1Sequence)
+            {
+                return new RC2CbcParameter((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public RC2CbcParameter(
+            byte[] iv)
+        {
+            this.iv = new DerOctetString(iv);
+        }
+
+		public RC2CbcParameter(
+            int		parameterVersion,
+            byte[]	iv)
+        {
+            this.version = new DerInteger(parameterVersion);
+            this.iv = new DerOctetString(iv);
+        }
+
+		private RC2CbcParameter(
+            Asn1Sequence seq)
+        {
+            if (seq.Count == 1)
+            {
+                iv = (Asn1OctetString)seq[0];
+            }
+            else
+            {
+                version = (DerInteger)seq[0];
+                iv = (Asn1OctetString)seq[1];
+            }
+        }
+
+		public BigInteger RC2ParameterVersion
+        {
+            get
+            {
+				return version == null ? null : version.Value;
+            }
+        }
+
+		public byte[] GetIV()
+        {
+			return Arrays.Clone(iv.GetOctets());
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (version != null)
+            {
+                v.Add(version);
+            }
+
+			v.Add(iv);
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAESOAEPparams.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAESOAEPparams.cs
new file mode 100644
index 0000000..5ecb394
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAESOAEPparams.cs
@@ -0,0 +1,145 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+	public class RsaesOaepParameters
+		: Asn1Encodable
+	{
+		private AlgorithmIdentifier hashAlgorithm;
+		private AlgorithmIdentifier maskGenAlgorithm;
+		private AlgorithmIdentifier pSourceAlgorithm;
+
+		public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+		public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+		public readonly static AlgorithmIdentifier DefaultPSourceAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]));
+
+		public static RsaesOaepParameters GetInstance(
+			object obj)
+		{
+			if (obj is RsaesOaepParameters)
+			{
+				return (RsaesOaepParameters)obj;
+			}
+			else if (obj is Asn1Sequence)
+			{
+				return new RsaesOaepParameters((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		/**
+		 * The default version
+		 */
+		public RsaesOaepParameters()
+		{
+			hashAlgorithm = DefaultHashAlgorithm;
+			maskGenAlgorithm = DefaultMaskGenFunction;
+			pSourceAlgorithm = DefaultPSourceAlgorithm;
+		}
+
+		public RsaesOaepParameters(
+			AlgorithmIdentifier hashAlgorithm,
+			AlgorithmIdentifier maskGenAlgorithm,
+			AlgorithmIdentifier pSourceAlgorithm)
+		{
+			this.hashAlgorithm = hashAlgorithm;
+			this.maskGenAlgorithm = maskGenAlgorithm;
+			this.pSourceAlgorithm = pSourceAlgorithm;
+		}
+
+		public RsaesOaepParameters(
+			Asn1Sequence seq)
+		{
+			hashAlgorithm = DefaultHashAlgorithm;
+			maskGenAlgorithm = DefaultMaskGenFunction;
+			pSourceAlgorithm = DefaultPSourceAlgorithm;
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
+
+				switch (o.TagNo)
+				{
+					case 0:
+						hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+						break;
+					case 1:
+						maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+						break;
+					case 2:
+						pSourceAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+						break;
+					default:
+						throw new ArgumentException("unknown tag");
+				}
+			}
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public AlgorithmIdentifier MaskGenAlgorithm
+		{
+			get { return maskGenAlgorithm; }
+		}
+
+		public AlgorithmIdentifier PSourceAlgorithm
+		{
+			get { return pSourceAlgorithm; }
+		}
+
+		/**
+		 * <pre>
+		 *  RSAES-OAEP-params ::= SEQUENCE {
+		 *     hashAlgorithm      [0] OAEP-PSSDigestAlgorithms     DEFAULT sha1,
+		 *     maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+		 *     pSourceAlgorithm   [2] PKCS1PSourceAlgorithms  DEFAULT pSpecifiedEmpty
+		 *   }
+		 *
+		 *   OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+		 *     { OID id-sha1 PARAMETERS NULL   }|
+		 *     { OID id-sha256 PARAMETERS NULL }|
+		 *     { OID id-sha384 PARAMETERS NULL }|
+		 *     { OID id-sha512 PARAMETERS NULL },
+		 *     ...  -- Allows for future expansion --
+		 *   }
+		 *   PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+		 *     { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+		 *    ...  -- Allows for future expansion --
+		 *   }
+		 *   PKCS1PSourceAlgorithms    ALGORITHM-IDENTIFIER ::= {
+		 *     { OID id-pSpecified PARAMETERS OCTET STRING },
+		 *     ...  -- Allows for future expansion --
+		 *  }
+		 * </pre>
+		 * @return the asn1 primitive representing the parameters.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+			{
+				v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+			}
+
+			if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+			{
+				v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+			}
+
+			if (!pSourceAlgorithm.Equals(DefaultPSourceAlgorithm))
+			{
+				v.Add(new DerTaggedObject(true, 2, pSourceAlgorithm));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAPrivateKeyStructure.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAPrivateKeyStructure.cs
new file mode 100644
index 0000000..7212991
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSAPrivateKeyStructure.cs
@@ -0,0 +1,146 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class RsaPrivateKeyStructure
+        : Asn1Encodable
+    {
+        private readonly BigInteger	modulus;
+        private readonly BigInteger	publicExponent;
+        private readonly BigInteger	privateExponent;
+        private readonly BigInteger	prime1;
+        private readonly BigInteger	prime2;
+        private readonly BigInteger	exponent1;
+        private readonly BigInteger	exponent2;
+        private readonly BigInteger	coefficient;
+
+        public static RsaPrivateKeyStructure GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        public static RsaPrivateKeyStructure GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is RsaPrivateKeyStructure)
+                return (RsaPrivateKeyStructure)obj;
+            return new RsaPrivateKeyStructure(Asn1Sequence.GetInstance(obj));
+        }
+
+        public RsaPrivateKeyStructure(
+            BigInteger	modulus,
+            BigInteger	publicExponent,
+            BigInteger	privateExponent,
+            BigInteger	prime1,
+            BigInteger	prime2,
+            BigInteger	exponent1,
+            BigInteger	exponent2,
+            BigInteger	coefficient)
+        {
+            this.modulus = modulus;
+            this.publicExponent = publicExponent;
+            this.privateExponent = privateExponent;
+            this.prime1 = prime1;
+            this.prime2 = prime2;
+            this.exponent1 = exponent1;
+            this.exponent2 = exponent2;
+            this.coefficient = coefficient;
+        }
+
+        [Obsolete("Use 'GetInstance' method(s) instead")]
+        public RsaPrivateKeyStructure(
+            Asn1Sequence seq)
+        {
+            BigInteger version = ((DerInteger) seq[0]).Value;
+            if (version.IntValue != 0)
+                throw new ArgumentException("wrong version for RSA private key");
+
+            modulus = ((DerInteger) seq[1]).Value;
+            publicExponent = ((DerInteger) seq[2]).Value;
+            privateExponent = ((DerInteger) seq[3]).Value;
+            prime1 = ((DerInteger) seq[4]).Value;
+            prime2 = ((DerInteger) seq[5]).Value;
+            exponent1 = ((DerInteger) seq[6]).Value;
+            exponent2 = ((DerInteger) seq[7]).Value;
+            coefficient = ((DerInteger) seq[8]).Value;
+        }
+
+        public BigInteger Modulus
+        {
+            get { return modulus; }
+        }
+
+        public BigInteger PublicExponent
+        {
+            get { return publicExponent; }
+        }
+
+        public BigInteger PrivateExponent
+        {
+            get { return privateExponent; }
+        }
+
+        public BigInteger Prime1
+        {
+            get { return prime1; }
+        }
+
+        public BigInteger Prime2
+        {
+            get { return prime2; }
+        }
+
+        public BigInteger Exponent1
+        {
+            get { return exponent1; }
+        }
+
+        public BigInteger Exponent2
+        {
+            get { return exponent2; }
+        }
+
+        public BigInteger Coefficient
+        {
+            get { return coefficient; }
+        }
+
+        /**
+         * This outputs the key in Pkcs1v2 format.
+         * <pre>
+         *      RsaPrivateKey ::= Sequence {
+         *                          version Version,
+         *                          modulus Integer, -- n
+         *                          publicExponent Integer, -- e
+         *                          privateExponent Integer, -- d
+         *                          prime1 Integer, -- p
+         *                          prime2 Integer, -- q
+         *                          exponent1 Integer, -- d mod (p-1)
+         *                          exponent2 Integer, -- d mod (q-1)
+         *                          coefficient Integer -- (inverse of q) mod p
+         *                      }
+         *
+         *      Version ::= Integer
+         * </pre>
+         * <p>This routine is written to output Pkcs1 version 0, private keys.</p>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(
+                new DerInteger(0), // version
+                new DerInteger(Modulus),
+                new DerInteger(PublicExponent),
+                new DerInteger(PrivateExponent),
+                new DerInteger(Prime1),
+                new DerInteger(Prime2),
+                new DerInteger(Exponent1),
+                new DerInteger(Exponent2),
+                new DerInteger(Coefficient));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/RSASSAPSSparams.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSASSAPSSparams.cs
new file mode 100644
index 0000000..9416207
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/RSASSAPSSparams.cs
@@ -0,0 +1,165 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+	public class RsassaPssParameters
+		: Asn1Encodable
+	{
+		private AlgorithmIdentifier hashAlgorithm;
+		private AlgorithmIdentifier maskGenAlgorithm;
+		private DerInteger saltLength;
+		private DerInteger trailerField;
+
+		public readonly static AlgorithmIdentifier DefaultHashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+		public readonly static AlgorithmIdentifier DefaultMaskGenFunction = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, DefaultHashAlgorithm);
+		public readonly static DerInteger DefaultSaltLength = new DerInteger(20);
+		public readonly static DerInteger DefaultTrailerField = new DerInteger(1);
+
+		public static RsassaPssParameters GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is RsassaPssParameters)
+			{
+				return (RsassaPssParameters)obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new RsassaPssParameters((Asn1Sequence)obj);
+			}
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		/**
+		 * The default version
+		 */
+		public RsassaPssParameters()
+		{
+			hashAlgorithm = DefaultHashAlgorithm;
+			maskGenAlgorithm = DefaultMaskGenFunction;
+			saltLength = DefaultSaltLength;
+			trailerField = DefaultTrailerField;
+		}
+
+		public RsassaPssParameters(
+			AlgorithmIdentifier hashAlgorithm,
+			AlgorithmIdentifier maskGenAlgorithm,
+			DerInteger saltLength,
+			DerInteger trailerField)
+		{
+			this.hashAlgorithm = hashAlgorithm;
+			this.maskGenAlgorithm = maskGenAlgorithm;
+			this.saltLength = saltLength;
+			this.trailerField = trailerField;
+		}
+
+		public RsassaPssParameters(
+			Asn1Sequence seq)
+		{
+			hashAlgorithm = DefaultHashAlgorithm;
+			maskGenAlgorithm = DefaultMaskGenFunction;
+			saltLength = DefaultSaltLength;
+			trailerField = DefaultTrailerField;
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				Asn1TaggedObject o = (Asn1TaggedObject)seq[i];
+
+				switch (o.TagNo)
+				{
+					case 0:
+						hashAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+						break;
+					case 1:
+						maskGenAlgorithm = AlgorithmIdentifier.GetInstance(o, true);
+						break;
+					case 2:
+						saltLength = DerInteger.GetInstance(o, true);
+						break;
+					case 3:
+						trailerField = DerInteger.GetInstance(o, true);
+						break;
+					default:
+						throw new ArgumentException("unknown tag");
+				}
+			}
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public AlgorithmIdentifier MaskGenAlgorithm
+		{
+			get { return maskGenAlgorithm; }
+		}
+
+		public DerInteger SaltLength
+		{
+			get { return saltLength; }
+		}
+
+		public DerInteger TrailerField
+		{
+			get { return trailerField; }
+		}
+
+		/**
+		 * <pre>
+		 * RSASSA-PSS-params ::= SEQUENCE {
+		 *   hashAlgorithm      [0] OAEP-PSSDigestAlgorithms  DEFAULT sha1,
+		 *    maskGenAlgorithm   [1] PKCS1MGFAlgorithms  DEFAULT mgf1SHA1,
+		 *    saltLength         [2] INTEGER  DEFAULT 20,
+		 *    trailerField       [3] TrailerField  DEFAULT trailerFieldBC
+		 *  }
+		 *
+		 * OAEP-PSSDigestAlgorithms    ALGORITHM-IDENTIFIER ::= {
+		 *    { OID id-sha1 PARAMETERS NULL   }|
+		 *    { OID id-sha256 PARAMETERS NULL }|
+		 *    { OID id-sha384 PARAMETERS NULL }|
+		 *    { OID id-sha512 PARAMETERS NULL },
+		 *    ...  -- Allows for future expansion --
+		 * }
+		 *
+		 * PKCS1MGFAlgorithms    ALGORITHM-IDENTIFIER ::= {
+		 *   { OID id-mgf1 PARAMETERS OAEP-PSSDigestAlgorithms },
+		 *    ...  -- Allows for future expansion --
+		 * }
+		 *
+		 * TrailerField ::= INTEGER { trailerFieldBC(1) }
+		 * </pre>
+		 * @return the asn1 primitive representing the parameters.
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (!hashAlgorithm.Equals(DefaultHashAlgorithm))
+			{
+				v.Add(new DerTaggedObject(true, 0, hashAlgorithm));
+			}
+
+			if (!maskGenAlgorithm.Equals(DefaultMaskGenFunction))
+			{
+				v.Add(new DerTaggedObject(true, 1, maskGenAlgorithm));
+			}
+
+			if (!saltLength.Equals(DefaultSaltLength))
+			{
+				v.Add(new DerTaggedObject(true, 2, saltLength));
+			}
+
+			if (!trailerField.Equals(DefaultTrailerField))
+			{
+				v.Add(new DerTaggedObject(true, 3, trailerField));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/SafeBag.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/SafeBag.cs
new file mode 100644
index 0000000..4b9350b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/SafeBag.cs
@@ -0,0 +1,70 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    public class SafeBag
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier bagID;
+        private readonly Asn1Object bagValue;
+        private readonly Asn1Set bagAttributes;
+
+		public SafeBag(
+            DerObjectIdentifier	oid,
+            Asn1Object			obj)
+        {
+            this.bagID = oid;
+            this.bagValue = obj;
+            this.bagAttributes = null;
+        }
+
+		public SafeBag(
+            DerObjectIdentifier	oid,
+            Asn1Object			obj,
+            Asn1Set				bagAttributes)
+        {
+            this.bagID = oid;
+            this.bagValue = obj;
+            this.bagAttributes = bagAttributes;
+        }
+
+		public SafeBag(
+            Asn1Sequence seq)
+        {
+            this.bagID = (DerObjectIdentifier) seq[0];
+            this.bagValue = ((DerTaggedObject) seq[1]).GetObject();
+            if (seq.Count == 3)
+            {
+                this.bagAttributes = (Asn1Set) seq[2];
+            }
+        }
+
+		public DerObjectIdentifier BagID
+		{
+			get { return bagID; }
+		}
+
+		public Asn1Object BagValue
+		{
+			get { return bagValue; }
+		}
+
+		public Asn1Set BagAttributes
+		{
+			get { return bagAttributes; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				bagID, new DerTaggedObject(0, bagValue));
+
+			if (bagAttributes != null)
+            {
+                v.Add(bagAttributes);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/SignedData.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/SignedData.cs
new file mode 100644
index 0000000..6e72bd0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/SignedData.cs
@@ -0,0 +1,157 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * a Pkcs#7 signed data object.
+     */
+    public class SignedData
+        : Asn1Encodable
+    {
+        private readonly DerInteger		version;
+        private readonly Asn1Set		digestAlgorithms;
+        private readonly ContentInfo	contentInfo;
+        private readonly Asn1Set		certificates;
+        private readonly Asn1Set		crls;
+        private readonly Asn1Set		signerInfos;
+
+        public static SignedData GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            SignedData existing = obj as SignedData;
+            if (existing != null)
+                return existing;
+            return new SignedData(Asn1Sequence.GetInstance(obj));
+        }
+
+        public SignedData(
+            DerInteger        _version,
+            Asn1Set           _digestAlgorithms,
+            ContentInfo       _contentInfo,
+            Asn1Set           _certificates,
+            Asn1Set           _crls,
+            Asn1Set           _signerInfos)
+        {
+            version          = _version;
+            digestAlgorithms = _digestAlgorithms;
+            contentInfo      = _contentInfo;
+            certificates     = _certificates;
+            crls             = _crls;
+            signerInfos      = _signerInfos;
+        }
+
+        private SignedData(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+            e.MoveNext();
+            version = (DerInteger) e.Current;
+
+            e.MoveNext();
+            digestAlgorithms = (Asn1Set) e.Current;
+
+            e.MoveNext();
+            contentInfo = ContentInfo.GetInstance(e.Current);
+
+            while (e.MoveNext())
+            {
+                Asn1Object o = (Asn1Object) e.Current;
+
+                //
+                // an interesting feature of SignedData is that there appear to be varying implementations...
+                // for the moment we ignore anything which doesn't fit.
+                //
+                if (o is DerTaggedObject)
+                {
+                    DerTaggedObject tagged = (DerTaggedObject) o;
+
+                    switch (tagged.TagNo)
+                    {
+                        case 0:
+                            certificates = Asn1Set.GetInstance(tagged, false);
+                            break;
+                        case 1:
+                            crls = Asn1Set.GetInstance(tagged, false);
+                            break;
+                        default:
+                            throw new ArgumentException("unknown tag value " + tagged.TagNo);
+                    }
+                }
+                else
+                {
+                    signerInfos = (Asn1Set) o;
+                }
+            }
+        }
+
+        public DerInteger Version
+        {
+            get { return version; }
+        }
+
+        public Asn1Set DigestAlgorithms
+        {
+            get { return digestAlgorithms; }
+        }
+
+        public ContentInfo ContentInfo
+        {
+            get { return contentInfo; }
+        }
+
+        public Asn1Set Certificates
+        {
+            get { return certificates; }
+        }
+
+        public Asn1Set Crls
+        {
+            get { return crls; }
+        }
+
+        public Asn1Set SignerInfos
+        {
+            get { return signerInfos; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  SignedData ::= Sequence {
+         *      version Version,
+         *      digestAlgorithms DigestAlgorithmIdentifiers,
+         *      contentInfo ContentInfo,
+         *      certificates
+         *          [0] IMPLICIT ExtendedCertificatesAndCertificates
+         *                   OPTIONAL,
+         *      crls
+         *          [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+         *      signerInfos SignerInfos }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                version, digestAlgorithms, contentInfo);
+
+            if (certificates != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, certificates));
+            }
+
+            if (crls != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, crls));
+            }
+
+            v.Add(signerInfos);
+
+            return new BerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/pkcs/SignerInfo.cs b/BouncyCastle.AxCrypt/src/asn1/pkcs/SignerInfo.cs
new file mode 100644
index 0000000..1e46945
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/pkcs/SignerInfo.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Pkcs
+{
+    /**
+     * a Pkcs#7 signer info object.
+     */
+    public class SignerInfo
+        : Asn1Encodable
+    {
+        private DerInteger              version;
+        private IssuerAndSerialNumber   issuerAndSerialNumber;
+        private AlgorithmIdentifier     digAlgorithm;
+        private Asn1Set                 authenticatedAttributes;
+        private AlgorithmIdentifier     digEncryptionAlgorithm;
+        private Asn1OctetString         encryptedDigest;
+        private Asn1Set                 unauthenticatedAttributes;
+
+		public static SignerInfo GetInstance(
+            object obj)
+        {
+            if (obj is SignerInfo)
+            {
+                return (SignerInfo) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SignerInfo((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		public SignerInfo(
+            DerInteger              version,
+            IssuerAndSerialNumber   issuerAndSerialNumber,
+            AlgorithmIdentifier     digAlgorithm,
+            Asn1Set                 authenticatedAttributes,
+            AlgorithmIdentifier     digEncryptionAlgorithm,
+            Asn1OctetString         encryptedDigest,
+            Asn1Set                 unauthenticatedAttributes)
+        {
+            this.version = version;
+            this.issuerAndSerialNumber = issuerAndSerialNumber;
+            this.digAlgorithm = digAlgorithm;
+            this.authenticatedAttributes = authenticatedAttributes;
+            this.digEncryptionAlgorithm = digEncryptionAlgorithm;
+            this.encryptedDigest = encryptedDigest;
+            this.unauthenticatedAttributes = unauthenticatedAttributes;
+        }
+
+		public SignerInfo(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+            version = (DerInteger) e.Current;
+
+			e.MoveNext();
+            issuerAndSerialNumber = IssuerAndSerialNumber.GetInstance(e.Current);
+
+			e.MoveNext();
+            digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+
+			e.MoveNext();
+            object obj = e.Current;
+
+			if (obj is Asn1TaggedObject)
+            {
+                authenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject) obj, false);
+
+				e.MoveNext();
+                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current);
+            }
+            else
+            {
+                authenticatedAttributes = null;
+                digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj);
+            }
+
+			e.MoveNext();
+            encryptedDigest = DerOctetString.GetInstance(e.Current);
+
+			if (e.MoveNext())
+            {
+                unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current, false);
+            }
+            else
+            {
+                unauthenticatedAttributes = null;
+            }
+        }
+
+		public DerInteger Version { get { return version; } }
+
+		public IssuerAndSerialNumber IssuerAndSerialNumber { get { return issuerAndSerialNumber; } }
+
+		public Asn1Set AuthenticatedAttributes { get { return authenticatedAttributes; } }
+
+		public AlgorithmIdentifier DigestAlgorithm { get { return digAlgorithm; } }
+
+		public Asn1OctetString EncryptedDigest { get { return encryptedDigest; } }
+
+		public AlgorithmIdentifier DigestEncryptionAlgorithm { get { return digEncryptionAlgorithm; } }
+
+		public Asn1Set UnauthenticatedAttributes { get { return unauthenticatedAttributes; } }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  SignerInfo ::= Sequence {
+         *      version Version,
+         *      issuerAndSerialNumber IssuerAndSerialNumber,
+         *      digestAlgorithm DigestAlgorithmIdentifier,
+         *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+         *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+         *      encryptedDigest EncryptedDigest,
+         *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+         *  }
+         *
+         *  EncryptedDigest ::= OCTET STRING
+         *
+         *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+         *
+         *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				version, issuerAndSerialNumber, digAlgorithm);
+
+			if (authenticatedAttributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, authenticatedAttributes));
+            }
+
+			v.Add(digEncryptionAlgorithm, encryptedDigest);
+
+			if (unauthenticatedAttributes != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, unauthenticatedAttributes));
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/sec/ECPrivateKeyStructure.cs b/BouncyCastle.AxCrypt/src/asn1/sec/ECPrivateKeyStructure.cs
new file mode 100644
index 0000000..8d805fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/sec/ECPrivateKeyStructure.cs
@@ -0,0 +1,126 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+    /**
+     * the elliptic curve private key object from SEC 1
+     */
+    public class ECPrivateKeyStructure
+        : Asn1Encodable
+    {
+        private readonly Asn1Sequence seq;
+
+        public static ECPrivateKeyStructure GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is ECPrivateKeyStructure)
+                return (ECPrivateKeyStructure)obj;
+            return new ECPrivateKeyStructure(Asn1Sequence.GetInstance(obj));
+        }
+
+        public ECPrivateKeyStructure(
+            Asn1Sequence seq)
+        {
+            if (seq == null)
+                throw new ArgumentNullException("seq");
+
+            this.seq = seq;
+        }
+
+        public ECPrivateKeyStructure(
+            BigInteger key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            this.seq = new DerSequence(
+                new DerInteger(1),
+                new DerOctetString(key.ToByteArrayUnsigned()));
+        }
+
+        public ECPrivateKeyStructure(
+            BigInteger		key,
+            Asn1Encodable	parameters)
+            : this(key, null, parameters)
+        {
+        }
+
+        public ECPrivateKeyStructure(
+            BigInteger		key,
+            DerBitString	publicKey,
+            Asn1Encodable	parameters)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                new DerInteger(1),
+                new DerOctetString(key.ToByteArrayUnsigned()));
+
+            if (parameters != null)
+            {
+                v.Add(new DerTaggedObject(true, 0, parameters));
+            }
+
+            if (publicKey != null)
+            {
+                v.Add(new DerTaggedObject(true, 1, publicKey));
+            }
+
+            this.seq = new DerSequence(v);
+        }
+
+        public virtual BigInteger GetKey()
+        {
+            Asn1OctetString octs = (Asn1OctetString) seq[1];
+
+            return new BigInteger(1, octs.GetOctets());
+        }
+
+        public virtual DerBitString GetPublicKey()
+        {
+            return (DerBitString) GetObjectInTag(1);
+        }
+
+        public virtual Asn1Object GetParameters()
+        {
+            return GetObjectInTag(0);
+        }
+
+        private Asn1Object GetObjectInTag(int tagNo)
+        {
+            foreach (Asn1Encodable ae in seq)
+            {
+                Asn1Object obj = ae.ToAsn1Object();
+
+                if (obj is Asn1TaggedObject)
+                {
+                    Asn1TaggedObject tag = (Asn1TaggedObject) obj;
+                    if (tag.TagNo == tagNo)
+                    {
+                        return tag.GetObject();
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        /**
+         * ECPrivateKey ::= SEQUENCE {
+         *     version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
+         *     privateKey OCTET STRING,
+         *     parameters [0] Parameters OPTIONAL,
+         *     publicKey [1] BIT STRING OPTIONAL }
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/sec/SECNamedCurves.cs b/BouncyCastle.AxCrypt/src/asn1/sec/SECNamedCurves.cs
new file mode 100644
index 0000000..60d456e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/sec/SECNamedCurves.cs
@@ -0,0 +1,1253 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+    public sealed class SecNamedCurves
+    {
+        private SecNamedCurves()
+        {
+        }
+
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
+        private static ECCurve ConfigureCurveGlv(ECCurve c, GlvTypeBParameters p)
+        {
+            return c.Configure().SetEndomorphism(new GlvTypeBEndomorphism(c, p)).Create();
+        }
+
+        private static BigInteger FromHex(string hex)
+        {
+            return new BigInteger(1, Hex.Decode(hex));
+        }
+
+        /*
+         * secp112r1
+         */
+        internal class Secp112r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp112r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp112r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = (2^128 - 3) / 76439
+                BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B");
+                BigInteger a = FromHex("DB7C2ABF62E35E668076BEAD2088");
+                BigInteger b = FromHex("659EF8BA043916EEDE8911702B22");
+                byte[] S = Hex.Decode("00F50B028E4D696E676875615175290472783FB1");
+                BigInteger n = FromHex("DB7C2ABF62E35E7628DFAC6561C5");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "09487239995A5EE76B55F9C2F098"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "09487239995A5EE76B55F9C2F098"
+                    + "A89CE5AF8724C0A23E0E0FF77500"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp112r2
+         */
+        internal class Secp112r2Holder
+            : X9ECParametersHolder
+        {
+            private Secp112r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp112r2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = (2^128 - 3) / 76439
+                BigInteger p = FromHex("DB7C2ABF62E35E668076BEAD208B");
+                BigInteger a = FromHex("6127C24C05F38A0AAAF65C0EF02C");
+                BigInteger b = FromHex("51DEF1815DB5ED74FCC34C85D709");
+                byte[] S = Hex.Decode("002757A1114D696E6768756151755316C05E0BD4");
+                BigInteger n = FromHex("36DF0AAFD8B8D7597CA10520D04B");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "4BA30AB5E892B4E1649DD0928643"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "4BA30AB5E892B4E1649DD0928643"
+                    + "ADCD46F5882E3747DEF36E956E97"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp128r1
+         */
+        internal class Secp128r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp128r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp128r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^128 - 2^97 - 1
+                BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+                BigInteger a = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC");
+                BigInteger b = FromHex("E87579C11079F43DD824993C2CEE5ED3");
+                byte[] S = Hex.Decode("000E0D4D696E6768756151750CC03A4473D03679");
+                BigInteger n = FromHex("FFFFFFFE0000000075A30D1B9038A115");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "161FF7528B899B2D0C28607CA52C5B86"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "161FF7528B899B2D0C28607CA52C5B86"
+                    + "CF5AC8395BAFEB13C02DA292DDED7A83"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp128r2
+         */
+        internal class Secp128r2Holder
+            : X9ECParametersHolder
+        {
+            private Secp128r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp128r2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^128 - 2^97 - 1
+                BigInteger p = FromHex("FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF");
+                BigInteger a = FromHex("D6031998D1B3BBFEBF59CC9BBFF9AEE1");
+                BigInteger b = FromHex("5EEEFCA380D02919DC2C6558BB6D8A5D");
+                byte[] S = Hex.Decode("004D696E67687561517512D8F03431FCE63B88F4");
+                BigInteger n = FromHex("3FFFFFFF7FFFFFFFBE0024720613B5A3");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "7B6AA5D85E572983E6FB32A7CDEBC140"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "7B6AA5D85E572983E6FB32A7CDEBC140"
+                    + "27B6916A894D3AEE7106FE805FC34B44"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp160k1
+         */
+        internal class Secp160k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp160k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp160k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.ValueOf(7);
+                byte[] S = null;
+                BigInteger n = FromHex("0100000000000000000001B8FA16DFAB9ACA16B6B3");
+                BigInteger h = BigInteger.One;
+
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("9ba48cba5ebcb9b6bd33b92830b2a2e0e192f10a", 16),
+                    new BigInteger("c39c6c3b3a36d7701b9c71a1f5804ae5d0003f4", 16),
+                    new BigInteger[]{
+                        new BigInteger("9162fbe73984472a0a9e", 16),
+                        new BigInteger("-96341f1138933bc2f505", 16) },
+                    new BigInteger[]{
+                        new BigInteger("127971af8721782ecffa3", 16),
+                        new BigInteger("9162fbe73984472a0a9e", 16) },
+                    new BigInteger("9162fbe73984472a0a9d0590", 16),
+                    new BigInteger("96341f1138933bc2f503fd44", 16),
+                    176);
+
+                ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                    //+ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB"
+                    + "938CF935318FDCED6BC28286531733C3F03C4FEE"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp160r1
+         */
+        internal class Secp160r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp160r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp160r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^160 - 2^31 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF");
+                BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC");
+                BigInteger b = FromHex("1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45");
+                byte[] S = Hex.Decode("1053CDE42C14D696E67687561517533BF3F83345");
+                BigInteger n = FromHex("0100000000000000000001F4C8F927AED3CA752257");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                    //+ "4A96B5688EF573284664698968C38BB913CBFC82"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "4A96B5688EF573284664698968C38BB913CBFC82"
+                    + "23A628553168947D59DCC912042351377AC5FB32"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp160r2
+         */
+        internal class Secp160r2Holder
+            : X9ECParametersHolder
+        {
+            private Secp160r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp160r2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^160 - 2^32 - 2^14 - 2^12 - 2^9 - 2^8 - 2^7 - 2^3 - 2^2 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73");
+                BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70");
+                BigInteger b = FromHex("B4E134D3FB59EB8BAB57274904664D5AF50388BA");
+                byte[] S = Hex.Decode("B99B99B099B323E02709A4D696E6768756151751");
+                BigInteger n = FromHex("0100000000000000000000351EE786A818F3A1A16B");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "52DCB034293A117E1F4FF11B30F7199D3144CE6D"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "52DCB034293A117E1F4FF11B30F7199D3144CE6D"
+                    + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp192k1
+         */
+        internal class Secp192k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp192k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp192k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37");
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.ValueOf(3);
+                byte[] S = null;
+                BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D");
+                BigInteger h = BigInteger.One;
+
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+                    new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+                    new BigInteger[]{
+                        new BigInteger("71169be7330b3038edb025f1", 16),
+                        new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+                    new BigInteger[]{
+                        new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+                        new BigInteger("71169be7330b3038edb025f1", 16) },
+                    new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+                    new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+                    208);
+
+                ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+                    + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp192r1
+         */
+        internal class Secp192r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp192r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp192r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^192 - 2^64 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF");
+                BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC");
+                BigInteger b = FromHex("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1");
+                byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+                BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+                    + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp224k1
+         */
+        internal class Secp224k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp224k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp224k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D");
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.ValueOf(5);
+                byte[] S = null;
+                BigInteger n = FromHex("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7");
+                BigInteger h = BigInteger.One;
+
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+                    new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+                    new BigInteger[]{
+                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+                        new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+                    new BigInteger[]{
+                        new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+                    new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+                    new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+                    240);
+
+                ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+                    + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp224r1
+         */
+        internal class Secp224r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp224r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp224r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^224 - 2^96 + 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001");
+                BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE");
+                BigInteger b = FromHex("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4");
+                byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+                BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+                    + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp256k1
+         */
+        internal class Secp256k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp256k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp256k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.ValueOf(7);
+                byte[] S = null;
+                BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
+                BigInteger h = BigInteger.One;
+
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+                    new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+                    new BigInteger[]{
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+                        new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+                    new BigInteger[]{
+                        new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+                    new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+                    new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+                    272);
+
+                ECCurve curve = ConfigureCurveGlv(new FpCurve(p, a, b, n, h), glv);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+                    + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp256r1
+         */
+        internal class Secp256r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp256r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp256r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^224 (2^32 - 1) + 2^192 + 2^96 - 1
+                BigInteger p = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF");
+                BigInteger a = FromHex("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC");
+                BigInteger b = FromHex("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B");
+                byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90");
+                BigInteger n = FromHex("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+                    + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp384r1
+         */
+        internal class Secp384r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp384r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp384r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^384 - 2^128 - 2^96 + 2^32 - 1
+                BigInteger p = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF");
+                BigInteger a = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC");
+                BigInteger b = FromHex("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF");
+                byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+                BigInteger n = FromHex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * secp521r1
+         */
+        internal class Secp521r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp521r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp521r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                // p = 2^521 - 1
+                BigInteger p = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
+                BigInteger a = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC");
+                BigInteger b = FromHex("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00");
+                byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+                BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409");
+                BigInteger h = BigInteger.One;
+
+                ECCurve curve = ConfigureCurve(new FpCurve(p, a, b, n, h));
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect113r1
+         */
+        internal class Sect113r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect113r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect113r1Holder();
+
+            private const int m = 113;
+            private const int k = 9;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("003088250CA6E7C7FE649CE85820F7");
+                BigInteger b = FromHex("00E8BEE4D3E2260744188BE0E9C723");
+                byte[] S = Hex.Decode("10E723AB14D696E6768756151756FEBF8FCB49A9");
+                BigInteger n = FromHex("0100000000000000D9CCEC8A39E56F");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "009D73616F35F4AB1407D73562C10F"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "009D73616F35F4AB1407D73562C10F"
+                    + "00A52830277958EE84D1315ED31886"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect113r2
+         */
+        internal class Sect113r2Holder
+            : X9ECParametersHolder
+        {
+            private Sect113r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect113r2Holder();
+
+            private const int m = 113;
+            private const int k = 9;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("00689918DBEC7E5A0DD6DFC0AA55C7");
+                BigInteger b = FromHex("0095E9A9EC9B297BD4BF36E059184F");
+                byte[] S = Hex.Decode("10C0FB15760860DEF1EEF4D696E676875615175D");
+                BigInteger n = FromHex("010000000000000108789B2496AF93");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "01A57A6A7B26CA5EF52FCDB8164797"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "01A57A6A7B26CA5EF52FCDB8164797"
+                    + "00B3ADC94ED1FE674C06E695BABA1D"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect131r1
+         */
+        internal class Sect131r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect131r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect131r1Holder();
+
+            private const int m = 131;
+            private const int k1 = 2;
+            private const int k2 = 3;
+            private const int k3 = 8;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("07A11B09A76B562144418FF3FF8C2570B8");
+                BigInteger b = FromHex("0217C05610884B63B9C6C7291678F9D341");
+                byte[] S = Hex.Decode("4D696E676875615175985BD3ADBADA21B43A97E2");
+                BigInteger n = FromHex("0400000000000000023123953A9464B54D");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "0081BAF91FDF9833C40F9C181343638399"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0081BAF91FDF9833C40F9C181343638399"
+                    + "078C6E7EA38C001F73C8134B1B4EF9E150"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect131r2
+         */
+        internal class Sect131r2Holder
+            : X9ECParametersHolder
+        {
+            private Sect131r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect131r2Holder();
+
+            private const int m = 131;
+            private const int k1 = 2;
+            private const int k2 = 3;
+            private const int k3 = 8;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("03E5A88919D7CAFCBF415F07C2176573B2");
+                BigInteger b = FromHex("04B8266A46C55657AC734CE38F018F2192");
+                byte[] S = Hex.Decode("985BD3ADBAD4D696E676875615175A21B43A97E3");
+                BigInteger n = FromHex("0400000000000000016954A233049BA98F");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "0356DCD8F2F95031AD652D23951BB366A8"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0356DCD8F2F95031AD652D23951BB366A8"
+                    + "0648F06D867940A5366D9E265DE9EB240F"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect163k1
+         */
+        internal class Sect163k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect163k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect163k1Holder();
+
+            private const int m = 163;
+            private const int k1 = 3;
+            private const int k2 = 6;
+            private const int k3 = 7;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("04000000000000000000020108A2E0CC0D99F8A5EF");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8"
+                    + "0289070FB05D38FF58321F2E800536D538CCDAA3D9"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect163r1
+         */
+        internal class Sect163r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect163r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect163r1Holder();
+
+            private const int m = 163;
+            private const int k1 = 3;
+            private const int k2 = 6;
+            private const int k3 = 7;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("07B6882CAAEFA84F9554FF8428BD88E246D2782AE2");
+                BigInteger b = FromHex("0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9");
+                byte[] S = Hex.Decode("24B7B137C8A14D696E6768756151756FD0DA2E5C");
+                BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "0369979697AB43897789566789567F787A7876A654"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0369979697AB43897789566789567F787A7876A654"
+                    + "00435EDB42EFAFB2989D51FEFCE3C80988F41FF883"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect163r2
+         */
+        internal class Sect163r2Holder
+            : X9ECParametersHolder
+        {
+            private Sect163r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect163r2Holder();
+
+            private const int m = 163;
+            private const int k1 = 3;
+            private const int k2 = 6;
+            private const int k3 = 7;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = FromHex("020A601907B8C953CA1481EB10512F78744A3205FD");
+                byte[] S = Hex.Decode("85E25BFE5C86226CDB12016F7553F9D0E693A268");
+                BigInteger n = FromHex("040000000000000000000292FE77E70C12A4234C33");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "03F0EBA16286A2D57EA0991168D4994637E8343E36"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "03F0EBA16286A2D57EA0991168D4994637E8343E36"
+                    + "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect193r1
+         */
+        internal class Sect193r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect193r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect193r1Holder();
+
+            private const int m = 193;
+            private const int k = 15;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01");
+                BigInteger b = FromHex("00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814");
+                byte[] S = Hex.Decode("103FAEC74D696E676875615175777FC5B191EF30");
+                BigInteger n = FromHex("01000000000000000000000000C7F34A778F443ACC920EBA49");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1"
+                    + "0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect193r2
+         */
+        internal class Sect193r2Holder
+            : X9ECParametersHolder
+        {
+            private Sect193r2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect193r2Holder();
+
+            private const int m = 193;
+            private const int k = 15;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = FromHex("0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B");
+                BigInteger b = FromHex("00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE");
+                byte[] S = Hex.Decode("10B7B4D696E676875615175137C8A16FD0DA2211");
+                BigInteger n = FromHex("010000000000000000000000015AAB561B005413CCD4EE99D5");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F"
+                    + "01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect233k1
+         */
+        internal class Sect233k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect233k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect233k1Holder();
+
+            private const int m = 233;
+            private const int k = 74;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126"
+                    + "01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect233r1
+         */
+        internal class Sect233r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect233r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect233r1Holder();
+
+            private const int m = 233;
+            private const int k = 74;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = FromHex("0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD");
+                byte[] S = Hex.Decode("74D59FF07F6B413D0EA14B344B20A2DB049B50C3");
+                BigInteger n = FromHex("01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B"
+                    + "01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect239k1
+         */
+        internal class Sect239k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect239k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect239k1Holder();
+
+            private const int m = 239;
+            private const int k = 158;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC"
+                    + "76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect283k1
+         */
+        internal class Sect283k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect283k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect283k1Holder();
+
+            private const int m = 283;
+            private const int k1 = 5;
+            private const int k2 = 7;
+            private const int k3 = 12;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836"
+                    + "01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect283r1
+         */
+        internal class Sect283r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect283r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect283r1Holder();
+
+            private const int m = 283;
+            private const int k1 = 5;
+            private const int k2 = 7;
+            private const int k3 = 12;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = FromHex("027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5");
+                byte[] S = Hex.Decode("77E2B07370EB0F832A6DD5B62DFC88CD06BB84BE");
+                BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053"
+                    + "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect409k1
+         */
+        internal class Sect409k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect409k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect409k1Holder();
+
+            private const int m = 409;
+            private const int k = 87;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746"
+                    + "01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect409r1
+         */
+        internal class Sect409r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect409r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect409r1Holder();
+
+            private const int m = 409;
+            private const int k = 87;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = FromHex("0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F");
+                byte[] S = Hex.Decode("4099B5A457F9D69F79213D094C4BCD4D4262210B");
+                BigInteger n = FromHex("010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7"
+                    + "0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect571k1
+         */
+        internal class Sect571k1Holder
+            : X9ECParametersHolder
+        {
+            private Sect571k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect571k1Holder();
+
+            private const int m = 571;
+            private const int k1 = 2;
+            private const int k2 = 5;
+            private const int k3 = 10;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.Zero;
+                BigInteger b = BigInteger.One;
+                byte[] S = null;
+                BigInteger n = FromHex("020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001");
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("02"
+                //+ "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972"
+                    + "0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+        /*
+         * sect571r1
+         */
+        internal class Sect571r1Holder
+            : X9ECParametersHolder
+        {
+            private Sect571r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Sect571r1Holder();
+
+            private const int m = 571;
+            private const int k1 = 2;
+            private const int k2 = 5;
+            private const int k3 = 10;
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger a = BigInteger.One;
+                BigInteger b = FromHex("02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A");
+                byte[] S = Hex.Decode("2AA058F73A0E33AB486B0F610410C53A7F132310");
+                BigInteger n = FromHex("03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47");
+                BigInteger h = BigInteger.ValueOf(2);
+
+                ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b, n, h);
+                //ECPoint G = curve.DecodePoint(Hex.Decode("03"
+                //+ "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"));
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19"
+                    + "037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B"));
+
+                return new X9ECParameters(curve, G, n, h, S);
+            }
+        }
+
+
+        private static readonly IDictionary objIds = Platform.CreateHashtable();
+        private static readonly IDictionary curves = Platform.CreateHashtable();
+        private static readonly IDictionary names = Platform.CreateHashtable();
+
+        private static void DefineCurve(
+            string					name,
+            DerObjectIdentifier		oid,
+            X9ECParametersHolder	holder)
+        {
+            objIds.Add(name, oid);
+            names.Add(oid, name);
+            curves.Add(oid, holder);
+        }
+
+        static SecNamedCurves()
+        {
+            DefineCurve("secp112r1", SecObjectIdentifiers.SecP112r1, Secp112r1Holder.Instance);
+            DefineCurve("secp112r2", SecObjectIdentifiers.SecP112r2, Secp112r2Holder.Instance);
+            DefineCurve("secp128r1", SecObjectIdentifiers.SecP128r1, Secp128r1Holder.Instance);
+            DefineCurve("secp128r2", SecObjectIdentifiers.SecP128r2, Secp128r2Holder.Instance);
+            DefineCurve("secp160k1", SecObjectIdentifiers.SecP160k1, Secp160k1Holder.Instance);
+            DefineCurve("secp160r1", SecObjectIdentifiers.SecP160r1, Secp160r1Holder.Instance);
+            DefineCurve("secp160r2", SecObjectIdentifiers.SecP160r2, Secp160r2Holder.Instance);
+            DefineCurve("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance);
+            DefineCurve("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance);
+            DefineCurve("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance);
+            DefineCurve("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance);
+            DefineCurve("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance);
+            DefineCurve("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance);
+            DefineCurve("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance);
+            DefineCurve("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance);
+
+            DefineCurve("sect113r1", SecObjectIdentifiers.SecT113r1, Sect113r1Holder.Instance);
+            DefineCurve("sect113r2", SecObjectIdentifiers.SecT113r2, Sect113r2Holder.Instance);
+            DefineCurve("sect131r1", SecObjectIdentifiers.SecT131r1, Sect131r1Holder.Instance);
+            DefineCurve("sect131r2", SecObjectIdentifiers.SecT131r2, Sect131r2Holder.Instance);
+            DefineCurve("sect163k1", SecObjectIdentifiers.SecT163k1, Sect163k1Holder.Instance);
+            DefineCurve("sect163r1", SecObjectIdentifiers.SecT163r1, Sect163r1Holder.Instance);
+            DefineCurve("sect163r2", SecObjectIdentifiers.SecT163r2, Sect163r2Holder.Instance);
+            DefineCurve("sect193r1", SecObjectIdentifiers.SecT193r1, Sect193r1Holder.Instance);
+            DefineCurve("sect193r2", SecObjectIdentifiers.SecT193r2, Sect193r2Holder.Instance);
+            DefineCurve("sect233k1", SecObjectIdentifiers.SecT233k1, Sect233k1Holder.Instance);
+            DefineCurve("sect233r1", SecObjectIdentifiers.SecT233r1, Sect233r1Holder.Instance);
+            DefineCurve("sect239k1", SecObjectIdentifiers.SecT239k1, Sect239k1Holder.Instance);
+            DefineCurve("sect283k1", SecObjectIdentifiers.SecT283k1, Sect283k1Holder.Instance);
+            DefineCurve("sect283r1", SecObjectIdentifiers.SecT283r1, Sect283r1Holder.Instance);
+            DefineCurve("sect409k1", SecObjectIdentifiers.SecT409k1, Sect409k1Holder.Instance);
+            DefineCurve("sect409r1", SecObjectIdentifiers.SecT409r1, Sect409r1Holder.Instance);
+            DefineCurve("sect571k1", SecObjectIdentifiers.SecT571k1, Sect571k1Holder.Instance);
+            DefineCurve("sect571r1", SecObjectIdentifiers.SecT571r1, Sect571r1Holder.Instance);
+        }
+
+        public static X9ECParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier)
+                objIds[Platform.ToLowerInvariant(name)];
+
+            return oid == null ? null : GetByOid(oid);
+        }
+
+        /**
+         * return the X9ECParameters object for the named curve represented by
+         * the passed in object identifier. Null if the curve isn't present.
+         *
+         * @param oid an object identifier representing a named curve, if present.
+         */
+        public static X9ECParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+            return holder == null ? null : holder.Parameters;
+        }
+
+        /**
+         * return the object identifier signified by the passed in name. Null
+         * if there is no object identifier associated with name.
+         *
+         * @return the object identifier associated with name, if present.
+         */
+        public static DerObjectIdentifier GetOid(
+            string name)
+        {
+            return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)];
+        }
+
+        /**
+         * return the named curve name represented by the given object identifier.
+         */
+        public static string GetName(
+            DerObjectIdentifier oid)
+        {
+            return (string) names[oid];
+        }
+
+        /**
+         * returns an enumeration containing the name strings for curves
+         * contained in this structure.
+         */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(objIds.Keys); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/sec/SECObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/sec/SECObjectIdentifiers.cs
new file mode 100644
index 0000000..afc10e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/sec/SECObjectIdentifiers.cs
@@ -0,0 +1,52 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+
+namespace Org.BouncyCastle.Asn1.Sec
+{
+	public abstract class SecObjectIdentifiers
+	{
+		/**
+		 *  EllipticCurve OBJECT IDENTIFIER ::= {
+		 *        iso(1) identified-organization(3) certicom(132) curve(0)
+		 *  }
+		 */
+		public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier("1.3.132.0");
+
+		public static readonly DerObjectIdentifier SecT163k1 = new DerObjectIdentifier(EllipticCurve + ".1");
+		public static readonly DerObjectIdentifier SecT163r1 = new DerObjectIdentifier(EllipticCurve + ".2");
+		public static readonly DerObjectIdentifier SecT239k1 = new DerObjectIdentifier(EllipticCurve + ".3");
+		public static readonly DerObjectIdentifier SecT113r1 = new DerObjectIdentifier(EllipticCurve + ".4");
+		public static readonly DerObjectIdentifier SecT113r2 = new DerObjectIdentifier(EllipticCurve + ".5");
+		public static readonly DerObjectIdentifier SecP112r1 = new DerObjectIdentifier(EllipticCurve + ".6");
+		public static readonly DerObjectIdentifier SecP112r2 = new DerObjectIdentifier(EllipticCurve + ".7");
+		public static readonly DerObjectIdentifier SecP160r1 = new DerObjectIdentifier(EllipticCurve + ".8");
+		public static readonly DerObjectIdentifier SecP160k1 = new DerObjectIdentifier(EllipticCurve + ".9");
+		public static readonly DerObjectIdentifier SecP256k1 = new DerObjectIdentifier(EllipticCurve + ".10");
+		public static readonly DerObjectIdentifier SecT163r2 = new DerObjectIdentifier(EllipticCurve + ".15");
+		public static readonly DerObjectIdentifier SecT283k1 = new DerObjectIdentifier(EllipticCurve + ".16");
+		public static readonly DerObjectIdentifier SecT283r1 = new DerObjectIdentifier(EllipticCurve + ".17");
+		public static readonly DerObjectIdentifier SecT131r1 = new DerObjectIdentifier(EllipticCurve + ".22");
+		public static readonly DerObjectIdentifier SecT131r2 = new DerObjectIdentifier(EllipticCurve + ".23");
+		public static readonly DerObjectIdentifier SecT193r1 = new DerObjectIdentifier(EllipticCurve + ".24");
+		public static readonly DerObjectIdentifier SecT193r2 = new DerObjectIdentifier(EllipticCurve + ".25");
+		public static readonly DerObjectIdentifier SecT233k1 = new DerObjectIdentifier(EllipticCurve + ".26");
+		public static readonly DerObjectIdentifier SecT233r1 = new DerObjectIdentifier(EllipticCurve + ".27");
+		public static readonly DerObjectIdentifier SecP128r1 = new DerObjectIdentifier(EllipticCurve + ".28");
+		public static readonly DerObjectIdentifier SecP128r2 = new DerObjectIdentifier(EllipticCurve + ".29");
+		public static readonly DerObjectIdentifier SecP160r2 = new DerObjectIdentifier(EllipticCurve + ".30");
+		public static readonly DerObjectIdentifier SecP192k1 = new DerObjectIdentifier(EllipticCurve + ".31");
+		public static readonly DerObjectIdentifier SecP224k1 = new DerObjectIdentifier(EllipticCurve + ".32");
+		public static readonly DerObjectIdentifier SecP224r1 = new DerObjectIdentifier(EllipticCurve + ".33");
+		public static readonly DerObjectIdentifier SecP384r1 = new DerObjectIdentifier(EllipticCurve + ".34");
+		public static readonly DerObjectIdentifier SecP521r1 = new DerObjectIdentifier(EllipticCurve + ".35");
+		public static readonly DerObjectIdentifier SecT409k1 = new DerObjectIdentifier(EllipticCurve + ".36");
+		public static readonly DerObjectIdentifier SecT409r1 = new DerObjectIdentifier(EllipticCurve + ".37");
+		public static readonly DerObjectIdentifier SecT571k1 = new DerObjectIdentifier(EllipticCurve + ".38");
+		public static readonly DerObjectIdentifier SecT571r1 = new DerObjectIdentifier(EllipticCurve + ".39");
+
+		public static readonly DerObjectIdentifier SecP192r1 = X9ObjectIdentifiers.Prime192v1;
+		public static readonly DerObjectIdentifier SecP256r1 = X9ObjectIdentifiers.Prime256v1;
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEAttributes.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEAttributes.cs
new file mode 100644
index 0000000..e154e5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEAttributes.cs
@@ -0,0 +1,11 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    public abstract class SmimeAttributes
+    {
+        public static readonly DerObjectIdentifier SmimeCapabilities = PkcsObjectIdentifiers.Pkcs9AtSmimeCapabilities;
+        public static readonly DerObjectIdentifier EncrypKeyPref = PkcsObjectIdentifiers.IdAAEncrypKeyPref;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilities.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilities.cs
new file mode 100644
index 0000000..ca3c3af
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilities.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    /**
+     * Handler class for dealing with S/MIME Capabilities
+     */
+    public class SmimeCapabilities
+        : Asn1Encodable
+    {
+        /**
+         * general preferences
+         */
+        public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData;
+        public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny;
+        public static readonly DerObjectIdentifier SmimeCapabilitesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions;
+
+		/**
+         * encryption algorithms preferences
+         */
+        public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+        public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc;
+        public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc;
+
+		private Asn1Sequence capabilities;
+
+		/**
+         * return an Attr object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static SmimeCapabilities GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is SmimeCapabilities)
+            {
+                return (SmimeCapabilities) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SmimeCapabilities((Asn1Sequence) obj);
+            }
+
+			if (obj is AttributeX509)
+            {
+                return new SmimeCapabilities(
+                    (Asn1Sequence)(((AttributeX509) obj).AttrValues[0]));
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		public SmimeCapabilities(
+            Asn1Sequence seq)
+        {
+            capabilities = seq;
+        }
+
+#if !SILVERLIGHT
+        [Obsolete("Use 'GetCapabilitiesForOid' instead")]
+        public ArrayList GetCapabilities(
+            DerObjectIdentifier capability)
+        {
+            ArrayList list = new ArrayList();
+            DoGetCapabilitiesForOid(capability, list);
+			return list;
+        }
+#endif
+
+        /**
+         * returns an ArrayList with 0 or more objects of all the capabilities
+         * matching the passed in capability Oid. If the Oid passed is null the
+         * entire set is returned.
+         */
+        public IList GetCapabilitiesForOid(
+            DerObjectIdentifier capability)
+        {
+            IList list = Platform.CreateArrayList();
+            DoGetCapabilitiesForOid(capability, list);
+			return list;
+        }
+
+        private void DoGetCapabilitiesForOid(DerObjectIdentifier capability, IList list)
+        {
+			if (capability == null)
+            {
+				foreach (object o in capabilities)
+				{
+                    SmimeCapability cap = SmimeCapability.GetInstance(o);
+
+					list.Add(cap);
+                }
+            }
+            else
+            {
+				foreach (object o in capabilities)
+				{
+                    SmimeCapability cap = SmimeCapability.GetInstance(o);
+
+					if (capability.Equals(cap.CapabilityID))
+                    {
+                        list.Add(cap);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SMIMECapabilities ::= Sequence OF SMIMECapability
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return capabilities;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilitiesAttribute.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilitiesAttribute.cs
new file mode 100644
index 0000000..310c478
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilitiesAttribute.cs
@@ -0,0 +1,16 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    public class SmimeCapabilitiesAttribute
+        : AttributeX509
+    {
+        public SmimeCapabilitiesAttribute(
+            SmimeCapabilityVector capabilities)
+            : base(SmimeAttributes.SmimeCapabilities,
+                    new DerSet(new DerSequence(capabilities.ToAsn1EncodableVector())))
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapability.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapability.cs
new file mode 100644
index 0000000..5709cb8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapability.cs
@@ -0,0 +1,101 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    public class SmimeCapability
+        : Asn1Encodable
+    {
+        /**
+         * general preferences
+         */
+        public static readonly DerObjectIdentifier PreferSignedData = PkcsObjectIdentifiers.PreferSignedData;
+        public static readonly DerObjectIdentifier CannotDecryptAny = PkcsObjectIdentifiers.CannotDecryptAny;
+        public static readonly DerObjectIdentifier SmimeCapabilitiesVersions = PkcsObjectIdentifiers.SmimeCapabilitiesVersions;
+
+		/**
+         * encryption algorithms preferences
+         */
+        public static readonly DerObjectIdentifier DesCbc = new DerObjectIdentifier("1.3.14.3.2.7");
+        public static readonly DerObjectIdentifier DesEde3Cbc = PkcsObjectIdentifiers.DesEde3Cbc;
+        public static readonly DerObjectIdentifier RC2Cbc = PkcsObjectIdentifiers.RC2Cbc;
+
+		private DerObjectIdentifier capabilityID;
+        private Asn1Object			parameters;
+
+		public SmimeCapability(
+            Asn1Sequence seq)
+        {
+            capabilityID = (DerObjectIdentifier) seq[0].ToAsn1Object();
+
+			if (seq.Count > 1)
+            {
+                parameters = seq[1].ToAsn1Object();
+            }
+        }
+
+		public SmimeCapability(
+            DerObjectIdentifier	capabilityID,
+            Asn1Encodable		parameters)
+        {
+			if (capabilityID == null)
+				throw new ArgumentNullException("capabilityID");
+
+			this.capabilityID = capabilityID;
+
+			if (parameters != null)
+			{
+				this.parameters = parameters.ToAsn1Object();
+			}
+        }
+
+		public static SmimeCapability GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is SmimeCapability)
+            {
+                return (SmimeCapability) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SmimeCapability((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid SmimeCapability");
+        }
+
+		public DerObjectIdentifier CapabilityID
+		{
+			get { return capabilityID; }
+		}
+
+		public Asn1Object Parameters
+		{
+			get { return parameters; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SMIMECapability ::= Sequence {
+         *     capabilityID OBJECT IDENTIFIER,
+         *     parameters ANY DEFINED BY capabilityID OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(capabilityID);
+
+			if (parameters != null)
+            {
+                v.Add(parameters);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilityVector.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilityVector.cs
new file mode 100644
index 0000000..842825b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMECapabilityVector.cs
@@ -0,0 +1,37 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    /**
+     * Handler for creating a vector S/MIME Capabilities
+     */
+    public class SmimeCapabilityVector
+    {
+        private readonly Asn1EncodableVector capabilities = new Asn1EncodableVector();
+
+		public void AddCapability(
+            DerObjectIdentifier capability)
+        {
+            capabilities.Add(new DerSequence(capability));
+        }
+
+		public void AddCapability(
+            DerObjectIdentifier capability,
+            int                 value)
+        {
+			capabilities.Add(new DerSequence(capability, new DerInteger(value)));
+        }
+
+		public void AddCapability(
+            DerObjectIdentifier capability,
+            Asn1Encodable		parameters)
+        {
+			capabilities.Add(new DerSequence(capability, parameters));
+        }
+
+		public Asn1EncodableVector ToAsn1EncodableVector()
+        {
+            return capabilities;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs
new file mode 100644
index 0000000..19c5fd7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/smime/SMIMEEncryptionKeyPreferenceAttribute.cs
@@ -0,0 +1,44 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Smime
+{
+    /**
+     * The SmimeEncryptionKeyPreference object.
+     * <pre>
+     * SmimeEncryptionKeyPreference ::= CHOICE {
+     *     issuerAndSerialNumber   [0] IssuerAndSerialNumber,
+     *     receipentKeyId          [1] RecipientKeyIdentifier,
+     *     subjectAltKeyIdentifier [2] SubjectKeyIdentifier
+     * }
+     * </pre>
+     */
+    public class SmimeEncryptionKeyPreferenceAttribute
+        : AttributeX509
+    {
+        public SmimeEncryptionKeyPreferenceAttribute(
+            IssuerAndSerialNumber issAndSer)
+            : base(SmimeAttributes.EncrypKeyPref,
+                new DerSet(new DerTaggedObject(false, 0, issAndSer)))
+        {
+        }
+
+        public SmimeEncryptionKeyPreferenceAttribute(
+            RecipientKeyIdentifier rKeyID)
+            : base(SmimeAttributes.EncrypKeyPref,
+                new DerSet(new DerTaggedObject(false, 1, rKeyID)))
+        {
+        }
+
+        /**
+         * @param sKeyId the subjectKeyIdentifier value (normally the X.509 one)
+         */
+        public SmimeEncryptionKeyPreferenceAttribute(
+            Asn1OctetString sKeyID)
+            : base(SmimeAttributes.EncrypKeyPref,
+                new DerSet(new DerTaggedObject(false, 2, sKeyID)))
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTNamedCurves.cs b/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTNamedCurves.cs
new file mode 100644
index 0000000..05060c1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTNamedCurves.cs
@@ -0,0 +1,474 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.TeleTrust
+{
+    /**
+    * elliptic curves defined in "ECC Brainpool Standard Curves and Curve Generation"
+    * http://www.ecc-brainpool.org/download/draft_pkix_additional_ecc_dp.txt
+    */
+    public class TeleTrusTNamedCurves
+    {
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
+        internal class BrainpoolP160r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP160r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP160r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+                    new BigInteger("340E7BE2A280EB74E2BE61BADA745D97E8F7C300", 16), // a
+                    new BigInteger("1E589A8595423412134FAA2DBDEC95C8D8675E58", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC31667CB477A1A8EC338F94741669C976316DA6321")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP160t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP160t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP160t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("E95E4A5F737059DC60DF5991D45029409E60FC09", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //   new BigInteger("24DBFF5DEC9B986BBFE5295A29BFBAE45E0F5D0B", 16), // Z
+                    new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620F", 16), // q
+                    new BigInteger("E95E4A5F737059DC60DFC7AD95B3D8139515620C", 16), // a'
+                    new BigInteger("7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04B199B13B9B34EFC1397E64BAEB05ACC265FF2378ADD6718B7C7C1961F0991B842443772152C9E0AD")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP192r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP192r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP192r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+                    new BigInteger("6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", 16), // a
+                    new BigInteger("469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD614B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP192t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP192t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP192t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("1B6F5CC8DB4DC7AF19458A9CB80DC2295E5EB9C3732104CB") //Z
+                    new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", 16), // q
+                    new BigInteger("C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294", 16), // a'
+                    new BigInteger("13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("043AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9")), // G'
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP224r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP224r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP224r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+                    new BigInteger("68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", 16), // a
+                    new BigInteger("2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP224t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP224t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP224t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("2DF271E14427A346910CF7A2E6CFA7B3F484E5C2CCE1C8B730E28B3F") //Z
+                    new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", 16), // q
+                    new BigInteger("D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC", 16), // a'
+                    new BigInteger("4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("046AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D5800374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C")), // G'
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP256r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP256r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP256r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+                    new BigInteger("7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", 16), // a
+                    new BigInteger("26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("048BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP256t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP256t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP256t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("3E2D4BD9597B58639AE7AA669CAB9837CF5CF20A2C852D10F655668DFC150EF0") //Z
+                    new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", 16), // q
+                    new BigInteger("A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374", 16), // a'
+                    new BigInteger("662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F42D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE")), // G'
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP320r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP320r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP320r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+                    new BigInteger("3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", 16), // a
+                    new BigInteger("520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("0443BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E2061114FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP320t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP320t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP320t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("15F75CAF668077F7E85B42EB01F0A81FF56ECD6191D55CB82B7D861458A18FEFC3E5AB7496F3C7B1") //Z
+                    new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", 16), // q
+                    new BigInteger("D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24", 16), // a'
+                    new BigInteger("A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED5263BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3")), // G'
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP384r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP384r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP384r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+                    new BigInteger("7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", 16), // a
+                    new BigInteger("4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("041D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP384t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP384t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP384t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("41DFE8DD399331F7166A66076734A89CD0D2BCDB7D068E44E1F378F41ECBAE97D2D63DBC87BCCDDCCC5DA39E8589291C") //Z
+                    new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", 16), // q
+                    new BigInteger("8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50", 16), // a'
+                    new BigInteger("7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("0418DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928")), // G'
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP512r1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP512r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP512r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+                    new BigInteger("7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", 16), // a
+                    new BigInteger("3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", 16), // b
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("0481AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F8227DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892")), // G
+                    n, h);
+            }
+        }
+
+        internal class BrainpoolP512t1Holder
+            : X9ECParametersHolder
+        {
+            private BrainpoolP512t1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new BrainpoolP512t1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", 16);
+                BigInteger h = new BigInteger("01", 16);
+
+                ECCurve curve = ConfigureCurve(new FpCurve(
+                    //new BigInteger("12EE58E6764838B69782136F0F2D3BA06E27695716054092E60A80BEDB212B64E585D90BCE13761F85C3F1D2A64E3BE8FEA2220F01EBA5EEB0F35DBD29D922AB") //Z
+                    new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", 16), // q
+                    new BigInteger("AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0", 16), // a'
+                    new BigInteger("7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E", 16), // b'
+                    n, h));
+
+                return new X9ECParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("04640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332")), // G'
+                    n, h);
+            }
+        }
+
+
+        private static readonly IDictionary objIds = Platform.CreateHashtable();
+        private static readonly IDictionary curves = Platform.CreateHashtable();
+        private static readonly IDictionary names = Platform.CreateHashtable();
+
+        private static void DefineCurve(
+            string					name,
+            DerObjectIdentifier		oid,
+            X9ECParametersHolder	holder)
+        {
+            objIds.Add(name, oid);
+            names.Add(oid, name);
+            curves.Add(oid, holder);
+        }
+
+        static TeleTrusTNamedCurves()
+        {
+            DefineCurve("brainpoolp160r1", TeleTrusTObjectIdentifiers.BrainpoolP160R1, BrainpoolP160r1Holder.Instance);
+            DefineCurve("brainpoolp160t1", TeleTrusTObjectIdentifiers.BrainpoolP160T1, BrainpoolP160t1Holder.Instance);
+            DefineCurve("brainpoolp192r1", TeleTrusTObjectIdentifiers.BrainpoolP192R1, BrainpoolP192r1Holder.Instance);
+            DefineCurve("brainpoolp192t1", TeleTrusTObjectIdentifiers.BrainpoolP192T1, BrainpoolP192t1Holder.Instance);
+            DefineCurve("brainpoolp224r1", TeleTrusTObjectIdentifiers.BrainpoolP224R1, BrainpoolP224r1Holder.Instance);
+            DefineCurve("brainpoolp224t1", TeleTrusTObjectIdentifiers.BrainpoolP224T1, BrainpoolP224t1Holder.Instance);
+            DefineCurve("brainpoolp256r1", TeleTrusTObjectIdentifiers.BrainpoolP256R1, BrainpoolP256r1Holder.Instance);
+            DefineCurve("brainpoolp256t1", TeleTrusTObjectIdentifiers.BrainpoolP256T1, BrainpoolP256t1Holder.Instance);
+            DefineCurve("brainpoolp320r1", TeleTrusTObjectIdentifiers.BrainpoolP320R1, BrainpoolP320r1Holder.Instance);
+            DefineCurve("brainpoolp320t1", TeleTrusTObjectIdentifiers.BrainpoolP320T1, BrainpoolP320t1Holder.Instance);
+            DefineCurve("brainpoolp384r1", TeleTrusTObjectIdentifiers.BrainpoolP384R1, BrainpoolP384r1Holder.Instance);
+            DefineCurve("brainpoolp384t1", TeleTrusTObjectIdentifiers.BrainpoolP384T1, BrainpoolP384t1Holder.Instance);
+            DefineCurve("brainpoolp512r1", TeleTrusTObjectIdentifiers.BrainpoolP512R1, BrainpoolP512r1Holder.Instance);
+            DefineCurve("brainpoolp512t1", TeleTrusTObjectIdentifiers.BrainpoolP512T1, BrainpoolP512t1Holder.Instance);
+        }
+
+        public static X9ECParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier)
+                objIds[Platform.ToLowerInvariant(name)];
+
+            return oid == null ? null : GetByOid(oid);
+        }
+
+        /**
+        * return the X9ECParameters object for the named curve represented by
+        * the passed in object identifier. Null if the curve isn't present.
+        *
+        * @param oid an object identifier representing a named curve, if present.
+        */
+        public static X9ECParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+            return holder == null ? null : holder.Parameters;
+        }
+
+        /**
+        * return the object identifier signified by the passed in name. Null
+        * if there is no object identifier associated with name.
+        *
+        * @return the object identifier associated with name, if present.
+        */
+        public static DerObjectIdentifier GetOid(
+            string name)
+        {
+            return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)];
+        }
+
+        /**
+        * return the named curve name represented by the given object identifier.
+        */
+        public static string GetName(
+            DerObjectIdentifier oid)
+        {
+            return (string) names[oid];
+        }
+
+
+        /**
+         * returns an enumeration containing the name strings for curves
+         * contained in this structure.
+         */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(objIds.Keys); }
+        }
+
+        public static DerObjectIdentifier GetOid(
+            short	curvesize,
+            bool	twisted)
+        {
+            return GetOid("brainpoolP" + curvesize + (twisted ? "t" : "r") + "1");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs
new file mode 100644
index 0000000..56e7084
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/teletrust/TeleTrusTObjectIdentifiers.cs
@@ -0,0 +1,45 @@
+namespace Org.BouncyCastle.Asn1.TeleTrust
+{
+	public sealed class TeleTrusTObjectIdentifiers
+	{
+		private TeleTrusTObjectIdentifiers()
+		{
+		}
+
+		public static readonly DerObjectIdentifier TeleTrusTAlgorithm = new DerObjectIdentifier("1.3.36.3");
+
+		public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.1");
+		public static readonly DerObjectIdentifier RipeMD128 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.2");
+		public static readonly DerObjectIdentifier RipeMD256 = new DerObjectIdentifier(TeleTrusTAlgorithm + ".2.3");
+
+		public static readonly DerObjectIdentifier TeleTrusTRsaSignatureAlgorithm = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.1");
+
+		public static readonly DerObjectIdentifier RsaSignatureWithRipeMD160 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".2");
+		public static readonly DerObjectIdentifier RsaSignatureWithRipeMD128 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".3");
+		public static readonly DerObjectIdentifier RsaSignatureWithRipeMD256 = new DerObjectIdentifier(TeleTrusTRsaSignatureAlgorithm + ".4");
+
+		public static readonly DerObjectIdentifier ECSign = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2");
+
+		public static readonly DerObjectIdentifier ECSignWithSha1 = new DerObjectIdentifier(ECSign + ".1");
+		public static readonly DerObjectIdentifier ECSignWithRipeMD160 = new DerObjectIdentifier(ECSign + ".2");
+
+		public static readonly DerObjectIdentifier EccBrainpool = new DerObjectIdentifier(TeleTrusTAlgorithm + ".3.2.8");
+		public static readonly DerObjectIdentifier EllipticCurve = new DerObjectIdentifier(EccBrainpool + ".1");
+		public static readonly DerObjectIdentifier VersionOne = new DerObjectIdentifier(EllipticCurve + ".1");    
+
+		public static readonly DerObjectIdentifier BrainpoolP160R1 = new DerObjectIdentifier(VersionOne + ".1");
+		public static readonly DerObjectIdentifier BrainpoolP160T1 = new DerObjectIdentifier(VersionOne + ".2");
+		public static readonly DerObjectIdentifier BrainpoolP192R1 = new DerObjectIdentifier(VersionOne + ".3");
+		public static readonly DerObjectIdentifier BrainpoolP192T1 = new DerObjectIdentifier(VersionOne + ".4");
+		public static readonly DerObjectIdentifier BrainpoolP224R1 = new DerObjectIdentifier(VersionOne + ".5");
+		public static readonly DerObjectIdentifier BrainpoolP224T1 = new DerObjectIdentifier(VersionOne + ".6");
+		public static readonly DerObjectIdentifier BrainpoolP256R1 = new DerObjectIdentifier(VersionOne + ".7");
+		public static readonly DerObjectIdentifier BrainpoolP256T1 = new DerObjectIdentifier(VersionOne + ".8");
+		public static readonly DerObjectIdentifier BrainpoolP320R1 = new DerObjectIdentifier(VersionOne + ".9");
+		public static readonly DerObjectIdentifier BrainpoolP320T1 = new DerObjectIdentifier(VersionOne + ".10");
+		public static readonly DerObjectIdentifier BrainpoolP384R1 = new DerObjectIdentifier(VersionOne + ".11");
+		public static readonly DerObjectIdentifier BrainpoolP384T1 = new DerObjectIdentifier(VersionOne + ".12");
+		public static readonly DerObjectIdentifier BrainpoolP512R1 = new DerObjectIdentifier(VersionOne + ".13");
+		public static readonly DerObjectIdentifier BrainpoolP512T1 = new DerObjectIdentifier(VersionOne + ".14");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/tsp/Accuracy.cs b/BouncyCastle.AxCrypt/src/asn1/tsp/Accuracy.cs
new file mode 100644
index 0000000..a193f52
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/tsp/Accuracy.cs
@@ -0,0 +1,149 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+	public class Accuracy
+		: Asn1Encodable
+	{
+		private readonly DerInteger seconds;
+		private readonly DerInteger millis;
+		private readonly DerInteger micros;
+
+		// constants
+		protected const int MinMillis = 1;
+		protected const int MaxMillis = 999;
+		protected const int MinMicros = 1;
+		protected const int MaxMicros = 999;
+
+		public Accuracy(
+			DerInteger seconds,
+			DerInteger millis,
+			DerInteger micros)
+		{
+			//Verifications
+			if (millis != null
+				&& (millis.Value.IntValue < MinMillis
+					|| millis.Value.IntValue > MaxMillis))
+			{
+				throw new ArgumentException(
+					"Invalid millis field : not in (1..999)");
+			}
+
+			if (micros != null
+				&& (micros.Value.IntValue < MinMicros
+					|| micros.Value.IntValue > MaxMicros))
+			{
+				throw new ArgumentException(
+					"Invalid micros field : not in (1..999)");
+			}
+
+			this.seconds = seconds;
+			this.millis = millis;
+			this.micros = micros;
+		}
+
+		private Accuracy(
+			Asn1Sequence seq)
+		{
+			for (int i = 0; i < seq.Count; ++i)
+			{
+				// seconds
+				if (seq[i] is DerInteger)
+				{
+					seconds = (DerInteger) seq[i];
+				}
+				else if (seq[i] is DerTaggedObject)
+				{
+					DerTaggedObject extra = (DerTaggedObject) seq[i];
+
+					switch (extra.TagNo)
+					{
+						case 0:
+							millis = DerInteger.GetInstance(extra, false);
+							if (millis.Value.IntValue < MinMillis
+								|| millis.Value.IntValue > MaxMillis)
+							{
+								throw new ArgumentException(
+									"Invalid millis field : not in (1..999).");
+							}
+							break;
+						case 1:
+							micros = DerInteger.GetInstance(extra, false);
+							if (micros.Value.IntValue < MinMicros
+								|| micros.Value.IntValue > MaxMicros)
+							{
+								throw new ArgumentException(
+									"Invalid micros field : not in (1..999).");
+							}
+							break;
+						default:
+							throw new ArgumentException("Invalig tag number");
+					}
+				}
+			}
+		}
+
+		public static Accuracy GetInstance(
+			object o)
+		{
+			if (o == null || o is Accuracy)
+			{
+				return (Accuracy) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new Accuracy((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"Unknown object in 'Accuracy' factory: " + o.GetType().FullName);
+		}
+
+		public DerInteger Seconds
+		{
+			get { return seconds; }
+		}
+
+		public DerInteger Millis
+		{
+			get { return millis; }
+		}
+
+		public DerInteger Micros
+		{
+			get { return micros; }
+		}
+
+		/**
+		 * <pre>
+		 * Accuracy ::= SEQUENCE {
+		 *             seconds        INTEGER              OPTIONAL,
+		 *             millis     [0] INTEGER  (1..999)    OPTIONAL,
+		 *             micros     [1] INTEGER  (1..999)    OPTIONAL
+		 *             }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (seconds != null)
+			{
+				v.Add(seconds);
+			}
+
+			if (millis != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, millis));
+			}
+
+			if (micros != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, micros));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/tsp/MessageImprint.cs b/BouncyCastle.AxCrypt/src/asn1/tsp/MessageImprint.cs
new file mode 100644
index 0000000..0933bae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/tsp/MessageImprint.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+	public class MessageImprint
+		: Asn1Encodable
+	{
+		private readonly AlgorithmIdentifier	hashAlgorithm;
+		private readonly byte[]					hashedMessage;
+
+		/**
+		 * @param o
+		 * @return a MessageImprint object.
+		 */
+		public static MessageImprint GetInstance(
+			object o)
+		{
+			if (o == null || o is MessageImprint)
+			{
+				return (MessageImprint) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new MessageImprint((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"Unknown object in 'MessageImprint' factory: " + o.GetType().FullName);
+		}
+
+		private MessageImprint(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+			this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]);
+			this.hashedMessage = Asn1OctetString.GetInstance(seq[1]).GetOctets();
+		}
+
+		public MessageImprint(
+			AlgorithmIdentifier	hashAlgorithm,
+			byte[]				hashedMessage)
+		{
+			this.hashAlgorithm = hashAlgorithm;
+			this.hashedMessage = hashedMessage;
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public byte[] GetHashedMessage()
+		{
+			return hashedMessage;
+		}
+
+		/**
+		 * <pre>
+		 *    MessageImprint ::= SEQUENCE  {
+		 *       hashAlgorithm                AlgorithmIdentifier,
+		 *       hashedMessage                OCTET STRING  }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(hashAlgorithm, new DerOctetString(hashedMessage));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/tsp/TSTInfo.cs b/BouncyCastle.AxCrypt/src/asn1/tsp/TSTInfo.cs
new file mode 100644
index 0000000..61d5399
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/tsp/TSTInfo.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+	public class TstInfo
+		: Asn1Encodable
+	{
+		private readonly DerInteger				version;
+		private readonly DerObjectIdentifier	tsaPolicyId;
+		private readonly MessageImprint			messageImprint;
+		private readonly DerInteger				serialNumber;
+		private readonly DerGeneralizedTime		genTime;
+		private readonly Accuracy				accuracy;
+		private readonly DerBoolean				ordering;
+		private readonly DerInteger				nonce;
+		private readonly GeneralName			tsa;
+		private readonly X509Extensions			extensions;
+
+		public static TstInfo GetInstance(
+			object o)
+		{
+			if (o == null || o is TstInfo)
+			{
+				return (TstInfo) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new TstInfo((Asn1Sequence) o);
+			}
+
+			if (o is Asn1OctetString)
+			{
+				try
+				{
+					byte[] octets = ((Asn1OctetString)o).GetOctets();
+					return GetInstance(Asn1Object.FromByteArray(octets));
+				}
+				catch (IOException)
+				{
+					throw new ArgumentException(
+						"Bad object format in 'TstInfo' factory.");
+				}
+			}
+
+			throw new ArgumentException(
+				"Unknown object in 'TstInfo' factory: " + o.GetType().FullName);
+		}
+
+		private TstInfo(
+			Asn1Sequence seq)
+		{
+			IEnumerator e = seq.GetEnumerator();
+
+			// version
+			e.MoveNext();
+			version = DerInteger.GetInstance(e.Current);
+
+			// tsaPolicy
+			e.MoveNext();
+			tsaPolicyId = DerObjectIdentifier.GetInstance(e.Current);
+
+			// messageImprint
+			e.MoveNext();
+			messageImprint = MessageImprint.GetInstance(e.Current);
+
+			// serialNumber
+			e.MoveNext();
+			serialNumber = DerInteger.GetInstance(e.Current);
+
+			// genTime
+			e.MoveNext();
+			genTime = DerGeneralizedTime.GetInstance(e.Current);
+
+			// default for ordering
+			ordering = DerBoolean.False;
+
+			while (e.MoveNext())
+			{
+				Asn1Object o = (Asn1Object) e.Current;
+
+				if (o is Asn1TaggedObject)
+				{
+					DerTaggedObject tagged = (DerTaggedObject) o;
+
+					switch (tagged.TagNo)
+					{
+						case 0:
+							tsa = GeneralName.GetInstance(tagged, true);
+							break;
+						case 1:
+							extensions = X509Extensions.GetInstance(tagged, false);
+							break;
+						default:
+							throw new ArgumentException("Unknown tag value " + tagged.TagNo);
+					}
+				}
+
+				if (o is DerSequence)
+				{
+					accuracy = Accuracy.GetInstance(o);
+				}
+
+				if (o is DerBoolean)
+				{
+					ordering = DerBoolean.GetInstance(o);
+				}
+
+				if (o is DerInteger)
+				{
+					nonce = DerInteger.GetInstance(o);
+				}
+			}
+		}
+
+		public TstInfo(
+			DerObjectIdentifier	tsaPolicyId,
+			MessageImprint		messageImprint,
+			DerInteger			serialNumber,
+			DerGeneralizedTime	genTime,
+			Accuracy			accuracy,
+			DerBoolean			ordering,
+			DerInteger			nonce,
+			GeneralName			tsa,
+			X509Extensions		extensions)
+		{
+			this.version = new DerInteger(1);
+			this.tsaPolicyId = tsaPolicyId;
+			this.messageImprint = messageImprint;
+			this.serialNumber = serialNumber;
+			this.genTime = genTime;
+			this.accuracy = accuracy;
+			this.ordering = ordering;
+			this.nonce = nonce;
+			this.tsa = tsa;
+			this.extensions = extensions;
+		}
+
+        public DerInteger Version
+        {
+            get { return version; }
+        }
+
+		public MessageImprint MessageImprint
+		{
+			get { return messageImprint; }
+		}
+
+		public DerObjectIdentifier Policy
+		{
+			get { return tsaPolicyId; }
+		}
+
+		public DerInteger SerialNumber
+		{
+			get { return serialNumber; }
+		}
+
+		public Accuracy Accuracy
+		{
+			get { return accuracy; }
+		}
+
+		public DerGeneralizedTime GenTime
+		{
+			get { return genTime; }
+		}
+
+		public DerBoolean Ordering
+		{
+			get { return ordering; }
+		}
+
+		public DerInteger Nonce
+		{
+			get { return nonce; }
+		}
+
+		public GeneralName Tsa
+		{
+			get { return tsa; }
+		}
+
+		public X509Extensions Extensions
+		{
+			get { return extensions; }
+		}
+
+		/**
+		 * <pre>
+		 *
+		 *     TstInfo ::= SEQUENCE  {
+		 *        version                      INTEGER  { v1(1) },
+		 *        policy                       TSAPolicyId,
+		 *        messageImprint               MessageImprint,
+		 *          -- MUST have the same value as the similar field in
+		 *          -- TimeStampReq
+		 *        serialNumber                 INTEGER,
+		 *         -- Time-Stamping users MUST be ready to accommodate integers
+		 *         -- up to 160 bits.
+		 *        genTime                      GeneralizedTime,
+		 *        accuracy                     Accuracy                 OPTIONAL,
+		 *        ordering                     BOOLEAN             DEFAULT FALSE,
+		 *        nonce                        INTEGER                  OPTIONAL,
+		 *          -- MUST be present if the similar field was present
+		 *          -- in TimeStampReq.  In that case it MUST have the same value.
+		 *        tsa                          [0] GeneralName          OPTIONAL,
+		 *        extensions                   [1] IMPLICIT Extensions   OPTIONAL  }
+		 *
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				version, tsaPolicyId, messageImprint, serialNumber, genTime);
+
+			if (accuracy != null)
+			{
+				v.Add(accuracy);
+			}
+
+			if (ordering != null && ordering.IsTrue)
+			{
+				v.Add(ordering);
+			}
+
+			if (nonce != null)
+			{
+				v.Add(nonce);
+			}
+
+			if (tsa != null)
+			{
+				v.Add(new DerTaggedObject(true, 0, tsa));
+			}
+
+			if (extensions != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, extensions));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampReq.cs b/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampReq.cs
new file mode 100644
index 0000000..55e973e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampReq.cs
@@ -0,0 +1,164 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+	public class TimeStampReq
+		: Asn1Encodable
+	{
+		private readonly DerInteger				version;
+		private readonly MessageImprint			messageImprint;
+		private readonly DerObjectIdentifier	tsaPolicy;
+		private readonly DerInteger				nonce;
+		private readonly DerBoolean				certReq;
+		private readonly X509Extensions			extensions;
+
+		public static TimeStampReq GetInstance(
+			object o)
+		{
+			if (o == null || o is TimeStampReq)
+			{
+				return (TimeStampReq) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new TimeStampReq((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"Unknown object in 'TimeStampReq' factory: " + o.GetType().FullName);
+		}
+
+		private TimeStampReq(
+			Asn1Sequence seq)
+		{
+			int nbObjects = seq.Count;
+			int seqStart = 0;
+
+			// version
+			version = DerInteger.GetInstance(seq[seqStart++]);
+
+			// messageImprint
+			messageImprint = MessageImprint.GetInstance(seq[seqStart++]);
+
+			for (int opt = seqStart; opt < nbObjects; opt++)
+			{
+				// tsaPolicy
+				if (seq[opt] is DerObjectIdentifier)
+				{
+					tsaPolicy = DerObjectIdentifier.GetInstance(seq[opt]);
+				}
+				// nonce
+				else if (seq[opt] is DerInteger)
+				{
+					nonce = DerInteger.GetInstance(seq[opt]);
+				}
+				// certReq
+				else if (seq[opt] is DerBoolean)
+				{
+					certReq = DerBoolean.GetInstance(seq[opt]);
+				}
+				// extensions
+				else if (seq[opt] is Asn1TaggedObject)
+				{
+					Asn1TaggedObject tagged = (Asn1TaggedObject) seq[opt];
+					if (tagged.TagNo == 0)
+					{
+						extensions = X509Extensions.GetInstance(tagged, false);
+					}
+				}
+			}
+		}
+
+		public TimeStampReq(
+			MessageImprint		messageImprint,
+			DerObjectIdentifier	tsaPolicy,
+			DerInteger			nonce,
+			DerBoolean			certReq,
+			X509Extensions		extensions)
+		{
+			// default
+			this.version = new DerInteger(1);
+
+			this.messageImprint = messageImprint;
+			this.tsaPolicy = tsaPolicy;
+			this.nonce = nonce;
+			this.certReq = certReq;
+			this.extensions = extensions;
+		}
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public MessageImprint MessageImprint
+		{
+			get { return messageImprint; }
+		}
+
+		public DerObjectIdentifier ReqPolicy
+		{
+			get { return tsaPolicy; }
+		}
+
+		public DerInteger Nonce
+		{
+			get { return nonce; }
+		}
+
+		public DerBoolean CertReq
+		{
+			get { return certReq; }
+		}
+
+		public X509Extensions Extensions
+		{
+			get { return extensions; }
+		}
+
+		/**
+		 * <pre>
+		 * TimeStampReq ::= SEQUENCE  {
+		 *  version                      INTEGER  { v1(1) },
+		 *  messageImprint               MessageImprint,
+		 *    --a hash algorithm OID and the hash value of the data to be
+		 *    --time-stamped
+		 *  reqPolicy             TSAPolicyId              OPTIONAL,
+		 *  nonce                 INTEGER                  OPTIONAL,
+		 *  certReq               BOOLEAN                  DEFAULT FALSE,
+		 *  extensions            [0] IMPLICIT Extensions  OPTIONAL
+		 * }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				version, messageImprint);
+
+			if (tsaPolicy != null)
+			{
+				v.Add(tsaPolicy);
+			}
+
+			if (nonce != null)
+			{
+				v.Add(nonce);
+			}
+
+			if (certReq != null && certReq.IsTrue)
+			{
+				v.Add(certReq);
+			}
+
+			if (extensions != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, extensions));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampResp.cs b/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampResp.cs
new file mode 100644
index 0000000..f26fb30
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/tsp/TimeStampResp.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+	public class TimeStampResp
+		: Asn1Encodable
+	{
+		private readonly PkiStatusInfo	pkiStatusInfo;
+		private readonly ContentInfo	timeStampToken;
+
+		public static TimeStampResp GetInstance(
+			object o)
+		{
+			if (o == null || o is TimeStampResp)
+			{
+				return (TimeStampResp) o;
+			}
+
+			if (o is Asn1Sequence)
+			{
+				return new TimeStampResp((Asn1Sequence) o);
+			}
+
+			throw new ArgumentException(
+				"Unknown object in 'TimeStampResp' factory: " + o.GetType().FullName);
+		}
+
+		private TimeStampResp(
+			Asn1Sequence seq)
+		{
+			this.pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				this.timeStampToken = ContentInfo.GetInstance(seq[1]);
+			}
+		}
+
+		public TimeStampResp(
+			PkiStatusInfo	pkiStatusInfo,
+			ContentInfo		timeStampToken)
+		{
+			this.pkiStatusInfo = pkiStatusInfo;
+			this.timeStampToken = timeStampToken;
+		}
+
+		public PkiStatusInfo Status
+		{
+			get { return pkiStatusInfo; }
+		}
+
+		public ContentInfo TimeStampToken
+		{
+			get { return timeStampToken; }
+		}
+
+		/**
+		 * <pre>
+		 * TimeStampResp ::= SEQUENCE  {
+		 *   status                  PkiStatusInfo,
+		 *   timeStampToken          TimeStampToken     OPTIONAL  }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
+
+			if (timeStampToken != null)
+			{
+				v.Add(timeStampToken);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/util/Asn1Dump.cs b/BouncyCastle.AxCrypt/src/asn1/util/Asn1Dump.cs
new file mode 100644
index 0000000..36b17c8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/util/Asn1Dump.cs
@@ -0,0 +1,373 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+    public sealed class Asn1Dump
+    {
+        private static readonly string NewLine = Platform.NewLine;
+
+        private Asn1Dump()
+        {
+        }
+
+        private const string Tab = "    ";
+        private const int SampleSize = 32;
+
+        /**
+         * dump a Der object as a formatted string with indentation
+         *
+         * @param obj the Asn1Object to be dumped out.
+         */
+        private static void AsString(
+            string			indent,
+            bool			verbose,
+            Asn1Object		obj,
+            StringBuilder	buf)
+        {
+            if (obj is Asn1Sequence)
+            {
+                string tab = indent + Tab;
+                buf.Append(indent);
+                if (obj is BerSequence)
+                {
+                    buf.Append("BER Sequence");
+                }
+                else if (obj is DerSequence)
+                {
+                    buf.Append("DER Sequence");
+                }
+                else
+                {
+                    buf.Append("Sequence");
+                }
+
+                buf.Append(NewLine);
+
+                foreach (Asn1Encodable o in ((Asn1Sequence)obj))
+                {
+                    if (o == null || o is Asn1Null)
+                    {
+                        buf.Append(tab);
+                        buf.Append("NULL");
+                        buf.Append(NewLine);
+                    }
+                    else
+                    {
+                        AsString(tab, verbose, o.ToAsn1Object(), buf);
+                    }
+                }
+            }
+            else if (obj is DerTaggedObject)
+            {
+                string tab = indent + Tab;
+                buf.Append(indent);
+                if (obj is BerTaggedObject)
+                {
+                    buf.Append("BER Tagged [");
+                }
+                else
+                {
+                    buf.Append("Tagged [");
+                }
+
+                DerTaggedObject o = (DerTaggedObject)obj;
+
+                buf.Append(((int)o.TagNo).ToString());
+                buf.Append(']');
+
+                if (!o.IsExplicit())
+                {
+                    buf.Append(" IMPLICIT ");
+                }
+
+                buf.Append(NewLine);
+
+                if (o.IsEmpty())
+                {
+                    buf.Append(tab);
+                    buf.Append("EMPTY");
+                    buf.Append(NewLine);
+                }
+                else
+                {
+                    AsString(tab, verbose, o.GetObject(), buf);
+                }
+            }
+            else if (obj is BerSet)
+            {
+                string tab = indent + Tab;
+
+                buf.Append(indent);
+                buf.Append("BER Set");
+                buf.Append(NewLine);
+
+                foreach (Asn1Encodable o in ((Asn1Set)obj))
+                {
+                    if (o == null)
+                    {
+                        buf.Append(tab);
+                        buf.Append("NULL");
+                        buf.Append(NewLine);
+                    }
+                    else
+                    {
+                        AsString(tab, verbose, o.ToAsn1Object(), buf);
+                    }
+                }
+            }
+            else if (obj is DerSet)
+            {
+                string tab = indent + Tab;
+
+                buf.Append(indent);
+                buf.Append("DER Set");
+                buf.Append(NewLine);
+
+                foreach (Asn1Encodable o in ((Asn1Set)obj))
+                {
+                    if (o == null)
+                    {
+                        buf.Append(tab);
+                        buf.Append("NULL");
+                        buf.Append(NewLine);
+                    }
+                    else
+                    {
+                        AsString(tab, verbose, o.ToAsn1Object(), buf);
+                    }
+                }
+            }
+            else if (obj is DerObjectIdentifier)
+            {
+                buf.Append(indent + "ObjectIdentifier(" + ((DerObjectIdentifier)obj).Id + ")" + NewLine);
+            }
+            else if (obj is DerBoolean)
+            {
+                buf.Append(indent + "Boolean(" + ((DerBoolean)obj).IsTrue + ")" + NewLine);
+            }
+            else if (obj is DerInteger)
+            {
+                buf.Append(indent + "Integer(" + ((DerInteger)obj).Value + ")" + NewLine);
+            }
+            else if (obj is BerOctetString)
+            {
+                byte[] octets = ((Asn1OctetString)obj).GetOctets();
+                string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+                buf.Append(indent + "BER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+            }
+            else if (obj is DerOctetString)
+            {
+                byte[] octets = ((Asn1OctetString)obj).GetOctets();
+                string extra = verbose ? dumpBinaryDataAsString(indent, octets) : "";
+                buf.Append(indent + "DER Octet String" + "[" + octets.Length + "] " + extra + NewLine);
+            }
+            else if (obj is DerBitString)
+            {
+                DerBitString bt = (DerBitString)obj; 
+                byte[] bytes = bt.GetBytes();
+                string extra = verbose ? dumpBinaryDataAsString(indent, bytes) : "";
+                buf.Append(indent + "DER Bit String" + "[" + bytes.Length + ", " + bt.PadBits + "] " + extra + NewLine);
+            }
+            else if (obj is DerIA5String)
+            {
+                buf.Append(indent + "IA5String(" + ((DerIA5String)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerUtf8String)
+            {
+                buf.Append(indent + "UTF8String(" + ((DerUtf8String)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerPrintableString)
+            {
+                buf.Append(indent + "PrintableString(" + ((DerPrintableString)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerVisibleString)
+            {
+                buf.Append(indent + "VisibleString(" + ((DerVisibleString)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerBmpString)
+            {
+                buf.Append(indent + "BMPString(" + ((DerBmpString)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerT61String)
+            {
+                buf.Append(indent + "T61String(" + ((DerT61String)obj).GetString() + ") " + NewLine);
+            }
+            else if (obj is DerUtcTime)
+            {
+                buf.Append(indent + "UTCTime(" + ((DerUtcTime)obj).TimeString + ") " + NewLine);
+            }
+            else if (obj is DerGeneralizedTime)
+            {
+                buf.Append(indent + "GeneralizedTime(" + ((DerGeneralizedTime)obj).GetTime() + ") " + NewLine);
+            }
+            else if (obj is BerApplicationSpecific)
+            {
+                buf.Append(outputApplicationSpecific("BER", indent, verbose, (BerApplicationSpecific)obj));
+            }
+            else if (obj is DerApplicationSpecific)
+            {
+                buf.Append(outputApplicationSpecific("DER", indent, verbose, (DerApplicationSpecific)obj));
+            }
+            else if (obj is DerEnumerated)
+            {
+                DerEnumerated en = (DerEnumerated)obj;
+                buf.Append(indent + "DER Enumerated(" + en.Value + ")" + NewLine);
+            }
+            else if (obj is DerExternal)
+            {
+                DerExternal ext = (DerExternal)obj;
+                buf.Append(indent + "External " + NewLine);
+                string tab = indent + Tab;
+
+                if (ext.DirectReference != null)
+                {
+                    buf.Append(tab + "Direct Reference: " + ext.DirectReference.Id + NewLine);
+                }
+                if (ext.IndirectReference != null)
+                {
+                    buf.Append(tab + "Indirect Reference: " + ext.IndirectReference.ToString() + NewLine);
+                }
+                if (ext.DataValueDescriptor != null)
+                {
+                    AsString(tab, verbose, ext.DataValueDescriptor, buf);
+                }
+                buf.Append(tab + "Encoding: " + ext.Encoding + NewLine);
+                AsString(tab, verbose, ext.ExternalContent, buf);
+            }
+            else
+            {
+                buf.Append(indent + obj.ToString() + NewLine);
+            }
+        }
+
+        private static string outputApplicationSpecific(
+            string					type,
+            string					indent,
+            bool					verbose,
+            DerApplicationSpecific	app)
+        {
+            StringBuilder buf = new StringBuilder();
+
+            if (app.IsConstructed())
+            {
+                try
+                {
+                    Asn1Sequence s = Asn1Sequence.GetInstance(app.GetObject(Asn1Tags.Sequence));
+                    buf.Append(indent + type + " ApplicationSpecific[" + app.ApplicationTag + "]" + NewLine);
+                    foreach (Asn1Encodable ae in s)
+                    {
+                        AsString(indent + Tab, verbose, ae.ToAsn1Object(), buf);
+                    }
+                }
+                catch (IOException e)
+                {
+                    buf.Append(e);
+                }
+                return buf.ToString();
+            }
+
+            return indent + type + " ApplicationSpecific[" + app.ApplicationTag + "] ("
+                + Hex.ToHexString(app.GetContents()) + ")" + NewLine;
+        }
+
+        [Obsolete("Use version accepting Asn1Encodable")]
+        public static string DumpAsString(
+            object   obj)
+        {
+            if (obj is Asn1Encodable)
+            {
+                StringBuilder buf = new StringBuilder();
+                AsString("", false, ((Asn1Encodable)obj).ToAsn1Object(), buf);
+                return buf.ToString();
+            }
+
+            return "unknown object type " + obj.ToString();
+        }
+
+        /**
+         * dump out a DER object as a formatted string, in non-verbose mode
+         *
+         * @param obj the Asn1Encodable to be dumped out.
+         * @return  the resulting string.
+         */
+        public static string DumpAsString(
+            Asn1Encodable obj)
+        {
+            return DumpAsString(obj, false);
+        }
+
+        /**
+         * Dump out the object as a string
+         *
+         * @param obj the Asn1Encodable to be dumped out.
+         * @param verbose  if true, dump out the contents of octet and bit strings.
+         * @return  the resulting string.
+         */
+        public static string DumpAsString(
+            Asn1Encodable	obj,
+            bool			verbose)
+        {
+            StringBuilder buf = new StringBuilder();
+            AsString("", verbose, obj.ToAsn1Object(), buf);
+            return buf.ToString();
+        }
+
+        private static string dumpBinaryDataAsString(string indent, byte[] bytes)
+        {
+            indent += Tab;
+
+            StringBuilder buf = new StringBuilder(NewLine);
+
+            for (int i = 0; i < bytes.Length; i += SampleSize)
+            {
+                if (bytes.Length - i > SampleSize)
+                {
+                    buf.Append(indent);
+                    buf.Append(Hex.ToHexString(bytes, i, SampleSize));
+                    buf.Append(Tab);
+                    buf.Append(calculateAscString(bytes, i, SampleSize));
+                    buf.Append(NewLine);
+                }
+                else
+                {
+                    buf.Append(indent);
+                    buf.Append(Hex.ToHexString(bytes, i, bytes.Length - i));
+                    for (int j = bytes.Length - i; j != SampleSize; j++)
+                    {
+                        buf.Append("  ");
+                    }
+                    buf.Append(Tab);
+                    buf.Append(calculateAscString(bytes, i, bytes.Length - i));
+                    buf.Append(NewLine);
+                }
+            }
+
+            return buf.ToString();
+        }
+
+        private static string calculateAscString(
+            byte[]	bytes,
+            int		off,
+            int		len)
+        {
+            StringBuilder buf = new StringBuilder();
+
+            for (int i = off; i != off + len; i++)
+            {
+                char c = (char)bytes[i]; 
+                if (c >= ' ' && c <= '~')
+                {
+                    buf.Append(c);
+                }
+            }
+
+            return buf.ToString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/util/Dump.cs b/BouncyCastle.AxCrypt/src/asn1/util/Dump.cs
new file mode 100644
index 0000000..164ed98
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/util/Dump.cs
@@ -0,0 +1,30 @@
+#if !PCL
+using Org.BouncyCastle.Asn1;
+
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+    public sealed class Dump
+    {
+        private Dump()
+        {
+        }
+
+        public static void Main(string[] args)
+        {
+            FileStream fIn = File.OpenRead(args[0]);
+            Asn1InputStream bIn = new Asn1InputStream(fIn);
+
+			Asn1Object obj;
+			while ((obj = bIn.ReadObject()) != null)
+            {
+                Console.WriteLine(Asn1Dump.DumpAsString(obj));
+            }
+
+			bIn.Close();
+        }
+    }
+}
+#endif
diff --git a/BouncyCastle.AxCrypt/src/asn1/util/FilterStream.cs b/BouncyCastle.AxCrypt/src/asn1/util/FilterStream.cs
new file mode 100644
index 0000000..2b22856
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/util/FilterStream.cs
@@ -0,0 +1,73 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.Utilities
+{
+    public class FilterStream : Stream
+    {
+        public FilterStream(Stream s)
+        {
+            this.s = s;
+        }
+        public override bool CanRead
+        {
+            get { return s.CanRead; }
+        }
+        public override bool CanSeek
+        {
+            get { return s.CanSeek; }
+        }
+        public override bool CanWrite
+        {
+            get { return s.CanWrite; }
+        }
+        public override long Length
+        {
+            get { return s.Length; }
+        }
+        public override long Position
+        {
+            get { return s.Position; }
+            set { s.Position = value; }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                s.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        public override void Flush()
+        {
+            s.Flush();
+        }
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            return s.Seek(offset, origin);
+        }
+        public override void SetLength(long value)
+        {
+            s.SetLength(value);
+        }
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            return s.Read(buffer, offset, count);
+        }
+        public override int ReadByte()
+        {
+            return s.ReadByte();
+        }
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            s.Write(buffer, offset, count);
+        }
+        public override void WriteByte(byte value)
+        {
+            s.WriteByte(value);
+        }
+        protected readonly Stream s;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x500/DirectoryString.cs b/BouncyCastle.AxCrypt/src/asn1/x500/DirectoryString.cs
new file mode 100644
index 0000000..78ecc26
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x500/DirectoryString.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X500
+{
+	public class DirectoryString
+		: Asn1Encodable, IAsn1Choice, IAsn1String
+	{
+		private readonly DerStringBase str;
+
+		public static DirectoryString GetInstance(
+			object obj)
+		{
+			if (obj is DirectoryString)
+			{
+				return (DirectoryString) obj;
+			}
+
+			if (obj is DerStringBase)
+			{
+				if (obj is DerT61String
+					|| obj is DerPrintableString
+					|| obj is DerUniversalString
+					|| obj is DerUtf8String
+					|| obj is DerBmpString)
+				{
+					return new DirectoryString((DerStringBase) obj);
+				}
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static DirectoryString GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			if (!isExplicit)
+				throw new ArgumentException("choice item must be explicitly tagged");
+
+			return GetInstance(obj.GetObject());
+		}
+
+		private DirectoryString(
+			DerStringBase str)
+		{
+			this.str = str;
+		}
+
+		public DirectoryString(
+			string str)
+		{
+			this.str = new DerUtf8String(str);
+		}
+
+		public string GetString()
+		{
+			return str.GetString();
+		}
+
+		/**
+		 * <pre>
+		 *  DirectoryString ::= CHOICE {
+		 *    teletexString               TeletexString (SIZE (1..MAX)),
+		 *    printableString             PrintableString (SIZE (1..MAX)),
+		 *    universalString             UniversalString (SIZE (1..MAX)),
+		 *    utf8String                  UTF8String (SIZE (1..MAX)),
+		 *    bmpString                   BMPString (SIZE (1..MAX))  }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return str.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AccessDescription.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AccessDescription.cs
new file mode 100644
index 0000000..09b5b59
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AccessDescription.cs
@@ -0,0 +1,83 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * The AccessDescription object.
+	 * <pre>
+	 * AccessDescription  ::=  SEQUENCE {
+	 *       accessMethod          OBJECT IDENTIFIER,
+	 *       accessLocation        GeneralName  }
+	 * </pre>
+	 */
+	public class AccessDescription
+		: Asn1Encodable
+	{
+		public readonly static DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier("1.3.6.1.5.5.7.48.2");
+		public readonly static DerObjectIdentifier IdADOcsp = new DerObjectIdentifier("1.3.6.1.5.5.7.48.1");
+
+		private readonly DerObjectIdentifier accessMethod;
+		private readonly GeneralName accessLocation;
+
+		public static AccessDescription GetInstance(
+			object obj)
+		{
+			if (obj is AccessDescription)
+				return (AccessDescription) obj;
+
+			if (obj is Asn1Sequence)
+				return new AccessDescription((Asn1Sequence) obj);
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private AccessDescription(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("wrong number of elements in sequence");
+
+			accessMethod = DerObjectIdentifier.GetInstance(seq[0]);
+			accessLocation = GeneralName.GetInstance(seq[1]);
+		}
+
+		/**
+		 * create an AccessDescription with the oid and location provided.
+		 */
+		public AccessDescription(
+			DerObjectIdentifier	oid,
+			GeneralName			location)
+		{
+			accessMethod = oid;
+			accessLocation = location;
+		}
+
+		/**
+		 *
+		 * @return the access method.
+		 */
+		public DerObjectIdentifier AccessMethod
+		{
+			get { return accessMethod; }
+		}
+
+		/**
+		 *
+		 * @return the access location
+		 */
+		public GeneralName AccessLocation
+		{
+			get { return accessLocation; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(accessMethod, accessLocation);
+		}
+
+		public override string ToString()
+		{
+			return "AccessDescription: Oid(" + this.accessMethod.Id + ")";
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AlgorithmIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AlgorithmIdentifier.cs
new file mode 100644
index 0000000..4ed3a40
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AlgorithmIdentifier.cs
@@ -0,0 +1,109 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AlgorithmIdentifier
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	objectID;
+        private readonly Asn1Encodable			parameters;
+        private readonly bool					parametersDefined;
+
+        public static AlgorithmIdentifier GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static AlgorithmIdentifier GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is AlgorithmIdentifier)
+                return (AlgorithmIdentifier) obj;
+
+            // TODO: delete
+            if (obj is DerObjectIdentifier)
+                return new AlgorithmIdentifier((DerObjectIdentifier) obj);
+
+            // TODO: delete
+            if (obj is string)
+                return new AlgorithmIdentifier((string) obj);
+
+            return new AlgorithmIdentifier(Asn1Sequence.GetInstance(obj));
+        }
+
+        public AlgorithmIdentifier(
+            DerObjectIdentifier objectID)
+        {
+            this.objectID = objectID;
+        }
+
+        public AlgorithmIdentifier(
+            string objectID)
+        {
+            this.objectID = new DerObjectIdentifier(objectID);
+        }
+
+        public AlgorithmIdentifier(
+            DerObjectIdentifier	objectID,
+            Asn1Encodable		parameters)
+        {
+            this.objectID = objectID;
+            this.parameters = parameters;
+            this.parametersDefined = true;
+        }
+
+        internal AlgorithmIdentifier(
+            Asn1Sequence seq)
+        {
+            if (seq.Count < 1 || seq.Count > 2)
+                throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+            this.objectID = DerObjectIdentifier.GetInstance(seq[0]);
+            this.parametersDefined = (seq.Count == 2);
+
+            if (parametersDefined)
+            {
+                this.parameters = seq[1];
+            }
+        }
+
+        public virtual DerObjectIdentifier ObjectID
+        {
+            get { return objectID; }
+        }
+
+        public Asn1Encodable Parameters
+        {
+            get { return parameters; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *      AlgorithmIdentifier ::= Sequence {
+         *                            algorithm OBJECT IDENTIFIER,
+         *                            parameters ANY DEFINED BY algorithm OPTIONAL }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(objectID);
+
+            if (parametersDefined)
+            {
+                if (parameters != null)
+                {
+                    v.Add(parameters);
+                }
+                else
+                {
+                    v.Add(DerNull.Instance);
+                }
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AttCertIssuer.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AttCertIssuer.cs
new file mode 100644
index 0000000..e9314fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AttCertIssuer.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttCertIssuer
+        : Asn1Encodable, IAsn1Choice
+    {
+        internal readonly Asn1Encodable	obj;
+        internal readonly Asn1Object	choiceObj;
+
+		public static AttCertIssuer GetInstance(
+			object obj)
+		{
+			if (obj is AttCertIssuer)
+			{
+				return (AttCertIssuer)obj;
+			}
+			else if (obj is V2Form)
+			{
+				return new AttCertIssuer(V2Form.GetInstance(obj));
+			}
+			else if (obj is GeneralNames)
+			{
+				return new AttCertIssuer((GeneralNames)obj);
+			}
+			else if (obj is Asn1TaggedObject)
+			{
+				return new AttCertIssuer(V2Form.GetInstance((Asn1TaggedObject)obj, false));
+			}
+			else if (obj is Asn1Sequence)
+			{
+				return new AttCertIssuer(GeneralNames.GetInstance(obj));
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static AttCertIssuer GetInstance(
+			Asn1TaggedObject	obj,
+			bool				isExplicit)
+		{
+			return GetInstance(obj.GetObject()); // must be explictly tagged
+		}
+
+		/// <summary>
+		/// Don't use this one if you are trying to be RFC 3281 compliant.
+		/// Use it for v1 attribute certificates only.
+		/// </summary>
+		/// <param name="names">Our GeneralNames structure</param>
+		public AttCertIssuer(
+			GeneralNames names)
+		{
+			obj = names;
+			choiceObj = obj.ToAsn1Object();
+		}
+
+		public AttCertIssuer(
+            V2Form v2Form)
+        {
+            obj = v2Form;
+            choiceObj = new DerTaggedObject(false, 0, obj);
+        }
+
+		public Asn1Encodable Issuer
+		{
+			get { return obj; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  AttCertIssuer ::= CHOICE {
+         *       v1Form   GeneralNames,  -- MUST NOT be used in this
+         *                               -- profile
+         *       v2Form   [0] V2Form     -- v2 only
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return choiceObj;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AttCertValidityPeriod.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AttCertValidityPeriod.cs
new file mode 100644
index 0000000..7f86cd0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AttCertValidityPeriod.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttCertValidityPeriod
+        : Asn1Encodable
+    {
+        private readonly DerGeneralizedTime	notBeforeTime;
+        private readonly DerGeneralizedTime	notAfterTime;
+
+		public static AttCertValidityPeriod GetInstance(
+            object obj)
+        {
+            if (obj is AttCertValidityPeriod || obj == null)
+            {
+                return (AttCertValidityPeriod) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new AttCertValidityPeriod((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static AttCertValidityPeriod GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		private AttCertValidityPeriod(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			notBeforeTime = DerGeneralizedTime.GetInstance(seq[0]);
+			notAfterTime = DerGeneralizedTime.GetInstance(seq[1]);
+        }
+
+		public AttCertValidityPeriod(
+            DerGeneralizedTime	notBeforeTime,
+            DerGeneralizedTime	notAfterTime)
+        {
+            this.notBeforeTime = notBeforeTime;
+            this.notAfterTime = notAfterTime;
+        }
+
+		public DerGeneralizedTime NotBeforeTime
+		{
+			get { return notBeforeTime; }
+		}
+
+		public DerGeneralizedTime NotAfterTime
+		{
+			get { return notAfterTime; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  AttCertValidityPeriod  ::= Sequence {
+         *       notBeforeTime  GeneralizedTime,
+         *       notAfterTime   GeneralizedTime
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(notBeforeTime, notAfterTime);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/Attribute.cs b/BouncyCastle.AxCrypt/src/asn1/x509/Attribute.cs
new file mode 100644
index 0000000..d26db93
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/Attribute.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttributeX509
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	attrType;
+        private readonly Asn1Set				attrValues;
+
+		/**
+         * return an Attr object from the given object.
+         *
+         * @param o the object we want converted.
+         * @exception ArgumentException if the object cannot be converted.
+         */
+        public static AttributeX509 GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is AttributeX509)
+            {
+                return (AttributeX509) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new AttributeX509((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private AttributeX509(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			attrType = DerObjectIdentifier.GetInstance(seq[0]);
+			attrValues = Asn1Set.GetInstance(seq[1]);
+        }
+
+		public AttributeX509(
+            DerObjectIdentifier	attrType,
+            Asn1Set				attrValues)
+        {
+            this.attrType = attrType;
+            this.attrValues = attrValues;
+        }
+
+		public DerObjectIdentifier AttrType
+		{
+			get { return attrType; }
+		}
+
+		public Asn1Encodable[] GetAttributeValues()
+		{
+			return attrValues.ToArray();
+		}
+
+		public Asn1Set AttrValues
+		{
+			get { return attrValues; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Attr ::= Sequence {
+         *     attrType OBJECT IDENTIFIER,
+         *     attrValues Set OF AttributeValue
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(attrType, attrValues);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificate.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificate.cs
new file mode 100644
index 0000000..5f85910
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificate.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttributeCertificate
+        : Asn1Encodable
+    {
+        private readonly AttributeCertificateInfo	acinfo;
+        private readonly AlgorithmIdentifier		signatureAlgorithm;
+        private readonly DerBitString				signatureValue;
+
+		/**
+         * @param obj
+         * @return
+         */
+        public static AttributeCertificate GetInstance(
+			object obj)
+        {
+            if (obj is AttributeCertificate)
+                return (AttributeCertificate) obj;
+
+			if (obj != null)
+				return new AttributeCertificate(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		public AttributeCertificate(
+            AttributeCertificateInfo	acinfo,
+            AlgorithmIdentifier			signatureAlgorithm,
+            DerBitString				signatureValue)
+        {
+            this.acinfo = acinfo;
+            this.signatureAlgorithm = signatureAlgorithm;
+            this.signatureValue = signatureValue;
+        }
+
+		private AttributeCertificate(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			this.acinfo = AttributeCertificateInfo.GetInstance(seq[0]);
+            this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+            this.signatureValue = DerBitString.GetInstance(seq[2]);
+        }
+
+		public AttributeCertificateInfo ACInfo
+		{
+			get { return acinfo; }
+		}
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return signatureAlgorithm; }
+		}
+
+		public DerBitString SignatureValue
+		{
+			get { return signatureValue; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  AttributeCertificate ::= Sequence {
+         *       acinfo               AttributeCertificateInfo,
+         *       signatureAlgorithm   AlgorithmIdentifier,
+         *       signatureValue       BIT STRING
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(acinfo, signatureAlgorithm, signatureValue);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificateInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificateInfo.cs
new file mode 100644
index 0000000..dcef3d4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeCertificateInfo.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttributeCertificateInfo
+        : Asn1Encodable
+    {
+        internal readonly DerInteger			version;
+        internal readonly Holder				holder;
+        internal readonly AttCertIssuer			issuer;
+        internal readonly AlgorithmIdentifier	signature;
+        internal readonly DerInteger			serialNumber;
+        internal readonly AttCertValidityPeriod	attrCertValidityPeriod;
+        internal readonly Asn1Sequence			attributes;
+        internal readonly DerBitString			issuerUniqueID;
+        internal readonly X509Extensions		extensions;
+
+		public static AttributeCertificateInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+		public static AttributeCertificateInfo GetInstance(
+            object obj)
+        {
+            if (obj is AttributeCertificateInfo)
+            {
+                return (AttributeCertificateInfo) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new AttributeCertificateInfo((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private AttributeCertificateInfo(
+            Asn1Sequence seq)
+        {
+			if (seq.Count < 7 || seq.Count > 9)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			this.version = DerInteger.GetInstance(seq[0]);
+            this.holder = Holder.GetInstance(seq[1]);
+            this.issuer = AttCertIssuer.GetInstance(seq[2]);
+            this.signature = AlgorithmIdentifier.GetInstance(seq[3]);
+            this.serialNumber = DerInteger.GetInstance(seq[4]);
+            this.attrCertValidityPeriod = AttCertValidityPeriod.GetInstance(seq[5]);
+            this.attributes = Asn1Sequence.GetInstance(seq[6]);
+
+			for (int i = 7; i < seq.Count; i++)
+            {
+                Asn1Encodable obj = (Asn1Encodable) seq[i];
+
+				if (obj is DerBitString)
+                {
+                    this.issuerUniqueID = DerBitString.GetInstance(seq[i]);
+                }
+                else if (obj is Asn1Sequence || obj is X509Extensions)
+                {
+                    this.extensions = X509Extensions.GetInstance(seq[i]);
+                }
+            }
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public Holder Holder
+		{
+			get { return holder; }
+		}
+
+		public AttCertIssuer Issuer
+		{
+			get { return issuer; }
+		}
+
+		public AlgorithmIdentifier Signature
+		{
+			get { return signature; }
+		}
+
+		public DerInteger SerialNumber
+		{
+			get { return serialNumber; }
+		}
+
+		public AttCertValidityPeriod AttrCertValidityPeriod
+		{
+			get { return attrCertValidityPeriod; }
+		}
+
+		public Asn1Sequence Attributes
+		{
+			get { return attributes; }
+		}
+
+		public DerBitString IssuerUniqueID
+		{
+			get { return issuerUniqueID; }
+		}
+
+		public X509Extensions Extensions
+		{
+			get { return extensions; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  AttributeCertificateInfo ::= Sequence {
+         *       version              AttCertVersion -- version is v2,
+         *       holder               Holder,
+         *       issuer               AttCertIssuer,
+         *       signature            AlgorithmIdentifier,
+         *       serialNumber         CertificateSerialNumber,
+         *       attrCertValidityPeriod   AttCertValidityPeriod,
+         *       attributes           Sequence OF Attr,
+         *       issuerUniqueID       UniqueIdentifier OPTIONAL,
+         *       extensions           Extensions OPTIONAL
+         *  }
+         *
+         *  AttCertVersion ::= Integer { v2(1) }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				version, holder, issuer, signature, serialNumber,
+				attrCertValidityPeriod, attributes);
+
+			if (issuerUniqueID != null)
+            {
+                v.Add(issuerUniqueID);
+            }
+
+			if (extensions != null)
+            {
+                v.Add(extensions);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AttributeTable.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeTable.cs
new file mode 100644
index 0000000..ffe0ea9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AttributeTable.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class AttributeTable
+    {
+        private readonly IDictionary attributes;
+
+        public AttributeTable(
+            IDictionary attrs)
+        {
+            this.attributes = Platform.CreateHashtable(attrs);
+        }
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public AttributeTable(
+            Hashtable attrs)
+        {
+            this.attributes = Platform.CreateHashtable(attrs);
+        }
+#endif
+
+		public AttributeTable(
+            Asn1EncodableVector v)
+        {
+            this.attributes = Platform.CreateHashtable(v.Count);
+
+			for (int i = 0; i != v.Count; i++)
+            {
+                AttributeX509 a = AttributeX509.GetInstance(v[i]);
+
+				attributes.Add(a.AttrType, a);
+            }
+        }
+
+		public AttributeTable(
+            Asn1Set s)
+        {
+            this.attributes = Platform.CreateHashtable(s.Count);
+
+			for (int i = 0; i != s.Count; i++)
+            {
+                AttributeX509 a = AttributeX509.GetInstance(s[i]);
+
+				attributes.Add(a.AttrType, a);
+            }
+        }
+
+		public AttributeX509 Get(
+            DerObjectIdentifier oid)
+        {
+            return (AttributeX509) attributes[oid];
+        }
+
+#if !SILVERLIGHT
+        [Obsolete("Use 'ToDictionary' instead")]
+		public Hashtable ToHashtable()
+        {
+            return new Hashtable(attributes);
+        }
+#endif
+
+        public IDictionary ToDictionary()
+        {
+            return Platform.CreateHashtable(attributes);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityInformationAccess.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityInformationAccess.cs
new file mode 100644
index 0000000..9329e2b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityInformationAccess.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The AuthorityInformationAccess object.
+     * <pre>
+     * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
+     *
+     * AuthorityInfoAccessSyntax  ::=
+     *      Sequence SIZE (1..MAX) OF AccessDescription
+     * AccessDescription  ::=  Sequence {
+     *       accessMethod          OBJECT IDENTIFIER,
+     *       accessLocation        GeneralName  }
+     *
+     * id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
+     * id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
+     * id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
+     * </pre>
+     */
+    public class AuthorityInformationAccess
+        : Asn1Encodable
+    {
+        private readonly AccessDescription[] descriptions;
+
+        public static AuthorityInformationAccess GetInstance(object obj)
+        {
+            if (obj is AuthorityInformationAccess)
+                return (AuthorityInformationAccess)obj;
+            if (obj == null)
+                return null;
+            return new AuthorityInformationAccess(Asn1Sequence.GetInstance(obj));
+        }
+
+        private AuthorityInformationAccess(
+            Asn1Sequence seq)
+        {
+            if (seq.Count < 1)
+                throw new ArgumentException("sequence may not be empty");
+
+            this.descriptions = new AccessDescription[seq.Count];
+
+            for (int i = 0; i < seq.Count; ++i)
+            {
+                descriptions[i] = AccessDescription.GetInstance(seq[i]);
+            }
+        }
+
+        public AuthorityInformationAccess(
+            AccessDescription description)
+        {
+            this.descriptions = new AccessDescription[]{ description };
+        }
+
+        /**
+         * create an AuthorityInformationAccess with the oid and location provided.
+         */
+        public AuthorityInformationAccess(DerObjectIdentifier oid, GeneralName location)
+            : this(new AccessDescription(oid, location))
+        {
+        }
+
+        public AccessDescription[] GetAccessDescriptions()
+        {
+            return (AccessDescription[])descriptions.Clone();
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(descriptions);
+        }
+
+        public override string ToString()
+        {
+            //return "AuthorityInformationAccess: Oid(" + this.descriptions[0].AccessMethod.Id + ")";
+
+            StringBuilder buf = new StringBuilder();
+            string sep = Platform.NewLine;
+
+            buf.Append("AuthorityInformationAccess:");
+            buf.Append(sep);
+
+            foreach (AccessDescription description in descriptions)
+            {
+                buf.Append("    ");
+                buf.Append(description);
+                buf.Append(sep);
+            }
+
+            return buf.ToString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityKeyIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityKeyIdentifier.cs
new file mode 100644
index 0000000..12ccacf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/AuthorityKeyIdentifier.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The AuthorityKeyIdentifier object.
+     * <pre>
+     * id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::=  { id-ce 35 }
+     *
+     *   AuthorityKeyIdentifier ::= Sequence {
+     *      keyIdentifier             [0] IMPLICIT KeyIdentifier           OPTIONAL,
+     *      authorityCertIssuer       [1] IMPLICIT GeneralNames            OPTIONAL,
+     *      authorityCertSerialNumber [2] IMPLICIT CertificateSerialNumber OPTIONAL  }
+     *
+     *   KeyIdentifier ::= OCTET STRING
+     * </pre>
+     *
+     */
+    public class AuthorityKeyIdentifier
+        : Asn1Encodable
+    {
+        internal readonly Asn1OctetString	keyidentifier;
+        internal readonly GeneralNames		certissuer;
+        internal readonly DerInteger		certserno;
+
+		public static AuthorityKeyIdentifier GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static AuthorityKeyIdentifier GetInstance(
+            object obj)
+        {
+            if (obj is AuthorityKeyIdentifier)
+            {
+                return (AuthorityKeyIdentifier) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new AuthorityKeyIdentifier((Asn1Sequence) obj);
+            }
+
+	        if (obj is X509Extension)
+			{
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		protected internal AuthorityKeyIdentifier(
+            Asn1Sequence seq)
+        {
+			foreach (Asn1TaggedObject o in seq)
+			{
+				switch (o.TagNo)
+                {
+					case 0:
+						this.keyidentifier = Asn1OctetString.GetInstance(o, false);
+						break;
+					case 1:
+						this.certissuer = GeneralNames.GetInstance(o, false);
+						break;
+					case 2:
+						this.certserno = DerInteger.GetInstance(o, false);
+						break;
+					default:
+						throw new ArgumentException("illegal tag");
+                }
+            }
+        }
+
+		/**
+         *
+         * Calulates the keyidentifier using a SHA1 hash over the BIT STRING
+         * from SubjectPublicKeyInfo as defined in RFC2459.
+         *
+         * Example of making a AuthorityKeyIdentifier:
+         * <pre>
+	     *   SubjectPublicKeyInfo apki = new SubjectPublicKeyInfo((ASN1Sequence)new ASN1InputStream(
+		 *       publicKey.getEncoded()).readObject());
+         *   AuthorityKeyIdentifier aki = new AuthorityKeyIdentifier(apki);
+         * </pre>
+         *
+         **/
+        public AuthorityKeyIdentifier(
+            SubjectPublicKeyInfo spki)
+        {
+            IDigest digest = new Sha1Digest();
+            byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			byte[] bytes = spki.PublicKeyData.GetBytes();
+            digest.BlockUpdate(bytes, 0, bytes.Length);
+            digest.DoFinal(resBuf, 0);
+            this.keyidentifier = new DerOctetString(resBuf);
+        }
+
+        /**
+         * create an AuthorityKeyIdentifier with the GeneralNames tag and
+         * the serial number provided as well.
+         */
+        public AuthorityKeyIdentifier(
+            SubjectPublicKeyInfo	spki,
+            GeneralNames			name,
+            BigInteger				serialNumber)
+        {
+            IDigest digest = new Sha1Digest();
+            byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			byte[] bytes = spki.PublicKeyData.GetBytes();
+            digest.BlockUpdate(bytes, 0, bytes.Length);
+            digest.DoFinal(resBuf, 0);
+
+			this.keyidentifier = new DerOctetString(resBuf);
+            this.certissuer = name;
+            this.certserno = new DerInteger(serialNumber);
+        }
+
+		/**
+		 * create an AuthorityKeyIdentifier with the GeneralNames tag and
+		 * the serial number provided.
+		 */
+		public AuthorityKeyIdentifier(
+			GeneralNames	name,
+			BigInteger		serialNumber)
+		{
+			this.keyidentifier = null;
+			this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
+			this.certserno = new DerInteger(serialNumber);
+		}
+
+		/**
+		 * create an AuthorityKeyIdentifier with a precomputed key identifier
+		 */
+		public AuthorityKeyIdentifier(
+			byte[] keyIdentifier)
+		{
+			this.keyidentifier = new DerOctetString(keyIdentifier);
+			this.certissuer = null;
+			this.certserno = null;
+		}
+
+		/**
+		 * create an AuthorityKeyIdentifier with a precomupted key identifier
+		 * and the GeneralNames tag and the serial number provided as well.
+		 */
+		public AuthorityKeyIdentifier(
+			byte[]			keyIdentifier,
+			GeneralNames	name,
+			BigInteger		serialNumber)
+		{
+			this.keyidentifier = new DerOctetString(keyIdentifier);
+			this.certissuer = GeneralNames.GetInstance(name.ToAsn1Object());
+			this.certserno = new DerInteger(serialNumber);
+		}
+
+		public byte[] GetKeyIdentifier()
+        {
+			return keyidentifier == null ? null : keyidentifier.GetOctets();
+        }
+
+		public GeneralNames AuthorityCertIssuer
+		{
+			get { return certissuer; }
+		}
+
+		public BigInteger AuthorityCertSerialNumber
+        {
+            get { return certserno == null ? null : certserno.Value; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (keyidentifier != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, keyidentifier));
+            }
+
+			if (certissuer != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, certissuer));
+            }
+
+			if (certserno != null)
+            {
+                v.Add(new DerTaggedObject(false, 2, certserno));
+            }
+
+			return new DerSequence(v);
+        }
+
+		public override string ToString()
+        {
+            return ("AuthorityKeyIdentifier: KeyID(" + this.keyidentifier.GetOctets() + ")");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/BasicConstraints.cs b/BouncyCastle.AxCrypt/src/asn1/x509/BasicConstraints.cs
new file mode 100644
index 0000000..522cb61
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/BasicConstraints.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class BasicConstraints
+        : Asn1Encodable
+    {
+        private readonly DerBoolean	cA;
+        private readonly DerInteger	pathLenConstraint;
+
+		public static BasicConstraints GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static BasicConstraints GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is BasicConstraints)
+            {
+                return (BasicConstraints) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new BasicConstraints((Asn1Sequence) obj);
+            }
+
+			if (obj is X509Extension)
+			{
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private BasicConstraints(
+            Asn1Sequence seq)
+        {
+			if (seq.Count > 0)
+			{
+				if (seq[0] is DerBoolean)
+				{
+					this.cA = DerBoolean.GetInstance(seq[0]);
+				}
+				else
+				{
+					this.pathLenConstraint = DerInteger.GetInstance(seq[0]);
+				}
+
+				if (seq.Count > 1)
+				{
+					if (this.cA == null)
+						throw new ArgumentException("wrong sequence in constructor", "seq");
+
+					this.pathLenConstraint = DerInteger.GetInstance(seq[1]);
+				}
+			}
+        }
+
+		public BasicConstraints(
+            bool cA)
+        {
+			if (cA)
+			{
+				this.cA = DerBoolean.True;
+			}
+        }
+
+		/**
+         * create a cA=true object for the given path length constraint.
+         *
+         * @param pathLenConstraint
+         */
+        public BasicConstraints(
+            int pathLenConstraint)
+        {
+            this.cA = DerBoolean.True;
+            this.pathLenConstraint = new DerInteger(pathLenConstraint);
+        }
+
+		public bool IsCA()
+        {
+            return cA != null && cA.IsTrue;
+        }
+
+		public BigInteger PathLenConstraint
+        {
+            get { return pathLenConstraint == null ? null : pathLenConstraint.Value; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * BasicConstraints := Sequence {
+         *    cA                  Boolean DEFAULT FALSE,
+         *    pathLenConstraint   Integer (0..MAX) OPTIONAL
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (cA != null)
+			{
+				v.Add(cA);
+			}
+
+            if (pathLenConstraint != null)  // yes some people actually do this when cA is false...
+            {
+                v.Add(pathLenConstraint);
+            }
+
+			return new DerSequence(v);
+        }
+
+		public override string ToString()
+        {
+            if (pathLenConstraint == null)
+            {
+				return "BasicConstraints: isCa(" + this.IsCA() + ")";
+            }
+
+			return "BasicConstraints: isCa(" + this.IsCA() + "), pathLenConstraint = " + pathLenConstraint.Value;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CRLDistPoint.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CRLDistPoint.cs
new file mode 100644
index 0000000..2b5c197
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CRLDistPoint.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class CrlDistPoint
+        : Asn1Encodable
+    {
+        internal readonly Asn1Sequence seq;
+
+		public static CrlDistPoint GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static CrlDistPoint GetInstance(
+            object obj)
+        {
+            if (obj is CrlDistPoint || obj == null)
+            {
+                return (CrlDistPoint) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new CrlDistPoint((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		private CrlDistPoint(
+            Asn1Sequence seq)
+        {
+            this.seq = seq;
+        }
+
+		public CrlDistPoint(
+            DistributionPoint[] points)
+        {
+			seq = new DerSequence(points);
+        }
+
+		/**
+         * Return the distribution points making up the sequence.
+         *
+         * @return DistributionPoint[]
+         */
+        public DistributionPoint[] GetDistributionPoints()
+        {
+            DistributionPoint[] dp = new DistributionPoint[seq.Count];
+
+			for (int i = 0; i != seq.Count; ++i)
+            {
+                dp[i] = DistributionPoint.GetInstance(seq[i]);
+            }
+
+			return dp;
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * CrlDistPoint ::= Sequence SIZE {1..MAX} OF DistributionPoint
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			string sep = Platform.NewLine;
+
+			buf.Append("CRLDistPoint:");
+			buf.Append(sep);
+			DistributionPoint[] dp = GetDistributionPoints();
+			for (int i = 0; i != dp.Length; i++)
+			{
+				buf.Append("    ");
+				buf.Append(dp[i]);
+				buf.Append(sep);
+			}
+			return buf.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CRLNumber.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CRLNumber.cs
new file mode 100644
index 0000000..d744416
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CRLNumber.cs
@@ -0,0 +1,30 @@
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The CRLNumber object.
+     * <pre>
+     * CRLNumber::= Integer(0..MAX)
+     * </pre>
+     */
+    public class CrlNumber
+        : DerInteger
+    {
+        public CrlNumber(
+			BigInteger number)
+			: base(number)
+        {
+        }
+
+		public BigInteger Number
+		{
+			get { return PositiveValue; }
+		}
+
+		public override string ToString()
+		{
+			return "CRLNumber: " + Number;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CRLReason.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CRLReason.cs
new file mode 100644
index 0000000..e8eb53a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CRLReason.cs
@@ -0,0 +1,61 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The CRLReason enumeration.
+     * <pre>
+     * CRLReason ::= Enumerated {
+     *  unspecified             (0),
+     *  keyCompromise           (1),
+     *  cACompromise            (2),
+     *  affiliationChanged      (3),
+     *  superseded              (4),
+     *  cessationOfOperation    (5),
+     *  certificateHold         (6),
+     *  removeFromCRL           (8),
+     *  privilegeWithdrawn      (9),
+     *  aACompromise           (10)
+     * }
+     * </pre>
+     */
+    public class CrlReason
+        : DerEnumerated
+    {
+        public const int Unspecified = 0;
+        public const int KeyCompromise = 1;
+        public const int CACompromise = 2;
+        public const int AffiliationChanged = 3;
+        public const int Superseded = 4;
+        public const int CessationOfOperation  = 5;
+        public const int CertificateHold = 6;
+		// 7 -> Unknown
+        public const int RemoveFromCrl = 8;
+        public const int PrivilegeWithdrawn = 9;
+        public const int AACompromise = 10;
+
+		private static readonly string[] ReasonString = new string[]
+		{
+			"Unspecified", "KeyCompromise", "CACompromise", "AffiliationChanged",
+			"Superseded", "CessationOfOperation", "CertificateHold", "Unknown",
+			"RemoveFromCrl", "PrivilegeWithdrawn", "AACompromise"
+		};
+
+		public CrlReason(
+			int reason)
+			: base(reason)
+        {
+        }
+
+		public CrlReason(
+			DerEnumerated reason)
+			: base(reason.Value.IntValue)
+        {
+        }
+
+		public override string ToString()
+		{
+			int reason = Value.IntValue;
+			string str = (reason < 0 || reason > 10) ? "Invalid" : ReasonString[reason];
+			return "CrlReason: " + str;
+		}    
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CertPolicyId.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CertPolicyId.cs
new file mode 100644
index 0000000..11cebcd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CertPolicyId.cs
@@ -0,0 +1,20 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * CertPolicyId, used in the CertificatePolicies and PolicyMappings
+     * X509V3 Extensions.
+     *
+     * <pre>
+     *     CertPolicyId ::= OBJECT IDENTIFIER
+     * </pre>
+     */
+     public class CertPolicyID
+		 : DerObjectIdentifier
+    {
+       public CertPolicyID(
+		   string id)
+		   : base(id)
+       {
+       }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CertificateList.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CertificateList.cs
new file mode 100644
index 0000000..0412e08
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CertificateList.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * PKIX RFC-2459
+     *
+     * The X.509 v2 CRL syntax is as follows.  For signature calculation,
+     * the data that is to be signed is ASN.1 Der encoded.
+     *
+     * <pre>
+     * CertificateList  ::=  Sequence  {
+     *      tbsCertList          TbsCertList,
+     *      signatureAlgorithm   AlgorithmIdentifier,
+     *      signatureValue       BIT STRING  }
+     * </pre>
+     */
+    public class CertificateList
+        : Asn1Encodable
+    {
+        private readonly TbsCertificateList	tbsCertList;
+        private readonly AlgorithmIdentifier sigAlgID;
+        private readonly DerBitString sig;
+
+		public static CertificateList GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static CertificateList GetInstance(
+            object obj)
+        {
+            if (obj is CertificateList)
+                return (CertificateList) obj;
+
+			if (obj != null)
+				return new CertificateList(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		private CertificateList(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 3)
+				throw new ArgumentException("sequence wrong size for CertificateList", "seq");
+
+			tbsCertList = TbsCertificateList.GetInstance(seq[0]);
+			sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]);
+			sig = DerBitString.GetInstance(seq[2]);
+        }
+
+		public TbsCertificateList TbsCertList
+		{
+			get { return tbsCertList; }
+		}
+
+		public CrlEntry[] GetRevokedCertificates()
+        {
+            return tbsCertList.GetRevokedCertificates();
+        }
+
+		public IEnumerable GetRevokedCertificateEnumeration()
+		{
+			return tbsCertList.GetRevokedCertificateEnumeration();
+		}
+
+		public AlgorithmIdentifier SignatureAlgorithm
+		{
+			get { return sigAlgID; }
+		}
+
+		public DerBitString Signature
+		{
+			get { return sig; }
+		}
+
+		public int Version
+		{
+			get { return tbsCertList.Version; }
+		}
+
+		public X509Name Issuer
+		{
+			get { return tbsCertList.Issuer; }
+		}
+
+		public Time ThisUpdate
+		{
+			get { return tbsCertList.ThisUpdate; }
+		}
+
+		public Time NextUpdate
+		{
+			get { return tbsCertList.NextUpdate; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(tbsCertList, sigAlgID, sig);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePair.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePair.cs
new file mode 100644
index 0000000..8baa647
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePair.cs
@@ -0,0 +1,160 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	* This class helps to support crossCerfificatePairs in a LDAP directory
+	* according RFC 2587
+	*
+	* <pre>
+	*     crossCertificatePairATTRIBUTE::={
+	*       WITH SYNTAX   CertificatePair
+	*       EQUALITY MATCHING RULE certificatePairExactMatch
+	*       ID joint-iso-ccitt(2) ds(5) attributeType(4) crossCertificatePair(40)}
+	* </pre>
+	*
+	* <blockquote> The forward elements of the crossCertificatePair attribute of a
+	* CA's directory entry shall be used to store all, except self-issued
+	* certificates issued to this CA. Optionally, the reverse elements of the
+	* crossCertificatePair attribute, of a CA's directory entry may contain a
+	* subset of certificates issued by this CA to other CAs. When both the forward
+	* and the reverse elements are present in a single attribute value, issuer name
+	* in one certificate shall match the subject name in the other and vice versa,
+	* and the subject public key in one certificate shall be capable of verifying
+	* the digital signature on the other certificate and vice versa.
+	*
+	* When a reverse element is present, the forward element value and the reverse
+	* element value need not be stored in the same attribute value; in other words,
+	* they can be stored in either a single attribute value or two attribute
+	* values. </blockquote>
+	*
+	* <pre>
+	*       CertificatePair ::= SEQUENCE {
+	*         forward		[0]	Certificate OPTIONAL,
+	*         reverse		[1]	Certificate OPTIONAL,
+	*         -- at least one of the pair shall be present -- }
+	* </pre>
+	*/
+	public class CertificatePair
+		: Asn1Encodable
+	{
+		private X509CertificateStructure forward, reverse;
+
+		public static CertificatePair GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is CertificatePair)
+			{
+				return (CertificatePair) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new CertificatePair((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type CertificatePair:
+		* <p/>
+		* <pre>
+		*       CertificatePair ::= SEQUENCE {
+		*         forward		[0]	Certificate OPTIONAL,
+		*         reverse		[1]	Certificate OPTIONAL,
+		*         -- at least one of the pair shall be present -- }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private CertificatePair(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 1 && seq.Count != 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+			}
+
+			foreach (object obj in seq)
+			{
+				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(obj);
+				if (o.TagNo == 0)
+				{
+					forward = X509CertificateStructure.GetInstance(o, true);
+				}
+				else if (o.TagNo == 1)
+				{
+					reverse = X509CertificateStructure.GetInstance(o, true);
+				}
+				else
+				{
+					throw new ArgumentException("Bad tag number: " + o.TagNo);
+				}
+			}
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param forward Certificates issued to this CA.
+		* @param reverse Certificates issued by this CA to other CAs.
+		*/
+		public CertificatePair(
+			X509CertificateStructure	forward,
+			X509CertificateStructure	reverse)
+		{
+			this.forward = forward;
+			this.reverse = reverse;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*       CertificatePair ::= SEQUENCE {
+		*         forward		[0]	Certificate OPTIONAL,
+		*         reverse		[1]	Certificate OPTIONAL,
+		*         -- at least one of the pair shall be present -- }
+		* </pre>
+		*
+		* @return a DERObject
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+
+			if (forward != null)
+			{
+				vec.Add(new DerTaggedObject(0, forward));
+			}
+
+			if (reverse != null)
+			{
+				vec.Add(new DerTaggedObject(1, reverse));
+			}
+
+			return new DerSequence(vec);
+		}
+
+		/**
+		* @return Returns the forward.
+		*/
+		public X509CertificateStructure Forward
+		{
+			get { return forward; }
+		}
+
+		/**
+		* @return Returns the reverse.
+		*/
+		public X509CertificateStructure Reverse
+		{
+			get { return reverse; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePolicies.cs b/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePolicies.cs
new file mode 100644
index 0000000..a83565b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/CertificatePolicies.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class CertificatePolicies
+        : Asn1Encodable
+    {
+        private readonly PolicyInformation[] policyInformation;
+
+        public static CertificatePolicies GetInstance(object obj)
+        {
+            if (obj == null || obj is CertificatePolicies)
+                return (CertificatePolicies)obj;
+
+            return new CertificatePolicies(Asn1Sequence.GetInstance(obj));
+        }
+
+        public static CertificatePolicies GetInstance(Asn1TaggedObject obj, bool isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+        /**
+         * Construct a CertificatePolicies object containing one PolicyInformation.
+         * 
+         * @param name the name to be contained.
+         */
+        public CertificatePolicies(PolicyInformation name)
+        {
+            this.policyInformation = new PolicyInformation[] { name };
+        }
+
+        public CertificatePolicies(PolicyInformation[] policyInformation)
+        {
+            this.policyInformation = policyInformation;
+        }
+
+        private CertificatePolicies(Asn1Sequence seq)
+        {
+            this.policyInformation = new PolicyInformation[seq.Count];
+
+            for (int i = 0; i < seq.Count; ++i)
+            {
+                policyInformation[i] = PolicyInformation.GetInstance(seq[i]);
+            }
+        }
+
+        public virtual PolicyInformation[] GetPolicyInformation()
+        {
+            return (PolicyInformation[])policyInformation.Clone();
+        }
+
+        /**
+         * Produce an object suitable for an ASN1OutputStream.
+         * <pre>
+         * CertificatePolicies ::= SEQUENCE SIZE {1..MAX} OF PolicyInformation
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(policyInformation);
+        }
+
+        public override string ToString()
+        {
+            StringBuilder sb = new StringBuilder("CertificatePolicies:");
+            if (policyInformation != null && policyInformation.Length > 0)
+            {
+                sb.Append(' ');
+                sb.Append(policyInformation[0]);
+                for (int i = 1; i < policyInformation.Length; ++i)
+                {
+                    sb.Append(", ");
+                    sb.Append(policyInformation[i]);
+                }
+            }
+            return sb.ToString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/DSAParameter.cs b/BouncyCastle.AxCrypt/src/asn1/x509/DSAParameter.cs
new file mode 100644
index 0000000..b2b325f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/DSAParameter.cs
@@ -0,0 +1,77 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class DsaParameter
+        : Asn1Encodable
+    {
+        internal readonly DerInteger p, q, g;
+
+		public static DsaParameter GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static DsaParameter GetInstance(
+            object obj)
+        {
+            if(obj == null || obj is DsaParameter)
+            {
+                return (DsaParameter) obj;
+            }
+
+			if(obj is Asn1Sequence)
+            {
+                return new DsaParameter((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid DsaParameter: " + obj.GetType().Name);
+        }
+
+		public DsaParameter(
+            BigInteger	p,
+            BigInteger	q,
+            BigInteger	g)
+        {
+            this.p = new DerInteger(p);
+            this.q = new DerInteger(q);
+            this.g = new DerInteger(g);
+        }
+
+		private DsaParameter(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.p = DerInteger.GetInstance(seq[0]);
+			this.q = DerInteger.GetInstance(seq[1]);
+			this.g = DerInteger.GetInstance(seq[2]);
+        }
+
+		public BigInteger P
+		{
+			get { return p.PositiveValue; }
+		}
+
+		public BigInteger Q
+		{
+			get { return q.PositiveValue; }
+		}
+
+		public BigInteger G
+		{
+			get { return g.PositiveValue; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(p, q, g);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/DigestInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x509/DigestInfo.cs
new file mode 100644
index 0000000..1dec227
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/DigestInfo.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The DigestInfo object.
+     * <pre>
+     * DigestInfo::=Sequence{
+     *          digestAlgorithm  AlgorithmIdentifier,
+     *          digest OCTET STRING }
+     * </pre>
+     */
+    public class DigestInfo
+        : Asn1Encodable
+    {
+        private readonly byte[] digest;
+        private readonly AlgorithmIdentifier algID;
+
+		public static DigestInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static DigestInfo GetInstance(
+            object obj)
+        {
+            if (obj is DigestInfo)
+            {
+                return (DigestInfo) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new DigestInfo((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public DigestInfo(
+            AlgorithmIdentifier	algID,
+            byte[]				digest)
+        {
+            this.digest = digest;
+            this.algID = algID;
+        }
+
+		private DigestInfo(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Wrong number of elements in sequence", "seq");
+
+            algID = AlgorithmIdentifier.GetInstance(seq[0]);
+			digest = Asn1OctetString.GetInstance(seq[1]).GetOctets();
+		}
+
+		public AlgorithmIdentifier AlgorithmID
+		{
+			get { return algID; }
+		}
+
+		public byte[] GetDigest()
+        {
+            return digest;
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(algID, new DerOctetString(digest));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/DisplayText.cs b/BouncyCastle.AxCrypt/src/asn1/x509/DisplayText.cs
new file mode 100644
index 0000000..699f390
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/DisplayText.cs
@@ -0,0 +1,172 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * <code>DisplayText</code> class, used in
+	 * <code>CertificatePolicies</code> X509 V3 extensions (in policy qualifiers).
+	 *
+	 * <p>It stores a string in a chosen encoding.
+	 * <pre>
+	 * DisplayText ::= CHOICE {
+	 *      ia5String        IA5String      (SIZE (1..200)),
+	 *      visibleString    VisibleString  (SIZE (1..200)),
+	 *      bmpString        BMPString      (SIZE (1..200)),
+	 *      utf8String       UTF8String     (SIZE (1..200)) }
+	 * </pre></p>
+	 * @see PolicyQualifierInfo
+	 * @see PolicyInformation
+	 */
+	public class DisplayText
+		: Asn1Encodable, IAsn1Choice
+	{
+		/**
+		 * Constant corresponding to ia5String encoding.
+		 *
+		 */
+		public const int ContentTypeIA5String = 0;
+		/**
+		 * Constant corresponding to bmpString encoding.
+		 *
+		 */
+		public const int ContentTypeBmpString = 1;
+		/**
+		 * Constant corresponding to utf8String encoding.
+		 *
+		 */
+		public const int ContentTypeUtf8String = 2;
+		/**
+		 * Constant corresponding to visibleString encoding.
+		 *
+		 */
+		public const int ContentTypeVisibleString = 3;
+		/**
+		 * Describe constant <code>DisplayTextMaximumSize</code> here.
+		 *
+		 */
+		public const int DisplayTextMaximumSize = 200;
+
+		internal readonly int contentType;
+		internal readonly IAsn1String contents;
+
+		/**
+		 * Creates a new <code>DisplayText</code> instance.
+		 *
+		 * @param type the desired encoding type for the text.
+		 * @param text the text to store. Strings longer than 200
+		 * characters are truncated.
+		 */
+		public DisplayText(
+			int		type,
+			string	text)
+		{
+			if (text.Length > DisplayTextMaximumSize)
+			{
+				// RFC3280 limits these strings to 200 chars
+				// truncate the string
+				text = text.Substring(0, DisplayTextMaximumSize);
+			}
+
+			contentType = type;
+			switch (type)
+			{
+				case ContentTypeIA5String:
+					contents = (IAsn1String)new DerIA5String (text);
+					break;
+				case ContentTypeUtf8String:
+					contents = (IAsn1String)new DerUtf8String(text);
+					break;
+				case ContentTypeVisibleString:
+					contents = (IAsn1String)new DerVisibleString(text);
+					break;
+				case ContentTypeBmpString:
+					contents = (IAsn1String)new DerBmpString(text);
+					break;
+				default:
+					contents = (IAsn1String)new DerUtf8String(text);
+					break;
+			}
+		}
+
+//		/**
+//		 * return true if the passed in string can be represented without
+//		 * loss as a PrintableString, false otherwise.
+//		 */
+//		private bool CanBePrintable(
+//			string str)
+//		{
+//			for (int i = str.Length - 1; i >= 0; i--)
+//			{
+//				if (str[i] > 0x007f)
+//				{
+//					return false;
+//				}
+//			}
+//
+//			return true;
+//		}
+
+		/**
+		 * Creates a new <code>DisplayText</code> instance.
+		 *
+		 * @param text the text to encapsulate. Strings longer than 200
+		 * characters are truncated.
+		 */
+		public DisplayText(
+			string text)
+		{
+			// by default use UTF8String
+			if (text.Length > DisplayTextMaximumSize)
+			{
+				text = text.Substring(0, DisplayTextMaximumSize);
+			}
+
+			contentType = ContentTypeUtf8String;
+			contents = new DerUtf8String(text);
+		}
+
+		/**
+		 * Creates a new <code>DisplayText</code> instance.
+		 * <p>Useful when reading back a <code>DisplayText</code> class
+		 * from it's Asn1Encodable form.</p>
+		 *
+		 * @param contents an <code>Asn1Encodable</code> instance.
+		 */
+		public DisplayText(
+			IAsn1String contents)
+		{
+			this.contents = contents;
+		}
+
+		public static DisplayText GetInstance(
+			object obj)
+		{
+			if (obj is IAsn1String)
+			{
+				return new DisplayText((IAsn1String) obj);
+			}
+
+			if (obj is DisplayText)
+			{
+				return (DisplayText) obj;
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return (Asn1Object) contents;
+		}
+
+		/**
+		 * Returns the stored <code>string</code> object.
+		 *
+		 * @return the stored text as a <code>string</code>.
+		 */
+		public string GetString()
+		{
+			return contents.GetString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPoint.cs b/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPoint.cs
new file mode 100644
index 0000000..ad1d398
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPoint.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The DistributionPoint object.
+     * <pre>
+     * DistributionPoint ::= Sequence {
+     *      distributionPoint [0] DistributionPointName OPTIONAL,
+     *      reasons           [1] ReasonFlags OPTIONAL,
+     *      cRLIssuer         [2] GeneralNames OPTIONAL
+     * }
+     * </pre>
+     */
+    public class DistributionPoint
+        : Asn1Encodable
+    {
+        internal readonly DistributionPointName	distributionPoint;
+        internal readonly ReasonFlags			reasons;
+        internal readonly GeneralNames			cRLIssuer;
+
+		public static DistributionPoint GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static DistributionPoint GetInstance(
+            object obj)
+        {
+            if(obj == null || obj is DistributionPoint)
+            {
+                return (DistributionPoint) obj;
+            }
+
+			if(obj is Asn1Sequence)
+            {
+                return new DistributionPoint((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid DistributionPoint: " + obj.GetType().Name);
+        }
+
+		private DistributionPoint(
+            Asn1Sequence seq)
+        {
+            for (int i = 0; i != seq.Count; i++)
+            {
+				Asn1TaggedObject t = Asn1TaggedObject.GetInstance(seq[i]);
+
+				switch (t.TagNo)
+                {
+                case 0:
+                    distributionPoint = DistributionPointName.GetInstance(t, true);
+                    break;
+                case 1:
+                    reasons = new ReasonFlags(DerBitString.GetInstance(t, false));
+                    break;
+                case 2:
+                    cRLIssuer = GeneralNames.GetInstance(t, false);
+                    break;
+                }
+            }
+        }
+
+		public DistributionPoint(
+            DistributionPointName	distributionPointName,
+            ReasonFlags				reasons,
+            GeneralNames			crlIssuer)
+        {
+            this.distributionPoint = distributionPointName;
+            this.reasons = reasons;
+            this.cRLIssuer = crlIssuer;
+        }
+
+		public DistributionPointName DistributionPointName
+        {
+			get { return distributionPoint; }
+        }
+
+		public ReasonFlags Reasons
+        {
+			get { return reasons; }
+        }
+
+		public GeneralNames CrlIssuer
+        {
+			get { return cRLIssuer; }
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (distributionPoint != null)
+            {
+                //
+                // as this is a CHOICE it must be explicitly tagged
+                //
+                v.Add(new DerTaggedObject(0, distributionPoint));
+            }
+
+			if (reasons != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, reasons));
+            }
+
+			if (cRLIssuer != null)
+            {
+                v.Add(new DerTaggedObject(false, 2, cRLIssuer));
+            }
+
+			return new DerSequence(v);
+        }
+
+		public override string ToString()
+		{
+			string sep = Platform.NewLine;
+			StringBuilder buf = new StringBuilder();
+			buf.Append("DistributionPoint: [");
+			buf.Append(sep);
+			if (distributionPoint != null)
+			{
+				appendObject(buf, sep, "distributionPoint", distributionPoint.ToString());
+			}
+			if (reasons != null)
+			{
+				appendObject(buf, sep, "reasons", reasons.ToString());
+			}
+			if (cRLIssuer != null)
+			{
+				appendObject(buf, sep, "cRLIssuer", cRLIssuer.ToString());
+			}
+			buf.Append("]");
+			buf.Append(sep);
+			return buf.ToString();
+		}
+
+		private void appendObject(
+			StringBuilder	buf,
+			string			sep,
+			string			name,
+			string			val)
+		{
+			string indent = "    ";
+
+			buf.Append(indent);
+			buf.Append(name);
+			buf.Append(":");
+			buf.Append(sep);
+			buf.Append(indent);
+			buf.Append(indent);
+			buf.Append(val);
+			buf.Append(sep);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPointName.cs b/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPointName.cs
new file mode 100644
index 0000000..1a9d242
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/DistributionPointName.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The DistributionPointName object.
+     * <pre>
+     * DistributionPointName ::= CHOICE {
+     *     fullName                 [0] GeneralNames,
+     *     nameRelativeToCRLIssuer  [1] RDN
+     * }
+     * </pre>
+     */
+    public class DistributionPointName
+        : Asn1Encodable, IAsn1Choice
+    {
+        internal readonly Asn1Encodable	name;
+        internal readonly int			type;
+
+		public const int FullName					= 0;
+        public const int NameRelativeToCrlIssuer	= 1;
+
+		public static DistributionPointName GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1TaggedObject.GetInstance(obj, true));
+        }
+
+		public static DistributionPointName GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is DistributionPointName)
+            {
+                return (DistributionPointName) obj;
+            }
+
+			if (obj is Asn1TaggedObject)
+            {
+                return new DistributionPointName((Asn1TaggedObject) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+        public DistributionPointName(
+            int				type,
+            Asn1Encodable	name)
+        {
+            this.type = type;
+            this.name = name;
+        }
+
+		public DistributionPointName(
+			GeneralNames name)
+			:	this(FullName, name)
+		{
+		}
+
+		public int PointType
+        {
+			get { return type; }
+        }
+
+		public Asn1Encodable Name
+        {
+			get { return name; }
+        }
+
+		public DistributionPointName(
+            Asn1TaggedObject obj)
+        {
+            this.type = obj.TagNo;
+
+			if (type == FullName)
+            {
+                this.name = GeneralNames.GetInstance(obj, false);
+            }
+            else
+            {
+                this.name = Asn1Set.GetInstance(obj, false);
+            }
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return new DerTaggedObject(false, type, name);
+        }
+
+		public override string ToString()
+		{
+			string sep = Platform.NewLine;
+			StringBuilder buf = new StringBuilder();
+			buf.Append("DistributionPointName: [");
+			buf.Append(sep);
+			if (type == FullName)
+			{
+				appendObject(buf, sep, "fullName", name.ToString());
+			}
+			else
+			{
+				appendObject(buf, sep, "nameRelativeToCRLIssuer", name.ToString());
+			}
+			buf.Append("]");
+			buf.Append(sep);
+			return buf.ToString();
+		}
+
+		private void appendObject(
+			StringBuilder	buf,
+			string			sep,
+			string			name,
+			string			val)
+		{
+			string indent = "    ";
+
+			buf.Append(indent);
+			buf.Append(name);
+			buf.Append(":");
+			buf.Append(sep);
+			buf.Append(indent);
+			buf.Append(indent);
+			buf.Append(val);
+			buf.Append(sep);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/ExtendedKeyUsage.cs b/BouncyCastle.AxCrypt/src/asn1/x509/ExtendedKeyUsage.cs
new file mode 100644
index 0000000..a5b11f2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/ExtendedKeyUsage.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The extendedKeyUsage object.
+     * <pre>
+     *      extendedKeyUsage ::= Sequence SIZE (1..MAX) OF KeyPurposeId
+     * </pre>
+     */
+    public class ExtendedKeyUsage
+        : Asn1Encodable
+    {
+        internal readonly IDictionary usageTable = Platform.CreateHashtable();
+        internal readonly Asn1Sequence seq;
+
+        public static ExtendedKeyUsage GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static ExtendedKeyUsage GetInstance(
+            object obj)
+        {
+            if (obj is ExtendedKeyUsage)
+            {
+                return (ExtendedKeyUsage) obj;
+            }
+
+            if (obj is Asn1Sequence)
+            {
+                return new ExtendedKeyUsage((Asn1Sequence) obj);
+            }
+
+            if (obj is X509Extension)
+            {
+                return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+            }
+
+            throw new ArgumentException("Invalid ExtendedKeyUsage: " + obj.GetType().Name);
+        }
+
+        private ExtendedKeyUsage(
+            Asn1Sequence seq)
+        {
+            this.seq = seq;
+
+            foreach (object o in seq)
+            {
+                if (!(o is DerObjectIdentifier))
+                    throw new ArgumentException("Only DerObjectIdentifier instances allowed in ExtendedKeyUsage.");
+
+                this.usageTable[o] = o;
+            }
+        }
+
+        public ExtendedKeyUsage(
+            params KeyPurposeID[] usages)
+        {
+            this.seq = new DerSequence(usages);
+
+            foreach (KeyPurposeID usage in usages)
+            {
+                this.usageTable[usage] = usage;
+            }
+        }
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public ExtendedKeyUsage(
+            ArrayList usages)
+            : this((IEnumerable)usages)
+        {
+        }
+#endif
+
+        public ExtendedKeyUsage(
+            IEnumerable usages)
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            foreach (object usage in usages)
+            {
+                Asn1Encodable o = KeyPurposeID.GetInstance(usage);
+
+                v.Add(o);
+                this.usageTable[o] = o;
+            }
+
+            this.seq = new DerSequence(v);
+        }
+
+        public bool HasKeyPurposeId(
+            KeyPurposeID keyPurposeId)
+        {
+            return usageTable.Contains(keyPurposeId);
+        }
+
+#if !SILVERLIGHT
+        [Obsolete("Use 'GetAllUsages'")]
+        public ArrayList GetUsages()
+        {
+            return new ArrayList(usageTable.Values);
+        }
+#endif
+
+        /**
+         * Returns all extended key usages.
+         * The returned ArrayList contains DerObjectIdentifier instances.
+         * @return An ArrayList with all key purposes.
+         */
+        public IList GetAllUsages()
+        {
+            return Platform.CreateArrayList(usageTable.Values);
+        }
+
+        public int Count
+        {
+            get { return usageTable.Count; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/GeneralName.cs b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralName.cs
new file mode 100644
index 0000000..710ddc9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralName.cs
@@ -0,0 +1,418 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using NetUtils = Org.BouncyCastle.Utilities.Net;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The GeneralName object.
+     * <pre>
+     * GeneralName ::= CHOICE {
+     *      otherName                       [0]     OtherName,
+     *      rfc822Name                      [1]     IA5String,
+     *      dNSName                         [2]     IA5String,
+     *      x400Address                     [3]     ORAddress,
+     *      directoryName                   [4]     Name,
+     *      ediPartyName                    [5]     EDIPartyName,
+     *      uniformResourceIdentifier       [6]     IA5String,
+     *      iPAddress                       [7]     OCTET STRING,
+     *      registeredID                    [8]     OBJECT IDENTIFIER}
+     *
+     * OtherName ::= Sequence {
+     *      type-id    OBJECT IDENTIFIER,
+     *      value      [0] EXPLICIT ANY DEFINED BY type-id }
+     *
+     * EDIPartyName ::= Sequence {
+     *      nameAssigner            [0]     DirectoryString OPTIONAL,
+     *      partyName               [1]     DirectoryString }
+     * </pre>
+     */
+    public class GeneralName
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int OtherName					= 0;
+        public const int Rfc822Name					= 1;
+        public const int DnsName					= 2;
+        public const int X400Address				= 3;
+        public const int DirectoryName				= 4;
+        public const int EdiPartyName				= 5;
+        public const int UniformResourceIdentifier	= 6;
+        public const int IPAddress					= 7;
+        public const int RegisteredID				= 8;
+
+		internal readonly Asn1Encodable	obj;
+        internal readonly int			tag;
+
+		public GeneralName(
+            X509Name directoryName)
+        {
+            this.obj = directoryName;
+            this.tag = 4;
+        }
+
+		/**
+         * When the subjectAltName extension contains an Internet mail address,
+         * the address MUST be included as an rfc822Name. The format of an
+         * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
+         *
+         * When the subjectAltName extension contains a domain name service
+         * label, the domain name MUST be stored in the dNSName (an IA5String).
+         * The name MUST be in the "preferred name syntax," as specified by RFC
+         * 1034 [RFC 1034].
+         *
+         * When the subjectAltName extension contains a URI, the name MUST be
+         * stored in the uniformResourceIdentifier (an IA5String). The name MUST
+         * be a non-relative URL, and MUST follow the URL syntax and encoding
+         * rules specified in [RFC 1738].  The name must include both a scheme
+         * (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
+         * specific-part must include a fully qualified domain name or IP
+         * address as the host.
+         *
+         * When the subjectAltName extension contains a iPAddress, the address
+         * MUST be stored in the octet string in "network byte order," as
+         * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
+         * each octet is the LSB of the corresponding byte in the network
+         * address. For IP Version 4, as specified in RFC 791, the octet string
+         * MUST contain exactly four octets.  For IP Version 6, as specified in
+         * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
+         * 1883].
+         */
+        public GeneralName(
+            Asn1Object	name,
+			int			tag)
+        {
+            this.obj = name;
+            this.tag = tag;
+        }
+
+		public GeneralName(
+            int				tag,
+            Asn1Encodable	name)
+        {
+            this.obj = name;
+            this.tag = tag;
+        }
+
+		/**
+		 * Create a GeneralName for the given tag from the passed in string.
+		 * <p>
+		 * This constructor can handle:
+		 * <ul>
+		 * <li>rfc822Name</li>
+		 * <li>iPAddress</li>
+		 * <li>directoryName</li>
+		 * <li>dNSName</li>
+		 * <li>uniformResourceIdentifier</li>
+		 * <li>registeredID</li>
+		 * </ul>
+		 * For x400Address, otherName and ediPartyName there is no common string
+		 * format defined.
+		 * </p><p>
+		 * Note: A directory name can be encoded in different ways into a byte
+		 * representation. Be aware of this if the byte representation is used for
+		 * comparing results.
+		 * </p>
+		 *
+		 * @param tag tag number
+		 * @param name string representation of name
+		 * @throws ArgumentException if the string encoding is not correct or
+		 *             not supported.
+		 */
+		public GeneralName(
+            int		tag,
+            string	name)
+        {
+			this.tag = tag;
+
+			if (tag == Rfc822Name || tag == DnsName || tag == UniformResourceIdentifier)
+			{
+				this.obj = new DerIA5String(name);
+			}
+			else if (tag == RegisteredID)
+			{
+				this.obj = new DerObjectIdentifier(name);
+			}
+			else if (tag == DirectoryName)
+			{
+				this.obj = new X509Name(name);
+			}
+			else if (tag == IPAddress)
+			{
+				byte[] enc = toGeneralNameEncoding(name);
+				if (enc == null)
+					throw new ArgumentException("IP Address is invalid", "name");
+
+				this.obj = new DerOctetString(enc);
+			}
+			else
+			{
+				throw new ArgumentException("can't process string for tag: " + tag, "tag");
+			}
+		}
+
+		public static GeneralName GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is GeneralName)
+            {
+                return (GeneralName) obj;
+            }
+
+            if (obj is Asn1TaggedObject)
+            {
+                Asn1TaggedObject	tagObj = (Asn1TaggedObject) obj;
+                int					tag = tagObj.TagNo;
+
+				switch (tag)
+				{
+					case OtherName:
+						return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+					case Rfc822Name:
+						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+					case DnsName:
+						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+					case X400Address:
+						throw new ArgumentException("unknown tag: " + tag);
+					case DirectoryName:
+						return new GeneralName(tag, X509Name.GetInstance(tagObj, true));
+					case EdiPartyName:
+						return new GeneralName(tag, Asn1Sequence.GetInstance(tagObj, false));
+					case UniformResourceIdentifier:
+						return new GeneralName(tag, DerIA5String.GetInstance(tagObj, false));
+					case IPAddress:
+						return new GeneralName(tag, Asn1OctetString.GetInstance(tagObj, false));
+					case RegisteredID:
+						return new GeneralName(tag, DerObjectIdentifier.GetInstance(tagObj, false));
+				}
+	        }
+
+            if (obj is byte[])
+	        {
+	            try
+	            {
+	                return GetInstance(Asn1Object.FromByteArray((byte[])obj));
+	            }
+	            catch (IOException)
+	            {
+	                throw new ArgumentException("unable to parse encoded general name");
+	            }
+	        }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		public static GeneralName GetInstance(
+            Asn1TaggedObject	tagObj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1TaggedObject.GetInstance(tagObj, true));
+        }
+
+		public int TagNo
+		{
+			get { return tag; }
+		}
+
+		public Asn1Encodable Name
+		{
+			get { return obj; }
+		}
+
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			buf.Append(tag);
+			buf.Append(": ");
+
+			switch (tag)
+			{
+				case Rfc822Name:
+				case DnsName:
+				case UniformResourceIdentifier:
+					buf.Append(DerIA5String.GetInstance(obj).GetString());
+					break;
+				case DirectoryName:
+					buf.Append(X509Name.GetInstance(obj).ToString());
+					break;
+				default:
+					buf.Append(obj.ToString());
+					break;
+			}
+
+			return buf.ToString();
+		}
+
+		private byte[] toGeneralNameEncoding(
+			string ip)
+		{
+			if (NetUtils.IPAddress.IsValidIPv6WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv6(ip))
+			{
+				int slashIndex = ip.IndexOf('/');
+
+				if (slashIndex < 0)
+				{
+					byte[] addr = new byte[16];
+					int[]  parsedIp = parseIPv6(ip);
+					copyInts(parsedIp, addr, 0);
+
+					return addr;
+				}
+				else
+				{
+					byte[] addr = new byte[32];
+					int[]  parsedIp = parseIPv6(ip.Substring(0, slashIndex));
+					copyInts(parsedIp, addr, 0);
+					string mask = ip.Substring(slashIndex + 1);
+					if (mask.IndexOf(':') > 0)
+					{
+						parsedIp = parseIPv6(mask);
+					}
+					else
+					{
+						parsedIp = parseMask(mask);
+					}
+					copyInts(parsedIp, addr, 16);
+
+					return addr;
+				}
+			}
+			else if (NetUtils.IPAddress.IsValidIPv4WithNetmask(ip) || NetUtils.IPAddress.IsValidIPv4(ip))
+			{
+				int slashIndex = ip.IndexOf('/');
+
+				if (slashIndex < 0)
+				{
+					byte[] addr = new byte[4];
+
+					parseIPv4(ip, addr, 0);
+
+					return addr;
+				}
+				else
+				{
+					byte[] addr = new byte[8];
+
+					parseIPv4(ip.Substring(0, slashIndex), addr, 0);
+
+					string mask = ip.Substring(slashIndex + 1);
+					if (mask.IndexOf('.') > 0)
+					{
+						parseIPv4(mask, addr, 4);
+					}
+					else
+					{
+						parseIPv4Mask(mask, addr, 4);
+					}
+
+					return addr;
+				}
+			}
+
+			return null;
+		}
+
+		private void parseIPv4Mask(string mask, byte[] addr, int offset)
+		{
+			int maskVal = Int32.Parse(mask);
+
+			for (int i = 0; i != maskVal; i++)
+			{
+				addr[(i / 8) + offset] |= (byte)(1 << (i % 8));
+			}
+		}
+
+		private void parseIPv4(string ip, byte[] addr, int offset)
+		{
+			foreach (string token in ip.Split('.', '/'))
+			{
+				addr[offset++] = (byte)Int32.Parse(token);
+			}
+		}
+
+		private int[] parseMask(string mask)
+		{
+			int[] res = new int[8];
+			int   maskVal = Int32.Parse(mask);
+
+			for (int i = 0; i != maskVal; i++)
+			{
+				res[i / 16] |= 1 << (i % 16);
+			}
+			return res;
+		}
+
+		private void copyInts(int[] parsedIp, byte[] addr, int offSet)
+		{
+			for (int i = 0; i != parsedIp.Length; i++)
+			{
+				addr[(i * 2) + offSet] = (byte)(parsedIp[i] >> 8);
+				addr[(i * 2 + 1) + offSet] = (byte)parsedIp[i];
+			}
+		}
+
+		private int[] parseIPv6(string ip)
+		{
+			if (ip.StartsWith("::"))
+			{
+				ip = ip.Substring(1);
+			}
+			else if (ip.EndsWith("::"))
+			{
+				ip = ip.Substring(0, ip.Length - 1);
+			}
+
+			IEnumerator sEnum = ip.Split(':').GetEnumerator();
+
+			int index = 0;
+			int[] val = new int[8];
+
+			int doubleColon = -1;
+
+			while (sEnum.MoveNext())
+			{
+				string e = (string) sEnum.Current;
+
+				if (e.Length == 0)
+				{
+					doubleColon = index;
+					val[index++] = 0;
+				}
+				else
+				{
+					if (e.IndexOf('.') < 0)
+					{
+						val[index++] = Int32.Parse(e, NumberStyles.AllowHexSpecifier);
+					}
+					else
+					{
+						string[] tokens = e.Split('.');
+
+						val[index++] = (Int32.Parse(tokens[0]) << 8) | Int32.Parse(tokens[1]);
+						val[index++] = (Int32.Parse(tokens[2]) << 8) | Int32.Parse(tokens[3]);
+					}
+				}
+			}
+
+			if (index != val.Length)
+			{
+				Array.Copy(val, doubleColon, val, val.Length - (index - doubleColon), index - doubleColon);
+				for (int i = doubleColon; i != val.Length - (index - doubleColon); i++)
+				{
+					val[i] = 0;
+				}
+			}
+
+			return val;
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			// Explicitly tagged if DirectoryName
+			return new DerTaggedObject(tag == DirectoryName, tag, obj);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/GeneralNames.cs b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralNames.cs
new file mode 100644
index 0000000..6c5c8e6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralNames.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	public class GeneralNames
+		: Asn1Encodable
+	{
+		private readonly GeneralName[] names;
+
+		public static GeneralNames GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is GeneralNames)
+			{
+				return (GeneralNames) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new GeneralNames((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static GeneralNames GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		/// <summary>Construct a GeneralNames object containing one GeneralName.</summary>
+		/// <param name="name">The name to be contained.</param>
+		public GeneralNames(
+			GeneralName name)
+		{
+			names = new GeneralName[]{ name };
+		}
+
+        public GeneralNames(
+            GeneralName[] names)
+        {
+            this.names = (GeneralName[])names.Clone();
+        }
+
+		private GeneralNames(
+			Asn1Sequence seq)
+		{
+			this.names = new GeneralName[seq.Count];
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				names[i] = GeneralName.GetInstance(seq[i]);
+			}
+		}
+
+		public GeneralName[] GetNames()
+		{
+			return (GeneralName[]) names.Clone();
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * <pre>
+		 * GeneralNames ::= Sequence SIZE {1..MAX} OF GeneralName
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(names);
+		}
+
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			string sep = Platform.NewLine;
+
+			buf.Append("GeneralNames:");
+			buf.Append(sep);
+
+			foreach (GeneralName name in names)
+			{
+				buf.Append("    ");
+				buf.Append(name);
+				buf.Append(sep);
+			}
+
+			return buf.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/GeneralSubtree.cs b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralSubtree.cs
new file mode 100644
index 0000000..e918a02
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/GeneralSubtree.cs
@@ -0,0 +1,189 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * Class for containing a restriction object subtrees in NameConstraints. See
+	 * RFC 3280.
+	 *
+	 * <pre>
+	 *
+	 *       GeneralSubtree ::= SEQUENCE
+	 *       {
+	 *         baseName                    GeneralName,
+	 *         minimum         [0]     BaseDistance DEFAULT 0,
+	 *         maximum         [1]     BaseDistance OPTIONAL
+	 *       }
+	 * </pre>
+	 *
+	 * @see org.bouncycastle.asn1.x509.NameConstraints
+	 *
+	 */
+	public class GeneralSubtree
+		: Asn1Encodable
+	{
+		private readonly GeneralName	baseName;
+		private readonly DerInteger		minimum;
+		private readonly DerInteger		maximum;
+
+		private GeneralSubtree(
+			Asn1Sequence seq)
+		{
+			baseName = GeneralName.GetInstance(seq[0]);
+
+			switch (seq.Count)
+			{
+				case 1:
+					break;
+				case 2:
+				{
+					Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[1]);
+					switch (o.TagNo)
+					{
+						case 0:
+							minimum = DerInteger.GetInstance(o, false);
+							break;
+						case 1:
+							maximum = DerInteger.GetInstance(o, false);
+							break;
+						default:
+							throw new ArgumentException("Bad tag number: " + o.TagNo);
+					}
+					break;
+				}
+				case 3:
+				{
+					{
+						Asn1TaggedObject oMin = Asn1TaggedObject.GetInstance(seq[1]);
+						if (oMin.TagNo != 0)
+							throw new ArgumentException("Bad tag number for 'minimum': " + oMin.TagNo);
+						minimum = DerInteger.GetInstance(oMin, false);
+					}
+
+					{
+						Asn1TaggedObject oMax = Asn1TaggedObject.GetInstance(seq[2]);
+						if (oMax.TagNo != 1)
+							throw new ArgumentException("Bad tag number for 'maximum': " + oMax.TagNo);
+						maximum = DerInteger.GetInstance(oMax, false);
+					}
+
+					break;
+				}
+				default:
+					throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+		}
+
+		/**
+		 * Constructor from a given details.
+		 *
+		 * According RFC 3280, the minimum and maximum fields are not used with any
+		 * name forms, thus minimum MUST be zero, and maximum MUST be absent.
+		 * <p>
+		 * If minimum is <code>null</code>, zero is assumed, if
+		 * maximum is <code>null</code>, maximum is absent.</p>
+		 *
+		 * @param baseName
+		 *            A restriction.
+		 * @param minimum
+		 *            Minimum
+		 *
+		 * @param maximum
+		 *            Maximum
+		 */
+		public GeneralSubtree(
+			GeneralName	baseName,
+			BigInteger	minimum,
+			BigInteger	maximum)
+		{
+			this.baseName = baseName;
+			if (minimum != null)
+			{
+				this.minimum = new DerInteger(minimum);
+			}
+			if (maximum != null)
+			{
+				this.maximum = new DerInteger(maximum);
+			}
+		}
+
+		public GeneralSubtree(
+			GeneralName baseName)
+			: this(baseName, null, null)
+		{
+		}
+
+		public static GeneralSubtree GetInstance(
+			Asn1TaggedObject	o,
+			bool				isExplicit)
+		{
+			return new GeneralSubtree(Asn1Sequence.GetInstance(o, isExplicit));
+		}
+
+		public static GeneralSubtree GetInstance(
+			object obj)
+		{
+			if (obj == null)
+			{
+				return null;
+			}
+
+			if (obj is GeneralSubtree)
+			{
+				return (GeneralSubtree) obj;
+			}
+
+			return new GeneralSubtree(Asn1Sequence.GetInstance(obj));
+		}
+
+		public GeneralName Base
+		{
+			get { return baseName; }
+		}
+
+		public BigInteger Minimum
+		{
+			get { return minimum == null ? BigInteger.Zero : minimum.Value; }
+		}
+
+		public BigInteger Maximum
+		{
+			get { return maximum == null ? null : maximum.Value; }
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 *
+		 * Returns:
+		 *
+		 * <pre>
+		 *       GeneralSubtree ::= SEQUENCE
+		 *       {
+		 *         baseName                    GeneralName,
+		 *         minimum         [0]     BaseDistance DEFAULT 0,
+		 *         maximum         [1]     BaseDistance OPTIONAL
+		 *       }
+		 * </pre>
+		 *
+		 * @return a DERObject
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(baseName);
+
+			if (minimum != null && minimum.Value.SignValue != 0)
+			{
+				v.Add(new DerTaggedObject(false, 0, minimum));
+			}
+
+			if (maximum != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, maximum));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/Holder.cs b/BouncyCastle.AxCrypt/src/asn1/x509/Holder.cs
new file mode 100644
index 0000000..d04f1cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/Holder.cs
@@ -0,0 +1,257 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * The Holder object.
+	 * <p>
+	 * For an v2 attribute certificate this is:
+	 * 
+	 * <pre>
+	 *            Holder ::= SEQUENCE {
+	 *                  baseCertificateID   [0] IssuerSerial OPTIONAL,
+	 *                           -- the issuer and serial number of
+	 *                           -- the holder's Public Key Certificate
+	 *                  entityName          [1] GeneralNames OPTIONAL,
+	 *                           -- the name of the claimant or role
+	 *                  objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+	 *                           -- used to directly authenticate the holder,
+	 *                           -- for example, an executable
+	 *            }
+	 * </pre>
+	 * </p>
+	 * <p>
+	 * For an v1 attribute certificate this is:
+	 * 
+	 * <pre>
+	 *         subject CHOICE {
+	 *          baseCertificateID [0] IssuerSerial,
+	 *          -- associated with a Public Key Certificate
+	 *          subjectName [1] GeneralNames },
+	 *          -- associated with a name
+	 * </pre>
+	 * </p>
+	 */
+	public class Holder
+        : Asn1Encodable
+    {
+		internal readonly IssuerSerial		baseCertificateID;
+        internal readonly GeneralNames		entityName;
+        internal readonly ObjectDigestInfo	objectDigestInfo;
+		private readonly int version;
+
+		public static Holder GetInstance(
+            object obj)
+        {
+            if (obj is Holder)
+            {
+                return (Holder) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new Holder((Asn1Sequence) obj);
+            }
+
+			if (obj is Asn1TaggedObject)
+			{
+				return new Holder((Asn1TaggedObject) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor for a holder for an v1 attribute certificate.
+		 * 
+		 * @param tagObj The ASN.1 tagged holder object.
+		 */
+		public Holder(
+			Asn1TaggedObject tagObj)
+		{
+			switch (tagObj.TagNo)
+			{
+				case 0:
+					baseCertificateID = IssuerSerial.GetInstance(tagObj, false);
+					break;
+				case 1:
+					entityName = GeneralNames.GetInstance(tagObj, false);
+					break;
+				default:
+					throw new ArgumentException("unknown tag in Holder");
+			}
+
+			this.version = 0;
+		}
+
+		/**
+		 * Constructor for a holder for an v2 attribute certificate. *
+		 * 
+		 * @param seq The ASN.1 sequence.
+		 */
+		private Holder(
+            Asn1Sequence seq)
+        {
+			if (seq.Count > 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			for (int i = 0; i != seq.Count; i++)
+            {
+				Asn1TaggedObject tObj = Asn1TaggedObject.GetInstance(seq[i]);
+
+				switch (tObj.TagNo)
+                {
+                    case 0:
+                        baseCertificateID = IssuerSerial.GetInstance(tObj, false);
+                        break;
+                    case 1:
+                        entityName = GeneralNames.GetInstance(tObj, false);
+                        break;
+                    case 2:
+                        objectDigestInfo = ObjectDigestInfo.GetInstance(tObj, false);
+                        break;
+                    default:
+                        throw new ArgumentException("unknown tag in Holder");
+                }
+            }
+
+			this.version = 1;
+		}
+
+		public Holder(
+			IssuerSerial baseCertificateID)
+			: this(baseCertificateID, 1)
+		{
+		}
+
+		/**
+		 * Constructs a holder from a IssuerSerial.
+		 * @param baseCertificateID The IssuerSerial.
+		 * @param version The version of the attribute certificate. 
+		 */
+		public Holder(
+			IssuerSerial	baseCertificateID,
+			int				version)
+		{
+			this.baseCertificateID = baseCertificateID;
+			this.version = version;
+		}
+
+		/**
+		 * Returns 1 for v2 attribute certificates or 0 for v1 attribute
+		 * certificates. 
+		 * @return The version of the attribute certificate.
+		 */
+		public int Version
+		{
+			get { return version; }
+		}
+
+		/**
+		 * Constructs a holder with an entityName for v2 attribute certificates or
+		 * with a subjectName for v1 attribute certificates.
+		 * 
+		 * @param entityName The entity or subject name.
+		 */
+		public Holder(
+			GeneralNames entityName)
+			: this(entityName, 1)
+		{
+		}
+
+		/**
+		 * Constructs a holder with an entityName for v2 attribute certificates or
+		 * with a subjectName for v1 attribute certificates.
+		 * 
+		 * @param entityName The entity or subject name.
+		 * @param version The version of the attribute certificate. 
+		 */
+		public Holder(
+			GeneralNames	entityName,
+			int				version)
+		{
+			this.entityName = entityName;
+			this.version = version;
+		}
+
+		/**
+		 * Constructs a holder from an object digest info.
+		 * 
+		 * @param objectDigestInfo The object digest info object.
+		 */
+		public Holder(
+			ObjectDigestInfo objectDigestInfo)
+		{
+			this.objectDigestInfo = objectDigestInfo;
+			this.version = 1;
+		}
+
+		public IssuerSerial BaseCertificateID
+		{
+			get { return baseCertificateID; }
+		}
+
+		/**
+		 * Returns the entityName for an v2 attribute certificate or the subjectName
+		 * for an v1 attribute certificate.
+		 * 
+		 * @return The entityname or subjectname.
+		 */
+		public GeneralNames EntityName
+		{
+			get { return entityName; }
+		}
+
+		public ObjectDigestInfo ObjectDigestInfo
+		{
+			get { return objectDigestInfo; }
+		}
+
+		/**
+         * The Holder object.
+         * <pre>
+         *  Holder ::= Sequence {
+         *        baseCertificateID   [0] IssuerSerial OPTIONAL,
+         *                 -- the issuer and serial number of
+         *                 -- the holder's Public Key Certificate
+         *        entityName          [1] GeneralNames OPTIONAL,
+         *                 -- the name of the claimant or role
+         *        objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+         *                 -- used to directly authenticate the holder,
+         *                 -- for example, an executable
+         *  }
+         * </pre>
+         */
+		public override Asn1Object ToAsn1Object()
+		{
+			if (version == 1)
+			{
+				Asn1EncodableVector v = new Asn1EncodableVector();
+
+				if (baseCertificateID != null)
+				{
+					v.Add(new DerTaggedObject(false, 0, baseCertificateID));
+				}
+
+				if (entityName != null)
+				{
+					v.Add(new DerTaggedObject(false, 1, entityName));
+				}
+
+				if (objectDigestInfo != null)
+				{
+					v.Add(new DerTaggedObject(false, 2, objectDigestInfo));
+				}
+
+				return new DerSequence(v);
+			}
+
+			if (entityName != null)
+			{
+				return new DerTaggedObject(false, 1, entityName);
+			}
+
+			return new DerTaggedObject(false, 0, baseCertificateID);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/IetfAttrSyntax.cs b/BouncyCastle.AxCrypt/src/asn1/x509/IetfAttrSyntax.cs
new file mode 100644
index 0000000..e719865
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/IetfAttrSyntax.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Implementation of <code>IetfAttrSyntax</code> as specified by RFC3281.
+     */
+    public class IetfAttrSyntax
+        : Asn1Encodable
+    {
+        public const int ValueOctets	= 1;
+        public const int ValueOid		= 2;
+        public const int ValueUtf8		= 3;
+
+		internal readonly GeneralNames	policyAuthority;
+        internal readonly Asn1EncodableVector values = new Asn1EncodableVector();
+
+		internal int valueChoice = -1;
+
+		/**
+         *
+         */
+        public IetfAttrSyntax(
+			Asn1Sequence seq)
+        {
+            int i = 0;
+
+            if (seq[0] is Asn1TaggedObject)
+            {
+                policyAuthority = GeneralNames.GetInstance(((Asn1TaggedObject)seq[0]), false);
+                i++;
+            }
+            else if (seq.Count == 2)
+            { // VOMS fix
+                policyAuthority = GeneralNames.GetInstance(seq[0]);
+                i++;
+            }
+
+			if (!(seq[i] is Asn1Sequence))
+            {
+                throw new ArgumentException("Non-IetfAttrSyntax encoding");
+            }
+
+			seq = (Asn1Sequence) seq[i];
+
+			foreach (Asn1Object obj in seq)
+			{
+                int type;
+
+                if (obj is DerObjectIdentifier)
+                {
+                    type = ValueOid;
+                }
+                else if (obj is DerUtf8String)
+                {
+                    type = ValueUtf8;
+                }
+                else if (obj is DerOctetString)
+                {
+                    type = ValueOctets;
+                }
+                else
+                {
+                    throw new ArgumentException("Bad value type encoding IetfAttrSyntax");
+                }
+
+				if (valueChoice < 0)
+                {
+                    valueChoice = type;
+                }
+
+				if (type != valueChoice)
+                {
+                    throw new ArgumentException("Mix of value types in IetfAttrSyntax");
+                }
+
+				values.Add(obj);
+            }
+        }
+
+		public GeneralNames PolicyAuthority
+		{
+			get { return policyAuthority; }
+		}
+
+		public int ValueType
+		{
+			get { return valueChoice; }
+		}
+
+		public object[] GetValues()
+        {
+            if (this.ValueType == ValueOctets)
+            {
+                Asn1OctetString[] tmp = new Asn1OctetString[values.Count];
+
+				for (int i = 0; i != tmp.Length; i++)
+                {
+                    tmp[i] = (Asn1OctetString) values[i];
+                }
+
+				return tmp;
+            }
+
+			if (this.ValueType == ValueOid)
+            {
+                DerObjectIdentifier[] tmp = new DerObjectIdentifier[values.Count];
+
+                for (int i = 0; i != tmp.Length; i++)
+                {
+                    tmp[i] = (DerObjectIdentifier) values[i];
+                }
+
+				return tmp;
+            }
+
+			{
+				DerUtf8String[] tmp = new DerUtf8String[values.Count];
+
+				for (int i = 0; i != tmp.Length; i++)
+				{
+					tmp[i] = (DerUtf8String) values[i];
+				}
+
+				return tmp;
+			}
+        }
+
+		/**
+         *
+         * <pre>
+         *
+         *  IetfAttrSyntax ::= Sequence {
+         *    policyAuthority [0] GeneralNames OPTIONAL,
+         *    values Sequence OF CHOICE {
+         *      octets OCTET STRING,
+         *      oid OBJECT IDENTIFIER,
+         *      string UTF8String
+         *    }
+         *  }
+         *
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (policyAuthority != null)
+            {
+                v.Add(new DerTaggedObject(0, policyAuthority));
+            }
+
+			v.Add(new DerSequence(values));
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/IssuerSerial.cs b/BouncyCastle.AxCrypt/src/asn1/x509/IssuerSerial.cs
new file mode 100644
index 0000000..6a24e73
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/IssuerSerial.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class IssuerSerial
+        : Asn1Encodable
+    {
+        internal readonly GeneralNames	issuer;
+        internal readonly DerInteger	serial;
+        internal readonly DerBitString	issuerUid;
+
+		public static IssuerSerial GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is IssuerSerial)
+            {
+                return (IssuerSerial) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new IssuerSerial((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+        public static IssuerSerial GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		private IssuerSerial(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2 && seq.Count != 3)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			issuer = GeneralNames.GetInstance(seq[0]);
+			serial = DerInteger.GetInstance(seq[1]);
+
+			if (seq.Count == 3)
+            {
+				issuerUid = DerBitString.GetInstance(seq[2]);
+			}
+        }
+
+		public IssuerSerial(
+			GeneralNames	issuer,
+			DerInteger		serial)
+		{
+			this.issuer = issuer;
+			this.serial = serial;
+		}
+
+		public GeneralNames Issuer
+		{
+			get { return issuer; }
+		}
+
+		public DerInteger Serial
+		{
+			get { return serial; }
+		}
+
+		public DerBitString IssuerUid
+		{
+			get { return issuerUid; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  IssuerSerial  ::=  Sequence {
+         *       issuer         GeneralNames,
+         *       serial         CertificateSerialNumber,
+         *       issuerUid      UniqueIdentifier OPTIONAL
+         *  }
+         * </pre>
+         */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				issuer, serial);
+
+			if (issuerUid != null)
+			{
+				v.Add(issuerUid);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/IssuingDistributionPoint.cs b/BouncyCastle.AxCrypt/src/asn1/x509/IssuingDistributionPoint.cs
new file mode 100644
index 0000000..3af0d56
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/IssuingDistributionPoint.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * <pre>
+	 * IssuingDistributionPoint ::= SEQUENCE { 
+	 *   distributionPoint          [0] DistributionPointName OPTIONAL, 
+	 *   onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE, 
+	 *   onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE, 
+	 *   onlySomeReasons            [3] ReasonFlags OPTIONAL, 
+	 *   indirectCRL                [4] BOOLEAN DEFAULT FALSE,
+	 *   onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
+	 * </pre>
+	 */
+	public class IssuingDistributionPoint
+        : Asn1Encodable
+    {
+		private readonly DistributionPointName	_distributionPoint;
+		private readonly bool					_onlyContainsUserCerts;
+        private readonly bool					_onlyContainsCACerts;
+		private readonly ReasonFlags			_onlySomeReasons;
+		private readonly bool					_indirectCRL;
+        private readonly bool					_onlyContainsAttributeCerts;
+
+		private readonly Asn1Sequence seq;
+
+		public static IssuingDistributionPoint GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static IssuingDistributionPoint GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is IssuingDistributionPoint)
+            {
+                return (IssuingDistributionPoint) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new IssuingDistributionPoint((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor from given details.
+		 * 
+		 * @param distributionPoint
+		 *            May contain an URI as pointer to most current CRL.
+		 * @param onlyContainsUserCerts Covers revocation information for end certificates.
+		 * @param onlyContainsCACerts Covers revocation information for CA certificates.
+		 * 
+		 * @param onlySomeReasons
+		 *            Which revocation reasons does this point cover.
+		 * @param indirectCRL
+		 *            If <code>true</code> then the CRL contains revocation
+		 *            information about certificates ssued by other CAs.
+		 * @param onlyContainsAttributeCerts Covers revocation information for attribute certificates.
+		 */
+		public IssuingDistributionPoint(
+			DistributionPointName	distributionPoint,
+			bool					onlyContainsUserCerts,
+			bool					onlyContainsCACerts,
+			ReasonFlags				onlySomeReasons,
+			bool					indirectCRL,
+			bool					onlyContainsAttributeCerts)
+		{
+			this._distributionPoint = distributionPoint;
+			this._indirectCRL = indirectCRL;
+			this._onlyContainsAttributeCerts = onlyContainsAttributeCerts;
+			this._onlyContainsCACerts = onlyContainsCACerts;
+			this._onlyContainsUserCerts = onlyContainsUserCerts;
+			this._onlySomeReasons = onlySomeReasons;
+
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+			if (distributionPoint != null)
+			{	// CHOICE item so explicitly tagged
+				vec.Add(new DerTaggedObject(true, 0, distributionPoint));
+			}
+			if (onlyContainsUserCerts)
+			{
+				vec.Add(new DerTaggedObject(false, 1, DerBoolean.True));
+			}
+			if (onlyContainsCACerts)
+			{
+				vec.Add(new DerTaggedObject(false, 2, DerBoolean.True));
+			}
+			if (onlySomeReasons != null)
+			{
+				vec.Add(new DerTaggedObject(false, 3, onlySomeReasons));
+			}
+			if (indirectCRL)
+			{
+				vec.Add(new DerTaggedObject(false, 4, DerBoolean.True));
+			}
+			if (onlyContainsAttributeCerts)
+			{
+				vec.Add(new DerTaggedObject(false, 5, DerBoolean.True));
+			}
+
+			seq = new DerSequence(vec);
+		}
+
+		/**
+         * Constructor from Asn1Sequence
+         */
+        private IssuingDistributionPoint(
+            Asn1Sequence seq)
+        {
+            this.seq = seq;
+
+			for (int i = 0; i != seq.Count; i++)
+            {
+				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]);
+
+				switch (o.TagNo)
+                {
+					case 0:
+						// CHOICE so explicit
+						_distributionPoint = DistributionPointName.GetInstance(o, true);
+						break;
+					case 1:
+						_onlyContainsUserCerts = DerBoolean.GetInstance(o, false).IsTrue;
+						break;
+					case 2:
+						_onlyContainsCACerts = DerBoolean.GetInstance(o, false).IsTrue;
+						break;
+					case 3:
+						_onlySomeReasons = new ReasonFlags(ReasonFlags.GetInstance(o, false));
+						break;
+					case 4:
+						_indirectCRL = DerBoolean.GetInstance(o, false).IsTrue;
+						break;
+					case 5:
+						_onlyContainsAttributeCerts = DerBoolean.GetInstance(o, false).IsTrue;
+						break;
+					default:
+						throw new ArgumentException("unknown tag in IssuingDistributionPoint");
+                }
+            }
+        }
+
+		public bool OnlyContainsUserCerts
+		{
+			get { return _onlyContainsUserCerts; }
+		}
+
+		public bool OnlyContainsCACerts
+		{
+			get { return _onlyContainsCACerts; }
+		}
+
+		public bool IsIndirectCrl
+		{
+			get { return _indirectCRL; }
+		}
+
+		public bool OnlyContainsAttributeCerts
+		{
+			get { return _onlyContainsAttributeCerts; }
+		}
+
+		/**
+		 * @return Returns the distributionPoint.
+		 */
+		public DistributionPointName DistributionPoint
+		{
+			get { return _distributionPoint; }
+		}
+
+		/**
+		 * @return Returns the onlySomeReasons.
+		 */
+		public ReasonFlags OnlySomeReasons
+		{
+			get { return _onlySomeReasons; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+
+		public override string ToString()
+		{
+			string sep = Platform.NewLine;
+			StringBuilder buf = new StringBuilder();
+
+			buf.Append("IssuingDistributionPoint: [");
+			buf.Append(sep);
+			if (_distributionPoint != null)
+			{
+				appendObject(buf, sep, "distributionPoint", _distributionPoint.ToString());
+			}
+			if (_onlyContainsUserCerts)
+			{
+				appendObject(buf, sep, "onlyContainsUserCerts", _onlyContainsUserCerts.ToString());
+			}
+			if (_onlyContainsCACerts)
+			{
+				appendObject(buf, sep, "onlyContainsCACerts", _onlyContainsCACerts.ToString());
+			}
+			if (_onlySomeReasons != null)
+			{
+				appendObject(buf, sep, "onlySomeReasons", _onlySomeReasons.ToString());
+			}
+			if (_onlyContainsAttributeCerts)
+			{
+				appendObject(buf, sep, "onlyContainsAttributeCerts", _onlyContainsAttributeCerts.ToString());
+			}
+			if (_indirectCRL)
+			{
+				appendObject(buf, sep, "indirectCRL", _indirectCRL.ToString());
+			}
+			buf.Append("]");
+			buf.Append(sep);
+			return buf.ToString();
+		}
+
+		private void appendObject(
+			StringBuilder	buf,
+			string			sep,
+			string			name,
+			string			val)
+		{
+			string indent = "    ";
+
+			buf.Append(indent);
+			buf.Append(name);
+			buf.Append(":");
+			buf.Append(sep);
+			buf.Append(indent);
+			buf.Append(indent);
+			buf.Append(val);
+			buf.Append(sep);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/KeyPurposeId.cs b/BouncyCastle.AxCrypt/src/asn1/x509/KeyPurposeId.cs
new file mode 100644
index 0000000..4b48a9b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/KeyPurposeId.cs
@@ -0,0 +1,36 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The KeyPurposeID object.
+     * <pre>
+     *     KeyPurposeID ::= OBJECT IDENTIFIER
+     * </pre>
+     */
+    public sealed class KeyPurposeID
+        : DerObjectIdentifier
+    {
+        private const string IdKP = "1.3.6.1.5.5.7.3";
+
+		private KeyPurposeID(
+			string id)
+			: base(id)
+        {
+        }
+
+		public static readonly KeyPurposeID AnyExtendedKeyUsage = new KeyPurposeID(X509Extensions.ExtendedKeyUsage.Id + ".0");
+        public static readonly KeyPurposeID IdKPServerAuth = new KeyPurposeID(IdKP + ".1");
+        public static readonly KeyPurposeID IdKPClientAuth = new KeyPurposeID(IdKP + ".2");
+        public static readonly KeyPurposeID IdKPCodeSigning = new KeyPurposeID(IdKP + ".3");
+        public static readonly KeyPurposeID IdKPEmailProtection = new KeyPurposeID(IdKP + ".4");
+        public static readonly KeyPurposeID IdKPIpsecEndSystem = new KeyPurposeID(IdKP + ".5");
+        public static readonly KeyPurposeID IdKPIpsecTunnel = new KeyPurposeID(IdKP + ".6");
+        public static readonly KeyPurposeID IdKPIpsecUser = new KeyPurposeID(IdKP + ".7");
+        public static readonly KeyPurposeID IdKPTimeStamping = new KeyPurposeID(IdKP + ".8");
+        public static readonly KeyPurposeID IdKPOcspSigning = new KeyPurposeID(IdKP + ".9");
+
+		//
+        // microsoft key purpose ids
+        //
+        public static readonly KeyPurposeID IdKPSmartCardLogon = new KeyPurposeID("1.3.6.1.4.1.311.20.2.2");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/KeyUsage.cs b/BouncyCastle.AxCrypt/src/asn1/x509/KeyUsage.cs
new file mode 100644
index 0000000..fef04e8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/KeyUsage.cs
@@ -0,0 +1,79 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The KeyUsage object.
+     * <pre>
+     *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+     *
+     *    KeyUsage ::= BIT STRING {
+     *         digitalSignature        (0),
+     *         nonRepudiation          (1),
+     *         keyEncipherment         (2),
+     *         dataEncipherment        (3),
+     *         keyAgreement            (4),
+     *         keyCertSign             (5),
+     *         cRLSign                 (6),
+     *         encipherOnly            (7),
+     *         decipherOnly            (8) }
+     * </pre>
+     */
+    public class KeyUsage
+        : DerBitString
+    {
+        public const int DigitalSignature = (1 << 7);
+        public const int NonRepudiation   = (1 << 6);
+        public const int KeyEncipherment  = (1 << 5);
+        public const int DataEncipherment = (1 << 4);
+        public const int KeyAgreement     = (1 << 3);
+        public const int KeyCertSign      = (1 << 2);
+        public const int CrlSign          = (1 << 1);
+        public const int EncipherOnly     = (1 << 0);
+        public const int DecipherOnly     = (1 << 15);
+
+		public static new KeyUsage GetInstance(
+			object obj)
+		{
+			if (obj is KeyUsage)
+			{
+				return (KeyUsage)obj;
+			}
+
+			if (obj is X509Extension)
+			{
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+			}
+
+			return new KeyUsage(DerBitString.GetInstance(obj));
+		}
+
+		/**
+         * Basic constructor.
+         *
+         * @param usage - the bitwise OR of the Key Usage flags giving the
+         * allowed uses for the key.
+         * e.g. (KeyUsage.keyEncipherment | KeyUsage.dataEncipherment)
+         */
+        public KeyUsage(
+			int usage)
+			: base(GetBytes(usage), GetPadBits(usage))
+        {
+        }
+
+		private KeyUsage(
+			DerBitString usage)
+			: base(usage.GetBytes(), usage.PadBits)
+        {
+        }
+
+		public override string ToString()
+        {
+			byte[] data = GetBytes();
+            if (data.Length == 1)
+            {
+				return "KeyUsage: 0x" + (data[0] & 0xff).ToString("X");
+            }
+
+			return "KeyUsage: 0x" + ((data[1] & 0xff) << 8 | (data[0] & 0xff)).ToString("X");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/NameConstraints.cs b/BouncyCastle.AxCrypt/src/asn1/x509/NameConstraints.cs
new file mode 100644
index 0000000..8374ff6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/NameConstraints.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	public class NameConstraints
+		: Asn1Encodable
+	{
+		private Asn1Sequence permitted, excluded;
+
+		public static NameConstraints GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is NameConstraints)
+			{
+				return (NameConstraints) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new NameConstraints((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public NameConstraints(
+			Asn1Sequence seq)
+		{
+			foreach (Asn1TaggedObject o in seq)
+			{
+				switch (o.TagNo)
+				{
+					case 0:
+						permitted = Asn1Sequence.GetInstance(o, false);
+						break;
+					case 1:
+						excluded = Asn1Sequence.GetInstance(o, false);
+						break;
+				}
+			}
+		}
+
+#if !SILVERLIGHT
+        public NameConstraints(
+            ArrayList permitted,
+            ArrayList excluded)
+            : this((IList)permitted, (IList)excluded)
+        {
+        }
+#endif
+
+        /**
+		 * Constructor from a given details.
+		 *
+		 * <p>permitted and excluded are Vectors of GeneralSubtree objects.</p>
+		 *
+		 * @param permitted Permitted subtrees
+		 * @param excluded Excluded subtrees
+		 */
+		public NameConstraints(
+			IList   permitted,
+			IList   excluded)
+		{
+			if (permitted != null)
+			{
+				this.permitted = CreateSequence(permitted);
+			}
+
+			if (excluded != null)
+			{
+				this.excluded = CreateSequence(excluded);
+			}
+		}
+
+		private DerSequence CreateSequence(
+			IList subtrees)
+		{
+            GeneralSubtree[] gsts = new GeneralSubtree[subtrees.Count];
+            for (int i = 0; i < subtrees.Count; ++i)
+            {
+                gsts[i] = (GeneralSubtree)subtrees[i];
+            }
+            return new DerSequence(gsts);
+		}
+
+		public Asn1Sequence PermittedSubtrees
+		{
+			get { return permitted; }
+		}
+
+		public Asn1Sequence ExcludedSubtrees
+		{
+			get { return excluded; }
+		}
+
+		/*
+		 * NameConstraints ::= SEQUENCE { permittedSubtrees [0] GeneralSubtrees
+		 * OPTIONAL, excludedSubtrees [1] GeneralSubtrees OPTIONAL }
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (permitted != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, permitted));
+			}
+
+			if (excluded != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, excluded));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/NoticeReference.cs b/BouncyCastle.AxCrypt/src/asn1/x509/NoticeReference.cs
new file mode 100644
index 0000000..f0d3a7b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/NoticeReference.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * <code>NoticeReference</code> class, used in
+     * <code>CertificatePolicies</code> X509 V3 extensions
+     * (in policy qualifiers).
+     *
+     * <pre>
+     *  NoticeReference ::= Sequence {
+     *      organization     DisplayText,
+     *      noticeNumbers    Sequence OF Integer }
+     *
+     * </pre>
+     *
+     * @see PolicyQualifierInfo
+     * @see PolicyInformation
+     */
+    public class NoticeReference
+        : Asn1Encodable
+    {
+        private readonly DisplayText organization;
+        private readonly Asn1Sequence noticeNumbers;
+
+        private static Asn1EncodableVector ConvertVector(IList numbers)
+        {
+            Asn1EncodableVector av = new Asn1EncodableVector();
+
+            foreach (object o in numbers)
+            {
+                DerInteger di;
+
+                if (o is BigInteger)
+                {
+                    di = new DerInteger((BigInteger)o);
+                }
+                else if (o is int)
+                {
+                    di = new DerInteger((int)o);
+                }
+                else
+                {
+                    throw new ArgumentException();
+                }
+
+                av.Add(di);
+            }
+            return av;
+        }
+
+        /**
+         * Creates a new <code>NoticeReference</code> instance.
+         *
+         * @param organization a <code>String</code> value
+         * @param numbers a <code>Vector</code> value
+         */
+        public NoticeReference(string organization, IList numbers)
+            : this(organization, ConvertVector(numbers))
+        {
+        }
+
+        /**
+        * Creates a new <code>NoticeReference</code> instance.
+        *
+        * @param organization a <code>String</code> value
+        * @param noticeNumbers an <code>ASN1EncodableVector</code> value
+        */
+        public NoticeReference(string organization, Asn1EncodableVector noticeNumbers)
+            : this(new DisplayText(organization), noticeNumbers)
+        {
+        }
+
+        /**
+         * Creates a new <code>NoticeReference</code> instance.
+         *
+         * @param organization displayText
+         * @param noticeNumbers an <code>ASN1EncodableVector</code> value
+         */
+        public NoticeReference(DisplayText organization, Asn1EncodableVector noticeNumbers)
+        {
+            this.organization = organization;
+            this.noticeNumbers = new DerSequence(noticeNumbers);
+        }
+
+        /**
+         * Creates a new <code>NoticeReference</code> instance.
+         * <p>Useful for reconstructing a <code>NoticeReference</code>
+         * instance from its encodable/encoded form.</p>
+         *
+         * @param as an <code>Asn1Sequence</code> value obtained from either
+         * calling @{link ToAsn1Object()} for a <code>NoticeReference</code>
+         * instance or from parsing it from a Der-encoded stream.
+         */
+        private NoticeReference(Asn1Sequence seq)
+        {
+            if (seq.Count != 2)
+                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            organization = DisplayText.GetInstance(seq[0]);
+            noticeNumbers = Asn1Sequence.GetInstance(seq[1]);
+        }
+
+        public static NoticeReference GetInstance(object obj)
+        {
+            if (obj is NoticeReference)
+                return (NoticeReference)obj;
+            if (obj == null)
+                return null;
+            return new NoticeReference(Asn1Sequence.GetInstance(obj));
+        }
+
+        public virtual DisplayText Organization
+        {
+            get { return organization; }
+        }
+
+        public virtual DerInteger[] GetNoticeNumbers()
+        {
+            DerInteger[] tmp = new DerInteger[noticeNumbers.Count];
+
+            for (int i = 0; i != noticeNumbers.Count; ++i)
+            {
+                tmp[i] = DerInteger.GetInstance(noticeNumbers[i]);
+            }
+
+            return tmp;
+        }
+
+        /**
+         * Describe <code>ToAsn1Object</code> method here.
+         *
+         * @return a <code>Asn1Object</code> value
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(organization, noticeNumbers);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/ObjectDigestInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x509/ObjectDigestInfo.cs
new file mode 100644
index 0000000..6d5b9c6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/ObjectDigestInfo.cs
@@ -0,0 +1,177 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * ObjectDigestInfo ASN.1 structure used in v2 attribute certificates.
+	 * 
+	 * <pre>
+	 *  
+	 *    ObjectDigestInfo ::= SEQUENCE {
+	 *         digestedObjectType  ENUMERATED {
+	 *                 publicKey            (0),
+	 *                 publicKeyCert        (1),
+	 *                 otherObjectTypes     (2) },
+	 *                         -- otherObjectTypes MUST NOT
+	 *                         -- be used in this profile
+	 *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+	 *         digestAlgorithm     AlgorithmIdentifier,
+	 *         objectDigest        BIT STRING
+	 *    }
+	 *   
+	 * </pre>
+	 * 
+	 */
+	public class ObjectDigestInfo
+        : Asn1Encodable
+    {
+		/**
+		 * The public key is hashed.
+		 */
+		public const int PublicKey = 0;
+
+		/**
+		 * The public key certificate is hashed.
+		 */
+		public const int PublicKeyCert = 1;
+
+		/**
+		 * An other object is hashed.
+		 */
+		public const int OtherObjectDigest = 2;
+
+		internal readonly DerEnumerated			digestedObjectType;
+        internal readonly DerObjectIdentifier	otherObjectTypeID;
+        internal readonly AlgorithmIdentifier	digestAlgorithm;
+        internal readonly DerBitString			objectDigest;
+
+		public static ObjectDigestInfo GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is ObjectDigestInfo)
+            {
+                return (ObjectDigestInfo) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new ObjectDigestInfo((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		public static ObjectDigestInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				isExplicit)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+        }
+
+		/**
+		 * Constructor from given details.
+		 * <p>
+		 * If <code>digestedObjectType</code> is not {@link #publicKeyCert} or
+		 * {@link #publicKey} <code>otherObjectTypeID</code> must be given,
+		 * otherwise it is ignored.</p>
+		 * 
+		 * @param digestedObjectType The digest object type.
+		 * @param otherObjectTypeID The object type ID for
+		 *            <code>otherObjectDigest</code>.
+		 * @param digestAlgorithm The algorithm identifier for the hash.
+		 * @param objectDigest The hash value.
+		 */
+		public ObjectDigestInfo(
+			int					digestedObjectType,
+			string				otherObjectTypeID,
+			AlgorithmIdentifier	digestAlgorithm,
+			byte[]				objectDigest)
+		{
+			this.digestedObjectType = new DerEnumerated(digestedObjectType);
+
+			if (digestedObjectType == OtherObjectDigest)
+			{
+				this.otherObjectTypeID = new DerObjectIdentifier(otherObjectTypeID);
+			}
+
+			this.digestAlgorithm = digestAlgorithm; 
+
+			this.objectDigest = new DerBitString(objectDigest);
+		}
+
+		private ObjectDigestInfo(
+			Asn1Sequence seq)
+        {
+			if (seq.Count > 4 || seq.Count < 3)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			digestedObjectType = DerEnumerated.GetInstance(seq[0]);
+
+			int offset = 0;
+
+			if (seq.Count == 4)
+            {
+                otherObjectTypeID = DerObjectIdentifier.GetInstance(seq[1]);
+                offset++;
+            }
+
+			digestAlgorithm = AlgorithmIdentifier.GetInstance(seq[1 + offset]);
+			objectDigest = DerBitString.GetInstance(seq[2 + offset]);
+		}
+
+		public DerEnumerated DigestedObjectType
+		{
+			get { return digestedObjectType; }
+		}
+
+		public DerObjectIdentifier OtherObjectTypeID
+		{
+			get { return otherObjectTypeID; }
+		}
+
+		public AlgorithmIdentifier DigestAlgorithm
+		{
+			get { return digestAlgorithm; }
+		}
+
+		public DerBitString ObjectDigest
+		{
+			get { return objectDigest; }
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * 
+		 * <pre>
+		 *  
+		 *    ObjectDigestInfo ::= SEQUENCE {
+		 *         digestedObjectType  ENUMERATED {
+		 *                 publicKey            (0),
+		 *                 publicKeyCert        (1),
+		 *                 otherObjectTypes     (2) },
+		 *                         -- otherObjectTypes MUST NOT
+		 *                         -- be used in this profile
+		 *         otherObjectTypeID   OBJECT IDENTIFIER OPTIONAL,
+		 *         digestAlgorithm     AlgorithmIdentifier,
+		 *         objectDigest        BIT STRING
+		 *    }
+		 *   
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(digestedObjectType);
+
+			if (otherObjectTypeID != null)
+            {
+                v.Add(otherObjectTypeID);
+            }
+
+			v.Add(digestAlgorithm, objectDigest);
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/PolicyInformation.cs b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyInformation.cs
new file mode 100644
index 0000000..29d2450
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyInformation.cs
@@ -0,0 +1,80 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class PolicyInformation
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	policyIdentifier;
+        private readonly Asn1Sequence			policyQualifiers;
+
+		private PolicyInformation(
+            Asn1Sequence seq)
+        {
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			policyIdentifier = DerObjectIdentifier.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				policyQualifiers = Asn1Sequence.GetInstance(seq[1]);
+			}
+        }
+
+		public PolicyInformation(
+            DerObjectIdentifier policyIdentifier)
+        {
+            this.policyIdentifier = policyIdentifier;
+        }
+
+		public PolicyInformation(
+            DerObjectIdentifier	policyIdentifier,
+            Asn1Sequence		policyQualifiers)
+        {
+            this.policyIdentifier = policyIdentifier;
+            this.policyQualifiers = policyQualifiers;
+        }
+
+		public static PolicyInformation GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is PolicyInformation)
+            {
+                return (PolicyInformation) obj;
+            }
+
+			return new PolicyInformation(Asn1Sequence.GetInstance(obj));
+        }
+
+		public DerObjectIdentifier PolicyIdentifier
+		{
+			get { return policyIdentifier; }
+		}
+
+		public Asn1Sequence PolicyQualifiers
+		{
+			get { return policyQualifiers; }
+		}
+
+		/*
+         * PolicyInformation ::= Sequence {
+         *      policyIdentifier   CertPolicyId,
+         *      policyQualifiers   Sequence SIZE (1..MAX) OF
+         *              PolicyQualifierInfo OPTIONAL }
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(policyIdentifier);
+
+			if (policyQualifiers != null)
+            {
+                v.Add(policyQualifiers);
+            }
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/PolicyMappings.cs b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyMappings.cs
new file mode 100644
index 0000000..3ad3511
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyMappings.cs
@@ -0,0 +1,70 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * PolicyMappings V3 extension, described in RFC3280.
+	 * <pre>
+	 *    PolicyMappings ::= Sequence SIZE (1..MAX) OF Sequence {
+	 *      issuerDomainPolicy      CertPolicyId,
+	 *      subjectDomainPolicy     CertPolicyId }
+	 * </pre>
+	 *
+	 * @see <a href="http://www.faqs.org/rfc/rfc3280.txt">RFC 3280, section 4.2.1.6</a>
+	 */
+	public class PolicyMappings
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence seq;
+
+		/**
+		 * Creates a new <code>PolicyMappings</code> instance.
+		 *
+		 * @param seq an <code>Asn1Sequence</code> constructed as specified
+		 * in RFC 3280
+		 */
+		public PolicyMappings(
+			Asn1Sequence seq)
+		{
+			this.seq = seq;
+		}
+
+#if !SILVERLIGHT
+        public PolicyMappings(
+            Hashtable mappings)
+            : this((IDictionary)mappings)
+        {
+        }
+#endif
+
+        /**
+		 * Creates a new <code>PolicyMappings</code> instance.
+		 *
+		 * @param mappings a <code>HashMap</code> value that maps
+		 * <code>string</code> oids
+		 * to other <code>string</code> oids.
+		 */
+		public PolicyMappings(
+			IDictionary mappings)
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			foreach (string idp in mappings.Keys)
+			{
+				string sdp = (string) mappings[idp];
+
+				v.Add(
+					new DerSequence(
+						new DerObjectIdentifier(idp),
+						new DerObjectIdentifier(sdp)));
+			}
+
+			seq = new DerSequence(v);
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return seq;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierId.cs b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierId.cs
new file mode 100644
index 0000000..c858f08
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierId.cs
@@ -0,0 +1,28 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * PolicyQualifierId, used in the CertificatePolicies
+	 * X509V3 extension.
+	 *
+	 * <pre>
+	 *    id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
+	 *    id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
+	 *    id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
+	 *  PolicyQualifierId ::=
+	 *       OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
+	 * </pre>
+	 */
+	public sealed class PolicyQualifierID : DerObjectIdentifier
+	{
+		private const string IdQt = "1.3.6.1.5.5.7.2";
+
+		private PolicyQualifierID(
+			string id)
+			: base(id)
+		{
+		}
+
+		public static readonly PolicyQualifierID IdQtCps = new PolicyQualifierID(IdQt + ".1");
+		public static readonly PolicyQualifierID IdQtUnotice = new PolicyQualifierID(IdQt + ".2");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierInfo.cs
new file mode 100644
index 0000000..3cf6d7e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/PolicyQualifierInfo.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Policy qualifiers, used in the X509V3 CertificatePolicies
+     * extension.
+     *
+     * <pre>
+     *   PolicyQualifierInfo ::= Sequence {
+     *       policyQualifierId  PolicyQualifierId,
+     *       qualifier          ANY DEFINED BY policyQualifierId }
+     * </pre>
+     */
+    public class PolicyQualifierInfo
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier policyQualifierId;
+        private readonly Asn1Encodable qualifier;
+
+        /**
+         * Creates a new <code>PolicyQualifierInfo</code> instance.
+         *
+         * @param policyQualifierId a <code>PolicyQualifierId</code> value
+         * @param qualifier the qualifier, defined by the above field.
+         */
+        public PolicyQualifierInfo(
+            DerObjectIdentifier	policyQualifierId,
+            Asn1Encodable		qualifier)
+        {
+            this.policyQualifierId = policyQualifierId;
+            this.qualifier = qualifier;
+        }
+
+        /**
+         * Creates a new <code>PolicyQualifierInfo</code> containing a
+         * cPSuri qualifier.
+         *
+         * @param cps the CPS (certification practice statement) uri as a
+         * <code>string</code>.
+         */
+        public PolicyQualifierInfo(
+            string cps)
+        {
+            policyQualifierId = PolicyQualifierID.IdQtCps;
+            qualifier = new DerIA5String(cps);
+        }
+
+        /**
+         * Creates a new <code>PolicyQualifierInfo</code> instance.
+         *
+         * @param as <code>PolicyQualifierInfo</code> X509 structure
+         * encoded as an Asn1Sequence.
+         */
+        private PolicyQualifierInfo(
+            Asn1Sequence seq)
+        {
+            if (seq.Count != 2)
+                throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            policyQualifierId = DerObjectIdentifier.GetInstance(seq[0]);
+            qualifier = seq[1];
+        }
+
+        public static PolicyQualifierInfo GetInstance(
+            object obj)
+        {
+            if (obj is PolicyQualifierInfo)
+                return (PolicyQualifierInfo)obj;
+            if (obj == null)
+                return null;
+            return new PolicyQualifierInfo(Asn1Sequence.GetInstance(obj));
+        }
+
+        public virtual DerObjectIdentifier PolicyQualifierId
+        {
+            get { return policyQualifierId; }
+        }
+
+        public virtual Asn1Encodable Qualifier
+        {
+            get { return qualifier; }
+        }
+
+        /**
+         * Returns a Der-encodable representation of this instance.
+         *
+         * @return a <code>Asn1Object</code> value
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(policyQualifierId, qualifier);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/PrivateKeyUsagePeriod.cs b/BouncyCastle.AxCrypt/src/asn1/x509/PrivateKeyUsagePeriod.cs
new file mode 100644
index 0000000..ad2961e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/PrivateKeyUsagePeriod.cs
@@ -0,0 +1,82 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/// <remarks>
+	/// <pre>
+	/// PrivateKeyUsagePeriod ::= SEQUENCE
+	/// {
+	/// notBefore       [0]     GeneralizedTime OPTIONAL,
+	/// notAfter        [1]     GeneralizedTime OPTIONAL }
+	/// </pre>
+	/// </remarks>
+	public class PrivateKeyUsagePeriod
+		: Asn1Encodable
+	{
+		public static PrivateKeyUsagePeriod GetInstance(
+			object obj)
+		{
+			if (obj is PrivateKeyUsagePeriod)
+			{
+				return (PrivateKeyUsagePeriod) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new PrivateKeyUsagePeriod((Asn1Sequence) obj);
+			}
+
+			if (obj is X509Extension)
+			{
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+			}
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		private DerGeneralizedTime _notBefore, _notAfter;
+
+		private PrivateKeyUsagePeriod(
+			Asn1Sequence seq)
+		{
+			foreach (Asn1TaggedObject tObj in seq)
+			{
+				if (tObj.TagNo == 0)
+				{
+					_notBefore = DerGeneralizedTime.GetInstance(tObj, false);
+				}
+				else if (tObj.TagNo == 1)
+				{
+					_notAfter = DerGeneralizedTime.GetInstance(tObj, false);
+				}
+			}
+		}
+
+		public DerGeneralizedTime NotBefore
+		{
+			get { return _notBefore; }
+		}
+
+		public DerGeneralizedTime NotAfter
+		{
+			get { return _notAfter; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (_notBefore != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, _notBefore));
+			}
+
+			if (_notAfter != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, _notAfter));
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/RSAPublicKeyStructure.cs b/BouncyCastle.AxCrypt/src/asn1/x509/RSAPublicKeyStructure.cs
new file mode 100644
index 0000000..bdcba78
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/RSAPublicKeyStructure.cs
@@ -0,0 +1,92 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class RsaPublicKeyStructure
+        : Asn1Encodable
+    {
+        private BigInteger modulus;
+        private BigInteger publicExponent;
+
+		public static RsaPublicKeyStructure GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static RsaPublicKeyStructure GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is RsaPublicKeyStructure)
+            {
+                return (RsaPublicKeyStructure) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new RsaPublicKeyStructure((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("Invalid RsaPublicKeyStructure: " + obj.GetType().Name);
+        }
+
+		public RsaPublicKeyStructure(
+            BigInteger	modulus,
+            BigInteger	publicExponent)
+        {
+			if (modulus == null)
+				throw new ArgumentNullException("modulus");
+			if (publicExponent == null)
+				throw new ArgumentNullException("publicExponent");
+			if (modulus.SignValue <= 0)
+				throw new ArgumentException("Not a valid RSA modulus", "modulus");
+			if (publicExponent.SignValue <= 0)
+				throw new ArgumentException("Not a valid RSA public exponent", "publicExponent");
+
+            this.modulus = modulus;
+            this.publicExponent = publicExponent;
+        }
+
+		private RsaPublicKeyStructure(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			// Note: we are accepting technically incorrect (i.e. negative) values here
+			modulus = DerInteger.GetInstance(seq[0]).PositiveValue;
+			publicExponent = DerInteger.GetInstance(seq[1]).PositiveValue;
+		}
+
+		public BigInteger Modulus
+        {
+            get { return modulus; }
+        }
+
+		public BigInteger PublicExponent
+        {
+            get { return publicExponent; }
+        }
+
+		/**
+         * This outputs the key in Pkcs1v2 format.
+         * <pre>
+         *      RSAPublicKey ::= Sequence {
+         *                          modulus Integer, -- n
+         *                          publicExponent Integer, -- e
+         *                      }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(
+				new DerInteger(Modulus),
+				new DerInteger(PublicExponent));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/ReasonFlags.cs b/BouncyCastle.AxCrypt/src/asn1/x509/ReasonFlags.cs
new file mode 100644
index 0000000..f204c36
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/ReasonFlags.cs
@@ -0,0 +1,46 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The ReasonFlags object.
+     * <pre>
+     * ReasonFlags ::= BIT STRING {
+     *    unused(0),
+     *    keyCompromise(1),
+     *    cACompromise(2),
+     *    affiliationChanged(3),
+     *    superseded(4),
+     *    cessationOfOperation(5),
+     *    certficateHold(6)
+     * }
+     * </pre>
+     */
+    public class ReasonFlags
+        : DerBitString
+    {
+        public const int Unused                 = (1 << 7);
+        public const int KeyCompromise          = (1 << 6);
+        public const int CACompromise           = (1 << 5);
+        public const int AffiliationChanged     = (1 << 4);
+        public const int Superseded             = (1 << 3);
+        public const int CessationOfOperation   = (1 << 2);
+        public const int CertificateHold        = (1 << 1);
+        public const int PrivilegeWithdrawn     = (1 << 0);
+        public const int AACompromise           = (1 << 15);
+
+		/**
+         * @param reasons - the bitwise OR of the Key Reason flags giving the
+         * allowed uses for the key.
+         */
+        public ReasonFlags(
+            int reasons)
+             : base(GetBytes(reasons), GetPadBits(reasons))
+        {
+        }
+
+		public ReasonFlags(
+            DerBitString reasons)
+             : base(reasons.GetBytes(), reasons.PadBits)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/RoleSyntax.cs b/BouncyCastle.AxCrypt/src/asn1/x509/RoleSyntax.cs
new file mode 100644
index 0000000..48c3c6c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/RoleSyntax.cs
@@ -0,0 +1,230 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	* Implementation of the RoleSyntax object as specified by the RFC3281.
+	*
+	* <pre>
+	* RoleSyntax ::= SEQUENCE {
+	*                 roleAuthority  [0] GeneralNames OPTIONAL,
+	*                 roleName       [1] GeneralName
+	*           }
+	* </pre>
+	*/
+	public class RoleSyntax
+		: Asn1Encodable
+	{
+		private readonly GeneralNames	roleAuthority;
+		private readonly GeneralName	roleName;
+
+		/**
+		 * RoleSyntax factory method.
+		 * @param obj the object used to construct an instance of <code>
+		 * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
+		 * </code> or <code>Asn1Sequence</code>.
+		 * @return the instance of <code>RoleSyntax</code> built from the
+		 * supplied object.
+		 * @throws java.lang.ArgumentException if the object passed
+		 * to the factory is not an instance of <code>RoleSyntax</code> or
+		 * <code>Asn1Sequence</code>.
+		 */
+		public static RoleSyntax GetInstance(
+			object obj)
+		{
+			if (obj is RoleSyntax)
+				return (RoleSyntax)obj;
+
+			if (obj != null)
+				return new RoleSyntax(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		/**
+		* Constructor.
+		* @param roleAuthority the role authority of this RoleSyntax.
+		* @param roleName    the role name of this RoleSyntax.
+		*/
+		public RoleSyntax(
+			GeneralNames	roleAuthority,
+			GeneralName		roleName)
+		{
+			if (roleName == null
+				|| roleName.TagNo != GeneralName.UniformResourceIdentifier
+				|| ((IAsn1String) roleName.Name).GetString().Equals(""))
+			{
+				throw new ArgumentException("the role name MUST be non empty and MUST " +
+					"use the URI option of GeneralName");
+			}
+
+			this.roleAuthority = roleAuthority;
+			this.roleName = roleName;
+		}
+
+		/**
+		* Constructor. Invoking this constructor is the same as invoking
+		* <code>new RoleSyntax(null, roleName)</code>.
+		* @param roleName    the role name of this RoleSyntax.
+		*/
+		public RoleSyntax(
+			GeneralName roleName)
+			: this(null, roleName)
+		{
+		}
+
+		/**
+		* Utility constructor. Takes a <code>string</code> argument representing
+		* the role name, builds a <code>GeneralName</code> to hold the role name
+		* and calls the constructor that takes a <code>GeneralName</code>.
+		* @param roleName
+		*/
+		public RoleSyntax(
+			string roleName)
+			: this(new GeneralName(GeneralName.UniformResourceIdentifier,
+				(roleName == null)? "": roleName))
+		{
+		}
+
+		/**
+		* Constructor that builds an instance of <code>RoleSyntax</code> by
+		* extracting the encoded elements from the <code>Asn1Sequence</code>
+		* object supplied.
+		* @param seq    an instance of <code>Asn1Sequence</code> that holds
+		* the encoded elements used to build this <code>RoleSyntax</code>.
+		*/
+		private RoleSyntax(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1 || seq.Count > 2)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				Asn1TaggedObject taggedObject = Asn1TaggedObject.GetInstance(seq[i]);
+				switch (taggedObject.TagNo)
+				{
+					case 0:
+						roleAuthority = GeneralNames.GetInstance(taggedObject, false);
+						break;
+					case 1:
+						roleName = GeneralName.GetInstance(taggedObject, true);
+						break;
+					default:
+						throw new ArgumentException("Unknown tag in RoleSyntax");
+				}
+			}
+		}
+
+		/**
+		* Gets the role authority of this RoleSyntax.
+		* @return    an instance of <code>GeneralNames</code> holding the
+		* role authority of this RoleSyntax.
+		*/
+		public GeneralNames RoleAuthority
+		{
+			get { return this.roleAuthority; }
+		}
+
+		/**
+		* Gets the role name of this RoleSyntax.
+		* @return    an instance of <code>GeneralName</code> holding the
+		* role name of this RoleSyntax.
+		*/
+		public GeneralName RoleName
+		{
+			get { return this.roleName; }
+		}
+
+		/**
+		* Gets the role name as a <code>java.lang.string</code> object.
+		* @return    the role name of this RoleSyntax represented as a
+		* <code>string</code> object.
+		*/
+		public string GetRoleNameAsString()
+		{
+			return ((IAsn1String) this.roleName.Name).GetString();
+		}
+
+		/**
+		* Gets the role authority as a <code>string[]</code> object.
+		* @return the role authority of this RoleSyntax represented as a
+		* <code>string[]</code> array.
+		*/
+		public string[] GetRoleAuthorityAsString()
+		{
+			if (roleAuthority == null)
+			{
+				return new string[0];
+			}
+
+			GeneralName[] names = roleAuthority.GetNames();
+			string[] namesString = new string[names.Length];
+			for(int i = 0; i < names.Length; i++)
+			{
+				Asn1Encodable asn1Value = names[i].Name;
+				if (asn1Value is IAsn1String)
+				{
+					namesString[i] = ((IAsn1String) asn1Value).GetString();
+				}
+				else
+				{
+					namesString[i] = asn1Value.ToString();
+				}
+			}
+
+			return namesString;
+		}
+
+		/**
+		* Implementation of the method <code>ToAsn1Object</code> as
+		* required by the superclass <code>ASN1Encodable</code>.
+		*
+		* <pre>
+		* RoleSyntax ::= SEQUENCE {
+		*                 roleAuthority  [0] GeneralNames OPTIONAL,
+		*                 roleName       [1] GeneralName
+		*           }
+		* </pre>
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			if (this.roleAuthority != null)
+			{
+				v.Add(new DerTaggedObject(false, 0, roleAuthority));
+			}
+
+			v.Add(new DerTaggedObject(true, 1, roleName));
+
+			return new DerSequence(v);
+		}
+
+		public override string ToString()
+		{
+			StringBuilder buff = new StringBuilder("Name: " + this.GetRoleNameAsString() +
+				" - Auth: ");
+
+			if (this.roleAuthority == null || roleAuthority.GetNames().Length == 0)
+			{
+				buff.Append("N/A");
+			}
+			else
+			{
+				string[] names = this.GetRoleAuthorityAsString();
+				buff.Append('[').Append(names[0]);
+				for(int i = 1; i < names.Length; i++)
+				{
+					buff.Append(", ").Append(names[i]);
+				}
+				buff.Append(']');
+			}
+
+			return buff.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/SubjectDirectoryAttributes.cs b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectDirectoryAttributes.cs
new file mode 100644
index 0000000..fcb3029
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectDirectoryAttributes.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * This extension may contain further X.500 attributes of the subject. See also
+	 * RFC 3039.
+	 *
+	 * <pre>
+	 *     SubjectDirectoryAttributes ::= Attributes
+	 *     Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+	 *     Attribute ::= SEQUENCE
+	 *     {
+	 *       type AttributeType
+	 *       values SET OF AttributeValue
+	 *     }
+	 *
+	 *     AttributeType ::= OBJECT IDENTIFIER
+	 *     AttributeValue ::= ANY DEFINED BY AttributeType
+	 * </pre>
+	 *
+	 * @see org.bouncycastle.asn1.x509.X509Name for AttributeType ObjectIdentifiers.
+	 */
+	public class SubjectDirectoryAttributes
+		: Asn1Encodable
+	{
+		private readonly IList attributes;
+
+		public static SubjectDirectoryAttributes GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is SubjectDirectoryAttributes)
+			{
+				return (SubjectDirectoryAttributes) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new SubjectDirectoryAttributes((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor from Asn1Sequence.
+		 *
+		 * The sequence is of type SubjectDirectoryAttributes:
+		 *
+		 * <pre>
+		 *      SubjectDirectoryAttributes ::= Attributes
+		 *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+		 *      Attribute ::= SEQUENCE
+		 *      {
+		 *        type AttributeType
+		 *        values SET OF AttributeValue
+		 *      }
+		 *
+		 *      AttributeType ::= OBJECT IDENTIFIER
+		 *      AttributeValue ::= ANY DEFINED BY AttributeType
+		 * </pre>
+		 *
+		 * @param seq
+		 *            The ASN.1 sequence.
+		 */
+		private SubjectDirectoryAttributes(
+			Asn1Sequence seq)
+		{
+            this.attributes = Platform.CreateArrayList();
+            foreach (object o in seq)
+			{
+				Asn1Sequence s = Asn1Sequence.GetInstance(o);
+				attributes.Add(AttributeX509.GetInstance(s));
+			}
+		}
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public SubjectDirectoryAttributes(
+            ArrayList attributes)
+            : this((IList)attributes)
+        {
+        }
+#endif
+
+        /**
+		 * Constructor from an ArrayList of attributes.
+		 *
+		 * The ArrayList consists of attributes of type {@link Attribute Attribute}
+		 *
+		 * @param attributes The attributes.
+		 *
+		 */
+		public SubjectDirectoryAttributes(
+			IList attributes)
+		{
+            this.attributes = Platform.CreateArrayList(attributes);
+        }
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 *
+		 * Returns:
+		 *
+		 * <pre>
+		 *      SubjectDirectoryAttributes ::= Attributes
+		 *      Attributes ::= SEQUENCE SIZE (1..MAX) OF Attribute
+		 *      Attribute ::= SEQUENCE
+		 *      {
+		 *        type AttributeType
+		 *        values SET OF AttributeValue
+		 *      }
+		 *
+		 *      AttributeType ::= OBJECT IDENTIFIER
+		 *      AttributeValue ::= ANY DEFINED BY AttributeType
+		 * </pre>
+		 *
+		 * @return a DERObject
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+            AttributeX509[] v = new AttributeX509[attributes.Count];
+            for (int i = 0; i < attributes.Count; ++i)
+            {
+                v[i] = (AttributeX509)attributes[i];
+            }
+            return new DerSequence(v);
+		}
+
+        /**
+		 * @return Returns the attributes.
+		 */
+		public IEnumerable Attributes
+		{
+			get { return new EnumerableProxy(attributes); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/SubjectKeyIdentifier.cs b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectKeyIdentifier.cs
new file mode 100644
index 0000000..e640760
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectKeyIdentifier.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The SubjectKeyIdentifier object.
+     * <pre>
+     * SubjectKeyIdentifier::= OCTET STRING
+     * </pre>
+     */
+    public class SubjectKeyIdentifier
+        : Asn1Encodable
+    {
+        private readonly byte[] keyIdentifier;
+
+		public static SubjectKeyIdentifier GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1OctetString.GetInstance(obj, explicitly));
+        }
+
+		public static SubjectKeyIdentifier GetInstance(
+            object obj)
+        {
+            if (obj is SubjectKeyIdentifier)
+            {
+                return (SubjectKeyIdentifier) obj;
+            }
+
+			if (obj is SubjectPublicKeyInfo)
+            {
+                return new SubjectKeyIdentifier((SubjectPublicKeyInfo) obj);
+            }
+
+			if (obj is Asn1OctetString)
+            {
+                return new SubjectKeyIdentifier((Asn1OctetString) obj);
+            }
+
+			if (obj is X509Extension)
+			{
+				return GetInstance(X509Extension.ConvertValueToObject((X509Extension) obj));
+			}
+
+			throw new ArgumentException("Invalid SubjectKeyIdentifier: " + obj.GetType().Name);
+        }
+
+		public SubjectKeyIdentifier(
+            byte[] keyID)
+        {
+			if (keyID == null)
+				throw new ArgumentNullException("keyID");
+
+			this.keyIdentifier = keyID;
+        }
+
+		public SubjectKeyIdentifier(
+            Asn1OctetString keyID)
+        {
+            this.keyIdentifier = keyID.GetOctets();
+        }
+
+		/**
+		 * Calculates the keyIdentifier using a SHA1 hash over the BIT STRING
+		 * from SubjectPublicKeyInfo as defined in RFC3280.
+		 *
+		 * @param spki the subject public key info.
+		 */
+		public SubjectKeyIdentifier(
+			SubjectPublicKeyInfo spki)
+		{
+			this.keyIdentifier = GetDigest(spki);
+		}
+
+		public byte[] GetKeyIdentifier()
+		{
+			return keyIdentifier;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerOctetString(keyIdentifier);
+		}
+
+		/**
+		 * Return a RFC 3280 type 1 key identifier. As in:
+		 * <pre>
+		 * (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+		 * value of the BIT STRING subjectPublicKey (excluding the tag,
+		 * length, and number of unused bits).
+		 * </pre>
+		 * @param keyInfo the key info object containing the subjectPublicKey field.
+		 * @return the key identifier.
+		 */
+		public static SubjectKeyIdentifier CreateSha1KeyIdentifier(
+			SubjectPublicKeyInfo keyInfo)
+		{
+			return new SubjectKeyIdentifier(keyInfo);
+		}
+
+		/**
+		 * Return a RFC 3280 type 2 key identifier. As in:
+		 * <pre>
+		 * (2) The keyIdentifier is composed of a four bit type field with
+		 * the value 0100 followed by the least significant 60 bits of the
+		 * SHA-1 hash of the value of the BIT STRING subjectPublicKey.
+		 * </pre>
+		 * @param keyInfo the key info object containing the subjectPublicKey field.
+		 * @return the key identifier.
+		 */
+		public static SubjectKeyIdentifier CreateTruncatedSha1KeyIdentifier(
+			SubjectPublicKeyInfo keyInfo)
+		{
+			byte[] dig = GetDigest(keyInfo);
+			byte[] id = new byte[8];
+
+			Array.Copy(dig, dig.Length - 8, id, 0, id.Length);
+
+			id[0] &= 0x0f;
+			id[0] |= 0x40;
+
+			return new SubjectKeyIdentifier(id);
+		}
+
+		private static byte[] GetDigest(
+			SubjectPublicKeyInfo spki)
+		{
+            IDigest digest = new Sha1Digest();
+            byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			byte[] bytes = spki.PublicKeyData.GetBytes();
+            digest.BlockUpdate(bytes, 0, bytes.Length);
+            digest.DoFinal(resBuf, 0);
+            return resBuf;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/SubjectPublicKeyInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectPublicKeyInfo.cs
new file mode 100644
index 0000000..8ce4b27
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/SubjectPublicKeyInfo.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The object that contains the public key stored in a certficate.
+     * <p>
+     * The GetEncoded() method in the public keys in the JCE produces a DER
+     * encoded one of these.</p>
+     */
+    public class SubjectPublicKeyInfo
+        : Asn1Encodable
+    {
+        private readonly AlgorithmIdentifier	algID;
+        private readonly DerBitString			keyData;
+
+		public static SubjectPublicKeyInfo GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static SubjectPublicKeyInfo GetInstance(
+            object obj)
+        {
+            if (obj is SubjectPublicKeyInfo)
+                return (SubjectPublicKeyInfo) obj;
+
+			if (obj != null)
+				return new SubjectPublicKeyInfo(Asn1Sequence.GetInstance(obj));
+
+			return null;
+        }
+
+		public SubjectPublicKeyInfo(
+            AlgorithmIdentifier	algID,
+            Asn1Encodable		publicKey)
+        {
+            this.keyData = new DerBitString(publicKey);
+            this.algID = algID;
+        }
+
+		public SubjectPublicKeyInfo(
+            AlgorithmIdentifier	algID,
+            byte[]				publicKey)
+        {
+            this.keyData = new DerBitString(publicKey);
+            this.algID = algID;
+        }
+
+		private SubjectPublicKeyInfo(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            this.algID = AlgorithmIdentifier.GetInstance(seq[0]);
+			this.keyData = DerBitString.GetInstance(seq[1]);
+		}
+
+		public AlgorithmIdentifier AlgorithmID
+        {
+			get { return algID; }
+        }
+
+		/**
+         * for when the public key is an encoded object - if the bitstring
+         * can't be decoded this routine raises an IOException.
+         *
+         * @exception IOException - if the bit string doesn't represent a Der
+         * encoded object.
+         */
+        public Asn1Object GetPublicKey()
+        {
+			return Asn1Object.FromByteArray(keyData.GetBytes());
+        }
+
+		/**
+         * for when the public key is raw bits...
+         */
+        public DerBitString PublicKeyData
+        {
+			get { return keyData; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SubjectPublicKeyInfo ::= Sequence {
+         *                          algorithm AlgorithmIdentifier,
+         *                          publicKey BIT STRING }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(algID, keyData);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertList.cs b/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertList.cs
new file mode 100644
index 0000000..b5934a2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertList.cs
@@ -0,0 +1,274 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	public class CrlEntry
+		: Asn1Encodable
+	{
+		internal Asn1Sequence	seq;
+		internal DerInteger		userCertificate;
+		internal Time			revocationDate;
+		internal X509Extensions	crlEntryExtensions;
+
+		public CrlEntry(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 2 || seq.Count > 3)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			this.seq = seq;
+
+			userCertificate = DerInteger.GetInstance(seq[0]);
+			revocationDate = Time.GetInstance(seq[1]);
+		}
+
+		public DerInteger UserCertificate
+		{
+			get { return userCertificate; }
+		}
+
+		public Time RevocationDate
+		{
+			get { return revocationDate; }
+		}
+
+		public X509Extensions Extensions
+		{
+			get
+			{
+				if (crlEntryExtensions == null && seq.Count == 3)
+				{
+					crlEntryExtensions = X509Extensions.GetInstance(seq[2]);
+				}
+
+				return crlEntryExtensions;
+			}
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return seq;
+		}
+	}
+
+	/**
+     * PKIX RFC-2459 - TbsCertList object.
+     * <pre>
+     * TbsCertList  ::=  Sequence  {
+     *      version                 Version OPTIONAL,
+     *                                   -- if present, shall be v2
+     *      signature               AlgorithmIdentifier,
+     *      issuer                  Name,
+     *      thisUpdate              Time,
+     *      nextUpdate              Time OPTIONAL,
+     *      revokedCertificates     Sequence OF Sequence  {
+     *           userCertificate         CertificateSerialNumber,
+     *           revocationDate          Time,
+     *           crlEntryExtensions      Extensions OPTIONAL
+     *                                         -- if present, shall be v2
+     *                                }  OPTIONAL,
+     *      crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+     *                                         -- if present, shall be v2
+     *                                }
+     * </pre>
+     */
+    public class TbsCertificateList
+        : Asn1Encodable
+    {
+		private class RevokedCertificatesEnumeration
+			: IEnumerable
+		{
+			private readonly IEnumerable en;
+
+			internal RevokedCertificatesEnumeration(
+				IEnumerable en)
+			{
+				this.en = en;
+			}
+
+			public IEnumerator GetEnumerator()
+			{
+				return new RevokedCertificatesEnumerator(en.GetEnumerator());
+			}
+
+			private class RevokedCertificatesEnumerator
+				: IEnumerator
+			{
+				private readonly IEnumerator e;
+
+				internal RevokedCertificatesEnumerator(
+					IEnumerator e)
+				{
+					this.e = e;
+				}
+
+				public bool MoveNext()
+				{
+					return e.MoveNext();
+				}
+
+				public void Reset()
+				{
+					e.Reset();
+				}
+
+				public object Current
+				{
+					get { return new CrlEntry(Asn1Sequence.GetInstance(e.Current)); }
+				}
+			}
+		}
+
+		internal Asn1Sequence			seq;
+		internal DerInteger				version;
+        internal AlgorithmIdentifier	signature;
+        internal X509Name				issuer;
+        internal Time					thisUpdate;
+        internal Time					nextUpdate;
+		internal Asn1Sequence			revokedCertificates;
+		internal X509Extensions			crlExtensions;
+
+		public static TbsCertificateList GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static TbsCertificateList GetInstance(
+            object obj)
+        {
+            TbsCertificateList list = obj as TbsCertificateList;
+
+			if (obj == null || list != null)
+            {
+                return list;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new TbsCertificateList((Asn1Sequence) obj);
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+		internal TbsCertificateList(
+            Asn1Sequence seq)
+        {
+			if (seq.Count < 3 || seq.Count > 7)
+			{
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+			}
+
+			int seqPos = 0;
+
+			this.seq = seq;
+
+			if (seq[seqPos] is DerInteger)
+            {
+				version = DerInteger.GetInstance(seq[seqPos++]);
+			}
+            else
+            {
+                version = new DerInteger(0);
+            }
+
+			signature = AlgorithmIdentifier.GetInstance(seq[seqPos++]);
+            issuer = X509Name.GetInstance(seq[seqPos++]);
+            thisUpdate = Time.GetInstance(seq[seqPos++]);
+
+			if (seqPos < seq.Count
+                && (seq[seqPos] is DerUtcTime
+                   || seq[seqPos] is DerGeneralizedTime
+                   || seq[seqPos] is Time))
+            {
+                nextUpdate = Time.GetInstance(seq[seqPos++]);
+            }
+
+			if (seqPos < seq.Count
+                && !(seq[seqPos] is DerTaggedObject))
+            {
+				revokedCertificates = Asn1Sequence.GetInstance(seq[seqPos++]);
+			}
+
+			if (seqPos < seq.Count
+                && seq[seqPos] is DerTaggedObject)
+            {
+				crlExtensions = X509Extensions.GetInstance(seq[seqPos]);
+			}
+        }
+
+		public int Version
+        {
+            get { return version.Value.IntValue + 1; }
+        }
+
+		public DerInteger VersionNumber
+        {
+            get { return version; }
+        }
+
+		public AlgorithmIdentifier Signature
+        {
+            get { return signature; }
+        }
+
+		public X509Name Issuer
+        {
+            get { return issuer; }
+        }
+
+		public Time ThisUpdate
+        {
+            get { return thisUpdate; }
+        }
+
+		public Time NextUpdate
+        {
+            get { return nextUpdate; }
+        }
+
+		public CrlEntry[] GetRevokedCertificates()
+        {
+			if (revokedCertificates == null)
+			{
+				return new CrlEntry[0];
+			}
+
+			CrlEntry[] entries = new CrlEntry[revokedCertificates.Count];
+
+			for (int i = 0; i < entries.Length; i++)
+			{
+				entries[i] = new CrlEntry(Asn1Sequence.GetInstance(revokedCertificates[i]));
+			}
+
+			return entries;
+		}
+
+		public IEnumerable GetRevokedCertificateEnumeration()
+		{
+			if (revokedCertificates == null)
+			{
+				return EmptyEnumerable.Instance;
+			}
+
+			return new RevokedCertificatesEnumeration(revokedCertificates);
+		}
+
+		public X509Extensions Extensions
+        {
+            get { return crlExtensions; }
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertificateStructure.cs b/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertificateStructure.cs
new file mode 100644
index 0000000..fc7c39b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/TBSCertificateStructure.cs
@@ -0,0 +1,185 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The TbsCertificate object.
+     * <pre>
+     * TbsCertificate ::= Sequence {
+     *      version          [ 0 ]  Version DEFAULT v1(0),
+     *      serialNumber            CertificateSerialNumber,
+     *      signature               AlgorithmIdentifier,
+     *      issuer                  Name,
+     *      validity                Validity,
+     *      subject                 Name,
+     *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
+     *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+     *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+     *      extensions        [ 3 ] Extensions OPTIONAL
+     *      }
+     * </pre>
+     * <p>
+     * Note: issuerUniqueID and subjectUniqueID are both deprecated by the IETF. This class
+     * will parse them, but you really shouldn't be creating new ones.</p>
+     */
+	public class TbsCertificateStructure
+		: Asn1Encodable
+	{
+		internal Asn1Sequence            seq;
+		internal DerInteger              version;
+		internal DerInteger              serialNumber;
+		internal AlgorithmIdentifier     signature;
+		internal X509Name                issuer;
+		internal Time                    startDate, endDate;
+		internal X509Name                subject;
+		internal SubjectPublicKeyInfo    subjectPublicKeyInfo;
+		internal DerBitString            issuerUniqueID;
+		internal DerBitString            subjectUniqueID;
+		internal X509Extensions          extensions;
+
+		public static TbsCertificateStructure GetInstance(
+			Asn1TaggedObject	obj,
+			bool				explicitly)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+		}
+
+		public static TbsCertificateStructure GetInstance(
+			object obj)
+		{
+			if (obj is TbsCertificateStructure)
+				return (TbsCertificateStructure) obj;
+
+			if (obj != null)
+				return new TbsCertificateStructure(Asn1Sequence.GetInstance(obj));
+
+			return null;
+		}
+
+		internal TbsCertificateStructure(
+			Asn1Sequence seq)
+		{
+			int seqStart = 0;
+
+			this.seq = seq;
+
+			//
+			// some certficates don't include a version number - we assume v1
+			//
+			if (seq[0] is DerTaggedObject)
+			{
+				version = DerInteger.GetInstance((Asn1TaggedObject)seq[0], true);
+			}
+			else
+			{
+				seqStart = -1;          // field 0 is missing!
+				version = new DerInteger(0);
+			}
+
+			serialNumber = DerInteger.GetInstance(seq[seqStart + 1]);
+
+			signature = AlgorithmIdentifier.GetInstance(seq[seqStart + 2]);
+			issuer = X509Name.GetInstance(seq[seqStart + 3]);
+
+			//
+			// before and after dates
+			//
+			Asn1Sequence  dates = (Asn1Sequence)seq[seqStart + 4];
+
+			startDate = Time.GetInstance(dates[0]);
+			endDate = Time.GetInstance(dates[1]);
+
+			subject = X509Name.GetInstance(seq[seqStart + 5]);
+
+			//
+			// public key info.
+			//
+			subjectPublicKeyInfo = SubjectPublicKeyInfo.GetInstance(seq[seqStart + 6]);
+
+			for (int extras = seq.Count - (seqStart + 6) - 1; extras > 0; extras--)
+			{
+				DerTaggedObject extra = (DerTaggedObject) seq[seqStart + 6 + extras];
+
+				switch (extra.TagNo)
+				{
+					case 1:
+						issuerUniqueID = DerBitString.GetInstance(extra, false);
+						break;
+					case 2:
+						subjectUniqueID = DerBitString.GetInstance(extra, false);
+						break;
+					case 3:
+						extensions = X509Extensions.GetInstance(extra);
+						break;
+				}
+			}
+		}
+
+		public int Version
+		{
+			get { return version.Value.IntValue + 1; }
+		}
+
+		public DerInteger VersionNumber
+		{
+			get { return version; }
+		}
+
+		public DerInteger SerialNumber
+		{
+			get { return serialNumber; }
+		}
+
+		public AlgorithmIdentifier Signature
+		{
+			get { return signature; }
+		}
+
+		public X509Name Issuer
+		{
+			get { return issuer; }
+		}
+
+		public Time StartDate
+		{
+			get { return startDate; }
+		}
+
+		public Time EndDate
+		{
+			get { return endDate; }
+		}
+
+		public X509Name Subject
+		{
+			get { return subject; }
+		}
+
+		public SubjectPublicKeyInfo SubjectPublicKeyInfo
+		{
+			get { return subjectPublicKeyInfo; }
+		}
+
+		public DerBitString IssuerUniqueID
+		{
+			get { return issuerUniqueID; }
+        }
+
+		public DerBitString SubjectUniqueID
+        {
+			get { return subjectUniqueID; }
+        }
+
+		public X509Extensions Extensions
+        {
+			get { return extensions; }
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return seq;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/Target.cs b/BouncyCastle.AxCrypt/src/asn1/x509/Target.cs
new file mode 100644
index 0000000..309b28c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/Target.cs
@@ -0,0 +1,139 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * Target structure used in target information extension for attribute
+	 * certificates from RFC 3281.
+	 * 
+	 * <pre>
+	 *     Target  ::= CHOICE {
+	 *       targetName          [0] GeneralName,
+	 *       targetGroup         [1] GeneralName,
+	 *       targetCert          [2] TargetCert
+	 *     }
+	 * </pre>
+	 * 
+	 * <p>
+	 * The targetCert field is currently not supported and must not be used
+	 * according to RFC 3281.</p>
+	 */
+	public class Target
+		: Asn1Encodable, IAsn1Choice
+	{
+		public enum Choice
+		{
+			Name = 0,
+			Group = 1
+		};
+
+		private readonly GeneralName targetName;
+		private readonly GeneralName targetGroup;
+
+		/**
+		* Creates an instance of a Target from the given object.
+		* <p>
+		* <code>obj</code> can be a Target or a {@link Asn1TaggedObject}</p>
+		* 
+		* @param obj The object.
+		* @return A Target instance.
+		* @throws ArgumentException if the given object cannot be
+		*             interpreted as Target.
+		*/
+		public static Target GetInstance(
+			object obj)
+		{
+			if (obj is Target)
+			{
+				return (Target) obj;
+			}
+
+			if (obj is Asn1TaggedObject)
+			{
+				return new Target((Asn1TaggedObject) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor from Asn1TaggedObject.
+		 * 
+		 * @param tagObj The tagged object.
+		 * @throws ArgumentException if the encoding is wrong.
+		 */
+		private Target(
+			Asn1TaggedObject tagObj)
+		{
+			switch ((Choice) tagObj.TagNo)
+			{
+				case Choice.Name:	// GeneralName is already a choice so explicit
+					targetName = GeneralName.GetInstance(tagObj, true);
+					break;
+				case Choice.Group:
+					targetGroup = GeneralName.GetInstance(tagObj, true);
+					break;
+				default:
+					throw new ArgumentException("unknown tag: " + tagObj.TagNo);
+			}
+		}
+
+		/**
+		 * Constructor from given details.
+		 * <p>
+		 * Exactly one of the parameters must be not <code>null</code>.</p>
+		 *
+		 * @param type the choice type to apply to the name.
+		 * @param name the general name.
+		 * @throws ArgumentException if type is invalid.
+		 */
+		public Target(
+			Choice		type,
+			GeneralName	name)
+			: this(new DerTaggedObject((int) type, name))
+		{
+		}
+
+		/**
+		 * @return Returns the targetGroup.
+		 */
+		public virtual GeneralName TargetGroup
+		{
+			get { return targetGroup; }
+		}
+
+		/**
+		 * @return Returns the targetName.
+		 */
+		public virtual GeneralName TargetName
+		{
+			get { return targetName; }
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * 
+		 * Returns:
+		 * 
+		 * <pre>
+		 *     Target  ::= CHOICE {
+		 *       targetName          [0] GeneralName,
+		 *       targetGroup         [1] GeneralName,
+		 *       targetCert          [2] TargetCert
+		 *     }
+		 * </pre>
+		 * 
+		 * @return an Asn1Object
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			// GeneralName is a choice already so most be explicitly tagged
+			if (targetName != null)
+			{
+				return new DerTaggedObject(true, 0, targetName);
+			}
+
+			return new DerTaggedObject(true, 1, targetGroup);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/TargetInformation.cs b/BouncyCastle.AxCrypt/src/asn1/x509/TargetInformation.cs
new file mode 100644
index 0000000..75b18c0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/TargetInformation.cs
@@ -0,0 +1,123 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * Target information extension for attributes certificates according to RFC
+	 * 3281.
+	 * 
+	 * <pre>
+	 *           SEQUENCE OF Targets
+	 * </pre>
+	 * 
+	 */
+	public class TargetInformation
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence targets;
+
+		/**
+		 * Creates an instance of a TargetInformation from the given object.
+		 * <p>
+		 * <code>obj</code> can be a TargetInformation or a {@link Asn1Sequence}</p>
+		 * 
+		 * @param obj The object.
+		 * @return A TargetInformation instance.
+		 * @throws ArgumentException if the given object cannot be interpreted as TargetInformation.
+		 */
+		public static TargetInformation GetInstance(
+			object obj)
+		{
+			if (obj is TargetInformation)
+			{
+				return (TargetInformation) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new TargetInformation((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor from a Asn1Sequence.
+		 * 
+		 * @param seq The Asn1Sequence.
+		 * @throws ArgumentException if the sequence does not contain
+		 *             correctly encoded Targets elements.
+		 */
+		private TargetInformation(
+			Asn1Sequence targets)
+		{
+			this.targets = targets;
+		}
+
+		/**
+		 * Returns the targets in this target information extension.
+		 * <p>
+		 * The ArrayList is cloned before it is returned.</p>
+		 * 
+		 * @return Returns the targets.
+		 */
+		public virtual Targets[] GetTargetsObjects()
+		{
+			Targets[] result = new Targets[targets.Count];
+
+			for (int i = 0; i < targets.Count; ++i)
+			{
+				result[i] = Targets.GetInstance(targets[i]);
+			}
+
+			return result;
+		}
+
+		/**
+		 * Constructs a target information from a single targets element. 
+		 * According to RFC 3281 only one targets element must be produced.
+		 * 
+		 * @param targets A Targets instance.
+		 */
+		public TargetInformation(
+			Targets targets)
+		{
+			this.targets = new DerSequence(targets);
+		}
+
+		/**
+		 * According to RFC 3281 only one targets element must be produced. If
+		 * multiple targets are given they must be merged in
+		 * into one targets element.
+		 *
+		 * @param targets An array with {@link Targets}.
+		 */
+		public TargetInformation(
+			Target[] targets)
+			: this(new Targets(targets))
+		{
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * 
+		 * Returns:
+		 * 
+		 * <pre>
+		 *          SEQUENCE OF Targets
+		 * </pre>
+		 * 
+		 * <p>
+		 * According to RFC 3281 only one targets element must be produced. If
+		 * multiple targets are given in the constructor they are merged into one
+		 * targets element. If this was produced from a
+		 * {@link Org.BouncyCastle.Asn1.Asn1Sequence} the encoding is kept.</p>
+		 * 
+		 * @return an Asn1Object
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return targets;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/Targets.cs b/BouncyCastle.AxCrypt/src/asn1/x509/Targets.cs
new file mode 100644
index 0000000..3e436d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/Targets.cs
@@ -0,0 +1,121 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/**
+	 * Targets structure used in target information extension for attribute
+	 * certificates from RFC 3281.
+	 * 
+	 * <pre>
+	 *            Targets ::= SEQUENCE OF Target
+	 *           
+	 *            Target  ::= CHOICE {
+	 *              targetName          [0] GeneralName,
+	 *              targetGroup         [1] GeneralName,
+	 *              targetCert          [2] TargetCert
+	 *            }
+	 *           
+	 *            TargetCert  ::= SEQUENCE {
+	 *              targetCertificate    IssuerSerial,
+	 *              targetName           GeneralName OPTIONAL,
+	 *              certDigestInfo       ObjectDigestInfo OPTIONAL
+	 *            }
+	 * </pre>
+	 * 
+	 * @see org.bouncycastle.asn1.x509.Target
+	 * @see org.bouncycastle.asn1.x509.TargetInformation
+	 */
+	public class Targets
+		: Asn1Encodable
+	{
+		private readonly Asn1Sequence targets;
+
+		/**
+		 * Creates an instance of a Targets from the given object.
+		 * <p>
+		 * <code>obj</code> can be a Targets or a {@link Asn1Sequence}</p>
+		 * 
+		 * @param obj The object.
+		 * @return A Targets instance.
+		 * @throws ArgumentException if the given object cannot be interpreted as Target.
+		 */
+		public static Targets GetInstance(
+			object obj)
+		{
+			if (obj is Targets)
+			{
+				return (Targets) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new Targets((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		 * Constructor from Asn1Sequence.
+		 * 
+		 * @param targets The ASN.1 SEQUENCE.
+		 * @throws ArgumentException if the contents of the sequence are
+		 *             invalid.
+		 */
+		private Targets(
+			Asn1Sequence targets)
+		{
+			this.targets = targets;
+		}
+
+		/**
+		 * Constructor from given targets.
+		 * <p>
+		 * The ArrayList is copied.</p>
+		 * 
+		 * @param targets An <code>ArrayList</code> of {@link Target}s.
+		 * @see Target
+		 * @throws ArgumentException if the ArrayList contains not only Targets.
+		 */
+		public Targets(
+			Target[] targets)
+		{
+			this.targets = new DerSequence(targets);
+		}
+
+		/**
+		 * Returns the targets in an <code>ArrayList</code>.
+		 * <p>
+		 * The ArrayList is cloned before it is returned.</p>
+		 * 
+		 * @return Returns the targets.
+		 */
+		public virtual Target[] GetTargets()
+		{
+			Target[] result = new Target[targets.Count];
+
+			for (int i = 0; i < targets.Count; ++i)
+			{
+				result[i] = Target.GetInstance(targets[i]);
+			}
+
+			return result;
+		}
+
+		/**
+		 * Produce an object suitable for an Asn1OutputStream.
+		 * 
+		 * Returns:
+		 * 
+		 * <pre>
+		 *            Targets ::= SEQUENCE OF Target
+		 * </pre>
+		 * 
+		 * @return an Asn1Object
+		 */
+		public override Asn1Object ToAsn1Object()
+		{
+			return targets;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/Time.cs b/BouncyCastle.AxCrypt/src/asn1/x509/Time.cs
new file mode 100644
index 0000000..04b4a5a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/Time.cs
@@ -0,0 +1,120 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class Time
+        : Asn1Encodable, IAsn1Choice
+    {
+        internal Asn1Object time;
+
+        public static Time GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(obj.GetObject());
+        }
+
+        public Time(
+            Asn1Object time)
+        {
+            if (time == null)
+                throw new ArgumentNullException("time");
+
+            if (!(time is DerUtcTime) && !(time is DerGeneralizedTime))
+            {
+                throw new ArgumentException("unknown object passed to Time");
+            }
+
+            this.time = time;
+        }
+
+        /**
+         * creates a time object from a given date - if the date is between 1950
+         * and 2049 a UTCTime object is Generated, otherwise a GeneralizedTime
+         * is used.
+         */
+        public Time(
+            DateTime date)
+        {
+            string d = date.ToUniversalTime().ToString("yyyyMMddHHmmss") + "Z";
+
+            int year = Int32.Parse(d.Substring(0, 4));
+
+            if (year < 1950 || year > 2049)
+            {
+                time = new DerGeneralizedTime(d);
+            }
+            else
+            {
+                time = new DerUtcTime(d.Substring(2));
+            }
+        }
+
+        public static Time GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Time)
+                return (Time) obj;
+
+            if (obj is DerUtcTime)
+                return new Time((DerUtcTime) obj);
+
+            if (obj is DerGeneralizedTime)
+                return new Time((DerGeneralizedTime) obj);
+
+            throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+        }
+
+        public string GetTime()
+        {
+            if (time is DerUtcTime)
+            {
+                return ((DerUtcTime) time).AdjustedTimeString;
+            }
+
+            return ((DerGeneralizedTime) time).GetTime();
+        }
+
+        /// <summary>
+        /// Return our time as DateTime.
+        /// </summary>
+        /// <returns>A date time.</returns>
+        public DateTime ToDateTime()
+        {
+            try
+            {
+                if (time is DerUtcTime)
+                {
+                    return ((DerUtcTime)time).ToAdjustedDateTime();
+                }
+                else
+                {
+                    return ((DerGeneralizedTime)time).ToDateTime();
+                }
+            }
+            catch (FormatException e)
+            {
+                // this should never happen
+                throw new InvalidOperationException("invalid date string: " + e.Message);
+            }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Time ::= CHOICE {
+         *             utcTime        UTCTime,
+         *             generalTime    GeneralizedTime }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return time;
+        }
+
+        public override string ToString()
+        {
+            return GetTime();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/UserNotice.cs b/BouncyCastle.AxCrypt/src/asn1/x509/UserNotice.cs
new file mode 100644
index 0000000..5938f7c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/UserNotice.cs
@@ -0,0 +1,122 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * <code>UserNotice</code> class, used in
+     * <code>CertificatePolicies</code> X509 extensions (in policy
+     * qualifiers).
+     * <pre>
+     * UserNotice ::= Sequence {
+     *      noticeRef        NoticeReference OPTIONAL,
+     *      explicitText     DisplayText OPTIONAL}
+     *
+     * </pre>
+     *
+     * @see PolicyQualifierId
+     * @see PolicyInformation
+     */
+    public class UserNotice
+        : Asn1Encodable
+    {
+        private readonly NoticeReference noticeRef;
+        private readonly DisplayText explicitText;
+
+        /**
+         * Creates a new <code>UserNotice</code> instance.
+         *
+         * @param noticeRef a <code>NoticeReference</code> value
+         * @param explicitText a <code>DisplayText</code> value
+         */
+        public UserNotice(
+            NoticeReference	noticeRef,
+            DisplayText		explicitText)
+        {
+            this.noticeRef = noticeRef;
+            this.explicitText = explicitText;
+        }
+
+        /**
+         * Creates a new <code>UserNotice</code> instance.
+         *
+         * @param noticeRef a <code>NoticeReference</code> value
+         * @param str the explicitText field as a string.
+         */
+        public UserNotice(
+            NoticeReference	noticeRef,
+            string			str)
+            : this(noticeRef, new DisplayText(str))
+        {
+        }
+
+        /**
+         * Creates a new <code>UserNotice</code> instance.
+         * <p>Useful from reconstructing a <code>UserNotice</code> instance
+         * from its encodable/encoded form.
+         *
+         * @param as an <code>ASN1Sequence</code> value obtained from either
+         * calling @{link toASN1Object()} for a <code>UserNotice</code>
+         * instance or from parsing it from a DER-encoded stream.</p>
+         */
+        public UserNotice(
+            Asn1Sequence seq)
+        {
+            if (seq.Count == 2)
+            {
+                noticeRef = NoticeReference.GetInstance(seq[0]);
+                explicitText = DisplayText.GetInstance(seq[1]);
+            }
+            else if (seq.Count == 1)
+            {
+                if (seq[0].ToAsn1Object() is Asn1Sequence)
+                {
+                    noticeRef = NoticeReference.GetInstance(seq[0]);
+                }
+                else
+                {
+                    explicitText = DisplayText.GetInstance(seq[0]);
+                }
+            }
+            else
+            {
+                throw new ArgumentException("Bad sequence size: " + seq.Count);
+            }
+        }
+
+        public static UserNotice GetInstance(object obj)
+        {
+            if (obj is UserNotice)
+                return (UserNotice)obj;
+            if (obj == null)
+                return null;
+            return new UserNotice(Asn1Sequence.GetInstance(obj));
+        }
+
+        public virtual NoticeReference NoticeRef
+        {
+            get { return noticeRef; }
+        }
+
+        public virtual DisplayText ExplicitText
+        {
+            get { return explicitText; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector av = new Asn1EncodableVector();
+
+            if (noticeRef != null)
+            {
+                av.Add(noticeRef);
+            }
+
+            if (explicitText != null)
+            {
+                av.Add(explicitText);
+            }
+
+            return new DerSequence(av);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/V1TBSCertificateGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/x509/V1TBSCertificateGenerator.cs
new file mode 100644
index 0000000..20b525a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/V1TBSCertificateGenerator.cs
@@ -0,0 +1,108 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Generator for Version 1 TbsCertificateStructures.
+     * <pre>
+     * TbsCertificate ::= Sequence {
+     *      version          [ 0 ]  Version DEFAULT v1(0),
+     *      serialNumber            CertificateSerialNumber,
+     *      signature               AlgorithmIdentifier,
+     *      issuer                  Name,
+     *      validity                Validity,
+     *      subject                 Name,
+     *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
+     *      }
+     * </pre>
+     *
+     */
+    public class V1TbsCertificateGenerator
+    {
+        internal DerTaggedObject		version = new DerTaggedObject(0, new DerInteger(0));
+        internal DerInteger				serialNumber;
+        internal AlgorithmIdentifier	signature;
+        internal X509Name				issuer;
+        internal Time					startDate, endDate;
+        internal X509Name				subject;
+        internal SubjectPublicKeyInfo	subjectPublicKeyInfo;
+
+		public V1TbsCertificateGenerator()
+        {
+        }
+
+		public void SetSerialNumber(
+            DerInteger serialNumber)
+        {
+            this.serialNumber = serialNumber;
+        }
+
+		public void SetSignature(
+            AlgorithmIdentifier signature)
+        {
+            this.signature = signature;
+        }
+
+		public void SetIssuer(
+            X509Name issuer)
+        {
+            this.issuer = issuer;
+        }
+
+		public void SetStartDate(
+            Time startDate)
+        {
+            this.startDate = startDate;
+        }
+
+		public void SetStartDate(
+            DerUtcTime startDate)
+        {
+            this.startDate = new Time(startDate);
+        }
+
+		public void SetEndDate(
+            Time endDate)
+        {
+            this.endDate = endDate;
+        }
+
+		public void SetEndDate(
+            DerUtcTime endDate)
+        {
+            this.endDate = new Time(endDate);
+        }
+
+		public void SetSubject(
+            X509Name subject)
+        {
+            this.subject = subject;
+        }
+
+		public void SetSubjectPublicKeyInfo(
+            SubjectPublicKeyInfo pubKeyInfo)
+        {
+            this.subjectPublicKeyInfo = pubKeyInfo;
+        }
+
+		public TbsCertificateStructure GenerateTbsCertificate()
+        {
+            if ((serialNumber == null) || (signature == null)
+                || (issuer == null) || (startDate == null) || (endDate == null)
+                || (subject == null) || (subjectPublicKeyInfo == null))
+            {
+                throw new InvalidOperationException("not all mandatory fields set in V1 TBScertificate generator");
+            }
+
+			return new TbsCertificateStructure(
+				new DerSequence(
+					//version, - not required as default value
+					serialNumber,
+					signature,
+					issuer,
+					new DerSequence(startDate, endDate), // before and after dates
+					subject,
+					subjectPublicKeyInfo));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs
new file mode 100644
index 0000000..02580b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/V2AttributeCertificateInfoGenerator.cs
@@ -0,0 +1,137 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Generator for Version 2 AttributeCertificateInfo
+     * <pre>
+     * AttributeCertificateInfo ::= Sequence {
+     *       version              AttCertVersion -- version is v2,
+     *       holder               Holder,
+     *       issuer               AttCertIssuer,
+     *       signature            AlgorithmIdentifier,
+     *       serialNumber         CertificateSerialNumber,
+     *       attrCertValidityPeriod   AttCertValidityPeriod,
+     *       attributes           Sequence OF Attr,
+     *       issuerUniqueID       UniqueIdentifier OPTIONAL,
+     *       extensions           Extensions OPTIONAL
+     * }
+     * </pre>
+     *
+     */
+    public class V2AttributeCertificateInfoGenerator
+    {
+        internal DerInteger				version;
+        internal Holder					holder;
+        internal AttCertIssuer			issuer;
+        internal AlgorithmIdentifier	signature;
+        internal DerInteger				serialNumber;
+//        internal AttCertValidityPeriod	attrCertValidityPeriod;
+        internal Asn1EncodableVector	attributes;
+        internal DerBitString			issuerUniqueID;
+        internal X509Extensions			extensions;
+        internal DerGeneralizedTime		startDate, endDate;
+
+		public V2AttributeCertificateInfoGenerator()
+        {
+            this.version = new DerInteger(1);
+            attributes = new Asn1EncodableVector();
+        }
+
+		public void SetHolder(
+			Holder holder)
+        {
+            this.holder = holder;
+        }
+
+		public void AddAttribute(
+			string			oid,
+			Asn1Encodable	value)
+        {
+            attributes.Add(new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value)));
+        }
+
+		/**
+         * @param attribute
+         */
+        public void AddAttribute(AttributeX509 attribute)
+        {
+            attributes.Add(attribute);
+        }
+
+		public void SetSerialNumber(
+            DerInteger serialNumber)
+        {
+            this.serialNumber = serialNumber;
+        }
+
+		public void SetSignature(
+            AlgorithmIdentifier signature)
+        {
+            this.signature = signature;
+        }
+
+		public void SetIssuer(
+            AttCertIssuer issuer)
+        {
+            this.issuer = issuer;
+        }
+
+		public void SetStartDate(
+            DerGeneralizedTime startDate)
+        {
+            this.startDate = startDate;
+        }
+
+		public void SetEndDate(
+            DerGeneralizedTime endDate)
+        {
+            this.endDate = endDate;
+        }
+
+		public void SetIssuerUniqueID(
+            DerBitString issuerUniqueID)
+        {
+            this.issuerUniqueID = issuerUniqueID;
+        }
+
+		public void SetExtensions(
+            X509Extensions extensions)
+        {
+            this.extensions = extensions;
+        }
+
+		public AttributeCertificateInfo GenerateAttributeCertificateInfo()
+        {
+            if ((serialNumber == null) || (signature == null)
+                || (issuer == null) || (startDate == null) || (endDate == null)
+                || (holder == null) || (attributes == null))
+            {
+                throw new InvalidOperationException("not all mandatory fields set in V2 AttributeCertificateInfo generator");
+            }
+
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				version, holder, issuer, signature, serialNumber);
+
+			//
+            // before and after dates => AttCertValidityPeriod
+            //
+            v.Add(new AttCertValidityPeriod(startDate, endDate));
+
+			// Attributes
+            v.Add(new DerSequence(attributes));
+
+			if (issuerUniqueID != null)
+            {
+                v.Add(issuerUniqueID);
+            }
+
+			if (extensions != null)
+            {
+                v.Add(extensions);
+            }
+
+			return AttributeCertificateInfo.GetInstance(new DerSequence(v));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/V2Form.cs b/BouncyCastle.AxCrypt/src/asn1/x509/V2Form.cs
new file mode 100644
index 0000000..2c6e54a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/V2Form.cs
@@ -0,0 +1,137 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class V2Form
+        : Asn1Encodable
+    {
+        internal GeneralNames        issuerName;
+        internal IssuerSerial        baseCertificateID;
+        internal ObjectDigestInfo    objectDigestInfo;
+
+        public static V2Form GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static V2Form GetInstance(object obj)
+        {
+            if (obj is V2Form)
+                return (V2Form)obj;
+            if (obj != null)
+                return new V2Form(Asn1Sequence.GetInstance(obj));
+            return null;
+        }
+
+        public V2Form(GeneralNames issuerName)
+            : this(issuerName, null, null)
+        {
+        }
+
+        public V2Form(GeneralNames issuerName, IssuerSerial baseCertificateID)
+            : this(issuerName, baseCertificateID, null)
+        {
+        }
+
+        public V2Form(GeneralNames issuerName, ObjectDigestInfo objectDigestInfo)
+            : this(issuerName, null, objectDigestInfo)
+        {
+        }
+
+        public V2Form(
+            GeneralNames issuerName,
+            IssuerSerial baseCertificateID,
+            ObjectDigestInfo objectDigestInfo)
+        {
+            this.issuerName = issuerName;
+            this.baseCertificateID = baseCertificateID;
+            this.objectDigestInfo = objectDigestInfo;
+        }
+
+        private V2Form(
+            Asn1Sequence seq)
+        {
+            if (seq.Count > 3)
+            {
+                throw new ArgumentException("Bad sequence size: " + seq.Count);
+            }
+
+            int index = 0;
+
+            if (!(seq[0] is Asn1TaggedObject))
+            {
+                index++;
+                this.issuerName = GeneralNames.GetInstance(seq[0]);
+            }
+
+            for (int i = index; i != seq.Count; i++)
+            {
+                Asn1TaggedObject o = Asn1TaggedObject.GetInstance(seq[i]);
+                if (o.TagNo == 0)
+                {
+                    baseCertificateID = IssuerSerial.GetInstance(o, false);
+                }
+                else if (o.TagNo == 1)
+                {
+                    objectDigestInfo = ObjectDigestInfo.GetInstance(o, false);
+                }
+                else
+                {
+                    throw new ArgumentException("Bad tag number: " + o.TagNo);
+                }
+            }
+        }
+
+        public GeneralNames IssuerName
+        {
+            get { return issuerName; }
+        }
+
+        public IssuerSerial BaseCertificateID
+        {
+            get { return baseCertificateID; }
+        }
+
+        public ObjectDigestInfo ObjectDigestInfo
+        {
+            get { return objectDigestInfo; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  V2Form ::= Sequence {
+         *       issuerName            GeneralNames  OPTIONAL,
+         *       baseCertificateID     [0] IssuerSerial  OPTIONAL,
+         *       objectDigestInfo      [1] ObjectDigestInfo  OPTIONAL
+         *         -- issuerName MUST be present in this profile
+         *         -- baseCertificateID and objectDigestInfo MUST NOT
+         *         -- be present in this profile
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (issuerName != null)
+            {
+                v.Add(issuerName);
+            }
+
+            if (baseCertificateID != null)
+            {
+                v.Add(new DerTaggedObject(false, 0, baseCertificateID));
+            }
+
+            if (objectDigestInfo != null)
+            {
+                v.Add(new DerTaggedObject(false, 1, objectDigestInfo));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/V2TBSCertListGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/x509/V2TBSCertListGenerator.cs
new file mode 100644
index 0000000..2c92918
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/V2TBSCertListGenerator.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Generator for Version 2 TbsCertList structures.
+     * <pre>
+     *  TbsCertList  ::=  Sequence  {
+     *       version                 Version OPTIONAL,
+     *                                    -- if present, shall be v2
+     *       signature               AlgorithmIdentifier,
+     *       issuer                  Name,
+     *       thisUpdate              Time,
+     *       nextUpdate              Time OPTIONAL,
+     *       revokedCertificates     Sequence OF Sequence  {
+     *            userCertificate         CertificateSerialNumber,
+     *            revocationDate          Time,
+     *            crlEntryExtensions      Extensions OPTIONAL
+     *                                          -- if present, shall be v2
+     *                                 }  OPTIONAL,
+     *       crlExtensions           [0]  EXPLICIT Extensions OPTIONAL
+     *                                          -- if present, shall be v2
+     *                                 }
+     * </pre>
+     *
+     * <b>Note: This class may be subject to change</b>
+     */
+    public class V2TbsCertListGenerator
+    {
+        private DerInteger			version = new DerInteger(1);
+        private AlgorithmIdentifier	signature;
+        private X509Name			issuer;
+        private Time				thisUpdate, nextUpdate;
+        private X509Extensions		extensions;
+        private IList			    crlEntries;
+
+		public V2TbsCertListGenerator()
+        {
+        }
+
+		public void SetSignature(
+            AlgorithmIdentifier signature)
+        {
+            this.signature = signature;
+        }
+
+		public void SetIssuer(
+            X509Name issuer)
+        {
+            this.issuer = issuer;
+        }
+
+		public void SetThisUpdate(
+            DerUtcTime thisUpdate)
+        {
+            this.thisUpdate = new Time(thisUpdate);
+        }
+
+		public void SetNextUpdate(
+            DerUtcTime nextUpdate)
+        {
+            this.nextUpdate = (nextUpdate != null)
+				?	new Time(nextUpdate)
+				:	null;
+        }
+
+		public void SetThisUpdate(
+            Time thisUpdate)
+        {
+            this.thisUpdate = thisUpdate;
+        }
+
+		public void SetNextUpdate(
+            Time nextUpdate)
+        {
+            this.nextUpdate = nextUpdate;
+        }
+
+		public void AddCrlEntry(
+			Asn1Sequence crlEntry)
+		{
+			if (crlEntries == null)
+			{
+				crlEntries = Platform.CreateArrayList();
+			}
+
+			crlEntries.Add(crlEntry);
+		}
+
+		public void AddCrlEntry(DerInteger userCertificate, DerUtcTime revocationDate, int reason)
+		{
+			AddCrlEntry(userCertificate, new Time(revocationDate), reason);
+		}
+
+		public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason)
+		{
+			AddCrlEntry(userCertificate, revocationDate, reason, null);
+		}
+
+		public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, int reason,
+			DerGeneralizedTime invalidityDate)
+		{
+            IList extOids = Platform.CreateArrayList();
+            IList extValues = Platform.CreateArrayList();
+
+			if (reason != 0)
+			{
+				CrlReason crlReason = new CrlReason(reason);
+
+				try
+				{
+					extOids.Add(X509Extensions.ReasonCode);
+					extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded())));
+				}
+				catch (IOException e)
+				{
+					throw new ArgumentException("error encoding reason: " + e);
+				}
+			}
+
+			if (invalidityDate != null)
+			{
+				try
+				{
+					extOids.Add(X509Extensions.InvalidityDate);
+					extValues.Add(new X509Extension(false, new DerOctetString(invalidityDate.GetEncoded())));
+				}
+				catch (IOException e)
+				{
+					throw new ArgumentException("error encoding invalidityDate: " + e);
+				}
+			}
+
+			if (extOids.Count != 0)
+			{
+				AddCrlEntry(userCertificate, revocationDate, new X509Extensions(extOids, extValues));
+			}
+			else
+			{
+				AddCrlEntry(userCertificate, revocationDate, null);
+			}
+		}
+
+		public void AddCrlEntry(DerInteger userCertificate, Time revocationDate, X509Extensions extensions)
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				userCertificate, revocationDate);
+
+			if (extensions != null)
+			{
+				v.Add(extensions);
+			}
+
+			AddCrlEntry(new DerSequence(v));
+		}
+
+		public void SetExtensions(
+            X509Extensions extensions)
+        {
+            this.extensions = extensions;
+        }
+
+		public TbsCertificateList GenerateTbsCertList()
+        {
+            if ((signature == null) || (issuer == null) || (thisUpdate == null))
+            {
+                throw new InvalidOperationException("Not all mandatory fields set in V2 TbsCertList generator.");
+            }
+
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				version, signature, issuer, thisUpdate);
+
+			if (nextUpdate != null)
+            {
+                v.Add(nextUpdate);
+            }
+
+			// Add CRLEntries if they exist
+            if (crlEntries != null)
+            {
+                Asn1Sequence[] certs = new Asn1Sequence[crlEntries.Count];
+                for (int i = 0; i < crlEntries.Count; ++i)
+                {
+                    certs[i] = (Asn1Sequence)crlEntries[i];
+                }
+				v.Add(new DerSequence(certs));
+            }
+
+			if (extensions != null)
+            {
+                v.Add(new DerTaggedObject(0, extensions));
+            }
+
+			return new TbsCertificateList(new DerSequence(v));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/V3TBSCertificateGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/x509/V3TBSCertificateGenerator.cs
new file mode 100644
index 0000000..beb469a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/V3TBSCertificateGenerator.cs
@@ -0,0 +1,168 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * Generator for Version 3 TbsCertificateStructures.
+     * <pre>
+     * TbsCertificate ::= Sequence {
+     *      version          [ 0 ]  Version DEFAULT v1(0),
+     *      serialNumber            CertificateSerialNumber,
+     *      signature               AlgorithmIdentifier,
+     *      issuer                  Name,
+     *      validity                Validity,
+     *      subject                 Name,
+     *      subjectPublicKeyInfo    SubjectPublicKeyInfo,
+     *      issuerUniqueID    [ 1 ] IMPLICIT UniqueIdentifier OPTIONAL,
+     *      subjectUniqueID   [ 2 ] IMPLICIT UniqueIdentifier OPTIONAL,
+     *      extensions        [ 3 ] Extensions OPTIONAL
+     *      }
+     * </pre>
+     *
+     */
+    public class V3TbsCertificateGenerator
+    {
+        internal DerTaggedObject         version = new DerTaggedObject(0, new DerInteger(2));
+        internal DerInteger              serialNumber;
+        internal AlgorithmIdentifier     signature;
+        internal X509Name                issuer;
+        internal Time                    startDate, endDate;
+        internal X509Name                subject;
+        internal SubjectPublicKeyInfo    subjectPublicKeyInfo;
+        internal X509Extensions          extensions;
+
+		private bool altNamePresentAndCritical;
+		private DerBitString issuerUniqueID;
+		private DerBitString subjectUniqueID;
+
+		public V3TbsCertificateGenerator()
+        {
+        }
+
+		public void SetSerialNumber(
+            DerInteger serialNumber)
+        {
+            this.serialNumber = serialNumber;
+        }
+
+		public void SetSignature(
+            AlgorithmIdentifier signature)
+        {
+            this.signature = signature;
+        }
+
+		public void SetIssuer(
+            X509Name issuer)
+        {
+            this.issuer = issuer;
+        }
+
+		public void SetStartDate(
+            DerUtcTime startDate)
+        {
+            this.startDate = new Time(startDate);
+        }
+
+		public void SetStartDate(
+            Time startDate)
+        {
+            this.startDate = startDate;
+        }
+
+		public void SetEndDate(
+            DerUtcTime endDate)
+        {
+            this.endDate = new Time(endDate);
+        }
+
+		public void SetEndDate(
+            Time endDate)
+        {
+            this.endDate = endDate;
+        }
+
+		public void SetSubject(
+            X509Name subject)
+        {
+            this.subject = subject;
+        }
+
+		public void SetIssuerUniqueID(
+			DerBitString uniqueID)
+		{
+			this.issuerUniqueID = uniqueID;
+		}
+
+		public void SetSubjectUniqueID(
+			DerBitString uniqueID)
+		{
+			this.subjectUniqueID = uniqueID;
+		}
+
+		public void SetSubjectPublicKeyInfo(
+            SubjectPublicKeyInfo pubKeyInfo)
+        {
+            this.subjectPublicKeyInfo = pubKeyInfo;
+        }
+
+		public void SetExtensions(
+            X509Extensions extensions)
+        {
+            this.extensions = extensions;
+
+			if (extensions != null)
+			{
+				X509Extension altName = extensions.GetExtension(X509Extensions.SubjectAlternativeName);
+
+				if (altName != null && altName.IsCritical)
+				{
+					altNamePresentAndCritical = true;
+				}
+			}
+		}
+
+		public TbsCertificateStructure GenerateTbsCertificate()
+        {
+            if ((serialNumber == null) || (signature == null)
+                || (issuer == null) || (startDate == null) || (endDate == null)
+				|| (subject == null && !altNamePresentAndCritical)
+				|| (subjectPublicKeyInfo == null))
+            {
+                throw new InvalidOperationException("not all mandatory fields set in V3 TBScertificate generator");
+            }
+
+			DerSequence validity = new DerSequence(startDate, endDate); // before and after dates
+
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				version, serialNumber, signature, issuer, validity);
+
+			if (subject != null)
+			{
+				v.Add(subject);
+			}
+			else
+			{
+				v.Add(DerSequence.Empty);
+			}
+
+			v.Add(subjectPublicKeyInfo);
+
+			if (issuerUniqueID != null)
+			{
+				v.Add(new DerTaggedObject(false, 1, issuerUniqueID));
+			}
+
+			if (subjectUniqueID != null)
+			{
+				v.Add(new DerTaggedObject(false, 2, subjectUniqueID));
+			}
+
+			if (extensions != null)
+            {
+                v.Add(new DerTaggedObject(3, extensions));
+            }
+
+			return new TbsCertificateStructure(new DerSequence(v));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509Attributes.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509Attributes.cs
new file mode 100644
index 0000000..291329a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509Attributes.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	public class X509Attributes
+	{
+		public static readonly DerObjectIdentifier RoleSyntax = new DerObjectIdentifier("2.5.4.72");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509CertificateStructure.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509CertificateStructure.cs
new file mode 100644
index 0000000..c8558ae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509CertificateStructure.cs
@@ -0,0 +1,127 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * an X509Certificate structure.
+     * <pre>
+     *  Certificate ::= Sequence {
+     *      tbsCertificate          TbsCertificate,
+     *      signatureAlgorithm      AlgorithmIdentifier,
+     *      signature               BIT STRING
+     *  }
+     * </pre>
+     */
+    public class X509CertificateStructure
+        : Asn1Encodable
+    {
+        private readonly TbsCertificateStructure	tbsCert;
+        private readonly AlgorithmIdentifier		sigAlgID;
+        private readonly DerBitString				sig;
+
+        public static X509CertificateStructure GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static X509CertificateStructure GetInstance(
+            object obj)
+        {
+            if (obj is X509CertificateStructure)
+                return (X509CertificateStructure)obj;
+            if (obj == null)
+                return null;
+            return new X509CertificateStructure(Asn1Sequence.GetInstance(obj));
+        }
+
+        public X509CertificateStructure(
+            TbsCertificateStructure	tbsCert,
+            AlgorithmIdentifier		sigAlgID,
+            DerBitString			sig)
+        {
+            if (tbsCert == null)
+                throw new ArgumentNullException("tbsCert");
+            if (sigAlgID == null)
+                throw new ArgumentNullException("sigAlgID");
+            if (sig == null)
+                throw new ArgumentNullException("sig");
+
+            this.tbsCert = tbsCert;
+            this.sigAlgID = sigAlgID;
+            this.sig = sig;
+        }
+
+        private X509CertificateStructure(
+            Asn1Sequence seq)
+        {
+            if (seq.Count != 3)
+                throw new ArgumentException("sequence wrong size for a certificate", "seq");
+
+            //
+            // correct x509 certficate
+            //
+            tbsCert = TbsCertificateStructure.GetInstance(seq[0]);
+            sigAlgID = AlgorithmIdentifier.GetInstance(seq[1]);
+            sig = DerBitString.GetInstance(seq[2]);
+        }
+
+        public TbsCertificateStructure TbsCertificate
+        {
+            get { return tbsCert; }
+        }
+
+        public int Version
+        {
+            get { return tbsCert.Version; }
+        }
+
+        public DerInteger SerialNumber
+        {
+            get { return tbsCert.SerialNumber; }
+        }
+
+        public X509Name Issuer
+        {
+            get { return tbsCert.Issuer; }
+        }
+
+        public Time StartDate
+        {
+            get { return tbsCert.StartDate; }
+        }
+
+        public Time EndDate
+        {
+            get { return tbsCert.EndDate; }
+        }
+
+        public X509Name Subject
+        {
+            get { return tbsCert.Subject; }
+        }
+
+        public SubjectPublicKeyInfo SubjectPublicKeyInfo
+        {
+            get { return tbsCert.SubjectPublicKeyInfo; }
+        }
+
+        public AlgorithmIdentifier SignatureAlgorithm
+        {
+            get { return sigAlgID; }
+        }
+
+        public DerBitString Signature
+        {
+            get { return sig; }
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(tbsCert, sigAlgID, sig);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509DefaultEntryConverter.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509DefaultEntryConverter.cs
new file mode 100644
index 0000000..7282ead
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509DefaultEntryConverter.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * The default converter for X509 DN entries when going from their
+     * string value to ASN.1 strings.
+     */
+    public class X509DefaultEntryConverter
+        : X509NameEntryConverter
+    {
+        /**
+         * Apply default conversion for the given value depending on the oid
+         * and the character range of the value.
+         *
+         * @param oid the object identifier for the DN entry
+         * @param value the value associated with it
+         * @return the ASN.1 equivalent for the string value.
+         */
+        public override Asn1Object GetConvertedValue(
+            DerObjectIdentifier	oid,
+            string				value)
+        {
+            if (value.Length != 0 && value[0] == '#')
+            {
+				try
+				{
+					return ConvertHexEncoded(value, 1);
+				}
+				catch (IOException)
+				{
+					throw new Exception("can't recode value for oid " + oid.Id);
+				}
+			}
+
+			if (value.Length != 0 && value[0] == '\\')
+			{
+				value = value.Substring(1);
+			}
+
+			if (oid.Equals(X509Name.EmailAddress) || oid.Equals(X509Name.DC))
+            {
+                return new DerIA5String(value);
+            }
+
+			if (oid.Equals(X509Name.DateOfBirth)) // accept time string as well as # (for compatibility)
+			{
+				return new DerGeneralizedTime(value);
+			}
+
+			if (oid.Equals(X509Name.C)
+				|| oid.Equals(X509Name.SerialNumber)
+				|| oid.Equals(X509Name.DnQualifier)
+				|| oid.Equals(X509Name.TelephoneNumber))
+			{
+				return new DerPrintableString(value);
+			}
+
+			return new DerUtf8String(value);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509Extension.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509Extension.cs
new file mode 100644
index 0000000..430ce44
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509Extension.cs
@@ -0,0 +1,79 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * an object for the elements in the X.509 V3 extension block.
+     */
+    public class X509Extension
+    {
+        internal bool				critical;
+        internal Asn1OctetString	value;
+
+		public X509Extension(
+            DerBoolean		critical,
+            Asn1OctetString	value)
+        {
+            if (critical == null)
+            {
+                throw new ArgumentNullException("critical");
+            }
+
+			this.critical = critical.IsTrue;
+            this.value = value;
+        }
+
+		public X509Extension(
+            bool			critical,
+            Asn1OctetString	value)
+        {
+            this.critical = critical;
+            this.value = value;
+        }
+
+		public bool IsCritical { get { return critical; } }
+
+		public Asn1OctetString Value { get { return value; } }
+
+		public Asn1Encodable GetParsedValue()
+		{
+			return ConvertValueToObject(this);
+		}
+
+		public override int GetHashCode()
+        {
+			int vh = this.Value.GetHashCode();
+
+			return IsCritical ? vh : ~vh;
+        }
+
+		public override bool Equals(
+            object obj)
+        {
+            X509Extension other = obj as X509Extension;
+            if (other == null)
+            {
+                return false;
+            }
+
+			return Value.Equals(other.Value) && IsCritical == other.IsCritical;
+        }
+
+		/// <sumary>Convert the value of the passed in extension to an object.</sumary>
+		/// <param name="ext">The extension to parse.</param>
+		/// <returns>The object the value string contains.</returns>
+		/// <exception cref="ArgumentException">If conversion is not possible.</exception>
+		public static Asn1Object ConvertValueToObject(
+			X509Extension ext)
+		{
+			try
+			{
+				return Asn1Object.FromByteArray(ext.Value.GetOctets());
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("can't convert extension", e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509Extensions.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509Extensions.cs
new file mode 100644
index 0000000..5dce562
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509Extensions.cs
@@ -0,0 +1,451 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public class X509Extensions
+        : Asn1Encodable
+    {
+		/**
+		 * Subject Directory Attributes
+		 */
+		public static readonly DerObjectIdentifier SubjectDirectoryAttributes = new DerObjectIdentifier("2.5.29.9");
+
+		/**
+         * Subject Key Identifier
+         */
+        public static readonly DerObjectIdentifier SubjectKeyIdentifier = new DerObjectIdentifier("2.5.29.14");
+
+		/**
+         * Key Usage
+         */
+        public static readonly DerObjectIdentifier KeyUsage = new DerObjectIdentifier("2.5.29.15");
+
+		/**
+         * Private Key Usage Period
+         */
+        public static readonly DerObjectIdentifier PrivateKeyUsagePeriod = new DerObjectIdentifier("2.5.29.16");
+
+		/**
+         * Subject Alternative Name
+         */
+        public static readonly DerObjectIdentifier SubjectAlternativeName = new DerObjectIdentifier("2.5.29.17");
+
+		/**
+         * Issuer Alternative Name
+         */
+        public static readonly DerObjectIdentifier IssuerAlternativeName = new DerObjectIdentifier("2.5.29.18");
+
+		/**
+         * Basic Constraints
+         */
+        public static readonly DerObjectIdentifier BasicConstraints = new DerObjectIdentifier("2.5.29.19");
+
+		/**
+         * CRL Number
+         */
+        public static readonly DerObjectIdentifier CrlNumber = new DerObjectIdentifier("2.5.29.20");
+
+		/**
+         * Reason code
+         */
+        public static readonly DerObjectIdentifier ReasonCode = new DerObjectIdentifier("2.5.29.21");
+
+		/**
+         * Hold Instruction Code
+         */
+        public static readonly DerObjectIdentifier InstructionCode = new DerObjectIdentifier("2.5.29.23");
+
+		/**
+         * Invalidity Date
+         */
+        public static readonly DerObjectIdentifier InvalidityDate = new DerObjectIdentifier("2.5.29.24");
+
+		/**
+         * Delta CRL indicator
+         */
+        public static readonly DerObjectIdentifier DeltaCrlIndicator = new DerObjectIdentifier("2.5.29.27");
+
+		/**
+         * Issuing Distribution Point
+         */
+        public static readonly DerObjectIdentifier IssuingDistributionPoint = new DerObjectIdentifier("2.5.29.28");
+
+		/**
+         * Certificate Issuer
+         */
+        public static readonly DerObjectIdentifier CertificateIssuer = new DerObjectIdentifier("2.5.29.29");
+
+		/**
+         * Name Constraints
+         */
+        public static readonly DerObjectIdentifier NameConstraints = new DerObjectIdentifier("2.5.29.30");
+
+		/**
+         * CRL Distribution Points
+         */
+        public static readonly DerObjectIdentifier CrlDistributionPoints = new DerObjectIdentifier("2.5.29.31");
+
+		/**
+         * Certificate Policies
+         */
+        public static readonly DerObjectIdentifier CertificatePolicies = new DerObjectIdentifier("2.5.29.32");
+
+		/**
+         * Policy Mappings
+         */
+        public static readonly DerObjectIdentifier PolicyMappings = new DerObjectIdentifier("2.5.29.33");
+
+		/**
+         * Authority Key Identifier
+         */
+        public static readonly DerObjectIdentifier AuthorityKeyIdentifier = new DerObjectIdentifier("2.5.29.35");
+
+		/**
+         * Policy Constraints
+         */
+        public static readonly DerObjectIdentifier PolicyConstraints = new DerObjectIdentifier("2.5.29.36");
+
+		/**
+         * Extended Key Usage
+         */
+        public static readonly DerObjectIdentifier ExtendedKeyUsage = new DerObjectIdentifier("2.5.29.37");
+
+		/**
+		 * Freshest CRL
+		 */
+		public static readonly DerObjectIdentifier FreshestCrl = new DerObjectIdentifier("2.5.29.46");
+
+		/**
+         * Inhibit Any Policy
+         */
+        public static readonly DerObjectIdentifier InhibitAnyPolicy = new DerObjectIdentifier("2.5.29.54");
+
+		/**
+         * Authority Info Access
+         */
+		public static readonly DerObjectIdentifier AuthorityInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.1");
+
+		/**
+		 * Subject Info Access
+		 */
+		public static readonly DerObjectIdentifier SubjectInfoAccess = new DerObjectIdentifier("1.3.6.1.5.5.7.1.11");
+
+		/**
+		 * Logo Type
+		 */
+		public static readonly DerObjectIdentifier LogoType = new DerObjectIdentifier("1.3.6.1.5.5.7.1.12");
+
+		/**
+		 * BiometricInfo
+		 */
+		public static readonly DerObjectIdentifier BiometricInfo = new DerObjectIdentifier("1.3.6.1.5.5.7.1.2");
+
+		/**
+		 * QCStatements
+		 */
+		public static readonly DerObjectIdentifier QCStatements = new DerObjectIdentifier("1.3.6.1.5.5.7.1.3");
+
+		/**
+		 * Audit identity extension in attribute certificates.
+		 */
+		public static readonly DerObjectIdentifier AuditIdentity = new DerObjectIdentifier("1.3.6.1.5.5.7.1.4");
+
+		/**
+		 * NoRevAvail extension in attribute certificates.
+		 */
+		public static readonly DerObjectIdentifier NoRevAvail = new DerObjectIdentifier("2.5.29.56");
+
+		/**
+		 * TargetInformation extension in attribute certificates.
+		 */
+		public static readonly DerObjectIdentifier TargetInformation = new DerObjectIdentifier("2.5.29.55");
+
+        private readonly IDictionary extensions = Platform.CreateHashtable();
+        private readonly IList ordering;
+
+		public static X509Extensions GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+		public static X509Extensions GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is X509Extensions)
+            {
+                return (X509Extensions) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new X509Extensions((Asn1Sequence) obj);
+            }
+
+			if (obj is Asn1TaggedObject)
+            {
+                return GetInstance(((Asn1TaggedObject) obj).GetObject());
+            }
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+         * Constructor from Asn1Sequence.
+         *
+         * the extensions are a list of constructed sequences, either with (Oid, OctetString) or (Oid, Boolean, OctetString)
+         */
+        private X509Extensions(
+            Asn1Sequence seq)
+        {
+            this.ordering = Platform.CreateArrayList();
+
+			foreach (Asn1Encodable ae in seq)
+			{
+				Asn1Sequence s = Asn1Sequence.GetInstance(ae.ToAsn1Object());
+
+				if (s.Count < 2 || s.Count > 3)
+					throw new ArgumentException("Bad sequence size: " + s.Count);
+
+				DerObjectIdentifier oid = DerObjectIdentifier.GetInstance(s[0].ToAsn1Object());
+
+				bool isCritical = s.Count == 3
+					&& DerBoolean.GetInstance(s[1].ToAsn1Object()).IsTrue;
+
+				Asn1OctetString octets = Asn1OctetString.GetInstance(s[s.Count - 1].ToAsn1Object());
+
+				extensions.Add(oid, new X509Extension(isCritical, octets));
+				ordering.Add(oid);
+			}
+        }
+
+        /**
+         * constructor from a table of extensions.
+         * <p>
+         * it's is assumed the table contains Oid/string pairs.</p>
+         */
+        public X509Extensions(
+            IDictionary extensions)
+            : this(null, extensions)
+        {
+        }
+
+        /**
+         * Constructor from a table of extensions with ordering.
+         * <p>
+         * It's is assumed the table contains Oid/string pairs.</p>
+         */
+        public X509Extensions(
+            IList       ordering,
+            IDictionary extensions)
+        {
+            if (ordering == null)
+            {
+                this.ordering = Platform.CreateArrayList(extensions.Keys);
+            }
+            else
+            {
+                this.ordering = Platform.CreateArrayList(ordering);
+            }
+
+            foreach (DerObjectIdentifier oid in this.ordering)
+            {
+                this.extensions.Add(oid, (X509Extension)extensions[oid]);
+            }
+        }
+
+        /**
+         * Constructor from two vectors
+         *
+         * @param objectIDs an ArrayList of the object identifiers.
+         * @param values an ArrayList of the extension values.
+         */
+        public X509Extensions(
+            IList oids,
+            IList values)
+        {
+            this.ordering = Platform.CreateArrayList(oids);
+
+            int count = 0;
+            foreach (DerObjectIdentifier oid in this.ordering)
+            {
+                this.extensions.Add(oid, (X509Extension)values[count++]);
+            }
+        }
+
+#if !SILVERLIGHT
+		/**
+         * constructor from a table of extensions.
+         * <p>
+         * it's is assumed the table contains Oid/string pairs.</p>
+         */
+        [Obsolete]
+        public X509Extensions(
+            Hashtable extensions)
+             : this(null, extensions)
+        {
+        }
+
+		/**
+         * Constructor from a table of extensions with ordering.
+         * <p>
+         * It's is assumed the table contains Oid/string pairs.</p>
+         */
+        [Obsolete]
+        public X509Extensions(
+            ArrayList	ordering,
+            Hashtable	extensions)
+        {
+            if (ordering == null)
+            {
+                this.ordering = Platform.CreateArrayList(extensions.Keys);
+            }
+            else
+            {
+                this.ordering = Platform.CreateArrayList(ordering);
+            }
+
+            foreach (DerObjectIdentifier oid in this.ordering)
+			{
+				this.extensions.Add(oid, (X509Extension) extensions[oid]);
+			}
+        }
+
+		/**
+		 * Constructor from two vectors
+		 *
+		 * @param objectIDs an ArrayList of the object identifiers.
+		 * @param values an ArrayList of the extension values.
+		 */
+        [Obsolete]
+		public X509Extensions(
+			ArrayList	oids,
+			ArrayList	values)
+		{
+            this.ordering = Platform.CreateArrayList(oids);
+
+            int count = 0;
+			foreach (DerObjectIdentifier oid in this.ordering)
+			{
+				this.extensions.Add(oid, (X509Extension) values[count++]);
+			}
+		}
+#endif
+
+        [Obsolete("Use ExtensionOids IEnumerable property")]
+		public IEnumerator Oids()
+		{
+			return ExtensionOids.GetEnumerator();
+		}
+
+		/**
+		 * return an Enumeration of the extension field's object ids.
+		 */
+		public IEnumerable ExtensionOids
+        {
+			get { return new EnumerableProxy(ordering); }
+        }
+
+		/**
+         * return the extension represented by the object identifier
+         * passed in.
+         *
+         * @return the extension if it's present, null otherwise.
+         */
+        public X509Extension GetExtension(
+            DerObjectIdentifier oid)
+        {
+             return (X509Extension) extensions[oid];
+        }
+
+		/**
+		 * <pre>
+		 *     Extensions        ::=   SEQUENCE SIZE (1..MAX) OF Extension
+		 *
+		 *     Extension         ::=   SEQUENCE {
+		 *        extnId            EXTENSION.&id ({ExtensionSet}),
+		 *        critical          BOOLEAN DEFAULT FALSE,
+		 *        extnValue         OCTET STRING }
+		 * </pre>
+		 */
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector	vec = new Asn1EncodableVector();
+
+			foreach (DerObjectIdentifier oid in ordering)
+			{
+                X509Extension ext = (X509Extension) extensions[oid];
+                Asn1EncodableVector	v = new Asn1EncodableVector(oid);
+
+				if (ext.IsCritical)
+                {
+                    v.Add(DerBoolean.True);
+                }
+
+				v.Add(ext.Value);
+
+				vec.Add(new DerSequence(v));
+            }
+
+			return new DerSequence(vec);
+        }
+
+		public bool Equivalent(
+			X509Extensions other)
+		{
+			if (extensions.Count != other.extensions.Count)
+				return false;
+
+			foreach (DerObjectIdentifier oid in extensions.Keys)
+			{
+				if (!extensions[oid].Equals(other.extensions[oid]))
+					return false;
+			}
+
+			return true;
+		}
+
+		public DerObjectIdentifier[] GetExtensionOids()
+		{
+			return ToOidArray(ordering);
+		}
+
+		public DerObjectIdentifier[] GetNonCriticalExtensionOids()
+		{
+			return GetExtensionOids(false);
+		}
+
+		public DerObjectIdentifier[] GetCriticalExtensionOids()
+		{
+			return GetExtensionOids(true);
+		}
+
+		private DerObjectIdentifier[] GetExtensionOids(bool isCritical)
+		{
+			IList oids = Platform.CreateArrayList();
+
+			foreach (DerObjectIdentifier oid in this.ordering)
+            {
+				X509Extension ext = (X509Extension)extensions[oid];
+				if (ext.IsCritical == isCritical)
+				{
+					oids.Add(oid);
+				}
+            }
+
+			return ToOidArray(oids);
+		}
+
+		private static DerObjectIdentifier[] ToOidArray(IList oids)
+		{
+			DerObjectIdentifier[] oidArray = new DerObjectIdentifier[oids.Count];
+			oids.CopyTo(oidArray, 0);
+			return oidArray;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509ExtensionsGenerator.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509ExtensionsGenerator.cs
new file mode 100644
index 0000000..d6f567b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509ExtensionsGenerator.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+	/// <remarks>Generator for X.509 extensions</remarks>
+	public class X509ExtensionsGenerator
+	{
+		private IDictionary extensions = Platform.CreateHashtable();
+        private IList extOrdering = Platform.CreateArrayList();
+
+		/// <summary>Reset the generator</summary>
+		public void Reset()
+		{
+            extensions = Platform.CreateHashtable();
+            extOrdering = Platform.CreateArrayList();
+		}
+
+		/// <summary>
+		/// Add an extension with the given oid and the passed in value to be included
+		/// in the OCTET STRING associated with the extension.
+		/// </summary>
+		/// <param name="oid">OID for the extension.</param>
+		/// <param name="critical">True if critical, false otherwise.</param>
+		/// <param name="extValue">The ASN.1 object to be included in the extension.</param>
+		public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			Asn1Encodable		extValue)
+		{
+			byte[] encoded;
+			try
+			{
+				encoded = extValue.GetDerEncoded();
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("error encoding value: " + e);
+			}
+
+			this.AddExtension(oid, critical, encoded);
+		}
+
+		/// <summary>
+		/// Add an extension with the given oid and the passed in byte array to be wrapped
+		/// in the OCTET STRING associated with the extension.
+		/// </summary>
+		/// <param name="oid">OID for the extension.</param>
+		/// <param name="critical">True if critical, false otherwise.</param>
+		/// <param name="extValue">The byte array to be wrapped.</param>
+		public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			byte[]				extValue)
+		{
+			if (extensions.Contains(oid))
+			{
+				throw new ArgumentException("extension " + oid + " already added");
+			}
+
+			extOrdering.Add(oid);
+			extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue)));
+		}
+
+		/// <summary>Return true if there are no extension present in this generator.</summary>
+		/// <returns>True if empty, false otherwise</returns>
+		public bool IsEmpty
+		{
+			get { return extOrdering.Count < 1; }
+		}
+
+		/// <summary>Generate an X509Extensions object based on the current state of the generator.</summary>
+		/// <returns>An <c>X509Extensions</c> object</returns>
+		public X509Extensions Generate()
+		{
+			return new X509Extensions(extOrdering, extensions);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509Name.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509Name.cs
new file mode 100644
index 0000000..c183e57
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509Name.cs
@@ -0,0 +1,1083 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+#if SILVERLIGHT
+using System.Collections.Generic;
+#endif
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+    * <pre>
+    *     RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+    *
+    *     RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
+    *
+    *     AttributeTypeAndValue ::= SEQUENCE {
+    *                                   type  OBJECT IDENTIFIER,
+    *                                   value ANY }
+    * </pre>
+    */
+    public class X509Name
+        : Asn1Encodable
+    {
+        /**
+        * country code - StringType(SIZE(2))
+        */
+        public static readonly DerObjectIdentifier C = new DerObjectIdentifier("2.5.4.6");
+
+        /**
+        * organization - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier O = new DerObjectIdentifier("2.5.4.10");
+
+        /**
+        * organizational unit name - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier OU = new DerObjectIdentifier("2.5.4.11");
+
+        /**
+        * Title
+        */
+        public static readonly DerObjectIdentifier T = new DerObjectIdentifier("2.5.4.12");
+
+        /**
+        * common name - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier CN = new DerObjectIdentifier("2.5.4.3");
+
+        /**
+        * street - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier Street = new DerObjectIdentifier("2.5.4.9");
+
+        /**
+        * device serial number name - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier SerialNumber = new DerObjectIdentifier("2.5.4.5");
+
+        /**
+        * locality name - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier L = new DerObjectIdentifier("2.5.4.7");
+
+        /**
+        * state, or province name - StringType(SIZE(1..64))
+        */
+        public static readonly DerObjectIdentifier ST = new DerObjectIdentifier("2.5.4.8");
+
+        /**
+        * Naming attributes of type X520name
+        */
+        public static readonly DerObjectIdentifier Surname = new DerObjectIdentifier("2.5.4.4");
+        public static readonly DerObjectIdentifier GivenName = new DerObjectIdentifier("2.5.4.42");
+        public static readonly DerObjectIdentifier Initials = new DerObjectIdentifier("2.5.4.43");
+        public static readonly DerObjectIdentifier Generation = new DerObjectIdentifier("2.5.4.44");
+        public static readonly DerObjectIdentifier UniqueIdentifier = new DerObjectIdentifier("2.5.4.45");
+
+        /**
+         * businessCategory - DirectoryString(SIZE(1..128)
+         */
+        public static readonly DerObjectIdentifier BusinessCategory = new DerObjectIdentifier(
+                                                                       "2.5.4.15");
+
+        /**
+         * postalCode - DirectoryString(SIZE(1..40)
+         */
+        public static readonly DerObjectIdentifier PostalCode = new DerObjectIdentifier(
+                                                                 "2.5.4.17");
+
+        /**
+         * dnQualifier - DirectoryString(SIZE(1..64)
+         */
+        public static readonly DerObjectIdentifier DnQualifier = new DerObjectIdentifier(
+                                                         "2.5.4.46");
+
+        /**
+         * RFC 3039 Pseudonym - DirectoryString(SIZE(1..64)
+         */
+        public static readonly DerObjectIdentifier Pseudonym = new DerObjectIdentifier(
+                                                                "2.5.4.65");
+
+        /**
+         * RFC 3039 DateOfBirth - GeneralizedTime - YYYYMMDD000000Z
+         */
+        public static readonly DerObjectIdentifier DateOfBirth = new DerObjectIdentifier(
+                                                                  "1.3.6.1.5.5.7.9.1");
+
+        /**
+         * RFC 3039 PlaceOfBirth - DirectoryString(SIZE(1..128)
+         */
+        public static readonly DerObjectIdentifier PlaceOfBirth = new DerObjectIdentifier(
+                                                                   "1.3.6.1.5.5.7.9.2");
+
+        /**
+         * RFC 3039 DateOfBirth - PrintableString (SIZE(1)) -- "M", "F", "m" or "f"
+         */
+        public static readonly DerObjectIdentifier Gender = new DerObjectIdentifier(
+                                                                   "1.3.6.1.5.5.7.9.3");
+
+        /**
+         * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+         * codes only
+         */
+        public static readonly DerObjectIdentifier CountryOfCitizenship = new DerObjectIdentifier(
+                                                                           "1.3.6.1.5.5.7.9.4");
+
+        /**
+         * RFC 3039 CountryOfCitizenship - PrintableString (SIZE (2)) -- ISO 3166
+         * codes only
+         */
+        public static readonly DerObjectIdentifier CountryOfResidence = new DerObjectIdentifier(
+                                                                         "1.3.6.1.5.5.7.9.5");
+
+        /**
+         * ISIS-MTT NameAtBirth - DirectoryString(SIZE(1..64)
+         */
+        public static readonly DerObjectIdentifier NameAtBirth =  new DerObjectIdentifier("1.3.36.8.3.14");
+
+        /**
+         * RFC 3039 PostalAddress - SEQUENCE SIZE (1..6) OF
+         * DirectoryString(SIZE(1..30))
+         */
+        public static readonly DerObjectIdentifier PostalAddress = new DerObjectIdentifier("2.5.4.16");
+
+        /**
+         * RFC 2256 dmdName
+         */
+        public static readonly DerObjectIdentifier DmdName = new DerObjectIdentifier("2.5.4.54");
+
+        /**
+         * id-at-telephoneNumber
+         */
+        public static readonly DerObjectIdentifier TelephoneNumber = X509ObjectIdentifiers.id_at_telephoneNumber;
+
+        /**
+         * id-at-name
+         */
+        public static readonly DerObjectIdentifier Name = X509ObjectIdentifiers.id_at_name;
+
+        /**
+        * Email address (RSA PKCS#9 extension) - IA5String.
+        * <p>Note: if you're trying to be ultra orthodox, don't use this! It shouldn't be in here.</p>
+        */
+        public static readonly DerObjectIdentifier EmailAddress = PkcsObjectIdentifiers.Pkcs9AtEmailAddress;
+
+        /**
+        * more from PKCS#9
+        */
+        public static readonly DerObjectIdentifier UnstructuredName = PkcsObjectIdentifiers.Pkcs9AtUnstructuredName;
+        public static readonly DerObjectIdentifier UnstructuredAddress = PkcsObjectIdentifiers.Pkcs9AtUnstructuredAddress;
+
+        /**
+        * email address in Verisign certificates
+        */
+        public static readonly DerObjectIdentifier E = EmailAddress;
+
+        /*
+        * others...
+        */
+        public static readonly DerObjectIdentifier DC = new DerObjectIdentifier("0.9.2342.19200300.100.1.25");
+
+        /**
+        * LDAP User id.
+        */
+        public static readonly DerObjectIdentifier UID = new DerObjectIdentifier("0.9.2342.19200300.100.1.1");
+
+        /**
+        * determines whether or not strings should be processed and printed
+        * from back to front.
+        */
+//        public static bool DefaultReverse = false;
+        public static bool DefaultReverse
+        {
+            get { return defaultReverse[0]; }
+            set { defaultReverse[0] = value; }
+        }
+
+        private static readonly bool[] defaultReverse = { false };
+
+#if SILVERLIGHT
+        /**
+        * default look up table translating OID values into their common symbols following
+        * the convention in RFC 2253 with a few extras
+        */
+        public static readonly IDictionary DefaultSymbols = Platform.CreateHashtable();
+
+        /**
+         * look up table translating OID values into their common symbols following the convention in RFC 2253
+         */
+        public static readonly IDictionary RFC2253Symbols = Platform.CreateHashtable();
+
+        /**
+         * look up table translating OID values into their common symbols following the convention in RFC 1779
+         *
+         */
+        public static readonly IDictionary RFC1779Symbols = Platform.CreateHashtable();
+
+        /**
+        * look up table translating common symbols into their OIDS.
+        */
+        public static readonly IDictionary DefaultLookup = Platform.CreateHashtable();
+#else
+        /**
+        * default look up table translating OID values into their common symbols following
+        * the convention in RFC 2253 with a few extras
+        */
+        public static readonly Hashtable DefaultSymbols = new Hashtable();
+
+        /**
+         * look up table translating OID values into their common symbols following the convention in RFC 2253
+         */
+        public static readonly Hashtable RFC2253Symbols = new Hashtable();
+
+        /**
+         * look up table translating OID values into their common symbols following the convention in RFC 1779
+         *
+         */
+        public static readonly Hashtable RFC1779Symbols = new Hashtable();
+
+        /**
+        * look up table translating common symbols into their OIDS.
+        */
+        public static readonly Hashtable DefaultLookup = new Hashtable();
+#endif
+
+        static X509Name()
+        {
+            DefaultSymbols.Add(C, "C");
+            DefaultSymbols.Add(O, "O");
+            DefaultSymbols.Add(T, "T");
+            DefaultSymbols.Add(OU, "OU");
+            DefaultSymbols.Add(CN, "CN");
+            DefaultSymbols.Add(L, "L");
+            DefaultSymbols.Add(ST, "ST");
+            DefaultSymbols.Add(SerialNumber, "SERIALNUMBER");
+            DefaultSymbols.Add(EmailAddress, "E");
+            DefaultSymbols.Add(DC, "DC");
+            DefaultSymbols.Add(UID, "UID");
+            DefaultSymbols.Add(Street, "STREET");
+            DefaultSymbols.Add(Surname, "SURNAME");
+            DefaultSymbols.Add(GivenName, "GIVENNAME");
+            DefaultSymbols.Add(Initials, "INITIALS");
+            DefaultSymbols.Add(Generation, "GENERATION");
+            DefaultSymbols.Add(UnstructuredAddress, "unstructuredAddress");
+            DefaultSymbols.Add(UnstructuredName, "unstructuredName");
+            DefaultSymbols.Add(UniqueIdentifier, "UniqueIdentifier");
+            DefaultSymbols.Add(DnQualifier, "DN");
+            DefaultSymbols.Add(Pseudonym, "Pseudonym");
+            DefaultSymbols.Add(PostalAddress, "PostalAddress");
+            DefaultSymbols.Add(NameAtBirth, "NameAtBirth");
+            DefaultSymbols.Add(CountryOfCitizenship, "CountryOfCitizenship");
+            DefaultSymbols.Add(CountryOfResidence, "CountryOfResidence");
+            DefaultSymbols.Add(Gender, "Gender");
+            DefaultSymbols.Add(PlaceOfBirth, "PlaceOfBirth");
+            DefaultSymbols.Add(DateOfBirth, "DateOfBirth");
+            DefaultSymbols.Add(PostalCode, "PostalCode");
+            DefaultSymbols.Add(BusinessCategory, "BusinessCategory");
+            DefaultSymbols.Add(TelephoneNumber, "TelephoneNumber");
+
+            RFC2253Symbols.Add(C, "C");
+            RFC2253Symbols.Add(O, "O");
+            RFC2253Symbols.Add(OU, "OU");
+            RFC2253Symbols.Add(CN, "CN");
+            RFC2253Symbols.Add(L, "L");
+            RFC2253Symbols.Add(ST, "ST");
+            RFC2253Symbols.Add(Street, "STREET");
+            RFC2253Symbols.Add(DC, "DC");
+            RFC2253Symbols.Add(UID, "UID");
+
+            RFC1779Symbols.Add(C, "C");
+            RFC1779Symbols.Add(O, "O");
+            RFC1779Symbols.Add(OU, "OU");
+            RFC1779Symbols.Add(CN, "CN");
+            RFC1779Symbols.Add(L, "L");
+            RFC1779Symbols.Add(ST, "ST");
+            RFC1779Symbols.Add(Street, "STREET");
+
+            DefaultLookup.Add("c", C);
+            DefaultLookup.Add("o", O);
+            DefaultLookup.Add("t", T);
+            DefaultLookup.Add("ou", OU);
+            DefaultLookup.Add("cn", CN);
+            DefaultLookup.Add("l", L);
+            DefaultLookup.Add("st", ST);
+            DefaultLookup.Add("serialnumber", SerialNumber);
+            DefaultLookup.Add("street", Street);
+            DefaultLookup.Add("emailaddress", E);
+            DefaultLookup.Add("dc", DC);
+            DefaultLookup.Add("e", E);
+            DefaultLookup.Add("uid", UID);
+            DefaultLookup.Add("surname", Surname);
+            DefaultLookup.Add("givenname", GivenName);
+            DefaultLookup.Add("initials", Initials);
+            DefaultLookup.Add("generation", Generation);
+            DefaultLookup.Add("unstructuredaddress", UnstructuredAddress);
+            DefaultLookup.Add("unstructuredname", UnstructuredName);
+            DefaultLookup.Add("uniqueidentifier", UniqueIdentifier);
+            DefaultLookup.Add("dn", DnQualifier);
+            DefaultLookup.Add("pseudonym", Pseudonym);
+            DefaultLookup.Add("postaladdress", PostalAddress);
+            DefaultLookup.Add("nameofbirth", NameAtBirth);
+            DefaultLookup.Add("countryofcitizenship", CountryOfCitizenship);
+            DefaultLookup.Add("countryofresidence", CountryOfResidence);
+            DefaultLookup.Add("gender", Gender);
+            DefaultLookup.Add("placeofbirth", PlaceOfBirth);
+            DefaultLookup.Add("dateofbirth", DateOfBirth);
+            DefaultLookup.Add("postalcode", PostalCode);
+            DefaultLookup.Add("businesscategory", BusinessCategory);
+            DefaultLookup.Add("telephonenumber", TelephoneNumber);
+        }
+
+        private readonly IList ordering = Platform.CreateArrayList();
+        private readonly X509NameEntryConverter converter;
+
+        private IList		    values = Platform.CreateArrayList();
+        private IList           added = Platform.CreateArrayList();
+        private Asn1Sequence	seq;
+
+        /**
+        * Return a X509Name based on the passed in tagged object.
+        *
+        * @param obj tag object holding name.
+        * @param explicitly true if explicitly tagged false otherwise.
+        * @return the X509Name
+        */
+        public static X509Name GetInstance(
+            Asn1TaggedObject	obj,
+            bool				explicitly)
+        {
+            return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
+        }
+
+        public static X509Name GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is X509Name)
+                return (X509Name)obj;
+
+            if (obj != null)
+                return new X509Name(Asn1Sequence.GetInstance(obj));
+
+            throw new ArgumentException("null object in factory", "obj");
+        }
+
+        protected X509Name()
+        {
+        }
+
+        /**
+        * Constructor from Asn1Sequence
+        *
+        * the principal will be a list of constructed sets, each containing an (OID, string) pair.
+        */
+        protected X509Name(
+            Asn1Sequence seq)
+        {
+            this.seq = seq;
+
+            foreach (Asn1Encodable asn1Obj in seq)
+            {
+                Asn1Set asn1Set = Asn1Set.GetInstance(asn1Obj.ToAsn1Object());
+
+                for (int i = 0; i < asn1Set.Count; i++)
+                {
+                    Asn1Sequence s = Asn1Sequence.GetInstance(asn1Set[i].ToAsn1Object());
+
+                    if (s.Count != 2)
+                        throw new ArgumentException("badly sized pair");
+
+                    ordering.Add(DerObjectIdentifier.GetInstance(s[0].ToAsn1Object()));
+
+                    Asn1Object derValue = s[1].ToAsn1Object();
+                    if (derValue is IAsn1String && !(derValue is DerUniversalString))
+                    {
+                        string v = ((IAsn1String)derValue).GetString();
+                        if (v.StartsWith("#"))
+                        {
+                            v = "\\" + v;
+                        }
+
+                        values.Add(v);
+                    }
+                    else
+                    {
+                        values.Add("#" + Hex.ToHexString(derValue.GetEncoded()));
+                    }
+
+                    added.Add(i != 0);
+                }
+            }
+        }
+
+        /**
+        * Constructor from a table of attributes with ordering.
+        * <p>
+        * it's is assumed the table contains OID/string pairs, and the contents
+        * of the table are copied into an internal table as part of the
+        * construction process. The ordering ArrayList should contain the OIDs
+        * in the order they are meant to be encoded or printed in ToString.</p>
+        */
+        public X509Name(
+            IList       ordering,
+            IDictionary attributes)
+            : this(ordering, attributes, new X509DefaultEntryConverter())
+        {
+        }
+
+        /**
+        * Constructor from a table of attributes with ordering.
+        * <p>
+        * it's is assumed the table contains OID/string pairs, and the contents
+        * of the table are copied into an internal table as part of the
+        * construction process. The ordering ArrayList should contain the OIDs
+        * in the order they are meant to be encoded or printed in ToString.</p>
+        * <p>
+        * The passed in converter will be used to convert the strings into their
+        * ASN.1 counterparts.</p>
+        */
+        public X509Name(
+            IList                   ordering,
+            IDictionary             attributes,
+            X509NameEntryConverter	converter)
+        {
+            this.converter = converter;
+
+            foreach (DerObjectIdentifier oid in ordering)
+            {
+                object attribute = attributes[oid];
+                if (attribute == null)
+                {
+                    throw new ArgumentException("No attribute for object id - " + oid + " - passed to distinguished name");
+                }
+
+                this.ordering.Add(oid);
+                this.added.Add(false);
+                this.values.Add(attribute); // copy the hash table
+            }
+        }
+
+        /**
+        * Takes two vectors one of the oids and the other of the values.
+        */
+        public X509Name(
+            IList   oids,
+            IList   values)
+            : this(oids, values, new X509DefaultEntryConverter())
+        {
+        }
+
+        /**
+        * Takes two vectors one of the oids and the other of the values.
+        * <p>
+        * The passed in converter will be used to convert the strings into their
+        * ASN.1 counterparts.</p>
+        */
+        public X509Name(
+            IList			    	oids,
+            IList		    		values,
+            X509NameEntryConverter	converter)
+        {
+            this.converter = converter;
+
+            if (oids.Count != values.Count)
+            {
+                throw new ArgumentException("'oids' must be same length as 'values'.");
+            }
+
+            for (int i = 0; i < oids.Count; i++)
+            {
+                this.ordering.Add(oids[i]);
+                this.values.Add(values[i]);
+                this.added.Add(false);
+            }
+        }
+
+//		private static bool IsEncoded(
+//			string s)
+//		{
+//			return s.StartsWith("#");
+//		}
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes.
+        */
+        public X509Name(
+            string dirName)
+            : this(DefaultReverse, (IDictionary)DefaultLookup, dirName)
+        {
+        }
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes with each
+        * string value being converted to its associated ASN.1 type using the passed
+        * in converter.
+        */
+        public X509Name(
+            string					dirName,
+            X509NameEntryConverter	converter)
+            : this(DefaultReverse, DefaultLookup, dirName, converter)
+        {
+        }
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes. If reverse
+        * is true, create the encoded version of the sequence starting from the
+        * last element in the string.
+        */
+        public X509Name(
+            bool	reverse,
+            string	dirName)
+            : this(reverse, (IDictionary)DefaultLookup, dirName)
+        {
+        }
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes with each
+        * string value being converted to its associated ASN.1 type using the passed
+        * in converter. If reverse is true the ASN.1 sequence representing the DN will
+        * be built by starting at the end of the string, rather than the start.
+        */
+        public X509Name(
+            bool					reverse,
+            string					dirName,
+            X509NameEntryConverter	converter)
+            : this(reverse, DefaultLookup, dirName, converter)
+        {
+        }
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes. lookUp
+        * should provide a table of lookups, indexed by lowercase only strings and
+        * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+        * will be processed automatically.
+        * <br/>
+        * If reverse is true, create the encoded version of the sequence
+        * starting from the last element in the string.
+        * @param reverse true if we should start scanning from the end (RFC 2553).
+        * @param lookUp table of names and their oids.
+        * @param dirName the X.500 string to be parsed.
+        */
+        public X509Name(
+            bool		reverse,
+            IDictionary lookUp,
+            string		dirName)
+            : this(reverse, lookUp, dirName, new X509DefaultEntryConverter())
+        {
+        }
+
+        private DerObjectIdentifier DecodeOid(
+            string		name,
+            IDictionary lookUp)
+        {
+            if (Platform.ToUpperInvariant(name).StartsWith("OID."))
+            {
+                return new DerObjectIdentifier(name.Substring(4));
+            }
+            else if (name[0] >= '0' && name[0] <= '9')
+            {
+                return new DerObjectIdentifier(name);
+            }
+
+            DerObjectIdentifier oid = (DerObjectIdentifier)lookUp[Platform.ToLowerInvariant(name)];
+            if (oid == null)
+            {
+                throw new ArgumentException("Unknown object id - " + name + " - passed to distinguished name");
+            }
+
+            return oid;
+        }
+
+        /**
+        * Takes an X509 dir name as a string of the format "C=AU, ST=Victoria", or
+        * some such, converting it into an ordered set of name attributes. lookUp
+        * should provide a table of lookups, indexed by lowercase only strings and
+        * yielding a DerObjectIdentifier, other than that OID. and numeric oids
+        * will be processed automatically. The passed in converter is used to convert the
+        * string values to the right of each equals sign to their ASN.1 counterparts.
+        * <br/>
+        * @param reverse true if we should start scanning from the end, false otherwise.
+        * @param lookUp table of names and oids.
+        * @param dirName the string dirName
+        * @param converter the converter to convert string values into their ASN.1 equivalents
+        */
+        public X509Name(
+            bool					reverse,
+            IDictionary				lookUp,
+            string					dirName,
+            X509NameEntryConverter	converter)
+        {
+            this.converter = converter;
+            X509NameTokenizer nTok = new X509NameTokenizer(dirName);
+
+            while (nTok.HasMoreTokens())
+            {
+                string token = nTok.NextToken();
+                int index = token.IndexOf('=');
+
+                if (index == -1)
+                {
+                    throw new ArgumentException("badly formated directory string");
+                }
+
+                string name = token.Substring(0, index);
+                string value = token.Substring(index + 1);
+                DerObjectIdentifier	oid = DecodeOid(name, lookUp);
+
+                if (value.IndexOf('+') > 0)
+                {
+                    X509NameTokenizer vTok = new X509NameTokenizer(value, '+');
+                    string v = vTok.NextToken();
+
+                    this.ordering.Add(oid);
+                    this.values.Add(v);
+                    this.added.Add(false);
+
+                    while (vTok.HasMoreTokens())
+                    {
+                        string sv = vTok.NextToken();
+                        int ndx = sv.IndexOf('=');
+
+                        string nm = sv.Substring(0, ndx);
+                        string vl = sv.Substring(ndx + 1);
+                        this.ordering.Add(DecodeOid(nm, lookUp));
+                        this.values.Add(vl);
+                        this.added.Add(true);
+                    }
+                }
+                else
+                {
+                    this.ordering.Add(oid);
+                    this.values.Add(value);
+                    this.added.Add(false);
+                }
+            }
+
+            if (reverse)
+            {
+//				this.ordering.Reverse();
+//				this.values.Reverse();
+//				this.added.Reverse();
+                IList o = Platform.CreateArrayList();
+                IList v = Platform.CreateArrayList();
+                IList a = Platform.CreateArrayList();
+                int count = 1;
+
+                for (int i = 0; i < this.ordering.Count; i++)
+                {
+                    if (!((bool) this.added[i]))
+                    {
+                        count = 0;
+                    }
+
+                    int index = count++;
+
+                    o.Insert(index, this.ordering[i]);
+                    v.Insert(index, this.values[i]);
+                    a.Insert(index, this.added[i]);
+                }
+
+                this.ordering = o;
+                this.values = v;
+                this.added = a;
+            }
+        }
+
+        /**
+        * return an IList of the oids in the name, in the order they were found.
+        */
+        public IList GetOidList()
+        {
+            return Platform.CreateArrayList(ordering);
+        }
+
+        /**
+        * return an IList of the values found in the name, in the order they
+        * were found.
+        */
+        public IList GetValueList()
+        {
+            return GetValueList(null);
+        }
+
+        /**
+         * return an IList of the values found in the name, in the order they
+         * were found, with the DN label corresponding to passed in oid.
+         */
+        public IList GetValueList(DerObjectIdentifier oid)
+        {
+            IList v = Platform.CreateArrayList();
+            for (int i = 0; i != values.Count; i++)
+            {
+                if (null == oid || oid.Equals(ordering[i]))
+                {
+                    string val = (string)values[i];
+
+                    if (val.StartsWith("\\#"))
+                    {
+                        val = val.Substring(1);
+                    }
+
+                    v.Add(val);
+                }
+            }
+            return v;
+        }
+
+        public override Asn1Object ToAsn1Object()
+        {
+            if (seq == null)
+            {
+                Asn1EncodableVector vec = new Asn1EncodableVector();
+                Asn1EncodableVector sVec = new Asn1EncodableVector();
+                DerObjectIdentifier lstOid = null;
+
+                for (int i = 0; i != ordering.Count; i++)
+                {
+                    DerObjectIdentifier oid = (DerObjectIdentifier)ordering[i];
+                    string str = (string)values[i];
+
+                    if (lstOid == null
+                        || ((bool)this.added[i]))
+                    {
+                    }
+                    else
+                    {
+                        vec.Add(new DerSet(sVec));
+                        sVec = new Asn1EncodableVector();
+                    }
+
+                    sVec.Add(
+                        new DerSequence(
+                            oid,
+                            converter.GetConvertedValue(oid, str)));
+
+                    lstOid = oid;
+                }
+
+                vec.Add(new DerSet(sVec));
+
+                seq = new DerSequence(vec);
+            }
+
+            return seq;
+        }
+
+        /// <param name="other">The X509Name object to test equivalency against.</param>
+        /// <param name="inOrder">If true, the order of elements must be the same,
+        /// as well as the values associated with each element.</param>
+        public bool Equivalent(
+            X509Name	other,
+            bool		inOrder)
+        {
+            if (!inOrder)
+                return this.Equivalent(other);
+
+            if (other == null)
+                return false;
+
+            if (other == this)
+                return true;
+
+            int orderingSize = ordering.Count;
+
+            if (orderingSize != other.ordering.Count)
+                return false;
+
+            for (int i = 0; i < orderingSize; i++)
+            {
+                DerObjectIdentifier oid = (DerObjectIdentifier) ordering[i];
+                DerObjectIdentifier oOid = (DerObjectIdentifier) other.ordering[i];
+
+                if (!oid.Equals(oOid))
+                    return false;
+
+                string val = (string) values[i];
+                string oVal = (string) other.values[i];
+
+                if (!equivalentStrings(val, oVal))
+                    return false;
+            }
+
+            return true;
+        }
+
+        /**
+         * test for equivalence - note: case is ignored.
+         */
+        public bool Equivalent(
+            X509Name other)
+        {
+            if (other == null)
+                return false;
+
+            if (other == this)
+                return true;
+
+            int orderingSize = ordering.Count;
+
+            if (orderingSize != other.ordering.Count)
+            {
+                return false;
+            }
+
+            bool[] indexes = new bool[orderingSize];
+            int start, end, delta;
+
+            if (ordering[0].Equals(other.ordering[0]))   // guess forward
+            {
+                start = 0;
+                end = orderingSize;
+                delta = 1;
+            }
+            else  // guess reversed - most common problem
+            {
+                start = orderingSize - 1;
+                end = -1;
+                delta = -1;
+            }
+
+            for (int i = start; i != end; i += delta)
+            {
+                bool found = false;
+                DerObjectIdentifier  oid = (DerObjectIdentifier)ordering[i];
+                string value = (string)values[i];
+
+                for (int j = 0; j < orderingSize; j++)
+                {
+                    if (indexes[j])
+                    {
+                        continue;
+                    }
+
+                    DerObjectIdentifier oOid = (DerObjectIdentifier)other.ordering[j];
+
+                    if (oid.Equals(oOid))
+                    {
+                        string oValue = (string)other.values[j];
+
+                        if (equivalentStrings(value, oValue))
+                        {
+                            indexes[j] = true;
+                            found      = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (!found)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private static bool equivalentStrings(
+            string	s1,
+            string	s2)
+        {
+            string v1 = canonicalize(s1);
+            string v2 = canonicalize(s2);
+
+            if (!v1.Equals(v2))
+            {
+                v1 = stripInternalSpaces(v1);
+                v2 = stripInternalSpaces(v2);
+
+                if (!v1.Equals(v2))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private static string canonicalize(
+            string s)
+        {
+            string v = Platform.ToLowerInvariant(s).Trim();
+
+            if (v.StartsWith("#"))
+            {
+                Asn1Object obj = decodeObject(v);
+
+                if (obj is IAsn1String)
+                {
+                    v = Platform.ToLowerInvariant(((IAsn1String)obj).GetString()).Trim();
+                }
+            }
+
+            return v;
+        }
+
+        private static Asn1Object decodeObject(
+            string v)
+        {
+            try
+            {
+                return Asn1Object.FromByteArray(Hex.Decode(v.Substring(1)));
+            }
+            catch (IOException e)
+            {
+                throw new InvalidOperationException("unknown encoding in name: " + e.Message, e);
+            }
+        }
+
+        private static string stripInternalSpaces(
+            string str)
+        {
+            StringBuilder res = new StringBuilder();
+
+            if (str.Length != 0)
+            {
+                char c1 = str[0];
+
+                res.Append(c1);
+
+                for (int k = 1; k < str.Length; k++)
+                {
+                    char c2 = str[k];
+                    if (!(c1 == ' ' && c2 == ' '))
+                    {
+                        res.Append(c2);
+                    }
+                    c1 = c2;
+                }
+            }
+
+            return res.ToString();
+        }
+
+        private void AppendValue(
+            StringBuilder		buf,
+            IDictionary         oidSymbols,
+            DerObjectIdentifier	oid,
+            string				val)
+        {
+            string sym = (string)oidSymbols[oid];
+
+            if (sym != null)
+            {
+                buf.Append(sym);
+            }
+            else
+            {
+                buf.Append(oid.Id);
+            }
+
+            buf.Append('=');
+
+            int index = buf.Length;
+
+            buf.Append(val);
+
+            int end = buf.Length;
+
+            if (val.StartsWith("\\#"))
+            {
+                index += 2;
+            }
+
+            while (index != end)
+            {
+                if ((buf[index] == ',')
+                || (buf[index] == '"')
+                || (buf[index] == '\\')
+                || (buf[index] == '+')
+                || (buf[index] == '=')
+                || (buf[index] == '<')
+                || (buf[index] == '>')
+                || (buf[index] == ';'))
+                {
+                    buf.Insert(index++, "\\");
+                    end++;
+                }
+
+                index++;
+            }
+        }
+
+        /**
+        * convert the structure to a string - if reverse is true the
+        * oids and values are listed out starting with the last element
+        * in the sequence (ala RFC 2253), otherwise the string will begin
+        * with the first element of the structure. If no string definition
+        * for the oid is found in oidSymbols the string value of the oid is
+        * added. Two standard symbol tables are provided DefaultSymbols, and
+        * RFC2253Symbols as part of this class.
+        *
+        * @param reverse if true start at the end of the sequence and work back.
+        * @param oidSymbols look up table strings for oids.
+        */
+        public string ToString(
+            bool		reverse,
+            IDictionary oidSymbols)
+        {
+#if SILVERLIGHT
+            List<object> components = new List<object>();
+#else
+            ArrayList components = new ArrayList();
+#endif
+
+            StringBuilder ava = null;
+
+            for (int i = 0; i < ordering.Count; i++)
+            {
+                if ((bool) added[i])
+                {
+                    ava.Append('+');
+                    AppendValue(ava, oidSymbols,
+                        (DerObjectIdentifier)ordering[i],
+                        (string)values[i]);
+                }
+                else
+                {
+                    ava = new StringBuilder();
+                    AppendValue(ava, oidSymbols,
+                        (DerObjectIdentifier)ordering[i],
+                        (string)values[i]);
+                    components.Add(ava);
+                }
+            }
+
+            if (reverse)
+            {
+                components.Reverse();
+            }
+
+            StringBuilder buf = new StringBuilder();
+
+            if (components.Count > 0)
+            {
+                buf.Append(components[0].ToString());
+
+                for (int i = 1; i < components.Count; ++i)
+                {
+                    buf.Append(',');
+                    buf.Append(components[i].ToString());
+                }
+            }
+
+            return buf.ToString();
+        }
+
+        public override string ToString()
+        {
+            return ToString(DefaultReverse, (IDictionary)DefaultSymbols);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509NameEntryConverter.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509NameEntryConverter.cs
new file mode 100644
index 0000000..5872656
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509NameEntryConverter.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * It turns out that the number of standard ways the fields in a DN should be
+     * encoded into their ASN.1 counterparts is rapidly approaching the
+     * number of machines on the internet. By default the X509Name class
+     * will produce UTF8Strings in line with the current recommendations (RFC 3280).
+     * <p>
+     * An example of an encoder look like below:
+     * <pre>
+     * public class X509DirEntryConverter
+     *     : X509NameEntryConverter
+     * {
+     *     public Asn1Object GetConvertedValue(
+     *         DerObjectIdentifier  oid,
+     *         string               value)
+     *     {
+     *         if (str.Length() != 0 && str.charAt(0) == '#')
+     *         {
+     *             return ConvertHexEncoded(str, 1);
+     *         }
+     *         if (oid.Equals(EmailAddress))
+     *         {
+     *             return new DerIA5String(str);
+     *         }
+     *         else if (CanBePrintable(str))
+     *         {
+     *             return new DerPrintableString(str);
+     *         }
+     *         else if (CanBeUTF8(str))
+     *         {
+     *             return new DerUtf8String(str);
+     *         }
+     *         else
+     *         {
+     *             return new DerBmpString(str);
+     *         }
+     *     }
+     * }
+	 * </pre>
+	 * </p>
+     */
+    public abstract class X509NameEntryConverter
+    {
+        /**
+         * Convert an inline encoded hex string rendition of an ASN.1
+         * object back into its corresponding ASN.1 object.
+         *
+         * @param str the hex encoded object
+         * @param off the index at which the encoding starts
+         * @return the decoded object
+         */
+        protected Asn1Object ConvertHexEncoded(
+            string	hexString,
+            int		offset)
+        {
+			string str = hexString.Substring(offset);
+
+			return Asn1Object.FromByteArray(Hex.Decode(str));
+        }
+
+		/**
+         * return true if the passed in string can be represented without
+         * loss as a PrintableString, false otherwise.
+         */
+        protected bool CanBePrintable(
+            string str)
+        {
+			return DerPrintableString.IsPrintableString(str);
+        }
+
+		/**
+         * Convert the passed in string value into the appropriate ASN.1
+         * encoded object.
+         *
+         * @param oid the oid associated with the value in the DN.
+         * @param value the value of the particular DN component.
+         * @return the ASN.1 equivalent for the value.
+         */
+        public abstract Asn1Object GetConvertedValue(DerObjectIdentifier oid, string value);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509NameTokenizer.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509NameTokenizer.cs
new file mode 100644
index 0000000..ab55295
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509NameTokenizer.cs
@@ -0,0 +1,104 @@
+using System.Text;
+
+namespace Org.BouncyCastle.Asn1.X509
+{
+    /**
+     * class for breaking up an X500 Name into it's component tokens, ala
+     * java.util.StringTokenizer. We need this class as some of the
+     * lightweight Java environment don't support classes like
+     * StringTokenizer.
+     */
+    public class X509NameTokenizer
+    {
+        private string			value;
+        private int				index;
+        private char			separator;
+        private StringBuilder	buffer = new StringBuilder();
+
+		public X509NameTokenizer(
+            string oid)
+            : this(oid, ',')
+        {
+        }
+
+		public X509NameTokenizer(
+            string	oid,
+            char	separator)
+        {
+            this.value = oid;
+            this.index = -1;
+            this.separator = separator;
+        }
+
+		public bool HasMoreTokens()
+        {
+            return index != value.Length;
+        }
+
+		public string NextToken()
+        {
+            if (index == value.Length)
+            {
+                return null;
+            }
+
+            int end = index + 1;
+            bool quoted = false;
+            bool escaped = false;
+
+			buffer.Remove(0, buffer.Length);
+
+			while (end != value.Length)
+            {
+                char c = value[end];
+
+				if (c == '"')
+                {
+                    if (!escaped)
+                    {
+                        quoted = !quoted;
+                    }
+                    else
+                    {
+                        buffer.Append(c);
+						escaped = false;
+                    }
+                }
+                else
+                {
+                    if (escaped || quoted)
+                    {
+						if (c == '#' && buffer[buffer.Length - 1] == '=')
+						{
+							buffer.Append('\\');
+						}
+						else if (c == '+' && separator != '+')
+						{
+							buffer.Append('\\');
+						}
+						buffer.Append(c);
+                        escaped = false;
+                    }
+                    else if (c == '\\')
+                    {
+                        escaped = true;
+                    }
+                    else if (c == separator)
+                    {
+                        break;
+                    }
+                    else
+                    {
+                        buffer.Append(c);
+                    }
+                }
+
+				end++;
+            }
+
+			index = end;
+
+			return buffer.ToString().Trim();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/X509ObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/x509/X509ObjectIdentifiers.cs
new file mode 100644
index 0000000..f00e314
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/X509ObjectIdentifiers.cs
@@ -0,0 +1,59 @@
+namespace Org.BouncyCastle.Asn1.X509
+{
+    public abstract class X509ObjectIdentifiers
+    {
+        //
+        // base id
+        //
+        internal const string ID = "2.5.4";
+
+		public static readonly DerObjectIdentifier CommonName              = new DerObjectIdentifier(ID + ".3");
+        public static readonly DerObjectIdentifier CountryName             = new DerObjectIdentifier(ID + ".6");
+        public static readonly DerObjectIdentifier LocalityName            = new DerObjectIdentifier(ID + ".7");
+        public static readonly DerObjectIdentifier StateOrProvinceName     = new DerObjectIdentifier(ID + ".8");
+        public static readonly DerObjectIdentifier Organization            = new DerObjectIdentifier(ID + ".10");
+        public static readonly DerObjectIdentifier OrganizationalUnitName  = new DerObjectIdentifier(ID + ".11");
+
+		public static readonly DerObjectIdentifier id_at_telephoneNumber   = new DerObjectIdentifier(ID + ".20");
+		public static readonly DerObjectIdentifier id_at_name              = new DerObjectIdentifier(ID + ".41");
+
+		// id-SHA1 OBJECT IDENTIFIER ::=
+        //   {iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 }    //
+        public static readonly DerObjectIdentifier IdSha1 = new DerObjectIdentifier("1.3.14.3.2.26");
+
+		//
+        // ripemd160 OBJECT IDENTIFIER ::=
+        //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) hashAlgorithm(2) RipeMD-160(1)}
+        //
+        public static readonly DerObjectIdentifier RipeMD160 = new DerObjectIdentifier("1.3.36.3.2.1");
+
+		//
+        // ripemd160WithRSAEncryption OBJECT IDENTIFIER ::=
+        //      {iso(1) identified-organization(3) TeleTrust(36) algorithm(3) signatureAlgorithm(3) rsaSignature(1) rsaSignatureWithripemd160(2) }
+        //
+        public static readonly DerObjectIdentifier RipeMD160WithRsaEncryption = new DerObjectIdentifier("1.3.36.3.3.1.2");
+
+		public static readonly DerObjectIdentifier IdEARsa = new DerObjectIdentifier("2.5.8.1.1");
+
+		// id-pkix
+		public static readonly DerObjectIdentifier IdPkix = new DerObjectIdentifier("1.3.6.1.5.5.7");
+
+		//
+		// private internet extensions
+		//
+		public static readonly DerObjectIdentifier IdPE = new DerObjectIdentifier(IdPkix + ".1");
+
+		//
+		// authority information access
+		//
+		public static readonly DerObjectIdentifier IdAD = new DerObjectIdentifier(IdPkix + ".48");
+		public static readonly DerObjectIdentifier IdADCAIssuers = new DerObjectIdentifier(IdAD + ".2");
+		public static readonly DerObjectIdentifier IdADOcsp = new DerObjectIdentifier(IdAD + ".1");
+
+		//
+		// OID for ocsp and crl uri in AuthorityInformationAccess extension
+		//
+		public static readonly DerObjectIdentifier OcspAccessMethod = IdADOcsp;
+		public static readonly DerObjectIdentifier CrlAccessMethod = IdADCAIssuers;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/BiometricData.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/BiometricData.cs
new file mode 100644
index 0000000..61d7c99
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/BiometricData.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The BiometricData object.
+    * <pre>
+    * BiometricData  ::=  SEQUENCE {
+    *       typeOfBiometricData  TypeOfBiometricData,
+    *       hashAlgorithm        AlgorithmIdentifier,
+    *       biometricDataHash    OCTET STRING,
+    *       sourceDataUri        IA5String OPTIONAL  }
+    * </pre>
+    */
+    public class BiometricData
+        : Asn1Encodable
+    {
+        private readonly TypeOfBiometricData typeOfBiometricData;
+        private readonly AlgorithmIdentifier hashAlgorithm;
+        private readonly Asn1OctetString     biometricDataHash;
+        private readonly DerIA5String        sourceDataUri;
+
+        public static BiometricData GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is BiometricData)
+            {
+                return (BiometricData)obj;
+            }
+
+            if (obj is Asn1Sequence)
+            {
+				return new BiometricData(Asn1Sequence.GetInstance(obj));
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		private BiometricData(
+			Asn1Sequence seq)
+        {
+			typeOfBiometricData = TypeOfBiometricData.GetInstance(seq[0]);
+			hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]);
+			biometricDataHash = Asn1OctetString.GetInstance(seq[2]);
+
+			if (seq.Count > 3)
+			{
+				sourceDataUri = DerIA5String.GetInstance(seq[3]);
+			}
+        }
+
+		public BiometricData(
+            TypeOfBiometricData	typeOfBiometricData,
+            AlgorithmIdentifier	hashAlgorithm,
+            Asn1OctetString		biometricDataHash,
+            DerIA5String		sourceDataUri)
+        {
+            this.typeOfBiometricData = typeOfBiometricData;
+            this.hashAlgorithm = hashAlgorithm;
+            this.biometricDataHash = biometricDataHash;
+            this.sourceDataUri = sourceDataUri;
+        }
+
+        public BiometricData(
+            TypeOfBiometricData	typeOfBiometricData,
+            AlgorithmIdentifier	hashAlgorithm,
+            Asn1OctetString		biometricDataHash)
+        {
+            this.typeOfBiometricData = typeOfBiometricData;
+            this.hashAlgorithm = hashAlgorithm;
+            this.biometricDataHash = biometricDataHash;
+            this.sourceDataUri = null;
+        }
+
+        public TypeOfBiometricData TypeOfBiometricData
+        {
+			get { return typeOfBiometricData; }
+        }
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public Asn1OctetString BiometricDataHash
+		{
+			get { return biometricDataHash; }
+		}
+
+		public DerIA5String SourceDataUri
+		{
+			get { return sourceDataUri; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector seq = new Asn1EncodableVector(
+				typeOfBiometricData, hashAlgorithm, biometricDataHash);
+
+			if (sourceDataUri != null)
+            {
+                seq.Add(sourceDataUri);
+            }
+
+			return new DerSequence(seq);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs
new file mode 100644
index 0000000..86a4eee
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/ETSIQCObjectIdentifiers.cs
@@ -0,0 +1,19 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+	public abstract class EtsiQCObjectIdentifiers
+	{
+		//
+		// base id
+		//
+		public static readonly DerObjectIdentifier IdEtsiQcs                 = new DerObjectIdentifier("0.4.0.1862.1");
+
+		public static readonly DerObjectIdentifier IdEtsiQcsQcCompliance     = new DerObjectIdentifier(IdEtsiQcs+".1");
+		public static readonly DerObjectIdentifier IdEtsiQcsLimitValue       = new DerObjectIdentifier(IdEtsiQcs+".2");
+		public static readonly DerObjectIdentifier IdEtsiQcsRetentionPeriod  = new DerObjectIdentifier(IdEtsiQcs+".3");
+		public static readonly DerObjectIdentifier IdEtsiQcsQcSscd           = new DerObjectIdentifier(IdEtsiQcs+".4");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/Iso4217CurrencyCode.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
new file mode 100644
index 0000000..3300562
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/Iso4217CurrencyCode.cs
@@ -0,0 +1,84 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The Iso4217CurrencyCode object.
+    * <pre>
+    * Iso4217CurrencyCode  ::=  CHOICE {
+    *       alphabetic              PrintableString (SIZE 3), --Recommended
+    *       numeric              INTEGER (1..999) }
+    * -- Alphabetic or numeric currency code as defined in ISO 4217
+    * -- It is recommended that the Alphabetic form is used
+    * </pre>
+    */
+    public class Iso4217CurrencyCode
+        : Asn1Encodable, IAsn1Choice
+    {
+        internal const int AlphabeticMaxSize = 3;
+        internal const int NumericMinSize = 1;
+        internal const int NumericMaxSize = 999;
+
+		internal Asn1Encodable	obj;
+//        internal int			numeric;
+
+		public static Iso4217CurrencyCode GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is Iso4217CurrencyCode)
+            {
+                return (Iso4217CurrencyCode) obj;
+            }
+
+			if (obj is DerInteger)
+            {
+                DerInteger numericobj = DerInteger.GetInstance(obj);
+                int numeric = numericobj.Value.IntValue;
+                return new Iso4217CurrencyCode(numeric);
+            }
+
+			if (obj is DerPrintableString)
+            {
+                DerPrintableString alphabetic = DerPrintableString.GetInstance(obj);
+                return new Iso4217CurrencyCode(alphabetic.GetString());
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+        }
+
+		public Iso4217CurrencyCode(
+            int numeric)
+        {
+            if (numeric > NumericMaxSize || numeric < NumericMinSize)
+            {
+                throw new ArgumentException("wrong size in numeric code : not in (" +NumericMinSize +".."+ NumericMaxSize +")");
+            }
+
+			obj = new DerInteger(numeric);
+        }
+
+		public Iso4217CurrencyCode(
+            string alphabetic)
+        {
+            if (alphabetic.Length > AlphabeticMaxSize)
+            {
+                throw new ArgumentException("wrong size in alphabetic code : max size is " + AlphabeticMaxSize);
+            }
+
+			obj = new DerPrintableString(alphabetic);
+        }
+
+		public bool IsAlphabetic { get { return obj is DerPrintableString; } }
+
+		public string Alphabetic { get { return ((DerPrintableString) obj).GetString(); } }
+
+		public int Numeric { get { return ((DerInteger)obj).Value.IntValue; } }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return obj.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/MonetaryValue.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/MonetaryValue.cs
new file mode 100644
index 0000000..45e1136
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/MonetaryValue.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The MonetaryValue object.
+    * <pre>
+    * MonetaryValue  ::=  SEQUENCE {
+    *       currency              Iso4217CurrencyCode,
+    *       amount               INTEGER,
+    *       exponent             INTEGER }
+    * -- value = amount * 10^exponent
+    * </pre>
+    */
+    public class MonetaryValue
+        : Asn1Encodable
+    {
+        internal Iso4217CurrencyCode	currency;
+        internal DerInteger				amount;
+        internal DerInteger				exponent;
+
+		public static MonetaryValue GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is MonetaryValue)
+            {
+                return (MonetaryValue) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new MonetaryValue(Asn1Sequence.GetInstance(obj));
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		private MonetaryValue(
+            Asn1Sequence seq)
+        {
+			if (seq.Count != 3)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+            currency = Iso4217CurrencyCode.GetInstance(seq[0]);
+            amount = DerInteger.GetInstance(seq[1]);
+            exponent = DerInteger.GetInstance(seq[2]);
+        }
+
+		public MonetaryValue(
+            Iso4217CurrencyCode	currency,
+            int					amount,
+            int					exponent)
+        {
+            this.currency = currency;
+            this.amount = new DerInteger(amount);
+            this.exponent = new DerInteger(exponent);
+        }
+
+		public Iso4217CurrencyCode Currency
+		{
+			get { return currency; }
+		}
+
+		public BigInteger Amount
+		{
+			get { return amount.Value; }
+		}
+
+		public BigInteger Exponent
+		{
+			get { return exponent.Value; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(currency, amount, exponent);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/QCStatement.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/QCStatement.cs
new file mode 100644
index 0000000..317f034
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/QCStatement.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The QCStatement object.
+    * <pre>
+    * QCStatement ::= SEQUENCE {
+    *   statementId        OBJECT IDENTIFIER,
+    *   statementInfo      ANY DEFINED BY statementId OPTIONAL}
+    * </pre>
+    */
+    public class QCStatement
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	qcStatementId;
+        private readonly Asn1Encodable			qcStatementInfo;
+
+		public static QCStatement GetInstance(
+            object obj)
+        {
+            if (obj == null || obj is QCStatement)
+            {
+                return (QCStatement) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+				return new QCStatement(Asn1Sequence.GetInstance(obj));
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		private QCStatement(
+            Asn1Sequence seq)
+        {
+			qcStatementId = DerObjectIdentifier.GetInstance(seq[0]);
+
+			if (seq.Count > 1)
+			{
+				qcStatementInfo = seq[1];
+			}
+        }
+
+		public QCStatement(
+            DerObjectIdentifier qcStatementId)
+        {
+            this.qcStatementId = qcStatementId;
+        }
+
+        public QCStatement(
+            DerObjectIdentifier qcStatementId,
+            Asn1Encodable       qcStatementInfo)
+        {
+            this.qcStatementId = qcStatementId;
+            this.qcStatementInfo = qcStatementInfo;
+        }
+
+		public DerObjectIdentifier StatementId
+		{
+			get { return qcStatementId; }
+		}
+
+		public Asn1Encodable StatementInfo
+		{
+			get { return qcStatementInfo; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector seq = new Asn1EncodableVector(qcStatementId);
+
+			if (qcStatementInfo != null)
+            {
+                seq.Add(qcStatementInfo);
+            }
+
+			return new DerSequence(seq);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs
new file mode 100644
index 0000000..8ebd69e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/RFC3739QCObjectIdentifiers.cs
@@ -0,0 +1,21 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    public sealed class Rfc3739QCObjectIdentifiers
+    {
+		private Rfc3739QCObjectIdentifiers()
+		{
+		}
+
+		//
+        // base id
+        //
+        public static readonly DerObjectIdentifier IdQcs = new DerObjectIdentifier("1.3.6.1.5.5.7.11");
+
+        public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV1 = new DerObjectIdentifier(IdQcs+".1");
+        public static readonly DerObjectIdentifier IdQcsPkixQCSyntaxV2 = new DerObjectIdentifier(IdQcs+".2");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/SemanticsInformation.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/SemanticsInformation.cs
new file mode 100644
index 0000000..72e7cd0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/SemanticsInformation.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The SemanticsInformation object.
+    * <pre>
+    *       SemanticsInformation ::= SEQUENCE {
+    *         semanticsIdentifier        OBJECT IDENTIFIER   OPTIONAL,
+    *         nameRegistrationAuthorities NameRegistrationAuthorities
+    *                                                         OPTIONAL }
+    *         (WITH COMPONENTS {..., semanticsIdentifier PRESENT}|
+    *          WITH COMPONENTS {..., nameRegistrationAuthorities PRESENT})
+    *
+    *     NameRegistrationAuthorities ::=  SEQUENCE SIZE (1..MAX) OF
+    *         GeneralName
+    * </pre>
+    */
+    public class SemanticsInformation
+		: Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	semanticsIdentifier;
+        private readonly GeneralName[]			nameRegistrationAuthorities;
+
+		public static SemanticsInformation GetInstance(
+			object obj)
+        {
+            if (obj == null || obj is SemanticsInformation)
+            {
+                return (SemanticsInformation) obj;
+            }
+
+			if (obj is Asn1Sequence)
+            {
+                return new SemanticsInformation(Asn1Sequence.GetInstance(obj));
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		public SemanticsInformation(
+			Asn1Sequence seq)
+        {
+            if (seq.Count < 1)
+            {
+                throw new ArgumentException("no objects in SemanticsInformation");
+            }
+
+			IEnumerator e = seq.GetEnumerator();
+			e.MoveNext();
+            object obj = e.Current;
+            if (obj is DerObjectIdentifier)
+            {
+                semanticsIdentifier = DerObjectIdentifier.GetInstance(obj);
+                if (e.MoveNext())
+                {
+                    obj  = e.Current;
+                }
+                else
+                {
+                    obj  = null;
+                }
+            }
+
+			if (obj  != null)
+            {
+                Asn1Sequence generalNameSeq = Asn1Sequence.GetInstance(obj );
+                nameRegistrationAuthorities = new GeneralName[generalNameSeq.Count];
+                for (int i= 0; i < generalNameSeq.Count; i++)
+                {
+                    nameRegistrationAuthorities[i] = GeneralName.GetInstance(generalNameSeq[i]);
+                }
+            }
+        }
+
+		public SemanticsInformation(
+            DerObjectIdentifier semanticsIdentifier,
+            GeneralName[] generalNames)
+        {
+            this.semanticsIdentifier = semanticsIdentifier;
+            this.nameRegistrationAuthorities = generalNames;
+        }
+
+		public SemanticsInformation(
+			DerObjectIdentifier semanticsIdentifier)
+        {
+            this.semanticsIdentifier = semanticsIdentifier;
+        }
+
+        public SemanticsInformation(
+			GeneralName[] generalNames)
+        {
+            this.nameRegistrationAuthorities = generalNames;
+        }
+
+		public DerObjectIdentifier SemanticsIdentifier { get { return semanticsIdentifier; } }
+
+		public GeneralName[] GetNameRegistrationAuthorities()
+        {
+            return nameRegistrationAuthorities;
+        }
+
+		public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector seq = new Asn1EncodableVector();
+
+            if (this.semanticsIdentifier != null)
+            {
+                seq.Add(semanticsIdentifier);
+            }
+
+			if (this.nameRegistrationAuthorities != null)
+            {
+                seq.Add(new DerSequence(nameRegistrationAuthorities));
+            }
+
+			return new DerSequence(seq);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/qualified/TypeOfBiometricData.cs b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/TypeOfBiometricData.cs
new file mode 100644
index 0000000..a77e54a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/qualified/TypeOfBiometricData.cs
@@ -0,0 +1,91 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X509.Qualified
+{
+    /**
+    * The TypeOfBiometricData object.
+    * <pre>
+    * TypeOfBiometricData ::= CHOICE {
+    *   predefinedBiometricType   PredefinedBiometricType,
+    *   biometricDataOid          OBJECT IDENTIFIER }
+    *
+    * PredefinedBiometricType ::= INTEGER {
+    *   picture(0),handwritten-signature(1)}
+    *   (picture|handwritten-signature)
+    * </pre>
+    */
+    public class TypeOfBiometricData
+        : Asn1Encodable, IAsn1Choice
+    {
+        public const int Picture				= 0;
+        public const int HandwrittenSignature	= 1;
+
+		internal Asn1Encodable obj;
+
+		public static TypeOfBiometricData GetInstance(
+			object obj)
+        {
+            if (obj == null || obj is TypeOfBiometricData)
+            {
+                return (TypeOfBiometricData) obj;
+            }
+
+			if (obj is DerInteger)
+            {
+                DerInteger predefinedBiometricTypeObj = DerInteger.GetInstance(obj);
+                int predefinedBiometricType = predefinedBiometricTypeObj.Value.IntValue;
+
+				return new TypeOfBiometricData(predefinedBiometricType);
+            }
+
+			if (obj is DerObjectIdentifier)
+            {
+                DerObjectIdentifier BiometricDataOid = DerObjectIdentifier.GetInstance(obj);
+                return new TypeOfBiometricData(BiometricDataOid);
+            }
+
+			throw new ArgumentException("unknown object in GetInstance: " + obj.GetType().FullName, "obj");
+		}
+
+		public TypeOfBiometricData(
+			int predefinedBiometricType)
+        {
+            if (predefinedBiometricType == Picture || predefinedBiometricType == HandwrittenSignature)
+            {
+                obj = new DerInteger(predefinedBiometricType);
+            }
+            else
+            {
+                throw new ArgumentException("unknow PredefinedBiometricType : " + predefinedBiometricType);
+            }
+        }
+
+		public TypeOfBiometricData(
+			DerObjectIdentifier biometricDataOid)
+        {
+            obj = biometricDataOid;
+        }
+
+		public bool IsPredefined
+		{
+			get { return obj is DerInteger; }
+		}
+
+		public int PredefinedBiometricType
+		{
+			get { return ((DerInteger) obj).Value.IntValue; }
+		}
+
+		public DerObjectIdentifier BiometricDataOid
+		{
+			get { return (DerObjectIdentifier) obj; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+        {
+            return obj.ToAsn1Object();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/sigi/NameOrPseudonym.cs b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/NameOrPseudonym.cs
new file mode 100644
index 0000000..222895c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/NameOrPseudonym.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+	/**
+	* Structure for a name or pseudonym.
+	* 
+	* <pre>
+	*       NameOrPseudonym ::= CHOICE {
+	*     	   surAndGivenName SEQUENCE {
+	*     	     surName DirectoryString,
+	*     	     givenName SEQUENCE OF DirectoryString 
+	*         },
+	*     	   pseudonym DirectoryString 
+	*       }
+	* </pre>
+	* 
+	* @see org.bouncycastle.asn1.x509.sigi.PersonalData
+	* 
+	*/
+	public class NameOrPseudonym
+		: Asn1Encodable, IAsn1Choice
+	{
+		private readonly DirectoryString	pseudonym;
+		private readonly DirectoryString	surname;
+		private readonly Asn1Sequence		givenName;
+
+		public static NameOrPseudonym GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is NameOrPseudonym)
+			{
+				return (NameOrPseudonym)obj;
+			}
+
+			if (obj is IAsn1String)
+			{
+				return new NameOrPseudonym(DirectoryString.GetInstance(obj));
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new NameOrPseudonym((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from DERString.
+		* <p/>
+		* The sequence is of type NameOrPseudonym:
+		* <p/>
+		* <pre>
+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* </pre>
+		* @param pseudonym pseudonym value to use.
+		*/
+		public NameOrPseudonym(
+			DirectoryString pseudonym)
+		{
+			this.pseudonym = pseudonym;
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type NameOrPseudonym:
+		* <p/>
+		* <pre>
+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private NameOrPseudonym(
+			Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			if (!(seq[0] is IAsn1String))
+				throw new ArgumentException("Bad object encountered: " + seq[0].GetType().Name);
+
+			surname = DirectoryString.GetInstance(seq[0]);
+			givenName = Asn1Sequence.GetInstance(seq[1]);
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param pseudonym The pseudonym.
+		*/
+		public NameOrPseudonym(
+			string pseudonym)
+			: this(new DirectoryString(pseudonym))
+		{
+		}
+
+		/**
+		 * Constructor from a given details.
+		 *
+		 * @param surname   The surname.
+		 * @param givenName A sequence of directory strings making up the givenName
+		 */
+		public NameOrPseudonym(
+			DirectoryString	surname,
+			Asn1Sequence	givenName)
+		{
+			this.surname = surname;
+			this.givenName = givenName;
+		}
+
+		public DirectoryString Pseudonym
+		{
+			get { return pseudonym; }
+		}
+
+		public DirectoryString Surname
+		{
+			get { return surname; }
+		}
+
+		public DirectoryString[] GetGivenName()
+		{
+			DirectoryString[] items = new DirectoryString[givenName.Count];
+			int count = 0;
+			foreach (object o in givenName)
+			{
+				items[count++] = DirectoryString.GetInstance(o);
+			}
+			return items;
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*       NameOrPseudonym ::= CHOICE {
+		*     	   surAndGivenName SEQUENCE {
+		*     	     surName DirectoryString,
+		*     	     givenName SEQUENCE OF DirectoryString
+		*         },
+		*     	   pseudonym DirectoryString
+		*       }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			if (pseudonym != null)
+			{
+				return pseudonym.ToAsn1Object();
+			}
+
+			return new DerSequence(surname, givenName);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/sigi/PersonalData.cs b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/PersonalData.cs
new file mode 100644
index 0000000..6acdc73
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/PersonalData.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+	/**
+	* Contains personal data for the otherName field in the subjectAltNames
+	* extension.
+	* <p/>
+	* <pre>
+	*     PersonalData ::= SEQUENCE {
+	*       nameOrPseudonym NameOrPseudonym,
+	*       nameDistinguisher [0] INTEGER OPTIONAL,
+	*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+	*       placeOfBirth [2] DirectoryString OPTIONAL,
+	*       gender [3] PrintableString OPTIONAL,
+	*       postalAddress [4] DirectoryString OPTIONAL
+	*       }
+	* </pre>
+	*
+	* @see org.bouncycastle.asn1.x509.sigi.NameOrPseudonym
+	* @see org.bouncycastle.asn1.x509.sigi.SigIObjectIdentifiers
+	*/
+	public class PersonalData
+		: Asn1Encodable
+	{
+		private readonly NameOrPseudonym	nameOrPseudonym;
+		private readonly BigInteger			nameDistinguisher;
+		private readonly DerGeneralizedTime	dateOfBirth;
+		private readonly DirectoryString	placeOfBirth;
+		private readonly string				gender;
+		private readonly DirectoryString	postalAddress;
+
+		public static PersonalData GetInstance(
+			object obj)
+		{
+			if (obj == null || obj is PersonalData)
+			{
+				return (PersonalData) obj;
+			}
+
+			if (obj is Asn1Sequence)
+			{
+				return new PersonalData((Asn1Sequence) obj);
+			}
+
+			throw new ArgumentException("unknown object in factory: " + obj.GetType().Name, "obj");
+		}
+
+		/**
+		* Constructor from Asn1Sequence.
+		* <p/>
+		* The sequence is of type NameOrPseudonym:
+		* <p/>
+		* <pre>
+		*     PersonalData ::= SEQUENCE {
+		*       nameOrPseudonym NameOrPseudonym,
+		*       nameDistinguisher [0] INTEGER OPTIONAL,
+		*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+		*       placeOfBirth [2] DirectoryString OPTIONAL,
+		*       gender [3] PrintableString OPTIONAL,
+		*       postalAddress [4] DirectoryString OPTIONAL
+		*       }
+		* </pre>
+		*
+		* @param seq The ASN.1 sequence.
+		*/
+		private PersonalData(
+			Asn1Sequence seq)
+		{
+			if (seq.Count < 1)
+				throw new ArgumentException("Bad sequence size: " + seq.Count);
+
+			IEnumerator e = seq.GetEnumerator();
+			e.MoveNext();
+
+			nameOrPseudonym = NameOrPseudonym.GetInstance(e.Current);
+
+			while (e.MoveNext())
+			{
+				Asn1TaggedObject o = Asn1TaggedObject.GetInstance(e.Current);
+				int tag = o.TagNo;
+				switch (tag)
+				{
+					case 0:
+						nameDistinguisher = DerInteger.GetInstance(o, false).Value;
+						break;
+					case 1:
+						dateOfBirth = DerGeneralizedTime.GetInstance(o, false);
+						break;
+					case 2:
+						placeOfBirth = DirectoryString.GetInstance(o, true);
+						break;
+					case 3:
+						gender = DerPrintableString.GetInstance(o, false).GetString();
+						break;
+					case 4:
+						postalAddress = DirectoryString.GetInstance(o, true);
+						break;
+					default:
+						throw new ArgumentException("Bad tag number: " + o.TagNo);
+				}
+			}
+		}
+
+		/**
+		* Constructor from a given details.
+		*
+		* @param nameOrPseudonym  Name or pseudonym.
+		* @param nameDistinguisher Name distinguisher.
+		* @param dateOfBirth      Date of birth.
+		* @param placeOfBirth     Place of birth.
+		* @param gender           Gender.
+		* @param postalAddress    Postal Address.
+		*/
+		public PersonalData(
+			NameOrPseudonym		nameOrPseudonym,
+			BigInteger			nameDistinguisher,
+			DerGeneralizedTime	dateOfBirth,
+			DirectoryString		placeOfBirth,
+			string				gender,
+			DirectoryString		postalAddress)
+		{
+			this.nameOrPseudonym = nameOrPseudonym;
+			this.dateOfBirth = dateOfBirth;
+			this.gender = gender;
+			this.nameDistinguisher = nameDistinguisher;
+			this.postalAddress = postalAddress;
+			this.placeOfBirth = placeOfBirth;
+		}
+
+		public NameOrPseudonym NameOrPseudonym
+		{
+			get { return nameOrPseudonym; }
+		}
+
+		public BigInteger NameDistinguisher
+		{
+			get { return nameDistinguisher; }
+		}
+
+		public DerGeneralizedTime DateOfBirth
+		{
+			get { return dateOfBirth; }
+		}
+
+		public DirectoryString PlaceOfBirth
+		{
+			get { return placeOfBirth; }
+		}
+
+		public string Gender
+		{
+			get { return gender; }
+		}
+
+		public DirectoryString PostalAddress
+		{
+			get { return postalAddress; }
+		}
+
+		/**
+		* Produce an object suitable for an Asn1OutputStream.
+		* <p/>
+		* Returns:
+		* <p/>
+		* <pre>
+		*     PersonalData ::= SEQUENCE {
+		*       nameOrPseudonym NameOrPseudonym,
+		*       nameDistinguisher [0] INTEGER OPTIONAL,
+		*       dateOfBirth [1] GeneralizedTime OPTIONAL,
+		*       placeOfBirth [2] DirectoryString OPTIONAL,
+		*       gender [3] PrintableString OPTIONAL,
+		*       postalAddress [4] DirectoryString OPTIONAL
+		*       }
+		* </pre>
+		*
+		* @return an Asn1Object
+		*/
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+			vec.Add(nameOrPseudonym);
+			if (nameDistinguisher != null)
+			{
+				vec.Add(new DerTaggedObject(false, 0, new DerInteger(nameDistinguisher)));
+			}
+			if (dateOfBirth != null)
+			{
+				vec.Add(new DerTaggedObject(false, 1, dateOfBirth));
+			}
+			if (placeOfBirth != null)
+			{
+				vec.Add(new DerTaggedObject(true, 2, placeOfBirth));
+			}
+			if (gender != null)
+			{
+				vec.Add(new DerTaggedObject(false, 3, new DerPrintableString(gender, true)));
+			}
+			if (postalAddress != null)
+			{
+				vec.Add(new DerTaggedObject(true, 4, postalAddress));
+			}
+			return new DerSequence(vec);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x509/sigi/SigIObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/SigIObjectIdentifiers.cs
new file mode 100644
index 0000000..682311a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x509/sigi/SigIObjectIdentifiers.cs
@@ -0,0 +1,49 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X509.SigI
+{
+	/**
+	 * Object Identifiers of SigI specifciation (German Signature Law
+	 * Interoperability specification).
+	 */
+	public sealed class SigIObjectIdentifiers
+	{
+		private SigIObjectIdentifiers()
+		{
+		}
+
+		public readonly static DerObjectIdentifier IdSigI = new DerObjectIdentifier("1.3.36.8");
+
+		/**
+		* Key purpose IDs for German SigI (Signature Interoperability
+		* Specification)
+		*/
+		public readonly static DerObjectIdentifier IdSigIKP = new DerObjectIdentifier(IdSigI + ".2");
+
+		/**
+		* Certificate policy IDs for German SigI (Signature Interoperability
+		* Specification)
+		*/
+		public readonly static DerObjectIdentifier IdSigICP = new DerObjectIdentifier(IdSigI + ".1");
+
+		/**
+		* Other Name IDs for German SigI (Signature Interoperability Specification)
+		*/
+		public readonly static DerObjectIdentifier IdSigION = new DerObjectIdentifier(IdSigI + ".4");
+
+		/**
+		* To be used for for the generation of directory service certificates.
+		*/
+		public static readonly DerObjectIdentifier IdSigIKPDirectoryService = new DerObjectIdentifier(IdSigIKP + ".1");
+
+		/**
+		* ID for PersonalData
+		*/
+		public static readonly DerObjectIdentifier IdSigIONPersonalData = new DerObjectIdentifier(IdSigION + ".1");
+
+		/**
+		* Certificate is conform to german signature law.
+		*/
+		public static readonly DerObjectIdentifier IdSigICPSigConform = new DerObjectIdentifier(IdSigICP + ".1");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/DHDomainParameters.cs b/BouncyCastle.AxCrypt/src/asn1/x9/DHDomainParameters.cs
new file mode 100644
index 0000000..8de8696
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/DHDomainParameters.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+	public class DHDomainParameters
+		: Asn1Encodable
+	{
+		private readonly DerInteger p, g, q, j;
+		private readonly DHValidationParms validationParms;
+
+		public static DHDomainParameters GetInstance(Asn1TaggedObject obj, bool isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		public static DHDomainParameters GetInstance(object obj)
+		{
+			if (obj == null || obj is DHDomainParameters)
+				return (DHDomainParameters)obj;
+
+			if (obj is Asn1Sequence)
+				return new DHDomainParameters((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid DHDomainParameters: " + obj.GetType().FullName, "obj");
+		}
+
+		public DHDomainParameters(DerInteger p, DerInteger g, DerInteger q, DerInteger j,
+			DHValidationParms validationParms)
+		{
+			if (p == null)
+				throw new ArgumentNullException("p");
+			if (g == null)
+				throw new ArgumentNullException("g");
+			if (q == null)
+				throw new ArgumentNullException("q");
+
+			this.p = p;
+			this.g = g;
+			this.q = q;
+			this.j = j;
+			this.validationParms = validationParms;
+		}
+
+		private DHDomainParameters(Asn1Sequence seq)
+		{
+			if (seq.Count < 3 || seq.Count > 5)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			IEnumerator e = seq.GetEnumerator();
+			this.p = DerInteger.GetInstance(GetNext(e));
+			this.g = DerInteger.GetInstance(GetNext(e));
+			this.q = DerInteger.GetInstance(GetNext(e));
+
+			Asn1Encodable next = GetNext(e);
+
+			if (next != null && next is DerInteger)
+			{
+				this.j = DerInteger.GetInstance(next);
+				next = GetNext(e);
+			}
+
+			if (next != null)
+			{
+				this.validationParms = DHValidationParms.GetInstance(next.ToAsn1Object());
+			}
+		}
+
+		private static Asn1Encodable GetNext(IEnumerator e)
+		{
+			return e.MoveNext() ? (Asn1Encodable)e.Current : null;
+		}
+
+		public DerInteger P
+		{
+			get { return this.p; }
+		}
+
+		public DerInteger G
+		{
+			get { return this.g; }
+		}
+
+		public DerInteger Q
+		{
+			get { return this.q; }
+		}
+
+		public DerInteger J
+		{
+			get { return this.j; }
+		}
+
+		public DHValidationParms ValidationParms
+		{
+			get { return this.validationParms; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector(p, g, q);
+
+			if (this.j != null)
+			{
+				v.Add(this.j);
+			}
+
+			if (this.validationParms != null)
+			{
+				v.Add(this.validationParms);
+			}
+
+			return new DerSequence(v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/DHPublicKey.cs b/BouncyCastle.AxCrypt/src/asn1/x9/DHPublicKey.cs
new file mode 100644
index 0000000..1a20a8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/DHPublicKey.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+	public class DHPublicKey
+		: Asn1Encodable
+	{
+		private readonly DerInteger y;
+
+		public static DHPublicKey GetInstance(Asn1TaggedObject obj, bool isExplicit)
+		{
+			return GetInstance(DerInteger.GetInstance(obj, isExplicit));
+		}
+
+		public static DHPublicKey GetInstance(object obj)
+		{
+			if (obj == null || obj is DHPublicKey)
+				return (DHPublicKey)obj;
+
+			if (obj is DerInteger)
+				return new DHPublicKey((DerInteger)obj);
+
+			throw new ArgumentException("Invalid DHPublicKey: " + obj.GetType().FullName, "obj");
+		}
+
+		public DHPublicKey(DerInteger y)
+		{
+			if (y == null)
+				throw new ArgumentNullException("y");
+
+			this.y = y;
+		}
+
+		public DerInteger Y
+		{
+			get { return this.y; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return this.y;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/DHValidationParms.cs b/BouncyCastle.AxCrypt/src/asn1/x9/DHValidationParms.cs
new file mode 100644
index 0000000..a37964c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/DHValidationParms.cs
@@ -0,0 +1,62 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+	public class DHValidationParms
+		: Asn1Encodable
+	{
+		private readonly DerBitString seed;
+		private readonly DerInteger pgenCounter;
+
+		public static DHValidationParms GetInstance(Asn1TaggedObject obj, bool isExplicit)
+		{
+			return GetInstance(Asn1Sequence.GetInstance(obj, isExplicit));
+		}
+
+		public static DHValidationParms GetInstance(object obj)
+		{
+			if (obj == null || obj is DHDomainParameters)
+				return (DHValidationParms)obj;
+
+			if (obj is Asn1Sequence)
+				return new DHValidationParms((Asn1Sequence)obj);
+
+			throw new ArgumentException("Invalid DHValidationParms: " + obj.GetType().FullName, "obj");
+		}
+		
+		public DHValidationParms(DerBitString seed, DerInteger pgenCounter)
+		{
+			if (seed == null)
+				throw new ArgumentNullException("seed");
+			if (pgenCounter == null)
+				throw new ArgumentNullException("pgenCounter");
+
+			this.seed = seed;
+			this.pgenCounter = pgenCounter;
+		}
+
+		private DHValidationParms(Asn1Sequence seq)
+		{
+			if (seq.Count != 2)
+				throw new ArgumentException("Bad sequence size: " + seq.Count, "seq");
+
+			this.seed = DerBitString.GetInstance(seq[0]);
+			this.pgenCounter = DerInteger.GetInstance(seq[1]);
+		}
+
+		public DerBitString Seed
+		{
+			get { return this.seed; }
+		}
+
+		public DerInteger PgenCounter
+		{
+			get { return this.pgenCounter; }
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new DerSequence(seed, pgenCounter);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/ECNamedCurveTable.cs b/BouncyCastle.AxCrypt/src/asn1/x9/ECNamedCurveTable.cs
new file mode 100644
index 0000000..0030d37
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/ECNamedCurveTable.cs
@@ -0,0 +1,118 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * A general class that reads all X9.62 style EC curve tables.
+     */
+    public class ECNamedCurveTable
+    {
+        /**
+         * return a X9ECParameters object representing the passed in named
+         * curve. The routine returns null if the curve is not present.
+         *
+         * @param name the name of the curve requested
+         * @return an X9ECParameters object or null if the curve is not available.
+         */
+        public static X9ECParameters GetByName(string name)
+        {
+            X9ECParameters ecP = X962NamedCurves.GetByName(name);
+
+            if (ecP == null)
+            {
+                ecP = SecNamedCurves.GetByName(name);
+            }
+
+            if (ecP == null)
+            {
+                ecP = TeleTrusTNamedCurves.GetByName(name);
+            }
+
+            if (ecP == null)
+            {
+                ecP = NistNamedCurves.GetByName(name);
+            }
+
+            return ecP;
+        }
+
+        /**
+         * return the object identifier signified by the passed in name. Null
+         * if there is no object identifier associated with name.
+         *
+         * @return the object identifier associated with name, if present.
+         */
+        public static DerObjectIdentifier GetOid(string name)
+        {
+            DerObjectIdentifier oid = X962NamedCurves.GetOid(name);
+
+            if (oid == null)
+            {
+                oid = SecNamedCurves.GetOid(name);
+            }
+
+            if (oid == null)
+            {
+                oid = TeleTrusTNamedCurves.GetOid(name);
+            }
+
+            if (oid == null)
+            {
+                oid = NistNamedCurves.GetOid(name);
+            }
+
+            return oid;
+        }
+
+        /**
+         * return a X9ECParameters object representing the passed in named
+         * curve.
+         *
+         * @param oid the object id of the curve requested
+         * @return an X9ECParameters object or null if the curve is not available.
+         */
+        public static X9ECParameters GetByOid(DerObjectIdentifier oid)
+        {
+            X9ECParameters ecP = X962NamedCurves.GetByOid(oid);
+
+            if (ecP == null)
+            {
+                ecP = SecNamedCurves.GetByOid(oid);
+            }
+
+            if (ecP == null)
+            {
+                ecP = TeleTrusTNamedCurves.GetByOid(oid);
+            }
+
+            // NOTE: All the NIST curves are currently from SEC, so no point in redundant OID lookup
+
+            return ecP;
+        }
+
+        /**
+         * return an enumeration of the names of the available curves.
+         *
+         * @return an enumeration of the names of the available curves.
+         */
+        public static IEnumerable Names
+        {
+            get
+            {
+                IList v = Platform.CreateArrayList();
+                CollectionUtilities.AddRange(v, X962NamedCurves.Names);
+                CollectionUtilities.AddRange(v, SecNamedCurves.Names);
+                CollectionUtilities.AddRange(v, NistNamedCurves.Names);
+                CollectionUtilities.AddRange(v, TeleTrusTNamedCurves.Names);
+                return v;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/KeySpecificInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x9/KeySpecificInfo.cs
new file mode 100644
index 0000000..4629864
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/KeySpecificInfo.cs
@@ -0,0 +1,58 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * ASN.1 def for Diffie-Hellman key exchange KeySpecificInfo structure. See
+     * RFC 2631, or X9.42, for further details.
+     */
+    public class KeySpecificInfo
+        : Asn1Encodable
+    {
+        private DerObjectIdentifier	algorithm;
+        private Asn1OctetString		counter;
+
+		public KeySpecificInfo(
+            DerObjectIdentifier	algorithm,
+            Asn1OctetString		counter)
+        {
+            this.algorithm = algorithm;
+            this.counter = counter;
+        }
+
+		public KeySpecificInfo(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+            algorithm = (DerObjectIdentifier)e.Current;
+            e.MoveNext();
+            counter = (Asn1OctetString)e.Current;
+        }
+
+		public DerObjectIdentifier Algorithm
+        {
+            get { return algorithm; }
+        }
+
+		public Asn1OctetString Counter
+        {
+            get { return counter; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  KeySpecificInfo ::= Sequence {
+         *      algorithm OBJECT IDENTIFIER,
+         *      counter OCTET STRING SIZE (4..4)
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+			return new DerSequence(algorithm, counter);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/OtherInfo.cs b/BouncyCastle.AxCrypt/src/asn1/x9/OtherInfo.cs
new file mode 100644
index 0000000..21863bd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/OtherInfo.cs
@@ -0,0 +1,88 @@
+using System.Collections;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * ANS.1 def for Diffie-Hellman key exchange OtherInfo structure. See
+     * RFC 2631, or X9.42, for further details.
+     */
+    public class OtherInfo
+        : Asn1Encodable
+    {
+        private KeySpecificInfo	keyInfo;
+        private Asn1OctetString	partyAInfo;
+        private Asn1OctetString	suppPubInfo;
+
+		public OtherInfo(
+            KeySpecificInfo	keyInfo,
+            Asn1OctetString	partyAInfo,
+            Asn1OctetString	suppPubInfo)
+        {
+            this.keyInfo = keyInfo;
+            this.partyAInfo = partyAInfo;
+            this.suppPubInfo = suppPubInfo;
+        }
+
+		public OtherInfo(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+            keyInfo = new KeySpecificInfo((Asn1Sequence) e.Current);
+
+			while (e.MoveNext())
+            {
+                DerTaggedObject o = (DerTaggedObject) e.Current;
+
+				if (o.TagNo == 0)
+                {
+                    partyAInfo = (Asn1OctetString) o.GetObject();
+                }
+                else if ((int) o.TagNo == 2)
+                {
+                    suppPubInfo = (Asn1OctetString) o.GetObject();
+                }
+            }
+        }
+
+		public KeySpecificInfo KeyInfo
+        {
+			get { return keyInfo; }
+        }
+
+		public Asn1OctetString PartyAInfo
+        {
+			get { return partyAInfo; }
+        }
+
+		public Asn1OctetString SuppPubInfo
+        {
+            get { return suppPubInfo; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  OtherInfo ::= Sequence {
+         *      keyInfo KeySpecificInfo,
+         *      partyAInfo [0] OCTET STRING OPTIONAL,
+         *      suppPubInfo [2] OCTET STRING
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(keyInfo);
+
+			if (partyAInfo != null)
+            {
+                v.Add(new DerTaggedObject(0, partyAInfo));
+            }
+
+			v.Add(new DerTaggedObject(2, suppPubInfo));
+
+			return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X962NamedCurves.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X962NamedCurves.cs
new file mode 100644
index 0000000..6b76c4e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X962NamedCurves.cs
@@ -0,0 +1,753 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * table of the current named curves defined in X.962 EC-DSA.
+     */
+    public sealed class X962NamedCurves
+    {
+        private X962NamedCurves()
+        {
+        }
+
+        internal class Prime192v1Holder
+            : X9ECParametersHolder
+        {
+            private Prime192v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime192v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("ffffffffffffffffffffffff99def836146bc9b1b4d22831", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp192v1 = new FpCurve(
+                    new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+                    new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+                    new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp192v1,
+                    cFp192v1.DecodePoint(
+                        Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")),
+                    n, h,
+                    Hex.Decode("3045AE6FC8422f64ED579528D38120EAE12196D5"));
+            }
+        }
+
+        internal class Prime192v2Holder
+            : X9ECParametersHolder
+        {
+            private Prime192v2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime192v2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("fffffffffffffffffffffffe5fb1a724dc80418648d8dd31", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp192v2 = new FpCurve(
+                    new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+                    new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+                    new BigInteger("cc22d6dfb95c6b25e49c0d6364a4e5980c393aa21668d953", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp192v2,
+                    cFp192v2.DecodePoint(
+                        Hex.Decode("03eea2bae7e1497842f2de7769cfe9c989c072ad696f48034a")),
+                    n, h,
+                    Hex.Decode("31a92ee2029fd10d901b113e990710f0d21ac6b6"));
+            }
+        }
+
+        internal class Prime192v3Holder
+            : X9ECParametersHolder
+        {
+            private Prime192v3Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime192v3Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("ffffffffffffffffffffffff7a62d031c83f4294f640ec13", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp192v3 = new FpCurve(
+                    new BigInteger("6277101735386680763835789423207666416083908700390324961279"),
+                    new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16),
+                    new BigInteger("22123dc2395a05caa7423daeccc94760a7d462256bd56916", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp192v3,
+                    cFp192v3.DecodePoint(
+                        Hex.Decode("027d29778100c65a1da1783716588dce2b8b4aee8e228f1896")),
+                    n, h,
+                    Hex.Decode("c469684435deb378c4b65ca9591e2a5763059a2e"));
+            }
+        }
+
+        internal class Prime239v1Holder
+            : X9ECParametersHolder
+        {
+            private Prime239v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime239v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff9e5e9a9f5d9071fbd1522688909d0b", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp239v1 = new FpCurve(
+                    new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+                    new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+                    new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp239v1,
+                    cFp239v1.DecodePoint(
+                        Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")),
+                    n, h,
+                    Hex.Decode("e43bb460f0b80cc0c0b075798e948060f8321b7d"));
+            }
+        }
+
+        internal class Prime239v2Holder
+            : X9ECParametersHolder
+        {
+            private Prime239v2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime239v2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("7fffffffffffffffffffffff800000cfa7e8594377d414c03821bc582063", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp239v2 = new FpCurve(
+                    new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+                    new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+                    new BigInteger("617fab6832576cbbfed50d99f0249c3fee58b94ba0038c7ae84c8c832f2c", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp239v2,
+                    cFp239v2.DecodePoint(
+                        Hex.Decode("0238af09d98727705120c921bb5e9e26296a3cdcf2f35757a0eafd87b830e7")),
+                    n, h,
+                    Hex.Decode("e8b4011604095303ca3b8099982be09fcb9ae616"));
+            }
+        }
+
+        internal class Prime239v3Holder
+            : X9ECParametersHolder
+        {
+            private Prime239v3Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime239v3Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("7fffffffffffffffffffffff7fffff975deb41b3a6057c3c432146526551", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp239v3 = new FpCurve(
+                    new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"),
+                    new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16),
+                    new BigInteger("255705fa2a306654b1f4cb03d6a750a30c250102d4988717d9ba15ab6d3e", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp239v3,
+                    cFp239v3.DecodePoint(
+                        Hex.Decode("036768ae8e18bb92cfcf005c949aa2c6d94853d0e660bbf854b1c9505fe95a")),
+                    n, h,
+                    Hex.Decode("7d7374168ffe3471b60a857686a19475d3bfa2ff"));
+            }
+        }
+
+        internal class Prime256v1Holder
+            : X9ECParametersHolder
+        {
+            private Prime256v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Prime256v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 16);
+                BigInteger h = BigInteger.One;
+
+                ECCurve cFp256v1 = new FpCurve(
+                    new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951"),
+                    new BigInteger("ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 16),
+                    new BigInteger("5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    cFp256v1,
+                    cFp256v1.DecodePoint(
+                        Hex.Decode("036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296")),
+                    n, h,
+                    Hex.Decode("c49d360886e704936a6678e1139d26b7819f7e90"));
+            }
+        }
+
+        /*
+         * F2m Curves
+         */
+        internal class C2pnb163v1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb163v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb163v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0400000000000000000001E60FC8821CC74DAEAFC1", 16);
+                BigInteger h = BigInteger.Two;
+
+                ECCurve c2m163v1 = new F2mCurve(
+                    163,
+                    1, 2, 8,
+                    new BigInteger("072546B5435234A422E0789675F432C89435DE5242", 16),
+                    new BigInteger("00C9517D06D5240D3CFF38C74B20B6CD4D6F9DD4D9", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m163v1,
+                    c2m163v1.DecodePoint(
+                        Hex.Decode("0307AF69989546103D79329FCC3D74880F33BBE803CB")),
+                    n, h,
+                    Hex.Decode("D2C0FB15760860DEF1EEF4D696E6768756151754"));
+            }
+        }
+
+        internal class C2pnb163v2Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb163v2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb163v2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFDF64DE1151ADBB78F10A7", 16);
+                BigInteger h = BigInteger.Two;
+
+                ECCurve c2m163v2 = new F2mCurve(
+                    163,
+                    1, 2, 8,
+                    new BigInteger("0108B39E77C4B108BED981ED0E890E117C511CF072", 16),
+                    new BigInteger("0667ACEB38AF4E488C407433FFAE4F1C811638DF20", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m163v2,
+                    c2m163v2.DecodePoint(
+                        Hex.Decode("030024266E4EB5106D0A964D92C4860E2671DB9B6CC5")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb163v3Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb163v3Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb163v3Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("03FFFFFFFFFFFFFFFFFFFE1AEE140F110AFF961309", 16);
+                BigInteger h = BigInteger.Two;
+
+                ECCurve c2m163v3 = new F2mCurve(
+                    163,
+                    1, 2, 8,
+                    new BigInteger("07A526C63D3E25A256A007699F5447E32AE456B50E", 16),
+                    new BigInteger("03F7061798EB99E238FD6F1BF95B48FEEB4854252B", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m163v3,
+                    c2m163v3.DecodePoint(Hex.Decode("0202F9F87B7C574D0BDECF8A22E6524775F98CDEBDCB")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb176w1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb176w1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb176w1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("010092537397ECA4F6145799D62B0A19CE06FE26AD", 16);
+                BigInteger h = BigInteger.ValueOf(0xFF6E);
+
+                ECCurve c2m176w1 = new F2mCurve(
+                    176,
+                    1, 2, 43,
+                    new BigInteger("00E4E6DB2995065C407D9D39B8D0967B96704BA8E9C90B", 16),
+                    new BigInteger("005DDA470ABE6414DE8EC133AE28E9BBD7FCEC0AE0FFF2", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m176w1,
+                    c2m176w1.DecodePoint(
+                        Hex.Decode("038D16C2866798B600F9F08BB4A8E860F3298CE04A5798")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb191v1Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb191v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb191v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("40000000000000000000000004A20E90C39067C893BBB9A5", 16);
+                BigInteger h = BigInteger.Two;
+
+                ECCurve c2m191v1 = new F2mCurve(
+                    191,
+                    9,
+                    new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16),
+                    new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m191v1,
+                    c2m191v1.DecodePoint(
+                        Hex.Decode("0236B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D")),
+                    n, h,
+                    Hex.Decode("4E13CA542744D696E67687561517552F279A8C84"));
+            }
+        }
+
+        internal class C2tnb191v2Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb191v2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb191v2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("20000000000000000000000050508CB89F652824E06B8173", 16);
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve c2m191v2 = new F2mCurve(
+                    191,
+                    9,
+                    new BigInteger("401028774D7777C7B7666D1366EA432071274F89FF01E718", 16),
+                    new BigInteger("0620048D28BCBD03B6249C99182B7C8CD19700C362C46A01", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m191v2,
+                    c2m191v2.DecodePoint(
+                        Hex.Decode("023809B2B7CC1B28CC5A87926AAD83FD28789E81E2C9E3BF10")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb191v3Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb191v3Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb191v3Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("155555555555555555555555610C0B196812BFB6288A3EA3", 16);
+                BigInteger h = BigInteger.ValueOf(6);
+
+                ECCurve c2m191v3 = new F2mCurve(
+                    191,
+                    9,
+                    new BigInteger("6C01074756099122221056911C77D77E77A777E7E7E77FCB", 16),
+                    new BigInteger("71FE1AF926CF847989EFEF8DB459F66394D90F32AD3F15E8", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m191v3,
+                    c2m191v3.DecodePoint(
+                        Hex.Decode("03375D4CE24FDE434489DE8746E71786015009E66E38A926DD")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb208w1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb208w1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb208w1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0101BAF95C9723C57B6C21DA2EFF2D5ED588BDD5717E212F9D", 16);
+                BigInteger h = BigInteger.ValueOf(0xFE48);
+
+                ECCurve c2m208w1 = new F2mCurve(
+                    208,
+                    1, 2, 83,
+                    new BigInteger("0", 16),
+                    new BigInteger("00C8619ED45A62E6212E1160349E2BFA844439FAFC2A3FD1638F9E", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m208w1,
+                    c2m208w1.DecodePoint(
+                        Hex.Decode("0289FDFBE4ABE193DF9559ECF07AC0CE78554E2784EB8C1ED1A57A")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb239v1Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb239v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb239v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("2000000000000000000000000000000F4D42FFE1492A4993F1CAD666E447", 16);
+                BigInteger h = BigInteger.ValueOf(4);
+
+                ECCurve c2m239v1 = new F2mCurve(
+                    239,
+                    36,
+                    new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16),
+                    new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m239v1,
+                    c2m239v1.DecodePoint(
+                        Hex.Decode("0257927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb239v2Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb239v2Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb239v2Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("1555555555555555555555555555553C6F2885259C31E3FCDF154624522D", 16);
+                BigInteger h = BigInteger.ValueOf(6);
+
+                ECCurve c2m239v2 = new F2mCurve(
+                    239,
+                    36,
+                    new BigInteger("4230017757A767FAE42398569B746325D45313AF0766266479B75654E65F", 16),
+                    new BigInteger("5037EA654196CFF0CD82B2C14A2FCF2E3FF8775285B545722F03EACDB74B", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m239v2,
+                    c2m239v2.DecodePoint(
+                        Hex.Decode("0228F9D04E900069C8DC47A08534FE76D2B900B7D7EF31F5709F200C4CA205")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb239v3Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb239v3Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb239v3Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0CCCCCCCCCCCCCCCCCCCCCCCCCCCCCAC4912D2D9DF903EF9888B8A0E4CFF", 16);
+                BigInteger h = BigInteger.ValueOf(10);
+
+                ECCurve c2m239v3 = new F2mCurve(
+                    239,
+                    36,
+                    new BigInteger("01238774666A67766D6676F778E676B66999176666E687666D8766C66A9F", 16),
+                    new BigInteger("6A941977BA9F6A435199ACFC51067ED587F519C5ECB541B8E44111DE1D40", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m239v3,
+                    c2m239v3.DecodePoint(
+                        Hex.Decode("0370F6E9D04D289C4E89913CE3530BFDE903977D42B146D539BF1BDE4E9C92")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb272w1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb272w1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb272w1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0100FAF51354E0E39E4892DF6E319C72C8161603FA45AA7B998A167B8F1E629521", 16);
+                BigInteger h = BigInteger.ValueOf(0xFF06);
+
+                ECCurve c2m272w1 = new F2mCurve(
+                    272,
+                    1, 3, 56,
+                    new BigInteger("0091A091F03B5FBA4AB2CCF49C4EDD220FB028712D42BE752B2C40094DBACDB586FB20", 16),
+                    new BigInteger("7167EFC92BB2E3CE7C8AAAFF34E12A9C557003D7C73A6FAF003F99F6CC8482E540F7", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m272w1,
+                    c2m272w1.DecodePoint(
+                        Hex.Decode("026108BABB2CEEBCF787058A056CBE0CFE622D7723A289E08A07AE13EF0D10D171DD8D")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb304w1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb304w1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb304w1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0101D556572AABAC800101D556572AABAC8001022D5C91DD173F8FB561DA6899164443051D", 16);
+                BigInteger h = BigInteger.ValueOf(0xFE2E);
+
+                ECCurve c2m304w1 = new F2mCurve(
+                    304,
+                    1, 2, 11,
+                    new BigInteger("00FD0D693149A118F651E6DCE6802085377E5F882D1B510B44160074C1288078365A0396C8E681", 16),
+                    new BigInteger("00BDDB97E555A50A908E43B01C798EA5DAA6788F1EA2794EFCF57166B8C14039601E55827340BE", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m304w1,
+                    c2m304w1.DecodePoint(
+                        Hex.Decode("02197B07845E9BE2D96ADB0F5F3C7F2CFFBD7A3EB8B6FEC35C7FD67F26DDF6285A644F740A2614")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb359v1Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb359v1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb359v1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("01AF286BCA1AF286BCA1AF286BCA1AF286BCA1AF286BC9FB8F6B85C556892C20A7EB964FE7719E74F490758D3B", 16);
+                BigInteger h = BigInteger.ValueOf(0x4C);
+
+                ECCurve c2m359v1 = new F2mCurve(
+                    359,
+                    68,
+                    new BigInteger("5667676A654B20754F356EA92017D946567C46675556F19556A04616B567D223A5E05656FB549016A96656A557", 16),
+                    new BigInteger("2472E2D0197C49363F1FE7F5B6DB075D52B6947D135D8CA445805D39BC345626089687742B6329E70680231988", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m359v1,
+                    c2m359v1.DecodePoint(
+                        Hex.Decode("033C258EF3047767E7EDE0F1FDAA79DAEE3841366A132E163ACED4ED2401DF9C6BDCDE98E8E707C07A2239B1B097")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2pnb368w1Holder
+            : X9ECParametersHolder
+        {
+            private C2pnb368w1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2pnb368w1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("010090512DA9AF72B08349D98A5DD4C7B0532ECA51CE03E2D10F3B7AC579BD87E909AE40A6F131E9CFCE5BD967", 16);
+                BigInteger h = BigInteger.ValueOf(0xFF70);
+
+                ECCurve c2m368w1 = new F2mCurve(
+                    368,
+                    1, 2, 85,
+                    new BigInteger("00E0D2EE25095206F5E2A4F9ED229F1F256E79A0E2B455970D8D0D865BD94778C576D62F0AB7519CCD2A1A906AE30D", 16),
+                    new BigInteger("00FC1217D4320A90452C760A58EDCD30C8DD069B3C34453837A34ED50CB54917E1C2112D84D164F444F8F74786046A", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m368w1,
+                    c2m368w1.DecodePoint(
+                        Hex.Decode("021085E2755381DCCCE3C1557AFA10C2F0C0C2825646C5B34A394CBCFA8BC16B22E7E789E927BE216F02E1FB136A5F")),
+                    n, h,
+                    null);
+            }
+        }
+
+        internal class C2tnb431r1Holder
+            : X9ECParametersHolder
+        {
+            private C2tnb431r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new C2tnb431r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                BigInteger n = new BigInteger("0340340340340340340340340340340340340340340340340340340323C313FAB50589703B5EC68D3587FEC60D161CC149C1AD4A91", 16);
+                BigInteger h = BigInteger.ValueOf(0x2760);
+
+                ECCurve c2m431r1 = new F2mCurve(
+                    431,
+                    120,
+                    new BigInteger("1A827EF00DD6FC0E234CAF046C6A5D8A85395B236CC4AD2CF32A0CADBDC9DDF620B0EB9906D0957F6C6FEACD615468DF104DE296CD8F", 16),
+                    new BigInteger("10D9B4A3D9047D8B154359ABFB1B7F5485B04CEB868237DDC9DEDA982A679A5A919B626D4E50A8DD731B107A9962381FB5D807BF2618", 16),
+                    n, h);
+
+                return new X9ECParameters(
+                    c2m431r1,
+                    c2m431r1.DecodePoint(
+                        Hex.Decode("02120FC05D3C67A99DE161D2F4092622FECA701BE4F50F4758714E8A87BBF2A658EF8C21E7C5EFE965361F6C2999C0C247B0DBD70CE6B7")),
+                    n, h,
+                    null);
+            }
+        }
+
+        private static readonly IDictionary objIds = Platform.CreateHashtable();
+        private static readonly IDictionary curves = Platform.CreateHashtable();
+        private static readonly IDictionary names = Platform.CreateHashtable();
+
+        private static void DefineCurve(
+            string					name,
+            DerObjectIdentifier		oid,
+            X9ECParametersHolder	holder)
+        {
+            objIds.Add(name, oid);
+            names.Add(oid, name);
+            curves.Add(oid, holder);
+        }
+
+        static X962NamedCurves()
+        {
+            DefineCurve("prime192v1", X9ObjectIdentifiers.Prime192v1, Prime192v1Holder.Instance);
+            DefineCurve("prime192v2", X9ObjectIdentifiers.Prime192v2, Prime192v2Holder.Instance);
+            DefineCurve("prime192v3", X9ObjectIdentifiers.Prime192v3, Prime192v3Holder.Instance);
+            DefineCurve("prime239v1", X9ObjectIdentifiers.Prime239v1, Prime239v1Holder.Instance);
+            DefineCurve("prime239v2", X9ObjectIdentifiers.Prime239v2, Prime239v2Holder.Instance);
+            DefineCurve("prime239v3", X9ObjectIdentifiers.Prime239v3, Prime239v3Holder.Instance);
+            DefineCurve("prime256v1", X9ObjectIdentifiers.Prime256v1, Prime256v1Holder.Instance);
+            DefineCurve("c2pnb163v1", X9ObjectIdentifiers.C2Pnb163v1, C2pnb163v1Holder.Instance);
+            DefineCurve("c2pnb163v2", X9ObjectIdentifiers.C2Pnb163v2, C2pnb163v2Holder.Instance);
+            DefineCurve("c2pnb163v3", X9ObjectIdentifiers.C2Pnb163v3, C2pnb163v3Holder.Instance);
+            DefineCurve("c2pnb176w1", X9ObjectIdentifiers.C2Pnb176w1, C2pnb176w1Holder.Instance);
+            DefineCurve("c2tnb191v1", X9ObjectIdentifiers.C2Tnb191v1, C2tnb191v1Holder.Instance);
+            DefineCurve("c2tnb191v2", X9ObjectIdentifiers.C2Tnb191v2, C2tnb191v2Holder.Instance);
+            DefineCurve("c2tnb191v3", X9ObjectIdentifiers.C2Tnb191v3, C2tnb191v3Holder.Instance);
+            DefineCurve("c2pnb208w1", X9ObjectIdentifiers.C2Pnb208w1, C2pnb208w1Holder.Instance);
+            DefineCurve("c2tnb239v1", X9ObjectIdentifiers.C2Tnb239v1, C2tnb239v1Holder.Instance);
+            DefineCurve("c2tnb239v2", X9ObjectIdentifiers.C2Tnb239v2, C2tnb239v2Holder.Instance);
+            DefineCurve("c2tnb239v3", X9ObjectIdentifiers.C2Tnb239v3, C2tnb239v3Holder.Instance);
+            DefineCurve("c2pnb272w1", X9ObjectIdentifiers.C2Pnb272w1, C2pnb272w1Holder.Instance);
+            DefineCurve("c2pnb304w1", X9ObjectIdentifiers.C2Pnb304w1, C2pnb304w1Holder.Instance);
+            DefineCurve("c2tnb359v1", X9ObjectIdentifiers.C2Tnb359v1, C2tnb359v1Holder.Instance);
+            DefineCurve("c2pnb368w1", X9ObjectIdentifiers.C2Pnb368w1, C2pnb368w1Holder.Instance);
+            DefineCurve("c2tnb431r1", X9ObjectIdentifiers.C2Tnb431r1, C2tnb431r1Holder.Instance);
+        }
+
+        public static X9ECParameters GetByName(
+            string name)
+        {
+            DerObjectIdentifier oid = (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)];
+
+            return oid == null ? null : GetByOid(oid);
+        }
+
+        /**
+         * return the X9ECParameters object for the named curve represented by
+         * the passed in object identifier. Null if the curve isn't present.
+         *
+         * @param oid an object identifier representing a named curve, if present.
+         */
+        public static X9ECParameters GetByOid(
+            DerObjectIdentifier oid)
+        {
+            X9ECParametersHolder holder = (X9ECParametersHolder) curves[oid];
+
+            return holder == null ? null : holder.Parameters;
+        }
+
+        /**
+         * return the object identifier signified by the passed in name. Null
+         * if there is no object identifier associated with name.
+         *
+         * @return the object identifier associated with name, if present.
+         */
+        public static DerObjectIdentifier GetOid(
+            string name)
+        {
+            return (DerObjectIdentifier)objIds[Platform.ToLowerInvariant(name)];
+        }
+
+        /**
+         * return the named curve name represented by the given object identifier.
+         */
+        public static string GetName(
+            DerObjectIdentifier oid)
+        {
+            return (string) names[oid];
+        }
+
+        /**
+         * returns an enumeration containing the name strings for curves
+         * contained in this structure.
+         */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(objIds.Keys); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X962Parameters.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X962Parameters.cs
new file mode 100644
index 0000000..5b7eaa1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X962Parameters.cs
@@ -0,0 +1,53 @@
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    public class X962Parameters
+        : Asn1Encodable, IAsn1Choice
+    {
+        private readonly Asn1Object _params;
+
+		public X962Parameters(
+            X9ECParameters ecParameters)
+        {
+            this._params = ecParameters.ToAsn1Object();
+        }
+
+		public X962Parameters(
+            DerObjectIdentifier namedCurve)
+        {
+            this._params = namedCurve;
+        }
+
+		public X962Parameters(
+            Asn1Object obj)
+        {
+            this._params = obj;
+        }
+
+		public bool IsNamedCurve
+        {
+			get { return (_params is DerObjectIdentifier); }
+        }
+
+		public Asn1Object Parameters
+        {
+            get { return _params; }
+        }
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * Parameters ::= CHOICE {
+         *    ecParameters ECParameters,
+         *    namedCurve   CURVES.&id({CurveNames}),
+         *    implicitlyCA Null
+         * }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return _params;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9Curve.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9Curve.cs
new file mode 100644
index 0000000..f05a946
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9Curve.cs
@@ -0,0 +1,146 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * ASN.1 def for Elliptic-Curve Curve structure. See
+     * X9.62, for further details.
+     */
+    public class X9Curve
+        : Asn1Encodable
+    {
+        private readonly ECCurve curve;
+        private readonly byte[] seed;
+        private readonly DerObjectIdentifier fieldIdentifier;
+
+        public X9Curve(
+            ECCurve curve)
+            : this(curve, null)
+        {
+        }
+
+        public X9Curve(
+            ECCurve	curve,
+            byte[]	seed)
+        {
+            if (curve == null)
+                throw new ArgumentNullException("curve");
+
+            this.curve = curve;
+            this.seed = Arrays.Clone(seed);
+
+            if (ECAlgorithms.IsFpCurve(curve))
+            {
+                this.fieldIdentifier = X9ObjectIdentifiers.PrimeField;
+            }
+            else if (ECAlgorithms.IsF2mCurve(curve))
+            {
+                this.fieldIdentifier = X9ObjectIdentifiers.CharacteristicTwoField;
+            }
+            else
+            {
+                throw new ArgumentException("This type of ECCurve is not implemented");
+            }
+        }
+
+        public X9Curve(
+            X9FieldID		fieldID,
+            Asn1Sequence	seq)
+        {
+            if (fieldID == null)
+                throw new ArgumentNullException("fieldID");
+            if (seq == null)
+                throw new ArgumentNullException("seq");
+
+            this.fieldIdentifier = fieldID.Identifier;
+
+            if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField))
+            {
+                BigInteger q = ((DerInteger) fieldID.Parameters).Value;
+                X9FieldElement x9A = new X9FieldElement(q, (Asn1OctetString) seq[0]);
+                X9FieldElement x9B = new X9FieldElement(q, (Asn1OctetString) seq[1]);
+                curve = new FpCurve(q, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
+            }
+            else
+            {
+                if (fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField)) 
+                {
+                    // Characteristic two field
+                    DerSequence parameters = (DerSequence)fieldID.Parameters;
+                    int m = ((DerInteger)parameters[0]).Value.IntValue;
+                    DerObjectIdentifier representation
+                        = (DerObjectIdentifier)parameters[1];
+
+                    int k1 = 0;
+                    int k2 = 0;
+                    int k3 = 0;
+                    if (representation.Equals(X9ObjectIdentifiers.TPBasis)) 
+                    {
+                        // Trinomial basis representation
+                        k1 = ((DerInteger)parameters[2]).Value.IntValue;
+                    }
+                    else 
+                    {
+                        // Pentanomial basis representation
+                        DerSequence pentanomial = (DerSequence) parameters[2];
+                        k1 = ((DerInteger) pentanomial[0]).Value.IntValue;
+                        k2 = ((DerInteger) pentanomial[1]).Value.IntValue;
+                        k3 = ((DerInteger) pentanomial[2]).Value.IntValue;
+                    }
+                    X9FieldElement x9A = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[0]);
+                    X9FieldElement x9B = new X9FieldElement(m, k1, k2, k3, (Asn1OctetString)seq[1]);
+                    // TODO Is it possible to get the order (n) and cofactor(h) too?
+                    curve = new F2mCurve(m, k1, k2, k3, x9A.Value.ToBigInteger(), x9B.Value.ToBigInteger());
+                }
+            }
+
+            if (seq.Count == 3)
+            {
+                seed = ((DerBitString) seq[2]).GetBytes();
+            }
+        }
+
+        public ECCurve Curve
+        {
+            get { return curve; }
+        }
+
+        public byte[] GetSeed()
+        {
+            return Arrays.Clone(seed);
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  Curve ::= Sequence {
+         *      a               FieldElement,
+         *      b               FieldElement,
+         *      seed            BIT STRING      OPTIONAL
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector();
+
+            if (fieldIdentifier.Equals(X9ObjectIdentifiers.PrimeField)
+                || fieldIdentifier.Equals(X9ObjectIdentifiers.CharacteristicTwoField)) 
+            { 
+                v.Add(new X9FieldElement(curve.A).ToAsn1Object());
+                v.Add(new X9FieldElement(curve.B).ToAsn1Object());
+            } 
+
+            if (seed != null)
+            {
+                v.Add(new DerBitString(seed));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParameters.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParameters.cs
new file mode 100644
index 0000000..a192e4c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParameters.cs
@@ -0,0 +1,186 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.Field;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * ASN.1 def for Elliptic-Curve ECParameters structure. See
+     * X9.62, for further details.
+     */
+    public class X9ECParameters
+        : Asn1Encodable
+    {
+        private X9FieldID	fieldID;
+        private ECCurve		curve;
+        private ECPoint		g;
+        private BigInteger	n;
+        private BigInteger	h;
+        private byte[]		seed;
+
+        public X9ECParameters(
+            Asn1Sequence seq)
+        {
+            if (!(seq[0] is DerInteger)
+               || !((DerInteger) seq[0]).Value.Equals(BigInteger.One))
+            {
+                throw new ArgumentException("bad version in X9ECParameters");
+            }
+
+            X9Curve x9c = null;
+            if (seq[2] is X9Curve)
+            {
+                x9c = (X9Curve) seq[2];
+            }
+            else
+            {
+                x9c = new X9Curve(
+                    new X9FieldID(
+                        (Asn1Sequence) seq[1]),
+                        (Asn1Sequence) seq[2]);
+            }
+
+            this.curve = x9c.Curve;
+
+            if (seq[3] is X9ECPoint)
+            {
+                this.g = ((X9ECPoint) seq[3]).Point;
+            }
+            else
+            {
+                this.g = new X9ECPoint(curve, (Asn1OctetString) seq[3]).Point;
+            }
+
+            this.n = ((DerInteger) seq[4]).Value;
+            this.seed = x9c.GetSeed();
+
+            if (seq.Count == 6)
+            {
+                this.h = ((DerInteger) seq[5]).Value;
+            }
+        }
+
+        public X9ECParameters(
+            ECCurve		curve,
+            ECPoint		g,
+            BigInteger	n)
+            : this(curve, g, n, BigInteger.One, null)
+        {
+        }
+
+        public X9ECParameters(
+            ECCurve		curve,
+            ECPoint		g,
+            BigInteger	n,
+            BigInteger	h)
+            : this(curve, g, n, h, null)
+        {
+        }
+
+        public X9ECParameters(
+            ECCurve		curve,
+            ECPoint		g,
+            BigInteger	n,
+            BigInteger	h,
+            byte[]		seed)
+        {
+            this.curve = curve;
+            this.g = g.Normalize();
+            this.n = n;
+            this.h = h;
+            this.seed = seed;
+
+            if (ECAlgorithms.IsFpCurve(curve))
+            {
+                this.fieldID = new X9FieldID(curve.Field.Characteristic);
+            }
+            else if (ECAlgorithms.IsF2mCurve(curve))
+            {
+                IPolynomialExtensionField field = (IPolynomialExtensionField)curve.Field;
+                int[] exponents = field.MinimalPolynomial.GetExponentsPresent();
+                if (exponents.Length == 3)
+                {
+                    this.fieldID = new X9FieldID(exponents[2], exponents[1]);
+                }
+                else if (exponents.Length == 5)
+                {
+                    this.fieldID = new X9FieldID(exponents[4], exponents[1], exponents[2], exponents[3]);
+                }
+                else
+                {
+                    throw new ArgumentException("Only trinomial and pentomial curves are supported");
+                }
+            }
+            else
+            {
+                throw new ArgumentException("'curve' is of an unsupported type");
+            }
+        }
+
+        public ECCurve Curve
+        {
+            get { return curve; }
+        }
+
+        public ECPoint G
+        {
+            get { return g; }
+        }
+
+        public BigInteger N
+        {
+            get { return n; }
+        }
+
+        public BigInteger H
+        {
+            get
+            {
+                if (h == null)
+                {
+                    // TODO - this should be calculated, it will cause issues with custom curves.
+                    return BigInteger.One;
+                }
+
+                return h;
+            }
+        }
+
+        public byte[] GetSeed()
+        {
+            return seed;
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  ECParameters ::= Sequence {
+         *      version         Integer { ecpVer1(1) } (ecpVer1),
+         *      fieldID         FieldID {{FieldTypes}},
+         *      curve           X9Curve,
+         *      base            X9ECPoint,
+         *      order           Integer,
+         *      cofactor        Integer OPTIONAL
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                new DerInteger(1),
+                fieldID,
+                new X9Curve(curve, seed),
+                new X9ECPoint(g),
+                new DerInteger(n));
+
+            if (h != null)
+            {
+                v.Add(new DerInteger(h));
+            }
+
+            return new DerSequence(v);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParametersHolder.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParametersHolder.cs
new file mode 100644
index 0000000..b345570
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECParametersHolder.cs
@@ -0,0 +1,22 @@
+namespace Org.BouncyCastle.Asn1.X9
+{
+	public abstract class X9ECParametersHolder
+	{
+		private X9ECParameters parameters;
+
+		public X9ECParameters Parameters
+		{
+			get
+			{
+				if (parameters == null)
+				{
+					parameters = CreateParameters();
+				}
+
+				return parameters;
+			}
+		}
+
+		protected abstract X9ECParameters CreateParameters();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9ECPoint.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECPoint.cs
new file mode 100644
index 0000000..75d58cd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9ECPoint.cs
@@ -0,0 +1,44 @@
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * class for describing an ECPoint as a Der object.
+     */
+    public class X9ECPoint
+        : Asn1Encodable
+    {
+        private readonly ECPoint p;
+
+        public X9ECPoint(
+            ECPoint p)
+        {
+            this.p = p.Normalize();
+        }
+
+        public X9ECPoint(
+            ECCurve			c,
+            Asn1OctetString	s)
+        {
+            this.p = c.DecodePoint(s.GetOctets());
+        }
+
+        public ECPoint Point
+        {
+            get { return p; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  ECPoint ::= OCTET STRING
+         * </pre>
+         * <p>
+         * Octet string produced using ECPoint.GetEncoded().</p>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerOctetString(p.GetEncoded());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldElement.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldElement.cs
new file mode 100644
index 0000000..94bd96b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldElement.cs
@@ -0,0 +1,69 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * Class for processing an ECFieldElement as a DER object.
+     */
+    public class X9FieldElement
+        : Asn1Encodable
+    {
+        private ECFieldElement f;
+
+        public X9FieldElement(
+            ECFieldElement f)
+        {
+            this.f = f;
+        }
+
+        public X9FieldElement(
+            BigInteger		p,
+            Asn1OctetString	s)
+            : this(new FpFieldElement(p, new BigInteger(1, s.GetOctets())))
+        {
+        }
+
+        public X9FieldElement(
+            int				m,
+            int				k1,
+            int				k2,
+            int				k3,
+            Asn1OctetString	s)
+            : this(new F2mFieldElement(m, k1, k2, k3, new BigInteger(1, s.GetOctets())))
+        {
+        }
+
+        public ECFieldElement Value
+        {
+            get { return f; }
+        }
+
+        /**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         *  FieldElement ::= OCTET STRING
+         * </pre>
+         * <p>
+         * <ol>
+         * <li> if <i>q</i> is an odd prime then the field element is
+         * processed as an Integer and converted to an octet string
+         * according to x 9.62 4.3.1.</li>
+         * <li> if <i>q</i> is 2<sup>m</sup> then the bit string
+         * contained in the field element is converted into an octet
+         * string with the same ordering padded at the front if necessary.
+         * </li>
+         * </ol>
+         * </p>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            int byteCount = X9IntegerConverter.GetByteLength(f);
+            byte[] paddedBigInteger = X9IntegerConverter.IntegerToBytes(f.ToBigInteger(), byteCount);
+
+            return new DerOctetString(paddedBigInteger);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldID.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldID.cs
new file mode 100644
index 0000000..58823a2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9FieldID.cs
@@ -0,0 +1,124 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    /**
+     * ASN.1 def for Elliptic-Curve Field ID structure. See
+     * X9.62, for further details.
+     */
+    public class X9FieldID
+        : Asn1Encodable
+    {
+        private readonly DerObjectIdentifier	id;
+        private readonly Asn1Object parameters;
+
+        /**
+         * Constructor for elliptic curves over prime fields
+         * <code>F<sub>2</sub></code>.
+         * @param primeP The prime <code>p</code> defining the prime field.
+         */
+        public X9FieldID(
+            BigInteger primeP)
+        {
+            this.id = X9ObjectIdentifiers.PrimeField;
+            this.parameters = new DerInteger(primeP);
+        }
+
+        /**
+         * Constructor for elliptic curves over binary fields
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+         * x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         */
+        public X9FieldID(int m, int k1)
+            : this(m, k1, 0, 0)
+        {
+        }
+
+        /**
+         * Constructor for elliptic curves over binary fields
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>..
+         */
+        public X9FieldID(
+            int m,
+            int k1,
+            int k2,
+            int k3)
+        {
+            this.id = X9ObjectIdentifiers.CharacteristicTwoField;
+
+            Asn1EncodableVector fieldIdParams = new Asn1EncodableVector(new DerInteger(m));
+
+            if (k2 == 0)
+            {
+                if (k3 != 0)
+                    throw new ArgumentException("inconsistent k values");
+
+                fieldIdParams.Add(
+                    X9ObjectIdentifiers.TPBasis,
+                    new DerInteger(k1));
+            }
+            else
+            {
+                if (k2 <= k1 || k3 <= k2)
+                    throw new ArgumentException("inconsistent k values");
+
+                fieldIdParams.Add(
+                    X9ObjectIdentifiers.PPBasis,
+                    new DerSequence(
+                        new DerInteger(k1),
+                        new DerInteger(k2),
+                        new DerInteger(k3)));
+            }
+
+            this.parameters = new DerSequence(fieldIdParams);
+        }
+
+        internal X9FieldID(
+            Asn1Sequence seq)
+        {
+            this.id = (DerObjectIdentifier) seq[0];
+            this.parameters = (Asn1Object) seq[1];
+        }
+
+        public DerObjectIdentifier Identifier
+        {
+            get { return id; }
+        }
+
+        public Asn1Object Parameters
+        {
+            get { return parameters; }
+        }
+
+        /**
+         * Produce a Der encoding of the following structure.
+         * <pre>
+         *  FieldID ::= Sequence {
+         *      fieldType       FIELD-ID.&id({IOSet}),
+         *      parameters      FIELD-ID.&Type({IOSet}{@fieldType})
+         *  }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            return new DerSequence(id, parameters);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9IntegerConverter.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9IntegerConverter.cs
new file mode 100644
index 0000000..e8f4571
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9IntegerConverter.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    public abstract class X9IntegerConverter
+    {
+        public static int GetByteLength(ECFieldElement fe)
+        {
+            return (fe.FieldSize + 7) / 8;
+        }
+
+        public static int GetByteLength(ECCurve c)
+        {
+            return (c.FieldSize + 7) / 8;
+        }
+
+        public static byte[] IntegerToBytes(BigInteger s, int qLength)
+        {
+            byte[] bytes = s.ToByteArrayUnsigned();
+
+            if (qLength < bytes.Length)
+            {
+                byte[] tmp = new byte[qLength];
+                Array.Copy(bytes, bytes.Length - tmp.Length, tmp, 0, tmp.Length);
+                return tmp;
+            }
+            else if (qLength > bytes.Length)
+            {
+                byte[] tmp = new byte[qLength];
+                Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
+                return tmp;
+            }
+
+            return bytes;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/asn1/x9/X9ObjectIdentifiers.cs b/BouncyCastle.AxCrypt/src/asn1/x9/X9ObjectIdentifiers.cs
new file mode 100644
index 0000000..9d7ecae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/asn1/x9/X9ObjectIdentifiers.cs
@@ -0,0 +1,137 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.X9
+{
+    public abstract class X9ObjectIdentifiers
+    {
+        //
+        // X9.62
+        //
+        // ansi-X9-62 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+        //            us(840) ansi-x962(10045) }
+        //
+
+        internal const string AnsiX962 = "1.2.840.10045";
+
+        public static readonly DerObjectIdentifier ansi_X9_62 = new DerObjectIdentifier(AnsiX962);
+
+        public static readonly DerObjectIdentifier IdFieldType = ansi_X9_62.Branch("1");
+
+        public static readonly DerObjectIdentifier PrimeField = IdFieldType.Branch("1");
+        public static readonly DerObjectIdentifier CharacteristicTwoField = IdFieldType.Branch("2");
+
+        public static readonly DerObjectIdentifier GNBasis = CharacteristicTwoField.Branch("3.1");
+        public static readonly DerObjectIdentifier TPBasis = CharacteristicTwoField.Branch("3.2");
+        public static readonly DerObjectIdentifier PPBasis = CharacteristicTwoField.Branch("3.3");
+
+        [Obsolete("Use 'id_ecSigType' instead")]
+        public const string IdECSigType = AnsiX962 + ".4";
+        public static readonly DerObjectIdentifier id_ecSigType = ansi_X9_62.Branch("4");
+
+        public static readonly DerObjectIdentifier ECDsaWithSha1 = id_ecSigType.Branch("1");
+
+        [Obsolete("Use 'id_publicKeyType' instead")]
+        public const string IdPublicKeyType = AnsiX962 + ".2";
+        public static readonly DerObjectIdentifier id_publicKeyType = ansi_X9_62.Branch("2");
+
+        public static readonly DerObjectIdentifier IdECPublicKey = id_publicKeyType.Branch("1");
+
+        public static readonly DerObjectIdentifier ECDsaWithSha2 = id_ecSigType.Branch("3");
+
+        public static readonly DerObjectIdentifier ECDsaWithSha224 = ECDsaWithSha2.Branch("1");
+        public static readonly DerObjectIdentifier ECDsaWithSha256 = ECDsaWithSha2.Branch("2");
+        public static readonly DerObjectIdentifier ECDsaWithSha384 = ECDsaWithSha2.Branch("3");
+        public static readonly DerObjectIdentifier ECDsaWithSha512 = ECDsaWithSha2.Branch("4");
+
+
+        //
+        // named curves
+        //
+        public static readonly DerObjectIdentifier EllipticCurve = ansi_X9_62.Branch("3");
+
+        //
+        // Two Curves
+        //
+        public static readonly DerObjectIdentifier CTwoCurve = EllipticCurve.Branch("0");
+
+        public static readonly DerObjectIdentifier C2Pnb163v1 = CTwoCurve.Branch("1");
+        public static readonly DerObjectIdentifier C2Pnb163v2 = CTwoCurve.Branch("2");
+        public static readonly DerObjectIdentifier C2Pnb163v3 = CTwoCurve.Branch("3");
+        public static readonly DerObjectIdentifier C2Pnb176w1 = CTwoCurve.Branch("4");
+        public static readonly DerObjectIdentifier C2Tnb191v1 = CTwoCurve.Branch("5");
+        public static readonly DerObjectIdentifier C2Tnb191v2 = CTwoCurve.Branch("6");
+        public static readonly DerObjectIdentifier C2Tnb191v3 = CTwoCurve.Branch("7");
+        public static readonly DerObjectIdentifier C2Onb191v4 = CTwoCurve.Branch("8");
+        public static readonly DerObjectIdentifier C2Onb191v5 = CTwoCurve.Branch("9");
+        public static readonly DerObjectIdentifier C2Pnb208w1 = CTwoCurve.Branch("10");
+        public static readonly DerObjectIdentifier C2Tnb239v1 = CTwoCurve.Branch("11");
+        public static readonly DerObjectIdentifier C2Tnb239v2 = CTwoCurve.Branch("12");
+        public static readonly DerObjectIdentifier C2Tnb239v3 = CTwoCurve.Branch("13");
+        public static readonly DerObjectIdentifier C2Onb239v4 = CTwoCurve.Branch("14");
+        public static readonly DerObjectIdentifier C2Onb239v5 = CTwoCurve.Branch("15");
+        public static readonly DerObjectIdentifier C2Pnb272w1 = CTwoCurve.Branch("16");
+        public static readonly DerObjectIdentifier C2Pnb304w1 = CTwoCurve.Branch("17");
+        public static readonly DerObjectIdentifier C2Tnb359v1 = CTwoCurve.Branch("18");
+        public static readonly DerObjectIdentifier C2Pnb368w1 = CTwoCurve.Branch("19");
+        public static readonly DerObjectIdentifier C2Tnb431r1 = CTwoCurve.Branch("20");
+
+        //
+        // Prime
+        //
+        public static readonly DerObjectIdentifier PrimeCurve = EllipticCurve.Branch("1");
+
+        public static readonly DerObjectIdentifier Prime192v1 = PrimeCurve.Branch("1");
+        public static readonly DerObjectIdentifier Prime192v2 = PrimeCurve.Branch("2");
+        public static readonly DerObjectIdentifier Prime192v3 = PrimeCurve.Branch("3");
+        public static readonly DerObjectIdentifier Prime239v1 = PrimeCurve.Branch("4");
+        public static readonly DerObjectIdentifier Prime239v2 = PrimeCurve.Branch("5");
+        public static readonly DerObjectIdentifier Prime239v3 = PrimeCurve.Branch("6");
+        public static readonly DerObjectIdentifier Prime256v1 = PrimeCurve.Branch("7");
+
+        //
+        // DSA
+        //
+        // dsapublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+        //            us(840) ansi-x957(10040) number-type(4) 1 }
+        public static readonly DerObjectIdentifier IdDsa = new DerObjectIdentifier("1.2.840.10040.4.1");
+
+        /**
+         *   id-dsa-with-sha1 OBJECT IDENTIFIER ::=  { iso(1) member-body(2)
+         *         us(840) x9-57 (10040) x9cm(4) 3 }
+         */
+        public static readonly DerObjectIdentifier IdDsaWithSha1 = new DerObjectIdentifier("1.2.840.10040.4.3");
+
+        /**
+         * X9.63
+         */
+        public static readonly DerObjectIdentifier X9x63Scheme = new DerObjectIdentifier("1.3.133.16.840.63.0");
+        public static readonly DerObjectIdentifier DHSinglePassStdDHSha1KdfScheme = X9x63Scheme.Branch("2");
+        public static readonly DerObjectIdentifier DHSinglePassCofactorDHSha1KdfScheme = X9x63Scheme.Branch("3");
+        public static readonly DerObjectIdentifier MqvSinglePassSha1KdfScheme = X9x63Scheme.Branch("16");
+
+        /**
+         * X9.42
+         */
+
+        public static readonly DerObjectIdentifier ansi_x9_42 = new DerObjectIdentifier("1.2.840.10046");
+
+        //
+        // Diffie-Hellman
+        //
+        // dhpublicnumber OBJECT IDENTIFIER ::= { iso(1) member-body(2)
+        //            us(840) ansi-x942(10046) number-type(2) 1 }
+        //
+        public static readonly DerObjectIdentifier DHPublicNumber = ansi_x9_42.Branch("2.1");
+
+        public static readonly DerObjectIdentifier X9x42Schemes = ansi_x9_42.Branch("2.3");
+
+        public static readonly DerObjectIdentifier DHStatic = X9x42Schemes.Branch("1");
+        public static readonly DerObjectIdentifier DHEphem = X9x42Schemes.Branch("2");
+        public static readonly DerObjectIdentifier DHOneFlow = X9x42Schemes.Branch("3");
+        public static readonly DerObjectIdentifier DHHybrid1 = X9x42Schemes.Branch("4");
+        public static readonly DerObjectIdentifier DHHybrid2 = X9x42Schemes.Branch("5");
+        public static readonly DerObjectIdentifier DHHybridOneFlow = X9x42Schemes.Branch("6");
+        public static readonly DerObjectIdentifier Mqv2 = X9x42Schemes.Branch("7");
+        public static readonly DerObjectIdentifier Mqv1 = X9x42Schemes.Branch("8");
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ArmoredInputStream.cs b/BouncyCastle.AxCrypt/src/bcpg/ArmoredInputStream.cs
new file mode 100644
index 0000000..c7bb859
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ArmoredInputStream.cs
@@ -0,0 +1,516 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * reader for Base64 armored objects - read the headers and then start returning
+    * bytes when the data is reached. An IOException is thrown if the CRC check
+    * fails.
+    */
+    public class ArmoredInputStream
+        : BaseInputStream
+    {
+        /*
+        * set up the decoding table.
+        */
+        private readonly static byte[] decodingTable;
+        static ArmoredInputStream()
+        {
+            decodingTable = new byte[128];
+            for (int i = 'A'; i <= 'Z'; i++)
+            {
+                decodingTable[i] = (byte)(i - 'A');
+            }
+            for (int i = 'a'; i <= 'z'; i++)
+            {
+                decodingTable[i] = (byte)(i - 'a' + 26);
+            }
+            for (int i = '0'; i <= '9'; i++)
+            {
+                decodingTable[i] = (byte)(i - '0' + 52);
+            }
+            decodingTable['+'] = 62;
+            decodingTable['/'] = 63;
+        }
+
+        /**
+        * decode the base 64 encoded input data.
+        *
+        * @return the offset the data starts in out.
+        */
+        private int Decode(
+            int      in0,
+            int      in1,
+            int      in2,
+            int      in3,
+            int[]    result)
+        {
+            if (in3 < 0)
+            {
+                throw new EndOfStreamException("unexpected end of file in armored stream.");
+            }
+
+            int    b1, b2, b3, b4;
+            if (in2 == '=')
+            {
+                b1 = decodingTable[in0] &0xff;
+                b2 = decodingTable[in1] & 0xff;
+                result[2] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+                return 2;
+            }
+            else if (in3 == '=')
+            {
+                b1 = decodingTable[in0];
+                b2 = decodingTable[in1];
+                b3 = decodingTable[in2];
+                result[1] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+                result[2] = ((b2 << 4) | (b3 >> 2)) & 0xff;
+                return 1;
+            }
+            else
+            {
+                b1 = decodingTable[in0];
+                b2 = decodingTable[in1];
+                b3 = decodingTable[in2];
+                b4 = decodingTable[in3];
+                result[0] = ((b1 << 2) | (b2 >> 4)) & 0xff;
+                result[1] = ((b2 << 4) | (b3 >> 2)) & 0xff;
+                result[2] = ((b3 << 6) | b4) & 0xff;
+                return 0;
+            }
+        }
+
+        Stream      input;
+        bool        start = true;
+        int[]       outBuf = new int[3];
+        int         bufPtr = 3;
+        Crc24       crc = new Crc24();
+        bool        crcFound = false;
+        bool        hasHeaders = true;
+        string      header = null;
+        bool        newLineFound = false;
+        bool        clearText = false;
+        bool        restart = false;
+        IList       headerList= Platform.CreateArrayList();
+        int         lastC = 0;
+		bool		isEndOfStream;
+
+        /**
+        * Create a stream for reading a PGP armoured message, parsing up to a header
+        * and then reading the data that follows.
+        *
+        * @param input
+        */
+        public ArmoredInputStream(
+            Stream input)
+			: this(input, true)
+        {
+        }
+
+		/**
+        * Create an armoured input stream which will assume the data starts
+        * straight away, or parse for headers first depending on the value of
+        * hasHeaders.
+        *
+        * @param input
+        * @param hasHeaders true if headers are to be looked for, false otherwise.
+        */
+        public ArmoredInputStream(
+            Stream	input,
+            bool	hasHeaders)
+        {
+            this.input = input;
+            this.hasHeaders = hasHeaders;
+
+			if (hasHeaders)
+            {
+                ParseHeaders();
+            }
+
+			start = false;
+        }
+
+		private bool ParseHeaders()
+        {
+            header = null;
+
+			int		c;
+            int		last = 0;
+            bool	headerFound = false;
+
+            headerList = Platform.CreateArrayList();
+
+			//
+            // if restart we already have a header
+            //
+            if (restart)
+            {
+                headerFound = true;
+            }
+            else
+            {
+                while ((c = input.ReadByte()) >= 0)
+                {
+                    if (c == '-' && (last == 0 || last == '\n' || last == '\r'))
+                    {
+                        headerFound = true;
+                        break;
+                    }
+
+					last = c;
+                }
+            }
+
+			if (headerFound)
+            {
+                StringBuilder    Buffer = new StringBuilder("-");
+                bool             eolReached = false;
+                bool             crLf = false;
+
+				if (restart)    // we've had to look ahead two '-'
+                {
+                    Buffer.Append('-');
+                }
+
+				while ((c = input.ReadByte()) >= 0)
+                {
+                    if (last == '\r' && c == '\n')
+                    {
+                        crLf = true;
+                    }
+                    if (eolReached && (last != '\r' && c == '\n'))
+                    {
+                        break;
+                    }
+                    if (eolReached && c == '\r')
+                    {
+                        break;
+                    }
+                    if (c == '\r' || (last != '\r' && c == '\n'))
+                    {
+						string line = Buffer.ToString();
+						if (line.Trim().Length < 1)
+							break;
+                        headerList.Add(line);
+                        Buffer.Length = 0;
+                    }
+
+                    if (c != '\n' && c != '\r')
+                    {
+                        Buffer.Append((char)c);
+                        eolReached = false;
+                    }
+                    else
+                    {
+                        if (c == '\r' || (last != '\r' && c == '\n'))
+                        {
+                            eolReached = true;
+                        }
+                    }
+
+					last = c;
+                }
+
+				if (crLf)
+                {
+                    input.ReadByte(); // skip last \n
+                }
+            }
+
+			if (headerList.Count > 0)
+            {
+                header = (string) headerList[0];
+            }
+
+			clearText = "-----BEGIN PGP SIGNED MESSAGE-----".Equals(header);
+            newLineFound = true;
+
+			return headerFound;
+        }
+
+		/**
+        * @return true if we are inside the clear text section of a PGP
+        * signed message.
+        */
+        public bool IsClearText()
+        {
+            return clearText;
+        }
+
+		/**
+		 * @return true if the stream is actually at end of file.
+		 */
+		public bool IsEndOfStream()
+		{
+			return isEndOfStream;
+		}
+
+		/**
+        * Return the armor header line (if there is one)
+        * @return the armor header line, null if none present.
+        */
+        public string GetArmorHeaderLine()
+        {
+            return header;
+        }
+
+		/**
+        * Return the armor headers (the lines after the armor header line),
+        * @return an array of armor headers, null if there aren't any.
+        */
+        public string[] GetArmorHeaders()
+        {
+            if (headerList.Count <= 1)
+            {
+                return null;
+            }
+
+			string[] hdrs = new string[headerList.Count - 1];
+            for (int i = 0; i != hdrs.Length; i++)
+            {
+                hdrs[i] = (string) headerList[i + 1];
+            }
+
+			return hdrs;
+        }
+
+		private int ReadIgnoreSpace()
+        {
+            int c;
+            do
+            {
+                c = input.ReadByte();
+            }
+            while (c == ' ' || c == '\t');
+
+			return c;
+        }
+
+		private int ReadIgnoreWhitespace()
+        {
+            int c;
+            do
+            {
+                c = input.ReadByte();
+            }
+            while (c == ' ' || c == '\t' || c == '\r' || c == '\n');
+
+            return c;
+        }
+
+		private int ReadByteClearText()
+        {
+            int c = input.ReadByte();
+
+            if (c == '\r' || (c == '\n' && lastC != '\r'))
+            {
+                newLineFound = true;
+            }
+            else if (newLineFound && c == '-')
+            {
+                c = input.ReadByte();
+                if (c == '-')            // a header, not dash escaped
+                {
+                    clearText = false;
+                    start = true;
+                    restart = true;
+                }
+                else                   // a space - must be a dash escape
+                {
+                    c = input.ReadByte();
+                }
+                newLineFound = false;
+            }
+            else
+            {
+                if (c != '\n' && lastC != '\r')
+                {
+                    newLineFound = false;
+                }
+            }
+
+            lastC = c;
+
+			if (c < 0)
+			{
+				isEndOfStream = true;
+			}
+
+			return c;
+        }
+
+        private int ReadClearText(byte[] buffer, int offset, int count)
+        {
+            int pos = offset;
+            try
+            {
+                int end = offset + count;
+                while (pos < end)
+                {
+                    int c = ReadByteClearText();
+                    if (c == -1)
+                    {
+                        break;
+                    }
+                    buffer[pos++] = (byte) c;
+                }
+            }
+            catch (IOException ioe)
+            {
+                if (pos == offset) throw ioe;
+            }
+
+			return pos - offset;
+        }
+
+        private int DoReadByte()
+        {
+            if (bufPtr > 2 || crcFound)
+            {
+                int c = ReadIgnoreSpace();
+                if (c == '\n' || c == '\r')
+                {
+                    c = ReadIgnoreWhitespace();
+                    if (c == '=')            // crc reached
+                    {
+                        bufPtr = Decode(ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
+
+                        if (bufPtr != 0)
+                        {
+                            throw new IOException("no crc found in armored message.");
+                        }
+
+                        crcFound = true;
+
+                        int i = ((outBuf[0] & 0xff) << 16)
+                            | ((outBuf[1] & 0xff) << 8)
+                            | (outBuf[2] & 0xff);
+
+                        if (i != crc.Value)
+                        {
+                            throw new IOException("crc check failed in armored message.");
+                        }
+
+						return ReadByte();
+                    }
+
+                    if (c == '-')        // end of record reached
+                    {
+                        while ((c = input.ReadByte()) >= 0)
+                        {
+                            if (c == '\n' || c == '\r')
+                            {
+                                break;
+                            }
+                        }
+
+                        if (!crcFound)
+                        {
+                            throw new IOException("crc check not found.");
+                        }
+
+                        crcFound = false;
+                        start = true;
+                        bufPtr = 3;
+
+						if (c < 0)
+						{
+							isEndOfStream = true;
+						}
+
+						return -1;
+                    }
+                }
+
+                if (c < 0)
+                {
+					isEndOfStream = true;
+					return -1;
+                }
+
+                bufPtr = Decode(c, ReadIgnoreSpace(), ReadIgnoreSpace(), ReadIgnoreSpace(), outBuf);
+            }
+
+            return outBuf[bufPtr++];
+        }
+
+        public override int ReadByte()
+        {
+            if (start)
+            {
+                if (hasHeaders)
+                {
+                    ParseHeaders();
+                }
+
+				crc.Reset();
+				start = false;
+            }
+
+			if (clearText)
+            {
+                return ReadByteClearText();
+            }
+
+            int c = DoReadByte();
+
+            crc.Update(c);
+
+            return c;
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            if (start && count > 0)
+            {
+                if (hasHeaders)
+                {
+                    ParseHeaders();
+                }
+                start = false;
+            }
+
+            if (clearText)
+            {
+                return ReadClearText(buffer, offset, count);
+            }
+
+            int pos = offset;
+            try
+            {
+                int end = offset + count;
+                while (pos < end)
+                {
+                    int c = DoReadByte();
+                    crc.Update(c);
+                    if (c == -1)
+                    {
+                        break;
+                    }
+                    buffer[pos++] = (byte) c;
+                }
+            }
+            catch (IOException ioe)
+            {
+                if (pos == offset) throw ioe;
+            }
+
+            return pos - offset;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                input.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ArmoredOutputStream.cs b/BouncyCastle.AxCrypt/src/bcpg/ArmoredOutputStream.cs
new file mode 100644
index 0000000..458e74a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ArmoredOutputStream.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic output stream.
+    */
+    public class ArmoredOutputStream
+        : BaseOutputStream
+    {
+        private static readonly byte[] encodingTable =
+        {
+            (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+            (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+            (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+            (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+            (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+            (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+            (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+            (byte)'v',
+            (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+            (byte)'7', (byte)'8', (byte)'9',
+            (byte)'+', (byte)'/'
+        };
+
+        /**
+         * encode the input data producing a base 64 encoded byte array.
+         */
+        private static void Encode(
+            Stream	outStream,
+            int[]	data,
+            int		len)
+        {
+			Debug.Assert(len > 0);
+			Debug.Assert(len < 4);
+
+			byte[] bs = new byte[4];
+			int d1 = data[0];
+			bs[0] = encodingTable[(d1 >> 2) & 0x3f];
+
+			switch (len)
+            {
+				case 1:
+				{
+					bs[1] = encodingTable[(d1 << 4) & 0x3f];
+					bs[2] = (byte)'=';
+					bs[3] = (byte)'=';
+					break;
+				}
+				case 2:
+				{
+					int d2 = data[1];
+					bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+					bs[2] = encodingTable[(d2 << 2) & 0x3f];
+					bs[3] = (byte)'=';
+					break;
+				}
+				case 3:
+				{
+					int d2 = data[1];
+					int d3 = data[2];
+					bs[1] = encodingTable[((d1 << 4) | (d2 >> 4)) & 0x3f];
+					bs[2] = encodingTable[((d2 << 2) | (d3 >> 6)) & 0x3f];
+					bs[3] = encodingTable[d3 & 0x3f];
+					break;
+				}
+            }
+
+			outStream.Write(bs, 0, bs.Length);
+        }
+
+        private readonly Stream outStream;
+        private int[]           buf = new int[3];
+        private int             bufPtr = 0;
+        private Crc24           crc = new Crc24();
+        private int             chunkCount = 0;
+        private int             lastb;
+
+        private bool            start = true;
+        private bool            clearText = false;
+        private bool            newLine = false;
+
+        private string          type;
+
+        private static readonly string	nl = Platform.NewLine;
+        private static readonly string	headerStart = "-----BEGIN PGP ";
+        private static readonly string	headerTail = "-----";
+        private static readonly string	footerStart = "-----END PGP ";
+        private static readonly string	footerTail = "-----";
+
+        private static readonly string version = "BCPG C# v" + AssemblyInfo.Version;
+
+		private readonly IDictionary headers;
+
+		public ArmoredOutputStream(Stream outStream)
+        {
+            this.outStream = outStream;
+            this.headers = Platform.CreateHashtable();
+            this.headers["Version"] = version;
+        }
+
+        public ArmoredOutputStream(Stream outStream, IDictionary headers)
+        {
+            this.outStream = outStream;
+            this.headers = Platform.CreateHashtable(headers);
+            this.headers["Version"] = version;
+        }
+
+        /**
+         * Set an additional header entry.
+         *
+         * @param name the name of the header entry.
+         * @param v the value of the header entry.
+         */
+        public void SetHeader(
+            string name,
+            string v)
+        {
+            headers[name] = v;
+        }
+
+        /**
+         * Reset the headers to only contain a Version string.
+         */
+        public void ResetHeaders()
+        {
+            headers.Clear();
+            headers["Version"] = version;
+        }
+
+        /**
+         * Start a clear text signed message.
+         * @param hashAlgorithm
+         */
+        public void BeginClearText(
+            HashAlgorithmTag    hashAlgorithm)
+        {
+            string    hash;
+
+            switch (hashAlgorithm)
+            {
+            case HashAlgorithmTag.Sha1:
+                hash = "SHA1";
+                break;
+            case HashAlgorithmTag.Sha256:
+                hash = "SHA256";
+                break;
+            case HashAlgorithmTag.Sha384:
+                hash = "SHA384";
+                break;
+            case HashAlgorithmTag.Sha512:
+                hash = "SHA512";
+                break;
+            case HashAlgorithmTag.MD2:
+                hash = "MD2";
+                break;
+            case HashAlgorithmTag.MD5:
+                hash = "MD5";
+                break;
+            case HashAlgorithmTag.RipeMD160:
+                hash = "RIPEMD160";
+                break;
+            default:
+                throw new IOException("unknown hash algorithm tag in beginClearText: " + hashAlgorithm);
+            }
+
+			DoWrite("-----BEGIN PGP SIGNED MESSAGE-----" + nl);
+            DoWrite("Hash: " + hash + nl + nl);
+
+			clearText = true;
+            newLine = true;
+            lastb = 0;
+        }
+
+        public void EndClearText()
+        {
+            clearText = false;
+        }
+
+        public override void WriteByte(
+            byte b)
+        {
+            if (clearText)
+            {
+                outStream.WriteByte(b);
+
+                if (newLine)
+                {
+                    if (!(b == '\n' && lastb == '\r'))
+                    {
+                        newLine = false;
+                    }
+                    if (b == '-')
+                    {
+                        outStream.WriteByte((byte)' ');
+                        outStream.WriteByte((byte)'-');      // dash escape
+                    }
+                }
+                if (b == '\r' || (b == '\n' && lastb != '\r'))
+                {
+                    newLine = true;
+                }
+                lastb = b;
+                return;
+            }
+
+            if (start)
+            {
+                bool newPacket = (b & 0x40) != 0;
+
+				int tag;
+                if (newPacket)
+                {
+                    tag = b & 0x3f;
+                }
+                else
+                {
+                    tag = (b & 0x3f) >> 2;
+                }
+
+                switch ((PacketTag)tag)
+                {
+                case PacketTag.PublicKey:
+                    type = "PUBLIC KEY BLOCK";
+                    break;
+                case PacketTag.SecretKey:
+                    type = "PRIVATE KEY BLOCK";
+                    break;
+                case PacketTag.Signature:
+                    type = "SIGNATURE";
+                    break;
+                default:
+                    type = "MESSAGE";
+				    break;
+                }
+
+                DoWrite(headerStart + type + headerTail + nl);
+                WriteHeaderEntry("Version", (string) headers["Version"]);
+
+                foreach (DictionaryEntry de in headers)
+                {
+                    string k = (string) de.Key;
+                    if (k != "Version")
+                    {
+                        string v = (string) de.Value;
+                        WriteHeaderEntry(k, v);
+                    }
+                }
+
+                DoWrite(nl);
+
+                start = false;
+            }
+
+            if (bufPtr == 3)
+            {
+                Encode(outStream, buf, bufPtr);
+                bufPtr = 0;
+                if ((++chunkCount & 0xf) == 0)
+                {
+                    DoWrite(nl);
+                }
+            }
+
+            crc.Update(b);
+            buf[bufPtr++] = b & 0xff;
+        }
+
+        /**
+         * <b>Note</b>: close does nor close the underlying stream. So it is possible to write
+         * multiple objects using armoring to a single stream.
+         */
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (type != null)
+                {
+                    if (bufPtr > 0)
+                    {
+                        Encode(outStream, buf, bufPtr);
+                    }
+
+                    DoWrite(nl + '=');
+
+                    int crcV = crc.Value;
+
+                    buf[0] = ((crcV >> 16) & 0xff);
+                    buf[1] = ((crcV >> 8) & 0xff);
+                    buf[2] = (crcV & 0xff);
+
+                    Encode(outStream, buf, 3);
+
+                    DoWrite(nl);
+                    DoWrite(footerStart);
+                    DoWrite(type);
+                    DoWrite(footerTail);
+                    DoWrite(nl);
+
+                    outStream.Flush();
+
+                    type = null;
+                    start = true;
+                }
+            }
+            base.Dispose(disposing);
+        }
+
+		private void WriteHeaderEntry(
+			string	name,
+			string	v)
+        {
+            DoWrite(name + ": " + v + nl);
+        }
+
+		private void DoWrite(
+			string s)
+        {
+            byte[] bs = Strings.ToAsciiByteArray(s);
+			outStream.Write(bs, 0, bs.Length);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/BcpgInputStream.cs b/BouncyCastle.AxCrypt/src/bcpg/BcpgInputStream.cs
new file mode 100644
index 0000000..e8a4f04
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/BcpgInputStream.cs
@@ -0,0 +1,358 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Reader for PGP objects.</remarks>
+    public class BcpgInputStream
+        : BaseInputStream
+    {
+        private Stream m_in;
+        private bool next = false;
+        private int nextB;
+
+        internal static BcpgInputStream Wrap(
+			Stream inStr)
+        {
+            if (inStr is BcpgInputStream)
+            {
+                return (BcpgInputStream) inStr;
+            }
+
+            return new BcpgInputStream(inStr);
+        }
+
+        private BcpgInputStream(
+			Stream inputStream)
+        {
+            this.m_in = inputStream;
+        }
+
+        public override int ReadByte()
+        {
+            if (next)
+            {
+                next = false;
+                return nextB;
+            }
+
+            return m_in.ReadByte();
+        }
+
+        public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+        {
+			// Strangely, when count == 0, we should still attempt to read a byte
+//			if (count == 0)
+//				return 0;
+
+			if (!next)
+				return m_in.Read(buffer, offset, count);
+
+			// We have next byte waiting, so return it
+
+			if (nextB < 0)
+				return 0; // EndOfStream
+
+			if (buffer == null)
+				throw new ArgumentNullException("buffer");
+
+			buffer[offset] = (byte) nextB;
+			next = false;
+
+			return 1;
+        }
+
+		public byte[] ReadAll()
+        {
+			return Streams.ReadAll(this);
+		}
+
+		public void ReadFully(
+            byte[]	buffer,
+            int		off,
+            int		len)
+        {
+			if (Streams.ReadFully(this, buffer, off, len) < len)
+				throw new EndOfStreamException();
+        }
+
+		public void ReadFully(
+            byte[] buffer)
+        {
+            ReadFully(buffer, 0, buffer.Length);
+        }
+
+		/// <summary>Returns the next packet tag in the stream.</summary>
+        public PacketTag NextPacketTag()
+        {
+            if (!next)
+            {
+                try
+                {
+                    nextB = m_in.ReadByte();
+                }
+                catch (EndOfStreamException)
+                {
+                    nextB = -1;
+                }
+
+                next = true;
+            }
+
+            if (nextB >= 0)
+            {
+                if ((nextB & 0x40) != 0)    // new
+                {
+                    return (PacketTag)(nextB & 0x3f);
+                }
+                else    // old
+                {
+                    return (PacketTag)((nextB & 0x3f) >> 2);
+                }
+            }
+
+            return (PacketTag) nextB;
+        }
+
+        public Packet ReadPacket()
+        {
+            int hdr = this.ReadByte();
+
+            if (hdr < 0)
+            {
+                return null;
+            }
+
+            if ((hdr & 0x80) == 0)
+            {
+                throw new IOException("invalid header encountered");
+            }
+
+            bool newPacket = (hdr & 0x40) != 0;
+            PacketTag tag = 0;
+            int bodyLen = 0;
+            bool partial = false;
+
+            if (newPacket)
+            {
+                tag = (PacketTag)(hdr & 0x3f);
+
+                int l = this.ReadByte();
+
+                if (l < 192)
+                {
+                    bodyLen = l;
+                }
+                else if (l <= 223)
+                {
+                    int b = m_in.ReadByte();
+                    bodyLen = ((l - 192) << 8) + (b) + 192;
+                }
+                else if (l == 255)
+                {
+                    bodyLen = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16)
+                        |  (m_in.ReadByte() << 8)  | m_in.ReadByte();
+                }
+                else
+                {
+                    partial = true;
+                    bodyLen = 1 << (l & 0x1f);
+                }
+            }
+            else
+            {
+                int lengthType = hdr & 0x3;
+
+                tag = (PacketTag)((hdr & 0x3f) >> 2);
+
+                switch (lengthType)
+                {
+                    case 0:
+                        bodyLen = this.ReadByte();
+                        break;
+                    case 1:
+                        bodyLen = (this.ReadByte() << 8) | this.ReadByte();
+                        break;
+                    case 2:
+                        bodyLen = (this.ReadByte() << 24) | (this.ReadByte() << 16)
+                            | (this.ReadByte() << 8) | this.ReadByte();
+                        break;
+                    case 3:
+                        partial = true;
+                        break;
+                    default:
+                        throw new IOException("unknown length type encountered");
+                }
+            }
+
+            BcpgInputStream objStream;
+            if (bodyLen == 0 && partial)
+            {
+                objStream = this;
+            }
+            else
+            {
+                PartialInputStream pis = new PartialInputStream(this, partial, bodyLen);
+                objStream = new BcpgInputStream(pis);
+            }
+
+            switch (tag)
+            {
+                case PacketTag.Reserved:
+                    return new InputStreamPacket(objStream);
+                case PacketTag.PublicKeyEncryptedSession:
+                    return new PublicKeyEncSessionPacket(objStream);
+                case PacketTag.Signature:
+                    return new SignaturePacket(objStream);
+                case PacketTag.SymmetricKeyEncryptedSessionKey:
+                    return new SymmetricKeyEncSessionPacket(objStream);
+                case PacketTag.OnePassSignature:
+                    return new OnePassSignaturePacket(objStream);
+                case PacketTag.SecretKey:
+                    return new SecretKeyPacket(objStream);
+                case PacketTag.PublicKey:
+                    return new PublicKeyPacket(objStream);
+                case PacketTag.SecretSubkey:
+                    return new SecretSubkeyPacket(objStream);
+                case PacketTag.CompressedData:
+                    return new CompressedDataPacket(objStream);
+                case PacketTag.SymmetricKeyEncrypted:
+                    return new SymmetricEncDataPacket(objStream);
+                case PacketTag.Marker:
+                    return new MarkerPacket(objStream);
+                case PacketTag.LiteralData:
+                    return new LiteralDataPacket(objStream);
+                case PacketTag.Trust:
+                    return new TrustPacket(objStream);
+                case PacketTag.UserId:
+                    return new UserIdPacket(objStream);
+                case PacketTag.UserAttribute:
+                    return new UserAttributePacket(objStream);
+                case PacketTag.PublicSubkey:
+                    return new PublicSubkeyPacket(objStream);
+                case PacketTag.SymmetricEncryptedIntegrityProtected:
+                    return new SymmetricEncIntegrityPacket(objStream);
+                case PacketTag.ModificationDetectionCode:
+                    return new ModDetectionCodePacket(objStream);
+                case PacketTag.Experimental1:
+                case PacketTag.Experimental2:
+                case PacketTag.Experimental3:
+                case PacketTag.Experimental4:
+                    return new ExperimentalPacket(tag, objStream);
+                default:
+                    throw new IOException("unknown packet type encountered: " + tag);
+            }
+        }
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            m_in.Dispose();
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		/// <summary>
+		/// A stream that overlays our input stream, allowing the user to only read a segment of it.
+		/// NB: dataLength will be negative if the segment length is in the upper range above 2**31.
+		/// </summary>
+		private class PartialInputStream
+            : BaseInputStream
+        {
+            private BcpgInputStream m_in;
+            private bool partial;
+            private int dataLength;
+
+            internal PartialInputStream(
+                BcpgInputStream	bcpgIn,
+                bool			partial,
+                int				dataLength)
+            {
+                this.m_in = bcpgIn;
+                this.partial = partial;
+                this.dataLength = dataLength;
+            }
+
+			public override int ReadByte()
+			{
+				do
+				{
+					if (dataLength != 0)
+					{
+						int ch = m_in.ReadByte();
+						if (ch < 0)
+						{
+							throw new EndOfStreamException("Premature end of stream in PartialInputStream");
+						}
+						dataLength--;
+						return ch;
+					}
+				}
+				while (partial && ReadPartialDataLength() >= 0);
+
+				return -1;
+			}
+
+			public override int Read(byte[] buffer, int offset, int count)
+			{
+				do
+				{
+					if (dataLength != 0)
+					{
+						int readLen = (dataLength > count || dataLength < 0) ? count : dataLength;
+						int len = m_in.Read(buffer, offset, readLen);
+						if (len < 1)
+						{
+							throw new EndOfStreamException("Premature end of stream in PartialInputStream");
+						}
+						dataLength -= len;
+						return len;
+					}
+				}
+				while (partial && ReadPartialDataLength() >= 0);
+
+				return 0;
+			}
+
+            private int ReadPartialDataLength()
+            {
+                int l = m_in.ReadByte();
+
+				if (l < 0)
+                {
+                    return -1;
+                }
+
+				partial = false;
+
+				if (l < 192)
+                {
+                    dataLength = l;
+                }
+                else if (l <= 223)
+                {
+                    dataLength = ((l - 192) << 8) + (m_in.ReadByte()) + 192;
+                }
+                else if (l == 255)
+                {
+                    dataLength = (m_in.ReadByte() << 24) | (m_in.ReadByte() << 16)
+                        |  (m_in.ReadByte() << 8)  | m_in.ReadByte();
+                }
+                else
+                {
+                    partial = true;
+                    dataLength = 1 << (l & 0x1f);
+                }
+
+                return 0;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/BcpgObject.cs b/BouncyCastle.AxCrypt/src/bcpg/BcpgObject.cs
new file mode 100644
index 0000000..4807ad4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/BcpgObject.cs
@@ -0,0 +1,22 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for a PGP object.</remarks>
+    public abstract class BcpgObject
+    {
+        public virtual byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+            pOut.WriteObject(this);
+
+            return bOut.ToArray();
+        }
+
+        public abstract void Encode(BcpgOutputStream bcpgOut);
+    }
+}
+
diff --git a/BouncyCastle.AxCrypt/src/bcpg/BcpgOutputStream.cs b/BouncyCastle.AxCrypt/src/bcpg/BcpgOutputStream.cs
new file mode 100644
index 0000000..f62fadc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/BcpgOutputStream.cs
@@ -0,0 +1,393 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic output stream.</remarks>
+    public class BcpgOutputStream
+        : BaseOutputStream
+    {
+		internal static BcpgOutputStream Wrap(
+			Stream outStr)
+		{
+			if (outStr is BcpgOutputStream)
+			{
+				return (BcpgOutputStream) outStr;
+			}
+
+			return new BcpgOutputStream(outStr);
+		}
+
+		private Stream outStr;
+        private byte[] partialBuffer;
+        private int partialBufferLength;
+        private int partialPower;
+        private int partialOffset;
+        private const int BufferSizePower = 16; // 2^16 size buffer on long files
+
+		/// <summary>Create a stream representing a general packet.</summary>
+		/// <param name="outStr">Output stream to write to.</param>
+		public BcpgOutputStream(
+            Stream outStr)
+        {
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			this.outStr = outStr;
+        }
+
+		/// <summary>Create a stream representing an old style partial object.</summary>
+		/// <param name="outStr">Output stream to write to.</param>
+		/// <param name="tag">The packet tag for the object.</param>
+        public BcpgOutputStream(
+            Stream		outStr,
+            PacketTag	tag)
+        {
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			this.outStr = outStr;
+            this.WriteHeader(tag, true, true, 0);
+        }
+
+		/// <summary>Create a stream representing a general packet.</summary>
+		/// <param name="outStr">Output stream to write to.</param>
+		/// <param name="tag">Packet tag.</param>
+		/// <param name="length">Size of chunks making up the packet.</param>
+		/// <param name="oldFormat">If true, the header is written out in old format.</param>
+		public BcpgOutputStream(
+            Stream		outStr,
+            PacketTag	tag,
+            long		length,
+            bool		oldFormat)
+        {
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			this.outStr = outStr;
+
+            if (length > 0xFFFFFFFFL)
+            {
+                this.WriteHeader(tag, false, true, 0);
+                this.partialBufferLength = 1 << BufferSizePower;
+                this.partialBuffer = new byte[partialBufferLength];
+				this.partialPower = BufferSizePower;
+				this.partialOffset = 0;
+            }
+            else
+            {
+                this.WriteHeader(tag, oldFormat, false, length);
+            }
+        }
+
+		/// <summary>Create a new style partial input stream buffered into chunks.</summary>
+		/// <param name="outStr">Output stream to write to.</param>
+		/// <param name="tag">Packet tag.</param>
+		/// <param name="length">Size of chunks making up the packet.</param>
+		public BcpgOutputStream(
+            Stream		outStr,
+            PacketTag	tag,
+            long		length)
+        {
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+            this.outStr = outStr;
+            this.WriteHeader(tag, false, false, length);
+        }
+
+		/// <summary>Create a new style partial input stream buffered into chunks.</summary>
+		/// <param name="outStr">Output stream to write to.</param>
+		/// <param name="tag">Packet tag.</param>
+		/// <param name="buffer">Buffer to use for collecting chunks.</param>
+        public BcpgOutputStream(
+            Stream		outStr,
+            PacketTag	tag,
+            byte[]		buffer)
+        {
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+            this.outStr = outStr;
+            this.WriteHeader(tag, false, true, 0);
+
+			this.partialBuffer = buffer;
+
+			uint length = (uint) partialBuffer.Length;
+            for (partialPower = 0; length != 1; partialPower++)
+            {
+                length >>= 1;
+            }
+
+			if (partialPower > 30)
+            {
+                throw new IOException("Buffer cannot be greater than 2^30 in length.");
+            }
+            this.partialBufferLength = 1 << partialPower;
+            this.partialOffset = 0;
+        }
+
+		private void WriteNewPacketLength(
+            long bodyLen)
+        {
+            if (bodyLen < 192)
+            {
+                outStr.WriteByte((byte)bodyLen);
+            }
+            else if (bodyLen <= 8383)
+            {
+                bodyLen -= 192;
+
+                outStr.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192));
+                outStr.WriteByte((byte)bodyLen);
+            }
+            else
+            {
+                outStr.WriteByte(0xff);
+                outStr.WriteByte((byte)(bodyLen >> 24));
+                outStr.WriteByte((byte)(bodyLen >> 16));
+                outStr.WriteByte((byte)(bodyLen >> 8));
+                outStr.WriteByte((byte)bodyLen);
+            }
+        }
+
+        private void WriteHeader(
+            PacketTag	tag,
+            bool		oldPackets,
+            bool		partial,
+            long		bodyLen)
+        {
+            int hdr = 0x80;
+
+            if (partialBuffer != null)
+            {
+                PartialFlush(true);
+                partialBuffer = null;
+            }
+
+            if (oldPackets)
+            {
+                hdr |= ((int) tag) << 2;
+
+                if (partial)
+                {
+                    this.WriteByte((byte)(hdr | 0x03));
+                }
+                else
+                {
+                    if (bodyLen <= 0xff)
+                    {
+                        this.WriteByte((byte) hdr);
+                        this.WriteByte((byte)bodyLen);
+                    }
+                    else if (bodyLen <= 0xffff)
+                    {
+                        this.WriteByte((byte)(hdr | 0x01));
+                        this.WriteByte((byte)(bodyLen >> 8));
+                        this.WriteByte((byte)(bodyLen));
+                    }
+                    else
+                    {
+                        this.WriteByte((byte)(hdr | 0x02));
+                        this.WriteByte((byte)(bodyLen >> 24));
+                        this.WriteByte((byte)(bodyLen >> 16));
+                        this.WriteByte((byte)(bodyLen >> 8));
+                        this.WriteByte((byte)bodyLen);
+                    }
+                }
+            }
+            else
+            {
+                hdr |= 0x40 | (int) tag;
+                this.WriteByte((byte) hdr);
+
+                if (partial)
+                {
+                    partialOffset = 0;
+                }
+                else
+                {
+                    this.WriteNewPacketLength(bodyLen);
+                }
+            }
+        }
+
+        private void PartialFlush(
+            bool isLast)
+        {
+            if (isLast)
+            {
+                WriteNewPacketLength(partialOffset);
+                outStr.Write(partialBuffer, 0, partialOffset);
+            }
+            else
+            {
+                outStr.WriteByte((byte)(0xE0 | partialPower));
+                outStr.Write(partialBuffer, 0, partialBufferLength);
+            }
+
+            partialOffset = 0;
+        }
+
+		private void WritePartial(
+            byte b)
+        {
+            if (partialOffset == partialBufferLength)
+            {
+                PartialFlush(false);
+            }
+
+			partialBuffer[partialOffset++] = b;
+        }
+
+		private void WritePartial(
+            byte[]	buffer,
+            int		off,
+            int		len)
+        {
+            if (partialOffset == partialBufferLength)
+            {
+                PartialFlush(false);
+            }
+
+            if (len <= (partialBufferLength - partialOffset))
+            {
+                Array.Copy(buffer, off, partialBuffer, partialOffset, len);
+                partialOffset += len;
+            }
+            else
+            {
+                int diff = partialBufferLength - partialOffset;
+                Array.Copy(buffer, off, partialBuffer, partialOffset, diff);
+                off += diff;
+                len -= diff;
+                PartialFlush(false);
+                while (len > partialBufferLength)
+                {
+                    Array.Copy(buffer, off, partialBuffer, 0, partialBufferLength);
+                    off += partialBufferLength;
+                    len -= partialBufferLength;
+                    PartialFlush(false);
+                }
+                Array.Copy(buffer, off, partialBuffer, 0, len);
+                partialOffset += len;
+            }
+        }
+        public override void WriteByte(
+			byte value)
+        {
+            if (partialBuffer != null)
+            {
+                WritePartial(value);
+            }
+            else
+            {
+                outStr.WriteByte(value);
+            }
+        }
+        public override void Write(
+            byte[]	buffer,
+            int		offset,
+            int		count)
+        {
+            if (partialBuffer != null)
+            {
+                WritePartial(buffer, offset, count);
+            }
+            else
+            {
+                outStr.Write(buffer, offset, count);
+            }
+        }
+
+		// Additional helper methods to write primitive types
+		internal virtual void WriteShort(
+			short n)
+		{
+			this.Write(
+				(byte)(n >> 8),
+				(byte)n);
+		}
+		internal virtual void WriteInt(
+			int n)
+		{
+			this.Write(
+				(byte)(n >> 24),
+				(byte)(n >> 16),
+				(byte)(n >> 8),
+				(byte)n);
+		}
+		internal virtual void WriteLong(
+			long n)
+		{
+			this.Write(
+				(byte)(n >> 56),
+				(byte)(n >> 48),
+				(byte)(n >> 40),
+				(byte)(n >> 32),
+				(byte)(n >> 24),
+				(byte)(n >> 16),
+				(byte)(n >> 8),
+				(byte)n);
+		}
+
+		public void WritePacket(
+            ContainedPacket p)
+        {
+            p.Encode(this);
+        }
+
+        internal void WritePacket(
+            PacketTag	tag,
+            byte[]		body,
+            bool		oldFormat)
+        {
+            this.WriteHeader(tag, oldFormat, false, body.Length);
+            this.Write(body);
+        }
+
+		public void WriteObject(
+            BcpgObject bcpgObject)
+        {
+            bcpgObject.Encode(this);
+        }
+
+		public void WriteObjects(
+			params BcpgObject[] v)
+		{
+			foreach (BcpgObject o in v)
+			{
+				o.Encode(this);
+			}
+		}
+
+		/// <summary>Flush the underlying stream.</summary>
+        public override void Flush()
+        {
+            outStr.Flush();
+        }
+
+		/// <summary>Finish writing out the current packet without closing the underlying stream.</summary>
+        public void Finish()
+        {
+            if (partialBuffer != null)
+            {
+                PartialFlush(true);
+                partialBuffer = null;
+            }
+        }
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+                this.Finish();
+                outStr.Flush();                
+                outStr.Dispose();
+	        }
+	       base.Dispose(disposing);
+	    }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/CompressedDataPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/CompressedDataPacket.cs
new file mode 100644
index 0000000..2432825
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/CompressedDataPacket.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Generic compressed data object.</remarks>
+    public class CompressedDataPacket
+        : InputStreamPacket
+    {
+        private readonly CompressionAlgorithmTag algorithm;
+
+		internal CompressedDataPacket(
+            BcpgInputStream bcpgIn)
+			: base(bcpgIn)
+        {
+            this.algorithm = (CompressionAlgorithmTag) bcpgIn.ReadByte();
+        }
+
+		/// <summary>The algorithm tag value.</summary>
+        public CompressionAlgorithmTag Algorithm
+		{
+			get { return algorithm; }
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/CompressionAlgorithmTags.cs b/BouncyCastle.AxCrypt/src/bcpg/CompressionAlgorithmTags.cs
new file mode 100644
index 0000000..0e45229
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/CompressionAlgorithmTags.cs
@@ -0,0 +1,11 @@
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic tags for compression algorithms.</remarks>
+	public enum CompressionAlgorithmTag
+	{
+		Uncompressed = 0,	// Uncompressed
+		Zip = 1,			// ZIP (RFC 1951)
+		ZLib = 2,			// ZLIB (RFC 1950)
+		BZip2 = 3,			// BZ2
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ContainedPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/ContainedPacket.cs
new file mode 100644
index 0000000..e8f387c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ContainedPacket.cs
@@ -0,0 +1,22 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic type for a PGP packet.</remarks>
+    public abstract class ContainedPacket
+        : Packet
+    {
+        public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+			pOut.WritePacket(this);
+
+			return bOut.ToArray();
+        }
+
+		public abstract void Encode(BcpgOutputStream bcpgOut);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/Crc24.cs b/BouncyCastle.AxCrypt/src/bcpg/Crc24.cs
new file mode 100644
index 0000000..97846f4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/Crc24.cs
@@ -0,0 +1,46 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    public class Crc24
+    {
+        private const int Crc24Init = 0x0b704ce;
+        private const int Crc24Poly = 0x1864cfb;
+
+        private int crc = Crc24Init;
+
+        public Crc24()
+        {
+        }
+
+        public void Update(
+            int b)
+        {
+            crc ^= b << 16;
+            for (int i = 0; i < 8; i++)
+            {
+                crc <<= 1;
+                if ((crc & 0x1000000) != 0)
+                {
+                    crc ^= Crc24Poly;
+                }
+            }
+        }
+
+		[Obsolete("Use 'Value' property instead")]
+        public int GetValue()
+        {
+            return crc;
+        }
+
+		public int Value
+		{
+			get { return crc; }
+		}
+
+		public void Reset()
+        {
+            crc = Crc24Init;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/DsaPublicBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/DsaPublicBcpgKey.cs
new file mode 100644
index 0000000..11294cc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/DsaPublicBcpgKey.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Base class for a DSA public key.</remarks>
+    public class DsaPublicBcpgKey
+        : BcpgObject, IBcpgKey
+    {
+        private readonly MPInteger p, q, g, y;
+
+        /// <param name="bcpgIn">The stream to read the packet from.</param>
+        public DsaPublicBcpgKey(
+            BcpgInputStream bcpgIn)
+        {
+            this.p = new MPInteger(bcpgIn);
+            this.q = new MPInteger(bcpgIn);
+            this.g = new MPInteger(bcpgIn);
+            this.y = new MPInteger(bcpgIn);
+        }
+
+        public DsaPublicBcpgKey(
+            BigInteger	p,
+            BigInteger	q,
+            BigInteger	g,
+            BigInteger	y)
+        {
+            this.p = new MPInteger(p);
+            this.q = new MPInteger(q);
+            this.g = new MPInteger(g);
+            this.y = new MPInteger(y);
+        }
+
+        /// <summary>The format, as a string, always "PGP".</summary>
+        public string Format
+        {
+            get { return "PGP"; }
+        }
+
+        /// <summary>Return the standard PGP encoding of the key.</summary>
+        public override byte[] GetEncoded()
+        {
+            try
+            {
+                return base.GetEncoded();
+            }
+            catch (Exception)
+            {
+                return null;
+            }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WriteObjects(p, q, g, y);
+        }
+
+        public BigInteger G
+        {
+            get { return g.Value; }
+        }
+
+        public BigInteger P
+        {
+            get { return p.Value; }
+        }
+
+        public BigInteger Q
+        {
+            get { return q.Value; }
+        }
+
+        public BigInteger Y
+        {
+            get { return y.Value; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/DsaSecretBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/DsaSecretBcpgKey.cs
new file mode 100644
index 0000000..41835d4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/DsaSecretBcpgKey.cs
@@ -0,0 +1,61 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for a DSA secret key.</remarks>
+	public class DsaSecretBcpgKey
+		: BcpgObject, IBcpgKey
+    {
+		internal MPInteger x;
+
+		/**
+		* @param in
+		*/
+		public DsaSecretBcpgKey(
+			BcpgInputStream bcpgIn)
+		{
+			this.x = new MPInteger(bcpgIn);
+		}
+
+		public DsaSecretBcpgKey(
+			BigInteger x)
+		{
+			this.x = new MPInteger(x);
+		}
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			bcpgOut.WriteObject(x);
+		}
+
+		/**
+		* @return x
+		*/
+		public BigInteger X
+		{
+			get { return x.Value; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ElGamalPublicBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/ElGamalPublicBcpgKey.cs
new file mode 100644
index 0000000..808e427
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ElGamalPublicBcpgKey.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an ElGamal public key.</remarks>
+	public class ElGamalPublicBcpgKey
+		: BcpgObject, IBcpgKey
+	{
+		internal MPInteger p, g, y;
+
+		public ElGamalPublicBcpgKey(
+			BcpgInputStream bcpgIn)
+		{
+			this.p = new MPInteger(bcpgIn);
+			this.g = new MPInteger(bcpgIn);
+			this.y = new MPInteger(bcpgIn);
+		}
+
+		public ElGamalPublicBcpgKey(
+			BigInteger p,
+			BigInteger g,
+			BigInteger y)
+		{
+			this.p = new MPInteger(p);
+			this.g = new MPInteger(g);
+			this.y = new MPInteger(y);
+		}
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+		public BigInteger P
+		{
+			get { return p.Value; }
+		}
+
+		public BigInteger G
+		{
+			get { return g.Value; }
+		}
+
+		public BigInteger Y
+		{
+			get { return y.Value; }
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			bcpgOut.WriteObjects(p, g, y);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ElGamalSecretBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/ElGamalSecretBcpgKey.cs
new file mode 100644
index 0000000..2d95b29
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ElGamalSecretBcpgKey.cs
@@ -0,0 +1,61 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an ElGamal secret key.</remarks>
+	public class ElGamalSecretBcpgKey
+		: BcpgObject, IBcpgKey
+	{
+		internal MPInteger x;
+
+		/**
+		* @param in
+		*/
+		public ElGamalSecretBcpgKey(
+			BcpgInputStream bcpgIn)
+		{
+			this.x = new MPInteger(bcpgIn);
+		}
+
+		/**
+		* @param x
+		*/
+		public ElGamalSecretBcpgKey(
+			BigInteger x)
+		{
+			this.x = new MPInteger(x);
+		}
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		public BigInteger X
+		{
+			get { return x.Value; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			bcpgOut.WriteObject(x);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ExperimentalPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/ExperimentalPacket.cs
new file mode 100644
index 0000000..36a254b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ExperimentalPacket.cs
@@ -0,0 +1,38 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for an experimental packet.</remarks>
+    public class ExperimentalPacket
+        : ContainedPacket //, PublicKeyAlgorithmTag
+    {
+        private readonly PacketTag	tag;
+        private readonly byte[]		contents;
+
+		internal ExperimentalPacket(
+            PacketTag		tag,
+            BcpgInputStream	bcpgIn)
+        {
+            this.tag = tag;
+
+			this.contents = bcpgIn.ReadAll();
+        }
+
+		public PacketTag Tag
+        {
+			get { return tag; }
+        }
+
+		public byte[] GetContents()
+        {
+			return (byte[]) contents.Clone();
+        }
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(tag, contents, true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/HashAlgorithmTags.cs b/BouncyCastle.AxCrypt/src/bcpg/HashAlgorithmTags.cs
new file mode 100644
index 0000000..96c0091
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/HashAlgorithmTags.cs
@@ -0,0 +1,19 @@
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic tags for hash algorithms.</remarks>
+	public enum HashAlgorithmTag
+	{
+		MD5 = 1,			// MD5
+		Sha1 = 2,			// SHA-1
+		RipeMD160 = 3,		// RIPE-MD/160
+		DoubleSha = 4,		// Reserved for double-width SHA (experimental)
+		MD2 = 5,			// MD2
+		Tiger192 = 6,		// Reserved for TIGER/192
+		Haval5pass160 = 7,	// Reserved for HAVAL (5 pass, 160-bit)
+
+		Sha256 = 8,			// SHA-256
+		Sha384 = 9,			// SHA-384
+		Sha512 = 10,		// SHA-512
+		Sha224 = 11,		// SHA-224
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/IBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/IBcpgKey.cs
new file mode 100644
index 0000000..2754617
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/IBcpgKey.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base interface for a PGP key.</remarks>
+    public interface IBcpgKey
+    {
+		/// <summary>
+		/// The base format for this key - in the case of the symmetric keys it will generally
+		/// be raw indicating that the key is just a straight byte representation, for an asymmetric
+		/// key the format will be PGP, indicating the key is a string of MPIs encoded in PGP format.
+		/// </summary>
+		/// <returns>"RAW" or "PGP".</returns>
+        string Format { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/InputStreamPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/InputStreamPacket.cs
new file mode 100644
index 0000000..c45efab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/InputStreamPacket.cs
@@ -0,0 +1,20 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    public class InputStreamPacket
+        : Packet
+    {
+        private readonly BcpgInputStream bcpgIn;
+
+		public InputStreamPacket(
+            BcpgInputStream bcpgIn)
+        {
+            this.bcpgIn = bcpgIn;
+        }
+
+		/// <summary>Note: you can only read from this once...</summary>
+		public BcpgInputStream GetInputStream()
+        {
+            return bcpgIn;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/LiteralDataPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/LiteralDataPacket.cs
new file mode 100644
index 0000000..63a2c6d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/LiteralDataPacket.cs
@@ -0,0 +1,57 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Generic literal data packet.</remarks>
+    public class LiteralDataPacket
+        : InputStreamPacket
+	{
+		private int		format;
+        private byte[]	fileName;
+        private long	modDate;
+
+		internal LiteralDataPacket(
+            BcpgInputStream bcpgIn)
+			: base(bcpgIn)
+        {
+            format = bcpgIn.ReadByte();
+            int len = bcpgIn.ReadByte();
+
+			fileName = new byte[len];
+			for (int i = 0; i != len; ++i)
+            {
+                fileName[i] = (byte)bcpgIn.ReadByte();
+            }
+
+			modDate = (((uint)bcpgIn.ReadByte() << 24)
+				| ((uint)bcpgIn.ReadByte() << 16)
+                | ((uint)bcpgIn.ReadByte() << 8)
+				| (uint)bcpgIn.ReadByte()) * 1000L;
+        }
+
+		/// <summary>The format tag value.</summary>
+        public int Format
+		{
+			get { return format; }
+		}
+
+		/// <summary>The modification time of the file in milli-seconds (since Jan 1, 1970 UTC)</summary>
+        public long ModificationTime
+		{
+			get { return modDate; }
+		}
+
+		public string FileName
+		{
+			get { return Strings.FromUtf8ByteArray(fileName); }
+		}
+
+		public byte[] GetRawFileName()
+		{
+			return Arrays.Clone(fileName);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/MPInteger.cs b/BouncyCastle.AxCrypt/src/bcpg/MPInteger.cs
new file mode 100644
index 0000000..4414072
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/MPInteger.cs
@@ -0,0 +1,59 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>A multiple precision integer</remarks>
+    public class MPInteger
+        : BcpgObject
+    {
+        private readonly BigInteger val;
+
+        public MPInteger(
+            BcpgInputStream bcpgIn)
+        {
+			if (bcpgIn == null)
+				throw new ArgumentNullException("bcpgIn");
+
+			int length = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
+            byte[] bytes = new byte[(length + 7) / 8];
+
+            bcpgIn.ReadFully(bytes);
+
+            this.val = new BigInteger(1, bytes);
+        }
+
+		public MPInteger(
+            BigInteger val)
+        {
+			if (val == null)
+				throw new ArgumentNullException("val");
+			if (val.SignValue < 0)
+				throw new ArgumentException("Values must be positive", "val");
+
+			this.val = val;
+        }
+
+		public BigInteger Value
+        {
+            get { return val; }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+			bcpgOut.WriteShort((short) val.BitLength);
+			bcpgOut.Write(val.ToByteArrayUnsigned());
+        }
+
+		internal static void Encode(
+			BcpgOutputStream	bcpgOut,
+			BigInteger			val)
+		{
+			bcpgOut.WriteShort((short) val.BitLength);
+			bcpgOut.Write(val.ToByteArrayUnsigned());
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/MarkerPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/MarkerPacket.cs
new file mode 100644
index 0000000..4dc4b5a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/MarkerPacket.cs
@@ -0,0 +1,24 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic type for a marker packet.</remarks>
+    public class MarkerPacket
+        : ContainedPacket
+    {
+        // "PGP"
+        byte[] marker = { (byte)0x50, (byte)0x47, (byte)0x50 };
+
+        public MarkerPacket(
+            BcpgInputStream bcpgIn)
+        {
+            bcpgIn.ReadFully(marker);
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.Marker, marker, true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/ModDetectionCodePacket.cs b/BouncyCastle.AxCrypt/src/bcpg/ModDetectionCodePacket.cs
new file mode 100644
index 0000000..6bb2364
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/ModDetectionCodePacket.cs
@@ -0,0 +1,42 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for a modification detection code packet.</remarks>
+    public class ModDetectionCodePacket
+        : ContainedPacket
+    {
+        private readonly byte[] digest;
+
+		internal ModDetectionCodePacket(
+            BcpgInputStream bcpgIn)
+        {
+			if (bcpgIn == null)
+				throw new ArgumentNullException("bcpgIn");
+
+			this.digest = new byte[20];
+            bcpgIn.ReadFully(this.digest);
+        }
+
+		public ModDetectionCodePacket(
+            byte[] digest)
+        {
+			if (digest == null)
+				throw new ArgumentNullException("digest");
+
+			this.digest = (byte[]) digest.Clone();
+        }
+
+		public byte[] GetDigest()
+        {
+			return (byte[]) digest.Clone();
+        }
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.ModificationDetectionCode, digest, false);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/OnePassSignaturePacket.cs b/BouncyCastle.AxCrypt/src/bcpg/OnePassSignaturePacket.cs
new file mode 100644
index 0000000..b67df0a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/OnePassSignaturePacket.cs
@@ -0,0 +1,93 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Generic signature object</remarks>
+	public class OnePassSignaturePacket
+		: ContainedPacket
+	{
+		private int version;
+		private int sigType;
+		private HashAlgorithmTag hashAlgorithm;
+		private PublicKeyAlgorithmTag keyAlgorithm;
+		private long keyId;
+		private int nested;
+
+		internal OnePassSignaturePacket(
+			BcpgInputStream	bcpgIn)
+		{
+			version = bcpgIn.ReadByte();
+			sigType = bcpgIn.ReadByte();
+			hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte();
+			keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
+
+			keyId |= (long)bcpgIn.ReadByte() << 56;
+			keyId |= (long)bcpgIn.ReadByte() << 48;
+			keyId |= (long)bcpgIn.ReadByte() << 40;
+			keyId |= (long)bcpgIn.ReadByte() << 32;
+			keyId |= (long)bcpgIn.ReadByte() << 24;
+			keyId |= (long)bcpgIn.ReadByte() << 16;
+			keyId |= (long)bcpgIn.ReadByte() << 8;
+			keyId |= (uint)bcpgIn.ReadByte();
+
+			nested = bcpgIn.ReadByte();
+		}
+
+		public OnePassSignaturePacket(
+			int						sigType,
+			HashAlgorithmTag		hashAlgorithm,
+			PublicKeyAlgorithmTag	keyAlgorithm,
+			long					keyId,
+			bool					isNested)
+		{
+			this.version = 3;
+			this.sigType = sigType;
+			this.hashAlgorithm = hashAlgorithm;
+			this.keyAlgorithm = keyAlgorithm;
+			this.keyId = keyId;
+			this.nested = (isNested) ? 0 : 1;
+		}
+
+		public int SignatureType
+		{
+			get { return sigType; }
+		}
+
+		/// <summary>The encryption algorithm tag.</summary>
+		public PublicKeyAlgorithmTag KeyAlgorithm
+		{
+			get { return keyAlgorithm; }
+		}
+
+		/// <summary>The hash algorithm tag.</summary>
+		public HashAlgorithmTag HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+		}
+
+		public long KeyId
+		{
+			get { return keyId; }
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			MemoryStream bOut = new MemoryStream();
+			BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+			pOut.Write(
+				(byte) version,
+				(byte) sigType,
+				(byte) hashAlgorithm,
+				(byte) keyAlgorithm);
+
+			pOut.WriteLong(keyId);
+
+			pOut.WriteByte((byte) nested);
+
+			bcpgOut.WritePacket(PacketTag.OnePassSignature, bOut.ToArray(), true);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/OutputStreamPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/OutputStreamPacket.cs
new file mode 100644
index 0000000..4eae141
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/OutputStreamPacket.cs
@@ -0,0 +1,24 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    public abstract class OutputStreamPacket
+    {
+        //private readonly BcpgOutputStream bcpgOut;
+
+		internal OutputStreamPacket(
+            BcpgOutputStream bcpgOut)
+        {
+			if (bcpgOut == null)
+				throw new ArgumentNullException("bcpgOut");
+
+		//	this.bcpgOut = bcpgOut;
+        }
+
+		public abstract BcpgOutputStream Open();
+
+		public abstract void Close();
+    }
+}
+
diff --git a/BouncyCastle.AxCrypt/src/bcpg/Packet.cs b/BouncyCastle.AxCrypt/src/bcpg/Packet.cs
new file mode 100644
index 0000000..83f6d1f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/Packet.cs
@@ -0,0 +1,7 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    public class Packet
+        //: PacketTag
+    {
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/PacketTags.cs b/BouncyCastle.AxCrypt/src/bcpg/PacketTags.cs
new file mode 100644
index 0000000..5a53d4e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/PacketTags.cs
@@ -0,0 +1,30 @@
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic PGP packet tag types.</remarks>
+    public enum PacketTag
+    {
+        Reserved =  0,								//  Reserved - a packet tag must not have this value
+        PublicKeyEncryptedSession = 1,				// Public-Key Encrypted Session Key Packet
+        Signature = 2,								// Signature Packet
+        SymmetricKeyEncryptedSessionKey = 3,		// Symmetric-Key Encrypted Session Key Packet
+        OnePassSignature = 4,						// One-Pass Signature Packet
+        SecretKey = 5,								// Secret Key Packet
+        PublicKey = 6,								// Public Key Packet
+        SecretSubkey = 7,							// Secret Subkey Packet
+        CompressedData = 8,							// Compressed Data Packet
+        SymmetricKeyEncrypted = 9,					// Symmetrically Encrypted Data Packet
+        Marker = 10,								// Marker Packet
+        LiteralData = 11,							// Literal Data Packet
+        Trust = 12,									// Trust Packet
+        UserId = 13,								// User ID Packet
+        PublicSubkey = 14,							// Public Subkey Packet
+        UserAttribute = 17,							// User attribute
+        SymmetricEncryptedIntegrityProtected = 18,	// Symmetric encrypted, integrity protected
+        ModificationDetectionCode = 19,				// Modification detection code
+
+        Experimental1 = 60,							// Private or Experimental Values
+        Experimental2 = 61,
+        Experimental3 = 62,
+        Experimental4 = 63
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/PublicKeyAlgorithmTags.cs b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyAlgorithmTags.cs
new file mode 100644
index 0000000..85ae548
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyAlgorithmTags.cs
@@ -0,0 +1,28 @@
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Public Key Algorithm tag numbers.</remarks>
+    public enum PublicKeyAlgorithmTag
+    {
+        RsaGeneral = 1,			// RSA (Encrypt or Sign)
+        RsaEncrypt = 2,			// RSA Encrypt-Only
+        RsaSign = 3,			// RSA Sign-Only
+        ElGamalEncrypt = 16,	// Elgamal (Encrypt-Only), see [ELGAMAL]
+        Dsa = 17,				// DSA (Digital Signature Standard)
+        EC = 18,				// Reserved for Elliptic Curve
+        ECDsa = 19,				// Reserved for ECDSA
+        ElGamalGeneral = 20,	// Elgamal (Encrypt or Sign)
+        DiffieHellman = 21,		// Reserved for Diffie-Hellman (X9.42, as defined for IETF-S/MIME)
+
+		Experimental_1 = 100,
+		Experimental_2 = 101,
+		Experimental_3 = 102,
+		Experimental_4 = 103,
+		Experimental_5 = 104,
+		Experimental_6 = 105,
+		Experimental_7 = 106,
+		Experimental_8 = 107,
+		Experimental_9 = 108,
+		Experimental_10 = 109,
+		Experimental_11 = 110,
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/PublicKeyEncSessionPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyEncSessionPacket.cs
new file mode 100644
index 0000000..d10605f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyEncSessionPacket.cs
@@ -0,0 +1,103 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for a PGP public key.</remarks>
+	public class PublicKeyEncSessionPacket
+		: ContainedPacket //, PublicKeyAlgorithmTag
+	{
+		private int version;
+		private long keyId;
+		private PublicKeyAlgorithmTag algorithm;
+		private BigInteger[] data;
+
+		internal PublicKeyEncSessionPacket(
+			BcpgInputStream bcpgIn)
+		{
+			version = bcpgIn.ReadByte();
+
+			keyId |= (long)bcpgIn.ReadByte() << 56;
+			keyId |= (long)bcpgIn.ReadByte() << 48;
+			keyId |= (long)bcpgIn.ReadByte() << 40;
+			keyId |= (long)bcpgIn.ReadByte() << 32;
+			keyId |= (long)bcpgIn.ReadByte() << 24;
+			keyId |= (long)bcpgIn.ReadByte() << 16;
+			keyId |= (long)bcpgIn.ReadByte() << 8;
+			keyId |= (uint)bcpgIn.ReadByte();
+
+			algorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
+
+			switch ((PublicKeyAlgorithmTag) algorithm)
+			{
+				case PublicKeyAlgorithmTag.RsaEncrypt:
+				case PublicKeyAlgorithmTag.RsaGeneral:
+					data = new BigInteger[]{ new MPInteger(bcpgIn).Value };
+					break;
+				case PublicKeyAlgorithmTag.ElGamalEncrypt:
+				case PublicKeyAlgorithmTag.ElGamalGeneral:
+					data = new BigInteger[]
+					{
+						new MPInteger(bcpgIn).Value,
+						new MPInteger(bcpgIn).Value
+					};
+					break;
+				default:
+					throw new IOException("unknown PGP public key algorithm encountered");
+			}
+		}
+
+		public PublicKeyEncSessionPacket(
+			long					keyId,
+			PublicKeyAlgorithmTag	algorithm,
+			BigInteger[]			data)
+		{
+			this.version = 3;
+			this.keyId = keyId;
+			this.algorithm = algorithm;
+			this.data = (BigInteger[]) data.Clone();
+		}
+
+		public int Version
+		{
+			get { return version; }
+		}
+
+		public long KeyId
+		{
+			get { return keyId; }
+		}
+
+		public PublicKeyAlgorithmTag Algorithm
+		{
+			get { return algorithm; }
+		}
+
+		public BigInteger[] GetEncSessionKey()
+		{
+			return (BigInteger[]) data.Clone();
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			MemoryStream bOut = new MemoryStream();
+			BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+			pOut.WriteByte((byte) version);
+
+			pOut.WriteLong(keyId);
+
+			pOut.WriteByte((byte)algorithm);
+
+			for (int i = 0; i != data.Length; i++)
+			{
+				MPInteger.Encode(pOut, data[i]);
+			}
+
+			bcpgOut.WritePacket(PacketTag.PublicKeyEncryptedSession , bOut.ToArray(), true);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/PublicKeyPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyPacket.cs
new file mode 100644
index 0000000..a45aeb4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/PublicKeyPacket.cs
@@ -0,0 +1,115 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <remarks>Basic packet for a PGP public key.</remarks>
+    public class PublicKeyPacket
+        : ContainedPacket //, PublicKeyAlgorithmTag
+    {
+        private int version;
+        private long time;
+        private int validDays;
+        private PublicKeyAlgorithmTag algorithm;
+        private IBcpgKey key;
+
+        internal PublicKeyPacket(
+            BcpgInputStream bcpgIn)
+        {
+            version = bcpgIn.ReadByte();
+
+            time = ((uint)bcpgIn.ReadByte() << 24) | ((uint)bcpgIn.ReadByte() << 16)
+                | ((uint)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte();
+
+            if (version <= 3)
+            {
+                validDays = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
+            }
+
+            algorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
+
+            switch ((PublicKeyAlgorithmTag) algorithm)
+            {
+                case PublicKeyAlgorithmTag.RsaEncrypt:
+                case PublicKeyAlgorithmTag.RsaGeneral:
+                case PublicKeyAlgorithmTag.RsaSign:
+                    key = new RsaPublicBcpgKey(bcpgIn);
+                    break;
+                case PublicKeyAlgorithmTag.Dsa:
+                    key = new DsaPublicBcpgKey(bcpgIn);
+                    break;
+                case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                case PublicKeyAlgorithmTag.ElGamalGeneral:
+                    key = new ElGamalPublicBcpgKey(bcpgIn);
+                    break;
+                default:
+                    throw new IOException("unknown PGP public key algorithm encountered");
+            }
+        }
+
+        /// <summary>Construct a version 4 public key packet.</summary>
+        public PublicKeyPacket(
+            PublicKeyAlgorithmTag	algorithm,
+            DateTime				time,
+            IBcpgKey				key)
+        {
+            this.version = 4;
+            this.time = DateTimeUtilities.DateTimeToUnixMs(time) / 1000L;
+            this.algorithm = algorithm;
+            this.key = key;
+        }
+
+        public virtual int Version
+        {
+            get { return version; }
+        }
+
+        public virtual PublicKeyAlgorithmTag Algorithm
+        {
+            get { return algorithm; }
+        }
+
+        public virtual int ValidDays
+        {
+            get { return validDays; }
+        }
+
+        public virtual DateTime GetTime()
+        {
+            return DateTimeUtilities.UnixMsToDateTime(time * 1000L);
+        }
+
+        public virtual IBcpgKey Key
+        {
+            get { return key; }
+        }
+
+        public virtual byte[] GetEncodedContents()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+            pOut.WriteByte((byte) version);
+            pOut.WriteInt((int) time);
+
+            if (version <= 3)
+            {
+                pOut.WriteShort((short) validDays);
+            }
+
+            pOut.WriteByte((byte) algorithm);
+
+            pOut.WriteObject((BcpgObject)key);
+
+            return bOut.ToArray();
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.PublicKey, GetEncodedContents(), true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/PublicSubkeyPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/PublicSubkeyPacket.cs
new file mode 100644
index 0000000..6e1aeda
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/PublicSubkeyPacket.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for a PGP public subkey</remarks>
+    public class PublicSubkeyPacket
+        : PublicKeyPacket
+    {
+        internal PublicSubkeyPacket(
+            BcpgInputStream bcpgIn)
+			: base(bcpgIn)
+        {
+        }
+
+		/// <summary>Construct a version 4 public subkey packet.</summary>
+        public PublicSubkeyPacket(
+            PublicKeyAlgorithmTag	algorithm,
+            DateTime				time,
+            IBcpgKey				key)
+            : base(algorithm, time, key)
+        {
+        }
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.PublicSubkey, GetEncodedContents(), true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/RsaPublicBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/RsaPublicBcpgKey.cs
new file mode 100644
index 0000000..fd2313c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/RsaPublicBcpgKey.cs
@@ -0,0 +1,66 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an RSA public key.</remarks>
+	public class RsaPublicBcpgKey
+		: BcpgObject, IBcpgKey
+	{
+		private readonly MPInteger n, e;
+
+		/// <summary>Construct an RSA public key from the passed in stream.</summary>
+		public RsaPublicBcpgKey(
+			BcpgInputStream bcpgIn)
+		{
+			this.n = new MPInteger(bcpgIn);
+			this.e = new MPInteger(bcpgIn);
+		}
+
+		/// <param name="n">The modulus.</param>
+		/// <param name="e">The public exponent.</param>
+		public RsaPublicBcpgKey(
+			BigInteger	n,
+			BigInteger	e)
+		{
+			this.n = new MPInteger(n);
+			this.e = new MPInteger(e);
+		}
+
+		public BigInteger PublicExponent
+		{
+			get { return e.Value; }
+		}
+
+		public BigInteger Modulus
+		{
+			get { return n.Value; }
+		}
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			bcpgOut.WriteObjects(n, e);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/RsaSecretBcpgKey.cs b/BouncyCastle.AxCrypt/src/bcpg/RsaSecretBcpgKey.cs
new file mode 100644
index 0000000..5c04d9f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/RsaSecretBcpgKey.cs
@@ -0,0 +1,114 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Base class for an RSA secret (or priate) key.</remarks>
+	public class RsaSecretBcpgKey
+		: BcpgObject, IBcpgKey
+	{
+		private readonly MPInteger d, p, q, u;
+		private readonly BigInteger expP, expQ, crt;
+
+		public RsaSecretBcpgKey(
+			BcpgInputStream bcpgIn)
+		{
+			this.d = new MPInteger(bcpgIn);
+			this.p = new MPInteger(bcpgIn);
+			this.q = new MPInteger(bcpgIn);
+			this.u = new MPInteger(bcpgIn);
+
+			this.expP = d.Value.Remainder(p.Value.Subtract(BigInteger.One));
+			this.expQ = d.Value.Remainder(q.Value.Subtract(BigInteger.One));
+			this.crt = q.Value.ModInverse(p.Value);
+		}
+
+		public RsaSecretBcpgKey(
+			BigInteger d,
+			BigInteger p,
+			BigInteger q)
+		{
+			// PGP requires (p < q)
+			int cmp = p.CompareTo(q);
+			if (cmp >= 0)
+			{
+				if (cmp == 0)
+					throw new ArgumentException("p and q cannot be equal");
+
+				BigInteger tmp = p;
+				p = q;
+				q = tmp;
+			}
+
+			this.d = new MPInteger(d);
+			this.p = new MPInteger(p);
+			this.q = new MPInteger(q);
+			this.u = new MPInteger(p.ModInverse(q));
+
+			this.expP = d.Remainder(p.Subtract(BigInteger.One));
+			this.expQ = d.Remainder(q.Subtract(BigInteger.One));
+			this.crt = q.ModInverse(p);
+		}
+
+		public BigInteger Modulus
+		{
+			get { return p.Value.Multiply(q.Value); }
+		}
+
+		public BigInteger PrivateExponent
+		{
+			get { return d.Value; }
+		}
+
+		public BigInteger PrimeP
+		{
+			get { return p.Value; }
+		}
+
+		public BigInteger PrimeQ
+		{
+			get { return q.Value; }
+		}
+
+		public BigInteger PrimeExponentP
+		{
+			get { return expP; }
+		}
+
+		public BigInteger PrimeExponentQ
+		{
+			get { return expQ; }
+		}
+
+		public BigInteger CrtCoefficient
+		{
+			get { return crt; }
+		}
+
+		/// <summary>The format, as a string, always "PGP".</summary>
+		public string Format
+		{
+			get { return "PGP"; }
+		}
+
+		/// <summary>Return the standard PGP encoding of the key.</summary>
+		public override byte[] GetEncoded()
+		{
+			try
+			{
+				return base.GetEncoded();
+			}
+			catch (Exception)
+			{
+				return null;
+			}
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+		{
+			bcpgOut.WriteObjects(d, p, q, u);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/S2k.cs b/BouncyCastle.AxCrypt/src/bcpg/S2k.cs
new file mode 100644
index 0000000..de08c01
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/S2k.cs
@@ -0,0 +1,147 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>The string to key specifier class.</remarks>
+    public class S2k
+        : BcpgObject
+    {
+        private const int ExpBias = 6;
+
+        public const int Simple = 0;
+        public const int Salted = 1;
+        public const int SaltedAndIterated = 3;
+        public const int GnuDummyS2K = 101;
+
+        internal int type;
+        internal HashAlgorithmTag algorithm;
+        internal byte[] iv;
+        internal int itCount = -1;
+        internal int protectionMode = -1;
+
+        internal S2k(
+            Stream inStr)
+        {
+			type = inStr.ReadByte();
+            algorithm = (HashAlgorithmTag) inStr.ReadByte();
+
+            //
+            // if this happens we have a dummy-S2k packet.
+            //
+            if (type != GnuDummyS2K)
+            {
+                if (type != 0)
+                {
+					iv = new byte[8];
+					if (Streams.ReadFully(inStr, iv, 0, iv.Length) < iv.Length)
+						throw new EndOfStreamException();
+
+					if (type == 3)
+					{
+						itCount = inStr.ReadByte();
+					}
+				}
+            }
+            else
+            {
+                inStr.ReadByte(); // G
+                inStr.ReadByte(); // N
+                inStr.ReadByte(); // U
+                protectionMode = inStr.ReadByte(); // protection mode
+            }
+        }
+
+        public S2k(
+            HashAlgorithmTag algorithm)
+        {
+            this.type = 0;
+            this.algorithm = algorithm;
+        }
+
+        public S2k(
+            HashAlgorithmTag algorithm,
+            byte[] iv)
+        {
+            this.type = 1;
+            this.algorithm = algorithm;
+            this.iv = iv;
+        }
+
+        public S2k(
+            HashAlgorithmTag algorithm,
+            byte[] iv,
+            int itCount)
+        {
+            this.type = 3;
+            this.algorithm = algorithm;
+            this.iv = iv;
+            this.itCount = itCount;
+        }
+
+        public int Type
+        {
+			get { return type; }
+        }
+
+		/// <summary>The hash algorithm.</summary>
+        public HashAlgorithmTag HashAlgorithm
+        {
+			get { return algorithm; }
+		}
+
+		/// <summary>The IV for the key generation algorithm.</summary>
+        public byte[] GetIV()
+        {
+            return Arrays.Clone(iv);
+        }
+
+		[Obsolete("Use 'IterationCount' property instead")]
+        public long GetIterationCount()
+        {
+            return IterationCount;
+        }
+
+		/// <summary>The iteration count</summary>
+		public long IterationCount
+		{
+			get { return (16 + (itCount & 15)) << ((itCount >> 4) + ExpBias); }
+		}
+
+		/// <summary>The protection mode - only if GnuDummyS2K</summary>
+        public int ProtectionMode
+        {
+			get { return protectionMode; }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WriteByte((byte) type);
+            bcpgOut.WriteByte((byte) algorithm);
+
+            if (type != GnuDummyS2K)
+            {
+                if (type != 0)
+                {
+                    bcpgOut.Write(iv);
+                }
+
+                if (type == 3)
+                {
+                    bcpgOut.WriteByte((byte) itCount);
+                }
+            }
+            else
+            {
+                bcpgOut.WriteByte((byte) 'G');
+                bcpgOut.WriteByte((byte) 'N');
+                bcpgOut.WriteByte((byte) 'U');
+                bcpgOut.WriteByte((byte) protectionMode);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SecretKeyPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SecretKeyPacket.cs
new file mode 100644
index 0000000..d9ceab4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SecretKeyPacket.cs
@@ -0,0 +1,170 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for a PGP secret key.</remarks>
+    public class SecretKeyPacket
+        : ContainedPacket //, PublicKeyAlgorithmTag
+    {
+		public const int UsageNone = 0x00;
+		public const int UsageChecksum = 0xff;
+		public const int UsageSha1 = 0xfe;
+
+		private PublicKeyPacket pubKeyPacket;
+        private readonly byte[] secKeyData;
+		private int s2kUsage;
+		private SymmetricKeyAlgorithmTag encAlgorithm;
+        private S2k s2k;
+        private byte[] iv;
+
+		internal SecretKeyPacket(
+            BcpgInputStream bcpgIn)
+        {
+			if (this is SecretSubkeyPacket)
+			{
+				pubKeyPacket = new PublicSubkeyPacket(bcpgIn);
+			}
+			else
+			{
+				pubKeyPacket = new PublicKeyPacket(bcpgIn);
+			}
+
+			s2kUsage = bcpgIn.ReadByte();
+
+			if (s2kUsage == UsageChecksum || s2kUsage == UsageSha1)
+            {
+                encAlgorithm = (SymmetricKeyAlgorithmTag) bcpgIn.ReadByte();
+                s2k = new S2k(bcpgIn);
+            }
+            else
+            {
+                encAlgorithm = (SymmetricKeyAlgorithmTag) s2kUsage;
+			}
+
+			if (!(s2k != null && s2k.Type == S2k.GnuDummyS2K && s2k.ProtectionMode == 0x01))
+            {
+				if (s2kUsage != 0)
+				{
+                    if (((int) encAlgorithm) < 7)
+                    {
+                        iv = new byte[8];
+                    }
+                    else
+                    {
+                        iv = new byte[16];
+                    }
+                    bcpgIn.ReadFully(iv);
+                }
+            }
+
+			secKeyData = bcpgIn.ReadAll();
+        }
+
+		public SecretKeyPacket(
+            PublicKeyPacket				pubKeyPacket,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            S2k							s2k,
+            byte[]						iv,
+            byte[]						secKeyData)
+        {
+            this.pubKeyPacket = pubKeyPacket;
+            this.encAlgorithm = encAlgorithm;
+
+			if (encAlgorithm != SymmetricKeyAlgorithmTag.Null)
+			{
+				this.s2kUsage = UsageChecksum;
+			}
+			else
+			{
+				this.s2kUsage = UsageNone;
+			}
+
+			this.s2k = s2k;
+			this.iv = Arrays.Clone(iv);
+			this.secKeyData = secKeyData;
+        }
+
+		public SecretKeyPacket(
+			PublicKeyPacket				pubKeyPacket,
+			SymmetricKeyAlgorithmTag	encAlgorithm,
+			int							s2kUsage,
+			S2k							s2k,
+			byte[]						iv,
+			byte[]						secKeyData)
+		{
+			this.pubKeyPacket = pubKeyPacket;
+			this.encAlgorithm = encAlgorithm;
+			this.s2kUsage = s2kUsage;
+			this.s2k = s2k;
+			this.iv = Arrays.Clone(iv);
+			this.secKeyData = secKeyData;
+		}
+
+		public SymmetricKeyAlgorithmTag EncAlgorithm
+        {
+			get { return encAlgorithm; }
+        }
+
+		public int S2kUsage
+		{
+			get { return s2kUsage; }
+		}
+
+		public byte[] GetIV()
+        {
+            return Arrays.Clone(iv);
+        }
+
+		public S2k S2k
+        {
+			get { return s2k; }
+        }
+
+		public PublicKeyPacket PublicKeyPacket
+        {
+			get { return pubKeyPacket; }
+        }
+
+		public byte[] GetSecretKeyData()
+        {
+            return secKeyData;
+        }
+
+		public byte[] GetEncodedContents()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+            pOut.Write(pubKeyPacket.GetEncodedContents());
+
+			pOut.WriteByte((byte) s2kUsage);
+
+			if (s2kUsage == UsageChecksum || s2kUsage == UsageSha1)
+            {
+                pOut.WriteByte((byte) encAlgorithm);
+                pOut.WriteObject(s2k);
+            }
+
+			if (iv != null)
+            {
+                pOut.Write(iv);
+            }
+
+            if (secKeyData != null && secKeyData.Length > 0)
+            {
+                pOut.Write(secKeyData);
+            }
+
+            return bOut.ToArray();
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.SecretKey, GetEncodedContents(), true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SecretSubkeyPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SecretSubkeyPacket.cs
new file mode 100644
index 0000000..8f17469
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SecretSubkeyPacket.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic packet for a PGP secret key.</remarks>
+    public class SecretSubkeyPacket
+        : SecretKeyPacket
+    {
+        internal SecretSubkeyPacket(
+			BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+        }
+
+		public SecretSubkeyPacket(
+            PublicKeyPacket				pubKeyPacket,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            S2k							s2k,
+            byte[]						iv,
+            byte[]						secKeyData)
+            : base(pubKeyPacket, encAlgorithm, s2k, iv, secKeyData)
+        {
+        }
+
+		public SecretSubkeyPacket(
+			PublicKeyPacket				pubKeyPacket,
+			SymmetricKeyAlgorithmTag	encAlgorithm,
+			int							s2kUsage,
+			S2k							s2k,
+			byte[]						iv,
+			byte[]						secKeyData)
+			: base(pubKeyPacket, encAlgorithm, s2kUsage, s2k, iv, secKeyData)
+		{
+		}
+
+		public override void Encode(
+			BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.SecretSubkey, GetEncodedContents(), true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SignaturePacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SignaturePacket.cs
new file mode 100644
index 0000000..605ce84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SignaturePacket.cs
@@ -0,0 +1,472 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Generic signature packet.</remarks>
+    public class SignaturePacket
+        : ContainedPacket //, PublicKeyAlgorithmTag
+    {
+		private int						version;
+        private int						signatureType;
+        private long					creationTime;
+        private long					keyId;
+        private PublicKeyAlgorithmTag	keyAlgorithm;
+        private HashAlgorithmTag		hashAlgorithm;
+        private MPInteger[]				signature;
+        private byte[]					fingerprint;
+        private SignatureSubpacket[]	hashedData;
+        private SignatureSubpacket[]	unhashedData;
+		private byte[]					signatureEncoding;
+
+		internal SignaturePacket(
+            BcpgInputStream bcpgIn)
+        {
+            version = bcpgIn.ReadByte();
+
+			if (version == 3 || version == 2)
+            {
+//                int l =
+                bcpgIn.ReadByte();
+
+				signatureType = bcpgIn.ReadByte();
+                creationTime = (((long)bcpgIn.ReadByte() << 24) | ((long)bcpgIn.ReadByte() << 16)
+                    | ((long)bcpgIn.ReadByte() << 8) | (uint)bcpgIn.ReadByte()) * 1000L;
+
+				keyId |= (long)bcpgIn.ReadByte() << 56;
+                keyId |= (long)bcpgIn.ReadByte() << 48;
+                keyId |= (long)bcpgIn.ReadByte() << 40;
+                keyId |= (long)bcpgIn.ReadByte() << 32;
+                keyId |= (long)bcpgIn.ReadByte() << 24;
+                keyId |= (long)bcpgIn.ReadByte() << 16;
+                keyId |= (long)bcpgIn.ReadByte() << 8;
+                keyId |= (uint)bcpgIn.ReadByte();
+
+				keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
+                hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte();
+            }
+            else if (version == 4)
+            {
+                signatureType = bcpgIn.ReadByte();
+                keyAlgorithm = (PublicKeyAlgorithmTag) bcpgIn.ReadByte();
+                hashAlgorithm = (HashAlgorithmTag) bcpgIn.ReadByte();
+
+				int hashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
+                byte[] hashed = new byte[hashedLength];
+
+				bcpgIn.ReadFully(hashed);
+
+				//
+                // read the signature sub packet data.
+                //
+                SignatureSubpacketsParser sIn = new SignatureSubpacketsParser(
+                    new MemoryStream(hashed, false));
+
+				IList v = Platform.CreateArrayList();
+				SignatureSubpacket sub;
+				while ((sub = sIn.ReadPacket()) != null)
+                {
+                    v.Add(sub);
+                }
+
+				hashedData = new SignatureSubpacket[v.Count];
+
+				for (int i = 0; i != hashedData.Length; i++)
+                {
+                    SignatureSubpacket p = (SignatureSubpacket)v[i];
+                    if (p is IssuerKeyId)
+                    {
+                        keyId = ((IssuerKeyId)p).KeyId;
+                    }
+                    else if (p is SignatureCreationTime)
+                    {
+                        creationTime = DateTimeUtilities.DateTimeToUnixMs(
+							((SignatureCreationTime)p).GetTime());
+                    }
+
+					hashedData[i] = p;
+                }
+
+				int unhashedLength = (bcpgIn.ReadByte() << 8) | bcpgIn.ReadByte();
+                byte[] unhashed = new byte[unhashedLength];
+
+				bcpgIn.ReadFully(unhashed);
+
+				sIn = new SignatureSubpacketsParser(new MemoryStream(unhashed, false));
+
+				v.Clear();
+
+				while ((sub = sIn.ReadPacket()) != null)
+                {
+                    v.Add(sub);
+                }
+
+				unhashedData = new SignatureSubpacket[v.Count];
+
+				for (int i = 0; i != unhashedData.Length; i++)
+                {
+                    SignatureSubpacket p = (SignatureSubpacket)v[i];
+                    if (p is IssuerKeyId)
+                    {
+                        keyId = ((IssuerKeyId)p).KeyId;
+                    }
+
+					unhashedData[i] = p;
+                }
+            }
+            else
+            {
+                throw new Exception("unsupported version: " + version);
+            }
+
+			fingerprint = new byte[2];
+            bcpgIn.ReadFully(fingerprint);
+
+			switch (keyAlgorithm)
+            {
+                case PublicKeyAlgorithmTag.RsaGeneral:
+                case PublicKeyAlgorithmTag.RsaSign:
+                    MPInteger v = new MPInteger(bcpgIn);
+					signature = new MPInteger[]{ v };
+                    break;
+				case PublicKeyAlgorithmTag.Dsa:
+                    MPInteger r = new MPInteger(bcpgIn);
+                    MPInteger s = new MPInteger(bcpgIn);
+					signature = new MPInteger[]{ r, s };
+                    break;
+                case PublicKeyAlgorithmTag.ElGamalEncrypt: // yep, this really does happen sometimes.
+                case PublicKeyAlgorithmTag.ElGamalGeneral:
+                    MPInteger p = new MPInteger(bcpgIn);
+                    MPInteger g = new MPInteger(bcpgIn);
+                    MPInteger y = new MPInteger(bcpgIn);
+					signature = new MPInteger[]{ p, g, y };
+                    break;
+                default:
+					if (keyAlgorithm >= PublicKeyAlgorithmTag.Experimental_1 && keyAlgorithm <= PublicKeyAlgorithmTag.Experimental_11)
+					{
+						signature = null;
+						MemoryStream bOut = new MemoryStream();
+						int ch;
+						while ((ch = bcpgIn.ReadByte()) >= 0)
+						{
+							bOut.WriteByte((byte) ch);
+						}
+						signatureEncoding = bOut.ToArray();
+					}
+					else
+					{
+						throw new IOException("unknown signature key algorithm: " + keyAlgorithm);
+					}
+					break;
+            }
+        }
+
+		/**
+        * Generate a version 4 signature packet.
+        *
+        * @param signatureType
+        * @param keyAlgorithm
+        * @param hashAlgorithm
+        * @param hashedData
+        * @param unhashedData
+        * @param fingerprint
+        * @param signature
+        */
+        public SignaturePacket(
+            int						signatureType,
+            long					keyId,
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            SignatureSubpacket[]	hashedData,
+            SignatureSubpacket[]	unhashedData,
+            byte[]					fingerprint,
+            MPInteger[]				signature)
+            : this(4, signatureType, keyId, keyAlgorithm, hashAlgorithm, hashedData, unhashedData, fingerprint, signature)
+        {
+        }
+
+		/**
+        * Generate a version 2/3 signature packet.
+        *
+        * @param signatureType
+        * @param keyAlgorithm
+        * @param hashAlgorithm
+        * @param fingerprint
+        * @param signature
+        */
+        public SignaturePacket(
+            int						version,
+            int						signatureType,
+            long					keyId,
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            long					creationTime,
+            byte[]					fingerprint,
+            MPInteger[]				signature)
+            : this(version, signatureType, keyId, keyAlgorithm, hashAlgorithm, null, null, fingerprint, signature)
+        {
+			this.creationTime = creationTime;
+        }
+
+		public SignaturePacket(
+            int						version,
+            int						signatureType,
+            long					keyId,
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            SignatureSubpacket[]	hashedData,
+            SignatureSubpacket[]	unhashedData,
+            byte[]					fingerprint,
+            MPInteger[]				signature)
+        {
+            this.version = version;
+            this.signatureType = signatureType;
+            this.keyId = keyId;
+            this.keyAlgorithm = keyAlgorithm;
+            this.hashAlgorithm = hashAlgorithm;
+            this.hashedData = hashedData;
+            this.unhashedData = unhashedData;
+            this.fingerprint = fingerprint;
+            this.signature = signature;
+
+			if (hashedData != null)
+			{
+				setCreationTime();
+			}
+		}
+
+		public int Version
+        {
+			get { return version; }
+        }
+
+		public int SignatureType
+        {
+			get { return signatureType; }
+		}
+
+		/**
+        * return the keyId
+        * @return the keyId that created the signature.
+        */
+        public long KeyId
+        {
+            get { return keyId; }
+        }
+
+		/**
+        * return the signature trailer that must be included with the data
+        * to reconstruct the signature
+        *
+        * @return byte[]
+        */
+        public byte[] GetSignatureTrailer()
+        {
+            byte[] trailer = null;
+
+			if (version == 3)
+            {
+                trailer = new byte[5];
+
+				long time = creationTime / 1000L;
+
+				trailer[0] = (byte)signatureType;
+                trailer[1] = (byte)(time >> 24);
+                trailer[2] = (byte)(time >> 16);
+                trailer[3] = (byte)(time >> 8);
+                trailer[4] = (byte)(time);
+            }
+            else
+            {
+                MemoryStream sOut = new MemoryStream();
+
+				sOut.WriteByte((byte)this.Version);
+                sOut.WriteByte((byte)this.SignatureType);
+                sOut.WriteByte((byte)this.KeyAlgorithm);
+                sOut.WriteByte((byte)this.HashAlgorithm);
+
+				MemoryStream hOut = new MemoryStream();
+                SignatureSubpacket[] hashed = this.GetHashedSubPackets();
+
+				for (int i = 0; i != hashed.Length; i++)
+                {
+                    hashed[i].Encode(hOut);
+                }
+
+				byte[] data = hOut.ToArray();
+
+				sOut.WriteByte((byte)(data.Length >> 8));
+                sOut.WriteByte((byte)data.Length);
+                sOut.Write(data, 0, data.Length);
+
+				byte[] hData = sOut.ToArray();
+
+				sOut.WriteByte((byte)this.Version);
+                sOut.WriteByte((byte)0xff);
+                sOut.WriteByte((byte)(hData.Length>> 24));
+                sOut.WriteByte((byte)(hData.Length >> 16));
+                sOut.WriteByte((byte)(hData.Length >> 8));
+                sOut.WriteByte((byte)(hData.Length));
+
+				trailer = sOut.ToArray();
+            }
+
+			return trailer;
+        }
+
+		public PublicKeyAlgorithmTag KeyAlgorithm
+        {
+			get { return keyAlgorithm; }
+        }
+
+		public HashAlgorithmTag HashAlgorithm
+		{
+			get { return hashAlgorithm; }
+        }
+
+		/**
+		* return the signature as a set of integers - note this is normalised to be the
+        * ASN.1 encoding of what appears in the signature packet.
+        */
+        public MPInteger[] GetSignature()
+        {
+            return signature;
+        }
+
+		/**
+		 * Return the byte encoding of the signature section.
+		 * @return uninterpreted signature bytes.
+		 */
+		public byte[] GetSignatureBytes()
+		{
+			if (signatureEncoding != null)
+			{
+				return (byte[]) signatureEncoding.Clone();
+			}
+
+			MemoryStream bOut = new MemoryStream();
+			BcpgOutputStream bcOut = new BcpgOutputStream(bOut);
+
+			foreach (MPInteger sigObj in signature)
+			{
+				try
+				{
+					bcOut.WriteObject(sigObj);
+				}
+				catch (IOException e)
+				{
+					throw new Exception("internal error: " + e);
+				}
+			}
+
+			return bOut.ToArray();
+		}
+
+		public SignatureSubpacket[] GetHashedSubPackets()
+        {
+            return hashedData;
+        }
+
+		public SignatureSubpacket[] GetUnhashedSubPackets()
+        {
+            return unhashedData;
+        }
+
+		/// <summary>Return the creation time in milliseconds since 1 Jan., 1970 UTC.</summary>
+        public long CreationTime
+        {
+            get { return creationTime; }
+        }
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+			pOut.WriteByte((byte) version);
+
+			if (version == 3 || version == 2)
+            {
+				pOut.Write(
+					5, // the length of the next block
+					(byte) signatureType);
+
+				pOut.WriteInt((int)(creationTime / 1000L));
+
+				pOut.WriteLong(keyId);
+
+				pOut.Write(
+					(byte) keyAlgorithm,
+					(byte) hashAlgorithm);
+            }
+            else if (version == 4)
+            {
+                pOut.Write(
+					(byte) signatureType,
+					(byte) keyAlgorithm,
+					(byte) hashAlgorithm);
+
+				EncodeLengthAndData(pOut, GetEncodedSubpackets(hashedData));
+
+				EncodeLengthAndData(pOut, GetEncodedSubpackets(unhashedData));
+            }
+            else
+            {
+                throw new IOException("unknown version: " + version);
+            }
+
+			pOut.Write(fingerprint);
+
+			if (signature != null)
+			{
+				pOut.WriteObjects(signature);
+			}
+			else
+			{
+				pOut.Write(signatureEncoding);
+			}
+
+			bcpgOut.WritePacket(PacketTag.Signature, bOut.ToArray(), true);
+        }
+
+		private static void EncodeLengthAndData(
+			BcpgOutputStream	pOut,
+			byte[]				data)
+		{
+			pOut.WriteShort((short) data.Length);
+			pOut.Write(data);
+		}
+
+		private static byte[] GetEncodedSubpackets(
+			SignatureSubpacket[] ps)
+		{
+			MemoryStream sOut = new MemoryStream();
+
+			foreach (SignatureSubpacket p in ps)
+			{
+				p.Encode(sOut);
+			}
+
+			return sOut.ToArray();
+		}
+
+		private void setCreationTime()
+		{
+			foreach (SignatureSubpacket p in hashedData)
+			{
+				if (p is SignatureCreationTime)
+				{
+                    creationTime = DateTimeUtilities.DateTimeToUnixMs(
+						((SignatureCreationTime)p).GetTime());
+					break;
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacket.cs
new file mode 100644
index 0000000..ac26f8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacket.cs
@@ -0,0 +1,76 @@
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic type for a PGP Signature sub-packet.</remarks>
+    public class SignatureSubpacket
+    {
+        private readonly SignatureSubpacketTag type;
+        private readonly bool critical;
+
+		internal readonly byte[] data;
+
+		protected internal SignatureSubpacket(
+            SignatureSubpacketTag	type,
+            bool					critical,
+            byte[]					data)
+        {
+            this.type = type;
+            this.critical = critical;
+            this.data = data;
+        }
+
+		public SignatureSubpacketTag SubpacketType
+        {
+			get { return type; }
+        }
+
+        public bool IsCritical()
+        {
+            return critical;
+        }
+
+		/// <summary>Return the generic data making up the packet.</summary>
+        public byte[] GetData()
+        {
+            return (byte[]) data.Clone();
+        }
+
+		public void Encode(
+            Stream os)
+        {
+            int bodyLen = data.Length + 1;
+
+            if (bodyLen < 192)
+            {
+                os.WriteByte((byte)bodyLen);
+            }
+            else if (bodyLen <= 8383)
+            {
+                bodyLen -= 192;
+
+                os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192));
+                os.WriteByte((byte)bodyLen);
+            }
+            else
+            {
+                os.WriteByte(0xff);
+                os.WriteByte((byte)(bodyLen >> 24));
+                os.WriteByte((byte)(bodyLen >> 16));
+                os.WriteByte((byte)(bodyLen >> 8));
+                os.WriteByte((byte)bodyLen);
+            }
+
+            if (critical)
+            {
+                os.WriteByte((byte)(0x80 | (int) type));
+            }
+            else
+            {
+                os.WriteByte((byte) type);
+            }
+
+            os.Write(data, 0, data.Length);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketTags.cs b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketTags.cs
new file mode 100644
index 0000000..1a8e254
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketTags.cs
@@ -0,0 +1,33 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic PGP signature sub-packet tag types.
+    */
+    public enum SignatureSubpacketTag
+    {
+        CreationTime = 2,						// signature creation time
+        ExpireTime = 3,							// signature expiration time
+        Exportable = 4,							// exportable certification
+        TrustSig = 5,							// trust signature
+        RegExp = 6,								// regular expression
+        Revocable = 7,							// revocable
+        KeyExpireTime = 9,						// key expiration time
+        Placeholder = 10,						// placeholder for backward compatibility
+        PreferredSymmetricAlgorithms = 11,		// preferred symmetric algorithms
+        RevocationKey = 12,						// revocation key
+        IssuerKeyId = 16,						// issuer key ID
+        NotationData = 20,						// notation data
+        PreferredHashAlgorithms = 21,			// preferred hash algorithms
+        PreferredCompressionAlgorithms = 22,	// preferred compression algorithms
+        KeyServerPreferences = 23,				// key server preferences
+        PreferredKeyServer = 24,				// preferred key server
+        PrimaryUserId = 25,						// primary user id
+        PolicyUrl = 26,							// policy URL
+        KeyFlags = 27,							// key flags
+        SignerUserId = 28,						// signer's user id
+        RevocationReason = 29,					// reason for revocation
+		Features = 30,							// features
+		SignatureTarget = 31,					// signature target
+		EmbeddedSignature = 32					// embedded signature
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketsReader.cs b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketsReader.cs
new file mode 100644
index 0000000..8dd1af3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SignatureSubpacketsReader.cs
@@ -0,0 +1,88 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/**
+	* reader for signature sub-packets
+	*/
+	public class SignatureSubpacketsParser
+	{
+		private readonly Stream input;
+
+		public SignatureSubpacketsParser(
+			Stream input)
+		{
+			this.input = input;
+		}
+
+		public SignatureSubpacket ReadPacket()
+		{
+			int l = input.ReadByte();
+			if (l < 0)
+				return null;
+
+			int bodyLen = 0;
+			if (l < 192)
+			{
+				bodyLen = l;
+			}
+			else if (l <= 223)
+			{
+				bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192;
+			}
+			else if (l == 255)
+			{
+				bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16)
+					|  (input.ReadByte() << 8)  | input.ReadByte();
+			}
+			else
+			{
+				// TODO Error?
+			}
+
+			int tag = input.ReadByte();
+			if (tag < 0)
+				throw new EndOfStreamException("unexpected EOF reading signature sub packet");
+
+			byte[] data = new byte[bodyLen - 1];
+			if (Streams.ReadFully(input, data) < data.Length)
+				throw new EndOfStreamException();
+
+			bool isCritical = ((tag & 0x80) != 0);
+			SignatureSubpacketTag type = (SignatureSubpacketTag)(tag & 0x7f);
+			switch (type)
+			{
+				case SignatureSubpacketTag.CreationTime:
+					return new SignatureCreationTime(isCritical, data);
+				case SignatureSubpacketTag.KeyExpireTime:
+					return new KeyExpirationTime(isCritical, data);
+				case SignatureSubpacketTag.ExpireTime:
+					return new SignatureExpirationTime(isCritical, data);
+				case SignatureSubpacketTag.Revocable:
+					return new Revocable(isCritical, data);
+				case SignatureSubpacketTag.Exportable:
+					return new Exportable(isCritical, data);
+				case SignatureSubpacketTag.IssuerKeyId:
+					return new IssuerKeyId(isCritical, data);
+				case SignatureSubpacketTag.TrustSig:
+					return new TrustSignature(isCritical, data);
+				case SignatureSubpacketTag.PreferredCompressionAlgorithms:
+				case SignatureSubpacketTag.PreferredHashAlgorithms:
+				case SignatureSubpacketTag.PreferredSymmetricAlgorithms:
+					return new PreferredAlgorithms(type, isCritical, data);
+				case SignatureSubpacketTag.KeyFlags:
+					return new KeyFlags(isCritical, data);
+				case SignatureSubpacketTag.PrimaryUserId:
+					return new PrimaryUserId(isCritical, data);
+				case SignatureSubpacketTag.SignerUserId:
+					return new SignerUserId(isCritical, data);
+				case SignatureSubpacketTag.NotationData:
+					return new NotationData(isCritical, data);
+			}
+			return new SignatureSubpacket(type, isCritical, data);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncDataPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncDataPacket.cs
new file mode 100644
index 0000000..17ee55b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncDataPacket.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <remarks>Basic type for a symmetric key encrypted packet.</remarks>
+    public class SymmetricEncDataPacket
+        : InputStreamPacket
+    {
+        public SymmetricEncDataPacket(
+            BcpgInputStream bcpgIn)
+            : base(bcpgIn)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncIntegrityPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncIntegrityPacket.cs
new file mode 100644
index 0000000..a9b6d06
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SymmetricEncIntegrityPacket.cs
@@ -0,0 +1,18 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	public class SymmetricEncIntegrityPacket
+		: InputStreamPacket
+	{
+		internal readonly int version;
+
+		internal SymmetricEncIntegrityPacket(
+			BcpgInputStream bcpgIn)
+			: base(bcpgIn)
+        {
+			version = bcpgIn.ReadByte();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyAlgorithmTags.cs b/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyAlgorithmTags.cs
new file mode 100644
index 0000000..e05a486
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyAlgorithmTags.cs
@@ -0,0 +1,23 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic tags for symmetric key algorithms
+    */
+    public enum SymmetricKeyAlgorithmTag
+    {
+        Null = 0,         // Plaintext or unencrypted data
+        Idea = 1,         // IDEA [IDEA]
+        TripleDes = 2,    // Triple-DES (DES-EDE, as per spec -168 bit key derived from 192)
+        Cast5 = 3,        // Cast5 (128 bit key, as per RFC 2144)
+        Blowfish = 4,     // Blowfish (128 bit key, 16 rounds) [Blowfish]
+        Safer = 5,        // Safer-SK128 (13 rounds) [Safer]
+        Des = 6,          // Reserved for DES/SK
+        Aes128 = 7,       // Reserved for AES with 128-bit key
+        Aes192 = 8,       // Reserved for AES with 192-bit key
+        Aes256 = 9,       // Reserved for AES with 256-bit key
+        Twofish = 10,     // Reserved for Twofish
+        Camellia128 = 11, // Reserved for AES with 128-bit key
+        Camellia192 = 12, // Reserved for AES with 192-bit key
+        Camellia256 = 13  // Reserved for AES with 256-bit key
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyEncSessionPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyEncSessionPacket.cs
new file mode 100644
index 0000000..0381fa3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/SymmetricKeyEncSessionPacket.cs
@@ -0,0 +1,91 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic type for a symmetric encrypted session key packet
+    */
+    public class SymmetricKeyEncSessionPacket
+        : ContainedPacket
+    {
+        private int version;
+        private SymmetricKeyAlgorithmTag encAlgorithm;
+        private S2k s2k;
+        private readonly byte[] secKeyData;
+
+        public SymmetricKeyEncSessionPacket(
+            BcpgInputStream bcpgIn)
+        {
+            version = bcpgIn.ReadByte();
+            encAlgorithm = (SymmetricKeyAlgorithmTag) bcpgIn.ReadByte();
+
+            s2k = new S2k(bcpgIn);
+
+            secKeyData = bcpgIn.ReadAll();
+        }
+
+		public SymmetricKeyEncSessionPacket(
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            S2k							s2k,
+            byte[]						secKeyData)
+        {
+            this.version = 4;
+            this.encAlgorithm = encAlgorithm;
+            this.s2k = s2k;
+            this.secKeyData = secKeyData;
+        }
+
+        /**
+        * @return int
+        */
+        public SymmetricKeyAlgorithmTag EncAlgorithm
+        {
+			get { return encAlgorithm; }
+        }
+
+        /**
+        * @return S2k
+        */
+        public S2k S2k
+        {
+			get { return s2k; }
+        }
+
+        /**
+        * @return byte[]
+        */
+        public byte[] GetSecKeyData()
+        {
+            return secKeyData;
+        }
+
+        /**
+        * @return int
+        */
+        public int Version
+        {
+			get { return version; }
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            MemoryStream bOut = new MemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+            pOut.Write(
+				(byte) version,
+				(byte) encAlgorithm);
+
+			pOut.WriteObject(s2k);
+
+			if (secKeyData != null && secKeyData.Length > 0)
+			{
+                pOut.Write(secKeyData);
+            }
+
+			bcpgOut.WritePacket(PacketTag.SymmetricKeyEncryptedSessionKey, bOut.ToArray(), true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/TrustPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/TrustPacket.cs
new file mode 100644
index 0000000..6f1969c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/TrustPacket.cs
@@ -0,0 +1,43 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+	/// <summary>Basic type for a trust packet.</summary>
+    public class TrustPacket
+        : ContainedPacket
+    {
+        private readonly byte[] levelAndTrustAmount;
+
+		public TrustPacket(
+            BcpgInputStream bcpgIn)
+        {
+            MemoryStream bOut = new MemoryStream();
+
+			int ch;
+            while ((ch = bcpgIn.ReadByte()) >= 0)
+            {
+                bOut.WriteByte((byte) ch);
+            }
+
+			levelAndTrustAmount = bOut.ToArray();
+        }
+
+		public TrustPacket(
+            int trustCode)
+        {
+			this.levelAndTrustAmount = new byte[]{ (byte) trustCode };
+        }
+
+		public byte[] GetLevelAndTrustAmount()
+		{
+			return (byte[]) levelAndTrustAmount.Clone();
+		}
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.Trust, levelAndTrustAmount, true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/UserAttributePacket.cs b/BouncyCastle.AxCrypt/src/bcpg/UserAttributePacket.cs
new file mode 100644
index 0000000..20e3598
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/UserAttributePacket.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic type for a user attribute packet.
+    */
+    public class UserAttributePacket
+        : ContainedPacket
+    {
+        private readonly UserAttributeSubpacket[] subpackets;
+
+        public UserAttributePacket(
+            BcpgInputStream bcpgIn)
+        {
+            UserAttributeSubpacketsParser sIn = new UserAttributeSubpacketsParser(bcpgIn);
+            UserAttributeSubpacket sub;
+
+            IList v = Platform.CreateArrayList();
+            while ((sub = sIn.ReadPacket()) != null)
+            {
+                v.Add(sub);
+            }
+
+            subpackets = new UserAttributeSubpacket[v.Count];
+
+            for (int i = 0; i != subpackets.Length; i++)
+            {
+                subpackets[i] = (UserAttributeSubpacket)v[i];
+            }
+        }
+
+        public UserAttributePacket(
+            UserAttributeSubpacket[] subpackets)
+        {
+            this.subpackets = subpackets;
+        }
+
+        public UserAttributeSubpacket[] GetSubpackets()
+        {
+            return subpackets;
+        }
+
+        public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            MemoryStream bOut = new MemoryStream();
+
+            for (int i = 0; i != subpackets.Length; i++)
+            {
+                subpackets[i].Encode(bOut);
+            }
+
+            bcpgOut.WritePacket(PacketTag.UserAttribute, bOut.ToArray(), false);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacket.cs b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacket.cs
new file mode 100644
index 0000000..05f60ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacket.cs
@@ -0,0 +1,90 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic type for a user attribute sub-packet.
+    */
+    public class UserAttributeSubpacket
+    {
+        internal readonly UserAttributeSubpacketTag	type;
+        private readonly bool longLength;   // we preserve this as not everyone encodes length properly.
+        protected readonly byte[] data;
+
+        protected internal UserAttributeSubpacket(UserAttributeSubpacketTag type, byte[] data)
+            : this(type, false, data)
+        {
+        }
+
+        protected internal UserAttributeSubpacket(UserAttributeSubpacketTag type, bool forceLongLength, byte[] data)
+        {
+            this.type = type;
+            this.longLength = forceLongLength;
+            this.data = data;
+        }
+
+        public virtual UserAttributeSubpacketTag SubpacketType
+        {
+            get { return type; }
+        }
+
+        /**
+        * return the generic data making up the packet.
+        */
+        public virtual byte[] GetData()
+        {
+            return data;
+        }
+
+        public virtual void Encode(Stream os)
+        {
+            int bodyLen = data.Length + 1;
+
+            if (bodyLen < 192 && !longLength)
+            {
+                os.WriteByte((byte)bodyLen);
+            }
+            else if (bodyLen <= 8383 && !longLength)
+            {
+                bodyLen -= 192;
+
+                os.WriteByte((byte)(((bodyLen >> 8) & 0xff) + 192));
+                os.WriteByte((byte)bodyLen);
+            }
+            else
+            {
+                os.WriteByte(0xff);
+                os.WriteByte((byte)(bodyLen >> 24));
+                os.WriteByte((byte)(bodyLen >> 16));
+                os.WriteByte((byte)(bodyLen >> 8));
+                os.WriteByte((byte)bodyLen);
+            }
+
+            os.WriteByte((byte) type);
+            os.Write(data, 0, data.Length);
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            UserAttributeSubpacket other = obj as UserAttributeSubpacket;
+
+            if (other == null)
+                return false;
+
+            return type == other.type
+                && Arrays.AreEqual(data, other.data);
+        }
+
+        public override int GetHashCode()
+        {
+            return type.GetHashCode() ^ Arrays.GetHashCode(data);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketTags.cs b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketTags.cs
new file mode 100644
index 0000000..7a9cd1d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketTags.cs
@@ -0,0 +1,10 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic PGP user attribute sub-packet tag types.
+    */
+    public enum UserAttributeSubpacketTag
+    {
+        ImageAttribute = 1
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketsReader.cs b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketsReader.cs
new file mode 100644
index 0000000..f0cc1b8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/UserAttributeSubpacketsReader.cs
@@ -0,0 +1,65 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Bcpg.Attr;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * reader for user attribute sub-packets
+    */
+    public class UserAttributeSubpacketsParser
+    {
+        private readonly Stream input;
+
+        public UserAttributeSubpacketsParser(
+            Stream input)
+        {
+            this.input = input;
+        }
+
+        public virtual UserAttributeSubpacket ReadPacket()
+        {
+            int l = input.ReadByte();
+            if (l < 0)
+                return null;
+
+            int bodyLen = 0;
+            bool longLength = false;
+            if (l < 192)
+            {
+                bodyLen = l;
+            }
+            else if (l <= 223)
+            {
+                bodyLen = ((l - 192) << 8) + (input.ReadByte()) + 192;
+            }
+            else if (l == 255)
+            {
+                bodyLen = (input.ReadByte() << 24) | (input.ReadByte() << 16)
+                    |  (input.ReadByte() << 8)  | input.ReadByte();
+                longLength = true;
+            }
+            else
+            {
+                throw new IOException("unrecognised length reading user attribute sub packet");
+            }
+
+            int tag = input.ReadByte();
+            if (tag < 0)
+                throw new EndOfStreamException("unexpected EOF reading user attribute sub packet");
+
+            byte[] data = new byte[bodyLen - 1];
+            if (Streams.ReadFully(input, data) < data.Length)
+                throw new EndOfStreamException();
+
+            UserAttributeSubpacketTag type = (UserAttributeSubpacketTag) tag;
+            switch (type)
+            {
+                case UserAttributeSubpacketTag.ImageAttribute:
+                    return new ImageAttrib(longLength, data);
+            }
+            return new UserAttributeSubpacket(type, longLength, data);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/UserIdPacket.cs b/BouncyCastle.AxCrypt/src/bcpg/UserIdPacket.cs
new file mode 100644
index 0000000..a175e74
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/UserIdPacket.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /**
+    * Basic type for a user ID packet.
+    */
+    public class UserIdPacket
+        : ContainedPacket
+    {
+        private readonly byte[] idData;
+
+        public UserIdPacket(
+            BcpgInputStream bcpgIn)
+        {
+            this.idData = bcpgIn.ReadAll();
+        }
+
+		public UserIdPacket(
+			string id)
+        {
+            this.idData = Encoding.UTF8.GetBytes(id);
+        }
+
+		public string GetId()
+        {
+			return Encoding.UTF8.GetString(idData, 0, idData.Length);
+        }
+
+		public override void Encode(
+            BcpgOutputStream bcpgOut)
+        {
+            bcpgOut.WritePacket(PacketTag.UserId, idData, true);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/attr/ImageAttrib.cs b/BouncyCastle.AxCrypt/src/bcpg/attr/ImageAttrib.cs
new file mode 100644
index 0000000..2d0fef8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/attr/ImageAttrib.cs
@@ -0,0 +1,72 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg.Attr
+{
+    /// <remarks>Basic type for a image attribute packet.</remarks>
+    public class ImageAttrib
+        : UserAttributeSubpacket
+    {
+        public enum Format : byte
+        {
+            Jpeg = 1
+        }
+
+        private static readonly byte[] Zeroes = new byte[12];
+
+        private int     hdrLength;
+        private int     _version;
+        private int     _encoding;
+        private byte[]  imageData;
+
+        public ImageAttrib(byte[] data)
+            : this(false, data)
+        {
+        }
+
+        public ImageAttrib(bool forceLongLength, byte[] data)
+            : base(UserAttributeSubpacketTag.ImageAttribute, forceLongLength, data)
+        {
+            hdrLength = ((data[1] & 0xff) << 8) | (data[0] & 0xff);
+            _version = data[2] & 0xff;
+            _encoding = data[3] & 0xff;
+
+            imageData = new byte[data.Length - hdrLength];
+            Array.Copy(data, hdrLength, imageData, 0, imageData.Length);
+        }
+
+        public ImageAttrib(
+            Format	imageType,
+            byte[]	imageData)
+            : this(ToByteArray(imageType, imageData))
+        {
+        }
+
+        private static byte[] ToByteArray(
+            Format	imageType,
+            byte[]	imageData)
+        {
+            MemoryStream bOut = new MemoryStream();
+            bOut.WriteByte(0x10); bOut.WriteByte(0x00); bOut.WriteByte(0x01);
+            bOut.WriteByte((byte) imageType);
+            bOut.Write(Zeroes, 0, Zeroes.Length);
+            bOut.Write(imageData, 0, imageData.Length);
+            return bOut.ToArray();
+        }
+
+        public virtual int Version
+        {
+            get { return _version; }
+        }
+
+        public virtual int Encoding
+        {
+            get { return _encoding; }
+        }
+
+        public virtual byte[] GetImageData()
+        {
+            return imageData;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/EmbeddedSignature.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/EmbeddedSignature.cs
new file mode 100644
index 0000000..e47604a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/EmbeddedSignature.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+	/**
+	 * Packet embedded signature
+	 */
+	public class EmbeddedSignature
+		: SignatureSubpacket
+	{
+		public EmbeddedSignature(
+			bool	critical,
+			byte[]	data)
+			: base(SignatureSubpacketTag.EmbeddedSignature, critical, data)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/Exportable.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/Exportable.cs
new file mode 100644
index 0000000..4455c38
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/Exportable.cs
@@ -0,0 +1,47 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving signature creation time.
+    */
+    public class Exportable
+        : SignatureSubpacket
+    {
+        private static byte[] BooleanToByteArray(bool val)
+        {
+            byte[]    data = new byte[1];
+
+            if (val)
+            {
+                data[0] = 1;
+                return data;
+            }
+            else
+            {
+                return data;
+            }
+        }
+
+        public Exportable(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.Exportable, critical, data)
+        {
+        }
+
+        public Exportable(
+            bool    critical,
+            bool    isExportable)
+            : base(SignatureSubpacketTag.Exportable, critical, BooleanToByteArray(isExportable))
+        {
+        }
+
+        public bool IsExportable()
+        {
+            return data[0] != 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/IssuerKeyId.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/IssuerKeyId.cs
new file mode 100644
index 0000000..91490d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/IssuerKeyId.cs
@@ -0,0 +1,61 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving signature creation time.
+    */
+    public class IssuerKeyId
+        : SignatureSubpacket
+    {
+        protected static byte[] KeyIdToBytes(
+            long    keyId)
+        {
+            byte[]    data = new byte[8];
+
+            data[0] = (byte)(keyId >> 56);
+            data[1] = (byte)(keyId >> 48);
+            data[2] = (byte)(keyId >> 40);
+            data[3] = (byte)(keyId >> 32);
+            data[4] = (byte)(keyId >> 24);
+            data[5] = (byte)(keyId >> 16);
+            data[6] = (byte)(keyId >> 8);
+            data[7] = (byte)keyId;
+
+            return data;
+        }
+
+        public IssuerKeyId(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.IssuerKeyId, critical, data)
+        {
+        }
+
+        public IssuerKeyId(
+            bool    critical,
+            long       keyId)
+            : base(SignatureSubpacketTag.IssuerKeyId, critical, KeyIdToBytes(keyId))
+        {
+        }
+
+        public long KeyId
+        {
+			get
+			{
+				long keyId = ((long)(data[0] & 0xff) << 56)
+					| ((long)(data[1] & 0xff) << 48)
+					| ((long)(data[2] & 0xff) << 40)
+					| ((long)(data[3] & 0xff) << 32)
+					| ((long)(data[4] & 0xff) << 24)
+					| ((long)(data[5] & 0xff) << 16)
+					| ((long)(data[6] & 0xff) << 8)
+					| ((long)data[7] & 0xff);
+
+				return keyId;
+			}
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/KeyExpirationTime.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/KeyExpirationTime.cs
new file mode 100644
index 0000000..23b4cac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/KeyExpirationTime.cs
@@ -0,0 +1,56 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving time after creation at which the key expires.
+    */
+    public class KeyExpirationTime
+        : SignatureSubpacket
+    {
+        protected static byte[] TimeToBytes(
+            long    t)
+        {
+            byte[]    data = new byte[4];
+
+            data[0] = (byte)(t >> 24);
+            data[1] = (byte)(t >> 16);
+            data[2] = (byte)(t >> 8);
+            data[3] = (byte)t;
+
+            return data;
+        }
+
+        public KeyExpirationTime(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.KeyExpireTime, critical, data)
+        {
+        }
+
+        public KeyExpirationTime(
+            bool    critical,
+            long       seconds)
+            : base(SignatureSubpacketTag.KeyExpireTime, critical, TimeToBytes(seconds))
+        {
+        }
+
+        /**
+        * Return the number of seconds after creation time a key is valid for.
+        *
+        * @return second count for key validity.
+        */
+        public long Time
+        {
+			get
+			{
+				long time = ((long)(data[0] & 0xff) << 24) | ((long)(data[1] & 0xff) << 16)
+					| ((long)(data[2] & 0xff) << 8) | ((long)data[3] & 0xff);
+
+				return time;
+			}
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/KeyFlags.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/KeyFlags.cs
new file mode 100644
index 0000000..0592301
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/KeyFlags.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * Packet holding the key flag values.
+    */
+    public class KeyFlags
+        : SignatureSubpacket
+    {
+		public const int CertifyOther	= 0x01;
+		public const int SignData		= 0x02;
+		public const int EncryptComms	= 0x04;
+		public const int EncryptStorage	= 0x08;
+		public const int Split			= 0x10;
+		public const int Authentication	= 0x20;
+		public const int Shared			= 0x80;
+
+        private static byte[] IntToByteArray(
+            int v)
+        {
+			byte[] tmp = new byte[4];
+			int size = 0;
+
+			for (int i = 0; i != 4; i++)
+			{
+				tmp[i] = (byte)(v >> (i * 8));
+				if (tmp[i] != 0)
+				{
+					size = i;
+				}
+			}
+
+			byte[] data = new byte[size + 1];
+			Array.Copy(tmp, 0, data, 0, data.Length);
+			return data;
+		}
+
+		public KeyFlags(
+            bool	critical,
+            byte[]	data)
+            : base(SignatureSubpacketTag.KeyFlags, critical, data)
+        {
+        }
+
+		public KeyFlags(
+			bool	critical,
+			int		flags)
+            : base(SignatureSubpacketTag.KeyFlags, critical, IntToByteArray(flags))
+        {
+        }
+
+		/// <summary>
+		/// Return the flag values contained in the first 4 octets (note: at the moment
+		/// the standard only uses the first one).
+		/// </summary>
+		public int Flags
+        {
+			get
+			{
+				int flags = 0;
+
+				for (int i = 0; i != data.Length; i++)
+				{
+					flags |= (data[i] & 0xff) << (i * 8);
+				}
+
+				return flags;
+			}
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/NotationData.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/NotationData.cs
new file mode 100644
index 0000000..ccc9aa7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/NotationData.cs
@@ -0,0 +1,112 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+	/**
+	* Class provided a NotationData object according to
+	* RFC2440, Chapter 5.2.3.15. Notation Data
+	*/
+	public class NotationData
+		: SignatureSubpacket
+	{
+		public const int HeaderFlagLength = 4;
+		public const int HeaderNameLength = 2;
+		public const int HeaderValueLength = 2;
+
+		public NotationData(
+			bool	critical,
+			byte[]	data)
+			: base(SignatureSubpacketTag.NotationData, critical, data)
+		{
+		}
+
+		public NotationData(
+			bool	critical,
+			bool	humanReadable,
+			string	notationName,
+			string	notationValue)
+			: base(SignatureSubpacketTag.NotationData, critical,
+				createData(humanReadable, notationName, notationValue))
+		{
+		}
+
+		private static byte[] createData(
+			bool	humanReadable,
+			string	notationName,
+			string	notationValue)
+		{
+			MemoryStream os = new MemoryStream();
+
+			// (4 octets of flags, 2 octets of name length (M),
+			// 2 octets of value length (N),
+			// M octets of name data,
+			// N octets of value data)
+
+			// flags
+			os.WriteByte(humanReadable ? (byte)0x80 : (byte)0x00);
+			os.WriteByte(0x0);
+			os.WriteByte(0x0);
+			os.WriteByte(0x0);
+
+			byte[] nameData, valueData = null;
+			int nameLength, valueLength;
+
+			nameData = Encoding.UTF8.GetBytes(notationName);
+			nameLength = System.Math.Min(nameData.Length, 0xFF);
+
+			valueData = Encoding.UTF8.GetBytes(notationValue);
+			valueLength = System.Math.Min(valueData.Length, 0xFF);
+
+			// name length
+			os.WriteByte((byte)(nameLength >> 8));
+			os.WriteByte((byte)(nameLength >> 0));
+
+			// value length
+			os.WriteByte((byte)(valueLength >> 8));
+			os.WriteByte((byte)(valueLength >> 0));
+
+			// name
+			os.Write(nameData, 0, nameLength);
+
+			// value
+			os.Write(valueData, 0, valueLength);
+
+			return os.ToArray();
+		}
+
+		public bool IsHumanReadable
+		{
+			get { return data[0] == (byte)0x80; }
+		}
+
+		public string GetNotationName()
+		{
+			int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+			int namePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength;
+
+			return Encoding.UTF8.GetString(data, namePos, nameLength);
+		}
+
+		public string GetNotationValue()
+		{
+			int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+			int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0));
+			int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength;
+
+			return Encoding.UTF8.GetString(data, valuePos, valueLength);
+		}
+
+		public byte[] GetNotationValueBytes()
+		{
+			int nameLength = ((data[HeaderFlagLength] << 8) + (data[HeaderFlagLength + 1] << 0));
+			int valueLength = ((data[HeaderFlagLength + HeaderNameLength] << 8) + (data[HeaderFlagLength + HeaderNameLength + 1] << 0));
+			int valuePos = HeaderFlagLength + HeaderNameLength + HeaderValueLength + nameLength;
+
+			byte[] bytes = new byte[valueLength];
+			Array.Copy(data, valuePos, bytes, 0, valueLength);
+			return bytes;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/PreferredAlgorithms.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/PreferredAlgorithms.cs
new file mode 100644
index 0000000..0f282a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/PreferredAlgorithms.cs
@@ -0,0 +1,54 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving signature creation time.
+    */
+    public class PreferredAlgorithms
+        : SignatureSubpacket
+    {
+        private static byte[] IntToByteArray(
+            int[]    v)
+        {
+            byte[]    data = new byte[v.Length];
+
+            for (int i = 0; i != v.Length; i++)
+            {
+                data[i] = (byte)v[i];
+            }
+
+            return data;
+        }
+
+        public PreferredAlgorithms(
+            SignatureSubpacketTag        type,
+            bool    critical,
+            byte[]     data)
+            : base(type, critical, data)
+        {
+        }
+
+        public PreferredAlgorithms(
+            SignatureSubpacketTag        type,
+            bool    critical,
+            int[]      preferences)
+            : base(type, critical, IntToByteArray(preferences))
+        {
+        }
+
+        public int[] GetPreferences()
+        {
+            int[]    v = new int[data.Length];
+
+            for (int i = 0; i != v.Length; i++)
+            {
+                v[i] = data[i] & 0xff;
+            }
+
+            return v;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/PrimaryUserId.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/PrimaryUserId.cs
new file mode 100644
index 0000000..fc0353a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/PrimaryUserId.cs
@@ -0,0 +1,48 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving whether or not the signature is signed using the primary user ID for the key.
+    */
+    public class PrimaryUserId
+        : SignatureSubpacket
+    {
+        private static byte[] BooleanToByteArray(
+            bool    val)
+        {
+            byte[]    data = new byte[1];
+
+            if (val)
+            {
+                data[0] = 1;
+                return data;
+            }
+            else
+            {
+                return data;
+            }
+        }
+
+        public PrimaryUserId(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.PrimaryUserId, critical, data)
+        {
+        }
+
+        public PrimaryUserId(
+            bool    critical,
+            bool    isPrimaryUserId)
+            : base(SignatureSubpacketTag.PrimaryUserId, critical, BooleanToByteArray(isPrimaryUserId))
+        {
+        }
+
+        public bool IsPrimaryUserId()
+        {
+            return data[0] != 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/Revocable.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/Revocable.cs
new file mode 100644
index 0000000..b5e94fe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/Revocable.cs
@@ -0,0 +1,48 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving whether or not is revocable.
+    */
+    public class Revocable
+        : SignatureSubpacket
+    {
+        private static byte[] BooleanToByteArray(
+            bool    value)
+        {
+            byte[]    data = new byte[1];
+
+            if (value)
+            {
+                data[0] = 1;
+                return data;
+            }
+            else
+            {
+                return data;
+            }
+        }
+
+        public Revocable(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.Revocable, critical, data)
+    {
+        }
+
+        public Revocable(
+            bool    critical,
+            bool    isRevocable)
+            : base(SignatureSubpacketTag.Revocable, critical, BooleanToByteArray(isRevocable))
+    {
+        }
+
+        public bool IsRevocable()
+        {
+            return data[0] != 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKey.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKey.cs
new file mode 100644
index 0000000..66982cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKey.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <summary>
+    /// Represents revocation key OpenPGP signature sub packet.
+    /// </summary>
+    public class RevocationKey
+		: SignatureSubpacket
+    {
+		// 1 octet of class, 
+		// 1 octet of public-key algorithm ID, 
+		// 20 octets of fingerprint
+		public RevocationKey(
+			bool	isCritical,
+			byte[]	data)
+			: base(SignatureSubpacketTag.RevocationKey, isCritical, data)
+		{
+		}
+
+		public RevocationKey(
+			bool					isCritical,
+			RevocationKeyTag		signatureClass,
+			PublicKeyAlgorithmTag	keyAlgorithm,
+			byte[]					fingerprint)
+			: base(SignatureSubpacketTag.RevocationKey, isCritical,
+				CreateData(signatureClass, keyAlgorithm, fingerprint))
+		{
+		}
+
+		private static byte[] CreateData(
+			RevocationKeyTag		signatureClass,
+			PublicKeyAlgorithmTag	keyAlgorithm,
+			byte[]					fingerprint)
+		{
+			byte[] data = new byte[2 + fingerprint.Length];
+			data[0] = (byte)signatureClass;
+			data[1] = (byte)keyAlgorithm;
+			Array.Copy(fingerprint, 0, data, 2, fingerprint.Length);
+			return data;
+		}
+
+		public virtual RevocationKeyTag SignatureClass
+		{
+			get { return (RevocationKeyTag)this.GetData()[0]; }
+		}
+
+		public virtual PublicKeyAlgorithmTag Algorithm
+		{
+			get { return (PublicKeyAlgorithmTag)this.GetData()[1]; }
+		}
+
+        public virtual byte[] GetFingerprint()
+		{
+			byte[] data = this.GetData();
+			byte[] fingerprint = new byte[data.Length - 2];
+			Array.Copy(data, 2, fingerprint, 0, fingerprint.Length);
+			return fingerprint;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKeyTags.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKeyTags.cs
new file mode 100644
index 0000000..d76d1dc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationKeyTags.cs
@@ -0,0 +1,9 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    public enum RevocationKeyTag
+		: byte
+    {
+		ClassDefault = 0x80,
+		ClassSensitive = 0x40
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReason.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReason.cs
new file mode 100644
index 0000000..98e9b0a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReason.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg
+{
+    /// <summary>
+    /// Represents revocation reason OpenPGP signature sub packet.
+    /// </summary>
+    public class RevocationReason
+		: SignatureSubpacket
+    {
+        public RevocationReason(bool isCritical, byte[] data)
+            : base(SignatureSubpacketTag.RevocationReason, isCritical, data)
+        {
+        }
+
+		public RevocationReason(
+			bool				isCritical,
+			RevocationReasonTag	reason,
+			string				description)
+            : base(SignatureSubpacketTag.RevocationReason, isCritical, CreateData(reason, description))
+        {
+        }
+
+        private static byte[] CreateData(
+			RevocationReasonTag	reason,
+			string				description)
+        {
+            byte[] descriptionBytes = Strings.ToUtf8ByteArray(description);
+            byte[] data = new byte[1 + descriptionBytes.Length];
+
+            data[0] = (byte)reason;
+            Array.Copy(descriptionBytes, 0, data, 1, descriptionBytes.Length);
+
+            return data;
+        }
+
+        public virtual RevocationReasonTag GetRevocationReason()
+        {
+            return (RevocationReasonTag)GetData()[0];
+        }
+
+        public virtual string GetRevocationDescription()
+        {
+            byte[] data = GetData();
+            if (data.Length == 1)
+            {
+                return string.Empty;
+            }
+
+            byte[] description = new byte[data.Length - 1];
+            Array.Copy(data, 1, description, 0, description.Length);
+
+            return Strings.FromUtf8ByteArray(description);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReasonTags.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReasonTags.cs
new file mode 100644
index 0000000..524a58c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/RevocationReasonTags.cs
@@ -0,0 +1,14 @@
+namespace Org.BouncyCastle.Bcpg
+{
+    public enum RevocationReasonTag
+		: byte
+    {
+		NoReason = 0,					// No reason specified (key revocations or cert revocations)
+		KeySuperseded = 1,				// Key is superseded (key revocations)
+		KeyCompromised = 2,				// Key material has been compromised (key revocations)
+		KeyRetired = 3,					// Key is retired and no longer used (key revocations)
+		UserNoLongerValid = 32,			// User ID information is no longer valid (cert revocations)
+
+		// 100-110 - Private Use
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureCreationTime.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureCreationTime.cs
new file mode 100644
index 0000000..e6f241f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureCreationTime.cs
@@ -0,0 +1,47 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving signature creation time.
+    */
+    public class SignatureCreationTime
+        : SignatureSubpacket
+    {
+		protected static byte[] TimeToBytes(
+            DateTime time)
+        {
+			long t = DateTimeUtilities.DateTimeToUnixMs(time) / 1000L;
+			byte[] data = new byte[4];
+			data[0] = (byte)(t >> 24);
+            data[1] = (byte)(t >> 16);
+            data[2] = (byte)(t >> 8);
+            data[3] = (byte)t;
+            return data;
+        }
+        public SignatureCreationTime(
+            bool	critical,
+            byte[]	data)
+            : base(SignatureSubpacketTag.CreationTime, critical, data)
+        {
+        }
+        public SignatureCreationTime(
+            bool		critical,
+            DateTime	date)
+            : base(SignatureSubpacketTag.CreationTime, critical, TimeToBytes(date))
+        {
+        }
+        public DateTime GetTime()
+        {
+			long time = (long)(
+					((uint)data[0] << 24)
+				|	((uint)data[1] << 16)
+				|	((uint)data[2] << 8)
+				|	((uint)data[3])
+				);
+			return DateTimeUtilities.UnixMsToDateTime(time * 1000L);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureExpirationTime.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureExpirationTime.cs
new file mode 100644
index 0000000..7fddf57
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/SignatureExpirationTime.cs
@@ -0,0 +1,54 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving signature expiration time.
+    */
+    public class SignatureExpirationTime
+        : SignatureSubpacket
+    {
+        protected static byte[] TimeToBytes(
+            long      t)
+        {
+            byte[]    data = new byte[4];
+
+            data[0] = (byte)(t >> 24);
+            data[1] = (byte)(t >> 16);
+            data[2] = (byte)(t >> 8);
+            data[3] = (byte)t;
+
+            return data;
+        }
+
+        public SignatureExpirationTime(
+            bool    critical,
+            byte[]     data)
+            : base(SignatureSubpacketTag.ExpireTime, critical, data)
+    {
+        }
+
+        public SignatureExpirationTime(
+            bool    critical,
+            long       seconds)
+            : base(SignatureSubpacketTag.ExpireTime, critical, TimeToBytes(seconds))
+        {
+        }
+
+        /**
+        * return time in seconds before signature expires after creation time.
+        */
+        public long Time
+        {
+            get
+            {
+                long time = ((long)(data[0] & 0xff) << 24) | ((long)(data[1] & 0xff) << 16)
+                    | ((long)(data[2] & 0xff) << 8) | ((long)data[3] & 0xff);
+
+                return time;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/SignerUserId.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/SignerUserId.cs
new file mode 100644
index 0000000..98cc808
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/SignerUserId.cs
@@ -0,0 +1,52 @@
+using System;
+
+
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving the User ID of the signer.
+    */
+    public class SignerUserId
+        : SignatureSubpacket
+    {
+        private static byte[] UserIdToBytes(
+            string id)
+        {
+            byte[] idData = new byte[id.Length];
+
+            for (int i = 0; i != id.Length; i++)
+            {
+                idData[i] = (byte)id[i];
+            }
+
+			return idData;
+        }
+
+        public SignerUserId(
+            bool	critical,
+            byte[]	data)
+            : base(SignatureSubpacketTag.SignerUserId, critical, data)
+		{
+		}
+
+		public SignerUserId(
+            bool	critical,
+            string	userId)
+            : base(SignatureSubpacketTag.SignerUserId, critical, UserIdToBytes(userId))
+		{
+        }
+
+		public string GetId()
+        {
+            char[] chars = new char[data.Length];
+
+			for (int i = 0; i != chars.Length; i++)
+            {
+                chars[i] = (char)(data[i] & 0xff);
+            }
+
+			return new string(chars);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/bcpg/sig/TrustSignature.cs b/BouncyCastle.AxCrypt/src/bcpg/sig/TrustSignature.cs
new file mode 100644
index 0000000..bbadd30
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/bcpg/sig/TrustSignature.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.Sig
+{
+    /**
+    * packet giving trust.
+    */
+    public class TrustSignature
+        : SignatureSubpacket
+    {
+        private static byte[] IntToByteArray(
+            int	v1,
+            int	v2)
+        {
+			return new byte[]{ (byte)v1, (byte)v2 };
+        }
+
+		public TrustSignature(
+            bool	critical,
+            byte[]	data)
+            : base(SignatureSubpacketTag.TrustSig, critical, data)
+        {
+        }
+
+        public TrustSignature(
+            bool	critical,
+            int		depth,
+            int		trustAmount)
+            : base(SignatureSubpacketTag.TrustSig, critical, IntToByteArray(depth, trustAmount))
+        {
+        }
+
+        public int Depth
+        {
+			get { return data[0] & 0xff; }
+        }
+
+        public int TrustAmount
+        {
+			get { return data[1] & 0xff; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/BaseDigestCalculator.cs b/BouncyCastle.AxCrypt/src/cms/BaseDigestCalculator.cs
new file mode 100644
index 0000000..3dcbca7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/BaseDigestCalculator.cs
@@ -0,0 +1,23 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class BaseDigestCalculator
+		: IDigestCalculator
+	{
+		private readonly byte[] digest;
+
+		internal BaseDigestCalculator(
+			byte[] digest)
+		{
+			this.digest = digest;
+		}
+
+		public byte[] GetDigest()
+		{
+			return Arrays.Clone(digest);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerationException.cs b/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerationException.cs
new file mode 100644
index 0000000..31b06d6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerationException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Cms
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CmsAttributeTableGenerationException
+		: CmsException
+	{
+		public CmsAttributeTableGenerationException()
+		{
+		}
+
+		public CmsAttributeTableGenerationException(
+			string name)
+			: base(name)
+		{
+		}
+
+		public CmsAttributeTableGenerationException(
+			string		name,
+			Exception	e)
+			: base(name, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerator.cs
new file mode 100644
index 0000000..92c9a29
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAttributeTableGenerator.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Cms
+{
+	/// <remarks>
+	/// The 'Signature' parameter is only available when generating unsigned attributes.
+	/// </remarks>
+	public enum CmsAttributeTableParameter
+	{
+//		const string ContentType = "contentType";
+//		const string Digest = "digest";
+//		const string Signature = "encryptedDigest";
+//		const string DigestAlgorithmIdentifier = "digestAlgID";
+
+		ContentType, Digest, Signature, DigestAlgorithmIdentifier
+	}
+
+	public interface CmsAttributeTableGenerator
+	{
+		AttributeTable GetAttributes(IDictionary parameters);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedData.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedData.cs
new file mode 100644
index 0000000..d76b050
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedData.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* containing class for an CMS AuthEnveloped Data object
+	*/
+	internal class CmsAuthEnvelopedData
+	{
+		internal RecipientInformationStore recipientInfoStore;
+		internal ContentInfo contentInfo;
+
+		// OriginatorInfo      originator;
+		private AlgorithmIdentifier authEncAlg;
+		//private Asn1Set             authAttrs;
+		//private byte[]              mac;
+		//private Asn1Set             unauthAttrs;
+	
+		public CmsAuthEnvelopedData(
+			byte[] authEnvData)
+			: this(CmsUtilities.ReadContentInfo(authEnvData))
+		{
+		}
+
+		public CmsAuthEnvelopedData(
+			Stream authEnvData)
+			: this(CmsUtilities.ReadContentInfo(authEnvData))
+		{
+		}
+
+		public CmsAuthEnvelopedData(
+			ContentInfo contentInfo)
+		{
+			this.contentInfo = contentInfo;
+
+			AuthEnvelopedData authEnvData = AuthEnvelopedData.GetInstance(contentInfo.Content);
+
+			//this.originator = authEnvData.OriginatorInfo;
+
+			//
+	        // read the recipients
+	        //
+	        Asn1Set recipientInfos = authEnvData.RecipientInfos;
+
+			//
+			// read the auth-encrypted content info
+			//
+			EncryptedContentInfo authEncInfo = authEnvData.AuthEncryptedContentInfo;
+			this.authEncAlg = authEncInfo.ContentEncryptionAlgorithm;
+			CmsSecureReadable secureReadable = new AuthEnvelopedSecureReadable(this);
+
+			//
+			// build the RecipientInformationStore
+			//
+			this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
+				recipientInfos, secureReadable);
+
+			// FIXME These need to be passed to the AEAD cipher as AAD (Additional Authenticated Data)
+			//this.authAttrs = authEnvData.AuthAttrs;
+			//this.mac = authEnvData.Mac.GetOctets();
+			//this.unauthAttrs = authEnvData.UnauthAttrs;
+		}
+
+		private class AuthEnvelopedSecureReadable : CmsSecureReadable
+		{
+			private readonly CmsAuthEnvelopedData parent;
+
+			internal AuthEnvelopedSecureReadable(CmsAuthEnvelopedData parent)
+			{
+				this.parent = parent;
+			}
+
+			public AlgorithmIdentifier Algorithm
+			{
+				get { return parent.authEncAlg; }
+			}
+
+			public object CryptoObject
+			{
+				get { return null; }
+			}
+
+			public CmsReadable GetReadable(KeyParameter key)
+			{
+				// TODO Create AEAD cipher instance to decrypt and calculate tag ( MAC)
+				throw new CmsException("AuthEnveloped data decryption not yet implemented");
+
+//				RFC 5084 ASN.1 Module
+//				-- Parameters for AlgorithmIdentifier
+//				
+//				CCMParameters ::= SEQUENCE {
+//				  aes-nonce         OCTET STRING (SIZE(7..13)),
+//				  aes-ICVlen        AES-CCM-ICVlen DEFAULT 12 }
+//				
+//				AES-CCM-ICVlen ::= INTEGER (4 | 6 | 8 | 10 | 12 | 14 | 16)
+//				
+//				GCMParameters ::= SEQUENCE {
+//				  aes-nonce        OCTET STRING, -- recommended size is 12 octets
+//				  aes-ICVlen       AES-GCM-ICVlen DEFAULT 12 }
+//				
+//				AES-GCM-ICVlen ::= INTEGER (12 | 13 | 14 | 15 | 16)
+			}            
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedGenerator.cs
new file mode 100644
index 0000000..4273cff
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthEnvelopedGenerator.cs
@@ -0,0 +1,16 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Nist;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class CmsAuthEnvelopedGenerator
+	{
+		public static readonly string Aes128Ccm = NistObjectIdentifiers.IdAes128Ccm.Id;
+		public static readonly string Aes192Ccm = NistObjectIdentifiers.IdAes192Ccm.Id;
+		public static readonly string Aes256Ccm = NistObjectIdentifiers.IdAes256Ccm.Id;
+		public static readonly string Aes128Gcm = NistObjectIdentifiers.IdAes128Gcm.Id;
+		public static readonly string Aes192Gcm = NistObjectIdentifiers.IdAes192Gcm.Id;
+		public static readonly string Aes256Gcm = NistObjectIdentifiers.IdAes256Gcm.Id;
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedData.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedData.cs
new file mode 100644
index 0000000..5e234da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedData.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* containing class for an CMS Authenticated Data object
+	*/
+	public class CmsAuthenticatedData
+	{
+		internal RecipientInformationStore recipientInfoStore;
+		internal ContentInfo contentInfo;
+
+		private AlgorithmIdentifier macAlg;
+		private Asn1Set authAttrs;
+		private Asn1Set unauthAttrs;
+		private byte[] mac;
+
+		public CmsAuthenticatedData(
+			byte[] authData)
+			: this(CmsUtilities.ReadContentInfo(authData))
+		{
+		}
+
+		public CmsAuthenticatedData(
+			Stream authData)
+			: this(CmsUtilities.ReadContentInfo(authData))
+		{
+		}
+
+		public CmsAuthenticatedData(
+			ContentInfo contentInfo)
+		{
+			this.contentInfo = contentInfo;
+
+			AuthenticatedData authData = AuthenticatedData.GetInstance(contentInfo.Content);
+
+			//
+			// read the recipients
+			//
+			Asn1Set recipientInfos = authData.RecipientInfos;
+
+			this.macAlg = authData.MacAlgorithm;
+
+			//
+			// read the authenticated content info
+			//
+			ContentInfo encInfo = authData.EncapsulatedContentInfo;
+			CmsReadable readable = new CmsProcessableByteArray(
+				Asn1OctetString.GetInstance(encInfo.Content).GetOctets());
+			CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable(
+				this.macAlg, readable);
+
+			//
+			// build the RecipientInformationStore
+			//
+			this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
+				recipientInfos, secureReadable);
+
+			this.authAttrs = authData.AuthAttrs;
+			this.mac = authData.Mac.GetOctets();
+			this.unauthAttrs = authData.UnauthAttrs;
+		}
+
+		public byte[] GetMac()
+		{
+			return Arrays.Clone(mac);
+		}
+
+		public AlgorithmIdentifier MacAlgorithmID
+		{
+			get { return macAlg; }
+		}
+
+		/**
+		* return the object identifier for the content MAC algorithm.
+		*/
+		public string MacAlgOid
+		{
+			get { return macAlg.ObjectID.Id; }
+		}
+
+		/**
+		* return a store of the intended recipients for this message
+		*/
+		public RecipientInformationStore GetRecipientInfos()
+		{
+			return recipientInfoStore;
+		}
+
+		/**
+		 * return the ContentInfo 
+		 */
+		public ContentInfo ContentInfo
+		{
+			get { return contentInfo; }
+		}
+
+		/**
+		* return a table of the digested attributes indexed by
+		* the OID of the attribute.
+		*/
+		public Asn1.Cms.AttributeTable GetAuthAttrs()
+		{
+			if (authAttrs == null)
+				return null;
+
+			return new Asn1.Cms.AttributeTable(authAttrs);
+		}
+
+		/**
+		* return a table of the undigested attributes indexed by
+		* the OID of the attribute.
+		*/
+		public Asn1.Cms.AttributeTable GetUnauthAttrs()
+		{
+			if (unauthAttrs == null)
+				return null;
+
+			return new Asn1.Cms.AttributeTable(unauthAttrs);
+		}
+
+		/**
+		* return the ASN.1 encoded representation of this object.
+		*/
+		public byte[] GetEncoded()
+		{
+			return contentInfo.GetEncoded();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataGenerator.cs
new file mode 100644
index 0000000..0a37ca4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataGenerator.cs
@@ -0,0 +1,156 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * General class for generating a CMS authenticated-data message.
+	 *
+	 * A simple example of usage.
+	 *
+	 * <pre>
+	 *      CMSAuthenticatedDataGenerator  fact = new CMSAuthenticatedDataGenerator();
+	 *
+	 *      fact.addKeyTransRecipient(cert);
+	 *
+	 *      CMSAuthenticatedData         data = fact.generate(content, algorithm, "BC");
+	 * </pre>
+	 */
+	public class CmsAuthenticatedDataGenerator
+	    : CmsAuthenticatedGenerator
+	{
+	    /**
+	     * base constructor
+	     */
+	    public CmsAuthenticatedDataGenerator()
+	    {
+	    }
+
+	    /**
+	     * constructor allowing specific source of randomness
+	     * @param rand instance of SecureRandom to use
+	     */
+	    public CmsAuthenticatedDataGenerator(
+	        SecureRandom rand)
+	        : base(rand)
+	    {
+	    }
+
+	    /**
+	     * generate an enveloped object that contains an CMS Enveloped Data
+	     * object using the given provider and the passed in key generator.
+	     */
+		private CmsAuthenticatedData Generate(
+			CmsProcessable		content,
+			string				macOid,
+			CipherKeyGenerator	keyGen)
+		{
+			AlgorithmIdentifier macAlgId;
+			KeyParameter encKey;
+			Asn1OctetString encContent;
+			Asn1OctetString macResult;
+
+			try
+			{
+				// FIXME Will this work for macs?
+				byte[] encKeyBytes = keyGen.GenerateKey();
+				encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);
+
+				Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);
+
+				ICipherParameters cipherParameters;
+				macAlgId = GetAlgorithmIdentifier(
+				macOid, encKey, asn1Params, out cipherParameters);
+
+				IMac mac = MacUtilities.GetMac(macOid);
+				// TODO Confirm no ParametersWithRandom needed
+				// FIXME Only passing key at the moment
+//	            mac.Init(cipherParameters);
+				mac.Init(encKey);
+
+				MemoryStream bOut = new MemoryStream();
+				Stream mOut = new TeeOutputStream(bOut, new MacOutputStream(mac));
+
+				content.Write(mOut);
+
+                mOut.Dispose();
+                bOut.Dispose();
+
+				encContent = new BerOctetString(bOut.ToArray());
+
+				byte[] macOctets = MacUtilities.DoFinal(mac);
+				macResult = new DerOctetString(macOctets);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception decoding algorithm parameters.", e);
+			}
+
+			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+			foreach (RecipientInfoGenerator rig in recipientInfoGenerators) 
+			{
+				try
+				{
+					recipientInfos.Add(rig.Generate(encKey, rand));
+				}
+				catch (InvalidKeyException e)
+				{
+					throw new CmsException("key inappropriate for algorithm.", e);
+				}
+				catch (GeneralSecurityException e)
+				{
+					throw new CmsException("error making encrypted content.", e);
+				}
+			}
+			
+			ContentInfo eci = new ContentInfo(CmsObjectIdentifiers.Data, encContent);
+			
+			ContentInfo contentInfo = new ContentInfo(
+			CmsObjectIdentifiers.AuthenticatedData,
+			new AuthenticatedData(null, new DerSet(recipientInfos), macAlgId, null, eci, null, macResult, null));
+			
+			return new CmsAuthenticatedData(contentInfo);
+		}
+
+	    /**
+	     * generate an authenticated object that contains an CMS Authenticated Data object
+	     */
+	    public CmsAuthenticatedData Generate(
+	        CmsProcessable	content,
+	        string			encryptionOid)
+	    {
+            try
+            {
+				// FIXME Will this work for macs?
+				CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+				keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
+
+				return Generate(content, encryptionOid, keyGen);
+            }
+            catch (SecurityUtilityException e)
+            {
+                throw new CmsException("can't find key generation algorithm.", e);
+            }
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataParser.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataParser.cs
new file mode 100644
index 0000000..c99aac6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataParser.cs
@@ -0,0 +1,214 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* Parsing class for an CMS Authenticated Data object from an input stream.
+	* <p>
+	* Note: that because we are in a streaming mode only one recipient can be tried and it is important
+	* that the methods on the parser are called in the appropriate order.
+	* </p>
+	* <p>
+	* Example of use - assuming the first recipient matches the private key we have.
+	* <pre>
+	*      CMSAuthenticatedDataParser     ad = new CMSAuthenticatedDataParser(inputStream);
+	*
+	*      RecipientInformationStore  recipients = ad.getRecipientInfos();
+	*
+	*      Collection  c = recipients.getRecipients();
+	*      Iterator    it = c.iterator();
+	*
+	*      if (it.hasNext())
+	*      {
+	*          RecipientInformation   recipient = (RecipientInformation)it.next();
+	*
+	*          CMSTypedStream recData = recipient.getContentStream(privateKey, "BC");
+	*
+	*          processDataStream(recData.getContentStream());
+	*
+	*          if (!Arrays.equals(ad.getMac(), recipient.getMac())
+	*          {
+	*              System.err.println("Data corrupted!!!!");
+	*          }
+	*      }
+	*  </pre>
+	*  Note: this class does not introduce buffering - if you are processing large files you should create
+	*  the parser with:
+	*  <pre>
+	*          CMSAuthenticatedDataParser     ep = new CMSAuthenticatedDataParser(new BufferedInputStream(inputStream, bufSize));
+	*  </pre>
+	*  where bufSize is a suitably large buffer size.
+	* </p>
+	*/
+	public class CmsAuthenticatedDataParser
+		: CmsContentInfoParser
+	{
+		internal RecipientInformationStore	_recipientInfoStore;
+		internal AuthenticatedDataParser	authData;
+
+		private AlgorithmIdentifier			macAlg;
+		private byte[]						mac;
+		private Asn1.Cms.AttributeTable		authAttrs;
+		private Asn1.Cms.AttributeTable		unauthAttrs;
+
+		private bool authAttrNotRead;
+		private bool unauthAttrNotRead;
+
+		public CmsAuthenticatedDataParser(
+			byte[] envelopedData)
+			: this(new MemoryStream(envelopedData, false))
+		{
+		}
+
+		public CmsAuthenticatedDataParser(
+			Stream envelopedData)
+			: base(envelopedData)
+		{
+			this.authAttrNotRead = true;
+			this.authData = new AuthenticatedDataParser(
+				(Asn1SequenceParser)contentInfo.GetContent(Asn1Tags.Sequence));
+
+			// TODO Validate version?
+			//DerInteger version = this.authData.getVersion();
+
+			//
+			// read the recipients
+			//
+			Asn1Set recipientInfos = Asn1Set.GetInstance(authData.GetRecipientInfos().ToAsn1Object());
+
+			this.macAlg = authData.GetMacAlgorithm();
+
+			//
+			// read the authenticated content info
+			//
+			ContentInfoParser data = authData.GetEnapsulatedContentInfo();
+			CmsReadable readable = new CmsProcessableInputStream(
+				((Asn1OctetStringParser)data.GetContent(Asn1Tags.OctetString)).GetOctetStream());
+			CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsAuthenticatedSecureReadable(
+				this.macAlg, readable);
+
+			//
+			// build the RecipientInformationStore
+			//
+			this._recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
+				recipientInfos, secureReadable);
+		}
+
+		public AlgorithmIdentifier MacAlgorithmID
+		{
+			get { return macAlg; }
+		}
+
+		/**
+		* return the object identifier for the mac algorithm.
+		*/
+		public string MacAlgOid
+		{
+			get { return macAlg.ObjectID.Id; }
+		}
+
+
+		/**
+		 * return the ASN.1 encoded encryption algorithm parameters, or null if
+		 * there aren't any.
+		 */
+		public Asn1Object MacAlgParams
+		{
+			get
+			{
+				Asn1Encodable ae = macAlg.Parameters;
+
+				return ae == null ? null : ae.ToAsn1Object();
+			}
+		}
+
+		/**
+		* return a store of the intended recipients for this message
+		*/
+		public RecipientInformationStore GetRecipientInfos()
+		{
+			return _recipientInfoStore;
+		}
+
+		public byte[] GetMac()
+		{
+			if (mac == null)
+			{
+				GetAuthAttrs();
+				mac = authData.GetMac().GetOctets();
+			}
+			return Arrays.Clone(mac);
+		}
+
+		/**
+		* return a table of the unauthenticated attributes indexed by
+		* the OID of the attribute.
+		* @exception java.io.IOException
+		*/
+		public Asn1.Cms.AttributeTable GetAuthAttrs()
+		{
+			if (authAttrs == null && authAttrNotRead)
+			{
+				Asn1SetParser s = authData.GetAuthAttrs();
+
+				authAttrNotRead = false;
+
+				if (s != null)
+				{
+					Asn1EncodableVector v = new Asn1EncodableVector();
+
+					IAsn1Convertible o;
+					while ((o = s.ReadObject()) != null)
+					{
+						Asn1SequenceParser seq = (Asn1SequenceParser)o;
+
+						v.Add(seq.ToAsn1Object());
+					}
+
+					authAttrs = new Asn1.Cms.AttributeTable(new DerSet(v));
+				}
+			}
+
+			return authAttrs;
+		}
+
+		/**
+		* return a table of the unauthenticated attributes indexed by
+		* the OID of the attribute.
+		* @exception java.io.IOException
+		*/
+		public Asn1.Cms.AttributeTable GetUnauthAttrs()
+		{
+			if (unauthAttrs == null && unauthAttrNotRead)
+			{
+				Asn1SetParser s = authData.GetUnauthAttrs();
+
+				unauthAttrNotRead = false;
+
+				if (s != null)
+				{
+					Asn1EncodableVector v = new Asn1EncodableVector();
+
+					IAsn1Convertible o;
+					while ((o = s.ReadObject()) != null)
+					{
+						Asn1SequenceParser seq = (Asn1SequenceParser)o;
+
+						v.Add(seq.ToAsn1Object());
+					}
+
+					unauthAttrs = new Asn1.Cms.AttributeTable(new DerSet(v));
+				}
+			}
+
+			return unauthAttrs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataStreamGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataStreamGenerator.cs
new file mode 100644
index 0000000..6638ccf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedDataStreamGenerator.cs
@@ -0,0 +1,276 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* General class for generating a CMS authenticated-data message stream.
+	* <p>
+	* A simple example of usage.
+	* <pre>
+	*      CMSAuthenticatedDataStreamGenerator edGen = new CMSAuthenticatedDataStreamGenerator();
+	*
+	*      edGen.addKeyTransRecipient(cert);
+	*
+	*      ByteArrayOutputStream  bOut = new ByteArrayOutputStream();
+	*
+	*      OutputStream out = edGen.open(
+	*                              bOut, CMSAuthenticatedDataGenerator.AES128_CBC, "BC");*
+	*      out.write(data);
+	*
+	*      out.close();
+	* </pre>
+	* </p>
+	*/
+	public class CmsAuthenticatedDataStreamGenerator
+		: CmsAuthenticatedGenerator
+	{
+		// TODO Add support
+//		private object              _originatorInfo = null;
+//		private object              _unprotectedAttributes = null;
+		private int                 _bufferSize;
+		private bool                _berEncodeRecipientSet;
+
+		/**
+		* base constructor
+		*/
+		public CmsAuthenticatedDataStreamGenerator()
+		{
+		}
+
+		/**
+		* constructor allowing specific source of randomness
+		* @param rand instance of SecureRandom to use
+		*/
+		public CmsAuthenticatedDataStreamGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+
+		/**
+		* Set the underlying string size for encapsulated data
+		*
+		* @param bufferSize length of octet strings to buffer the data.
+		*/
+		public void SetBufferSize(
+			int bufferSize)
+		{
+			_bufferSize = bufferSize;
+		}
+
+		/**
+		* Use a BER Set to store the recipient information
+		*/
+		public void SetBerEncodeRecipients(
+			bool berEncodeRecipientSet)
+		{
+			_berEncodeRecipientSet = berEncodeRecipientSet;
+		}
+
+		/**
+		* generate an enveloped object that contains an CMS Enveloped Data
+		* object using the given provider and the passed in key generator.
+		* @throws java.io.IOException
+		*/
+		private Stream Open(
+			Stream				outStr,
+			string				macOid,
+			CipherKeyGenerator	keyGen)
+		{
+			// FIXME Will this work for macs?
+			byte[] encKeyBytes = keyGen.GenerateKey();
+			KeyParameter encKey = ParameterUtilities.CreateKeyParameter(macOid, encKeyBytes);
+
+			Asn1Encodable asn1Params = GenerateAsn1Parameters(macOid, encKeyBytes);
+
+			ICipherParameters cipherParameters;
+			AlgorithmIdentifier macAlgId = GetAlgorithmIdentifier(
+				macOid, encKey, asn1Params, out cipherParameters);
+
+			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+			foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
+			{
+				try
+				{
+					recipientInfos.Add(rig.Generate(encKey, rand));
+				}
+				catch (InvalidKeyException e)
+				{
+					throw new CmsException("key inappropriate for algorithm.", e);
+				}
+				catch (GeneralSecurityException e)
+				{
+					throw new CmsException("error making encrypted content.", e);
+				}
+			}
+
+			// FIXME Only passing key at the moment
+//			return Open(outStr, macAlgId, cipherParameters, recipientInfos);
+			return Open(outStr, macAlgId, encKey, recipientInfos);
+		}
+
+		protected Stream Open(
+			Stream        			outStr,
+			AlgorithmIdentifier		macAlgId,
+			ICipherParameters		cipherParameters,
+			Asn1EncodableVector		recipientInfos)
+		{
+			try
+			{
+				//
+				// ContentInfo
+				//
+				BerSequenceGenerator cGen = new BerSequenceGenerator(outStr);
+
+				cGen.AddObject(CmsObjectIdentifiers.AuthenticatedData);
+
+				//
+				// Authenticated Data
+				//
+				BerSequenceGenerator authGen = new BerSequenceGenerator(
+					cGen.GetRawOutputStream(), 0, true);
+
+				authGen.AddObject(new DerInteger(AuthenticatedData.CalculateVersion(null)));
+
+				Stream authRaw = authGen.GetRawOutputStream();
+				Asn1Generator recipGen = _berEncodeRecipientSet
+					?	(Asn1Generator) new BerSetGenerator(authRaw)
+					:	new DerSetGenerator(authRaw);
+
+				foreach (Asn1Encodable ae in recipientInfos)
+				{
+					recipGen.AddObject(ae);
+				}
+
+				recipGen.Close();
+
+				authGen.AddObject(macAlgId);
+
+				BerSequenceGenerator eiGen = new BerSequenceGenerator(authRaw);
+				eiGen.AddObject(CmsObjectIdentifiers.Data);
+
+				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
+					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
+
+				IMac mac = MacUtilities.GetMac(macAlgId.ObjectID);
+				// TODO Confirm no ParametersWithRandom needed
+	            mac.Init(cipherParameters);
+				Stream mOut = new TeeOutputStream(octetOutputStream, new MacOutputStream(mac));
+
+				return new CmsAuthenticatedDataOutputStream(mOut, mac, cGen, authGen, eiGen);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception decoding algorithm parameters.", e);
+			}
+		}
+
+		/**
+		* generate an enveloped object that contains an CMS Enveloped Data object
+		*/
+		public Stream Open(
+			Stream	outStr,
+			string	encryptionOid)
+		{
+			CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+			keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
+
+			return Open(outStr, encryptionOid, keyGen);
+		}
+
+		/**
+		* generate an enveloped object that contains an CMS Enveloped Data object
+		*/
+		public Stream Open(
+			Stream	outStr,
+			string	encryptionOid,
+			int		keySize)
+		{
+			CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+			keyGen.Init(new KeyGenerationParameters(rand, keySize));
+
+			return Open(outStr, encryptionOid, keyGen);
+		}
+
+		private class CmsAuthenticatedDataOutputStream
+			: BaseOutputStream
+		{
+			private readonly Stream					macStream;
+			private readonly IMac					mac;
+			private readonly BerSequenceGenerator	cGen;
+			private readonly BerSequenceGenerator	authGen;
+			private readonly BerSequenceGenerator	eiGen;
+
+			public CmsAuthenticatedDataOutputStream(
+				Stream					macStream,
+				IMac					mac,
+				BerSequenceGenerator	cGen,
+				BerSequenceGenerator	authGen,
+				BerSequenceGenerator	eiGen)
+			{
+				this.macStream = macStream;
+				this.mac = mac;
+				this.cGen = cGen;
+				this.authGen = authGen;
+				this.eiGen = eiGen;
+			}
+
+			public override void WriteByte(
+				byte b)
+			{
+				macStream.WriteByte(b);
+			}
+
+			public override void Write(
+				byte[]	bytes,
+				int		off,
+				int		len)
+			{
+				macStream.Write(bytes, off, len);
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+                    macStream.Dispose();
+
+                    // TODO Parent context(s) should really be be closed explicitly
+
+                    eiGen.Close();
+
+                    // [TODO] auth attributes go here 
+                    byte[] macOctets = MacUtilities.DoFinal(mac);
+                    authGen.AddObject(new DerOctetString(macOctets));
+                    // [TODO] unauth attributes go here
+
+                    authGen.Close();
+                    cGen.Close();
+		        }
+		        base.Dispose(disposing);
+		    }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedGenerator.cs
new file mode 100644
index 0000000..8824d19
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSAuthenticatedGenerator.cs
@@ -0,0 +1,35 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class CmsAuthenticatedGenerator
+		: CmsEnvelopedGenerator
+	{
+		/**
+		* base constructor
+		*/
+		public CmsAuthenticatedGenerator()
+		{
+		}
+
+		/**
+		* constructor allowing specific source of randomness
+		*
+		* @param rand instance of SecureRandom to use
+		*/
+		public CmsAuthenticatedGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSCompressedData.cs b/BouncyCastle.AxCrypt/src/cms/CMSCompressedData.cs
new file mode 100644
index 0000000..a351d72
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSCompressedData.cs
@@ -0,0 +1,107 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * containing class for an CMS Compressed Data object
+    */
+    public class CmsCompressedData
+    {
+        internal ContentInfo contentInfo;
+
+		public CmsCompressedData(
+            byte[] compressedData)
+            : this(CmsUtilities.ReadContentInfo(compressedData))
+        {
+        }
+
+		public CmsCompressedData(
+            Stream compressedDataStream)
+            : this(CmsUtilities.ReadContentInfo(compressedDataStream))
+        {
+        }
+
+		public CmsCompressedData(
+            ContentInfo contentInfo)
+        {
+            this.contentInfo = contentInfo;
+        }
+
+		/**
+		 * Return the uncompressed content.
+		 *
+		 * @return the uncompressed content
+		 * @throws CmsException if there is an exception uncompressing the data.
+		 */
+		public byte[] GetContent()
+        {
+            CompressedData comData = CompressedData.GetInstance(contentInfo.Content);
+            ContentInfo content = comData.EncapContentInfo;
+
+			Asn1OctetString bytes = (Asn1OctetString) content.Content;
+			ZInputStream zIn = new ZInputStream(bytes.GetOctetStream());
+
+			try
+			{
+				return CmsUtilities.StreamToByteArray(zIn);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception reading compressed stream.", e);
+			}
+			finally
+			{
+				zIn.Dispose();
+			}
+        }
+
+	    /**
+	     * Return the uncompressed content, throwing an exception if the data size
+	     * is greater than the passed in limit. If the content is exceeded getCause()
+	     * on the CMSException will contain a StreamOverflowException
+	     *
+	     * @param limit maximum number of bytes to read
+	     * @return the content read
+	     * @throws CMSException if there is an exception uncompressing the data.
+	     */
+		public byte[] GetContent(int limit)
+		{
+			CompressedData  comData = CompressedData.GetInstance(contentInfo.Content);
+			ContentInfo     content = comData.EncapContentInfo;
+
+			Asn1OctetString bytes = (Asn1OctetString)content.Content;
+
+			ZInputStream zIn = new ZInputStream(new MemoryStream(bytes.GetOctets(), false));
+
+			try
+			{
+				return CmsUtilities.StreamToByteArray(zIn, limit);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception reading compressed stream.", e);
+			}
+		}
+
+		/**
+		 * return the ContentInfo 
+		 */
+		public ContentInfo ContentInfo
+		{
+			get { return contentInfo; }
+		}
+
+		/**
+        * return the ASN.1 encoded representation of this object.
+        */
+        public byte[] GetEncoded()
+        {
+			return contentInfo.GetEncoded();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataGenerator.cs
new file mode 100644
index 0000000..f147bb7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataGenerator.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * General class for generating a compressed CMS message.
+    * <p>
+    * A simple example of usage.</p>
+    * <p>
+    * <pre>
+    *      CMSCompressedDataGenerator fact = new CMSCompressedDataGenerator();
+    *      CMSCompressedData data = fact.Generate(content, algorithm);
+    * </pre>
+	* </p>
+    */
+    public class CmsCompressedDataGenerator
+    {
+        public const string ZLib = "1.2.840.113549.1.9.16.3.8";
+
+		public CmsCompressedDataGenerator()
+        {
+        }
+
+		/**
+        * Generate an object that contains an CMS Compressed Data
+        */
+        public CmsCompressedData Generate(
+            CmsProcessable	content,
+            string			compressionOid)
+        {
+            AlgorithmIdentifier comAlgId;
+            Asn1OctetString comOcts;
+
+            try
+            {
+                MemoryStream bOut = new MemoryStream();
+                ZOutputStream zOut = new ZOutputStream(bOut, JZlib.Z_DEFAULT_COMPRESSION);
+
+				content.Write(zOut);
+
+				zOut.Dispose();
+
+				comAlgId = new AlgorithmIdentifier(new DerObjectIdentifier(compressionOid));
+				comOcts = new BerOctetString(bOut.ToArray());
+            }
+            catch (IOException e)
+            {
+                throw new CmsException("exception encoding data.", e);
+            }
+
+            ContentInfo comContent = new ContentInfo(CmsObjectIdentifiers.Data, comOcts);
+            ContentInfo contentInfo = new ContentInfo(
+                CmsObjectIdentifiers.CompressedData,
+                new CompressedData(comAlgId, comContent));
+
+			return new CmsCompressedData(contentInfo);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataParser.cs b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataParser.cs
new file mode 100644
index 0000000..93dfa12
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataParser.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * Class for reading a CMS Compressed Data stream.
+    * <pre>
+    *     CMSCompressedDataParser cp = new CMSCompressedDataParser(inputStream);
+    *
+    *     process(cp.GetContent().GetContentStream());
+    * </pre>
+    *  Note: this class does not introduce buffering - if you are processing large files you should create
+    *  the parser with:
+    *  <pre>
+    *      CMSCompressedDataParser     ep = new CMSCompressedDataParser(new BufferedInputStream(inputStream, bufSize));
+    *  </pre>
+    *  where bufSize is a suitably large buffer size.
+    */
+    public class CmsCompressedDataParser
+        : CmsContentInfoParser
+    {
+        public CmsCompressedDataParser(
+            byte[] compressedData)
+            : this(new MemoryStream(compressedData, false))
+        {
+        }
+
+        public CmsCompressedDataParser(
+            Stream compressedData)
+            : base(compressedData)
+        {
+        }
+
+		public CmsTypedStream GetContent()
+        {
+            try
+            {
+                CompressedDataParser comData = new CompressedDataParser((Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence));
+                ContentInfoParser content = comData.GetEncapContentInfo();
+
+                Asn1OctetStringParser bytes = (Asn1OctetStringParser)content.GetContent(Asn1Tags.OctetString);
+
+                return new CmsTypedStream(content.ContentType.ToString(), new ZInputStream(bytes.GetOctetStream()));
+            }
+            catch (IOException e)
+            {
+                throw new CmsException("IOException reading compressed content.", e);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataStreamGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataStreamGenerator.cs
new file mode 100644
index 0000000..c5a4afa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSCompressedDataStreamGenerator.cs
@@ -0,0 +1,143 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* General class for generating a compressed CMS message stream.
+	* <p>
+	* A simple example of usage.
+	* </p>
+	* <pre>
+	*      CMSCompressedDataStreamGenerator gen = new CMSCompressedDataStreamGenerator();
+	*
+	*      Stream cOut = gen.Open(outputStream, CMSCompressedDataStreamGenerator.ZLIB);
+	*
+	*      cOut.Write(data);
+	*
+	*      cOut.Close();
+	* </pre>
+	*/
+	public class CmsCompressedDataStreamGenerator
+	{
+		public const string ZLib = "1.2.840.113549.1.9.16.3.8";
+
+		private int _bufferSize;
+		
+		/**
+		* base constructor
+		*/
+		public CmsCompressedDataStreamGenerator()
+		{
+		}
+
+		/**
+		* Set the underlying string size for encapsulated data
+		*
+		* @param bufferSize length of octet strings to buffer the data.
+		*/
+		public void SetBufferSize(
+			int bufferSize)
+		{
+			_bufferSize = bufferSize;
+		}
+
+		public Stream Open(
+			Stream	outStream,
+			string	compressionOID)
+		{
+			return Open(outStream, CmsObjectIdentifiers.Data.Id, compressionOID);
+		}
+
+		public Stream Open(
+			Stream	outStream,
+			string	contentOID,
+			string	compressionOID)
+		{
+			BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
+
+			sGen.AddObject(CmsObjectIdentifiers.CompressedData);
+
+			//
+			// Compressed Data
+			//
+			BerSequenceGenerator cGen = new BerSequenceGenerator(
+				sGen.GetRawOutputStream(), 0, true);
+
+			// CMSVersion
+			cGen.AddObject(new DerInteger(0));
+
+			// CompressionAlgorithmIdentifier
+			cGen.AddObject(new AlgorithmIdentifier(new DerObjectIdentifier(ZLib)));
+
+			//
+			// Encapsulated ContentInfo
+			//
+			BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream());
+
+			eiGen.AddObject(new DerObjectIdentifier(contentOID));
+
+			Stream octetStream = CmsUtilities.CreateBerOctetOutputStream(
+				eiGen.GetRawOutputStream(), 0, true, _bufferSize);
+
+			return new CmsCompressedOutputStream(
+				new ZOutputStream(octetStream, JZlib.Z_DEFAULT_COMPRESSION), sGen, cGen, eiGen);
+		}
+
+		private class CmsCompressedOutputStream
+			: BaseOutputStream
+		{
+			private ZOutputStream _out;
+			private BerSequenceGenerator _sGen;
+			private BerSequenceGenerator _cGen;
+			private BerSequenceGenerator _eiGen;
+
+			internal CmsCompressedOutputStream(
+				ZOutputStream			outStream,
+				BerSequenceGenerator	sGen,
+				BerSequenceGenerator	cGen,
+				BerSequenceGenerator	eiGen)
+			{
+				_out = outStream;
+				_sGen = sGen;
+				_cGen = cGen;
+				_eiGen = eiGen;
+			}
+
+			public override void WriteByte(
+				byte b)
+			{
+				_out.WriteByte(b);
+			}
+
+			public override void Write(
+				byte[]	bytes,
+				int		off,
+				int		len)
+			{
+				_out.Write(bytes, off, len);
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+                    _out.Dispose();
+
+                    // TODO Parent context(s) should really be be closed explicitly
+
+                    _eiGen.Close();
+                    _cGen.Close();
+                    _sGen.Close();
+		        }
+		        base.Dispose(disposing);
+		    }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSContentInfoParser.cs b/BouncyCastle.AxCrypt/src/cms/CMSContentInfoParser.cs
new file mode 100644
index 0000000..5b16063
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSContentInfoParser.cs
@@ -0,0 +1,47 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class CmsContentInfoParser
+	{
+		protected ContentInfoParser	contentInfo;
+		protected Stream data;
+
+		protected CmsContentInfoParser(
+			Stream data)
+		{
+			if (data == null)
+				throw new ArgumentNullException("data");
+
+			this.data = data;
+
+			try
+			{
+				Asn1StreamParser inStream = new Asn1StreamParser(data);
+
+				this.contentInfo = new ContentInfoParser((Asn1SequenceParser)inStream.ReadObject());
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("IOException reading content.", e);
+			}
+			catch (InvalidCastException e)
+			{
+				throw new CmsException("Unexpected object reading content.", e);
+			}
+		}
+
+		/**
+		* Close the underlying data stream.
+		* @throws IOException if the close fails.
+		*/
+		public void Close()
+		{
+            this.data.Dispose();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedData.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedData.cs
new file mode 100644
index 0000000..0731c30
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedData.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * containing class for an CMS Enveloped Data object
+    */
+    public class CmsEnvelopedData
+    {
+        internal RecipientInformationStore	recipientInfoStore;
+        internal ContentInfo				contentInfo;
+
+		private AlgorithmIdentifier	encAlg;
+        private Asn1Set				unprotectedAttributes;
+
+		public CmsEnvelopedData(
+            byte[] envelopedData)
+            : this(CmsUtilities.ReadContentInfo(envelopedData))
+        {
+        }
+
+        public CmsEnvelopedData(
+            Stream envelopedData)
+            : this(CmsUtilities.ReadContentInfo(envelopedData))
+        {
+        }
+
+        public CmsEnvelopedData(
+            ContentInfo contentInfo)
+        {
+            this.contentInfo = contentInfo;
+
+			EnvelopedData envData = EnvelopedData.GetInstance(contentInfo.Content);
+
+			//
+			// read the recipients
+			//
+			Asn1Set recipientInfos = envData.RecipientInfos;
+
+			//
+			// read the encrypted content info
+			//
+			EncryptedContentInfo encInfo = envData.EncryptedContentInfo;
+			this.encAlg = encInfo.ContentEncryptionAlgorithm;
+			CmsReadable readable = new CmsProcessableByteArray(encInfo.EncryptedContent.GetOctets());
+			CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable(
+				this.encAlg, readable);
+
+			//
+			// build the RecipientInformationStore
+			//
+			this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
+				recipientInfos, secureReadable);
+
+			this.unprotectedAttributes = envData.UnprotectedAttrs;
+        }
+
+		public AlgorithmIdentifier EncryptionAlgorithmID
+		{
+			get { return encAlg; }
+		}
+
+		/**
+        * return the object identifier for the content encryption algorithm.
+        */
+        public string EncryptionAlgOid
+        {
+			get { return encAlg.ObjectID.Id; }
+        }
+
+		/**
+        * return a store of the intended recipients for this message
+        */
+        public RecipientInformationStore GetRecipientInfos()
+        {
+            return recipientInfoStore;
+        }
+
+		/**
+		 * return the ContentInfo 
+		 */
+		public ContentInfo ContentInfo
+		{
+			get { return contentInfo; }
+		}
+
+		/**
+        * return a table of the unprotected attributes indexed by
+        * the OID of the attribute.
+        */
+        public Asn1.Cms.AttributeTable GetUnprotectedAttributes()
+        {
+            if (unprotectedAttributes == null)
+                return null;
+
+			return new Asn1.Cms.AttributeTable(unprotectedAttributes);
+        }
+
+		/**
+        * return the ASN.1 encoded representation of this object.
+        */
+        public byte[] GetEncoded()
+        {
+			return contentInfo.GetEncoded();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataGenerator.cs
new file mode 100644
index 0000000..5071af4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataGenerator.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+    /// <remarks>
+    /// General class for generating a CMS enveloped-data message.
+    ///
+    /// A simple example of usage.
+    ///
+    /// <pre>
+    ///      CmsEnvelopedDataGenerator  fact = new CmsEnvelopedDataGenerator();
+    ///
+    ///      fact.AddKeyTransRecipient(cert);
+    ///
+    ///      CmsEnvelopedData         data = fact.Generate(content, algorithm);
+    /// </pre>
+    /// </remarks>
+    public class CmsEnvelopedDataGenerator
+		: CmsEnvelopedGenerator
+    {
+		public CmsEnvelopedDataGenerator()
+        {
+        }
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		public CmsEnvelopedDataGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+
+		/// <summary>
+		/// Generate an enveloped object that contains a CMS Enveloped Data
+		/// object using the passed in key generator.
+		/// </summary>
+        private CmsEnvelopedData Generate(
+            CmsProcessable		content,
+            string				encryptionOid,
+            CipherKeyGenerator	keyGen)
+        {
+            AlgorithmIdentifier encAlgId = null;
+			KeyParameter encKey;
+            Asn1OctetString encContent;
+
+			try
+			{
+				byte[] encKeyBytes = keyGen.GenerateKey();
+				encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);
+
+				Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);
+
+				ICipherParameters cipherParameters;
+				encAlgId = GetAlgorithmIdentifier(
+					encryptionOid, encKey, asn1Params, out cipherParameters);
+
+				IBufferedCipher cipher = CipherUtilities.GetCipher(encryptionOid);
+				cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));
+
+				MemoryStream bOut = new MemoryStream();
+				CipherStream cOut = new CipherStream(bOut, null, cipher);
+
+				content.Write(cOut);
+
+                cOut.Dispose();
+
+				encContent = new BerOctetString(bOut.ToArray());
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception decoding algorithm parameters.", e);
+			}
+
+
+			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+            foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
+            {
+                try
+                {
+                    recipientInfos.Add(rig.Generate(encKey, rand));
+                }
+                catch (InvalidKeyException e)
+                {
+                    throw new CmsException("key inappropriate for algorithm.", e);
+                }
+                catch (GeneralSecurityException e)
+                {
+                    throw new CmsException("error making encrypted content.", e);
+                }
+            }
+
+            EncryptedContentInfo eci = new EncryptedContentInfo(
+                CmsObjectIdentifiers.Data,
+                encAlgId,
+                encContent);
+
+			Asn1Set unprotectedAttrSet = null;
+            if (unprotectedAttributeGenerator != null)
+            {
+                Asn1.Cms.AttributeTable attrTable = unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());
+
+                unprotectedAttrSet = new BerSet(attrTable.ToAsn1EncodableVector());
+            }
+
+			ContentInfo contentInfo = new ContentInfo(
+                CmsObjectIdentifiers.EnvelopedData,
+                new EnvelopedData(null, new DerSet(recipientInfos), eci, unprotectedAttrSet));
+
+            return new CmsEnvelopedData(contentInfo);
+        }
+
+		/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        public CmsEnvelopedData Generate(
+            CmsProcessable	content,
+            string			encryptionOid)
+        {
+            try
+            {
+				CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+				keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
+
+				return Generate(content, encryptionOid, keyGen);
+            }
+            catch (SecurityUtilityException e)
+            {
+                throw new CmsException("can't find key generation algorithm.", e);
+            }
+        }
+
+		/// <summary>Generate an enveloped object that contains an CMS Enveloped Data object.</summary>
+        public CmsEnvelopedData Generate(
+            CmsProcessable  content,
+            string          encryptionOid,
+            int             keySize)
+        {
+            try
+            {
+				CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+				keyGen.Init(new KeyGenerationParameters(rand, keySize));
+
+				return Generate(content, encryptionOid, keyGen);
+            }
+            catch (SecurityUtilityException e)
+            {
+                throw new CmsException("can't find key generation algorithm.", e);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataParser.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataParser.cs
new file mode 100644
index 0000000..01a949d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataParser.cs
@@ -0,0 +1,161 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* Parsing class for an CMS Enveloped Data object from an input stream.
+	* <p>
+	* Note: that because we are in a streaming mode only one recipient can be tried and it is important
+	* that the methods on the parser are called in the appropriate order.
+	* </p>
+	* <p>
+	* Example of use - assuming the first recipient matches the private key we have.
+	* <pre>
+	*      CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(inputStream);
+	*
+	*      RecipientInformationStore  recipients = ep.GetRecipientInfos();
+	*
+	*      Collection  c = recipients.getRecipients();
+	*      Iterator    it = c.iterator();
+	*
+	*      if (it.hasNext())
+	*      {
+	*          RecipientInformation   recipient = (RecipientInformation)it.next();
+	*
+	*          CMSTypedStream recData = recipient.getContentStream(privateKey);
+	*
+	*          processDataStream(recData.getContentStream());
+	*      }
+	*  </pre>
+	*  Note: this class does not introduce buffering - if you are processing large files you should create
+	*  the parser with:
+	*  <pre>
+	*          CmsEnvelopedDataParser     ep = new CmsEnvelopedDataParser(new BufferedInputStream(inputStream, bufSize));
+	*  </pre>
+	*  where bufSize is a suitably large buffer size.
+	* </p>
+	*/
+	public class CmsEnvelopedDataParser
+		: CmsContentInfoParser
+	{
+		internal RecipientInformationStore	recipientInfoStore;
+		internal EnvelopedDataParser		envelopedData;
+
+		private AlgorithmIdentifier			_encAlg;
+		private Asn1.Cms.AttributeTable		_unprotectedAttributes;
+		private bool						_attrNotRead;
+
+		public CmsEnvelopedDataParser(
+			byte[] envelopedData)
+			: this(new MemoryStream(envelopedData, false))
+		{
+		}
+
+		public CmsEnvelopedDataParser(
+			Stream envelopedData)
+			: base(envelopedData)
+		{
+			this._attrNotRead = true;
+			this.envelopedData = new EnvelopedDataParser(
+				(Asn1SequenceParser)this.contentInfo.GetContent(Asn1Tags.Sequence));
+
+			// TODO Validate version?
+			//DerInteger version = this.envelopedData.Version;
+
+			//
+			// read the recipients
+			//
+			Asn1Set recipientInfos = Asn1Set.GetInstance(this.envelopedData.GetRecipientInfos().ToAsn1Object());
+
+			//
+			// read the encrypted content info
+			//
+			EncryptedContentInfoParser encInfo = this.envelopedData.GetEncryptedContentInfo();
+			this._encAlg = encInfo.ContentEncryptionAlgorithm;
+			CmsReadable readable = new CmsProcessableInputStream(
+				((Asn1OctetStringParser)encInfo.GetEncryptedContent(Asn1Tags.OctetString)).GetOctetStream());
+			CmsSecureReadable secureReadable = new CmsEnvelopedHelper.CmsEnvelopedSecureReadable(
+				this._encAlg, readable);
+
+			//
+			// build the RecipientInformationStore
+			//
+			this.recipientInfoStore = CmsEnvelopedHelper.BuildRecipientInformationStore(
+				recipientInfos, secureReadable);
+		}
+
+		public AlgorithmIdentifier EncryptionAlgorithmID
+		{
+			get { return _encAlg; }
+		}
+
+		/**
+		 * return the object identifier for the content encryption algorithm.
+		 */
+		public string EncryptionAlgOid
+		{
+			get { return _encAlg.ObjectID.Id; }
+		}
+
+		/**
+		 * return the ASN.1 encoded encryption algorithm parameters, or null if
+		 * there aren't any.
+		 */
+		public Asn1Object EncryptionAlgParams
+		{
+			get
+			{
+				Asn1Encodable ae = _encAlg.Parameters;
+
+				return ae == null ? null : ae.ToAsn1Object();
+			}
+		}
+
+		/**
+		 * return a store of the intended recipients for this message
+		 */
+		public RecipientInformationStore GetRecipientInfos()
+		{
+			return this.recipientInfoStore;
+		}
+
+		/**
+		 * return a table of the unprotected attributes indexed by
+		 * the OID of the attribute.
+		 * @throws IOException
+		 */
+		public Asn1.Cms.AttributeTable GetUnprotectedAttributes()
+		{
+			if (_unprotectedAttributes == null && _attrNotRead)
+			{
+				Asn1SetParser asn1Set = this.envelopedData.GetUnprotectedAttrs();
+
+				_attrNotRead = false;
+
+				if (asn1Set != null)
+				{
+					Asn1EncodableVector v = new Asn1EncodableVector();
+					IAsn1Convertible o;
+
+					while ((o = asn1Set.ReadObject()) != null)
+					{
+						Asn1SequenceParser seq = (Asn1SequenceParser)o;
+
+						v.Add(seq.ToAsn1Object());
+					}
+
+					_unprotectedAttributes = new Asn1.Cms.AttributeTable(new DerSet(v));
+				}
+			}
+
+			return _unprotectedAttributes;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataStreamGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataStreamGenerator.cs
new file mode 100644
index 0000000..cb5b246
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedDataStreamGenerator.cs
@@ -0,0 +1,284 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* General class for generating a CMS enveloped-data message stream.
+	* <p>
+	* A simple example of usage.
+	* <pre>
+	*      CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+	*
+	*      edGen.AddKeyTransRecipient(cert);
+	*
+	*      MemoryStream  bOut = new MemoryStream();
+	*
+	*      Stream out = edGen.Open(
+	*                              bOut, CMSEnvelopedDataGenerator.AES128_CBC);*
+	*      out.Write(data);
+	*
+	*      out.Close();
+	* </pre>
+	* </p>
+	*/
+	public class CmsEnvelopedDataStreamGenerator
+		: CmsEnvelopedGenerator
+	{
+		private object	_originatorInfo = null;
+		private object	_unprotectedAttributes = null;
+		private int		_bufferSize;
+		private bool	_berEncodeRecipientSet;
+
+		public CmsEnvelopedDataStreamGenerator()
+		{
+		}
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		public CmsEnvelopedDataStreamGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+
+		/// <summary>Set the underlying string size for encapsulated data.</summary>
+		/// <param name="bufferSize">Length of octet strings to buffer the data.</param>
+		public void SetBufferSize(
+			int bufferSize)
+		{
+			_bufferSize = bufferSize;
+		}
+
+		/// <summary>Use a BER Set to store the recipient information.</summary>
+		public void SetBerEncodeRecipients(
+			bool berEncodeRecipientSet)
+		{
+			_berEncodeRecipientSet = berEncodeRecipientSet;
+		}
+
+		private DerInteger Version
+		{
+			get
+			{
+				int version = (_originatorInfo != null || _unprotectedAttributes != null)
+					?	2
+					:	0;
+
+				return new DerInteger(version);
+			}
+		}
+
+		/// <summary>
+		/// Generate an enveloped object that contains an CMS Enveloped Data
+		/// object using the passed in key generator.
+		/// </summary>
+		private Stream Open(
+			Stream				outStream,
+			string				encryptionOid,
+			CipherKeyGenerator	keyGen)
+		{
+			byte[] encKeyBytes = keyGen.GenerateKey();
+			KeyParameter encKey = ParameterUtilities.CreateKeyParameter(encryptionOid, encKeyBytes);
+
+			Asn1Encodable asn1Params = GenerateAsn1Parameters(encryptionOid, encKeyBytes);
+
+			ICipherParameters cipherParameters;
+			AlgorithmIdentifier encAlgID = GetAlgorithmIdentifier(
+				encryptionOid, encKey, asn1Params, out cipherParameters);
+
+			Asn1EncodableVector recipientInfos = new Asn1EncodableVector();
+
+			foreach (RecipientInfoGenerator rig in recipientInfoGenerators)
+			{
+				try
+				{
+					recipientInfos.Add(rig.Generate(encKey, rand));
+				}
+				catch (InvalidKeyException e)
+				{
+					throw new CmsException("key inappropriate for algorithm.", e);
+				}
+				catch (GeneralSecurityException e)
+				{
+					throw new CmsException("error making encrypted content.", e);
+				}
+			}
+
+			return Open(outStream, encAlgID, cipherParameters, recipientInfos);
+		}
+
+		private Stream Open(
+			Stream				outStream,
+			AlgorithmIdentifier	encAlgID,
+			ICipherParameters	cipherParameters,
+			Asn1EncodableVector	recipientInfos)
+		{
+			try
+			{
+				//
+				// ContentInfo
+				//
+				BerSequenceGenerator cGen = new BerSequenceGenerator(outStream);
+
+				cGen.AddObject(CmsObjectIdentifiers.EnvelopedData);
+
+				//
+				// Encrypted Data
+				//
+				BerSequenceGenerator envGen = new BerSequenceGenerator(
+					cGen.GetRawOutputStream(), 0, true);
+
+				envGen.AddObject(this.Version);
+
+				Stream envRaw = envGen.GetRawOutputStream();
+				Asn1Generator recipGen = _berEncodeRecipientSet
+					?	(Asn1Generator) new BerSetGenerator(envRaw)
+					:	new DerSetGenerator(envRaw);
+
+				foreach (Asn1Encodable ae in recipientInfos)
+				{
+					recipGen.AddObject(ae);
+				}
+
+				recipGen.Close();
+
+				BerSequenceGenerator eiGen = new BerSequenceGenerator(envRaw);
+				eiGen.AddObject(CmsObjectIdentifiers.Data);
+				eiGen.AddObject(encAlgID);
+
+				Stream octetOutputStream = CmsUtilities.CreateBerOctetOutputStream(
+					eiGen.GetRawOutputStream(), 0, false, _bufferSize);
+
+				IBufferedCipher cipher = CipherUtilities.GetCipher(encAlgID.ObjectID);
+				cipher.Init(true, new ParametersWithRandom(cipherParameters, rand));
+				CipherStream cOut = new CipherStream(octetOutputStream, null, cipher);
+
+				return new CmsEnvelopedDataOutputStream(this, cOut, cGen, envGen, eiGen);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("exception decoding algorithm parameters.", e);
+			}
+		}
+
+		/**
+		* generate an enveloped object that contains an CMS Enveloped Data object
+		* @throws IOException
+		*/
+		public Stream Open(
+			Stream	outStream,
+			string	encryptionOid)
+		{
+			CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+			keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
+
+			return Open(outStream, encryptionOid, keyGen);
+		}
+
+		/**
+		* generate an enveloped object that contains an CMS Enveloped Data object
+		* @throws IOException
+		*/
+		public Stream Open(
+			Stream	outStream,
+			string	encryptionOid,
+			int		keySize)
+		{
+			CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator(encryptionOid);
+
+			keyGen.Init(new KeyGenerationParameters(rand, keySize));
+
+			return Open(outStream, encryptionOid, keyGen);
+		}
+
+		private class CmsEnvelopedDataOutputStream
+			: BaseOutputStream
+		{
+            private readonly CmsEnvelopedGenerator _outer;
+
+			private readonly CipherStream			_out;
+			private readonly BerSequenceGenerator	_cGen;
+			private readonly BerSequenceGenerator	_envGen;
+			private readonly BerSequenceGenerator	_eiGen;
+
+			public CmsEnvelopedDataOutputStream(
+				CmsEnvelopedGenerator	outer,
+				CipherStream			outStream,
+				BerSequenceGenerator	cGen,
+				BerSequenceGenerator	envGen,
+				BerSequenceGenerator	eiGen)
+			{
+				_outer = outer;
+				_out = outStream;
+				_cGen = cGen;
+				_envGen = envGen;
+				_eiGen = eiGen;
+			}
+
+			public override void WriteByte(
+				byte b)
+			{
+				_out.WriteByte(b);
+			}
+
+			public override void Write(
+				byte[]	bytes,
+				int		off,
+				int		len)
+			{
+				_out.Write(bytes, off, len);
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+                    _out.Dispose();
+
+                    // TODO Parent context(s) should really be be closed explicitly
+
+                    _eiGen.Close();
+
+                    if (_outer.unprotectedAttributeGenerator != null)
+                    {
+                        Asn1.Cms.AttributeTable attrTable = _outer.unprotectedAttributeGenerator.GetAttributes(Platform.CreateHashtable());
+
+                        Asn1Set unprotectedAttrs = new BerSet(attrTable.ToAsn1EncodableVector());
+
+                        _envGen.AddObject(new DerTaggedObject(false, 1, unprotectedAttrs));
+                    }
+
+                    _envGen.Close();
+                    _cGen.Close();
+		        }
+		        base.Dispose(disposing);
+		    }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedGenerator.cs
new file mode 100644
index 0000000..f92ae38
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedGenerator.cs
@@ -0,0 +1,331 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* General class for generating a CMS enveloped-data message.
+	*
+	* A simple example of usage.
+	*
+	* <pre>
+	*      CMSEnvelopedDataGenerator  fact = new CMSEnvelopedDataGenerator();
+	*
+	*      fact.addKeyTransRecipient(cert);
+	*
+	*      CMSEnvelopedData         data = fact.generate(content, algorithm, "BC");
+	* </pre>
+	*/
+	public class CmsEnvelopedGenerator
+	{
+		// Note: These tables are complementary: If rc2Table[i]==j, then rc2Ekb[j]==i
+		internal static readonly short[] rc2Table =
+		{
+			0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
+			0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
+			0x41, 0x9f, 0xe1, 0xd9, 0x4a, 0x4d, 0x9e, 0xda, 0xa0, 0x68, 0x2c, 0xc3, 0x27, 0x5f, 0x80, 0x36,
+			0x3e, 0xee, 0xfb, 0x95, 0x1a, 0xfe, 0xce, 0xa8, 0x34, 0xa9, 0x13, 0xf0, 0xa6, 0x3f, 0xd8, 0x0c,
+			0x78, 0x24, 0xaf, 0x23, 0x52, 0xc1, 0x67, 0x17, 0xf5, 0x66, 0x90, 0xe7, 0xe8, 0x07, 0xb8, 0x60,
+			0x48, 0xe6, 0x1e, 0x53, 0xf3, 0x92, 0xa4, 0x72, 0x8c, 0x08, 0x15, 0x6e, 0x86, 0x00, 0x84, 0xfa,
+			0xf4, 0x7f, 0x8a, 0x42, 0x19, 0xf6, 0xdb, 0xcd, 0x14, 0x8d, 0x50, 0x12, 0xba, 0x3c, 0x06, 0x4e,
+			0xec, 0xb3, 0x35, 0x11, 0xa1, 0x88, 0x8e, 0x2b, 0x94, 0x99, 0xb7, 0x71, 0x74, 0xd3, 0xe4, 0xbf,
+			0x3a, 0xde, 0x96, 0x0e, 0xbc, 0x0a, 0xed, 0x77, 0xfc, 0x37, 0x6b, 0x03, 0x79, 0x89, 0x62, 0xc6,
+			0xd7, 0xc0, 0xd2, 0x7c, 0x6a, 0x8b, 0x22, 0xa3, 0x5b, 0x05, 0x5d, 0x02, 0x75, 0xd5, 0x61, 0xe3,
+			0x18, 0x8f, 0x55, 0x51, 0xad, 0x1f, 0x0b, 0x5e, 0x85, 0xe5, 0xc2, 0x57, 0x63, 0xca, 0x3d, 0x6c,
+			0xb4, 0xc5, 0xcc, 0x70, 0xb2, 0x91, 0x59, 0x0d, 0x47, 0x20, 0xc8, 0x4f, 0x58, 0xe0, 0x01, 0xe2,
+			0x16, 0x38, 0xc4, 0x6f, 0x3b, 0x0f, 0x65, 0x46, 0xbe, 0x7e, 0x2d, 0x7b, 0x82, 0xf9, 0x40, 0xb5,
+			0x1d, 0x73, 0xf8, 0xeb, 0x26, 0xc7, 0x87, 0x97, 0x25, 0x54, 0xb1, 0x28, 0xaa, 0x98, 0x9d, 0xa5,
+			0x64, 0x6d, 0x7a, 0xd4, 0x10, 0x81, 0x44, 0xef, 0x49, 0xd6, 0xae, 0x2e, 0xdd, 0x76, 0x5c, 0x2f,
+			0xa7, 0x1c, 0xc9, 0x09, 0x69, 0x9a, 0x83, 0xcf, 0x29, 0x39, 0xb9, 0xe9, 0x4c, 0xff, 0x43, 0xab
+		};
+
+//		internal static readonly short[] rc2Ekb =
+//		{
+//			0x5d, 0xbe, 0x9b, 0x8b, 0x11, 0x99, 0x6e, 0x4d, 0x59, 0xf3, 0x85, 0xa6, 0x3f, 0xb7, 0x83, 0xc5,
+//			0xe4, 0x73, 0x6b, 0x3a, 0x68, 0x5a, 0xc0, 0x47, 0xa0, 0x64, 0x34, 0x0c, 0xf1, 0xd0, 0x52, 0xa5,
+//			0xb9, 0x1e, 0x96, 0x43, 0x41, 0xd8, 0xd4, 0x2c, 0xdb, 0xf8, 0x07, 0x77, 0x2a, 0xca, 0xeb, 0xef,
+//			0x10, 0x1c, 0x16, 0x0d, 0x38, 0x72, 0x2f, 0x89, 0xc1, 0xf9, 0x80, 0xc4, 0x6d, 0xae, 0x30, 0x3d,
+//			0xce, 0x20, 0x63, 0xfe, 0xe6, 0x1a, 0xc7, 0xb8, 0x50, 0xe8, 0x24, 0x17, 0xfc, 0x25, 0x6f, 0xbb,
+//			0x6a, 0xa3, 0x44, 0x53, 0xd9, 0xa2, 0x01, 0xab, 0xbc, 0xb6, 0x1f, 0x98, 0xee, 0x9a, 0xa7, 0x2d,
+//			0x4f, 0x9e, 0x8e, 0xac, 0xe0, 0xc6, 0x49, 0x46, 0x29, 0xf4, 0x94, 0x8a, 0xaf, 0xe1, 0x5b, 0xc3,
+//			0xb3, 0x7b, 0x57, 0xd1, 0x7c, 0x9c, 0xed, 0x87, 0x40, 0x8c, 0xe2, 0xcb, 0x93, 0x14, 0xc9, 0x61,
+//			0x2e, 0xe5, 0xcc, 0xf6, 0x5e, 0xa8, 0x5c, 0xd6, 0x75, 0x8d, 0x62, 0x95, 0x58, 0x69, 0x76, 0xa1,
+//			0x4a, 0xb5, 0x55, 0x09, 0x78, 0x33, 0x82, 0xd7, 0xdd, 0x79, 0xf5, 0x1b, 0x0b, 0xde, 0x26, 0x21,
+//			0x28, 0x74, 0x04, 0x97, 0x56, 0xdf, 0x3c, 0xf0, 0x37, 0x39, 0xdc, 0xff, 0x06, 0xa4, 0xea, 0x42,
+//			0x08, 0xda, 0xb4, 0x71, 0xb0, 0xcf, 0x12, 0x7a, 0x4e, 0xfa, 0x6c, 0x1d, 0x84, 0x00, 0xc8, 0x7f,
+//			0x91, 0x45, 0xaa, 0x2b, 0xc2, 0xb1, 0x8f, 0xd5, 0xba, 0xf2, 0xad, 0x19, 0xb2, 0x67, 0x36, 0xf7,
+//			0x0f, 0x0a, 0x92, 0x7d, 0xe3, 0x9d, 0xe9, 0x90, 0x3e, 0x23, 0x27, 0x66, 0x13, 0xec, 0x81, 0x15,
+//			0xbd, 0x22, 0xbf, 0x9f, 0x7e, 0xa9, 0x51, 0x4b, 0x4c, 0xfb, 0x02, 0xd3, 0x70, 0x86, 0x31, 0xe7,
+//			0x3b, 0x05, 0x03, 0x54, 0x60, 0x48, 0x65, 0x18, 0xd2, 0xcd, 0x5f, 0x32, 0x88, 0x0e, 0x35, 0xfd
+//		};
+
+
+		// TODO Create named constants for all of these
+		public static readonly string DesEde3Cbc		= PkcsObjectIdentifiers.DesEde3Cbc.Id;
+		public static readonly string RC2Cbc			= PkcsObjectIdentifiers.RC2Cbc.Id;
+		public const string IdeaCbc						= "1.3.6.1.4.1.188.7.1.1.2";
+		public const string Cast5Cbc					= "1.2.840.113533.7.66.10";
+		public static readonly string Aes128Cbc			= NistObjectIdentifiers.IdAes128Cbc.Id;
+		public static readonly string Aes192Cbc			= NistObjectIdentifiers.IdAes192Cbc.Id;
+		public static readonly string Aes256Cbc			= NistObjectIdentifiers.IdAes256Cbc.Id;
+		public static readonly string Camellia128Cbc	= NttObjectIdentifiers.IdCamellia128Cbc.Id;
+		public static readonly string Camellia192Cbc	= NttObjectIdentifiers.IdCamellia192Cbc.Id;
+		public static readonly string Camellia256Cbc	= NttObjectIdentifiers.IdCamellia256Cbc.Id;
+		public static readonly string SeedCbc			= KisaObjectIdentifiers.IdSeedCbc.Id;
+
+		public static readonly string DesEde3Wrap		= PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id;
+		public static readonly string Aes128Wrap		= NistObjectIdentifiers.IdAes128Wrap.Id;
+		public static readonly string Aes192Wrap		= NistObjectIdentifiers.IdAes192Wrap.Id;
+		public static readonly string Aes256Wrap		= NistObjectIdentifiers.IdAes256Wrap.Id;
+		public static readonly string Camellia128Wrap	= NttObjectIdentifiers.IdCamellia128Wrap.Id;
+		public static readonly string Camellia192Wrap	= NttObjectIdentifiers.IdCamellia192Wrap.Id;
+		public static readonly string Camellia256Wrap	= NttObjectIdentifiers.IdCamellia256Wrap.Id;
+		public static readonly string SeedWrap			= KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id;
+
+		public static readonly string ECDHSha1Kdf		= X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id;
+		public static readonly string ECMqvSha1Kdf		= X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id;
+
+		internal readonly IList recipientInfoGenerators = Platform.CreateArrayList();
+		internal readonly SecureRandom rand;
+
+        internal CmsAttributeTableGenerator unprotectedAttributeGenerator = null;
+
+		public CmsEnvelopedGenerator()
+			: this(new SecureRandom())
+		{
+		}
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		public CmsEnvelopedGenerator(
+			SecureRandom rand)
+		{
+			this.rand = rand;
+		}
+
+        public CmsAttributeTableGenerator UnprotectedAttributeGenerator
+        {
+            get { return this.unprotectedAttributeGenerator; }
+            set { this.unprotectedAttributeGenerator = value; }
+        }
+
+		/**
+		 * add a recipient.
+		 *
+		 * @param cert recipient's public key certificate
+		 * @exception ArgumentException if there is a problem with the certificate
+		 */
+		public void AddKeyTransRecipient(
+			X509Certificate cert)
+		{
+			KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator();
+			ktrig.RecipientCert = cert;
+
+			recipientInfoGenerators.Add(ktrig);
+		}
+
+		/**
+		* add a recipient
+		*
+		* @param key the public key used by the recipient
+		* @param subKeyId the identifier for the recipient's public key
+		* @exception ArgumentException if there is a problem with the key
+		*/
+		public void AddKeyTransRecipient(
+			AsymmetricKeyParameter	pubKey,
+			byte[]					subKeyId)
+		{
+			KeyTransRecipientInfoGenerator ktrig = new KeyTransRecipientInfoGenerator();
+			ktrig.RecipientPublicKey = pubKey;
+			ktrig.SubjectKeyIdentifier = new DerOctetString(subKeyId);
+
+			recipientInfoGenerators.Add(ktrig);
+		}
+
+		/**
+		 * add a KEK recipient.
+		 * @param key the secret key to use for wrapping
+		 * @param keyIdentifier the byte string that identifies the key
+		 */
+		public void AddKekRecipient(
+			string			keyAlgorithm, // TODO Remove need for this parameter
+			KeyParameter	key,
+			byte[]			keyIdentifier)
+		{
+			AddKekRecipient(keyAlgorithm, key, new KekIdentifier(keyIdentifier, null, null));
+		}
+
+		/**
+		* add a KEK recipient.
+		* @param key the secret key to use for wrapping
+		* @param keyIdentifier the byte string that identifies the key
+		*/
+		public void AddKekRecipient(
+			string			keyAlgorithm, // TODO Remove need for this parameter
+			KeyParameter	key,
+			KekIdentifier	kekIdentifier)
+		{
+			KekRecipientInfoGenerator kekrig = new KekRecipientInfoGenerator();
+			kekrig.KekIdentifier = kekIdentifier;
+			kekrig.KeyEncryptionKeyOID = keyAlgorithm;
+			kekrig.KeyEncryptionKey = key;
+
+			recipientInfoGenerators.Add(kekrig);
+		}
+
+		public void AddPasswordRecipient(
+			CmsPbeKey	pbeKey,
+			string		kekAlgorithmOid)
+		{
+			Pbkdf2Params p = new Pbkdf2Params(pbeKey.Salt, pbeKey.IterationCount);
+
+			PasswordRecipientInfoGenerator prig = new PasswordRecipientInfoGenerator();
+			prig.KeyDerivationAlgorithm = new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPbkdf2, p);
+			prig.KeyEncryptionKeyOID = kekAlgorithmOid;
+			prig.KeyEncryptionKey = pbeKey.GetEncoded(kekAlgorithmOid);
+
+			recipientInfoGenerators.Add(prig);
+		}
+
+		/**
+		* Add a key agreement based recipient.
+		*
+		* @param agreementAlgorithm key agreement algorithm to use.
+		* @param senderPrivateKey private key to initialise sender side of agreement with.
+		* @param senderPublicKey sender public key to include with message.
+		* @param recipientCert recipient's public key certificate.
+		* @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+		* @exception SecurityUtilityException if the algorithm requested cannot be found
+		* @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+		*/
+		public void AddKeyAgreementRecipient(
+			string					agreementAlgorithm,
+			AsymmetricKeyParameter	senderPrivateKey,
+			AsymmetricKeyParameter	senderPublicKey,
+			X509Certificate			recipientCert,
+			string					cekWrapAlgorithm)
+		{
+            IList recipientCerts = Platform.CreateArrayList(1);
+			recipientCerts.Add(recipientCert);
+
+			AddKeyAgreementRecipients(agreementAlgorithm, senderPrivateKey, senderPublicKey,
+				recipientCerts, cekWrapAlgorithm);
+		}
+
+		/**
+		 * Add multiple key agreement based recipients (sharing a single KeyAgreeRecipientInfo structure).
+		 *
+		 * @param agreementAlgorithm key agreement algorithm to use.
+		 * @param senderPrivateKey private key to initialise sender side of agreement with.
+		 * @param senderPublicKey sender public key to include with message.
+		 * @param recipientCerts recipients' public key certificates.
+		 * @param cekWrapAlgorithm OID for key wrapping algorithm to use.
+		 * @exception SecurityUtilityException if the algorithm requested cannot be found
+		 * @exception InvalidKeyException if the keys are inappropriate for the algorithm specified
+		 */
+		public void AddKeyAgreementRecipients(
+			string					agreementAlgorithm,
+			AsymmetricKeyParameter	senderPrivateKey,
+			AsymmetricKeyParameter	senderPublicKey,
+			ICollection				recipientCerts,
+			string					cekWrapAlgorithm)
+		{
+			if (!senderPrivateKey.IsPrivate)
+				throw new ArgumentException("Expected private key", "senderPrivateKey");
+			if (senderPublicKey.IsPrivate)
+				throw new ArgumentException("Expected public key", "senderPublicKey");
+
+			/* TODO
+			 * "a recipient X.509 version 3 certificate that contains a key usage extension MUST
+			 * assert the keyAgreement bit."
+			 */
+
+			KeyAgreeRecipientInfoGenerator karig = new KeyAgreeRecipientInfoGenerator();
+			karig.KeyAgreementOID = new DerObjectIdentifier(agreementAlgorithm);
+			karig.KeyEncryptionOID = new DerObjectIdentifier(cekWrapAlgorithm);
+			karig.RecipientCerts = recipientCerts;
+			karig.SenderKeyPair = new AsymmetricCipherKeyPair(senderPublicKey, senderPrivateKey);
+
+			recipientInfoGenerators.Add(karig);
+		}
+
+        protected internal virtual AlgorithmIdentifier GetAlgorithmIdentifier(
+			string					encryptionOid,
+			KeyParameter			encKey,
+			Asn1Encodable			asn1Params,
+			out ICipherParameters	cipherParameters)
+		{
+			Asn1Object asn1Object;
+			if (asn1Params != null)
+			{
+				asn1Object = asn1Params.ToAsn1Object();
+				cipherParameters = ParameterUtilities.GetCipherParameters(
+					encryptionOid, encKey, asn1Object);
+			}
+			else
+			{
+				asn1Object = DerNull.Instance;
+				cipherParameters = encKey;
+			}
+
+			return new AlgorithmIdentifier(
+				new DerObjectIdentifier(encryptionOid),
+				asn1Object);
+		}
+
+		protected internal virtual Asn1Encodable GenerateAsn1Parameters(
+			string	encryptionOid,
+			byte[]	encKeyBytes)
+		{
+			Asn1Encodable asn1Params = null;
+
+			try
+			{
+				if (encryptionOid.Equals(RC2Cbc))
+				{
+					byte[] iv = new byte[8];
+					rand.NextBytes(iv);
+
+					// TODO Is this detailed repeat of Java version really necessary?
+					int effKeyBits = encKeyBytes.Length * 8;
+					int parameterVersion;
+
+					if (effKeyBits < 256)
+					{
+						parameterVersion = rc2Table[effKeyBits];
+					}
+					else
+					{
+						parameterVersion = effKeyBits;
+					}
+
+					asn1Params = new RC2CbcParameter(parameterVersion, iv);
+				}
+				else
+				{
+					asn1Params = ParameterUtilities.GenerateParameters(encryptionOid, rand);
+				}
+			}
+			catch (SecurityUtilityException)
+			{
+				// No problem... no parameters generated
+			}
+
+			return asn1Params;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedHelper.cs b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedHelper.cs
new file mode 100644
index 0000000..fe2b14c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSEnvelopedHelper.cs
@@ -0,0 +1,311 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	class CmsEnvelopedHelper
+	{
+		internal static readonly CmsEnvelopedHelper Instance = new CmsEnvelopedHelper();
+
+		private static readonly IDictionary KeySizes = Platform.CreateHashtable();
+		private static readonly IDictionary BaseCipherNames = Platform.CreateHashtable();
+
+		static CmsEnvelopedHelper()
+		{
+			KeySizes.Add(CmsEnvelopedGenerator.DesEde3Cbc, 192);
+			KeySizes.Add(CmsEnvelopedGenerator.Aes128Cbc, 128);
+			KeySizes.Add(CmsEnvelopedGenerator.Aes192Cbc, 192);
+			KeySizes.Add(CmsEnvelopedGenerator.Aes256Cbc, 256);
+
+			BaseCipherNames.Add(CmsEnvelopedGenerator.DesEde3Cbc,  "DESEDE");
+			BaseCipherNames.Add(CmsEnvelopedGenerator.Aes128Cbc,  "AES");
+			BaseCipherNames.Add(CmsEnvelopedGenerator.Aes192Cbc,  "AES");
+			BaseCipherNames.Add(CmsEnvelopedGenerator.Aes256Cbc,  "AES");
+		}
+
+		private string GetAsymmetricEncryptionAlgName(
+			string encryptionAlgOid)
+		{
+			if (Asn1.Pkcs.PkcsObjectIdentifiers.RsaEncryption.Id.Equals(encryptionAlgOid))
+			{
+				return "RSA/ECB/PKCS1Padding";
+			}
+
+			return encryptionAlgOid;
+		}
+
+		internal IBufferedCipher CreateAsymmetricCipher(
+			string encryptionOid)
+		{
+			string asymName = GetAsymmetricEncryptionAlgName(encryptionOid);
+			if (!asymName.Equals(encryptionOid))
+			{
+				try
+				{
+					return CipherUtilities.GetCipher(asymName);
+				}
+				catch (SecurityUtilityException)
+				{
+					// Ignore
+				}
+			}
+			return CipherUtilities.GetCipher(encryptionOid);
+		}
+
+		internal IWrapper CreateWrapper(
+			string encryptionOid)
+		{
+			try
+			{
+				return WrapperUtilities.GetWrapper(encryptionOid);
+			}
+			catch (SecurityUtilityException)
+			{
+				return WrapperUtilities.GetWrapper(GetAsymmetricEncryptionAlgName(encryptionOid));
+			}
+		}
+
+		internal string GetRfc3211WrapperName(
+			string oid)
+		{
+			if (oid == null)
+				throw new ArgumentNullException("oid");
+
+			string alg = (string) BaseCipherNames[oid];
+
+			if (alg == null)
+				throw new ArgumentException("no name for " + oid, "oid");
+
+			return alg + "RFC3211Wrap";
+		}
+
+		internal int GetKeySize(
+			string oid)
+		{
+			if (!KeySizes.Contains(oid))
+			{
+				throw new ArgumentException("no keysize for " + oid, "oid");
+			}
+
+			return (int) KeySizes[oid];
+		}
+
+		internal static RecipientInformationStore BuildRecipientInformationStore(
+			Asn1Set recipientInfos, CmsSecureReadable secureReadable)
+		{
+			IList infos = Platform.CreateArrayList();
+			for (int i = 0; i != recipientInfos.Count; i++)
+			{
+				RecipientInfo info = RecipientInfo.GetInstance(recipientInfos[i]);
+
+				ReadRecipientInfo(infos, info, secureReadable);
+			}
+			return new RecipientInformationStore(infos);
+		}
+
+		private static void ReadRecipientInfo(
+			IList infos, RecipientInfo info, CmsSecureReadable secureReadable)
+		{
+			Asn1Encodable recipInfo = info.Info;
+			if (recipInfo is KeyTransRecipientInfo)
+			{
+				infos.Add(new KeyTransRecipientInformation((KeyTransRecipientInfo)recipInfo, secureReadable));
+			}
+			else if (recipInfo is KekRecipientInfo)
+			{
+				infos.Add(new KekRecipientInformation((KekRecipientInfo)recipInfo, secureReadable));
+			}
+			else if (recipInfo is KeyAgreeRecipientInfo)
+			{
+				KeyAgreeRecipientInformation.ReadRecipientInfo(infos, (KeyAgreeRecipientInfo)recipInfo, secureReadable);
+			}
+			else if (recipInfo is PasswordRecipientInfo)
+			{
+				infos.Add(new PasswordRecipientInformation((PasswordRecipientInfo)recipInfo, secureReadable));
+			}
+		}
+
+		internal class CmsAuthenticatedSecureReadable : CmsSecureReadable
+		{
+			private AlgorithmIdentifier algorithm;
+			private IMac mac;
+			private CmsReadable readable;
+
+			internal CmsAuthenticatedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
+			{
+				this.algorithm = algorithm;
+				this.readable = readable;
+			}
+
+			public AlgorithmIdentifier Algorithm
+			{
+				get { return this.algorithm; }
+			}
+
+			public object CryptoObject
+			{
+				get { return this.mac; }
+			}
+
+			public CmsReadable GetReadable(KeyParameter sKey)
+			{
+				string macAlg = this.algorithm.ObjectID.Id;
+//				Asn1Object sParams = this.algorithm.Parameters.ToAsn1Object();
+
+				try
+				{
+					this.mac = MacUtilities.GetMac(macAlg);
+
+					// FIXME Support for MAC algorithm parameters similar to cipher parameters
+//						ASN1Object sParams = (ASN1Object)macAlg.getParameters();
+//
+//						if (sParams != null && !(sParams instanceof ASN1Null))
+//						{
+//							AlgorithmParameters params = CMSEnvelopedHelper.INSTANCE.createAlgorithmParameters(macAlg.getObjectId().getId(), provider);
+//
+//							params.init(sParams.getEncoded(), "ASN.1");
+//
+//							mac.init(sKey, params.getParameterSpec(IvParameterSpec.class));
+//						}
+//						else
+					{
+						mac.Init(sKey);
+					}
+
+//						Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
+//
+//						ICipherParameters cipherParameters = sKey;
+//
+//						if (asn1Params != null && !(asn1Params is Asn1Null))
+//						{
+//							cipherParameters = ParameterUtilities.GetCipherParameters(
+//							macAlg.ObjectID, cipherParameters, asn1Params);
+//						}
+//						else
+//						{
+//							string alg = macAlg.ObjectID.Id;
+//							if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
+//								|| alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
+//								|| alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
+//							{
+//								cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
+//							}
+//						}
+//
+//						mac.Init(cipherParameters);
+				}
+				catch (SecurityUtilityException e)
+				{
+					throw new CmsException("couldn't create cipher.", e);
+				}
+				catch (InvalidKeyException e)
+				{
+					throw new CmsException("key invalid in message.", e);
+				}
+				catch (IOException e)
+				{
+					throw new CmsException("error decoding algorithm parameters.", e);
+				}
+
+				try
+				{
+					return new CmsProcessableInputStream(
+						new TeeInputStream(
+							readable.GetInputStream(),
+							new MacOutputStream(this.mac)));
+				}
+				catch (IOException e)
+				{
+					throw new CmsException("error reading content.", e);
+				}
+			}
+		}
+
+		internal class CmsEnvelopedSecureReadable : CmsSecureReadable
+		{
+			private AlgorithmIdentifier algorithm;
+			private IBufferedCipher cipher;
+			private CmsReadable readable;
+
+			internal CmsEnvelopedSecureReadable(AlgorithmIdentifier algorithm, CmsReadable readable)
+			{
+				this.algorithm = algorithm;
+				this.readable = readable;
+			}
+
+			public AlgorithmIdentifier Algorithm
+			{
+				get { return this.algorithm; }
+			}
+
+			public object CryptoObject
+			{
+				get { return this.cipher; }
+			}
+
+			public CmsReadable GetReadable(KeyParameter sKey)
+			{
+				try
+				{
+					this.cipher =  CipherUtilities.GetCipher(this.algorithm.ObjectID);
+
+					Asn1Encodable asn1Enc = this.algorithm.Parameters;
+					Asn1Object asn1Params = asn1Enc == null ? null : asn1Enc.ToAsn1Object();
+
+					ICipherParameters cipherParameters = sKey;
+
+					if (asn1Params != null && !(asn1Params is Asn1Null))
+					{
+						cipherParameters = ParameterUtilities.GetCipherParameters(
+							this.algorithm.ObjectID, cipherParameters, asn1Params);
+					}
+					else
+					{
+						string alg = this.algorithm.ObjectID.Id;
+						if (alg.Equals(CmsEnvelopedDataGenerator.DesEde3Cbc)
+							|| alg.Equals(CmsEnvelopedDataGenerator.IdeaCbc)
+							|| alg.Equals(CmsEnvelopedDataGenerator.Cast5Cbc))
+						{
+							cipherParameters = new ParametersWithIV(cipherParameters, new byte[8]);
+						}
+					}
+
+					cipher.Init(false, cipherParameters);
+				}
+				catch (SecurityUtilityException e)
+				{
+					throw new CmsException("couldn't create cipher.", e);
+				}
+				catch (InvalidKeyException e)
+				{
+					throw new CmsException("key invalid in message.", e);
+				}
+				catch (IOException e)
+				{
+					throw new CmsException("error decoding algorithm parameters.", e);
+				}
+
+				try
+				{
+					return new CmsProcessableInputStream(
+						new CipherStream(readable.GetInputStream(), cipher, null));
+				}
+				catch (IOException e)
+				{
+					throw new CmsException("error reading content.", e);
+				}
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSException.cs b/BouncyCastle.AxCrypt/src/cms/CMSException.cs
new file mode 100644
index 0000000..5a6e335
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Cms
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CmsException
+		: Exception
+	{
+		public CmsException()
+		{
+		}
+
+		public CmsException(
+			string msg)
+			: base(msg)
+		{
+		}
+
+		public CmsException(
+			string		msg,
+			Exception	e)
+			: base(msg, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSPBEKey.cs b/BouncyCastle.AxCrypt/src/cms/CMSPBEKey.cs
new file mode 100644
index 0000000..cb1e54c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSPBEKey.cs
@@ -0,0 +1,109 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+//import javax.crypto.interfaces.PBEKey;
+
+namespace Org.BouncyCastle.Cms
+{
+	public abstract class CmsPbeKey
+		// TODO Create an equivalent interface somewhere?
+		//	: PBEKey
+		: ICipherParameters
+	{
+		internal readonly char[]	password;
+		internal readonly byte[]	salt;
+		internal readonly int		iterationCount;
+
+		[Obsolete("Use version taking 'char[]' instead")]
+		public CmsPbeKey(
+			string	password,
+			byte[]	salt,
+			int		iterationCount)
+			: this(password.ToCharArray(), salt, iterationCount)
+		{
+		}
+
+		[Obsolete("Use version taking 'char[]' instead")]
+		public CmsPbeKey(
+			string				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+			: this(password.ToCharArray(), keyDerivationAlgorithm)
+		{
+		}
+		
+		public CmsPbeKey(
+			char[]	password,
+			byte[]	salt,
+			int		iterationCount)
+		{
+			this.password = (char[])password.Clone();
+			this.salt = Arrays.Clone(salt);
+			this.iterationCount = iterationCount;
+		}
+
+		public CmsPbeKey(
+			char[]				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+		{
+			if (!keyDerivationAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdPbkdf2))
+				throw new ArgumentException("Unsupported key derivation algorithm: "
+					+ keyDerivationAlgorithm.ObjectID);
+
+			Pbkdf2Params kdfParams = Pbkdf2Params.GetInstance(
+				keyDerivationAlgorithm.Parameters.ToAsn1Object());
+
+			this.password = (char[])password.Clone();
+			this.salt = kdfParams.GetSalt();
+			this.iterationCount = kdfParams.IterationCount.IntValue;
+		}
+
+		~CmsPbeKey()
+		{
+			Array.Clear(this.password, 0, this.password.Length);
+		}
+
+		[Obsolete("Will be removed")]
+		public string Password
+		{
+			get { return new string(password); }
+		}
+
+		public byte[] Salt
+		{
+			get { return Arrays.Clone(salt); }
+		}
+
+		[Obsolete("Use 'Salt' property instead")]
+		public byte[] GetSalt()
+		{
+			return Salt;
+		}
+
+		public int IterationCount
+		{
+			get { return iterationCount; }
+		}
+
+		public string Algorithm
+		{
+			get { return "PKCS5S2"; }
+		}
+
+		public string Format
+		{
+			get { return "RAW"; }
+		}
+
+		public byte[] GetEncoded()
+		{
+			return null;
+		}
+
+		internal abstract KeyParameter GetEncoded(string algorithmOid);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSProcessable.cs b/BouncyCastle.AxCrypt/src/cms/CMSProcessable.cs
new file mode 100644
index 0000000..41018d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSProcessable.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	public interface CmsProcessable
+	{
+		/// <summary>
+		/// Generic routine to copy out the data we want processed.
+		/// </summary>
+		/// <remarks>
+		/// This routine may be called multiple times.
+		/// </remarks>
+		void Write(Stream outStream);
+
+		[Obsolete]
+		object GetContent();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSProcessableByteArray.cs b/BouncyCastle.AxCrypt/src/cms/CMSProcessableByteArray.cs
new file mode 100644
index 0000000..4bee4f8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSProcessableByteArray.cs
@@ -0,0 +1,36 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* a holding class for a byte array of data to be processed.
+	*/
+	public class CmsProcessableByteArray
+		: CmsProcessable, CmsReadable
+	{
+		private readonly byte[] bytes;
+
+		public CmsProcessableByteArray(
+			byte[] bytes)
+		{
+			this.bytes = bytes;
+		}
+
+		public Stream GetInputStream()
+		{
+			return new MemoryStream(bytes, false);
+		}
+
+		public virtual void Write(Stream zOut)
+		{
+			zOut.Write(bytes, 0, bytes.Length);
+		}
+
+		/// <returns>A clone of the byte array</returns>
+		public virtual object GetContent()
+		{
+			return bytes.Clone();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSProcessableFile.cs b/BouncyCastle.AxCrypt/src/cms/CMSProcessableFile.cs
new file mode 100644
index 0000000..3a3229b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSProcessableFile.cs
@@ -0,0 +1,56 @@
+#if !PCL
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* a holding class for a file of data to be processed.
+	*/
+	public class CmsProcessableFile
+		: CmsProcessable, CmsReadable
+	{
+		private const int DefaultBufSize = 32 * 1024;
+
+		private readonly FileInfo	_file;
+		private readonly int		_bufSize;
+
+		public CmsProcessableFile(
+			FileInfo file)
+			: this(file, DefaultBufSize)
+		{
+		}
+
+		public CmsProcessableFile(
+			FileInfo	file,
+			int			bufSize)
+		{
+			_file = file;
+			_bufSize = bufSize;
+		}
+
+		public virtual Stream GetInputStream()
+		{
+			return new FileStream(
+				_file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, _bufSize);
+		}
+
+		public virtual void Write(
+			Stream zOut)
+		{
+			Stream inStr = GetInputStream();
+			Streams.PipeAll(inStr, zOut);
+			inStr.Dispose();
+		}
+
+		/// <returns>The file handle</returns>
+		[Obsolete]
+		public virtual object GetContent()
+		{
+			return _file;
+		}
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSProcessableInputStream.cs b/BouncyCastle.AxCrypt/src/cms/CMSProcessableInputStream.cs
new file mode 100644
index 0000000..0af6cbf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSProcessableInputStream.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class CmsProcessableInputStream
+		: CmsProcessable, CmsReadable
+	{
+		private Stream input;
+		private bool used = false;
+
+		public CmsProcessableInputStream(
+			Stream input)
+		{
+			this.input = input;
+		}
+
+		public Stream GetInputStream()
+		{
+			CheckSingleUsage();
+
+			return input;
+		}
+
+		public void Write(Stream output)
+		{
+			CheckSingleUsage();
+
+			Streams.PipeAll(input, output);
+            input.Dispose();
+		}
+
+		[Obsolete]
+		public object GetContent()
+		{
+			return GetInputStream();
+		}
+
+		private void CheckSingleUsage()
+		{
+			lock (this)
+			{
+				if (used)
+					throw new InvalidOperationException("CmsProcessableInputStream can only be used once");
+
+				used = true;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSReadable.cs b/BouncyCastle.AxCrypt/src/cms/CMSReadable.cs
new file mode 100644
index 0000000..9507b92
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSReadable.cs
@@ -0,0 +1,10 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal interface CmsReadable
+	{
+		Stream GetInputStream();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSecureReadable.cs b/BouncyCastle.AxCrypt/src/cms/CMSSecureReadable.cs
new file mode 100644
index 0000000..5ceac24
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSecureReadable.cs
@@ -0,0 +1,14 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal interface CmsSecureReadable
+	{
+		AlgorithmIdentifier Algorithm { get; }
+		object CryptoObject { get; }
+		CmsReadable GetReadable(KeyParameter key);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedData.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedData.cs
new file mode 100644
index 0000000..81c87a4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedData.cs
@@ -0,0 +1,425 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* general class for handling a pkcs7-signature message.
+	*
+	* A simple example of usage - note, in the example below the validity of
+	* the certificate isn't verified, just the fact that one of the certs
+	* matches the given signer...
+	*
+	* <pre>
+	*  IX509Store              certs = s.GetCertificates();
+	*  SignerInformationStore  signers = s.GetSignerInfos();
+	*
+	*  foreach (SignerInformation signer in signers.GetSigners())
+	*  {
+	*      ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+	*      X509Certificate cert = (X509Certificate) certList[0];
+	*
+	*      if (signer.Verify(cert.GetPublicKey()))
+	*      {
+	*          verified++;
+	*      }
+	*  }
+	* </pre>
+	*/
+	public class CmsSignedData
+	{
+		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+		private readonly CmsProcessable	signedContent;
+		private SignedData				signedData;
+		private ContentInfo				contentInfo;
+		private SignerInformationStore	signerInfoStore;
+		private IX509Store				attrCertStore;
+		private IX509Store				certificateStore;
+		private IX509Store				crlStore;
+		private IDictionary				hashes;
+
+		private CmsSignedData(
+			CmsSignedData c)
+		{
+			this.signedData = c.signedData;
+			this.contentInfo = c.contentInfo;
+			this.signedContent = c.signedContent;
+			this.signerInfoStore = c.signerInfoStore;
+		}
+
+		public CmsSignedData(
+			byte[] sigBlock)
+			: this(CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
+		{
+		}
+
+		public CmsSignedData(
+			CmsProcessable	signedContent,
+			byte[]			sigBlock)
+			: this(signedContent, CmsUtilities.ReadContentInfo(new MemoryStream(sigBlock, false)))
+		{
+		}
+
+		/**
+		 * Content with detached signature, digests precomputed
+		 *
+		 * @param hashes a map of precomputed digests for content indexed by name of hash.
+		 * @param sigBlock the signature object.
+		 */
+		public CmsSignedData(
+			IDictionary	hashes,
+			byte[]		sigBlock)
+			: this(hashes, CmsUtilities.ReadContentInfo(sigBlock))
+		{
+		}
+
+		/**
+		* base constructor - content with detached signature.
+		*
+		* @param signedContent the content that was signed.
+		* @param sigData the signature object.
+		*/
+		public CmsSignedData(
+			CmsProcessable	signedContent,
+			Stream			sigData)
+			: this(signedContent, CmsUtilities.ReadContentInfo(sigData))
+		{
+		}
+
+		/**
+		* base constructor - with encapsulated content
+		*/
+		public CmsSignedData(
+			Stream sigData)
+			: this(CmsUtilities.ReadContentInfo(sigData))
+		{
+		}
+
+		public CmsSignedData(
+			CmsProcessable  signedContent,
+			ContentInfo     sigData)
+		{
+			this.signedContent = signedContent;
+			this.contentInfo = sigData;
+			this.signedData = SignedData.GetInstance(contentInfo.Content);
+		}
+
+		public CmsSignedData(
+			IDictionary	hashes,
+			ContentInfo	sigData)
+		{
+			this.hashes = hashes;
+			this.contentInfo = sigData;
+			this.signedData = SignedData.GetInstance(contentInfo.Content);
+		}
+
+		public CmsSignedData(
+			ContentInfo sigData)
+		{
+			this.contentInfo = sigData;
+			this.signedData = SignedData.GetInstance(contentInfo.Content);
+
+			//
+			// this can happen if the signed message is sent simply to send a
+			// certificate chain.
+			//
+			if (signedData.EncapContentInfo.Content != null)
+			{
+				this.signedContent = new CmsProcessableByteArray(
+					((Asn1OctetString)(signedData.EncapContentInfo.Content)).GetOctets());
+			}
+//			else
+//			{
+//				this.signedContent = null;
+//			}
+		}
+
+		/// <summary>Return the version number for this object.</summary>
+		public int Version
+		{
+			get { return signedData.Version.Value.IntValue; }
+		}
+
+		/**
+		* return the collection of signers that are associated with the
+		* signatures for the message.
+		*/
+		public SignerInformationStore GetSignerInfos()
+		{
+			if (signerInfoStore == null)
+			{
+                IList signerInfos = Platform.CreateArrayList();
+				Asn1Set s = signedData.SignerInfos;
+
+				foreach (object obj in s)
+				{
+					SignerInfo info = SignerInfo.GetInstance(obj);
+					DerObjectIdentifier contentType = signedData.EncapContentInfo.ContentType;
+
+					if (hashes == null)
+					{
+						signerInfos.Add(new SignerInformation(info, contentType, signedContent, null));
+					}
+					else
+					{
+						byte[] hash = (byte[]) hashes[info.DigestAlgorithm.ObjectID.Id];
+
+						signerInfos.Add(new SignerInformation(info, contentType, null, new BaseDigestCalculator(hash)));
+					}
+				}
+
+				signerInfoStore = new SignerInformationStore(signerInfos);
+			}
+
+			return signerInfoStore;
+		}
+
+		/**
+		 * return a X509Store containing the attribute certificates, if any, contained
+		 * in this message.
+		 *
+		 * @param type type of store to create
+		 * @return a store of attribute certificates
+		 * @exception NoSuchStoreException if the store type isn't available.
+		 * @exception CmsException if a general exception prevents creation of the X509Store
+		 */
+		public IX509Store GetAttributeCertificates(
+			string type)
+		{
+			if (attrCertStore == null)
+			{
+				attrCertStore = Helper.CreateAttributeStore(type, signedData.Certificates);
+			}
+
+			return attrCertStore;
+		}
+
+		/**
+		 * return a X509Store containing the public key certificates, if any, contained
+		 * in this message.
+		 *
+		 * @param type type of store to create
+		 * @return a store of public key certificates
+		 * @exception NoSuchStoreException if the store type isn't available.
+		 * @exception CmsException if a general exception prevents creation of the X509Store
+		 */
+		public IX509Store GetCertificates(
+			string type)
+		{
+			if (certificateStore == null)
+			{
+				certificateStore = Helper.CreateCertificateStore(type, signedData.Certificates);
+			}
+
+			return certificateStore;
+		}
+
+		/**
+		* return a X509Store containing CRLs, if any, contained
+		* in this message.
+		*
+		* @param type type of store to create
+		* @return a store of CRLs
+		* @exception NoSuchStoreException if the store type isn't available.
+		* @exception CmsException if a general exception prevents creation of the X509Store
+		*/
+		public IX509Store GetCrls(
+			string type)
+		{
+			if (crlStore == null)
+			{
+				crlStore = Helper.CreateCrlStore(type, signedData.CRLs);
+			}
+
+			return crlStore;
+		}
+
+		[Obsolete("Use 'SignedContentType' property instead.")]
+		public string SignedContentTypeOid
+		{
+			get { return signedData.EncapContentInfo.ContentType.Id; }
+		}
+
+		/// <summary>
+		/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+		/// content info structure carried in the signed data.
+		/// </summary>
+		public DerObjectIdentifier SignedContentType
+		{
+			get { return signedData.EncapContentInfo.ContentType; }
+		}
+
+		public CmsProcessable SignedContent
+		{
+			get { return signedContent; }
+		}
+
+		/**
+		 * return the ContentInfo
+		 */
+		public ContentInfo ContentInfo
+		{
+			get { return contentInfo; }
+		}
+
+		/**
+		* return the ASN.1 encoded representation of this object.
+		*/
+		public byte[] GetEncoded()
+		{
+			return contentInfo.GetEncoded();
+		}
+
+		/**
+		* Replace the signerinformation store associated with this
+		* CmsSignedData object with the new one passed in. You would
+		* probably only want to do this if you wanted to change the unsigned
+		* attributes associated with a signer, or perhaps delete one.
+		*
+		* @param signedData the signed data object to be used as a base.
+		* @param signerInformationStore the new signer information store to use.
+		* @return a new signed data object.
+		*/
+		public static CmsSignedData ReplaceSigners(
+			CmsSignedData           signedData,
+			SignerInformationStore  signerInformationStore)
+		{
+			//
+			// copy
+			//
+			CmsSignedData cms = new CmsSignedData(signedData);
+
+			//
+			// replace the store
+			//
+			cms.signerInfoStore = signerInformationStore;
+
+			//
+			// replace the signers in the SignedData object
+			//
+			Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
+			Asn1EncodableVector vec = new Asn1EncodableVector();
+
+			foreach (SignerInformation signer in signerInformationStore.GetSigners())
+			{
+				digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
+				vec.Add(signer.ToSignerInfo());
+			}
+
+			Asn1Set digests = new DerSet(digestAlgs);
+			Asn1Set signers = new DerSet(vec);
+			Asn1Sequence sD = (Asn1Sequence)signedData.signedData.ToAsn1Object();
+
+			//
+			// signers are the last item in the sequence.
+			//
+			vec = new Asn1EncodableVector(
+				sD[0], // version
+				digests);
+
+			for (int i = 2; i != sD.Count - 1; i++)
+			{
+				vec.Add(sD[i]);
+			}
+
+			vec.Add(signers);
+
+			cms.signedData = SignedData.GetInstance(new BerSequence(vec));
+
+			//
+			// replace the contentInfo with the new one
+			//
+			cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
+
+			return cms;
+		}
+
+		/**
+		* Replace the certificate and CRL information associated with this
+		* CmsSignedData object with the new one passed in.
+		*
+		* @param signedData the signed data object to be used as a base.
+		* @param x509Certs the new certificates to be used.
+		* @param x509Crls the new CRLs to be used.
+		* @return a new signed data object.
+		* @exception CmsException if there is an error processing the stores
+		*/
+		public static CmsSignedData ReplaceCertificatesAndCrls(
+			CmsSignedData	signedData,
+			IX509Store		x509Certs,
+			IX509Store		x509Crls,
+			IX509Store		x509AttrCerts)
+		{
+			if (x509AttrCerts != null)
+				throw Platform.CreateNotImplementedException("Currently can't replace attribute certificates");
+
+			//
+			// copy
+			//
+			CmsSignedData cms = new CmsSignedData(signedData);
+
+			//
+			// replace the certs and crls in the SignedData object
+			//
+			Asn1Set certs = null;
+			try
+			{
+				Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList(
+					CmsUtilities.GetCertificatesFromStore(x509Certs));
+
+				if (asn1Set.Count != 0)
+				{
+					certs = asn1Set;
+				}
+			}
+			catch (X509StoreException e)
+			{
+				throw new CmsException("error getting certificates from store", e);
+			}
+
+			Asn1Set crls = null;
+			try
+			{
+				Asn1Set asn1Set = CmsUtilities.CreateBerSetFromList(
+					CmsUtilities.GetCrlsFromStore(x509Crls));
+
+				if (asn1Set.Count != 0)
+				{
+					crls = asn1Set;
+				}
+			}
+			catch (X509StoreException e)
+			{
+				throw new CmsException("error getting CRLs from store", e);
+			}
+
+			//
+			// replace the CMS structure.
+			//
+			SignedData old = signedData.signedData;
+			cms.signedData = new SignedData(
+				old.DigestAlgorithms,
+				old.EncapContentInfo,
+				certs,
+				crls,
+				old.SignerInfos);
+
+			//
+			// replace the contentInfo with the new one
+			//
+			cms.contentInfo = new ContentInfo(cms.contentInfo.ContentType, cms.signedData);
+
+			return cms;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedDataGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataGenerator.cs
new file mode 100644
index 0000000..6d8dd40
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataGenerator.cs
@@ -0,0 +1,551 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+     * general class for generating a pkcs7-signature message.
+     * <p>
+     * A simple example of usage.
+     *
+     * <pre>
+     *      IX509Store certs...
+     *      IX509Store crls...
+     *      CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+     *
+     *      gen.AddSigner(privKey, cert, CmsSignedGenerator.DigestSha1);
+     *      gen.AddCertificates(certs);
+     *      gen.AddCrls(crls);
+     *
+     *      CmsSignedData data = gen.Generate(content);
+     * </pre>
+	 * </p>
+     */
+    public class CmsSignedDataGenerator
+        : CmsSignedGenerator
+    {
+		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+		private readonly IList signerInfs = Platform.CreateArrayList();
+
+		private class SignerInf
+        {
+            private readonly CmsSignedGenerator outer;
+
+			private readonly AsymmetricKeyParameter		key;
+			private readonly SignerIdentifier			signerIdentifier;
+			private readonly string						digestOID;
+			private readonly string						encOID;
+			private readonly CmsAttributeTableGenerator	sAttr;
+			private readonly CmsAttributeTableGenerator	unsAttr;
+			//private readonly Asn1.Cms.AttributeTable	baseSignedTable;
+
+			internal SignerInf(
+                CmsSignedGenerator			outer,
+	            AsymmetricKeyParameter		key,
+	            SignerIdentifier			signerIdentifier,
+	            string						digestOID,
+	            string						encOID,
+	            CmsAttributeTableGenerator	sAttr,
+	            CmsAttributeTableGenerator	unsAttr,
+	            Asn1.Cms.AttributeTable		baseSignedTable)
+	        {
+                this.outer = outer;
+                this.key = key;
+                this.signerIdentifier = signerIdentifier;
+                this.digestOID = digestOID;
+                this.encOID = encOID;
+	            this.sAttr = sAttr;
+	            this.unsAttr = unsAttr;
+	            //this.baseSignedTable = baseSignedTable;
+            }
+
+			internal AlgorithmIdentifier DigestAlgorithmID
+			{
+				get { return new AlgorithmIdentifier(new DerObjectIdentifier(digestOID), DerNull.Instance); }
+			}
+
+			internal CmsAttributeTableGenerator SignedAttributes
+            {
+				get { return sAttr; }
+            }
+
+            internal CmsAttributeTableGenerator UnsignedAttributes
+            {
+				get { return unsAttr; }
+            }
+
+			internal SignerInfo ToSignerInfo(
+                DerObjectIdentifier	contentType,
+                CmsProcessable		content,
+				SecureRandom		random)
+            {
+                AlgorithmIdentifier digAlgId = DigestAlgorithmID;
+				string digestName = Helper.GetDigestAlgName(digestOID);
+				IDigest dig = Helper.GetDigestInstance(digestName);
+
+				string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(encOID);
+				ISigner sig = Helper.GetSignatureInstance(signatureName);
+
+				// TODO Optimise the case where more than one signer with same digest
+				if (content != null)
+                {
+                    content.Write(new DigOutputStream(dig));
+				}
+
+				byte[] hash = DigestUtilities.DoFinal(dig);
+				outer._digests.Add(digestOID, hash.Clone());
+
+				sig.Init(true, new ParametersWithRandom(key, random));
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
+				Stream sigStr = new SigOutputStream(sig);
+#else
+				Stream sigStr = new BufferedStream(new SigOutputStream(sig));
+#endif
+
+				Asn1Set signedAttr = null;
+				if (sAttr != null)
+				{
+					IDictionary parameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+
+//					Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
+					Asn1.Cms.AttributeTable signed = sAttr.GetAttributes(parameters);
+
+                    if (contentType == null) //counter signature
+                    {
+                        if (signed != null && signed[CmsAttributes.ContentType] != null)
+                        {
+                            IDictionary tmpSigned = signed.ToDictionary();
+                            tmpSigned.Remove(CmsAttributes.ContentType);
+                            signed = new Asn1.Cms.AttributeTable(tmpSigned);
+                        }
+                    }
+
+					// TODO Validate proposed signed attributes
+
+					signedAttr = outer.GetAttributeSet(signed);
+
+					// sig must be composed from the DER encoding.
+					new DerOutputStream(sigStr).WriteObject(signedAttr);
+				}
+                else if (content != null)
+                {
+					// TODO Use raw signature of the hash value instead
+					content.Write(sigStr);
+                }
+
+                sigStr.Dispose();
+				byte[] sigBytes = sig.GenerateSignature();
+
+				Asn1Set unsignedAttr = null;
+				if (unsAttr != null)
+				{
+					IDictionary baseParameters = outer.GetBaseParameters(contentType, digAlgId, hash);
+					baseParameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
+
+//					Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(Collections.unmodifiableMap(baseParameters));
+					Asn1.Cms.AttributeTable unsigned = unsAttr.GetAttributes(baseParameters);
+
+					// TODO Validate proposed unsigned attributes
+
+					unsignedAttr = outer.GetAttributeSet(unsigned);
+				}
+
+				// TODO[RSAPSS] Need the ability to specify non-default parameters
+				Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
+				AlgorithmIdentifier encAlgId = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+					new DerObjectIdentifier(encOID), sigX509Parameters);
+				
+                return new SignerInfo(signerIdentifier, digAlgId,
+                    signedAttr, encAlgId, new DerOctetString(sigBytes), unsignedAttr);
+            }
+        }
+
+		public CmsSignedDataGenerator()
+        {
+        }
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		public CmsSignedDataGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+
+		/**
+        * add a signer - no attributes other than the default ones will be
+        * provided here.
+		*
+		* @param key signing key to use
+		* @param cert certificate containing corresponding public key
+		* @param digestOID digest algorithm OID
+        */
+        public void AddSigner(
+            AsymmetricKeyParameter	privateKey,
+            X509Certificate			cert,
+            string					digestOID)
+        {
+        	AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID);
+		}
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+		 * provided here.
+		 *
+		 * @param key signing key to use
+		 * @param cert certificate containing corresponding public key
+		 * @param encryptionOID digest encryption algorithm OID
+		 * @param digestOID digest algorithm OID
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate			cert,
+			string					encryptionOID,
+			string					digestOID)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID,
+				new DefaultSignedAttributeTableGenerator(), null, null);
+		}
+
+	    /**
+	     * add a signer - no attributes other than the default ones will be
+	     * provided here.
+	     */
+	    public void AddSigner(
+            AsymmetricKeyParameter	privateKey,
+	        byte[]					subjectKeyID,
+            string					digestOID)
+	    {
+			AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID);
+	    }
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm to use - no attributes other than the default ones will be
+		 * provided here.
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					encryptionOID,
+			string					digestOID)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
+				new DefaultSignedAttributeTableGenerator(), null, null);
+		}
+
+        /**
+        * add a signer with extra signed/unsigned attributes.
+		*
+		* @param key signing key to use
+		* @param cert certificate containing corresponding public key
+		* @param digestOID digest algorithm OID
+		* @param signedAttr table of attributes to be included in signature
+		* @param unsignedAttr table of attributes to be included as unsigned
+        */
+        public void AddSigner(
+            AsymmetricKeyParameter	privateKey,
+            X509Certificate			cert,
+            string					digestOID,
+            Asn1.Cms.AttributeTable	signedAttr,
+            Asn1.Cms.AttributeTable	unsignedAttr)
+        {
+			AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+				signedAttr, unsignedAttr);
+		}
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+		 *
+		 * @param key signing key to use
+		 * @param cert certificate containing corresponding public key
+		 * @param encryptionOID digest encryption algorithm OID
+		 * @param digestOID digest algorithm OID
+		 * @param signedAttr table of attributes to be included in signature
+		 * @param unsignedAttr table of attributes to be included as unsigned
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate			cert,
+			string					encryptionOID,
+			string					digestOID,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID,
+				new DefaultSignedAttributeTableGenerator(signedAttr),
+				new SimpleAttributeTableGenerator(unsignedAttr),
+				signedAttr);
+		}
+
+	    /**
+	     * add a signer with extra signed/unsigned attributes.
+		 *
+		 * @param key signing key to use
+		 * @param subjectKeyID subjectKeyID of corresponding public key
+		 * @param digestOID digest algorithm OID
+		 * @param signedAttr table of attributes to be included in signature
+		 * @param unsignedAttr table of attributes to be included as unsigned
+	     */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					digestOID,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+		{
+			AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+				signedAttr, unsignedAttr); 
+		}
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes.
+		 *
+		 * @param key signing key to use
+		 * @param subjectKeyID subjectKeyID of corresponding public key
+		 * @param encryptionOID digest encryption algorithm OID
+		 * @param digestOID digest algorithm OID
+		 * @param signedAttr table of attributes to be included in signature
+		 * @param unsignedAttr table of attributes to be included as unsigned
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					encryptionOID,
+			string					digestOID,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
+				new DefaultSignedAttributeTableGenerator(signedAttr),
+				new SimpleAttributeTableGenerator(unsignedAttr),
+				signedAttr);
+		}
+
+		/**
+		 * add a signer with extra signed/unsigned attributes based on generators.
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			X509Certificate				cert,
+			string						digestOID,
+			CmsAttributeTableGenerator	signedAttrGen,
+			CmsAttributeTableGenerator	unsignedAttrGen)
+		{
+			AddSigner(privateKey, cert, GetEncOid(privateKey, digestOID), digestOID,
+				signedAttrGen, unsignedAttrGen);
+		}
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			X509Certificate				cert,
+			string						encryptionOID,
+			string						digestOID,
+			CmsAttributeTableGenerator	signedAttrGen,
+			CmsAttributeTableGenerator	unsignedAttrGen)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOID, digestOID, signedAttrGen,
+				unsignedAttrGen, null);
+		}
+
+	    /**
+	     * add a signer with extra signed/unsigned attributes based on generators.
+	     */
+	    public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+	        byte[]						subjectKeyID,
+	        string						digestOID,
+	        CmsAttributeTableGenerator	signedAttrGen,
+	        CmsAttributeTableGenerator	unsignedAttrGen)
+	    {
+			AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOID), digestOID,
+				signedAttrGen, unsignedAttrGen);
+	    }
+
+		/**
+		 * add a signer, including digest encryption algorithm, with extra signed/unsigned attributes based on generators.
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			byte[]						subjectKeyID,
+			string						encryptionOID,
+			string						digestOID,
+			CmsAttributeTableGenerator	signedAttrGen,
+			CmsAttributeTableGenerator	unsignedAttrGen)
+		{
+			doAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOID, digestOID,
+				signedAttrGen, unsignedAttrGen, null);
+		}
+
+		private void doAddSigner(
+			AsymmetricKeyParameter		privateKey,
+			SignerIdentifier            signerIdentifier,
+			string                      encryptionOID,
+			string                      digestOID,
+			CmsAttributeTableGenerator  signedAttrGen,
+			CmsAttributeTableGenerator  unsignedAttrGen,
+			Asn1.Cms.AttributeTable		baseSignedTable)
+		{
+			signerInfs.Add(new SignerInf(this, privateKey, signerIdentifier, digestOID, encryptionOID,
+				signedAttrGen, unsignedAttrGen, baseSignedTable));
+		}
+
+		/**
+        * generate a signed object that for a CMS Signed Data object
+        */
+        public CmsSignedData Generate(
+            CmsProcessable content)
+        {
+            return Generate(content, false);
+        }
+
+        /**
+        * generate a signed object that for a CMS Signed Data
+        * object  - if encapsulate is true a copy
+        * of the message will be included in the signature. The content type
+        * is set according to the OID represented by the string signedContentType.
+        */
+        public CmsSignedData Generate(
+            string			signedContentType,
+			// FIXME Avoid accessing more than once to support CmsProcessableInputStream
+            CmsProcessable	content,
+            bool			encapsulate)
+        {
+            Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
+            Asn1EncodableVector signerInfos = new Asn1EncodableVector();
+
+			_digests.Clear(); // clear the current preserved digest state
+
+			//
+            // add the precalculated SignerInfo objects.
+            //
+            foreach (SignerInformation signer in _signers)
+            {
+				digestAlgs.Add(Helper.FixAlgID(signer.DigestAlgorithmID));
+
+				// TODO Verify the content type and calculated digest match the precalculated SignerInfo
+				signerInfos.Add(signer.ToSignerInfo());
+            }
+
+			//
+            // add the SignerInfo objects
+            //
+            bool isCounterSignature = (signedContentType == null);
+
+            DerObjectIdentifier contentTypeOid = isCounterSignature
+                ?   null
+				:	new DerObjectIdentifier(signedContentType);
+
+            foreach (SignerInf signer in signerInfs)
+            {
+				try
+                {
+					digestAlgs.Add(signer.DigestAlgorithmID);
+                    signerInfos.Add(signer.ToSignerInfo(contentTypeOid, content, rand));
+				}
+                catch (IOException e)
+                {
+                    throw new CmsException("encoding error.", e);
+                }
+                catch (InvalidKeyException e)
+                {
+                    throw new CmsException("key inappropriate for signature.", e);
+                }
+                catch (SignatureException e)
+                {
+                    throw new CmsException("error creating signature.", e);
+                }
+                catch (CertificateEncodingException e)
+                {
+                    throw new CmsException("error creating sid.", e);
+                }
+            }
+
+			Asn1Set certificates = null;
+
+			if (_certs.Count != 0)
+			{
+				certificates = CmsUtilities.CreateBerSetFromList(_certs);
+			}
+
+			Asn1Set certrevlist = null;
+
+			if (_crls.Count != 0)
+			{
+				certrevlist = CmsUtilities.CreateBerSetFromList(_crls);
+			}
+
+			Asn1OctetString octs = null;
+			if (encapsulate)
+            {
+                MemoryStream bOut = new MemoryStream();
+				if (content != null)
+				{
+	                try
+	                {
+	                    content.Write(bOut);
+	                }
+	                catch (IOException e)
+	                {
+	                    throw new CmsException("encapsulation error.", e);
+	                }
+				}
+				octs = new BerOctetString(bOut.ToArray());
+            }
+
+            ContentInfo encInfo = new ContentInfo(contentTypeOid, octs);
+
+            SignedData sd = new SignedData(
+                new DerSet(digestAlgs),
+                encInfo,
+                certificates,
+                certrevlist,
+                new DerSet(signerInfos));
+
+            ContentInfo contentInfo = new ContentInfo(CmsObjectIdentifiers.SignedData, sd);
+
+            return new CmsSignedData(content, contentInfo);
+        }
+
+        /**
+        * generate a signed object that for a CMS Signed Data
+        * object - if encapsulate is true a copy
+        * of the message will be included in the signature with the
+        * default content type "data".
+        */
+        public CmsSignedData Generate(
+            CmsProcessable	content,
+            bool			encapsulate)
+        {
+            return this.Generate(Data, content, encapsulate);
+        }
+
+		/**
+		* generate a set of one or more SignerInformation objects representing counter signatures on
+		* the passed in SignerInformation object.
+		*
+		* @param signer the signer to be countersigned
+		* @param sigProvider the provider to be used for counter signing.
+		* @return a store containing the signers.
+		*/
+		public SignerInformationStore GenerateCounterSigners(
+			SignerInformation signer)
+		{
+			return this.Generate(null, new CmsProcessableByteArray(signer.GetSignature()), false).GetSignerInfos();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedDataParser.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataParser.cs
new file mode 100644
index 0000000..ec5a84f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataParser.cs
@@ -0,0 +1,450 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* Parsing class for an CMS Signed Data object from an input stream.
+	* <p>
+	* Note: that because we are in a streaming mode only one signer can be tried and it is important
+	* that the methods on the parser are called in the appropriate order.
+	* </p>
+	* <p>
+	* A simple example of usage for an encapsulated signature.
+	* </p>
+	* <p>
+	* Two notes: first, in the example below the validity of
+	* the certificate isn't verified, just the fact that one of the certs
+	* matches the given signer, and, second, because we are in a streaming
+	* mode the order of the operations is important.
+	* </p>
+	* <pre>
+	*      CmsSignedDataParser     sp = new CmsSignedDataParser(encapSigData);
+	*
+	*      sp.GetSignedContent().Drain();
+	*
+	*      IX509Store              certs = sp.GetCertificates();
+	*      SignerInformationStore  signers = sp.GetSignerInfos();
+	*
+	*      foreach (SignerInformation signer in signers.GetSigners())
+	*      {
+	*          ArrayList       certList = new ArrayList(certs.GetMatches(signer.SignerID));
+	*          X509Certificate cert = (X509Certificate) certList[0];
+	*
+	*          Console.WriteLine("verify returns: " + signer.Verify(cert));
+	*      }
+	* </pre>
+	*  Note also: this class does not introduce buffering - if you are processing large files you should create
+	*  the parser with:
+	*  <pre>
+	*          CmsSignedDataParser     ep = new CmsSignedDataParser(new BufferedInputStream(encapSigData, bufSize));
+	*  </pre>
+	*  where bufSize is a suitably large buffer size.
+	*/
+	public class CmsSignedDataParser
+		: CmsContentInfoParser
+	{
+		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+		private SignedDataParser        _signedData;
+		private DerObjectIdentifier		_signedContentType;
+		private CmsTypedStream          _signedContent;
+		private IDictionary				_digests;
+		private ISet					_digestOids;
+
+		private SignerInformationStore  _signerInfoStore;
+		private Asn1Set                 _certSet, _crlSet;
+		private bool					_isCertCrlParsed;
+		private IX509Store				_attributeStore;
+		private IX509Store				_certificateStore;
+		private IX509Store				_crlStore;
+
+		public CmsSignedDataParser(
+			byte[] sigBlock)
+			: this(new MemoryStream(sigBlock, false))
+		{
+		}
+
+		public CmsSignedDataParser(
+			CmsTypedStream	signedContent,
+			byte[]			sigBlock)
+			: this(signedContent, new MemoryStream(sigBlock, false))
+		{
+		}
+
+		/**
+		* base constructor - with encapsulated content
+		*/
+		public CmsSignedDataParser(
+			Stream sigData)
+			: this(null, sigData)
+		{
+		}
+
+		/**
+		* base constructor
+		*
+		* @param signedContent the content that was signed.
+		* @param sigData the signature object.
+		*/
+		public CmsSignedDataParser(
+			CmsTypedStream	signedContent,
+			Stream			sigData)
+			: base(sigData)
+		{
+			try
+			{
+				this._signedContent = signedContent;
+				this._signedData = SignedDataParser.GetInstance(this.contentInfo.GetContent(Asn1Tags.Sequence));
+				this._digests = Platform.CreateHashtable();
+				this._digestOids = new HashSet();
+
+				Asn1SetParser digAlgs = _signedData.GetDigestAlgorithms();
+				IAsn1Convertible o;
+
+				while ((o = digAlgs.ReadObject()) != null)
+				{
+					AlgorithmIdentifier id = AlgorithmIdentifier.GetInstance(o.ToAsn1Object());
+
+					try
+					{
+						string digestOid = id.ObjectID.Id;
+						string digestName = Helper.GetDigestAlgName(digestOid);
+
+						if (!this._digests.Contains(digestName))
+						{
+							this._digests[digestName] = Helper.GetDigestInstance(digestName);
+							this._digestOids.Add(digestOid);
+						}
+					}
+					catch (SecurityUtilityException)
+					{
+						// TODO Should do something other than ignore it
+					}
+				}
+
+				//
+				// If the message is simply a certificate chain message GetContent() may return null.
+				//
+				ContentInfoParser cont = _signedData.GetEncapContentInfo();
+				Asn1OctetStringParser octs = (Asn1OctetStringParser)
+					cont.GetContent(Asn1Tags.OctetString);
+
+				if (octs != null)
+				{
+					CmsTypedStream ctStr = new CmsTypedStream(
+						cont.ContentType.Id, octs.GetOctetStream());
+
+					if (_signedContent == null)
+					{
+						this._signedContent = ctStr;
+					}
+					else
+					{
+						//
+						// content passed in, need to read past empty encapsulated content info object if present
+						//
+						ctStr.Drain();
+					}
+				}
+
+				_signedContentType = _signedContent == null
+					?	cont.ContentType
+					:	new DerObjectIdentifier(_signedContent.ContentType);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("io exception: " + e.Message, e);
+			}
+		}
+
+		/**
+		 * Return the version number for the SignedData object
+		 *
+		 * @return the version number
+		 */
+		public int Version
+		{
+			get { return _signedData.Version.Value.IntValue; }
+		}
+
+		public ISet DigestOids
+		{
+			get { return new HashSet(_digestOids); }
+		}
+
+		/**
+		* return the collection of signers that are associated with the
+		* signatures for the message.
+		* @throws CmsException
+		*/
+		public SignerInformationStore GetSignerInfos()
+		{
+			if (_signerInfoStore == null)
+			{
+				PopulateCertCrlSets();
+
+                IList signerInfos = Platform.CreateArrayList();
+                IDictionary hashes = Platform.CreateHashtable();
+
+				foreach (object digestKey in _digests.Keys)
+				{
+					hashes[digestKey] = DigestUtilities.DoFinal(
+						(IDigest)_digests[digestKey]);
+				}
+
+				try
+				{
+					Asn1SetParser s = _signedData.GetSignerInfos();
+					IAsn1Convertible o;
+
+					while ((o = s.ReadObject()) != null)
+					{
+						SignerInfo info = SignerInfo.GetInstance(o.ToAsn1Object());
+						string digestName = Helper.GetDigestAlgName(
+							info.DigestAlgorithm.ObjectID.Id);
+
+						byte[] hash = (byte[]) hashes[digestName];
+
+						signerInfos.Add(new SignerInformation(info, _signedContentType, null, new BaseDigestCalculator(hash)));
+					}
+				}
+				catch (IOException e)
+				{
+					throw new CmsException("io exception: " + e.Message, e);
+				}
+
+				_signerInfoStore = new SignerInformationStore(signerInfos);
+			}
+
+			return _signerInfoStore;
+		}
+
+		/**
+		 * return a X509Store containing the attribute certificates, if any, contained
+		 * in this message.
+		 *
+		 * @param type type of store to create
+		 * @return a store of attribute certificates
+		 * @exception org.bouncycastle.x509.NoSuchStoreException if the store type isn't available.
+		 * @exception CmsException if a general exception prevents creation of the X509Store
+		 */
+		public IX509Store GetAttributeCertificates(
+			string type)
+		{
+			if (_attributeStore == null)
+			{
+				PopulateCertCrlSets();
+
+				_attributeStore = Helper.CreateAttributeStore(type, _certSet);
+			}
+
+			return _attributeStore;
+		}
+
+		/**
+		* return a X509Store containing the public key certificates, if any, contained
+		* in this message.
+		*
+		* @param type type of store to create
+		* @return a store of public key certificates
+		* @exception NoSuchStoreException if the store type isn't available.
+		* @exception CmsException if a general exception prevents creation of the X509Store
+		*/
+		public IX509Store GetCertificates(
+			string type)
+		{
+			if (_certificateStore == null)
+			{
+				PopulateCertCrlSets();
+
+				_certificateStore = Helper.CreateCertificateStore(type, _certSet);
+			}
+
+			return _certificateStore;
+		}
+
+		/**
+		* return a X509Store containing CRLs, if any, contained
+		* in this message.
+		*
+		* @param type type of store to create
+		* @return a store of CRLs
+		* @exception NoSuchStoreException if the store type isn't available.
+		* @exception CmsException if a general exception prevents creation of the X509Store
+		*/
+		public IX509Store GetCrls(
+			string type)
+		{
+			if (_crlStore == null)
+			{
+				PopulateCertCrlSets();
+
+				_crlStore = Helper.CreateCrlStore(type, _crlSet);
+			}
+
+			return _crlStore;
+		}
+
+		private void PopulateCertCrlSets()
+		{
+			if (_isCertCrlParsed)
+				return;
+
+			_isCertCrlParsed = true;
+
+			try
+			{
+				// care! Streaming - Must process the GetCertificates() result before calling GetCrls()
+				_certSet = GetAsn1Set(_signedData.GetCertificates());
+				_crlSet = GetAsn1Set(_signedData.GetCrls());
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("problem parsing cert/crl sets", e);
+			}
+		}
+
+		/// <summary>
+		/// Return the <c>DerObjectIdentifier</c> associated with the encapsulated
+		/// content info structure carried in the signed data.
+		/// </summary>
+		public DerObjectIdentifier SignedContentType
+		{
+			get { return _signedContentType; }
+		}
+
+		public CmsTypedStream GetSignedContent()
+		{
+			if (_signedContent == null)
+			{
+				return null;
+			}
+
+			Stream digStream = _signedContent.ContentStream;
+
+			foreach (IDigest digest in _digests.Values)
+			{
+				digStream = new DigestStream(digStream, digest, null);
+			}
+
+			return new CmsTypedStream(_signedContent.ContentType, digStream);
+		}
+
+		/**
+		 * Replace the signerinformation store associated with the passed
+		 * in message contained in the stream original with the new one passed in.
+		 * You would probably only want to do this if you wanted to change the unsigned
+		 * attributes associated with a signer, or perhaps delete one.
+		 * <p>
+		 * The output stream is returned unclosed.
+		 * </p>
+		 * @param original the signed data stream to be used as a base.
+		 * @param signerInformationStore the new signer information store to use.
+		 * @param out the stream to Write the new signed data object to.
+		 * @return out.
+		 */
+		public static Stream ReplaceSigners(
+			Stream					original,
+			SignerInformationStore	signerInformationStore,
+			Stream					outStr)
+		{
+			// NB: SecureRandom would be ignored since using existing signatures only
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+			CmsSignedDataParser parser = new CmsSignedDataParser(original);
+
+//			gen.AddDigests(parser.DigestOids);
+			gen.AddSigners(signerInformationStore);
+
+			CmsTypedStream signedContent = parser.GetSignedContent();
+			bool encapsulate = (signedContent != null);
+			Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
+			if (encapsulate)
+			{
+				Streams.PipeAll(signedContent.ContentStream, contentOut);
+			}
+
+			gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
+			gen.AddCertificates(parser.GetCertificates("Collection"));
+			gen.AddCrls(parser.GetCrls("Collection"));
+
+//			gen.AddSigners(parser.GetSignerInfos());
+
+            contentOut.Dispose();
+
+			return outStr;
+		}
+
+		/**
+		 * Replace the certificate and CRL information associated with this
+		 * CMSSignedData object with the new one passed in.
+		 * <p>
+		 * The output stream is returned unclosed.
+		 * </p>
+		 * @param original the signed data stream to be used as a base.
+		 * @param certsAndCrls the new certificates and CRLs to be used.
+		 * @param out the stream to Write the new signed data object to.
+		 * @return out.
+		 * @exception CmsException if there is an error processing the CertStore
+		 */
+		public static Stream ReplaceCertificatesAndCrls(
+			Stream			original,
+			IX509Store		x509Certs,
+			IX509Store		x509Crls,
+			IX509Store		x509AttrCerts,
+			Stream			outStr)
+		{
+			// NB: SecureRandom would be ignored since using existing signatures only
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+			CmsSignedDataParser parser = new CmsSignedDataParser(original);
+
+			gen.AddDigests(parser.DigestOids);
+
+			CmsTypedStream signedContent = parser.GetSignedContent();
+			bool encapsulate = (signedContent != null);
+			Stream contentOut = gen.Open(outStr, parser.SignedContentType.Id, encapsulate);
+			if (encapsulate)
+			{
+				Streams.PipeAll(signedContent.ContentStream, contentOut);
+			}
+
+//			gen.AddAttributeCertificates(parser.GetAttributeCertificates("Collection"));
+//			gen.AddCertificates(parser.GetCertificates("Collection"));
+//			gen.AddCrls(parser.GetCrls("Collection"));
+			if (x509AttrCerts != null)
+				gen.AddAttributeCertificates(x509AttrCerts);
+			if (x509Certs != null)
+				gen.AddCertificates(x509Certs);
+			if (x509Crls != null)
+				gen.AddCrls(x509Crls);
+
+			gen.AddSigners(parser.GetSignerInfos());
+
+            contentOut.Dispose();
+
+			return outStr;
+		}
+
+		private static Asn1Set GetAsn1Set(
+			Asn1SetParser asn1SetParser)
+		{
+			return asn1SetParser == null
+				?	null
+				:	Asn1Set.GetInstance(asn1SetParser.ToAsn1Object());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedDataStreamGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataStreamGenerator.cs
new file mode 100644
index 0000000..395a8ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedDataStreamGenerator.cs
@@ -0,0 +1,916 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * General class for generating a pkcs7-signature message stream.
+    * <p>
+    * A simple example of usage.
+    * </p>
+    * <pre>
+    *      IX509Store                   certs...
+    *      CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+    *
+    *      gen.AddSigner(privateKey, cert, CmsSignedDataStreamGenerator.DIGEST_SHA1);
+    *
+    *      gen.AddCertificates(certs);
+    *
+    *      Stream sigOut = gen.Open(bOut);
+    *
+    *      sigOut.Write(Encoding.UTF8.GetBytes("Hello World!"));
+    *
+    *      sigOut.Close();
+    * </pre>
+    */
+    public class CmsSignedDataStreamGenerator
+        : CmsSignedGenerator
+    {
+		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+		private readonly IList      _signerInfs = Platform.CreateArrayList();
+		private readonly ISet		_messageDigestOids = new HashSet();
+        private readonly IDictionary _messageDigests = Platform.CreateHashtable();
+        private readonly IDictionary _messageHashes = Platform.CreateHashtable();
+		private bool				_messageDigestsLocked;
+        private int					_bufferSize;
+
+		private class DigestAndSignerInfoGeneratorHolder
+		{
+			internal readonly SignerInfoGenerator	signerInf;
+			internal readonly string				digestOID;
+
+			internal DigestAndSignerInfoGeneratorHolder(SignerInfoGenerator signerInf, String digestOID)
+			{
+				this.signerInf = signerInf;
+				this.digestOID = digestOID;
+			}
+
+			internal AlgorithmIdentifier DigestAlgorithm
+			{
+				get { return new AlgorithmIdentifier(new DerObjectIdentifier(this.digestOID), DerNull.Instance); }
+			}
+		}
+
+		private class SignerInfoGeneratorImpl : SignerInfoGenerator
+        {
+			private readonly CmsSignedDataStreamGenerator outer;
+
+			private readonly SignerIdentifier			_signerIdentifier;
+			private readonly string						_digestOID;
+			private readonly string						_encOID;
+			private readonly CmsAttributeTableGenerator	_sAttr;
+			private readonly CmsAttributeTableGenerator	_unsAttr;
+			private readonly string						_encName;
+			private readonly ISigner					_sig;
+
+			internal SignerInfoGeneratorImpl(
+				CmsSignedDataStreamGenerator	outer,
+				AsymmetricKeyParameter			key,
+				SignerIdentifier				signerIdentifier,
+				string							digestOID,
+				string							encOID,
+				CmsAttributeTableGenerator		sAttr,
+				CmsAttributeTableGenerator		unsAttr)
+			{
+				this.outer = outer;
+
+				_signerIdentifier = signerIdentifier;
+				_digestOID = digestOID;
+				_encOID = encOID;
+				_sAttr = sAttr;
+				_unsAttr = unsAttr;
+				_encName = Helper.GetEncryptionAlgName(_encOID);
+
+				string digestName = Helper.GetDigestAlgName(_digestOID);
+				string signatureName = digestName + "with" + _encName;
+
+				if (_sAttr != null)
+				{
+            		_sig = Helper.GetSignatureInstance(signatureName);
+				}
+				else
+				{
+					// Note: Need to use raw signatures here since we have already calculated the digest
+					if (_encName.Equals("RSA"))
+					{
+						_sig = Helper.GetSignatureInstance("RSA");
+					}
+					else if (_encName.Equals("DSA"))
+					{
+						_sig = Helper.GetSignatureInstance("NONEwithDSA");
+					}
+					// TODO Add support for raw PSS
+//					else if (_encName.equals("RSAandMGF1"))
+//					{
+//						_sig = CMSSignedHelper.INSTANCE.getSignatureInstance("NONEWITHRSAPSS", _sigProvider);
+//						try
+//						{
+//							// Init the params this way to avoid having a 'raw' version of each PSS algorithm
+//							Signature sig2 = CMSSignedHelper.INSTANCE.getSignatureInstance(signatureName, _sigProvider);
+//							PSSParameterSpec spec = (PSSParameterSpec)sig2.getParameters().getParameterSpec(PSSParameterSpec.class);
+//							_sig.setParameter(spec);
+//						}
+//						catch (Exception e)
+//						{
+//							throw new SignatureException("algorithm: " + _encName + " could not be configured.");
+//						}
+//					}
+					else
+					{
+						throw new SignatureException("algorithm: " + _encName + " not supported in base signatures.");
+					}
+				}
+
+				_sig.Init(true, new ParametersWithRandom(key, outer.rand));
+			}
+
+			public SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
+        		byte[] calculatedDigest)
+			{
+				try
+				{
+					string digestName = Helper.GetDigestAlgName(_digestOID);
+					string signatureName = digestName + "with" + _encName;
+
+//					AlgorithmIdentifier digAlgId = DigestAlgorithmID;
+//
+//					byte[] hash = (byte[])outer._messageHashes[Helper.GetDigestAlgName(this._digestOID)];
+//					outer._digests[_digestOID] = hash.Clone();
+
+					byte[] bytesToSign = calculatedDigest;
+
+					/* RFC 3852 5.4
+					 * The result of the message digest calculation process depends on
+					 * whether the signedAttrs field is present.  When the field is absent,
+					 * the result is just the message digest of the content as described
+					 *
+					 * above.  When the field is present, however, the result is the message
+					 * digest of the complete DER encoding of the SignedAttrs value
+					 * contained in the signedAttrs field.
+					 */
+					Asn1Set signedAttr = null;
+					if (_sAttr != null)
+					{
+						IDictionary parameters = outer.GetBaseParameters(contentType, digestAlgorithm, calculatedDigest);
+
+//						Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(Collections.unmodifiableMap(parameters));
+						Asn1.Cms.AttributeTable signed = _sAttr.GetAttributes(parameters);
+
+                        if (contentType == null) //counter signature
+                        {
+                            if (signed != null && signed[CmsAttributes.ContentType] != null)
+                            {
+                                IDictionary tmpSigned = signed.ToDictionary();
+                                tmpSigned.Remove(CmsAttributes.ContentType);
+                                signed = new Asn1.Cms.AttributeTable(tmpSigned);
+                            }
+                        }
+
+                        signedAttr = outer.GetAttributeSet(signed);
+
+                		// sig must be composed from the DER encoding.
+						bytesToSign = signedAttr.GetEncoded(Asn1Encodable.Der);
+					}
+					else
+					{
+						// Note: Need to use raw signatures here since we have already calculated the digest
+						if (_encName.Equals("RSA"))
+						{
+							DigestInfo dInfo = new DigestInfo(digestAlgorithm, calculatedDigest);
+							bytesToSign = dInfo.GetEncoded(Asn1Encodable.Der);
+						}
+					}
+
+					_sig.BlockUpdate(bytesToSign, 0, bytesToSign.Length);
+					byte[] sigBytes = _sig.GenerateSignature();
+
+					Asn1Set unsignedAttr = null;
+					if (_unsAttr != null)
+					{
+						IDictionary parameters = outer.GetBaseParameters(
+							contentType, digestAlgorithm, calculatedDigest);
+						parameters[CmsAttributeTableParameter.Signature] = sigBytes.Clone();
+
+//						Asn1.Cms.AttributeTable unsigned = _unsAttr.getAttributes(Collections.unmodifiableMap(parameters));
+						Asn1.Cms.AttributeTable unsigned = _unsAttr.GetAttributes(parameters);
+
+						unsignedAttr = outer.GetAttributeSet(unsigned);
+					}
+
+					// TODO[RSAPSS] Need the ability to specify non-default parameters
+					Asn1Encodable sigX509Parameters = SignerUtilities.GetDefaultX509Parameters(signatureName);
+					AlgorithmIdentifier digestEncryptionAlgorithm = CmsSignedGenerator.GetEncAlgorithmIdentifier(
+						new DerObjectIdentifier(_encOID), sigX509Parameters);
+
+					return new SignerInfo(_signerIdentifier, digestAlgorithm,
+						signedAttr, digestEncryptionAlgorithm, new DerOctetString(sigBytes), unsignedAttr);
+				}
+	            catch (IOException e)
+	            {
+	                throw new CmsStreamException("encoding error.", e);
+	            }
+	            catch (SignatureException e)
+	            {
+	                throw new CmsStreamException("error creating signature.", e);
+	            }
+            }
+        }
+
+		public CmsSignedDataStreamGenerator()
+        {
+        }
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		public CmsSignedDataStreamGenerator(
+			SecureRandom rand)
+			: base(rand)
+		{
+		}
+
+		/**
+        * Set the underlying string size for encapsulated data
+        *
+        * @param bufferSize length of octet strings to buffer the data.
+        */
+        public void SetBufferSize(
+            int bufferSize)
+        {
+            _bufferSize = bufferSize;
+        }
+
+		public void AddDigests(
+       		params string[] digestOids)
+		{
+       		AddDigests((IEnumerable) digestOids);
+		}
+
+		public void AddDigests(
+			IEnumerable digestOids)
+		{
+			foreach (string digestOid in digestOids)
+			{
+				ConfigureDigest(digestOid);
+			}
+		}
+
+		/**
+        * add a signer - no attributes other than the default ones will be
+        * provided here.
+        * @throws NoSuchAlgorithmException
+        * @throws InvalidKeyException
+        */
+        public void AddSigner(
+            AsymmetricKeyParameter	privateKey,
+            X509Certificate			cert,
+            string					digestOid)
+        {
+			AddSigner(privateKey, cert, digestOid,
+				new DefaultSignedAttributeTableGenerator(), null);
+		}
+
+		/**
+		 * add a signer, specifying the digest encryption algorithm - no attributes other than the default ones will be
+		 * provided here.
+		 * @throws NoSuchProviderException
+		 * @throws NoSuchAlgorithmException
+		 * @throws InvalidKeyException
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate			cert,
+			string					encryptionOid,
+			string					digestOid)
+		{
+			AddSigner(privateKey, cert, encryptionOid, digestOid,
+				new DefaultSignedAttributeTableGenerator(),
+				(CmsAttributeTableGenerator)null);
+		}
+
+        /**
+        * add a signer with extra signed/unsigned attributes.
+        * @throws NoSuchAlgorithmException
+        * @throws InvalidKeyException
+        */
+        public void AddSigner(
+            AsymmetricKeyParameter	privateKey,
+            X509Certificate			cert,
+            string					digestOid,
+            Asn1.Cms.AttributeTable	signedAttr,
+            Asn1.Cms.AttributeTable	unsignedAttr)
+        {
+			AddSigner(privateKey, cert, digestOid,
+				new DefaultSignedAttributeTableGenerator(signedAttr),
+				new SimpleAttributeTableGenerator(unsignedAttr));
+		}
+
+		/**
+		 * add a signer with extra signed/unsigned attributes - specifying digest
+		 * encryption algorithm.
+		 * @throws NoSuchProviderException
+		 * @throws NoSuchAlgorithmException
+		 * @throws InvalidKeyException
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate			cert,
+			string					encryptionOid,
+			string					digestOid,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+		{
+			AddSigner(privateKey, cert, encryptionOid, digestOid,
+				new DefaultSignedAttributeTableGenerator(signedAttr),
+				new SimpleAttributeTableGenerator(unsignedAttr));
+		}
+
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			X509Certificate				cert,
+			string						digestOid,
+			CmsAttributeTableGenerator  signedAttrGenerator,
+			CmsAttributeTableGenerator  unsignedAttrGenerator)
+		{
+			AddSigner(privateKey, cert, GetEncOid(privateKey, digestOid), digestOid,
+				signedAttrGenerator, unsignedAttrGenerator);
+        }
+
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			X509Certificate				cert,
+			string						encryptionOid,
+			string						digestOid,
+			CmsAttributeTableGenerator  signedAttrGenerator,
+			CmsAttributeTableGenerator  unsignedAttrGenerator)
+		{
+			DoAddSigner(privateKey, GetSignerIdentifier(cert), encryptionOid, digestOid,
+				signedAttrGenerator, unsignedAttrGenerator);
+		}
+
+		/**
+		* add a signer - no attributes other than the default ones will be
+		* provided here.
+		* @throws NoSuchAlgorithmException
+		* @throws InvalidKeyException
+		*/
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					digestOid)
+		{
+			AddSigner(privateKey, subjectKeyID, digestOid, new DefaultSignedAttributeTableGenerator(),
+				(CmsAttributeTableGenerator)null);
+		}
+
+		/**
+		 * add a signer - no attributes other than the default ones will be
+		 * provided here.
+		 * @throws NoSuchProviderException
+		 * @throws NoSuchAlgorithmException
+		 * @throws InvalidKeyException
+		 */
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					encryptionOid,
+			string					digestOid)
+		{
+			AddSigner(privateKey, subjectKeyID, encryptionOid, digestOid,
+				new DefaultSignedAttributeTableGenerator(),
+				(CmsAttributeTableGenerator)null);
+		}
+
+		/**
+		* add a signer with extra signed/unsigned attributes.
+		* @throws NoSuchAlgorithmException
+		* @throws InvalidKeyException
+		*/
+		public void AddSigner(
+			AsymmetricKeyParameter	privateKey,
+			byte[]					subjectKeyID,
+			string					digestOid,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+	    {
+	        AddSigner(privateKey, subjectKeyID, digestOid,
+				new DefaultSignedAttributeTableGenerator(signedAttr),
+				new SimpleAttributeTableGenerator(unsignedAttr));
+		}
+
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			byte[]						subjectKeyID,
+			string						digestOid,
+			CmsAttributeTableGenerator	signedAttrGenerator,
+			CmsAttributeTableGenerator	unsignedAttrGenerator)
+		{
+			AddSigner(privateKey, subjectKeyID, GetEncOid(privateKey, digestOid),
+				digestOid, signedAttrGenerator, unsignedAttrGenerator);
+		}
+
+		public void AddSigner(
+			AsymmetricKeyParameter		privateKey,
+			byte[]						subjectKeyID,
+			string						encryptionOid,
+			string						digestOid,
+			CmsAttributeTableGenerator	signedAttrGenerator,
+			CmsAttributeTableGenerator	unsignedAttrGenerator)
+		{
+			DoAddSigner(privateKey, GetSignerIdentifier(subjectKeyID), encryptionOid, digestOid,
+				signedAttrGenerator, unsignedAttrGenerator);
+		}
+
+		private void DoAddSigner(
+			AsymmetricKeyParameter		privateKey,
+			SignerIdentifier			signerIdentifier,
+			string						encryptionOid,
+			string						digestOid,
+			CmsAttributeTableGenerator	signedAttrGenerator,
+			CmsAttributeTableGenerator	unsignedAttrGenerator)
+		{
+			ConfigureDigest(digestOid);
+
+			SignerInfoGeneratorImpl signerInf = new SignerInfoGeneratorImpl(this, privateKey,
+				signerIdentifier, digestOid, encryptionOid, signedAttrGenerator, unsignedAttrGenerator);
+
+			_signerInfs.Add(new DigestAndSignerInfoGeneratorHolder(signerInf, digestOid));
+		}
+
+		internal override void AddSignerCallback(
+			SignerInformation si)
+		{
+			// FIXME If there were parameters in si.DigestAlgorithmID.Parameters, they are lost
+			// NB: Would need to call FixAlgID on the DigestAlgorithmID
+
+			// For precalculated signers, just need to register the algorithm, not configure a digest
+			RegisterDigestOid(si.DigestAlgorithmID.ObjectID.Id);
+		}
+
+		/**
+        * generate a signed object that for a CMS Signed Data object
+        */
+        public Stream Open(
+            Stream outStream)
+        {
+            return Open(outStream, false);
+        }
+
+        /**
+        * generate a signed object that for a CMS Signed Data
+        * object - if encapsulate is true a copy
+        * of the message will be included in the signature with the
+        * default content type "data".
+        */
+        public Stream Open(
+            Stream	outStream,
+            bool	encapsulate)
+        {
+            return Open(outStream, Data, encapsulate);
+        }
+
+		/**
+		 * generate a signed object that for a CMS Signed Data
+		 * object using the given provider - if encapsulate is true a copy
+		 * of the message will be included in the signature with the
+		 * default content type "data". If dataOutputStream is non null the data
+		 * being signed will be written to the stream as it is processed.
+		 * @param out stream the CMS object is to be written to.
+		 * @param encapsulate true if data should be encapsulated.
+		 * @param dataOutputStream output stream to copy the data being signed to.
+		 */
+		public Stream Open(
+			Stream	outStream,
+			bool	encapsulate,
+			Stream	dataOutputStream)
+		{
+			return Open(outStream, Data, encapsulate, dataOutputStream);
+		}
+
+		/**
+        * generate a signed object that for a CMS Signed Data
+        * object - if encapsulate is true a copy
+        * of the message will be included in the signature. The content type
+        * is set according to the OID represented by the string signedContentType.
+        */
+        public Stream Open(
+            Stream	outStream,
+            string	signedContentType,
+            bool	encapsulate)
+        {
+			return Open(outStream, signedContentType, encapsulate, null);
+		}
+
+		/**
+		* generate a signed object that for a CMS Signed Data
+		* object using the given provider - if encapsulate is true a copy
+		* of the message will be included in the signature. The content type
+		* is set according to the OID represented by the string signedContentType.
+		* @param out stream the CMS object is to be written to.
+		* @param signedContentType OID for data to be signed.
+		* @param encapsulate true if data should be encapsulated.
+		* @param dataOutputStream output stream to copy the data being signed to.
+		*/
+		public Stream Open(
+			Stream	outStream,
+			string	signedContentType,
+			bool	encapsulate,
+			Stream	dataOutputStream)
+		{
+			if (outStream == null)
+				throw new ArgumentNullException("outStream");
+			if (!outStream.CanWrite)
+				throw new ArgumentException("Expected writeable stream", "outStream");
+			if (dataOutputStream != null && !dataOutputStream.CanWrite)
+				throw new ArgumentException("Expected writeable stream", "dataOutputStream");
+
+			_messageDigestsLocked = true;
+
+			//
+            // ContentInfo
+            //
+            BerSequenceGenerator sGen = new BerSequenceGenerator(outStream);
+
+			sGen.AddObject(CmsObjectIdentifiers.SignedData);
+
+			//
+            // Signed Data
+            //
+            BerSequenceGenerator sigGen = new BerSequenceGenerator(
+				sGen.GetRawOutputStream(), 0, true);
+
+            bool isCounterSignature = (signedContentType == null);
+
+            DerObjectIdentifier contentTypeOid = isCounterSignature
+                ? null
+                : new DerObjectIdentifier(signedContentType);
+
+            sigGen.AddObject(CalculateVersion(contentTypeOid));
+
+			Asn1EncodableVector digestAlgs = new Asn1EncodableVector();
+
+			foreach (string digestOid in _messageDigestOids)
+            {
+				digestAlgs.Add(
+            		new AlgorithmIdentifier(new DerObjectIdentifier(digestOid), DerNull.Instance));
+            }
+
+            {
+				byte[] tmp = new DerSet(digestAlgs).GetEncoded();
+				sigGen.GetRawOutputStream().Write(tmp, 0, tmp.Length);
+			}
+
+			BerSequenceGenerator eiGen = new BerSequenceGenerator(sigGen.GetRawOutputStream());
+            eiGen.AddObject(contentTypeOid);
+
+        	// If encapsulating, add the data as an octet string in the sequence
+			Stream encapStream = encapsulate
+				?	CmsUtilities.CreateBerOctetOutputStream(eiGen.GetRawOutputStream(), 0, true, _bufferSize)
+				:	null;
+
+        	// Also send the data to 'dataOutputStream' if necessary
+			Stream teeStream = GetSafeTeeOutputStream(dataOutputStream, encapStream);
+
+        	// Let all the digests see the data as it is written
+			Stream digStream = AttachDigestsToOutputStream(_messageDigests.Values, teeStream);
+
+			return new CmsSignedDataOutputStream(this, digStream, signedContentType, sGen, sigGen, eiGen);
+        }
+
+		private void RegisterDigestOid(
+			string digestOid)
+		{
+       		if (_messageDigestsLocked)
+       		{
+       			if (!_messageDigestOids.Contains(digestOid))
+					throw new InvalidOperationException("Cannot register new digest OIDs after the data stream is opened");
+       		}
+       		else
+       		{
+				_messageDigestOids.Add(digestOid);
+       		}
+		}
+
+		private void ConfigureDigest(
+			string digestOid)
+		{
+       		RegisterDigestOid(digestOid);
+
+       		string digestName = Helper.GetDigestAlgName(digestOid);
+			IDigest dig = (IDigest)_messageDigests[digestName];
+			if (dig == null)
+			{
+				if (_messageDigestsLocked)
+					throw new InvalidOperationException("Cannot configure new digests after the data stream is opened");
+
+            	dig = Helper.GetDigestInstance(digestName);
+            	_messageDigests[digestName] = dig;
+            }
+		}
+
+		// TODO Make public?
+		internal void Generate(
+			Stream			outStream,
+			string			eContentType,
+			bool			encapsulate,
+			Stream			dataOutputStream,
+			CmsProcessable	content)
+		{
+			Stream signedOut = Open(outStream, eContentType, encapsulate, dataOutputStream);
+			if (content != null)
+			{
+				content.Write(signedOut);
+			}
+            signedOut.Dispose();
+		}
+
+		// RFC3852, section 5.1:
+		// IF ((certificates is present) AND
+		//    (any certificates with a type of other are present)) OR
+		//    ((crls is present) AND
+		//    (any crls with a type of other are present))
+		// THEN version MUST be 5
+		// ELSE
+		//    IF (certificates is present) AND
+		//       (any version 2 attribute certificates are present)
+		//    THEN version MUST be 4
+		//    ELSE
+		//       IF ((certificates is present) AND
+		//          (any version 1 attribute certificates are present)) OR
+		//          (any SignerInfo structures are version 3) OR
+		//          (encapContentInfo eContentType is other than id-data)
+		//       THEN version MUST be 3
+		//       ELSE version MUST be 1
+		//
+		private DerInteger CalculateVersion(
+			DerObjectIdentifier contentOid)
+		{
+			bool otherCert = false;
+			bool otherCrl = false;
+			bool attrCertV1Found = false;
+			bool attrCertV2Found = false;
+
+			if (_certs != null)
+			{
+				foreach (object obj in _certs)
+				{
+					if (obj is Asn1TaggedObject)
+					{
+						Asn1TaggedObject tagged = (Asn1TaggedObject) obj;
+
+						if (tagged.TagNo == 1)
+						{
+							attrCertV1Found = true;
+						}
+						else if (tagged.TagNo == 2)
+						{
+							attrCertV2Found = true;
+						}
+						else if (tagged.TagNo == 3)
+						{
+							otherCert = true;
+							break;
+						}
+					}
+				}
+			}
+
+			if (otherCert)
+			{
+				return new DerInteger(5);
+			}
+
+			if (_crls != null)
+			{
+				foreach (object obj in _crls)
+				{
+					if (obj is Asn1TaggedObject)
+					{
+						otherCrl = true;
+						break;
+					}
+				}
+			}
+
+			if (otherCrl)
+			{
+				return new DerInteger(5);
+			}
+
+			if (attrCertV2Found)
+			{
+				return new DerInteger(4);
+			}
+
+            if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(_signers))
+            {
+                return new DerInteger(3);
+            }
+
+            return new DerInteger(1);
+        }
+
+		private bool CheckForVersion3(
+			IList signerInfos)
+		{
+			foreach (SignerInformation si in signerInfos)
+			{
+				SignerInfo s = SignerInfo.GetInstance(si.ToSignerInfo());
+
+				if (s.Version.Value.IntValue == 3)
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		private static Stream AttachDigestsToOutputStream(ICollection digests, Stream s)
+		{
+			Stream result = s;
+			foreach (IDigest digest in digests)
+			{
+				result = GetSafeTeeOutputStream(result, new DigOutputStream(digest));
+			}
+			return result;
+		}
+
+		private static Stream GetSafeOutputStream(Stream s)
+		{
+			if (s == null)
+				return new NullOutputStream();
+			return s;
+		}
+
+		private static Stream GetSafeTeeOutputStream(Stream s1, Stream s2)
+		{
+			if (s1 == null)
+				return GetSafeOutputStream(s2);
+			if (s2 == null)
+				return GetSafeOutputStream(s1);
+			return new TeeOutputStream(s1, s2);
+		}
+
+		private class CmsSignedDataOutputStream
+            : BaseOutputStream
+        {
+			private readonly CmsSignedDataStreamGenerator outer;
+
+			private Stream					_out;
+            private DerObjectIdentifier		_contentOID;
+            private BerSequenceGenerator	_sGen;
+            private BerSequenceGenerator	_sigGen;
+            private BerSequenceGenerator	_eiGen;
+
+			public CmsSignedDataOutputStream(
+				CmsSignedDataStreamGenerator	outer,
+				Stream							outStream,
+                string							contentOID,
+                BerSequenceGenerator			sGen,
+                BerSequenceGenerator			sigGen,
+                BerSequenceGenerator			eiGen)
+            {
+				this.outer = outer;
+
+				_out = outStream;
+                _contentOID = new DerObjectIdentifier(contentOID);
+                _sGen = sGen;
+                _sigGen = sigGen;
+                _eiGen = eiGen;
+            }
+
+			public override void WriteByte(
+                byte b)
+            {
+                _out.WriteByte(b);
+            }
+
+			public override void Write(
+                byte[]	bytes,
+                int		off,
+                int		len)
+            {
+                _out.Write(bytes, off, len);
+            }
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+                    _out.Dispose();
+
+                    // TODO Parent context(s) should really be be closed explicitly
+
+                    _eiGen.Close();
+
+                    outer._digests.Clear();    // clear the current preserved digest state
+
+                    if (outer._certs.Count > 0)
+                    {
+                        Asn1Set certs = CmsUtilities.CreateBerSetFromList(outer._certs);
+
+                        WriteToGenerator(_sigGen, new BerTaggedObject(false, 0, certs));
+                    }
+
+                    if (outer._crls.Count > 0)
+                    {
+                        Asn1Set crls = CmsUtilities.CreateBerSetFromList(outer._crls);
+
+                        WriteToGenerator(_sigGen, new BerTaggedObject(false, 1, crls));
+                    }
+
+                    //
+                    // Calculate the digest hashes
+                    //
+                    foreach (DictionaryEntry de in outer._messageDigests)
+                    {
+                        outer._messageHashes.Add(de.Key, DigestUtilities.DoFinal((IDigest)de.Value));
+                    }
+
+                    // TODO If the digest OIDs for precalculated signers weren't mixed in with
+                    // the others, we could fill in outer._digests here, instead of SignerInfoGenerator.Generate
+
+                    //
+                    // collect all the SignerInfo objects
+                    //
+                    Asn1EncodableVector signerInfos = new Asn1EncodableVector();
+
+                    //
+                    // add the generated SignerInfo objects
+                    //
+                    {
+                        foreach (DigestAndSignerInfoGeneratorHolder holder in outer._signerInfs)
+                        {
+                            AlgorithmIdentifier digestAlgorithm = holder.DigestAlgorithm;
+
+                            byte[] calculatedDigest = (byte[])outer._messageHashes[
+                                Helper.GetDigestAlgName(holder.digestOID)];
+                            outer._digests[holder.digestOID] = calculatedDigest.Clone();
+
+                            signerInfos.Add(holder.signerInf.Generate(_contentOID, digestAlgorithm, calculatedDigest));
+                        }
+                    }
+
+                    //
+                    // add the precalculated SignerInfo objects.
+                    //
+                    {
+                        foreach (SignerInformation signer in outer._signers)
+                        {
+                            // TODO Verify the content type and calculated digest match the precalculated SignerInfo
+                            //						if (!signer.ContentType.Equals(_contentOID))
+                            //						{
+                            //							// TODO The precalculated content type did not match - error?
+                            //						}
+                            //
+                            //						byte[] calculatedDigest = (byte[])outer._digests[signer.DigestAlgOid];
+                            //						if (calculatedDigest == null)
+                            //						{
+                            //							// TODO We can't confirm this digest because we didn't calculate it - error?
+                            //						}
+                            //						else
+                            //						{
+                            //							if (!Arrays.AreEqual(signer.GetContentDigest(), calculatedDigest))
+                            //							{
+                            //								// TODO The precalculated digest did not match - error?
+                            //							}
+                            //						}
+
+                            signerInfos.Add(signer.ToSignerInfo());
+                        }
+                    }
+
+                    WriteToGenerator(_sigGen, new DerSet(signerInfos));
+
+                    _sigGen.Close();
+                    _sGen.Close();
+		        }
+		        base.Dispose(disposing);
+		    }
+
+			private static void WriteToGenerator(
+				Asn1Generator	ag,
+				Asn1Encodable	ae)
+			{
+				byte[] encoded = ae.GetEncoded();
+				ag.GetRawOutputStream().Write(encoded, 0, encoded.Length);
+			}
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedGenerator.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedGenerator.cs
new file mode 100644
index 0000000..f272c83
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedGenerator.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    public class CmsSignedGenerator
+    {
+        /**
+        * Default type for the signed data.
+        */
+        public static readonly string Data = CmsObjectIdentifiers.Data.Id;
+
+		public static readonly string DigestSha1 = OiwObjectIdentifiers.IdSha1.Id;
+        public static readonly string DigestSha224 = NistObjectIdentifiers.IdSha224.Id;
+        public static readonly string DigestSha256 = NistObjectIdentifiers.IdSha256.Id;
+        public static readonly string DigestSha384 = NistObjectIdentifiers.IdSha384.Id;
+        public static readonly string DigestSha512 = NistObjectIdentifiers.IdSha512.Id;
+        public static readonly string DigestMD5 = PkcsObjectIdentifiers.MD5.Id;
+        public static readonly string DigestGost3411 = CryptoProObjectIdentifiers.GostR3411.Id;
+		public static readonly string DigestRipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id;
+		public static readonly string DigestRipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id;
+		public static readonly string DigestRipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id;
+
+		public static readonly string EncryptionRsa = PkcsObjectIdentifiers.RsaEncryption.Id;
+        public static readonly string EncryptionDsa = X9ObjectIdentifiers.IdDsaWithSha1.Id;
+        public static readonly string EncryptionECDsa = X9ObjectIdentifiers.ECDsaWithSha1.Id;
+        public static readonly string EncryptionRsaPss = PkcsObjectIdentifiers.IdRsassaPss.Id;
+        public static readonly string EncryptionGost3410 = CryptoProObjectIdentifiers.GostR3410x94.Id;
+        public static readonly string EncryptionECGost3410 = CryptoProObjectIdentifiers.GostR3410x2001.Id;
+
+		private static readonly string EncryptionECDsaWithSha1 = X9ObjectIdentifiers.ECDsaWithSha1.Id;
+		private static readonly string EncryptionECDsaWithSha224 = X9ObjectIdentifiers.ECDsaWithSha224.Id;
+		private static readonly string EncryptionECDsaWithSha256 = X9ObjectIdentifiers.ECDsaWithSha256.Id;
+		private static readonly string EncryptionECDsaWithSha384 = X9ObjectIdentifiers.ECDsaWithSha384.Id;
+		private static readonly string EncryptionECDsaWithSha512 = X9ObjectIdentifiers.ECDsaWithSha512.Id;
+
+		private static readonly ISet noParams = new HashSet();
+		private static readonly IDictionary ecAlgorithms = Platform.CreateHashtable();
+
+		static CmsSignedGenerator()
+		{
+			noParams.Add(EncryptionDsa);
+//			noParams.Add(EncryptionECDsa);
+			noParams.Add(EncryptionECDsaWithSha1);
+			noParams.Add(EncryptionECDsaWithSha224);
+			noParams.Add(EncryptionECDsaWithSha256);
+			noParams.Add(EncryptionECDsaWithSha384);
+			noParams.Add(EncryptionECDsaWithSha512);
+
+			ecAlgorithms.Add(DigestSha1, EncryptionECDsaWithSha1);
+			ecAlgorithms.Add(DigestSha224, EncryptionECDsaWithSha224);
+			ecAlgorithms.Add(DigestSha256, EncryptionECDsaWithSha256);
+			ecAlgorithms.Add(DigestSha384, EncryptionECDsaWithSha384);
+			ecAlgorithms.Add(DigestSha512, EncryptionECDsaWithSha512);
+		}
+
+		internal IList _certs = Platform.CreateArrayList();
+        internal IList _crls = Platform.CreateArrayList();
+		internal IList _signers = Platform.CreateArrayList();
+		internal IDictionary _digests = Platform.CreateHashtable();
+
+		protected readonly SecureRandom rand;
+
+		protected CmsSignedGenerator()
+			: this(new SecureRandom())
+		{
+		}
+
+		/// <summary>Constructor allowing specific source of randomness</summary>
+		/// <param name="rand">Instance of <c>SecureRandom</c> to use.</param>
+		protected CmsSignedGenerator(
+			SecureRandom rand)
+		{
+			this.rand = rand;
+		}
+
+		protected string GetEncOid(
+            AsymmetricKeyParameter	key,
+            string					digestOID)
+        {
+            string encOID = null;
+
+			if (key is RsaKeyParameters)
+			{
+				if (!((RsaKeyParameters) key).IsPrivate)
+					throw new ArgumentException("Expected RSA private key");
+
+				encOID = EncryptionRsa;
+			}
+			else if (key is DsaPrivateKeyParameters)
+			{
+				if (!digestOID.Equals(DigestSha1))
+					throw new ArgumentException("can't mix DSA with anything but SHA1");
+
+				encOID = EncryptionDsa;
+			}
+			else if (key is ECPrivateKeyParameters)
+			{
+				ECPrivateKeyParameters ecPrivKey = (ECPrivateKeyParameters) key;
+				string algName = ecPrivKey.AlgorithmName;
+
+				if (algName == "ECGOST3410")
+				{
+					encOID = EncryptionECGost3410;
+				}
+				else
+				{
+					// TODO Should we insist on algName being one of "EC" or "ECDSA", as Java does?
+					encOID = (string) ecAlgorithms[digestOID];
+
+					if (encOID == null)
+						throw new ArgumentException("can't mix ECDSA with anything but SHA family digests");
+				}
+			}
+			else if (key is Gost3410PrivateKeyParameters)
+			{
+				encOID = EncryptionGost3410;
+			}
+			else
+			{
+				throw new ArgumentException("Unknown algorithm in CmsSignedGenerator.GetEncOid");
+			}
+
+			return encOID;
+        }
+
+		internal static AlgorithmIdentifier GetEncAlgorithmIdentifier(
+			DerObjectIdentifier	encOid,
+			Asn1Encodable		sigX509Parameters)
+		{
+			if (noParams.Contains(encOid.Id))
+			{
+				return new AlgorithmIdentifier(encOid);
+			}
+
+			return new AlgorithmIdentifier(encOid, sigX509Parameters);
+		}
+
+		internal protected virtual IDictionary GetBaseParameters(
+			DerObjectIdentifier	contentType,
+			AlgorithmIdentifier	digAlgId,
+			byte[]				hash)
+		{
+			IDictionary param = Platform.CreateHashtable();
+
+            if (contentType != null)
+            {
+                param[CmsAttributeTableParameter.ContentType] = contentType;
+            }
+
+			param[CmsAttributeTableParameter.DigestAlgorithmIdentifier] = digAlgId;
+            param[CmsAttributeTableParameter.Digest] = hash.Clone();
+
+            return param;
+		}
+
+		internal protected virtual Asn1Set GetAttributeSet(
+            Asn1.Cms.AttributeTable attr)
+        {
+			return attr == null
+				?	null
+				:	new DerSet(attr.ToAsn1EncodableVector());
+        }
+
+		public void AddCertificates(
+			IX509Store certStore)
+		{
+            CollectionUtilities.AddRange(_certs, CmsUtilities.GetCertificatesFromStore(certStore));
+        }
+
+		public void AddCrls(
+			IX509Store crlStore)
+		{
+            CollectionUtilities.AddRange(_crls, CmsUtilities.GetCrlsFromStore(crlStore));
+		}
+
+		/**
+		* Add the attribute certificates contained in the passed in store to the
+		* generator.
+		*
+		* @param store a store of Version 2 attribute certificates
+		* @throws CmsException if an error occurse processing the store.
+		*/
+		public void AddAttributeCertificates(
+			IX509Store store)
+		{
+			try
+			{
+				foreach (IX509AttributeCertificate attrCert in store.GetMatches(null))
+				{
+					_certs.Add(new DerTaggedObject(false, 2,
+						AttributeCertificate.GetInstance(Asn1Object.FromByteArray(attrCert.GetEncoded()))));
+				}
+			}
+			catch (Exception e)
+			{
+				throw new CmsException("error processing attribute certs", e);
+			}
+		}
+
+		/**
+		 * Add a store of precalculated signers to the generator.
+		 *
+		 * @param signerStore store of signers
+		 */
+		public void AddSigners(
+			SignerInformationStore signerStore)
+		{
+			foreach (SignerInformation o in signerStore.GetSigners())
+			{
+				_signers.Add(o);
+				AddSignerCallback(o);
+			}
+		}
+
+		/**
+		 * Return a map of oids and byte arrays representing the digests calculated on the content during
+		 * the last generate.
+		 *
+		 * @return a map of oids (as String objects) and byte[] representing digests.
+		 */
+		public IDictionary GetGeneratedDigests()
+		{
+			return Platform.CreateHashtable(_digests);
+		}
+
+		internal virtual void AddSignerCallback(
+			SignerInformation si)
+		{
+		}
+
+		internal static SignerIdentifier GetSignerIdentifier(X509Certificate cert)
+		{
+			return new SignerIdentifier(CmsUtilities.GetIssuerAndSerialNumber(cert));
+		}
+
+		internal static SignerIdentifier GetSignerIdentifier(byte[] subjectKeyIdentifier)
+		{
+			return new SignerIdentifier(new DerOctetString(subjectKeyIdentifier));    
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSSignedHelper.cs b/BouncyCastle.AxCrypt/src/cms/CMSSignedHelper.cs
new file mode 100644
index 0000000..b3406fc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSSignedHelper.cs
@@ -0,0 +1,319 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Eac;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    internal class CmsSignedHelper
+    {
+        internal static readonly CmsSignedHelper Instance = new CmsSignedHelper();
+
+		private static readonly IDictionary encryptionAlgs = Platform.CreateHashtable();
+        private static readonly IDictionary digestAlgs = Platform.CreateHashtable();
+        private static readonly IDictionary digestAliases = Platform.CreateHashtable();
+
+		private static void AddEntries(DerObjectIdentifier oid, string digest, string encryption)
+		{
+			string alias = oid.Id;
+			digestAlgs.Add(alias, digest);
+			encryptionAlgs.Add(alias, encryption);
+		}
+
+		static CmsSignedHelper()
+		{
+			AddEntries(NistObjectIdentifiers.DsaWithSha224, "SHA224", "DSA");
+			AddEntries(NistObjectIdentifiers.DsaWithSha256, "SHA256", "DSA");
+			AddEntries(NistObjectIdentifiers.DsaWithSha384, "SHA384", "DSA");
+			AddEntries(NistObjectIdentifiers.DsaWithSha512, "SHA512", "DSA");
+			AddEntries(OiwObjectIdentifiers.DsaWithSha1, "SHA1", "DSA");
+			AddEntries(OiwObjectIdentifiers.MD4WithRsa, "MD4", "RSA");
+			AddEntries(OiwObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA");
+			AddEntries(OiwObjectIdentifiers.MD5WithRsa, "MD5", "RSA");
+			AddEntries(OiwObjectIdentifiers.Sha1WithRsa, "SHA1", "RSA");
+			AddEntries(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2", "RSA");
+			AddEntries(PkcsObjectIdentifiers.MD4WithRsaEncryption, "MD4", "RSA");
+			AddEntries(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5", "RSA");
+			AddEntries(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1", "RSA");
+			AddEntries(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224", "RSA");
+			AddEntries(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256", "RSA");
+			AddEntries(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384", "RSA");
+			AddEntries(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512", "RSA");
+			AddEntries(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1", "ECDSA");
+			AddEntries(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224", "ECDSA");
+			AddEntries(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256", "ECDSA");
+			AddEntries(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384", "ECDSA");
+			AddEntries(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512", "ECDSA");
+			AddEntries(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1", "DSA");
+			AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_1, "SHA1", "ECDSA");
+			AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_224, "SHA224", "ECDSA");
+			AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_256, "SHA256", "ECDSA");
+			AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_384, "SHA384", "ECDSA");
+			AddEntries(EacObjectIdentifiers.id_TA_ECDSA_SHA_512, "SHA512", "ECDSA");
+			AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_1, "SHA1", "RSA");
+			AddEntries(EacObjectIdentifiers.id_TA_RSA_v1_5_SHA_256, "SHA256", "RSA");
+			AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_1, "SHA1", "RSAandMGF1");
+			AddEntries(EacObjectIdentifiers.id_TA_RSA_PSS_SHA_256, "SHA256", "RSAandMGF1");
+
+			encryptionAlgs.Add(X9ObjectIdentifiers.IdDsa.Id, "DSA");
+			encryptionAlgs.Add(PkcsObjectIdentifiers.RsaEncryption.Id, "RSA");
+			encryptionAlgs.Add(TeleTrusTObjectIdentifiers.TeleTrusTRsaSignatureAlgorithm, "RSA");
+			encryptionAlgs.Add(X509ObjectIdentifiers.IdEARsa.Id, "RSA");
+			encryptionAlgs.Add(CmsSignedGenerator.EncryptionRsaPss, "RSAandMGF1");
+			encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x94.Id, "GOST3410");
+			encryptionAlgs.Add(CryptoProObjectIdentifiers.GostR3410x2001.Id, "ECGOST3410");
+			encryptionAlgs.Add("1.3.6.1.4.1.5849.1.6.2", "ECGOST3410");
+			encryptionAlgs.Add("1.3.6.1.4.1.5849.1.1.5", "GOST3410");
+
+			digestAlgs.Add(PkcsObjectIdentifiers.MD2.Id, "MD2");
+			digestAlgs.Add(PkcsObjectIdentifiers.MD4.Id, "MD4");
+			digestAlgs.Add(PkcsObjectIdentifiers.MD5.Id, "MD5");
+			digestAlgs.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1");
+			digestAlgs.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224");
+			digestAlgs.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256");
+			digestAlgs.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384");
+			digestAlgs.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512");
+			digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128");
+			digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160");
+			digestAlgs.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256");
+			digestAlgs.Add(CryptoProObjectIdentifiers.GostR3411.Id,  "GOST3411");
+			digestAlgs.Add("1.3.6.1.4.1.5849.1.2.1",  "GOST3411");
+
+			digestAliases.Add("SHA1", new string[] { "SHA-1" });
+			digestAliases.Add("SHA224", new string[] { "SHA-224" });
+			digestAliases.Add("SHA256", new string[] { "SHA-256" });
+			digestAliases.Add("SHA384", new string[] { "SHA-384" });
+			digestAliases.Add("SHA512", new string[] { "SHA-512" });
+		}
+
+		/**
+        * Return the digest algorithm using one of the standard JCA string
+        * representations rather than the algorithm identifier (if possible).
+        */
+        internal string GetDigestAlgName(
+            string digestAlgOid)
+        {
+			string algName = (string)digestAlgs[digestAlgOid];
+
+			if (algName != null)
+			{
+				return algName;
+			}
+
+			return digestAlgOid;
+        }
+
+		internal string[] GetDigestAliases(
+			string algName)
+		{
+			string[] aliases = (string[]) digestAliases[algName];
+
+			return aliases == null ? new String[0] : (string[]) aliases.Clone();
+		}
+
+		/**
+        * Return the digest encryption algorithm using one of the standard
+        * JCA string representations rather than the algorithm identifier (if
+        * possible).
+        */
+        internal string GetEncryptionAlgName(
+            string encryptionAlgOid)
+        {
+			string algName = (string) encryptionAlgs[encryptionAlgOid];
+
+			if (algName != null)
+			{
+				return algName;
+			}
+
+			return encryptionAlgOid;
+        }
+
+		internal IDigest GetDigestInstance(
+			string algorithm)
+		{
+			try
+			{
+				return DigestUtilities.GetDigest(algorithm);
+			}
+			catch (SecurityUtilityException e)
+			{
+				// This is probably superfluous on C#, since no provider infrastructure,
+				// assuming DigestUtilities already knows all the aliases
+				foreach (string alias in GetDigestAliases(algorithm))
+				{
+					try { return DigestUtilities.GetDigest(alias); }
+					catch (SecurityUtilityException) {}
+				}
+				throw e;
+			}
+		}
+
+		internal ISigner GetSignatureInstance(
+			string algorithm)
+		{
+			return SignerUtilities.GetSigner(algorithm);
+		}
+
+		internal IX509Store CreateAttributeStore(
+			string	type,
+			Asn1Set	certSet)
+		{
+			IList certs = Platform.CreateArrayList();
+
+			if (certSet != null)
+			{
+				foreach (Asn1Encodable ae in certSet)
+				{
+					try
+					{
+						Asn1Object obj = ae.ToAsn1Object();
+
+						if (obj is Asn1TaggedObject)
+						{
+							Asn1TaggedObject tagged = (Asn1TaggedObject)obj;
+
+							if (tagged.TagNo == 2)
+							{
+								certs.Add(
+									new X509V2AttributeCertificate(
+										Asn1Sequence.GetInstance(tagged, false).GetEncoded()));
+							}
+						}
+					}
+					catch (Exception ex)
+					{
+						throw new CmsException("can't re-encode attribute certificate!", ex);
+					}
+				}
+			}
+
+			try
+			{
+				return X509StoreFactory.Create(
+					"AttributeCertificate/" + type,
+					new X509CollectionStoreParameters(certs));
+			}
+			catch (ArgumentException e)
+			{
+				throw new CmsException("can't setup the X509Store", e);
+			}
+		}
+
+		internal IX509Store CreateCertificateStore(
+			string	type,
+			Asn1Set	certSet)
+		{
+			IList certs = Platform.CreateArrayList();
+
+			if (certSet != null)
+			{
+				AddCertsFromSet(certs, certSet);
+			}
+
+			try
+			{
+				return X509StoreFactory.Create(
+					"Certificate/" + type,
+					new X509CollectionStoreParameters(certs));
+			}
+			catch (ArgumentException e)
+			{
+				throw new CmsException("can't setup the X509Store", e);
+			}
+		}
+
+		internal IX509Store CreateCrlStore(
+			string	type,
+			Asn1Set	crlSet)
+		{
+			IList crls = Platform.CreateArrayList();
+
+			if (crlSet != null)
+			{
+				AddCrlsFromSet(crls, crlSet);
+			}
+
+			try
+			{
+				return X509StoreFactory.Create(
+					"CRL/" + type,
+					new X509CollectionStoreParameters(crls));
+			}
+			catch (ArgumentException e)
+			{
+				throw new CmsException("can't setup the X509Store", e);
+			}
+		}
+
+		private void AddCertsFromSet(
+			IList	certs,
+			Asn1Set	certSet)
+		{
+			X509CertificateParser cf = new X509CertificateParser();
+
+			foreach (Asn1Encodable ae in certSet)
+			{
+				try
+				{
+					Asn1Object obj = ae.ToAsn1Object();
+
+					if (obj is Asn1Sequence)
+					{
+						// TODO Build certificate directly from sequence?
+						certs.Add(cf.ReadCertificate(obj.GetEncoded()));
+					}
+				}
+				catch (Exception ex)
+				{
+					throw new CmsException("can't re-encode certificate!", ex);
+				}
+			}
+		}
+
+		private void AddCrlsFromSet(
+			IList	crls,
+			Asn1Set	crlSet)
+		{
+			X509CrlParser cf = new X509CrlParser();
+
+			foreach (Asn1Encodable ae in crlSet)
+			{
+				try
+				{
+					// TODO Build CRL directly from ae.ToAsn1Object()?
+					crls.Add(cf.ReadCrl(ae.GetEncoded()));
+				}
+				catch (Exception ex)
+				{
+					throw new CmsException("can't re-encode CRL!", ex);
+				}
+			}
+		}
+
+		internal AlgorithmIdentifier FixAlgID(
+			AlgorithmIdentifier algId)
+		{
+			if (algId.Parameters == null)
+				return new AlgorithmIdentifier(algId.ObjectID, DerNull.Instance);
+
+			return algId;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSStreamException.cs b/BouncyCastle.AxCrypt/src/cms/CMSStreamException.cs
new file mode 100644
index 0000000..bf0a6ad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSStreamException.cs
@@ -0,0 +1,29 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CmsStreamException
+        : IOException
+    {
+		public CmsStreamException()
+		{
+		}
+
+		public CmsStreamException(
+			string name)
+			: base(name)
+        {
+        }
+
+		public CmsStreamException(
+			string		name,
+			Exception	e)
+			: base(name, e)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSTypedStream.cs b/BouncyCastle.AxCrypt/src/cms/CMSTypedStream.cs
new file mode 100644
index 0000000..edb22dd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSTypedStream.cs
@@ -0,0 +1,72 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class CmsTypedStream
+	{
+		private const int BufferSize = 32 * 1024;
+
+		private readonly string	_oid;
+		private readonly Stream	_in;
+
+		public CmsTypedStream(
+			Stream inStream)
+			: this(PkcsObjectIdentifiers.Data.Id, inStream, BufferSize)
+		{
+		}
+
+		public CmsTypedStream(
+			string oid,
+			Stream inStream)
+			: this(oid, inStream, BufferSize)
+		{
+		}
+
+		public CmsTypedStream(
+			string	oid,
+			Stream	inStream,
+			int		bufSize)
+		{
+			_oid = oid;
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
+			_in = new FullReaderStream(inStream);
+#else
+			_in = new FullReaderStream(new BufferedStream(inStream, bufSize));
+#endif
+		}
+
+		public string ContentType
+		{
+			get { return _oid; }
+		}
+
+		public Stream ContentStream
+		{
+			get { return _in; }
+		}
+
+		public void Drain()
+		{
+			Streams.Drain(_in);
+			_in.Dispose();
+		}
+
+		private class FullReaderStream : FilterStream
+		{
+			internal FullReaderStream(Stream input)
+				: base(input)
+			{
+			}
+
+			public override int Read(byte[]	buf, int off, int len)
+			{
+				return Streams.ReadFully(base.s, buf, off, len);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CMSUtils.cs b/BouncyCastle.AxCrypt/src/cms/CMSUtils.cs
new file mode 100644
index 0000000..95d7106
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CMSUtils.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    internal class CmsUtilities
+    {
+		// TODO Is there a .NET equivalent to this?
+//		private static readonly Runtime RUNTIME = Runtime.getRuntime();
+
+		internal static int MaximumMemory
+		{
+			get
+			{
+				// TODO Is there a .NET equivalent to this?
+				long maxMem = int.MaxValue;//RUNTIME.maxMemory();
+
+				if (maxMem > int.MaxValue)
+				{
+					return int.MaxValue;
+				}
+
+				return (int)maxMem;
+			}
+		}
+
+		internal static ContentInfo ReadContentInfo(
+			byte[] input)
+		{
+			// enforce limit checking as from a byte array
+			return ReadContentInfo(new Asn1InputStream(input));
+		}
+
+		internal static ContentInfo ReadContentInfo(
+			Stream input)
+		{
+			// enforce some limit checking
+			return ReadContentInfo(new Asn1InputStream(input, MaximumMemory));
+		}
+
+		private static ContentInfo ReadContentInfo(
+			Asn1InputStream aIn)
+		{
+			try
+			{
+				return ContentInfo.GetInstance(aIn.ReadObject());
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("IOException reading content.", e);
+			}
+			catch (InvalidCastException e)
+			{
+				throw new CmsException("Malformed content.", e);
+			}
+			catch (ArgumentException e)
+			{
+				throw new CmsException("Malformed content.", e);
+			}
+		}
+
+		public static byte[] StreamToByteArray(
+            Stream inStream)
+        {
+			return Streams.ReadAll(inStream);
+        }
+
+		public static byte[] StreamToByteArray(
+            Stream	inStream,
+			int		limit)
+        {
+			return Streams.ReadAllLimited(inStream, limit);
+        }
+
+		public static IList GetCertificatesFromStore(
+			IX509Store certStore)
+		{
+			try
+			{
+				IList certs = Platform.CreateArrayList();
+
+				if (certStore != null)
+				{
+					foreach (X509Certificate c in certStore.GetMatches(null))
+					{
+						certs.Add(
+							X509CertificateStructure.GetInstance(
+								Asn1Object.FromByteArray(c.GetEncoded())));
+					}
+				}
+
+				return certs;
+			}
+			catch (CertificateEncodingException e)
+			{
+				throw new CmsException("error encoding certs", e);
+			}
+			catch (Exception e)
+			{
+				throw new CmsException("error processing certs", e);
+			}
+		}
+
+		public static IList GetCrlsFromStore(
+			IX509Store crlStore)
+		{
+			try
+			{
+                IList crls = Platform.CreateArrayList();
+
+				if (crlStore != null)
+				{
+					foreach (X509Crl c in crlStore.GetMatches(null))
+					{
+						crls.Add(
+							CertificateList.GetInstance(
+								Asn1Object.FromByteArray(c.GetEncoded())));
+					}
+				}
+
+				return crls;
+			}
+			catch (CrlException e)
+			{
+				throw new CmsException("error encoding crls", e);
+			}
+			catch (Exception e)
+			{
+				throw new CmsException("error processing crls", e);
+			}
+		}
+
+		public static Asn1Set CreateBerSetFromList(
+			IList berObjects)
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			foreach (Asn1Encodable ae in berObjects)
+			{
+				v.Add(ae);
+			}
+
+			return new BerSet(v);
+		}
+
+		public static Asn1Set CreateDerSetFromList(
+			IList derObjects)
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			foreach (Asn1Encodable ae in derObjects)
+			{
+				v.Add(ae);
+			}
+
+			return new DerSet(v);
+		}
+
+		internal static Stream CreateBerOctetOutputStream(Stream s, int tagNo, bool isExplicit, int bufferSize)
+		{
+			BerOctetStringGenerator octGen = new BerOctetStringGenerator(s, tagNo, isExplicit);
+			return octGen.GetOctetOutputStream(bufferSize);
+		}
+
+		internal static TbsCertificateStructure GetTbsCertificateStructure(X509Certificate cert)
+		{
+			return TbsCertificateStructure.GetInstance(Asn1Object.FromByteArray(cert.GetTbsCertificate()));
+		}
+
+		internal static IssuerAndSerialNumber GetIssuerAndSerialNumber(X509Certificate cert)
+		{
+			TbsCertificateStructure tbsCert = GetTbsCertificateStructure(cert);
+			return new IssuerAndSerialNumber(tbsCert.Issuer, tbsCert.SerialNumber.Value);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/CounterSignatureDigestCalculator.cs b/BouncyCastle.AxCrypt/src/cms/CounterSignatureDigestCalculator.cs
new file mode 100644
index 0000000..6f8bf65
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/CounterSignatureDigestCalculator.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class CounterSignatureDigestCalculator
+		: IDigestCalculator
+	{
+		private readonly string alg;
+		private readonly byte[] data;
+
+		internal CounterSignatureDigestCalculator(
+			string	alg,
+			byte[]	data)
+		{
+			this.alg = alg;
+			this.data = data;
+		}
+
+		public byte[] GetDigest()
+		{
+			IDigest digest = CmsSignedHelper.Instance.GetDigestInstance(alg);
+			return DigestUtilities.DoFinal(digest, data);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs b/BouncyCastle.AxCrypt/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs
new file mode 100644
index 0000000..d49b1d9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/DefaultAuthenticatedAttributeTableGenerator.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * Default authenticated attributes generator.
+	 */
+	public class DefaultAuthenticatedAttributeTableGenerator
+		: CmsAttributeTableGenerator
+	{
+		private readonly IDictionary table;
+
+		/**
+		 * Initialise to use all defaults
+		 */
+		public DefaultAuthenticatedAttributeTableGenerator()
+		{
+			table = Platform.CreateHashtable();
+		}
+
+		/**
+		 * Initialise with some extra attributes or overrides.
+		 *
+		 * @param attributeTable initial attribute table to use.
+		 */
+		public DefaultAuthenticatedAttributeTableGenerator(
+			AttributeTable attributeTable)
+		{
+			if (attributeTable != null)
+			{
+				table = attributeTable.ToDictionary();
+			}
+			else
+			{
+				table = Platform.CreateHashtable();
+			}
+		}
+
+		/**
+		 * Create a standard attribute table from the passed in parameters - this will
+		 * normally include contentType and messageDigest. If the constructor
+		 * using an AttributeTable was used, entries in it for contentType and
+		 * messageDigest will override the generated ones.
+		 *
+		 * @param parameters source parameters for table generation.
+		 *
+		 * @return a filled in IDictionary of attributes.
+		 */
+		protected virtual IDictionary CreateStandardAttributeTable(
+			IDictionary parameters)
+		{
+            IDictionary std = Platform.CreateHashtable(table);
+
+			if (!std.Contains(CmsAttributes.ContentType))
+            {
+                DerObjectIdentifier contentType = (DerObjectIdentifier)
+                    parameters[CmsAttributeTableParameter.ContentType];
+                Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType,
+                    new DerSet(contentType));
+                std[attr.AttrType] = attr;
+            }
+
+			if (!std.Contains(CmsAttributes.MessageDigest))
+            {
+                byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest];
+                Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
+                    new DerSet(new DerOctetString(messageDigest)));
+                std[attr.AttrType] = attr;
+            }
+
+            return std;
+		}
+
+        /**
+		 * @param parameters source parameters
+		 * @return the populated attribute table
+		 */
+		public virtual AttributeTable GetAttributes(
+			IDictionary parameters)
+		{
+            IDictionary table = CreateStandardAttributeTable(parameters);
+			return new AttributeTable(table);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/DefaultSignedAttributeTableGenerator.cs b/BouncyCastle.AxCrypt/src/cms/DefaultSignedAttributeTableGenerator.cs
new file mode 100644
index 0000000..055de89
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/DefaultSignedAttributeTableGenerator.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * Default signed attributes generator.
+	 */
+	public class DefaultSignedAttributeTableGenerator
+		: CmsAttributeTableGenerator
+	{
+		private readonly IDictionary table;
+
+		/**
+		 * Initialise to use all defaults
+		 */
+		public DefaultSignedAttributeTableGenerator()
+		{
+			table = Platform.CreateHashtable();
+		}
+
+		/**
+		 * Initialise with some extra attributes or overrides.
+		 *
+		 * @param attributeTable initial attribute table to use.
+		 */
+		public DefaultSignedAttributeTableGenerator(
+			AttributeTable attributeTable)
+		{
+			if (attributeTable != null)
+			{
+				table = attributeTable.ToDictionary();
+			}
+			else
+			{
+				table = Platform.CreateHashtable();
+			}
+		}
+
+#if SILVERLIGHT
+		/**
+		 * Create a standard attribute table from the passed in parameters - this will
+		 * normally include contentType, signingTime, and messageDigest. If the constructor
+		 * using an AttributeTable was used, entries in it for contentType, signingTime, and
+		 * messageDigest will override the generated ones.
+		 *
+		 * @param parameters source parameters for table generation.
+		 *
+		 * @return a filled in Hashtable of attributes.
+		 */
+		protected virtual IDictionary createStandardAttributeTable(
+			IDictionary parameters)
+		{
+            IDictionary std = Platform.CreateHashtable(table);
+            DoCreateStandardAttributeTable(parameters, std);
+            return std;
+		}
+#else
+        /**
+		 * Create a standard attribute table from the passed in parameters - this will
+		 * normally include contentType, signingTime, and messageDigest. If the constructor
+		 * using an AttributeTable was used, entries in it for contentType, signingTime, and
+		 * messageDigest will override the generated ones.
+		 *
+		 * @param parameters source parameters for table generation.
+		 *
+		 * @return a filled in Hashtable of attributes.
+		 */
+		protected virtual Hashtable createStandardAttributeTable(
+			IDictionary parameters)
+		{
+            Hashtable std = new Hashtable(table);
+            DoCreateStandardAttributeTable(parameters, std);
+			return std;
+		}
+#endif
+
+        private void DoCreateStandardAttributeTable(IDictionary parameters, IDictionary std)
+        {
+            // contentType will be absent if we're trying to generate a counter signature.
+            if (parameters.Contains(CmsAttributeTableParameter.ContentType))
+            {
+                if (!std.Contains(CmsAttributes.ContentType))
+                {
+                    DerObjectIdentifier contentType = (DerObjectIdentifier)
+                        parameters[CmsAttributeTableParameter.ContentType];
+                    Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.ContentType,
+                        new DerSet(contentType));
+                    std[attr.AttrType] = attr;
+                }
+            }
+
+            if (!std.Contains(CmsAttributes.SigningTime))
+            {
+                Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.SigningTime,
+                    new DerSet(new Time(DateTime.UtcNow)));
+                std[attr.AttrType] = attr;
+            }
+
+            if (!std.Contains(CmsAttributes.MessageDigest))
+            {
+                byte[] messageDigest = (byte[])parameters[CmsAttributeTableParameter.Digest];
+                Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
+                    new DerSet(new DerOctetString(messageDigest)));
+                std[attr.AttrType] = attr;
+            }
+        }
+
+        /**
+		 * @param parameters source parameters
+		 * @return the populated attribute table
+		 */
+		public virtual AttributeTable GetAttributes(
+			IDictionary parameters)
+		{
+            IDictionary table = createStandardAttributeTable(parameters);
+			return new AttributeTable(table);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/DigOutputStream.cs b/BouncyCastle.AxCrypt/src/cms/DigOutputStream.cs
new file mode 100644
index 0000000..103b45c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/DigOutputStream.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class DigOutputStream
+		: BaseOutputStream
+	{
+		private readonly IDigest dig;
+
+		internal DigOutputStream(IDigest dig)
+		{
+			this.dig = dig;
+		}
+
+		public override void WriteByte(byte b)
+		{
+			dig.Update(b);
+		}
+
+		public override void Write(byte[] b, int off, int len)
+		{
+			dig.BlockUpdate(b, off, len);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/IDigestCalculator.cs b/BouncyCastle.AxCrypt/src/cms/IDigestCalculator.cs
new file mode 100644
index 0000000..3661e40
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/IDigestCalculator.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal interface IDigestCalculator
+	{
+		byte[] GetDigest();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KEKRecipientInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/KEKRecipientInfoGenerator.cs
new file mode 100644
index 0000000..a9bedad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KEKRecipientInfoGenerator.cs
@@ -0,0 +1,137 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class KekRecipientInfoGenerator : RecipientInfoGenerator
+	{
+		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+		private KeyParameter	keyEncryptionKey;
+		// TODO Can get this from keyEncryptionKey?		
+		private string			keyEncryptionKeyOID;
+		private KekIdentifier	kekIdentifier;
+
+		// Derived
+		private AlgorithmIdentifier keyEncryptionAlgorithm;
+
+		internal KekRecipientInfoGenerator()
+		{
+		}
+
+		internal KekIdentifier KekIdentifier
+		{
+			set { this.kekIdentifier = value; }
+		}
+
+		internal KeyParameter KeyEncryptionKey
+		{
+			set
+			{
+				this.keyEncryptionKey = value;
+				this.keyEncryptionAlgorithm = DetermineKeyEncAlg(keyEncryptionKeyOID, keyEncryptionKey);
+			}
+		}
+
+		internal string KeyEncryptionKeyOID
+		{
+			set { this.keyEncryptionKeyOID = value; }
+		}
+
+		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+		{
+			byte[] keyBytes = contentEncryptionKey.GetKey();
+
+			IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id);
+			keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
+        	Asn1OctetString encryptedKey = new DerOctetString(
+				keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
+
+			return new RecipientInfo(new KekRecipientInfo(kekIdentifier, keyEncryptionAlgorithm, encryptedKey));
+		}
+
+		private static AlgorithmIdentifier DetermineKeyEncAlg(
+			string algorithm, KeyParameter key)
+		{
+			if (algorithm.StartsWith("DES"))
+			{
+				return new AlgorithmIdentifier(
+					PkcsObjectIdentifiers.IdAlgCms3DesWrap,
+					DerNull.Instance);
+			}
+			else if (algorithm.StartsWith("RC2"))
+			{
+				return new AlgorithmIdentifier(
+					PkcsObjectIdentifiers.IdAlgCmsRC2Wrap,
+					new DerInteger(58));
+			}
+			else if (algorithm.StartsWith("AES"))
+			{
+				int length = key.GetKey().Length * 8;
+				DerObjectIdentifier wrapOid;
+
+				if (length == 128)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes128Wrap;
+				}
+				else if (length == 192)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes192Wrap;
+				}
+				else if (length == 256)
+				{
+					wrapOid = NistObjectIdentifiers.IdAes256Wrap;
+				}
+				else
+				{
+					throw new ArgumentException("illegal keysize in AES");
+				}
+
+				return new AlgorithmIdentifier(wrapOid);  // parameters absent
+			}
+			else if (algorithm.StartsWith("SEED"))
+			{
+				// parameters absent
+				return new AlgorithmIdentifier(KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap);
+			}
+			else if (algorithm.StartsWith("CAMELLIA"))
+			{
+				int length = key.GetKey().Length * 8;
+				DerObjectIdentifier wrapOid;
+
+				if (length == 128)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia128Wrap;
+				}
+				else if (length == 192)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia192Wrap;
+				}
+				else if (length == 256)
+				{
+					wrapOid = NttObjectIdentifiers.IdCamellia256Wrap;
+				}
+				else
+				{
+					throw new ArgumentException("illegal keysize in Camellia");
+				}
+
+				return new AlgorithmIdentifier(wrapOid); // parameters must be absent
+			}
+			else
+			{
+				throw new ArgumentException("unknown algorithm");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KEKRecipientInformation.cs b/BouncyCastle.AxCrypt/src/cms/KEKRecipientInformation.cs
new file mode 100644
index 0000000..f960197
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KEKRecipientInformation.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * the RecipientInfo class for a recipient who has been sent a message
+    * encrypted using a secret key known to the other side.
+    */
+    public class KekRecipientInformation
+        : RecipientInformation
+    {
+        private KekRecipientInfo info;
+
+		internal KekRecipientInformation(
+			KekRecipientInfo	info,
+			CmsSecureReadable	secureReadable)
+			: base(info.KeyEncryptionAlgorithm, secureReadable)
+		{
+            this.info = info;
+            this.rid = new RecipientID();
+
+			KekIdentifier kekId = info.KekID;
+
+			rid.KeyIdentifier = kekId.KeyIdentifier.GetOctets();
+        }
+
+		/**
+        * decrypt the content and return an input stream.
+        */
+        public override CmsTypedStream GetContentStream(
+            ICipherParameters key)
+        {
+			try
+			{
+				byte[] encryptedKey = info.EncryptedKey.GetOctets();
+				IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyEncAlg.ObjectID.Id);
+
+				keyWrapper.Init(false, key);
+
+				KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
+					GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
+
+				return GetContentFromSessionKey(sKey);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInfoGenerator.cs
new file mode 100644
index 0000000..4fafb7c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInfoGenerator.cs
@@ -0,0 +1,171 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Cms.Ecc;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class KeyAgreeRecipientInfoGenerator : RecipientInfoGenerator
+	{
+		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+		private DerObjectIdentifier			keyAgreementOID;
+		private DerObjectIdentifier			keyEncryptionOID;
+		private IList					    recipientCerts;
+		private AsymmetricCipherKeyPair		senderKeyPair;
+
+		internal KeyAgreeRecipientInfoGenerator()
+		{
+		}
+
+		internal DerObjectIdentifier KeyAgreementOID
+		{
+			set { this.keyAgreementOID = value; }
+		}
+
+		internal DerObjectIdentifier KeyEncryptionOID
+		{
+			set { this.keyEncryptionOID = value; }
+		}
+
+		internal ICollection RecipientCerts
+		{
+			set { this.recipientCerts = Platform.CreateArrayList(value); }
+		}
+
+		internal AsymmetricCipherKeyPair SenderKeyPair
+		{
+			set { this.senderKeyPair = value; }
+		}
+
+		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+		{
+			byte[] keyBytes = contentEncryptionKey.GetKey();
+
+			AsymmetricKeyParameter senderPublicKey = senderKeyPair.Public;
+			ICipherParameters senderPrivateParams = senderKeyPair.Private;
+
+
+			OriginatorIdentifierOrKey originator;
+			try
+			{
+				originator = new OriginatorIdentifierOrKey(
+					CreateOriginatorPublicKey(senderPublicKey));
+			}
+			catch (IOException e)
+			{
+				throw new InvalidKeyException("cannot extract originator public key: " + e);
+			}
+
+
+			Asn1OctetString ukm = null;
+			if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
+			{
+				try
+				{
+					IAsymmetricCipherKeyPairGenerator ephemKPG =
+						GeneratorUtilities.GetKeyPairGenerator(keyAgreementOID);
+					ephemKPG.Init(
+						((ECPublicKeyParameters)senderPublicKey).CreateKeyGenerationParameters(random));
+
+					AsymmetricCipherKeyPair ephemKP = ephemKPG.GenerateKeyPair();
+
+					ukm = new DerOctetString(
+						new MQVuserKeyingMaterial(
+							CreateOriginatorPublicKey(ephemKP.Public), null));
+
+					senderPrivateParams = new MqvPrivateParameters(
+						(ECPrivateKeyParameters)senderPrivateParams,
+						(ECPrivateKeyParameters)ephemKP.Private,
+						(ECPublicKeyParameters)ephemKP.Public);
+				}
+				catch (IOException e)
+				{
+					throw new InvalidKeyException("cannot extract MQV ephemeral public key: " + e);
+				}
+				catch (SecurityUtilityException e)
+				{
+					throw new InvalidKeyException("cannot determine MQV ephemeral key pair parameters from public key: " + e);
+				}
+			}
+
+
+			DerSequence paramSeq = new DerSequence(
+				keyEncryptionOID,
+				DerNull.Instance);
+			AlgorithmIdentifier keyEncAlg = new AlgorithmIdentifier(keyAgreementOID, paramSeq);
+
+
+			Asn1EncodableVector recipientEncryptedKeys = new Asn1EncodableVector();
+			foreach (X509Certificate recipientCert in recipientCerts)
+			{
+				TbsCertificateStructure tbsCert;
+				try
+				{
+					tbsCert = TbsCertificateStructure.GetInstance(
+						Asn1Object.FromByteArray(recipientCert.GetTbsCertificate()));
+				}
+				catch (Exception)
+				{
+					throw new ArgumentException("can't extract TBS structure from certificate");
+				}
+
+				// TODO Should there be a SubjectKeyIdentifier-based alternative?
+				IssuerAndSerialNumber issuerSerial = new IssuerAndSerialNumber(
+					tbsCert.Issuer, tbsCert.SerialNumber.Value);
+				KeyAgreeRecipientIdentifier karid = new KeyAgreeRecipientIdentifier(issuerSerial);
+
+				ICipherParameters recipientPublicParams = recipientCert.GetPublicKey();
+				if (keyAgreementOID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
+				{
+					recipientPublicParams = new MqvPublicParameters(
+						(ECPublicKeyParameters)recipientPublicParams,
+						(ECPublicKeyParameters)recipientPublicParams);
+				}
+
+				// Use key agreement to choose a wrap key for this recipient
+				IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreementWithKdf(
+					keyAgreementOID, keyEncryptionOID.Id);
+				keyAgreement.Init(new ParametersWithRandom(senderPrivateParams, random));
+				BigInteger agreedValue = keyAgreement.CalculateAgreement(recipientPublicParams);
+
+				int keyEncryptionKeySize = GeneratorUtilities.GetDefaultKeySize(keyEncryptionOID) / 8;
+				byte[] keyEncryptionKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, keyEncryptionKeySize);
+				KeyParameter keyEncryptionKey = ParameterUtilities.CreateKeyParameter(
+					keyEncryptionOID, keyEncryptionKeyBytes);
+
+				// Wrap the content encryption key with the agreement key
+				IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionOID.Id);
+				keyWrapper.Init(true, new ParametersWithRandom(keyEncryptionKey, random));
+				byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
+
+	        	Asn1OctetString encryptedKey = new DerOctetString(encryptedKeyBytes);
+
+				recipientEncryptedKeys.Add(new RecipientEncryptedKey(karid, encryptedKey));
+			}
+
+			return new RecipientInfo(new KeyAgreeRecipientInfo(originator, ukm, keyEncAlg,
+				new DerSequence(recipientEncryptedKeys)));
+		}
+
+		private static OriginatorPublicKey CreateOriginatorPublicKey(
+			AsymmetricKeyParameter publicKey)
+		{
+			SubjectPublicKeyInfo spki = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+			return new OriginatorPublicKey(
+				new AlgorithmIdentifier(spki.AlgorithmID.ObjectID, DerNull.Instance),
+				spki.PublicKeyData.GetBytes());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInformation.cs b/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInformation.cs
new file mode 100644
index 0000000..8e006e5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KeyAgreeRecipientInformation.cs
@@ -0,0 +1,226 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Cms.Ecc;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * the RecipientInfo class for a recipient who has been sent a message
+    * encrypted using key agreement.
+    */
+    public class KeyAgreeRecipientInformation
+        : RecipientInformation
+    {
+        private KeyAgreeRecipientInfo info;
+        private Asn1OctetString       encryptedKey;
+
+        internal static void ReadRecipientInfo(IList infos, KeyAgreeRecipientInfo info,
+            CmsSecureReadable secureReadable)
+        {
+            try
+            {
+                foreach (Asn1Encodable rek in info.RecipientEncryptedKeys)
+                {
+                    RecipientEncryptedKey id = RecipientEncryptedKey.GetInstance(rek.ToAsn1Object());
+
+                    RecipientID rid = new RecipientID();
+
+                    Asn1.Cms.KeyAgreeRecipientIdentifier karid = id.Identifier;
+
+                    Asn1.Cms.IssuerAndSerialNumber iAndSN = karid.IssuerAndSerialNumber;
+                    if (iAndSN != null)
+                    {
+                        rid.Issuer = iAndSN.Name;
+                        rid.SerialNumber = iAndSN.SerialNumber.Value;
+                    }
+                    else
+                    {
+                        Asn1.Cms.RecipientKeyIdentifier rKeyID = karid.RKeyID;
+
+                        // Note: 'date' and 'other' fields of RecipientKeyIdentifier appear to be only informational 
+
+                        rid.SubjectKeyIdentifier = rKeyID.SubjectKeyIdentifier.GetOctets();
+                    }
+
+                    infos.Add(new KeyAgreeRecipientInformation(info, rid, id.EncryptedKey,
+                        secureReadable));
+                }
+            }
+            catch (IOException e)
+            {
+                throw new ArgumentException("invalid rid in KeyAgreeRecipientInformation", e);
+            }
+        }
+
+        internal KeyAgreeRecipientInformation(
+            KeyAgreeRecipientInfo	info,
+            RecipientID				rid,
+            Asn1OctetString			encryptedKey,
+            CmsSecureReadable		secureReadable)
+            : base(info.KeyEncryptionAlgorithm, secureReadable)
+        {
+            this.info = info;
+            this.rid = rid;
+            this.encryptedKey = encryptedKey;
+        }
+
+        private AsymmetricKeyParameter GetSenderPublicKey(
+            AsymmetricKeyParameter		receiverPrivateKey,
+            OriginatorIdentifierOrKey	originator)
+        {
+            OriginatorPublicKey opk = originator.OriginatorPublicKey;
+            if (opk != null)
+            {
+                return GetPublicKeyFromOriginatorPublicKey(receiverPrivateKey, opk);
+            }
+            
+            OriginatorID origID = new OriginatorID();
+            
+            Asn1.Cms.IssuerAndSerialNumber iAndSN = originator.IssuerAndSerialNumber;
+            if (iAndSN != null)
+            {
+                origID.Issuer = iAndSN.Name;
+                origID.SerialNumber = iAndSN.SerialNumber.Value;
+            }
+            else
+            {
+                SubjectKeyIdentifier ski = originator.SubjectKeyIdentifier;
+
+                origID.SubjectKeyIdentifier = ski.GetKeyIdentifier();
+            }
+
+            return GetPublicKeyFromOriginatorID(origID);
+        }
+
+        private AsymmetricKeyParameter GetPublicKeyFromOriginatorPublicKey(
+            AsymmetricKeyParameter	receiverPrivateKey,
+            OriginatorPublicKey		originatorPublicKey)
+        {
+            PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(receiverPrivateKey);
+            SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(
+                privInfo.PrivateKeyAlgorithm,
+                originatorPublicKey.PublicKey.GetBytes());
+            return PublicKeyFactory.CreateKey(pubInfo);
+        }
+
+        private AsymmetricKeyParameter GetPublicKeyFromOriginatorID(
+            OriginatorID origID)
+        {
+            // TODO Support all alternatives for OriginatorIdentifierOrKey
+            // see RFC 3852 6.2.2
+            throw new CmsException("No support for 'originator' as IssuerAndSerialNumber or SubjectKeyIdentifier");
+        }
+
+        private KeyParameter CalculateAgreedWrapKey(
+            string					wrapAlg,
+            AsymmetricKeyParameter	senderPublicKey,
+            AsymmetricKeyParameter	receiverPrivateKey)
+        {
+            DerObjectIdentifier agreeAlgID = keyEncAlg.ObjectID;
+
+            ICipherParameters senderPublicParams = senderPublicKey;
+            ICipherParameters receiverPrivateParams = receiverPrivateKey;
+
+            if (agreeAlgID.Id.Equals(CmsEnvelopedGenerator.ECMqvSha1Kdf))
+            {
+                byte[] ukmEncoding = info.UserKeyingMaterial.GetOctets();
+                MQVuserKeyingMaterial ukm = MQVuserKeyingMaterial.GetInstance(
+                    Asn1Object.FromByteArray(ukmEncoding));
+
+                AsymmetricKeyParameter ephemeralKey = GetPublicKeyFromOriginatorPublicKey(
+                    receiverPrivateKey, ukm.EphemeralPublicKey);
+
+                senderPublicParams = new MqvPublicParameters(
+                    (ECPublicKeyParameters)senderPublicParams,
+                    (ECPublicKeyParameters)ephemeralKey);
+                receiverPrivateParams = new MqvPrivateParameters(
+                    (ECPrivateKeyParameters)receiverPrivateParams,
+                    (ECPrivateKeyParameters)receiverPrivateParams);
+            }
+
+            IBasicAgreement agreement = AgreementUtilities.GetBasicAgreementWithKdf(
+                agreeAlgID, wrapAlg);
+            agreement.Init(receiverPrivateParams);
+            BigInteger agreedValue = agreement.CalculateAgreement(senderPublicParams);
+
+            int wrapKeySize = GeneratorUtilities.GetDefaultKeySize(wrapAlg) / 8;
+            byte[] wrapKeyBytes = X9IntegerConverter.IntegerToBytes(agreedValue, wrapKeySize);
+            return ParameterUtilities.CreateKeyParameter(wrapAlg, wrapKeyBytes);
+        }
+
+        private KeyParameter UnwrapSessionKey(
+            string			wrapAlg,
+            KeyParameter	agreedKey)
+        {
+            byte[] encKeyOctets = encryptedKey.GetOctets();
+
+            IWrapper keyCipher = WrapperUtilities.GetWrapper(wrapAlg);
+            keyCipher.Init(false, agreedKey);
+            byte[] sKeyBytes = keyCipher.Unwrap(encKeyOctets, 0, encKeyOctets.Length);
+            return ParameterUtilities.CreateKeyParameter(GetContentAlgorithmName(), sKeyBytes);
+        }
+
+        internal KeyParameter GetSessionKey(
+            AsymmetricKeyParameter receiverPrivateKey)
+        {
+            try
+            {
+                string wrapAlg = DerObjectIdentifier.GetInstance(
+                    Asn1Sequence.GetInstance(keyEncAlg.Parameters)[0]).Id;
+
+                AsymmetricKeyParameter senderPublicKey = GetSenderPublicKey(
+                    receiverPrivateKey, info.Originator);
+
+                KeyParameter agreedWrapKey = CalculateAgreedWrapKey(wrapAlg,
+                    senderPublicKey, receiverPrivateKey);
+
+                return UnwrapSessionKey(wrapAlg, agreedWrapKey);
+            }
+            catch (SecurityUtilityException e)
+            {
+                throw new CmsException("couldn't create cipher.", e);
+            }
+            catch (InvalidKeyException e)
+            {
+                throw new CmsException("key invalid in message.", e);
+            }
+            catch (Exception e)
+            {
+                throw new CmsException("originator key invalid.", e);
+            }
+        }
+
+        /**
+        * decrypt the content and return an input stream.
+        */
+        public override CmsTypedStream GetContentStream(
+            ICipherParameters key)
+        {
+            if (!(key is AsymmetricKeyParameter))
+                throw new ArgumentException("KeyAgreement requires asymmetric key", "key");
+
+            AsymmetricKeyParameter receiverPrivateKey = (AsymmetricKeyParameter) key;
+
+            if (!receiverPrivateKey.IsPrivate)
+                throw new ArgumentException("Expected private key", "key");
+
+            KeyParameter sKey = GetSessionKey(receiverPrivateKey);
+
+            return GetContentFromSessionKey(sKey);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInfoGenerator.cs
new file mode 100644
index 0000000..0992e6d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInfoGenerator.cs
@@ -0,0 +1,87 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class KeyTransRecipientInfoGenerator : RecipientInfoGenerator
+	{
+		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+		private TbsCertificateStructure	recipientTbsCert;
+		private AsymmetricKeyParameter	recipientPublicKey;
+		private Asn1OctetString			subjectKeyIdentifier;
+
+		// Derived fields
+		private SubjectPublicKeyInfo info;
+
+		internal KeyTransRecipientInfoGenerator()
+		{
+		}
+
+		internal X509Certificate RecipientCert
+		{
+			set
+			{
+				this.recipientTbsCert = CmsUtilities.GetTbsCertificateStructure(value);
+				this.recipientPublicKey = value.GetPublicKey();
+				this.info = recipientTbsCert.SubjectPublicKeyInfo;
+			}
+		}
+		
+		internal AsymmetricKeyParameter RecipientPublicKey
+		{
+			set
+			{
+				this.recipientPublicKey = value;
+
+				try
+				{
+					info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
+						recipientPublicKey);
+				}
+				catch (IOException)
+				{
+					throw new ArgumentException("can't extract key algorithm from this key");
+				}
+			}
+		}
+		
+		internal Asn1OctetString SubjectKeyIdentifier
+		{
+			set { this.subjectKeyIdentifier = value; }
+		}
+
+		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+		{
+			byte[] keyBytes = contentEncryptionKey.GetKey();
+			AlgorithmIdentifier keyEncryptionAlgorithm = info.AlgorithmID;
+
+			IWrapper keyWrapper = Helper.CreateWrapper(keyEncryptionAlgorithm.ObjectID.Id);
+			keyWrapper.Init(true, new ParametersWithRandom(recipientPublicKey, random));
+			byte[] encryptedKeyBytes = keyWrapper.Wrap(keyBytes, 0, keyBytes.Length);
+
+			RecipientIdentifier recipId;
+			if (recipientTbsCert != null)
+			{
+				IssuerAndSerialNumber issuerAndSerial = new IssuerAndSerialNumber(
+					recipientTbsCert.Issuer, recipientTbsCert.SerialNumber.Value);
+				recipId = new RecipientIdentifier(issuerAndSerial);
+			}
+			else
+			{
+				recipId = new RecipientIdentifier(subjectKeyIdentifier);
+			}
+
+			return new RecipientInfo(new KeyTransRecipientInfo(recipId, keyEncryptionAlgorithm,
+				new DerOctetString(encryptedKeyBytes)));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInformation.cs b/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInformation.cs
new file mode 100644
index 0000000..24121cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/KeyTransRecipientInformation.cs
@@ -0,0 +1,113 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Asn1Pkcs = Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * the KeyTransRecipientInformation class for a recipient who has been sent a secret
+    * key encrypted using their public key that needs to be used to
+    * extract the message.
+    */
+    public class KeyTransRecipientInformation
+        : RecipientInformation
+    {
+        private KeyTransRecipientInfo info;
+
+		internal KeyTransRecipientInformation(
+			KeyTransRecipientInfo	info,
+			CmsSecureReadable		secureReadable)
+			: base(info.KeyEncryptionAlgorithm, secureReadable)
+		{
+            this.info = info;
+            this.rid = new RecipientID();
+
+			RecipientIdentifier r = info.RecipientIdentifier;
+
+			try
+            {
+                if (r.IsTagged)
+                {
+                    Asn1OctetString octs = Asn1OctetString.GetInstance(r.ID);
+
+					rid.SubjectKeyIdentifier = octs.GetOctets();
+                }
+                else
+                {
+                    IssuerAndSerialNumber iAnds = IssuerAndSerialNumber.GetInstance(r.ID);
+
+					rid.Issuer = iAnds.Name;
+                    rid.SerialNumber = iAnds.SerialNumber.Value;
+                }
+            }
+            catch (IOException)
+            {
+                throw new ArgumentException("invalid rid in KeyTransRecipientInformation");
+            }
+        }
+
+		private string GetExchangeEncryptionAlgorithmName(
+			DerObjectIdentifier oid)
+		{
+			if (Asn1Pkcs.PkcsObjectIdentifiers.RsaEncryption.Equals(oid))
+			{
+				return "RSA//PKCS1Padding";
+			}
+
+			return oid.Id;
+		}
+
+		internal KeyParameter UnwrapKey(ICipherParameters key)
+		{
+			byte[] encryptedKey = info.EncryptedKey.GetOctets();
+			string keyExchangeAlgorithm = GetExchangeEncryptionAlgorithmName(keyEncAlg.ObjectID);
+
+			try
+			{
+				IWrapper keyWrapper = WrapperUtilities.GetWrapper(keyExchangeAlgorithm);
+				keyWrapper.Init(false, key);
+
+				// FIXME Support for MAC algorithm parameters similar to cipher parameters
+				return ParameterUtilities.CreateKeyParameter(
+					GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+//			catch (IllegalBlockSizeException e)
+			catch (DataLengthException e)
+			{
+				throw new CmsException("illegal blocksize in message.", e);
+			}
+//			catch (BadPaddingException e)
+			catch (InvalidCipherTextException e)
+			{
+				throw new CmsException("bad padding in message.", e);
+			}
+		}
+		
+		/**
+        * decrypt the content and return it as a byte array.
+        */
+        public override CmsTypedStream GetContentStream(
+            ICipherParameters key)
+        {
+			KeyParameter sKey = UnwrapKey(key);
+
+			return GetContentFromSessionKey(sKey);
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/MacOutputStream.cs b/BouncyCastle.AxCrypt/src/cms/MacOutputStream.cs
new file mode 100644
index 0000000..8891dbc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/MacOutputStream.cs
@@ -0,0 +1,28 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class MacOutputStream
+		: BaseOutputStream
+	{
+		private readonly IMac mac;
+
+		internal MacOutputStream(IMac mac)
+		{
+			this.mac = mac;
+		}
+
+		public override void Write(byte[] b, int off, int len)
+		{
+			mac.BlockUpdate(b, off, len);
+		}
+
+		public override void WriteByte(byte b)
+		{
+			mac.Update(b);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/NullOutputStream.cs b/BouncyCastle.AxCrypt/src/cms/NullOutputStream.cs
new file mode 100644
index 0000000..ed937bd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/NullOutputStream.cs
@@ -0,0 +1,20 @@
+using System;
+
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class NullOutputStream
+		: BaseOutputStream
+	{
+		public override void WriteByte(byte b)
+		{
+			// do nothing
+		}
+
+		public override void Write(byte[] buffer, int offset, int count)
+		{
+			// do nothing
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/OriginatorId.cs b/BouncyCastle.AxCrypt/src/cms/OriginatorId.cs
new file mode 100644
index 0000000..5a3b737
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/OriginatorId.cs
@@ -0,0 +1,51 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * a basic index for an originator.
+    */
+    public class OriginatorID
+        : X509CertStoreSelector
+    {
+        public override int GetHashCode()
+        {
+            int code = Arrays.GetHashCode(this.SubjectKeyIdentifier);
+
+			BigInteger serialNumber = this.SerialNumber;
+			if (serialNumber != null)
+            {
+                code ^= serialNumber.GetHashCode();
+            }
+
+			X509Name issuer = this.Issuer;
+            if (issuer != null)
+            {
+                code ^= issuer.GetHashCode();
+            }
+
+			return code;
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return false;
+
+			OriginatorID id = obj as OriginatorID;
+
+			if (id == null)
+				return false;
+
+			return Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier)
+				&& Platform.Equals(SerialNumber, id.SerialNumber)
+				&& IssuersMatch(Issuer, id.Issuer);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/OriginatorInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/OriginatorInfoGenerator.cs
new file mode 100644
index 0000000..6bf1087
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/OriginatorInfoGenerator.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    public class OriginatorInfoGenerator
+    {
+        private readonly IList origCerts;
+        private readonly IList origCrls;
+
+        public OriginatorInfoGenerator(X509Certificate origCert)
+        {
+            this.origCerts = Platform.CreateArrayList(1);
+            this.origCrls = null;
+            origCerts.Add(origCert.CertificateStructure);
+        }
+
+        public OriginatorInfoGenerator(IX509Store origCerts)
+            : this(origCerts, null)
+        {
+        }
+
+        public OriginatorInfoGenerator(IX509Store origCerts, IX509Store origCrls)
+        {
+            this.origCerts = CmsUtilities.GetCertificatesFromStore(origCerts);
+            this.origCrls = origCrls == null ? null : CmsUtilities.GetCrlsFromStore(origCrls);
+        }
+
+        public virtual OriginatorInfo Generate()
+        {
+            Asn1Set certSet = CmsUtilities.CreateDerSetFromList(origCerts);
+            Asn1Set crlSet = origCrls == null ? null : CmsUtilities.CreateDerSetFromList(origCrls);
+            return new OriginatorInfo(certSet, crlSet);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/OriginatorInformation.cs b/BouncyCastle.AxCrypt/src/cms/OriginatorInformation.cs
new file mode 100644
index 0000000..618add6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/OriginatorInformation.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class OriginatorInformation
+	{
+		private readonly OriginatorInfo originatorInfo;
+
+		internal OriginatorInformation(OriginatorInfo originatorInfo)
+		{
+			this.originatorInfo = originatorInfo;
+		}
+
+		/**
+		* Return the certificates stored in the underlying OriginatorInfo object.
+		*
+		* @return a Store of X509CertificateHolder objects.
+		*/
+		public virtual IX509Store GetCertificates()
+		{
+			Asn1Set certSet = originatorInfo.Certificates;
+
+			if (certSet != null)
+			{
+				IList certList = Platform.CreateArrayList(certSet.Count);
+
+				foreach (Asn1Encodable enc in certSet)
+				{
+					Asn1Object obj = enc.ToAsn1Object();
+					if (obj is Asn1Sequence)
+					{
+						certList.Add(new X509Certificate(X509CertificateStructure.GetInstance(obj)));
+					}
+				}
+
+				return X509StoreFactory.Create(
+					"Certificate/Collection",
+					new X509CollectionStoreParameters(certList));
+			}
+
+			return X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(Platform.CreateArrayList()));
+		}
+
+		/**
+		* Return the CRLs stored in the underlying OriginatorInfo object.
+		*
+		* @return a Store of X509CRLHolder objects.
+		*/
+		public virtual IX509Store GetCrls()
+		{
+			Asn1Set crlSet = originatorInfo.Certificates;
+
+			if (crlSet != null)
+			{
+                IList crlList = Platform.CreateArrayList(crlSet.Count);
+
+				foreach (Asn1Encodable enc in crlSet)
+				{
+					Asn1Object obj = enc.ToAsn1Object();
+					if (obj is Asn1Sequence)
+					{
+						crlList.Add(new X509Crl(CertificateList.GetInstance(obj)));
+					}
+				}
+
+				return X509StoreFactory.Create(
+					"CRL/Collection",
+					new X509CollectionStoreParameters(crlList));
+			}
+
+			return X509StoreFactory.Create(
+				"CRL/Collection",
+                new X509CollectionStoreParameters(Platform.CreateArrayList()));
+		}
+
+		/**
+		* Return the underlying ASN.1 object defining this SignerInformation object.
+		*
+		* @return a OriginatorInfo.
+		*/
+		public virtual OriginatorInfo ToAsn1Structure()
+		{
+			return originatorInfo;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2PBEKey.cs b/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2PBEKey.cs
new file mode 100644
index 0000000..08b8518
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2PBEKey.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+	/// <summary>
+	/// PKCS5 scheme-2 - password converted to bytes assuming ASCII.
+	/// </summary>
+	public class Pkcs5Scheme2PbeKey
+		: CmsPbeKey
+	{
+		[Obsolete("Use version taking 'char[]' instead")]
+		public Pkcs5Scheme2PbeKey(
+			string	password,
+			byte[]	salt,
+			int		iterationCount)
+			: this(password.ToCharArray(), salt, iterationCount)
+		{
+		}
+
+		[Obsolete("Use version taking 'char[]' instead")]
+		public Pkcs5Scheme2PbeKey(
+			string				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+			: this(password.ToCharArray(), keyDerivationAlgorithm)
+		{
+		}
+		
+		public Pkcs5Scheme2PbeKey(
+			char[]	password,
+			byte[]	salt,
+			int		iterationCount)
+			: base(password, salt, iterationCount)
+		{
+		}
+
+		public Pkcs5Scheme2PbeKey(
+			char[]				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+			: base(password, keyDerivationAlgorithm)
+		{
+		}
+
+		internal override KeyParameter GetEncoded(
+			string algorithmOid)
+		{
+			Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
+
+			gen.Init(
+				PbeParametersGenerator.Pkcs5PasswordToBytes(password),
+				salt,
+				iterationCount);
+
+			return (KeyParameter) gen.GenerateDerivedParameters(
+				algorithmOid,
+				CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2UTF8PBEKey.cs b/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2UTF8PBEKey.cs
new file mode 100644
index 0000000..7aecc29
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/PKCS5Scheme2UTF8PBEKey.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * PKCS5 scheme-2 - password converted to bytes using UTF-8.
+	 */
+	public class Pkcs5Scheme2Utf8PbeKey
+		: CmsPbeKey
+	{
+		[Obsolete("Use version taking 'char[]' instead")]
+		public Pkcs5Scheme2Utf8PbeKey(
+			string	password,
+			byte[]	salt,
+			int		iterationCount)
+			: this(password.ToCharArray(), salt, iterationCount)
+		{
+		}
+
+		[Obsolete("Use version taking 'char[]' instead")]
+		public Pkcs5Scheme2Utf8PbeKey(
+			string				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+			: this(password.ToCharArray(), keyDerivationAlgorithm)
+		{
+		}
+
+		public Pkcs5Scheme2Utf8PbeKey(
+			char[]	password,
+			byte[]	salt,
+			int		iterationCount)
+			: base(password, salt, iterationCount)
+		{
+		}
+
+		public Pkcs5Scheme2Utf8PbeKey(
+			char[]				password,
+			AlgorithmIdentifier keyDerivationAlgorithm)
+			: base(password, keyDerivationAlgorithm)
+		{
+		}
+
+		internal override KeyParameter GetEncoded(
+			string algorithmOid)
+		{
+			Pkcs5S2ParametersGenerator gen = new Pkcs5S2ParametersGenerator();
+
+			gen.Init(
+				PbeParametersGenerator.Pkcs5PasswordToUtf8Bytes(password),
+				salt,
+				iterationCount);
+
+			return (KeyParameter) gen.GenerateDerivedParameters(
+				algorithmOid,
+				CmsEnvelopedHelper.Instance.GetKeySize(algorithmOid));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInfoGenerator.cs
new file mode 100644
index 0000000..0a0b27b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInfoGenerator.cs
@@ -0,0 +1,69 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class PasswordRecipientInfoGenerator : RecipientInfoGenerator
+	{
+		private static readonly CmsEnvelopedHelper Helper = CmsEnvelopedHelper.Instance;
+
+		private AlgorithmIdentifier	keyDerivationAlgorithm;
+		private KeyParameter		keyEncryptionKey;
+		// TODO Can get this from keyEncryptionKey?		
+		private string				keyEncryptionKeyOID;
+
+		internal PasswordRecipientInfoGenerator()
+		{
+		}
+
+		internal AlgorithmIdentifier KeyDerivationAlgorithm
+		{
+			set { this.keyDerivationAlgorithm = value; }
+		}
+
+		internal KeyParameter KeyEncryptionKey
+		{
+			set { this.keyEncryptionKey = value; }
+		}
+
+		internal string KeyEncryptionKeyOID
+		{
+			set { this.keyEncryptionKeyOID = value; }
+		}
+
+		public RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random)
+		{
+			byte[] keyBytes = contentEncryptionKey.GetKey();
+
+			string rfc3211WrapperName = Helper.GetRfc3211WrapperName(keyEncryptionKeyOID);
+			IWrapper keyWrapper = Helper.CreateWrapper(rfc3211WrapperName);
+
+			// Note: In Java build, the IV is automatically generated in JCE layer
+			int ivLength = rfc3211WrapperName.StartsWith("DESEDE") ? 8 : 16;
+			byte[] iv = new byte[ivLength];
+			random.NextBytes(iv);
+
+			ICipherParameters parameters = new ParametersWithIV(keyEncryptionKey, iv);
+			keyWrapper.Init(true, new ParametersWithRandom(parameters, random));
+        	Asn1OctetString encryptedKey = new DerOctetString(
+				keyWrapper.Wrap(keyBytes, 0, keyBytes.Length));
+
+			DerSequence seq = new DerSequence(
+				new DerObjectIdentifier(keyEncryptionKeyOID),
+				new DerOctetString(iv));
+
+			AlgorithmIdentifier keyEncryptionAlgorithm = new AlgorithmIdentifier(
+				PkcsObjectIdentifiers.IdAlgPwriKek, seq);
+
+			return new RecipientInfo(new PasswordRecipientInfo(
+				keyDerivationAlgorithm, keyEncryptionAlgorithm, encryptedKey));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInformation.cs b/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInformation.cs
new file mode 100644
index 0000000..f629cab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/PasswordRecipientInformation.cs
@@ -0,0 +1,79 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * the RecipientInfo class for a recipient who has been sent a message
+	 * encrypted using a password.
+	 */
+	public class PasswordRecipientInformation
+		: RecipientInformation
+	{
+		private readonly PasswordRecipientInfo	info;
+
+		internal PasswordRecipientInformation(
+			PasswordRecipientInfo	info,
+			CmsSecureReadable		secureReadable)
+			: base(info.KeyEncryptionAlgorithm, secureReadable)
+		{
+			this.info = info;
+			this.rid = new RecipientID();
+		}
+
+		/**
+		 * return the object identifier for the key derivation algorithm, or null
+		 * if there is none present.
+		 *
+		 * @return OID for key derivation algorithm, if present.
+		 */
+		public virtual AlgorithmIdentifier KeyDerivationAlgorithm
+		{
+			get { return info.KeyDerivationAlgorithm; }
+		}
+
+		/**
+		 * decrypt the content and return an input stream.
+		 */
+		public override CmsTypedStream GetContentStream(
+			ICipherParameters key)
+		{
+			try
+			{
+				AlgorithmIdentifier kekAlg = AlgorithmIdentifier.GetInstance(info.KeyEncryptionAlgorithm);
+				Asn1Sequence        kekAlgParams = (Asn1Sequence)kekAlg.Parameters;
+				byte[]              encryptedKey = info.EncryptedKey.GetOctets();
+				string              kekAlgName = DerObjectIdentifier.GetInstance(kekAlgParams[0]).Id;
+				string				cName = CmsEnvelopedHelper.Instance.GetRfc3211WrapperName(kekAlgName);
+				IWrapper			keyWrapper = WrapperUtilities.GetWrapper(cName);
+
+				byte[] iv = Asn1OctetString.GetInstance(kekAlgParams[1]).GetOctets();
+
+				ICipherParameters parameters = ((CmsPbeKey)key).GetEncoded(kekAlgName);
+				parameters = new ParametersWithIV(parameters, iv);
+
+				keyWrapper.Init(false, parameters);
+
+				KeyParameter sKey = ParameterUtilities.CreateKeyParameter(
+					GetContentAlgorithmName(), keyWrapper.Unwrap(encryptedKey, 0, encryptedKey.Length));
+
+				return GetContentFromSessionKey(sKey);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new CmsException("couldn't create cipher.", e);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key invalid in message.", e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/RecipientId.cs b/BouncyCastle.AxCrypt/src/cms/RecipientId.cs
new file mode 100644
index 0000000..9b6eb09
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/RecipientId.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    public class RecipientID
+        : X509CertStoreSelector
+    {
+        private byte[] keyIdentifier;
+
+		public byte[] KeyIdentifier
+		{
+			get { return Arrays.Clone(keyIdentifier); }
+			set { keyIdentifier = Arrays.Clone(value); }
+		}
+
+		public override int GetHashCode()
+        {
+            int code = Arrays.GetHashCode(keyIdentifier)
+				^ Arrays.GetHashCode(this.SubjectKeyIdentifier);
+
+			BigInteger serialNumber = this.SerialNumber;
+			if (serialNumber != null)
+            {
+                code ^= serialNumber.GetHashCode();
+            }
+
+			X509Name issuer = this.Issuer;
+            if (issuer != null)
+            {
+                code ^= issuer.GetHashCode();
+            }
+
+            return code;
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return true;
+
+			RecipientID id = obj as RecipientID;
+
+			if (id == null)
+				return false;
+
+			return Arrays.AreEqual(keyIdentifier, id.keyIdentifier)
+				&& Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier)
+				&& Platform.Equals(SerialNumber, id.SerialNumber)
+				&& IssuersMatch(Issuer, id.Issuer);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/RecipientInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/RecipientInfoGenerator.cs
new file mode 100644
index 0000000..c41db61
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/RecipientInfoGenerator.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	interface RecipientInfoGenerator
+	{
+		/// <summary>
+		/// Generate a RecipientInfo object for the given key.
+		/// </summary>
+		/// <param name="contentEncryptionKey">
+		/// A <see cref="KeyParameter"/>
+		/// </param>
+		/// <param name="random">
+		/// A <see cref="SecureRandom"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="RecipientInfo"/>
+		/// </returns>
+		/// <exception cref="GeneralSecurityException"></exception>
+		RecipientInfo Generate(KeyParameter contentEncryptionKey, SecureRandom random);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/RecipientInformation.cs b/BouncyCastle.AxCrypt/src/cms/RecipientInformation.cs
new file mode 100644
index 0000000..8b0316b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/RecipientInformation.cs
@@ -0,0 +1,126 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Cms
+{
+    public abstract class RecipientInformation
+    {
+		internal RecipientID			rid = new RecipientID();
+		internal AlgorithmIdentifier	keyEncAlg;
+		internal CmsSecureReadable		secureReadable;
+		
+		private byte[] resultMac;
+
+		internal RecipientInformation(
+			AlgorithmIdentifier	keyEncAlg,
+			CmsSecureReadable	secureReadable)
+		{
+			this.keyEncAlg = keyEncAlg;
+			this.secureReadable = secureReadable;
+		}
+
+		internal string GetContentAlgorithmName()
+		{
+			AlgorithmIdentifier algorithm = secureReadable.Algorithm;
+//			return CmsEnvelopedHelper.Instance.GetSymmetricCipherName(algorithm.ObjectID.Id);
+			return algorithm.ObjectID.Id;
+		}
+
+		public RecipientID RecipientID
+        {
+			get { return rid; }
+        }
+
+		public AlgorithmIdentifier KeyEncryptionAlgorithmID
+		{
+			get { return keyEncAlg; }
+		}
+
+		/**
+        * return the object identifier for the key encryption algorithm.
+        * 
+		* @return OID for key encryption algorithm.
+        */
+        public string KeyEncryptionAlgOid
+        {
+			get { return keyEncAlg.ObjectID.Id; }
+        }
+
+		/**
+        * return the ASN.1 encoded key encryption algorithm parameters, or null if
+        * there aren't any.
+        * 
+		* @return ASN.1 encoding of key encryption algorithm parameters.
+        */
+		public Asn1Object KeyEncryptionAlgParams
+		{
+			get
+			{
+				Asn1Encodable ae = keyEncAlg.Parameters;
+
+				return ae == null ? null : ae.ToAsn1Object();
+			}
+		}
+
+		internal CmsTypedStream GetContentFromSessionKey(
+			KeyParameter sKey)
+		{
+			CmsReadable readable = secureReadable.GetReadable(sKey); 
+
+			try
+			{
+				return new CmsTypedStream(readable.GetInputStream());
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("error getting .", e);
+			}
+		}
+
+		public byte[] GetContent(
+            ICipherParameters key)
+        {
+            try
+            {
+				return CmsUtilities.StreamToByteArray(GetContentStream(key).ContentStream);
+            }
+            catch (IOException e)
+            {
+                throw new Exception("unable to parse internal stream: " + e);
+            }
+        }
+
+		/**
+		* Return the MAC calculated for the content stream. Note: this call is only meaningful once all
+		* the content has been read.
+		*
+		* @return  byte array containing the mac.
+		*/
+		public byte[] GetMac()
+		{
+			if (resultMac == null)
+			{
+				object cryptoObject = secureReadable.CryptoObject;
+				if (cryptoObject is IMac)
+				{
+					resultMac = MacUtilities.DoFinal((IMac)cryptoObject);
+				}
+			}
+
+			return Arrays.Clone(resultMac);
+		}
+		
+		public abstract CmsTypedStream GetContentStream(ICipherParameters key);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/RecipientInformationStore.cs b/BouncyCastle.AxCrypt/src/cms/RecipientInformationStore.cs
new file mode 100644
index 0000000..33b472f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/RecipientInformationStore.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+	public class RecipientInformationStore
+	{
+		private readonly IList all; //ArrayList[RecipientInformation]
+		private readonly IDictionary table = Platform.CreateHashtable(); // Hashtable[RecipientID, ArrayList[RecipientInformation]]
+
+		public RecipientInformationStore(
+			ICollection recipientInfos)
+		{
+			foreach (RecipientInformation recipientInformation in recipientInfos)
+			{
+				RecipientID rid = recipientInformation.RecipientID;
+                IList list = (IList)table[rid];
+
+				if (list == null)
+				{
+					table[rid] = list = Platform.CreateArrayList(1);
+				}
+
+				list.Add(recipientInformation);
+			}
+
+            this.all = Platform.CreateArrayList(recipientInfos);
+		}
+
+		public RecipientInformation this[RecipientID selector]
+		{
+			get { return GetFirstRecipient(selector); }
+		}
+
+		/**
+		* Return the first RecipientInformation object that matches the
+		* passed in selector. Null if there are no matches.
+		*
+		* @param selector to identify a recipient
+		* @return a single RecipientInformation object. Null if none matches.
+		*/
+		public RecipientInformation GetFirstRecipient(
+			RecipientID selector)
+		{
+			IList list = (IList) table[selector];
+
+			return list == null ? null : (RecipientInformation) list[0];
+		}
+
+		/**
+		* Return the number of recipients in the collection.
+		*
+		* @return number of recipients identified.
+		*/
+		public int Count
+		{
+			get { return all.Count; }
+		}
+
+		/**
+		* Return all recipients in the collection
+		*
+		* @return a collection of recipients.
+		*/
+		public ICollection GetRecipients()
+		{
+			return Platform.CreateArrayList(all);
+		}
+
+		/**
+		* Return possible empty collection with recipients matching the passed in RecipientID
+		*
+		* @param selector a recipient id to select against.
+		* @return a collection of RecipientInformation objects.
+		*/
+		public ICollection GetRecipients(
+			RecipientID selector)
+		{
+            IList list = (IList)table[selector];
+
+            return list == null ? Platform.CreateArrayList() : Platform.CreateArrayList(list);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/SigOutputStream.cs b/BouncyCastle.AxCrypt/src/cms/SigOutputStream.cs
new file mode 100644
index 0000000..a807fa7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SigOutputStream.cs
@@ -0,0 +1,43 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal class SigOutputStream
+		: BaseOutputStream
+	{
+		private readonly ISigner sig;
+
+		internal SigOutputStream(ISigner sig)
+		{
+			this.sig = sig;
+		}
+
+		public override void WriteByte(byte b)
+		{
+			try
+			{
+				sig.Update(b);
+			}
+			catch (SignatureException e)
+			{
+				throw new CmsStreamException("signature problem: " + e);
+			}
+		}
+
+		public override void Write(byte[] b, int off, int len)
+		{
+			try
+			{
+				sig.BlockUpdate(b, off, len);
+			}
+			catch (SignatureException e)
+			{
+				throw new CmsStreamException("signature problem: " + e);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/cms/SignerId.cs b/BouncyCastle.AxCrypt/src/cms/SignerId.cs
new file mode 100644
index 0000000..baac936
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SignerId.cs
@@ -0,0 +1,51 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms
+{
+    /**
+    * a basic index for a signer.
+    */
+    public class SignerID
+        : X509CertStoreSelector
+    {
+        public override int GetHashCode()
+        {
+            int code = Arrays.GetHashCode(this.SubjectKeyIdentifier);
+
+			BigInteger serialNumber = this.SerialNumber;
+			if (serialNumber != null)
+            {
+                code ^= serialNumber.GetHashCode();
+            }
+
+			X509Name issuer = this.Issuer;
+            if (issuer != null)
+            {
+                code ^= issuer.GetHashCode();
+            }
+
+			return code;
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return false;
+
+			SignerID id = obj as SignerID;
+
+			if (id == null)
+				return false;
+
+			return Arrays.AreEqual(SubjectKeyIdentifier, id.SubjectKeyIdentifier)
+				&& Platform.Equals(SerialNumber, id.SerialNumber)
+				&& IssuersMatch(Issuer, id.Issuer);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/SignerInfoGenerator.cs b/BouncyCastle.AxCrypt/src/cms/SignerInfoGenerator.cs
new file mode 100644
index 0000000..f78cf2c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SignerInfoGenerator.cs
@@ -0,0 +1,14 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	internal interface SignerInfoGenerator
+	{
+		SignerInfo Generate(DerObjectIdentifier contentType, AlgorithmIdentifier digestAlgorithm,
+        	byte[] calculatedDigest);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/SignerInformation.cs b/BouncyCastle.AxCrypt/src/cms/SignerInformation.cs
new file mode 100644
index 0000000..20af29a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SignerInformation.cs
@@ -0,0 +1,758 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	* an expanded SignerInfo block from a CMS Signed message
+	*/
+	public class SignerInformation
+	{
+		private static readonly CmsSignedHelper Helper = CmsSignedHelper.Instance;
+
+		private SignerID			sid;
+		private SignerInfo			info;
+		private AlgorithmIdentifier	digestAlgorithm;
+		private AlgorithmIdentifier	encryptionAlgorithm;
+		private readonly Asn1Set	signedAttributeSet;
+		private readonly Asn1Set	unsignedAttributeSet;
+		private CmsProcessable		content;
+		private byte[]				signature;
+		private DerObjectIdentifier	contentType;
+		private IDigestCalculator	digestCalculator;
+		private byte[]				resultDigest;
+
+		// Derived
+		private Asn1.Cms.AttributeTable	signedAttributeTable;
+		private Asn1.Cms.AttributeTable	unsignedAttributeTable;
+		private readonly bool isCounterSignature;
+
+		internal SignerInformation(
+			SignerInfo			info,
+			DerObjectIdentifier	contentType,
+			CmsProcessable		content,
+			IDigestCalculator	digestCalculator)
+		{
+			this.info = info;
+			this.sid = new SignerID();
+			this.contentType = contentType;
+			this.isCounterSignature = contentType == null;
+
+			try
+			{
+				SignerIdentifier s = info.SignerID;
+
+				if (s.IsTagged)
+				{
+					Asn1OctetString octs = Asn1OctetString.GetInstance(s.ID);
+
+					sid.SubjectKeyIdentifier = octs.GetEncoded();
+				}
+				else
+				{
+					Asn1.Cms.IssuerAndSerialNumber iAnds =
+						Asn1.Cms.IssuerAndSerialNumber.GetInstance(s.ID);
+
+					sid.Issuer = iAnds.Name;
+					sid.SerialNumber = iAnds.SerialNumber.Value;
+				}
+			}
+			catch (IOException)
+			{
+				throw new ArgumentException("invalid sid in SignerInfo");
+			}
+
+			this.digestAlgorithm = info.DigestAlgorithm;
+			this.signedAttributeSet = info.AuthenticatedAttributes;
+			this.unsignedAttributeSet = info.UnauthenticatedAttributes;
+			this.encryptionAlgorithm = info.DigestEncryptionAlgorithm;
+			this.signature = info.EncryptedDigest.GetOctets();
+
+			this.content = content;
+			this.digestCalculator = digestCalculator;
+		}
+
+		public bool IsCounterSignature
+		{
+			get { return isCounterSignature; }
+		}
+
+		public DerObjectIdentifier ContentType
+		{
+			get { return contentType; }
+		}
+
+		public SignerID SignerID
+		{
+			get { return sid; }
+		}
+
+		/**
+		* return the version number for this objects underlying SignerInfo structure.
+		*/
+		public int Version
+		{
+			get { return info.Version.Value.IntValue; }
+		}
+
+		public AlgorithmIdentifier DigestAlgorithmID
+		{
+			get { return digestAlgorithm; }
+		}
+
+		/**
+		* return the object identifier for the signature.
+		*/
+		public string DigestAlgOid
+		{
+			get { return digestAlgorithm.ObjectID.Id; }
+		}
+
+		/**
+		* return the signature parameters, or null if there aren't any.
+		*/
+		public Asn1Object DigestAlgParams
+		{
+			get
+			{
+				Asn1Encodable ae = digestAlgorithm.Parameters;
+
+				return ae == null ? null : ae.ToAsn1Object();
+			}
+		}
+
+		/**
+		 * return the content digest that was calculated during verification.
+		 */
+		public byte[] GetContentDigest()
+		{
+			if (resultDigest == null)
+			{
+				throw new InvalidOperationException("method can only be called after verify.");
+			}
+
+			return (byte[])resultDigest.Clone();
+		}
+
+		public AlgorithmIdentifier EncryptionAlgorithmID
+		{
+			get { return encryptionAlgorithm; }
+		}
+
+		/**
+		* return the object identifier for the signature.
+		*/
+		public string EncryptionAlgOid
+		{
+			get { return encryptionAlgorithm.ObjectID.Id; }
+		}
+
+		/**
+		* return the signature/encryption algorithm parameters, or null if
+		* there aren't any.
+		*/
+		public Asn1Object EncryptionAlgParams
+		{
+			get
+			{
+				Asn1Encodable ae = encryptionAlgorithm.Parameters;
+
+				return ae == null ? null : ae.ToAsn1Object();
+			}
+		}
+
+		/**
+		* return a table of the signed attributes - indexed by
+		* the OID of the attribute.
+		*/
+		public Asn1.Cms.AttributeTable SignedAttributes
+		{
+			get
+			{
+				if (signedAttributeSet != null && signedAttributeTable == null)
+				{
+					signedAttributeTable = new Asn1.Cms.AttributeTable(signedAttributeSet);
+				}
+				return signedAttributeTable;
+			}
+		}
+
+		/**
+		* return a table of the unsigned attributes indexed by
+		* the OID of the attribute.
+		*/
+		public Asn1.Cms.AttributeTable UnsignedAttributes
+		{
+			get
+			{
+				if (unsignedAttributeSet != null && unsignedAttributeTable == null)
+				{
+					unsignedAttributeTable = new Asn1.Cms.AttributeTable(unsignedAttributeSet);
+				}
+				return unsignedAttributeTable;
+			}
+		}
+
+		/**
+		* return the encoded signature
+		*/
+		public byte[] GetSignature()
+		{
+			return (byte[]) signature.Clone();
+		}
+
+		/**
+		* Return a SignerInformationStore containing the counter signatures attached to this
+		* signer. If no counter signatures are present an empty store is returned.
+		*/
+		public SignerInformationStore GetCounterSignatures()
+		{
+			// TODO There are several checks implied by the RFC3852 comments that are missing
+
+			/*
+			The countersignature attribute MUST be an unsigned attribute; it MUST
+			NOT be a signed attribute, an authenticated attribute, an
+			unauthenticated attribute, or an unprotected attribute.
+			*/
+			Asn1.Cms.AttributeTable unsignedAttributeTable = UnsignedAttributes;
+			if (unsignedAttributeTable == null)
+			{
+                return new SignerInformationStore(Platform.CreateArrayList(0));
+			}
+
+            IList counterSignatures = Platform.CreateArrayList();
+
+			/*
+			The UnsignedAttributes syntax is defined as a SET OF Attributes.  The
+			UnsignedAttributes in a signerInfo may include multiple instances of
+			the countersignature attribute.
+			*/
+			Asn1EncodableVector allCSAttrs = unsignedAttributeTable.GetAll(CmsAttributes.CounterSignature);
+
+			foreach (Asn1.Cms.Attribute counterSignatureAttribute in allCSAttrs)
+			{
+				/*
+				A countersignature attribute can have multiple attribute values.  The
+				syntax is defined as a SET OF AttributeValue, and there MUST be one
+				or more instances of AttributeValue present.
+				*/
+				Asn1Set values = counterSignatureAttribute.AttrValues;
+				if (values.Count < 1)
+				{
+					// TODO Throw an appropriate exception?
+				}
+
+				foreach (Asn1Encodable asn1Obj in values)
+				{
+					/*
+					Countersignature values have the same meaning as SignerInfo values
+					for ordinary signatures, except that:
+
+					   1. The signedAttributes field MUST NOT contain a content-type
+					      attribute; there is no content type for countersignatures.
+
+					   2. The signedAttributes field MUST contain a message-digest
+					      attribute if it contains any other attributes.
+
+					   3. The input to the message-digesting process is the contents
+					      octets of the DER encoding of the signatureValue field of the
+					      SignerInfo value with which the attribute is associated.
+					*/
+					SignerInfo si = SignerInfo.GetInstance(asn1Obj.ToAsn1Object());
+
+					string digestName = CmsSignedHelper.Instance.GetDigestAlgName(si.DigestAlgorithm.ObjectID.Id);
+
+					counterSignatures.Add(new SignerInformation(si, null, null, new CounterSignatureDigestCalculator(digestName, GetSignature())));
+				}
+			}
+
+			return new SignerInformationStore(counterSignatures);
+		}
+
+		/**
+		* return the DER encoding of the signed attributes.
+		* @throws IOException if an encoding error occurs.
+		*/
+		public byte[] GetEncodedSignedAttributes()
+		{
+			return signedAttributeSet == null
+				?	null
+				:	signedAttributeSet.GetEncoded(Asn1Encodable.Der);
+		}
+
+		private bool DoVerify(
+			AsymmetricKeyParameter	key)
+		{
+			string digestName = Helper.GetDigestAlgName(this.DigestAlgOid);
+			IDigest digest = Helper.GetDigestInstance(digestName);
+
+			DerObjectIdentifier sigAlgOid = this.encryptionAlgorithm.ObjectID;
+			Asn1Encodable sigParams = this.encryptionAlgorithm.Parameters;
+			ISigner sig;
+
+			if (sigAlgOid.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdRsassaPss))
+			{
+				// RFC 4056 2.2
+				// When the id-RSASSA-PSS algorithm identifier is used for a signature,
+				// the AlgorithmIdentifier parameters field MUST contain RSASSA-PSS-params.
+				if (sigParams == null)
+					throw new CmsException("RSASSA-PSS signature must specify algorithm parameters");
+
+				try
+				{
+					// TODO Provide abstract configuration mechanism
+					// (via alternate SignerUtilities.GetSigner method taking ASN.1 params)
+
+					Asn1.Pkcs.RsassaPssParameters pss = Asn1.Pkcs.RsassaPssParameters.GetInstance(
+						sigParams.ToAsn1Object());
+
+					if (!pss.HashAlgorithm.ObjectID.Equals(this.digestAlgorithm.ObjectID))
+						throw new CmsException("RSASSA-PSS signature parameters specified incorrect hash algorithm");
+					if (!pss.MaskGenAlgorithm.ObjectID.Equals(Asn1.Pkcs.PkcsObjectIdentifiers.IdMgf1))
+						throw new CmsException("RSASSA-PSS signature parameters specified unknown MGF");
+
+					IDigest pssDigest = DigestUtilities.GetDigest(pss.HashAlgorithm.ObjectID);
+					int saltLength = pss.SaltLength.Value.IntValue;
+					byte trailerField = (byte) pss.TrailerField.Value.IntValue;
+
+					// RFC 4055 3.1
+					// The value MUST be 1, which represents the trailer field with hexadecimal value 0xBC
+					if (trailerField != 1)
+						throw new CmsException("RSASSA-PSS signature parameters must have trailerField of 1");
+
+					sig = new PssSigner(new RsaBlindedEngine(), pssDigest, saltLength);
+				}
+				catch (Exception e)
+				{
+					throw new CmsException("failed to set RSASSA-PSS signature parameters", e);
+				}
+			}
+			else
+			{
+				// TODO Probably too strong a check at the moment
+//				if (sigParams != null)
+//					throw new CmsException("unrecognised signature parameters provided");
+
+				string signatureName = digestName + "with" + Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
+
+				sig = Helper.GetSignatureInstance(signatureName);
+			}
+
+			try
+			{
+				if (digestCalculator != null)
+				{
+					resultDigest = digestCalculator.GetDigest();
+				}
+				else
+				{
+					if (content != null)
+					{
+						content.Write(new DigOutputStream(digest));
+					}
+					else if (signedAttributeSet == null)
+					{
+						// TODO Get rid of this exception and just treat content==null as empty not missing?
+						throw new CmsException("data not encapsulated in signature - use detached constructor.");
+					}
+
+					resultDigest = DigestUtilities.DoFinal(digest);
+				}
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("can't process mime object to create signature.", e);
+			}
+
+			// RFC 3852 11.1 Check the content-type attribute is correct
+			{
+				Asn1Object validContentType = GetSingleValuedSignedAttribute(
+					CmsAttributes.ContentType, "content-type");
+				if (validContentType == null)
+				{
+					if (!isCounterSignature && signedAttributeSet != null)
+						throw new CmsException("The content-type attribute type MUST be present whenever signed attributes are present in signed-data");
+				}
+				else
+				{
+					if (isCounterSignature)
+						throw new CmsException("[For counter signatures,] the signedAttributes field MUST NOT contain a content-type attribute");
+
+					if (!(validContentType is DerObjectIdentifier))
+						throw new CmsException("content-type attribute value not of ASN.1 type 'OBJECT IDENTIFIER'");
+
+					DerObjectIdentifier signedContentType = (DerObjectIdentifier)validContentType;
+
+					if (!signedContentType.Equals(contentType))
+						throw new CmsException("content-type attribute value does not match eContentType");
+				}
+			}
+
+			// RFC 3852 11.2 Check the message-digest attribute is correct
+			{
+				Asn1Object validMessageDigest = GetSingleValuedSignedAttribute(
+					CmsAttributes.MessageDigest, "message-digest");
+				if (validMessageDigest == null)
+				{
+				    if (signedAttributeSet != null)
+						throw new CmsException("the message-digest signed attribute type MUST be present when there are any signed attributes present");
+				}
+				else
+				{
+					if (!(validMessageDigest is Asn1OctetString))
+					{
+						throw new CmsException("message-digest attribute value not of ASN.1 type 'OCTET STRING'");
+					}
+
+					Asn1OctetString signedMessageDigest = (Asn1OctetString)validMessageDigest;
+
+					if (!Arrays.AreEqual(resultDigest, signedMessageDigest.GetOctets()))
+						throw new CmsException("message-digest attribute value does not match calculated value");
+				}
+			}
+
+			// RFC 3852 11.4 Validate countersignature attribute(s)
+			{
+            	Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes;
+            	if (signedAttrTable != null
+                	&& signedAttrTable.GetAll(CmsAttributes.CounterSignature).Count > 0)
+            	{
+                	throw new CmsException("A countersignature attribute MUST NOT be a signed attribute");
+            	}
+
+            	Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes;
+            	if (unsignedAttrTable != null)
+            	{
+					foreach (Asn1.Cms.Attribute csAttr in unsignedAttrTable.GetAll(CmsAttributes.CounterSignature))
+	                {
+                    	if (csAttr.AttrValues.Count < 1)
+	                        throw new CmsException("A countersignature attribute MUST contain at least one AttributeValue");
+
+						// Note: We don't recursively validate the countersignature value
+    	            }
+	            }
+			}
+
+			try
+			{
+				sig.Init(false, key);
+
+				if (signedAttributeSet == null)
+				{
+					if (digestCalculator != null)
+					{
+						// need to decrypt signature and check message bytes
+						return VerifyDigest(resultDigest, key, this.GetSignature());
+					}
+					else if (content != null)
+					{
+						// TODO Use raw signature of the hash value instead
+						content.Write(new SigOutputStream(sig));
+					}
+				}
+				else
+				{
+					byte[] tmp = this.GetEncodedSignedAttributes();
+					sig.BlockUpdate(tmp, 0, tmp.Length);
+				}
+
+				return sig.VerifySignature(this.GetSignature());
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new CmsException("key not appropriate to signature in message.", e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("can't process mime object to create signature.", e);
+			}
+			catch (SignatureException e)
+			{
+				throw new CmsException("invalid signature format in message: " + e.Message, e);
+			}
+		}
+
+		private bool IsNull(
+			Asn1Encodable o)
+		{
+			return (o is Asn1Null) || (o == null);
+		}
+
+		private DigestInfo DerDecode(
+			byte[] encoding)
+		{
+			if (encoding[0] != (int)(Asn1Tags.Constructed | Asn1Tags.Sequence))
+			{
+				throw new IOException("not a digest info object");
+			}
+
+			DigestInfo digInfo = DigestInfo.GetInstance(Asn1Object.FromByteArray(encoding));
+
+			// length check to avoid Bleichenbacher vulnerability
+
+			if (digInfo.GetEncoded().Length != encoding.Length)
+			{
+				throw new CmsException("malformed RSA signature");
+			}
+
+			return digInfo;
+		}
+
+		private bool VerifyDigest(
+			byte[]					digest,
+			AsymmetricKeyParameter	key,
+			byte[]					signature)
+		{
+			string algorithm = Helper.GetEncryptionAlgName(this.EncryptionAlgOid);
+
+			try
+			{
+				if (algorithm.Equals("RSA"))
+				{
+					IBufferedCipher c = CmsEnvelopedHelper.Instance.CreateAsymmetricCipher("RSA/ECB/PKCS1Padding");
+
+					c.Init(false, key);
+
+					byte[] decrypt = c.DoFinal(signature);
+
+					DigestInfo digInfo = DerDecode(decrypt);
+
+					if (!digInfo.AlgorithmID.ObjectID.Equals(digestAlgorithm.ObjectID))
+					{
+						return false;
+					}
+
+					if (!IsNull(digInfo.AlgorithmID.Parameters))
+					{
+						return false;
+					}
+
+					byte[] sigHash = digInfo.GetDigest();
+
+					return Arrays.ConstantTimeAreEqual(digest, sigHash);
+				}
+				else if (algorithm.Equals("DSA"))
+				{
+					ISigner sig = SignerUtilities.GetSigner("NONEwithDSA");
+
+					sig.Init(false, key);
+
+					sig.BlockUpdate(digest, 0, digest.Length);
+
+					return sig.VerifySignature(signature);
+				}
+				else
+				{
+					throw new CmsException("algorithm: " + algorithm + " not supported in base signatures.");
+				}
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw e;
+			}
+			catch (GeneralSecurityException e)
+			{
+				throw new CmsException("Exception processing signature: " + e, e);
+			}
+			catch (IOException e)
+			{
+				throw new CmsException("Exception decoding signature: " + e, e);
+			}
+		}
+
+		/**
+		* verify that the given public key successfully handles and confirms the
+		* signature associated with this signer.
+		*/
+		public bool Verify(
+			AsymmetricKeyParameter pubKey)
+		{
+			if (pubKey.IsPrivate)
+				throw new ArgumentException("Expected public key", "pubKey");
+
+			// Optional, but still need to validate if present
+			GetSigningTime();
+
+			return DoVerify(pubKey);
+		}
+
+		/**
+		* verify that the given certificate successfully handles and confirms
+		* the signature associated with this signer and, if a signingTime
+		* attribute is available, that the certificate was valid at the time the
+		* signature was generated.
+		*/
+		public bool Verify(
+			X509Certificate cert)
+		{
+			Asn1.Cms.Time signingTime = GetSigningTime();
+			if (signingTime != null)
+			{
+				cert.CheckValidity(signingTime.Date);
+			}
+
+			return DoVerify(cert.GetPublicKey());
+		}
+
+		/**
+		* Return the base ASN.1 CMS structure that this object contains.
+		*
+		* @return an object containing a CMS SignerInfo structure.
+		*/
+		public SignerInfo ToSignerInfo()
+		{
+			return info;
+		}
+
+		private Asn1Object GetSingleValuedSignedAttribute(
+			DerObjectIdentifier attrOID, string printableName)
+		{
+
+			Asn1.Cms.AttributeTable unsignedAttrTable = this.UnsignedAttributes;
+			if (unsignedAttrTable != null
+				&& unsignedAttrTable.GetAll(attrOID).Count > 0)
+			{
+				throw new CmsException("The " + printableName
+					+ " attribute MUST NOT be an unsigned attribute");
+			}
+
+			Asn1.Cms.AttributeTable signedAttrTable = this.SignedAttributes;
+			if (signedAttrTable == null)
+			{
+				return null;
+			}
+
+			Asn1EncodableVector v = signedAttrTable.GetAll(attrOID);
+			switch (v.Count)
+			{
+				case 0:
+					return null;
+				case 1:
+					Asn1.Cms.Attribute t = (Asn1.Cms.Attribute) v[0];
+					Asn1Set attrValues = t.AttrValues;
+
+					if (attrValues.Count != 1)
+						throw new CmsException("A " + printableName
+							+ " attribute MUST have a single attribute value");
+
+					return attrValues[0].ToAsn1Object();
+				default:
+					throw new CmsException("The SignedAttributes in a signerInfo MUST NOT include multiple instances of the "
+						+ printableName + " attribute");
+			}
+		}
+
+		private Asn1.Cms.Time GetSigningTime()
+		{
+			Asn1Object validSigningTime = GetSingleValuedSignedAttribute(
+				CmsAttributes.SigningTime, "signing-time");
+
+			if (validSigningTime == null)
+				return null;
+
+			try
+			{
+				return Asn1.Cms.Time.GetInstance(validSigningTime);
+			}
+			catch (ArgumentException)
+			{
+				throw new CmsException("signing-time attribute value not a valid 'Time' structure");
+			}
+		}
+
+		/**
+		* Return a signer information object with the passed in unsigned
+		* attributes replacing the ones that are current associated with
+		* the object passed in.
+		*
+		* @param signerInformation the signerInfo to be used as the basis.
+		* @param unsignedAttributes the unsigned attributes to add.
+		* @return a copy of the original SignerInformationObject with the changed attributes.
+		*/
+		public static SignerInformation ReplaceUnsignedAttributes(
+			SignerInformation		signerInformation,
+			Asn1.Cms.AttributeTable	unsignedAttributes)
+		{
+			SignerInfo sInfo = signerInformation.info;
+			Asn1Set unsignedAttr = null;
+
+			if (unsignedAttributes != null)
+			{
+				unsignedAttr = new DerSet(unsignedAttributes.ToAsn1EncodableVector());
+			}
+
+			return new SignerInformation(
+				new SignerInfo(
+					sInfo.SignerID,
+					sInfo.DigestAlgorithm,
+					sInfo.AuthenticatedAttributes,
+					sInfo.DigestEncryptionAlgorithm,
+					sInfo.EncryptedDigest,
+					unsignedAttr),
+				signerInformation.contentType,
+				signerInformation.content,
+				null);
+		}
+
+		/**
+		 * Return a signer information object with passed in SignerInformationStore representing counter
+		 * signatures attached as an unsigned attribute.
+		 *
+		 * @param signerInformation the signerInfo to be used as the basis.
+		 * @param counterSigners signer info objects carrying counter signature.
+		 * @return a copy of the original SignerInformationObject with the changed attributes.
+		 */
+		public static SignerInformation AddCounterSigners(
+			SignerInformation		signerInformation,
+			SignerInformationStore	counterSigners)
+		{
+			// TODO Perform checks from RFC 3852 11.4
+
+			SignerInfo sInfo = signerInformation.info;
+			Asn1.Cms.AttributeTable unsignedAttr = signerInformation.UnsignedAttributes;
+			Asn1EncodableVector v;
+
+			if (unsignedAttr != null)
+			{
+				v = unsignedAttr.ToAsn1EncodableVector();
+			}
+			else
+			{
+				v = new Asn1EncodableVector();
+			}
+
+			Asn1EncodableVector sigs = new Asn1EncodableVector();
+
+			foreach (SignerInformation sigInf in counterSigners.GetSigners())
+			{
+				sigs.Add(sigInf.ToSignerInfo());
+			}
+
+			v.Add(new Asn1.Cms.Attribute(CmsAttributes.CounterSignature, new DerSet(sigs)));
+
+			return new SignerInformation(
+				new SignerInfo(
+					sInfo.SignerID,
+					sInfo.DigestAlgorithm,
+					sInfo.AuthenticatedAttributes,
+					sInfo.DigestEncryptionAlgorithm,
+					sInfo.EncryptedDigest,
+					new DerSet(v)),
+				signerInformation.contentType,
+				signerInformation.content,
+				null);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/SignerInformationStore.cs b/BouncyCastle.AxCrypt/src/cms/SignerInformationStore.cs
new file mode 100644
index 0000000..bd61384
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SignerInformationStore.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Cms
+{
+    public class SignerInformationStore
+    {
+		private readonly IList all; //ArrayList[SignerInformation]
+		private readonly IDictionary table = Platform.CreateHashtable(); // Hashtable[SignerID, ArrayList[SignerInformation]]
+
+		public SignerInformationStore(
+            ICollection signerInfos)
+        {
+            foreach (SignerInformation signer in signerInfos)
+            {
+                SignerID sid = signer.SignerID;
+                IList list = (IList)table[sid];
+
+				if (list == null)
+				{
+					table[sid] = list = Platform.CreateArrayList(1);
+				}
+
+				list.Add(signer);
+            }
+
+            this.all = Platform.CreateArrayList(signerInfos);
+        }
+
+        /**
+        * Return the first SignerInformation object that matches the
+        * passed in selector. Null if there are no matches.
+        *
+        * @param selector to identify a signer
+        * @return a single SignerInformation object. Null if none matches.
+        */
+        public SignerInformation GetFirstSigner(
+            SignerID selector)
+        {
+			IList list = (IList) table[selector];
+
+			return list == null ? null : (SignerInformation) list[0];
+        }
+
+		/// <summary>The number of signers in the collection.</summary>
+		public int Count
+        {
+			get { return all.Count; }
+        }
+
+		/// <returns>An ICollection of all signers in the collection</returns>
+        public ICollection GetSigners()
+        {
+            return Platform.CreateArrayList(all);
+        }
+
+		/**
+        * Return possible empty collection with signers matching the passed in SignerID
+        *
+        * @param selector a signer id to select against.
+        * @return a collection of SignerInformation objects.
+        */
+        public ICollection GetSigners(
+            SignerID selector)
+        {
+			IList list = (IList) table[selector];
+
+            return list == null ? Platform.CreateArrayList() : Platform.CreateArrayList(list);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/cms/SimpleAttributeTableGenerator.cs b/BouncyCastle.AxCrypt/src/cms/SimpleAttributeTableGenerator.cs
new file mode 100644
index 0000000..b3df21c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/cms/SimpleAttributeTableGenerator.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Cms
+{
+	/**
+	 * Basic generator that just returns a preconstructed attribute table
+	 */
+	public class SimpleAttributeTableGenerator
+		: CmsAttributeTableGenerator
+	{
+		private readonly AttributeTable attributes;
+
+		public SimpleAttributeTableGenerator(
+			AttributeTable attributes)
+		{
+			this.attributes = attributes;
+		}
+
+		public virtual AttributeTable GetAttributes(
+			IDictionary parameters)
+		{
+			return attributes;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/AsymmetricCipherKeyPair.cs b/BouncyCastle.AxCrypt/src/crypto/AsymmetricCipherKeyPair.cs
new file mode 100644
index 0000000..b00a3dc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/AsymmetricCipherKeyPair.cs
@@ -0,0 +1,52 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * a holding class for public/private parameter pairs.
+     */
+    public class AsymmetricCipherKeyPair
+    {
+        private readonly AsymmetricKeyParameter publicParameter;
+        private readonly AsymmetricKeyParameter privateParameter;
+
+		/**
+         * basic constructor.
+         *
+         * @param publicParam a public key parameters object.
+         * @param privateParam the corresponding private key parameters.
+         */
+        public AsymmetricCipherKeyPair(
+            AsymmetricKeyParameter    publicParameter,
+            AsymmetricKeyParameter    privateParameter)
+        {
+			if (publicParameter.IsPrivate)
+				throw new ArgumentException("Expected a public key", "publicParameter");
+			if (!privateParameter.IsPrivate)
+				throw new ArgumentException("Expected a private key", "privateParameter");
+
+			this.publicParameter = publicParameter;
+            this.privateParameter = privateParameter;
+        }
+
+		/**
+         * return the public key parameters.
+         *
+         * @return the public key parameters.
+         */
+        public AsymmetricKeyParameter Public
+        {
+            get { return publicParameter; }
+        }
+
+		/**
+         * return the private key parameters.
+         *
+         * @return the private key parameters.
+         */
+        public AsymmetricKeyParameter Private
+        {
+            get { return privateParameter; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/AsymmetricKeyParameter.cs b/BouncyCastle.AxCrypt/src/crypto/AsymmetricKeyParameter.cs
new file mode 100644
index 0000000..7502ee3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/AsymmetricKeyParameter.cs
@@ -0,0 +1,47 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto
+{
+    public abstract class AsymmetricKeyParameter
+		: ICipherParameters
+    {
+        private readonly bool privateKey;
+
+        protected AsymmetricKeyParameter(
+            bool privateKey)
+        {
+            this.privateKey = privateKey;
+        }
+
+		public bool IsPrivate
+        {
+            get { return privateKey; }
+        }
+
+		public override bool Equals(
+			object obj)
+		{
+			AsymmetricKeyParameter other = obj as AsymmetricKeyParameter;
+
+			if (other == null)
+			{
+				return false;
+			}
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			AsymmetricKeyParameter other)
+		{
+			return privateKey == other.privateKey;
+		}
+
+		public override int GetHashCode()
+		{
+			return privateKey.GetHashCode();
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedAeadBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedAeadBlockCipher.cs
new file mode 100644
index 0000000..04bcb88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedAeadBlockCipher.cs
@@ -0,0 +1,247 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/**
+	* The AEAD block ciphers already handle buffering internally, so this class
+	* just takes care of implementing IBufferedCipher methods.
+	*/
+	public class BufferedAeadBlockCipher
+		: BufferedCipherBase
+	{
+		private readonly IAeadBlockCipher cipher;
+
+		public BufferedAeadBlockCipher(
+			IAeadBlockCipher cipher)
+		{
+			if (cipher == null)
+				throw new ArgumentNullException("cipher");
+
+			this.cipher = cipher;
+		}
+
+		public override string AlgorithmName
+		{
+			get { return cipher.AlgorithmName; }
+		}
+
+		/**
+		* initialise the cipher.
+		*
+		* @param forEncryption if true the cipher is initialised for
+		*  encryption, if false for decryption.
+		* @param param the key and other data required by the cipher.
+		* @exception ArgumentException if the parameters argument is
+		* inappropriate.
+		*/
+		public override void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithRandom)
+			{
+				parameters = ((ParametersWithRandom) parameters).Parameters;
+			}
+
+			cipher.Init(forEncryption, parameters);
+		}
+
+		/**
+		* return the blocksize for the underlying cipher.
+		*
+		* @return the blocksize for the underlying cipher.
+		*/
+		public override int GetBlockSize()
+		{
+			return cipher.GetBlockSize();
+		}
+
+		/**
+		* return the size of the output buffer required for an update
+		* an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update
+		* with len bytes of input.
+		*/
+		public override int GetUpdateOutputSize(
+			int length)
+		{
+			return cipher.GetUpdateOutputSize(length);
+		}
+
+		/**
+		* return the size of the output buffer required for an update plus a
+		* doFinal with an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update and doFinal
+		* with len bytes of input.
+		*/
+		public override int GetOutputSize(
+			int length)
+		{
+			return cipher.GetOutputSize(length);
+		}
+
+		/**
+		* process a single byte, producing an output block if neccessary.
+		*
+		* @param in the input byte.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessByte(
+			byte	input,
+			byte[]	output,
+			int		outOff)
+		{
+			return cipher.ProcessByte(input, output, outOff);
+		}
+
+		public override byte[] ProcessByte(
+			byte input)
+		{
+			int outLength = GetUpdateOutputSize(1);
+
+			byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+			int pos = ProcessByte(input, outBytes, 0);
+
+			if (outLength > 0 && pos < outLength)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+			return outBytes;
+		}
+
+		public override byte[] ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (input == null)
+				throw new ArgumentNullException("input");
+			if (length < 1)
+				return null;
+
+			int outLength = GetUpdateOutputSize(length);
+
+			byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+			int pos = ProcessBytes(input, inOff, length, outBytes, 0);
+
+			if (outLength > 0 && pos < outLength)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+			return outBytes;
+		}
+
+		/**
+		* process an array of bytes, producing output if necessary.
+		*
+		* @param in the input byte array.
+		* @param inOff the offset at which the input data starts.
+		* @param len the number of bytes to be copied out of the input array.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			return cipher.ProcessBytes(input, inOff, length, output, outOff);
+		}
+
+		public override byte[] DoFinal()
+		{
+            byte[] outBytes = new byte[GetOutputSize(0)];
+
+            int pos = DoFinal(outBytes, 0);
+
+            if (pos < outBytes.Length)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+            return outBytes;
+		}
+
+		public override byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		inLen)
+		{
+			if (input == null)
+				throw new ArgumentNullException("input");
+
+            byte[] outBytes = new byte[GetOutputSize(inLen)];
+
+            int pos = (inLen > 0)
+				?	ProcessBytes(input, inOff, inLen, outBytes, 0)
+				:	0;
+
+			pos += DoFinal(outBytes, pos);
+
+            if (pos < outBytes.Length)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+            return outBytes;
+		}
+
+		/**
+		* Process the last block in the buffer.
+		*
+		* @param out the array the block currently being held is copied into.
+		* @param outOff the offset at which the copying starts.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there is insufficient space in out for
+		* the output, or the input is not block size aligned and should be.
+		* @exception InvalidOperationException if the underlying cipher is not
+		* initialised.
+		* @exception InvalidCipherTextException if padding is expected and not found.
+		* @exception DataLengthException if the input is not block size
+		* aligned.
+		*/
+		public override int DoFinal(
+			byte[]	output,
+			int		outOff)
+		{
+			return cipher.DoFinal(output, outOff);
+		}
+
+		/**
+		* Reset the buffer and cipher. After resetting the object is in the same
+		* state as it was after the last init (if there was one).
+		*/
+		public override void Reset()
+		{
+			cipher.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedAsymmetricBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedAsymmetricBlockCipher.cs
new file mode 100644
index 0000000..09ec59f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedAsymmetricBlockCipher.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Engines;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+    * a buffer wrapper for an asymmetric block cipher, allowing input
+    * to be accumulated in a piecemeal fashion until final processing.
+    */
+    public class BufferedAsymmetricBlockCipher
+		: BufferedCipherBase
+    {
+		private readonly IAsymmetricBlockCipher cipher;
+
+		private byte[] buffer;
+		private int bufOff;
+
+		/**
+        * base constructor.
+        *
+        * @param cipher the cipher this buffering object wraps.
+        */
+        public BufferedAsymmetricBlockCipher(
+            IAsymmetricBlockCipher cipher)
+        {
+            this.cipher = cipher;
+		}
+
+		/**
+        * return the amount of data sitting in the buffer.
+        *
+        * @return the amount of data sitting in the buffer.
+        */
+        internal int GetBufferPosition()
+        {
+            return bufOff;
+        }
+
+		public override string AlgorithmName
+        {
+            get { return cipher.AlgorithmName; }
+        }
+
+		public override int GetBlockSize()
+        {
+			return cipher.GetInputBlockSize();
+        }
+
+		public override int GetOutputSize(
+			int length)
+		{
+			return cipher.GetOutputBlockSize();
+		}
+
+		public override int GetUpdateOutputSize(
+			int length)
+		{
+			return 0;
+		}
+
+		/**
+        * initialise the buffer and the underlying cipher.
+        *
+        * @param forEncryption if true the cipher is initialised for
+        *  encryption, if false for decryption.
+        * @param param the key and other data required by the cipher.
+        */
+        public override void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+			Reset();
+
+			cipher.Init(forEncryption, parameters);
+
+			//
+			// we allow for an extra byte where people are using their own padding
+			// mechanisms on a raw cipher.
+			//
+			this.buffer = new byte[cipher.GetInputBlockSize() + (forEncryption ? 1 : 0)];
+			this.bufOff = 0;
+        }
+
+		public override byte[] ProcessByte(
+			byte input)
+		{
+			if (bufOff >= buffer.Length)
+				throw new DataLengthException("attempt to process message to long for cipher");
+
+			buffer[bufOff++] = input;
+			return null;
+		}
+
+		public override byte[] ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (length < 1)
+				return null;
+
+			if (input == null)
+				throw new ArgumentNullException("input");
+			if (bufOff + length > buffer.Length)
+				throw new DataLengthException("attempt to process message to long for cipher");
+
+			Array.Copy(input, inOff, buffer, bufOff, length);
+			bufOff += length;
+			return null;
+		}
+
+		/**
+        * process the contents of the buffer using the underlying
+        * cipher.
+        *
+        * @return the result of the encryption/decryption process on the
+        * buffer.
+        * @exception InvalidCipherTextException if we are given a garbage block.
+        */
+        public override byte[] DoFinal()
+        {
+			byte[] outBytes = bufOff > 0
+				?	cipher.ProcessBlock(buffer, 0, bufOff)
+				:	EmptyBuffer;
+
+			Reset();
+
+			return outBytes;
+        }
+
+		public override byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			ProcessBytes(input, inOff, length);
+			return DoFinal();
+		}
+
+		/// <summary>Reset the buffer</summary>
+        public override void Reset()
+        {
+			if (buffer != null)
+			{
+				Array.Clear(buffer, 0, buffer.Length);
+				bufOff = 0;
+			}
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedBlockCipher.cs
new file mode 100644
index 0000000..3a98798
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedBlockCipher.cs
@@ -0,0 +1,377 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/**
+	* A wrapper class that allows block ciphers to be used to process data in
+	* a piecemeal fashion. The BufferedBlockCipher outputs a block only when the
+	* buffer is full and more data is being added, or on a doFinal.
+	* <p>
+	* Note: in the case where the underlying cipher is either a CFB cipher or an
+	* OFB one the last block may not be a multiple of the block size.
+	* </p>
+	*/
+	public class BufferedBlockCipher
+		: BufferedCipherBase
+	{
+		internal byte[]			buf;
+		internal int			bufOff;
+		internal bool			forEncryption;
+		internal IBlockCipher	cipher;
+
+		/**
+		* constructor for subclasses
+		*/
+		protected BufferedBlockCipher()
+		{
+		}
+
+		/**
+		* Create a buffered block cipher without padding.
+		*
+		* @param cipher the underlying block cipher this buffering object wraps.
+		* false otherwise.
+		*/
+		public BufferedBlockCipher(
+			IBlockCipher cipher)
+		{
+			if (cipher == null)
+				throw new ArgumentNullException("cipher");
+
+			this.cipher = cipher;
+			buf = new byte[cipher.GetBlockSize()];
+			bufOff = 0;
+		}
+
+		public override string AlgorithmName
+		{
+			get { return cipher.AlgorithmName; }
+		}
+
+		/**
+		* initialise the cipher.
+		*
+		* @param forEncryption if true the cipher is initialised for
+		*  encryption, if false for decryption.
+		* @param param the key and other data required by the cipher.
+		* @exception ArgumentException if the parameters argument is
+		* inappropriate.
+		*/
+		// Note: This doubles as the Init in the event that this cipher is being used as an IWrapper
+		public override void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+
+            ParametersWithRandom pwr = parameters as ParametersWithRandom;
+            if (pwr != null)
+                parameters = pwr.Parameters;
+
+            Reset();
+
+			cipher.Init(forEncryption, parameters);
+		}
+
+		/**
+		* return the blocksize for the underlying cipher.
+		*
+		* @return the blocksize for the underlying cipher.
+		*/
+		public override int GetBlockSize()
+		{
+			return cipher.GetBlockSize();
+		}
+
+		/**
+		* return the size of the output buffer required for an update
+		* an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update
+		* with len bytes of input.
+		*/
+		public override int GetUpdateOutputSize(
+			int length)
+		{
+			int total = length + bufOff;
+			int leftOver = total % buf.Length;
+			return total - leftOver;
+		}
+
+		/**
+		* return the size of the output buffer required for an update plus a
+		* doFinal with an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update and doFinal
+		* with len bytes of input.
+		*/
+		public override int GetOutputSize(
+			int length)
+		{
+			// Note: Can assume IsPartialBlockOkay is true for purposes of this calculation
+			return length + bufOff;
+		}
+
+		/**
+		* process a single byte, producing an output block if neccessary.
+		*
+		* @param in the input byte.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessByte(
+			byte	input,
+			byte[]	output,
+			int		outOff)
+		{
+			buf[bufOff++] = input;
+
+			if (bufOff == buf.Length)
+			{
+				if ((outOff + buf.Length) > output.Length)
+					throw new DataLengthException("output buffer too short");
+
+				bufOff = 0;
+				return cipher.ProcessBlock(buf, 0, output, outOff);
+			}
+
+			return 0;
+		}
+
+		public override byte[] ProcessByte(
+			byte input)
+		{
+			int outLength = GetUpdateOutputSize(1);
+
+			byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+			int pos = ProcessByte(input, outBytes, 0);
+
+			if (outLength > 0 && pos < outLength)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+			return outBytes;
+		}
+
+		public override byte[] ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (input == null)
+				throw new ArgumentNullException("input");
+			if (length < 1)
+				return null;
+
+			int outLength = GetUpdateOutputSize(length);
+
+			byte[] outBytes = outLength > 0 ? new byte[outLength] : null;
+
+			int pos = ProcessBytes(input, inOff, length, outBytes, 0);
+
+			if (outLength > 0 && pos < outLength)
+			{
+				byte[] tmp = new byte[pos];
+				Array.Copy(outBytes, 0, tmp, 0, pos);
+				outBytes = tmp;
+			}
+
+			return outBytes;
+		}
+
+		/**
+		* process an array of bytes, producing output if necessary.
+		*
+		* @param in the input byte array.
+		* @param inOff the offset at which the input data starts.
+		* @param len the number of bytes to be copied out of the input array.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			if (length < 1)
+			{
+				if (length < 0)
+					throw new ArgumentException("Can't have a negative input length!");
+
+				return 0;
+			}
+
+			int blockSize = GetBlockSize();
+			int outLength = GetUpdateOutputSize(length);
+
+			if (outLength > 0)
+			{
+				if ((outOff + outLength) > output.Length)
+				{
+					throw new DataLengthException("output buffer too short");
+				}
+			}
+
+			int resultLen = 0;
+			int gapLen = buf.Length - bufOff;
+			if (length > gapLen)
+			{
+				Array.Copy(input, inOff, buf, bufOff, gapLen);
+				resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+				bufOff = 0;
+				length -= gapLen;
+				inOff += gapLen;
+				while (length > buf.Length)
+				{
+					resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen);
+					length -= blockSize;
+					inOff += blockSize;
+				}
+			}
+			Array.Copy(input, inOff, buf, bufOff, length);
+			bufOff += length;
+			if (bufOff == buf.Length)
+			{
+				resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
+				bufOff = 0;
+			}
+			return resultLen;
+		}
+
+		public override byte[] DoFinal()
+		{
+			byte[] outBytes = EmptyBuffer;
+
+			int length = GetOutputSize(0);
+			if (length > 0)
+			{
+				outBytes = new byte[length];
+
+				int pos = DoFinal(outBytes, 0);
+				if (pos < outBytes.Length)
+				{
+					byte[] tmp = new byte[pos];
+					Array.Copy(outBytes, 0, tmp, 0, pos);
+					outBytes = tmp;
+				}
+			}
+			else
+			{
+				Reset();
+			}
+
+			return outBytes;
+		}
+
+		public override byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		inLen)
+		{
+			if (input == null)
+				throw new ArgumentNullException("input");
+
+			int length = GetOutputSize(inLen);
+
+			byte[] outBytes = EmptyBuffer;
+
+			if (length > 0)
+			{
+				outBytes = new byte[length];
+
+				int pos = (inLen > 0)
+					?	ProcessBytes(input, inOff, inLen, outBytes, 0)
+					:	0;
+
+				pos += DoFinal(outBytes, pos);
+
+				if (pos < outBytes.Length)
+				{
+					byte[] tmp = new byte[pos];
+					Array.Copy(outBytes, 0, tmp, 0, pos);
+					outBytes = tmp;
+				}
+			}
+			else
+			{
+				Reset();
+			}
+
+			return outBytes;
+		}
+
+		/**
+		* Process the last block in the buffer.
+		*
+		* @param out the array the block currently being held is copied into.
+		* @param outOff the offset at which the copying starts.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there is insufficient space in out for
+		* the output, or the input is not block size aligned and should be.
+		* @exception InvalidOperationException if the underlying cipher is not
+		* initialised.
+		* @exception InvalidCipherTextException if padding is expected and not found.
+		* @exception DataLengthException if the input is not block size
+		* aligned.
+		*/
+		public override int DoFinal(
+			byte[]	output,
+			int		outOff)
+		{
+			try
+			{
+				if (bufOff != 0)
+				{
+					if (!cipher.IsPartialBlockOkay)
+					{
+						throw new DataLengthException("data not block size aligned");
+					}
+	
+					if (outOff + bufOff > output.Length)
+					{
+						throw new DataLengthException("output buffer too short for DoFinal()");
+					}
+	
+					// NB: Can't copy directly, or we may write too much output
+					cipher.ProcessBlock(buf, 0, buf, 0);
+					Array.Copy(buf, 0, output, outOff, bufOff);
+				}
+
+				return bufOff;
+			}
+			finally
+			{
+				Reset();
+			}
+		}
+
+		/**
+		* Reset the buffer and cipher. After resetting the object is in the same
+		* state as it was after the last init (if there was one).
+		*/
+		public override void Reset()
+		{
+			Array.Clear(buf, 0, buf.Length);
+			bufOff = 0;
+
+			cipher.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedCipherBase.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedCipherBase.cs
new file mode 100644
index 0000000..9d86102
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedCipherBase.cs
@@ -0,0 +1,113 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	public abstract class BufferedCipherBase
+		: IBufferedCipher
+	{
+		protected static readonly byte[] EmptyBuffer = new byte[0];
+
+		public abstract string AlgorithmName { get; }
+
+		public abstract void Init(bool forEncryption, ICipherParameters parameters);
+
+		public abstract int GetBlockSize();
+
+		public abstract int GetOutputSize(int inputLen);
+		public abstract int GetUpdateOutputSize(int inputLen);
+
+		public abstract byte[] ProcessByte(byte input);
+
+		public virtual int ProcessByte(
+			byte	input,
+			byte[]	output,
+			int		outOff)
+		{
+			byte[] outBytes = ProcessByte(input);
+			if (outBytes == null)
+				return 0;
+			if (outOff + outBytes.Length > output.Length)
+				throw new DataLengthException("output buffer too short");
+			outBytes.CopyTo(output, outOff);
+			return outBytes.Length;
+		}
+
+		public virtual byte[] ProcessBytes(
+			byte[] input)
+		{
+			return ProcessBytes(input, 0, input.Length);
+		}
+
+		public abstract byte[] ProcessBytes(byte[] input, int inOff, int length);
+
+		public virtual int ProcessBytes(
+			byte[]	input,
+			byte[]	output,
+			int		outOff)
+		{
+			return ProcessBytes(input, 0, input.Length, output, outOff);
+		}
+
+		public virtual int ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			byte[] outBytes = ProcessBytes(input, inOff, length);
+			if (outBytes == null)
+				return 0;
+			if (outOff + outBytes.Length > output.Length)
+				throw new DataLengthException("output buffer too short");
+			outBytes.CopyTo(output, outOff);
+			return outBytes.Length;
+		}
+
+		public abstract byte[] DoFinal();
+
+		public virtual byte[] DoFinal(
+			byte[] input)
+		{
+			return DoFinal(input, 0, input.Length);
+		}
+
+		public abstract byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		length);
+
+		public virtual int DoFinal(
+			byte[]	output,
+			int		outOff)
+		{
+			byte[] outBytes = DoFinal();
+			if (outOff + outBytes.Length > output.Length)
+				throw new DataLengthException("output buffer too short");
+			outBytes.CopyTo(output, outOff);
+			return outBytes.Length;
+		}
+
+		public virtual int DoFinal(
+			byte[]	input,
+			byte[]	output,
+			int		outOff)
+		{
+			return DoFinal(input, 0, input.Length, output, outOff);
+		}
+
+		public virtual int DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			int len = ProcessBytes(input, inOff, length, output, outOff);
+			len += DoFinal(output, outOff + len);
+			return len;
+		}
+
+		public abstract void Reset();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedIesCipher.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedIesCipher.cs
new file mode 100644
index 0000000..6dab4ae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedIesCipher.cs
@@ -0,0 +1,113 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto
+{
+	public class BufferedIesCipher
+		: BufferedCipherBase
+	{
+		private readonly IesEngine engine;
+		private bool forEncryption;
+		private MemoryStream buffer = new MemoryStream();
+
+		public BufferedIesCipher(
+			IesEngine engine)
+		{
+			if (engine == null)
+				throw new ArgumentNullException("engine");
+
+			this.engine = engine;
+		}
+
+		public override string AlgorithmName
+		{
+			// TODO Create IESEngine.AlgorithmName
+			get { return "IES"; }
+		}
+
+		public override void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+
+			// TODO
+			throw Platform.CreateNotImplementedException("IES");
+		}
+
+		public override int GetBlockSize()
+		{
+			return 0;
+		}
+
+		public override int GetOutputSize(
+			int inputLen)
+		{
+			if (engine == null)
+				throw new InvalidOperationException("cipher not initialised");
+
+			int baseLen = inputLen + (int) buffer.Length;
+			return forEncryption
+				?	baseLen + 20
+				:	baseLen - 20;
+		}
+
+		public override int GetUpdateOutputSize(
+			int inputLen)
+		{
+			return 0;
+		}
+
+		public override byte[] ProcessByte(
+			byte input)
+		{
+			buffer.WriteByte(input);
+			return null;
+		}
+
+		public override byte[] ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (input == null)
+				throw new ArgumentNullException("input");
+			if (inOff < 0)
+				throw new ArgumentException("inOff");
+			if (length < 0)
+				throw new ArgumentException("length");
+			if (inOff + length > input.Length)
+				throw new ArgumentException("invalid offset/length specified for input array");
+
+			buffer.Write(input, inOff, length);
+			return null;
+		}
+
+		public override byte[] DoFinal()
+		{
+			byte[] buf = buffer.ToArray();
+
+			Reset();
+
+			return engine.ProcessBlock(buf, 0, buf.Length);
+		}
+
+		public override byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			ProcessBytes(input, inOff, length);
+			return DoFinal();
+		}
+
+		public override void Reset()
+		{
+			buffer.SetLength(0);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/BufferedStreamCipher.cs b/BouncyCastle.AxCrypt/src/crypto/BufferedStreamCipher.cs
new file mode 100644
index 0000000..2d4987b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/BufferedStreamCipher.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto
+{
+	public class BufferedStreamCipher
+		: BufferedCipherBase
+	{
+		private readonly IStreamCipher cipher;
+
+		public BufferedStreamCipher(
+			IStreamCipher cipher)
+		{
+			if (cipher == null)
+				throw new ArgumentNullException("cipher");
+
+			this.cipher = cipher;
+		}
+
+		public override string AlgorithmName
+		{
+			get { return cipher.AlgorithmName; }
+		}
+
+		public override void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithRandom)
+			{
+				parameters = ((ParametersWithRandom) parameters).Parameters;
+			}
+
+			cipher.Init(forEncryption, parameters);
+		}
+
+		public override int GetBlockSize()
+		{
+			return 0;
+		}
+
+		public override int GetOutputSize(
+			int inputLen)
+		{
+			return inputLen;
+		}
+
+		public override int GetUpdateOutputSize(
+			int inputLen)
+		{
+			return inputLen;
+		}
+
+		public override byte[] ProcessByte(
+			byte input)
+		{
+			return new byte[]{ cipher.ReturnByte(input) };
+		}
+
+		public override int ProcessByte(
+			byte	input,
+			byte[]	output,
+			int		outOff)
+		{
+			if (outOff >= output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			output[outOff] = cipher.ReturnByte(input);
+			return 1;
+		}
+
+		public override byte[] ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (length < 1)
+				return null;
+
+			byte[] output = new byte[length];
+			cipher.ProcessBytes(input, inOff, length, output, 0);
+			return output;
+		}
+
+		public override int ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			if (length < 1)
+				return 0;
+
+			if (length > 0)
+			{
+				cipher.ProcessBytes(input, inOff, length, output, outOff);
+			}
+
+			return length;
+		}
+
+		public override byte[] DoFinal()
+		{
+			Reset();
+
+			return EmptyBuffer;
+		}
+
+		public override byte[] DoFinal(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (length < 1)
+				return EmptyBuffer;
+
+			byte[] output = ProcessBytes(input, inOff, length);
+
+			Reset();
+
+			return output;
+		}
+
+		public override void Reset()
+		{
+			cipher.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/CipherKeyGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/CipherKeyGenerator.cs
new file mode 100644
index 0000000..5d00d34
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/CipherKeyGenerator.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/**
+	 * The base class for symmetric, or secret, cipher key generators.
+	 */
+	public class CipherKeyGenerator
+	{
+		protected internal SecureRandom	random;
+		protected internal int			strength;
+		private bool uninitialised = true;
+		private int defaultStrength;
+
+		public CipherKeyGenerator()
+		{
+		}
+
+		internal CipherKeyGenerator(
+			int defaultStrength)
+		{
+			if (defaultStrength < 1)
+				throw new ArgumentException("strength must be a positive value", "defaultStrength");
+
+			this.defaultStrength = defaultStrength;
+		}
+
+		public int DefaultStrength
+		{
+			get { return defaultStrength; }
+		}
+
+		/**
+		 * initialise the key generator.
+		 *
+		 * @param param the parameters to be used for key generation
+		 */
+		public void Init(
+			KeyGenerationParameters parameters)
+		{
+			if (parameters == null)
+				throw new ArgumentNullException("parameters");
+
+			this.uninitialised = false;
+
+			engineInit(parameters);
+		}
+
+		protected virtual void engineInit(
+			KeyGenerationParameters parameters)
+		{
+			this.random = parameters.Random;
+			this.strength = (parameters.Strength + 7) / 8;
+		}
+
+		/**
+		 * Generate a secret key.
+		 *
+		 * @return a byte array containing the key value.
+		 */
+		public byte[] GenerateKey()
+		{
+			if (uninitialised)
+			{
+				if (defaultStrength < 1)
+					throw new InvalidOperationException("Generator has not been initialised");
+
+				uninitialised = false;
+
+				engineInit(new KeyGenerationParameters(new SecureRandom(), defaultStrength));
+			}
+
+			return engineGenerateKey();
+		}
+
+		protected virtual byte[] engineGenerateKey()
+		{
+			return random.GenerateSeed(strength);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/CryptoException.cs b/BouncyCastle.AxCrypt/src/crypto/CryptoException.cs
new file mode 100644
index 0000000..67f0d86
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/CryptoException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CryptoException
+		: Exception
+    {
+        public CryptoException()
+        {
+        }
+
+		public CryptoException(
+            string message)
+			: base(message)
+        {
+        }
+
+		public CryptoException(
+            string		message,
+            Exception	exception)
+			: base(message, exception)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/DataLengthException.cs b/BouncyCastle.AxCrypt/src/crypto/DataLengthException.cs
new file mode 100644
index 0000000..e9efc0b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/DataLengthException.cs
@@ -0,0 +1,42 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * this exception is thrown if a buffer that is meant to have output
+     * copied into it turns out to be too short, or if we've been given
+     * insufficient input. In general this exception will Get thrown rather
+     * than an ArrayOutOfBounds exception.
+     */
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class DataLengthException
+		: CryptoException
+	{
+        /**
+        * base constructor.
+		*/
+        public DataLengthException()
+        {
+        }
+
+		/**
+         * create a DataLengthException with the given message.
+         *
+         * @param message the message to be carried with the exception.
+         */
+        public DataLengthException(
+            string message)
+			: base(message)
+        {
+		}
+
+		public DataLengthException(
+            string		message,
+            Exception	exception)
+			: base(message, exception)
+        {
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IAsymmetricBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/IAsymmetricBlockCipher.cs
new file mode 100644
index 0000000..455cfaa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IAsymmetricBlockCipher.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <remarks>Base interface for a public/private key block cipher.</remarks>
+	public interface IAsymmetricBlockCipher
+    {
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+        string AlgorithmName { get; }
+
+		/// <summary>Initialise the cipher.</summary>
+		/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+		/// <param name="parameters">The key or other data required by the cipher.</param>
+        void Init(bool forEncryption, ICipherParameters parameters);
+
+		/// <returns>The maximum size, in bytes, an input block may be.</returns>
+        int GetInputBlockSize();
+
+		/// <returns>The maximum size, in bytes, an output block will be.</returns>
+		int GetOutputBlockSize();
+
+		/// <summary>Process a block.</summary>
+		/// <param name="inBuf">The input buffer.</param>
+		/// <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+		/// <param name="inLen">The length of the input block.</param>
+		/// <exception cref="InvalidCipherTextException">Input decrypts improperly.</exception>
+		/// <exception cref="DataLengthException">Input is too large for the cipher.</exception>
+        byte[] ProcessBlock(byte[] inBuf, int inOff, int inLen);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IAsymmetricCipherKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/IAsymmetricCipherKeyPairGenerator.cs
new file mode 100644
index 0000000..9ec5dfa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IAsymmetricCipherKeyPairGenerator.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * interface that a public/private key pair generator should conform to.
+     */
+    public interface IAsymmetricCipherKeyPairGenerator
+    {
+        /**
+         * intialise the key pair generator.
+         *
+         * @param the parameters the key pair is to be initialised with.
+         */
+        void Init(KeyGenerationParameters parameters);
+
+        /**
+         * return an AsymmetricCipherKeyPair containing the Generated keys.
+         *
+         * @return an AsymmetricCipherKeyPair containing the Generated keys.
+         */
+        AsymmetricCipherKeyPair GenerateKeyPair();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/IBasicAgreement.cs
new file mode 100644
index 0000000..7dfc618
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IBasicAgreement.cs
@@ -0,0 +1,29 @@
+using System;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * The basic interface that basic Diffie-Hellman implementations
+     * conforms to.
+     */
+    public interface IBasicAgreement
+    {
+        /**
+         * initialise the agreement engine.
+         */
+        void Init(ICipherParameters parameters);
+
+        /**
+         * return the field size for the agreement algorithm in bytes.
+         */
+        int GetFieldSize();
+
+        /**
+         * given a public key from a given party calculate the next
+         * message in the agreement sequence.
+         */
+        BigInteger CalculateAgreement(ICipherParameters pubKey);
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/IBlockCipher.cs
new file mode 100644
index 0000000..a3ad6d6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IBlockCipher.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <remarks>Base interface for a symmetric key block cipher.</remarks>
+    public interface IBlockCipher
+    {
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+		string AlgorithmName { get; }
+
+		/// <summary>Initialise the cipher.</summary>
+		/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+		/// <param name="parameters">The key or other data required by the cipher.</param>
+		void Init(bool forEncryption, ICipherParameters parameters);
+
+		/// <returns>The block size for this cipher, in bytes.</returns>
+		int GetBlockSize();
+
+		/// <summary>Indicates whether this cipher can handle partial blocks.</summary>
+		bool IsPartialBlockOkay { get; }
+
+		/// <summary>Process a block.</summary>
+		/// <param name="inBuf">The input buffer.</param>
+		/// <param name="inOff">The offset into <paramref>inBuf</paramref> that the input block begins.</param>
+		/// <param name="outBuf">The output buffer.</param>
+		/// <param name="outOff">The offset into <paramref>outBuf</paramref> to write the output block.</param>
+		/// <exception cref="DataLengthException">If input block is wrong size, or outBuf too small.</exception>
+		/// <returns>The number of bytes processed and produced.</returns>
+		int ProcessBlock(byte[] inBuf, int inOff, byte[] outBuf, int outOff);
+
+		/// <summary>
+		/// Reset the cipher to the same state as it was after the last init (if there was one).
+		/// </summary>
+        void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IBufferedCipher.cs b/BouncyCastle.AxCrypt/src/crypto/IBufferedCipher.cs
new file mode 100644
index 0000000..69dec95
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IBufferedCipher.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <remarks>Block cipher engines are expected to conform to this interface.</remarks>
+    public interface IBufferedCipher
+    {
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+		string AlgorithmName { get; }
+
+		/// <summary>Initialise the cipher.</summary>
+		/// <param name="forEncryption">If true the cipher is initialised for encryption,
+		/// if false for decryption.</param>
+		/// <param name="parameters">The key and other data required by the cipher.</param>
+        void Init(bool forEncryption, ICipherParameters parameters);
+
+		int GetBlockSize();
+
+		int GetOutputSize(int inputLen);
+
+		int GetUpdateOutputSize(int inputLen);
+
+		byte[] ProcessByte(byte input);
+		int ProcessByte(byte input, byte[] output, int outOff);
+
+		byte[] ProcessBytes(byte[] input);
+		byte[] ProcessBytes(byte[] input, int inOff, int length);
+		int ProcessBytes(byte[] input, byte[] output, int outOff);
+		int ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff);
+
+		byte[] DoFinal();
+		byte[] DoFinal(byte[] input);
+		byte[] DoFinal(byte[] input, int inOff, int length);
+		int DoFinal(byte[] output, int outOff);
+		int DoFinal(byte[] input, byte[] output, int outOff);
+		int DoFinal(byte[] input, int inOff, int length, byte[] output, int outOff);
+
+		/// <summary>
+		/// Reset the cipher. After resetting the cipher is in the same state
+		/// as it was after the last init (if there was one).
+		/// </summary>
+        void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/ICipherParameters.cs b/BouncyCastle.AxCrypt/src/crypto/ICipherParameters.cs
new file mode 100644
index 0000000..fff0941
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/ICipherParameters.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * all parameter classes implement this.
+     */
+    public interface ICipherParameters
+    {
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IDSA.cs b/BouncyCastle.AxCrypt/src/crypto/IDSA.cs
new file mode 100644
index 0000000..46056d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IDSA.cs
@@ -0,0 +1,40 @@
+using System;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * interface for classes implementing the Digital Signature Algorithm
+     */
+    public interface IDsa
+    {
+		string AlgorithmName { get; }
+
+		/**
+         * initialise the signer for signature generation or signature
+         * verification.
+         *
+         * @param forSigning true if we are generating a signature, false
+         * otherwise.
+         * @param param key parameters for signature generation.
+         */
+        void Init(bool forSigning, ICipherParameters parameters);
+
+        /**
+         * sign the passed in message (usually the output of a hash function).
+         *
+         * @param message the message to be signed.
+         * @return two big integers representing the r and s values respectively.
+         */
+        BigInteger[] GenerateSignature(byte[] message);
+
+        /**
+         * verify the message message against the signature values r and s.
+         *
+         * @param message the message that was supposed to have been signed.
+         * @param r the r signature value.
+         * @param s the s signature value.
+         */
+        bool VerifySignature(byte[] message, BigInteger  r, BigInteger s);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IDerivationFunction.cs b/BouncyCastle.AxCrypt/src/crypto/IDerivationFunction.cs
new file mode 100644
index 0000000..7f289f7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IDerivationFunction.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * base interface for general purpose byte derivation functions.
+     */
+    public interface IDerivationFunction
+    {
+        void Init(IDerivationParameters parameters);
+
+        /**
+         * return the message digest used as the basis for the function
+         */
+        IDigest Digest
+        {
+            get;
+        }
+
+        int GenerateBytes(byte[] output, int outOff, int length);
+        //throws DataLengthException, ArgumentException;
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IDerivationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/IDerivationParameters.cs
new file mode 100644
index 0000000..f1c8485
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IDerivationParameters.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * Parameters for key/byte stream derivation classes
+     */
+    public interface IDerivationParameters
+    {
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IDigest.cs b/BouncyCastle.AxCrypt/src/crypto/IDigest.cs
new file mode 100644
index 0000000..6769dcc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IDigest.cs
@@ -0,0 +1,61 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * interface that a message digest conforms to.
+     */
+    public interface IDigest
+    {
+        /**
+         * return the algorithm name
+         *
+         * @return the algorithm name
+         */
+        string AlgorithmName { get; }
+
+		/**
+         * return the size, in bytes, of the digest produced by this message digest.
+         *
+         * @return the size, in bytes, of the digest produced by this message digest.
+         */
+		int GetDigestSize();
+
+		/**
+         * return the size, in bytes, of the internal buffer used by this digest.
+         *
+         * @return the size, in bytes, of the internal buffer used by this digest.
+         */
+		int GetByteLength();
+
+		/**
+         * update the message digest with a single byte.
+         *
+         * @param inByte the input byte to be entered.
+         */
+        void Update(byte input);
+
+        /**
+         * update the message digest with a block of bytes.
+         *
+         * @param input the byte array containing the data.
+         * @param inOff the offset into the byte array where the data starts.
+         * @param len the length of the data.
+         */
+        void BlockUpdate(byte[] input, int inOff, int length);
+
+        /**
+         * Close the digest, producing the final digest value. The doFinal
+         * call leaves the digest reset.
+         *
+         * @param output the array the digest is to be copied into.
+         * @param outOff the offset into the out array the digest is to start at.
+         */
+        int DoFinal(byte[] output, int outOff);
+
+        /**
+         * reset the digest back to it's initial state.
+         */
+        void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IMac.cs b/BouncyCastle.AxCrypt/src/crypto/IMac.cs
new file mode 100644
index 0000000..03a86e8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IMac.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * The base interface for implementations of message authentication codes (MACs).
+     */
+    public interface IMac
+    {
+        /**
+         * Initialise the MAC.
+         *
+         * @param param the key and other data required by the MAC.
+         * @exception ArgumentException if the parameters argument is
+         * inappropriate.
+         */
+        void Init(ICipherParameters parameters);
+
+        /**
+         * Return the name of the algorithm the MAC implements.
+         *
+         * @return the name of the algorithm the MAC implements.
+         */
+        string AlgorithmName { get; }
+
+		/**
+		 * Return the block size for this MAC (in bytes).
+		 *
+		 * @return the block size for this MAC in bytes.
+		 */
+		int GetMacSize();
+
+        /**
+         * add a single byte to the mac for processing.
+         *
+         * @param in the byte to be processed.
+         * @exception InvalidOperationException if the MAC is not initialised.
+         */
+        void Update(byte input);
+
+		/**
+         * @param in the array containing the input.
+         * @param inOff the index in the array the data begins at.
+         * @param len the length of the input starting at inOff.
+         * @exception InvalidOperationException if the MAC is not initialised.
+         * @exception DataLengthException if there isn't enough data in in.
+         */
+        void BlockUpdate(byte[] input, int inOff, int len);
+
+		/**
+         * Compute the final stage of the MAC writing the output to the out
+         * parameter.
+         * <p>
+         * doFinal leaves the MAC in the same state it was after the last init.
+         * </p>
+         * @param out the array the MAC is to be output to.
+         * @param outOff the offset into the out buffer the output is to start at.
+         * @exception DataLengthException if there isn't enough space in out.
+         * @exception InvalidOperationException if the MAC is not initialised.
+         */
+        int DoFinal(byte[] output, int outOff);
+
+		/**
+         * Reset the MAC. At the end of resetting the MAC should be in the
+         * in the same state it was after the last init (if there was one).
+         */
+        void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/ISigner.cs b/BouncyCastle.AxCrypt/src/crypto/ISigner.cs
new file mode 100644
index 0000000..e03bbf4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/ISigner.cs
@@ -0,0 +1,50 @@
+
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Crypto
+{
+    public interface ISigner
+    {
+        /**
+         * Return the name of the algorithm the signer implements.
+         *
+         * @return the name of the algorithm the signer implements.
+         */
+        string AlgorithmName { get; }
+
+		/**
+         * Initialise the signer for signing or verification.
+         *
+         * @param forSigning true if for signing, false otherwise
+         * @param param necessary parameters.
+         */
+         void Init(bool forSigning, ICipherParameters parameters);
+
+        /**
+         * update the internal digest with the byte b
+         */
+        void Update(byte input);
+
+        /**
+         * update the internal digest with the byte array in
+         */
+        void BlockUpdate(byte[] input, int inOff, int length);
+
+        /**
+         * Generate a signature for the message we've been loaded with using
+         * the key we were initialised with.
+         */
+        byte[] GenerateSignature();
+        /**
+         * return true if the internal state represents the signature described
+         * in the passed in array.
+         */
+        bool VerifySignature(byte[] signature);
+
+        /**
+         * reset the internal state
+         */
+        void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/ISignerWithRecovery.cs b/BouncyCastle.AxCrypt/src/crypto/ISignerWithRecovery.cs
new file mode 100644
index 0000000..024f5ce
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/ISignerWithRecovery.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * Signer with message recovery.
+     */
+    public interface ISignerWithRecovery
+        : ISigner
+    {
+        /**
+         * Returns true if the signer has recovered the full message as
+         * part of signature verification.
+         *
+         * @return true if full message recovered.
+         */
+        bool HasFullMessage();
+
+        /**
+         * Returns a reference to what message was recovered (if any).
+         *
+         * @return full/partial message, null if nothing.
+         */
+        byte[] GetRecoveredMessage();
+
+		/**
+		 * Perform an update with the recovered message before adding any other data. This must
+		 * be the first update method called, and calling it will result in the signer assuming
+		 * that further calls to update will include message content past what is recoverable.
+		 *
+		 * @param signature the signature that we are in the process of verifying.
+		 * @throws IllegalStateException
+		 */
+		void UpdateWithRecoveredMessage(byte[] signature);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IStreamCipher.cs b/BouncyCastle.AxCrypt/src/crypto/IStreamCipher.cs
new file mode 100644
index 0000000..8e575a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IStreamCipher.cs
@@ -0,0 +1,45 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <summary>The interface stream ciphers conform to.</summary>
+    public interface IStreamCipher
+    {
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+		string AlgorithmName { get; }
+
+		/// <summary>Initialise the cipher.</summary>
+		/// <param name="forEncryption">If true the cipher is initialised for encryption,
+		/// if false for decryption.</param>
+		/// <param name="parameters">The key and other data required by the cipher.</param>
+		/// <exception cref="ArgumentException">
+		/// If the parameters argument is inappropriate.
+		/// </exception>
+        void Init(bool forEncryption, ICipherParameters parameters);
+
+		/// <summary>encrypt/decrypt a single byte returning the result.</summary>
+		/// <param name="input">the byte to be processed.</param>
+		/// <returns>the result of processing the input byte.</returns>
+        byte ReturnByte(byte input);
+
+		/// <summary>
+		/// Process a block of bytes from <c>input</c> putting the result into <c>output</c>.
+		/// </summary>
+		/// <param name="input">The input byte array.</param>
+		/// <param name="inOff">
+		/// The offset into <c>input</c> where the data to be processed starts.
+		/// </param>
+		/// <param name="length">The number of bytes to be processed.</param>
+		/// <param name="output">The output buffer the processed bytes go into.</param>
+		/// <param name="outOff">
+		/// The offset into <c>output</c> the processed data starts at.
+		/// </param>
+		/// <exception cref="DataLengthException">If the output buffer is too small.</exception>
+        void ProcessBytes(byte[] input, int inOff, int length, byte[] output, int outOff);
+
+		/// <summary>
+		/// Reset the cipher to the same state as it was after the last init (if there was one).
+		/// </summary>
+		void Reset();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/IWrapper.cs b/BouncyCastle.AxCrypt/src/crypto/IWrapper.cs
new file mode 100644
index 0000000..58202b3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/IWrapper.cs
@@ -0,0 +1,18 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto
+{
+    public interface IWrapper
+    {
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+		string AlgorithmName { get; }
+
+		void Init(bool forWrapping, ICipherParameters parameters);
+
+		byte[] Wrap(byte[] input, int inOff, int length);
+
+        byte[] Unwrap(byte[] input, int inOff, int length);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/InvalidCipherTextException.cs b/BouncyCastle.AxCrypt/src/crypto/InvalidCipherTextException.cs
new file mode 100644
index 0000000..4d22526
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/InvalidCipherTextException.cs
@@ -0,0 +1,40 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * this exception is thrown whenever we find something we don't expect in a
+     * message.
+     */
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class InvalidCipherTextException
+		: CryptoException
+    {
+		/**
+		* base constructor.
+		*/
+        public InvalidCipherTextException()
+        {
+        }
+
+		/**
+         * create a InvalidCipherTextException with the given message.
+         *
+         * @param message the message to be carried with the exception.
+         */
+        public InvalidCipherTextException(
+            string message)
+			: base(message)
+        {
+        }
+
+		public InvalidCipherTextException(
+            string		message,
+            Exception	exception)
+			: base(message, exception)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/KeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/KeyGenerationParameters.cs
new file mode 100644
index 0000000..0cb6b07
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/KeyGenerationParameters.cs
@@ -0,0 +1,55 @@
+using System;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * The base class for parameters to key generators.
+     */
+    public class KeyGenerationParameters
+    {
+        private SecureRandom	random;
+        private int				strength;
+
+        /**
+         * initialise the generator with a source of randomness
+         * and a strength (in bits).
+         *
+         * @param random the random byte source.
+         * @param strength the size, in bits, of the keys we want to produce.
+         */
+        public KeyGenerationParameters(
+            SecureRandom	random,
+            int				strength)
+        {
+			if (random == null)
+				throw new ArgumentNullException("random");
+			if (strength < 1)
+				throw new ArgumentException("strength must be a positive value", "strength");
+
+			this.random = random;
+            this.strength = strength;
+        }
+
+		/**
+         * return the random source associated with this
+         * generator.
+         *
+         * @return the generators random source.
+         */
+        public SecureRandom Random
+        {
+            get { return random; }
+        }
+
+		/**
+         * return the bit strength for keys produced by this generator,
+         *
+         * @return the strength of the keys this generator produces (in bits).
+         */
+        public int Strength
+        {
+            get { return strength; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/MaxBytesExceededException.cs b/BouncyCastle.AxCrypt/src/crypto/MaxBytesExceededException.cs
new file mode 100644
index 0000000..be078cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/MaxBytesExceededException.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/// <summary>
+	/// This exception is thrown whenever a cipher requires a change of key, iv
+	/// or similar after x amount of bytes enciphered
+	/// </summary>
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class MaxBytesExceededException
+		: CryptoException
+	{
+		public MaxBytesExceededException()
+		{
+		}
+
+		public MaxBytesExceededException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public MaxBytesExceededException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/PbeParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/PbeParametersGenerator.cs
new file mode 100644
index 0000000..21679d4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/PbeParametersGenerator.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto
+{
+    /**
+     * super class for all Password Based Encyrption (Pbe) parameter generator classes.
+     */
+    public abstract class PbeParametersGenerator
+    {
+        protected byte[]	mPassword;
+        protected byte[]	mSalt;
+        protected int		mIterationCount;
+
+        /**
+         * base constructor.
+         */
+        protected PbeParametersGenerator()
+        {
+        }
+
+        /**
+         * initialise the Pbe generator.
+         *
+         * @param password the password converted into bytes (see below).
+         * @param salt the salt to be mixed with the password.
+         * @param iterationCount the number of iterations the "mixing" function
+         * is to be applied for.
+         */
+        public virtual void Init(
+            byte[]  password,
+            byte[]  salt,
+            int     iterationCount)
+        {
+            if (password == null)
+                throw new ArgumentNullException("password");
+            if (salt == null)
+                throw new ArgumentNullException("salt");
+
+            this.mPassword = Arrays.Clone(password);
+            this.mSalt = Arrays.Clone(salt);
+            this.mIterationCount = iterationCount;
+        }
+
+        public virtual byte[] Password
+        {
+            get { return Arrays.Clone(mPassword); }
+        }
+
+        /**
+         * return the password byte array.
+         *
+         * @return the password byte array.
+         */
+        [Obsolete("Use 'Password' property")]
+        public byte[] GetPassword()
+        {
+            return Password;
+        }
+
+        public virtual byte[] Salt
+        {
+            get { return Arrays.Clone(mSalt); }
+        }
+
+        /**
+         * return the salt byte array.
+         *
+         * @return the salt byte array.
+         */
+        [Obsolete("Use 'Salt' property")]
+        public byte[] GetSalt()
+        {
+            return Salt;
+        }
+
+        /**
+         * return the iteration count.
+         *
+         * @return the iteration count.
+         */
+        public virtual int IterationCount
+        {
+            get { return mIterationCount; }
+        }
+
+        /**
+         * Generate derived parameters for a key of length keySize.
+         *
+         * @param keySize the length, in bits, of the key required.
+         * @return a parameters object representing a key.
+         */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public abstract ICipherParameters GenerateDerivedParameters(int keySize);
+        public abstract ICipherParameters GenerateDerivedParameters(string algorithm, int keySize);
+
+        /**
+         * Generate derived parameters for a key of length keySize, and
+         * an initialisation vector (IV) of length ivSize.
+         *
+         * @param keySize the length, in bits, of the key required.
+         * @param ivSize the length, in bits, of the iv required.
+         * @return a parameters object representing a key and an IV.
+         */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public abstract ICipherParameters GenerateDerivedParameters(int keySize, int ivSize);
+        public abstract ICipherParameters GenerateDerivedParameters(string algorithm, int keySize, int ivSize);
+
+        /**
+         * Generate derived parameters for a key of length keySize, specifically
+         * for use with a MAC.
+         *
+         * @param keySize the length, in bits, of the key required.
+         * @return a parameters object representing a key.
+         */
+        public abstract ICipherParameters GenerateDerivedMacParameters(int keySize);
+
+        /**
+         * converts a password to a byte array according to the scheme in
+         * Pkcs5 (ascii, no padding)
+         *
+         * @param password a character array representing the password.
+         * @return a byte array representing the password.
+         */
+        public static byte[] Pkcs5PasswordToBytes(
+            char[] password)
+        {
+            if (password == null)
+                return new byte[0];
+
+            return Strings.ToAsciiByteArray(password);
+        }
+
+        [Obsolete("Use version taking 'char[]' instead")]
+        public static byte[] Pkcs5PasswordToBytes(
+            string password)
+        {
+            if (password == null)
+                return new byte[0];
+
+            return Strings.ToAsciiByteArray(password);
+        }
+
+        /**
+         * converts a password to a byte array according to the scheme in
+         * PKCS5 (UTF-8, no padding)
+         *
+         * @param password a character array representing the password.
+         * @return a byte array representing the password.
+         */
+        public static byte[] Pkcs5PasswordToUtf8Bytes(
+            char[] password)
+        {
+            if (password == null)
+                return new byte[0];
+
+            return Encoding.UTF8.GetBytes(password);
+        }
+
+        [Obsolete("Use version taking 'char[]' instead")]
+        public static byte[] Pkcs5PasswordToUtf8Bytes(
+            string password)
+        {
+            if (password == null)
+                return new byte[0];
+
+            return Encoding.UTF8.GetBytes(password);
+        }
+
+        /**
+         * converts a password to a byte array according to the scheme in
+         * Pkcs12 (unicode, big endian, 2 zero pad bytes at the end).
+         *
+         * @param password a character array representing the password.
+         * @return a byte array representing the password.
+         */
+        public static byte[] Pkcs12PasswordToBytes(
+            char[] password)
+        {
+            return Pkcs12PasswordToBytes(password, false);
+        }
+
+        public static byte[] Pkcs12PasswordToBytes(
+            char[]	password,
+            bool	wrongPkcs12Zero)
+        {
+            if (password == null || password.Length < 1)
+            {
+                return new byte[wrongPkcs12Zero ? 2 : 0];
+            }
+
+            // +1 for extra 2 pad bytes.
+            byte[] bytes = new byte[(password.Length + 1) * 2];
+
+            Encoding.BigEndianUnicode.GetBytes(password, 0, password.Length, bytes, 0);
+
+            return bytes;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/StreamBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/StreamBlockCipher.cs
new file mode 100644
index 0000000..ef2a8b6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/StreamBlockCipher.cs
@@ -0,0 +1,109 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto
+{
+	/**
+	 * a wrapper for block ciphers with a single byte block size, so that they
+	 * can be treated like stream ciphers.
+	 */
+	public class StreamBlockCipher
+		: IStreamCipher
+	{
+		private readonly IBlockCipher cipher;
+		private readonly byte[] oneByte = new byte[1];
+
+		/**
+		 * basic constructor.
+		 *
+		 * @param cipher the block cipher to be wrapped.
+		 * @exception ArgumentException if the cipher has a block size other than
+		 * one.
+		 */
+		public StreamBlockCipher(
+			IBlockCipher cipher)
+		{
+			if (cipher == null)
+				throw new ArgumentNullException("cipher");
+			if (cipher.GetBlockSize() != 1)
+				throw new ArgumentException("block cipher block size != 1.", "cipher");
+
+			this.cipher = cipher;
+		}
+
+		/**
+		 * initialise the underlying cipher.
+		 *
+		 * @param forEncryption true if we are setting up for encryption, false otherwise.
+		 * @param param the necessary parameters for the underlying cipher to be initialised.
+		 */
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			cipher.Init(forEncryption, parameters);
+		}
+
+		/**
+		* return the name of the algorithm we are wrapping.
+		*
+		* @return the name of the algorithm we are wrapping.
+		*/
+		public string AlgorithmName
+		{
+			get { return cipher.AlgorithmName; }
+		}
+
+		/**
+		* encrypt/decrypt a single byte returning the result.
+		*
+		* @param in the byte to be processed.
+		* @return the result of processing the input byte.
+		*/
+		public byte ReturnByte(
+			byte input)
+		{
+			oneByte[0] = input;
+
+			cipher.ProcessBlock(oneByte, 0, oneByte, 0);
+
+			return oneByte[0];
+		}
+
+		/**
+		* process a block of bytes from in putting the result into out.
+		*
+		* @param in the input byte array.
+		* @param inOff the offset into the in array where the data to be processed starts.
+		* @param len the number of bytes to be processed.
+		* @param out the output buffer the processed bytes go into.
+		* @param outOff the offset into the output byte array the processed data stars at.
+		* @exception DataLengthException if the output buffer is too small.
+		*/
+		public void ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			if (outOff + length > output.Length)
+				throw new DataLengthException("output buffer too small in ProcessBytes()");
+
+			for (int i = 0; i != length; i++)
+			{
+				cipher.ProcessBlock(input, inOff + i, output, outOff + i);
+			}
+		}
+
+		/**
+		* reset the underlying cipher. This leaves it in the same state
+		* it was at after the last init (if there was one).
+		*/
+		public void Reset()
+		{
+			cipher.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/DHAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/DHAgreement.cs
new file mode 100644
index 0000000..d214caa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/DHAgreement.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+	/**
+	 * a Diffie-Hellman key exchange engine.
+	 * <p>
+	 * note: This uses MTI/A0 key agreement in order to make the key agreement
+	 * secure against passive attacks. If you're doing Diffie-Hellman and both
+	 * parties have long term public keys you should look at using this. For
+	 * further information have a look at RFC 2631.</p>
+	 * <p>
+	 * It's possible to extend this to more than two parties as well, for the moment
+	 * that is left as an exercise for the reader.</p>
+	 */
+	public class DHAgreement
+	{
+		private DHPrivateKeyParameters  key;
+		private DHParameters			dhParams;
+		private BigInteger				privateValue;
+		private SecureRandom			random;
+
+		public void Init(
+			ICipherParameters parameters)
+		{
+			AsymmetricKeyParameter kParam;
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+				this.random = rParam.Random;
+				kParam = (AsymmetricKeyParameter)rParam.Parameters;
+			}
+			else
+			{
+				this.random = new SecureRandom();
+				kParam = (AsymmetricKeyParameter)parameters;
+			}
+
+			if (!(kParam is DHPrivateKeyParameters))
+			{
+				throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
+			}
+
+			this.key = (DHPrivateKeyParameters)kParam;
+			this.dhParams = key.Parameters;
+		}
+
+		/**
+		 * calculate our initial message.
+		 */
+		public BigInteger CalculateMessage()
+		{
+			DHKeyPairGenerator dhGen = new DHKeyPairGenerator();
+			dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
+			AsymmetricCipherKeyPair dhPair = dhGen.GenerateKeyPair();
+
+			this.privateValue = ((DHPrivateKeyParameters)dhPair.Private).X;
+
+			return ((DHPublicKeyParameters)dhPair.Public).Y;
+		}
+
+		/**
+		 * given a message from a given party and the corresponding public key
+		 * calculate the next message in the agreement sequence. In this case
+		 * this will represent the shared secret.
+		 */
+		public BigInteger CalculateAgreement(
+			DHPublicKeyParameters	pub,
+			BigInteger				message)
+		{
+			if (pub == null)
+				throw new ArgumentNullException("pub");
+			if (message == null)
+				throw new ArgumentNullException("message");
+
+			if (!pub.Parameters.Equals(dhParams))
+			{
+				throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
+			}
+
+			BigInteger p = dhParams.P;
+
+			return message.ModPow(key.X, p).Multiply(pub.Y.ModPow(privateValue, p)).Mod(p);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/DHBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/DHBasicAgreement.cs
new file mode 100644
index 0000000..75b5e9d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/DHBasicAgreement.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+    /**
+     * a Diffie-Hellman key agreement class.
+     * <p>
+     * note: This is only the basic algorithm, it doesn't take advantage of
+     * long term public keys if they are available. See the DHAgreement class
+     * for a "better" implementation.</p>
+     */
+    public class DHBasicAgreement
+        : IBasicAgreement
+    {
+        private DHPrivateKeyParameters	key;
+        private DHParameters			dhParams;
+
+        public virtual void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is ParametersWithRandom)
+            {
+                parameters = ((ParametersWithRandom) parameters).Parameters;
+            }
+
+            if (!(parameters is DHPrivateKeyParameters))
+            {
+                throw new ArgumentException("DHEngine expects DHPrivateKeyParameters");
+            }
+
+            this.key = (DHPrivateKeyParameters) parameters;
+            this.dhParams = key.Parameters;
+        }
+
+        public virtual int GetFieldSize()
+        {
+            return (key.Parameters.P.BitLength + 7) / 8;
+        }
+
+        /**
+         * given a short term public key from a given party calculate the next
+         * message in the agreement sequence.
+         */
+        public virtual BigInteger CalculateAgreement(
+            ICipherParameters pubKey)
+        {
+            if (this.key == null)
+                throw new InvalidOperationException("Agreement algorithm not initialised");
+
+            DHPublicKeyParameters pub = (DHPublicKeyParameters)pubKey;
+
+            if (!pub.Parameters.Equals(dhParams))
+            {
+                throw new ArgumentException("Diffie-Hellman public key has wrong parameters.");
+            }
+
+            return pub.Y.ModPow(key.X, dhParams.P);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/DHStandardGroups.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/DHStandardGroups.cs
new file mode 100644
index 0000000..6c46b60
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/DHStandardGroups.cs
@@ -0,0 +1,206 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+    /// <summary>Standard Diffie-Hellman groups from various IETF specifications.</summary>
+    public class DHStandardGroups
+    {
+        private static DHParameters FromPG(string hexP, string hexG)
+        {
+            BigInteger p = new BigInteger(1, Hex.Decode(hexP));
+            BigInteger g = new BigInteger(1, Hex.Decode(hexG));
+            return new DHParameters(p, g);
+        }
+
+        private static DHParameters FromPGQ(string hexP, string hexG, string hexQ)
+        {
+            BigInteger p = new BigInteger(1, Hex.Decode(hexP));
+            BigInteger g = new BigInteger(1, Hex.Decode(hexG));
+            BigInteger q = new BigInteger(1, Hex.Decode(hexQ));
+            return new DHParameters(p, g, q);
+        }
+
+        /*
+         * RFC 2409
+         */
+        private static readonly string rfc2409_768_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF";
+        private static readonly string rfc2409_768_g = "02";
+        public static readonly DHParameters rfc2409_768 = FromPG(rfc2409_768_p, rfc2409_768_g);
+
+        private static readonly string rfc2409_1024_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
+            + "FFFFFFFFFFFFFFFF";
+        private static readonly string rfc2409_1024_g = "02";
+        public static readonly DHParameters rfc2409_1024 = FromPG(rfc2409_1024_p, rfc2409_1024_g);
+
+        /*
+         * RFC 3526
+         */
+        private static readonly string rfc3526_1536_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_1536_g = "02";
+        public static readonly DHParameters rfc3526_1536 = FromPG(rfc3526_1536_p, rfc3526_1536_g);
+
+        private static readonly string rfc3526_2048_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AACAA68FFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_2048_g = "02";
+        public static readonly DHParameters rfc3526_2048 = FromPG(rfc3526_2048_p, rfc3526_2048_g);
+
+        private static readonly string rfc3526_3072_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+            + "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_3072_g = "02";
+        public static readonly DHParameters rfc3526_3072 = FromPG(rfc3526_3072_p, rfc3526_3072_g);
+
+        private static readonly string rfc3526_4096_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+            + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+            + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+            + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
+            + "FFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_4096_g = "02";
+        public static readonly DHParameters rfc3526_4096 = FromPG(rfc3526_4096_p, rfc3526_4096_g);
+
+        private static readonly string rfc3526_6144_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08"
+            + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B"
+            + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9"
+            + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6"
+            + "49286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8"
+            + "FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C"
+            + "180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF695581718"
+            + "3995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D"
+            + "04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7D"
+            + "B3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D226"
+            + "1AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
+            + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFC"
+            + "E0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B26"
+            + "99C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB"
+            + "04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2"
+            + "233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127"
+            + "D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+            + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406"
+            + "AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918"
+            + "DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B33205151"
+            + "2BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03"
+            + "F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97F"
+            + "BEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
+            + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58B"
+            + "B7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632"
+            + "387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E"
+            + "6DCC4024FFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_6144_g = "02";
+        public static readonly DHParameters rfc3526_6144 = FromPG(rfc3526_6144_p, rfc3526_6144_g);
+
+        private static readonly string rfc3526_8192_p = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
+            + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
+            + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
+            + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
+            + "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" + "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
+            + "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" + "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
+            + "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" + "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
+            + "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" + "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
+            + "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" + "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
+            + "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" + "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
+            + "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" + "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
+            + "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" + "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
+            + "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" + "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
+            + "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" + "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
+            + "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" + "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
+            + "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" + "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
+            + "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" + "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
+            + "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" + "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
+            + "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" + "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
+            + "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" + "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
+            + "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" + "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
+            + "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" + "60C980DD98EDD3DFFFFFFFFFFFFFFFFF";
+        private static readonly string rfc3526_8192_g = "02";
+        public static readonly DHParameters rfc3526_8192 = FromPG(rfc3526_8192_p, rfc3526_8192_g);
+
+        /*
+         * RFC 4306
+         */
+        public static readonly DHParameters rfc4306_768 = rfc2409_768;
+        public static readonly DHParameters rfc4306_1024 = rfc2409_1024;
+
+        /*
+         * RFC 5114
+         */
+        private static readonly string rfc5114_1024_160_p = "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
+            + "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" + "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
+            + "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" + "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
+            + "DF1FB2BC2E4A4371";
+        private static readonly string rfc5114_1024_160_g = "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
+            + "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" + "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
+            + "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" + "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
+            + "855E6EEB22B3B2E5";
+        private static readonly string rfc5114_1024_160_q = "F518AA8781A8DF278ABA4E7D64B7CB9D49462353";
+        public static readonly DHParameters rfc5114_1024_160 = FromPGQ(rfc5114_1024_160_p, rfc5114_1024_160_g,
+            rfc5114_1024_160_q);
+
+        private static readonly string rfc5114_2048_224_p = "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
+            + "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" + "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
+            + "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" + "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
+            + "B3BF8A317091883681286130BC8985DB1602E714415D9330" + "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
+            + "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" + "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
+            + "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" + "CF9DE5384E71B81C0AC4DFFE0C10E64F";
+        private static readonly string rfc5114_2048_224_g = "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
+            + "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" + "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
+            + "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" + "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
+            + "F180EB34118E98D119529A45D6F834566E3025E316A330EF" + "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
+            + "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" + "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
+            + "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" + "81BC087F2A7065B384B890D3191F2BFA";
+        private static readonly string rfc5114_2048_224_q = "801C0D34C58D93FE997177101F80535A4738CEBCBF389A99B36371EB";
+        public static readonly DHParameters rfc5114_2048_224 = FromPGQ(rfc5114_2048_224_p, rfc5114_2048_224_g,
+            rfc5114_2048_224_q);
+
+        private static readonly string rfc5114_2048_256_p = "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2"
+            + "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30" + "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD"
+            + "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B" + "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C"
+            + "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E" + "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9"
+            + "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026" + "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3"
+            + "75F26375D7014103A4B54330C198AF126116D2276E11715F" + "693877FAD7EF09CADB094AE91E1A1597";
+        private static readonly string rfc5114_2048_256_g = "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054"
+            + "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555" + "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18"
+            + "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B" + "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83"
+            + "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55" + "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14"
+            + "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915" + "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6"
+            + "184B523D1DB246C32F63078490F00EF8D647D148D4795451" + "5E2327CFEF98C582664B4C0F6CC41659";
+        private static readonly string rfc5114_2048_256_q = "8CF83642A709A097B447997640129DA299B1A47D1EB3750B"
+            + "A308B0FE64F5FBD3";
+        public static readonly DHParameters rfc5114_2048_256 = FromPGQ(rfc5114_2048_256_p, rfc5114_2048_256_g,
+            rfc5114_2048_256_q);
+
+        /*
+         * RFC 5996
+         */
+        public static readonly DHParameters rfc5996_768 = rfc4306_768;
+        public static readonly DHParameters rfc5996_1024 = rfc4306_1024;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHBasicAgreement.cs
new file mode 100644
index 0000000..c33f16f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHBasicAgreement.cs
@@ -0,0 +1,57 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+    /**
+     * P1363 7.2.1 ECSVDP-DH
+     *
+     * ECSVDP-DH is Elliptic Curve Secret Value Derivation Primitive,
+     * Diffie-Hellman version. It is based on the work of [DH76], [Mil86],
+     * and [Kob87]. This primitive derives a shared secret value from one
+     * party's private key and another party's public key, where both have
+     * the same set of EC domain parameters. If two parties correctly
+     * execute this primitive, they will produce the same output. This
+     * primitive can be invoked by a scheme to derive a shared secret key;
+     * specifically, it may be used with the schemes ECKAS-DH1 and
+     * DL/ECKAS-DH2. It assumes that the input keys are valid (see also
+     * Section 7.2.2).
+     */
+    public class ECDHBasicAgreement
+        : IBasicAgreement
+    {
+        protected internal ECPrivateKeyParameters privKey;
+
+        public virtual void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is ParametersWithRandom)
+            {
+                parameters = ((ParametersWithRandom)parameters).Parameters;
+            }
+
+            this.privKey = (ECPrivateKeyParameters)parameters;
+        }
+
+        public virtual int GetFieldSize()
+        {
+            return (privKey.Parameters.Curve.FieldSize + 7) / 8;
+        }
+
+        public virtual BigInteger CalculateAgreement(
+            ICipherParameters pubKey)
+        {
+            ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey;
+            ECPoint P = pub.Q.Multiply(privKey.D).Normalize();
+
+            if (P.IsInfinity)
+                throw new InvalidOperationException("Infinity is not a valid agreement value for ECDH");
+
+            return P.AffineXCoord.ToBigInteger();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHCBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHCBasicAgreement.cs
new file mode 100644
index 0000000..89be706
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHCBasicAgreement.cs
@@ -0,0 +1,66 @@
+using System;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+    /**
+     * P1363 7.2.2 ECSVDP-DHC
+     *
+     * ECSVDP-DHC is Elliptic Curve Secret Value Derivation Primitive,
+     * Diffie-Hellman version with cofactor multiplication. It is based on
+     * the work of [DH76], [Mil86], [Kob87], [LMQ98] and [Kal98a]. This
+     * primitive derives a shared secret value from one party's private key
+     * and another party's public key, where both have the same set of EC
+     * domain parameters. If two parties correctly execute this primitive,
+     * they will produce the same output. This primitive can be invoked by a
+     * scheme to derive a shared secret key; specifically, it may be used
+     * with the schemes ECKAS-DH1 and DL/ECKAS-DH2. It does not assume the
+     * validity of the input public key (see also Section 7.2.1).
+     * <p>
+     * Note: As stated P1363 compatibility mode with ECDH can be preset, and
+     * in this case the implementation doesn't have a ECDH compatibility mode
+     * (if you want that just use ECDHBasicAgreement and note they both implement
+     * BasicAgreement!).</p>
+     */
+    public class ECDHCBasicAgreement
+        : IBasicAgreement
+    {
+        private ECPrivateKeyParameters key;
+
+        public virtual void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is ParametersWithRandom)
+            {
+                parameters = ((ParametersWithRandom) parameters).Parameters;
+            }
+
+            this.key = (ECPrivateKeyParameters)parameters;
+        }
+
+        public virtual int GetFieldSize()
+        {
+            return (key.Parameters.Curve.FieldSize + 7) / 8;
+        }
+
+        public virtual BigInteger CalculateAgreement(
+            ICipherParameters pubKey)
+        {
+            ECPublicKeyParameters pub = (ECPublicKeyParameters) pubKey;
+            ECDomainParameters parameters = pub.Parameters;
+
+            BigInteger hd = parameters.H.Multiply(key.D).Mod(parameters.N);
+
+            ECPoint P = pub.Q.Multiply(hd).Normalize();
+
+            if (P.IsInfinity)
+                throw new InvalidOperationException("Infinity is not a valid agreement value for ECDHC");
+
+            return P.AffineXCoord.ToBigInteger();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs
new file mode 100644
index 0000000..1de80d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/ECDHWithKdfBasicAgreement.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+	public class ECDHWithKdfBasicAgreement
+		: ECDHBasicAgreement
+	{
+		private readonly string algorithm;
+		private readonly IDerivationFunction kdf;
+
+		public ECDHWithKdfBasicAgreement(
+			string				algorithm,
+			IDerivationFunction	kdf)
+		{
+			if (algorithm == null)
+				throw new ArgumentNullException("algorithm");
+			if (kdf == null)
+				throw new ArgumentNullException("kdf");
+
+			this.algorithm = algorithm;
+			this.kdf = kdf;
+		}
+
+		public override BigInteger CalculateAgreement(
+			ICipherParameters pubKey)
+		{
+			// Note that the ec.KeyAgreement class in JCE only uses kdf in one
+			// of the engineGenerateSecret methods.
+
+			BigInteger result = base.CalculateAgreement(pubKey);
+
+			int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
+
+			DHKdfParameters dhKdfParams = new DHKdfParameters(
+				new DerObjectIdentifier(algorithm),
+				keySize,
+				BigIntToBytes(result));
+
+			kdf.Init(dhKdfParams);
+
+			byte[] keyBytes = new byte[keySize / 8];
+			kdf.GenerateBytes(keyBytes, 0, keyBytes.Length);
+
+			return new BigInteger(1, keyBytes);
+		}
+
+		private byte[] BigIntToBytes(BigInteger r)
+		{
+			int byteLength = X9IntegerConverter.GetByteLength(privKey.Parameters.Curve);
+			return X9IntegerConverter.IntegerToBytes(r, byteLength);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvBasicAgreement.cs
new file mode 100644
index 0000000..f55ae46
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvBasicAgreement.cs
@@ -0,0 +1,89 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+    public class ECMqvBasicAgreement
+        : IBasicAgreement
+    {
+        protected internal MqvPrivateParameters privParams;
+
+        public virtual void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is ParametersWithRandom)
+            {
+                parameters = ((ParametersWithRandom)parameters).Parameters;
+            }
+
+            this.privParams = (MqvPrivateParameters)parameters;
+        }
+
+        public virtual int GetFieldSize()
+        {
+            return (privParams.StaticPrivateKey.Parameters.Curve.FieldSize + 7) / 8;
+        }
+
+        public virtual BigInteger CalculateAgreement(
+            ICipherParameters pubKey)
+        {
+            MqvPublicParameters pubParams = (MqvPublicParameters)pubKey;
+
+            ECPrivateKeyParameters staticPrivateKey = privParams.StaticPrivateKey;
+
+            ECPoint agreement = CalculateMqvAgreement(staticPrivateKey.Parameters, staticPrivateKey,
+                privParams.EphemeralPrivateKey, privParams.EphemeralPublicKey,
+                pubParams.StaticPublicKey, pubParams.EphemeralPublicKey).Normalize();
+
+            if (agreement.IsInfinity)
+                throw new InvalidOperationException("Infinity is not a valid agreement value for MQV");
+
+            return agreement.AffineXCoord.ToBigInteger();
+        }
+
+        // The ECMQV Primitive as described in SEC-1, 3.4
+        private static ECPoint CalculateMqvAgreement(
+            ECDomainParameters		parameters,
+            ECPrivateKeyParameters	d1U,
+            ECPrivateKeyParameters	d2U,
+            ECPublicKeyParameters	Q2U,
+            ECPublicKeyParameters	Q1V,
+            ECPublicKeyParameters	Q2V)
+        {
+            BigInteger n = parameters.N;
+            int e = (n.BitLength + 1) / 2;
+            BigInteger powE = BigInteger.One.ShiftLeft(e);
+
+            ECCurve curve = parameters.Curve;
+
+            ECPoint[] points = new ECPoint[]{
+                // The Q2U public key is optional
+                ECAlgorithms.ImportPoint(curve, Q2U == null ? parameters.G.Multiply(d2U.D) : Q2U.Q),
+                ECAlgorithms.ImportPoint(curve, Q1V.Q),
+                ECAlgorithms.ImportPoint(curve, Q2V.Q)
+            };
+
+            curve.NormalizeAll(points);
+
+            ECPoint q2u = points[0], q1v = points[1], q2v = points[2];
+
+            BigInteger x = q2u.AffineXCoord.ToBigInteger();
+            BigInteger xBar = x.Mod(powE);
+            BigInteger Q2UBar = xBar.SetBit(e);
+            BigInteger s = d1U.D.Multiply(Q2UBar).Add(d2U.D).Mod(n);
+
+            BigInteger xPrime = q2v.AffineXCoord.ToBigInteger();
+            BigInteger xPrimeBar = xPrime.Mod(powE);
+            BigInteger Q2VBar = xPrimeBar.SetBit(e);
+
+            BigInteger hs = parameters.H.Multiply(s).Mod(n);
+
+            return ECAlgorithms.SumOfTwoMultiplies(
+                q1v, Q2VBar.Multiply(hs).Mod(n), q2v, hs);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs
new file mode 100644
index 0000000..7d79fc4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/ECMqvWithKdfBasicAgreement.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement
+{
+	public class ECMqvWithKdfBasicAgreement
+		: ECMqvBasicAgreement
+	{
+		private readonly string algorithm;
+		private readonly IDerivationFunction kdf;
+
+		public ECMqvWithKdfBasicAgreement(
+			string				algorithm,
+			IDerivationFunction	kdf)
+		{
+			if (algorithm == null)
+				throw new ArgumentNullException("algorithm");
+			if (kdf == null)
+				throw new ArgumentNullException("kdf");
+
+			this.algorithm = algorithm;
+			this.kdf = kdf;
+		}
+
+		public override BigInteger CalculateAgreement(
+			ICipherParameters pubKey)
+		{
+			// Note that the ec.KeyAgreement class in JCE only uses kdf in one
+			// of the engineGenerateSecret methods.
+
+			BigInteger result = base.CalculateAgreement(pubKey);
+
+			int keySize = GeneratorUtilities.GetDefaultKeySize(algorithm);
+
+			DHKdfParameters dhKdfParams = new DHKdfParameters(
+				new DerObjectIdentifier(algorithm),
+				keySize,
+				BigIntToBytes(result));
+
+			kdf.Init(dhKdfParams);
+
+			byte[] keyBytes = new byte[keySize / 8];
+			kdf.GenerateBytes(keyBytes, 0, keyBytes.Length);
+
+			return new BigInteger(1, keyBytes);
+		}
+
+		private byte[] BigIntToBytes(BigInteger r)
+		{
+			int byteLength = X9IntegerConverter.GetByteLength(privParams.StaticPrivateKey.Parameters.Curve);
+			return X9IntegerConverter.IntegerToBytes(r, byteLength);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKdfParameters.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKdfParameters.cs
new file mode 100644
index 0000000..f6c9e60
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKdfParameters.cs
@@ -0,0 +1,57 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+	public class DHKdfParameters
+		: IDerivationParameters
+	{
+		private readonly DerObjectIdentifier algorithm;
+		private readonly int keySize;
+		private readonly byte[] z;
+		private readonly byte[] extraInfo;
+
+		public DHKdfParameters(
+			DerObjectIdentifier	algorithm,
+			int					keySize,
+			byte[]				z)
+			: this(algorithm, keySize, z, null)
+		{
+		}
+
+		public DHKdfParameters(
+			DerObjectIdentifier algorithm,
+			int keySize,
+			byte[] z,
+			byte[] extraInfo)
+		{
+			this.algorithm = algorithm;
+			this.keySize = keySize;
+			this.z = z; // TODO Clone?
+			this.extraInfo = extraInfo;
+		}
+
+		public DerObjectIdentifier Algorithm
+		{
+			get { return algorithm; }
+		}
+
+		public int KeySize
+		{
+			get { return keySize; }
+		}
+
+		public byte[] GetZ()
+		{
+			// TODO Clone?
+			return z;
+		}
+
+		public byte[] GetExtraInfo()
+		{
+			// TODO Clone?
+			return extraInfo;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKekGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKekGenerator.cs
new file mode 100644
index 0000000..259e21e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/DHKekGenerator.cs
@@ -0,0 +1,112 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+    /**
+    * RFC 2631 Diffie-hellman KEK derivation function.
+    */
+    public class DHKekGenerator
+        : IDerivationFunction
+    {
+        private readonly IDigest digest;
+
+        private DerObjectIdentifier	algorithm;
+        private int					keySize;
+        private byte[]				z;
+        private byte[]				partyAInfo;
+
+        public DHKekGenerator(IDigest digest)
+        {
+            this.digest = digest;
+        }
+
+        public virtual void Init(IDerivationParameters param)
+        {
+            DHKdfParameters parameters = (DHKdfParameters)param;
+
+            this.algorithm = parameters.Algorithm;
+            this.keySize = parameters.KeySize;
+            this.z = parameters.GetZ(); // TODO Clone?
+            this.partyAInfo = parameters.GetExtraInfo(); // TODO Clone?
+        }
+
+        public virtual IDigest Digest
+        {
+            get { return digest; }
+        }
+
+        public virtual int GenerateBytes(byte[]	outBytes, int outOff, int len)
+        {
+            if ((outBytes.Length - len) < outOff)
+            {
+                throw new DataLengthException("output buffer too small");
+            }
+
+            long oBytes = len;
+            int outLen = digest.GetDigestSize();
+
+            //
+            // this is at odds with the standard implementation, the
+            // maximum value should be hBits * (2^32 - 1) where hBits
+            // is the digest output size in bits. We can't have an
+            // array with a long index at the moment...
+            //
+            if (oBytes > ((2L << 32) - 1))
+            {
+                throw new ArgumentException("Output length too large");
+            }
+
+            int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+            byte[] dig = new byte[digest.GetDigestSize()];
+
+            uint counter = 1;
+
+            for (int i = 0; i < cThreshold; i++)
+            {
+                digest.BlockUpdate(z, 0, z.Length);
+
+                // KeySpecificInfo
+                DerSequence keyInfo = new DerSequence(
+                    algorithm,
+                    new DerOctetString(Pack.UInt32_To_BE(counter)));
+
+                // OtherInfo
+                Asn1EncodableVector v1 = new Asn1EncodableVector(keyInfo);
+
+                if (partyAInfo != null)
+                {
+                    v1.Add(new DerTaggedObject(true, 0, new DerOctetString(partyAInfo)));
+                }
+
+                v1.Add(new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
+
+                byte[] other = new DerSequence(v1).GetDerEncoded();
+
+                digest.BlockUpdate(other, 0, other.Length);
+
+                digest.DoFinal(dig, 0);
+
+                if (len > outLen)
+                {
+                    Array.Copy(dig, 0, outBytes, outOff, outLen);
+                    outOff += outLen;
+                    len -= outLen;
+                }
+                else
+                {
+                    Array.Copy(dig, 0, outBytes, outOff, len);
+                }
+
+                counter++;
+            }
+
+            digest.Reset();
+
+            return (int)oBytes;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/ECDHKekGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/ECDHKekGenerator.cs
new file mode 100644
index 0000000..7446457
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/kdf/ECDHKekGenerator.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Kdf
+{
+    /**
+    * X9.63 based key derivation function for ECDH CMS.
+    */
+    public class ECDHKekGenerator
+        : IDerivationFunction
+    {
+        private readonly IDerivationFunction kdf;
+
+        private DerObjectIdentifier	algorithm;
+        private int					keySize;
+        private byte[]				z;
+
+        public ECDHKekGenerator(IDigest digest)
+        {
+            this.kdf = new Kdf2BytesGenerator(digest);
+        }
+
+        public virtual void Init(IDerivationParameters param)
+        {
+            DHKdfParameters parameters = (DHKdfParameters)param;
+
+            this.algorithm = parameters.Algorithm;
+            this.keySize = parameters.KeySize;
+            this.z = parameters.GetZ(); // TODO Clone?
+        }
+
+        public virtual IDigest Digest
+        {
+            get { return kdf.Digest; }
+        }
+
+        public virtual int GenerateBytes(byte[]	outBytes, int outOff, int len)
+        {
+            // TODO Create an ASN.1 class for this (RFC3278)
+            // ECC-CMS-SharedInfo
+            DerSequence s = new DerSequence(
+                new AlgorithmIdentifier(algorithm, DerNull.Instance),
+                new DerTaggedObject(true, 2, new DerOctetString(Pack.UInt32_To_BE((uint)keySize))));
+
+            kdf.Init(new KdfParameters(z, s.GetDerEncoded()));
+
+            return kdf.GenerateBytes(outBytes, outOff, len);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Client.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Client.cs
new file mode 100644
index 0000000..3097365
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Client.cs
@@ -0,0 +1,93 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Srp
+{
+	/**
+	 * Implements the client side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+	 * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+	 * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+	 */
+	public class Srp6Client
+	{
+	    protected BigInteger N;
+	    protected BigInteger g;
+
+	    protected BigInteger privA;
+	    protected BigInteger pubA;
+
+	    protected BigInteger B;
+
+	    protected BigInteger x;
+	    protected BigInteger u;
+	    protected BigInteger S;
+
+	    protected IDigest digest;
+	    protected SecureRandom random;
+
+	    public Srp6Client()
+	    {
+	    }
+
+	    /**
+	     * Initialises the client to begin new authentication attempt
+	     * @param N The safe prime associated with the client's verifier
+	     * @param g The group parameter associated with the client's verifier
+	     * @param digest The digest algorithm associated with the client's verifier
+	     * @param random For key generation
+	     */
+	    public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
+	    {
+	        this.N = N;
+	        this.g = g;
+	        this.digest = digest;
+	        this.random = random;
+	    }
+
+	    /**
+	     * Generates client's credentials given the client's salt, identity and password
+	     * @param salt The salt used in the client's verifier.
+	     * @param identity The user's identity (eg. username)
+	     * @param password The user's password
+	     * @return Client's public value to send to server
+	     */
+	    public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
+	    {
+	        this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
+	        this.privA = SelectPrivateValue();
+	        this.pubA = g.ModPow(privA, N);
+
+	        return pubA;
+	    }
+
+	    /**
+	     * Generates client's verification message given the server's credentials
+	     * @param serverB The server's credentials
+	     * @return Client's verification message for the server
+	     * @throws CryptoException If server's credentials are invalid
+	     */
+	    public virtual BigInteger CalculateSecret(BigInteger serverB)
+	    {
+	        this.B = Srp6Utilities.ValidatePublicValue(N, serverB);
+	        this.u = Srp6Utilities.CalculateU(digest, N, pubA, B);
+	        this.S = CalculateS();
+
+	        return S;
+	    }
+
+	    protected virtual BigInteger SelectPrivateValue()
+	    {
+	    	return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);    	
+	    }
+
+	    private BigInteger CalculateS()
+	    {
+	        BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
+	        BigInteger exp = u.Multiply(x).Add(privA);
+	        BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N);
+	        return B.Subtract(tmp).Mod(N).ModPow(exp, N);
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Server.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Server.cs
new file mode 100644
index 0000000..35b96d4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Server.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Srp
+{
+	/**
+	 * Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
+	 * This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
+	 * "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
+	 */
+	public class Srp6Server
+	{
+	    protected BigInteger N;
+	    protected BigInteger g;
+	    protected BigInteger v;
+
+	    protected SecureRandom random;
+	    protected IDigest digest;
+
+	    protected BigInteger A;
+
+	    protected BigInteger privB;
+	    protected BigInteger pubB;
+
+	    protected BigInteger u;
+	    protected BigInteger S;
+
+	    public Srp6Server()
+	    {
+	    }
+
+	    /**
+	     * Initialises the server to accept a new client authentication attempt
+	     * @param N The safe prime associated with the client's verifier
+	     * @param g The group parameter associated with the client's verifier
+	     * @param v The client's verifier
+	     * @param digest The digest algorithm associated with the client's verifier
+	     * @param random For key generation
+	     */
+	    public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random)
+	    {
+	        this.N = N;
+	        this.g = g;
+	        this.v = v;
+
+	        this.random = random;
+	        this.digest = digest;
+	    }
+
+	    /**
+	     * Generates the server's credentials that are to be sent to the client.
+	     * @return The server's public value to the client
+	     */
+	    public virtual BigInteger GenerateServerCredentials()
+	    {
+	        BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
+	        this.privB = SelectPrivateValue();
+	    	this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N);
+
+	        return pubB;
+	    }
+
+	    /**
+	     * Processes the client's credentials. If valid the shared secret is generated and returned.
+	     * @param clientA The client's credentials
+	     * @return A shared secret BigInteger
+	     * @throws CryptoException If client's credentials are invalid
+	     */
+	    public virtual BigInteger CalculateSecret(BigInteger clientA)
+	    {
+	        this.A = Srp6Utilities.ValidatePublicValue(N, clientA);
+	        this.u = Srp6Utilities.CalculateU(digest, N, A, pubB);
+	        this.S = CalculateS();
+
+	        return S;
+	    }
+
+	    protected virtual BigInteger SelectPrivateValue()
+	    {
+	    	return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);    	
+	    }
+
+		private BigInteger CalculateS()
+	    {
+			return v.ModPow(u, N).Multiply(A).Mod(N).ModPow(privB, N);
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Utilities.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Utilities.cs
new file mode 100644
index 0000000..4e790f5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6Utilities.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Srp
+{
+	public class Srp6Utilities
+	{
+		public static BigInteger CalculateK(IDigest digest, BigInteger N, BigInteger g)
+		{
+			return HashPaddedPair(digest, N, N, g);
+		}
+
+	    public static BigInteger CalculateU(IDigest digest, BigInteger N, BigInteger A, BigInteger B)
+	    {
+	    	return HashPaddedPair(digest, N, A, B);
+	    }
+
+		public static BigInteger CalculateX(IDigest digest, BigInteger N, byte[] salt, byte[] identity, byte[] password)
+	    {
+	        byte[] output = new byte[digest.GetDigestSize()];
+
+	        digest.BlockUpdate(identity, 0, identity.Length);
+	        digest.Update((byte)':');
+	        digest.BlockUpdate(password, 0, password.Length);
+	        digest.DoFinal(output, 0);
+
+	        digest.BlockUpdate(salt, 0, salt.Length);
+	        digest.BlockUpdate(output, 0, output.Length);
+	        digest.DoFinal(output, 0);
+
+	        return new BigInteger(1, output);
+	    }
+
+		public static BigInteger GeneratePrivateValue(IDigest digest, BigInteger N, BigInteger g, SecureRandom random)
+	    {
+			int minBits = System.Math.Min(256, N.BitLength / 2);
+	        BigInteger min = BigInteger.One.ShiftLeft(minBits - 1);
+	        BigInteger max = N.Subtract(BigInteger.One);
+
+	        return BigIntegers.CreateRandomInRange(min, max, random);
+	    }
+
+		public static BigInteger ValidatePublicValue(BigInteger N, BigInteger val)
+		{
+		    val = val.Mod(N);
+
+	        // Check that val % N != 0
+	        if (val.Equals(BigInteger.Zero))
+	            throw new CryptoException("Invalid public value: 0");
+
+		    return val;
+		}
+
+		private static BigInteger HashPaddedPair(IDigest digest, BigInteger N, BigInteger n1, BigInteger n2)
+		{
+	    	int padLength = (N.BitLength + 7) / 8;
+
+	    	byte[] n1_bytes = GetPadded(n1, padLength);
+	    	byte[] n2_bytes = GetPadded(n2, padLength);
+
+	        digest.BlockUpdate(n1_bytes, 0, n1_bytes.Length);
+	        digest.BlockUpdate(n2_bytes, 0, n2_bytes.Length);
+
+	        byte[] output = new byte[digest.GetDigestSize()];
+	        digest.DoFinal(output, 0);
+
+	        return new BigInteger(1, output);
+		}
+
+		private static byte[] GetPadded(BigInteger n, int length)
+		{
+			byte[] bs = BigIntegers.AsUnsignedByteArray(n);
+			if (bs.Length < length)
+			{
+				byte[] tmp = new byte[length];
+				Array.Copy(bs, 0, tmp, length - bs.Length, bs.Length);
+				bs = tmp;
+			}
+			return bs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6VerifierGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6VerifierGenerator.cs
new file mode 100644
index 0000000..264833b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/agreement/srp/SRP6VerifierGenerator.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Agreement.Srp
+{
+	/**
+	 * Generates new SRP verifier for user
+	 */
+	public class Srp6VerifierGenerator
+	{
+	    protected BigInteger N;
+	    protected BigInteger g;
+	    protected IDigest digest;
+
+	    public Srp6VerifierGenerator()
+	    {
+	    }
+
+	    /**
+	     * Initialises generator to create new verifiers
+	     * @param N The safe prime to use (see DHParametersGenerator)
+	     * @param g The group parameter to use (see DHParametersGenerator)
+	     * @param digest The digest to use. The same digest type will need to be used later for the actual authentication
+	     * attempt. Also note that the final session key size is dependent on the chosen digest.
+	     */
+	    public virtual void Init(BigInteger N, BigInteger g, IDigest digest)
+	    {
+	        this.N = N;
+	        this.g = g;
+	        this.digest = digest;
+	    }
+
+	    /**
+	     * Creates a new SRP verifier
+	     * @param salt The salt to use, generally should be large and random
+	     * @param identity The user's identifying information (eg. username)
+	     * @param password The user's password
+	     * @return A new verifier for use in future SRP authentication
+	     */
+	    public virtual BigInteger GenerateVerifier(byte[] salt, byte[] identity, byte[] password)
+	    {
+	    	BigInteger x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
+
+	        return g.ModPow(x, N);
+	    }
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/GOST3411Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/GOST3411Digest.cs
new file mode 100644
index 0000000..218adf6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/GOST3411Digest.cs
@@ -0,0 +1,356 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+	/**
+	* implementation of GOST R 34.11-94
+	*/
+	public class Gost3411Digest
+		: IDigest, IMemoable
+	{
+		private const int DIGEST_LENGTH = 32;
+
+		private byte[]	H = new byte[32], L = new byte[32],
+						M = new byte[32], Sum = new byte[32];
+		private byte[][] C = MakeC();
+
+		private byte[]	xBuf = new byte[32];
+		private int		xBufOff;
+		private ulong	byteCount;
+
+		private readonly IBlockCipher cipher = new Gost28147Engine();
+		private byte[] sBox;
+
+		private static byte[][] MakeC()
+		{
+			byte[][] c = new byte[4][];
+			for (int i = 0; i < 4; ++i)
+			{
+				c[i] = new byte[32];
+			}
+			return c;
+		}
+
+		/**
+		 * Standard constructor
+		 */
+		public Gost3411Digest()
+		{
+			sBox = Gost28147Engine.GetSBox("D-A");
+			cipher.Init(true, new ParametersWithSBox(null, sBox));
+
+			Reset();
+		}
+
+		/**
+		 * Constructor to allow use of a particular sbox with GOST28147
+		 * @see GOST28147Engine#getSBox(String)
+		 */
+		public Gost3411Digest(byte[] sBoxParam)
+		{
+			sBox = Arrays.Clone(sBoxParam);
+			cipher.Init(true, new ParametersWithSBox(null, sBox));
+
+			Reset();
+		}
+
+		/**
+		 * Copy constructor.  This will copy the state of the provided
+		 * message digest.
+		 */
+		public Gost3411Digest(Gost3411Digest t)
+		{
+			Reset(t);
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Gost3411"; }
+		}
+
+		public int GetDigestSize()
+		{
+			return DIGEST_LENGTH;
+		}
+
+		public void Update(
+			byte input)
+		{
+			xBuf[xBufOff++] = input;
+			if (xBufOff == xBuf.Length)
+			{
+				sumByteArray(xBuf); // calc sum M
+				processBlock(xBuf, 0);
+				xBufOff = 0;
+			}
+			byteCount++;
+		}
+
+		public void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			while ((xBufOff != 0) && (length > 0))
+			{
+				Update(input[inOff]);
+				inOff++;
+				length--;
+			}
+
+			while (length > xBuf.Length)
+			{
+				Array.Copy(input, inOff, xBuf, 0, xBuf.Length);
+
+				sumByteArray(xBuf); // calc sum M
+				processBlock(xBuf, 0);
+				inOff += xBuf.Length;
+				length -= xBuf.Length;
+				byteCount += (uint)xBuf.Length;
+			}
+
+			// load in the remainder.
+			while (length > 0)
+			{
+				Update(input[inOff]);
+				inOff++;
+				length--;
+			}
+		}
+
+		// (i + 1 + 4(k - 1)) = 8i + k      i = 0-3, k = 1-8
+		private byte[] K = new byte[32];
+
+		private byte[] P(byte[] input)
+		{
+			int fourK = 0;
+			for(int k = 0; k < 8; k++)
+			{
+				K[fourK++] = input[k];
+				K[fourK++] = input[8 + k];
+				K[fourK++] = input[16 + k];
+				K[fourK++] = input[24 + k];
+			}
+
+			return K;
+		}
+
+		//A (x) = (x0 ^ x1) || x3 || x2 || x1
+		byte[] a = new byte[8];
+		private byte[] A(byte[] input)
+		{
+			for(int j=0; j<8; j++)
+			{
+				a[j]=(byte)(input[j] ^ input[j+8]);
+			}
+
+			Array.Copy(input, 8, input, 0, 24);
+			Array.Copy(a, 0, input, 24, 8);
+
+			return input;
+		}
+
+		//Encrypt function, ECB mode
+		private void E(byte[] key, byte[] s, int sOff, byte[] input, int inOff)
+		{
+			cipher.Init(true, new KeyParameter(key));
+
+			cipher.ProcessBlock(input, inOff, s, sOff);
+		}
+
+		// (in:) n16||..||n1 ==> (out:) n1^n2^n3^n4^n13^n16||n16||..||n2
+		internal short[] wS = new short[16], w_S = new short[16];
+
+		private void fw(byte[] input)
+		{
+			cpyBytesToShort(input, wS);
+			w_S[15] = (short)(wS[0] ^ wS[1] ^ wS[2] ^ wS[3] ^ wS[12] ^ wS[15]);
+			Array.Copy(wS, 1, w_S, 0, 15);
+			cpyShortToBytes(w_S, input);
+		}
+
+		// block processing
+		internal byte[] S = new byte[32], U = new byte[32], V = new byte[32], W = new byte[32];
+
+		private void processBlock(byte[] input, int inOff)
+		{
+			Array.Copy(input, inOff, M, 0, 32);
+
+			//key step 1
+
+			// H = h3 || h2 || h1 || h0
+			// S = s3 || s2 || s1 || s0
+			H.CopyTo(U, 0);
+			M.CopyTo(V, 0);
+			for (int j=0; j<32; j++)
+			{
+				W[j] = (byte)(U[j]^V[j]);
+			}
+			// Encrypt gost28147-ECB
+			E(P(W), S, 0, H, 0); // s0 = EK0 [h0]
+
+			//keys step 2,3,4
+			for (int i=1; i<4; i++)
+			{
+				byte[] tmpA = A(U);
+				for (int j=0; j<32; j++)
+				{
+					U[j] = (byte)(tmpA[j] ^ C[i][j]);
+				}
+				V = A(A(V));
+				for (int j=0; j<32; j++)
+				{
+					W[j] = (byte)(U[j]^V[j]);
+				}
+				// Encrypt gost28147-ECB
+				E(P(W), S, i * 8, H, i * 8); // si = EKi [hi]
+			}
+
+			// x(M, H) = y61(H^y(M^y12(S)))
+			for(int n = 0; n < 12; n++)
+			{
+				fw(S);
+			}
+			for(int n = 0; n < 32; n++)
+			{
+				S[n] = (byte)(S[n] ^ M[n]);
+			}
+
+			fw(S);
+
+			for(int n = 0; n < 32; n++)
+			{
+				S[n] = (byte)(H[n] ^ S[n]);
+			}
+			for(int n = 0; n < 61; n++)
+			{
+				fw(S);
+			}
+			Array.Copy(S, 0, H, 0, H.Length);
+		}
+
+		private void finish()
+		{
+			ulong bitCount = byteCount * 8;
+			Pack.UInt64_To_LE(bitCount, L);
+
+			while (xBufOff != 0)
+			{
+				Update((byte)0);
+			}
+
+			processBlock(L, 0);
+			processBlock(Sum, 0);
+		}
+
+		public int DoFinal(
+			byte[]  output,
+			int     outOff)
+		{
+			finish();
+
+			H.CopyTo(output, outOff);
+
+			Reset();
+
+			return DIGEST_LENGTH;
+		}
+
+		/**
+		* reset the chaining variables to the IV values.
+		*/
+		private static readonly byte[] C2 = {
+			0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,
+			(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,(byte)0xFF,0x00,
+			0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF,0x00,0x00,(byte)0xFF,
+			(byte)0xFF,0x00,0x00,0x00,(byte)0xFF,(byte)0xFF,0x00,(byte)0xFF
+		};
+
+		public void Reset()
+		{
+			byteCount = 0;
+			xBufOff = 0;
+
+			Array.Clear(H, 0, H.Length);
+			Array.Clear(L, 0, L.Length);
+			Array.Clear(M, 0, M.Length);
+			Array.Clear(C[1], 0, C[1].Length); // real index C = +1 because index array with 0.
+			Array.Clear(C[3], 0, C[3].Length);
+			Array.Clear(Sum, 0, Sum.Length);
+			Array.Clear(xBuf, 0, xBuf.Length);
+
+			C2.CopyTo(C[2], 0);
+		}
+
+		//  256 bitsblock modul -> (Sum + a mod (2^256))
+		private void sumByteArray(
+			byte[] input)
+		{
+			int carry = 0;
+
+			for (int i = 0; i != Sum.Length; i++)
+			{
+				int sum = (Sum[i] & 0xff) + (input[i] & 0xff) + carry;
+
+				Sum[i] = (byte)sum;
+
+				carry = sum >> 8;
+			}
+		}
+
+		private static void cpyBytesToShort(byte[] S, short[] wS)
+		{
+			for(int i = 0; i < S.Length / 2; i++)
+			{
+				wS[i] = (short)(((S[i*2+1]<<8)&0xFF00)|(S[i*2]&0xFF));
+			}
+		}
+
+		private static void cpyShortToBytes(short[] wS, byte[] S)
+		{
+			for(int i=0; i<S.Length/2; i++)
+			{
+				S[i*2 + 1] = (byte)(wS[i] >> 8);
+				S[i*2] = (byte)wS[i];
+			}
+		}
+
+		public int GetByteLength()
+		{
+			return 32;
+		}
+
+		public IMemoable Copy()
+		{
+			return new Gost3411Digest(this);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			Gost3411Digest t = (Gost3411Digest)other;
+
+			this.sBox = t.sBox;
+			cipher.Init(true, new ParametersWithSBox(null, sBox));
+
+			Reset();
+
+			Array.Copy(t.H, 0, this.H, 0, t.H.Length);
+			Array.Copy(t.L, 0, this.L, 0, t.L.Length);
+			Array.Copy(t.M, 0, this.M, 0, t.M.Length);
+			Array.Copy(t.Sum, 0, this.Sum, 0, t.Sum.Length);
+			Array.Copy(t.C[1], 0, this.C[1], 0, t.C[1].Length);
+			Array.Copy(t.C[2], 0, this.C[2], 0, t.C[2].Length);
+			Array.Copy(t.C[3], 0, this.C[3], 0, t.C[3].Length);
+			Array.Copy(t.xBuf, 0, this.xBuf, 0, t.xBuf.Length);
+
+			this.xBufOff = t.xBufOff;
+			this.byteCount = t.byteCount;
+		}
+	}
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/GeneralDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/GeneralDigest.cs
new file mode 100644
index 0000000..54a09ae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/GeneralDigest.cs
@@ -0,0 +1,127 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * base implementation of MD4 family style digest as outlined in
+    * "Handbook of Applied Cryptography", pages 344 - 347.
+    */
+    public abstract class GeneralDigest
+		: IDigest, IMemoable
+    {
+        private const int BYTE_LENGTH = 64;
+
+        private byte[]  xBuf;
+        private int     xBufOff;
+
+        private long    byteCount;
+
+        internal GeneralDigest()
+        {
+            xBuf = new byte[4];
+        }
+
+        internal GeneralDigest(GeneralDigest t)
+		{
+			xBuf = new byte[t.xBuf.Length];
+			CopyIn(t);
+		}
+
+		protected void CopyIn(GeneralDigest t)
+		{
+            Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length);
+
+            xBufOff = t.xBufOff;
+            byteCount = t.byteCount;
+        }
+
+        public void Update(byte input)
+        {
+            xBuf[xBufOff++] = input;
+
+            if (xBufOff == xBuf.Length)
+            {
+                ProcessWord(xBuf, 0);
+                xBufOff = 0;
+            }
+
+            byteCount++;
+        }
+
+        public void BlockUpdate(
+            byte[]  input,
+            int     inOff,
+            int     length)
+        {
+            //
+            // fill the current word
+            //
+            while ((xBufOff != 0) && (length > 0))
+            {
+                Update(input[inOff]);
+                inOff++;
+                length--;
+            }
+
+            //
+            // process whole words.
+            //
+            while (length > xBuf.Length)
+            {
+                ProcessWord(input, inOff);
+
+                inOff += xBuf.Length;
+                length -= xBuf.Length;
+                byteCount += xBuf.Length;
+            }
+
+            //
+            // load in the remainder.
+            //
+            while (length > 0)
+            {
+                Update(input[inOff]);
+
+                inOff++;
+                length--;
+            }
+        }
+
+        public void Finish()
+        {
+            long    bitLength = (byteCount << 3);
+
+            //
+            // add the pad bytes.
+            //
+            Update((byte)128);
+
+            while (xBufOff != 0) Update((byte)0);
+            ProcessLength(bitLength);
+            ProcessBlock();
+        }
+
+        public virtual void Reset()
+        {
+            byteCount = 0;
+            xBufOff = 0;
+			Array.Clear(xBuf, 0, xBuf.Length);
+        }
+
+		public int GetByteLength()
+		{
+			return BYTE_LENGTH;
+		}
+
+		internal abstract void ProcessWord(byte[] input, int inOff);
+        internal abstract void ProcessLength(long bitLength);
+        internal abstract void ProcessBlock();
+        public abstract string AlgorithmName { get; }
+		public abstract int GetDigestSize();
+        public abstract int DoFinal(byte[] output, int outOff);
+		public abstract IMemoable Copy();
+		public abstract void Reset(IMemoable t);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/LongDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/LongDigest.cs
new file mode 100644
index 0000000..9ee9bcd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/LongDigest.cs
@@ -0,0 +1,355 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * Base class for SHA-384 and SHA-512.
+    */
+    public abstract class LongDigest
+		: IDigest, IMemoable
+    {
+        private int     MyByteLength = 128;
+
+        private byte[]  xBuf;
+        private int     xBufOff;
+
+        private long	byteCount1;
+        private long	byteCount2;
+
+        internal ulong H1, H2, H3, H4, H5, H6, H7, H8;
+
+        private ulong[] W = new ulong[80];
+        private int wOff;
+
+		/**
+        * Constructor for variable length word
+        */
+        internal LongDigest()
+        {
+            xBuf = new byte[8];
+
+			Reset();
+        }
+
+		/**
+        * Copy constructor.  We are using copy constructors in place
+        * of the object.Clone() interface as this interface is not
+        * supported by J2ME.
+        */
+        internal LongDigest(
+			LongDigest t)
+		{
+			xBuf = new byte[t.xBuf.Length];
+
+			CopyIn(t);
+		}
+
+		protected void CopyIn(LongDigest t)
+		{
+            Array.Copy(t.xBuf, 0, xBuf, 0, t.xBuf.Length);
+
+            xBufOff = t.xBufOff;
+            byteCount1 = t.byteCount1;
+            byteCount2 = t.byteCount2;
+
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+            H6 = t.H6;
+            H7 = t.H7;
+            H8 = t.H8;
+
+            Array.Copy(t.W, 0, W, 0, t.W.Length);
+            wOff = t.wOff;
+        }
+
+        public void Update(
+            byte input)
+        {
+            xBuf[xBufOff++] = input;
+
+            if (xBufOff == xBuf.Length)
+            {
+                ProcessWord(xBuf, 0);
+                xBufOff = 0;
+            }
+
+            byteCount1++;
+        }
+
+        public void BlockUpdate(
+            byte[]  input,
+            int     inOff,
+            int     length)
+        {
+            //
+            // fill the current word
+            //
+            while ((xBufOff != 0) && (length > 0))
+            {
+                Update(input[inOff]);
+
+                inOff++;
+                length--;
+            }
+
+            //
+            // process whole words.
+            //
+            while (length > xBuf.Length)
+            {
+                ProcessWord(input, inOff);
+
+                inOff += xBuf.Length;
+                length -= xBuf.Length;
+                byteCount1 += xBuf.Length;
+            }
+
+            //
+            // load in the remainder.
+            //
+            while (length > 0)
+            {
+                Update(input[inOff]);
+
+                inOff++;
+                length--;
+            }
+        }
+
+        public void Finish()
+        {
+            AdjustByteCounts();
+
+            long    lowBitLength = byteCount1 << 3;
+            long    hiBitLength = byteCount2;
+
+            //
+            // add the pad bytes.
+            //
+            Update((byte)128);
+
+            while (xBufOff != 0)
+            {
+                Update((byte)0);
+            }
+
+            ProcessLength(lowBitLength, hiBitLength);
+
+            ProcessBlock();
+        }
+
+        public virtual void Reset()
+        {
+            byteCount1 = 0;
+            byteCount2 = 0;
+
+            xBufOff = 0;
+            for ( int i = 0; i < xBuf.Length; i++ )
+            {
+                xBuf[i] = 0;
+            }
+
+            wOff = 0;
+			Array.Clear(W, 0, W.Length);
+        }
+
+        internal void ProcessWord(
+            byte[]  input,
+            int     inOff)
+        {
+			W[wOff] = Pack.BE_To_UInt64(input, inOff);
+
+            if (++wOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+		/**
+        * adjust the byte counts so that byteCount2 represents the
+        * upper long (less 3 bits) word of the byte count.
+        */
+        private void AdjustByteCounts()
+        {
+            if (byteCount1 > 0x1fffffffffffffffL)
+            {
+                byteCount2 += (long) ((ulong) byteCount1 >> 61);
+                byteCount1 &= 0x1fffffffffffffffL;
+            }
+        }
+
+        internal void ProcessLength(
+            long	lowW,
+            long	hiW)
+        {
+            if (wOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            W[14] = (ulong)hiW;
+            W[15] = (ulong)lowW;
+        }
+
+        internal void ProcessBlock()
+        {
+            AdjustByteCounts();
+
+            //
+            // expand 16 word block into 80 word blocks.
+            //
+            for (int ti = 16; ti <= 79; ++ti)
+            {
+                W[ti] = Sigma1(W[ti - 2]) + W[ti - 7] + Sigma0(W[ti - 15]) + W[ti - 16];
+            }
+
+            //
+            // set up working variables.
+            //
+            ulong a = H1;
+            ulong b = H2;
+            ulong c = H3;
+            ulong d = H4;
+            ulong e = H5;
+            ulong f = H6;
+            ulong g = H7;
+            ulong h = H8;
+
+			int t = 0;
+			for(int i = 0; i < 10; i ++)
+			{
+				// t = 8 * i
+				h += Sum1(e) + Ch(e, f, g) + K[t] + W[t++];
+				d += h;
+				h += Sum0(a) + Maj(a, b, c);
+
+				// t = 8 * i + 1
+				g += Sum1(d) + Ch(d, e, f) + K[t] + W[t++];
+				c += g;
+				g += Sum0(h) + Maj(h, a, b);
+
+				// t = 8 * i + 2
+				f += Sum1(c) + Ch(c, d, e) + K[t] + W[t++];
+				b += f;
+				f += Sum0(g) + Maj(g, h, a);
+
+				// t = 8 * i + 3
+				e += Sum1(b) + Ch(b, c, d) + K[t] + W[t++];
+				a += e;
+				e += Sum0(f) + Maj(f, g, h);
+
+				// t = 8 * i + 4
+				d += Sum1(a) + Ch(a, b, c) + K[t] + W[t++];
+				h += d;
+				d += Sum0(e) + Maj(e, f, g);
+
+				// t = 8 * i + 5
+				c += Sum1(h) + Ch(h, a, b) + K[t] + W[t++];
+				g += c;
+				c += Sum0(d) + Maj(d, e, f);
+
+				// t = 8 * i + 6
+				b += Sum1(g) + Ch(g, h, a) + K[t] + W[t++];
+				f += b;
+				b += Sum0(c) + Maj(c, d, e);
+
+				// t = 8 * i + 7
+				a += Sum1(f) + Ch(f, g, h) + K[t] + W[t++];
+				e += a;
+				a += Sum0(b) + Maj(b, c, d);
+			}
+
+			H1 += a;
+            H2 += b;
+            H3 += c;
+            H4 += d;
+            H5 += e;
+            H6 += f;
+            H7 += g;
+            H8 += h;
+
+			//
+            // reset the offset and clean out the word buffer.
+            //
+            wOff = 0;
+			Array.Clear(W, 0, 16);
+		}
+
+		/* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
+        private static ulong Ch(ulong x, ulong y, ulong z)
+        {
+            return (x & y) ^ (~x & z);
+        }
+
+        private static ulong Maj(ulong x, ulong y, ulong z)
+        {
+            return (x & y) ^ (x & z) ^ (y & z);
+        }
+
+        private static ulong Sum0(ulong x)
+        {
+	        return ((x << 36) | (x >> 28)) ^ ((x << 30) | (x >> 34)) ^ ((x << 25) | (x >> 39));
+        }
+
+		private static ulong Sum1(ulong x)
+        {
+	        return ((x << 50) | (x >> 14)) ^ ((x << 46) | (x >> 18)) ^ ((x << 23) | (x >> 41));
+        }
+
+        private static ulong Sigma0(ulong x)
+        {
+	        return ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7);
+        }
+
+        private static ulong Sigma1(ulong x)
+        {
+	        return ((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6);
+        }
+
+        /* SHA-384 and SHA-512 Constants
+         * (represent the first 64 bits of the fractional parts of the
+         * cube roots of the first sixty-four prime numbers)
+         */
+		internal static readonly ulong[] K =
+		{
+			0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+			0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+			0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+			0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
+			0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+			0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+			0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+			0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
+			0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+			0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
+			0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
+			0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+			0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+			0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+			0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+			0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+			0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+			0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+			0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+			0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+		};
+
+		public int GetByteLength()
+		{
+			return MyByteLength;
+		}
+
+		public abstract string AlgorithmName { get; }
+		public abstract int GetDigestSize();
+        public abstract int DoFinal(byte[] output, int outOff);
+		public abstract IMemoable Copy();
+		public abstract void Reset(IMemoable t);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/MD2Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/MD2Digest.cs
new file mode 100644
index 0000000..6d90f3f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/MD2Digest.cs
@@ -0,0 +1,269 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+    /**
+    * implementation of MD2
+    * as outlined in RFC1319 by B.Kaliski from RSA Laboratories April 1992
+    */
+    public class MD2Digest
+		: IDigest, IMemoable
+    {
+        private const int DigestLength = 16;
+        private const int BYTE_LENGTH = 16;
+
+        /* X buffer */
+        private byte[]   X = new byte[48];
+        private int     xOff;
+
+        /* M buffer */
+
+        private byte[]   M = new byte[16];
+        private int     mOff;
+
+        /* check sum */
+
+        private byte[]   C = new byte[16];
+        private int COff;
+
+        public MD2Digest()
+        {
+            Reset();
+        }
+
+        public MD2Digest(MD2Digest t)
+		{
+			CopyIn(t);
+		}
+
+		private void CopyIn(MD2Digest t)
+		{
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+            Array.Copy(t.M, 0, M, 0, t.M.Length);
+            mOff = t.mOff;
+            Array.Copy(t.C, 0, C, 0, t.C.Length);
+            COff = t.COff;
+        }
+
+        /**
+        * return the algorithm name
+        *
+        * @return the algorithm name
+        */
+        public string AlgorithmName
+		{
+			get { return "MD2"; }
+		}
+
+		public int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		public int GetByteLength()
+		{
+			return BYTE_LENGTH;
+		}
+
+		/**
+        * Close the digest, producing the final digest value. The doFinal
+        * call leaves the digest reset.
+        *
+        * @param out the array the digest is to be copied into.
+        * @param outOff the offset into the out array the digest is to start at.
+        */
+        public int DoFinal(byte[] output, int outOff)
+        {
+            // add padding
+            byte paddingByte = (byte)(M.Length - mOff);
+            for (int i=mOff;i<M.Length;i++)
+            {
+                M[i] = paddingByte;
+            }
+            //do final check sum
+            ProcessChecksum(M);
+            // do final block process
+            ProcessBlock(M);
+
+            ProcessBlock(C);
+
+            Array.Copy(X, xOff, output, outOff, 16);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the digest back to it's initial state.
+        */
+        public void Reset()
+        {
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+            mOff = 0;
+            for (int i = 0; i != M.Length; i++)
+            {
+                M[i] = 0;
+            }
+            COff = 0;
+            for (int i = 0; i != C.Length; i++)
+            {
+                C[i] = 0;
+            }
+        }
+        /**
+        * update the message digest with a single byte.
+        *
+        * @param in the input byte to be entered.
+        */
+        public void Update(byte input)
+        {
+            M[mOff++] = input;
+
+            if (mOff == 16)
+            {
+                ProcessChecksum(M);
+                ProcessBlock(M);
+                mOff = 0;
+            }
+        }
+
+        /**
+        * update the message digest with a block of bytes.
+        *
+        * @param in the byte array containing the data.
+        * @param inOff the offset into the byte array where the data starts.
+        * @param len the length of the data.
+        */
+        public void BlockUpdate(byte[] input, int inOff, int length)
+        {
+            //
+            // fill the current word
+            //
+            while ((mOff != 0) && (length > 0))
+            {
+                Update(input[inOff]);
+                inOff++;
+                length--;
+            }
+
+            //
+            // process whole words.
+            //
+            while (length > 16)
+            {
+                Array.Copy(input,inOff,M,0,16);
+                ProcessChecksum(M);
+                ProcessBlock(M);
+                length -= 16;
+                inOff += 16;
+            }
+
+            //
+            // load in the remainder.
+            //
+            while (length > 0)
+            {
+                Update(input[inOff]);
+                inOff++;
+                length--;
+            }
+        }
+
+        internal void ProcessChecksum(byte[] m)
+        {
+            int L = C[15];
+            for (int i=0;i<16;i++)
+            {
+                C[i] ^= S[(m[i] ^ L) & 0xff];
+                L = C[i];
+            }
+        }
+        internal void ProcessBlock(byte[] m)
+        {
+            for (int i=0;i<16;i++)
+            {
+                X[i+16] = m[i];
+                X[i+32] = (byte)(m[i] ^ X[i]);
+            }
+            // encrypt block
+            int t = 0;
+
+            for (int j=0;j<18;j++)
+            {
+                for (int k=0;k<48;k++)
+                {
+                    t = X[k] ^= S[t];
+                    t = t & 0xff;
+                }
+                t = (t + j)%256;
+            }
+        }
+
+
+
+        // 256-byte random permutation constructed from the digits of PI
+        private static readonly byte[] S = {
+        (byte)41,(byte)46,(byte)67,(byte)201,(byte)162,(byte)216,(byte)124,
+        (byte)1,(byte)61,(byte)54,(byte)84,(byte)161,(byte)236,(byte)240,
+        (byte)6,(byte)19,(byte)98,(byte)167,(byte)5,(byte)243,(byte)192,
+        (byte)199,(byte)115,(byte)140,(byte)152,(byte)147,(byte)43,(byte)217,
+        (byte)188,(byte)76,(byte)130,(byte)202,(byte)30,(byte)155,(byte)87,
+        (byte)60,(byte)253,(byte)212,(byte)224,(byte)22,(byte)103,(byte)66,
+        (byte)111,(byte)24,(byte)138,(byte)23,(byte)229,(byte)18,(byte)190,
+        (byte)78,(byte)196,(byte)214,(byte)218,(byte)158,(byte)222,(byte)73,
+        (byte)160,(byte)251,(byte)245,(byte)142,(byte)187,(byte)47,(byte)238,
+        (byte)122,(byte)169,(byte)104,(byte)121,(byte)145,(byte)21,(byte)178,
+        (byte)7,(byte)63,(byte)148,(byte)194,(byte)16,(byte)137,(byte)11,
+        (byte)34,(byte)95,(byte)33,(byte)128,(byte)127,(byte)93,(byte)154,
+        (byte)90,(byte)144,(byte)50,(byte)39,(byte)53,(byte)62,(byte)204,
+        (byte)231,(byte)191,(byte)247,(byte)151,(byte)3,(byte)255,(byte)25,
+        (byte)48,(byte)179,(byte)72,(byte)165,(byte)181,(byte)209,(byte)215,
+        (byte)94,(byte)146,(byte)42,(byte)172,(byte)86,(byte)170,(byte)198,
+        (byte)79,(byte)184,(byte)56,(byte)210,(byte)150,(byte)164,(byte)125,
+        (byte)182,(byte)118,(byte)252,(byte)107,(byte)226,(byte)156,(byte)116,
+        (byte)4,(byte)241,(byte)69,(byte)157,(byte)112,(byte)89,(byte)100,
+        (byte)113,(byte)135,(byte)32,(byte)134,(byte)91,(byte)207,(byte)101,
+        (byte)230,(byte)45,(byte)168,(byte)2,(byte)27,(byte)96,(byte)37,
+        (byte)173,(byte)174,(byte)176,(byte)185,(byte)246,(byte)28,(byte)70,
+        (byte)97,(byte)105,(byte)52,(byte)64,(byte)126,(byte)15,(byte)85,
+        (byte)71,(byte)163,(byte)35,(byte)221,(byte)81,(byte)175,(byte)58,
+        (byte)195,(byte)92,(byte)249,(byte)206,(byte)186,(byte)197,(byte)234,
+        (byte)38,(byte)44,(byte)83,(byte)13,(byte)110,(byte)133,(byte)40,
+        (byte)132, 9,(byte)211,(byte)223,(byte)205,(byte)244,(byte)65,
+        (byte)129,(byte)77,(byte)82,(byte)106,(byte)220,(byte)55,(byte)200,
+        (byte)108,(byte)193,(byte)171,(byte)250,(byte)36,(byte)225,(byte)123,
+        (byte)8,(byte)12,(byte)189,(byte)177,(byte)74,(byte)120,(byte)136,
+        (byte)149,(byte)139,(byte)227,(byte)99,(byte)232,(byte)109,(byte)233,
+        (byte)203,(byte)213,(byte)254,(byte)59,(byte)0,(byte)29,(byte)57,
+        (byte)242,(byte)239,(byte)183,(byte)14,(byte)102,(byte)88,(byte)208,
+        (byte)228,(byte)166,(byte)119,(byte)114,(byte)248,(byte)235,(byte)117,
+        (byte)75,(byte)10,(byte)49,(byte)68,(byte)80,(byte)180,(byte)143,
+        (byte)237,(byte)31,(byte)26,(byte)219,(byte)153,(byte)141,(byte)51,
+        (byte)159,(byte)17,(byte)131,(byte)20
+        };
+
+		public IMemoable Copy()
+		{
+			return new MD2Digest(this);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			MD2Digest d = (MD2Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/MD4Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/MD4Digest.cs
new file mode 100644
index 0000000..8743f7d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/MD4Digest.cs
@@ -0,0 +1,292 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * implementation of MD4 as RFC 1320 by R. Rivest, MIT Laboratory for
+    * Computer Science and RSA Data Security, Inc.
+    * <p>
+    * <b>NOTE</b>: This algorithm is only included for backwards compatibility
+    * with legacy applications, it's not secure, don't use it for anything new!</p>
+    */
+    public class MD4Digest
+		: GeneralDigest
+    {
+        private const int    DigestLength = 16;
+
+        private int     H1, H2, H3, H4;         // IV's
+
+        private int[]   X = new int[16];
+        private int     xOff;
+
+        /**
+        * Standard constructor
+        */
+        public MD4Digest()
+        {
+            Reset();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public MD4Digest(MD4Digest t) : base(t)
+		{
+			CopyIn(t);
+		}
+
+		private void CopyIn(MD4Digest t)
+		{
+			base.CopyIn(t);
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+		public override string AlgorithmName
+		{
+			get { return "MD4"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		internal override void ProcessWord(
+            byte[]  input,
+            int     inOff)
+        {
+            X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+                | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+            if (xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(
+            long    bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (int)(bitLength & 0xffffffff);
+            X[15] = (int)((ulong) bitLength >> 32);
+        }
+
+        private void UnpackWord(
+            int     word,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            outBytes[outOff]     = (byte)word;
+            outBytes[outOff + 1] = (byte)((uint) word >> 8);
+            outBytes[outOff + 2] = (byte)((uint) word >> 16);
+            outBytes[outOff + 3] = (byte)((uint) word >> 24);
+        }
+
+        public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            UnpackWord(H1, output, outOff);
+            UnpackWord(H2, output, outOff + 4);
+            UnpackWord(H3, output, outOff + 8);
+            UnpackWord(H4, output, outOff + 12);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables to the IV values.
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            H1 = unchecked((int) 0x67452301);
+            H2 = unchecked((int) 0xefcdab89);
+            H3 = unchecked((int) 0x98badcfe);
+            H4 = unchecked((int) 0x10325476);
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        //
+        // round 1 left rotates
+        //
+        private const int S11 = 3;
+        private const int S12 = 7;
+        private const int S13 = 11;
+        private const int S14 = 19;
+
+        //
+        // round 2 left rotates
+        //
+        private const int S21 = 3;
+        private const int S22 = 5;
+        private const int S23 = 9;
+        private const int S24 = 13;
+
+        //
+        // round 3 left rotates
+        //
+        private const int S31 = 3;
+        private const int S32 = 9;
+        private const int S33 = 11;
+        private const int S34 = 15;
+
+        /*
+        * rotate int x left n bits.
+        */
+        private int RotateLeft(
+            int x,
+            int n)
+        {
+            return (x << n) | (int) ((uint) x >> (32 - n));
+        }
+
+        /*
+        * F, G, H and I are the basic MD4 functions.
+        */
+        private int F(
+            int u,
+            int v,
+            int w)
+        {
+            return (u & v) | (~u & w);
+        }
+
+        private int G(
+            int u,
+            int v,
+            int w)
+        {
+            return (u & v) | (u & w) | (v & w);
+        }
+
+        private int H(
+            int u,
+            int v,
+            int w)
+        {
+            return u ^ v ^ w;
+        }
+
+        internal override void ProcessBlock()
+        {
+            int a = H1;
+            int b = H2;
+            int c = H3;
+            int d = H4;
+
+            //
+            // Round 1 - F cycle, 16 times.
+            //
+            a = RotateLeft((a + F(b, c, d) + X[ 0]), S11);
+            d = RotateLeft((d + F(a, b, c) + X[ 1]), S12);
+            c = RotateLeft((c + F(d, a, b) + X[ 2]), S13);
+            b = RotateLeft((b + F(c, d, a) + X[ 3]), S14);
+            a = RotateLeft((a + F(b, c, d) + X[ 4]), S11);
+            d = RotateLeft((d + F(a, b, c) + X[ 5]), S12);
+            c = RotateLeft((c + F(d, a, b) + X[ 6]), S13);
+            b = RotateLeft((b + F(c, d, a) + X[ 7]), S14);
+            a = RotateLeft((a + F(b, c, d) + X[ 8]), S11);
+            d = RotateLeft((d + F(a, b, c) + X[ 9]), S12);
+            c = RotateLeft((c + F(d, a, b) + X[10]), S13);
+            b = RotateLeft((b + F(c, d, a) + X[11]), S14);
+            a = RotateLeft((a + F(b, c, d) + X[12]), S11);
+            d = RotateLeft((d + F(a, b, c) + X[13]), S12);
+            c = RotateLeft((c + F(d, a, b) + X[14]), S13);
+            b = RotateLeft((b + F(c, d, a) + X[15]), S14);
+
+            //
+            // Round 2 - G cycle, 16 times.
+            //
+            a = RotateLeft((a + G(b, c, d) + X[ 0] + 0x5a827999), S21);
+            d = RotateLeft((d + G(a, b, c) + X[ 4] + 0x5a827999), S22);
+            c = RotateLeft((c + G(d, a, b) + X[ 8] + 0x5a827999), S23);
+            b = RotateLeft((b + G(c, d, a) + X[12] + 0x5a827999), S24);
+            a = RotateLeft((a + G(b, c, d) + X[ 1] + 0x5a827999), S21);
+            d = RotateLeft((d + G(a, b, c) + X[ 5] + 0x5a827999), S22);
+            c = RotateLeft((c + G(d, a, b) + X[ 9] + 0x5a827999), S23);
+            b = RotateLeft((b + G(c, d, a) + X[13] + 0x5a827999), S24);
+            a = RotateLeft((a + G(b, c, d) + X[ 2] + 0x5a827999), S21);
+            d = RotateLeft((d + G(a, b, c) + X[ 6] + 0x5a827999), S22);
+            c = RotateLeft((c + G(d, a, b) + X[10] + 0x5a827999), S23);
+            b = RotateLeft((b + G(c, d, a) + X[14] + 0x5a827999), S24);
+            a = RotateLeft((a + G(b, c, d) + X[ 3] + 0x5a827999), S21);
+            d = RotateLeft((d + G(a, b, c) + X[ 7] + 0x5a827999), S22);
+            c = RotateLeft((c + G(d, a, b) + X[11] + 0x5a827999), S23);
+            b = RotateLeft((b + G(c, d, a) + X[15] + 0x5a827999), S24);
+
+            //
+            // Round 3 - H cycle, 16 times.
+            //
+            a = RotateLeft((a + H(b, c, d) + X[ 0] + 0x6ed9eba1), S31);
+            d = RotateLeft((d + H(a, b, c) + X[ 8] + 0x6ed9eba1), S32);
+            c = RotateLeft((c + H(d, a, b) + X[ 4] + 0x6ed9eba1), S33);
+            b = RotateLeft((b + H(c, d, a) + X[12] + 0x6ed9eba1), S34);
+            a = RotateLeft((a + H(b, c, d) + X[ 2] + 0x6ed9eba1), S31);
+            d = RotateLeft((d + H(a, b, c) + X[10] + 0x6ed9eba1), S32);
+            c = RotateLeft((c + H(d, a, b) + X[ 6] + 0x6ed9eba1), S33);
+            b = RotateLeft((b + H(c, d, a) + X[14] + 0x6ed9eba1), S34);
+            a = RotateLeft((a + H(b, c, d) + X[ 1] + 0x6ed9eba1), S31);
+            d = RotateLeft((d + H(a, b, c) + X[ 9] + 0x6ed9eba1), S32);
+            c = RotateLeft((c + H(d, a, b) + X[ 5] + 0x6ed9eba1), S33);
+            b = RotateLeft((b + H(c, d, a) + X[13] + 0x6ed9eba1), S34);
+            a = RotateLeft((a + H(b, c, d) + X[ 3] + 0x6ed9eba1), S31);
+            d = RotateLeft((d + H(a, b, c) + X[11] + 0x6ed9eba1), S32);
+            c = RotateLeft((c + H(d, a, b) + X[ 7] + 0x6ed9eba1), S33);
+            b = RotateLeft((b + H(c, d, a) + X[15] + 0x6ed9eba1), S34);
+
+            H1 += a;
+            H2 += b;
+            H3 += c;
+            H4 += d;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+		public override IMemoable Copy()
+		{
+			return new MD4Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			MD4Digest d = (MD4Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/MD5Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/MD5Digest.cs
new file mode 100644
index 0000000..c60ac92
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/MD5Digest.cs
@@ -0,0 +1,313 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * implementation of MD5 as outlined in "Handbook of Applied Cryptography", pages 346 - 347.
+    */
+    public class MD5Digest
+        : GeneralDigest
+    {
+        private const int DigestLength = 16;
+
+        private uint H1, H2, H3, H4;         // IV's
+
+        private uint[] X = new uint[16];
+        private int xOff;
+
+        public MD5Digest()
+        {
+            Reset();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public MD5Digest(MD5Digest t)
+            : base(t)
+		{
+			CopyIn(t);
+		}
+
+		private void CopyIn(MD5Digest t)
+		{
+			base.CopyIn(t);
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "MD5"; }
+        }
+
+        public override int GetDigestSize()
+        {
+            return DigestLength;
+        }
+
+        internal override void ProcessWord(
+            byte[] input,
+            int inOff)
+        {
+            X[xOff] = Pack.LE_To_UInt32(input, inOff);
+
+            if (++xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+                if (xOff == 15)
+                    X[15] = 0;
+
+                ProcessBlock();
+            }
+
+            for (int i = xOff; i < 14; ++i)
+            {
+                X[i] = 0;
+            }
+
+            X[14] = (uint)((ulong)bitLength);
+            X[15] = (uint)((ulong)bitLength >> 32);
+        }
+
+        public override int DoFinal(
+            byte[] output,
+            int outOff)
+        {
+            Finish();
+
+            Pack.UInt32_To_LE(H1, output, outOff);
+            Pack.UInt32_To_LE(H2, output, outOff + 4);
+            Pack.UInt32_To_LE(H3, output, outOff + 8);
+            Pack.UInt32_To_LE(H4, output, outOff + 12);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables to the IV values.
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            H1 = 0x67452301;
+            H2 = 0xefcdab89;
+            H3 = 0x98badcfe;
+            H4 = 0x10325476;
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        //
+        // round 1 left rotates
+        //
+        private static readonly int S11 = 7;
+        private static readonly int S12 = 12;
+        private static readonly int S13 = 17;
+        private static readonly int S14 = 22;
+
+        //
+        // round 2 left rotates
+        //
+        private static readonly int S21 = 5;
+        private static readonly int S22 = 9;
+        private static readonly int S23 = 14;
+        private static readonly int S24 = 20;
+
+        //
+        // round 3 left rotates
+        //
+        private static readonly int S31 = 4;
+        private static readonly int S32 = 11;
+        private static readonly int S33 = 16;
+        private static readonly int S34 = 23;
+
+        //
+        // round 4 left rotates
+        //
+        private static readonly int S41 = 6;
+        private static readonly int S42 = 10;
+        private static readonly int S43 = 15;
+        private static readonly int S44 = 21;
+
+        /*
+        * rotate int x left n bits.
+        */
+        private static uint RotateLeft(
+            uint x,
+            int n)
+        {
+            return (x << n) | (x >> (32 - n));
+        }
+
+        /*
+        * F, G, H and I are the basic MD5 functions.
+        */
+        private static uint F(
+            uint u,
+            uint v,
+            uint w)
+        {
+            return (u & v) | (~u & w);
+        }
+
+        private static uint G(
+            uint u,
+            uint v,
+            uint w)
+        {
+            return (u & w) | (v & ~w);
+        }
+
+        private static uint H(
+            uint u,
+            uint v,
+            uint w)
+        {
+            return u ^ v ^ w;
+        }
+
+        private static uint K(
+            uint u,
+            uint v,
+            uint w)
+        {
+            return v ^ (u | ~w);
+        }
+
+        internal override void ProcessBlock()
+        {
+            uint a = H1;
+            uint b = H2;
+            uint c = H3;
+            uint d = H4;
+
+            //
+            // Round 1 - F cycle, 16 times.
+            //
+            a = RotateLeft((a + F(b, c, d) + X[0] + 0xd76aa478), S11) + b;
+            d = RotateLeft((d + F(a, b, c) + X[1] + 0xe8c7b756), S12) + a;
+            c = RotateLeft((c + F(d, a, b) + X[2] + 0x242070db), S13) + d;
+            b = RotateLeft((b + F(c, d, a) + X[3] + 0xc1bdceee), S14) + c;
+            a = RotateLeft((a + F(b, c, d) + X[4] + 0xf57c0faf), S11) + b;
+            d = RotateLeft((d + F(a, b, c) + X[5] + 0x4787c62a), S12) + a;
+            c = RotateLeft((c + F(d, a, b) + X[6] + 0xa8304613), S13) + d;
+            b = RotateLeft((b + F(c, d, a) + X[7] + 0xfd469501), S14) + c;
+            a = RotateLeft((a + F(b, c, d) + X[8] + 0x698098d8), S11) + b;
+            d = RotateLeft((d + F(a, b, c) + X[9] + 0x8b44f7af), S12) + a;
+            c = RotateLeft((c + F(d, a, b) + X[10] + 0xffff5bb1), S13) + d;
+            b = RotateLeft((b + F(c, d, a) + X[11] + 0x895cd7be), S14) + c;
+            a = RotateLeft((a + F(b, c, d) + X[12] + 0x6b901122), S11) + b;
+            d = RotateLeft((d + F(a, b, c) + X[13] + 0xfd987193), S12) + a;
+            c = RotateLeft((c + F(d, a, b) + X[14] + 0xa679438e), S13) + d;
+            b = RotateLeft((b + F(c, d, a) + X[15] + 0x49b40821), S14) + c;
+
+            //
+            // Round 2 - G cycle, 16 times.
+            //
+            a = RotateLeft((a + G(b, c, d) + X[1] + 0xf61e2562), S21) + b;
+            d = RotateLeft((d + G(a, b, c) + X[6] + 0xc040b340), S22) + a;
+            c = RotateLeft((c + G(d, a, b) + X[11] + 0x265e5a51), S23) + d;
+            b = RotateLeft((b + G(c, d, a) + X[0] + 0xe9b6c7aa), S24) + c;
+            a = RotateLeft((a + G(b, c, d) + X[5] + 0xd62f105d), S21) + b;
+            d = RotateLeft((d + G(a, b, c) + X[10] + 0x02441453), S22) + a;
+            c = RotateLeft((c + G(d, a, b) + X[15] + 0xd8a1e681), S23) + d;
+            b = RotateLeft((b + G(c, d, a) + X[4] + 0xe7d3fbc8), S24) + c;
+            a = RotateLeft((a + G(b, c, d) + X[9] + 0x21e1cde6), S21) + b;
+            d = RotateLeft((d + G(a, b, c) + X[14] + 0xc33707d6), S22) + a;
+            c = RotateLeft((c + G(d, a, b) + X[3] + 0xf4d50d87), S23) + d;
+            b = RotateLeft((b + G(c, d, a) + X[8] + 0x455a14ed), S24) + c;
+            a = RotateLeft((a + G(b, c, d) + X[13] + 0xa9e3e905), S21) + b;
+            d = RotateLeft((d + G(a, b, c) + X[2] + 0xfcefa3f8), S22) + a;
+            c = RotateLeft((c + G(d, a, b) + X[7] + 0x676f02d9), S23) + d;
+            b = RotateLeft((b + G(c, d, a) + X[12] + 0x8d2a4c8a), S24) + c;
+
+            //
+            // Round 3 - H cycle, 16 times.
+            //
+            a = RotateLeft((a + H(b, c, d) + X[5] + 0xfffa3942), S31) + b;
+            d = RotateLeft((d + H(a, b, c) + X[8] + 0x8771f681), S32) + a;
+            c = RotateLeft((c + H(d, a, b) + X[11] + 0x6d9d6122), S33) + d;
+            b = RotateLeft((b + H(c, d, a) + X[14] + 0xfde5380c), S34) + c;
+            a = RotateLeft((a + H(b, c, d) + X[1] + 0xa4beea44), S31) + b;
+            d = RotateLeft((d + H(a, b, c) + X[4] + 0x4bdecfa9), S32) + a;
+            c = RotateLeft((c + H(d, a, b) + X[7] + 0xf6bb4b60), S33) + d;
+            b = RotateLeft((b + H(c, d, a) + X[10] + 0xbebfbc70), S34) + c;
+            a = RotateLeft((a + H(b, c, d) + X[13] + 0x289b7ec6), S31) + b;
+            d = RotateLeft((d + H(a, b, c) + X[0] + 0xeaa127fa), S32) + a;
+            c = RotateLeft((c + H(d, a, b) + X[3] + 0xd4ef3085), S33) + d;
+            b = RotateLeft((b + H(c, d, a) + X[6] + 0x04881d05), S34) + c;
+            a = RotateLeft((a + H(b, c, d) + X[9] + 0xd9d4d039), S31) + b;
+            d = RotateLeft((d + H(a, b, c) + X[12] + 0xe6db99e5), S32) + a;
+            c = RotateLeft((c + H(d, a, b) + X[15] + 0x1fa27cf8), S33) + d;
+            b = RotateLeft((b + H(c, d, a) + X[2] + 0xc4ac5665), S34) + c;
+
+            //
+            // Round 4 - K cycle, 16 times.
+            //
+            a = RotateLeft((a + K(b, c, d) + X[0] + 0xf4292244), S41) + b;
+            d = RotateLeft((d + K(a, b, c) + X[7] + 0x432aff97), S42) + a;
+            c = RotateLeft((c + K(d, a, b) + X[14] + 0xab9423a7), S43) + d;
+            b = RotateLeft((b + K(c, d, a) + X[5] + 0xfc93a039), S44) + c;
+            a = RotateLeft((a + K(b, c, d) + X[12] + 0x655b59c3), S41) + b;
+            d = RotateLeft((d + K(a, b, c) + X[3] + 0x8f0ccc92), S42) + a;
+            c = RotateLeft((c + K(d, a, b) + X[10] + 0xffeff47d), S43) + d;
+            b = RotateLeft((b + K(c, d, a) + X[1] + 0x85845dd1), S44) + c;
+            a = RotateLeft((a + K(b, c, d) + X[8] + 0x6fa87e4f), S41) + b;
+            d = RotateLeft((d + K(a, b, c) + X[15] + 0xfe2ce6e0), S42) + a;
+            c = RotateLeft((c + K(d, a, b) + X[6] + 0xa3014314), S43) + d;
+            b = RotateLeft((b + K(c, d, a) + X[13] + 0x4e0811a1), S44) + c;
+            a = RotateLeft((a + K(b, c, d) + X[4] + 0xf7537e82), S41) + b;
+            d = RotateLeft((d + K(a, b, c) + X[11] + 0xbd3af235), S42) + a;
+            c = RotateLeft((c + K(d, a, b) + X[2] + 0x2ad7d2bb), S43) + d;
+            b = RotateLeft((b + K(c, d, a) + X[9] + 0xeb86d391), S44) + c;
+
+            H1 += a;
+            H2 += b;
+            H3 += c;
+            H4 += d;
+
+            xOff = 0;
+        }
+
+		public override IMemoable Copy()
+		{
+			return new MD5Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			MD5Digest d = (MD5Digest)other;
+
+			CopyIn(d);
+		}
+
+	}
+
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/NullDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/NullDigest.cs
new file mode 100644
index 0000000..e598cb1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/NullDigest.cs
@@ -0,0 +1,49 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+	public class NullDigest : IDigest
+	{
+		private readonly MemoryStream bOut = new MemoryStream();
+
+		public string AlgorithmName
+		{
+			get { return "NULL"; }
+		}
+
+		public int GetByteLength()
+		{
+			// TODO Is this okay?
+			return 0;
+		}
+
+		public int GetDigestSize()
+		{
+			return (int) bOut.Length;
+		}
+
+		public void Update(byte b)
+		{
+			bOut.WriteByte(b);
+		}
+
+		public void BlockUpdate(byte[] inBytes, int inOff, int len)
+		{
+			bOut.Write(inBytes, inOff, len);
+		}
+
+		public int DoFinal(byte[] outBytes, int outOff)
+		{
+			byte[] res = bOut.ToArray();
+			res.CopyTo(outBytes, outOff);
+			Reset();
+			return res.Length;
+		}
+
+		public void Reset()
+		{
+			bOut.SetLength(0);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD128Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD128Digest.cs
new file mode 100644
index 0000000..e8a0331
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD128Digest.cs
@@ -0,0 +1,484 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * implementation of RipeMD128
+    */
+    public class RipeMD128Digest
+		: GeneralDigest
+    {
+        private const int DigestLength = 16;
+
+        private int H0, H1, H2, H3; // IV's
+
+        private int[] X = new int[16];
+        private int xOff;
+
+        /**
+        * Standard constructor
+        */
+        public RipeMD128Digest()
+        {
+            Reset();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public RipeMD128Digest(RipeMD128Digest t) : base(t)
+		{
+			CopyIn(t);
+		}
+
+		private void CopyIn(RipeMD128Digest t)
+		{
+			base.CopyIn(t);
+
+			H0 = t.H0;
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+		public override string AlgorithmName
+		{
+			get { return "RIPEMD128"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		internal override void ProcessWord(
+            byte[] input,
+            int inOff)
+        {
+            X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+                | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+            if (xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+            ProcessBlock();
+            }
+
+            X[14] = (int)(bitLength & 0xffffffff);
+            X[15] = (int)((ulong) bitLength >> 32);
+        }
+
+        private void UnpackWord(
+            int word,
+            byte[] outBytes,
+            int outOff)
+        {
+            outBytes[outOff]     = (byte)word;
+            outBytes[outOff + 1] = (byte)((uint) word >> 8);
+            outBytes[outOff + 2] = (byte)((uint) word >> 16);
+            outBytes[outOff + 3] = (byte)((uint) word >> 24);
+        }
+
+        public override int DoFinal(
+            byte[] output,
+            int outOff)
+        {
+            Finish();
+
+            UnpackWord(H0, output, outOff);
+            UnpackWord(H1, output, outOff + 4);
+            UnpackWord(H2, output, outOff + 8);
+            UnpackWord(H3, output, outOff + 12);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables to the IV values.
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            H0 = unchecked((int) 0x67452301);
+            H1 = unchecked((int) 0xefcdab89);
+            H2 = unchecked((int) 0x98badcfe);
+            H3 = unchecked((int) 0x10325476);
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        /*
+        * rotate int x left n bits.
+        */
+        private int RL(
+            int x,
+            int n)
+        {
+            return (x << n) | (int) ((uint) x >> (32 - n));
+        }
+
+        /*
+        * f1,f2,f3,f4 are the basic RipeMD128 functions.
+        */
+
+        /*
+        * F
+        */
+        private int F1(
+            int x,
+            int y,
+            int z)
+        {
+            return x ^ y ^ z;
+        }
+
+        /*
+        * G
+        */
+        private int F2(
+            int x,
+            int y,
+            int z)
+        {
+            return (x & y) | (~x & z);
+        }
+
+        /*
+        * H
+        */
+        private int F3(
+            int x,
+            int y,
+            int z)
+        {
+            return (x | ~y) ^ z;
+        }
+
+        /*
+        * I
+        */
+        private int F4(
+            int x,
+            int y,
+            int z)
+        {
+            return (x & z) | (y & ~z);
+        }
+
+        private int F1(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+            return RL(a + F1(b, c, d) + x, s);
+        }
+
+        private int F2(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+            return RL(a + F2(b, c, d) + x + unchecked((int) 0x5a827999), s);
+        }
+
+        private int F3(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+            return RL(a + F3(b, c, d) + x + unchecked((int) 0x6ed9eba1), s);
+        }
+
+        private int F4(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+            return RL(a + F4(b, c, d) + x + unchecked((int) 0x8f1bbcdc), s);
+        }
+
+        private int FF1(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+            return RL(a + F1(b, c, d) + x, s);
+        }
+
+        private int FF2(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+        return RL(a + F2(b, c, d) + x + unchecked((int) 0x6d703ef3), s);
+        }
+
+        private int FF3(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+        return RL(a + F3(b, c, d) + x + unchecked((int) 0x5c4dd124), s);
+        }
+
+        private int FF4(
+            int a,
+            int b,
+            int c,
+            int d,
+            int x,
+            int s)
+        {
+        return RL(a + F4(b, c, d) + x + unchecked((int) 0x50a28be6), s);
+        }
+
+        internal override void ProcessBlock()
+        {
+            int a, aa;
+            int b, bb;
+            int c, cc;
+            int d, dd;
+
+            a = aa = H0;
+            b = bb = H1;
+            c = cc = H2;
+            d = dd = H3;
+
+            //
+            // Round 1
+            //
+            a = F1(a, b, c, d, X[ 0], 11);
+            d = F1(d, a, b, c, X[ 1], 14);
+            c = F1(c, d, a, b, X[ 2], 15);
+            b = F1(b, c, d, a, X[ 3], 12);
+            a = F1(a, b, c, d, X[ 4],  5);
+            d = F1(d, a, b, c, X[ 5],  8);
+            c = F1(c, d, a, b, X[ 6],  7);
+            b = F1(b, c, d, a, X[ 7],  9);
+            a = F1(a, b, c, d, X[ 8], 11);
+            d = F1(d, a, b, c, X[ 9], 13);
+            c = F1(c, d, a, b, X[10], 14);
+            b = F1(b, c, d, a, X[11], 15);
+            a = F1(a, b, c, d, X[12],  6);
+            d = F1(d, a, b, c, X[13],  7);
+            c = F1(c, d, a, b, X[14],  9);
+            b = F1(b, c, d, a, X[15],  8);
+
+            //
+            // Round 2
+            //
+            a = F2(a, b, c, d, X[ 7],  7);
+            d = F2(d, a, b, c, X[ 4],  6);
+            c = F2(c, d, a, b, X[13],  8);
+            b = F2(b, c, d, a, X[ 1], 13);
+            a = F2(a, b, c, d, X[10], 11);
+            d = F2(d, a, b, c, X[ 6],  9);
+            c = F2(c, d, a, b, X[15],  7);
+            b = F2(b, c, d, a, X[ 3], 15);
+            a = F2(a, b, c, d, X[12],  7);
+            d = F2(d, a, b, c, X[ 0], 12);
+            c = F2(c, d, a, b, X[ 9], 15);
+            b = F2(b, c, d, a, X[ 5],  9);
+            a = F2(a, b, c, d, X[ 2], 11);
+            d = F2(d, a, b, c, X[14],  7);
+            c = F2(c, d, a, b, X[11], 13);
+            b = F2(b, c, d, a, X[ 8], 12);
+
+            //
+            // Round 3
+            //
+            a = F3(a, b, c, d, X[ 3], 11);
+            d = F3(d, a, b, c, X[10], 13);
+            c = F3(c, d, a, b, X[14],  6);
+            b = F3(b, c, d, a, X[ 4],  7);
+            a = F3(a, b, c, d, X[ 9], 14);
+            d = F3(d, a, b, c, X[15],  9);
+            c = F3(c, d, a, b, X[ 8], 13);
+            b = F3(b, c, d, a, X[ 1], 15);
+            a = F3(a, b, c, d, X[ 2], 14);
+            d = F3(d, a, b, c, X[ 7],  8);
+            c = F3(c, d, a, b, X[ 0], 13);
+            b = F3(b, c, d, a, X[ 6],  6);
+            a = F3(a, b, c, d, X[13],  5);
+            d = F3(d, a, b, c, X[11], 12);
+            c = F3(c, d, a, b, X[ 5],  7);
+            b = F3(b, c, d, a, X[12],  5);
+
+            //
+            // Round 4
+            //
+            a = F4(a, b, c, d, X[ 1], 11);
+            d = F4(d, a, b, c, X[ 9], 12);
+            c = F4(c, d, a, b, X[11], 14);
+            b = F4(b, c, d, a, X[10], 15);
+            a = F4(a, b, c, d, X[ 0], 14);
+            d = F4(d, a, b, c, X[ 8], 15);
+            c = F4(c, d, a, b, X[12],  9);
+            b = F4(b, c, d, a, X[ 4],  8);
+            a = F4(a, b, c, d, X[13],  9);
+            d = F4(d, a, b, c, X[ 3], 14);
+            c = F4(c, d, a, b, X[ 7],  5);
+            b = F4(b, c, d, a, X[15],  6);
+            a = F4(a, b, c, d, X[14],  8);
+            d = F4(d, a, b, c, X[ 5],  6);
+            c = F4(c, d, a, b, X[ 6],  5);
+            b = F4(b, c, d, a, X[ 2], 12);
+
+            //
+            // Parallel round 1
+            //
+            aa = FF4(aa, bb, cc, dd, X[ 5],  8);
+            dd = FF4(dd, aa, bb, cc, X[14],  9);
+            cc = FF4(cc, dd, aa, bb, X[ 7],  9);
+            bb = FF4(bb, cc, dd, aa, X[ 0], 11);
+            aa = FF4(aa, bb, cc, dd, X[ 9], 13);
+            dd = FF4(dd, aa, bb, cc, X[ 2], 15);
+            cc = FF4(cc, dd, aa, bb, X[11], 15);
+            bb = FF4(bb, cc, dd, aa, X[ 4],  5);
+            aa = FF4(aa, bb, cc, dd, X[13],  7);
+            dd = FF4(dd, aa, bb, cc, X[ 6],  7);
+            cc = FF4(cc, dd, aa, bb, X[15],  8);
+            bb = FF4(bb, cc, dd, aa, X[ 8], 11);
+            aa = FF4(aa, bb, cc, dd, X[ 1], 14);
+            dd = FF4(dd, aa, bb, cc, X[10], 14);
+            cc = FF4(cc, dd, aa, bb, X[ 3], 12);
+            bb = FF4(bb, cc, dd, aa, X[12],  6);
+
+            //
+            // Parallel round 2
+            //
+            aa = FF3(aa, bb, cc, dd, X[ 6],  9);
+            dd = FF3(dd, aa, bb, cc, X[11], 13);
+            cc = FF3(cc, dd, aa, bb, X[ 3], 15);
+            bb = FF3(bb, cc, dd, aa, X[ 7],  7);
+            aa = FF3(aa, bb, cc, dd, X[ 0], 12);
+            dd = FF3(dd, aa, bb, cc, X[13],  8);
+            cc = FF3(cc, dd, aa, bb, X[ 5],  9);
+            bb = FF3(bb, cc, dd, aa, X[10], 11);
+            aa = FF3(aa, bb, cc, dd, X[14],  7);
+            dd = FF3(dd, aa, bb, cc, X[15],  7);
+            cc = FF3(cc, dd, aa, bb, X[ 8], 12);
+            bb = FF3(bb, cc, dd, aa, X[12],  7);
+            aa = FF3(aa, bb, cc, dd, X[ 4],  6);
+            dd = FF3(dd, aa, bb, cc, X[ 9], 15);
+            cc = FF3(cc, dd, aa, bb, X[ 1], 13);
+            bb = FF3(bb, cc, dd, aa, X[ 2], 11);
+
+            //
+            // Parallel round 3
+            //
+            aa = FF2(aa, bb, cc, dd, X[15],  9);
+            dd = FF2(dd, aa, bb, cc, X[ 5],  7);
+            cc = FF2(cc, dd, aa, bb, X[ 1], 15);
+            bb = FF2(bb, cc, dd, aa, X[ 3], 11);
+            aa = FF2(aa, bb, cc, dd, X[ 7],  8);
+            dd = FF2(dd, aa, bb, cc, X[14],  6);
+            cc = FF2(cc, dd, aa, bb, X[ 6],  6);
+            bb = FF2(bb, cc, dd, aa, X[ 9], 14);
+            aa = FF2(aa, bb, cc, dd, X[11], 12);
+            dd = FF2(dd, aa, bb, cc, X[ 8], 13);
+            cc = FF2(cc, dd, aa, bb, X[12],  5);
+            bb = FF2(bb, cc, dd, aa, X[ 2], 14);
+            aa = FF2(aa, bb, cc, dd, X[10], 13);
+            dd = FF2(dd, aa, bb, cc, X[ 0], 13);
+            cc = FF2(cc, dd, aa, bb, X[ 4],  7);
+            bb = FF2(bb, cc, dd, aa, X[13],  5);
+
+            //
+            // Parallel round 4
+            //
+            aa = FF1(aa, bb, cc, dd, X[ 8], 15);
+            dd = FF1(dd, aa, bb, cc, X[ 6],  5);
+            cc = FF1(cc, dd, aa, bb, X[ 4],  8);
+            bb = FF1(bb, cc, dd, aa, X[ 1], 11);
+            aa = FF1(aa, bb, cc, dd, X[ 3], 14);
+            dd = FF1(dd, aa, bb, cc, X[11], 14);
+            cc = FF1(cc, dd, aa, bb, X[15],  6);
+            bb = FF1(bb, cc, dd, aa, X[ 0], 14);
+            aa = FF1(aa, bb, cc, dd, X[ 5],  6);
+            dd = FF1(dd, aa, bb, cc, X[12],  9);
+            cc = FF1(cc, dd, aa, bb, X[ 2], 12);
+            bb = FF1(bb, cc, dd, aa, X[13],  9);
+            aa = FF1(aa, bb, cc, dd, X[ 9], 12);
+            dd = FF1(dd, aa, bb, cc, X[ 7],  5);
+            cc = FF1(cc, dd, aa, bb, X[10], 15);
+            bb = FF1(bb, cc, dd, aa, X[14],  8);
+
+            dd += c + H1;               // final result for H0
+
+            //
+            // combine the results
+            //
+            H1 = H2 + d + aa;
+            H2 = H3 + a + bb;
+            H3 = H0 + b + cc;
+            H0 = dd;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new RipeMD128Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			RipeMD128Digest d = (RipeMD128Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD160Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD160Digest.cs
new file mode 100644
index 0000000..af4aa44
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD160Digest.cs
@@ -0,0 +1,445 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * implementation of RipeMD see,
+    * http://www.esat.kuleuven.ac.be/~bosselae/ripemd160.html
+    */
+    public class RipeMD160Digest
+		: GeneralDigest
+    {
+        private const int DigestLength = 20;
+
+        private int H0, H1, H2, H3, H4; // IV's
+
+        private int[] X = new int[16];
+        private int xOff;
+
+        /**
+        * Standard constructor
+        */
+        public RipeMD160Digest()
+        {
+            Reset();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public RipeMD160Digest(RipeMD160Digest t) : base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(RipeMD160Digest t)
+		{
+			base.CopyIn(t);
+
+            H0 = t.H0;
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        public override string AlgorithmName
+		{
+			get { return "RIPEMD160"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		internal override void ProcessWord(
+            byte[] input,
+            int inOff)
+        {
+            X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+                | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+            if (xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+		internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+            ProcessBlock();
+            }
+
+            X[14] = (int)(bitLength & 0xffffffff);
+            X[15] = (int)((ulong) bitLength >> 32);
+        }
+
+        private void UnpackWord(
+            int word,
+            byte[] outBytes,
+            int outOff)
+        {
+            outBytes[outOff]     = (byte)word;
+            outBytes[outOff + 1] = (byte)((uint) word >> 8);
+            outBytes[outOff + 2] = (byte)((uint) word >> 16);
+            outBytes[outOff + 3] = (byte)((uint) word >> 24);
+        }
+
+        public override int DoFinal(
+            byte[] output,
+            int outOff)
+        {
+            Finish();
+
+            UnpackWord(H0, output, outOff);
+            UnpackWord(H1, output, outOff + 4);
+            UnpackWord(H2, output, outOff + 8);
+            UnpackWord(H3, output, outOff + 12);
+            UnpackWord(H4, output, outOff + 16);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables to the IV values.
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            H0 = unchecked((int) 0x67452301);
+            H1 = unchecked((int) 0xefcdab89);
+            H2 = unchecked((int) 0x98badcfe);
+            H3 = unchecked((int) 0x10325476);
+            H4 = unchecked((int) 0xc3d2e1f0);
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        /*
+        * rotate int x left n bits.
+        */
+        private  int RL(
+            int x,
+            int n)
+        {
+            return (x << n) | (int) ((uint) x >> (32 - n));
+        }
+
+        /*
+        * f1,f2,f3,f4,f5 are the basic RipeMD160 functions.
+        */
+
+        /*
+        * rounds 0-15
+        */
+        private  int F1(
+            int x,
+            int y,
+            int z)
+        {
+            return x ^ y ^ z;
+        }
+
+        /*
+        * rounds 16-31
+        */
+        private  int F2(
+            int x,
+            int y,
+            int z)
+        {
+            return (x & y) | (~x & z);
+        }
+
+        /*
+        * rounds 32-47
+        */
+        private  int F3(
+            int x,
+            int y,
+            int z)
+        {
+            return (x | ~y) ^ z;
+        }
+
+        /*
+        * rounds 48-63
+        */
+        private  int F4(
+            int x,
+            int y,
+            int z)
+        {
+            return (x & z) | (y & ~z);
+        }
+
+        /*
+        * rounds 64-79
+        */
+        private  int F5(
+            int x,
+            int y,
+            int z)
+        {
+            return x ^ (y | ~z);
+        }
+
+        internal override void ProcessBlock()
+        {
+            int a, aa;
+            int b, bb;
+            int c, cc;
+            int d, dd;
+            int e, ee;
+
+            a = aa = H0;
+            b = bb = H1;
+            c = cc = H2;
+            d = dd = H3;
+            e = ee = H4;
+
+            //
+            // Rounds 1 - 16
+            //
+            // left
+            a = RL(a + F1(b,c,d) + X[ 0], 11) + e; c = RL(c, 10);
+            e = RL(e + F1(a,b,c) + X[ 1], 14) + d; b = RL(b, 10);
+            d = RL(d + F1(e,a,b) + X[ 2], 15) + c; a = RL(a, 10);
+            c = RL(c + F1(d,e,a) + X[ 3], 12) + b; e = RL(e, 10);
+            b = RL(b + F1(c,d,e) + X[ 4],  5) + a; d = RL(d, 10);
+            a = RL(a + F1(b,c,d) + X[ 5],  8) + e; c = RL(c, 10);
+            e = RL(e + F1(a,b,c) + X[ 6],  7) + d; b = RL(b, 10);
+            d = RL(d + F1(e,a,b) + X[ 7],  9) + c; a = RL(a, 10);
+            c = RL(c + F1(d,e,a) + X[ 8], 11) + b; e = RL(e, 10);
+            b = RL(b + F1(c,d,e) + X[ 9], 13) + a; d = RL(d, 10);
+            a = RL(a + F1(b,c,d) + X[10], 14) + e; c = RL(c, 10);
+            e = RL(e + F1(a,b,c) + X[11], 15) + d; b = RL(b, 10);
+            d = RL(d + F1(e,a,b) + X[12],  6) + c; a = RL(a, 10);
+            c = RL(c + F1(d,e,a) + X[13],  7) + b; e = RL(e, 10);
+            b = RL(b + F1(c,d,e) + X[14],  9) + a; d = RL(d, 10);
+            a = RL(a + F1(b,c,d) + X[15],  8) + e; c = RL(c, 10);
+
+            // right
+            aa = RL(aa + F5(bb,cc,dd) + X[ 5] + unchecked((int) 0x50a28be6),  8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa,bb,cc) + X[14] + unchecked((int) 0x50a28be6),  9) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee,aa,bb) + X[ 7] + unchecked((int) 0x50a28be6),  9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd,ee,aa) + X[ 0] + unchecked((int) 0x50a28be6), 11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc,dd,ee) + X[ 9] + unchecked((int) 0x50a28be6), 13) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb,cc,dd) + X[ 2] + unchecked((int) 0x50a28be6), 15) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa,bb,cc) + X[11] + unchecked((int) 0x50a28be6), 15) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee,aa,bb) + X[ 4] + unchecked((int) 0x50a28be6),  5) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd,ee,aa) + X[13] + unchecked((int) 0x50a28be6),  7) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc,dd,ee) + X[ 6] + unchecked((int) 0x50a28be6),  7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb,cc,dd) + X[15] + unchecked((int) 0x50a28be6),  8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa,bb,cc) + X[ 8] + unchecked((int) 0x50a28be6), 11) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee,aa,bb) + X[ 1] + unchecked((int) 0x50a28be6), 14) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd,ee,aa) + X[10] + unchecked((int) 0x50a28be6), 14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc,dd,ee) + X[ 3] + unchecked((int) 0x50a28be6), 12) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb,cc,dd) + X[12] + unchecked((int) 0x50a28be6),  6) + ee; cc = RL(cc, 10);
+
+            //
+            // Rounds 16-31
+            //
+            // left
+            e = RL(e + F2(a,b,c) + X[ 7] + unchecked((int) 0x5a827999),   7) + d; b = RL(b, 10);
+            d = RL(d + F2(e,a,b) + X[ 4] + unchecked((int) 0x5a827999),   6) + c; a = RL(a, 10);
+            c = RL(c + F2(d,e,a) + X[13] + unchecked((int) 0x5a827999),   8) + b; e = RL(e, 10);
+            b = RL(b + F2(c,d,e) + X[ 1] + unchecked((int) 0x5a827999),  13) + a; d = RL(d, 10);
+            a = RL(a + F2(b,c,d) + X[10] + unchecked((int) 0x5a827999),  11) + e; c = RL(c, 10);
+            e = RL(e + F2(a,b,c) + X[ 6] + unchecked((int) 0x5a827999),   9) + d; b = RL(b, 10);
+            d = RL(d + F2(e,a,b) + X[15] + unchecked((int) 0x5a827999),   7) + c; a = RL(a, 10);
+            c = RL(c + F2(d,e,a) + X[ 3] + unchecked((int) 0x5a827999),  15) + b; e = RL(e, 10);
+            b = RL(b + F2(c,d,e) + X[12] + unchecked((int) 0x5a827999),   7) + a; d = RL(d, 10);
+            a = RL(a + F2(b,c,d) + X[ 0] + unchecked((int) 0x5a827999),  12) + e; c = RL(c, 10);
+            e = RL(e + F2(a,b,c) + X[ 9] + unchecked((int) 0x5a827999),  15) + d; b = RL(b, 10);
+            d = RL(d + F2(e,a,b) + X[ 5] + unchecked((int) 0x5a827999),   9) + c; a = RL(a, 10);
+            c = RL(c + F2(d,e,a) + X[ 2] + unchecked((int) 0x5a827999),  11) + b; e = RL(e, 10);
+            b = RL(b + F2(c,d,e) + X[14] + unchecked((int) 0x5a827999),   7) + a; d = RL(d, 10);
+            a = RL(a + F2(b,c,d) + X[11] + unchecked((int) 0x5a827999),  13) + e; c = RL(c, 10);
+            e = RL(e + F2(a,b,c) + X[ 8] + unchecked((int) 0x5a827999),  12) + d; b = RL(b, 10);
+
+            // right
+            ee = RL(ee + F4(aa,bb,cc) + X[ 6] + unchecked((int) 0x5c4dd124),   9) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee,aa,bb) + X[11] + unchecked((int) 0x5c4dd124),  13) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd,ee,aa) + X[ 3] + unchecked((int) 0x5c4dd124),  15) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc,dd,ee) + X[ 7] + unchecked((int) 0x5c4dd124),   7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb,cc,dd) + X[ 0] + unchecked((int) 0x5c4dd124),  12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa,bb,cc) + X[13] + unchecked((int) 0x5c4dd124),   8) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee,aa,bb) + X[ 5] + unchecked((int) 0x5c4dd124),   9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd,ee,aa) + X[10] + unchecked((int) 0x5c4dd124),  11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc,dd,ee) + X[14] + unchecked((int) 0x5c4dd124),   7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb,cc,dd) + X[15] + unchecked((int) 0x5c4dd124),   7) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa,bb,cc) + X[ 8] + unchecked((int) 0x5c4dd124),  12) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee,aa,bb) + X[12] + unchecked((int) 0x5c4dd124),   7) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd,ee,aa) + X[ 4] + unchecked((int) 0x5c4dd124),   6) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc,dd,ee) + X[ 9] + unchecked((int) 0x5c4dd124),  15) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb,cc,dd) + X[ 1] + unchecked((int) 0x5c4dd124),  13) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa,bb,cc) + X[ 2] + unchecked((int) 0x5c4dd124),  11) + dd; bb = RL(bb, 10);
+
+            //
+            // Rounds 32-47
+            //
+            // left
+            d = RL(d + F3(e,a,b) + X[ 3] + unchecked((int) 0x6ed9eba1),  11) + c; a = RL(a, 10);
+            c = RL(c + F3(d,e,a) + X[10] + unchecked((int) 0x6ed9eba1),  13) + b; e = RL(e, 10);
+            b = RL(b + F3(c,d,e) + X[14] + unchecked((int) 0x6ed9eba1),   6) + a; d = RL(d, 10);
+            a = RL(a + F3(b,c,d) + X[ 4] + unchecked((int) 0x6ed9eba1),   7) + e; c = RL(c, 10);
+            e = RL(e + F3(a,b,c) + X[ 9] + unchecked((int) 0x6ed9eba1),  14) + d; b = RL(b, 10);
+            d = RL(d + F3(e,a,b) + X[15] + unchecked((int) 0x6ed9eba1),   9) + c; a = RL(a, 10);
+            c = RL(c + F3(d,e,a) + X[ 8] + unchecked((int) 0x6ed9eba1),  13) + b; e = RL(e, 10);
+            b = RL(b + F3(c,d,e) + X[ 1] + unchecked((int) 0x6ed9eba1),  15) + a; d = RL(d, 10);
+            a = RL(a + F3(b,c,d) + X[ 2] + unchecked((int) 0x6ed9eba1),  14) + e; c = RL(c, 10);
+            e = RL(e + F3(a,b,c) + X[ 7] + unchecked((int) 0x6ed9eba1),   8) + d; b = RL(b, 10);
+            d = RL(d + F3(e,a,b) + X[ 0] + unchecked((int) 0x6ed9eba1),  13) + c; a = RL(a, 10);
+            c = RL(c + F3(d,e,a) + X[ 6] + unchecked((int) 0x6ed9eba1),   6) + b; e = RL(e, 10);
+            b = RL(b + F3(c,d,e) + X[13] + unchecked((int) 0x6ed9eba1),   5) + a; d = RL(d, 10);
+            a = RL(a + F3(b,c,d) + X[11] + unchecked((int) 0x6ed9eba1),  12) + e; c = RL(c, 10);
+            e = RL(e + F3(a,b,c) + X[ 5] + unchecked((int) 0x6ed9eba1),   7) + d; b = RL(b, 10);
+            d = RL(d + F3(e,a,b) + X[12] + unchecked((int) 0x6ed9eba1),   5) + c; a = RL(a, 10);
+
+            // right
+            dd = RL(dd + F3(ee,aa,bb) + X[15] + unchecked((int) 0x6d703ef3),   9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd,ee,aa) + X[ 5] + unchecked((int) 0x6d703ef3),   7) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc,dd,ee) + X[ 1] + unchecked((int) 0x6d703ef3),  15) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb,cc,dd) + X[ 3] + unchecked((int) 0x6d703ef3),  11) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa,bb,cc) + X[ 7] + unchecked((int) 0x6d703ef3),   8) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee,aa,bb) + X[14] + unchecked((int) 0x6d703ef3),   6) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd,ee,aa) + X[ 6] + unchecked((int) 0x6d703ef3),   6) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc,dd,ee) + X[ 9] + unchecked((int) 0x6d703ef3),  14) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb,cc,dd) + X[11] + unchecked((int) 0x6d703ef3),  12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa,bb,cc) + X[ 8] + unchecked((int) 0x6d703ef3),  13) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee,aa,bb) + X[12] + unchecked((int) 0x6d703ef3),   5) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd,ee,aa) + X[ 2] + unchecked((int) 0x6d703ef3),  14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc,dd,ee) + X[10] + unchecked((int) 0x6d703ef3),  13) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb,cc,dd) + X[ 0] + unchecked((int) 0x6d703ef3),  13) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa,bb,cc) + X[ 4] + unchecked((int) 0x6d703ef3),   7) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee,aa,bb) + X[13] + unchecked((int) 0x6d703ef3),   5) + cc; aa = RL(aa, 10);
+
+            //
+            // Rounds 48-63
+            //
+            // left
+            c = RL(c + F4(d,e,a) + X[ 1] + unchecked((int) 0x8f1bbcdc),  11) + b; e = RL(e, 10);
+            b = RL(b + F4(c,d,e) + X[ 9] + unchecked((int) 0x8f1bbcdc),  12) + a; d = RL(d, 10);
+            a = RL(a + F4(b,c,d) + X[11] + unchecked((int) 0x8f1bbcdc), 14) + e; c = RL(c, 10);
+            e = RL(e + F4(a,b,c) + X[10] + unchecked((int) 0x8f1bbcdc), 15) + d; b = RL(b, 10);
+            d = RL(d + F4(e,a,b) + X[ 0] + unchecked((int) 0x8f1bbcdc), 14) + c; a = RL(a, 10);
+            c = RL(c + F4(d,e,a) + X[ 8] + unchecked((int) 0x8f1bbcdc), 15) + b; e = RL(e, 10);
+            b = RL(b + F4(c,d,e) + X[12] + unchecked((int) 0x8f1bbcdc),  9) + a; d = RL(d, 10);
+            a = RL(a + F4(b,c,d) + X[ 4] + unchecked((int) 0x8f1bbcdc),  8) + e; c = RL(c, 10);
+            e = RL(e + F4(a,b,c) + X[13] + unchecked((int) 0x8f1bbcdc),  9) + d; b = RL(b, 10);
+            d = RL(d + F4(e,a,b) + X[ 3] + unchecked((int) 0x8f1bbcdc), 14) + c; a = RL(a, 10);
+            c = RL(c + F4(d,e,a) + X[ 7] + unchecked((int) 0x8f1bbcdc),  5) + b; e = RL(e, 10);
+            b = RL(b + F4(c,d,e) + X[15] + unchecked((int) 0x8f1bbcdc),  6) + a; d = RL(d, 10);
+            a = RL(a + F4(b,c,d) + X[14] + unchecked((int) 0x8f1bbcdc),  8) + e; c = RL(c, 10);
+            e = RL(e + F4(a,b,c) + X[ 5] + unchecked((int) 0x8f1bbcdc),  6) + d; b = RL(b, 10);
+            d = RL(d + F4(e,a,b) + X[ 6] + unchecked((int) 0x8f1bbcdc),  5) + c; a = RL(a, 10);
+            c = RL(c + F4(d,e,a) + X[ 2] + unchecked((int) 0x8f1bbcdc), 12) + b; e = RL(e, 10);
+
+            // right
+            cc = RL(cc + F2(dd,ee,aa) + X[ 8] + unchecked((int) 0x7a6d76e9),  15) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc,dd,ee) + X[ 6] + unchecked((int) 0x7a6d76e9),   5) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb,cc,dd) + X[ 4] + unchecked((int) 0x7a6d76e9),   8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa,bb,cc) + X[ 1] + unchecked((int) 0x7a6d76e9),  11) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee,aa,bb) + X[ 3] + unchecked((int) 0x7a6d76e9),  14) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd,ee,aa) + X[11] + unchecked((int) 0x7a6d76e9),  14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc,dd,ee) + X[15] + unchecked((int) 0x7a6d76e9),   6) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb,cc,dd) + X[ 0] + unchecked((int) 0x7a6d76e9),  14) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa,bb,cc) + X[ 5] + unchecked((int) 0x7a6d76e9),   6) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee,aa,bb) + X[12] + unchecked((int) 0x7a6d76e9),   9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd,ee,aa) + X[ 2] + unchecked((int) 0x7a6d76e9),  12) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc,dd,ee) + X[13] + unchecked((int) 0x7a6d76e9),   9) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb,cc,dd) + X[ 9] + unchecked((int) 0x7a6d76e9),  12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa,bb,cc) + X[ 7] + unchecked((int) 0x7a6d76e9),   5) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee,aa,bb) + X[10] + unchecked((int) 0x7a6d76e9),  15) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd,ee,aa) + X[14] + unchecked((int) 0x7a6d76e9),   8) + bb; ee = RL(ee, 10);
+
+            //
+            // Rounds 64-79
+            //
+            // left
+            b = RL(b + F5(c,d,e) + X[ 4] + unchecked((int) 0xa953fd4e),  9) + a; d = RL(d, 10);
+            a = RL(a + F5(b,c,d) + X[ 0] + unchecked((int) 0xa953fd4e), 15) + e; c = RL(c, 10);
+            e = RL(e + F5(a,b,c) + X[ 5] + unchecked((int) 0xa953fd4e),  5) + d; b = RL(b, 10);
+            d = RL(d + F5(e,a,b) + X[ 9] + unchecked((int) 0xa953fd4e), 11) + c; a = RL(a, 10);
+            c = RL(c + F5(d,e,a) + X[ 7] + unchecked((int) 0xa953fd4e),  6) + b; e = RL(e, 10);
+            b = RL(b + F5(c,d,e) + X[12] + unchecked((int) 0xa953fd4e),  8) + a; d = RL(d, 10);
+            a = RL(a + F5(b,c,d) + X[ 2] + unchecked((int) 0xa953fd4e), 13) + e; c = RL(c, 10);
+            e = RL(e + F5(a,b,c) + X[10] + unchecked((int) 0xa953fd4e), 12) + d; b = RL(b, 10);
+            d = RL(d + F5(e,a,b) + X[14] + unchecked((int) 0xa953fd4e),  5) + c; a = RL(a, 10);
+            c = RL(c + F5(d,e,a) + X[ 1] + unchecked((int) 0xa953fd4e), 12) + b; e = RL(e, 10);
+            b = RL(b + F5(c,d,e) + X[ 3] + unchecked((int) 0xa953fd4e), 13) + a; d = RL(d, 10);
+            a = RL(a + F5(b,c,d) + X[ 8] + unchecked((int) 0xa953fd4e), 14) + e; c = RL(c, 10);
+            e = RL(e + F5(a,b,c) + X[11] + unchecked((int) 0xa953fd4e), 11) + d; b = RL(b, 10);
+            d = RL(d + F5(e,a,b) + X[ 6] + unchecked((int) 0xa953fd4e),  8) + c; a = RL(a, 10);
+            c = RL(c + F5(d,e,a) + X[15] + unchecked((int) 0xa953fd4e),  5) + b; e = RL(e, 10);
+            b = RL(b + F5(c,d,e) + X[13] + unchecked((int) 0xa953fd4e),  6) + a; d = RL(d, 10);
+
+            // right
+            bb = RL(bb + F1(cc,dd,ee) + X[12],  8) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb,cc,dd) + X[15],  5) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa,bb,cc) + X[10], 12) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee,aa,bb) + X[ 4],  9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd,ee,aa) + X[ 1], 12) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc,dd,ee) + X[ 5],  5) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb,cc,dd) + X[ 8], 14) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa,bb,cc) + X[ 7],  6) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee,aa,bb) + X[ 6],  8) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd,ee,aa) + X[ 2], 13) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc,dd,ee) + X[13],  6) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb,cc,dd) + X[14],  5) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa,bb,cc) + X[ 0], 15) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee,aa,bb) + X[ 3], 13) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd,ee,aa) + X[ 9], 11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc,dd,ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+            dd += c + H1;
+            H1 = H2 + d + ee;
+            H2 = H3 + e + aa;
+            H3 = H4 + a + bb;
+            H4 = H0 + b + cc;
+            H0 = dd;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new RipeMD160Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			RipeMD160Digest d = (RipeMD160Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD256Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD256Digest.cs
new file mode 100644
index 0000000..3062757
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD256Digest.cs
@@ -0,0 +1,430 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /// <remarks>
+    /// <p>Implementation of RipeMD256.</p>
+    /// <p><b>Note:</b> this algorithm offers the same level of security as RipeMD128.</p>
+    /// </remarks>
+    public class RipeMD256Digest
+		: GeneralDigest
+    {
+        public override string AlgorithmName
+		{
+			get { return "RIPEMD256"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		private const int DigestLength = 32;
+
+		private int H0, H1, H2, H3, H4, H5, H6, H7; // IV's
+
+		private int[] X = new int[16];
+        private int xOff;
+
+        /// <summary> Standard constructor</summary>
+        public RipeMD256Digest()
+        {
+            Reset();
+        }
+
+        /// <summary> Copy constructor.  This will copy the state of the provided
+        /// message digest.
+        /// </summary>
+        public RipeMD256Digest(RipeMD256Digest t):base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(RipeMD256Digest t)
+		{
+			base.CopyIn(t);
+
+            H0 = t.H0;
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+            H6 = t.H6;
+            H7 = t.H7;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        internal override void ProcessWord(
+            byte[] input,
+            int inOff)
+        {
+            X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+                | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+            if (xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (int)(bitLength & 0xffffffff);
+            X[15] = (int)((ulong)bitLength >> 32);
+        }
+
+        private void UnpackWord(
+            int word,
+            byte[] outBytes,
+            int outOff)
+        {
+            outBytes[outOff] = (byte)(uint)word;
+            outBytes[outOff + 1] = (byte)((uint)word >> 8);
+            outBytes[outOff + 2] = (byte)((uint)word >> 16);
+            outBytes[outOff + 3] = (byte)((uint)word >> 24);
+        }
+
+        public override int DoFinal(byte[] output, int outOff)
+        {
+            Finish();
+
+            UnpackWord(H0, output, outOff);
+            UnpackWord(H1, output, outOff + 4);
+            UnpackWord(H2, output, outOff + 8);
+            UnpackWord(H3, output, outOff + 12);
+            UnpackWord(H4, output, outOff + 16);
+            UnpackWord(H5, output, outOff + 20);
+            UnpackWord(H6, output, outOff + 24);
+            UnpackWord(H7, output, outOff + 28);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /// <summary> reset the chaining variables to the IV values.</summary>
+        public override void  Reset()
+        {
+            base.Reset();
+
+            H0 = unchecked((int)0x67452301);
+            H1 = unchecked((int)0xefcdab89);
+            H2 = unchecked((int)0x98badcfe);
+            H3 = unchecked((int)0x10325476);
+            H4 = unchecked((int)0x76543210);
+            H5 = unchecked((int)0xFEDCBA98);
+            H6 = unchecked((int)0x89ABCDEF);
+            H7 = unchecked((int)0x01234567);
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        /*
+        * rotate int x left n bits.
+        */
+        private int RL(
+            int x,
+            int n)
+        {
+            return (x << n) | (int)((uint)x >> (32 - n));
+        }
+
+        /*
+        * f1,f2,f3,f4 are the basic RipeMD128 functions.
+        */
+
+        /*
+        * F
+        */
+        private int F1(int x, int y, int z)
+        {
+            return x ^ y ^ z;
+        }
+
+        /*
+        * G
+        */
+        private int F2(int x, int y, int z)
+        {
+            return (x & y) | (~ x & z);
+        }
+
+        /*
+        * H
+        */
+        private int F3(int x, int y, int z)
+        {
+            return (x | ~ y) ^ z;
+        }
+
+        /*
+        * I
+        */
+        private int F4(int x, int y, int z)
+        {
+            return (x & z) | (y & ~ z);
+        }
+
+        private int F1(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F1(b, c, d) + x, s);
+        }
+
+        private int F2(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F2(b, c, d) + x + unchecked((int)0x5a827999), s);
+        }
+
+        private int F3(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F3(b, c, d) + x + unchecked((int)0x6ed9eba1), s);
+        }
+
+        private int F4(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F4(b, c, d) + x + unchecked((int)0x8f1bbcdc), s);
+        }
+
+        private int FF1(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F1(b, c, d) + x, s);
+        }
+
+        private int FF2(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F2(b, c, d) + x + unchecked((int)0x6d703ef3), s);
+        }
+
+        private int FF3(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F3(b, c, d) + x + unchecked((int)0x5c4dd124), s);
+        }
+
+        private int FF4(int a, int b, int c, int d, int x, int s)
+        {
+            return RL(a + F4(b, c, d) + x + unchecked((int)0x50a28be6), s);
+        }
+
+        internal override void ProcessBlock()
+        {
+            int a, aa;
+            int b, bb;
+            int c, cc;
+            int d, dd;
+            int t;
+
+            a = H0;
+            b = H1;
+            c = H2;
+            d = H3;
+            aa = H4;
+            bb = H5;
+            cc = H6;
+            dd = H7;
+
+            //
+            // Round 1
+            //
+
+            a = F1(a, b, c, d, X[0], 11);
+            d = F1(d, a, b, c, X[1], 14);
+            c = F1(c, d, a, b, X[2], 15);
+            b = F1(b, c, d, a, X[3], 12);
+            a = F1(a, b, c, d, X[4], 5);
+            d = F1(d, a, b, c, X[5], 8);
+            c = F1(c, d, a, b, X[6], 7);
+            b = F1(b, c, d, a, X[7], 9);
+            a = F1(a, b, c, d, X[8], 11);
+            d = F1(d, a, b, c, X[9], 13);
+            c = F1(c, d, a, b, X[10], 14);
+            b = F1(b, c, d, a, X[11], 15);
+            a = F1(a, b, c, d, X[12], 6);
+            d = F1(d, a, b, c, X[13], 7);
+            c = F1(c, d, a, b, X[14], 9);
+            b = F1(b, c, d, a, X[15], 8);
+
+            aa = FF4(aa, bb, cc, dd, X[5], 8);
+            dd = FF4(dd, aa, bb, cc, X[14], 9);
+            cc = FF4(cc, dd, aa, bb, X[7], 9);
+            bb = FF4(bb, cc, dd, aa, X[0], 11);
+            aa = FF4(aa, bb, cc, dd, X[9], 13);
+            dd = FF4(dd, aa, bb, cc, X[2], 15);
+            cc = FF4(cc, dd, aa, bb, X[11], 15);
+            bb = FF4(bb, cc, dd, aa, X[4], 5);
+            aa = FF4(aa, bb, cc, dd, X[13], 7);
+            dd = FF4(dd, aa, bb, cc, X[6], 7);
+            cc = FF4(cc, dd, aa, bb, X[15], 8);
+            bb = FF4(bb, cc, dd, aa, X[8], 11);
+            aa = FF4(aa, bb, cc, dd, X[1], 14);
+            dd = FF4(dd, aa, bb, cc, X[10], 14);
+            cc = FF4(cc, dd, aa, bb, X[3], 12);
+            bb = FF4(bb, cc, dd, aa, X[12], 6);
+
+            t = a; a = aa; aa = t;
+
+            //
+            // Round 2
+            //
+            a = F2(a, b, c, d, X[7], 7);
+            d = F2(d, a, b, c, X[4], 6);
+            c = F2(c, d, a, b, X[13], 8);
+            b = F2(b, c, d, a, X[1], 13);
+            a = F2(a, b, c, d, X[10], 11);
+            d = F2(d, a, b, c, X[6], 9);
+            c = F2(c, d, a, b, X[15], 7);
+            b = F2(b, c, d, a, X[3], 15);
+            a = F2(a, b, c, d, X[12], 7);
+            d = F2(d, a, b, c, X[0], 12);
+            c = F2(c, d, a, b, X[9], 15);
+            b = F2(b, c, d, a, X[5], 9);
+            a = F2(a, b, c, d, X[2], 11);
+            d = F2(d, a, b, c, X[14], 7);
+            c = F2(c, d, a, b, X[11], 13);
+            b = F2(b, c, d, a, X[8], 12);
+
+            aa = FF3(aa, bb, cc, dd, X[6], 9);
+            dd = FF3(dd, aa, bb, cc, X[11], 13);
+            cc = FF3(cc, dd, aa, bb, X[3], 15);
+            bb = FF3(bb, cc, dd, aa, X[7], 7);
+            aa = FF3(aa, bb, cc, dd, X[0], 12);
+            dd = FF3(dd, aa, bb, cc, X[13], 8);
+            cc = FF3(cc, dd, aa, bb, X[5], 9);
+            bb = FF3(bb, cc, dd, aa, X[10], 11);
+            aa = FF3(aa, bb, cc, dd, X[14], 7);
+            dd = FF3(dd, aa, bb, cc, X[15], 7);
+            cc = FF3(cc, dd, aa, bb, X[8], 12);
+            bb = FF3(bb, cc, dd, aa, X[12], 7);
+            aa = FF3(aa, bb, cc, dd, X[4], 6);
+            dd = FF3(dd, aa, bb, cc, X[9], 15);
+            cc = FF3(cc, dd, aa, bb, X[1], 13);
+            bb = FF3(bb, cc, dd, aa, X[2], 11);
+
+            t = b; b = bb; bb = t;
+
+            //
+            // Round 3
+            //
+            a = F3(a, b, c, d, X[3], 11);
+            d = F3(d, a, b, c, X[10], 13);
+            c = F3(c, d, a, b, X[14], 6);
+            b = F3(b, c, d, a, X[4], 7);
+            a = F3(a, b, c, d, X[9], 14);
+            d = F3(d, a, b, c, X[15], 9);
+            c = F3(c, d, a, b, X[8], 13);
+            b = F3(b, c, d, a, X[1], 15);
+            a = F3(a, b, c, d, X[2], 14);
+            d = F3(d, a, b, c, X[7], 8);
+            c = F3(c, d, a, b, X[0], 13);
+            b = F3(b, c, d, a, X[6], 6);
+            a = F3(a, b, c, d, X[13], 5);
+            d = F3(d, a, b, c, X[11], 12);
+            c = F3(c, d, a, b, X[5], 7);
+            b = F3(b, c, d, a, X[12], 5);
+
+            aa = FF2(aa, bb, cc, dd, X[15], 9);
+            dd = FF2(dd, aa, bb, cc, X[5], 7);
+            cc = FF2(cc, dd, aa, bb, X[1], 15);
+            bb = FF2(bb, cc, dd, aa, X[3], 11);
+            aa = FF2(aa, bb, cc, dd, X[7], 8);
+            dd = FF2(dd, aa, bb, cc, X[14], 6);
+            cc = FF2(cc, dd, aa, bb, X[6], 6);
+            bb = FF2(bb, cc, dd, aa, X[9], 14);
+            aa = FF2(aa, bb, cc, dd, X[11], 12);
+            dd = FF2(dd, aa, bb, cc, X[8], 13);
+            cc = FF2(cc, dd, aa, bb, X[12], 5);
+            bb = FF2(bb, cc, dd, aa, X[2], 14);
+            aa = FF2(aa, bb, cc, dd, X[10], 13);
+            dd = FF2(dd, aa, bb, cc, X[0], 13);
+            cc = FF2(cc, dd, aa, bb, X[4], 7);
+            bb = FF2(bb, cc, dd, aa, X[13], 5);
+
+            t = c; c = cc; cc = t;
+
+            //
+            // Round 4
+            //
+            a = F4(a, b, c, d, X[1], 11);
+            d = F4(d, a, b, c, X[9], 12);
+            c = F4(c, d, a, b, X[11], 14);
+            b = F4(b, c, d, a, X[10], 15);
+            a = F4(a, b, c, d, X[0], 14);
+            d = F4(d, a, b, c, X[8], 15);
+            c = F4(c, d, a, b, X[12], 9);
+            b = F4(b, c, d, a, X[4], 8);
+            a = F4(a, b, c, d, X[13], 9);
+            d = F4(d, a, b, c, X[3], 14);
+            c = F4(c, d, a, b, X[7], 5);
+            b = F4(b, c, d, a, X[15], 6);
+            a = F4(a, b, c, d, X[14], 8);
+            d = F4(d, a, b, c, X[5], 6);
+            c = F4(c, d, a, b, X[6], 5);
+            b = F4(b, c, d, a, X[2], 12);
+
+            aa = FF1(aa, bb, cc, dd, X[8], 15);
+            dd = FF1(dd, aa, bb, cc, X[6], 5);
+            cc = FF1(cc, dd, aa, bb, X[4], 8);
+            bb = FF1(bb, cc, dd, aa, X[1], 11);
+            aa = FF1(aa, bb, cc, dd, X[3], 14);
+            dd = FF1(dd, aa, bb, cc, X[11], 14);
+            cc = FF1(cc, dd, aa, bb, X[15], 6);
+            bb = FF1(bb, cc, dd, aa, X[0], 14);
+            aa = FF1(aa, bb, cc, dd, X[5], 6);
+            dd = FF1(dd, aa, bb, cc, X[12], 9);
+            cc = FF1(cc, dd, aa, bb, X[2], 12);
+            bb = FF1(bb, cc, dd, aa, X[13], 9);
+            aa = FF1(aa, bb, cc, dd, X[9], 12);
+            dd = FF1(dd, aa, bb, cc, X[7], 5);
+            cc = FF1(cc, dd, aa, bb, X[10], 15);
+            bb = FF1(bb, cc, dd, aa, X[14], 8);
+
+            t = d; d = dd; dd = t;
+
+            H0 += a;
+            H1 += b;
+            H2 += c;
+            H3 += d;
+            H4 += aa;
+            H5 += bb;
+            H6 += cc;
+            H7 += dd;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new RipeMD256Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			RipeMD256Digest d = (RipeMD256Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD320Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD320Digest.cs
new file mode 100644
index 0000000..767d74d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/RipeMD320Digest.cs
@@ -0,0 +1,459 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+	/// <remarks>
+	/// <p>Implementation of RipeMD 320.</p>
+	/// <p><b>Note:</b> this algorithm offers the same level of security as RipeMD160.</p>
+	/// </remarks>
+    public class RipeMD320Digest
+		: GeneralDigest
+    {
+        public override string AlgorithmName
+		{
+			get { return "RIPEMD320"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		private const int DigestLength = 40;
+
+		private int H0, H1, H2, H3, H4, H5, H6, H7, H8, H9; // IV's
+
+        private int[] X = new int[16];
+        private int xOff;
+
+        /// <summary> Standard constructor</summary>
+        public RipeMD320Digest()
+        {
+            Reset();
+        }
+
+        /// <summary> Copy constructor.  This will copy the state of the provided
+        /// message digest.
+        /// </summary>
+        public RipeMD320Digest(RipeMD320Digest t)
+			: base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(RipeMD320Digest t)
+		{
+			base.CopyIn(t);
+
+            H0 = t.H0;
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+            H6 = t.H6;
+            H7 = t.H7;
+            H8 = t.H8;
+            H9 = t.H9;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        internal override void ProcessWord(
+            byte[] input,
+            int inOff)
+        {
+            X[xOff++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+                | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+            if (xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (int)(bitLength & 0xffffffff);
+            X[15] = (int)((ulong)bitLength >> 32);
+        }
+
+        private void UnpackWord(
+            int word,
+            byte[] outBytes,
+            int outOff)
+        {
+            outBytes[outOff] = (byte)word;
+            outBytes[outOff + 1] = (byte)((uint)word >> 8);
+            outBytes[outOff + 2] = (byte)((uint)word >> 16);
+            outBytes[outOff + 3] = (byte)((uint)word >> 24);
+        }
+
+        public override int DoFinal(byte[] output, int outOff)
+        {
+            Finish();
+
+            UnpackWord(H0, output, outOff);
+            UnpackWord(H1, output, outOff + 4);
+            UnpackWord(H2, output, outOff + 8);
+            UnpackWord(H3, output, outOff + 12);
+            UnpackWord(H4, output, outOff + 16);
+            UnpackWord(H5, output, outOff + 20);
+            UnpackWord(H6, output, outOff + 24);
+            UnpackWord(H7, output, outOff + 28);
+            UnpackWord(H8, output, outOff + 32);
+            UnpackWord(H9, output, outOff + 36);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /// <summary> reset the chaining variables to the IV values.</summary>
+        public override void  Reset()
+        {
+            base.Reset();
+
+            H0 = unchecked((int) 0x67452301);
+            H1 = unchecked((int) 0xefcdab89);
+            H2 = unchecked((int) 0x98badcfe);
+            H3 = unchecked((int) 0x10325476);
+            H4 = unchecked((int) 0xc3d2e1f0);
+            H5 = unchecked((int) 0x76543210);
+            H6 = unchecked((int) 0xFEDCBA98);
+            H7 = unchecked((int) 0x89ABCDEF);
+            H8 = unchecked((int) 0x01234567);
+            H9 = unchecked((int) 0x3C2D1E0F);
+
+            xOff = 0;
+
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+
+        /*
+        * rotate int x left n bits.
+        */
+        private int RL(
+            int x,
+            int n)
+        {
+            return (x << n) | (int)(((uint)x) >> (32 - n));
+        }
+
+        /*
+        * f1,f2,f3,f4,f5 are the basic RipeMD160 functions.
+        */
+
+        /*
+        * rounds 0-15
+        */
+        private int F1(int x, int y, int z)
+        {
+            return x ^ y ^ z;
+        }
+
+        /*
+        * rounds 16-31
+        */
+        private int F2(int x, int y, int z)
+        {
+            return (x & y) | (~ x & z);
+        }
+
+        /*
+        * rounds 32-47
+        */
+        private int F3(int x, int y, int z)
+        {
+            return (x | ~ y) ^ z;
+        }
+
+        /*
+        * rounds 48-63
+        */
+        private int F4(int x, int y, int z)
+        {
+            return (x & z) | (y & ~ z);
+        }
+
+        /*
+        * rounds 64-79
+        */
+        private int F5(int x, int y, int z)
+        {
+            return x ^ (y | ~z);
+        }
+
+        internal override void ProcessBlock()
+        {
+            int a, aa;
+            int b, bb;
+            int c, cc;
+            int d, dd;
+            int e, ee;
+            int t;
+
+            a = H0;
+            b = H1;
+            c = H2;
+            d = H3;
+            e = H4;
+            aa = H5;
+            bb = H6;
+            cc = H7;
+            dd = H8;
+            ee = H9;
+
+            //
+            // Rounds 1 - 16
+            //
+            // left
+            a = RL(a + F1(b, c, d) + X[0], 11) + e; c = RL(c, 10);
+            e = RL(e + F1(a, b, c) + X[1], 14) + d; b = RL(b, 10);
+            d = RL(d + F1(e, a, b) + X[2], 15) + c; a = RL(a, 10);
+            c = RL(c + F1(d, e, a) + X[3], 12) + b; e = RL(e, 10);
+            b = RL(b + F1(c, d, e) + X[4], 5) + a; d = RL(d, 10);
+            a = RL(a + F1(b, c, d) + X[5], 8) + e; c = RL(c, 10);
+            e = RL(e + F1(a, b, c) + X[6], 7) + d; b = RL(b, 10);
+            d = RL(d + F1(e, a, b) + X[7], 9) + c; a = RL(a, 10);
+            c = RL(c + F1(d, e, a) + X[8], 11) + b; e = RL(e, 10);
+            b = RL(b + F1(c, d, e) + X[9], 13) + a; d = RL(d, 10);
+            a = RL(a + F1(b, c, d) + X[10], 14) + e; c = RL(c, 10);
+            e = RL(e + F1(a, b, c) + X[11], 15) + d; b = RL(b, 10);
+            d = RL(d + F1(e, a, b) + X[12], 6) + c; a = RL(a, 10);
+            c = RL(c + F1(d, e, a) + X[13], 7) + b; e = RL(e, 10);
+            b = RL(b + F1(c, d, e) + X[14], 9) + a; d = RL(d, 10);
+            a = RL(a + F1(b, c, d) + X[15], 8) + e; c = RL(c, 10);
+
+            // right
+            aa = RL(aa + F5(bb, cc, dd) + X[5] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa, bb, cc) + X[14] + unchecked((int)0x50a28be6), 9) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee, aa, bb) + X[7] + unchecked((int)0x50a28be6), 9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd, ee, aa) + X[0] + unchecked((int)0x50a28be6), 11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc, dd, ee) + X[9] + unchecked((int)0x50a28be6), 13) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb, cc, dd) + X[2] + unchecked((int)0x50a28be6), 15) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa, bb, cc) + X[11] + unchecked((int)0x50a28be6), 15) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee, aa, bb) + X[4] + unchecked((int)0x50a28be6), 5) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd, ee, aa) + X[13] + unchecked((int)0x50a28be6), 7) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc, dd, ee) + X[6] + unchecked((int)0x50a28be6), 7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb, cc, dd) + X[15] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F5(aa, bb, cc) + X[8] + unchecked((int)0x50a28be6), 11) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F5(ee, aa, bb) + X[1] + unchecked((int)0x50a28be6), 14) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F5(dd, ee, aa) + X[10] + unchecked((int)0x50a28be6), 14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F5(cc, dd, ee) + X[3] + unchecked((int)0x50a28be6), 12) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F5(bb, cc, dd) + X[12] + unchecked((int)0x50a28be6), 6) + ee; cc = RL(cc, 10);
+
+            t = a; a = aa; aa = t;
+            //
+            // Rounds 16-31
+            //
+            // left
+            e = RL(e + F2(a, b, c) + X[7] + unchecked((int)0x5a827999), 7) + d; b = RL(b, 10);
+            d = RL(d + F2(e, a, b) + X[4] + unchecked((int)0x5a827999), 6) + c; a = RL(a, 10);
+            c = RL(c + F2(d, e, a) + X[13] + unchecked((int)0x5a827999), 8) + b; e = RL(e, 10);
+            b = RL(b + F2(c, d, e) + X[1] + unchecked((int)0x5a827999), 13) + a; d = RL(d, 10);
+            a = RL(a + F2(b, c, d) + X[10] + unchecked((int)0x5a827999), 11) + e; c = RL(c, 10);
+            e = RL(e + F2(a, b, c) + X[6] + unchecked((int)0x5a827999), 9) + d; b = RL(b, 10);
+            d = RL(d + F2(e, a, b) + X[15] + unchecked((int)0x5a827999), 7) + c; a = RL(a, 10);
+            c = RL(c + F2(d, e, a) + X[3] + unchecked((int)0x5a827999), 15) + b; e = RL(e, 10);
+            b = RL(b + F2(c, d, e) + X[12] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
+            a = RL(a + F2(b, c, d) + X[0] + unchecked((int)0x5a827999), 12) + e; c = RL(c, 10);
+            e = RL(e + F2(a, b, c) + X[9] + unchecked((int)0x5a827999), 15) + d; b = RL(b, 10);
+            d = RL(d + F2(e, a, b) + X[5] + unchecked((int)0x5a827999), 9) + c; a = RL(a, 10);
+            c = RL(c + F2(d, e, a) + X[2] + unchecked((int)0x5a827999), 11) + b; e = RL(e, 10);
+            b = RL(b + F2(c, d, e) + X[14] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
+            a = RL(a + F2(b, c, d) + X[11] + unchecked((int)0x5a827999), 13) + e; c = RL(c, 10);
+            e = RL(e + F2(a, b, c) + X[8] + unchecked((int)0x5a827999), 12) + d; b = RL(b, 10);
+
+            // right
+            ee = RL(ee + F4(aa, bb, cc) + X[6] + unchecked((int)0x5c4dd124), 9) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee, aa, bb) + X[11] + unchecked((int)0x5c4dd124), 13) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd, ee, aa) + X[3] + unchecked((int)0x5c4dd124), 15) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc, dd, ee) + X[7] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb, cc, dd) + X[0] + unchecked((int)0x5c4dd124), 12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa, bb, cc) + X[13] + unchecked((int)0x5c4dd124), 8) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee, aa, bb) + X[5] + unchecked((int)0x5c4dd124), 9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd, ee, aa) + X[10] + unchecked((int)0x5c4dd124), 11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc, dd, ee) + X[14] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb, cc, dd) + X[15] + unchecked((int)0x5c4dd124), 7) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa, bb, cc) + X[8] + unchecked((int)0x5c4dd124), 12) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F4(ee, aa, bb) + X[12] + unchecked((int)0x5c4dd124), 7) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F4(dd, ee, aa) + X[4] + unchecked((int)0x5c4dd124), 6) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F4(cc, dd, ee) + X[9] + unchecked((int)0x5c4dd124), 15) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F4(bb, cc, dd) + X[1] + unchecked((int)0x5c4dd124), 13) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F4(aa, bb, cc) + X[2] + unchecked((int)0x5c4dd124), 11) + dd; bb = RL(bb, 10);
+
+            t = b; b = bb; bb = t;
+
+            //
+            // Rounds 32-47
+            //
+            // left
+            d = RL(d + F3(e, a, b) + X[3] + unchecked((int)0x6ed9eba1), 11) + c; a = RL(a, 10);
+            c = RL(c + F3(d, e, a) + X[10] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
+            b = RL(b + F3(c, d, e) + X[14] + unchecked((int)0x6ed9eba1), 6) + a; d = RL(d, 10);
+            a = RL(a + F3(b, c, d) + X[4] + unchecked((int)0x6ed9eba1), 7) + e; c = RL(c, 10);
+            e = RL(e + F3(a, b, c) + X[9] + unchecked((int)0x6ed9eba1), 14) + d; b = RL(b, 10);
+            d = RL(d + F3(e, a, b) + X[15] + unchecked((int)0x6ed9eba1), 9) + c; a = RL(a, 10);
+            c = RL(c + F3(d, e, a) + X[8] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
+            b = RL(b + F3(c, d, e) + X[1] + unchecked((int)0x6ed9eba1), 15) + a; d = RL(d, 10);
+            a = RL(a + F3(b, c, d) + X[2] + unchecked((int)0x6ed9eba1), 14) + e; c = RL(c, 10);
+            e = RL(e + F3(a, b, c) + X[7] + unchecked((int)0x6ed9eba1), 8) + d; b = RL(b, 10);
+            d = RL(d + F3(e, a, b) + X[0] + unchecked((int)0x6ed9eba1), 13) + c; a = RL(a, 10);
+            c = RL(c + F3(d, e, a) + X[6] + unchecked((int)0x6ed9eba1), 6) + b; e = RL(e, 10);
+            b = RL(b + F3(c, d, e) + X[13] + unchecked((int)0x6ed9eba1), 5) + a; d = RL(d, 10);
+            a = RL(a + F3(b, c, d) + X[11] + unchecked((int)0x6ed9eba1), 12) + e; c = RL(c, 10);
+            e = RL(e + F3(a, b, c) + X[5] + unchecked((int)0x6ed9eba1), 7) + d; b = RL(b, 10);
+            d = RL(d + F3(e, a, b) + X[12] + unchecked((int)0x6ed9eba1), 5) + c; a = RL(a, 10);
+
+            // right
+            dd = RL(dd + F3(ee, aa, bb) + X[15] + unchecked((int)0x6d703ef3), 9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd, ee, aa) + X[5] + unchecked((int)0x6d703ef3), 7) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc, dd, ee) + X[1] + unchecked((int)0x6d703ef3), 15) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb, cc, dd) + X[3] + unchecked((int)0x6d703ef3), 11) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa, bb, cc) + X[7] + unchecked((int)0x6d703ef3), 8) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee, aa, bb) + X[14] + unchecked((int)0x6d703ef3), 6) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd, ee, aa) + X[6] + unchecked((int)0x6d703ef3), 6) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc, dd, ee) + X[9] + unchecked((int)0x6d703ef3), 14) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb, cc, dd) + X[11] + unchecked((int)0x6d703ef3), 12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa, bb, cc) + X[8] + unchecked((int)0x6d703ef3), 13) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee, aa, bb) + X[12] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F3(dd, ee, aa) + X[2] + unchecked((int)0x6d703ef3), 14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F3(cc, dd, ee) + X[10] + unchecked((int)0x6d703ef3), 13) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F3(bb, cc, dd) + X[0] + unchecked((int)0x6d703ef3), 13) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F3(aa, bb, cc) + X[4] + unchecked((int)0x6d703ef3), 7) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F3(ee, aa, bb) + X[13] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
+
+            t = c; c = cc; cc = t;
+
+            //
+            // Rounds 48-63
+            //
+            // left
+            c = RL(c + F4(d, e, a) + X[1] + unchecked((int)0x8f1bbcdc), 11) + b; e = RL(e, 10);
+            b = RL(b + F4(c, d, e) + X[9] + unchecked((int)0x8f1bbcdc), 12) + a; d = RL(d, 10);
+            a = RL(a + F4(b, c, d) + X[11] + unchecked((int)0x8f1bbcdc), 14) + e; c = RL(c, 10);
+            e = RL(e + F4(a, b, c) + X[10] + unchecked((int)0x8f1bbcdc), 15) + d; b = RL(b, 10);
+            d = RL(d + F4(e, a, b) + X[0] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
+            c = RL(c + F4(d, e, a) + X[8] + unchecked((int)0x8f1bbcdc), 15) + b; e = RL(e, 10);
+            b = RL(b + F4(c, d, e) + X[12] + unchecked((int)0x8f1bbcdc), 9) + a; d = RL(d, 10);
+            a = RL(a + F4(b, c, d) + X[4] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
+            e = RL(e + F4(a, b, c) + X[13] + unchecked((int)0x8f1bbcdc), 9) + d; b = RL(b, 10);
+            d = RL(d + F4(e, a, b) + X[3] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
+            c = RL(c + F4(d, e, a) + X[7] + unchecked((int)0x8f1bbcdc), 5) + b; e = RL(e, 10);
+            b = RL(b + F4(c, d, e) + X[15] + unchecked((int)0x8f1bbcdc), 6) + a; d = RL(d, 10);
+            a = RL(a + F4(b, c, d) + X[14] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
+            e = RL(e + F4(a, b, c) + X[5] + unchecked((int)0x8f1bbcdc), 6) + d; b = RL(b, 10);
+            d = RL(d + F4(e, a, b) + X[6] + unchecked((int)0x8f1bbcdc), 5) + c; a = RL(a, 10);
+            c = RL(c + F4(d, e, a) + X[2] + unchecked((int)0x8f1bbcdc), 12) + b; e = RL(e, 10);
+
+            // right
+            cc = RL(cc + F2(dd, ee, aa) + X[8] + unchecked((int)0x7a6d76e9), 15) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc, dd, ee) + X[6] + unchecked((int)0x7a6d76e9), 5) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb, cc, dd) + X[4] + unchecked((int)0x7a6d76e9), 8) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa, bb, cc) + X[1] + unchecked((int)0x7a6d76e9), 11) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee, aa, bb) + X[3] + unchecked((int)0x7a6d76e9), 14) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd, ee, aa) + X[11] + unchecked((int)0x7a6d76e9), 14) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc, dd, ee) + X[15] + unchecked((int)0x7a6d76e9), 6) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb, cc, dd) + X[0] + unchecked((int)0x7a6d76e9), 14) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa, bb, cc) + X[5] + unchecked((int)0x7a6d76e9), 6) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee, aa, bb) + X[12] + unchecked((int)0x7a6d76e9), 9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd, ee, aa) + X[2] + unchecked((int)0x7a6d76e9), 12) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F2(cc, dd, ee) + X[13] + unchecked((int)0x7a6d76e9), 9) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F2(bb, cc, dd) + X[9] + unchecked((int)0x7a6d76e9), 12) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F2(aa, bb, cc) + X[7] + unchecked((int)0x7a6d76e9), 5) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F2(ee, aa, bb) + X[10] + unchecked((int)0x7a6d76e9), 15) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F2(dd, ee, aa) + X[14] + unchecked((int)0x7a6d76e9), 8) + bb; ee = RL(ee, 10);
+
+            t = d; d = dd; dd = t;
+
+            //
+            // Rounds 64-79
+            //
+            // left
+            b = RL(b + F5(c, d, e) + X[4] + unchecked((int)0xa953fd4e), 9) + a; d = RL(d, 10);
+            a = RL(a + F5(b, c, d) + X[0] + unchecked((int)0xa953fd4e), 15) + e; c = RL(c, 10);
+            e = RL(e + F5(a, b, c) + X[5] + unchecked((int)0xa953fd4e), 5) + d; b = RL(b, 10);
+            d = RL(d + F5(e, a, b) + X[9] + unchecked((int)0xa953fd4e), 11) + c; a = RL(a, 10);
+            c = RL(c + F5(d, e, a) + X[7] + unchecked((int)0xa953fd4e), 6) + b; e = RL(e, 10);
+            b = RL(b + F5(c, d, e) + X[12] + unchecked((int)0xa953fd4e), 8) + a; d = RL(d, 10);
+            a = RL(a + F5(b, c, d) + X[2] + unchecked((int)0xa953fd4e), 13) + e; c = RL(c, 10);
+            e = RL(e + F5(a, b, c) + X[10] + unchecked((int)0xa953fd4e), 12) + d; b = RL(b, 10);
+            d = RL(d + F5(e, a, b) + X[14] + unchecked((int)0xa953fd4e), 5) + c; a = RL(a, 10);
+            c = RL(c + F5(d, e, a) + X[1] + unchecked((int)0xa953fd4e), 12) + b; e = RL(e, 10);
+            b = RL(b + F5(c, d, e) + X[3] + unchecked((int)0xa953fd4e), 13) + a; d = RL(d, 10);
+            a = RL(a + F5(b, c, d) + X[8] + unchecked((int)0xa953fd4e), 14) + e; c = RL(c, 10);
+            e = RL(e + F5(a, b, c) + X[11] + unchecked((int)0xa953fd4e), 11) + d; b = RL(b, 10);
+            d = RL(d + F5(e, a, b) + X[6] + unchecked((int)0xa953fd4e), 8) + c; a = RL(a, 10);
+            c = RL(c + F5(d, e, a) + X[15] + unchecked((int)0xa953fd4e), 5) + b; e = RL(e, 10);
+            b = RL(b + F5(c, d, e) + X[13] + unchecked((int)0xa953fd4e), 6) + a; d = RL(d, 10);
+
+            // right
+            bb = RL(bb + F1(cc, dd, ee) + X[12], 8) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb, cc, dd) + X[15], 5) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa, bb, cc) + X[10], 12) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee, aa, bb) + X[4], 9) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd, ee, aa) + X[1], 12) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc, dd, ee) + X[5], 5) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb, cc, dd) + X[8], 14) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa, bb, cc) + X[7], 6) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee, aa, bb) + X[6], 8) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd, ee, aa) + X[2], 13) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc, dd, ee) + X[13], 6) + aa; dd = RL(dd, 10);
+            aa = RL(aa + F1(bb, cc, dd) + X[14], 5) + ee; cc = RL(cc, 10);
+            ee = RL(ee + F1(aa, bb, cc) + X[0], 15) + dd; bb = RL(bb, 10);
+            dd = RL(dd + F1(ee, aa, bb) + X[3], 13) + cc; aa = RL(aa, 10);
+            cc = RL(cc + F1(dd, ee, aa) + X[9], 11) + bb; ee = RL(ee, 10);
+            bb = RL(bb + F1(cc, dd, ee) + X[11], 11) + aa; dd = RL(dd, 10);
+
+            //
+            // do (e, ee) swap as part of assignment.
+            //
+
+            H0 += a;
+            H1 += b;
+            H2 += c;
+            H3 += d;
+            H4 += ee;
+            H5 += aa;
+            H6 += bb;
+            H7 += cc;
+            H8 += dd;
+            H9 += e;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+            for (int i = 0; i != X.Length; i++)
+            {
+                X[i] = 0;
+            }
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new RipeMD320Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			RipeMD320Digest d = (RipeMD320Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/SHA3Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/SHA3Digest.cs
new file mode 100644
index 0000000..2c6837b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/SHA3Digest.cs
@@ -0,0 +1,560 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /// <summary>
+    /// Implementation of SHA-3 based on following KeccakNISTInterface.c from http://keccak.noekeon.org/
+    /// </summary>
+    /// <remarks>
+    /// Following the naming conventions used in the C source code to enable easy review of the implementation.
+    /// </remarks>
+    public class Sha3Digest
+        : IDigest, IMemoable
+    {
+        private static readonly ulong[] KeccakRoundConstants = KeccakInitializeRoundConstants();
+
+        private static readonly int[] KeccakRhoOffsets = KeccakInitializeRhoOffsets();
+
+        private static ulong[] KeccakInitializeRoundConstants()
+        {
+            ulong[] keccakRoundConstants = new ulong[24];
+            byte LFSRState = 0x01;
+
+            for (int i = 0; i < 24; i++)
+            {
+                keccakRoundConstants[i] = 0;
+                for (int j = 0; j < 7; j++)
+                {
+                    int bitPosition = (1 << j) - 1;
+
+                    // LFSR86540
+
+                    bool loBit = (LFSRState & 0x01) != 0;
+                    if (loBit)
+                    {
+                        keccakRoundConstants[i] ^= 1UL << bitPosition;
+                    }
+
+                    bool hiBit = (LFSRState & 0x80) != 0;
+                    LFSRState <<= 1;
+                    if (hiBit)
+                    {
+                        LFSRState ^= 0x71;
+                    }
+
+                }
+            }
+
+            return keccakRoundConstants;
+        }
+
+        private static int[] KeccakInitializeRhoOffsets()
+        {
+            int[] keccakRhoOffsets = new int[25];
+            int x, y, t, newX, newY;
+
+            int rhoOffset = 0;
+            keccakRhoOffsets[(((0) % 5) + 5 * ((0) % 5))] = rhoOffset;
+            x = 1;
+            y = 0;
+            for (t = 1; t < 25; t++)
+            {
+                //rhoOffset = ((t + 1) * (t + 2) / 2) % 64;
+                rhoOffset = (rhoOffset + t) & 63;
+                keccakRhoOffsets[(((x) % 5) + 5 * ((y) % 5))] = rhoOffset;
+                newX = (0 * x + 1 * y) % 5;
+                newY = (2 * x + 3 * y) % 5;
+                x = newX;
+                y = newY;
+            }
+
+            return keccakRhoOffsets;
+        }
+
+        private byte[] state = new byte[(1600 / 8)];
+        private byte[] dataQueue = new byte[(1536 / 8)];
+        private int rate;
+        private int bitsInQueue;
+        private int fixedOutputLength;
+        private bool squeezing;
+        private int bitsAvailableForSqueezing;
+        private byte[] chunk;
+        private byte[] oneByte;
+
+        private void ClearDataQueueSection(int off, int len)
+        {
+            for (int i = off; i != off + len; i++)
+            {
+                dataQueue[i] = 0;
+            }
+        }
+
+        public Sha3Digest()
+        {
+            Init(0);
+        }
+
+        public Sha3Digest(int bitLength)
+        {
+            Init(bitLength);
+        }
+
+        public Sha3Digest(Sha3Digest source)
+        {
+			CopyIn(source);
+		}
+
+		private void CopyIn(Sha3Digest source)
+		{
+            Array.Copy(source.state, 0, this.state, 0, source.state.Length);
+            Array.Copy(source.dataQueue, 0, this.dataQueue, 0, source.dataQueue.Length);
+            this.rate = source.rate;
+            this.bitsInQueue = source.bitsInQueue;
+            this.fixedOutputLength = source.fixedOutputLength;
+            this.squeezing = source.squeezing;
+            this.bitsAvailableForSqueezing = source.bitsAvailableForSqueezing;
+            this.chunk = Arrays.Clone(source.chunk);
+            this.oneByte = Arrays.Clone(source.oneByte);
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return "SHA3-" + fixedOutputLength; }
+        }
+
+        public virtual int GetDigestSize()
+        {
+            return fixedOutputLength / 8;
+        }
+
+        public virtual void Update(byte input)
+        {
+            oneByte[0] = input;
+
+            DoUpdate(oneByte, 0, 8L);
+        }
+
+        public virtual void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            DoUpdate(input, inOff, len * 8L);
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            Squeeze(output, outOff, fixedOutputLength);
+
+            Reset();
+
+            return GetDigestSize();
+        }
+
+        public virtual void Reset()
+        {
+            Init(fixedOutputLength);
+        }
+
+        /**
+         * Return the size of block that the compression function is applied to in bytes.
+         *
+         * @return internal byte length of a block.
+         */
+        public virtual int GetByteLength()
+        {
+            return rate / 8;
+        }
+
+        private void Init(int bitLength)
+        {
+            switch (bitLength)
+            {
+            case 0:
+            case 288:
+                InitSponge(1024, 576);
+                break;
+            case 224:
+                InitSponge(1152, 448);
+                break;
+            case 256:
+                InitSponge(1088, 512);
+                break;
+            case 384:
+                InitSponge(832, 768);
+                break;
+            case 512:
+                InitSponge(576, 1024);
+                break;
+            default:
+                throw new ArgumentException("must be one of 224, 256, 384, or 512.", "bitLength");
+            }
+        }
+
+        private void DoUpdate(byte[] data, int off, long databitlen)
+        {
+            if ((databitlen % 8) == 0)
+            {
+                Absorb(data, off, databitlen);
+            }
+            else
+            {
+                Absorb(data, off, databitlen - (databitlen % 8));
+
+                byte[] lastByte = new byte[1];
+
+                lastByte[0] = (byte)(data[off + (int)(databitlen / 8)] >> (int)(8 - (databitlen % 8)));
+                Absorb(lastByte, off, databitlen % 8);
+            }
+        }
+
+        private void InitSponge(int rate, int capacity)
+        {
+            if (rate + capacity != 1600)
+            {
+                throw new InvalidOperationException("rate + capacity != 1600");
+            }
+            if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0))
+            {
+                throw new InvalidOperationException("invalid rate value");
+            }
+
+            this.rate = rate;
+            // this is never read, need to check to see why we want to save it
+            //  this.capacity = capacity;
+            this.fixedOutputLength = 0;
+            Arrays.Fill(this.state, (byte)0);
+            Arrays.Fill(this.dataQueue, (byte)0);
+            this.bitsInQueue = 0;
+            this.squeezing = false;
+            this.bitsAvailableForSqueezing = 0;
+            this.fixedOutputLength = capacity / 2;
+            this.chunk = new byte[rate / 8];
+            this.oneByte = new byte[1];
+        }
+
+        private void AbsorbQueue()
+        {
+            KeccakAbsorb(state, dataQueue, rate / 8);
+
+            bitsInQueue = 0;
+        }
+
+        private void Absorb(byte[] data, int off, long databitlen)
+        {
+            long i, j, wholeBlocks;
+
+            if ((bitsInQueue % 8) != 0)
+            {
+                throw new InvalidOperationException("attempt to absorb with odd length queue.");
+            }
+            if (squeezing)
+            {
+                throw new InvalidOperationException("attempt to absorb while squeezing.");
+            }
+
+            i = 0;
+            while (i < databitlen)
+            {
+                if ((bitsInQueue == 0) && (databitlen >= rate) && (i <= (databitlen - rate)))
+                {
+                    wholeBlocks = (databitlen - i) / rate;
+
+                    for (j = 0; j < wholeBlocks; j++)
+                    {
+                        Array.Copy(data, (int)(off + (i / 8) + (j * chunk.Length)), chunk, 0, chunk.Length);
+
+                        //displayIntermediateValues.displayBytes(1, "Block to be absorbed", curData, rate / 8);
+
+                        KeccakAbsorb(state, chunk, chunk.Length);
+                    }
+
+                    i += wholeBlocks * rate;
+                }
+                else
+                {
+                    int partialBlock = (int)(databitlen - i);
+                    if (partialBlock + bitsInQueue > rate)
+                    {
+                        partialBlock = rate - bitsInQueue;
+                    }
+                    int partialByte = partialBlock % 8;
+                    partialBlock -= partialByte;
+                    Array.Copy(data, off + (int)(i / 8), dataQueue, bitsInQueue / 8, partialBlock / 8);
+
+                    bitsInQueue += partialBlock;
+                    i += partialBlock;
+                    if (bitsInQueue == rate)
+                    {
+                        AbsorbQueue();
+                    }
+                    if (partialByte > 0)
+                    {
+                        int mask = (1 << partialByte) - 1;
+                        dataQueue[bitsInQueue / 8] = (byte)(data[off + ((int)(i / 8))] & mask);
+                        bitsInQueue += partialByte;
+                        i += partialByte;
+                    }
+                }
+            }
+        }
+
+        private void PadAndSwitchToSqueezingPhase()
+        {
+            if (bitsInQueue + 1 == rate)
+            {
+                dataQueue[bitsInQueue / 8] |= (byte)(1U << (bitsInQueue % 8));
+                AbsorbQueue();
+                ClearDataQueueSection(0, rate / 8);
+            }
+            else
+            {
+                ClearDataQueueSection((bitsInQueue + 7) / 8, rate / 8 - (bitsInQueue + 7) / 8);
+                dataQueue[bitsInQueue / 8] |= (byte)(1U << (bitsInQueue % 8));
+            }
+            dataQueue[(rate - 1) / 8] |= (byte)(1U << ((rate - 1) % 8));
+            AbsorbQueue();
+
+            //displayIntermediateValues.displayText(1, "--- Switching to squeezing phase ---");
+
+            if (rate == 1024)
+            {
+                KeccakExtract1024bits(state, dataQueue);
+                bitsAvailableForSqueezing = 1024;
+            }
+            else
+            {
+                KeccakExtract(state, dataQueue, rate / 64);
+                bitsAvailableForSqueezing = rate;
+            }
+
+            //displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+            squeezing = true;
+        }
+
+        private void Squeeze(byte[] output, int offset, long outputLength)
+        {
+            long i;
+            int partialBlock;
+
+            if (!squeezing)
+            {
+                PadAndSwitchToSqueezingPhase();
+            }
+            if ((outputLength % 8) != 0)
+            {
+                throw new InvalidOperationException("outputLength not a multiple of 8");
+            }
+
+            i = 0;
+            while (i < outputLength)
+            {
+                if (bitsAvailableForSqueezing == 0)
+                {
+                    KeccakPermutation(state);
+
+                    if (rate == 1024)
+                    {
+                        KeccakExtract1024bits(state, dataQueue);
+                        bitsAvailableForSqueezing = 1024;
+                    }
+                    else
+
+                    {
+                        KeccakExtract(state, dataQueue, rate / 64);
+                        bitsAvailableForSqueezing = rate;
+                    }
+
+                    //displayIntermediateValues.displayBytes(1, "Block available for squeezing", dataQueue, bitsAvailableForSqueezing / 8);
+
+                }
+                partialBlock = bitsAvailableForSqueezing;
+                if ((long)partialBlock > outputLength - i)
+                {
+                    partialBlock = (int)(outputLength - i);
+                }
+
+                Array.Copy(dataQueue, (rate - bitsAvailableForSqueezing) / 8, output, offset + (int)(i / 8), partialBlock / 8);
+                bitsAvailableForSqueezing -= partialBlock;
+                i += partialBlock;
+            }
+        }
+
+        private static void FromBytesToWords(ulong[] stateAsWords, byte[] state)
+        {
+            for (int i = 0; i < (1600 / 64); i++)
+            {
+                stateAsWords[i] = 0;
+                int index = i * (64 / 8);
+                for (int j = 0; j < (64 / 8); j++)
+                {
+                    stateAsWords[i] |= ((ulong)state[index + j] & 0xff) << ((8 * j));
+                }
+            }
+        }
+
+        private static void FromWordsToBytes(byte[] state, ulong[] stateAsWords)
+        {
+            for (int i = 0; i < (1600 / 64); i++)
+            {
+                int index = i * (64 / 8);
+                for (int j = 0; j < (64 / 8); j++)
+                {
+                    state[index + j] = (byte)(stateAsWords[i] >> (8 * j));
+                }
+            }
+        }
+
+        private void KeccakPermutation(byte[] state)
+        {
+            ulong[] longState = new ulong[state.Length / 8];
+
+            FromBytesToWords(longState, state);
+
+            //displayIntermediateValues.displayStateAsBytes(1, "Input of permutation", longState);
+
+            KeccakPermutationOnWords(longState);
+
+            //displayIntermediateValues.displayStateAsBytes(1, "State after permutation", longState);
+
+            FromWordsToBytes(state, longState);
+        }
+
+        private void KeccakPermutationAfterXor(byte[] state, byte[] data, int dataLengthInBytes)
+        {
+            for (int i = 0; i < dataLengthInBytes; i++)
+            {
+                state[i] ^= data[i];
+            }
+
+            KeccakPermutation(state);
+        }
+
+        private void KeccakPermutationOnWords(ulong[] state)
+        {
+            int i;
+
+            //displayIntermediateValues.displayStateAs64bitWords(3, "Same, with lanes as 64-bit words", state);
+
+            for (i = 0; i < 24; i++)
+            {
+                //displayIntermediateValues.displayRoundNumber(3, i);
+
+                Theta(state);
+                //displayIntermediateValues.displayStateAs64bitWords(3, "After theta", state);
+
+                Rho(state);
+                //displayIntermediateValues.displayStateAs64bitWords(3, "After rho", state);
+
+                Pi(state);
+                //displayIntermediateValues.displayStateAs64bitWords(3, "After pi", state);
+
+                Chi(state);
+                //displayIntermediateValues.displayStateAs64bitWords(3, "After chi", state);
+
+                Iota(state, i);
+                //displayIntermediateValues.displayStateAs64bitWords(3, "After iota", state);
+            }
+        }
+
+        ulong[] C = new ulong[5];
+
+        private void Theta(ulong[] A)
+        {
+            for (int x = 0; x < 5; x++)
+            {
+                C[x] = 0;
+                for (int y = 0; y < 5; y++)
+                {
+                    C[x] ^= A[x + 5 * y];
+                }
+            }
+            for (int x = 0; x < 5; x++)
+            {
+                ulong dX = ((((C[(x + 1) % 5]) << 1) ^ ((C[(x + 1) % 5]) >> (64 - 1)))) ^ C[(x + 4) % 5];
+                for (int y = 0; y < 5; y++)
+                {
+                    A[x + 5 * y] ^= dX;
+                }
+            }
+        }
+
+        private void Rho(ulong[] A)
+        {
+            for (int x = 0; x < 5; x++)
+            {
+                for (int y = 0; y < 5; y++)
+                {
+                    int index = x + 5 * y;
+                    A[index] = ((KeccakRhoOffsets[index] != 0) ? (((A[index]) << KeccakRhoOffsets[index]) ^ ((A[index]) >> (64 - KeccakRhoOffsets[index]))) : A[index]);
+                }
+            }
+        }
+
+        ulong[] tempA = new ulong[25];
+
+        private void Pi(ulong[] A)
+        {
+            Array.Copy(A, 0, tempA, 0, tempA.Length);
+
+            for (int x = 0; x < 5; x++)
+            {
+                for (int y = 0; y < 5; y++)
+                {
+                    A[y + 5 * ((2 * x + 3 * y) % 5)] = tempA[x + 5 * y];
+                }
+            }
+        }
+
+        ulong[] chiC = new ulong[5];
+
+        private void Chi(ulong[] A)
+        {
+            for (int y = 0; y < 5; y++)
+            {
+                for (int x = 0; x < 5; x++)
+                {
+                    chiC[x] = A[x + 5 * y] ^ ((~A[(((x + 1) % 5) + 5 * y)]) & A[(((x + 2) % 5) + 5 * y)]);
+                }
+                for (int x = 0; x < 5; x++)
+                {
+                    A[x + 5 * y] = chiC[x];
+                }
+            }
+        }
+
+        private static void Iota(ulong[] A, int indexRound)
+        {
+            A[(((0) % 5) + 5 * ((0) % 5))] ^= KeccakRoundConstants[indexRound];
+        }
+
+        private void KeccakAbsorb(byte[] byteState, byte[] data, int dataInBytes)
+        {
+            KeccakPermutationAfterXor(byteState, data, dataInBytes);
+        }
+
+        private void KeccakExtract1024bits(byte[] byteState, byte[] data)
+        {
+            Array.Copy(byteState, 0, data, 0, 128);
+        }
+
+        private void KeccakExtract(byte[] byteState, byte[] data, int laneCount)
+        {
+            Array.Copy(byteState, 0, data, 0, laneCount * 8);
+        }
+
+		public IMemoable Copy()
+		{
+			return new Sha3Digest(this);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			Sha3Digest d = (Sha3Digest)other;
+
+			CopyIn(d);
+		}
+
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/SM3Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/SM3Digest.cs
new file mode 100644
index 0000000..d81b2dd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/SM3Digest.cs
@@ -0,0 +1,328 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+	/// <summary>
+	/// Implementation of Chinese SM3 digest as described at
+	/// http://tools.ietf.org/html/draft-shen-sm3-hash-00
+	/// and at .... ( Chinese PDF )
+	/// </summary>
+	/// <remarks>
+	/// The specification says "process a bit stream",
+	/// but this is written to process bytes in blocks of 4,
+	/// meaning this will process 32-bit word groups.
+	/// But so do also most other digest specifications,
+	/// including the SHA-256 which was a origin for
+	/// this specification.
+	/// </remarks>
+	public class SM3Digest
+		: GeneralDigest
+	{
+		private const int DIGEST_LENGTH = 32;   // bytes
+		private const int BLOCK_SIZE = 64 / 4; // of 32 bit ints (16 ints)
+
+		private uint[] V = new uint[DIGEST_LENGTH / 4]; // in 32 bit ints (8 ints)
+		private uint[] inwords = new uint[BLOCK_SIZE];
+		private int xOff;
+
+		// Work-bufs used within processBlock()
+		private uint[] W = new uint[68];
+		private uint[] W1 = new uint[64];
+
+		// Round constant T for processBlock() which is 32 bit integer rolled left up to (63 MOD 32) bit positions.
+		private static readonly uint[] T = new uint[64];
+
+		static SM3Digest()
+		{
+			for (int i = 0; i < 16; ++i)
+			{
+				uint t = 0x79CC4519;
+				T[i] = (t << i) | (t >> (32 - i));
+			}
+			for (int i = 16; i < 64; ++i)
+			{
+				int n = i % 32;
+				uint t = 0x7A879D8A;
+				T[i] = (t << n) | (t >> (32 - n));
+			}
+		}
+
+
+		/// <summary>
+		/// Standard constructor
+		/// </summary>
+		public SM3Digest()
+		{
+			Reset();
+		}
+
+		/// <summary>
+		/// Copy constructor.  This will copy the state of the provided
+		/// message digest.
+		/// </summary>
+		public SM3Digest(SM3Digest t)
+			: base(t)
+		{
+			CopyIn(t);
+		}
+
+		private void CopyIn(SM3Digest t)
+		{
+			Array.Copy(t.V, 0, this.V, 0, this.V.Length);
+			Array.Copy(t.inwords, 0, this.inwords, 0, this.inwords.Length);
+			xOff = t.xOff;
+		}
+
+		public override string AlgorithmName
+		{
+			get { return "SM3"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DIGEST_LENGTH;
+		}
+
+		public override IMemoable Copy()
+		{
+			return new SM3Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			SM3Digest d = (SM3Digest)other;
+
+			base.CopyIn(d);
+			CopyIn(d);
+		}
+
+		/// <summary>
+		/// reset the chaining variables
+		/// </summary>
+		public override void Reset()
+		{
+			base.Reset();
+
+			this.V[0] = 0x7380166F;
+			this.V[1] = 0x4914B2B9;
+			this.V[2] = 0x172442D7;
+			this.V[3] = 0xDA8A0600;
+			this.V[4] = 0xA96F30BC;
+			this.V[5] = 0x163138AA;
+			this.V[6] = 0xE38DEE4D;
+			this.V[7] = 0xB0FB0E4E;
+
+			this.xOff = 0;
+		}
+
+
+		public override int DoFinal(byte[] output, int outOff)
+		{
+			Finish();
+
+			Pack.UInt32_To_BE(this.V[0], output, outOff + 0);
+			Pack.UInt32_To_BE(this.V[1], output, outOff + 4);
+			Pack.UInt32_To_BE(this.V[2], output, outOff + 8);
+			Pack.UInt32_To_BE(this.V[3], output, outOff + 12);
+			Pack.UInt32_To_BE(this.V[4], output, outOff + 16);
+			Pack.UInt32_To_BE(this.V[5], output, outOff + 20);
+			Pack.UInt32_To_BE(this.V[6], output, outOff + 24);
+			Pack.UInt32_To_BE(this.V[7], output, outOff + 28);
+
+			Reset();
+
+			return DIGEST_LENGTH;
+		}
+
+
+		internal override void ProcessWord(byte[] input,
+		                                   int inOff)
+		{
+			uint n = Pack.BE_To_UInt32(input, inOff);
+			this.inwords[this.xOff] = n;
+			++this.xOff;
+
+			if (this.xOff >= 16)
+			{
+				ProcessBlock();
+			}
+		}
+
+		internal override void ProcessLength(long bitLength)
+		{
+			if (this.xOff > (BLOCK_SIZE - 2))
+			{
+				// xOff == 15  --> can't fit the 64 bit length field at tail..
+				this.inwords[this.xOff] = 0; // fill with zero
+				++this.xOff;
+
+				ProcessBlock();
+			}
+			// Fill with zero words, until reach 2nd to last slot
+			while (this.xOff < (BLOCK_SIZE - 2))
+			{
+				this.inwords[this.xOff] = 0;
+				++this.xOff;
+			}
+
+			// Store input data length in BITS
+			this.inwords[this.xOff++] = (uint)(bitLength >> 32);
+			this.inwords[this.xOff++] = (uint)(bitLength);
+		}
+
+		/*
+
+	3.4.2.  Constants
+
+
+	   Tj = 79cc4519        when 0  < = j < = 15
+	   Tj = 7a879d8a        when 16 < = j < = 63
+
+	3.4.3.  Boolean function
+
+
+	   FFj(X;Y;Z) = X XOR Y XOR Z                       when 0  < = j < = 15
+	              = (X AND Y) OR (X AND Z) OR (Y AND Z) when 16 < = j < = 63
+
+	   GGj(X;Y;Z) = X XOR Y XOR Z                       when 0  < = j < = 15
+	              = (X AND Y) OR (NOT X AND Z)          when 16 < = j < = 63
+
+	   The X, Y, Z in the fomular are words!GBP
+
+	3.4.4.  Permutation function
+
+
+	   P0(X) = X XOR (X <<<  9) XOR (X <<< 17)   ## ROLL, not SHIFT
+	   P1(X) = X XOR (X <<< 15) XOR (X <<< 23)   ## ROLL, not SHIFT
+
+	   The X in the fomular are a word.
+
+	----------
+
+	Each ROLL converted to Java expression:
+
+	ROLL 9  :  ((x <<  9) | (x >> (32-9))))
+	ROLL 17 :  ((x << 17) | (x >> (32-17)))
+	ROLL 15 :  ((x << 15) | (x >> (32-15)))
+	ROLL 23 :  ((x << 23) | (x >> (32-23)))
+
+	 */
+
+		private uint P0(uint x)
+		{
+			uint r9 = ((x << 9) | (x >> (32 - 9)));
+			uint r17 = ((x << 17) | (x >> (32 - 17)));
+			return (x ^ r9 ^ r17);
+		}
+
+		private uint P1(uint x)
+		{
+			uint r15 = ((x << 15) | (x >> (32 - 15)));
+			uint r23 = ((x << 23) | (x >> (32 - 23)));
+			return (x ^ r15 ^ r23);
+		}
+
+		private uint FF0(uint x, uint y, uint z)
+		{
+			return (x ^ y ^ z);
+		}
+
+		private uint FF1(uint x, uint y, uint z)
+		{
+			return ((x & y) | (x & z) | (y & z));
+		}
+
+		private uint GG0(uint x, uint y, uint z)
+		{
+			return (x ^ y ^ z);
+		}
+
+		private uint GG1(uint x, uint y, uint z)
+		{
+			return ((x & y) | ((~x) & z));
+		}
+
+
+		internal override void ProcessBlock()
+		{
+			for (int j = 0; j < 16; ++j)
+			{
+				this.W[j] = this.inwords[j];
+			}
+			for (int j = 16; j < 68; ++j)
+			{
+				uint wj3 = this.W[j - 3];
+				uint r15 = ((wj3 << 15) | (wj3 >> (32 - 15)));
+				uint wj13 = this.W[j - 13];
+				uint r7 = ((wj13 << 7) | (wj13 >> (32 - 7)));
+				this.W[j] = P1(this.W[j - 16] ^ this.W[j - 9] ^ r15) ^ r7 ^ this.W[j - 6];
+			}
+			for (int j = 0; j < 64; ++j)
+			{
+				this.W1[j] = this.W[j] ^ this.W[j + 4];
+			}
+
+			uint A = this.V[0];
+			uint B = this.V[1];
+			uint C = this.V[2];
+			uint D = this.V[3];
+			uint E = this.V[4];
+			uint F = this.V[5];
+			uint G = this.V[6];
+			uint H = this.V[7];
+
+
+			for (int j = 0; j < 16; ++j)
+			{
+				uint a12 = ((A << 12) | (A >> (32 - 12)));
+				uint s1_ = a12 + E + T[j];
+				uint SS1 = ((s1_ << 7) | (s1_ >> (32 - 7)));
+				uint SS2 = SS1 ^ a12;
+				uint TT1 = FF0(A, B, C) + D + SS2 + this.W1[j];
+				uint TT2 = GG0(E, F, G) + H + SS1 + this.W[j];
+				D = C;
+				C = ((B << 9) | (B >> (32 - 9)));
+				B = A;
+				A = TT1;
+				H = G;
+				G = ((F << 19) | (F >> (32 - 19)));
+				F = E;
+				E = P0(TT2);
+			}
+
+			// Different FF,GG functions on rounds 16..63
+			for (int j = 16; j < 64; ++j)
+			{
+				uint a12 = ((A << 12) | (A >> (32 - 12)));
+				uint s1_ = a12 + E + T[j];
+				uint SS1 = ((s1_ << 7) | (s1_ >> (32 - 7)));
+				uint SS2 = SS1 ^ a12;
+				uint TT1 = FF1(A, B, C) + D + SS2 + this.W1[j];
+				uint TT2 = GG1(E, F, G) + H + SS1 + this.W[j];
+				D = C;
+				C = ((B << 9) | (B >> (32 - 9)));
+				B = A;
+				A = TT1;
+				H = G;
+				G = ((F << 19) | (F >> (32 - 19)));
+				F = E;
+				E = P0(TT2);
+			}
+
+			this.V[0] ^= A;
+			this.V[1] ^= B;
+			this.V[2] ^= C;
+			this.V[3] ^= D;
+			this.V[4] ^= E;
+			this.V[5] ^= F;
+			this.V[6] ^= G;
+			this.V[7] ^= H;
+
+			this.xOff = 0;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha1Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha1Digest.cs
new file mode 100644
index 0000000..60ec651
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha1Digest.cs
@@ -0,0 +1,284 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+    /**
+     * implementation of SHA-1 as outlined in "Handbook of Applied Cryptography", pages 346 - 349.
+     *
+     * It is interesting to ponder why the, apart from the extra IV, the other difference here from MD5
+     * is the "endianness" of the word processing!
+     */
+    public class Sha1Digest
+        : GeneralDigest
+    {
+        private const int DigestLength = 20;
+
+        private uint H1, H2, H3, H4, H5;
+
+        private uint[] X = new uint[80];
+        private int xOff;
+
+        public Sha1Digest()
+        {
+            Reset();
+        }
+
+        /**
+         * Copy constructor.  This will copy the state of the provided
+         * message digest.
+         */
+        public Sha1Digest(Sha1Digest t)
+            : base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(Sha1Digest t)
+		{
+			base.CopyIn(t);
+
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "SHA-1"; }
+        }
+
+        public override int GetDigestSize()
+        {
+            return DigestLength;
+        }
+
+        internal override void ProcessWord(
+            byte[]  input,
+            int     inOff)
+        {
+            X[xOff] = Pack.BE_To_UInt32(input, inOff);
+
+            if (++xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+        internal override void ProcessLength(long    bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (uint)((ulong)bitLength >> 32);
+            X[15] = (uint)((ulong)bitLength);
+        }
+
+        public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            Pack.UInt32_To_BE(H1, output, outOff);
+            Pack.UInt32_To_BE(H2, output, outOff + 4);
+            Pack.UInt32_To_BE(H3, output, outOff + 8);
+            Pack.UInt32_To_BE(H4, output, outOff + 12);
+            Pack.UInt32_To_BE(H5, output, outOff + 16);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+         * reset the chaining variables
+         */
+        public override void Reset()
+        {
+            base.Reset();
+
+            H1 = 0x67452301;
+            H2 = 0xefcdab89;
+            H3 = 0x98badcfe;
+            H4 = 0x10325476;
+            H5 = 0xc3d2e1f0;
+
+            xOff = 0;
+            Array.Clear(X, 0, X.Length);
+        }
+
+        //
+        // Additive constants
+        //
+        private const uint Y1 = 0x5a827999;
+        private const uint Y2 = 0x6ed9eba1;
+        private const uint Y3 = 0x8f1bbcdc;
+        private const uint Y4 = 0xca62c1d6;
+
+        private static uint F(uint u, uint v, uint w)
+        {
+            return (u & v) | (~u & w);
+        }
+
+        private static uint H(uint u, uint v, uint w)
+        {
+            return u ^ v ^ w;
+        }
+
+        private static uint G(uint u, uint v, uint w)
+        {
+            return (u & v) | (u & w) | (v & w);
+        }
+
+        internal override void ProcessBlock()
+        {
+            //
+            // expand 16 word block into 80 word block.
+            //
+            for (int i = 16; i < 80; i++)
+            {
+                uint t = X[i - 3] ^ X[i - 8] ^ X[i - 14] ^ X[i - 16];
+                X[i] = t << 1 | t >> 31;
+            }
+
+            //
+            // set up working variables.
+            //
+            uint A = H1;
+            uint B = H2;
+            uint C = H3;
+            uint D = H4;
+            uint E = H5;
+
+            //
+            // round 1
+            //
+            int idx = 0;
+
+            for (int j = 0; j < 4; j++)
+            {
+                // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+                // B = rotateLeft(B, 30)
+                E += (A << 5 | (A >> 27)) + F(B, C, D) + X[idx++] + Y1;
+                B = B << 30 | (B >> 2);
+
+                D += (E << 5 | (E >> 27)) + F(A, B, C) + X[idx++] + Y1;
+                A = A << 30 | (A >> 2);
+
+                C += (D << 5 | (D >> 27)) + F(E, A, B) + X[idx++] + Y1;
+                E = E << 30 | (E >> 2);
+
+                B += (C << 5 | (C >> 27)) + F(D, E, A) + X[idx++] + Y1;
+                D = D << 30 | (D >> 2);
+
+                A += (B << 5 | (B >> 27)) + F(C, D, E) + X[idx++] + Y1;
+                C = C << 30 | (C >> 2);
+            }
+
+            //
+            // round 2
+            //
+            for (int j = 0; j < 4; j++)
+            {
+                // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+                // B = rotateLeft(B, 30)
+                E += (A << 5 | (A >> 27)) + H(B, C, D) + X[idx++] + Y2;
+                B = B << 30 | (B >> 2);
+
+                D += (E << 5 | (E >> 27)) + H(A, B, C) + X[idx++] + Y2;
+                A = A << 30 | (A >> 2);
+
+                C += (D << 5 | (D >> 27)) + H(E, A, B) + X[idx++] + Y2;
+                E = E << 30 | (E >> 2);
+
+                B += (C << 5 | (C >> 27)) + H(D, E, A) + X[idx++] + Y2;
+                D = D << 30 | (D >> 2);
+
+                A += (B << 5 | (B >> 27)) + H(C, D, E) + X[idx++] + Y2;
+                C = C << 30 | (C >> 2);
+            }
+
+            //
+            // round 3
+            //
+            for (int j = 0; j < 4; j++)
+            {
+                // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+                // B = rotateLeft(B, 30)
+                E += (A << 5 | (A >> 27)) + G(B, C, D) + X[idx++] + Y3;
+                B = B << 30 | (B >> 2);
+
+                D += (E << 5 | (E >> 27)) + G(A, B, C) + X[idx++] + Y3;
+                A = A << 30 | (A >> 2);
+
+                C += (D << 5 | (D >> 27)) + G(E, A, B) + X[idx++] + Y3;
+                E = E << 30 | (E >> 2);
+
+                B += (C << 5 | (C >> 27)) + G(D, E, A) + X[idx++] + Y3;
+                D = D << 30 | (D >> 2);
+
+                A += (B << 5 | (B >> 27)) + G(C, D, E) + X[idx++] + Y3;
+                C = C << 30 | (C >> 2);
+            }
+
+            //
+            // round 4
+            //
+            for (int j = 0; j < 4; j++)
+            {
+                // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+                // B = rotateLeft(B, 30)
+                E += (A << 5 | (A >> 27)) + H(B, C, D) + X[idx++] + Y4;
+                B = B << 30 | (B >> 2);
+
+                D += (E << 5 | (E >> 27)) + H(A, B, C) + X[idx++] + Y4;
+                A = A << 30 | (A >> 2);
+
+                C += (D << 5 | (D >> 27)) + H(E, A, B) + X[idx++] + Y4;
+                E = E << 30 | (E >> 2);
+
+                B += (C << 5 | (C >> 27)) + H(D, E, A) + X[idx++] + Y4;
+                D = D << 30 | (D >> 2);
+
+                A += (B << 5 | (B >> 27)) + H(C, D, E) + X[idx++] + Y4;
+                C = C << 30 | (C >> 2);
+            }
+
+            H1 += A;
+            H2 += B;
+            H3 += C;
+            H4 += D;
+            H5 += E;
+
+            //
+            // reset start of the buffer.
+            //
+            xOff = 0;
+            Array.Clear(X, 0, 16);
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new Sha1Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha1Digest d = (Sha1Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha224Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha224Digest.cs
new file mode 100644
index 0000000..b4e8537
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha224Digest.cs
@@ -0,0 +1,289 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+     * SHA-224 as described in RFC 3874
+     * <pre>
+     *         block  word  digest
+     * SHA-1   512    32    160
+     * SHA-224 512    32    224
+     * SHA-256 512    32    256
+     * SHA-384 1024   64    384
+     * SHA-512 1024   64    512
+     * </pre>
+     */
+    public class Sha224Digest
+        : GeneralDigest
+    {
+        private const int DigestLength = 28;
+
+		private uint H1, H2, H3, H4, H5, H6, H7, H8;
+
+		private uint[] X = new uint[64];
+        private int     xOff;
+
+		/**
+         * Standard constructor
+         */
+        public Sha224Digest()
+        {
+            Reset();
+        }
+
+		/**
+         * Copy constructor.  This will copy the state of the provided
+         * message digest.
+         */
+         public Sha224Digest(
+			 Sha224Digest t)
+			 : base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(Sha224Digest t)
+		{
+			base.CopyIn(t);
+
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+            H6 = t.H6;
+            H7 = t.H7;
+            H8 = t.H8;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+		public override string AlgorithmName
+		{
+			get { return "SHA-224"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		internal override void ProcessWord(
+            byte[]  input,
+            int     inOff)
+        {
+			X[xOff] = Pack.BE_To_UInt32(input, inOff);
+
+			if (++xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+		internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (uint)((ulong)bitLength >> 32);
+            X[15] = (uint)((ulong)bitLength);
+        }
+
+        public override int DoFinal(
+            byte[]	output,
+            int		outOff)
+        {
+            Finish();
+
+			Pack.UInt32_To_BE(H1, output, outOff);
+            Pack.UInt32_To_BE(H2, output, outOff + 4);
+            Pack.UInt32_To_BE(H3, output, outOff + 8);
+            Pack.UInt32_To_BE(H4, output, outOff + 12);
+            Pack.UInt32_To_BE(H5, output, outOff + 16);
+            Pack.UInt32_To_BE(H6, output, outOff + 20);
+            Pack.UInt32_To_BE(H7, output, outOff + 24);
+
+			Reset();
+
+			return DigestLength;
+        }
+
+		/**
+         * reset the chaining variables
+         */
+        public override void Reset()
+        {
+            base.Reset();
+
+            /* SHA-224 initial hash value
+             */
+            H1 = 0xc1059ed8;
+            H2 = 0x367cd507;
+            H3 = 0x3070dd17;
+            H4 = 0xf70e5939;
+            H5 = 0xffc00b31;
+            H6 = 0x68581511;
+            H7 = 0x64f98fa7;
+            H8 = 0xbefa4fa4;
+
+			xOff = 0;
+			Array.Clear(X, 0, X.Length);
+        }
+
+        internal override void ProcessBlock()
+        {
+            //
+            // expand 16 word block into 64 word blocks.
+            //
+            for (int ti = 16; ti <= 63; ti++)
+            {
+                X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
+            }
+
+			//
+            // set up working variables.
+            //
+            uint a = H1;
+            uint b = H2;
+            uint c = H3;
+            uint d = H4;
+            uint e = H5;
+            uint f = H6;
+            uint g = H7;
+            uint h = H8;
+
+			int t = 0;
+			for(int i = 0; i < 8; i ++)
+			{
+				// t = 8 * i
+				h += Sum1(e) + Ch(e, f, g) + K[t] + X[t];
+				d += h;
+				h += Sum0(a) + Maj(a, b, c);
+				++t;
+
+				// t = 8 * i + 1
+				g += Sum1(d) + Ch(d, e, f) + K[t] + X[t];
+				c += g;
+				g += Sum0(h) + Maj(h, a, b);
+				++t;
+
+				// t = 8 * i + 2
+				f += Sum1(c) + Ch(c, d, e) + K[t] + X[t];
+				b += f;
+				f += Sum0(g) + Maj(g, h, a);
+				++t;
+
+				// t = 8 * i + 3
+				e += Sum1(b) + Ch(b, c, d) + K[t] + X[t];
+				a += e;
+				e += Sum0(f) + Maj(f, g, h);
+				++t;
+
+				// t = 8 * i + 4
+				d += Sum1(a) + Ch(a, b, c) + K[t] + X[t];
+				h += d;
+				d += Sum0(e) + Maj(e, f, g);
+				++t;
+
+				// t = 8 * i + 5
+				c += Sum1(h) + Ch(h, a, b) + K[t] + X[t];
+				g += c;
+				c += Sum0(d) + Maj(d, e, f);
+				++t;
+
+				// t = 8 * i + 6
+				b += Sum1(g) + Ch(g, h, a) + K[t] + X[t];
+				f += b;
+				b += Sum0(c) + Maj(c, d, e);
+				++t;
+
+				// t = 8 * i + 7
+				a += Sum1(f) + Ch(f, g, h) + K[t] + X[t];
+				e += a;
+				a += Sum0(b) + Maj(b, c, d);
+				++t;
+			}
+
+			H1 += a;
+            H2 += b;
+            H3 += c;
+            H4 += d;
+            H5 += e;
+            H6 += f;
+            H7 += g;
+            H8 += h;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+			Array.Clear(X, 0, 16);
+		}
+
+		/* SHA-224 functions */
+        private static uint Ch(uint x, uint y, uint z)
+        {
+            return (x & y) ^ (~x & z);
+        }
+
+        private static uint Maj(uint x, uint y, uint z)
+        {
+            return (x & y) ^ (x & z) ^ (y & z);
+        }
+
+        private static uint Sum0(uint x)
+        {
+	        return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10));
+        }
+
+        private static uint Sum1(uint x)
+        {
+			return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7));
+        }
+
+		private static uint Theta0(uint x)
+        {
+	        return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
+        }
+
+        private static uint Theta1(uint x)
+        {
+	        return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
+        }
+
+		/* SHA-224 Constants
+         * (represent the first 32 bits of the fractional parts of the
+         * cube roots of the first sixty-four prime numbers)
+         */
+        internal static readonly uint[] K = {
+            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+			0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+        };
+		
+		public override IMemoable Copy()
+		{
+			return new Sha224Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha224Digest d = (Sha224Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha256Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha256Digest.cs
new file mode 100644
index 0000000..98e10a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha256Digest.cs
@@ -0,0 +1,330 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * Draft FIPS 180-2 implementation of SHA-256. <b>Note:</b> As this is
+    * based on a draft this implementation is subject to change.
+    *
+    * <pre>
+    *         block  word  digest
+    * SHA-1   512    32    160
+    * SHA-256 512    32    256
+    * SHA-384 1024   64    384
+    * SHA-512 1024   64    512
+    * </pre>
+    */
+    public class Sha256Digest
+		: GeneralDigest
+    {
+        private const int DigestLength = 32;
+
+        private uint H1, H2, H3, H4, H5, H6, H7, H8;
+        private uint[] X = new uint[64];
+        private int xOff;
+
+        public Sha256Digest()
+        {
+			initHs();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public Sha256Digest(Sha256Digest t) : base(t)
+        {
+			CopyIn(t);
+		}
+
+		private void CopyIn(Sha256Digest t)
+		{
+			base.CopyIn(t);
+
+            H1 = t.H1;
+            H2 = t.H2;
+            H3 = t.H3;
+            H4 = t.H4;
+            H5 = t.H5;
+            H6 = t.H6;
+            H7 = t.H7;
+            H8 = t.H8;
+
+            Array.Copy(t.X, 0, X, 0, t.X.Length);
+            xOff = t.xOff;
+        }
+
+        public override string AlgorithmName
+		{
+			get { return "SHA-256"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		internal override void ProcessWord(
+            byte[]  input,
+            int     inOff)
+		{
+			X[xOff] = Pack.BE_To_UInt32(input, inOff);
+
+			if (++xOff == 16)
+            {
+                ProcessBlock();
+            }
+        }
+
+		internal override void ProcessLength(
+            long bitLength)
+        {
+            if (xOff > 14)
+            {
+                ProcessBlock();
+            }
+
+            X[14] = (uint)((ulong)bitLength >> 32);
+            X[15] = (uint)((ulong)bitLength);
+        }
+
+        public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            Pack.UInt32_To_BE((uint)H1, output, outOff);
+            Pack.UInt32_To_BE((uint)H2, output, outOff + 4);
+            Pack.UInt32_To_BE((uint)H3, output, outOff + 8);
+            Pack.UInt32_To_BE((uint)H4, output, outOff + 12);
+            Pack.UInt32_To_BE((uint)H5, output, outOff + 16);
+            Pack.UInt32_To_BE((uint)H6, output, outOff + 20);
+            Pack.UInt32_To_BE((uint)H7, output, outOff + 24);
+            Pack.UInt32_To_BE((uint)H8, output, outOff + 28);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+			initHs();
+
+            xOff = 0;
+			Array.Clear(X, 0, X.Length);
+        }
+
+		private void initHs()
+		{
+            /* SHA-256 initial hash value
+            * The first 32 bits of the fractional parts of the square roots
+            * of the first eight prime numbers
+            */
+            H1 = 0x6a09e667;
+            H2 = 0xbb67ae85;
+            H3 = 0x3c6ef372;
+            H4 = 0xa54ff53a;
+            H5 = 0x510e527f;
+            H6 = 0x9b05688c;
+            H7 = 0x1f83d9ab;
+            H8 = 0x5be0cd19;
+		}
+
+        internal override void ProcessBlock()
+        {
+            //
+            // expand 16 word block into 64 word blocks.
+            //
+            for (int ti = 16; ti <= 63; ti++)
+            {
+                X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
+            }
+
+            //
+            // set up working variables.
+            //
+            uint a = H1;
+            uint b = H2;
+            uint c = H3;
+            uint d = H4;
+            uint e = H5;
+            uint f = H6;
+            uint g = H7;
+            uint h = H8;
+
+			int t = 0;
+			for(int i = 0; i < 8; ++i)
+			{
+				// t = 8 * i
+				h += Sum1Ch(e, f, g) + K[t] + X[t];
+				d += h;
+				h += Sum0Maj(a, b, c);
+				++t;
+
+				// t = 8 * i + 1
+				g += Sum1Ch(d, e, f) + K[t] + X[t];
+				c += g;
+				g += Sum0Maj(h, a, b);
+				++t;
+
+				// t = 8 * i + 2
+				f += Sum1Ch(c, d, e) + K[t] + X[t];
+				b += f;
+				f += Sum0Maj(g, h, a);
+				++t;
+
+				// t = 8 * i + 3
+				e += Sum1Ch(b, c, d) + K[t] + X[t];
+				a += e;
+				e += Sum0Maj(f, g, h);
+				++t;
+
+				// t = 8 * i + 4
+				d += Sum1Ch(a, b, c) + K[t] + X[t];
+				h += d;
+				d += Sum0Maj(e, f, g);
+				++t;
+
+				// t = 8 * i + 5
+				c += Sum1Ch(h, a, b) + K[t] + X[t];
+				g += c;
+				c += Sum0Maj(d, e, f);
+				++t;
+
+				// t = 8 * i + 6
+				b += Sum1Ch(g, h, a) + K[t] + X[t];
+				f += b;
+				b += Sum0Maj(c, d, e);
+				++t;
+
+				// t = 8 * i + 7
+				a += Sum1Ch(f, g, h) + K[t] + X[t];
+				e += a;
+				a += Sum0Maj(b, c, d);
+				++t;
+			}
+
+			H1 += a;
+            H2 += b;
+            H3 += c;
+            H4 += d;
+            H5 += e;
+            H6 += f;
+            H7 += g;
+            H8 += h;
+
+            //
+            // reset the offset and clean out the word buffer.
+            //
+            xOff = 0;
+			Array.Clear(X, 0, 16);
+        }
+
+		private static uint Sum1Ch(
+            uint    x,
+            uint    y,
+            uint    z)
+		{
+//			return Sum1(x) + Ch(x, y, z);
+	        return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
+				+ ((x & y) ^ ((~x) & z));
+		}
+
+		private static uint Sum0Maj(
+            uint	x,
+            uint    y,
+            uint    z)
+		{
+//			return Sum0(x) + Maj(x, y, z);
+	        return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
+				+ ((x & y) ^ (x & z) ^ (y & z));
+		}
+
+//		/* SHA-256 functions */
+//        private static uint Ch(
+//            uint    x,
+//            uint    y,
+//            uint    z)
+//        {
+//            return ((x & y) ^ ((~x) & z));
+//        }
+//
+//        private static uint Maj(
+//            uint	x,
+//            uint    y,
+//            uint    z)
+//        {
+//            return ((x & y) ^ (x & z) ^ (y & z));
+//        }
+//
+//        private static uint Sum0(
+//            uint x)
+//        {
+//	        return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10));
+//        }
+//
+//        private static uint Sum1(
+//            uint x)
+//        {
+//	        return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7));
+//        }
+
+        private static uint Theta0(
+            uint x)
+        {
+	        return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
+        }
+
+        private static uint Theta1(
+            uint x)
+        {
+	        return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
+        }
+
+        /* SHA-256 Constants
+        * (represent the first 32 bits of the fractional parts of the
+        * cube roots of the first sixty-four prime numbers)
+        */
+        private static readonly uint[] K = {
+            0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+			0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+            0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+            0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+            0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+            0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+            0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+            0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+            0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+            0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+            0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+            0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+            0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+            0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+            0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+            0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+        };
+		
+		public override IMemoable Copy()
+		{
+			return new Sha256Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha256Digest d = (Sha256Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha384Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha384Digest.cs
new file mode 100644
index 0000000..e6c9a9a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha384Digest.cs
@@ -0,0 +1,101 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+     * Draft FIPS 180-2 implementation of SHA-384. <b>Note:</b> As this is
+     * based on a draft this implementation is subject to change.
+     *
+     * <pre>
+     *         block  word  digest
+     * SHA-1   512    32    160
+     * SHA-256 512    32    256
+     * SHA-384 1024   64    384
+     * SHA-512 1024   64    512
+     * </pre>
+     */
+    public class Sha384Digest
+		: LongDigest
+    {
+        private const int DigestLength = 48;
+
+		public Sha384Digest()
+        {
+        }
+
+        /**
+         * Copy constructor.  This will copy the state of the provided
+         * message digest.
+         */
+        public Sha384Digest(
+			Sha384Digest t)
+			: base(t)
+		{
+		}
+
+		public override string AlgorithmName
+		{
+			get { return "SHA-384"; }
+		}
+
+		public override int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            Pack.UInt64_To_BE(H1, output, outOff);
+            Pack.UInt64_To_BE(H2, output, outOff + 8);
+            Pack.UInt64_To_BE(H3, output, outOff + 16);
+            Pack.UInt64_To_BE(H4, output, outOff + 24);
+            Pack.UInt64_To_BE(H5, output, outOff + 32);
+            Pack.UInt64_To_BE(H6, output, outOff + 40);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            /* SHA-384 initial hash value
+                * The first 64 bits of the fractional parts of the square roots
+                * of the 9th through 16th prime numbers
+                */
+            H1 = 0xcbbb9d5dc1059ed8;
+            H2 = 0x629a292a367cd507;
+            H3 = 0x9159015a3070dd17;
+            H4 = 0x152fecd8f70e5939;
+            H5 = 0x67332667ffc00b31;
+            H6 = 0x8eb44a8768581511;
+            H7 = 0xdb0c2e0d64f98fa7;
+            H8 = 0x47b5481dbefa4fa4;
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new Sha384Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha384Digest d = (Sha384Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha512Digest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha512Digest.cs
new file mode 100644
index 0000000..2a0964f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha512Digest.cs
@@ -0,0 +1,104 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+     * Draft FIPS 180-2 implementation of SHA-512. <b>Note:</b> As this is
+     * based on a draft this implementation is subject to change.
+     *
+     * <pre>
+     *         block  word  digest
+     * SHA-1   512    32    160
+     * SHA-256 512    32    256
+     * SHA-384 1024   64    384
+     * SHA-512 1024   64    512
+     * </pre>
+     */
+    public class Sha512Digest
+        : LongDigest
+    {
+        private const int DigestLength = 64;
+
+        public Sha512Digest()
+        {
+        }
+
+        /**
+         * Copy constructor.  This will copy the state of the provided
+         * message digest.
+         */
+        public Sha512Digest(
+            Sha512Digest t)
+            : base(t)
+        {
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "SHA-512"; }
+        }
+
+        public override int GetDigestSize()
+        {
+            return DigestLength;
+        }
+
+        public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            Pack.UInt64_To_BE(H1, output, outOff);
+            Pack.UInt64_To_BE(H2, output, outOff + 8);
+            Pack.UInt64_To_BE(H3, output, outOff + 16);
+            Pack.UInt64_To_BE(H4, output, outOff + 24);
+            Pack.UInt64_To_BE(H5, output, outOff + 32);
+            Pack.UInt64_To_BE(H6, output, outOff + 40);
+            Pack.UInt64_To_BE(H7, output, outOff + 48);
+            Pack.UInt64_To_BE(H8, output, outOff + 56);
+
+            Reset();
+
+            return DigestLength;
+
+        }
+
+        /**
+        * reset the chaining variables
+        */
+        public override void Reset()
+        {
+            base.Reset();
+
+            /* SHA-512 initial hash value
+             * The first 64 bits of the fractional parts of the square roots
+             * of the first eight prime numbers
+             */
+            H1 = 0x6a09e667f3bcc908;
+            H2 = 0xbb67ae8584caa73b;
+            H3 = 0x3c6ef372fe94f82b;
+            H4 = 0xa54ff53a5f1d36f1;
+            H5 = 0x510e527fade682d1;
+            H6 = 0x9b05688c2b3e6c1f;
+            H7 = 0x1f83d9abfb41bd6b;
+            H8 = 0x5be0cd19137e2179;
+        }
+		
+		public override IMemoable Copy()
+		{
+			return new Sha512Digest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha512Digest d = (Sha512Digest)other;
+
+			CopyIn(d);
+		}
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/Sha512tDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/Sha512tDigest.cs
new file mode 100644
index 0000000..2caefa7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/Sha512tDigest.cs
@@ -0,0 +1,200 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+     * FIPS 180-4 implementation of SHA-512/t
+     */
+    public class Sha512tDigest
+        : LongDigest
+    {
+        private const ulong A5 = 0xa5a5a5a5a5a5a5a5UL;
+
+        private readonly int digestLength;
+
+        private ulong H1t, H2t, H3t, H4t, H5t, H6t, H7t, H8t;
+
+        /**
+         * Standard constructor
+         */
+        public Sha512tDigest(int bitLength)
+        {
+            if (bitLength >= 512)
+                throw new ArgumentException("cannot be >= 512", "bitLength");
+            if (bitLength % 8 != 0)
+                throw new ArgumentException("needs to be a multiple of 8", "bitLength");
+            if (bitLength == 384)
+                throw new ArgumentException("cannot be 384 use SHA384 instead", "bitLength");
+
+            this.digestLength = bitLength / 8;
+
+            tIvGenerate(digestLength * 8);
+
+            Reset();
+        }
+
+        /**
+         * Copy constructor.  This will copy the state of the provided
+         * message digest.
+         */
+        public Sha512tDigest(Sha512tDigest t)
+            : base(t)
+        {
+            this.digestLength = t.digestLength;
+
+			Reset(t);
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "SHA-512/" + (digestLength * 8); }
+        }
+
+        public override int GetDigestSize()
+        {
+            return digestLength;
+        }
+
+        public override int DoFinal(byte[] output, int outOff)
+        {
+            Finish();
+
+            UInt64_To_BE(H1, output, outOff, digestLength);
+            UInt64_To_BE(H2, output, outOff + 8, digestLength - 8);
+            UInt64_To_BE(H3, output, outOff + 16, digestLength - 16);
+            UInt64_To_BE(H4, output, outOff + 24, digestLength - 24);
+            UInt64_To_BE(H5, output, outOff + 32, digestLength - 32);
+            UInt64_To_BE(H6, output, outOff + 40, digestLength - 40);
+            UInt64_To_BE(H7, output, outOff + 48, digestLength - 48);
+            UInt64_To_BE(H8, output, outOff + 56, digestLength - 56);
+
+            Reset();
+
+            return digestLength;
+        }
+
+        /**
+         * reset the chaining variables
+         */
+        public override void Reset()
+        {
+            base.Reset();
+
+            /*
+             * initial hash values use the iv generation algorithm for t.
+             */
+            H1 = H1t;
+            H2 = H2t;
+            H3 = H3t;
+            H4 = H4t;
+            H5 = H5t;
+            H6 = H6t;
+            H7 = H7t;
+            H8 = H8t;
+        }
+
+        private void tIvGenerate(int bitLength)
+        {
+            H1 = 0x6a09e667f3bcc908UL ^ A5;
+            H2 = 0xbb67ae8584caa73bUL ^ A5;
+            H3 = 0x3c6ef372fe94f82bUL ^ A5;
+            H4 = 0xa54ff53a5f1d36f1UL ^ A5;
+            H5 = 0x510e527fade682d1UL ^ A5;
+            H6 = 0x9b05688c2b3e6c1fUL ^ A5;
+            H7 = 0x1f83d9abfb41bd6bUL ^ A5;
+            H8 = 0x5be0cd19137e2179UL ^ A5;
+
+            Update(0x53);
+            Update(0x48);
+            Update(0x41);
+            Update(0x2D);
+            Update(0x35);
+            Update(0x31);
+            Update(0x32);
+            Update(0x2F);
+
+            if (bitLength > 100)
+            {
+                Update((byte)(bitLength / 100 + 0x30));
+                bitLength = bitLength % 100;
+                Update((byte)(bitLength / 10 + 0x30));
+                bitLength = bitLength % 10;
+                Update((byte)(bitLength + 0x30));
+            }
+            else if (bitLength > 10)
+            {
+                Update((byte)(bitLength / 10 + 0x30));
+                bitLength = bitLength % 10;
+                Update((byte)(bitLength + 0x30));
+            }
+            else
+            {
+                Update((byte)(bitLength + 0x30));
+            }
+
+            Finish();
+
+            H1t = H1;
+            H2t = H2;
+            H3t = H3;
+            H4t = H4;
+            H5t = H5;
+            H6t = H6;
+            H7t = H7;
+            H8t = H8;
+        }
+
+        private static void UInt64_To_BE(ulong n, byte[] bs, int off, int max)
+        {
+            if (max > 0)
+            {
+                UInt32_To_BE((uint)(n >> 32), bs, off, max);
+
+                if (max > 4)
+                {
+                    UInt32_To_BE((uint)n, bs, off + 4, max - 4);
+                }
+            }
+        }
+
+        private static void UInt32_To_BE(uint n, byte[] bs, int off, int max)
+        {
+            int num = System.Math.Min(4, max);
+            while (--num >= 0)
+            {
+                int shift = 8 * (3 - num);
+                bs[off + num] = (byte)(n >> shift);
+            }
+        }
+
+		public override IMemoable Copy()
+		{
+			return new Sha512tDigest(this);
+		}
+
+		public override void Reset(IMemoable other)
+		{
+			Sha512tDigest t = (Sha512tDigest)other;
+
+			if (this.digestLength != t.digestLength)
+			{
+				throw new MemoableResetException("digestLength inappropriate in other");
+			}
+
+			base.CopyIn(t);
+
+			this.H1t = t.H1t;
+			this.H2t = t.H2t;
+			this.H3t = t.H3t;
+			this.H4t = t.H4t;
+			this.H5t = t.H5t;
+			this.H6t = t.H6t;
+			this.H7t = t.H7t;
+			this.H8t = t.H8t;
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/ShortenedDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/ShortenedDigest.cs
new file mode 100644
index 0000000..9e4d99e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/ShortenedDigest.cs
@@ -0,0 +1,82 @@
+using System;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+	/**
+	* Wrapper class that reduces the output length of a particular digest to
+	* only the first n bytes of the digest function.
+	*/
+	public class ShortenedDigest
+		: IDigest
+	{
+		private IDigest	baseDigest;
+		private int		length;
+
+		/**
+		* Base constructor.
+		*
+		* @param baseDigest underlying digest to use.
+		* @param length length in bytes of the output of doFinal.
+		* @exception ArgumentException if baseDigest is null, or length is greater than baseDigest.GetDigestSize().
+		*/
+		public ShortenedDigest(
+			IDigest	baseDigest,
+			int		length)
+		{
+			if (baseDigest == null)
+			{
+				throw new ArgumentNullException("baseDigest");
+			}
+
+			if (length > baseDigest.GetDigestSize())
+			{
+				throw new ArgumentException("baseDigest output not large enough to support length");
+			}
+
+			this.baseDigest = baseDigest;
+			this.length = length;
+		}
+
+		public string AlgorithmName
+		{
+			get { return baseDigest.AlgorithmName + "(" + length * 8 + ")"; }
+		}
+
+		public int GetDigestSize()
+		{
+			return length;
+		}
+
+		public void Update(byte input)
+		{
+			baseDigest.Update(input);
+		}
+
+		public void BlockUpdate(byte[] input, int inOff, int length)
+		{
+			baseDigest.BlockUpdate(input, inOff, length);
+		}
+
+		public int DoFinal(byte[] output, int outOff)
+		{
+			byte[] tmp = new byte[baseDigest.GetDigestSize()];
+
+			baseDigest.DoFinal(tmp, 0);
+
+	        Array.Copy(tmp, 0, output, outOff, length);
+
+			return length;
+		}
+
+		public void Reset()
+		{
+			baseDigest.Reset();
+		}
+
+		public int GetByteLength()
+		{
+			return baseDigest.GetByteLength();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/SkeinDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/SkeinDigest.cs
new file mode 100644
index 0000000..f826ce5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/SkeinDigest.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+	/// <summary>
+	/// Implementation of the Skein parameterised hash function in 256, 512 and 1024 bit block sizes,
+	/// based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+	/// </summary>
+	/// <remarks>
+	/// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+	/// competition in October 2010.
+	/// <p/>
+	/// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+	/// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+	/// </remarks>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+	public class SkeinDigest
+		: IDigest, IMemoable
+	{
+		/// <summary>
+		/// 256 bit block size - Skein-256
+		/// </summary>
+		public const int SKEIN_256 = SkeinEngine.SKEIN_256;
+		/// <summary>
+		/// 512 bit block size - Skein-512
+		/// </summary>
+		public const int SKEIN_512 = SkeinEngine.SKEIN_512;
+		/// <summary>
+		/// 1024 bit block size - Skein-1024
+		/// </summary>
+		public const int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+		private readonly SkeinEngine engine;
+
+		/// <summary>
+		/// Constructs a Skein digest with an internal state size and output size.
+		/// </summary>
+		/// <param name="stateSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+		///                       <see cref="SKEIN_1024"/>.</param>
+		/// <param name="digestSizeBits">the output/digest size to produce in bits, which must be an integral number of
+		///                      bytes.</param>
+		public SkeinDigest(int stateSizeBits, int digestSizeBits)
+		{
+			this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+			Init(null);
+		}
+
+		public SkeinDigest(SkeinDigest digest)
+		{
+			this.engine = new SkeinEngine(digest.engine);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			SkeinDigest d = (SkeinDigest)other;
+			engine.Reset(d.engine);
+		}
+
+		public IMemoable Copy()
+		{
+			return new SkeinDigest(this);
+		}
+
+		public String AlgorithmName
+		{
+			get { return "Skein-" + (engine.BlockSize * 8) + "-" + (engine.OutputSize * 8); }
+		}
+
+		public int GetDigestSize()
+		{
+			return engine.OutputSize;
+		}
+
+		public int GetByteLength()
+		{
+			return engine.BlockSize;
+		}
+
+		/// <summary>
+		/// Optionally initialises the Skein digest with the provided parameters.
+		/// </summary>
+		/// See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+		/// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+		public void Init(SkeinParameters parameters)
+		{
+			engine.Init(parameters);
+		}
+
+		public void Reset()
+		{
+			engine.Reset();
+		}
+
+		public void Update(byte inByte)
+		{
+			engine.Update(inByte);
+		}
+
+		public void BlockUpdate(byte[] inBytes, int inOff, int len)
+		{
+			engine.Update(inBytes, inOff, len);
+		}
+
+		public int DoFinal(byte[] outBytes, int outOff)
+		{
+			return engine.DoFinal(outBytes, outOff);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/SkeinEngine.cs b/BouncyCastle.AxCrypt/src/crypto/digests/SkeinEngine.cs
new file mode 100644
index 0000000..7e93138
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/SkeinEngine.cs
@@ -0,0 +1,804 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+
+    /// <summary>
+    /// Implementation of the Skein family of parameterised hash functions in 256, 512 and 1024 bit block
+    /// sizes, based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+    /// </summary>
+    /// <remarks>
+    /// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+    /// competition in October 2010.
+    /// <p/>
+    /// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+    /// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+    /// <p/>
+    /// This implementation is the basis for <see cref="Org.BouncyCastle.Crypto.Digests.SkeinDigest"/> and <see cref="Org.BouncyCastle.Crypto.Macs.SkeinMac"/>, implementing the
+    /// parameter based configuration system that allows Skein to be adapted to multiple applications. <br/>
+    /// Initialising the engine with <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> allows standard and arbitrary parameters to
+    /// be applied during the Skein hash function.
+    /// <p/>
+    /// Implemented:
+    /// <ul>
+    /// <li>256, 512 and 1024 bit internal states.</li>
+    /// <li>Full 96 bit input length.</li>
+    /// <li>Parameters defined in the Skein specification, and arbitrary other pre and post message
+    /// parameters.</li>
+    /// <li>Arbitrary output size in 1 byte intervals.</li>
+    /// </ul>
+    /// <p/>
+    /// Not implemented:
+    /// <ul>
+    /// <li>Sub-byte length input (bit padding).</li>
+    /// <li>Tree hashing.</li>
+    /// </ul>
+    /// </remarks>
+    /// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+    public class SkeinEngine
+        : IMemoable
+    {
+        /// <summary>
+        /// 256 bit block size - Skein-256
+        /// </summary>
+        public const int SKEIN_256 = ThreefishEngine.BLOCKSIZE_256;
+        /// <summary>
+        /// 512 bit block size - Skein-512
+        /// </summary>
+        public const int SKEIN_512 = ThreefishEngine.BLOCKSIZE_512;
+        /// <summary>
+        /// 1024 bit block size - Skein-1024
+        /// </summary>
+        public const int SKEIN_1024 = ThreefishEngine.BLOCKSIZE_1024;
+
+        // Minimal at present, but more complex when tree hashing is implemented
+        private class Configuration
+        {
+            private byte[] bytes = new byte[32];
+
+            public Configuration(long outputSizeBits)
+            {
+                // 0..3 = ASCII SHA3
+                bytes[0] = (byte)'S';
+                bytes[1] = (byte)'H';
+                bytes[2] = (byte)'A';
+                bytes[3] = (byte)'3';
+
+                // 4..5 = version number in LSB order
+                bytes[4] = 1;
+                bytes[5] = 0;
+
+                // 8..15 = output length
+                ThreefishEngine.WordToBytes((ulong)outputSizeBits, bytes, 8);
+            }
+
+            public byte[] Bytes
+            {
+                get { return bytes; }
+            }
+
+        }
+
+        public class Parameter
+        {
+            private int type;
+            private byte[] value;
+
+            public Parameter(int type, byte[] value)
+            {
+                this.type = type;
+                this.value = value;
+            }
+
+            public int Type
+            {
+                get { return type; }
+            }
+
+            public byte[] Value
+            {
+                get { return value; }
+            }
+
+        }
+
+        /**
+         * The parameter type for the Skein key.
+         */
+        private const int PARAM_TYPE_KEY = 0;
+
+        /**
+         * The parameter type for the Skein configuration block.
+         */
+        private const int PARAM_TYPE_CONFIG = 4;
+
+        /**
+         * The parameter type for the message.
+         */
+        private const int PARAM_TYPE_MESSAGE = 48;
+
+        /**
+         * The parameter type for the output transformation.
+         */
+        private const int PARAM_TYPE_OUTPUT = 63;
+
+        /**
+         * Precalculated UBI(CFG) states for common state/output combinations without key or other
+         * pre-message params.
+         */
+        private static readonly IDictionary INITIAL_STATES = Platform.CreateHashtable();
+
+        static SkeinEngine()
+        {
+            // From Appendix C of the Skein 1.3 NIST submission
+            InitialState(SKEIN_256, 128, new ulong[]{
+                0xe1111906964d7260UL,
+                0x883daaa77c8d811cUL,
+                0x10080df491960f7aUL,
+                0xccf7dde5b45bc1c2UL});
+
+            InitialState(SKEIN_256, 160, new ulong[]{
+                0x1420231472825e98UL,
+                0x2ac4e9a25a77e590UL,
+                0xd47a58568838d63eUL,
+                0x2dd2e4968586ab7dUL});
+
+            InitialState(SKEIN_256, 224, new ulong[]{
+                0xc6098a8c9ae5ea0bUL,
+                0x876d568608c5191cUL,
+                0x99cb88d7d7f53884UL,
+                0x384bddb1aeddb5deUL});
+
+            InitialState(SKEIN_256, 256, new ulong[]{
+                0xfc9da860d048b449UL,
+                0x2fca66479fa7d833UL,
+                0xb33bc3896656840fUL,
+                0x6a54e920fde8da69UL});
+
+            InitialState(SKEIN_512, 128, new ulong[]{
+                0xa8bc7bf36fbf9f52UL,
+                0x1e9872cebd1af0aaUL,
+                0x309b1790b32190d3UL,
+                0xbcfbb8543f94805cUL,
+                0x0da61bcd6e31b11bUL,
+                0x1a18ebead46a32e3UL,
+                0xa2cc5b18ce84aa82UL,
+                0x6982ab289d46982dUL});
+
+            InitialState(SKEIN_512, 160, new ulong[]{
+                0x28b81a2ae013bd91UL,
+                0xc2f11668b5bdf78fUL,
+                0x1760d8f3f6a56f12UL,
+                0x4fb747588239904fUL,
+                0x21ede07f7eaf5056UL,
+                0xd908922e63ed70b8UL,
+                0xb8ec76ffeccb52faUL,
+                0x01a47bb8a3f27a6eUL});
+
+            InitialState(SKEIN_512, 224, new ulong[]{
+                0xccd0616248677224UL,
+                0xcba65cf3a92339efUL,
+                0x8ccd69d652ff4b64UL,
+                0x398aed7b3ab890b4UL,
+                0x0f59d1b1457d2bd0UL,
+                0x6776fe6575d4eb3dUL,
+                0x99fbc70e997413e9UL,
+                0x9e2cfccfe1c41ef7UL});
+
+            InitialState(SKEIN_512, 384, new ulong[]{
+                0xa3f6c6bf3a75ef5fUL,
+                0xb0fef9ccfd84faa4UL,
+                0x9d77dd663d770cfeUL,
+                0xd798cbf3b468fddaUL,
+                0x1bc4a6668a0e4465UL,
+                0x7ed7d434e5807407UL,
+                0x548fc1acd4ec44d6UL,
+                0x266e17546aa18ff8UL});
+
+            InitialState(SKEIN_512, 512, new ulong[]{
+                0x4903adff749c51ceUL,
+                0x0d95de399746df03UL,
+                0x8fd1934127c79bceUL,
+                0x9a255629ff352cb1UL,
+                0x5db62599df6ca7b0UL,
+                0xeabe394ca9d5c3f4UL,
+                0x991112c71a75b523UL,
+                0xae18a40b660fcc33UL});
+        }
+
+        private static void InitialState(int blockSize, int outputSize, ulong[] state)
+        {
+            INITIAL_STATES.Add(VariantIdentifier(blockSize / 8, outputSize / 8), state);
+        }
+
+        private static int VariantIdentifier(int blockSizeBytes, int outputSizeBytes)
+        {
+            return (outputSizeBytes << 16) | blockSizeBytes;
+        }
+
+        private class UbiTweak
+        {
+            /**
+             * Point at which position might overflow long, so switch to add with carry logic
+             */
+            private const ulong LOW_RANGE = UInt64.MaxValue - UInt32.MaxValue;
+
+            /**
+             * Bit 127 = final
+             */
+            private const ulong T1_FINAL = 1UL << 63;
+
+            /**
+             * Bit 126 = first
+             */
+            private const ulong T1_FIRST = 1UL << 62;
+
+            /**
+             * UBI uses a 128 bit tweak
+             */
+            private ulong[] tweak = new ulong[2];
+
+            /**
+             * Whether 64 bit position exceeded
+             */
+            private bool extendedPosition;
+
+            public UbiTweak()
+            {
+                Reset();
+            }
+
+            public void Reset(UbiTweak tweak)
+            {
+                this.tweak = Arrays.Clone(tweak.tweak, this.tweak);
+                this.extendedPosition = tweak.extendedPosition;
+            }
+
+            public void Reset()
+            {
+                tweak[0] = 0;
+                tweak[1] = 0;
+                extendedPosition = false;
+                First = true;
+            }
+
+            public uint Type 
+            {
+                get 
+                {
+                    return (uint)((tweak[1] >> 56) & 0x3FUL);
+                }
+
+                set 
+                {
+                    // Bits 120..125 = type
+                    tweak[1] = (tweak[1] & 0xFFFFFFC000000000UL) | ((value & 0x3FUL) << 56);
+                }
+            }
+
+            public bool First
+            {
+                get
+                {
+                    return ((tweak[1] & T1_FIRST) != 0);
+                }
+                set
+                {
+                    if (value)
+                    {
+                        tweak[1] |= T1_FIRST;
+                    }
+                    else
+                    {
+                        tweak[1] &= ~T1_FIRST;
+                    }
+                }
+            }
+
+            public bool Final
+            {
+                get
+                {
+                    return ((tweak[1] & T1_FINAL) != 0);
+                }
+                set
+                {
+                    if (value)
+                    {
+                        tweak[1] |= T1_FINAL;
+                    }
+                    else
+                    {
+                        tweak[1] &= ~T1_FINAL;
+                    }
+                }
+            }
+
+            /**
+             * Advances the position in the tweak by the specified value.
+             */
+            public void AdvancePosition(int advance)
+            {
+                // Bits 0..95 = position
+                if (extendedPosition)
+                {
+                    ulong[] parts = new ulong[3];
+                    parts[0] = tweak[0] & 0xFFFFFFFFUL;
+                    parts[1] = (tweak[0] >> 32) & 0xFFFFFFFFUL;
+                    parts[2] = tweak[1] & 0xFFFFFFFFUL;
+
+                    ulong carry = (ulong)advance;
+                    for (int i = 0; i < parts.Length; i++)
+                    {
+                        carry += parts[i];
+                        parts[i] = carry;
+                        carry >>= 32;
+                    }
+                    tweak[0] = ((parts[1] & 0xFFFFFFFFUL) << 32) | (parts[0] & 0xFFFFFFFFUL);
+                    tweak[1] = (tweak[1] & 0xFFFFFFFF00000000UL) | (parts[2] & 0xFFFFFFFFUL);
+                }
+                else
+                {
+                    ulong position = tweak[0];
+                    position += (uint)advance;
+                    tweak[0] = position;
+                    if (position > LOW_RANGE)
+                    {
+                        extendedPosition = true;
+                    }
+                }
+            }
+
+            public ulong[] GetWords()
+            {
+                return tweak;
+            }
+
+            public override string ToString()
+            {
+                return Type + " first: " + First + ", final: " + Final;
+            }
+
+        }
+
+        /**
+         * The Unique Block Iteration chaining mode.
+         */
+        // TODO: This might be better as methods...
+        private class UBI
+        {
+            private readonly UbiTweak tweak = new UbiTweak();
+
+            private readonly SkeinEngine engine;
+
+            /**
+             * Buffer for the current block of message data
+             */
+            private byte[] currentBlock;
+
+            /**
+             * Offset into the current message block
+             */
+            private int currentOffset;
+
+            /**
+             * Buffer for message words for feedback into encrypted block
+             */
+            private ulong[] message;
+
+            public UBI(SkeinEngine engine, int blockSize)
+            {
+                this.engine = engine;
+                currentBlock = new byte[blockSize];
+                message = new ulong[currentBlock.Length / 8];
+            }
+
+            public void Reset(UBI ubi)
+            {
+                currentBlock = Arrays.Clone(ubi.currentBlock, currentBlock);
+                currentOffset = ubi.currentOffset;
+                message = Arrays.Clone(ubi.message, this.message);
+                tweak.Reset(ubi.tweak);
+            }
+
+            public void Reset(int type)
+            {
+                tweak.Reset();
+                tweak.Type = (uint)type;
+                currentOffset = 0;
+            }
+
+            public void Update(byte[] value, int offset, int len, ulong[] output)
+            {
+                /*
+                 * Buffer complete blocks for the underlying Threefish cipher, only flushing when there
+                 * are subsequent bytes (last block must be processed in doFinal() with final=true set).
+                 */
+                int copied = 0;
+                while (len > copied)
+                {
+                    if (currentOffset == currentBlock.Length)
+                    {
+                        ProcessBlock(output);
+                        tweak.First = false;
+                        currentOffset = 0;
+                    }
+
+                    int toCopy = System.Math.Min((len - copied), currentBlock.Length - currentOffset);
+                    Array.Copy(value, offset + copied, currentBlock, currentOffset, toCopy);
+                    copied += toCopy;
+                    currentOffset += toCopy;
+                    tweak.AdvancePosition(toCopy);
+                }
+            }
+
+            private void ProcessBlock(ulong[] output)
+            {
+                engine.threefish.Init(true, engine.chain, tweak.GetWords());
+                for (int i = 0; i < message.Length; i++)
+                {
+                    message[i] = ThreefishEngine.BytesToWord(currentBlock, i * 8);
+                }
+
+                engine.threefish.ProcessBlock(message, output);
+
+                for (int i = 0; i < output.Length; i++)
+                {
+                    output[i] ^= message[i];
+                }
+            }
+
+            public void DoFinal(ulong[] output)
+            {
+                // Pad remainder of current block with zeroes
+                for (int i = currentOffset; i < currentBlock.Length; i++)
+                {
+                    currentBlock[i] = 0;
+                }
+
+                tweak.Final = true;
+                ProcessBlock(output);
+            }
+
+        }
+
+        /**
+         * Underlying Threefish tweakable block cipher
+         */
+        private readonly ThreefishEngine threefish;
+
+        /**
+         * Size of the digest output, in bytes
+         */
+        private readonly int outputSizeBytes;
+
+        /**
+         * The current chaining/state value
+         */
+        private ulong[] chain;
+
+        /**
+         * The initial state value
+         */
+        private ulong[] initialState;
+
+        /**
+         * The (optional) key parameter
+         */
+        private byte[] key;
+
+        /**
+         * Parameters to apply prior to the message
+         */
+        private Parameter[] preMessageParameters;
+
+        /**
+         * Parameters to apply after the message, but prior to output
+         */
+        private Parameter[] postMessageParameters;
+
+        /**
+         * The current UBI operation
+         */
+        private readonly UBI ubi;
+
+        /**
+         * Buffer for single byte update method
+         */
+        private readonly byte[] singleByte = new byte[1];
+
+        /// <summary>
+        /// Constructs a Skein digest with an internal state size and output size.
+        /// </summary>
+        /// <param name="blockSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+        ///                       <see cref="SKEIN_1024"/>.</param>
+        /// <param name="outputSizeBits">the output/digest size to produce in bits, which must be an integral number of
+        ///                      bytes.</param>
+        public SkeinEngine(int blockSizeBits, int outputSizeBits)
+        {
+            if (outputSizeBits % 8 != 0)
+            {
+                throw new ArgumentException("Output size must be a multiple of 8 bits. :" + outputSizeBits);
+            }
+            // TODO: Prevent digest sizes > block size?
+            this.outputSizeBytes = outputSizeBits / 8;
+
+            this.threefish = new ThreefishEngine(blockSizeBits);
+            this.ubi = new UBI(this,threefish.GetBlockSize());
+        }
+
+        /// <summary>
+        /// Creates a SkeinEngine as an exact copy of an existing instance.
+        /// </summary>
+        public SkeinEngine(SkeinEngine engine)
+            : this(engine.BlockSize * 8, engine.OutputSize * 8)
+        {
+            CopyIn(engine);
+        }
+
+        private void CopyIn(SkeinEngine engine)
+        {
+            this.ubi.Reset(engine.ubi);
+            this.chain = Arrays.Clone(engine.chain, this.chain);
+            this.initialState = Arrays.Clone(engine.initialState, this.initialState);
+            this.key = Arrays.Clone(engine.key, this.key);
+            this.preMessageParameters = Clone(engine.preMessageParameters, this.preMessageParameters);
+            this.postMessageParameters = Clone(engine.postMessageParameters, this.postMessageParameters);
+        }
+
+        private static Parameter[] Clone(Parameter[] data, Parameter[] existing)
+        {
+            if (data == null)
+            {
+                return null;
+            }
+            if ((existing == null) || (existing.Length != data.Length))
+            {
+                existing = new Parameter[data.Length];
+            }
+            Array.Copy(data, 0, existing, 0, existing.Length);
+            return existing;
+        }
+
+        public IMemoable Copy()
+        {
+            return new SkeinEngine(this);
+        }
+
+        public void Reset(IMemoable other)
+        {
+            SkeinEngine s = (SkeinEngine)other;
+            if ((BlockSize != s.BlockSize) || (outputSizeBytes != s.outputSizeBytes))
+            {
+                throw new MemoableResetException("Incompatible parameters in provided SkeinEngine.");
+            }
+            CopyIn(s);
+        }
+
+        public int OutputSize
+        {
+            get { return outputSizeBytes; }
+        }
+
+        public int BlockSize
+        {
+            get { return threefish.GetBlockSize (); }
+        }
+
+        /// <summary>
+        /// Initialises the Skein engine with the provided parameters. See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/> for
+        /// details on the parameterisation of the Skein hash function.
+        /// </summary>
+        /// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+        public void Init(SkeinParameters parameters)
+        {
+            this.chain = null;
+            this.key = null;
+            this.preMessageParameters = null;
+            this.postMessageParameters = null;
+
+            if (parameters != null)
+            {
+                byte[] key = parameters.GetKey();
+                if (key.Length < 16)
+                {
+                    throw new ArgumentException("Skein key must be at least 128 bits.");
+                }
+                InitParams(parameters.GetParameters());
+            }
+            CreateInitialState();
+
+            // Initialise message block
+            UbiInit(PARAM_TYPE_MESSAGE);
+        }
+
+        private void InitParams(IDictionary parameters)
+        {
+            IEnumerator keys = parameters.Keys.GetEnumerator();
+            IList pre = Platform.CreateArrayList();
+            IList post = Platform.CreateArrayList();
+
+            while (keys.MoveNext())
+            {
+                int type = (int)keys.Current;
+                byte[] value = (byte[])parameters[type];
+
+                if (type == PARAM_TYPE_KEY)
+                {
+                    this.key = value;
+                }
+                else if (type < PARAM_TYPE_MESSAGE)
+                {
+                    pre.Add(new Parameter(type, value));
+                }
+                else
+                {
+                    post.Add(new Parameter(type, value));
+                }
+            }
+            preMessageParameters = new Parameter[pre.Count];
+            pre.CopyTo(preMessageParameters, 0);
+            Array.Sort(preMessageParameters);
+
+            postMessageParameters = new Parameter[post.Count];
+            post.CopyTo(postMessageParameters, 0);
+            Array.Sort(postMessageParameters);
+        }
+
+        /**
+         * Calculate the initial (pre message block) chaining state.
+         */
+        private void CreateInitialState()
+        {
+            ulong[] precalc = (ulong[])INITIAL_STATES[VariantIdentifier(BlockSize, OutputSize)];
+            if ((key == null) && (precalc != null))
+            {
+                // Precalculated UBI(CFG)
+                chain = Arrays.Clone(precalc);
+            }
+            else
+            {
+                // Blank initial state
+                chain = new ulong[BlockSize / 8];
+
+                // Process key block
+                if (key != null)
+                {
+                    UbiComplete(SkeinParameters.PARAM_TYPE_KEY, key);
+                }
+
+                // Process configuration block
+                UbiComplete(PARAM_TYPE_CONFIG, new Configuration(outputSizeBytes * 8).Bytes);
+            }
+
+            // Process additional pre-message parameters
+            if (preMessageParameters != null)
+            {
+                for (int i = 0; i < preMessageParameters.Length; i++)
+                {
+                    Parameter param = preMessageParameters[i];
+                    UbiComplete(param.Type, param.Value);
+                }
+            }
+            initialState = Arrays.Clone(chain);
+        }
+
+        /// <summary>
+        /// Reset the engine to the initial state (with the key and any pre-message parameters , ready to
+        /// accept message input.
+        /// </summary>
+        public void Reset()
+        {
+            Array.Copy(initialState, 0, chain, 0, chain.Length);
+
+            UbiInit(PARAM_TYPE_MESSAGE);
+        }
+
+        private void UbiComplete(int type, byte[] value)
+        {
+            UbiInit(type);
+            this.ubi.Update(value, 0, value.Length, chain);
+            UbiFinal();
+        }
+
+        private void UbiInit(int type)
+        {
+            this.ubi.Reset(type);
+        }
+
+        private void UbiFinal()
+        {
+            ubi.DoFinal(chain);
+        }
+
+        private void CheckInitialised()
+        {
+            if (this.ubi == null)
+            {
+                throw new ArgumentException("Skein engine is not initialised.");
+            }
+        }
+
+        public void Update(byte inByte)
+        {
+            singleByte[0] = inByte;
+            Update(singleByte, 0, 1);
+        }
+
+        public void Update(byte[] inBytes, int inOff, int len)
+        {
+            CheckInitialised();
+            ubi.Update(inBytes, inOff, len, chain);
+        }
+
+        public int DoFinal(byte[] outBytes, int outOff)
+        {
+            CheckInitialised();
+            if (outBytes.Length < (outOff + outputSizeBytes))
+            {
+                throw new DataLengthException("Output buffer is too short to hold output of " + outputSizeBytes + " bytes");
+            }
+
+            // Finalise message block
+            UbiFinal();
+
+            // Process additional post-message parameters
+            if (postMessageParameters != null)
+            {
+                for (int i = 0; i < postMessageParameters.Length; i++)
+                {
+                    Parameter param = postMessageParameters[i];
+                    UbiComplete(param.Type, param.Value);
+                }
+            }
+
+            // Perform the output transform
+            int blockSize = BlockSize;
+            int blocksRequired = ((outputSizeBytes + blockSize - 1) / blockSize);
+            for (int i = 0; i < blocksRequired; i++)
+            {
+                int toWrite = System.Math.Min(blockSize, outputSizeBytes - (i * blockSize));
+                Output((ulong)i, outBytes, outOff + (i * blockSize), toWrite);
+            }
+
+            Reset();
+
+            return outputSizeBytes;
+        }
+
+        private void Output(ulong outputSequence, byte[] outBytes, int outOff, int outputBytes)
+        {
+            byte[] currentBytes = new byte[8];
+            ThreefishEngine.WordToBytes(outputSequence, currentBytes, 0);
+
+            // Output is a sequence of UBI invocations all of which use and preserve the pre-output
+            // state
+            ulong[] outputWords = new ulong[chain.Length];
+            UbiInit(PARAM_TYPE_OUTPUT);
+            this.ubi.Update(currentBytes, 0, currentBytes.Length, outputWords);
+            ubi.DoFinal(outputWords);
+
+            int wordsRequired = ((outputBytes + 8 - 1) / 8);
+            for (int i = 0; i < wordsRequired; i++)
+            {
+                int toWrite = System.Math.Min(8, outputBytes - (i * 8));
+                if (toWrite == 8)
+                {
+                    ThreefishEngine.WordToBytes(outputWords[i], outBytes, outOff + (i * 8));
+                }
+                else
+                {
+                    ThreefishEngine.WordToBytes(outputWords[i], currentBytes, 0);
+                    Array.Copy(currentBytes, 0, outBytes, outOff + (i * 8), toWrite);
+                }
+            }
+        }
+
+    }
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/TigerDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/TigerDigest.cs
new file mode 100644
index 0000000..059232d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/TigerDigest.cs
@@ -0,0 +1,883 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+    /**
+    * implementation of Tiger based on:
+    * <a href="http://www.cs.technion.ac.il/~biham/Reports/Tiger">
+    *  http://www.cs.technion.ac.il/~biham/Reports/Tiger</a>
+    */
+    public class TigerDigest
+		: IDigest, IMemoable
+    {
+        private const int MyByteLength = 64;
+
+        /*
+        * S-Boxes.
+        */
+        private static readonly long[] t1 = {
+            unchecked((long) 0x02AAB17CF7E90C5EL)   /*    0 */,    unchecked((long) 0xAC424B03E243A8ECL)   /*    1 */,
+            unchecked((long) 0x72CD5BE30DD5FCD3L)   /*    2 */,    unchecked((long) 0x6D019B93F6F97F3AL)   /*    3 */,
+            unchecked((long) 0xCD9978FFD21F9193L)   /*    4 */,    unchecked((long) 0x7573A1C9708029E2L)   /*    5 */,
+            unchecked((long) 0xB164326B922A83C3L)   /*    6 */,    unchecked((long) 0x46883EEE04915870L)   /*    7 */,
+            unchecked((long) 0xEAACE3057103ECE6L)   /*    8 */,    unchecked((long) 0xC54169B808A3535CL)   /*    9 */,
+            unchecked((long) 0x4CE754918DDEC47CL)   /*   10 */,    unchecked((long) 0x0AA2F4DFDC0DF40CL)   /*   11 */,
+            unchecked((long) 0x10B76F18A74DBEFAL)   /*   12 */,    unchecked((long) 0xC6CCB6235AD1AB6AL)   /*   13 */,
+            unchecked((long) 0x13726121572FE2FFL)   /*   14 */,    unchecked((long) 0x1A488C6F199D921EL)   /*   15 */,
+            unchecked((long) 0x4BC9F9F4DA0007CAL)   /*   16 */,    unchecked((long) 0x26F5E6F6E85241C7L)   /*   17 */,
+            unchecked((long) 0x859079DBEA5947B6L)   /*   18 */,    unchecked((long) 0x4F1885C5C99E8C92L)   /*   19 */,
+            unchecked((long) 0xD78E761EA96F864BL)   /*   20 */,    unchecked((long) 0x8E36428C52B5C17DL)   /*   21 */,
+            unchecked((long) 0x69CF6827373063C1L)   /*   22 */,    unchecked((long) 0xB607C93D9BB4C56EL)   /*   23 */,
+            unchecked((long) 0x7D820E760E76B5EAL)   /*   24 */,    unchecked((long) 0x645C9CC6F07FDC42L)   /*   25 */,
+            unchecked((long) 0xBF38A078243342E0L)   /*   26 */,    unchecked((long) 0x5F6B343C9D2E7D04L)   /*   27 */,
+            unchecked((long) 0xF2C28AEB600B0EC6L)   /*   28 */,    unchecked((long) 0x6C0ED85F7254BCACL)   /*   29 */,
+            unchecked((long) 0x71592281A4DB4FE5L)   /*   30 */,    unchecked((long) 0x1967FA69CE0FED9FL)   /*   31 */,
+            unchecked((long) 0xFD5293F8B96545DBL)   /*   32 */,    unchecked((long) 0xC879E9D7F2A7600BL)   /*   33 */,
+            unchecked((long) 0x860248920193194EL)   /*   34 */,    unchecked((long) 0xA4F9533B2D9CC0B3L)   /*   35 */,
+            unchecked((long) 0x9053836C15957613L)   /*   36 */,    unchecked((long) 0xDB6DCF8AFC357BF1L)   /*   37 */,
+            unchecked((long) 0x18BEEA7A7A370F57L)   /*   38 */,    unchecked((long) 0x037117CA50B99066L)   /*   39 */,
+            unchecked((long) 0x6AB30A9774424A35L)   /*   40 */,    unchecked((long) 0xF4E92F02E325249BL)   /*   41 */,
+            unchecked((long) 0x7739DB07061CCAE1L)   /*   42 */,    unchecked((long) 0xD8F3B49CECA42A05L)   /*   43 */,
+            unchecked((long) 0xBD56BE3F51382F73L)   /*   44 */,    unchecked((long) 0x45FAED5843B0BB28L)   /*   45 */,
+            unchecked((long) 0x1C813D5C11BF1F83L)   /*   46 */,    unchecked((long) 0x8AF0E4B6D75FA169L)   /*   47 */,
+            unchecked((long) 0x33EE18A487AD9999L)   /*   48 */,    unchecked((long) 0x3C26E8EAB1C94410L)   /*   49 */,
+            unchecked((long) 0xB510102BC0A822F9L)   /*   50 */,    unchecked((long) 0x141EEF310CE6123BL)   /*   51 */,
+            unchecked((long) 0xFC65B90059DDB154L)   /*   52 */,    unchecked((long) 0xE0158640C5E0E607L)   /*   53 */,
+            unchecked((long) 0x884E079826C3A3CFL)   /*   54 */,    unchecked((long) 0x930D0D9523C535FDL)   /*   55 */,
+            unchecked((long) 0x35638D754E9A2B00L)   /*   56 */,    unchecked((long) 0x4085FCCF40469DD5L)   /*   57 */,
+            unchecked((long) 0xC4B17AD28BE23A4CL)   /*   58 */,    unchecked((long) 0xCAB2F0FC6A3E6A2EL)   /*   59 */,
+            unchecked((long) 0x2860971A6B943FCDL)   /*   60 */,    unchecked((long) 0x3DDE6EE212E30446L)   /*   61 */,
+            unchecked((long) 0x6222F32AE01765AEL)   /*   62 */,    unchecked((long) 0x5D550BB5478308FEL)   /*   63 */,
+            unchecked((long) 0xA9EFA98DA0EDA22AL)   /*   64 */,    unchecked((long) 0xC351A71686C40DA7L)   /*   65 */,
+            unchecked((long) 0x1105586D9C867C84L)   /*   66 */,    unchecked((long) 0xDCFFEE85FDA22853L)   /*   67 */,
+            unchecked((long) 0xCCFBD0262C5EEF76L)   /*   68 */,    unchecked((long) 0xBAF294CB8990D201L)   /*   69 */,
+            unchecked((long) 0xE69464F52AFAD975L)   /*   70 */,    unchecked((long) 0x94B013AFDF133E14L)   /*   71 */,
+            unchecked((long) 0x06A7D1A32823C958L)   /*   72 */,    unchecked((long) 0x6F95FE5130F61119L)   /*   73 */,
+            unchecked((long) 0xD92AB34E462C06C0L)   /*   74 */,    unchecked((long) 0xED7BDE33887C71D2L)   /*   75 */,
+            unchecked((long) 0x79746D6E6518393EL)   /*   76 */,    unchecked((long) 0x5BA419385D713329L)   /*   77 */,
+            unchecked((long) 0x7C1BA6B948A97564L)   /*   78 */,    unchecked((long) 0x31987C197BFDAC67L)   /*   79 */,
+            unchecked((long) 0xDE6C23C44B053D02L)   /*   80 */,    unchecked((long) 0x581C49FED002D64DL)   /*   81 */,
+            unchecked((long) 0xDD474D6338261571L)   /*   82 */,    unchecked((long) 0xAA4546C3E473D062L)   /*   83 */,
+            unchecked((long) 0x928FCE349455F860L)   /*   84 */,    unchecked((long) 0x48161BBACAAB94D9L)   /*   85 */,
+            unchecked((long) 0x63912430770E6F68L)   /*   86 */,    unchecked((long) 0x6EC8A5E602C6641CL)   /*   87 */,
+            unchecked((long) 0x87282515337DDD2BL)   /*   88 */,    unchecked((long) 0x2CDA6B42034B701BL)   /*   89 */,
+            unchecked((long) 0xB03D37C181CB096DL)   /*   90 */,    unchecked((long) 0xE108438266C71C6FL)   /*   91 */,
+            unchecked((long) 0x2B3180C7EB51B255L)   /*   92 */,    unchecked((long) 0xDF92B82F96C08BBCL)   /*   93 */,
+            unchecked((long) 0x5C68C8C0A632F3BAL)   /*   94 */,    unchecked((long) 0x5504CC861C3D0556L)   /*   95 */,
+            unchecked((long) 0xABBFA4E55FB26B8FL)   /*   96 */,    unchecked((long) 0x41848B0AB3BACEB4L)   /*   97 */,
+            unchecked((long) 0xB334A273AA445D32L)   /*   98 */,    unchecked((long) 0xBCA696F0A85AD881L)   /*   99 */,
+            unchecked((long) 0x24F6EC65B528D56CL)   /*  100 */,    unchecked((long) 0x0CE1512E90F4524AL)   /*  101 */,
+            unchecked((long) 0x4E9DD79D5506D35AL)   /*  102 */,    unchecked((long) 0x258905FAC6CE9779L)   /*  103 */,
+            unchecked((long) 0x2019295B3E109B33L)   /*  104 */,    unchecked((long) 0xF8A9478B73A054CCL)   /*  105 */,
+            unchecked((long) 0x2924F2F934417EB0L)   /*  106 */,    unchecked((long) 0x3993357D536D1BC4L)   /*  107 */,
+            unchecked((long) 0x38A81AC21DB6FF8BL)   /*  108 */,    unchecked((long) 0x47C4FBF17D6016BFL)   /*  109 */,
+            unchecked((long) 0x1E0FAADD7667E3F5L)   /*  110 */,    unchecked((long) 0x7ABCFF62938BEB96L)   /*  111 */,
+            unchecked((long) 0xA78DAD948FC179C9L)   /*  112 */,    unchecked((long) 0x8F1F98B72911E50DL)   /*  113 */,
+            unchecked((long) 0x61E48EAE27121A91L)   /*  114 */,    unchecked((long) 0x4D62F7AD31859808L)   /*  115 */,
+            unchecked((long) 0xECEBA345EF5CEAEBL)   /*  116 */,    unchecked((long) 0xF5CEB25EBC9684CEL)   /*  117 */,
+            unchecked((long) 0xF633E20CB7F76221L)   /*  118 */,    unchecked((long) 0xA32CDF06AB8293E4L)   /*  119 */,
+            unchecked((long) 0x985A202CA5EE2CA4L)   /*  120 */,    unchecked((long) 0xCF0B8447CC8A8FB1L)   /*  121 */,
+            unchecked((long) 0x9F765244979859A3L)   /*  122 */,    unchecked((long) 0xA8D516B1A1240017L)   /*  123 */,
+            unchecked((long) 0x0BD7BA3EBB5DC726L)   /*  124 */,    unchecked((long) 0xE54BCA55B86ADB39L)   /*  125 */,
+            unchecked((long) 0x1D7A3AFD6C478063L)   /*  126 */,    unchecked((long) 0x519EC608E7669EDDL)   /*  127 */,
+            unchecked((long) 0x0E5715A2D149AA23L)   /*  128 */,    unchecked((long) 0x177D4571848FF194L)   /*  129 */,
+            unchecked((long) 0xEEB55F3241014C22L)   /*  130 */,    unchecked((long) 0x0F5E5CA13A6E2EC2L)   /*  131 */,
+            unchecked((long) 0x8029927B75F5C361L)   /*  132 */,    unchecked((long) 0xAD139FABC3D6E436L)   /*  133 */,
+            unchecked((long) 0x0D5DF1A94CCF402FL)   /*  134 */,    unchecked((long) 0x3E8BD948BEA5DFC8L)   /*  135 */,
+            unchecked((long) 0xA5A0D357BD3FF77EL)   /*  136 */,    unchecked((long) 0xA2D12E251F74F645L)   /*  137 */,
+            unchecked((long) 0x66FD9E525E81A082L)   /*  138 */,    unchecked((long) 0x2E0C90CE7F687A49L)   /*  139 */,
+            unchecked((long) 0xC2E8BCBEBA973BC5L)   /*  140 */,    unchecked((long) 0x000001BCE509745FL)   /*  141 */,
+            unchecked((long) 0x423777BBE6DAB3D6L)   /*  142 */,    unchecked((long) 0xD1661C7EAEF06EB5L)   /*  143 */,
+            unchecked((long) 0xA1781F354DAACFD8L)   /*  144 */,    unchecked((long) 0x2D11284A2B16AFFCL)   /*  145 */,
+            unchecked((long) 0xF1FC4F67FA891D1FL)   /*  146 */,    unchecked((long) 0x73ECC25DCB920ADAL)   /*  147 */,
+            unchecked((long) 0xAE610C22C2A12651L)   /*  148 */,    unchecked((long) 0x96E0A810D356B78AL)   /*  149 */,
+            unchecked((long) 0x5A9A381F2FE7870FL)   /*  150 */,    unchecked((long) 0xD5AD62EDE94E5530L)   /*  151 */,
+            unchecked((long) 0xD225E5E8368D1427L)   /*  152 */,    unchecked((long) 0x65977B70C7AF4631L)   /*  153 */,
+            unchecked((long) 0x99F889B2DE39D74FL)   /*  154 */,    unchecked((long) 0x233F30BF54E1D143L)   /*  155 */,
+            unchecked((long) 0x9A9675D3D9A63C97L)   /*  156 */,    unchecked((long) 0x5470554FF334F9A8L)   /*  157 */,
+            unchecked((long) 0x166ACB744A4F5688L)   /*  158 */,    unchecked((long) 0x70C74CAAB2E4AEADL)   /*  159 */,
+            unchecked((long) 0xF0D091646F294D12L)   /*  160 */,    unchecked((long) 0x57B82A89684031D1L)   /*  161 */,
+            unchecked((long) 0xEFD95A5A61BE0B6BL)   /*  162 */,    unchecked((long) 0x2FBD12E969F2F29AL)   /*  163 */,
+            unchecked((long) 0x9BD37013FEFF9FE8L)   /*  164 */,    unchecked((long) 0x3F9B0404D6085A06L)   /*  165 */,
+            unchecked((long) 0x4940C1F3166CFE15L)   /*  166 */,    unchecked((long) 0x09542C4DCDF3DEFBL)   /*  167 */,
+            unchecked((long) 0xB4C5218385CD5CE3L)   /*  168 */,    unchecked((long) 0xC935B7DC4462A641L)   /*  169 */,
+            unchecked((long) 0x3417F8A68ED3B63FL)   /*  170 */,    unchecked((long) 0xB80959295B215B40L)   /*  171 */,
+            unchecked((long) 0xF99CDAEF3B8C8572L)   /*  172 */,    unchecked((long) 0x018C0614F8FCB95DL)   /*  173 */,
+            unchecked((long) 0x1B14ACCD1A3ACDF3L)   /*  174 */,    unchecked((long) 0x84D471F200BB732DL)   /*  175 */,
+            unchecked((long) 0xC1A3110E95E8DA16L)   /*  176 */,    unchecked((long) 0x430A7220BF1A82B8L)   /*  177 */,
+            unchecked((long) 0xB77E090D39DF210EL)   /*  178 */,    unchecked((long) 0x5EF4BD9F3CD05E9DL)   /*  179 */,
+            unchecked((long) 0x9D4FF6DA7E57A444L)   /*  180 */,    unchecked((long) 0xDA1D60E183D4A5F8L)   /*  181 */,
+            unchecked((long) 0xB287C38417998E47L)   /*  182 */,    unchecked((long) 0xFE3EDC121BB31886L)   /*  183 */,
+            unchecked((long) 0xC7FE3CCC980CCBEFL)   /*  184 */,    unchecked((long) 0xE46FB590189BFD03L)   /*  185 */,
+            unchecked((long) 0x3732FD469A4C57DCL)   /*  186 */,    unchecked((long) 0x7EF700A07CF1AD65L)   /*  187 */,
+            unchecked((long) 0x59C64468A31D8859L)   /*  188 */,    unchecked((long) 0x762FB0B4D45B61F6L)   /*  189 */,
+            unchecked((long) 0x155BAED099047718L)   /*  190 */,    unchecked((long) 0x68755E4C3D50BAA6L)   /*  191 */,
+            unchecked((long) 0xE9214E7F22D8B4DFL)   /*  192 */,    unchecked((long) 0x2ADDBF532EAC95F4L)   /*  193 */,
+            unchecked((long) 0x32AE3909B4BD0109L)   /*  194 */,    unchecked((long) 0x834DF537B08E3450L)   /*  195 */,
+            unchecked((long) 0xFA209DA84220728DL)   /*  196 */,    unchecked((long) 0x9E691D9B9EFE23F7L)   /*  197 */,
+            unchecked((long) 0x0446D288C4AE8D7FL)   /*  198 */,    unchecked((long) 0x7B4CC524E169785BL)   /*  199 */,
+            unchecked((long) 0x21D87F0135CA1385L)   /*  200 */,    unchecked((long) 0xCEBB400F137B8AA5L)   /*  201 */,
+            unchecked((long) 0x272E2B66580796BEL)   /*  202 */,    unchecked((long) 0x3612264125C2B0DEL)   /*  203 */,
+            unchecked((long) 0x057702BDAD1EFBB2L)   /*  204 */,    unchecked((long) 0xD4BABB8EACF84BE9L)   /*  205 */,
+            unchecked((long) 0x91583139641BC67BL)   /*  206 */,    unchecked((long) 0x8BDC2DE08036E024L)   /*  207 */,
+            unchecked((long) 0x603C8156F49F68EDL)   /*  208 */,    unchecked((long) 0xF7D236F7DBEF5111L)   /*  209 */,
+            unchecked((long) 0x9727C4598AD21E80L)   /*  210 */,    unchecked((long) 0xA08A0896670A5FD7L)   /*  211 */,
+            unchecked((long) 0xCB4A8F4309EBA9CBL)   /*  212 */,    unchecked((long) 0x81AF564B0F7036A1L)   /*  213 */,
+            unchecked((long) 0xC0B99AA778199ABDL)   /*  214 */,    unchecked((long) 0x959F1EC83FC8E952L)   /*  215 */,
+            unchecked((long) 0x8C505077794A81B9L)   /*  216 */,    unchecked((long) 0x3ACAAF8F056338F0L)   /*  217 */,
+            unchecked((long) 0x07B43F50627A6778L)   /*  218 */,    unchecked((long) 0x4A44AB49F5ECCC77L)   /*  219 */,
+            unchecked((long) 0x3BC3D6E4B679EE98L)   /*  220 */,    unchecked((long) 0x9CC0D4D1CF14108CL)   /*  221 */,
+            unchecked((long) 0x4406C00B206BC8A0L)   /*  222 */,    unchecked((long) 0x82A18854C8D72D89L)   /*  223 */,
+            unchecked((long) 0x67E366B35C3C432CL)   /*  224 */,    unchecked((long) 0xB923DD61102B37F2L)   /*  225 */,
+            unchecked((long) 0x56AB2779D884271DL)   /*  226 */,    unchecked((long) 0xBE83E1B0FF1525AFL)   /*  227 */,
+            unchecked((long) 0xFB7C65D4217E49A9L)   /*  228 */,    unchecked((long) 0x6BDBE0E76D48E7D4L)   /*  229 */,
+            unchecked((long) 0x08DF828745D9179EL)   /*  230 */,    unchecked((long) 0x22EA6A9ADD53BD34L)   /*  231 */,
+            unchecked((long) 0xE36E141C5622200AL)   /*  232 */,    unchecked((long) 0x7F805D1B8CB750EEL)   /*  233 */,
+            unchecked((long) 0xAFE5C7A59F58E837L)   /*  234 */,    unchecked((long) 0xE27F996A4FB1C23CL)   /*  235 */,
+            unchecked((long) 0xD3867DFB0775F0D0L)   /*  236 */,    unchecked((long) 0xD0E673DE6E88891AL)   /*  237 */,
+            unchecked((long) 0x123AEB9EAFB86C25L)   /*  238 */,    unchecked((long) 0x30F1D5D5C145B895L)   /*  239 */,
+            unchecked((long) 0xBB434A2DEE7269E7L)   /*  240 */,    unchecked((long) 0x78CB67ECF931FA38L)   /*  241 */,
+            unchecked((long) 0xF33B0372323BBF9CL)   /*  242 */,    unchecked((long) 0x52D66336FB279C74L)   /*  243 */,
+            unchecked((long) 0x505F33AC0AFB4EAAL)   /*  244 */,    unchecked((long) 0xE8A5CD99A2CCE187L)   /*  245 */,
+            unchecked((long) 0x534974801E2D30BBL)   /*  246 */,    unchecked((long) 0x8D2D5711D5876D90L)   /*  247 */,
+            unchecked((long) 0x1F1A412891BC038EL)   /*  248 */,    unchecked((long) 0xD6E2E71D82E56648L)   /*  249 */,
+            unchecked((long) 0x74036C3A497732B7L)   /*  250 */,    unchecked((long) 0x89B67ED96361F5ABL)   /*  251 */,
+            unchecked((long) 0xFFED95D8F1EA02A2L)   /*  252 */,    unchecked((long) 0xE72B3BD61464D43DL)   /*  253 */,
+            unchecked((long) 0xA6300F170BDC4820L)   /*  254 */,    unchecked((long) 0xEBC18760ED78A77AL)   /*  255 */,
+        };
+
+        private static readonly long[] t2 = {
+            unchecked((long) 0xE6A6BE5A05A12138L)   /*  256 */,    unchecked((long) 0xB5A122A5B4F87C98L)   /*  257 */,
+            unchecked((long) 0x563C6089140B6990L)   /*  258 */,    unchecked((long) 0x4C46CB2E391F5DD5L)   /*  259 */,
+            unchecked((long) 0xD932ADDBC9B79434L)   /*  260 */,    unchecked((long) 0x08EA70E42015AFF5L)   /*  261 */,
+            unchecked((long) 0xD765A6673E478CF1L)   /*  262 */,    unchecked((long) 0xC4FB757EAB278D99L)   /*  263 */,
+            unchecked((long) 0xDF11C6862D6E0692L)   /*  264 */,    unchecked((long) 0xDDEB84F10D7F3B16L)   /*  265 */,
+            unchecked((long) 0x6F2EF604A665EA04L)   /*  266 */,    unchecked((long) 0x4A8E0F0FF0E0DFB3L)   /*  267 */,
+            unchecked((long) 0xA5EDEEF83DBCBA51L)   /*  268 */,    unchecked((long) 0xFC4F0A2A0EA4371EL)   /*  269 */,
+            unchecked((long) 0xE83E1DA85CB38429L)   /*  270 */,    unchecked((long) 0xDC8FF882BA1B1CE2L)   /*  271 */,
+            unchecked((long) 0xCD45505E8353E80DL)   /*  272 */,    unchecked((long) 0x18D19A00D4DB0717L)   /*  273 */,
+            unchecked((long) 0x34A0CFEDA5F38101L)   /*  274 */,    unchecked((long) 0x0BE77E518887CAF2L)   /*  275 */,
+            unchecked((long) 0x1E341438B3C45136L)   /*  276 */,    unchecked((long) 0xE05797F49089CCF9L)   /*  277 */,
+            unchecked((long) 0xFFD23F9DF2591D14L)   /*  278 */,    unchecked((long) 0x543DDA228595C5CDL)   /*  279 */,
+            unchecked((long) 0x661F81FD99052A33L)   /*  280 */,    unchecked((long) 0x8736E641DB0F7B76L)   /*  281 */,
+            unchecked((long) 0x15227725418E5307L)   /*  282 */,    unchecked((long) 0xE25F7F46162EB2FAL)   /*  283 */,
+            unchecked((long) 0x48A8B2126C13D9FEL)   /*  284 */,    unchecked((long) 0xAFDC541792E76EEAL)   /*  285 */,
+            unchecked((long) 0x03D912BFC6D1898FL)   /*  286 */,    unchecked((long) 0x31B1AAFA1B83F51BL)   /*  287 */,
+            unchecked((long) 0xF1AC2796E42AB7D9L)   /*  288 */,    unchecked((long) 0x40A3A7D7FCD2EBACL)   /*  289 */,
+            unchecked((long) 0x1056136D0AFBBCC5L)   /*  290 */,    unchecked((long) 0x7889E1DD9A6D0C85L)   /*  291 */,
+            unchecked((long) 0xD33525782A7974AAL)   /*  292 */,    unchecked((long) 0xA7E25D09078AC09BL)   /*  293 */,
+            unchecked((long) 0xBD4138B3EAC6EDD0L)   /*  294 */,    unchecked((long) 0x920ABFBE71EB9E70L)   /*  295 */,
+            unchecked((long) 0xA2A5D0F54FC2625CL)   /*  296 */,    unchecked((long) 0xC054E36B0B1290A3L)   /*  297 */,
+            unchecked((long) 0xF6DD59FF62FE932BL)   /*  298 */,    unchecked((long) 0x3537354511A8AC7DL)   /*  299 */,
+            unchecked((long) 0xCA845E9172FADCD4L)   /*  300 */,    unchecked((long) 0x84F82B60329D20DCL)   /*  301 */,
+            unchecked((long) 0x79C62CE1CD672F18L)   /*  302 */,    unchecked((long) 0x8B09A2ADD124642CL)   /*  303 */,
+            unchecked((long) 0xD0C1E96A19D9E726L)   /*  304 */,    unchecked((long) 0x5A786A9B4BA9500CL)   /*  305 */,
+            unchecked((long) 0x0E020336634C43F3L)   /*  306 */,    unchecked((long) 0xC17B474AEB66D822L)   /*  307 */,
+            unchecked((long) 0x6A731AE3EC9BAAC2L)   /*  308 */,    unchecked((long) 0x8226667AE0840258L)   /*  309 */,
+            unchecked((long) 0x67D4567691CAECA5L)   /*  310 */,    unchecked((long) 0x1D94155C4875ADB5L)   /*  311 */,
+            unchecked((long) 0x6D00FD985B813FDFL)   /*  312 */,    unchecked((long) 0x51286EFCB774CD06L)   /*  313 */,
+            unchecked((long) 0x5E8834471FA744AFL)   /*  314 */,    unchecked((long) 0xF72CA0AEE761AE2EL)   /*  315 */,
+            unchecked((long) 0xBE40E4CDAEE8E09AL)   /*  316 */,    unchecked((long) 0xE9970BBB5118F665L)   /*  317 */,
+            unchecked((long) 0x726E4BEB33DF1964L)   /*  318 */,    unchecked((long) 0x703B000729199762L)   /*  319 */,
+            unchecked((long) 0x4631D816F5EF30A7L)   /*  320 */,    unchecked((long) 0xB880B5B51504A6BEL)   /*  321 */,
+            unchecked((long) 0x641793C37ED84B6CL)   /*  322 */,    unchecked((long) 0x7B21ED77F6E97D96L)   /*  323 */,
+            unchecked((long) 0x776306312EF96B73L)   /*  324 */,    unchecked((long) 0xAE528948E86FF3F4L)   /*  325 */,
+            unchecked((long) 0x53DBD7F286A3F8F8L)   /*  326 */,    unchecked((long) 0x16CADCE74CFC1063L)   /*  327 */,
+            unchecked((long) 0x005C19BDFA52C6DDL)   /*  328 */,    unchecked((long) 0x68868F5D64D46AD3L)   /*  329 */,
+            unchecked((long) 0x3A9D512CCF1E186AL)   /*  330 */,    unchecked((long) 0x367E62C2385660AEL)   /*  331 */,
+            unchecked((long) 0xE359E7EA77DCB1D7L)   /*  332 */,    unchecked((long) 0x526C0773749ABE6EL)   /*  333 */,
+            unchecked((long) 0x735AE5F9D09F734BL)   /*  334 */,    unchecked((long) 0x493FC7CC8A558BA8L)   /*  335 */,
+            unchecked((long) 0xB0B9C1533041AB45L)   /*  336 */,    unchecked((long) 0x321958BA470A59BDL)   /*  337 */,
+            unchecked((long) 0x852DB00B5F46C393L)   /*  338 */,    unchecked((long) 0x91209B2BD336B0E5L)   /*  339 */,
+            unchecked((long) 0x6E604F7D659EF19FL)   /*  340 */,    unchecked((long) 0xB99A8AE2782CCB24L)   /*  341 */,
+            unchecked((long) 0xCCF52AB6C814C4C7L)   /*  342 */,    unchecked((long) 0x4727D9AFBE11727BL)   /*  343 */,
+            unchecked((long) 0x7E950D0C0121B34DL)   /*  344 */,    unchecked((long) 0x756F435670AD471FL)   /*  345 */,
+            unchecked((long) 0xF5ADD442615A6849L)   /*  346 */,    unchecked((long) 0x4E87E09980B9957AL)   /*  347 */,
+            unchecked((long) 0x2ACFA1DF50AEE355L)   /*  348 */,    unchecked((long) 0xD898263AFD2FD556L)   /*  349 */,
+            unchecked((long) 0xC8F4924DD80C8FD6L)   /*  350 */,    unchecked((long) 0xCF99CA3D754A173AL)   /*  351 */,
+            unchecked((long) 0xFE477BACAF91BF3CL)   /*  352 */,    unchecked((long) 0xED5371F6D690C12DL)   /*  353 */,
+            unchecked((long) 0x831A5C285E687094L)   /*  354 */,    unchecked((long) 0xC5D3C90A3708A0A4L)   /*  355 */,
+            unchecked((long) 0x0F7F903717D06580L)   /*  356 */,    unchecked((long) 0x19F9BB13B8FDF27FL)   /*  357 */,
+            unchecked((long) 0xB1BD6F1B4D502843L)   /*  358 */,    unchecked((long) 0x1C761BA38FFF4012L)   /*  359 */,
+            unchecked((long) 0x0D1530C4E2E21F3BL)   /*  360 */,    unchecked((long) 0x8943CE69A7372C8AL)   /*  361 */,
+            unchecked((long) 0xE5184E11FEB5CE66L)   /*  362 */,    unchecked((long) 0x618BDB80BD736621L)   /*  363 */,
+            unchecked((long) 0x7D29BAD68B574D0BL)   /*  364 */,    unchecked((long) 0x81BB613E25E6FE5BL)   /*  365 */,
+            unchecked((long) 0x071C9C10BC07913FL)   /*  366 */,    unchecked((long) 0xC7BEEB7909AC2D97L)   /*  367 */,
+            unchecked((long) 0xC3E58D353BC5D757L)   /*  368 */,    unchecked((long) 0xEB017892F38F61E8L)   /*  369 */,
+            unchecked((long) 0xD4EFFB9C9B1CC21AL)   /*  370 */,    unchecked((long) 0x99727D26F494F7ABL)   /*  371 */,
+            unchecked((long) 0xA3E063A2956B3E03L)   /*  372 */,    unchecked((long) 0x9D4A8B9A4AA09C30L)   /*  373 */,
+            unchecked((long) 0x3F6AB7D500090FB4L)   /*  374 */,    unchecked((long) 0x9CC0F2A057268AC0L)   /*  375 */,
+            unchecked((long) 0x3DEE9D2DEDBF42D1L)   /*  376 */,    unchecked((long) 0x330F49C87960A972L)   /*  377 */,
+            unchecked((long) 0xC6B2720287421B41L)   /*  378 */,    unchecked((long) 0x0AC59EC07C00369CL)   /*  379 */,
+            unchecked((long) 0xEF4EAC49CB353425L)   /*  380 */,    unchecked((long) 0xF450244EEF0129D8L)   /*  381 */,
+            unchecked((long) 0x8ACC46E5CAF4DEB6L)   /*  382 */,    unchecked((long) 0x2FFEAB63989263F7L)   /*  383 */,
+            unchecked((long) 0x8F7CB9FE5D7A4578L)   /*  384 */,    unchecked((long) 0x5BD8F7644E634635L)   /*  385 */,
+            unchecked((long) 0x427A7315BF2DC900L)   /*  386 */,    unchecked((long) 0x17D0C4AA2125261CL)   /*  387 */,
+            unchecked((long) 0x3992486C93518E50L)   /*  388 */,    unchecked((long) 0xB4CBFEE0A2D7D4C3L)   /*  389 */,
+            unchecked((long) 0x7C75D6202C5DDD8DL)   /*  390 */,    unchecked((long) 0xDBC295D8E35B6C61L)   /*  391 */,
+            unchecked((long) 0x60B369D302032B19L)   /*  392 */,    unchecked((long) 0xCE42685FDCE44132L)   /*  393 */,
+            unchecked((long) 0x06F3DDB9DDF65610L)   /*  394 */,    unchecked((long) 0x8EA4D21DB5E148F0L)   /*  395 */,
+            unchecked((long) 0x20B0FCE62FCD496FL)   /*  396 */,    unchecked((long) 0x2C1B912358B0EE31L)   /*  397 */,
+            unchecked((long) 0xB28317B818F5A308L)   /*  398 */,    unchecked((long) 0xA89C1E189CA6D2CFL)   /*  399 */,
+            unchecked((long) 0x0C6B18576AAADBC8L)   /*  400 */,    unchecked((long) 0xB65DEAA91299FAE3L)   /*  401 */,
+            unchecked((long) 0xFB2B794B7F1027E7L)   /*  402 */,    unchecked((long) 0x04E4317F443B5BEBL)   /*  403 */,
+            unchecked((long) 0x4B852D325939D0A6L)   /*  404 */,    unchecked((long) 0xD5AE6BEEFB207FFCL)   /*  405 */,
+            unchecked((long) 0x309682B281C7D374L)   /*  406 */,    unchecked((long) 0xBAE309A194C3B475L)   /*  407 */,
+            unchecked((long) 0x8CC3F97B13B49F05L)   /*  408 */,    unchecked((long) 0x98A9422FF8293967L)   /*  409 */,
+            unchecked((long) 0x244B16B01076FF7CL)   /*  410 */,    unchecked((long) 0xF8BF571C663D67EEL)   /*  411 */,
+            unchecked((long) 0x1F0D6758EEE30DA1L)   /*  412 */,    unchecked((long) 0xC9B611D97ADEB9B7L)   /*  413 */,
+            unchecked((long) 0xB7AFD5887B6C57A2L)   /*  414 */,    unchecked((long) 0x6290AE846B984FE1L)   /*  415 */,
+            unchecked((long) 0x94DF4CDEACC1A5FDL)   /*  416 */,    unchecked((long) 0x058A5BD1C5483AFFL)   /*  417 */,
+            unchecked((long) 0x63166CC142BA3C37L)   /*  418 */,    unchecked((long) 0x8DB8526EB2F76F40L)   /*  419 */,
+            unchecked((long) 0xE10880036F0D6D4EL)   /*  420 */,    unchecked((long) 0x9E0523C9971D311DL)   /*  421 */,
+            unchecked((long) 0x45EC2824CC7CD691L)   /*  422 */,    unchecked((long) 0x575B8359E62382C9L)   /*  423 */,
+            unchecked((long) 0xFA9E400DC4889995L)   /*  424 */,    unchecked((long) 0xD1823ECB45721568L)   /*  425 */,
+            unchecked((long) 0xDAFD983B8206082FL)   /*  426 */,    unchecked((long) 0xAA7D29082386A8CBL)   /*  427 */,
+            unchecked((long) 0x269FCD4403B87588L)   /*  428 */,    unchecked((long) 0x1B91F5F728BDD1E0L)   /*  429 */,
+            unchecked((long) 0xE4669F39040201F6L)   /*  430 */,    unchecked((long) 0x7A1D7C218CF04ADEL)   /*  431 */,
+            unchecked((long) 0x65623C29D79CE5CEL)   /*  432 */,    unchecked((long) 0x2368449096C00BB1L)   /*  433 */,
+            unchecked((long) 0xAB9BF1879DA503BAL)   /*  434 */,    unchecked((long) 0xBC23ECB1A458058EL)   /*  435 */,
+            unchecked((long) 0x9A58DF01BB401ECCL)   /*  436 */,    unchecked((long) 0xA070E868A85F143DL)   /*  437 */,
+            unchecked((long) 0x4FF188307DF2239EL)   /*  438 */,    unchecked((long) 0x14D565B41A641183L)   /*  439 */,
+            unchecked((long) 0xEE13337452701602L)   /*  440 */,    unchecked((long) 0x950E3DCF3F285E09L)   /*  441 */,
+            unchecked((long) 0x59930254B9C80953L)   /*  442 */,    unchecked((long) 0x3BF299408930DA6DL)   /*  443 */,
+            unchecked((long) 0xA955943F53691387L)   /*  444 */,    unchecked((long) 0xA15EDECAA9CB8784L)   /*  445 */,
+            unchecked((long) 0x29142127352BE9A0L)   /*  446 */,    unchecked((long) 0x76F0371FFF4E7AFBL)   /*  447 */,
+            unchecked((long) 0x0239F450274F2228L)   /*  448 */,    unchecked((long) 0xBB073AF01D5E868BL)   /*  449 */,
+            unchecked((long) 0xBFC80571C10E96C1L)   /*  450 */,    unchecked((long) 0xD267088568222E23L)   /*  451 */,
+            unchecked((long) 0x9671A3D48E80B5B0L)   /*  452 */,    unchecked((long) 0x55B5D38AE193BB81L)   /*  453 */,
+            unchecked((long) 0x693AE2D0A18B04B8L)   /*  454 */,    unchecked((long) 0x5C48B4ECADD5335FL)   /*  455 */,
+            unchecked((long) 0xFD743B194916A1CAL)   /*  456 */,    unchecked((long) 0x2577018134BE98C4L)   /*  457 */,
+            unchecked((long) 0xE77987E83C54A4ADL)   /*  458 */,    unchecked((long) 0x28E11014DA33E1B9L)   /*  459 */,
+            unchecked((long) 0x270CC59E226AA213L)   /*  460 */,    unchecked((long) 0x71495F756D1A5F60L)   /*  461 */,
+            unchecked((long) 0x9BE853FB60AFEF77L)   /*  462 */,    unchecked((long) 0xADC786A7F7443DBFL)   /*  463 */,
+            unchecked((long) 0x0904456173B29A82L)   /*  464 */,    unchecked((long) 0x58BC7A66C232BD5EL)   /*  465 */,
+            unchecked((long) 0xF306558C673AC8B2L)   /*  466 */,    unchecked((long) 0x41F639C6B6C9772AL)   /*  467 */,
+            unchecked((long) 0x216DEFE99FDA35DAL)   /*  468 */,    unchecked((long) 0x11640CC71C7BE615L)   /*  469 */,
+            unchecked((long) 0x93C43694565C5527L)   /*  470 */,    unchecked((long) 0xEA038E6246777839L)   /*  471 */,
+            unchecked((long) 0xF9ABF3CE5A3E2469L)   /*  472 */,    unchecked((long) 0x741E768D0FD312D2L)   /*  473 */,
+            unchecked((long) 0x0144B883CED652C6L)   /*  474 */,    unchecked((long) 0xC20B5A5BA33F8552L)   /*  475 */,
+            unchecked((long) 0x1AE69633C3435A9DL)   /*  476 */,    unchecked((long) 0x97A28CA4088CFDECL)   /*  477 */,
+            unchecked((long) 0x8824A43C1E96F420L)   /*  478 */,    unchecked((long) 0x37612FA66EEEA746L)   /*  479 */,
+            unchecked((long) 0x6B4CB165F9CF0E5AL)   /*  480 */,    unchecked((long) 0x43AA1C06A0ABFB4AL)   /*  481 */,
+            unchecked((long) 0x7F4DC26FF162796BL)   /*  482 */,    unchecked((long) 0x6CBACC8E54ED9B0FL)   /*  483 */,
+            unchecked((long) 0xA6B7FFEFD2BB253EL)   /*  484 */,    unchecked((long) 0x2E25BC95B0A29D4FL)   /*  485 */,
+            unchecked((long) 0x86D6A58BDEF1388CL)   /*  486 */,    unchecked((long) 0xDED74AC576B6F054L)   /*  487 */,
+            unchecked((long) 0x8030BDBC2B45805DL)   /*  488 */,    unchecked((long) 0x3C81AF70E94D9289L)   /*  489 */,
+            unchecked((long) 0x3EFF6DDA9E3100DBL)   /*  490 */,    unchecked((long) 0xB38DC39FDFCC8847L)   /*  491 */,
+            unchecked((long) 0x123885528D17B87EL)   /*  492 */,    unchecked((long) 0xF2DA0ED240B1B642L)   /*  493 */,
+            unchecked((long) 0x44CEFADCD54BF9A9L)   /*  494 */,    unchecked((long) 0x1312200E433C7EE6L)   /*  495 */,
+            unchecked((long) 0x9FFCC84F3A78C748L)   /*  496 */,    unchecked((long) 0xF0CD1F72248576BBL)   /*  497 */,
+            unchecked((long) 0xEC6974053638CFE4L)   /*  498 */,    unchecked((long) 0x2BA7B67C0CEC4E4CL)   /*  499 */,
+            unchecked((long) 0xAC2F4DF3E5CE32EDL)   /*  500 */,    unchecked((long) 0xCB33D14326EA4C11L)   /*  501 */,
+            unchecked((long) 0xA4E9044CC77E58BCL)   /*  502 */,    unchecked((long) 0x5F513293D934FCEFL)   /*  503 */,
+            unchecked((long) 0x5DC9645506E55444L)   /*  504 */,    unchecked((long) 0x50DE418F317DE40AL)   /*  505 */,
+            unchecked((long) 0x388CB31A69DDE259L)   /*  506 */,    unchecked((long) 0x2DB4A83455820A86L)   /*  507 */,
+            unchecked((long) 0x9010A91E84711AE9L)   /*  508 */,    unchecked((long) 0x4DF7F0B7B1498371L)   /*  509 */,
+            unchecked((long) 0xD62A2EABC0977179L)   /*  510 */,    unchecked((long) 0x22FAC097AA8D5C0EL)   /*  511 */,
+        };
+
+        private static readonly long[] t3 = {
+            unchecked((long) 0xF49FCC2FF1DAF39BL)   /*  512 */,    unchecked((long) 0x487FD5C66FF29281L)   /*  513 */,
+            unchecked((long) 0xE8A30667FCDCA83FL)   /*  514 */,    unchecked((long) 0x2C9B4BE3D2FCCE63L)   /*  515 */,
+            unchecked((long) 0xDA3FF74B93FBBBC2L)   /*  516 */,    unchecked((long) 0x2FA165D2FE70BA66L)   /*  517 */,
+            unchecked((long) 0xA103E279970E93D4L)   /*  518 */,    unchecked((long) 0xBECDEC77B0E45E71L)   /*  519 */,
+            unchecked((long) 0xCFB41E723985E497L)   /*  520 */,    unchecked((long) 0xB70AAA025EF75017L)   /*  521 */,
+            unchecked((long) 0xD42309F03840B8E0L)   /*  522 */,    unchecked((long) 0x8EFC1AD035898579L)   /*  523 */,
+            unchecked((long) 0x96C6920BE2B2ABC5L)   /*  524 */,    unchecked((long) 0x66AF4163375A9172L)   /*  525 */,
+            unchecked((long) 0x2174ABDCCA7127FBL)   /*  526 */,    unchecked((long) 0xB33CCEA64A72FF41L)   /*  527 */,
+            unchecked((long) 0xF04A4933083066A5L)   /*  528 */,    unchecked((long) 0x8D970ACDD7289AF5L)   /*  529 */,
+            unchecked((long) 0x8F96E8E031C8C25EL)   /*  530 */,    unchecked((long) 0xF3FEC02276875D47L)   /*  531 */,
+            unchecked((long) 0xEC7BF310056190DDL)   /*  532 */,    unchecked((long) 0xF5ADB0AEBB0F1491L)   /*  533 */,
+            unchecked((long) 0x9B50F8850FD58892L)   /*  534 */,    unchecked((long) 0x4975488358B74DE8L)   /*  535 */,
+            unchecked((long) 0xA3354FF691531C61L)   /*  536 */,    unchecked((long) 0x0702BBE481D2C6EEL)   /*  537 */,
+            unchecked((long) 0x89FB24057DEDED98L)   /*  538 */,    unchecked((long) 0xAC3075138596E902L)   /*  539 */,
+            unchecked((long) 0x1D2D3580172772EDL)   /*  540 */,    unchecked((long) 0xEB738FC28E6BC30DL)   /*  541 */,
+            unchecked((long) 0x5854EF8F63044326L)   /*  542 */,    unchecked((long) 0x9E5C52325ADD3BBEL)   /*  543 */,
+            unchecked((long) 0x90AA53CF325C4623L)   /*  544 */,    unchecked((long) 0xC1D24D51349DD067L)   /*  545 */,
+            unchecked((long) 0x2051CFEEA69EA624L)   /*  546 */,    unchecked((long) 0x13220F0A862E7E4FL)   /*  547 */,
+            unchecked((long) 0xCE39399404E04864L)   /*  548 */,    unchecked((long) 0xD9C42CA47086FCB7L)   /*  549 */,
+            unchecked((long) 0x685AD2238A03E7CCL)   /*  550 */,    unchecked((long) 0x066484B2AB2FF1DBL)   /*  551 */,
+            unchecked((long) 0xFE9D5D70EFBF79ECL)   /*  552 */,    unchecked((long) 0x5B13B9DD9C481854L)   /*  553 */,
+            unchecked((long) 0x15F0D475ED1509ADL)   /*  554 */,    unchecked((long) 0x0BEBCD060EC79851L)   /*  555 */,
+            unchecked((long) 0xD58C6791183AB7F8L)   /*  556 */,    unchecked((long) 0xD1187C5052F3EEE4L)   /*  557 */,
+            unchecked((long) 0xC95D1192E54E82FFL)   /*  558 */,    unchecked((long) 0x86EEA14CB9AC6CA2L)   /*  559 */,
+            unchecked((long) 0x3485BEB153677D5DL)   /*  560 */,    unchecked((long) 0xDD191D781F8C492AL)   /*  561 */,
+            unchecked((long) 0xF60866BAA784EBF9L)   /*  562 */,    unchecked((long) 0x518F643BA2D08C74L)   /*  563 */,
+            unchecked((long) 0x8852E956E1087C22L)   /*  564 */,    unchecked((long) 0xA768CB8DC410AE8DL)   /*  565 */,
+            unchecked((long) 0x38047726BFEC8E1AL)   /*  566 */,    unchecked((long) 0xA67738B4CD3B45AAL)   /*  567 */,
+            unchecked((long) 0xAD16691CEC0DDE19L)   /*  568 */,    unchecked((long) 0xC6D4319380462E07L)   /*  569 */,
+            unchecked((long) 0xC5A5876D0BA61938L)   /*  570 */,    unchecked((long) 0x16B9FA1FA58FD840L)   /*  571 */,
+            unchecked((long) 0x188AB1173CA74F18L)   /*  572 */,    unchecked((long) 0xABDA2F98C99C021FL)   /*  573 */,
+            unchecked((long) 0x3E0580AB134AE816L)   /*  574 */,    unchecked((long) 0x5F3B05B773645ABBL)   /*  575 */,
+            unchecked((long) 0x2501A2BE5575F2F6L)   /*  576 */,    unchecked((long) 0x1B2F74004E7E8BA9L)   /*  577 */,
+            unchecked((long) 0x1CD7580371E8D953L)   /*  578 */,    unchecked((long) 0x7F6ED89562764E30L)   /*  579 */,
+            unchecked((long) 0xB15926FF596F003DL)   /*  580 */,    unchecked((long) 0x9F65293DA8C5D6B9L)   /*  581 */,
+            unchecked((long) 0x6ECEF04DD690F84CL)   /*  582 */,    unchecked((long) 0x4782275FFF33AF88L)   /*  583 */,
+            unchecked((long) 0xE41433083F820801L)   /*  584 */,    unchecked((long) 0xFD0DFE409A1AF9B5L)   /*  585 */,
+            unchecked((long) 0x4325A3342CDB396BL)   /*  586 */,    unchecked((long) 0x8AE77E62B301B252L)   /*  587 */,
+            unchecked((long) 0xC36F9E9F6655615AL)   /*  588 */,    unchecked((long) 0x85455A2D92D32C09L)   /*  589 */,
+            unchecked((long) 0xF2C7DEA949477485L)   /*  590 */,    unchecked((long) 0x63CFB4C133A39EBAL)   /*  591 */,
+            unchecked((long) 0x83B040CC6EBC5462L)   /*  592 */,    unchecked((long) 0x3B9454C8FDB326B0L)   /*  593 */,
+            unchecked((long) 0x56F56A9E87FFD78CL)   /*  594 */,    unchecked((long) 0x2DC2940D99F42BC6L)   /*  595 */,
+            unchecked((long) 0x98F7DF096B096E2DL)   /*  596 */,    unchecked((long) 0x19A6E01E3AD852BFL)   /*  597 */,
+            unchecked((long) 0x42A99CCBDBD4B40BL)   /*  598 */,    unchecked((long) 0xA59998AF45E9C559L)   /*  599 */,
+            unchecked((long) 0x366295E807D93186L)   /*  600 */,    unchecked((long) 0x6B48181BFAA1F773L)   /*  601 */,
+            unchecked((long) 0x1FEC57E2157A0A1DL)   /*  602 */,    unchecked((long) 0x4667446AF6201AD5L)   /*  603 */,
+            unchecked((long) 0xE615EBCACFB0F075L)   /*  604 */,    unchecked((long) 0xB8F31F4F68290778L)   /*  605 */,
+            unchecked((long) 0x22713ED6CE22D11EL)   /*  606 */,    unchecked((long) 0x3057C1A72EC3C93BL)   /*  607 */,
+            unchecked((long) 0xCB46ACC37C3F1F2FL)   /*  608 */,    unchecked((long) 0xDBB893FD02AAF50EL)   /*  609 */,
+            unchecked((long) 0x331FD92E600B9FCFL)   /*  610 */,    unchecked((long) 0xA498F96148EA3AD6L)   /*  611 */,
+            unchecked((long) 0xA8D8426E8B6A83EAL)   /*  612 */,    unchecked((long) 0xA089B274B7735CDCL)   /*  613 */,
+            unchecked((long) 0x87F6B3731E524A11L)   /*  614 */,    unchecked((long) 0x118808E5CBC96749L)   /*  615 */,
+            unchecked((long) 0x9906E4C7B19BD394L)   /*  616 */,    unchecked((long) 0xAFED7F7E9B24A20CL)   /*  617 */,
+            unchecked((long) 0x6509EADEEB3644A7L)   /*  618 */,    unchecked((long) 0x6C1EF1D3E8EF0EDEL)   /*  619 */,
+            unchecked((long) 0xB9C97D43E9798FB4L)   /*  620 */,    unchecked((long) 0xA2F2D784740C28A3L)   /*  621 */,
+            unchecked((long) 0x7B8496476197566FL)   /*  622 */,    unchecked((long) 0x7A5BE3E6B65F069DL)   /*  623 */,
+            unchecked((long) 0xF96330ED78BE6F10L)   /*  624 */,    unchecked((long) 0xEEE60DE77A076A15L)   /*  625 */,
+            unchecked((long) 0x2B4BEE4AA08B9BD0L)   /*  626 */,    unchecked((long) 0x6A56A63EC7B8894EL)   /*  627 */,
+            unchecked((long) 0x02121359BA34FEF4L)   /*  628 */,    unchecked((long) 0x4CBF99F8283703FCL)   /*  629 */,
+            unchecked((long) 0x398071350CAF30C8L)   /*  630 */,    unchecked((long) 0xD0A77A89F017687AL)   /*  631 */,
+            unchecked((long) 0xF1C1A9EB9E423569L)   /*  632 */,    unchecked((long) 0x8C7976282DEE8199L)   /*  633 */,
+            unchecked((long) 0x5D1737A5DD1F7ABDL)   /*  634 */,    unchecked((long) 0x4F53433C09A9FA80L)   /*  635 */,
+            unchecked((long) 0xFA8B0C53DF7CA1D9L)   /*  636 */,    unchecked((long) 0x3FD9DCBC886CCB77L)   /*  637 */,
+            unchecked((long) 0xC040917CA91B4720L)   /*  638 */,    unchecked((long) 0x7DD00142F9D1DCDFL)   /*  639 */,
+            unchecked((long) 0x8476FC1D4F387B58L)   /*  640 */,    unchecked((long) 0x23F8E7C5F3316503L)   /*  641 */,
+            unchecked((long) 0x032A2244E7E37339L)   /*  642 */,    unchecked((long) 0x5C87A5D750F5A74BL)   /*  643 */,
+            unchecked((long) 0x082B4CC43698992EL)   /*  644 */,    unchecked((long) 0xDF917BECB858F63CL)   /*  645 */,
+            unchecked((long) 0x3270B8FC5BF86DDAL)   /*  646 */,    unchecked((long) 0x10AE72BB29B5DD76L)   /*  647 */,
+            unchecked((long) 0x576AC94E7700362BL)   /*  648 */,    unchecked((long) 0x1AD112DAC61EFB8FL)   /*  649 */,
+            unchecked((long) 0x691BC30EC5FAA427L)   /*  650 */,    unchecked((long) 0xFF246311CC327143L)   /*  651 */,
+            unchecked((long) 0x3142368E30E53206L)   /*  652 */,    unchecked((long) 0x71380E31E02CA396L)   /*  653 */,
+            unchecked((long) 0x958D5C960AAD76F1L)   /*  654 */,    unchecked((long) 0xF8D6F430C16DA536L)   /*  655 */,
+            unchecked((long) 0xC8FFD13F1BE7E1D2L)   /*  656 */,    unchecked((long) 0x7578AE66004DDBE1L)   /*  657 */,
+            unchecked((long) 0x05833F01067BE646L)   /*  658 */,    unchecked((long) 0xBB34B5AD3BFE586DL)   /*  659 */,
+            unchecked((long) 0x095F34C9A12B97F0L)   /*  660 */,    unchecked((long) 0x247AB64525D60CA8L)   /*  661 */,
+            unchecked((long) 0xDCDBC6F3017477D1L)   /*  662 */,    unchecked((long) 0x4A2E14D4DECAD24DL)   /*  663 */,
+            unchecked((long) 0xBDB5E6D9BE0A1EEBL)   /*  664 */,    unchecked((long) 0x2A7E70F7794301ABL)   /*  665 */,
+            unchecked((long) 0xDEF42D8A270540FDL)   /*  666 */,    unchecked((long) 0x01078EC0A34C22C1L)   /*  667 */,
+            unchecked((long) 0xE5DE511AF4C16387L)   /*  668 */,    unchecked((long) 0x7EBB3A52BD9A330AL)   /*  669 */,
+            unchecked((long) 0x77697857AA7D6435L)   /*  670 */,    unchecked((long) 0x004E831603AE4C32L)   /*  671 */,
+            unchecked((long) 0xE7A21020AD78E312L)   /*  672 */,    unchecked((long) 0x9D41A70C6AB420F2L)   /*  673 */,
+            unchecked((long) 0x28E06C18EA1141E6L)   /*  674 */,    unchecked((long) 0xD2B28CBD984F6B28L)   /*  675 */,
+            unchecked((long) 0x26B75F6C446E9D83L)   /*  676 */,    unchecked((long) 0xBA47568C4D418D7FL)   /*  677 */,
+            unchecked((long) 0xD80BADBFE6183D8EL)   /*  678 */,    unchecked((long) 0x0E206D7F5F166044L)   /*  679 */,
+            unchecked((long) 0xE258A43911CBCA3EL)   /*  680 */,    unchecked((long) 0x723A1746B21DC0BCL)   /*  681 */,
+            unchecked((long) 0xC7CAA854F5D7CDD3L)   /*  682 */,    unchecked((long) 0x7CAC32883D261D9CL)   /*  683 */,
+            unchecked((long) 0x7690C26423BA942CL)   /*  684 */,    unchecked((long) 0x17E55524478042B8L)   /*  685 */,
+            unchecked((long) 0xE0BE477656A2389FL)   /*  686 */,    unchecked((long) 0x4D289B5E67AB2DA0L)   /*  687 */,
+            unchecked((long) 0x44862B9C8FBBFD31L)   /*  688 */,    unchecked((long) 0xB47CC8049D141365L)   /*  689 */,
+            unchecked((long) 0x822C1B362B91C793L)   /*  690 */,    unchecked((long) 0x4EB14655FB13DFD8L)   /*  691 */,
+            unchecked((long) 0x1ECBBA0714E2A97BL)   /*  692 */,    unchecked((long) 0x6143459D5CDE5F14L)   /*  693 */,
+            unchecked((long) 0x53A8FBF1D5F0AC89L)   /*  694 */,    unchecked((long) 0x97EA04D81C5E5B00L)   /*  695 */,
+            unchecked((long) 0x622181A8D4FDB3F3L)   /*  696 */,    unchecked((long) 0xE9BCD341572A1208L)   /*  697 */,
+            unchecked((long) 0x1411258643CCE58AL)   /*  698 */,    unchecked((long) 0x9144C5FEA4C6E0A4L)   /*  699 */,
+            unchecked((long) 0x0D33D06565CF620FL)   /*  700 */,    unchecked((long) 0x54A48D489F219CA1L)   /*  701 */,
+            unchecked((long) 0xC43E5EAC6D63C821L)   /*  702 */,    unchecked((long) 0xA9728B3A72770DAFL)   /*  703 */,
+            unchecked((long) 0xD7934E7B20DF87EFL)   /*  704 */,    unchecked((long) 0xE35503B61A3E86E5L)   /*  705 */,
+            unchecked((long) 0xCAE321FBC819D504L)   /*  706 */,    unchecked((long) 0x129A50B3AC60BFA6L)   /*  707 */,
+            unchecked((long) 0xCD5E68EA7E9FB6C3L)   /*  708 */,    unchecked((long) 0xB01C90199483B1C7L)   /*  709 */,
+            unchecked((long) 0x3DE93CD5C295376CL)   /*  710 */,    unchecked((long) 0xAED52EDF2AB9AD13L)   /*  711 */,
+            unchecked((long) 0x2E60F512C0A07884L)   /*  712 */,    unchecked((long) 0xBC3D86A3E36210C9L)   /*  713 */,
+            unchecked((long) 0x35269D9B163951CEL)   /*  714 */,    unchecked((long) 0x0C7D6E2AD0CDB5FAL)   /*  715 */,
+            unchecked((long) 0x59E86297D87F5733L)   /*  716 */,    unchecked((long) 0x298EF221898DB0E7L)   /*  717 */,
+            unchecked((long) 0x55000029D1A5AA7EL)   /*  718 */,    unchecked((long) 0x8BC08AE1B5061B45L)   /*  719 */,
+            unchecked((long) 0xC2C31C2B6C92703AL)   /*  720 */,    unchecked((long) 0x94CC596BAF25EF42L)   /*  721 */,
+            unchecked((long) 0x0A1D73DB22540456L)   /*  722 */,    unchecked((long) 0x04B6A0F9D9C4179AL)   /*  723 */,
+            unchecked((long) 0xEFFDAFA2AE3D3C60L)   /*  724 */,    unchecked((long) 0xF7C8075BB49496C4L)   /*  725 */,
+            unchecked((long) 0x9CC5C7141D1CD4E3L)   /*  726 */,    unchecked((long) 0x78BD1638218E5534L)   /*  727 */,
+            unchecked((long) 0xB2F11568F850246AL)   /*  728 */,    unchecked((long) 0xEDFABCFA9502BC29L)   /*  729 */,
+            unchecked((long) 0x796CE5F2DA23051BL)   /*  730 */,    unchecked((long) 0xAAE128B0DC93537CL)   /*  731 */,
+            unchecked((long) 0x3A493DA0EE4B29AEL)   /*  732 */,    unchecked((long) 0xB5DF6B2C416895D7L)   /*  733 */,
+            unchecked((long) 0xFCABBD25122D7F37L)   /*  734 */,    unchecked((long) 0x70810B58105DC4B1L)   /*  735 */,
+            unchecked((long) 0xE10FDD37F7882A90L)   /*  736 */,    unchecked((long) 0x524DCAB5518A3F5CL)   /*  737 */,
+            unchecked((long) 0x3C9E85878451255BL)   /*  738 */,    unchecked((long) 0x4029828119BD34E2L)   /*  739 */,
+            unchecked((long) 0x74A05B6F5D3CECCBL)   /*  740 */,    unchecked((long) 0xB610021542E13ECAL)   /*  741 */,
+            unchecked((long) 0x0FF979D12F59E2ACL)   /*  742 */,    unchecked((long) 0x6037DA27E4F9CC50L)   /*  743 */,
+            unchecked((long) 0x5E92975A0DF1847DL)   /*  744 */,    unchecked((long) 0xD66DE190D3E623FEL)   /*  745 */,
+            unchecked((long) 0x5032D6B87B568048L)   /*  746 */,    unchecked((long) 0x9A36B7CE8235216EL)   /*  747 */,
+            unchecked((long) 0x80272A7A24F64B4AL)   /*  748 */,    unchecked((long) 0x93EFED8B8C6916F7L)   /*  749 */,
+            unchecked((long) 0x37DDBFF44CCE1555L)   /*  750 */,    unchecked((long) 0x4B95DB5D4B99BD25L)   /*  751 */,
+            unchecked((long) 0x92D3FDA169812FC0L)   /*  752 */,    unchecked((long) 0xFB1A4A9A90660BB6L)   /*  753 */,
+            unchecked((long) 0x730C196946A4B9B2L)   /*  754 */,    unchecked((long) 0x81E289AA7F49DA68L)   /*  755 */,
+            unchecked((long) 0x64669A0F83B1A05FL)   /*  756 */,    unchecked((long) 0x27B3FF7D9644F48BL)   /*  757 */,
+            unchecked((long) 0xCC6B615C8DB675B3L)   /*  758 */,    unchecked((long) 0x674F20B9BCEBBE95L)   /*  759 */,
+            unchecked((long) 0x6F31238275655982L)   /*  760 */,    unchecked((long) 0x5AE488713E45CF05L)   /*  761 */,
+            unchecked((long) 0xBF619F9954C21157L)   /*  762 */,    unchecked((long) 0xEABAC46040A8EAE9L)   /*  763 */,
+            unchecked((long) 0x454C6FE9F2C0C1CDL)   /*  764 */,    unchecked((long) 0x419CF6496412691CL)   /*  765 */,
+            unchecked((long) 0xD3DC3BEF265B0F70L)   /*  766 */,    unchecked((long) 0x6D0E60F5C3578A9EL)   /*  767 */,
+        };
+
+        private static readonly long[] t4 = {
+            unchecked((long) 0x5B0E608526323C55L)   /*  768 */,    unchecked((long) 0x1A46C1A9FA1B59F5L)   /*  769 */,
+            unchecked((long) 0xA9E245A17C4C8FFAL)   /*  770 */,    unchecked((long) 0x65CA5159DB2955D7L)   /*  771 */,
+            unchecked((long) 0x05DB0A76CE35AFC2L)   /*  772 */,    unchecked((long) 0x81EAC77EA9113D45L)   /*  773 */,
+            unchecked((long) 0x528EF88AB6AC0A0DL)   /*  774 */,    unchecked((long) 0xA09EA253597BE3FFL)   /*  775 */,
+            unchecked((long) 0x430DDFB3AC48CD56L)   /*  776 */,    unchecked((long) 0xC4B3A67AF45CE46FL)   /*  777 */,
+            unchecked((long) 0x4ECECFD8FBE2D05EL)   /*  778 */,    unchecked((long) 0x3EF56F10B39935F0L)   /*  779 */,
+            unchecked((long) 0x0B22D6829CD619C6L)   /*  780 */,    unchecked((long) 0x17FD460A74DF2069L)   /*  781 */,
+            unchecked((long) 0x6CF8CC8E8510ED40L)   /*  782 */,    unchecked((long) 0xD6C824BF3A6ECAA7L)   /*  783 */,
+            unchecked((long) 0x61243D581A817049L)   /*  784 */,    unchecked((long) 0x048BACB6BBC163A2L)   /*  785 */,
+            unchecked((long) 0xD9A38AC27D44CC32L)   /*  786 */,    unchecked((long) 0x7FDDFF5BAAF410ABL)   /*  787 */,
+            unchecked((long) 0xAD6D495AA804824BL)   /*  788 */,    unchecked((long) 0xE1A6A74F2D8C9F94L)   /*  789 */,
+            unchecked((long) 0xD4F7851235DEE8E3L)   /*  790 */,    unchecked((long) 0xFD4B7F886540D893L)   /*  791 */,
+            unchecked((long) 0x247C20042AA4BFDAL)   /*  792 */,    unchecked((long) 0x096EA1C517D1327CL)   /*  793 */,
+            unchecked((long) 0xD56966B4361A6685L)   /*  794 */,    unchecked((long) 0x277DA5C31221057DL)   /*  795 */,
+            unchecked((long) 0x94D59893A43ACFF7L)   /*  796 */,    unchecked((long) 0x64F0C51CCDC02281L)   /*  797 */,
+            unchecked((long) 0x3D33BCC4FF6189DBL)   /*  798 */,    unchecked((long) 0xE005CB184CE66AF1L)   /*  799 */,
+            unchecked((long) 0xFF5CCD1D1DB99BEAL)   /*  800 */,    unchecked((long) 0xB0B854A7FE42980FL)   /*  801 */,
+            unchecked((long) 0x7BD46A6A718D4B9FL)   /*  802 */,    unchecked((long) 0xD10FA8CC22A5FD8CL)   /*  803 */,
+            unchecked((long) 0xD31484952BE4BD31L)   /*  804 */,    unchecked((long) 0xC7FA975FCB243847L)   /*  805 */,
+            unchecked((long) 0x4886ED1E5846C407L)   /*  806 */,    unchecked((long) 0x28CDDB791EB70B04L)   /*  807 */,
+            unchecked((long) 0xC2B00BE2F573417FL)   /*  808 */,    unchecked((long) 0x5C9590452180F877L)   /*  809 */,
+            unchecked((long) 0x7A6BDDFFF370EB00L)   /*  810 */,    unchecked((long) 0xCE509E38D6D9D6A4L)   /*  811 */,
+            unchecked((long) 0xEBEB0F00647FA702L)   /*  812 */,    unchecked((long) 0x1DCC06CF76606F06L)   /*  813 */,
+            unchecked((long) 0xE4D9F28BA286FF0AL)   /*  814 */,    unchecked((long) 0xD85A305DC918C262L)   /*  815 */,
+            unchecked((long) 0x475B1D8732225F54L)   /*  816 */,    unchecked((long) 0x2D4FB51668CCB5FEL)   /*  817 */,
+            unchecked((long) 0xA679B9D9D72BBA20L)   /*  818 */,    unchecked((long) 0x53841C0D912D43A5L)   /*  819 */,
+            unchecked((long) 0x3B7EAA48BF12A4E8L)   /*  820 */,    unchecked((long) 0x781E0E47F22F1DDFL)   /*  821 */,
+            unchecked((long) 0xEFF20CE60AB50973L)   /*  822 */,    unchecked((long) 0x20D261D19DFFB742L)   /*  823 */,
+            unchecked((long) 0x16A12B03062A2E39L)   /*  824 */,    unchecked((long) 0x1960EB2239650495L)   /*  825 */,
+            unchecked((long) 0x251C16FED50EB8B8L)   /*  826 */,    unchecked((long) 0x9AC0C330F826016EL)   /*  827 */,
+            unchecked((long) 0xED152665953E7671L)   /*  828 */,    unchecked((long) 0x02D63194A6369570L)   /*  829 */,
+            unchecked((long) 0x5074F08394B1C987L)   /*  830 */,    unchecked((long) 0x70BA598C90B25CE1L)   /*  831 */,
+            unchecked((long) 0x794A15810B9742F6L)   /*  832 */,    unchecked((long) 0x0D5925E9FCAF8C6CL)   /*  833 */,
+            unchecked((long) 0x3067716CD868744EL)   /*  834 */,    unchecked((long) 0x910AB077E8D7731BL)   /*  835 */,
+            unchecked((long) 0x6A61BBDB5AC42F61L)   /*  836 */,    unchecked((long) 0x93513EFBF0851567L)   /*  837 */,
+            unchecked((long) 0xF494724B9E83E9D5L)   /*  838 */,    unchecked((long) 0xE887E1985C09648DL)   /*  839 */,
+            unchecked((long) 0x34B1D3C675370CFDL)   /*  840 */,    unchecked((long) 0xDC35E433BC0D255DL)   /*  841 */,
+            unchecked((long) 0xD0AAB84234131BE0L)   /*  842 */,    unchecked((long) 0x08042A50B48B7EAFL)   /*  843 */,
+            unchecked((long) 0x9997C4EE44A3AB35L)   /*  844 */,    unchecked((long) 0x829A7B49201799D0L)   /*  845 */,
+            unchecked((long) 0x263B8307B7C54441L)   /*  846 */,    unchecked((long) 0x752F95F4FD6A6CA6L)   /*  847 */,
+            unchecked((long) 0x927217402C08C6E5L)   /*  848 */,    unchecked((long) 0x2A8AB754A795D9EEL)   /*  849 */,
+            unchecked((long) 0xA442F7552F72943DL)   /*  850 */,    unchecked((long) 0x2C31334E19781208L)   /*  851 */,
+            unchecked((long) 0x4FA98D7CEAEE6291L)   /*  852 */,    unchecked((long) 0x55C3862F665DB309L)   /*  853 */,
+            unchecked((long) 0xBD0610175D53B1F3L)   /*  854 */,    unchecked((long) 0x46FE6CB840413F27L)   /*  855 */,
+            unchecked((long) 0x3FE03792DF0CFA59L)   /*  856 */,    unchecked((long) 0xCFE700372EB85E8FL)   /*  857 */,
+            unchecked((long) 0xA7BE29E7ADBCE118L)   /*  858 */,    unchecked((long) 0xE544EE5CDE8431DDL)   /*  859 */,
+            unchecked((long) 0x8A781B1B41F1873EL)   /*  860 */,    unchecked((long) 0xA5C94C78A0D2F0E7L)   /*  861 */,
+            unchecked((long) 0x39412E2877B60728L)   /*  862 */,    unchecked((long) 0xA1265EF3AFC9A62CL)   /*  863 */,
+            unchecked((long) 0xBCC2770C6A2506C5L)   /*  864 */,    unchecked((long) 0x3AB66DD5DCE1CE12L)   /*  865 */,
+            unchecked((long) 0xE65499D04A675B37L)   /*  866 */,    unchecked((long) 0x7D8F523481BFD216L)   /*  867 */,
+            unchecked((long) 0x0F6F64FCEC15F389L)   /*  868 */,    unchecked((long) 0x74EFBE618B5B13C8L)   /*  869 */,
+            unchecked((long) 0xACDC82B714273E1DL)   /*  870 */,    unchecked((long) 0xDD40BFE003199D17L)   /*  871 */,
+            unchecked((long) 0x37E99257E7E061F8L)   /*  872 */,    unchecked((long) 0xFA52626904775AAAL)   /*  873 */,
+            unchecked((long) 0x8BBBF63A463D56F9L)   /*  874 */,    unchecked((long) 0xF0013F1543A26E64L)   /*  875 */,
+            unchecked((long) 0xA8307E9F879EC898L)   /*  876 */,    unchecked((long) 0xCC4C27A4150177CCL)   /*  877 */,
+            unchecked((long) 0x1B432F2CCA1D3348L)   /*  878 */,    unchecked((long) 0xDE1D1F8F9F6FA013L)   /*  879 */,
+            unchecked((long) 0x606602A047A7DDD6L)   /*  880 */,    unchecked((long) 0xD237AB64CC1CB2C7L)   /*  881 */,
+            unchecked((long) 0x9B938E7225FCD1D3L)   /*  882 */,    unchecked((long) 0xEC4E03708E0FF476L)   /*  883 */,
+            unchecked((long) 0xFEB2FBDA3D03C12DL)   /*  884 */,    unchecked((long) 0xAE0BCED2EE43889AL)   /*  885 */,
+            unchecked((long) 0x22CB8923EBFB4F43L)   /*  886 */,    unchecked((long) 0x69360D013CF7396DL)   /*  887 */,
+            unchecked((long) 0x855E3602D2D4E022L)   /*  888 */,    unchecked((long) 0x073805BAD01F784CL)   /*  889 */,
+            unchecked((long) 0x33E17A133852F546L)   /*  890 */,    unchecked((long) 0xDF4874058AC7B638L)   /*  891 */,
+            unchecked((long) 0xBA92B29C678AA14AL)   /*  892 */,    unchecked((long) 0x0CE89FC76CFAADCDL)   /*  893 */,
+            unchecked((long) 0x5F9D4E0908339E34L)   /*  894 */,    unchecked((long) 0xF1AFE9291F5923B9L)   /*  895 */,
+            unchecked((long) 0x6E3480F60F4A265FL)   /*  896 */,    unchecked((long) 0xEEBF3A2AB29B841CL)   /*  897 */,
+            unchecked((long) 0xE21938A88F91B4ADL)   /*  898 */,    unchecked((long) 0x57DFEFF845C6D3C3L)   /*  899 */,
+            unchecked((long) 0x2F006B0BF62CAAF2L)   /*  900 */,    unchecked((long) 0x62F479EF6F75EE78L)   /*  901 */,
+            unchecked((long) 0x11A55AD41C8916A9L)   /*  902 */,    unchecked((long) 0xF229D29084FED453L)   /*  903 */,
+            unchecked((long) 0x42F1C27B16B000E6L)   /*  904 */,    unchecked((long) 0x2B1F76749823C074L)   /*  905 */,
+            unchecked((long) 0x4B76ECA3C2745360L)   /*  906 */,    unchecked((long) 0x8C98F463B91691BDL)   /*  907 */,
+            unchecked((long) 0x14BCC93CF1ADE66AL)   /*  908 */,    unchecked((long) 0x8885213E6D458397L)   /*  909 */,
+            unchecked((long) 0x8E177DF0274D4711L)   /*  910 */,    unchecked((long) 0xB49B73B5503F2951L)   /*  911 */,
+            unchecked((long) 0x10168168C3F96B6BL)   /*  912 */,    unchecked((long) 0x0E3D963B63CAB0AEL)   /*  913 */,
+            unchecked((long) 0x8DFC4B5655A1DB14L)   /*  914 */,    unchecked((long) 0xF789F1356E14DE5CL)   /*  915 */,
+            unchecked((long) 0x683E68AF4E51DAC1L)   /*  916 */,    unchecked((long) 0xC9A84F9D8D4B0FD9L)   /*  917 */,
+            unchecked((long) 0x3691E03F52A0F9D1L)   /*  918 */,    unchecked((long) 0x5ED86E46E1878E80L)   /*  919 */,
+            unchecked((long) 0x3C711A0E99D07150L)   /*  920 */,    unchecked((long) 0x5A0865B20C4E9310L)   /*  921 */,
+            unchecked((long) 0x56FBFC1FE4F0682EL)   /*  922 */,    unchecked((long) 0xEA8D5DE3105EDF9BL)   /*  923 */,
+            unchecked((long) 0x71ABFDB12379187AL)   /*  924 */,    unchecked((long) 0x2EB99DE1BEE77B9CL)   /*  925 */,
+            unchecked((long) 0x21ECC0EA33CF4523L)   /*  926 */,    unchecked((long) 0x59A4D7521805C7A1L)   /*  927 */,
+            unchecked((long) 0x3896F5EB56AE7C72L)   /*  928 */,    unchecked((long) 0xAA638F3DB18F75DCL)   /*  929 */,
+            unchecked((long) 0x9F39358DABE9808EL)   /*  930 */,    unchecked((long) 0xB7DEFA91C00B72ACL)   /*  931 */,
+            unchecked((long) 0x6B5541FD62492D92L)   /*  932 */,    unchecked((long) 0x6DC6DEE8F92E4D5BL)   /*  933 */,
+            unchecked((long) 0x353F57ABC4BEEA7EL)   /*  934 */,    unchecked((long) 0x735769D6DA5690CEL)   /*  935 */,
+            unchecked((long) 0x0A234AA642391484L)   /*  936 */,    unchecked((long) 0xF6F9508028F80D9DL)   /*  937 */,
+            unchecked((long) 0xB8E319A27AB3F215L)   /*  938 */,    unchecked((long) 0x31AD9C1151341A4DL)   /*  939 */,
+            unchecked((long) 0x773C22A57BEF5805L)   /*  940 */,    unchecked((long) 0x45C7561A07968633L)   /*  941 */,
+            unchecked((long) 0xF913DA9E249DBE36L)   /*  942 */,    unchecked((long) 0xDA652D9B78A64C68L)   /*  943 */,
+            unchecked((long) 0x4C27A97F3BC334EFL)   /*  944 */,    unchecked((long) 0x76621220E66B17F4L)   /*  945 */,
+            unchecked((long) 0x967743899ACD7D0BL)   /*  946 */,    unchecked((long) 0xF3EE5BCAE0ED6782L)   /*  947 */,
+            unchecked((long) 0x409F753600C879FCL)   /*  948 */,    unchecked((long) 0x06D09A39B5926DB6L)   /*  949 */,
+            unchecked((long) 0x6F83AEB0317AC588L)   /*  950 */,    unchecked((long) 0x01E6CA4A86381F21L)   /*  951 */,
+            unchecked((long) 0x66FF3462D19F3025L)   /*  952 */,    unchecked((long) 0x72207C24DDFD3BFBL)   /*  953 */,
+            unchecked((long) 0x4AF6B6D3E2ECE2EBL)   /*  954 */,    unchecked((long) 0x9C994DBEC7EA08DEL)   /*  955 */,
+            unchecked((long) 0x49ACE597B09A8BC4L)   /*  956 */,    unchecked((long) 0xB38C4766CF0797BAL)   /*  957 */,
+            unchecked((long) 0x131B9373C57C2A75L)   /*  958 */,    unchecked((long) 0xB1822CCE61931E58L)   /*  959 */,
+            unchecked((long) 0x9D7555B909BA1C0CL)   /*  960 */,    unchecked((long) 0x127FAFDD937D11D2L)   /*  961 */,
+            unchecked((long) 0x29DA3BADC66D92E4L)   /*  962 */,    unchecked((long) 0xA2C1D57154C2ECBCL)   /*  963 */,
+            unchecked((long) 0x58C5134D82F6FE24L)   /*  964 */,    unchecked((long) 0x1C3AE3515B62274FL)   /*  965 */,
+            unchecked((long) 0xE907C82E01CB8126L)   /*  966 */,    unchecked((long) 0xF8ED091913E37FCBL)   /*  967 */,
+            unchecked((long) 0x3249D8F9C80046C9L)   /*  968 */,    unchecked((long) 0x80CF9BEDE388FB63L)   /*  969 */,
+            unchecked((long) 0x1881539A116CF19EL)   /*  970 */,    unchecked((long) 0x5103F3F76BD52457L)   /*  971 */,
+            unchecked((long) 0x15B7E6F5AE47F7A8L)   /*  972 */,    unchecked((long) 0xDBD7C6DED47E9CCFL)   /*  973 */,
+            unchecked((long) 0x44E55C410228BB1AL)   /*  974 */,    unchecked((long) 0xB647D4255EDB4E99L)   /*  975 */,
+            unchecked((long) 0x5D11882BB8AAFC30L)   /*  976 */,    unchecked((long) 0xF5098BBB29D3212AL)   /*  977 */,
+            unchecked((long) 0x8FB5EA14E90296B3L)   /*  978 */,    unchecked((long) 0x677B942157DD025AL)   /*  979 */,
+            unchecked((long) 0xFB58E7C0A390ACB5L)   /*  980 */,    unchecked((long) 0x89D3674C83BD4A01L)   /*  981 */,
+            unchecked((long) 0x9E2DA4DF4BF3B93BL)   /*  982 */,    unchecked((long) 0xFCC41E328CAB4829L)   /*  983 */,
+            unchecked((long) 0x03F38C96BA582C52L)   /*  984 */,    unchecked((long) 0xCAD1BDBD7FD85DB2L)   /*  985 */,
+            unchecked((long) 0xBBB442C16082AE83L)   /*  986 */,    unchecked((long) 0xB95FE86BA5DA9AB0L)   /*  987 */,
+            unchecked((long) 0xB22E04673771A93FL)   /*  988 */,    unchecked((long) 0x845358C9493152D8L)   /*  989 */,
+            unchecked((long) 0xBE2A488697B4541EL)   /*  990 */,    unchecked((long) 0x95A2DC2DD38E6966L)   /*  991 */,
+            unchecked((long) 0xC02C11AC923C852BL)   /*  992 */,    unchecked((long) 0x2388B1990DF2A87BL)   /*  993 */,
+            unchecked((long) 0x7C8008FA1B4F37BEL)   /*  994 */,    unchecked((long) 0x1F70D0C84D54E503L)   /*  995 */,
+            unchecked((long) 0x5490ADEC7ECE57D4L)   /*  996 */,    unchecked((long) 0x002B3C27D9063A3AL)   /*  997 */,
+            unchecked((long) 0x7EAEA3848030A2BFL)   /*  998 */,    unchecked((long) 0xC602326DED2003C0L)   /*  999 */,
+            unchecked((long) 0x83A7287D69A94086L)   /* 1000 */,    unchecked((long) 0xC57A5FCB30F57A8AL)   /* 1001 */,
+            unchecked((long) 0xB56844E479EBE779L)   /* 1002 */,    unchecked((long) 0xA373B40F05DCBCE9L)   /* 1003 */,
+            unchecked((long) 0xD71A786E88570EE2L)   /* 1004 */,    unchecked((long) 0x879CBACDBDE8F6A0L)   /* 1005 */,
+            unchecked((long) 0x976AD1BCC164A32FL)   /* 1006 */,    unchecked((long) 0xAB21E25E9666D78BL)   /* 1007 */,
+            unchecked((long) 0x901063AAE5E5C33CL)   /* 1008 */,    unchecked((long) 0x9818B34448698D90L)   /* 1009 */,
+            unchecked((long) 0xE36487AE3E1E8ABBL)   /* 1010 */,    unchecked((long) 0xAFBDF931893BDCB4L)   /* 1011 */,
+            unchecked((long) 0x6345A0DC5FBBD519L)   /* 1012 */,    unchecked((long) 0x8628FE269B9465CAL)   /* 1013 */,
+            unchecked((long) 0x1E5D01603F9C51ECL)   /* 1014 */,    unchecked((long) 0x4DE44006A15049B7L)   /* 1015 */,
+            unchecked((long) 0xBF6C70E5F776CBB1L)   /* 1016 */,    unchecked((long) 0x411218F2EF552BEDL)   /* 1017 */,
+            unchecked((long) 0xCB0C0708705A36A3L)   /* 1018 */,    unchecked((long) 0xE74D14754F986044L)   /* 1019 */,
+            unchecked((long) 0xCD56D9430EA8280EL)   /* 1020 */,    unchecked((long) 0xC12591D7535F5065L)   /* 1021 */,
+            unchecked((long) 0xC83223F1720AEF96L)   /* 1022 */,    unchecked((long) 0xC3A0396F7363A51FL)   /* 1023 */
+        };
+
+        private const int    DigestLength = 24;
+
+        //
+        // registers
+        //
+        private long    a, b, c;
+        private long    byteCount;
+
+        //
+        // buffers
+        //
+        private byte[]  Buffer = new byte[8];
+        private int     bOff;
+
+        private long[]  x = new long[8];
+        private int     xOff;
+
+        /**
+        * Standard constructor
+        */
+        public TigerDigest()
+        {
+            Reset();
+        }
+
+        /**
+        * Copy constructor.  This will copy the state of the provided
+        * message digest.
+        */
+        public TigerDigest(TigerDigest t)
+        {
+			Reset(t);
+        }
+
+		public string AlgorithmName
+		{
+			get { return "Tiger"; }
+		}
+
+		public int GetDigestSize()
+		{
+			return DigestLength;
+		}
+
+		public int GetByteLength()
+		{
+			return MyByteLength;
+		}
+
+		private void ProcessWord(
+            byte[]  b,
+            int     off)
+        {
+            x[xOff++] =   ((long)(b[off + 7] & 0xff) << 56)
+                        | ((long)(b[off + 6] & 0xff) << 48)
+                        | ((long)(b[off + 5] & 0xff) << 40)
+                        | ((long)(b[off + 4] & 0xff) << 32)
+                        | ((long)(b[off + 3] & 0xff) << 24)
+                        | ((long)(b[off + 2] & 0xff) << 16)
+                        | ((long)(b[off + 1] & 0xff) << 8)
+                        | ((uint)(b[off + 0] & 0xff));
+
+            if (xOff == x.Length)
+            {
+                ProcessBlock();
+            }
+
+            bOff = 0;
+        }
+
+        public void Update(
+            byte input)
+        {
+            Buffer[bOff++] = input;
+
+            if (bOff == Buffer.Length)
+            {
+                ProcessWord(Buffer, 0);
+            }
+
+            byteCount++;
+        }
+
+        public void BlockUpdate(
+            byte[]  input,
+            int     inOff,
+            int     length)
+        {
+            //
+            // fill the current word
+            //
+            while ((bOff != 0) && (length > 0))
+            {
+                Update(input[inOff]);
+
+                inOff++;
+                length--;
+            }
+
+            //
+            // process whole words.
+            //
+            while (length > 8)
+            {
+                ProcessWord(input, inOff);
+
+                inOff += 8;
+                length -= 8;
+                byteCount += 8;
+            }
+
+            //
+            // load in the remainder.
+            //
+            while (length > 0)
+            {
+                Update(input[inOff]);
+
+                inOff++;
+                length--;
+            }
+        }
+
+        private void RoundABC(
+            long    x,
+            long    mul)
+        {
+            c ^= x ;
+            a -= t1[(int)c & 0xff] ^ t2[(int)(c >> 16) & 0xff]
+                    ^ t3[(int)(c >> 32) & 0xff] ^ t4[(int)(c >> 48) & 0xff];
+            b += t4[(int)(c >> 8) & 0xff] ^ t3[(int)(c >> 24) & 0xff]
+                    ^ t2[(int)(c >> 40) & 0xff] ^ t1[(int)(c >> 56) & 0xff];
+            b *= mul;
+        }
+
+        private void RoundBCA(
+            long    x,
+            long    mul)
+        {
+            a ^= x ;
+            b -= t1[(int)a & 0xff] ^ t2[(int)(a >> 16) & 0xff]
+                    ^ t3[(int)(a >> 32) & 0xff] ^ t4[(int)(a >> 48) & 0xff];
+            c += t4[(int)(a >> 8) & 0xff] ^ t3[(int)(a >> 24) & 0xff]
+                    ^ t2[(int)(a >> 40) & 0xff] ^ t1[(int)(a >> 56) & 0xff];
+            c *= mul;
+        }
+
+        private void RoundCAB(
+            long    x,
+            long    mul)
+        {
+            b ^= x ;
+            c -= t1[(int)b & 0xff] ^ t2[(int)(b >> 16) & 0xff]
+                    ^ t3[(int)(b >> 32) & 0xff] ^ t4[(int)(b >> 48) & 0xff];
+            a += t4[(int)(b >> 8) & 0xff] ^ t3[(int)(b >> 24) & 0xff]
+                    ^ t2[(int)(b >> 40) & 0xff] ^ t1[(int)(b >> 56) & 0xff];
+            a *= mul;
+        }
+
+        private void KeySchedule()
+        {
+            x[0] -= x[7] ^ unchecked ((long) 0xA5A5A5A5A5A5A5A5L);
+            x[1] ^= x[0];
+            x[2] += x[1];
+            x[3] -= x[2] ^ ((~x[1]) << 19);
+            x[4] ^= x[3];
+            x[5] += x[4];
+            x[6] -= x[5] ^ (long) ((ulong) (~x[4]) >> 23);
+            x[7] ^= x[6];
+            x[0] += x[7];
+            x[1] -= x[0] ^ ((~x[7]) << 19);
+            x[2] ^= x[1];
+            x[3] += x[2];
+            x[4] -= x[3] ^ (long) ((ulong) (~x[2]) >> 23);
+            x[5] ^= x[4];
+            x[6] += x[5];
+            x[7] -= x[6] ^ 0x0123456789ABCDEFL;
+        }
+
+        private void ProcessBlock()
+        {
+            //
+            // save abc
+            //
+            long aa = a;
+            long bb = b;
+            long cc = c;
+
+            //
+            // rounds and schedule
+            //
+            RoundABC(x[0], 5);
+            RoundBCA(x[1], 5);
+            RoundCAB(x[2], 5);
+            RoundABC(x[3], 5);
+            RoundBCA(x[4], 5);
+            RoundCAB(x[5], 5);
+            RoundABC(x[6], 5);
+            RoundBCA(x[7], 5);
+
+            KeySchedule();
+
+            RoundCAB(x[0], 7);
+            RoundABC(x[1], 7);
+            RoundBCA(x[2], 7);
+            RoundCAB(x[3], 7);
+            RoundABC(x[4], 7);
+            RoundBCA(x[5], 7);
+            RoundCAB(x[6], 7);
+            RoundABC(x[7], 7);
+
+            KeySchedule();
+
+            RoundBCA(x[0], 9);
+            RoundCAB(x[1], 9);
+            RoundABC(x[2], 9);
+            RoundBCA(x[3], 9);
+            RoundCAB(x[4], 9);
+            RoundABC(x[5], 9);
+            RoundBCA(x[6], 9);
+            RoundCAB(x[7], 9);
+
+            //
+            // feed forward
+            //
+            a ^= aa;
+            b -= bb;
+            c += cc;
+
+            //
+            // clear the x buffer
+            //
+            xOff = 0;
+            for (int i = 0; i != x.Length; i++)
+            {
+                x[i] = 0;
+            }
+        }
+
+        private void UnpackWord(
+            long    r,
+            byte[]  output,
+            int     outOff)
+        {
+            output[outOff + 7]     = (byte)(r >> 56);
+            output[outOff + 6] = (byte)(r >> 48);
+            output[outOff + 5] = (byte)(r >> 40);
+            output[outOff + 4] = (byte)(r >> 32);
+            output[outOff + 3] = (byte)(r >> 24);
+            output[outOff + 2] = (byte)(r >> 16);
+            output[outOff + 1] = (byte)(r >> 8);
+            output[outOff] = (byte)r;
+        }
+
+        private void ProcessLength(
+            long    bitLength)
+        {
+            x[7] = bitLength;
+        }
+
+        private void Finish()
+        {
+            long    bitLength = (byteCount << 3);
+
+            Update((byte)0x01);
+
+            while (bOff != 0)
+            {
+                Update((byte)0);
+            }
+
+            ProcessLength(bitLength);
+
+            ProcessBlock();
+        }
+
+        public int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            Finish();
+
+            UnpackWord(a, output, outOff);
+            UnpackWord(b, output, outOff + 8);
+            UnpackWord(c, output, outOff + 16);
+
+            Reset();
+
+            return DigestLength;
+        }
+
+        /**
+        * reset the chaining variables
+        */
+        public void Reset()
+        {
+            a = unchecked((long) 0x0123456789ABCDEFL);
+            b = unchecked((long) 0xFEDCBA9876543210L);
+            c = unchecked((long) 0xF096A5B4C3B2E187L);
+
+            xOff = 0;
+            for (int i = 0; i != x.Length; i++)
+            {
+                x[i] = 0;
+            }
+
+            bOff = 0;
+            for (int i = 0; i != Buffer.Length; i++)
+            {
+                Buffer[i] = 0;
+            }
+
+            byteCount = 0;
+        }
+
+		public IMemoable Copy()
+		{
+			return new TigerDigest(this);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			TigerDigest t = (TigerDigest)other;
+
+			a = t.a;
+			b = t.b;
+			c = t.c;
+
+			Array.Copy(t.x, 0, x, 0, t.x.Length);
+			xOff = t.xOff;
+
+			Array.Copy(t.Buffer, 0, Buffer, 0, t.Buffer.Length);
+			bOff = t.bOff;
+
+			byteCount = t.byteCount;
+		}    
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/digests/WhirlpoolDigest.cs b/BouncyCastle.AxCrypt/src/crypto/digests/WhirlpoolDigest.cs
new file mode 100644
index 0000000..55b7120
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/digests/WhirlpoolDigest.cs
@@ -0,0 +1,413 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Digests
+{
+	/**
+	* Implementation of WhirlpoolDigest, based on Java source published by Barreto
+	* and Rijmen.
+	*
+	*/
+	public sealed class WhirlpoolDigest
+		: IDigest, IMemoable
+	{
+		private const int BYTE_LENGTH = 64;
+
+		private const int DIGEST_LENGTH_BYTES = 512 / 8;
+		private const int ROUNDS = 10;
+		private const int REDUCTION_POLYNOMIAL = 0x011d; // 2^8 + 2^4 + 2^3 + 2 + 1;
+
+		private static readonly int[] SBOX =
+		{
+			0x18, 0x23, 0xc6, 0xe8, 0x87, 0xb8, 0x01, 0x4f, 0x36, 0xa6, 0xd2, 0xf5, 0x79, 0x6f, 0x91, 0x52,
+			0x60, 0xbc, 0x9b, 0x8e, 0xa3, 0x0c, 0x7b, 0x35, 0x1d, 0xe0, 0xd7, 0xc2, 0x2e, 0x4b, 0xfe, 0x57,
+			0x15, 0x77, 0x37, 0xe5, 0x9f, 0xf0, 0x4a, 0xda, 0x58, 0xc9, 0x29, 0x0a, 0xb1, 0xa0, 0x6b, 0x85,
+			0xbd, 0x5d, 0x10, 0xf4, 0xcb, 0x3e, 0x05, 0x67, 0xe4, 0x27, 0x41, 0x8b, 0xa7, 0x7d, 0x95, 0xd8,
+			0xfb, 0xee, 0x7c, 0x66, 0xdd, 0x17, 0x47, 0x9e, 0xca, 0x2d, 0xbf, 0x07, 0xad, 0x5a, 0x83, 0x33,
+			0x63, 0x02, 0xaa, 0x71, 0xc8, 0x19, 0x49, 0xd9, 0xf2, 0xe3, 0x5b, 0x88, 0x9a, 0x26, 0x32, 0xb0,
+			0xe9, 0x0f, 0xd5, 0x80, 0xbe, 0xcd, 0x34, 0x48, 0xff, 0x7a, 0x90, 0x5f, 0x20, 0x68, 0x1a, 0xae,
+			0xb4, 0x54, 0x93, 0x22, 0x64, 0xf1, 0x73, 0x12, 0x40, 0x08, 0xc3, 0xec, 0xdb, 0xa1, 0x8d, 0x3d,
+			0x97, 0x00, 0xcf, 0x2b, 0x76, 0x82, 0xd6, 0x1b, 0xb5, 0xaf, 0x6a, 0x50, 0x45, 0xf3, 0x30, 0xef,
+			0x3f, 0x55, 0xa2, 0xea, 0x65, 0xba, 0x2f, 0xc0, 0xde, 0x1c, 0xfd, 0x4d, 0x92, 0x75, 0x06, 0x8a,
+			0xb2, 0xe6, 0x0e, 0x1f, 0x62, 0xd4, 0xa8, 0x96, 0xf9, 0xc5, 0x25, 0x59, 0x84, 0x72, 0x39, 0x4c,
+			0x5e, 0x78, 0x38, 0x8c, 0xd1, 0xa5, 0xe2, 0x61, 0xb3, 0x21, 0x9c, 0x1e, 0x43, 0xc7, 0xfc, 0x04,
+			0x51, 0x99, 0x6d, 0x0d, 0xfa, 0xdf, 0x7e, 0x24, 0x3b, 0xab, 0xce, 0x11, 0x8f, 0x4e, 0xb7, 0xeb,
+			0x3c, 0x81, 0x94, 0xf7, 0xb9, 0x13, 0x2c, 0xd3, 0xe7, 0x6e, 0xc4, 0x03, 0x56, 0x44, 0x7f, 0xa9,
+			0x2a, 0xbb, 0xc1, 0x53, 0xdc, 0x0b, 0x9d, 0x6c, 0x31, 0x74, 0xf6, 0x46, 0xac, 0x89, 0x14, 0xe1,
+			0x16, 0x3a, 0x69, 0x09, 0x70, 0xb6, 0xd0, 0xed, 0xcc, 0x42, 0x98, 0xa4, 0x28, 0x5c, 0xf8, 0x86
+		};
+
+		private static readonly long[] C0 = new long[256];
+		private static readonly long[] C1 = new long[256];
+		private static readonly long[] C2 = new long[256];
+		private static readonly long[] C3 = new long[256];
+		private static readonly long[] C4 = new long[256];
+		private static readonly long[] C5 = new long[256];
+		private static readonly long[] C6 = new long[256];
+		private static readonly long[] C7 = new long[256];
+
+		private readonly long[] _rc = new long[ROUNDS + 1];
+
+		/*
+			* increment() can be implemented in this way using 2 arrays or
+			* by having some temporary variables that are used to set the
+			* value provided by EIGHT[i] and carry within the loop.
+			*
+			* not having done any timing, this seems likely to be faster
+			* at the slight expense of 32*(sizeof short) bytes
+			*/
+		private static readonly short[] EIGHT = new short[BITCOUNT_ARRAY_SIZE];
+
+		static WhirlpoolDigest()
+		{
+			EIGHT[BITCOUNT_ARRAY_SIZE - 1] = 8;
+
+			for (int i = 0; i < 256; i++)
+			{
+				int v1 = SBOX[i];
+				int v2 = maskWithReductionPolynomial(v1 << 1);
+				int v4 = maskWithReductionPolynomial(v2 << 1);
+				int v5 = v4 ^ v1;
+				int v8 = maskWithReductionPolynomial(v4 << 1);
+				int v9 = v8 ^ v1;
+
+				C0[i] = packIntoLong(v1, v1, v4, v1, v8, v5, v2, v9);
+				C1[i] = packIntoLong(v9, v1, v1, v4, v1, v8, v5, v2);
+				C2[i] = packIntoLong(v2, v9, v1, v1, v4, v1, v8, v5);
+				C3[i] = packIntoLong(v5, v2, v9, v1, v1, v4, v1, v8);
+				C4[i] = packIntoLong(v8, v5, v2, v9, v1, v1, v4, v1);
+				C5[i] = packIntoLong(v1, v8, v5, v2, v9, v1, v1, v4);
+				C6[i] = packIntoLong(v4, v1, v8, v5, v2, v9, v1, v1);
+				C7[i] = packIntoLong(v1, v4, v1, v8, v5, v2, v9, v1);
+			}
+		}
+
+		public WhirlpoolDigest()
+		{
+			_rc[0] = 0L;
+			for (int r = 1; r <= ROUNDS; r++)
+			{
+				int i = 8 * (r - 1);
+				_rc[r] = (long)((ulong)C0[i] & 0xff00000000000000L) ^
+					(C1[i + 1] & (long) 0x00ff000000000000L) ^
+					(C2[i + 2] & (long) 0x0000ff0000000000L) ^
+					(C3[i + 3] & (long) 0x000000ff00000000L) ^
+					(C4[i + 4] & (long) 0x00000000ff000000L) ^
+					(C5[i + 5] & (long) 0x0000000000ff0000L) ^
+					(C6[i + 6] & (long) 0x000000000000ff00L) ^
+					(C7[i + 7] & (long) 0x00000000000000ffL);
+			}
+		}
+
+		private static long packIntoLong(int b7, int b6, int b5, int b4, int b3, int b2, int b1, int b0)
+		{
+			return
+				((long)b7 << 56) ^
+				((long)b6 << 48) ^
+				((long)b5 << 40) ^
+				((long)b4 << 32) ^
+				((long)b3 << 24) ^
+				((long)b2 << 16) ^
+				((long)b1 <<  8) ^
+				b0;
+		}
+
+		/*
+			* int's are used to prevent sign extension.  The values that are really being used are
+			* actually just 0..255
+			*/
+		private static int maskWithReductionPolynomial(int input)
+		{
+			int rv = input;
+			if (rv >= 0x100L) // high bit set
+			{
+				rv ^= REDUCTION_POLYNOMIAL; // reduced by the polynomial
+			}
+			return rv;
+		}
+
+		// --------------------------------------------------------------------------------------//
+
+		// -- buffer information --
+		private const int BITCOUNT_ARRAY_SIZE = 32;
+		private byte[]  _buffer    = new byte[64];
+		private int     _bufferPos;
+		private short[] _bitCount  = new short[BITCOUNT_ARRAY_SIZE];
+
+		// -- internal hash state --
+		private long[] _hash  = new long[8];
+		private long[] _K = new long[8]; // the round key
+		private long[] _L = new long[8];
+		private long[] _block = new long[8]; // mu (buffer)
+		private long[] _state = new long[8]; // the current "cipher" state
+
+
+
+		/**
+			* Copy constructor. This will copy the state of the provided message
+			* digest.
+			*/
+		public WhirlpoolDigest(WhirlpoolDigest originalDigest)
+		{
+			Reset(originalDigest);
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Whirlpool"; }
+		}
+
+		public int GetDigestSize()
+		{
+			return DIGEST_LENGTH_BYTES;
+		}
+
+		public int DoFinal(byte[] output, int outOff)
+		{
+			// sets output[outOff] .. output[outOff+DIGEST_LENGTH_BYTES]
+			finish();
+
+			for (int i = 0; i < 8; i++)
+			{
+				convertLongToByteArray(_hash[i], output, outOff + (i * 8));
+			}
+
+			Reset();
+
+			return GetDigestSize();
+		}
+
+		/**
+			* Reset the chaining variables
+			*/
+		public void Reset()
+		{
+			// set variables to null, blank, whatever
+			_bufferPos = 0;
+			Array.Clear(_bitCount, 0, _bitCount.Length);
+			Array.Clear(_buffer, 0, _buffer.Length);
+			Array.Clear(_hash, 0, _hash.Length);
+			Array.Clear(_K, 0, _K.Length);
+			Array.Clear(_L, 0, _L.Length);
+			Array.Clear(_block, 0, _block.Length);
+			Array.Clear(_state, 0, _state.Length);
+		}
+
+		// this takes a buffer of information and fills the block
+		private void processFilledBuffer()
+		{
+			// copies into the block...
+			for (int i = 0; i < _state.Length; i++)
+			{
+				_block[i] = bytesToLongFromBuffer(_buffer, i * 8);
+			}
+			processBlock();
+			_bufferPos = 0;
+			Array.Clear(_buffer, 0, _buffer.Length);
+		}
+
+		private static long bytesToLongFromBuffer(byte[] buffer, int startPos)
+		{
+			long rv = (((buffer[startPos + 0] & 0xffL) << 56) |
+				((buffer[startPos + 1] & 0xffL) << 48) |
+				((buffer[startPos + 2] & 0xffL) << 40) |
+				((buffer[startPos + 3] & 0xffL) << 32) |
+				((buffer[startPos + 4] & 0xffL) << 24) |
+				((buffer[startPos + 5] & 0xffL) << 16) |
+				((buffer[startPos + 6] & 0xffL) <<  8) |
+				((buffer[startPos + 7]) & 0xffL));
+
+			return rv;
+		}
+
+		private static void convertLongToByteArray(long inputLong, byte[] outputArray, int offSet)
+		{
+			for (int i = 0; i < 8; i++)
+			{
+				outputArray[offSet + i] = (byte)((inputLong >> (56 - (i * 8))) & 0xff);
+			}
+		}
+
+		private void processBlock()
+		{
+			// buffer contents have been transferred to the _block[] array via
+			// processFilledBuffer
+
+			// compute and apply K^0
+			for (int i = 0; i < 8; i++)
+			{
+				_state[i] = _block[i] ^ (_K[i] = _hash[i]);
+			}
+
+			// iterate over the rounds
+			for (int round = 1; round <= ROUNDS; round++)
+			{
+				for (int i = 0; i < 8; i++)
+				{
+					_L[i] = 0;
+					_L[i] ^= C0[(int)(_K[(i - 0) & 7] >> 56) & 0xff];
+					_L[i] ^= C1[(int)(_K[(i - 1) & 7] >> 48) & 0xff];
+					_L[i] ^= C2[(int)(_K[(i - 2) & 7] >> 40) & 0xff];
+					_L[i] ^= C3[(int)(_K[(i - 3) & 7] >> 32) & 0xff];
+					_L[i] ^= C4[(int)(_K[(i - 4) & 7] >> 24) & 0xff];
+					_L[i] ^= C5[(int)(_K[(i - 5) & 7] >> 16) & 0xff];
+					_L[i] ^= C6[(int)(_K[(i - 6) & 7] >>  8) & 0xff];
+					_L[i] ^= C7[(int)(_K[(i - 7) & 7]) & 0xff];
+				}
+
+				Array.Copy(_L, 0, _K, 0, _K.Length);
+
+				_K[0] ^= _rc[round];
+
+				// apply the round transformation
+				for (int i = 0; i < 8; i++)
+				{
+					_L[i] = _K[i];
+
+					_L[i] ^= C0[(int)(_state[(i - 0) & 7] >> 56) & 0xff];
+					_L[i] ^= C1[(int)(_state[(i - 1) & 7] >> 48) & 0xff];
+					_L[i] ^= C2[(int)(_state[(i - 2) & 7] >> 40) & 0xff];
+					_L[i] ^= C3[(int)(_state[(i - 3) & 7] >> 32) & 0xff];
+					_L[i] ^= C4[(int)(_state[(i - 4) & 7] >> 24) & 0xff];
+					_L[i] ^= C5[(int)(_state[(i - 5) & 7] >> 16) & 0xff];
+					_L[i] ^= C6[(int)(_state[(i - 6) & 7] >> 8) & 0xff];
+					_L[i] ^= C7[(int)(_state[(i - 7) & 7]) & 0xff];
+				}
+
+				// save the current state
+				Array.Copy(_L, 0, _state, 0, _state.Length);
+			}
+
+			// apply Miuaguchi-Preneel compression
+			for (int i = 0; i < 8; i++)
+			{
+				_hash[i] ^= _state[i] ^ _block[i];
+			}
+
+		}
+
+		public void Update(byte input)
+		{
+			_buffer[_bufferPos] = input;
+
+			//Console.WriteLine("adding to buffer = "+_buffer[_bufferPos]);
+
+			++_bufferPos;
+
+			if (_bufferPos == _buffer.Length)
+			{
+				processFilledBuffer();
+			}
+
+			increment();
+		}
+
+		private void increment()
+		{
+			int carry = 0;
+			for (int i = _bitCount.Length - 1; i >= 0; i--)
+			{
+				int sum = (_bitCount[i] & 0xff) + EIGHT[i] + carry;
+
+				carry = sum >> 8;
+				_bitCount[i] = (short)(sum & 0xff);
+			}
+		}
+
+		public void BlockUpdate(byte[] input, int inOff, int length)
+		{
+			while (length > 0)
+			{
+				Update(input[inOff]);
+				++inOff;
+				--length;
+			}
+
+		}
+
+		private void finish()
+		{
+			/*
+				* this makes a copy of the current bit length. at the expense of an
+				* object creation of 32 bytes rather than providing a _stopCounting
+				* boolean which was the alternative I could think of.
+				*/
+			byte[] bitLength = copyBitLength();
+
+			_buffer[_bufferPos++] |= 0x80;
+
+			if (_bufferPos == _buffer.Length)
+			{
+				processFilledBuffer();
+			}
+
+			/*
+				* Final block contains
+				* [ ... data .... ][0][0][0][ length ]
+				*
+				* if [ length ] cannot fit.  Need to create a new block.
+				*/
+			if (_bufferPos > 32)
+			{
+				while (_bufferPos != 0)
+				{
+					Update((byte)0);
+				}
+			}
+
+			while (_bufferPos <= 32)
+			{
+				Update((byte)0);
+			}
+
+			// copy the length information to the final 32 bytes of the
+			// 64 byte block....
+			Array.Copy(bitLength, 0, _buffer, 32, bitLength.Length);
+
+			processFilledBuffer();
+		}
+
+		private byte[] copyBitLength()
+		{
+			byte[] rv = new byte[BITCOUNT_ARRAY_SIZE];
+			for (int i = 0; i < rv.Length; i++)
+			{
+				rv[i] = (byte)(_bitCount[i] & 0xff);
+			}
+			return rv;
+		}
+
+		public int GetByteLength()
+		{
+			return BYTE_LENGTH;
+		}
+
+		public IMemoable Copy()
+		{
+			return new WhirlpoolDigest(this);
+		}
+
+		public void Reset(IMemoable other)
+		{
+			WhirlpoolDigest originalDigest = (WhirlpoolDigest)other;
+
+			Array.Copy(originalDigest._rc, 0, _rc, 0, _rc.Length);
+
+			Array.Copy(originalDigest._buffer, 0, _buffer, 0, _buffer.Length);
+
+			this._bufferPos = originalDigest._bufferPos;
+			Array.Copy(originalDigest._bitCount, 0, _bitCount, 0, _bitCount.Length);
+
+			// -- internal hash state --
+			Array.Copy(originalDigest._hash, 0, _hash, 0, _hash.Length);
+			Array.Copy(originalDigest._K, 0, _K, 0, _K.Length);
+			Array.Copy(originalDigest._L, 0, _L, 0, _L.Length);
+			Array.Copy(originalDigest._block, 0, _block, 0, _block.Length);
+			Array.Copy(originalDigest._state, 0, _state, 0, _state.Length);
+		}
+
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/ec/CustomNamedCurves.cs b/BouncyCastle.AxCrypt/src/crypto/ec/CustomNamedCurves.cs
new file mode 100644
index 0000000..8ff1d24
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/ec/CustomNamedCurves.cs
@@ -0,0 +1,366 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Custom.Djb;
+using Org.BouncyCastle.Math.EC.Custom.Sec;
+using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.EC
+{
+    public sealed class CustomNamedCurves
+    {
+        private CustomNamedCurves()
+        {
+        }
+
+        private static BigInteger FromHex(string hex)
+        {
+            return new BigInteger(1, Hex.Decode(hex));
+        }
+
+        private static ECCurve ConfigureCurve(ECCurve curve)
+        {
+            return curve;
+        }
+
+        private static ECCurve ConfigureCurveGlv(ECCurve c, GlvTypeBParameters p)
+        {
+            return c.Configure().SetEndomorphism(new GlvTypeBEndomorphism(c, p)).Create();
+        }
+
+        /*
+         * curve25519
+         */
+        internal class Curve25519Holder
+            : X9ECParametersHolder
+        {
+            private Curve25519Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Curve25519Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = null;
+                ECCurve curve = ConfigureCurve(new Curve25519());
+
+                /*
+                 * NOTE: Curve25519 was specified in Montgomery form. Rewriting in Weierstrass form
+                 * involves substitution of variables, so the base-point x coordinate is 9 + (486662 / 3).
+                 * 
+                 * The Curve25519 paper doesn't say which of the two possible y values the base
+                 * point has. The choice here is guided by language in the Ed25519 paper.
+                 * 
+                 * (The other possible y value is 5F51E65E475F794B1FE122D388B72EB36DC2B28192839E4DD6163A5D81312C14) 
+                 */
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD245A"
+                    + "20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9"));
+
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp192k1
+         */
+        internal class Secp192k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp192k1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp192k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = null;
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("bb85691939b869c1d087f601554b96b80cb4f55b35f433c2", 16),
+                    new BigInteger("3d84f26c12238d7b4f3d516613c1759033b1a5800175d0b1", 16),
+                    new BigInteger[]{
+                        new BigInteger("71169be7330b3038edb025f1", 16),
+                        new BigInteger("-b3fb3400dec5c4adceb8655c", 16) },
+                    new BigInteger[]{
+                        new BigInteger("12511cfe811d0f4e6bc688b4d", 16),
+                        new BigInteger("71169be7330b3038edb025f1", 16) },
+                    new BigInteger("71169be7330b3038edb025f1d0f9", 16),
+                    new BigInteger("b3fb3400dec5c4adceb8655d4c94", 16),
+                    208);
+                ECCurve curve = ConfigureCurveGlv(new SecP192K1Curve(), glv);
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D"
+                    + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp192r1
+         */
+        internal class Secp192r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp192r1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp192r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("3045AE6FC8422F64ED579528D38120EAE12196D5");
+                ECCurve curve = ConfigureCurve(new SecP192R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012"
+                    + "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp224k1
+         */
+        internal class Secp224k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp224k1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp224k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = null;
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("fe0e87005b4e83761908c5131d552a850b3f58b749c37cf5b84d6768", 16),
+                    new BigInteger("60dcd2104c4cbc0be6eeefc2bdd610739ec34e317f9b33046c9e4788", 16),
+                    new BigInteger[]{
+                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16),
+                        new BigInteger("-b8adf1378a6eb73409fa6c9c637d", 16) },
+                    new BigInteger[]{
+                        new BigInteger("1243ae1b4d71613bc9f780a03690e", 16),
+                        new BigInteger("6b8cf07d4ca75c88957d9d670591", 16) },
+                    new BigInteger("6b8cf07d4ca75c88957d9d67059037a4", 16),
+                    new BigInteger("b8adf1378a6eb73409fa6c9c637ba7f5", 16),
+                    240);
+                ECCurve curve = ConfigureCurveGlv(new SecP224K1Curve(), glv);
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C"
+                    + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp224r1
+         */
+        internal class Secp224r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp224r1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp224r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("BD71344799D5C7FCDC45B59FA3B9AB8F6A948BC5");
+                ECCurve curve = ConfigureCurve(new SecP224R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21"
+                    + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp256k1
+         */
+        internal class Secp256k1Holder
+            : X9ECParametersHolder
+        {
+            private Secp256k1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp256k1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = null;
+                GlvTypeBParameters glv = new GlvTypeBParameters(
+                    new BigInteger("7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee", 16),
+                    new BigInteger("5363ad4cc05c30e0a5261c028812645a122e22ea20816678df02967c1b23bd72", 16),
+                    new BigInteger[]{
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16),
+                        new BigInteger("-e4437ed6010e88286f547fa90abfe4c3", 16) },
+                    new BigInteger[]{
+                        new BigInteger("114ca50f7a8e2f3f657c1108d9d44cfd8", 16),
+                        new BigInteger("3086d221a7d46bcde86c90e49284eb15", 16) },
+                    new BigInteger("3086d221a7d46bcde86c90e49284eb153dab", 16),
+                    new BigInteger("e4437ed6010e88286f547fa90abfe4c42212", 16),
+                    272);
+                ECCurve curve = ConfigureCurveGlv(new SecP256K1Curve(), glv);
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798"
+                    + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp256r1
+         */
+        internal class Secp256r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp256r1Holder() {}
+
+            internal static readonly X9ECParametersHolder Instance = new Secp256r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("C49D360886E704936A6678E1139D26B7819F7E90");
+                ECCurve curve = ConfigureCurve(new SecP256R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"
+                    + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp384r1
+         */
+        internal class Secp384r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp384r1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp384r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("A335926AA319A27A1D00896A6773A4827ACDAC73");
+                ECCurve curve = ConfigureCurve(new SecP384R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7"
+                    + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        /*
+         * secp521r1
+         */
+        internal class Secp521r1Holder
+            : X9ECParametersHolder
+        {
+            private Secp521r1Holder() { }
+
+            internal static readonly X9ECParametersHolder Instance = new Secp521r1Holder();
+
+            protected override X9ECParameters CreateParameters()
+            {
+                byte[] S = Hex.Decode("D09E8800291CB85396CC6717393284AAA0DA64BA");
+                ECCurve curve = ConfigureCurve(new SecP521R1Curve());
+                ECPoint G = curve.DecodePoint(Hex.Decode("04"
+                    + "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66"
+                    + "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650"));
+                return new X9ECParameters(curve, G, curve.Order, curve.Cofactor, S);
+            }
+        }
+
+        private static readonly IDictionary nameToCurve = Platform.CreateHashtable();
+        private static readonly IDictionary nameToOid = Platform.CreateHashtable();
+        private static readonly IDictionary oidToCurve = Platform.CreateHashtable();
+        private static readonly IDictionary oidToName = Platform.CreateHashtable();
+
+        private static void DefineCurve(string name, X9ECParametersHolder holder)
+        {
+            nameToCurve.Add(name, holder);
+        }
+
+        private static void DefineCurve(string name, DerObjectIdentifier oid, X9ECParametersHolder holder)
+        {
+            nameToCurve.Add(name, holder);
+            nameToOid.Add(name, oid);
+            oidToName.Add(oid, name);
+            oidToCurve.Add(oid, holder);
+        }
+
+        private static void DefineCurveAlias(string alias, DerObjectIdentifier oid)
+        {
+            alias = Platform.ToLowerInvariant(alias);
+            nameToOid.Add(alias, oid);
+            nameToCurve.Add(alias, oidToCurve[oid]);
+        }
+
+        static CustomNamedCurves()
+        {
+            DefineCurve("curve25519", Curve25519Holder.Instance);
+
+            DefineCurve("secp192k1", SecObjectIdentifiers.SecP192k1, Secp192k1Holder.Instance);
+            DefineCurve("secp192r1", SecObjectIdentifiers.SecP192r1, Secp192r1Holder.Instance);
+            DefineCurve("secp224k1", SecObjectIdentifiers.SecP224k1, Secp224k1Holder.Instance);
+            DefineCurve("secp224r1", SecObjectIdentifiers.SecP224r1, Secp224r1Holder.Instance);
+            DefineCurve("secp256k1", SecObjectIdentifiers.SecP256k1, Secp256k1Holder.Instance);
+            DefineCurve("secp256r1", SecObjectIdentifiers.SecP256r1, Secp256r1Holder.Instance);
+            DefineCurve("secp384r1", SecObjectIdentifiers.SecP384r1, Secp384r1Holder.Instance);
+            DefineCurve("secp521r1", SecObjectIdentifiers.SecP521r1, Secp521r1Holder.Instance);
+
+            DefineCurveAlias("P-192", SecObjectIdentifiers.SecP192r1);
+            DefineCurveAlias("P-224", SecObjectIdentifiers.SecP224r1);
+            DefineCurveAlias("P-256", SecObjectIdentifiers.SecP256r1);
+            DefineCurveAlias("P-384", SecObjectIdentifiers.SecP384r1);
+            DefineCurveAlias("P-521", SecObjectIdentifiers.SecP521r1);
+        }
+
+        public static X9ECParameters GetByName(string name)
+        {
+            X9ECParametersHolder holder = (X9ECParametersHolder)nameToCurve[Platform.ToLowerInvariant(name)];
+            return holder == null ? null : holder.Parameters;
+        }
+
+        /**
+         * return the X9ECParameters object for the named curve represented by
+         * the passed in object identifier. Null if the curve isn't present.
+         *
+         * @param oid an object identifier representing a named curve, if present.
+         */
+        public static X9ECParameters GetByOid(DerObjectIdentifier oid)
+        {
+            X9ECParametersHolder holder = (X9ECParametersHolder)oidToCurve[oid];
+            return holder == null ? null : holder.Parameters;
+        }
+
+        /**
+         * return the object identifier signified by the passed in name. Null
+         * if there is no object identifier associated with name.
+         *
+         * @return the object identifier associated with name, if present.
+         */
+        public static DerObjectIdentifier GetOid(string name)
+        {
+            return (DerObjectIdentifier)nameToOid[Platform.ToLowerInvariant(name)];
+        }
+
+        /**
+         * return the named curve name represented by the given object identifier.
+         */
+        public static string GetName(DerObjectIdentifier oid)
+        {
+            return (string)oidToName[oid];
+        }
+
+        /**
+         * returns an enumeration containing the name strings for curves
+         * contained in this structure.
+         */
+        public static IEnumerable Names
+        {
+            get { return new EnumerableProxy(nameToCurve.Keys); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/encodings/ISO9796d1Encoding.cs b/BouncyCastle.AxCrypt/src/crypto/encodings/ISO9796d1Encoding.cs
new file mode 100644
index 0000000..30e9883
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/encodings/ISO9796d1Encoding.cs
@@ -0,0 +1,273 @@
+using System;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Encodings
+{
+	/**
+	* ISO 9796-1 padding. Note in the light of recent results you should
+	* only use this with RSA (rather than the "simpler" Rabin keys) and you
+	* should never use it with anything other than a hash (ie. even if the
+	* message is small don't sign the message, sign it's hash) or some "random"
+	* value. See your favorite search engine for details.
+	*/
+	public class ISO9796d1Encoding
+		: IAsymmetricBlockCipher
+	{
+		private static readonly BigInteger Sixteen = BigInteger.ValueOf(16);
+		private static readonly BigInteger Six = BigInteger.ValueOf(6);
+
+		private static readonly byte[] shadows = { 0xe, 0x3, 0x5, 0x8, 0x9, 0x4, 0x2, 0xf,
+			0x0, 0xd, 0xb, 0x6, 0x7, 0xa, 0xc, 0x1 };
+		private static readonly byte[] inverse = { 0x8, 0xf, 0x6, 0x1, 0x5, 0x2, 0xb, 0xc,
+			0x3, 0x4, 0xd, 0xa, 0xe, 0x9, 0x0, 0x7 };
+
+		private readonly IAsymmetricBlockCipher engine;
+		private bool forEncryption;
+		private int bitSize;
+		private int padBits = 0;
+		private BigInteger modulus;
+
+		public ISO9796d1Encoding(
+			IAsymmetricBlockCipher   cipher)
+		{
+			this.engine = cipher;
+		}
+
+		public string AlgorithmName
+		{
+			get { return engine.AlgorithmName + "/ISO9796-1Padding"; }
+		}
+
+		public IAsymmetricBlockCipher GetUnderlyingCipher()
+		{
+			return engine;
+		}
+
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			RsaKeyParameters kParam;
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+				kParam = (RsaKeyParameters)rParam.Parameters;
+			}
+			else
+			{
+				kParam = (RsaKeyParameters)parameters;
+			}
+
+			engine.Init(forEncryption, parameters);
+
+			modulus = kParam.Modulus;
+			bitSize = modulus.BitLength;
+
+			this.forEncryption = forEncryption;
+		}
+
+		/**
+		* return the input block size. The largest message we can process
+		* is (key_size_in_bits + 3)/16, which in our world comes to
+		* key_size_in_bytes / 2.
+		*/
+		public int GetInputBlockSize()
+		{
+			int baseBlockSize = engine.GetInputBlockSize();
+
+			if (forEncryption)
+			{
+				return (baseBlockSize + 1) / 2;
+			}
+			else
+			{
+				return baseBlockSize;
+			}
+		}
+
+		/**
+		* return the maximum possible size for the output.
+		*/
+		public int GetOutputBlockSize()
+		{
+			int baseBlockSize = engine.GetOutputBlockSize();
+
+			if (forEncryption)
+			{
+				return baseBlockSize;
+			}
+			else
+			{
+				return (baseBlockSize + 1) / 2;
+			}
+		}
+
+		/**
+		* set the number of bits in the next message to be treated as
+		* pad bits.
+		*/
+		public void SetPadBits(
+			int     padBits)
+		{
+			if (padBits > 7)
+			{
+				throw new ArgumentException("padBits > 7");
+			}
+
+			this.padBits = padBits;
+		}
+
+		/**
+		* retrieve the number of pad bits in the last decoded message.
+		*/
+		public int GetPadBits()
+		{
+			return padBits;
+		}
+
+		public byte[] ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (forEncryption)
+			{
+				return EncodeBlock(input, inOff, length);
+			}
+			else
+			{
+				return DecodeBlock(input, inOff, length);
+			}
+		}
+
+		private byte[] EncodeBlock(
+			byte[]	input,
+			int		inOff,
+			int		inLen)
+		{
+			byte[]  block = new byte[(bitSize + 7) / 8];
+			int     r = padBits + 1;
+			int     z = inLen;
+			int     t = (bitSize + 13) / 16;
+
+			for (int i = 0; i < t; i += z)
+			{
+				if (i > t - z)
+				{
+					Array.Copy(input, inOff + inLen - (t - i),
+						block, block.Length - t, t - i);
+				}
+				else
+				{
+					Array.Copy(input, inOff, block, block.Length - (i + z), z);
+				}
+			}
+
+			for (int i = block.Length - 2 * t; i != block.Length; i += 2)
+			{
+				byte val = block[block.Length - t + i / 2];
+
+				block[i] = (byte)((shadows[(uint) (val & 0xff) >> 4] << 4)
+					| shadows[val & 0x0f]);
+				block[i + 1] = val;
+			}
+
+			block[block.Length - 2 * z] ^= (byte) r;
+			block[block.Length - 1] = (byte)((block[block.Length - 1] << 4) | 0x06);
+
+			int maxBit = (8 - (bitSize - 1) % 8);
+			int offSet = 0;
+
+			if (maxBit != 8)
+			{
+				block[0] &= (byte) ((ushort) 0xff >> maxBit);
+				block[0] |= (byte) ((ushort) 0x80 >> maxBit);
+			}
+			else
+			{
+				block[0] = 0x00;
+				block[1] |= 0x80;
+				offSet = 1;
+			}
+
+			return engine.ProcessBlock(block, offSet, block.Length - offSet);
+		}
+
+		/**
+		* @exception InvalidCipherTextException if the decrypted block is not a valid ISO 9796 bit string
+		*/
+		private byte[] DecodeBlock(
+			byte[]	input,
+			int		inOff,
+			int		inLen)
+		{
+			byte[]  block = engine.ProcessBlock(input, inOff, inLen);
+			int     r = 1;
+			int     t = (bitSize + 13) / 16;
+
+			BigInteger iS = new BigInteger(1, block);
+			BigInteger iR;
+			if (iS.Mod(Sixteen).Equals(Six))
+			{
+				iR = iS;
+			}
+			else
+			{
+				iR = modulus.Subtract(iS);
+
+				if (!iR.Mod(Sixteen).Equals(Six))
+					throw new InvalidCipherTextException("resulting integer iS or (modulus - iS) is not congruent to 6 mod 16");
+			}
+
+			block = iR.ToByteArrayUnsigned();
+
+			if ((block[block.Length - 1] & 0x0f) != 0x6)
+				throw new InvalidCipherTextException("invalid forcing byte in block");
+
+			block[block.Length - 1] =
+				(byte)(((ushort)(block[block.Length - 1] & 0xff) >> 4)
+				| ((inverse[(block[block.Length - 2] & 0xff) >> 4]) << 4));
+
+			block[0] = (byte)((shadows[(uint) (block[1] & 0xff) >> 4] << 4)
+				| shadows[block[1] & 0x0f]);
+
+			bool boundaryFound = false;
+			int boundary = 0;
+
+			for (int i = block.Length - 1; i >= block.Length - 2 * t; i -= 2)
+			{
+				int val = ((shadows[(uint) (block[i] & 0xff) >> 4] << 4)
+					| shadows[block[i] & 0x0f]);
+
+				if (((block[i - 1] ^ val) & 0xff) != 0)
+				{
+					if (!boundaryFound)
+					{
+						boundaryFound = true;
+						r = (block[i - 1] ^ val) & 0xff;
+						boundary = i - 1;
+					}
+					else
+					{
+						throw new InvalidCipherTextException("invalid tsums in block");
+					}
+				}
+			}
+
+			block[boundary] = 0;
+
+			byte[] nblock = new byte[(block.Length - boundary) / 2];
+
+			for (int i = 0; i < nblock.Length; i++)
+			{
+				nblock[i] = block[2 * i + boundary + 1];
+			}
+
+			padBits = r - 1;
+
+			return nblock;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/encodings/OaepEncoding.cs b/BouncyCastle.AxCrypt/src/crypto/encodings/OaepEncoding.cs
new file mode 100644
index 0000000..a4d2f0e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/encodings/OaepEncoding.cs
@@ -0,0 +1,349 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Encodings
+{
+    /**
+    * Optimal Asymmetric Encryption Padding (OAEP) - see PKCS 1 V 2.
+    */
+    public class OaepEncoding
+        : IAsymmetricBlockCipher
+    {
+        private byte[] defHash;
+        private IDigest hash;
+        private IDigest mgf1Hash;
+
+        private IAsymmetricBlockCipher engine;
+        private SecureRandom random;
+        private bool forEncryption;
+
+        public OaepEncoding(
+            IAsymmetricBlockCipher cipher)
+            : this(cipher, new Sha1Digest(), null)
+        {
+        }
+
+        public OaepEncoding(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					hash)
+            : this(cipher, hash, null)
+        {
+        }
+
+        public OaepEncoding(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					hash,
+            byte[]					encodingParams)
+            : this(cipher, hash, hash, encodingParams)
+        {
+        }
+
+        public OaepEncoding(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					hash,
+            IDigest					mgf1Hash,
+            byte[]					encodingParams)
+        {
+            this.engine = cipher;
+            this.hash = hash;
+            this.mgf1Hash = mgf1Hash;
+            this.defHash = new byte[hash.GetDigestSize()];
+
+            if (encodingParams != null)
+            {
+                hash.BlockUpdate(encodingParams, 0, encodingParams.Length);
+            }
+
+            hash.DoFinal(defHash, 0);
+        }
+
+        public IAsymmetricBlockCipher GetUnderlyingCipher()
+        {
+            return engine;
+        }
+
+        public string AlgorithmName
+        {
+            get { return engine.AlgorithmName + "/OAEPPadding"; }
+        }
+
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	param)
+        {
+            if (param is ParametersWithRandom)
+            {
+                ParametersWithRandom rParam = (ParametersWithRandom)param;
+                this.random = rParam.Random;
+            }
+            else
+            {
+                this.random = new SecureRandom();
+            }
+
+            engine.Init(forEncryption, param);
+
+            this.forEncryption = forEncryption;
+        }
+
+        public int GetInputBlockSize()
+        {
+            int baseBlockSize = engine.GetInputBlockSize();
+
+            if (forEncryption)
+            {
+                return baseBlockSize - 1 - 2 * defHash.Length;
+            }
+            else
+            {
+                return baseBlockSize;
+            }
+        }
+
+        public int GetOutputBlockSize()
+        {
+            int baseBlockSize = engine.GetOutputBlockSize();
+
+            if (forEncryption)
+            {
+                return baseBlockSize;
+            }
+            else
+            {
+                return baseBlockSize - 1 - 2 * defHash.Length;
+            }
+        }
+
+        public byte[] ProcessBlock(
+            byte[]	inBytes,
+            int		inOff,
+            int		inLen)
+        {
+            if (forEncryption)
+            {
+                return EncodeBlock(inBytes, inOff, inLen);
+            }
+            else
+            {
+                return DecodeBlock(inBytes, inOff, inLen);
+            }
+        }
+
+        private byte[] EncodeBlock(
+            byte[]	inBytes,
+            int		inOff,
+            int		inLen)
+        {
+            byte[] block = new byte[GetInputBlockSize() + 1 + 2 * defHash.Length];
+
+            //
+            // copy in the message
+            //
+            Array.Copy(inBytes, inOff, block, block.Length - inLen, inLen);
+
+            //
+            // add sentinel
+            //
+            block[block.Length - inLen - 1] = 0x01;
+
+            //
+            // as the block is already zeroed - there's no need to add PS (the >= 0 pad of 0)
+            //
+
+            //
+            // add the hash of the encoding params.
+            //
+            Array.Copy(defHash, 0, block, defHash.Length, defHash.Length);
+
+            //
+            // generate the seed.
+            //
+            byte[] seed = random.GenerateSeed(defHash.Length);
+
+            //
+            // mask the message block.
+            //
+            byte[] mask = maskGeneratorFunction1(seed, 0, seed.Length, block.Length - defHash.Length);
+
+            for (int i = defHash.Length; i != block.Length; i++)
+            {
+                block[i] ^= mask[i - defHash.Length];
+            }
+
+            //
+            // add in the seed
+            //
+            Array.Copy(seed, 0, block, 0, defHash.Length);
+
+            //
+            // mask the seed.
+            //
+            mask = maskGeneratorFunction1(
+                block, defHash.Length, block.Length - defHash.Length, defHash.Length);
+
+            for (int i = 0; i != defHash.Length; i++)
+            {
+                block[i] ^= mask[i];
+            }
+
+            return engine.ProcessBlock(block, 0, block.Length);
+        }
+
+        /**
+        * @exception InvalidCipherTextException if the decrypted block turns out to
+        * be badly formatted.
+        */
+        private byte[] DecodeBlock(
+            byte[]	inBytes,
+            int		inOff,
+            int		inLen)
+        {
+            byte[] data = engine.ProcessBlock(inBytes, inOff, inLen);
+            byte[] block;
+
+            //
+            // as we may have zeros in our leading bytes for the block we produced
+            // on encryption, we need to make sure our decrypted block comes back
+            // the same size.
+            //
+            if (data.Length < engine.GetOutputBlockSize())
+            {
+                block = new byte[engine.GetOutputBlockSize()];
+
+                Array.Copy(data, 0, block, block.Length - data.Length, data.Length);
+            }
+            else
+            {
+                block = data;
+            }
+
+            if (block.Length < (2 * defHash.Length) + 1)
+            {
+                throw new InvalidCipherTextException("data too short");
+            }
+
+            //
+            // unmask the seed.
+            //
+            byte[] mask = maskGeneratorFunction1(
+                block, defHash.Length, block.Length - defHash.Length, defHash.Length);
+
+            for (int i = 0; i != defHash.Length; i++)
+            {
+                block[i] ^= mask[i];
+            }
+
+            //
+            // unmask the message block.
+            //
+            mask = maskGeneratorFunction1(block, 0, defHash.Length, block.Length - defHash.Length);
+
+            for (int i = defHash.Length; i != block.Length; i++)
+            {
+                block[i] ^= mask[i - defHash.Length];
+            }
+
+            //
+            // check the hash of the encoding params.
+            // long check to try to avoid this been a source of a timing attack.
+            //
+            {
+                int diff = 0;
+                for (int i = 0; i < defHash.Length; ++i)
+                {
+                    diff |= (byte)(defHash[i] ^ block[defHash.Length + i]);
+                }
+ 
+                if (diff != 0)
+                    throw new InvalidCipherTextException("data hash wrong");
+            }
+
+            //
+            // find the data block
+            //
+            int start;
+            for (start = 2 * defHash.Length; start != block.Length; start++)
+            {
+                if (block[start] != 0)
+                {
+                    break;
+                }
+            }
+
+            if (start >= (block.Length - 1) || block[start] != 1)
+            {
+                throw new InvalidCipherTextException("data start wrong " + start);
+            }
+
+            start++;
+
+            //
+            // extract the data block
+            //
+            byte[] output = new byte[block.Length - start];
+
+            Array.Copy(block, start, output, 0, output.Length);
+
+            return output;
+        }
+
+        /**
+        * int to octet string.
+        */
+        private void ItoOSP(
+            int		i,
+            byte[]	sp)
+        {
+            sp[0] = (byte)((uint)i >> 24);
+            sp[1] = (byte)((uint)i >> 16);
+            sp[2] = (byte)((uint)i >> 8);
+            sp[3] = (byte)((uint)i >> 0);
+        }
+
+        /**
+        * mask generator function, as described in PKCS1v2.
+        */
+        private byte[] maskGeneratorFunction1(
+            byte[]	Z,
+            int		zOff,
+            int		zLen,
+            int		length)
+        {
+            byte[] mask = new byte[length];
+            byte[] hashBuf = new byte[mgf1Hash.GetDigestSize()];
+            byte[] C = new byte[4];
+            int counter = 0;
+
+            hash.Reset();
+
+            do
+            {
+                ItoOSP(counter, C);
+
+                mgf1Hash.BlockUpdate(Z, zOff, zLen);
+                mgf1Hash.BlockUpdate(C, 0, C.Length);
+                mgf1Hash.DoFinal(hashBuf, 0);
+
+                Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, hashBuf.Length);
+            }
+            while (++counter < (length / hashBuf.Length));
+
+            if ((counter * hashBuf.Length) < length)
+            {
+                ItoOSP(counter, C);
+
+                mgf1Hash.BlockUpdate(Z, zOff, zLen);
+                mgf1Hash.BlockUpdate(C, 0, C.Length);
+                mgf1Hash.DoFinal(hashBuf, 0);
+
+                Array.Copy(hashBuf, 0, mask, counter * hashBuf.Length, mask.Length - (counter * hashBuf.Length));
+            }
+
+            return mask;
+        }
+    }
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/encodings/Pkcs1Encoding.cs b/BouncyCastle.AxCrypt/src/crypto/encodings/Pkcs1Encoding.cs
new file mode 100644
index 0000000..35fd96a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/encodings/Pkcs1Encoding.cs
@@ -0,0 +1,382 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Encodings
+{
+    /**
+    * this does your basic Pkcs 1 v1.5 padding - whether or not you should be using this
+    * depends on your application - see Pkcs1 Version 2 for details.
+    */
+    public class Pkcs1Encoding
+        : IAsymmetricBlockCipher
+    {
+        /**
+         * some providers fail to include the leading zero in PKCS1 encoded blocks. If you need to
+         * work with one of these set the system property Org.BouncyCastle.Pkcs1.Strict to false.
+         */
+        public const string StrictLengthEnabledProperty = "Org.BouncyCastle.Pkcs1.Strict";
+
+        private const int HeaderLength = 10;
+
+        /**
+         * The same effect can be achieved by setting the static property directly
+         * <p>
+         * The static property is checked during construction of the encoding object, it is set to
+         * true by default.
+         * </p>
+         */
+        public static bool StrictLengthEnabled
+        {
+            get { return strictLengthEnabled[0]; }
+            set { strictLengthEnabled[0] = value; }
+        }
+
+        private static readonly bool[] strictLengthEnabled;
+
+        static Pkcs1Encoding()
+        {
+            string strictProperty = Platform.GetEnvironmentVariable(StrictLengthEnabledProperty);
+
+            strictLengthEnabled = new bool[]{ strictProperty == null || strictProperty.Equals("true")};
+        }
+
+
+        private SecureRandom			random;
+        private IAsymmetricBlockCipher	engine;
+        private bool					forEncryption;
+        private bool					forPrivateKey;
+        private bool					useStrictLength;
+        private int                     pLen = -1;
+        private byte[]                  fallback = null;
+
+        /**
+         * Basic constructor.
+         * @param cipher
+         */
+        public Pkcs1Encoding(
+            IAsymmetricBlockCipher cipher)
+        {
+            this.engine = cipher;
+            this.useStrictLength = StrictLengthEnabled;
+        }
+
+        /**
+         * Constructor for decryption with a fixed plaintext length.
+         * 
+         * @param cipher The cipher to use for cryptographic operation.
+         * @param pLen Length of the expected plaintext.
+         */
+        public Pkcs1Encoding(IAsymmetricBlockCipher cipher, int pLen)
+        {
+            this.engine = cipher;
+            this.useStrictLength = StrictLengthEnabled;
+            this.pLen = pLen;
+        }
+
+        /**
+         * Constructor for decryption with a fixed plaintext length and a fallback
+         * value that is returned, if the padding is incorrect.
+         * 
+         * @param cipher
+         *            The cipher to use for cryptographic operation.
+         * @param fallback
+         *            The fallback value, we don't to a arraycopy here.
+         */
+        public Pkcs1Encoding(IAsymmetricBlockCipher cipher, byte[] fallback)
+        {
+            this.engine = cipher;
+            this.useStrictLength = StrictLengthEnabled;
+            this.fallback = fallback;
+            this.pLen = fallback.Length;
+        }
+
+        public IAsymmetricBlockCipher GetUnderlyingCipher()
+        {
+            return engine;
+        }
+
+        public string AlgorithmName
+        {
+            get { return engine.AlgorithmName + "/PKCS1Padding"; }
+        }
+
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            AsymmetricKeyParameter kParam;
+            if (parameters is ParametersWithRandom)
+            {
+                ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+                this.random = rParam.Random;
+                kParam = (AsymmetricKeyParameter)rParam.Parameters;
+            }
+            else
+            {
+                this.random = new SecureRandom();
+                kParam = (AsymmetricKeyParameter)parameters;
+            }
+
+            engine.Init(forEncryption, parameters);
+
+            this.forPrivateKey = kParam.IsPrivate;
+            this.forEncryption = forEncryption;
+        }
+
+        public int GetInputBlockSize()
+        {
+            int baseBlockSize = engine.GetInputBlockSize();
+
+            return forEncryption
+                ?	baseBlockSize - HeaderLength
+                :	baseBlockSize;
+        }
+
+        public int GetOutputBlockSize()
+        {
+            int baseBlockSize = engine.GetOutputBlockSize();
+
+            return forEncryption
+                ?	baseBlockSize
+                :	baseBlockSize - HeaderLength;
+        }
+
+        public byte[] ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            int		length)
+        {
+            return forEncryption
+                ?	EncodeBlock(input, inOff, length)
+                :	DecodeBlock(input, inOff, length);
+        }
+
+        private byte[] EncodeBlock(
+            byte[]	input,
+            int		inOff,
+            int		inLen)
+        {
+            if (inLen > GetInputBlockSize())
+                throw new ArgumentException("input data too large", "inLen");
+
+            byte[] block = new byte[engine.GetInputBlockSize()];
+
+            if (forPrivateKey)
+            {
+                block[0] = 0x01;                        // type code 1
+
+                for (int i = 1; i != block.Length - inLen - 1; i++)
+                {
+                    block[i] = (byte)0xFF;
+                }
+            }
+            else
+            {
+                random.NextBytes(block);                // random fill
+
+                block[0] = 0x02;                        // type code 2
+
+                //
+                // a zero byte marks the end of the padding, so all
+                // the pad bytes must be non-zero.
+                //
+                for (int i = 1; i != block.Length - inLen - 1; i++)
+                {
+                    while (block[i] == 0)
+                    {
+                        block[i] = (byte)random.NextInt();
+                    }
+                }
+            }
+
+            block[block.Length - inLen - 1] = 0x00;       // mark the end of the padding
+            Array.Copy(input, inOff, block, block.Length - inLen, inLen);
+
+            return engine.ProcessBlock(block, 0, block.Length);
+        }
+
+        /**
+         * Checks if the argument is a correctly PKCS#1.5 encoded Plaintext
+         * for encryption.
+         * 
+         * @param encoded The Plaintext.
+         * @param pLen Expected length of the plaintext.
+         * @return Either 0, if the encoding is correct, or -1, if it is incorrect.
+         */
+        private static int CheckPkcs1Encoding(byte[] encoded, int pLen)
+        {
+            int correct = 0;
+            /*
+             * Check if the first two bytes are 0 2
+             */
+            correct |= (encoded[0] ^ 2);
+
+            /*
+             * Now the padding check, check for no 0 byte in the padding
+             */
+            int plen = encoded.Length - (
+                      pLen /* Lenght of the PMS */
+                    +  1 /* Final 0-byte before PMS */
+            );
+
+            for (int i = 1; i < plen; i++)
+            {
+                int tmp = encoded[i];
+                tmp |= tmp >> 1;
+                tmp |= tmp >> 2;
+                tmp |= tmp >> 4;
+                correct |= (tmp & 1) - 1;
+            }
+
+            /*
+             * Make sure the padding ends with a 0 byte.
+             */
+            correct |= encoded[encoded.Length - (pLen + 1)];
+
+            /*
+             * Return 0 or 1, depending on the result.
+             */
+            correct |= correct >> 1;
+            correct |= correct >> 2;
+            correct |= correct >> 4;
+            return ~((correct & 1) - 1);
+        }
+
+        /**
+         * Decode PKCS#1.5 encoding, and return a random value if the padding is not correct.
+         * 
+         * @param in The encrypted block.
+         * @param inOff Offset in the encrypted block.
+         * @param inLen Length of the encrypted block.
+         * @param pLen Length of the desired output.
+         * @return The plaintext without padding, or a random value if the padding was incorrect.
+         * 
+         * @throws InvalidCipherTextException
+         */
+        private byte[] DecodeBlockOrRandom(byte[] input, int inOff, int inLen)
+        {
+            if (!forPrivateKey)
+                throw new InvalidCipherTextException("sorry, this method is only for decryption, not for signing");
+
+            byte[] block = engine.ProcessBlock(input, inOff, inLen);
+            byte[] random = null;
+            if (this.fallback == null)
+            {
+                random = new byte[this.pLen];
+                this.random.NextBytes(random);
+            }
+            else
+            {
+                random = fallback;
+            }
+
+            /*
+             * TODO: This is a potential dangerous side channel. However, you can
+             * fix this by changing the RSA engine in a way, that it will always
+             * return blocks of the same length and prepend them with 0 bytes if
+             * needed.
+             */
+            if (block.Length < GetOutputBlockSize())
+                throw new InvalidCipherTextException("block truncated");
+
+            /*
+             * TODO: Potential side channel. Fix it by making the engine always
+             * return blocks of the correct length.
+             */
+            if (useStrictLength && block.Length != engine.GetOutputBlockSize())
+                throw new InvalidCipherTextException("block incorrect size");
+
+            /*
+             * Check the padding.
+             */
+            int correct = Pkcs1Encoding.CheckPkcs1Encoding(block, this.pLen);
+
+            /*
+             * Now, to a constant time constant memory copy of the decrypted value
+             * or the random value, depending on the validity of the padding.
+             */
+            byte[] result = new byte[this.pLen];
+            for (int i = 0; i < this.pLen; i++)
+            {
+                result[i] = (byte)((block[i+(block.Length-pLen)]&(~correct)) | (random[i]&correct));
+            }
+
+            return result;
+        }
+
+        /**
+        * @exception InvalidCipherTextException if the decrypted block is not in Pkcs1 format.
+        */
+        private byte[] DecodeBlock(
+            byte[]	input,
+            int		inOff,
+            int		inLen)
+        {
+            /*
+             * If the length of the expected plaintext is known, we use a constant-time decryption.
+             * If the decryption fails, we return a random value.
+             */
+            if (this.pLen != -1)
+            {
+                return this.DecodeBlockOrRandom(input, inOff, inLen);
+            }
+
+            byte[] block = engine.ProcessBlock(input, inOff, inLen);
+
+            if (block.Length < GetOutputBlockSize())
+            {
+                throw new InvalidCipherTextException("block truncated");
+            }
+
+            byte type = block[0];
+
+            if (type != 1 && type != 2)
+            {
+                throw new InvalidCipherTextException("unknown block type");
+            }
+
+            if (useStrictLength && block.Length != engine.GetOutputBlockSize())
+            {
+                throw new InvalidCipherTextException("block incorrect size");
+            }
+
+            //
+            // find and extract the message block.
+            //
+            int start;
+            for (start = 1; start != block.Length; start++)
+            {
+                byte pad = block[start];
+
+                if (pad == 0)
+                {
+                    break;
+                }
+
+                if (type == 1 && pad != (byte)0xff)
+                {
+                    throw new InvalidCipherTextException("block padding incorrect");
+                }
+            }
+
+            start++;           // data should start at the next byte
+
+            if (start > block.Length || start < HeaderLength)
+            {
+                throw new InvalidCipherTextException("no data in block");
+            }
+
+            byte[] result = new byte[block.Length - start];
+
+            Array.Copy(block, start, result, 0, result.Length);
+
+            return result;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/AesEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/AesEngine.cs
new file mode 100644
index 0000000..0cdd868
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/AesEngine.cs
@@ -0,0 +1,532 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * an implementation of the AES (Rijndael), from FIPS-197.
+    * <p>
+    * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+    *
+    * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+    * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+    *
+    * There are three levels of tradeoff of speed vs memory
+    * Because java has no preprocessor, they are written as three separate classes from which to choose
+    *
+    * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+    * and 4 for decryption.
+    *
+    * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+    * adding 12 rotate operations per round to compute the values contained in the other tables from
+    * the contents of the first.
+    *
+    * The slowest version uses no static tables at all and computes the values in each round.
+    * </p>
+    * <p>
+    * This file contains the middle performance version with 2Kbytes of static tables for round precomputation.
+    * </p>
+    */
+    public class AesEngine
+        : IBlockCipher
+    {
+        // The S box
+        private static readonly byte[] S =
+        {
+            99,	124, 119, 123, 242, 107, 111, 197,
+            48, 1, 103, 43, 254, 215, 171, 118,
+            202, 130, 201, 125, 250, 89, 71, 240,
+            173, 212, 162, 175, 156, 164, 114, 192,
+            183, 253, 147, 38, 54, 63, 247, 204,
+            52, 165, 229, 241, 113, 216, 49, 21,
+            4, 199, 35, 195, 24, 150, 5, 154,
+            7, 18, 128, 226, 235, 39, 178, 117,
+            9, 131, 44, 26, 27, 110, 90, 160,
+            82, 59, 214, 179, 41, 227, 47, 132,
+            83, 209, 0, 237, 32, 252, 177, 91,
+            106, 203, 190, 57, 74, 76, 88, 207,
+            208, 239, 170, 251, 67, 77, 51, 133,
+            69, 249, 2, 127, 80, 60, 159, 168,
+            81, 163, 64, 143, 146, 157, 56, 245,
+            188, 182, 218, 33, 16, 255, 243, 210,
+            205, 12, 19, 236, 95, 151, 68, 23,
+            196, 167, 126, 61, 100, 93, 25, 115,
+            96, 129, 79, 220, 34, 42, 144, 136,
+            70, 238, 184, 20, 222, 94, 11, 219,
+            224, 50, 58, 10, 73, 6, 36, 92,
+            194, 211, 172, 98, 145, 149, 228, 121,
+            231, 200, 55, 109, 141, 213, 78, 169,
+            108, 86, 244, 234, 101, 122, 174, 8,
+            186, 120, 37, 46, 28, 166, 180, 198,
+            232, 221, 116, 31, 75, 189, 139, 138,
+            112, 62, 181, 102, 72, 3, 246, 14,
+            97, 53, 87, 185, 134, 193, 29, 158,
+            225, 248, 152, 17, 105, 217, 142, 148,
+            155, 30, 135, 233, 206, 85, 40, 223,
+            140, 161, 137, 13, 191, 230, 66, 104,
+            65, 153, 45, 15, 176, 84, 187, 22,
+        };
+
+        // The inverse S-box
+        private static readonly byte[] Si =
+        {
+            82, 9, 106, 213, 48, 54, 165, 56,
+            191, 64, 163, 158, 129, 243, 215, 251,
+            124, 227, 57, 130, 155, 47, 255, 135,
+            52, 142, 67, 68, 196, 222, 233, 203,
+            84, 123, 148, 50, 166, 194, 35, 61,
+            238, 76, 149, 11, 66, 250, 195, 78,
+            8, 46, 161, 102, 40, 217, 36, 178,
+            118, 91, 162, 73, 109, 139, 209, 37,
+            114, 248, 246, 100, 134, 104, 152, 22,
+            212, 164, 92, 204, 93, 101, 182, 146,
+            108, 112, 72, 80, 253, 237, 185, 218,
+            94, 21, 70, 87, 167, 141, 157, 132,
+            144, 216, 171, 0, 140, 188, 211, 10,
+            247, 228, 88, 5, 184, 179, 69, 6,
+            208, 44, 30, 143, 202, 63, 15, 2,
+            193, 175, 189, 3, 1, 19, 138, 107,
+            58, 145, 17, 65, 79, 103, 220, 234,
+            151, 242, 207, 206, 240, 180, 230, 115,
+            150, 172, 116, 34, 231, 173, 53, 133,
+            226, 249, 55, 232, 28, 117, 223, 110,
+            71, 241, 26, 113, 29, 41, 197, 137,
+            111, 183, 98, 14, 170, 24, 190, 27,
+            252, 86, 62, 75, 198, 210, 121, 32,
+            154, 219, 192, 254, 120, 205, 90, 244,
+            31, 221, 168, 51, 136, 7, 199, 49,
+            177, 18, 16, 89, 39, 128, 236, 95,
+            96, 81, 127, 169, 25, 181, 74, 13,
+            45, 229, 122, 159, 147, 201, 156, 239,
+            160, 224, 59, 77, 174, 42, 245, 176,
+            200, 235, 187, 60, 131, 83, 153, 97,
+            23, 43, 4, 126, 186, 119, 214, 38,
+            225, 105, 20, 99, 85, 33, 12, 125,
+        };
+
+        // vector used in calculating key schedule (powers of x in GF(256))
+        private static readonly byte[] rcon =
+        {
+            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+        };
+
+        // precomputation tables of calculations for rounds
+        private static readonly uint[] T0 =
+        {
+            0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+            0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+            0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+            0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+            0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+            0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+            0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+            0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+            0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+            0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+            0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+            0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+            0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+            0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+            0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+            0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+            0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+            0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+            0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+            0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+            0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+            0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+            0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+            0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+            0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+            0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+            0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+            0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+            0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+            0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+            0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+            0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+            0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+            0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+            0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+            0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+            0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+            0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+            0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+            0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+            0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+            0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+            0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+            0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+            0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+            0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+            0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+            0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+            0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+            0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+            0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+            0x3a16162c
+        };
+
+        private static readonly uint[] Tinv0 =
+        {
+            0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+            0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+            0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+            0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+            0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+            0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+            0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+            0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+            0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+            0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+            0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+            0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+            0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+            0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+            0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+            0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+            0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+            0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+            0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+            0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+            0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+            0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+            0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+            0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+            0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+            0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+            0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+            0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+            0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+            0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+            0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+            0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+            0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+            0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+            0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+            0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+            0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+            0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+            0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+            0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+            0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+            0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+            0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+            0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+            0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+            0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+            0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+            0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+            0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+            0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+            0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+            0x4257b8d0
+        };
+
+        private static uint Shift(uint r, int shift)
+        {
+            return (r >> shift) | (r << (32 - shift));
+        }
+
+        /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+        private const uint m1 = 0x80808080;
+        private const uint m2 = 0x7f7f7f7f;
+        private const uint m3 = 0x0000001b;
+
+        private static uint FFmulX(uint x)
+        {
+            return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3);
+        }
+
+        /*
+        The following defines provide alternative definitions of FFmulX that might
+        give improved performance if a fast 32-bit multiply is not available.
+
+        private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+        private static final int  m4 = 0x1b1b1b1b;
+        private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+        */
+
+        private static uint Inv_Mcol(uint x)
+        {
+            uint f2 = FFmulX(x);
+            uint f4 = FFmulX(f2);
+            uint f8 = FFmulX(f4);
+            uint f9 = x ^ f8;
+
+            return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
+        }
+
+        private static uint SubWord(uint x)
+        {
+            return (uint)S[x&255]
+                | (((uint)S[(x>>8)&255]) << 8)
+                | (((uint)S[(x>>16)&255]) << 16)
+                | (((uint)S[(x>>24)&255]) << 24);
+        }
+
+        /**
+        * Calculate the necessary round keys
+        * The number of calculations depends on key size and block size
+        * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+        * This code is written assuming those are the only possible values
+        */
+        private uint[][] GenerateWorkingKey(
+            byte[]	key,
+            bool	forEncryption)
+        {
+            int KC = key.Length / 4;  // key length in words
+            int t;
+
+            if ((KC != 4) && (KC != 6) && (KC != 8)) 
+                throw new ArgumentException("Key length not 128/192/256 bits.");
+
+            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+
+            uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
+            for (int i = 0; i <= ROUNDS; ++i)
+            {
+                W[i] = new uint[4];
+            }
+
+            //
+            // copy the key into the round key array
+            //
+
+            t = 0;
+            for (int i = 0; i < key.Length; t++)
+            {
+                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
+                i+=4;
+            }
+
+            //
+            // while not enough round key material calculated
+            // calculate new values
+            //
+            int k = (ROUNDS + 1) << 2;
+            for (int i = KC; (i < k); i++)
+            {
+                uint temp = W[(i-1)>>2][(i-1)&3];
+                if ((i % KC) == 0) 
+                {
+                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
+                } 
+                else if ((KC > 6) && ((i % KC) == 4)) 
+                {
+                    temp = SubWord(temp);
+                }
+
+                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+            }
+
+            if (!forEncryption)
+            {
+                for (int j = 1; j < ROUNDS; j++)
+                {
+                    uint[] w = W[j];
+                    for (int i = 0; i < 4; i++)
+                    {
+                        w[i] = Inv_Mcol(w[i]);
+                    }
+                }
+            }
+
+            return W;
+        }
+
+        private int ROUNDS;
+        private uint[][] WorkingKey;
+        private uint C0, C1, C2, C3;
+        private bool forEncryption;
+
+        private const int BLOCK_SIZE = 16;
+
+        /**
+        * default constructor - 128 bit block size.
+        */
+        public AesEngine()
+        {
+        }
+
+        /**
+        * initialise an AES cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            KeyParameter keyParameter = parameters as KeyParameter;
+
+            if (keyParameter == null)
+                throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name);
+
+            WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
+
+            this.forEncryption = forEncryption;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "AES"; }
+        }
+
+        public bool IsPartialBlockOkay
+        {
+            get { return false; }
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (WorkingKey == null)
+            {
+                throw new InvalidOperationException("AES engine not initialised");
+            }
+
+            if ((inOff + (32 / 2)) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + (32 / 2)) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            UnPackBlock(input, inOff);
+
+            if (forEncryption)
+            {
+                EncryptBlock(WorkingKey);
+            }
+            else
+            {
+                DecryptBlock(WorkingKey);
+            }
+
+            PackBlock(output, outOff);
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+        }
+
+        private void UnPackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            C0 = Pack.LE_To_UInt32(bytes, off);
+            C1 = Pack.LE_To_UInt32(bytes, off + 4);
+            C2 = Pack.LE_To_UInt32(bytes, off + 8);
+            C3 = Pack.LE_To_UInt32(bytes, off + 12);
+        }
+
+        private void PackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            Pack.UInt32_To_LE(C0, bytes, off);
+            Pack.UInt32_To_LE(C1, bytes, off + 4);
+            Pack.UInt32_To_LE(C2, bytes, off + 8);
+            Pack.UInt32_To_LE(C3, bytes, off + 12);
+        }
+
+        private void EncryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[0];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = 1;
+            while (r < ROUNDS - 1)
+            {
+                kw = KW[r++];
+                r0 = T0[t0 & 255] ^ Shift(T0[(t1 >> 8) & 255], 24) ^ Shift(T0[(t2 >> 16) & 255], 16) ^ Shift(T0[(r3 >> 24) & 255], 8) ^ kw[0];
+                r1 = T0[t1 & 255] ^ Shift(T0[(t2 >> 8) & 255], 24) ^ Shift(T0[(r3 >> 16) & 255], 16) ^ Shift(T0[(t0 >> 24) & 255], 8) ^ kw[1];
+                r2 = T0[t2 & 255] ^ Shift(T0[(r3 >> 8) & 255], 24) ^ Shift(T0[(t0 >> 16) & 255], 16) ^ Shift(T0[(t1 >> 24) & 255], 8) ^ kw[2];
+                r3 = T0[r3 & 255] ^ Shift(T0[(t0 >> 8) & 255], 24) ^ Shift(T0[(t1 >> 16) & 255], 16) ^ Shift(T0[(t2 >> 24) & 255], 8) ^ kw[3];
+                kw = KW[r++];
+                t0 = T0[r0 & 255] ^ Shift(T0[(r1 >> 8) & 255], 24) ^ Shift(T0[(r2 >> 16) & 255], 16) ^ Shift(T0[(r3 >> 24) & 255], 8) ^ kw[0];
+                t1 = T0[r1 & 255] ^ Shift(T0[(r2 >> 8) & 255], 24) ^ Shift(T0[(r3 >> 16) & 255], 16) ^ Shift(T0[(r0 >> 24) & 255], 8) ^ kw[1];
+                t2 = T0[r2 & 255] ^ Shift(T0[(r3 >> 8) & 255], 24) ^ Shift(T0[(r0 >> 16) & 255], 16) ^ Shift(T0[(r1 >> 24) & 255], 8) ^ kw[2];
+                r3 = T0[r3 & 255] ^ Shift(T0[(r0 >> 8) & 255], 24) ^ Shift(T0[(r1 >> 16) & 255], 16) ^ Shift(T0[(r2 >> 24) & 255], 8) ^ kw[3];
+            }
+
+            kw = KW[r++];
+            r0 = T0[t0 & 255] ^ Shift(T0[(t1 >> 8) & 255], 24) ^ Shift(T0[(t2 >> 16) & 255], 16) ^ Shift(T0[(r3 >> 24) & 255], 8) ^ kw[0];
+            r1 = T0[t1 & 255] ^ Shift(T0[(t2 >> 8) & 255], 24) ^ Shift(T0[(r3 >> 16) & 255], 16) ^ Shift(T0[(t0 >> 24) & 255], 8) ^ kw[1];
+            r2 = T0[t2 & 255] ^ Shift(T0[(r3 >> 8) & 255], 24) ^ Shift(T0[(t0 >> 16) & 255], 16) ^ Shift(T0[(t1 >> 24) & 255], 8) ^ kw[2];
+            r3 = T0[r3 & 255] ^ Shift(T0[(t0 >> 8) & 255], 24) ^ Shift(T0[(t1 >> 16) & 255], 16) ^ Shift(T0[(t2 >> 24) & 255], 8) ^ kw[3];
+
+            // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+            kw = KW[r];
+            this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0];
+            this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1];
+            this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2];
+            this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3];
+        }
+
+        private void DecryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[ROUNDS];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = ROUNDS - 1;
+            while (r > 1)
+            {
+                kw = KW[r--];
+                r0 = Tinv0[t0 & 255] ^ Shift(Tinv0[(r3 >> 8) & 255], 24) ^ Shift(Tinv0[(t2 >> 16) & 255], 16) ^ Shift(Tinv0[(t1 >> 24) & 255], 8) ^ kw[0];
+                r1 = Tinv0[t1 & 255] ^ Shift(Tinv0[(t0 >> 8) & 255], 24) ^ Shift(Tinv0[(r3 >> 16) & 255], 16) ^ Shift(Tinv0[(t2 >> 24) & 255], 8) ^ kw[1];
+                r2 = Tinv0[t2 & 255] ^ Shift(Tinv0[(t1 >> 8) & 255], 24) ^ Shift(Tinv0[(t0 >> 16) & 255], 16) ^ Shift(Tinv0[(r3 >> 24) & 255], 8) ^ kw[2];
+                r3 = Tinv0[r3 & 255] ^ Shift(Tinv0[(t2 >> 8) & 255], 24) ^ Shift(Tinv0[(t1 >> 16) & 255], 16) ^ Shift(Tinv0[(t0 >> 24) & 255], 8) ^ kw[3];
+                kw = KW[r--];
+                t0 = Tinv0[r0 & 255] ^ Shift(Tinv0[(r3 >> 8) & 255], 24) ^ Shift(Tinv0[(r2 >> 16) & 255], 16) ^ Shift(Tinv0[(r1 >> 24) & 255], 8) ^ kw[0];
+                t1 = Tinv0[r1 & 255] ^ Shift(Tinv0[(r0 >> 8) & 255], 24) ^ Shift(Tinv0[(r3 >> 16) & 255], 16) ^ Shift(Tinv0[(r2 >> 24) & 255], 8) ^ kw[1];
+                t2 = Tinv0[r2 & 255] ^ Shift(Tinv0[(r1 >> 8) & 255], 24) ^ Shift(Tinv0[(r0 >> 16) & 255], 16) ^ Shift(Tinv0[(r3 >> 24) & 255], 8) ^ kw[2];
+                r3 = Tinv0[r3 & 255] ^ Shift(Tinv0[(r2 >> 8) & 255], 24) ^ Shift(Tinv0[(r1 >> 16) & 255], 16) ^ Shift(Tinv0[(r0 >> 24) & 255], 8) ^ kw[3];
+            }
+
+            kw = KW[1];
+            r0 = Tinv0[t0 & 255] ^ Shift(Tinv0[(r3 >> 8) & 255], 24) ^ Shift(Tinv0[(t2 >> 16) & 255], 16) ^ Shift(Tinv0[(t1 >> 24) & 255], 8) ^ kw[0];
+            r1 = Tinv0[t1 & 255] ^ Shift(Tinv0[(t0 >> 8) & 255], 24) ^ Shift(Tinv0[(r3 >> 16) & 255], 16) ^ Shift(Tinv0[(t2 >> 24) & 255], 8) ^ kw[1];
+            r2 = Tinv0[t2 & 255] ^ Shift(Tinv0[(t1 >> 8) & 255], 24) ^ Shift(Tinv0[(t0 >> 16) & 255], 16) ^ Shift(Tinv0[(r3 >> 24) & 255], 8) ^ kw[2];
+            r3 = Tinv0[r3 & 255] ^ Shift(Tinv0[(t2 >> 8) & 255], 24) ^ Shift(Tinv0[(t1 >> 16) & 255], 16) ^ Shift(Tinv0[(t0 >> 24) & 255], 8) ^ kw[3];
+
+            // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+            kw = KW[0];
+            this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0];
+            this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1];
+            this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2];
+            this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/AesFastEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/AesFastEngine.cs
new file mode 100644
index 0000000..38d3a58
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/AesFastEngine.cs
@@ -0,0 +1,864 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * an implementation of the AES (Rijndael)), from FIPS-197.
+    * <p>
+    * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+    *
+    * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+    * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+    *
+    * There are three levels of tradeoff of speed vs memory
+    * Because java has no preprocessor), they are written as three separate classes from which to choose
+    *
+    * The fastest uses 8Kbytes of static tables to precompute round calculations), 4 256 word tables for encryption
+    * and 4 for decryption.
+    *
+    * The middle performance version uses only one 256 word table for each), for a total of 2Kbytes),
+    * adding 12 rotate operations per round to compute the values contained in the other tables from
+    * the contents of the first
+    *
+    * The slowest version uses no static tables at all and computes the values in each round
+    * </p>
+    * <p>
+    * This file contains the fast version with 8Kbytes of static tables for round precomputation
+    * </p>
+    */
+    public class AesFastEngine
+        : IBlockCipher
+    {
+        // The S box
+        private static readonly byte[] S =
+        {
+            99, 124, 119, 123, 242, 107, 111, 197,
+            48,   1, 103,  43, 254, 215, 171, 118,
+            202, 130, 201, 125, 250,  89,  71, 240,
+            173, 212, 162, 175, 156, 164, 114, 192,
+            183, 253, 147,  38,  54,  63, 247, 204,
+            52, 165, 229, 241, 113, 216,  49,  21,
+            4, 199,  35, 195,  24, 150,   5, 154,
+            7,  18, 128, 226, 235,  39, 178, 117,
+            9, 131,  44,  26,  27, 110,  90, 160,
+            82,  59, 214, 179,  41, 227,  47, 132,
+            83, 209,   0, 237,  32, 252, 177,  91,
+            106, 203, 190,  57,  74,  76,  88, 207,
+            208, 239, 170, 251,  67,  77,  51, 133,
+            69, 249,   2, 127,  80,  60, 159, 168,
+            81, 163,  64, 143, 146, 157,  56, 245,
+            188, 182, 218,  33,  16, 255, 243, 210,
+            205,  12,  19, 236,  95, 151,  68,  23,
+            196, 167, 126,  61, 100,  93,  25, 115,
+            96, 129,  79, 220,  34,  42, 144, 136,
+            70, 238, 184,  20, 222,  94,  11, 219,
+            224,  50,  58,  10,  73,   6,  36,  92,
+            194, 211, 172,  98, 145, 149, 228, 121,
+            231, 200,  55, 109, 141, 213,  78, 169,
+            108,  86, 244, 234, 101, 122, 174,   8,
+            186, 120,  37,  46,  28, 166, 180, 198,
+            232, 221, 116,  31,  75, 189, 139, 138,
+            112,  62, 181, 102,  72,   3, 246,  14,
+            97,  53,  87, 185, 134, 193,  29, 158,
+            225, 248, 152,  17, 105, 217, 142, 148,
+            155,  30, 135, 233, 206,  85,  40, 223,
+            140, 161, 137,  13, 191, 230,  66, 104,
+            65, 153,  45,  15, 176,  84, 187,  22,
+        };
+
+        // The inverse S-box
+        private static readonly byte[] Si =
+        {
+            82,   9, 106, 213,  48,  54, 165,  56,
+            191,  64, 163, 158, 129, 243, 215, 251,
+            124, 227,  57, 130, 155,  47, 255, 135,
+            52, 142,  67,  68, 196, 222, 233, 203,
+            84, 123, 148,  50, 166, 194,  35,  61,
+            238,  76, 149,  11,  66, 250, 195,  78,
+            8,  46, 161, 102,  40, 217,  36, 178,
+            118,  91, 162,  73, 109, 139, 209,  37,
+            114, 248, 246, 100, 134, 104, 152,  22,
+            212, 164,  92, 204,  93, 101, 182, 146,
+            108, 112,  72,  80, 253, 237, 185, 218,
+            94,  21,  70,  87, 167, 141, 157, 132,
+            144, 216, 171,   0, 140, 188, 211,  10,
+            247, 228,  88,   5, 184, 179,  69,   6,
+            208,  44,  30, 143, 202,  63,  15,   2,
+            193, 175, 189,   3,   1,  19, 138, 107,
+            58, 145,  17,  65,  79, 103, 220, 234,
+            151, 242, 207, 206, 240, 180, 230, 115,
+            150, 172, 116,  34, 231, 173,  53, 133,
+            226, 249,  55, 232,  28, 117, 223, 110,
+            71, 241,  26, 113,  29,  41, 197, 137,
+            111, 183,  98,  14, 170,  24, 190,  27,
+            252,  86,  62,  75, 198, 210, 121,  32,
+            154, 219, 192, 254, 120, 205,  90, 244,
+            31, 221, 168,  51, 136,   7, 199,  49,
+            177,  18,  16,  89,  39, 128, 236,  95,
+            96,  81, 127, 169,  25, 181,  74,  13,
+            45, 229, 122, 159, 147, 201, 156, 239,
+            160, 224,  59,  77, 174,  42, 245, 176,
+            200, 235, 187,  60, 131,  83, 153,  97,
+            23,  43,   4, 126, 186, 119, 214,  38,
+            225, 105,  20,  99,  85,  33,  12, 125,
+        };
+
+        // vector used in calculating key schedule (powers of x in GF(256))
+        private static readonly byte[] rcon =
+        {
+            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+        };
+
+        // precomputation tables of calculations for rounds
+        private static readonly uint[] T0 =
+        {
+            0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+            0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+            0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+            0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+            0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+            0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+            0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+            0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+            0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+            0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+            0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+            0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+            0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+            0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+            0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+            0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+            0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+            0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+            0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+            0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+            0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+            0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+            0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+            0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+            0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+            0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+            0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+            0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+            0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+            0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+            0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+            0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+            0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+            0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+            0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+            0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+            0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+            0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+            0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+            0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+            0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+            0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+            0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+            0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+            0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+            0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+            0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+            0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+            0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+            0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+            0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+            0x3a16162c
+        };
+
+        private static readonly uint[] T1 =
+        {
+            0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
+            0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
+            0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
+            0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+            0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
+            0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
+            0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
+            0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+            0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
+            0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
+            0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
+            0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+            0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
+            0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
+            0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
+            0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+            0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
+            0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
+            0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
+            0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+            0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
+            0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
+            0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
+            0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+            0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
+            0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
+            0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
+            0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+            0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
+            0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
+            0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
+            0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+            0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
+            0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
+            0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
+            0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+            0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
+            0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
+            0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
+            0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+            0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
+            0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
+            0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
+            0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+            0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
+            0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
+            0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
+            0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+            0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
+            0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
+            0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
+            0x16162c3a
+        };
+
+        private static readonly uint[] T2 =
+        {
+            0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
+            0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
+            0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
+            0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+            0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
+            0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
+            0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
+            0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+            0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
+            0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
+            0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
+            0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+            0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
+            0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
+            0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
+            0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+            0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
+            0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
+            0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
+            0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+            0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
+            0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
+            0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
+            0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+            0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
+            0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
+            0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
+            0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+            0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
+            0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
+            0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
+            0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+            0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
+            0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
+            0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
+            0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+            0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
+            0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
+            0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
+            0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+            0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
+            0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
+            0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
+            0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+            0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
+            0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
+            0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
+            0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+            0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
+            0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
+            0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
+            0x162c3a16
+        };
+
+        private static readonly uint[] T3 =
+        {
+            0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
+            0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
+            0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
+            0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+            0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
+            0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
+            0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
+            0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+            0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
+            0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
+            0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
+            0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+            0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
+            0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
+            0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
+            0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+            0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
+            0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
+            0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
+            0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+            0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
+            0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
+            0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
+            0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+            0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
+            0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
+            0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
+            0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+            0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
+            0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
+            0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
+            0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+            0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
+            0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
+            0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
+            0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+            0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
+            0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
+            0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
+            0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+            0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
+            0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
+            0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
+            0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+            0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
+            0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
+            0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
+            0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+            0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
+            0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
+            0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
+            0x2c3a1616
+        };
+
+        private static readonly uint[] Tinv0 =
+        {
+            0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+            0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+            0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+            0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+            0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+            0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+            0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+            0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+            0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+            0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+            0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+            0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+            0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+            0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+            0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+            0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+            0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+            0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+            0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+            0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+            0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+            0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+            0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+            0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+            0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+            0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+            0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+            0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+            0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+            0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+            0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+            0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+            0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+            0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+            0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+            0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+            0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+            0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+            0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+            0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+            0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+            0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+            0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+            0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+            0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+            0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+            0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+            0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+            0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+            0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+            0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+            0x4257b8d0
+        };
+
+        private static readonly uint[] Tinv1 =
+        {
+            0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
+            0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
+            0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
+            0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
+            0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
+            0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
+            0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
+            0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
+            0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
+            0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
+            0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
+            0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
+            0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
+            0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
+            0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
+            0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
+            0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
+            0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
+            0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
+            0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
+            0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
+            0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
+            0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
+            0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
+            0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
+            0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
+            0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
+            0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
+            0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
+            0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
+            0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
+            0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
+            0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
+            0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
+            0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
+            0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
+            0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
+            0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
+            0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
+            0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
+            0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
+            0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
+            0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
+            0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
+            0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
+            0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
+            0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
+            0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
+            0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
+            0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
+            0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
+            0x57b8d042
+        };
+
+        private static readonly uint[] Tinv2 =
+        {
+            0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
+            0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
+            0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
+            0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
+            0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
+            0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
+            0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
+            0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
+            0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
+            0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
+            0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
+            0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
+            0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
+            0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
+            0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
+            0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
+            0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
+            0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
+            0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
+            0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
+            0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
+            0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
+            0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
+            0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
+            0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
+            0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
+            0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
+            0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
+            0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
+            0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
+            0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
+            0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
+            0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
+            0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
+            0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
+            0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
+            0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
+            0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
+            0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
+            0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
+            0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
+            0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
+            0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
+            0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
+            0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
+            0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
+            0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
+            0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
+            0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
+            0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
+            0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
+            0xb8d04257
+        };
+
+        private static readonly uint[] Tinv3 =
+        {
+            0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
+            0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
+            0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
+            0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
+            0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
+            0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
+            0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
+            0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
+            0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
+            0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
+            0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
+            0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
+            0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
+            0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
+            0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
+            0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
+            0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
+            0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
+            0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
+            0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
+            0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
+            0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
+            0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
+            0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
+            0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
+            0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
+            0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
+            0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
+            0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
+            0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
+            0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
+            0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
+            0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
+            0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
+            0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
+            0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
+            0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
+            0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
+            0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
+            0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
+            0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
+            0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
+            0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
+            0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
+            0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
+            0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
+            0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
+            0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
+            0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
+            0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
+            0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
+            0xd04257b8
+        };
+
+        private static uint Shift(uint r, int shift)
+        {
+            return (r >> shift) | (r << (32 - shift));
+        }
+
+        /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+        private const uint m1 = 0x80808080;
+        private const uint m2 = 0x7f7f7f7f;
+        private const uint m3 = 0x0000001b;
+
+        private static uint FFmulX(uint x)
+        {
+            return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3);
+        }
+
+        /*
+        The following defines provide alternative definitions of FFmulX that might
+        give improved performance if a fast 32-bit multiply is not available.
+
+        private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+        private static final int  m4 = 0x1b1b1b1b;
+        private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+        */
+
+        private static uint Inv_Mcol(uint x)
+        {
+            uint f2 = FFmulX(x);
+            uint f4 = FFmulX(f2);
+            uint f8 = FFmulX(f4);
+            uint f9 = x ^ f8;
+
+            return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
+        }
+
+        private static uint SubWord(uint x)
+        {
+            return (uint)S[x&255]
+                | (((uint)S[(x>>8)&255]) << 8)
+                | (((uint)S[(x>>16)&255]) << 16)
+                | (((uint)S[(x>>24)&255]) << 24);
+        }
+
+        /**
+        * Calculate the necessary round keys
+        * The number of calculations depends on key size and block size
+        * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+        * This code is written assuming those are the only possible values
+        */
+        private uint[][] GenerateWorkingKey(
+            byte[]	key,
+            bool	forEncryption)
+        {
+            int KC = key.Length / 4;  // key length in words
+
+            if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
+                throw new ArgumentException("Key length not 128/192/256 bits.");
+
+            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+
+            uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
+            for (int i = 0; i <= ROUNDS; ++i)
+            {
+                W[i] = new uint[4];
+            }
+
+            //
+            // copy the key into the round key array
+            //
+
+            int t = 0;
+            for (int i = 0; i < key.Length; t++)
+            {
+                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
+                i+=4;
+            }
+
+            //
+            // while not enough round key material calculated
+            // calculate new values
+            //
+            int k = (ROUNDS + 1) << 2;
+            for (int i = KC; (i < k); i++)
+            {
+                uint temp = W[(i-1)>>2][(i-1)&3];
+                if ((i % KC) == 0) {
+                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
+                } else if ((KC > 6) && ((i % KC) == 4)) {
+                    temp = SubWord(temp);
+                }
+
+                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+            }
+
+            if (!forEncryption)
+            {
+                for (int j = 1; j < ROUNDS; j++)
+                {
+                    uint[] w = W[j];
+                    for (int i = 0; i < 4; i++)
+                    {
+                        w[i] = Inv_Mcol(w[i]);
+                    }
+                }
+            }
+
+            return W;
+        }
+
+        private int ROUNDS;
+        private uint[][] WorkingKey;
+        private uint C0, C1, C2, C3;
+        private bool forEncryption;
+
+        private const int BLOCK_SIZE = 16;
+
+        /**
+        * default constructor - 128 bit block size.
+        */
+        public AesFastEngine()
+        {
+        }
+
+        /**
+        * initialise an AES cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            KeyParameter keyParameter = parameters as KeyParameter;
+
+            if (keyParameter == null)
+                throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name);
+
+            WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
+
+            this.forEncryption = forEncryption;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "AES"; }
+        }
+
+        public bool IsPartialBlockOkay
+        {
+            get { return false; }
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public int ProcessBlock(
+            byte[] input,
+            int inOff,
+            byte[] output,
+            int outOff)
+        {
+            if (WorkingKey == null)
+            {
+                throw new InvalidOperationException("AES engine not initialised");
+            }
+
+            if ((inOff + (32 / 2)) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + (32 / 2)) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            UnPackBlock(input, inOff);
+
+            if (forEncryption)
+            {
+                EncryptBlock(WorkingKey);
+            }
+            else
+            {
+                DecryptBlock(WorkingKey);
+            }
+
+            PackBlock(output, outOff);
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+        }
+
+        private void UnPackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            C0 = Pack.LE_To_UInt32(bytes, off);
+            C1 = Pack.LE_To_UInt32(bytes, off + 4);
+            C2 = Pack.LE_To_UInt32(bytes, off + 8);
+            C3 = Pack.LE_To_UInt32(bytes, off + 12);
+        }
+
+        private void PackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            Pack.UInt32_To_LE(C0, bytes, off);
+            Pack.UInt32_To_LE(C1, bytes, off + 4);
+            Pack.UInt32_To_LE(C2, bytes, off + 8);
+            Pack.UInt32_To_LE(C3, bytes, off + 12);
+        }
+
+        private void EncryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[0];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = 1;
+            while (r < ROUNDS - 1)
+            {
+                kw = KW[r++];
+                r0 = T0[t0 & 255] ^ T1[(t1 >> 8) & 255] ^ T2[(t2 >> 16) & 255] ^ T3[r3 >> 24] ^ kw[0];
+                r1 = T0[t1 & 255] ^ T1[(t2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[t0 >> 24] ^ kw[1];
+                r2 = T0[t2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(t0 >> 16) & 255] ^ T3[t1 >> 24] ^ kw[2];
+                r3 = T0[r3 & 255] ^ T1[(t0 >> 8) & 255] ^ T2[(t1 >> 16) & 255] ^ T3[t2 >> 24] ^ kw[3];
+                kw = KW[r++];
+                t0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[r3 >> 24] ^ kw[0];
+                t1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[r0 >> 24] ^ kw[1];
+                t2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[r1 >> 24] ^ kw[2];
+                r3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[r2 >> 24] ^ kw[3];
+            }
+
+            kw = KW[r++];
+            r0 = T0[t0 & 255] ^ T1[(t1 >> 8) & 255] ^ T2[(t2 >> 16) & 255] ^ T3[r3 >> 24] ^ kw[0];
+            r1 = T0[t1 & 255] ^ T1[(t2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[t0 >> 24] ^ kw[1];
+            r2 = T0[t2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(t0 >> 16) & 255] ^ T3[t1 >> 24] ^ kw[2];
+            r3 = T0[r3 & 255] ^ T1[(t0 >> 8) & 255] ^ T2[(t1 >> 16) & 255] ^ T3[t2 >> 24] ^ kw[3];
+
+            // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+            kw = KW[r];
+            this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ kw[0];
+            this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ kw[1];
+            this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ kw[2];
+            this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ kw[3];
+        }
+
+        private void DecryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[ROUNDS];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = ROUNDS - 1;
+            while (r > 1)
+            {
+                kw = KW[r--];
+                r0 = Tinv0[t0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(t2 >> 16) & 255] ^ Tinv3[t1 >> 24] ^ kw[0];
+                r1 = Tinv0[t1 & 255] ^ Tinv1[(t0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[t2 >> 24] ^ kw[1];
+                r2 = Tinv0[t2 & 255] ^ Tinv1[(t1 >> 8) & 255] ^ Tinv2[(t0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ kw[2];
+                r3 = Tinv0[r3 & 255] ^ Tinv1[(t2 >> 8) & 255] ^ Tinv2[(t1 >> 16) & 255] ^ Tinv3[t0 >> 24] ^ kw[3];
+                kw = KW[r--];
+                t0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[r1 >> 24] ^ kw[0];
+                t1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[r2 >> 24] ^ kw[1];
+                t2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ kw[2];
+                r3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[r0 >> 24] ^ kw[3];
+            }
+
+            kw = KW[1];
+            r0 = Tinv0[t0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(t2 >> 16) & 255] ^ Tinv3[t1 >> 24] ^ kw[0];
+            r1 = Tinv0[t1 & 255] ^ Tinv1[(t0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[t2 >> 24] ^ kw[1];
+            r2 = Tinv0[t2 & 255] ^ Tinv1[(t1 >> 8) & 255] ^ Tinv2[(t0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ kw[2];
+            r3 = Tinv0[r3 & 255] ^ Tinv1[(t2 >> 8) & 255] ^ Tinv2[(t1 >> 16) & 255] ^ Tinv3[t0 >> 24] ^ kw[3];
+
+            // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+            kw = KW[0];
+            this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ kw[0];
+            this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ kw[1];
+            this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ kw[2];
+            this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ kw[3];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/AesLightEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/AesLightEngine.cs
new file mode 100644
index 0000000..54f2d2e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/AesLightEngine.cs
@@ -0,0 +1,427 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * an implementation of the AES (Rijndael), from FIPS-197.
+    * <p>
+    * For further details see: <a href="http://csrc.nist.gov/encryption/aes/">http://csrc.nist.gov/encryption/aes/</a>.
+    *
+    * This implementation is based on optimizations from Dr. Brian Gladman's paper and C code at
+    * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+    *
+    * There are three levels of tradeoff of speed vs memory
+    * Because java has no preprocessor, they are written as three separate classes from which to choose
+    *
+    * The fastest uses 8Kbytes of static tables to precompute round calculations, 4 256 word tables for encryption
+    * and 4 for decryption.
+    *
+    * The middle performance version uses only one 256 word table for each, for a total of 2Kbytes,
+    * adding 12 rotate operations per round to compute the values contained in the other tables from
+    * the contents of the first
+    *
+    * The slowest version uses no static tables at all and computes the values
+    * in each round.
+    * </p>
+    * <p>
+    * This file contains the slowest performance version with no static tables
+    * for round precomputation, but it has the smallest foot print.
+    * </p>
+    */
+    public class AesLightEngine
+        : IBlockCipher
+    {
+        // The S box
+        private static readonly byte[] S =
+        {
+            99, 124, 119, 123, 242, 107, 111, 197,
+            48,   1, 103,  43, 254, 215, 171, 118,
+            202, 130, 201, 125, 250,  89,  71, 240,
+            173, 212, 162, 175, 156, 164, 114, 192,
+            183, 253, 147,  38,  54,  63, 247, 204,
+            52, 165, 229, 241, 113, 216,  49,  21,
+            4, 199,  35, 195,  24, 150,   5, 154,
+            7,  18, 128, 226, 235,  39, 178, 117,
+            9, 131,  44,  26,  27, 110,  90, 160,
+            82,  59, 214, 179,  41, 227,  47, 132,
+            83, 209,   0, 237,  32, 252, 177,  91,
+            106, 203, 190,  57,  74,  76,  88, 207,
+            208, 239, 170, 251,  67,  77,  51, 133,
+            69, 249,   2, 127,  80,  60, 159, 168,
+            81, 163,  64, 143, 146, 157,  56, 245,
+            188, 182, 218,  33,  16, 255, 243, 210,
+            205,  12,  19, 236,  95, 151,  68,  23,
+            196, 167, 126,  61, 100,  93,  25, 115,
+            96, 129,  79, 220,  34,  42, 144, 136,
+            70, 238, 184,  20, 222,  94,  11, 219,
+            224,  50,  58,  10,  73,   6,  36,  92,
+            194, 211, 172,  98, 145, 149, 228, 121,
+            231, 200,  55, 109, 141, 213,  78, 169,
+            108,  86, 244, 234, 101, 122, 174,   8,
+            186, 120,  37,  46,  28, 166, 180, 198,
+            232, 221, 116,  31,  75, 189, 139, 138,
+            112,  62, 181, 102,  72,   3, 246,  14,
+            97,  53,  87, 185, 134, 193,  29, 158,
+            225, 248, 152,  17, 105, 217, 142, 148,
+            155,  30, 135, 233, 206,  85,  40, 223,
+            140, 161, 137,  13, 191, 230,  66, 104,
+            65, 153,  45,  15, 176,  84, 187,  22,
+        };
+
+        // The inverse S-box
+        private static readonly byte[] Si =
+        {
+            82,   9, 106, 213,  48,  54, 165,  56,
+            191,  64, 163, 158, 129, 243, 215, 251,
+            124, 227,  57, 130, 155,  47, 255, 135,
+            52, 142,  67,  68, 196, 222, 233, 203,
+            84, 123, 148,  50, 166, 194,  35,  61,
+            238,  76, 149,  11,  66, 250, 195,  78,
+            8,  46, 161, 102,  40, 217,  36, 178,
+            118,  91, 162,  73, 109, 139, 209,  37,
+            114, 248, 246, 100, 134, 104, 152,  22,
+            212, 164,  92, 204,  93, 101, 182, 146,
+            108, 112,  72,  80, 253, 237, 185, 218,
+            94,  21,  70,  87, 167, 141, 157, 132,
+            144, 216, 171,   0, 140, 188, 211,  10,
+            247, 228,  88,   5, 184, 179,  69,   6,
+            208,  44,  30, 143, 202,  63,  15,   2,
+            193, 175, 189,   3,   1,  19, 138, 107,
+            58, 145,  17,  65,  79, 103, 220, 234,
+            151, 242, 207, 206, 240, 180, 230, 115,
+            150, 172, 116,  34, 231, 173,  53, 133,
+            226, 249,  55, 232,  28, 117, 223, 110,
+            71, 241,  26, 113,  29,  41, 197, 137,
+            111, 183,  98,  14, 170,  24, 190,  27,
+            252,  86,  62,  75, 198, 210, 121,  32,
+            154, 219, 192, 254, 120, 205,  90, 244,
+            31, 221, 168,  51, 136,   7, 199,  49,
+            177,  18,  16,  89,  39, 128, 236,  95,
+            96,  81, 127, 169,  25, 181,  74,  13,
+            45, 229, 122, 159, 147, 201, 156, 239,
+            160, 224,  59,  77, 174,  42, 245, 176,
+            200, 235, 187,  60, 131,  83, 153,  97,
+            23,  43,   4, 126, 186, 119, 214,  38,
+            225, 105,  20,  99,  85,  33,  12, 125,
+        };
+
+        // vector used in calculating key schedule (powers of x in GF(256))
+        private static readonly byte[] rcon =
+        {
+            0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+            0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+        };
+
+        private static uint Shift(uint r, int shift)
+        {
+            return (r >> shift) | (r << (32 - shift));
+        }
+
+        /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */
+
+        private const uint m1 = 0x80808080;
+        private const uint m2 = 0x7f7f7f7f;
+        private const uint m3 = 0x0000001b;
+
+        private static uint FFmulX(uint x)
+        {
+            return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3);
+        }
+
+        /*
+        The following defines provide alternative definitions of FFmulX that might
+        give improved performance if a fast 32-bit multiply is not available.
+
+        private int FFmulX(int x) { int u = x & m1; u |= (u >> 1); return ((x & m2) << 1) ^ ((u >>> 3) | (u >>> 6)); }
+        private static final int  m4 = 0x1b1b1b1b;
+        private int FFmulX(int x) { int u = x & m1; return ((x & m2) << 1) ^ ((u - (u >>> 7)) & m4); }
+
+        */
+
+        private static uint Mcol(uint x)
+        {
+            uint f2 = FFmulX(x);
+            return f2 ^ Shift(x ^ f2, 8) ^ Shift(x, 16) ^ Shift(x, 24);
+        }
+
+        private static uint Inv_Mcol(uint x)
+        {
+            uint f2 = FFmulX(x);
+            uint f4 = FFmulX(f2);
+            uint f8 = FFmulX(f4);
+            uint f9 = x ^ f8;
+
+            return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
+        }
+
+        private static uint SubWord(uint x)
+        {
+            return (uint)S[x&255]
+                | (((uint)S[(x>>8)&255]) << 8)
+                | (((uint)S[(x>>16)&255]) << 16)
+                | (((uint)S[(x>>24)&255]) << 24);
+        }
+
+        /**
+        * Calculate the necessary round keys
+        * The number of calculations depends on key size and block size
+        * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits
+        * This code is written assuming those are the only possible values
+        */
+        private uint[][] GenerateWorkingKey(
+            byte[]	key,
+            bool	forEncryption)
+        {
+            int KC = key.Length / 4;  // key length in words
+            int t;
+
+            if ((KC != 4) && (KC != 6) && (KC != 8))
+                throw new ArgumentException("Key length not 128/192/256 bits.");
+
+            ROUNDS = KC + 6;  // This is not always true for the generalized Rijndael that allows larger block sizes
+
+            uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
+            for (int i = 0; i <= ROUNDS; ++i)
+            {
+                W[i] = new uint[4];
+            }
+
+            //
+            // copy the key into the round key array
+            //
+
+            t = 0;
+            for (int i = 0; i < key.Length; t++)
+            {
+                W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i);
+                i+=4;
+            }
+
+            //
+            // while not enough round key material calculated
+            // calculate new values
+            //
+            int k = (ROUNDS + 1) << 2;
+            for (int i = KC; (i < k); i++)
+            {
+                uint temp = W[(i-1)>>2][(i-1)&3];
+                if ((i % KC) == 0) 
+                {
+                    temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1];
+                } 
+                else if ((KC > 6) && ((i % KC) == 4)) 
+                {
+                    temp = SubWord(temp);
+                }
+
+                W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp;
+            }
+
+            if (!forEncryption) 
+            {
+                for (int j = 1; j < ROUNDS; j++) 
+                {
+                    uint[] w = W[j];
+                    for (int i = 0; i < 4; i++)
+                    {
+                        w[i] = Inv_Mcol(w[i]);
+                    }
+                }
+            }
+
+            return W;
+        }
+
+        private int ROUNDS;
+        private uint[][] WorkingKey;
+        private uint C0, C1, C2, C3;
+        private bool forEncryption;
+
+        private const int BLOCK_SIZE = 16;
+
+        /**
+        * default constructor - 128 bit block size.
+        */
+        public AesLightEngine()
+        {
+        }
+
+        /**
+        * initialise an AES cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            KeyParameter keyParameter = parameters as KeyParameter;
+
+            if (keyParameter == null)
+                throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name);
+
+            WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
+
+            this.forEncryption = forEncryption;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "AES"; }
+        }
+
+        public bool IsPartialBlockOkay
+        {
+            get { return false; }
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (WorkingKey == null)
+            {
+                throw new InvalidOperationException("AES engine not initialised");
+            }
+
+            if ((inOff + (32 / 2)) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + (32 / 2)) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            UnPackBlock(input, inOff);
+
+            if (forEncryption)
+            {
+                EncryptBlock(WorkingKey);
+            }
+            else
+            {
+                DecryptBlock(WorkingKey);
+            }
+
+            PackBlock(output, outOff);
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+        }
+
+        private void UnPackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            C0 = Pack.LE_To_UInt32(bytes, off);
+            C1 = Pack.LE_To_UInt32(bytes, off + 4);
+            C2 = Pack.LE_To_UInt32(bytes, off + 8);
+            C3 = Pack.LE_To_UInt32(bytes, off + 12);
+        }
+
+        private void PackBlock(
+            byte[]	bytes,
+            int		off)
+        {
+            Pack.UInt32_To_LE(C0, bytes, off);
+            Pack.UInt32_To_LE(C1, bytes, off + 4);
+            Pack.UInt32_To_LE(C2, bytes, off + 8);
+            Pack.UInt32_To_LE(C3, bytes, off + 12);
+        }
+
+        private void EncryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[0];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = 1;
+            while (r < ROUNDS - 1)
+            {
+                kw = KW[r++];
+                r0 = Mcol((uint)S[t0 & 255] ^ (((uint)S[(t1 >> 8) & 255]) << 8) ^ (((uint)S[(t2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24)) ^ kw[0];
+                r1 = Mcol((uint)S[t1 & 255] ^ (((uint)S[(t2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(t0 >> 24) & 255]) << 24)) ^ kw[1];
+                r2 = Mcol((uint)S[t2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(t0 >> 16) & 255]) << 16) ^ (((uint)S[(t1 >> 24) & 255]) << 24)) ^ kw[2];
+                r3 = Mcol((uint)S[r3 & 255] ^ (((uint)S[(t0 >> 8) & 255]) << 8) ^ (((uint)S[(t1 >> 16) & 255]) << 16) ^ (((uint)S[(t2 >> 24) & 255]) << 24)) ^ kw[3];
+                kw = KW[r++];
+                t0 = Mcol((uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24)) ^ kw[0];
+                t1 = Mcol((uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24)) ^ kw[1];
+                t2 = Mcol((uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24)) ^ kw[2];
+                r3 = Mcol((uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24)) ^ kw[3];
+            }
+
+            kw = KW[r++];
+            r0 = Mcol((uint)S[t0 & 255] ^ (((uint)S[(t1 >> 8) & 255]) << 8) ^ (((uint)S[(t2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24)) ^ kw[0];
+            r1 = Mcol((uint)S[t1 & 255] ^ (((uint)S[(t2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(t0 >> 24) & 255]) << 24)) ^ kw[1];
+            r2 = Mcol((uint)S[t2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(t0 >> 16) & 255]) << 16) ^ (((uint)S[(t1 >> 24) & 255]) << 24)) ^ kw[2];
+            r3 = Mcol((uint)S[r3 & 255] ^ (((uint)S[(t0 >> 8) & 255]) << 8) ^ (((uint)S[(t1 >> 16) & 255]) << 16) ^ (((uint)S[(t2 >> 24) & 255]) << 24)) ^ kw[3];
+
+            // the final round is a simple function of S
+
+            kw = KW[r];
+            this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[(r3 >> 24) & 255]) << 24) ^ kw[0];
+            this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[(r0 >> 24) & 255]) << 24) ^ kw[1];
+            this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[(r1 >> 24) & 255]) << 24) ^ kw[2];
+            this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[(r2 >> 24) & 255]) << 24) ^ kw[3];
+        }
+
+        private void DecryptBlock(uint[][] KW)
+        {
+            uint[] kw = KW[ROUNDS];
+            uint t0 = this.C0 ^ kw[0];
+            uint t1 = this.C1 ^ kw[1];
+            uint t2 = this.C2 ^ kw[2];
+
+            uint r0, r1, r2, r3 = this.C3 ^ kw[3];
+            int r = ROUNDS - 1;
+            while (r > 1)
+            {
+                kw = KW[r--];
+                r0 = Inv_Mcol((uint)Si[t0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(t2 >> 16) & 255]) << 16) ^ ((uint)Si[(t1 >> 24) & 255] << 24)) ^ kw[0];
+                r1 = Inv_Mcol((uint)Si[t1 & 255] ^ (((uint)Si[(t0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ ((uint)Si[(t2 >> 24) & 255] << 24)) ^ kw[1];
+                r2 = Inv_Mcol((uint)Si[t2 & 255] ^ (((uint)Si[(t1 >> 8) & 255]) << 8) ^ (((uint)Si[(t0 >> 16) & 255]) << 16) ^ ((uint)Si[(r3 >> 24) & 255] << 24)) ^ kw[2];
+                r3 = Inv_Mcol((uint)Si[r3 & 255] ^ (((uint)Si[(t2 >> 8) & 255]) << 8) ^ (((uint)Si[(t1 >> 16) & 255]) << 16) ^ ((uint)Si[(t0 >> 24) & 255] << 24)) ^ kw[3];
+                kw = KW[r--];
+                t0 = Inv_Mcol((uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ ((uint)Si[(r1 >> 24) & 255] << 24)) ^ kw[0];
+                t1 = Inv_Mcol((uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ ((uint)Si[(r2 >> 24) & 255] << 24)) ^ kw[1];
+                t2 = Inv_Mcol((uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ ((uint)Si[(r3 >> 24) & 255] << 24)) ^ kw[2];
+                r3 = Inv_Mcol((uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ ((uint)Si[(r0 >> 24) & 255] << 24)) ^ kw[3];
+            }
+
+            kw = KW[1];
+            r0 = Inv_Mcol((uint)Si[t0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(t2 >> 16) & 255]) << 16) ^ ((uint)Si[(t1 >> 24) & 255] << 24)) ^ kw[0];
+            r1 = Inv_Mcol((uint)Si[t1 & 255] ^ (((uint)Si[(t0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ ((uint)Si[(t2 >> 24) & 255] << 24)) ^ kw[1];
+            r2 = Inv_Mcol((uint)Si[t2 & 255] ^ (((uint)Si[(t1 >> 8) & 255]) << 8) ^ (((uint)Si[(t0 >> 16) & 255]) << 16) ^ ((uint)Si[(r3 >> 24) & 255] << 24)) ^ kw[2];
+            r3 = Inv_Mcol((uint)Si[r3 & 255] ^ (((uint)Si[(t2 >> 8) & 255]) << 8) ^ (((uint)Si[(t1 >> 16) & 255]) << 16) ^ ((uint)Si[(t0 >> 24) & 255] << 24)) ^ kw[3];
+
+            // the final round's table is a simple function of Si
+
+            kw = KW[0];
+            this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[(r1 >> 24) & 255]) << 24) ^ kw[0];
+            this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[(r2 >> 24) & 255]) << 24) ^ kw[1];
+            this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[(r3 >> 24) & 255]) << 24) ^ kw[2];
+            this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[(r0 >> 24) & 255]) << 24) ^ kw[3];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/AesWrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/AesWrapEngine.cs
new file mode 100644
index 0000000..1ce0154
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/AesWrapEngine.cs
@@ -0,0 +1,16 @@
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <remarks>
+	/// An implementation of the AES Key Wrapper from the NIST Key Wrap Specification.
+	/// <p/>
+	/// For further details see: <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+	/// </remarks>
+	public class AesWrapEngine
+		: Rfc3394WrapEngine
+	{
+		public AesWrapEngine()
+			: base(new AesEngine())
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/BlowfishEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/BlowfishEngine.cs
new file mode 100644
index 0000000..8f80f71
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/BlowfishEngine.cs
@@ -0,0 +1,561 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * A class that provides Blowfish key encryption operations,
+    * such as encoding data and generating keys.
+    * All the algorithms herein are from Applied Cryptography
+    * and implement a simplified cryptography interface.
+    */
+    public sealed class BlowfishEngine
+		: IBlockCipher
+    {
+        private readonly static uint[] KP =
+		{
+			0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+			0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+			0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+			0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+			0x9216D5D9, 0x8979FB1B
+		},
+		KS0 =
+		{
+			0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+			0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+			0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+			0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+			0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+			0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+			0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+			0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+			0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+			0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+			0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+			0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+			0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+			0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+			0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+			0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+			0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+			0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+			0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+			0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+			0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+			0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+			0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+			0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+			0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+			0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+			0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+			0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+			0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+			0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+			0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+			0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+			0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+			0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+			0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+			0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+			0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+			0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+			0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+			0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+			0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+			0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+			0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+			0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+			0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+			0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+			0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+			0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+			0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+			0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+			0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+			0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+			0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+			0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+			0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+			0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+			0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+			0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+			0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+			0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+			0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+			0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+			0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+			0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
+		},
+		KS1 =
+		{
+			0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+			0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+			0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+			0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+			0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+			0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+			0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+			0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+			0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+			0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+			0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+			0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+			0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+			0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+			0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+			0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+			0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+			0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+			0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+			0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+			0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+			0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+			0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+			0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+			0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+			0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+			0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+			0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+			0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+			0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+			0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+			0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+			0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+			0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+			0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+			0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+			0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+			0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+			0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+			0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+			0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+			0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+			0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+			0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+			0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+			0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+			0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+			0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+			0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+			0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+			0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+			0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+			0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+			0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+			0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+			0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+			0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+			0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+			0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+			0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+			0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+			0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+			0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+			0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
+		},
+		KS2 =
+		{
+			0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+			0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+			0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+			0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+			0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+			0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+			0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+			0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+			0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+			0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+			0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+			0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+			0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+			0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+			0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+			0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+			0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+			0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+			0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+			0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+			0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+			0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+			0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+			0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+			0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+			0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+			0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+			0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+			0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+			0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+			0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+			0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+			0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+			0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+			0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+			0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+			0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+			0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+			0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+			0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+			0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+			0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+			0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+			0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+			0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+			0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+			0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+			0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+			0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+			0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+			0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+			0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+			0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+			0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+			0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+			0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+			0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+			0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+			0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+			0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+			0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+			0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+			0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+			0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
+		},
+		KS3 =
+		{
+			0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+			0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+			0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+			0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+			0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+			0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+			0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+			0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+			0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+			0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+			0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+			0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+			0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+			0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+			0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+			0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+			0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+			0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+			0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+			0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+			0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+			0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+			0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+			0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+			0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+			0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+			0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+			0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+			0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+			0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+			0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+			0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+			0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+			0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+			0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+			0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+			0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+			0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+			0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+			0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+			0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+			0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+			0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+			0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+			0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+			0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+			0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+			0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+			0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+			0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+			0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+			0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+			0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+			0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+			0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+			0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+			0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+			0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+			0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+			0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+			0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+			0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+			0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+			0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
+		};
+
+        //====================================
+        // Useful constants
+        //====================================
+
+        private static readonly int    ROUNDS = 16;
+        private const int    BLOCK_SIZE = 8;  // bytes = 64 bits
+        private static readonly int    SBOX_SK = 256;
+        private static readonly int    P_SZ = ROUNDS+2;
+
+        private readonly uint[] S0, S1, S2, S3;     // the s-boxes
+        private readonly uint[] P;                  // the p-array
+
+        private bool encrypting;
+
+        private byte[] workingKey;
+
+        public BlowfishEngine()
+        {
+            S0 = new uint[SBOX_SK];
+            S1 = new uint[SBOX_SK];
+            S2 = new uint[SBOX_SK];
+            S3 = new uint[SBOX_SK];
+            P = new uint[P_SZ];
+        }
+
+        /**
+        * initialise a Blowfish cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool               forEncryption,
+            ICipherParameters  parameters)
+        {
+            if (!(parameters is KeyParameter))
+				throw new ArgumentException("invalid parameter passed to Blowfish init - " + parameters.GetType().ToString());
+
+			this.encrypting = forEncryption;
+			this.workingKey = ((KeyParameter)parameters).GetKey();
+			SetKey(this.workingKey);
+        }
+
+		public string AlgorithmName
+        {
+            get { return "Blowfish"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public  int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (workingKey == null)
+            {
+                throw new InvalidOperationException("Blowfish not initialised");
+            }
+
+            if ((inOff + BLOCK_SIZE) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + BLOCK_SIZE) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            if (encrypting)
+            {
+                EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                DecryptBlock(input, inOff, output, outOff);
+            }
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        //==================================
+        // Private Implementation
+        //==================================
+
+        private uint F(uint x)
+        {
+            return (((S0[x >> 24] + S1[(x >> 16) & 0xff]) ^ S2[(x >> 8) & 0xff]) + S3[x & 0xff]);
+        }
+
+        /**
+        * apply the encryption cycle to each value pair in the table.
+        */
+        private void ProcessTable(
+            uint	xl,
+            uint	xr,
+            uint[]	table)
+        {
+            int size = table.Length;
+
+            for (int s = 0; s < size; s += 2)
+            {
+                xl ^= P[0];
+
+                for (int i = 1; i < ROUNDS; i += 2)
+                {
+                    xr ^= F(xl) ^ P[i];
+                    xl ^= F(xr) ^ P[i + 1];
+                }
+
+                xr ^= P[ROUNDS + 1];
+
+                table[s] = xr;
+                table[s + 1] = xl;
+
+                xr = xl;            // end of cycle swap
+                xl = table[s];
+            }
+        }
+
+        private void SetKey(byte[] key)
+        {
+            /*
+            * - comments are from _Applied Crypto_, Schneier, p338
+            * please be careful comparing the two, AC numbers the
+            * arrays from 1, the enclosed code from 0.
+            *
+            * (1)
+            * Initialise the S-boxes and the P-array, with a fixed string
+            * This string contains the hexadecimal digits of pi (3.141...)
+            */
+            Array.Copy(KS0, 0, S0, 0, SBOX_SK);
+            Array.Copy(KS1, 0, S1, 0, SBOX_SK);
+            Array.Copy(KS2, 0, S2, 0, SBOX_SK);
+            Array.Copy(KS3, 0, S3, 0, SBOX_SK);
+
+            Array.Copy(KP, 0, P, 0, P_SZ);
+
+            /*
+            * (2)
+            * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
+            * second 32-bits of the key, and so on for all bits of the key
+            * (up to P[17]).  Repeatedly cycle through the key bits until the
+            * entire P-array has been XOR-ed with the key bits
+            */
+            int keyLength = key.Length;
+            int keyIndex = 0;
+
+            for (int i=0; i < P_SZ; i++)
+            {
+                // Get the 32 bits of the key, in 4 * 8 bit chunks
+                uint data = 0x0000000;
+                for (int j=0; j < 4; j++)
+                {
+                    // create a 32 bit block
+                    data = (data << 8) | (uint)key[keyIndex++];
+
+                    // wrap when we get to the end of the key
+                    if (keyIndex >= keyLength)
+                    {
+                        keyIndex = 0;
+                    }
+                }
+                // XOR the newly created 32 bit chunk onto the P-array
+                P[i] ^= data;
+            }
+
+            /*
+            * (3)
+            * Encrypt the all-zero string with the Blowfish algorithm, using
+            * the subkeys described in (1) and (2)
+            *
+            * (4)
+            * Replace P1 and P2 with the output of step (3)
+            *
+            * (5)
+            * Encrypt the output of step(3) using the Blowfish algorithm,
+            * with the modified subkeys.
+            *
+            * (6)
+            * Replace P3 and P4 with the output of step (5)
+            *
+            * (7)
+            * Continue the process, replacing all elements of the P-array
+            * and then all four S-boxes in order, with the output of the
+            * continuously changing Blowfish algorithm
+            */
+
+            ProcessTable(0, 0, P);
+            ProcessTable(P[P_SZ - 2], P[P_SZ - 1], S0);
+            ProcessTable(S0[SBOX_SK - 2], S0[SBOX_SK - 1], S1);
+            ProcessTable(S1[SBOX_SK - 2], S1[SBOX_SK - 1], S2);
+            ProcessTable(S2[SBOX_SK - 2], S2[SBOX_SK - 1], S3);
+        }
+
+        /**
+        * Encrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        * The input will be an exact multiple of our blocksize.
+        */
+        private void EncryptBlock(
+            byte[]  src,
+            int     srcIndex,
+            byte[]  dst,
+            int     dstIndex)
+        {
+            uint xl = Pack.BE_To_UInt32(src, srcIndex);
+            uint xr = Pack.BE_To_UInt32(src, srcIndex+4);
+
+            xl ^= P[0];
+
+            for (int i = 1; i < ROUNDS; i += 2)
+            {
+                xr ^= F(xl) ^ P[i];
+                xl ^= F(xr) ^ P[i + 1];
+            }
+
+            xr ^= P[ROUNDS + 1];
+
+            Pack.UInt32_To_BE(xr, dst, dstIndex);
+            Pack.UInt32_To_BE(xl, dst, dstIndex + 4);
+        }
+
+        /**
+        * Decrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        * The input will be an exact multiple of our blocksize.
+        */
+        private void DecryptBlock(
+            byte[] src,
+            int srcIndex,
+            byte[] dst,
+            int dstIndex)
+        {
+            uint xl = Pack.BE_To_UInt32(src, srcIndex);
+            uint xr = Pack.BE_To_UInt32(src, srcIndex + 4);
+
+            xl ^= P[ROUNDS + 1];
+
+            for (int i = ROUNDS; i > 0 ; i -= 2)
+            {
+                xr ^= F(xl) ^ P[i];
+                xl ^= F(xr) ^ P[i - 1];
+            }
+
+            xr ^= P[0];
+
+            Pack.UInt32_To_BE(xr, dst, dstIndex);
+            Pack.UInt32_To_BE(xl, dst, dstIndex + 4);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaEngine.cs
new file mode 100644
index 0000000..8f4a442
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaEngine.cs
@@ -0,0 +1,669 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* Camellia - based on RFC 3713.
+	*/
+	public class CamelliaEngine
+		: IBlockCipher
+	{
+		private bool initialised = false;
+		private bool _keyIs128;
+
+		private const int BLOCK_SIZE = 16;
+
+		private uint[] subkey = new uint[24 * 4];
+		private uint[] kw = new uint[4 * 2]; // for whitening
+		private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1)
+		private uint[] state = new uint[4]; // for encryption and decryption
+
+		private static readonly uint[] SIGMA = new uint[]{
+			0xa09e667f, 0x3bcc908b,
+			0xb67ae858, 0x4caa73b2,
+			0xc6ef372f, 0xe94f82be,
+			0x54ff53a5, 0xf1d36f1c,
+			0x10e527fa, 0xde682d1d,
+			0xb05688c2, 0xb3e6c1fd
+		};
+
+		/*
+		*
+		* S-box data
+		*
+		*/
+		private static readonly uint[] SBOX1_1110 = new uint[]{
+			0x70707000, 0x82828200, 0x2c2c2c00, 0xececec00, 0xb3b3b300, 0x27272700,
+			0xc0c0c000, 0xe5e5e500, 0xe4e4e400, 0x85858500, 0x57575700, 0x35353500,
+			0xeaeaea00, 0x0c0c0c00, 0xaeaeae00, 0x41414100, 0x23232300, 0xefefef00,
+			0x6b6b6b00, 0x93939300, 0x45454500, 0x19191900, 0xa5a5a500, 0x21212100,
+			0xededed00, 0x0e0e0e00, 0x4f4f4f00, 0x4e4e4e00, 0x1d1d1d00, 0x65656500,
+			0x92929200, 0xbdbdbd00, 0x86868600, 0xb8b8b800, 0xafafaf00, 0x8f8f8f00,
+			0x7c7c7c00, 0xebebeb00, 0x1f1f1f00, 0xcecece00, 0x3e3e3e00, 0x30303000,
+			0xdcdcdc00, 0x5f5f5f00, 0x5e5e5e00, 0xc5c5c500, 0x0b0b0b00, 0x1a1a1a00,
+			0xa6a6a600, 0xe1e1e100, 0x39393900, 0xcacaca00, 0xd5d5d500, 0x47474700,
+			0x5d5d5d00, 0x3d3d3d00, 0xd9d9d900, 0x01010100, 0x5a5a5a00, 0xd6d6d600,
+			0x51515100, 0x56565600, 0x6c6c6c00, 0x4d4d4d00, 0x8b8b8b00, 0x0d0d0d00,
+			0x9a9a9a00, 0x66666600, 0xfbfbfb00, 0xcccccc00, 0xb0b0b000, 0x2d2d2d00,
+			0x74747400, 0x12121200, 0x2b2b2b00, 0x20202000, 0xf0f0f000, 0xb1b1b100,
+			0x84848400, 0x99999900, 0xdfdfdf00, 0x4c4c4c00, 0xcbcbcb00, 0xc2c2c200,
+			0x34343400, 0x7e7e7e00, 0x76767600, 0x05050500, 0x6d6d6d00, 0xb7b7b700,
+			0xa9a9a900, 0x31313100, 0xd1d1d100, 0x17171700, 0x04040400, 0xd7d7d700,
+			0x14141400, 0x58585800, 0x3a3a3a00, 0x61616100, 0xdedede00, 0x1b1b1b00,
+			0x11111100, 0x1c1c1c00, 0x32323200, 0x0f0f0f00, 0x9c9c9c00, 0x16161600,
+			0x53535300, 0x18181800, 0xf2f2f200, 0x22222200, 0xfefefe00, 0x44444400,
+			0xcfcfcf00, 0xb2b2b200, 0xc3c3c300, 0xb5b5b500, 0x7a7a7a00, 0x91919100,
+			0x24242400, 0x08080800, 0xe8e8e800, 0xa8a8a800, 0x60606000, 0xfcfcfc00,
+			0x69696900, 0x50505000, 0xaaaaaa00, 0xd0d0d000, 0xa0a0a000, 0x7d7d7d00,
+			0xa1a1a100, 0x89898900, 0x62626200, 0x97979700, 0x54545400, 0x5b5b5b00,
+			0x1e1e1e00, 0x95959500, 0xe0e0e000, 0xffffff00, 0x64646400, 0xd2d2d200,
+			0x10101000, 0xc4c4c400, 0x00000000, 0x48484800, 0xa3a3a300, 0xf7f7f700,
+			0x75757500, 0xdbdbdb00, 0x8a8a8a00, 0x03030300, 0xe6e6e600, 0xdadada00,
+			0x09090900, 0x3f3f3f00, 0xdddddd00, 0x94949400, 0x87878700, 0x5c5c5c00,
+			0x83838300, 0x02020200, 0xcdcdcd00, 0x4a4a4a00, 0x90909000, 0x33333300,
+			0x73737300, 0x67676700, 0xf6f6f600, 0xf3f3f300, 0x9d9d9d00, 0x7f7f7f00,
+			0xbfbfbf00, 0xe2e2e200, 0x52525200, 0x9b9b9b00, 0xd8d8d800, 0x26262600,
+			0xc8c8c800, 0x37373700, 0xc6c6c600, 0x3b3b3b00, 0x81818100, 0x96969600,
+			0x6f6f6f00, 0x4b4b4b00, 0x13131300, 0xbebebe00, 0x63636300, 0x2e2e2e00,
+			0xe9e9e900, 0x79797900, 0xa7a7a700, 0x8c8c8c00, 0x9f9f9f00, 0x6e6e6e00,
+			0xbcbcbc00, 0x8e8e8e00, 0x29292900, 0xf5f5f500, 0xf9f9f900, 0xb6b6b600,
+			0x2f2f2f00, 0xfdfdfd00, 0xb4b4b400, 0x59595900, 0x78787800, 0x98989800,
+			0x06060600, 0x6a6a6a00, 0xe7e7e700, 0x46464600, 0x71717100, 0xbababa00,
+			0xd4d4d400, 0x25252500, 0xababab00, 0x42424200, 0x88888800, 0xa2a2a200,
+			0x8d8d8d00, 0xfafafa00, 0x72727200, 0x07070700, 0xb9b9b900, 0x55555500,
+			0xf8f8f800, 0xeeeeee00, 0xacacac00, 0x0a0a0a00, 0x36363600, 0x49494900,
+			0x2a2a2a00, 0x68686800, 0x3c3c3c00, 0x38383800, 0xf1f1f100, 0xa4a4a400,
+			0x40404000, 0x28282800, 0xd3d3d300, 0x7b7b7b00, 0xbbbbbb00, 0xc9c9c900,
+			0x43434300, 0xc1c1c100, 0x15151500, 0xe3e3e300, 0xadadad00, 0xf4f4f400,
+			0x77777700, 0xc7c7c700, 0x80808000, 0x9e9e9e00
+		};
+
+		private static readonly uint[] SBOX4_4404 = new uint[]{
+			0x70700070, 0x2c2c002c, 0xb3b300b3, 0xc0c000c0, 0xe4e400e4, 0x57570057,
+			0xeaea00ea, 0xaeae00ae, 0x23230023, 0x6b6b006b, 0x45450045, 0xa5a500a5,
+			0xeded00ed, 0x4f4f004f, 0x1d1d001d, 0x92920092, 0x86860086, 0xafaf00af,
+			0x7c7c007c, 0x1f1f001f, 0x3e3e003e, 0xdcdc00dc, 0x5e5e005e, 0x0b0b000b,
+			0xa6a600a6, 0x39390039, 0xd5d500d5, 0x5d5d005d, 0xd9d900d9, 0x5a5a005a,
+			0x51510051, 0x6c6c006c, 0x8b8b008b, 0x9a9a009a, 0xfbfb00fb, 0xb0b000b0,
+			0x74740074, 0x2b2b002b, 0xf0f000f0, 0x84840084, 0xdfdf00df, 0xcbcb00cb,
+			0x34340034, 0x76760076, 0x6d6d006d, 0xa9a900a9, 0xd1d100d1, 0x04040004,
+			0x14140014, 0x3a3a003a, 0xdede00de, 0x11110011, 0x32320032, 0x9c9c009c,
+			0x53530053, 0xf2f200f2, 0xfefe00fe, 0xcfcf00cf, 0xc3c300c3, 0x7a7a007a,
+			0x24240024, 0xe8e800e8, 0x60600060, 0x69690069, 0xaaaa00aa, 0xa0a000a0,
+			0xa1a100a1, 0x62620062, 0x54540054, 0x1e1e001e, 0xe0e000e0, 0x64640064,
+			0x10100010, 0x00000000, 0xa3a300a3, 0x75750075, 0x8a8a008a, 0xe6e600e6,
+			0x09090009, 0xdddd00dd, 0x87870087, 0x83830083, 0xcdcd00cd, 0x90900090,
+			0x73730073, 0xf6f600f6, 0x9d9d009d, 0xbfbf00bf, 0x52520052, 0xd8d800d8,
+			0xc8c800c8, 0xc6c600c6, 0x81810081, 0x6f6f006f, 0x13130013, 0x63630063,
+			0xe9e900e9, 0xa7a700a7, 0x9f9f009f, 0xbcbc00bc, 0x29290029, 0xf9f900f9,
+			0x2f2f002f, 0xb4b400b4, 0x78780078, 0x06060006, 0xe7e700e7, 0x71710071,
+			0xd4d400d4, 0xabab00ab, 0x88880088, 0x8d8d008d, 0x72720072, 0xb9b900b9,
+			0xf8f800f8, 0xacac00ac, 0x36360036, 0x2a2a002a, 0x3c3c003c, 0xf1f100f1,
+			0x40400040, 0xd3d300d3, 0xbbbb00bb, 0x43430043, 0x15150015, 0xadad00ad,
+			0x77770077, 0x80800080, 0x82820082, 0xecec00ec, 0x27270027, 0xe5e500e5,
+			0x85850085, 0x35350035, 0x0c0c000c, 0x41410041, 0xefef00ef, 0x93930093,
+			0x19190019, 0x21210021, 0x0e0e000e, 0x4e4e004e, 0x65650065, 0xbdbd00bd,
+			0xb8b800b8, 0x8f8f008f, 0xebeb00eb, 0xcece00ce, 0x30300030, 0x5f5f005f,
+			0xc5c500c5, 0x1a1a001a, 0xe1e100e1, 0xcaca00ca, 0x47470047, 0x3d3d003d,
+			0x01010001, 0xd6d600d6, 0x56560056, 0x4d4d004d, 0x0d0d000d, 0x66660066,
+			0xcccc00cc, 0x2d2d002d, 0x12120012, 0x20200020, 0xb1b100b1, 0x99990099,
+			0x4c4c004c, 0xc2c200c2, 0x7e7e007e, 0x05050005, 0xb7b700b7, 0x31310031,
+			0x17170017, 0xd7d700d7, 0x58580058, 0x61610061, 0x1b1b001b, 0x1c1c001c,
+			0x0f0f000f, 0x16160016, 0x18180018, 0x22220022, 0x44440044, 0xb2b200b2,
+			0xb5b500b5, 0x91910091, 0x08080008, 0xa8a800a8, 0xfcfc00fc, 0x50500050,
+			0xd0d000d0, 0x7d7d007d, 0x89890089, 0x97970097, 0x5b5b005b, 0x95950095,
+			0xffff00ff, 0xd2d200d2, 0xc4c400c4, 0x48480048, 0xf7f700f7, 0xdbdb00db,
+			0x03030003, 0xdada00da, 0x3f3f003f, 0x94940094, 0x5c5c005c, 0x02020002,
+			0x4a4a004a, 0x33330033, 0x67670067, 0xf3f300f3, 0x7f7f007f, 0xe2e200e2,
+			0x9b9b009b, 0x26260026, 0x37370037, 0x3b3b003b, 0x96960096, 0x4b4b004b,
+			0xbebe00be, 0x2e2e002e, 0x79790079, 0x8c8c008c, 0x6e6e006e, 0x8e8e008e,
+			0xf5f500f5, 0xb6b600b6, 0xfdfd00fd, 0x59590059, 0x98980098, 0x6a6a006a,
+			0x46460046, 0xbaba00ba, 0x25250025, 0x42420042, 0xa2a200a2, 0xfafa00fa,
+			0x07070007, 0x55550055, 0xeeee00ee, 0x0a0a000a, 0x49490049, 0x68680068,
+			0x38380038, 0xa4a400a4, 0x28280028, 0x7b7b007b, 0xc9c900c9, 0xc1c100c1,
+			0xe3e300e3, 0xf4f400f4, 0xc7c700c7, 0x9e9e009e
+		};
+
+		private static readonly uint[] SBOX2_0222 = new uint[]{
+			0x00e0e0e0, 0x00050505, 0x00585858, 0x00d9d9d9, 0x00676767, 0x004e4e4e,
+			0x00818181, 0x00cbcbcb, 0x00c9c9c9, 0x000b0b0b, 0x00aeaeae, 0x006a6a6a,
+			0x00d5d5d5, 0x00181818, 0x005d5d5d, 0x00828282, 0x00464646, 0x00dfdfdf,
+			0x00d6d6d6, 0x00272727, 0x008a8a8a, 0x00323232, 0x004b4b4b, 0x00424242,
+			0x00dbdbdb, 0x001c1c1c, 0x009e9e9e, 0x009c9c9c, 0x003a3a3a, 0x00cacaca,
+			0x00252525, 0x007b7b7b, 0x000d0d0d, 0x00717171, 0x005f5f5f, 0x001f1f1f,
+			0x00f8f8f8, 0x00d7d7d7, 0x003e3e3e, 0x009d9d9d, 0x007c7c7c, 0x00606060,
+			0x00b9b9b9, 0x00bebebe, 0x00bcbcbc, 0x008b8b8b, 0x00161616, 0x00343434,
+			0x004d4d4d, 0x00c3c3c3, 0x00727272, 0x00959595, 0x00ababab, 0x008e8e8e,
+			0x00bababa, 0x007a7a7a, 0x00b3b3b3, 0x00020202, 0x00b4b4b4, 0x00adadad,
+			0x00a2a2a2, 0x00acacac, 0x00d8d8d8, 0x009a9a9a, 0x00171717, 0x001a1a1a,
+			0x00353535, 0x00cccccc, 0x00f7f7f7, 0x00999999, 0x00616161, 0x005a5a5a,
+			0x00e8e8e8, 0x00242424, 0x00565656, 0x00404040, 0x00e1e1e1, 0x00636363,
+			0x00090909, 0x00333333, 0x00bfbfbf, 0x00989898, 0x00979797, 0x00858585,
+			0x00686868, 0x00fcfcfc, 0x00ececec, 0x000a0a0a, 0x00dadada, 0x006f6f6f,
+			0x00535353, 0x00626262, 0x00a3a3a3, 0x002e2e2e, 0x00080808, 0x00afafaf,
+			0x00282828, 0x00b0b0b0, 0x00747474, 0x00c2c2c2, 0x00bdbdbd, 0x00363636,
+			0x00222222, 0x00383838, 0x00646464, 0x001e1e1e, 0x00393939, 0x002c2c2c,
+			0x00a6a6a6, 0x00303030, 0x00e5e5e5, 0x00444444, 0x00fdfdfd, 0x00888888,
+			0x009f9f9f, 0x00656565, 0x00878787, 0x006b6b6b, 0x00f4f4f4, 0x00232323,
+			0x00484848, 0x00101010, 0x00d1d1d1, 0x00515151, 0x00c0c0c0, 0x00f9f9f9,
+			0x00d2d2d2, 0x00a0a0a0, 0x00555555, 0x00a1a1a1, 0x00414141, 0x00fafafa,
+			0x00434343, 0x00131313, 0x00c4c4c4, 0x002f2f2f, 0x00a8a8a8, 0x00b6b6b6,
+			0x003c3c3c, 0x002b2b2b, 0x00c1c1c1, 0x00ffffff, 0x00c8c8c8, 0x00a5a5a5,
+			0x00202020, 0x00898989, 0x00000000, 0x00909090, 0x00474747, 0x00efefef,
+			0x00eaeaea, 0x00b7b7b7, 0x00151515, 0x00060606, 0x00cdcdcd, 0x00b5b5b5,
+			0x00121212, 0x007e7e7e, 0x00bbbbbb, 0x00292929, 0x000f0f0f, 0x00b8b8b8,
+			0x00070707, 0x00040404, 0x009b9b9b, 0x00949494, 0x00212121, 0x00666666,
+			0x00e6e6e6, 0x00cecece, 0x00ededed, 0x00e7e7e7, 0x003b3b3b, 0x00fefefe,
+			0x007f7f7f, 0x00c5c5c5, 0x00a4a4a4, 0x00373737, 0x00b1b1b1, 0x004c4c4c,
+			0x00919191, 0x006e6e6e, 0x008d8d8d, 0x00767676, 0x00030303, 0x002d2d2d,
+			0x00dedede, 0x00969696, 0x00262626, 0x007d7d7d, 0x00c6c6c6, 0x005c5c5c,
+			0x00d3d3d3, 0x00f2f2f2, 0x004f4f4f, 0x00191919, 0x003f3f3f, 0x00dcdcdc,
+			0x00797979, 0x001d1d1d, 0x00525252, 0x00ebebeb, 0x00f3f3f3, 0x006d6d6d,
+			0x005e5e5e, 0x00fbfbfb, 0x00696969, 0x00b2b2b2, 0x00f0f0f0, 0x00313131,
+			0x000c0c0c, 0x00d4d4d4, 0x00cfcfcf, 0x008c8c8c, 0x00e2e2e2, 0x00757575,
+			0x00a9a9a9, 0x004a4a4a, 0x00575757, 0x00848484, 0x00111111, 0x00454545,
+			0x001b1b1b, 0x00f5f5f5, 0x00e4e4e4, 0x000e0e0e, 0x00737373, 0x00aaaaaa,
+			0x00f1f1f1, 0x00dddddd, 0x00595959, 0x00141414, 0x006c6c6c, 0x00929292,
+			0x00545454, 0x00d0d0d0, 0x00787878, 0x00707070, 0x00e3e3e3, 0x00494949,
+			0x00808080, 0x00505050, 0x00a7a7a7, 0x00f6f6f6, 0x00777777, 0x00939393,
+			0x00868686, 0x00838383, 0x002a2a2a, 0x00c7c7c7, 0x005b5b5b, 0x00e9e9e9,
+			0x00eeeeee, 0x008f8f8f, 0x00010101, 0x003d3d3d
+		};
+
+		private static readonly uint[] SBOX3_3033 = new uint[]{
+			0x38003838, 0x41004141, 0x16001616, 0x76007676, 0xd900d9d9, 0x93009393,
+			0x60006060, 0xf200f2f2, 0x72007272, 0xc200c2c2, 0xab00abab, 0x9a009a9a,
+			0x75007575, 0x06000606, 0x57005757, 0xa000a0a0, 0x91009191, 0xf700f7f7,
+			0xb500b5b5, 0xc900c9c9, 0xa200a2a2, 0x8c008c8c, 0xd200d2d2, 0x90009090,
+			0xf600f6f6, 0x07000707, 0xa700a7a7, 0x27002727, 0x8e008e8e, 0xb200b2b2,
+			0x49004949, 0xde00dede, 0x43004343, 0x5c005c5c, 0xd700d7d7, 0xc700c7c7,
+			0x3e003e3e, 0xf500f5f5, 0x8f008f8f, 0x67006767, 0x1f001f1f, 0x18001818,
+			0x6e006e6e, 0xaf00afaf, 0x2f002f2f, 0xe200e2e2, 0x85008585, 0x0d000d0d,
+			0x53005353, 0xf000f0f0, 0x9c009c9c, 0x65006565, 0xea00eaea, 0xa300a3a3,
+			0xae00aeae, 0x9e009e9e, 0xec00ecec, 0x80008080, 0x2d002d2d, 0x6b006b6b,
+			0xa800a8a8, 0x2b002b2b, 0x36003636, 0xa600a6a6, 0xc500c5c5, 0x86008686,
+			0x4d004d4d, 0x33003333, 0xfd00fdfd, 0x66006666, 0x58005858, 0x96009696,
+			0x3a003a3a, 0x09000909, 0x95009595, 0x10001010, 0x78007878, 0xd800d8d8,
+			0x42004242, 0xcc00cccc, 0xef00efef, 0x26002626, 0xe500e5e5, 0x61006161,
+			0x1a001a1a, 0x3f003f3f, 0x3b003b3b, 0x82008282, 0xb600b6b6, 0xdb00dbdb,
+			0xd400d4d4, 0x98009898, 0xe800e8e8, 0x8b008b8b, 0x02000202, 0xeb00ebeb,
+			0x0a000a0a, 0x2c002c2c, 0x1d001d1d, 0xb000b0b0, 0x6f006f6f, 0x8d008d8d,
+			0x88008888, 0x0e000e0e, 0x19001919, 0x87008787, 0x4e004e4e, 0x0b000b0b,
+			0xa900a9a9, 0x0c000c0c, 0x79007979, 0x11001111, 0x7f007f7f, 0x22002222,
+			0xe700e7e7, 0x59005959, 0xe100e1e1, 0xda00dada, 0x3d003d3d, 0xc800c8c8,
+			0x12001212, 0x04000404, 0x74007474, 0x54005454, 0x30003030, 0x7e007e7e,
+			0xb400b4b4, 0x28002828, 0x55005555, 0x68006868, 0x50005050, 0xbe00bebe,
+			0xd000d0d0, 0xc400c4c4, 0x31003131, 0xcb00cbcb, 0x2a002a2a, 0xad00adad,
+			0x0f000f0f, 0xca00caca, 0x70007070, 0xff00ffff, 0x32003232, 0x69006969,
+			0x08000808, 0x62006262, 0x00000000, 0x24002424, 0xd100d1d1, 0xfb00fbfb,
+			0xba00baba, 0xed00eded, 0x45004545, 0x81008181, 0x73007373, 0x6d006d6d,
+			0x84008484, 0x9f009f9f, 0xee00eeee, 0x4a004a4a, 0xc300c3c3, 0x2e002e2e,
+			0xc100c1c1, 0x01000101, 0xe600e6e6, 0x25002525, 0x48004848, 0x99009999,
+			0xb900b9b9, 0xb300b3b3, 0x7b007b7b, 0xf900f9f9, 0xce00cece, 0xbf00bfbf,
+			0xdf00dfdf, 0x71007171, 0x29002929, 0xcd00cdcd, 0x6c006c6c, 0x13001313,
+			0x64006464, 0x9b009b9b, 0x63006363, 0x9d009d9d, 0xc000c0c0, 0x4b004b4b,
+			0xb700b7b7, 0xa500a5a5, 0x89008989, 0x5f005f5f, 0xb100b1b1, 0x17001717,
+			0xf400f4f4, 0xbc00bcbc, 0xd300d3d3, 0x46004646, 0xcf00cfcf, 0x37003737,
+			0x5e005e5e, 0x47004747, 0x94009494, 0xfa00fafa, 0xfc00fcfc, 0x5b005b5b,
+			0x97009797, 0xfe00fefe, 0x5a005a5a, 0xac00acac, 0x3c003c3c, 0x4c004c4c,
+			0x03000303, 0x35003535, 0xf300f3f3, 0x23002323, 0xb800b8b8, 0x5d005d5d,
+			0x6a006a6a, 0x92009292, 0xd500d5d5, 0x21002121, 0x44004444, 0x51005151,
+			0xc600c6c6, 0x7d007d7d, 0x39003939, 0x83008383, 0xdc00dcdc, 0xaa00aaaa,
+			0x7c007c7c, 0x77007777, 0x56005656, 0x05000505, 0x1b001b1b, 0xa400a4a4,
+			0x15001515, 0x34003434, 0x1e001e1e, 0x1c001c1c, 0xf800f8f8, 0x52005252,
+			0x20002020, 0x14001414, 0xe900e9e9, 0xbd00bdbd, 0xdd00dddd, 0xe400e4e4,
+			0xa100a1a1, 0xe000e0e0, 0x8a008a8a, 0xf100f1f1, 0xd600d6d6, 0x7a007a7a,
+			0xbb00bbbb, 0xe300e3e3, 0x40004040, 0x4f004f4f
+		};
+
+		private static uint rightRotate(uint x, int s)
+		{
+			return ((x >> s) + (x << (32 - s)));
+		}
+
+		private static uint leftRotate(uint x, int s)
+		{
+			return (x << s) + (x >> (32 - s));
+		}
+
+		private static void roldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+			ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+			ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+			ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+			ki[0 + ioff] = ko[0 + ooff];
+			ki[1 + ioff] = ko[1 + ooff];
+			ki[2 + ioff] = ko[2 + ooff];
+			ki[3 + ioff] = ko[3 + ooff];
+		}
+
+		private static void decroldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+			ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+			ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+			ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+			ki[0 + ioff] = ko[2 + ooff];
+			ki[1 + ioff] = ko[3 + ooff];
+			ki[2 + ioff] = ko[0 + ooff];
+			ki[3 + ioff] = ko[1 + ooff];
+		}
+
+		private static void roldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+			ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+			ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+			ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+			ki[0 + ioff] = ko[0 + ooff];
+			ki[1 + ioff] = ko[1 + ooff];
+			ki[2 + ioff] = ko[2 + ooff];
+			ki[3 + ioff] = ko[3 + ooff];
+		}
+
+		private static void decroldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+			ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+			ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+			ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+			ki[0 + ioff] = ko[2 + ooff];
+			ki[1 + ioff] = ko[3 + ooff];
+			ki[2 + ioff] = ko[0 + ooff];
+			ki[3 + ioff] = ko[1 + ooff];
+		}
+
+		private static uint bytes2uint(byte[] src, int offset)
+		{
+			uint word = 0;
+			for (int i = 0; i < 4; i++)
+			{
+				word = (word << 8) + (uint)src[i + offset];
+			}
+			return word;
+		}
+
+		private static void uint2bytes(uint word, byte[] dst, int offset)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				dst[(3 - i) + offset] = (byte)word;
+				word >>= 8;
+			}
+		}
+
+		private static void camelliaF2(uint[] s, uint[] skey, int keyoff)
+		{
+			uint t1, t2, u, v;
+
+			t1 = s[0] ^ skey[0 + keyoff];
+			u = SBOX4_4404[(byte)t1];
+			u ^= SBOX3_3033[(byte)(t1 >> 8)];
+			u ^= SBOX2_0222[(byte)(t1 >> 16)];
+			u ^= SBOX1_1110[(byte)(t1 >> 24)];
+			t2 = s[1] ^ skey[1 + keyoff];
+			v = SBOX1_1110[(byte)t2];
+			v ^= SBOX4_4404[(byte)(t2 >> 8)];
+			v ^= SBOX3_3033[(byte)(t2 >> 16)];
+			v ^= SBOX2_0222[(byte)(t2 >> 24)];
+
+			s[2] ^= u ^ v;
+			s[3] ^= u ^ v ^ rightRotate(u, 8);
+
+			t1 = s[2] ^ skey[2 + keyoff];
+			u = SBOX4_4404[(byte)t1];
+			u ^= SBOX3_3033[(byte)(t1 >> 8)];
+			u ^= SBOX2_0222[(byte)(t1 >> 16)];
+			u ^= SBOX1_1110[(byte)(t1 >> 24)];
+			t2 = s[3] ^ skey[3 + keyoff];
+			v = SBOX1_1110[(byte)t2];
+			v ^= SBOX4_4404[(byte)(t2 >> 8)];
+			v ^= SBOX3_3033[(byte)(t2 >> 16)];
+			v ^= SBOX2_0222[(byte)(t2 >> 24)];
+
+			s[0] ^= u ^ v;
+			s[1] ^= u ^ v ^ rightRotate(u, 8);
+		}
+
+		private static void camelliaFLs(uint[] s, uint[] fkey, int keyoff)
+		{
+
+			s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+			s[0] ^= fkey[1 + keyoff] | s[1];
+
+			s[2] ^= fkey[3 + keyoff] | s[3];
+			s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+		}
+
+		private void setKey(bool forEncryption, byte[] key)
+		{
+			uint[] k = new uint[8];
+			uint[] ka = new uint[4];
+			uint[] kb = new uint[4];
+			uint[] t = new uint[4];
+
+			switch (key.Length)
+			{
+				case 16:
+					_keyIs128 = true;
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = k[5] = k[6] = k[7] = 0;
+					break;
+				case 24:
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = bytes2uint(key, 16);
+					k[5] = bytes2uint(key, 20);
+					k[6] = ~k[4];
+					k[7] = ~k[5];
+					_keyIs128 = false;
+					break;
+				case 32:
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = bytes2uint(key, 16);
+					k[5] = bytes2uint(key, 20);
+					k[6] = bytes2uint(key, 24);
+					k[7] = bytes2uint(key, 28);
+					_keyIs128 = false;
+					break;
+				default:
+					throw new ArgumentException("key sizes are only 16/24/32 bytes.");
+			}
+
+			for (int i = 0; i < 4; i++)
+			{
+				ka[i] = k[i] ^ k[i + 4];
+			}
+			/* compute KA */
+			camelliaF2(ka, SIGMA, 0);
+			for (int i = 0; i < 4; i++)
+			{
+				ka[i] ^= k[i];
+			}
+			camelliaF2(ka, SIGMA, 4);
+
+			if (_keyIs128)
+			{
+				if (forEncryption)
+				{
+					/* KL dependant keys */
+					kw[0] = k[0];
+					kw[1] = k[1];
+					kw[2] = k[2];
+					kw[3] = k[3];
+					roldq(15, k, 0, subkey, 4);
+					roldq(30, k, 0, subkey, 12);
+					roldq(15, k, 0, t, 0);
+					subkey[18] = t[2];
+					subkey[19] = t[3];
+					roldq(17, k, 0, ke, 4);
+					roldq(17, k, 0, subkey, 24);
+					roldq(17, k, 0, subkey, 32);
+					/* KA dependant keys */
+					subkey[0] = ka[0];
+					subkey[1] = ka[1];
+					subkey[2] = ka[2];
+					subkey[3] = ka[3];
+					roldq(15, ka, 0, subkey, 8);
+					roldq(15, ka, 0, ke, 0);
+					roldq(15, ka, 0, t, 0);
+					subkey[16] = t[0];
+					subkey[17] = t[1];
+					roldq(15, ka, 0, subkey, 20);
+					roldqo32(34, ka, 0, subkey, 28);
+					roldq(17, ka, 0, kw, 4);
+
+				}
+				else
+				{ // decryption
+					/* KL dependant keys */
+					kw[4] = k[0];
+					kw[5] = k[1];
+					kw[6] = k[2];
+					kw[7] = k[3];
+					decroldq(15, k, 0, subkey, 28);
+					decroldq(30, k, 0, subkey, 20);
+					decroldq(15, k, 0, t, 0);
+					subkey[16] = t[0];
+					subkey[17] = t[1];
+					decroldq(17, k, 0, ke, 0);
+					decroldq(17, k, 0, subkey, 8);
+					decroldq(17, k, 0, subkey, 0);
+					/* KA dependant keys */
+					subkey[34] = ka[0];
+					subkey[35] = ka[1];
+					subkey[32] = ka[2];
+					subkey[33] = ka[3];
+					decroldq(15, ka, 0, subkey, 24);
+					decroldq(15, ka, 0, ke, 4);
+					decroldq(15, ka, 0, t, 0);
+					subkey[18] = t[2];
+					subkey[19] = t[3];
+					decroldq(15, ka, 0, subkey, 12);
+					decroldqo32(34, ka, 0, subkey, 4);
+					roldq(17, ka, 0, kw, 0);
+				}
+			}
+			else
+			{ // 192bit or 256bit
+				/* compute KB */
+				for (int i = 0; i < 4; i++)
+				{
+					kb[i] = ka[i] ^ k[i + 4];
+				}
+				camelliaF2(kb, SIGMA, 8);
+
+				if (forEncryption)
+				{
+					/* KL dependant keys */
+					kw[0] = k[0];
+					kw[1] = k[1];
+					kw[2] = k[2];
+					kw[3] = k[3];
+					roldqo32(45, k, 0, subkey, 16);
+					roldq(15, k, 0, ke, 4);
+					roldq(17, k, 0, subkey, 32);
+					roldqo32(34, k, 0, subkey, 44);
+					/* KR dependant keys */
+					roldq(15, k, 4, subkey, 4);
+					roldq(15, k, 4, ke, 0);
+					roldq(30, k, 4, subkey, 24);
+					roldqo32(34, k, 4, subkey, 36);
+					/* KA dependant keys */
+					roldq(15, ka, 0, subkey, 8);
+					roldq(30, ka, 0, subkey, 20);
+					/* 32bit rotation */
+					ke[8] = ka[1];
+					ke[9] = ka[2];
+					ke[10] = ka[3];
+					ke[11] = ka[0];
+					roldqo32(49, ka, 0, subkey, 40);
+
+					/* KB dependant keys */
+					subkey[0] = kb[0];
+					subkey[1] = kb[1];
+					subkey[2] = kb[2];
+					subkey[3] = kb[3];
+					roldq(30, kb, 0, subkey, 12);
+					roldq(30, kb, 0, subkey, 28);
+					roldqo32(51, kb, 0, kw, 4);
+
+				}
+				else
+				{ // decryption
+					/* KL dependant keys */
+					kw[4] = k[0];
+					kw[5] = k[1];
+					kw[6] = k[2];
+					kw[7] = k[3];
+					decroldqo32(45, k, 0, subkey, 28);
+					decroldq(15, k, 0, ke, 4);
+					decroldq(17, k, 0, subkey, 12);
+					decroldqo32(34, k, 0, subkey, 0);
+					/* KR dependant keys */
+					decroldq(15, k, 4, subkey, 40);
+					decroldq(15, k, 4, ke, 8);
+					decroldq(30, k, 4, subkey, 20);
+					decroldqo32(34, k, 4, subkey, 8);
+					/* KA dependant keys */
+					decroldq(15, ka, 0, subkey, 36);
+					decroldq(30, ka, 0, subkey, 24);
+					/* 32bit rotation */
+					ke[2] = ka[1];
+					ke[3] = ka[2];
+					ke[0] = ka[3];
+					ke[1] = ka[0];
+					decroldqo32(49, ka, 0, subkey, 4);
+
+					/* KB dependant keys */
+					subkey[46] = kb[0];
+					subkey[47] = kb[1];
+					subkey[44] = kb[2];
+					subkey[45] = kb[3];
+					decroldq(30, kb, 0, subkey, 32);
+					decroldq(30, kb, 0, subkey, 16);
+					roldqo32(51, kb, 0, kw, 0);
+				}
+			}
+		}
+
+		private int processBlock128(byte[] input, int inOff, byte[] output, int outOff)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				state[i] = bytes2uint(input, inOff + (i * 4));
+				state[i] ^= kw[i];
+			}
+
+			camelliaF2(state, subkey, 0);
+			camelliaF2(state, subkey, 4);
+			camelliaF2(state, subkey, 8);
+			camelliaFLs(state, ke, 0);
+			camelliaF2(state, subkey, 12);
+			camelliaF2(state, subkey, 16);
+			camelliaF2(state, subkey, 20);
+			camelliaFLs(state, ke, 4);
+			camelliaF2(state, subkey, 24);
+			camelliaF2(state, subkey, 28);
+			camelliaF2(state, subkey, 32);
+
+			state[2] ^= kw[4];
+			state[3] ^= kw[5];
+			state[0] ^= kw[6];
+			state[1] ^= kw[7];
+
+			uint2bytes(state[2], output, outOff);
+			uint2bytes(state[3], output, outOff + 4);
+			uint2bytes(state[0], output, outOff + 8);
+			uint2bytes(state[1], output, outOff + 12);
+
+			return BLOCK_SIZE;
+		}
+
+		private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				state[i] = bytes2uint(input, inOff + (i * 4));
+				state[i] ^= kw[i];
+			}
+
+			camelliaF2(state, subkey, 0);
+			camelliaF2(state, subkey, 4);
+			camelliaF2(state, subkey, 8);
+			camelliaFLs(state, ke, 0);
+			camelliaF2(state, subkey, 12);
+			camelliaF2(state, subkey, 16);
+			camelliaF2(state, subkey, 20);
+			camelliaFLs(state, ke, 4);
+			camelliaF2(state, subkey, 24);
+			camelliaF2(state, subkey, 28);
+			camelliaF2(state, subkey, 32);
+			camelliaFLs(state, ke, 8);
+			camelliaF2(state, subkey, 36);
+			camelliaF2(state, subkey, 40);
+			camelliaF2(state, subkey, 44);
+
+			state[2] ^= kw[4];
+			state[3] ^= kw[5];
+			state[0] ^= kw[6];
+			state[1] ^= kw[7];
+
+			uint2bytes(state[2], output, outOff);
+			uint2bytes(state[3], output, outOff + 4);
+			uint2bytes(state[0], output, outOff + 8);
+			uint2bytes(state[1], output, outOff + 12);
+			return BLOCK_SIZE;
+		}
+
+		public CamelliaEngine()
+		{
+		}
+
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is KeyParameter))
+				throw new ArgumentException("only simple KeyParameter expected.");
+
+			setKey(forEncryption, ((KeyParameter)parameters).GetKey());
+
+			initialised = true;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Camellia"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BLOCK_SIZE;
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if (!initialised)
+				throw new InvalidOperationException("Camellia engine not initialised");
+			if ((inOff + BLOCK_SIZE) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + BLOCK_SIZE) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			if (_keyIs128)
+			{
+				return processBlock128(input, inOff, output, outOff);
+			}
+			else
+			{
+				return processBlock192or256(input, inOff, output, outOff);
+			}
+		}
+
+		public void Reset()
+		{
+			// nothing
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaLightEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaLightEngine.cs
new file mode 100644
index 0000000..a301eb5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaLightEngine.cs
@@ -0,0 +1,581 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* Camellia - based on RFC 3713, smaller implementation, about half the size of CamelliaEngine.
+	*/
+	public class CamelliaLightEngine
+		: IBlockCipher
+	{
+		private const int BLOCK_SIZE = 16;
+//		private const int MASK8 = 0xff;
+		private bool initialised;
+		private bool _keyis128;
+
+		private uint[] subkey = new uint[24 * 4];
+		private uint[] kw = new uint[4 * 2]; // for whitening
+		private uint[] ke = new uint[6 * 2]; // for FL and FL^(-1)
+		private uint[] state = new uint[4]; // for encryption and decryption
+
+		private static readonly uint[] SIGMA = {
+			0xa09e667f, 0x3bcc908b,
+			0xb67ae858, 0x4caa73b2,
+			0xc6ef372f, 0xe94f82be,
+			0x54ff53a5, 0xf1d36f1c,
+			0x10e527fa, 0xde682d1d,
+			0xb05688c2, 0xb3e6c1fd
+		};
+
+		/*
+		*
+		* S-box data
+		*
+		*/
+		private static readonly byte[] SBOX1 = {
+			(byte)112, (byte)130, (byte)44, (byte)236,
+			(byte)179, (byte)39, (byte)192, (byte)229,
+			(byte)228, (byte)133, (byte)87, (byte)53,
+			(byte)234, (byte)12, (byte)174, (byte)65,
+			(byte)35, (byte)239, (byte)107, (byte)147,
+			(byte)69, (byte)25, (byte)165, (byte)33,
+			(byte)237, (byte)14, (byte)79, (byte)78,
+			(byte)29, (byte)101, (byte)146, (byte)189,
+			(byte)134, (byte)184, (byte)175, (byte)143,
+			(byte)124, (byte)235, (byte)31, (byte)206,
+			(byte)62, (byte)48, (byte)220, (byte)95,
+			(byte)94, (byte)197, (byte)11, (byte)26,
+			(byte)166, (byte)225, (byte)57, (byte)202,
+			(byte)213, (byte)71, (byte)93, (byte)61,
+			(byte)217, (byte)1, (byte)90, (byte)214,
+			(byte)81, (byte)86, (byte)108, (byte)77,
+			(byte)139, (byte)13, (byte)154, (byte)102,
+			(byte)251, (byte)204, (byte)176, (byte)45,
+			(byte)116, (byte)18, (byte)43, (byte)32,
+			(byte)240, (byte)177, (byte)132, (byte)153,
+			(byte)223, (byte)76, (byte)203, (byte)194,
+			(byte)52, (byte)126, (byte)118, (byte)5,
+			(byte)109, (byte)183, (byte)169, (byte)49,
+			(byte)209, (byte)23, (byte)4, (byte)215,
+			(byte)20, (byte)88, (byte)58, (byte)97,
+			(byte)222, (byte)27, (byte)17, (byte)28,
+			(byte)50, (byte)15, (byte)156, (byte)22,
+			(byte)83, (byte)24, (byte)242, (byte)34,
+			(byte)254, (byte)68, (byte)207, (byte)178,
+			(byte)195, (byte)181, (byte)122, (byte)145,
+			(byte)36, (byte)8, (byte)232, (byte)168,
+			(byte)96, (byte)252, (byte)105, (byte)80,
+			(byte)170, (byte)208, (byte)160, (byte)125,
+			(byte)161, (byte)137, (byte)98, (byte)151,
+			(byte)84, (byte)91, (byte)30, (byte)149,
+			(byte)224, (byte)255, (byte)100, (byte)210,
+			(byte)16, (byte)196, (byte)0, (byte)72,
+			(byte)163, (byte)247, (byte)117, (byte)219,
+			(byte)138, (byte)3, (byte)230, (byte)218,
+			(byte)9, (byte)63, (byte)221, (byte)148,
+			(byte)135, (byte)92, (byte)131, (byte)2,
+			(byte)205, (byte)74, (byte)144, (byte)51,
+			(byte)115, (byte)103, (byte)246, (byte)243,
+			(byte)157, (byte)127, (byte)191, (byte)226,
+			(byte)82, (byte)155, (byte)216, (byte)38,
+			(byte)200, (byte)55, (byte)198, (byte)59,
+			(byte)129, (byte)150, (byte)111, (byte)75,
+			(byte)19, (byte)190, (byte)99, (byte)46,
+			(byte)233, (byte)121, (byte)167, (byte)140,
+			(byte)159, (byte)110, (byte)188, (byte)142,
+			(byte)41, (byte)245, (byte)249, (byte)182,
+			(byte)47, (byte)253, (byte)180, (byte)89,
+			(byte)120, (byte)152, (byte)6, (byte)106,
+			(byte)231, (byte)70, (byte)113, (byte)186,
+			(byte)212, (byte)37, (byte)171, (byte)66,
+			(byte)136, (byte)162, (byte)141, (byte)250,
+			(byte)114, (byte)7, (byte)185, (byte)85,
+			(byte)248, (byte)238, (byte)172, (byte)10,
+			(byte)54, (byte)73, (byte)42, (byte)104,
+			(byte)60, (byte)56, (byte)241, (byte)164,
+			(byte)64, (byte)40, (byte)211, (byte)123,
+			(byte)187, (byte)201, (byte)67, (byte)193,
+			(byte)21, (byte)227, (byte)173, (byte)244,
+			(byte)119, (byte)199, (byte)128, (byte)158
+		};
+
+		private static uint rightRotate(uint x, int s)
+		{
+			return ((x >> s) + (x << (32 - s)));
+		}
+
+		private static uint leftRotate(uint x, int s)
+		{
+			return (x << s) + (x >> (32 - s));
+		}
+
+		private static void roldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[0 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+			ko[1 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+			ko[2 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+			ko[3 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+			ki[0 + ioff] = ko[0 + ooff];
+			ki[1 + ioff] = ko[1 + ooff];
+			ki[2 + ioff] = ko[2 + ooff];
+			ki[3 + ioff] = ko[3 + ooff];
+		}
+
+		private static void decroldq(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[2 + ooff] = (ki[0 + ioff] << rot) | (ki[1 + ioff] >> (32 - rot));
+			ko[3 + ooff] = (ki[1 + ioff] << rot) | (ki[2 + ioff] >> (32 - rot));
+			ko[0 + ooff] = (ki[2 + ioff] << rot) | (ki[3 + ioff] >> (32 - rot));
+			ko[1 + ooff] = (ki[3 + ioff] << rot) | (ki[0 + ioff] >> (32 - rot));
+			ki[0 + ioff] = ko[2 + ooff];
+			ki[1 + ioff] = ko[3 + ooff];
+			ki[2 + ioff] = ko[0 + ooff];
+			ki[3 + ioff] = ko[1 + ooff];
+		}
+
+		private static void roldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[0 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+			ko[1 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+			ko[2 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+			ko[3 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+			ki[0 + ioff] = ko[0 + ooff];
+			ki[1 + ioff] = ko[1 + ooff];
+			ki[2 + ioff] = ko[2 + ooff];
+			ki[3 + ioff] = ko[3 + ooff];
+		}
+
+		private static void decroldqo32(int rot, uint[] ki, int ioff, uint[] ko, int ooff)
+		{
+			ko[2 + ooff] = (ki[1 + ioff] << (rot - 32)) | (ki[2 + ioff] >> (64 - rot));
+			ko[3 + ooff] = (ki[2 + ioff] << (rot - 32)) | (ki[3 + ioff] >> (64 - rot));
+			ko[0 + ooff] = (ki[3 + ioff] << (rot - 32)) | (ki[0 + ioff] >> (64 - rot));
+			ko[1 + ooff] = (ki[0 + ioff] << (rot - 32)) | (ki[1 + ioff] >> (64 - rot));
+			ki[0 + ioff] = ko[2 + ooff];
+			ki[1 + ioff] = ko[3 + ooff];
+			ki[2 + ioff] = ko[0 + ooff];
+			ki[3 + ioff] = ko[1 + ooff];
+		}
+
+		private static uint bytes2uint(byte[] src, int offset)
+		{
+			uint word = 0;
+			for (int i = 0; i < 4; i++)
+			{
+				word = (word << 8) + (uint)src[i + offset];
+			}
+			return word;
+		}
+
+		private static void uint2bytes(uint word, byte[] dst, int offset)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				dst[(3 - i) + offset] = (byte)word;
+				word >>= 8;
+			}
+		}
+
+		private byte lRot8(byte v, int rot)
+		{
+			return (byte)(((uint)v << rot) | ((uint)v >> (8 - rot)));
+		}
+
+		private uint sbox2(int x)
+		{
+			return (uint)lRot8(SBOX1[x], 1);
+		}
+
+		private uint sbox3(int x)
+		{
+			return (uint)lRot8(SBOX1[x], 7);
+		}
+
+		private uint sbox4(int x)
+		{
+			return (uint)SBOX1[lRot8((byte)x, 1)];
+		}
+
+		private void camelliaF2(uint[] s, uint[] skey, int keyoff)
+		{
+			uint t1, t2, u, v;
+
+			t1 = s[0] ^ skey[0 + keyoff];
+			u = sbox4((byte)t1);
+			u |= (sbox3((byte)(t1 >> 8)) << 8);
+			u |= (sbox2((byte)(t1 >> 16)) << 16);
+			u |= ((uint)(SBOX1[(byte)(t1 >> 24)]) << 24);
+
+			t2 = s[1] ^ skey[1 + keyoff];
+			v = (uint)SBOX1[(byte)t2];
+			v |= (sbox4((byte)(t2 >> 8)) << 8);
+			v |= (sbox3((byte)(t2 >> 16)) << 16);
+			v |= (sbox2((byte)(t2 >> 24)) << 24);
+
+			v = leftRotate(v, 8);
+			u ^= v;
+			v = leftRotate(v, 8) ^ u;
+			u = rightRotate(u, 8) ^ v;
+			s[2] ^= leftRotate(v, 16) ^ u;
+			s[3] ^= leftRotate(u, 8);
+
+			t1 = s[2] ^ skey[2 + keyoff];
+			u = sbox4((byte)t1);
+			u |= sbox3((byte)(t1 >> 8)) << 8;
+			u |= sbox2((byte)(t1 >> 16)) << 16;
+			u |= ((uint)SBOX1[(byte)(t1 >> 24)]) << 24;
+
+			t2 = s[3] ^ skey[3 + keyoff];
+			v = (uint)SBOX1[(byte)t2];
+			v |= sbox4((byte)(t2 >> 8)) << 8;
+			v |= sbox3((byte)(t2 >> 16)) << 16;
+			v |= sbox2((byte)(t2 >> 24)) << 24;
+
+			v = leftRotate(v, 8);
+			u ^= v;
+			v = leftRotate(v, 8) ^ u;
+			u = rightRotate(u, 8) ^ v;
+			s[0] ^= leftRotate(v, 16) ^ u;
+			s[1] ^= leftRotate(u, 8);
+		}
+
+		private void camelliaFLs(uint[] s, uint[] fkey, int keyoff)
+		{
+			s[1] ^= leftRotate(s[0] & fkey[0 + keyoff], 1);
+			s[0] ^= fkey[1 + keyoff] | s[1];
+
+			s[2] ^= fkey[3 + keyoff] | s[3];
+			s[3] ^= leftRotate(fkey[2 + keyoff] & s[2], 1);
+		}
+
+		private void setKey(bool forEncryption, byte[] key)
+		{
+			uint[] k = new uint[8];
+			uint[] ka = new uint[4];
+			uint[] kb = new uint[4];
+			uint[] t = new uint[4];
+
+			switch (key.Length)
+			{
+				case 16:
+					_keyis128 = true;
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = k[5] = k[6] = k[7] = 0;
+					break;
+				case 24:
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = bytes2uint(key, 16);
+					k[5] = bytes2uint(key, 20);
+					k[6] = ~k[4];
+					k[7] = ~k[5];
+					_keyis128 = false;
+					break;
+				case 32:
+					k[0] = bytes2uint(key, 0);
+					k[1] = bytes2uint(key, 4);
+					k[2] = bytes2uint(key, 8);
+					k[3] = bytes2uint(key, 12);
+					k[4] = bytes2uint(key, 16);
+					k[5] = bytes2uint(key, 20);
+					k[6] = bytes2uint(key, 24);
+					k[7] = bytes2uint(key, 28);
+					_keyis128 = false;
+					break;
+				default:
+					throw new ArgumentException("key sizes are only 16/24/32 bytes.");
+			}
+
+			for (int i = 0; i < 4; i++)
+			{
+				ka[i] = k[i] ^ k[i + 4];
+			}
+			/* compute KA */
+			camelliaF2(ka, SIGMA, 0);
+			for (int i = 0; i < 4; i++)
+			{
+				ka[i] ^= k[i];
+			}
+			camelliaF2(ka, SIGMA, 4);
+
+			if (_keyis128)
+			{
+				if (forEncryption)
+				{
+					/* KL dependant keys */
+					kw[0] = k[0];
+					kw[1] = k[1];
+					kw[2] = k[2];
+					kw[3] = k[3];
+					roldq(15, k, 0, subkey, 4);
+					roldq(30, k, 0, subkey, 12);
+					roldq(15, k, 0, t, 0);
+					subkey[18] = t[2];
+					subkey[19] = t[3];
+					roldq(17, k, 0, ke, 4);
+					roldq(17, k, 0, subkey, 24);
+					roldq(17, k, 0, subkey, 32);
+					/* KA dependant keys */
+					subkey[0] = ka[0];
+					subkey[1] = ka[1];
+					subkey[2] = ka[2];
+					subkey[3] = ka[3];
+					roldq(15, ka, 0, subkey, 8);
+					roldq(15, ka, 0, ke, 0);
+					roldq(15, ka, 0, t, 0);
+					subkey[16] = t[0];
+					subkey[17] = t[1];
+					roldq(15, ka, 0, subkey, 20);
+					roldqo32(34, ka, 0, subkey, 28);
+					roldq(17, ka, 0, kw, 4);
+
+				}
+				else
+				{ // decryption
+					/* KL dependant keys */
+					kw[4] = k[0];
+					kw[5] = k[1];
+					kw[6] = k[2];
+					kw[7] = k[3];
+					decroldq(15, k, 0, subkey, 28);
+					decroldq(30, k, 0, subkey, 20);
+					decroldq(15, k, 0, t, 0);
+					subkey[16] = t[0];
+					subkey[17] = t[1];
+					decroldq(17, k, 0, ke, 0);
+					decroldq(17, k, 0, subkey, 8);
+					decroldq(17, k, 0, subkey, 0);
+					/* KA dependant keys */
+					subkey[34] = ka[0];
+					subkey[35] = ka[1];
+					subkey[32] = ka[2];
+					subkey[33] = ka[3];
+					decroldq(15, ka, 0, subkey, 24);
+					decroldq(15, ka, 0, ke, 4);
+					decroldq(15, ka, 0, t, 0);
+					subkey[18] = t[2];
+					subkey[19] = t[3];
+					decroldq(15, ka, 0, subkey, 12);
+					decroldqo32(34, ka, 0, subkey, 4);
+					roldq(17, ka, 0, kw, 0);
+				}
+			}
+			else
+			{ // 192bit or 256bit
+				/* compute KB */
+				for (int i = 0; i < 4; i++)
+				{
+					kb[i] = ka[i] ^ k[i + 4];
+				}
+				camelliaF2(kb, SIGMA, 8);
+
+				if (forEncryption)
+				{
+					/* KL dependant keys */
+					kw[0] = k[0];
+					kw[1] = k[1];
+					kw[2] = k[2];
+					kw[3] = k[3];
+					roldqo32(45, k, 0, subkey, 16);
+					roldq(15, k, 0, ke, 4);
+					roldq(17, k, 0, subkey, 32);
+					roldqo32(34, k, 0, subkey, 44);
+					/* KR dependant keys */
+					roldq(15, k, 4, subkey, 4);
+					roldq(15, k, 4, ke, 0);
+					roldq(30, k, 4, subkey, 24);
+					roldqo32(34, k, 4, subkey, 36);
+					/* KA dependant keys */
+					roldq(15, ka, 0, subkey, 8);
+					roldq(30, ka, 0, subkey, 20);
+					/* 32bit rotation */
+					ke[8] = ka[1];
+					ke[9] = ka[2];
+					ke[10] = ka[3];
+					ke[11] = ka[0];
+					roldqo32(49, ka, 0, subkey, 40);
+
+					/* KB dependant keys */
+					subkey[0] = kb[0];
+					subkey[1] = kb[1];
+					subkey[2] = kb[2];
+					subkey[3] = kb[3];
+					roldq(30, kb, 0, subkey, 12);
+					roldq(30, kb, 0, subkey, 28);
+					roldqo32(51, kb, 0, kw, 4);
+
+				}
+				else
+				{ // decryption
+					/* KL dependant keys */
+					kw[4] = k[0];
+					kw[5] = k[1];
+					kw[6] = k[2];
+					kw[7] = k[3];
+					decroldqo32(45, k, 0, subkey, 28);
+					decroldq(15, k, 0, ke, 4);
+					decroldq(17, k, 0, subkey, 12);
+					decroldqo32(34, k, 0, subkey, 0);
+					/* KR dependant keys */
+					decroldq(15, k, 4, subkey, 40);
+					decroldq(15, k, 4, ke, 8);
+					decroldq(30, k, 4, subkey, 20);
+					decroldqo32(34, k, 4, subkey, 8);
+					/* KA dependant keys */
+					decroldq(15, ka, 0, subkey, 36);
+					decroldq(30, ka, 0, subkey, 24);
+					/* 32bit rotation */
+					ke[2] = ka[1];
+					ke[3] = ka[2];
+					ke[0] = ka[3];
+					ke[1] = ka[0];
+					decroldqo32(49, ka, 0, subkey, 4);
+
+					/* KB dependant keys */
+					subkey[46] = kb[0];
+					subkey[47] = kb[1];
+					subkey[44] = kb[2];
+					subkey[45] = kb[3];
+					decroldq(30, kb, 0, subkey, 32);
+					decroldq(30, kb, 0, subkey, 16);
+					roldqo32(51, kb, 0, kw, 0);
+				}
+			}
+		}
+
+		private int processBlock128(byte[] input, int inOff, byte[] output, int outOff)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				state[i] = bytes2uint(input, inOff + (i * 4));
+				state[i] ^= kw[i];
+			}
+
+			camelliaF2(state, subkey, 0);
+			camelliaF2(state, subkey, 4);
+			camelliaF2(state, subkey, 8);
+			camelliaFLs(state, ke, 0);
+			camelliaF2(state, subkey, 12);
+			camelliaF2(state, subkey, 16);
+			camelliaF2(state, subkey, 20);
+			camelliaFLs(state, ke, 4);
+			camelliaF2(state, subkey, 24);
+			camelliaF2(state, subkey, 28);
+			camelliaF2(state, subkey, 32);
+
+			state[2] ^= kw[4];
+			state[3] ^= kw[5];
+			state[0] ^= kw[6];
+			state[1] ^= kw[7];
+
+			uint2bytes(state[2], output, outOff);
+			uint2bytes(state[3], output, outOff + 4);
+			uint2bytes(state[0], output, outOff + 8);
+			uint2bytes(state[1], output, outOff + 12);
+
+			return BLOCK_SIZE;
+		}
+
+		private int processBlock192or256(byte[] input, int inOff, byte[] output, int outOff)
+		{
+			for (int i = 0; i < 4; i++)
+			{
+				state[i] = bytes2uint(input, inOff + (i * 4));
+				state[i] ^= kw[i];
+			}
+
+			camelliaF2(state, subkey, 0);
+			camelliaF2(state, subkey, 4);
+			camelliaF2(state, subkey, 8);
+			camelliaFLs(state, ke, 0);
+			camelliaF2(state, subkey, 12);
+			camelliaF2(state, subkey, 16);
+			camelliaF2(state, subkey, 20);
+			camelliaFLs(state, ke, 4);
+			camelliaF2(state, subkey, 24);
+			camelliaF2(state, subkey, 28);
+			camelliaF2(state, subkey, 32);
+			camelliaFLs(state, ke, 8);
+			camelliaF2(state, subkey, 36);
+			camelliaF2(state, subkey, 40);
+			camelliaF2(state, subkey, 44);
+
+			state[2] ^= kw[4];
+			state[3] ^= kw[5];
+			state[0] ^= kw[6];
+			state[1] ^= kw[7];
+
+			uint2bytes(state[2], output, outOff);
+			uint2bytes(state[3], output, outOff + 4);
+			uint2bytes(state[0], output, outOff + 8);
+			uint2bytes(state[1], output, outOff + 12);
+			return BLOCK_SIZE;
+		}
+
+		public CamelliaLightEngine()
+		{
+			initialised = false;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Camellia"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BLOCK_SIZE;
+		}
+
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is KeyParameter))
+				throw new ArgumentException("only simple KeyParameter expected.");
+
+			setKey(forEncryption, ((KeyParameter)parameters).GetKey());
+
+			initialised = true;
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+            byte[]	output,
+			int		outOff)
+		{
+			if (!initialised)
+				throw new InvalidOperationException("Camellia engine not initialised");
+			if ((inOff + BLOCK_SIZE) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + BLOCK_SIZE) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			if (_keyis128)
+			{
+				return processBlock128(input, inOff, output, outOff);
+			}
+			else
+			{
+				return processBlock192or256(input, inOff, output, outOff);
+			}
+		}
+
+		public void Reset()
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaWrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaWrapEngine.cs
new file mode 100644
index 0000000..49dc833
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/CamelliaWrapEngine.cs
@@ -0,0 +1,16 @@
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <remarks>
+	/// An implementation of the Camellia key wrapper based on RFC 3657/RFC 3394.
+	/// <p/>
+	/// For further details see: <a href="http://www.ietf.org/rfc/rfc3657.txt">http://www.ietf.org/rfc/rfc3657.txt</a>.
+	/// </remarks>
+	public class CamelliaWrapEngine
+		: Rfc3394WrapEngine
+	{
+		public CamelliaWrapEngine()
+			: base(new CamelliaEngine())
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/Cast5Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/Cast5Engine.cs
new file mode 100644
index 0000000..4c3f84a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/Cast5Engine.cs
@@ -0,0 +1,802 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * A class that provides CAST key encryption operations,
+    * such as encoding data and generating keys.
+    *
+    * All the algorithms herein are from the Internet RFC's
+    *
+    * RFC2144 - Cast5 (64bit block, 40-128bit key)
+    * RFC2612 - CAST6 (128bit block, 128-256bit key)
+    *
+    * and implement a simplified cryptography interface.
+    */
+    public class Cast5Engine
+		: IBlockCipher
+    {
+		internal static readonly uint[] S1 =
+		{
+			0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+			0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+			0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+			0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+			0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+			0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+			0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+			0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+			0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+			0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+			0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+			0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+			0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+			0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+			0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+			0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+			0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+			0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+			0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+			0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+			0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+			0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+			0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+			0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+			0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+			0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+			0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+			0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+			0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+			0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+			0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+			0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+		},
+		S2 =
+		{
+			0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+			0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+			0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+			0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+			0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+			0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+			0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+			0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+			0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+			0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+			0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+			0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+			0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+			0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+			0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+			0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+			0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+			0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+			0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+			0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+			0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+			0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+			0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+			0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+			0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+			0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+			0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+			0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+			0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+			0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+			0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+			0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
+		},
+		S3 =
+		{
+			0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+			0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+			0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+			0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+			0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+			0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+			0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+			0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+			0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+			0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+			0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+			0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+			0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+			0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+			0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+			0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+			0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+			0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+			0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+			0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+			0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+			0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+			0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+			0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+			0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+			0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+			0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+			0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+			0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+			0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+			0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+			0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
+		},
+		S4 =
+		{
+			0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+			0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+			0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+			0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+			0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+			0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+			0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+			0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+			0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+			0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+			0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+			0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+			0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+			0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+			0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+			0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+			0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+			0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+			0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+			0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+			0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+			0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+			0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+			0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+			0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+			0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+			0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+			0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+			0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+			0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+			0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+			0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+		},
+		S5 =
+		{
+			0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+			0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+			0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+			0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+			0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+			0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+			0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+			0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+			0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+			0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+			0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+			0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+			0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+			0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+			0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+			0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+			0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+			0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+			0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+			0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+			0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+			0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+			0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+			0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+			0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+			0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+			0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+			0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+			0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+			0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+			0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+			0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
+		},
+		S6 =
+		{
+			0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+			0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+			0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+			0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+			0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+			0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+			0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+			0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+			0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+			0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+			0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+			0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+			0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+			0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+			0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+			0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+			0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+			0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+			0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+			0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+			0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+			0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+			0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+			0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+			0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+			0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+			0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+			0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+			0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+			0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+			0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+			0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
+		},
+		S7 =
+		{
+			0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+			0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+			0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+			0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+			0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+			0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+			0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+			0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+			0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+			0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+			0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+			0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+			0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+			0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+			0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+			0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+			0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+			0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+			0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+			0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+			0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+			0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+			0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+			0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+			0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+			0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+			0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+			0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+			0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+			0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+			0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+			0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
+		},
+		S8 =
+		{
+			0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+			0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+			0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+			0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+			0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+			0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+			0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+			0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+			0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+			0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+			0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+			0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+			0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+			0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+			0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+			0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+			0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+			0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+			0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+			0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+			0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+			0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+			0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+			0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+			0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+			0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+			0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+			0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+			0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+			0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+			0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+			0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
+		};
+
+        //====================================
+        // Useful constants
+        //====================================
+
+        internal static readonly int MAX_ROUNDS = 16;
+        internal static readonly int RED_ROUNDS = 12;
+
+        private const int BLOCK_SIZE = 8;  // bytes = 64 bits
+
+        private int[] _Kr = new int[17];        // the rotating round key
+        private uint[] _Km = new uint[17];        // the masking round key
+
+        private bool _encrypting;
+
+        private byte[] _workingKey;
+        private int _rounds = MAX_ROUNDS;
+
+        public Cast5Engine()
+        {
+        }
+
+        /**
+        * initialise a CAST cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+				throw new ArgumentException("Invalid parameter passed to "+ AlgorithmName +" init - " + parameters.GetType().ToString());
+
+			_encrypting = forEncryption;
+			_workingKey = ((KeyParameter)parameters).GetKey();
+			SetKey(_workingKey);
+        }
+
+		public virtual string AlgorithmName
+        {
+            get { return "CAST5"; }
+        }
+
+		public virtual bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public virtual int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+			int blockSize = GetBlockSize();
+            if (_workingKey == null)
+                throw new InvalidOperationException(AlgorithmName + " not initialised");
+            if ((inOff + blockSize) > input.Length)
+                throw new DataLengthException("Input buffer too short");
+            if ((outOff + blockSize) > output.Length)
+                throw new DataLengthException("Output buffer too short");
+
+			if (_encrypting)
+            {
+                return EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                return DecryptBlock(input, inOff, output, outOff);
+            }
+        }
+
+        public virtual void Reset()
+        {
+        }
+
+        public virtual int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        //==================================
+        // Private Implementation
+        //==================================
+
+        /*
+        * Creates the subkeys using the same nomenclature
+        * as described in RFC2144.
+        *
+        * See section 2.4
+        */
+        internal virtual void SetKey(byte[] key)
+        {
+            /*
+            * Determine the key size here, if required
+            *
+            * if keysize <= 80bits, use 12 rounds instead of 16
+            * if keysize < 128bits, pad with 0
+            *
+            * Typical key sizes => 40, 64, 80, 128
+            */
+
+            if (key.Length < 11)
+            {
+                _rounds = RED_ROUNDS;
+            }
+
+            int [] z = new int[16];
+            int [] x = new int[16];
+
+            uint z03, z47, z8B, zCF;
+            uint x03, x47, x8B, xCF;
+
+            /* copy the key into x */
+            for (int i=0; i< key.Length; i++)
+            {
+                x[i] = (int)(key[i] & 0xff);
+            }
+
+            /*
+            * This will look different because the selection of
+            * bytes from the input key I've already chosen the
+            * correct int.
+            */
+            x03 = IntsTo32bits(x, 0x0);
+            x47 = IntsTo32bits(x, 0x4);
+            x8B = IntsTo32bits(x, 0x8);
+            xCF = IntsTo32bits(x, 0xC);
+
+            z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+
+            Bits32ToInts(z03, z, 0x0);
+            z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+            Bits32ToInts(z47, z, 0x4);
+            z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+            Bits32ToInts(z8B, z, 0x8);
+            zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+            Bits32ToInts(zCF, z, 0xC);
+            _Km[ 1]= S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
+            _Km[ 2]= S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
+            _Km[ 3]= S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
+            _Km[ 4]= S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
+
+            z03 = IntsTo32bits(z, 0x0);
+            z47 = IntsTo32bits(z, 0x4);
+            z8B = IntsTo32bits(z, 0x8);
+            zCF = IntsTo32bits(z, 0xC);
+            x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+            Bits32ToInts(x03, x, 0x0);
+            x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+            Bits32ToInts(x47, x, 0x4);
+            x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+            Bits32ToInts(x8B, x, 0x8);
+            xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+            Bits32ToInts(xCF, x, 0xC);
+            _Km[ 5]= S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
+            _Km[ 6]= S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
+            _Km[ 7]= S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
+            _Km[ 8]= S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
+
+            x03 = IntsTo32bits(x, 0x0);
+            x47 = IntsTo32bits(x, 0x4);
+            x8B = IntsTo32bits(x, 0x8);
+            xCF = IntsTo32bits(x, 0xC);
+            z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+            Bits32ToInts(z03, z, 0x0);
+            z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+            Bits32ToInts(z47, z, 0x4);
+            z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+            Bits32ToInts(z8B, z, 0x8);
+            zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+            Bits32ToInts(zCF, z, 0xC);
+            _Km[ 9]= S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
+            _Km[10]= S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
+            _Km[11]= S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
+            _Km[12]= S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
+
+            z03 = IntsTo32bits(z, 0x0);
+            z47 = IntsTo32bits(z, 0x4);
+            z8B = IntsTo32bits(z, 0x8);
+            zCF = IntsTo32bits(z, 0xC);
+            x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+            Bits32ToInts(x03, x, 0x0);
+            x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+            Bits32ToInts(x47, x, 0x4);
+            x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+            Bits32ToInts(x8B, x, 0x8);
+            xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+            Bits32ToInts(xCF, x, 0xC);
+            _Km[13]= S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
+            _Km[14]= S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
+            _Km[15]= S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
+            _Km[16]= S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
+
+            x03 = IntsTo32bits(x, 0x0);
+            x47 = IntsTo32bits(x, 0x4);
+            x8B = IntsTo32bits(x, 0x8);
+            xCF = IntsTo32bits(x, 0xC);
+            z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+            Bits32ToInts(z03, z, 0x0);
+            z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+            Bits32ToInts(z47, z, 0x4);
+            z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+            Bits32ToInts(z8B, z, 0x8);
+            zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+            Bits32ToInts(zCF, z, 0xC);
+            _Kr[ 1]=(int)((S5[z[0x8]]^S6[z[0x9]]^S7[z[0x7]]^S8[z[0x6]] ^ S5[z[0x2]])&0x1f);
+            _Kr[ 2]=(int)((S5[z[0xA]]^S6[z[0xB]]^S7[z[0x5]]^S8[z[0x4]] ^ S6[z[0x6]])&0x1f);
+            _Kr[ 3]=(int)((S5[z[0xC]]^S6[z[0xD]]^S7[z[0x3]]^S8[z[0x2]] ^ S7[z[0x9]])&0x1f);
+            _Kr[ 4]=(int)((S5[z[0xE]]^S6[z[0xF]]^S7[z[0x1]]^S8[z[0x0]] ^ S8[z[0xC]])&0x1f);
+
+            z03 = IntsTo32bits(z, 0x0);
+            z47 = IntsTo32bits(z, 0x4);
+            z8B = IntsTo32bits(z, 0x8);
+            zCF = IntsTo32bits(z, 0xC);
+            x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+            Bits32ToInts(x03, x, 0x0);
+            x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+            Bits32ToInts(x47, x, 0x4);
+            x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+            Bits32ToInts(x8B, x, 0x8);
+            xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+            Bits32ToInts(xCF, x, 0xC);
+            _Kr[ 5]=(int)((S5[x[0x3]]^S6[x[0x2]]^S7[x[0xC]]^S8[x[0xD]]^S5[x[0x8]])&0x1f);
+            _Kr[ 6]=(int)((S5[x[0x1]]^S6[x[0x0]]^S7[x[0xE]]^S8[x[0xF]]^S6[x[0xD]])&0x1f);
+            _Kr[ 7]=(int)((S5[x[0x7]]^S6[x[0x6]]^S7[x[0x8]]^S8[x[0x9]]^S7[x[0x3]])&0x1f);
+            _Kr[ 8]=(int)((S5[x[0x5]]^S6[x[0x4]]^S7[x[0xA]]^S8[x[0xB]]^S8[x[0x7]])&0x1f);
+
+            x03 = IntsTo32bits(x, 0x0);
+            x47 = IntsTo32bits(x, 0x4);
+            x8B = IntsTo32bits(x, 0x8);
+            xCF = IntsTo32bits(x, 0xC);
+            z03 = x03 ^S5[x[0xD]] ^S6[x[0xF]] ^S7[x[0xC]] ^S8[x[0xE]] ^S7[x[0x8]];
+            Bits32ToInts(z03, z, 0x0);
+            z47 = x8B ^S5[z[0x0]] ^S6[z[0x2]] ^S7[z[0x1]] ^S8[z[0x3]] ^S8[x[0xA]];
+            Bits32ToInts(z47, z, 0x4);
+            z8B = xCF ^S5[z[0x7]] ^S6[z[0x6]] ^S7[z[0x5]] ^S8[z[0x4]] ^S5[x[0x9]];
+            Bits32ToInts(z8B, z, 0x8);
+            zCF = x47 ^S5[z[0xA]] ^S6[z[0x9]] ^S7[z[0xB]] ^S8[z[0x8]] ^S6[x[0xB]];
+            Bits32ToInts(zCF, z, 0xC);
+            _Kr[ 9]=(int)((S5[z[0x3]]^S6[z[0x2]]^S7[z[0xC]]^S8[z[0xD]]^S5[z[0x9]])&0x1f);
+            _Kr[10]=(int)((S5[z[0x1]]^S6[z[0x0]]^S7[z[0xE]]^S8[z[0xF]]^S6[z[0xc]])&0x1f);
+            _Kr[11]=(int)((S5[z[0x7]]^S6[z[0x6]]^S7[z[0x8]]^S8[z[0x9]]^S7[z[0x2]])&0x1f);
+            _Kr[12]=(int)((S5[z[0x5]]^S6[z[0x4]]^S7[z[0xA]]^S8[z[0xB]]^S8[z[0x6]])&0x1f);
+
+            z03 = IntsTo32bits(z, 0x0);
+            z47 = IntsTo32bits(z, 0x4);
+            z8B = IntsTo32bits(z, 0x8);
+            zCF = IntsTo32bits(z, 0xC);
+            x03 = z8B ^S5[z[0x5]] ^S6[z[0x7]] ^S7[z[0x4]] ^S8[z[0x6]] ^S7[z[0x0]];
+            Bits32ToInts(x03, x, 0x0);
+            x47 = z03 ^S5[x[0x0]] ^S6[x[0x2]] ^S7[x[0x1]] ^S8[x[0x3]] ^S8[z[0x2]];
+            Bits32ToInts(x47, x, 0x4);
+            x8B = z47 ^S5[x[0x7]] ^S6[x[0x6]] ^S7[x[0x5]] ^S8[x[0x4]] ^S5[z[0x1]];
+            Bits32ToInts(x8B, x, 0x8);
+            xCF = zCF ^S5[x[0xA]] ^S6[x[0x9]] ^S7[x[0xB]] ^S8[x[0x8]] ^S6[z[0x3]];
+            Bits32ToInts(xCF, x, 0xC);
+            _Kr[13]=(int)((S5[x[0x8]]^S6[x[0x9]]^S7[x[0x7]]^S8[x[0x6]]^S5[x[0x3]])&0x1f);
+            _Kr[14]=(int)((S5[x[0xA]]^S6[x[0xB]]^S7[x[0x5]]^S8[x[0x4]]^S6[x[0x7]])&0x1f);
+            _Kr[15]=(int)((S5[x[0xC]]^S6[x[0xD]]^S7[x[0x3]]^S8[x[0x2]]^S7[x[0x8]])&0x1f);
+            _Kr[16]=(int)((S5[x[0xE]]^S6[x[0xF]]^S7[x[0x1]]^S8[x[0x0]]^S8[x[0xD]])&0x1f);
+        }
+
+        /**
+        * Encrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param src        The plaintext buffer
+        * @param srcIndex    An offset into src
+        * @param dst        The ciphertext buffer
+        * @param dstIndex    An offset into dst
+        */
+        internal virtual int EncryptBlock(
+            byte[] src,
+            int srcIndex,
+            byte[] dst,
+            int dstIndex)
+        {
+            // process the input block
+            // batch the units up into a 32 bit chunk and go for it
+            // the array is in bytes, the increment is 8x8 bits = 64
+
+            uint L0 = Pack.BE_To_UInt32(src, srcIndex);
+            uint R0 = Pack.BE_To_UInt32(src, srcIndex + 4);
+
+            uint[] result = new uint[2];
+            CAST_Encipher(L0, R0, result);
+
+            // now stuff them into the destination block
+            Pack.UInt32_To_BE(result[0], dst, dstIndex);
+            Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
+
+            return BLOCK_SIZE;
+        }
+
+        /**
+        * Decrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param src        The plaintext buffer
+        * @param srcIndex    An offset into src
+        * @param dst        The ciphertext buffer
+        * @param dstIndex    An offset into dst
+        */
+        internal virtual int DecryptBlock(
+            byte[] src,
+            int srcIndex,
+            byte[] dst,
+            int dstIndex)
+        {
+            // process the input block
+            // batch the units up into a 32 bit chunk and go for it
+            // the array is in bytes, the increment is 8x8 bits = 64
+            uint L16 = Pack.BE_To_UInt32(src, srcIndex);
+            uint R16 = Pack.BE_To_UInt32(src, srcIndex + 4);
+
+            uint[] result = new uint[2];
+            CAST_Decipher(L16, R16, result);
+
+            // now stuff them into the destination block
+            Pack.UInt32_To_BE(result[0], dst, dstIndex);
+            Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
+
+            return BLOCK_SIZE;
+        }
+
+        /**
+        * The first of the three processing functions for the
+        * encryption and decryption.
+        *
+        * @param D            the input to be processed
+        * @param Kmi        the mask to be used from Km[n]
+        * @param Kri        the rotation value to be used
+        *
+        */
+        internal static uint F1(uint D, uint Kmi, int Kri)
+        {
+            uint I = Kmi + D;
+            I = I << Kri | (I >> (32-Kri));
+            return ((S1[(I>>24)&0xff]^S2[(I>>16)&0xff])-S3[(I>>8)&0xff])+S4[I&0xff];
+        }
+
+        /**
+        * The second of the three processing functions for the
+        * encryption and decryption.
+        *
+        * @param D            the input to be processed
+        * @param Kmi        the mask to be used from Km[n]
+        * @param Kri        the rotation value to be used
+        *
+        */
+        internal static uint F2(uint D, uint Kmi, int Kri)
+        {
+            uint I = Kmi ^ D;
+            I = I << Kri | (I >> (32-Kri));
+            return ((S1[(I>>24)&0xff]-S2[(I>>16)&0xff])+S3[(I>>8)&0xff])^S4[I&0xff];
+        }
+
+        /**
+        * The third of the three processing functions for the
+        * encryption and decryption.
+        *
+        * @param D            the input to be processed
+        * @param Kmi        the mask to be used from Km[n]
+        * @param Kri        the rotation value to be used
+        *
+        */
+        internal static uint F3(uint D, uint Kmi, int Kri)
+        {
+            uint I = Kmi - D;
+            I = I << Kri | (I >> (32-Kri));
+            return ((S1[(I>>24)&0xff]+S2[(I>>16)&0xff])^S3[(I>>8)&0xff])-S4[I&0xff];
+        }
+
+        /**
+        * Does the 16 rounds to encrypt the block.
+        *
+        * @param L0    the LH-32bits of the plaintext block
+        * @param R0    the RH-32bits of the plaintext block
+        */
+        internal void CAST_Encipher(uint L0, uint R0, uint[] result)
+        {
+            uint Lp = L0;        // the previous value, equiv to L[i-1]
+            uint Rp = R0;        // equivalent to R[i-1]
+
+            /*
+            * numbering consistent with paper to make
+            * checking and validating easier
+            */
+            uint Li = L0, Ri = R0;
+
+            for (int i = 1; i<=_rounds ; i++)
+            {
+                Lp = Li;
+                Rp = Ri;
+
+                Li = Rp;
+                switch (i)
+                {
+                    case  1:
+                    case  4:
+                    case  7:
+                    case 10:
+                    case 13:
+                    case 16:
+                        Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+                        break;
+                    case  2:
+                    case  5:
+                    case  8:
+                    case 11:
+                    case 14:
+                        Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+                        break;
+                    case  3:
+                    case  6:
+                    case  9:
+                    case 12:
+                    case 15:
+                        Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+                        break;
+                }
+            }
+
+            result[0] = Ri;
+            result[1] = Li;
+
+            return;
+        }
+
+        internal void CAST_Decipher(uint L16, uint R16, uint[] result)
+        {
+            uint Lp = L16;        // the previous value, equiv to L[i-1]
+            uint Rp = R16;        // equivalent to R[i-1]
+
+            /*
+            * numbering consistent with paper to make
+            * checking and validating easier
+            */
+            uint Li = L16, Ri = R16;
+
+            for (int i = _rounds; i > 0; i--)
+            {
+                Lp = Li;
+                Rp = Ri;
+
+                Li = Rp;
+                switch (i)
+                {
+                    case  1:
+                    case  4:
+                    case  7:
+                    case 10:
+                    case 13:
+                    case 16:
+                        Ri = Lp ^ F1(Rp, _Km[i], _Kr[i]);
+                        break;
+                    case  2:
+                    case  5:
+                    case  8:
+                    case 11:
+                    case 14:
+                        Ri = Lp ^ F2(Rp, _Km[i], _Kr[i]);
+                        break;
+                    case  3:
+                    case  6:
+                    case  9:
+                    case 12:
+                    case 15:
+                        Ri = Lp ^ F3(Rp, _Km[i], _Kr[i]);
+                        break;
+                }
+            }
+
+            result[0] = Ri;
+            result[1] = Li;
+
+            return;
+        }
+
+        internal static void Bits32ToInts(uint inData, int[] b, int offset)
+        {
+            b[offset + 3] = (int) (inData & 0xff);
+            b[offset + 2] = (int) ((inData >> 8) & 0xff);
+            b[offset + 1] = (int) ((inData >> 16) & 0xff);
+            b[offset]     = (int) ((inData >> 24) & 0xff);
+        }
+
+        internal static uint IntsTo32bits(int[] b, int i)
+        {
+            return (uint)(((b[i]   & 0xff) << 24) |
+                ((b[i+1] & 0xff) << 16) |
+                ((b[i+2] & 0xff) << 8) |
+                ((b[i+3] & 0xff)));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/Cast6Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/Cast6Engine.cs
new file mode 100644
index 0000000..c5c419b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/Cast6Engine.cs
@@ -0,0 +1,279 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+     * A class that provides CAST6 key encryption operations,
+     * such as encoding data and generating keys.
+     *
+     * All the algorithms herein are from the Internet RFC
+     *
+     * RFC2612 - CAST6 (128bit block, 128-256bit key)
+     *
+     * and implement a simplified cryptography interface.
+     */
+    public sealed class Cast6Engine
+		: Cast5Engine
+    {
+        //====================================
+        // Useful constants
+        //====================================
+        private const int ROUNDS = 12;
+        private const int BLOCK_SIZE = 16;  // bytes = 128 bits
+
+		/*
+        * Put the round and mask keys into an array.
+        * Kr0[i] => _Kr[i*4 + 0]
+        */
+        private int []_Kr = new int[ROUNDS*4]; // the rotating round key(s)
+        private uint []_Km = new uint[ROUNDS*4]; // the masking round key(s)
+
+		/*
+        * Key setup
+        */
+        private int []_Tr = new int[24 * 8];
+        private uint []_Tm = new uint[24 * 8];
+        private uint[] _workingKey = new uint[8];
+
+		public Cast6Engine()
+        {
+        }
+
+		public override string AlgorithmName
+        {
+            get { return "CAST6"; }
+        }
+
+		public override void Reset()
+        {
+        }
+
+		public override int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+		//==================================
+        // Private Implementation
+        //==================================
+        /*
+        * Creates the subkeys using the same nomenclature
+        * as described in RFC2612.
+        *
+        * See section 2.4
+        */
+        internal override void SetKey(
+			byte[] key)
+        {
+            uint Cm = 0x5a827999;
+            uint Mm = 0x6ed9eba1;
+            int Cr = 19;
+            int Mr = 17;
+            /*
+            * Determine the key size here, if required
+            *
+            * if keysize < 256 bytes, pad with 0
+            *
+            * Typical key sizes => 128, 160, 192, 224, 256
+            */
+            for (int i=0; i< 24; i++)
+            {
+                for (int j=0; j< 8; j++)
+                {
+                    _Tm[i*8 + j] = Cm;
+                    Cm += Mm; //mod 2^32;
+                    _Tr[i*8 + j] = Cr;
+                    Cr = (Cr + Mr) & 0x1f;            // mod 32
+                }
+            }
+
+			byte[] tmpKey = new byte[64];
+			key.CopyTo(tmpKey, 0);
+
+			// now create ABCDEFGH
+            for (int i = 0; i < 8; i++)
+            {
+                _workingKey[i] = Pack.BE_To_UInt32(tmpKey, i*4);
+            }
+
+			// Generate the key schedule
+            for (int i = 0; i < 12; i++)
+            {
+                // KAPPA <- W2i(KAPPA)
+                int i2 = i*2 *8;
+                _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
+                _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+                _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+                _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+                _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+                _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+                _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+                _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+                // KAPPA <- W2i+1(KAPPA)
+                i2 = (i*2 + 1)*8;
+                _workingKey[6] ^= F1(_workingKey[7], _Tm[i2], _Tr[i2]);
+                _workingKey[5] ^= F2(_workingKey[6], _Tm[i2+1], _Tr[i2+1]);
+                _workingKey[4] ^= F3(_workingKey[5], _Tm[i2+2], _Tr[i2+2]);
+                _workingKey[3] ^= F1(_workingKey[4], _Tm[i2+3], _Tr[i2+3]);
+                _workingKey[2] ^= F2(_workingKey[3], _Tm[i2+4], _Tr[i2+4]);
+                _workingKey[1] ^= F3(_workingKey[2], _Tm[i2+5], _Tr[i2+5]);
+                _workingKey[0] ^= F1(_workingKey[1], _Tm[i2+6], _Tr[i2+6]);
+                _workingKey[7] ^= F2(_workingKey[0], _Tm[i2+7], _Tr[i2+7]);
+                // Kr_(i) <- KAPPA
+                _Kr[i*4] = (int)(_workingKey[0] & 0x1f);
+                _Kr[i*4 + 1] = (int)(_workingKey[2] & 0x1f);
+                _Kr[i*4 + 2] = (int)(_workingKey[4] & 0x1f);
+                _Kr[i*4 + 3] = (int)(_workingKey[6] & 0x1f);
+                // Km_(i) <- KAPPA
+                _Km[i*4] = _workingKey[7];
+                _Km[i*4 + 1] = _workingKey[5];
+                _Km[i*4 + 2] = _workingKey[3];
+                _Km[i*4 + 3] = _workingKey[1];
+            }
+        }
+
+		/**
+        * Encrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param src        The plaintext buffer
+        * @param srcIndex    An offset into src
+        * @param dst        The ciphertext buffer
+        * @param dstIndex    An offset into dst
+        */
+        internal override int EncryptBlock(
+            byte[]	src,
+            int		srcIndex,
+            byte[]	dst,
+            int		dstIndex)
+        {
+            // process the input block
+            // batch the units up into 4x32 bit chunks and go for it
+            uint A = Pack.BE_To_UInt32(src, srcIndex);
+            uint B = Pack.BE_To_UInt32(src, srcIndex + 4);
+            uint C = Pack.BE_To_UInt32(src, srcIndex + 8);
+            uint D = Pack.BE_To_UInt32(src, srcIndex + 12);
+            uint[] result = new uint[4];
+            CAST_Encipher(A, B, C, D, result);
+            // now stuff them into the destination block
+            Pack.UInt32_To_BE(result[0], dst, dstIndex);
+            Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
+            Pack.UInt32_To_BE(result[2], dst, dstIndex + 8);
+            Pack.UInt32_To_BE(result[3], dst, dstIndex + 12);
+            return BLOCK_SIZE;
+        }
+
+		/**
+        * Decrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param src        The plaintext buffer
+        * @param srcIndex    An offset into src
+        * @param dst        The ciphertext buffer
+        * @param dstIndex    An offset into dst
+        */
+        internal override int DecryptBlock(
+            byte[]	src,
+            int		srcIndex,
+            byte[]	dst,
+            int		dstIndex)
+        {
+            // process the input block
+            // batch the units up into 4x32 bit chunks and go for it
+            uint A = Pack.BE_To_UInt32(src, srcIndex);
+            uint B = Pack.BE_To_UInt32(src, srcIndex + 4);
+            uint C = Pack.BE_To_UInt32(src, srcIndex + 8);
+            uint D = Pack.BE_To_UInt32(src, srcIndex + 12);
+            uint[] result = new uint[4];
+            CAST_Decipher(A, B, C, D, result);
+            // now stuff them into the destination block
+            Pack.UInt32_To_BE(result[0], dst, dstIndex);
+            Pack.UInt32_To_BE(result[1], dst, dstIndex + 4);
+            Pack.UInt32_To_BE(result[2], dst, dstIndex + 8);
+            Pack.UInt32_To_BE(result[3], dst, dstIndex + 12);
+            return BLOCK_SIZE;
+        }
+
+		/**
+        * Does the 12 quad rounds rounds to encrypt the block.
+        *
+        * @param A    the 00-31  bits of the plaintext block
+        * @param B    the 32-63  bits of the plaintext block
+        * @param C    the 64-95  bits of the plaintext block
+        * @param D    the 96-127 bits of the plaintext block
+        * @param result the resulting ciphertext
+        */
+        private void CAST_Encipher(
+			uint	A,
+			uint	B,
+			uint	C,
+			uint	D,
+			uint[]	result)
+        {
+            for (int i = 0; i < 6; i++)
+            {
+                int x = i*4;
+                // BETA <- Qi(BETA)
+                C ^= F1(D, _Km[x], _Kr[x]);
+                B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+                A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+                D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+            }
+            for (int i = 6; i < 12; i++)
+            {
+                int x = i*4;
+                // BETA <- QBARi(BETA)
+                D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+                A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+                B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+                C ^= F1(D, _Km[x], _Kr[x]);
+            }
+            result[0] = A;
+            result[1] = B;
+            result[2] = C;
+            result[3] = D;
+        }
+
+		/**
+        * Does the 12 quad rounds rounds to decrypt the block.
+        *
+        * @param A    the 00-31  bits of the ciphertext block
+        * @param B    the 32-63  bits of the ciphertext block
+        * @param C    the 64-95  bits of the ciphertext block
+        * @param D    the 96-127 bits of the ciphertext block
+        * @param result the resulting plaintext
+        */
+        private void CAST_Decipher(
+			uint	A,
+			uint	B,
+			uint	C,
+			uint	D,
+			uint[]	result)
+        {
+            for (int i = 0; i < 6; i++)
+            {
+                int x = (11-i)*4;
+                // BETA <- Qi(BETA)
+                C ^= F1(D, _Km[x], _Kr[x]);
+                B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+                A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+                D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+            }
+            for (int i=6; i<12; i++)
+            {
+                int x = (11-i)*4;
+                // BETA <- QBARi(BETA)
+                D ^= F1(A, _Km[x + 3], _Kr[x + 3]);
+                A ^= F3(B, _Km[x + 2], _Kr[x + 2]);
+                B ^= F2(C, _Km[x + 1], _Kr[x + 1]);
+                C ^= F1(D, _Km[x], _Kr[x]);
+            }
+            result[0] = A;
+            result[1] = B;
+            result[2] = C;
+            result[3] = D;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/ChaChaEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/ChaChaEngine.cs
new file mode 100644
index 0000000..f4a7b8f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/ChaChaEngine.cs
@@ -0,0 +1,189 @@
+using System;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <summary>
+	/// Implementation of Daniel J. Bernstein's ChaCha stream cipher.
+	/// </summary>
+	public class ChaChaEngine
+		: Salsa20Engine
+	{
+
+		/// <summary>
+		/// Creates a 20 rounds ChaCha engine.
+		/// </summary>
+		public ChaChaEngine()
+		{
+		}
+
+		/// <summary>
+		/// Creates a ChaCha engine with a specific number of rounds.
+		/// </summary>
+		/// <param name="rounds">the number of rounds (must be an even number).</param>
+		public ChaChaEngine(int rounds)
+			: base(rounds)
+		{
+		}
+
+		public override string AlgorithmName
+		{
+			get { return "ChaCha" + rounds; }
+		}
+
+		protected override void AdvanceCounter()
+		{
+			if (++engineState[12] == 0)
+			{
+				++engineState[13];
+			}
+		}
+
+		protected override void ResetCounter()
+		{
+			engineState[12] = engineState[13] = 0;
+		}
+
+		protected override void SetKey(byte[] keyBytes, byte[] ivBytes)
+		{
+			if ((keyBytes.Length != 16) && (keyBytes.Length != 32))
+			{
+				throw new ArgumentException(AlgorithmName + " requires 128 bit or 256 bit key");
+			}
+
+			int offset = 0;
+			byte[] constants;
+
+			// Key
+			engineState[4] = Pack.LE_To_UInt32(keyBytes, 0);
+			engineState[5] = Pack.LE_To_UInt32(keyBytes, 4);
+			engineState[6] = Pack.LE_To_UInt32(keyBytes, 8);
+			engineState[7] = Pack.LE_To_UInt32(keyBytes, 12);
+
+			if (keyBytes.Length == 32)
+			{
+				constants = sigma;
+				offset = 16;
+			} else
+			{
+				constants = tau;
+			}
+
+			engineState[8] = Pack.LE_To_UInt32(keyBytes, offset);
+			engineState[9] = Pack.LE_To_UInt32(keyBytes, offset + 4);
+			engineState[10] = Pack.LE_To_UInt32(keyBytes, offset + 8);
+			engineState[11] = Pack.LE_To_UInt32(keyBytes, offset + 12);
+
+			engineState[0] = Pack.LE_To_UInt32(constants, 0);
+			engineState[1] = Pack.LE_To_UInt32(constants, 4);
+			engineState[2] = Pack.LE_To_UInt32(constants, 8);
+			engineState[3] = Pack.LE_To_UInt32(constants, 12);
+
+			// Counter
+			engineState[12] = engineState[13] = 0;
+
+			// IV
+			engineState[14] = Pack.LE_To_UInt32(ivBytes, 0);
+			engineState[15] = Pack.LE_To_UInt32(ivBytes, 4);
+		}
+
+		protected override void GenerateKeyStream(byte[] output)
+		{
+			ChachaCore(rounds, engineState, x);
+			Pack.UInt32_To_LE(x, output, 0);
+		}
+
+		/// <summary>
+		/// ChacCha function.
+		/// </summary>
+		/// <param name="rounds">The number of ChaCha rounds to execute</param>
+		/// <param name="input">The input words.</param>
+		/// <param name="x">The ChaCha state to modify.</param>
+		internal static void ChachaCore(int rounds, uint[] input, uint[] x)
+		{
+			if (input.Length != 16) {
+				throw new ArgumentException();
+			}
+			if (x.Length != 16) {
+				throw new ArgumentException();
+			}
+			if (rounds % 2 != 0) {
+				throw new ArgumentException("Number of rounds must be even");
+			}
+
+			uint x00 = input[ 0];
+			uint x01 = input[ 1];
+			uint x02 = input[ 2];
+			uint x03 = input[ 3];
+			uint x04 = input[ 4];
+			uint x05 = input[ 5];
+			uint x06 = input[ 6];
+			uint x07 = input[ 7];
+			uint x08 = input[ 8];
+			uint x09 = input[ 9];
+			uint x10 = input[10];
+			uint x11 = input[11];
+			uint x12 = input[12];
+			uint x13 = input[13];
+			uint x14 = input[14];
+			uint x15 = input[15];
+
+			for (int i = rounds; i > 0; i -= 2)
+			{
+				x00 += x04; x12 = R(x12 ^ x00, 16);
+				x08 += x12; x04 = R(x04 ^ x08, 12);
+				x00 += x04; x12 = R(x12 ^ x00, 8);
+				x08 += x12; x04 = R(x04 ^ x08, 7);
+				x01 += x05; x13 = R(x13 ^ x01, 16);
+				x09 += x13; x05 = R(x05 ^ x09, 12);
+				x01 += x05; x13 = R(x13 ^ x01, 8);
+				x09 += x13; x05 = R(x05 ^ x09, 7);
+				x02 += x06; x14 = R(x14 ^ x02, 16);
+				x10 += x14; x06 = R(x06 ^ x10, 12);
+				x02 += x06; x14 = R(x14 ^ x02, 8);
+				x10 += x14; x06 = R(x06 ^ x10, 7);
+				x03 += x07; x15 = R(x15 ^ x03, 16);
+				x11 += x15; x07 = R(x07 ^ x11, 12);
+				x03 += x07; x15 = R(x15 ^ x03, 8);
+				x11 += x15; x07 = R(x07 ^ x11, 7);
+				x00 += x05; x15 = R(x15 ^ x00, 16);
+				x10 += x15; x05 = R(x05 ^ x10, 12);
+				x00 += x05; x15 = R(x15 ^ x00, 8);
+				x10 += x15; x05 = R(x05 ^ x10, 7);
+				x01 += x06; x12 = R(x12 ^ x01, 16);
+				x11 += x12; x06 = R(x06 ^ x11, 12);
+				x01 += x06; x12 = R(x12 ^ x01, 8);
+				x11 += x12; x06 = R(x06 ^ x11, 7);
+				x02 += x07; x13 = R(x13 ^ x02, 16);
+				x08 += x13; x07 = R(x07 ^ x08, 12);
+				x02 += x07; x13 = R(x13 ^ x02, 8);
+				x08 += x13; x07 = R(x07 ^ x08, 7);
+				x03 += x04; x14 = R(x14 ^ x03, 16);
+				x09 += x14; x04 = R(x04 ^ x09, 12);
+				x03 += x04; x14 = R(x14 ^ x03, 8);
+				x09 += x14; x04 = R(x04 ^ x09, 7);
+
+			}
+
+			x[ 0] = x00 + input[ 0];
+			x[ 1] = x01 + input[ 1];
+			x[ 2] = x02 + input[ 2];
+			x[ 3] = x03 + input[ 3];
+			x[ 4] = x04 + input[ 4];
+			x[ 5] = x05 + input[ 5];
+			x[ 6] = x06 + input[ 6];
+			x[ 7] = x07 + input[ 7];
+			x[ 8] = x08 + input[ 8];
+			x[ 9] = x09 + input[ 9];
+			x[10] = x10 + input[10];
+			x[11] = x11 + input[11];
+			x[12] = x12 + input[12];
+			x[13] = x13 + input[13];
+			x[14] = x14 + input[14];
+			x[15] = x15 + input[15];
+		}
+
+	}
+
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeEngine.cs
new file mode 100644
index 0000000..eec4ec5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeEngine.cs
@@ -0,0 +1,100 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /// <remarks>A class that provides a basic DESede (or Triple DES) engine.</remarks>
+    public class DesEdeEngine
+        : DesEngine
+    {
+        private int[] workingKey1, workingKey2, workingKey3;
+        private bool forEncryption;
+
+        /**
+        * initialise a DESede cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public override void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+                throw new ArgumentException("invalid parameter passed to DESede init - " + parameters.GetType().ToString());
+
+            byte[] keyMaster = ((KeyParameter)parameters).GetKey();
+            if (keyMaster.Length != 24 && keyMaster.Length != 16)
+                throw new ArgumentException("key size must be 16 or 24 bytes.");
+
+            this.forEncryption = forEncryption;
+
+            byte[] key1 = new byte[8];
+            Array.Copy(keyMaster, 0, key1, 0, key1.Length);
+            workingKey1 = GenerateWorkingKey(forEncryption, key1);
+
+            byte[] key2 = new byte[8];
+            Array.Copy(keyMaster, 8, key2, 0, key2.Length);
+            workingKey2 = GenerateWorkingKey(!forEncryption, key2);
+
+            if (keyMaster.Length == 24)
+            {
+                byte[] key3 = new byte[8];
+                Array.Copy(keyMaster, 16, key3, 0, key3.Length);
+                workingKey3 = GenerateWorkingKey(forEncryption, key3);
+            }
+            else        // 16 byte key
+            {
+                workingKey3 = workingKey1;
+            }
+        }
+
+        public override string AlgorithmName
+        {
+            get { return "DESede"; }
+        }
+
+        public override int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public override int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (workingKey1 == null)
+                throw new InvalidOperationException("DESede engine not initialised");
+            if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+            byte[] temp = new byte[BLOCK_SIZE];
+
+            if (forEncryption)
+            {
+                DesFunc(workingKey1, input, inOff, temp, 0);
+                DesFunc(workingKey2, temp, 0, temp, 0);
+                DesFunc(workingKey3, temp, 0, output, outOff);
+            }
+            else
+            {
+                DesFunc(workingKey3, input, inOff, temp, 0);
+                DesFunc(workingKey2, temp, 0, temp, 0);
+                DesFunc(workingKey1, temp, 0, output, outOff);
+            }
+
+            return BLOCK_SIZE;
+        }
+
+        public override void Reset()
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeWrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeWrapEngine.cs
new file mode 100644
index 0000000..fdc7168
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/DesEdeWrapEngine.cs
@@ -0,0 +1,322 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * Wrap keys according to
+    * <a href="http://www.ietf.org/internet-drafts/draft-ietf-smime-key-wrap-01.txt">
+    * draft-ietf-smime-key-wrap-01.txt</a>.
+    * <p>
+    * Note:
+    * <ul>
+    * <li>this is based on a draft, and as such is subject to change - don't use this class for anything requiring long term storage.</li>
+    * <li>if you are using this to wrap triple-des keys you need to set the
+    * parity bits on the key and, if it's a two-key triple-des key, pad it
+    * yourself.</li>
+    * </ul>
+	* </p>
+    */
+    public class DesEdeWrapEngine
+		: IWrapper
+    {
+        /** Field engine */
+        private CbcBlockCipher engine;
+        /** Field param */
+        private KeyParameter param;
+        /** Field paramPlusIV */
+        private ParametersWithIV paramPlusIV;
+        /** Field iv */
+        private byte[] iv;
+        /** Field forWrapping */
+        private bool forWrapping;
+        /** Field IV2           */
+        private static readonly byte[] IV2 = { (byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+                                            (byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+                                            (byte) 0x21, (byte) 0x05 };
+
+		//
+        // checksum digest
+        //
+        private readonly IDigest sha1 = new Sha1Digest();
+        private readonly byte[] digest = new byte[20];
+
+		/**
+        * Method init
+        *
+        * @param forWrapping
+        * @param param
+        */
+        public void Init(
+			bool				forWrapping,
+			ICipherParameters	parameters)
+        {
+            this.forWrapping = forWrapping;
+            this.engine = new CbcBlockCipher(new DesEdeEngine());
+
+			SecureRandom sr;
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom pr = (ParametersWithRandom) parameters;
+				parameters = pr.Parameters;
+				sr = pr.Random;
+			}
+			else
+			{
+				sr = new SecureRandom();
+			}
+
+			if (parameters is KeyParameter)
+            {
+                this.param = (KeyParameter) parameters;
+                if (this.forWrapping)
+				{
+                    // Hm, we have no IV but we want to wrap ?!?
+                    // well, then we have to create our own IV.
+                    this.iv = new byte[8];
+					sr.NextBytes(iv);
+
+					this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+                }
+            }
+            else if (parameters is ParametersWithIV)
+            {
+				if (!forWrapping)
+					throw new ArgumentException("You should not supply an IV for unwrapping");
+
+				this.paramPlusIV = (ParametersWithIV) parameters;
+                this.iv = this.paramPlusIV.GetIV();
+                this.param = (KeyParameter) this.paramPlusIV.Parameters;
+
+				if (this.iv.Length != 8)
+					throw new ArgumentException("IV is not 8 octets", "parameters");
+            }
+        }
+
+		/**
+        * Method GetAlgorithmName
+        *
+        * @return
+        */
+        public string AlgorithmName
+        {
+            get { return "DESede"; }
+        }
+
+		/**
+        * Method wrap
+        *
+        * @param in
+        * @param inOff
+        * @param inLen
+        * @return
+        */
+        public byte[] Wrap(
+			byte[]	input,
+			int		inOff,
+			int		length)
+        {
+            if (!forWrapping)
+            {
+                throw new InvalidOperationException("Not initialized for wrapping");
+            }
+
+			byte[] keyToBeWrapped = new byte[length];
+            Array.Copy(input, inOff, keyToBeWrapped, 0, length);
+
+            // Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+            byte[] CKS = CalculateCmsKeyChecksum(keyToBeWrapped);
+
+            // Let WKCKS = WK || CKS where || is concatenation.
+            byte[] WKCKS = new byte[keyToBeWrapped.Length + CKS.Length];
+            Array.Copy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.Length);
+            Array.Copy(CKS, 0, WKCKS, keyToBeWrapped.Length, CKS.Length);
+
+            // Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+            // initialization vector. Call the results TEMP1.
+
+			int blockSize = engine.GetBlockSize();
+
+			if (WKCKS.Length % blockSize != 0)
+                throw new InvalidOperationException("Not multiple of block length");
+
+			engine.Init(true, paramPlusIV);
+
+            byte [] TEMP1 = new byte[WKCKS.Length];
+
+			for (int currentBytePos = 0; currentBytePos != WKCKS.Length; currentBytePos += blockSize)
+			{
+                engine.ProcessBlock(WKCKS, currentBytePos, TEMP1, currentBytePos);
+            }
+
+            // Let TEMP2 = IV || TEMP1.
+            byte[] TEMP2 = new byte[this.iv.Length + TEMP1.Length];
+            Array.Copy(this.iv, 0, TEMP2, 0, this.iv.Length);
+            Array.Copy(TEMP1, 0, TEMP2, this.iv.Length, TEMP1.Length);
+
+            // Reverse the order of the octets in TEMP2 and call the result TEMP3.
+            byte[] TEMP3 = reverse(TEMP2);
+
+			// Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+            // of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired
+            // result. It is 40 octets long if a 168 bit key is being wrapped.
+            ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+            this.engine.Init(true, param2);
+
+            for (int currentBytePos = 0; currentBytePos != TEMP3.Length; currentBytePos += blockSize)
+			{
+                engine.ProcessBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+            }
+
+            return TEMP3;
+        }
+
+		/**
+        * Method unwrap
+        *
+        * @param in
+        * @param inOff
+        * @param inLen
+        * @return
+        * @throws InvalidCipherTextException
+        */
+        public byte[] Unwrap(
+			byte[]	input,
+			int		inOff,
+			int		length)
+        {
+            if (forWrapping)
+            {
+                throw new InvalidOperationException("Not set for unwrapping");
+            }
+            if (input == null)
+            {
+                throw new InvalidCipherTextException("Null pointer as ciphertext");
+            }
+
+			int blockSize = engine.GetBlockSize();
+			
+            if (length % blockSize != 0)
+            {
+                throw new InvalidCipherTextException("Ciphertext not multiple of " + blockSize);
+            }
+
+			/*
+            // Check if the length of the cipher text is reasonable given the key
+            // type. It must be 40 bytes for a 168 bit key and either 32, 40, or
+            // 48 bytes for a 128, 192, or 256 bit key. If the length is not supported
+            // or inconsistent with the algorithm for which the key is intended,
+            // return error.
+            //
+            // we do not accept 168 bit keys. it has to be 192 bit.
+            int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+            int lengthB = estimatedKeyLengthInBit % 8;
+            if ((lengthA != keyToBeUnwrapped.Length) || (lengthB != 0)) {
+                throw new XMLSecurityException("empty");
+            }
+            */
+
+            // Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+            // and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+            ParametersWithIV param2 = new ParametersWithIV(this.param, IV2);
+            this.engine.Init(false, param2);
+
+            byte [] TEMP3 = new byte[length];
+
+			for (int currentBytePos = 0; currentBytePos != TEMP3.Length; currentBytePos += blockSize)
+			{
+				engine.ProcessBlock(input, inOff + currentBytePos, TEMP3, currentBytePos);
+            }
+
+            // Reverse the order of the octets in TEMP3 and call the result TEMP2.
+            byte[] TEMP2 = reverse(TEMP3);
+
+			// Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets.
+            this.iv = new byte[8];
+            byte[] TEMP1 = new byte[TEMP2.Length - 8];
+            Array.Copy(TEMP2, 0, this.iv, 0, 8);
+            Array.Copy(TEMP2, 8, TEMP1, 0, TEMP2.Length - 8);
+
+            // Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+            // found in the previous step. Call the result WKCKS.
+            this.paramPlusIV = new ParametersWithIV(this.param, this.iv);
+            this.engine.Init(false, this.paramPlusIV);
+
+            byte[] WKCKS = new byte[TEMP1.Length];
+
+            for (int currentBytePos = 0; currentBytePos != WKCKS.Length; currentBytePos += blockSize)
+			{
+                engine.ProcessBlock(TEMP1, currentBytePos, WKCKS, currentBytePos);
+            }
+
+            // Decompose WKCKS. CKS is the last 8 octets and WK, the wrapped key, are
+            // those octets before the CKS.
+            byte[] result = new byte[WKCKS.Length - 8];
+            byte[] CKStoBeVerified = new byte[8];
+            Array.Copy(WKCKS, 0, result, 0, WKCKS.Length - 8);
+            Array.Copy(WKCKS, WKCKS.Length - 8, CKStoBeVerified, 0, 8);
+
+            // Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare
+            // with the CKS extracted in the above step. If they are not equal, return error.
+            if (!CheckCmsKeyChecksum(result, CKStoBeVerified)) {
+                throw new InvalidCipherTextException(
+                    "Checksum inside ciphertext is corrupted");
+            }
+
+            // WK is the wrapped key, now extracted for use in data decryption.
+            return result;
+        }
+
+		/**
+        * Some key wrap algorithms make use of the Key Checksum defined
+        * in CMS [CMS-Algorithms]. This is used to provide an integrity
+        * check value for the key being wrapped. The algorithm is
+        *
+        * - Compute the 20 octet SHA-1 hash on the key being wrapped.
+        * - Use the first 8 octets of this hash as the checksum value.
+        *
+        * @param key
+        * @return
+        * @throws Exception
+        * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        */
+        private byte[] CalculateCmsKeyChecksum(
+            byte[] key)
+        {
+			sha1.BlockUpdate(key, 0, key.Length);
+            sha1.DoFinal(digest, 0);
+
+            byte[] result = new byte[8];
+			Array.Copy(digest, 0, result, 0, 8);
+			return result;
+        }
+
+		/**
+        * @param key
+        * @param checksum
+        * @return
+        * @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+        */
+        private bool CheckCmsKeyChecksum(
+            byte[]	key,
+            byte[]	checksum)
+        {
+			return Arrays.ConstantTimeAreEqual(CalculateCmsKeyChecksum(key), checksum);
+        }
+
+		private static byte[] reverse(byte[] bs)
+		{
+			byte[] result = new byte[bs.Length];
+			for (int i = 0; i < bs.Length; i++) 
+			{
+				result[i] = bs[bs.Length - (i + 1)];
+			}
+			return result;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/DesEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/DesEngine.cs
new file mode 100644
index 0000000..067cf45
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/DesEngine.cs
@@ -0,0 +1,475 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <remarks>A class that provides a basic DES engine.</remarks>
+    public class DesEngine
+		: IBlockCipher
+    {
+        internal const int BLOCK_SIZE = 8;
+
+		private int[] workingKey;
+
+        public virtual int[] GetWorkingKey()
+		{
+			return workingKey;
+		}
+
+		/**
+        * initialise a DES cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public virtual void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+				throw new ArgumentException("invalid parameter passed to DES init - " + parameters.GetType().ToString());
+
+			workingKey = GenerateWorkingKey(forEncryption, ((KeyParameter)parameters).GetKey());
+        }
+
+		public virtual string AlgorithmName
+        {
+            get { return "DES"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public virtual int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public virtual int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (workingKey == null)
+                throw new InvalidOperationException("DES engine not initialised");
+			if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+			DesFunc(workingKey, input, inOff, output, outOff);
+
+			return BLOCK_SIZE;
+        }
+
+        public virtual void Reset()
+        {
+        }
+
+        /**
+        * what follows is mainly taken from "Applied Cryptography", by
+        * Bruce Schneier, however it also bears great resemblance to Richard
+        * Outerbridge's D3DES...
+        */
+
+//        private static readonly short[] Df_Key =
+//        {
+//            0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,
+//            0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10,
+//            0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67
+//        };
+
+		private static readonly short[] bytebit =
+        {
+            128, 64, 32, 16, 8, 4, 2, 1
+        };
+
+		private static readonly int[] bigbyte =
+        {
+            0x800000,	0x400000,	0x200000,	0x100000,
+            0x80000,	0x40000,	0x20000,	0x10000,
+            0x8000,		0x4000,		0x2000,		0x1000,
+            0x800,		0x400,		0x200,		0x100,
+            0x80,		0x40,		0x20,		0x10,
+            0x8,		0x4,		0x2,		0x1
+        };
+
+		/*
+        * Use the key schedule specified in the Standard (ANSI X3.92-1981).
+        */
+        private static readonly byte[] pc1 =
+        {
+            56, 48, 40, 32, 24, 16,  8,   0, 57, 49, 41, 33, 25, 17,
+            9,  1, 58, 50, 42, 34, 26,  18, 10,  2, 59, 51, 43, 35,
+            62, 54, 46, 38, 30, 22, 14,   6, 61, 53, 45, 37, 29, 21,
+            13,  5, 60, 52, 44, 36, 28,  20, 12,  4, 27, 19, 11,  3
+        };
+
+        private static readonly byte[] totrot =
+        {
+            1, 2, 4, 6, 8, 10, 12, 14,
+            15, 17, 19, 21, 23, 25, 27, 28
+        };
+
+		private static readonly byte[] pc2 =
+        {
+            13, 16, 10, 23,  0,  4,  2, 27, 14,  5, 20,  9,
+            22, 18, 11,  3, 25,  7, 15,  6, 26, 19, 12,  1,
+            40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+            43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+        };
+
+		private static readonly uint[] SP1 =
+		{
+            0x01010400, 0x00000000, 0x00010000, 0x01010404,
+            0x01010004, 0x00010404, 0x00000004, 0x00010000,
+            0x00000400, 0x01010400, 0x01010404, 0x00000400,
+            0x01000404, 0x01010004, 0x01000000, 0x00000004,
+            0x00000404, 0x01000400, 0x01000400, 0x00010400,
+            0x00010400, 0x01010000, 0x01010000, 0x01000404,
+            0x00010004, 0x01000004, 0x01000004, 0x00010004,
+            0x00000000, 0x00000404, 0x00010404, 0x01000000,
+            0x00010000, 0x01010404, 0x00000004, 0x01010000,
+            0x01010400, 0x01000000, 0x01000000, 0x00000400,
+            0x01010004, 0x00010000, 0x00010400, 0x01000004,
+            0x00000400, 0x00000004, 0x01000404, 0x00010404,
+            0x01010404, 0x00010004, 0x01010000, 0x01000404,
+            0x01000004, 0x00000404, 0x00010404, 0x01010400,
+            0x00000404, 0x01000400, 0x01000400, 0x00000000,
+            0x00010004, 0x00010400, 0x00000000, 0x01010004
+        };
+
+		private static readonly uint[] SP2 =
+		{
+            0x80108020, 0x80008000, 0x00008000, 0x00108020,
+            0x00100000, 0x00000020, 0x80100020, 0x80008020,
+            0x80000020, 0x80108020, 0x80108000, 0x80000000,
+            0x80008000, 0x00100000, 0x00000020, 0x80100020,
+            0x00108000, 0x00100020, 0x80008020, 0x00000000,
+            0x80000000, 0x00008000, 0x00108020, 0x80100000,
+            0x00100020, 0x80000020, 0x00000000, 0x00108000,
+            0x00008020, 0x80108000, 0x80100000, 0x00008020,
+            0x00000000, 0x00108020, 0x80100020, 0x00100000,
+            0x80008020, 0x80100000, 0x80108000, 0x00008000,
+            0x80100000, 0x80008000, 0x00000020, 0x80108020,
+            0x00108020, 0x00000020, 0x00008000, 0x80000000,
+            0x00008020, 0x80108000, 0x00100000, 0x80000020,
+            0x00100020, 0x80008020, 0x80000020, 0x00100020,
+            0x00108000, 0x00000000, 0x80008000, 0x00008020,
+            0x80000000, 0x80100020, 0x80108020, 0x00108000
+        };
+
+		private static readonly uint[] SP3 =
+		{
+            0x00000208, 0x08020200, 0x00000000, 0x08020008,
+            0x08000200, 0x00000000, 0x00020208, 0x08000200,
+            0x00020008, 0x08000008, 0x08000008, 0x00020000,
+            0x08020208, 0x00020008, 0x08020000, 0x00000208,
+            0x08000000, 0x00000008, 0x08020200, 0x00000200,
+            0x00020200, 0x08020000, 0x08020008, 0x00020208,
+            0x08000208, 0x00020200, 0x00020000, 0x08000208,
+            0x00000008, 0x08020208, 0x00000200, 0x08000000,
+            0x08020200, 0x08000000, 0x00020008, 0x00000208,
+            0x00020000, 0x08020200, 0x08000200, 0x00000000,
+            0x00000200, 0x00020008, 0x08020208, 0x08000200,
+            0x08000008, 0x00000200, 0x00000000, 0x08020008,
+            0x08000208, 0x00020000, 0x08000000, 0x08020208,
+            0x00000008, 0x00020208, 0x00020200, 0x08000008,
+            0x08020000, 0x08000208, 0x00000208, 0x08020000,
+            0x00020208, 0x00000008, 0x08020008, 0x00020200
+        };
+
+		private static readonly uint[] SP4 =
+		{
+            0x00802001, 0x00002081, 0x00002081, 0x00000080,
+            0x00802080, 0x00800081, 0x00800001, 0x00002001,
+            0x00000000, 0x00802000, 0x00802000, 0x00802081,
+            0x00000081, 0x00000000, 0x00800080, 0x00800001,
+            0x00000001, 0x00002000, 0x00800000, 0x00802001,
+            0x00000080, 0x00800000, 0x00002001, 0x00002080,
+            0x00800081, 0x00000001, 0x00002080, 0x00800080,
+            0x00002000, 0x00802080, 0x00802081, 0x00000081,
+            0x00800080, 0x00800001, 0x00802000, 0x00802081,
+            0x00000081, 0x00000000, 0x00000000, 0x00802000,
+            0x00002080, 0x00800080, 0x00800081, 0x00000001,
+            0x00802001, 0x00002081, 0x00002081, 0x00000080,
+            0x00802081, 0x00000081, 0x00000001, 0x00002000,
+            0x00800001, 0x00002001, 0x00802080, 0x00800081,
+            0x00002001, 0x00002080, 0x00800000, 0x00802001,
+            0x00000080, 0x00800000, 0x00002000, 0x00802080
+        };
+
+		private static readonly uint[] SP5 =
+		{
+            0x00000100, 0x02080100, 0x02080000, 0x42000100,
+            0x00080000, 0x00000100, 0x40000000, 0x02080000,
+            0x40080100, 0x00080000, 0x02000100, 0x40080100,
+            0x42000100, 0x42080000, 0x00080100, 0x40000000,
+            0x02000000, 0x40080000, 0x40080000, 0x00000000,
+            0x40000100, 0x42080100, 0x42080100, 0x02000100,
+            0x42080000, 0x40000100, 0x00000000, 0x42000000,
+            0x02080100, 0x02000000, 0x42000000, 0x00080100,
+            0x00080000, 0x42000100, 0x00000100, 0x02000000,
+            0x40000000, 0x02080000, 0x42000100, 0x40080100,
+            0x02000100, 0x40000000, 0x42080000, 0x02080100,
+            0x40080100, 0x00000100, 0x02000000, 0x42080000,
+            0x42080100, 0x00080100, 0x42000000, 0x42080100,
+            0x02080000, 0x00000000, 0x40080000, 0x42000000,
+            0x00080100, 0x02000100, 0x40000100, 0x00080000,
+            0x00000000, 0x40080000, 0x02080100, 0x40000100
+        };
+
+		private static readonly uint[] SP6 =
+		{
+            0x20000010, 0x20400000, 0x00004000, 0x20404010,
+            0x20400000, 0x00000010, 0x20404010, 0x00400000,
+            0x20004000, 0x00404010, 0x00400000, 0x20000010,
+            0x00400010, 0x20004000, 0x20000000, 0x00004010,
+            0x00000000, 0x00400010, 0x20004010, 0x00004000,
+            0x00404000, 0x20004010, 0x00000010, 0x20400010,
+            0x20400010, 0x00000000, 0x00404010, 0x20404000,
+            0x00004010, 0x00404000, 0x20404000, 0x20000000,
+            0x20004000, 0x00000010, 0x20400010, 0x00404000,
+            0x20404010, 0x00400000, 0x00004010, 0x20000010,
+            0x00400000, 0x20004000, 0x20000000, 0x00004010,
+            0x20000010, 0x20404010, 0x00404000, 0x20400000,
+            0x00404010, 0x20404000, 0x00000000, 0x20400010,
+            0x00000010, 0x00004000, 0x20400000, 0x00404010,
+            0x00004000, 0x00400010, 0x20004010, 0x00000000,
+            0x20404000, 0x20000000, 0x00400010, 0x20004010
+        };
+
+		private static readonly uint[] SP7 =
+		{
+            0x00200000, 0x04200002, 0x04000802, 0x00000000,
+            0x00000800, 0x04000802, 0x00200802, 0x04200800,
+            0x04200802, 0x00200000, 0x00000000, 0x04000002,
+            0x00000002, 0x04000000, 0x04200002, 0x00000802,
+            0x04000800, 0x00200802, 0x00200002, 0x04000800,
+            0x04000002, 0x04200000, 0x04200800, 0x00200002,
+            0x04200000, 0x00000800, 0x00000802, 0x04200802,
+            0x00200800, 0x00000002, 0x04000000, 0x00200800,
+            0x04000000, 0x00200800, 0x00200000, 0x04000802,
+            0x04000802, 0x04200002, 0x04200002, 0x00000002,
+            0x00200002, 0x04000000, 0x04000800, 0x00200000,
+            0x04200800, 0x00000802, 0x00200802, 0x04200800,
+            0x00000802, 0x04000002, 0x04200802, 0x04200000,
+            0x00200800, 0x00000000, 0x00000002, 0x04200802,
+            0x00000000, 0x00200802, 0x04200000, 0x00000800,
+            0x04000002, 0x04000800, 0x00000800, 0x00200002
+        };
+
+		private static readonly uint[] SP8 =
+		{
+            0x10001040, 0x00001000, 0x00040000, 0x10041040,
+            0x10000000, 0x10001040, 0x00000040, 0x10000000,
+            0x00040040, 0x10040000, 0x10041040, 0x00041000,
+            0x10041000, 0x00041040, 0x00001000, 0x00000040,
+            0x10040000, 0x10000040, 0x10001000, 0x00001040,
+            0x00041000, 0x00040040, 0x10040040, 0x10041000,
+            0x00001040, 0x00000000, 0x00000000, 0x10040040,
+            0x10000040, 0x10001000, 0x00041040, 0x00040000,
+            0x00041040, 0x00040000, 0x10041000, 0x00001000,
+            0x00000040, 0x10040040, 0x00001000, 0x00041040,
+            0x10001000, 0x00000040, 0x10000040, 0x10040000,
+            0x10040040, 0x10000000, 0x00040000, 0x10001040,
+            0x00000000, 0x10041040, 0x00040040, 0x10000040,
+            0x10040000, 0x10001000, 0x10001040, 0x00000000,
+            0x10041040, 0x00041000, 0x00041000, 0x00001040,
+            0x00001040, 0x00040040, 0x10000000, 0x10041000
+        };
+
+		/**
+        * Generate an integer based working key based on our secret key
+        * and what we processing we are planning to do.
+        *
+        * Acknowledgements for this routine go to James Gillogly and Phil Karn.
+        *         (whoever, and wherever they are!).
+        */
+        protected static int[] GenerateWorkingKey(
+            bool	encrypting,
+            byte[]	key)
+        {
+            int[] newKey = new int[32];
+            bool[] pc1m = new bool[56];
+			bool[] pcr = new bool[56];
+
+			for (int j = 0; j < 56; j++ )
+            {
+                int l = pc1[j];
+
+				pc1m[j] = ((key[(uint) l >> 3] & bytebit[l & 07]) != 0);
+            }
+
+            for (int i = 0; i < 16; i++)
+            {
+                int l, m, n;
+
+                if (encrypting)
+                {
+                    m = i << 1;
+                }
+                else
+                {
+                    m = (15 - i) << 1;
+                }
+
+                n = m + 1;
+                newKey[m] = newKey[n] = 0;
+
+                for (int j = 0; j < 28; j++)
+                {
+                    l = j + totrot[i];
+                    if ( l < 28 )
+                    {
+                        pcr[j] = pc1m[l];
+                    }
+                    else
+                    {
+                        pcr[j] = pc1m[l - 28];
+                    }
+                }
+
+                for (int j = 28; j < 56; j++)
+                {
+                    l = j + totrot[i];
+                    if (l < 56 )
+                    {
+                        pcr[j] = pc1m[l];
+                    }
+                    else
+                    {
+                        pcr[j] = pc1m[l - 28];
+                    }
+                }
+
+                for (int j = 0; j < 24; j++)
+                {
+                    if (pcr[pc2[j]])
+                    {
+                        newKey[m] |= bigbyte[j];
+                    }
+
+                    if (pcr[pc2[j + 24]])
+                    {
+                        newKey[n] |= bigbyte[j];
+                    }
+                }
+            }
+
+            //
+            // store the processed key
+            //
+            for (int i = 0; i != 32; i += 2)
+            {
+                int i1, i2;
+
+                i1 = newKey[i];
+                i2 = newKey[i + 1];
+
+                newKey[i] = (int) ( (uint) ((i1 & 0x00fc0000) << 6)  |
+                                    (uint) ((i1 & 0x00000fc0) << 10) |
+                                    ((uint) (i2 & 0x00fc0000) >> 10) |
+                                    ((uint) (i2 & 0x00000fc0) >> 6));
+
+                newKey[i + 1] = (int) ( (uint) ((i1 & 0x0003f000) << 12) |
+                                        (uint) ((i1 & 0x0000003f) << 16) |
+                                        ((uint) (i2 & 0x0003f000) >> 4) |
+                                        (uint) (i2 & 0x0000003f));
+            }
+
+            return newKey;
+        }
+
+        /**
+        * the DES engine.
+        */
+        internal static void DesFunc(
+            int[]	wKey,
+            byte[]	input,
+            int		inOff,
+            byte[]	outBytes,
+            int		outOff)
+        {
+			uint left = Pack.BE_To_UInt32(input, inOff);
+			uint right = Pack.BE_To_UInt32(input, inOff + 4);
+			uint work;
+
+            work = ((left >> 4) ^ right) & 0x0f0f0f0f;
+            right ^= work;
+            left ^= (work << 4);
+            work = ((left >> 16) ^ right) & 0x0000ffff;
+            right ^= work;
+            left ^= (work << 16);
+            work = ((right >> 2) ^ left) & 0x33333333;
+            left ^= work;
+            right ^= (work << 2);
+            work = ((right >> 8) ^ left) & 0x00ff00ff;
+            left ^= work;
+            right ^= (work << 8);
+            right = (right << 1) | (right >> 31);
+            work = (left ^ right) & 0xaaaaaaaa;
+            left ^= work;
+            right ^= work;
+            left = (left << 1) | (left >> 31);
+
+            for (int round = 0; round < 8; round++)
+            {
+                uint fval;
+
+                work  = (right << 28) | (right >> 4);
+                work ^= (uint)wKey[round * 4 + 0];
+                fval  = SP7[work         & 0x3f];
+                fval |= SP5[(work >>  8) & 0x3f];
+                fval |= SP3[(work >> 16) & 0x3f];
+                fval |= SP1[(work >> 24) & 0x3f];
+                work  = right ^ (uint)wKey[round * 4 + 1];
+                fval |= SP8[ work        & 0x3f];
+                fval |= SP6[(work >>  8) & 0x3f];
+                fval |= SP4[(work >> 16) & 0x3f];
+                fval |= SP2[(work >> 24) & 0x3f];
+                left ^= fval;
+                work  = (left << 28) | (left >> 4);
+                work ^= (uint)wKey[round * 4 + 2];
+                fval  = SP7[ work        & 0x3f];
+                fval |= SP5[(work >>  8) & 0x3f];
+                fval |= SP3[(work >> 16) & 0x3f];
+                fval |= SP1[(work >> 24) & 0x3f];
+                work  = left ^ (uint)wKey[round * 4 + 3];
+                fval |= SP8[ work        & 0x3f];
+                fval |= SP6[(work >>  8) & 0x3f];
+                fval |= SP4[(work >> 16) & 0x3f];
+                fval |= SP2[(work >> 24) & 0x3f];
+                right ^= fval;
+            }
+
+            right = (right << 31) | (right >> 1);
+            work = (left ^ right) & 0xaaaaaaaa;
+            left ^= work;
+            right ^= work;
+            left = (left << 31) | (left >> 1);
+            work = ((left >> 8) ^ right) & 0x00ff00ff;
+            right ^= work;
+            left ^= (work << 8);
+            work = ((left >> 2) ^ right) & 0x33333333;
+            right ^= work;
+            left ^= (work << 2);
+            work = ((right >> 16) ^ left) & 0x0000ffff;
+            left ^= work;
+            right ^= (work << 16);
+            work = ((right >> 4) ^ left) & 0x0f0f0f0f;
+            left ^= work;
+            right ^= (work << 4);
+
+			Pack.UInt32_To_BE(right, outBytes, outOff);
+			Pack.UInt32_To_BE(left, outBytes, outOff + 4);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/ElGamalEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/ElGamalEngine.cs
new file mode 100644
index 0000000..3d256a0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/ElGamalEngine.cs
@@ -0,0 +1,178 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* this does your basic ElGamal algorithm.
+	*/
+	public class ElGamalEngine
+		: IAsymmetricBlockCipher
+	{
+		private ElGamalKeyParameters key;
+		private SecureRandom random;
+		private bool forEncryption;
+		private int bitSize;
+
+		public string AlgorithmName
+		{
+			get { return "ElGamal"; }
+		}
+
+		/**
+		* initialise the ElGamal engine.
+		*
+		* @param forEncryption true if we are encrypting, false otherwise.
+		* @param param the necessary ElGamal key parameters.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom p = (ParametersWithRandom) parameters;
+
+				this.key = (ElGamalKeyParameters) p.Parameters;
+				this.random = p.Random;
+			}
+			else
+			{
+				this.key = (ElGamalKeyParameters) parameters;
+				this.random = new SecureRandom();
+			}
+
+			this.forEncryption = forEncryption;
+			this.bitSize = key.Parameters.P.BitLength;
+
+			if (forEncryption)
+			{
+				if (!(key is ElGamalPublicKeyParameters))
+				{
+					throw new ArgumentException("ElGamalPublicKeyParameters are required for encryption.");
+				}
+			}
+			else
+			{
+				if (!(key is ElGamalPrivateKeyParameters))
+				{
+					throw new ArgumentException("ElGamalPrivateKeyParameters are required for decryption.");
+				}
+			}
+		}
+
+		/**
+		* Return the maximum size for an input block to this engine.
+		* For ElGamal this is always one byte less than the size of P on
+		* encryption, and twice the length as the size of P on decryption.
+		*
+		* @return maximum size for an input block.
+		*/
+		public int GetInputBlockSize()
+		{
+			if (forEncryption)
+			{
+				return (bitSize - 1) / 8;
+			}
+
+			return 2 * ((bitSize + 7) / 8);
+		}
+
+		/**
+		* Return the maximum size for an output block to this engine.
+		* For ElGamal this is always one byte less than the size of P on
+		* decryption, and twice the length as the size of P on encryption.
+		*
+		* @return maximum size for an output block.
+		*/
+		public int GetOutputBlockSize()
+		{
+			if (forEncryption)
+			{
+				return 2 * ((bitSize + 7) / 8);
+			}
+
+			return (bitSize - 1) / 8;
+		}
+
+		/**
+		* Process a single block using the basic ElGamal algorithm.
+		*
+		* @param in the input array.
+		* @param inOff the offset into the input buffer where the data starts.
+		* @param length the length of the data to be processed.
+		* @return the result of the ElGamal process.
+		* @exception DataLengthException the input block is too large.
+		*/
+		public byte[] ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (key == null)
+				throw new InvalidOperationException("ElGamal engine not initialised");
+
+			int maxLength = forEncryption
+				?	(bitSize - 1 + 7) / 8
+				:	GetInputBlockSize();
+
+			if (length > maxLength)
+				throw new DataLengthException("input too large for ElGamal cipher.\n");
+
+			BigInteger p = key.Parameters.P;
+
+			byte[] output;
+			if (key is ElGamalPrivateKeyParameters) // decryption
+			{
+				int halfLength = length / 2;
+				BigInteger gamma = new BigInteger(1, input, inOff, halfLength);
+				BigInteger phi = new BigInteger(1, input, inOff + halfLength, halfLength);
+
+				ElGamalPrivateKeyParameters priv = (ElGamalPrivateKeyParameters) key;
+
+				// a shortcut, which generally relies on p being prime amongst other things.
+				// if a problem with this shows up, check the p and g values!
+				BigInteger m = gamma.ModPow(p.Subtract(BigInteger.One).Subtract(priv.X), p).Multiply(phi).Mod(p);
+
+				output = m.ToByteArrayUnsigned();
+			}
+			else // encryption
+			{
+				BigInteger tmp = new BigInteger(1, input, inOff, length);
+
+				if (tmp.BitLength >= p.BitLength)
+					throw new DataLengthException("input too large for ElGamal cipher.\n");
+
+
+				ElGamalPublicKeyParameters pub = (ElGamalPublicKeyParameters) key;
+
+				BigInteger pSub2 = p.Subtract(BigInteger.Two);
+
+				// TODO In theory, a series of 'k', 'g.ModPow(k, p)' and 'y.ModPow(k, p)' can be pre-calculated
+				BigInteger k;
+				do
+				{
+					k = new BigInteger(p.BitLength, random);
+				}
+				while (k.SignValue == 0 || k.CompareTo(pSub2) > 0);
+
+				BigInteger g = key.Parameters.G;
+				BigInteger gamma = g.ModPow(k, p);
+				BigInteger phi = tmp.Multiply(pub.Y.ModPow(k, p)).Mod(p);
+
+				output = new byte[this.GetOutputBlockSize()];
+
+				// TODO Add methods to allow writing BigInteger to existing byte array?
+				byte[] out1 = gamma.ToByteArrayUnsigned();
+				byte[] out2 = phi.ToByteArrayUnsigned();
+				out1.CopyTo(output, output.Length / 2 - out1.Length);
+				out2.CopyTo(output, output.Length - out2.Length);
+			}
+
+			return output;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/GOST28147Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/GOST28147Engine.cs
new file mode 100644
index 0000000..8eb6f36
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/GOST28147Engine.cs
@@ -0,0 +1,376 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* implementation of GOST 28147-89
+	*/
+	public class Gost28147Engine
+		: IBlockCipher
+	{
+		private const int  BlockSize = 8;
+		private int[] workingKey = null;
+		private bool forEncryption;
+
+		private byte[] S = Sbox_Default;
+
+		// these are the S-boxes given in Applied Cryptography 2nd Ed., p. 333
+		// This is default S-box!
+		private static readonly byte[] Sbox_Default = {
+			0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+			0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+			0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+			0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+			0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+			0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+			0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+			0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+		};
+
+		/*
+		 * class content S-box parameters for encrypting
+		 * getting from, see: http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-01.txt
+		 *                    http://tools.ietf.org/id/draft-popov-cryptopro-cpalgs-02.txt
+		 */
+		private static readonly byte[] ESbox_Test = {
+			0x4,0x2,0xF,0x5,0x9,0x1,0x0,0x8,0xE,0x3,0xB,0xC,0xD,0x7,0xA,0x6,
+			0xC,0x9,0xF,0xE,0x8,0x1,0x3,0xA,0x2,0x7,0x4,0xD,0x6,0x0,0xB,0x5,
+			0xD,0x8,0xE,0xC,0x7,0x3,0x9,0xA,0x1,0x5,0x2,0x4,0x6,0xF,0x0,0xB,
+			0xE,0x9,0xB,0x2,0x5,0xF,0x7,0x1,0x0,0xD,0xC,0x6,0xA,0x4,0x3,0x8,
+			0x3,0xE,0x5,0x9,0x6,0x8,0x0,0xD,0xA,0xB,0x7,0xC,0x2,0x1,0xF,0x4,
+			0x8,0xF,0x6,0xB,0x1,0x9,0xC,0x5,0xD,0x3,0x7,0xA,0x0,0xE,0x2,0x4,
+			0x9,0xB,0xC,0x0,0x3,0x6,0x7,0x5,0x4,0x8,0xE,0xF,0x1,0xA,0x2,0xD,
+			0xC,0x6,0x5,0x2,0xB,0x0,0x9,0xD,0x3,0xE,0x7,0xA,0xF,0x4,0x1,0x8
+		};
+
+		private static readonly byte[] ESbox_A = {
+			0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+			0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+			0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+			0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+			0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+			0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+			0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+			0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+		};
+
+		private static readonly byte[] ESbox_B = {
+			0x8,0x4,0xB,0x1,0x3,0x5,0x0,0x9,0x2,0xE,0xA,0xC,0xD,0x6,0x7,0xF,
+			0x0,0x1,0x2,0xA,0x4,0xD,0x5,0xC,0x9,0x7,0x3,0xF,0xB,0x8,0x6,0xE,
+			0xE,0xC,0x0,0xA,0x9,0x2,0xD,0xB,0x7,0x5,0x8,0xF,0x3,0x6,0x1,0x4,
+			0x7,0x5,0x0,0xD,0xB,0x6,0x1,0x2,0x3,0xA,0xC,0xF,0x4,0xE,0x9,0x8,
+			0x2,0x7,0xC,0xF,0x9,0x5,0xA,0xB,0x1,0x4,0x0,0xD,0x6,0x8,0xE,0x3,
+			0x8,0x3,0x2,0x6,0x4,0xD,0xE,0xB,0xC,0x1,0x7,0xF,0xA,0x0,0x9,0x5,
+			0x5,0x2,0xA,0xB,0x9,0x1,0xC,0x3,0x7,0x4,0xD,0x0,0x6,0xF,0x8,0xE,
+			0x0,0x4,0xB,0xE,0x8,0x3,0x7,0x1,0xA,0x2,0x9,0x6,0xF,0xD,0x5,0xC
+		};
+
+		private static readonly byte[] ESbox_C = {
+			0x1,0xB,0xC,0x2,0x9,0xD,0x0,0xF,0x4,0x5,0x8,0xE,0xA,0x7,0x6,0x3,
+			0x0,0x1,0x7,0xD,0xB,0x4,0x5,0x2,0x8,0xE,0xF,0xC,0x9,0xA,0x6,0x3,
+			0x8,0x2,0x5,0x0,0x4,0x9,0xF,0xA,0x3,0x7,0xC,0xD,0x6,0xE,0x1,0xB,
+			0x3,0x6,0x0,0x1,0x5,0xD,0xA,0x8,0xB,0x2,0x9,0x7,0xE,0xF,0xC,0x4,
+			0x8,0xD,0xB,0x0,0x4,0x5,0x1,0x2,0x9,0x3,0xC,0xE,0x6,0xF,0xA,0x7,
+			0xC,0x9,0xB,0x1,0x8,0xE,0x2,0x4,0x7,0x3,0x6,0x5,0xA,0x0,0xF,0xD,
+			0xA,0x9,0x6,0x8,0xD,0xE,0x2,0x0,0xF,0x3,0x5,0xB,0x4,0x1,0xC,0x7,
+			0x7,0x4,0x0,0x5,0xA,0x2,0xF,0xE,0xC,0x6,0x1,0xB,0xD,0x9,0x3,0x8
+		};
+
+		private static readonly byte[] ESbox_D = {
+			0xF,0xC,0x2,0xA,0x6,0x4,0x5,0x0,0x7,0x9,0xE,0xD,0x1,0xB,0x8,0x3,
+			0xB,0x6,0x3,0x4,0xC,0xF,0xE,0x2,0x7,0xD,0x8,0x0,0x5,0xA,0x9,0x1,
+			0x1,0xC,0xB,0x0,0xF,0xE,0x6,0x5,0xA,0xD,0x4,0x8,0x9,0x3,0x7,0x2,
+			0x1,0x5,0xE,0xC,0xA,0x7,0x0,0xD,0x6,0x2,0xB,0x4,0x9,0x3,0xF,0x8,
+			0x0,0xC,0x8,0x9,0xD,0x2,0xA,0xB,0x7,0x3,0x6,0x5,0x4,0xE,0xF,0x1,
+			0x8,0x0,0xF,0x3,0x2,0x5,0xE,0xB,0x1,0xA,0x4,0x7,0xC,0x9,0xD,0x6,
+			0x3,0x0,0x6,0xF,0x1,0xE,0x9,0x2,0xD,0x8,0xC,0x4,0xB,0xA,0x5,0x7,
+			0x1,0xA,0x6,0x8,0xF,0xB,0x0,0x4,0xC,0x3,0x5,0x9,0x7,0xD,0x2,0xE
+		};
+
+		//S-box for digest
+		private static readonly byte[] DSbox_Test = {
+			0x4,0xA,0x9,0x2,0xD,0x8,0x0,0xE,0x6,0xB,0x1,0xC,0x7,0xF,0x5,0x3,
+			0xE,0xB,0x4,0xC,0x6,0xD,0xF,0xA,0x2,0x3,0x8,0x1,0x0,0x7,0x5,0x9,
+			0x5,0x8,0x1,0xD,0xA,0x3,0x4,0x2,0xE,0xF,0xC,0x7,0x6,0x0,0x9,0xB,
+			0x7,0xD,0xA,0x1,0x0,0x8,0x9,0xF,0xE,0x4,0x6,0xC,0xB,0x2,0x5,0x3,
+			0x6,0xC,0x7,0x1,0x5,0xF,0xD,0x8,0x4,0xA,0x9,0xE,0x0,0x3,0xB,0x2,
+			0x4,0xB,0xA,0x0,0x7,0x2,0x1,0xD,0x3,0x6,0x8,0x5,0x9,0xC,0xF,0xE,
+			0xD,0xB,0x4,0x1,0x3,0xF,0x5,0x9,0x0,0xA,0xE,0x7,0x6,0x8,0x2,0xC,
+			0x1,0xF,0xD,0x0,0x5,0x7,0xA,0x4,0x9,0x2,0x3,0xE,0x6,0xB,0x8,0xC
+		};
+
+		private static readonly byte[] DSbox_A = {
+			0xA,0x4,0x5,0x6,0x8,0x1,0x3,0x7,0xD,0xC,0xE,0x0,0x9,0x2,0xB,0xF,
+			0x5,0xF,0x4,0x0,0x2,0xD,0xB,0x9,0x1,0x7,0x6,0x3,0xC,0xE,0xA,0x8,
+			0x7,0xF,0xC,0xE,0x9,0x4,0x1,0x0,0x3,0xB,0x5,0x2,0x6,0xA,0x8,0xD,
+			0x4,0xA,0x7,0xC,0x0,0xF,0x2,0x8,0xE,0x1,0x6,0x5,0xD,0xB,0x9,0x3,
+			0x7,0x6,0x4,0xB,0x9,0xC,0x2,0xA,0x1,0x8,0x0,0xE,0xF,0xD,0x3,0x5,
+			0x7,0x6,0x2,0x4,0xD,0x9,0xF,0x0,0xA,0x1,0x5,0xB,0x8,0xE,0xC,0x3,
+			0xD,0xE,0x4,0x1,0x7,0x0,0x5,0xA,0x3,0xC,0x8,0xF,0x6,0x2,0x9,0xB,
+			0x1,0x3,0xA,0x9,0x5,0xB,0x4,0xF,0x8,0x6,0x7,0xE,0xD,0x0,0x2,0xC
+		};
+
+		//
+		// pre-defined sbox table
+		//
+		private static readonly IDictionary sBoxes = Platform.CreateHashtable();
+
+		static Gost28147Engine()
+		{
+			AddSBox("Default", Sbox_Default);
+			AddSBox("E-TEST", ESbox_Test);
+			AddSBox("E-A", ESbox_A);
+			AddSBox("E-B", ESbox_B);
+			AddSBox("E-C", ESbox_C);
+			AddSBox("E-D", ESbox_D);
+			AddSBox("D-TEST", DSbox_Test);
+			AddSBox("D-A", DSbox_A);
+		}
+
+		private static void AddSBox(string sBoxName, byte[] sBox)
+		{
+			sBoxes.Add(Platform.ToUpperInvariant(sBoxName), sBox);        
+		}
+
+		/**
+		* standard constructor.
+		*/
+		public Gost28147Engine()
+		{
+		}
+
+		/**
+		* initialise an Gost28147 cipher.
+		*
+		* @param forEncryption whether or not we are for encryption.
+		* @param parameters the parameters required to set up the cipher.
+		* @exception ArgumentException if the parameters argument is inappropriate.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithSBox)
+			{
+				ParametersWithSBox   param = (ParametersWithSBox)parameters;
+
+				//
+				// Set the S-Box
+				//
+				byte[] sBox = param.GetSBox();
+				if (sBox.Length != Sbox_Default.Length)
+					throw new ArgumentException("invalid S-box passed to GOST28147 init");
+
+				this.S = Arrays.Clone(sBox);
+
+				//
+				// set key if there is one
+				//
+				if (param.Parameters != null)
+				{
+					workingKey = generateWorkingKey(forEncryption,
+							((KeyParameter)param.Parameters).GetKey());
+				}
+			}
+			else if (parameters is KeyParameter)
+			{
+				workingKey = generateWorkingKey(forEncryption,
+									((KeyParameter)parameters).GetKey());
+			}
+			else if (parameters != null)
+			{
+				throw new ArgumentException("invalid parameter passed to Gost28147 init - " + parameters.GetType().Name);
+			}
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Gost28147"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BlockSize;
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if (workingKey == null)
+			{
+				throw new InvalidOperationException("Gost28147 engine not initialised");
+			}
+
+			if ((inOff + BlockSize) > input.Length)
+			{
+				throw new DataLengthException("input buffer too short");
+			}
+
+			if ((outOff + BlockSize) > output.Length)
+			{
+				throw new DataLengthException("output buffer too short");
+			}
+
+			Gost28147Func(workingKey, input, inOff, output, outOff);
+
+			return BlockSize;
+		}
+
+		public void Reset()
+		{
+		}
+
+		private int[] generateWorkingKey(
+			bool forEncryption,
+			byte[]  userKey)
+		{
+			this.forEncryption = forEncryption;
+
+			if (userKey.Length != 32)
+			{
+				throw new ArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+			}
+
+			int[] key = new int[8];
+			for(int i=0; i!=8; i++)
+			{
+				key[i] = bytesToint(userKey,i*4);
+			}
+
+			return key;
+		}
+
+		private int Gost28147_mainStep(int n1, int key)
+		{
+			int cm = (key + n1); // CM1
+
+			// S-box replacing
+
+			int om = S[  0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+			om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+			om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+			om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+			om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+			om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+			om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+			om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+//			return om << 11 | om >>> (32-11); // 11-leftshift
+			int omLeft = om << 11;
+			int omRight = (int)(((uint) om) >> (32 - 11)); // Note: Casts required to get unsigned bit rotation
+
+			return omLeft | omRight;
+		}
+
+		private void Gost28147Func(
+			int[]   workingKey,
+			byte[]  inBytes,
+			int     inOff,
+			byte[]  outBytes,
+			int     outOff)
+		{
+			int N1, N2, tmp;  //tmp -> for saving N1
+			N1 = bytesToint(inBytes, inOff);
+			N2 = bytesToint(inBytes, inOff + 4);
+
+			if (this.forEncryption)
+			{
+			for(int k = 0; k < 3; k++)  // 1-24 steps
+			{
+				for(int j = 0; j < 8; j++)
+				{
+					tmp = N1;
+					int step = Gost28147_mainStep(N1, workingKey[j]);
+					N1 = N2 ^ step; // CM2
+					N2 = tmp;
+				}
+			}
+			for(int j = 7; j > 0; j--)  // 25-31 steps
+			{
+				tmp = N1;
+				N1 = N2 ^ Gost28147_mainStep(N1, workingKey[j]); // CM2
+				N2 = tmp;
+			}
+			}
+			else //decrypt
+			{
+			for(int j = 0; j < 8; j++)  // 1-8 steps
+			{
+				tmp = N1;
+				N1 = N2 ^ Gost28147_mainStep(N1, workingKey[j]); // CM2
+				N2 = tmp;
+			}
+			for(int k = 0; k < 3; k++)  //9-31 steps
+			{
+				for(int j = 7; j >= 0; j--)
+				{
+					if ((k == 2) && (j==0))
+					{
+						break; // break 32 step
+					}
+					tmp = N1;
+					N1 = N2 ^ Gost28147_mainStep(N1, workingKey[j]); // CM2
+					N2 = tmp;
+				}
+			}
+			}
+
+			N2 = N2 ^ Gost28147_mainStep(N1, workingKey[0]);  // 32 step (N1=N1)
+
+			intTobytes(N1, outBytes, outOff);
+			intTobytes(N2, outBytes, outOff + 4);
+		}
+
+		//array of bytes to type int
+		private static int bytesToint(
+			byte[]  inBytes,
+			int     inOff)
+		{
+			return  (int)((inBytes[inOff + 3] << 24) & 0xff000000) + ((inBytes[inOff + 2] << 16) & 0xff0000) +
+					((inBytes[inOff + 1] << 8) & 0xff00) + (inBytes[inOff] & 0xff);
+		}
+
+		//int to array of bytes
+		private static void intTobytes(
+				int     num,
+				byte[]  outBytes,
+				int     outOff)
+		{
+				outBytes[outOff + 3] = (byte)(num >> 24);
+				outBytes[outOff + 2] = (byte)(num >> 16);
+				outBytes[outOff + 1] = (byte)(num >> 8);
+				outBytes[outOff] =     (byte)num;
+		}
+
+		/**
+		* Return the S-Box associated with SBoxName
+		* @param sBoxName name of the S-Box
+		* @return byte array representing the S-Box
+		*/
+		public static byte[] GetSBox(
+			string sBoxName)
+		{
+			byte[] sBox = (byte[])sBoxes[Platform.ToUpperInvariant(sBoxName)];
+
+            if (sBox == null)
+			{
+				throw new ArgumentException("Unknown S-Box - possible types: "
+					+ "\"Default\", \"E-Test\", \"E-A\", \"E-B\", \"E-C\", \"E-D\", \"D-Test\", \"D-A\".");
+			}
+
+			return Arrays.Clone(sBox);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/HC128Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/HC128Engine.cs
new file mode 100644
index 0000000..a2d099f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/HC128Engine.cs
@@ -0,0 +1,235 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* HC-128 is a software-efficient stream cipher created by Hongjun Wu. It
+	* generates keystream from a 128-bit secret key and a 128-bit initialization
+	* vector.
+	* <p>
+	* http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+	* </p><p>
+	* It is a third phase candidate in the eStream contest, and is patent-free.
+	* No attacks are known as of today (April 2007). See
+	*
+	* http://www.ecrypt.eu.org/stream/hcp3.html
+	* </p>
+	*/
+	public class HC128Engine
+		: IStreamCipher
+	{
+		private uint[] p = new uint[512];
+		private uint[] q = new uint[512];
+		private uint cnt = 0;
+
+		private static uint F1(uint x)
+		{
+			return RotateRight(x, 7) ^ RotateRight(x, 18) ^ (x >> 3);
+		}
+
+		private static uint F2(uint x)
+		{
+			return RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10);
+		}
+
+		private uint G1(uint x, uint y, uint z)
+		{
+			return (RotateRight(x, 10) ^ RotateRight(z, 23)) + RotateRight(y, 8);
+		}
+
+		private uint G2(uint x, uint y, uint z)
+		{
+			return (RotateLeft(x, 10) ^ RotateLeft(z, 23)) + RotateLeft(y, 8);
+		}
+
+		private static uint RotateLeft(uint	x, int bits)
+		{
+			return (x << bits) | (x >> -bits);
+		}
+
+		private static uint RotateRight(uint x, int bits)
+		{
+			return (x >> bits) | (x << -bits);
+		}
+
+		private uint H1(uint x)
+		{
+			return q[x & 0xFF] + q[((x >> 16) & 0xFF) + 256];
+		}
+
+		private uint H2(uint x)
+		{
+			return p[x & 0xFF] + p[((x >> 16) & 0xFF) + 256];
+		}
+
+		private static uint Mod1024(uint x)
+		{
+			return x & 0x3FF;
+		}
+
+		private static uint Mod512(uint x)
+		{
+			return x & 0x1FF;
+		}
+
+		private static uint Dim(uint x, uint y)
+		{
+			return Mod512(x - y);
+		}
+
+		private uint Step()
+		{
+			uint j = Mod512(cnt);
+			uint ret;
+			if (cnt < 512)
+			{
+				p[j] += G1(p[Dim(j, 3)], p[Dim(j, 10)], p[Dim(j, 511)]);
+				ret = H1(p[Dim(j, 12)]) ^ p[j];
+			}
+			else
+			{
+				q[j] += G2(q[Dim(j, 3)], q[Dim(j, 10)], q[Dim(j, 511)]);
+				ret = H2(q[Dim(j, 12)]) ^ q[j];
+			}
+			cnt = Mod1024(cnt + 1);
+			return ret;
+		}
+
+		private byte[] key, iv;
+		private bool initialised;
+
+		private void Init()
+		{
+			if (key.Length != 16)
+				throw new ArgumentException("The key must be 128 bits long");
+
+			cnt = 0;
+
+			uint[] w = new uint[1280];
+
+			for (int i = 0; i < 16; i++)
+			{
+				w[i >> 2] |= ((uint)key[i] << (8 * (i & 0x3)));
+			}
+			Array.Copy(w, 0, w, 4, 4);
+
+			for (int i = 0; i < iv.Length && i < 16; i++)
+			{
+				w[(i >> 2) + 8] |= ((uint)iv[i] << (8 * (i & 0x3)));
+			}
+			Array.Copy(w, 8, w, 12, 4);
+
+			for (uint i = 16; i < 1280; i++)
+			{
+				w[i] = F2(w[i - 2]) + w[i - 7] + F1(w[i - 15]) + w[i - 16] + i;
+			}
+
+			Array.Copy(w, 256, p, 0, 512);
+			Array.Copy(w, 768, q, 0, 512);
+
+			for (int i = 0; i < 512; i++)
+			{
+				p[i] = Step();
+			}
+			for (int i = 0; i < 512; i++)
+			{
+				q[i] = Step();
+			}
+
+			cnt = 0;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "HC-128"; }
+		}
+
+		/**
+		* Initialise a HC-128 cipher.
+		*
+		* @param forEncryption whether or not we are for encryption. Irrelevant, as
+		*                      encryption and decryption are the same.
+		* @param params        the parameters required to set up the cipher.
+		* @throws ArgumentException if the params argument is
+		*                                  inappropriate (ie. the key is not 128 bit long).
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			ICipherParameters keyParam = parameters;
+
+			if (parameters is ParametersWithIV)
+			{
+				iv = ((ParametersWithIV)parameters).GetIV();
+				keyParam = ((ParametersWithIV)parameters).Parameters;
+			}
+			else
+			{
+				iv = new byte[0];
+			}
+
+			if (keyParam is KeyParameter)
+			{
+				key = ((KeyParameter)keyParam).GetKey();
+				Init();
+			}
+			else
+			{
+				throw new ArgumentException(
+					"Invalid parameter passed to HC128 init - " + parameters.GetType().Name,
+					"parameters");
+			}
+
+			initialised = true;
+		}
+
+		private byte[] buf = new byte[4];
+		private int idx = 0;
+
+		private byte GetByte()
+		{
+			if (idx == 0)
+			{
+				Pack.UInt32_To_LE(Step(), buf);				
+			}
+			byte ret = buf[idx];
+			idx = idx + 1 & 0x3;
+			return ret;
+		}
+
+		public void ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		len,
+			byte[]	output,
+			int		outOff)
+		{
+			if (!initialised)
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+			if ((inOff + len) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + len) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			for (int i = 0; i < len; i++)
+			{
+				output[outOff + i] = (byte)(input[inOff + i] ^ GetByte());
+			}
+		}
+
+		public void Reset()
+		{
+			idx = 0;
+			Init();
+		}
+
+		public byte ReturnByte(byte input)
+		{
+			return (byte)(input ^ GetByte());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/HC256Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/HC256Engine.cs
new file mode 100644
index 0000000..da717da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/HC256Engine.cs
@@ -0,0 +1,224 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* HC-256 is a software-efficient stream cipher created by Hongjun Wu. It 
+	* generates keystream from a 256-bit secret key and a 256-bit initialization 
+	* vector.
+	* <p>
+	* http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+	* </p><p>
+	* Its brother, HC-128, is a third phase candidate in the eStream contest.
+	* The algorithm is patent-free. No attacks are known as of today (April 2007). 
+	* See
+	* 
+	* http://www.ecrypt.eu.org/stream/hcp3.html
+	* </p>
+	*/
+	public class HC256Engine
+		: IStreamCipher
+	{
+		private uint[] p = new uint[1024];
+		private uint[] q = new uint[1024];
+		private uint cnt = 0;
+
+		private uint Step()
+		{
+			uint j = cnt & 0x3FF;
+			uint ret;
+			if (cnt < 1024)
+			{
+				uint x = p[(j - 3 & 0x3FF)];
+				uint y = p[(j - 1023 & 0x3FF)];
+				p[j] += p[(j - 10 & 0x3FF)]
+					+ (RotateRight(x, 10) ^ RotateRight(y, 23))
+					+ q[((x ^ y) & 0x3FF)];
+
+				x = p[(j - 12 & 0x3FF)];
+				ret = (q[x & 0xFF] + q[((x >> 8) & 0xFF) + 256]
+					+ q[((x >> 16) & 0xFF) + 512] + q[((x >> 24) & 0xFF) + 768])
+					^ p[j];
+			}
+			else
+			{
+				uint x = q[(j - 3 & 0x3FF)];
+				uint y = q[(j - 1023 & 0x3FF)];
+				q[j] += q[(j - 10 & 0x3FF)]
+					+ (RotateRight(x, 10) ^ RotateRight(y, 23))
+					+ p[((x ^ y) & 0x3FF)];
+
+				x = q[(j - 12 & 0x3FF)];
+				ret = (p[x & 0xFF] + p[((x >> 8) & 0xFF) + 256]
+					+ p[((x >> 16) & 0xFF) + 512] + p[((x >> 24) & 0xFF) + 768])
+					^ q[j];
+			}
+			cnt = cnt + 1 & 0x7FF;
+			return ret;
+		}
+
+		private byte[] key, iv;
+		private bool initialised;
+
+		private void Init()
+		{
+			if (key.Length != 32 && key.Length != 16)
+				throw new ArgumentException("The key must be 128/256 bits long");
+
+			if (iv.Length < 16)
+				throw new ArgumentException("The IV must be at least 128 bits long");
+
+			if (key.Length != 32)
+	        {
+				byte[] k = new byte[32];
+
+				Array.Copy(key, 0, k, 0, key.Length);
+				Array.Copy(key, 0, k, 16, key.Length);
+
+				key = k;
+			}
+
+			if (iv.Length < 32)
+			{
+				byte[] newIV = new byte[32];
+
+				Array.Copy(iv, 0, newIV, 0, iv.Length);
+				Array.Copy(iv, 0, newIV, iv.Length, newIV.Length - iv.Length);
+
+				iv = newIV;
+			}
+
+			cnt = 0;
+
+			uint[] w = new uint[2560];
+
+			for (int i = 0; i < 32; i++)
+			{
+				w[i >> 2] |= ((uint)key[i] << (8 * (i & 0x3)));
+			}
+
+			for (int i = 0; i < 32; i++)
+			{
+				w[(i >> 2) + 8] |= ((uint)iv[i] << (8 * (i & 0x3)));
+			}
+
+			for (uint i = 16; i < 2560; i++)
+			{
+				uint x = w[i - 2];
+				uint y = w[i - 15];
+				w[i] = (RotateRight(x, 17) ^ RotateRight(x, 19) ^ (x >> 10))
+					+ w[i - 7]
+					+ (RotateRight(y, 7) ^ RotateRight(y, 18) ^ (y >> 3))
+					+ w[i - 16] + i;
+			}
+
+			Array.Copy(w, 512, p, 0, 1024);
+			Array.Copy(w, 1536, q, 0, 1024);
+
+			for (int i = 0; i < 4096; i++)
+			{
+				Step();
+			}
+
+			cnt = 0;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "HC-256"; }
+		}
+
+		/**
+		* Initialise a HC-256 cipher.
+		*
+		* @param forEncryption whether or not we are for encryption. Irrelevant, as
+		*                      encryption and decryption are the same.
+		* @param params        the parameters required to set up the cipher.
+		* @throws ArgumentException if the params argument is
+		*                                  inappropriate (ie. the key is not 256 bit long).
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			ICipherParameters keyParam = parameters;
+
+			if (parameters is ParametersWithIV)
+			{
+				iv = ((ParametersWithIV)parameters).GetIV();
+				keyParam = ((ParametersWithIV)parameters).Parameters;
+			}
+			else
+			{
+				iv = new byte[0];
+			}
+
+			if (keyParam is KeyParameter)
+			{
+				key = ((KeyParameter)keyParam).GetKey();
+				Init();
+			}
+			else
+			{
+				throw new ArgumentException(
+					"Invalid parameter passed to HC256 init - " + parameters.GetType().Name,
+					"parameters");
+			}
+
+			initialised = true;
+		}
+
+		private byte[] buf = new byte[4];
+		private int idx = 0;
+
+		private byte GetByte()
+		{
+			if (idx == 0)
+			{
+				Pack.UInt32_To_LE(Step(), buf);
+			}
+			byte ret = buf[idx];
+			idx = idx + 1 & 0x3;
+			return ret;
+		}
+
+		public void ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		len,
+			byte[]	output,
+			int		outOff)
+		{
+			if (!initialised)
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+			if ((inOff + len) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + len) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			for (int i = 0; i < len; i++)
+			{
+				output[outOff + i] = (byte)(input[inOff + i] ^ GetByte());
+			}
+		}
+
+		public void Reset()
+		{
+			idx = 0;
+			Init();
+		}
+
+		public byte ReturnByte(byte input)
+		{
+			return (byte)(input ^ GetByte());
+		}
+
+		private static uint RotateRight(uint x, int bits)
+		{
+			return (x >> bits) | (x << -bits);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/ISAACEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/ISAACEngine.cs
new file mode 100644
index 0000000..9c58678
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/ISAACEngine.cs
@@ -0,0 +1,212 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * Implementation of Bob Jenkin's ISAAC (Indirection Shift Accumulate Add and Count).
+    * see: http://www.burtleburtle.net/bob/rand/isaacafa.html
+    */
+    public class IsaacEngine
+        : IStreamCipher
+    {
+        // Constants
+        private static readonly int sizeL          = 8,
+                                    stateArraySize = sizeL<<5; // 256
+
+        // Cipher's internal state
+        private uint[]   engineState   = null, // mm                
+                        results       = null; // randrsl
+        private uint     a = 0, b = 0, c = 0;
+
+        // Engine state
+        private int     index         = 0;
+        private byte[]  keyStream     = new byte[stateArraySize<<2], // results expanded into bytes
+                        workingKey    = null;
+        private bool	initialised   = false;
+
+        /**
+        * initialise an ISAAC cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param params the parameters required to set up the cipher.
+        * @exception ArgumentException if the params argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption, 
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+                throw new ArgumentException(
+                    "invalid parameter passed to ISAAC Init - " + parameters.GetType().Name,
+                    "parameters");
+
+            /* 
+            * ISAAC encryption and decryption is completely
+            * symmetrical, so the 'forEncryption' is 
+            * irrelevant.
+            */
+            KeyParameter p = (KeyParameter) parameters;
+            setKey(p.GetKey());
+        }
+
+        public byte ReturnByte(
+            byte input)
+        {
+            if (index == 0) 
+            {
+                isaac();
+                keyStream = Pack.UInt32_To_BE(results);
+            }
+
+            byte output = (byte)(keyStream[index]^input);
+            index = (index + 1) & 1023;
+
+            return output;
+        }
+
+        public void ProcessBytes(
+            byte[]	input, 
+            int		inOff, 
+            int		len, 
+            byte[]	output, 
+            int		outOff)
+        {
+            if (!initialised)
+                throw new InvalidOperationException(AlgorithmName + " not initialised");
+            if ((inOff + len) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + len) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+            for (int i = 0; i < len; i++)
+            {
+                if (index == 0) 
+                {
+                    isaac();
+                    keyStream = Pack.UInt32_To_BE(results);
+                }
+                output[i+outOff] = (byte)(keyStream[index]^input[i+inOff]);
+                index = (index + 1) & 1023;
+            }
+        }
+
+        public string AlgorithmName
+        {
+            get { return "ISAAC"; }
+        }
+
+        public void Reset()
+        {
+            setKey(workingKey);
+        }
+
+        // Private implementation
+        private void setKey(
+            byte[] keyBytes)
+        {
+            workingKey = keyBytes;
+
+            if (engineState == null)
+            {
+                engineState = new uint[stateArraySize];
+            }
+
+            if (results == null)
+            {
+                results = new uint[stateArraySize];
+            }
+
+            int i, j, k;
+
+            // Reset state
+            for (i = 0; i < stateArraySize; i++)
+            {
+                engineState[i] = results[i] = 0;
+            }
+            a = b = c = 0;
+
+            // Reset index counter for output
+            index = 0;
+
+            // Convert the key bytes to ints and put them into results[] for initialization
+            byte[] t = new byte[keyBytes.Length + (keyBytes.Length & 3)];
+            Array.Copy(keyBytes, 0, t, 0, keyBytes.Length);
+            for (i = 0; i < t.Length; i+=4)
+            {
+                results[i >> 2] = Pack.LE_To_UInt32(t, i);
+            }
+
+            // It has begun?
+            uint[] abcdefgh = new uint[sizeL];
+
+            for (i = 0; i < sizeL; i++)
+            {
+                abcdefgh[i] = 0x9e3779b9; // Phi (golden ratio)
+            }
+
+            for (i = 0; i < 4; i++)
+            {
+                mix(abcdefgh);
+            }
+
+            for (i = 0; i < 2; i++)
+            {
+                for (j = 0; j < stateArraySize; j+=sizeL)
+                {
+                    for (k = 0; k < sizeL; k++)
+                    {
+                        abcdefgh[k] += (i<1) ? results[j+k] : engineState[j+k];
+                    }
+
+                    mix(abcdefgh);
+
+                    for (k = 0; k < sizeL; k++)
+                    {
+                        engineState[j+k] = abcdefgh[k];
+                    }
+                }
+            }
+
+            isaac();
+
+            initialised = true;
+        }    
+
+        private void isaac()
+        {
+            uint x, y;
+
+            b += ++c;
+            for (int i = 0; i < stateArraySize; i++)
+            {
+                x = engineState[i];
+                switch (i & 3)
+                {
+                    case 0: a ^= (a << 13); break;
+                    case 1: a ^= (a >>  6); break;
+                    case 2: a ^= (a <<  2); break;
+                    case 3: a ^= (a >> 16); break;
+                }
+                a += engineState[(i+128) & 0xFF];
+                engineState[i] = y = engineState[(int)((uint)x >> 2) & 0xFF] + a + b;
+                results[i] = b = engineState[(int)((uint)y >> 10) & 0xFF] + x;
+            }
+        }
+
+        private void mix(uint[] x)
+        {
+            x[0]^=x[1]<< 11; x[3]+=x[0]; x[1]+=x[2];
+            x[1]^=x[2]>>  2; x[4]+=x[1]; x[2]+=x[3];
+            x[2]^=x[3]<<  8; x[5]+=x[2]; x[3]+=x[4];
+            x[3]^=x[4]>> 16; x[6]+=x[3]; x[4]+=x[5];
+            x[4]^=x[5]<< 10; x[7]+=x[4]; x[5]+=x[6];
+            x[5]^=x[6]>>  4; x[0]+=x[5]; x[6]+=x[7];
+            x[6]^=x[7]<<  8; x[1]+=x[6]; x[7]+=x[0];
+            x[7]^=x[0]>>  9; x[2]+=x[7]; x[0]+=x[1];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/IdeaEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/IdeaEngine.cs
new file mode 100644
index 0000000..46b5a78
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/IdeaEngine.cs
@@ -0,0 +1,337 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * A class that provides a basic International Data Encryption Algorithm (IDEA) engine.
+    * <p>
+    * This implementation is based on the "HOWTO: INTERNATIONAL DATA ENCRYPTION ALGORITHM"
+    * implementation summary by Fauzan Mirza (F.U.Mirza at sheffield.ac.uk). (baring 1 typo at the
+    * end of the mulinv function!).
+    * </p>
+    * <p>
+    * It can be found at ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/idea/
+    * </p>
+    * <p>
+    * Note 1: This algorithm is patented in the USA, Japan, and Europe including
+    * at least Austria, France, Germany, Italy, Netherlands, Spain, Sweden, Switzerland
+    * and the United Kingdom. Non-commercial use is free, however any commercial
+    * products are liable for royalties. Please see
+    * <a href="http://www.mediacrypt.com">www.mediacrypt.com</a> for
+    * further details. This announcement has been included at the request of
+    * the patent holders.
+    * </p>
+    * <p>
+    * Note 2: Due to the requests concerning the above, this algorithm is now only
+    * included in the extended assembly. It is not included in the default distributions.
+    * </p>
+    */
+    public class IdeaEngine
+        : IBlockCipher
+    {
+        private const int  BLOCK_SIZE = 8;
+        private int[] workingKey;
+        /**
+        * standard constructor.
+        */
+        public IdeaEngine()
+        {
+        }
+        /**
+        * initialise an IDEA cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+                throw new ArgumentException("invalid parameter passed to IDEA init - " + parameters.GetType().ToString());
+
+            workingKey = GenerateWorkingKey(forEncryption,
+                ((KeyParameter)parameters).GetKey());
+        }
+
+        public string AlgorithmName
+        {
+            get { return "IDEA"; }
+        }
+
+        public bool IsPartialBlockOkay
+        {
+            get { return false; }
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public int ProcessBlock(
+            byte[] input,
+            int inOff,
+            byte[] output,
+            int outOff)
+        {
+            if (workingKey == null)
+            {
+                throw new InvalidOperationException("IDEA engine not initialised");
+            }
+            if ((inOff + BLOCK_SIZE) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+            if ((outOff + BLOCK_SIZE) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+            IdeaFunc(workingKey, input, inOff, output, outOff);
+            return BLOCK_SIZE;
+        }
+        public void Reset()
+        {
+        }
+        private static readonly int    MASK = 0xffff;
+        private static readonly int    BASE = 0x10001;
+        private int BytesToWord(
+            byte[]  input,
+            int     inOff)
+        {
+            return ((input[inOff] << 8) & 0xff00) + (input[inOff + 1] & 0xff);
+        }
+        private void WordToBytes(
+            int     word,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            outBytes[outOff] = (byte)((uint) word >> 8);
+            outBytes[outOff + 1] = (byte)word;
+        }
+        /**
+        * return x = x * y where the multiplication is done modulo
+        * 65537 (0x10001) (as defined in the IDEA specification) and
+        * a zero input is taken to be 65536 (0x10000).
+        *
+        * @param x the x value
+        * @param y the y value
+        * @return x = x * y
+        */
+        private int Mul(
+            int x,
+            int y)
+        {
+            if (x == 0)
+            {
+                x = (BASE - y);
+            }
+            else if (y == 0)
+            {
+                x = (BASE - x);
+            }
+            else
+            {
+                int     p = x * y;
+                y = p & MASK;
+                x = (int) ((uint) p >> 16);
+                x = y - x + ((y < x) ? 1 : 0);
+            }
+            return x & MASK;
+        }
+        private void IdeaFunc(
+            int[]   workingKey,
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int     x0, x1, x2, x3, t0, t1;
+            int     keyOff = 0;
+            x0 = BytesToWord(input, inOff);
+            x1 = BytesToWord(input, inOff + 2);
+            x2 = BytesToWord(input, inOff + 4);
+            x3 = BytesToWord(input, inOff + 6);
+            for (int round = 0; round < 8; round++)
+            {
+                x0 = Mul(x0, workingKey[keyOff++]);
+                x1 += workingKey[keyOff++];
+                x1 &= MASK;
+                x2 += workingKey[keyOff++];
+                x2 &= MASK;
+                x3 = Mul(x3, workingKey[keyOff++]);
+                t0 = x1;
+                t1 = x2;
+                x2 ^= x0;
+                x1 ^= x3;
+                x2 = Mul(x2, workingKey[keyOff++]);
+                x1 += x2;
+                x1 &= MASK;
+                x1 = Mul(x1, workingKey[keyOff++]);
+                x2 += x1;
+                x2 &= MASK;
+                x0 ^= x1;
+                x3 ^= x2;
+                x1 ^= t1;
+                x2 ^= t0;
+            }
+            WordToBytes(Mul(x0, workingKey[keyOff++]), outBytes, outOff);
+            WordToBytes(x2 + workingKey[keyOff++], outBytes, outOff + 2);  /* NB: Order */
+            WordToBytes(x1 + workingKey[keyOff++], outBytes, outOff + 4);
+            WordToBytes(Mul(x3, workingKey[keyOff]), outBytes, outOff + 6);
+        }
+        /**
+        * The following function is used to expand the user key to the encryption
+        * subkey. The first 16 bytes are the user key, and the rest of the subkey
+        * is calculated by rotating the previous 16 bytes by 25 bits to the left,
+        * and so on until the subkey is completed.
+        */
+        private int[] ExpandKey(
+            byte[]  uKey)
+        {
+            int[]   key = new int[52];
+            if (uKey.Length < 16)
+            {
+                byte[]  tmp = new byte[16];
+                Array.Copy(uKey, 0, tmp, tmp.Length - uKey.Length, uKey.Length);
+                uKey = tmp;
+            }
+            for (int i = 0; i < 8; i++)
+            {
+                key[i] = BytesToWord(uKey, i * 2);
+            }
+            for (int i = 8; i < 52; i++)
+            {
+                if ((i & 7) < 6)
+                {
+                    key[i] = ((key[i - 7] & 127) << 9 | key[i - 6] >> 7) & MASK;
+                }
+                else if ((i & 7) == 6)
+                {
+                    key[i] = ((key[i - 7] & 127) << 9 | key[i - 14] >> 7) & MASK;
+                }
+                else
+                {
+                    key[i] = ((key[i - 15] & 127) << 9 | key[i - 14] >> 7) & MASK;
+                }
+            }
+            return key;
+        }
+        /**
+        * This function computes multiplicative inverse using Euclid's Greatest
+        * Common Divisor algorithm. Zero and one are self inverse.
+        * <p>
+        * i.e. x * MulInv(x) == 1 (modulo BASE)
+        * </p>
+        */
+        private int MulInv(
+            int x)
+        {
+            int t0, t1, q, y;
+
+            if (x < 2)
+            {
+                return x;
+            }
+            t0 = 1;
+            t1 = BASE / x;
+            y  = BASE % x;
+            while (y != 1)
+            {
+                q = x / y;
+                x = x % y;
+                t0 = (t0 + (t1 * q)) & MASK;
+                if (x == 1)
+                {
+                    return t0;
+                }
+                q = y / x;
+                y = y % x;
+                t1 = (t1 + (t0 * q)) & MASK;
+            }
+            return (1 - t1) & MASK;
+        }
+        /**
+        * Return the additive inverse of x.
+        * <p>
+        * i.e. x + AddInv(x) == 0
+        * </p>
+        */
+        int AddInv(
+            int x)
+        {
+            return (0 - x) & MASK;
+        }
+
+        /**
+        * The function to invert the encryption subkey to the decryption subkey.
+        * It also involves the multiplicative inverse and the additive inverse functions.
+        */
+        private int[] InvertKey(
+            int[] inKey)
+        {
+            int     t1, t2, t3, t4;
+            int     p = 52;                 /* We work backwards */
+            int[]   key = new int[52];
+            int     inOff = 0;
+
+            t1 = MulInv(inKey[inOff++]);
+            t2 = AddInv(inKey[inOff++]);
+            t3 = AddInv(inKey[inOff++]);
+            t4 = MulInv(inKey[inOff++]);
+            key[--p] = t4;
+            key[--p] = t3;
+            key[--p] = t2;
+            key[--p] = t1;
+
+            for (int round = 1; round < 8; round++)
+            {
+                t1 = inKey[inOff++];
+                t2 = inKey[inOff++];
+                key[--p] = t2;
+                key[--p] = t1;
+
+                t1 = MulInv(inKey[inOff++]);
+                t2 = AddInv(inKey[inOff++]);
+                t3 = AddInv(inKey[inOff++]);
+                t4 = MulInv(inKey[inOff++]);
+                key[--p] = t4;
+                key[--p] = t2; /* NB: Order */
+                key[--p] = t3;
+                key[--p] = t1;
+            }
+            t1 = inKey[inOff++];
+            t2 = inKey[inOff++];
+            key[--p] = t2;
+            key[--p] = t1;
+
+            t1 = MulInv(inKey[inOff++]);
+            t2 = AddInv(inKey[inOff++]);
+            t3 = AddInv(inKey[inOff++]);
+            t4 = MulInv(inKey[inOff]);
+            key[--p] = t4;
+            key[--p] = t3;
+            key[--p] = t2;
+            key[--p] = t1;
+            return key;
+        }
+
+        private int[] GenerateWorkingKey(
+            bool forEncryption,
+            byte[]  userKey)
+        {
+            if (forEncryption)
+            {
+                return ExpandKey(userKey);
+            }
+            else
+            {
+                return InvertKey(ExpandKey(userKey));
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/IesEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/IesEngine.cs
new file mode 100644
index 0000000..70df307
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/IesEngine.cs
@@ -0,0 +1,233 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * support class for constructing intergrated encryption ciphers
+    * for doing basic message exchanges on top of key agreement ciphers
+    */
+    public class IesEngine
+    {
+        private readonly IBasicAgreement     agree;
+        private readonly IDerivationFunction kdf;
+        private readonly IMac                mac;
+        private readonly BufferedBlockCipher cipher;
+        private readonly byte[]              macBuf;
+
+        private bool				forEncryption;
+        private ICipherParameters	privParam, pubParam;
+        private IesParameters		param;
+
+        /**
+        * set up for use with stream mode, where the key derivation function
+        * is used to provide a stream of bytes to xor with the message.
+        *
+        * @param agree the key agreement used as the basis for the encryption
+        * @param kdf the key derivation function used for byte generation
+        * @param mac the message authentication code generator for the message
+        */
+        public IesEngine(
+            IBasicAgreement     agree,
+            IDerivationFunction kdf,
+            IMac                mac)
+        {
+            this.agree = agree;
+            this.kdf = kdf;
+            this.mac = mac;
+            this.macBuf = new byte[mac.GetMacSize()];
+//            this.cipher = null;
+        }
+
+        /**
+        * set up for use in conjunction with a block cipher to handle the
+        * message.
+        *
+        * @param agree the key agreement used as the basis for the encryption
+        * @param kdf the key derivation function used for byte generation
+        * @param mac the message authentication code generator for the message
+        * @param cipher the cipher to used for encrypting the message
+        */
+        public IesEngine(
+            IBasicAgreement     agree,
+            IDerivationFunction kdf,
+            IMac                mac,
+            BufferedBlockCipher cipher)
+        {
+            this.agree = agree;
+            this.kdf = kdf;
+            this.mac = mac;
+            this.macBuf = new byte[mac.GetMacSize()];
+            this.cipher = cipher;
+        }
+
+        /**
+        * Initialise the encryptor.
+        *
+        * @param forEncryption whether or not this is encryption/decryption.
+        * @param privParam our private key parameters
+        * @param pubParam the recipient's/sender's public key parameters
+        * @param param encoding and derivation parameters.
+        */
+        public void Init(
+            bool                     forEncryption,
+            ICipherParameters            privParameters,
+            ICipherParameters            pubParameters,
+            ICipherParameters            iesParameters)
+        {
+            this.forEncryption = forEncryption;
+            this.privParam = privParameters;
+            this.pubParam = pubParameters;
+            this.param = (IesParameters)iesParameters;
+        }
+
+        private byte[] DecryptBlock(
+            byte[]  in_enc,
+            int     inOff,
+            int     inLen,
+            byte[]  z)
+        {
+            byte[]          M = null;
+            KeyParameter    macKey = null;
+            KdfParameters   kParam = new KdfParameters(z, param.GetDerivationV());
+            int             macKeySize = param.MacKeySize;
+
+            kdf.Init(kParam);
+
+            inLen -= mac.GetMacSize();
+
+            if (cipher == null)     // stream mode
+            {
+                byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
+
+                M = new byte[inLen];
+
+                for (int i = 0; i != inLen; i++)
+                {
+                    M[i] = (byte)(in_enc[inOff + i] ^ Buffer[i]);
+                }
+
+                macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
+            }
+            else
+            {
+                int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
+                byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
+
+                cipher.Init(false, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
+
+                M = cipher.DoFinal(in_enc, inOff, inLen);
+
+                macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
+            }
+
+            byte[] macIV = param.GetEncodingV();
+
+            mac.Init(macKey);
+            mac.BlockUpdate(in_enc, inOff, inLen);
+            mac.BlockUpdate(macIV, 0, macIV.Length);
+            mac.DoFinal(macBuf, 0);
+
+            inOff += inLen;
+
+            byte[] T1 = Arrays.CopyOfRange(in_enc, inOff, inOff + macBuf.Length);
+
+            if (!Arrays.ConstantTimeAreEqual(T1, macBuf))
+                throw (new InvalidCipherTextException("Invalid MAC."));
+
+            return M;
+        }
+
+        private byte[] EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            int     inLen,
+            byte[]  z)
+        {
+            byte[]          C = null;
+            KeyParameter    macKey = null;
+            KdfParameters   kParam = new KdfParameters(z, param.GetDerivationV());
+            int             c_text_length = 0;
+            int             macKeySize = param.MacKeySize;
+
+            if (cipher == null)     // stream mode
+            {
+                byte[] Buffer = GenerateKdfBytes(kParam, inLen + (macKeySize / 8));
+
+                C = new byte[inLen + mac.GetMacSize()];
+                c_text_length = inLen;
+
+                for (int i = 0; i != inLen; i++)
+                {
+                    C[i] = (byte)(input[inOff + i] ^ Buffer[i]);
+                }
+
+                macKey = new KeyParameter(Buffer, inLen, (macKeySize / 8));
+            }
+            else
+            {
+                int cipherKeySize = ((IesWithCipherParameters)param).CipherKeySize;
+                byte[] Buffer = GenerateKdfBytes(kParam, (cipherKeySize / 8) + (macKeySize / 8));
+
+                cipher.Init(true, new KeyParameter(Buffer, 0, (cipherKeySize / 8)));
+
+                c_text_length = cipher.GetOutputSize(inLen);
+                byte[] tmp = new byte[c_text_length];
+
+                int len = cipher.ProcessBytes(input, inOff, inLen, tmp, 0);
+                len += cipher.DoFinal(tmp, len);
+
+                C = new byte[len + mac.GetMacSize()];
+                c_text_length = len;
+
+                Array.Copy(tmp, 0, C, 0, len);
+
+                macKey = new KeyParameter(Buffer, (cipherKeySize / 8), (macKeySize / 8));
+            }
+
+            byte[] macIV = param.GetEncodingV();
+
+            mac.Init(macKey);
+            mac.BlockUpdate(C, 0, c_text_length);
+            mac.BlockUpdate(macIV, 0, macIV.Length);
+            //
+            // return the message and it's MAC
+            //
+            mac.DoFinal(C, c_text_length);
+            return C;
+        }
+
+        private byte[] GenerateKdfBytes(
+            KdfParameters	kParam,
+            int				length)
+        {
+            byte[] buf = new byte[length];
+
+            kdf.Init(kParam);
+
+            kdf.GenerateBytes(buf, 0, buf.Length);
+
+            return buf;
+        }
+
+        public byte[] ProcessBlock(
+            byte[]  input,
+            int     inOff,
+            int     inLen)
+        {
+            agree.Init(privParam);
+
+            BigInteger z = agree.CalculateAgreement(pubParam);
+
+            byte[] zBytes = BigIntegers.AsUnsignedByteArray(agree.GetFieldSize(), z);
+
+            return forEncryption
+                ?	EncryptBlock(input, inOff, inLen, zBytes)
+                :	DecryptBlock(input, inOff, inLen, zBytes);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/NaccacheSternEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/NaccacheSternEngine.cs
new file mode 100644
index 0000000..486c880
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/NaccacheSternEngine.cs
@@ -0,0 +1,433 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* NaccacheStern Engine. For details on this cipher, please see
+	* http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	*/
+	public class NaccacheSternEngine
+		: IAsymmetricBlockCipher
+	{
+		private bool forEncryption;
+
+		private NaccacheSternKeyParameters key;
+
+		private IList[] lookup = null;
+
+		private bool debug = false;
+
+		public string AlgorithmName
+		{
+			get { return "NaccacheStern"; }
+		}
+
+		/**
+		* Initializes this algorithm. Must be called before all other Functions.
+		*
+		* @see org.bouncycastle.crypto.AsymmetricBlockCipher#init(bool,
+		*      org.bouncycastle.crypto.CipherParameters)
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+
+			if (parameters is ParametersWithRandom)
+			{
+				parameters = ((ParametersWithRandom) parameters).Parameters;
+			}
+
+			key = (NaccacheSternKeyParameters)parameters;
+
+			// construct lookup table for faster decryption if necessary
+			if (!this.forEncryption)
+			{
+				if (debug)
+				{
+
+                    System.Diagnostics.Debug.WriteLine("Constructing lookup Array");
+				}
+				NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+				IList primes = priv.SmallPrimesList;
+				lookup = new IList[primes.Count];
+				for (int i = 0; i < primes.Count; i++)
+				{
+					BigInteger actualPrime = (BigInteger) primes[i];
+					int actualPrimeValue = actualPrime.IntValue;
+
+					lookup[i] = Platform.CreateArrayList(actualPrimeValue);
+					lookup[i].Add(BigInteger.One);
+
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("Constructing lookup ArrayList for " + actualPrimeValue);
+					}
+
+					BigInteger accJ = BigInteger.Zero;
+
+					for (int j = 1; j < actualPrimeValue; j++)
+					{
+//						BigInteger bigJ = BigInteger.ValueOf(j);
+//						accJ = priv.PhiN.Multiply(bigJ);
+						accJ = accJ.Add(priv.PhiN);
+						BigInteger comp = accJ.Divide(actualPrime);
+						lookup[i].Add(priv.G.ModPow(comp, priv.Modulus));
+					}
+				}
+			}
+		}
+
+		public bool Debug
+		{
+			set { this.debug = value; }
+		}
+
+		/**
+		* Returns the input block size of this algorithm.
+		*
+		* @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetInputBlockSize()
+		*/
+		public int GetInputBlockSize()
+		{
+			if (forEncryption)
+			{
+				// We can only encrypt values up to lowerSigmaBound
+				return (key.LowerSigmaBound + 7) / 8 - 1;
+			}
+			else
+			{
+				// We pad to modulus-size bytes for easier decryption.
+//				return key.Modulus.ToByteArray().Length;
+				return key.Modulus.BitLength / 8 + 1;
+			}
+		}
+
+		/**
+		* Returns the output block size of this algorithm.
+		*
+		* @see org.bouncycastle.crypto.AsymmetricBlockCipher#GetOutputBlockSize()
+		*/
+		public int GetOutputBlockSize()
+		{
+			if (forEncryption)
+			{
+				// encrypted Data is always padded up to modulus size
+//				return key.Modulus.ToByteArray().Length;
+				return key.Modulus.BitLength / 8 + 1;
+			}
+			else
+			{
+				// decrypted Data has upper limit lowerSigmaBound
+				return (key.LowerSigmaBound + 7) / 8 - 1;
+			}
+		}
+
+		/**
+		* Process a single Block using the Naccache-Stern algorithm.
+		*
+		* @see org.bouncycastle.crypto.AsymmetricBlockCipher#ProcessBlock(byte[],
+		*      int, int)
+		*/
+		public byte[] ProcessBlock(
+			byte[]	inBytes,
+			int		inOff,
+			int		length)
+		{
+			if (key == null)
+				throw new InvalidOperationException("NaccacheStern engine not initialised");
+			if (length > (GetInputBlockSize() + 1))
+				throw new DataLengthException("input too large for Naccache-Stern cipher.\n");
+
+			if (!forEncryption)
+			{
+				// At decryption make sure that we receive padded data blocks
+				if (length < GetInputBlockSize())
+				{
+					throw new InvalidCipherTextException("BlockLength does not match modulus for Naccache-Stern cipher.\n");
+				}
+			}
+
+			// transform input into BigInteger
+			BigInteger input = new BigInteger(1, inBytes, inOff, length);
+
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("input as BigInteger: " + input);
+			}
+
+			byte[] output;
+			if (forEncryption)
+			{
+				output = Encrypt(input);
+			}
+			else
+			{
+				IList plain = Platform.CreateArrayList();
+				NaccacheSternPrivateKeyParameters priv = (NaccacheSternPrivateKeyParameters)key;
+				IList primes = priv.SmallPrimesList;
+				// Get Chinese Remainders of CipherText
+				for (int i = 0; i < primes.Count; i++)
+				{
+					BigInteger exp = input.ModPow(priv.PhiN.Divide((BigInteger)primes[i]), priv.Modulus);
+					IList al = lookup[i];
+					if (lookup[i].Count != ((BigInteger)primes[i]).IntValue)
+					{
+						if (debug)
+						{
+                            System.Diagnostics.Debug.WriteLine("Prime is " + primes[i] + ", lookup table has size " + al.Count);
+						}
+						throw new InvalidCipherTextException("Error in lookup Array for "
+										+ ((BigInteger)primes[i]).IntValue
+										+ ": Size mismatch. Expected ArrayList with length "
+										+ ((BigInteger)primes[i]).IntValue + " but found ArrayList of length "
+										+ lookup[i].Count);
+					}
+					int lookedup = al.IndexOf(exp);
+
+					if (lookedup == -1)
+					{
+						if (debug)
+						{
+                            System.Diagnostics.Debug.WriteLine("Actual prime is " + primes[i]);
+                            System.Diagnostics.Debug.WriteLine("Decrypted value is " + exp);
+
+                            System.Diagnostics.Debug.WriteLine("LookupList for " + primes[i] + " with size " + lookup[i].Count
+											+ " is: ");
+							for (int j = 0; j < lookup[i].Count; j++)
+							{
+                                System.Diagnostics.Debug.WriteLine(lookup[i][j]);
+							}
+						}
+						throw new InvalidCipherTextException("Lookup failed");
+					}
+					plain.Add(BigInteger.ValueOf(lookedup));
+				}
+				BigInteger test = chineseRemainder(plain, primes);
+
+				// Should not be used as an oracle, so reencrypt output to see
+				// if it corresponds to input
+
+				// this breaks probabilisic encryption, so disable it. Anyway, we do
+				// use the first n primes for key generation, so it is pretty easy
+				// to guess them. But as stated in the paper, this is not a security
+				// breach. So we can just work with the correct sigma.
+
+				// if (debug) {
+				//      Console.WriteLine("Decryption is " + test);
+				// }
+				// if ((key.G.ModPow(test, key.Modulus)).Equals(input)) {
+				//      output = test.ToByteArray();
+				// } else {
+				//      if(debug){
+				//          Console.WriteLine("Engine seems to be used as an oracle,
+				//          returning null");
+				//      }
+				//      output = null;
+				// }
+
+				output = test.ToByteArray();
+			}
+
+			return output;
+		}
+
+		/**
+		* Encrypts a BigInteger aka Plaintext with the public key.
+		*
+		* @param plain
+		*            The BigInteger to encrypt
+		* @return The byte[] representation of the encrypted BigInteger (i.e.
+		*         crypted.toByteArray())
+		*/
+		public byte[] Encrypt(
+			BigInteger plain)
+		{
+			// Always return modulus size values 0-padded at the beginning
+			// 0-padding at the beginning is correctly parsed by BigInteger :)
+//			byte[] output = key.Modulus.ToByteArray();
+//			Array.Clear(output, 0, output.Length);
+			byte[] output = new byte[key.Modulus.BitLength / 8 + 1];
+
+			byte[] tmp = key.G.ModPow(plain, key.Modulus).ToByteArray();
+			Array.Copy(tmp, 0, output, output.Length - tmp.Length, tmp.Length);
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("Encrypted value is:  " + new BigInteger(output));
+			}
+			return output;
+		}
+
+		/**
+		* Adds the contents of two encrypted blocks mod sigma
+		*
+		* @param block1
+		*            the first encrypted block
+		* @param block2
+		*            the second encrypted block
+		* @return encrypt((block1 + block2) mod sigma)
+		* @throws InvalidCipherTextException
+		*/
+		public byte[] AddCryptedBlocks(
+			byte[] block1,
+			byte[] block2)
+		{
+			// check for correct blocksize
+			if (forEncryption)
+			{
+				if ((block1.Length > GetOutputBlockSize())
+						|| (block2.Length > GetOutputBlockSize()))
+				{
+					throw new InvalidCipherTextException(
+							"BlockLength too large for simple addition.\n");
+				}
+			}
+			else
+			{
+				if ((block1.Length > GetInputBlockSize())
+						|| (block2.Length > GetInputBlockSize()))
+				{
+					throw new InvalidCipherTextException(
+							"BlockLength too large for simple addition.\n");
+				}
+			}
+
+			// calculate resulting block
+			BigInteger m1Crypt = new BigInteger(1, block1);
+			BigInteger m2Crypt = new BigInteger(1, block2);
+			BigInteger m1m2Crypt = m1Crypt.Multiply(m2Crypt);
+			m1m2Crypt = m1m2Crypt.Mod(key.Modulus);
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("c(m1) as BigInteger:....... " + m1Crypt);
+                System.Diagnostics.Debug.WriteLine("c(m2) as BigInteger:....... " + m2Crypt);
+                System.Diagnostics.Debug.WriteLine("c(m1)*c(m2)%n = c(m1+m2)%n: " + m1m2Crypt);
+			}
+
+			//byte[] output = key.Modulus.ToByteArray();
+			//Array.Clear(output, 0, output.Length);
+			byte[] output = new byte[key.Modulus.BitLength / 8 + 1];
+
+			byte[] m1m2CryptBytes = m1m2Crypt.ToByteArray();
+			Array.Copy(m1m2CryptBytes, 0, output,
+				output.Length - m1m2CryptBytes.Length, m1m2CryptBytes.Length);
+
+			return output;
+		}
+
+		/**
+		* Convenience Method for data exchange with the cipher.
+		*
+		* Determines blocksize and splits data to blocksize.
+		*
+		* @param data the data to be processed
+		* @return the data after it went through the NaccacheSternEngine.
+		* @throws InvalidCipherTextException
+		*/
+		public byte[] ProcessData(
+			byte[] data)
+		{
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("");
+			}
+			if (data.Length > GetInputBlockSize())
+			{
+				int inBlocksize = GetInputBlockSize();
+				int outBlocksize = GetOutputBlockSize();
+				if (debug)
+				{
+                    System.Diagnostics.Debug.WriteLine("Input blocksize is:  " + inBlocksize + " bytes");
+                    System.Diagnostics.Debug.WriteLine("Output blocksize is: " + outBlocksize + " bytes");
+                    System.Diagnostics.Debug.WriteLine("Data has length:.... " + data.Length + " bytes");
+				}
+				int datapos = 0;
+				int retpos = 0;
+				byte[] retval = new byte[(data.Length / inBlocksize + 1) * outBlocksize];
+				while (datapos < data.Length)
+				{
+					byte[] tmp;
+					if (datapos + inBlocksize < data.Length)
+					{
+						tmp = ProcessBlock(data, datapos, inBlocksize);
+						datapos += inBlocksize;
+					}
+					else
+					{
+						tmp = ProcessBlock(data, datapos, data.Length - datapos);
+						datapos += data.Length - datapos;
+					}
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("new datapos is " + datapos);
+					}
+					if (tmp != null)
+					{
+						tmp.CopyTo(retval, retpos);
+						retpos += tmp.Length;
+					}
+					else
+					{
+						if (debug)
+						{
+                            System.Diagnostics.Debug.WriteLine("cipher returned null");
+						}
+						throw new InvalidCipherTextException("cipher returned null");
+					}
+				}
+				byte[] ret = new byte[retpos];
+				Array.Copy(retval, 0, ret, 0, retpos);
+				if (debug)
+				{
+                    System.Diagnostics.Debug.WriteLine("returning " + ret.Length + " bytes");
+				}
+				return ret;
+			}
+			else
+			{
+				if (debug)
+				{
+                    System.Diagnostics.Debug.WriteLine("data size is less then input block size, processing directly");
+				}
+				return ProcessBlock(data, 0, data.Length);
+			}
+		}
+
+		/**
+		* Computes the integer x that is expressed through the given primes and the
+		* congruences with the chinese remainder theorem (CRT).
+		*
+		* @param congruences
+		*            the congruences c_i
+		* @param primes
+		*            the primes p_i
+		* @return an integer x for that x % p_i == c_i
+		*/
+		private static BigInteger chineseRemainder(IList congruences, IList primes)
+		{
+			BigInteger retval = BigInteger.Zero;
+			BigInteger all = BigInteger.One;
+			for (int i = 0; i < primes.Count; i++)
+			{
+				all = all.Multiply((BigInteger)primes[i]);
+			}
+			for (int i = 0; i < primes.Count; i++)
+			{
+				BigInteger a = (BigInteger)primes[i];
+				BigInteger b = all.Divide(a);
+				BigInteger b2 = b.ModInverse(a);
+				BigInteger tmp = b.Multiply(b2);
+				tmp = tmp.Multiply((BigInteger)congruences[i]);
+				retval = retval.Add(tmp);
+			}
+
+			return retval.Mod(all);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/NoekeonEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/NoekeonEngine.cs
new file mode 100644
index 0000000..b73e696
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/NoekeonEngine.cs
@@ -0,0 +1,240 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* A Noekeon engine, using direct-key mode.
+	*/
+	public class NoekeonEngine
+		: IBlockCipher
+	{
+		private const int GenericSize = 16; // Block and key size, as well as the amount of rounds.
+
+		private static readonly uint[] nullVector = 
+		{
+			0x00, 0x00, 0x00, 0x00 // Used in decryption
+		};
+
+		private static readonly uint[] roundConstants = 
+		{
+			0x80, 0x1b, 0x36, 0x6c,
+			0xd8, 0xab, 0x4d, 0x9a,
+			0x2f, 0x5e, 0xbc, 0x63,
+			0xc6, 0x97, 0x35, 0x6a,
+			0xd4
+		};
+
+		private uint[]	state = new uint[4], // a
+						subKeys = new uint[4], // k
+						decryptKeys = new uint[4];
+
+		private bool _initialised, _forEncryption;
+
+		/**
+		* Create an instance of the Noekeon encryption algorithm
+		* and set some defaults
+		*/
+		public NoekeonEngine()
+		{
+			_initialised = false;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Noekeon"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return GenericSize;
+		}
+
+		/**
+		* initialise
+		*
+		* @param forEncryption whether or not we are for encryption.
+		* @param params the parameters required to set up the cipher.
+		* @exception ArgumentException if the params argument is
+		* inappropriate.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is KeyParameter))
+				throw new ArgumentException("Invalid parameters passed to Noekeon init - " + parameters.GetType().Name, "parameters");
+
+			_forEncryption = forEncryption;
+			_initialised = true;
+
+			KeyParameter p = (KeyParameter) parameters;
+
+			setKey(p.GetKey());
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if (!_initialised)
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+			if ((inOff + GenericSize) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + GenericSize) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			return _forEncryption
+				?	encryptBlock(input, inOff, output, outOff)
+				:	decryptBlock(input, inOff, output, outOff);
+		}
+
+		public void Reset()
+		{
+			// TODO This should do something in case the encryption is aborted
+		}
+
+		/**
+		* Re-key the cipher.
+		*
+		* @param  key  the key to be used
+		*/
+		private void setKey(byte[] key)
+		{
+			subKeys[0] = Pack.BE_To_UInt32(key, 0);
+			subKeys[1] = Pack.BE_To_UInt32(key, 4);
+			subKeys[2] = Pack.BE_To_UInt32(key, 8);
+			subKeys[3] = Pack.BE_To_UInt32(key, 12);
+		}
+
+		private int encryptBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			state[0] = Pack.BE_To_UInt32(input, inOff);
+			state[1] = Pack.BE_To_UInt32(input, inOff+4);
+			state[2] = Pack.BE_To_UInt32(input, inOff+8);
+			state[3] = Pack.BE_To_UInt32(input, inOff+12);
+
+			int i;
+			for (i = 0; i < GenericSize; i++)
+			{
+				state[0] ^= roundConstants[i];
+				theta(state, subKeys);
+				pi1(state);
+				gamma(state);
+				pi2(state);            
+			}
+
+			state[0] ^= roundConstants[i];
+			theta(state, subKeys);
+
+			Pack.UInt32_To_BE(state[0], output, outOff);
+			Pack.UInt32_To_BE(state[1], output, outOff+4);
+			Pack.UInt32_To_BE(state[2], output, outOff+8);
+			Pack.UInt32_To_BE(state[3], output, outOff+12);
+
+			return GenericSize;
+		}
+
+		private int decryptBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			state[0] = Pack.BE_To_UInt32(input, inOff);
+			state[1] = Pack.BE_To_UInt32(input, inOff+4);
+			state[2] = Pack.BE_To_UInt32(input, inOff+8);
+			state[3] = Pack.BE_To_UInt32(input, inOff+12);
+
+			Array.Copy(subKeys, 0, decryptKeys, 0, subKeys.Length);
+			theta(decryptKeys, nullVector);
+
+			int i;
+			for (i = GenericSize; i > 0; i--)
+			{
+				theta(state, decryptKeys);
+				state[0] ^= roundConstants[i];
+				pi1(state);
+				gamma(state);
+				pi2(state);
+			}
+
+			theta(state, decryptKeys);
+			state[0] ^= roundConstants[i];
+
+			Pack.UInt32_To_BE(state[0], output, outOff);
+			Pack.UInt32_To_BE(state[1], output, outOff+4);
+			Pack.UInt32_To_BE(state[2], output, outOff+8);
+			Pack.UInt32_To_BE(state[3], output, outOff+12);
+
+			return GenericSize;
+		}
+
+		private void gamma(uint[] a)
+		{
+			a[1] ^= ~a[3] & ~a[2];
+			a[0] ^= a[2] & a[1];
+
+			uint tmp = a[3];
+			a[3]  = a[0];
+			a[0]  = tmp;
+			a[2] ^= a[0]^a[1]^a[3];
+
+			a[1] ^= ~a[3] & ~a[2];
+			a[0] ^= a[2] & a[1];
+		}
+
+		private void theta(uint[] a, uint[] k)
+		{
+			uint tmp;
+			tmp   = a[0]^a[2]; 
+			tmp  ^= rotl(tmp,8)^rotl(tmp,24); 
+			a[1] ^= tmp; 
+			a[3] ^= tmp; 
+
+			for (int i = 0; i < 4; i++)
+			{
+				a[i] ^= k[i];
+			}
+
+			tmp   = a[1]^a[3]; 
+			tmp  ^= rotl(tmp,8)^rotl(tmp,24); 
+			a[0] ^= tmp; 
+			a[2] ^= tmp;
+		}
+
+		private void pi1(uint[] a)
+		{
+			a[1] = rotl(a[1], 1);
+			a[2] = rotl(a[2], 5);
+			a[3] = rotl(a[3], 2);
+		}
+
+		private void pi2(uint[] a)
+		{
+			a[1] = rotl(a[1], 31);
+			a[2] = rotl(a[2], 27);
+			a[3] = rotl(a[3], 30);
+		}
+
+		// Helpers
+
+		private uint rotl(uint x, int y)
+		{
+			return (x << y) | (x >> (32-y));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/NullEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/NullEngine.cs
new file mode 100644
index 0000000..407b8cc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/NullEngine.cs
@@ -0,0 +1,70 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* The no-op engine that just copies bytes through, irrespective of whether encrypting and decrypting.
+	* Provided for the sake of completeness.
+	*/
+	public class NullEngine
+		: IBlockCipher
+	{
+		private bool initialised;
+		private const int BlockSize = 1;
+
+		public NullEngine()
+		{
+		}
+
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			// we don't mind any parameters that may come in
+			initialised = true;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Null"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BlockSize;
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if (!initialised)
+				throw new InvalidOperationException("Null engine not initialised");
+			if ((inOff + BlockSize) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + BlockSize) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			for (int i = 0; i < BlockSize; ++i)
+			{
+				output[outOff + i] = input[inOff + i];
+			}
+
+			return BlockSize;
+		}
+
+		public void Reset()
+		{
+			// nothing needs to be done
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC2Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC2Engine.cs
new file mode 100644
index 0000000..aaf8c71
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC2Engine.cs
@@ -0,0 +1,312 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * an implementation of RC2 as described in RFC 2268
+    *      "A Description of the RC2(r) Encryption Algorithm" R. Rivest.
+    */
+    public class RC2Engine
+		: IBlockCipher
+    {
+        //
+        // the values we use for key expansion (based on the digits of PI)
+        //
+        private static readonly byte[] piTable =
+        {
+            (byte)0xd9, (byte)0x78, (byte)0xf9, (byte)0xc4, (byte)0x19, (byte)0xdd, (byte)0xb5, (byte)0xed,
+            (byte)0x28, (byte)0xe9, (byte)0xfd, (byte)0x79, (byte)0x4a, (byte)0xa0, (byte)0xd8, (byte)0x9d,
+            (byte)0xc6, (byte)0x7e, (byte)0x37, (byte)0x83, (byte)0x2b, (byte)0x76, (byte)0x53, (byte)0x8e,
+            (byte)0x62, (byte)0x4c, (byte)0x64, (byte)0x88, (byte)0x44, (byte)0x8b, (byte)0xfb, (byte)0xa2,
+            (byte)0x17, (byte)0x9a, (byte)0x59, (byte)0xf5, (byte)0x87, (byte)0xb3, (byte)0x4f, (byte)0x13,
+            (byte)0x61, (byte)0x45, (byte)0x6d, (byte)0x8d, (byte)0x9, (byte)0x81, (byte)0x7d, (byte)0x32,
+            (byte)0xbd, (byte)0x8f, (byte)0x40, (byte)0xeb, (byte)0x86, (byte)0xb7, (byte)0x7b, (byte)0xb,
+            (byte)0xf0, (byte)0x95, (byte)0x21, (byte)0x22, (byte)0x5c, (byte)0x6b, (byte)0x4e, (byte)0x82,
+            (byte)0x54, (byte)0xd6, (byte)0x65, (byte)0x93, (byte)0xce, (byte)0x60, (byte)0xb2, (byte)0x1c,
+            (byte)0x73, (byte)0x56, (byte)0xc0, (byte)0x14, (byte)0xa7, (byte)0x8c, (byte)0xf1, (byte)0xdc,
+            (byte)0x12, (byte)0x75, (byte)0xca, (byte)0x1f, (byte)0x3b, (byte)0xbe, (byte)0xe4, (byte)0xd1,
+            (byte)0x42, (byte)0x3d, (byte)0xd4, (byte)0x30, (byte)0xa3, (byte)0x3c, (byte)0xb6, (byte)0x26,
+            (byte)0x6f, (byte)0xbf, (byte)0xe, (byte)0xda, (byte)0x46, (byte)0x69, (byte)0x7, (byte)0x57,
+            (byte)0x27, (byte)0xf2, (byte)0x1d, (byte)0x9b, (byte)0xbc, (byte)0x94, (byte)0x43, (byte)0x3,
+            (byte)0xf8, (byte)0x11, (byte)0xc7, (byte)0xf6, (byte)0x90, (byte)0xef, (byte)0x3e, (byte)0xe7,
+            (byte)0x6, (byte)0xc3, (byte)0xd5, (byte)0x2f, (byte)0xc8, (byte)0x66, (byte)0x1e, (byte)0xd7,
+            (byte)0x8, (byte)0xe8, (byte)0xea, (byte)0xde, (byte)0x80, (byte)0x52, (byte)0xee, (byte)0xf7,
+            (byte)0x84, (byte)0xaa, (byte)0x72, (byte)0xac, (byte)0x35, (byte)0x4d, (byte)0x6a, (byte)0x2a,
+            (byte)0x96, (byte)0x1a, (byte)0xd2, (byte)0x71, (byte)0x5a, (byte)0x15, (byte)0x49, (byte)0x74,
+            (byte)0x4b, (byte)0x9f, (byte)0xd0, (byte)0x5e, (byte)0x4, (byte)0x18, (byte)0xa4, (byte)0xec,
+            (byte)0xc2, (byte)0xe0, (byte)0x41, (byte)0x6e, (byte)0xf, (byte)0x51, (byte)0xcb, (byte)0xcc,
+            (byte)0x24, (byte)0x91, (byte)0xaf, (byte)0x50, (byte)0xa1, (byte)0xf4, (byte)0x70, (byte)0x39,
+            (byte)0x99, (byte)0x7c, (byte)0x3a, (byte)0x85, (byte)0x23, (byte)0xb8, (byte)0xb4, (byte)0x7a,
+            (byte)0xfc, (byte)0x2, (byte)0x36, (byte)0x5b, (byte)0x25, (byte)0x55, (byte)0x97, (byte)0x31,
+            (byte)0x2d, (byte)0x5d, (byte)0xfa, (byte)0x98, (byte)0xe3, (byte)0x8a, (byte)0x92, (byte)0xae,
+            (byte)0x5, (byte)0xdf, (byte)0x29, (byte)0x10, (byte)0x67, (byte)0x6c, (byte)0xba, (byte)0xc9,
+            (byte)0xd3, (byte)0x0, (byte)0xe6, (byte)0xcf, (byte)0xe1, (byte)0x9e, (byte)0xa8, (byte)0x2c,
+            (byte)0x63, (byte)0x16, (byte)0x1, (byte)0x3f, (byte)0x58, (byte)0xe2, (byte)0x89, (byte)0xa9,
+            (byte)0xd, (byte)0x38, (byte)0x34, (byte)0x1b, (byte)0xab, (byte)0x33, (byte)0xff, (byte)0xb0,
+            (byte)0xbb, (byte)0x48, (byte)0xc, (byte)0x5f, (byte)0xb9, (byte)0xb1, (byte)0xcd, (byte)0x2e,
+            (byte)0xc5, (byte)0xf3, (byte)0xdb, (byte)0x47, (byte)0xe5, (byte)0xa5, (byte)0x9c, (byte)0x77,
+            (byte)0xa, (byte)0xa6, (byte)0x20, (byte)0x68, (byte)0xfe, (byte)0x7f, (byte)0xc1, (byte)0xad
+        };
+
+        private const int BLOCK_SIZE = 8;
+
+        private int[]   workingKey;
+        private bool encrypting;
+
+        private int[] GenerateWorkingKey(
+            byte[]      key,
+            int         bits)
+        {
+            int     x;
+            int[]   xKey = new int[128];
+
+            for (int i = 0; i != key.Length; i++)
+            {
+                xKey[i] = key[i] & 0xff;
+            }
+
+            // Phase 1: Expand input key to 128 bytes
+            int len = key.Length;
+
+            if (len < 128)
+            {
+                int     index = 0;
+
+                x = xKey[len - 1];
+
+                do
+                {
+                    x = piTable[(x + xKey[index++]) & 255] & 0xff;
+                    xKey[len++] = x;
+                }
+                while (len < 128);
+            }
+
+            // Phase 2 - reduce effective key size to "bits"
+            len = (bits + 7) >> 3;
+            x = piTable[xKey[128 - len] & (255 >> (7 & -bits))] & 0xff;
+            xKey[128 - len] = x;
+
+            for (int i = 128 - len - 1; i >= 0; i--)
+            {
+                    x = piTable[x ^ xKey[i + len]] & 0xff;
+                    xKey[i] = x;
+            }
+
+            // Phase 3 - copy to newKey in little-endian order
+            int[] newKey = new int[64];
+
+            for (int i = 0; i != newKey.Length; i++)
+            {
+                newKey[i] = (xKey[2 * i] + (xKey[2 * i + 1] << 8));
+            }
+
+            return newKey;
+        }
+
+        /**
+        * initialise a RC2 cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            this.encrypting = forEncryption;
+
+			if (parameters is RC2Parameters)
+            {
+                RC2Parameters param = (RC2Parameters) parameters;
+
+				workingKey = GenerateWorkingKey(param.GetKey(), param.EffectiveKeyBits);
+            }
+            else if (parameters is KeyParameter)
+            {
+				KeyParameter param = (KeyParameter) parameters;
+				byte[] key = param.GetKey();
+
+				workingKey = GenerateWorkingKey(key, key.Length * 8);
+            }
+            else
+            {
+                throw new ArgumentException("invalid parameter passed to RC2 init - " + parameters.GetType().Name);
+            }
+        }
+
+		public void Reset()
+        {
+        }
+
+		public string AlgorithmName
+        {
+            get { return "RC2"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public  int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (workingKey == null)
+                throw new InvalidOperationException("RC2 engine not initialised");
+            if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+			if (encrypting)
+            {
+                EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                DecryptBlock(input, inOff, output, outOff);
+            }
+
+            return BLOCK_SIZE;
+        }
+
+        /**
+        * return the result rotating the 16 bit number in x left by y
+        */
+        private int RotateWordLeft(
+            int x,
+            int y)
+        {
+            x &= 0xffff;
+            return (x << y) | (x >> (16 - y));
+        }
+
+        private void EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int x76, x54, x32, x10;
+
+            x76 = ((input[inOff + 7] & 0xff) << 8) + (input[inOff + 6] & 0xff);
+            x54 = ((input[inOff + 5] & 0xff) << 8) + (input[inOff + 4] & 0xff);
+            x32 = ((input[inOff + 3] & 0xff) << 8) + (input[inOff + 2] & 0xff);
+            x10 = ((input[inOff + 1] & 0xff) << 8) + (input[inOff + 0] & 0xff);
+
+            for (int i = 0; i <= 16; i += 4)
+            {
+                    x10 = RotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
+                    x32 = RotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+                    x54 = RotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+                    x76 = RotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+            }
+
+            x10 += workingKey[x76 & 63];
+            x32 += workingKey[x10 & 63];
+            x54 += workingKey[x32 & 63];
+            x76 += workingKey[x54 & 63];
+
+            for (int i = 20; i <= 40; i += 4)
+            {
+                    x10 = RotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
+                    x32 = RotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+                    x54 = RotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+                    x76 = RotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+            }
+
+            x10 += workingKey[x76 & 63];
+            x32 += workingKey[x10 & 63];
+            x54 += workingKey[x32 & 63];
+            x76 += workingKey[x54 & 63];
+
+            for (int i = 44; i < 64; i += 4)
+            {
+                    x10 = RotateWordLeft(x10 + (x32 & ~x76) + (x54 & x76) + workingKey[i  ], 1);
+                    x32 = RotateWordLeft(x32 + (x54 & ~x10) + (x76 & x10) + workingKey[i+1], 2);
+                    x54 = RotateWordLeft(x54 + (x76 & ~x32) + (x10 & x32) + workingKey[i+2], 3);
+                    x76 = RotateWordLeft(x76 + (x10 & ~x54) + (x32 & x54) + workingKey[i+3], 5);
+            }
+
+            outBytes[outOff + 0] = (byte)x10;
+            outBytes[outOff + 1] = (byte)(x10 >> 8);
+            outBytes[outOff + 2] = (byte)x32;
+            outBytes[outOff + 3] = (byte)(x32 >> 8);
+            outBytes[outOff + 4] = (byte)x54;
+            outBytes[outOff + 5] = (byte)(x54 >> 8);
+            outBytes[outOff + 6] = (byte)x76;
+            outBytes[outOff + 7] = (byte)(x76 >> 8);
+        }
+
+        private void DecryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int x76, x54, x32, x10;
+
+            x76 = ((input[inOff + 7] & 0xff) << 8) + (input[inOff + 6] & 0xff);
+            x54 = ((input[inOff + 5] & 0xff) << 8) + (input[inOff + 4] & 0xff);
+            x32 = ((input[inOff + 3] & 0xff) << 8) + (input[inOff + 2] & 0xff);
+            x10 = ((input[inOff + 1] & 0xff) << 8) + (input[inOff + 0] & 0xff);
+
+            for (int i = 60; i >= 44; i -= 4)
+            {
+                x76 = RotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+                x54 = RotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+                x32 = RotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+                x10 = RotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
+            }
+
+            x76 -= workingKey[x54 & 63];
+            x54 -= workingKey[x32 & 63];
+            x32 -= workingKey[x10 & 63];
+            x10 -= workingKey[x76 & 63];
+
+            for (int i = 40; i >= 20; i -= 4)
+            {
+                x76 = RotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+                x54 = RotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+                x32 = RotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+                x10 = RotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
+            }
+
+            x76 -= workingKey[x54 & 63];
+            x54 -= workingKey[x32 & 63];
+            x32 -= workingKey[x10 & 63];
+            x10 -= workingKey[x76 & 63];
+
+            for (int i = 16; i >= 0; i -= 4)
+            {
+                x76 = RotateWordLeft(x76, 11) - ((x10 & ~x54) + (x32 & x54) + workingKey[i+3]);
+                x54 = RotateWordLeft(x54, 13) - ((x76 & ~x32) + (x10 & x32) + workingKey[i+2]);
+                x32 = RotateWordLeft(x32, 14) - ((x54 & ~x10) + (x76 & x10) + workingKey[i+1]);
+                x10 = RotateWordLeft(x10, 15) - ((x32 & ~x76) + (x54 & x76) + workingKey[i  ]);
+            }
+
+            outBytes[outOff + 0] = (byte)x10;
+            outBytes[outOff + 1] = (byte)(x10 >> 8);
+            outBytes[outOff + 2] = (byte)x32;
+            outBytes[outOff + 3] = (byte)(x32 >> 8);
+            outBytes[outOff + 4] = (byte)x54;
+            outBytes[outOff + 5] = (byte)(x54 >> 8);
+            outBytes[outOff + 6] = (byte)x76;
+            outBytes[outOff + 7] = (byte)(x76 >> 8);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC2WrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC2WrapEngine.cs
new file mode 100644
index 0000000..238c9f7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC2WrapEngine.cs
@@ -0,0 +1,370 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	 * Wrap keys according to RFC 3217 - RC2 mechanism
+	 */
+	public class RC2WrapEngine
+		: IWrapper
+	{
+		/** Field engine */
+		private CbcBlockCipher engine;
+
+		/** Field param */
+		private ICipherParameters parameters;
+
+		/** Field paramPlusIV */
+		private ParametersWithIV paramPlusIV;
+
+		/** Field iv */
+		private byte[] iv;
+
+		/** Field forWrapping */
+		private bool forWrapping;
+
+		private SecureRandom sr;
+
+		/** Field IV2           */
+		private static readonly byte[] IV2 =
+		{
+			(byte) 0x4a, (byte) 0xdd, (byte) 0xa2,
+			(byte) 0x2c, (byte) 0x79, (byte) 0xe8,
+			(byte) 0x21, (byte) 0x05
+		};
+
+		//
+		// checksum digest
+		//
+		IDigest sha1 = new Sha1Digest();
+		byte[] digest = new byte[20];
+
+		/**
+			* Method init
+			*
+			* @param forWrapping
+			* @param param
+			*/
+		public void Init(
+			bool				forWrapping,
+			ICipherParameters	parameters)
+		{
+			this.forWrapping = forWrapping;
+			this.engine = new CbcBlockCipher(new RC2Engine());
+
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom pWithR = (ParametersWithRandom)parameters;
+				sr = pWithR.Random;
+				parameters = pWithR.Parameters;
+			}
+			else
+			{
+				sr = new SecureRandom();
+			}
+
+			if (parameters is ParametersWithIV)
+			{
+				if (!forWrapping)
+					throw new ArgumentException("You should not supply an IV for unwrapping");
+
+				this.paramPlusIV = (ParametersWithIV)parameters;
+				this.iv = this.paramPlusIV.GetIV();
+				this.parameters = this.paramPlusIV.Parameters;
+
+				if (this.iv.Length != 8)
+					throw new ArgumentException("IV is not 8 octets");
+			}
+			else
+			{
+				this.parameters = parameters;
+
+				if (this.forWrapping)
+				{
+					// Hm, we have no IV but we want to wrap ?!?
+					// well, then we have to create our own IV.
+					this.iv = new byte[8];
+					sr.NextBytes(iv);
+					this.paramPlusIV = new ParametersWithIV(this.parameters, this.iv);
+				}
+			}
+		}
+
+		/**
+		* Method GetAlgorithmName
+		*
+		* @return
+		*/
+		public string AlgorithmName
+		{
+			get { return "RC2"; }
+		}
+
+		/**
+		* Method wrap
+		*
+		* @param in
+		* @param inOff
+		* @param inLen
+		* @return
+		*/
+		public byte[] Wrap(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (!forWrapping)
+			{
+				throw new InvalidOperationException("Not initialized for wrapping");
+			}
+
+			int len = length + 1;
+			if ((len % 8) != 0)
+			{
+				len += 8 - (len % 8);
+			}
+
+			byte [] keyToBeWrapped = new byte[len];
+
+			keyToBeWrapped[0] = (byte)length;
+			Array.Copy(input, inOff, keyToBeWrapped, 1, length);
+
+			byte[] pad = new byte[keyToBeWrapped.Length - length - 1];
+
+			if (pad.Length > 0)
+			{
+				sr.NextBytes(pad);
+				Array.Copy(pad, 0, keyToBeWrapped, length + 1, pad.Length);
+			}
+
+			// Compute the CMS Key Checksum, (section 5.6.1), call this CKS.
+			byte[] CKS = CalculateCmsKeyChecksum(keyToBeWrapped);
+
+			// Let WKCKS = WK || CKS where || is concatenation.
+			byte[] WKCKS = new byte[keyToBeWrapped.Length + CKS.Length];
+
+			Array.Copy(keyToBeWrapped, 0, WKCKS, 0, keyToBeWrapped.Length);
+			Array.Copy(CKS, 0, WKCKS, keyToBeWrapped.Length, CKS.Length);
+
+			// Encrypt WKCKS in CBC mode using KEK as the key and IV as the
+			// initialization vector. Call the results TEMP1.
+			byte [] TEMP1 = new byte[WKCKS.Length];
+
+			Array.Copy(WKCKS, 0, TEMP1, 0, WKCKS.Length);
+
+			int noOfBlocks = WKCKS.Length / engine.GetBlockSize();
+			int extraBytes = WKCKS.Length % engine.GetBlockSize();
+
+			if (extraBytes != 0)
+			{
+				throw new InvalidOperationException("Not multiple of block length");
+			}
+
+			engine.Init(true, paramPlusIV);
+
+			for (int i = 0; i < noOfBlocks; i++)
+			{
+				int currentBytePos = i * engine.GetBlockSize();
+
+				engine.ProcessBlock(TEMP1, currentBytePos, TEMP1, currentBytePos);
+			}
+
+			// Left TEMP2 = IV || TEMP1.
+			byte[] TEMP2 = new byte[this.iv.Length + TEMP1.Length];
+
+			Array.Copy(this.iv, 0, TEMP2, 0, this.iv.Length);
+			Array.Copy(TEMP1, 0, TEMP2, this.iv.Length, TEMP1.Length);
+
+			// Reverse the order of the octets in TEMP2 and call the result TEMP3.
+			byte[] TEMP3 = new byte[TEMP2.Length];
+
+			for (int i = 0; i < TEMP2.Length; i++)
+			{
+				TEMP3[i] = TEMP2[TEMP2.Length - (i + 1)];
+			}
+
+			// Encrypt TEMP3 in CBC mode using the KEK and an initialization vector
+			// of 0x 4a dd a2 2c 79 e8 21 05. The resulting cipher text is the desired
+			// result. It is 40 octets long if a 168 bit key is being wrapped.
+			ParametersWithIV param2 = new ParametersWithIV(this.parameters, IV2);
+
+			this.engine.Init(true, param2);
+
+			for (int i = 0; i < noOfBlocks + 1; i++)
+			{
+				int currentBytePos = i * engine.GetBlockSize();
+
+				engine.ProcessBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+			}
+
+			return TEMP3;
+		}
+
+		/**
+		* Method unwrap
+		*
+		* @param in
+		* @param inOff
+		* @param inLen
+		* @return
+		* @throws InvalidCipherTextException
+		*/
+		public byte[] Unwrap(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			if (forWrapping)
+			{
+				throw new InvalidOperationException("Not set for unwrapping");
+			}
+
+			if (input == null)
+			{
+				throw new InvalidCipherTextException("Null pointer as ciphertext");
+			}
+
+			if (length % engine.GetBlockSize() != 0)
+			{
+				throw new InvalidCipherTextException("Ciphertext not multiple of "
+					+ engine.GetBlockSize());
+			}
+
+			/*
+			// Check if the length of the cipher text is reasonable given the key
+			// type. It must be 40 bytes for a 168 bit key and either 32, 40, or
+			// 48 bytes for a 128, 192, or 256 bit key. If the length is not supported
+			// or inconsistent with the algorithm for which the key is intended,
+			// return error.
+			//
+			// we do not accept 168 bit keys. it has to be 192 bit.
+			int lengthA = (estimatedKeyLengthInBit / 8) + 16;
+			int lengthB = estimatedKeyLengthInBit % 8;
+
+			if ((lengthA != keyToBeUnwrapped.Length) || (lengthB != 0)) {
+				throw new XMLSecurityException("empty");
+			}
+			*/
+
+			// Decrypt the cipher text with TRIPLedeS in CBC mode using the KEK
+			// and an initialization vector (IV) of 0x4adda22c79e82105. Call the output TEMP3.
+			ParametersWithIV param2 = new ParametersWithIV(this.parameters, IV2);
+
+			this.engine.Init(false, param2);
+
+			byte [] TEMP3 = new byte[length];
+
+			Array.Copy(input, inOff, TEMP3, 0, length);
+
+			for (int i = 0; i < (TEMP3.Length / engine.GetBlockSize()); i++)
+			{
+				int currentBytePos = i * engine.GetBlockSize();
+
+				engine.ProcessBlock(TEMP3, currentBytePos, TEMP3, currentBytePos);
+			}
+
+			// Reverse the order of the octets in TEMP3 and call the result TEMP2.
+			byte[] TEMP2 = new byte[TEMP3.Length];
+
+			for (int i = 0; i < TEMP3.Length; i++)
+			{
+				TEMP2[i] = TEMP3[TEMP3.Length - (i + 1)];
+			}
+
+			// Decompose TEMP2 into IV, the first 8 octets, and TEMP1, the remaining octets.
+			this.iv = new byte[8];
+
+			byte[] TEMP1 = new byte[TEMP2.Length - 8];
+
+			Array.Copy(TEMP2, 0, this.iv, 0, 8);
+			Array.Copy(TEMP2, 8, TEMP1, 0, TEMP2.Length - 8);
+
+			// Decrypt TEMP1 using TRIPLedeS in CBC mode using the KEK and the IV
+			// found in the previous step. Call the result WKCKS.
+			this.paramPlusIV = new ParametersWithIV(this.parameters, this.iv);
+
+			this.engine.Init(false, this.paramPlusIV);
+
+			byte[] LCEKPADICV = new byte[TEMP1.Length];
+
+			Array.Copy(TEMP1, 0, LCEKPADICV, 0, TEMP1.Length);
+
+			for (int i = 0; i < (LCEKPADICV.Length / engine.GetBlockSize()); i++)
+			{
+				int currentBytePos = i * engine.GetBlockSize();
+
+				engine.ProcessBlock(LCEKPADICV, currentBytePos, LCEKPADICV, currentBytePos);
+			}
+
+			// Decompose LCEKPADICV. CKS is the last 8 octets and WK, the wrapped key, are
+			// those octets before the CKS.
+			byte[] result = new byte[LCEKPADICV.Length - 8];
+			byte[] CKStoBeVerified = new byte[8];
+
+			Array.Copy(LCEKPADICV, 0, result, 0, LCEKPADICV.Length - 8);
+			Array.Copy(LCEKPADICV, LCEKPADICV.Length - 8, CKStoBeVerified, 0, 8);
+
+			// Calculate a CMS Key Checksum, (section 5.6.1), over the WK and compare
+			// with the CKS extracted in the above step. If they are not equal, return error.
+			if (!CheckCmsKeyChecksum(result, CKStoBeVerified))
+			{
+				throw new InvalidCipherTextException(
+					"Checksum inside ciphertext is corrupted");
+			}
+
+			if ((result.Length - ((result[0] & 0xff) + 1)) > 7)
+			{
+				throw new InvalidCipherTextException(
+					"too many pad bytes (" + (result.Length - ((result[0] & 0xff) + 1)) + ")");
+			}
+
+			// CEK is the wrapped key, now extracted for use in data decryption.
+			byte[] CEK = new byte[result[0]];
+			Array.Copy(result, 1, CEK, 0, CEK.Length);
+			return CEK;
+		}
+
+		/**
+		* Some key wrap algorithms make use of the Key Checksum defined
+		* in CMS [CMS-Algorithms]. This is used to provide an integrity
+		* check value for the key being wrapped. The algorithm is
+		*
+		* - Compute the 20 octet SHA-1 hash on the key being wrapped.
+		* - Use the first 8 octets of this hash as the checksum value.
+		*
+		* @param key
+		* @return
+		* @throws Exception
+		* @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+		*/
+		private byte[] CalculateCmsKeyChecksum(
+			byte[] key)
+		{
+			sha1.BlockUpdate(key, 0, key.Length);
+			sha1.DoFinal(digest, 0);
+
+			byte[] result = new byte[8];
+			Array.Copy(digest, 0, result, 0, 8);
+			return result;
+		}
+
+		/**
+		* @param key
+		* @param checksum
+		* @return
+		* @see http://www.w3.org/TR/xmlenc-core/#sec-CMSKeyChecksum
+		*/
+		private bool CheckCmsKeyChecksum(
+			byte[]	key,
+			byte[]	checksum)
+		{
+			return Arrays.ConstantTimeAreEqual(CalculateCmsKeyChecksum(key), checksum);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC4Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC4Engine.cs
new file mode 100644
index 0000000..c65468d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC4Engine.cs
@@ -0,0 +1,147 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    public class RC4Engine
+		: IStreamCipher
+    {
+        private readonly static int STATE_LENGTH = 256;
+
+        /*
+        * variables to hold the state of the RC4 engine
+        * during encryption and decryption
+        */
+
+        private byte[]	engineState;
+        private int		x;
+        private int		y;
+        private byte[]	workingKey;
+
+        /**
+        * initialise a RC4 cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (parameters is KeyParameter)
+            {
+                /*
+                * RC4 encryption and decryption is completely
+                * symmetrical, so the 'forEncryption' is
+                * irrelevant.
+                */
+                workingKey = ((KeyParameter)parameters).GetKey();
+                SetKey(workingKey);
+
+                return;
+            }
+
+            throw new ArgumentException("invalid parameter passed to RC4 init - " + parameters.GetType().ToString());
+        }
+
+		public string AlgorithmName
+        {
+            get { return "RC4"; }
+        }
+
+		public byte ReturnByte(
+			byte input)
+        {
+            x = (x + 1) & 0xff;
+            y = (engineState[x] + y) & 0xff;
+
+            // swap
+            byte tmp = engineState[x];
+            engineState[x] = engineState[y];
+            engineState[y] = tmp;
+
+            // xor
+            return (byte)(input ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+        }
+
+        public void ProcessBytes(
+            byte[]	input,
+            int		inOff,
+            int		length,
+            byte[]	output,
+            int		outOff
+        )
+        {
+            if ((inOff + length) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + length) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            for (int i = 0; i < length ; i++)
+            {
+                x = (x + 1) & 0xff;
+                y = (engineState[x] + y) & 0xff;
+
+                // swap
+                byte tmp = engineState[x];
+                engineState[x] = engineState[y];
+                engineState[y] = tmp;
+
+                // xor
+                output[i+outOff] = (byte)(input[i + inOff]
+                        ^ engineState[(engineState[x] + engineState[y]) & 0xff]);
+            }
+        }
+
+        public void Reset()
+        {
+            SetKey(workingKey);
+        }
+
+        // Private implementation
+
+        private void SetKey(
+			byte[] keyBytes)
+        {
+            workingKey = keyBytes;
+
+            // System.out.println("the key length is ; "+ workingKey.Length);
+
+            x = 0;
+            y = 0;
+
+            if (engineState == null)
+            {
+                engineState = new byte[STATE_LENGTH];
+            }
+
+            // reset the state of the engine
+            for (int i=0; i < STATE_LENGTH; i++)
+            {
+                engineState[i] = (byte)i;
+            }
+
+            int i1 = 0;
+            int i2 = 0;
+
+            for (int i=0; i < STATE_LENGTH; i++)
+            {
+                i2 = ((keyBytes[i1] & 0xff) + engineState[i] + i2) & 0xff;
+                // do the byte-swap inline
+                byte tmp = engineState[i];
+                engineState[i] = engineState[i2];
+                engineState[i2] = tmp;
+                i1 = (i1+1) % keyBytes.Length;
+            }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC532Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC532Engine.cs
new file mode 100644
index 0000000..1661707
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC532Engine.cs
@@ -0,0 +1,294 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+    * publication in RSA CryptoBytes, Spring of 1995.
+    * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+    * <p>
+    * This implementation has a word size of 32 bits.</p>
+    */
+    public class RC532Engine
+		: IBlockCipher
+    {
+        /*
+        * the number of rounds to perform
+        */
+        private int _noRounds;
+
+        /*
+        * the expanded key array of size 2*(rounds + 1)
+        */
+        private int [] _S;
+
+        /*
+        * our "magic constants" for 32 32
+        *
+        * Pw = Odd((e-2) * 2^wordsize)
+        * Qw = Odd((o-2) * 2^wordsize)
+        *
+        * where e is the base of natural logarithms (2.718281828...)
+        * and o is the golden ratio (1.61803398...)
+        */
+        private static readonly int P32 = unchecked((int) 0xb7e15163);
+        private static readonly int Q32 = unchecked((int) 0x9e3779b9);
+
+        private bool forEncryption;
+
+        /**
+        * Create an instance of the RC5 encryption algorithm
+        * and set some defaults
+        */
+        public RC532Engine()
+        {
+            _noRounds     = 12;         // the default
+//            _S            = null;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "RC5-32"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return 2 * 4;
+        }
+
+		/**
+        * initialise a RC5-32 cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (typeof(RC5Parameters).IsInstanceOfType(parameters))
+            {
+                RC5Parameters p = (RC5Parameters)parameters;
+
+                _noRounds = p.Rounds;
+
+                SetKey(p.GetKey());
+            }
+            else if (typeof(KeyParameter).IsInstanceOfType(parameters))
+            {
+                KeyParameter p = (KeyParameter)parameters;
+
+                SetKey(p.GetKey());
+            }
+            else
+            {
+                throw new ArgumentException("invalid parameter passed to RC532 init - " + parameters.GetType().ToString());
+            }
+
+            this.forEncryption = forEncryption;
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            return (forEncryption)
+				?	EncryptBlock(input, inOff, output, outOff)
+				:	DecryptBlock(input, inOff, output, outOff);
+        }
+
+		public void Reset()
+        {
+        }
+
+        /**
+        * Re-key the cipher.
+        *
+        * @param  key  the key to be used
+        */
+        private void SetKey(
+            byte[] key)
+        {
+            //
+            // KEY EXPANSION:
+            //
+            // There are 3 phases to the key expansion.
+            //
+            // Phase 1:
+            //   Copy the secret key K[0...b-1] into an array L[0..c-1] of
+            //   c = ceil(b/u), where u = 32/8 in little-endian order.
+            //   In other words, we fill up L using u consecutive key bytes
+            //   of K. Any unfilled byte positions in L are zeroed. In the
+            //   case that b = c = 0, set c = 1 and L[0] = 0.
+            //
+            int[]   L = new int[(key.Length + (4 - 1)) / 4];
+
+            for (int i = 0; i != key.Length; i++)
+            {
+                L[i / 4] += (key[i] & 0xff) << (8 * (i % 4));
+            }
+
+            //
+            // Phase 2:
+            //   Initialize S to a particular fixed pseudo-random bit pattern
+            //   using an arithmetic progression modulo 2^wordsize determined
+            //   by the magic numbers, Pw & Qw.
+            //
+            _S            = new int[2*(_noRounds + 1)];
+
+            _S[0] = P32;
+            for (int i=1; i < _S.Length; i++)
+            {
+                _S[i] = (_S[i-1] + Q32);
+            }
+
+            //
+            // Phase 3:
+            //   Mix in the user's secret key in 3 passes over the arrays S & L.
+            //   The max of the arrays sizes is used as the loop control
+            //
+            int iter;
+
+            if (L.Length > _S.Length)
+            {
+                iter = 3 * L.Length;
+            }
+            else
+            {
+                iter = 3 * _S.Length;
+            }
+
+            int A = 0, B = 0;
+            int ii = 0, jj = 0;
+
+            for (int k = 0; k < iter; k++)
+            {
+                A = _S[ii] = RotateLeft(_S[ii] + A + B, 3);
+                B =  L[jj] = RotateLeft( L[jj] + A + B, A+B);
+                ii = (ii+1) % _S.Length;
+                jj = (jj+1) %  L.Length;
+            }
+        }
+
+        /**
+        * Encrypt the given block starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param  in     in byte buffer containing data to encrypt
+        * @param  inOff  offset into src buffer
+        * @param  out     out buffer where encrypted data is written
+        * @param  outOff  offset into out buffer
+        */
+        private int EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int A = BytesToWord(input, inOff) + _S[0];
+            int B = BytesToWord(input, inOff + 4) + _S[1];
+
+            for (int i = 1; i <= _noRounds; i++)
+            {
+                A = RotateLeft(A ^ B, B) + _S[2*i];
+                B = RotateLeft(B ^ A, A) + _S[2*i+1];
+            }
+
+            WordToBytes(A, outBytes, outOff);
+            WordToBytes(B, outBytes, outOff + 4);
+
+            return 2 * 4;
+        }
+
+        private int DecryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int A = BytesToWord(input, inOff);
+            int B = BytesToWord(input, inOff + 4);
+
+            for (int i = _noRounds; i >= 1; i--)
+            {
+                B = RotateRight(B - _S[2*i+1], A) ^ A;
+                A = RotateRight(A - _S[2*i],   B) ^ B;
+            }
+
+            WordToBytes(A - _S[0], outBytes, outOff);
+            WordToBytes(B - _S[1], outBytes, outOff + 4);
+
+            return 2 * 4;
+        }
+
+
+        //////////////////////////////////////////////////////////////
+        //
+        // PRIVATE Helper Methods
+        //
+        //////////////////////////////////////////////////////////////
+
+        /**
+        * Perform a left "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(32)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param  x  word to rotate
+        * @param  y    number of bits to rotate % 32
+        */
+        private int RotateLeft(int x, int y) {
+            return ((int)  (  (uint) (x << (y & (32-1))) |
+                              ((uint) x >> (32 - (y & (32-1)))) )
+                   );
+        }
+
+        /**
+        * Perform a right "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(32)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param  x  word to rotate
+        * @param  y    number of bits to rotate % 32
+        */
+        private int RotateRight(int x, int y) {
+            return ((int) (     ((uint) x >> (y & (32-1))) |
+                                (uint) (x << (32 - (y & (32-1))))   )
+                   );
+        }
+
+        private int BytesToWord(
+            byte[]  src,
+            int     srcOff)
+        {
+            return (src[srcOff] & 0xff) | ((src[srcOff + 1] & 0xff) << 8)
+                | ((src[srcOff + 2] & 0xff) << 16) | ((src[srcOff + 3] & 0xff) << 24);
+        }
+
+        private void WordToBytes(
+            int    word,
+            byte[]  dst,
+            int     dstOff)
+        {
+            dst[dstOff] = (byte)word;
+            dst[dstOff + 1] = (byte)(word >> 8);
+            dst[dstOff + 2] = (byte)(word >> 16);
+            dst[dstOff + 3] = (byte)(word >> 24);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC564Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC564Engine.cs
new file mode 100644
index 0000000..5c69d40
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC564Engine.cs
@@ -0,0 +1,295 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * The specification for RC5 came from the <code>RC5 Encryption Algorithm</code>
+    * publication in RSA CryptoBytes, Spring of 1995.
+    * <em>http://www.rsasecurity.com/rsalabs/cryptobytes</em>.
+    * <p>
+    * This implementation is set to work with a 64 bit word size.</p>
+    */
+    public class RC564Engine
+		: IBlockCipher
+    {
+        private static readonly int wordSize = 64;
+        private static readonly int bytesPerWord = wordSize / 8;
+
+        /*
+        * the number of rounds to perform
+        */
+        private int _noRounds;
+
+        /*
+        * the expanded key array of size 2*(rounds + 1)
+        */
+        private long [] _S;
+
+        /*
+        * our "magic constants" for wordSize 62
+        *
+        * Pw = Odd((e-2) * 2^wordsize)
+        * Qw = Odd((o-2) * 2^wordsize)
+        *
+        * where e is the base of natural logarithms (2.718281828...)
+        * and o is the golden ratio (1.61803398...)
+        */
+        private static readonly long P64 = unchecked( (long) 0xb7e151628aed2a6bL);
+        private static readonly long Q64 = unchecked( (long) 0x9e3779b97f4a7c15L);
+
+        private bool forEncryption;
+
+        /**
+        * Create an instance of the RC5 encryption algorithm
+        * and set some defaults
+        */
+        public RC564Engine()
+        {
+            _noRounds     = 12;
+//            _S            = null;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "RC5-64"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return 2 * bytesPerWord;
+        }
+
+        /**
+        * initialise a RC5-64 cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool             forEncryption,
+            ICipherParameters    parameters)
+        {
+            if (!(typeof(RC5Parameters).IsInstanceOfType(parameters)))
+            {
+                throw new ArgumentException("invalid parameter passed to RC564 init - " + parameters.GetType().ToString());
+            }
+
+            RC5Parameters       p = (RC5Parameters)parameters;
+
+            this.forEncryption = forEncryption;
+
+            _noRounds     = p.Rounds;
+
+            SetKey(p.GetKey());
+        }
+
+        public int ProcessBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  output,
+            int     outOff)
+        {
+            return (forEncryption) ? EncryptBlock(input, inOff, output, outOff)
+                                        : DecryptBlock(input, inOff, output, outOff);
+        }
+
+        public void Reset()
+        {
+        }
+
+        /**
+        * Re-key the cipher.
+        *
+        * @param  key  the key to be used
+        */
+        private void SetKey(
+            byte[]      key)
+        {
+            //
+            // KEY EXPANSION:
+            //
+            // There are 3 phases to the key expansion.
+            //
+            // Phase 1:
+            //   Copy the secret key K[0...b-1] into an array L[0..c-1] of
+            //   c = ceil(b/u), where u = wordSize/8 in little-endian order.
+            //   In other words, we fill up L using u consecutive key bytes
+            //   of K. Any unfilled byte positions in L are zeroed. In the
+            //   case that b = c = 0, set c = 1 and L[0] = 0.
+            //
+            long[]   L = new long[(key.Length + (bytesPerWord - 1)) / bytesPerWord];
+
+            for (int i = 0; i != key.Length; i++)
+            {
+                L[i / bytesPerWord] += (long)(key[i] & 0xff) << (8 * (i % bytesPerWord));
+            }
+
+            //
+            // Phase 2:
+            //   Initialize S to a particular fixed pseudo-random bit pattern
+            //   using an arithmetic progression modulo 2^wordsize determined
+            //   by the magic numbers, Pw & Qw.
+            //
+            _S            = new long[2*(_noRounds + 1)];
+
+            _S[0] = P64;
+            for (int i=1; i < _S.Length; i++)
+            {
+                _S[i] = (_S[i-1] + Q64);
+            }
+
+            //
+            // Phase 3:
+            //   Mix in the user's secret key in 3 passes over the arrays S & L.
+            //   The max of the arrays sizes is used as the loop control
+            //
+            int iter;
+
+            if (L.Length > _S.Length)
+            {
+                iter = 3 * L.Length;
+            }
+            else
+            {
+                iter = 3 * _S.Length;
+            }
+
+            long A = 0, B = 0;
+            int ii = 0, jj = 0;
+
+            for (int k = 0; k < iter; k++)
+            {
+                A = _S[ii] = RotateLeft(_S[ii] + A + B, 3);
+                B =  L[jj] = RotateLeft( L[jj] + A + B, A+B);
+                ii = (ii+1) % _S.Length;
+                jj = (jj+1) %  L.Length;
+            }
+        }
+
+        /**
+        * Encrypt the given block starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        *
+        * @param  in      in byte buffer containing data to encrypt
+        * @param  inOff   offset into src buffer
+        * @param  out     out buffer where encrypted data is written
+        * @param  outOff  offset into out buffer
+        */
+        private int EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            long A = BytesToWord(input, inOff) + _S[0];
+            long B = BytesToWord(input, inOff + bytesPerWord) + _S[1];
+
+            for (int i = 1; i <= _noRounds; i++)
+            {
+                A = RotateLeft(A ^ B, B) + _S[2*i];
+                B = RotateLeft(B ^ A, A) + _S[2*i+1];
+            }
+
+            WordToBytes(A, outBytes, outOff);
+            WordToBytes(B, outBytes, outOff + bytesPerWord);
+
+            return 2 * bytesPerWord;
+        }
+
+        private int DecryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            long A = BytesToWord(input, inOff);
+            long B = BytesToWord(input, inOff + bytesPerWord);
+
+            for (int i = _noRounds; i >= 1; i--)
+            {
+                B = RotateRight(B - _S[2*i+1], A) ^ A;
+                A = RotateRight(A - _S[2*i],   B) ^ B;
+            }
+
+            WordToBytes(A - _S[0], outBytes, outOff);
+            WordToBytes(B - _S[1], outBytes, outOff + bytesPerWord);
+
+            return 2 * bytesPerWord;
+        }
+
+
+        //////////////////////////////////////////////////////////////
+        //
+        // PRIVATE Helper Methods
+        //
+        //////////////////////////////////////////////////////////////
+
+        /**
+        * Perform a left "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param  x  word to rotate
+        * @param  y    number of bits to rotate % wordSize
+        */
+        private long RotateLeft(long x, long y) {
+            return ((long) (    (ulong) (x << (int) (y & (wordSize-1))) |
+                                ((ulong) x >> (int) (wordSize - (y & (wordSize-1)))))
+                   );
+        }
+
+        /**
+        * Perform a right "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param x word to rotate
+        * @param y number of bits to rotate % wordSize
+        */
+        private long RotateRight(long x, long y) {
+            return ((long) (    ((ulong) x >> (int) (y & (wordSize-1))) |
+                                (ulong) (x << (int) (wordSize - (y & (wordSize-1)))))
+                   );
+        }
+
+        private long BytesToWord(
+            byte[]  src,
+            int     srcOff)
+        {
+            long    word = 0;
+
+            for (int i = bytesPerWord - 1; i >= 0; i--)
+            {
+                word = (word << 8) + (src[i + srcOff] & 0xff);
+            }
+
+            return word;
+        }
+
+        private void WordToBytes(
+            long    word,
+            byte[]  dst,
+            int     dstOff)
+        {
+            for (int i = 0; i < bytesPerWord; i++)
+            {
+                dst[i + dstOff] = (byte)word;
+                word = (long) ((ulong) word >> 8);
+            }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RC6Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RC6Engine.cs
new file mode 100644
index 0000000..d72cc2f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RC6Engine.cs
@@ -0,0 +1,362 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * An RC6 engine.
+    */
+    public class RC6Engine
+		: IBlockCipher
+    {
+        private static readonly int wordSize = 32;
+        private static readonly int bytesPerWord = wordSize / 8;
+
+        /*
+        * the number of rounds to perform
+        */
+        private static readonly int _noRounds = 20;
+
+        /*
+        * the expanded key array of size 2*(rounds + 1)
+        */
+        private int [] _S;
+
+        /*
+        * our "magic constants" for wordSize 32
+        *
+        * Pw = Odd((e-2) * 2^wordsize)
+        * Qw = Odd((o-2) * 2^wordsize)
+        *
+        * where e is the base of natural logarithms (2.718281828...)
+        * and o is the golden ratio (1.61803398...)
+        */
+        private static readonly int    P32 = unchecked((int) 0xb7e15163);
+        private static readonly int    Q32 = unchecked((int) 0x9e3779b9);
+
+        private static readonly int    LGW = 5;        // log2(32)
+
+        private bool forEncryption;
+
+        /**
+        * Create an instance of the RC6 encryption algorithm
+        * and set some defaults
+        */
+        public RC6Engine()
+        {
+//            _S            = null;
+        }
+
+        public string AlgorithmName
+        {
+            get { return "RC6"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return 4 * bytesPerWord;
+        }
+
+        /**
+        * initialise a RC5-32 cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+                throw new ArgumentException("invalid parameter passed to RC6 init - " + parameters.GetType().ToString());
+
+            this.forEncryption = forEncryption;
+
+			KeyParameter p = (KeyParameter)parameters;
+			SetKey(p.GetKey());
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+			int blockSize = GetBlockSize();
+			if (_S == null)
+				throw new InvalidOperationException("RC6 engine not initialised");
+			if ((inOff + blockSize) > input.Length)
+				throw new DataLengthException("input buffer too short");
+			if ((outOff + blockSize) > output.Length)
+				throw new DataLengthException("output buffer too short");
+
+			return (forEncryption)
+				?	EncryptBlock(input, inOff, output, outOff)
+				:	DecryptBlock(input, inOff, output, outOff);
+        }
+
+		public void Reset()
+        {
+        }
+
+        /**
+        * Re-key the cipher.
+        *
+        * @param inKey the key to be used
+        */
+        private void SetKey(
+            byte[] key)
+        {
+            //
+            // KEY EXPANSION:
+            //
+            // There are 3 phases to the key expansion.
+            //
+            // Phase 1:
+            //   Copy the secret key K[0...b-1] into an array L[0..c-1] of
+            //   c = ceil(b/u), where u = wordSize/8 in little-endian order.
+            //   In other words, we fill up L using u consecutive key bytes
+            //   of K. Any unfilled byte positions in L are zeroed. In the
+            //   case that b = c = 0, set c = 1 and L[0] = 0.
+            //
+            // compute number of dwords
+            int c = (key.Length + (bytesPerWord - 1)) / bytesPerWord;
+            if (c == 0)
+            {
+                c = 1;
+            }
+            int[]   L = new int[(key.Length + bytesPerWord - 1) / bytesPerWord];
+
+            // load all key bytes into array of key dwords
+            for (int i = key.Length - 1; i >= 0; i--)
+            {
+                L[i / bytesPerWord] = (L[i / bytesPerWord] << 8) + (key[i] & 0xff);
+            }
+
+            //
+            // Phase 2:
+            //   Key schedule is placed in a array of 2+2*ROUNDS+2 = 44 dwords.
+            //   Initialize S to a particular fixed pseudo-random bit pattern
+            //   using an arithmetic progression modulo 2^wordsize determined
+            //   by the magic numbers, Pw & Qw.
+            //
+            _S            = new int[2+2*_noRounds+2];
+
+            _S[0] = P32;
+            for (int i=1; i < _S.Length; i++)
+            {
+                _S[i] = (_S[i-1] + Q32);
+            }
+
+            //
+            // Phase 3:
+            //   Mix in the user's secret key in 3 passes over the arrays S & L.
+            //   The max of the arrays sizes is used as the loop control
+            //
+            int iter;
+
+            if (L.Length > _S.Length)
+            {
+                iter = 3 * L.Length;
+            }
+            else
+            {
+                iter = 3 * _S.Length;
+            }
+
+            int A = 0;
+            int B = 0;
+            int ii = 0, jj = 0;
+
+            for (int k = 0; k < iter; k++)
+            {
+                A = _S[ii] = RotateLeft(_S[ii] + A + B, 3);
+                B =  L[jj] = RotateLeft( L[jj] + A + B, A+B);
+                ii = (ii+1) % _S.Length;
+                jj = (jj+1) %  L.Length;
+            }
+        }
+
+        private int EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            // load A,B,C and D registers from in.
+            int A = BytesToWord(input, inOff);
+            int B = BytesToWord(input, inOff + bytesPerWord);
+            int C = BytesToWord(input, inOff + bytesPerWord*2);
+            int D = BytesToWord(input, inOff + bytesPerWord*3);
+
+            // Do pseudo-round #0: pre-whitening of B and D
+            B += _S[0];
+            D += _S[1];
+
+            // perform round #1,#2 ... #ROUNDS of encryption
+            for (int i = 1; i <= _noRounds; i++)
+            {
+                int t = 0,u = 0;
+
+                t = B*(2*B+1);
+                t = RotateLeft(t,5);
+
+                u = D*(2*D+1);
+                u = RotateLeft(u,5);
+
+                A ^= t;
+                A = RotateLeft(A,u);
+                A += _S[2*i];
+
+                C ^= u;
+                C = RotateLeft(C,t);
+                C += _S[2*i+1];
+
+                int temp = A;
+                A = B;
+                B = C;
+                C = D;
+                D = temp;
+            }
+            // do pseudo-round #(ROUNDS+1) : post-whitening of A and C
+            A += _S[2*_noRounds+2];
+            C += _S[2*_noRounds+3];
+
+            // store A, B, C and D registers to out
+            WordToBytes(A, outBytes, outOff);
+            WordToBytes(B, outBytes, outOff + bytesPerWord);
+            WordToBytes(C, outBytes, outOff + bytesPerWord*2);
+            WordToBytes(D, outBytes, outOff + bytesPerWord*3);
+
+            return 4 * bytesPerWord;
+        }
+
+        private int DecryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            // load A,B,C and D registers from out.
+            int A = BytesToWord(input, inOff);
+            int B = BytesToWord(input, inOff + bytesPerWord);
+            int C = BytesToWord(input, inOff + bytesPerWord*2);
+            int D = BytesToWord(input, inOff + bytesPerWord*3);
+
+            // Undo pseudo-round #(ROUNDS+1) : post whitening of A and C
+            C -= _S[2*_noRounds+3];
+            A -= _S[2*_noRounds+2];
+
+            // Undo round #ROUNDS, .., #2,#1 of encryption
+            for (int i = _noRounds; i >= 1; i--)
+            {
+                int t=0,u = 0;
+
+                int temp = D;
+                D = C;
+                C = B;
+                B = A;
+                A = temp;
+
+                t = B*(2*B+1);
+                t = RotateLeft(t, LGW);
+
+                u = D*(2*D+1);
+                u = RotateLeft(u, LGW);
+
+                C -= _S[2*i+1];
+                C = RotateRight(C,t);
+                C ^= u;
+
+                A -= _S[2*i];
+                A = RotateRight(A,u);
+                A ^= t;
+
+            }
+            // Undo pseudo-round #0: pre-whitening of B and D
+            D -= _S[1];
+            B -= _S[0];
+
+            WordToBytes(A, outBytes, outOff);
+            WordToBytes(B, outBytes, outOff + bytesPerWord);
+            WordToBytes(C, outBytes, outOff + bytesPerWord*2);
+            WordToBytes(D, outBytes, outOff + bytesPerWord*3);
+
+            return 4 * bytesPerWord;
+        }
+
+
+        //////////////////////////////////////////////////////////////
+        //
+        // PRIVATE Helper Methods
+        //
+        //////////////////////////////////////////////////////////////
+
+        /**
+        * Perform a left "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param x word to rotate
+        * @param y number of bits to rotate % wordSize
+        */
+        private int RotateLeft(int x, int y)
+        {
+            return ((int)((uint)(x << (y & (wordSize-1)))
+				| ((uint) x >> (wordSize - (y & (wordSize-1))))));
+        }
+
+        /**
+        * Perform a right "spin" of the word. The rotation of the given
+        * word <em>x</em> is rotated left by <em>y</em> bits.
+        * Only the <em>lg(wordSize)</em> low-order bits of <em>y</em>
+        * are used to determine the rotation amount. Here it is
+        * assumed that the wordsize used is a power of 2.
+        *
+        * @param x word to rotate
+        * @param y number of bits to rotate % wordSize
+        */
+        private int RotateRight(int x, int y) 
+		{
+            return ((int)(((uint) x >> (y & (wordSize-1)))
+				| (uint)(x << (wordSize - (y & (wordSize-1))))));
+        }
+
+        private int BytesToWord(
+            byte[]	src,
+            int		srcOff)
+        {
+            int word = 0;
+
+            for (int i = bytesPerWord - 1; i >= 0; i--)
+            {
+                word = (word << 8) + (src[i + srcOff] & 0xff);
+            }
+
+            return word;
+        }
+
+        private void WordToBytes(
+            int		word,
+            byte[]	dst,
+            int		dstOff)
+        {
+            for (int i = 0; i < bytesPerWord; i++)
+            {
+                dst[i + dstOff] = (byte)word;
+                word = (int) ((uint) word >> 8);
+            }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RFC3211WrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RFC3211WrapEngine.cs
new file mode 100644
index 0000000..e520075
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RFC3211WrapEngine.cs
@@ -0,0 +1,168 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	 * an implementation of the RFC 3211 Key Wrap
+	 * Specification.
+	 */
+	public class Rfc3211WrapEngine
+		: IWrapper
+	{
+		private CbcBlockCipher		engine;
+		private ParametersWithIV	param;
+		private bool				forWrapping;
+		private SecureRandom		rand;
+
+		public Rfc3211WrapEngine(
+			IBlockCipher engine)
+		{
+			this.engine = new CbcBlockCipher(engine);
+		}
+
+		public void Init(
+			bool				forWrapping,
+			ICipherParameters	param)
+		{
+			this.forWrapping = forWrapping;
+
+			if (param is ParametersWithRandom)
+			{
+				ParametersWithRandom p = (ParametersWithRandom) param;
+
+				this.rand = p.Random;
+				this.param = (ParametersWithIV) p.Parameters;
+			}
+			else
+			{
+				if (forWrapping)
+				{
+					rand = new SecureRandom();
+				}
+
+				this.param = (ParametersWithIV) param;
+			}
+		}
+
+		public string AlgorithmName
+		{
+			get { return engine.GetUnderlyingCipher().AlgorithmName + "/RFC3211Wrap"; }
+		}
+
+		public byte[] Wrap(
+			byte[]	inBytes,
+			int		inOff,
+			int		inLen)
+		{
+			if (!forWrapping)
+			{
+				throw new InvalidOperationException("not set for wrapping");
+			}
+
+			engine.Init(true, param);
+
+			int blockSize = engine.GetBlockSize();
+			byte[] cekBlock;
+
+			if (inLen + 4 < blockSize * 2)
+			{
+				cekBlock = new byte[blockSize * 2];
+			}
+			else
+			{
+				cekBlock = new byte[(inLen + 4) % blockSize == 0 ? inLen + 4 : ((inLen + 4) / blockSize + 1) * blockSize];
+			}
+
+			cekBlock[0] = (byte)inLen;
+			cekBlock[1] = (byte)~inBytes[inOff];
+			cekBlock[2] = (byte)~inBytes[inOff + 1];
+			cekBlock[3] = (byte)~inBytes[inOff + 2];
+
+			Array.Copy(inBytes, inOff, cekBlock, 4, inLen);
+
+			rand.NextBytes(cekBlock, inLen + 4, cekBlock.Length - inLen - 4);
+
+			for (int i = 0; i < cekBlock.Length; i += blockSize)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);
+			}
+
+			for (int i = 0; i < cekBlock.Length; i += blockSize)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);
+			}
+
+			return cekBlock;
+		}
+
+		public byte[] Unwrap(
+			byte[]	inBytes,
+			int		inOff,
+			int		inLen)
+		{
+			if (forWrapping)
+			{
+				throw new InvalidOperationException("not set for unwrapping");
+			}
+
+			int blockSize = engine.GetBlockSize();
+
+			if (inLen < 2 * blockSize)
+			{
+				throw new InvalidCipherTextException("input too short");
+			}
+
+			byte[] cekBlock = new byte[inLen];
+			byte[] iv = new byte[blockSize];
+
+			Array.Copy(inBytes, inOff, cekBlock, 0, inLen);
+			Array.Copy(inBytes, inOff, iv, 0, iv.Length);
+
+			engine.Init(false, new ParametersWithIV(param.Parameters, iv));
+
+			for (int i = blockSize; i < cekBlock.Length; i += blockSize)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);    
+			}
+
+			Array.Copy(cekBlock, cekBlock.Length - iv.Length, iv, 0, iv.Length);
+
+			engine.Init(false, new ParametersWithIV(param.Parameters, iv));
+
+			engine.ProcessBlock(cekBlock, 0, cekBlock, 0);
+
+			engine.Init(false, param);
+
+			for (int i = 0; i < cekBlock.Length; i += blockSize)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);
+			}
+
+			if ((cekBlock[0] & 0xff) > cekBlock.Length - 4)
+			{
+				throw new InvalidCipherTextException("wrapped key corrupted");
+			}
+
+			byte[] key = new byte[cekBlock[0] & 0xff];
+
+			Array.Copy(cekBlock, 4, key, 0, cekBlock[0]);
+
+			// Note: Using constant time comparison
+			int nonEqual = 0;
+			for (int i = 0; i != 3; i++)
+			{
+				byte check = (byte)~cekBlock[1 + i];
+				nonEqual |= (check ^ key[i]);
+			}
+
+			if (nonEqual != 0)
+				throw new InvalidCipherTextException("wrapped key fails checksum");
+
+			return key;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RFC3394WrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RFC3394WrapEngine.cs
new file mode 100644
index 0000000..5615a63
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RFC3394WrapEngine.cs
@@ -0,0 +1,178 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <remarks>
+	/// An implementation of the AES Key Wrapper from the NIST Key Wrap
+	/// Specification as described in RFC 3394.
+	/// <p/>
+	/// For further details see: <a href="http://www.ietf.org/rfc/rfc3394.txt">http://www.ietf.org/rfc/rfc3394.txt</a>
+	/// and  <a href="http://csrc.nist.gov/encryption/kms/key-wrap.pdf">http://csrc.nist.gov/encryption/kms/key-wrap.pdf</a>.
+	/// </remarks>
+	public class Rfc3394WrapEngine
+		: IWrapper
+	{
+		private readonly IBlockCipher engine;
+
+		private KeyParameter	param;
+		private bool			forWrapping;
+
+		private byte[] iv =
+		{
+			0xa6, 0xa6, 0xa6, 0xa6,
+			0xa6, 0xa6, 0xa6, 0xa6
+		};
+
+		public Rfc3394WrapEngine(
+			IBlockCipher engine)
+		{
+			this.engine = engine;
+		}
+
+		public void Init(
+			bool				forWrapping,
+			ICipherParameters	parameters)
+		{
+			this.forWrapping = forWrapping;
+
+			if (parameters is ParametersWithRandom)
+			{
+				parameters = ((ParametersWithRandom) parameters).Parameters;
+			}
+
+			if (parameters is KeyParameter)
+			{
+				this.param = (KeyParameter) parameters;
+			}
+			else if (parameters is ParametersWithIV)
+			{
+				ParametersWithIV pIV = (ParametersWithIV) parameters;
+				byte[] iv = pIV.GetIV();
+
+				if (iv.Length != 8)
+					throw new ArgumentException("IV length not equal to 8", "parameters");
+
+				this.iv = iv;
+				this.param = (KeyParameter) pIV.Parameters;
+			}
+			else
+			{
+				// TODO Throw an exception for bad parameters?
+			}
+		}
+
+		public string AlgorithmName
+		{
+			get { return engine.AlgorithmName; }
+		}
+
+		public byte[] Wrap(
+			byte[]	input,
+			int		inOff,
+			int		inLen)
+		{
+			if (!forWrapping)
+			{
+				throw new InvalidOperationException("not set for wrapping");
+			}
+
+			int n = inLen / 8;
+
+			if ((n * 8) != inLen)
+			{
+				throw new DataLengthException("wrap data must be a multiple of 8 bytes");
+			}
+
+			byte[] block = new byte[inLen + iv.Length];
+			byte[] buf = new byte[8 + iv.Length];
+
+			Array.Copy(iv, 0, block, 0, iv.Length);
+			Array.Copy(input, inOff, block, iv.Length, inLen);
+
+			engine.Init(true, param);
+
+			for (int j = 0; j != 6; j++)
+			{
+				for (int i = 1; i <= n; i++)
+				{
+					Array.Copy(block, 0, buf, 0, iv.Length);
+					Array.Copy(block, 8 * i, buf, iv.Length, 8);
+					engine.ProcessBlock(buf, 0, buf, 0);
+
+					int t = n * j + i;
+					for (int k = 1; t != 0; k++)
+					{
+						byte v = (byte)t;
+
+						buf[iv.Length - k] ^= v;
+						t = (int) ((uint)t >> 8);
+					}
+
+					Array.Copy(buf, 0, block, 0, 8);
+					Array.Copy(buf, 8, block, 8 * i, 8);
+				}
+			}
+
+			return block;
+		}
+
+		public byte[] Unwrap(
+			byte[]  input,
+			int     inOff,
+			int     inLen)
+		{
+			if (forWrapping)
+			{
+				throw new InvalidOperationException("not set for unwrapping");
+			}
+
+			int n = inLen / 8;
+
+			if ((n * 8) != inLen)
+			{
+				throw new InvalidCipherTextException("unwrap data must be a multiple of 8 bytes");
+			}
+
+			byte[]  block = new byte[inLen - iv.Length];
+			byte[]  a = new byte[iv.Length];
+			byte[]  buf = new byte[8 + iv.Length];
+
+			Array.Copy(input, inOff, a, 0, iv.Length);
+            Array.Copy(input, inOff + iv.Length, block, 0, inLen - iv.Length);
+
+			engine.Init(false, param);
+
+			n = n - 1;
+
+			for (int j = 5; j >= 0; j--)
+			{
+				for (int i = n; i >= 1; i--)
+				{
+					Array.Copy(a, 0, buf, 0, iv.Length);
+					Array.Copy(block, 8 * (i - 1), buf, iv.Length, 8);
+
+					int t = n * j + i;
+					for (int k = 1; t != 0; k++)
+					{
+						byte v = (byte)t;
+
+						buf[iv.Length - k] ^= v;
+						t = (int) ((uint)t >> 8);
+					}
+
+					engine.ProcessBlock(buf, 0, buf, 0);
+					Array.Copy(buf, 0, a, 0, 8);
+					Array.Copy(buf, 8, block, 8 * (i - 1), 8);
+				}
+			}
+
+			if (!Arrays.ConstantTimeAreEqual(a, iv))
+				throw new InvalidCipherTextException("checksum failed");
+
+			return block;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindedEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindedEngine.cs
new file mode 100644
index 0000000..cdf69dd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindedEngine.cs
@@ -0,0 +1,124 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	 * this does your basic RSA algorithm with blinding
+	 */
+	public class RsaBlindedEngine
+		: IAsymmetricBlockCipher
+	{
+		private readonly RsaCoreEngine core = new RsaCoreEngine();
+		private RsaKeyParameters key;
+		private SecureRandom random;
+
+		public string AlgorithmName
+		{
+			get { return "RSA"; }
+		}
+
+		/**
+		 * initialise the RSA engine.
+		 *
+		 * @param forEncryption true if we are encrypting, false otherwise.
+		 * @param param the necessary RSA key parameters.
+		 */
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	param)
+		{
+			core.Init(forEncryption, param);
+
+			if (param is ParametersWithRandom)
+			{
+				ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+				key = (RsaKeyParameters)rParam.Parameters;
+				random = rParam.Random;
+			}
+			else
+			{
+				key = (RsaKeyParameters)param;
+				random = new SecureRandom();
+			}
+		}
+
+		/**
+		 * Return the maximum size for an input block to this engine.
+		 * For RSA this is always one byte less than the key size on
+		 * encryption, and the same length as the key size on decryption.
+		 *
+		 * @return maximum size for an input block.
+		 */
+		public int GetInputBlockSize()
+		{
+			return core.GetInputBlockSize();
+		}
+
+		/**
+		 * Return the maximum size for an output block to this engine.
+		 * For RSA this is always one byte less than the key size on
+		 * decryption, and the same length as the key size on encryption.
+		 *
+		 * @return maximum size for an output block.
+		 */
+		public int GetOutputBlockSize()
+		{
+			return core.GetOutputBlockSize();
+		}
+
+		/**
+		 * Process a single block using the basic RSA algorithm.
+		 *
+		 * @param inBuf the input array.
+		 * @param inOff the offset into the input buffer where the data starts.
+		 * @param inLen the length of the data to be processed.
+		 * @return the result of the RSA process.
+		 * @exception DataLengthException the input block is too large.
+		 */
+		public byte[] ProcessBlock(
+			byte[]	inBuf,
+			int		inOff,
+			int		inLen)
+		{
+			if (key == null)
+				throw new InvalidOperationException("RSA engine not initialised");
+
+			BigInteger input = core.ConvertInput(inBuf, inOff, inLen);
+
+			BigInteger result;
+			if (key is RsaPrivateCrtKeyParameters)
+			{
+				RsaPrivateCrtKeyParameters k = (RsaPrivateCrtKeyParameters)key;
+				BigInteger e = k.PublicExponent;
+				if (e != null)   // can't do blinding without a public exponent
+				{
+					BigInteger m = k.Modulus;
+					BigInteger r = BigIntegers.CreateRandomInRange(
+						BigInteger.One, m.Subtract(BigInteger.One), random);
+
+					BigInteger blindedInput = r.ModPow(e, m).Multiply(input).Mod(m);
+					BigInteger blindedResult = core.ProcessBlock(blindedInput);
+
+					BigInteger rInv = r.ModInverse(m);
+					result = blindedResult.Multiply(rInv).Mod(m);
+				}
+				else
+				{
+					result = core.ProcessBlock(input);
+				}
+			}
+			else
+			{
+				result = core.ProcessBlock(input);
+			}
+
+			return core.ConvertOutput(result);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindingEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindingEngine.cs
new file mode 100644
index 0000000..76b57a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RSABlindingEngine.cs
@@ -0,0 +1,139 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* This does your basic RSA Chaum's blinding and unblinding as outlined in
+	* "Handbook of Applied Cryptography", page 475. You need to use this if you are
+	* trying to get another party to generate signatures without them being aware
+	* of the message they are signing.
+	*/
+	public class RsaBlindingEngine
+		: IAsymmetricBlockCipher
+	{
+		private readonly RsaCoreEngine core = new RsaCoreEngine();
+
+		private RsaKeyParameters key;
+		private BigInteger blindingFactor;
+
+		private bool forEncryption;
+
+		public string AlgorithmName
+		{
+			get { return "RSA"; }
+		}
+
+		/**
+		* Initialise the blinding engine.
+		*
+		* @param forEncryption true if we are encrypting (blinding), false otherwise.
+		* @param param         the necessary RSA key parameters.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	param)
+		{
+			RsaBlindingParameters p;
+
+			if (param is ParametersWithRandom)
+			{
+				ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+				p = (RsaBlindingParameters)rParam.Parameters;
+			}
+			else
+			{
+				p = (RsaBlindingParameters)param;
+			}
+
+			core.Init(forEncryption, p.PublicKey);
+
+			this.forEncryption = forEncryption;
+			this.key = p.PublicKey;
+			this.blindingFactor = p.BlindingFactor;
+		}
+
+		/**
+		* Return the maximum size for an input block to this engine.
+		* For RSA this is always one byte less than the key size on
+		* encryption, and the same length as the key size on decryption.
+		*
+		* @return maximum size for an input block.
+		*/
+		public int GetInputBlockSize()
+		{
+			return core.GetInputBlockSize();
+		}
+
+		/**
+		* Return the maximum size for an output block to this engine.
+		* For RSA this is always one byte less than the key size on
+		* decryption, and the same length as the key size on encryption.
+		*
+		* @return maximum size for an output block.
+		*/
+		public int GetOutputBlockSize()
+		{
+			return core.GetOutputBlockSize();
+		}
+
+		/**
+		* Process a single block using the RSA blinding algorithm.
+		*
+		* @param in    the input array.
+		* @param inOff the offset into the input buffer where the data starts.
+		* @param inLen the length of the data to be processed.
+		* @return the result of the RSA process.
+		* @throws DataLengthException the input block is too large.
+		*/
+		public byte[] ProcessBlock(
+			byte[]	inBuf,
+			int		inOff,
+			int		inLen)
+		{
+			BigInteger msg = core.ConvertInput(inBuf, inOff, inLen);
+
+			if (forEncryption)
+			{
+				msg = BlindMessage(msg);
+			}
+			else
+			{
+				msg = UnblindMessage(msg);
+			}
+
+			return core.ConvertOutput(msg);
+		}
+
+		/*
+		* Blind message with the blind factor.
+		*/
+		private BigInteger BlindMessage(
+			BigInteger msg)
+		{
+			BigInteger blindMsg = blindingFactor;
+			blindMsg = msg.Multiply(blindMsg.ModPow(key.Exponent, key.Modulus));
+			blindMsg = blindMsg.Mod(key.Modulus);
+
+			return blindMsg;
+		}
+
+		/*
+		* Unblind the message blinded with the blind factor.
+		*/
+		private BigInteger UnblindMessage(
+			BigInteger blindedMsg)
+		{
+			BigInteger m = key.Modulus;
+			BigInteger msg = blindedMsg;
+			BigInteger blindFactorInverse = blindingFactor.ModInverse(m);
+			msg = msg.Multiply(blindFactorInverse);
+			msg = msg.Mod(m);
+
+			return msg;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RSACoreEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RSACoreEngine.cs
new file mode 100644
index 0000000..4e64d25
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RSACoreEngine.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* this does your basic RSA algorithm.
+	*/
+	class RsaCoreEngine
+	{
+		private RsaKeyParameters	key;
+		private bool				forEncryption;
+		private int					bitSize;
+
+		/**
+		* initialise the RSA engine.
+		*
+		* @param forEncryption true if we are encrypting, false otherwise.
+		* @param param the necessary RSA key parameters.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithRandom)
+			{
+				parameters = ((ParametersWithRandom) parameters).Parameters;
+			}
+
+			if (!(parameters is RsaKeyParameters))
+				throw new InvalidKeyException("Not an RSA key");
+
+			this.key = (RsaKeyParameters) parameters;
+			this.forEncryption = forEncryption;
+			this.bitSize = key.Modulus.BitLength;
+		}
+
+		/**
+		* Return the maximum size for an input block to this engine.
+		* For RSA this is always one byte less than the key size on
+		* encryption, and the same length as the key size on decryption.
+		*
+		* @return maximum size for an input block.
+		*/
+		public int GetInputBlockSize()
+		{
+			if (forEncryption)
+			{
+				return (bitSize - 1) / 8;
+			}
+
+			return (bitSize + 7) / 8;
+		}
+
+		/**
+		* Return the maximum size for an output block to this engine.
+		* For RSA this is always one byte less than the key size on
+		* decryption, and the same length as the key size on encryption.
+		*
+		* @return maximum size for an output block.
+		*/
+		public int GetOutputBlockSize()
+		{
+			if (forEncryption)
+			{
+				return (bitSize + 7) / 8;
+			}
+
+			return (bitSize - 1) / 8;
+		}
+
+		public BigInteger ConvertInput(
+			byte[]	inBuf,
+			int		inOff,
+			int		inLen)
+		{
+			int maxLength = (bitSize + 7) / 8;
+
+			if (inLen > maxLength)
+				throw new DataLengthException("input too large for RSA cipher.");
+
+			BigInteger input = new BigInteger(1, inBuf, inOff, inLen);
+
+			if (input.CompareTo(key.Modulus) >= 0)
+				throw new DataLengthException("input too large for RSA cipher.");
+
+			return input;
+		}
+
+		public byte[] ConvertOutput(
+			BigInteger result)
+		{
+			byte[] output = result.ToByteArrayUnsigned();
+
+			if (forEncryption)
+			{
+				int outSize = GetOutputBlockSize();
+
+				// TODO To avoid this, create version of BigInteger.ToByteArray that
+				// writes to an existing array
+				if (output.Length < outSize) // have ended up with less bytes than normal, lengthen
+				{
+					byte[] tmp = new byte[outSize];
+					output.CopyTo(tmp, tmp.Length - output.Length);
+					output = tmp;
+				}
+			}
+
+			return output;
+		}
+
+		public BigInteger ProcessBlock(
+			BigInteger input)
+		{
+			if (key is RsaPrivateCrtKeyParameters)
+			{
+				//
+				// we have the extra factors, use the Chinese Remainder Theorem - the author
+				// wishes to express his thanks to Dirk Bonekaemper at rtsffm.com for
+				// advice regarding the expression of this.
+				//
+				RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters)key;
+
+				BigInteger p = crtKey.P;;
+				BigInteger q = crtKey.Q;
+				BigInteger dP = crtKey.DP;
+				BigInteger dQ = crtKey.DQ;
+				BigInteger qInv = crtKey.QInv;
+
+				BigInteger mP, mQ, h, m;
+
+				// mP = ((input Mod p) ^ dP)) Mod p
+				mP = (input.Remainder(p)).ModPow(dP, p);
+
+				// mQ = ((input Mod q) ^ dQ)) Mod q
+				mQ = (input.Remainder(q)).ModPow(dQ, q);
+
+				// h = qInv * (mP - mQ) Mod p
+				h = mP.Subtract(mQ);
+				h = h.Multiply(qInv);
+				h = h.Mod(p);               // Mod (in Java) returns the positive residual
+
+				// m = h * q + mQ
+				m = h.Multiply(q);
+				m = m.Add(mQ);
+
+				return m;
+			}
+
+			return input.ModPow(key.Exponent, key.Modulus);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RijndaelEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RijndaelEngine.cs
new file mode 100644
index 0000000..df2e5ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RijndaelEngine.cs
@@ -0,0 +1,747 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* an implementation of Rijndael, based on the documentation and reference implementation
+	* by Paulo Barreto, Vincent Rijmen, for v2.0 August '99.
+	* <p>
+	* Note: this implementation is based on information prior to readonly NIST publication.
+	* </p>
+	*/
+	public class RijndaelEngine
+		: IBlockCipher
+	{
+		private static readonly int MAXROUNDS = 14;
+
+		private static readonly int MAXKC = (256/4);
+
+		private static readonly byte[] Logtable =
+		{
+			0,    0,    25,   1,    50,   2,    26,   198,
+			75,   199,  27,   104,  51,   238,  223,  3,
+			100,  4,    224,  14,   52,   141,  129,  239,
+			76,   113,  8,    200,  248,  105,  28,   193,
+			125,  194,  29,   181,  249,  185,  39,   106,
+			77,   228,  166,  114,  154,  201,  9,    120,
+			101,  47,   138,  5,    33,   15,   225,  36,
+			18,   240,  130,  69,   53,   147,  218,  142,
+			150,  143,  219,  189,  54,   208,  206,  148,
+			19,   92,   210,  241,  64,   70,   131,  56,
+			102,  221,  253,  48,   191,  6,    139,  98,
+			179,  37,   226,  152,  34,   136,  145,  16,
+			126,  110,  72,   195,  163,  182,  30,   66,
+			58,   107,  40,   84,   250,  133,  61,   186,
+			43,   121,  10,   21,   155,  159,  94,   202,
+			78,   212,  172,  229,  243,  115,  167,  87,
+			175,  88,   168,  80,   244,  234,  214,  116,
+			79,   174,  233,  213,  231,  230,  173,  232,
+			44,   215,  117,  122,  235,  22,   11,   245,
+			89,   203,  95,   176,  156,  169,  81,   160,
+			127,  12,   246,  111,  23,   196,  73,   236,
+			216,  67,   31,   45,   164,  118,  123,  183,
+			204,  187,  62,   90,   251,  96,   177,  134,
+			59,   82,   161,  108,  170,  85,   41,   157,
+			151,  178,  135,  144,  97,   190,  220,  252,
+			188,  149,  207,  205,  55,   63,   91,   209,
+			83,   57,   132,  60,   65,   162,  109,  71,
+			20,   42,   158,  93,   86,   242,  211,  171,
+			68,   17,   146,  217,  35,   32,   46,   137,
+			180,  124,  184,  38,   119,  153,  227,  165,
+			103,  74,   237,  222,  197,  49,   254,  24,
+			13,   99,   140,  128,  192,  247,  112,  7
+		};
+
+		private static readonly byte[] Alogtable =
+		{
+			0,   3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,  19,  53,
+			95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,  30,  34, 102, 170,
+			229,  52,  92, 228,  55,  89, 235,  38, 106, 190, 217, 112, 144, 171, 230,  49,
+			83, 245,   4,  12,  20,  60,  68, 204,  79, 209, 104, 184, 211, 110, 178, 205,
+			76, 212, 103, 169, 224,  59,  77, 215,  98, 166, 241,   8,  24,  40, 120, 136,
+			131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154,
+			181, 196,  87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
+			254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,  96, 160,
+			251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86, 250,  21,  63,  65,
+			195,  94, 226,  61,  71, 201,  64, 192,  91, 237,  44, 116, 156, 191, 218, 117,
+			159, 186, 213, 100, 172, 239,  42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+			155, 182, 193,  88, 232,  35, 101, 175, 234,  37, 111, 177, 200,  67, 197,  84,
+			252,  31,  33,  99, 165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,
+			69, 207,  74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
+			18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,  13,  23,
+			57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180, 199,  82, 246,   1,
+			3,   5,  15,  17,  51,  85, 255,  26,  46, 114, 150, 161, 248,  19,  53,
+			95, 225,  56,  72, 216, 115, 149, 164, 247,   2,   6,  10,  30,  34, 102, 170,
+			229,  52,  92, 228,  55,  89, 235,  38, 106, 190, 217, 112, 144, 171, 230,  49,
+			83, 245,   4,  12,  20,  60,  68, 204,  79, 209, 104, 184, 211, 110, 178, 205,
+			76, 212, 103, 169, 224,  59,  77, 215,  98, 166, 241,   8,  24,  40, 120, 136,
+			131, 158, 185, 208, 107, 189, 220, 127, 129, 152, 179, 206,  73, 219, 118, 154,
+			181, 196,  87, 249,  16,  48,  80, 240,  11,  29,  39, 105, 187, 214,  97, 163,
+			254,  25,  43, 125, 135, 146, 173, 236,  47, 113, 147, 174, 233,  32,  96, 160,
+			251,  22,  58,  78, 210, 109, 183, 194,  93, 231,  50,  86, 250,  21,  63,  65,
+			195,  94, 226,  61,  71, 201,  64, 192,  91, 237,  44, 116, 156, 191, 218, 117,
+			159, 186, 213, 100, 172, 239,  42, 126, 130, 157, 188, 223, 122, 142, 137, 128,
+			155, 182, 193,  88, 232,  35, 101, 175, 234,  37, 111, 177, 200,  67, 197,  84,
+			252,  31,  33,  99, 165, 244,   7,   9,  27,  45, 119, 153, 176, 203,  70, 202,
+			69, 207,  74, 222, 121, 139, 134, 145, 168, 227,  62,  66, 198,  81, 243,  14,
+			18,  54,  90, 238,  41, 123, 141, 140, 143, 138, 133, 148, 167, 242,  13,  23,
+			57,  75, 221, 124, 132, 151, 162, 253,  28,  36, 108, 180, 199,  82, 246,   1,
+		};
+
+		private static readonly byte[] S =
+		{
+			99, 124, 119, 123, 242, 107, 111, 197,  48,   1, 103,  43, 254, 215, 171, 118,
+			202, 130, 201, 125, 250,  89,  71, 240, 173, 212, 162, 175, 156, 164, 114, 192,
+			183, 253, 147,  38,  54,  63, 247, 204,  52, 165, 229, 241, 113, 216,  49,  21,
+			4, 199,  35, 195,  24, 150,   5, 154,   7,  18, 128, 226, 235,  39, 178, 117,
+			9, 131,  44,  26,  27, 110,  90, 160,  82,  59, 214, 179,  41, 227,  47, 132,
+			83, 209,   0, 237,  32, 252, 177,  91, 106, 203, 190,  57,  74,  76,  88, 207,
+			208, 239, 170, 251,  67,  77,  51, 133,  69, 249,   2, 127,  80,  60, 159, 168,
+			81, 163,  64, 143, 146, 157,  56, 245, 188, 182, 218,  33,  16, 255, 243, 210,
+			205,  12,  19, 236,  95, 151,  68,  23, 196, 167, 126,  61, 100,  93,  25, 115,
+			96, 129,  79, 220,  34,  42, 144, 136,  70, 238, 184,  20, 222,  94,  11, 219,
+			224,  50,  58,  10,  73,   6,  36,  92, 194, 211, 172,  98, 145, 149, 228, 121,
+			231, 200,  55, 109, 141, 213,  78, 169, 108,  86, 244, 234, 101, 122, 174,   8,
+			186, 120,  37,  46,  28, 166, 180, 198, 232, 221, 116,  31,  75, 189, 139, 138,
+			112,  62, 181, 102,  72,   3, 246,  14,  97,  53,  87, 185, 134, 193,  29, 158,
+			225, 248, 152,  17, 105, 217, 142, 148, 155,  30, 135, 233, 206,  85,  40, 223,
+			140, 161, 137,  13, 191, 230,  66, 104,  65, 153,  45,  15, 176,  84, 187,  22,
+		};
+
+		private static readonly byte[] Si =
+		{
+			82,   9, 106, 213,  48,  54, 165,  56, 191,  64, 163, 158, 129, 243, 215, 251,
+			124, 227,  57, 130, 155,  47, 255, 135,  52, 142,  67,  68, 196, 222, 233, 203,
+			84, 123, 148,  50, 166, 194,  35,  61, 238,  76, 149,  11,  66, 250, 195,  78,
+			8,  46, 161, 102,  40, 217,  36, 178, 118,  91, 162,  73, 109, 139, 209,  37,
+			114, 248, 246, 100, 134, 104, 152,  22, 212, 164,  92, 204,  93, 101, 182, 146,
+			108, 112,  72,  80, 253, 237, 185, 218,  94,  21,  70,  87, 167, 141, 157, 132,
+			144, 216, 171,   0, 140, 188, 211,  10, 247, 228,  88,   5, 184, 179,  69,   6,
+			208,  44,  30, 143, 202,  63,  15,   2, 193, 175, 189,   3,   1,  19, 138, 107,
+			58, 145,  17,  65,  79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115,
+			150, 172, 116,  34, 231, 173,  53, 133, 226, 249,  55, 232,  28, 117, 223, 110,
+			71, 241,  26, 113,  29,  41, 197, 137, 111, 183,  98,  14, 170,  24, 190,  27,
+			252,  86,  62,  75, 198, 210, 121,  32, 154, 219, 192, 254, 120, 205,  90, 244,
+			31, 221, 168,  51, 136,   7, 199,  49, 177,  18,  16,  89,  39, 128, 236,  95,
+			96,  81, 127, 169,  25, 181,  74,  13,  45, 229, 122, 159, 147, 201, 156, 239,
+			160, 224,  59,  77, 174,  42, 245, 176, 200, 235, 187,  60, 131,  83, 153,  97,
+			23,  43,   4, 126, 186, 119, 214,  38, 225, 105,  20,  99,  85,  33,  12, 125,
+		};
+
+		private static readonly byte[] rcon =
+		{
+			0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+			0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+		};
+
+		static readonly byte[][] shifts0 = new byte [][]
+		{
+			new byte[]{ 0, 8, 16, 24 },
+			new byte[]{ 0, 8, 16, 24 },
+			new byte[]{ 0, 8, 16, 24 },
+			new byte[]{ 0, 8, 16, 32 },
+			new byte[]{ 0, 8, 24, 32 }
+		};
+
+		static readonly byte[][] shifts1 =
+		{
+			new byte[]{ 0, 24, 16, 8 },
+			new byte[]{ 0, 32, 24, 16 },
+			new byte[]{ 0, 40, 32, 24 },
+			new byte[]{ 0, 48, 40, 24 },
+			new byte[]{ 0, 56, 40, 32 }
+		};
+
+		/**
+		* multiply two elements of GF(2^m)
+		* needed for MixColumn and InvMixColumn
+		*/
+		private byte Mul0x2(
+			int b)
+		{
+			if (b != 0)
+			{
+				return Alogtable[25 + (Logtable[b] & 0xff)];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		private byte Mul0x3(
+			int b)
+		{
+			if (b != 0)
+			{
+				return Alogtable[1 + (Logtable[b] & 0xff)];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		private byte Mul0x9(
+			int b)
+		{
+			if (b >= 0)
+			{
+				return Alogtable[199 + b];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		private byte Mul0xb(
+			int b)
+		{
+			if (b >= 0)
+			{
+				return Alogtable[104 + b];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		private byte Mul0xd(
+			int b)
+		{
+			if (b >= 0)
+			{
+				return Alogtable[238 + b];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		private byte Mul0xe(
+			int b)
+		{
+			if (b >= 0)
+			{
+				return Alogtable[223 + b];
+			}
+			else
+			{
+				return 0;
+			}
+		}
+
+		/**
+		* xor corresponding text input and round key input bytes
+		*/
+		private void KeyAddition(
+			long[] rk)
+		{
+			A0 ^= rk[0];
+			A1 ^= rk[1];
+			A2 ^= rk[2];
+			A3 ^= rk[3];
+		}
+
+		private long Shift(
+			long	r,
+			int	shift)
+		{
+			//return (((long)((ulong) r >> shift) | (r << (BC - shift)))) & BC_MASK;
+
+			ulong temp = (ulong) r >> shift;
+
+			// NB: This corrects for Mono Bug #79087 (fixed in 1.1.17)
+			if (shift > 31)
+			{
+				temp &= 0xFFFFFFFFUL;
+			}
+
+			return ((long) temp | (r << (BC - shift))) & BC_MASK;
+		}
+
+		/**
+		* Row 0 remains unchanged
+		* The other three rows are shifted a variable amount
+		*/
+		private void ShiftRow(
+			byte[]      shiftsSC)
+		{
+			A1 = Shift(A1, shiftsSC[1]);
+			A2 = Shift(A2, shiftsSC[2]);
+			A3 = Shift(A3, shiftsSC[3]);
+		}
+
+		private long ApplyS(
+			long    r,
+			byte[]  box)
+		{
+			long    res = 0;
+
+			for (int j = 0; j < BC; j += 8)
+			{
+				res |= (long)(box[(int)((r >> j) & 0xff)] & 0xff) << j;
+			}
+
+			return res;
+		}
+
+		/**
+		* Replace every byte of the input by the byte at that place
+		* in the nonlinear S-box
+		*/
+		private void Substitution(
+			byte[]      box)
+		{
+			A0 = ApplyS(A0, box);
+			A1 = ApplyS(A1, box);
+			A2 = ApplyS(A2, box);
+			A3 = ApplyS(A3, box);
+		}
+
+		/**
+		* Mix the bytes of every column in a linear way
+		*/
+		private void MixColumn()
+		{
+			long r0, r1, r2, r3;
+
+			r0 = r1 = r2 = r3 = 0;
+
+			for (int j = 0; j < BC; j += 8)
+			{
+				int a0 = (int)((A0 >> j) & 0xff);
+				int a1 = (int)((A1 >> j) & 0xff);
+				int a2 = (int)((A2 >> j) & 0xff);
+				int a3 = (int)((A3 >> j) & 0xff);
+
+				r0 |= (long)((Mul0x2(a0) ^ Mul0x3(a1) ^ a2 ^ a3) & 0xff) << j;
+
+				r1 |= (long)((Mul0x2(a1) ^ Mul0x3(a2) ^ a3 ^ a0) & 0xff) << j;
+
+				r2 |= (long)((Mul0x2(a2) ^ Mul0x3(a3) ^ a0 ^ a1) & 0xff) << j;
+
+				r3 |= (long)((Mul0x2(a3) ^ Mul0x3(a0) ^ a1 ^ a2) & 0xff) << j;
+			}
+
+			A0 = r0;
+			A1 = r1;
+			A2 = r2;
+			A3 = r3;
+		}
+
+		/**
+		* Mix the bytes of every column in a linear way
+		* This is the opposite operation of Mixcolumn
+		*/
+		private void InvMixColumn()
+		{
+			long r0, r1, r2, r3;
+
+			r0 = r1 = r2 = r3 = 0;
+			for (int j = 0; j < BC; j += 8)
+			{
+				int a0 = (int)((A0 >> j) & 0xff);
+				int a1 = (int)((A1 >> j) & 0xff);
+				int a2 = (int)((A2 >> j) & 0xff);
+				int a3 = (int)((A3 >> j) & 0xff);
+
+				//
+				// pre-lookup the log table
+				//
+				a0 = (a0 != 0) ? (Logtable[a0 & 0xff] & 0xff) : -1;
+				a1 = (a1 != 0) ? (Logtable[a1 & 0xff] & 0xff) : -1;
+				a2 = (a2 != 0) ? (Logtable[a2 & 0xff] & 0xff) : -1;
+				a3 = (a3 != 0) ? (Logtable[a3 & 0xff] & 0xff) : -1;
+
+				r0 |= (long)((Mul0xe(a0) ^ Mul0xb(a1) ^ Mul0xd(a2) ^ Mul0x9(a3)) & 0xff) << j;
+
+				r1 |= (long)((Mul0xe(a1) ^ Mul0xb(a2) ^ Mul0xd(a3) ^ Mul0x9(a0)) & 0xff) << j;
+
+				r2 |= (long)((Mul0xe(a2) ^ Mul0xb(a3) ^ Mul0xd(a0) ^ Mul0x9(a1)) & 0xff) << j;
+
+				r3 |= (long)((Mul0xe(a3) ^ Mul0xb(a0) ^ Mul0xd(a1) ^ Mul0x9(a2)) & 0xff) << j;
+			}
+
+			A0 = r0;
+			A1 = r1;
+			A2 = r2;
+			A3 = r3;
+		}
+
+		/**
+		* Calculate the necessary round keys
+		* The number of calculations depends on keyBits and blockBits
+		*/
+		private long[][] GenerateWorkingKey(
+			byte[]      key)
+		{
+			int         KC;
+			int         t, rconpointer = 0;
+			int         keyBits = key.Length * 8;
+			byte[,]    tk = new byte[4,MAXKC];
+			//long[,]    W = new long[MAXROUNDS+1,4];
+			long[][]    W = new long[MAXROUNDS+1][];
+
+			for (int i = 0; i < MAXROUNDS+1; i++) W[i] = new long[4];
+
+			switch (keyBits)
+			{
+				case 128:
+					KC = 4;
+					break;
+				case 160:
+					KC = 5;
+					break;
+				case 192:
+					KC = 6;
+					break;
+				case 224:
+					KC = 7;
+					break;
+				case 256:
+					KC = 8;
+					break;
+				default :
+					throw new ArgumentException("Key length not 128/160/192/224/256 bits.");
+			}
+
+			if (keyBits >= blockBits)
+			{
+				ROUNDS = KC + 6;
+			}
+			else
+			{
+				ROUNDS = (BC / 8) + 6;
+			}
+
+			//
+			// copy the key into the processing area
+			//
+			int index = 0;
+
+			for (int i = 0; i < key.Length; i++)
+			{
+				tk[i % 4,i / 4] = key[index++];
+			}
+
+			t = 0;
+
+			//
+			// copy values into round key array
+			//
+			for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC / 8)); j++, t++)
+			{
+				for (int i = 0; i < 4; i++)
+				{
+					W[t / (BC / 8)][i] |= (long)(tk[i,j] & 0xff) << ((t * 8) % BC);
+				}
+			}
+
+			//
+			// while not enough round key material calculated
+			// calculate new values
+			//
+			while (t < (ROUNDS+1)*(BC/8))
+			{
+				for (int i = 0; i < 4; i++)
+				{
+					tk[i,0] ^= S[tk[(i+1)%4,KC-1] & 0xff];
+				}
+				tk[0,0] ^= (byte) rcon[rconpointer++];
+
+				if (KC <= 6)
+				{
+					for (int j = 1; j < KC; j++)
+					{
+						for (int i = 0; i < 4; i++)
+						{
+							tk[i,j] ^= tk[i,j-1];
+						}
+					}
+				}
+				else
+				{
+					for (int j = 1; j < 4; j++)
+					{
+						for (int i = 0; i < 4; i++)
+						{
+							tk[i,j] ^= tk[i,j-1];
+						}
+					}
+					for (int i = 0; i < 4; i++)
+					{
+						tk[i,4] ^= S[tk[i,3] & 0xff];
+					}
+					for (int j = 5; j < KC; j++)
+					{
+						for (int i = 0; i < 4; i++)
+						{
+							tk[i,j] ^= tk[i,j-1];
+						}
+					}
+				}
+
+				//
+				// copy values into round key array
+				//
+				for (int j = 0; (j < KC) && (t < (ROUNDS+1)*(BC/8)); j++, t++)
+				{
+					for (int i = 0; i < 4; i++)
+					{
+						W[t / (BC/8)][i] |= (long)(tk[i,j] & 0xff) << ((t * 8) % (BC));
+					}
+				}
+			}
+			return W;
+		}
+
+		private int         BC;
+		private long        BC_MASK;
+		private int         ROUNDS;
+		private int         blockBits;
+		private long[][]    workingKey;
+		private long        A0, A1, A2, A3;
+		private bool     forEncryption;
+		private byte[]      shifts0SC;
+		private byte[]      shifts1SC;
+
+		/**
+		* default constructor - 128 bit block size.
+		*/
+		public RijndaelEngine() : this(128) {}
+
+		/**
+		* basic constructor - set the cipher up for a given blocksize
+		*
+		* @param blocksize the blocksize in bits, must be 128, 192, or 256.
+		*/
+		public RijndaelEngine(
+			int blockBits)
+		{
+			switch (blockBits)
+			{
+				case 128:
+					BC = 32;
+					BC_MASK = 0xffffffffL;
+					shifts0SC = shifts0[0];
+					shifts1SC = shifts1[0];
+					break;
+				case 160:
+					BC = 40;
+					BC_MASK = 0xffffffffffL;
+					shifts0SC = shifts0[1];
+					shifts1SC = shifts1[1];
+					break;
+				case 192:
+					BC = 48;
+					BC_MASK = 0xffffffffffffL;
+					shifts0SC = shifts0[2];
+					shifts1SC = shifts1[2];
+					break;
+				case 224:
+					BC = 56;
+					BC_MASK = 0xffffffffffffffL;
+					shifts0SC = shifts0[3];
+					shifts1SC = shifts1[3];
+					break;
+				case 256:
+					BC = 64;
+					BC_MASK = unchecked( (long)0xffffffffffffffffL);
+					shifts0SC = shifts0[4];
+					shifts1SC = shifts1[4];
+					break;
+				default:
+					throw new ArgumentException("unknown blocksize to Rijndael");
+			}
+
+			this.blockBits = blockBits;
+		}
+
+		/**
+		* initialise a Rijndael cipher.
+		*
+		* @param forEncryption whether or not we are for encryption.
+		* @param parameters the parameters required to set up the cipher.
+		* @exception ArgumentException if the parameters argument is
+		* inappropriate.
+		*/
+		public void Init(
+			bool           forEncryption,
+			ICipherParameters  parameters)
+		{
+			if (typeof(KeyParameter).IsInstanceOfType(parameters))
+			{
+				workingKey = GenerateWorkingKey(((KeyParameter)parameters).GetKey());
+				this.forEncryption = forEncryption;
+				return;
+			}
+
+			throw new ArgumentException("invalid parameter passed to Rijndael init - " + parameters.GetType().ToString());
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Rijndael"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BC / 2;
+		}
+
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if (workingKey == null)
+			{
+				throw new InvalidOperationException("Rijndael engine not initialised");
+			}
+
+			if ((inOff + (BC / 2)) > input.Length)
+			{
+				throw new DataLengthException("input buffer too short");
+			}
+
+			if ((outOff + (BC / 2)) > output.Length)
+			{
+				throw new DataLengthException("output buffer too short");
+			}
+
+			UnPackBlock(input, inOff);
+
+			if (forEncryption)
+			{
+				EncryptBlock(workingKey);
+			}
+			else
+			{
+				DecryptBlock(workingKey);
+			}
+
+			PackBlock(output, outOff);
+
+			return BC / 2;
+		}
+
+		public void Reset()
+		{
+		}
+
+		private  void UnPackBlock(
+			byte[]      bytes,
+			int         off)
+		{
+			int     index = off;
+
+			A0 = (long)(bytes[index++] & 0xff);
+			A1 = (long)(bytes[index++] & 0xff);
+			A2 = (long)(bytes[index++] & 0xff);
+			A3 = (long)(bytes[index++] & 0xff);
+
+			for (int j = 8; j != BC; j += 8)
+			{
+				A0 |= (long)(bytes[index++] & 0xff) << j;
+				A1 |= (long)(bytes[index++] & 0xff) << j;
+				A2 |= (long)(bytes[index++] & 0xff) << j;
+				A3 |= (long)(bytes[index++] & 0xff) << j;
+			}
+		}
+
+		private  void PackBlock(
+			byte[]      bytes,
+			int         off)
+		{
+			int     index = off;
+
+			for (int j = 0; j != BC; j += 8)
+			{
+				bytes[index++] = (byte)(A0 >> j);
+				bytes[index++] = (byte)(A1 >> j);
+				bytes[index++] = (byte)(A2 >> j);
+				bytes[index++] = (byte)(A3 >> j);
+			}
+		}
+
+		private  void EncryptBlock(
+			long[][] rk)
+		{
+			int r;
+
+			//
+			// begin with a key addition
+			//
+			KeyAddition(rk[0]);
+
+			//
+			// ROUNDS-1 ordinary rounds
+			//
+			for (r = 1; r < ROUNDS; r++)
+			{
+				Substitution(S);
+				ShiftRow(shifts0SC);
+				MixColumn();
+				KeyAddition(rk[r]);
+			}
+
+			//
+			// Last round is special: there is no MixColumn
+			//
+			Substitution(S);
+			ShiftRow(shifts0SC);
+			KeyAddition(rk[ROUNDS]);
+		}
+
+		private void DecryptBlock(
+			long[][] rk)
+		{
+			int r;
+
+			// To decrypt: apply the inverse operations of the encrypt routine,
+			//             in opposite order
+			//
+			// (KeyAddition is an involution: it 's equal to its inverse)
+			// (the inverse of Substitution with table S is Substitution with the inverse table of S)
+			// (the inverse of Shiftrow is Shiftrow over a suitable distance)
+			//
+
+			// First the special round:
+			//   without InvMixColumn
+			//   with extra KeyAddition
+			//
+			KeyAddition(rk[ROUNDS]);
+			Substitution(Si);
+			ShiftRow(shifts1SC);
+
+			//
+			// ROUNDS-1 ordinary rounds
+			//
+			for (r = ROUNDS-1; r > 0; r--)
+			{
+				KeyAddition(rk[r]);
+				InvMixColumn();
+				Substitution(Si);
+				ShiftRow(shifts1SC);
+			}
+
+			//
+			// End with the extra key addition
+			//
+			KeyAddition(rk[0]);
+		}
+	}
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/RsaEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/RsaEngine.cs
new file mode 100644
index 0000000..7e6dfb1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/RsaEngine.cs
@@ -0,0 +1,78 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * this does your basic RSA algorithm.
+    */
+    public class RsaEngine
+		: IAsymmetricBlockCipher
+    {
+		private RsaCoreEngine core;
+
+        public string AlgorithmName
+        {
+            get { return "RSA"; }
+        }
+
+		/**
+        * initialise the RSA engine.
+        *
+        * @param forEncryption true if we are encrypting, false otherwise.
+        * @param param the necessary RSA key parameters.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+			if (core == null)
+				core = new RsaCoreEngine();
+
+			core.Init(forEncryption, parameters);
+		}
+
+		/**
+        * Return the maximum size for an input block to this engine.
+        * For RSA this is always one byte less than the key size on
+        * encryption, and the same length as the key size on decryption.
+        *
+        * @return maximum size for an input block.
+        */
+        public int GetInputBlockSize()
+        {
+			return core.GetInputBlockSize();
+        }
+
+		/**
+        * Return the maximum size for an output block to this engine.
+        * For RSA this is always one byte less than the key size on
+        * decryption, and the same length as the key size on encryption.
+        *
+        * @return maximum size for an output block.
+        */
+        public int GetOutputBlockSize()
+        {
+			return core.GetOutputBlockSize();
+        }
+
+		/**
+        * Process a single block using the basic RSA algorithm.
+        *
+        * @param inBuf the input array.
+        * @param inOff the offset into the input buffer where the data starts.
+        * @param inLen the length of the data to be processed.
+        * @return the result of the RSA process.
+        * @exception DataLengthException the input block is too large.
+        */
+        public byte[] ProcessBlock(
+            byte[]	inBuf,
+            int		inOff,
+            int		inLen)
+        {
+			if (core == null)
+				throw new InvalidOperationException("RSA engine not initialised");
+
+			return core.ConvertOutput(core.ProcessBlock(core.ConvertInput(inBuf, inOff, inLen)));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/SEEDEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/SEEDEngine.cs
new file mode 100644
index 0000000..efea0f1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/SEEDEngine.cs
@@ -0,0 +1,361 @@
+using System;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* Implementation of the SEED algorithm as described in RFC 4009
+	*/
+	public class SeedEngine
+		: IBlockCipher
+	{
+		private const int BlockSize = 16;
+
+		private static readonly uint[] SS0 =
+		{
+			0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124,
+			0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360,
+			0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314,
+			0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec,
+			0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074,
+			0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100,
+			0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8,
+			0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8,
+			0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c,
+			0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4,
+			0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008,
+			0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0,
+			0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8,
+			0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208,
+			0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064,
+			0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264,
+			0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0,
+			0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc,
+			0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038,
+			0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394,
+			0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188,
+			0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4,
+			0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8,
+			0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4,
+			0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040,
+			0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154,
+			0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254,
+			0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8,
+			0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0,
+			0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088,
+			0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330,
+			0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298
+		};
+
+		private static readonly uint[] SS1 =
+		{
+			0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0,
+			0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53,
+			0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3,
+			0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43,
+			0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0,
+			0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890,
+			0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3,
+			0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272,
+			0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83,
+			0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430,
+			0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0,
+			0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1,
+			0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1,
+			0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171,
+			0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951,
+			0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0,
+			0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3,
+			0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41,
+			0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62,
+			0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0,
+			0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303,
+			0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901,
+			0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501,
+			0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343,
+			0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971,
+			0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53,
+			0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642,
+			0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1,
+			0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70,
+			0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393,
+			0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783,
+			0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3
+		};
+
+		private static readonly uint[] SS2 =
+		{
+
+			0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505,
+			0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343,
+			0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707,
+			0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece,
+			0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444,
+			0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101,
+			0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9,
+			0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9,
+			0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f,
+			0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5,
+			0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808,
+			0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1,
+			0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b,
+			0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a,
+			0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444,
+			0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646,
+			0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0,
+			0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf,
+			0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808,
+			0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787,
+			0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989,
+			0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4,
+			0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888,
+			0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484,
+			0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040,
+			0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545,
+			0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646,
+			0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca,
+			0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282,
+			0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888,
+			0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303,
+			0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a
+		};
+
+		private static readonly uint[] SS3 =
+		{
+
+			0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838,
+			0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b,
+			0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427,
+			0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b,
+			0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434,
+			0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818,
+			0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f,
+			0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032,
+			0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b,
+			0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434,
+			0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838,
+			0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839,
+			0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031,
+			0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031,
+			0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819,
+			0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010,
+			0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f,
+			0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d,
+			0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e,
+			0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c,
+			0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003,
+			0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809,
+			0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405,
+			0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003,
+			0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839,
+			0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f,
+			0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406,
+			0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d,
+			0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c,
+			0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013,
+			0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407,
+			0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437
+		};
+
+		private static readonly uint[] KC =
+		{
+			0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc,
+			0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf,
+			0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1,
+			0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b
+		};
+
+		private int[] wKey;
+		private bool forEncryption;
+
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+			wKey = createWorkingKey(((KeyParameter)parameters).GetKey());
+		}
+
+		public string AlgorithmName
+		{
+			get { return "SEED"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return BlockSize;
+		}
+
+		public int ProcessBlock(
+			byte[]	inBuf,
+			int		inOff,
+			byte[]	outBuf,
+			int		outOff)
+		{
+			if (wKey == null)
+				throw new InvalidOperationException("SEED engine not initialised");
+			if (inOff + BlockSize > inBuf.Length)
+				throw new DataLengthException("input buffer too short");
+			if (outOff + BlockSize > outBuf.Length)
+				throw new DataLengthException("output buffer too short");
+
+			long l = bytesToLong(inBuf, inOff + 0);
+			long r = bytesToLong(inBuf, inOff + 8);
+
+			if (forEncryption)
+			{
+				for (int i = 0; i < 16; i++)
+				{
+					long nl = r;
+
+					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+					l = nl;
+				}
+			}
+			else
+			{
+				for (int i = 15; i >= 0; i--)
+				{
+					long nl = r;
+
+					r = l ^ F(wKey[2 * i], wKey[(2 * i) + 1], r);
+					l = nl;
+				}
+			}
+
+			longToBytes(outBuf, outOff + 0, r);
+			longToBytes(outBuf, outOff + 8, l);
+
+			return BlockSize;
+		}
+
+		public void Reset()
+		{
+		}
+
+		private int[] createWorkingKey(
+			byte[] inKey)
+		{
+			int[] key = new int[32];
+			long lower = bytesToLong(inKey, 0);
+			long upper = bytesToLong(inKey, 8);
+
+			int key0 = extractW0(lower);
+			int key1 = extractW1(lower);
+			int key2 = extractW0(upper);
+			int key3 = extractW1(upper);
+
+			for (int i = 0; i < 16; i++)
+			{
+				key[2 * i] = G(key0 + key2 - (int)KC[i]);
+				key[2 * i + 1] = G(key1 - key3 + (int)KC[i]);
+
+				if (i % 2 == 0)
+				{
+					lower = rotateRight8(lower);
+					key0 = extractW0(lower);
+					key1 = extractW1(lower);
+				}
+				else
+				{
+					upper = rotateLeft8(upper);
+					key2 = extractW0(upper);
+					key3 = extractW1(upper);
+				}
+			}
+
+			return key;
+		}
+
+		private int extractW1(
+			long lVal)
+		{
+			return (int)lVal;
+		}
+
+		private int extractW0(
+			long lVal)
+		{
+			return (int)(lVal >> 32);
+		}
+
+		private long rotateLeft8(
+			long x)
+		{
+			return (x << 8) | ((long)((ulong) x >> 56));
+		}
+
+		private long rotateRight8(
+			long x)
+		{
+			return ((long)((ulong) x >> 8)) | (x << 56);
+		}
+
+		private long bytesToLong(
+			byte[]	src,
+			int		srcOff)
+		{
+			long word = 0;
+
+			for (int i = 0; i <= 7; i++)
+			{
+				word = (word << 8) + (src[i + srcOff] & 0xff);
+			}
+
+			return word;
+		}
+
+		private void longToBytes(
+			byte[]	dest,
+			int		destOff,
+			long	value)
+		{
+			for (int i = 0; i < 8; i++)
+			{
+				dest[i + destOff] = (byte)(value >> ((7 - i) * 8));
+			}
+		}
+
+		private int G(
+			int x)
+		{
+			return (int)(SS0[x & 0xff] ^ SS1[(x >> 8) & 0xff] ^ SS2[(x >> 16) & 0xff] ^ SS3[(x >> 24) & 0xff]);
+		}
+
+		private long F(
+			int		ki0,
+			int		ki1,
+			long	r)
+		{
+			int r0 = (int)(r >> 32);
+			int r1 = (int)r;
+			int rd1 = phaseCalc2(r0, ki0, r1, ki1);
+			int rd0 = rd1 + phaseCalc1(r0, ki0, r1, ki1);
+
+			return ((long)rd0 << 32) | (rd1 & 0xffffffffL);
+		}
+
+		private int phaseCalc1(
+			int	r0,
+			int	ki0,
+			int	r1,
+			int	ki1)
+		{
+			return G(G((r0 ^ ki0) ^ (r1 ^ ki1)) + (r0 ^ ki0));
+		}
+
+		private int phaseCalc2(
+			int	r0,
+			int	ki0,
+			int	r1,
+			int	ki1)
+		{
+			return G(phaseCalc1(r0, ki0, r1, ki1) + G((r0 ^ ki0) ^ (r1 ^ ki1)));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/SEEDWrapEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/SEEDWrapEngine.cs
new file mode 100644
index 0000000..6b71f94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/SEEDWrapEngine.cs
@@ -0,0 +1,16 @@
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <remarks>
+	/// An implementation of the SEED key wrapper based on RFC 4010/RFC 3394.
+	/// <p/>
+	/// For further details see: <a href="http://www.ietf.org/rfc/rfc4010.txt">http://www.ietf.org/rfc/rfc4010.txt</a>.
+	/// </remarks>
+	public class SeedWrapEngine
+		: Rfc3394WrapEngine
+	{
+		public SeedWrapEngine()
+			: base(new SeedEngine())
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/Salsa20Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/Salsa20Engine.cs
new file mode 100644
index 0000000..81884d6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/Salsa20Engine.cs
@@ -0,0 +1,372 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <summary>
+	/// Implementation of Daniel J. Bernstein's Salsa20 stream cipher, Snuffle 2005
+	/// </summary>
+	public class Salsa20Engine
+		: IStreamCipher
+	{
+		public static readonly int DEFAULT_ROUNDS = 20;
+
+		/** Constants */
+		private const int StateSize = 16; // 16, 32 bit ints = 64 bytes
+
+		protected readonly static byte[]
+			sigma = Strings.ToAsciiByteArray("expand 32-byte k"),
+			tau = Strings.ToAsciiByteArray("expand 16-byte k");
+
+		protected int rounds;
+
+		/*
+		 * variables to hold the state of the engine
+		 * during encryption and decryption
+		 */
+		private int		 index = 0;
+		internal uint[] engineState = new uint[StateSize]; // state
+		internal uint[] x = new uint[StateSize]; // internal buffer
+		private byte[]	 keyStream = new byte[StateSize * 4]; // expanded state, 64 bytes
+		private bool	 initialised = false;
+
+		/*
+		 * internal counter
+		 */
+		private uint cW0, cW1, cW2;
+
+		/// <summary>
+		/// Creates a 20 round Salsa20 engine.
+		/// </summary>
+		public Salsa20Engine()
+			: this(DEFAULT_ROUNDS)
+		{
+		}
+
+		/// <summary>
+		/// Creates a Salsa20 engine with a specific number of rounds.
+		/// </summary>
+		/// <param name="rounds">the number of rounds (must be an even number).</param>
+		public Salsa20Engine(int rounds)
+		{
+			if (rounds <= 0 || (rounds & 1) != 0)
+			{
+				throw new ArgumentException("'rounds' must be a positive, even number");
+			}
+
+			this.rounds = rounds;
+		}
+
+		public void Init(
+			bool				forEncryption, 
+			ICipherParameters	parameters)
+		{
+			/* 
+			 * Salsa20 encryption and decryption is completely
+			 * symmetrical, so the 'forEncryption' is 
+			 * irrelevant. (Like 90% of stream ciphers)
+			 */
+
+			ParametersWithIV ivParams = parameters as ParametersWithIV;
+
+			if (ivParams == null)
+				throw new ArgumentException(AlgorithmName + " Init requires an IV", "parameters");
+
+			byte[] iv = ivParams.GetIV();
+
+			if (iv == null || iv.Length != NonceSize)
+				throw new ArgumentException(AlgorithmName + " requires exactly " + NonceSize + " bytes of IV");
+
+			KeyParameter key = ivParams.Parameters as KeyParameter;
+
+			if (key == null)
+				throw new ArgumentException(AlgorithmName + " Init requires a key", "parameters");
+
+			SetKey(key.GetKey(), iv);
+			Reset();
+			initialised = true;
+		}
+
+		protected virtual int NonceSize
+		{
+			get { return 8; }
+		}
+
+		public virtual string AlgorithmName
+		{
+			get { 
+				string name = "Salsa20";
+				if (rounds != DEFAULT_ROUNDS)
+				{
+					name += "/" + rounds;
+				}
+				return name;
+			}
+		}
+
+		public byte ReturnByte(
+			byte input)
+		{
+			if (LimitExceeded())
+			{
+				throw new MaxBytesExceededException("2^70 byte limit per IV; Change IV");
+			}
+
+			if (index == 0)
+			{
+				GenerateKeyStream(keyStream);
+				AdvanceCounter();
+			}
+
+			byte output = (byte)(keyStream[index] ^ input);
+			index = (index + 1) & 63;
+
+			return output;
+		}
+
+		protected virtual void AdvanceCounter()
+		{
+			if (++engineState[8] == 0)
+			{
+				++engineState[9];
+			}
+		}
+
+		public void ProcessBytes(
+			byte[]	inBytes, 
+			int		inOff, 
+			int		len, 
+			byte[]	outBytes, 
+			int		outOff)
+		{
+			if (!initialised)
+			{
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+			}
+
+			if ((inOff + len) > inBytes.Length)
+			{
+				throw new DataLengthException("input buffer too short");
+			}
+
+			if ((outOff + len) > outBytes.Length)
+			{
+				throw new DataLengthException("output buffer too short");
+			}
+
+			if (LimitExceeded((uint)len))
+			{
+				throw new MaxBytesExceededException("2^70 byte limit per IV would be exceeded; Change IV");
+			}
+
+			for (int i = 0; i < len; i++)
+			{
+				if (index == 0)
+				{
+					GenerateKeyStream(keyStream);
+					AdvanceCounter();
+				}
+				outBytes[i+outOff] = (byte)(keyStream[index]^inBytes[i+inOff]);
+				index = (index + 1) & 63;
+			}
+		}
+
+		public void Reset()
+		{
+			index = 0;
+			ResetLimitCounter();
+			ResetCounter();
+		}
+
+		protected virtual void ResetCounter()
+		{
+			engineState[8] = engineState[9] = 0;
+		}
+
+		protected virtual void SetKey(byte[] keyBytes, byte[] ivBytes)
+		{
+			if ((keyBytes.Length != 16) && (keyBytes.Length != 32)) {
+				throw new ArgumentException(AlgorithmName + " requires 128 bit or 256 bit key");
+			}
+
+			int offset = 0;
+			byte[] constants;
+
+			// Key
+			engineState[1] = Pack.LE_To_UInt32(keyBytes, 0);
+			engineState[2] = Pack.LE_To_UInt32(keyBytes, 4);
+			engineState[3] = Pack.LE_To_UInt32(keyBytes, 8);
+			engineState[4] = Pack.LE_To_UInt32(keyBytes, 12);
+
+			if (keyBytes.Length == 32)
+			{
+				constants = sigma;
+				offset = 16;
+			}
+			else
+			{
+				constants = tau;
+			}
+
+			engineState[11] = Pack.LE_To_UInt32(keyBytes, offset);
+			engineState[12] = Pack.LE_To_UInt32(keyBytes, offset + 4);
+			engineState[13] = Pack.LE_To_UInt32(keyBytes, offset + 8);
+			engineState[14] = Pack.LE_To_UInt32(keyBytes, offset + 12);
+			engineState[0] = Pack.LE_To_UInt32(constants, 0);
+			engineState[5] = Pack.LE_To_UInt32(constants, 4);
+			engineState[10] = Pack.LE_To_UInt32(constants, 8);
+			engineState[15] = Pack.LE_To_UInt32(constants, 12);
+
+			// IV
+			engineState[6] = Pack.LE_To_UInt32(ivBytes, 0);
+			engineState[7] = Pack.LE_To_UInt32(ivBytes, 4);
+			ResetCounter();
+		}
+
+		protected virtual void GenerateKeyStream(byte[] output)
+		{
+			SalsaCore(rounds, engineState, x);
+			Pack.UInt32_To_LE(x, output, 0);
+		}
+
+		internal static void SalsaCore(int rounds, uint[] input, uint[] x)
+		{
+			if (input.Length != 16) {
+				throw new ArgumentException();
+			}
+			if (x.Length != 16) {
+				throw new ArgumentException();
+			}
+			if (rounds % 2 != 0) {
+				throw new ArgumentException("Number of rounds must be even");
+			}
+
+			uint x00 = input[ 0];
+			uint x01 = input[ 1];
+			uint x02 = input[ 2];
+			uint x03 = input[ 3];
+			uint x04 = input[ 4];
+			uint x05 = input[ 5];
+			uint x06 = input[ 6];
+			uint x07 = input[ 7];
+			uint x08 = input[ 8];
+			uint x09 = input[ 9];
+			uint x10 = input[10];
+			uint x11 = input[11];
+			uint x12 = input[12];
+			uint x13 = input[13];
+			uint x14 = input[14];
+			uint x15 = input[15];
+
+			for (int i = rounds; i > 0; i -= 2)
+			{
+				x04 ^= R((x00+x12), 7);
+				x08 ^= R((x04+x00), 9);
+				x12 ^= R((x08+x04),13);
+				x00 ^= R((x12+x08),18);
+				x09 ^= R((x05+x01), 7);
+				x13 ^= R((x09+x05), 9);
+				x01 ^= R((x13+x09),13);
+				x05 ^= R((x01+x13),18);
+				x14 ^= R((x10+x06), 7);
+				x02 ^= R((x14+x10), 9);
+				x06 ^= R((x02+x14),13);
+				x10 ^= R((x06+x02),18);
+				x03 ^= R((x15+x11), 7);
+				x07 ^= R((x03+x15), 9);
+				x11 ^= R((x07+x03),13);
+				x15 ^= R((x11+x07),18);
+
+				x01 ^= R((x00+x03), 7);
+				x02 ^= R((x01+x00), 9);
+				x03 ^= R((x02+x01),13);
+				x00 ^= R((x03+x02),18);
+				x06 ^= R((x05+x04), 7);
+				x07 ^= R((x06+x05), 9);
+				x04 ^= R((x07+x06),13);
+				x05 ^= R((x04+x07),18);
+				x11 ^= R((x10+x09), 7);
+				x08 ^= R((x11+x10), 9);
+				x09 ^= R((x08+x11),13);
+				x10 ^= R((x09+x08),18);
+				x12 ^= R((x15+x14), 7);
+				x13 ^= R((x12+x15), 9);
+				x14 ^= R((x13+x12),13);
+				x15 ^= R((x14+x13),18);
+			}
+
+			x[ 0] = x00 + input[ 0];
+			x[ 1] = x01 + input[ 1];
+			x[ 2] = x02 + input[ 2];
+			x[ 3] = x03 + input[ 3];
+			x[ 4] = x04 + input[ 4];
+			x[ 5] = x05 + input[ 5];
+			x[ 6] = x06 + input[ 6];
+			x[ 7] = x07 + input[ 7];
+			x[ 8] = x08 + input[ 8];
+			x[ 9] = x09 + input[ 9];
+			x[10] = x10 + input[10];
+			x[11] = x11 + input[11];
+			x[12] = x12 + input[12];
+			x[13] = x13 + input[13];
+			x[14] = x14 + input[14];
+			x[15] = x15 + input[15];
+		}
+
+		/**
+		 * Rotate left
+		 *
+		 * @param   x   value to rotate
+		 * @param   y   amount to rotate x
+		 *
+		 * @return  rotated x
+		 */
+		internal static uint R(uint x, int y)
+		{
+			return (x << y) | (x >> (32 - y));
+		}
+
+		private void ResetLimitCounter()
+		{
+			cW0 = 0;
+			cW1 = 0;
+			cW2 = 0;
+		}
+
+		private bool LimitExceeded()
+		{
+			if (++cW0 == 0)
+			{
+				if (++cW1 == 0)
+				{
+					return (++cW2 & 0x20) != 0;          // 2^(32 + 32 + 6)
+				}
+			}
+
+			return false;
+		}
+
+		/*
+		 * this relies on the fact len will always be positive.
+		 */
+		private bool LimitExceeded(
+			uint len)
+		{
+			uint old = cW0;
+			cW0 += len;
+			if (cW0 < old)
+			{
+				if (++cW1 == 0)
+				{
+					return (++cW2 & 0x20) != 0;          // 2^(32 + 32 + 6)
+				}
+			}
+
+			return false;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/SerpentEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/SerpentEngine.cs
new file mode 100644
index 0000000..92b25ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/SerpentEngine.cs
@@ -0,0 +1,779 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * Serpent is a 128-bit 32-round block cipher with variable key lengths,
+    * including 128, 192 and 256 bit keys conjectured to be at least as
+    * secure as three-key triple-DES.
+    * <p>
+    * Serpent was designed by Ross Anderson, Eli Biham and Lars Knudsen as a
+    * candidate algorithm for the NIST AES Quest.>
+	* </p>
+    * <p>
+    * For full details see the <a href="http://www.cl.cam.ac.uk/~rja14/serpent.html">The Serpent home page</a>
+	* </p>
+    */
+    public class SerpentEngine
+		: IBlockCipher
+    {
+        private const int    BLOCK_SIZE = 16;
+
+        static readonly int ROUNDS = 32;
+        static readonly int PHI    = unchecked((int)0x9E3779B9);       // (Sqrt(5) - 1) * 2**31
+
+        private bool        encrypting;
+        private int[]          wKey;
+
+        private int           X0, X1, X2, X3;    // registers
+
+        /**
+        * initialise a Serpent cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+				throw new ArgumentException("invalid parameter passed to Serpent init - " + parameters.GetType().ToString());
+
+			this.encrypting = forEncryption;
+            this.wKey = MakeWorkingKey(((KeyParameter)parameters).GetKey());
+        }
+
+		public string AlgorithmName
+		{
+			get { return "Serpent"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        /**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public  int ProcessBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  output,
+            int     outOff)
+        {
+            if (wKey == null)
+                throw new InvalidOperationException("Serpent not initialised");
+            if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+			if (encrypting)
+            {
+                EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                DecryptBlock(input, inOff, output, outOff);
+            }
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+        }
+
+        /**
+        * Expand a user-supplied key material into a session key.
+        *
+        * @param key  The user-key bytes (multiples of 4) to use.
+        * @exception ArgumentException
+        */
+        private int[] MakeWorkingKey(
+            byte[] key)
+        {
+            //
+            // pad key to 256 bits
+            //
+            int[]   kPad = new int[16];
+            int     off = 0;
+            int     length = 0;
+
+            for (off = key.Length - 4; off > 0; off -= 4)
+            {
+                kPad[length++] = BytesToWord(key, off);
+            }
+
+            if (off == 0)
+            {
+                kPad[length++] = BytesToWord(key, 0);
+                if (length < 8)
+                {
+                    kPad[length] = 1;
+                }
+            }
+            else
+            {
+                throw new ArgumentException("key must be a multiple of 4 bytes");
+            }
+
+            //
+            // expand the padded key up to 33 x 128 bits of key material
+            //
+            int amount = (ROUNDS + 1) * 4;
+            int[] w = new int[amount];
+
+            //
+            // compute w0 to w7 from w-8 to w-1
+            //
+            for (int i = 8; i < 16; i++)
+            {
+                kPad[i] = RotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
+            }
+
+            Array.Copy(kPad, 8, w, 0, 8);
+
+            //
+            // compute w8 to w136
+            //
+            for (int i = 8; i < amount; i++)
+            {
+                w[i] = RotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
+            }
+
+            //
+            // create the working keys by processing w with the Sbox and IP
+            //
+            Sb3(w[0], w[1], w[2], w[3]);
+            w[0] = X0; w[1] = X1; w[2] = X2; w[3] = X3;
+            Sb2(w[4], w[5], w[6], w[7]);
+            w[4] = X0; w[5] = X1; w[6] = X2; w[7] = X3;
+            Sb1(w[8], w[9], w[10], w[11]);
+            w[8] = X0; w[9] = X1; w[10] = X2; w[11] = X3;
+            Sb0(w[12], w[13], w[14], w[15]);
+            w[12] = X0; w[13] = X1; w[14] = X2; w[15] = X3;
+            Sb7(w[16], w[17], w[18], w[19]);
+            w[16] = X0; w[17] = X1; w[18] = X2; w[19] = X3;
+            Sb6(w[20], w[21], w[22], w[23]);
+            w[20] = X0; w[21] = X1; w[22] = X2; w[23] = X3;
+            Sb5(w[24], w[25], w[26], w[27]);
+            w[24] = X0; w[25] = X1; w[26] = X2; w[27] = X3;
+            Sb4(w[28], w[29], w[30], w[31]);
+            w[28] = X0; w[29] = X1; w[30] = X2; w[31] = X3;
+            Sb3(w[32], w[33], w[34], w[35]);
+            w[32] = X0; w[33] = X1; w[34] = X2; w[35] = X3;
+            Sb2(w[36], w[37], w[38], w[39]);
+            w[36] = X0; w[37] = X1; w[38] = X2; w[39] = X3;
+            Sb1(w[40], w[41], w[42], w[43]);
+            w[40] = X0; w[41] = X1; w[42] = X2; w[43] = X3;
+            Sb0(w[44], w[45], w[46], w[47]);
+            w[44] = X0; w[45] = X1; w[46] = X2; w[47] = X3;
+            Sb7(w[48], w[49], w[50], w[51]);
+            w[48] = X0; w[49] = X1; w[50] = X2; w[51] = X3;
+            Sb6(w[52], w[53], w[54], w[55]);
+            w[52] = X0; w[53] = X1; w[54] = X2; w[55] = X3;
+            Sb5(w[56], w[57], w[58], w[59]);
+            w[56] = X0; w[57] = X1; w[58] = X2; w[59] = X3;
+            Sb4(w[60], w[61], w[62], w[63]);
+            w[60] = X0; w[61] = X1; w[62] = X2; w[63] = X3;
+            Sb3(w[64], w[65], w[66], w[67]);
+            w[64] = X0; w[65] = X1; w[66] = X2; w[67] = X3;
+            Sb2(w[68], w[69], w[70], w[71]);
+            w[68] = X0; w[69] = X1; w[70] = X2; w[71] = X3;
+            Sb1(w[72], w[73], w[74], w[75]);
+            w[72] = X0; w[73] = X1; w[74] = X2; w[75] = X3;
+            Sb0(w[76], w[77], w[78], w[79]);
+            w[76] = X0; w[77] = X1; w[78] = X2; w[79] = X3;
+            Sb7(w[80], w[81], w[82], w[83]);
+            w[80] = X0; w[81] = X1; w[82] = X2; w[83] = X3;
+            Sb6(w[84], w[85], w[86], w[87]);
+            w[84] = X0; w[85] = X1; w[86] = X2; w[87] = X3;
+            Sb5(w[88], w[89], w[90], w[91]);
+            w[88] = X0; w[89] = X1; w[90] = X2; w[91] = X3;
+            Sb4(w[92], w[93], w[94], w[95]);
+            w[92] = X0; w[93] = X1; w[94] = X2; w[95] = X3;
+            Sb3(w[96], w[97], w[98], w[99]);
+            w[96] = X0; w[97] = X1; w[98] = X2; w[99] = X3;
+            Sb2(w[100], w[101], w[102], w[103]);
+            w[100] = X0; w[101] = X1; w[102] = X2; w[103] = X3;
+            Sb1(w[104], w[105], w[106], w[107]);
+            w[104] = X0; w[105] = X1; w[106] = X2; w[107] = X3;
+            Sb0(w[108], w[109], w[110], w[111]);
+            w[108] = X0; w[109] = X1; w[110] = X2; w[111] = X3;
+            Sb7(w[112], w[113], w[114], w[115]);
+            w[112] = X0; w[113] = X1; w[114] = X2; w[115] = X3;
+            Sb6(w[116], w[117], w[118], w[119]);
+            w[116] = X0; w[117] = X1; w[118] = X2; w[119] = X3;
+            Sb5(w[120], w[121], w[122], w[123]);
+            w[120] = X0; w[121] = X1; w[122] = X2; w[123] = X3;
+            Sb4(w[124], w[125], w[126], w[127]);
+            w[124] = X0; w[125] = X1; w[126] = X2; w[127] = X3;
+            Sb3(w[128], w[129], w[130], w[131]);
+            w[128] = X0; w[129] = X1; w[130] = X2; w[131] = X3;
+
+            return w;
+        }
+
+        private int RotateLeft(
+            int     x,
+            int     bits)
+        {
+            return ((x << bits) | (int) ((uint)x >> (32 - bits)));
+        }
+
+        private int RotateRight(
+            int     x,
+            int     bits)
+        {
+            return ( (int)((uint)x >> bits) | (x << (32 - bits)));
+        }
+
+        private int BytesToWord(
+            byte[]  src,
+            int     srcOff)
+        {
+            return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) <<  16) |
+            ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
+        }
+
+        private void WordToBytes(
+            int     word,
+            byte[]  dst,
+            int     dstOff)
+        {
+            dst[dstOff + 3] = (byte)(word);
+            dst[dstOff + 2] = (byte)((uint)word >> 8);
+            dst[dstOff + 1] = (byte)((uint)word >> 16);
+            dst[dstOff]     = (byte)((uint)word >> 24);
+        }
+
+        /**
+        * Encrypt one block of plaintext.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        */
+        private void EncryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            X3 = BytesToWord(input, inOff);
+            X2 = BytesToWord(input, inOff + 4);
+            X1 = BytesToWord(input, inOff + 8);
+            X0 = BytesToWord(input, inOff + 12);
+
+            Sb0(wKey[0] ^ X0, wKey[1] ^ X1, wKey[2] ^ X2, wKey[3] ^ X3); LT();
+            Sb1(wKey[4] ^ X0, wKey[5] ^ X1, wKey[6] ^ X2, wKey[7] ^ X3); LT();
+            Sb2(wKey[8] ^ X0, wKey[9] ^ X1, wKey[10] ^ X2, wKey[11] ^ X3); LT();
+            Sb3(wKey[12] ^ X0, wKey[13] ^ X1, wKey[14] ^ X2, wKey[15] ^ X3); LT();
+            Sb4(wKey[16] ^ X0, wKey[17] ^ X1, wKey[18] ^ X2, wKey[19] ^ X3); LT();
+            Sb5(wKey[20] ^ X0, wKey[21] ^ X1, wKey[22] ^ X2, wKey[23] ^ X3); LT();
+            Sb6(wKey[24] ^ X0, wKey[25] ^ X1, wKey[26] ^ X2, wKey[27] ^ X3); LT();
+            Sb7(wKey[28] ^ X0, wKey[29] ^ X1, wKey[30] ^ X2, wKey[31] ^ X3); LT();
+            Sb0(wKey[32] ^ X0, wKey[33] ^ X1, wKey[34] ^ X2, wKey[35] ^ X3); LT();
+            Sb1(wKey[36] ^ X0, wKey[37] ^ X1, wKey[38] ^ X2, wKey[39] ^ X3); LT();
+            Sb2(wKey[40] ^ X0, wKey[41] ^ X1, wKey[42] ^ X2, wKey[43] ^ X3); LT();
+            Sb3(wKey[44] ^ X0, wKey[45] ^ X1, wKey[46] ^ X2, wKey[47] ^ X3); LT();
+            Sb4(wKey[48] ^ X0, wKey[49] ^ X1, wKey[50] ^ X2, wKey[51] ^ X3); LT();
+            Sb5(wKey[52] ^ X0, wKey[53] ^ X1, wKey[54] ^ X2, wKey[55] ^ X3); LT();
+            Sb6(wKey[56] ^ X0, wKey[57] ^ X1, wKey[58] ^ X2, wKey[59] ^ X3); LT();
+            Sb7(wKey[60] ^ X0, wKey[61] ^ X1, wKey[62] ^ X2, wKey[63] ^ X3); LT();
+            Sb0(wKey[64] ^ X0, wKey[65] ^ X1, wKey[66] ^ X2, wKey[67] ^ X3); LT();
+            Sb1(wKey[68] ^ X0, wKey[69] ^ X1, wKey[70] ^ X2, wKey[71] ^ X3); LT();
+            Sb2(wKey[72] ^ X0, wKey[73] ^ X1, wKey[74] ^ X2, wKey[75] ^ X3); LT();
+            Sb3(wKey[76] ^ X0, wKey[77] ^ X1, wKey[78] ^ X2, wKey[79] ^ X3); LT();
+            Sb4(wKey[80] ^ X0, wKey[81] ^ X1, wKey[82] ^ X2, wKey[83] ^ X3); LT();
+            Sb5(wKey[84] ^ X0, wKey[85] ^ X1, wKey[86] ^ X2, wKey[87] ^ X3); LT();
+            Sb6(wKey[88] ^ X0, wKey[89] ^ X1, wKey[90] ^ X2, wKey[91] ^ X3); LT();
+            Sb7(wKey[92] ^ X0, wKey[93] ^ X1, wKey[94] ^ X2, wKey[95] ^ X3); LT();
+            Sb0(wKey[96] ^ X0, wKey[97] ^ X1, wKey[98] ^ X2, wKey[99] ^ X3); LT();
+            Sb1(wKey[100] ^ X0, wKey[101] ^ X1, wKey[102] ^ X2, wKey[103] ^ X3); LT();
+            Sb2(wKey[104] ^ X0, wKey[105] ^ X1, wKey[106] ^ X2, wKey[107] ^ X3); LT();
+            Sb3(wKey[108] ^ X0, wKey[109] ^ X1, wKey[110] ^ X2, wKey[111] ^ X3); LT();
+            Sb4(wKey[112] ^ X0, wKey[113] ^ X1, wKey[114] ^ X2, wKey[115] ^ X3); LT();
+            Sb5(wKey[116] ^ X0, wKey[117] ^ X1, wKey[118] ^ X2, wKey[119] ^ X3); LT();
+            Sb6(wKey[120] ^ X0, wKey[121] ^ X1, wKey[122] ^ X2, wKey[123] ^ X3); LT();
+            Sb7(wKey[124] ^ X0, wKey[125] ^ X1, wKey[126] ^ X2, wKey[127] ^ X3);
+
+            WordToBytes(wKey[131] ^ X3, outBytes, outOff);
+            WordToBytes(wKey[130] ^ X2, outBytes, outOff + 4);
+            WordToBytes(wKey[129] ^ X1, outBytes, outOff + 8);
+            WordToBytes(wKey[128] ^ X0, outBytes, outOff + 12);
+        }
+
+        /**
+        * Decrypt one block of ciphertext.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        */
+        private void DecryptBlock(
+            byte[]  input,
+            int     inOff,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            X3 = wKey[131] ^ BytesToWord(input, inOff);
+            X2 = wKey[130] ^ BytesToWord(input, inOff + 4);
+            X1 = wKey[129] ^ BytesToWord(input, inOff + 8);
+            X0 = wKey[128] ^ BytesToWord(input, inOff + 12);
+
+            Ib7(X0, X1, X2, X3);
+            X0 ^= wKey[124]; X1 ^= wKey[125]; X2 ^= wKey[126]; X3 ^= wKey[127];
+            InverseLT(); Ib6(X0, X1, X2, X3);
+            X0 ^= wKey[120]; X1 ^= wKey[121]; X2 ^= wKey[122]; X3 ^= wKey[123];
+            InverseLT(); Ib5(X0, X1, X2, X3);
+            X0 ^= wKey[116]; X1 ^= wKey[117]; X2 ^= wKey[118]; X3 ^= wKey[119];
+            InverseLT(); Ib4(X0, X1, X2, X3);
+            X0 ^= wKey[112]; X1 ^= wKey[113]; X2 ^= wKey[114]; X3 ^= wKey[115];
+            InverseLT(); Ib3(X0, X1, X2, X3);
+            X0 ^= wKey[108]; X1 ^= wKey[109]; X2 ^= wKey[110]; X3 ^= wKey[111];
+            InverseLT(); Ib2(X0, X1, X2, X3);
+            X0 ^= wKey[104]; X1 ^= wKey[105]; X2 ^= wKey[106]; X3 ^= wKey[107];
+            InverseLT(); Ib1(X0, X1, X2, X3);
+            X0 ^= wKey[100]; X1 ^= wKey[101]; X2 ^= wKey[102]; X3 ^= wKey[103];
+            InverseLT(); Ib0(X0, X1, X2, X3);
+            X0 ^= wKey[96]; X1 ^= wKey[97]; X2 ^= wKey[98]; X3 ^= wKey[99];
+            InverseLT(); Ib7(X0, X1, X2, X3);
+            X0 ^= wKey[92]; X1 ^= wKey[93]; X2 ^= wKey[94]; X3 ^= wKey[95];
+            InverseLT(); Ib6(X0, X1, X2, X3);
+            X0 ^= wKey[88]; X1 ^= wKey[89]; X2 ^= wKey[90]; X3 ^= wKey[91];
+            InverseLT(); Ib5(X0, X1, X2, X3);
+            X0 ^= wKey[84]; X1 ^= wKey[85]; X2 ^= wKey[86]; X3 ^= wKey[87];
+            InverseLT(); Ib4(X0, X1, X2, X3);
+            X0 ^= wKey[80]; X1 ^= wKey[81]; X2 ^= wKey[82]; X3 ^= wKey[83];
+            InverseLT(); Ib3(X0, X1, X2, X3);
+            X0 ^= wKey[76]; X1 ^= wKey[77]; X2 ^= wKey[78]; X3 ^= wKey[79];
+            InverseLT(); Ib2(X0, X1, X2, X3);
+            X0 ^= wKey[72]; X1 ^= wKey[73]; X2 ^= wKey[74]; X3 ^= wKey[75];
+            InverseLT(); Ib1(X0, X1, X2, X3);
+            X0 ^= wKey[68]; X1 ^= wKey[69]; X2 ^= wKey[70]; X3 ^= wKey[71];
+            InverseLT(); Ib0(X0, X1, X2, X3);
+            X0 ^= wKey[64]; X1 ^= wKey[65]; X2 ^= wKey[66]; X3 ^= wKey[67];
+            InverseLT(); Ib7(X0, X1, X2, X3);
+            X0 ^= wKey[60]; X1 ^= wKey[61]; X2 ^= wKey[62]; X3 ^= wKey[63];
+            InverseLT(); Ib6(X0, X1, X2, X3);
+            X0 ^= wKey[56]; X1 ^= wKey[57]; X2 ^= wKey[58]; X3 ^= wKey[59];
+            InverseLT(); Ib5(X0, X1, X2, X3);
+            X0 ^= wKey[52]; X1 ^= wKey[53]; X2 ^= wKey[54]; X3 ^= wKey[55];
+            InverseLT(); Ib4(X0, X1, X2, X3);
+            X0 ^= wKey[48]; X1 ^= wKey[49]; X2 ^= wKey[50]; X3 ^= wKey[51];
+            InverseLT(); Ib3(X0, X1, X2, X3);
+            X0 ^= wKey[44]; X1 ^= wKey[45]; X2 ^= wKey[46]; X3 ^= wKey[47];
+            InverseLT(); Ib2(X0, X1, X2, X3);
+            X0 ^= wKey[40]; X1 ^= wKey[41]; X2 ^= wKey[42]; X3 ^= wKey[43];
+            InverseLT(); Ib1(X0, X1, X2, X3);
+            X0 ^= wKey[36]; X1 ^= wKey[37]; X2 ^= wKey[38]; X3 ^= wKey[39];
+            InverseLT(); Ib0(X0, X1, X2, X3);
+            X0 ^= wKey[32]; X1 ^= wKey[33]; X2 ^= wKey[34]; X3 ^= wKey[35];
+            InverseLT(); Ib7(X0, X1, X2, X3);
+            X0 ^= wKey[28]; X1 ^= wKey[29]; X2 ^= wKey[30]; X3 ^= wKey[31];
+            InverseLT(); Ib6(X0, X1, X2, X3);
+            X0 ^= wKey[24]; X1 ^= wKey[25]; X2 ^= wKey[26]; X3 ^= wKey[27];
+            InverseLT(); Ib5(X0, X1, X2, X3);
+            X0 ^= wKey[20]; X1 ^= wKey[21]; X2 ^= wKey[22]; X3 ^= wKey[23];
+            InverseLT(); Ib4(X0, X1, X2, X3);
+            X0 ^= wKey[16]; X1 ^= wKey[17]; X2 ^= wKey[18]; X3 ^= wKey[19];
+            InverseLT(); Ib3(X0, X1, X2, X3);
+            X0 ^= wKey[12]; X1 ^= wKey[13]; X2 ^= wKey[14]; X3 ^= wKey[15];
+            InverseLT(); Ib2(X0, X1, X2, X3);
+            X0 ^= wKey[8]; X1 ^= wKey[9]; X2 ^= wKey[10]; X3 ^= wKey[11];
+            InverseLT(); Ib1(X0, X1, X2, X3);
+            X0 ^= wKey[4]; X1 ^= wKey[5]; X2 ^= wKey[6]; X3 ^= wKey[7];
+            InverseLT(); Ib0(X0, X1, X2, X3);
+
+            WordToBytes(X3 ^ wKey[3], outBytes, outOff);
+            WordToBytes(X2 ^ wKey[2], outBytes, outOff + 4);
+            WordToBytes(X1 ^ wKey[1], outBytes, outOff + 8);
+            WordToBytes(X0 ^ wKey[0], outBytes, outOff + 12);
+        }
+
+        /*
+        * The sboxes below are based on the work of Brian Gladman and
+        * Sam Simpson, whose original notice appears below.
+        * <p>
+        * For further details see:
+        *      http://fp.gladman.plus.com/cryptography_technology/serpent/
+		* </p>
+        */
+
+        /* Partially optimised Serpent S Box bool functions derived  */
+        /* using a recursive descent analyser but without a full search */
+        /* of all subtrees. This set of S boxes is the result of work    */
+        /* by Sam Simpson and Brian Gladman using the spare time on a    */
+        /* cluster of high capacity servers to search for S boxes with    */
+        /* this customised search engine. There are now an average of    */
+        /* 15.375 terms    per S box.                                        */
+        /*                                                              */
+        /* Copyright:   Dr B. R Gladman (gladman at seven77.demon.co.uk)   */
+        /*                and Sam Simpson (s.simpson at mia.co.uk)            */
+        /*              17th December 1998                                */
+        /*                                                              */
+        /* We hereby give permission for information in this file to be */
+        /* used freely subject only to acknowledgement of its origin.    */
+
+        /**
+        * S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+        */
+        private void Sb0(int a, int b, int c, int d)
+        {
+            int    t1 = a ^ d;
+            int    t3 = c ^ t1;
+            int    t4 = b ^ t3;
+            X3 = (a & d) ^ t4;
+            int    t7 = a ^ (b & t1);
+            X2 = t4 ^ (c | t7);
+            int    t12 = X3 & (t3 ^ t7);
+            X1 = (~t3) ^ t12;
+            X0 = t12 ^ (~t7);
+        }
+
+        /**
+        * InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+        */
+        private void Ib0(int a, int b, int c, int d)
+        {
+            int    t1 = ~a;
+            int    t2 = a ^ b;
+            int    t4 = d ^ (t1 | t2);
+            int    t5 = c ^ t4;
+            X2 = t2 ^ t5;
+            int    t8 = t1 ^ (d & t2);
+            X1 = t4 ^ (X2 & t8);
+            X3 = (a & t4) ^ (t5 | X1);
+            X0 = X3 ^ (t5 ^ t8);
+        }
+
+        /**
+        * S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+        */
+        private void Sb1(int a, int b, int c, int d)
+        {
+            int    t2 = b ^ (~a);
+            int    t5 = c ^ (a | t2);
+            X2 = d ^ t5;
+            int    t7 = b ^ (d | t2);
+            int    t8 = t2 ^ X2;
+            X3 = t8 ^ (t5 & t7);
+            int    t11 = t5 ^ t7;
+            X1 = X3 ^ t11;
+            X0 = t5 ^ (t8 & t11);
+        }
+
+        /**
+        * InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+        */
+        private void Ib1(int a, int b, int c, int d)
+        {
+            int    t1 = b ^ d;
+            int    t3 = a ^ (b & t1);
+            int    t4 = t1 ^ t3;
+            X3 = c ^ t4;
+            int    t7 = b ^ (t1 & t3);
+            int    t8 = X3 | t7;
+            X1 = t3 ^ t8;
+            int    t10 = ~X1;
+            int    t11 = X3 ^ t7;
+            X0 = t10 ^ t11;
+            X2 = t4 ^ (t10 | t11);
+        }
+
+        /**
+        * S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+        */
+        private void Sb2(int a, int b, int c, int d)
+        {
+            int    t1 = ~a;
+            int    t2 = b ^ d;
+            int    t3 = c & t1;
+            X0 = t2 ^ t3;
+            int    t5 = c ^ t1;
+            int    t6 = c ^ X0;
+            int    t7 = b & t6;
+            X3 = t5 ^ t7;
+            X2 = a ^ ((d | t7) & (X0 | t5));
+            X1 = (t2 ^ X3) ^ (X2 ^ (d | t1));
+        }
+
+        /**
+        * InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+        */
+        private void Ib2(int a, int b, int c, int d)
+        {
+            int    t1 = b ^ d;
+            int    t2 = ~t1;
+            int    t3 = a ^ c;
+            int    t4 = c ^ t1;
+            int    t5 = b & t4;
+            X0 = t3 ^ t5;
+            int    t7 = a | t2;
+            int    t8 = d ^ t7;
+            int    t9 = t3 | t8;
+            X3 = t1 ^ t9;
+            int    t11 = ~t4;
+            int    t12 = X0 | X3;
+            X1 = t11 ^ t12;
+            X2 = (d & t11) ^ (t3 ^ t12);
+        }
+
+        /**
+        * S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+        */
+        private void Sb3(int a, int b, int c, int d)
+        {
+            int    t1 = a ^ b;
+            int    t2 = a & c;
+            int    t3 = a | d;
+            int    t4 = c ^ d;
+            int    t5 = t1 & t3;
+            int    t6 = t2 | t5;
+            X2 = t4 ^ t6;
+            int    t8 = b ^ t3;
+            int    t9 = t6 ^ t8;
+            int    t10 = t4 & t9;
+            X0 = t1 ^ t10;
+            int    t12 = X2 & X0;
+            X1 = t9 ^ t12;
+            X3 = (b | d) ^ (t4 ^ t12);
+        }
+
+        /**
+        * InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+        */
+        private void Ib3(int a, int b, int c, int d)
+        {
+            int    t1 = a | b;
+            int    t2 = b ^ c;
+            int    t3 = b & t2;
+            int    t4 = a ^ t3;
+            int    t5 = c ^ t4;
+            int    t6 = d | t4;
+            X0 = t2 ^ t6;
+            int    t8 = t2 | t6;
+            int    t9 = d ^ t8;
+            X2 = t5 ^ t9;
+            int    t11 = t1 ^ t9;
+            int    t12 = X0 & t11;
+            X3 = t4 ^ t12;
+            X1 = X3 ^ (X0 ^ t11);
+        }
+
+        /**
+        * S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+        */
+        private void Sb4(int a, int b, int c, int d)
+        {
+            int    t1 = a ^ d;
+            int    t2 = d & t1;
+            int    t3 = c ^ t2;
+            int    t4 = b | t3;
+            X3 = t1 ^ t4;
+            int    t6 = ~b;
+            int    t7 = t1 | t6;
+            X0 = t3 ^ t7;
+            int    t9 = a & X0;
+            int    t10 = t1 ^ t6;
+            int    t11 = t4 & t10;
+            X2 = t9 ^ t11;
+            X1 = (a ^ t3) ^ (t10 & X2);
+        }
+
+        /**
+        * InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+        */
+        private void Ib4(int a, int b, int c, int d)
+        {
+            int    t1 = c | d;
+            int    t2 = a & t1;
+            int    t3 = b ^ t2;
+            int    t4 = a & t3;
+            int    t5 = c ^ t4;
+            X1 = d ^ t5;
+            int    t7 = ~a;
+            int    t8 = t5 & X1;
+            X3 = t3 ^ t8;
+            int    t10 = X1 | t7;
+            int    t11 = d ^ t10;
+            X0 = X3 ^ t11;
+            X2 = (t3 & t11) ^ (X1 ^ t7);
+        }
+
+        /**
+        * S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+        */
+        private void Sb5(int a, int b, int c, int d)
+        {
+            int    t1 = ~a;
+            int    t2 = a ^ b;
+            int    t3 = a ^ d;
+            int    t4 = c ^ t1;
+            int    t5 = t2 | t3;
+            X0 = t4 ^ t5;
+            int    t7 = d & X0;
+            int    t8 = t2 ^ X0;
+            X1 = t7 ^ t8;
+            int    t10 = t1 | X0;
+            int    t11 = t2 | t7;
+            int    t12 = t3 ^ t10;
+            X2 = t11 ^ t12;
+            X3 = (b ^ t7) ^ (X1 & t12);
+        }
+
+        /**
+        * InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+        */
+        private void Ib5(int a, int b, int c, int d)
+        {
+            int    t1 = ~c;
+            int    t2 = b & t1;
+            int    t3 = d ^ t2;
+            int    t4 = a & t3;
+            int    t5 = b ^ t1;
+            X3 = t4 ^ t5;
+            int    t7 = b | X3;
+            int    t8 = a & t7;
+            X1 = t3 ^ t8;
+            int    t10 = a | d;
+            int    t11 = t1 ^ t7;
+            X0 = t10 ^ t11;
+            X2 = (b & t10) ^ (t4 | (a ^ c));
+        }
+
+        /**
+        * S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+        */
+        private void Sb6(int a, int b, int c, int d)
+        {
+            int    t1 = ~a;
+            int    t2 = a ^ d;
+            int    t3 = b ^ t2;
+            int    t4 = t1 | t2;
+            int    t5 = c ^ t4;
+            X1 = b ^ t5;
+            int    t7 = t2 | X1;
+            int    t8 = d ^ t7;
+            int    t9 = t5 & t8;
+            X2 = t3 ^ t9;
+            int    t11 = t5 ^ t8;
+            X0 = X2 ^ t11;
+            X3 = (~t5) ^ (t3 & t11);
+        }
+
+        /**
+        * InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+        */
+        private void Ib6(int a, int b, int c, int d)
+        {
+            int    t1 = ~a;
+            int    t2 = a ^ b;
+            int    t3 = c ^ t2;
+            int    t4 = c | t1;
+            int    t5 = d ^ t4;
+            X1 = t3 ^ t5;
+            int    t7 = t3 & t5;
+            int    t8 = t2 ^ t7;
+            int    t9 = b | t8;
+            X3 = t5 ^ t9;
+            int    t11 = b | X3;
+            X0 = t8 ^ t11;
+            X2 = (d & t1) ^ (t3 ^ t11);
+        }
+
+        /**
+        * S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+        */
+        private void Sb7(int a, int b, int c, int d)
+        {
+            int    t1 = b ^ c;
+            int    t2 = c & t1;
+            int    t3 = d ^ t2;
+            int    t4 = a ^ t3;
+            int    t5 = d | t1;
+            int    t6 = t4 & t5;
+            X1 = b ^ t6;
+            int    t8 = t3 | X1;
+            int    t9 = a & t4;
+            X3 = t1 ^ t9;
+            int    t11 = t4 ^ t8;
+            int    t12 = X3 & t11;
+            X2 = t3 ^ t12;
+            X0 = (~t11) ^ (X3 & X2);
+        }
+
+        /**
+        * InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+        */
+        private void Ib7(int a, int b, int c, int d)
+        {
+            int t3 = c | (a & b);
+            int    t4 = d & (a | b);
+            X3 = t3 ^ t4;
+            int    t6 = ~d;
+            int    t7 = b ^ t4;
+            int    t9 = t7 | (X3 ^ t6);
+            X1 = a ^ t9;
+            X0 = (c ^ t7) ^ (d | X1);
+            X2 = (t3 ^ X1) ^ (X0 ^ (a & X3));
+        }
+
+        /**
+        * Apply the linear transformation to the register set.
+        */
+        private void LT()
+        {
+            int x0  = RotateLeft(X0, 13);
+            int x2  = RotateLeft(X2, 3);
+            int x1  = X1 ^ x0 ^ x2 ;
+            int x3  = X3 ^ x2 ^ x0 << 3;
+
+            X1  = RotateLeft(x1, 1);
+            X3  = RotateLeft(x3, 7);
+            X0  = RotateLeft(x0 ^ X1 ^ X3, 5);
+            X2  = RotateLeft(x2 ^ X3 ^ (X1 << 7), 22);
+        }
+
+        /**
+        * Apply the inverse of the linear transformation to the register set.
+        */
+        private void InverseLT()
+        {
+            int x2 = RotateRight(X2, 22) ^ X3 ^ (X1 << 7);
+            int x0 = RotateRight(X0, 5) ^ X1 ^ X3;
+            int x3 = RotateRight(X3, 7);
+            int x1 = RotateRight(X1, 1);
+            X3 = x3 ^ x2 ^ x0 << 3;
+            X1 = x1 ^ x0 ^ x2;
+            X2 = RotateRight(x2, 3);
+            X0 = RotateRight(x0, 13);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/SkipjackEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/SkipjackEngine.cs
new file mode 100644
index 0000000..3d2a781
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/SkipjackEngine.cs
@@ -0,0 +1,255 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * a class that provides a basic SKIPJACK engine.
+    */
+    public class SkipjackEngine
+		: IBlockCipher
+    {
+        const int BLOCK_SIZE = 8;
+
+        static readonly short [] ftable =
+        {
+            0xa3, 0xd7, 0x09, 0x83, 0xf8, 0x48, 0xf6, 0xf4, 0xb3, 0x21, 0x15, 0x78, 0x99, 0xb1, 0xaf, 0xf9,
+            0xe7, 0x2d, 0x4d, 0x8a, 0xce, 0x4c, 0xca, 0x2e, 0x52, 0x95, 0xd9, 0x1e, 0x4e, 0x38, 0x44, 0x28,
+            0x0a, 0xdf, 0x02, 0xa0, 0x17, 0xf1, 0x60, 0x68, 0x12, 0xb7, 0x7a, 0xc3, 0xe9, 0xfa, 0x3d, 0x53,
+            0x96, 0x84, 0x6b, 0xba, 0xf2, 0x63, 0x9a, 0x19, 0x7c, 0xae, 0xe5, 0xf5, 0xf7, 0x16, 0x6a, 0xa2,
+            0x39, 0xb6, 0x7b, 0x0f, 0xc1, 0x93, 0x81, 0x1b, 0xee, 0xb4, 0x1a, 0xea, 0xd0, 0x91, 0x2f, 0xb8,
+            0x55, 0xb9, 0xda, 0x85, 0x3f, 0x41, 0xbf, 0xe0, 0x5a, 0x58, 0x80, 0x5f, 0x66, 0x0b, 0xd8, 0x90,
+            0x35, 0xd5, 0xc0, 0xa7, 0x33, 0x06, 0x65, 0x69, 0x45, 0x00, 0x94, 0x56, 0x6d, 0x98, 0x9b, 0x76,
+            0x97, 0xfc, 0xb2, 0xc2, 0xb0, 0xfe, 0xdb, 0x20, 0xe1, 0xeb, 0xd6, 0xe4, 0xdd, 0x47, 0x4a, 0x1d,
+            0x42, 0xed, 0x9e, 0x6e, 0x49, 0x3c, 0xcd, 0x43, 0x27, 0xd2, 0x07, 0xd4, 0xde, 0xc7, 0x67, 0x18,
+            0x89, 0xcb, 0x30, 0x1f, 0x8d, 0xc6, 0x8f, 0xaa, 0xc8, 0x74, 0xdc, 0xc9, 0x5d, 0x5c, 0x31, 0xa4,
+            0x70, 0x88, 0x61, 0x2c, 0x9f, 0x0d, 0x2b, 0x87, 0x50, 0x82, 0x54, 0x64, 0x26, 0x7d, 0x03, 0x40,
+            0x34, 0x4b, 0x1c, 0x73, 0xd1, 0xc4, 0xfd, 0x3b, 0xcc, 0xfb, 0x7f, 0xab, 0xe6, 0x3e, 0x5b, 0xa5,
+            0xad, 0x04, 0x23, 0x9c, 0x14, 0x51, 0x22, 0xf0, 0x29, 0x79, 0x71, 0x7e, 0xff, 0x8c, 0x0e, 0xe2,
+            0x0c, 0xef, 0xbc, 0x72, 0x75, 0x6f, 0x37, 0xa1, 0xec, 0xd3, 0x8e, 0x62, 0x8b, 0x86, 0x10, 0xe8,
+            0x08, 0x77, 0x11, 0xbe, 0x92, 0x4f, 0x24, 0xc5, 0x32, 0x36, 0x9d, 0xcf, 0xf3, 0xa6, 0xbb, 0xac,
+            0x5e, 0x6c, 0xa9, 0x13, 0x57, 0x25, 0xb5, 0xe3, 0xbd, 0xa8, 0x3a, 0x01, 0x05, 0x59, 0x2a, 0x46
+        };
+
+        private int[] key0, key1, key2, key3;
+        private bool encrypting;
+
+        /**
+        * initialise a SKIPJACK cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is KeyParameter))
+	            throw new ArgumentException("invalid parameter passed to SKIPJACK init - " + parameters.GetType().ToString());
+
+			byte[] keyBytes = ((KeyParameter)parameters).GetKey();
+
+            this.encrypting = forEncryption;
+            this.key0 = new int[32];
+            this.key1 = new int[32];
+            this.key2 = new int[32];
+            this.key3 = new int[32];
+
+            //
+            // expand the key to 128 bytes in 4 parts (saving us a modulo, multiply
+            // and an addition).
+            //
+            for (int i = 0; i < 32; i ++)
+            {
+                key0[i] = keyBytes[(i * 4) % 10] & 0xff;
+                key1[i] = keyBytes[(i * 4 + 1) % 10] & 0xff;
+                key2[i] = keyBytes[(i * 4 + 2) % 10] & 0xff;
+                key3[i] = keyBytes[(i * 4 + 3) % 10] & 0xff;
+            }
+        }
+
+        public string AlgorithmName
+        {
+            get { return "SKIPJACK"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (key1 == null)
+                throw new InvalidOperationException("SKIPJACK engine not initialised");
+            if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+			if (encrypting)
+            {
+                EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                DecryptBlock(input, inOff, output, outOff);
+            }
+
+			return BLOCK_SIZE;
+        }
+
+		public void Reset()
+        {
+        }
+
+        /**
+        * The G permutation
+        */
+        private int G(
+            int     k,
+            int     w)
+        {
+            int g1, g2, g3, g4, g5, g6;
+
+            g1 = (w >> 8) & 0xff;
+            g2 = w & 0xff;
+
+            g3 = ftable[g2 ^ key0[k]] ^ g1;
+            g4 = ftable[g3 ^ key1[k]] ^ g2;
+            g5 = ftable[g4 ^ key2[k]] ^ g3;
+            g6 = ftable[g5 ^ key3[k]] ^ g4;
+
+            return ((g5 << 8) + g6);
+        }
+
+        public int EncryptBlock(
+            byte[]      input,
+            int         inOff,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            int w1 = (input[inOff + 0] << 8) + (input[inOff + 1] & 0xff);
+            int w2 = (input[inOff + 2] << 8) + (input[inOff + 3] & 0xff);
+            int w3 = (input[inOff + 4] << 8) + (input[inOff + 5] & 0xff);
+            int w4 = (input[inOff + 6] << 8) + (input[inOff + 7] & 0xff);
+
+            int k = 0;
+
+            for (int t = 0; t < 2; t++)
+            {
+                for(int i = 0; i < 8; i++)
+                {
+                    int tmp = w4;
+                    w4 = w3;
+                    w3 = w2;
+                    w2 = G(k, w1);
+                    w1 = w2 ^ tmp ^ (k + 1);
+                    k++;
+                }
+
+                for(int i = 0; i < 8; i++)
+                {
+                    int tmp = w4;
+                    w4 = w3;
+                    w3 = w1 ^ w2 ^ (k + 1);
+                    w2 = G(k, w1);
+                    w1 = tmp;
+                    k++;
+                }
+            }
+
+            outBytes[outOff + 0] = (byte)((w1 >> 8));
+            outBytes[outOff + 1] = (byte)(w1);
+            outBytes[outOff + 2] = (byte)((w2 >> 8));
+            outBytes[outOff + 3] = (byte)(w2);
+            outBytes[outOff + 4] = (byte)((w3 >> 8));
+            outBytes[outOff + 5] = (byte)(w3);
+            outBytes[outOff + 6] = (byte)((w4 >> 8));
+            outBytes[outOff + 7] = (byte)(w4);
+
+            return BLOCK_SIZE;
+        }
+
+        /**
+        * the inverse of the G permutation.
+        */
+        private int H(
+            int     k,
+            int     w)
+        {
+            int h1, h2, h3, h4, h5, h6;
+
+            h1 = w & 0xff;
+            h2 = (w >> 8) & 0xff;
+
+            h3 = ftable[h2 ^ key3[k]] ^ h1;
+            h4 = ftable[h3 ^ key2[k]] ^ h2;
+            h5 = ftable[h4 ^ key1[k]] ^ h3;
+            h6 = ftable[h5 ^ key0[k]] ^ h4;
+
+            return ((h6 << 8) + h5);
+        }
+
+        public int DecryptBlock(
+            byte[]      input,
+            int         inOff,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            int w2 = (input[inOff + 0] << 8) + (input[inOff + 1] & 0xff);
+            int w1 = (input[inOff + 2] << 8) + (input[inOff + 3] & 0xff);
+            int w4 = (input[inOff + 4] << 8) + (input[inOff + 5] & 0xff);
+            int w3 = (input[inOff + 6] << 8) + (input[inOff + 7] & 0xff);
+
+            int k = 31;
+
+            for (int t = 0; t < 2; t++)
+            {
+                for(int i = 0; i < 8; i++)
+                {
+                    int tmp = w4;
+                    w4 = w3;
+                    w3 = w2;
+                    w2 = H(k, w1);
+                    w1 = w2 ^ tmp ^ (k + 1);
+                    k--;
+                }
+
+                for(int i = 0; i < 8; i++)
+                {
+                    int tmp = w4;
+                    w4 = w3;
+                    w3 = w1 ^ w2 ^ (k + 1);
+                    w2 = H(k, w1);
+                    w1 = tmp;
+                    k--;
+                }
+            }
+
+            outBytes[outOff + 0] = (byte)((w2 >> 8));
+            outBytes[outOff + 1] = (byte)(w2);
+            outBytes[outOff + 2] = (byte)((w1 >> 8));
+            outBytes[outOff + 3] = (byte)(w1);
+            outBytes[outOff + 4] = (byte)((w4 >> 8));
+            outBytes[outOff + 5] = (byte)(w4);
+            outBytes[outOff + 6] = (byte)((w3 >> 8));
+            outBytes[outOff + 7] = (byte)(w3);
+
+            return BLOCK_SIZE;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/TEAEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/TEAEngine.cs
new file mode 100644
index 0000000..582dd0f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/TEAEngine.cs
@@ -0,0 +1,168 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* An TEA engine.
+	*/
+	public class TeaEngine
+		: IBlockCipher
+	{
+		private const int
+			rounds		= 32,
+			block_size	= 8;
+//			key_size	= 16,
+
+		private const uint 
+			delta		= 0x9E3779B9,
+			d_sum		= 0xC6EF3720; // sum on decrypt
+
+		/*
+		* the expanded key array of 4 subkeys
+		*/
+		private uint _a, _b, _c, _d;
+		private bool _initialised;
+		private bool _forEncryption;
+
+		/**
+		* Create an instance of the TEA encryption algorithm
+		* and set some defaults
+		*/
+		public TeaEngine()
+		{
+			_initialised = false;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "TEA"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return block_size;
+		}
+
+		/**
+		* initialise
+		*
+		* @param forEncryption whether or not we are for encryption.
+		* @param params the parameters required to set up the cipher.
+		* @exception ArgumentException if the params argument is
+		* inappropriate.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is KeyParameter))
+			{
+				throw new ArgumentException("invalid parameter passed to TEA init - "
+					+ parameters.GetType().FullName);
+			}
+
+			_forEncryption = forEncryption;
+			_initialised = true;
+
+			KeyParameter p = (KeyParameter) parameters;
+
+			setKey(p.GetKey());
+		}
+
+		public int ProcessBlock(
+			byte[]  inBytes,
+			int     inOff,
+			byte[]  outBytes,
+			int     outOff)
+		{
+			if (!_initialised)
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+
+			if ((inOff + block_size) > inBytes.Length)
+				throw new DataLengthException("input buffer too short");
+
+			if ((outOff + block_size) > outBytes.Length)
+				throw new DataLengthException("output buffer too short");
+
+			return _forEncryption
+				?	encryptBlock(inBytes, inOff, outBytes, outOff)
+				:	decryptBlock(inBytes, inOff, outBytes, outOff);
+		}
+
+		public void Reset()
+		{
+		}
+
+		/**
+		* Re-key the cipher.
+		*
+		* @param  key  the key to be used
+		*/
+		private void setKey(
+			byte[] key)
+		{
+			_a = Pack.BE_To_UInt32(key, 0);
+			_b = Pack.BE_To_UInt32(key, 4);
+			_c = Pack.BE_To_UInt32(key, 8);
+			_d = Pack.BE_To_UInt32(key, 12);
+		}
+
+		private int encryptBlock(
+			byte[]	inBytes,
+			int		inOff,
+			byte[]	outBytes,
+			int		outOff)
+		{
+			// Pack bytes into integers
+			uint v0 = Pack.BE_To_UInt32(inBytes, inOff);
+			uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4);
+	        
+			uint sum = 0;
+	        
+			for (int i = 0; i != rounds; i++)
+			{
+				sum += delta;
+				v0  += ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >> 5) + _b);
+				v1  += ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >> 5) + _d);
+			}
+
+			Pack.UInt32_To_BE(v0, outBytes, outOff);
+			Pack.UInt32_To_BE(v1, outBytes, outOff + 4);
+
+			return block_size;
+		}
+
+		private int decryptBlock(
+			byte[]	inBytes,
+			int		inOff,
+			byte[]	outBytes,
+			int		outOff)
+		{
+			// Pack bytes into integers
+			uint v0 = Pack.BE_To_UInt32(inBytes, inOff);
+			uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4);
+
+			uint sum = d_sum;
+
+			for (int i = 0; i != rounds; i++)
+			{
+				v1  -= ((v0 << 4) + _c) ^ (v0 + sum) ^ ((v0 >> 5) + _d);
+				v0  -= ((v1 << 4) + _a) ^ (v1 + sum) ^ ((v1 >> 5) + _b);
+				sum -= delta;
+			}
+
+			Pack.UInt32_To_BE(v0, outBytes, outOff);
+			Pack.UInt32_To_BE(v1, outBytes, outOff + 4);
+
+			return block_size;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/ThreefishEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/ThreefishEngine.cs
new file mode 100644
index 0000000..9544703
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/ThreefishEngine.cs
@@ -0,0 +1,1490 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <summary>
+	/// Implementation of the Threefish tweakable large block cipher in 256, 512 and 1024 bit block
+	/// sizes.
+	/// </summary>
+	/// <remarks>
+	/// This is the 1.3 version of Threefish defined in the Skein hash function submission to the NIST
+	/// SHA-3 competition in October 2010.
+	/// <p/>
+	/// Threefish was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+	/// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+	/// <p/>
+	/// This implementation inlines all round functions, unrolls 8 rounds, and uses 1.2k of static tables
+	/// to speed up key schedule injection. <br/>
+	/// 2 x block size state is retained by each cipher instance.
+	/// </remarks>
+	public class ThreefishEngine
+		: IBlockCipher
+	{
+		/// <summary>
+		/// 256 bit block size - Threefish-256
+		/// </summary>
+		public const int BLOCKSIZE_256 = 256;
+		/// <summary>
+		/// 512 bit block size - Threefish-512
+		/// </summary>
+		public const int BLOCKSIZE_512 = 512;
+		/// <summary>
+		/// 1024 bit block size - Threefish-1024
+		/// </summary>
+		public const int BLOCKSIZE_1024 = 1024;
+
+		/**
+	     * Size of the tweak in bytes (always 128 bit/16 bytes)
+	     */
+		private const int TWEAK_SIZE_BYTES = 16;
+		private const int TWEAK_SIZE_WORDS = TWEAK_SIZE_BYTES / 8;
+
+		/**
+	     * Rounds in Threefish-256
+	     */
+		private const int ROUNDS_256 = 72;
+		/**
+	     * Rounds in Threefish-512
+	     */
+		private const int ROUNDS_512 = 72;
+		/**
+	     * Rounds in Threefish-1024
+	     */
+		private const int ROUNDS_1024 = 80;
+
+		/**
+	     * Max rounds of any of the variants
+	     */
+		private const int MAX_ROUNDS = ROUNDS_1024;
+
+		/**
+	     * Key schedule parity constant
+	     */
+		private const ulong C_240 = 0x1BD11BDAA9FC1A22L;
+
+		/* Pre-calculated modulo arithmetic tables for key schedule lookups */
+		private static readonly int[] MOD9 = new int[MAX_ROUNDS];
+		private static readonly int[] MOD17 = new int[MOD9.Length];
+		private static readonly int[] MOD5 = new int[MOD9.Length];
+		private static readonly int[] MOD3 = new int[MOD9.Length];
+
+		static ThreefishEngine()
+		{
+			for (int i = 0; i < MOD9.Length; i++)
+			{
+				MOD17[i] = i % 17;
+				MOD9[i] = i % 9;
+				MOD5[i] = i % 5;
+				MOD3[i] = i % 3;
+			}
+		}
+
+		/**
+	     * Block size in bytes
+	     */
+		private readonly int blocksizeBytes;
+
+		/**
+	     * Block size in 64 bit words
+	     */
+		private readonly int blocksizeWords;
+
+		/**
+	     * Buffer for byte oriented processBytes to call internal word API
+	     */
+		private readonly ulong[] currentBlock;
+
+		/**
+	     * Tweak bytes (2 byte t1,t2, calculated t3 and repeat of t1,t2 for modulo free lookup
+	     */
+		private readonly ulong[] t = new ulong[5];
+
+		/**
+	     * Key schedule words
+	     */
+		private readonly ulong[] kw;
+
+		/**
+	     * The internal cipher implementation (varies by blocksize)
+	     */
+		private readonly ThreefishCipher cipher;
+
+		private bool forEncryption;
+
+		/// <summary>
+		/// Constructs a new Threefish cipher, with a specified block size.
+		/// </summary>
+		/// <param name="blocksizeBits">the block size in bits, one of <see cref="BLOCKSIZE_256"/>, <see cref="BLOCKSIZE_512"/>,
+		///                      <see cref="BLOCKSIZE_1024"/> .</param>
+		public ThreefishEngine(int blocksizeBits)
+		{
+			this.blocksizeBytes = (blocksizeBits / 8);
+			this.blocksizeWords = (this.blocksizeBytes / 8);
+			this.currentBlock = new ulong[blocksizeWords];
+
+			/*
+	         * Provide room for original key words, extended key word and repeat of key words for modulo
+	         * free lookup of key schedule words.
+	         */
+			this.kw = new ulong[2 * blocksizeWords + 1];
+
+			switch (blocksizeBits)
+			{
+				case BLOCKSIZE_256:
+				cipher = new Threefish256Cipher(kw, t);
+				break;
+				case BLOCKSIZE_512:
+				cipher = new Threefish512Cipher(kw, t);
+				break;
+				case BLOCKSIZE_1024:
+				cipher = new Threefish1024Cipher(kw, t);
+				break;
+				default:
+				throw new ArgumentException(
+					"Invalid blocksize - Threefish is defined with block size of 256, 512, or 1024 bits");
+			}
+		}
+
+		/// <summary>
+		/// Initialise the engine.
+		/// </summary>
+		/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+		/// <param name="parameters">an instance of <see cref="TweakableBlockCipherParameters"/> or <see cref="KeyParameter"/> (to
+		///               use a 0 tweak)</param>
+		public void Init(bool forEncryption, ICipherParameters parameters)
+		{
+			byte[] keyBytes;
+			byte[] tweakBytes;
+
+			if (parameters is TweakableBlockCipherParameters)
+			{
+				TweakableBlockCipherParameters tParams = (TweakableBlockCipherParameters)parameters;
+				keyBytes = tParams.Key.GetKey();
+				tweakBytes = tParams.Tweak;
+			}
+			else if (parameters is KeyParameter)
+			{
+				keyBytes = ((KeyParameter)parameters).GetKey();
+				tweakBytes = null;
+			}
+			else
+			{
+				throw new ArgumentException("Invalid parameter passed to Threefish init - "
+				                            + parameters.GetType().Name);
+			}
+
+			ulong[] keyWords = null;
+			ulong[] tweakWords = null;
+
+			if (keyBytes != null)
+			{
+				if (keyBytes.Length != this.blocksizeBytes)
+				{
+					throw new ArgumentException("Threefish key must be same size as block (" + blocksizeBytes
+					                            + " bytes)");
+				}
+				keyWords = new ulong[blocksizeWords];
+				for (int i = 0; i < keyWords.Length; i++)
+				{
+					keyWords[i] = BytesToWord(keyBytes, i * 8);
+				}
+			}
+			if (tweakBytes != null)
+			{
+				if (tweakBytes.Length != TWEAK_SIZE_BYTES)
+				{
+					throw new ArgumentException("Threefish tweak must be " + TWEAK_SIZE_BYTES + " bytes");
+				}
+				tweakWords = new ulong[]{BytesToWord(tweakBytes, 0), BytesToWord(tweakBytes, 8)};
+			}
+			Init(forEncryption, keyWords, tweakWords);
+		}
+
+		/// <summary>
+		/// Initialise the engine, specifying the key and tweak directly.
+		/// </summary>
+		/// <param name="forEncryption">the cipher mode.</param>
+		/// <param name="key">the words of the key, or <code>null</code> to use the current key.</param>
+		/// <param name="tweak">the 2 word (128 bit) tweak, or <code>null</code> to use the current tweak.</param>
+		internal void Init(bool forEncryption, ulong[] key, ulong[] tweak)
+		{
+			this.forEncryption = forEncryption;
+			if (key != null)
+			{
+				SetKey(key);
+			}
+			if (tweak != null)
+			{
+				SetTweak(tweak);
+			}
+		}
+
+		private void SetKey(ulong[] key)
+		{
+			if (key.Length != this.blocksizeWords)
+			{
+				throw new ArgumentException("Threefish key must be same size as block (" + blocksizeWords
+				                            + " words)");
+			}
+
+			/*
+	         * Full subkey schedule is deferred to execution to avoid per cipher overhead (10k for 512,
+	         * 20k for 1024).
+	         * 
+	         * Key and tweak word sequences are repeated, and static MOD17/MOD9/MOD5/MOD3 calculations
+	         * used, to avoid expensive mod computations during cipher operation.
+	         */
+
+			ulong knw = C_240;
+			for (int i = 0; i < blocksizeWords; i++)
+			{
+				kw[i] = key[i];
+				knw = knw ^ kw[i];
+			}
+			kw[blocksizeWords] = knw;
+			Array.Copy(kw, 0, kw, blocksizeWords + 1, blocksizeWords);
+		}
+
+		private void SetTweak(ulong[] tweak)
+		{
+			if (tweak.Length != TWEAK_SIZE_WORDS)
+			{
+				throw new ArgumentException("Tweak must be " + TWEAK_SIZE_WORDS + " words.");
+			}
+
+			/*
+	         * Tweak schedule partially repeated to avoid mod computations during cipher operation
+	         */
+			t[0] = tweak[0];
+			t[1] = tweak[1];
+			t[2] = t[0] ^ t[1];
+			t[3] = t[0];
+			t[4] = t[1];
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Threefish-" + (blocksizeBytes * 8); }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return blocksizeBytes;
+		}
+
+		public void Reset()
+		{
+		}
+
+		public int ProcessBlock(byte[] inBytes, int inOff, byte[] outBytes, int outOff)
+		{
+			if ((outOff + blocksizeBytes) > outBytes.Length)
+			{
+				throw new DataLengthException("Output buffer too short");
+			}
+
+			if ((inOff + blocksizeBytes) > inBytes.Length)
+			{
+				throw new DataLengthException("Input buffer too short");
+			}
+
+			for (int i = 0; i < blocksizeBytes; i += 8)
+			{
+				currentBlock[i >> 3] = BytesToWord(inBytes, inOff + i);
+			}
+			ProcessBlock(this.currentBlock, this.currentBlock);
+			for (int i = 0; i < blocksizeBytes; i += 8)
+			{
+				WordToBytes(this.currentBlock[i >> 3], outBytes, outOff + i);
+			}
+
+			return blocksizeBytes;
+		}
+
+		/// <summary>
+		/// Process a block of data represented as 64 bit words.
+		/// </summary>
+		/// <returns>the number of 8 byte words processed (which will be the same as the block size).</returns>
+		/// <param name="inWords">a block sized buffer of words to process.</param>
+		/// <param name="outWords">a block sized buffer of words to receive the output of the operation.</param>
+		/// <exception cref="DataLengthException">if either the input or output is not block sized</exception>
+		/// <exception cref="InvalidOperationException">if this engine is not initialised</exception>
+		internal int ProcessBlock(ulong[] inWords, ulong[] outWords)
+		{
+			if (kw[blocksizeWords] == 0)
+			{
+				throw new InvalidOperationException("Threefish engine not initialised");
+			}
+
+			if (inWords.Length != blocksizeWords)
+			{
+				throw new DataLengthException("Input buffer too short");
+			}
+			if (outWords.Length != blocksizeWords)
+			{
+				throw new DataLengthException("Output buffer too short");
+			}
+
+			if (forEncryption)
+			{
+				cipher.EncryptBlock(inWords, outWords);
+			}
+			else
+			{
+				cipher.DecryptBlock(inWords, outWords);
+			}
+
+			return blocksizeWords;
+		}
+
+		/// <summary>
+		/// Read a single 64 bit word from input in LSB first order.
+		/// </summary>
+		internal static ulong BytesToWord(byte[] bytes, int off)
+		{
+			if ((off + 8) > bytes.Length)
+			{
+				// Help the JIT avoid index checks
+				throw new ArgumentException();
+			}
+
+			ulong word = 0;
+			int index = off;
+
+			word = (bytes[index++] & 0xffUL);
+			word |= (bytes[index++] & 0xffUL) << 8;
+			word |= (bytes[index++] & 0xffUL) << 16;
+			word |= (bytes[index++] & 0xffUL) << 24;
+			word |= (bytes[index++] & 0xffUL) << 32;
+			word |= (bytes[index++] & 0xffUL) << 40;
+			word |= (bytes[index++] & 0xffUL) << 48;
+			word |= (bytes[index++] & 0xffUL) << 56;
+
+			return word;
+		}
+
+		/// <summary>
+		/// Write a 64 bit word to output in LSB first order.
+		/// </summary>
+		internal static void WordToBytes(ulong word, byte[] bytes, int off)
+		{
+			if ((off + 8) > bytes.Length)
+			{
+				// Help the JIT avoid index checks
+				throw new ArgumentException();
+			}
+			int index = off;
+
+			bytes[index++] = (byte)word;
+			bytes[index++] = (byte)(word >> 8);
+			bytes[index++] = (byte)(word >> 16);
+			bytes[index++] = (byte)(word >> 24);
+			bytes[index++] = (byte)(word >> 32);
+			bytes[index++] = (byte)(word >> 40);
+			bytes[index++] = (byte)(word >> 48);
+			bytes[index++] = (byte)(word >> 56);
+		}
+
+		/**
+	     * Rotate left + xor part of the mix operation.
+	     */
+		private static ulong RotlXor(ulong x, int n, ulong xor)
+		{
+			return ((x << n) | (x >> (64 - n))) ^ xor;
+		}
+
+		/**
+	     * Rotate xor + rotate right part of the unmix operation.
+	     */
+		private static ulong XorRotr(ulong x, int n, ulong xor)
+		{
+			ulong xored = x ^ xor;
+			return (xored >> n) | (xored << (64 - n));
+		}
+
+		private abstract class ThreefishCipher
+		{
+			/**
+	         * The extended + repeated tweak words
+	         */
+			protected readonly ulong[] t;
+			/**
+	         * The extended + repeated key words
+	         */
+			protected readonly ulong[] kw;
+
+			protected ThreefishCipher(ulong[] kw, ulong[] t)
+			{
+				this.kw = kw;
+				this.t = t;
+			}
+
+			internal abstract void EncryptBlock(ulong[] block, ulong[] outWords);
+
+			internal abstract void DecryptBlock(ulong[] block, ulong[] outWords);
+
+		}
+
+		private sealed class Threefish256Cipher
+			: ThreefishCipher
+		{
+			/**
+	         * Mix rotation constants defined in Skein 1.3 specification
+	         */
+			private const int ROTATION_0_0 = 14, ROTATION_0_1 = 16;
+			private const int ROTATION_1_0 = 52, ROTATION_1_1 = 57;
+			private const int ROTATION_2_0 = 23, ROTATION_2_1 = 40;
+			private const int ROTATION_3_0 = 5, ROTATION_3_1 = 37;
+
+			private const int ROTATION_4_0 = 25, ROTATION_4_1 = 33;
+			private const int ROTATION_5_0 = 46, ROTATION_5_1 = 12;
+			private const int ROTATION_6_0 = 58, ROTATION_6_1 = 22;
+			private const int ROTATION_7_0 = 32, ROTATION_7_1 = 32;
+
+			public Threefish256Cipher(ulong[] kw, ulong[] t)
+				: base(kw, t)
+			{
+			}
+
+			internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod5 = MOD5;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 9)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				/*
+	             * Read 4 words of plaintext data, not using arrays for cipher state
+	             */
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+
+				/*
+	             * First subkey injection.
+	             */
+				b0 += kw[0];
+				b1 += kw[1] + t[0];
+				b2 += kw[2] + t[1];
+				b3 += kw[3];
+
+				/*
+	             * Rounds loop, unrolled to 8 rounds per iteration.
+	             * 
+	             * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+	             * inlining of the permutations, which cycle every of 2 rounds (avoiding array
+	             * index/lookup).
+	             * 
+	             * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+	             * inlining constant rotation values (avoiding array index/lookup).
+	             */
+
+				for (int d = 1; d < (ROUNDS_256 / 4); d += 2)
+				{
+					int dm5 = mod5[d];
+					int dm3 = mod3[d];
+
+					/*
+	                 * 4 rounds of mix and permute.
+	                 * 
+	                 * Permute schedule has a 2 round cycle, so permutes are inlined in the mix
+	                 * operations in each 4 round block.
+	                 */
+					b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+
+					b3 = RotlXor(b3, ROTATION_1_0, b0 += b3);
+					b1 = RotlXor(b1, ROTATION_1_1, b2 += b1);
+
+					b1 = RotlXor(b1, ROTATION_2_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_2_1, b2 += b3);
+
+					b3 = RotlXor(b3, ROTATION_3_0, b0 += b3);
+					b1 = RotlXor(b1, ROTATION_3_1, b2 += b1);
+
+					/*
+	                 * Subkey injection for first 4 rounds.
+	                 */
+					b0 += kw[dm5];
+					b1 += kw[dm5 + 1] + t[dm3];
+					b2 += kw[dm5 + 2] + t[dm3 + 1];
+					b3 += kw[dm5 + 3] + (uint)d;
+
+					/*
+	                 * 4 more rounds of mix/permute
+	                 */
+					b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+
+					b3 = RotlXor(b3, ROTATION_5_0, b0 += b3);
+					b1 = RotlXor(b1, ROTATION_5_1, b2 += b1);
+
+					b1 = RotlXor(b1, ROTATION_6_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_6_1, b2 += b3);
+
+					b3 = RotlXor(b3, ROTATION_7_0, b0 += b3);
+					b1 = RotlXor(b1, ROTATION_7_1, b2 += b1);
+
+					/*
+	                 * Subkey injection for next 4 rounds.
+	                 */
+					b0 += kw[dm5 + 1];
+					b1 += kw[dm5 + 2] + t[dm3 + 1];
+					b2 += kw[dm5 + 3] + t[dm3 + 2];
+					b3 += kw[dm5 + 4] + (uint)d + 1;
+				}
+
+				/*
+	             * Output cipher state.
+	             */
+				outWords[0] = b0;
+				outWords[1] = b1;
+				outWords[2] = b2;
+				outWords[3] = b3;
+			}
+
+			internal override void DecryptBlock(ulong[] block, ulong[] state)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod5 = MOD5;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 9)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+
+				for (int d = (ROUNDS_256 / 4) - 1; d >= 1; d -= 2)
+				{
+					int dm5 = mod5[d];
+					int dm3 = mod3[d];
+
+					/* Reverse key injection for second 4 rounds */
+					b0 -= kw[dm5 + 1];
+					b1 -= kw[dm5 + 2] + t[dm3 + 1];
+					b2 -= kw[dm5 + 3] + t[dm3 + 2];
+					b3 -= kw[dm5 + 4] + (uint)d + 1;
+
+					/* Reverse second 4 mix/permute rounds */
+
+					b3 = XorRotr(b3, ROTATION_7_0, b0);
+					b0 -= b3;
+					b1 = XorRotr(b1, ROTATION_7_1, b2);
+					b2 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_6_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_6_1, b2);
+					b2 -= b3;
+
+					b3 = XorRotr(b3, ROTATION_5_0, b0);
+					b0 -= b3;
+					b1 = XorRotr(b1, ROTATION_5_1, b2);
+					b2 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_4_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_4_1, b2);
+					b2 -= b3;
+
+					/* Reverse key injection for first 4 rounds */
+					b0 -= kw[dm5];
+					b1 -= kw[dm5 + 1] + t[dm3];
+					b2 -= kw[dm5 + 2] + t[dm3 + 1];
+					b3 -= kw[dm5 + 3] + (uint)d;
+
+					/* Reverse first 4 mix/permute rounds */
+					b3 = XorRotr(b3, ROTATION_3_0, b0);
+					b0 -= b3;
+					b1 = XorRotr(b1, ROTATION_3_1, b2);
+					b2 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_2_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_2_1, b2);
+					b2 -= b3;
+
+					b3 = XorRotr(b3, ROTATION_1_0, b0);
+					b0 -= b3;
+					b1 = XorRotr(b1, ROTATION_1_1, b2);
+					b2 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_0_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_0_1, b2);
+					b2 -= b3;
+				}
+
+				/*
+	             * First subkey uninjection.
+	             */
+				b0 -= kw[0];
+				b1 -= kw[1] + t[0];
+				b2 -= kw[2] + t[1];
+				b3 -= kw[3];
+
+				/*
+	             * Output cipher state.
+	             */
+				state[0] = b0;
+				state[1] = b1;
+				state[2] = b2;
+				state[3] = b3;
+			}
+
+		}
+
+		private sealed class Threefish512Cipher
+			: ThreefishCipher
+		{
+			/**
+	         * Mix rotation constants defined in Skein 1.3 specification
+	         */
+			private const int ROTATION_0_0 = 46, ROTATION_0_1 = 36, ROTATION_0_2 = 19, ROTATION_0_3 = 37;
+			private const int ROTATION_1_0 = 33, ROTATION_1_1 = 27, ROTATION_1_2 = 14, ROTATION_1_3 = 42;
+			private const int ROTATION_2_0 = 17, ROTATION_2_1 = 49, ROTATION_2_2 = 36, ROTATION_2_3 = 39;
+			private const int ROTATION_3_0 = 44, ROTATION_3_1 = 9, ROTATION_3_2 = 54, ROTATION_3_3 = 56;
+
+			private const int ROTATION_4_0 = 39, ROTATION_4_1 = 30, ROTATION_4_2 = 34, ROTATION_4_3 = 24;
+			private const int ROTATION_5_0 = 13, ROTATION_5_1 = 50, ROTATION_5_2 = 10, ROTATION_5_3 = 17;
+			private const int ROTATION_6_0 = 25, ROTATION_6_1 = 29, ROTATION_6_2 = 39, ROTATION_6_3 = 43;
+			private const int ROTATION_7_0 = 8, ROTATION_7_1 = 35, ROTATION_7_2 = 56, ROTATION_7_3 = 22;
+
+			internal Threefish512Cipher(ulong[] kw, ulong[] t)
+				: base(kw, t)
+			{
+			}
+
+			internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod9 = MOD9;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 17)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				/*
+	             * Read 8 words of plaintext data, not using arrays for cipher state
+	             */
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+				ulong b4 = block[4];
+				ulong b5 = block[5];
+				ulong b6 = block[6];
+				ulong b7 = block[7];
+
+				/*
+	             * First subkey injection.
+	             */
+				b0 += kw[0];
+				b1 += kw[1];
+				b2 += kw[2];
+				b3 += kw[3];
+				b4 += kw[4];
+				b5 += kw[5] + t[0];
+				b6 += kw[6] + t[1];
+				b7 += kw[7];
+
+				/*
+	             * Rounds loop, unrolled to 8 rounds per iteration.
+	             * 
+	             * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+	             * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+	             * index/lookup).
+	             * 
+	             * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+	             * inlining constant rotation values (avoiding array index/lookup).
+	             */
+
+				for (int d = 1; d < (ROUNDS_512 / 4); d += 2)
+				{
+					int dm9 = mod9[d];
+					int dm3 = mod3[d];
+
+					/*
+	                 * 4 rounds of mix and permute.
+	                 * 
+	                 * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+	                 * operations in each 4 round block.
+	                 */
+					b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+					b5 = RotlXor(b5, ROTATION_0_2, b4 += b5);
+					b7 = RotlXor(b7, ROTATION_0_3, b6 += b7);
+
+					b1 = RotlXor(b1, ROTATION_1_0, b2 += b1);
+					b7 = RotlXor(b7, ROTATION_1_1, b4 += b7);
+					b5 = RotlXor(b5, ROTATION_1_2, b6 += b5);
+					b3 = RotlXor(b3, ROTATION_1_3, b0 += b3);
+
+					b1 = RotlXor(b1, ROTATION_2_0, b4 += b1);
+					b3 = RotlXor(b3, ROTATION_2_1, b6 += b3);
+					b5 = RotlXor(b5, ROTATION_2_2, b0 += b5);
+					b7 = RotlXor(b7, ROTATION_2_3, b2 += b7);
+
+					b1 = RotlXor(b1, ROTATION_3_0, b6 += b1);
+					b7 = RotlXor(b7, ROTATION_3_1, b0 += b7);
+					b5 = RotlXor(b5, ROTATION_3_2, b2 += b5);
+					b3 = RotlXor(b3, ROTATION_3_3, b4 += b3);
+
+					/*
+	                 * Subkey injection for first 4 rounds.
+	                 */
+					b0 += kw[dm9];
+					b1 += kw[dm9 + 1];
+					b2 += kw[dm9 + 2];
+					b3 += kw[dm9 + 3];
+					b4 += kw[dm9 + 4];
+					b5 += kw[dm9 + 5] + t[dm3];
+					b6 += kw[dm9 + 6] + t[dm3 + 1];
+					b7 += kw[dm9 + 7] + (uint)d;
+
+					/*
+	                 * 4 more rounds of mix/permute
+	                 */
+					b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+					b5 = RotlXor(b5, ROTATION_4_2, b4 += b5);
+					b7 = RotlXor(b7, ROTATION_4_3, b6 += b7);
+
+					b1 = RotlXor(b1, ROTATION_5_0, b2 += b1);
+					b7 = RotlXor(b7, ROTATION_5_1, b4 += b7);
+					b5 = RotlXor(b5, ROTATION_5_2, b6 += b5);
+					b3 = RotlXor(b3, ROTATION_5_3, b0 += b3);
+
+					b1 = RotlXor(b1, ROTATION_6_0, b4 += b1);
+					b3 = RotlXor(b3, ROTATION_6_1, b6 += b3);
+					b5 = RotlXor(b5, ROTATION_6_2, b0 += b5);
+					b7 = RotlXor(b7, ROTATION_6_3, b2 += b7);
+
+					b1 = RotlXor(b1, ROTATION_7_0, b6 += b1);
+					b7 = RotlXor(b7, ROTATION_7_1, b0 += b7);
+					b5 = RotlXor(b5, ROTATION_7_2, b2 += b5);
+					b3 = RotlXor(b3, ROTATION_7_3, b4 += b3);
+
+					/*
+	                 * Subkey injection for next 4 rounds.
+	                 */
+					b0 += kw[dm9 + 1];
+					b1 += kw[dm9 + 2];
+					b2 += kw[dm9 + 3];
+					b3 += kw[dm9 + 4];
+					b4 += kw[dm9 + 5];
+					b5 += kw[dm9 + 6] + t[dm3 + 1];
+					b6 += kw[dm9 + 7] + t[dm3 + 2];
+					b7 += kw[dm9 + 8] + (uint)d + 1;
+				}
+
+				/*
+	             * Output cipher state.
+	             */
+				outWords[0] = b0;
+				outWords[1] = b1;
+				outWords[2] = b2;
+				outWords[3] = b3;
+				outWords[4] = b4;
+				outWords[5] = b5;
+				outWords[6] = b6;
+				outWords[7] = b7;
+			}
+
+			internal override void DecryptBlock(ulong[] block, ulong[] state)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod9 = MOD9;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 17)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+				ulong b4 = block[4];
+				ulong b5 = block[5];
+				ulong b6 = block[6];
+				ulong b7 = block[7];
+
+				for (int d = (ROUNDS_512 / 4) - 1; d >= 1; d -= 2)
+				{
+					int dm9 = mod9[d];
+					int dm3 = mod3[d];
+
+					/* Reverse key injection for second 4 rounds */
+					b0 -= kw[dm9 + 1];
+					b1 -= kw[dm9 + 2];
+					b2 -= kw[dm9 + 3];
+					b3 -= kw[dm9 + 4];
+					b4 -= kw[dm9 + 5];
+					b5 -= kw[dm9 + 6] + t[dm3 + 1];
+					b6 -= kw[dm9 + 7] + t[dm3 + 2];
+					b7 -= kw[dm9 + 8] + (uint)d + 1;
+
+					/* Reverse second 4 mix/permute rounds */
+
+					b1 = XorRotr(b1, ROTATION_7_0, b6);
+					b6 -= b1;
+					b7 = XorRotr(b7, ROTATION_7_1, b0);
+					b0 -= b7;
+					b5 = XorRotr(b5, ROTATION_7_2, b2);
+					b2 -= b5;
+					b3 = XorRotr(b3, ROTATION_7_3, b4);
+					b4 -= b3;
+
+					b1 = XorRotr(b1, ROTATION_6_0, b4);
+					b4 -= b1;
+					b3 = XorRotr(b3, ROTATION_6_1, b6);
+					b6 -= b3;
+					b5 = XorRotr(b5, ROTATION_6_2, b0);
+					b0 -= b5;
+					b7 = XorRotr(b7, ROTATION_6_3, b2);
+					b2 -= b7;
+
+					b1 = XorRotr(b1, ROTATION_5_0, b2);
+					b2 -= b1;
+					b7 = XorRotr(b7, ROTATION_5_1, b4);
+					b4 -= b7;
+					b5 = XorRotr(b5, ROTATION_5_2, b6);
+					b6 -= b5;
+					b3 = XorRotr(b3, ROTATION_5_3, b0);
+					b0 -= b3;
+
+					b1 = XorRotr(b1, ROTATION_4_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_4_1, b2);
+					b2 -= b3;
+					b5 = XorRotr(b5, ROTATION_4_2, b4);
+					b4 -= b5;
+					b7 = XorRotr(b7, ROTATION_4_3, b6);
+					b6 -= b7;
+
+					/* Reverse key injection for first 4 rounds */
+					b0 -= kw[dm9];
+					b1 -= kw[dm9 + 1];
+					b2 -= kw[dm9 + 2];
+					b3 -= kw[dm9 + 3];
+					b4 -= kw[dm9 + 4];
+					b5 -= kw[dm9 + 5] + t[dm3];
+					b6 -= kw[dm9 + 6] + t[dm3 + 1];
+					b7 -= kw[dm9 + 7] + (uint)d;
+
+					/* Reverse first 4 mix/permute rounds */
+					b1 = XorRotr(b1, ROTATION_3_0, b6);
+					b6 -= b1;
+					b7 = XorRotr(b7, ROTATION_3_1, b0);
+					b0 -= b7;
+					b5 = XorRotr(b5, ROTATION_3_2, b2);
+					b2 -= b5;
+					b3 = XorRotr(b3, ROTATION_3_3, b4);
+					b4 -= b3;
+
+					b1 = XorRotr(b1, ROTATION_2_0, b4);
+					b4 -= b1;
+					b3 = XorRotr(b3, ROTATION_2_1, b6);
+					b6 -= b3;
+					b5 = XorRotr(b5, ROTATION_2_2, b0);
+					b0 -= b5;
+					b7 = XorRotr(b7, ROTATION_2_3, b2);
+					b2 -= b7;
+
+					b1 = XorRotr(b1, ROTATION_1_0, b2);
+					b2 -= b1;
+					b7 = XorRotr(b7, ROTATION_1_1, b4);
+					b4 -= b7;
+					b5 = XorRotr(b5, ROTATION_1_2, b6);
+					b6 -= b5;
+					b3 = XorRotr(b3, ROTATION_1_3, b0);
+					b0 -= b3;
+
+					b1 = XorRotr(b1, ROTATION_0_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_0_1, b2);
+					b2 -= b3;
+					b5 = XorRotr(b5, ROTATION_0_2, b4);
+					b4 -= b5;
+					b7 = XorRotr(b7, ROTATION_0_3, b6);
+					b6 -= b7;
+				}
+
+				/*
+	             * First subkey uninjection.
+	             */
+				b0 -= kw[0];
+				b1 -= kw[1];
+				b2 -= kw[2];
+				b3 -= kw[3];
+				b4 -= kw[4];
+				b5 -= kw[5] + t[0];
+				b6 -= kw[6] + t[1];
+				b7 -= kw[7];
+
+				/*
+	             * Output cipher state.
+	             */
+				state[0] = b0;
+				state[1] = b1;
+				state[2] = b2;
+				state[3] = b3;
+				state[4] = b4;
+				state[5] = b5;
+				state[6] = b6;
+				state[7] = b7;
+			}
+		}
+
+		private sealed class Threefish1024Cipher
+			: ThreefishCipher
+		{
+			/**
+	         * Mix rotation constants defined in Skein 1.3 specification
+	         */
+			private const int ROTATION_0_0 = 24, ROTATION_0_1 = 13, ROTATION_0_2 = 8, ROTATION_0_3 = 47;
+			private const int ROTATION_0_4 = 8, ROTATION_0_5 = 17, ROTATION_0_6 = 22, ROTATION_0_7 = 37;
+			private const int ROTATION_1_0 = 38, ROTATION_1_1 = 19, ROTATION_1_2 = 10, ROTATION_1_3 = 55;
+			private const int ROTATION_1_4 = 49, ROTATION_1_5 = 18, ROTATION_1_6 = 23, ROTATION_1_7 = 52;
+			private const int ROTATION_2_0 = 33, ROTATION_2_1 = 4, ROTATION_2_2 = 51, ROTATION_2_3 = 13;
+			private const int ROTATION_2_4 = 34, ROTATION_2_5 = 41, ROTATION_2_6 = 59, ROTATION_2_7 = 17;
+			private const int ROTATION_3_0 = 5, ROTATION_3_1 = 20, ROTATION_3_2 = 48, ROTATION_3_3 = 41;
+			private const int ROTATION_3_4 = 47, ROTATION_3_5 = 28, ROTATION_3_6 = 16, ROTATION_3_7 = 25;
+
+			private const int ROTATION_4_0 = 41, ROTATION_4_1 = 9, ROTATION_4_2 = 37, ROTATION_4_3 = 31;
+			private const int ROTATION_4_4 = 12, ROTATION_4_5 = 47, ROTATION_4_6 = 44, ROTATION_4_7 = 30;
+			private const int ROTATION_5_0 = 16, ROTATION_5_1 = 34, ROTATION_5_2 = 56, ROTATION_5_3 = 51;
+			private const int ROTATION_5_4 = 4, ROTATION_5_5 = 53, ROTATION_5_6 = 42, ROTATION_5_7 = 41;
+			private const int ROTATION_6_0 = 31, ROTATION_6_1 = 44, ROTATION_6_2 = 47, ROTATION_6_3 = 46;
+			private const int ROTATION_6_4 = 19, ROTATION_6_5 = 42, ROTATION_6_6 = 44, ROTATION_6_7 = 25;
+			private const int ROTATION_7_0 = 9, ROTATION_7_1 = 48, ROTATION_7_2 = 35, ROTATION_7_3 = 52;
+			private const int ROTATION_7_4 = 23, ROTATION_7_5 = 31, ROTATION_7_6 = 37, ROTATION_7_7 = 20;
+
+			public Threefish1024Cipher(ulong[] kw, ulong[] t)
+				: base(kw, t)
+			{
+			}
+
+			internal override void EncryptBlock(ulong[] block, ulong[] outWords)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod17 = MOD17;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 33)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				/*
+	             * Read 16 words of plaintext data, not using arrays for cipher state
+	             */
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+				ulong b4 = block[4];
+				ulong b5 = block[5];
+				ulong b6 = block[6];
+				ulong b7 = block[7];
+				ulong b8 = block[8];
+				ulong b9 = block[9];
+				ulong b10 = block[10];
+				ulong b11 = block[11];
+				ulong b12 = block[12];
+				ulong b13 = block[13];
+				ulong b14 = block[14];
+				ulong b15 = block[15];
+
+				/*
+	             * First subkey injection.
+	             */
+				b0 += kw[0];
+				b1 += kw[1];
+				b2 += kw[2];
+				b3 += kw[3];
+				b4 += kw[4];
+				b5 += kw[5];
+				b6 += kw[6];
+				b7 += kw[7];
+				b8 += kw[8];
+				b9 += kw[9];
+				b10 += kw[10];
+				b11 += kw[11];
+				b12 += kw[12];
+				b13 += kw[13] + t[0];
+				b14 += kw[14] + t[1];
+				b15 += kw[15];
+
+				/*
+	             * Rounds loop, unrolled to 8 rounds per iteration.
+	             * 
+	             * Unrolling to multiples of 4 avoids the mod 4 check for key injection, and allows
+	             * inlining of the permutations, which cycle every of 4 rounds (avoiding array
+	             * index/lookup).
+	             * 
+	             * Unrolling to multiples of 8 avoids the mod 8 rotation constant lookup, and allows
+	             * inlining constant rotation values (avoiding array index/lookup).
+	             */
+
+				for (int d = 1; d < (ROUNDS_1024 / 4); d += 2)
+				{
+					int dm17 = mod17[d];
+					int dm3 = mod3[d];
+
+					/*
+	                 * 4 rounds of mix and permute.
+	                 * 
+	                 * Permute schedule has a 4 round cycle, so permutes are inlined in the mix
+	                 * operations in each 4 round block.
+	                 */
+					b1 = RotlXor(b1, ROTATION_0_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_0_1, b2 += b3);
+					b5 = RotlXor(b5, ROTATION_0_2, b4 += b5);
+					b7 = RotlXor(b7, ROTATION_0_3, b6 += b7);
+					b9 = RotlXor(b9, ROTATION_0_4, b8 += b9);
+					b11 = RotlXor(b11, ROTATION_0_5, b10 += b11);
+					b13 = RotlXor(b13, ROTATION_0_6, b12 += b13);
+					b15 = RotlXor(b15, ROTATION_0_7, b14 += b15);
+
+					b9 = RotlXor(b9, ROTATION_1_0, b0 += b9);
+					b13 = RotlXor(b13, ROTATION_1_1, b2 += b13);
+					b11 = RotlXor(b11, ROTATION_1_2, b6 += b11);
+					b15 = RotlXor(b15, ROTATION_1_3, b4 += b15);
+					b7 = RotlXor(b7, ROTATION_1_4, b10 += b7);
+					b3 = RotlXor(b3, ROTATION_1_5, b12 += b3);
+					b5 = RotlXor(b5, ROTATION_1_6, b14 += b5);
+					b1 = RotlXor(b1, ROTATION_1_7, b8 += b1);
+
+					b7 = RotlXor(b7, ROTATION_2_0, b0 += b7);
+					b5 = RotlXor(b5, ROTATION_2_1, b2 += b5);
+					b3 = RotlXor(b3, ROTATION_2_2, b4 += b3);
+					b1 = RotlXor(b1, ROTATION_2_3, b6 += b1);
+					b15 = RotlXor(b15, ROTATION_2_4, b12 += b15);
+					b13 = RotlXor(b13, ROTATION_2_5, b14 += b13);
+					b11 = RotlXor(b11, ROTATION_2_6, b8 += b11);
+					b9 = RotlXor(b9, ROTATION_2_7, b10 += b9);
+
+					b15 = RotlXor(b15, ROTATION_3_0, b0 += b15);
+					b11 = RotlXor(b11, ROTATION_3_1, b2 += b11);
+					b13 = RotlXor(b13, ROTATION_3_2, b6 += b13);
+					b9 = RotlXor(b9, ROTATION_3_3, b4 += b9);
+					b1 = RotlXor(b1, ROTATION_3_4, b14 += b1);
+					b5 = RotlXor(b5, ROTATION_3_5, b8 += b5);
+					b3 = RotlXor(b3, ROTATION_3_6, b10 += b3);
+					b7 = RotlXor(b7, ROTATION_3_7, b12 += b7);
+
+					/*
+	                 * Subkey injection for first 4 rounds.
+	                 */
+					b0 += kw[dm17];
+					b1 += kw[dm17 + 1];
+					b2 += kw[dm17 + 2];
+					b3 += kw[dm17 + 3];
+					b4 += kw[dm17 + 4];
+					b5 += kw[dm17 + 5];
+					b6 += kw[dm17 + 6];
+					b7 += kw[dm17 + 7];
+					b8 += kw[dm17 + 8];
+					b9 += kw[dm17 + 9];
+					b10 += kw[dm17 + 10];
+					b11 += kw[dm17 + 11];
+					b12 += kw[dm17 + 12];
+					b13 += kw[dm17 + 13] + t[dm3];
+					b14 += kw[dm17 + 14] + t[dm3 + 1];
+					b15 += kw[dm17 + 15] + (uint)d;
+
+					/*
+	                 * 4 more rounds of mix/permute
+	                 */
+					b1 = RotlXor(b1, ROTATION_4_0, b0 += b1);
+					b3 = RotlXor(b3, ROTATION_4_1, b2 += b3);
+					b5 = RotlXor(b5, ROTATION_4_2, b4 += b5);
+					b7 = RotlXor(b7, ROTATION_4_3, b6 += b7);
+					b9 = RotlXor(b9, ROTATION_4_4, b8 += b9);
+					b11 = RotlXor(b11, ROTATION_4_5, b10 += b11);
+					b13 = RotlXor(b13, ROTATION_4_6, b12 += b13);
+					b15 = RotlXor(b15, ROTATION_4_7, b14 += b15);
+
+					b9 = RotlXor(b9, ROTATION_5_0, b0 += b9);
+					b13 = RotlXor(b13, ROTATION_5_1, b2 += b13);
+					b11 = RotlXor(b11, ROTATION_5_2, b6 += b11);
+					b15 = RotlXor(b15, ROTATION_5_3, b4 += b15);
+					b7 = RotlXor(b7, ROTATION_5_4, b10 += b7);
+					b3 = RotlXor(b3, ROTATION_5_5, b12 += b3);
+					b5 = RotlXor(b5, ROTATION_5_6, b14 += b5);
+					b1 = RotlXor(b1, ROTATION_5_7, b8 += b1);
+
+					b7 = RotlXor(b7, ROTATION_6_0, b0 += b7);
+					b5 = RotlXor(b5, ROTATION_6_1, b2 += b5);
+					b3 = RotlXor(b3, ROTATION_6_2, b4 += b3);
+					b1 = RotlXor(b1, ROTATION_6_3, b6 += b1);
+					b15 = RotlXor(b15, ROTATION_6_4, b12 += b15);
+					b13 = RotlXor(b13, ROTATION_6_5, b14 += b13);
+					b11 = RotlXor(b11, ROTATION_6_6, b8 += b11);
+					b9 = RotlXor(b9, ROTATION_6_7, b10 += b9);
+
+					b15 = RotlXor(b15, ROTATION_7_0, b0 += b15);
+					b11 = RotlXor(b11, ROTATION_7_1, b2 += b11);
+					b13 = RotlXor(b13, ROTATION_7_2, b6 += b13);
+					b9 = RotlXor(b9, ROTATION_7_3, b4 += b9);
+					b1 = RotlXor(b1, ROTATION_7_4, b14 += b1);
+					b5 = RotlXor(b5, ROTATION_7_5, b8 += b5);
+					b3 = RotlXor(b3, ROTATION_7_6, b10 += b3);
+					b7 = RotlXor(b7, ROTATION_7_7, b12 += b7);
+
+					/*
+	                 * Subkey injection for next 4 rounds.
+	                 */
+					b0 += kw[dm17 + 1];
+					b1 += kw[dm17 + 2];
+					b2 += kw[dm17 + 3];
+					b3 += kw[dm17 + 4];
+					b4 += kw[dm17 + 5];
+					b5 += kw[dm17 + 6];
+					b6 += kw[dm17 + 7];
+					b7 += kw[dm17 + 8];
+					b8 += kw[dm17 + 9];
+					b9 += kw[dm17 + 10];
+					b10 += kw[dm17 + 11];
+					b11 += kw[dm17 + 12];
+					b12 += kw[dm17 + 13];
+					b13 += kw[dm17 + 14] + t[dm3 + 1];
+					b14 += kw[dm17 + 15] + t[dm3 + 2];
+					b15 += kw[dm17 + 16] + (uint)d + 1;
+
+				}
+
+				/*
+	             * Output cipher state.
+	             */
+				outWords[0] = b0;
+				outWords[1] = b1;
+				outWords[2] = b2;
+				outWords[3] = b3;
+				outWords[4] = b4;
+				outWords[5] = b5;
+				outWords[6] = b6;
+				outWords[7] = b7;
+				outWords[8] = b8;
+				outWords[9] = b9;
+				outWords[10] = b10;
+				outWords[11] = b11;
+				outWords[12] = b12;
+				outWords[13] = b13;
+				outWords[14] = b14;
+				outWords[15] = b15;
+			}
+
+			internal override void DecryptBlock(ulong[] block, ulong[] state)
+			{
+				ulong[] kw = this.kw;
+				ulong[] t = this.t;
+				int[] mod17 = MOD17;
+				int[] mod3 = MOD3;
+
+				/* Help the JIT avoid index bounds checks */
+				if (kw.Length != 33)
+				{
+					throw new ArgumentException();
+				}
+				if (t.Length != 5)
+				{
+					throw new ArgumentException();
+				}
+
+				ulong b0 = block[0];
+				ulong b1 = block[1];
+				ulong b2 = block[2];
+				ulong b3 = block[3];
+				ulong b4 = block[4];
+				ulong b5 = block[5];
+				ulong b6 = block[6];
+				ulong b7 = block[7];
+				ulong b8 = block[8];
+				ulong b9 = block[9];
+				ulong b10 = block[10];
+				ulong b11 = block[11];
+				ulong b12 = block[12];
+				ulong b13 = block[13];
+				ulong b14 = block[14];
+				ulong b15 = block[15];
+
+				for (int d = (ROUNDS_1024 / 4) - 1; d >= 1; d -= 2)
+				{
+					int dm17 = mod17[d];
+					int dm3 = mod3[d];
+
+					/* Reverse key injection for second 4 rounds */
+					b0 -= kw[dm17 + 1];
+					b1 -= kw[dm17 + 2];
+					b2 -= kw[dm17 + 3];
+					b3 -= kw[dm17 + 4];
+					b4 -= kw[dm17 + 5];
+					b5 -= kw[dm17 + 6];
+					b6 -= kw[dm17 + 7];
+					b7 -= kw[dm17 + 8];
+					b8 -= kw[dm17 + 9];
+					b9 -= kw[dm17 + 10];
+					b10 -= kw[dm17 + 11];
+					b11 -= kw[dm17 + 12];
+					b12 -= kw[dm17 + 13];
+					b13 -= kw[dm17 + 14] + t[dm3 + 1];
+					b14 -= kw[dm17 + 15] + t[dm3 + 2];
+					b15 -= kw[dm17 + 16] + (uint)d + 1;
+
+					/* Reverse second 4 mix/permute rounds */
+					b15 = XorRotr(b15, ROTATION_7_0, b0);
+					b0 -= b15;
+					b11 = XorRotr(b11, ROTATION_7_1, b2);
+					b2 -= b11;
+					b13 = XorRotr(b13, ROTATION_7_2, b6);
+					b6 -= b13;
+					b9 = XorRotr(b9, ROTATION_7_3, b4);
+					b4 -= b9;
+					b1 = XorRotr(b1, ROTATION_7_4, b14);
+					b14 -= b1;
+					b5 = XorRotr(b5, ROTATION_7_5, b8);
+					b8 -= b5;
+					b3 = XorRotr(b3, ROTATION_7_6, b10);
+					b10 -= b3;
+					b7 = XorRotr(b7, ROTATION_7_7, b12);
+					b12 -= b7;
+
+					b7 = XorRotr(b7, ROTATION_6_0, b0);
+					b0 -= b7;
+					b5 = XorRotr(b5, ROTATION_6_1, b2);
+					b2 -= b5;
+					b3 = XorRotr(b3, ROTATION_6_2, b4);
+					b4 -= b3;
+					b1 = XorRotr(b1, ROTATION_6_3, b6);
+					b6 -= b1;
+					b15 = XorRotr(b15, ROTATION_6_4, b12);
+					b12 -= b15;
+					b13 = XorRotr(b13, ROTATION_6_5, b14);
+					b14 -= b13;
+					b11 = XorRotr(b11, ROTATION_6_6, b8);
+					b8 -= b11;
+					b9 = XorRotr(b9, ROTATION_6_7, b10);
+					b10 -= b9;
+
+					b9 = XorRotr(b9, ROTATION_5_0, b0);
+					b0 -= b9;
+					b13 = XorRotr(b13, ROTATION_5_1, b2);
+					b2 -= b13;
+					b11 = XorRotr(b11, ROTATION_5_2, b6);
+					b6 -= b11;
+					b15 = XorRotr(b15, ROTATION_5_3, b4);
+					b4 -= b15;
+					b7 = XorRotr(b7, ROTATION_5_4, b10);
+					b10 -= b7;
+					b3 = XorRotr(b3, ROTATION_5_5, b12);
+					b12 -= b3;
+					b5 = XorRotr(b5, ROTATION_5_6, b14);
+					b14 -= b5;
+					b1 = XorRotr(b1, ROTATION_5_7, b8);
+					b8 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_4_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_4_1, b2);
+					b2 -= b3;
+					b5 = XorRotr(b5, ROTATION_4_2, b4);
+					b4 -= b5;
+					b7 = XorRotr(b7, ROTATION_4_3, b6);
+					b6 -= b7;
+					b9 = XorRotr(b9, ROTATION_4_4, b8);
+					b8 -= b9;
+					b11 = XorRotr(b11, ROTATION_4_5, b10);
+					b10 -= b11;
+					b13 = XorRotr(b13, ROTATION_4_6, b12);
+					b12 -= b13;
+					b15 = XorRotr(b15, ROTATION_4_7, b14);
+					b14 -= b15;
+
+					/* Reverse key injection for first 4 rounds */
+					b0 -= kw[dm17];
+					b1 -= kw[dm17 + 1];
+					b2 -= kw[dm17 + 2];
+					b3 -= kw[dm17 + 3];
+					b4 -= kw[dm17 + 4];
+					b5 -= kw[dm17 + 5];
+					b6 -= kw[dm17 + 6];
+					b7 -= kw[dm17 + 7];
+					b8 -= kw[dm17 + 8];
+					b9 -= kw[dm17 + 9];
+					b10 -= kw[dm17 + 10];
+					b11 -= kw[dm17 + 11];
+					b12 -= kw[dm17 + 12];
+					b13 -= kw[dm17 + 13] + t[dm3];
+					b14 -= kw[dm17 + 14] + t[dm3 + 1];
+					b15 -= kw[dm17 + 15] + (uint)d;
+
+					/* Reverse first 4 mix/permute rounds */
+					b15 = XorRotr(b15, ROTATION_3_0, b0);
+					b0 -= b15;
+					b11 = XorRotr(b11, ROTATION_3_1, b2);
+					b2 -= b11;
+					b13 = XorRotr(b13, ROTATION_3_2, b6);
+					b6 -= b13;
+					b9 = XorRotr(b9, ROTATION_3_3, b4);
+					b4 -= b9;
+					b1 = XorRotr(b1, ROTATION_3_4, b14);
+					b14 -= b1;
+					b5 = XorRotr(b5, ROTATION_3_5, b8);
+					b8 -= b5;
+					b3 = XorRotr(b3, ROTATION_3_6, b10);
+					b10 -= b3;
+					b7 = XorRotr(b7, ROTATION_3_7, b12);
+					b12 -= b7;
+
+					b7 = XorRotr(b7, ROTATION_2_0, b0);
+					b0 -= b7;
+					b5 = XorRotr(b5, ROTATION_2_1, b2);
+					b2 -= b5;
+					b3 = XorRotr(b3, ROTATION_2_2, b4);
+					b4 -= b3;
+					b1 = XorRotr(b1, ROTATION_2_3, b6);
+					b6 -= b1;
+					b15 = XorRotr(b15, ROTATION_2_4, b12);
+					b12 -= b15;
+					b13 = XorRotr(b13, ROTATION_2_5, b14);
+					b14 -= b13;
+					b11 = XorRotr(b11, ROTATION_2_6, b8);
+					b8 -= b11;
+					b9 = XorRotr(b9, ROTATION_2_7, b10);
+					b10 -= b9;
+
+					b9 = XorRotr(b9, ROTATION_1_0, b0);
+					b0 -= b9;
+					b13 = XorRotr(b13, ROTATION_1_1, b2);
+					b2 -= b13;
+					b11 = XorRotr(b11, ROTATION_1_2, b6);
+					b6 -= b11;
+					b15 = XorRotr(b15, ROTATION_1_3, b4);
+					b4 -= b15;
+					b7 = XorRotr(b7, ROTATION_1_4, b10);
+					b10 -= b7;
+					b3 = XorRotr(b3, ROTATION_1_5, b12);
+					b12 -= b3;
+					b5 = XorRotr(b5, ROTATION_1_6, b14);
+					b14 -= b5;
+					b1 = XorRotr(b1, ROTATION_1_7, b8);
+					b8 -= b1;
+
+					b1 = XorRotr(b1, ROTATION_0_0, b0);
+					b0 -= b1;
+					b3 = XorRotr(b3, ROTATION_0_1, b2);
+					b2 -= b3;
+					b5 = XorRotr(b5, ROTATION_0_2, b4);
+					b4 -= b5;
+					b7 = XorRotr(b7, ROTATION_0_3, b6);
+					b6 -= b7;
+					b9 = XorRotr(b9, ROTATION_0_4, b8);
+					b8 -= b9;
+					b11 = XorRotr(b11, ROTATION_0_5, b10);
+					b10 -= b11;
+					b13 = XorRotr(b13, ROTATION_0_6, b12);
+					b12 -= b13;
+					b15 = XorRotr(b15, ROTATION_0_7, b14);
+					b14 -= b15;
+				}
+
+				/*
+	             * First subkey uninjection.
+	             */
+				b0 -= kw[0];
+				b1 -= kw[1];
+				b2 -= kw[2];
+				b3 -= kw[3];
+				b4 -= kw[4];
+				b5 -= kw[5];
+				b6 -= kw[6];
+				b7 -= kw[7];
+				b8 -= kw[8];
+				b9 -= kw[9];
+				b10 -= kw[10];
+				b11 -= kw[11];
+				b12 -= kw[12];
+				b13 -= kw[13] + t[0];
+				b14 -= kw[14] + t[1];
+				b15 -= kw[15];
+
+				/*
+	             * Output cipher state.
+	             */
+				state[0] = b0;
+				state[1] = b1;
+				state[2] = b2;
+				state[3] = b3;
+				state[4] = b4;
+				state[5] = b5;
+				state[6] = b6;
+				state[7] = b7;
+				state[8] = b8;
+				state[9] = b9;
+				state[10] = b10;
+				state[11] = b11;
+				state[12] = b12;
+				state[13] = b13;
+				state[14] = b14;
+				state[15] = b15;
+			}
+
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/TwofishEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/TwofishEngine.cs
new file mode 100644
index 0000000..b983d9d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/TwofishEngine.cs
@@ -0,0 +1,675 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    /**
+    * A class that provides Twofish encryption operations.
+    *
+    * This Java implementation is based on the Java reference
+    * implementation provided by Bruce Schneier and developed
+    * by Raif S. Naffah.
+    */
+    public sealed class TwofishEngine
+		: IBlockCipher
+    {
+        private static readonly byte[,] P =  {
+        {  // p0
+            (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+            (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+            (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+            (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+            (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+            (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+            (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+            (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+            (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+            (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+            (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+            (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+            (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+            (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+            (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+            (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+            (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+            (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+            (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+            (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+            (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+            (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+            (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+            (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+            (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+            (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+            (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+            (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+            (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+            (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+            (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+            (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+            (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+            (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+            (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+            (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+            (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+            (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+            (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+            (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+            (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+            (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+            (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+            (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+            (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+            (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+            (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+            (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+            (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+            (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+            (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+            (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+            (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+            (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+            (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+            (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+            (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+            (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+            (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+            (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+            (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+            (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+            (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+            (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0 },
+        {  // p1
+            (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+            (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+            (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+            (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+            (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+            (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+            (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+            (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+            (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+            (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+            (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+            (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+            (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+            (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+            (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+            (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+            (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+            (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+            (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+            (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+            (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+            (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+            (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+            (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+            (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+            (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+            (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+            (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+            (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+            (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+            (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+            (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+            (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+            (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+            (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+            (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+            (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+            (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+            (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+            (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+            (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+            (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+            (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+            (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+            (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+            (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+            (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+            (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+            (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+            (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+            (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+            (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+            (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+            (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+            (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+            (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+            (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+            (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+            (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+            (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+            (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+            (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+            (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+            (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91  }
+        };
+
+        /**
+        * Define the fixed p0/p1 permutations used in keyed S-box lookup.
+        * By changing the following constant definitions, the S-boxes will
+        * automatically Get changed in the Twofish engine.
+        */
+        private const int P_00 = 1;
+        private const int P_01 = 0;
+        private const int P_02 = 0;
+        private const int P_03 = P_01 ^ 1;
+        private const int P_04 = 1;
+
+        private const int P_10 = 0;
+        private const int P_11 = 0;
+        private const int P_12 = 1;
+        private const int P_13 = P_11 ^ 1;
+        private const int P_14 = 0;
+
+        private const int P_20 = 1;
+        private const int P_21 = 1;
+        private const int P_22 = 0;
+        private const int P_23 = P_21 ^ 1;
+        private const int P_24 = 0;
+
+        private const int P_30 = 0;
+        private const int P_31 = 1;
+        private const int P_32 = 1;
+        private const int P_33 = P_31 ^ 1;
+        private const int P_34 = 1;
+
+        /* Primitive polynomial for GF(256) */
+        private const int GF256_FDBK = 0x169;
+        private const int GF256_FDBK_2 = GF256_FDBK / 2;
+        private const int GF256_FDBK_4 = GF256_FDBK / 4;
+
+        private const int RS_GF_FDBK = 0x14D; // field generator
+
+        //====================================
+        // Useful constants
+        //====================================
+
+        private const int    ROUNDS = 16;
+        private const int    MAX_ROUNDS = 16;  // bytes = 128 bits
+        private const int    BLOCK_SIZE = 16;  // bytes = 128 bits
+        private const int    MAX_KEY_BITS = 256;
+
+        private const int    INPUT_WHITEN=0;
+        private const int    OUTPUT_WHITEN=INPUT_WHITEN+BLOCK_SIZE/4; // 4
+        private const int    ROUND_SUBKEYS=OUTPUT_WHITEN+BLOCK_SIZE/4;// 8
+
+        private const int    TOTAL_SUBKEYS=ROUND_SUBKEYS+2*MAX_ROUNDS;// 40
+
+        private const int    SK_STEP = 0x02020202;
+        private const int    SK_BUMP = 0x01010101;
+        private const int    SK_ROTL = 9;
+
+        private bool encrypting;
+
+        private int[] gMDS0 = new int[MAX_KEY_BITS];
+        private int[] gMDS1 = new int[MAX_KEY_BITS];
+        private int[] gMDS2 = new int[MAX_KEY_BITS];
+        private int[] gMDS3 = new int[MAX_KEY_BITS];
+
+        /**
+        * gSubKeys[] and gSBox[] are eventually used in the
+        * encryption and decryption methods.
+        */
+        private int[] gSubKeys;
+        private int[] gSBox;
+
+        private int k64Cnt;
+
+        private byte[] workingKey;
+
+        public TwofishEngine()
+        {
+            // calculate the MDS matrix
+            int[] m1 = new int[2];
+            int[] mX = new int[2];
+            int[] mY = new int[2];
+            int j;
+
+            for (int i=0; i< MAX_KEY_BITS ; i++)
+            {
+                j = P[0,i] & 0xff;
+                m1[0] = j;
+                mX[0] = Mx_X(j) & 0xff;
+                mY[0] = Mx_Y(j) & 0xff;
+
+                j = P[1,i] & 0xff;
+                m1[1] = j;
+                mX[1] = Mx_X(j) & 0xff;
+                mY[1] = Mx_Y(j) & 0xff;
+
+                gMDS0[i] = m1[P_00]       | mX[P_00] <<  8 |
+                            mY[P_00] << 16 | mY[P_00] << 24;
+
+                gMDS1[i] = mY[P_10]       | mY[P_10] <<  8 |
+                            mX[P_10] << 16 | m1[P_10] << 24;
+
+                gMDS2[i] = mX[P_20]       | mY[P_20] <<  8 |
+                            m1[P_20] << 16 | mY[P_20] << 24;
+
+                gMDS3[i] = mX[P_30]       | m1[P_30] <<  8 |
+                            mY[P_30] << 16 | mX[P_30] << 24;
+            }
+        }
+
+        /**
+        * initialise a Twofish cipher.
+        *
+        * @param forEncryption whether or not we are for encryption.
+        * @param parameters the parameters required to set up the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool              forEncryption,
+            ICipherParameters parameters)
+        {
+            if (!(parameters is KeyParameter))
+				throw new ArgumentException("invalid parameter passed to Twofish init - " + parameters.GetType().ToString());
+
+			this.encrypting = forEncryption;
+			this.workingKey = ((KeyParameter)parameters).GetKey();
+			this.k64Cnt = (this.workingKey.Length / 8); // pre-padded ?
+			SetKey(this.workingKey);
+        }
+
+		public string AlgorithmName
+        {
+            get { return "Twofish"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if (workingKey == null)
+                throw new InvalidOperationException("Twofish not initialised");
+            if ((inOff + BLOCK_SIZE) > input.Length)
+                throw new DataLengthException("input buffer too short");
+            if ((outOff + BLOCK_SIZE) > output.Length)
+                throw new DataLengthException("output buffer too short");
+
+			if (encrypting)
+            {
+                EncryptBlock(input, inOff, output, outOff);
+            }
+            else
+            {
+                DecryptBlock(input, inOff, output, outOff);
+            }
+
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+            if (this.workingKey != null)
+            {
+                SetKey(this.workingKey);
+            }
+        }
+
+        public int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        //==================================
+        // Private Implementation
+        //==================================
+
+        private void SetKey(byte[] key)
+        {
+            int[] k32e = new int[MAX_KEY_BITS/64]; // 4
+            int[] k32o = new int[MAX_KEY_BITS/64]; // 4
+
+            int[] sBoxKeys = new int[MAX_KEY_BITS/64]; // 4
+            gSubKeys = new int[TOTAL_SUBKEYS];
+
+            if (k64Cnt < 1)
+            {
+                throw new ArgumentException("Key size less than 64 bits");
+            }
+
+            if (k64Cnt > 4)
+            {
+                throw new ArgumentException("Key size larger than 256 bits");
+            }
+
+            /*
+            * k64Cnt is the number of 8 byte blocks (64 chunks)
+            * that are in the input key.  The input key is a
+            * maximum of 32 bytes ( 256 bits ), so the range
+            * for k64Cnt is 1..4
+            */
+            for (int i=0,p=0; i<k64Cnt ; i++)
+            {
+                p = i* 8;
+
+                k32e[i] = BytesTo32Bits(key, p);
+                k32o[i] = BytesTo32Bits(key, p+4);
+
+                sBoxKeys[k64Cnt-1-i] = RS_MDS_Encode(k32e[i], k32o[i]);
+            }
+
+            int q,A,B;
+            for (int i=0; i < TOTAL_SUBKEYS / 2 ; i++)
+            {
+                q = i*SK_STEP;
+                A = F32(q,         k32e);
+                B = F32(q+SK_BUMP, k32o);
+                B = B << 8 | (int)((uint)B >> 24);
+                A += B;
+                gSubKeys[i*2] = A;
+                A += B;
+                gSubKeys[i*2 + 1] = A << SK_ROTL | (int)((uint)A >> (32-SK_ROTL));
+            }
+
+            /*
+            * fully expand the table for speed
+            */
+            int k0 = sBoxKeys[0];
+            int k1 = sBoxKeys[1];
+            int k2 = sBoxKeys[2];
+            int k3 = sBoxKeys[3];
+            int b0, b1, b2, b3;
+            gSBox = new int[4*MAX_KEY_BITS];
+            for (int i=0; i<MAX_KEY_BITS; i++)
+            {
+                b0 = b1 = b2 = b3 = i;
+                switch (k64Cnt & 3)
+                {
+                    case 1:
+                        gSBox[i*2]       = gMDS0[(P[P_01,b0] & 0xff) ^ M_b0(k0)];
+                        gSBox[i*2+1]     = gMDS1[(P[P_11,b1] & 0xff) ^ M_b1(k0)];
+                        gSBox[i*2+0x200] = gMDS2[(P[P_21,b2] & 0xff) ^ M_b2(k0)];
+                        gSBox[i*2+0x201] = gMDS3[(P[P_31,b3] & 0xff) ^ M_b3(k0)];
+                    break;
+                    case 0: // 256 bits of key
+                        b0 = (P[P_04,b0] & 0xff) ^ M_b0(k3);
+                        b1 = (P[P_14,b1] & 0xff) ^ M_b1(k3);
+                        b2 = (P[P_24,b2] & 0xff) ^ M_b2(k3);
+                        b3 = (P[P_34,b3] & 0xff) ^ M_b3(k3);
+                        // fall through, having pre-processed b[0]..b[3] with k32[3]
+                        goto case 3;
+                    case 3: // 192 bits of key
+                        b0 = (P[P_03,b0] & 0xff) ^ M_b0(k2);
+                        b1 = (P[P_13,b1] & 0xff) ^ M_b1(k2);
+                        b2 = (P[P_23,b2] & 0xff) ^ M_b2(k2);
+                        b3 = (P[P_33,b3] & 0xff) ^ M_b3(k2);
+                        // fall through, having pre-processed b[0]..b[3] with k32[2]
+                        goto case 2;
+                    case 2: // 128 bits of key
+                        gSBox[i * 2] = gMDS0[(P[P_01, (P[P_02, b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)];
+                        gSBox[i*2+1] = gMDS1[(P[P_11,(P[P_12,b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)];
+                        gSBox[i*2+0x200] = gMDS2[(P[P_21,(P[P_22,b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)];
+                        gSBox[i * 2 + 0x201] = gMDS3[(P[P_31, (P[P_32, b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
+                        break;
+                }
+            }
+
+            /*
+            * the function exits having setup the gSBox with the
+            * input key material.
+            */
+        }
+
+        /**
+        * Encrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        * The input will be an exact multiple of our blocksize.
+        *
+        * encryptBlock uses the pre-calculated gSBox[] and subKey[]
+        * arrays.
+        */
+        private void EncryptBlock(
+            byte[] src,
+            int srcIndex,
+            byte[] dst,
+            int dstIndex)
+        {
+            int x0 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[INPUT_WHITEN];
+            int x1 = BytesTo32Bits(src, srcIndex + 4) ^ gSubKeys[INPUT_WHITEN + 1];
+            int x2 = BytesTo32Bits(src, srcIndex + 8) ^ gSubKeys[INPUT_WHITEN + 2];
+            int x3 = BytesTo32Bits(src, srcIndex + 12) ^ gSubKeys[INPUT_WHITEN + 3];
+
+            int k = ROUND_SUBKEYS;
+            int t0, t1;
+            for (int r = 0; r < ROUNDS; r +=2)
+            {
+                t0 = Fe32_0(x0);
+                t1 = Fe32_3(x1);
+                x2 ^= t0 + t1 + gSubKeys[k++];
+                x2 = (int)((uint)x2 >>1) | x2 << 31;
+                x3 = (x3 << 1 | (int) ((uint)x3 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);
+
+                t0 = Fe32_0(x2);
+                t1 = Fe32_3(x3);
+                x0 ^= t0 + t1 + gSubKeys[k++];
+                x0 = (int) ((uint)x0 >>1) | x0 << 31;
+                x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2*t1 + gSubKeys[k++]);
+            }
+
+            Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], dst, dstIndex);
+            Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], dst, dstIndex + 4);
+            Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], dst, dstIndex + 8);
+            Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], dst, dstIndex + 12);
+        }
+
+        /**
+        * Decrypt the given input starting at the given offset and place
+        * the result in the provided buffer starting at the given offset.
+        * The input will be an exact multiple of our blocksize.
+        */
+        private void DecryptBlock(
+            byte[] src,
+            int srcIndex,
+            byte[] dst,
+            int dstIndex)
+        {
+            int x2 = BytesTo32Bits(src, srcIndex) ^ gSubKeys[OUTPUT_WHITEN];
+            int x3 = BytesTo32Bits(src, srcIndex+4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+            int x0 = BytesTo32Bits(src, srcIndex+8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+            int x1 = BytesTo32Bits(src, srcIndex+12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+
+            int k = ROUND_SUBKEYS + 2 * ROUNDS -1 ;
+            int t0, t1;
+            for (int r = 0; r< ROUNDS ; r +=2)
+            {
+                t0 = Fe32_0(x2);
+                t1 = Fe32_3(x3);
+                x1 ^= t0 + 2*t1 + gSubKeys[k--];
+                x0 = (x0 << 1 | (int)((uint) x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+                x1 = (int) ((uint)x1 >>1) | x1 << 31;
+
+                t0 = Fe32_0(x0);
+                t1 = Fe32_3(x1);
+                x3 ^= t0 + 2*t1 + gSubKeys[k--];
+                x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+                x3 = (int)((uint)x3 >>1) | x3 << 31;
+            }
+
+            Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], dst, dstIndex);
+            Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], dst, dstIndex + 4);
+            Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], dst, dstIndex + 8);
+            Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], dst, dstIndex + 12);
+        }
+
+        /*
+        * TODO:  This can be optimised and made cleaner by combining
+        * the functionality in this function and applying it appropriately
+        * to the creation of the subkeys during key setup.
+        */
+        private  int F32(int x, int[] k32)
+        {
+            int b0 = M_b0(x);
+            int b1 = M_b1(x);
+            int b2 = M_b2(x);
+            int b3 = M_b3(x);
+            int k0 = k32[0];
+            int k1 = k32[1];
+            int k2 = k32[2];
+            int k3 = k32[3];
+
+            int result = 0;
+            switch (k64Cnt & 3)
+            {
+                case 1:
+                    result = gMDS0[(P[P_01,b0] & 0xff) ^ M_b0(k0)] ^
+                            gMDS1[(P[P_11,b1] & 0xff) ^ M_b1(k0)] ^
+                            gMDS2[(P[P_21,b2] & 0xff) ^ M_b2(k0)] ^
+                            gMDS3[(P[P_31,b3] & 0xff) ^ M_b3(k0)];
+                    break;
+                case 0: /* 256 bits of key */
+                    b0 = (P[P_04,b0] & 0xff) ^ M_b0(k3);
+                    b1 = (P[P_14,b1] & 0xff) ^ M_b1(k3);
+                    b2 = (P[P_24,b2] & 0xff) ^ M_b2(k3);
+                    b3 = (P[P_34,b3] & 0xff) ^ M_b3(k3);
+                    goto case 3;
+                case 3:
+                    b0 = (P[P_03,b0] & 0xff) ^ M_b0(k2);
+                    b1 = (P[P_13,b1] & 0xff) ^ M_b1(k2);
+                    b2 = (P[P_23,b2] & 0xff) ^ M_b2(k2);
+                    b3 = (P[P_33,b3] & 0xff) ^ M_b3(k2);
+                    goto case 2;
+                case 2:
+                    result =
+                    gMDS0[(P[P_01,(P[P_02,b0]&0xff)^M_b0(k1)]&0xff)^M_b0(k0)] ^
+                    gMDS1[(P[P_11,(P[P_12,b1]&0xff)^M_b1(k1)]&0xff)^M_b1(k0)] ^
+                    gMDS2[(P[P_21,(P[P_22,b2]&0xff)^M_b2(k1)]&0xff)^M_b2(k0)] ^
+                    gMDS3[(P[P_31,(P[P_32,b3]&0xff)^M_b3(k1)]&0xff)^M_b3(k0)];
+                break;
+            }
+            return result;
+        }
+
+        /**
+        * Use (12, 8) Reed-Solomon code over GF(256) to produce
+        * a key S-box 32-bit entity from 2 key material 32-bit
+        * entities.
+        *
+        * @param    k0 first 32-bit entity
+        * @param    k1 second 32-bit entity
+        * @return     Remainder polynomial Generated using RS code
+        */
+        private  int RS_MDS_Encode(int k0, int k1)
+        {
+            int r = k1;
+            for (int i = 0 ; i < 4 ; i++) // shift 1 byte at a time
+            {
+                r = RS_rem(r);
+            }
+            r ^= k0;
+            for (int i=0 ; i < 4 ; i++)
+            {
+                r = RS_rem(r);
+            }
+
+            return r;
+        }
+
+        /**
+        * Reed-Solomon code parameters: (12,8) reversible code:
+		* <p>
+        * <pre>
+        * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+        * </pre>
+        * where a = primitive root of field generator 0x14D
+		* </p>
+        */
+        private  int RS_rem(int x)
+        {
+            int b = (int) (((uint)x >> 24) & 0xff);
+            int g2 = ((b << 1) ^
+                    ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+            int g3 = ( (int)((uint)b >> 1) ^
+                    ((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2 ;
+            return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+        }
+
+        private  int LFSR1(int x)
+        {
+            return (x >> 1) ^
+                    (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+        }
+
+        private  int LFSR2(int x)
+        {
+            return (x >> 2) ^
+                    (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+                    (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+        }
+
+        private  int Mx_X(int x)
+        {
+            return x ^ LFSR2(x);
+        } // 5B
+
+        private  int Mx_Y(int x)
+        {
+            return x ^ LFSR1(x) ^ LFSR2(x);
+        } // EF
+
+        private  int M_b0(int x)
+        {
+            return x & 0xff;
+        }
+
+        private  int M_b1(int x)
+        {
+            return (int)((uint)x >> 8) & 0xff;
+        }
+
+        private  int M_b2(int x)
+        {
+            return (int)((uint)x >> 16) & 0xff;
+        }
+
+        private  int M_b3(int x)
+        {
+            return (int)((uint)x >> 24) & 0xff;
+        }
+
+        private  int Fe32_0(int x)
+        {
+            return gSBox[ 0x000 + 2*(x & 0xff) ] ^
+                gSBox[ 0x001 + 2*((int)((uint)x >> 8) & 0xff) ] ^
+                gSBox[ 0x200 + 2*((int)((uint)x >> 16) & 0xff) ] ^
+                gSBox[ 0x201 + 2*((int)((uint)x >> 24) & 0xff) ];
+        }
+
+        private  int Fe32_3(int x)
+        {
+            return gSBox[ 0x000 + 2*((int)((uint)x >> 24) & 0xff) ] ^
+                gSBox[ 0x001 + 2*(x & 0xff) ] ^
+                gSBox[ 0x200 + 2*((int)((uint)x >> 8) & 0xff) ] ^
+                gSBox[ 0x201 + 2*((int)((uint)x >> 16) & 0xff) ];
+        }
+
+        private  int BytesTo32Bits(byte[] b, int p)
+        {
+            return ((b[p] & 0xff) ) |
+                ((b[p+1] & 0xff) << 8) |
+                ((b[p+2] & 0xff) << 16) |
+                ((b[p+3] & 0xff) << 24);
+        }
+
+        private  void Bits32ToBytes(int inData,  byte[] b, int offset)
+        {
+            b[offset] = (byte)inData;
+            b[offset + 1] = (byte)(inData >> 8);
+            b[offset + 2] = (byte)(inData >> 16);
+            b[offset + 3] = (byte)(inData >> 24);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/VMPCEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/VMPCEngine.cs
new file mode 100644
index 0000000..1c2802a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/VMPCEngine.cs
@@ -0,0 +1,140 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+    public class VmpcEngine
+        : IStreamCipher
+    {
+        /*
+        * variables to hold the state of the VMPC engine during encryption and
+        * decryption
+        */
+        protected byte n = 0;
+        protected byte[] P = null;
+        protected byte s = 0;
+
+        protected byte[] workingIV;
+        protected byte[] workingKey;
+
+        public virtual string AlgorithmName
+        {
+            get { return "VMPC"; }
+        }
+
+        /**
+        * initialise a VMPC cipher.
+        * 
+        * @param forEncryption
+        *    whether or not we are for encryption.
+        * @param params
+        *    the parameters required to set up the cipher.
+        * @exception ArgumentException
+        *    if the params argument is inappropriate.
+        */
+        public virtual void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            if (!(parameters is ParametersWithIV))
+                throw new ArgumentException("VMPC Init parameters must include an IV");
+
+            ParametersWithIV ivParams = (ParametersWithIV) parameters;
+
+            if (!(ivParams.Parameters is KeyParameter))
+                throw new ArgumentException("VMPC Init parameters must include a key");
+
+            KeyParameter key = (KeyParameter)ivParams.Parameters;
+
+            this.workingIV = ivParams.GetIV();
+
+            if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768)
+                throw new ArgumentException("VMPC requires 1 to 768 bytes of IV");
+
+            this.workingKey = key.GetKey();
+
+            InitKey(this.workingKey, this.workingIV);
+        }
+
+        protected virtual void InitKey(
+            byte[]	keyBytes,
+            byte[]	ivBytes)
+        {
+            s = 0;
+            P = new byte[256];
+            for (int i = 0; i < 256; i++)
+            {
+                P[i] = (byte) i;
+            }
+
+            for (int m = 0; m < 768; m++)
+            {
+                s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
+                byte temp = P[m & 0xff];
+                P[m & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+            }
+            for (int m = 0; m < 768; m++)
+            {
+                s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff];
+                byte temp = P[m & 0xff];
+                P[m & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+            }
+            n = 0;
+        }
+
+        public virtual void ProcessBytes(
+            byte[]	input,
+            int		inOff,
+            int		len,
+            byte[]	output,
+            int		outOff)
+        {
+            if ((inOff + len) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + len) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            for (int i = 0; i < len; i++)
+            {
+                s = P[(s + P[n & 0xff]) & 0xff];
+                byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+                // encryption
+                byte temp = P[n & 0xff];
+                P[n & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+                n = (byte) ((n + 1) & 0xff);
+
+                // xor
+                output[i + outOff] = (byte) (input[i + inOff] ^ z);
+            }
+        }
+
+        public virtual void Reset()
+        {
+            InitKey(this.workingKey, this.workingIV);
+        }
+
+        public virtual byte ReturnByte(
+            byte input)
+        {
+            s = P[(s + P[n & 0xff]) & 0xff];
+            byte z = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+            // encryption
+            byte temp = P[n & 0xff];
+            P[n & 0xff] = P[s & 0xff];
+            P[s & 0xff] = temp;
+            n = (byte) ((n + 1) & 0xff);
+
+            // xor
+            return (byte) (input ^ z);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/VMPCKSA3Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/VMPCKSA3Engine.cs
new file mode 100644
index 0000000..95b6813
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/VMPCKSA3Engine.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	public class VmpcKsa3Engine
+		: VmpcEngine
+	{
+		public override string AlgorithmName
+		{
+			get { return "VMPC-KSA3"; }
+		}
+
+		protected override void InitKey(
+			byte[]	keyBytes,
+			byte[]	ivBytes)
+		{
+			s = 0;
+			P = new byte[256];
+			for (int i = 0; i < 256; i++)
+			{
+				P[i] = (byte) i;
+			}
+
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+
+			n = 0;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/XSalsa20Engine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/XSalsa20Engine.cs
new file mode 100644
index 0000000..fc66309
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/XSalsa20Engine.cs
@@ -0,0 +1,71 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/// <summary>
+	/// Implementation of Daniel J. Bernstein's XSalsa20 stream cipher - Salsa20 with an extended nonce.
+	/// </summary>
+	/// <remarks>
+	/// XSalsa20 requires a 256 bit key, and a 192 bit nonce.
+	/// </remarks>
+	public class XSalsa20Engine 
+		: Salsa20Engine
+	{
+
+		public override string AlgorithmName
+		{
+			get { return "XSalsa20"; }
+		}
+
+		protected override int NonceSize
+		{
+			get { return 24; }
+		}
+
+		/// <summary>
+		/// XSalsa20 key generation: process 256 bit input key and 128 bits of the input nonce
+		/// using a core Salsa20 function without input addition to produce 256 bit working key
+		/// and use that with the remaining 64 bits of nonce to initialize a standard Salsa20 engine state.
+		/// </summary>
+		protected override void SetKey(byte[] keyBytes, byte[] ivBytes)
+		{
+			if (keyBytes.Length != 32)
+			{
+				throw new ArgumentException(AlgorithmName + " requires a 256 bit key");
+			}
+
+			// Set key for HSalsa20
+			base.SetKey(keyBytes, ivBytes);
+
+			// Pack next 64 bits of IV into engine state instead of counter
+			engineState[8] = Pack.LE_To_UInt32(ivBytes, 8);
+			engineState[9] = Pack.LE_To_UInt32(ivBytes, 12);
+
+			// Process engine state to generate Salsa20 key
+			uint[] hsalsa20Out = new uint[engineState.Length];
+			SalsaCore(20, engineState, hsalsa20Out);
+
+			// Set new key, removing addition in last round of salsaCore
+			engineState[1] = hsalsa20Out[0] - engineState[0];
+			engineState[2] = hsalsa20Out[5] - engineState[5];
+			engineState[3] = hsalsa20Out[10] - engineState[10];
+			engineState[4] = hsalsa20Out[15] - engineState[15];
+
+			engineState[11] = hsalsa20Out[6] - engineState[6];
+			engineState[12] = hsalsa20Out[7] - engineState[7];
+			engineState[13] = hsalsa20Out[8] - engineState[8];
+			engineState[14] = hsalsa20Out[9] - engineState[9];
+
+			// Last 64 bits of input IV
+			engineState[6] = Pack.LE_To_UInt32(ivBytes, 16);
+			engineState[7] = Pack.LE_To_UInt32(ivBytes, 20);
+
+			// Counter reset
+			ResetCounter();
+		}
+
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/engines/XTEAEngine.cs b/BouncyCastle.AxCrypt/src/crypto/engines/XTEAEngine.cs
new file mode 100644
index 0000000..eb92917
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/engines/XTEAEngine.cs
@@ -0,0 +1,168 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Engines
+{
+	/**
+	* An XTEA engine.
+	*/
+	public class XteaEngine
+		: IBlockCipher
+	{
+		private const int
+			rounds		= 32,
+			block_size	= 8,
+//			key_size	= 16,
+			delta		= unchecked((int) 0x9E3779B9);
+
+		/*
+		* the expanded key array of 4 subkeys
+		*/
+		private uint[] _S = new uint[4],
+			_sum0 = new uint[32],
+			_sum1 = new uint[32];
+		private bool _initialised, _forEncryption;
+
+		/**
+		* Create an instance of the TEA encryption algorithm
+		* and set some defaults
+		*/
+		public XteaEngine()
+		{
+			_initialised = false;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "XTEA"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		public int GetBlockSize()
+		{
+			return block_size;
+		}
+
+		/**
+		* initialise
+		*
+		* @param forEncryption whether or not we are for encryption.
+		* @param params the parameters required to set up the cipher.
+		* @exception ArgumentException if the params argument is
+		* inappropriate.
+		*/
+		public void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			if (!(parameters is KeyParameter))
+			{
+				throw new ArgumentException("invalid parameter passed to TEA init - "
+					+ parameters.GetType().FullName);
+			}
+
+			_forEncryption = forEncryption;
+			_initialised = true;
+
+			KeyParameter p = (KeyParameter) parameters;
+
+			setKey(p.GetKey());
+		}
+
+		public int ProcessBlock(
+			byte[]	inBytes,
+			int		inOff,
+			byte[]	outBytes,
+			int		outOff)
+		{
+			if (!_initialised)
+				throw new InvalidOperationException(AlgorithmName + " not initialised");
+
+			if ((inOff + block_size) > inBytes.Length)
+				throw new DataLengthException("input buffer too short");
+
+			if ((outOff + block_size) > outBytes.Length)
+				throw new DataLengthException("output buffer too short");
+
+			return _forEncryption
+				?	encryptBlock(inBytes, inOff, outBytes, outOff)
+				:	decryptBlock(inBytes, inOff, outBytes, outOff);
+		}
+
+		public void Reset()
+		{
+		}
+
+		/**
+		* Re-key the cipher.
+		*
+		* @param  key  the key to be used
+		*/
+		private void setKey(
+			byte[] key)
+		{
+			int i, j;
+			for (i = j = 0; i < 4; i++,j+=4)
+			{
+				_S[i] = Pack.BE_To_UInt32(key, j);
+			}
+
+			for (i = j = 0; i < rounds; i++)
+			{
+				_sum0[i] = ((uint)j + _S[j & 3]);
+				j += delta;
+				_sum1[i] = ((uint)j + _S[j >> 11 & 3]);
+			}
+		}
+
+		private int encryptBlock(
+			byte[]  inBytes,
+			int     inOff,
+			byte[]  outBytes,
+			int     outOff)
+		{
+			// Pack bytes into integers
+			uint v0 = Pack.BE_To_UInt32(inBytes, inOff);
+			uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4);
+
+			for (int i = 0; i < rounds; i++)
+			{
+				v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ _sum0[i];
+				v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ _sum1[i];
+			}
+
+			Pack.UInt32_To_BE(v0, outBytes, outOff);
+			Pack.UInt32_To_BE(v1, outBytes, outOff + 4);
+
+			return block_size;
+		}
+
+		private int decryptBlock(
+			byte[]	inBytes,
+			int		inOff,
+			byte[]	outBytes,
+			int		outOff)
+		{
+			// Pack bytes into integers
+			uint v0 = Pack.BE_To_UInt32(inBytes, inOff);
+			uint v1 = Pack.BE_To_UInt32(inBytes, inOff + 4);
+
+			for (int i = rounds-1; i >= 0; i--)
+			{
+				v1  -= ((v0 << 4 ^ v0 >> 5) + v0) ^ _sum1[i];
+				v0  -= ((v1 << 4 ^ v1 >> 5) + v1) ^ _sum0[i];
+			}
+
+			Pack.UInt32_To_BE(v0, outBytes, outOff);
+			Pack.UInt32_To_BE(v1, outBytes, outOff + 4);
+
+			return block_size;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/BaseKdfBytesGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/BaseKdfBytesGenerator.cs
new file mode 100644
index 0000000..bca4207
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/BaseKdfBytesGenerator.cs
@@ -0,0 +1,132 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+    * Basic KDF generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+    * <br/>
+    * This implementation is based on ISO 18033/P1363a.
+    */
+    public class BaseKdfBytesGenerator
+        : IDerivationFunction
+    {
+        private int     counterStart;
+        private IDigest  digest;
+        private byte[]  shared;
+        private byte[]  iv;
+
+        /**
+        * Construct a KDF Parameters generator.
+        *
+        * @param counterStart value of counter.
+        * @param digest the digest to be used as the source of derived keys.
+        */
+        public BaseKdfBytesGenerator(int counterStart, IDigest digest)
+        {
+            this.counterStart = counterStart;
+            this.digest = digest;
+        }
+
+        public virtual void Init(IDerivationParameters parameters)
+        {
+            if (parameters is KdfParameters)
+            {
+                KdfParameters   p = (KdfParameters)parameters;
+
+                shared = p.GetSharedSecret();
+                iv = p.GetIV();
+            }
+            else if (parameters is Iso18033KdfParameters)
+            {
+                Iso18033KdfParameters p = (Iso18033KdfParameters)parameters;
+
+                shared = p.GetSeed();
+                iv = null;
+            }
+            else
+            {
+                throw new ArgumentException("KDF parameters required for KDF Generator");
+            }
+        }
+
+        /**
+        * return the underlying digest.
+        */
+        public virtual IDigest Digest
+        {
+            get { return digest; }
+        }
+
+        /**
+        * fill len bytes of the output buffer with bytes generated from
+        * the derivation function.
+        *
+        * @throws ArgumentException if the size of the request will cause an overflow.
+        * @throws DataLengthException if the out buffer is too small.
+        */
+        public virtual int GenerateBytes(byte[] output, int outOff, int length)
+        {
+            if ((output.Length - length) < outOff)
+                throw new DataLengthException("output buffer too small");
+
+            long oBytes = length;
+            int outLen = digest.GetDigestSize();
+
+            //
+            // this is at odds with the standard implementation, the
+            // maximum value should be hBits * (2^32 - 1) where hBits
+            // is the digest output size in bits. We can't have an
+            // array with a long index at the moment...
+            //
+            if (oBytes > ((2L << 32) - 1))
+                throw new ArgumentException("Output length too large");
+
+            int cThreshold = (int)((oBytes + outLen - 1) / outLen);
+
+            byte[] dig = new byte[digest.GetDigestSize()];
+
+            byte[] C = new byte[4];
+            Pack.UInt32_To_BE((uint)counterStart, C, 0);
+
+            uint counterBase = (uint)(counterStart & ~0xFF);
+
+            for (int i = 0; i < cThreshold; i++)
+            {
+                digest.BlockUpdate(shared, 0, shared.Length);
+                digest.BlockUpdate(C, 0, 4);
+
+                if (iv != null)
+                {
+                    digest.BlockUpdate(iv, 0, iv.Length);
+                }
+
+                digest.DoFinal(dig, 0);
+
+                if (length > outLen)
+                {
+                    Array.Copy(dig, 0, output, outOff, outLen);
+                    outOff += outLen;
+                    length -= outLen;
+                }
+                else
+                {
+                    Array.Copy(dig, 0, output, outOff, length);
+                }
+
+                if (++C[3] == 0)
+                {
+                    counterBase += 0x100;
+                    Pack.UInt32_To_BE(counterBase, C, 0);
+                }
+            }
+
+            digest.Reset();
+
+            return (int)oBytes;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DHBasicKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DHBasicKeyPairGenerator.cs
new file mode 100644
index 0000000..51b3af6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DHBasicKeyPairGenerator.cs
@@ -0,0 +1,38 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * a basic Diffie-Hellman key pair generator.
+     *
+     * This generates keys consistent for use with the basic algorithm for
+     * Diffie-Hellman.
+     */
+    public class DHBasicKeyPairGenerator
+		: IAsymmetricCipherKeyPairGenerator
+    {
+        private DHKeyGenerationParameters param;
+
+        public virtual void Init(
+			KeyGenerationParameters parameters)
+        {
+            this.param = (DHKeyGenerationParameters)parameters;
+        }
+
+        public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+			DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
+			DHParameters dhp = param.Parameters;
+
+			BigInteger x = helper.CalculatePrivate(dhp, param.Random);
+			BigInteger y = helper.CalculatePublic(dhp, x);
+
+			return new AsymmetricCipherKeyPair(
+                new DHPublicKeyParameters(y, dhp),
+                new DHPrivateKeyParameters(x, dhp));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyGeneratorHelper.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyGeneratorHelper.cs
new file mode 100644
index 0000000..68aba64
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyGeneratorHelper.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    class DHKeyGeneratorHelper
+    {
+        internal static readonly DHKeyGeneratorHelper Instance = new DHKeyGeneratorHelper();
+
+        private DHKeyGeneratorHelper()
+        {
+        }
+
+        internal BigInteger CalculatePrivate(
+            DHParameters	dhParams,
+            SecureRandom	random)
+        {
+            int limit = dhParams.L;
+
+            if (limit != 0)
+            {
+                int minWeight = limit >> 2;
+                for (;;)
+                {
+                    BigInteger x = new BigInteger(limit, random).SetBit(limit - 1);
+                    if (WNafUtilities.GetNafWeight(x) >= minWeight)
+                    {
+                        return x;
+                    }
+                }
+            }
+
+            BigInteger min = BigInteger.Two;
+            int m = dhParams.M;
+            if (m != 0)
+            {
+                min = BigInteger.One.ShiftLeft(m - 1);
+            }
+
+            BigInteger q = dhParams.Q;
+            if (q == null)
+            {
+                q = dhParams.P;
+            }
+            BigInteger max = q.Subtract(BigInteger.Two);
+
+            {
+                int minWeight = max.BitLength >> 2;
+                for (;;)
+                {
+                    BigInteger x = BigIntegers.CreateRandomInRange(min, max, random);
+                    if (WNafUtilities.GetNafWeight(x) >= minWeight)
+                    {
+                        return x;
+                    }
+                }
+            }
+        }
+
+        internal BigInteger CalculatePublic(
+            DHParameters	dhParams,
+            BigInteger		x)
+        {
+            return dhParams.G.ModPow(x, dhParams.P);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyPairGenerator.cs
new file mode 100644
index 0000000..3bf58ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DHKeyPairGenerator.cs
@@ -0,0 +1,38 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * a Diffie-Hellman key pair generator.
+     *
+     * This generates keys consistent for use in the MTI/A0 key agreement protocol
+     * as described in "Handbook of Applied Cryptography", Pages 516-519.
+     */
+    public class DHKeyPairGenerator
+		: IAsymmetricCipherKeyPairGenerator
+    {
+		private DHKeyGenerationParameters param;
+
+		public virtual void Init(
+			KeyGenerationParameters parameters)
+        {
+            this.param = (DHKeyGenerationParameters)parameters;
+        }
+
+		public virtual AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+			DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
+			DHParameters dhp = param.Parameters;
+
+			BigInteger x = helper.CalculatePrivate(dhp, param.Random);
+			BigInteger y = helper.CalculatePublic(dhp, x);
+
+			return new AsymmetricCipherKeyPair(
+                new DHPublicKeyParameters(y, dhp),
+                new DHPrivateKeyParameters(x, dhp));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersGenerator.cs
new file mode 100644
index 0000000..e752c84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersGenerator.cs
@@ -0,0 +1,45 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    public class DHParametersGenerator
+    {
+        private int				size;
+        private int				certainty;
+        private SecureRandom	random;
+
+        public virtual void Init(
+            int				size,
+            int				certainty,
+            SecureRandom	random)
+        {
+            this.size = size;
+            this.certainty = certainty;
+            this.random = random;
+        }
+
+        /**
+         * which Generates the p and g values from the given parameters,
+         * returning the DHParameters object.
+         * <p>
+         * Note: can take a while...</p>
+         */
+        public virtual DHParameters GenerateParameters()
+        {
+			//
+			// find a safe prime p where p = 2*q + 1, where p and q are prime.
+			//
+			BigInteger[] safePrimes = DHParametersHelper.GenerateSafePrimes(size, certainty, random);
+
+			BigInteger p = safePrimes[0];
+			BigInteger q = safePrimes[1];
+			BigInteger g = DHParametersHelper.SelectGenerator(p, q, random);
+
+			return new DHParameters(p, g, q, BigInteger.Two, null);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersHelper.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersHelper.cs
new file mode 100644
index 0000000..bf2de2a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DHParametersHelper.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    internal class DHParametersHelper
+    {
+        private static readonly BigInteger Six = BigInteger.ValueOf(6);
+
+        private static readonly int[][] primeLists = BigInteger.primeLists;
+        private static readonly int[] primeProducts = BigInteger.primeProducts;
+        private static readonly BigInteger[] BigPrimeProducts = ConstructBigPrimeProducts(primeProducts);
+
+        private static BigInteger[] ConstructBigPrimeProducts(int[] primeProducts)
+        {
+            BigInteger[] bpp = new BigInteger[primeProducts.Length];
+            for (int i = 0; i < bpp.Length; ++i)
+            {
+                bpp[i] = BigInteger.ValueOf(primeProducts[i]);
+            }
+            return bpp;
+        }
+
+        /*
+         * Finds a pair of prime BigInteger's {p, q: p = 2q + 1}
+         * 
+         * (see: Handbook of Applied Cryptography 4.86)
+         */
+        internal static BigInteger[] GenerateSafePrimes(int size, int certainty, SecureRandom random)
+        {
+            BigInteger p, q;
+            int qLength = size - 1;
+            int minWeight = size >> 2;
+
+            if (size <= 32)
+            {
+                for (;;)
+                {
+                    q = new BigInteger(qLength, 2, random);
+
+                    p = q.ShiftLeft(1).Add(BigInteger.One);
+
+                    if (!p.IsProbablePrime(certainty))
+                        continue;
+
+                    if (certainty > 2 && !q.IsProbablePrime(certainty - 2))
+                        continue;
+
+                    break;
+                }
+            }
+            else
+            {
+                // Note: Modified from Java version for speed
+                for (;;)
+                {
+                    q = new BigInteger(qLength, 0, random);
+
+                retry:
+                    for (int i = 0; i < primeLists.Length; ++i)
+                    {
+                        int test = q.Remainder(BigPrimeProducts[i]).IntValue;
+
+                        if (i == 0)
+                        {
+                            int rem3 = test % 3;
+                            if (rem3 != 2)
+                            {
+                                int diff = 2 * rem3 + 2;
+                                q = q.Add(BigInteger.ValueOf(diff));
+                                test = (test + diff) % primeProducts[i];
+                            }
+                        }
+
+                        int[] primeList = primeLists[i];
+                        for (int j = 0; j < primeList.Length; ++j)
+                        {
+                            int prime = primeList[j];
+                            int qRem = test % prime;
+                            if (qRem == 0 || qRem == (prime >> 1))
+                            {
+                                q = q.Add(Six);
+                                goto retry;
+                            }
+                        }
+                    }
+
+                    if (q.BitLength != qLength)
+                        continue;
+
+                    if (!q.RabinMillerTest(2, random))
+                        continue;
+
+                    p = q.ShiftLeft(1).Add(BigInteger.One);
+
+                    if (!p.RabinMillerTest(certainty, random))
+                        continue;
+
+                    if (certainty > 2 && !q.RabinMillerTest(certainty - 2, random))
+                        continue;
+
+                    /*
+                     * Require a minimum weight of the NAF representation, since low-weight primes may be
+                     * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+                     * 
+                     * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+                     */
+                    if (WNafUtilities.GetNafWeight(p) < minWeight)
+                        continue;
+
+                    break;
+                }
+            }
+
+            return new BigInteger[] { p, q };
+        }
+
+        /*
+         * Select a high order element of the multiplicative group Zp*
+         * 
+         * p and q must be s.t. p = 2*q + 1, where p and q are prime (see generateSafePrimes)
+         */
+        internal static BigInteger SelectGenerator(BigInteger p, BigInteger q, SecureRandom random)
+        {
+            BigInteger pMinusTwo = p.Subtract(BigInteger.Two);
+            BigInteger g;
+
+            /*
+             * (see: Handbook of Applied Cryptography 4.80)
+             */
+//			do
+//			{
+//				g = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
+//			}
+//			while (g.ModPow(BigInteger.Two, p).Equals(BigInteger.One)
+//				|| g.ModPow(q, p).Equals(BigInteger.One));
+
+            /*
+             * RFC 2631 2.2.1.2 (and see: Handbook of Applied Cryptography 4.81)
+             */
+            do
+            {
+                BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusTwo, random);
+
+                g = h.ModPow(BigInteger.Two, p);
+            }
+            while (g.Equals(BigInteger.One));
+
+            return g;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DesEdeKeyGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DesEdeKeyGenerator.cs
new file mode 100644
index 0000000..5902643
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DesEdeKeyGenerator.cs
@@ -0,0 +1,67 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    public class DesEdeKeyGenerator
+		: DesKeyGenerator
+    {
+		public DesEdeKeyGenerator()
+		{
+		}
+
+		internal DesEdeKeyGenerator(
+			int defaultStrength)
+			: base(defaultStrength)
+		{
+		}
+
+		/**
+        * initialise the key generator - if strength is set to zero
+        * the key Generated will be 192 bits in size, otherwise
+        * strength can be 128 or 192 (or 112 or 168 if you don't count
+        * parity bits), depending on whether you wish to do 2-key or 3-key
+        * triple DES.
+        *
+        * @param param the parameters to be used for key generation
+        */
+        protected override void engineInit(
+			KeyGenerationParameters parameters)
+        {
+			this.random = parameters.Random;
+			this.strength = (parameters.Strength + 7) / 8;
+
+			if (strength == 0 || strength == (168 / 8))
+            {
+                strength = DesEdeParameters.DesEdeKeyLength;
+            }
+            else if (strength == (112 / 8))
+            {
+                strength = 2 * DesEdeParameters.DesKeyLength;
+            }
+            else if (strength != DesEdeParameters.DesEdeKeyLength
+                && strength != (2 * DesEdeParameters.DesKeyLength))
+            {
+                throw new ArgumentException("DESede key must be "
+                    + (DesEdeParameters.DesEdeKeyLength * 8) + " or "
+                    + (2 * 8 * DesEdeParameters.DesKeyLength)
+                    + " bits long.");
+            }
+        }
+
+        protected override byte[] engineGenerateKey()
+        {
+            byte[] newKey;
+
+			do
+            {
+                newKey = random.GenerateSeed(strength);
+                DesEdeParameters.SetOddParity(newKey);
+            }
+            while (DesEdeParameters.IsWeakKey(newKey, 0, newKey.Length));
+
+            return newKey;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DesKeyGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DesKeyGenerator.cs
new file mode 100644
index 0000000..154e347
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DesKeyGenerator.cs
@@ -0,0 +1,57 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    public class DesKeyGenerator
+		: CipherKeyGenerator
+    {
+		public DesKeyGenerator()
+		{
+		}
+
+		internal DesKeyGenerator(
+			int defaultStrength)
+			: base(defaultStrength)
+		{
+		}
+
+		/**
+		* initialise the key generator - if strength is set to zero
+		* the key generated will be 64 bits in size, otherwise
+		* strength can be 64 or 56 bits (if you don't count the parity bits).
+		*
+		* @param param the parameters to be used for key generation
+		*/
+		protected override void engineInit(
+			KeyGenerationParameters parameters)
+		{
+			base.engineInit(parameters);
+
+			if (strength == 0 || strength == (56 / 8))
+			{
+				strength = DesParameters.DesKeyLength;
+			}
+			else if (strength != DesParameters.DesKeyLength)
+			{
+				throw new ArgumentException(
+					"DES key must be " + (DesParameters.DesKeyLength * 8) + " bits long.");
+			}
+		}
+
+		protected override byte[] engineGenerateKey()
+        {
+            byte[] newKey;
+
+			do
+            {
+				newKey = random.GenerateSeed(DesParameters.DesKeyLength);
+				DesParameters.SetOddParity(newKey);
+            }
+            while (DesParameters.IsWeakKey(newKey, 0));
+
+			return newKey;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DsaKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DsaKeyPairGenerator.cs
new file mode 100644
index 0000000..1c9ce5a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DsaKeyPairGenerator.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * a DSA key pair generator.
+     *
+     * This Generates DSA keys in line with the method described
+     * in <i>FIPS 186-3 B.1 FFC Key Pair Generation</i>.
+     */
+    public class DsaKeyPairGenerator
+        : IAsymmetricCipherKeyPairGenerator
+    {
+        private static readonly BigInteger One = BigInteger.One;
+
+        private DsaKeyGenerationParameters param;
+
+        public void Init(
+            KeyGenerationParameters parameters)
+        {
+            if (parameters == null)
+                throw new ArgumentNullException("parameters");
+
+            // Note: If we start accepting instances of KeyGenerationParameters,
+            // must apply constraint checking on strength (see DsaParametersGenerator.Init)
+
+            this.param = (DsaKeyGenerationParameters) parameters;
+        }
+
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+            DsaParameters dsaParams = param.Parameters;
+
+            BigInteger x = GeneratePrivateKey(dsaParams.Q, param.Random);
+            BigInteger y = CalculatePublicKey(dsaParams.P, dsaParams.G, x);
+
+            return new AsymmetricCipherKeyPair(
+                new DsaPublicKeyParameters(y, dsaParams),
+                new DsaPrivateKeyParameters(x, dsaParams));
+        }
+
+        private static BigInteger GeneratePrivateKey(BigInteger q, SecureRandom random)
+        {
+            // B.1.2 Key Pair Generation by Testing Candidates
+            int minWeight = q.BitLength >> 2;
+            for (;;)
+            {
+                // TODO Prefer this method? (change test cases that used fixed random)
+                // B.1.1 Key Pair Generation Using Extra Random Bits
+                //BigInteger x = new BigInteger(q.BitLength + 64, random).Mod(q.Subtract(One)).Add(One);
+
+                BigInteger x = BigIntegers.CreateRandomInRange(One, q.Subtract(One), random);
+                if (WNafUtilities.GetNafWeight(x) >= minWeight)
+                {
+                    return x;
+                }
+            }
+        }
+
+        private static BigInteger CalculatePublicKey(BigInteger p, BigInteger g, BigInteger x)
+        {
+            return g.ModPow(x, p);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/DsaParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/DsaParametersGenerator.cs
new file mode 100644
index 0000000..cf6343a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/DsaParametersGenerator.cs
@@ -0,0 +1,390 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * Generate suitable parameters for DSA, in line with FIPS 186-2, or FIPS 186-3.
+     */
+    public class DsaParametersGenerator
+    {
+        private IDigest         digest;
+        private int				L, N;
+        private int				certainty;
+        private SecureRandom	random;
+        private bool            use186_3;
+        private int             usageIndex;
+
+        public DsaParametersGenerator()
+            : this(new Sha1Digest())
+        {
+        }
+
+        public DsaParametersGenerator(IDigest digest)
+        {
+            this.digest = digest;
+        }
+
+        /**
+         * initialise the key generator.
+         *
+         * @param size size of the key (range 2^512 -> 2^1024 - 64 bit increments)
+         * @param certainty measure of robustness of prime (for FIPS 186-2 compliance this should be at least 80).
+         * @param random random byte source.
+         */
+        public virtual void Init(
+            int             size,
+            int             certainty,
+            SecureRandom    random)
+        {
+            if (!IsValidDsaStrength(size))
+                throw new ArgumentException("size must be from 512 - 1024 and a multiple of 64", "size");
+
+            this.use186_3 = false;
+            this.L = size;
+            this.N = GetDefaultN(size);
+            this.certainty = certainty;
+            this.random = random;
+        }
+
+        /**
+         * Initialise the key generator for DSA 2.
+         * <p>
+         *     Use this init method if you need to generate parameters for DSA 2 keys.
+         * </p>
+         *
+         * @param params  DSA 2 key generation parameters.
+         */
+        public virtual void Init(DsaParameterGenerationParameters parameters)
+        {
+            // TODO Should we enforce the minimum 'certainty' values as per C.3 Table C.1?
+            this.use186_3 = true;
+            this.L = parameters.L;
+            this.N = parameters.N;
+            this.certainty = parameters.Certainty;
+            this.random = parameters.Random;
+            this.usageIndex = parameters.UsageIndex;
+
+            if ((L < 1024 || L > 3072) || L % 1024 != 0)
+                throw new ArgumentException("Values must be between 1024 and 3072 and a multiple of 1024", "L");
+            if (L == 1024 && N != 160)
+                throw new ArgumentException("N must be 160 for L = 1024");
+            if (L == 2048 && (N != 224 && N != 256))
+                throw new ArgumentException("N must be 224 or 256 for L = 2048");
+            if (L == 3072 && N != 256)
+                throw new ArgumentException("N must be 256 for L = 3072");
+
+            if (digest.GetDigestSize() * 8 < N)
+                throw new InvalidOperationException("Digest output size too small for value of N");
+        }
+
+//        /**
+//         * add value to b, returning the result in a. The a value is treated
+//         * as a BigInteger of length (a.Length * 8) bits. The result is
+//         * modulo 2^a.Length in case of overflow.
+//         */
+//        private static void Add(
+//            byte[]  a,
+//            byte[]  b,
+//            int     value)
+//        {
+//            int     x = (b[b.Length - 1] & 0xff) + value;
+//
+//            a[b.Length - 1] = (byte)x;
+//            x = (int) ((uint) x >>8);
+//
+//            for (int i = b.Length - 2; i >= 0; i--)
+//            {
+//                x += (b[i] & 0xff);
+//                a[i] = (byte)x;
+//                x = (int) ((uint) x >>8);
+//            }
+//        }
+
+        /**
+         * which Generates the p and g values from the given parameters,
+         * returning the DsaParameters object.
+         * <p>
+         * Note: can take a while...</p>
+         */
+        public virtual DsaParameters GenerateParameters()
+        {
+            return use186_3
+                ?	GenerateParameters_FIPS186_3()
+                :	GenerateParameters_FIPS186_2();
+        }
+
+        protected virtual DsaParameters GenerateParameters_FIPS186_2()
+        {
+            byte[] seed = new byte[20];
+            byte[] part1 = new byte[20];
+            byte[] part2 = new byte[20];
+            byte[] u = new byte[20];
+            int n = (L - 1) / 160;
+            byte[] w = new byte[L / 8];
+
+            if (!(digest is Sha1Digest))
+                throw new InvalidOperationException("can only use SHA-1 for generating FIPS 186-2 parameters");
+
+            for (;;)
+            {
+                random.NextBytes(seed);
+
+                Hash(digest, seed, part1);
+                Array.Copy(seed, 0, part2, 0, seed.Length);
+                Inc(part2);
+                Hash(digest, part2, part2);
+
+                for (int i = 0; i != u.Length; i++)
+                {
+                    u[i] = (byte)(part1[i] ^ part2[i]);
+                }
+
+                u[0] |= (byte)0x80;
+                u[19] |= (byte)0x01;
+
+                BigInteger q = new BigInteger(1, u);
+
+                if (!q.IsProbablePrime(certainty))
+                    continue;
+
+                byte[] offset = Arrays.Clone(seed);
+                Inc(offset);
+
+                for (int counter = 0; counter < 4096; ++counter)
+                {
+                    for (int k = 0; k < n; k++)
+                    {
+                        Inc(offset);
+                        Hash(digest, offset, part1);
+                        Array.Copy(part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
+                    }
+
+                    Inc(offset);
+                    Hash(digest, offset, part1);
+                    Array.Copy(part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);
+
+                    w[0] |= (byte)0x80;
+
+                    BigInteger x = new BigInteger(1, w);
+
+                    BigInteger c = x.Mod(q.ShiftLeft(1));
+
+                    BigInteger p = x.Subtract(c.Subtract(BigInteger.One));
+
+                    if (p.BitLength != L)
+                        continue;
+
+                    if (p.IsProbablePrime(certainty))
+                    {
+                        BigInteger g = CalculateGenerator_FIPS186_2(p, q, random);
+
+                        return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter));
+                    }
+                }
+            }
+        }
+
+        protected virtual BigInteger CalculateGenerator_FIPS186_2(BigInteger p, BigInteger q, SecureRandom r)
+        {
+            BigInteger e = p.Subtract(BigInteger.One).Divide(q);
+            BigInteger pSub2 = p.Subtract(BigInteger.Two);
+
+            for (;;)
+            {
+                BigInteger h = BigIntegers.CreateRandomInRange(BigInteger.Two, pSub2, r);
+                BigInteger g = h.ModPow(e, p);
+
+                if (g.BitLength > 1)
+                    return g;
+            }
+        }
+
+        /**
+         * generate suitable parameters for DSA, in line with
+         * <i>FIPS 186-3 A.1 Generation of the FFC Primes p and q</i>.
+         */
+        protected virtual DsaParameters GenerateParameters_FIPS186_3()
+        {
+// A.1.1.2 Generation of the Probable Primes p and q Using an Approved Hash Function
+            IDigest d = digest;
+            int outlen = d.GetDigestSize() * 8;
+
+// 1. Check that the (L, N) pair is in the list of acceptable (L, N pairs) (see Section 4.2). If
+//    the pair is not in the list, then return INVALID.
+            // Note: checked at initialisation
+            
+// 2. If (seedlen < N), then return INVALID.
+            // FIXME This should be configurable (must be >= N)
+            int seedlen = N;
+            byte[] seed = new byte[seedlen / 8];
+
+// 3. n = ceiling(L ⁄ outlen) – 1.
+            int n = (L - 1) / outlen;
+
+// 4. b = L – 1 – (n ∗ outlen).
+            int b = (L - 1) % outlen;
+
+            byte[] output = new byte[d.GetDigestSize()];
+            for (;;)
+            {
+// 5. Get an arbitrary sequence of seedlen bits as the domain_parameter_seed.
+                random.NextBytes(seed);
+
+// 6. U = Hash (domain_parameter_seed) mod 2^(N–1).
+                Hash(d, seed, output);
+                BigInteger U = new BigInteger(1, output).Mod(BigInteger.One.ShiftLeft(N - 1));
+
+// 7. q = 2^(N–1) + U + 1 – ( U mod 2).
+                BigInteger q = BigInteger.One.ShiftLeft(N - 1).Add(U).Add(BigInteger.One).Subtract(
+                    U.Mod(BigInteger.Two));
+
+// 8. Test whether or not q is prime as specified in Appendix C.3.
+                // TODO Review C.3 for primality checking
+                if (!q.IsProbablePrime(certainty))
+                {
+// 9. If q is not a prime, then go to step 5.
+                    continue;
+                }
+
+// 10. offset = 1.
+                // Note: 'offset' value managed incrementally
+                byte[] offset = Arrays.Clone(seed);
+
+// 11. For counter = 0 to (4L – 1) do
+                int counterLimit = 4 * L;
+                for (int counter = 0; counter < counterLimit; ++counter)
+                {
+// 11.1 For j = 0 to n do
+//      Vj = Hash ((domain_parameter_seed + offset + j) mod 2^seedlen).
+// 11.2 W = V0 + (V1 ∗ 2^outlen) + ... + (V^(n–1) ∗ 2^((n–1) ∗ outlen)) + ((Vn mod 2^b) ∗ 2^(n ∗ outlen)).
+                    // TODO Assemble w as a byte array
+                    BigInteger W = BigInteger.Zero;
+                    for (int j = 0, exp = 0; j <= n; ++j, exp += outlen)
+                    {
+                        Inc(offset);
+                        Hash(d, offset, output);
+
+                        BigInteger Vj = new BigInteger(1, output);
+                        if (j == n)
+                        {
+                            Vj = Vj.Mod(BigInteger.One.ShiftLeft(b));
+                        }
+
+                        W = W.Add(Vj.ShiftLeft(exp));
+                    }
+
+// 11.3 X = W + 2^(L–1). Comment: 0 ≤ W < 2L–1; hence, 2L–1 ≤ X < 2L.
+                    BigInteger X = W.Add(BigInteger.One.ShiftLeft(L - 1));
+
+// 11.4 c = X mod 2q.
+                    BigInteger c = X.Mod(q.ShiftLeft(1));
+
+// 11.5 p = X - (c - 1). Comment: p ≡ 1 (mod 2q).
+                    BigInteger p = X.Subtract(c.Subtract(BigInteger.One));
+
+                    // 11.6 If (p < 2^(L - 1)), then go to step 11.9
+                    if (p.BitLength != L)
+                        continue;
+
+// 11.7 Test whether or not p is prime as specified in Appendix C.3.
+                    // TODO Review C.3 for primality checking
+                    if (p.IsProbablePrime(certainty))
+                    {
+// 11.8 If p is determined to be prime, then return VALID and the values of p, q and
+//      (optionally) the values of domain_parameter_seed and counter.
+                        // TODO Make configurable (8-bit unsigned)?
+
+                        if (usageIndex >= 0)
+                        {
+                            BigInteger g = CalculateGenerator_FIPS186_3_Verifiable(d, p, q, seed, usageIndex);
+                            if (g != null)
+                                return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter, usageIndex));
+                        }
+
+                        {
+                            BigInteger g = CalculateGenerator_FIPS186_3_Unverifiable(p, q, random);
+
+                            return new DsaParameters(p, q, g, new DsaValidationParameters(seed, counter));
+                        }
+                    }
+
+// 11.9 offset = offset + n + 1.      Comment: Increment offset; then, as part of
+//                                    the loop in step 11, increment counter; if
+//                                    counter < 4L, repeat steps 11.1 through 11.8.
+                    // Note: 'offset' value already incremented in inner loop
+                }
+// 12. Go to step 5.
+            }
+        }
+
+        protected virtual BigInteger CalculateGenerator_FIPS186_3_Unverifiable(BigInteger p, BigInteger q,
+            SecureRandom r)
+        {
+            return CalculateGenerator_FIPS186_2(p, q, r);
+        }
+
+        protected virtual BigInteger CalculateGenerator_FIPS186_3_Verifiable(IDigest d, BigInteger p, BigInteger q,
+            byte[] seed, int index)
+        {
+            // A.2.3 Verifiable Canonical Generation of the Generator g
+            BigInteger e = p.Subtract(BigInteger.One).Divide(q);
+            byte[] ggen = Hex.Decode("6767656E");
+
+            // 7. U = domain_parameter_seed || "ggen" || index || count.
+            byte[] U = new byte[seed.Length + ggen.Length + 1 + 2];
+            Array.Copy(seed, 0, U, 0, seed.Length);
+            Array.Copy(ggen, 0, U, seed.Length, ggen.Length);
+            U[U.Length - 3] = (byte)index; 
+
+            byte[] w = new byte[d.GetDigestSize()];
+            for (int count = 1; count < (1 << 16); ++count)
+            {
+                Inc(U);
+                Hash(d, U, w);
+                BigInteger W = new BigInteger(1, w);
+                BigInteger g = W.ModPow(e, p);
+
+                if (g.CompareTo(BigInteger.Two) >= 0)
+                    return g;
+            }
+
+            return null;
+        }
+        
+        private static bool IsValidDsaStrength(
+            int strength)
+        {
+            return strength >= 512 && strength <= 1024 && strength % 64 == 0;
+        }
+
+        protected static void Hash(IDigest d, byte[] input, byte[] output)
+        {
+            d.BlockUpdate(input, 0, input.Length);
+            d.DoFinal(output, 0);
+        }
+
+        private static int GetDefaultN(int L)
+        {
+            return L > 1024 ? 256 : 160;
+        }
+
+        protected static void Inc(byte[] buf)
+        {
+            for (int i = buf.Length - 1; i >= 0; --i)
+            {
+                byte b = (byte)(buf[i] + 1);
+                buf[i] = b;
+
+                if (b != 0)
+                    break;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/ECKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/ECKeyPairGenerator.cs
new file mode 100644
index 0000000..6e777c7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/ECKeyPairGenerator.cs
@@ -0,0 +1,167 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    public class ECKeyPairGenerator
+        : IAsymmetricCipherKeyPairGenerator
+    {
+        private readonly string algorithm;
+
+        private ECDomainParameters parameters;
+        private DerObjectIdentifier publicKeyParamSet;
+        private SecureRandom random;
+
+        public ECKeyPairGenerator()
+            : this("EC")
+        {
+        }
+
+        public ECKeyPairGenerator(
+            string algorithm)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            this.algorithm = ECKeyParameters.VerifyAlgorithmName(algorithm);
+        }
+
+        public void Init(
+            KeyGenerationParameters parameters)
+        {
+            if (parameters is ECKeyGenerationParameters)
+            {
+                ECKeyGenerationParameters ecP = (ECKeyGenerationParameters) parameters;
+
+                this.publicKeyParamSet = ecP.PublicKeyParamSet;
+                this.parameters = ecP.DomainParameters;
+            }
+            else
+            {
+                DerObjectIdentifier oid;
+                switch (parameters.Strength)
+                {
+                    case 192:
+                        oid = X9ObjectIdentifiers.Prime192v1;
+                        break;
+                    case 224:
+                        oid = SecObjectIdentifiers.SecP224r1;
+                        break;
+                    case 239:
+                        oid = X9ObjectIdentifiers.Prime239v1;
+                        break;
+                    case 256:
+                        oid = X9ObjectIdentifiers.Prime256v1;
+                        break;
+                    case 384:
+                        oid = SecObjectIdentifiers.SecP384r1;
+                        break;
+                    case 521:
+                        oid = SecObjectIdentifiers.SecP521r1;
+                        break;
+                    default:
+                        throw new InvalidParameterException("unknown key size.");
+                }
+
+                X9ECParameters ecps = FindECCurveByOid(oid);
+
+                this.parameters = new ECDomainParameters(
+                    ecps.Curve, ecps.G, ecps.N, ecps.H, ecps.GetSeed());
+            }
+
+            this.random = parameters.Random;
+
+            if (this.random == null)
+            {
+                this.random = new SecureRandom();
+            }
+        }
+
+        /**
+         * Given the domain parameters this routine generates an EC key
+         * pair in accordance with X9.62 section 5.2.1 pages 26, 27.
+         */
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+            BigInteger n = parameters.N;
+            BigInteger d;
+            int minWeight = n.BitLength >> 2;
+
+            for (;;)
+            {
+                d = new BigInteger(n.BitLength, random);
+
+                if (d.CompareTo(BigInteger.Two) < 0 || d.CompareTo(n) >= 0)
+                    continue;
+
+                /*
+                 * Require a minimum weight of the NAF representation, since low-weight primes may be
+                 * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+                 * 
+                 * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+                 */
+                if (WNafUtilities.GetNafWeight(d) < minWeight)
+                    continue;
+
+                break;
+            }
+
+            ECPoint q = CreateBasePointMultiplier().Multiply(parameters.G, d);
+
+            if (publicKeyParamSet != null)
+            {
+                return new AsymmetricCipherKeyPair(
+                    new ECPublicKeyParameters(algorithm, q, publicKeyParamSet),
+                    new ECPrivateKeyParameters(algorithm, d, publicKeyParamSet));
+            }
+
+            return new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(algorithm, q, parameters),
+                new ECPrivateKeyParameters(algorithm, d, parameters));
+        }
+
+        protected virtual ECMultiplier CreateBasePointMultiplier()
+        {
+            return new FixedPointCombMultiplier();
+        }
+
+        internal static X9ECParameters FindECCurveByOid(DerObjectIdentifier oid)
+        {
+            // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
+
+            X9ECParameters ecP = CustomNamedCurves.GetByOid(oid);
+            if (ecP == null)
+            {
+                ecP = ECNamedCurveTable.GetByOid(oid);
+            }
+            return ecP;
+        }
+
+        internal static ECPublicKeyParameters GetCorrespondingPublicKey(
+            ECPrivateKeyParameters privKey)
+        {
+            ECDomainParameters ec = privKey.Parameters;
+            ECPoint q = new FixedPointCombMultiplier().Multiply(ec.G, privKey.D);
+
+            if (privKey.PublicKeyParamSet != null)
+            {
+                return new ECPublicKeyParameters(privKey.AlgorithmName, q, privKey.PublicKeyParamSet);
+            }
+
+            return new ECPublicKeyParameters(privKey.AlgorithmName, q, ec);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalKeyPairGenerator.cs
new file mode 100644
index 0000000..227e7fe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalKeyPairGenerator.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * a ElGamal key pair generator.
+     * <p>
+     * This Generates keys consistent for use with ElGamal as described in
+     * page 164 of "Handbook of Applied Cryptography".</p>
+     */
+    public class ElGamalKeyPairGenerator
+		: IAsymmetricCipherKeyPairGenerator
+    {
+        private ElGamalKeyGenerationParameters param;
+
+        public void Init(
+			KeyGenerationParameters parameters)
+        {
+            this.param = (ElGamalKeyGenerationParameters) parameters;
+        }
+
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+			DHKeyGeneratorHelper helper = DHKeyGeneratorHelper.Instance;
+			ElGamalParameters egp = param.Parameters;
+			DHParameters dhp = new DHParameters(egp.P, egp.G, null, 0, egp.L);
+
+			BigInteger x = helper.CalculatePrivate(dhp, param.Random);
+			BigInteger y = helper.CalculatePublic(dhp, x);
+
+			return new AsymmetricCipherKeyPair(
+                new ElGamalPublicKeyParameters(y, egp),
+                new ElGamalPrivateKeyParameters(x, egp));
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalParametersGenerator.cs
new file mode 100644
index 0000000..8443bb0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/ElGamalParametersGenerator.cs
@@ -0,0 +1,46 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    public class ElGamalParametersGenerator
+    {
+		private int				size;
+        private int				certainty;
+        private SecureRandom	random;
+
+		public void Init(
+            int				size,
+            int				certainty,
+            SecureRandom	random)
+        {
+            this.size = size;
+            this.certainty = certainty;
+            this.random = random;
+        }
+
+		/**
+         * which Generates the p and g values from the given parameters,
+         * returning the ElGamalParameters object.
+         * <p>
+         * Note: can take a while...
+		 * </p>
+         */
+        public ElGamalParameters GenerateParameters()
+        {
+			//
+			// find a safe prime p where p = 2*q + 1, where p and q are prime.
+			//
+			BigInteger[] safePrimes = DHParametersHelper.GenerateSafePrimes(size, certainty, random);
+
+			BigInteger p = safePrimes[0];
+			BigInteger q = safePrimes[1];
+			BigInteger g = DHParametersHelper.SelectGenerator(p, q, random);
+
+			return new ElGamalParameters(p, g);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410KeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410KeyPairGenerator.cs
new file mode 100644
index 0000000..013b818
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410KeyPairGenerator.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * a GOST3410 key pair generator.
+     * This generates GOST3410 keys in line with the method described
+     * in GOST R 34.10-94.
+     */
+    public class Gost3410KeyPairGenerator
+        : IAsymmetricCipherKeyPairGenerator
+    {
+        private Gost3410KeyGenerationParameters param;
+
+        public void Init(
+            KeyGenerationParameters parameters)
+        {
+            if (parameters is Gost3410KeyGenerationParameters)
+            {
+                this.param = (Gost3410KeyGenerationParameters) parameters;
+            }
+            else
+            {
+                Gost3410KeyGenerationParameters kgp = new Gost3410KeyGenerationParameters(
+                    parameters.Random,
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA);
+
+                if (parameters.Strength != kgp.Parameters.P.BitLength - 1)
+                {
+                    // TODO Should we complain?
+                }
+
+                this.param = kgp;
+            }
+        }
+
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+            SecureRandom random = param.Random;
+            Gost3410Parameters gost3410Params = param.Parameters;
+
+            BigInteger q = gost3410Params.Q, x;
+
+            int minWeight = 64;
+            for (;;)
+            {
+                x = new BigInteger(256, random);
+
+                if (x.SignValue < 1 || x.CompareTo(q) >= 0)
+                    continue;
+
+                /*
+                 * Require a minimum weight of the NAF representation, since low-weight primes may be
+                 * weak against a version of the number-field-sieve for the discrete-logarithm-problem.
+                 * 
+                 * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+                 */
+                if (WNafUtilities.GetNafWeight(x) < minWeight)
+                    continue;
+
+                break;
+            }
+
+            BigInteger p = gost3410Params.P;
+            BigInteger a = gost3410Params.A;
+
+            // calculate the public key.
+            BigInteger y = a.ModPow(x, p);
+
+            if (param.PublicKeyParamSet != null)
+            {
+                return new AsymmetricCipherKeyPair(
+                    new Gost3410PublicKeyParameters(y, param.PublicKeyParamSet),
+                    new Gost3410PrivateKeyParameters(x, param.PublicKeyParamSet));
+            }
+
+            return new AsymmetricCipherKeyPair(
+                new Gost3410PublicKeyParameters(y, gost3410Params),
+                new Gost3410PrivateKeyParameters(x, gost3410Params));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410ParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410ParametersGenerator.cs
new file mode 100644
index 0000000..52a9f5a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/GOST3410ParametersGenerator.cs
@@ -0,0 +1,530 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	 * generate suitable parameters for GOST3410.
+	 */
+	public class Gost3410ParametersGenerator
+	{
+		private int             size;
+		private int             typeproc;
+		private SecureRandom    init_random;
+
+		/**
+		 * initialise the key generator.
+		 *
+		 * @param size size of the key
+		 * @param typeProcedure type procedure A,B = 1;  A',B' - else
+		 * @param random random byte source.
+		 */
+		public void Init(
+			int             size,
+			int             typeProcedure,
+			SecureRandom    random)
+		{
+			this.size = size;
+			this.typeproc = typeProcedure;
+			this.init_random = random;
+		}
+
+		//Procedure A
+		private int procedure_A(int x0, int c,  BigInteger[] pq, int size)
+		{
+			//Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
+			while(x0<0 || x0>65536)
+			{
+				x0 = init_random.NextInt()/32768;
+			}
+
+			while((c<0 || c>65536) || (c/2==0))
+			{
+				c = init_random.NextInt()/32768 + 1;
+			}
+
+			BigInteger C = BigInteger.ValueOf(c);
+			BigInteger constA16 = BigInteger.ValueOf(19381);
+
+			//step1
+			BigInteger[] y = new BigInteger[1]; // begin length = 1
+			y[0] = BigInteger.ValueOf(x0);
+
+			//step 2
+			int[] t = new int[1]; // t - orders; begin length = 1
+			t[0] = size;
+			int s = 0;
+			for (int i=0; t[i]>=17; i++)
+			{
+				// extension array t
+				int[] tmp_t = new int[t.Length + 1];             ///////////////
+					Array.Copy(t,0,tmp_t,0,t.Length);          //  extension
+				t = new int[tmp_t.Length];                       //  array t
+				Array.Copy(tmp_t, 0, t, 0, tmp_t.Length);  ///////////////
+
+				t[i+1] = t[i]/2;
+				s = i+1;
+			}
+
+			//step3
+			BigInteger[] p = new BigInteger[s+1];
+			p[s] = new BigInteger("8003",16); //set min prime number length 16 bit
+
+			int m = s-1;  //step4
+
+			for (int i=0; i<s; i++)
+			{
+				int rm = t[m]/16;  //step5
+
+			step6: for(;;)
+				   {
+					   //step 6
+					   BigInteger[] tmp_y = new BigInteger[y.Length];  ////////////////
+					   Array.Copy(y,0,tmp_y,0,y.Length);         //  extension
+					   y = new BigInteger[rm+1];                       //  array y
+					   Array.Copy(tmp_y,0,y,0,tmp_y.Length);     ////////////////
+
+					   for (int j=0; j<rm; j++)
+					   {
+						   y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
+					   }
+
+					   //step 7
+					   BigInteger Ym = BigInteger.Zero;
+					   for (int j=0; j<rm; j++)
+					   {
+						   Ym = Ym.Add(y[j].ShiftLeft(16*j));
+					   }
+
+					   y[0] = y[rm]; //step 8
+
+					   //step 9
+					   BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
+						   Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(16*rm)));
+
+					   if (N.TestBit(0))
+					   {
+						   N = N.Add(BigInteger.One);
+					   }
+
+					   //step 10
+
+						for(;;)
+						{
+							//step 11
+							BigInteger NByLastP = N.Multiply(p[m+1]);
+
+							if (NByLastP.BitLength > t[m])
+							{
+								goto step6; //step 12
+							}
+
+							p[m] = NByLastP.Add(BigInteger.One);
+
+							//step13
+							if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
+								&& BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
+							{
+								break;
+							}
+
+							N = N.Add(BigInteger.Two);
+						}
+
+					   if (--m < 0)
+					   {
+						   pq[0] = p[0];
+						   pq[1] = p[1];
+						   return y[0].IntValue; //return for procedure B step 2
+					   }
+
+					   break; //step 14
+				   }
+			}
+			return y[0].IntValue;
+		}
+
+		//Procedure A'
+		private long procedure_Aa(long x0, long c, BigInteger[] pq, int size)
+		{
+			//Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
+			while(x0<0 || x0>4294967296L)
+			{
+				x0 = init_random.NextInt()*2;
+			}
+
+			while((c<0 || c>4294967296L) || (c/2==0))
+			{
+				c = init_random.NextInt()*2+1;
+			}
+
+			BigInteger C = BigInteger.ValueOf(c);
+			BigInteger constA32 = BigInteger.ValueOf(97781173);
+
+			//step1
+			BigInteger[] y = new BigInteger[1]; // begin length = 1
+			y[0] = BigInteger.ValueOf(x0);
+
+			//step 2
+			int[] t = new int[1]; // t - orders; begin length = 1
+			t[0] = size;
+			int s = 0;
+			for (int i=0; t[i]>=33; i++)
+			{
+				// extension array t
+				int[] tmp_t = new int[t.Length + 1];             ///////////////
+					Array.Copy(t,0,tmp_t,0,t.Length);          //  extension
+				t = new int[tmp_t.Length];                       //  array t
+				Array.Copy(tmp_t, 0, t, 0, tmp_t.Length);  ///////////////
+
+				t[i+1] = t[i]/2;
+				s = i+1;
+			}
+
+			//step3
+			BigInteger[] p = new BigInteger[s+1];
+			p[s] = new BigInteger("8000000B",16); //set min prime number length 32 bit
+
+			int m = s-1;  //step4
+
+			for (int i=0; i<s; i++)
+			{
+				int rm = t[m]/32;  //step5
+
+			step6: for(;;)
+				   {
+					   //step 6
+					   BigInteger[] tmp_y = new BigInteger[y.Length];  ////////////////
+						   Array.Copy(y,0,tmp_y,0,y.Length);         //  extension
+					   y = new BigInteger[rm+1];                       //  array y
+					   Array.Copy(tmp_y,0,y,0,tmp_y.Length);     ////////////////
+
+					   for (int j=0; j<rm; j++)
+					   {
+						   y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
+					   }
+
+					   //step 7
+					   BigInteger Ym = BigInteger.Zero;
+					   for (int j=0; j<rm; j++)
+					   {
+						   Ym = Ym.Add(y[j].ShiftLeft(32*j));
+					   }
+
+					   y[0] = y[rm]; //step 8
+
+					   //step 9
+					   BigInteger N = BigInteger.One.ShiftLeft(t[m]-1).Divide(p[m+1]).Add(
+						   Ym.ShiftLeft(t[m]-1).Divide(p[m+1].ShiftLeft(32*rm)));
+
+					   if (N.TestBit(0))
+					   {
+						   N = N.Add(BigInteger.One);
+					   }
+
+					   //step 10
+
+						for(;;)
+						{
+							//step 11
+							BigInteger NByLastP = N.Multiply(p[m+1]);
+
+							if (NByLastP.BitLength > t[m])
+							{
+								goto step6; //step 12
+							}
+
+							p[m] = NByLastP.Add(BigInteger.One);
+
+							//step13
+							if (BigInteger.Two.ModPow(NByLastP, p[m]).CompareTo(BigInteger.One) == 0
+								&& BigInteger.Two.ModPow(N, p[m]).CompareTo(BigInteger.One) != 0)
+							{
+								break;
+							}
+
+							N = N.Add(BigInteger.Two);
+						}
+
+					   if (--m < 0)
+					   {
+						   pq[0] = p[0];
+						   pq[1] = p[1];
+						   return y[0].LongValue; //return for procedure B' step 2
+					   }
+
+					   break; //step 14
+				   }
+			}
+			return y[0].LongValue;
+		}
+
+		//Procedure B
+		private void procedure_B(int x0, int c, BigInteger[] pq)
+		{
+			//Verify and perform condition: 0<x<2^16; 0<c<2^16; c - odd.
+			while(x0<0 || x0>65536)
+			{
+				x0 = init_random.NextInt()/32768;
+			}
+
+			while((c<0 || c>65536) || (c/2==0))
+			{
+				c = init_random.NextInt()/32768 + 1;
+			}
+
+			BigInteger [] qp = new BigInteger[2];
+			BigInteger q = null, Q = null, p = null;
+			BigInteger C = BigInteger.ValueOf(c);
+			BigInteger constA16 = BigInteger.ValueOf(19381);
+
+			//step1
+			x0 = procedure_A(x0, c, qp, 256);
+			q = qp[0];
+
+			//step2
+			x0 = procedure_A(x0, c, qp, 512);
+			Q = qp[0];
+
+			BigInteger[] y = new BigInteger[65];
+			y[0] = BigInteger.ValueOf(x0);
+
+			const int tp = 1024;
+
+			BigInteger qQ = q.Multiply(Q);
+
+step3:
+			for(;;)
+			{
+				//step 3
+				for (int j=0; j<64; j++)
+				{
+					y[j+1] = (y[j].Multiply(constA16).Add(C)).Mod(BigInteger.Two.Pow(16));
+				}
+
+				//step 4
+				BigInteger Y = BigInteger.Zero;
+
+				for (int j=0; j<64; j++)
+				{
+					Y = Y.Add(y[j].ShiftLeft(16*j));
+				}
+
+				y[0] = y[64]; //step 5
+
+				//step 6
+				BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
+					Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
+
+				if (N.TestBit(0))
+				{
+					N = N.Add(BigInteger.One);
+				}
+
+				//step 7
+
+				for(;;)
+				{
+					//step 11
+					BigInteger qQN = qQ.Multiply(N);
+
+					if (qQN.BitLength > tp)
+					{
+						goto step3; //step 9
+					}
+
+					p = qQN.Add(BigInteger.One);
+
+					//step10
+					if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
+						&& BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
+					{
+						pq[0] = p;
+						pq[1] = q;
+						return;
+					}
+
+					N = N.Add(BigInteger.Two);
+				}
+			}
+		}
+
+		//Procedure B'
+		private void procedure_Bb(long x0, long c, BigInteger[] pq)
+		{
+			//Verify and perform condition: 0<x<2^32; 0<c<2^32; c - odd.
+			while(x0<0 || x0>4294967296L)
+			{
+				x0 = init_random.NextInt()*2;
+			}
+
+			while((c<0 || c>4294967296L) || (c/2==0))
+			{
+				c = init_random.NextInt()*2+1;
+			}
+
+			BigInteger [] qp = new BigInteger[2];
+			BigInteger q = null, Q = null, p = null;
+			BigInteger C = BigInteger.ValueOf(c);
+			BigInteger constA32 = BigInteger.ValueOf(97781173);
+
+			//step1
+			x0 = procedure_Aa(x0, c, qp, 256);
+			q = qp[0];
+
+			//step2
+			x0 = procedure_Aa(x0, c, qp, 512);
+			Q = qp[0];
+
+			BigInteger[] y = new BigInteger[33];
+			y[0] = BigInteger.ValueOf(x0);
+
+			const int tp = 1024;
+
+			BigInteger qQ = q.Multiply(Q);
+
+step3:
+			for(;;)
+			{
+				//step 3
+				for (int j=0; j<32; j++)
+				{
+					y[j+1] = (y[j].Multiply(constA32).Add(C)).Mod(BigInteger.Two.Pow(32));
+				}
+
+				//step 4
+				BigInteger Y = BigInteger.Zero;
+				for (int j=0; j<32; j++)
+				{
+					Y = Y.Add(y[j].ShiftLeft(32*j));
+				}
+
+				y[0] = y[32]; //step 5
+
+				//step 6
+				BigInteger N = BigInteger.One.ShiftLeft(tp-1).Divide(qQ).Add(
+					Y.ShiftLeft(tp-1).Divide(qQ.ShiftLeft(1024)));
+
+				if (N.TestBit(0))
+				{
+					N = N.Add(BigInteger.One);
+				}
+
+				//step 7
+
+				for(;;)
+				{
+					//step 11
+					BigInteger qQN = qQ.Multiply(N);
+
+					if (qQN.BitLength > tp)
+					{
+						goto step3; //step 9
+					}
+
+					p = qQN.Add(BigInteger.One);
+
+					//step10
+					if (BigInteger.Two.ModPow(qQN, p).CompareTo(BigInteger.One) == 0
+						&& BigInteger.Two.ModPow(q.Multiply(N), p).CompareTo(BigInteger.One) != 0)
+					{
+						pq[0] = p;
+						pq[1] = q;
+						return;
+					}
+
+					N = N.Add(BigInteger.Two);
+				}
+			}
+		}
+
+
+		/**
+		 * Procedure C
+		 * procedure generates the a value from the given p,q,
+		 * returning the a value.
+		 */
+		private BigInteger procedure_C(BigInteger p, BigInteger q)
+		{
+			BigInteger pSub1 = p.Subtract(BigInteger.One);
+			BigInteger pSub1Divq = pSub1.Divide(q);
+
+			for(;;)
+			{
+				BigInteger d = new BigInteger(p.BitLength, init_random);
+
+				// 1 < d < p-1
+				if (d.CompareTo(BigInteger.One) > 0 && d.CompareTo(pSub1) < 0)
+				{
+					BigInteger a = d.ModPow(pSub1Divq, p);
+
+					if (a.CompareTo(BigInteger.One) != 0)
+					{
+						return a;
+					}
+				}
+			}
+		}
+
+		/**
+		 * which generates the p , q and a values from the given parameters,
+		 * returning the Gost3410Parameters object.
+		 */
+		public Gost3410Parameters GenerateParameters()
+		{
+			BigInteger [] pq = new BigInteger[2];
+			BigInteger    q = null, p = null, a = null;
+
+			int  x0, c;
+			long  x0L, cL;
+
+			if (typeproc==1)
+			{
+				x0 = init_random.NextInt();
+				c  = init_random.NextInt();
+
+				switch(size)
+				{
+					case 512:
+						procedure_A(x0, c, pq, 512);
+						break;
+					case 1024:
+						procedure_B(x0, c, pq);
+						break;
+					default:
+						throw new ArgumentException("Ooops! key size 512 or 1024 bit.");
+				}
+				p = pq[0];  q = pq[1];
+				a = procedure_C(p, q);
+				//System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+				//System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+				return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0, c));
+			}
+			else
+			{
+				x0L = init_random.NextLong();
+				cL  = init_random.NextLong();
+
+				switch(size)
+				{
+					case 512:
+						procedure_Aa(x0L, cL, pq, 512);
+						break;
+					case 1024:
+						procedure_Bb(x0L, cL, pq);
+						break;
+					default:
+						throw new InvalidOperationException("Ooops! key size 512 or 1024 bit.");
+				}
+				p = pq[0];  q = pq[1];
+				a = procedure_C(p, q);
+				//System.out.println("p:"+p.toString(16)+"\n"+"q:"+q.toString(16)+"\n"+"a:"+a.toString(16));
+				//System.out.println("p:"+p+"\n"+"q:"+q+"\n"+"a:"+a);
+				return new Gost3410Parameters(p, q, a, new Gost3410ValidationParameters(x0L, cL));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Kdf1BytesGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Kdf1BytesGenerator.cs
new file mode 100644
index 0000000..0ddf6c1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Kdf1BytesGenerator.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	 * KFD2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+	 * <br/>
+	 * This implementation is based on IEEE P1363/ISO 18033.
+	 */
+	public class Kdf1BytesGenerator
+		: BaseKdfBytesGenerator
+	{
+		/**
+		 * Construct a KDF1 byte generator.
+		 *
+		 * @param digest the digest to be used as the source of derived keys.
+		 */
+		public Kdf1BytesGenerator(IDigest digest)
+			: base(0, digest)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Kdf2BytesGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Kdf2BytesGenerator.cs
new file mode 100644
index 0000000..8a68219
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Kdf2BytesGenerator.cs
@@ -0,0 +1,27 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	 * KDF2 generator for derived keys and ivs as defined by IEEE P1363a/ISO 18033
+	 * <br/>
+	 * This implementation is based on IEEE P1363/ISO 18033.
+	 */
+	public class Kdf2BytesGenerator
+		: BaseKdfBytesGenerator
+	{
+		/**
+		* Construct a KDF2 bytes generator. Generates key material
+		* according to IEEE P1363 or ISO 18033 depending on the initialisation.
+		*
+		* @param digest the digest to be used as the source of derived keys.
+		*/
+		public Kdf2BytesGenerator(IDigest digest)
+			: base(1, digest)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Mgf1BytesGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Mgf1BytesGenerator.cs
new file mode 100644
index 0000000..23a3aca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Mgf1BytesGenerator.cs
@@ -0,0 +1,117 @@
+using System;
+//using Org.BouncyCastle.Math;
+//using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+    * Generator for MGF1 as defined in Pkcs 1v2
+    */
+    public class Mgf1BytesGenerator : IDerivationFunction
+    {
+        private IDigest digest;
+        private byte[]  seed;
+        private int     hLen;
+
+        /**
+        * @param digest the digest to be used as the source of Generated bytes
+        */
+        public Mgf1BytesGenerator(
+            IDigest  digest)
+        {
+            this.digest = digest;
+            this.hLen = digest.GetDigestSize();
+        }
+
+        public void Init(
+            IDerivationParameters    parameters)
+        {
+            if (!(typeof(MgfParameters).IsInstanceOfType(parameters)))
+            {
+                throw new ArgumentException("MGF parameters required for MGF1Generator");
+            }
+
+            MgfParameters   p = (MgfParameters)parameters;
+
+            seed = p.GetSeed();
+        }
+
+        /**
+        * return the underlying digest.
+        */
+        public IDigest Digest
+        {
+            get
+            {
+                return digest;
+            }
+        }
+
+        /**
+        * int to octet string.
+        */
+        private void ItoOSP(
+            int     i,
+            byte[]  sp)
+        {
+            sp[0] = (byte)((uint) i >> 24);
+            sp[1] = (byte)((uint) i >> 16);
+            sp[2] = (byte)((uint) i >> 8);
+            sp[3] = (byte)((uint) i >> 0);
+        }
+
+        /**
+        * fill len bytes of the output buffer with bytes Generated from
+        * the derivation function.
+        *
+        * @throws DataLengthException if the out buffer is too small.
+        */
+        public int GenerateBytes(
+            byte[]  output,
+            int     outOff,
+            int     length)
+        {
+			if ((output.Length - length) < outOff)
+			{
+				throw new DataLengthException("output buffer too small");
+			}
+
+			byte[]  hashBuf = new byte[hLen];
+            byte[]  C = new byte[4];
+            int     counter = 0;
+
+            digest.Reset();
+
+			if (length > hLen)
+			{
+				do
+				{
+					ItoOSP(counter, C);
+
+					digest.BlockUpdate(seed, 0, seed.Length);
+					digest.BlockUpdate(C, 0, C.Length);
+					digest.DoFinal(hashBuf, 0);
+
+					Array.Copy(hashBuf, 0, output, outOff + counter * hLen, hLen);
+				}
+				while (++counter < (length / hLen));
+			}
+
+            if ((counter * hLen) < length)
+            {
+                ItoOSP(counter, C);
+
+                digest.BlockUpdate(seed, 0, seed.Length);
+                digest.BlockUpdate(C, 0, C.Length);
+                digest.DoFinal(hashBuf, 0);
+
+                Array.Copy(hashBuf, 0, output, outOff + counter * hLen, length - (counter * hLen));
+            }
+
+            return length;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/NaccacheSternKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/NaccacheSternKeyPairGenerator.cs
new file mode 100644
index 0000000..e69813f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/NaccacheSternKeyPairGenerator.cs
@@ -0,0 +1,333 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	 * Key generation parameters for NaccacheStern cipher. For details on this cipher, please see
+	 *
+	 * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	 */
+	public class NaccacheSternKeyPairGenerator
+		: IAsymmetricCipherKeyPairGenerator
+	{
+		private static readonly int[] smallPrimes =
+		{
+			3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67,
+			71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
+			151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
+			239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331,
+			337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431,
+			433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523,
+			541, 547, 557
+		};
+
+		private NaccacheSternKeyGenerationParameters param;
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#init(org.bouncycastle.crypto.KeyGenerationParameters)
+		 */
+		public void Init(KeyGenerationParameters parameters)
+		{
+			this.param = (NaccacheSternKeyGenerationParameters)parameters;
+		}
+
+		/*
+		 * (non-Javadoc)
+		 *
+		 * @see org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator#generateKeyPair()
+		 */
+		public AsymmetricCipherKeyPair GenerateKeyPair()
+		{
+			int strength = param.Strength;
+			SecureRandom rand = param.Random;
+			int certainty = param.Certainty;
+			bool debug = param.IsDebug;
+
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("Fetching first " + param.CountSmallPrimes + " primes.");
+			}
+
+			IList smallPrimes = findFirstPrimes(param.CountSmallPrimes);
+
+			smallPrimes = permuteList(smallPrimes, rand);
+
+			BigInteger u = BigInteger.One;
+			BigInteger v = BigInteger.One;
+
+			for (int i = 0; i < smallPrimes.Count / 2; i++)
+			{
+				u = u.Multiply((BigInteger)smallPrimes[i]);
+			}
+			for (int i = smallPrimes.Count / 2; i < smallPrimes.Count; i++)
+			{
+				v = v.Multiply((BigInteger)smallPrimes[i]);
+			}
+
+			BigInteger sigma = u.Multiply(v);
+
+			// n = (2 a u _p + 1 ) ( 2 b v _q + 1)
+			// -> |n| = strength
+			// |2| = 1 in bits
+			// -> |a| * |b| = |n| - |u| - |v| - |_p| - |_q| - |2| -|2|
+			// remainingStrength = strength - sigma.bitLength() - _p.bitLength() -
+			// _q.bitLength() - 1 -1
+			int remainingStrength = strength - sigma.BitLength - 48;
+			BigInteger a = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+			BigInteger b = generatePrime(remainingStrength / 2 + 1, certainty, rand);
+
+			BigInteger _p;
+			BigInteger _q;
+			BigInteger p;
+			BigInteger q;
+
+			long tries = 0;
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("generating p and q");
+			}
+
+			BigInteger _2au = a.Multiply(u).ShiftLeft(1);
+			BigInteger _2bv = b.Multiply(v).ShiftLeft(1);
+
+			for (;;)
+			{
+				tries++;
+
+				_p = generatePrime(24, certainty, rand);
+
+				p = _p.Multiply(_2au).Add(BigInteger.One);
+
+				if (!p.IsProbablePrime(certainty))
+					continue;
+
+				for (;;)
+				{
+					_q = generatePrime(24, certainty, rand);
+
+					if (_p.Equals(_q))
+						continue;
+
+					q = _q.Multiply(_2bv).Add(BigInteger.One);
+
+					if (q.IsProbablePrime(certainty))
+						break;
+				}
+
+				if (!sigma.Gcd(_p.Multiply(_q)).Equals(BigInteger.One))
+				{
+                    System.Diagnostics.Debug.WriteLine("sigma.gcd(_p.mult(_q)) != 1!\n _p: " + _p + "\n _q: " + _q);
+					continue;
+				}
+
+				if (p.Multiply(q).BitLength < strength)
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("key size too small. Should be " + strength + " but is actually "
+							+ p.Multiply(q).BitLength);
+					}
+					continue;
+				}
+				break;
+			}
+
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("needed " + tries + " tries to generate p and q.");
+			}
+
+			BigInteger n = p.Multiply(q);
+			BigInteger phi_n = p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));
+			BigInteger g;
+			tries = 0;
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("generating g");
+			}
+			for (;;)
+			{
+				// TODO After the first loop, just regenerate one randomly-selected gPart each time?
+				IList gParts = Platform.CreateArrayList();
+				for (int ind = 0; ind != smallPrimes.Count; ind++)
+				{
+					BigInteger i = (BigInteger)smallPrimes[ind];
+					BigInteger e = phi_n.Divide(i);
+
+					for (;;)
+					{
+						tries++;
+
+						g = generatePrime(strength, certainty, rand);
+
+						if (!g.ModPow(e, n).Equals(BigInteger.One))
+						{
+							gParts.Add(g);
+							break;
+						}
+					}
+				}
+				g = BigInteger.One;
+				for (int i = 0; i < smallPrimes.Count; i++)
+				{
+					BigInteger gPart = (BigInteger) gParts[i];
+					BigInteger smallPrime = (BigInteger) smallPrimes[i];
+					g = g.Multiply(gPart.ModPow(sigma.Divide(smallPrime), n)).Mod(n);
+				}
+
+				// make sure that g is not divisible by p_i or q_i
+				bool divisible = false;
+				for (int i = 0; i < smallPrimes.Count; i++)
+				{
+					if (g.ModPow(phi_n.Divide((BigInteger)smallPrimes[i]), n).Equals(BigInteger.One))
+					{
+						if (debug)
+						{
+                            System.Diagnostics.Debug.WriteLine("g has order phi(n)/" + smallPrimes[i] + "\n g: " + g);
+						}
+						divisible = true;
+						break;
+					}
+				}
+
+				if (divisible)
+				{
+					continue;
+				}
+
+				// make sure that g has order > phi_n/4
+
+				//if (g.ModPow(phi_n.Divide(BigInteger.ValueOf(4)), n).Equals(BigInteger.One))
+				if (g.ModPow(phi_n.ShiftRight(2), n).Equals(BigInteger.One))
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("g has order phi(n)/4\n g:" + g);
+					}
+					continue;
+				}
+
+				if (g.ModPow(phi_n.Divide(_p), n).Equals(BigInteger.One))
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("g has order phi(n)/p'\n g: " + g);
+					}
+					continue;
+				}
+				if (g.ModPow(phi_n.Divide(_q), n).Equals(BigInteger.One))
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("g has order phi(n)/q'\n g: " + g);
+					}
+					continue;
+				}
+				if (g.ModPow(phi_n.Divide(a), n).Equals(BigInteger.One))
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("g has order phi(n)/a\n g: " + g);
+					}
+					continue;
+				}
+				if (g.ModPow(phi_n.Divide(b), n).Equals(BigInteger.One))
+				{
+					if (debug)
+					{
+                        System.Diagnostics.Debug.WriteLine("g has order phi(n)/b\n g: " + g);
+					}
+					continue;
+				}
+				break;
+			}
+			if (debug)
+			{
+                System.Diagnostics.Debug.WriteLine("needed " + tries + " tries to generate g");
+                System.Diagnostics.Debug.WriteLine("");
+                System.Diagnostics.Debug.WriteLine("found new NaccacheStern cipher variables:");
+                System.Diagnostics.Debug.WriteLine("smallPrimes: " + CollectionUtilities.ToString(smallPrimes));
+                System.Diagnostics.Debug.WriteLine("sigma:...... " + sigma + " (" + sigma.BitLength + " bits)");
+                System.Diagnostics.Debug.WriteLine("a:.......... " + a);
+                System.Diagnostics.Debug.WriteLine("b:.......... " + b);
+                System.Diagnostics.Debug.WriteLine("p':......... " + _p);
+                System.Diagnostics.Debug.WriteLine("q':......... " + _q);
+                System.Diagnostics.Debug.WriteLine("p:.......... " + p);
+                System.Diagnostics.Debug.WriteLine("q:.......... " + q);
+                System.Diagnostics.Debug.WriteLine("n:.......... " + n);
+                System.Diagnostics.Debug.WriteLine("phi(n):..... " + phi_n);
+                System.Diagnostics.Debug.WriteLine("g:.......... " + g);
+                System.Diagnostics.Debug.WriteLine("");
+			}
+
+			return new AsymmetricCipherKeyPair(new NaccacheSternKeyParameters(false, g, n, sigma.BitLength),
+				new NaccacheSternPrivateKeyParameters(g, n, sigma.BitLength, smallPrimes, phi_n));
+		}
+
+		private static BigInteger generatePrime(
+			int bitLength,
+			int certainty,
+			SecureRandom rand)
+		{
+			return new BigInteger(bitLength, certainty, rand);
+		}
+
+		/**
+		 * Generates a permuted ArrayList from the original one. The original List
+		 * is not modified
+		 *
+		 * @param arr
+		 *            the ArrayList to be permuted
+		 * @param rand
+		 *            the source of Randomness for permutation
+		 * @return a new IList with the permuted elements.
+		 */
+		private static IList permuteList(
+			IList           arr,
+			SecureRandom    rand)
+		{
+            // TODO Create a utility method for generating permutation of first 'n' integers
+
+            IList retval = Platform.CreateArrayList(arr.Count);
+
+			foreach (object element in arr)
+			{
+				int index = rand.Next(retval.Count + 1);
+				retval.Insert(index, element);
+			}
+
+			return retval;
+		}
+
+		/**
+		 * Finds the first 'count' primes starting with 3
+		 *
+		 * @param count
+		 *            the number of primes to find
+		 * @return a vector containing the found primes as Integer
+		 */
+		private static IList findFirstPrimes(
+			int count)
+		{
+			IList primes = Platform.CreateArrayList(count);
+
+			for (int i = 0; i != count; i++)
+			{
+				primes.Add(BigInteger.ValueOf(smallPrimes[i]));
+			}
+
+			return primes;
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/OpenSSLPBEParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/OpenSSLPBEParametersGenerator.cs
new file mode 100644
index 0000000..8da5d3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/OpenSSLPBEParametersGenerator.cs
@@ -0,0 +1,167 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	 * Generator for PBE derived keys and ivs as usd by OpenSSL.
+	 * <p>
+	 * The scheme is a simple extension of PKCS 5 V2.0 Scheme 1 using MD5 with an
+	 * iteration count of 1.
+	 * </p>
+	 */
+	public class OpenSslPbeParametersGenerator
+		: PbeParametersGenerator
+	{
+		private readonly IDigest digest = new MD5Digest();
+
+		/**
+		 * Construct a OpenSSL Parameters generator. 
+		 */
+		public OpenSslPbeParametersGenerator()
+		{
+		}
+
+		public override void Init(
+			byte[]	password,
+			byte[]	salt,
+			int		iterationCount)
+		{
+			// Ignore the provided iterationCount
+			base.Init(password, salt, 1);
+		}
+
+		/**
+		 * Initialise - note the iteration count for this algorithm is fixed at 1.
+		 * 
+		 * @param password password to use.
+		 * @param salt salt to use.
+		 */
+		public virtual void Init(
+			byte[] password,
+			byte[] salt)
+		{
+			base.Init(password, salt, 1);
+		}
+
+		/**
+		 * the derived key function, the ith hash of the password and the salt.
+		 */
+		private byte[] GenerateDerivedKey(
+			int bytesNeeded)
+		{
+			byte[] buf = new byte[digest.GetDigestSize()];
+			byte[] key = new byte[bytesNeeded];
+			int offset = 0;
+        
+			for (;;)
+			{
+				digest.BlockUpdate(mPassword, 0, mPassword.Length);
+				digest.BlockUpdate(mSalt, 0, mSalt.Length);
+
+				digest.DoFinal(buf, 0);
+
+				int len = (bytesNeeded > buf.Length) ? buf.Length : bytesNeeded;
+				Array.Copy(buf, 0, key, offset, len);
+				offset += len;
+
+				// check if we need any more
+				bytesNeeded -= len;
+				if (bytesNeeded == 0)
+				{
+					break;
+				}
+
+				// do another round
+				digest.Reset();
+				digest.BlockUpdate(buf, 0, buf.Length);
+			}
+
+			return key;
+		}
+
+		/**
+		 * Generate a key parameter derived from the password, salt, and iteration
+		 * count we are currently initialised with.
+		 *
+		 * @param keySize the size of the key we want (in bits)
+		 * @return a KeyParameter object.
+		 * @exception ArgumentException if the key length larger than the base hash size.
+		 */
+		[Obsolete("Use version with 'algorithm' parameter")]
+		public override ICipherParameters GenerateDerivedParameters(
+			int keySize)
+		{
+			return GenerateDerivedMacParameters(keySize);
+		}
+
+		public override ICipherParameters GenerateDerivedParameters(
+			string	algorithm,
+			int		keySize)
+		{
+			keySize /= 8;
+
+			byte[] dKey = GenerateDerivedKey(keySize);
+
+			return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+		}
+
+		/**
+		 * Generate a key with initialisation vector parameter derived from
+		 * the password, salt, and iteration count we are currently initialised
+		 * with.
+		 *
+		 * @param keySize the size of the key we want (in bits)
+		 * @param ivSize the size of the iv we want (in bits)
+		 * @return a ParametersWithIV object.
+		 * @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+		 */
+		[Obsolete("Use version with 'algorithm' parameter")]
+		public override ICipherParameters GenerateDerivedParameters(
+			int     keySize,
+			int     ivSize)
+		{
+			keySize = keySize / 8;
+			ivSize = ivSize / 8;
+
+			byte[] dKey = GenerateDerivedKey(keySize + ivSize);
+
+			return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+		}
+
+		public override ICipherParameters GenerateDerivedParameters(
+			string	algorithm,
+			int		keySize,
+			int     ivSize)
+		{
+			keySize /= 8;
+			ivSize /= 8;
+
+			byte[] dKey = GenerateDerivedKey(keySize + ivSize);
+			KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+			return new ParametersWithIV(key, dKey, keySize, ivSize);
+		}
+
+		/**
+		 * Generate a key parameter for use with a MAC derived from the password,
+		 * salt, and iteration count we are currently initialised with.
+		 *
+		 * @param keySize the size of the key we want (in bits)
+		 * @return a KeyParameter object.
+		 * @exception ArgumentException if the key length larger than the base hash size.
+		 */
+		public override ICipherParameters GenerateDerivedMacParameters(
+			int keySize)
+		{
+			keySize = keySize / 8;
+
+			byte[] dKey = GenerateDerivedKey(keySize);
+
+			return new KeyParameter(dKey, 0, keySize);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs12ParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs12ParametersGenerator.cs
new file mode 100644
index 0000000..cbbfd1b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs12ParametersGenerator.cs
@@ -0,0 +1,245 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * Generator for Pbe derived keys and ivs as defined by Pkcs 12 V1.0.
+     * <p>
+     * The document this implementation is based on can be found at
+     * <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-12/index.html">
+     * RSA's Pkcs12 Page</a>
+     * </p>
+     */
+    public class Pkcs12ParametersGenerator
+        : PbeParametersGenerator
+    {
+        public const int KeyMaterial = 1;
+        public const int IVMaterial  = 2;
+        public const int MacMaterial = 3;
+
+        private readonly IDigest digest;
+
+        private readonly int u;
+        private readonly int v;
+
+        /**
+         * Construct a Pkcs 12 Parameters generator.
+         *
+         * @param digest the digest to be used as the source of derived keys.
+         * @exception ArgumentException if an unknown digest is passed in.
+         */
+        public Pkcs12ParametersGenerator(
+            IDigest digest)
+        {
+            this.digest = digest;
+
+            u = digest.GetDigestSize();
+            v = digest.GetByteLength();
+        }
+
+        /**
+         * add a + b + 1, returning the result in a. The a value is treated
+         * as a BigInteger of length (b.Length * 8) bits. The result is
+         * modulo 2^b.Length in case of overflow.
+         */
+        private void Adjust(
+            byte[]  a,
+            int     aOff,
+            byte[]  b)
+        {
+            int  x = (b[b.Length - 1] & 0xff) + (a[aOff + b.Length - 1] & 0xff) + 1;
+
+            a[aOff + b.Length - 1] = (byte)x;
+            x = (int) ((uint) x >> 8);
+
+            for (int i = b.Length - 2; i >= 0; i--)
+            {
+                x += (b[i] & 0xff) + (a[aOff + i] & 0xff);
+                a[aOff + i] = (byte)x;
+                x = (int) ((uint) x >> 8);
+            }
+        }
+
+        /**
+         * generation of a derived key ala Pkcs12 V1.0.
+         */
+        private byte[] GenerateDerivedKey(
+            int idByte,
+            int n)
+        {
+            byte[] D = new byte[v];
+            byte[] dKey = new byte[n];
+
+            for (int i = 0; i != D.Length; i++)
+            {
+                D[i] = (byte)idByte;
+            }
+
+            byte[] S;
+
+            if ((mSalt != null) && (mSalt.Length != 0))
+            {
+                S = new byte[v * ((mSalt.Length + v - 1) / v)];
+
+                for (int i = 0; i != S.Length; i++)
+                {
+                    S[i] = mSalt[i % mSalt.Length];
+                }
+            }
+            else
+            {
+                S = new byte[0];
+            }
+
+            byte[] P;
+
+            if ((mPassword != null) && (mPassword.Length != 0))
+            {
+                P = new byte[v * ((mPassword.Length + v - 1) / v)];
+
+                for (int i = 0; i != P.Length; i++)
+                {
+                    P[i] = mPassword[i % mPassword.Length];
+                }
+            }
+            else
+            {
+                P = new byte[0];
+            }
+
+            byte[]  I = new byte[S.Length + P.Length];
+
+            Array.Copy(S, 0, I, 0, S.Length);
+            Array.Copy(P, 0, I, S.Length, P.Length);
+
+            byte[]  B = new byte[v];
+            int     c = (n + u - 1) / u;
+            byte[]  A = new byte[u];
+
+            for (int i = 1; i <= c; i++)
+            {
+                digest.BlockUpdate(D, 0, D.Length);
+                digest.BlockUpdate(I, 0, I.Length);
+                digest.DoFinal(A, 0);
+
+                for (int j = 1; j != mIterationCount; j++)
+                {
+                    digest.BlockUpdate(A, 0, A.Length);
+                    digest.DoFinal(A, 0);
+                }
+
+                for (int j = 0; j != B.Length; j++)
+                {
+                    B[j] = A[j % A.Length];
+                }
+
+                for (int j = 0; j != I.Length / v; j++)
+                {
+                    Adjust(I, j * v, B);
+                }
+
+                if (i == c)
+                {
+                    Array.Copy(A, 0, dKey, (i - 1) * u, dKey.Length - ((i - 1) * u));
+                }
+                else
+                {
+                    Array.Copy(A, 0, dKey, (i - 1) * u, A.Length);
+                }
+            }
+
+            return dKey;
+        }
+
+        /**
+         * Generate a key parameter derived from the password, salt, and iteration
+         * count we are currently initialised with.
+         *
+         * @param keySize the size of the key we want (in bits)
+         * @return a KeyParameter object.
+         */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public override ICipherParameters GenerateDerivedParameters(
+            int keySize)
+        {
+            keySize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
+
+            return new KeyParameter(dKey, 0, keySize);
+        }
+
+        public override ICipherParameters GenerateDerivedParameters(
+            string	algorithm,
+            int		keySize)
+        {
+            keySize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
+
+            return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+        }
+
+        /**
+         * Generate a key with initialisation vector parameter derived from
+         * the password, salt, and iteration count we are currently initialised
+         * with.
+         *
+         * @param keySize the size of the key we want (in bits)
+         * @param ivSize the size of the iv we want (in bits)
+         * @return a ParametersWithIV object.
+         */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public override ICipherParameters GenerateDerivedParameters(
+            int	keySize,
+            int	ivSize)
+        {
+            keySize /= 8;
+            ivSize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
+
+            byte[] iv = GenerateDerivedKey(IVMaterial, ivSize);
+
+            return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), iv, 0, ivSize);
+        }
+
+        public override ICipherParameters GenerateDerivedParameters(
+            string	algorithm,
+            int		keySize,
+            int		ivSize)
+        {
+            keySize /= 8;
+            ivSize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(KeyMaterial, keySize);
+            KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+            byte[] iv = GenerateDerivedKey(IVMaterial, ivSize);
+
+            return new ParametersWithIV(key, iv, 0, ivSize);
+        }
+
+        /**
+         * Generate a key parameter for use with a MAC derived from the password,
+         * salt, and iteration count we are currently initialised with.
+         *
+         * @param keySize the size of the key we want (in bits)
+         * @return a KeyParameter object.
+         */
+        public override ICipherParameters GenerateDerivedMacParameters(
+            int keySize)
+        {
+            keySize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(MacMaterial, keySize);
+
+            return new KeyParameter(dKey, 0, keySize);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S1ParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S1ParametersGenerator.cs
new file mode 100644
index 0000000..8586e1c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S1ParametersGenerator.cs
@@ -0,0 +1,162 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	* Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 1.
+	* Note this generator is limited to the size of the hash produced by the
+	* digest used to drive it.
+	* <p>
+	* The document this implementation is based on can be found at
+	* <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+	* RSA's Pkcs5 Page</a>
+	* </p>
+	*/
+	public class Pkcs5S1ParametersGenerator
+		: PbeParametersGenerator
+	{
+		private readonly IDigest digest;
+
+		/**
+		* Construct a Pkcs 5 Scheme 1 Parameters generator.
+		*
+		* @param digest the digest to be used as the source of derived keys.
+		*/
+		public Pkcs5S1ParametersGenerator(
+			IDigest digest)
+		{
+			this.digest = digest;
+		}
+
+		/**
+		* the derived key function, the ith hash of the mPassword and the mSalt.
+		*/
+		private byte[] GenerateDerivedKey()
+		{
+			byte[] digestBytes = new byte[digest.GetDigestSize()];
+
+			digest.BlockUpdate(mPassword, 0, mPassword.Length);
+			digest.BlockUpdate(mSalt, 0, mSalt.Length);
+
+			digest.DoFinal(digestBytes, 0);
+			for (int i = 1; i < mIterationCount; i++)
+			{
+				digest.BlockUpdate(digestBytes, 0, digestBytes.Length);
+				digest.DoFinal(digestBytes, 0);
+			}
+
+			return digestBytes;
+		}
+
+		/**
+		* Generate a key parameter derived from the mPassword, mSalt, and iteration
+		* count we are currently initialised with.
+		*
+		* @param keySize the size of the key we want (in bits)
+		* @return a KeyParameter object.
+		* @exception ArgumentException if the key length larger than the base hash size.
+		*/
+		[Obsolete("Use version with 'algorithm' parameter")]
+		public override ICipherParameters GenerateDerivedParameters(
+			int keySize)
+		{
+			return GenerateDerivedMacParameters(keySize);
+		}
+
+		public override ICipherParameters GenerateDerivedParameters(
+			string	algorithm,
+			int		keySize)
+		{
+			keySize /= 8;
+
+			if (keySize > digest.GetDigestSize())
+			{
+				throw new ArgumentException(
+					"Can't Generate a derived key " + keySize + " bytes long.");
+			}
+
+			byte[] dKey = GenerateDerivedKey();
+
+			return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+		}
+
+		/**
+		* Generate a key with initialisation vector parameter derived from
+		* the mPassword, mSalt, and iteration count we are currently initialised
+		* with.
+		*
+		* @param keySize the size of the key we want (in bits)
+		* @param ivSize the size of the iv we want (in bits)
+		* @return a ParametersWithIV object.
+		* @exception ArgumentException if keySize + ivSize is larger than the base hash size.
+		*/
+		[Obsolete("Use version with 'algorithm' parameter")]
+		public override ICipherParameters GenerateDerivedParameters(
+			int	keySize,
+			int	ivSize)
+		{
+			keySize /= 8;
+			ivSize /= 8;
+
+			if ((keySize + ivSize) > digest.GetDigestSize())
+			{
+				throw new ArgumentException(
+					"Can't Generate a derived key " + (keySize + ivSize) + " bytes long.");
+			}
+
+			byte[] dKey = GenerateDerivedKey();
+
+			return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+		}
+
+		public override ICipherParameters GenerateDerivedParameters(
+			string	algorithm,
+			int		keySize,
+			int		ivSize)
+		{
+			keySize /= 8;
+			ivSize /= 8;
+
+			if ((keySize + ivSize) > digest.GetDigestSize())
+			{
+				throw new ArgumentException(
+					"Can't Generate a derived key " + (keySize + ivSize) + " bytes long.");
+			}
+
+			byte[] dKey = GenerateDerivedKey();
+			KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+			return new ParametersWithIV(key, dKey, keySize, ivSize);
+		}
+
+		/**
+		* Generate a key parameter for use with a MAC derived from the mPassword,
+		* mSalt, and iteration count we are currently initialised with.
+		*
+		* @param keySize the size of the key we want (in bits)
+		* @return a KeyParameter object.
+		* @exception ArgumentException if the key length larger than the base hash size.
+		*/
+		public override ICipherParameters GenerateDerivedMacParameters(
+			int keySize)
+		{
+			keySize /= 8;
+
+			if (keySize > digest.GetDigestSize())
+			{
+				throw new ArgumentException(
+					"Can't Generate a derived key " + keySize + " bytes long.");
+			}
+
+			byte[] dKey = GenerateDerivedKey();
+
+			return new KeyParameter(dKey, 0, keySize);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S2ParametersGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S2ParametersGenerator.cs
new file mode 100644
index 0000000..10352ab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Pkcs5S2ParametersGenerator.cs
@@ -0,0 +1,180 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+    * Generator for Pbe derived keys and ivs as defined by Pkcs 5 V2.0 Scheme 2.
+    * This generator uses a SHA-1 HMac as the calculation function.
+    * <p>
+    * The document this implementation is based on can be found at
+    * <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+    * RSA's Pkcs5 Page</a></p>
+    */
+    public class Pkcs5S2ParametersGenerator
+        : PbeParametersGenerator
+    {
+        private readonly IMac hMac;
+        private readonly byte[] state;
+
+        /**
+        * construct a Pkcs5 Scheme 2 Parameters generator.
+        */
+        public Pkcs5S2ParametersGenerator()
+            : this(new Sha1Digest())
+        {
+        }
+
+        public Pkcs5S2ParametersGenerator(IDigest digest)
+        {
+            this.hMac = new HMac(digest);
+            this.state = new byte[hMac.GetMacSize()];
+        }
+
+        private void F(
+            byte[]  S,
+            int     c,
+            byte[]  iBuf,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            if (c == 0)
+                throw new ArgumentException("iteration count must be at least 1.");
+
+            if (S != null)
+            {
+                hMac.BlockUpdate(S, 0, S.Length);
+            }
+
+            hMac.BlockUpdate(iBuf, 0, iBuf.Length);
+            hMac.DoFinal(state, 0);
+
+            Array.Copy(state, 0, outBytes, outOff, state.Length);
+
+            for (int count = 1; count < c; ++count)
+            {
+                hMac.BlockUpdate(state, 0, state.Length);
+                hMac.DoFinal(state, 0);
+
+                for (int j = 0; j < state.Length; ++j)
+                {
+                    outBytes[outOff + j] ^= state[j];
+                }
+            }
+        }
+
+        private byte[] GenerateDerivedKey(
+            int dkLen)
+        {
+            int     hLen = hMac.GetMacSize();
+            int     l = (dkLen + hLen - 1) / hLen;
+            byte[]  iBuf = new byte[4];
+            byte[]  outBytes = new byte[l * hLen];
+            int     outPos = 0;
+
+            ICipherParameters param = new KeyParameter(mPassword);
+
+            hMac.Init(param);
+
+            for (int i = 1; i <= l; i++)
+            {
+                // Increment the value in 'iBuf'
+                int pos = 3;
+                while (++iBuf[pos] == 0)
+                {
+                    --pos;
+                }
+
+                F(mSalt, mIterationCount, iBuf, outBytes, outPos);
+                outPos += hLen;
+            }
+
+            return outBytes;
+        }
+
+        /**
+        * Generate a key parameter derived from the password, salt, and iteration
+        * count we are currently initialised with.
+        *
+        * @param keySize the size of the key we want (in bits)
+        * @return a KeyParameter object.
+        */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public override ICipherParameters GenerateDerivedParameters(
+            int keySize)
+        {
+            return GenerateDerivedMacParameters(keySize);
+        }
+
+        public override ICipherParameters GenerateDerivedParameters(
+            string	algorithm,
+            int		keySize)
+        {
+            keySize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(keySize);
+
+            return ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+        }
+
+        /**
+        * Generate a key with initialisation vector parameter derived from
+        * the password, salt, and iteration count we are currently initialised
+        * with.
+        *
+        * @param keySize the size of the key we want (in bits)
+        * @param ivSize the size of the iv we want (in bits)
+        * @return a ParametersWithIV object.
+        */
+        [Obsolete("Use version with 'algorithm' parameter")]
+        public override ICipherParameters GenerateDerivedParameters(
+            int	keySize,
+            int	ivSize)
+        {
+            keySize /= 8;
+            ivSize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(keySize + ivSize);
+
+            return new ParametersWithIV(new KeyParameter(dKey, 0, keySize), dKey, keySize, ivSize);
+        }
+
+        public override ICipherParameters GenerateDerivedParameters(
+            string	algorithm,
+            int		keySize,
+            int		ivSize)
+        {
+            keySize /= 8;
+            ivSize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(keySize + ivSize);
+            KeyParameter key = ParameterUtilities.CreateKeyParameter(algorithm, dKey, 0, keySize);
+
+            return new ParametersWithIV(key, dKey, keySize, ivSize);
+        }
+
+        /**
+        * Generate a key parameter for use with a MAC derived from the password,
+        * salt, and iteration count we are currently initialised with.
+        *
+        * @param keySize the size of the key we want (in bits)
+        * @return a KeyParameter object.
+        */
+        public override ICipherParameters GenerateDerivedMacParameters(
+            int keySize)
+        {
+            keySize /= 8;
+
+            byte[] dKey = GenerateDerivedKey(keySize);
+
+            return new KeyParameter(dKey, 0, keySize);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/Poly1305KeyGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/Poly1305KeyGenerator.cs
new file mode 100644
index 0000000..5deb50f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/Poly1305KeyGenerator.cs
@@ -0,0 +1,123 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/// <summary>
+	/// Generates keys for the Poly1305 MAC.
+	/// </summary>
+	/// <remarks>
+	/// Poly1305 keys are 256 bit keys consisting of a 128 bit secret key used for the underlying block
+	/// cipher followed by a 128 bit {@code r} value used for the polynomial portion of the Mac. <br/>
+	/// The {@code r} value has a specific format with some bits required to be cleared, resulting in an
+	/// effective 106 bit key. <br/>
+	/// A separately generated 256 bit key can be modified to fit the Poly1305 key format by using the
+	/// {@link #clamp(byte[])} method to clear the required bits.
+	/// </remarks>
+	/// <seealso cref="Poly1305"/>
+	public class Poly1305KeyGenerator
+		: CipherKeyGenerator
+	{
+		private const byte R_MASK_LOW_2 = (byte)0xFC;
+		private const byte R_MASK_HIGH_4 = (byte)0x0F;
+
+		/// <summary>
+		/// Initialises the key generator.
+		/// </summary>
+		/// <remarks>
+		/// Poly1305 keys are always 256 bits, so the key length in the provided parameters is ignored.
+		/// </remarks>
+		protected override void engineInit(KeyGenerationParameters param)
+		{
+			// Poly1305 keys are always 256 bits
+			this.random = param.Random;
+			this.strength = 32;
+		}
+
+		/// <summary>
+		/// Generates a 256 bit key in the format required for Poly1305 - e.g.
+		/// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+		/// as per <see cref="Clamp(byte[])"/>.
+		/// </summary>
+		protected override byte[] engineGenerateKey()
+		{
+			byte[] key = base.engineGenerateKey();
+			Clamp(key);
+			return key;
+		}
+
+		/// <summary>
+		/// Modifies an existing 32 byte key value to comply with the requirements of the Poly1305 key by
+		/// clearing required bits in the <code>r</code> (second 16 bytes) portion of the key.<br/>
+		/// Specifically:
+		/// <ul>
+		/// <li>r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})</li>
+		/// <li>r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252})</li>
+		/// </ul>
+		/// </summary>
+		/// <param name="key">a 32 byte key value <code>k[0] ... k[15], r[0] ... r[15]</code></param>
+		public static void Clamp(byte[] key)
+		{
+			/*
+	         * Key is k[0] ... k[15], r[0] ... r[15] as per poly1305_aes_clamp in ref impl.
+	         */
+			if (key.Length != 32)
+			{
+				throw new ArgumentException("Poly1305 key must be 256 bits.");
+			}
+
+			/*
+	         * r[3], r[7], r[11], r[15] have top four bits clear (i.e., are {0, 1, . . . , 15})
+	         */
+			key[19] &= R_MASK_HIGH_4;
+			key[23] &= R_MASK_HIGH_4;
+			key[27] &= R_MASK_HIGH_4;
+			key[31] &= R_MASK_HIGH_4;
+
+			/*
+	         * r[4], r[8], r[12] have bottom two bits clear (i.e., are in {0, 4, 8, . . . , 252}).
+	         */
+			key[20] &= R_MASK_LOW_2;
+			key[24] &= R_MASK_LOW_2;
+			key[28] &= R_MASK_LOW_2;
+		}
+
+		/// <summary>
+		/// Checks a 32 byte key for compliance with the Poly1305 key requirements, e.g.
+		/// <code>k[0] ... k[15], r[0] ... r[15]</code> with the required bits in <code>r</code> cleared
+		/// as per <see cref="Clamp(byte[])"/>.
+		/// </summary>
+		/// <param name="key">Key.</param>
+		/// <exception cref="System.ArgumentException">if the key is of the wrong length, or has invalid bits set
+		///           in the <code>r</code> portion of the key.</exception>
+		public static void CheckKey(byte[] key)
+		{
+			if (key.Length != 32)
+			{
+				throw new ArgumentException("Poly1305 key must be 256 bits.");
+			}
+
+			checkMask(key[19], R_MASK_HIGH_4);
+			checkMask(key[23], R_MASK_HIGH_4);
+			checkMask(key[27], R_MASK_HIGH_4);
+			checkMask(key[31], R_MASK_HIGH_4);
+
+			checkMask(key[20], R_MASK_LOW_2);
+			checkMask(key[24], R_MASK_LOW_2);
+			checkMask(key[28], R_MASK_LOW_2);
+		}
+
+		private static void checkMask(byte b, byte mask)
+		{
+			if ((b & (~mask)) != 0)
+			{
+				throw new ArgumentException("Invalid format for r portion of Poly1305 key.");
+			}
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/RSABlindingFactorGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/RSABlindingFactorGenerator.cs
new file mode 100644
index 0000000..e2f63fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/RSABlindingFactorGenerator.cs
@@ -0,0 +1,69 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	/**
+	* Generate a random factor suitable for use with RSA blind signatures
+	* as outlined in Chaum's blinding and unblinding as outlined in
+	* "Handbook of Applied Cryptography", page 475.
+	*/
+	public class RsaBlindingFactorGenerator
+	{
+		private RsaKeyParameters key;
+		private SecureRandom random;
+
+		/**
+		* Initialise the factor generator
+		*
+		* @param param the necessary RSA key parameters.
+		*/
+		public void Init(
+			ICipherParameters param)
+		{
+			if (param is ParametersWithRandom)
+			{
+				ParametersWithRandom rParam = (ParametersWithRandom)param;
+
+				key = (RsaKeyParameters)rParam.Parameters;
+				random = rParam.Random;
+			}
+			else
+			{
+				key = (RsaKeyParameters)param;
+				random = new SecureRandom();
+			}
+
+			if (key.IsPrivate)
+				throw new ArgumentException("generator requires RSA public key");
+		}
+
+		/**
+		* Generate a suitable blind factor for the public key the generator was initialised with.
+		*
+		* @return a random blind factor
+		*/
+		public BigInteger GenerateBlindingFactor()
+		{
+			if (key == null)
+				throw new InvalidOperationException("generator not initialised");
+
+			BigInteger m = key.Modulus;
+			int length = m.BitLength - 1; // must be less than m.BitLength
+			BigInteger factor;
+			BigInteger gcd;
+
+			do
+			{
+				factor = new BigInteger(length, random);
+				gcd = factor.Gcd(m);
+			}
+			while (factor.SignValue == 0 || factor.Equals(BigInteger.One) || !gcd.Equals(BigInteger.One));
+
+			return factor;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/RsaKeyPairGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/generators/RsaKeyPairGenerator.cs
new file mode 100644
index 0000000..e870f1c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/RsaKeyPairGenerator.cs
@@ -0,0 +1,150 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC.Multiplier;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+    /**
+     * an RSA key pair generator.
+     */
+    public class RsaKeyPairGenerator
+        : IAsymmetricCipherKeyPairGenerator
+    {
+        private static readonly BigInteger DefaultPublicExponent = BigInteger.ValueOf(0x10001);
+        private const int DefaultTests = 12;
+
+        private RsaKeyGenerationParameters param;
+
+        public void Init(
+            KeyGenerationParameters parameters)
+        {
+            if (parameters is RsaKeyGenerationParameters)
+            {
+                this.param = (RsaKeyGenerationParameters)parameters;
+            }
+            else
+            {
+                this.param = new RsaKeyGenerationParameters(
+                    DefaultPublicExponent, parameters.Random, parameters.Strength, DefaultTests);
+            }
+        }
+
+        public AsymmetricCipherKeyPair GenerateKeyPair()
+        {
+            BigInteger p, q, n, d, e, pSub1, qSub1, phi;
+
+            //
+            // p and q values should have a length of half the strength in bits
+            //
+            int strength = param.Strength;
+            int qBitlength = strength >> 1;
+            int pBitlength = strength - qBitlength;
+            int mindiffbits = strength / 3;
+            int minWeight = strength >> 2;
+
+            e = param.PublicExponent;
+
+            // TODO Consider generating safe primes for p, q (see DHParametersHelper.GenerateSafePrimes)
+            // (then p-1 and q-1 will not consist of only small factors - see "Pollard's algorithm")
+
+            p = ChooseRandomPrime(pBitlength, e);
+
+            //
+            // Generate a modulus of the required length
+            //
+            for (;;)
+            {
+                q = ChooseRandomPrime(qBitlength, e);
+
+                // p and q should not be too close together (or equal!)
+                BigInteger diff = q.Subtract(p).Abs();
+                if (diff.BitLength < mindiffbits)
+                    continue;
+
+                //
+                // calculate the modulus
+                //
+                n = p.Multiply(q);
+
+                if (n.BitLength != strength)
+                {
+                    //
+                    // if we get here our primes aren't big enough, make the largest
+                    // of the two p and try again
+                    //
+                    p = p.Max(q);
+                    continue;
+                }
+
+                /*
+                 * Require a minimum weight of the NAF representation, since low-weight composites may
+                 * be weak against a version of the number-field-sieve for factoring.
+                 * 
+                 * See "The number field sieve for integers of low weight", Oliver Schirokauer.
+                 */
+                if (WNafUtilities.GetNafWeight(n) < minWeight)
+                {
+                    p = ChooseRandomPrime(pBitlength, e);
+                    continue;
+                }
+
+                break;
+            }
+
+            if (p.CompareTo(q) < 0)
+            {
+                phi = p;
+                p = q;
+                q = phi;
+            }
+
+            pSub1 = p.Subtract(BigInteger.One);
+            qSub1 = q.Subtract(BigInteger.One);
+            phi = pSub1.Multiply(qSub1);
+
+            //
+            // calculate the private exponent
+            //
+            d = e.ModInverse(phi);
+
+            //
+            // calculate the CRT factors
+            //
+            BigInteger dP, dQ, qInv;
+
+            dP = d.Remainder(pSub1);
+            dQ = d.Remainder(qSub1);
+            qInv = q.ModInverse(p);
+
+            return new AsymmetricCipherKeyPair(
+                new RsaKeyParameters(false, n, e),
+                new RsaPrivateCrtKeyParameters(n, e, d, p, q, dP, dQ, qInv));
+        }
+
+        /// <summary>Choose a random prime value for use with RSA</summary>
+        /// <param name="bitlength">the bit-length of the returned prime</param>
+        /// <param name="e">the RSA public exponent</param>
+        /// <returns>a prime p, with (p-1) relatively prime to e</returns>
+        protected virtual BigInteger ChooseRandomPrime(int bitlength, BigInteger e)
+        {
+            for (;;)
+            {
+                BigInteger p = new BigInteger(bitlength, 1, param.Random);
+
+                if (p.Mod(e).Equals(BigInteger.One))
+                    continue;
+
+                if (!p.IsProbablePrime(param.Certainty))
+                    continue;
+
+                if (!e.Gcd(p.Subtract(BigInteger.One)).Equals(BigInteger.One))
+                    continue;
+
+                return p;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/generators/SCrypt.cs b/BouncyCastle.AxCrypt/src/crypto/generators/SCrypt.cs
new file mode 100644
index 0000000..efa74d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/generators/SCrypt.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Threading;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Generators
+{
+	public class SCrypt
+	{
+		// TODO Validate arguments
+		public static byte[] Generate(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+		{
+			return MFcrypt(P, S, N, r, p, dkLen);
+		}
+
+		private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen)
+		{
+			int MFLenBytes = r * 128;
+			byte[] bytes = SingleIterationPBKDF2(P, S, p * MFLenBytes);
+
+			uint[] B = null;
+
+			try
+			{
+				int BLen = bytes.Length >> 2;
+				B = new uint[BLen];
+
+				Pack.LE_To_UInt32(bytes, 0, B);
+
+				int MFLenWords = MFLenBytes >> 2;
+				for (int BOff = 0; BOff < BLen; BOff += MFLenWords)
+				{
+					// TODO These can be done in parallel threads
+					SMix(B, BOff, N, r);
+				}
+
+				Pack.UInt32_To_LE(B, bytes, 0);
+
+				return SingleIterationPBKDF2(P, bytes, dkLen);
+			}
+			finally
+			{
+				ClearAll(bytes, B);
+			}
+		}
+
+		private static byte[] SingleIterationPBKDF2(byte[] P, byte[] S, int dkLen)
+		{
+			PbeParametersGenerator pGen = new Pkcs5S2ParametersGenerator(new Sha256Digest());
+			pGen.Init(P, S, 1);
+			KeyParameter key = (KeyParameter)pGen.GenerateDerivedMacParameters(dkLen * 8);
+			return key.GetKey();
+		}
+
+		private static void SMix(uint[] B, int BOff, int N, int r)
+		{
+			int BCount = r * 32;
+
+			uint[] blockX1 = new uint[16];
+			uint[] blockX2 = new uint[16];
+			uint[] blockY = new uint[BCount];
+
+			uint[] X = new uint[BCount];
+			uint[][] V = new uint[N][];
+
+			try
+			{
+				Array.Copy(B, BOff, X, 0, BCount);
+
+				for (int i = 0; i < N; ++i)
+				{
+					V[i] = (uint[])X.Clone();
+					BlockMix(X, blockX1, blockX2, blockY, r);
+				}
+
+				uint mask = (uint)N - 1;
+				for (int i = 0; i < N; ++i)
+				{
+					uint j = X[BCount - 16] & mask;
+					Xor(X, V[j], 0, X);
+					BlockMix(X, blockX1, blockX2, blockY, r);
+				}
+
+				Array.Copy(X, 0, B, BOff, BCount);
+			}
+			finally
+			{
+				ClearAll(V);
+				ClearAll(X, blockX1, blockX2, blockY);
+			}
+		}
+
+		private static void BlockMix(uint[] B, uint[] X1, uint[] X2, uint[] Y, int r)
+		{
+			Array.Copy(B, B.Length - 16, X1, 0, 16);
+
+			int BOff = 0, YOff = 0, halfLen = B.Length >> 1;
+
+			for (int i = 2 * r; i > 0; --i)
+			{
+				Xor(X1, B, BOff, X2);
+
+				Salsa20Engine.SalsaCore(8, X2, X1);
+				Array.Copy(X1, 0, Y, YOff, 16);
+
+				YOff = halfLen + BOff - YOff;
+				BOff += 16;
+			}
+
+			Array.Copy(Y, 0, B, 0, Y.Length);
+		}
+
+		private static void Xor(uint[] a, uint[] b, int bOff, uint[] output)
+		{
+			for (int i = output.Length - 1; i >= 0; --i)
+			{
+				output[i] = a[i] ^ b[bOff + i];
+			}
+		}
+
+		private static void Clear(Array array)
+		{
+			if (array != null)
+			{
+				Array.Clear(array, 0, array.Length);
+			}
+		}
+
+		private static void ClearAll(params Array[] arrays)
+		{
+			foreach (Array array in arrays)
+			{
+				Clear(array);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/io/CipherStream.cs b/BouncyCastle.AxCrypt/src/crypto/io/CipherStream.cs
new file mode 100644
index 0000000..f2083e8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/io/CipherStream.cs
@@ -0,0 +1,238 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+    public class CipherStream
+		: Stream
+    {
+        internal Stream stream;
+        internal IBufferedCipher inCipher, outCipher;
+        private byte[] mInBuf;
+		private int mInPos;
+		private bool inStreamEnded;
+
+		public CipherStream(
+            Stream			stream,
+            IBufferedCipher	readCipher,
+            IBufferedCipher	writeCipher)
+        {
+            this.stream = stream;
+
+			if (readCipher != null)
+			{
+				this.inCipher = readCipher;
+				mInBuf = null;
+			}
+
+			if (writeCipher != null)
+			{
+				this.outCipher = writeCipher;
+			}
+		}
+
+		public IBufferedCipher ReadCipher
+		{
+			get { return inCipher; }
+		}
+
+		public IBufferedCipher WriteCipher
+		{
+			get { return outCipher; }
+		}
+
+		public override int ReadByte()
+        {
+            if (inCipher == null)
+                return stream.ReadByte();
+
+			if (mInBuf == null || mInPos >= mInBuf.Length)
+			{
+				if (!FillInBuf())
+					return -1;
+            }
+
+			return mInBuf[mInPos++];
+        }
+
+		public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+        {
+            if (inCipher == null)
+                return stream.Read(buffer, offset, count);
+
+			int num = 0;
+			while (num < count)
+			{
+				if (mInBuf == null || mInPos >= mInBuf.Length)
+				{
+					if (!FillInBuf())
+						break;
+				}
+
+				int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos);
+				Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy);
+				mInPos += numToCopy;
+				num += numToCopy;
+			}
+
+			return num;
+		}
+
+		private bool FillInBuf()
+        {
+			if (inStreamEnded)
+				return false;
+
+			mInPos = 0;
+
+			do
+			{
+				mInBuf = ReadAndProcessBlock();
+			}
+			while (!inStreamEnded && mInBuf == null);
+
+			return mInBuf != null;
+		}
+
+		private byte[] ReadAndProcessBlock()
+		{
+			int blockSize = inCipher.GetBlockSize();
+			int readSize = (blockSize == 0) ? 256 : blockSize;
+
+			byte[] block = new byte[readSize];
+			int numRead = 0;
+			do
+			{
+				int count = stream.Read(block, numRead, block.Length - numRead);
+				if (count < 1)
+				{
+					inStreamEnded = true;
+					break;
+				}
+				numRead += count;
+			}
+			while (numRead < block.Length);
+
+			Debug.Assert(inStreamEnded || numRead == block.Length);
+
+			byte[] bytes = inStreamEnded
+				?	inCipher.DoFinal(block, 0, numRead)
+				:	inCipher.ProcessBytes(block);
+
+			if (bytes != null && bytes.Length == 0)
+			{
+				bytes = null;
+			}
+
+			return bytes;
+		}
+
+		public override void Write(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+        {
+			Debug.Assert(buffer != null);
+			Debug.Assert(0 <= offset && offset <= buffer.Length);
+			Debug.Assert(count >= 0);
+
+			int end = offset + count;
+
+			Debug.Assert(0 <= end && end <= buffer.Length);
+
+			if (outCipher == null)
+            {
+                stream.Write(buffer, offset, count);
+                return;
+            }
+
+			byte[] data = outCipher.ProcessBytes(buffer, offset, count);
+			if (data != null)
+			{
+				stream.Write(data, 0, data.Length);
+			}
+		}
+
+		public override void WriteByte(
+			byte b)
+        {
+            if (outCipher == null)
+            {
+                stream.WriteByte(b);
+                return;
+            }
+
+			byte[] data = outCipher.ProcessByte(b);
+			if (data != null)
+			{
+				stream.Write(data, 0, data.Length);
+			}
+		}
+
+		public override bool CanRead
+        {
+            get { return stream.CanRead && (inCipher != null); }
+        }
+
+		public override bool CanWrite
+        {
+            get { return stream.CanWrite && (outCipher != null); }
+        }
+
+		public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+		public sealed override long Length
+		{
+			get { throw new NotSupportedException(); }
+		}
+
+		public sealed override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                if (outCipher != null)
+                {
+                    byte[] data = outCipher.DoFinal();
+                    stream.Write(data, 0, data.Length);
+                    stream.Flush();
+                }
+                stream.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+		public override void Flush()
+        {
+			// Note: outCipher.DoFinal is only called during Close()
+			stream.Flush();
+        }
+
+		public sealed override long Seek(
+			long		offset,
+			SeekOrigin	origin)
+		{
+			throw new NotSupportedException();
+		}
+
+		public sealed override void SetLength(
+			long length)
+		{
+			throw new NotSupportedException();
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/io/DigestStream.cs b/BouncyCastle.AxCrypt/src/crypto/io/DigestStream.cs
new file mode 100644
index 0000000..b0a69f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/io/DigestStream.cs
@@ -0,0 +1,141 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+	public class DigestStream
+		: Stream
+	{
+		protected readonly Stream stream;
+		protected readonly IDigest inDigest;
+		protected readonly IDigest outDigest;
+
+		public DigestStream(
+			Stream	stream,
+			IDigest	readDigest,
+			IDigest	writeDigest)
+		{
+			this.stream = stream;
+			this.inDigest = readDigest;
+			this.outDigest = writeDigest;
+		}
+
+		public virtual IDigest ReadDigest()
+		{
+			return inDigest;
+		}
+
+		public virtual IDigest WriteDigest()
+		{
+			return outDigest;
+		}
+
+		public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			int n = stream.Read(buffer, offset, count);
+			if (inDigest != null)
+			{
+				if (n > 0)
+				{
+					inDigest.BlockUpdate(buffer, offset, n);
+				}
+			}
+			return n;
+		}
+
+		public override int ReadByte()
+		{
+			int b = stream.ReadByte();
+			if (inDigest != null)
+			{
+				if (b >= 0)
+				{
+					inDigest.Update((byte)b);
+				}
+			}
+			return b;
+		}
+
+		public override void Write(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			if (outDigest != null)
+			{
+				if (count > 0)
+				{
+					outDigest.BlockUpdate(buffer, offset, count);
+				}
+			}
+			stream.Write(buffer, offset, count);
+		}
+
+		public override void WriteByte(
+			byte b)
+		{
+			if (outDigest != null)
+			{
+				outDigest.Update(b);
+			}
+			stream.WriteByte(b);
+		}
+
+		public override bool CanRead
+		{
+			get { return stream.CanRead; }
+		}
+
+		public override bool CanWrite
+		{
+			get { return stream.CanWrite; }
+		}
+
+		public override bool CanSeek
+		{
+			get { return stream.CanSeek; }
+		}
+
+		public override long Length
+		{
+			get { return stream.Length; }
+		}
+
+		public override long Position
+		{
+			get { return stream.Position; }
+			set { stream.Position = value; }
+		}
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            stream.Dispose();
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		public override  void Flush()
+		{
+			stream.Flush();
+		}
+
+		public override long Seek(
+			long		offset,
+			SeekOrigin	origin)
+		{
+			return stream.Seek(offset, origin);
+		}
+
+		public override void SetLength(
+			long length)
+		{
+			stream.SetLength(length);
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/io/MacStream.cs b/BouncyCastle.AxCrypt/src/crypto/io/MacStream.cs
new file mode 100644
index 0000000..c7feabc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/io/MacStream.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+	public class MacStream
+		: Stream
+	{
+		protected readonly Stream stream;
+		protected readonly IMac inMac;
+		protected readonly IMac outMac;
+
+		public MacStream(
+			Stream	stream,
+			IMac	readMac,
+			IMac	writeMac)
+		{
+			this.stream = stream;
+			this.inMac = readMac;
+			this.outMac = writeMac;
+		}
+
+		public virtual IMac ReadMac()
+		{
+			return inMac;
+		}
+
+		public virtual IMac WriteMac()
+		{
+			return outMac;
+		}
+
+		public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			int n = stream.Read(buffer, offset, count);
+			if (inMac != null)
+			{
+				if (n > 0)
+				{
+					inMac.BlockUpdate(buffer, offset, n);
+				}
+			}
+			return n;
+		}
+
+		public override int ReadByte()
+		{
+			int b = stream.ReadByte();
+			if (inMac != null)
+			{
+				if (b >= 0)
+				{
+					inMac.Update((byte)b);
+				}
+			}
+			return b;
+		}
+
+		public override void Write(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			if (outMac != null)
+			{
+				if (count > 0)
+				{
+					outMac.BlockUpdate(buffer, offset, count);
+				}
+			}
+			stream.Write(buffer, offset, count);
+		}
+
+		public override void WriteByte(byte b)
+		{
+			if (outMac != null)
+			{
+				outMac.Update(b);
+			}
+			stream.WriteByte(b);
+		}
+
+		public override bool CanRead
+		{
+			get { return stream.CanRead; }
+		}
+
+		public override bool CanWrite
+		{
+			get { return stream.CanWrite; }
+		}
+
+		public override bool CanSeek
+		{
+			get { return stream.CanSeek; }
+		}
+
+		public override long Length
+		{
+			get { return stream.Length; }
+		}
+
+		public override long Position
+		{
+			get { return stream.Position; }
+			set { stream.Position = value; }
+		}
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            stream.Dispose();
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		public override void Flush()
+		{
+			stream.Flush();
+		}
+
+		public override long Seek(
+			long		offset,
+			SeekOrigin	origin)
+		{
+			return stream.Seek(offset,origin);
+		}
+
+		public override void SetLength(
+			long length)
+		{
+			stream.SetLength(length);
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/io/SignerStream.cs b/BouncyCastle.AxCrypt/src/crypto/io/SignerStream.cs
new file mode 100644
index 0000000..2a609f6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/io/SignerStream.cs
@@ -0,0 +1,141 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.IO
+{
+	public class SignerStream
+		: Stream
+	{
+		protected readonly Stream stream;
+		protected readonly ISigner inSigner;
+		protected readonly ISigner outSigner;
+
+		public SignerStream(
+			Stream	stream,
+			ISigner	readSigner,
+			ISigner	writeSigner)
+		{
+			this.stream = stream;
+			this.inSigner = readSigner;
+			this.outSigner = writeSigner;
+		}
+
+		public virtual ISigner ReadSigner()
+		{
+			return inSigner;
+		}
+
+		public virtual ISigner WriteSigner()
+		{
+			return outSigner;
+		}
+
+		public override int Read(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			int n = stream.Read(buffer, offset, count);
+			if (inSigner != null)
+			{
+				if (n > 0)
+				{
+					inSigner.BlockUpdate(buffer, offset, n);
+				}
+			}
+			return n;
+		}
+
+		public override int ReadByte()
+		{
+			int b = stream.ReadByte();
+			if (inSigner != null)
+			{
+				if (b >= 0)
+				{
+					inSigner.Update((byte)b);
+				}
+			}
+			return b;
+		}
+
+		public override void Write(
+			byte[]	buffer,
+			int		offset,
+			int		count)
+		{
+			if (outSigner != null)
+			{
+				if (count > 0)
+				{
+					outSigner.BlockUpdate(buffer, offset, count);
+				}
+			}
+			stream.Write(buffer, offset, count);
+		}
+
+		public override void WriteByte(
+			byte b)
+		{
+			if (outSigner != null)
+			{
+				outSigner.Update(b);
+			}
+			stream.WriteByte(b);
+		}
+
+		public override bool CanRead
+		{
+			get { return stream.CanRead; }
+		}
+
+		public override bool CanWrite
+		{
+			get { return stream.CanWrite; }
+		}
+
+		public override bool CanSeek
+		{
+			get { return stream.CanSeek; }
+		}
+
+		public override long Length
+		{
+			get { return stream.Length; }
+		}
+
+		public override long Position
+		{
+			get { return stream.Position; }
+			set { stream.Position = value; }
+		}
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            stream.Dispose();
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		public override  void Flush()
+		{
+			stream.Flush();
+		}
+
+		public override long Seek(
+			long		offset,
+			SeekOrigin	origin)
+		{
+			return stream.Seek(offset, origin);
+		}
+
+		public override void SetLength(
+			long length)
+		{
+			stream.SetLength(length);
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/CMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/CMac.cs
new file mode 100644
index 0000000..682c12b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/CMac.cs
@@ -0,0 +1,257 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /**
+    * CMAC - as specified at www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
+    * <p>
+    * CMAC is analogous to OMAC1 - see also en.wikipedia.org/wiki/CMAC
+    * </p><p>
+    * CMAC is a NIST recomendation - see 
+    * csrc.nist.gov/CryptoToolkit/modes/800-38_Series_Publications/SP800-38B.pdf
+    * </p><p>
+    * CMAC/OMAC1 is a blockcipher-based message authentication code designed and
+    * analyzed by Tetsu Iwata and Kaoru Kurosawa.
+    * </p><p>
+    * CMAC/OMAC1 is a simple variant of the CBC MAC (Cipher Block Chaining Message 
+    * Authentication Code). OMAC stands for One-Key CBC MAC.
+    * </p><p>
+    * It supports 128- or 64-bits block ciphers, with any key size, and returns
+    * a MAC with dimension less or equal to the block size of the underlying 
+    * cipher.
+    * </p>
+    */
+    public class CMac
+        : IMac
+    {
+        private const byte CONSTANT_128 = (byte)0x87;
+        private const byte CONSTANT_64 = (byte)0x1b;
+
+        private byte[] ZEROES;
+
+        private byte[] mac;
+
+        private byte[] buf;
+        private int bufOff;
+        private IBlockCipher cipher;
+
+        private int macSize;
+
+        private byte[] L, Lu, Lu2;
+
+        /**
+        * create a standard MAC based on a CBC block cipher (64 or 128 bit block).
+        * This will produce an authentication code the length of the block size
+        * of the cipher.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        */
+        public CMac(
+            IBlockCipher cipher)
+            : this(cipher, cipher.GetBlockSize() * 8)
+        {
+        }
+
+        /**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits.
+        * <p/>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        *
+        * @param cipher        the cipher to be used as the basis of the MAC generation.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8 and @lt;= 128.
+        */
+        public CMac(
+            IBlockCipher	cipher,
+            int				macSizeInBits)
+        {
+            if ((macSizeInBits % 8) != 0)
+                throw new ArgumentException("MAC size must be multiple of 8");
+
+            if (macSizeInBits > (cipher.GetBlockSize() * 8))
+            {
+                throw new ArgumentException(
+                    "MAC size must be less or equal to "
+                        + (cipher.GetBlockSize() * 8));
+            }
+
+            if (cipher.GetBlockSize() != 8 && cipher.GetBlockSize() != 16)
+            {
+                throw new ArgumentException(
+                    "Block size must be either 64 or 128 bits");
+            }
+
+            this.cipher = new CbcBlockCipher(cipher);
+            this.macSize = macSizeInBits / 8;
+
+            mac = new byte[cipher.GetBlockSize()];
+
+            buf = new byte[cipher.GetBlockSize()];
+
+            ZEROES = new byte[cipher.GetBlockSize()];
+
+            bufOff = 0;
+        }
+
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName; }
+        }
+
+        private static int ShiftLeft(byte[] block, byte[] output)
+        {
+            int i = block.Length;
+            uint bit = 0;
+            while (--i >= 0)
+            {
+                uint b = block[i];
+                output[i] = (byte)((b << 1) | bit);
+                bit = (b >> 7) & 1;
+            }
+            return (int)bit;
+        }
+
+        private static byte[] DoubleLu(byte[] input)
+        {
+            byte[] ret = new byte[input.Length];
+            int carry = ShiftLeft(input, ret);
+            int xor = input.Length == 16 ? CONSTANT_128 : CONSTANT_64;
+
+            /*
+             * NOTE: This construction is an attempt at a constant-time implementation.
+             */
+            ret[input.Length - 1] ^= (byte)(xor >> ((1 - carry) << 3));
+
+            return ret;
+        }
+
+        public void Init(
+            ICipherParameters parameters)
+        {
+            if (parameters is KeyParameter)
+            {
+                cipher.Init(true, parameters);
+
+                //initializes the L, Lu, Lu2 numbers
+                L = new byte[ZEROES.Length];
+                cipher.ProcessBlock(ZEROES, 0, L, 0);
+                Lu = DoubleLu(L);
+                Lu2 = DoubleLu(Lu);
+            }
+            else if (parameters != null)
+            {
+                // CMAC mode does not permit IV to underlying CBC mode
+                throw new ArgumentException("CMac mode only permits key to be set.", "parameters");
+            }
+
+            Reset();
+        }
+
+        public int GetMacSize()
+        {
+            return macSize;
+        }
+
+        public void Update(
+            byte input)
+        {
+            if (bufOff == buf.Length)
+            {
+                cipher.ProcessBlock(buf, 0, mac, 0);
+                bufOff = 0;
+            }
+
+            buf[bufOff++] = input;
+        }
+
+        public void BlockUpdate(
+            byte[]	inBytes,
+            int		inOff,
+            int		len)
+        {
+            if (len < 0)
+                throw new ArgumentException("Can't have a negative input length!");
+
+            int blockSize = cipher.GetBlockSize();
+            int gapLen = blockSize - bufOff;
+
+            if (len > gapLen)
+            {
+                Array.Copy(inBytes, inOff, buf, bufOff, gapLen);
+
+                cipher.ProcessBlock(buf, 0, mac, 0);
+
+                bufOff = 0;
+                len -= gapLen;
+                inOff += gapLen;
+
+                while (len > blockSize)
+                {
+                    cipher.ProcessBlock(inBytes, inOff, mac, 0);
+
+                    len -= blockSize;
+                    inOff += blockSize;
+                }
+            }
+
+            Array.Copy(inBytes, inOff, buf, bufOff, len);
+
+            bufOff += len;
+        }
+
+        public int DoFinal(
+            byte[]	outBytes,
+            int		outOff)
+        {
+            int blockSize = cipher.GetBlockSize();
+
+            byte[] lu;
+            if (bufOff == blockSize)
+            {
+                lu = Lu;
+            }
+            else
+            {
+                new ISO7816d4Padding().AddPadding(buf, bufOff);
+                lu = Lu2;
+            }
+
+            for (int i = 0; i < mac.Length; i++)
+            {
+                buf[i] ^= lu[i];
+            }
+
+            cipher.ProcessBlock(buf, 0, mac, 0);
+
+            Array.Copy(mac, 0, outBytes, outOff, macSize);
+
+            Reset();
+
+            return macSize;
+        }
+
+        /**
+        * Reset the mac generator.
+        */
+        public void Reset()
+        {
+            /*
+            * clean the buffer.
+            */
+            Array.Clear(buf, 0, buf.Length);
+            bufOff = 0;
+
+            /*
+            * Reset the underlying cipher.
+            */
+            cipher.Reset();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/CbcBlockCipherMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/CbcBlockCipherMac.cs
new file mode 100644
index 0000000..146e16a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/CbcBlockCipherMac.cs
@@ -0,0 +1,209 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /**
+    * standard CBC Block Cipher MAC - if no padding is specified the default of
+    * pad of zeroes is used.
+    */
+    public class CbcBlockCipherMac
+		: IMac
+    {
+        private byte[] buf;
+        private int bufOff;
+        private IBlockCipher cipher;
+        private IBlockCipherPadding padding;
+		private int macSize;
+
+		/**
+        * create a standard MAC based on a CBC block cipher. This will produce an
+        * authentication code half the length of the block size of the cipher.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        */
+        public CbcBlockCipherMac(
+			IBlockCipher cipher)
+			: this(cipher, (cipher.GetBlockSize() * 8) / 2, null)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a CBC block cipher. This will produce an
+        * authentication code half the length of the block size of the cipher.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param padding the padding to be used to complete the last block.
+        */
+        public CbcBlockCipherMac(
+            IBlockCipher		cipher,
+            IBlockCipherPadding	padding)
+        : this(cipher, (cipher.GetBlockSize() * 8) / 2, padding)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits. This class uses CBC mode as the basis for the
+        * MAC generation.
+        * <p>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        * </p>
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        */
+        public CbcBlockCipherMac(
+            IBlockCipher	cipher,
+            int				macSizeInBits)
+			: this(cipher, macSizeInBits, null)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits. This class uses CBC mode as the basis for the
+        * MAC generation.
+        * <p>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        * </p>
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        * @param padding the padding to be used to complete the last block.
+        */
+        public CbcBlockCipherMac(
+            IBlockCipher		cipher,
+            int					macSizeInBits,
+            IBlockCipherPadding	padding)
+        {
+            if ((macSizeInBits % 8) != 0)
+                throw new ArgumentException("MAC size must be multiple of 8");
+
+			this.cipher = new CbcBlockCipher(cipher);
+            this.padding = padding;
+            this.macSize = macSizeInBits / 8;
+
+			buf = new byte[cipher.GetBlockSize()];
+            bufOff = 0;
+        }
+
+		public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName; }
+        }
+
+		public void Init(
+            ICipherParameters parameters)
+        {
+            Reset();
+
+			cipher.Init(true, parameters);
+        }
+
+		public int GetMacSize()
+        {
+            return macSize;
+        }
+
+		public void Update(
+            byte input)
+        {
+			if (bufOff == buf.Length)
+            {
+				cipher.ProcessBlock(buf, 0, buf, 0);
+                bufOff = 0;
+            }
+
+			buf[bufOff++] = input;
+        }
+
+        public void BlockUpdate(
+            byte[]	input,
+            int		inOff,
+            int		len)
+        {
+            if (len < 0)
+                throw new ArgumentException("Can't have a negative input length!");
+
+			int blockSize = cipher.GetBlockSize();
+            int gapLen = blockSize - bufOff;
+
+            if (len > gapLen)
+            {
+                Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+                cipher.ProcessBlock(buf, 0, buf, 0);
+
+                bufOff = 0;
+                len -= gapLen;
+                inOff += gapLen;
+
+                while (len > blockSize)
+                {
+                    cipher.ProcessBlock(input, inOff, buf, 0);
+
+                    len -= blockSize;
+                    inOff += blockSize;
+                }
+            }
+
+            Array.Copy(input, inOff, buf, bufOff, len);
+
+            bufOff += len;
+        }
+
+        public int DoFinal(
+            byte[]	output,
+            int		outOff)
+        {
+            int blockSize = cipher.GetBlockSize();
+
+            if (padding == null)
+            {
+                // pad with zeroes
+                while (bufOff < blockSize)
+                {
+                    buf[bufOff++] = 0;
+                }
+            }
+            else
+            {
+                if (bufOff == blockSize)
+                {
+                    cipher.ProcessBlock(buf, 0, buf, 0);
+                    bufOff = 0;
+                }
+
+				padding.AddPadding(buf, bufOff);
+            }
+
+			cipher.ProcessBlock(buf, 0, buf, 0);
+
+			Array.Copy(buf, 0, output, outOff, macSize);
+
+			Reset();
+
+			return macSize;
+        }
+
+		/**
+        * Reset the mac generator.
+        */
+        public void Reset()
+        {
+            // Clear the buffer.
+			Array.Clear(buf, 0, buf.Length);
+			bufOff = 0;
+
+			// Reset the underlying cipher.
+            cipher.Reset();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/CfbBlockCipherMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/CfbBlockCipherMac.cs
new file mode 100644
index 0000000..364cf84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/CfbBlockCipherMac.cs
@@ -0,0 +1,368 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /**
+    * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+    */
+    class MacCFBBlockCipher
+		: IBlockCipher
+    {
+        private byte[] IV;
+        private byte[] cfbV;
+        private byte[] cfbOutV;
+
+		private readonly int blockSize;
+        private readonly IBlockCipher cipher;
+
+		/**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used as the basis of the
+        * feedback mode.
+        * @param blockSize the block size in bits (note: a multiple of 8)
+        */
+        public MacCFBBlockCipher(
+            IBlockCipher	cipher,
+            int				bitBlockSize)
+        {
+            this.cipher = cipher;
+            this.blockSize = bitBlockSize / 8;
+
+            this.IV = new byte[cipher.GetBlockSize()];
+            this.cfbV = new byte[cipher.GetBlockSize()];
+            this.cfbOutV = new byte[cipher.GetBlockSize()];
+        }
+
+		/**
+        * Initialise the cipher and, possibly, the initialisation vector (IV).
+        * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+        * An IV which is too short is handled in FIPS compliant fashion.
+        *
+        * @param param the key and other data required by the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+		public void Init(
+			bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+			if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV)parameters;
+                byte[] iv = ivParam.GetIV();
+
+                if (iv.Length < IV.Length)
+                {
+                    Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length);
+                }
+                else
+                {
+                    Array.Copy(iv, 0, IV, 0, IV.Length);
+                }
+
+				parameters = ivParam.Parameters;
+            }
+
+			Reset();
+
+			cipher.Init(true, parameters);
+        }
+
+        /**
+        * return the algorithm name and mode.
+        *
+        * @return the name of the underlying algorithm followed by "/CFB"
+        * and the block size in bits.
+        */
+        public string AlgorithmName
+        {
+			get { return cipher.AlgorithmName + "/CFB" + (blockSize * 8); }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		/**
+        * return the block size we are operating at.
+        *
+        * @return the block size we are operating at (in bytes).
+        */
+        public int GetBlockSize()
+        {
+            return blockSize;
+        }
+
+		/**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+                throw new DataLengthException("input buffer too short");
+
+			if ((outOff + blockSize) > outBytes.Length)
+                throw new DataLengthException("output buffer too short");
+
+			cipher.ProcessBlock(cfbV, 0, cfbOutV, 0);
+
+            //
+            // XOR the cfbV with the plaintext producing the cipher text
+            //
+            for (int i = 0; i < blockSize; i++)
+            {
+                outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]);
+            }
+
+			//
+            // change over the input block.
+            //
+            Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize);
+            Array.Copy(outBytes, outOff, cfbV, cfbV.Length - blockSize, blockSize);
+
+			return blockSize;
+        }
+
+		/**
+        * reset the chaining vector back to the IV and reset the underlying
+        * cipher.
+        */
+        public void Reset()
+        {
+			IV.CopyTo(cfbV, 0);
+
+			cipher.Reset();
+        }
+
+		public void GetMacBlock(
+            byte[] mac)
+        {
+            cipher.ProcessBlock(cfbV, 0, mac, 0);
+        }
+    }
+
+	public class CfbBlockCipherMac
+		: IMac
+    {
+        private byte[] mac;
+        private byte[] Buffer;
+        private int bufOff;
+        private MacCFBBlockCipher cipher;
+        private IBlockCipherPadding padding;
+        private int macSize;
+
+		/**
+        * create a standard MAC based on a CFB block cipher. This will produce an
+        * authentication code half the length of the block size of the cipher, with
+        * the CFB mode set to 8 bits.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        */
+        public CfbBlockCipherMac(
+            IBlockCipher cipher)
+			: this(cipher, 8, (cipher.GetBlockSize() * 8) / 2, null)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a CFB block cipher. This will produce an
+        * authentication code half the length of the block size of the cipher, with
+        * the CFB mode set to 8 bits.
+        *
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param padding the padding to be used.
+        */
+        public CfbBlockCipherMac(
+            IBlockCipher		cipher,
+            IBlockCipherPadding	padding)
+			: this(cipher, 8, (cipher.GetBlockSize() * 8) / 2, padding)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits. This class uses CFB mode as the basis for the
+        * MAC generation.
+        * <p>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        * </p>
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param cfbBitSize the size of an output block produced by the CFB mode.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        */
+        public CfbBlockCipherMac(
+            IBlockCipher	cipher,
+            int				cfbBitSize,
+            int				macSizeInBits)
+			: this(cipher, cfbBitSize, macSizeInBits, null)
+		{
+		}
+
+		/**
+        * create a standard MAC based on a block cipher with the size of the
+        * MAC been given in bits. This class uses CFB mode as the basis for the
+        * MAC generation.
+        * <p>
+        * Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+        * or 16 bits if being used as a data authenticator (FIPS Publication 113),
+        * and in general should be less than the size of the block cipher as it reduces
+        * the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+        * </p>
+        * @param cipher the cipher to be used as the basis of the MAC generation.
+        * @param cfbBitSize the size of an output block produced by the CFB mode.
+        * @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+        * @param padding a padding to be used.
+        */
+        public CfbBlockCipherMac(
+            IBlockCipher		cipher,
+            int					cfbBitSize,
+            int					macSizeInBits,
+            IBlockCipherPadding	padding)
+        {
+            if ((macSizeInBits % 8) != 0)
+                throw new ArgumentException("MAC size must be multiple of 8");
+
+			mac = new byte[cipher.GetBlockSize()];
+
+			this.cipher = new MacCFBBlockCipher(cipher, cfbBitSize);
+            this.padding = padding;
+            this.macSize = macSizeInBits / 8;
+
+			Buffer = new byte[this.cipher.GetBlockSize()];
+            bufOff = 0;
+        }
+
+		public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName; }
+        }
+
+		public void Init(
+            ICipherParameters parameters)
+        {
+            Reset();
+
+			cipher.Init(true, parameters);
+        }
+
+		public int GetMacSize()
+        {
+            return macSize;
+        }
+
+		public void Update(
+            byte input)
+        {
+            if (bufOff == Buffer.Length)
+            {
+				cipher.ProcessBlock(Buffer, 0, mac, 0);
+                bufOff = 0;
+            }
+
+			Buffer[bufOff++] = input;
+        }
+
+		public void BlockUpdate(
+            byte[]	input,
+            int		inOff,
+            int		len)
+        {
+            if (len < 0)
+                throw new ArgumentException("Can't have a negative input length!");
+
+			int blockSize = cipher.GetBlockSize();
+            int resultLen = 0;
+            int gapLen = blockSize - bufOff;
+
+			if (len > gapLen)
+            {
+                Array.Copy(input, inOff, Buffer, bufOff, gapLen);
+
+				resultLen += cipher.ProcessBlock(Buffer, 0, mac, 0);
+
+				bufOff = 0;
+                len -= gapLen;
+                inOff += gapLen;
+
+				while (len > blockSize)
+                {
+                    resultLen += cipher.ProcessBlock(input, inOff, mac, 0);
+
+					len -= blockSize;
+                    inOff += blockSize;
+                }
+            }
+
+			Array.Copy(input, inOff, Buffer, bufOff, len);
+
+			bufOff += len;
+        }
+
+		public int DoFinal(
+            byte[]	output,
+            int		outOff)
+        {
+            int blockSize = cipher.GetBlockSize();
+
+            // pad with zeroes
+            if (this.padding == null)
+            {
+                while (bufOff < blockSize)
+                {
+                    Buffer[bufOff++] = 0;
+                }
+            }
+            else
+            {
+                padding.AddPadding(Buffer, bufOff);
+            }
+
+			cipher.ProcessBlock(Buffer, 0, mac, 0);
+
+			cipher.GetMacBlock(mac);
+
+			Array.Copy(mac, 0, output, outOff, macSize);
+
+			Reset();
+
+			return macSize;
+        }
+
+        /**
+        * Reset the mac generator.
+        */
+        public void Reset()
+        {
+            // Clear the buffer.
+			Array.Clear(Buffer, 0, Buffer.Length);
+            bufOff = 0;
+
+			// Reset the underlying cipher.
+            cipher.Reset();
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/GMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/GMac.cs
new file mode 100644
index 0000000..f2c3990
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/GMac.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /// <summary>
+    /// The GMAC specialisation of Galois/Counter mode (GCM) detailed in NIST Special Publication
+    /// 800-38D.
+    /// </summary>
+    /// <remarks>
+    /// GMac is an invocation of the GCM mode where no data is encrypted (i.e. all input data to the Mac
+    /// is processed as additional authenticated data with the underlying GCM block cipher).
+    /// </remarks>
+    public class GMac 
+        : IMac
+    {
+        private readonly GcmBlockCipher cipher;
+        private readonly int macSizeBits;
+
+        /// <summary>
+        /// Creates a GMAC based on the operation of a block cipher in GCM mode.
+        /// </summary>
+        /// <remarks>
+        /// This will produce an authentication code the length of the block size of the cipher.
+        /// </remarks>
+        /// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+        public GMac(GcmBlockCipher cipher)
+            : this(cipher, 128)
+        {
+        }
+
+        /// <summary>
+        /// Creates a GMAC based on the operation of a 128 bit block cipher in GCM mode.
+        /// </summary>
+        /// <remarks>
+        /// This will produce an authentication code the length of the block size of the cipher.
+        /// </remarks>
+        /// <param name="cipher">the cipher to be used in GCM mode to generate the MAC.</param>
+        /// <param name="macSizeBits">the mac size to generate, in bits. Must be a multiple of 8, between 32 and 128 (inclusive).
+        /// Sizes less than 96 are not recommended, but are supported for specialized applications.</param>
+        public GMac(GcmBlockCipher cipher, int macSizeBits)
+        {
+            this.cipher = cipher;
+            this.macSizeBits = macSizeBits;
+        }
+
+        /// <summary>
+        /// Initialises the GMAC - requires a <see cref="Org.BouncyCastle.Crypto.Parameters.ParametersWithIV"/> 
+        /// providing a <see cref="Org.BouncyCastle.Crypto.Parameters.KeyParameter"/> and a nonce.
+        /// </summary>
+        public void Init(ICipherParameters parameters)
+        {
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV param = (ParametersWithIV)parameters;
+
+                byte[] iv = param.GetIV();
+                KeyParameter keyParam = (KeyParameter)param.Parameters;
+
+                // GCM is always operated in encrypt mode to calculate MAC
+                cipher.Init(true, new AeadParameters(keyParam, macSizeBits, iv));
+            }
+            else
+            {
+                throw new ArgumentException("GMAC requires ParametersWithIV");
+            }
+        }
+
+        public string AlgorithmName
+        {
+            get { return cipher.GetUnderlyingCipher().AlgorithmName + "-GMAC"; }
+        }
+
+        public int GetMacSize()
+        {
+            return macSizeBits / 8;
+        }
+
+        public void Update(byte input) 
+        {
+            cipher.ProcessAadByte(input);
+        }
+
+        public void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            cipher.ProcessAadBytes(input, inOff, len);
+        }
+
+        public int DoFinal(byte[] output, int outOff)
+        {
+            try
+            {
+                return cipher.DoFinal(output, outOff);
+            }
+            catch (InvalidCipherTextException e)
+            {
+                // Impossible in encrypt mode
+                throw new InvalidOperationException(e.ToString());
+            }
+        }
+
+        public void Reset()
+        {
+            cipher.Reset();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/GOST28147Mac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/GOST28147Mac.cs
new file mode 100644
index 0000000..9a8f1b7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/GOST28147Mac.cs
@@ -0,0 +1,296 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+	/**
+	* implementation of GOST 28147-89 MAC
+	*/
+	public class Gost28147Mac : IMac
+	{
+		private const int			blockSize = 8;
+		private const int			macSize = 4;
+		private int					bufOff;
+		private byte[]				buf;
+		private byte[]				mac;
+		private bool				firstStep = true;
+		private int[]				workingKey;
+
+		//
+		// This is default S-box - E_A.
+		private byte[] S =
+		{
+			0x9,0x6,0x3,0x2,0x8,0xB,0x1,0x7,0xA,0x4,0xE,0xF,0xC,0x0,0xD,0x5,
+			0x3,0x7,0xE,0x9,0x8,0xA,0xF,0x0,0x5,0x2,0x6,0xC,0xB,0x4,0xD,0x1,
+			0xE,0x4,0x6,0x2,0xB,0x3,0xD,0x8,0xC,0xF,0x5,0xA,0x0,0x7,0x1,0x9,
+			0xE,0x7,0xA,0xC,0xD,0x1,0x3,0x9,0x0,0x2,0xB,0x4,0xF,0x8,0x5,0x6,
+			0xB,0x5,0x1,0x9,0x8,0xD,0xF,0x0,0xE,0x4,0x2,0x3,0xC,0x7,0xA,0x6,
+			0x3,0xA,0xD,0xC,0x1,0x2,0x0,0xB,0x7,0x5,0x9,0x4,0x8,0xF,0xE,0x6,
+			0x1,0xD,0x2,0x9,0x7,0xA,0x6,0x0,0x8,0xC,0x4,0x5,0xF,0x3,0xB,0xE,
+			0xB,0xA,0xF,0x5,0x0,0xC,0xE,0x8,0x6,0x2,0x3,0x9,0x1,0x7,0xD,0x4
+		};
+
+		public Gost28147Mac()
+		{
+			mac = new byte[blockSize];
+			buf = new byte[blockSize];
+			bufOff = 0;
+		}
+
+		private static int[] generateWorkingKey(
+			byte[] userKey)
+		{
+			if (userKey.Length != 32)
+				throw new ArgumentException("Key length invalid. Key needs to be 32 byte - 256 bit!!!");
+
+			int[] key = new int[8];
+			for(int i=0; i!=8; i++)
+			{
+				key[i] = bytesToint(userKey,i*4);
+			}
+
+			return key;
+		}
+
+		public void Init(
+			ICipherParameters parameters)
+		{
+			Reset();
+			buf = new byte[blockSize];
+			if (parameters is ParametersWithSBox)
+			{
+				ParametersWithSBox param = (ParametersWithSBox)parameters;
+
+				//
+				// Set the S-Box
+				//
+				param.GetSBox().CopyTo(this.S, 0);
+
+				//
+				// set key if there is one
+				//
+				if (param.Parameters != null)
+				{
+					workingKey = generateWorkingKey(((KeyParameter)param.Parameters).GetKey());
+				}
+			}
+			else if (parameters is KeyParameter)
+			{
+				workingKey = generateWorkingKey(((KeyParameter)parameters).GetKey());
+			}
+			else
+			{
+				throw new ArgumentException("invalid parameter passed to Gost28147 init - "
+					+ parameters.GetType().Name);
+			}
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Gost28147Mac"; }
+		}
+
+		public int GetMacSize()
+		{
+			return macSize;
+		}
+
+		private int gost28147_mainStep(int n1, int key)
+		{
+			int cm = (key + n1); // CM1
+
+			// S-box replacing
+
+			int om = S[  0 + ((cm >> (0 * 4)) & 0xF)] << (0 * 4);
+			om += S[ 16 + ((cm >> (1 * 4)) & 0xF)] << (1 * 4);
+			om += S[ 32 + ((cm >> (2 * 4)) & 0xF)] << (2 * 4);
+			om += S[ 48 + ((cm >> (3 * 4)) & 0xF)] << (3 * 4);
+			om += S[ 64 + ((cm >> (4 * 4)) & 0xF)] << (4 * 4);
+			om += S[ 80 + ((cm >> (5 * 4)) & 0xF)] << (5 * 4);
+			om += S[ 96 + ((cm >> (6 * 4)) & 0xF)] << (6 * 4);
+			om += S[112 + ((cm >> (7 * 4)) & 0xF)] << (7 * 4);
+
+//			return om << 11 | om >>> (32-11); // 11-leftshift
+			int omLeft = om << 11;
+			int omRight = (int)(((uint) om) >> (32 - 11)); // Note: Casts required to get unsigned bit rotation
+
+			return omLeft | omRight;
+		}
+
+		private void gost28147MacFunc(
+			int[]	workingKey,
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			int N1, N2, tmp;  //tmp -> for saving N1
+			N1 = bytesToint(input, inOff);
+			N2 = bytesToint(input, inOff + 4);
+
+			for (int k = 0; k < 2; k++)  // 1-16 steps
+			{
+				for (int j = 0; j < 8; j++)
+				{
+					tmp = N1;
+					N1 = N2 ^ gost28147_mainStep(N1, workingKey[j]); // CM2
+					N2 = tmp;
+				}
+			}
+
+			intTobytes(N1, output, outOff);
+			intTobytes(N2, output, outOff + 4);
+		}
+
+		//array of bytes to type int
+		private static int bytesToint(
+			byte[]	input,
+			int		inOff)
+		{
+			return (int)((input[inOff + 3] << 24) & 0xff000000) + ((input[inOff + 2] << 16) & 0xff0000)
+				+ ((input[inOff + 1] << 8) & 0xff00) + (input[inOff] & 0xff);
+		}
+
+		//int to array of bytes
+		private static void intTobytes(
+			int		num,
+			byte[]	output,
+			int		outOff)
+		{
+			output[outOff + 3] = (byte)(num >> 24);
+			output[outOff + 2] = (byte)(num >> 16);
+			output[outOff + 1] = (byte)(num >> 8);
+			output[outOff] =     (byte)num;
+		}
+
+		private static byte[] CM5func(
+			byte[]	buf,
+			int		bufOff,
+			byte[]	mac)
+		{
+			byte[] sum = new byte[buf.Length - bufOff];
+
+			Array.Copy(buf, bufOff, sum, 0, mac.Length);
+
+			for (int i = 0; i != mac.Length; i++)
+			{
+				sum[i] = (byte)(sum[i] ^ mac[i]);
+			}
+
+			return sum;
+		}
+
+		public void Update(
+			byte input)
+		{
+			if (bufOff == buf.Length)
+			{
+				byte[] sumbuf = new byte[buf.Length];
+				Array.Copy(buf, 0, sumbuf, 0, mac.Length);
+
+				if (firstStep)
+				{
+					firstStep = false;
+				}
+				else
+				{
+					sumbuf = CM5func(buf, 0, mac);
+				}
+
+				gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+				bufOff = 0;
+			}
+
+			buf[bufOff++] = input;
+		}
+
+		public void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		len)
+		{
+			if (len < 0)
+				throw new ArgumentException("Can't have a negative input length!");
+
+			int gapLen = blockSize - bufOff;
+
+			if (len > gapLen)
+			{
+				Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+				byte[] sumbuf = new byte[buf.Length];
+				Array.Copy(buf, 0, sumbuf, 0, mac.Length);
+
+				if (firstStep)
+				{
+					firstStep = false;
+				}
+				else
+				{
+					sumbuf = CM5func(buf, 0, mac);
+				}
+
+				gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+				bufOff = 0;
+				len -= gapLen;
+				inOff += gapLen;
+
+				while (len > blockSize)
+				{
+					sumbuf = CM5func(input, inOff, mac);
+					gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+					len -= blockSize;
+					inOff += blockSize;
+				}
+			}
+
+			Array.Copy(input, inOff, buf, bufOff, len);
+
+			bufOff += len;
+		}
+
+		public int DoFinal(
+			byte[]	output,
+			int		outOff)
+		{
+			//padding with zero
+			while (bufOff < blockSize)
+			{
+				buf[bufOff++] = 0;
+			}
+
+			byte[] sumbuf = new byte[buf.Length];
+			Array.Copy(buf, 0, sumbuf, 0, mac.Length);
+
+			if (firstStep)
+			{
+				firstStep = false;
+			}
+			else
+			{
+				sumbuf = CM5func(buf, 0, mac);
+			}
+
+			gost28147MacFunc(workingKey, sumbuf, 0, mac, 0);
+
+			Array.Copy(mac, (mac.Length/2)-macSize, output, outOff, macSize);
+
+			Reset();
+
+			return macSize;
+		}
+
+		public void Reset()
+		{
+			// Clear the buffer.
+			Array.Clear(buf, 0, buf.Length);
+			bufOff = 0;
+
+			firstStep = true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/HMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/HMac.cs
new file mode 100644
index 0000000..460f3c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/HMac.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /**
+    * HMAC implementation based on RFC2104
+    *
+    * H(K XOR opad, H(K XOR ipad, text))
+    */
+    public class HMac
+		: IMac
+    {
+        private const byte IPAD = (byte)0x36;
+        private const byte OPAD = (byte)0x5C;
+
+        private readonly IDigest digest;
+        private readonly int digestSize;
+        private readonly int blockLength;
+		private IMemoable ipadState;
+		private IMemoable opadState;
+
+		private readonly byte[] inputPad;
+        private readonly byte[] outputBuf;
+
+        public HMac(IDigest digest)
+        {
+            this.digest = digest;
+            this.digestSize = digest.GetDigestSize();
+            this.blockLength = digest.GetByteLength();
+            this.inputPad = new byte[blockLength];
+            this.outputBuf = new byte[blockLength + digestSize];
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return digest.AlgorithmName + "/HMAC"; }
+        }
+
+		public virtual IDigest GetUnderlyingDigest()
+        {
+            return digest;
+        }
+
+        public virtual void Init(ICipherParameters parameters)
+        {
+            digest.Reset();
+
+            byte[] key = ((KeyParameter)parameters).GetKey();
+			int keyLength = key.Length;
+
+            if (keyLength > blockLength)
+            {
+                digest.BlockUpdate(key, 0, keyLength);
+                digest.DoFinal(inputPad, 0);
+
+				keyLength = digestSize;
+            }
+            else
+            {
+				Array.Copy(key, 0, inputPad, 0, keyLength);
+            }
+
+			Array.Clear(inputPad, keyLength, blockLength - keyLength);
+            Array.Copy(inputPad, 0, outputBuf, 0, blockLength);
+
+			XorPad(inputPad, blockLength, IPAD);
+            XorPad(outputBuf, blockLength, OPAD);
+
+			if (digest is IMemoable)
+			{
+				opadState = ((IMemoable)digest).Copy();
+
+				((IDigest)opadState).BlockUpdate(outputBuf, 0, blockLength);
+			}
+
+			digest.BlockUpdate(inputPad, 0, inputPad.Length);
+
+			if (digest is IMemoable)
+			{
+				ipadState = ((IMemoable)digest).Copy();
+			}
+        }
+
+        public virtual int GetMacSize()
+        {
+            return digestSize;
+        }
+
+        public virtual void Update(byte input)
+        {
+            digest.Update(input);
+        }
+
+        public virtual void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            digest.BlockUpdate(input, inOff, len);
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            digest.DoFinal(outputBuf, blockLength);
+
+			if (opadState != null)
+			{
+				((IMemoable)digest).Reset(opadState);
+				digest.BlockUpdate(outputBuf, blockLength, digest.GetDigestSize());
+			}
+			else
+			{
+				digest.BlockUpdate(outputBuf, 0, outputBuf.Length);
+			}
+
+			int len = digest.DoFinal(output, outOff);
+
+			Array.Clear(outputBuf, blockLength, digestSize);
+
+			if (ipadState != null)
+			{
+				((IMemoable)digest).Reset(ipadState);
+			}
+			else
+			{
+				digest.BlockUpdate(inputPad, 0, inputPad.Length);
+			}
+
+            return len;
+        }
+
+        /**
+        * Reset the mac generator.
+        */
+        public virtual void Reset()
+        {
+			// Reset underlying digest
+            digest.Reset();
+
+			// Initialise the digest
+            digest.BlockUpdate(inputPad, 0, inputPad.Length);
+        }
+
+        private static void XorPad(byte[] pad, int len, byte n)
+		{
+			for (int i = 0; i < len; ++i)
+            {
+                pad[i] ^= n;
+            }
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/ISO9797Alg3Mac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/ISO9797Alg3Mac.cs
new file mode 100644
index 0000000..6fee619
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/ISO9797Alg3Mac.cs
@@ -0,0 +1,275 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+	/**
+	* DES based CBC Block Cipher MAC according to ISO9797, algorithm 3 (ANSI X9.19 Retail MAC)
+	*
+	* This could as well be derived from CBCBlockCipherMac, but then the property mac in the base
+	* class must be changed to protected
+	*/
+	public class ISO9797Alg3Mac : IMac
+	{
+		private byte[] mac;
+		private byte[] buf;
+		private int bufOff;
+		private IBlockCipher cipher;
+		private IBlockCipherPadding padding;
+		private int macSize;
+		private KeyParameter lastKey2;
+		private KeyParameter lastKey3;
+
+		/**
+		* create a Retail-MAC based on a CBC block cipher. This will produce an
+		* authentication code of the length of the block size of the cipher.
+		*
+		* @param cipher the cipher to be used as the basis of the MAC generation. This must
+		* be DESEngine.
+		*/
+		public ISO9797Alg3Mac(
+			IBlockCipher cipher)
+			: this(cipher, cipher.GetBlockSize() * 8, null)
+		{
+		}
+
+		/**
+		* create a Retail-MAC based on a CBC block cipher. This will produce an
+		* authentication code of the length of the block size of the cipher.
+		*
+		* @param cipher the cipher to be used as the basis of the MAC generation.
+		* @param padding the padding to be used to complete the last block.
+		*/
+		public ISO9797Alg3Mac(
+			IBlockCipher		cipher,
+			IBlockCipherPadding	padding)
+			: this(cipher, cipher.GetBlockSize() * 8, padding)
+		{
+		}
+
+		/**
+		* create a Retail-MAC based on a block cipher with the size of the
+		* MAC been given in bits. This class uses single DES CBC mode as the basis for the
+		* MAC generation.
+		* <p>
+		* Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+		* or 16 bits if being used as a data authenticator (FIPS Publication 113),
+		* and in general should be less than the size of the block cipher as it reduces
+		* the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+		* </p>
+		* @param cipher the cipher to be used as the basis of the MAC generation.
+		* @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+		*/
+		public ISO9797Alg3Mac(
+			IBlockCipher	cipher,
+			int				macSizeInBits)
+			: this(cipher, macSizeInBits, null)
+		{
+		}
+
+		/**
+		* create a standard MAC based on a block cipher with the size of the
+		* MAC been given in bits. This class uses single DES CBC mode as the basis for the
+		* MAC generation. The final block is decrypted and then encrypted using the
+		* middle and right part of the key.
+		* <p>
+		* Note: the size of the MAC must be at least 24 bits (FIPS Publication 81),
+		* or 16 bits if being used as a data authenticator (FIPS Publication 113),
+		* and in general should be less than the size of the block cipher as it reduces
+		* the chance of an exhaustive attack (see Handbook of Applied Cryptography).
+		* </p>
+		* @param cipher the cipher to be used as the basis of the MAC generation.
+		* @param macSizeInBits the size of the MAC in bits, must be a multiple of 8.
+		* @param padding the padding to be used to complete the last block.
+		*/
+		public ISO9797Alg3Mac(
+			IBlockCipher		cipher,
+			int					macSizeInBits,
+			IBlockCipherPadding	padding)
+		{
+			if ((macSizeInBits % 8) != 0)
+				throw new ArgumentException("MAC size must be multiple of 8");
+
+			if (!(cipher is DesEngine))
+				throw new ArgumentException("cipher must be instance of DesEngine");
+
+			this.cipher = new CbcBlockCipher(cipher);
+			this.padding = padding;
+			this.macSize = macSizeInBits / 8;
+
+			mac = new byte[cipher.GetBlockSize()];
+			buf = new byte[cipher.GetBlockSize()];
+			bufOff = 0;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "ISO9797Alg3"; }
+		}
+
+		public void Init(
+			ICipherParameters parameters)
+		{
+			Reset();
+
+			if (!(parameters is KeyParameter || parameters is ParametersWithIV))
+				throw new ArgumentException("parameters must be an instance of KeyParameter or ParametersWithIV");
+
+			// KeyParameter must contain a double or triple length DES key,
+			// however the underlying cipher is a single DES. The middle and
+			// right key are used only in the final step.
+
+			KeyParameter kp;
+			if (parameters is KeyParameter)
+			{
+				kp = (KeyParameter)parameters;
+			}
+			else
+			{
+				kp = (KeyParameter)((ParametersWithIV)parameters).Parameters;
+			}
+
+			KeyParameter key1;
+			byte[] keyvalue = kp.GetKey();
+
+			if (keyvalue.Length == 16)
+			{ // Double length DES key
+				key1 = new KeyParameter(keyvalue, 0, 8);
+				this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+				this.lastKey3 = key1;
+			}
+			else if (keyvalue.Length == 24)
+			{ // Triple length DES key
+				key1 = new KeyParameter(keyvalue, 0, 8);
+				this.lastKey2 = new KeyParameter(keyvalue, 8, 8);
+				this.lastKey3 = new KeyParameter(keyvalue, 16, 8);
+			}
+			else
+			{
+				throw new ArgumentException("Key must be either 112 or 168 bit long");
+			}
+
+			if (parameters is ParametersWithIV)
+			{
+				cipher.Init(true, new ParametersWithIV(key1, ((ParametersWithIV)parameters).GetIV()));
+			}
+			else
+			{
+				cipher.Init(true, key1);
+			}
+		}
+
+		public int GetMacSize()
+		{
+			return macSize;
+		}
+
+		public void Update(
+			byte input)
+		{
+			if (bufOff == buf.Length)
+			{
+				cipher.ProcessBlock(buf, 0, mac, 0);
+				bufOff = 0;
+			}
+
+			buf[bufOff++] = input;
+		}
+
+		public void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		len)
+		{
+			if (len < 0)
+				throw new ArgumentException("Can't have a negative input length!");
+
+			int blockSize = cipher.GetBlockSize();
+			int resultLen = 0;
+			int gapLen = blockSize - bufOff;
+
+			if (len > gapLen)
+			{
+				Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+				resultLen += cipher.ProcessBlock(buf, 0, mac, 0);
+
+				bufOff = 0;
+				len -= gapLen;
+				inOff += gapLen;
+
+				while (len > blockSize)
+				{
+					resultLen += cipher.ProcessBlock(input, inOff, mac, 0);
+
+					len -= blockSize;
+					inOff += blockSize;
+				}
+			}
+
+			Array.Copy(input, inOff, buf, bufOff, len);
+
+			bufOff += len;
+		}
+
+		public int DoFinal(
+			byte[]	output,
+			int		outOff)
+		{
+			int blockSize = cipher.GetBlockSize();
+
+			if (padding == null)
+			{
+				// pad with zeroes
+				while (bufOff < blockSize)
+				{
+					buf[bufOff++] = 0;
+				}
+			}
+			else
+			{
+				if (bufOff == blockSize)
+				{
+					cipher.ProcessBlock(buf, 0, mac, 0);
+					bufOff = 0;
+				}
+
+				padding.AddPadding(buf, bufOff);
+			}
+
+			cipher.ProcessBlock(buf, 0, mac, 0);
+
+			// Added to code from base class
+			DesEngine deseng = new DesEngine();
+
+			deseng.Init(false, this.lastKey2);
+			deseng.ProcessBlock(mac, 0, mac, 0);
+
+			deseng.Init(true, this.lastKey3);
+			deseng.ProcessBlock(mac, 0, mac, 0);
+			// ****
+
+			Array.Copy(mac, 0, output, outOff, macSize);
+
+			Reset();
+
+			return macSize;
+		}
+
+		/**
+		* Reset the mac generator.
+		*/
+		public void Reset()
+		{
+			Array.Clear(buf, 0, buf.Length);
+			bufOff = 0;
+
+			// reset the underlying cipher.
+			cipher.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/Poly1305.cs b/BouncyCastle.AxCrypt/src/crypto/macs/Poly1305.cs
new file mode 100644
index 0000000..1a951ca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/Poly1305.cs
@@ -0,0 +1,291 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+
+    /// <summary>
+    /// Poly1305 message authentication code, designed by D. J. Bernstein.
+    /// </summary>
+    /// <remarks>
+    /// Poly1305 computes a 128-bit (16 bytes) authenticator, using a 128 bit nonce and a 256 bit key
+    /// consisting of a 128 bit key applied to an underlying cipher, and a 128 bit key (with 106
+    /// effective key bits) used in the authenticator.
+    /// 
+    /// The polynomial calculation in this implementation is adapted from the public domain <a
+    /// href="https://github.com/floodyberry/poly1305-donna">poly1305-donna-unrolled</a> C implementation
+    /// by Andrew M (@floodyberry).
+    /// </remarks>
+    /// <seealso cref="Org.BouncyCastle.Crypto.Generators.Poly1305KeyGenerator"/>
+    public class Poly1305
+        : IMac
+    {
+        private const int BLOCK_SIZE = 16;
+
+        private readonly IBlockCipher cipher;
+
+        private readonly byte[] singleByte = new byte[1];
+
+        // Initialised state
+
+        /** Polynomial key */
+        private uint r0, r1, r2, r3, r4;
+
+        /** Precomputed 5 * r[1..4] */
+        private uint s1, s2, s3, s4;
+
+        /** Encrypted nonce */
+        private uint k0, k1, k2, k3;
+
+        // Accumulating state
+
+        /** Current block of buffered input */
+        private byte[] currentBlock = new byte[BLOCK_SIZE];
+
+        /** Current offset in input buffer */
+        private int currentBlockOffset = 0;
+
+        /** Polynomial accumulator */
+        private uint h0, h1, h2, h3, h4;
+
+        /**
+         * Constructs a Poly1305 MAC, where the key passed to init() will be used directly.
+         */
+        public Poly1305()
+        {
+            this.cipher = null;
+        }
+
+        /**
+         * Constructs a Poly1305 MAC, using a 128 bit block cipher.
+         */
+        public Poly1305(IBlockCipher cipher)
+        {
+            if (cipher.GetBlockSize() != BLOCK_SIZE)
+            {
+                throw new ArgumentException("Poly1305 requires a 128 bit block cipher.");
+            }
+            this.cipher = cipher;
+        }
+
+        /// <summary>
+        /// Initialises the Poly1305 MAC.
+        /// </summary>
+        /// <param name="parameters">a {@link ParametersWithIV} containing a 128 bit nonce and a {@link KeyParameter} with
+        ///          a 256 bit key complying to the {@link Poly1305KeyGenerator Poly1305 key format}.</param>
+        public void Init(ICipherParameters parameters)
+        {
+            byte[] nonce = null;
+
+            if (cipher != null)
+            {
+                if (!(parameters is ParametersWithIV))
+                    throw new ArgumentException("Poly1305 requires an IV when used with a block cipher.", "parameters");
+
+                ParametersWithIV ivParams = (ParametersWithIV)parameters;
+                nonce = ivParams.GetIV();
+                parameters = ivParams.Parameters;
+            }
+
+            if (!(parameters is KeyParameter))
+                throw new ArgumentException("Poly1305 requires a key.");
+
+            KeyParameter keyParams = (KeyParameter)parameters;
+
+            SetKey(keyParams.GetKey(), nonce);
+
+            Reset();
+        }
+
+        private void SetKey(byte[] key, byte[] nonce)
+        {
+            if (cipher != null && (nonce == null || nonce.Length != BLOCK_SIZE))
+                throw new ArgumentException("Poly1305 requires a 128 bit IV.");
+
+            Poly1305KeyGenerator.CheckKey(key);
+
+            // Extract r portion of key
+            uint t0 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 0);
+            uint t1 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 4);
+            uint t2 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 8);
+            uint t3 = Pack.LE_To_UInt32(key, BLOCK_SIZE + 12);
+
+            r0 = t0 & 0x3ffffff; t0 >>= 26; t0 |= t1 << 6;
+            r1 = t0 & 0x3ffff03; t1 >>= 20; t1 |= t2 << 12;
+            r2 = t1 & 0x3ffc0ff; t2 >>= 14; t2 |= t3 << 18;
+            r3 = t2 & 0x3f03fff; t3 >>= 8;
+            r4 = t3 & 0x00fffff;
+
+            // Precompute multipliers
+            s1 = r1 * 5;
+            s2 = r2 * 5;
+            s3 = r3 * 5;
+            s4 = r4 * 5;
+
+            byte[] kBytes;
+            if (cipher == null)
+            {
+                kBytes = key;
+            }
+            else
+            {
+                // Compute encrypted nonce
+                kBytes = new byte[BLOCK_SIZE];
+                cipher.Init(true, new KeyParameter(key, 0, BLOCK_SIZE));
+                cipher.ProcessBlock(nonce, 0, kBytes, 0);
+            }
+
+            k0 = Pack.LE_To_UInt32(kBytes, 0);
+            k1 = Pack.LE_To_UInt32(kBytes, 4);
+            k2 = Pack.LE_To_UInt32(kBytes, 8);
+            k3 = Pack.LE_To_UInt32(kBytes, 12);
+        }
+
+        public string AlgorithmName
+        {
+            get { return cipher == null ? "Poly1305" : "Poly1305-" + cipher.AlgorithmName; }
+        }
+
+        public int GetMacSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public void Update(byte input)
+        {
+            singleByte[0] = input;
+            BlockUpdate(singleByte, 0, 1);
+        }
+
+        public void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            int copied = 0;
+            while (len > copied)
+            {
+                if (currentBlockOffset == BLOCK_SIZE)
+                {
+                    processBlock();
+                    currentBlockOffset = 0;
+                }
+
+                int toCopy = System.Math.Min((len - copied), BLOCK_SIZE - currentBlockOffset);
+                Array.Copy(input, copied + inOff, currentBlock, currentBlockOffset, toCopy);
+                copied += toCopy;
+                currentBlockOffset += toCopy;
+            }
+
+        }
+
+        private void processBlock()
+        {
+            if (currentBlockOffset < BLOCK_SIZE)
+            {
+                currentBlock[currentBlockOffset] = 1;
+                for (int i = currentBlockOffset + 1; i < BLOCK_SIZE; i++)
+                {
+                    currentBlock[i] = 0;
+                }
+            }
+
+            ulong t0 = Pack.LE_To_UInt32(currentBlock, 0);
+            ulong t1 = Pack.LE_To_UInt32(currentBlock, 4);
+            ulong t2 = Pack.LE_To_UInt32(currentBlock, 8);
+            ulong t3 = Pack.LE_To_UInt32(currentBlock, 12);
+
+            h0 += (uint)(t0 & 0x3ffffffU);
+            h1 += (uint)((((t1 << 32) | t0) >> 26) & 0x3ffffff);
+            h2 += (uint)((((t2 << 32) | t1) >> 20) & 0x3ffffff);
+            h3 += (uint)((((t3 << 32) | t2) >> 14) & 0x3ffffff);
+            h4 += (uint)(t3 >> 8);
+
+            if (currentBlockOffset == BLOCK_SIZE)
+            {
+                h4 += (1 << 24);
+            }
+
+            ulong tp0 = mul32x32_64(h0,r0) + mul32x32_64(h1,s4) + mul32x32_64(h2,s3) + mul32x32_64(h3,s2) + mul32x32_64(h4,s1);
+            ulong tp1 = mul32x32_64(h0,r1) + mul32x32_64(h1,r0) + mul32x32_64(h2,s4) + mul32x32_64(h3,s3) + mul32x32_64(h4,s2);
+            ulong tp2 = mul32x32_64(h0,r2) + mul32x32_64(h1,r1) + mul32x32_64(h2,r0) + mul32x32_64(h3,s4) + mul32x32_64(h4,s3);
+            ulong tp3 = mul32x32_64(h0,r3) + mul32x32_64(h1,r2) + mul32x32_64(h2,r1) + mul32x32_64(h3,r0) + mul32x32_64(h4,s4);
+            ulong tp4 = mul32x32_64(h0,r4) + mul32x32_64(h1,r3) + mul32x32_64(h2,r2) + mul32x32_64(h3,r1) + mul32x32_64(h4,r0);
+
+            ulong b;
+            h0 = (uint)tp0 & 0x3ffffff; b = (tp0 >> 26);
+            tp1 += b; h1 = (uint)tp1 & 0x3ffffff; b = (tp1 >> 26);
+            tp2 += b; h2 = (uint)tp2 & 0x3ffffff; b = (tp2 >> 26);
+            tp3 += b; h3 = (uint)tp3 & 0x3ffffff; b = (tp3 >> 26);
+            tp4 += b; h4 = (uint)tp4 & 0x3ffffff; b = (tp4 >> 26);
+            h0 += (uint)(b * 5);
+        }
+
+        public int DoFinal(byte[] output, int outOff)
+        {
+            if (outOff + BLOCK_SIZE > output.Length)
+            {
+                throw new DataLengthException("Output buffer is too short.");
+            }
+
+            if (currentBlockOffset > 0)
+            {
+                // Process padded block
+                processBlock();
+            }
+
+            ulong f0, f1, f2, f3;
+
+            uint b = h0 >> 26;
+            h0 = h0 & 0x3ffffff;
+            h1 += b; b = h1 >> 26; h1 = h1 & 0x3ffffff;
+            h2 += b; b = h2 >> 26; h2 = h2 & 0x3ffffff;
+            h3 += b; b = h3 >> 26; h3 = h3 & 0x3ffffff;
+            h4 += b; b = h4 >> 26; h4 = h4 & 0x3ffffff;
+            h0 += b * 5;
+
+            uint g0, g1, g2, g3, g4;
+            g0 = h0 + 5; b = g0 >> 26; g0 &= 0x3ffffff;
+            g1 = h1 + b; b = g1 >> 26; g1 &= 0x3ffffff;
+            g2 = h2 + b; b = g2 >> 26; g2 &= 0x3ffffff;
+            g3 = h3 + b; b = g3 >> 26; g3 &= 0x3ffffff;
+            g4 = h4 + b - (1 << 26);
+
+            b = (g4 >> 31) - 1;
+            uint nb = ~b;
+            h0 = (h0 & nb) | (g0 & b);
+            h1 = (h1 & nb) | (g1 & b);
+            h2 = (h2 & nb) | (g2 & b);
+            h3 = (h3 & nb) | (g3 & b);
+            h4 = (h4 & nb) | (g4 & b);
+
+            f0 = ((h0      ) | (h1 << 26)) + (ulong)k0;
+            f1 = ((h1 >> 6 ) | (h2 << 20)) + (ulong)k1;
+            f2 = ((h2 >> 12) | (h3 << 14)) + (ulong)k2;
+            f3 = ((h3 >> 18) | (h4 << 8 )) + (ulong)k3;
+
+            Pack.UInt32_To_LE((uint)f0, output, outOff);
+            f1 += (f0 >> 32);
+            Pack.UInt32_To_LE((uint)f1, output, outOff + 4);
+            f2 += (f1 >> 32);
+            Pack.UInt32_To_LE((uint)f2, output, outOff + 8);
+            f3 += (f2 >> 32);
+            Pack.UInt32_To_LE((uint)f3, output, outOff + 12);
+
+            Reset();
+            return BLOCK_SIZE;
+        }
+
+        public void Reset()
+        {
+            currentBlockOffset = 0;
+
+            h0 = h1 = h2 = h3 = h4 = 0;
+        }
+
+        private static ulong mul32x32_64(uint i1, uint i2)
+        {
+            return ((ulong)i1) * i2;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/SipHash.cs b/BouncyCastle.AxCrypt/src/crypto/macs/SipHash.cs
new file mode 100644
index 0000000..e1a19fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/SipHash.cs
@@ -0,0 +1,199 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+    /// <summary>
+    /// Implementation of SipHash as specified in "SipHash: a fast short-input PRF", by Jean-Philippe
+    /// Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf).
+    /// </summary>
+    /// <remarks>
+    /// "SipHash is a family of PRFs SipHash-c-d where the integer parameters c and d are the number of
+    /// compression rounds and the number of finalization rounds. A compression round is identical to a
+    /// finalization round and this round function is called SipRound. Given a 128-bit key k and a
+    /// (possibly empty) byte string m, SipHash-c-d returns a 64-bit value..."
+    /// </remarks>
+    public class SipHash
+        : IMac
+    {
+        protected readonly int c, d;
+
+        protected long k0, k1;
+        protected long v0, v1, v2, v3;
+
+        protected long m = 0;
+        protected int wordPos = 0;
+        protected int wordCount = 0;
+
+        /// <summary>SipHash-2-4</summary>
+        public SipHash()
+            : this(2, 4)
+        {
+        }
+
+        /// <summary>SipHash-c-d</summary>
+        /// <param name="c">the number of compression rounds</param>
+        /// <param name="d">the number of finalization rounds</param>
+        public SipHash(int c, int d)
+        {
+            this.c = c;
+            this.d = d;
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return "SipHash-" + c + "-" + d; }
+        }
+
+        public virtual int GetMacSize()
+        {
+            return 8;
+        }
+
+        public virtual void Init(ICipherParameters parameters)
+        {
+            KeyParameter keyParameter = parameters as KeyParameter;
+            if (keyParameter == null)
+                throw new ArgumentException("must be an instance of KeyParameter", "parameters");
+            byte[] key = keyParameter.GetKey();
+            if (key.Length != 16)
+                throw new ArgumentException("must be a 128-bit key", "parameters");
+
+            this.k0 = (long)Pack.LE_To_UInt64(key, 0);
+            this.k1 = (long)Pack.LE_To_UInt64(key, 8);
+
+            Reset();
+        }
+
+        public virtual void Update(byte input)
+        {
+            m = (long)(((ulong)m >> 8) | ((ulong)input << 56));
+
+            if (++wordPos == 8)
+            {
+                ProcessMessageWord();
+                wordPos = 0;
+            }
+        }
+
+        public virtual void BlockUpdate(byte[] input, int offset, int length)
+        {
+            int i = 0, fullWords = length & ~7;
+            if (wordPos == 0)
+            {
+                for (; i < fullWords; i += 8)
+                {
+                    m = (long)Pack.LE_To_UInt64(input, offset + i);
+                    ProcessMessageWord();
+                }
+                for (; i < length; ++i)
+                {
+                    m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
+                }
+                wordPos = length - fullWords;
+            }
+            else
+            {
+                int bits = wordPos << 3;
+                for (; i < fullWords; i += 8)
+                {
+                    ulong n = Pack.LE_To_UInt64(input, offset + i);
+                    m = (long)((n << bits) | ((ulong)m >> -bits));
+                    ProcessMessageWord();
+                    m = (long)n;
+                }
+                for (; i < length; ++i)
+                {
+                    m = (long)(((ulong)m >> 8) | ((ulong)input[offset + i] << 56));
+
+                    if (++wordPos == 8)
+                    {
+                        ProcessMessageWord();
+                        wordPos = 0;
+                    }
+                }
+            }
+        }
+
+        public virtual long DoFinal()
+        {
+            // NOTE: 2 distinct shifts to avoid "64-bit shift" when wordPos == 0
+            m = (long)((ulong)m >> ((7 - wordPos) << 3));
+            m = (long)((ulong)m >> 8);
+            m = (long)((ulong)m | ((ulong)((wordCount << 3) + wordPos) << 56));
+
+            ProcessMessageWord();
+
+            v2 ^= 0xffL;
+
+            ApplySipRounds(d);
+
+            long result = v0 ^ v1 ^ v2 ^ v3;
+
+            Reset();
+
+            return result;
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            long result = DoFinal();
+            Pack.UInt64_To_LE((ulong)result, output, outOff);
+            return 8;
+        }
+
+        public virtual void Reset()
+        {
+            v0 = k0 ^ 0x736f6d6570736575L;
+            v1 = k1 ^ 0x646f72616e646f6dL;
+            v2 = k0 ^ 0x6c7967656e657261L;
+            v3 = k1 ^ 0x7465646279746573L;
+
+            m = 0;
+            wordPos = 0;
+            wordCount = 0;
+        }
+
+        protected virtual void ProcessMessageWord()
+        {
+            ++wordCount;
+            v3 ^= m;
+            ApplySipRounds(c);
+            v0 ^= m;
+        }
+
+        protected virtual void ApplySipRounds(int n)
+        {
+            long r0 = v0, r1 = v1, r2 = v2, r3 = v3;
+
+            for (int r = 0; r < n; ++r)
+            {
+                r0 += r1;
+                r2 += r3;
+                r1 = RotateLeft(r1, 13);
+                r3 = RotateLeft(r3, 16);
+                r1 ^= r0;
+                r3 ^= r2;
+                r0 = RotateLeft(r0, 32);
+                r2 += r1;
+                r0 += r3;
+                r1 = RotateLeft(r1, 17);
+                r3 = RotateLeft(r3, 21);
+                r1 ^= r2;
+                r3 ^= r0;
+                r2 = RotateLeft(r2, 32);
+            }
+
+            v0 = r0; v1 = r1; v2 = r2; v3 = r3;
+        }
+
+        protected static long RotateLeft(long x, int n)
+        {
+            ulong ux = (ulong)x;
+            ux = (ux << n) | (ux >> -n);
+            return (long)ux;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/SkeinMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/SkeinMac.cs
new file mode 100644
index 0000000..1d61a41
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/SkeinMac.cs
@@ -0,0 +1,117 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+
+	/// <summary>
+	/// Implementation of the Skein parameterised MAC function in 256, 512 and 1024 bit block sizes,
+	/// based on the <see cref="Org.BouncyCastle.Crypto.Engines.ThreefishEngine">Threefish</see> tweakable block cipher.
+	/// </summary>
+	/// <remarks>
+	/// This is the 1.3 version of Skein defined in the Skein hash function submission to the NIST SHA-3
+	/// competition in October 2010.
+	/// <p/>
+	/// Skein was designed by Niels Ferguson - Stefan Lucks - Bruce Schneier - Doug Whiting - Mihir
+	/// Bellare - Tadayoshi Kohno - Jon Callas - Jesse Walker.
+	/// </remarks>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"/>
+	public class SkeinMac
+		: IMac
+	{
+		/// <summary>
+		/// 256 bit block size - Skein-256
+		/// </summary>
+		public const int SKEIN_256 = SkeinEngine.SKEIN_256;
+		/// <summary>
+		/// 512 bit block size - Skein-512
+		/// </summary>
+		public const int SKEIN_512 = SkeinEngine.SKEIN_512;
+		/// <summary>
+		/// 1024 bit block size - Skein-1024
+		/// </summary>
+		public const int SKEIN_1024 = SkeinEngine.SKEIN_1024;
+
+		private readonly SkeinEngine engine;
+
+		/// <summary>
+		/// Constructs a Skein MAC with an internal state size and output size.
+		/// </summary>
+		/// <param name="stateSizeBits">the internal state size in bits - one of <see cref="SKEIN_256"/> <see cref="SKEIN_512"/> or
+		///                       <see cref="SKEIN_1024"/>.</param>
+		/// <param name="digestSizeBits">the output/MAC size to produce in bits, which must be an integral number of
+		///                      bytes.</param>
+		public SkeinMac(int stateSizeBits, int digestSizeBits)
+		{
+			this.engine = new SkeinEngine(stateSizeBits, digestSizeBits);
+		}
+
+		public SkeinMac(SkeinMac mac)
+		{
+			this.engine = new SkeinEngine(mac.engine);
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Skein-MAC-" + (engine.BlockSize * 8) + "-" + (engine.OutputSize * 8); }
+		}
+
+		/// <summary>
+		/// Optionally initialises the Skein digest with the provided parameters.
+		/// </summary>
+		/// See <see cref="Org.BouncyCastle.Crypto.Parameters.SkeinParameters"></see> for details on the parameterisation of the Skein hash function.
+		/// <param name="parameters">the parameters to apply to this engine, or <code>null</code> to use no parameters.</param>
+		public void Init(ICipherParameters parameters)
+		{
+			SkeinParameters skeinParameters;
+			if (parameters is SkeinParameters)
+			{
+				skeinParameters = (SkeinParameters)parameters;
+			}
+			else if (parameters is KeyParameter)
+			{
+				skeinParameters = new SkeinParameters.Builder().SetKey(((KeyParameter)parameters).GetKey()).Build();
+			}
+			else
+			{
+				throw new ArgumentException("Invalid parameter passed to Skein MAC init - "
+				                            + parameters.GetType().Name);
+			}
+			if (skeinParameters.GetKey() == null)
+			{
+				throw new ArgumentException("Skein MAC requires a key parameter.");
+			}
+			engine.Init(skeinParameters);
+		}
+
+		public int GetMacSize()
+		{
+			return engine.OutputSize;
+		}
+
+		public void Reset()
+		{
+			engine.Reset();
+		}
+
+		public void Update(byte inByte)
+		{
+			engine.Update(inByte);
+		}
+
+		public void BlockUpdate(byte[] input, int inOff, int len)
+		{
+			engine.Update(input, inOff, len);
+		}
+
+		public int DoFinal(byte[] output, int outOff)
+		{
+			return engine.DoFinal(output, outOff);
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/macs/VMPCMac.cs b/BouncyCastle.AxCrypt/src/crypto/macs/VMPCMac.cs
new file mode 100644
index 0000000..8991635
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/macs/VMPCMac.cs
@@ -0,0 +1,173 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Macs
+{
+	public class VmpcMac
+		: IMac
+	{
+		private byte g;
+
+		private byte n = 0;
+		private byte[] P = null;
+		private byte s = 0;
+
+		private byte[] T;
+		private byte[] workingIV;
+
+		private byte[] workingKey;
+
+		private byte x1, x2, x3, x4;
+
+		public virtual int DoFinal(byte[] output, int outOff)
+		{
+			// Execute the Post-Processing Phase
+			for (int r = 1; r < 25; r++)
+			{
+				s = P[(s + P[n & 0xff]) & 0xff];
+
+				x4 = P[(x4 + x3 + r) & 0xff];
+				x3 = P[(x3 + x2 + r) & 0xff];
+				x2 = P[(x2 + x1 + r) & 0xff];
+				x1 = P[(x1 + s + r) & 0xff];
+				T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+				T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+				T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+				T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+				g = (byte) ((g + 4) & 0x1f);
+
+				byte temp = P[n & 0xff];
+				P[n & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+				n = (byte) ((n + 1) & 0xff);
+			}
+
+			// Input T to the IV-phase of the VMPC KSA
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + T[m & 0x1f]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+
+			// Store 20 new outputs of the VMPC Stream Cipher input table M
+			byte[] M = new byte[20];
+			for (int i = 0; i < 20; i++)
+			{
+				s = P[(s + P[i & 0xff]) & 0xff];
+				M[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+
+				byte temp = P[i & 0xff];
+				P[i & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+
+			Array.Copy(M, 0, output, outOff, M.Length);
+			Reset();
+
+			return M.Length;
+		}
+
+		public virtual string AlgorithmName
+		{
+			get { return "VMPC-MAC"; }
+		}
+
+		public virtual int GetMacSize()
+		{
+			return 20;
+		}
+
+		public virtual void Init(ICipherParameters parameters)
+		{
+			if (!(parameters is ParametersWithIV))
+				throw new ArgumentException("VMPC-MAC Init parameters must include an IV", "parameters");
+
+			ParametersWithIV ivParams = (ParametersWithIV) parameters;
+			KeyParameter key = (KeyParameter) ivParams.Parameters;
+
+			if (!(ivParams.Parameters is KeyParameter))
+				throw new ArgumentException("VMPC-MAC Init parameters must include a key", "parameters");
+
+			this.workingIV = ivParams.GetIV();
+
+			if (workingIV == null || workingIV.Length < 1 || workingIV.Length > 768)
+				throw new ArgumentException("VMPC-MAC requires 1 to 768 bytes of IV", "parameters");
+
+			this.workingKey = key.GetKey();
+
+			Reset();
+
+		}
+
+		private void initKey(byte[] keyBytes, byte[] ivBytes)
+		{
+			s = 0;
+			P = new byte[256];
+			for (int i = 0; i < 256; i++)
+			{
+				P[i] = (byte) i;
+			}
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + keyBytes[m % keyBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+			for (int m = 0; m < 768; m++)
+			{
+				s = P[(s + P[m & 0xff] + ivBytes[m % ivBytes.Length]) & 0xff];
+				byte temp = P[m & 0xff];
+				P[m & 0xff] = P[s & 0xff];
+				P[s & 0xff] = temp;
+			}
+			n = 0;
+		}
+
+		public virtual void Reset()
+		{
+			initKey(this.workingKey, this.workingIV);
+			g = x1 = x2 = x3 = x4 = n = 0;
+			T = new byte[32];
+			for (int i = 0; i < 32; i++)
+			{
+				T[i] = 0;
+			}
+		}
+
+		public virtual void Update(byte input)
+		{
+			s = P[(s + P[n & 0xff]) & 0xff];
+			byte c = (byte) (input ^ P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff]);
+
+			x4 = P[(x4 + x3) & 0xff];
+			x3 = P[(x3 + x2) & 0xff];
+			x2 = P[(x2 + x1) & 0xff];
+			x1 = P[(x1 + s + c) & 0xff];
+			T[g & 0x1f] = (byte) (T[g & 0x1f] ^ x1);
+			T[(g + 1) & 0x1f] = (byte) (T[(g + 1) & 0x1f] ^ x2);
+			T[(g + 2) & 0x1f] = (byte) (T[(g + 2) & 0x1f] ^ x3);
+			T[(g + 3) & 0x1f] = (byte) (T[(g + 3) & 0x1f] ^ x4);
+			g = (byte) ((g + 4) & 0x1f);
+
+			byte temp = P[n & 0xff];
+			P[n & 0xff] = P[s & 0xff];
+			P[s & 0xff] = temp;
+			n = (byte) ((n + 1) & 0xff);
+		}
+
+		public virtual void BlockUpdate(byte[] input, int inOff, int len)
+		{
+			if ((inOff + len) > input.Length)
+				throw new DataLengthException("input buffer too short");
+
+			for (int i = 0; i < len; i++)
+			{
+				Update(input[i]);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/CbcBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/CbcBlockCipher.cs
new file mode 100644
index 0000000..9345fd8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/CbcBlockCipher.cs
@@ -0,0 +1,241 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher.
+    */
+    public class CbcBlockCipher
+		: IBlockCipher
+    {
+        private byte[]			IV, cbcV, cbcNextV;
+		private int				blockSize;
+        private IBlockCipher	cipher;
+        private bool			encrypting;
+
+        /**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used as the basis of chaining.
+        */
+        public CbcBlockCipher(
+            IBlockCipher cipher)
+        {
+            this.cipher = cipher;
+            this.blockSize = cipher.GetBlockSize();
+
+            this.IV = new byte[blockSize];
+            this.cbcV = new byte[blockSize];
+            this.cbcNextV = new byte[blockSize];
+        }
+
+        /**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+        /**
+        * Initialise the cipher and, possibly, the initialisation vector (IV).
+        * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+        *
+        * @param forEncryption if true the cipher is initialised for
+        *  encryption, if false for decryption.
+        * @param param the key and other data required by the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool forEncryption,
+            ICipherParameters parameters)
+        {
+            bool oldEncrypting = this.encrypting;
+
+            this.encrypting = forEncryption;
+
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV)parameters;
+                byte[]      iv = ivParam.GetIV();
+
+                if (iv.Length != blockSize)
+                {
+                    throw new ArgumentException("initialisation vector must be the same length as block size");
+                }
+
+                Array.Copy(iv, 0, IV, 0, iv.Length);
+
+				parameters = ivParam.Parameters;
+            }
+
+			Reset();
+
+            // if null it's an IV changed only.
+            if (parameters != null)
+            {
+                cipher.Init(encrypting, parameters);
+            }
+            else if (oldEncrypting != encrypting)
+            {
+                throw new ArgumentException("cannot change encrypting state without providing key.");
+            }
+        }
+
+		/**
+        * return the algorithm name and mode.
+        *
+        * @return the name of the underlying algorithm followed by "/CBC".
+        */
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/CBC"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return false; }
+		}
+
+		/**
+        * return the block size of the underlying cipher.
+        *
+        * @return the block size of the underlying cipher.
+        */
+        public int GetBlockSize()
+        {
+            return cipher.GetBlockSize();
+        }
+
+        /**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            return (encrypting)
+				?	EncryptBlock(input, inOff, output, outOff)
+				:	DecryptBlock(input, inOff, output, outOff);
+        }
+
+        /**
+        * reset the chaining vector back to the IV and reset the underlying
+        * cipher.
+        */
+        public void Reset()
+        {
+            Array.Copy(IV, 0, cbcV, 0, IV.Length);
+			Array.Clear(cbcNextV, 0, cbcNextV.Length);
+
+            cipher.Reset();
+        }
+
+        /**
+        * Do the appropriate chaining step for CBC mode encryption.
+        *
+        * @param in the array containing the data to be encrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the encrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        private int EncryptBlock(
+            byte[]      input,
+            int         inOff,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            /*
+            * XOR the cbcV and the input,
+            * then encrypt the cbcV
+            */
+            for (int i = 0; i < blockSize; i++)
+            {
+                cbcV[i] ^= input[inOff + i];
+            }
+
+            int length = cipher.ProcessBlock(cbcV, 0, outBytes, outOff);
+
+            /*
+            * copy ciphertext to cbcV
+            */
+            Array.Copy(outBytes, outOff, cbcV, 0, cbcV.Length);
+
+            return length;
+        }
+
+        /**
+        * Do the appropriate chaining step for CBC mode decryption.
+        *
+        * @param in the array containing the data to be decrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the decrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        private int DecryptBlock(
+            byte[]      input,
+            int         inOff,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            Array.Copy(input, inOff, cbcNextV, 0, blockSize);
+
+            int length = cipher.ProcessBlock(input, inOff, outBytes, outOff);
+
+            /*
+            * XOR the cbcV and the output
+            */
+            for (int i = 0; i < blockSize; i++)
+            {
+                outBytes[outOff + i] ^= cbcV[i];
+            }
+
+            /*
+            * swap the back up buffer into next position
+            */
+            byte[]  tmp;
+
+            tmp = cbcV;
+            cbcV = cbcNextV;
+            cbcNextV = tmp;
+
+            return length;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/CcmBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/CcmBlockCipher.cs
new file mode 100644
index 0000000..d58a2cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/CcmBlockCipher.cs
@@ -0,0 +1,383 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * Implements the Counter with Cipher Block Chaining mode (CCM) detailed in
+    * NIST Special Publication 800-38C.
+    * <p>
+    * <b>Note</b>: this mode is a packet mode - it needs all the data up front.
+    * </p>
+    */
+    public class CcmBlockCipher
+        : IAeadBlockCipher
+    {
+        private static readonly int BlockSize = 16;
+
+        private readonly IBlockCipher	cipher;
+        private readonly byte[]			macBlock;
+        private bool					forEncryption;
+        private byte[]					nonce;
+        private byte[]					initialAssociatedText;
+        private int						macSize;
+        private ICipherParameters		keyParam;
+        private readonly MemoryStream   associatedText = new MemoryStream();
+        private readonly MemoryStream   data = new MemoryStream();
+
+        /**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used.
+        */
+        public CcmBlockCipher(
+            IBlockCipher cipher)
+        {
+            this.cipher = cipher;
+            this.macBlock = new byte[BlockSize];
+
+            if (cipher.GetBlockSize() != BlockSize)
+                throw new ArgumentException("cipher required with a block size of " + BlockSize + ".");
+        }
+
+        /**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public virtual IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+        public virtual void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            this.forEncryption = forEncryption;
+
+            if (parameters is AeadParameters)
+            {
+                AeadParameters param = (AeadParameters) parameters;
+
+                nonce = param.GetNonce();
+                initialAssociatedText = param.GetAssociatedText();
+                macSize = param.MacSize / 8;
+                keyParam = param.Key;
+            }
+            else if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV param = (ParametersWithIV) parameters;
+
+                nonce = param.GetIV();
+                initialAssociatedText = null;
+                macSize = macBlock.Length / 2;
+                keyParam = param.Parameters;
+            }
+            else
+            {
+                throw new ArgumentException("invalid parameters passed to CCM");
+            }
+
+            if (nonce == null || nonce.Length < 7 || nonce.Length > 13)
+            {
+                throw new ArgumentException("nonce must have length from 7 to 13 octets");
+            }
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/CCM"; }
+        }
+
+        public virtual int GetBlockSize()
+        {
+            return cipher.GetBlockSize();
+        }
+
+        public virtual void ProcessAadByte(byte input)
+        {
+            associatedText.WriteByte(input);
+        }
+
+        public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len)
+        {
+            // TODO: Process AAD online
+            associatedText.Write(inBytes, inOff, len);
+        }
+
+        public virtual int ProcessByte(
+            byte	input,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            data.WriteByte(input);
+
+            return 0;
+        }
+
+        public virtual int ProcessBytes(
+            byte[]	inBytes,
+            int		inOff,
+            int		inLen,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            data.Write(inBytes, inOff, inLen);
+
+            return 0;
+        }
+
+        public virtual int DoFinal(
+            byte[]	outBytes,
+            int		outOff)
+        {
+            byte[] enc = ProcessPacket(data.ToArray(), 0, (int)data.Position);
+
+            Array.Copy(enc, 0, outBytes, outOff, enc.Length);
+
+            Reset();
+
+            return enc.Length;
+        }
+
+        public virtual void Reset()
+        {
+            cipher.Reset();
+            associatedText.SetLength(0);
+            data.SetLength(0);
+        }
+
+        /**
+        * Returns a byte array containing the mac calculated as part of the
+        * last encrypt or decrypt operation.
+        *
+        * @return the last mac calculated.
+        */
+        public virtual byte[] GetMac()
+        {
+            byte[] mac = new byte[macSize];
+
+            Array.Copy(macBlock, 0, mac, 0, mac.Length);
+
+            return mac;
+        }
+
+        public virtual int GetUpdateOutputSize(
+            int len)
+        {
+            return 0;
+        }
+
+        public int GetOutputSize(
+            int len)
+        {
+            int totalData = (int)data.Length + len;
+
+            if (forEncryption)
+            {
+                return totalData + macSize;
+            }
+
+            return totalData < macSize ? 0 : totalData - macSize;
+        }
+
+        public byte[] ProcessPacket(
+            byte[]	input,
+            int		inOff,
+            int		inLen)
+        {
+            // TODO: handle null keyParam (e.g. via RepeatedKeySpec)
+            // Need to keep the CTR and CBC Mac parts around and reset
+            if (keyParam == null)
+                throw new InvalidOperationException("CCM cipher unitialized.");
+
+            int n = nonce.Length;
+            int q = 15 - n;
+            if (q < 4)
+            {
+                int limitLen = 1 << (8 * q);
+                if (inLen >= limitLen)
+                    throw new InvalidOperationException("CCM packet too large for choice of q.");
+            }
+
+            byte[] iv = new byte[BlockSize];
+            iv[0] = (byte)((q - 1) & 0x7);
+            nonce.CopyTo(iv, 1);
+
+            IBlockCipher ctrCipher = new SicBlockCipher(cipher);
+            ctrCipher.Init(forEncryption, new ParametersWithIV(keyParam, iv));
+
+            int index = inOff;
+            int outOff = 0;
+            byte[] output;
+
+            if (forEncryption)
+            {
+                output = new byte[inLen + macSize];
+
+                calculateMac(input, inOff, inLen, macBlock);
+
+                ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0);   // S0
+
+                while (index < inLen - BlockSize)                   // S1...
+                {
+                    ctrCipher.ProcessBlock(input, index, output, outOff);
+                    outOff += BlockSize;
+                    index += BlockSize;
+                }
+
+                byte[] block = new byte[BlockSize];
+
+                Array.Copy(input, index, block, 0, inLen - index);
+
+                ctrCipher.ProcessBlock(block, 0, block, 0);
+
+                Array.Copy(block, 0, output, outOff, inLen - index);
+
+                outOff += inLen - index;
+
+                Array.Copy(macBlock, 0, output, outOff, output.Length - outOff);
+            }
+            else
+            {
+                output = new byte[inLen - macSize];
+
+                Array.Copy(input, inOff + inLen - macSize, macBlock, 0, macSize);
+
+                ctrCipher.ProcessBlock(macBlock, 0, macBlock, 0);
+
+                for (int i = macSize; i != macBlock.Length; i++)
+                {
+                    macBlock[i] = 0;
+                }
+
+                while (outOff < output.Length - BlockSize)
+                {
+                    ctrCipher.ProcessBlock(input, index, output, outOff);
+                    outOff += BlockSize;
+                    index += BlockSize;
+                }
+
+                byte[] block = new byte[BlockSize];
+
+                Array.Copy(input, index, block, 0, output.Length - outOff);
+
+                ctrCipher.ProcessBlock(block, 0, block, 0);
+
+                Array.Copy(block, 0, output, outOff, output.Length - outOff);
+
+                byte[] calculatedMacBlock = new byte[BlockSize];
+
+                calculateMac(output, 0, output.Length, calculatedMacBlock);
+
+                if (!Arrays.ConstantTimeAreEqual(macBlock, calculatedMacBlock))
+                    throw new InvalidCipherTextException("mac check in CCM failed");
+            }
+
+            return output;
+        }
+
+        private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
+        {
+            IMac cMac = new CbcBlockCipherMac(cipher, macSize * 8);
+
+            cMac.Init(keyParam);
+
+            //
+            // build b0
+            //
+            byte[] b0 = new byte[16];
+
+            if (HasAssociatedText())
+            {
+                b0[0] |= 0x40;
+            }
+
+            b0[0] |= (byte)((((cMac.GetMacSize() - 2) / 2) & 0x7) << 3);
+
+            b0[0] |= (byte)(((15 - nonce.Length) - 1) & 0x7);
+
+            Array.Copy(nonce, 0, b0, 1, nonce.Length);
+
+            int q = dataLen;
+            int count = 1;
+            while (q > 0)
+            {
+                b0[b0.Length - count] = (byte)(q & 0xff);
+                q >>= 8;
+                count++;
+            }
+
+            cMac.BlockUpdate(b0, 0, b0.Length);
+
+            //
+            // process associated text
+            //
+            if (HasAssociatedText())
+            {
+                int extra;
+
+                int textLength = GetAssociatedTextLength();
+                if (textLength < ((1 << 16) - (1 << 8)))
+                {
+                    cMac.Update((byte)(textLength >> 8));
+                    cMac.Update((byte)textLength);
+
+                    extra = 2;
+                }
+                else // can't go any higher than 2^32
+                {
+                    cMac.Update((byte)0xff);
+                    cMac.Update((byte)0xfe);
+                    cMac.Update((byte)(textLength >> 24));
+                    cMac.Update((byte)(textLength >> 16));
+                    cMac.Update((byte)(textLength >> 8));
+                    cMac.Update((byte)textLength);
+
+                    extra = 6;
+                }
+
+                if (initialAssociatedText != null)
+                {
+                    cMac.BlockUpdate(initialAssociatedText, 0, initialAssociatedText.Length);
+                }
+                if (associatedText.Position > 0)
+                {
+                    cMac.BlockUpdate(associatedText.ToArray(), 0, (int)associatedText.Position);
+                }
+
+                extra = (extra + textLength) % 16;
+                if (extra != 0)
+                {
+                    for (int i = extra; i < 16; ++i)
+                    {
+                        cMac.Update((byte)0x00);
+                    }
+                }
+            }
+
+            //
+            // add the text
+            //
+            cMac.BlockUpdate(data, dataOff, dataLen);
+
+            return cMac.DoFinal(macBlock, 0);
+        }
+
+        private int GetAssociatedTextLength()
+        {
+            return (int)associatedText.Length + ((initialAssociatedText == null) ? 0 : initialAssociatedText.Length);
+        }
+
+        private bool HasAssociatedText()
+        {
+            return GetAssociatedTextLength() > 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/CfbBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/CfbBlockCipher.cs
new file mode 100644
index 0000000..4337165
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/CfbBlockCipher.cs
@@ -0,0 +1,224 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
+    */
+    public class CfbBlockCipher
+		: IBlockCipher
+    {
+        private byte[]	IV;
+        private byte[]	cfbV;
+        private byte[]	cfbOutV;
+		private bool	encrypting;
+
+		private readonly int			blockSize;
+        private readonly IBlockCipher	cipher;
+
+		/**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used as the basis of the
+        * feedback mode.
+        * @param blockSize the block size in bits (note: a multiple of 8)
+        */
+        public CfbBlockCipher(
+            IBlockCipher cipher,
+            int          bitBlockSize)
+        {
+            this.cipher = cipher;
+            this.blockSize = bitBlockSize / 8;
+            this.IV = new byte[cipher.GetBlockSize()];
+            this.cfbV = new byte[cipher.GetBlockSize()];
+            this.cfbOutV = new byte[cipher.GetBlockSize()];
+        }
+        /**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+        /**
+        * Initialise the cipher and, possibly, the initialisation vector (IV).
+        * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+        * An IV which is too short is handled in FIPS compliant fashion.
+        *
+        * @param forEncryption if true the cipher is initialised for
+        *  encryption, if false for decryption.
+        * @param param the key and other data required by the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool forEncryption,
+            ICipherParameters parameters)
+        {
+            this.encrypting = forEncryption;
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV) parameters;
+                byte[] iv = ivParam.GetIV();
+                int diff = IV.Length - iv.Length;
+                Array.Copy(iv, 0, IV, diff, iv.Length);
+                Array.Clear(IV, 0, diff);
+
+                parameters = ivParam.Parameters;
+            }
+            Reset();
+
+            // if it's null, key is to be reused.
+            if (parameters != null)
+            {
+                cipher.Init(true, parameters);
+            }
+        }
+
+        /**
+        * return the algorithm name and mode.
+        *
+        * @return the name of the underlying algorithm followed by "/CFB"
+        * and the block size in bits.
+        */
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/CFB" + (blockSize * 8); }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		/**
+        * return the block size we are operating at.
+        *
+        * @return the block size we are operating at (in bytes).
+        */
+        public int GetBlockSize()
+        {
+            return blockSize;
+        }
+
+		/**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            return (encrypting)
+				?	EncryptBlock(input, inOff, output, outOff)
+				:	DecryptBlock(input, inOff, output, outOff);
+        }
+
+		/**
+        * Do the appropriate processing for CFB mode encryption.
+        *
+        * @param in the array containing the data to be encrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the encrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int EncryptBlock(
+            byte[]      input,
+            int         inOff,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+            if ((outOff + blockSize) > outBytes.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+            cipher.ProcessBlock(cfbV, 0, cfbOutV, 0);
+            //
+            // XOR the cfbV with the plaintext producing the ciphertext
+            //
+            for (int i = 0; i < blockSize; i++)
+            {
+                outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]);
+            }
+            //
+            // change over the input block.
+            //
+            Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize);
+            Array.Copy(outBytes, outOff, cfbV, cfbV.Length - blockSize, blockSize);
+            return blockSize;
+        }
+        /**
+        * Do the appropriate processing for CFB mode decryption.
+        *
+        * @param in the array containing the data to be decrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the encrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int DecryptBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+            if ((outOff + blockSize) > outBytes.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+            cipher.ProcessBlock(cfbV, 0, cfbOutV, 0);
+            //
+            // change over the input block.
+            //
+            Array.Copy(cfbV, blockSize, cfbV, 0, cfbV.Length - blockSize);
+            Array.Copy(input, inOff, cfbV, cfbV.Length - blockSize, blockSize);
+            //
+            // XOR the cfbV with the ciphertext producing the plaintext
+            //
+            for (int i = 0; i < blockSize; i++)
+            {
+                outBytes[outOff + i] = (byte)(cfbOutV[i] ^ input[inOff + i]);
+            }
+            return blockSize;
+        }
+        /**
+        * reset the chaining vector back to the IV and reset the underlying
+        * cipher.
+        */
+        public void Reset()
+        {
+            Array.Copy(IV, 0, cfbV, 0, IV.Length);
+            cipher.Reset();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/CtsBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/CtsBlockCipher.cs
new file mode 100644
index 0000000..a32b496
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/CtsBlockCipher.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+    * be used to produce cipher text which is the same outLength as the plain text.
+    */
+    public class CtsBlockCipher
+		: BufferedBlockCipher
+    {
+        private readonly int blockSize;
+
+        /**
+        * Create a buffered block cipher that uses Cipher Text Stealing
+        *
+        * @param cipher the underlying block cipher this buffering object wraps.
+        */
+        public CtsBlockCipher(
+            IBlockCipher cipher)
+        {
+			// TODO Should this test for acceptable ones instead?
+			if (cipher is OfbBlockCipher || cipher is CfbBlockCipher)
+                throw new ArgumentException("CtsBlockCipher can only accept ECB, or CBC ciphers");
+
+			this.cipher = cipher;
+
+            blockSize = cipher.GetBlockSize();
+
+            buf = new byte[blockSize * 2];
+            bufOff = 0;
+        }
+
+        /**
+        * return the size of the output buffer required for an update of 'length' bytes.
+        *
+        * @param length the outLength of the input.
+        * @return the space required to accommodate a call to update
+        * with length bytes of input.
+        */
+        public override int GetUpdateOutputSize(
+            int length)
+        {
+            int total = length + bufOff;
+            int leftOver = total % buf.Length;
+
+			if (leftOver == 0)
+            {
+                return total - buf.Length;
+            }
+
+			return total - leftOver;
+        }
+
+        /**
+        * return the size of the output buffer required for an update plus a
+        * doFinal with an input of length bytes.
+        *
+        * @param length the outLength of the input.
+        * @return the space required to accommodate a call to update and doFinal
+        * with length bytes of input.
+        */
+        public override int GetOutputSize(
+            int length)
+        {
+            return length + bufOff;
+        }
+
+        /**
+        * process a single byte, producing an output block if neccessary.
+        *
+        * @param in the input byte.
+        * @param out the space for any output that might be produced.
+        * @param outOff the offset from which the output will be copied.
+        * @return the number of output bytes copied to out.
+        * @exception DataLengthException if there isn't enough space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        */
+        public override int ProcessByte(
+            byte	input,
+            byte[]	output,
+            int		outOff)
+        {
+            int resultLen = 0;
+
+            if (bufOff == buf.Length)
+            {
+                resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
+				Debug.Assert(resultLen == blockSize);
+
+				Array.Copy(buf, blockSize, buf, 0, blockSize);
+                bufOff = blockSize;
+            }
+
+            buf[bufOff++] = input;
+
+            return resultLen;
+        }
+
+		/**
+        * process an array of bytes, producing output if necessary.
+        *
+        * @param in the input byte array.
+        * @param inOff the offset at which the input data starts.
+        * @param length the number of bytes to be copied out of the input array.
+        * @param out the space for any output that might be produced.
+        * @param outOff the offset from which the output will be copied.
+        * @return the number of output bytes copied to out.
+        * @exception DataLengthException if there isn't enough space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        */
+        public override int ProcessBytes(
+            byte[]	input,
+            int		inOff,
+            int		length,
+            byte[]	output,
+            int		outOff)
+        {
+            if (length < 0)
+            {
+                throw new ArgumentException("Can't have a negative input outLength!");
+            }
+
+            int blockSize = GetBlockSize();
+            int outLength = GetUpdateOutputSize(length);
+
+            if (outLength > 0)
+            {
+                if ((outOff + outLength) > output.Length)
+                {
+                    throw new DataLengthException("output buffer too short");
+                }
+            }
+
+            int resultLen = 0;
+            int gapLen = buf.Length - bufOff;
+
+            if (length > gapLen)
+            {
+                Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+                resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+                Array.Copy(buf, blockSize, buf, 0, blockSize);
+
+                bufOff = blockSize;
+
+                length -= gapLen;
+                inOff += gapLen;
+
+                while (length > blockSize)
+                {
+                    Array.Copy(input, inOff, buf, bufOff, blockSize);
+                    resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
+                    Array.Copy(buf, blockSize, buf, 0, blockSize);
+
+                    length -= blockSize;
+                    inOff += blockSize;
+                }
+            }
+
+            Array.Copy(input, inOff, buf, bufOff, length);
+
+            bufOff += length;
+
+            return resultLen;
+        }
+
+        /**
+        * Process the last block in the buffer.
+        *
+        * @param out the array the block currently being held is copied into.
+        * @param outOff the offset at which the copying starts.
+        * @return the number of output bytes copied to out.
+        * @exception DataLengthException if there is insufficient space in out for
+        * the output.
+        * @exception InvalidOperationException if the underlying cipher is not
+        * initialised.
+        * @exception InvalidCipherTextException if cipher text decrypts wrongly (in
+        * case the exception will never Get thrown).
+        */
+        public override int DoFinal(
+            byte[]  output,
+            int     outOff)
+        {
+            if (bufOff + outOff > output.Length)
+            {
+                throw new DataLengthException("output buffer too small in doFinal");
+            }
+
+            int blockSize = cipher.GetBlockSize();
+            int length = bufOff - blockSize;
+            byte[] block = new byte[blockSize];
+
+            if (forEncryption)
+            {
+                cipher.ProcessBlock(buf, 0, block, 0);
+
+				if (bufOff < blockSize)
+				{
+					throw new DataLengthException("need at least one block of input for CTS");
+				}
+
+                for (int i = bufOff; i != buf.Length; i++)
+                {
+                    buf[i] = block[i - blockSize];
+                }
+
+                for (int i = blockSize; i != bufOff; i++)
+                {
+                    buf[i] ^= block[i - blockSize];
+                }
+
+				IBlockCipher c = (cipher is CbcBlockCipher)
+					?	((CbcBlockCipher)cipher).GetUnderlyingCipher()
+					:	cipher;
+
+				c.ProcessBlock(buf, blockSize, output, outOff);
+
+				Array.Copy(block, 0, output, outOff + blockSize, length);
+            }
+            else
+            {
+                byte[] lastBlock = new byte[blockSize];
+
+				IBlockCipher c = (cipher is CbcBlockCipher)
+					?	((CbcBlockCipher)cipher).GetUnderlyingCipher()
+					:	cipher;
+
+				c.ProcessBlock(buf, 0, block, 0);
+
+				for (int i = blockSize; i != bufOff; i++)
+                {
+                    lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+                }
+
+                Array.Copy(buf, blockSize, block, 0, length);
+
+                cipher.ProcessBlock(block, 0, output, outOff);
+                Array.Copy(lastBlock, 0, output, outOff + blockSize, length);
+            }
+
+            int offset = bufOff;
+
+            Reset();
+
+            return offset;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/EAXBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/EAXBlockCipher.cs
new file mode 100644
index 0000000..5ccc69b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/EAXBlockCipher.cs
@@ -0,0 +1,370 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+	/**
+	* A Two-Pass Authenticated-Encryption Scheme Optimized for Simplicity and 
+	* Efficiency - by M. Bellare, P. Rogaway, D. Wagner.
+	* 
+	* http://www.cs.ucdavis.edu/~rogaway/papers/eax.pdf
+	* 
+	* EAX is an AEAD scheme based on CTR and OMAC1/CMAC, that uses a single block 
+	* cipher to encrypt and authenticate data. It's on-line (the length of a 
+	* message isn't needed to begin processing it), has good performances, it's
+	* simple and provably secure (provided the underlying block cipher is secure).
+	* 
+	* Of course, this implementations is NOT thread-safe.
+	*/
+	public class EaxBlockCipher
+		: IAeadBlockCipher
+	{
+		private enum Tag : byte { N, H, C };
+
+		private SicBlockCipher cipher;
+
+		private bool forEncryption;
+
+		private int blockSize;
+
+		private IMac mac;
+
+		private byte[] nonceMac;
+		private byte[] associatedTextMac;
+		private byte[] macBlock;
+
+		private int macSize;
+		private byte[] bufBlock;
+		private int bufOff;
+
+        private bool cipherInitialized;
+        private byte[] initialAssociatedText;
+
+		/**
+		* Constructor that accepts an instance of a block cipher engine.
+		*
+		* @param cipher the engine to use
+		*/
+		public EaxBlockCipher(
+			IBlockCipher cipher)
+		{
+			blockSize = cipher.GetBlockSize();
+			mac = new CMac(cipher);
+			macBlock = new byte[blockSize];
+			bufBlock = new byte[blockSize * 2];
+			associatedTextMac = new byte[mac.GetMacSize()];
+			nonceMac = new byte[mac.GetMacSize()];
+			this.cipher = new SicBlockCipher(cipher);
+		}
+
+		public virtual string AlgorithmName
+		{
+			get { return cipher.GetUnderlyingCipher().AlgorithmName + "/EAX"; }
+		}
+
+		public IBlockCipher GetUnderlyingCipher()
+		{
+			return cipher;
+		}
+
+		public virtual int GetBlockSize()
+		{
+			return cipher.GetBlockSize();
+		}
+
+		public virtual void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+
+			byte[] nonce;
+			ICipherParameters keyParam;
+
+			if (parameters is AeadParameters)
+			{
+				AeadParameters param = (AeadParameters) parameters;
+
+				nonce = param.GetNonce();
+                initialAssociatedText = param.GetAssociatedText();
+				macSize = param.MacSize / 8;
+				keyParam = param.Key;
+			}
+			else if (parameters is ParametersWithIV)
+			{
+				ParametersWithIV param = (ParametersWithIV) parameters;
+
+				nonce = param.GetIV();
+                initialAssociatedText = null;
+				macSize = mac.GetMacSize() / 2;
+				keyParam = param.Parameters;
+			}
+			else
+			{
+				throw new ArgumentException("invalid parameters passed to EAX");
+			}
+
+            byte[] tag = new byte[blockSize];
+
+            // Key reuse implemented in CBC mode of underlying CMac
+            mac.Init(keyParam);
+
+            tag[blockSize - 1] = (byte)Tag.N;
+            mac.BlockUpdate(tag, 0, blockSize);
+            mac.BlockUpdate(nonce, 0, nonce.Length);
+            mac.DoFinal(nonceMac, 0);
+
+            tag[blockSize - 1] = (byte)Tag.H;
+            mac.BlockUpdate(tag, 0, blockSize);
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+
+            // Same BlockCipher underlies this and the mac, so reuse last key on cipher 
+            cipher.Init(true, new ParametersWithIV(null, nonceMac));
+		}
+
+        private void InitCipher()
+        {
+            if (cipherInitialized)
+            {
+                return;
+            }
+
+            cipherInitialized = true;
+
+            mac.DoFinal(associatedTextMac, 0);
+
+            byte[] tag = new byte[blockSize];
+            tag[blockSize - 1] = (byte)Tag.C;
+            mac.BlockUpdate(tag, 0, blockSize);
+        }
+
+        private void CalculateMac()
+		{
+			byte[] outC = new byte[blockSize];
+			mac.DoFinal(outC, 0);
+
+			for (int i = 0; i < macBlock.Length; i++)
+			{
+				macBlock[i] = (byte)(nonceMac[i] ^ associatedTextMac[i] ^ outC[i]);
+			}
+		}
+
+		public virtual void Reset()
+		{
+			Reset(true);
+		}
+
+		private void Reset(
+			bool clearMac)
+		{
+            cipher.Reset(); // TODO Redundant since the mac will reset it?
+			mac.Reset();
+
+			bufOff = 0;
+			Array.Clear(bufBlock, 0, bufBlock.Length);
+
+			if (clearMac)
+			{
+				Array.Clear(macBlock, 0, macBlock.Length);
+			}
+
+            byte[] tag = new byte[blockSize];
+            tag[blockSize - 1] = (byte)Tag.H;
+            mac.BlockUpdate(tag, 0, blockSize);
+
+            cipherInitialized = false;
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+        }
+        
+        public virtual void ProcessAadByte(byte input)
+        {
+            if (cipherInitialized)
+            {
+                throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun.");
+            }
+            mac.Update(input);
+        }
+
+        public void ProcessAadBytes(byte[] inBytes, int inOff, int len)
+        {
+            if (cipherInitialized)
+            {
+                throw new InvalidOperationException("AAD data cannot be added after encryption/decription processing has begun.");
+            }
+            mac.BlockUpdate(inBytes, inOff, len);
+        }
+
+        public virtual int ProcessByte(
+			byte	input,
+			byte[]	outBytes,
+			int		outOff)
+		{
+            InitCipher();
+
+            return Process(input, outBytes, outOff);
+		}
+
+        public virtual int ProcessBytes(
+			byte[]	inBytes,
+			int		inOff,
+			int		len,
+			byte[]	outBytes,
+			int		outOff)
+		{
+            InitCipher();
+
+            int resultLen = 0;
+
+			for (int i = 0; i != len; i++)
+			{
+				resultLen += Process(inBytes[inOff + i], outBytes, outOff + resultLen);
+			}
+
+            return resultLen;
+		}
+
+		public virtual int DoFinal(
+			byte[]	outBytes,
+			int		outOff)
+		{
+            InitCipher();
+
+            int extra = bufOff;
+			byte[] tmp = new byte[bufBlock.Length];
+
+            bufOff = 0;
+
+			if (forEncryption)
+			{
+				cipher.ProcessBlock(bufBlock, 0, tmp, 0);
+				cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize);
+
+				Array.Copy(tmp, 0, outBytes, outOff, extra);
+
+				mac.BlockUpdate(tmp, 0, extra);
+
+				CalculateMac();
+
+				Array.Copy(macBlock, 0, outBytes, outOff + extra, macSize);
+
+				Reset(false);
+
+				return extra + macSize;
+			}
+			else
+			{
+				if (extra > macSize)
+				{
+					mac.BlockUpdate(bufBlock, 0, extra - macSize);
+
+					cipher.ProcessBlock(bufBlock, 0, tmp, 0);
+					cipher.ProcessBlock(bufBlock, blockSize, tmp, blockSize);
+
+					Array.Copy(tmp, 0, outBytes, outOff, extra - macSize);
+				}
+
+				CalculateMac();
+
+				if (!VerifyMac(bufBlock, extra - macSize))
+					throw new InvalidCipherTextException("mac check in EAX failed");
+
+				Reset(false);
+
+				return extra - macSize;
+			}
+		}
+
+		public virtual byte[] GetMac()
+		{
+			byte[] mac = new byte[macSize];
+
+			Array.Copy(macBlock, 0, mac, 0, macSize);
+
+			return mac;
+		}
+
+        public virtual int GetUpdateOutputSize(
+			int len)
+		{
+            int totalData = len + bufOff;
+            if (!forEncryption)
+            {
+                if (totalData < macSize)
+                {
+                    return 0;
+                }
+                totalData -= macSize;
+            }
+            return totalData - totalData % blockSize;
+        }
+
+		public virtual int GetOutputSize(
+			int len)
+		{
+            int totalData = len + bufOff;
+
+            if (forEncryption)
+            {
+                return totalData + macSize;
+            }
+
+            return totalData < macSize ? 0 : totalData - macSize;
+        }
+
+		private int Process(
+			byte	b,
+			byte[]	outBytes,
+			int		outOff)
+		{
+			bufBlock[bufOff++] = b;
+
+			if (bufOff == bufBlock.Length)
+			{
+				int size;
+
+				if (forEncryption)
+				{
+					size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff);
+
+					mac.BlockUpdate(outBytes, outOff, blockSize);
+				}
+				else
+				{
+					mac.BlockUpdate(bufBlock, 0, blockSize);
+
+					size = cipher.ProcessBlock(bufBlock, 0, outBytes, outOff);
+				}
+
+				bufOff = blockSize;
+				Array.Copy(bufBlock, blockSize, bufBlock, 0, blockSize);
+
+				return size;
+			}
+
+			return 0;
+		}
+
+		private bool VerifyMac(byte[] mac, int off)
+		{
+            int nonEqual = 0;
+
+            for (int i = 0; i < macSize; i++)
+            {
+                nonEqual |= (macBlock[i] ^ mac[off + i]);
+            }
+
+            return nonEqual == 0;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/GCMBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/GCMBlockCipher.cs
new file mode 100644
index 0000000..2e2ac2e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/GCMBlockCipher.cs
@@ -0,0 +1,516 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes.Gcm;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /// <summary>
+    /// Implements the Galois/Counter mode (GCM) detailed in
+    /// NIST Special Publication 800-38D.
+    /// </summary>
+    public class GcmBlockCipher
+        : IAeadBlockCipher
+    {
+        private const int BlockSize = 16;
+
+        private readonly IBlockCipher	cipher;
+        private readonly IGcmMultiplier	multiplier;
+        private IGcmExponentiator exp;
+
+        // These fields are set by Init and not modified by processing
+        private bool        forEncryption;
+        private int         macSize;
+        private byte[]      nonce;
+        private byte[]      initialAssociatedText;
+        private byte[]      H;
+        private byte[]      J0;
+
+        // These fields are modified during processing
+        private byte[]		bufBlock;
+        private byte[]		macBlock;
+        private byte[]      S, S_at, S_atPre;
+        private byte[]      counter;
+        private int         bufOff;
+        private ulong		totalLength;
+        private byte[]      atBlock;
+        private int         atBlockPos;
+        private ulong       atLength;
+        private ulong       atLengthPre;
+
+        public GcmBlockCipher(
+            IBlockCipher c)
+            : this(c, null)
+        {
+        }
+
+        public GcmBlockCipher(
+            IBlockCipher	c,
+            IGcmMultiplier	m)
+        {
+            if (c.GetBlockSize() != BlockSize)
+                throw new ArgumentException("cipher required with a block size of " + BlockSize + ".");
+
+            if (m == null)
+            {
+                // TODO Consider a static property specifying default multiplier
+                m = new Tables8kGcmMultiplier();
+            }
+
+            this.cipher = c;
+            this.multiplier = m;
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/GCM"; }
+        }
+
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+        public virtual int GetBlockSize()
+        {
+            return BlockSize;
+        }
+
+        /// <remarks>
+        /// MAC sizes from 32 bits to 128 bits (must be a multiple of 8) are supported. The default is 128 bits.
+        /// Sizes less than 96 are not recommended, but are supported for specialized applications.
+        /// </remarks>
+        public virtual void Init(
+            bool				forEncryption,
+            ICipherParameters	parameters)
+        {
+            this.forEncryption = forEncryption;
+            this.macBlock = null;
+
+            KeyParameter keyParam;
+
+            if (parameters is AeadParameters)
+            {
+                AeadParameters param = (AeadParameters)parameters;
+
+                nonce = param.GetNonce();
+                initialAssociatedText = param.GetAssociatedText();
+
+                int macSizeBits = param.MacSize;
+                if (macSizeBits < 32 || macSizeBits > 128 || macSizeBits % 8 != 0)
+                {
+                    throw new ArgumentException("Invalid value for MAC size: " + macSizeBits);
+                }
+
+                macSize = macSizeBits / 8; 
+                keyParam = param.Key;
+            }
+            else if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV param = (ParametersWithIV)parameters;
+
+                nonce = param.GetIV();
+                initialAssociatedText = null;
+                macSize = 16; 
+                keyParam = (KeyParameter)param.Parameters;
+            }
+            else
+            {
+                throw new ArgumentException("invalid parameters passed to GCM");
+            }
+
+            int bufLength = forEncryption ? BlockSize : (BlockSize + macSize);
+            this.bufBlock = new byte[bufLength];
+
+            if (nonce == null || nonce.Length < 1)
+            {
+                throw new ArgumentException("IV must be at least 1 byte");
+            }
+
+            // TODO Restrict macSize to 16 if nonce length not 12?
+
+            // Cipher always used in forward mode
+            // if keyParam is null we're reusing the last key.
+            if (keyParam != null)
+            {
+                cipher.Init(true, keyParam);
+
+                this.H = new byte[BlockSize];
+                cipher.ProcessBlock(H, 0, H, 0);
+
+                // if keyParam is null we're reusing the last key and the multiplier doesn't need re-init
+                multiplier.Init(H);
+                exp = null;
+            }
+            else if (this.H == null)
+            {
+                throw new ArgumentException("Key must be specified in initial init");
+            }
+
+            this.J0 = new byte[BlockSize];
+
+            if (nonce.Length == 12)
+            {
+                Array.Copy(nonce, 0, J0, 0, nonce.Length);
+                this.J0[BlockSize - 1] = 0x01;
+            }
+            else
+            {
+                gHASH(J0, nonce, nonce.Length);
+                byte[] X = new byte[BlockSize];
+                Pack.UInt64_To_BE((ulong)nonce.Length * 8UL, X, 8);
+                gHASHBlock(J0, X);
+            }
+
+            this.S = new byte[BlockSize];
+            this.S_at = new byte[BlockSize];
+            this.S_atPre = new byte[BlockSize];
+            this.atBlock = new byte[BlockSize];
+            this.atBlockPos = 0;
+            this.atLength = 0;
+            this.atLengthPre = 0;
+            this.counter = Arrays.Clone(J0);
+            this.bufOff = 0;
+            this.totalLength = 0;
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+        }
+
+        public virtual byte[] GetMac()
+        {
+            return Arrays.Clone(macBlock);
+        }
+
+        public virtual int GetOutputSize(
+            int len)
+        {
+            int totalData = len + bufOff;
+
+            if (forEncryption)
+            {
+                return totalData + macSize;
+            }
+
+            return totalData < macSize ? 0 : totalData - macSize;
+        }
+
+        public virtual int GetUpdateOutputSize(
+            int len)
+        {
+            int totalData = len + bufOff;
+            if (!forEncryption)
+            {
+                if (totalData < macSize)
+                {
+                    return 0;
+                }
+                totalData -= macSize;
+            }
+            return totalData - totalData % BlockSize;
+        }
+
+        public virtual void ProcessAadByte(byte input)
+        {
+            atBlock[atBlockPos] = input;
+            if (++atBlockPos == BlockSize)
+            {
+                // Hash each block as it fills
+                gHASHBlock(S_at, atBlock);
+                atBlockPos = 0;
+                atLength += BlockSize;
+            }
+        }
+
+        public virtual void ProcessAadBytes(byte[] inBytes, int inOff, int len)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                atBlock[atBlockPos] = inBytes[inOff + i];
+                if (++atBlockPos == BlockSize)
+                {
+                    // Hash each block as it fills
+                    gHASHBlock(S_at, atBlock);
+                    atBlockPos = 0;
+                    atLength += BlockSize;
+                }
+            }
+        }
+
+        private void InitCipher()
+        {
+            if (atLength > 0)
+            {
+                Array.Copy(S_at, 0, S_atPre, 0, BlockSize);
+                atLengthPre = atLength;
+            }
+
+            // Finish hash for partial AAD block
+            if (atBlockPos > 0)
+            {
+                gHASHPartial(S_atPre, atBlock, 0, atBlockPos);
+                atLengthPre += (uint)atBlockPos;
+            }
+
+            if (atLengthPre > 0)
+            {
+                Array.Copy(S_atPre, 0, S, 0, BlockSize);
+            }
+        }
+
+        public virtual int ProcessByte(
+            byte	input,
+            byte[]	output,
+            int		outOff)
+        {
+            bufBlock[bufOff] = input;
+            if (++bufOff == bufBlock.Length)
+            {
+                OutputBlock(output, outOff);
+                return BlockSize;
+            }
+            return 0;
+        }
+
+        public virtual int ProcessBytes(
+            byte[]	input,
+            int		inOff,
+            int		len,
+            byte[]	output,
+            int		outOff)
+        {
+            int resultLen = 0;
+
+            for (int i = 0; i < len; ++i)
+            {
+                bufBlock[bufOff] = input[inOff + i];
+                if (++bufOff == bufBlock.Length)
+                {
+                    OutputBlock(output, outOff + resultLen);
+                    resultLen += BlockSize;
+                }
+            }
+
+            return resultLen;
+        }
+
+        private void OutputBlock(byte[] output, int offset)
+        {
+            if (totalLength == 0)
+            {
+                InitCipher();
+            }
+            gCTRBlock(bufBlock, output, offset);
+            if (forEncryption)
+            {
+                bufOff = 0;
+            }
+            else
+            {
+                Array.Copy(bufBlock, BlockSize, bufBlock, 0, macSize);
+                bufOff = macSize;
+            }
+        }
+
+        public int DoFinal(byte[] output, int outOff)
+        {
+            if (totalLength == 0)
+            {
+                InitCipher();
+            }
+
+            int extra = bufOff;
+            if (!forEncryption)
+            {
+                if (extra < macSize)
+                    throw new InvalidCipherTextException("data too short");
+
+                extra -= macSize;
+            }
+
+            if (extra > 0)
+            {
+                gCTRPartial(bufBlock, 0, extra, output, outOff);
+            }
+
+            atLength += (uint)atBlockPos;
+
+            if (atLength > atLengthPre)
+            {
+                /*
+                 *  Some AAD was sent after the cipher started. We determine the difference b/w the hash value
+                 *  we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at).
+                 *  Then we carry this difference forward by multiplying by H^c, where c is the number of (full or
+                 *  partial) cipher-text blocks produced, and adjust the current hash.
+                 */
+
+                // Finish hash for partial AAD block
+                if (atBlockPos > 0)
+                {
+                    gHASHPartial(S_at, atBlock, 0, atBlockPos);
+                }
+
+                // Find the difference between the AAD hashes
+                if (atLengthPre > 0)
+                {
+                    GcmUtilities.Xor(S_at, S_atPre);
+                }
+
+                // Number of cipher-text blocks produced
+                long c = (long)(((totalLength * 8) + 127) >> 7);
+
+                // Calculate the adjustment factor
+                byte[] H_c = new byte[16];
+                if (exp == null)
+                {
+                    exp = new Tables1kGcmExponentiator();
+                    exp.Init(H);
+                }
+                exp.ExponentiateX(c, H_c);
+
+                // Carry the difference forward
+                GcmUtilities.Multiply(S_at, H_c);
+
+                // Adjust the current hash
+                GcmUtilities.Xor(S, S_at);
+            }
+
+            // Final gHASH
+            byte[] X = new byte[BlockSize];
+            Pack.UInt64_To_BE(atLength * 8UL, X, 0);
+            Pack.UInt64_To_BE(totalLength * 8UL, X, 8);
+
+            gHASHBlock(S, X);
+
+            // T = MSBt(GCTRk(J0,S))
+            byte[] tag = new byte[BlockSize];
+            cipher.ProcessBlock(J0, 0, tag, 0);
+            GcmUtilities.Xor(tag, S);
+
+            int resultLen = extra;
+
+            // We place into macBlock our calculated value for T
+            this.macBlock = new byte[macSize];
+            Array.Copy(tag, 0, macBlock, 0, macSize);
+
+            if (forEncryption)
+            {
+                // Append T to the message
+                Array.Copy(macBlock, 0, output, outOff + bufOff, macSize);
+                resultLen += macSize;
+            }
+            else
+            {
+                // Retrieve the T value from the message and compare to calculated one
+                byte[] msgMac = new byte[macSize];
+                Array.Copy(bufBlock, extra, msgMac, 0, macSize);
+                if (!Arrays.ConstantTimeAreEqual(this.macBlock, msgMac))
+                    throw new InvalidCipherTextException("mac check in GCM failed");
+            }
+
+            Reset(false);
+
+            return resultLen;
+        }
+
+        public virtual void Reset()
+        {
+            Reset(true);
+        }
+
+        private void Reset(
+            bool clearMac)
+        {
+            cipher.Reset();
+
+            S = new byte[BlockSize];
+            S_at = new byte[BlockSize];
+            S_atPre = new byte[BlockSize];
+            atBlock = new byte[BlockSize];
+            atBlockPos = 0;
+            atLength = 0;
+            atLengthPre = 0;
+            counter = Arrays.Clone(J0);
+            bufOff = 0;
+            totalLength = 0;
+
+            if (bufBlock != null)
+            {
+                Arrays.Fill(bufBlock, 0);
+            }
+
+            if (clearMac)
+            {
+                macBlock = null;
+            }
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+        }
+
+        private void gCTRBlock(byte[] block, byte[] output, int outOff)
+        {
+            byte[] tmp = GetNextCounterBlock();
+
+            GcmUtilities.Xor(tmp, block);
+            Array.Copy(tmp, 0, output, outOff, BlockSize);
+
+            gHASHBlock(S, forEncryption ? tmp : block);
+
+            totalLength += BlockSize;
+        }
+
+        private void gCTRPartial(byte[] buf, int off, int len, byte[] output, int outOff)
+        {
+            byte[] tmp = GetNextCounterBlock();
+
+            GcmUtilities.Xor(tmp, buf, off, len);
+            Array.Copy(tmp, 0, output, outOff, len);
+
+            gHASHPartial(S, forEncryption ? tmp : buf, 0, len);
+
+            totalLength += (uint)len;
+        }
+
+        private void gHASH(byte[] Y, byte[] b, int len)
+        {
+            for (int pos = 0; pos < len; pos += BlockSize)
+            {
+                int num = System.Math.Min(len - pos, BlockSize);
+                gHASHPartial(Y, b, pos, num);
+            }
+        }
+
+        private void gHASHBlock(byte[] Y, byte[] b)
+        {
+            GcmUtilities.Xor(Y, b);
+            multiplier.MultiplyH(Y);
+        }
+
+        private void gHASHPartial(byte[] Y, byte[] b, int off, int len)
+        {
+            GcmUtilities.Xor(Y, b, off, len);
+            multiplier.MultiplyH(Y);
+        }
+
+        private byte[] GetNextCounterBlock()
+        {
+            for (int i = 15; i >= 12; --i)
+            {
+                if (++counter[i] != 0) break;
+            }
+
+            byte[] tmp = new byte[BlockSize];
+            // TODO Sure would be nice if ciphers could operate on int[]
+            cipher.ProcessBlock(counter, 0, tmp, 0);
+            return tmp;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/GOFBBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/GOFBBlockCipher.cs
new file mode 100644
index 0000000..a915625
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/GOFBBlockCipher.cs
@@ -0,0 +1,227 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+	/**
+	* implements the GOST 28147 OFB counter mode (GCTR).
+	*/
+	public class GOfbBlockCipher
+		: IBlockCipher
+	{
+		private byte[]	IV;
+		private byte[]	ofbV;
+		private byte[]	ofbOutV;
+
+		private readonly int			blockSize;
+		private readonly IBlockCipher	cipher;
+
+		bool firstStep = true;
+		int N3;
+		int N4;
+		const int C1 = 16843012; //00000001000000010000000100000100
+		const int C2 = 16843009; //00000001000000010000000100000001
+
+		/**
+		* Basic constructor.
+		*
+		* @param cipher the block cipher to be used as the basis of the
+		* counter mode (must have a 64 bit block size).
+		*/
+		public GOfbBlockCipher(
+			IBlockCipher cipher)
+		{
+			this.cipher = cipher;
+			this.blockSize = cipher.GetBlockSize();
+
+			if (blockSize != 8)
+			{
+				throw new ArgumentException("GCTR only for 64 bit block ciphers");
+			}
+
+			this.IV = new byte[cipher.GetBlockSize()];
+			this.ofbV = new byte[cipher.GetBlockSize()];
+			this.ofbOutV = new byte[cipher.GetBlockSize()];
+		}
+
+		/**
+		* return the underlying block cipher that we are wrapping.
+		*
+		* @return the underlying block cipher that we are wrapping.
+		*/
+		public IBlockCipher GetUnderlyingCipher()
+		{
+			return cipher;
+		}
+
+		/**
+		* Initialise the cipher and, possibly, the initialisation vector (IV).
+		* If an IV isn't passed as part of the parameter, the IV will be all zeros.
+		* An IV which is too short is handled in FIPS compliant fashion.
+		*
+		* @param encrypting if true the cipher is initialised for
+		*  encryption, if false for decryption.
+		* @param parameters the key and other data required by the cipher.
+		* @exception ArgumentException if the parameters argument is inappropriate.
+		*/
+		public void Init(
+			bool				forEncryption, //ignored by this CTR mode
+			ICipherParameters	parameters)
+		{
+			firstStep = true;
+			N3 = 0;
+			N4 = 0;
+
+			if (parameters is ParametersWithIV)
+			{
+				ParametersWithIV ivParam = (ParametersWithIV)parameters;
+				byte[]      iv = ivParam.GetIV();
+
+				if (iv.Length < IV.Length)
+				{
+					// prepend the supplied IV with zeros (per FIPS PUB 81)
+					Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length);
+					for (int i = 0; i < IV.Length - iv.Length; i++)
+					{
+						IV[i] = 0;
+					}
+				}
+				else
+				{
+					Array.Copy(iv, 0, IV, 0, IV.Length);
+				}
+
+				parameters = ivParam.Parameters;
+			}
+
+			Reset();
+
+            // if it's null, key is to be reused.
+            if (parameters != null)
+            {
+                cipher.Init(true, parameters);
+            }
+		}
+
+		/**
+		* return the algorithm name and mode.
+		*
+		* @return the name of the underlying algorithm followed by "/GCTR"
+		* and the block size in bits
+		*/
+		public string AlgorithmName
+		{
+			get { return cipher.AlgorithmName + "/GCTR"; }
+		}
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		/**
+		* return the block size we are operating at (in bytes).
+		*
+		* @return the block size we are operating at (in bytes).
+		*/
+		public int GetBlockSize()
+		{
+			return blockSize;
+		}
+
+		/**
+		* Process one block of input from the array in and write it to
+		* the out array.
+		*
+		* @param in the array containing the input data.
+		* @param inOff offset into the in array the data starts at.
+		* @param out the array the output data will be copied into.
+		* @param outOff the offset into the out array the output will start at.
+		* @exception DataLengthException if there isn't enough data in in, or
+		* space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		* @return the number of bytes processed and produced.
+		*/
+		public int ProcessBlock(
+			byte[]	input,
+			int		inOff,
+			byte[]	output,
+			int		outOff)
+		{
+			if ((inOff + blockSize) > input.Length)
+			{
+				throw new DataLengthException("input buffer too short");
+			}
+
+			if ((outOff + blockSize) > output.Length)
+			{
+				throw new DataLengthException("output buffer too short");
+			}
+
+			if (firstStep)
+			{
+				firstStep = false;
+				cipher.ProcessBlock(ofbV, 0, ofbOutV, 0);
+				N3 = bytesToint(ofbOutV, 0);
+				N4 = bytesToint(ofbOutV, 4);
+			}
+			N3 += C2;
+			N4 += C1;
+			intTobytes(N3, ofbV, 0);
+			intTobytes(N4, ofbV, 4);
+
+			cipher.ProcessBlock(ofbV, 0, ofbOutV, 0);
+
+			//
+			// XOR the ofbV with the plaintext producing the cipher text (and
+			// the next input block).
+			//
+			for (int i = 0; i < blockSize; i++)
+			{
+				output[outOff + i] = (byte)(ofbOutV[i] ^ input[inOff + i]);
+			}
+
+			//
+			// change over the input block.
+			//
+			Array.Copy(ofbV, blockSize, ofbV, 0, ofbV.Length - blockSize);
+			Array.Copy(ofbOutV, 0, ofbV, ofbV.Length - blockSize, blockSize);
+
+			return blockSize;
+		}
+
+		/**
+		* reset the feedback vector back to the IV and reset the underlying
+		* cipher.
+		*/
+		public void Reset()
+		{
+			Array.Copy(IV, 0, ofbV, 0, IV.Length);
+
+			cipher.Reset();
+		}
+
+		//array of bytes to type int
+		private int bytesToint(
+			byte[]  inBytes,
+			int     inOff)
+		{
+			return  (int)((inBytes[inOff + 3] << 24) & 0xff000000) + ((inBytes[inOff + 2] << 16) & 0xff0000) +
+					((inBytes[inOff + 1] << 8) & 0xff00) + (inBytes[inOff] & 0xff);
+		}
+
+		//int to array of bytes
+		private void intTobytes(
+				int     num,
+				byte[]  outBytes,
+				int     outOff)
+		{
+				outBytes[outOff + 3] = (byte)(num >> 24);
+				outBytes[outOff + 2] = (byte)(num >> 16);
+				outBytes[outOff + 1] = (byte)(num >> 8);
+				outBytes[outOff] =     (byte)num;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/IAeadBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/IAeadBlockCipher.cs
new file mode 100644
index 0000000..52c4ff4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/IAeadBlockCipher.cs
@@ -0,0 +1,105 @@
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+	/// <summary>
+	/// A block cipher mode that includes authenticated encryption with a streaming mode
+	/// and optional associated data.</summary>
+	/// <see cref="AeadParameters"/>
+	public interface IAeadBlockCipher
+	{
+		/// <summary>The name of the algorithm this cipher implements.</summary>
+		string AlgorithmName { get; }
+
+		/// <summary>The block cipher underlying this algorithm.</summary>
+		IBlockCipher GetUnderlyingCipher();
+
+		/// <summary>Initialise the cipher.</summary>
+		/// <remarks>Parameter can either be an AeadParameters or a ParametersWithIV object.</remarks>
+		/// <param name="forEncryption">Initialise for encryption if true, for decryption if false.</param>
+		/// <param name="parameters">The key or other data required by the cipher.</param>
+		void Init(bool forEncryption, ICipherParameters parameters);
+
+		/// <returns>The block size for this cipher, in bytes.</returns>
+		int GetBlockSize();
+
+        /// <summary>Add a single byte to the associated data check.</summary>
+		/// <remarks>If the implementation supports it, this will be an online operation and will not retain the associated data.</remarks>
+        /// <param name="input">The byte to be processed.</param>
+        void ProcessAadByte(byte input);
+
+        /// <summary>Add a sequence of bytes to the associated data check.</summary>
+		/// <remarks>If the implementation supports it, this will be an online operation and will not retain the associated data.</remarks>
+        /// <param name="inBytes">The input byte array.</param>
+        /// <param name="inOff">The offset into the input array where the data to be processed starts.</param>
+        /// <param name="len">The number of bytes to be processed.</param>
+        void ProcessAadBytes(byte[] inBytes, int inOff, int len);
+
+        /**
+		* Encrypt/decrypt a single byte.
+		*
+		* @param input the byte to be processed.
+		* @param outBytes the output buffer the processed byte goes into.
+		* @param outOff the offset into the output byte array the processed data starts at.
+		* @return the number of bytes written to out.
+		* @exception DataLengthException if the output buffer is too small.
+		*/
+		int ProcessByte(byte input, byte[] outBytes, int outOff);
+
+		/**
+		* Process a block of bytes from in putting the result into out.
+		*
+		* @param inBytes the input byte array.
+		* @param inOff the offset into the in array where the data to be processed starts.
+		* @param len the number of bytes to be processed.
+		* @param outBytes the output buffer the processed bytes go into.
+		* @param outOff the offset into the output byte array the processed data starts at.
+		* @return the number of bytes written to out.
+		* @exception DataLengthException if the output buffer is too small.
+		*/
+		int ProcessBytes(byte[] inBytes, int inOff, int len, byte[] outBytes, int outOff);
+
+		/**
+		* Finish the operation either appending or verifying the MAC at the end of the data.
+		*
+		* @param outBytes space for any resulting output data.
+		* @param outOff offset into out to start copying the data at.
+		* @return number of bytes written into out.
+		* @throws InvalidOperationException if the cipher is in an inappropriate state.
+		* @throws InvalidCipherTextException if the MAC fails to match.
+		*/
+		int DoFinal(byte[] outBytes, int outOff);
+
+		/**
+		* Return the value of the MAC associated with the last stream processed.
+		*
+		* @return MAC for plaintext data.
+		*/
+		byte[] GetMac();
+
+		/**
+		* Return the size of the output buffer required for a ProcessBytes
+		* an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to ProcessBytes
+		* with len bytes of input.
+		*/
+		int GetUpdateOutputSize(int len);
+
+		/**
+		* Return the size of the output buffer required for a ProcessBytes plus a
+		* DoFinal with an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to ProcessBytes and DoFinal
+		* with len bytes of input.
+		*/
+		int GetOutputSize(int len);
+
+		/// <summary>
+		/// Reset the cipher to the same state as it was after the last init (if there was one).
+		/// </summary>
+		void Reset();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/OCBBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/OCBBlockCipher.cs
new file mode 100644
index 0000000..54359df
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/OCBBlockCipher.cs
@@ -0,0 +1,558 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+     * An implementation of <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
+     * Authenticated-Encryption Algorithm</a>, licensed per:
+     * 
+     * <blockquote><p><a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
+     * Open-Source Software Implementations of OCB</a> (Jan 9, 2013) - 'License 1'<br/>
+     * Under this license, you are authorized to make, use, and distribute open-source software
+     * implementations of OCB. This license terminates for you if you sue someone over their open-source
+     * software implementation of OCB claiming that you have a patent covering their implementation.
+     * </p><p>
+     * This is a non-binding summary of a legal document (the link above). The parameters of the license
+     * are specified in the license document and that document is controlling.</p></blockquote>
+     */
+    public class OcbBlockCipher
+        : IAeadBlockCipher
+    {
+        private const int BLOCK_SIZE = 16;
+
+        private readonly IBlockCipher hashCipher;
+        private readonly IBlockCipher mainCipher;
+
+        /*
+         * CONFIGURATION
+         */
+        private bool forEncryption;
+        private int macSize;
+        private byte[] initialAssociatedText;
+
+        /*
+         * KEY-DEPENDENT
+         */
+        // NOTE: elements are lazily calculated
+        private IList L;
+        private byte[] L_Asterisk, L_Dollar;
+
+        /*
+         * NONCE-DEPENDENT
+         */
+        private byte[] KtopInput = null;
+        private byte[] Stretch = new byte[24];
+        private byte[] OffsetMAIN_0 = new byte[16];
+
+        /*
+         * PER-ENCRYPTION/DECRYPTION
+         */
+        private byte[] hashBlock, mainBlock;
+        private int hashBlockPos, mainBlockPos;
+        private long hashBlockCount, mainBlockCount;
+        private byte[] OffsetHASH;
+        private byte[] Sum;
+        private byte[] OffsetMAIN = new byte[16];
+        private byte[] Checksum;
+
+        // NOTE: The MAC value is preserved after doFinal
+        private byte[] macBlock;
+
+        public OcbBlockCipher(IBlockCipher hashCipher, IBlockCipher mainCipher)
+        {
+            if (hashCipher == null)
+                throw new ArgumentNullException("hashCipher");
+            if (hashCipher.GetBlockSize() != BLOCK_SIZE)
+                throw new ArgumentException("must have a block size of " + BLOCK_SIZE, "hashCipher");
+            if (mainCipher == null)
+                throw new ArgumentNullException("mainCipher");
+            if (mainCipher.GetBlockSize() != BLOCK_SIZE)
+                throw new ArgumentException("must have a block size of " + BLOCK_SIZE, "mainCipher");
+
+            if (!hashCipher.AlgorithmName.Equals(mainCipher.AlgorithmName))
+                throw new ArgumentException("'hashCipher' and 'mainCipher' must be the same algorithm");
+
+            this.hashCipher = hashCipher;
+            this.mainCipher = mainCipher;
+        }
+
+        public virtual IBlockCipher GetUnderlyingCipher()
+        {
+            return mainCipher;
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return mainCipher.AlgorithmName + "/OCB"; }
+        }
+
+        public virtual void Init(bool forEncryption, ICipherParameters parameters)
+        {
+            bool oldForEncryption = this.forEncryption;
+            this.forEncryption = forEncryption;
+            this.macBlock = null;
+
+            KeyParameter keyParameter;
+
+            byte[] N;
+            if (parameters is AeadParameters)
+            {
+                AeadParameters aeadParameters = (AeadParameters) parameters;
+
+                N = aeadParameters.GetNonce();
+                initialAssociatedText = aeadParameters.GetAssociatedText();
+
+                int macSizeBits = aeadParameters.MacSize;
+                if (macSizeBits < 64 || macSizeBits > 128 || macSizeBits % 8 != 0)
+                    throw new ArgumentException("Invalid value for MAC size: " + macSizeBits);
+
+                macSize = macSizeBits / 8;
+                keyParameter = aeadParameters.Key;
+            }
+            else if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV parametersWithIV = (ParametersWithIV) parameters;
+
+                N = parametersWithIV.GetIV();
+                initialAssociatedText = null;
+                macSize = 16;
+                keyParameter = (KeyParameter) parametersWithIV.Parameters;
+            }
+            else
+            {
+                throw new ArgumentException("invalid parameters passed to OCB");
+            }
+
+            this.hashBlock = new byte[16];
+            this.mainBlock = new byte[forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize)];
+
+            if (N == null)
+            {
+                N = new byte[0];
+            }
+
+            if (N.Length > 15)
+            {
+                throw new ArgumentException("IV must be no more than 15 bytes");
+            }
+
+            /*
+             * KEY-DEPENDENT INITIALISATION
+             */
+
+            if (keyParameter != null)
+            {
+                // hashCipher always used in forward mode
+                hashCipher.Init(true, keyParameter);
+                mainCipher.Init(forEncryption, keyParameter);
+                KtopInput = null;
+            }
+            else if (oldForEncryption != forEncryption)
+            {
+                throw new ArgumentException("cannot change encrypting state without providing key.");
+            }
+
+            this.L_Asterisk = new byte[16];
+            hashCipher.ProcessBlock(L_Asterisk, 0, L_Asterisk, 0);
+
+            this.L_Dollar = OCB_double(L_Asterisk);
+
+            this.L = Platform.CreateArrayList();
+            this.L.Add(OCB_double(L_Dollar));
+
+            /*
+             * NONCE-DEPENDENT AND PER-ENCRYPTION/DECRYPTION INITIALISATION
+             */
+
+            int bottom = ProcessNonce(N);
+
+            int bits = bottom % 8, bytes = bottom / 8;
+            if (bits == 0)
+            {
+                Array.Copy(Stretch, bytes, OffsetMAIN_0, 0, 16);
+            }
+            else
+            {
+                for (int i = 0; i < 16; ++i)
+                {
+                    uint b1 = Stretch[bytes];
+                    uint b2 = Stretch[++bytes];
+                    this.OffsetMAIN_0[i] = (byte) ((b1 << bits) | (b2 >> (8 - bits)));
+                }
+            }
+
+            this.hashBlockPos = 0;
+            this.mainBlockPos = 0;
+
+            this.hashBlockCount = 0;
+            this.mainBlockCount = 0;
+
+            this.OffsetHASH = new byte[16];
+            this.Sum = new byte[16];
+            Array.Copy(OffsetMAIN_0, 0, OffsetMAIN, 0, 16);
+            this.Checksum = new byte[16];
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+        }
+
+        protected virtual int ProcessNonce(byte[] N)
+        {
+            byte[] nonce = new byte[16];
+            Array.Copy(N, 0, nonce, nonce.Length - N.Length, N.Length);
+            nonce[0] = (byte)(macSize << 4);
+            nonce[15 - N.Length] |= 1;
+
+            int bottom = nonce[15] & 0x3F;
+            nonce[15] &= 0xC0;
+
+            /*
+             * When used with incrementing nonces, the cipher is only applied once every 64 inits.
+             */
+            if (KtopInput == null || !Arrays.AreEqual(nonce, KtopInput))
+            {
+                byte[] Ktop = new byte[16];
+                KtopInput = nonce;
+                hashCipher.ProcessBlock(KtopInput, 0, Ktop, 0);
+                Array.Copy(Ktop, 0, Stretch, 0, 16);
+                for (int i = 0; i < 8; ++i)
+                {
+                    Stretch[16 + i] = (byte)(Ktop[i] ^ Ktop[i + 1]);
+                }
+            }
+
+            return bottom;
+        }
+
+        public virtual int GetBlockSize()
+        {
+            return BLOCK_SIZE;
+        }
+
+        public virtual byte[] GetMac()
+        {
+            return Arrays.Clone(macBlock);
+        }
+
+        public virtual int GetOutputSize(int len)
+        {
+            int totalData = len + mainBlockPos;
+            if (forEncryption)
+            {
+                return totalData + macSize;
+            }
+            return totalData < macSize ? 0 : totalData - macSize;
+        }
+
+        public virtual int GetUpdateOutputSize(int len)
+        {
+            int totalData = len + mainBlockPos;
+            if (!forEncryption)
+            {
+                if (totalData < macSize)
+                {
+                    return 0;
+                }
+                totalData -= macSize;
+            }
+            return totalData - totalData % BLOCK_SIZE;
+        }
+
+        public virtual void ProcessAadByte(byte input)
+        {
+            hashBlock[hashBlockPos] = input;
+            if (++hashBlockPos == hashBlock.Length)
+            {
+                ProcessHashBlock();
+            }
+        }
+
+        public virtual void ProcessAadBytes(byte[] input, int off, int len)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                hashBlock[hashBlockPos] = input[off + i];
+                if (++hashBlockPos == hashBlock.Length)
+                {
+                    ProcessHashBlock();
+                }
+            }
+        }
+
+        public virtual int ProcessByte(byte input, byte[] output, int outOff)
+        {
+            mainBlock[mainBlockPos] = input;
+            if (++mainBlockPos == mainBlock.Length)
+            {
+                ProcessMainBlock(output, outOff);
+                return BLOCK_SIZE;
+            }
+            return 0;
+        }
+
+        public virtual int ProcessBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
+        {
+            int resultLen = 0;
+
+            for (int i = 0; i < len; ++i)
+            {
+                mainBlock[mainBlockPos] = input[inOff + i];
+                if (++mainBlockPos == mainBlock.Length)
+                {
+                    ProcessMainBlock(output, outOff + resultLen);
+                    resultLen += BLOCK_SIZE;
+                }
+            }
+
+            return resultLen;
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            /*
+             * For decryption, get the tag from the end of the message
+             */
+            byte[] tag = null;
+            if (!forEncryption) {
+                if (mainBlockPos < macSize)
+                    throw new InvalidCipherTextException("data too short");
+
+                mainBlockPos -= macSize;
+                tag = new byte[macSize];
+                Array.Copy(mainBlock, mainBlockPos, tag, 0, macSize);
+            }
+
+            /*
+             * HASH: Process any final partial block; compute final hash value
+             */
+            if (hashBlockPos > 0)
+            {
+                OCB_extend(hashBlock, hashBlockPos);
+                UpdateHASH(L_Asterisk);
+            }
+
+            /*
+             * OCB-ENCRYPT/OCB-DECRYPT: Process any final partial block
+             */
+            if (mainBlockPos > 0)
+            {
+                if (forEncryption)
+                {
+                    OCB_extend(mainBlock, mainBlockPos);
+                    Xor(Checksum, mainBlock);
+                }
+
+                Xor(OffsetMAIN, L_Asterisk);
+
+                byte[] Pad = new byte[16];
+                hashCipher.ProcessBlock(OffsetMAIN, 0, Pad, 0);
+
+                Xor(mainBlock, Pad);
+
+                Array.Copy(mainBlock, 0, output, outOff, mainBlockPos);
+
+                if (!forEncryption)
+                {
+                    OCB_extend(mainBlock, mainBlockPos);
+                    Xor(Checksum, mainBlock);
+                }
+            }
+
+            /*
+             * OCB-ENCRYPT/OCB-DECRYPT: Compute raw tag
+             */
+            Xor(Checksum, OffsetMAIN);
+            Xor(Checksum, L_Dollar);
+            hashCipher.ProcessBlock(Checksum, 0, Checksum, 0);
+            Xor(Checksum, Sum);
+
+            this.macBlock = new byte[macSize];
+            Array.Copy(Checksum, 0, macBlock, 0, macSize);
+
+            /*
+             * Validate or append tag and reset this cipher for the next run
+             */
+            int resultLen = mainBlockPos;
+
+            if (forEncryption)
+            {
+                // Append tag to the message
+                Array.Copy(macBlock, 0, output, outOff + resultLen, macSize);
+                resultLen += macSize;
+            }
+            else
+            {
+                // Compare the tag from the message with the calculated one
+                if (!Arrays.ConstantTimeAreEqual(macBlock, tag))
+                    throw new InvalidCipherTextException("mac check in OCB failed");
+            }
+
+            Reset(false);
+
+            return resultLen;
+        }
+
+        public virtual void Reset()
+        {
+            Reset(true);
+        }
+
+        protected virtual void Clear(byte[] bs)
+        {
+            if (bs != null)
+            {
+                Array.Clear(bs, 0, bs.Length);
+            }
+        }
+
+        protected virtual byte[] GetLSub(int n)
+        {
+            while (n >= L.Count)
+            {
+                L.Add(OCB_double((byte[]) L[L.Count - 1]));
+            }
+            return (byte[])L[n];
+        }
+
+        protected virtual void ProcessHashBlock()
+        {
+            /*
+             * HASH: Process any whole blocks
+             */
+            UpdateHASH(GetLSub(OCB_ntz(++hashBlockCount)));
+            hashBlockPos = 0;
+        }
+
+        protected virtual void ProcessMainBlock(byte[] output, int outOff)
+        {
+            /*
+             * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks
+             */
+
+            if (forEncryption)
+            {
+                Xor(Checksum, mainBlock);
+                mainBlockPos = 0;
+            }
+
+            Xor(OffsetMAIN, GetLSub(OCB_ntz(++mainBlockCount)));
+
+            Xor(mainBlock, OffsetMAIN);
+            mainCipher.ProcessBlock(mainBlock, 0, mainBlock, 0);
+            Xor(mainBlock, OffsetMAIN);
+
+            Array.Copy(mainBlock, 0, output, outOff, 16);
+
+            if (!forEncryption)
+            {
+                Xor(Checksum, mainBlock);
+                Array.Copy(mainBlock, BLOCK_SIZE, mainBlock, 0, macSize);
+                mainBlockPos = macSize;
+            }
+        }
+
+        protected virtual void Reset(bool clearMac)
+        {
+            hashCipher.Reset();
+            mainCipher.Reset();
+
+            Clear(hashBlock);
+            Clear(mainBlock);
+
+            hashBlockPos = 0;
+            mainBlockPos = 0;
+
+            hashBlockCount = 0;
+            mainBlockCount = 0;
+
+            Clear(OffsetHASH);
+            Clear(Sum);
+            Array.Copy(OffsetMAIN_0, 0, OffsetMAIN, 0, 16);
+            Clear(Checksum);
+
+            if (clearMac)
+            {
+                macBlock = null;
+            }
+
+            if (initialAssociatedText != null)
+            {
+                ProcessAadBytes(initialAssociatedText, 0, initialAssociatedText.Length);
+            }
+        }
+
+        protected virtual void UpdateHASH(byte[] LSub)
+        {
+            Xor(OffsetHASH, LSub);
+            Xor(hashBlock, OffsetHASH);
+            hashCipher.ProcessBlock(hashBlock, 0, hashBlock, 0);
+            Xor(Sum, hashBlock);
+        }
+
+        protected static byte[] OCB_double(byte[] block)
+        {
+            byte[] result = new byte[16];
+            int carry = ShiftLeft(block, result);
+
+            /*
+             * NOTE: This construction is an attempt at a constant-time implementation.
+             */
+            result[15] ^= (byte)(0x87 >> ((1 - carry) << 3));
+
+            return result;
+        }
+
+        protected static void OCB_extend(byte[] block, int pos)
+        {
+            block[pos] = (byte) 0x80;
+            while (++pos < 16)
+            {
+                block[pos] = 0;
+            }
+        }
+
+        protected static int OCB_ntz(long x)
+        {
+            if (x == 0)
+            {
+                return 64;
+            }
+
+            int n = 0;
+            ulong ux = (ulong)x;
+            while ((ux & 1UL) == 0UL)
+            {
+                ++n;
+                ux >>= 1;
+            }
+            return n;
+        }
+
+        protected static int ShiftLeft(byte[] block, byte[] output)
+        {
+            int i = 16;
+            uint bit = 0;
+            while (--i >= 0)
+            {
+                uint b = block[i];
+                output[i] = (byte) ((b << 1) | bit);
+                bit = (b >> 7) & 1;
+            }
+            return (int)bit;
+        }
+
+        protected static void Xor(byte[] block, byte[] val)
+        {
+            for (int i = 15; i >= 0; --i)
+            {
+                block[i] ^= val[i];
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/OfbBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/OfbBlockCipher.cs
new file mode 100644
index 0000000..a99f8c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/OfbBlockCipher.cs
@@ -0,0 +1,182 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * implements a Output-FeedBack (OFB) mode on top of a simple cipher.
+    */
+    public class OfbBlockCipher
+		: IBlockCipher
+    {
+        private byte[]	IV;
+        private byte[]	ofbV;
+        private byte[]	ofbOutV;
+
+        private readonly int			blockSize;
+        private readonly IBlockCipher	cipher;
+
+        /**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used as the basis of the
+        * feedback mode.
+        * @param blockSize the block size in bits (note: a multiple of 8)
+        */
+        public OfbBlockCipher(
+            IBlockCipher cipher,
+            int         blockSize)
+        {
+            this.cipher = cipher;
+            this.blockSize = blockSize / 8;
+
+            this.IV = new byte[cipher.GetBlockSize()];
+            this.ofbV = new byte[cipher.GetBlockSize()];
+            this.ofbOutV = new byte[cipher.GetBlockSize()];
+        }
+
+        /**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+        /**
+        * Initialise the cipher and, possibly, the initialisation vector (IV).
+        * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+        * An IV which is too short is handled in FIPS compliant fashion.
+        *
+        * @param forEncryption if true the cipher is initialised for
+        *  encryption, if false for decryption.
+        * @param param the key and other data required by the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool				forEncryption, //ignored by this OFB mode
+            ICipherParameters	parameters)
+        {
+			if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV)parameters;
+                byte[] iv = ivParam.GetIV();
+
+                if (iv.Length < IV.Length)
+                {
+                    // prepend the supplied IV with zeros (per FIPS PUB 81)
+                    Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length);
+                    for (int i = 0; i < IV.Length - iv.Length; i++)
+                    {
+                        IV[i] = 0;
+                    }
+                }
+                else
+                {
+                    Array.Copy(iv, 0, IV, 0, IV.Length);
+                }
+
+				parameters = ivParam.Parameters;
+            }
+
+			Reset();
+
+            // if it's null, key is to be reused.
+            if (parameters != null)
+            {
+                cipher.Init(true, parameters);
+            }
+        }
+
+        /**
+        * return the algorithm name and mode.
+        *
+        * @return the name of the underlying algorithm followed by "/OFB"
+        * and the block size in bits
+        */
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/OFB" + (blockSize * 8); }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		/**
+        * return the block size we are operating at (in bytes).
+        *
+        * @return the block size we are operating at (in bytes).
+        */
+        public int GetBlockSize()
+        {
+            return blockSize;
+        }
+
+        /**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + blockSize) > output.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            cipher.ProcessBlock(ofbV, 0, ofbOutV, 0);
+
+            //
+            // XOR the ofbV with the plaintext producing the cipher text (and
+            // the next input block).
+            //
+            for (int i = 0; i < blockSize; i++)
+            {
+                output[outOff + i] = (byte)(ofbOutV[i] ^ input[inOff + i]);
+            }
+
+            //
+            // change over the input block.
+            //
+            Array.Copy(ofbV, blockSize, ofbV, 0, ofbV.Length - blockSize);
+            Array.Copy(ofbOutV, 0, ofbV, ofbV.Length - blockSize, blockSize);
+
+            return blockSize;
+        }
+
+        /**
+        * reset the feedback vector back to the IV and reset the underlying
+        * cipher.
+        */
+        public void Reset()
+        {
+            Array.Copy(IV, 0, ofbV, 0, IV.Length);
+
+            cipher.Reset();
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/OpenPgpCfbBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/OpenPgpCfbBlockCipher.cs
new file mode 100644
index 0000000..038ca78
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/OpenPgpCfbBlockCipher.cs
@@ -0,0 +1,337 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * Implements OpenPGP's rather strange version of Cipher-FeedBack (CFB) mode
+    * on top of a simple cipher. This class assumes the IV has been prepended
+    * to the data stream already, and just accomodates the reset after
+    * (blockSize + 2) bytes have been read.
+    * <p>
+    * For further info see <a href="http://www.ietf.org/rfc/rfc2440.html">RFC 2440</a>.
+	* </p>
+    */
+    public class OpenPgpCfbBlockCipher
+        : IBlockCipher
+    {
+        private byte[] IV;
+        private byte[] FR;
+        private byte[] FRE;
+
+		private readonly IBlockCipher cipher;
+		private readonly int blockSize;
+
+		private int count;
+        private bool forEncryption;
+
+		/**
+        * Basic constructor.
+        *
+        * @param cipher the block cipher to be used as the basis of the
+        * feedback mode.
+        */
+        public OpenPgpCfbBlockCipher(
+            IBlockCipher cipher)
+        {
+            this.cipher = cipher;
+
+            this.blockSize = cipher.GetBlockSize();
+            this.IV = new byte[blockSize];
+            this.FR = new byte[blockSize];
+            this.FRE = new byte[blockSize];
+        }
+
+		/**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+		/**
+        * return the algorithm name and mode.
+        *
+        * @return the name of the underlying algorithm followed by "/PGPCFB"
+        * and the block size in bits.
+        */
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/OpenPGPCFB"; }
+        }
+
+		public bool IsPartialBlockOkay
+		{
+			get { return true; }
+		}
+
+		/**
+        * return the block size we are operating at.
+        *
+        * @return the block size we are operating at (in bytes).
+        */
+        public int GetBlockSize()
+        {
+            return cipher.GetBlockSize();
+        }
+
+		/**
+        * Process one block of input from the array in and write it to
+        * the out array.
+        *
+        * @param in the array containing the input data.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the output data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            return (forEncryption) ? EncryptBlock(input, inOff, output, outOff) : DecryptBlock(input, inOff, output, outOff);
+        }
+
+		/**
+        * reset the chaining vector back to the IV and reset the underlying
+        * cipher.
+        */
+        public void Reset()
+        {
+            count = 0;
+
+			Array.Copy(IV, 0, FR, 0, FR.Length);
+
+			cipher.Reset();
+        }
+
+        /**
+        * Initialise the cipher and, possibly, the initialisation vector (IV).
+        * If an IV isn't passed as part of the parameter, the IV will be all zeros.
+        * An IV which is too short is handled in FIPS compliant fashion.
+        *
+        * @param forEncryption if true the cipher is initialised for
+        *  encryption, if false for decryption.
+        * @param parameters the key and other data required by the cipher.
+        * @exception ArgumentException if the parameters argument is
+        * inappropriate.
+        */
+        public void Init(
+            bool forEncryption,
+            ICipherParameters parameters)
+        {
+            this.forEncryption = forEncryption;
+
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV)parameters;
+                byte[] iv = ivParam.GetIV();
+
+                if (iv.Length < IV.Length)
+                {
+                    // prepend the supplied IV with zeros (per FIPS PUB 81)
+                    Array.Copy(iv, 0, IV, IV.Length - iv.Length, iv.Length);
+                    for (int i = 0; i < IV.Length - iv.Length; i++)
+                    {
+                        IV[i] = 0;
+                    }
+                }
+                else
+                {
+                    Array.Copy(iv, 0, IV, 0, IV.Length);
+                }
+
+                parameters = ivParam.Parameters;
+            }
+
+            Reset();
+
+            cipher.Init(true, parameters);
+        }
+
+		/**
+        * Encrypt one byte of data according to CFB mode.
+        * @param data the byte to encrypt
+        * @param blockOff offset in the current block
+        * @returns the encrypted byte
+        */
+        private byte EncryptByte(byte data, int blockOff)
+        {
+            return (byte)(FRE[blockOff] ^ data);
+        }
+
+		/**
+        * Do the appropriate processing for CFB IV mode encryption.
+        *
+        * @param in the array containing the data to be encrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the encrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        private int EncryptBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + blockSize) > outBytes.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            if (count > blockSize)
+            {
+                FR[blockSize - 2] = outBytes[outOff] = EncryptByte(input[inOff], blockSize - 2);
+                FR[blockSize - 1] = outBytes[outOff + 1] = EncryptByte(input[inOff + 1], blockSize - 1);
+
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                for (int n = 2; n < blockSize; n++)
+                {
+					FR[n - 2] = outBytes[outOff + n] = EncryptByte(input[inOff + n], n - 2);
+                }
+            }
+            else if (count == 0)
+            {
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+				for (int n = 0; n < blockSize; n++)
+                {
+					FR[n] = outBytes[outOff + n] = EncryptByte(input[inOff + n], n);
+                }
+
+				count += blockSize;
+            }
+            else if (count == blockSize)
+            {
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                outBytes[outOff] = EncryptByte(input[inOff], 0);
+                outBytes[outOff + 1] = EncryptByte(input[inOff + 1], 1);
+
+                //
+                // do reset
+                //
+                Array.Copy(FR, 2, FR, 0, blockSize - 2);
+                Array.Copy(outBytes, outOff, FR, blockSize - 2, 2);
+
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                for (int n = 2; n < blockSize; n++)
+                {
+					FR[n - 2] = outBytes[outOff + n] = EncryptByte(input[inOff + n], n - 2);
+                }
+
+				count += blockSize;
+            }
+
+            return blockSize;
+        }
+
+        /**
+        * Do the appropriate processing for CFB IV mode decryption.
+        *
+        * @param in the array containing the data to be decrypted.
+        * @param inOff offset into the in array the data starts at.
+        * @param out the array the encrypted data will be copied into.
+        * @param outOff the offset into the out array the output will start at.
+        * @exception DataLengthException if there isn't enough data in in, or
+        * space in out.
+        * @exception InvalidOperationException if the cipher isn't initialised.
+        * @return the number of bytes processed and produced.
+        */
+        private int DecryptBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	outBytes,
+            int		outOff)
+        {
+            if ((inOff + blockSize) > input.Length)
+            {
+                throw new DataLengthException("input buffer too short");
+            }
+
+            if ((outOff + blockSize) > outBytes.Length)
+            {
+                throw new DataLengthException("output buffer too short");
+            }
+
+            if (count > blockSize)
+            {
+				byte inVal = input[inOff];
+				FR[blockSize - 2] = inVal;
+				outBytes[outOff] = EncryptByte(inVal, blockSize - 2);
+
+				inVal = input[inOff + 1];
+				FR[blockSize - 1] = inVal;
+				outBytes[outOff + 1] = EncryptByte(inVal, blockSize - 1);
+
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                for (int n = 2; n < blockSize; n++)
+                {
+					inVal = input[inOff + n];
+					FR[n - 2] = inVal;
+					outBytes[outOff + n] = EncryptByte(inVal, n - 2);
+				}
+            }
+            else if (count == 0)
+            {
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                for (int n = 0; n < blockSize; n++)
+                {
+                    FR[n] = input[inOff + n];
+                    outBytes[n] = EncryptByte(input[inOff + n], n);
+                }
+
+                count += blockSize;
+            }
+            else if (count == blockSize)
+            {
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+				byte inVal1 = input[inOff];
+				byte inVal2 = input[inOff + 1];
+				outBytes[outOff    ] = EncryptByte(inVal1, 0);
+				outBytes[outOff + 1] = EncryptByte(inVal2, 1);
+
+                Array.Copy(FR, 2, FR, 0, blockSize - 2);
+
+				FR[blockSize - 2] = inVal1;
+				FR[blockSize - 1] = inVal2;
+
+                cipher.ProcessBlock(FR, 0, FRE, 0);
+
+                for (int n = 2; n < blockSize; n++)
+                {
+					byte inVal = input[inOff + n];
+					FR[n - 2] = inVal;
+					outBytes[outOff + n] = EncryptByte(inVal, n - 2);
+                }
+
+                count += blockSize;
+            }
+
+            return blockSize;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/SicBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/modes/SicBlockCipher.cs
new file mode 100644
index 0000000..da7ed78
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/SicBlockCipher.cs
@@ -0,0 +1,115 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Modes
+{
+    /**
+    * Implements the Segmented Integer Counter (SIC) mode on top of a simple
+    * block cipher.
+    */
+    public class SicBlockCipher
+        : IBlockCipher
+    {
+        private readonly IBlockCipher cipher;
+        private readonly int blockSize;
+        private readonly byte[] IV;
+        private readonly byte[] counter;
+        private readonly byte[] counterOut;
+
+        /**
+        * Basic constructor.
+        *
+        * @param c the block cipher to be used.
+        */
+        public SicBlockCipher(IBlockCipher cipher)
+        {
+            this.cipher = cipher;
+            this.blockSize = cipher.GetBlockSize();
+            this.IV = new byte[blockSize];
+            this.counter = new byte[blockSize];
+            this.counterOut = new byte[blockSize];
+        }
+
+        /**
+        * return the underlying block cipher that we are wrapping.
+        *
+        * @return the underlying block cipher that we are wrapping.
+        */
+        public IBlockCipher GetUnderlyingCipher()
+        {
+            return cipher;
+        }
+
+        public void Init(
+            bool				forEncryption, //ignored by this CTR mode
+            ICipherParameters	parameters)
+        {
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParam = (ParametersWithIV) parameters;
+                byte[] iv = ivParam.GetIV();
+                Array.Copy(iv, 0, IV, 0, IV.Length);
+
+                Reset();
+
+                // if null it's an IV changed only.
+                if (ivParam.Parameters != null)
+                {
+                    cipher.Init(true, ivParam.Parameters);
+                }
+            }
+            else
+            {
+                throw new ArgumentException("SIC mode requires ParametersWithIV", "parameters");
+            }
+        }
+
+        public string AlgorithmName
+        {
+            get { return cipher.AlgorithmName + "/SIC"; }
+        }
+
+        public bool IsPartialBlockOkay
+        {
+            get { return true; }
+        }
+
+        public int GetBlockSize()
+        {
+            return cipher.GetBlockSize();
+        }
+
+        public int ProcessBlock(
+            byte[]	input,
+            int		inOff,
+            byte[]	output,
+            int		outOff)
+        {
+            cipher.ProcessBlock(counter, 0, counterOut, 0);
+
+            //
+            // XOR the counterOut with the plaintext producing the cipher text
+            //
+            for (int i = 0; i < counterOut.Length; i++)
+            {
+                output[outOff + i] = (byte)(counterOut[i] ^ input[inOff + i]);
+            }
+
+            // Increment the counter
+            int j = counter.Length;
+            while (--j >= 0 && ++counter[j] == 0)
+            {
+            }
+
+            return counter.Length;
+        }
+
+        public void Reset()
+        {
+            Array.Copy(IV, 0, counter, 0, counter.Length);
+            cipher.Reset();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmExponentiator.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmExponentiator.cs
new file mode 100644
index 0000000..98049e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmExponentiator.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+	public class BasicGcmExponentiator
+		: IGcmExponentiator
+	{
+		private byte[] x;
+
+		public void Init(byte[] x)
+		{
+			this.x = Arrays.Clone(x);
+		}
+
+		public void ExponentiateX(long pow, byte[] output)
+		{
+			// Initial value is little-endian 1
+			byte[] y = GcmUtilities.OneAsBytes();
+
+			if (pow > 0)
+			{
+				byte[] powX = Arrays.Clone(x);
+				do
+				{
+					if ((pow & 1L) != 0)
+					{
+						GcmUtilities.Multiply(y, powX);
+					}
+					GcmUtilities.Multiply(powX, powX);
+					pow >>= 1;
+				}
+				while (pow > 0);
+			}
+
+			Array.Copy(y, 0, output, 0, 16);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmMultiplier.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmMultiplier.cs
new file mode 100644
index 0000000..85e3ac9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/BasicGcmMultiplier.cs
@@ -0,0 +1,22 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+	public class BasicGcmMultiplier
+		: IGcmMultiplier
+	{
+		private byte[] H;
+
+		public void Init(byte[] H)
+		{
+            this.H = Arrays.Clone(H);
+		}
+
+        public void MultiplyH(byte[] x)
+		{
+			GcmUtilities.Multiply(x, H);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/GcmUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/GcmUtilities.cs
new file mode 100644
index 0000000..71e63c8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/GcmUtilities.cs
@@ -0,0 +1,237 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+    internal abstract class GcmUtilities
+    {
+        internal static byte[] OneAsBytes()
+        {
+            byte[] tmp = new byte[16];
+            tmp[0] = 0x80;
+            return tmp;
+        }
+
+        internal static uint[] OneAsUints()
+        {
+            uint[] tmp = new uint[4];
+            tmp[0] = 0x80000000;
+            return tmp;
+        }
+
+        internal static uint[] AsUints(byte[] bs)
+        {
+            uint[] output = new uint[4];
+            Pack.BE_To_UInt32(bs, 0, output);
+            return output;
+        }
+
+        internal static void AsUints(byte[] bs, uint[] output)
+        {
+            Pack.BE_To_UInt32(bs, 0, output);
+        }
+
+        internal static void Multiply(byte[] block, byte[] val)
+        {
+            byte[] tmp = Arrays.Clone(block);
+            byte[] c = new byte[16];
+
+            for (int i = 0; i < 16; ++i)
+            {
+                byte bits = val[i];
+                for (int j = 7; j >= 0; --j)
+                {
+                    if ((bits & (1 << j)) != 0)
+                    {
+                        Xor(c, tmp);
+                    }
+
+                    bool lsb = (tmp[15] & 1) != 0;
+                    ShiftRight(tmp);
+                    if (lsb)
+                    {
+                        // R = new byte[]{ 0xe1, ... };
+                        //GCMUtilities.Xor(tmp, R);
+                        tmp[0] ^= (byte)0xe1;
+                    }
+                }
+            }
+
+            Array.Copy(c, 0, block, 0, 16);
+        }
+
+        // P is the value with only bit i=1 set
+        internal static void MultiplyP(uint[] x)
+        {
+            bool lsb = (x[3] & 1) != 0;
+            ShiftRight(x);
+            if (lsb)
+            {
+                // R = new uint[]{ 0xe1000000, 0, 0, 0 };
+                //Xor(v, R);
+                x[0] ^= 0xe1000000;
+            }
+        }
+
+        internal static void MultiplyP(uint[] x, uint[] output)
+        {
+            bool lsb = (x[3] & 1) != 0;
+            ShiftRight(x, output);
+            if (lsb)
+            {
+                output[0] ^= 0xe1000000;
+            }
+        }
+
+        internal static void MultiplyP8(uint[] x)
+        {
+//			for (int i = 8; i != 0; --i)
+//			{
+//				MultiplyP(x);
+//			}
+
+            uint lsw = x[3];
+            ShiftRightN(x, 8);
+            for (int i = 7; i >= 0; --i)
+            {
+                if ((lsw & (1 << i)) != 0)
+                {
+                    x[0] ^= (0xe1000000 >> (7 - i));
+                }
+            }
+        }
+
+        internal static void MultiplyP8(uint[] x, uint[] output)
+        {
+            uint lsw = x[3];
+            ShiftRightN(x, 8, output);
+            for (int i = 7; i >= 0; --i)
+            {
+                if ((lsw & (1 << i)) != 0)
+                {
+                    output[0] ^= (0xe1000000 >> (7 - i));
+                }
+            }
+        }
+
+        internal static void ShiftRight(byte[] block)
+        {
+            int i = 0;
+            byte bit = 0;
+            for (; ; )
+            {
+                byte b = block[i];
+                block[i] = (byte)((b >> 1) | bit);
+                if (++i == 16) break;
+                bit = (byte)(b << 7);
+            }
+        }
+
+        static void ShiftRight(byte[] block, byte[] output)
+        {
+            int i = 0;
+            byte bit = 0;
+            for (;;)
+            {
+                byte b = block[i];
+                output[i] = (byte)((b >> 1) | bit);
+                if (++i == 16) break;
+                bit = (byte)(b << 7);
+            }
+        }
+
+        internal static void ShiftRight(uint[] block)
+        {
+            int i = 0;
+            uint bit = 0;
+            for (; ; )
+            {
+                uint b = block[i];
+                block[i] = (b >> 1) | bit;
+                if (++i == 4) break;
+                bit = b << 31;
+            }
+        }
+
+        internal static void ShiftRight(uint[] block, uint[] output)
+        {
+            int i = 0;
+            uint bit = 0;
+            for (; ; )
+            {
+                uint b = block[i];
+                output[i] = (b >> 1) | bit;
+                if (++i == 4) break;
+                bit = b << 31;
+            }
+        }
+
+        internal static void ShiftRightN(uint[] block, int n)
+        {
+            int i = 0;
+            uint bit = 0;
+            for (; ; )
+            {
+                uint b = block[i];
+                block[i] = (b >> n) | bit;
+                if (++i == 4) break;
+                bit = b << (32 - n);
+            }
+        }
+
+        internal static void ShiftRightN(uint[] block, int n, uint[] output)
+        {
+            int i = 0;
+            uint bit = 0;
+            for (; ; )
+            {
+                uint b = block[i];
+                output[i] = (b >> n) | bit;
+                if (++i == 4) break;
+                bit = b << (32 - n);
+            }
+        }
+
+        internal static void Xor(byte[] block, byte[] val)
+        {
+            for (int i = 15; i >= 0; --i)
+            {
+                block[i] ^= val[i];
+            }
+        }
+
+        internal static void Xor(byte[] block, byte[] val, int off, int len)
+        {
+            while (--len >= 0)
+            {
+                block[len] ^= val[off + len];
+            }
+        }
+
+        internal static void Xor(byte[] block, byte[] val, byte[] output)
+        {
+            for (int i = 15; i >= 0; --i)
+            {
+                output[i] = (byte)(block[i] ^ val[i]);
+            }
+        }
+
+        internal static void Xor(uint[] block, uint[] val)
+        {
+            for (int i = 3; i >= 0; --i)
+            {
+                block[i] ^= val[i];
+            }
+        }
+
+        internal static void Xor(uint[] block, uint[] val, uint[] output)
+        {
+            for (int i = 3; i >= 0; --i)
+            {
+                output[i] = block[i] ^ val[i];
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmExponentiator.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmExponentiator.cs
new file mode 100644
index 0000000..5b4ce9d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmExponentiator.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+	public interface IGcmExponentiator
+	{
+		void Init(byte[] x);
+		void ExponentiateX(long pow, byte[] output);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmMultiplier.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmMultiplier.cs
new file mode 100644
index 0000000..ec7b906
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/IGcmMultiplier.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+	public interface IGcmMultiplier
+	{
+		void Init(byte[] H);
+		void MultiplyH(byte[] x);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
new file mode 100644
index 0000000..44933bb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables1kGcmExponentiator.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+	public class Tables1kGcmExponentiator
+		: IGcmExponentiator
+	{
+        // A lookup table of the power-of-two powers of 'x'
+        // - lookupPowX2[i] = x^(2^i)
+        private IList lookupPowX2;
+
+        public void Init(byte[] x)
+		{
+            if (lookupPowX2 != null && Arrays.AreEqual(x, (byte[])lookupPowX2[0]))
+            {
+                return;
+            }
+
+            lookupPowX2 = Platform.CreateArrayList(8);
+            lookupPowX2.Add(Arrays.Clone(x));
+		}
+
+		public void ExponentiateX(long pow, byte[] output)
+		{
+			byte[] y = GcmUtilities.OneAsBytes();
+            int bit = 0;
+            while (pow > 0)
+            {
+                if ((pow & 1L) != 0)
+                {
+                    EnsureAvailable(bit);
+                    GcmUtilities.Multiply(y, (byte[])lookupPowX2[bit]);
+                }
+                ++bit;
+                pow >>= 1;
+            }
+
+			Array.Copy(y, 0, output, 0, 16);
+		}
+
+        private void EnsureAvailable(int bit)
+        {
+            int count = lookupPowX2.Count;
+            if (count <= bit)
+            {
+                byte[] tmp = (byte[])lookupPowX2[count - 1];
+                do
+                {
+                    tmp = Arrays.Clone(tmp);
+                    GcmUtilities.Multiply(tmp, tmp);
+                    lookupPowX2.Add(tmp);
+                }
+                while (++count <= bit);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs
new file mode 100644
index 0000000..707b0be
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables64kGcmMultiplier.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+    public class Tables64kGcmMultiplier
+        : IGcmMultiplier
+    {
+        private byte[] H;
+        private uint[][][] M;
+
+        public void Init(byte[] H)
+        {
+            if (M == null)
+            {
+                M = new uint[16][][];
+            }
+            else if (Arrays.AreEqual(this.H, H))
+            {
+                return;
+            }
+
+            this.H = Arrays.Clone(H);
+
+            M[0] = new uint[256][];
+            M[0][0] = new uint[4];
+            M[0][128] = GcmUtilities.AsUints(H);
+            for (int j = 64; j >= 1; j >>= 1)
+            {
+                uint[] tmp = (uint[])M[0][j + j].Clone();
+                GcmUtilities.MultiplyP(tmp);
+                M[0][j] = tmp;
+            }
+            for (int i = 0; ; )
+            {
+                for (int j = 2; j < 256; j += j)
+                {
+                    for (int k = 1; k < j; ++k)
+                    {
+                        uint[] tmp = (uint[])M[i][j].Clone();
+                        GcmUtilities.Xor(tmp, M[i][k]);
+                        M[i][j + k] = tmp;
+                    }
+                }
+
+                if (++i == 16) return;
+
+                M[i] = new uint[256][];
+                M[i][0] = new uint[4];
+                for (int j = 128; j > 0; j >>= 1)
+                {
+                    uint[] tmp = (uint[])M[i - 1][j].Clone();
+                    GcmUtilities.MultiplyP8(tmp);
+                    M[i][j] = tmp;
+                }
+            }
+        }
+
+        public void MultiplyH(byte[] x)
+        {
+            uint[] z = new uint[4];
+            for (int i = 0; i != 16; ++i)
+            {
+                //GcmUtilities.Xor(z, M[i][x[i]]);
+                uint[] m = M[i][x[i]];
+                z[0] ^= m[0];
+                z[1] ^= m[1];
+                z[2] ^= m[2];
+                z[3] ^= m[3];
+            }
+
+            Pack.UInt32_To_BE(z, x, 0);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs
new file mode 100644
index 0000000..5f3d6c8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/modes/gcm/Tables8kGcmMultiplier.cs
@@ -0,0 +1,103 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Modes.Gcm
+{
+    public class Tables8kGcmMultiplier
+        : IGcmMultiplier
+    {
+        private byte[] H;
+        private uint[][][] M;
+
+        public void Init(byte[] H)
+        {
+            if (M == null)
+            {
+                M = new uint[32][][];
+            }
+            else if (Arrays.AreEqual(this.H, H))
+            {
+                return;
+            }
+
+            this.H = Arrays.Clone(H);
+
+            M[0] = new uint[16][];
+            M[1] = new uint[16][];
+            M[0][0] = new uint[4];
+            M[1][0] = new uint[4];
+            M[1][8] = GcmUtilities.AsUints(H);
+
+            for (int j = 4; j >= 1; j >>= 1)
+            {
+                uint[] tmp = (uint[])M[1][j + j].Clone();
+                GcmUtilities.MultiplyP(tmp);
+                M[1][j] = tmp;
+            }
+
+            {
+                uint[] tmp = (uint[])M[1][1].Clone();
+                GcmUtilities.MultiplyP(tmp);
+                M[0][8] = tmp;
+            }
+
+            for (int j = 4; j >= 1; j >>= 1)
+            {
+                uint[] tmp = (uint[])M[0][j + j].Clone();
+                GcmUtilities.MultiplyP(tmp);
+                M[0][j] = tmp;
+            }
+
+            for (int i = 0; ; )
+            {
+                for (int j = 2; j < 16; j += j)
+                {
+                    for (int k = 1; k < j; ++k)
+                    {
+                        uint[] tmp = (uint[])M[i][j].Clone();
+                        GcmUtilities.Xor(tmp, M[i][k]);
+                        M[i][j + k] = tmp;
+                    }
+                }
+
+                if (++i == 32) return;
+
+                if (i > 1)
+                {
+                    M[i] = new uint[16][];
+                    M[i][0] = new uint[4];
+                    for (int j = 8; j > 0; j >>= 1)
+                    {
+                        uint[] tmp = (uint[])M[i - 2][j].Clone();
+                        GcmUtilities.MultiplyP8(tmp);
+                        M[i][j] = tmp;
+                    }
+                }
+            }
+        }
+
+        public void MultiplyH(byte[] x)
+        {
+            uint[] z = new uint[4];
+            for (int i = 15; i >= 0; --i)
+            {
+                //GcmUtilities.Xor(z, M[i + i][x[i] & 0x0f]);
+                uint[] m = M[i + i][x[i] & 0x0f];
+                z[0] ^= m[0];
+                z[1] ^= m[1];
+                z[2] ^= m[2];
+                z[3] ^= m[3];
+                //GcmUtilities.Xor(z, M[i + i + 1][(x[i] & 0xf0) >> 4]);
+                m = M[i + i + 1][(x[i] & 0xf0) >> 4];
+                z[0] ^= m[0];
+                z[1] ^= m[1];
+                z[2] ^= m[2];
+                z[3] ^= m[3];
+            }
+
+            Pack.UInt32_To_BE(z, x, 0);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/BlockCipherPadding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/BlockCipherPadding.cs
new file mode 100644
index 0000000..33a5f9f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/BlockCipherPadding.cs
@@ -0,0 +1,43 @@
+using System;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+    /**
+     * Block cipher padders are expected to conform to this interface
+     */
+    public interface IBlockCipherPadding
+    {
+        /**
+         * Initialise the padder.
+         *
+         * @param param parameters, if any required.
+         */
+        void Init(SecureRandom random);
+            //throws ArgumentException;
+
+        /**
+         * Return the name of the algorithm the cipher implements.
+         *
+         * @return the name of the algorithm the cipher implements.
+         */
+        string PaddingName { get; }
+
+		/**
+         * add the pad bytes to the passed in block, returning the
+         * number of bytes added.
+         */
+        int AddPadding(byte[] input, int inOff);
+
+        /**
+         * return the number of pad bytes present in the block.
+         * @exception InvalidCipherTextException if the padding is badly formed
+         * or invalid.
+         */
+        int PadCount(byte[] input);
+        //throws InvalidCipherTextException;
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/ISO10126d2Padding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/ISO10126d2Padding.cs
new file mode 100644
index 0000000..e132a62
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/ISO10126d2Padding.cs
@@ -0,0 +1,76 @@
+using System;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+
+    /**
+    * A padder that adds ISO10126-2 padding to a block.
+    */
+    public class ISO10126d2Padding: IBlockCipherPadding
+    {
+        private SecureRandom random;
+
+        /**
+        * Initialise the padder.
+        *
+        * @param random a SecureRandom if available.
+        */
+        public void Init(
+			SecureRandom random)
+            //throws ArgumentException
+        {
+			this.random = (random != null) ? random : new SecureRandom();
+        }
+
+		/**
+        * Return the name of the algorithm the cipher implements.
+        *
+        * @return the name of the algorithm the cipher implements.
+        */
+        public string PaddingName
+        {
+            get { return "ISO10126-2"; }
+        }
+
+		/**
+        * add the pad bytes to the passed in block, returning the
+        * number of bytes added.
+        */
+        public int AddPadding(
+            byte[]	input,
+            int		inOff)
+        {
+            byte code = (byte)(input.Length - inOff);
+
+            while (inOff < (input.Length - 1))
+            {
+                input[inOff] = (byte)random.NextInt();
+                inOff++;
+            }
+
+            input[inOff] = code;
+
+            return code;
+        }
+
+        /**
+        * return the number of pad bytes present in the block.
+        */
+        public int PadCount(byte[] input)
+            //throws InvalidCipherTextException
+        {
+            int count = input[input.Length - 1] & 0xff;
+
+            if (count > input.Length)
+            {
+                throw new InvalidCipherTextException("pad block corrupted");
+            }
+
+            return count;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/ISO7816d4Padding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/ISO7816d4Padding.cs
new file mode 100644
index 0000000..016b25a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/ISO7816d4Padding.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+	/**
+	 * A padder that adds the padding according to the scheme referenced in
+	 * ISO 7814-4 - scheme 2 from ISO 9797-1. The first byte is 0x80, rest is 0x00
+	 */
+	public class ISO7816d4Padding
+		: IBlockCipherPadding
+	{
+		/**
+		 * Initialise the padder.
+		 *
+		 * @param random - a SecureRandom if available.
+		 */
+		public void Init(
+			SecureRandom random)
+		{
+			// nothing to do.
+		}
+
+		/**
+		 * Return the name of the algorithm the padder implements.
+		 *
+		 * @return the name of the algorithm the padder implements.
+		 */
+		public string PaddingName
+		{
+			get { return "ISO7816-4"; }
+		}
+
+		/**
+		 * add the pad bytes to the passed in block, returning the
+		 * number of bytes added.
+		 */
+		public int AddPadding(
+			byte[]	input,
+			int		inOff)
+		{
+			int added = (input.Length - inOff);
+
+			input[inOff]= (byte) 0x80;
+			inOff ++;
+
+			while (inOff < input.Length)
+			{
+				input[inOff] = (byte) 0;
+				inOff++;
+			}
+
+			return added;
+		}
+
+		/**
+		 * return the number of pad bytes present in the block.
+		 */
+		public int PadCount(
+			byte[] input)
+		{
+			int count = input.Length - 1;
+
+			while (count > 0 && input[count] == 0)
+			{
+				count--;
+			}
+
+			if (input[count] != (byte)0x80)
+			{
+				throw new InvalidCipherTextException("pad block corrupted");
+			}
+
+			return input.Length - count;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/PaddedBufferedBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/PaddedBufferedBlockCipher.cs
new file mode 100644
index 0000000..fb8a92b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/PaddedBufferedBlockCipher.cs
@@ -0,0 +1,288 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+	/**
+	* A wrapper class that allows block ciphers to be used to process data in
+	* a piecemeal fashion with padding. The PaddedBufferedBlockCipher
+	* outputs a block only when the buffer is full and more data is being added,
+	* or on a doFinal (unless the current block in the buffer is a pad block).
+	* The default padding mechanism used is the one outlined in Pkcs5/Pkcs7.
+	*/
+	public class PaddedBufferedBlockCipher
+		: BufferedBlockCipher
+	{
+		private readonly IBlockCipherPadding padding;
+
+		/**
+		* Create a buffered block cipher with the desired padding.
+		*
+		* @param cipher the underlying block cipher this buffering object wraps.
+		* @param padding the padding type.
+		*/
+		public PaddedBufferedBlockCipher(
+			IBlockCipher		cipher,
+			IBlockCipherPadding	padding)
+		{
+			this.cipher = cipher;
+			this.padding = padding;
+
+			buf = new byte[cipher.GetBlockSize()];
+			bufOff = 0;
+		}
+
+		/**
+		* Create a buffered block cipher Pkcs7 padding
+		*
+		* @param cipher the underlying block cipher this buffering object wraps.
+		*/
+		public PaddedBufferedBlockCipher(
+			IBlockCipher cipher)
+			: this(cipher, new Pkcs7Padding())    { }
+
+		/**
+		* initialise the cipher.
+		*
+		* @param forEncryption if true the cipher is initialised for
+		*  encryption, if false for decryption.
+		* @param param the key and other data required by the cipher.
+		* @exception ArgumentException if the parameters argument is
+		* inappropriate.
+		*/
+		public override void Init(
+			bool				forEncryption,
+			ICipherParameters	parameters)
+		{
+			this.forEncryption = forEncryption;
+
+			SecureRandom initRandom = null;
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom p = (ParametersWithRandom)parameters;
+				initRandom = p.Random;
+				parameters = p.Parameters;
+			}
+
+			Reset();
+			padding.Init(initRandom);
+			cipher.Init(forEncryption, parameters);
+		}
+
+		/**
+		* return the minimum size of the output buffer required for an update
+		* plus a doFinal with an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update and doFinal
+		* with len bytes of input.
+		*/
+		public override int GetOutputSize(
+			int length)
+		{
+			int total = length + bufOff;
+			int leftOver = total % buf.Length;
+
+			if (leftOver == 0)
+			{
+				if (forEncryption)
+				{
+					return total + buf.Length;
+				}
+
+				return total;
+			}
+
+			return total - leftOver + buf.Length;
+		}
+
+		/**
+		* return the size of the output buffer required for an update
+		* an input of len bytes.
+		*
+		* @param len the length of the input.
+		* @return the space required to accommodate a call to update
+		* with len bytes of input.
+		*/
+		public override int GetUpdateOutputSize(
+			int length)
+		{
+			int total       = length + bufOff;
+			int leftOver    = total % buf.Length;
+
+			if (leftOver == 0)
+			{
+				return total - buf.Length;
+			}
+
+			return total - leftOver;
+		}
+
+		/**
+		* process a single byte, producing an output block if neccessary.
+		*
+		* @param in the input byte.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessByte(
+			byte	input,
+			byte[]	output,
+			int		outOff)
+		{
+			int resultLen = 0;
+
+			if (bufOff == buf.Length)
+			{
+				resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
+				bufOff = 0;
+			}
+
+			buf[bufOff++] = input;
+
+			return resultLen;
+		}
+
+		/**
+		* process an array of bytes, producing output if necessary.
+		*
+		* @param in the input byte array.
+		* @param inOff the offset at which the input data starts.
+		* @param len the number of bytes to be copied out of the input array.
+		* @param out the space for any output that might be produced.
+		* @param outOff the offset from which the output will be copied.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there isn't enough space in out.
+		* @exception InvalidOperationException if the cipher isn't initialised.
+		*/
+		public override int ProcessBytes(
+			byte[]	input,
+			int		inOff,
+			int		length,
+			byte[]	output,
+			int		outOff)
+		{
+			if (length < 0)
+			{
+				throw new ArgumentException("Can't have a negative input length!");
+			}
+
+			int blockSize = GetBlockSize();
+			int outLength = GetUpdateOutputSize(length);
+
+			if (outLength > 0)
+			{
+				if ((outOff + outLength) > output.Length)
+				{
+					throw new DataLengthException("output buffer too short");
+				}
+			}
+
+			int resultLen = 0;
+			int gapLen = buf.Length - bufOff;
+
+			if (length > gapLen)
+			{
+				Array.Copy(input, inOff, buf, bufOff, gapLen);
+
+				resultLen += cipher.ProcessBlock(buf, 0, output, outOff);
+
+				bufOff = 0;
+				length -= gapLen;
+				inOff += gapLen;
+
+				while (length > buf.Length)
+				{
+					resultLen += cipher.ProcessBlock(input, inOff, output, outOff + resultLen);
+
+					length -= blockSize;
+					inOff += blockSize;
+				}
+			}
+
+			Array.Copy(input, inOff, buf, bufOff, length);
+
+			bufOff += length;
+
+			return resultLen;
+		}
+
+		/**
+		* Process the last block in the buffer. If the buffer is currently
+		* full and padding needs to be added a call to doFinal will produce
+		* 2 * GetBlockSize() bytes.
+		*
+		* @param out the array the block currently being held is copied into.
+		* @param outOff the offset at which the copying starts.
+		* @return the number of output bytes copied to out.
+		* @exception DataLengthException if there is insufficient space in out for
+		* the output or we are decrypting and the input is not block size aligned.
+		* @exception InvalidOperationException if the underlying cipher is not
+		* initialised.
+		* @exception InvalidCipherTextException if padding is expected and not found.
+		*/
+		public override int DoFinal(
+			byte[]  output,
+			int     outOff)
+		{
+			int blockSize = cipher.GetBlockSize();
+			int resultLen = 0;
+
+			if (forEncryption)
+			{
+				if (bufOff == blockSize)
+				{
+					if ((outOff + 2 * blockSize) > output.Length)
+					{
+						Reset();
+
+						throw new DataLengthException("output buffer too short");
+					}
+
+					resultLen = cipher.ProcessBlock(buf, 0, output, outOff);
+					bufOff = 0;
+				}
+
+				padding.AddPadding(buf, bufOff);
+
+				resultLen += cipher.ProcessBlock(buf, 0, output, outOff + resultLen);
+
+				Reset();
+			}
+			else
+			{
+				if (bufOff == blockSize)
+				{
+					resultLen = cipher.ProcessBlock(buf, 0, buf, 0);
+					bufOff = 0;
+				}
+				else
+				{
+					Reset();
+
+					throw new DataLengthException("last block incomplete in decryption");
+				}
+
+				try
+				{
+					resultLen -= padding.PadCount(buf);
+
+					Array.Copy(buf, 0, output, outOff, resultLen);
+				}
+				finally
+				{
+					Reset();
+				}
+			}
+
+			return resultLen;
+		}
+	}
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/Pkcs7Padding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/Pkcs7Padding.cs
new file mode 100644
index 0000000..f3166fd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/Pkcs7Padding.cs
@@ -0,0 +1,79 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+    /**
+    * A padder that adds Pkcs7/Pkcs5 padding to a block.
+    */
+    public class Pkcs7Padding
+		: IBlockCipherPadding
+    {
+        /**
+        * Initialise the padder.
+        *
+        * @param random - a SecureRandom if available.
+        */
+        public void Init(
+			SecureRandom random)
+        {
+            // nothing to do.
+        }
+
+        /**
+        * Return the name of the algorithm the cipher implements.
+        *
+        * @return the name of the algorithm the cipher implements.
+        */
+        public string PaddingName
+        {
+            get { return "PKCS7"; }
+        }
+
+		/**
+        * add the pad bytes to the passed in block, returning the
+        * number of bytes added.
+        */
+        public int AddPadding(
+            byte[]  input,
+            int     inOff)
+        {
+            byte code = (byte)(input.Length - inOff);
+
+            while (inOff < input.Length)
+            {
+                input[inOff] = code;
+                inOff++;
+            }
+
+            return code;
+        }
+
+        /**
+        * return the number of pad bytes present in the block.
+        */
+        public int PadCount(
+			byte[] input)
+        {
+            int count = (int) input[input.Length - 1];
+
+			if (count < 1 || count > input.Length)
+            {
+                throw new InvalidCipherTextException("pad block corrupted");
+            }
+
+			for (int i = 1; i <= count; i++)
+            {
+                if (input[input.Length - i] != count)
+                {
+                    throw new InvalidCipherTextException("pad block corrupted");
+                }
+            }
+
+            return count;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/TbcPadding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/TbcPadding.cs
new file mode 100644
index 0000000..74b64e8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/TbcPadding.cs
@@ -0,0 +1,79 @@
+using System;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+
+    /// <summary> A padder that adds Trailing-Bit-Compliment padding to a block.
+    /// <p>
+    /// This padding pads the block out compliment of the last bit
+    /// of the plain text.
+    /// </p>
+    /// </summary>
+    public class TbcPadding
+		: IBlockCipherPadding
+    {
+        /// <summary> Return the name of the algorithm the cipher implements.</summary>
+        /// <returns> the name of the algorithm the cipher implements.
+        /// </returns>
+        public string PaddingName
+        {
+            get { return "TBC"; }
+        }
+
+		/// <summary> Initialise the padder.</summary>
+        /// <param name="random">- a SecureRandom if available.
+        /// </param>
+        public virtual void Init(SecureRandom random)
+        {
+            // nothing to do.
+        }
+
+        /// <summary> add the pad bytes to the passed in block, returning the
+        /// number of bytes added.
+        /// <p>
+        /// Note: this assumes that the last block of plain text is always
+        /// passed to it inside in. i.e. if inOff is zero, indicating the
+        /// entire block is to be overwritten with padding the value of in
+        /// should be the same as the last block of plain text.
+        /// </p>
+        /// </summary>
+        public virtual int AddPadding(byte[] input, int inOff)
+        {
+            int count = input.Length - inOff;
+            byte code;
+
+            if (inOff > 0)
+            {
+                code = (byte)((input[inOff - 1] & 0x01) == 0?0xff:0x00);
+            }
+            else
+            {
+                code = (byte)((input[input.Length - 1] & 0x01) == 0?0xff:0x00);
+            }
+
+            while (inOff < input.Length)
+            {
+                input[inOff] = code;
+                inOff++;
+            }
+
+            return count;
+        }
+
+        /// <summary> return the number of pad bytes present in the block.</summary>
+        public virtual int PadCount(byte[] input)
+        {
+            byte code = input[input.Length - 1];
+
+            int index = input.Length - 1;
+            while (index > 0 && input[index - 1] == code)
+            {
+                index--;
+            }
+
+            return input.Length - index;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/X923Padding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/X923Padding.cs
new file mode 100644
index 0000000..cc1b52b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/X923Padding.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+    /**
+    * A padder that adds X9.23 padding to a block - if a SecureRandom is
+    * passed in random padding is assumed, otherwise padding with zeros is used.
+    */
+    public class X923Padding
+		: IBlockCipherPadding
+    {
+        private SecureRandom random;
+
+		/**
+        * Initialise the padder.
+        *
+        * @param random a SecureRandom if one is available.
+        */
+        public void Init(
+			SecureRandom random)
+        {
+            this.random = random;
+        }
+
+		/**
+        * Return the name of the algorithm the cipher implements.
+        *
+        * @return the name of the algorithm the cipher implements.
+        */
+        public string PaddingName
+        {
+            get { return "X9.23"; }
+        }
+
+		/**
+        * add the pad bytes to the passed in block, returning the
+        * number of bytes added.
+        */
+        public int AddPadding(
+            byte[]  input,
+            int     inOff)
+        {
+            byte code = (byte)(input.Length - inOff);
+
+            while (inOff < input.Length - 1)
+            {
+                if (random == null)
+                {
+                    input[inOff] = 0;
+                }
+                else
+                {
+                    input[inOff] = (byte)random.NextInt();
+                }
+                inOff++;
+            }
+
+            input[inOff] = code;
+
+            return code;
+        }
+
+        /**
+        * return the number of pad bytes present in the block.
+        */
+        public int PadCount(
+			byte[] input)
+        {
+            int count = input[input.Length - 1] & 0xff;
+
+            if (count > input.Length)
+            {
+                throw new InvalidCipherTextException("pad block corrupted");
+            }
+
+            return count;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/paddings/ZeroBytePadding.cs b/BouncyCastle.AxCrypt/src/crypto/paddings/ZeroBytePadding.cs
new file mode 100644
index 0000000..0d55ca4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/paddings/ZeroBytePadding.cs
@@ -0,0 +1,68 @@
+using System;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Paddings
+{
+
+    /// <summary> A padder that adds Null byte padding to a block.</summary>
+    public class ZeroBytePadding : IBlockCipherPadding
+    {
+        /// <summary> Return the name of the algorithm the cipher implements.
+        ///
+        /// </summary>
+        /// <returns> the name of the algorithm the cipher implements.
+        /// </returns>
+        public string PaddingName
+        {
+            get { return "ZeroBytePadding"; }
+        }
+
+		/// <summary> Initialise the padder.
+        ///
+        /// </summary>
+        /// <param name="random">- a SecureRandom if available.
+        /// </param>
+        public void Init(SecureRandom random)
+        {
+            // nothing to do.
+        }
+
+        /// <summary> add the pad bytes to the passed in block, returning the
+        /// number of bytes added.
+        /// </summary>
+        public int AddPadding(
+			byte[]	input,
+			int		inOff)
+        {
+            int added = (input.Length - inOff);
+
+            while (inOff < input.Length)
+            {
+                input[inOff] = (byte) 0;
+                inOff++;
+            }
+
+            return added;
+        }
+
+		/// <summary> return the number of pad bytes present in the block.</summary>
+        public int PadCount(
+			byte[] input)
+        {
+            int count = input.Length;
+
+            while (count > 0)
+            {
+                if (input[count - 1] != 0)
+                {
+                    break;
+                }
+
+                count--;
+            }
+
+            return input.Length - count;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/AEADParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/AEADParameters.cs
new file mode 100644
index 0000000..825d6b7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/AEADParameters.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class AeadParameters
+		: ICipherParameters
+	{
+		private readonly byte[] associatedText;
+		private readonly byte[] nonce;
+		private readonly KeyParameter key;
+		private readonly int macSize;
+
+        /**
+         * Base constructor.
+         *
+         * @param key key to be used by underlying cipher
+         * @param macSize macSize in bits
+         * @param nonce nonce to be used
+         */
+        public AeadParameters(KeyParameter key, int macSize, byte[] nonce)
+           : this(key, macSize, nonce, null)
+        {
+        }
+
+        /**
+		 * Base constructor.
+		 *
+		 * @param key key to be used by underlying cipher
+		 * @param macSize macSize in bits
+		 * @param nonce nonce to be used
+		 * @param associatedText associated text, if any
+		 */
+		public AeadParameters(
+			KeyParameter	key,
+			int				macSize,
+			byte[]			nonce,
+			byte[]			associatedText)
+		{
+			this.key = key;
+			this.nonce = nonce;
+			this.macSize = macSize;
+			this.associatedText = associatedText;
+		}
+
+		public virtual KeyParameter Key
+		{
+			get { return key; }
+		}
+
+		public virtual int MacSize
+		{
+			get { return macSize; }
+		}
+
+		public virtual byte[] GetAssociatedText()
+		{
+			return associatedText;
+		}
+
+		public virtual byte[] GetNonce()
+		{
+			return nonce;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/CcmParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/CcmParameters.cs
new file mode 100644
index 0000000..d445908
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/CcmParameters.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    [Obsolete("Use AeadParameters")]
+    public class CcmParameters
+        : AeadParameters 
+    {
+		/**
+		 * Base constructor.
+		 * 
+		 * @param key key to be used by underlying cipher
+		 * @param macSize macSize in bits
+		 * @param nonce nonce to be used
+		 * @param associatedText associated text, if any
+		 */
+		public CcmParameters(
+			KeyParameter	key,
+			int				macSize,
+			byte[]			nonce,
+			byte[]			associatedText)
+			: base(key, macSize, nonce, associatedText)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyGenerationParameters.cs
new file mode 100644
index 0000000..ab3e18f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyGenerationParameters.cs
@@ -0,0 +1,31 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHKeyGenerationParameters
+		: KeyGenerationParameters
+    {
+        private readonly DHParameters parameters;
+
+		public DHKeyGenerationParameters(
+            SecureRandom	random,
+            DHParameters	parameters)
+			: base(random, GetStrength(parameters))
+        {
+            this.parameters = parameters;
+        }
+
+		public DHParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+		internal static int GetStrength(
+			DHParameters parameters)
+		{
+			return parameters.L != 0 ? parameters.L : parameters.P.BitLength;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyParameters.cs
new file mode 100644
index 0000000..1a5c138
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHKeyParameters.cs
@@ -0,0 +1,76 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHKeyParameters
+		: AsymmetricKeyParameter
+    {
+        private readonly DHParameters parameters;
+		private readonly DerObjectIdentifier algorithmOid;
+
+		protected DHKeyParameters(
+            bool			isPrivate,
+            DHParameters	parameters)
+			: this(isPrivate, parameters, PkcsObjectIdentifiers.DhKeyAgreement)
+        {
+        }
+
+		protected DHKeyParameters(
+            bool				isPrivate,
+            DHParameters		parameters,
+			DerObjectIdentifier	algorithmOid)
+			: base(isPrivate)
+        {
+			// TODO Should we allow parameters to be null?
+            this.parameters = parameters;
+			this.algorithmOid = algorithmOid;
+        }
+
+		public DHParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+		public DerObjectIdentifier AlgorithmOid
+		{
+			get { return algorithmOid; }
+		}
+
+		public override bool Equals(
+			object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DHKeyParameters other = obj as DHKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DHKeyParameters other)
+		{
+			return Platform.Equals(parameters, other.parameters)
+				&& base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+			int hc = base.GetHashCode();
+
+			if (parameters != null)
+			{
+				hc ^= parameters.GetHashCode();
+			}
+
+			return hc;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHParameters.cs
new file mode 100644
index 0000000..a0544e7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHParameters.cs
@@ -0,0 +1,184 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHParameters
+		: ICipherParameters
+    {
+		private const int DefaultMinimumLength = 160;
+
+		private readonly BigInteger p, g, q, j;
+		private readonly int m, l;
+		private readonly DHValidationParameters validation;
+
+		private static int GetDefaultMParam(
+			int lParam)
+		{
+			if (lParam == 0)
+				return DefaultMinimumLength;
+
+			return System.Math.Min(lParam, DefaultMinimumLength);
+		}
+
+		public DHParameters(
+			BigInteger	p,
+			BigInteger	g)
+			: this(p, g, null, 0)
+		{
+		}
+
+		public DHParameters(
+			BigInteger	p,
+			BigInteger	g,
+			BigInteger	q)
+			: this(p, g, q, 0)
+		{
+		}
+
+		public DHParameters(
+			BigInteger	p,
+			BigInteger	g,
+			BigInteger	q,
+			int			l)
+			: this(p, g, q, GetDefaultMParam(l), l, null, null)
+		{
+		}
+
+		public DHParameters(
+			BigInteger  p,
+			BigInteger  g,
+			BigInteger  q,
+			int         m,
+			int         l)
+			: this(p, g, q, m, l, null, null)
+		{
+		}
+
+		public DHParameters(
+			BigInteger				p,
+			BigInteger				g,
+			BigInteger				q,
+			BigInteger				j,
+			DHValidationParameters	validation)
+			: this(p, g, q,  DefaultMinimumLength, 0, j, validation)
+		{
+		}
+
+		public DHParameters(
+			BigInteger				p,
+			BigInteger				g,
+			BigInteger				q,
+			int						m,
+			int						l,
+			BigInteger				j,
+			DHValidationParameters	validation)
+		{
+			if (p == null)
+				throw new ArgumentNullException("p");
+			if (g == null)
+				throw new ArgumentNullException("g");
+			if (!p.TestBit(0))
+				throw new ArgumentException("field must be an odd prime", "p");
+			if (g.CompareTo(BigInteger.Two) < 0
+				|| g.CompareTo(p.Subtract(BigInteger.Two)) > 0)
+				throw new ArgumentException("generator must in the range [2, p - 2]", "g");
+			if (q != null && q.BitLength >= p.BitLength)
+				throw new ArgumentException("q too big to be a factor of (p-1)", "q");
+			if (m >= p.BitLength)
+				throw new ArgumentException("m value must be < bitlength of p", "m");
+			if (l != 0)
+			{ 
+	            if (l >= p.BitLength)
+                	throw new ArgumentException("when l value specified, it must be less than bitlength(p)", "l");
+				if (l < m)
+					throw new ArgumentException("when l value specified, it may not be less than m value", "l");
+			}
+			if (j != null && j.CompareTo(BigInteger.Two) < 0)
+				throw new ArgumentException("subgroup factor must be >= 2", "j");
+
+			// TODO If q, j both provided, validate p = jq + 1 ?
+
+			this.p = p;
+			this.g = g;
+			this.q = q;
+			this.m = m;
+			this.l = l;
+			this.j = j;
+			this.validation = validation;
+        }
+
+		public BigInteger P
+        {
+            get { return p; }
+        }
+
+		public BigInteger G
+        {
+            get { return g; }
+        }
+
+		public BigInteger Q
+        {
+            get { return q; }
+        }
+
+		public BigInteger J
+        {
+            get { return j; }
+        }
+
+		/// <summary>The minimum bitlength of the private value.</summary>
+		public int M
+		{
+			get { return m; }
+		}
+
+		/// <summary>The bitlength of the private value.</summary>
+		public int L
+		{
+			get { return l; }
+		}
+
+		public DHValidationParameters ValidationParameters
+        {
+			get { return validation; }
+        }
+
+		public override bool Equals(
+			object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DHParameters other = obj as DHParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			DHParameters other)
+		{
+			return p.Equals(other.p)
+				&& g.Equals(other.g)
+				&& Platform.Equals(q, other.q);
+		}
+
+		public override int GetHashCode()
+        {
+			int hc = p.GetHashCode() ^ g.GetHashCode();
+
+			if (q != null)
+			{
+				hc ^= q.GetHashCode();
+			}
+
+			return hc;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHPrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHPrivateKeyParameters.cs
new file mode 100644
index 0000000..fc724df
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHPrivateKeyParameters.cs
@@ -0,0 +1,60 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHPrivateKeyParameters
+		: DHKeyParameters
+    {
+        private readonly BigInteger x;
+
+		public DHPrivateKeyParameters(
+            BigInteger		x,
+            DHParameters	parameters)
+			: base(true, parameters)
+        {
+            this.x = x;
+        }
+
+		public DHPrivateKeyParameters(
+            BigInteger			x,
+            DHParameters		parameters,
+		    DerObjectIdentifier	algorithmOid)
+			: base(true, parameters, algorithmOid)
+        {
+            this.x = x;
+        }
+
+		public BigInteger X
+        {
+            get { return x; }
+        }
+
+		public override bool Equals(
+			object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DHPrivateKeyParameters other = obj as DHPrivateKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DHPrivateKeyParameters other)
+		{
+			return x.Equals(other.x) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+            return x.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHPublicKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHPublicKeyParameters.cs
new file mode 100644
index 0000000..e79375f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHPublicKeyParameters.cs
@@ -0,0 +1,66 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHPublicKeyParameters
+		: DHKeyParameters
+    {
+        private readonly BigInteger y;
+
+		public DHPublicKeyParameters(
+            BigInteger		y,
+            DHParameters	parameters)
+			: base(false, parameters)
+        {
+			if (y == null)
+				throw new ArgumentNullException("y");
+
+			this.y = y;
+        }
+
+		public DHPublicKeyParameters(
+            BigInteger			y,
+            DHParameters		parameters,
+		    DerObjectIdentifier	algorithmOid)
+			: base(false, parameters, algorithmOid)
+        {
+			if (y == null)
+				throw new ArgumentNullException("y");
+
+			this.y = y;
+        }
+
+        public BigInteger Y
+        {
+            get { return y; }
+        }
+
+		public override bool Equals(
+			object  obj)
+        {
+			if (obj == this)
+				return true;
+
+			DHPublicKeyParameters other = obj as DHPublicKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DHPublicKeyParameters other)
+		{
+			return y.Equals(other.y) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+            return y.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DHValidationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DHValidationParameters.cs
new file mode 100644
index 0000000..50c0739
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DHValidationParameters.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DHValidationParameters
+    {
+        private readonly byte[] seed;
+        private readonly int counter;
+
+		public DHValidationParameters(
+            byte[]	seed,
+            int		counter)
+        {
+			if (seed == null)
+				throw new ArgumentNullException("seed");
+
+			this.seed = (byte[]) seed.Clone();
+            this.counter = counter;
+        }
+
+		public byte[] GetSeed()
+        {
+            return (byte[]) seed.Clone();
+        }
+
+		public int Counter
+        {
+            get { return counter; }
+        }
+
+		public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DHValidationParameters other = obj as DHValidationParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			DHValidationParameters other)
+		{
+			return counter == other.counter
+				&& Arrays.AreEqual(this.seed, other.seed);
+		}
+
+		public override int GetHashCode()
+        {
+			return counter.GetHashCode() ^ Arrays.GetHashCode(seed);
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DSAParameterGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DSAParameterGenerationParameters.cs
new file mode 100644
index 0000000..7427574
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DSAParameterGenerationParameters.cs
@@ -0,0 +1,74 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaParameterGenerationParameters
+    {
+        public const int DigitalSignatureUsage = 1;
+        public const int KeyEstablishmentUsage = 2;
+
+        private readonly int l;
+        private readonly int n;
+        private readonly int certainty;
+        private readonly SecureRandom random;
+        private readonly int usageIndex;
+
+        /**
+         * Construct without a usage index, this will do a random construction of G.
+         *
+         * @param L desired length of prime P in bits (the effective key size).
+         * @param N desired length of prime Q in bits.
+         * @param certainty certainty level for prime number generation.
+         * @param random the source of randomness to use.
+         */
+        public DsaParameterGenerationParameters(int L, int N, int certainty, SecureRandom random)
+            : this(L, N, certainty, random, -1)
+        {
+        }
+
+        /**
+         * Construct for a specific usage index - this has the effect of using verifiable canonical generation of G.
+         *
+         * @param L desired length of prime P in bits (the effective key size).
+         * @param N desired length of prime Q in bits.
+         * @param certainty certainty level for prime number generation.
+         * @param random the source of randomness to use.
+         * @param usageIndex a valid usage index.
+         */
+        public DsaParameterGenerationParameters(int L, int N, int certainty, SecureRandom random, int usageIndex)
+        {
+            this.l = L;
+            this.n = N;
+            this.certainty = certainty;
+            this.random = random;
+            this.usageIndex = usageIndex;
+        }
+
+        public virtual int L
+        {
+            get { return l; }
+        }
+
+        public virtual int N
+        {
+            get { return n; }
+        }
+
+        public virtual int UsageIndex
+        {
+            get { return usageIndex; }
+        }
+
+        public virtual int Certainty
+        {
+            get { return certainty; }
+        }
+
+        public virtual SecureRandom Random
+        {
+            get { return random; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DesEdeParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DesEdeParameters.cs
new file mode 100644
index 0000000..420aaec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DesEdeParameters.cs
@@ -0,0 +1,95 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DesEdeParameters
+		: DesParameters
+    {
+        /*
+        * DES-EDE Key length in bytes.
+        */
+		public const int DesEdeKeyLength = 24;
+
+		private static byte[] FixKey(
+			byte[]	key,
+			int		keyOff,
+			int		keyLen)
+		{
+			byte[] tmp = new byte[24];
+
+			switch (keyLen)
+			{
+				case 16:
+					Array.Copy(key, keyOff, tmp, 0, 16);
+					Array.Copy(key, keyOff, tmp, 16, 8);
+					break;
+				case 24:
+					Array.Copy(key, keyOff, tmp, 0, 24);
+					break;
+				default:
+					throw new ArgumentException("Bad length for DESede key: " + keyLen, "keyLen");
+			}
+
+			if (IsWeakKey(tmp))
+				throw new ArgumentException("attempt to create weak DESede key");
+
+			return tmp;
+		}
+
+		public DesEdeParameters(
+            byte[] key)
+			: base(FixKey(key, 0, key.Length))
+        {
+        }
+
+		public DesEdeParameters(
+			byte[]	key,
+			int		keyOff,
+			int		keyLen)
+			: base(FixKey(key, keyOff, keyLen))
+		{
+		}
+
+		/**
+         * return true if the passed in key is a DES-EDE weak key.
+         *
+         * @param key bytes making up the key
+         * @param offset offset into the byte array the key starts at
+         * @param length number of bytes making up the key
+         */
+        public static bool IsWeakKey(
+            byte[]  key,
+            int     offset,
+            int     length)
+        {
+            for (int i = offset; i < length; i += DesKeyLength)
+            {
+                if (DesParameters.IsWeakKey(key, i))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        /**
+         * return true if the passed in key is a DES-EDE weak key.
+         *
+         * @param key bytes making up the key
+         * @param offset offset into the byte array the key starts at
+         */
+        public static new bool IsWeakKey(
+            byte[]	key,
+            int		offset)
+        {
+            return IsWeakKey(key, offset, key.Length - offset);
+        }
+
+		public static new bool IsWeakKey(
+			byte[] key)
+		{
+			return IsWeakKey(key, 0, key.Length);
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DesParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DesParameters.cs
new file mode 100644
index 0000000..ee37cd8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DesParameters.cs
@@ -0,0 +1,130 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DesParameters
+		: KeyParameter
+    {
+        public DesParameters(
+            byte[] key)
+			: base(key)
+        {
+            if (IsWeakKey(key))
+				throw new ArgumentException("attempt to create weak DES key");
+        }
+
+		public DesParameters(
+			byte[]	key,
+			int		keyOff,
+			int		keyLen)
+			: base(key, keyOff, keyLen)
+		{
+			if (IsWeakKey(key, keyOff))
+				throw new ArgumentException("attempt to create weak DES key");
+		}
+
+		/*
+        * DES Key Length in bytes.
+        */
+        public const int DesKeyLength = 8;
+
+        /*
+        * Table of weak and semi-weak keys taken from Schneier pp281
+        */
+        private const int N_DES_WEAK_KEYS = 16;
+
+        private static readonly byte[] DES_weak_keys =
+        {
+            /* weak keys */
+            (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+            (byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+            (byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+            (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+
+            /* semi-weak keys */
+            (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+            (byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+            (byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+            (byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+            (byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+            (byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+            (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+            (byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+            (byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+            (byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+            (byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+            (byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+        };
+
+        /**
+        * DES has 16 weak keys.  This method will check
+        * if the given DES key material is weak or semi-weak.
+        * Key material that is too short is regarded as weak.
+        * <p>
+        * See <a href="http://www.counterpane.com/applied.html">"Applied
+        * Cryptography"</a> by Bruce Schneier for more information.
+        * </p>
+        * @return true if the given DES key material is weak or semi-weak,
+        *     false otherwise.
+        */
+        public static bool IsWeakKey(
+            byte[]	key,
+            int		offset)
+        {
+            if (key.Length - offset < DesKeyLength)
+                throw new ArgumentException("key material too short.");
+
+			//nextkey:
+            for (int i = 0; i < N_DES_WEAK_KEYS; i++)
+            {
+                bool unmatch = false;
+                for (int j = 0; j < DesKeyLength; j++)
+                {
+                    if (key[j + offset] != DES_weak_keys[i * DesKeyLength + j])
+                    {
+                        //continue nextkey;
+                        unmatch = true;
+						break;
+                    }
+                }
+
+				if (!unmatch)
+				{
+					return true;
+				}
+            }
+
+			return false;
+        }
+
+		public static bool IsWeakKey(
+			byte[] key)
+		{
+			return IsWeakKey(key, 0);
+		}
+
+		/**
+        * DES Keys use the LSB as the odd parity bit.  This can
+        * be used to check for corrupt keys.
+        *
+        * @param bytes the byte array to set the parity on.
+        */
+        public static void SetOddParity(
+            byte[] bytes)
+        {
+            for (int i = 0; i < bytes.Length; i++)
+            {
+                int b = bytes[i];
+                bytes[i] = (byte)((b & 0xfe) |
+                                ((((b >> 1) ^
+                                (b >> 2) ^
+                                (b >> 3) ^
+                                (b >> 4) ^
+                                (b >> 5) ^
+                                (b >> 6) ^
+                                (b >> 7)) ^ 0x01) & 0x01));
+            }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyGenerationParameters.cs
new file mode 100644
index 0000000..86d6f5b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyGenerationParameters.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaKeyGenerationParameters
+		: KeyGenerationParameters
+    {
+        private readonly DsaParameters parameters;
+
+        public DsaKeyGenerationParameters(
+            SecureRandom	random,
+            DsaParameters	parameters)
+			: base(random, parameters.P.BitLength - 1)
+        {
+            this.parameters = parameters;
+        }
+
+		public DsaParameters Parameters
+        {
+            get { return parameters; }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyParameters.cs
new file mode 100644
index 0000000..5fe6d7a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaKeyParameters.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public abstract class DsaKeyParameters
+		: AsymmetricKeyParameter
+    {
+		private readonly DsaParameters parameters;
+
+		protected DsaKeyParameters(
+            bool			isPrivate,
+            DsaParameters	parameters)
+			: base(isPrivate)
+        {
+			// Note: parameters may be null
+            this.parameters = parameters;
+        }
+
+		public DsaParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			DsaKeyParameters other = obj as DsaKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			DsaKeyParameters other)
+		{
+			return Platform.Equals(parameters, other.parameters)
+				&& base.Equals(other);
+		}
+
+		public override int GetHashCode()
+		{
+			int hc = base.GetHashCode();
+
+			if (parameters != null)
+			{
+				hc ^= parameters.GetHashCode();
+			}
+
+			return hc;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaParameters.cs
new file mode 100644
index 0000000..50d080e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaParameters.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaParameters
+		: ICipherParameters
+    {
+        private readonly BigInteger p, q , g;
+        private readonly DsaValidationParameters validation;
+
+		public DsaParameters(
+            BigInteger	p,
+            BigInteger	q,
+            BigInteger	g)
+			: this(p, q, g, null)
+        {
+        }
+
+		public DsaParameters(
+            BigInteger				p,
+            BigInteger				q,
+            BigInteger				g,
+            DsaValidationParameters	parameters)
+        {
+			if (p == null)
+				throw new ArgumentNullException("p");
+			if (q == null)
+				throw new ArgumentNullException("q");
+			if (g == null)
+				throw new ArgumentNullException("g");
+
+			this.p = p;
+            this.q = q;
+			this.g = g;
+			this.validation = parameters;
+        }
+
+        public BigInteger P
+        {
+            get { return p; }
+        }
+
+		public BigInteger Q
+        {
+            get { return q; }
+        }
+
+		public BigInteger G
+        {
+            get { return g; }
+        }
+
+		public DsaValidationParameters ValidationParameters
+        {
+			get { return validation; }
+        }
+
+		public override bool Equals(
+			object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DsaParameters other = obj as DsaParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DsaParameters other)
+		{
+			return p.Equals(other.p) && q.Equals(other.q) && g.Equals(other.g);
+		}
+
+		public override int GetHashCode()
+        {
+			return p.GetHashCode() ^ q.GetHashCode() ^ g.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPrivateKeyParameters.cs
new file mode 100644
index 0000000..2abdd0e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPrivateKeyParameters.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaPrivateKeyParameters
+		: DsaKeyParameters
+    {
+        private readonly BigInteger x;
+
+		public DsaPrivateKeyParameters(
+            BigInteger		x,
+            DsaParameters	parameters)
+			: base(true, parameters)
+        {
+			if (x == null)
+				throw new ArgumentNullException("x");
+
+			this.x = x;
+        }
+
+		public BigInteger X
+        {
+            get { return x; }
+        }
+
+		public override bool Equals(
+			object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DsaPrivateKeyParameters other = obj as DsaPrivateKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DsaPrivateKeyParameters other)
+		{
+			return x.Equals(other.x) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+            return x.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPublicKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPublicKeyParameters.cs
new file mode 100644
index 0000000..f11f858
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaPublicKeyParameters.cs
@@ -0,0 +1,52 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaPublicKeyParameters
+		: DsaKeyParameters
+    {
+        private readonly BigInteger y;
+
+		public DsaPublicKeyParameters(
+            BigInteger		y,
+            DsaParameters	parameters)
+			: base(false, parameters)
+        {
+			if (y == null)
+				throw new ArgumentNullException("y");
+
+			this.y = y;
+        }
+
+		public BigInteger Y
+        {
+            get { return y; }
+        }
+
+		public override bool Equals(object obj)
+        {
+			if (obj == this)
+				return true;
+
+			DsaPublicKeyParameters other = obj as DsaPublicKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			DsaPublicKeyParameters other)
+		{
+			return y.Equals(other.y) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+			return y.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/DsaValidationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaValidationParameters.cs
new file mode 100644
index 0000000..c2f84c7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/DsaValidationParameters.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class DsaValidationParameters
+    {
+        private readonly byte[] seed;
+        private readonly int counter;
+        private readonly int usageIndex;
+
+        public DsaValidationParameters(byte[] seed, int counter)
+            : this(seed, counter, -1)
+        {
+        }
+
+        public DsaValidationParameters(
+            byte[]	seed,
+            int		counter,
+            int     usageIndex)
+        {
+            if (seed == null)
+                throw new ArgumentNullException("seed");
+
+            this.seed = (byte[]) seed.Clone();
+            this.counter = counter;
+            this.usageIndex = usageIndex;
+        }
+
+        public virtual byte[] GetSeed()
+        {
+            return (byte[]) seed.Clone();
+        }
+
+        public virtual int Counter
+        {
+            get { return counter; }
+        }
+
+        public virtual int UsageIndex
+        {
+            get { return usageIndex; }
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            DsaValidationParameters other = obj as DsaValidationParameters;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        protected virtual bool Equals(
+            DsaValidationParameters other)
+        {
+            return counter == other.counter
+                && Arrays.AreEqual(seed, other.seed);
+        }
+
+        public override int GetHashCode()
+        {
+            return counter.GetHashCode() ^ Arrays.GetHashCode(seed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ECDomainParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ECDomainParameters.cs
new file mode 100644
index 0000000..619971a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ECDomainParameters.cs
@@ -0,0 +1,116 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ECDomainParameters
+    {
+        internal ECCurve     curve;
+        internal byte[]      seed;
+        internal ECPoint     g;
+        internal BigInteger  n;
+        internal BigInteger  h;
+
+        public ECDomainParameters(
+            ECCurve     curve,
+            ECPoint     g,
+            BigInteger  n)
+            : this(curve, g, n, BigInteger.One)
+        {
+        }
+
+        public ECDomainParameters(
+            ECCurve     curve,
+            ECPoint     g,
+            BigInteger  n,
+            BigInteger  h)
+            : this(curve, g, n, h, null)
+        {
+        }
+
+        public ECDomainParameters(
+            ECCurve     curve,
+            ECPoint     g,
+            BigInteger  n,
+            BigInteger  h,
+            byte[]      seed)
+        {
+            if (curve == null)
+                throw new ArgumentNullException("curve");
+            if (g == null)
+                throw new ArgumentNullException("g");
+            if (n == null)
+                throw new ArgumentNullException("n");
+            if (h == null)
+                throw new ArgumentNullException("h");
+
+            this.curve = curve;
+            this.g = g.Normalize();
+            this.n = n;
+            this.h = h;
+            this.seed = Arrays.Clone(seed);
+        }
+
+        public ECCurve Curve
+        {
+            get { return curve; }
+        }
+
+        public ECPoint G
+        {
+            get { return g; }
+        }
+
+        public BigInteger N
+        {
+            get { return n; }
+        }
+
+        public BigInteger H
+        {
+            get { return h; }
+        }
+
+        public byte[] GetSeed()
+        {
+            return Arrays.Clone(seed);
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            ECDomainParameters other = obj as ECDomainParameters;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        protected bool Equals(
+            ECDomainParameters other)
+        {
+            return curve.Equals(other.curve)
+                &&	g.Equals(other.g)
+                &&	n.Equals(other.n)
+                &&	h.Equals(other.h)
+                &&	Arrays.AreEqual(seed, other.seed);
+        }
+
+        public override int GetHashCode()
+        {
+            return curve.GetHashCode()
+                ^	g.GetHashCode()
+                ^	n.GetHashCode()
+                ^	h.GetHashCode()
+                ^	Arrays.GetHashCode(seed);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyGenerationParameters.cs
new file mode 100644
index 0000000..9b2b988
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyGenerationParameters.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ECKeyGenerationParameters
+		: KeyGenerationParameters
+    {
+        private readonly ECDomainParameters domainParams;
+		private readonly DerObjectIdentifier publicKeyParamSet;
+
+		public ECKeyGenerationParameters(
+			ECDomainParameters	domainParameters,
+			SecureRandom		random)
+			: base(random, domainParameters.N.BitLength)
+        {
+            this.domainParams = domainParameters;
+        }
+
+		public ECKeyGenerationParameters(
+			DerObjectIdentifier	publicKeyParamSet,
+			SecureRandom		random)
+			: this(ECKeyParameters.LookupParameters(publicKeyParamSet), random)
+		{
+			this.publicKeyParamSet = publicKeyParamSet;
+		}
+
+		public ECDomainParameters DomainParameters
+        {
+			get { return domainParams; }
+        }
+
+		public DerObjectIdentifier PublicKeyParamSet
+		{
+			get { return publicKeyParamSet; }
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyParameters.cs
new file mode 100644
index 0000000..70b3543
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ECKeyParameters.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public abstract class ECKeyParameters
+        : AsymmetricKeyParameter
+    {
+        private static readonly string[] algorithms = { "EC", "ECDSA", "ECDH", "ECDHC", "ECGOST3410", "ECMQV" };
+
+        private readonly string algorithm;
+        private readonly ECDomainParameters parameters;
+        private readonly DerObjectIdentifier publicKeyParamSet;
+
+        protected ECKeyParameters(
+            string				algorithm,
+            bool				isPrivate,
+            ECDomainParameters	parameters)
+            : base(isPrivate)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+            if (parameters == null)
+                throw new ArgumentNullException("parameters");
+
+            this.algorithm = VerifyAlgorithmName(algorithm);
+            this.parameters = parameters;
+        }
+
+        protected ECKeyParameters(
+            string				algorithm,
+            bool				isPrivate,
+            DerObjectIdentifier	publicKeyParamSet)
+            : base(isPrivate)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+            if (publicKeyParamSet == null)
+                throw new ArgumentNullException("publicKeyParamSet");
+
+            this.algorithm = VerifyAlgorithmName(algorithm);
+            this.parameters = LookupParameters(publicKeyParamSet);
+            this.publicKeyParamSet = publicKeyParamSet;
+        }
+
+        public string AlgorithmName
+        {
+            get { return algorithm; }
+        }
+
+        public ECDomainParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+        public DerObjectIdentifier PublicKeyParamSet
+        {
+            get { return publicKeyParamSet; }
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            ECDomainParameters other = obj as ECDomainParameters;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        protected bool Equals(
+            ECKeyParameters other)
+        {
+            return parameters.Equals(other.parameters) && base.Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return parameters.GetHashCode() ^ base.GetHashCode();
+        }
+
+        internal ECKeyGenerationParameters CreateKeyGenerationParameters(
+            SecureRandom random)
+        {
+            if (publicKeyParamSet != null)
+            {
+                return new ECKeyGenerationParameters(publicKeyParamSet, random);
+            }
+
+            return new ECKeyGenerationParameters(parameters, random);
+        }
+
+        internal static string VerifyAlgorithmName(string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            if (Array.IndexOf(algorithms, algorithm, 0, algorithms.Length) < 0)
+                throw new ArgumentException("unrecognised algorithm: " + algorithm, "algorithm");
+            return upper;
+        }
+
+        internal static ECDomainParameters LookupParameters(
+            DerObjectIdentifier publicKeyParamSet)
+        {
+            if (publicKeyParamSet == null)
+                throw new ArgumentNullException("publicKeyParamSet");
+
+            ECDomainParameters p = ECGost3410NamedCurves.GetByOid(publicKeyParamSet);
+
+            if (p == null)
+            {
+                X9ECParameters x9 = ECKeyPairGenerator.FindECCurveByOid(publicKeyParamSet);
+
+                if (x9 == null)
+                {
+                    throw new ArgumentException("OID is not a valid public key parameter set", "publicKeyParamSet");
+                }
+
+                p = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+            }
+
+            return p;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ECPrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ECPrivateKeyParameters.cs
new file mode 100644
index 0000000..4d0fa1f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ECPrivateKeyParameters.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ECPrivateKeyParameters
+        : ECKeyParameters
+    {
+        private readonly BigInteger d;
+
+        public ECPrivateKeyParameters(
+            BigInteger			d,
+            ECDomainParameters	parameters)
+            : this("EC", d, parameters)
+        {
+        }
+
+        [Obsolete("Use version with explicit 'algorithm' parameter")]
+        public ECPrivateKeyParameters(
+            BigInteger			d,
+            DerObjectIdentifier publicKeyParamSet)
+            : base("ECGOST3410", true, publicKeyParamSet)
+        {
+            if (d == null)
+                throw new ArgumentNullException("d");
+
+            this.d = d;
+        }
+
+        public ECPrivateKeyParameters(
+            string				algorithm,
+            BigInteger			d,
+            ECDomainParameters	parameters)
+            : base(algorithm, true, parameters)
+        {
+            if (d == null)
+                throw new ArgumentNullException("d");
+
+            this.d = d;
+        }
+
+        public ECPrivateKeyParameters(
+            string				algorithm,
+            BigInteger			d,
+            DerObjectIdentifier publicKeyParamSet)
+            : base(algorithm, true, publicKeyParamSet)
+        {
+            if (d == null)
+                throw new ArgumentNullException("d");
+
+            this.d = d;
+        }
+
+        public BigInteger D
+        {
+            get { return d; }
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            ECPrivateKeyParameters other = obj as ECPrivateKeyParameters;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        protected bool Equals(
+            ECPrivateKeyParameters other)
+        {
+            return d.Equals(other.d) && base.Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return d.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ECPublicKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ECPublicKeyParameters.cs
new file mode 100644
index 0000000..1eb665d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ECPublicKeyParameters.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Globalization;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ECPublicKeyParameters
+        : ECKeyParameters
+    {
+        private readonly ECPoint q;
+
+        public ECPublicKeyParameters(
+            ECPoint				q,
+            ECDomainParameters	parameters)
+            : this("EC", q, parameters)
+        {
+        }
+
+        [Obsolete("Use version with explicit 'algorithm' parameter")]
+        public ECPublicKeyParameters(
+            ECPoint				q,
+            DerObjectIdentifier publicKeyParamSet)
+            : base("ECGOST3410", false, publicKeyParamSet)
+        {
+            if (q == null)
+                throw new ArgumentNullException("q");
+
+            this.q = q.Normalize();
+        }
+
+        public ECPublicKeyParameters(
+            string				algorithm,
+            ECPoint				q,
+            ECDomainParameters	parameters)
+            : base(algorithm, false, parameters)
+        {
+            if (q == null)
+                throw new ArgumentNullException("q");
+
+            this.q = q.Normalize();
+        }
+
+        public ECPublicKeyParameters(
+            string				algorithm,
+            ECPoint				q,
+            DerObjectIdentifier publicKeyParamSet)
+            : base(algorithm, false, publicKeyParamSet)
+        {
+            if (q == null)
+                throw new ArgumentNullException("q");
+
+            this.q = q.Normalize();
+        }
+
+        public ECPoint Q
+        {
+            get { return q; }
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (obj == this)
+                return true;
+
+            ECPublicKeyParameters other = obj as ECPublicKeyParameters;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        protected bool Equals(
+            ECPublicKeyParameters other)
+        {
+            return q.Equals(other.q) && base.Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return q.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyGenerationParameters.cs
new file mode 100644
index 0000000..40ca70d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyGenerationParameters.cs
@@ -0,0 +1,31 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ElGamalKeyGenerationParameters
+		: KeyGenerationParameters
+    {
+        private readonly ElGamalParameters parameters;
+
+		public ElGamalKeyGenerationParameters(
+            SecureRandom		random,
+            ElGamalParameters	parameters)
+			: base(random, GetStrength(parameters))
+        {
+            this.parameters = parameters;
+        }
+
+		public ElGamalParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+		internal static int GetStrength(
+			ElGamalParameters parameters)
+		{
+			return parameters.L != 0 ? parameters.L : parameters.P.BitLength;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyParameters.cs
new file mode 100644
index 0000000..8b6e279
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalKeyParameters.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ElGamalKeyParameters
+		: AsymmetricKeyParameter
+    {
+        private readonly ElGamalParameters parameters;
+
+		protected ElGamalKeyParameters(
+            bool				isPrivate,
+            ElGamalParameters	parameters)
+			: base(isPrivate)
+        {
+			// TODO Should we allow 'parameters' to be null?
+            this.parameters = parameters;
+        }
+
+		public ElGamalParameters Parameters
+        {
+            get { return parameters; }
+        }
+
+		public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return true;
+
+			ElGamalKeyParameters other = obj as ElGamalKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			ElGamalKeyParameters other)
+		{
+			return Platform.Equals(parameters, other.parameters)
+				&& base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+			int hc = base.GetHashCode();
+
+			if (parameters != null)
+			{
+				hc ^= parameters.GetHashCode();
+			}
+
+			return hc;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalParameters.cs
new file mode 100644
index 0000000..ab6d3e7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalParameters.cs
@@ -0,0 +1,81 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ElGamalParameters
+		: ICipherParameters
+    {
+        private readonly BigInteger p, g;
+		private readonly int l;
+
+		public ElGamalParameters(
+            BigInteger	p,
+            BigInteger	g)
+			: this(p, g, 0)
+        {
+        }
+
+		public ElGamalParameters(
+			BigInteger	p,
+			BigInteger	g,
+			int			l)
+		{
+			if (p == null)
+				throw new ArgumentNullException("p");
+			if (g == null)
+				throw new ArgumentNullException("g");
+
+			this.p = p;
+			this.g = g;
+			this.l = l;
+		}
+
+		public BigInteger P
+        {
+            get { return p; }
+        }
+
+		/**
+        * return the generator - g
+        */
+        public BigInteger G
+        {
+            get { return g; }
+        }
+
+		/**
+		 * return private value limit - l
+		 */
+		public int L
+		{
+			get { return l; }
+		}
+
+		public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return true;
+
+			ElGamalParameters other = obj as ElGamalParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			ElGamalParameters other)
+		{
+			return p.Equals(other.p) && g.Equals(other.g) && l == other.l;
+		}
+
+		public override int GetHashCode()
+        {
+            return p.GetHashCode() ^ g.GetHashCode() ^ l;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPrivateKeyParameters.cs
new file mode 100644
index 0000000..6363f2b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPrivateKeyParameters.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ElGamalPrivateKeyParameters
+		: ElGamalKeyParameters
+    {
+        private readonly BigInteger x;
+
+		public ElGamalPrivateKeyParameters(
+            BigInteger			x,
+            ElGamalParameters	parameters)
+			: base(true, parameters)
+        {
+			if (x == null)
+				throw new ArgumentNullException("x");
+
+			this.x = x;
+        }
+
+		public BigInteger X
+        {
+            get { return x; }
+        }
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			ElGamalPrivateKeyParameters other = obj as ElGamalPrivateKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			ElGamalPrivateKeyParameters other)
+		{
+			return other.x.Equals(x) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+		{
+			return x.GetHashCode() ^ base.GetHashCode();
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPublicKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPublicKeyParameters.cs
new file mode 100644
index 0000000..25ac625
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ElGamalPublicKeyParameters.cs
@@ -0,0 +1,53 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ElGamalPublicKeyParameters
+		: ElGamalKeyParameters
+    {
+        private readonly BigInteger y;
+
+		public ElGamalPublicKeyParameters(
+            BigInteger			y,
+            ElGamalParameters	parameters)
+			: base(false, parameters)
+        {
+			if (y == null)
+				throw new ArgumentNullException("y");
+
+			this.y = y;
+        }
+
+		public BigInteger Y
+        {
+            get { return y; }
+        }
+
+		public override bool Equals(
+            object obj)
+        {
+			if (obj == this)
+				return true;
+
+			ElGamalPublicKeyParameters other = obj as ElGamalPublicKeyParameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+        }
+
+		protected bool Equals(
+			ElGamalPublicKeyParameters other)
+		{
+			return y.Equals(other.y) && base.Equals(other);
+		}
+
+		public override int GetHashCode()
+        {
+			return y.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyGenerationParameters.cs
new file mode 100644
index 0000000..b06a5d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyGenerationParameters.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class Gost3410KeyGenerationParameters
+		: KeyGenerationParameters
+	{
+		private readonly Gost3410Parameters parameters;
+		private readonly DerObjectIdentifier publicKeyParamSet;
+
+		public Gost3410KeyGenerationParameters(
+			SecureRandom random,
+			Gost3410Parameters parameters)
+			: base(random, parameters.P.BitLength - 1)
+		{
+			this.parameters = parameters;
+		}
+
+		public Gost3410KeyGenerationParameters(
+			SecureRandom		random,
+			DerObjectIdentifier	publicKeyParamSet)
+			: this(random, LookupParameters(publicKeyParamSet))
+		{
+			this.publicKeyParamSet = publicKeyParamSet;
+		}
+
+		public Gost3410Parameters Parameters
+		{
+			get { return parameters; }
+		}
+
+		public DerObjectIdentifier PublicKeyParamSet
+		{
+			get { return publicKeyParamSet; }
+		}
+
+		private static Gost3410Parameters LookupParameters(
+			DerObjectIdentifier publicKeyParamSet)
+		{
+			if (publicKeyParamSet == null)
+				throw new ArgumentNullException("publicKeyParamSet");
+
+			Gost3410ParamSetParameters p = Gost3410NamedParameters.GetByOid(publicKeyParamSet);
+
+			if (p == null)
+				throw new ArgumentException("OID is not a valid CryptoPro public key parameter set", "publicKeyParamSet");
+
+			return new Gost3410Parameters(p.P, p.Q, p.A);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyParameters.cs
new file mode 100644
index 0000000..f771c4d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410KeyParameters.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public abstract class Gost3410KeyParameters
+		: AsymmetricKeyParameter
+	{
+		private readonly Gost3410Parameters parameters;
+		private readonly DerObjectIdentifier publicKeyParamSet;
+
+		protected Gost3410KeyParameters(
+			bool				isPrivate,
+			Gost3410Parameters	parameters)
+			: base(isPrivate)
+		{
+			this.parameters = parameters;
+		}
+
+		protected Gost3410KeyParameters(
+			bool				isPrivate,
+			DerObjectIdentifier	publicKeyParamSet)
+			: base(isPrivate)
+		{
+			this.parameters = LookupParameters(publicKeyParamSet);
+			this.publicKeyParamSet = publicKeyParamSet;
+		}
+
+		public Gost3410Parameters Parameters
+		{
+			get { return parameters; }
+		}
+
+		public DerObjectIdentifier PublicKeyParamSet
+		{
+			get { return publicKeyParamSet; }
+		}
+
+		// TODO Implement Equals/GetHashCode
+
+		private static Gost3410Parameters LookupParameters(
+			DerObjectIdentifier publicKeyParamSet)
+		{
+			if (publicKeyParamSet == null)
+				throw new ArgumentNullException("publicKeyParamSet");
+
+			Gost3410ParamSetParameters p = Gost3410NamedParameters.GetByOid(publicKeyParamSet);
+
+			if (p == null)
+				throw new ArgumentException("OID is not a valid CryptoPro public key parameter set", "publicKeyParamSet");
+
+			return new Gost3410Parameters(p.P, p.Q, p.A);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410Parameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410Parameters.cs
new file mode 100644
index 0000000..2ec167e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410Parameters.cs
@@ -0,0 +1,86 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class Gost3410Parameters
+		: ICipherParameters
+	{
+		private readonly BigInteger p, q, a;
+		private readonly Gost3410ValidationParameters validation;
+
+		public Gost3410Parameters(
+			BigInteger	p,
+			BigInteger	q,
+			BigInteger	a)
+			: this(p, q, a, null)
+		{
+		}
+
+		public Gost3410Parameters(
+			BigInteger						p,
+			BigInteger						q,
+			BigInteger						a,
+			Gost3410ValidationParameters	validation)
+		{
+			if (p == null)
+				throw new ArgumentNullException("p");
+			if (q == null)
+				throw new ArgumentNullException("q");
+			if (a == null)
+				throw new ArgumentNullException("a");
+
+			this.p = p;
+			this.q = q;
+			this.a = a;
+			this.validation = validation;
+		}
+
+		public BigInteger P
+		{
+			get { return p; }
+		}
+
+		public BigInteger Q
+		{
+			get { return q; }
+		}
+
+		public BigInteger A
+		{
+			get { return a; }
+		}
+
+		public Gost3410ValidationParameters ValidationParameters
+		{
+			get { return validation; }
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			Gost3410Parameters other = obj as Gost3410Parameters;
+
+			if (other == null)
+				return false;
+
+			return Equals(other);
+		}
+
+		protected bool Equals(
+			Gost3410Parameters other)
+		{
+			return p.Equals(other.p) && q.Equals(other.q) && a.Equals(other.a);
+		}
+
+		public override int GetHashCode()
+		{
+			return p.GetHashCode() ^ q.GetHashCode() ^ a.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PrivateKeyParameters.cs
new file mode 100644
index 0000000..e3a613d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PrivateKeyParameters.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class Gost3410PrivateKeyParameters
+		: Gost3410KeyParameters
+	{
+		private readonly BigInteger x;
+
+		public Gost3410PrivateKeyParameters(
+			BigInteger			x,
+			Gost3410Parameters	parameters)
+			: base(true, parameters)
+		{
+			if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0)
+				throw new ArgumentException("Invalid x for GOST3410 private key", "x");
+
+			this.x = x;
+		}
+
+		public Gost3410PrivateKeyParameters(
+			BigInteger			x,
+			DerObjectIdentifier	publicKeyParamSet)
+			: base(true, publicKeyParamSet)
+		{
+			if (x.SignValue < 1 || x.BitLength > 256 || x.CompareTo(Parameters.Q) >= 0)
+				throw new ArgumentException("Invalid x for GOST3410 private key", "x");
+
+			this.x = x;
+		}
+
+		public BigInteger X
+		{
+			get { return x; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PublicKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PublicKeyParameters.cs
new file mode 100644
index 0000000..96b7e91
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410PublicKeyParameters.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class Gost3410PublicKeyParameters
+		: Gost3410KeyParameters
+	{
+		private readonly BigInteger y;
+
+		public Gost3410PublicKeyParameters(
+			BigInteger y,
+			Gost3410Parameters parameters)
+			: base(false, parameters)
+		{
+			if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0)
+				throw new ArgumentException("Invalid y for GOST3410 public key", "y");
+
+			this.y = y;
+		}
+
+		public Gost3410PublicKeyParameters(
+			BigInteger			y,
+			DerObjectIdentifier publicKeyParamSet)
+			: base(false, publicKeyParamSet)
+		{
+			if (y.SignValue < 1 || y.CompareTo(Parameters.P) >= 0)
+				throw new ArgumentException("Invalid y for GOST3410 public key", "y");
+
+			this.y = y;
+		}
+
+		public BigInteger Y
+		{
+			get { return y; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410ValidationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410ValidationParameters.cs
new file mode 100644
index 0000000..21e5af8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/GOST3410ValidationParameters.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class Gost3410ValidationParameters
+	{
+		private int x0;
+		private int c;
+		private long x0L;
+		private long cL;
+
+		public Gost3410ValidationParameters(
+			int x0,
+			int c)
+		{
+			this.x0 = x0;
+			this.c = c;
+		}
+
+		public Gost3410ValidationParameters(
+			long x0L,
+			long cL)
+		{
+			this.x0L = x0L;
+			this.cL = cL;
+		}
+
+		public int C { get { return c; } }
+		public int X0 { get { return x0; } }
+		public long CL { get { return cL; } }
+		public long X0L { get { return x0L; } }
+
+		public override bool Equals(
+			object obj)
+		{
+			Gost3410ValidationParameters other = obj as Gost3410ValidationParameters;
+
+			return other != null
+				&& other.c == this.c
+				&& other.x0 == this.x0
+				&& other.cL == this.cL
+				&& other.x0L == this.x0L;
+		}
+
+		public override int GetHashCode()
+		{
+			return c.GetHashCode() ^ x0.GetHashCode() ^ cL.GetHashCode() ^ x0L.GetHashCode();
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ISO18033KDFParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ISO18033KDFParameters.cs
new file mode 100644
index 0000000..2d8fff8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ISO18033KDFParameters.cs
@@ -0,0 +1,25 @@
+using System;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	/**
+	* parameters for Key derivation functions for ISO-18033
+	*/
+	public class Iso18033KdfParameters
+		: IDerivationParameters
+	{
+		byte[]  seed;
+
+		public Iso18033KdfParameters(
+			byte[]  seed)
+		{
+			this.seed = seed;
+		}
+
+		public byte[] GetSeed()
+		{
+			return seed;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/IesParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/IesParameters.cs
new file mode 100644
index 0000000..d306b2c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/IesParameters.cs
@@ -0,0 +1,49 @@
+using System;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    /**
+     * parameters for using an integrated cipher in stream mode.
+     */
+    public class IesParameters : ICipherParameters
+    {
+        private byte[]  derivation;
+        private byte[]  encoding;
+        private int     macKeySize;
+
+        /**
+         * @param derivation the derivation parameter for the KDF function.
+         * @param encoding the encoding parameter for the KDF function.
+         * @param macKeySize the size of the MAC key (in bits).
+         */
+        public IesParameters(
+            byte[]  derivation,
+            byte[]  encoding,
+            int     macKeySize)
+        {
+            this.derivation = derivation;
+            this.encoding = encoding;
+            this.macKeySize = macKeySize;
+        }
+
+        public byte[] GetDerivationV()
+        {
+            return derivation;
+        }
+
+        public byte[] GetEncodingV()
+        {
+            return encoding;
+        }
+
+        public int MacKeySize
+        {
+			get
+			{
+				return macKeySize;
+			}
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/IesWithCipherParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/IesWithCipherParameters.cs
new file mode 100644
index 0000000..70ef55d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/IesWithCipherParameters.cs
@@ -0,0 +1,33 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class IesWithCipherParameters : IesParameters
+    {
+        private int cipherKeySize;
+
+        /**
+         * @param derivation the derivation parameter for the KDF function.
+         * @param encoding the encoding parameter for the KDF function.
+         * @param macKeySize the size of the MAC key (in bits).
+         * @param cipherKeySize the size of the associated Cipher key (in bits).
+         */
+        public IesWithCipherParameters(
+            byte[]  derivation,
+            byte[]  encoding,
+            int     macKeySize,
+            int     cipherKeySize) : base(derivation, encoding, macKeySize)
+        {
+            this.cipherKeySize = cipherKeySize;
+        }
+
+        public int CipherKeySize
+        {
+            get
+            {
+                return cipherKeySize;
+            }
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/KdfParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/KdfParameters.cs
new file mode 100644
index 0000000..bc5c905
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/KdfParameters.cs
@@ -0,0 +1,33 @@
+using System;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    /**
+     * parameters for Key derivation functions for IEEE P1363a
+     */
+    public class KdfParameters : IDerivationParameters
+    {
+        byte[]  iv;
+        byte[]  shared;
+
+        public KdfParameters(
+            byte[]  shared,
+            byte[]  iv)
+        {
+            this.shared = shared;
+            this.iv = iv;
+        }
+
+        public byte[] GetSharedSecret()
+        {
+            return shared;
+        }
+
+        public byte[] GetIV()
+        {
+            return iv;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/KeyParameter.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/KeyParameter.cs
new file mode 100644
index 0000000..33dff96
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/KeyParameter.cs
@@ -0,0 +1,43 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class KeyParameter
+		: ICipherParameters
+    {
+        private readonly byte[] key;
+
+		public KeyParameter(
+			byte[] key)
+		{
+			if (key == null)
+				throw new ArgumentNullException("key");
+
+			this.key = (byte[]) key.Clone();
+		}
+
+		public KeyParameter(
+            byte[]	key,
+            int		keyOff,
+            int		keyLen)
+        {
+			if (key == null)
+				throw new ArgumentNullException("key");
+			if (keyOff < 0 || keyOff > key.Length)
+				throw new ArgumentOutOfRangeException("keyOff");
+			if (keyLen < 0 || (keyOff + keyLen) > key.Length)
+				throw new ArgumentOutOfRangeException("keyLen");
+
+			this.key = new byte[keyLen];
+            Array.Copy(key, keyOff, this.key, 0, keyLen);
+        }
+
+		public byte[] GetKey()
+        {
+			return (byte[]) key.Clone();
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/MgfParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/MgfParameters.cs
new file mode 100644
index 0000000..11983b8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/MgfParameters.cs
@@ -0,0 +1,31 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	/// <remarks>Parameters for mask derivation functions.</remarks>
+    public class MgfParameters
+		: IDerivationParameters
+    {
+        private readonly byte[] seed;
+
+		public MgfParameters(
+            byte[] seed)
+			: this(seed, 0, seed.Length)
+        {
+        }
+
+		public MgfParameters(
+            byte[]  seed,
+            int     off,
+            int     len)
+        {
+            this.seed = new byte[len];
+            Array.Copy(seed, off, this.seed, 0, len);
+        }
+
+		public byte[] GetSeed()
+        {
+            return (byte[]) seed.Clone();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPrivateParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPrivateParameters.cs
new file mode 100644
index 0000000..4bf33e3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPrivateParameters.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class MqvPrivateParameters
+		: ICipherParameters
+	{
+		private readonly ECPrivateKeyParameters staticPrivateKey;
+		private readonly ECPrivateKeyParameters ephemeralPrivateKey;
+		private readonly ECPublicKeyParameters ephemeralPublicKey;
+		
+		public MqvPrivateParameters(
+			ECPrivateKeyParameters	staticPrivateKey,
+			ECPrivateKeyParameters	ephemeralPrivateKey)
+			: this(staticPrivateKey, ephemeralPrivateKey, null)
+		{
+		}
+
+		public MqvPrivateParameters(
+			ECPrivateKeyParameters	staticPrivateKey,
+			ECPrivateKeyParameters	ephemeralPrivateKey,
+			ECPublicKeyParameters	ephemeralPublicKey)
+		{
+			this.staticPrivateKey = staticPrivateKey;
+			this.ephemeralPrivateKey = ephemeralPrivateKey;
+			this.ephemeralPublicKey = ephemeralPublicKey;
+		}
+
+		public ECPrivateKeyParameters StaticPrivateKey
+		{
+			get { return staticPrivateKey; }
+		}
+
+		public ECPrivateKeyParameters EphemeralPrivateKey
+		{
+			get { return ephemeralPrivateKey; }
+		}
+
+		public ECPublicKeyParameters EphemeralPublicKey
+		{
+			get { return ephemeralPublicKey; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPublicParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPublicParameters.cs
new file mode 100644
index 0000000..a0e273a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/MqvPublicParameters.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class MqvPublicParameters
+		: ICipherParameters
+	{
+		private readonly ECPublicKeyParameters staticPublicKey;
+		private readonly ECPublicKeyParameters ephemeralPublicKey;
+
+		public MqvPublicParameters(
+			ECPublicKeyParameters	staticPublicKey,
+			ECPublicKeyParameters	ephemeralPublicKey)
+		{
+			this.staticPublicKey = staticPublicKey;
+			this.ephemeralPublicKey = ephemeralPublicKey;
+		}
+
+		public ECPublicKeyParameters StaticPublicKey
+		{
+			get { return staticPublicKey; }
+		}
+
+		public ECPublicKeyParameters EphemeralPublicKey
+		{
+			get { return ephemeralPublicKey; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs
new file mode 100644
index 0000000..5b40525
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyGenerationParameters.cs
@@ -0,0 +1,101 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	/**
+	 * Parameters for NaccacheStern public private key generation. For details on
+	 * this cipher, please see
+	 *
+	 * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	 */
+	public class NaccacheSternKeyGenerationParameters : KeyGenerationParameters
+	{
+		// private BigInteger publicExponent;
+		private readonly int certainty;
+		private readonly int countSmallPrimes;
+		private bool debug;
+
+		/**
+		 * Parameters for generating a NaccacheStern KeyPair.
+		 *
+		 * @param random
+		 *            The source of randomness
+		 * @param strength
+		 *            The desired strength of the Key in Bits
+		 * @param certainty
+		 *            the probability that the generated primes are not really prime
+		 *            as integer: 2^(-certainty) is then the probability
+		 * @param countSmallPrimes
+		 *            How many small key factors are desired
+		 */
+		public NaccacheSternKeyGenerationParameters(
+			SecureRandom	random,
+			int				strength,
+			int				certainty,
+			int				countSmallPrimes)
+			: this(random, strength, certainty, countSmallPrimes, false)
+		{
+		}
+
+		/**
+		 * Parameters for a NaccacheStern KeyPair.
+		 *
+		 * @param random
+		 *            The source of randomness
+		 * @param strength
+		 *            The desired strength of the Key in Bits
+		 * @param certainty
+		 *            the probability that the generated primes are not really prime
+		 *            as integer: 2^(-certainty) is then the probability
+		 * @param cntSmallPrimes
+		 *            How many small key factors are desired
+		 * @param debug
+		 *            Turn debugging on or off (reveals secret information, use with
+		 *            caution)
+		 */
+		public NaccacheSternKeyGenerationParameters(SecureRandom random,
+			int		strength,
+			int		certainty,
+			int		countSmallPrimes,
+			bool	debug)
+			: base(random, strength)
+		{
+			if (countSmallPrimes % 2 == 1)
+			{
+				throw new ArgumentException("countSmallPrimes must be a multiple of 2");
+			}
+			if (countSmallPrimes < 30)
+			{
+				throw new ArgumentException("countSmallPrimes must be >= 30 for security reasons");
+			}
+			this.certainty = certainty;
+			this.countSmallPrimes = countSmallPrimes;
+			this.debug = debug;
+		}
+
+		/**
+		 * @return Returns the certainty.
+		 */
+		public int Certainty
+		{
+			get { return certainty; }
+		}
+
+		/**
+		 * @return Returns the countSmallPrimes.
+		 */
+		public int CountSmallPrimes
+		{
+			get { return countSmallPrimes; }
+		}
+
+		public bool IsDebug
+		{
+			get { return debug; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyParameters.cs
new file mode 100644
index 0000000..8be7ad8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternKeyParameters.cs
@@ -0,0 +1,44 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	/**
+	 * Public key parameters for NaccacheStern cipher. For details on this cipher,
+	 * please see
+	 *
+	 * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	 */
+	public class NaccacheSternKeyParameters : AsymmetricKeyParameter
+	{
+		private readonly BigInteger g, n;
+		private readonly int lowerSigmaBound;
+
+		/**
+		 * @param privateKey
+		 */
+		public NaccacheSternKeyParameters(bool privateKey, BigInteger g, BigInteger n, int lowerSigmaBound)
+			: base(privateKey)
+		{
+			this.g = g;
+			this.n = n;
+			this.lowerSigmaBound = lowerSigmaBound;
+		}
+
+		/**
+		 * @return Returns the g.
+		 */
+		public BigInteger G { get  { return g; } }
+
+		/**
+		 * @return Returns the lowerSigmaBound.
+		 */
+		public int LowerSigmaBound { get { return lowerSigmaBound; } }
+
+		/**
+		 * @return Returns the n.
+		 */
+		public BigInteger Modulus { get { return n; } }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs
new file mode 100644
index 0000000..0e1fe14
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/NaccacheSternPrivateKeyParameters.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	/**
+	 * Private key parameters for NaccacheStern cipher. For details on this cipher,
+	 * please see
+	 *
+	 * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	 */
+	public class NaccacheSternPrivateKeyParameters : NaccacheSternKeyParameters
+	{
+		private readonly BigInteger phiN;
+		private readonly IList smallPrimes;
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public NaccacheSternPrivateKeyParameters(
+            BigInteger g,
+            BigInteger n,
+            int lowerSigmaBound,
+            ArrayList smallPrimes,
+            BigInteger phiN)
+            : base(true, g, n, lowerSigmaBound)
+        {
+            this.smallPrimes = smallPrimes;
+            this.phiN = phiN;
+        }
+#endif
+
+		/**
+		 * Constructs a NaccacheSternPrivateKey
+		 *
+		 * @param g
+		 *            the public enryption parameter g
+		 * @param n
+		 *            the public modulus n = p*q
+		 * @param lowerSigmaBound
+		 *            the public lower sigma bound up to which data can be encrypted
+		 * @param smallPrimes
+		 *            the small primes, of which sigma is constructed in the right
+		 *            order
+		 * @param phi_n
+		 *            the private modulus phi(n) = (p-1)(q-1)
+		 */
+		public NaccacheSternPrivateKeyParameters(
+			BigInteger	g,
+			BigInteger	n,
+			int			lowerSigmaBound,
+			IList       smallPrimes,
+			BigInteger	phiN)
+			: base(true, g, n, lowerSigmaBound)
+		{
+			this.smallPrimes = smallPrimes;
+			this.phiN = phiN;
+		}
+
+		public BigInteger PhiN
+		{
+			get { return phiN; }
+		}
+
+#if !SILVERLIGHT
+        [Obsolete("Use 'SmallPrimesList' instead")]
+        public ArrayList SmallPrimes
+		{
+			get { return new ArrayList(smallPrimes); }
+		}
+#endif
+
+        public IList SmallPrimesList
+        {
+            get { return smallPrimes; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithIV.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithIV.cs
new file mode 100644
index 0000000..11a8b77
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithIV.cs
@@ -0,0 +1,43 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ParametersWithIV
+		: ICipherParameters
+    {
+		private readonly ICipherParameters	parameters;
+		private readonly byte[]				iv;
+
+		public ParametersWithIV(
+            ICipherParameters	parameters,
+            byte[]				iv)
+			: this(parameters, iv, 0, iv.Length)
+		{
+		}
+
+		public ParametersWithIV(
+            ICipherParameters	parameters,
+            byte[]				iv,
+            int					ivOff,
+            int					ivLen)
+        {
+            // NOTE: 'parameters' may be null to imply key re-use
+			if (iv == null)
+				throw new ArgumentNullException("iv");
+
+			this.parameters = parameters;
+			this.iv = new byte[ivLen];
+            Array.Copy(iv, ivOff, this.iv, 0, ivLen);
+        }
+
+		public byte[] GetIV()
+        {
+			return (byte[]) iv.Clone();
+        }
+
+		public ICipherParameters Parameters
+        {
+            get { return parameters; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithRandom.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithRandom.cs
new file mode 100644
index 0000000..a05e774
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithRandom.cs
@@ -0,0 +1,48 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class ParametersWithRandom
+		: ICipherParameters
+    {
+        private readonly ICipherParameters	parameters;
+		private readonly SecureRandom		random;
+
+		public ParametersWithRandom(
+            ICipherParameters	parameters,
+            SecureRandom		random)
+        {
+			if (parameters == null)
+				throw new ArgumentNullException("random");
+			if (random == null)
+				throw new ArgumentNullException("random");
+
+			this.parameters = parameters;
+			this.random = random;
+		}
+
+		public ParametersWithRandom(
+            ICipherParameters parameters)
+			: this(parameters, new SecureRandom())
+        {
+		}
+
+		[Obsolete("Use Random property instead")]
+		public SecureRandom GetRandom()
+		{
+			return Random;
+		}
+
+		public SecureRandom Random
+        {
+			get { return random; }
+        }
+
+		public ICipherParameters Parameters
+        {
+            get { return parameters; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSBox.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSBox.cs
new file mode 100644
index 0000000..6473796
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSBox.cs
@@ -0,0 +1,24 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class ParametersWithSBox : ICipherParameters
+	{
+		private ICipherParameters  parameters;
+		private byte[] sBox;
+
+		public ParametersWithSBox(
+			ICipherParameters parameters,
+			byte[] sBox)
+		{
+			this.parameters = parameters;
+			this.sBox = sBox;
+		}
+
+		public byte[] GetSBox() { return sBox; }
+
+		public ICipherParameters Parameters { get { return parameters; } }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSalt.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSalt.cs
new file mode 100644
index 0000000..7f4cd6c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/ParametersWithSalt.cs
@@ -0,0 +1,39 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+    /// <summary> Cipher parameters with a fixed salt value associated with them.</summary>
+    public class ParametersWithSalt : ICipherParameters
+    {
+        private byte[] salt;
+        private ICipherParameters parameters;
+
+        public ParametersWithSalt(ICipherParameters parameters, byte[] salt):this(parameters, salt, 0, salt.Length)
+        {
+        }
+
+        public ParametersWithSalt(ICipherParameters parameters, byte[] salt, int saltOff, int saltLen)
+        {
+            this.salt = new byte[saltLen];
+            this.parameters = parameters;
+
+            Array.Copy(salt, saltOff, this.salt, 0, saltLen);
+        }
+
+        public byte[] GetSalt()
+        {
+            return salt;
+        }
+
+        public ICipherParameters Parameters
+        {
+            get
+            {
+                return parameters;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RC2Parameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RC2Parameters.cs
new file mode 100644
index 0000000..7a6d5bb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RC2Parameters.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class RC2Parameters
+		: KeyParameter
+	{
+		private readonly int bits;
+
+		public RC2Parameters(
+			byte[] key)
+			: this(key, (key.Length > 128) ? 1024 : (key.Length * 8))
+		{
+		}
+
+		public RC2Parameters(
+			byte[]	key,
+			int		keyOff,
+			int		keyLen)
+			: this(key, keyOff, keyLen, (keyLen > 128) ? 1024 : (keyLen * 8))
+		{
+		}
+
+		public RC2Parameters(
+			byte[]	key,
+			int		bits)
+			: base(key)
+		{
+			this.bits = bits;
+		}
+
+		public RC2Parameters(
+			byte[]	key,
+			int		keyOff,
+			int		keyLen,
+			int		bits)
+			: base(key, keyOff, keyLen)
+		{
+			this.bits = bits;
+		}
+
+		public int EffectiveKeyBits
+		{
+			get { return bits; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RC5Parameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RC5Parameters.cs
new file mode 100644
index 0000000..88a59e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RC5Parameters.cs
@@ -0,0 +1,27 @@
+using System;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class RC5Parameters
+		: KeyParameter
+    {
+        private readonly int rounds;
+
+		public RC5Parameters(
+            byte[]	key,
+            int		rounds)
+			: base(key)
+        {
+            if (key.Length > 255)
+                throw new ArgumentException("RC5 key length can be no greater than 255");
+
+			this.rounds = rounds;
+        }
+
+		public int Rounds
+        {
+			get { return rounds; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RSABlindingParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RSABlindingParameters.cs
new file mode 100644
index 0000000..49c7bcc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RSABlindingParameters.cs
@@ -0,0 +1,34 @@
+using System;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class RsaBlindingParameters
+		: ICipherParameters
+	{
+		private readonly RsaKeyParameters	publicKey;
+		private readonly BigInteger			blindingFactor;
+
+		public RsaBlindingParameters(
+			RsaKeyParameters	publicKey,
+			BigInteger			blindingFactor)
+		{
+			if (publicKey.IsPrivate)
+				throw new ArgumentException("RSA parameters should be for a public key");
+
+			this.publicKey = publicKey;
+			this.blindingFactor = blindingFactor;
+		}
+
+		public RsaKeyParameters PublicKey
+		{
+			get { return publicKey; }
+		}
+
+		public BigInteger BlindingFactor
+		{
+			get { return blindingFactor; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyGenerationParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyGenerationParameters.cs
new file mode 100644
index 0000000..619ab65
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyGenerationParameters.cs
@@ -0,0 +1,55 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class RsaKeyGenerationParameters
+		: KeyGenerationParameters
+    {
+        private readonly BigInteger publicExponent;
+        private readonly int certainty;
+
+		public RsaKeyGenerationParameters(
+            BigInteger		publicExponent,
+            SecureRandom	random,
+            int				strength,
+            int				certainty)
+			: base(random, strength)
+        {
+            this.publicExponent = publicExponent;
+            this.certainty = certainty;
+        }
+
+		public BigInteger PublicExponent
+        {
+			get { return publicExponent; }
+        }
+
+		public int Certainty
+        {
+			get { return certainty; }
+        }
+
+		public override bool Equals(
+			object obj)
+		{
+			RsaKeyGenerationParameters other = obj as RsaKeyGenerationParameters;
+
+			if (other == null)
+			{
+				return false;
+			}
+
+			return certainty == other.certainty
+				&& publicExponent.Equals(other.publicExponent);
+		}
+
+		public override int GetHashCode()
+		{
+			return certainty.GetHashCode() ^ publicExponent.GetHashCode();
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyParameters.cs
new file mode 100644
index 0000000..72c0d80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaKeyParameters.cs
@@ -0,0 +1,63 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+	public class RsaKeyParameters
+		: AsymmetricKeyParameter
+    {
+        private readonly BigInteger modulus;
+        private readonly BigInteger exponent;
+
+		public RsaKeyParameters(
+            bool		isPrivate,
+            BigInteger	modulus,
+            BigInteger	exponent)
+			: base(isPrivate)
+        {
+			if (modulus == null)
+				throw new ArgumentNullException("modulus");
+			if (exponent == null)
+				throw new ArgumentNullException("exponent");
+			if (modulus.SignValue <= 0)
+				throw new ArgumentException("Not a valid RSA modulus", "modulus");
+			if (exponent.SignValue <= 0)
+				throw new ArgumentException("Not a valid RSA exponent", "exponent");
+
+			this.modulus = modulus;
+			this.exponent = exponent;
+        }
+
+		public BigInteger Modulus
+        {
+            get { return modulus; }
+        }
+
+		public BigInteger Exponent
+        {
+            get { return exponent; }
+        }
+
+		public override bool Equals(
+			object obj)
+        {
+            RsaKeyParameters kp = obj as RsaKeyParameters;
+
+			if (kp == null)
+			{
+				return false;
+			}
+
+			return kp.IsPrivate == this.IsPrivate
+				&& kp.Modulus.Equals(this.modulus)
+				&& kp.Exponent.Equals(this.exponent);
+        }
+
+		public override int GetHashCode()
+        {
+            return modulus.GetHashCode() ^ exponent.GetHashCode() ^ IsPrivate.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs
new file mode 100644
index 0000000..7bd8abd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/RsaPrivateCrtKeyParameters.cs
@@ -0,0 +1,104 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+    public class RsaPrivateCrtKeyParameters
+		: RsaKeyParameters
+    {
+        private readonly BigInteger e, p, q, dP, dQ, qInv;
+
+		public RsaPrivateCrtKeyParameters(
+            BigInteger	modulus,
+            BigInteger	publicExponent,
+            BigInteger	privateExponent,
+            BigInteger	p,
+            BigInteger	q,
+            BigInteger	dP,
+            BigInteger	dQ,
+            BigInteger	qInv)
+			: base(true, modulus, privateExponent)
+        {
+			ValidateValue(publicExponent, "publicExponent", "exponent");
+			ValidateValue(p, "p", "P value");
+			ValidateValue(q, "q", "Q value");
+			ValidateValue(dP, "dP", "DP value");
+			ValidateValue(dQ, "dQ", "DQ value");
+			ValidateValue(qInv, "qInv", "InverseQ value");
+
+			this.e = publicExponent;
+            this.p = p;
+            this.q = q;
+            this.dP = dP;
+            this.dQ = dQ;
+            this.qInv = qInv;
+        }
+
+		public BigInteger PublicExponent
+        {
+            get { return e; }
+		}
+
+		public BigInteger P
+		{
+			get { return p; }
+		}
+
+		public BigInteger Q
+		{
+			get { return q; }
+		}
+
+		public BigInteger DP
+		{
+			get { return dP; }
+		}
+
+		public BigInteger DQ
+		{
+			get { return dQ; }
+		}
+
+		public BigInteger QInv
+		{
+			get { return qInv; }
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			RsaPrivateCrtKeyParameters kp = obj as RsaPrivateCrtKeyParameters;
+
+			if (kp == null)
+				return false;
+
+			return kp.DP.Equals(dP)
+				&& kp.DQ.Equals(dQ)
+				&& kp.Exponent.Equals(this.Exponent)
+				&& kp.Modulus.Equals(this.Modulus)
+				&& kp.P.Equals(p)
+				&& kp.Q.Equals(q)
+				&& kp.PublicExponent.Equals(e)
+				&& kp.QInv.Equals(qInv);
+		}
+
+		public override int GetHashCode()
+		{
+			return DP.GetHashCode() ^ DQ.GetHashCode() ^ Exponent.GetHashCode() ^ Modulus.GetHashCode()
+				^ P.GetHashCode() ^ Q.GetHashCode() ^ PublicExponent.GetHashCode() ^ QInv.GetHashCode();
+		}
+
+		private static void ValidateValue(BigInteger x, string name, string desc)
+		{
+			if (x == null)
+				throw new ArgumentNullException(name);
+			if (x.SignValue <= 0)
+				throw new ArgumentException("Not a valid RSA " + desc, name);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/SkeinParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/SkeinParameters.cs
new file mode 100644
index 0000000..f1f5f33
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/SkeinParameters.cs
@@ -0,0 +1,285 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+	/// <summary>
+	/// Parameters for the Skein hash function - a series of byte[] strings identified by integer tags.
+	/// </summary>
+	/// <remarks>
+	/// Parameterised Skein can be used for:
+	/// <ul> 
+	/// <li>MAC generation, by providing a <see cref="SkeinParameters.Builder.SetKey(byte[])">key</see>.</li>
+	/// <li>Randomised hashing, by providing a <see cref="SkeinParameters.Builder.SetNonce(byte[])">nonce</see>.</li>
+	/// <li>A hash function for digital signatures, associating a
+	/// <see cref="SkeinParameters.Builder.SetPublicKey(byte[])">public key</see> with the message digest.</li>
+	/// <li>A key derivation function, by providing a
+	/// <see cref="SkeinParameters.Builder.SetKeyIdentifier(byte[])">key identifier</see>.</li>
+	/// <li>Personalised hashing, by providing a
+	/// <see cref="SkeinParameters.Builder.SetPersonalisation(DateTime,string,string)">recommended format</see> or
+	/// <see cref="SkeinParameters.Builder.SetPersonalisation(byte[])">arbitrary</see> personalisation string.</li>
+	/// </ul>
+	/// </remarks>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinEngine"/>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Digests.SkeinDigest"/>
+	/// <seealso cref="Org.BouncyCastle.Crypto.Macs.SkeinMac"/>
+	public class SkeinParameters
+		: ICipherParameters
+	{
+		/// <summary>
+		/// The parameter type for a secret key, supporting MAC or KDF functions: 0
+		/// </summary>
+		public const int PARAM_TYPE_KEY = 0;
+
+		/// <summary>
+		/// The parameter type for the Skein configuration block: 4
+		/// </summary>
+		public const int PARAM_TYPE_CONFIG = 4;
+
+		/// <summary>
+		/// The parameter type for a personalisation string: 8
+		/// </summary>
+		public const int PARAM_TYPE_PERSONALISATION = 8;
+
+		/// <summary>
+		/// The parameter type for a public key: 12
+		/// </summary>
+		public const int PARAM_TYPE_PUBLIC_KEY = 12;
+
+		/// <summary>
+		/// The parameter type for a key identifier string: 16
+		/// </summary>
+		public const int PARAM_TYPE_KEY_IDENTIFIER = 16;
+
+		/// <summary>
+		/// The parameter type for a nonce: 20
+		/// </summary>
+		public const int PARAM_TYPE_NONCE = 20;
+
+		/// <summary>
+		/// The parameter type for the message: 48
+		/// </summary>
+		public const int PARAM_TYPE_MESSAGE = 48;
+
+		/// <summary>
+		/// The parameter type for the output transformation: 63
+		/// </summary>
+		public const int PARAM_TYPE_OUTPUT = 63;
+
+		private IDictionary parameters;
+
+		public SkeinParameters()
+			: this(Platform.CreateHashtable())
+
+		{
+		}
+
+		private SkeinParameters(IDictionary parameters)
+		{
+			this.parameters = parameters;
+		}
+
+		/// <summary>
+		/// Obtains a map of type (int) to value (byte[]) for the parameters tracked in this object.
+		/// </summary>
+		public IDictionary GetParameters()
+		{
+			return parameters;
+		}
+
+		/// <summary>
+		/// Obtains the value of the <see cref="PARAM_TYPE_KEY">key parameter</see>, or <code>null</code> if not
+		/// set.
+		/// </summary>
+		/// <returns>The key.</returns>
+		public byte[] GetKey()
+		{
+			return (byte[])parameters[PARAM_TYPE_KEY];
+		}
+
+		/// <summary>
+		/// Obtains the value of the <see cref="PARAM_TYPE_PERSONALISATION">personalisation parameter</see>, or
+		/// <code>null</code> if not set.
+		/// </summary>
+		public byte[] GetPersonalisation()
+		{
+			return (byte[])parameters[PARAM_TYPE_PERSONALISATION];
+		}
+
+		/// <summary>
+		/// Obtains the value of the <see cref="PARAM_TYPE_PUBLIC_KEY">public key parameter</see>, or
+		/// <code>null</code> if not set.
+		/// </summary>
+		public byte[] GetPublicKey()
+		{
+			return (byte[])parameters[PARAM_TYPE_PUBLIC_KEY];
+		}
+
+		/// <summary>
+		/// Obtains the value of the <see cref="PARAM_TYPE_KEY_IDENTIFIER">key identifier parameter</see>, or
+		/// <code>null</code> if not set.
+		/// </summary>
+		public byte[] GetKeyIdentifier()
+		{
+			return (byte[])parameters[PARAM_TYPE_KEY_IDENTIFIER];
+		}
+
+		/// <summary>
+		/// Obtains the value of the <see cref="PARAM_TYPE_NONCE">nonce parameter</see>, or <code>null</code> if
+		/// not set.
+		/// </summary>
+		public byte[] GetNonce()
+		{
+			return (byte[])parameters[PARAM_TYPE_NONCE];
+		}
+
+		/// <summary>
+		/// A builder for <see cref="SkeinParameters"/>.
+		/// </summary>
+		public class Builder
+		{
+			private IDictionary parameters = Platform.CreateHashtable();
+
+			public Builder()
+			{
+			}
+
+			public Builder(IDictionary paramsMap)
+			{
+				IEnumerator keys = paramsMap.Keys.GetEnumerator();
+				while (keys.MoveNext())
+				{
+					int key = (int)keys.Current;
+					parameters.Add(key, paramsMap[key]);
+				}
+			}
+
+			public Builder(SkeinParameters parameters)
+			{
+				IEnumerator keys = parameters.parameters.Keys.GetEnumerator();
+				while (keys.MoveNext())
+				{
+					int key = (int)keys.Current;
+					this.parameters.Add(key, parameters.parameters[key]);
+				}
+			}
+
+			/// <summary>
+			/// Sets a parameters to apply to the Skein hash function.
+			/// </summary>
+			/// <remarks>
+			/// Parameter types must be in the range 0,5..62, and cannot use the value 48
+			/// (reserved for message body).
+			/// <p/>
+			/// Parameters with type < 48 are processed before
+			/// the message content, parameters with type > 48
+			/// are processed after the message and prior to output.
+			/// </remarks>
+			/// <param name="type">the type of the parameter, in the range 5..62.</param>
+			/// <param name="value">the byte sequence of the parameter.</param>
+			public Builder Set(int type, byte[] value)
+			{
+				if (value == null)
+				{
+					throw new ArgumentException("Parameter value must not be null.");
+				}
+				if ((type != PARAM_TYPE_KEY)
+				    && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE))
+				{
+					throw new ArgumentException("Parameter types must be in the range 0,5..47,49..62.");
+				}
+				if (type == PARAM_TYPE_CONFIG)
+				{
+					throw new ArgumentException("Parameter type " + PARAM_TYPE_CONFIG
+					                            + " is reserved for internal use.");
+				}
+				this.parameters.Add(type, value);
+				return this;
+			}
+
+			/// <summary>
+			/// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY"/> parameter.
+			/// </summary>
+			public Builder SetKey(byte[] key)
+			{
+				return Set(PARAM_TYPE_KEY, key);
+			}
+
+			/// <summary>
+			/// Sets the <see cref="SkeinParameters.PARAM_TYPE_PERSONALISATION"/> parameter.
+			/// </summary>
+			public Builder SetPersonalisation(byte[] personalisation)
+			{
+				return Set(PARAM_TYPE_PERSONALISATION, personalisation);
+			}
+
+			/// <summary>
+			/// Implements the recommended personalisation format for Skein defined in Section 4.11 of
+			/// the Skein 1.3 specification.
+			/// </summary>
+			/// <remarks>
+			/// The format is <code>YYYYMMDD email at address distinguisher</code>, encoded to a byte
+			/// sequence using UTF-8 encoding.
+			/// </remarks>
+			/// <param name="date">the date the personalised application of the Skein was defined.</param>
+			/// <param name="emailAddress">the email address of the creation of the personalised application.</param>
+			/// <param name="distinguisher">an arbitrary personalisation string distinguishing the application.</param>
+			public Builder SetPersonalisation(DateTime date, string emailAddress, string distinguisher)
+			{
+				try
+				{
+					MemoryStream bout = new MemoryStream();
+					StreamWriter outBytes = new StreamWriter(bout, System.Text.Encoding.UTF8);
+					outBytes.Write(date.ToString("YYYYMMDD"));
+					outBytes.Write(" ");
+					outBytes.Write(emailAddress);
+					outBytes.Write(" ");
+					outBytes.Write(distinguisher);
+					outBytes.Dispose();
+					return Set(PARAM_TYPE_PERSONALISATION, bout.ToArray());
+				}
+				catch (IOException e)
+				{
+					throw new InvalidOperationException("Byte I/O failed.", e);
+				}
+			}
+
+			/// <summary>
+			/// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+			/// </summary>
+			public Builder SetPublicKey(byte[] publicKey)
+			{
+				return Set(PARAM_TYPE_PUBLIC_KEY, publicKey);
+			}
+
+			/// <summary>
+			/// Sets the <see cref="SkeinParameters.PARAM_TYPE_KEY_IDENTIFIER"/> parameter.
+			/// </summary>
+			public Builder SetKeyIdentifier(byte[] keyIdentifier)
+			{
+				return Set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier);
+			}
+
+			/// <summary>
+			/// Sets the <see cref="SkeinParameters.PARAM_TYPE_NONCE"/> parameter.
+			/// </summary>
+			public Builder SetNonce(byte[] nonce)
+			{
+				return Set(PARAM_TYPE_NONCE, nonce);
+			}
+
+			/// <summary>
+			/// Constructs a new <see cref="SkeinParameters"/> instance with the parameters provided to this
+			/// builder.
+			/// </summary>
+			public SkeinParameters Build()
+			{
+				return new SkeinParameters(parameters);
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/parameters/TweakableBlockCipherParameters.cs b/BouncyCastle.AxCrypt/src/crypto/parameters/TweakableBlockCipherParameters.cs
new file mode 100644
index 0000000..f757266
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/parameters/TweakableBlockCipherParameters.cs
@@ -0,0 +1,40 @@
+using System;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Parameters
+{
+
+	/// <summary>
+	/// Parameters for tweakable block ciphers.
+	/// </summary>
+	public class TweakableBlockCipherParameters
+		: ICipherParameters
+	{
+		private readonly byte[] tweak;
+		private readonly KeyParameter key;
+
+		public TweakableBlockCipherParameters(KeyParameter key, byte[] tweak)
+		{
+			this.key = key;
+			this.tweak = Arrays.Clone(tweak);
+		}
+
+		/// <summary>
+		/// Gets the key.
+		/// </summary>
+		/// <value>the key to use, or <code>null</code> to use the current key.</value>
+		public KeyParameter Key
+		{
+			get { return key; }
+		}
+
+		/// <summary>
+		/// Gets the tweak value.
+		/// </summary>
+		/// <value>The tweak to use, or <code>null</code> to use the current tweak.</value>
+		public byte[] Tweak
+		{
+			get { return tweak; }
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/CryptoApiRandomGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/CryptoApiRandomGenerator.cs
new file mode 100644
index 0000000..d815656
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/CryptoApiRandomGenerator.cs
@@ -0,0 +1,66 @@
+#if !NETCF_1_0 && !PCL
+
+using System;
+using System.Security.Cryptography;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+	/// <summary>
+	/// Uses Microsoft's RNGCryptoServiceProvider
+	/// </summary>
+	public class CryptoApiRandomGenerator
+		: IRandomGenerator
+	{
+		private readonly RandomNumberGenerator rndProv;
+
+		public CryptoApiRandomGenerator()
+			: this(new RNGCryptoServiceProvider())
+		{
+		}
+
+		public CryptoApiRandomGenerator(RandomNumberGenerator rng)
+		{
+			this.rndProv = rng;
+		}
+
+		#region IRandomGenerator Members
+
+		public virtual void AddSeedMaterial(byte[] seed)
+		{
+			// We don't care about the seed
+		}
+
+		public virtual void AddSeedMaterial(long seed)
+		{
+			// We don't care about the seed
+		}
+
+		public virtual void NextBytes(byte[] bytes)
+		{
+			rndProv.GetBytes(bytes);
+		}
+
+		public virtual void NextBytes(byte[] bytes, int start, int len)
+		{
+			if (start < 0)
+				throw new ArgumentException("Start offset cannot be negative", "start");
+			if (bytes.Length < (start + len))
+				throw new ArgumentException("Byte array too small for requested offset and length");
+
+			if (bytes.Length == len && start == 0) 
+			{
+				NextBytes(bytes);
+			}
+			else 
+			{
+				byte[] tmpBuf = new byte[len];
+				rndProv.GetBytes(tmpBuf);
+				Array.Copy(tmpBuf, 0, bytes, start, len);
+			}
+		}
+
+		#endregion
+	}
+}
+
+#endif
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/DigestRandomGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/DigestRandomGenerator.cs
new file mode 100644
index 0000000..cbd2ef0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/DigestRandomGenerator.cs
@@ -0,0 +1,129 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+	/**
+	 * Random generation based on the digest with counter. Calling AddSeedMaterial will
+	 * always increase the entropy of the hash.
+	 * <p>
+	 * Internal access to the digest is synchronized so a single one of these can be shared.
+	 * </p>
+	 */
+	public class DigestRandomGenerator
+		: IRandomGenerator
+	{
+		private const long CYCLE_COUNT = 10;
+
+		private long	stateCounter;
+		private long	seedCounter;
+		private IDigest	digest;
+		private byte[]	state;
+		private byte[]	seed;
+
+		public DigestRandomGenerator(
+			IDigest digest)
+		{
+			this.digest = digest;
+
+			this.seed = new byte[digest.GetDigestSize()];
+			this.seedCounter = 1;
+
+			this.state = new byte[digest.GetDigestSize()];
+			this.stateCounter = 1;
+		}
+
+		public void AddSeedMaterial(
+			byte[] inSeed)
+		{
+			lock (this)
+			{
+				DigestUpdate(inSeed);
+				DigestUpdate(seed);
+				DigestDoFinal(seed);
+			}
+		}
+
+		public void AddSeedMaterial(
+			long rSeed)
+		{
+			lock (this)
+			{
+				DigestAddCounter(rSeed);
+				DigestUpdate(seed);
+				DigestDoFinal(seed);
+			}
+		}
+
+		public void NextBytes(
+			byte[] bytes)
+		{
+			NextBytes(bytes, 0, bytes.Length);
+		}
+
+		public void NextBytes(
+			byte[]	bytes,
+			int		start,
+			int		len)
+		{
+			lock (this)
+			{
+				int stateOff = 0;
+
+				GenerateState();
+
+				int end = start + len;
+				for (int i = start; i < end; ++i)
+				{
+					if (stateOff == state.Length)
+					{
+						GenerateState();
+						stateOff = 0;
+					}
+					bytes[i] = state[stateOff++];
+				}
+			}
+		}
+
+		private void CycleSeed()
+		{
+			DigestUpdate(seed);
+			DigestAddCounter(seedCounter++);
+			DigestDoFinal(seed);
+		}
+
+		private void GenerateState()
+		{
+			DigestAddCounter(stateCounter++);
+			DigestUpdate(state);
+			DigestUpdate(seed);
+			DigestDoFinal(state);
+
+			if ((stateCounter % CYCLE_COUNT) == 0)
+			{
+				CycleSeed();
+			}
+		}
+
+		private void DigestAddCounter(long seedVal)
+		{
+			ulong seed = (ulong)seedVal;
+			for (int i = 0; i != 8; i++)
+			{
+				digest.Update((byte)seed);
+				seed >>= 8;
+			}
+		}
+
+		private void DigestUpdate(byte[] inSeed)
+		{
+			digest.BlockUpdate(inSeed, 0, inSeed.Length);
+		}
+
+		private void DigestDoFinal(byte[] result)
+		{
+			digest.DoFinal(result, 0);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/IRandomGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/IRandomGenerator.cs
new file mode 100644
index 0000000..8dbe406
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/IRandomGenerator.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+	/// <remarks>Generic interface for objects generating random bytes.</remarks>
+	public interface IRandomGenerator
+	{
+		/// <summary>Add more seed material to the generator.</summary>
+		/// <param name="seed">A byte array to be mixed into the generator's state.</param>
+		void AddSeedMaterial(byte[] seed);
+
+		/// <summary>Add more seed material to the generator.</summary>
+		/// <param name="seed">A long value to be mixed into the generator's state.</param>
+		void AddSeedMaterial(long seed);
+
+		/// <summary>Fill byte array with random values.</summary>
+		/// <param name="bytes">Array to be filled.</param>
+		void NextBytes(byte[] bytes);
+
+		/// <summary>Fill byte array with random values.</summary>
+		/// <param name="bytes">Array to receive bytes.</param>
+		/// <param name="start">Index to start filling at.</param>
+		/// <param name="len">Length of segment to fill.</param>
+		void NextBytes(byte[] bytes, int start, int len);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/ReversedWindowGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/ReversedWindowGenerator.cs
new file mode 100644
index 0000000..dd28c52
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/ReversedWindowGenerator.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+	/// <remarks>
+	/// Takes bytes generated by an underling RandomGenerator and reverses the order in
+	/// each small window (of configurable size).
+	/// <p>
+	/// Access to internals is synchronized so a single one of these can be shared.
+	/// </p>
+	/// </remarks>
+	public class ReversedWindowGenerator
+		: IRandomGenerator
+	{
+		private readonly IRandomGenerator generator;
+
+		private byte[] window;
+		private int windowCount;
+
+		public ReversedWindowGenerator(
+			IRandomGenerator	generator,
+			int					windowSize)
+		{
+			if (generator == null)
+				throw new ArgumentNullException("generator");
+			if (windowSize < 2)
+				throw new ArgumentException("Window size must be at least 2", "windowSize");
+
+			this.generator = generator;
+			this.window = new byte[windowSize];
+		}
+
+		/// <summary>Add more seed material to the generator.</summary>
+		/// <param name="seed">A byte array to be mixed into the generator's state.</param>
+		public virtual void AddSeedMaterial(
+			byte[] seed)
+		{
+			lock (this)
+			{
+				windowCount = 0;
+				generator.AddSeedMaterial(seed);
+			}
+		}
+
+		/// <summary>Add more seed material to the generator.</summary>
+		/// <param name="seed">A long value to be mixed into the generator's state.</param>
+		public virtual void AddSeedMaterial(
+			long seed)
+		{
+			lock (this)
+			{
+				windowCount = 0;
+				generator.AddSeedMaterial(seed);
+			}
+		}
+
+		/// <summary>Fill byte array with random values.</summary>
+		/// <param name="bytes">Array to be filled.</param>
+		public virtual void NextBytes(
+			byte[] bytes)
+		{
+			doNextBytes(bytes, 0, bytes.Length);
+		}
+
+		/// <summary>Fill byte array with random values.</summary>
+		/// <param name="bytes">Array to receive bytes.</param>
+		/// <param name="start">Index to start filling at.</param>
+		/// <param name="len">Length of segment to fill.</param>
+		public virtual void NextBytes(
+			byte[]	bytes,
+			int		start,
+			int		len)
+		{
+			doNextBytes(bytes, start, len);
+		}
+
+		private void doNextBytes(
+			byte[]	bytes,
+			int		start,
+			int		len)
+		{
+			lock (this)
+			{
+				int done = 0;
+				while (done < len)
+				{
+					if (windowCount < 1)
+					{
+						generator.NextBytes(window, 0, window.Length);
+						windowCount = window.Length;
+					}
+
+					bytes[start + done++] = window[--windowCount];
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/ThreadedSeedGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/ThreadedSeedGenerator.cs
new file mode 100644
index 0000000..a6c1a4a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/ThreadedSeedGenerator.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+	/**
+	 * A thread based seed generator - one source of randomness.
+	 * <p>
+	 * Based on an idea from Marcus Lippert.
+	 * </p>
+	 */
+	public class ThreadedSeedGenerator
+	{
+		private class SeedGenerator
+		{
+#if NETCF_1_0
+			// No volatile keyword, but all fields implicitly volatile anyway
+			private int		counter = 0;
+			private bool	stop = false;
+#else
+			private volatile int	counter = 0;
+			private volatile bool	stop = false;
+#endif
+
+			private void Run(object ignored)
+			{
+				while (!this.stop)
+				{
+					this.counter++;
+				}
+			}
+
+			public byte[] GenerateSeed(
+				int		numBytes,
+				bool	fast)
+			{
+#if SILVERLIGHT
+                return DoGenerateSeed(numBytes, fast);
+#else
+                ThreadPriority originalPriority = Thread.CurrentThread.Priority;
+                try
+                {
+                    Thread.CurrentThread.Priority = ThreadPriority.Normal;
+                    return DoGenerateSeed(numBytes, fast);
+                }
+                finally
+                {
+                    Thread.CurrentThread.Priority = originalPriority;
+                }
+#endif
+            }
+
+            private byte[] DoGenerateSeed(
+				int		numBytes,
+				bool	fast)
+            {
+                this.counter = 0;
+				this.stop = false;
+
+				byte[] result = new byte[numBytes];
+				int last = 0;
+				int end = fast ? numBytes : numBytes * 8;
+
+				ThreadPool.QueueUserWorkItem(new WaitCallback(Run));
+
+				for (int i = 0; i < end; i++)
+				{
+				    using (var mre = new ManualResetEvent(false))
+				    {
+				        while (this.counter == last)
+				        {
+				            try
+				            {
+				                mre.WaitOne(1);
+				            }
+				            catch (Exception)
+				            {
+				                // ignore
+				            }
+				        }
+				    }
+
+				    last = this.counter;
+
+					if (fast)
+					{
+						result[i] = (byte) last;
+					}
+					else
+					{
+						int bytepos = i / 8;
+						result[bytepos] = (byte) ((result[bytepos] << 1) | (last & 1));
+					}
+				}
+
+				this.stop = true;
+
+				return result;
+			}
+		}
+
+		/**
+		 * Generate seed bytes. Set fast to false for best quality.
+		 * <p>
+		 * If fast is set to true, the code should be round about 8 times faster when
+		 * generating a long sequence of random bytes. 20 bytes of random values using
+		 * the fast mode take less than half a second on a Nokia e70. If fast is set to false,
+		 * it takes round about 2500 ms.
+		 * </p>
+		 * @param numBytes the number of bytes to generate
+		 * @param fast true if fast mode should be used
+		 */
+		public byte[] GenerateSeed(
+			int		numBytes,
+			bool	fast)
+		{
+			return new SeedGenerator().GenerateSeed(numBytes, fast);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/prng/VMPCRandomGenerator.cs b/BouncyCastle.AxCrypt/src/crypto/prng/VMPCRandomGenerator.cs
new file mode 100644
index 0000000..64f287d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/prng/VMPCRandomGenerator.cs
@@ -0,0 +1,114 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Prng
+{
+    public class VmpcRandomGenerator
+        : IRandomGenerator 
+    {
+        private byte n = 0;
+
+        /// <remarks>
+        /// Permutation generated by code:
+        /// <code>
+        /// // First 1850 fractional digit of Pi number. 
+        /// byte[] key = new BigInteger("14159265358979323846...5068006422512520511").ToByteArray();
+        /// s = 0;
+        /// P = new byte[256];
+        /// for (int i = 0; i < 256; i++) 
+        /// {
+        ///     P[i] = (byte) i;
+        /// }
+        /// for (int m = 0; m < 768; m++) 
+        /// {
+        ///     s = P[(s + P[m & 0xff] + key[m % key.length]) & 0xff];
+        ///     byte temp = P[m & 0xff];
+        ///     P[m & 0xff] = P[s & 0xff];
+        ///     P[s & 0xff] = temp;
+        /// } </code>
+        /// </remarks>
+        private byte[] P =
+        {
+            (byte) 0xbb, (byte) 0x2c, (byte) 0x62, (byte) 0x7f, (byte) 0xb5, (byte) 0xaa, (byte) 0xd4,
+            (byte) 0x0d, (byte) 0x81, (byte) 0xfe, (byte) 0xb2, (byte) 0x82, (byte) 0xcb, (byte) 0xa0, (byte) 0xa1,
+            (byte) 0x08, (byte) 0x18, (byte) 0x71, (byte) 0x56, (byte) 0xe8, (byte) 0x49, (byte) 0x02, (byte) 0x10,
+            (byte) 0xc4, (byte) 0xde, (byte) 0x35, (byte) 0xa5, (byte) 0xec, (byte) 0x80, (byte) 0x12, (byte) 0xb8,
+            (byte) 0x69, (byte) 0xda, (byte) 0x2f, (byte) 0x75, (byte) 0xcc, (byte) 0xa2, (byte) 0x09, (byte) 0x36,
+            (byte) 0x03, (byte) 0x61, (byte) 0x2d, (byte) 0xfd, (byte) 0xe0, (byte) 0xdd, (byte) 0x05, (byte) 0x43,
+            (byte) 0x90, (byte) 0xad, (byte) 0xc8, (byte) 0xe1, (byte) 0xaf, (byte) 0x57, (byte) 0x9b, (byte) 0x4c,
+            (byte) 0xd8, (byte) 0x51, (byte) 0xae, (byte) 0x50, (byte) 0x85, (byte) 0x3c, (byte) 0x0a, (byte) 0xe4,
+            (byte) 0xf3, (byte) 0x9c, (byte) 0x26, (byte) 0x23, (byte) 0x53, (byte) 0xc9, (byte) 0x83, (byte) 0x97,
+            (byte) 0x46, (byte) 0xb1, (byte) 0x99, (byte) 0x64, (byte) 0x31, (byte) 0x77, (byte) 0xd5, (byte) 0x1d,
+            (byte) 0xd6, (byte) 0x78, (byte) 0xbd, (byte) 0x5e, (byte) 0xb0, (byte) 0x8a, (byte) 0x22, (byte) 0x38,
+            (byte) 0xf8, (byte) 0x68, (byte) 0x2b, (byte) 0x2a, (byte) 0xc5, (byte) 0xd3, (byte) 0xf7, (byte) 0xbc,
+            (byte) 0x6f, (byte) 0xdf, (byte) 0x04, (byte) 0xe5, (byte) 0x95, (byte) 0x3e, (byte) 0x25, (byte) 0x86,
+            (byte) 0xa6, (byte) 0x0b, (byte) 0x8f, (byte) 0xf1, (byte) 0x24, (byte) 0x0e, (byte) 0xd7, (byte) 0x40,
+            (byte) 0xb3, (byte) 0xcf, (byte) 0x7e, (byte) 0x06, (byte) 0x15, (byte) 0x9a, (byte) 0x4d, (byte) 0x1c,
+            (byte) 0xa3, (byte) 0xdb, (byte) 0x32, (byte) 0x92, (byte) 0x58, (byte) 0x11, (byte) 0x27, (byte) 0xf4,
+            (byte) 0x59, (byte) 0xd0, (byte) 0x4e, (byte) 0x6a, (byte) 0x17, (byte) 0x5b, (byte) 0xac, (byte) 0xff,
+            (byte) 0x07, (byte) 0xc0, (byte) 0x65, (byte) 0x79, (byte) 0xfc, (byte) 0xc7, (byte) 0xcd, (byte) 0x76,
+            (byte) 0x42, (byte) 0x5d, (byte) 0xe7, (byte) 0x3a, (byte) 0x34, (byte) 0x7a, (byte) 0x30, (byte) 0x28,
+            (byte) 0x0f, (byte) 0x73, (byte) 0x01, (byte) 0xf9, (byte) 0xd1, (byte) 0xd2, (byte) 0x19, (byte) 0xe9,
+            (byte) 0x91, (byte) 0xb9, (byte) 0x5a, (byte) 0xed, (byte) 0x41, (byte) 0x6d, (byte) 0xb4, (byte) 0xc3,
+            (byte) 0x9e, (byte) 0xbf, (byte) 0x63, (byte) 0xfa, (byte) 0x1f, (byte) 0x33, (byte) 0x60, (byte) 0x47,
+            (byte) 0x89, (byte) 0xf0, (byte) 0x96, (byte) 0x1a, (byte) 0x5f, (byte) 0x93, (byte) 0x3d, (byte) 0x37,
+            (byte) 0x4b, (byte) 0xd9, (byte) 0xa8, (byte) 0xc1, (byte) 0x1b, (byte) 0xf6, (byte) 0x39, (byte) 0x8b,
+            (byte) 0xb7, (byte) 0x0c, (byte) 0x20, (byte) 0xce, (byte) 0x88, (byte) 0x6e, (byte) 0xb6, (byte) 0x74,
+            (byte) 0x8e, (byte) 0x8d, (byte) 0x16, (byte) 0x29, (byte) 0xf2, (byte) 0x87, (byte) 0xf5, (byte) 0xeb,
+            (byte) 0x70, (byte) 0xe3, (byte) 0xfb, (byte) 0x55, (byte) 0x9f, (byte) 0xc6, (byte) 0x44, (byte) 0x4a,
+            (byte) 0x45, (byte) 0x7d, (byte) 0xe2, (byte) 0x6b, (byte) 0x5c, (byte) 0x6c, (byte) 0x66, (byte) 0xa9,
+            (byte) 0x8c, (byte) 0xee, (byte) 0x84, (byte) 0x13, (byte) 0xa7, (byte) 0x1e, (byte) 0x9d, (byte) 0xdc,
+            (byte) 0x67, (byte) 0x48, (byte) 0xba, (byte) 0x2e, (byte) 0xe6, (byte) 0xa4, (byte) 0xab, (byte) 0x7c,
+            (byte) 0x94, (byte) 0x00, (byte) 0x21, (byte) 0xef, (byte) 0xea, (byte) 0xbe, (byte) 0xca, (byte) 0x72,
+            (byte) 0x4f, (byte) 0x52, (byte) 0x98, (byte) 0x3f, (byte) 0xc2, (byte) 0x14, (byte) 0x7b, (byte) 0x3b,
+            (byte) 0x54
+        };
+
+        /// <remarks>Value generated in the same way as <c>P</c>.</remarks>
+        private byte s = (byte) 0xbe;
+
+        public VmpcRandomGenerator()
+        {
+        }
+
+        public virtual void AddSeedMaterial(byte[] seed) 
+        {
+            for (int m = 0; m < seed.Length; m++) 
+            {
+                s = P[(s + P[n & 0xff] + seed[m]) & 0xff];
+                byte temp = P[n & 0xff];
+                P[n & 0xff] = P[s & 0xff];
+                P[s & 0xff] = temp;
+                n = (byte) ((n + 1) & 0xff);
+            }
+        }
+
+        public virtual void AddSeedMaterial(long seed) 
+        {
+            AddSeedMaterial(Pack.UInt64_To_BE((ulong)seed));
+        }
+
+        public virtual void NextBytes(byte[] bytes) 
+        {
+            NextBytes(bytes, 0, bytes.Length);
+        }
+
+        public virtual void NextBytes(byte[] bytes, int start, int len) 
+        {
+            lock (P) 
+            {
+                int end = start + len;
+                for (int i = start; i != end; i++) 
+                {
+                    s = P[(s + P[n & 0xff]) & 0xff];
+                    bytes[i] = P[(P[(P[s & 0xff]) & 0xff] + 1) & 0xff];
+                    byte temp = P[n & 0xff];
+                    P[n & 0xff] = P[s & 0xff];
+                    P[s & 0xff] = temp;
+                    n = (byte) ((n + 1) & 0xff);
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/DsaDigestSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/DsaDigestSigner.cs
new file mode 100644
index 0000000..aee7134
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/DsaDigestSigner.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	public class DsaDigestSigner
+		: ISigner
+	{
+		private readonly IDigest digest;
+		private readonly IDsa dsaSigner;
+		private bool forSigning;
+
+		public DsaDigestSigner(
+			IDsa	signer,
+			IDigest	digest)
+		{
+			this.digest = digest;
+			this.dsaSigner = signer;
+		}
+
+		public string AlgorithmName
+		{
+			get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
+		}
+
+		public void Init(
+			bool							forSigning,
+			ICipherParameters	parameters)
+		{
+			this.forSigning = forSigning;
+
+			AsymmetricKeyParameter k;
+
+			if (parameters is ParametersWithRandom)
+			{
+				k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+			}
+			else
+			{
+				k = (AsymmetricKeyParameter)parameters;
+			}
+
+			if (forSigning && !k.IsPrivate)
+				throw new InvalidKeyException("Signing Requires Private Key.");
+
+			if (!forSigning && k.IsPrivate)
+				throw new InvalidKeyException("Verification Requires Public Key.");
+
+			Reset();
+
+			dsaSigner.Init(forSigning, parameters);
+		}
+
+		/**
+		 * update the internal digest with the byte b
+		 */
+		public void Update(
+			byte input)
+		{
+			digest.Update(input);
+		}
+
+		/**
+		 * update the internal digest with the byte array in
+		 */
+		public void BlockUpdate(
+			byte[]	input,
+			int			inOff,
+			int			length)
+		{
+			digest.BlockUpdate(input, inOff, length);
+		}
+
+		/**
+		 * Generate a signature for the message we've been loaded with using
+		 * the key we were initialised with.
+     */
+		public byte[] GenerateSignature()
+		{
+			if (!forSigning)
+				throw new InvalidOperationException("DSADigestSigner not initialised for signature generation.");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			BigInteger[] sig = dsaSigner.GenerateSignature(hash);
+
+			return DerEncode(sig[0], sig[1]);
+		}
+
+		/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
+		public bool VerifySignature(
+			byte[] signature)
+		{
+			if (forSigning)
+				throw new InvalidOperationException("DSADigestSigner not initialised for verification");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			try
+			{
+				BigInteger[] sig = DerDecode(signature);
+				return dsaSigner.VerifySignature(hash, sig[0], sig[1]);
+			}
+			catch (IOException)
+			{
+				return false;
+			}
+		}
+
+		/// <summary>Reset the internal state</summary>
+		public void Reset()
+		{
+			digest.Reset();
+		}
+
+		private byte[] DerEncode(
+			BigInteger	r,
+			BigInteger	s)
+		{
+			return new DerSequence(new DerInteger(r), new DerInteger(s)).GetDerEncoded();
+		}
+
+		private BigInteger[] DerDecode(
+			byte[] encoding)
+		{
+			Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+			return new BigInteger[]
+			{
+				((DerInteger) s[0]).Value,
+				((DerInteger) s[1]).Value
+			};
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/DsaSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/DsaSigner.cs
new file mode 100644
index 0000000..bb28add
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/DsaSigner.cs
@@ -0,0 +1,156 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * The Digital Signature Algorithm - as described in "Handbook of Applied
+     * Cryptography", pages 452 - 453.
+     */
+    public class DsaSigner
+        : IDsa
+    {
+        protected readonly IDsaKCalculator kCalculator;
+
+        protected DsaKeyParameters key = null;
+        protected SecureRandom random = null;
+
+        /**
+         * Default configuration, random K values.
+         */
+        public DsaSigner()
+        {
+            this.kCalculator = new RandomDsaKCalculator();
+        }
+
+        /**
+         * Configuration with an alternate, possibly deterministic calculator of K.
+         *
+         * @param kCalculator a K value calculator.
+         */
+        public DsaSigner(IDsaKCalculator kCalculator)
+        {
+            this.kCalculator = kCalculator;
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return "DSA"; }
+        }
+
+        public virtual void Init(bool forSigning, ICipherParameters	parameters)
+        {
+            SecureRandom providedRandom = null;
+
+            if (forSigning)
+            {
+                if (parameters is ParametersWithRandom)
+                {
+                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+                    providedRandom = rParam.Random;
+                    parameters = rParam.Parameters;
+                }
+
+                if (!(parameters is DsaPrivateKeyParameters))
+                    throw new InvalidKeyException("DSA private key required for signing");
+
+                this.key = (DsaPrivateKeyParameters)parameters;
+            }
+            else
+            {
+                if (!(parameters is DsaPublicKeyParameters))
+                    throw new InvalidKeyException("DSA public key required for verification");
+
+                this.key = (DsaPublicKeyParameters)parameters;
+            }
+
+            this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom);
+        }
+
+        /**
+         * Generate a signature for the given message using the key we were
+         * initialised with. For conventional DSA the message should be a SHA-1
+         * hash of the message of interest.
+         *
+         * @param message the message that will be verified later.
+         */
+        public virtual BigInteger[] GenerateSignature(byte[] message)
+        {
+            DsaParameters parameters = key.Parameters;
+            BigInteger q = parameters.Q;
+            BigInteger m = CalculateE(q, message);
+            BigInteger x = ((DsaPrivateKeyParameters)key).X;
+
+            if (kCalculator.IsDeterministic)
+            {
+                kCalculator.Init(q, x, message);
+            }
+            else
+            {
+                kCalculator.Init(q, random);
+            }
+
+            BigInteger k = kCalculator.NextK();
+
+            BigInteger r = parameters.G.ModPow(k, parameters.P).Mod(q);
+
+            k = k.ModInverse(q).Multiply(m.Add(x.Multiply(r)));
+
+            BigInteger s = k.Mod(q);
+
+            return new BigInteger[]{ r, s };
+        }
+
+        /**
+         * return true if the value r and s represent a DSA signature for
+         * the passed in message for standard DSA the message should be a
+         * SHA-1 hash of the real message to be verified.
+         */
+        public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
+        {
+            DsaParameters parameters = key.Parameters;
+            BigInteger q = parameters.Q;
+            BigInteger m = CalculateE(q, message);
+
+            if (r.SignValue <= 0 || q.CompareTo(r) <= 0)
+            {
+                return false;
+            }
+
+            if (s.SignValue <= 0 || q.CompareTo(s) <= 0)
+            {
+                return false;
+            }
+
+            BigInteger w = s.ModInverse(q);
+
+            BigInteger u1 = m.Multiply(w).Mod(q);
+            BigInteger u2 = r.Multiply(w).Mod(q);
+
+            BigInteger p = parameters.P;
+            u1 = parameters.G.ModPow(u1, p);
+            u2 = ((DsaPublicKeyParameters)key).Y.ModPow(u2, p);
+
+            BigInteger v = u1.Multiply(u2).Mod(p).Mod(q);
+
+            return v.Equals(r);
+        }
+
+        protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
+        {
+            int length = System.Math.Min(message.Length, n.BitLength / 8);
+
+            return new BigInteger(1, message, 0, length);
+        }
+
+        protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
+        {
+            return !needed ? null : (provided != null) ? provided : new SecureRandom();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/ECDsaSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/ECDsaSigner.cs
new file mode 100644
index 0000000..9821732
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/ECDsaSigner.cs
@@ -0,0 +1,185 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * EC-DSA as described in X9.62
+     */
+    public class ECDsaSigner
+        : IDsa
+    {
+        protected readonly IDsaKCalculator kCalculator;
+
+        protected ECKeyParameters key = null;
+        protected SecureRandom random = null;
+
+        /**
+         * Default configuration, random K values.
+         */
+        public ECDsaSigner()
+        {
+            this.kCalculator = new RandomDsaKCalculator();
+        }
+
+        /**
+         * Configuration with an alternate, possibly deterministic calculator of K.
+         *
+         * @param kCalculator a K value calculator.
+         */
+        public ECDsaSigner(IDsaKCalculator kCalculator)
+        {
+            this.kCalculator = kCalculator;
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return "ECDSA"; }
+        }
+
+        public virtual void Init(bool forSigning, ICipherParameters parameters)
+        {
+            SecureRandom providedRandom = null;
+
+            if (forSigning)
+            {
+                if (parameters is ParametersWithRandom)
+                {
+                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+                    providedRandom = rParam.Random;
+                    parameters = rParam.Parameters;
+                }
+
+                if (!(parameters is ECPrivateKeyParameters))
+                    throw new InvalidKeyException("EC private key required for signing");
+
+                this.key = (ECPrivateKeyParameters)parameters;
+            }
+            else
+            {
+                if (!(parameters is ECPublicKeyParameters))
+                    throw new InvalidKeyException("EC public key required for verification");
+
+                this.key = (ECPublicKeyParameters)parameters;
+            }
+
+            this.random = InitSecureRandom(forSigning && !kCalculator.IsDeterministic, providedRandom);
+        }
+
+        // 5.3 pg 28
+        /**
+         * Generate a signature for the given message using the key we were
+         * initialised with. For conventional DSA the message should be a SHA-1
+         * hash of the message of interest.
+         *
+         * @param message the message that will be verified later.
+         */
+        public virtual BigInteger[] GenerateSignature(byte[] message)
+        {
+            ECDomainParameters ec = key.Parameters;
+            BigInteger n = ec.N;
+            BigInteger e = CalculateE(n, message);
+            BigInteger d = ((ECPrivateKeyParameters)key).D;
+
+            if (kCalculator.IsDeterministic)
+            {
+                kCalculator.Init(n, d, message);
+            }
+            else
+            {
+                kCalculator.Init(n, random);
+            }
+
+            BigInteger r, s;
+
+            ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
+
+            // 5.3.2
+            do // Generate s
+            {
+                BigInteger k;
+                do // Generate r
+                {
+                    k = kCalculator.NextK();
+
+                    ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize();
+
+                    // 5.3.3
+                    r = p.AffineXCoord.ToBigInteger().Mod(n);
+                }
+                while (r.SignValue == 0);
+
+                s = k.ModInverse(n).Multiply(e.Add(d.Multiply(r))).Mod(n);
+            }
+            while (s.SignValue == 0);
+
+            return new BigInteger[]{ r, s };
+        }
+
+        // 5.4 pg 29
+        /**
+         * return true if the value r and s represent a DSA signature for
+         * the passed in message (for standard DSA the message should be
+         * a SHA-1 hash of the real message to be verified).
+         */
+        public virtual bool VerifySignature(byte[] message, BigInteger r, BigInteger s)
+        {
+            BigInteger n = key.Parameters.N;
+
+            // r and s should both in the range [1,n-1]
+            if (r.SignValue < 1 || s.SignValue < 1
+                || r.CompareTo(n) >= 0 || s.CompareTo(n) >= 0)
+            {
+                return false;
+            }
+
+            BigInteger e = CalculateE(n, message);
+            BigInteger c = s.ModInverse(n);
+
+            BigInteger u1 = e.Multiply(c).Mod(n);
+            BigInteger u2 = r.Multiply(c).Mod(n);
+
+            ECPoint G = key.Parameters.G;
+            ECPoint Q = ((ECPublicKeyParameters) key).Q;
+
+            ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, u1, Q, u2).Normalize();
+
+            if (point.IsInfinity)
+                return false;
+
+            BigInteger v = point.AffineXCoord.ToBigInteger().Mod(n);
+
+            return v.Equals(r);
+        }
+
+        protected virtual BigInteger CalculateE(BigInteger n, byte[] message)
+        {
+            int messageBitLength = message.Length * 8;
+            BigInteger trunc = new BigInteger(1, message);
+
+            if (n.BitLength < messageBitLength)
+            {
+                trunc = trunc.ShiftRight(messageBitLength - n.BitLength);
+            }
+
+            return trunc;
+        }
+
+        protected virtual ECMultiplier CreateBasePointMultiplier()
+        {
+            return new FixedPointCombMultiplier();
+        }
+
+        protected virtual SecureRandom InitSecureRandom(bool needed, SecureRandom provided)
+        {
+            return !needed ? null : (provided != null) ? provided : new SecureRandom();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/ECGOST3410Signer.cs b/BouncyCastle.AxCrypt/src/crypto/signers/ECGOST3410Signer.cs
new file mode 100644
index 0000000..6027aa9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/ECGOST3410Signer.cs
@@ -0,0 +1,162 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * GOST R 34.10-2001 Signature Algorithm
+     */
+    public class ECGost3410Signer
+        : IDsa
+    {
+        private ECKeyParameters key;
+        private SecureRandom random;
+
+        public string AlgorithmName
+        {
+            get { return "ECGOST3410"; }
+        }
+
+        public void Init(
+            bool				forSigning,
+            ICipherParameters	parameters)
+        {
+            if (forSigning)
+            {
+                if (parameters is ParametersWithRandom)
+                {
+                    ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+                    this.random = rParam.Random;
+                    parameters = rParam.Parameters;
+                }
+                else
+                {
+                    this.random = new SecureRandom();
+                }
+
+                if (!(parameters is ECPrivateKeyParameters))
+                    throw new InvalidKeyException("EC private key required for signing");
+
+                this.key = (ECPrivateKeyParameters) parameters;
+            }
+            else
+            {
+                if (!(parameters is ECPublicKeyParameters))
+                    throw new InvalidKeyException("EC public key required for verification");
+
+                this.key = (ECPublicKeyParameters)parameters;
+            }
+        }
+
+        /**
+         * generate a signature for the given message using the key we were
+         * initialised with. For conventional GOST3410 the message should be a GOST3411
+         * hash of the message of interest.
+         *
+         * @param message the message that will be verified later.
+         */
+        public BigInteger[] GenerateSignature(
+            byte[] message)
+        {
+            byte[] mRev = new byte[message.Length]; // conversion is little-endian
+            for (int i = 0; i != mRev.Length; i++)
+            {
+                mRev[i] = message[mRev.Length - 1 - i];
+            }
+
+            BigInteger e = new BigInteger(1, mRev);
+
+            ECDomainParameters ec = key.Parameters;
+            BigInteger n = ec.N;
+            BigInteger d = ((ECPrivateKeyParameters)key).D;
+
+            BigInteger r, s = null;
+
+            ECMultiplier basePointMultiplier = CreateBasePointMultiplier();
+
+            do // generate s
+            {
+                BigInteger k;
+                do // generate r
+                {
+                    do
+                    {
+                        k = new BigInteger(n.BitLength, random);
+                    }
+                    while (k.SignValue == 0);
+
+                    ECPoint p = basePointMultiplier.Multiply(ec.G, k).Normalize();
+
+                    r = p.AffineXCoord.ToBigInteger().Mod(n);
+                }
+                while (r.SignValue == 0);
+
+                s = (k.Multiply(e)).Add(d.Multiply(r)).Mod(n);
+            }
+            while (s.SignValue == 0);
+
+            return new BigInteger[]{ r, s };
+        }
+
+        /**
+         * return true if the value r and s represent a GOST3410 signature for
+         * the passed in message (for standard GOST3410 the message should be
+         * a GOST3411 hash of the real message to be verified).
+         */
+        public bool VerifySignature(
+            byte[]		message,
+            BigInteger	r,
+            BigInteger	s)
+        {
+            byte[] mRev = new byte[message.Length]; // conversion is little-endian
+            for (int i = 0; i != mRev.Length; i++)
+            {
+                mRev[i] = message[mRev.Length - 1 - i];
+            }
+
+            BigInteger e = new BigInteger(1, mRev);
+            BigInteger n = key.Parameters.N;
+
+            // r in the range [1,n-1]
+            if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
+            {
+                return false;
+            }
+
+            // s in the range [1,n-1]
+            if (s.CompareTo(BigInteger.One) < 0 || s.CompareTo(n) >= 0)
+            {
+                return false;
+            }
+
+            BigInteger v = e.ModInverse(n);
+
+            BigInteger z1 = s.Multiply(v).Mod(n);
+            BigInteger z2 = (n.Subtract(r)).Multiply(v).Mod(n);
+
+            ECPoint G = key.Parameters.G; // P
+            ECPoint Q = ((ECPublicKeyParameters)key).Q;
+
+            ECPoint point = ECAlgorithms.SumOfTwoMultiplies(G, z1, Q, z2).Normalize();
+
+            if (point.IsInfinity)
+                return false;
+
+            BigInteger R = point.AffineXCoord.ToBigInteger().Mod(n);
+
+            return R.Equals(r);
+        }
+
+        protected virtual ECMultiplier CreateBasePointMultiplier()
+        {
+            return new FixedPointCombMultiplier();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/ECNRSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/ECNRSigner.cs
new file mode 100644
index 0000000..cae15bd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/ECNRSigner.cs
@@ -0,0 +1,188 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * EC-NR as described in IEEE 1363-2000
+     */
+    public class ECNRSigner
+        : IDsa
+    {
+        private bool			forSigning;
+        private ECKeyParameters	key;
+        private SecureRandom	random;
+
+        public string AlgorithmName
+        {
+            get { return "ECNR"; }
+        }
+
+        public void Init(
+            bool				forSigning,
+            ICipherParameters	parameters)
+        {
+            this.forSigning = forSigning;
+
+            if (forSigning)
+            {
+                if (parameters is ParametersWithRandom)
+                {
+                    ParametersWithRandom rParam = (ParametersWithRandom) parameters;
+
+                    this.random = rParam.Random;
+                    parameters = rParam.Parameters;
+                }
+                else
+                {
+                    this.random = new SecureRandom();
+                }
+
+                if (!(parameters is ECPrivateKeyParameters))
+                    throw new InvalidKeyException("EC private key required for signing");
+
+                this.key = (ECPrivateKeyParameters) parameters;
+            }
+            else
+            {
+                if (!(parameters is ECPublicKeyParameters))
+                    throw new InvalidKeyException("EC public key required for verification");
+
+                this.key = (ECPublicKeyParameters) parameters;
+            }
+        }
+
+        // Section 7.2.5 ECSP-NR, pg 34
+        /**
+         * generate a signature for the given message using the key we were
+         * initialised with.  Generally, the order of the curve should be at
+         * least as long as the hash of the message of interest, and with
+         * ECNR it *must* be at least as long.
+         *
+         * @param digest  the digest to be signed.
+         * @exception DataLengthException if the digest is longer than the key allows
+         */
+        public BigInteger[] GenerateSignature(
+            byte[] message)
+        {
+            if (!this.forSigning)
+            {
+                // not properly initilaized... deal with it
+                throw new InvalidOperationException("not initialised for signing");
+            }
+
+            BigInteger n = ((ECPrivateKeyParameters) this.key).Parameters.N;
+            int nBitLength = n.BitLength;
+
+            BigInteger e = new BigInteger(1, message);
+            int eBitLength = e.BitLength;
+
+            ECPrivateKeyParameters  privKey = (ECPrivateKeyParameters)key;
+
+            if (eBitLength > nBitLength)
+            {
+                throw new DataLengthException("input too large for ECNR key.");
+            }
+
+            BigInteger r = null;
+            BigInteger s = null;
+
+            AsymmetricCipherKeyPair tempPair;
+            do // generate r
+            {
+                // generate another, but very temporary, key pair using
+                // the same EC parameters
+                ECKeyPairGenerator keyGen = new ECKeyPairGenerator();
+
+                keyGen.Init(new ECKeyGenerationParameters(privKey.Parameters, this.random));
+
+                tempPair = keyGen.GenerateKeyPair();
+
+                //    BigInteger Vx = tempPair.getPublic().getW().getAffineX();
+                ECPublicKeyParameters V = (ECPublicKeyParameters) tempPair.Public; // get temp's public key
+                BigInteger Vx = V.Q.AffineXCoord.ToBigInteger(); // get the point's x coordinate
+
+                r = Vx.Add(e).Mod(n);
+            }
+            while (r.SignValue == 0);
+
+            // generate s
+            BigInteger x = privKey.D;                // private key value
+            BigInteger u = ((ECPrivateKeyParameters) tempPair.Private).D; // temp's private key value
+            s = u.Subtract(r.Multiply(x)).Mod(n);
+
+            return new BigInteger[]{ r, s };
+        }
+
+        // Section 7.2.6 ECVP-NR, pg 35
+        /**
+         * return true if the value r and s represent a signature for the
+         * message passed in. Generally, the order of the curve should be at
+         * least as long as the hash of the message of interest, and with
+         * ECNR, it *must* be at least as long.  But just in case the signer
+         * applied mod(n) to the longer digest, this implementation will
+         * apply mod(n) during verification.
+         *
+         * @param digest  the digest to be verified.
+         * @param r       the r value of the signature.
+         * @param s       the s value of the signature.
+         * @exception DataLengthException if the digest is longer than the key allows
+         */
+        public bool VerifySignature(
+            byte[]		message,
+            BigInteger	r,
+            BigInteger	s)
+        {
+            if (this.forSigning)
+            {
+                // not properly initilaized... deal with it
+                throw new InvalidOperationException("not initialised for verifying");
+            }
+
+            ECPublicKeyParameters pubKey = (ECPublicKeyParameters)key;
+            BigInteger n = pubKey.Parameters.N;
+            int nBitLength = n.BitLength;
+
+            BigInteger e = new BigInteger(1, message);
+            int eBitLength = e.BitLength;
+
+            if (eBitLength > nBitLength)
+            {
+                throw new DataLengthException("input too large for ECNR key.");
+            }
+
+            // r in the range [1,n-1]
+            if (r.CompareTo(BigInteger.One) < 0 || r.CompareTo(n) >= 0)
+            {
+                return false;
+            }
+
+            // s in the range [0,n-1]           NB: ECNR spec says 0
+            if (s.CompareTo(BigInteger.Zero) < 0 || s.CompareTo(n) >= 0)
+            {
+                return false;
+            }
+
+            // compute P = sG + rW
+
+            ECPoint G = pubKey.Parameters.G;
+            ECPoint W = pubKey.Q;
+            // calculate P using Bouncy math
+            ECPoint P = ECAlgorithms.SumOfTwoMultiplies(G, s, W, r).Normalize();
+
+            if (P.IsInfinity)
+                return false;
+
+            BigInteger x = P.AffineXCoord.ToBigInteger();
+            BigInteger t = r.Subtract(x).Mod(n);
+
+            return t.Equals(e);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410DigestSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410DigestSigner.cs
new file mode 100644
index 0000000..58aefa3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410DigestSigner.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	public class Gost3410DigestSigner
+		: ISigner
+	{
+		private readonly IDigest digest;
+		private readonly IDsa dsaSigner;
+		private bool forSigning;
+
+		public Gost3410DigestSigner(
+			IDsa	signer,
+			IDigest	digest)
+		{
+			this.dsaSigner = signer;
+			this.digest = digest;
+		}
+
+		public string AlgorithmName
+		{
+			get { return digest.AlgorithmName + "with" + dsaSigner.AlgorithmName; }
+		}
+
+		public void Init(
+			bool				forSigning,
+			ICipherParameters	parameters)
+		{
+			this.forSigning = forSigning;
+
+			AsymmetricKeyParameter k;
+			if (parameters is ParametersWithRandom)
+			{
+				k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+			}
+			else
+			{
+				k = (AsymmetricKeyParameter)parameters;
+			}
+
+			if (forSigning && !k.IsPrivate)
+			{
+				throw new InvalidKeyException("Signing Requires Private Key.");
+			}
+
+			if (!forSigning && k.IsPrivate)
+			{
+				throw new InvalidKeyException("Verification Requires Public Key.");
+			}
+
+			Reset();
+
+			dsaSigner.Init(forSigning, parameters);
+		}
+
+		/**
+		 * update the internal digest with the byte b
+		 */
+		public void Update(
+			byte input)
+		{
+			digest.Update(input);
+		}
+
+		/**
+		 * update the internal digest with the byte array in
+		 */
+		public void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			digest.BlockUpdate(input, inOff, length);
+		}
+
+		/**
+		 * Generate a signature for the message we've been loaded with using
+		 * the key we were initialised with.
+		 */
+		public byte[] GenerateSignature()
+		{
+			if (!forSigning)
+				throw new InvalidOperationException("GOST3410DigestSigner not initialised for signature generation.");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			try
+			{
+				BigInteger[] sig = dsaSigner.GenerateSignature(hash);
+				byte[] sigBytes = new byte[64];
+
+				// TODO Add methods to allow writing BigInteger to existing byte array?
+				byte[] r = sig[0].ToByteArrayUnsigned();
+				byte[] s = sig[1].ToByteArrayUnsigned();
+				s.CopyTo(sigBytes, 32 - s.Length);
+				r.CopyTo(sigBytes, 64 - r.Length);
+				return sigBytes;
+			}
+			catch (Exception e)
+			{
+				throw new SignatureException(e.Message, e);
+			}
+		}
+
+		/// <returns>true if the internal state represents the signature described in the passed in array.</returns>
+		public bool VerifySignature(
+			byte[] signature)
+		{
+			if (forSigning)
+				throw new InvalidOperationException("DSADigestSigner not initialised for verification");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			BigInteger R, S;
+			try
+			{
+				R = new BigInteger(1, signature, 32, 32);
+				S = new BigInteger(1, signature, 0, 32);
+			}
+			catch (Exception e)
+			{
+				throw new SignatureException("error decoding signature bytes.", e);
+			}
+
+			return dsaSigner.VerifySignature(hash, R, S);
+		}
+
+		/// <summary>Reset the internal state</summary>
+		public void Reset()
+		{
+			digest.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410Signer.cs b/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410Signer.cs
new file mode 100644
index 0000000..375eeb5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/GOST3410Signer.cs
@@ -0,0 +1,132 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	/**
+	 * Gost R 34.10-94 Signature Algorithm
+	 */
+	public class Gost3410Signer
+		: IDsa
+	{
+		private Gost3410KeyParameters key;
+		private SecureRandom random;
+
+		public string AlgorithmName
+		{
+			get { return "GOST3410"; }
+		}
+
+		public void Init(
+			bool				forSigning,
+			ICipherParameters	parameters)
+		{
+			if (forSigning)
+			{
+				if (parameters is ParametersWithRandom)
+				{
+					ParametersWithRandom rParam = (ParametersWithRandom)parameters;
+
+					this.random = rParam.Random;
+					parameters = rParam.Parameters;
+				}
+				else
+				{
+					this.random = new SecureRandom();
+				}
+
+				if (!(parameters is Gost3410PrivateKeyParameters))
+					throw new InvalidKeyException("GOST3410 private key required for signing");
+
+				this.key = (Gost3410PrivateKeyParameters) parameters;
+			}
+			else
+			{
+				if (!(parameters is Gost3410PublicKeyParameters))
+					throw new InvalidKeyException("GOST3410 public key required for signing");
+
+				this.key = (Gost3410PublicKeyParameters) parameters;
+			}
+		}
+
+		/**
+		 * generate a signature for the given message using the key we were
+		 * initialised with. For conventional Gost3410 the message should be a Gost3411
+		 * hash of the message of interest.
+		 *
+		 * @param message the message that will be verified later.
+		 */
+		public BigInteger[] GenerateSignature(
+			byte[] message)
+		{
+			byte[] mRev = new byte[message.Length]; // conversion is little-endian
+			for (int i = 0; i != mRev.Length; i++)
+			{
+				mRev[i] = message[mRev.Length - 1 - i];
+			}
+
+			BigInteger m = new BigInteger(1, mRev);
+			Gost3410Parameters parameters = key.Parameters;
+			BigInteger k;
+
+			do
+			{
+				k = new BigInteger(parameters.Q.BitLength, random);
+			}
+			while (k.CompareTo(parameters.Q) >= 0);
+
+			BigInteger r = parameters.A.ModPow(k, parameters.P).Mod(parameters.Q);
+
+			BigInteger s = k.Multiply(m).
+				Add(((Gost3410PrivateKeyParameters)key).X.Multiply(r)).
+				Mod(parameters.Q);
+
+			return new BigInteger[]{ r, s };
+		}
+
+		/**
+		 * return true if the value r and s represent a Gost3410 signature for
+		 * the passed in message for standard Gost3410 the message should be a
+		 * Gost3411 hash of the real message to be verified.
+		 */
+		public bool VerifySignature(
+			byte[]		message,
+			BigInteger	r,
+			BigInteger	s)
+		{
+			byte[] mRev = new byte[message.Length]; // conversion is little-endian
+			for (int i = 0; i != mRev.Length; i++)
+			{
+				mRev[i] = message[mRev.Length - 1 - i];
+			}
+
+			BigInteger m = new BigInteger(1, mRev);
+			Gost3410Parameters parameters = key.Parameters;
+
+			if (r.SignValue < 0 || parameters.Q.CompareTo(r) <= 0)
+			{
+				return false;
+			}
+
+			if (s.SignValue < 0 || parameters.Q.CompareTo(s) <= 0)
+			{
+				return false;
+			}
+
+			BigInteger v = m.ModPow(parameters.Q.Subtract(BigInteger.Two), parameters.Q);
+
+			BigInteger z1 = s.Multiply(v).Mod(parameters.Q);
+			BigInteger z2 = (parameters.Q.Subtract(r)).Multiply(v).Mod(parameters.Q);
+
+			z1 = parameters.A.ModPow(z1, parameters.P);
+			z2 = ((Gost3410PublicKeyParameters)key).Y.ModPow(z2, parameters.P);
+
+			BigInteger u = z1.Multiply(z2).Mod(parameters.P).Mod(parameters.Q);
+
+			return u.Equals(r);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/GenericSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/GenericSigner.cs
new file mode 100644
index 0000000..1a53eee
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/GenericSigner.cs
@@ -0,0 +1,129 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	public class GenericSigner
+		: ISigner
+	{
+		private readonly IAsymmetricBlockCipher engine;
+		private readonly IDigest digest;
+		private bool forSigning;
+
+		public GenericSigner(
+			IAsymmetricBlockCipher	engine,
+			IDigest					digest)
+		{
+			this.engine = engine;
+			this.digest = digest;
+		}
+
+		public string AlgorithmName
+		{
+			get { return "Generic(" + engine.AlgorithmName + "/" + digest.AlgorithmName + ")"; }
+		}
+
+		/**
+		* initialise the signer for signing or verification.
+		*
+		* @param forSigning
+		*            true if for signing, false otherwise
+		* @param parameters
+		*            necessary parameters.
+		*/
+		public void Init(
+			bool				forSigning,
+			ICipherParameters	parameters)
+		{
+			this.forSigning = forSigning;
+			AsymmetricKeyParameter k;
+
+			if (parameters is ParametersWithRandom)
+			{
+				k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+			}
+			else
+			{
+				k = (AsymmetricKeyParameter)parameters;
+			}
+
+            if (forSigning && !k.IsPrivate)
+                throw new InvalidKeyException("Signing requires private key.");
+
+			if (!forSigning && k.IsPrivate)
+                throw new InvalidKeyException("Verification requires public key.");
+
+			Reset();
+
+			engine.Init(forSigning, parameters);
+		}
+
+		/**
+		* update the internal digest with the byte b
+		*/
+		public void Update(
+			byte input)
+		{
+			digest.Update(input);
+		}
+
+		/**
+		* update the internal digest with the byte array in
+		*/
+		public void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			digest.BlockUpdate(input, inOff, length);
+		}
+
+		/**
+		* Generate a signature for the message we've been loaded with using the key
+		* we were initialised with.
+		*/
+		public byte[] GenerateSignature()
+		{
+			if (!forSigning)
+				throw new InvalidOperationException("GenericSigner not initialised for signature generation.");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			return engine.ProcessBlock(hash, 0, hash.Length);
+		}
+
+		/**
+		* return true if the internal state represents the signature described in
+		* the passed in array.
+		*/
+		public bool VerifySignature(
+			byte[] signature)
+		{
+			if (forSigning)
+				throw new InvalidOperationException("GenericSigner not initialised for verification");
+
+			byte[] hash = new byte[digest.GetDigestSize()];
+			digest.DoFinal(hash, 0);
+
+			try
+			{
+				byte[] sig = engine.ProcessBlock(signature, 0, signature.Length);
+
+				return Arrays.ConstantTimeAreEqual(sig, hash);
+			}
+			catch (Exception)
+			{
+				return false;
+			}
+		}
+
+		public void Reset()
+		{
+			digest.Reset();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/HMacDsaKCalculator.cs b/BouncyCastle.AxCrypt/src/crypto/signers/HMacDsaKCalculator.cs
new file mode 100644
index 0000000..8231197
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/HMacDsaKCalculator.cs
@@ -0,0 +1,150 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * A deterministic K calculator based on the algorithm in section 3.2 of RFC 6979.
+     */
+    public class HMacDsaKCalculator
+        :   IDsaKCalculator
+    {
+        private readonly HMac hMac;
+        private readonly byte[] K;
+        private readonly byte[] V;
+
+        private BigInteger n;
+
+        /**
+         * Base constructor.
+         *
+         * @param digest digest to build the HMAC on.
+         */
+        public HMacDsaKCalculator(IDigest digest)
+        {
+            this.hMac = new HMac(digest);
+            this.V = new byte[hMac.GetMacSize()];
+            this.K = new byte[hMac.GetMacSize()];
+        }
+
+        public virtual bool IsDeterministic
+        {
+            get { return true; }
+        }
+
+        public virtual void Init(BigInteger n, SecureRandom random)
+        {
+            throw new InvalidOperationException("Operation not supported");
+        }
+
+        public void Init(BigInteger n, BigInteger d, byte[] message)
+        {
+            this.n = n;
+
+            Arrays.Fill(V, (byte)0x01);
+            Arrays.Fill(K, (byte)0);
+
+            byte[] x = new byte[(n.BitLength + 7) / 8];
+            byte[] dVal = BigIntegers.AsUnsignedByteArray(d);
+
+            Array.Copy(dVal, 0, x, x.Length - dVal.Length, dVal.Length);
+
+            byte[] m = new byte[(n.BitLength + 7) / 8];
+
+            BigInteger mInt = BitsToInt(message);
+
+            if (mInt.CompareTo(n) >= 0)
+            {
+                mInt = mInt.Subtract(n);
+            }
+
+            byte[] mVal = BigIntegers.AsUnsignedByteArray(mInt);
+
+            Array.Copy(mVal, 0, m, m.Length - mVal.Length, mVal.Length);
+
+            hMac.Init(new KeyParameter(K));
+
+            hMac.BlockUpdate(V, 0, V.Length);
+            hMac.Update((byte)0x00);
+            hMac.BlockUpdate(x, 0, x.Length);
+            hMac.BlockUpdate(m, 0, m.Length);
+
+            hMac.DoFinal(K, 0);
+
+            hMac.Init(new KeyParameter(K));
+
+            hMac.BlockUpdate(V, 0, V.Length);
+
+            hMac.DoFinal(V, 0);
+
+            hMac.BlockUpdate(V, 0, V.Length);
+            hMac.Update((byte)0x01);
+            hMac.BlockUpdate(x, 0, x.Length);
+            hMac.BlockUpdate(m, 0, m.Length);
+
+            hMac.DoFinal(K, 0);
+
+            hMac.Init(new KeyParameter(K));
+
+            hMac.BlockUpdate(V, 0, V.Length);
+
+            hMac.DoFinal(V, 0);
+        }
+
+        public virtual BigInteger NextK()
+        {
+            byte[] t = new byte[((n.BitLength + 7) / 8)];
+
+            for (;;)
+            {
+                int tOff = 0;
+
+                while (tOff < t.Length)
+                {
+                    hMac.BlockUpdate(V, 0, V.Length);
+
+                    hMac.DoFinal(V, 0);
+
+                    int len = System.Math.Min(t.Length - tOff, V.Length);
+                    Array.Copy(V, 0, t, tOff, len);
+                    tOff += len;
+                }
+
+                BigInteger k = BitsToInt(t);
+
+                if (k.SignValue > 0 && k.CompareTo(n) < 0)
+                {
+                    return k;
+                }
+
+                hMac.BlockUpdate(V, 0, V.Length);
+                hMac.Update((byte)0x00);
+
+                hMac.DoFinal(K, 0);
+
+                hMac.Init(new KeyParameter(K));
+
+                hMac.BlockUpdate(V, 0, V.Length);
+
+                hMac.DoFinal(V, 0);
+            }
+        }
+
+        private BigInteger BitsToInt(byte[] t)
+        {
+            BigInteger v = new BigInteger(1, t);
+
+            if (t.Length * 8 > n.BitLength)
+            {
+                v = v.ShiftRight(t.Length * 8 - n.BitLength);
+            }
+
+            return v;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/IDsaKCalculator.cs b/BouncyCastle.AxCrypt/src/crypto/signers/IDsaKCalculator.cs
new file mode 100644
index 0000000..645186d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/IDsaKCalculator.cs
@@ -0,0 +1,44 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /**
+     * Interface define calculators of K values for DSA/ECDSA.
+     */
+    public interface IDsaKCalculator
+    {
+        /**
+         * Return true if this calculator is deterministic, false otherwise.
+         *
+         * @return true if deterministic, otherwise false.
+         */
+        bool IsDeterministic { get; }
+
+        /**
+         * Non-deterministic initialiser.
+         *
+         * @param n the order of the DSA group.
+         * @param random a source of randomness.
+         */
+        void Init(BigInteger n, SecureRandom random);
+
+        /**
+         * Deterministic initialiser.
+         *
+         * @param n the order of the DSA group.
+         * @param d the DSA private value.
+         * @param message the message being signed.
+         */
+        void Init(BigInteger n, BigInteger d, byte[] message);
+
+        /**
+         * Return the next valid value of K.
+         *
+         * @return a K value.
+         */
+        BigInteger NextK();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2PssSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2PssSigner.cs
new file mode 100644
index 0000000..d4f6c55
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2PssSigner.cs
@@ -0,0 +1,617 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /// <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 2 and 3).
+    /// <p>
+    /// Note: the usual length for the salt is the length of the hash
+    /// function used in bytes.</p>
+    /// </summary>
+    public class Iso9796d2PssSigner
+        : ISignerWithRecovery
+    {
+        /// <summary>
+        /// Return a reference to the recoveredMessage message.
+        /// </summary>
+        /// <returns>The full/partial recoveredMessage message.</returns>
+        /// <seealso cref="ISignerWithRecovery.GetRecoveredMessage"/>
+        public byte[] GetRecoveredMessage()
+        {
+            return recoveredMessage;
+        }
+
+        public const int TrailerImplicit = 0xBC;
+        public const int TrailerRipeMD160 = 0x31CC;
+        public const int TrailerRipeMD128 = 0x32CC;
+        public const int TrailerSha1 = 0x33CC;
+        public const int TrailerSha256 = 0x34CC;
+        public const int TrailerSha512 = 0x35CC;
+        public const int TrailerSha384 = 0x36CC;
+        public const int TrailerWhirlpool = 0x37CC;
+
+        private static readonly IDictionary trailerMap = Platform.CreateHashtable();
+
+        static Iso9796d2PssSigner()
+        {
+            trailerMap.Add("RIPEMD128", TrailerRipeMD128);
+            trailerMap.Add("RIPEMD160", TrailerRipeMD160);
+            trailerMap.Add("SHA-1", TrailerSha1);
+            trailerMap.Add("SHA-256", TrailerSha256);
+            trailerMap.Add("SHA-384", TrailerSha384);
+            trailerMap.Add("SHA-512", TrailerSha512);
+
+            trailerMap.Add("Whirlpool", TrailerWhirlpool);
+        }
+
+        private IDigest digest;
+        private IAsymmetricBlockCipher cipher;
+
+        private SecureRandom random;
+        private byte[] standardSalt;
+
+        private int hLen;
+        private int trailer;
+        private int keyBits;
+        private byte[] block;
+        private byte[] mBuf;
+        private int messageLength;
+        private readonly int saltLength;
+        private bool fullMessage;
+        private byte[] recoveredMessage;
+
+        private byte[] preSig;
+        private byte[] preBlock;
+        private int preMStart;
+        private int preTLength;
+
+        /// <summary>
+        /// Generate a signer for the with either implicit or explicit trailers
+        /// for ISO9796-2, scheme 2 or 3.
+        /// </summary>
+        /// <param name="cipher">base cipher to use for signature creation/verification</param>
+        /// <param name="digest">digest to use.</param>
+        /// <param name="saltLength">length of salt in bytes.</param>
+        /// <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        public Iso9796d2PssSigner(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					digest,
+            int						saltLength,
+            bool					isImplicit)
+        {
+            this.cipher = cipher;
+            this.digest = digest;
+            this.hLen = digest.GetDigestSize();
+            this.saltLength = saltLength;
+
+            if (isImplicit)
+            {
+                trailer = TrailerImplicit;
+            }
+            else
+            {
+                string digestAlg = digest.AlgorithmName;
+                if (!trailerMap.Contains(digestAlg))
+                    throw new ArgumentException("no valid trailer for digest");
+
+                trailer = (int)trailerMap[digestAlg];
+            }
+        }
+
+        /// <summary> Constructor for a signer with an explicit digest trailer.
+        ///
+        /// </summary>
+        /// <param name="cipher">cipher to use.
+        /// </param>
+        /// <param name="digest">digest to sign with.
+        /// </param>
+        /// <param name="saltLength">length of salt in bytes.
+        /// </param>
+        public Iso9796d2PssSigner(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					digest,
+            int						saltLength)
+            : this(cipher, digest, saltLength, false)
+        {
+        }
+
+        public string AlgorithmName
+        {
+            get { return digest.AlgorithmName + "with" + "ISO9796-2S2"; }
+        }
+
+        /// <summary>Initialise the signer.</summary>
+        /// <param name="forSigning">true if for signing, false if for verification.</param>
+        /// <param name="parameters">parameters for signature generation/verification. If the
+        /// parameters are for generation they should be a ParametersWithRandom,
+        /// a ParametersWithSalt, or just an RsaKeyParameters object. If RsaKeyParameters
+        /// are passed in a SecureRandom will be created.
+        /// </param>
+        /// <exception cref="ArgumentException">if wrong parameter type or a fixed
+        /// salt is passed in which is the wrong length.
+        /// </exception>
+        public virtual void Init(
+            bool				forSigning,
+            ICipherParameters	parameters)
+        {
+            RsaKeyParameters kParam;
+            if (parameters is ParametersWithRandom)
+            {
+                ParametersWithRandom p = (ParametersWithRandom) parameters;
+
+                kParam = (RsaKeyParameters) p.Parameters;
+
+                if (forSigning)
+                {
+                    random = p.Random;
+                }
+            }
+            else if (parameters is ParametersWithSalt)
+            {
+                if (!forSigning)
+                    throw new ArgumentException("ParametersWithSalt only valid for signing", "parameters");
+
+                ParametersWithSalt p = (ParametersWithSalt) parameters;
+
+                kParam = (RsaKeyParameters) p.Parameters;
+                standardSalt = p.GetSalt();
+
+                if (standardSalt.Length != saltLength)
+                    throw new ArgumentException("Fixed salt is of wrong length");
+            }
+            else
+            {
+                kParam = (RsaKeyParameters) parameters;
+
+                if (forSigning)
+                {
+                    random = new SecureRandom();
+                }
+            }
+
+            cipher.Init(forSigning, kParam);
+
+            keyBits = kParam.Modulus.BitLength;
+
+            block = new byte[(keyBits + 7) / 8];
+
+            if (trailer == TrailerImplicit)
+            {
+                mBuf = new byte[block.Length - digest.GetDigestSize() - saltLength - 1 - 1];
+            }
+            else
+            {
+                mBuf = new byte[block.Length - digest.GetDigestSize() - saltLength - 1 - 2];
+            }
+
+            Reset();
+        }
+
+        /// <summary> compare two byte arrays - constant time.</summary>
+        private bool IsSameAs(byte[] a, byte[] b)
+        {
+            if (messageLength != b.Length)
+            {
+                return false;
+            }
+
+            bool isOkay = true;
+
+            for (int i = 0; i != b.Length; i++)
+            {
+                if (a[i] != b[i])
+                {
+                    isOkay = false;
+                }
+            }
+
+            return isOkay;
+        }
+
+        /// <summary> clear possible sensitive data</summary>
+        private void  ClearBlock(
+            byte[] block)
+        {
+            Array.Clear(block, 0, block.Length);
+        }
+
+        public virtual void UpdateWithRecoveredMessage(
+            byte[] signature)
+        {
+            byte[] block = cipher.ProcessBlock(signature, 0, signature.Length);
+
+            //
+            // adjust block size for leading zeroes if necessary
+            //
+            if (block.Length < (keyBits + 7) / 8)
+            {
+                byte[] tmp = new byte[(keyBits + 7) / 8];
+
+                Array.Copy(block, 0, tmp, tmp.Length - block.Length, block.Length);
+                ClearBlock(block);
+                block = tmp;
+            }
+
+            int tLength;
+
+            if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0)
+            {
+                tLength = 1;
+            }
+            else
+            {
+                int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF);
+
+                string digestAlg = digest.AlgorithmName;
+                if (!trailerMap.Contains(digestAlg))
+                    throw new ArgumentException("unrecognised hash in signature");
+
+                if (sigTrail != (int)trailerMap[digestAlg])
+                    throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail);
+
+                tLength = 2;
+            }
+
+            //
+            // calculate H(m2)
+            //
+            byte[] m2Hash = new byte[hLen];
+            digest.DoFinal(m2Hash, 0);
+
+            //
+            // remove the mask
+            //
+            byte[] dbMask = MaskGeneratorFunction1(block, block.Length - hLen - tLength, hLen, block.Length - hLen - tLength);
+            for (int i = 0; i != dbMask.Length; i++)
+            {
+                block[i] ^= dbMask[i];
+            }
+
+            block[0] &= 0x7f;
+
+            //
+            // find out how much padding we've got
+            //
+            int mStart = 0;
+
+            while (mStart < block.Length)
+            {
+                if (block[mStart++] == 0x01)
+                    break;
+            }
+
+            if (mStart >= block.Length)
+            {
+                ClearBlock(block);
+            }
+
+            fullMessage = (mStart > 1);
+
+            recoveredMessage = new byte[dbMask.Length - mStart - saltLength];
+
+            Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length);
+            recoveredMessage.CopyTo(mBuf, 0);
+
+            preSig = signature;
+            preBlock = block;
+            preMStart = mStart;
+            preTLength = tLength;
+        }
+
+        /// <summary> update the internal digest with the byte b</summary>
+        public virtual void Update(
+            byte input)
+        {
+            if (preSig == null && messageLength < mBuf.Length)
+            {
+                mBuf[messageLength++] = input;
+            }
+            else
+            {
+                digest.Update(input);
+            }
+        }
+
+        /// <summary> update the internal digest with the byte array in</summary>
+        public virtual void BlockUpdate(
+            byte[]	input,
+            int		inOff,
+            int		length)
+        {
+            if (preSig == null)
+            {
+                while (length > 0 && messageLength < mBuf.Length)
+                {
+                    this.Update(input[inOff]);
+                    inOff++;
+                    length--;
+                }
+            }
+
+            if (length > 0)
+            {
+                digest.BlockUpdate(input, inOff, length);
+            }
+        }
+
+        /// <summary> reset the internal state</summary>
+        public virtual void Reset()
+        {
+            digest.Reset();
+            messageLength = 0;
+            if (mBuf != null)
+            {
+                ClearBlock(mBuf);
+            }
+            if (recoveredMessage != null)
+            {
+                ClearBlock(recoveredMessage);
+                recoveredMessage = null;
+            }
+            fullMessage = false;
+            if (preSig != null)
+            {
+                preSig = null;
+                ClearBlock(preBlock);
+                preBlock = null;
+            }
+        }
+
+        /// <summary> Generate a signature for the loaded message using the key we were
+        /// initialised with.
+        /// </summary>
+        public byte[] GenerateSignature()
+        {
+            int digSize = digest.GetDigestSize();
+            byte[] m2Hash = new byte[digSize];
+            digest.DoFinal(m2Hash, 0);
+
+            byte[] C = new byte[8];
+            LtoOSP(messageLength * 8, C);
+
+            digest.BlockUpdate(C, 0, C.Length);
+            digest.BlockUpdate(mBuf, 0, messageLength);
+            digest.BlockUpdate(m2Hash, 0, m2Hash.Length);
+
+            byte[] salt;
+            if (standardSalt != null)
+            {
+                salt = standardSalt;
+            }
+            else
+            {
+                salt = new byte[saltLength];
+                random.NextBytes(salt);
+            }
+
+            digest.BlockUpdate(salt, 0, salt.Length);
+
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            int tLength = 2;
+            if (trailer == TrailerImplicit)
+            {
+                tLength = 1;
+            }
+
+            int off = block.Length - messageLength - salt.Length - hLen - tLength - 1;
+
+            block[off] = (byte) (0x01);
+
+            Array.Copy(mBuf, 0, block, off + 1, messageLength);
+            Array.Copy(salt, 0, block, off + 1 + messageLength, salt.Length);
+
+            byte[] dbMask = MaskGeneratorFunction1(hash, 0, hash.Length, block.Length - hLen - tLength);
+            for (int i = 0; i != dbMask.Length; i++)
+            {
+                block[i] ^= dbMask[i];
+            }
+
+            Array.Copy(hash, 0, block, block.Length - hLen - tLength, hLen);
+
+            if (trailer == TrailerImplicit)
+            {
+                block[block.Length - 1] = (byte)TrailerImplicit;
+            }
+            else
+            {
+                block[block.Length - 2] = (byte) ((uint)trailer >> 8);
+                block[block.Length - 1] = (byte) trailer;
+            }
+
+            block[0] &= (byte) (0x7f);
+
+            byte[] b = cipher.ProcessBlock(block, 0, block.Length);
+
+            ClearBlock(mBuf);
+            ClearBlock(block);
+            messageLength = 0;
+
+            return b;
+        }
+
+        /// <summary> return true if the signature represents a ISO9796-2 signature
+        /// for the passed in message.
+        /// </summary>
+        public virtual bool VerifySignature(
+            byte[] signature)
+        {
+            //
+            // calculate H(m2)
+            //
+            byte[] m2Hash = new byte[hLen];
+            digest.DoFinal(m2Hash, 0);
+
+            byte[] block;
+            int tLength;
+            int mStart = 0;
+
+            if (preSig == null)
+            {
+                try
+                {
+                    UpdateWithRecoveredMessage(signature);
+                }
+                catch (Exception)
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if (!Arrays.AreEqual(preSig, signature))
+                {
+                    throw new InvalidOperationException("UpdateWithRecoveredMessage called on different signature");
+                }
+            }
+
+            block = preBlock;
+            mStart = preMStart;
+            tLength = preTLength;
+
+            preSig = null;
+            preBlock = null;
+
+            //
+            // check the hashes
+            //
+            byte[] C = new byte[8];
+            LtoOSP(recoveredMessage.Length * 8, C);
+
+            digest.BlockUpdate(C, 0, C.Length);
+
+            if (recoveredMessage.Length != 0)
+            {
+                digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length);
+            }
+
+            digest.BlockUpdate(m2Hash, 0, m2Hash.Length);
+
+            // Update for the salt
+            digest.BlockUpdate(block, mStart + recoveredMessage.Length, saltLength);
+
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            int off = block.Length - tLength - hash.Length;
+
+            bool isOkay = true;
+
+            for (int i = 0; i != hash.Length; i++)
+            {
+                if (hash[i] != block[off + i])
+                {
+                    isOkay = false;
+                }
+            }
+
+            ClearBlock(block);
+            ClearBlock(hash);
+
+            if (!isOkay)
+            {
+                fullMessage = false;
+                ClearBlock(recoveredMessage);
+                return false;
+            }
+
+            //
+            // if they've input a message check what we've recovered against
+            // what was input.
+            //
+            if (messageLength != 0)
+            {
+                if (!IsSameAs(mBuf, recoveredMessage))
+                {
+                    ClearBlock(mBuf);
+                    return false;
+                }
+                messageLength = 0;
+            }
+
+            ClearBlock(mBuf);
+            return true;
+        }
+
+        /// <summary>
+        /// Return true if the full message was recoveredMessage.
+        /// </summary>
+        /// <returns>true on full message recovery, false otherwise, or if not sure.</returns>
+        /// <seealso cref="ISignerWithRecovery.HasFullMessage"/>
+        public virtual bool HasFullMessage()
+        {
+            return fullMessage;
+        }
+
+        /// <summary> int to octet string.</summary>
+        /// <summary> int to octet string.</summary>
+        private void ItoOSP(
+            int		i,
+            byte[]	sp)
+        {
+            sp[0] = (byte)((uint)i >> 24);
+            sp[1] = (byte)((uint)i >> 16);
+            sp[2] = (byte)((uint)i >> 8);
+            sp[3] = (byte)((uint)i >> 0);
+        }
+
+        /// <summary> long to octet string.</summary>
+        private void  LtoOSP(long l, byte[] sp)
+        {
+            sp[0] = (byte)((ulong)l >> 56);
+            sp[1] = (byte)((ulong)l >> 48);
+            sp[2] = (byte)((ulong)l >> 40);
+            sp[3] = (byte)((ulong)l >> 32);
+            sp[4] = (byte)((ulong)l >> 24);
+            sp[5] = (byte)((ulong)l >> 16);
+            sp[6] = (byte)((ulong)l >> 8);
+            sp[7] = (byte)((ulong)l >> 0);
+        }
+
+        /// <summary> mask generator function, as described in Pkcs1v2.</summary>
+        private byte[] MaskGeneratorFunction1(
+            byte[]	Z,
+            int		zOff,
+            int		zLen,
+            int		length)
+        {
+            byte[] mask = new byte[length];
+            byte[] hashBuf = new byte[hLen];
+            byte[] C = new byte[4];
+            int counter = 0;
+
+            digest.Reset();
+
+            do
+            {
+                ItoOSP(counter, C);
+
+                digest.BlockUpdate(Z, zOff, zLen);
+                digest.BlockUpdate(C, 0, C.Length);
+                digest.DoFinal(hashBuf, 0);
+
+                Array.Copy(hashBuf, 0, mask, counter * hLen, hLen);
+            }
+            while (++counter < (length / hLen));
+
+            if ((counter * hLen) < length)
+            {
+                ItoOSP(counter, C);
+
+                digest.BlockUpdate(Z, zOff, zLen);
+                digest.BlockUpdate(C, 0, C.Length);
+                digest.DoFinal(hashBuf, 0);
+
+                Array.Copy(hashBuf, 0, mask, counter * hLen, mask.Length - (counter * hLen));
+            }
+
+            return mask;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2Signer.cs b/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2Signer.cs
new file mode 100644
index 0000000..cfb8942
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/Iso9796d2Signer.cs
@@ -0,0 +1,563 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    /// <summary> ISO9796-2 - mechanism using a hash function with recovery (scheme 1)</summary>
+    public class Iso9796d2Signer : ISignerWithRecovery
+    {
+        /// <summary>
+        /// Return a reference to the recoveredMessage message.
+        /// </summary>
+        /// <returns>The full/partial recoveredMessage message.</returns>
+        /// <seealso cref="ISignerWithRecovery.GetRecoveredMessage"/>
+        public byte[] GetRecoveredMessage()
+        {
+            return recoveredMessage;
+        }
+
+        public const int TrailerImplicit = 0xBC;
+        public const int TrailerRipeMD160 = 0x31CC;
+        public const int TrailerRipeMD128 = 0x32CC;
+        public const int TrailerSha1 = 0x33CC;
+        public const int TrailerSha256 = 0x34CC;
+        public const int TrailerSha512 = 0x35CC;
+        public const int TrailerSha384 = 0x36CC;
+        public const int TrailerWhirlpool = 0x37CC;
+
+        private static IDictionary trailerMap = Platform.CreateHashtable();
+
+        static Iso9796d2Signer()
+        {
+            trailerMap.Add("RIPEMD128", TrailerRipeMD128);
+            trailerMap.Add("RIPEMD160", TrailerRipeMD160);
+
+            trailerMap.Add("SHA-1", TrailerSha1);
+            trailerMap.Add("SHA-256", TrailerSha256);
+            trailerMap.Add("SHA-384", TrailerSha384);
+            trailerMap.Add("SHA-512", TrailerSha512);
+
+            trailerMap.Add("Whirlpool", TrailerWhirlpool);
+        }
+
+        private IDigest digest;
+        private IAsymmetricBlockCipher cipher;
+
+        private int trailer;
+        private int keyBits;
+        private byte[] block;
+        private byte[] mBuf;
+        private int messageLength;
+        private bool fullMessage;
+        private byte[] recoveredMessage;
+
+        private byte[] preSig;
+        private byte[] preBlock;
+
+        /// <summary>
+        /// Generate a signer for the with either implicit or explicit trailers
+        /// for ISO9796-2.
+        /// </summary>
+        /// <param name="cipher">base cipher to use for signature creation/verification</param>
+        /// <param name="digest">digest to use.</param>
+        /// <param name="isImplicit">whether or not the trailer is implicit or gives the hash.</param>
+        public Iso9796d2Signer(
+            IAsymmetricBlockCipher	cipher,
+            IDigest					digest,
+            bool					isImplicit)
+        {
+            this.cipher = cipher;
+            this.digest = digest;
+
+            if (isImplicit)
+            {
+                trailer = TrailerImplicit;
+            }
+            else
+            {
+                string digestName = digest.AlgorithmName;
+
+                if (trailerMap.Contains(digestName))
+                {
+                    trailer = (int)trailerMap[digest.AlgorithmName];
+                }
+                else
+                {
+                    throw new System.ArgumentException("no valid trailer for digest");
+                }
+            }
+        }
+
+        /// <summary> Constructor for a signer with an explicit digest trailer.
+        ///
+        /// </summary>
+        /// <param name="cipher">cipher to use.
+        /// </param>
+        /// <param name="digest">digest to sign with.
+        /// </param>
+        public Iso9796d2Signer(IAsymmetricBlockCipher cipher, IDigest digest)
+            : this(cipher, digest, false)
+        {
+        }
+
+        public string AlgorithmName
+        {
+            get { return digest.AlgorithmName + "with" + "ISO9796-2S1"; }
+        }
+
+        public virtual void Init(bool forSigning, ICipherParameters parameters)
+        {
+            RsaKeyParameters kParam = (RsaKeyParameters) parameters;
+
+            cipher.Init(forSigning, kParam);
+
+            keyBits = kParam.Modulus.BitLength;
+
+            block = new byte[(keyBits + 7) / 8];
+            if (trailer == TrailerImplicit)
+            {
+                mBuf = new byte[block.Length - digest.GetDigestSize() - 2];
+            }
+            else
+            {
+                mBuf = new byte[block.Length - digest.GetDigestSize() - 3];
+            }
+
+            Reset();
+        }
+
+        /// <summary> compare two byte arrays - constant time.</summary>
+        private bool IsSameAs(byte[] a, byte[] b)
+        {
+            int checkLen;
+            if (messageLength > mBuf.Length)
+            {
+                if (mBuf.Length > b.Length)
+                {
+                    return false;
+                }
+
+                checkLen = mBuf.Length;
+            }
+            else
+            {
+                if (messageLength != b.Length)
+                {
+                    return false;
+                }
+
+                checkLen = b.Length;
+            }
+
+            bool isOkay = true;
+
+            for (int i = 0; i != checkLen; i++)
+            {
+                if (a[i] != b[i])
+                {
+                    isOkay = false;
+                }
+            }
+
+            return isOkay;
+        }
+
+        /// <summary> clear possible sensitive data</summary>
+        private void  ClearBlock(
+            byte[] block)
+        {
+            Array.Clear(block, 0, block.Length);
+        }
+
+        public virtual void UpdateWithRecoveredMessage(
+            byte[] signature)
+        {
+            byte[] block = cipher.ProcessBlock(signature, 0, signature.Length);
+
+            if (((block[0] & 0xC0) ^ 0x40) != 0)
+                throw new InvalidCipherTextException("malformed signature");
+
+            if (((block[block.Length - 1] & 0xF) ^ 0xC) != 0)
+                throw new InvalidCipherTextException("malformed signature");
+
+            int delta = 0;
+
+            if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0)
+            {
+                delta = 1;
+            }
+            else
+            {
+                int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF);
+
+                string digestName = digest.AlgorithmName;
+                if (!trailerMap.Contains(digestName))
+                    throw new ArgumentException("unrecognised hash in signature");
+                if (sigTrail != (int)trailerMap[digestName])
+                    throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail);
+
+                delta = 2;
+            }
+
+            //
+            // find out how much padding we've got
+            //
+            int mStart = 0;
+
+            for (mStart = 0; mStart != block.Length; mStart++)
+            {
+                if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+                    break;
+            }
+
+            mStart++;
+
+            int off = block.Length - delta - digest.GetDigestSize();
+
+            //
+            // there must be at least one byte of message string
+            //
+            if ((off - mStart) <= 0)
+                throw new InvalidCipherTextException("malformed block");
+
+            //
+            // if we contain the whole message as well, check the hash of that.
+            //
+            if ((block[0] & 0x20) == 0)
+            {
+                fullMessage = true;
+
+                recoveredMessage = new byte[off - mStart];
+                Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length);
+            }
+            else
+            {
+                fullMessage = false;
+
+                recoveredMessage = new byte[off - mStart];
+                Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length);
+            }
+
+            preSig = signature;
+            preBlock = block;
+
+            digest.BlockUpdate(recoveredMessage, 0, recoveredMessage.Length);
+            messageLength = recoveredMessage.Length;
+            recoveredMessage.CopyTo(mBuf, 0);
+        }
+
+        /// <summary> update the internal digest with the byte b</summary>
+        public void Update(
+            byte input)
+        {
+            digest.Update(input);
+
+            if (messageLength < mBuf.Length)
+            {
+                mBuf[messageLength] = input;
+            }
+
+            messageLength++;
+        }
+
+        /// <summary> update the internal digest with the byte array in</summary>
+        public void BlockUpdate(
+            byte[]	input,
+            int		inOff,
+            int		length)
+        {
+            while (length > 0 && messageLength < mBuf.Length)
+            {
+                //for (int i = 0; i < length && (i + messageLength) < mBuf.Length; i++)
+                //{
+                //    mBuf[messageLength + i] = input[inOff + i];
+                //}
+                this.Update(input[inOff]);
+                inOff++;
+                length--;
+            }
+
+            digest.BlockUpdate(input, inOff, length);
+            messageLength += length;
+        }
+
+        /// <summary> reset the internal state</summary>
+        public virtual void Reset()
+        {
+            digest.Reset();
+            messageLength = 0;
+            ClearBlock(mBuf);
+
+            if (recoveredMessage != null)
+            {
+                ClearBlock(recoveredMessage);
+            }
+
+            recoveredMessage = null;
+            fullMessage = false;
+
+            if (preSig != null)
+            {
+                preSig = null;
+                ClearBlock(preBlock);
+                preBlock = null;
+            }
+        }
+
+        /// <summary> Generate a signature for the loaded message using the key we were
+        /// initialised with.
+        /// </summary>
+        public virtual byte[] GenerateSignature()
+        {
+            int digSize = digest.GetDigestSize();
+
+            int t = 0;
+            int delta = 0;
+
+            if (trailer == TrailerImplicit)
+            {
+                t = 8;
+                delta = block.Length - digSize - 1;
+                digest.DoFinal(block, delta);
+                block[block.Length - 1] = (byte) TrailerImplicit;
+            }
+            else
+            {
+                t = 16;
+                delta = block.Length - digSize - 2;
+                digest.DoFinal(block, delta);
+                block[block.Length - 2] = (byte) ((uint)trailer >> 8);
+                block[block.Length - 1] = (byte) trailer;
+            }
+
+            byte header = 0;
+            int x = (digSize + messageLength) * 8 + t + 4 - keyBits;
+
+            if (x > 0)
+            {
+                int mR = messageLength - ((x + 7) / 8);
+                header = (byte) (0x60);
+
+                delta -= mR;
+
+                Array.Copy(mBuf, 0, block, delta, mR);
+            }
+            else
+            {
+                header = (byte) (0x40);
+                delta -= messageLength;
+
+                Array.Copy(mBuf, 0, block, delta, messageLength);
+            }
+
+            if ((delta - 1) > 0)
+            {
+                for (int i = delta - 1; i != 0; i--)
+                {
+                    block[i] = (byte) 0xbb;
+                }
+                block[delta - 1] ^= (byte) 0x01;
+                block[0] = (byte) 0x0b;
+                block[0] |= header;
+            }
+            else
+            {
+                block[0] = (byte) 0x0a;
+                block[0] |= header;
+            }
+
+            byte[] b = cipher.ProcessBlock(block, 0, block.Length);
+
+            ClearBlock(mBuf);
+            ClearBlock(block);
+
+            return b;
+        }
+
+        /// <summary> return true if the signature represents a ISO9796-2 signature
+        /// for the passed in message.
+        /// </summary>
+        public virtual bool VerifySignature(byte[] signature)
+        {
+            byte[] block;
+
+            if (preSig == null)
+            {
+                try
+                {
+                    block = cipher.ProcessBlock(signature, 0, signature.Length);
+                }
+                catch (Exception)
+                {
+                    return false;
+                }
+            }
+            else
+            {
+                if (!Arrays.AreEqual(preSig, signature))
+                    throw new InvalidOperationException("updateWithRecoveredMessage called on different signature");
+
+                block = preBlock;
+
+                preSig = null;
+                preBlock = null;
+            }
+
+            if (((block[0] & 0xC0) ^ 0x40) != 0)
+                return ReturnFalse(block);
+
+            if (((block[block.Length - 1] & 0xF) ^ 0xC) != 0)
+                return ReturnFalse(block);
+
+            int delta = 0;
+
+            if (((block[block.Length - 1] & 0xFF) ^ 0xBC) == 0)
+            {
+                delta = 1;
+            }
+            else
+            {
+                int sigTrail = ((block[block.Length - 2] & 0xFF) << 8) | (block[block.Length - 1] & 0xFF);
+
+                string digestName = digest.AlgorithmName;
+                if (!trailerMap.Contains(digestName))
+                    throw new ArgumentException("unrecognised hash in signature");
+                if (sigTrail != (int)trailerMap[digestName])
+                    throw new InvalidOperationException("signer initialised with wrong digest for trailer " + sigTrail);
+
+                delta = 2;
+            }
+
+            //
+            // find out how much padding we've got
+            //
+            int mStart = 0;
+            for (; mStart != block.Length; mStart++)
+            {
+                if (((block[mStart] & 0x0f) ^ 0x0a) == 0)
+                {
+                    break;
+                }
+            }
+
+            mStart++;
+
+            //
+            // check the hashes
+            //
+            byte[] hash = new byte[digest.GetDigestSize()];
+
+            int off = block.Length - delta - hash.Length;
+
+            //
+            // there must be at least one byte of message string
+            //
+            if ((off - mStart) <= 0)
+            {
+                return ReturnFalse(block);
+            }
+
+            //
+            // if we contain the whole message as well, check the hash of that.
+            //
+            if ((block[0] & 0x20) == 0)
+            {
+                fullMessage = true;
+
+                // check right number of bytes passed in.
+                if (messageLength > off - mStart)
+                {
+                    return ReturnFalse(block);
+                }
+
+                digest.Reset();
+                digest.BlockUpdate(block, mStart, off - mStart);
+                digest.DoFinal(hash, 0);
+
+                bool isOkay = true;
+                
+                for (int i = 0; i != hash.Length; i++)
+                {
+                    block[off + i] ^= hash[i];
+                    if (block[off + i] != 0)
+                    {
+                        isOkay = false;
+                    }
+                }
+
+                if (!isOkay)
+                {
+                    return ReturnFalse(block);
+                }
+
+                recoveredMessage = new byte[off - mStart];
+                Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length);
+            }
+            else
+            {
+                fullMessage = false;
+
+                digest.DoFinal(hash, 0);
+
+                bool isOkay = true;
+
+                for (int i = 0; i != hash.Length; i++)
+                {
+                    block[off + i] ^= hash[i];
+                    if (block[off + i] != 0)
+                    {
+                        isOkay = false;
+                    }
+                }
+
+                if (!isOkay)
+                {
+                    return ReturnFalse(block);
+                }
+
+                recoveredMessage = new byte[off - mStart];
+                Array.Copy(block, mStart, recoveredMessage, 0, recoveredMessage.Length);
+            }
+
+            //
+            // if they've input a message check what we've recovered against
+            // what was input.
+            //
+            if (messageLength != 0)
+            {
+                if (!IsSameAs(mBuf, recoveredMessage))
+                {
+                    return ReturnFalse(block);
+                }
+            }
+
+            ClearBlock(mBuf);
+            ClearBlock(block);
+
+            return true;
+        }
+
+        private bool ReturnFalse(byte[] block)
+        {
+            ClearBlock(mBuf);
+            ClearBlock(block);
+
+            return false;
+        }
+
+        /// <summary>
+        /// Return true if the full message was recoveredMessage.
+        /// </summary>
+        /// <returns> true on full message recovery, false otherwise.</returns>
+        /// <seealso cref="ISignerWithRecovery.HasFullMessage"/>
+        public virtual bool HasFullMessage()
+        {
+            return fullMessage;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/PssSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/PssSigner.cs
new file mode 100644
index 0000000..6900224
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/PssSigner.cs
@@ -0,0 +1,345 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+	/// <summary> RSA-PSS as described in Pkcs# 1 v 2.1.
+	/// <p>
+	/// Note: the usual value for the salt length is the number of
+	/// bytes in the hash function.</p>
+	/// </summary>
+	public class PssSigner
+		: ISigner
+	{
+		public const byte TrailerImplicit = (byte)0xBC;
+
+		private readonly IDigest contentDigest1, contentDigest2;
+		private readonly IDigest mgfDigest;
+		private readonly IAsymmetricBlockCipher cipher;
+
+		private SecureRandom random;
+
+		private int hLen;
+		private int mgfhLen;
+		private int sLen;
+		private int emBits;
+		private byte[] salt;
+		private byte[] mDash;
+		private byte[] block;
+		private byte trailer;
+
+		public static PssSigner CreateRawSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					digest)
+		{
+			return new PssSigner(cipher, new NullDigest(), digest, digest, digest.GetDigestSize(), TrailerImplicit);
+		}
+
+		public static PssSigner CreateRawSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					contentDigest,
+			IDigest					mgfDigest,
+			int						saltLen,
+			byte					trailer)
+		{
+			return new PssSigner(cipher, new NullDigest(), contentDigest, mgfDigest, saltLen, trailer);
+		}
+
+		public PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					digest)
+			: this(cipher, digest, digest.GetDigestSize())
+		{
+		}
+
+		/// <summary>Basic constructor</summary>
+		/// <param name="cipher">the asymmetric cipher to use.</param>
+		/// <param name="digest">the digest to use.</param>
+		/// <param name="saltLen">the length of the salt to use (in bytes).</param>
+		public PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					digest,
+			int						saltLen)
+			: this(cipher, digest, saltLen, TrailerImplicit)
+		{
+		}
+
+		public PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					contentDigest,
+			IDigest					mgfDigest,
+			int						saltLen)
+			: this(cipher, contentDigest, mgfDigest, saltLen, TrailerImplicit)
+		{
+		}
+
+		public PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					digest,
+			int						saltLen,
+			byte					trailer)
+			: this(cipher, digest, digest, saltLen, TrailerImplicit)
+		{
+		}
+
+		public PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					contentDigest,
+			IDigest					mgfDigest,
+			int						saltLen,
+			byte					trailer)
+			: this(cipher, contentDigest, contentDigest, mgfDigest, saltLen, trailer)
+		{
+		}
+
+		private PssSigner(
+			IAsymmetricBlockCipher	cipher,
+			IDigest					contentDigest1,
+			IDigest					contentDigest2,
+			IDigest					mgfDigest,
+			int						saltLen,
+			byte					trailer)
+		{
+			this.cipher = cipher;
+			this.contentDigest1 = contentDigest1;
+			this.contentDigest2 = contentDigest2;
+			this.mgfDigest = mgfDigest;
+			this.hLen = contentDigest2.GetDigestSize();
+			this.mgfhLen = mgfDigest.GetDigestSize();
+			this.sLen = saltLen;
+			this.salt = new byte[saltLen];
+			this.mDash = new byte[8 + saltLen + hLen];
+			this.trailer = trailer;
+		}
+
+		public string AlgorithmName
+		{
+			get { return mgfDigest.AlgorithmName + "withRSAandMGF1"; }
+		}
+
+		public virtual void Init(
+			bool				forSigning,
+			ICipherParameters	parameters)
+		{
+			if (parameters is ParametersWithRandom)
+			{
+				ParametersWithRandom p = (ParametersWithRandom) parameters;
+
+				parameters = p.Parameters;
+				random = p.Random;
+			}
+			else
+			{
+				if (forSigning)
+				{
+					random = new SecureRandom();
+				}
+			}
+
+			cipher.Init(forSigning, parameters);
+
+			RsaKeyParameters kParam;
+			if (parameters is RsaBlindingParameters)
+			{
+				kParam = ((RsaBlindingParameters) parameters).PublicKey;
+			}
+			else
+			{
+				kParam = (RsaKeyParameters) parameters;
+			}
+
+			emBits = kParam.Modulus.BitLength - 1;
+
+			if (emBits < (8 * hLen + 8 * sLen + 9))
+				throw new ArgumentException("key too small for specified hash and salt lengths");
+
+			block = new byte[(emBits + 7) / 8];
+		}
+
+		/// <summary> clear possible sensitive data</summary>
+		private void ClearBlock(
+			byte[] block)
+		{
+			Array.Clear(block, 0, block.Length);
+		}
+
+		/// <summary> update the internal digest with the byte b</summary>
+		public virtual void Update(
+			byte input)
+		{
+			contentDigest1.Update(input);
+		}
+
+		/// <summary> update the internal digest with the byte array in</summary>
+		public virtual void BlockUpdate(
+			byte[]	input,
+			int		inOff,
+			int		length)
+		{
+			contentDigest1.BlockUpdate(input, inOff, length);
+		}
+
+		/// <summary> reset the internal state</summary>
+		public virtual void Reset()
+		{
+			contentDigest1.Reset();
+		}
+
+		/// <summary> Generate a signature for the message we've been loaded with using
+		/// the key we were initialised with.
+		/// </summary>
+		public virtual byte[] GenerateSignature()
+		{
+			contentDigest1.DoFinal(mDash, mDash.Length - hLen - sLen);
+
+			if (sLen != 0)
+			{
+				random.NextBytes(salt);
+				salt.CopyTo(mDash, mDash.Length - sLen);
+			}
+
+			byte[] h = new byte[hLen];
+
+			contentDigest2.BlockUpdate(mDash, 0, mDash.Length);
+
+			contentDigest2.DoFinal(h, 0);
+
+			block[block.Length - sLen - 1 - hLen - 1] = (byte) (0x01);
+			salt.CopyTo(block, block.Length - sLen - hLen - 1);
+
+			byte[] dbMask = MaskGeneratorFunction1(h, 0, h.Length, block.Length - hLen - 1);
+			for (int i = 0; i != dbMask.Length; i++)
+			{
+				block[i] ^= dbMask[i];
+			}
+
+			block[0] &= (byte) ((0xff >> ((block.Length * 8) - emBits)));
+
+			h.CopyTo(block, block.Length - hLen - 1);
+
+			block[block.Length - 1] = trailer;
+
+			byte[] b = cipher.ProcessBlock(block, 0, block.Length);
+
+			ClearBlock(block);
+
+			return b;
+		}
+
+		/// <summary> return true if the internal state represents the signature described
+		/// in the passed in array.
+		/// </summary>
+		public virtual bool VerifySignature(
+			byte[] signature)
+		{
+			contentDigest1.DoFinal(mDash, mDash.Length - hLen - sLen);
+
+			byte[] b = cipher.ProcessBlock(signature, 0, signature.Length);
+			b.CopyTo(block, block.Length - b.Length);
+
+			if (block[block.Length - 1] != trailer)
+			{
+				ClearBlock(block);
+				return false;
+			}
+
+			byte[] dbMask = MaskGeneratorFunction1(block, block.Length - hLen - 1, hLen, block.Length - hLen - 1);
+
+			for (int i = 0; i != dbMask.Length; i++)
+			{
+				block[i] ^= dbMask[i];
+			}
+
+			block[0] &= (byte) ((0xff >> ((block.Length * 8) - emBits)));
+
+			for (int i = 0; i != block.Length - hLen - sLen - 2; i++)
+			{
+				if (block[i] != 0)
+				{
+					ClearBlock(block);
+					return false;
+				}
+			}
+
+			if (block[block.Length - hLen - sLen - 2] != 0x01)
+			{
+				ClearBlock(block);
+				return false;
+			}
+
+			Array.Copy(block, block.Length - sLen - hLen - 1, mDash, mDash.Length - sLen, sLen);
+
+			contentDigest2.BlockUpdate(mDash, 0, mDash.Length);
+			contentDigest2.DoFinal(mDash, mDash.Length - hLen);
+
+			for (int i = block.Length - hLen - 1, j = mDash.Length - hLen; j != mDash.Length; i++, j++)
+			{
+				if ((block[i] ^ mDash[j]) != 0)
+				{
+					ClearBlock(mDash);
+					ClearBlock(block);
+					return false;
+				}
+			}
+
+			ClearBlock(mDash);
+			ClearBlock(block);
+
+			return true;
+		}
+
+		/// <summary> int to octet string.</summary>
+		private void ItoOSP(
+			int		i,
+			byte[]	sp)
+		{
+			sp[0] = (byte)((uint) i >> 24);
+			sp[1] = (byte)((uint) i >> 16);
+			sp[2] = (byte)((uint) i >> 8);
+			sp[3] = (byte)((uint) i >> 0);
+		}
+
+		/// <summary> mask generator function, as described in Pkcs1v2.</summary>
+		private byte[] MaskGeneratorFunction1(
+			byte[]	Z,
+			int		zOff,
+			int		zLen,
+			int		length)
+		{
+			byte[] mask = new byte[length];
+			byte[] hashBuf = new byte[mgfhLen];
+			byte[] C = new byte[4];
+			int counter = 0;
+
+			mgfDigest.Reset();
+
+			while (counter < (length / mgfhLen))
+			{
+				ItoOSP(counter, C);
+
+				mgfDigest.BlockUpdate(Z, zOff, zLen);
+				mgfDigest.BlockUpdate(C, 0, C.Length);
+				mgfDigest.DoFinal(hashBuf, 0);
+
+				hashBuf.CopyTo(mask, counter * mgfhLen);
+				++counter;
+			}
+
+			if ((counter * mgfhLen) < length)
+			{
+				ItoOSP(counter, C);
+
+				mgfDigest.BlockUpdate(Z, zOff, zLen);
+				mgfDigest.BlockUpdate(C, 0, C.Length);
+				mgfDigest.DoFinal(hashBuf, 0);
+
+				Array.Copy(hashBuf, 0, mask, counter * mgfhLen, mask.Length - (counter * mgfhLen));
+			}
+
+			return mask;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/RandomDsaKCalculator.cs b/BouncyCastle.AxCrypt/src/crypto/signers/RandomDsaKCalculator.cs
new file mode 100644
index 0000000..022cc26
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/RandomDsaKCalculator.cs
@@ -0,0 +1,44 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    public class RandomDsaKCalculator
+        :   IDsaKCalculator
+    {
+        private BigInteger q;
+        private SecureRandom random;
+
+        public virtual bool IsDeterministic
+        {
+            get { return false; }
+        }
+
+        public virtual void Init(BigInteger n, SecureRandom random)
+        {
+            this.q = n;
+            this.random = random;
+        }
+
+        public virtual void Init(BigInteger n, BigInteger d, byte[] message)
+        {
+            throw new InvalidOperationException("Operation not supported");
+        }
+
+        public virtual BigInteger NextK()
+        {
+            int qBitLength = q.BitLength;
+
+            BigInteger k;
+            do
+            {
+                k = new BigInteger(qBitLength, random);
+            }
+            while (k.SignValue < 1 || k.CompareTo(q) >= 0);
+
+            return k;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/signers/RsaDigestSigner.cs b/BouncyCastle.AxCrypt/src/crypto/signers/RsaDigestSigner.cs
new file mode 100644
index 0000000..9af4e71
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/signers/RsaDigestSigner.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Signers
+{
+    public class RsaDigestSigner
+        : ISigner
+    {
+        private readonly IAsymmetricBlockCipher rsaEngine = new Pkcs1Encoding(new RsaBlindedEngine());
+        private readonly AlgorithmIdentifier algId;
+        private readonly IDigest digest;
+        private bool forSigning;
+
+        private static readonly IDictionary oidMap = Platform.CreateHashtable();
+
+        /// <summary>
+        /// Load oid table.
+        /// </summary>
+        static RsaDigestSigner()
+        {
+            oidMap["RIPEMD128"] = TeleTrusTObjectIdentifiers.RipeMD128;
+            oidMap["RIPEMD160"] = TeleTrusTObjectIdentifiers.RipeMD160;
+            oidMap["RIPEMD256"] = TeleTrusTObjectIdentifiers.RipeMD256;
+
+            oidMap["SHA-1"] = X509ObjectIdentifiers.IdSha1;
+            oidMap["SHA-224"] = NistObjectIdentifiers.IdSha224;
+            oidMap["SHA-256"] = NistObjectIdentifiers.IdSha256;
+            oidMap["SHA-384"] = NistObjectIdentifiers.IdSha384;
+            oidMap["SHA-512"] = NistObjectIdentifiers.IdSha512;
+
+            oidMap["MD2"] = PkcsObjectIdentifiers.MD2;
+            oidMap["MD4"] = PkcsObjectIdentifiers.MD4;
+            oidMap["MD5"] = PkcsObjectIdentifiers.MD5;
+        }
+
+        public RsaDigestSigner(IDigest digest)
+            :   this(digest, (DerObjectIdentifier)oidMap[digest.AlgorithmName])
+        {
+        }
+
+        public RsaDigestSigner(IDigest digest, DerObjectIdentifier digestOid)
+            :   this(digest, new AlgorithmIdentifier(digestOid, DerNull.Instance))
+        {
+        }
+
+        public RsaDigestSigner(IDigest digest, AlgorithmIdentifier algId)
+        {
+            this.digest = digest;
+            this.algId = algId;
+        }
+
+        [Obsolete]
+        public string AlgorithmName
+        {
+            get { return digest.AlgorithmName + "withRSA"; }
+        }
+
+        /**
+         * Initialise the signer for signing or verification.
+         *
+         * @param forSigning true if for signing, false otherwise
+         * @param param necessary parameters.
+         */
+        public void Init(
+            bool				forSigning,
+            ICipherParameters	parameters)
+        {
+            this.forSigning = forSigning;
+            AsymmetricKeyParameter k;
+
+            if (parameters is ParametersWithRandom)
+            {
+                k = (AsymmetricKeyParameter)((ParametersWithRandom)parameters).Parameters;
+            }
+            else
+            {
+                k = (AsymmetricKeyParameter)parameters;
+            }
+
+            if (forSigning && !k.IsPrivate)
+                throw new InvalidKeyException("Signing requires private key.");
+
+            if (!forSigning && k.IsPrivate)
+                throw new InvalidKeyException("Verification requires public key.");
+
+            Reset();
+
+            rsaEngine.Init(forSigning, parameters);
+        }
+
+        /**
+         * update the internal digest with the byte b
+         */
+        public void Update(
+            byte input)
+        {
+            digest.Update(input);
+        }
+
+        /**
+         * update the internal digest with the byte array in
+         */
+        public void BlockUpdate(
+            byte[]	input,
+            int		inOff,
+            int		length)
+        {
+            digest.BlockUpdate(input, inOff, length);
+        }
+
+        /**
+         * Generate a signature for the message we've been loaded with using
+         * the key we were initialised with.
+         */
+        public byte[] GenerateSignature()
+        {
+            if (!forSigning)
+                throw new InvalidOperationException("RsaDigestSigner not initialised for signature generation.");
+
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            byte[] data = DerEncode(hash);
+            return rsaEngine.ProcessBlock(data, 0, data.Length);
+        }
+
+        /**
+         * return true if the internal state represents the signature described
+         * in the passed in array.
+         */
+        public bool VerifySignature(
+            byte[] signature)
+        {
+            if (forSigning)
+                throw new InvalidOperationException("RsaDigestSigner not initialised for verification");
+
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            byte[] sig;
+            byte[] expected;
+
+            try
+            {
+                sig = rsaEngine.ProcessBlock(signature, 0, signature.Length);
+                expected = DerEncode(hash);
+            }
+            catch (Exception)
+            {
+                return false;
+            }
+
+            if (sig.Length == expected.Length)
+            {
+                return Arrays.ConstantTimeAreEqual(sig, expected);
+            }
+            else if (sig.Length == expected.Length - 2)  // NULL left out
+            {
+                int sigOffset = sig.Length - hash.Length - 2;
+                int expectedOffset = expected.Length - hash.Length - 2;
+
+                expected[1] -= 2;      // adjust lengths
+                expected[3] -= 2;
+
+                int nonEqual = 0;
+
+                for (int i = 0; i < hash.Length; i++)
+                {
+                    nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]);
+                }
+
+                for (int i = 0; i < sigOffset; i++)
+                {
+                    nonEqual |= (sig[i] ^ expected[i]);  // check header less NULL
+                }
+
+                return nonEqual == 0;
+            }
+            else
+            {
+                return false;
+            }
+        }
+
+        public void Reset()
+        {
+            digest.Reset();
+        }
+
+        private byte[] DerEncode(byte[] hash)
+        {
+            if (algId == null)
+            {
+                // For raw RSA, the DigestInfo must be prepared externally
+                return hash;
+            }
+
+            DigestInfo dInfo = new DigestInfo(algId, hash);
+
+            return dInfo.GetDerEncoded();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsAgreementCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsAgreementCredentials.cs
new file mode 100644
index 0000000..2d7af80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsAgreementCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsAgreementCredentials
+        :   AbstractTlsCredentials, TlsAgreementCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        public abstract byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCipherFactory.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCipherFactory.cs
new file mode 100644
index 0000000..141ee65
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCipherFactory.cs
@@ -0,0 +1,15 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class AbstractTlsCipherFactory
+        :   TlsCipherFactory
+    {
+        /// <exception cref="IOException"></exception>
+        public virtual TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsClient.cs
new file mode 100644
index 0000000..9484afa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsClient.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsClient
+        :   AbstractTlsPeer, TlsClient
+    {
+        protected TlsCipherFactory mCipherFactory;
+
+        protected TlsClientContext mContext;
+
+        protected IList mSupportedSignatureAlgorithms;
+        protected int[] mNamedCurves;
+        protected byte[] mClientECPointFormats, mServerECPointFormats;
+
+        protected int mSelectedCipherSuite;
+        protected short mSelectedCompressionMethod;
+
+        public AbstractTlsClient()
+            :   this(new DefaultTlsCipherFactory())
+        {
+        }
+
+        public AbstractTlsClient(TlsCipherFactory cipherFactory)
+        {
+            this.mCipherFactory = cipherFactory;
+        }
+
+        public virtual void Init(TlsClientContext context)
+        {
+            this.mContext = context;
+        }
+
+        public virtual TlsSession GetSessionToResume()
+        {
+            return null;
+        }
+
+        /**
+         * RFC 5246 E.1. "TLS clients that wish to negotiate with older servers MAY send any value
+         * {03,XX} as the record layer version number. Typical values would be {03,00}, the lowest
+         * version number supported by the client, and the value of ClientHello.client_version. No
+         * single value will guarantee interoperability with all old servers, but this is a complex
+         * topic beyond the scope of this document."
+         */
+        public virtual ProtocolVersion ClientHelloRecordLayerVersion
+        {
+            get
+            {
+                // "{03,00}"
+                // return ProtocolVersion.SSLv3;
+
+                // "the lowest version number supported by the client"
+                // return getMinimumVersion();
+
+                // "the value of ClientHello.client_version"
+                return ClientVersion;
+            }
+        }
+
+        public virtual ProtocolVersion ClientVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        public virtual IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = null;
+
+            ProtocolVersion clientVersion = mContext.ClientVersion;
+
+            /*
+             * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior to 1.2.
+             * Clients MUST NOT offer it if they are offering prior versions.
+             */
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
+            {
+                // TODO Provide a way for the user to specify the acceptable hash/signature algorithms.
+
+                byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+                    HashAlgorithm.sha224, HashAlgorithm.sha1 };
+
+                // TODO Sort out ECDSA signatures and add them as the preferred option here
+                byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa };
+
+                this.mSupportedSignatureAlgorithms = Platform.CreateArrayList();
+                for (int i = 0; i < hashAlgorithms.Length; ++i)
+                {
+                    for (int j = 0; j < signatureAlgorithms.Length; ++j)
+                    {
+                        this.mSupportedSignatureAlgorithms.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+                            signatureAlgorithms[j]));
+                    }
+                }
+
+                /*
+                 * RFC 5264 7.4.3. Currently, DSA [DSS] may only be used with SHA-1.
+                 */
+                this.mSupportedSignatureAlgorithms.Add(new SignatureAndHashAlgorithm(HashAlgorithm.sha1,
+                    SignatureAlgorithm.dsa));
+
+                clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions);
+
+                TlsUtilities.AddSignatureAlgorithmsExtension(clientExtensions, mSupportedSignatureAlgorithms);
+            }
+
+            if (TlsEccUtilities.ContainsEccCipherSuites(GetCipherSuites()))
+            {
+                /*
+                 * RFC 4492 5.1. A client that proposes ECC cipher suites in its ClientHello message
+                 * appends these extensions (along with any others), enumerating the curves it supports
+                 * and the point formats it can parse. Clients SHOULD send both the Supported Elliptic
+                 * Curves Extension and the Supported Point Formats Extension.
+                 */
+                /*
+                 * TODO Could just add all the curves since we support them all, but users may not want
+                 * to use unnecessarily large fields. Need configuration options.
+                 */
+                this.mNamedCurves = new int[]{ NamedCurve.secp256r1, NamedCurve.secp384r1 };
+                this.mClientECPointFormats = new byte[]{ ECPointFormat.uncompressed,
+                    ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
+
+                clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(clientExtensions);
+
+                TlsEccUtilities.AddSupportedEllipticCurvesExtension(clientExtensions, mNamedCurves);
+                TlsEccUtilities.AddSupportedPointFormatsExtension(clientExtensions, mClientECPointFormats);
+            }
+
+            return clientExtensions;
+        }
+
+        public virtual ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.TLSv10; }
+        }
+
+        public virtual void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            if (!MinimumVersion.IsEqualOrEarlierVersionOf(serverVersion))
+                throw new TlsFatalAlert(AlertDescription.protocol_version);
+        }
+
+        public abstract int[] GetCipherSuites();
+
+        public virtual byte[] GetCompressionMethods()
+        {
+            return new byte[]{ CompressionMethod.cls_null };
+        }
+
+        public virtual void NotifySessionID(byte[] sessionID)
+        {
+            // Currently ignored
+        }
+
+        public virtual void NotifySelectedCipherSuite(int selectedCipherSuite)
+        {
+            this.mSelectedCipherSuite = selectedCipherSuite;
+        }
+
+        public virtual void NotifySelectedCompressionMethod(byte selectedCompressionMethod)
+        {
+            this.mSelectedCompressionMethod = selectedCompressionMethod;
+        }
+
+        public virtual void ProcessServerExtensions(IDictionary serverExtensions)
+        {
+            /*
+             * TlsProtocol implementation validates that any server extensions received correspond to
+             * client extensions sent. By default, we don't send any, and this method is not called.
+             */
+            if (serverExtensions != null)
+            {
+                /*
+                 * RFC 5246 7.4.1.4.1. Servers MUST NOT send this extension.
+                 */
+                if (serverExtensions.Contains(ExtensionType.signature_algorithms))
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+                int[] namedCurves = TlsEccUtilities.GetSupportedEllipticCurvesExtension(serverExtensions);
+                if (namedCurves != null)
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+                this.mServerECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(serverExtensions);
+                if (this.mServerECPointFormats != null && !TlsEccUtilities.IsEccCipherSuite(this.mSelectedCipherSuite))
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+        }
+
+        public virtual void ProcessServerSupplementalData(IList serverSupplementalData)
+        {
+            if (serverSupplementalData != null)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public abstract TlsKeyExchange GetKeyExchange();
+
+        public abstract TlsAuthentication GetAuthentication();
+
+        public virtual IList GetClientSupplementalData()
+        {
+            return null;
+        }
+
+        public override TlsCompression GetCompression()
+        {
+            switch (mSelectedCompressionMethod)
+            {
+            case CompressionMethod.cls_null:
+                return new TlsNullCompression();
+
+            case CompressionMethod.DEFLATE:
+                return new TlsDeflateCompression();
+
+            default:
+                /*
+                 * Note: internal error here; the TlsProtocol implementation verifies that the
+                 * server-selected compression method was in the list of client-offered compression
+                 * methods, so if we now can't produce an implementation, we shouldn't have offered it!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public virtual void NotifyNewSessionTicket(NewSessionTicket newSessionTicket)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsContext.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsContext.cs
new file mode 100644
index 0000000..83150d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsContext.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Threading;
+
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal abstract class AbstractTlsContext
+        : TlsContext
+    {
+        private static long counter = Times.NanoTime();
+
+        private static long NextCounterValue()
+        {
+            return Interlocked.Increment(ref counter);
+        }
+
+        private readonly IRandomGenerator mNonceRandom;
+        private readonly SecureRandom mSecureRandom;
+        private readonly SecurityParameters mSecurityParameters;
+
+        private ProtocolVersion mClientVersion = null;
+        private ProtocolVersion mServerVersion = null;
+        private TlsSession mSession = null;
+        private object mUserObject = null;
+
+       internal AbstractTlsContext(SecureRandom secureRandom, SecurityParameters securityParameters)
+        {
+            IDigest d = TlsUtilities.CreateHash(HashAlgorithm.sha256);
+            byte[] seed = new byte[d.GetDigestSize()];
+            secureRandom.NextBytes(seed);
+
+            this.mNonceRandom = new DigestRandomGenerator(d);
+            mNonceRandom.AddSeedMaterial(NextCounterValue());
+            mNonceRandom.AddSeedMaterial(Times.NanoTime());
+            mNonceRandom.AddSeedMaterial(seed);
+
+            this.mSecureRandom = secureRandom;
+            this.mSecurityParameters = securityParameters;
+        }
+
+        public virtual IRandomGenerator NonceRandomGenerator
+        {
+            get { return mNonceRandom; }
+        }
+
+        public virtual SecureRandom SecureRandom
+        {
+            get { return mSecureRandom; }
+        }
+
+        public virtual SecurityParameters SecurityParameters
+        {
+            get { return mSecurityParameters; }
+        }
+
+        public abstract bool IsServer { get; }
+
+        public virtual ProtocolVersion ClientVersion
+        {
+            get { return mClientVersion; }
+        }
+
+        internal virtual void SetClientVersion(ProtocolVersion clientVersion)
+        {
+            this.mClientVersion = clientVersion;
+        }
+
+        public virtual ProtocolVersion ServerVersion
+        {
+            get { return mServerVersion; }
+        }
+
+        internal virtual void SetServerVersion(ProtocolVersion serverVersion)
+        {
+            this.mServerVersion = serverVersion;
+        }
+
+        public virtual TlsSession ResumableSession
+        {
+            get { return mSession; }
+        }
+
+        internal virtual void SetResumableSession(TlsSession session)
+        {
+            this.mSession = session;
+        }
+
+        public virtual object UserObject
+        {
+            get { return mUserObject; }
+            set { this.mUserObject = value; }
+        }
+
+        public virtual byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length)
+        {
+            if (context_value != null && !TlsUtilities.IsValidUint16(context_value.Length))
+                throw new ArgumentException("must have length less than 2^16 (or be null)", "context_value");
+
+            SecurityParameters sp = SecurityParameters;
+            byte[] cr = sp.ClientRandom, sr = sp.ServerRandom;
+
+            int seedLength = cr.Length + sr.Length;
+            if (context_value != null)
+            {
+                seedLength += (2 + context_value.Length);
+            }
+
+            byte[] seed = new byte[seedLength];
+            int seedPos = 0;
+
+            Array.Copy(cr, 0, seed, seedPos, cr.Length);
+            seedPos += cr.Length;
+            Array.Copy(sr, 0, seed, seedPos, sr.Length);
+            seedPos += sr.Length;
+            if (context_value != null)
+            {
+                TlsUtilities.WriteUint16(context_value.Length, seed, seedPos);
+                seedPos += 2;
+                Array.Copy(context_value, 0, seed, seedPos, context_value.Length);
+                seedPos += context_value.Length;
+            }
+
+            if (seedPos != seedLength)
+                throw new InvalidOperationException("error in calculation of seed for export");
+
+            return TlsUtilities.PRF(this, sp.MasterSecret, asciiLabel, seed, length);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCredentials.cs
new file mode 100644
index 0000000..6411b81
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsCredentials.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsCredentials
+        :   TlsCredentials
+    {
+        public abstract Certificate Certificate { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsEncryptionCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsEncryptionCredentials.cs
new file mode 100644
index 0000000..05b129c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsEncryptionCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsEncryptionCredentials
+        : AbstractTlsCredentials, TlsEncryptionCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        public abstract byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsKeyExchange.cs
new file mode 100644
index 0000000..155ac94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsKeyExchange.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsKeyExchange
+        :   TlsKeyExchange
+    {
+        protected readonly int mKeyExchange;
+        protected IList mSupportedSignatureAlgorithms;
+
+        protected TlsContext context;
+
+        protected AbstractTlsKeyExchange(int keyExchange, IList supportedSignatureAlgorithms)
+        {
+            this.mKeyExchange = keyExchange;
+            this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
+        }
+
+        public virtual void Init(TlsContext context)
+        {
+            this.context = context;
+
+            ProtocolVersion clientVersion = context.ClientVersion;
+
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(clientVersion))
+            {
+                /*
+                 * RFC 5264 7.4.1.4.1. If the client does not send the signature_algorithms extension,
+                 * the server MUST do the following:
+                 * 
+                 * - If the negotiated key exchange algorithm is one of (RSA, DHE_RSA, DH_RSA, RSA_PSK,
+                 * ECDH_RSA, ECDHE_RSA), behave as if client had sent the value {sha1,rsa}.
+                 * 
+                 * - If the negotiated key exchange algorithm is one of (DHE_DSS, DH_DSS), behave as if
+                 * the client had sent the value {sha1,dsa}.
+                 * 
+                 * - If the negotiated key exchange algorithm is one of (ECDH_ECDSA, ECDHE_ECDSA),
+                 * behave as if the client had sent value {sha1,ecdsa}.
+                 */
+                if (this.mSupportedSignatureAlgorithms == null)
+                {
+                    switch (mKeyExchange)
+                    {
+                    case KeyExchangeAlgorithm.DH_DSS:
+                    case KeyExchangeAlgorithm.DHE_DSS:
+                    case KeyExchangeAlgorithm.SRP_DSS:
+                    {
+                        this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultDssSignatureAlgorithms();
+                        break;
+                    }
+
+                    case KeyExchangeAlgorithm.ECDH_ECDSA:
+                    case KeyExchangeAlgorithm.ECDHE_ECDSA:
+                    {
+                        this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultECDsaSignatureAlgorithms();
+                        break;
+                    }
+
+                    case KeyExchangeAlgorithm.DH_RSA:
+                    case KeyExchangeAlgorithm.DHE_RSA:
+                    case KeyExchangeAlgorithm.ECDH_RSA:
+                    case KeyExchangeAlgorithm.ECDHE_RSA:
+                    case KeyExchangeAlgorithm.RSA:
+                    case KeyExchangeAlgorithm.RSA_PSK:
+                    case KeyExchangeAlgorithm.SRP_RSA:
+                    {
+                        this.mSupportedSignatureAlgorithms = TlsUtilities.GetDefaultRsaSignatureAlgorithms();
+                        break;
+                    }
+
+                    case KeyExchangeAlgorithm.DHE_PSK:
+                    case KeyExchangeAlgorithm.ECDHE_PSK:
+                    case KeyExchangeAlgorithm.PSK:
+                    case KeyExchangeAlgorithm.SRP:
+                        break;
+
+                    default:
+                        throw new InvalidOperationException("unsupported key exchange algorithm");
+                    }
+                }
+
+            }
+            else if (this.mSupportedSignatureAlgorithms != null)
+            {
+                throw new InvalidOperationException("supported_signature_algorithms not allowed for " + clientVersion);
+            }
+        }
+
+        public abstract void SkipServerCredentials();
+
+        public virtual void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (mSupportedSignatureAlgorithms == null)
+            {
+                /*
+                 * TODO RFC 2264 7.4.2. Unless otherwise specified, the signing algorithm for the
+                 * certificate must be the same as the algorithm for the certificate key.
+                 */
+            }
+            else
+            {
+                /*
+                 * TODO RFC 5264 7.4.2. If the client provided a "signature_algorithms" extension, then
+                 * all certificates provided by the server MUST be signed by a hash/signature algorithm
+                 * pair that appears in that extension.
+                 */
+            }
+        }
+
+        public virtual void ProcessServerCredentials(TlsCredentials serverCredentials)
+        {
+            ProcessServerCertificate(serverCredentials.Certificate);
+        }
+
+        public virtual bool RequiresServerKeyExchange
+        {
+            get { return false; }
+        }
+
+        public virtual byte[] GenerateServerKeyExchange()
+        {
+            if (RequiresServerKeyExchange)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            return null;
+        }
+
+        public virtual void SkipServerKeyExchange()
+        {
+            if (RequiresServerKeyExchange)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public virtual void ProcessServerKeyExchange(Stream input)
+        {
+            if (!RequiresServerKeyExchange)
+            {
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+            }
+        }
+
+        public abstract void ValidateCertificateRequest(CertificateRequest certificateRequest);
+
+        public virtual void SkipClientCredentials()
+        {
+        }
+
+        public abstract void ProcessClientCredentials(TlsCredentials clientCredentials);
+
+        public virtual void ProcessClientCertificate(Certificate clientCertificate)
+        {
+        }
+
+        public abstract void GenerateClientKeyExchange(Stream output);
+
+        public virtual void ProcessClientKeyExchange(Stream input)
+        {
+            // Key exchange implementation MUST support client key exchange
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public abstract byte[] GeneratePremasterSecret();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsPeer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsPeer.cs
new file mode 100644
index 0000000..81a5338
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsPeer.cs
@@ -0,0 +1,48 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsPeer
+        :   TlsPeer
+    {
+        public virtual bool ShouldUseGmtUnixTime()
+        {
+            /*
+             * draft-mathewson-no-gmtunixtime-00 2. For the reasons we discuss above, we recommend that
+             * TLS implementors MUST by default set the entire value the ClientHello.Random and
+             * ServerHello.Random fields, including gmt_unix_time, to a cryptographically random
+             * sequence.
+             */
+            return false;
+        }
+
+        public virtual void NotifySecureRenegotiation(bool secureRenegotiation)
+        {
+            if (!secureRenegotiation)
+            {
+                /*
+                 * RFC 5746 3.4/3.6. In this case, some clients/servers may want to terminate the handshake instead
+                 * of continuing; see Section 4.1/4.3 for discussion.
+                 */
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+            }
+        }
+
+        public abstract TlsCompression GetCompression();
+
+        public abstract TlsCipher GetCipher();
+
+        public virtual void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+        }
+
+        public virtual void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+        }
+
+        public virtual void NotifyHandshakeComplete()
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsServer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsServer.cs
new file mode 100644
index 0000000..47542c7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsServer.cs
@@ -0,0 +1,318 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsServer
+        :   AbstractTlsPeer, TlsServer
+    {
+        protected TlsCipherFactory mCipherFactory;
+
+        protected TlsServerContext mContext;
+
+        protected ProtocolVersion mClientVersion;
+        protected int[] mOfferedCipherSuites;
+        protected byte[] mOfferedCompressionMethods;
+        protected IDictionary mClientExtensions;
+
+        protected bool mEncryptThenMacOffered;
+        protected short mMaxFragmentLengthOffered;
+        protected bool mTruncatedHMacOffered;
+        protected IList mSupportedSignatureAlgorithms;
+        protected bool mEccCipherSuitesOffered;
+        protected int[] mNamedCurves;
+        protected byte[] mClientECPointFormats, mServerECPointFormats;
+
+        protected ProtocolVersion mServerVersion;
+        protected int mSelectedCipherSuite;
+        protected byte mSelectedCompressionMethod;
+        protected IDictionary mServerExtensions;
+
+        public AbstractTlsServer()
+            :   this(new DefaultTlsCipherFactory())
+        {
+        }
+
+        public AbstractTlsServer(TlsCipherFactory cipherFactory)
+        {
+            this.mCipherFactory = cipherFactory;
+        }
+
+        protected virtual bool AllowEncryptThenMac
+        {
+            get { return true; }
+        }
+
+        protected virtual bool AllowTruncatedHMac
+        {
+            get { return false; }
+        }
+
+        protected virtual IDictionary CheckServerExtensions()
+        {
+            return this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mServerExtensions);
+        }
+
+        protected abstract int[] GetCipherSuites();
+
+        protected byte[] GetCompressionMethods()
+        {
+            return new byte[] { CompressionMethod.cls_null };
+        }
+
+        protected virtual ProtocolVersion MaximumVersion
+        {
+            get { return ProtocolVersion.TLSv11; }
+        }
+
+        protected virtual ProtocolVersion MinimumVersion
+        {
+            get { return ProtocolVersion.TLSv10; }
+        }
+
+        protected virtual bool SupportsClientEccCapabilities(int[] namedCurves, byte[] ecPointFormats)
+        {
+            // NOTE: BC supports all the current set of point formats so we don't check them here
+
+            if (namedCurves == null)
+            {
+                /*
+                 * RFC 4492 4. A client that proposes ECC cipher suites may choose not to include these
+                 * extensions. In this case, the server is free to choose any one of the elliptic curves
+                 * or point formats [...].
+                 */
+                return TlsEccUtilities.HasAnySupportedNamedCurves();
+            }
+
+            for (int i = 0; i < namedCurves.Length; ++i)
+            {
+                int namedCurve = namedCurves[i];
+                if (NamedCurve.IsValid(namedCurve)
+                    && (!NamedCurve.RefersToASpecificNamedCurve(namedCurve) || TlsEccUtilities.IsSupportedNamedCurve(namedCurve)))
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+
+        public virtual void Init(TlsServerContext context)
+        {
+            this.mContext = context;
+        }
+
+        public virtual void NotifyClientVersion(ProtocolVersion clientVersion)
+        {
+            this.mClientVersion = clientVersion;
+        }
+
+        public virtual void NotifyOfferedCipherSuites(int[] offeredCipherSuites)
+        {
+            this.mOfferedCipherSuites = offeredCipherSuites;
+            this.mEccCipherSuitesOffered = TlsEccUtilities.ContainsEccCipherSuites(this.mOfferedCipherSuites);
+        }
+
+        public virtual void NotifyOfferedCompressionMethods(byte[] offeredCompressionMethods)
+        {
+            this.mOfferedCompressionMethods = offeredCompressionMethods;
+        }
+
+        public virtual void ProcessClientExtensions(IDictionary clientExtensions)
+        {
+            this.mClientExtensions = clientExtensions;
+
+            if (clientExtensions != null)
+            {
+                this.mEncryptThenMacOffered = TlsExtensionsUtilities.HasEncryptThenMacExtension(clientExtensions);
+                this.mMaxFragmentLengthOffered = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions);
+                this.mTruncatedHMacOffered = TlsExtensionsUtilities.HasTruncatedHMacExtension(clientExtensions);
+
+                this.mSupportedSignatureAlgorithms = TlsUtilities.GetSignatureAlgorithmsExtension(clientExtensions);
+                if (this.mSupportedSignatureAlgorithms != null)
+                {
+                    /*
+                     * RFC 5246 7.4.1.4.1. Note: this extension is not meaningful for TLS versions prior
+                     * to 1.2. Clients MUST NOT offer it if they are offering prior versions.
+                     */
+                    if (!TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mClientVersion))
+                        throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+
+                this.mNamedCurves = TlsEccUtilities.GetSupportedEllipticCurvesExtension(clientExtensions);
+                this.mClientECPointFormats = TlsEccUtilities.GetSupportedPointFormatsExtension(clientExtensions);
+            }
+
+            /*
+             * RFC 4429 4. The client MUST NOT include these extensions in the ClientHello message if it
+             * does not propose any ECC cipher suites.
+             */
+            if (!this.mEccCipherSuitesOffered && (this.mNamedCurves != null || this.mClientECPointFormats != null))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+        }
+
+        public virtual ProtocolVersion GetServerVersion()
+        {
+            if (MinimumVersion.IsEqualOrEarlierVersionOf(mClientVersion))
+            {
+                ProtocolVersion maximumVersion = MaximumVersion;
+                if (mClientVersion.IsEqualOrEarlierVersionOf(maximumVersion))
+                {
+                    return mServerVersion = mClientVersion;
+                }
+                if (mClientVersion.IsLaterVersionOf(maximumVersion))
+                {
+                    return mServerVersion = maximumVersion;
+                }
+            }
+            throw new TlsFatalAlert(AlertDescription.protocol_version);
+        }
+
+        public virtual int GetSelectedCipherSuite()
+        {
+            /*
+             * TODO RFC 5246 7.4.3. In order to negotiate correctly, the server MUST check any candidate
+             * cipher suites against the "signature_algorithms" extension before selecting them. This is
+             * somewhat inelegant but is a compromise designed to minimize changes to the original
+             * cipher suite design.
+             */
+
+            /*
+             * RFC 4429 5.1. A server that receives a ClientHello containing one or both of these
+             * extensions MUST use the client's enumerated capabilities to guide its selection of an
+             * appropriate cipher suite. One of the proposed ECC cipher suites must be negotiated only
+             * if the server can successfully complete the handshake while using the curves and point
+             * formats supported by the client [...].
+             */
+            bool eccCipherSuitesEnabled = SupportsClientEccCapabilities(this.mNamedCurves, this.mClientECPointFormats);
+
+            int[] cipherSuites = GetCipherSuites();
+            for (int i = 0; i < cipherSuites.Length; ++i)
+            {
+                int cipherSuite = cipherSuites[i];
+
+                if (Arrays.Contains(this.mOfferedCipherSuites, cipherSuite)
+                    && (eccCipherSuitesEnabled || !TlsEccUtilities.IsEccCipherSuite(cipherSuite))
+                    && TlsUtilities.IsValidCipherSuiteForVersion(cipherSuite, mServerVersion))
+                {
+                    return this.mSelectedCipherSuite = cipherSuite;
+                }
+            }
+            throw new TlsFatalAlert(AlertDescription.handshake_failure);
+        }
+
+        public virtual byte GetSelectedCompressionMethod()
+        {
+            byte[] compressionMethods = GetCompressionMethods();
+            for (int i = 0; i < compressionMethods.Length; ++i)
+            {
+                if (Arrays.Contains(mOfferedCompressionMethods, compressionMethods[i]))
+                {
+                    return this.mSelectedCompressionMethod = compressionMethods[i];
+                }
+            }
+            throw new TlsFatalAlert(AlertDescription.handshake_failure);
+        }
+
+        // IDictionary is (Int32 -> byte[])
+        public virtual IDictionary GetServerExtensions()
+        {
+            if (this.mEncryptThenMacOffered && AllowEncryptThenMac)
+            {
+                /*
+                 * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
+                 * request extension from a client and then selects a stream or AEAD cipher suite, it
+                 * MUST NOT send an encrypt-then-MAC response extension back to the client.
+                 */
+                if (TlsUtilities.IsBlockCipherSuite(this.mSelectedCipherSuite))
+                {
+                    TlsExtensionsUtilities.AddEncryptThenMacExtension(CheckServerExtensions());
+                }
+            }
+
+            if (this.mMaxFragmentLengthOffered >= 0)
+            {
+                TlsExtensionsUtilities.AddMaxFragmentLengthExtension(CheckServerExtensions(), (byte)this.mMaxFragmentLengthOffered);
+            }
+
+            if (this.mTruncatedHMacOffered && AllowTruncatedHMac)
+            {
+                TlsExtensionsUtilities.AddTruncatedHMacExtension(CheckServerExtensions());
+            }
+
+            if (this.mClientECPointFormats != null && TlsEccUtilities.IsEccCipherSuite(this.mSelectedCipherSuite))
+            {
+                /*
+                 * RFC 4492 5.2. A server that selects an ECC cipher suite in response to a ClientHello
+                 * message including a Supported Point Formats Extension appends this extension (along
+                 * with others) to its ServerHello message, enumerating the point formats it can parse.
+                 */
+                this.mServerECPointFormats = new byte[]{ ECPointFormat.uncompressed,
+                    ECPointFormat.ansiX962_compressed_prime, ECPointFormat.ansiX962_compressed_char2, };
+
+                TlsEccUtilities.AddSupportedPointFormatsExtension(CheckServerExtensions(), mServerECPointFormats);
+            }
+
+            return mServerExtensions;
+        }
+
+        public virtual IList GetServerSupplementalData()
+        {
+            return null;
+        }
+
+        public abstract TlsCredentials GetCredentials();
+
+        public virtual CertificateStatus GetCertificateStatus()
+        {
+            return null;
+        }
+
+        public abstract TlsKeyExchange GetKeyExchange();
+
+        public virtual CertificateRequest GetCertificateRequest()
+        {
+            return null;
+        }
+
+        public virtual void ProcessClientSupplementalData(IList clientSupplementalData)
+        {
+            if (clientSupplementalData != null)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public virtual void NotifyClientCertificate(Certificate clientCertificate)
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public override TlsCompression GetCompression()
+        {
+            switch (mSelectedCompressionMethod)
+            {
+            case CompressionMethod.cls_null:
+                return new TlsNullCompression();
+
+            default:
+                /*
+                 * Note: internal error here; we selected the compression method, so if we now can't
+                 * produce an implementation, we shouldn't have chosen it!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public virtual NewSessionTicket GetNewSessionTicket()
+        {
+            /*
+             * RFC 5077 3.3. If the server determines that it does not want to include a ticket after it
+             * has included the SessionTicket extension in the ServerHello, then it sends a zero-length
+             * ticket in the NewSessionTicket handshake message.
+             */
+            return new NewSessionTicket(0L, TlsUtilities.EmptyBytes);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSigner.cs
new file mode 100644
index 0000000..1f4aabf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSigner.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsSigner
+        :   TlsSigner
+    {
+        protected TlsContext mContext;
+
+        public virtual void Init(TlsContext context)
+        {
+            this.mContext = context;
+        }
+
+        public virtual byte[] GenerateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1)
+        {
+            return GenerateRawSignature(null, privateKey, md5AndSha1);
+        }
+
+        public abstract byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+            AsymmetricKeyParameter privateKey, byte[] hash);
+
+        public virtual bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1)
+        {
+            return VerifyRawSignature(null, sigBytes, publicKey, md5AndSha1);
+        }
+
+        public abstract bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+            AsymmetricKeyParameter publicKey, byte[] hash);
+
+        public virtual ISigner CreateSigner(AsymmetricKeyParameter privateKey)
+        {
+            return CreateSigner(null, privateKey);
+        }
+
+        public abstract ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
+
+        public virtual ISigner CreateVerifyer(AsymmetricKeyParameter publicKey)
+        {
+            return CreateVerifyer(null, publicKey);
+        }
+
+        public abstract ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
+
+        public abstract bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSignerCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSignerCredentials.cs
new file mode 100644
index 0000000..886c46c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AbstractTlsSignerCredentials.cs
@@ -0,0 +1,20 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class AbstractTlsSignerCredentials
+        : AbstractTlsCredentials, TlsSignerCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        public abstract byte[] GenerateCertificateSignature(byte[] hash);
+
+        public virtual SignatureAndHashAlgorithm SignatureAndHashAlgorithm
+        {
+            get
+            {
+                throw new InvalidOperationException("TlsSignerCredentials implementation does not support (D)TLS 1.2+");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AlertDescription.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AlertDescription.cs
new file mode 100644
index 0000000..e09da6c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AlertDescription.cs
@@ -0,0 +1,217 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 5246 7.2
+    /// </summary>
+    public abstract class AlertDescription
+    {
+        /**
+         * This message notifies the recipient that the sender will not send any more messages on this
+         * connection. Note that as of TLS 1.1, failure to properly close a connection no longer
+         * requires that a session not be resumed. This is a change from TLS 1.0 ("The session becomes
+         * unresumable if any connection is terminated without proper close_notify messages with level
+         * equal to warning.") to conform with widespread implementation practice.
+         */
+        public const byte close_notify = 0;
+
+        /**
+         * An inappropriate message was received. This alert is always fatal and should never be
+         * observed in communication between proper implementations.
+         */
+        public const byte unexpected_message = 10;
+
+        /**
+         * This alert is returned if a record is received with an incorrect MAC. This alert also MUST be
+         * returned if an alert is sent because a TLSCiphertext decrypted in an invalid way: either it
+         * wasn't an even multiple of the block length, or its padding values, when checked, weren't
+         * correct. This message is always fatal and should never be observed in communication between
+         * proper implementations (except when messages were corrupted in the network).
+         */
+        public const byte bad_record_mac = 20;
+
+        /**
+         * This alert was used in some earlier versions of TLS, and may have permitted certain attacks
+         * against the CBC mode [CBCATT]. It MUST NOT be sent by compliant implementations.
+         */
+        public const byte decryption_failed = 21;
+
+        /**
+         * A TLSCiphertext record was received that had a length more than 2^14+2048 bytes, or a record
+         * decrypted to a TLSCompressed record with more than 2^14+1024 bytes. This message is always
+         * fatal and should never be observed in communication between proper implementations (except
+         * when messages were corrupted in the network).
+         */
+        public const byte record_overflow = 22;
+
+        /**
+         * The decompression function received improper input (e.g., data that would expand to excessive
+         * length). This message is always fatal and should never be observed in communication between
+         * proper implementations.
+         */
+        public const byte decompression_failure = 30;
+
+        /**
+         * Reception of a handshake_failure alert message indicates that the sender was unable to
+         * negotiate an acceptable set of security parameters given the options available. This is a
+         * fatal error.
+         */
+        public const byte handshake_failure = 40;
+
+        /**
+         * This alert was used in SSLv3 but not any version of TLS. It MUST NOT be sent by compliant
+         * implementations.
+         */
+        public const byte no_certificate = 41;
+
+        /**
+         * A certificate was corrupt, contained signatures that did not verify correctly, etc.
+         */
+        public const byte bad_certificate = 42;
+
+        /**
+         * A certificate was of an unsupported type.
+         */
+        public const byte unsupported_certificate = 43;
+
+        /**
+         * A certificate was revoked by its signer.
+         */
+        public const byte certificate_revoked = 44;
+
+        /**
+         * A certificate has expired or is not currently valid.
+         */
+        public const byte certificate_expired = 45;
+
+        /**
+         * Some other (unspecified) issue arose in processing the certificate, rendering it
+         * unacceptable.
+         */
+        public const byte certificate_unknown = 46;
+
+        /**
+         * A field in the handshake was out of range or inconsistent with other fields. This message is
+         * always fatal.
+         */
+        public const byte illegal_parameter = 47;
+
+        /**
+         * A valid certificate chain or partial chain was received, but the certificate was not accepted
+         * because the CA certificate could not be located or couldn't be matched with a known, trusted
+         * CA. This message is always fatal.
+         */
+        public const byte unknown_ca = 48;
+
+        /**
+         * A valid certificate was received, but when access control was applied, the sender decided not
+         * to proceed with negotiation. This message is always fatal.
+         */
+        public const byte access_denied = 49;
+
+        /**
+         * A message could not be decoded because some field was out of the specified range or the
+         * length of the message was incorrect. This message is always fatal and should never be
+         * observed in communication between proper implementations (except when messages were corrupted
+         * in the network).
+         */
+        public const byte decode_error = 50;
+
+        /**
+         * A handshake cryptographic operation failed, including being unable to correctly verify a
+         * signature or validate a Finished message. This message is always fatal.
+         */
+        public const byte decrypt_error = 51;
+
+        /**
+         * This alert was used in some earlier versions of TLS. It MUST NOT be sent by compliant
+         * implementations.
+         */
+        public const byte export_restriction = 60;
+
+        /**
+         * The protocol version the client has attempted to negotiate is recognized but not supported.
+         * (For example, old protocol versions might be avoided for security reasons.) This message is
+         * always fatal.
+         */
+        public const byte protocol_version = 70;
+
+        /**
+         * Returned instead of handshake_failure when a negotiation has failed specifically because the
+         * server requires ciphers more secure than those supported by the client. This message is
+         * always fatal.
+         */
+        public const byte insufficient_security = 71;
+
+        /**
+         * An internal error unrelated to the peer or the correctness of the protocol (such as a memory
+         * allocation failure) makes it impossible to continue. This message is always fatal.
+         */
+        public const byte internal_error = 80;
+
+        /**
+         * This handshake is being canceled for some reason unrelated to a protocol failure. If the user
+         * cancels an operation after the handshake is complete, just closing the connection by sending
+         * a close_notify is more appropriate. This alert should be followed by a close_notify. This
+         * message is generally a warning.
+         */
+        public const byte user_canceled = 90;
+
+        /**
+         * Sent by the client in response to a hello request or by the server in response to a client
+         * hello after initial handshaking. Either of these would normally lead to renegotiation; when
+         * that is not appropriate, the recipient should respond with this alert. At that point, the
+         * original requester can decide whether to proceed with the connection. One case where this
+         * would be appropriate is where a server has spawned a process to satisfy a request; the
+         * process might receive security parameters (key length, authentication, etc.) at startup, and
+         * it might be difficult to communicate changes to these parameters after that point. This
+         * message is always a warning.
+         */
+        public const byte no_renegotiation = 100;
+
+        /**
+         * Sent by clients that receive an extended server hello containing an extension that they did
+         * not put in the corresponding client hello. This message is always fatal.
+         */
+        public const byte unsupported_extension = 110;
+
+        /*
+         * RFC 3546
+         */
+
+        /**
+         * This alert is sent by servers who are unable to retrieve a certificate chain from the URL
+         * supplied by the client (see Section 3.3). This message MAY be fatal - for example if client
+         * authentication is required by the server for the handshake to continue and the server is
+         * unable to retrieve the certificate chain, it may send a fatal alert.
+         */
+        public const byte certificate_unobtainable = 111;
+
+        /**
+         * This alert is sent by servers that receive a server_name extension request, but do not
+         * recognize the server name. This message MAY be fatal.
+         */
+        public const byte unrecognized_name = 112;
+
+        /**
+         * This alert is sent by clients that receive an invalid certificate status response (see
+         * Section 3.6). This message is always fatal.
+         */
+        public const byte bad_certificate_status_response = 113;
+
+        /**
+         * This alert is sent by servers when a certificate hash does not match a client provided
+         * certificate_hash. This message is always fatal.
+         */
+        public const byte bad_certificate_hash_value = 114;
+
+        /*
+         * RFC 4279
+         */
+
+        /**
+         * If the server does not recognize the PSK identity, it MAY respond with an
+         * "unknown_psk_identity" alert message.
+         */
+        public const byte unknown_psk_identity = 115;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AlertLevel.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AlertLevel.cs
new file mode 100644
index 0000000..d77251d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AlertLevel.cs
@@ -0,0 +1,11 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 5246 7.2
+    /// </summary>
+    public abstract class AlertLevel
+    {
+        public const byte warning = 1;
+        public const byte fatal = 2;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/AlwaysValidVerifyer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/AlwaysValidVerifyer.cs
new file mode 100644
index 0000000..e26c6fc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/AlwaysValidVerifyer.cs
@@ -0,0 +1,24 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	/// <remarks>
+	/// A certificate verifyer, that will always return true.
+	/// <pre>
+	/// DO NOT USE THIS FILE UNLESS YOU KNOW EXACTLY WHAT YOU ARE DOING.
+	/// </pre>
+	/// </remarks>
+	[Obsolete("Perform certificate verification in TlsAuthentication implementation")]
+	public class AlwaysValidVerifyer
+		: ICertificateVerifyer
+	{
+		/// <summary>Return true.</summary>
+		public bool IsValid(
+			X509CertificateStructure[] certs)
+		{
+			return true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/BulkCipherAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/BulkCipherAlgorithm.cs
new file mode 100644
index 0000000..07ff8dc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/BulkCipherAlgorithm.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class BulkCipherAlgorithm
+    {
+        public const int cls_null = 0;
+        public const int rc4 = 1;
+        public const int rc2 = 2;
+        public const int des = 3;
+        public const int cls_3des = 4;
+        public const int des40 = 5;
+
+        /*
+         * RFC 4346
+         */
+        public const int aes = 6;
+        public const int idea = 7;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ByteQueue.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ByteQueue.cs
new file mode 100644
index 0000000..f9398bb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ByteQueue.cs
@@ -0,0 +1,147 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <remarks>
+    /// A queue for bytes.
+    /// <p>
+    /// This file could be more optimized.
+    /// </p>
+    /// </remarks>
+    public class ByteQueue
+    {
+        /// <returns>The smallest number which can be written as 2^x which is bigger than i.</returns>
+        public static int NextTwoPow(
+            int i)
+        {
+            /*
+            * This code is based of a lot of code I found on the Internet
+            * which mostly referenced a book called "Hacking delight".
+            *
+            */
+            i |= (i >> 1);
+            i |= (i >> 2);
+            i |= (i >> 4);
+            i |= (i >> 8);
+            i |= (i >> 16);
+            return i + 1;
+        }
+
+        /**
+         * The initial size for our buffer.
+         */
+        private const int DefaultCapacity = 1024;
+
+        /**
+         * The buffer where we store our data.
+         */
+        private byte[] databuf;
+
+        /**
+         * How many bytes at the beginning of the buffer are skipped.
+         */
+        private int skipped = 0;
+
+        /**
+         * How many bytes in the buffer are valid data.
+         */
+        private int available = 0;
+
+        public ByteQueue()
+            : this(DefaultCapacity)
+        {
+        }
+
+        public ByteQueue(int capacity)
+        {
+            this.databuf = new byte[capacity];
+        }
+
+        /// <summary>Read data from the buffer.</summary>
+        /// <param name="buf">The buffer where the read data will be copied to.</param>
+        /// <param name="offset">How many bytes to skip at the beginning of buf.</param>
+        /// <param name="len">How many bytes to read at all.</param>
+        /// <param name="skip">How many bytes from our data to skip.</param>
+        public void Read(
+            byte[]	buf,
+            int		offset,
+            int		len,
+            int		skip)
+        {
+            if ((buf.Length - offset) < len)
+            {
+                throw new ArgumentException("Buffer size of " + buf.Length + " is too small for a read of " + len + " bytes");
+            }
+            if ((available - skip) < len)
+            {
+                throw new InvalidOperationException("Not enough data to read");
+            }
+            Array.Copy(databuf, skipped + skip, buf, offset, len);
+        }
+
+        /// <summary>Add some data to our buffer.</summary>
+        /// <param name="data">A byte-array to read data from.</param>
+        /// <param name="offset">How many bytes to skip at the beginning of the array.</param>
+        /// <param name="len">How many bytes to read from the array.</param>
+        public void AddData(
+            byte[]	data,
+            int		offset,
+            int		len)
+        {
+            if ((skipped + available + len) > databuf.Length)
+            {
+                int desiredSize = ByteQueue.NextTwoPow(available + len);
+                if (desiredSize > databuf.Length)
+                {
+                    byte[] tmp = new byte[desiredSize];
+                    Array.Copy(databuf, skipped, tmp, 0, available);
+                    databuf = tmp;
+                }
+                else
+                {
+                    Array.Copy(databuf, skipped, databuf, 0, available);
+                }
+                skipped = 0;
+            }
+
+            Array.Copy(data, offset, databuf, skipped + available, len);
+            available += len;
+        }
+
+        /// <summary>Remove some bytes from our data from the beginning.</summary>
+        /// <param name="i">How many bytes to remove.</param>
+        public void RemoveData(
+            int i)
+        {
+            if (i > available)
+            {
+                throw new InvalidOperationException("Cannot remove " + i + " bytes, only got " + available);
+            }
+
+            /*
+            * Skip the data.
+            */
+            available -= i;
+            skipped += i;
+        }
+
+        public void RemoveData(byte[] buf, int off, int len, int skip)
+        {
+            Read(buf, off, len, skip);
+            RemoveData(skip + len);
+        }
+
+        public byte[] RemoveData(int len, int skip)
+        {
+            byte[] buf = new byte[len];
+            RemoveData(buf, 0, len, skip);
+            return buf;
+        }
+
+        /// <summary>The number of bytes which are available in this buffer.</summary>
+        public int Available
+        {
+            get { return available; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertChainType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertChainType.cs
new file mode 100644
index 0000000..cbb1834
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertChainType.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /*
+     * RFC 3546 3.3.
+     */
+    public abstract class CertChainType
+    {
+        public const byte individual_certs = 0;
+        public const byte pkipath = 1;
+
+        public static bool IsValid(byte certChainType)
+        {
+            return certChainType >= individual_certs && certChainType <= pkipath;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/Certificate.cs b/BouncyCastle.AxCrypt/src/crypto/tls/Certificate.cs
new file mode 100644
index 0000000..c59616c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/Certificate.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * Parsing and encoding of a <i>Certificate</i> struct from RFC 4346.
+     * <p/>
+     * <pre>
+     * opaque ASN.1Cert<2^24-1>;
+     *
+     * struct {
+     *     ASN.1Cert certificate_list<0..2^24-1>;
+     * } Certificate;
+     * </pre>
+     *
+     * @see Org.BouncyCastle.Asn1.X509.X509CertificateStructure
+     */
+    public class Certificate
+    {
+        public static readonly Certificate EmptyChain = new Certificate(new X509CertificateStructure[0]);
+
+        /**
+        * The certificates.
+        */
+        protected readonly X509CertificateStructure[] mCertificateList;
+
+        public Certificate(X509CertificateStructure[] certificateList)
+        {
+            if (certificateList == null)
+                throw new ArgumentNullException("certificateList");
+
+            this.mCertificateList = certificateList;
+        }
+
+        /**
+         * @return an array of {@link org.bouncycastle.asn1.x509.Certificate} representing a certificate
+         *         chain.
+         */
+        public virtual X509CertificateStructure[] GetCertificateList()
+        {
+            return CloneCertificateList();
+        }
+
+        public virtual X509CertificateStructure GetCertificateAt(int index)
+        {
+            return mCertificateList[index];
+        }
+
+        public virtual int Length
+        {
+            get { return mCertificateList.Length; }
+        }
+
+        /**
+         * @return <code>true</code> if this certificate chain contains no certificates, or
+         *         <code>false</code> otherwise.
+         */
+        public virtual bool IsEmpty
+        {
+            get { return mCertificateList.Length == 0; }
+        }
+
+        /**
+         * Encode this {@link Certificate} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            IList derEncodings = Platform.CreateArrayList(mCertificateList.Length);
+
+            int totalLength = 0;
+            foreach (Asn1Encodable asn1Cert in mCertificateList)
+            {
+                byte[] derEncoding = asn1Cert.GetEncoded(Asn1Encodable.Der);
+                derEncodings.Add(derEncoding);
+                totalLength += derEncoding.Length + 3;
+            }
+
+            TlsUtilities.CheckUint24(totalLength);
+            TlsUtilities.WriteUint24(totalLength, output);
+
+            foreach (byte[] derEncoding in derEncodings)
+            {
+                TlsUtilities.WriteOpaque24(derEncoding, output);
+            }
+        }
+
+        /**
+         * Parse a {@link Certificate} from a {@link Stream}.
+         *
+         * @param input the {@link Stream} to parse from.
+         * @return a {@link Certificate} object.
+         * @throws IOException
+         */
+        public static Certificate Parse(Stream input)
+        {
+            int totalLength = TlsUtilities.ReadUint24(input);
+            if (totalLength == 0)
+            {
+                return EmptyChain;
+            }
+
+            byte[] certListData = TlsUtilities.ReadFully(totalLength, input);
+
+            MemoryStream buf = new MemoryStream(certListData, false);
+
+            IList certificate_list = Platform.CreateArrayList();
+            while (buf.Position < buf.Length)
+            {
+                byte[] derEncoding = TlsUtilities.ReadOpaque24(buf);
+                Asn1Object asn1Cert = TlsUtilities.ReadDerObject(derEncoding);
+                certificate_list.Add(X509CertificateStructure.GetInstance(asn1Cert));
+            }
+
+            X509CertificateStructure[] certificateList = new X509CertificateStructure[certificate_list.Count];
+            for (int i = 0; i < certificate_list.Count; ++i)
+            {
+                certificateList[i] = (X509CertificateStructure)certificate_list[i];
+            }
+            return new Certificate(certificateList);
+        }
+
+        protected virtual X509CertificateStructure[] CloneCertificateList()
+        {
+            return (X509CertificateStructure[])mCertificateList.Clone();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertificateRequest.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateRequest.cs
new file mode 100644
index 0000000..f3dcb3b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateRequest.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * Parsing and encoding of a <i>CertificateRequest</i> struct from RFC 4346.
+     * <p/>
+     * <pre>
+     * struct {
+     *     ClientCertificateType certificate_types<1..2^8-1>;
+     *     DistinguishedName certificate_authorities<3..2^16-1>
+     * } CertificateRequest;
+     * </pre>
+     *
+     * @see ClientCertificateType
+     * @see X509Name
+     */
+    public class CertificateRequest
+    {
+        protected readonly byte[] mCertificateTypes;
+        protected readonly IList mSupportedSignatureAlgorithms;
+        protected readonly IList mCertificateAuthorities;
+
+        /**
+         * @param certificateTypes       see {@link ClientCertificateType} for valid constants.
+         * @param certificateAuthorities an {@link IList} of {@link X509Name}.
+         */
+        public CertificateRequest(byte[] certificateTypes, IList supportedSignatureAlgorithms,
+            IList certificateAuthorities)
+        {
+            this.mCertificateTypes = certificateTypes;
+            this.mSupportedSignatureAlgorithms = supportedSignatureAlgorithms;
+            this.mCertificateAuthorities = certificateAuthorities;
+        }
+
+        /**
+         * @return an array of certificate types
+         * @see {@link ClientCertificateType}
+         */
+        public virtual byte[] CertificateTypes
+        {
+            get { return mCertificateTypes; }
+        }
+
+        /**
+         * @return an {@link IList} of {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+         */
+        public virtual IList SupportedSignatureAlgorithms
+        {
+            get { return mSupportedSignatureAlgorithms; }
+        }
+
+        /**
+         * @return an {@link IList} of {@link X509Name}
+         */
+        public virtual IList CertificateAuthorities
+        {
+            get { return mCertificateAuthorities; }
+        }
+
+        /**
+         * Encode this {@link CertificateRequest} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            if (mCertificateTypes == null || mCertificateTypes.Length == 0)
+            {
+                TlsUtilities.WriteUint8(0, output);
+            }
+            else
+            {
+                TlsUtilities.WriteUint8ArrayWithUint8Length(mCertificateTypes, output);
+            }
+
+            if (mSupportedSignatureAlgorithms != null)
+            {
+                // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+                TlsUtilities.EncodeSupportedSignatureAlgorithms(mSupportedSignatureAlgorithms, false, output);
+            }
+
+            if (mCertificateAuthorities == null || mCertificateAuthorities.Count < 1)
+            {
+                TlsUtilities.WriteUint16(0, output);
+            }
+            else
+            {
+                IList derEncodings = Platform.CreateArrayList(mCertificateAuthorities.Count);
+
+                int totalLength = 0;
+                foreach (Asn1Encodable certificateAuthority in mCertificateAuthorities)
+                {
+                    byte[] derEncoding = certificateAuthority.GetEncoded(Asn1Encodable.Der);
+                    derEncodings.Add(derEncoding);
+                    totalLength += derEncoding.Length + 2;
+                }
+
+                TlsUtilities.CheckUint16(totalLength);
+                TlsUtilities.WriteUint16(totalLength, output);
+
+                foreach (byte[] derEncoding in derEncodings)
+                {
+                    TlsUtilities.WriteOpaque16(derEncoding, output);
+                }
+            }
+        }
+
+        /**
+         * Parse a {@link CertificateRequest} from a {@link Stream}.
+         * 
+         * @param context
+         *            the {@link TlsContext} of the current connection.
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link CertificateRequest} object.
+         * @throws IOException
+         */
+        public static CertificateRequest Parse(TlsContext context, Stream input)
+        {
+            int numTypes = TlsUtilities.ReadUint8(input);
+            byte[] certificateTypes = new byte[numTypes];
+            for (int i = 0; i < numTypes; ++i)
+            {
+                certificateTypes[i] = TlsUtilities.ReadUint8(input);
+            }
+
+            IList supportedSignatureAlgorithms = null;
+            if (TlsUtilities.IsTlsV12(context))
+            {
+                // TODO Check whether SignatureAlgorithm.anonymous is allowed here
+                supportedSignatureAlgorithms = TlsUtilities.ParseSupportedSignatureAlgorithms(false, input);
+            }
+
+            IList certificateAuthorities = Platform.CreateArrayList();
+            byte[] certAuthData = TlsUtilities.ReadOpaque16(input);
+            MemoryStream bis = new MemoryStream(certAuthData, false);
+            while (bis.Position < bis.Length)
+            {
+                byte[] derEncoding = TlsUtilities.ReadOpaque16(bis);
+                Asn1Object asn1 = TlsUtilities.ReadDerObject(derEncoding);
+                // TODO Switch to X500Name when available
+                certificateAuthorities.Add(X509Name.GetInstance(asn1));
+            }
+
+            return new CertificateRequest(certificateTypes, supportedSignatureAlgorithms, certificateAuthorities);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatus.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatus.cs
new file mode 100644
index 0000000..0f95475
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatus.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class CertificateStatus
+    {
+        protected readonly byte mStatusType;
+        protected readonly object mResponse;
+
+        public CertificateStatus(byte statusType, object response)
+        {
+            if (!IsCorrectType(statusType, response))
+                throw new ArgumentException("not an instance of the correct type", "response");
+
+            this.mStatusType = statusType;
+            this.mResponse = response;
+        }
+
+        public virtual byte StatusType
+        {
+            get { return mStatusType; }
+        }
+
+        public virtual object Response
+        {
+            get { return mResponse; }
+        }
+
+        public virtual OcspResponse GetOcspResponse()
+        {
+            if (!IsCorrectType(CertificateStatusType.ocsp, mResponse))
+                throw new InvalidOperationException("'response' is not an OcspResponse");
+
+            return (OcspResponse)mResponse;
+        }
+
+        /**
+         * Encode this {@link CertificateStatus} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(mStatusType, output);
+
+            switch (mStatusType)
+            {
+            case CertificateStatusType.ocsp:
+                byte[] derEncoding = ((OcspResponse)mResponse).GetEncoded(Asn1Encodable.Der);
+                TlsUtilities.WriteOpaque24(derEncoding, output);
+                break;
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        /**
+         * Parse a {@link CertificateStatus} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link CertificateStatus} object.
+         * @throws IOException
+         */
+        public static CertificateStatus Parse(Stream input)
+        {
+            byte status_type = TlsUtilities.ReadUint8(input);
+            object response;
+
+            switch (status_type)
+            {
+            case CertificateStatusType.ocsp:
+            {
+                byte[] derEncoding = TlsUtilities.ReadOpaque24(input);
+                response = OcspResponse.GetInstance(TlsUtilities.ReadDerObject(derEncoding));
+                break;
+            }
+            default:
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            }
+
+            return new CertificateStatus(status_type, response);
+        }
+
+        protected static bool IsCorrectType(byte statusType, object response)
+        {
+            switch (statusType)
+            {
+            case CertificateStatusType.ocsp:
+                return response is OcspResponse;
+            default:
+                throw new ArgumentException("unsupported value", "statusType");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusRequest.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusRequest.cs
new file mode 100644
index 0000000..9587d7d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusRequest.cs
@@ -0,0 +1,95 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class CertificateStatusRequest
+    {
+        protected readonly byte mStatusType;
+        protected readonly object mRequest;
+
+        public CertificateStatusRequest(byte statusType, Object request)
+        {
+            if (!IsCorrectType(statusType, request))
+                throw new ArgumentException("not an instance of the correct type", "request");
+
+            this.mStatusType = statusType;
+            this.mRequest = request;
+        }
+
+        public virtual byte StatusType
+        {
+            get { return mStatusType; }
+        }
+
+        public virtual object Request
+        {
+            get { return mRequest; }
+        }
+
+        public virtual OcspStatusRequest GetOcspStatusRequest()
+        {
+            if (!IsCorrectType(CertificateStatusType.ocsp, mRequest))
+                throw new InvalidOperationException("'request' is not an OCSPStatusRequest");
+
+            return (OcspStatusRequest)mRequest;
+        }
+
+        /**
+         * Encode this {@link CertificateStatusRequest} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(mStatusType, output);
+
+            switch (mStatusType)
+            {
+            case CertificateStatusType.ocsp:
+                ((OcspStatusRequest)mRequest).Encode(output);
+                break;
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        /**
+         * Parse a {@link CertificateStatusRequest} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link CertificateStatusRequest} object.
+         * @throws IOException
+         */
+        public static CertificateStatusRequest Parse(Stream input)
+        {
+            byte status_type = TlsUtilities.ReadUint8(input);
+            object result;
+
+            switch (status_type)
+            {
+            case CertificateStatusType.ocsp:
+                result = OcspStatusRequest.Parse(input);
+                break;
+            default:
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            }
+
+            return new CertificateStatusRequest(status_type, result);
+        }
+
+        protected static bool IsCorrectType(byte statusType, object request)
+        {
+            switch (statusType)
+            {
+            case CertificateStatusType.ocsp:
+                return request is OcspStatusRequest;
+            default:
+                throw new ArgumentException("unsupported value", "statusType");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusType.cs
new file mode 100644
index 0000000..54b741b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateStatusType.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class CertificateStatusType
+    {
+        /*
+         *  RFC 3546 3.6
+         */
+        public const byte ocsp = 1;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CertificateUrl.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateUrl.cs
new file mode 100644
index 0000000..b511211
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CertificateUrl.cs
@@ -0,0 +1,124 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /*
+     * RFC 3546 3.3
+     */
+    public class CertificateUrl
+    {
+        protected readonly byte mType;
+        protected readonly IList mUrlAndHashList;
+
+        /**
+         * @param type
+         *            see {@link CertChainType} for valid constants.
+         * @param urlAndHashList
+         *            a {@link IList} of {@link UrlAndHash}.
+         */
+        public CertificateUrl(byte type, IList urlAndHashList)
+        {
+            if (!CertChainType.IsValid(type))
+                throw new ArgumentException("not a valid CertChainType value", "type");
+            if (urlAndHashList == null || urlAndHashList.Count < 1)
+                throw new ArgumentException("must have length > 0", "urlAndHashList");
+
+            this.mType = type;
+            this.mUrlAndHashList = urlAndHashList;
+        }
+
+        /**
+         * @return {@link CertChainType}
+         */
+        public virtual byte Type
+        {
+            get { return mType; }
+        }
+
+        /**
+         * @return an {@link IList} of {@link UrlAndHash} 
+         */
+        public virtual IList UrlAndHashList
+        {
+            get { return mUrlAndHashList; }
+        }
+
+        /**
+         * Encode this {@link CertificateUrl} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(this.mType, output);
+
+            ListBuffer16 buf = new ListBuffer16();
+            foreach (UrlAndHash urlAndHash in this.mUrlAndHashList)
+            {
+                urlAndHash.Encode(buf);
+            }
+            buf.EncodeTo(output);
+        }
+
+        /**
+         * Parse a {@link CertificateUrl} from a {@link Stream}.
+         * 
+         * @param context
+         *            the {@link TlsContext} of the current connection.
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link CertificateUrl} object.
+         * @throws IOException
+         */
+        public static CertificateUrl parse(TlsContext context, Stream input)
+        {
+            byte type = TlsUtilities.ReadUint8(input);
+            if (!CertChainType.IsValid(type))
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int totalLength = TlsUtilities.ReadUint16(input);
+            if (totalLength < 1)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            byte[] urlAndHashListData = TlsUtilities.ReadFully(totalLength, input);
+
+            MemoryStream buf = new MemoryStream(urlAndHashListData, false);
+
+            IList url_and_hash_list = Platform.CreateArrayList();
+            while (buf.Position < buf.Length)
+            {
+                UrlAndHash url_and_hash = UrlAndHash.Parse(context, buf);
+                url_and_hash_list.Add(url_and_hash);
+            }
+
+            return new CertificateUrl(type, url_and_hash_list);
+        }
+
+        // TODO Could be more generally useful
+        internal class ListBuffer16
+            : MemoryStream
+        {
+            internal ListBuffer16()
+            {
+                // Reserve space for length
+                TlsUtilities.WriteUint16(0,  this);
+            }
+
+            internal void EncodeTo(Stream output)
+            {
+                // Patch actual length back in
+                long length = Length - 2;
+                TlsUtilities.CheckUint16(length);
+                this.Position = 0;
+                TlsUtilities.WriteUint16((int)length, this);
+                this.WriteTo(output);
+                this.Dispose();
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/Chacha20Poly1305.cs b/BouncyCastle.AxCrypt/src/crypto/tls/Chacha20Poly1305.cs
new file mode 100644
index 0000000..e4e4c7e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/Chacha20Poly1305.cs
@@ -0,0 +1,153 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class Chacha20Poly1305
+        :   TlsCipher
+    {
+        protected readonly TlsContext context;
+
+        protected readonly ChaChaEngine encryptCipher;
+        protected readonly ChaChaEngine decryptCipher;
+
+        /// <exception cref="IOException"></exception>
+        public Chacha20Poly1305(TlsContext context)
+        {
+            if (!TlsUtilities.IsTlsV12(context))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.context = context;
+
+            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, 64);
+
+            KeyParameter client_write_key = new KeyParameter(key_block, 0, 32);
+            KeyParameter server_write_key = new KeyParameter(key_block, 32, 32);
+
+            this.encryptCipher = new ChaChaEngine(20);
+            this.decryptCipher = new ChaChaEngine(20);
+
+            KeyParameter encryptKey, decryptKey;
+            if (context.IsServer)
+            {
+                encryptKey = server_write_key;
+                decryptKey = client_write_key;
+            }
+            else
+            {
+                encryptKey = client_write_key;
+                decryptKey = server_write_key;
+            }
+
+            byte[] dummyNonce = new byte[8];
+
+            this.encryptCipher.Init(true, new ParametersWithIV(encryptKey, dummyNonce));
+            this.decryptCipher.Init(false, new ParametersWithIV(decryptKey, dummyNonce));
+        }
+
+        public virtual int GetPlaintextLimit(int ciphertextLimit)
+        {
+            return ciphertextLimit - 16;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
+        {
+            int ciphertextLength = len + 16;
+
+            KeyParameter macKey = InitRecordMac(encryptCipher, true, seqNo);
+
+            byte[] output = new byte[ciphertextLength];
+            encryptCipher.ProcessBytes(plaintext, offset, len, output, 0);
+
+            byte[] additionalData = GetAdditionalData(seqNo, type, len);
+            byte[] mac = CalculateRecordMac(macKey, additionalData, output, 0, len);
+            Array.Copy(mac, 0, output, len, mac.Length);
+
+            return output;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
+        {
+            if (GetPlaintextLimit(len) < 0)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int plaintextLength = len - 16;
+
+            byte[] receivedMAC = Arrays.CopyOfRange(ciphertext, offset + plaintextLength, offset + len);
+
+            KeyParameter macKey = InitRecordMac(decryptCipher, false, seqNo);
+
+            byte[] additionalData = GetAdditionalData(seqNo, type, plaintextLength);
+            byte[] calculatedMAC = CalculateRecordMac(macKey, additionalData, ciphertext, offset, plaintextLength);
+
+            if (!Arrays.ConstantTimeAreEqual(calculatedMAC, receivedMAC))
+                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+
+            byte[] output = new byte[plaintextLength];
+            decryptCipher.ProcessBytes(ciphertext, offset, plaintextLength, output, 0);
+
+            return output;
+        }
+
+        protected virtual KeyParameter InitRecordMac(ChaChaEngine cipher, bool forEncryption, long seqNo)
+        {
+            byte[] nonce = new byte[8];
+            TlsUtilities.WriteUint64(seqNo, nonce, 0);
+
+            cipher.Init(forEncryption, new ParametersWithIV(null, nonce));
+
+            byte[] firstBlock = new byte[64];
+            cipher.ProcessBytes(firstBlock, 0, firstBlock.Length, firstBlock, 0);
+
+            // NOTE: The BC implementation puts 'r' after 'k'
+            Array.Copy(firstBlock, 0, firstBlock, 32, 16);
+            KeyParameter macKey = new KeyParameter(firstBlock, 16, 32);
+            Poly1305KeyGenerator.Clamp(macKey.GetKey());
+            return macKey;
+        }
+
+        protected virtual byte[] CalculateRecordMac(KeyParameter macKey, byte[] additionalData, byte[] buf, int off, int len)
+        {
+            IMac mac = new Poly1305();
+            mac.Init(macKey);
+
+            UpdateRecordMac(mac, additionalData, 0, additionalData.Length);
+            UpdateRecordMac(mac, buf, off, len);
+            return MacUtilities.DoFinal(mac);
+        }
+
+        protected virtual void UpdateRecordMac(IMac mac, byte[] buf, int off, int len)
+        {
+            mac.BlockUpdate(buf, off, len);
+
+            byte[] longLen = Pack.UInt64_To_LE((ulong)len);
+            mac.BlockUpdate(longLen, 0, longLen.Length);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual byte[] GetAdditionalData(long seqNo, byte type, int len)
+        {
+            /*
+             * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
+             * TLSCompressed.length
+             */
+            byte[] additional_data = new byte[13];
+            TlsUtilities.WriteUint64(seqNo, additional_data, 0);
+            TlsUtilities.WriteUint8(type, additional_data, 8);
+            TlsUtilities.WriteVersion(context.ServerVersion, additional_data, 9);
+            TlsUtilities.WriteUint16(len, additional_data, 11);
+
+            return additional_data;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ChangeCipherSpec.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ChangeCipherSpec.cs
new file mode 100644
index 0000000..323de91
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ChangeCipherSpec.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class ChangeCipherSpec
+    {
+        public const byte change_cipher_spec = 1;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CipherSuite.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CipherSuite.cs
new file mode 100644
index 0000000..f034ab8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CipherSuite.cs
@@ -0,0 +1,352 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 2246 A.5
+    /// </summary>
+    public abstract class CipherSuite
+    {
+        public const int TLS_NULL_WITH_NULL_NULL = 0x0000;
+        public const int TLS_RSA_WITH_NULL_MD5 = 0x0001;
+        public const int TLS_RSA_WITH_NULL_SHA = 0x0002;
+        public const int TLS_RSA_EXPORT_WITH_RC4_40_MD5 = 0x0003;
+        public const int TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
+        public const int TLS_RSA_WITH_RC4_128_SHA = 0x0005;
+        public const int TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 = 0x0006;
+        public const int TLS_RSA_WITH_IDEA_CBC_SHA = 0x0007;
+        public const int TLS_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0008;
+        public const int TLS_RSA_WITH_DES_CBC_SHA = 0x0009;
+        public const int TLS_RSA_WITH_3DES_EDE_CBC_SHA = 0x000A;
+        public const int TLS_DH_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x000B;
+        public const int TLS_DH_DSS_WITH_DES_CBC_SHA = 0x000C;
+        public const int TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA = 0x000D;
+        public const int TLS_DH_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x000E;
+        public const int TLS_DH_RSA_WITH_DES_CBC_SHA = 0x000F;
+        public const int TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0010;
+        public const int TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA = 0x0011;
+        public const int TLS_DHE_DSS_WITH_DES_CBC_SHA = 0x0012;
+        public const int TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA = 0x0013;
+        public const int TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA = 0x0014;
+        public const int TLS_DHE_RSA_WITH_DES_CBC_SHA = 0x0015;
+        public const int TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x0016;
+        public const int TLS_DH_anon_EXPORT_WITH_RC4_40_MD5 = 0x0017;
+        public const int TLS_DH_anon_WITH_RC4_128_MD5 = 0x0018;
+        public const int TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA = 0x0019;
+        public const int TLS_DH_anon_WITH_DES_CBC_SHA = 0x001A;
+        public const int TLS_DH_anon_WITH_3DES_EDE_CBC_SHA = 0x001B;
+
+        /*
+         * Note: The cipher suite values { 0x00, 0x1C } and { 0x00, 0x1D } are reserved to avoid
+         * collision with Fortezza-based cipher suites in SSL 3.
+         */
+
+        /*
+         * RFC 3268
+         */
+        public const int TLS_RSA_WITH_AES_128_CBC_SHA = 0x002F;
+        public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA = 0x0030;
+        public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA = 0x0031;
+        public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA = 0x0032;
+        public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x0033;
+        public const int TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x0034;
+        public const int TLS_RSA_WITH_AES_256_CBC_SHA = 0x0035;
+        public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA = 0x0036;
+        public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA = 0x0037;
+        public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA = 0x0038;
+        public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x0039;
+        public const int TLS_DH_anon_WITH_AES_256_CBC_SHA = 0x003A;
+
+        /*
+         * RFC 5932
+         */
+        public const int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0041;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0042;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0043;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA = 0x0044;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x0045;
+        public const int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA = 0x0046;
+
+        public const int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0084;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0085;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0086;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA = 0x0087;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x0088;
+        public const int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA = 0x0089;
+
+        public const int TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BA;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BB;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BC;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BD;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BE;
+        public const int TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 = 0x00BF;
+
+        public const int TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C0;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C1;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C2;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C3;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C4;
+        public const int TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 = 0x00C5;
+
+        /*
+         * RFC 4162
+         */
+        public const int TLS_RSA_WITH_SEED_CBC_SHA = 0x0096;
+        public const int TLS_DH_DSS_WITH_SEED_CBC_SHA = 0x0097;
+        public const int TLS_DH_RSA_WITH_SEED_CBC_SHA = 0x0098;
+        public const int TLS_DHE_DSS_WITH_SEED_CBC_SHA = 0x0099;
+        public const int TLS_DHE_RSA_WITH_SEED_CBC_SHA = 0x009A;
+        public const int TLS_DH_anon_WITH_SEED_CBC_SHA = 0x009B;
+
+        /*
+         * RFC 4279
+         */
+        public const int TLS_PSK_WITH_RC4_128_SHA = 0x008A;
+        public const int TLS_PSK_WITH_3DES_EDE_CBC_SHA = 0x008B;
+        public const int TLS_PSK_WITH_AES_128_CBC_SHA = 0x008C;
+        public const int TLS_PSK_WITH_AES_256_CBC_SHA = 0x008D;
+        public const int TLS_DHE_PSK_WITH_RC4_128_SHA = 0x008E;
+        public const int TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA = 0x008F;
+        public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA = 0x0090;
+        public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA = 0x0091;
+        public const int TLS_RSA_PSK_WITH_RC4_128_SHA = 0x0092;
+        public const int TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA = 0x0093;
+        public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA = 0x0094;
+        public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA = 0x0095;
+
+        /*
+         * RFC 4492
+         */
+        public const int TLS_ECDH_ECDSA_WITH_NULL_SHA = 0xC001;
+        public const int TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0xC002;
+        public const int TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC003;
+        public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0xC004;
+        public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0xC005;
+        public const int TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0xC006;
+        public const int TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
+        public const int TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0xC008;
+        public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0xC009;
+        public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0xC00A;
+        public const int TLS_ECDH_RSA_WITH_NULL_SHA = 0xC00B;
+        public const int TLS_ECDH_RSA_WITH_RC4_128_SHA = 0xC00C;
+        public const int TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0xC00D;
+        public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0xC00E;
+        public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0xC00F;
+        public const int TLS_ECDHE_RSA_WITH_NULL_SHA = 0xC010;
+        public const int TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
+        public const int TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0xC012;
+        public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0xC013;
+        public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0xC014;
+        public const int TLS_ECDH_anon_WITH_NULL_SHA = 0xC015;
+        public const int TLS_ECDH_anon_WITH_RC4_128_SHA = 0xC016;
+        public const int TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA = 0xC017;
+        public const int TLS_ECDH_anon_WITH_AES_128_CBC_SHA = 0xC018;
+        public const int TLS_ECDH_anon_WITH_AES_256_CBC_SHA = 0xC019;
+
+        /*
+         * RFC 4785
+         */
+        public const int TLS_PSK_WITH_NULL_SHA = 0x002C;
+        public const int TLS_DHE_PSK_WITH_NULL_SHA = 0x002D;
+        public const int TLS_RSA_PSK_WITH_NULL_SHA = 0x002E;
+
+        /*
+         * RFC 5054
+         */
+        public const int TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA = 0xC01A;
+        public const int TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA = 0xC01B;
+        public const int TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA = 0xC01C;
+        public const int TLS_SRP_SHA_WITH_AES_128_CBC_SHA = 0xC01D;
+        public const int TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA = 0xC01E;
+        public const int TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA = 0xC01F;
+        public const int TLS_SRP_SHA_WITH_AES_256_CBC_SHA = 0xC020;
+        public const int TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA = 0xC021;
+        public const int TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA = 0xC022;
+
+        /*
+         * RFC 5246
+         */
+        public const int TLS_RSA_WITH_NULL_SHA256 = 0x003B;
+        public const int TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x003C;
+        public const int TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x003D;
+        public const int TLS_DH_DSS_WITH_AES_128_CBC_SHA256 = 0x003E;
+        public const int TLS_DH_RSA_WITH_AES_128_CBC_SHA256 = 0x003F;
+        public const int TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 = 0x0040;
+        public const int TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x0067;
+        public const int TLS_DH_DSS_WITH_AES_256_CBC_SHA256 = 0x0068;
+        public const int TLS_DH_RSA_WITH_AES_256_CBC_SHA256 = 0x0069;
+        public const int TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 = 0x006A;
+        public const int TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x006B;
+        public const int TLS_DH_anon_WITH_AES_128_CBC_SHA256 = 0x006C;
+        public const int TLS_DH_anon_WITH_AES_256_CBC_SHA256 = 0x006D;
+
+        /*
+         * RFC 5288
+         */
+        public const int TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x009C;
+        public const int TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x009D;
+        public const int TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x009E;
+        public const int TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x009F;
+        public const int TLS_DH_RSA_WITH_AES_128_GCM_SHA256 = 0x00A0;
+        public const int TLS_DH_RSA_WITH_AES_256_GCM_SHA384 = 0x00A1;
+        public const int TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 = 0x00A2;
+        public const int TLS_DHE_DSS_WITH_AES_256_GCM_SHA384 = 0x00A3;
+        public const int TLS_DH_DSS_WITH_AES_128_GCM_SHA256 = 0x00A4;
+        public const int TLS_DH_DSS_WITH_AES_256_GCM_SHA384 = 0x00A5;
+        public const int TLS_DH_anon_WITH_AES_128_GCM_SHA256 = 0x00A6;
+        public const int TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0x00A7;
+
+        /*
+         * RFC 5289
+         */
+        public const int TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC023;
+        public const int TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC024;
+        public const int TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0xC025;
+        public const int TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0xC026;
+        public const int TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0xC027;
+        public const int TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0xC028;
+        public const int TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0xC029;
+        public const int TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0xC02A;
+        public const int TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02B;
+        public const int TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02C;
+        public const int TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0xC02D;
+        public const int TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0xC02E;
+        public const int TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0xC02F;
+        public const int TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0xC030;
+        public const int TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0xC031;
+        public const int TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0xC032;
+
+        /*
+         * RFC 5487
+         */
+        public const int TLS_PSK_WITH_AES_128_GCM_SHA256 = 0x00A8;
+        public const int TLS_PSK_WITH_AES_256_GCM_SHA384 = 0x00A9;
+        public const int TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0x00AA;
+        public const int TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0x00AB;
+        public const int TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 = 0x00AC;
+        public const int TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 = 0x00AD;
+        public const int TLS_PSK_WITH_AES_128_CBC_SHA256 = 0x00AE;
+        public const int TLS_PSK_WITH_AES_256_CBC_SHA384 = 0x00AF;
+        public const int TLS_PSK_WITH_NULL_SHA256 = 0x00B0;
+        public const int TLS_PSK_WITH_NULL_SHA384 = 0x00B1;
+        public const int TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0x00B2;
+        public const int TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0x00B3;
+        public const int TLS_DHE_PSK_WITH_NULL_SHA256 = 0x00B4;
+        public const int TLS_DHE_PSK_WITH_NULL_SHA384 = 0x00B5;
+        public const int TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 = 0x00B6;
+        public const int TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 = 0x00B7;
+        public const int TLS_RSA_PSK_WITH_NULL_SHA256 = 0x00B8;
+        public const int TLS_RSA_PSK_WITH_NULL_SHA384 = 0x00B9;
+
+        /*
+         * RFC 5489
+         */
+        public const int TLS_ECDHE_PSK_WITH_RC4_128_SHA = 0xC033;
+        public const int TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA = 0xC034;
+        public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA = 0xC035;
+        public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA = 0xC036;
+        public const int TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0xC037;
+        public const int TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 = 0xC038;
+        public const int TLS_ECDHE_PSK_WITH_NULL_SHA = 0xC039;
+        public const int TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0xC03A;
+        public const int TLS_ECDHE_PSK_WITH_NULL_SHA384 = 0xC03B;
+
+        /*
+         * RFC 5746
+         */
+        public const int TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF;
+
+        /*
+         * RFC 6367
+         */
+        public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC072;
+        public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC073;
+        public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC074;
+        public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC075;
+        public const int TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC076;
+        public const int TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC077;
+        public const int TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xC078;
+        public const int TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 = 0xC079;
+
+        public const int TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07A;
+        public const int TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07B;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07C;
+        public const int TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07D;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC07E;
+        public const int TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC07F;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC080;
+        public const int TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC081;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256 = 0xC082;
+        public const int TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384 = 0xC083;
+        public const int TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256 = 0xC084;
+        public const int TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384 = 0xC085;
+        public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC086;
+        public const int TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC087;
+        public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC088;
+        public const int TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC089;
+        public const int TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08A;
+        public const int TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08B;
+        public const int TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08C;
+        public const int TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08D;
+
+        public const int TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC08E;
+        public const int TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC08F;
+        public const int TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC090;
+        public const int TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC091;
+        public const int TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 = 0xC092;
+        public const int TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 = 0xC093;
+        public const int TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC094;
+        public const int TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC095;
+        public const int TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC096;
+        public const int TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC097;
+        public const int TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC098;
+        public const int TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC099;
+        public const int TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 = 0xC09A;
+        public const int TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 = 0xC09B;
+
+        /*
+         * RFC 6655
+         */
+        public const int TLS_RSA_WITH_AES_128_CCM = 0xC09C;
+        public const int TLS_RSA_WITH_AES_256_CCM = 0xC09D;
+        public const int TLS_DHE_RSA_WITH_AES_128_CCM = 0xC09E;
+        public const int TLS_DHE_RSA_WITH_AES_256_CCM = 0xC09F;
+        public const int TLS_RSA_WITH_AES_128_CCM_8 = 0xC0A0;
+        public const int TLS_RSA_WITH_AES_256_CCM_8 = 0xC0A1;
+        public const int TLS_DHE_RSA_WITH_AES_128_CCM_8 = 0xC0A2;
+        public const int TLS_DHE_RSA_WITH_AES_256_CCM_8 = 0xC0A3;
+        public const int TLS_PSK_WITH_AES_128_CCM = 0xC0A4;
+        public const int TLS_PSK_WITH_AES_256_CCM = 0xC0A5;
+        public const int TLS_DHE_PSK_WITH_AES_128_CCM = 0xC0A6;
+        public const int TLS_DHE_PSK_WITH_AES_256_CCM = 0xC0A7;
+        public const int TLS_PSK_WITH_AES_128_CCM_8 = 0xC0A8;
+        public const int TLS_PSK_WITH_AES_256_CCM_8 = 0xC0A9;
+        public const int TLS_PSK_DHE_WITH_AES_128_CCM_8 = 0xC0AA;
+        public const int TLS_PSK_DHE_WITH_AES_256_CCM_8 = 0xC0AB;
+
+        /*
+         * draft-agl-tls-chacha20poly1305-04
+         */
+        public const int TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC13;
+        public const int TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC14;
+        public const int TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xCC15;
+
+        /*
+         * draft-josefsson-salsa20-tls-04
+         */
+        public const int TLS_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE410;
+        public const int TLS_RSA_WITH_SALSA20_SHA1 = 0xE411;
+        public const int TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE412;
+        public const int TLS_ECDHE_RSA_WITH_SALSA20_SHA1 = 0xE413;
+        public const int TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE414;
+        public const int TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1 = 0xE415;
+        public const int TLS_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE416;
+        public const int TLS_PSK_WITH_SALSA20_SHA1 = 0xE417;
+        public const int TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE418;
+        public const int TLS_ECDHE_PSK_WITH_SALSA20_SHA1 = 0xE419;
+        public const int TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41A;
+        public const int TLS_RSA_PSK_WITH_SALSA20_SHA1 = 0xE41B;
+        public const int TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1 = 0xE41C;
+        public const int TLS_DHE_PSK_WITH_SALSA20_SHA1 = 0xE41D;
+        public const int TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1 = 0xE41E;
+        public const int TLS_DHE_RSA_WITH_SALSA20_SHA1 = 0xE41F;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CipherType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CipherType.cs
new file mode 100644
index 0000000..b2ad7d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CipherType.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class CipherType
+    {
+        public const int stream = 0;
+        public const int block = 1;
+
+        /*
+         * RFC 5246
+         */
+        public const int aead = 2;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ClientAuthenticationType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ClientAuthenticationType.cs
new file mode 100644
index 0000000..dd248f3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ClientAuthenticationType.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class ClientAuthenticationType
+    {
+        /*
+         * RFC 5077 4
+         */
+        public const byte anonymous = 0;
+        public const byte certificate_based = 1;
+        public const byte psk = 2;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ClientCertificateType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ClientCertificateType.cs
new file mode 100644
index 0000000..a291a46
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ClientCertificateType.cs
@@ -0,0 +1,23 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class ClientCertificateType
+    {
+        /*
+         *  RFC 4346 7.4.4
+         */
+        public const byte rsa_sign = 1;
+        public const byte dss_sign = 2;
+        public const byte rsa_fixed_dh = 3;
+        public const byte dss_fixed_dh = 4;
+        public const byte rsa_ephemeral_dh_RESERVED = 5;
+        public const byte dss_ephemeral_dh_RESERVED = 6;
+        public const byte fortezza_dms_RESERVED = 20;
+
+        /*
+        * RFC 4492 5.5
+        */
+        public const byte ecdsa_sign = 64;
+        public const byte rsa_fixed_ecdh = 65;
+        public const byte ecdsa_fixed_ecdh = 66;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CombinedHash.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CombinedHash.cs
new file mode 100644
index 0000000..74a52d5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CombinedHash.cs
@@ -0,0 +1,133 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * A combined hash, which implements md5(m) || sha1(m).
+     */
+    internal class CombinedHash
+        :   TlsHandshakeHash
+    {
+        protected TlsContext mContext;
+        protected IDigest mMd5;
+        protected IDigest mSha1;
+
+        internal CombinedHash()
+        {
+            this.mMd5 = TlsUtilities.CreateHash(HashAlgorithm.md5);
+            this.mSha1 = TlsUtilities.CreateHash(HashAlgorithm.sha1);
+        }
+
+        internal CombinedHash(CombinedHash t)
+        {
+            this.mContext = t.mContext;
+            this.mMd5 = TlsUtilities.CloneHash(HashAlgorithm.md5, t.mMd5);
+            this.mSha1 = TlsUtilities.CloneHash(HashAlgorithm.sha1, t.mSha1);
+        }
+
+        public virtual void Init(TlsContext context)
+        {
+            this.mContext = context;
+        }
+
+        public virtual TlsHandshakeHash NotifyPrfDetermined()
+        {
+            return this;
+        }
+
+        public virtual void TrackHashAlgorithm(byte hashAlgorithm)
+        {
+            throw new InvalidOperationException("CombinedHash only supports calculating the legacy PRF for handshake hash");
+        }
+
+        public virtual void SealHashAlgorithms()
+        {
+        }
+
+        public virtual TlsHandshakeHash StopTracking()
+        {
+            return new CombinedHash(this);
+        }
+
+        public virtual IDigest ForkPrfHash()
+        {
+            return new CombinedHash(this);
+        }
+
+        public virtual byte[] GetFinalHash(byte hashAlgorithm)
+        {
+            throw new InvalidOperationException("CombinedHash doesn't support multiple hashes");
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return mMd5.AlgorithmName + " and " + mSha1.AlgorithmName; }
+        }
+
+        public virtual int GetByteLength()
+        {
+            return System.Math.Max(mMd5.GetByteLength(), mSha1.GetByteLength());
+        }
+
+        public virtual int GetDigestSize()
+        {
+            return mMd5.GetDigestSize() + mSha1.GetDigestSize();
+        }
+
+        public virtual void Update(byte input)
+        {
+            mMd5.Update(input);
+            mSha1.Update(input);
+        }
+
+        /**
+         * @see org.bouncycastle.crypto.Digest#update(byte[], int, int)
+         */
+        public virtual void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            mMd5.BlockUpdate(input, inOff, len);
+            mSha1.BlockUpdate(input, inOff, len);
+        }
+
+        /**
+         * @see org.bouncycastle.crypto.Digest#doFinal(byte[], int)
+         */
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            if (mContext != null && TlsUtilities.IsSsl(mContext))
+            {
+                Ssl3Complete(mMd5, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 48);
+                Ssl3Complete(mSha1, Ssl3Mac.IPAD, Ssl3Mac.OPAD, 40);
+            }
+
+            int i1 = mMd5.DoFinal(output, outOff);
+            int i2 = mSha1.DoFinal(output, outOff + i1);
+            return i1 + i2;
+        }
+
+        /**
+         * @see org.bouncycastle.crypto.Digest#reset()
+         */
+        public virtual void Reset()
+        {
+            mMd5.Reset();
+            mSha1.Reset();
+        }
+
+        protected virtual void Ssl3Complete(IDigest d, byte[] ipad, byte[] opad, int padLength)
+        {
+            byte[] master_secret = mContext.SecurityParameters.masterSecret;
+
+            d.BlockUpdate(master_secret, 0, master_secret.Length);
+            d.BlockUpdate(ipad, 0, padLength);
+
+            byte[] tmp = DigestUtilities.DoFinal(d);
+
+            d.BlockUpdate(master_secret, 0, master_secret.Length);
+            d.BlockUpdate(opad, 0, padLength);
+            d.BlockUpdate(tmp, 0, tmp.Length);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/CompressionMethod.cs b/BouncyCastle.AxCrypt/src/crypto/tls/CompressionMethod.cs
new file mode 100644
index 0000000..89c1f5f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/CompressionMethod.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 2246 6.1
+    /// </summary>
+    public abstract class CompressionMethod
+    {
+        public const byte cls_null = 0;
+
+        /*
+         * RFC 3749 2
+         */
+        public const byte DEFLATE = 1;
+
+        /*
+         * Values from 224 decimal (0xE0) through 255 decimal (0xFF)
+         * inclusive are reserved for private use.
+         */
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ConnectionEnd.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ConnectionEnd.cs
new file mode 100644
index 0000000..afc9460
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ConnectionEnd.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class ConnectionEnd
+    {
+        public const int server = 0;
+        public const int client = 1;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ContentType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ContentType.cs
new file mode 100644
index 0000000..d6ab438
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ContentType.cs
@@ -0,0 +1,14 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 2246 6.2.1
+     */
+    public abstract class ContentType
+    {
+        public const byte change_cipher_spec = 20;
+        public const byte alert = 21;
+        public const byte handshake = 22;
+        public const byte application_data = 23;
+        public const byte heartbeat = 24;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsAgreementCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsAgreementCredentials.cs
new file mode 100644
index 0000000..5147a19
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsAgreementCredentials.cs
@@ -0,0 +1,69 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsAgreementCredentials
+        : AbstractTlsAgreementCredentials
+    {
+        protected readonly Certificate mCertificate;
+        protected readonly AsymmetricKeyParameter mPrivateKey;
+
+        protected readonly IBasicAgreement mBasicAgreement;
+        protected readonly bool mTruncateAgreement;
+
+        public DefaultTlsAgreementCredentials(Certificate certificate, AsymmetricKeyParameter privateKey)
+        {
+            if (certificate == null)
+                throw new ArgumentNullException("certificate");
+            if (certificate.IsEmpty)
+                throw new ArgumentException("cannot be empty", "certificate");
+            if (privateKey == null)
+                throw new ArgumentNullException("privateKey");
+            if (!privateKey.IsPrivate)
+                throw new ArgumentException("must be private", "privateKey");
+
+            if (privateKey is DHPrivateKeyParameters)
+            {
+                mBasicAgreement = new DHBasicAgreement();
+                mTruncateAgreement = true;
+            }
+            else if (privateKey is ECPrivateKeyParameters)
+            {
+                mBasicAgreement = new ECDHBasicAgreement();
+                mTruncateAgreement = false;
+            }
+            else
+            {
+                throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
+            }
+
+            this.mCertificate = certificate;
+            this.mPrivateKey = privateKey;
+        }
+
+        public override Certificate Certificate
+        {
+            get { return mCertificate; }
+        }
+
+        /// <exception cref="IOException"></exception>
+        public override byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey)
+        {
+            mBasicAgreement.Init(mPrivateKey);
+            BigInteger agreementValue = mBasicAgreement.CalculateAgreement(peerPublicKey);
+
+            if (mTruncateAgreement)
+            {
+                return BigIntegers.AsUnsignedByteArray(agreementValue);
+            }
+
+            return BigIntegers.AsUnsignedByteArray(mBasicAgreement.GetFieldSize(), agreementValue);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsCipherFactory.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsCipherFactory.cs
new file mode 100644
index 0000000..7c4213c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsCipherFactory.cs
@@ -0,0 +1,225 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsCipherFactory
+        :   AbstractTlsCipherFactory
+    {
+        /// <exception cref="IOException"></exception>
+        public override TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm)
+        {
+            switch (encryptionAlgorithm)
+            {
+            case EncryptionAlgorithm.cls_3DES_EDE_CBC:
+                return CreateDesEdeCipher(context, macAlgorithm);
+            case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
+                // NOTE: Ignores macAlgorithm
+                return CreateChaCha20Poly1305(context);
+            case EncryptionAlgorithm.AES_128_CBC:
+                return CreateAESCipher(context, 16, macAlgorithm);
+            case EncryptionAlgorithm.AES_128_CCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Ccm(context, 16, 16);
+            case EncryptionAlgorithm.AES_128_CCM_8:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Ccm(context, 16, 8);
+            case EncryptionAlgorithm.AES_256_CCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Ccm(context, 32, 16);
+            case EncryptionAlgorithm.AES_256_CCM_8:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Ccm(context, 32, 8);
+            case EncryptionAlgorithm.AES_128_GCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Gcm(context, 16, 16);
+            case EncryptionAlgorithm.AES_256_CBC:
+                return CreateAESCipher(context, 32, macAlgorithm);
+            case EncryptionAlgorithm.AES_256_GCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Aes_Gcm(context, 32, 16);
+            case EncryptionAlgorithm.CAMELLIA_128_CBC:
+                return CreateCamelliaCipher(context, 16, macAlgorithm);
+            case EncryptionAlgorithm.CAMELLIA_128_GCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Camellia_Gcm(context, 16, 16);
+            case EncryptionAlgorithm.CAMELLIA_256_CBC:
+                return CreateCamelliaCipher(context, 32, macAlgorithm);
+            case EncryptionAlgorithm.CAMELLIA_256_GCM:
+                // NOTE: Ignores macAlgorithm
+                return CreateCipher_Camellia_Gcm(context, 32, 16);
+            case EncryptionAlgorithm.ESTREAM_SALSA20:
+                return CreateSalsa20Cipher(context, 12, 32, macAlgorithm);
+            case EncryptionAlgorithm.NULL:
+                return CreateNullCipher(context, macAlgorithm);
+            case EncryptionAlgorithm.RC4_128:
+                return CreateRC4Cipher(context, 16, macAlgorithm);
+            case EncryptionAlgorithm.SALSA20:
+                return CreateSalsa20Cipher(context, 20, 32, macAlgorithm);
+            case EncryptionAlgorithm.SEED_CBC:
+                return CreateSeedCipher(context, macAlgorithm);
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsBlockCipher CreateAESCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+        {
+            return new TlsBlockCipher(context, CreateAesBlockCipher(), CreateAesBlockCipher(),
+                CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsBlockCipher CreateCamelliaCipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+        {
+            return new TlsBlockCipher(context, CreateCamelliaBlockCipher(),
+                CreateCamelliaBlockCipher(), CreateHMacDigest(macAlgorithm),
+                CreateHMacDigest(macAlgorithm), cipherKeySize);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsCipher CreateChaCha20Poly1305(TlsContext context)
+        {
+            return new Chacha20Poly1305(context);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsAeadCipher CreateCipher_Aes_Ccm(TlsContext context, int cipherKeySize, int macSize)
+        {
+            return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Ccm(),
+                CreateAeadBlockCipher_Aes_Ccm(), cipherKeySize, macSize);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsAeadCipher CreateCipher_Aes_Gcm(TlsContext context, int cipherKeySize, int macSize)
+        {
+            return new TlsAeadCipher(context, CreateAeadBlockCipher_Aes_Gcm(),
+                CreateAeadBlockCipher_Aes_Gcm(), cipherKeySize, macSize);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsAeadCipher CreateCipher_Camellia_Gcm(TlsContext context, int cipherKeySize, int macSize)
+        {
+            return new TlsAeadCipher(context, CreateAeadBlockCipher_Camellia_Gcm(),
+                CreateAeadBlockCipher_Camellia_Gcm(), cipherKeySize, macSize);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsBlockCipher CreateDesEdeCipher(TlsContext context, int macAlgorithm)
+        {
+            return new TlsBlockCipher(context, CreateDesEdeBlockCipher(), CreateDesEdeBlockCipher(),
+                CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), 24);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsNullCipher CreateNullCipher(TlsContext context, int macAlgorithm)
+        {
+            return new TlsNullCipher(context, CreateHMacDigest(macAlgorithm),
+                CreateHMacDigest(macAlgorithm));
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsStreamCipher CreateRC4Cipher(TlsContext context, int cipherKeySize, int macAlgorithm)
+        {
+            return new TlsStreamCipher(context, CreateRC4StreamCipher(), CreateRC4StreamCipher(),
+                CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize, false);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsStreamCipher CreateSalsa20Cipher(TlsContext context, int rounds, int cipherKeySize, int macAlgorithm)
+        {
+            return new TlsStreamCipher(context, CreateSalsa20StreamCipher(rounds), CreateSalsa20StreamCipher(rounds),
+                CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), cipherKeySize, true);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual TlsBlockCipher CreateSeedCipher(TlsContext context, int macAlgorithm)
+        {
+            return new TlsBlockCipher(context, CreateSeedBlockCipher(), CreateSeedBlockCipher(),
+                CreateHMacDigest(macAlgorithm), CreateHMacDigest(macAlgorithm), 16);
+        }
+
+        protected virtual IBlockCipher CreateAesEngine()
+        {
+            return new AesEngine();
+        }
+
+        protected virtual IBlockCipher CreateCamelliaEngine()
+        {
+            return new CamelliaEngine();
+        }
+
+        protected virtual IBlockCipher CreateAesBlockCipher()
+        {
+            return new CbcBlockCipher(CreateAesEngine());
+        }
+
+        protected virtual IAeadBlockCipher CreateAeadBlockCipher_Aes_Ccm()
+        {
+            return new CcmBlockCipher(CreateAesEngine());
+        }
+
+        protected virtual IAeadBlockCipher CreateAeadBlockCipher_Aes_Gcm()
+        {
+            // TODO Consider allowing custom configuration of multiplier
+            return new GcmBlockCipher(CreateAesEngine());
+        }
+
+        protected virtual IAeadBlockCipher CreateAeadBlockCipher_Camellia_Gcm()
+        {
+            // TODO Consider allowing custom configuration of multiplier
+            return new GcmBlockCipher(CreateCamelliaEngine());
+        }
+
+        protected virtual IBlockCipher CreateCamelliaBlockCipher()
+        {
+            return new CbcBlockCipher(CreateCamelliaEngine());
+        }
+
+        protected virtual IBlockCipher CreateDesEdeBlockCipher()
+        {
+            return new CbcBlockCipher(new DesEdeEngine());
+        }
+
+        protected virtual IStreamCipher CreateRC4StreamCipher()
+        {
+            return new RC4Engine();
+        }
+
+        protected virtual IStreamCipher CreateSalsa20StreamCipher(int rounds)
+        {
+            return new Salsa20Engine(rounds);
+        }
+
+        protected virtual IBlockCipher CreateSeedBlockCipher()
+        {
+            return new CbcBlockCipher(new SeedEngine());
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual IDigest CreateHMacDigest(int macAlgorithm)
+        {
+            switch (macAlgorithm)
+            {
+            case MacAlgorithm.cls_null:
+                return null;
+            case MacAlgorithm.hmac_md5:
+                return TlsUtilities.CreateHash(HashAlgorithm.md5);
+            case MacAlgorithm.hmac_sha1:
+                return TlsUtilities.CreateHash(HashAlgorithm.sha1);
+            case MacAlgorithm.hmac_sha256:
+                return TlsUtilities.CreateHash(HashAlgorithm.sha256);
+            case MacAlgorithm.hmac_sha384:
+                return TlsUtilities.CreateHash(HashAlgorithm.sha384);
+            case MacAlgorithm.hmac_sha512:
+                return TlsUtilities.CreateHash(HashAlgorithm.sha512);
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsClient.cs
new file mode 100644
index 0000000..a2a04a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsClient.cs
@@ -0,0 +1,461 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class DefaultTlsClient
+        :   AbstractTlsClient
+    {
+        public DefaultTlsClient()
+            :   base()
+        {
+        }
+
+        public DefaultTlsClient(TlsCipherFactory cipherFactory)
+            :   base(cipherFactory)
+        {
+        }
+
+        public override int[] GetCipherSuites()
+        {
+            return new int[]
+            {
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+                CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
+                CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+            };
+        }
+
+        public override TlsKeyExchange GetKeyExchange()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
+
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
+
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return CreateRsaKeyExchange();
+
+            default:
+                /*
+                    * Note: internal error here; the TlsProtocol implementation verifies that the
+                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                    * we now can't produce an implementation, we shouldn't have offered it!
+                    */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override TlsCipher GetCipher()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1);
+
+            default:
+                /*
+                    * Note: internal error here; the TlsProtocol implementation verifies that the
+                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                    * we now can't produce an implementation, we shouldn't have offered it!
+                    */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
+        {
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+        }
+
+        protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
+        {
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, null);
+        }
+
+        protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
+        {
+            return new TlsECDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats,
+                mServerECPointFormats);
+        }
+
+        protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange)
+        {
+            return new TlsECDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats,
+                mServerECPointFormats);
+        }
+
+        protected virtual TlsKeyExchange CreateRsaKeyExchange()
+        {
+            return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsEncryptionCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsEncryptionCredentials.cs
new file mode 100644
index 0000000..34d15d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsEncryptionCredentials.cs
@@ -0,0 +1,51 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsEncryptionCredentials
+        :   AbstractTlsEncryptionCredentials
+    {
+        protected readonly TlsContext mContext;
+        protected readonly Certificate mCertificate;
+        protected readonly AsymmetricKeyParameter mPrivateKey;
+
+        public DefaultTlsEncryptionCredentials(TlsContext context, Certificate certificate,
+            AsymmetricKeyParameter privateKey)
+        {
+            if (certificate == null)
+                throw new ArgumentNullException("certificate");
+            if (certificate.IsEmpty)
+                throw new ArgumentException("cannot be empty", "certificate");
+            if (privateKey == null)
+                throw new ArgumentNullException("'privateKey' cannot be null");
+            if (!privateKey.IsPrivate)
+                throw new ArgumentException("must be private", "privateKey");
+
+            if (privateKey is RsaKeyParameters)
+            {
+            }
+            else
+            {
+                throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
+            }
+
+            this.mContext = context;
+            this.mCertificate = certificate;
+            this.mPrivateKey = privateKey;
+        }
+
+        public override Certificate Certificate
+        {
+            get { return mCertificate; }
+        }
+
+        /// <exception cref="IOException"></exception>
+        public override byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret)
+        {
+            return TlsRsaUtilities.SafeDecryptPreMasterSecret(mContext, (RsaKeyParameters)mPrivateKey, encryptedPreMasterSecret);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsServer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsServer.cs
new file mode 100644
index 0000000..017ed0d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsServer.cs
@@ -0,0 +1,548 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class DefaultTlsServer
+        :   AbstractTlsServer
+    {
+        public DefaultTlsServer()
+            :   base()
+        {
+        }
+
+        public DefaultTlsServer(TlsCipherFactory cipherFactory)
+            :   base(cipherFactory)
+        {
+        }
+
+        protected virtual TlsEncryptionCredentials GetRsaEncryptionCredentials()
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        protected virtual TlsSignerCredentials GetRsaSignerCredentials()
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        protected virtual DHParameters GetDHParameters()
+        {
+            return DHStandardGroups.rfc5114_1024_160;
+        }
+
+        protected override int[] GetCipherSuites()
+        {
+            return new int[]
+            {
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
+                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+                CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384,
+                CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
+                CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256,
+                CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA,
+                CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA,
+            };
+        }
+
+        public override TlsCredentials GetCredentials()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return GetRsaEncryptionCredentials();
+
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+                return GetRsaSignerCredentials();
+
+            default:
+                /*
+                 * Note: internal error here; selected a key exchange we don't implement!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override TlsKeyExchange GetKeyExchange()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_DSS);
+
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+                return CreateDHKeyExchange(KeyExchangeAlgorithm.DH_RSA);
+
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_DSS);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+                return CreateDheKeyExchange(KeyExchangeAlgorithm.DHE_RSA);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_ECDSA);
+
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+                return CreateECDHKeyExchange(KeyExchangeAlgorithm.ECDH_RSA);
+
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_ECDSA);
+
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+                return CreateECDheKeyExchange(KeyExchangeAlgorithm.ECDHE_RSA);
+
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return createRSAKeyExchange();
+
+            default:
+                /*
+                 * Note: internal error here; selected a key exchange we don't implement!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override TlsCipher GetCipher()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AEAD_CHACHA20_POLY1305, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_md5);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_md5);
+
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SEED_CBC, MacAlgorithm.hmac_sha1);
+
+            default:
+                /*
+                 * Note: internal error here; selected a cipher suite we don't implement!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        protected virtual TlsKeyExchange CreateDHKeyExchange(int keyExchange)
+        {
+            return new TlsDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+        }
+
+        protected virtual TlsKeyExchange CreateDheKeyExchange(int keyExchange)
+        {
+            return new TlsDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, GetDHParameters());
+        }
+
+        protected virtual TlsKeyExchange CreateECDHKeyExchange(int keyExchange)
+        {
+            return new TlsECDHKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats,
+                mServerECPointFormats);
+        }
+
+        protected virtual TlsKeyExchange CreateECDheKeyExchange(int keyExchange)
+        {
+            return new TlsECDheKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mNamedCurves, mClientECPointFormats,
+                mServerECPointFormats);
+        }
+
+        protected virtual TlsKeyExchange createRSAKeyExchange()
+        {
+            return new TlsRsaKeyExchange(mSupportedSignatureAlgorithms);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsSignerCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsSignerCredentials.cs
new file mode 100644
index 0000000..c7a1365
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DefaultTlsSignerCredentials.cs
@@ -0,0 +1,92 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DefaultTlsSignerCredentials
+        :   AbstractTlsSignerCredentials
+    {
+        protected readonly TlsContext mContext;
+        protected readonly Certificate mCertificate;
+        protected readonly AsymmetricKeyParameter mPrivateKey;
+        protected readonly SignatureAndHashAlgorithm mSignatureAndHashAlgorithm;
+
+        protected readonly TlsSigner mSigner;
+
+        public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey)
+            :   this(context, certificate, privateKey, null)
+        {
+        }
+
+        public DefaultTlsSignerCredentials(TlsContext context, Certificate certificate, AsymmetricKeyParameter privateKey,
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm)
+        {
+            if (certificate == null)
+                throw new ArgumentNullException("certificate");
+            if (certificate.IsEmpty)
+                throw new ArgumentException("cannot be empty", "clientCertificate");
+            if (privateKey == null)
+                throw new ArgumentNullException("privateKey");
+            if (!privateKey.IsPrivate)
+                throw new ArgumentException("must be private", "privateKey");
+            if (TlsUtilities.IsTlsV12(context) && signatureAndHashAlgorithm == null)
+                throw new ArgumentException("cannot be null for (D)TLS 1.2+", "signatureAndHashAlgorithm");
+
+            if (privateKey is RsaKeyParameters)
+            {
+                mSigner = new TlsRsaSigner();
+            }
+            else if (privateKey is DsaPrivateKeyParameters)
+            {
+                mSigner = new TlsDssSigner();
+            }
+            else if (privateKey is ECPrivateKeyParameters)
+            {
+                mSigner = new TlsECDsaSigner();
+            }
+            else
+            {
+                throw new ArgumentException("type not supported: " + privateKey.GetType().FullName, "privateKey");
+            }
+
+            this.mSigner.Init(context);
+
+            this.mContext = context;
+            this.mCertificate = certificate;
+            this.mPrivateKey = privateKey;
+            this.mSignatureAndHashAlgorithm = signatureAndHashAlgorithm;
+        }
+
+        public override Certificate Certificate
+        {
+            get { return mCertificate; }
+        }
+
+        /// <exception cref="IOException"></exception>
+        public override byte[] GenerateCertificateSignature(byte[] hash)
+        {
+            try
+            {
+                if (TlsUtilities.IsTlsV12(mContext))
+                {
+                    return mSigner.GenerateRawSignature(mSignatureAndHashAlgorithm, mPrivateKey, hash);
+                }
+                else
+                {
+                    return mSigner.GenerateRawSignature(mPrivateKey, hash);
+                }
+            }
+            catch (CryptoException e)
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
+        }
+
+        public override SignatureAndHashAlgorithm SignatureAndHashAlgorithm
+        {
+            get { return mSignatureAndHashAlgorithm; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DeferredHash.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DeferredHash.cs
new file mode 100644
index 0000000..1112d4a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DeferredHash.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * Buffers input until the hash algorithm is determined.
+     */
+    internal class DeferredHash
+        :   TlsHandshakeHash
+    {
+        protected const int BUFFERING_HASH_LIMIT = 4;
+
+        protected TlsContext mContext;
+
+        private DigestInputBuffer mBuf;
+        private IDictionary mHashes;
+        private int mPrfHashAlgorithm;
+
+        internal DeferredHash()
+        {
+            this.mBuf = new DigestInputBuffer();
+            this.mHashes = Platform.CreateHashtable();
+            this.mPrfHashAlgorithm = -1;
+        }
+
+        private DeferredHash(byte prfHashAlgorithm, IDigest prfHash)
+        {
+            this.mBuf = null;
+            this.mHashes = Platform.CreateHashtable();
+            this.mPrfHashAlgorithm = prfHashAlgorithm;
+            mHashes[prfHashAlgorithm] = prfHash;
+        }
+
+        public virtual void Init(TlsContext context)
+        {
+            this.mContext = context;
+        }
+
+        public virtual TlsHandshakeHash NotifyPrfDetermined()
+        {
+            int prfAlgorithm = mContext.SecurityParameters.PrfAlgorithm;
+            if (prfAlgorithm == PrfAlgorithm.tls_prf_legacy)
+            {
+                CombinedHash legacyHash = new CombinedHash();
+                legacyHash.Init(mContext);
+                mBuf.UpdateDigest(legacyHash);
+                return legacyHash.NotifyPrfDetermined();
+            }
+
+            this.mPrfHashAlgorithm = TlsUtilities.GetHashAlgorithmForPrfAlgorithm(prfAlgorithm);
+
+            CheckTrackingHash((byte)mPrfHashAlgorithm);
+
+            return this;
+        }
+
+        public virtual void TrackHashAlgorithm(byte hashAlgorithm)
+        {
+            if (mBuf == null)
+                throw new InvalidOperationException("Too late to track more hash algorithms");
+
+            CheckTrackingHash(hashAlgorithm);
+        }
+
+        public virtual void SealHashAlgorithms()
+        {
+            CheckStopBuffering();
+        }
+
+        public virtual TlsHandshakeHash StopTracking()
+        {
+            byte prfHashAlgorithm = (byte)mPrfHashAlgorithm;
+            IDigest prfHash = TlsUtilities.CloneHash(prfHashAlgorithm, (IDigest)mHashes[prfHashAlgorithm]);
+            if (mBuf != null)
+            {
+                mBuf.UpdateDigest(prfHash);
+            }
+            DeferredHash result = new DeferredHash(prfHashAlgorithm, prfHash);
+            result.Init(mContext);
+            return result;
+        }
+
+        public virtual IDigest ForkPrfHash()
+        {
+            CheckStopBuffering();
+
+            byte prfHashAlgorithm = (byte)mPrfHashAlgorithm;
+            if (mBuf != null)
+            {
+                IDigest prfHash = TlsUtilities.CreateHash(prfHashAlgorithm);
+                mBuf.UpdateDigest(prfHash);
+                return prfHash;
+            }
+
+            return TlsUtilities.CloneHash(prfHashAlgorithm, (IDigest)mHashes[prfHashAlgorithm]);
+        }
+
+        public virtual byte[] GetFinalHash(byte hashAlgorithm)
+        {
+            IDigest d = (IDigest)mHashes[hashAlgorithm];
+            if (d == null)
+                throw new InvalidOperationException("HashAlgorithm " + hashAlgorithm + " is not being tracked");
+
+            d = TlsUtilities.CloneHash(hashAlgorithm, d);
+            if (mBuf != null)
+            {
+                mBuf.UpdateDigest(d);
+            }
+
+            return DigestUtilities.DoFinal(d);
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { throw new InvalidOperationException("Use Fork() to get a definite IDigest"); }
+        }
+
+        public virtual int GetByteLength()
+        {
+            throw new InvalidOperationException("Use Fork() to get a definite IDigest");
+        }
+
+        public virtual int GetDigestSize()
+        {
+            throw new InvalidOperationException("Use Fork() to get a definite IDigest");
+        }
+
+        public virtual void Update(byte input)
+        {
+            if (mBuf != null)
+            {
+                mBuf.WriteByte(input);
+                return;
+            }
+
+            foreach (IDigest hash in mHashes.Values)
+            {
+                hash.Update(input);
+            }
+        }
+
+        public virtual void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            if (mBuf != null)
+            {
+                mBuf.Write(input, inOff, len);
+                return;
+            }
+
+            foreach (IDigest hash in mHashes.Values)
+            {
+                hash.BlockUpdate(input, inOff, len);
+            }
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            throw new InvalidOperationException("Use Fork() to get a definite IDigest");
+        }
+
+        public virtual void Reset()
+        {
+            if (mBuf != null)
+            {
+                mBuf.SetLength(0);
+                return;
+            }
+
+            foreach (IDigest hash in mHashes.Values)
+            {
+                hash.Reset();
+            }
+        }
+
+        protected virtual void CheckStopBuffering()
+        {
+            if (mBuf != null && mHashes.Count <= BUFFERING_HASH_LIMIT)
+            {
+                foreach (IDigest hash in mHashes.Values)
+                {
+                    mBuf.UpdateDigest(hash);
+                }
+
+                this.mBuf = null;
+            }
+        }
+
+        protected virtual void CheckTrackingHash(byte hashAlgorithm)
+        {
+            if (!mHashes.Contains(hashAlgorithm))
+            {
+                IDigest hash = TlsUtilities.CreateHash(hashAlgorithm);
+                mHashes[hashAlgorithm] = hash;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DigestAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DigestAlgorithm.cs
new file mode 100644
index 0000000..cede6b7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DigestAlgorithm.cs
@@ -0,0 +1,21 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public enum DigestAlgorithm
+	{
+		/*
+		 * Note that the values here are implementation-specific and arbitrary.
+		 * It is recommended not to depend on the particular values (e.g. serialization).
+		 */
+		NULL,
+		MD5,
+		SHA,
+
+		/*
+		 * RFC 5289
+		 */
+		SHA256,
+		SHA384,
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DigestInputBuffer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DigestInputBuffer.cs
new file mode 100644
index 0000000..547bcab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DigestInputBuffer.cs
@@ -0,0 +1,39 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class DigestInputBuffer
+        :   MemoryStream
+    {
+        internal void UpdateDigest(IDigest d)
+        {
+            WriteTo(new DigStream(d));
+        }
+
+        private class DigStream
+            :   BaseOutputStream
+        {
+            private readonly IDigest d;
+
+            internal DigStream(IDigest d)
+            {
+                this.d = d;
+            }
+
+            public override void WriteByte(byte b)
+            {
+                d.Update(b);
+            }
+
+            public override void Write(byte[] buf, int off, int len)
+            {
+                d.BlockUpdate(buf, off, len);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/DigitallySigned.cs b/BouncyCastle.AxCrypt/src/crypto/tls/DigitallySigned.cs
new file mode 100644
index 0000000..8b7344f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/DigitallySigned.cs
@@ -0,0 +1,70 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class DigitallySigned
+    {
+        protected readonly SignatureAndHashAlgorithm mAlgorithm;
+        protected readonly byte[] mSignature;
+
+        public DigitallySigned(SignatureAndHashAlgorithm algorithm, byte[] signature)
+        {
+            if (signature == null)
+                throw new ArgumentNullException("signature");
+
+            this.mAlgorithm = algorithm;
+            this.mSignature = signature;
+        }
+
+        /**
+         * @return a {@link SignatureAndHashAlgorithm} (or null before TLS 1.2).
+         */
+        public virtual SignatureAndHashAlgorithm Algorithm
+        {
+            get { return mAlgorithm; }
+        }
+
+        public virtual byte[] Signature
+        {
+            get { return mSignature; }
+        }
+
+        /**
+         * Encode this {@link DigitallySigned} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            if (mAlgorithm != null)
+            {
+                mAlgorithm.Encode(output);
+            }
+            TlsUtilities.WriteOpaque16(mSignature, output);
+        }
+
+        /**
+         * Parse a {@link DigitallySigned} from a {@link Stream}.
+         * 
+         * @param context
+         *            the {@link TlsContext} of the current connection.
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link DigitallySigned} object.
+         * @throws IOException
+         */
+        public static DigitallySigned Parse(TlsContext context, Stream input)
+        {
+            SignatureAndHashAlgorithm algorithm = null;
+            if (TlsUtilities.IsTlsV12(context))
+            {
+                algorithm = SignatureAndHashAlgorithm.Parse(input);
+            }
+            byte[] signature = TlsUtilities.ReadOpaque16(input);
+            return new DigitallySigned(algorithm, signature);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ECBasisType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ECBasisType.cs
new file mode 100644
index 0000000..5416e17
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ECBasisType.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 4492 5.4. (Errata ID: 2389)</summary>
+    public abstract class ECBasisType
+    {
+        public const byte ec_basis_trinomial = 1;
+        public const byte ec_basis_pentanomial = 2;
+
+        public static bool IsValid(byte ecBasisType)
+        {
+            return ecBasisType >= ec_basis_trinomial && ecBasisType <= ec_basis_pentanomial;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ECCurveType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ECCurveType.cs
new file mode 100644
index 0000000..1b352e9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ECCurveType.cs
@@ -0,0 +1,29 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 4492 5.4
+    /// </summary>
+    public abstract class ECCurveType
+    {
+        /**
+         * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+         * underlying finite field is a prime field.
+         */
+        public const byte explicit_prime = 1;
+
+        /**
+         * Indicates the elliptic curve domain parameters are conveyed verbosely, and the
+         * underlying finite field is a characteristic-2 field.
+         */
+        public const byte explicit_char2 = 2;
+
+        /**
+         * Indicates that a named curve is used. This option SHOULD be used when applicable.
+         */
+        public const byte named_curve = 3;
+
+        /*
+         * Values 248 through 255 are reserved for private use.
+         */
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ECPointFormat.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ECPointFormat.cs
new file mode 100644
index 0000000..21b0fdd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ECPointFormat.cs
@@ -0,0 +1,16 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 4492 5.1.2
+    /// </summary>
+    public abstract class ECPointFormat
+    {
+        public const byte uncompressed = 0;
+        public const byte ansiX962_compressed_prime = 1;
+        public const byte ansiX962_compressed_char2 = 2;
+
+        /*
+         * reserved (248..255)
+         */
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/EncryptionAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/EncryptionAlgorithm.cs
new file mode 100644
index 0000000..05d1c5d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/EncryptionAlgorithm.cs
@@ -0,0 +1,69 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class EncryptionAlgorithm
+    {
+        public const int NULL = 0;
+        public const int RC4_40 = 1;
+        public const int RC4_128 = 2;
+        public const int RC2_CBC_40 = 3;
+        public const int IDEA_CBC = 4;
+        public const int DES40_CBC = 5;
+        public const int DES_CBC = 6;
+        public const int cls_3DES_EDE_CBC = 7;
+
+        /*
+         * RFC 3268
+         */
+        public const int AES_128_CBC = 8;
+        public const int AES_256_CBC = 9;
+
+        /*
+         * RFC 5289
+         */
+        public const int AES_128_GCM = 10;
+        public const int AES_256_GCM = 11;
+
+        /*
+         * RFC 4132
+         */
+        public const int CAMELLIA_128_CBC = 12;
+        public const int CAMELLIA_256_CBC = 13;
+
+        /*
+         * RFC 4162
+         */
+        public const int SEED_CBC = 14;
+
+        /*
+         * RFC 6655
+         */
+        public const int AES_128_CCM = 15;
+        public const int AES_128_CCM_8 = 16;
+        public const int AES_256_CCM = 17;
+        public const int AES_256_CCM_8 = 18;
+
+        /*
+         * RFC 6367
+         */
+        public const int CAMELLIA_128_GCM = 19;
+        public const int CAMELLIA_256_GCM = 20;
+
+        /*
+         * draft-josefsson-salsa20-tls-04 
+         */
+        public const int ESTREAM_SALSA20 = 100;
+        public const int SALSA20 = 101;
+
+        /*
+         * draft-agl-tls-chacha20poly1305-04
+         */
+        public const int AEAD_CHACHA20_POLY1305 = 102;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ExporterLabel.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ExporterLabel.cs
new file mode 100644
index 0000000..f301ea3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ExporterLabel.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 5705</summary>
+    public abstract class ExporterLabel
+    {
+        /*
+         * RFC 5246
+         */
+        public const string client_finished = "client finished";
+        public const string server_finished = "server finished";
+        public const string master_secret = "master secret";
+        public const string key_expansion = "key expansion";
+
+        /*
+         * RFC 5216
+         */
+        public const string client_EAP_encryption = "client EAP encryption";
+
+        /*
+         * RFC 5281
+         */
+        public const string ttls_keying_material = "ttls keying material";
+        public const string ttls_challenge = "ttls challenge";
+
+        /*
+         * RFC 5764
+         */
+        public const string dtls_srtp = "EXTRACTOR-dtls_srtp";
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ExtensionType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ExtensionType.cs
new file mode 100644
index 0000000..929c134
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ExtensionType.cs
@@ -0,0 +1,61 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class ExtensionType
+    {
+        /*
+         * RFC 2546 2.3.
+         */
+        public const int server_name = 0;
+        public const int max_fragment_length = 1;
+        public const int client_certificate_url = 2;
+        public const int trusted_ca_keys = 3;
+        public const int truncated_hmac = 4;
+        public const int status_request = 5;
+
+        /*
+         * RFC 4681
+         */
+        public const int user_mapping = 6;
+
+        /*
+         * RFC 4492 5.1.
+         */
+        public const int elliptic_curves = 10;
+        public const int ec_point_formats = 11;
+
+        /*
+         * RFC 5054 2.8.1.
+         */
+        public const int srp = 12;
+
+        /*
+         * RFC 5246 7.4.1.4.
+         */
+        public const int signature_algorithms = 13;
+
+        /*
+         * RFC 5764 9.
+         */
+        public const int use_srtp = 14;
+
+        /*
+         * RFC 6520 6.
+         */
+        public const int heartbeat = 15;
+
+        /*
+         * RFC 5077 7.
+         */
+        public const int session_ticket = 35;
+
+        /*
+         * draft-ietf-tls-encrypt-then-mac-03
+         */
+        public const int encrypt_then_mac = 22;
+
+        /*
+         * RFC 5746 3.2.
+         */
+        public const int renegotiation_info = 0xff01;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HandshakeType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HandshakeType.cs
new file mode 100644
index 0000000..e63042a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HandshakeType.cs
@@ -0,0 +1,40 @@
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class HandshakeType
+    {
+        /*
+         * RFC 2246 7.4
+         */
+        public const byte hello_request = 0;
+        public const byte client_hello = 1;
+        public const byte server_hello = 2;
+        public const byte certificate = 11;
+        public const byte server_key_exchange = 12;
+        public const byte certificate_request = 13;
+        public const byte server_hello_done = 14;
+        public const byte certificate_verify = 15;
+        public const byte client_key_exchange = 16;
+        public const byte finished = 20;
+
+        /*
+         * RFC 3546 2.4
+         */
+        public const byte certificate_url = 21;
+        public const byte certificate_status = 22;
+
+        /*
+         *  (DTLS) RFC 4347 4.3.2
+         */
+        public const byte hello_verify_request = 3;
+
+        /*
+         * RFC 4680 
+         */
+        public const byte supplemental_data = 23;
+
+        /*
+         * RFC 5077 
+         */
+        public const byte session_ticket = 4;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HashAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HashAlgorithm.cs
new file mode 100644
index 0000000..ac6def2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HashAlgorithm.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 5246 7.4.1.4.1</summary>
+    public abstract class HashAlgorithm
+    {
+        public const byte none = 0;
+        public const byte md5 = 1;
+        public const byte sha1 = 2;
+        public const byte sha224 = 3;
+        public const byte sha256 = 4;
+        public const byte sha384 = 5;
+        public const byte sha512 = 6;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatExtension.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatExtension.cs
new file mode 100644
index 0000000..0498372
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatExtension.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class HeartbeatExtension
+    {
+        protected readonly byte mMode;
+
+        public HeartbeatExtension(byte mode)
+        {
+            if (!HeartbeatMode.IsValid(mode))
+                throw new ArgumentException("not a valid HeartbeatMode value", "mode");
+
+            this.mMode = mode;
+        }
+
+        public virtual byte Mode
+        {
+            get { return mMode; }
+        }
+
+        /**
+         * Encode this {@link HeartbeatExtension} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(mMode, output);
+        }
+
+        /**
+         * Parse a {@link HeartbeatExtension} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link HeartbeatExtension} object.
+         * @throws IOException
+         */
+        public static HeartbeatExtension Parse(Stream input)
+        {
+            byte mode = TlsUtilities.ReadUint8(input);
+            if (!HeartbeatMode.IsValid(mode))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return new HeartbeatExtension(mode);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessage.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessage.cs
new file mode 100644
index 0000000..daf366e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessage.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class HeartbeatMessage
+    {
+        protected readonly byte mType;
+        protected readonly byte[] mPayload;
+        protected readonly int mPaddingLength;
+
+        public HeartbeatMessage(byte type, byte[] payload, int paddingLength)
+        {
+            if (!HeartbeatMessageType.IsValid(type))
+                throw new ArgumentException("not a valid HeartbeatMessageType value", "type");
+            if (payload == null || payload.Length >= (1 << 16))
+                throw new ArgumentException("must have length < 2^16", "payload");
+            if (paddingLength < 16)
+                throw new ArgumentException("must be at least 16", "paddingLength");
+
+            this.mType = type;
+            this.mPayload = payload;
+            this.mPaddingLength = paddingLength;
+        }
+
+        /**
+         * Encode this {@link HeartbeatMessage} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(TlsContext context, Stream output)
+        {
+            TlsUtilities.WriteUint8(mType, output);
+
+            TlsUtilities.CheckUint16(mPayload.Length);
+            TlsUtilities.WriteUint16(mPayload.Length, output);
+            output.Write(mPayload, 0, mPayload.Length);
+
+            byte[] padding = new byte[mPaddingLength];
+            context.NonceRandomGenerator.NextBytes(padding);
+            output.Write(padding, 0, padding.Length);
+        }
+
+        /**
+         * Parse a {@link HeartbeatMessage} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link HeartbeatMessage} object.
+         * @throws IOException
+         */
+        public static HeartbeatMessage Parse(Stream input)
+        {
+            byte type = TlsUtilities.ReadUint8(input);
+            if (!HeartbeatMessageType.IsValid(type))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            int payload_length = TlsUtilities.ReadUint16(input);
+
+            PayloadBuffer buf = new PayloadBuffer();
+            Streams.PipeAll(input, buf);
+
+            byte[] payload = buf.ToTruncatedByteArray(payload_length);
+            if (payload == null)
+            {
+                /*
+                 * RFC 6520 4. If the payload_length of a received HeartbeatMessage is too large, the
+                 * received HeartbeatMessage MUST be discarded silently.
+                 */
+                return null;
+            }
+
+            TlsUtilities.CheckUint16(buf.Length);
+            int padding_length = (int)buf.Length - payload.Length;
+
+            /*
+             * RFC 6520 4. The padding of a received HeartbeatMessage message MUST be ignored
+             */
+            return new HeartbeatMessage(type, payload, padding_length);
+        }
+
+        internal class PayloadBuffer
+            :   MemoryStream
+        {
+            internal byte[] ToTruncatedByteArray(int payloadLength)
+            {
+                /*
+                 * RFC 6520 4. The padding_length MUST be at least 16.
+                 */
+                int minimumCount = payloadLength + 16;
+                if (Length < minimumCount)
+                    return null;
+                return Arrays.CopyOf(ToArray(), payloadLength);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessageType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessageType.cs
new file mode 100644
index 0000000..57a4b86
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMessageType.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /*
+     * RFC 6520 3.
+     */
+    public abstract class HeartbeatMessageType
+    {
+        public const byte heartbeat_request = 1;
+        public const byte heartbeat_response = 2;
+
+        public static bool IsValid(byte heartbeatMessageType)
+        {
+            return heartbeatMessageType >= heartbeat_request && heartbeatMessageType <= heartbeat_response;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMode.cs b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMode.cs
new file mode 100644
index 0000000..f1570a8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/HeartbeatMode.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /*
+     * RFC 6520
+     */
+    public abstract class HeartbeatMode
+    {
+        public const byte peer_allowed_to_send = 1;
+        public const byte peer_not_allowed_to_send = 2;
+
+        public static bool IsValid(byte heartbeatMode)
+        {
+            return heartbeatMode >= peer_allowed_to_send && heartbeatMode <= peer_not_allowed_to_send;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ICertificateVerifyer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ICertificateVerifyer.cs
new file mode 100644
index 0000000..df5ea51
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ICertificateVerifyer.cs
@@ -0,0 +1,18 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	/// <remarks>
+	/// This should be implemented by any class which can find out, if a given
+	/// certificate chain is being accepted by an client.
+	/// </remarks>
+	[Obsolete("Perform certificate verification in TlsAuthentication implementation")]
+	public interface ICertificateVerifyer
+	{
+		/// <param name="certs">The certs, which are part of the chain.</param>
+		/// <returns>True, if the chain is accepted, false otherwise</returns>
+		bool IsValid(X509CertificateStructure[] certs);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/KeyExchangeAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/KeyExchangeAlgorithm.cs
new file mode 100644
index 0000000..9b1b3ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/KeyExchangeAlgorithm.cs
@@ -0,0 +1,54 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class KeyExchangeAlgorithm
+    {
+        public const int NULL = 0;
+        public const int RSA = 1;
+        public const int RSA_EXPORT = 2;
+        public const int DHE_DSS = 3;
+        public const int DHE_DSS_EXPORT = 4;
+        public const int DHE_RSA = 5;
+        public const int DHE_RSA_EXPORT = 6;
+        public const int DH_DSS = 7;
+        public const int DH_DSS_EXPORT = 8;
+        public const int DH_RSA = 9;
+        public const int DH_RSA_EXPORT = 10;
+        public const int DH_anon = 11;
+        public const int DH_anon_EXPORT = 12;
+
+        /*
+         * RFC 4279
+         */
+        public const int PSK = 13;
+        public const int DHE_PSK = 14;
+        public const int RSA_PSK = 15;
+
+        /*
+         * RFC 4429
+         */
+        public const int ECDH_ECDSA = 16;
+        public const int ECDHE_ECDSA = 17;
+        public const int ECDH_RSA = 18;
+        public const int ECDHE_RSA = 19;
+        public const int ECDH_anon = 20;
+
+        /*
+         * RFC 5054
+         */
+        public const int SRP = 21;
+        public const int SRP_DSS = 22;
+        public const int SRP_RSA = 23;
+    
+        /*
+         * RFC 5489
+         */
+        public const int ECDHE_PSK = 24;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsAuthentication.cs b/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsAuthentication.cs
new file mode 100644
index 0000000..395f942
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsAuthentication.cs
@@ -0,0 +1,30 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	/// <summary>
+	/// A temporary class to wrap old CertificateVerifyer stuff for new TlsAuthentication.
+	/// </summary>
+	[Obsolete]
+	public class LegacyTlsAuthentication
+		: TlsAuthentication
+	{
+		protected ICertificateVerifyer verifyer;
+
+		public LegacyTlsAuthentication(ICertificateVerifyer verifyer)
+		{
+			this.verifyer = verifyer;
+		}
+
+		public virtual void NotifyServerCertificate(Certificate serverCertificate)
+		{
+			if (!this.verifyer.IsValid(serverCertificate.GetCerts()))
+				throw new TlsFatalAlert(AlertDescription.user_canceled);
+		}
+
+		public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+		{
+			return null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsClient.cs
new file mode 100644
index 0000000..fbb9a73
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/LegacyTlsClient.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	/// <summary>
+	/// A temporary class to use LegacyTlsAuthentication 
+	/// </summary>
+	[Obsolete]
+	public class LegacyTlsClient
+		: DefaultTlsClient
+	{
+		[Obsolete]
+		protected ICertificateVerifyer verifyer;
+
+		[Obsolete]
+		public LegacyTlsClient(ICertificateVerifyer verifyer)
+		{
+			this.verifyer = verifyer;
+		}
+
+		public override TlsAuthentication GetAuthentication()
+		{
+			return new LegacyTlsAuthentication(verifyer);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/MacAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/MacAlgorithm.cs
new file mode 100644
index 0000000..e4aa88d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/MacAlgorithm.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 2246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class MacAlgorithm
+    {
+        public const int cls_null = 0;
+        public const int md5 = 1;
+        public const int sha = 2;
+
+        /*
+         * RFC 5246
+         */
+        public const int hmac_md5 = md5;
+        public const int hmac_sha1 = sha;
+        public const int hmac_sha256 = 3;
+        public const int hmac_sha384 = 4;
+        public const int hmac_sha512 = 5;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/MaxFragmentLength.cs b/BouncyCastle.AxCrypt/src/crypto/tls/MaxFragmentLength.cs
new file mode 100644
index 0000000..5b10b35
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/MaxFragmentLength.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class MaxFragmentLength
+    {
+        /*
+         * RFC 3546 3.2.
+         */
+        public const byte pow2_9 = 1;
+        public const byte pow2_10 = 2;
+        public const byte pow2_11 = 3;
+        public const byte pow2_12 = 4;
+
+        public static bool IsValid(byte maxFragmentLength)
+        {
+            return maxFragmentLength >= pow2_9 && maxFragmentLength <= pow2_12;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/NameType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/NameType.cs
new file mode 100644
index 0000000..25f6046
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/NameType.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class NameType
+    {
+        /*
+         * RFC 3546 3.1.
+         */
+        public const byte host_name = 0;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/NamedCurve.cs b/BouncyCastle.AxCrypt/src/crypto/tls/NamedCurve.cs
new file mode 100644
index 0000000..b8aa0ec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/NamedCurve.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// RFC 4492 5.1.1
+    /// The named curves defined here are those specified in SEC 2 [13]. Note that many of
+    /// these curves are also recommended in ANSI X9.62 [7] and FIPS 186-2 [11]. Values 0xFE00
+    /// through 0xFEFF are reserved for private use. Values 0xFF01 and 0xFF02 indicate that the
+    /// client supports arbitrary prime and characteristic-2 curves, respectively (the curve
+    /// parameters must be encoded explicitly in ECParameters).
+    /// </summary>
+    public abstract class NamedCurve
+    {
+        public const int sect163k1 = 1;
+        public const int sect163r1 = 2;
+        public const int sect163r2 = 3;
+        public const int sect193r1 = 4;
+        public const int sect193r2 = 5;
+        public const int sect233k1 = 6;
+        public const int sect233r1 = 7;
+        public const int sect239k1 = 8;
+        public const int sect283k1 = 9;
+        public const int sect283r1 = 10;
+        public const int sect409k1 = 11;
+        public const int sect409r1 = 12;
+        public const int sect571k1 = 13;
+        public const int sect571r1 = 14;
+        public const int secp160k1 = 15;
+        public const int secp160r1 = 16;
+        public const int secp160r2 = 17;
+        public const int secp192k1 = 18;
+        public const int secp192r1 = 19;
+        public const int secp224k1 = 20;
+        public const int secp224r1 = 21;
+        public const int secp256k1 = 22;
+        public const int secp256r1 = 23;
+        public const int secp384r1 = 24;
+        public const int secp521r1 = 25;
+    
+        /*
+         * RFC 7027
+         */
+        public const int brainpoolP256r1 = 26;
+        public const int brainpoolP384r1 = 27;
+        public const int brainpoolP512r1 = 28;
+
+        /*
+         * reserved (0xFE00..0xFEFF)
+         */
+
+        public const int arbitrary_explicit_prime_curves = 0xFF01;
+        public const int arbitrary_explicit_char2_curves = 0xFF02;
+
+        public static bool IsValid(int namedCurve)
+        {
+            return (namedCurve >= sect163k1 && namedCurve <= brainpoolP512r1)
+                || (namedCurve >= arbitrary_explicit_prime_curves && namedCurve <= arbitrary_explicit_char2_curves);
+        }
+
+        public static bool RefersToASpecificNamedCurve(int namedCurve)
+        {
+            switch (namedCurve)
+            {
+            case arbitrary_explicit_prime_curves:
+            case arbitrary_explicit_char2_curves:
+                return false;
+            default:
+                return true;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/NewSessionTicket.cs b/BouncyCastle.AxCrypt/src/crypto/tls/NewSessionTicket.cs
new file mode 100644
index 0000000..a84026b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/NewSessionTicket.cs
@@ -0,0 +1,53 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class NewSessionTicket
+    {
+        protected readonly long mTicketLifetimeHint;
+        protected readonly byte[] mTicket;
+
+        public NewSessionTicket(long ticketLifetimeHint, byte[] ticket)
+        {
+            this.mTicketLifetimeHint = ticketLifetimeHint;
+            this.mTicket = ticket;
+        }
+
+        public virtual long TicketLifetimeHint
+        {
+            get { return mTicketLifetimeHint; }
+        }
+
+        public virtual byte[] Ticket
+        {
+            get { return mTicket; }
+        }
+
+        /**
+         * Encode this {@link NewSessionTicket} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint32(mTicketLifetimeHint, output);
+            TlsUtilities.WriteOpaque16(mTicket, output);
+        }
+
+        /**
+         * Parse a {@link NewSessionTicket} from a {@link Stream}.
+         *
+         * @param input the {@link Stream} to parse from.
+         * @return a {@link NewSessionTicket} object.
+         * @throws IOException
+         */
+        public static NewSessionTicket Parse(Stream input)
+        {
+            long ticketLifetimeHint = TlsUtilities.ReadUint32(input);
+            byte[] ticket = TlsUtilities.ReadOpaque16(input);
+            return new NewSessionTicket(ticketLifetimeHint, ticket);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/OcspStatusRequest.cs b/BouncyCastle.AxCrypt/src/crypto/tls/OcspStatusRequest.cs
new file mode 100644
index 0000000..2dd8371
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/OcspStatusRequest.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 3546 3.6
+     */
+    public class OcspStatusRequest
+    {
+        protected readonly IList mResponderIDList;
+        protected readonly X509Extensions mRequestExtensions;
+
+        /**
+         * @param responderIDList
+         *            an {@link IList} of {@link ResponderID}, specifying the list of trusted OCSP
+         *            responders. An empty list has the special meaning that the responders are
+         *            implicitly known to the server - e.g., by prior arrangement.
+         * @param requestExtensions
+         *            OCSP request extensions. A null value means that there are no extensions.
+         */
+        public OcspStatusRequest(IList responderIDList, X509Extensions requestExtensions)
+        {
+            this.mResponderIDList = responderIDList;
+            this.mRequestExtensions = requestExtensions;
+        }
+
+        /**
+         * @return an {@link IList} of {@link ResponderID}
+         */
+        public virtual IList ResponderIDList
+        {
+            get { return mResponderIDList; }
+        }
+
+        /**
+         * @return OCSP request extensions
+         */
+        public virtual X509Extensions RequestExtensions
+        {
+            get { return mRequestExtensions; }
+        }
+
+        /**
+         * Encode this {@link OcspStatusRequest} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            if (mResponderIDList == null || mResponderIDList.Count < 1)
+            {
+                TlsUtilities.WriteUint16(0, output);
+            }
+            else
+            {
+                MemoryStream buf = new MemoryStream();
+                for (int i = 0; i < mResponderIDList.Count; ++i)
+                {
+                    ResponderID responderID = (ResponderID)mResponderIDList[i];
+                    byte[] derEncoding = responderID.GetEncoded(Asn1Encodable.Der);
+                    TlsUtilities.WriteOpaque16(derEncoding, buf);
+                }
+                TlsUtilities.CheckUint16(buf.Length);
+                TlsUtilities.WriteUint16((int)buf.Length, output);
+                buf.WriteTo(output);
+            }
+
+            if (mRequestExtensions == null)
+            {
+                TlsUtilities.WriteUint16(0, output);
+            }
+            else
+            {
+                byte[] derEncoding = mRequestExtensions.GetEncoded(Asn1Encodable.Der);
+                TlsUtilities.CheckUint16(derEncoding.Length);
+                TlsUtilities.WriteUint16(derEncoding.Length, output);
+                output.Write(derEncoding, 0, derEncoding.Length);
+            }
+        }
+
+        /**
+         * Parse a {@link OcspStatusRequest} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return an {@link OcspStatusRequest} object.
+         * @throws IOException
+         */
+        public static OcspStatusRequest Parse(Stream input)
+        {
+            IList responderIDList = Platform.CreateArrayList();
+            {
+                int length = TlsUtilities.ReadUint16(input);
+                if (length > 0)
+                {
+                    byte[] data = TlsUtilities.ReadFully(length, input);
+                    MemoryStream buf = new MemoryStream(data, false);
+                    do
+                    {
+                        byte[] derEncoding = TlsUtilities.ReadOpaque16(buf);
+                        ResponderID responderID = ResponderID.GetInstance(TlsUtilities.ReadDerObject(derEncoding));
+                        responderIDList.Add(responderID);
+                    }
+                    while (buf.Position < buf.Length);
+                }
+            }
+
+            X509Extensions requestExtensions = null;
+            {
+                int length = TlsUtilities.ReadUint16(input);
+                if (length > 0)
+                {
+                    byte[] derEncoding = TlsUtilities.ReadFully(length, input);
+                    requestExtensions = X509Extensions.GetInstance(TlsUtilities.ReadDerObject(derEncoding));
+                }
+            }
+
+            return new OcspStatusRequest(responderIDList, requestExtensions);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/PrfAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/PrfAlgorithm.cs
new file mode 100644
index 0000000..871241b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/PrfAlgorithm.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 5246</summary>
+    /// <remarks>
+    /// Note that the values here are implementation-specific and arbitrary. It is recommended not to
+    /// depend on the particular values (e.g. serialization).
+    /// </remarks>
+    public abstract class PrfAlgorithm
+    {
+        /*
+         * Placeholder to refer to the legacy TLS algorithm
+         */
+        public const int tls_prf_legacy = 0;
+
+        public const int tls_prf_sha256 = 1;
+
+        /*
+         * Implied by RFC 5288
+         */
+        public const int tls_prf_sha384 = 2;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ProtocolVersion.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ProtocolVersion.cs
new file mode 100644
index 0000000..b0d5518
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ProtocolVersion.cs
@@ -0,0 +1,159 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public sealed class ProtocolVersion
+    {
+        public static readonly ProtocolVersion SSLv3 = new ProtocolVersion(0x0300, "SSL 3.0");
+        public static readonly ProtocolVersion TLSv10 = new ProtocolVersion(0x0301, "TLS 1.0");
+        public static readonly ProtocolVersion TLSv11 = new ProtocolVersion(0x0302, "TLS 1.1");
+        public static readonly ProtocolVersion TLSv12 = new ProtocolVersion(0x0303, "TLS 1.2");
+        public static readonly ProtocolVersion DTLSv10 = new ProtocolVersion(0xFEFF, "DTLS 1.0");
+        public static readonly ProtocolVersion DTLSv12 = new ProtocolVersion(0xFEFD, "DTLS 1.2");
+
+        private readonly int version;
+        private readonly String name;
+
+        private ProtocolVersion(int v, String name)
+        {
+            this.version = v & 0xffff;
+            this.name = name;
+        }
+
+        public int FullVersion
+        {
+            get { return version; }
+        }
+
+        public int MajorVersion
+        {
+            get { return version >> 8; }
+        }
+
+        public int MinorVersion
+        {
+            get { return version & 0xff; }
+        }
+
+        public bool IsDtls
+        {
+            get { return MajorVersion == 0xFE; }
+        }
+
+        public bool IsSsl
+        {
+            get { return this == SSLv3; }
+        }
+
+        public bool IsTls
+        {
+            get { return MajorVersion == 0x03; }
+        }
+
+        public ProtocolVersion GetEquivalentTLSVersion()
+        {
+            if (!IsDtls)
+            {
+                return this;
+            }
+            if (this == DTLSv10)
+            {
+                return TLSv11;
+            }
+            return TLSv12;
+        }
+
+        public bool IsEqualOrEarlierVersionOf(ProtocolVersion version)
+        {
+            if (MajorVersion != version.MajorVersion)
+            {
+                return false;
+            }
+            int diffMinorVersion = version.MinorVersion - MinorVersion;
+            return IsDtls ? diffMinorVersion <= 0 : diffMinorVersion >= 0;
+        }
+
+        public bool IsLaterVersionOf(ProtocolVersion version)
+        {
+            if (MajorVersion != version.MajorVersion)
+            {
+                return false;
+            }
+            int diffMinorVersion = version.MinorVersion - MinorVersion;
+            return IsDtls ? diffMinorVersion > 0 : diffMinorVersion < 0;
+        }
+
+        public override bool Equals(object other)
+        {
+            return this == other || (other is ProtocolVersion && Equals((ProtocolVersion)other));
+        }
+
+        public bool Equals(ProtocolVersion other)
+        {
+            return other != null && this.version == other.version;
+        }
+
+        public override int GetHashCode()
+        {
+            return version;
+        }
+
+        /// <exception cref="IOException"/>
+        public static ProtocolVersion Get(int major, int minor)
+        {
+            switch (major)
+            {
+                case 0x03:
+                {
+                    switch (minor)
+                    {
+                        case 0x00:
+                            return SSLv3;
+                        case 0x01:
+                            return TLSv10;
+                        case 0x02:
+                            return TLSv11;
+                        case 0x03:
+                            return TLSv12;
+                    }
+                    return GetUnknownVersion(major, minor, "TLS");
+                }
+                case 0xFE:
+                {
+                    switch (minor)
+                    {
+                        case 0xFF:
+                            return DTLSv10;
+                        case 0xFE:
+                            throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                        case 0xFD:
+                            return DTLSv12;
+                    }
+                    return GetUnknownVersion(major, minor, "DTLS");
+                }
+                default:
+                {
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+        }
+
+        public override string ToString()
+        {
+            return name;
+        }
+
+        private static ProtocolVersion GetUnknownVersion(int major, int minor, string prefix)
+        {
+            TlsUtilities.CheckUint8(major);
+            TlsUtilities.CheckUint8(minor);
+
+            int v = (major << 8) | minor;
+            String hex = Platform.ToUpperInvariant(Convert.ToString(0x10000 | v, 16).Substring(1));
+            return new ProtocolVersion(v, prefix + " 0x" + hex);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/PskTlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/PskTlsClient.cs
new file mode 100644
index 0000000..6063572
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/PskTlsClient.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class PskTlsClient
+        :   AbstractTlsClient
+    {
+        protected TlsPskIdentity mPskIdentity;
+
+        public PskTlsClient(TlsPskIdentity pskIdentity)
+            :   this(new DefaultTlsCipherFactory(), pskIdentity)
+        {
+        }
+
+        public PskTlsClient(TlsCipherFactory cipherFactory, TlsPskIdentity pskIdentity)
+            :   base(cipherFactory)
+        {
+            this.mPskIdentity = pskIdentity;
+        }
+
+        public override int[] GetCipherSuites()
+        {
+            return new int[]
+            {
+                CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+                CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
+                CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA
+            };
+        }
+
+        public override TlsKeyExchange GetKeyExchange()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+                return CreatePskKeyExchange(KeyExchangeAlgorithm.DHE_PSK);
+
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+                return CreatePskKeyExchange(KeyExchangeAlgorithm.ECDHE_PSK);
+
+            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+                return CreatePskKeyExchange(KeyExchangeAlgorithm.PSK);
+
+            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+                return CreatePskKeyExchange(KeyExchangeAlgorithm.RSA_PSK);
+
+            default:
+                /*
+                    * Note: internal error here; the TlsProtocol implementation verifies that the
+                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                    * we now can't produce an implementation, we shouldn't have offered it!
+                    */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override TlsCipher GetCipher()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CCM_8, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_CBC, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_128_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_CBC, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.CAMELLIA_256_GCM, MacAlgorithm.cls_null);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.ESTREAM_SALSA20, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha256);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.NULL, MacAlgorithm.hmac_sha384);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.RC4_128, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.SALSA20, MacAlgorithm.hmac_sha1);
+
+            default:
+                /*
+                    * Note: internal error here; the TlsProtocol implementation verifies that the
+                    * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                    * we now can't produce an implementation, we shouldn't have offered it!
+                    */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        protected virtual TlsKeyExchange CreatePskKeyExchange(int keyExchange)
+        {
+            return new TlsPskKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mPskIdentity, null, mNamedCurves,
+                mClientECPointFormats, mServerECPointFormats);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/RecordStream.cs b/BouncyCastle.AxCrypt/src/crypto/tls/RecordStream.cs
new file mode 100644
index 0000000..e5d0feb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/RecordStream.cs
@@ -0,0 +1,333 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>An implementation of the TLS 1.0/1.1/1.2 record layer, allowing downgrade to SSLv3.</summary>
+    internal class RecordStream
+    {
+        private const int DEFAULT_PLAINTEXT_LIMIT = (1 << 14);
+
+        private TlsProtocol mHandler;
+        private Stream mInput;
+        private Stream mOutput;
+        private TlsCompression mPendingCompression = null, mReadCompression = null, mWriteCompression = null;
+        private TlsCipher mPendingCipher = null, mReadCipher = null, mWriteCipher = null;
+        private long mReadSeqNo = 0, mWriteSeqNo = 0;
+        private MemoryStream mBuffer = new MemoryStream();
+
+        private TlsHandshakeHash mHandshakeHash = null;
+
+        private ProtocolVersion mReadVersion = null, mWriteVersion = null;
+        private bool mRestrictReadVersion = true;
+
+        private int mPlaintextLimit, mCompressedLimit, mCiphertextLimit;
+
+        internal RecordStream(TlsProtocol handler, Stream input, Stream output)
+        {
+            this.mHandler = handler;
+            this.mInput = input;
+            this.mOutput = output;
+            this.mReadCompression = new TlsNullCompression();
+            this.mWriteCompression = this.mReadCompression;
+        }
+
+        internal virtual void Init(TlsContext context)
+        {
+            this.mReadCipher = new TlsNullCipher(context);
+            this.mWriteCipher = this.mReadCipher;
+            this.mHandshakeHash = new DeferredHash();
+            this.mHandshakeHash.Init(context);
+
+            SetPlaintextLimit(DEFAULT_PLAINTEXT_LIMIT);
+        }
+
+        internal virtual int GetPlaintextLimit()
+        {
+            return mPlaintextLimit;
+        }
+
+        internal virtual void SetPlaintextLimit(int plaintextLimit)
+        {
+            this.mPlaintextLimit = plaintextLimit;
+            this.mCompressedLimit = this.mPlaintextLimit + 1024;
+            this.mCiphertextLimit = this.mCompressedLimit + 1024;
+        }
+
+        internal virtual ProtocolVersion ReadVersion
+        {
+            get { return mReadVersion; }
+            set { this.mReadVersion = value; }
+        }
+
+        internal virtual void SetWriteVersion(ProtocolVersion writeVersion)
+        {
+            this.mWriteVersion = writeVersion;
+        }
+
+        /**
+         * RFC 5246 E.1. "Earlier versions of the TLS specification were not fully clear on what the
+         * record layer version number (TLSPlaintext.version) should contain when sending ClientHello
+         * (i.e., before it is known which version of the protocol will be employed). Thus, TLS servers
+         * compliant with this specification MUST accept any value {03,XX} as the record layer version
+         * number for ClientHello."
+         */
+        internal virtual void SetRestrictReadVersion(bool enabled)
+        {
+            this.mRestrictReadVersion = enabled;
+        }
+
+        internal virtual void SetPendingConnectionState(TlsCompression tlsCompression, TlsCipher tlsCipher)
+        {
+            this.mPendingCompression = tlsCompression;
+            this.mPendingCipher = tlsCipher;
+        }
+
+        internal virtual void SentWriteCipherSpec()
+        {
+            if (mPendingCompression == null || mPendingCipher == null)
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
+            this.mWriteCompression = this.mPendingCompression;
+            this.mWriteCipher = this.mPendingCipher;
+            this.mWriteSeqNo = 0;
+        }
+
+        internal virtual void ReceivedReadCipherSpec()
+        {
+            if (mPendingCompression == null || mPendingCipher == null)
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
+            this.mReadCompression = this.mPendingCompression;
+            this.mReadCipher = this.mPendingCipher;
+            this.mReadSeqNo = 0;
+        }
+
+        internal virtual void FinaliseHandshake()
+        {
+            if (mReadCompression != mPendingCompression || mWriteCompression != mPendingCompression
+                || mReadCipher != mPendingCipher || mWriteCipher != mPendingCipher)
+            {
+                throw new TlsFatalAlert(AlertDescription.handshake_failure);
+            }
+            this.mPendingCompression = null;
+            this.mPendingCipher = null;
+        }
+
+        internal virtual bool ReadRecord()
+        {
+            byte[] recordHeader = TlsUtilities.ReadAllOrNothing(5, mInput);
+            if (recordHeader == null)
+                return false;
+
+            byte type = TlsUtilities.ReadUint8(recordHeader, 0);
+
+            /*
+             * RFC 5246 6. If a TLS implementation receives an unexpected record type, it MUST send an
+             * unexpected_message alert.
+             */
+            CheckType(type, AlertDescription.unexpected_message);
+
+            if (!mRestrictReadVersion)
+            {
+                int version = TlsUtilities.ReadVersionRaw(recordHeader, 1);
+                if ((version & 0xffffff00) != 0x0300)
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+            else
+            {
+                ProtocolVersion version = TlsUtilities.ReadVersion(recordHeader, 1);
+                if (mReadVersion == null)
+                {
+                    mReadVersion = version;
+                }
+                else if (!version.Equals(mReadVersion))
+                {
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+
+            int length = TlsUtilities.ReadUint16(recordHeader, 3);
+            byte[] plaintext = DecodeAndVerify(type, mInput, length);
+            mHandler.ProcessRecord(type, plaintext, 0, plaintext.Length);
+            return true;
+        }
+
+        internal virtual byte[] DecodeAndVerify(byte type, Stream input, int len)
+        {
+            CheckLength(len, mCiphertextLimit, AlertDescription.record_overflow);
+
+            byte[] buf = TlsUtilities.ReadFully(len, input);
+            byte[] decoded = mReadCipher.DecodeCiphertext(mReadSeqNo++, type, buf, 0, buf.Length);
+
+            CheckLength(decoded.Length, mCompressedLimit, AlertDescription.record_overflow);
+
+            /*
+             * TODO RFC5264 6.2.2. Implementation note: Decompression functions are responsible for
+             * ensuring that messages cannot cause internal buffer overflows.
+             */
+            Stream cOut = mReadCompression.Decompress(mBuffer);
+            if (cOut != mBuffer)
+            {
+                cOut.Write(decoded, 0, decoded.Length);
+                cOut.Flush();
+                decoded = GetBufferContents();
+            }
+
+            /*
+             * RFC 5264 6.2.2. If the decompression function encounters a TLSCompressed.fragment that
+             * would decompress to a length in excess of 2^14 bytes, it should report a fatal
+             * decompression failure error.
+             */
+            CheckLength(decoded.Length, mPlaintextLimit, AlertDescription.decompression_failure);
+
+            /*
+             * RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
+             * or ChangeCipherSpec content types.
+             */
+            if (decoded.Length < 1 && type != ContentType.application_data)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return decoded;
+        }
+
+        internal virtual void WriteRecord(byte type, byte[] plaintext, int plaintextOffset, int plaintextLength)
+        {
+            // Never send anything until a valid ClientHello has been received
+            if (mWriteVersion == null)
+                return;
+
+            /*
+             * RFC 5264 6. Implementations MUST NOT send record types not defined in this document
+             * unless negotiated by some extension.
+             */
+            CheckType(type, AlertDescription.internal_error);
+
+            /*
+             * RFC 5264 6.2.1 The length should not exceed 2^14.
+             */
+            CheckLength(plaintextLength, mPlaintextLimit, AlertDescription.internal_error);
+
+            /*
+             * RFC 5264 6.2.1 Implementations MUST NOT send zero-length fragments of Handshake, Alert,
+             * or ChangeCipherSpec content types.
+             */
+            if (plaintextLength < 1 && type != ContentType.application_data)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            if (type == ContentType.handshake)
+            {
+                UpdateHandshakeData(plaintext, plaintextOffset, plaintextLength);
+            }
+
+            Stream cOut = mWriteCompression.Compress(mBuffer);
+
+            byte[] ciphertext;
+            if (cOut == mBuffer)
+            {
+                ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, plaintext, plaintextOffset, plaintextLength);
+            }
+            else
+            {
+                cOut.Write(plaintext, plaintextOffset, plaintextLength);
+                cOut.Flush();
+                byte[] compressed = GetBufferContents();
+
+                /*
+                 * RFC5264 6.2.2. Compression must be lossless and may not increase the content length
+                 * by more than 1024 bytes.
+                 */
+                CheckLength(compressed.Length, plaintextLength + 1024, AlertDescription.internal_error);
+
+                ciphertext = mWriteCipher.EncodePlaintext(mWriteSeqNo++, type, compressed, 0, compressed.Length);
+            }
+
+            /*
+             * RFC 5264 6.2.3. The length may not exceed 2^14 + 2048.
+             */
+            CheckLength(ciphertext.Length, mCiphertextLimit, AlertDescription.internal_error);
+
+            byte[] record = new byte[ciphertext.Length + 5];
+            TlsUtilities.WriteUint8(type, record, 0);
+            TlsUtilities.WriteVersion(mWriteVersion, record, 1);
+            TlsUtilities.WriteUint16(ciphertext.Length, record, 3);
+            Array.Copy(ciphertext, 0, record, 5, ciphertext.Length);
+            mOutput.Write(record, 0, record.Length);
+            mOutput.Flush();
+        }
+
+        internal virtual void NotifyHelloComplete()
+        {
+            this.mHandshakeHash = mHandshakeHash.NotifyPrfDetermined();
+        }
+
+        internal virtual TlsHandshakeHash HandshakeHash
+        {
+            get { return mHandshakeHash; }
+        }
+
+        internal virtual TlsHandshakeHash PrepareToFinish()
+        {
+            TlsHandshakeHash result = mHandshakeHash;
+            this.mHandshakeHash = mHandshakeHash.StopTracking();
+            return result;
+        }
+
+        internal virtual void UpdateHandshakeData(byte[] message, int offset, int len)
+        {
+            mHandshakeHash.BlockUpdate(message, offset, len);
+        }
+
+        internal virtual void SafeClose()
+        {
+            try
+            {
+                mInput.Dispose();
+            }
+            catch (IOException)
+            {
+            }
+
+            try
+            {
+                mOutput.Dispose();
+            }
+            catch (IOException)
+            {
+            }
+        }
+
+        internal virtual void Flush()
+        {
+            mOutput.Flush();
+        }
+
+        private byte[] GetBufferContents()
+        {
+            byte[] contents = mBuffer.ToArray();
+            mBuffer.SetLength(0);
+            return contents;
+        }
+
+        private static void CheckType(byte type, byte alertDescription)
+        {
+            switch (type)
+            {
+            case ContentType.application_data:
+            case ContentType.alert:
+            case ContentType.change_cipher_spec:
+            case ContentType.handshake:
+            case ContentType.heartbeat:
+                break;
+            default:
+                throw new TlsFatalAlert(alertDescription);
+            }
+        }
+
+        private static void CheckLength(int length, int limit, byte alertDescription)
+        {
+            if (length > limit)
+                throw new TlsFatalAlert(alertDescription);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SecurityParameters.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SecurityParameters.cs
new file mode 100644
index 0000000..6a115a9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SecurityParameters.cs
@@ -0,0 +1,94 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class SecurityParameters
+    {
+        internal int entity = -1;
+        internal int cipherSuite = -1;
+        internal byte compressionAlgorithm = CompressionMethod.cls_null;
+        internal int prfAlgorithm = -1;
+        internal int verifyDataLength = -1;
+        internal byte[] masterSecret = null;
+        internal byte[] clientRandom = null;
+        internal byte[] serverRandom = null;
+
+        // TODO Keep these internal, since it's maybe not the ideal place for them
+        internal short maxFragmentLength = -1;
+        internal bool truncatedHMac = false;
+        internal bool encryptThenMac = false;
+
+        internal void CopySessionParametersFrom(SecurityParameters other)
+        {
+            this.entity = other.entity;
+            this.cipherSuite = other.cipherSuite;
+            this.compressionAlgorithm = other.compressionAlgorithm;
+            this.prfAlgorithm = other.prfAlgorithm;
+            this.verifyDataLength = other.verifyDataLength;
+            this.masterSecret = Arrays.Clone(other.masterSecret);
+        }
+
+        internal virtual void Clear()
+        {
+            if (this.masterSecret != null)
+            {
+                Arrays.Fill(this.masterSecret, (byte)0);
+                this.masterSecret = null;
+            }
+        }
+
+        /**
+         * @return {@link ConnectionEnd}
+         */
+        public virtual int Entity
+        {
+            get { return entity; }
+        }
+
+        /**
+         * @return {@link CipherSuite}
+         */
+        public virtual int CipherSuite
+        {
+            get { return cipherSuite; }
+        }
+
+        /**
+         * @return {@link CompressionMethod}
+         */
+        public byte CompressionAlgorithm
+        {
+            get { return compressionAlgorithm; }
+        }
+
+        /**
+         * @return {@link PRFAlgorithm}
+         */
+        public virtual int PrfAlgorithm
+        {
+            get { return prfAlgorithm; }
+        }
+
+        public virtual int VerifyDataLength
+        {
+            get { return verifyDataLength; }
+        }
+
+        public virtual byte[] MasterSecret
+        {
+            get { return masterSecret; }
+        }
+
+        public virtual byte[] ClientRandom
+        {
+            get { return clientRandom; }
+        }
+
+        public virtual byte[] ServerRandom
+        {
+            get { return serverRandom; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ServerDHParams.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ServerDHParams.cs
new file mode 100644
index 0000000..3818588
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ServerDHParams.cs
@@ -0,0 +1,60 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class ServerDHParams
+    {
+        protected readonly DHPublicKeyParameters mPublicKey;
+
+        public ServerDHParams(DHPublicKeyParameters publicKey)
+        {
+            if (publicKey == null)
+                throw new ArgumentNullException("publicKey");
+
+            this.mPublicKey = publicKey;
+        }
+
+        public virtual DHPublicKeyParameters PublicKey
+        {
+            get { return mPublicKey; }
+        }
+
+        /**
+         * Encode this {@link ServerDHParams} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            DHParameters dhParameters = mPublicKey.Parameters;
+            BigInteger Ys = mPublicKey.Y;
+
+            TlsDHUtilities.WriteDHParameter(dhParameters.P, output);
+            TlsDHUtilities.WriteDHParameter(dhParameters.G, output);
+            TlsDHUtilities.WriteDHParameter(Ys, output);
+        }
+
+        /**
+         * Parse a {@link ServerDHParams} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link ServerDHParams} object.
+         * @throws IOException
+         */
+        public static ServerDHParams Parse(Stream input)
+        {
+            BigInteger p = TlsDHUtilities.ReadDHParameter(input);
+            BigInteger g = TlsDHUtilities.ReadDHParameter(input);
+            BigInteger Ys = TlsDHUtilities.ReadDHParameter(input);
+
+            return new ServerDHParams(new DHPublicKeyParameters(Ys, new DHParameters(p, g)));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ServerName.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ServerName.cs
new file mode 100644
index 0000000..3d1e8f8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ServerName.cs
@@ -0,0 +1,105 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class ServerName
+    {
+        protected readonly byte mNameType;
+        protected readonly object mName;
+
+        public ServerName(byte nameType, object name)
+        {
+            if (!IsCorrectType(nameType, name))
+                throw new ArgumentException("not an instance of the correct type", "name");
+
+            this.mNameType = nameType;
+            this.mName = name;
+        }
+
+        public virtual byte NameType
+        {
+            get { return mNameType; }
+        }
+
+        public virtual object Name
+        {
+            get { return mName; }
+        }
+
+        public virtual string GetHostName()
+        {
+            if (!IsCorrectType(Tls.NameType.host_name, mName))
+                throw new InvalidOperationException("'name' is not a HostName string");
+
+            return (string)mName;
+        }
+
+        /**
+         * Encode this {@link ServerName} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(mNameType, output);
+
+            switch (mNameType)
+            {
+            case Tls.NameType.host_name:
+                byte[] utf8Encoding = Strings.ToUtf8ByteArray((string)mName);
+                if (utf8Encoding.Length < 1)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+                TlsUtilities.WriteOpaque16(utf8Encoding, output);
+                break;
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        /**
+         * Parse a {@link ServerName} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link ServerName} object.
+         * @throws IOException
+         */
+        public static ServerName Parse(Stream input)
+        {
+            byte name_type = TlsUtilities.ReadUint8(input);
+            object name;
+
+            switch (name_type)
+            {
+            case Tls.NameType.host_name:
+            {
+                byte[] utf8Encoding = TlsUtilities.ReadOpaque16(input);
+                if (utf8Encoding.Length < 1)
+                    throw new TlsFatalAlert(AlertDescription.decode_error);
+                name = Strings.FromUtf8ByteArray(utf8Encoding);
+                break;
+            }
+            default:
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            }
+
+            return new ServerName(name_type, name);
+        }
+
+        protected static bool IsCorrectType(byte nameType, object name)
+        {
+            switch (nameType)
+            {
+            case Tls.NameType.host_name:
+                return name is string;
+            default:
+                throw new ArgumentException("unsupported value", "name");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ServerNameList.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ServerNameList.cs
new file mode 100644
index 0000000..13da79b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ServerNameList.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class ServerNameList
+    {
+        protected readonly IList mServerNameList;
+
+        /**
+         * @param serverNameList an {@link IList} of {@link ServerName}.
+         */
+        public ServerNameList(IList serverNameList)
+        {
+            if (serverNameList == null || serverNameList.Count < 1)
+                throw new ArgumentException("must not be null or empty", "serverNameList");
+
+            this.mServerNameList = serverNameList;
+        }
+
+        /**
+         * @return an {@link IList} of {@link ServerName}.
+         */
+        public virtual IList ServerNames
+        {
+            get { return mServerNameList; }
+        }
+
+        /**
+         * Encode this {@link ServerNameList} to a {@link Stream}.
+         * 
+         * @param output
+         *            the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            MemoryStream buf = new MemoryStream();
+
+            foreach (ServerName entry in ServerNames)
+            {
+                entry.Encode(buf);
+            }
+
+            TlsUtilities.CheckUint16(buf.Length);
+            TlsUtilities.WriteUint16((int)buf.Length, output);
+            buf.WriteTo(output);
+        }
+
+        /**
+         * Parse a {@link ServerNameList} from a {@link Stream}.
+         * 
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link ServerNameList} object.
+         * @throws IOException
+         */
+        public static ServerNameList Parse(Stream input)
+        {
+            int length = TlsUtilities.ReadUint16(input);
+            if (length < 1)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            byte[] data = TlsUtilities.ReadFully(length, input);
+
+            MemoryStream buf = new MemoryStream(data, false);
+
+            IList server_name_list = Platform.CreateArrayList();
+            while (buf.Position < buf.Length)
+            {
+                ServerName entry = ServerName.Parse(buf);
+                server_name_list.Add(entry);
+            }
+
+            return new ServerNameList(server_name_list);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/ServerOnlyTlsAuthentication.cs b/BouncyCastle.AxCrypt/src/crypto/tls/ServerOnlyTlsAuthentication.cs
new file mode 100644
index 0000000..4858897
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/ServerOnlyTlsAuthentication.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class ServerOnlyTlsAuthentication
+        :   TlsAuthentication
+    {
+        public abstract void NotifyServerCertificate(Certificate serverCertificate);
+
+        public TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+        {
+            return null;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SessionParameters.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SessionParameters.cs
new file mode 100644
index 0000000..c4616ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SessionParameters.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public sealed class SessionParameters
+    {
+        public sealed class Builder
+        {
+            private int mCipherSuite = -1;
+            private short mCompressionAlgorithm = -1;
+            private byte[] mMasterSecret = null;
+            private Certificate mPeerCertificate = null;
+            private byte[] mEncodedServerExtensions = null;
+
+            public Builder()
+            {
+            }
+
+            public SessionParameters Build()
+            {
+                Validate(this.mCipherSuite >= 0, "cipherSuite");
+                Validate(this.mCompressionAlgorithm >= 0, "compressionAlgorithm");
+                Validate(this.mMasterSecret != null, "masterSecret");
+                return new SessionParameters(mCipherSuite, (byte)mCompressionAlgorithm, mMasterSecret, mPeerCertificate,
+                    mEncodedServerExtensions);
+            }
+
+            public Builder SetCipherSuite(int cipherSuite)
+            {
+                this.mCipherSuite = cipherSuite;
+                return this;
+            }
+
+            public Builder SetCompressionAlgorithm(byte compressionAlgorithm)
+            {
+                this.mCompressionAlgorithm = compressionAlgorithm;
+                return this;
+            }
+
+            public Builder SetMasterSecret(byte[] masterSecret)
+            {
+                this.mMasterSecret = masterSecret;
+                return this;
+            }
+
+            public Builder SetPeerCertificate(Certificate peerCertificate)
+            {
+                this.mPeerCertificate = peerCertificate;
+                return this;
+            }
+
+            public Builder SetServerExtensions(IDictionary serverExtensions)
+            {
+                if (serverExtensions == null)
+                {
+                    mEncodedServerExtensions = null;
+                }
+                else
+                {
+                    MemoryStream buf = new MemoryStream();
+                    TlsProtocol.WriteExtensions(buf, serverExtensions);
+                    mEncodedServerExtensions = buf.ToArray();
+                }
+                return this;
+            }
+
+            private void Validate(bool condition, string parameter)
+            {
+                if (!condition)
+                    throw new InvalidOperationException("Required session parameter '" + parameter + "' not configured");
+            }
+        }
+
+        private int mCipherSuite;
+        private byte mCompressionAlgorithm;
+        private byte[] mMasterSecret;
+        private Certificate mPeerCertificate;
+        private byte[] mEncodedServerExtensions;
+
+        private SessionParameters(int cipherSuite, byte compressionAlgorithm, byte[] masterSecret,
+            Certificate peerCertificate, byte[] encodedServerExtensions)
+        {
+            this.mCipherSuite = cipherSuite;
+            this.mCompressionAlgorithm = compressionAlgorithm;
+            this.mMasterSecret = Arrays.Clone(masterSecret);
+            this.mPeerCertificate = peerCertificate;
+            this.mEncodedServerExtensions = encodedServerExtensions;
+        }
+
+        public void Clear()
+        {
+            if (this.mMasterSecret != null)
+            {
+                Arrays.Fill(this.mMasterSecret, (byte)0);
+            }
+        }
+
+        public SessionParameters Copy()
+        {
+            return new SessionParameters(mCipherSuite, mCompressionAlgorithm, mMasterSecret, mPeerCertificate,
+                mEncodedServerExtensions);
+        }
+
+        public int CipherSuite
+        {
+            get { return mCipherSuite; }
+        }
+
+        public byte CompressionAlgorithm
+        {
+            get { return mCompressionAlgorithm; }
+        }
+
+        public byte[] MasterSecret
+        {
+            get { return mMasterSecret; }
+        }
+
+        public Certificate PeerCertificate
+        {
+            get { return mPeerCertificate; }
+        }
+
+        public IDictionary ReadServerExtensions()
+        {
+            if (mEncodedServerExtensions == null)
+                return null;
+
+            MemoryStream buf = new MemoryStream(mEncodedServerExtensions, false);
+            return TlsProtocol.ReadExtensions(buf);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAlgorithm.cs
new file mode 100644
index 0000000..35b9617
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAlgorithm.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 5246 7.4.1.4.1 (in RFC 2246, there were no specific values assigned)
+     */
+    public abstract class SignatureAlgorithm
+    {
+        public const byte anonymous = 0;
+        public const byte rsa = 1;
+        public const byte dsa = 2;
+        public const byte ecdsa = 3;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAndHashAlgorithm.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAndHashAlgorithm.cs
new file mode 100644
index 0000000..f74205b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SignatureAndHashAlgorithm.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 5246 7.4.1.4.1
+     */
+    public class SignatureAndHashAlgorithm
+    {
+        protected readonly byte mHash;
+        protected readonly byte mSignature;
+
+        /**
+         * @param hash      {@link HashAlgorithm}
+         * @param signature {@link SignatureAlgorithm}
+         */
+        public SignatureAndHashAlgorithm(byte hash, byte signature)
+        {
+            if (!TlsUtilities.IsValidUint8(hash))
+            {
+                throw new ArgumentException("should be a uint8", "hash");
+            }
+            if (!TlsUtilities.IsValidUint8(signature))
+            {
+                throw new ArgumentException("should be a uint8", "signature");
+            }
+            if (signature == SignatureAlgorithm.anonymous)
+            {
+                throw new ArgumentException("MUST NOT be \"anonymous\"", "signature");
+            }
+
+            this.mHash = hash;
+            this.mSignature = signature;
+        }
+
+        /**
+         * @return {@link HashAlgorithm}
+         */
+        public virtual byte Hash
+        {
+            get { return mHash; }
+        }
+
+        /**
+         * @return {@link SignatureAlgorithm}
+         */
+        public virtual byte Signature
+        {
+            get { return mSignature; }
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is SignatureAndHashAlgorithm))
+            {
+                return false;
+            }
+            SignatureAndHashAlgorithm other = (SignatureAndHashAlgorithm)obj;
+            return other.Hash == Hash && other.Signature == Signature;
+        }
+
+        public override int GetHashCode()
+        {
+            return ((int)Hash << 16) | (int)Signature;
+        }
+
+        /**
+         * Encode this {@link SignatureAndHashAlgorithm} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            TlsUtilities.WriteUint8(Hash, output);
+            TlsUtilities.WriteUint8(Signature, output);
+        }
+
+        /**
+         * Parse a {@link SignatureAndHashAlgorithm} from a {@link Stream}.
+         *
+         * @param input the {@link Stream} to parse from.
+         * @return a {@link SignatureAndHashAlgorithm} object.
+         * @throws IOException
+         */
+        public static SignatureAndHashAlgorithm Parse(Stream input)
+        {
+            byte hash = TlsUtilities.ReadUint8(input);
+            byte signature = TlsUtilities.ReadUint8(input);
+            return new SignatureAndHashAlgorithm(hash, signature);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SignerInputBuffer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SignerInputBuffer.cs
new file mode 100644
index 0000000..ef2827c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SignerInputBuffer.cs
@@ -0,0 +1,39 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class SignerInputBuffer
+        : MemoryStream
+    {
+        internal void UpdateSigner(ISigner s)
+        {
+            WriteTo(new SigStream(s));
+        }
+
+        private class SigStream
+            : BaseOutputStream
+        {
+            private readonly ISigner s;
+
+            internal SigStream(ISigner s)
+            {
+                this.s = s;
+            }
+
+            public override void WriteByte(byte b)
+            {
+                s.Update(b);
+            }
+
+            public override void Write(byte[] buf, int off, int len)
+            {
+                s.BlockUpdate(buf, off, len);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SrpTlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SrpTlsClient.cs
new file mode 100644
index 0000000..5d82ed4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SrpTlsClient.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class SrpTlsClient
+        :   AbstractTlsClient
+    {
+        protected byte[] mIdentity;
+        protected byte[] mPassword;
+
+        public SrpTlsClient(byte[] identity, byte[] password)
+            : this(new DefaultTlsCipherFactory(), identity, password)
+        {
+        }
+
+        public SrpTlsClient(TlsCipherFactory cipherFactory, byte[] identity, byte[] password)
+            :   base(cipherFactory)
+        {
+            this.mIdentity = Arrays.Clone(identity);
+            this.mPassword = Arrays.Clone(password);
+        }
+
+        protected virtual bool RequireSrpServerExtension
+        {
+            // No explicit guidance in RFC 5054; by default an (empty) extension from server is optional
+            get { return false; }
+        }
+
+        public override int[] GetCipherSuites()
+        {
+            return new int[]
+            {
+                CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
+            };
+        }
+
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+            TlsSrpUtilities.AddSrpExtension(clientExtensions, this.mIdentity);
+            return clientExtensions;
+        }
+
+        public override void ProcessServerExtensions(IDictionary serverExtensions)
+        {
+            if (!TlsUtilities.HasExpectedEmptyExtensionData(serverExtensions, ExtensionType.srp,
+                AlertDescription.illegal_parameter))
+            {
+                if (RequireSrpServerExtension)
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            base.ProcessServerExtensions(serverExtensions);
+        }
+
+        public override TlsKeyExchange GetKeyExchange()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP);
+
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_RSA);
+
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+                return CreateSrpKeyExchange(KeyExchangeAlgorithm.SRP_DSS);
+
+            default:
+                /*
+                 * Note: internal error here; the TlsProtocol implementation verifies that the
+                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                 * we now can't produce an implementation, we shouldn't have offered it!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override TlsCipher GetCipher()
+        {
+            switch (mSelectedCipherSuite)
+            {
+            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.cls_3DES_EDE_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_128_CBC, MacAlgorithm.hmac_sha1);
+
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+                return mCipherFactory.CreateCipher(mContext, EncryptionAlgorithm.AES_256_CBC, MacAlgorithm.hmac_sha1);
+
+            default:
+                /*
+                 * Note: internal error here; the TlsProtocol implementation verifies that the
+                 * server-selected cipher suite was in the list of client-offered cipher suites, so if
+                 * we now can't produce an implementation, we shouldn't have offered it!
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        protected virtual TlsKeyExchange CreateSrpKeyExchange(int keyExchange)
+        {
+            return new TlsSrpKeyExchange(keyExchange, mSupportedSignatureAlgorithms, mIdentity, mPassword);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SrtpProtectionProfile.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SrtpProtectionProfile.cs
new file mode 100644
index 0000000..1ce89f8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SrtpProtectionProfile.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class SrtpProtectionProfile
+    {
+        /*
+         * RFC 5764 4.1.2.
+         */
+        public const int SRTP_AES128_CM_HMAC_SHA1_80 = 0x0001;
+        public const int SRTP_AES128_CM_HMAC_SHA1_32 = 0x0002;
+        public const int SRTP_NULL_HMAC_SHA1_80 = 0x0005;
+        public const int SRTP_NULL_HMAC_SHA1_32 = 0x0006;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/Ssl3Mac.cs b/BouncyCastle.AxCrypt/src/crypto/tls/Ssl3Mac.cs
new file mode 100644
index 0000000..8bdb342
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/Ssl3Mac.cs
@@ -0,0 +1,110 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * HMAC implementation based on original internet draft for HMAC (RFC 2104)
+     * 
+     * The difference is that padding is concatentated versus XORed with the key
+     * 
+     * H(K + opad, H(K + ipad, text))
+     */
+    public class Ssl3Mac
+        : IMac
+    {
+        private const byte IPAD_BYTE = 0x36;
+        private const byte OPAD_BYTE = 0x5C;
+
+        internal static readonly byte[] IPAD = GenPad(IPAD_BYTE, 48);
+        internal static readonly byte[] OPAD = GenPad(OPAD_BYTE, 48);
+
+        private readonly IDigest digest;
+        private readonly int padLength;
+
+        private byte[] secret;
+
+        /**
+         * Base constructor for one of the standard digest algorithms that the byteLength of
+         * the algorithm is know for. Behaviour is undefined for digests other than MD5 or SHA1.
+         * 
+         * @param digest the digest.
+         */
+        public Ssl3Mac(IDigest digest)
+        {
+            this.digest = digest;
+
+            if (digest.GetDigestSize() == 20)
+            {
+                this.padLength = 40;
+            }
+            else
+            {
+                this.padLength = 48;
+            }
+        }
+
+        public virtual string AlgorithmName
+        {
+            get { return digest.AlgorithmName + "/SSL3MAC"; }
+        }
+
+        public virtual void Init(ICipherParameters parameters)
+        {
+            secret = Arrays.Clone(((KeyParameter)parameters).GetKey());
+
+            Reset();
+        }
+
+        public virtual int GetMacSize()
+        {
+            return digest.GetDigestSize();
+        }
+
+        public virtual void Update(byte input)
+        {
+            digest.Update(input);
+        }
+
+        public virtual void BlockUpdate(byte[] input, int inOff, int len)
+        {
+            digest.BlockUpdate(input, inOff, len);
+        }
+
+        public virtual int DoFinal(byte[] output, int outOff)
+        {
+            byte[] tmp = new byte[digest.GetDigestSize()];
+            digest.DoFinal(tmp, 0);
+
+            digest.BlockUpdate(secret, 0, secret.Length);
+            digest.BlockUpdate(OPAD, 0, padLength);
+            digest.BlockUpdate(tmp, 0, tmp.Length);
+
+            int len = digest.DoFinal(output, outOff);
+
+            Reset();
+
+            return len;
+        }
+
+        /**
+         * Reset the mac generator.
+         */
+        public virtual void Reset()
+        {
+            digest.Reset();
+            digest.BlockUpdate(secret, 0, secret.Length);
+            digest.BlockUpdate(IPAD, 0, padLength);
+        }
+
+        private static byte[] GenPad(byte b, int count)
+        {
+            byte[] padding = new byte[count];
+            Arrays.Fill(padding, b);
+            return padding;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataEntry.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataEntry.cs
new file mode 100644
index 0000000..5adc4fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataEntry.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class SupplementalDataEntry
+    {
+        protected readonly int mDataType;
+        protected readonly byte[] mData;
+
+        public SupplementalDataEntry(int dataType, byte[] data)
+        {
+            this.mDataType = dataType;
+            this.mData = data;
+        }
+
+        public virtual int DataType
+        {
+            get { return mDataType; }
+        }
+
+        public virtual byte[] Data
+        {
+            get { return mData; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataType.cs
new file mode 100644
index 0000000..79511c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/SupplementalDataType.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>RFC 4680</summary>
+    public abstract class SupplementalDataType
+    {
+        /*
+         * RFC 4681
+         */
+        public const int user_mapping_data = 0;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsAeadCipher.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAeadCipher.cs
new file mode 100644
index 0000000..951e866
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAeadCipher.cs
@@ -0,0 +1,189 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsAeadCipher
+        :   TlsCipher
+    {
+        protected readonly TlsContext context;
+        protected readonly int macSize;
+        protected readonly int nonce_explicit_length;
+
+        protected readonly IAeadBlockCipher encryptCipher;
+        protected readonly IAeadBlockCipher decryptCipher;
+
+        protected readonly byte[] encryptImplicitNonce, decryptImplicitNonce;
+
+        /// <exception cref="IOException"></exception>
+        public TlsAeadCipher(TlsContext context, IAeadBlockCipher clientWriteCipher, IAeadBlockCipher serverWriteCipher,
+            int cipherKeySize, int macSize)
+        {
+            if (!TlsUtilities.IsTlsV12(context))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.context = context;
+            this.macSize = macSize;
+
+            // NOTE: Valid for RFC 5288/6655 ciphers but may need review for other AEAD ciphers
+            this.nonce_explicit_length = 8;
+
+            // TODO SecurityParameters.fixed_iv_length
+            int fixed_iv_length = 4;
+
+            int key_block_size = (2 * cipherKeySize) + (2 * fixed_iv_length);
+
+            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
+
+            int offset = 0;
+
+            KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            byte[] client_write_IV = Arrays.CopyOfRange(key_block, offset, offset + fixed_iv_length);
+            offset += fixed_iv_length;
+            byte[] server_write_IV = Arrays.CopyOfRange(key_block, offset, offset + fixed_iv_length);
+            offset += fixed_iv_length;
+
+            if (offset != key_block_size)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            KeyParameter encryptKey, decryptKey;
+            if (context.IsServer)
+            {
+                this.encryptCipher = serverWriteCipher;
+                this.decryptCipher = clientWriteCipher;
+                this.encryptImplicitNonce = server_write_IV;
+                this.decryptImplicitNonce = client_write_IV;
+                encryptKey = server_write_key;
+                decryptKey = client_write_key;
+            }
+            else
+            {
+                this.encryptCipher = clientWriteCipher;
+                this.decryptCipher = serverWriteCipher;
+                this.encryptImplicitNonce = client_write_IV;
+                this.decryptImplicitNonce = server_write_IV;
+                encryptKey = client_write_key;
+                decryptKey = server_write_key;
+            }
+
+            byte[] dummyNonce = new byte[fixed_iv_length + nonce_explicit_length];
+
+            this.encryptCipher.Init(true, new AeadParameters(encryptKey, 8 * macSize, dummyNonce));
+            this.decryptCipher.Init(false, new AeadParameters(decryptKey, 8 * macSize, dummyNonce));
+        }
+
+        public virtual int GetPlaintextLimit(int ciphertextLimit)
+        {
+            // TODO We ought to be able to ask the decryptCipher (independently of it's current state!)
+            return ciphertextLimit - macSize - nonce_explicit_length;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
+        {
+            byte[] nonce = new byte[this.encryptImplicitNonce.Length + nonce_explicit_length];
+            Array.Copy(encryptImplicitNonce, 0, nonce, 0, encryptImplicitNonce.Length);
+
+            /*
+             * RFC 5288/6655 The nonce_explicit MAY be the 64-bit sequence number.
+             * 
+             * (May need review for other AEAD ciphers).
+             */
+            TlsUtilities.WriteUint64(seqNo, nonce, encryptImplicitNonce.Length);
+
+            int plaintextOffset = offset;
+            int plaintextLength = len;
+            int ciphertextLength = encryptCipher.GetOutputSize(plaintextLength);
+
+            byte[] output = new byte[nonce_explicit_length + ciphertextLength];
+            Array.Copy(nonce, encryptImplicitNonce.Length, output, 0, nonce_explicit_length);
+            int outputPos = nonce_explicit_length;
+
+            byte[] additionalData = GetAdditionalData(seqNo, type, plaintextLength);
+            AeadParameters parameters = new AeadParameters(null, 8 * macSize, nonce, additionalData);
+
+            try
+            {
+                encryptCipher.Init(true, parameters);
+                outputPos += encryptCipher.ProcessBytes(plaintext, plaintextOffset, plaintextLength, output, outputPos);
+                outputPos += encryptCipher.DoFinal(output, outputPos);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
+
+            if (outputPos != output.Length)
+            {
+                // NOTE: Existing AEAD cipher implementations all give exact output lengths
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            return output;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
+        {
+            if (GetPlaintextLimit(len) < 0)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            byte[] nonce = new byte[this.decryptImplicitNonce.Length + nonce_explicit_length];
+            Array.Copy(decryptImplicitNonce, 0, nonce, 0, decryptImplicitNonce.Length);
+            Array.Copy(ciphertext, offset, nonce, decryptImplicitNonce.Length, nonce_explicit_length);
+
+            int ciphertextOffset = offset + nonce_explicit_length;
+            int ciphertextLength = len - nonce_explicit_length;
+            int plaintextLength = decryptCipher.GetOutputSize(ciphertextLength);
+
+            byte[] output = new byte[plaintextLength];
+            int outputPos = 0;
+
+            byte[] additionalData = GetAdditionalData(seqNo, type, plaintextLength);
+            AeadParameters parameters = new AeadParameters(null, 8 * macSize, nonce, additionalData);
+
+            try
+            {
+                decryptCipher.Init(false, parameters);
+                outputPos += decryptCipher.ProcessBytes(ciphertext, ciphertextOffset, ciphertextLength, output, outputPos);
+                outputPos += decryptCipher.DoFinal(output, outputPos);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.bad_record_mac, e);
+            }
+
+            if (outputPos != output.Length)
+            {
+                // NOTE: Existing AEAD cipher implementations all give exact output lengths
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            return output;
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual byte[] GetAdditionalData(long seqNo, byte type, int len)
+        {
+            /*
+             * additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
+             * TLSCompressed.length
+             */
+
+            byte[] additional_data = new byte[13];
+            TlsUtilities.WriteUint64(seqNo, additional_data, 0);
+            TlsUtilities.WriteUint8(type, additional_data, 8);
+            TlsUtilities.WriteVersion(context.ServerVersion, additional_data, 9);
+            TlsUtilities.WriteUint16(len, additional_data, 11);
+
+            return additional_data;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsAgreementCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAgreementCredentials.cs
new file mode 100644
index 0000000..7c64072
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAgreementCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsAgreementCredentials
+        :   TlsCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        byte[] GenerateAgreement(AsymmetricKeyParameter peerPublicKey);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsAuthentication.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAuthentication.cs
new file mode 100644
index 0000000..9aea5e4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsAuthentication.cs
@@ -0,0 +1,31 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public interface TlsAuthentication
+	{
+		/// <summary>
+		/// Called by the protocol handler to report the server certificate.
+		/// </summary>
+		/// <remarks>
+		/// This method is responsible for certificate verification and validation
+		/// </remarks>
+		/// <param name="serverCertificate">The server <see cref="Certificate"/> received</param>
+		/// <exception cref="IOException"></exception>
+		void NotifyServerCertificate(Certificate serverCertificate);
+
+		/// <summary>
+		/// Return client credentials in response to server's certificate request
+		/// </summary>
+		/// <param name="certificateRequest">
+		/// A <see cref="CertificateRequest"/> containing server certificate request details
+		/// </param>
+		/// <returns>
+		/// A <see cref="TlsCredentials"/> to be used for client authentication
+		/// (or <c>null</c> for no client authentication)
+		/// </returns>
+		/// <exception cref="IOException"></exception>
+		TlsCredentials GetClientCredentials(CertificateRequest certificateRequest);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsBlockCipher.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsBlockCipher.cs
new file mode 100644
index 0000000..82c0318
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsBlockCipher.cs
@@ -0,0 +1,378 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// A generic TLS 1.0-1.2 / SSLv3 block cipher. This can be used for AES or 3DES for example.
+    /// </summary>
+    public class TlsBlockCipher
+        :   TlsCipher
+    {
+        protected readonly TlsContext context;
+        protected readonly byte[] randomData;
+        protected readonly bool useExplicitIV;
+        protected readonly bool encryptThenMac;
+
+        protected readonly IBlockCipher encryptCipher;
+        protected readonly IBlockCipher decryptCipher;
+
+        protected readonly TlsMac mWriteMac;
+        protected readonly TlsMac mReadMac;
+
+        public virtual TlsMac WriteMac
+        {
+            get { return mWriteMac; }
+        }
+
+        public virtual TlsMac ReadMac
+        {
+            get { return mReadMac; }
+        }
+
+        /// <exception cref="IOException"></exception>
+        public TlsBlockCipher(TlsContext context, IBlockCipher clientWriteCipher, IBlockCipher serverWriteCipher,
+            IDigest clientWriteDigest, IDigest serverWriteDigest, int cipherKeySize)
+        {
+            this.context = context;
+
+            this.randomData = new byte[256];
+            context.NonceRandomGenerator.NextBytes(randomData);
+
+            this.useExplicitIV = TlsUtilities.IsTlsV11(context);
+            this.encryptThenMac = context.SecurityParameters.encryptThenMac;
+
+            int key_block_size = (2 * cipherKeySize) + clientWriteDigest.GetDigestSize()
+                + serverWriteDigest.GetDigestSize();
+
+            // From TLS 1.1 onwards, block ciphers don't need client_write_IV
+            if (!useExplicitIV)
+            {
+                key_block_size += clientWriteCipher.GetBlockSize() + serverWriteCipher.GetBlockSize();
+            }
+
+            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
+
+            int offset = 0;
+
+            TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+                clientWriteDigest.GetDigestSize());
+            offset += clientWriteDigest.GetDigestSize();
+            TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+                serverWriteDigest.GetDigestSize());
+            offset += serverWriteDigest.GetDigestSize();
+
+            KeyParameter client_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            KeyParameter server_write_key = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+
+            byte[] client_write_IV, server_write_IV;
+            if (useExplicitIV)
+            {
+                client_write_IV = new byte[clientWriteCipher.GetBlockSize()];
+                server_write_IV = new byte[serverWriteCipher.GetBlockSize()];
+            }
+            else
+            {
+                client_write_IV = Arrays.CopyOfRange(key_block, offset, offset + clientWriteCipher.GetBlockSize());
+                offset += clientWriteCipher.GetBlockSize();
+                server_write_IV = Arrays.CopyOfRange(key_block, offset, offset + serverWriteCipher.GetBlockSize());
+                offset += serverWriteCipher.GetBlockSize();
+            }
+
+            if (offset != key_block_size)
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            ICipherParameters encryptParams, decryptParams;
+            if (context.IsServer)
+            {
+                this.mWriteMac = serverWriteMac;
+                this.mReadMac = clientWriteMac;
+                this.encryptCipher = serverWriteCipher;
+                this.decryptCipher = clientWriteCipher;
+                encryptParams = new ParametersWithIV(server_write_key, server_write_IV);
+                decryptParams = new ParametersWithIV(client_write_key, client_write_IV);
+            }
+            else
+            {
+                this.mWriteMac = clientWriteMac;
+                this.mReadMac = serverWriteMac;
+                this.encryptCipher = clientWriteCipher;
+                this.decryptCipher = serverWriteCipher;
+                encryptParams = new ParametersWithIV(client_write_key, client_write_IV);
+                decryptParams = new ParametersWithIV(server_write_key, server_write_IV);
+            }
+
+            this.encryptCipher.Init(true, encryptParams);
+            this.decryptCipher.Init(false, decryptParams);
+        }
+
+        public virtual int GetPlaintextLimit(int ciphertextLimit)
+        {
+            int blockSize = encryptCipher.GetBlockSize();
+            int macSize = mWriteMac.Size;
+
+            int plaintextLimit = ciphertextLimit;
+
+            // An explicit IV consumes 1 block
+            if (useExplicitIV)
+            {
+                plaintextLimit -= blockSize;
+            }
+
+            // Leave room for the MAC, and require block-alignment
+            if (encryptThenMac)
+            {
+                plaintextLimit -= macSize;
+                plaintextLimit -= plaintextLimit % blockSize;
+            }
+            else
+            {
+                plaintextLimit -= plaintextLimit % blockSize;
+                plaintextLimit -= macSize;
+            }
+
+            // Minimum 1 byte of padding
+            --plaintextLimit;
+
+            return plaintextLimit;
+        }
+
+        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
+        {
+            int blockSize = encryptCipher.GetBlockSize();
+            int macSize = mWriteMac.Size;
+
+            ProtocolVersion version = context.ServerVersion;
+
+            int enc_input_length = len;
+            if (!encryptThenMac)
+            {
+                enc_input_length += macSize;
+            }
+
+            int padding_length = blockSize - 1 - (enc_input_length % blockSize);
+
+            // TODO[DTLS] Consider supporting in DTLS (without exceeding send limit though)
+            if (!version.IsDtls && !version.IsSsl)
+            {
+                // Add a random number of extra blocks worth of padding
+                int maxExtraPadBlocks = (255 - padding_length) / blockSize;
+                int actualExtraPadBlocks = ChooseExtraPadBlocks(context.SecureRandom, maxExtraPadBlocks);
+                padding_length += actualExtraPadBlocks * blockSize;
+            }
+
+            int totalSize = len + macSize + padding_length + 1;
+            if (useExplicitIV)
+            {
+                totalSize += blockSize;
+            }
+
+            byte[] outBuf = new byte[totalSize];
+            int outOff = 0;
+
+            if (useExplicitIV)
+            {
+                byte[] explicitIV = new byte[blockSize];
+                context.NonceRandomGenerator.NextBytes(explicitIV);
+
+                encryptCipher.Init(true, new ParametersWithIV(null, explicitIV));
+
+                Array.Copy(explicitIV, 0, outBuf, outOff, blockSize);
+                outOff += blockSize;
+            }
+
+            int blocks_start = outOff;
+
+            Array.Copy(plaintext, offset, outBuf, outOff, len);
+            outOff += len;
+
+            if (!encryptThenMac)
+            {
+                byte[] mac = mWriteMac.CalculateMac(seqNo, type, plaintext, offset, len);
+                Array.Copy(mac, 0, outBuf, outOff, mac.Length);
+                outOff += mac.Length;
+            }
+
+            for (int i = 0; i <= padding_length; i++)
+            {
+                outBuf[outOff++] = (byte)padding_length;
+            }
+
+            for (int i = blocks_start; i < outOff; i += blockSize)
+            {
+                encryptCipher.ProcessBlock(outBuf, i, outBuf, i);
+            }
+
+            if (encryptThenMac)
+            {
+                byte[] mac = mWriteMac.CalculateMac(seqNo, type, outBuf, 0, outOff);
+                Array.Copy(mac, 0, outBuf, outOff, mac.Length);
+                outOff += mac.Length;
+            }
+
+    //        assert outBuf.length == outOff;
+
+            return outBuf;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
+        {
+            int blockSize = decryptCipher.GetBlockSize();
+            int macSize = mReadMac.Size;
+
+            int minLen = blockSize;
+            if (encryptThenMac)
+            {
+                minLen += macSize;
+            }
+            else
+            {
+                minLen = System.Math.Max(minLen, macSize + 1);
+            }
+
+            if (useExplicitIV)
+            {
+                minLen += blockSize;
+            }
+
+            if (len < minLen)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int blocks_length = len;
+            if (encryptThenMac)
+            {
+                blocks_length -= macSize;
+            }
+
+            if (blocks_length % blockSize != 0)
+                throw new TlsFatalAlert(AlertDescription.decryption_failed);
+
+            if (encryptThenMac)
+            {
+                int end = offset + len;
+                byte[] receivedMac = Arrays.CopyOfRange(ciphertext, end - macSize, end);
+                byte[] calculatedMac = mReadMac.CalculateMac(seqNo, type, ciphertext, offset, len - macSize);
+
+                bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);
+
+                if (badMac)
+                    throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+            }
+
+            if (useExplicitIV)
+            {
+                decryptCipher.Init(false, new ParametersWithIV(null, ciphertext, offset, blockSize));
+
+                offset += blockSize;
+                blocks_length -= blockSize;
+            }
+
+            for (int i = 0; i < blocks_length; i += blockSize)
+            {
+                decryptCipher.ProcessBlock(ciphertext, offset + i, ciphertext, offset + i);
+            }
+
+            // If there's anything wrong with the padding, this will return zero
+            int totalPad = CheckPaddingConstantTime(ciphertext, offset, blocks_length, blockSize, encryptThenMac ? 0 : macSize);
+
+            int dec_output_length = blocks_length - totalPad;
+
+            if (!encryptThenMac)
+            {
+                dec_output_length -= macSize;
+                int macInputLen = dec_output_length;
+                int macOff = offset + macInputLen;
+                byte[] receivedMac = Arrays.CopyOfRange(ciphertext, macOff, macOff + macSize);
+                byte[] calculatedMac = mReadMac.CalculateMacConstantTime(seqNo, type, ciphertext, offset, macInputLen,
+                    blocks_length - macSize, randomData);
+
+                bool badMac = !Arrays.ConstantTimeAreEqual(calculatedMac, receivedMac);
+
+                if (badMac || totalPad == 0)
+                {
+                    throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+                }
+            }
+
+            return Arrays.CopyOfRange(ciphertext, offset, offset + dec_output_length);
+        }
+
+        protected virtual int CheckPaddingConstantTime(byte[] buf, int off, int len, int blockSize, int macSize)
+        {
+            int end = off + len;
+            byte lastByte = buf[end - 1];
+            int padlen = lastByte & 0xff;
+            int totalPad = padlen + 1;
+
+            int dummyIndex = 0;
+            byte padDiff = 0;
+
+            if ((TlsUtilities.IsSsl(context) && totalPad > blockSize) || (macSize + totalPad > len))
+            {
+                totalPad = 0;
+            }
+            else
+            {
+                int padPos = end - totalPad;
+                do
+                {
+                    padDiff |= (byte)(buf[padPos++] ^ lastByte);
+                }
+                while (padPos < end);
+
+                dummyIndex = totalPad;
+
+                if (padDiff != 0)
+                {
+                    totalPad = 0;
+                }
+            }
+
+            // Run some extra dummy checks so the number of checks is always constant
+            {
+                byte[] dummyPad = randomData;
+                while (dummyIndex < 256)
+                {
+                    padDiff |= (byte)(dummyPad[dummyIndex++] ^ lastByte);
+                }
+                // Ensure the above loop is not eliminated
+                dummyPad[0] ^= padDiff;
+            }
+
+            return totalPad;
+        }
+
+        protected virtual int ChooseExtraPadBlocks(SecureRandom r, int max)
+        {
+            // return r.NextInt(max + 1);
+
+            int x = r.NextInt();
+            int n = LowestBitSet(x);
+            return System.Math.Min(n, max);
+        }
+
+        protected virtual int LowestBitSet(int x)
+        {
+            if (x == 0)
+                return 32;
+
+            uint ux = (uint)x;
+            int n = 0;
+            while ((ux & 1U) == 0)
+            {
+                ++n;
+                ux >>= 1;
+            }
+            return n;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipher.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipher.cs
new file mode 100644
index 0000000..7bd8573
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipher.cs
@@ -0,0 +1,16 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsCipher
+    {
+        int GetPlaintextLimit(int ciphertextLimit);
+
+        /// <exception cref="IOException"></exception>
+        byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len);
+
+        /// <exception cref="IOException"></exception>
+        byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipherFactory.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipherFactory.cs
new file mode 100644
index 0000000..4e1fe0e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCipherFactory.cs
@@ -0,0 +1,11 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsCipherFactory
+    {
+        /// <exception cref="IOException"></exception>
+        TlsCipher CreateCipher(TlsContext context, int encryptionAlgorithm, int macAlgorithm);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsClient.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClient.cs
new file mode 100644
index 0000000..cd5dfad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClient.cs
@@ -0,0 +1,134 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsClient
+        :   TlsPeer
+    {
+        /// <summary>
+        /// Called at the start of a new TLS session, before any other methods.
+        /// </summary>
+        /// <param name="context">
+        /// A <see cref="TlsProtocolHandler"/>
+        /// </param>
+        void Init(TlsClientContext context);
+
+        /// <summary>Return the session this client wants to resume, if any.</summary>
+        /// <remarks>Note that the peer's certificate chain for the session (if any) may need to be periodically revalidated.</remarks>
+        /// <returns>
+        /// A <see cref="TlsSession"/> representing the resumable session to be used for this connection,
+        /// or null to use a new session.
+        /// </returns>
+        TlsSession GetSessionToResume();
+
+        ProtocolVersion ClientHelloRecordLayerVersion { get; }
+
+        ProtocolVersion ClientVersion { get; }
+
+        /// <summary>
+        /// Get the list of cipher suites that this client supports.
+        /// </summary>
+        /// <returns>
+        /// An array of <see cref="CipherSuite"/> values, each specifying a supported cipher suite.
+        /// </returns>
+        int[] GetCipherSuites();
+
+        /// <summary>
+        /// Get the list of compression methods that this client supports.
+        /// </summary>
+        /// <returns>
+        /// An array of <see cref="CompressionMethod"/> values, each specifying a supported compression method.
+        /// </returns>
+        byte[] GetCompressionMethods();
+
+        /// <summary>
+        /// Get the (optional) table of client extensions to be included in (extended) client hello.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="IDictionary"/> (Int32 -> byte[]). May be null.
+        /// </returns>
+        /// <exception cref="IOException"></exception>
+        IDictionary GetClientExtensions();
+
+        /// <exception cref="IOException"></exception>
+        void NotifyServerVersion(ProtocolVersion selectedVersion);
+
+        /// <summary>
+        /// Notifies the client of the session_id sent in the ServerHello.
+        /// </summary>
+        /// <param name="sessionID">An array of <see cref="System.Byte"/></param>
+        void NotifySessionID(byte[] sessionID);
+
+        /// <summary>
+        /// Report the cipher suite that was selected by the server.
+        /// </summary>
+        /// <remarks>
+        /// The protocol handler validates this value against the offered cipher suites
+        /// <seealso cref="GetCipherSuites"/>
+        /// </remarks>
+        /// <param name="selectedCipherSuite">
+        /// A <see cref="CipherSuite"/>
+        /// </param>
+        void NotifySelectedCipherSuite(int selectedCipherSuite);
+
+        /// <summary>
+        /// Report the compression method that was selected by the server.
+        /// </summary>
+        /// <remarks>
+        /// The protocol handler validates this value against the offered compression methods
+        /// <seealso cref="GetCompressionMethods"/>
+        /// </remarks>
+        /// <param name="selectedCompressionMethod">
+        /// A <see cref="CompressionMethod"/>
+        /// </param>
+        void NotifySelectedCompressionMethod(byte selectedCompressionMethod);
+
+        /// <summary>
+        /// Report the extensions from an extended server hello.
+        /// </summary>
+        /// <remarks>
+        /// Will only be called if we returned a non-null result from <see cref="GetClientExtensions"/>.
+        /// </remarks>
+        /// <param name="serverExtensions">
+        /// A <see cref="IDictionary"/>  (Int32 -> byte[])
+        /// </param>
+        void ProcessServerExtensions(IDictionary serverExtensions);
+
+        /// <param name="serverSupplementalData">A <see cref="IList">list</see> of <see cref="SupplementalDataEntry"/></param>
+        /// <exception cref="IOException"/>
+        void ProcessServerSupplementalData(IList serverSupplementalData);
+
+        /// <summary>
+        /// Return an implementation of <see cref="TlsKeyExchange"/> to negotiate the key exchange
+        /// part of the protocol.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="TlsKeyExchange"/>
+        /// </returns>
+        /// <exception cref="IOException"/>
+        TlsKeyExchange GetKeyExchange();
+
+        /// <summary>
+        /// Return an implementation of <see cref="TlsAuthentication"/> to handle authentication
+        /// part of the protocol.
+        /// </summary>
+        /// <exception cref="IOException"/>
+        TlsAuthentication GetAuthentication();
+
+        /// <returns>A <see cref="IList">list</see> of <see cref="SupplementalDataEntry"/></returns>
+        /// <exception cref="IOException"/>
+        IList GetClientSupplementalData();
+
+        /// <summary>RFC 5077 3.3. NewSessionTicket Handshake Message</summary>
+        /// <remarks>
+        /// This method will be called (only) when a NewSessionTicket handshake message is received. The
+        /// ticket is opaque to the client and clients MUST NOT examine the ticket under the assumption
+        /// that it complies with e.g. <i>RFC 5077 4. Recommended Ticket Construction</i>.
+        /// </remarks>
+        /// <param name="newSessionTicket">The <see cref="NewSessionTicket">ticket</see></param>
+        /// <exception cref="IOException"/>
+        void NotifyNewSessionTicket(NewSessionTicket newSessionTicket);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContext.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContext.cs
new file mode 100644
index 0000000..b077d0a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContext.cs
@@ -0,0 +1,11 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsClientContext
+        :   TlsContext
+    {
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContextImpl.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContextImpl.cs
new file mode 100644
index 0000000..674d689
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientContextImpl.cs
@@ -0,0 +1,20 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class TlsClientContextImpl
+        :   AbstractTlsContext, TlsClientContext
+    {
+        internal TlsClientContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+            :   base(secureRandom, securityParameters)
+        {
+        }
+
+        public override bool IsServer
+        {
+            get { return false; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientProtocol.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientProtocol.cs
new file mode 100644
index 0000000..e48c92d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsClientProtocol.cs
@@ -0,0 +1,861 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsClientProtocol
+        :   TlsProtocol
+    {
+        protected TlsClient mTlsClient = null;
+        internal TlsClientContextImpl mTlsClientContext = null;
+
+        protected byte[] mSelectedSessionID = null;
+
+        protected TlsKeyExchange mKeyExchange = null;
+        protected TlsAuthentication mAuthentication = null;
+
+        protected CertificateStatus mCertificateStatus = null;
+        protected CertificateRequest mCertificateRequest = null;
+
+        public TlsClientProtocol(Stream stream, SecureRandom secureRandom)
+            :   base(stream, secureRandom)
+        {
+        }
+
+        public TlsClientProtocol(Stream input, Stream output, SecureRandom secureRandom)
+            :   base(input, output, secureRandom)
+        {
+        }
+
+        /**
+         * Initiates a TLS handshake in the role of client
+         *
+         * @param tlsClient The {@link TlsClient} to use for the handshake.
+         * @throws IOException If handshake was not successful.
+         */
+        public virtual void Connect(TlsClient tlsClient)
+        {
+            if (tlsClient == null)
+                throw new ArgumentNullException("tlsClient");
+            if (this.mTlsClient != null)
+                throw new InvalidOperationException("'Connect' can only be called once");
+
+            this.mTlsClient = tlsClient;
+
+            this.mSecurityParameters = new SecurityParameters();
+            this.mSecurityParameters.entity = ConnectionEnd.client;
+
+            this.mTlsClientContext = new TlsClientContextImpl(mSecureRandom, mSecurityParameters);
+
+            this.mSecurityParameters.clientRandom = CreateRandomBlock(tlsClient.ShouldUseGmtUnixTime(),
+                mTlsClientContext.NonceRandomGenerator);
+
+            this.mTlsClient.Init(mTlsClientContext);
+            this.mRecordStream.Init(mTlsClientContext);
+
+            TlsSession sessionToResume = tlsClient.GetSessionToResume();
+            if (sessionToResume != null)
+            {
+                SessionParameters sessionParameters = sessionToResume.ExportSessionParameters();
+                if (sessionParameters != null)
+                {
+                    this.mTlsSession = sessionToResume;
+                    this.mSessionParameters = sessionParameters;
+                }
+            }
+
+            SendClientHelloMessage();
+            this.mConnectionState = CS_CLIENT_HELLO;
+
+            CompleteHandshake();
+        }
+
+        protected override void CleanupHandshake()
+        {
+            base.CleanupHandshake();
+
+            this.mSelectedSessionID = null;
+            this.mKeyExchange = null;
+            this.mAuthentication = null;
+            this.mCertificateStatus = null;
+            this.mCertificateRequest = null;
+        }
+
+        protected override TlsContext Context
+        {
+            get { return mTlsClientContext; }
+        }
+
+        internal override AbstractTlsContext ContextAdmin
+        {
+            get { return mTlsClientContext; }
+        }
+
+        protected override TlsPeer Peer
+        {
+            get { return mTlsClient; }
+        }
+
+        protected override void HandleHandshakeMessage(byte type, byte[] data)
+        {
+            MemoryStream buf = new MemoryStream(data, false);
+
+            if (this.mResumedSession)
+            {
+                if (type != HandshakeType.finished || this.mConnectionState != CS_SERVER_HELLO)
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                ProcessFinishedMessage(buf);
+                this.mConnectionState = CS_SERVER_FINISHED;
+
+                SendFinishedMessage();
+                this.mConnectionState = CS_CLIENT_FINISHED;
+                this.mConnectionState = CS_END;
+
+                return;
+            }
+
+            switch (type)
+            {
+            case HandshakeType.certificate:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO:
+                case CS_SERVER_SUPPLEMENTAL_DATA:
+                {
+                    if (this.mConnectionState == CS_SERVER_HELLO)
+                    {
+                        HandleSupplementalData(null);
+                    }
+
+                    // Parse the Certificate message and Send to cipher suite
+
+                    this.mPeerCertificate = Certificate.Parse(buf);
+
+                    AssertEmpty(buf);
+
+                    // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+                    if (this.mPeerCertificate == null || this.mPeerCertificate.IsEmpty)
+                    {
+                        this.mAllowCertificateStatus = false;
+                    }
+
+                    this.mKeyExchange.ProcessServerCertificate(this.mPeerCertificate);
+
+                    this.mAuthentication = mTlsClient.GetAuthentication();
+                    this.mAuthentication.NotifyServerCertificate(this.mPeerCertificate);
+
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+
+                this.mConnectionState = CS_SERVER_CERTIFICATE;
+                break;
+            }
+            case HandshakeType.certificate_status:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_CERTIFICATE:
+                {
+                    if (!this.mAllowCertificateStatus)
+                    {
+                        /*
+                         * RFC 3546 3.6. If a server returns a "CertificateStatus" message, then the
+                         * server MUST have included an extension of type "status_request" with empty
+                         * "extension_data" in the extended server hello..
+                         */
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                    }
+
+                    this.mCertificateStatus = CertificateStatus.Parse(buf);
+
+                    AssertEmpty(buf);
+
+                    // TODO[RFC 3546] Figure out how to provide this to the client/authentication.
+
+                    this.mConnectionState = CS_CERTIFICATE_STATUS;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.finished:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_CLIENT_FINISHED:
+                case CS_SERVER_SESSION_TICKET:
+                {
+                    if (this.mConnectionState == CS_CLIENT_FINISHED && this.mExpectSessionTicket)
+                    {
+                        /*
+                         * RFC 5077 3.3. This message MUST be sent if the server included a
+                         * SessionTicket extension in the ServerHello.
+                         */
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                    }
+
+                    ProcessFinishedMessage(buf);
+                    this.mConnectionState = CS_SERVER_FINISHED;
+                    this.mConnectionState = CS_END;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.server_hello:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_CLIENT_HELLO:
+                {
+                    ReceiveServerHelloMessage(buf);
+                    this.mConnectionState = CS_SERVER_HELLO;
+
+                    if (this.mSecurityParameters.maxFragmentLength >= 0)
+                    {
+                        int plainTextLimit = 1 << (8 + this.mSecurityParameters.maxFragmentLength);
+                        mRecordStream.SetPlaintextLimit(plainTextLimit);
+                    }
+
+                    this.mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context,
+                        this.mSecurityParameters.CipherSuite);
+
+                    /*
+                     * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify
+                     * verify_data_length has a verify_data_length equal to 12. This includes all
+                     * existing cipher suites.
+                     */
+                    this.mSecurityParameters.verifyDataLength = 12;
+
+                    this.mRecordStream.NotifyHelloComplete();
+
+                    if (this.mResumedSession)
+                    {
+                        this.mSecurityParameters.masterSecret = Arrays.Clone(this.mSessionParameters.MasterSecret);
+                        this.mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher());
+
+                        SendChangeCipherSpecMessage();
+                    }
+                    else
+                    {
+                        InvalidateSession();
+
+                        if (this.mSelectedSessionID.Length > 0)
+                        {
+                            this.mTlsSession = new TlsSessionImpl(this.mSelectedSessionID, null);
+                        }
+                    }
+
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.supplemental_data:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO:
+                {
+                    HandleSupplementalData(ReadSupplementalDataMessage(buf));
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.server_hello_done:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO:
+                case CS_SERVER_SUPPLEMENTAL_DATA:
+                case CS_SERVER_CERTIFICATE:
+                case CS_CERTIFICATE_STATUS:
+                case CS_SERVER_KEY_EXCHANGE:
+                case CS_CERTIFICATE_REQUEST:
+                {
+                    if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA)
+                    {
+                        HandleSupplementalData(null);
+                    }
+
+                    if (mConnectionState < CS_SERVER_CERTIFICATE)
+                    {
+                        // There was no server certificate message; check it's OK
+                        this.mKeyExchange.SkipServerCredentials();
+                        this.mAuthentication = null;
+                    }
+
+                    if (mConnectionState < CS_SERVER_KEY_EXCHANGE)
+                    {
+                        // There was no server key exchange message; check it's OK
+                        this.mKeyExchange.SkipServerKeyExchange();
+                    }
+
+                    AssertEmpty(buf);
+
+                    this.mConnectionState = CS_SERVER_HELLO_DONE;
+
+                    this.mRecordStream.HandshakeHash.SealHashAlgorithms();
+
+                    IList clientSupplementalData = mTlsClient.GetClientSupplementalData();
+                    if (clientSupplementalData != null)
+                    {
+                        SendSupplementalDataMessage(clientSupplementalData);
+                    }
+                    this.mConnectionState = CS_CLIENT_SUPPLEMENTAL_DATA;
+
+                    TlsCredentials clientCreds = null;
+                    if (mCertificateRequest == null)
+                    {
+                        this.mKeyExchange.SkipClientCredentials();
+                    }
+                    else
+                    {
+                        clientCreds = this.mAuthentication.GetClientCredentials(mCertificateRequest);
+
+                        if (clientCreds == null)
+                        {
+                            this.mKeyExchange.SkipClientCredentials();
+
+                            /*
+                             * RFC 5246 If no suitable certificate is available, the client MUST Send a
+                             * certificate message containing no certificates.
+                             * 
+                             * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+                             */
+                            SendCertificateMessage(Certificate.EmptyChain);
+                        }
+                        else
+                        {
+                            this.mKeyExchange.ProcessClientCredentials(clientCreds);
+
+                            SendCertificateMessage(clientCreds.Certificate);
+                        }
+                    }
+
+                    this.mConnectionState = CS_CLIENT_CERTIFICATE;
+
+                    /*
+                     * Send the client key exchange message, depending on the key exchange we are using
+                     * in our CipherSuite.
+                     */
+                    SendClientKeyExchangeMessage();
+                    this.mConnectionState = CS_CLIENT_KEY_EXCHANGE;
+
+                    EstablishMasterSecret(Context, mKeyExchange);
+                    mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher());
+
+                    TlsHandshakeHash prepareFinishHash = mRecordStream.PrepareToFinish();
+
+                    if (clientCreds != null && clientCreds is TlsSignerCredentials)
+                    {
+                        TlsSignerCredentials signerCredentials = (TlsSignerCredentials)clientCreds;
+
+                        /*
+                         * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+                         */
+                        SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+                        byte[] hash;
+
+                        if (TlsUtilities.IsTlsV12(Context))
+                        {
+                            signatureAndHashAlgorithm = signerCredentials.SignatureAndHashAlgorithm;
+                            if (signatureAndHashAlgorithm == null)
+                                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+                            hash = prepareFinishHash.GetFinalHash(signatureAndHashAlgorithm.Hash);
+                        }
+                        else
+                        {
+                            signatureAndHashAlgorithm = null;
+                            hash = GetCurrentPrfHash(Context, prepareFinishHash, null);
+                        }
+
+                        byte[] signature = signerCredentials.GenerateCertificateSignature(hash);
+                        DigitallySigned certificateVerify = new DigitallySigned(signatureAndHashAlgorithm, signature);
+                        SendCertificateVerifyMessage(certificateVerify);
+
+                        this.mConnectionState = CS_CERTIFICATE_VERIFY;
+                    }
+
+                    SendChangeCipherSpecMessage();
+                    SendFinishedMessage();
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.handshake_failure);
+                }
+
+                this.mConnectionState = CS_CLIENT_FINISHED;
+                break;
+            }
+            case HandshakeType.server_key_exchange:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO:
+                case CS_SERVER_SUPPLEMENTAL_DATA:
+                case CS_SERVER_CERTIFICATE:
+                case CS_CERTIFICATE_STATUS:
+                {
+                    if (mConnectionState < CS_SERVER_SUPPLEMENTAL_DATA)
+                    {
+                        HandleSupplementalData(null);
+                    }
+
+                    if (mConnectionState < CS_SERVER_CERTIFICATE)
+                    {
+                        // There was no server certificate message; check it's OK
+                        this.mKeyExchange.SkipServerCredentials();
+                        this.mAuthentication = null;
+                    }
+
+                    this.mKeyExchange.ProcessServerKeyExchange(buf);
+
+                    AssertEmpty(buf);
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+
+                this.mConnectionState = CS_SERVER_KEY_EXCHANGE;
+                break;
+            }
+            case HandshakeType.certificate_request:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_CERTIFICATE:
+                case CS_CERTIFICATE_STATUS:
+                case CS_SERVER_KEY_EXCHANGE:
+                {
+                    if (this.mConnectionState != CS_SERVER_KEY_EXCHANGE)
+                    {
+                        // There was no server key exchange message; check it's OK
+                        this.mKeyExchange.SkipServerKeyExchange();
+                    }
+
+                    if (this.mAuthentication == null)
+                    {
+                        /*
+                         * RFC 2246 7.4.4. It is a fatal handshake_failure alert for an anonymous server
+                         * to request client identification.
+                         */
+                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
+                    }
+
+                    this.mCertificateRequest = CertificateRequest.Parse(Context, buf);
+
+                    AssertEmpty(buf);
+
+                    this.mKeyExchange.ValidateCertificateRequest(this.mCertificateRequest);
+
+                    /*
+                     * TODO Give the client a chance to immediately select the CertificateVerify hash
+                     * algorithm here to avoid tracking the other hash algorithms unnecessarily?
+                     */
+                    TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash,
+                        this.mCertificateRequest.SupportedSignatureAlgorithms);
+
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+
+                this.mConnectionState = CS_CERTIFICATE_REQUEST;
+                break;
+            }
+            case HandshakeType.session_ticket:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_CLIENT_FINISHED:
+                {
+                    if (!this.mExpectSessionTicket)
+                    {
+                        /*
+                         * RFC 5077 3.3. This message MUST NOT be sent if the server did not include a
+                         * SessionTicket extension in the ServerHello.
+                         */
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                    }
+
+                    /*
+                     * RFC 5077 3.4. If the client receives a session ticket from the server, then it
+                     * discards any Session ID that was sent in the ServerHello.
+                     */
+                    InvalidateSession();
+
+                    ReceiveNewSessionTicketMessage(buf);
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+
+                this.mConnectionState = CS_SERVER_SESSION_TICKET;
+                break;
+            }
+            case HandshakeType.hello_request:
+            {
+                AssertEmpty(buf);
+
+                /*
+                 * RFC 2246 7.4.1.1 Hello request This message will be ignored by the client if the
+                 * client is currently negotiating a session. This message may be ignored by the client
+                 * if it does not wish to renegotiate a session, or the client may, if it wishes,
+                 * respond with a no_renegotiation alert.
+                 */
+                if (this.mConnectionState == CS_END)
+                {
+                    /*
+                     * RFC 5746 4.5 SSLv3 clients that refuse renegotiation SHOULD use a fatal
+                     * handshake_failure alert.
+                     */
+                    if (TlsUtilities.IsSsl(Context))
+                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
+
+                    string message = "Renegotiation not supported";
+                    RaiseWarning(AlertDescription.no_renegotiation, message);
+                }
+                break;
+            }
+            case HandshakeType.client_hello:
+            case HandshakeType.client_key_exchange:
+            case HandshakeType.certificate_verify:
+            case HandshakeType.hello_verify_request:
+            default:
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+            }
+        }
+
+        protected virtual void HandleSupplementalData(IList serverSupplementalData)
+        {
+            this.mTlsClient.ProcessServerSupplementalData(serverSupplementalData);
+            this.mConnectionState = CS_SERVER_SUPPLEMENTAL_DATA;
+
+            this.mKeyExchange = mTlsClient.GetKeyExchange();
+            this.mKeyExchange.Init(Context);
+        }
+
+        protected virtual void ReceiveNewSessionTicketMessage(MemoryStream buf)
+        {
+            NewSessionTicket newSessionTicket = NewSessionTicket.Parse(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            mTlsClient.NotifyNewSessionTicket(newSessionTicket);
+        }
+
+        protected virtual void ReceiveServerHelloMessage(MemoryStream buf)
+        {
+            ProtocolVersion server_version = TlsUtilities.ReadVersion(buf);
+            if (server_version.IsDtls)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            // Check that this matches what the server is Sending in the record layer
+            if (!server_version.Equals(this.mRecordStream.ReadVersion))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            ProtocolVersion client_version = Context.ClientVersion;
+            if (!server_version.IsEqualOrEarlierVersionOf(client_version))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            this.mRecordStream.SetWriteVersion(server_version);
+            ContextAdmin.SetServerVersion(server_version);
+            this.mTlsClient.NotifyServerVersion(server_version);
+
+            /*
+             * Read the server random
+             */
+            this.mSecurityParameters.serverRandom = TlsUtilities.ReadFully(32, buf);
+
+            this.mSelectedSessionID = TlsUtilities.ReadOpaque8(buf);
+            if (this.mSelectedSessionID.Length > 32)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            this.mTlsClient.NotifySessionID(this.mSelectedSessionID);
+
+            this.mResumedSession = this.mSelectedSessionID.Length > 0 && this.mTlsSession != null
+                && Arrays.AreEqual(this.mSelectedSessionID, this.mTlsSession.SessionID);
+
+            /*
+             * Find out which CipherSuite the server has chosen and check that it was one of the offered
+             * ones, and is a valid selection for the negotiated version.
+             */
+            int selectedCipherSuite = TlsUtilities.ReadUint16(buf);
+            if (!Arrays.Contains(this.mOfferedCipherSuites, selectedCipherSuite)
+                || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+                || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+                || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version))
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            this.mTlsClient.NotifySelectedCipherSuite(selectedCipherSuite);
+
+            /*
+             * Find out which CompressionMethod the server has chosen and check that it was one of the
+             * offered ones.
+             */
+            byte selectedCompressionMethod = TlsUtilities.ReadUint8(buf);
+            if (!Arrays.Contains(this.mOfferedCompressionMethods, selectedCompressionMethod))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            this.mTlsClient.NotifySelectedCompressionMethod(selectedCompressionMethod);
+
+            /*
+             * RFC3546 2.2 The extended server hello message format MAY be sent in place of the server
+             * hello message when the client has requested extended functionality via the extended
+             * client hello message specified in Section 2.1. ... Note that the extended server hello
+             * message is only sent in response to an extended client hello message. This prevents the
+             * possibility that the extended server hello message could "break" existing TLS 1.0
+             * clients.
+             */
+            this.mServerExtensions = ReadExtensions(buf);
+
+            /*
+             * RFC 3546 2.2 Note that the extended server hello message is only sent in response to an
+             * extended client hello message.
+             * 
+             * However, see RFC 5746 exception below. We always include the SCSV, so an Extended Server
+             * Hello is always allowed.
+             */
+            if (this.mServerExtensions != null)
+            {
+                foreach (int extType in this.mServerExtensions.Keys)
+                {
+                    /*
+                     * RFC 5746 3.6. Note that Sending a "renegotiation_info" extension in response to a
+                     * ClientHello containing only the SCSV is an explicit exception to the prohibition
+                     * in RFC 5246, Section 7.4.1.4, on the server Sending unsolicited extensions and is
+                     * only allowed because the client is signaling its willingness to receive the
+                     * extension via the TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
+                     */
+                    if (extType == ExtensionType.renegotiation_info)
+                        continue;
+
+                    /*
+                     * RFC 3546 2.3. If [...] the older session is resumed, then the server MUST ignore
+                     * extensions appearing in the client hello, and Send a server hello containing no
+                     * extensions[.]
+                     */
+                    if (this.mResumedSession)
+                    {
+                        // TODO[compat-gnutls] GnuTLS test server Sends server extensions e.g. ec_point_formats
+                        // TODO[compat-openssl] OpenSSL test server Sends server extensions e.g. ec_point_formats
+                        // TODO[compat-polarssl] PolarSSL test server Sends server extensions e.g. ec_point_formats
+    //                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                    }
+
+                    /*
+                     * RFC 5246 7.4.1.4 An extension type MUST NOT appear in the ServerHello unless the
+                     * same extension type appeared in the corresponding ClientHello. If a client
+                     * receives an extension type in ServerHello that it did not request in the
+                     * associated ClientHello, it MUST abort the handshake with an unsupported_extension
+                     * fatal alert.
+                     */
+                    if (null == TlsUtilities.GetExtensionData(this.mClientExtensions, extType))
+                        throw new TlsFatalAlert(AlertDescription.unsupported_extension);
+                }
+            }
+
+            /*
+             * RFC 5746 3.4. Client Behavior: Initial Handshake
+             */
+            {
+                /*
+                 * When a ServerHello is received, the client MUST check if it includes the
+                 * "renegotiation_info" extension:
+                 */
+                byte[] renegExtData = TlsUtilities.GetExtensionData(this.mServerExtensions, ExtensionType.renegotiation_info);
+                if (renegExtData != null)
+                {
+                    /*
+                     * If the extension is present, set the secure_renegotiation flag to TRUE. The
+                     * client MUST then verify that the length of the "renegotiated_connection"
+                     * field is zero, and if it is not, MUST abort the handshake (by Sending a fatal
+                     * handshake_failure alert).
+                     */
+                    this.mSecureRenegotiation = true;
+
+                    if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
+                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
+                }
+            }
+
+            // TODO[compat-gnutls] GnuTLS test server fails to Send renegotiation_info extension when resuming
+            this.mTlsClient.NotifySecureRenegotiation(this.mSecureRenegotiation);
+
+            IDictionary sessionClientExtensions = mClientExtensions, sessionServerExtensions = mServerExtensions;
+            if (this.mResumedSession)
+            {
+                if (selectedCipherSuite != this.mSessionParameters.CipherSuite
+                    || selectedCompressionMethod != this.mSessionParameters.CompressionAlgorithm)
+                {
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+
+                sessionClientExtensions = null;
+                sessionServerExtensions = this.mSessionParameters.ReadServerExtensions();
+            }
+
+            this.mSecurityParameters.cipherSuite = selectedCipherSuite;
+            this.mSecurityParameters.compressionAlgorithm = selectedCompressionMethod;
+
+            if (sessionServerExtensions != null)
+            {
+                /*
+                 * draft-ietf-tls-encrypt-then-mac-03 3. If a server receives an encrypt-then-MAC
+                 * request extension from a client and then selects a stream or AEAD cipher suite, it
+                 * MUST NOT Send an encrypt-then-MAC response extension back to the client.
+                 */
+                bool serverSentEncryptThenMAC = TlsExtensionsUtilities.HasEncryptThenMacExtension(sessionServerExtensions);
+                if (serverSentEncryptThenMAC && !TlsUtilities.IsBlockCipherSuite(selectedCipherSuite))
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+                this.mSecurityParameters.encryptThenMac = serverSentEncryptThenMAC;
+
+                this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(sessionClientExtensions,
+                    sessionServerExtensions, AlertDescription.illegal_parameter);
+
+                this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(sessionServerExtensions);
+
+                /*
+                 * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
+                 * a session resumption handshake.
+                 */
+                this.mAllowCertificateStatus = !this.mResumedSession
+                    && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.status_request,
+                        AlertDescription.illegal_parameter);
+
+                this.mExpectSessionTicket = !this.mResumedSession
+                    && TlsUtilities.HasExpectedEmptyExtensionData(sessionServerExtensions, ExtensionType.session_ticket,
+                        AlertDescription.illegal_parameter);
+            }
+
+            if (sessionClientExtensions != null)
+            {
+                this.mTlsClient.ProcessServerExtensions(sessionServerExtensions);
+            }
+        }
+
+        protected virtual void SendCertificateVerifyMessage(DigitallySigned certificateVerify)
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_verify);
+
+            certificateVerify.Encode(message);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendClientHelloMessage()
+        {
+            this.mRecordStream.SetWriteVersion(this.mTlsClient.ClientHelloRecordLayerVersion);
+
+            ProtocolVersion client_version = this.mTlsClient.ClientVersion;
+            if (client_version.IsDtls)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            ContextAdmin.SetClientVersion(client_version);
+
+            /*
+             * TODO RFC 5077 3.4. When presenting a ticket, the client MAY generate and include a
+             * Session ID in the TLS ClientHello.
+             */
+            byte[] session_id = TlsUtilities.EmptyBytes;
+            if (this.mTlsSession != null)
+            {
+                session_id = this.mTlsSession.SessionID;
+                if (session_id == null || session_id.Length > 32)
+                {
+                    session_id = TlsUtilities.EmptyBytes;
+                }
+            }
+
+            this.mOfferedCipherSuites = this.mTlsClient.GetCipherSuites();
+
+            this.mOfferedCompressionMethods = this.mTlsClient.GetCompressionMethods();
+
+            if (session_id.Length > 0 && this.mSessionParameters != null)
+            {
+                if (!Arrays.Contains(this.mOfferedCipherSuites, mSessionParameters.CipherSuite)
+                    || !Arrays.Contains(this.mOfferedCompressionMethods, mSessionParameters.CompressionAlgorithm))
+                {
+                    session_id = TlsUtilities.EmptyBytes;
+                }
+            }
+
+            this.mClientExtensions = this.mTlsClient.GetClientExtensions();
+
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_hello);
+
+            TlsUtilities.WriteVersion(client_version, message);
+
+            message.Write(this.mSecurityParameters.ClientRandom);
+
+            TlsUtilities.WriteOpaque8(session_id, message);
+
+            // Cipher Suites (and SCSV)
+            {
+                /*
+                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+                 * ClientHello. Including both is NOT RECOMMENDED.
+                 */
+                byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info);
+                bool noRenegExt = (null == renegExtData);
+
+                bool noSCSV = !Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
+
+                if (noRenegExt && noSCSV)
+                {
+                    // TODO Consider whether to default to a client extension instead
+    //                this.mClientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(this.mClientExtensions);
+    //                this.mClientExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
+                    this.mOfferedCipherSuites = Arrays.Append(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV);
+                }
+
+                TlsUtilities.WriteUint16ArrayWithUint16Length(mOfferedCipherSuites, message);
+            }
+
+            TlsUtilities.WriteUint8ArrayWithUint8Length(mOfferedCompressionMethods, message);
+
+            if (mClientExtensions != null)
+            {
+                WriteExtensions(message, mClientExtensions);
+            }
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendClientKeyExchangeMessage()
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.client_key_exchange);
+
+            this.mKeyExchange.GenerateClientKeyExchange(message);
+
+            message.WriteToRecordStream(this);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsCompression.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCompression.cs
new file mode 100644
index 0000000..177d64b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCompression.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public interface TlsCompression
+	{
+		Stream Compress(Stream output);
+
+		Stream Decompress(Stream output);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsContext.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsContext.cs
new file mode 100644
index 0000000..d066723
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsContext.cs
@@ -0,0 +1,45 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsContext
+    {
+        IRandomGenerator NonceRandomGenerator { get; }
+
+        SecureRandom SecureRandom { get; }
+
+        SecurityParameters SecurityParameters { get; }
+
+        bool IsServer { get; }
+
+        ProtocolVersion ClientVersion { get; }
+
+        ProtocolVersion ServerVersion { get; }
+
+        /**
+         * Used to get the resumable session, if any, used by this connection. Only available after the
+         * handshake has successfully completed.
+         * 
+         * @return A {@link TlsSession} representing the resumable session used by this connection, or
+         *         null if no resumable session available.
+         * @see TlsPeer#NotifyHandshakeComplete()
+         */
+        TlsSession ResumableSession { get; }
+
+        object UserObject { get; set; }
+
+        /**
+         * Export keying material according to RFC 5705: "Keying Material Exporters for TLS".
+         *
+         * @param asciiLabel    indicates which application will use the exported keys.
+         * @param context_value allows the application using the exporter to mix its own data with the TLS PRF for
+         *                      the exporter output.
+         * @param length        the number of bytes to generate
+         * @return a pseudorandom bit string of 'length' bytes generated from the master_secret.
+         */
+        byte[] ExportKeyingMaterial(string asciiLabel, byte[] context_value, int length);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCredentials.cs
new file mode 100644
index 0000000..5c5f1c0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsCredentials.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public interface TlsCredentials
+	{
+		Certificate Certificate { get; }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHKeyExchange.cs
new file mode 100644
index 0000000..b831249
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHKeyExchange.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS DH key exchange.</summary>
+    public class TlsDHKeyExchange
+        :   AbstractTlsKeyExchange
+    {
+        protected TlsSigner mTlsSigner;
+        protected DHParameters mDHParameters;
+
+        protected AsymmetricKeyParameter mServerPublicKey;
+        protected DHPublicKeyParameters mDHAgreeServerPublicKey;
+        protected TlsAgreementCredentials mAgreementCredentials;
+        protected DHPrivateKeyParameters mDHAgreeClientPrivateKey;
+
+        protected DHPrivateKeyParameters mDHAgreeServerPrivateKey;
+        protected DHPublicKeyParameters mDHAgreeClientPublicKey;
+
+        public TlsDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+            :   base(keyExchange, supportedSignatureAlgorithms)
+        {
+            switch (keyExchange)
+            {
+            case KeyExchangeAlgorithm.DH_RSA:
+            case KeyExchangeAlgorithm.DH_DSS:
+                this.mTlsSigner = null;
+                break;
+            case KeyExchangeAlgorithm.DHE_RSA:
+                this.mTlsSigner = new TlsRsaSigner();
+                break;
+            case KeyExchangeAlgorithm.DHE_DSS:
+                this.mTlsSigner = new TlsDssSigner();
+                break;
+            default:
+                throw new InvalidOperationException("unsupported key exchange algorithm");
+            }
+
+            this.mDHParameters = dhParameters;
+        }
+
+        public override void Init(TlsContext context)
+        {
+            base.Init(context);
+
+            if (this.mTlsSigner != null)
+            {
+                this.mTlsSigner.Init(context);
+            }
+        }
+
+        public override void SkipServerCredentials()
+        {
+            throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (serverCertificate.IsEmpty)
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+
+            X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+
+            if (mTlsSigner == null)
+            {
+                try
+                {
+                    this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey((DHPublicKeyParameters)this.mServerPublicKey);
+                }
+                catch (InvalidCastException e)
+                {
+                    throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
+                }
+
+                TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
+            }
+            else
+            {
+                if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey))
+                {
+                    throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+                }
+
+                TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+            }
+
+            base.ProcessServerCertificate(serverCertificate);
+        }
+
+        public override bool RequiresServerKeyExchange
+        {
+            get
+            {
+                switch (mKeyExchange)
+                {
+                case KeyExchangeAlgorithm.DHE_DSS:
+                case KeyExchangeAlgorithm.DHE_RSA:
+                case KeyExchangeAlgorithm.DH_anon:
+                    return true;
+                default:
+                    return false;
+                }
+            }
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            byte[] types = certificateRequest.CertificateTypes;
+            for (int i = 0; i < types.Length; ++i)
+            {
+                switch (types[i])
+                {
+                case ClientCertificateType.rsa_sign:
+                case ClientCertificateType.dss_sign:
+                case ClientCertificateType.rsa_fixed_dh:
+                case ClientCertificateType.dss_fixed_dh:
+                case ClientCertificateType.ecdsa_sign:
+                    break;
+                default:
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            if (clientCredentials is TlsAgreementCredentials)
+            {
+                // TODO Validate client cert has matching parameters (see 'areCompatibleParameters')?
+
+                this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials;
+            }
+            else if (clientCredentials is TlsSignerCredentials)
+            {
+                // OK
+            }
+            else
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override void GenerateClientKeyExchange(Stream output)
+        {
+            /*
+             * RFC 2246 7.4.7.2 If the client certificate already contains a suitable Diffie-Hellman
+             * key, then Yc is implicit and does not need to be sent again. In this case, the Client Key
+             * Exchange message will be sent, but will be empty.
+             */
+            if (mAgreementCredentials == null)
+            {
+                this.mDHAgreeClientPrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom,
+                    mDHAgreeServerPublicKey.Parameters, output);
+            }
+        }
+
+        public override byte[] GeneratePremasterSecret()
+        {
+            if (mAgreementCredentials != null)
+            {
+                return mAgreementCredentials.GenerateAgreement(mDHAgreeServerPublicKey);
+            }
+
+            if (mDHAgreeServerPrivateKey != null)
+            {
+                return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeClientPublicKey, mDHAgreeServerPrivateKey);
+            }
+
+            if (mDHAgreeClientPrivateKey != null)
+            {
+                return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreeServerPublicKey, mDHAgreeClientPrivateKey);
+            }
+
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHUtilities.cs
new file mode 100644
index 0000000..477c3eb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDHUtilities.cs
@@ -0,0 +1,101 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsDHUtilities
+    {
+        internal static readonly BigInteger One = BigInteger.One;
+        internal static readonly BigInteger Two = BigInteger.Two;
+
+        public static bool AreCompatibleParameters(DHParameters a, DHParameters b)
+        {
+            return a.P.Equals(b.P) && a.G.Equals(b.G);
+        }
+
+        public static byte[] CalculateDHBasicAgreement(DHPublicKeyParameters publicKey,
+            DHPrivateKeyParameters privateKey)
+        {
+            DHBasicAgreement basicAgreement = new DHBasicAgreement();
+            basicAgreement.Init(privateKey);
+            BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey);
+
+            /*
+             * RFC 5246 8.1.2. Leading bytes of Z that contain all zero bits are stripped before it is
+             * used as the pre_master_secret.
+             */
+            return BigIntegers.AsUnsignedByteArray(agreementValue);
+        }
+
+        public static AsymmetricCipherKeyPair GenerateDHKeyPair(SecureRandom random, DHParameters dhParams)
+        {
+            DHBasicKeyPairGenerator dhGen = new DHBasicKeyPairGenerator();
+            dhGen.Init(new DHKeyGenerationParameters(random, dhParams));
+            return dhGen.GenerateKeyPair();
+        }
+
+        public static DHPrivateKeyParameters GenerateEphemeralClientKeyExchange(SecureRandom random,
+            DHParameters dhParams, Stream output)
+        {
+            AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams);
+
+            DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public;
+            WriteDHParameter(dhPublic.Y, output);
+
+            return (DHPrivateKeyParameters)kp.Private;
+        }
+
+        public static DHPrivateKeyParameters GenerateEphemeralServerKeyExchange(SecureRandom random,
+            DHParameters dhParams, Stream output)
+        {
+            AsymmetricCipherKeyPair kp = GenerateDHKeyPair(random, dhParams);
+
+            DHPublicKeyParameters dhPublic = (DHPublicKeyParameters)kp.Public;
+            new ServerDHParams(dhPublic).Encode(output);
+
+            return (DHPrivateKeyParameters)kp.Private;
+        }
+        
+        public static DHPublicKeyParameters ValidateDHPublicKey(DHPublicKeyParameters key)
+        {
+            BigInteger Y = key.Y;
+            DHParameters parameters = key.Parameters;
+            BigInteger p = parameters.P;
+            BigInteger g = parameters.G;
+
+            if (!p.IsProbablePrime(2))
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+            if (g.CompareTo(Two) < 0 || g.CompareTo(p.Subtract(Two)) > 0)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+            if (Y.CompareTo(Two) < 0 || Y.CompareTo(p.Subtract(One)) > 0)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            // TODO See RFC 2631 for more discussion of Diffie-Hellman validation
+
+            return key;
+        }
+
+        public static BigInteger ReadDHParameter(Stream input)
+        {
+            return new BigInteger(1, TlsUtilities.ReadOpaque16(input));
+        }
+
+        public static void WriteDHParameter(BigInteger x, Stream output)
+        {
+            TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(x), output);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDeflateCompression.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDeflateCompression.cs
new file mode 100644
index 0000000..9e11529
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDeflateCompression.cs
@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsDeflateCompression : TlsCompression
+    {
+        public const int LEVEL_NONE = JZlib.Z_NO_COMPRESSION;
+        public const int LEVEL_FASTEST = JZlib.Z_BEST_SPEED;
+        public const int LEVEL_SMALLEST = JZlib.Z_BEST_COMPRESSION;
+        public const int LEVEL_DEFAULT = JZlib.Z_DEFAULT_COMPRESSION;
+
+        protected readonly ZStream zIn, zOut;
+
+        public TlsDeflateCompression()
+            : this(LEVEL_DEFAULT)
+        {
+        }
+
+        public TlsDeflateCompression(int level)
+        {
+            this.zIn = new ZStream();
+            this.zIn.inflateInit();
+
+            this.zOut = new ZStream();
+            this.zOut.deflateInit(level);
+        }
+
+        public virtual Stream Compress(Stream output)
+        {
+            return new DeflateOutputStream(output, zOut, true);
+        }
+
+        public virtual Stream Decompress(Stream output)
+        {
+            return new DeflateOutputStream(output, zIn, false);
+        }
+
+        protected class DeflateOutputStream : ZOutputStream
+        {
+            public DeflateOutputStream(Stream output, ZStream z, bool compress)
+                : base(output, z)
+            {
+                this.compress = compress;
+
+                /*
+                 * See discussion at http://www.bolet.org/~pornin/deflate-flush.html .
+                 */
+                this.FlushMode = JZlib.Z_SYNC_FLUSH;
+            }
+
+            public override void Flush()
+            {
+                /*
+                 * TODO The inflateSyncPoint doesn't appear to work the way I hoped at the moment.
+                 * In any case, we may like to accept PARTIAL_FLUSH input, not just SYNC_FLUSH.
+                 * It's not clear how to check this in the Inflater.
+                 */
+                //if (!this.compress && (z == null || z.istate == null || z.istate.inflateSyncPoint(z) <= 0))
+                //{
+                //    throw new TlsFatalAlert(AlertDescription.decompression_failure);
+                //}
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDheKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDheKeyExchange.cs
new file mode 100644
index 0000000..3c05bb6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDheKeyExchange.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsDheKeyExchange
+        :   TlsDHKeyExchange
+    {
+        protected TlsSignerCredentials mServerCredentials = null;
+
+        public TlsDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, DHParameters dhParameters)
+            :   base(keyExchange, supportedSignatureAlgorithms, dhParameters)
+        {
+        }
+
+        public override void ProcessServerCredentials(TlsCredentials serverCredentials)
+        {
+            if (!(serverCredentials is TlsSignerCredentials))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            ProcessServerCertificate(serverCredentials.Certificate);
+
+            this.mServerCredentials = (TlsSignerCredentials)serverCredentials;
+        }
+
+        public override byte[] GenerateServerKeyExchange()
+        {
+            if (this.mDHParameters == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            DigestInputBuffer buf = new DigestInputBuffer();
+
+            this.mDHAgreeServerPrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom,
+                this.mDHParameters, buf);
+
+            /*
+             * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+             */
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+            IDigest d;
+
+            if (TlsUtilities.IsTlsV12(context))
+            {
+                signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm;
+                if (signatureAndHashAlgorithm == null)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+
+                d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash);
+            }
+            else
+            {
+                signatureAndHashAlgorithm = null;
+                d = new CombinedHash();
+            }
+
+            SecurityParameters securityParameters = context.SecurityParameters;
+            d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+            d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+            buf.UpdateDigest(d);
+
+            byte[] hash = DigestUtilities.DoFinal(d);
+
+            byte[] signature = mServerCredentials.GenerateCertificateSignature(hash);
+
+            DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+            signed_params.Encode(buf);
+
+            return buf.ToArray();
+        }
+
+        public override void ProcessServerKeyExchange(Stream input)
+        {
+            SecurityParameters securityParameters = context.SecurityParameters;
+
+            SignerInputBuffer buf = new SignerInputBuffer();
+            Stream teeIn = new TeeInputStream(input, buf);
+
+            ServerDHParams dhParams = ServerDHParams.Parse(teeIn);
+
+            DigitallySigned signed_params = DigitallySigned.Parse(context, input);
+
+            ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
+            buf.UpdateSigner(signer);
+            if (!signer.VerifySignature(signed_params.Signature))
+                throw new TlsFatalAlert(AlertDescription.decrypt_error);
+
+            this.mDHAgreeServerPublicKey = TlsDHUtilities.ValidateDHPublicKey(dhParams.PublicKey);
+        }
+
+        protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
+            SecurityParameters securityParameters)
+        {
+            ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey);
+            signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+            signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+            return signer;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDsaSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDsaSigner.cs
new file mode 100644
index 0000000..a5ac559
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDsaSigner.cs
@@ -0,0 +1,83 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsDsaSigner
+        :	AbstractTlsSigner
+    {
+        public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+            AsymmetricKeyParameter privateKey, byte[] hash)
+        {
+            ISigner signer = MakeSigner(algorithm, true, true,
+                new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
+            if (algorithm == null)
+            {
+                // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+                signer.BlockUpdate(hash, 16, 20);
+            }
+            else
+            {
+                signer.BlockUpdate(hash, 0, hash.Length);
+            }
+            return signer.GenerateSignature();
+        }
+
+        public override bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+            AsymmetricKeyParameter publicKey, byte[] hash)
+        {
+            ISigner signer = MakeSigner(algorithm, true, false, publicKey);
+            if (algorithm == null)
+            {
+                // Note: Only use the SHA1 part of the (MD5/SHA1) hash
+                signer.BlockUpdate(hash, 16, 20);
+            }
+            else
+            {
+                signer.BlockUpdate(hash, 0, hash.Length);
+            }
+            return signer.VerifySignature(sigBytes);
+        }
+
+        public override ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
+        {
+            return MakeSigner(algorithm, false, true, privateKey);
+        }
+
+        public override ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
+        {
+            return MakeSigner(algorithm, false, false, publicKey);
+        }
+
+        protected virtual ICipherParameters MakeInitParameters(bool forSigning, ICipherParameters cp)
+        {
+            return cp;
+        }
+
+        protected virtual ISigner MakeSigner(SignatureAndHashAlgorithm algorithm, bool raw, bool forSigning,
+            ICipherParameters cp)
+        {
+            if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext))
+                throw new InvalidOperationException();
+
+            // TODO For TLS 1.2+, lift the SHA-1 restriction here
+            if (algorithm != null && (algorithm.Hash != HashAlgorithm.sha1 || algorithm.Signature != SignatureAlgorithm))
+                throw new InvalidOperationException();
+
+            byte hashAlgorithm = algorithm == null ? HashAlgorithm.sha1 : algorithm.Hash;
+            IDigest d = raw ? new NullDigest() : TlsUtilities.CreateHash(hashAlgorithm);
+
+            ISigner s = new DsaDigestSigner(CreateDsaImpl(hashAlgorithm), d);
+            s.Init(forSigning, MakeInitParameters(forSigning, cp));
+            return s;
+        }
+
+        protected abstract byte SignatureAlgorithm { get; }
+
+        protected abstract IDsa CreateDsaImpl(byte hashAlgorithm);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsDssSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDssSigner.cs
new file mode 100644
index 0000000..707ef38
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsDssSigner.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsDssSigner
+        :   TlsDsaSigner
+    {
+        public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+        {
+            return publicKey is DsaPublicKeyParameters;
+        }
+
+        protected override IDsa CreateDsaImpl(byte hashAlgorithm)
+        {
+            return new DsaSigner(new HMacDsaKCalculator(TlsUtilities.CreateHash(hashAlgorithm)));
+        }
+
+        protected override byte SignatureAlgorithm
+        {
+            get { return Tls.SignatureAlgorithm.dsa; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDHKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDHKeyExchange.cs
new file mode 100644
index 0000000..42dc2f2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDHKeyExchange.cs
@@ -0,0 +1,211 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS ECDH key exchange (see RFC 4492).</summary>
+    public class TlsECDHKeyExchange
+        :   AbstractTlsKeyExchange
+    {
+        protected TlsSigner mTlsSigner;
+        protected int[] mNamedCurves;
+        protected byte[] mClientECPointFormats, mServerECPointFormats;
+
+        protected AsymmetricKeyParameter mServerPublicKey;
+        protected TlsAgreementCredentials mAgreementCredentials;
+
+        protected ECPrivateKeyParameters mECAgreePrivateKey;
+        protected ECPublicKeyParameters mECAgreePublicKey;
+
+        public TlsECDHKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, int[] namedCurves,
+            byte[] clientECPointFormats, byte[] serverECPointFormats)
+            :   base(keyExchange, supportedSignatureAlgorithms)
+        {
+            switch (keyExchange)
+            {
+            case KeyExchangeAlgorithm.ECDHE_RSA:
+                this.mTlsSigner = new TlsRsaSigner();
+                break;
+            case KeyExchangeAlgorithm.ECDHE_ECDSA:
+                this.mTlsSigner = new TlsECDsaSigner();
+                break;
+            case KeyExchangeAlgorithm.ECDH_RSA:
+            case KeyExchangeAlgorithm.ECDH_ECDSA:
+                this.mTlsSigner = null;
+                break;
+            default:
+                throw new InvalidOperationException("unsupported key exchange algorithm");
+            }
+
+            this.mNamedCurves = namedCurves;
+            this.mClientECPointFormats = clientECPointFormats;
+            this.mServerECPointFormats = serverECPointFormats;
+        }
+
+        public override void Init(TlsContext context)
+        {
+            base.Init(context);
+
+            if (this.mTlsSigner != null)
+            {
+                this.mTlsSigner.Init(context);
+            }
+        }
+
+        public override void SkipServerCredentials()
+        {
+            throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (serverCertificate.IsEmpty)
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+
+            X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+
+            if (mTlsSigner == null)
+            {
+                try
+                {
+                    this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey((ECPublicKeyParameters) this.mServerPublicKey);
+                }
+                catch (InvalidCastException e)
+                {
+                    throw new TlsFatalAlert(AlertDescription.certificate_unknown, e);
+                }
+
+                TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyAgreement);
+            }
+            else
+            {
+                if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey))
+                    throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+
+                TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+            }
+
+            base.ProcessServerCertificate(serverCertificate);
+        }
+
+        public override bool RequiresServerKeyExchange
+        {
+            get
+            {
+                switch (mKeyExchange)
+                {
+                case KeyExchangeAlgorithm.ECDHE_ECDSA:
+                case KeyExchangeAlgorithm.ECDHE_RSA:
+                case KeyExchangeAlgorithm.ECDH_anon:
+                    return true;
+                default:
+                    return false;
+                }
+            }
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            /*
+             * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
+             * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
+             * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
+             * these algorithms.
+             */
+            byte[] types = certificateRequest.CertificateTypes;
+            for (int i = 0; i < types.Length; ++i)
+            {
+                switch (types[i])
+                {
+                case ClientCertificateType.rsa_sign:
+                case ClientCertificateType.dss_sign:
+                case ClientCertificateType.ecdsa_sign:
+                case ClientCertificateType.rsa_fixed_ecdh:
+                case ClientCertificateType.ecdsa_fixed_ecdh:
+                    break;
+                default:
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            if (clientCredentials is TlsAgreementCredentials)
+            {
+                // TODO Validate client cert has matching parameters (see 'TlsEccUtilities.AreOnSameCurve')?
+
+                this.mAgreementCredentials = (TlsAgreementCredentials)clientCredentials;
+            }
+            else if (clientCredentials is TlsSignerCredentials)
+            {
+                // OK
+            }
+            else
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public override void GenerateClientKeyExchange(Stream output)
+        {
+            if (mAgreementCredentials == null)
+            {
+                this.mECAgreePrivateKey = TlsEccUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom,
+                    mServerECPointFormats, mECAgreePublicKey.Parameters, output);
+            }
+        }
+
+        public override void ProcessClientCertificate(Certificate clientCertificate)
+        {
+            // TODO Extract the public key
+            // TODO If the certificate is 'fixed', take the public key as mECAgreeClientPublicKey
+        }
+
+        public override void ProcessClientKeyExchange(Stream input)
+        {
+            if (mECAgreePublicKey != null)
+            {
+                // For ecdsa_fixed_ecdh and rsa_fixed_ecdh, the key arrived in the client certificate
+                return;
+            }
+
+            byte[] point = TlsUtilities.ReadOpaque8(input);
+
+            ECDomainParameters curve_params = this.mECAgreePrivateKey.Parameters;
+
+            this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
+                mServerECPointFormats, curve_params, point));
+        }
+
+        public override byte[] GeneratePremasterSecret()
+        {
+            if (mAgreementCredentials != null)
+            {
+                return mAgreementCredentials.GenerateAgreement(mECAgreePublicKey);
+            }
+
+            if (mECAgreePrivateKey != null)
+            {
+                return TlsEccUtilities.CalculateECDHBasicAgreement(mECAgreePublicKey, mECAgreePrivateKey);
+            }
+
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDheKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDheKeyExchange.cs
new file mode 100644
index 0000000..0644bd4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDheKeyExchange.cs
@@ -0,0 +1,206 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS ECDHE key exchange (see RFC 4492).</summary>
+    public class TlsECDheKeyExchange
+        :   TlsECDHKeyExchange
+    {
+        protected TlsSignerCredentials mServerCredentials = null;
+
+        public TlsECDheKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, int[] namedCurves,
+            byte[] clientECPointFormats, byte[] serverECPointFormats)
+            :   base(keyExchange, supportedSignatureAlgorithms, namedCurves, clientECPointFormats, serverECPointFormats)
+        {
+        }
+
+        public override void ProcessServerCredentials(TlsCredentials serverCredentials)
+        {
+            if (!(serverCredentials is TlsSignerCredentials))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            ProcessServerCertificate(serverCredentials.Certificate);
+
+            this.mServerCredentials = (TlsSignerCredentials)serverCredentials;
+        }
+
+        public override byte[] GenerateServerKeyExchange()
+        {
+            /*
+             * First we try to find a supported named curve from the client's list.
+             */
+            int namedCurve = -1;
+            if (mNamedCurves == null)
+            {
+                // TODO Let the peer choose the default named curve
+                namedCurve = NamedCurve.secp256r1;
+            }
+            else
+            {
+                for (int i = 0; i < mNamedCurves.Length; ++i)
+                {
+                    int entry = mNamedCurves[i];
+                    if (NamedCurve.IsValid(entry) && TlsEccUtilities.IsSupportedNamedCurve(entry))
+                    {
+                        namedCurve = entry;
+                        break;
+                    }
+                }
+            }
+
+            ECDomainParameters curve_params = null;
+            if (namedCurve >= 0)
+            {
+                curve_params = TlsEccUtilities.GetParametersForNamedCurve(namedCurve);
+            }
+            else
+            {
+                /*
+                 * If no named curves are suitable, check if the client supports explicit curves.
+                 */
+                if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_prime_curves))
+                {
+                    curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.secp256r1);
+                }
+                else if (Arrays.Contains(mNamedCurves, NamedCurve.arbitrary_explicit_char2_curves))
+                {
+                    curve_params = TlsEccUtilities.GetParametersForNamedCurve(NamedCurve.sect283r1);
+                }
+            }
+
+            if (curve_params == null)
+            {
+                /*
+                 * NOTE: We shouldn't have negotiated ECDHE key exchange since we apparently can't find
+                 * a suitable curve.
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(context.SecureRandom, curve_params);
+            this.mECAgreePrivateKey = (ECPrivateKeyParameters)kp.Private;
+
+            DigestInputBuffer buf = new DigestInputBuffer();
+
+            if (namedCurve < 0)
+            {
+                TlsEccUtilities.WriteExplicitECParameters(mClientECPointFormats, curve_params, buf);
+            }
+            else
+            {
+                TlsEccUtilities.WriteNamedECParameters(namedCurve, buf);
+            }
+
+            ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public;
+            TlsEccUtilities.WriteECPoint(mClientECPointFormats, ecPublicKey.Q, buf);
+
+            /*
+             * RFC 5246 4.7. digitally-signed element needs SignatureAndHashAlgorithm from TLS 1.2
+             */
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm;
+            IDigest d;
+
+            if (TlsUtilities.IsTlsV12(context))
+            {
+                signatureAndHashAlgorithm = mServerCredentials.SignatureAndHashAlgorithm;
+                if (signatureAndHashAlgorithm == null)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+
+                d = TlsUtilities.CreateHash(signatureAndHashAlgorithm.Hash);
+            }
+            else
+            {
+                signatureAndHashAlgorithm = null;
+                d = new CombinedHash();
+            }
+
+            SecurityParameters securityParameters = context.SecurityParameters;
+            d.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+            d.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+            buf.UpdateDigest(d);
+
+            byte[] hash = DigestUtilities.DoFinal(d);
+
+            byte[] signature = mServerCredentials.GenerateCertificateSignature(hash);
+
+            DigitallySigned signed_params = new DigitallySigned(signatureAndHashAlgorithm, signature);
+            signed_params.Encode(buf);
+
+            return buf.ToArray();
+        }
+
+        public override void ProcessServerKeyExchange(Stream input)
+        {
+            SecurityParameters securityParameters = context.SecurityParameters;
+
+            SignerInputBuffer buf = new SignerInputBuffer();
+            Stream teeIn = new TeeInputStream(input, buf);
+
+            ECDomainParameters curve_params = TlsEccUtilities.ReadECParameters(mNamedCurves, mClientECPointFormats, teeIn);
+
+            byte[] point = TlsUtilities.ReadOpaque8(teeIn);
+
+            DigitallySigned signed_params = DigitallySigned.Parse(context, input);
+
+            ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
+            buf.UpdateSigner(signer);
+            if (!signer.VerifySignature(signed_params.Signature))
+                throw new TlsFatalAlert(AlertDescription.decrypt_error);
+
+            this.mECAgreePublicKey = TlsEccUtilities.ValidateECPublicKey(TlsEccUtilities.DeserializeECPublicKey(
+                mClientECPointFormats, curve_params, point));
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            /*
+             * RFC 4492 3. [...] The ECDSA_fixed_ECDH and RSA_fixed_ECDH mechanisms are usable with
+             * ECDH_ECDSA and ECDH_RSA. Their use with ECDHE_ECDSA and ECDHE_RSA is prohibited because
+             * the use of a long-term ECDH client key would jeopardize the forward secrecy property of
+             * these algorithms.
+             */
+            byte[] types = certificateRequest.CertificateTypes;
+            for (int i = 0; i < types.Length; ++i)
+            {
+                switch (types[i])
+                {
+                case ClientCertificateType.rsa_sign:
+                case ClientCertificateType.dss_sign:
+                case ClientCertificateType.ecdsa_sign:
+                    break;
+                default:
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            if (clientCredentials is TlsSignerCredentials)
+            {
+                // OK
+            }
+            else
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
+            SecurityParameters securityParameters)
+        {
+            ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey);
+            signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+            signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+            return signer;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDsaSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDsaSigner.cs
new file mode 100644
index 0000000..fa9d0b7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsECDsaSigner.cs
@@ -0,0 +1,26 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsECDsaSigner
+        :   TlsDsaSigner
+    {
+        public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+        {
+            return publicKey is ECPublicKeyParameters;
+        }
+
+        protected override IDsa CreateDsaImpl(byte hashAlgorithm)
+        {
+            return new ECDsaSigner(new HMacDsaKCalculator(TlsUtilities.CreateHash(hashAlgorithm)));
+        }
+
+        protected override byte SignatureAlgorithm
+        {
+            get { return Tls.SignatureAlgorithm.ecdsa; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsEccUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsEccUtilities.cs
new file mode 100644
index 0000000..64c3c15
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsEccUtilities.cs
@@ -0,0 +1,647 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Math.Field;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsEccUtilities
+    {
+        private static readonly string[] CurveNames = new string[] { "sect163k1", "sect163r1", "sect163r2", "sect193r1",
+            "sect193r2", "sect233k1", "sect233r1", "sect239k1", "sect283k1", "sect283r1", "sect409k1", "sect409r1",
+            "sect571k1", "sect571r1", "secp160k1", "secp160r1", "secp160r2", "secp192k1", "secp192r1", "secp224k1",
+            "secp224r1", "secp256k1", "secp256r1", "secp384r1", "secp521r1",
+            "brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1"};
+
+        public static void AddSupportedEllipticCurvesExtension(IDictionary extensions, int[] namedCurves)
+        {
+            extensions[ExtensionType.elliptic_curves] = CreateSupportedEllipticCurvesExtension(namedCurves);
+        }
+
+        public static void AddSupportedPointFormatsExtension(IDictionary extensions, byte[] ecPointFormats)
+        {
+            extensions[ExtensionType.ec_point_formats] = CreateSupportedPointFormatsExtension(ecPointFormats);
+        }
+
+        public static int[] GetSupportedEllipticCurvesExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.elliptic_curves);
+            return extensionData == null ? null : ReadSupportedEllipticCurvesExtension(extensionData);
+        }
+
+        public static byte[] GetSupportedPointFormatsExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.ec_point_formats);
+            return extensionData == null ? null : ReadSupportedPointFormatsExtension(extensionData);
+        }
+
+        public static byte[] CreateSupportedEllipticCurvesExtension(int[] namedCurves)
+        {
+            if (namedCurves == null || namedCurves.Length < 1)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            return TlsUtilities.EncodeUint16ArrayWithUint16Length(namedCurves);
+        }
+
+        public static byte[] CreateSupportedPointFormatsExtension(byte[] ecPointFormats)
+        {
+            if (ecPointFormats == null || !Arrays.Contains(ecPointFormats, ECPointFormat.uncompressed))
+            {
+                /*
+                 * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
+                 * contain the value 0 (uncompressed) as one of the items in the list of point formats.
+                 */
+
+                // NOTE: We add it at the end (lowest preference)
+                ecPointFormats = Arrays.Append(ecPointFormats, ECPointFormat.uncompressed);
+            }
+
+            return TlsUtilities.EncodeUint8ArrayWithUint8Length(ecPointFormats);
+        }
+
+        public static int[] ReadSupportedEllipticCurvesExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            int length = TlsUtilities.ReadUint16(buf);
+            if (length < 2 || (length & 1) != 0)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int[] namedCurves = TlsUtilities.ReadUint16Array(length / 2, buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return namedCurves;
+        }
+
+        public static byte[] ReadSupportedPointFormatsExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            byte length = TlsUtilities.ReadUint8(buf);
+            if (length < 1)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            byte[] ecPointFormats = TlsUtilities.ReadUint8Array(length, buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            if (!Arrays.Contains(ecPointFormats, ECPointFormat.uncompressed))
+            {
+                /*
+                 * RFC 4492 5.1. If the Supported Point Formats Extension is indeed sent, it MUST
+                 * contain the value 0 (uncompressed) as one of the items in the list of point formats.
+                 */
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            return ecPointFormats;
+        }
+
+        public static string GetNameOfNamedCurve(int namedCurve)
+        {
+            return IsSupportedNamedCurve(namedCurve) ? CurveNames[namedCurve - 1] : null;
+        }
+
+        public static ECDomainParameters GetParametersForNamedCurve(int namedCurve)
+        {
+            string curveName = GetNameOfNamedCurve(namedCurve);
+            if (curveName == null)
+                return null;
+
+            // Parameters are lazily created the first time a particular curve is accessed
+
+            X9ECParameters ecP = CustomNamedCurves.GetByName(curveName);
+            if (ecP == null)
+            {
+                ecP = ECNamedCurveTable.GetByName(curveName);
+                if (ecP == null)
+                    return null;
+            }
+
+            // It's a bit inefficient to do this conversion every time
+            return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
+        }
+
+        public static bool HasAnySupportedNamedCurves()
+        {
+            return CurveNames.Length > 0;
+        }
+
+        public static bool ContainsEccCipherSuites(int[] cipherSuites)
+        {
+            for (int i = 0; i < cipherSuites.Length; ++i)
+            {
+                if (IsEccCipherSuite(cipherSuites[i]))
+                    return true;
+            }
+            return false;
+        }
+
+        public static bool IsEccCipherSuite(int cipherSuite)
+        {
+            switch (cipherSuite)
+            {
+            /*
+             * RFC 4492
+             */
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_AES_256_CBC_SHA:
+
+            /*
+             * RFC 5289
+             */
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+
+            /*
+             * RFC 5489
+             */
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+
+            /*
+             * RFC 6367
+             */
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+
+            /*
+             * draft-agl-tls-chacha20poly1305-04
+             */
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+
+            /*
+             * draft-josefsson-salsa20-tls-04 
+             */
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+
+                return true;
+
+            default:
+                return false;
+            }
+        }
+
+        public static bool AreOnSameCurve(ECDomainParameters a, ECDomainParameters b)
+        {
+            // TODO Move to ECDomainParameters.Equals() or other utility method?
+            return a.Curve.Equals(b.Curve) && a.G.Equals(b.G) && a.N.Equals(b.N) && a.H.Equals(b.H);
+        }
+
+        public static bool IsSupportedNamedCurve(int namedCurve)
+        {
+            return (namedCurve > 0 && namedCurve <= CurveNames.Length);
+        }
+
+        public static bool IsCompressionPreferred(byte[] ecPointFormats, byte compressionFormat)
+        {
+            if (ecPointFormats == null)
+                return false;
+
+            for (int i = 0; i < ecPointFormats.Length; ++i)
+            {
+                byte ecPointFormat = ecPointFormats[i];
+                if (ecPointFormat == ECPointFormat.uncompressed)
+                    return false;
+                if (ecPointFormat == compressionFormat)
+                    return true;
+            }
+            return false;
+        }
+
+        public static byte[] SerializeECFieldElement(int fieldSize, BigInteger x)
+        {
+            return BigIntegers.AsUnsignedByteArray((fieldSize + 7) / 8, x);
+        }
+
+        public static byte[] SerializeECPoint(byte[] ecPointFormats, ECPoint point)
+        {
+            ECCurve curve = point.Curve;
+
+            /*
+             * RFC 4492 5.7. ...an elliptic curve point in uncompressed or compressed format. Here, the
+             * format MUST conform to what the server has requested through a Supported Point Formats
+             * Extension if this extension was used, and MUST be uncompressed if this extension was not
+             * used.
+             */
+            bool compressed = false;
+            if (ECAlgorithms.IsFpCurve(curve))
+            {
+                compressed = IsCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_prime);
+            }
+            else if (ECAlgorithms.IsF2mCurve(curve))
+            {
+                compressed = IsCompressionPreferred(ecPointFormats, ECPointFormat.ansiX962_compressed_char2);
+            }
+            return point.GetEncoded(compressed);
+        }
+
+        public static byte[] SerializeECPublicKey(byte[] ecPointFormats, ECPublicKeyParameters keyParameters)
+        {
+            return SerializeECPoint(ecPointFormats, keyParameters.Q);
+        }
+
+        public static BigInteger DeserializeECFieldElement(int fieldSize, byte[] encoding)
+        {
+            int requiredLength = (fieldSize + 7) / 8;
+            if (encoding.Length != requiredLength)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            return new BigInteger(1, encoding);
+        }
+
+        public static ECPoint DeserializeECPoint(byte[] ecPointFormats, ECCurve curve, byte[] encoding)
+        {
+            if (encoding == null || encoding.Length < 1)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            byte actualFormat;
+            switch (encoding[0])
+            {
+            case 0x02: // compressed
+            case 0x03: // compressed
+            {
+                if (ECAlgorithms.IsF2mCurve(curve))
+                {
+                    actualFormat = ECPointFormat.ansiX962_compressed_char2;
+                }
+                else if (ECAlgorithms.IsFpCurve(curve))
+                {
+                    actualFormat = ECPointFormat.ansiX962_compressed_prime;
+                }
+                else
+                {
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+                break;
+            }
+            case 0x04: // uncompressed
+            {
+                actualFormat = ECPointFormat.uncompressed;
+                break;
+            }
+            case 0x00: // infinity
+            case 0x06: // hybrid
+            case 0x07: // hybrid
+            default:
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            if (actualFormat != ECPointFormat.uncompressed
+                && (ecPointFormats == null || !Arrays.Contains(ecPointFormats, actualFormat)))
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            return curve.DecodePoint(encoding);
+        }
+
+        public static ECPublicKeyParameters DeserializeECPublicKey(byte[] ecPointFormats, ECDomainParameters curve_params,
+            byte[] encoding)
+        {
+            try
+            {
+                ECPoint Y = DeserializeECPoint(ecPointFormats, curve_params.Curve, encoding);
+                return new ECPublicKeyParameters(Y, curve_params);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter, e);
+            }
+        }
+
+        public static byte[] CalculateECDHBasicAgreement(ECPublicKeyParameters publicKey, ECPrivateKeyParameters privateKey)
+        {
+            ECDHBasicAgreement basicAgreement = new ECDHBasicAgreement();
+            basicAgreement.Init(privateKey);
+            BigInteger agreementValue = basicAgreement.CalculateAgreement(publicKey);
+
+            /*
+             * RFC 4492 5.10. Note that this octet string (Z in IEEE 1363 terminology) as output by
+             * FE2OSP, the Field Element to Octet String Conversion Primitive, has constant length for
+             * any given field; leading zeros found in this octet string MUST NOT be truncated.
+             */
+            return BigIntegers.AsUnsignedByteArray(basicAgreement.GetFieldSize(), agreementValue);
+        }
+
+        public static AsymmetricCipherKeyPair GenerateECKeyPair(SecureRandom random, ECDomainParameters ecParams)
+        {
+            ECKeyPairGenerator keyPairGenerator = new ECKeyPairGenerator();
+            keyPairGenerator.Init(new ECKeyGenerationParameters(ecParams, random));
+            return keyPairGenerator.GenerateKeyPair();
+        }
+
+        public static ECPrivateKeyParameters GenerateEphemeralClientKeyExchange(SecureRandom random, byte[] ecPointFormats,
+            ECDomainParameters ecParams, Stream output)
+        {
+            AsymmetricCipherKeyPair kp = TlsEccUtilities.GenerateECKeyPair(random, ecParams);
+
+            ECPublicKeyParameters ecPublicKey = (ECPublicKeyParameters)kp.Public;
+            WriteECPoint(ecPointFormats, ecPublicKey.Q, output);
+
+            return (ECPrivateKeyParameters)kp.Private;
+        }
+
+        public static ECPublicKeyParameters ValidateECPublicKey(ECPublicKeyParameters key)
+        {
+            // TODO Check RFC 4492 for validation
+            return key;
+        }
+
+        public static int ReadECExponent(int fieldSize, Stream input)
+        {
+            BigInteger K = ReadECParameter(input);
+            if (K.BitLength < 32)
+            {
+                int k = K.IntValue;
+                if (k > 0 && k < fieldSize)
+                {
+                    return k;
+                }
+            }
+            throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+        }
+
+        public static BigInteger ReadECFieldElement(int fieldSize, Stream input)
+        {
+            return DeserializeECFieldElement(fieldSize, TlsUtilities.ReadOpaque8(input));
+        }
+
+        public static BigInteger ReadECParameter(Stream input)
+        {
+            // TODO Are leading zeroes okay here?
+            return new BigInteger(1, TlsUtilities.ReadOpaque8(input));
+        }
+
+        public static ECDomainParameters ReadECParameters(int[] namedCurves, byte[] ecPointFormats, Stream input)
+        {
+            try
+            {
+                byte curveType = TlsUtilities.ReadUint8(input);
+
+                switch (curveType)
+                {
+                case ECCurveType.explicit_prime:
+                {
+                    CheckNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_prime_curves);
+
+                    BigInteger prime_p = ReadECParameter(input);
+                    BigInteger a = ReadECFieldElement(prime_p.BitLength, input);
+                    BigInteger b = ReadECFieldElement(prime_p.BitLength, input);
+                    byte[] baseEncoding = TlsUtilities.ReadOpaque8(input);
+                    BigInteger order = ReadECParameter(input);
+                    BigInteger cofactor = ReadECParameter(input);
+                    ECCurve curve = new FpCurve(prime_p, a, b, order, cofactor);
+                    ECPoint basePoint = DeserializeECPoint(ecPointFormats, curve, baseEncoding);
+                    return new ECDomainParameters(curve, basePoint, order, cofactor);
+                }
+                case ECCurveType.explicit_char2:
+                {
+                    CheckNamedCurve(namedCurves, NamedCurve.arbitrary_explicit_char2_curves);
+
+                    int m = TlsUtilities.ReadUint16(input);
+                    byte basis = TlsUtilities.ReadUint8(input);
+                    if (!ECBasisType.IsValid(basis))
+                        throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+                    int k1 = ReadECExponent(m, input), k2 = -1, k3 = -1;
+                    if (basis == ECBasisType.ec_basis_pentanomial)
+                    {
+                        k2 = ReadECExponent(m, input);
+                        k3 = ReadECExponent(m, input);
+                    }
+
+                    BigInteger a = ReadECFieldElement(m, input);
+                    BigInteger b = ReadECFieldElement(m, input);
+                    byte[] baseEncoding = TlsUtilities.ReadOpaque8(input);
+                    BigInteger order = ReadECParameter(input);
+                    BigInteger cofactor = ReadECParameter(input);
+
+                    ECCurve curve = (basis == ECBasisType.ec_basis_pentanomial)
+                        ? new F2mCurve(m, k1, k2, k3, a, b, order, cofactor)
+                        : new F2mCurve(m, k1, a, b, order, cofactor);
+
+                    ECPoint basePoint = DeserializeECPoint(ecPointFormats, curve, baseEncoding);
+
+                    return new ECDomainParameters(curve, basePoint, order, cofactor);
+                }
+                case ECCurveType.named_curve:
+                {
+                    int namedCurve = TlsUtilities.ReadUint16(input);
+                    if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve))
+                    {
+                        /*
+                         * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a
+                         * specific curve. Values of NamedCurve that indicate support for a class of
+                         * explicitly defined curves are not allowed here [...].
+                         */
+                        throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                    }
+
+                    CheckNamedCurve(namedCurves, namedCurve);
+
+                    return GetParametersForNamedCurve(namedCurve);
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter, e);
+            }
+        }
+
+        private static void CheckNamedCurve(int[] namedCurves, int namedCurve)
+        {
+            if (namedCurves != null && !Arrays.Contains(namedCurves, namedCurve))
+            {
+                /*
+                 * RFC 4492 4. [...] servers MUST NOT negotiate the use of an ECC cipher suite
+                 * unless they can complete the handshake while respecting the choice of curves
+                 * and compression techniques specified by the client.
+                 */
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+        }
+
+        public static void WriteECExponent(int k, Stream output)
+        {
+            BigInteger K = BigInteger.ValueOf(k);
+            WriteECParameter(K, output);
+        }
+
+        public static void WriteECFieldElement(ECFieldElement x, Stream output)
+        {
+            TlsUtilities.WriteOpaque8(x.GetEncoded(), output);
+        }
+
+        public static void WriteECFieldElement(int fieldSize, BigInteger x, Stream output)
+        {
+            TlsUtilities.WriteOpaque8(SerializeECFieldElement(fieldSize, x), output);
+        }
+
+        public static void WriteECParameter(BigInteger x, Stream output)
+        {
+            TlsUtilities.WriteOpaque8(BigIntegers.AsUnsignedByteArray(x), output);
+        }
+
+        public static void WriteExplicitECParameters(byte[] ecPointFormats, ECDomainParameters ecParameters,
+            Stream output)
+        {
+            ECCurve curve = ecParameters.Curve;
+
+            if (ECAlgorithms.IsFpCurve(curve))
+            {
+                TlsUtilities.WriteUint8(ECCurveType.explicit_prime, output);
+
+                WriteECParameter(curve.Field.Characteristic, output);
+            }
+            else if (ECAlgorithms.IsF2mCurve(curve))
+            {
+                IPolynomialExtensionField field = (IPolynomialExtensionField)curve.Field;
+                int[] exponents = field.MinimalPolynomial.GetExponentsPresent();
+
+                TlsUtilities.WriteUint8(ECCurveType.explicit_char2, output);
+
+                int m = exponents[exponents.Length - 1];
+                TlsUtilities.CheckUint16(m);
+                TlsUtilities.WriteUint16(m, output);
+
+                if (exponents.Length == 3)
+                {
+                    TlsUtilities.WriteUint8(ECBasisType.ec_basis_trinomial, output);
+                    WriteECExponent(exponents[1], output);
+                }
+                else if (exponents.Length == 5)
+                {
+                    TlsUtilities.WriteUint8(ECBasisType.ec_basis_pentanomial, output);
+                    WriteECExponent(exponents[1], output);
+                    WriteECExponent(exponents[2], output);
+                    WriteECExponent(exponents[3], output);
+                }
+                else
+                {
+                    throw new ArgumentException("Only trinomial and pentomial curves are supported");
+                }
+            }
+            else
+            {
+                throw new ArgumentException("'ecParameters' not a known curve type");
+            }
+
+            WriteECFieldElement(curve.A, output);
+            WriteECFieldElement(curve.B, output);
+            TlsUtilities.WriteOpaque8(SerializeECPoint(ecPointFormats, ecParameters.G), output);
+            WriteECParameter(ecParameters.N, output);
+            WriteECParameter(ecParameters.H, output);
+        }
+
+        public static void WriteECPoint(byte[] ecPointFormats, ECPoint point, Stream output)
+        {
+            TlsUtilities.WriteOpaque8(SerializeECPoint(ecPointFormats, point), output);
+        }
+
+        public static void WriteNamedECParameters(int namedCurve, Stream output)
+        {
+            if (!NamedCurve.RefersToASpecificNamedCurve(namedCurve))
+            {
+                /*
+                 * RFC 4492 5.4. All those values of NamedCurve are allowed that refer to a specific
+                 * curve. Values of NamedCurve that indicate support for a class of explicitly defined
+                 * curves are not allowed here [...].
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            TlsUtilities.WriteUint8(ECCurveType.named_curve, output);
+            TlsUtilities.CheckUint16(namedCurve);
+            TlsUtilities.WriteUint16(namedCurve, output);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsEncryptionCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsEncryptionCredentials.cs
new file mode 100644
index 0000000..52f0070
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsEncryptionCredentials.cs
@@ -0,0 +1,12 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsEncryptionCredentials
+        :   TlsCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        byte[] DecryptPreMasterSecret(byte[] encryptedPreMasterSecret);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsException.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsException.cs
new file mode 100644
index 0000000..fa3e732
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsException.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public class TlsException : Exception
+	{
+		public TlsException() : base() { }
+		public TlsException(string message) : base(message) { }
+		public TlsException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsExtensionsUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsExtensionsUtilities.cs
new file mode 100644
index 0000000..8876911
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsExtensionsUtilities.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsExtensionsUtilities
+    {
+        public static IDictionary EnsureExtensionsInitialised(IDictionary extensions)
+        {
+            return extensions == null ? Platform.CreateHashtable() : extensions;
+        }
+
+        public static void AddEncryptThenMacExtension(IDictionary extensions)
+        {
+            extensions[ExtensionType.encrypt_then_mac] = CreateEncryptThenMacExtension();
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static void AddHeartbeatExtension(IDictionary extensions, HeartbeatExtension heartbeatExtension)
+        {
+            extensions[ExtensionType.heartbeat] = CreateHeartbeatExtension(heartbeatExtension);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static void AddMaxFragmentLengthExtension(IDictionary extensions, byte maxFragmentLength)
+        {
+            extensions[ExtensionType.max_fragment_length] = CreateMaxFragmentLengthExtension(maxFragmentLength);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static void AddServerNameExtension(IDictionary extensions, ServerNameList serverNameList)
+        {
+            extensions[ExtensionType.server_name] = CreateServerNameExtension(serverNameList);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static void AddStatusRequestExtension(IDictionary extensions, CertificateStatusRequest statusRequest)
+        {
+            extensions[ExtensionType.status_request] = CreateStatusRequestExtension(statusRequest);
+        }
+
+        public static void AddTruncatedHMacExtension(IDictionary extensions)
+        {
+            extensions[ExtensionType.truncated_hmac] = CreateTruncatedHMacExtension();
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static HeartbeatExtension GetHeartbeatExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.heartbeat);
+            return extensionData == null ? null : ReadHeartbeatExtension(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static short GetMaxFragmentLengthExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.max_fragment_length);
+            return extensionData == null ? (short)-1 : (short)ReadMaxFragmentLengthExtension(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static ServerNameList GetServerNameExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.server_name);
+            return extensionData == null ? null : ReadServerNameExtension(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static CertificateStatusRequest GetStatusRequestExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.status_request);
+            return extensionData == null ? null : ReadStatusRequestExtension(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static bool HasEncryptThenMacExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.encrypt_then_mac);
+            return extensionData == null ? false : ReadEncryptThenMacExtension(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static bool HasTruncatedHMacExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.truncated_hmac);
+            return extensionData == null ? false : ReadTruncatedHMacExtension(extensionData);
+        }
+
+        public static byte[] CreateEmptyExtensionData()
+        {
+            return TlsUtilities.EmptyBytes;
+        }
+
+        public static byte[] CreateEncryptThenMacExtension()
+        {
+            return CreateEmptyExtensionData();
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static byte[] CreateHeartbeatExtension(HeartbeatExtension heartbeatExtension)
+        {
+            if (heartbeatExtension == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            MemoryStream buf = new MemoryStream();
+
+            heartbeatExtension.Encode(buf);
+
+            return buf.ToArray();
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static byte[] CreateMaxFragmentLengthExtension(byte maxFragmentLength)
+        {
+            if (!MaxFragmentLength.IsValid(maxFragmentLength))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            return new byte[]{ maxFragmentLength };
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static byte[] CreateServerNameExtension(ServerNameList serverNameList)
+        {
+            if (serverNameList == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            MemoryStream buf = new MemoryStream();
+        
+            serverNameList.Encode(buf);
+
+            return buf.ToArray();
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static byte[] CreateStatusRequestExtension(CertificateStatusRequest statusRequest)
+        {
+            if (statusRequest == null)
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            MemoryStream buf = new MemoryStream();
+
+            statusRequest.Encode(buf);
+
+            return buf.ToArray();
+        }
+
+        public static byte[] CreateTruncatedHMacExtension()
+        {
+            return CreateEmptyExtensionData();
+        }
+
+        /// <exception cref="IOException"></exception>
+        private static bool ReadEmptyExtensionData(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            if (extensionData.Length != 0)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return true;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static bool ReadEncryptThenMacExtension(byte[] extensionData)
+        {
+            return ReadEmptyExtensionData(extensionData);
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static HeartbeatExtension ReadHeartbeatExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            HeartbeatExtension heartbeatExtension = HeartbeatExtension.Parse(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return heartbeatExtension;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static short ReadMaxFragmentLengthExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            if (extensionData.Length != 1)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            byte maxFragmentLength = extensionData[0];
+
+            if (!MaxFragmentLength.IsValid(maxFragmentLength))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return maxFragmentLength;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static ServerNameList ReadServerNameExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            ServerNameList serverNameList = ServerNameList.Parse(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return serverNameList;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static CertificateStatusRequest ReadStatusRequestExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            CertificateStatusRequest statusRequest = CertificateStatusRequest.Parse(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return statusRequest;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public static bool ReadTruncatedHMacExtension(byte[] extensionData)
+        {
+            return ReadEmptyExtensionData(extensionData);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsFatalAlert.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsFatalAlert.cs
new file mode 100644
index 0000000..0c7ed88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsFatalAlert.cs
@@ -0,0 +1,27 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsFatalAlert
+        : IOException
+    {
+        private readonly byte alertDescription;
+
+        public TlsFatalAlert(byte alertDescription)
+            : this(alertDescription, null)
+        {
+        }
+
+        public TlsFatalAlert(byte alertDescription, Exception alertCause)
+            :   base("Fatal alert: " + alertDescription, alertCause)
+        {
+            this.alertDescription = alertDescription;
+        }
+
+        public virtual byte AlertDescription
+        {
+            get { return alertDescription; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsHandshakeHash.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsHandshakeHash.cs
new file mode 100644
index 0000000..7118d97
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsHandshakeHash.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsHandshakeHash
+        :   IDigest
+    {
+        void Init(TlsContext context);
+
+        TlsHandshakeHash NotifyPrfDetermined();
+
+        void TrackHashAlgorithm(byte hashAlgorithm);
+
+        void SealHashAlgorithms();
+
+        TlsHandshakeHash StopTracking();
+
+        IDigest ForkPrfHash();
+
+        byte[] GetFinalHash(byte hashAlgorithm);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsKeyExchange.cs
new file mode 100644
index 0000000..6731f6f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsKeyExchange.cs
@@ -0,0 +1,54 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// A generic interface for key exchange implementations in (D)TLS.
+    /// </summary>
+    public interface TlsKeyExchange
+    {
+        void Init(TlsContext context);
+
+        /// <exception cref="IOException"/>
+        void SkipServerCredentials();
+
+        /// <exception cref="IOException"/>
+        void ProcessServerCredentials(TlsCredentials serverCredentials);
+
+        /// <exception cref="IOException"/>
+        void ProcessServerCertificate(Certificate serverCertificate);
+
+        bool RequiresServerKeyExchange { get; }
+
+        /// <exception cref="IOException"/>
+        byte[] GenerateServerKeyExchange();
+
+        /// <exception cref="IOException"/>
+        void SkipServerKeyExchange();
+
+        /// <exception cref="IOException"/>
+        void ProcessServerKeyExchange(Stream input);
+
+        /// <exception cref="IOException"/>
+        void ValidateCertificateRequest(CertificateRequest certificateRequest);
+
+        /// <exception cref="IOException"/>
+        void SkipClientCredentials();
+
+        /// <exception cref="IOException"/>
+        void ProcessClientCredentials(TlsCredentials clientCredentials);
+
+        /// <exception cref="IOException"/>
+        void ProcessClientCertificate(Certificate clientCertificate);
+
+        /// <exception cref="IOException"/>
+        void GenerateClientKeyExchange(Stream output);
+
+        /// <exception cref="IOException"/>
+        void ProcessClientKeyExchange(Stream input);
+
+        /// <exception cref="IOException"/>
+        byte[] GeneratePremasterSecret();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsMac.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsMac.cs
new file mode 100644
index 0000000..a80319a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsMac.cs
@@ -0,0 +1,173 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// A generic TLS MAC implementation, acting as an HMAC based on some underlying Digest.
+    /// </summary>
+    public class TlsMac
+    {
+        protected readonly TlsContext context;
+        protected readonly byte[] secret;
+        protected readonly IMac mac;
+        protected readonly int digestBlockSize;
+        protected readonly int digestOverhead;
+        protected readonly int macLength;
+
+        /**
+         * Generate a new instance of an TlsMac.
+         *
+         * @param context the TLS client context
+         * @param digest  The digest to use.
+         * @param key     A byte-array where the key for this MAC is located.
+         * @param keyOff  The number of bytes to skip, before the key starts in the buffer.
+         * @param keyLen  The length of the key.
+         */
+        public TlsMac(TlsContext context, IDigest digest, byte[] key, int keyOff, int keyLen)
+        {
+            this.context = context;
+
+            KeyParameter keyParameter = new KeyParameter(key, keyOff, keyLen);
+
+            this.secret = Arrays.Clone(keyParameter.GetKey());
+
+            // TODO This should check the actual algorithm, not rely on the engine type
+            if (digest is LongDigest)
+            {
+                this.digestBlockSize = 128;
+                this.digestOverhead = 16;
+            }
+            else
+            {
+                this.digestBlockSize = 64;
+                this.digestOverhead = 8;
+            }
+
+            if (TlsUtilities.IsSsl(context))
+            {
+                this.mac = new Ssl3Mac(digest);
+
+                // TODO This should check the actual algorithm, not assume based on the digest size
+                if (digest.GetDigestSize() == 20)
+                {
+                    /*
+                     * NOTE: When SHA-1 is used with the SSL 3.0 MAC, the secret + input pad is not
+                     * digest block-aligned.
+                     */
+                    this.digestOverhead = 4;
+                }
+            }
+            else
+            {
+                this.mac = new HMac(digest);
+
+                // NOTE: The input pad for HMAC is always a full digest block
+            }
+
+            this.mac.Init(keyParameter);
+
+            this.macLength = mac.GetMacSize();
+            if (context.SecurityParameters.truncatedHMac)
+            {
+                this.macLength = System.Math.Min(this.macLength, 10);
+            }
+        }
+
+        /**
+         * @return the MAC write secret
+         */
+        public virtual byte[] MacSecret
+        {
+            get { return this.secret; }
+        }
+
+        /**
+         * @return The output length of this MAC.
+         */
+        public virtual int Size
+        {
+            get { return macLength; }
+        }
+
+        /**
+         * Calculate the MAC for some given data.
+         *
+         * @param type    The message type of the message.
+         * @param message A byte-buffer containing the message.
+         * @param offset  The number of bytes to skip, before the message starts.
+         * @param length  The length of the message.
+         * @return A new byte-buffer containing the MAC value.
+         */
+        public virtual byte[] CalculateMac(long seqNo, byte type, byte[] message, int offset, int length)
+        {
+            ProtocolVersion serverVersion = context.ServerVersion;
+            bool isSsl = serverVersion.IsSsl;
+
+            byte[] macHeader = new byte[isSsl ? 11 : 13];
+            TlsUtilities.WriteUint64(seqNo, macHeader, 0);
+            TlsUtilities.WriteUint8(type, macHeader, 8);
+            if (!isSsl)
+            {
+                TlsUtilities.WriteVersion(serverVersion, macHeader, 9);
+            }
+            TlsUtilities.WriteUint16(length, macHeader, macHeader.Length - 2);
+
+            mac.BlockUpdate(macHeader, 0, macHeader.Length);
+            mac.BlockUpdate(message, offset, length);
+
+            return Truncate(MacUtilities.DoFinal(mac));
+        }
+
+        public virtual byte[] CalculateMacConstantTime(long seqNo, byte type, byte[] message, int offset, int length,
+            int fullLength, byte[] dummyData)
+        {
+            /*
+             * Actual MAC only calculated on 'length' bytes...
+             */
+            byte[] result = CalculateMac(seqNo, type, message, offset, length);
+
+            /*
+             * ...but ensure a constant number of complete digest blocks are processed (as many as would
+             * be needed for 'fullLength' bytes of input).
+             */
+            int headerLength = TlsUtilities.IsSsl(context) ? 11 : 13;
+
+            // How many extra full blocks do we need to calculate?
+            int extra = GetDigestBlockCount(headerLength + fullLength) - GetDigestBlockCount(headerLength + length);
+
+            while (--extra >= 0)
+            {
+                mac.BlockUpdate(dummyData, 0, digestBlockSize);
+            }
+
+            // One more byte in case the implementation is "lazy" about processing blocks
+            mac.Update(dummyData[0]);
+            mac.Reset();
+
+            return result;
+        }
+
+        protected virtual int GetDigestBlockCount(int inputLength)
+        {
+            // NOTE: This calculation assumes a minimum of 1 pad byte
+            return (inputLength + digestOverhead) / digestBlockSize;
+        }
+
+        protected virtual byte[] Truncate(byte[] bs)
+        {
+            if (bs.Length <= macLength)
+            {
+                return bs;
+            }
+
+            return Arrays.CopyOf(bs, macLength);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCipher.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCipher.cs
new file mode 100644
index 0000000..f30ace2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCipher.cs
@@ -0,0 +1,118 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>
+    /// A NULL CipherSuite, with optional MAC.
+    /// </summary>
+    public class TlsNullCipher
+        :   TlsCipher
+    {
+        protected readonly TlsContext context;
+
+        protected readonly TlsMac writeMac;
+        protected readonly TlsMac readMac;
+
+        public TlsNullCipher(TlsContext context)
+        {
+            this.context = context;
+            this.writeMac = null;
+            this.readMac = null;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public TlsNullCipher(TlsContext context, IDigest clientWriteDigest, IDigest serverWriteDigest)
+        {
+            if ((clientWriteDigest == null) != (serverWriteDigest == null))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.context = context;
+
+            TlsMac clientWriteMac = null, serverWriteMac = null;
+
+            if (clientWriteDigest != null)
+            {
+                int key_block_size = clientWriteDigest.GetDigestSize()
+                    + serverWriteDigest.GetDigestSize();
+                byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
+
+                int offset = 0;
+
+                clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+                    clientWriteDigest.GetDigestSize());
+                offset += clientWriteDigest.GetDigestSize();
+
+                serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+                    serverWriteDigest.GetDigestSize());
+                offset += serverWriteDigest.GetDigestSize();
+
+                if (offset != key_block_size)
+                {
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+                }
+            }
+
+            if (context.IsServer)
+            {
+                writeMac = serverWriteMac;
+                readMac = clientWriteMac;
+            }
+            else
+            {
+                writeMac = clientWriteMac;
+                readMac = serverWriteMac;
+            }
+        }
+
+        public virtual int GetPlaintextLimit(int ciphertextLimit)
+        {
+            int result = ciphertextLimit;
+            if (writeMac != null)
+            {
+                result -= writeMac.Size;
+            }
+            return result;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
+        {
+            if (writeMac == null)
+            {
+                return Arrays.CopyOfRange(plaintext, offset, offset + len);
+            }
+
+            byte[] mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
+            byte[] ciphertext = new byte[len + mac.Length];
+            Array.Copy(plaintext, offset, ciphertext, 0, len);
+            Array.Copy(mac, 0, ciphertext, len, mac.Length);
+            return ciphertext;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
+        {
+            if (readMac == null)
+            {
+                return Arrays.CopyOfRange(ciphertext, offset, offset + len);
+            }
+
+            int macSize = readMac.Size;
+            if (len < macSize)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int macInputLen = len - macSize;
+
+            byte[] receivedMac = Arrays.CopyOfRange(ciphertext, offset + macInputLen, offset + len);
+            byte[] computedMac = readMac.CalculateMac(seqNo, type, ciphertext, offset, macInputLen);
+
+            if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac))
+                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+
+            return Arrays.CopyOfRange(ciphertext, offset, offset + macInputLen);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCompression.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCompression.cs
new file mode 100644
index 0000000..45f8fc7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsNullCompression.cs
@@ -0,0 +1,19 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public class TlsNullCompression
+		: TlsCompression
+	{
+		public virtual Stream Compress(Stream output)
+		{
+			return output;
+		}
+
+		public virtual Stream Decompress(Stream output)
+		{
+			return output;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsPeer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPeer.cs
new file mode 100644
index 0000000..1ae41a4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPeer.cs
@@ -0,0 +1,62 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsPeer
+    {
+        /// <summary>
+        /// draft-mathewson-no-gmtunixtime-00 2. "If existing users of a TLS implementation may rely on
+        /// gmt_unix_time containing the current time, we recommend that implementors MAY provide the
+        /// ability to set gmt_unix_time as an option only, off by default."
+        /// </summary>
+        /// <returns>
+        /// <code>true</code> if the current time should be used in the gmt_unix_time field of
+        /// Random, or <code>false</code> if gmt_unix_time should contain a cryptographically
+        /// random value.
+        /// </returns>
+        bool ShouldUseGmtUnixTime();
+
+        /// <summary>
+        /// Report whether the server supports secure renegotiation
+        /// </summary>
+        /// <remarks>
+        /// The protocol handler automatically processes the relevant extensions
+        /// </remarks>
+        /// <param name="secureRenegotiation">
+        /// A <see cref="System.Boolean"/>, true if the server supports secure renegotiation
+        /// </param>
+        /// <exception cref="IOException"></exception>
+        void NotifySecureRenegotiation(bool secureRenegotiation);
+
+        /// <summary>
+        /// Return an implementation of <see cref="TlsCompression"/> to handle record compression.
+        /// </summary>
+        /// <returns>A <see cref="TlsCompression"/></returns>
+        /// <exception cref="IOException"/>
+        TlsCompression GetCompression();
+
+        /// <summary>
+        /// Return an implementation of <see cref="TlsCipher"/> to use for encryption/decryption.
+        /// </summary>
+        /// <returns>A <see cref="TlsCipher"/></returns>
+        /// <exception cref="IOException"/>
+        TlsCipher GetCipher();
+
+        /// <summary>This method will be called when an alert is raised by the protocol.</summary>
+        /// <param name="alertLevel"><see cref="AlertLevel"/></param>
+        /// <param name="alertDescription"><see cref="AlertDescription"/></param>
+        /// <param name="message">A human-readable message explaining what caused this alert. May be null.</param>
+        /// <param name="cause">The <c>Exception</c> that caused this alert to be raised. May be null.</param>
+        void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause);
+
+        /// <summary>This method will be called when an alert is received from the remote peer.</summary>
+        /// <param name="alertLevel"><see cref="AlertLevel"/></param>
+        /// <param name="alertDescription"><see cref="AlertDescription"/></param>
+        void NotifyAlertReceived(byte alertLevel, byte alertDescription);
+
+        /// <summary>Notifies the peer that the handshake has been successfully completed.</summary>
+        /// <exception cref="IOException"></exception>
+        void NotifyHandshakeComplete();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocol.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocol.cs
new file mode 100644
index 0000000..11be322
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocol.cs
@@ -0,0 +1,1102 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsProtocol
+    {
+        private static readonly string TLS_ERROR_MESSAGE = "Internal TLS error, this could be an attack";
+
+        /*
+         * Our Connection states
+         */
+        protected const short CS_START = 0;
+        protected const short CS_CLIENT_HELLO = 1;
+        protected const short CS_SERVER_HELLO = 2;
+        protected const short CS_SERVER_SUPPLEMENTAL_DATA = 3;
+        protected const short CS_SERVER_CERTIFICATE = 4;
+        protected const short CS_CERTIFICATE_STATUS = 5;
+        protected const short CS_SERVER_KEY_EXCHANGE = 6;
+        protected const short CS_CERTIFICATE_REQUEST = 7;
+        protected const short CS_SERVER_HELLO_DONE = 8;
+        protected const short CS_CLIENT_SUPPLEMENTAL_DATA = 9;
+        protected const short CS_CLIENT_CERTIFICATE = 10;
+        protected const short CS_CLIENT_KEY_EXCHANGE = 11;
+        protected const short CS_CERTIFICATE_VERIFY = 12;
+        protected const short CS_CLIENT_FINISHED = 13;
+        protected const short CS_SERVER_SESSION_TICKET = 14;
+        protected const short CS_SERVER_FINISHED = 15;
+        protected const short CS_END = 16;
+
+        /*
+         * Queues for data from some protocols.
+         */
+        private ByteQueue mApplicationDataQueue = new ByteQueue();
+        private ByteQueue mAlertQueue = new ByteQueue(2);
+        private ByteQueue mHandshakeQueue = new ByteQueue();
+    //    private ByteQueue mHeartbeatQueue = new ByteQueue();
+
+        /*
+         * The Record Stream we use
+         */
+        internal RecordStream mRecordStream;
+        protected SecureRandom mSecureRandom;
+
+        private TlsStream mTlsStream = null;
+
+        private volatile bool mClosed = false;
+        private volatile bool mFailedWithError = false;
+        private volatile bool mAppDataReady = false;
+        private volatile bool mSplitApplicationDataRecords = true;
+        private byte[] mExpectedVerifyData = null;
+
+        protected TlsSession mTlsSession = null;
+        protected SessionParameters mSessionParameters = null;
+        protected SecurityParameters mSecurityParameters = null;
+        protected Certificate mPeerCertificate = null;
+
+        protected int[] mOfferedCipherSuites = null;
+        protected byte[] mOfferedCompressionMethods = null;
+        protected IDictionary mClientExtensions = null;
+        protected IDictionary mServerExtensions = null;
+
+        protected short mConnectionState = CS_START;
+        protected bool mResumedSession = false;
+        protected bool mReceivedChangeCipherSpec = false;
+        protected bool mSecureRenegotiation = false;
+        protected bool mAllowCertificateStatus = false;
+        protected bool mExpectSessionTicket = false;
+
+        public TlsProtocol(Stream stream, SecureRandom secureRandom)
+            :   this(stream, stream, secureRandom)
+        {
+        }
+
+        public TlsProtocol(Stream input, Stream output, SecureRandom secureRandom)
+        {
+            this.mRecordStream = new RecordStream(this, input, output);
+            this.mSecureRandom = secureRandom;
+        }
+
+        protected abstract TlsContext Context { get; }
+
+        internal abstract AbstractTlsContext ContextAdmin { get; }
+
+        protected abstract TlsPeer Peer { get; }
+
+        protected virtual void HandleChangeCipherSpecMessage()
+        {
+        }
+
+        protected abstract void HandleHandshakeMessage(byte type, byte[] buf);
+
+        protected virtual void HandleWarningMessage(byte description)
+        {
+        }
+
+        protected virtual void CleanupHandshake()
+        {
+            if (this.mExpectedVerifyData != null)
+            {
+                Arrays.Fill(this.mExpectedVerifyData, (byte)0);
+                this.mExpectedVerifyData = null;
+            }
+
+            this.mSecurityParameters.Clear();
+            this.mPeerCertificate = null;
+
+            this.mOfferedCipherSuites = null;
+            this.mOfferedCompressionMethods = null;
+            this.mClientExtensions = null;
+            this.mServerExtensions = null;
+
+            this.mResumedSession = false;
+            this.mReceivedChangeCipherSpec = false;
+            this.mSecureRenegotiation = false;
+            this.mAllowCertificateStatus = false;
+            this.mExpectSessionTicket = false;
+        }
+
+        protected virtual void CompleteHandshake()
+        {
+            try
+            {
+                /*
+                 * We will now read data, until we have completed the handshake.
+                 */
+                while (this.mConnectionState != CS_END)
+                {
+                    if (this.mClosed)
+                    {
+                        // TODO What kind of exception/alert?
+                    }
+
+                    SafeReadRecord();
+                }
+
+                this.mRecordStream.FinaliseHandshake();
+
+                this.mSplitApplicationDataRecords = !TlsUtilities.IsTlsV11(Context);
+
+                /*
+                 * If this was an initial handshake, we are now ready to send and receive application data.
+                 */
+                if (!mAppDataReady)
+                {
+                    this.mAppDataReady = true;
+
+                    this.mTlsStream = new TlsStream(this);
+                }
+
+                if (this.mTlsSession != null)
+                {
+                    if (this.mSessionParameters == null)
+                    {
+                        this.mSessionParameters = new SessionParameters.Builder()
+                            .SetCipherSuite(this.mSecurityParameters.cipherSuite)
+                            .SetCompressionAlgorithm(this.mSecurityParameters.compressionAlgorithm)
+                            .SetMasterSecret(this.mSecurityParameters.masterSecret)
+                            .SetPeerCertificate(this.mPeerCertificate)
+                            // TODO Consider filtering extensions that aren't relevant to resumed sessions
+                            .SetServerExtensions(this.mServerExtensions)
+                            .Build();
+
+                        this.mTlsSession = new TlsSessionImpl(this.mTlsSession.SessionID, this.mSessionParameters);
+                    }
+
+                    ContextAdmin.SetResumableSession(this.mTlsSession);
+                }
+
+                Peer.NotifyHandshakeComplete();
+            }
+            finally
+            {
+                CleanupHandshake();
+            }
+        }
+
+        protected internal void ProcessRecord(byte protocol, byte[] buf, int offset, int len)
+        {
+            /*
+             * Have a look at the protocol type, and add it to the correct queue.
+             */
+            switch (protocol)
+            {
+            case ContentType.alert:
+            {
+                mAlertQueue.AddData(buf, offset, len);
+                ProcessAlert();
+                break;
+            }
+            case ContentType.application_data:
+            {
+                if (!mAppDataReady)
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                mApplicationDataQueue.AddData(buf, offset, len);
+                ProcessApplicationData();
+                break;
+            }
+            case ContentType.change_cipher_spec:
+            {
+                ProcessChangeCipherSpec(buf, offset, len);
+                break;
+            }
+            case ContentType.handshake:
+            {
+                mHandshakeQueue.AddData(buf, offset, len);
+                ProcessHandshake();
+                break;
+            }
+            case ContentType.heartbeat:
+            {
+                if (!mAppDataReady)
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                // TODO[RFC 6520]
+    //            mHeartbeatQueue.AddData(buf, offset, len);
+    //            ProcessHeartbeat();
+                break;
+            }
+            default:
+                /*
+                 * Uh, we don't know this protocol.
+                 * 
+                 * RFC2246 defines on page 13, that we should ignore this.
+                 */
+                break;
+            }
+        }
+
+        private void ProcessHandshake()
+        {
+            bool read;
+            do
+            {
+                read = false;
+                /*
+                 * We need the first 4 bytes, they contain type and length of the message.
+                 */
+                if (mHandshakeQueue.Available >= 4)
+                {
+                    byte[] beginning = new byte[4];
+                    mHandshakeQueue.Read(beginning, 0, 4, 0);
+                    byte type = TlsUtilities.ReadUint8(beginning, 0);
+                    int len = TlsUtilities.ReadUint24(beginning, 1);
+
+                    /*
+                     * Check if we have enough bytes in the buffer to read the full message.
+                     */
+                    if (mHandshakeQueue.Available >= (len + 4))
+                    {
+                        /*
+                         * Read the message.
+                         */
+                        byte[] buf = mHandshakeQueue.RemoveData(len, 4);
+
+                        /*
+                         * RFC 2246 7.4.9. The value handshake_messages includes all handshake messages
+                         * starting at client hello up to, but not including, this finished message.
+                         * [..] Note: [Also,] Hello Request messages are omitted from handshake hashes.
+                         */
+                        switch (type)
+                        {
+                        case HandshakeType.hello_request:
+                            break;
+                        case HandshakeType.finished:
+                        default:
+                            if (type == HandshakeType.finished && this.mExpectedVerifyData == null)
+                            {
+                                this.mExpectedVerifyData = CreateVerifyData(!Context.IsServer);
+                            }
+
+                            mRecordStream.UpdateHandshakeData(beginning, 0, 4);
+                            mRecordStream.UpdateHandshakeData(buf, 0, len);
+                            break;
+                        }
+
+                        /*
+                         * Now, parse the message.
+                         */
+                        HandleHandshakeMessage(type, buf);
+                        read = true;
+                    }
+                }
+            }
+            while (read);
+        }
+
+        private void ProcessApplicationData()
+        {
+            /*
+             * There is nothing we need to do here.
+             * 
+             * This function could be used for callbacks when application data arrives in the future.
+             */
+        }
+
+        private void ProcessAlert()
+        {
+            while (mAlertQueue.Available >= 2)
+            {
+                /*
+                 * An alert is always 2 bytes. Read the alert.
+                 */
+                byte[] tmp = mAlertQueue.RemoveData(2, 0);
+                byte level = tmp[0];
+                byte description = tmp[1];
+
+                Peer.NotifyAlertReceived(level, description);
+
+                if (level == AlertLevel.fatal)
+                {
+                    /*
+                     * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
+                     * without proper close_notify messages with level equal to warning.
+                     */
+                    InvalidateSession();
+
+                    this.mFailedWithError = true;
+                    this.mClosed = true;
+
+                    mRecordStream.SafeClose();
+
+                    throw new IOException(TLS_ERROR_MESSAGE);
+                }
+                else
+                {
+
+                    /*
+                     * RFC 5246 7.2.1. The other party MUST respond with a close_notify alert of its own
+                     * and close down the connection immediately, discarding any pending writes.
+                     */
+                    // TODO Can close_notify be a fatal alert?
+                    if (description == AlertDescription.close_notify)
+                    {
+                        HandleClose(false);
+                    }
+
+                    /*
+                     * If it is just a warning, we continue.
+                     */
+                    HandleWarningMessage(description);
+                }
+            }
+        }
+
+        /**
+         * This method is called, when a change cipher spec message is received.
+         *
+         * @throws IOException If the message has an invalid content or the handshake is not in the correct
+         * state.
+         */
+        private void ProcessChangeCipherSpec(byte[] buf, int off, int len)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                byte message = TlsUtilities.ReadUint8(buf, off + i);
+
+                if (message != ChangeCipherSpec.change_cipher_spec)
+                    throw new TlsFatalAlert(AlertDescription.decode_error);
+
+                if (this.mReceivedChangeCipherSpec
+                    || mAlertQueue.Available > 0
+                    || mHandshakeQueue.Available > 0)
+                {
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+
+                mRecordStream.ReceivedReadCipherSpec();
+
+                this.mReceivedChangeCipherSpec = true;
+
+                HandleChangeCipherSpecMessage();
+            }
+        }
+
+        protected internal virtual int ApplicationDataAvailable()
+        {
+            return mApplicationDataQueue.Available;
+        }
+
+        /**
+         * Read data from the network. The method will return immediately, if there is still some data
+         * left in the buffer, or block until some application data has been read from the network.
+         *
+         * @param buf    The buffer where the data will be copied to.
+         * @param offset The position where the data will be placed in the buffer.
+         * @param len    The maximum number of bytes to read.
+         * @return The number of bytes read.
+         * @throws IOException If something goes wrong during reading data.
+         */
+        protected internal virtual int ReadApplicationData(byte[] buf, int offset, int len)
+        {
+            if (len < 1)
+                return 0;
+
+            while (mApplicationDataQueue.Available == 0)
+            {
+                /*
+                 * We need to read some data.
+                 */
+                if (this.mClosed)
+                {
+                    if (this.mFailedWithError)
+                    {
+                        /*
+                         * Something went terribly wrong, we should throw an IOException
+                         */
+                        throw new IOException(TLS_ERROR_MESSAGE);
+                    }
+
+                    /*
+                     * Connection has been closed, there is no more data to read.
+                     */
+                    return 0;
+                }
+
+                SafeReadRecord();
+            }
+
+            len = System.Math.Min(len, mApplicationDataQueue.Available);
+            mApplicationDataQueue.RemoveData(buf, offset, len, 0);
+            return len;
+        }
+
+        protected virtual void SafeReadRecord()
+        {
+            try
+            {
+                if (!mRecordStream.ReadRecord())
+                {
+                    // TODO It would be nicer to allow graceful connection close if between records
+    //                this.FailWithError(AlertLevel.warning, AlertDescription.close_notify);
+                    throw new EndOfStreamException();
+                }
+            }
+            catch (TlsFatalAlert e)
+            {
+                if (!mClosed)
+                {
+                    this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to read record", e);
+                }
+                throw e;
+            }
+            catch (Exception e)
+            {
+                if (!mClosed)
+                {
+                    this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to read record", e);
+                }
+                throw e;
+            }
+        }
+
+        protected virtual void SafeWriteRecord(byte type, byte[] buf, int offset, int len)
+        {
+            try
+            {
+                mRecordStream.WriteRecord(type, buf, offset, len);
+            }
+            catch (TlsFatalAlert e)
+            {
+                if (!mClosed)
+                {
+                    this.FailWithError(AlertLevel.fatal, e.AlertDescription, "Failed to write record", e);
+                }
+                throw e;
+            }
+            catch (Exception e)
+            {
+                if (!mClosed)
+                {
+                    this.FailWithError(AlertLevel.fatal, AlertDescription.internal_error, "Failed to write record", e);
+                }
+                throw e;
+            }
+        }
+
+        /**
+         * Send some application data to the remote system.
+         * <p/>
+         * The method will handle fragmentation internally.
+         *
+         * @param buf    The buffer with the data.
+         * @param offset The position in the buffer where the data is placed.
+         * @param len    The length of the data.
+         * @throws IOException If something goes wrong during sending.
+         */
+        protected internal virtual void WriteData(byte[] buf, int offset, int len)
+        {
+            if (this.mClosed)
+            {
+                if (this.mFailedWithError)
+                    throw new IOException(TLS_ERROR_MESSAGE);
+
+                throw new IOException("Sorry, connection has been closed, you cannot write more data");
+            }
+
+            while (len > 0)
+            {
+                /*
+                 * RFC 5246 6.2.1. Zero-length fragments of Application data MAY be sent as they are
+                 * potentially useful as a traffic analysis countermeasure.
+                 * 
+                 * NOTE: Actually, implementations appear to have settled on 1/n-1 record splitting.
+                 */
+
+                if (this.mSplitApplicationDataRecords)
+                {
+                    /*
+                     * Protect against known IV attack!
+                     * 
+                     * DO NOT REMOVE THIS CODE, EXCEPT YOU KNOW EXACTLY WHAT YOU ARE DOING HERE.
+                     */
+                    SafeWriteRecord(ContentType.application_data, buf, offset, 1);
+                    ++offset;
+                    --len;
+                }
+
+                if (len > 0)
+                {
+                    // Fragment data according to the current fragment limit.
+                    int toWrite = System.Math.Min(len, mRecordStream.GetPlaintextLimit());
+                    SafeWriteRecord(ContentType.application_data, buf, offset, toWrite);
+                    offset += toWrite;
+                    len -= toWrite;
+                }
+            }
+        }
+
+        protected virtual void WriteHandshakeMessage(byte[] buf, int off, int len)
+        {
+            while (len > 0)
+            {
+                // Fragment data according to the current fragment limit.
+                int toWrite = System.Math.Min(len, mRecordStream.GetPlaintextLimit());
+                SafeWriteRecord(ContentType.handshake, buf, off, toWrite);
+                off += toWrite;
+                len -= toWrite;
+            }
+        }
+
+        /// <summary>The secure bidirectional stream for this connection</summary>
+        public virtual Stream Stream
+        {
+            get { return this.mTlsStream; }
+        }
+
+        /**
+         * Terminate this connection with an alert. Can be used for normal closure too.
+         * 
+         * @param alertLevel
+         *            See {@link AlertLevel} for values.
+         * @param alertDescription
+         *            See {@link AlertDescription} for values.
+         * @throws IOException
+         *             If alert was fatal.
+         */
+        protected virtual void FailWithError(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            /*
+             * Check if the connection is still open.
+             */
+            if (!mClosed)
+            {
+                /*
+                 * Prepare the message
+                 */
+                this.mClosed = true;
+
+                if (alertLevel == AlertLevel.fatal)
+                {
+                    /*
+                     * RFC 2246 7.2.1. The session becomes unresumable if any connection is terminated
+                     * without proper close_notify messages with level equal to warning.
+                     */
+                    // TODO This isn't quite in the right place. Also, as of TLS 1.1 the above is obsolete.
+                    InvalidateSession();
+
+                    this.mFailedWithError = true;
+                }
+                RaiseAlert(alertLevel, alertDescription, message, cause);
+                mRecordStream.SafeClose();
+                if (alertLevel != AlertLevel.fatal)
+                {
+                    return;
+                }
+            }
+
+            throw new IOException(TLS_ERROR_MESSAGE);
+        }
+
+        protected virtual void InvalidateSession()
+        {
+            if (this.mSessionParameters != null)
+            {
+                this.mSessionParameters.Clear();
+                this.mSessionParameters = null;
+            }
+
+            if (this.mTlsSession != null)
+            {
+                this.mTlsSession.Invalidate();
+                this.mTlsSession = null;
+            }
+        }
+
+        protected virtual void ProcessFinishedMessage(MemoryStream buf)
+        {
+            byte[] verify_data = TlsUtilities.ReadFully(mExpectedVerifyData.Length, buf);
+
+            AssertEmpty(buf);
+
+            /*
+             * Compare both checksums.
+             */
+            if (!Arrays.ConstantTimeAreEqual(mExpectedVerifyData, verify_data))
+            {
+                /*
+                 * Wrong checksum in the finished message.
+                 */
+                throw new TlsFatalAlert(AlertDescription.decrypt_error);
+            }
+        }
+
+        protected virtual void RaiseAlert(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            Peer.NotifyAlertRaised(alertLevel, alertDescription, message, cause);
+
+            byte[] error = new byte[]{ alertLevel, alertDescription };
+
+            SafeWriteRecord(ContentType.alert, error, 0, 2);
+        }
+
+        protected virtual void RaiseWarning(byte alertDescription, string message)
+        {
+            RaiseAlert(AlertLevel.warning, alertDescription, message, null);
+        }
+
+        protected virtual void SendCertificateMessage(Certificate certificate)
+        {
+            if (certificate == null)
+            {
+                certificate = Certificate.EmptyChain;
+            }
+
+            if (certificate.IsEmpty)
+            {
+                TlsContext context = Context;
+                if (!context.IsServer)
+                {
+                    ProtocolVersion serverVersion = Context.ServerVersion;
+                    if (serverVersion.IsSsl)
+                    {
+                        string errorMessage = serverVersion.ToString() + " client didn't provide credentials";
+                        RaiseWarning(AlertDescription.no_certificate, errorMessage);
+                        return;
+                    }
+                }
+            }
+
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate);
+
+            certificate.Encode(message);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendChangeCipherSpecMessage()
+        {
+            byte[] message = new byte[]{ 1 };
+            SafeWriteRecord(ContentType.change_cipher_spec, message, 0, message.Length);
+            mRecordStream.SentWriteCipherSpec();
+        }
+
+        protected virtual void SendFinishedMessage()
+        {
+            byte[] verify_data = CreateVerifyData(Context.IsServer);
+
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.finished, verify_data.Length);
+
+            message.Write(verify_data, 0, verify_data.Length);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendSupplementalDataMessage(IList supplementalData)
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.supplemental_data);
+
+            WriteSupplementalData(message, supplementalData);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual byte[] CreateVerifyData(bool isServer)
+        {
+            TlsContext context = Context;
+            string asciiLabel = isServer ? ExporterLabel.server_finished : ExporterLabel.client_finished;
+            byte[] sslSender = isServer ? TlsUtilities.SSL_SERVER : TlsUtilities.SSL_CLIENT;
+            byte[] hash = GetCurrentPrfHash(context, mRecordStream.HandshakeHash, sslSender);
+            return TlsUtilities.CalculateVerifyData(context, asciiLabel, hash);
+        }
+
+        /**
+         * Closes this connection.
+         *
+         * @throws IOException If something goes wrong during closing.
+         */
+        public virtual void Close()
+        {
+            HandleClose(true);
+        }
+
+        protected virtual void HandleClose(bool user_canceled)
+        {
+            if (!mClosed)
+            {
+                if (user_canceled && !mAppDataReady)
+                {
+                    RaiseWarning(AlertDescription.user_canceled, "User canceled handshake");
+                }
+                this.FailWithError(AlertLevel.warning, AlertDescription.close_notify, "Connection closed", null);
+            }
+        }
+
+        protected internal virtual void Flush()
+        {
+            mRecordStream.Flush();
+        }
+
+        protected internal virtual bool IsClosed
+        {
+            get { return mClosed; }
+        }
+
+        protected virtual short ProcessMaxFragmentLengthExtension(IDictionary clientExtensions, IDictionary serverExtensions,
+            byte alertDescription)
+        {
+            short maxFragmentLength = TlsExtensionsUtilities.GetMaxFragmentLengthExtension(serverExtensions);
+            if (maxFragmentLength >= 0 && !this.mResumedSession)
+            {
+                if (maxFragmentLength != TlsExtensionsUtilities.GetMaxFragmentLengthExtension(clientExtensions))
+                    throw new TlsFatalAlert(alertDescription);
+            }
+            return maxFragmentLength;
+        }
+
+        /**
+         * Make sure the InputStream 'buf' now empty. Fail otherwise.
+         *
+         * @param buf The InputStream to check.
+         * @throws IOException If 'buf' is not empty.
+         */
+        protected internal static void AssertEmpty(MemoryStream buf)
+        {
+            if (buf.Position < buf.Length)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+        }
+
+        protected internal static byte[] CreateRandomBlock(bool useGmtUnixTime, IRandomGenerator randomGenerator)
+        {
+            byte[] result = new byte[32];
+            randomGenerator.NextBytes(result);
+
+            if (useGmtUnixTime)
+            {
+                TlsUtilities.WriteGmtUnixTime(result, 0);
+            }
+
+            return result;
+        }
+
+        protected internal static byte[] CreateRenegotiationInfo(byte[] renegotiated_connection)
+        {
+            return TlsUtilities.EncodeOpaque8(renegotiated_connection);
+        }
+
+        protected internal static void EstablishMasterSecret(TlsContext context, TlsKeyExchange keyExchange)
+        {
+            byte[] pre_master_secret = keyExchange.GeneratePremasterSecret();
+
+            try
+            {
+                context.SecurityParameters.masterSecret = TlsUtilities.CalculateMasterSecret(context, pre_master_secret);
+            }
+            finally
+            {
+                // TODO Is there a way to ensure the data is really overwritten?
+                /*
+                 * RFC 2246 8.1. The pre_master_secret should be deleted from memory once the
+                 * master_secret has been computed.
+                 */
+                if (pre_master_secret != null)
+                {
+                    Arrays.Fill(pre_master_secret, (byte)0);
+                }
+            }
+        }
+
+        /**
+         * 'sender' only relevant to SSLv3
+         */
+        protected internal static byte[] GetCurrentPrfHash(TlsContext context, TlsHandshakeHash handshakeHash, byte[] sslSender)
+        {
+            IDigest d = handshakeHash.ForkPrfHash();
+
+            if (sslSender != null && TlsUtilities.IsSsl(context))
+            {
+                d.BlockUpdate(sslSender, 0, sslSender.Length);
+            }
+
+            return DigestUtilities.DoFinal(d);
+        }
+
+        protected internal static IDictionary ReadExtensions(MemoryStream input)
+        {
+            if (input.Position >= input.Length)
+                return null;
+
+            byte[] extBytes = TlsUtilities.ReadOpaque16(input);
+
+            AssertEmpty(input);
+
+            MemoryStream buf = new MemoryStream(extBytes, false);
+
+            // Integer -> byte[]
+            IDictionary extensions = Platform.CreateHashtable();
+
+            while (buf.Position < buf.Length)
+            {
+                int extension_type = TlsUtilities.ReadUint16(buf);
+                byte[] extension_data = TlsUtilities.ReadOpaque16(buf);
+
+                /*
+                 * RFC 3546 2.3 There MUST NOT be more than one extension of the same type.
+                 */
+                if (extensions.Contains(extension_type))
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+                extensions.Add(extension_type, extension_data);
+            }
+
+            return extensions;
+        }
+
+        protected internal static IList ReadSupplementalDataMessage(MemoryStream input)
+        {
+            byte[] supp_data = TlsUtilities.ReadOpaque24(input);
+
+            AssertEmpty(input);
+
+            MemoryStream buf = new MemoryStream(supp_data, false);
+
+            IList supplementalData = Platform.CreateArrayList();
+
+            while (buf.Position < buf.Length)
+            {
+                int supp_data_type = TlsUtilities.ReadUint16(buf);
+                byte[] data = TlsUtilities.ReadOpaque16(buf);
+
+                supplementalData.Add(new SupplementalDataEntry(supp_data_type, data));
+            }
+
+            return supplementalData;
+        }
+
+        protected internal static void WriteExtensions(Stream output, IDictionary extensions)
+        {
+            MemoryStream buf = new MemoryStream();
+
+            foreach (int extension_type in extensions.Keys)
+            {
+                byte[] extension_data = (byte[])extensions[extension_type];
+
+                TlsUtilities.CheckUint16(extension_type);
+                TlsUtilities.WriteUint16(extension_type, buf);
+                TlsUtilities.WriteOpaque16(extension_data, buf);
+            }
+
+            byte[] extBytes = buf.ToArray();
+
+            TlsUtilities.WriteOpaque16(extBytes, output);
+        }
+
+        protected internal static void WriteSupplementalData(Stream output, IList supplementalData)
+        {
+            MemoryStream buf = new MemoryStream();
+
+            foreach (SupplementalDataEntry entry in supplementalData)
+            {
+                int supp_data_type = entry.DataType;
+                TlsUtilities.CheckUint16(supp_data_type);
+                TlsUtilities.WriteUint16(supp_data_type, buf);
+                TlsUtilities.WriteOpaque16(entry.Data, buf);
+            }
+
+            byte[] supp_data = buf.ToArray();
+
+            TlsUtilities.WriteOpaque24(supp_data, output);
+        }
+
+        protected internal static int GetPrfAlgorithm(TlsContext context, int ciphersuite)
+        {
+            bool isTLSv12 = TlsUtilities.IsTlsV12(context);
+
+            switch (ciphersuite)
+            {
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+            {
+                if (isTLSv12)
+                {
+                    return PrfAlgorithm.tls_prf_sha256;
+                }
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            {
+                if (isTLSv12)
+                {
+                    return PrfAlgorithm.tls_prf_sha384;
+                }
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+            {
+                if (isTLSv12)
+                {
+                    return PrfAlgorithm.tls_prf_sha384;
+                }
+                return PrfAlgorithm.tls_prf_legacy;
+            }
+
+            default:
+            {
+                if (isTLSv12)
+                {
+                    return PrfAlgorithm.tls_prf_sha256;
+                }
+                return PrfAlgorithm.tls_prf_legacy;
+            }
+            }
+        }
+
+        internal class HandshakeMessage
+            :   MemoryStream
+        {
+            internal HandshakeMessage(byte handshakeType)
+                :   this(handshakeType, 60)
+            {
+            }
+
+            internal HandshakeMessage(byte handshakeType, int length)
+                :   base(length + 4)
+            {
+                TlsUtilities.WriteUint8(handshakeType, this);
+                // Reserve space for length
+                TlsUtilities.WriteUint24(0, this);
+            }
+
+            internal void Write(byte[] data)
+            {
+                Write(data, 0, data.Length);
+            }
+
+            internal void WriteToRecordStream(TlsProtocol protocol)
+            {
+                // Patch actual length back in
+                long length = Length - 4;
+                TlsUtilities.CheckUint24(length);
+                this.Position = 1;
+                TlsUtilities.WriteUint24((int)length, this);
+                protocol.WriteHandshakeMessage(ToArray(), 0, (int)Length);
+                this.Dispose();
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocolHandler.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocolHandler.cs
new file mode 100644
index 0000000..6f22346
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsProtocolHandler.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Agreement.Srp;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    [Obsolete("Use 'TlsClientProtocol' instead")]
+    public class TlsProtocolHandler
+        :   TlsClientProtocol
+    {
+        public TlsProtocolHandler(Stream stream, SecureRandom secureRandom)
+            :   base(stream, stream, secureRandom)
+        {
+        }
+
+        /// <remarks>Both streams can be the same object</remarks>
+        public TlsProtocolHandler(Stream input, Stream output, SecureRandom	secureRandom)
+            :   base(input, output, secureRandom)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskIdentity.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskIdentity.cs
new file mode 100644
index 0000000..119064e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskIdentity.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+	public interface TlsPskIdentity
+	{
+		void SkipIdentityHint();
+
+		void NotifyIdentityHint(byte[] psk_identity_hint);
+
+		byte[] GetPskIdentity();
+
+		byte[] GetPsk();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskKeyExchange.cs
new file mode 100644
index 0000000..cd13e34
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsPskKeyExchange.cs
@@ -0,0 +1,254 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS PSK key exchange (RFC 4279).</summary>
+    public class TlsPskKeyExchange
+        :   AbstractTlsKeyExchange
+    {
+        protected TlsPskIdentity mPskIdentity;
+        protected DHParameters mDHParameters;
+        protected int[] mNamedCurves;
+        protected byte[] mClientECPointFormats, mServerECPointFormats;
+
+        protected byte[] mPskIdentityHint = null;
+
+        protected DHPrivateKeyParameters mDHAgreePrivateKey = null;
+        protected DHPublicKeyParameters mDHAgreePublicKey = null;
+
+        protected AsymmetricKeyParameter mServerPublicKey = null;
+        protected RsaKeyParameters mRsaServerPublicKey = null;
+        protected TlsEncryptionCredentials mServerCredentials = null;
+        protected byte[] mPremasterSecret;
+
+        public TlsPskKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, TlsPskIdentity pskIdentity,
+            DHParameters dhParameters, int[] namedCurves, byte[] clientECPointFormats, byte[] serverECPointFormats)
+            :   base(keyExchange, supportedSignatureAlgorithms)
+        {
+            switch (keyExchange)
+            {
+            case KeyExchangeAlgorithm.DHE_PSK:
+            case KeyExchangeAlgorithm.ECDHE_PSK:
+            case KeyExchangeAlgorithm.PSK:
+            case KeyExchangeAlgorithm.RSA_PSK:
+                break;
+            default:
+                throw new InvalidOperationException("unsupported key exchange algorithm");
+            }
+
+            this.mPskIdentity = pskIdentity;
+            this.mDHParameters = dhParameters;
+            this.mNamedCurves = namedCurves;
+            this.mClientECPointFormats = clientECPointFormats;
+            this.mServerECPointFormats = serverECPointFormats;
+        }
+
+        public override void SkipServerCredentials()
+        {
+            if (mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessServerCredentials(TlsCredentials serverCredentials)
+        {
+            if (!(serverCredentials is TlsEncryptionCredentials))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            ProcessServerCertificate(serverCredentials.Certificate);
+
+            this.mServerCredentials = (TlsEncryptionCredentials)serverCredentials;
+        }
+
+        public override byte[] GenerateServerKeyExchange()
+        {
+            // TODO[RFC 4279] Need a server-side PSK API to determine hint and resolve identities to keys
+            this.mPskIdentityHint = null;
+
+            if (this.mPskIdentityHint == null && !RequiresServerKeyExchange)
+                return null;
+
+            MemoryStream buf = new MemoryStream();
+
+            if (this.mPskIdentityHint == null)
+            {
+                TlsUtilities.WriteOpaque16(TlsUtilities.EmptyBytes, buf);
+            }
+            else
+            {
+                TlsUtilities.WriteOpaque16(this.mPskIdentityHint, buf);
+            }
+
+            if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
+            {
+                if (this.mDHParameters == null)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+
+                this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralServerKeyExchange(context.SecureRandom,
+                    this.mDHParameters, buf);
+            }
+            else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+            {
+                // TODO[RFC 5489]
+            }
+
+            return buf.ToArray();
+        }
+
+        public override void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (mKeyExchange != KeyExchangeAlgorithm.RSA_PSK)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+            if (serverCertificate.IsEmpty)
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+
+            X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+
+            // Sanity check the PublicKeyFactory
+            if (this.mServerPublicKey.IsPrivate)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.mRsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.mServerPublicKey);
+
+            TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment);
+
+            base.ProcessServerCertificate(serverCertificate);
+        }
+
+        public override bool RequiresServerKeyExchange
+        {
+            get
+            {
+                switch (mKeyExchange)
+                {
+                case KeyExchangeAlgorithm.DHE_PSK:
+                case KeyExchangeAlgorithm.ECDHE_PSK:
+                    return true;
+                default:
+                    return false;
+                }
+            }
+        }
+
+        public override void ProcessServerKeyExchange(Stream input)
+        {
+            this.mPskIdentityHint = TlsUtilities.ReadOpaque16(input);
+
+            if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
+            {
+                ServerDHParams serverDHParams = ServerDHParams.Parse(input);
+
+                this.mDHAgreePublicKey = TlsDHUtilities.ValidateDHPublicKey(serverDHParams.PublicKey);
+            }
+            else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+            {
+                // TODO[RFC 5489]
+            }
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public override void GenerateClientKeyExchange(Stream output)
+        {
+            if (mPskIdentityHint == null)
+            {
+                mPskIdentity.SkipIdentityHint();
+            }
+            else
+            {
+                mPskIdentity.NotifyIdentityHint(mPskIdentityHint);
+            }
+
+            byte[] psk_identity = mPskIdentity.GetPskIdentity();
+
+            TlsUtilities.WriteOpaque16(psk_identity, output);
+
+            if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
+            {
+                this.mDHAgreePrivateKey = TlsDHUtilities.GenerateEphemeralClientKeyExchange(context.SecureRandom,
+                    mDHAgreePublicKey.Parameters, output);
+            }
+            else if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+            {
+                // TODO[RFC 5489]
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+            else if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
+            {
+                this.mPremasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context,
+                    this.mRsaServerPublicKey, output);
+            }
+        }
+
+        public override byte[] GeneratePremasterSecret()
+        {
+            byte[] psk = mPskIdentity.GetPsk();
+            byte[] other_secret = GenerateOtherSecret(psk.Length);
+
+            MemoryStream buf = new MemoryStream(4 + other_secret.Length + psk.Length);
+            TlsUtilities.WriteOpaque16(other_secret, buf);
+            TlsUtilities.WriteOpaque16(psk, buf);
+            return buf.ToArray();
+        }
+
+        protected virtual byte[] GenerateOtherSecret(int pskLength)
+        {
+            if (this.mKeyExchange == KeyExchangeAlgorithm.DHE_PSK)
+            {
+                if (mDHAgreePrivateKey != null)
+                {
+                    return TlsDHUtilities.CalculateDHBasicAgreement(mDHAgreePublicKey, mDHAgreePrivateKey);
+                }
+
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            if (this.mKeyExchange == KeyExchangeAlgorithm.ECDHE_PSK)
+            {
+                // TODO[RFC 5489]
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            if (this.mKeyExchange == KeyExchangeAlgorithm.RSA_PSK)
+            {
+                return this.mPremasterSecret;
+            }
+
+            return new byte[pskLength];
+        }
+
+        protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key)
+        {
+            // TODO What is the minimum bit length required?
+            // key.Modulus.BitLength;
+
+            if (!key.Exponent.IsProbablePrime(2))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return key;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaKeyExchange.cs
new file mode 100644
index 0000000..3a0a491
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaKeyExchange.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS and SSLv3 RSA key exchange.</summary>
+    public class TlsRsaKeyExchange
+        :   AbstractTlsKeyExchange
+    {
+        protected AsymmetricKeyParameter serverPublicKey = null;
+
+        protected RsaKeyParameters rsaServerPublicKey = null;
+
+        protected TlsEncryptionCredentials serverCredentials = null;
+
+        protected byte[] premasterSecret;
+
+        public TlsRsaKeyExchange(IList supportedSignatureAlgorithms)
+            :   base(KeyExchangeAlgorithm.RSA, supportedSignatureAlgorithms)
+        {
+        }
+
+        public override void SkipServerCredentials()
+        {
+            throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessServerCredentials(TlsCredentials serverCredentials)
+        {
+            if (!(serverCredentials is TlsEncryptionCredentials))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            ProcessServerCertificate(serverCredentials.Certificate);
+
+            this.serverCredentials = (TlsEncryptionCredentials)serverCredentials;
+        }
+
+        public override void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (serverCertificate.IsEmpty)
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+
+            X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                this.serverPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+
+            // Sanity check the PublicKeyFactory
+            if (this.serverPublicKey.IsPrivate)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            this.rsaServerPublicKey = ValidateRsaPublicKey((RsaKeyParameters)this.serverPublicKey);
+
+            TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.KeyEncipherment);
+
+            base.ProcessServerCertificate(serverCertificate);
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            byte[] types = certificateRequest.CertificateTypes;
+            for (int i = 0; i < types.Length; ++i)
+            {
+                switch (types[i])
+                {
+                case ClientCertificateType.rsa_sign:
+                case ClientCertificateType.dss_sign:
+                case ClientCertificateType.ecdsa_sign:
+                    break;
+                default:
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+            }
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            if (!(clientCredentials is TlsSignerCredentials))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public override void GenerateClientKeyExchange(Stream output)
+        {
+            this.premasterSecret = TlsRsaUtilities.GenerateEncryptedPreMasterSecret(context, rsaServerPublicKey, output);
+        }
+
+        public override void ProcessClientKeyExchange(Stream input)
+        {
+            byte[] encryptedPreMasterSecret;
+            if (TlsUtilities.IsSsl(context))
+            {
+                // TODO Do any SSLv3 clients actually include the length?
+                encryptedPreMasterSecret = Streams.ReadAll(input);
+            }
+            else
+            {
+                encryptedPreMasterSecret = TlsUtilities.ReadOpaque16(input);
+            }
+
+            this.premasterSecret = serverCredentials.DecryptPreMasterSecret(encryptedPreMasterSecret);
+        }
+
+        public override byte[] GeneratePremasterSecret()
+        {
+            if (this.premasterSecret == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            byte[] tmp = this.premasterSecret;
+            this.premasterSecret = null;
+            return tmp;
+        }
+
+        protected virtual RsaKeyParameters ValidateRsaPublicKey(RsaKeyParameters key)
+        {
+            // TODO What is the minimum bit length required?
+            // key.Modulus.BitLength;
+
+            if (!key.Exponent.IsProbablePrime(2))
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            return key;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaSigner.cs
new file mode 100644
index 0000000..6da1c5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaSigner.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsRsaSigner
+        :   AbstractTlsSigner
+    {
+        public override byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+            AsymmetricKeyParameter privateKey, byte[] hash)
+        {
+            ISigner signer = MakeSigner(algorithm, true, true,
+                new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
+            signer.BlockUpdate(hash, 0, hash.Length);
+            return signer.GenerateSignature();
+        }
+
+        public override bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+            AsymmetricKeyParameter publicKey, byte[] hash)
+        {
+            ISigner signer = MakeSigner(algorithm, true, false, publicKey);
+            signer.BlockUpdate(hash, 0, hash.Length);
+            return signer.VerifySignature(sigBytes);
+        }
+
+        public override ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey)
+        {
+            return MakeSigner(algorithm, false, true, new ParametersWithRandom(privateKey, this.mContext.SecureRandom));
+        }
+
+        public override ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey)
+        {
+            return MakeSigner(algorithm, false, false, publicKey);
+        }
+
+        public override bool IsValidPublicKey(AsymmetricKeyParameter publicKey)
+        {
+            return publicKey is RsaKeyParameters && !publicKey.IsPrivate;
+        }
+
+        protected virtual ISigner MakeSigner(SignatureAndHashAlgorithm algorithm, bool raw, bool forSigning,
+            ICipherParameters cp)
+        {
+            if ((algorithm != null) != TlsUtilities.IsTlsV12(mContext))
+                throw new InvalidOperationException();
+            if (algorithm != null && algorithm.Signature != SignatureAlgorithm.rsa)
+                throw new InvalidOperationException();
+
+            IDigest d;
+            if (raw)
+            {
+                d = new NullDigest();
+            }
+            else if (algorithm == null)
+            {
+                d = new CombinedHash();
+            }
+            else
+            {
+                d = TlsUtilities.CreateHash(algorithm.Hash);
+            }
+
+            ISigner s;
+            if (algorithm != null)
+            {
+                /*
+                 * RFC 5246 4.7. In RSA signing, the opaque vector contains the signature generated
+                 * using the RSASSA-PKCS1-v1_5 signature scheme defined in [PKCS1].
+                 */
+                s = new RsaDigestSigner(d, TlsUtilities.GetOidForHashAlgorithm(algorithm.Hash));
+            }
+            else
+            {
+                /*
+                 * RFC 5246 4.7. Note that earlier versions of TLS used a different RSA signature scheme
+                 * that did not include a DigestInfo encoding.
+                 */
+                s = new GenericSigner(CreateRsaImpl(), d);
+            }
+            s.Init(forSigning, cp);
+            return s;
+        }
+
+        protected virtual IAsymmetricBlockCipher CreateRsaImpl()
+        {
+            /*
+             * RFC 5264 7.4.7.1. Implementation note: It is now known that remote timing-based attacks
+             * on TLS are possible, at least when the client and server are on the same LAN.
+             * Accordingly, implementations that use static RSA keys MUST use RSA blinding or some other
+             * anti-timing technique, as described in [TIMING].
+             */
+            return new Pkcs1Encoding(new RsaBlindedEngine());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaUtilities.cs
new file mode 100644
index 0000000..0e42c17
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsRsaUtilities.cs
@@ -0,0 +1,132 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsRsaUtilities
+    {
+        /// <exception cref="IOException"></exception>
+        public static byte[] GenerateEncryptedPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPublicKey,
+            Stream output)
+        {
+            /*
+             * Choose a PremasterSecret and send it encrypted to the server
+             */
+            byte[] premasterSecret = new byte[48];
+            context.SecureRandom.NextBytes(premasterSecret);
+            TlsUtilities.WriteVersion(context.ClientVersion, premasterSecret, 0);
+
+            Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine());
+            encoding.Init(true, new ParametersWithRandom(rsaServerPublicKey, context.SecureRandom));
+
+            try
+            {
+                byte[] encryptedPreMasterSecret = encoding.ProcessBlock(premasterSecret, 0, premasterSecret.Length);
+
+                if (TlsUtilities.IsSsl(context))
+                {
+                    // TODO Do any SSLv3 servers actually expect the length?
+                    output.Write(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
+                }
+                else
+                {
+                    TlsUtilities.WriteOpaque16(encryptedPreMasterSecret, output);
+                }
+            }
+            catch (InvalidCipherTextException e)
+            {
+                /*
+                 * This should never happen, only during decryption.
+                 */
+                throw new TlsFatalAlert(AlertDescription.internal_error, e);
+            }
+
+            return premasterSecret;
+        }
+
+        public static byte[] SafeDecryptPreMasterSecret(TlsContext context, RsaKeyParameters rsaServerPrivateKey,
+            byte[] encryptedPreMasterSecret)
+        {
+            /*
+             * RFC 5246 7.4.7.1.
+             */
+            ProtocolVersion clientVersion = context.ClientVersion;
+
+            // TODO Provide as configuration option?
+            bool versionNumberCheckDisabled = false;
+
+            /*
+             * Generate 48 random bytes we can use as a Pre-Master-Secret, if the
+             * PKCS1 padding check should fail.
+             */
+            byte[] fallback = new byte[48];
+            context.SecureRandom.NextBytes(fallback);
+
+            byte[] M = Arrays.Clone(fallback);
+            try
+            {
+                Pkcs1Encoding encoding = new Pkcs1Encoding(new RsaBlindedEngine(), fallback);
+                encoding.Init(false,
+                    new ParametersWithRandom(rsaServerPrivateKey, context.SecureRandom));
+
+                M = encoding.ProcessBlock(encryptedPreMasterSecret, 0, encryptedPreMasterSecret.Length);
+            }
+            catch (Exception)
+            {
+                /*
+                 * This should never happen since the decryption should never throw an exception
+                 * and return a random value instead.
+                 *
+                 * In any case, a TLS server MUST NOT generate an alert if processing an
+                 * RSA-encrypted premaster secret message fails, or the version number is not as
+                 * expected. Instead, it MUST continue the handshake with a randomly generated
+                 * premaster secret.
+                 */
+            }
+
+            /*
+             * If ClientHello.client_version is TLS 1.1 or higher, server implementations MUST
+             * check the version number [..].
+             */
+            if (versionNumberCheckDisabled && clientVersion.IsEqualOrEarlierVersionOf(ProtocolVersion.TLSv10))
+            {
+                /*
+                 * If the version number is TLS 1.0 or earlier, server
+                 * implementations SHOULD check the version number, but MAY have a
+                 * configuration option to disable the check.
+                 *
+                 * So there is nothing to do here.
+                 */
+            }
+            else
+            {
+                /*
+                 * OK, we need to compare the version number in the decrypted Pre-Master-Secret with the
+                 * clientVersion received during the handshake. If they don't match, we replace the
+                 * decrypted Pre-Master-Secret with a random one.
+                 */
+                int correct = (clientVersion.MajorVersion ^ (M[0] & 0xff))
+                    | (clientVersion.MinorVersion ^ (M[1] & 0xff));
+                correct |= correct >> 1;
+                correct |= correct >> 2;
+                correct |= correct >> 4;
+                int mask = ~((correct & 1) - 1);
+
+                /*
+                 * mask will be all bits set to 0xff if the version number differed.
+                 */
+                for (int i = 0; i < 48; i++)
+                {
+                    M[i] = (byte)((M[i] & (~mask)) | (fallback[i] & mask));
+                }
+            }
+            return M;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsServer.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServer.cs
new file mode 100644
index 0000000..93e62b9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServer.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsServer
+        :   TlsPeer
+    {
+        void Init(TlsServerContext context);
+
+        /// <exception cref="IOException"></exception>
+        void NotifyClientVersion(ProtocolVersion clientVersion);
+
+        /// <exception cref="IOException"></exception>
+        void NotifyOfferedCipherSuites(int[] offeredCipherSuites);
+
+        /// <exception cref="IOException"></exception>
+        void NotifyOfferedCompressionMethods(byte[] offeredCompressionMethods);
+
+        /// <param name="clientExtensions">A <see cref="IDictionary"/> (Int32 -> byte[]). Will never be null.</param>
+        /// <exception cref="IOException"></exception>
+        void ProcessClientExtensions(IDictionary clientExtensions);
+
+        /// <exception cref="IOException"></exception>
+        ProtocolVersion GetServerVersion();
+
+        /// <exception cref="IOException"></exception>
+        int GetSelectedCipherSuite();
+
+        /// <exception cref="IOException"></exception>
+        byte GetSelectedCompressionMethod();
+
+        /// <summary>
+        /// Get the (optional) table of server extensions to be included in (extended) server hello.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="IDictionary"/> (Int32 -> byte[]). May be null.
+        /// </returns>
+        /// <exception cref="IOException"></exception>
+        IDictionary GetServerExtensions();
+
+        /// <returns>
+        /// A <see cref="IList"/> (<see cref="SupplementalDataEntry"/>). May be null.
+        /// </returns>
+        /// <exception cref="IOException"></exception>
+        IList GetServerSupplementalData();
+
+        /// <exception cref="IOException"></exception>
+        TlsCredentials GetCredentials();
+
+        /// <remarks>
+        /// This method will be called (only) if the server included an extension of type
+        /// "status_request" with empty "extension_data" in the extended server hello. See <i>RFC 3546
+        /// 3.6. Certificate Status Request</i>. If a non-null <see cref="CertificateStatus"/> is returned, it
+        /// is sent to the client as a handshake message of type "certificate_status".
+        /// </remarks>
+        /// <returns>A <see cref="CertificateStatus"/> to be sent to the client (or null for none).</returns>
+        /// <exception cref="IOException"></exception>
+        CertificateStatus GetCertificateStatus();
+
+        /// <exception cref="IOException"></exception>
+        TlsKeyExchange GetKeyExchange();
+
+        /// <exception cref="IOException"></exception>
+        CertificateRequest GetCertificateRequest();
+
+        /// <param name="clientSupplementalData"><see cref="IList"/> (<see cref="SupplementalDataEntry"/>)</param>
+        /// <exception cref="IOException"></exception>
+        void ProcessClientSupplementalData(IList clientSupplementalData);
+
+        /// <summary>
+        /// Called by the protocol handler to report the client certificate, only if <c>GetCertificateRequest</c>
+        /// returned non-null.
+        /// </summary>
+        /// <remarks>Note: this method is responsible for certificate verification and validation.</remarks>
+        /// <param name="clientCertificate">the effective client certificate (may be an empty chain).</param>
+        /// <exception cref="IOException"></exception>
+        void NotifyClientCertificate(Certificate clientCertificate);
+
+        /// <summary>RFC 5077 3.3. NewSessionTicket Handshake Message.</summary>
+        /// <remarks>
+        /// This method will be called (only) if a NewSessionTicket extension was sent by the server. See
+        /// <i>RFC 5077 4. Recommended Ticket Construction</i> for recommended format and protection.
+        /// </remarks>
+        /// <returns>The <see cref="NewSessionTicket">ticket</see>)</returns>
+        /// <exception cref="IOException"></exception>
+        NewSessionTicket GetNewSessionTicket();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContext.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContext.cs
new file mode 100644
index 0000000..4021571
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContext.cs
@@ -0,0 +1,11 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsServerContext
+        : TlsContext
+    {
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContextImpl.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContextImpl.cs
new file mode 100644
index 0000000..d56566f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerContextImpl.cs
@@ -0,0 +1,20 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class TlsServerContextImpl
+        : AbstractTlsContext, TlsServerContext
+    {
+        internal TlsServerContextImpl(SecureRandom secureRandom, SecurityParameters securityParameters)
+            : base(secureRandom, securityParameters)
+        {
+        }
+
+        public override bool IsServer
+        {
+            get { return true; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerProtocol.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerProtocol.cs
new file mode 100644
index 0000000..589ede8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsServerProtocol.cs
@@ -0,0 +1,744 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsServerProtocol
+        :   TlsProtocol
+    {
+        protected TlsServer mTlsServer = null;
+        internal TlsServerContextImpl mTlsServerContext = null;
+
+        protected TlsKeyExchange mKeyExchange = null;
+        protected TlsCredentials mServerCredentials = null;
+        protected CertificateRequest mCertificateRequest = null;
+
+        protected short mClientCertificateType = -1;
+        protected TlsHandshakeHash mPrepareFinishHash = null;
+
+        public TlsServerProtocol(Stream stream, SecureRandom secureRandom)
+            :   base(stream, secureRandom)
+        {
+        }
+
+        public TlsServerProtocol(Stream input, Stream output, SecureRandom secureRandom)
+            :   base(input, output, secureRandom)
+        {
+        }
+
+        /**
+         * Receives a TLS handshake in the role of server
+         *
+         * @param mTlsServer
+         * @throws IOException If handshake was not successful.
+         */
+        public virtual void Accept(TlsServer tlsServer)
+        {
+            if (tlsServer == null)
+                throw new ArgumentNullException("tlsServer");
+            if (this.mTlsServer != null)
+                throw new InvalidOperationException("'Accept' can only be called once");
+
+            this.mTlsServer = tlsServer;
+
+            this.mSecurityParameters = new SecurityParameters();
+            this.mSecurityParameters.entity = ConnectionEnd.server;
+
+            this.mTlsServerContext = new TlsServerContextImpl(mSecureRandom, mSecurityParameters);
+
+            this.mSecurityParameters.serverRandom = CreateRandomBlock(tlsServer.ShouldUseGmtUnixTime(),
+                mTlsServerContext.NonceRandomGenerator);
+
+            this.mTlsServer.Init(mTlsServerContext);
+            this.mRecordStream.Init(mTlsServerContext);
+
+            this.mRecordStream.SetRestrictReadVersion(false);
+
+            CompleteHandshake();
+        }
+
+        protected override void CleanupHandshake()
+        {
+            base.CleanupHandshake();
+        
+            this.mKeyExchange = null;
+            this.mServerCredentials = null;
+            this.mCertificateRequest = null;
+            this.mPrepareFinishHash = null;
+        }
+
+        protected override TlsContext Context
+        {
+            get { return mTlsServerContext; }
+        }
+
+        internal override AbstractTlsContext ContextAdmin
+        {
+            get { return mTlsServerContext; }
+        }
+
+        protected override TlsPeer Peer
+        {
+            get { return mTlsServer; }
+        }
+
+        protected override void HandleHandshakeMessage(byte type, byte[] data)
+        {
+            MemoryStream buf = new MemoryStream(data);
+
+            switch (type)
+            {
+            case HandshakeType.client_hello:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_START:
+                {
+                    ReceiveClientHelloMessage(buf);
+                    this.mConnectionState = CS_CLIENT_HELLO;
+
+                    SendServerHelloMessage();
+                    this.mConnectionState = CS_SERVER_HELLO;
+
+                    IList serverSupplementalData = mTlsServer.GetServerSupplementalData();
+                    if (serverSupplementalData != null)
+                    {
+                        SendSupplementalDataMessage(serverSupplementalData);
+                    }
+                    this.mConnectionState = CS_SERVER_SUPPLEMENTAL_DATA;
+
+                    this.mKeyExchange = mTlsServer.GetKeyExchange();
+                    this.mKeyExchange.Init(Context);
+
+                    this.mServerCredentials = mTlsServer.GetCredentials();
+
+                    Certificate serverCertificate = null;
+
+                    if (this.mServerCredentials == null)
+                    {
+                        this.mKeyExchange.SkipServerCredentials();
+                    }
+                    else
+                    {
+                        this.mKeyExchange.ProcessServerCredentials(this.mServerCredentials);
+
+                        serverCertificate = this.mServerCredentials.Certificate;
+                        SendCertificateMessage(serverCertificate);
+                    }
+                    this.mConnectionState = CS_SERVER_CERTIFICATE;
+
+                    // TODO[RFC 3546] Check whether empty certificates is possible, allowed, or excludes CertificateStatus
+                    if (serverCertificate == null || serverCertificate.IsEmpty)
+                    {
+                        this.mAllowCertificateStatus = false;
+                    }
+
+                    if (this.mAllowCertificateStatus)
+                    {
+                        CertificateStatus certificateStatus = mTlsServer.GetCertificateStatus();
+                        if (certificateStatus != null)
+                        {
+                            SendCertificateStatusMessage(certificateStatus);
+                        }
+                    }
+
+                    this.mConnectionState = CS_CERTIFICATE_STATUS;
+
+                    byte[] serverKeyExchange = this.mKeyExchange.GenerateServerKeyExchange();
+                    if (serverKeyExchange != null)
+                    {
+                        SendServerKeyExchangeMessage(serverKeyExchange);
+                    }
+                    this.mConnectionState = CS_SERVER_KEY_EXCHANGE;
+
+                    if (this.mServerCredentials != null)
+                    {
+                        this.mCertificateRequest = mTlsServer.GetCertificateRequest();
+                        if (this.mCertificateRequest != null)
+                        {
+                            this.mKeyExchange.ValidateCertificateRequest(mCertificateRequest);
+
+                            SendCertificateRequestMessage(mCertificateRequest);
+
+                            TlsUtilities.TrackHashAlgorithms(this.mRecordStream.HandshakeHash,
+                                this.mCertificateRequest.SupportedSignatureAlgorithms);
+                        }
+                    }
+                    this.mConnectionState = CS_CERTIFICATE_REQUEST;
+
+                    SendServerHelloDoneMessage();
+                    this.mConnectionState = CS_SERVER_HELLO_DONE;
+
+                    this.mRecordStream.HandshakeHash.SealHashAlgorithms();
+
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.supplemental_data:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO_DONE:
+                {
+                    mTlsServer.ProcessClientSupplementalData(ReadSupplementalDataMessage(buf));
+                    this.mConnectionState = CS_CLIENT_SUPPLEMENTAL_DATA;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.certificate:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO_DONE:
+                case CS_CLIENT_SUPPLEMENTAL_DATA:
+                {
+                    if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA)
+                    {
+                        mTlsServer.ProcessClientSupplementalData(null);
+                    }
+
+                    if (this.mCertificateRequest == null)
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                    ReceiveCertificateMessage(buf);
+                    this.mConnectionState = CS_CLIENT_CERTIFICATE;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.client_key_exchange:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_SERVER_HELLO_DONE:
+                case CS_CLIENT_SUPPLEMENTAL_DATA:
+                case CS_CLIENT_CERTIFICATE:
+                {
+                    if (mConnectionState < CS_CLIENT_SUPPLEMENTAL_DATA)
+                    {
+                        mTlsServer.ProcessClientSupplementalData(null);
+                    }
+
+                    if (mConnectionState < CS_CLIENT_CERTIFICATE)
+                    {
+                        if (this.mCertificateRequest == null)
+                        {
+                            this.mKeyExchange.SkipClientCredentials();
+                        }
+                        else
+                        {
+                            if (TlsUtilities.IsTlsV12(Context))
+                            {
+                                /*
+                                 * RFC 5246 If no suitable certificate is available, the client MUST Send a
+                                 * certificate message containing no certificates.
+                                 * 
+                                 * NOTE: In previous RFCs, this was SHOULD instead of MUST.
+                                 */
+                                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                            }
+                            else if (TlsUtilities.IsSsl(Context))
+                            {
+                                if (this.mPeerCertificate == null)
+                                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                            }
+                            else
+                            {
+                                NotifyClientCertificate(Certificate.EmptyChain);
+                            }
+                        }
+                    }
+
+                    ReceiveClientKeyExchangeMessage(buf);
+                    this.mConnectionState = CS_CLIENT_KEY_EXCHANGE;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.certificate_verify:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_CLIENT_KEY_EXCHANGE:
+                {
+                    /*
+                     * RFC 5246 7.4.8 This message is only sent following a client certificate that has
+                     * signing capability (i.e., all certificates except those containing fixed
+                     * Diffie-Hellman parameters).
+                     */
+                    if (!ExpectCertificateVerifyMessage())
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                    ReceiveCertificateVerifyMessage(buf);
+                    this.mConnectionState = CS_CERTIFICATE_VERIFY;
+
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.finished:
+            {
+                switch (this.mConnectionState)
+                {
+                case CS_CLIENT_KEY_EXCHANGE:
+                case CS_CERTIFICATE_VERIFY:
+                {
+                    if (mConnectionState < CS_CERTIFICATE_VERIFY && ExpectCertificateVerifyMessage())
+                        throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+                    ProcessFinishedMessage(buf);
+                    this.mConnectionState = CS_CLIENT_FINISHED;
+
+                    if (this.mExpectSessionTicket)
+                    {
+                        SendNewSessionTicketMessage(mTlsServer.GetNewSessionTicket());
+                        SendChangeCipherSpecMessage();
+                    }
+                    this.mConnectionState = CS_SERVER_SESSION_TICKET;
+
+                    SendFinishedMessage();
+                    this.mConnectionState = CS_SERVER_FINISHED;
+                    this.mConnectionState = CS_END;
+                    break;
+                }
+                default:
+                    throw new TlsFatalAlert(AlertDescription.unexpected_message);
+                }
+                break;
+            }
+            case HandshakeType.hello_request:
+            case HandshakeType.hello_verify_request:
+            case HandshakeType.server_hello:
+            case HandshakeType.server_key_exchange:
+            case HandshakeType.certificate_request:
+            case HandshakeType.server_hello_done:
+            case HandshakeType.session_ticket:
+            default:
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+            }
+        }
+
+        protected override void HandleWarningMessage(byte description)
+        {
+            switch (description)
+            {
+            case AlertDescription.no_certificate:
+            {
+                /*
+                 * SSL 3.0 If the server has sent a certificate request Message, the client must Send
+                 * either the certificate message or a no_certificate alert.
+                 */
+                if (TlsUtilities.IsSsl(Context) && mCertificateRequest != null)
+                {
+                    NotifyClientCertificate(Certificate.EmptyChain);
+                }
+                break;
+            }
+            default:
+            {
+                base.HandleWarningMessage(description);
+                break;
+            }
+            }
+        }
+
+        protected virtual void NotifyClientCertificate(Certificate clientCertificate)
+        {
+            if (mCertificateRequest == null)
+                throw new InvalidOperationException();
+            if (mPeerCertificate != null)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+
+            this.mPeerCertificate = clientCertificate;
+
+            if (clientCertificate.IsEmpty)
+            {
+                this.mKeyExchange.SkipClientCredentials();
+            }
+            else
+            {
+
+                /*
+                 * TODO RFC 5246 7.4.6. If the certificate_authorities list in the certificate request
+                 * message was non-empty, one of the certificates in the certificate chain SHOULD be
+                 * issued by one of the listed CAs.
+                 */
+
+                this.mClientCertificateType = TlsUtilities.GetClientCertificateType(clientCertificate,
+                    this.mServerCredentials.Certificate);
+
+                this.mKeyExchange.ProcessClientCertificate(clientCertificate);
+            }
+
+            /*
+             * RFC 5246 7.4.6. If the client does not Send any certificates, the server MAY at its
+             * discretion either continue the handshake without client authentication, or respond with a
+             * fatal handshake_failure alert. Also, if some aspect of the certificate chain was
+             * unacceptable (e.g., it was not signed by a known, trusted CA), the server MAY at its
+             * discretion either continue the handshake (considering the client unauthenticated) or Send
+             * a fatal alert.
+             */
+            this.mTlsServer.NotifyClientCertificate(clientCertificate);
+        }
+
+        protected virtual void ReceiveCertificateMessage(MemoryStream buf)
+        {
+            Certificate clientCertificate = Certificate.Parse(buf);
+
+            AssertEmpty(buf);
+
+            NotifyClientCertificate(clientCertificate);
+        }
+
+        protected virtual void ReceiveCertificateVerifyMessage(MemoryStream buf)
+        {
+            DigitallySigned clientCertificateVerify = DigitallySigned.Parse(Context, buf);
+
+            AssertEmpty(buf);
+
+            // Verify the CertificateVerify message contains a correct signature.
+            try
+            {
+                byte[] certificateVerifyHash;
+                if (TlsUtilities.IsTlsV12(Context))
+                {
+                    certificateVerifyHash = mPrepareFinishHash.GetFinalHash(clientCertificateVerify.Algorithm.Hash);
+                }
+                else
+                {
+                    certificateVerifyHash = TlsProtocol.GetCurrentPrfHash(Context, mPrepareFinishHash, null);
+                }
+
+                X509CertificateStructure x509Cert = mPeerCertificate.GetCertificateAt(0);
+                SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+                AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(keyInfo);
+
+                TlsSigner tlsSigner = TlsUtilities.CreateTlsSigner((byte)mClientCertificateType);
+                tlsSigner.Init(Context);
+                if (!tlsSigner.VerifyRawSignature(clientCertificateVerify.Algorithm,
+                    clientCertificateVerify.Signature, publicKey, certificateVerifyHash))
+                {
+                    throw new TlsFatalAlert(AlertDescription.decrypt_error);
+                }
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.decrypt_error, e);
+            }
+        }
+
+        protected virtual void ReceiveClientHelloMessage(MemoryStream buf)
+        {
+            ProtocolVersion client_version = TlsUtilities.ReadVersion(buf);
+            if (client_version.IsDtls)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            byte[] client_random = TlsUtilities.ReadFully(32, buf);
+
+            /*
+             * TODO RFC 5077 3.4. If a ticket is presented by the client, the server MUST NOT attempt to
+             * use the Session ID in the ClientHello for stateful session resumption.
+             */
+            byte[] sessionID = TlsUtilities.ReadOpaque8(buf);
+            if (sessionID.Length > 32)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            /*
+             * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
+             * resumption request), this vector MUST include at least the cipher_suite from that
+             * session.
+             */
+            int cipher_suites_length = TlsUtilities.ReadUint16(buf);
+            if (cipher_suites_length < 2 || (cipher_suites_length & 1) != 0)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            this.mOfferedCipherSuites = TlsUtilities.ReadUint16Array(cipher_suites_length / 2, buf);
+
+            /*
+             * TODO RFC 5246 7.4.1.2. If the session_id field is not empty (implying a session
+             * resumption request), it MUST include the compression_method from that session.
+             */
+            int compression_methods_length = TlsUtilities.ReadUint8(buf);
+            if (compression_methods_length < 1)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+
+            this.mOfferedCompressionMethods = TlsUtilities.ReadUint8Array(compression_methods_length, buf);
+
+            /*
+             * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore
+             * extensions appearing in the client hello, and Send a server hello containing no
+             * extensions.
+             */
+            this.mClientExtensions = ReadExtensions(buf);
+
+            ContextAdmin.SetClientVersion(client_version);
+
+            mTlsServer.NotifyClientVersion(client_version);
+
+            mSecurityParameters.clientRandom = client_random;
+
+            mTlsServer.NotifyOfferedCipherSuites(mOfferedCipherSuites);
+            mTlsServer.NotifyOfferedCompressionMethods(mOfferedCompressionMethods);
+
+            /*
+             * RFC 5746 3.6. Server Behavior: Initial Handshake
+             */
+            {
+                /*
+                 * RFC 5746 3.4. The client MUST include either an empty "renegotiation_info" extension,
+                 * or the TLS_EMPTY_RENEGOTIATION_INFO_SCSV signaling cipher suite value in the
+                 * ClientHello. Including both is NOT RECOMMENDED.
+                 */
+
+                /*
+                 * When a ClientHello is received, the server MUST check if it includes the
+                 * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV. If it does, set the secure_renegotiation flag
+                 * to TRUE.
+                 */
+                if (Arrays.Contains(mOfferedCipherSuites, CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV))
+                {
+                    this.mSecureRenegotiation = true;
+                }
+
+                /*
+                 * The server MUST check if the "renegotiation_info" extension is included in the
+                 * ClientHello.
+                 */
+                byte[] renegExtData = TlsUtilities.GetExtensionData(mClientExtensions, ExtensionType.renegotiation_info);
+                if (renegExtData != null)
+                {
+                    /*
+                     * If the extension is present, set secure_renegotiation flag to TRUE. The
+                     * server MUST then verify that the length of the "renegotiated_connection"
+                     * field is zero, and if it is not, MUST abort the handshake.
+                     */
+                    this.mSecureRenegotiation = true;
+
+                    if (!Arrays.ConstantTimeAreEqual(renegExtData, CreateRenegotiationInfo(TlsUtilities.EmptyBytes)))
+                        throw new TlsFatalAlert(AlertDescription.handshake_failure);
+                }
+            }
+
+            mTlsServer.NotifySecureRenegotiation(this.mSecureRenegotiation);
+
+            if (mClientExtensions != null)
+            {
+                mTlsServer.ProcessClientExtensions(mClientExtensions);
+            }
+        }
+
+        protected virtual void ReceiveClientKeyExchangeMessage(MemoryStream buf)
+        {
+            mKeyExchange.ProcessClientKeyExchange(buf);
+
+            AssertEmpty(buf);
+
+            EstablishMasterSecret(Context, mKeyExchange);
+            mRecordStream.SetPendingConnectionState(Peer.GetCompression(), Peer.GetCipher());
+
+            this.mPrepareFinishHash = mRecordStream.PrepareToFinish();
+
+            if (!mExpectSessionTicket)
+            {
+                SendChangeCipherSpecMessage();
+            }
+        }
+
+        protected virtual void SendCertificateRequestMessage(CertificateRequest certificateRequest)
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_request);
+
+            certificateRequest.Encode(message);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendCertificateStatusMessage(CertificateStatus certificateStatus)
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.certificate_status);
+
+            certificateStatus.Encode(message);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendNewSessionTicketMessage(NewSessionTicket newSessionTicket)
+        {
+            if (newSessionTicket == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.session_ticket);
+
+            newSessionTicket.Encode(message);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual void SendServerHelloMessage()
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_hello);
+
+            ProtocolVersion server_version = mTlsServer.GetServerVersion();
+            if (!server_version.IsEqualOrEarlierVersionOf(Context.ClientVersion))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            mRecordStream.ReadVersion = server_version;
+            mRecordStream.SetWriteVersion(server_version);
+            mRecordStream.SetRestrictReadVersion(true);
+            ContextAdmin.SetServerVersion(server_version);
+
+            TlsUtilities.WriteVersion(server_version, message);
+
+            message.Write(this.mSecurityParameters.serverRandom);
+
+            /*
+             * The server may return an empty session_id to indicate that the session will not be cached
+             * and therefore cannot be resumed.
+             */
+            TlsUtilities.WriteOpaque8(TlsUtilities.EmptyBytes, message);
+
+            int selectedCipherSuite = mTlsServer.GetSelectedCipherSuite();
+            if (!Arrays.Contains(mOfferedCipherSuites, selectedCipherSuite)
+                || selectedCipherSuite == CipherSuite.TLS_NULL_WITH_NULL_NULL
+                || selectedCipherSuite == CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV
+                || !TlsUtilities.IsValidCipherSuiteForVersion(selectedCipherSuite, server_version))
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+            mSecurityParameters.cipherSuite = selectedCipherSuite;
+
+            byte selectedCompressionMethod = mTlsServer.GetSelectedCompressionMethod();
+            if (!Arrays.Contains(mOfferedCompressionMethods, selectedCompressionMethod))
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+            mSecurityParameters.compressionAlgorithm = selectedCompressionMethod;
+
+            TlsUtilities.WriteUint16(selectedCipherSuite, message);
+            TlsUtilities.WriteUint8(selectedCompressionMethod, message);
+
+            this.mServerExtensions = mTlsServer.GetServerExtensions();
+
+            /*
+             * RFC 5746 3.6. Server Behavior: Initial Handshake
+             */
+            if (this.mSecureRenegotiation)
+            {
+                byte[] renegExtData = TlsUtilities.GetExtensionData(this.mServerExtensions, ExtensionType.renegotiation_info);
+                bool noRenegExt = (null == renegExtData);
+
+                if (noRenegExt)
+                {
+                    /*
+                     * Note that Sending a "renegotiation_info" extension in response to a ClientHello
+                     * containing only the SCSV is an explicit exception to the prohibition in RFC 5246,
+                     * Section 7.4.1.4, on the server Sending unsolicited extensions and is only allowed
+                     * because the client is signaling its willingness to receive the extension via the
+                     * TLS_EMPTY_RENEGOTIATION_INFO_SCSV SCSV.
+                     */
+
+                    /*
+                     * If the secure_renegotiation flag is set to TRUE, the server MUST include an empty
+                     * "renegotiation_info" extension in the ServerHello message.
+                     */
+                    this.mServerExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(mServerExtensions);
+                    this.mServerExtensions[ExtensionType.renegotiation_info] = CreateRenegotiationInfo(TlsUtilities.EmptyBytes);
+                }
+            }
+
+            /*
+             * TODO RFC 3546 2.3 If [...] the older session is resumed, then the server MUST ignore
+             * extensions appearing in the client hello, and Send a server hello containing no
+             * extensions.
+             */
+
+            if (this.mServerExtensions != null)
+            {
+                this.mSecurityParameters.encryptThenMac = TlsExtensionsUtilities.HasEncryptThenMacExtension(mServerExtensions);
+
+                this.mSecurityParameters.maxFragmentLength = ProcessMaxFragmentLengthExtension(mClientExtensions,
+                    mServerExtensions, AlertDescription.internal_error);
+
+                this.mSecurityParameters.truncatedHMac = TlsExtensionsUtilities.HasTruncatedHMacExtension(mServerExtensions);
+
+                /*
+                 * TODO It's surprising that there's no provision to allow a 'fresh' CertificateStatus to be sent in
+                 * a session resumption handshake.
+                 */
+                this.mAllowCertificateStatus = !mResumedSession
+                    && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.status_request,
+                        AlertDescription.internal_error);
+
+                this.mExpectSessionTicket = !mResumedSession
+                    && TlsUtilities.HasExpectedEmptyExtensionData(mServerExtensions, ExtensionType.session_ticket,
+                        AlertDescription.internal_error);
+
+                WriteExtensions(message, this.mServerExtensions);
+            }
+
+            if (mSecurityParameters.maxFragmentLength >= 0)
+            {
+                int plainTextLimit = 1 << (8 + mSecurityParameters.maxFragmentLength);
+                mRecordStream.SetPlaintextLimit(plainTextLimit);
+            }
+
+            mSecurityParameters.prfAlgorithm = GetPrfAlgorithm(Context, mSecurityParameters.CipherSuite);
+
+            /*
+             * RFC 5264 7.4.9. Any cipher suite which does not explicitly specify verify_data_length has
+             * a verify_data_length equal to 12. This includes all existing cipher suites.
+             */
+            mSecurityParameters.verifyDataLength = 12;
+
+            message.WriteToRecordStream(this);
+
+            this.mRecordStream.NotifyHelloComplete();
+        }
+
+        protected virtual void SendServerHelloDoneMessage()
+        {
+            byte[] message = new byte[4];
+            TlsUtilities.WriteUint8(HandshakeType.server_hello_done, message, 0);
+            TlsUtilities.WriteUint24(0, message, 1);
+
+            WriteHandshakeMessage(message, 0, message.Length);
+        }
+
+        protected virtual void SendServerKeyExchangeMessage(byte[] serverKeyExchange)
+        {
+            HandshakeMessage message = new HandshakeMessage(HandshakeType.server_key_exchange, serverKeyExchange.Length);
+
+            message.Write(serverKeyExchange);
+
+            message.WriteToRecordStream(this);
+        }
+
+        protected virtual bool ExpectCertificateVerifyMessage()
+        {
+            return mClientCertificateType >= 0 && TlsUtilities.HasSigningCapability((byte)mClientCertificateType);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSession.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSession.cs
new file mode 100644
index 0000000..6c22991
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSession.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsSession
+    {
+        SessionParameters ExportSessionParameters();
+
+        byte[] SessionID { get; }
+
+        void Invalidate();
+
+        bool IsResumable { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSessionImpl.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSessionImpl.cs
new file mode 100644
index 0000000..8663926
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSessionImpl.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class TlsSessionImpl
+        :   TlsSession
+    {
+        internal readonly byte[] mSessionID;
+        internal SessionParameters mSessionParameters;
+
+        internal TlsSessionImpl(byte[] sessionID, SessionParameters sessionParameters)
+        {
+            if (sessionID == null)
+                throw new ArgumentNullException("sessionID");
+            if (sessionID.Length < 1 || sessionID.Length > 32)
+                throw new ArgumentException("must have length between 1 and 32 bytes, inclusive", "sessionID");
+
+            this.mSessionID = Arrays.Clone(sessionID);
+            this.mSessionParameters = sessionParameters;
+        }
+
+        public virtual SessionParameters ExportSessionParameters()
+        {
+            lock (this)
+            {
+                return this.mSessionParameters == null ? null : this.mSessionParameters.Copy();
+            }
+        }
+
+        public virtual byte[] SessionID
+        {
+            get { lock (this) return mSessionID; }
+        }
+
+        public virtual void Invalidate()
+        {
+            lock (this)
+            {
+                if (this.mSessionParameters != null)
+                {
+                    this.mSessionParameters.Clear();
+                    this.mSessionParameters = null;
+                }
+            }
+        }
+
+        public virtual bool IsResumable
+        {
+            get { lock (this) return this.mSessionParameters != null; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSigner.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSigner.cs
new file mode 100644
index 0000000..ffdd4c9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSigner.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsSigner
+    {
+        void Init(TlsContext context);
+
+        byte[] GenerateRawSignature(AsymmetricKeyParameter privateKey, byte[] md5AndSha1);
+
+        byte[] GenerateRawSignature(SignatureAndHashAlgorithm algorithm,
+            AsymmetricKeyParameter privateKey, byte[] hash);
+
+        bool VerifyRawSignature(byte[] sigBytes, AsymmetricKeyParameter publicKey, byte[] md5AndSha1);
+
+        bool VerifyRawSignature(SignatureAndHashAlgorithm algorithm, byte[] sigBytes,
+            AsymmetricKeyParameter publicKey, byte[] hash);
+
+        ISigner CreateSigner(AsymmetricKeyParameter privateKey);
+
+        ISigner CreateSigner(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter privateKey);
+
+        ISigner CreateVerifyer(AsymmetricKeyParameter publicKey);
+
+        ISigner CreateVerifyer(SignatureAndHashAlgorithm algorithm, AsymmetricKeyParameter publicKey);
+
+        bool IsValidPublicKey(AsymmetricKeyParameter publicKey);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSignerCredentials.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSignerCredentials.cs
new file mode 100644
index 0000000..92ed7cc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSignerCredentials.cs
@@ -0,0 +1,14 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public interface TlsSignerCredentials
+        :   TlsCredentials
+    {
+        /// <exception cref="IOException"></exception>
+        byte[] GenerateCertificateSignature(byte[] hash);
+
+        SignatureAndHashAlgorithm SignatureAndHashAlgorithm { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpKeyExchange.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpKeyExchange.cs
new file mode 100644
index 0000000..f42f745
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpKeyExchange.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Agreement.Srp;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <summary>(D)TLS SRP key exchange (RFC 5054).</summary>
+    public class TlsSrpKeyExchange
+        :   AbstractTlsKeyExchange
+    {
+        protected TlsSigner mTlsSigner;
+        protected byte[] mIdentity;
+        protected byte[] mPassword;
+
+        protected AsymmetricKeyParameter mServerPublicKey = null;
+
+        protected byte[] mS = null;
+        protected BigInteger mB = null;
+        protected Srp6Client mSrpClient = new Srp6Client();
+
+        public TlsSrpKeyExchange(int keyExchange, IList supportedSignatureAlgorithms, byte[] identity, byte[] password)
+            :   base(keyExchange, supportedSignatureAlgorithms)
+        {
+            switch (keyExchange)
+            {
+            case KeyExchangeAlgorithm.SRP:
+                this.mTlsSigner = null;
+                break;
+            case KeyExchangeAlgorithm.SRP_RSA:
+                this.mTlsSigner = new TlsRsaSigner();
+                break;
+            case KeyExchangeAlgorithm.SRP_DSS:
+                this.mTlsSigner = new TlsDssSigner();
+                break;
+            default:
+                throw new InvalidOperationException("unsupported key exchange algorithm");
+            }
+
+            this.mIdentity = identity;
+            this.mPassword = password;
+        }
+
+        public override void Init(TlsContext context)
+        {
+            base.Init(context);
+
+            if (this.mTlsSigner != null)
+            {
+                this.mTlsSigner.Init(context);
+            }
+        }
+
+        public override void SkipServerCredentials()
+        {
+            if (mTlsSigner != null)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessServerCertificate(Certificate serverCertificate)
+        {
+            if (mTlsSigner == null)
+                throw new TlsFatalAlert(AlertDescription.unexpected_message);
+            if (serverCertificate.IsEmpty)
+                throw new TlsFatalAlert(AlertDescription.bad_certificate);
+
+            X509CertificateStructure x509Cert = serverCertificate.GetCertificateAt(0);
+
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                this.mServerPublicKey = PublicKeyFactory.CreateKey(keyInfo);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+
+            if (!mTlsSigner.IsValidPublicKey(this.mServerPublicKey))
+                throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+
+            TlsUtilities.ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+
+            base.ProcessServerCertificate(serverCertificate);
+        }
+
+        public override bool RequiresServerKeyExchange
+        {
+            get { return true; }
+        }
+
+        public override void ProcessServerKeyExchange(Stream input)
+        {
+            SecurityParameters securityParameters = context.SecurityParameters;
+
+            SignerInputBuffer buf = null;
+            Stream teeIn = input;
+
+            if (mTlsSigner != null)
+            {
+                buf = new SignerInputBuffer();
+                teeIn = new TeeInputStream(input, buf);
+            }
+
+            byte[] NBytes = TlsUtilities.ReadOpaque16(teeIn);
+            byte[] gBytes = TlsUtilities.ReadOpaque16(teeIn);
+            byte[] sBytes = TlsUtilities.ReadOpaque8(teeIn);
+            byte[] BBytes = TlsUtilities.ReadOpaque16(teeIn);
+
+            if (buf != null)
+            {
+                DigitallySigned signed_params = DigitallySigned.Parse(context, input);
+
+                ISigner signer = InitVerifyer(mTlsSigner, signed_params.Algorithm, securityParameters);
+                buf.UpdateSigner(signer);
+                if (!signer.VerifySignature(signed_params.Signature))
+                    throw new TlsFatalAlert(AlertDescription.decrypt_error);
+            }
+
+            BigInteger N = new BigInteger(1, NBytes);
+            BigInteger g = new BigInteger(1, gBytes);
+
+            // TODO Validate group parameters (see RFC 5054)
+    //        throw new TlsFatalAlert(AlertDescription.insufficient_security);
+
+            this.mS = sBytes;
+
+            /*
+             * RFC 5054 2.5.3: The client MUST abort the handshake with an "illegal_parameter" alert if
+             * B % N = 0.
+             */
+            try
+            {
+                this.mB = Srp6Utilities.ValidatePublicValue(N, new BigInteger(1, BBytes));
+            }
+            catch (CryptoException e)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter, e);
+            }
+
+            this.mSrpClient.Init(N, g, TlsUtilities.CreateHash(HashAlgorithm.sha1), context.SecureRandom);
+        }
+
+        public override void ValidateCertificateRequest(CertificateRequest certificateRequest)
+        {
+            throw new TlsFatalAlert(AlertDescription.unexpected_message);
+        }
+
+        public override void ProcessClientCredentials(TlsCredentials clientCredentials)
+        {
+            throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public override void GenerateClientKeyExchange(Stream output)
+        {
+            BigInteger A = mSrpClient.GenerateClientCredentials(mS, this.mIdentity, this.mPassword);
+            TlsUtilities.WriteOpaque16(BigIntegers.AsUnsignedByteArray(A), output);
+        }
+
+        public override byte[] GeneratePremasterSecret()
+        {
+            try
+            {
+                // TODO Check if this needs to be a fixed size
+                return BigIntegers.AsUnsignedByteArray(mSrpClient.CalculateSecret(mB));
+            }
+            catch (CryptoException e)
+            {
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter, e);
+            }
+        }
+
+        protected virtual ISigner InitVerifyer(TlsSigner tlsSigner, SignatureAndHashAlgorithm algorithm,
+            SecurityParameters securityParameters)
+        {
+            ISigner signer = tlsSigner.CreateVerifyer(algorithm, this.mServerPublicKey);
+            signer.BlockUpdate(securityParameters.clientRandom, 0, securityParameters.clientRandom.Length);
+            signer.BlockUpdate(securityParameters.serverRandom, 0, securityParameters.serverRandom.Length);
+            return signer;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpUtilities.cs
new file mode 100644
index 0000000..bbb6ac2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrpUtilities.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public abstract class TlsSrpUtilities
+    {
+        public static void AddSrpExtension(IDictionary extensions, byte[] identity)
+        {
+            extensions[ExtensionType.srp] = CreateSrpExtension(identity);
+        }
+
+        public static byte[] GetSrpExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.srp);
+            return extensionData == null ? null : ReadSrpExtension(extensionData);
+        }
+
+        public static byte[] CreateSrpExtension(byte[] identity)
+        {
+            if (identity == null)
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+
+            return TlsUtilities.EncodeOpaque8(identity);
+        }
+
+        public static byte[] ReadSrpExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+            byte[] identity = TlsUtilities.ReadOpaque8(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return identity;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrtpUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrtpUtilities.cs
new file mode 100644
index 0000000..626c0e3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsSrtpUtilities.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 5764 DTLS Extension to Establish Keys for SRTP.
+     */
+    public abstract class TlsSRTPUtils
+    {
+        public static void AddUseSrtpExtension(IDictionary extensions, UseSrtpData useSRTPData)
+        {
+            extensions[ExtensionType.use_srtp] = CreateUseSrtpExtension(useSRTPData);
+        }
+
+        public static UseSrtpData GetUseSrtpExtension(IDictionary extensions)
+        {
+            byte[] extensionData = TlsUtilities.GetExtensionData(extensions, ExtensionType.use_srtp);
+            return extensionData == null ? null : ReadUseSrtpExtension(extensionData);
+        }
+
+        public static byte[] CreateUseSrtpExtension(UseSrtpData useSrtpData)
+        {
+            if (useSrtpData == null)
+                throw new ArgumentNullException("useSrtpData");
+
+            MemoryStream buf = new MemoryStream();
+
+            // SRTPProtectionProfiles
+            TlsUtilities.WriteUint16ArrayWithUint16Length(useSrtpData.ProtectionProfiles, buf);
+
+            // srtp_mki
+            TlsUtilities.WriteOpaque8(useSrtpData.Mki, buf);
+
+            return buf.ToArray();
+        }
+
+        public static UseSrtpData ReadUseSrtpExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, true);
+
+            // SRTPProtectionProfiles
+            int length = TlsUtilities.ReadUint16(buf);
+            if (length < 2 || (length & 1) != 0)
+            {
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            }
+            int[] protectionProfiles = TlsUtilities.ReadUint16Array(length / 2, buf);
+
+            // srtp_mki
+            byte[] mki = TlsUtilities.ReadOpaque8(buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return new UseSrtpData(protectionProfiles, mki);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsStream.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsStream.cs
new file mode 100644
index 0000000..f78ba03
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsStream.cs
@@ -0,0 +1,89 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    internal class TlsStream
+        : Stream
+    {
+        private readonly TlsProtocol handler;
+
+        internal TlsStream(TlsProtocol handler)
+        {
+            this.handler = handler;
+        }
+
+        public override bool CanRead
+        {
+            get { return !handler.IsClosed; }
+        }
+
+        public override bool CanSeek
+        {
+            get { return false; }
+        }
+
+        public override bool CanWrite
+        {
+            get { return !handler.IsClosed; }
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                handler.Close();
+            }
+            base.Dispose(disposing);
+        }
+
+        public override void Flush()
+        {
+            handler.Flush();
+        }
+
+        public override long Length
+        {
+            get { throw new NotSupportedException(); }
+        }
+
+        public override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+
+        public override int Read(byte[]	buf, int off, int len)
+        {
+            return this.handler.ReadApplicationData(buf, off, len);
+        }
+
+        public override int ReadByte()
+        {
+            byte[] buf = new byte[1];
+            if (this.Read(buf, 0, 1) <= 0)
+                return -1;
+            return buf[0];
+        }
+
+        public override long Seek(long offset, SeekOrigin origin)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void SetLength(long value)
+        {
+            throw new NotSupportedException();
+        }
+
+        public override void Write(byte[] buf, int off, int len)
+        {
+            this.handler.WriteData(buf, off, len);
+        }
+
+        public override void WriteByte(byte b)
+        {
+            this.handler.WriteData(new byte[] { b }, 0, 1);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsStreamCipher.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsStreamCipher.cs
new file mode 100644
index 0000000..45f2a9a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsStreamCipher.cs
@@ -0,0 +1,164 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Tls;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    public class TlsStreamCipher
+        :   TlsCipher
+    {
+        protected readonly TlsContext context;
+
+        protected readonly IStreamCipher encryptCipher;
+        protected readonly IStreamCipher decryptCipher;
+
+        protected readonly TlsMac writeMac;
+        protected readonly TlsMac readMac;
+
+        protected readonly bool usesNonce;
+
+        /// <exception cref="IOException"></exception>
+        public TlsStreamCipher(TlsContext context, IStreamCipher clientWriteCipher,
+            IStreamCipher serverWriteCipher, IDigest clientWriteDigest, IDigest serverWriteDigest,
+            int cipherKeySize, bool usesNonce)
+        {
+            bool isServer = context.IsServer;
+
+            this.context = context;
+            this.usesNonce = usesNonce;
+
+            this.encryptCipher = clientWriteCipher;
+            this.decryptCipher = serverWriteCipher;
+
+            int key_block_size = (2 * cipherKeySize) + clientWriteDigest.GetDigestSize()
+                + serverWriteDigest.GetDigestSize();
+
+            byte[] key_block = TlsUtilities.CalculateKeyBlock(context, key_block_size);
+
+            int offset = 0;
+
+            // Init MACs
+            TlsMac clientWriteMac = new TlsMac(context, clientWriteDigest, key_block, offset,
+                clientWriteDigest.GetDigestSize());
+            offset += clientWriteDigest.GetDigestSize();
+            TlsMac serverWriteMac = new TlsMac(context, serverWriteDigest, key_block, offset,
+                serverWriteDigest.GetDigestSize());
+            offset += serverWriteDigest.GetDigestSize();
+
+            // Build keys
+            KeyParameter clientWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+            KeyParameter serverWriteKey = new KeyParameter(key_block, offset, cipherKeySize);
+            offset += cipherKeySize;
+
+            if (offset != key_block_size)
+            {
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+
+            ICipherParameters encryptParams, decryptParams;
+            if (isServer)
+            {
+                this.writeMac = serverWriteMac;
+                this.readMac = clientWriteMac;
+                this.encryptCipher = serverWriteCipher;
+                this.decryptCipher = clientWriteCipher;
+                encryptParams = serverWriteKey;
+                decryptParams = clientWriteKey;
+            }
+            else
+            {
+                this.writeMac = clientWriteMac;
+                this.readMac = serverWriteMac;
+                this.encryptCipher = clientWriteCipher;
+                this.decryptCipher = serverWriteCipher;
+                encryptParams = clientWriteKey;
+                decryptParams = serverWriteKey;
+            }
+
+            if (usesNonce)
+            {
+                byte[] dummyNonce = new byte[8];
+                encryptParams = new ParametersWithIV(encryptParams, dummyNonce);
+                decryptParams = new ParametersWithIV(decryptParams, dummyNonce);
+            }
+
+            this.encryptCipher.Init(true, encryptParams);
+            this.decryptCipher.Init(false, decryptParams);
+        }
+
+        public virtual int GetPlaintextLimit(int ciphertextLimit)
+        {
+            return ciphertextLimit - writeMac.Size;
+        }
+
+        public virtual byte[] EncodePlaintext(long seqNo, byte type, byte[] plaintext, int offset, int len)
+        {
+            /*
+             * draft-josefsson-salsa20-tls-04 2.1 Note that Salsa20 requires a 64-bit nonce. That
+             * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS
+             * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation
+             * of the 16-bit epoch with the 48-bit sequence number.
+             */
+            if (usesNonce)
+            {
+                UpdateIV(encryptCipher, true, seqNo);
+            }
+
+            byte[] outBuf = new byte[len + writeMac.Size];
+
+            encryptCipher.ProcessBytes(plaintext, offset, len, outBuf, 0);
+
+            byte[] mac = writeMac.CalculateMac(seqNo, type, plaintext, offset, len);
+            encryptCipher.ProcessBytes(mac, 0, mac.Length, outBuf, len);
+
+            return outBuf;
+        }
+
+        /// <exception cref="IOException"></exception>
+        public virtual byte[] DecodeCiphertext(long seqNo, byte type, byte[] ciphertext, int offset, int len)
+        {
+            /*
+             * draft-josefsson-salsa20-tls-04 2.1 Note that Salsa20 requires a 64-bit nonce. That
+             * nonce is updated on the encryption of every TLS record, and is set to be the 64-bit TLS
+             * record sequence number. In case of DTLS the 64-bit nonce is formed as the concatenation
+             * of the 16-bit epoch with the 48-bit sequence number.
+             */
+            if (usesNonce)
+            {
+                UpdateIV(decryptCipher, false, seqNo);
+            }
+
+            int macSize = readMac.Size;
+            if (len < macSize)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+
+            int plaintextLength = len - macSize;
+
+            byte[] deciphered = new byte[len];
+            decryptCipher.ProcessBytes(ciphertext, offset, len, deciphered, 0);
+            CheckMac(seqNo, type, deciphered, plaintextLength, len, deciphered, 0, plaintextLength);
+            return Arrays.CopyOfRange(deciphered, 0, plaintextLength);
+        }
+
+        /// <exception cref="IOException"></exception>
+        protected virtual void CheckMac(long seqNo, byte type, byte[] recBuf, int recStart, int recEnd, byte[] calcBuf, int calcOff, int calcLen)
+        {
+            byte[] receivedMac = Arrays.CopyOfRange(recBuf, recStart, recEnd);
+            byte[] computedMac = readMac.CalculateMac(seqNo, type, calcBuf, calcOff, calcLen);
+
+            if (!Arrays.ConstantTimeAreEqual(receivedMac, computedMac))
+                throw new TlsFatalAlert(AlertDescription.bad_record_mac);
+        }
+
+        protected virtual void UpdateIV(IStreamCipher cipher, bool forEncryption, long seqNo)
+        {
+            byte[] nonce = new byte[8];
+            TlsUtilities.WriteUint64(seqNo, nonce, 0);
+            cipher.Init(forEncryption, new ParametersWithIV(null, nonce));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/TlsUtilities.cs b/BouncyCastle.AxCrypt/src/crypto/tls/TlsUtilities.cs
new file mode 100644
index 0000000..f1ea099
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/TlsUtilities.cs
@@ -0,0 +1,1631 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <remarks>Some helper functions for MicroTLS.</remarks>
+    public abstract class TlsUtilities
+    {
+        public static readonly byte[] EmptyBytes = new byte[0];
+
+        public static void CheckUint8(int i)
+        {
+            if (!IsValidUint8(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint8(long i)
+        {
+            if (!IsValidUint8(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint16(int i)
+        {
+            if (!IsValidUint16(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint16(long i)
+        {
+            if (!IsValidUint16(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint24(int i)
+        {
+            if (!IsValidUint24(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint24(long i)
+        {
+            if (!IsValidUint24(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint32(long i)
+        {
+            if (!IsValidUint32(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint48(long i)
+        {
+            if (!IsValidUint48(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static void CheckUint64(long i)
+        {
+            if (!IsValidUint64(i))
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+        }
+
+        public static bool IsValidUint8(int i)
+        {
+            return (i & 0xFF) == i;
+        }
+
+        public static bool IsValidUint8(long i)
+        {
+            return (i & 0xFFL) == i;
+        }
+
+        public static bool IsValidUint16(int i)
+        {
+            return (i & 0xFFFF) == i;
+        }
+
+        public static bool IsValidUint16(long i)
+        {
+            return (i & 0xFFFFL) == i;
+        }
+
+        public static bool IsValidUint24(int i)
+        {
+            return (i & 0xFFFFFF) == i;
+        }
+
+        public static bool IsValidUint24(long i)
+        {
+            return (i & 0xFFFFFFL) == i;
+        }
+
+        public static bool IsValidUint32(long i)
+        {
+            return (i & 0xFFFFFFFFL) == i;
+        }
+
+        public static bool IsValidUint48(long i)
+        {
+            return (i & 0xFFFFFFFFFFFFL) == i;
+        }
+
+        public static bool IsValidUint64(long i)
+        {
+            return true;
+        }
+
+        public static bool IsSsl(TlsContext context)
+        {
+            return context.ServerVersion.IsSsl;
+        }
+
+        public static bool IsTlsV11(TlsContext context)
+        {
+            return ProtocolVersion.TLSv11.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+        }
+
+        public static bool IsTlsV12(TlsContext context)
+        {
+            return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(context.ServerVersion.GetEquivalentTLSVersion());
+        }
+
+        public static void WriteUint8(byte i, Stream output)
+        {
+            output.WriteByte(i);
+        }
+
+        public static void WriteUint8(byte i, byte[] buf, int offset)
+        {
+            buf[offset] = i;
+        }
+
+        public static void WriteUint16(int i, Stream output)
+        {
+            output.WriteByte((byte)(i >> 8));
+            output.WriteByte((byte)i);
+        }
+
+        public static void WriteUint16(int i, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)(i >> 8);
+            buf[offset + 1] = (byte)i;
+        }
+
+        public static void WriteUint24(int i, Stream output)
+        {
+            output.WriteByte((byte)(i >> 16));
+            output.WriteByte((byte)(i >> 8));
+            output.WriteByte((byte)i);
+        }
+
+        public static void WriteUint24(int i, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)(i >> 16);
+            buf[offset + 1] = (byte)(i >> 8);
+            buf[offset + 2] = (byte)i;
+        }
+
+        public static void WriteUint32(long i, Stream output)
+        {
+            output.WriteByte((byte)(i >> 24));
+            output.WriteByte((byte)(i >> 16));
+            output.WriteByte((byte)(i >> 8));
+            output.WriteByte((byte)i);
+        }
+
+        public static void WriteUint32(long i, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)(i >> 24);
+            buf[offset + 1] = (byte)(i >> 16);
+            buf[offset + 2] = (byte)(i >> 8);
+            buf[offset + 3] = (byte)i;
+        }
+
+        public static void WriteUint48(long i, Stream output)
+        {
+            output.WriteByte((byte)(i >> 40));
+            output.WriteByte((byte)(i >> 32));
+            output.WriteByte((byte)(i >> 24));
+            output.WriteByte((byte)(i >> 16));
+            output.WriteByte((byte)(i >> 8));
+            output.WriteByte((byte)i);
+        }
+
+        public static void WriteUint48(long i, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)(i >> 40);
+            buf[offset + 1] = (byte)(i >> 32);
+            buf[offset + 2] = (byte)(i >> 24);
+            buf[offset + 3] = (byte)(i >> 16);
+            buf[offset + 4] = (byte)(i >> 8);
+            buf[offset + 5] = (byte)i;
+        }
+
+        public static void WriteUint64(long i, Stream output)
+        {
+            output.WriteByte((byte)(i >> 56));
+            output.WriteByte((byte)(i >> 48));
+            output.WriteByte((byte)(i >> 40));
+            output.WriteByte((byte)(i >> 32));
+            output.WriteByte((byte)(i >> 24));
+            output.WriteByte((byte)(i >> 16));
+            output.WriteByte((byte)(i >> 8));
+            output.WriteByte((byte)i);
+        }
+
+        public static void WriteUint64(long i, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)(i >> 56);
+            buf[offset + 1] = (byte)(i >> 48);
+            buf[offset + 2] = (byte)(i >> 40);
+            buf[offset + 3] = (byte)(i >> 32);
+            buf[offset + 4] = (byte)(i >> 24);
+            buf[offset + 5] = (byte)(i >> 16);
+            buf[offset + 6] = (byte)(i >> 8);
+            buf[offset + 7] = (byte)i;
+        }
+
+        public static void WriteOpaque8(byte[] buf, Stream output)
+        {
+            WriteUint8((byte)buf.Length, output);
+            output.Write(buf, 0, buf.Length);
+        }
+
+        public static void WriteOpaque16(byte[] buf, Stream output)
+        {
+            WriteUint16(buf.Length, output);
+            output.Write(buf, 0, buf.Length);
+        }
+
+        public static void WriteOpaque24(byte[] buf, Stream output)
+        {
+            WriteUint24(buf.Length, output);
+            output.Write(buf, 0, buf.Length);
+        }
+
+        public static void WriteUint8Array(byte[] uints, Stream output)
+        {
+            output.Write(uints, 0, uints.Length);
+        }
+
+        public static void WriteUint8Array(byte[] uints, byte[] buf, int offset)
+        {
+            for (int i = 0; i < uints.Length; ++i)
+            {
+                WriteUint8(uints[i], buf, offset);
+                ++offset;
+            }
+        }
+
+        public static void WriteUint8ArrayWithUint8Length(byte[] uints, Stream output)
+        {
+            CheckUint8(uints.Length);
+            WriteUint8((byte)uints.Length, output);
+            WriteUint8Array(uints, output);
+        }
+
+        public static void WriteUint8ArrayWithUint8Length(byte[] uints, byte[] buf, int offset)
+        {
+            CheckUint8(uints.Length);
+            WriteUint8((byte)uints.Length, buf, offset);
+            WriteUint8Array(uints, buf, offset + 1);
+        }
+
+        public static void WriteUint16Array(int[] uints, Stream output)
+        {
+            for (int i = 0; i < uints.Length; ++i)
+            {
+                WriteUint16(uints[i], output);
+            }
+        }
+
+        public static void WriteUint16Array(int[] uints, byte[] buf, int offset)
+        {
+            for (int i = 0; i < uints.Length; ++i)
+            {
+                WriteUint16(uints[i], buf, offset);
+                offset += 2;
+            }
+        }
+
+        public static void WriteUint16ArrayWithUint16Length(int[] uints, Stream output)
+        {
+            int length = 2 * uints.Length;
+            CheckUint16(length);
+            WriteUint16(length, output);
+            WriteUint16Array(uints, output);
+        }
+
+        public static void WriteUint16ArrayWithUint16Length(int[] uints, byte[] buf, int offset)
+        {
+            int length = 2 * uints.Length;
+            CheckUint16(length);
+            WriteUint16(length, buf, offset);
+            WriteUint16Array(uints, buf, offset + 2);
+        }
+
+        public static byte[] EncodeOpaque8(byte[] buf)
+        {
+            CheckUint8(buf.Length);
+            return Arrays.Prepend(buf, (byte)buf.Length);
+        }
+
+        public static byte[] EncodeUint8ArrayWithUint8Length(byte[] uints)
+        {
+            byte[] result = new byte[1 + uints.Length];
+            WriteUint8ArrayWithUint8Length(uints, result, 0);
+            return result;
+        }
+
+        public static byte[] EncodeUint16ArrayWithUint16Length(int[] uints)
+        {
+            int length = 2 * uints.Length;
+            byte[] result = new byte[2 + length];
+            WriteUint16ArrayWithUint16Length(uints, result, 0);
+            return result;
+        }
+
+        public static byte ReadUint8(Stream input)
+        {
+            int i = input.ReadByte();
+            if (i < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return (byte)i;
+        }
+
+        public static byte ReadUint8(byte[] buf, int offset)
+        {
+            return buf[offset];
+        }
+
+        public static int ReadUint16(Stream input)
+        {
+            int i1 = input.ReadByte();
+            int i2 = input.ReadByte();
+            if ((i1 | i2) < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return i1 << 8 | i2;
+        }
+
+        public static int ReadUint16(byte[] buf, int offset)
+        {
+            uint n = (uint)buf[offset] << 8;
+            n |= (uint)buf[++offset];
+            return (int)n;
+        }
+
+        public static int ReadUint24(Stream input)
+        {
+            int i1 = input.ReadByte();
+            int i2 = input.ReadByte();
+            int i3 = input.ReadByte();
+            if ((i1 | i2 | i3) < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return (i1 << 16) | (i2 << 8) | i3;
+        }
+
+        public static int ReadUint24(byte[] buf, int offset)
+        {
+            uint n = (uint)buf[offset] << 16;
+            n |= (uint)buf[++offset] << 8;
+            n |= (uint)buf[++offset];
+            return (int)n;
+        }
+
+        public static long ReadUint32(Stream input)
+        {
+            int i1 = input.ReadByte();
+            int i2 = input.ReadByte();
+            int i3 = input.ReadByte();
+            int i4 = input.ReadByte();
+            if (i4 < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return (long)(uint)((i1 << 24) | (i2 << 16) | (i3 << 8) | i4);
+        }
+
+        public static long ReadUint32(byte[] buf, int offset)
+        {
+            uint n = (uint)buf[offset] << 24;
+            n |= (uint)buf[++offset] << 16;
+            n |= (uint)buf[++offset] << 8;
+            n |= (uint)buf[++offset];
+            return (long)n;
+        }
+
+        public static long ReadUint48(Stream input)
+        {
+            int hi = ReadUint24(input);
+            int lo = ReadUint24(input);
+            return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL);
+        }
+
+        public static long ReadUint48(byte[] buf, int offset)
+        {
+            int hi = ReadUint24(buf, offset);
+            int lo = ReadUint24(buf, offset + 3);
+            return ((long)(hi & 0xffffffffL) << 24) | (long)(lo & 0xffffffffL);
+        }
+
+        public static byte[] ReadAllOrNothing(int length, Stream input)
+        {
+            if (length < 1)
+                return EmptyBytes;
+            byte[] buf = new byte[length];
+            int read = Streams.ReadFully(input, buf);
+            if (read == 0)
+                return null;
+            if (read != length)
+                throw new EndOfStreamException();
+            return buf;
+        }
+
+        public static byte[] ReadFully(int length, Stream input)
+        {
+            if (length < 1)
+                return EmptyBytes;
+            byte[] buf = new byte[length];
+            if (length != Streams.ReadFully(input, buf))
+                throw new EndOfStreamException();
+            return buf;
+        }
+
+        public static void ReadFully(byte[] buf, Stream input)
+        {
+            if (Streams.ReadFully(input, buf, 0, buf.Length) < buf.Length)
+                throw new EndOfStreamException();
+        }
+
+        public static byte[] ReadOpaque8(Stream input)
+        {
+            byte length = ReadUint8(input);
+            byte[] bytes = new byte[length];
+            ReadFully(bytes, input);
+            return bytes;
+        }
+
+        public static byte[] ReadOpaque16(Stream input)
+        {
+            int length = ReadUint16(input);
+            byte[] bytes = new byte[length];
+            ReadFully(bytes, input);
+            return bytes;
+        }
+
+        public static byte[] ReadOpaque24(Stream input)
+        {
+            int length = ReadUint24(input);
+            return ReadFully(length, input);
+        }
+
+        public static byte[] ReadUint8Array(int count, Stream input)
+        {
+            byte[] uints = new byte[count];
+            for (int i = 0; i < count; ++i)
+            {
+                uints[i] = ReadUint8(input);
+            }
+            return uints;
+        }
+
+        public static int[] ReadUint16Array(int count, Stream input)
+        {
+            int[] uints = new int[count];
+            for (int i = 0; i < count; ++i)
+            {
+                uints[i] = ReadUint16(input);
+            }
+            return uints;
+        }
+
+        public static ProtocolVersion ReadVersion(byte[] buf, int offset)
+        {
+            return ProtocolVersion.Get(buf[offset], buf[offset + 1]);
+        }
+
+        public static ProtocolVersion ReadVersion(Stream input)
+        {
+            int i1 = input.ReadByte();
+            int i2 = input.ReadByte();
+            if (i2 < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return ProtocolVersion.Get(i1, i2);
+        }
+
+        public static int ReadVersionRaw(byte[] buf, int offset)
+        {
+            return (buf[offset] << 8) | buf[offset + 1];
+        }
+
+        public static int ReadVersionRaw(Stream input)
+        {
+            int i1 = input.ReadByte();
+            int i2 = input.ReadByte();
+            if (i2 < 0)
+            {
+                throw new EndOfStreamException();
+            }
+            return (i1 << 8) | i2;
+        }
+
+        public static Asn1Object ReadAsn1Object(byte[] encoding)
+        {
+            Asn1InputStream asn1 = new Asn1InputStream(encoding);
+            Asn1Object result = asn1.ReadObject();
+            if (null == result)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            if (null != asn1.ReadObject())
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            return result;
+        }
+
+        public static Asn1Object ReadDerObject(byte[] encoding)
+        {
+            /*
+             * NOTE: The current ASN.1 parsing code can't enforce DER-only parsing, but since DER is
+             * canonical, we can check it by re-encoding the result and comparing to the original.
+             */
+            Asn1Object result = ReadAsn1Object(encoding);
+            byte[] check = result.GetEncoded(Asn1Encodable.Der);
+            if (!Arrays.AreEqual(check, encoding))
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            return result;
+        }
+
+        public static void WriteGmtUnixTime(byte[] buf, int offset)
+        {
+            int t = (int)(DateTimeUtilities.CurrentUnixMs() / 1000L);
+            buf[offset] = (byte)(t >> 24);
+            buf[offset + 1] = (byte)(t >> 16);
+            buf[offset + 2] = (byte)(t >> 8);
+            buf[offset + 3] = (byte)t;
+        }
+
+        public static void WriteVersion(ProtocolVersion version, Stream output)
+        {
+            output.WriteByte((byte)version.MajorVersion);
+            output.WriteByte((byte)version.MinorVersion);
+        }
+
+        public static void WriteVersion(ProtocolVersion version, byte[] buf, int offset)
+        {
+            buf[offset] = (byte)version.MajorVersion;
+            buf[offset + 1] = (byte)version.MinorVersion;
+        }
+
+        public static IList GetDefaultDssSignatureAlgorithms()
+        {
+            return VectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.dsa));
+        }
+
+        public static IList GetDefaultECDsaSignatureAlgorithms()
+        {
+            return VectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.ecdsa));
+        }
+
+        public static IList GetDefaultRsaSignatureAlgorithms()
+        {
+            return VectorOfOne(new SignatureAndHashAlgorithm(HashAlgorithm.sha1, SignatureAlgorithm.rsa));
+        }
+
+        public static byte[] GetExtensionData(IDictionary extensions, int extensionType)
+        {
+            return extensions == null ? null : (byte[])extensions[extensionType];
+        }
+
+        public static bool HasExpectedEmptyExtensionData(IDictionary extensions, int extensionType,
+            byte alertDescription)
+        {
+            byte[] extension_data = GetExtensionData(extensions, extensionType);
+            if (extension_data == null)
+                return false;
+            if (extension_data.Length != 0)
+                throw new TlsFatalAlert(alertDescription);
+            return true;
+        }
+
+        public static TlsSession ImportSession(byte[] sessionID, SessionParameters sessionParameters)
+        {
+            return new TlsSessionImpl(sessionID, sessionParameters);
+        }
+
+        public static bool IsSignatureAlgorithmsExtensionAllowed(ProtocolVersion clientVersion)
+        {
+            return ProtocolVersion.TLSv12.IsEqualOrEarlierVersionOf(clientVersion.GetEquivalentTLSVersion());
+        }
+
+        /**
+         * Add a 'signature_algorithms' extension to existing extensions.
+         *
+         * @param extensions                   A {@link Hashtable} to add the extension to.
+         * @param supportedSignatureAlgorithms {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+         * @throws IOException
+         */
+        public static void AddSignatureAlgorithmsExtension(IDictionary extensions, IList supportedSignatureAlgorithms)
+        {
+            extensions[ExtensionType.signature_algorithms] = CreateSignatureAlgorithmsExtension(supportedSignatureAlgorithms);
+        }
+
+        /**
+         * Get a 'signature_algorithms' extension from extensions.
+         *
+         * @param extensions A {@link Hashtable} to get the extension from, if it is present.
+         * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}, or null.
+         * @throws IOException
+         */
+        public static IList GetSignatureAlgorithmsExtension(IDictionary extensions)
+        {
+            byte[] extensionData = GetExtensionData(extensions, ExtensionType.signature_algorithms);
+            return extensionData == null ? null : ReadSignatureAlgorithmsExtension(extensionData);
+        }
+
+        /**
+         * Create a 'signature_algorithms' extension value.
+         *
+         * @param supportedSignatureAlgorithms A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+         * @return A byte array suitable for use as an extension value.
+         * @throws IOException
+         */
+        public static byte[] CreateSignatureAlgorithmsExtension(IList supportedSignatureAlgorithms)
+        {
+            MemoryStream buf = new MemoryStream();
+
+            // supported_signature_algorithms
+            EncodeSupportedSignatureAlgorithms(supportedSignatureAlgorithms, false, buf);
+
+            return buf.ToArray();
+        }
+
+        /**
+         * Read 'signature_algorithms' extension data.
+         *
+         * @param extensionData The extension data.
+         * @return A {@link Vector} containing at least 1 {@link SignatureAndHashAlgorithm}.
+         * @throws IOException
+         */
+        public static IList ReadSignatureAlgorithmsExtension(byte[] extensionData)
+        {
+            if (extensionData == null)
+                throw new ArgumentNullException("extensionData");
+
+            MemoryStream buf = new MemoryStream(extensionData, false);
+
+            // supported_signature_algorithms
+            IList supported_signature_algorithms = ParseSupportedSignatureAlgorithms(false, buf);
+
+            TlsProtocol.AssertEmpty(buf);
+
+            return supported_signature_algorithms;
+        }
+
+        public static void EncodeSupportedSignatureAlgorithms(IList supportedSignatureAlgorithms, bool allowAnonymous,
+            Stream output)
+        {
+            if (supportedSignatureAlgorithms == null || supportedSignatureAlgorithms.Count < 1
+                || supportedSignatureAlgorithms.Count >= (1 << 15))
+            {
+                throw new ArgumentException("must have length from 1 to (2^15 - 1)", "supportedSignatureAlgorithms");
+            }
+
+            // supported_signature_algorithms
+            int length = 2 * supportedSignatureAlgorithms.Count;
+            CheckUint16(length);
+            WriteUint16(length, output);
+
+            foreach (SignatureAndHashAlgorithm entry in supportedSignatureAlgorithms)
+            {
+                if (!allowAnonymous && entry.Signature == SignatureAlgorithm.anonymous)
+                {
+                    /*
+                     * RFC 5246 7.4.1.4.1 The "anonymous" value is meaningless in this context but used
+                     * in Section 7.4.3. It MUST NOT appear in this extension.
+                     */
+                    throw new ArgumentException(
+                        "SignatureAlgorithm.anonymous MUST NOT appear in the signature_algorithms extension");
+                }
+                entry.Encode(output);
+            }
+        }
+
+        public static IList ParseSupportedSignatureAlgorithms(bool allowAnonymous, Stream input)
+        {
+            // supported_signature_algorithms
+            int length = ReadUint16(input);
+            if (length < 2 || (length & 1) != 0)
+                throw new TlsFatalAlert(AlertDescription.decode_error);
+            int count = length / 2;
+            IList supportedSignatureAlgorithms = Platform.CreateArrayList(count);
+            for (int i = 0; i < count; ++i)
+            {
+                SignatureAndHashAlgorithm entry = SignatureAndHashAlgorithm.Parse(input);
+                if (!allowAnonymous && entry.Signature == SignatureAlgorithm.anonymous)
+                {
+                    /*
+                     * RFC 5246 7.4.1.4.1 The "anonymous" value is meaningless in this context but used
+                     * in Section 7.4.3. It MUST NOT appear in this extension.
+                     */
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                }
+                supportedSignatureAlgorithms.Add(entry);
+            }
+            return supportedSignatureAlgorithms;
+        }
+
+        public static byte[] PRF(TlsContext context, byte[] secret, string asciiLabel, byte[] seed, int size)
+        {
+            ProtocolVersion version = context.ServerVersion;
+
+            if (version.IsSsl)
+                throw new InvalidOperationException("No PRF available for SSLv3 session");
+
+            byte[] label = Strings.ToByteArray(asciiLabel);
+            byte[] labelSeed = Concat(label, seed);
+
+            int prfAlgorithm = context.SecurityParameters.PrfAlgorithm;
+
+            if (prfAlgorithm == PrfAlgorithm.tls_prf_legacy)
+            {
+                return PRF_legacy(secret, label, labelSeed, size);
+            }
+
+            IDigest prfDigest = CreatePrfHash(prfAlgorithm);
+            byte[] buf = new byte[size];
+            HMacHash(prfDigest, secret, labelSeed, buf);
+            return buf;
+        }
+
+        public static byte[] PRF_legacy(byte[] secret, string asciiLabel, byte[] seed, int size)
+        {
+            byte[] label = Strings.ToByteArray(asciiLabel);
+            byte[] labelSeed = Concat(label, seed);
+
+            return PRF_legacy(secret, label, labelSeed, size);
+        }
+
+        internal static byte[] PRF_legacy(byte[] secret, byte[] label, byte[] labelSeed, int size)
+        {
+            int s_half = (secret.Length + 1) / 2;
+            byte[] s1 = new byte[s_half];
+            byte[] s2 = new byte[s_half];
+            Array.Copy(secret, 0, s1, 0, s_half);
+            Array.Copy(secret, secret.Length - s_half, s2, 0, s_half);
+
+            byte[] b1 = new byte[size];
+            byte[] b2 = new byte[size];
+            HMacHash(CreateHash(HashAlgorithm.md5), s1, labelSeed, b1);
+            HMacHash(CreateHash(HashAlgorithm.sha1), s2, labelSeed, b2);
+            for (int i = 0; i < size; i++)
+            {
+                b1[i] ^= b2[i];
+            }
+            return b1;
+        }
+
+        internal static byte[] Concat(byte[] a, byte[] b)
+        {
+            byte[] c = new byte[a.Length + b.Length];
+            Array.Copy(a, 0, c, 0, a.Length);
+            Array.Copy(b, 0, c, a.Length, b.Length);
+            return c;
+        }
+
+        internal static void HMacHash(IDigest digest, byte[] secret, byte[] seed, byte[] output)
+        {
+            HMac mac = new HMac(digest);
+            mac.Init(new KeyParameter(secret));
+            byte[] a = seed;
+            int size = digest.GetDigestSize();
+            int iterations = (output.Length + size - 1) / size;
+            byte[] buf = new byte[mac.GetMacSize()];
+            byte[] buf2 = new byte[mac.GetMacSize()];
+            for (int i = 0; i < iterations; i++)
+            {
+                mac.BlockUpdate(a, 0, a.Length);
+                mac.DoFinal(buf, 0);
+                a = buf;
+                mac.BlockUpdate(a, 0, a.Length);
+                mac.BlockUpdate(seed, 0, seed.Length);
+                mac.DoFinal(buf2, 0);
+                Array.Copy(buf2, 0, output, (size * i), System.Math.Min(size, output.Length - (size * i)));
+            }
+        }
+
+        internal static void ValidateKeyUsage(X509CertificateStructure c, int keyUsageBits)
+        {
+            X509Extensions exts = c.TbsCertificate.Extensions;
+            if (exts != null)
+            {
+                X509Extension ext = exts.GetExtension(X509Extensions.KeyUsage);
+                if (ext != null)
+                {
+                    DerBitString ku = KeyUsage.GetInstance(ext);
+                    int bits = ku.GetBytes()[0];
+                    if ((bits & keyUsageBits) != keyUsageBits)
+                    {
+                        throw new TlsFatalAlert(AlertDescription.certificate_unknown);
+                    }
+                }
+            }
+        }
+
+        internal static byte[] CalculateKeyBlock(TlsContext context, int size)
+        {
+            SecurityParameters securityParameters = context.SecurityParameters;
+            byte[] master_secret = securityParameters.MasterSecret;
+            byte[] seed = Concat(securityParameters.ServerRandom, securityParameters.ClientRandom);
+
+            if (IsSsl(context))
+            {
+                return CalculateKeyBlock_Ssl(master_secret, seed, size);
+            }
+
+            return PRF(context, master_secret, ExporterLabel.key_expansion, seed, size);
+        }
+
+        internal static byte[] CalculateKeyBlock_Ssl(byte[] master_secret, byte[] random, int size)
+        {
+            IDigest md5 = CreateHash(HashAlgorithm.md5);
+            IDigest sha1 = CreateHash(HashAlgorithm.sha1);
+            int md5Size = md5.GetDigestSize();
+            byte[] shatmp = new byte[sha1.GetDigestSize()];
+            byte[] tmp = new byte[size + md5Size];
+
+            int i = 0, pos = 0;
+            while (pos < size)
+            {
+                byte[] ssl3Const = SSL3_CONST[i];
+
+                sha1.BlockUpdate(ssl3Const, 0, ssl3Const.Length);
+                sha1.BlockUpdate(master_secret, 0, master_secret.Length);
+                sha1.BlockUpdate(random, 0, random.Length);
+                sha1.DoFinal(shatmp, 0);
+
+                md5.BlockUpdate(master_secret, 0, master_secret.Length);
+                md5.BlockUpdate(shatmp, 0, shatmp.Length);
+                md5.DoFinal(tmp, pos);
+
+                pos += md5Size;
+                ++i;
+            }
+
+            return Arrays.CopyOfRange(tmp, 0, size);
+        }
+
+        internal static byte[] CalculateMasterSecret(TlsContext context, byte[] pre_master_secret)
+        {
+            SecurityParameters securityParameters = context.SecurityParameters;
+            byte[] seed = Concat(securityParameters.ClientRandom, securityParameters.ServerRandom);
+
+            if (IsSsl(context))
+            {
+                return CalculateMasterSecret_Ssl(pre_master_secret, seed);
+            }
+
+            return PRF(context, pre_master_secret, ExporterLabel.master_secret, seed, 48);
+        }
+
+        internal static byte[] CalculateMasterSecret_Ssl(byte[] pre_master_secret, byte[] random)
+        {
+            IDigest md5 = CreateHash(HashAlgorithm.md5);
+            IDigest sha1 = CreateHash(HashAlgorithm.sha1);
+            int md5Size = md5.GetDigestSize();
+            byte[] shatmp = new byte[sha1.GetDigestSize()];
+
+            byte[] rval = new byte[md5Size * 3];
+            int pos = 0;
+
+            for (int i = 0; i < 3; ++i)
+            {
+                byte[] ssl3Const = SSL3_CONST[i];
+
+                sha1.BlockUpdate(ssl3Const, 0, ssl3Const.Length);
+                sha1.BlockUpdate(pre_master_secret, 0, pre_master_secret.Length);
+                sha1.BlockUpdate(random, 0, random.Length);
+                sha1.DoFinal(shatmp, 0);
+
+                md5.BlockUpdate(pre_master_secret, 0, pre_master_secret.Length);
+                md5.BlockUpdate(shatmp, 0, shatmp.Length);
+                md5.DoFinal(rval, pos);
+
+                pos += md5Size;
+            }
+
+            return rval;
+        }
+
+        internal static byte[] CalculateVerifyData(TlsContext context, string asciiLabel, byte[] handshakeHash)
+        {
+            if (IsSsl(context))
+            {
+                return handshakeHash;
+            }
+
+            SecurityParameters securityParameters = context.SecurityParameters;
+            byte[] master_secret = securityParameters.MasterSecret;
+            int verify_data_length = securityParameters.VerifyDataLength;
+
+            return PRF(context, master_secret, asciiLabel, handshakeHash, verify_data_length);
+        }
+
+        public static IDigest CreateHash(byte hashAlgorithm)
+        {
+            switch (hashAlgorithm)
+            {
+            case HashAlgorithm.md5:
+                return new MD5Digest();
+            case HashAlgorithm.sha1:
+                return new Sha1Digest();
+            case HashAlgorithm.sha224:
+                return new Sha224Digest();
+            case HashAlgorithm.sha256:
+                return new Sha256Digest();
+            case HashAlgorithm.sha384:
+                return new Sha384Digest();
+            case HashAlgorithm.sha512:
+                return new Sha512Digest();
+            default:
+                throw new ArgumentException("unknown HashAlgorithm", "hashAlgorithm");
+            }
+        }
+
+        public static IDigest CloneHash(byte hashAlgorithm, IDigest hash)
+        {
+            switch (hashAlgorithm)
+            {
+            case HashAlgorithm.md5:
+                return new MD5Digest((MD5Digest)hash);
+            case HashAlgorithm.sha1:
+                return new Sha1Digest((Sha1Digest)hash);
+            case HashAlgorithm.sha224:
+                return new Sha224Digest((Sha224Digest)hash);
+            case HashAlgorithm.sha256:
+                return new Sha256Digest((Sha256Digest)hash);
+            case HashAlgorithm.sha384:
+                return new Sha384Digest((Sha384Digest)hash);
+            case HashAlgorithm.sha512:
+                return new Sha512Digest((Sha512Digest)hash);
+            default:
+                throw new ArgumentException("unknown HashAlgorithm", "hashAlgorithm");
+            }
+        }
+
+        public static IDigest CreatePrfHash(int prfAlgorithm)
+        {
+            switch (prfAlgorithm)
+            {
+                case PrfAlgorithm.tls_prf_legacy:
+                    return new CombinedHash();
+                default:
+                    return CreateHash(GetHashAlgorithmForPrfAlgorithm(prfAlgorithm));
+            }
+        }
+
+        public static IDigest ClonePrfHash(int prfAlgorithm, IDigest hash)
+        {
+            switch (prfAlgorithm)
+            {
+                case PrfAlgorithm.tls_prf_legacy:
+                    return new CombinedHash((CombinedHash)hash);
+                default:
+                    return CloneHash(GetHashAlgorithmForPrfAlgorithm(prfAlgorithm), hash);
+            }
+        }
+
+        public static byte GetHashAlgorithmForPrfAlgorithm(int prfAlgorithm)
+        {
+            switch (prfAlgorithm)
+            {
+                case PrfAlgorithm.tls_prf_legacy:
+                    throw new ArgumentException("legacy PRF not a valid algorithm", "prfAlgorithm");
+                case PrfAlgorithm.tls_prf_sha256:
+                    return HashAlgorithm.sha256;
+                case PrfAlgorithm.tls_prf_sha384:
+                    return HashAlgorithm.sha384;
+                default:
+                    throw new ArgumentException("unknown PrfAlgorithm", "prfAlgorithm");
+            }
+        }
+
+        public static DerObjectIdentifier GetOidForHashAlgorithm(byte hashAlgorithm)
+        {
+            switch (hashAlgorithm)
+            {
+                case HashAlgorithm.md5:
+                    return PkcsObjectIdentifiers.MD5;
+                case HashAlgorithm.sha1:
+                    return X509ObjectIdentifiers.IdSha1;
+                case HashAlgorithm.sha224:
+                    return NistObjectIdentifiers.IdSha224;
+                case HashAlgorithm.sha256:
+                    return NistObjectIdentifiers.IdSha256;
+                case HashAlgorithm.sha384:
+                    return NistObjectIdentifiers.IdSha384;
+                case HashAlgorithm.sha512:
+                    return NistObjectIdentifiers.IdSha512;
+                default:
+                    throw new ArgumentException("unknown HashAlgorithm", "hashAlgorithm");
+            }
+        }
+
+        internal static short GetClientCertificateType(Certificate clientCertificate, Certificate serverCertificate)
+        {
+            if (clientCertificate.IsEmpty)
+                return -1;
+
+            X509CertificateStructure x509Cert = clientCertificate.GetCertificateAt(0);
+            SubjectPublicKeyInfo keyInfo = x509Cert.SubjectPublicKeyInfo;
+            try
+            {
+                AsymmetricKeyParameter publicKey = PublicKeyFactory.CreateKey(keyInfo);
+                if (publicKey.IsPrivate)
+                    throw new TlsFatalAlert(AlertDescription.internal_error);
+
+                /*
+                 * TODO RFC 5246 7.4.6. The certificates MUST be signed using an acceptable hash/
+                 * signature algorithm pair, as described in Section 7.4.4. Note that this relaxes the
+                 * constraints on certificate-signing algorithms found in prior versions of TLS.
+                 */
+
+                /*
+                 * RFC 5246 7.4.6. Client Certificate
+                 */
+
+                /*
+                 * RSA public key; the certificate MUST allow the key to be used for signing with the
+                 * signature scheme and hash algorithm that will be employed in the certificate verify
+                 * message.
+                 */
+                if (publicKey is RsaKeyParameters)
+                {
+                    ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+                    return ClientCertificateType.rsa_sign;
+                }
+
+                /*
+                 * DSA public key; the certificate MUST allow the key to be used for signing with the
+                 * hash algorithm that will be employed in the certificate verify message.
+                 */
+                if (publicKey is DsaPublicKeyParameters)
+                {
+                    ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+                    return ClientCertificateType.dss_sign;
+                }
+
+                /*
+                 * ECDSA-capable public key; the certificate MUST allow the key to be used for signing
+                 * with the hash algorithm that will be employed in the certificate verify message; the
+                 * public key MUST use a curve and point format supported by the server.
+                 */
+                if (publicKey is ECPublicKeyParameters)
+                {
+                    ValidateKeyUsage(x509Cert, KeyUsage.DigitalSignature);
+                    // TODO Check the curve and point format
+                    return ClientCertificateType.ecdsa_sign;
+                }
+
+                // TODO Add support for ClientCertificateType.*_fixed_*
+
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate);
+            }
+            catch (Exception e)
+            {
+                throw new TlsFatalAlert(AlertDescription.unsupported_certificate, e);
+            }
+        }
+
+        internal static void TrackHashAlgorithms(TlsHandshakeHash handshakeHash, IList supportedSignatureAlgorithms)
+        {
+            if (supportedSignatureAlgorithms != null)
+            {
+                foreach (SignatureAndHashAlgorithm signatureAndHashAlgorithm in supportedSignatureAlgorithms)
+                {
+                    byte hashAlgorithm = signatureAndHashAlgorithm.Hash;
+                    handshakeHash.TrackHashAlgorithm(hashAlgorithm);
+                }
+            }
+        }
+
+        public static bool HasSigningCapability(byte clientCertificateType)
+        {
+            switch (clientCertificateType)
+            {
+            case ClientCertificateType.dss_sign:
+            case ClientCertificateType.ecdsa_sign:
+            case ClientCertificateType.rsa_sign:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        public static TlsSigner CreateTlsSigner(byte clientCertificateType)
+        {
+            switch (clientCertificateType)
+            {
+            case ClientCertificateType.dss_sign:
+                return new TlsDssSigner();
+            case ClientCertificateType.ecdsa_sign:
+                return new TlsECDsaSigner();
+            case ClientCertificateType.rsa_sign:
+                return new TlsRsaSigner();
+            default:
+                throw new ArgumentException("not a type with signing capability", "clientCertificateType");
+            }
+        }
+
+        internal static readonly byte[] SSL_CLIENT = {0x43, 0x4C, 0x4E, 0x54};
+        internal static readonly byte[] SSL_SERVER = {0x53, 0x52, 0x56, 0x52};
+
+        // SSL3 magic mix constants ("A", "BB", "CCC", ...)
+        internal static readonly byte[][] SSL3_CONST = GenSsl3Const();
+
+        private static byte[][] GenSsl3Const()
+        {
+            int n = 10;
+            byte[][] arr = new byte[n][];
+            for (int i = 0; i < n; i++)
+            {
+                byte[] b = new byte[i + 1];
+                Arrays.Fill(b, (byte)('A' + i));
+                arr[i] = b;
+            }
+            return arr;
+        }
+
+        private static IList VectorOfOne(object obj)
+        {
+            IList v = Platform.CreateArrayList(1);
+            v.Add(obj);
+            return v;
+        }
+
+        public static int GetCipherType(int ciphersuite)
+        {
+            switch (GetEncryptionAlgorithm(ciphersuite))
+            {
+            case EncryptionAlgorithm.AES_128_GCM:
+            case EncryptionAlgorithm.AES_256_GCM:
+            case EncryptionAlgorithm.AES_128_CCM:
+            case EncryptionAlgorithm.AES_128_CCM_8:
+            case EncryptionAlgorithm.AES_256_CCM:
+            case EncryptionAlgorithm.AES_256_CCM_8:
+            case EncryptionAlgorithm.CAMELLIA_128_GCM:
+            case EncryptionAlgorithm.CAMELLIA_256_GCM:
+            case EncryptionAlgorithm.AEAD_CHACHA20_POLY1305:
+                return CipherType.aead;
+
+            case EncryptionAlgorithm.RC2_CBC_40:
+            case EncryptionAlgorithm.IDEA_CBC:
+            case EncryptionAlgorithm.DES40_CBC:
+            case EncryptionAlgorithm.DES_CBC:
+            case EncryptionAlgorithm.cls_3DES_EDE_CBC:
+            case EncryptionAlgorithm.AES_128_CBC:
+            case EncryptionAlgorithm.AES_256_CBC:
+            case EncryptionAlgorithm.CAMELLIA_128_CBC:
+            case EncryptionAlgorithm.CAMELLIA_256_CBC:
+            case EncryptionAlgorithm.SEED_CBC:
+                return CipherType.block;
+
+            case EncryptionAlgorithm.RC4_40:
+            case EncryptionAlgorithm.RC4_128:
+            case EncryptionAlgorithm.ESTREAM_SALSA20:
+            case EncryptionAlgorithm.SALSA20:
+                return CipherType.stream;
+
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public static int GetEncryptionAlgorithm(int ciphersuite)
+        {
+            switch (ciphersuite)
+            {
+            case CipherSuite.TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA:
+                return EncryptionAlgorithm.cls_3DES_EDE_CBC;
+
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+                return EncryptionAlgorithm.AEAD_CHACHA20_POLY1305;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_128_CBC_SHA:
+                return EncryptionAlgorithm.AES_128_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+                return EncryptionAlgorithm.AES_128_CBC;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+                return EncryptionAlgorithm.AES_128_CCM;
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+                return EncryptionAlgorithm.AES_128_CCM_8;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+                return EncryptionAlgorithm.AES_128_GCM;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA:
+            case CipherSuite.TLS_SRP_SHA_WITH_AES_256_CBC_SHA:
+                return EncryptionAlgorithm.AES_256_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+                return EncryptionAlgorithm.AES_256_CBC;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_CBC_SHA384:
+                return EncryptionAlgorithm.AES_256_CBC;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+                return EncryptionAlgorithm.AES_256_CCM;
+
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+                return EncryptionAlgorithm.AES_256_CCM_8;
+
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+                return EncryptionAlgorithm.AES_256_GCM;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA:
+                return EncryptionAlgorithm.CAMELLIA_128_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+                return EncryptionAlgorithm.CAMELLIA_128_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+                return EncryptionAlgorithm.CAMELLIA_128_GCM;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA:
+                return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+                return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384:
+                return EncryptionAlgorithm.CAMELLIA_256_CBC;
+
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+                return EncryptionAlgorithm.CAMELLIA_256_GCM;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_ESTREAM_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1:
+                return EncryptionAlgorithm.ESTREAM_SALSA20;
+
+            case CipherSuite.TLS_RSA_WITH_NULL_MD5:
+                return EncryptionAlgorithm.NULL;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_NULL_SHA:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA:
+                return EncryptionAlgorithm.NULL;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA256:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+                return EncryptionAlgorithm.NULL;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_PSK_WITH_NULL_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_NULL_SHA384:
+                return EncryptionAlgorithm.NULL;
+
+            case CipherSuite.TLS_DH_anon_WITH_RC4_128_MD5:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_MD5:
+                return EncryptionAlgorithm.RC4_128;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_anon_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDH_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_PSK_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_WITH_RC4_128_SHA:
+            case CipherSuite.TLS_RSA_PSK_WITH_RC4_128_SHA:
+                return EncryptionAlgorithm.RC4_128;
+
+            case CipherSuite.TLS_DHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_DHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_PSK_WITH_SALSA20_SHA1:
+            case CipherSuite.TLS_RSA_WITH_SALSA20_SHA1:
+                return EncryptionAlgorithm.SALSA20;
+
+            case CipherSuite.TLS_DH_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DH_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_DSS_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_DHE_RSA_WITH_SEED_CBC_SHA:
+            case CipherSuite.TLS_RSA_WITH_SEED_CBC_SHA:
+                return EncryptionAlgorithm.SEED_CBC;
+
+            default:
+                throw new TlsFatalAlert(AlertDescription.internal_error);
+            }
+        }
+
+        public static ProtocolVersion GetMinimumVersion(int ciphersuite)
+        {
+            switch (ciphersuite)
+            {
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_anon_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_DSS_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_DHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_DHE_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM:
+            case CipherSuite.TLS_PSK_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_128_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM:
+            case CipherSuite.TLS_RSA_WITH_AES_256_CCM_8:
+            case CipherSuite.TLS_RSA_WITH_AES_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256:
+            case CipherSuite.TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384:
+            case CipherSuite.TLS_RSA_WITH_NULL_SHA256:
+                return ProtocolVersion.TLSv12;
+
+            default:
+                return ProtocolVersion.SSLv3;
+            }
+        }
+
+        public static bool IsAeadCipherSuite(int ciphersuite)
+        {
+            return CipherType.aead == GetCipherType(ciphersuite);
+        }
+
+        public static bool IsBlockCipherSuite(int ciphersuite)
+        {
+            return CipherType.block == GetCipherType(ciphersuite);
+        }
+
+        public static bool IsStreamCipherSuite(int ciphersuite)
+        {
+            return CipherType.stream == GetCipherType(ciphersuite);
+        }
+
+        public static bool IsValidCipherSuiteForVersion(int cipherSuite, ProtocolVersion serverVersion)
+        {
+            return GetMinimumVersion(cipherSuite).IsEqualOrEarlierVersionOf(serverVersion.GetEquivalentTLSVersion());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/UrlAndHash.cs b/BouncyCastle.AxCrypt/src/crypto/tls/UrlAndHash.cs
new file mode 100644
index 0000000..9ffd2cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/UrlAndHash.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 6066 5.
+     */
+    public class UrlAndHash
+    {
+        protected readonly string mUrl;
+        protected readonly byte[] mSha1Hash;
+
+        public UrlAndHash(string url, byte[] sha1Hash)
+        {
+            if (url == null || url.Length < 1 || url.Length >= (1 << 16))
+                throw new ArgumentException("must have length from 1 to (2^16 - 1)", "url");
+            if (sha1Hash != null && sha1Hash.Length != 20)
+                throw new ArgumentException("must have length == 20, if present", "sha1Hash");
+
+            this.mUrl = url;
+            this.mSha1Hash = sha1Hash;
+        }
+
+        public virtual string Url
+        {
+            get { return mUrl; }
+        }
+
+        public virtual byte[] Sha1Hash
+        {
+            get { return mSha1Hash; }
+        }
+
+        /**
+         * Encode this {@link UrlAndHash} to a {@link Stream}.
+         *
+         * @param output the {@link Stream} to encode to.
+         * @throws IOException
+         */
+        public virtual void Encode(Stream output)
+        {
+            byte[] urlEncoding = Strings.ToByteArray(this.mUrl);
+            TlsUtilities.WriteOpaque16(urlEncoding, output);
+
+            if (this.mSha1Hash == null)
+            {
+                TlsUtilities.WriteUint8(0, output);
+            }
+            else
+            {
+                TlsUtilities.WriteUint8(1, output);
+                output.Write(this.mSha1Hash, 0, this.mSha1Hash.Length);
+            }
+        }
+
+        /**
+         * Parse a {@link UrlAndHash} from a {@link Stream}.
+         * 
+         * @param context
+         *            the {@link TlsContext} of the current connection.
+         * @param input
+         *            the {@link Stream} to parse from.
+         * @return a {@link UrlAndHash} object.
+         * @throws IOException
+         */
+        public static UrlAndHash Parse(TlsContext context, Stream input)
+        {
+            byte[] urlEncoding = TlsUtilities.ReadOpaque16(input);
+            if (urlEncoding.Length < 1)
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            string url = Strings.FromByteArray(urlEncoding);
+
+            byte[] sha1Hash = null;
+            byte padding = TlsUtilities.ReadUint8(input);
+            switch (padding)
+            {
+            case 0:
+                if (TlsUtilities.IsTlsV12(context))
+                    throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+                break;
+            case 1:
+                sha1Hash = TlsUtilities.ReadFully(20, input);
+                break;
+            default:
+                throw new TlsFatalAlert(AlertDescription.illegal_parameter);
+            }
+
+            return new UrlAndHash(url, sha1Hash);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/UseSrtpData.cs b/BouncyCastle.AxCrypt/src/crypto/tls/UseSrtpData.cs
new file mode 100644
index 0000000..fe8f8ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/UseSrtpData.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+using System.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /**
+     * RFC 5764 4.1.1
+     */
+    public class UseSrtpData
+    {
+        protected readonly int[] mProtectionProfiles;
+        protected readonly byte[] mMki;
+
+        /**
+         * @param protectionProfiles see {@link SrtpProtectionProfile} for valid constants.
+         * @param mki                valid lengths from 0 to 255.
+         */
+        public UseSrtpData(int[] protectionProfiles, byte[] mki)
+        {
+            if (protectionProfiles == null || protectionProfiles.Length < 1
+                || protectionProfiles.Length >= (1 << 15))
+            {
+                throw new ArgumentException("must have length from 1 to (2^15 - 1)", "protectionProfiles");
+            }
+
+            if (mki == null)
+            {
+                mki = TlsUtilities.EmptyBytes;
+            }
+            else if (mki.Length > 255)
+            {
+                throw new ArgumentException("cannot be longer than 255 bytes", "mki");
+            }
+
+            this.mProtectionProfiles = protectionProfiles;
+            this.mMki = mki;
+        }
+
+        /**
+         * @return see {@link SrtpProtectionProfile} for valid constants.
+         */
+        public virtual int[] ProtectionProfiles
+        {
+            get { return mProtectionProfiles; }
+        }
+
+        /**
+         * @return valid lengths from 0 to 255.
+         */
+        public virtual byte[] Mki
+        {
+            get { return mMki; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/tls/UserMappingType.cs b/BouncyCastle.AxCrypt/src/crypto/tls/UserMappingType.cs
new file mode 100644
index 0000000..6cff517
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/tls/UserMappingType.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+    /// <remarks>RFC 4681</remarks>
+    public abstract class UserMappingType
+    {
+        /*
+         * RFC 4681
+         */
+        public const byte upn_domain_hint = 64;
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/crypto/util/Pack.cs b/BouncyCastle.AxCrypt/src/crypto/util/Pack.cs
new file mode 100644
index 0000000..087cb7c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/crypto/util/Pack.cs
@@ -0,0 +1,266 @@
+using System;
+
+namespace Org.BouncyCastle.Crypto.Utilities
+{
+    internal sealed class Pack
+    {
+        private Pack()
+        {
+        }
+
+        internal static void UInt16_To_BE(ushort n, byte[] bs)
+        {
+            bs[0] = (byte)(n >> 8);
+            bs[1] = (byte)(n);
+        }
+
+        internal static void UInt16_To_BE(ushort n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n >> 8);
+            bs[off + 1] = (byte)(n);
+        }
+
+        internal static ushort BE_To_UInt16(byte[] bs)
+        {
+            uint n = (uint)bs[0] << 8
+                | (uint)bs[1];
+            return (ushort)n;
+        }
+
+        internal static ushort BE_To_UInt16(byte[] bs, int off)
+        {
+            uint n = (uint)bs[off] << 8
+                | (uint)bs[off + 1];
+            return (ushort)n;
+        }
+
+        internal static byte[] UInt32_To_BE(uint n)
+        {
+            byte[] bs = new byte[4];
+            UInt32_To_BE(n, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt32_To_BE(uint n, byte[] bs)
+        {
+            bs[0] = (byte)(n >> 24);
+            bs[1] = (byte)(n >> 16);
+            bs[2] = (byte)(n >> 8);
+            bs[3] = (byte)(n);
+        }
+
+        internal static void UInt32_To_BE(uint n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n >> 24);
+            bs[off + 1] = (byte)(n >> 16);
+            bs[off + 2] = (byte)(n >> 8);
+            bs[off + 3] = (byte)(n);
+        }
+
+        internal static byte[] UInt32_To_BE(uint[] ns)
+        {
+            byte[] bs = new byte[4 * ns.Length];
+            UInt32_To_BE(ns, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt32_To_BE(uint[] ns, byte[] bs, int off)
+        {
+            for (int i = 0; i < ns.Length; ++i)
+            {
+                UInt32_To_BE(ns[i], bs, off);
+                off += 4;
+            }
+        }
+
+        internal static uint BE_To_UInt32(byte[] bs)
+        {
+            return (uint)bs[0] << 24
+                | (uint)bs[1] << 16
+                | (uint)bs[2] << 8
+                | (uint)bs[3];
+        }
+
+        internal static uint BE_To_UInt32(byte[] bs, int off)
+        {
+            return (uint)bs[off] << 24
+                | (uint)bs[off + 1] << 16
+                | (uint)bs[off + 2] << 8
+                | (uint)bs[off + 3];
+        }
+
+        internal static void BE_To_UInt32(byte[] bs, int off, uint[] ns)
+        {
+            for (int i = 0; i < ns.Length; ++i)
+            {
+                ns[i] = BE_To_UInt32(bs, off);
+                off += 4;
+            }
+        }
+
+        internal static byte[] UInt64_To_BE(ulong n)
+        {
+            byte[] bs = new byte[8];
+            UInt64_To_BE(n, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt64_To_BE(ulong n, byte[] bs)
+        {
+            UInt32_To_BE((uint)(n >> 32), bs);
+            UInt32_To_BE((uint)(n), bs, 4);
+        }
+
+        internal static void UInt64_To_BE(ulong n, byte[] bs, int off)
+        {
+            UInt32_To_BE((uint)(n >> 32), bs, off);
+            UInt32_To_BE((uint)(n), bs, off + 4);
+        }
+
+        internal static ulong BE_To_UInt64(byte[] bs)
+        {
+            uint hi = BE_To_UInt32(bs);
+            uint lo = BE_To_UInt32(bs, 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        internal static ulong BE_To_UInt64(byte[] bs, int off)
+        {
+            uint hi = BE_To_UInt32(bs, off);
+            uint lo = BE_To_UInt32(bs, off + 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        internal static void UInt16_To_LE(ushort n, byte[] bs)
+        {
+            bs[0] = (byte)(n);
+            bs[1] = (byte)(n >> 8);
+        }
+
+        internal static void UInt16_To_LE(ushort n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n);
+            bs[off + 1] = (byte)(n >> 8);
+        }
+
+        internal static ushort LE_To_UInt16(byte[] bs)
+        {
+            uint n = (uint)bs[0]
+                | (uint)bs[1] << 8;
+            return (ushort)n;
+        }
+
+        internal static ushort LE_To_UInt16(byte[] bs, int off)
+        {
+            uint n = (uint)bs[off]
+                | (uint)bs[off + 1] << 8;
+            return (ushort)n;
+        }
+
+        internal static byte[] UInt32_To_LE(uint n)
+        {
+            byte[] bs = new byte[4];
+            UInt32_To_LE(n, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt32_To_LE(uint n, byte[] bs)
+        {
+            bs[0] = (byte)(n);
+            bs[1] = (byte)(n >> 8);
+            bs[2] = (byte)(n >> 16);
+            bs[3] = (byte)(n >> 24);
+        }
+
+        internal static void UInt32_To_LE(uint n, byte[] bs, int off)
+        {
+            bs[off] = (byte)(n);
+            bs[off + 1] = (byte)(n >> 8);
+            bs[off + 2] = (byte)(n >> 16);
+            bs[off + 3] = (byte)(n >> 24);
+        }
+
+        internal static byte[] UInt32_To_LE(uint[] ns)
+        {
+            byte[] bs = new byte[4 * ns.Length];
+            UInt32_To_LE(ns, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt32_To_LE(uint[] ns, byte[] bs, int off)
+        {
+            for (int i = 0; i < ns.Length; ++i)
+            {
+                UInt32_To_LE(ns[i], bs, off);
+                off += 4;
+            }
+        }
+
+        internal static uint LE_To_UInt32(byte[] bs)
+        {
+            return (uint)bs[0]
+                | (uint)bs[1] << 8
+                | (uint)bs[2] << 16
+                | (uint)bs[3] << 24;
+        }
+
+        internal static uint LE_To_UInt32(byte[] bs, int off)
+        {
+            return (uint)bs[off]
+                | (uint)bs[off + 1] << 8
+                | (uint)bs[off + 2] << 16
+                | (uint)bs[off + 3] << 24;
+        }
+
+        internal static void LE_To_UInt32(byte[] bs, int off, uint[] ns)
+        {
+            for (int i = 0; i < ns.Length; ++i)
+            {
+                ns[i] = LE_To_UInt32(bs, off);
+                off += 4;
+            }
+        }
+
+        internal static void LE_To_UInt32(byte[] bs, int bOff, uint[] ns, int nOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                ns[nOff + i] = LE_To_UInt32(bs, bOff);
+                bOff += 4;
+            }
+        }
+
+        internal static byte[] UInt64_To_LE(ulong n)
+        {
+            byte[] bs = new byte[8];
+            UInt64_To_LE(n, bs, 0);
+            return bs;
+        }
+
+        internal static void UInt64_To_LE(ulong n, byte[] bs)
+        {
+            UInt32_To_LE((uint)(n), bs);
+            UInt32_To_LE((uint)(n >> 32), bs, 4);
+        }
+
+        internal static void UInt64_To_LE(ulong n, byte[] bs, int off)
+        {
+            UInt32_To_LE((uint)(n), bs, off);
+            UInt32_To_LE((uint)(n >> 32), bs, off + 4);
+        }
+
+        internal static ulong LE_To_UInt64(byte[] bs)
+        {
+            uint lo = LE_To_UInt32(bs);
+            uint hi = LE_To_UInt32(bs, 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+
+        internal static ulong LE_To_UInt64(byte[] bs, int off)
+        {
+            uint lo = LE_To_UInt32(bs, off);
+            uint hi = LE_To_UInt32(bs, off + 4);
+            return ((ulong)hi << 32) | (ulong)lo;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/BigInteger.cs b/BouncyCastle.AxCrypt/src/math/BigInteger.cs
new file mode 100644
index 0000000..b5b1bc4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/BigInteger.cs
@@ -0,0 +1,3565 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Globalization;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class BigInteger
+    {
+        // The first few odd primes
+        /*
+                3   5   7   11  13  17  19  23  29
+            31  37  41  43  47  53  59  61  67  71
+            73  79  83  89  97  101 103 107 109 113
+            127 131 137 139 149 151 157 163 167 173
+            179 181 191 193 197 199 211 223 227 229
+            233 239 241 251 257 263 269 271 277 281
+            283 293 307 311 313 317 331 337 347 349
+            353 359 367 373 379 383 389 397 401 409
+            419 421 431 433 439 443 449 457 461 463
+            467 479 487 491 499 503 509 521 523 541
+            547 557 563 569 571 577 587 593 599 601
+            607 613 617 619 631 641 643 647 653 659
+            661 673 677 683 691 701 709 719 727 733
+            739 743 751 757 761 769 773 787 797 809
+            811 821 823 827 829 839 853 857 859 863
+            877 881 883 887 907 911 919 929 937 941
+            947 953 967 971 977 983 991 997 1009
+            1013 1019 1021 1031 1033 1039 1049 1051
+            1061 1063 1069 1087 1091 1093 1097 1103
+            1109 1117 1123 1129 1151 1153 1163 1171
+            1181 1187 1193 1201 1213 1217 1223 1229
+            1231 1237 1249 1259 1277 1279 1283 1289
+        */
+
+        // Each list has a product < 2^31
+        internal static readonly int[][] primeLists = new int[][]
+        {
+            new int[]{ 3, 5, 7, 11, 13, 17, 19, 23 },
+            new int[]{ 29, 31, 37, 41, 43 },
+            new int[]{ 47, 53, 59, 61, 67 },
+            new int[]{ 71, 73, 79, 83 },
+            new int[]{ 89, 97, 101, 103 },
+
+            new int[]{ 107, 109, 113, 127 },
+            new int[]{ 131, 137, 139, 149 },
+            new int[]{ 151, 157, 163, 167 },
+            new int[]{ 173, 179, 181, 191 },
+            new int[]{ 193, 197, 199, 211 },
+
+            new int[]{ 223, 227, 229 },
+            new int[]{ 233, 239, 241 },
+            new int[]{ 251, 257, 263 },
+            new int[]{ 269, 271, 277 },
+            new int[]{ 281, 283, 293 },
+
+            new int[]{ 307, 311, 313 },
+            new int[]{ 317, 331, 337 },
+            new int[]{ 347, 349, 353 },
+            new int[]{ 359, 367, 373 },
+            new int[]{ 379, 383, 389 },
+
+            new int[]{ 397, 401, 409 },
+            new int[]{ 419, 421, 431 },
+            new int[]{ 433, 439, 443 },
+            new int[]{ 449, 457, 461 },
+            new int[]{ 463, 467, 479 },
+
+            new int[]{ 487, 491, 499 },
+            new int[]{ 503, 509, 521 },
+            new int[]{ 523, 541, 547 },
+            new int[]{ 557, 563, 569 },
+            new int[]{ 571, 577, 587 },
+
+            new int[]{ 593, 599, 601 },
+            new int[]{ 607, 613, 617 },
+            new int[]{ 619, 631, 641 },
+            new int[]{ 643, 647, 653 },
+            new int[]{ 659, 661, 673 },
+
+            new int[]{ 677, 683, 691 },
+            new int[]{ 701, 709, 719 },
+            new int[]{ 727, 733, 739 },
+            new int[]{ 743, 751, 757 },
+            new int[]{ 761, 769, 773 },
+
+            new int[]{ 787, 797, 809 },
+            new int[]{ 811, 821, 823 },
+            new int[]{ 827, 829, 839 },
+            new int[]{ 853, 857, 859 },
+            new int[]{ 863, 877, 881 },
+
+            new int[]{ 883, 887, 907 },
+            new int[]{ 911, 919, 929 },
+            new int[]{ 937, 941, 947 },
+            new int[]{ 953, 967, 971 },
+            new int[]{ 977, 983, 991 },
+
+            new int[]{ 997, 1009, 1013 },
+            new int[]{ 1019, 1021, 1031 },
+            new int[]{ 1033, 1039, 1049 },
+            new int[]{ 1051, 1061, 1063 },
+            new int[]{ 1069, 1087, 1091 },
+
+            new int[]{ 1093, 1097, 1103 },
+            new int[]{ 1109, 1117, 1123 },
+            new int[]{ 1129, 1151, 1153 },
+            new int[]{ 1163, 1171, 1181 },
+            new int[]{ 1187, 1193, 1201 },
+
+            new int[]{ 1213, 1217, 1223 },
+            new int[]{ 1229, 1231, 1237 },
+            new int[]{ 1249, 1259, 1277 },
+            new int[]{ 1279, 1283, 1289 },
+        };
+
+        internal static readonly int[] primeProducts;
+
+        private const long IMASK = 0xFFFFFFFFL;
+        private const ulong UIMASK = 0xFFFFFFFFUL;
+
+        private static readonly int[] ZeroMagnitude = new int[0];
+        private static readonly byte[] ZeroEncoding = new byte[0];
+
+        private static readonly BigInteger[] SMALL_CONSTANTS = new BigInteger[17];
+        public static readonly BigInteger Zero;
+        public static readonly BigInteger One;
+        public static readonly BigInteger Two;
+        public static readonly BigInteger Three;
+        public static readonly BigInteger Ten;
+
+        //private readonly static byte[] BitCountTable =
+        //{
+        //    0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
+        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        //    1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        //    2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
+        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        //    3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
+        //    4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
+        //};
+
+        private readonly static byte[] BitLengthTable =
+        {
+            0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+        };
+
+        // TODO Parse radix-2 64 bits at a time and radix-8 63 bits at a time
+        private const int chunk2 = 1, chunk8 = 1, chunk10 = 19, chunk16 = 16;
+        private static readonly BigInteger radix2, radix2E, radix8, radix8E, radix10, radix10E, radix16, radix16E;
+
+        private static readonly Random RandomSource = new Random();
+
+        /*
+         * These are the threshold bit-lengths (of an exponent) where we increase the window size.
+         * They are calculated according to the expected savings in multiplications.
+         * Some squares will also be saved on average, but we offset these against the extra storage costs.
+         */
+        private static readonly int[] ExpWindowThresholds = { 7, 25, 81, 241, 673, 1793, 4609, Int32.MaxValue };
+
+        private const int BitsPerByte = 8;
+        private const int BitsPerInt = 32;
+        private const int BytesPerInt = 4;
+
+        static BigInteger()
+        {
+            Zero = new BigInteger(0, ZeroMagnitude, false);
+            Zero.nBits = 0; Zero.nBitLength = 0;
+
+            SMALL_CONSTANTS[0] = Zero;
+            for (uint i = 1; i < SMALL_CONSTANTS.Length; ++i)
+            {
+                SMALL_CONSTANTS[i] = CreateUValueOf(i);
+            }
+
+            One = SMALL_CONSTANTS[1];
+            Two = SMALL_CONSTANTS[2];
+            Three = SMALL_CONSTANTS[3];
+            Ten = SMALL_CONSTANTS[10];
+
+            radix2 = ValueOf(2);
+            radix2E = radix2.Pow(chunk2);
+
+            radix8 = ValueOf(8);
+            radix8E = radix8.Pow(chunk8);
+
+            radix10 = ValueOf(10);
+            radix10E = radix10.Pow(chunk10);
+
+            radix16 = ValueOf(16);
+            radix16E = radix16.Pow(chunk16);
+
+            primeProducts = new int[primeLists.Length];
+
+            for (int i = 0; i < primeLists.Length; ++i)
+            {
+                int[] primeList = primeLists[i];
+                int product = primeList[0];
+                for (int j = 1; j < primeList.Length; ++j)
+                {
+                    product *= primeList[j];
+                }
+                primeProducts[i] = product;
+            }
+        }
+
+        private int[] magnitude; // array of ints with [0] being the most significant
+        private int sign; // -1 means -ve; +1 means +ve; 0 means 0;
+        private int nBits = -1; // cache BitCount() value
+        private int nBitLength = -1; // cache BitLength() value
+        private int mQuote = 0; // -m^(-1) mod b, b = 2^32 (see Montgomery mult.), 0 when uninitialised
+
+        private static int GetByteLength(
+            int nBits)
+        {
+            return (nBits + BitsPerByte - 1) / BitsPerByte;
+        }
+
+        private BigInteger(
+            int		signum,
+            int[]	mag,
+            bool	checkMag)
+        {
+            if (checkMag)
+            {
+                int i = 0;
+                while (i < mag.Length && mag[i] == 0)
+                {
+                    ++i;
+                }
+
+                if (i == mag.Length)
+                {
+                    this.sign = 0;
+                    this.magnitude = ZeroMagnitude;
+                }
+                else
+                {
+                    this.sign = signum;
+
+                    if (i == 0)
+                    {
+                        this.magnitude = mag;
+                    }
+                    else
+                    {
+                        // strip leading 0 words
+                        this.magnitude = new int[mag.Length - i];
+                        Array.Copy(mag, i, this.magnitude, 0, this.magnitude.Length);
+                    }
+                }
+            }
+            else
+            {
+                this.sign = signum;
+                this.magnitude = mag;
+            }
+        }
+
+        public BigInteger(
+            string value)
+            : this(value, 10)
+        {
+        }
+
+        public BigInteger(
+            string	str,
+            int		radix)
+        {
+            if (str.Length == 0)
+                throw new FormatException("Zero length BigInteger");
+
+            NumberStyles style;
+            int chunk;
+            BigInteger r;
+            BigInteger rE;
+
+            switch (radix)
+            {
+                case 2:
+                    // Is there anyway to restrict to binary digits?
+                    style = NumberStyles.Integer;
+                    chunk = chunk2;
+                    r = radix2;
+                    rE = radix2E;
+                    break;
+                case 8:
+                    // Is there anyway to restrict to octal digits?
+                    style = NumberStyles.Integer;
+                    chunk = chunk8;
+                    r = radix8;
+                    rE = radix8E;
+                    break;
+                case 10:
+                    // This style seems to handle spaces and minus sign already (our processing redundant?)
+                    style = NumberStyles.Integer;
+                    chunk = chunk10;
+                    r = radix10;
+                    rE = radix10E;
+                    break;
+                case 16:
+                    // TODO Should this be HexNumber?
+                    style = NumberStyles.AllowHexSpecifier;
+                    chunk = chunk16;
+                    r = radix16;
+                    rE = radix16E;
+                    break;
+                default:
+                    throw new FormatException("Only bases 2, 8, 10, or 16 allowed");
+            }
+
+
+            int index = 0;
+            sign = 1;
+
+            if (str[0] == '-')
+            {
+                if (str.Length == 1)
+                    throw new FormatException("Zero length BigInteger");
+
+                sign = -1;
+                index = 1;
+            }
+
+            // strip leading zeros from the string str
+            while (index < str.Length && Int32.Parse(str[index].ToString(), style) == 0)
+            {
+                index++;
+            }
+
+            if (index >= str.Length)
+            {
+                // zero value - we're done
+                sign = 0;
+                magnitude = ZeroMagnitude;
+                return;
+            }
+
+            //////
+            // could we work out the max number of ints required to store
+            // str.Length digits in the given base, then allocate that
+            // storage in one hit?, then Generate the magnitude in one hit too?
+            //////
+
+            BigInteger b = Zero;
+
+
+            int next = index + chunk;
+
+            if (next <= str.Length)
+            {
+                do
+                {
+                    string s = str.Substring(index, chunk);
+                    ulong i = ulong.Parse(s, style);
+                    BigInteger bi = CreateUValueOf(i);
+
+                    switch (radix)
+                    {
+                        case 2:
+                            // TODO Need this because we are parsing in radix 10 above
+                            if (i >= 2)
+                                throw new FormatException("Bad character in radix 2 string: " + s);
+
+                            // TODO Parse 64 bits at a time
+                            b = b.ShiftLeft(1);
+                            break;
+                        case 8:
+                            // TODO Need this because we are parsing in radix 10 above
+                            if (i >= 8)
+                                throw new FormatException("Bad character in radix 8 string: " + s);
+
+                            // TODO Parse 63 bits at a time
+                            b = b.ShiftLeft(3);
+                            break;
+                        case 16:
+                            b = b.ShiftLeft(64);
+                            break;
+                        default:
+                            b = b.Multiply(rE);
+                            break;
+                    }
+
+                    b = b.Add(bi);
+
+                    index = next;
+                    next += chunk;
+                }
+                while (next <= str.Length);
+            }
+
+            if (index < str.Length)
+            {
+                string s = str.Substring(index);
+                ulong i = ulong.Parse(s, style);
+                BigInteger bi = CreateUValueOf(i);
+
+                if (b.sign > 0)
+                {
+                    if (radix == 2)
+                    {
+                        // NB: Can't reach here since we are parsing one char at a time
+                        Debug.Assert(false);
+
+                        // TODO Parse all bits at once
+//						b = b.ShiftLeft(s.Length);
+                    }
+                    else if (radix == 8)
+                    {
+                        // NB: Can't reach here since we are parsing one char at a time
+                        Debug.Assert(false);
+
+                        // TODO Parse all bits at once
+//						b = b.ShiftLeft(s.Length * 3);
+                    }
+                    else if (radix == 16)
+                    {
+                        b = b.ShiftLeft(s.Length << 2);
+                    }
+                    else
+                    {
+                        b = b.Multiply(r.Pow(s.Length));
+                    }
+
+                    b = b.Add(bi);
+                }
+                else
+                {
+                    b = bi;
+                }
+            }
+
+            // Note: This is the previous (slower) algorithm
+//			while (index < value.Length)
+//            {
+//				char c = value[index];
+//				string s = c.ToString();
+//				int i = Int32.Parse(s, style);
+//
+//                b = b.Multiply(r).Add(ValueOf(i));
+//                index++;
+//            }
+
+            magnitude = b.magnitude;
+        }
+
+        public BigInteger(
+            byte[] bytes)
+            : this(bytes, 0, bytes.Length)
+        {
+        }
+
+        public BigInteger(
+            byte[]	bytes,
+            int		offset,
+            int		length)
+        {
+            if (length == 0)
+                throw new FormatException("Zero length BigInteger");
+
+            // TODO Move this processing into MakeMagnitude (provide sign argument)
+            if ((sbyte)bytes[offset] < 0)
+            {
+                this.sign = -1;
+
+                int end = offset + length;
+
+                int iBval;
+                // strip leading sign bytes
+                for (iBval = offset; iBval < end && ((sbyte)bytes[iBval] == -1); iBval++)
+                {
+                }
+
+                if (iBval >= end)
+                {
+                    this.magnitude = One.magnitude;
+                }
+                else
+                {
+                    int numBytes = end - iBval;
+                    byte[] inverse = new byte[numBytes];
+
+                    int index = 0;
+                    while (index < numBytes)
+                    {
+                        inverse[index++] = (byte)~bytes[iBval++];
+                    }
+
+                    Debug.Assert(iBval == end);
+
+                    while (inverse[--index] == byte.MaxValue)
+                    {
+                        inverse[index] = byte.MinValue;
+                    }
+
+                    inverse[index]++;
+
+                    this.magnitude = MakeMagnitude(inverse, 0, inverse.Length);
+                }
+            }
+            else
+            {
+                // strip leading zero bytes and return magnitude bytes
+                this.magnitude = MakeMagnitude(bytes, offset, length);
+                this.sign = this.magnitude.Length > 0 ? 1 : 0;
+            }
+        }
+
+        private static int[] MakeMagnitude(
+            byte[]	bytes,
+            int		offset,
+            int		length)
+        {
+            int end = offset + length;
+
+            // strip leading zeros
+            int firstSignificant;
+            for (firstSignificant = offset; firstSignificant < end
+                && bytes[firstSignificant] == 0; firstSignificant++)
+            {
+            }
+
+            if (firstSignificant >= end)
+            {
+                return ZeroMagnitude;
+            }
+
+            int nInts = (end - firstSignificant + 3) / BytesPerInt;
+            int bCount = (end - firstSignificant) % BytesPerInt;
+            if (bCount == 0)
+            {
+                bCount = BytesPerInt;
+            }
+
+            if (nInts < 1)
+            {
+                return ZeroMagnitude;
+            }
+
+            int[] mag = new int[nInts];
+
+            int v = 0;
+            int magnitudeIndex = 0;
+            for (int i = firstSignificant; i < end; ++i)
+            {
+                v <<= 8;
+                v |= bytes[i] & 0xff;
+                bCount--;
+                if (bCount <= 0)
+                {
+                    mag[magnitudeIndex] = v;
+                    magnitudeIndex++;
+                    bCount = BytesPerInt;
+                    v = 0;
+                }
+            }
+
+            if (magnitudeIndex < mag.Length)
+            {
+                mag[magnitudeIndex] = v;
+            }
+
+            return mag;
+        }
+
+        public BigInteger(
+            int		sign,
+            byte[]	bytes)
+            : this(sign, bytes, 0, bytes.Length)
+        {
+        }
+
+        public BigInteger(
+            int		sign,
+            byte[]	bytes,
+            int		offset,
+            int		length)
+        {
+            if (sign < -1 || sign > 1)
+                throw new FormatException("Invalid sign value");
+
+            if (sign == 0)
+            {
+                this.sign = 0;
+                this.magnitude = ZeroMagnitude;
+            }
+            else
+            {
+                // copy bytes
+                this.magnitude = MakeMagnitude(bytes, offset, length);
+                this.sign = this.magnitude.Length < 1 ? 0 : sign;
+            }
+        }
+
+        public BigInteger(
+            int		sizeInBits,
+            Random	random)
+        {
+            if (sizeInBits < 0)
+                throw new ArgumentException("sizeInBits must be non-negative");
+
+            this.nBits = -1;
+            this.nBitLength = -1;
+
+            if (sizeInBits == 0)
+            {
+                this.sign = 0;
+                this.magnitude = ZeroMagnitude;
+                return;
+            }
+
+            int nBytes = GetByteLength(sizeInBits);
+            byte[] b = new byte[nBytes];
+            random.NextBytes(b);
+
+            // strip off any excess bits in the MSB
+            int xBits = BitsPerByte * nBytes - sizeInBits;
+            b[0] &= (byte)(255U >> xBits);
+
+            this.magnitude = MakeMagnitude(b, 0, b.Length);
+            this.sign = this.magnitude.Length < 1 ? 0 : 1;
+        }
+
+        public BigInteger(
+            int		bitLength,
+            int		certainty,
+            Random	random)
+        {
+            if (bitLength < 2)
+                throw new ArithmeticException("bitLength < 2");
+
+            this.sign = 1;
+            this.nBitLength = bitLength;
+
+            if (bitLength == 2)
+            {
+                this.magnitude = random.Next(2) == 0
+                    ?	Two.magnitude
+                    :	Three.magnitude;
+                return;
+            }
+             
+            int nBytes = GetByteLength(bitLength);
+            byte[] b = new byte[nBytes];
+
+            int xBits = BitsPerByte * nBytes - bitLength;
+            byte mask = (byte)(255U >> xBits);
+
+            for (;;)
+            {
+                random.NextBytes(b);
+
+                // strip off any excess bits in the MSB
+                b[0] &= mask;
+
+                // ensure the leading bit is 1 (to meet the strength requirement)
+                b[0] |= (byte)(1 << (7 - xBits));
+
+                // ensure the trailing bit is 1 (i.e. must be odd)
+                b[nBytes - 1] |= 1;
+
+                this.magnitude = MakeMagnitude(b, 0, b.Length);
+                this.nBits = -1;
+                this.mQuote = 0;
+
+                if (certainty < 1)
+                    break;
+
+                if (CheckProbablePrime(certainty, random))
+                    break;
+
+                if (bitLength > 32)
+                {
+                    for (int rep = 0; rep < 10000; ++rep)
+                    {
+                        int n = 33 + random.Next(bitLength - 2);
+                        this.magnitude[this.magnitude.Length - (n >> 5)] ^= (1 << (n & 31));
+                        this.magnitude[this.magnitude.Length - 1] ^= ((random.Next() + 1) << 1);
+                        this.mQuote = 0;
+
+                        if (CheckProbablePrime(certainty, random))
+                            return;
+                    }
+                }
+            }
+        }
+
+        public BigInteger Abs()
+        {
+            return sign >= 0 ? this : Negate();
+        }
+
+        /**
+         * return a = a + b - b preserved.
+         */
+        private static int[] AddMagnitudes(
+            int[] a,
+            int[] b)
+        {
+            int tI = a.Length - 1;
+            int vI = b.Length - 1;
+            long m = 0;
+
+            while (vI >= 0)
+            {
+                m += ((long)(uint)a[tI] + (long)(uint)b[vI--]);
+                a[tI--] = (int)m;
+                m = (long)((ulong)m >> 32);
+            }
+
+            if (m != 0)
+            {
+                while (tI >= 0 && ++a[tI--] == 0)
+                {
+                }
+            }
+
+            return a;
+        }
+
+        public BigInteger Add(
+            BigInteger value)
+        {
+            if (this.sign == 0)
+                return value;
+
+            if (this.sign != value.sign)
+            {
+                if (value.sign == 0)
+                    return this;
+
+                if (value.sign < 0)
+                    return Subtract(value.Negate());
+
+                return value.Subtract(Negate());
+            }
+
+            return AddToMagnitude(value.magnitude);
+        }
+
+        private BigInteger AddToMagnitude(
+            int[] magToAdd)
+        {
+            int[] big, small;
+            if (this.magnitude.Length < magToAdd.Length)
+            {
+                big = magToAdd;
+                small = this.magnitude;
+            }
+            else
+            {
+                big = this.magnitude;
+                small = magToAdd;
+            }
+
+            // Conservatively avoid over-allocation when no overflow possible
+            uint limit = uint.MaxValue;
+            if (big.Length == small.Length)
+                limit -= (uint) small[0];
+
+            bool possibleOverflow = (uint) big[0] >= limit;
+
+            int[] bigCopy;
+            if (possibleOverflow)
+            {
+                bigCopy = new int[big.Length + 1];
+                big.CopyTo(bigCopy, 1);
+            }
+            else
+            {
+                bigCopy = (int[]) big.Clone();
+            }
+
+            bigCopy = AddMagnitudes(bigCopy, small);
+
+            return new BigInteger(this.sign, bigCopy, possibleOverflow);
+        }
+
+        public BigInteger And(
+            BigInteger value)
+        {
+            if (this.sign == 0 || value.sign == 0)
+            {
+                return Zero;
+            }
+
+            int[] aMag = this.sign > 0
+                ? this.magnitude
+                : Add(One).magnitude;
+
+            int[] bMag = value.sign > 0
+                ? value.magnitude
+                : value.Add(One).magnitude;
+
+            bool resultNeg = sign < 0 && value.sign < 0;
+            int resultLength = System.Math.Max(aMag.Length, bMag.Length);
+            int[] resultMag = new int[resultLength];
+
+            int aStart = resultMag.Length - aMag.Length;
+            int bStart = resultMag.Length - bMag.Length;
+
+            for (int i = 0; i < resultMag.Length; ++i)
+            {
+                int aWord = i >= aStart ? aMag[i - aStart] : 0;
+                int bWord = i >= bStart ? bMag[i - bStart] : 0;
+
+                if (this.sign < 0)
+                {
+                    aWord = ~aWord;
+                }
+
+                if (value.sign < 0)
+                {
+                    bWord = ~bWord;
+                }
+
+                resultMag[i] = aWord & bWord;
+
+                if (resultNeg)
+                {
+                    resultMag[i] = ~resultMag[i];
+                }
+            }
+
+            BigInteger result = new BigInteger(1, resultMag, true);
+
+            // TODO Optimise this case
+            if (resultNeg)
+            {
+                result = result.Not();
+            }
+
+            return result;
+        }
+
+        public BigInteger AndNot(
+            BigInteger val)
+        {
+            return And(val.Not());
+        }
+
+        public int BitCount
+        {
+            get
+            {
+                if (nBits == -1)
+                {
+                    if (sign < 0)
+                    {
+                        // TODO Optimise this case
+                        nBits = Not().BitCount;
+                    }
+                    else
+                    {
+                        int sum = 0;
+                        for (int i = 0; i < magnitude.Length; ++i)
+                        {
+                            sum += BitCnt(magnitude[i]);
+                        }
+                        nBits = sum;
+                    }
+                }
+
+                return nBits;
+            }
+        }
+
+        public static int BitCnt(int i)
+        {
+            uint u = (uint)i;
+            u = u - ((u >> 1) & 0x55555555);
+            u = (u & 0x33333333) + ((u >> 2) & 0x33333333);
+            u = (u + (u >> 4)) & 0x0f0f0f0f;
+            u += (u >> 8);
+            u += (u >> 16);
+            u &= 0x3f;
+            return (int)u;
+        }
+
+        private static int CalcBitLength(int sign, int indx, int[]	mag)
+        {
+            for (;;)
+            {
+                if (indx >= mag.Length)
+                    return 0;
+
+                if (mag[indx] != 0)
+                    break;
+
+                ++indx;
+            }
+
+            // bit length for everything after the first int
+            int bitLength = 32 * ((mag.Length - indx) - 1);
+
+            // and determine bitlength of first int
+            int firstMag = mag[indx];
+            bitLength += BitLen(firstMag);
+
+            // Check for negative powers of two
+            if (sign < 0 && ((firstMag & -firstMag) == firstMag))
+            {
+                do
+                {
+                    if (++indx >= mag.Length)
+                    {
+                        --bitLength;
+                        break;
+                    }
+                }
+                while (mag[indx] == 0);
+            }
+
+            return bitLength;
+        }
+
+        public int BitLength
+        {
+            get
+            {
+                if (nBitLength == -1)
+                {
+                    nBitLength = sign == 0
+                        ? 0
+                        : CalcBitLength(sign, 0, magnitude);
+                }
+
+                return nBitLength;
+            }
+        }
+
+        //
+        // BitLen(value) is the number of bits in value.
+        //
+        private static int BitLen(int w)
+        {
+            uint v = (uint)w;
+            uint t = v >> 24;
+            if (t != 0)
+                return 24 + BitLengthTable[t];
+            t = v >> 16;
+            if (t != 0)
+                return 16 + BitLengthTable[t];
+            t = v >> 8;
+            if (t != 0)
+                return 8 + BitLengthTable[t];
+            return BitLengthTable[v];
+        }
+
+        private bool QuickPow2Check()
+        {
+            return sign > 0 && nBits == 1;
+        }
+
+        public int CompareTo(
+            object obj)
+        {
+            return CompareTo((BigInteger)obj);
+        }
+
+        /**
+         * unsigned comparison on two arrays - note the arrays may
+         * start with leading zeros.
+         */
+        private static int CompareTo(
+            int		xIndx,
+            int[]	x,
+            int		yIndx,
+            int[]	y)
+        {
+            while (xIndx != x.Length && x[xIndx] == 0)
+            {
+                xIndx++;
+            }
+
+            while (yIndx != y.Length && y[yIndx] == 0)
+            {
+                yIndx++;
+            }
+
+            return CompareNoLeadingZeroes(xIndx, x, yIndx, y);
+        }
+
+        private static int CompareNoLeadingZeroes(
+            int		xIndx,
+            int[]	x,
+            int		yIndx,
+            int[]	y)
+        {
+            int diff = (x.Length - y.Length) - (xIndx - yIndx);
+
+            if (diff != 0)
+            {
+                return diff < 0 ? -1 : 1;
+            }
+
+            // lengths of magnitudes the same, test the magnitude values
+
+            while (xIndx < x.Length)
+            {
+                uint v1 = (uint)x[xIndx++];
+                uint v2 = (uint)y[yIndx++];
+
+                if (v1 != v2)
+                    return v1 < v2 ? -1 : 1;
+            }
+
+            return 0;
+        }
+
+        public int CompareTo(
+            BigInteger value)
+        {
+            return sign < value.sign ? -1
+                : sign > value.sign ? 1
+                : sign == 0 ? 0
+                : sign * CompareNoLeadingZeroes(0, magnitude, 0, value.magnitude);
+        }
+
+        /**
+         * return z = x / y - done in place (z value preserved, x contains the
+         * remainder)
+         */
+        private int[] Divide(
+            int[]	x,
+            int[]	y)
+        {
+            int xStart = 0;
+            while (xStart < x.Length && x[xStart] == 0)
+            {
+                ++xStart;
+            }
+
+            int yStart = 0;
+            while (yStart < y.Length && y[yStart] == 0)
+            {
+                ++yStart;
+            }
+
+            Debug.Assert(yStart < y.Length);
+
+            int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+            int[] count;
+
+            if (xyCmp > 0)
+            {
+                int yBitLength = CalcBitLength(1, yStart, y);
+                int xBitLength = CalcBitLength(1, xStart, x);
+                int shift = xBitLength - yBitLength;
+
+                int[] iCount;
+                int iCountStart = 0;
+
+                int[] c;
+                int cStart = 0;
+                int cBitLength = yBitLength;
+                if (shift > 0)
+                {
+//					iCount = ShiftLeft(One.magnitude, shift);
+                    iCount = new int[(shift >> 5) + 1];
+                    iCount[0] = 1 << (shift % 32);
+
+                    c = ShiftLeft(y, shift);
+                    cBitLength += shift;
+                }
+                else
+                {
+                    iCount = new int[] { 1 };
+
+                    int len = y.Length - yStart;
+                    c = new int[len];
+                    Array.Copy(y, yStart, c, 0, len);
+                }
+
+                count = new int[iCount.Length];
+
+                for (;;)
+                {
+                    if (cBitLength < xBitLength
+                        || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
+                    {
+                        Subtract(xStart, x, cStart, c);
+                        AddMagnitudes(count, iCount);
+
+                        while (x[xStart] == 0)
+                        {
+                            if (++xStart == x.Length)
+                                return count;
+                        }
+
+                        //xBitLength = CalcBitLength(xStart, x);
+                        xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
+
+                        if (xBitLength <= yBitLength)
+                        {
+                            if (xBitLength < yBitLength)
+                                return count;
+
+                            xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+
+                            if (xyCmp <= 0)
+                                break;
+                        }
+                    }
+
+                    shift = cBitLength - xBitLength;
+
+                    // NB: The case where c[cStart] is 1-bit is harmless
+                    if (shift == 1)
+                    {
+                        uint firstC = (uint) c[cStart] >> 1;
+                        uint firstX = (uint) x[xStart];
+                        if (firstC > firstX)
+                            ++shift;
+                    }
+
+                    if (shift < 2)
+                    {
+                        ShiftRightOneInPlace(cStart, c);
+                        --cBitLength;
+                        ShiftRightOneInPlace(iCountStart, iCount);
+                    }
+                    else
+                    {
+                        ShiftRightInPlace(cStart, c, shift);
+                        cBitLength -= shift;
+                        ShiftRightInPlace(iCountStart, iCount, shift);
+                    }
+
+                    //cStart = c.Length - ((cBitLength + 31) / 32);
+                    while (c[cStart] == 0)
+                    {
+                        ++cStart;
+                    }
+
+                    while (iCount[iCountStart] == 0)
+                    {
+                        ++iCountStart;
+                    }
+                }
+            }
+            else
+            {
+                count = new int[1];
+            }
+
+            if (xyCmp == 0)
+            {
+                AddMagnitudes(count, One.magnitude);
+                Array.Clear(x, xStart, x.Length - xStart);
+            }
+
+            return count;
+        }
+
+        public BigInteger Divide(
+            BigInteger val)
+        {
+            if (val.sign == 0)
+                throw new ArithmeticException("Division by zero error");
+
+            if (sign == 0)
+                return Zero;
+
+            if (val.QuickPow2Check()) // val is power of two
+            {
+                BigInteger result = this.Abs().ShiftRight(val.Abs().BitLength - 1);
+                return val.sign == this.sign ? result : result.Negate();
+            }
+
+            int[] mag = (int[]) this.magnitude.Clone();
+
+            return new BigInteger(this.sign * val.sign, Divide(mag, val.magnitude), true);
+        }
+
+        public BigInteger[] DivideAndRemainder(
+            BigInteger val)
+        {
+            if (val.sign == 0)
+                throw new ArithmeticException("Division by zero error");
+
+            BigInteger[] biggies = new BigInteger[2];
+
+            if (sign == 0)
+            {
+                biggies[0] = Zero;
+                biggies[1] = Zero;
+            }
+            else if (val.QuickPow2Check()) // val is power of two
+            {
+                int e = val.Abs().BitLength - 1;
+                BigInteger quotient = this.Abs().ShiftRight(e);
+                int[] remainder = this.LastNBits(e);
+
+                biggies[0] = val.sign == this.sign ? quotient : quotient.Negate();
+                biggies[1] = new BigInteger(this.sign, remainder, true);
+            }
+            else
+            {
+                int[] remainder = (int[]) this.magnitude.Clone();
+                int[] quotient = Divide(remainder, val.magnitude);
+
+                biggies[0] = new BigInteger(this.sign * val.sign, quotient, true);
+                biggies[1] = new BigInteger(this.sign, remainder, true);
+            }
+
+            return biggies;
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            BigInteger biggie = obj as BigInteger;
+            if (biggie == null)
+                return false;
+
+            return sign == biggie.sign && IsEqualMagnitude(biggie);
+        }
+
+        private bool IsEqualMagnitude(BigInteger x)
+        {
+            //int[] xMag = x.magnitude;
+            if (magnitude.Length != x.magnitude.Length)
+                return false;
+            for (int i = 0; i < magnitude.Length; i++)
+            {
+                if (magnitude[i] != x.magnitude[i])
+                    return false;
+            }
+            return true;
+        }
+
+        public BigInteger Gcd(
+            BigInteger value)
+        {
+            if (value.sign == 0)
+                return Abs();
+
+            if (sign == 0)
+                return value.Abs();
+
+            BigInteger r;
+            BigInteger u = this;
+            BigInteger v = value;
+
+            while (v.sign != 0)
+            {
+                r = u.Mod(v);
+                u = v;
+                v = r;
+            }
+
+            return u;
+        }
+
+        public override int GetHashCode()
+        {
+            int hc = magnitude.Length;
+            if (magnitude.Length > 0)
+            {
+                hc ^= magnitude[0];
+
+                if (magnitude.Length > 1)
+                {
+                    hc ^= magnitude[magnitude.Length - 1];
+                }
+            }
+
+            return sign < 0 ? ~hc : hc;
+        }
+
+        // TODO Make public?
+        private BigInteger Inc()
+        {
+            if (this.sign == 0)
+                return One;
+
+            if (this.sign < 0)
+                return new BigInteger(-1, doSubBigLil(this.magnitude, One.magnitude), true);
+
+            return AddToMagnitude(One.magnitude);
+        }
+
+        public int IntValue
+        {
+            get
+            {
+                if (sign == 0)
+                    return 0;
+
+                int n = magnitude.Length;
+
+                int v = magnitude[n - 1];
+
+                return sign < 0 ? -v : v;
+            }
+        }
+
+        /**
+         * return whether or not a BigInteger is probably prime with a
+         * probability of 1 - (1/2)**certainty.
+         * <p>From Knuth Vol 2, pg 395.</p>
+         */
+        public bool IsProbablePrime(
+            int certainty)
+        {
+            if (certainty <= 0)
+                return true;
+
+            BigInteger n = Abs();
+
+            if (!n.TestBit(0))
+                return n.Equals(Two);
+
+            if (n.Equals(One))
+                return false;
+
+            return n.CheckProbablePrime(certainty, RandomSource);
+        }
+
+        private bool CheckProbablePrime(
+            int		certainty,
+            Random	random)
+        {
+            Debug.Assert(certainty > 0);
+            Debug.Assert(CompareTo(Two) > 0);
+            Debug.Assert(TestBit(0));
+
+
+            // Try to reduce the penalty for really small numbers
+            int numLists = System.Math.Min(BitLength - 1, primeLists.Length);
+
+            for (int i = 0; i < numLists; ++i)
+            {
+                int test = Remainder(primeProducts[i]);
+
+                int[] primeList = primeLists[i];
+                for (int j = 0; j < primeList.Length; ++j)
+                {
+                    int prime = primeList[j];
+                    int qRem = test % prime;
+                    if (qRem == 0)
+                    {
+                        // We may find small numbers in the list
+                        return BitLength < 16 && IntValue == prime;
+                    }
+                }
+            }
+
+
+            // TODO Special case for < 10^16 (RabinMiller fixed list)
+//			if (BitLength < 30)
+//			{
+//				RabinMiller against 2, 3, 5, 7, 11, 13, 23 is sufficient
+//			}
+
+
+            // TODO Is it worth trying to create a hybrid of these two?
+            return RabinMillerTest(certainty, random);
+//			return SolovayStrassenTest(certainty, random);
+
+//			bool rbTest = RabinMillerTest(certainty, random);
+//			bool ssTest = SolovayStrassenTest(certainty, random);
+//
+//			Debug.Assert(rbTest == ssTest);
+//
+//			return rbTest;
+        }
+
+        public bool RabinMillerTest(int certainty, Random random)
+        {
+            Debug.Assert(certainty > 0);
+            Debug.Assert(BitLength > 2);
+            Debug.Assert(TestBit(0));
+
+            // let n = 1 + d . 2^s
+            BigInteger n = this;
+            int s = n.GetLowestSetBitMaskFirst(-1 << 1);
+            Debug.Assert(s >= 1);
+            BigInteger r = n.ShiftRight(s);
+
+            // NOTE: Avoid conversion to/from Montgomery form and check for R/-R as result instead
+
+            BigInteger montRadix = One.ShiftLeft(32 * n.magnitude.Length).Remainder(n);
+            BigInteger minusMontRadix = n.Subtract(montRadix);
+
+            do
+            {
+                BigInteger a;
+                do
+                {
+                    a = new BigInteger(n.BitLength, random);
+                }
+                while (a.sign == 0 || a.CompareTo(n) >= 0
+                    || a.IsEqualMagnitude(montRadix) || a.IsEqualMagnitude(minusMontRadix));
+
+                BigInteger y = ModPowMonty(a, r, n, false);
+
+                if (!y.Equals(montRadix))
+                {
+                    int j = 0;
+                    while (!y.Equals(minusMontRadix))
+                    {
+                        if (++j == s)
+                            return false;
+
+                        y = ModPowMonty(y, Two, n, false);
+
+                        if (y.Equals(montRadix))
+                            return false;
+                    }
+                }
+
+                certainty -= 2; // composites pass for only 1/4 possible 'a'
+            }
+            while (certainty > 0);
+
+            return true;
+        }
+
+//		private bool SolovayStrassenTest(
+//			int		certainty,
+//			Random	random)
+//		{
+//			Debug.Assert(certainty > 0);
+//			Debug.Assert(CompareTo(Two) > 0);
+//			Debug.Assert(TestBit(0));
+//
+//			BigInteger n = this;
+//			BigInteger nMinusOne = n.Subtract(One);
+//			BigInteger e = nMinusOne.ShiftRight(1);
+//
+//			do
+//			{
+//				BigInteger a;
+//				do
+//				{
+//					a = new BigInteger(nBitLength, random);
+//				}
+//				// NB: Spec says 0 < x < n, but 1 is trivial
+//				while (a.CompareTo(One) <= 0 || a.CompareTo(n) >= 0);
+//
+//
+//				// TODO Check this is redundant given the way Jacobi() works?
+////				if (!a.Gcd(n).Equals(One))
+////					return false;
+//
+//				int x = Jacobi(a, n);
+//
+//				if (x == 0)
+//					return false;
+//
+//				BigInteger check = a.ModPow(e, n);
+//
+//				if (x == 1 && !check.Equals(One))
+//					return false;
+//
+//				if (x == -1 && !check.Equals(nMinusOne))
+//					return false;
+//
+//				--certainty;
+//			}
+//			while (certainty > 0);
+//
+//			return true;
+//		}
+//
+//		private static int Jacobi(
+//			BigInteger	a,
+//			BigInteger	b)
+//		{
+//			Debug.Assert(a.sign >= 0);
+//			Debug.Assert(b.sign > 0);
+//			Debug.Assert(b.TestBit(0));
+//			Debug.Assert(a.CompareTo(b) < 0);
+//
+//			int totalS = 1;
+//			for (;;)
+//			{
+//				if (a.sign == 0)
+//					return 0;
+//
+//				if (a.Equals(One))
+//					break;
+//
+//				int e = a.GetLowestSetBit();
+//
+//				int bLsw = b.magnitude[b.magnitude.Length - 1];
+//				if ((e & 1) != 0 && ((bLsw & 7) == 3 || (bLsw & 7) == 5))
+//					totalS = -totalS;
+//
+//				// TODO Confirm this is faster than later a1.Equals(One) test
+//				if (a.BitLength == e + 1)
+//					break;
+//				BigInteger a1 = a.ShiftRight(e);
+////				if (a1.Equals(One))
+////					break;
+//
+//				int a1Lsw = a1.magnitude[a1.magnitude.Length - 1];
+//				if ((bLsw & 3) == 3 && (a1Lsw & 3) == 3)
+//					totalS = -totalS;
+//
+////				a = b.Mod(a1);
+//				a = b.Remainder(a1);
+//				b = a1;
+//			}
+//			return totalS;
+//		}
+
+        public long LongValue
+        {
+            get
+            {
+                if (sign == 0)
+                    return 0;
+
+                int n = magnitude.Length;
+
+                long v = magnitude[n - 1] & IMASK;
+                if (n > 1)
+                {
+                    v |= (magnitude[n - 2] & IMASK) << 32;
+                }
+
+                return sign < 0 ? -v : v;
+            }
+        }
+
+        public BigInteger Max(
+            BigInteger value)
+        {
+            return CompareTo(value) > 0 ? this : value;
+        }
+
+        public BigInteger Min(
+            BigInteger value)
+        {
+            return CompareTo(value) < 0 ? this : value;
+        }
+
+        public BigInteger Mod(
+            BigInteger m)
+        {
+            if (m.sign < 1)
+                throw new ArithmeticException("Modulus must be positive");
+
+            BigInteger biggie = Remainder(m);
+
+            return (biggie.sign >= 0 ? biggie : biggie.Add(m));
+        }
+
+        public BigInteger ModInverse(
+            BigInteger m)
+        {
+            if (m.sign < 1)
+                throw new ArithmeticException("Modulus must be positive");
+
+            // TODO Too slow at the moment
+//			// "Fast Key Exchange with Elliptic Curve Systems" R.Schoeppel
+//			if (m.TestBit(0))
+//			{
+//				//The Almost Inverse Algorithm
+//				int k = 0;
+//				BigInteger B = One, C = Zero, F = this, G = m, tmp;
+//
+//				for (;;)
+//				{
+//					// While F is even, do F=F/u, C=C*u, k=k+1.
+//					int zeroes = F.GetLowestSetBit();
+//					if (zeroes > 0)
+//					{
+//						F = F.ShiftRight(zeroes);
+//						C = C.ShiftLeft(zeroes);
+//						k += zeroes;
+//					}
+//
+//					// If F = 1, then return B,k.
+//					if (F.Equals(One))
+//					{
+//						BigInteger half = m.Add(One).ShiftRight(1);
+//						BigInteger halfK = half.ModPow(BigInteger.ValueOf(k), m);
+//						return B.Multiply(halfK).Mod(m);
+//					}
+//
+//					if (F.CompareTo(G) < 0)
+//					{
+//						tmp = G; G = F; F = tmp;
+//						tmp = B; B = C; C = tmp;
+//					}
+//
+//					F = F.Add(G);
+//					B = B.Add(C);
+//				}
+//			}
+
+            if (m.QuickPow2Check())
+            {
+                return ModInversePow2(m);
+            }
+
+            BigInteger d = this.Remainder(m);
+            BigInteger x;
+            BigInteger gcd = ExtEuclid(d, m, out x);
+
+            if (!gcd.Equals(One))
+                throw new ArithmeticException("Numbers not relatively prime.");
+
+            if (x.sign < 0)
+            {
+                x = x.Add(m);
+            }
+
+            return x;
+        }
+
+        private BigInteger ModInversePow2(BigInteger m)
+        {
+            Debug.Assert(m.SignValue > 0);
+            Debug.Assert(m.BitCount == 1);
+
+            if (!TestBit(0))
+            {
+                throw new ArithmeticException("Numbers not relatively prime.");
+            }
+
+            int pow = m.BitLength - 1;
+
+            long inv64 = ModInverse64(LongValue);
+            if (pow < 64)
+            {
+                inv64 &= ((1L << pow) - 1);
+            }
+
+            BigInteger x = BigInteger.ValueOf(inv64);
+
+            if (pow > 64)
+            {
+                BigInteger d = this.Remainder(m);
+                int bitsCorrect = 64;
+
+                do
+                {
+                    BigInteger t = x.Multiply(d).Remainder(m);
+                    x = x.Multiply(Two.Subtract(t)).Remainder(m);
+                    bitsCorrect <<= 1;
+                }
+                while (bitsCorrect < pow);
+            }
+
+            if (x.sign < 0)
+            {
+                x = x.Add(m);
+            }
+
+            return x;
+        }
+
+        private static int ModInverse32(int d)
+        {
+            // Newton's method with initial estimate "correct to 4 bits"
+            Debug.Assert((d & 1) != 0);
+            int x = d + (((d + 1) & 4) << 1);   // d.x == 1 mod 2**4
+            Debug.Assert(((d * x) & 15) == 1);
+            x *= 2 - d * x;                     // d.x == 1 mod 2**8
+            x *= 2 - d * x;                     // d.x == 1 mod 2**16
+            x *= 2 - d * x;                     // d.x == 1 mod 2**32
+            Debug.Assert(d * x == 1);
+            return x;
+        }
+
+        private static long ModInverse64(long d)
+        {
+            // Newton's method with initial estimate "correct to 4 bits"
+            Debug.Assert((d & 1L) != 0);
+            long x = d + (((d + 1L) & 4L) << 1);    // d.x == 1 mod 2**4
+            Debug.Assert(((d * x) & 15L) == 1L);
+            x *= 2 - d * x;                         // d.x == 1 mod 2**8
+            x *= 2 - d * x;                         // d.x == 1 mod 2**16
+            x *= 2 - d * x;                         // d.x == 1 mod 2**32
+            x *= 2 - d * x;                         // d.x == 1 mod 2**64
+            Debug.Assert(d * x == 1L);
+            return x;
+        }
+
+        /**
+         * Calculate the numbers u1, u2, and u3 such that:
+         *
+         * u1 * a + u2 * b = u3
+         *
+         * where u3 is the greatest common divider of a and b.
+         * a and b using the extended Euclid algorithm (refer p. 323
+         * of The Art of Computer Programming vol 2, 2nd ed).
+         * This also seems to have the side effect of calculating
+         * some form of multiplicative inverse.
+         *
+         * @param a    First number to calculate gcd for
+         * @param b    Second number to calculate gcd for
+         * @param u1Out      the return object for the u1 value
+         * @return     The greatest common divisor of a and b
+         */
+        private static BigInteger ExtEuclid(BigInteger a, BigInteger b, out BigInteger u1Out)
+        {
+            BigInteger u1 = One, v1 = Zero;
+            BigInteger u3 = a, v3 = b;
+
+            if (v3.sign > 0)
+            {
+                for (;;)
+                {
+                    BigInteger[] q = u3.DivideAndRemainder(v3);
+                    u3 = v3;
+                    v3 = q[1];
+
+                    BigInteger oldU1 = u1;
+                    u1 = v1;
+
+                    if (v3.sign <= 0)
+                        break;
+
+                    v1 = oldU1.Subtract(v1.Multiply(q[0]));
+                }
+            }
+
+            u1Out = u1;
+
+            return u3;
+        }
+
+        private static void ZeroOut(
+            int[] x)
+        {
+            Array.Clear(x, 0, x.Length);
+        }
+
+        public BigInteger ModPow(BigInteger e, BigInteger m)
+        {
+            if (m.sign < 1)
+                throw new ArithmeticException("Modulus must be positive");
+
+            if (m.Equals(One))
+                return Zero;
+
+            if (e.sign == 0)
+                return One;
+
+            if (sign == 0)
+                return Zero;
+
+            bool negExp = e.sign < 0;
+            if (negExp)
+                e = e.Negate();
+
+            BigInteger result = this.Mod(m);
+            if (!e.Equals(One))
+            {
+                if ((m.magnitude[m.magnitude.Length - 1] & 1) == 0)
+                {
+                    result = ModPowBarrett(result, e, m);
+                }
+                else
+                {
+                    result = ModPowMonty(result, e, m, true);
+                }
+            }
+
+            if (negExp)
+                result = result.ModInverse(m);
+
+            return result;
+        }
+
+        private static BigInteger ModPowBarrett(BigInteger b, BigInteger e, BigInteger m)
+        {
+            int k = m.magnitude.Length;
+            BigInteger mr = One.ShiftLeft((k + 1) << 5);
+            BigInteger yu = One.ShiftLeft(k << 6).Divide(m);
+
+            // Sliding window from MSW to LSW
+            int extraBits = 0, expLength = e.BitLength;
+            while (expLength > ExpWindowThresholds[extraBits])
+            {
+                ++extraBits;
+            }
+
+            int numPowers = 1 << extraBits;
+            BigInteger[] oddPowers = new BigInteger[numPowers];
+            oddPowers[0] = b;
+
+            BigInteger b2 = ReduceBarrett(b.Square(), m, mr, yu);
+
+            for (int i = 1; i < numPowers; ++i)
+            {
+                oddPowers[i] = ReduceBarrett(oddPowers[i - 1].Multiply(b2), m, mr, yu);
+            }
+
+            int[] windowList = GetWindowList(e.magnitude, extraBits);
+            Debug.Assert(windowList.Length > 0);
+
+            int window = windowList[0];
+            int mult = window & 0xFF, lastZeroes = window >> 8;
+
+            BigInteger y;
+            if (mult == 1)
+            {
+                y = b2;
+                --lastZeroes;
+            }
+            else
+            {
+                y = oddPowers[mult >> 1];
+            }
+
+            int windowPos = 1;
+            while ((window = windowList[windowPos++]) != -1)
+            {
+                mult = window & 0xFF;
+
+                int bits = lastZeroes + BitLengthTable[mult];
+                for (int j = 0; j < bits; ++j)
+                {
+                    y = ReduceBarrett(y.Square(), m, mr, yu);
+                }
+
+                y = ReduceBarrett(y.Multiply(oddPowers[mult >> 1]), m, mr, yu);
+
+                lastZeroes = window >> 8;
+            }
+
+            for (int i = 0; i < lastZeroes; ++i)
+            {
+                y = ReduceBarrett(y.Square(), m, mr, yu);
+            }
+
+            return y;
+        }
+
+        private static BigInteger ReduceBarrett(BigInteger x, BigInteger m, BigInteger mr, BigInteger yu)
+        {
+            int xLen = x.BitLength, mLen = m.BitLength;
+            if (xLen < mLen)
+                return x;
+
+            if (xLen - mLen > 1)
+            {
+                int k = m.magnitude.Length;
+
+                BigInteger q1 = x.DivideWords(k - 1);
+                BigInteger q2 = q1.Multiply(yu); // TODO Only need partial multiplication here
+                BigInteger q3 = q2.DivideWords(k + 1);
+
+                BigInteger r1 = x.RemainderWords(k + 1);
+                BigInteger r2 = q3.Multiply(m); // TODO Only need partial multiplication here
+                BigInteger r3 = r2.RemainderWords(k + 1);
+
+                x = r1.Subtract(r3);
+                if (x.sign < 0)
+                {
+                    x = x.Add(mr);
+                }
+            }
+
+            while (x.CompareTo(m) >= 0)
+            {
+                x = x.Subtract(m);
+            }
+
+            return x;
+        }
+
+        private static BigInteger ModPowMonty(BigInteger b, BigInteger e, BigInteger m, bool convert)
+        {
+            int n = m.magnitude.Length;
+            int powR = 32 * n;
+            bool smallMontyModulus = m.BitLength + 2 <= powR;
+            uint mDash = (uint)m.GetMQuote();
+
+            // tmp = this * R mod m
+            if (convert)
+            {
+                b = b.ShiftLeft(powR).Remainder(m);
+            }
+
+            int[] yAccum = new int[n + 1];
+
+            int[] zVal = b.magnitude;
+            Debug.Assert(zVal.Length <= n);
+            if (zVal.Length < n)
+            {
+                int[] tmp = new int[n];
+                zVal.CopyTo(tmp, n - zVal.Length);
+                zVal = tmp;
+            }
+
+            // Sliding window from MSW to LSW
+
+            int extraBits = 0;
+
+            // Filter the common case of small RSA exponents with few bits set
+            if (e.magnitude.Length > 1 || e.BitCount > 2)
+            {
+                int expLength = e.BitLength;
+                while (expLength > ExpWindowThresholds[extraBits])
+                {
+                    ++extraBits;
+                }
+            }
+
+            int numPowers = 1 << extraBits;
+            int[][] oddPowers = new int[numPowers][];
+            oddPowers[0] = zVal;
+
+            int[] zSquared = Arrays.Clone(zVal);
+            SquareMonty(yAccum, zSquared, m.magnitude, mDash, smallMontyModulus);
+
+            for (int i = 1; i < numPowers; ++i)
+            {
+                oddPowers[i] = Arrays.Clone(oddPowers[i - 1]);
+                MultiplyMonty(yAccum, oddPowers[i], zSquared, m.magnitude, mDash, smallMontyModulus);
+            }
+
+            int[] windowList = GetWindowList(e.magnitude, extraBits);
+            Debug.Assert(windowList.Length > 1);
+
+            int window = windowList[0];
+            int mult = window & 0xFF, lastZeroes = window >> 8;
+
+            int[] yVal;
+            if (mult == 1)
+            {
+                yVal = zSquared;
+                --lastZeroes;
+            }
+            else
+            {
+                yVal = Arrays.Clone(oddPowers[mult >> 1]);
+            }
+
+            int windowPos = 1;
+            while ((window = windowList[windowPos++]) != -1)
+            {
+                mult = window & 0xFF;
+
+                int bits = lastZeroes + BitLengthTable[mult];
+                for (int j = 0; j < bits; ++j)
+                {
+                    SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
+                }
+
+                MultiplyMonty(yAccum, yVal, oddPowers[mult >> 1], m.magnitude, mDash, smallMontyModulus);
+
+                lastZeroes = window >> 8;
+            }
+
+            for (int i = 0; i < lastZeroes; ++i)
+            {
+                SquareMonty(yAccum, yVal, m.magnitude, mDash, smallMontyModulus);
+            }
+
+            if (convert)
+            {
+                // Return y * R^(-1) mod m
+                MontgomeryReduce(yVal, m.magnitude, mDash);
+            }
+            else if (smallMontyModulus && CompareTo(0, yVal, 0, m.magnitude) >= 0)
+            {
+                Subtract(0, yVal, 0, m.magnitude);
+            }
+
+            return new BigInteger(1, yVal, true);
+        }
+
+        private static int[] GetWindowList(int[] mag, int extraBits)
+        {
+            int v = mag[0];
+            Debug.Assert(v != 0);
+
+            int leadingBits = BitLen(v);
+
+            int resultSize = (((mag.Length - 1) << 5) + leadingBits) / (1 + extraBits) + 2;
+            int[] result = new int[resultSize];
+            int resultPos = 0;
+
+            int bitPos = 33 - leadingBits;
+            v <<= bitPos;
+
+            int mult = 1, multLimit = 1 << extraBits;
+            int zeroes = 0;
+
+            int i = 0;
+            for (; ; )
+            {
+                for (; bitPos < 32; ++bitPos)
+                {
+                    if (mult < multLimit)
+                    {
+                        mult = (mult << 1) | (int)((uint)v >> 31);
+                    }
+                    else if (v < 0)
+                    {
+                        result[resultPos++] = CreateWindowEntry(mult, zeroes);
+                        mult = 1;
+                        zeroes = 0;
+                    }
+                    else
+                    {
+                        ++zeroes;
+                    }
+
+                    v <<= 1;
+                }
+
+                if (++i == mag.Length)
+                {
+                    result[resultPos++] = CreateWindowEntry(mult, zeroes);
+                    break;
+                }
+
+                v = mag[i];
+                bitPos = 0;
+            }
+
+            result[resultPos] = -1;
+            return result;
+        }
+
+        private static int CreateWindowEntry(int mult, int zeroes)
+        {
+            while ((mult & 1) == 0)
+            {
+                mult >>= 1;
+                ++zeroes;
+            }
+
+            return mult | (zeroes << 8);
+        }
+
+        /**
+         * return w with w = x * x - w is assumed to have enough space.
+         */
+        private static int[] Square(
+            int[]	w,
+            int[]	x)
+        {
+            // Note: this method allows w to be only (2 * x.Length - 1) words if result will fit
+//			if (w.Length != 2 * x.Length)
+//				throw new ArgumentException("no I don't think so...");
+
+            ulong c;
+
+            int wBase = w.Length - 1;
+
+            for (int i = x.Length - 1; i > 0; --i)
+            {
+                ulong v = (uint)x[i];
+
+                c = v * v + (uint)w[wBase];
+                w[wBase] = (int)c;
+                c >>= 32;
+
+                for (int j = i - 1; j >= 0; --j)
+                {
+                    ulong prod = v * (uint)x[j];
+
+                    c += ((uint)w[--wBase] & UIMASK) + ((uint)prod << 1);
+                    w[wBase] = (int)c;
+                    c = (c >> 32) + (prod >> 31);
+                }
+
+                c += (uint)w[--wBase];
+                w[wBase] = (int)c;
+
+                if (--wBase >= 0)
+                {
+                    w[wBase] = (int)(c >> 32);
+                }
+                else
+                {
+                    Debug.Assert((c >> 32) == 0);
+                }
+
+                wBase += i;
+            }
+
+            c = (uint)x[0];
+
+            c = c * c + (uint)w[wBase];
+            w[wBase] = (int)c;
+
+            if (--wBase >= 0)
+            {
+                w[wBase] += (int)(c >> 32);
+            }
+            else
+            {
+                Debug.Assert((c >> 32) == 0);
+            }
+
+            return w;
+        }
+
+        /**
+         * return x with x = y * z - x is assumed to have enough space.
+         */
+        private static int[] Multiply(int[]	x, int[] y, int[] z)
+        {
+            int i = z.Length;
+
+            if (i < 1)
+                return x;
+
+            int xBase = x.Length - y.Length;
+
+            do
+            {
+                long a = z[--i] & IMASK;
+                long val = 0;
+
+                if (a != 0)
+                {
+                    for (int j = y.Length - 1; j >= 0; j--)
+                    {
+                        val += a * (y[j] & IMASK) + (x[xBase + j] & IMASK);
+    
+                        x[xBase + j] = (int)val;
+    
+                        val = (long)((ulong)val >> 32);
+                    }
+                }
+
+                --xBase;
+
+                if (xBase >= 0)
+                {
+                    x[xBase] = (int)val;
+                }
+                else
+                {
+                    Debug.Assert(val == 0);
+                }
+            }
+            while (i > 0);
+
+            return x;
+        }
+
+        /**
+         * Calculate mQuote = -m^(-1) mod b with b = 2^32 (32 = word size)
+         */
+        private int GetMQuote()
+        {
+            if (mQuote != 0)
+            {
+                return mQuote; // already calculated
+            }
+
+            Debug.Assert(this.sign > 0);
+
+            int d = -magnitude[magnitude.Length - 1];
+
+            Debug.Assert((d & 1) != 0);
+
+            return mQuote = ModInverse32(d);
+        }
+
+        private static void MontgomeryReduce(int[] x, int[] m, uint mDash) // mDash = -m^(-1) mod b
+        {
+            // NOTE: Not a general purpose reduction (which would allow x up to twice the bitlength of m)
+            Debug.Assert(x.Length == m.Length);
+
+            int n = m.Length;
+
+            for (int i = n - 1; i >= 0; --i)
+            {
+                uint x0 = (uint)x[n - 1];
+                ulong t = x0 * mDash;
+
+                ulong carry = t * (uint)m[n - 1] + x0;
+                Debug.Assert((uint)carry == 0);
+                carry >>= 32;
+
+                for (int j = n - 2; j >= 0; --j)
+                {
+                    carry += t * (uint)m[j] + (uint)x[j];
+                    x[j + 1] = (int)carry;
+                    carry >>= 32;
+                }
+
+                x[0] = (int)carry;
+                Debug.Assert(carry >> 32 == 0);
+            }
+
+            if (CompareTo(0, x, 0, m) >= 0)
+            {
+                Subtract(0, x, 0, m);
+            }
+        }
+
+        /**
+         * Montgomery multiplication: a = x * y * R^(-1) mod m
+         * <br/>
+         * Based algorithm 14.36 of Handbook of Applied Cryptography.
+         * <br/>
+         * <li> m, x, y should have length n </li>
+         * <li> a should have length (n + 1) </li>
+         * <li> b = 2^32, R = b^n </li>
+         * <br/>
+         * The result is put in x
+         * <br/>
+         * NOTE: the indices of x, y, m, a different in HAC and in Java
+         */
+        private static void MultiplyMonty(int[]	a, int[] x, int[] y, int[] m, uint mDash, bool smallMontyModulus)
+            // mDash = -m^(-1) mod b
+        {
+            int n = m.Length;
+
+            if (n == 1)
+            {
+                x[0] = (int)MultiplyMontyNIsOne((uint)x[0], (uint)y[0], (uint)m[0], mDash);
+                return;
+            }
+
+            uint y0 = (uint)y[n - 1];
+            int aMax;
+
+            {
+                ulong xi = (uint)x[n - 1];
+
+                ulong carry = xi * y0;
+                ulong t = (uint)carry * mDash;
+
+                ulong prod2 = t * (uint)m[n - 1];
+                carry += (uint)prod2;
+                Debug.Assert((uint)carry == 0);
+                carry = (carry >> 32) + (prod2 >> 32);
+
+                for (int j = n - 2; j >= 0; --j)
+                {
+                    ulong prod1 = xi * (uint)y[j];
+                    prod2 = t * (uint)m[j];
+
+                    carry += (prod1 & UIMASK) + (uint)prod2;
+                    a[j + 2] = (int)carry;
+                    carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
+                }
+
+                a[1] = (int)carry;
+                aMax = (int)(carry >> 32);
+            }
+
+            for (int i = n - 2; i >= 0; --i)
+            {
+                uint a0 = (uint)a[n];
+                ulong xi = (uint)x[i];
+
+                ulong prod1 = xi * y0;
+                ulong carry = (prod1 & UIMASK) + a0;
+                ulong t = (uint)carry * mDash;
+
+                ulong prod2 = t * (uint)m[n - 1];
+                carry += (uint)prod2;
+                Debug.Assert((uint)carry == 0);
+                carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
+
+                for (int j = n - 2; j >= 0; --j)
+                {
+                    prod1 = xi * (uint)y[j];
+                    prod2 = t * (uint)m[j];
+
+                    carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[j + 1];
+                    a[j + 2] = (int)carry;
+                    carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
+                }
+
+                carry += (uint)aMax;
+                a[1] = (int)carry;
+                aMax = (int)(carry >> 32);
+            }
+
+            a[0] = aMax;
+
+            if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
+            {
+                Subtract(0, a, 0, m);
+            }
+
+            Array.Copy(a, 1, x, 0, n);
+        }
+
+        private static void SquareMonty(int[] a, int[] x, int[] m, uint mDash, bool smallMontyModulus)
+            // mDash = -m^(-1) mod b
+        {
+            int n = m.Length;
+
+            if (n == 1)
+            {
+                uint xVal = (uint)x[0];
+                x[0] = (int)MultiplyMontyNIsOne(xVal, xVal, (uint)m[0], mDash);
+                return;
+            }
+
+            ulong x0 = (uint)x[n - 1];
+            int aMax;
+
+            {
+                ulong carry = x0 * x0;
+                ulong t = (uint)carry * mDash;
+
+                ulong prod2 = t * (uint)m[n - 1];
+                carry += (uint)prod2;
+                Debug.Assert((uint)carry == 0);
+                carry = (carry >> 32) + (prod2 >> 32);
+
+                for (int j = n - 2; j >= 0; --j)
+                {
+                    ulong prod1 = x0 * (uint)x[j];
+                    prod2 = t * (uint)m[j];
+
+                    carry += (prod2 & UIMASK) + ((uint)prod1 << 1);
+                    a[j + 2] = (int)carry;
+                    carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32);
+                }
+
+                a[1] = (int)carry;
+                aMax = (int)(carry >> 32);
+            }
+
+            for (int i = n - 2; i >= 0; --i)
+            {
+                uint a0 = (uint)a[n];
+                ulong t = a0 * mDash;
+
+                ulong carry = t * (uint)m[n - 1] + a0;
+                Debug.Assert((uint)carry == 0);
+                carry >>= 32;
+
+                for (int j = n - 2; j > i; --j)
+                {
+                    carry += t * (uint)m[j] + (uint)a[j + 1];
+                    a[j + 2] = (int)carry;
+                    carry >>= 32;
+                }
+
+                ulong xi = (uint)x[i];
+
+                {
+                    ulong prod1 = xi * xi;
+                    ulong prod2 = t * (uint)m[i];
+
+                    carry += (prod1 & UIMASK) + (uint)prod2 + (uint)a[i + 1];
+                    a[i + 2] = (int)carry;
+                    carry = (carry >> 32) + (prod1 >> 32) + (prod2 >> 32);
+                }
+
+                for (int j = i - 1; j >= 0; --j)
+                {
+                    ulong prod1 = xi * (uint)x[j];
+                    ulong prod2 = t * (uint)m[j];
+
+                    carry += (prod2 & UIMASK) + ((uint)prod1 << 1) + (uint)a[j + 1];
+                    a[j + 2] = (int)carry;
+                    carry = (carry >> 32) + (prod1 >> 31) + (prod2 >> 32);
+                }
+
+                carry += (uint)aMax;
+                a[1] = (int)carry;
+                aMax = (int)(carry >> 32);
+            }
+
+            a[0] = aMax;
+
+            if (!smallMontyModulus && CompareTo(0, a, 0, m) >= 0)
+            {
+                Subtract(0, a, 0, m);
+            }
+
+            Array.Copy(a, 1, x, 0, n);
+        }
+
+        private static uint MultiplyMontyNIsOne(uint x, uint y, uint m, uint mDash)
+        {
+            ulong carry = (ulong)x * y;
+            uint t = (uint)carry * mDash;
+            ulong um = m;
+            ulong prod2 = um * t;
+            carry += (uint)prod2;
+            Debug.Assert((uint)carry == 0);
+            carry = (carry >> 32) + (prod2 >> 32);
+            if (carry > um)
+            {
+                carry -= um;
+            }
+            Debug.Assert(carry < um);
+            return (uint)carry;
+        }
+
+        public BigInteger Multiply(
+            BigInteger val)
+        {
+            if (val == this)
+                return Square();
+
+            if ((sign & val.sign) == 0)
+                return Zero;
+
+            if (val.QuickPow2Check()) // val is power of two
+            {
+                BigInteger result = this.ShiftLeft(val.Abs().BitLength - 1);
+                return val.sign > 0 ? result : result.Negate();
+            }
+
+            if (this.QuickPow2Check()) // this is power of two
+            {
+                BigInteger result = val.ShiftLeft(this.Abs().BitLength - 1);
+                return this.sign > 0 ? result : result.Negate();
+            }
+
+            int resLength = magnitude.Length + val.magnitude.Length;
+            int[] res = new int[resLength];
+
+            Multiply(res, this.magnitude, val.magnitude);
+
+            int resSign = sign ^ val.sign ^ 1;
+            return new BigInteger(resSign, res, true);
+        }
+
+        public BigInteger Square()
+        {
+            if (sign == 0)
+                return Zero;
+            if (this.QuickPow2Check())
+                return ShiftLeft(Abs().BitLength - 1);
+            int resLength = magnitude.Length << 1;
+            if ((uint)magnitude[0] >> 16 == 0)
+                --resLength;
+            int[] res = new int[resLength];
+            Square(res, magnitude);
+            return new BigInteger(1, res, false);
+        }
+
+        public BigInteger Negate()
+        {
+            if (sign == 0)
+                return this;
+
+            return new BigInteger(-sign, magnitude, false);
+        }
+
+        public BigInteger NextProbablePrime()
+        {
+            if (sign < 0)
+                throw new ArithmeticException("Cannot be called on value < 0");
+
+            if (CompareTo(Two) < 0)
+                return Two;
+
+            BigInteger n = Inc().SetBit(0);
+
+            while (!n.CheckProbablePrime(100, RandomSource))
+            {
+                n = n.Add(Two);
+            }
+
+            return n;
+        }
+
+        public BigInteger Not()
+        {
+            return Inc().Negate();
+        }
+
+        public BigInteger Pow(int exp)
+        {
+            if (exp <= 0)
+            {
+                if (exp < 0)
+                    throw new ArithmeticException("Negative exponent");
+
+                return One;
+            }
+
+            if (sign == 0)
+            {
+                return this;
+            }
+
+            if (QuickPow2Check())
+            {
+                long powOf2 = (long)exp * (BitLength - 1);
+                if (powOf2 > Int32.MaxValue)
+                {
+                    throw new ArithmeticException("Result too large");
+                }
+                return One.ShiftLeft((int)powOf2); 
+            }
+
+            BigInteger y = One;
+            BigInteger z = this;
+
+            for (;;)
+            {
+                if ((exp & 0x1) == 1)
+                {
+                    y = y.Multiply(z);
+                }
+                exp >>= 1;
+                if (exp == 0) break;
+                z = z.Multiply(z);
+            }
+
+            return y;
+        }
+
+        public static BigInteger ProbablePrime(
+            int bitLength,
+            Random random)
+        {
+            return new BigInteger(bitLength, 100, random);
+        }
+
+        private int Remainder(
+            int m)
+        {
+            Debug.Assert(m > 0);
+
+            long acc = 0;
+            for (int pos = 0; pos < magnitude.Length; ++pos)
+            {
+                long posVal = (uint) magnitude[pos];
+                acc = (acc << 32 | posVal) % m;
+            }
+
+            return (int) acc;
+        }
+
+        /**
+         * return x = x % y - done in place (y value preserved)
+         */
+        private static int[] Remainder(
+            int[] x,
+            int[] y)
+        {
+            int xStart = 0;
+            while (xStart < x.Length && x[xStart] == 0)
+            {
+                ++xStart;
+            }
+
+            int yStart = 0;
+            while (yStart < y.Length && y[yStart] == 0)
+            {
+                ++yStart;
+            }
+
+            Debug.Assert(yStart < y.Length);
+
+            int xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+
+            if (xyCmp > 0)
+            {
+                int yBitLength = CalcBitLength(1, yStart, y);
+                int xBitLength = CalcBitLength(1, xStart, x);
+                int shift = xBitLength - yBitLength;
+
+                int[] c;
+                int cStart = 0;
+                int cBitLength = yBitLength;
+                if (shift > 0)
+                {
+                    c = ShiftLeft(y, shift);
+                    cBitLength += shift;
+                    Debug.Assert(c[0] != 0);
+                }
+                else
+                {
+                    int len = y.Length - yStart;
+                    c = new int[len];
+                    Array.Copy(y, yStart, c, 0, len);
+                }
+
+                for (;;)
+                {
+                    if (cBitLength < xBitLength
+                        || CompareNoLeadingZeroes(xStart, x, cStart, c) >= 0)
+                    {
+                        Subtract(xStart, x, cStart, c);
+
+                        while (x[xStart] == 0)
+                        {
+                            if (++xStart == x.Length)
+                                return x;
+                        }
+
+                        //xBitLength = CalcBitLength(xStart, x);
+                        xBitLength = 32 * (x.Length - xStart - 1) + BitLen(x[xStart]);
+
+                        if (xBitLength <= yBitLength)
+                        {
+                            if (xBitLength < yBitLength)
+                                return x;
+
+                            xyCmp = CompareNoLeadingZeroes(xStart, x, yStart, y);
+
+                            if (xyCmp <= 0)
+                                break;
+                        }
+                    }
+
+                    shift = cBitLength - xBitLength;
+
+                    // NB: The case where c[cStart] is 1-bit is harmless
+                    if (shift == 1)
+                    {
+                        uint firstC = (uint) c[cStart] >> 1;
+                        uint firstX = (uint) x[xStart];
+                        if (firstC > firstX)
+                            ++shift;
+                    }
+
+                    if (shift < 2)
+                    {
+                        ShiftRightOneInPlace(cStart, c);
+                        --cBitLength;
+                    }
+                    else
+                    {
+                        ShiftRightInPlace(cStart, c, shift);
+                        cBitLength -= shift;
+                    }
+
+                    //cStart = c.Length - ((cBitLength + 31) / 32);
+                    while (c[cStart] == 0)
+                    {
+                        ++cStart;
+                    }
+                }
+            }
+
+            if (xyCmp == 0)
+            {
+                Array.Clear(x, xStart, x.Length - xStart);
+            }
+
+            return x;
+        }
+
+        public BigInteger Remainder(
+            BigInteger n)
+        {
+            if (n.sign == 0)
+                throw new ArithmeticException("Division by zero error");
+
+            if (this.sign == 0)
+                return Zero;
+
+            // For small values, use fast remainder method
+            if (n.magnitude.Length == 1)
+            {
+                int val = n.magnitude[0];
+
+                if (val > 0)
+                {
+                    if (val == 1)
+                        return Zero;
+
+                    // TODO Make this func work on uint, and handle val == 1?
+                    int rem = Remainder(val);
+
+                    return rem == 0
+                        ?	Zero
+                        :	new BigInteger(sign, new int[]{ rem }, false);
+                }
+            }
+
+            if (CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude) < 0)
+                return this;
+
+            int[] result;
+            if (n.QuickPow2Check())  // n is power of two
+            {
+                // TODO Move before small values branch above?
+                result = LastNBits(n.Abs().BitLength - 1);
+            }
+            else
+            {
+                result = (int[]) this.magnitude.Clone();
+                result = Remainder(result, n.magnitude);
+            }
+
+            return new BigInteger(sign, result, true);
+        }
+
+        private int[] LastNBits(
+            int n)
+        {
+            if (n < 1)
+                return ZeroMagnitude;
+
+            int numWords = (n + BitsPerInt - 1) / BitsPerInt;
+            numWords = System.Math.Min(numWords, this.magnitude.Length);
+            int[] result = new int[numWords];
+
+            Array.Copy(this.magnitude, this.magnitude.Length - numWords, result, 0, numWords);
+
+            int excessBits = (numWords << 5) - n;
+            if (excessBits > 0)
+            {
+                result[0] &= (int)(UInt32.MaxValue >> excessBits);
+            }
+
+            return result;
+        }
+
+        private BigInteger DivideWords(int w)
+        {
+            Debug.Assert(w >= 0);
+            int n = magnitude.Length;
+            if (w >= n)
+                return Zero;
+            int[] mag = new int[n - w];
+            Array.Copy(magnitude, 0, mag, 0, n - w);
+            return new BigInteger(sign, mag, false);
+        }
+
+        private BigInteger RemainderWords(int w)
+        {
+            Debug.Assert(w >= 0);
+            int n = magnitude.Length;
+            if (w >= n)
+                return this;
+            int[] mag = new int[w];
+            Array.Copy(magnitude, n - w, mag, 0, w);
+            return new BigInteger(sign, mag, false);
+        }
+
+        /**
+         * do a left shift - this returns a new array.
+         */
+        private static int[] ShiftLeft(
+            int[]	mag,
+            int		n)
+        {
+            int nInts = (int)((uint)n >> 5);
+            int nBits = n & 0x1f;
+            int magLen = mag.Length;
+            int[] newMag;
+
+            if (nBits == 0)
+            {
+                newMag = new int[magLen + nInts];
+                mag.CopyTo(newMag, 0);
+            }
+            else
+            {
+                int i = 0;
+                int nBits2 = 32 - nBits;
+                int highBits = (int)((uint)mag[0] >> nBits2);
+
+                if (highBits != 0)
+                {
+                    newMag = new int[magLen + nInts + 1];
+                    newMag[i++] = highBits;
+                }
+                else
+                {
+                    newMag = new int[magLen + nInts];
+                }
+
+                int m = mag[0];
+                for (int j = 0; j < magLen - 1; j++)
+                {
+                    int next = mag[j + 1];
+
+                    newMag[i++] = (m << nBits) | (int)((uint)next >> nBits2);
+                    m = next;
+                }
+
+                newMag[i] = mag[magLen - 1] << nBits;
+            }
+
+            return newMag;
+        }
+
+        private static int ShiftLeftOneInPlace(int[] x, int carry)
+        {
+            Debug.Assert(carry == 0 || carry == 1);
+            int pos = x.Length;
+            while (--pos >= 0)
+            {
+                uint val = (uint)x[pos];
+                x[pos] = (int)(val << 1) | carry;
+                carry = (int)(val >> 31);
+            }
+            return carry;
+        }
+
+        public BigInteger ShiftLeft(
+            int n)
+        {
+            if (sign == 0 || magnitude.Length == 0)
+                return Zero;
+
+            if (n == 0)
+                return this;
+
+            if (n < 0)
+                return ShiftRight(-n);
+
+            BigInteger result = new BigInteger(sign, ShiftLeft(magnitude, n), true);
+
+            if (this.nBits != -1)
+            {
+                result.nBits = sign > 0
+                    ?	this.nBits
+                    :	this.nBits + n;
+            }
+
+            if (this.nBitLength != -1)
+            {
+                result.nBitLength = this.nBitLength + n;
+            }
+
+            return result;
+        }
+
+        /**
+         * do a right shift - this does it in place.
+         */
+        private static void ShiftRightInPlace(
+            int		start,
+            int[]	mag,
+            int		n)
+        {
+            int nInts = (int)((uint)n >> 5) + start;
+            int nBits = n & 0x1f;
+            int magEnd = mag.Length - 1;
+
+            if (nInts != start)
+            {
+                int delta = (nInts - start);
+
+                for (int i = magEnd; i >= nInts; i--)
+                {
+                    mag[i] = mag[i - delta];
+                }
+                for (int i = nInts - 1; i >= start; i--)
+                {
+                    mag[i] = 0;
+                }
+            }
+
+            if (nBits != 0)
+            {
+                int nBits2 = 32 - nBits;
+                int m = mag[magEnd];
+
+                for (int i = magEnd; i > nInts; --i)
+                {
+                    int next = mag[i - 1];
+
+                    mag[i] = (int)((uint)m >> nBits) | (next << nBits2);
+                    m = next;
+                }
+
+                mag[nInts] = (int)((uint)mag[nInts] >> nBits);
+            }
+        }
+
+        /**
+         * do a right shift by one - this does it in place.
+         */
+        private static void ShiftRightOneInPlace(
+            int		start,
+            int[]	mag)
+        {
+            int i = mag.Length;
+            int m = mag[i - 1];
+
+            while (--i > start)
+            {
+                int next = mag[i - 1];
+                mag[i] = ((int)((uint)m >> 1)) | (next << 31);
+                m = next;
+            }
+
+            mag[start] = (int)((uint)mag[start] >> 1);
+        }
+
+        public BigInteger ShiftRight(
+            int n)
+        {
+            if (n == 0)
+                return this;
+
+            if (n < 0)
+                return ShiftLeft(-n);
+
+            if (n >= BitLength)
+                return (this.sign < 0 ? One.Negate() : Zero);
+
+//			int[] res = (int[]) this.magnitude.Clone();
+//
+//			ShiftRightInPlace(0, res, n);
+//
+//			return new BigInteger(this.sign, res, true);
+
+            int resultLength = (BitLength - n + 31) >> 5;
+            int[] res = new int[resultLength];
+
+            int numInts = n >> 5;
+            int numBits = n & 31;
+
+            if (numBits == 0)
+            {
+                Array.Copy(this.magnitude, 0, res, 0, res.Length);
+            }
+            else
+            {
+                int numBits2 = 32 - numBits;
+
+                int magPos = this.magnitude.Length - 1 - numInts;
+                for (int i = resultLength - 1; i >= 0; --i)
+                {
+                    res[i] = (int)((uint) this.magnitude[magPos--] >> numBits);
+
+                    if (magPos >= 0)
+                    {
+                        res[i] |= this.magnitude[magPos] << numBits2;
+                    }
+                }
+            }
+
+            Debug.Assert(res[0] != 0);
+
+            return new BigInteger(this.sign, res, false);
+        }
+
+        public int SignValue
+        {
+            get { return sign; }
+        }
+
+        /**
+         * returns x = x - y - we assume x is >= y
+         */
+        private static int[] Subtract(
+            int		xStart,
+            int[]	x,
+            int		yStart,
+            int[]	y)
+        {
+            Debug.Assert(yStart < y.Length);
+            Debug.Assert(x.Length - xStart >= y.Length - yStart);
+
+            int iT = x.Length;
+            int iV = y.Length;
+            long m;
+            int borrow = 0;
+
+            do
+            {
+                m = (x[--iT] & IMASK) - (y[--iV] & IMASK) + borrow;
+                x[iT] = (int) m;
+
+//				borrow = (m < 0) ? -1 : 0;
+                borrow = (int)(m >> 63);
+            }
+            while (iV > yStart);
+
+            if (borrow != 0)
+            {
+                while (--x[--iT] == -1)
+                {
+                }
+            }
+
+            return x;
+        }
+
+        public BigInteger Subtract(
+            BigInteger n)
+        {
+            if (n.sign == 0)
+                return this;
+
+            if (this.sign == 0)
+                return n.Negate();
+
+            if (this.sign != n.sign)
+                return Add(n.Negate());
+
+            int compare = CompareNoLeadingZeroes(0, magnitude, 0, n.magnitude);
+            if (compare == 0)
+                return Zero;
+
+            BigInteger bigun, lilun;
+            if (compare < 0)
+            {
+                bigun = n;
+                lilun = this;
+            }
+            else
+            {
+                bigun = this;
+                lilun = n;
+            }
+
+            return new BigInteger(this.sign * compare, doSubBigLil(bigun.magnitude, lilun.magnitude), true);
+        }
+
+        private static int[] doSubBigLil(
+            int[]	bigMag,
+            int[]	lilMag)
+        {
+            int[] res = (int[]) bigMag.Clone();
+
+            return Subtract(0, res, 0, lilMag);
+        }
+
+        public byte[] ToByteArray()
+        {
+            return ToByteArray(false);
+        }
+
+        public byte[] ToByteArrayUnsigned()
+        {
+            return ToByteArray(true);
+        }
+
+        private byte[] ToByteArray(
+            bool unsigned)
+        {
+            if (sign == 0)
+                return unsigned ? ZeroEncoding : new byte[1];
+
+            int nBits = (unsigned && sign > 0)
+                ?	BitLength
+                :	BitLength + 1;
+
+            int nBytes = GetByteLength(nBits);
+            byte[] bytes = new byte[nBytes];
+
+            int magIndex = magnitude.Length;
+            int bytesIndex = bytes.Length;
+
+            if (sign > 0)
+            {
+                while (magIndex > 1)
+                {
+                    uint mag = (uint) magnitude[--magIndex];
+                    bytes[--bytesIndex] = (byte) mag;
+                    bytes[--bytesIndex] = (byte)(mag >> 8);
+                    bytes[--bytesIndex] = (byte)(mag >> 16);
+                    bytes[--bytesIndex] = (byte)(mag >> 24);
+                }
+
+                uint lastMag = (uint) magnitude[0];
+                while (lastMag > byte.MaxValue)
+                {
+                    bytes[--bytesIndex] = (byte) lastMag;
+                    lastMag >>= 8;
+                }
+
+                bytes[--bytesIndex] = (byte) lastMag;
+            }
+            else // sign < 0
+            {
+                bool carry = true;
+
+                while (magIndex > 1)
+                {
+                    uint mag = ~((uint) magnitude[--magIndex]);
+
+                    if (carry)
+                    {
+                        carry = (++mag == uint.MinValue);
+                    }
+
+                    bytes[--bytesIndex] = (byte) mag;
+                    bytes[--bytesIndex] = (byte)(mag >> 8);
+                    bytes[--bytesIndex] = (byte)(mag >> 16);
+                    bytes[--bytesIndex] = (byte)(mag >> 24);
+                }
+
+                uint lastMag = (uint) magnitude[0];
+
+                if (carry)
+                {
+                    // Never wraps because magnitude[0] != 0
+                    --lastMag;
+                }
+
+                while (lastMag > byte.MaxValue)
+                {
+                    bytes[--bytesIndex] = (byte) ~lastMag;
+                    lastMag >>= 8;
+                }
+
+                bytes[--bytesIndex] = (byte) ~lastMag;
+
+                if (bytesIndex > 0)
+                {
+                    bytes[--bytesIndex] = byte.MaxValue;
+                }
+            }
+
+            return bytes;
+        }
+
+        public override string ToString()
+        {
+            return ToString(10);
+        }
+
+        public string ToString(int radix)
+        {
+            // TODO Make this method work for other radices (ideally 2 <= radix <= 36 as in Java)
+
+            switch (radix)
+            {
+                case 2:
+                case 8:
+                case 10:
+                case 16:
+                    break;
+                default:
+                    throw new FormatException("Only bases 2, 8, 10, 16 are allowed");
+            }
+
+            // NB: Can only happen to internally managed instances
+            if (magnitude == null)
+                return "null";
+
+            if (sign == 0)
+                return "0";
+
+
+            // NOTE: This *should* be unnecessary, since the magnitude *should* never have leading zero digits
+            int firstNonZero = 0;
+            while (firstNonZero < magnitude.Length)
+            {
+                if (magnitude[firstNonZero] != 0)
+                {
+                    break;
+                }
+                ++firstNonZero;
+            }
+
+            if (firstNonZero == magnitude.Length)
+            {
+                return "0";
+            }
+
+
+            StringBuilder sb = new StringBuilder();
+            if (sign == -1)
+            {
+                sb.Append('-');
+            }
+
+            switch (radix)
+            {
+            case 2:
+            {
+                int pos = firstNonZero;
+                sb.Append(Convert.ToString(magnitude[pos], 2));
+                while (++pos < magnitude.Length)
+                {
+                    AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 2), 32);
+                }
+                break;
+            }
+            case 8:
+            {
+                int mask = (1 << 30) - 1;
+                BigInteger u = this.Abs();
+                int bits = u.BitLength;
+                IList S = Platform.CreateArrayList();
+                while (bits > 30)
+                {
+                    S.Add(Convert.ToString(u.IntValue & mask, 8));
+                    u = u.ShiftRight(30);
+                    bits -= 30;
+                }
+                sb.Append(Convert.ToString(u.IntValue, 8));
+                for (int i = S.Count - 1; i >= 0; --i)
+                {
+                    AppendZeroExtendedString(sb, (string)S[i], 10);
+                }
+                break;
+            }
+            case 16:
+            {
+                int pos = firstNonZero;
+                sb.Append(Convert.ToString(magnitude[pos], 16));
+                while (++pos < magnitude.Length)
+                {
+                    AppendZeroExtendedString(sb, Convert.ToString(magnitude[pos], 16), 8);
+                }
+                break;
+            }
+            // TODO This could work for other radices if there is an alternative to Convert.ToString method
+            //default:
+            case 10:
+            {
+                BigInteger q = this.Abs();
+                if (q.BitLength < 64)
+                {
+                    sb.Append(Convert.ToString(q.LongValue, radix));
+                    break;
+                }
+
+                // Based on algorithm 1a from chapter 4.4 in Seminumerical Algorithms (Knuth)
+
+                // Work out the largest power of 'rdx' that is a positive 64-bit integer
+                // TODO possibly cache power/exponent against radix?
+                long limit = Int64.MaxValue / radix;
+                long power = radix;
+                int exponent = 1;
+                while (power <= limit)
+                {
+                    power *= radix;
+                    ++exponent;
+                }
+
+                BigInteger bigPower = BigInteger.ValueOf(power);
+
+                IList S = Platform.CreateArrayList();
+                while (q.CompareTo(bigPower) >= 0)
+                {
+                    BigInteger[] qr = q.DivideAndRemainder(bigPower);
+                    S.Add(Convert.ToString(qr[1].LongValue, radix));
+                    q = qr[0];
+                }
+
+                sb.Append(Convert.ToString(q.LongValue, radix));
+                for (int i = S.Count - 1; i >= 0; --i)
+                {
+                    AppendZeroExtendedString(sb, (string)S[i], exponent);
+                }
+                break;
+            }
+            }
+
+            return sb.ToString();
+        }
+
+        private static void AppendZeroExtendedString(StringBuilder sb, string s, int minLength)
+        {
+            for (int len = s.Length; len < minLength; ++len)
+            {
+                sb.Append('0');
+            }
+            sb.Append(s);
+        }
+
+        private static BigInteger CreateUValueOf(
+            ulong value)
+        {
+            int msw = (int)(value >> 32);
+            int lsw = (int)value;
+
+            if (msw != 0)
+                return new BigInteger(1, new int[] { msw, lsw }, false);
+
+            if (lsw != 0)
+            {
+                BigInteger n = new BigInteger(1, new int[] { lsw }, false);
+                // Check for a power of two
+                if ((lsw & -lsw) == lsw)
+                {
+                    n.nBits = 1;
+                }
+                return n;
+            }
+
+            return Zero;
+        }
+
+        private static BigInteger CreateValueOf(
+            long value)
+        {
+            if (value < 0)
+            {
+                if (value == long.MinValue)
+                    return CreateValueOf(~value).Not();
+
+                return CreateValueOf(-value).Negate();
+            }
+
+            return CreateUValueOf((ulong)value);
+        }
+
+        public static BigInteger ValueOf(
+            long value)
+        {
+            if (value >= 0 && value < SMALL_CONSTANTS.Length)
+            {
+                return SMALL_CONSTANTS[value];
+            }
+
+            return CreateValueOf(value);
+        }
+
+        public int GetLowestSetBit()
+        {
+            if (this.sign == 0)
+                return -1;
+
+            return GetLowestSetBitMaskFirst(-1);
+        }
+
+        private int GetLowestSetBitMaskFirst(int firstWordMask)
+        {
+            int w = magnitude.Length, offset = 0;
+
+            uint word = (uint)(magnitude[--w] & firstWordMask);
+            Debug.Assert(magnitude[0] != 0);
+
+            while (word == 0)
+            {
+                word = (uint)magnitude[--w];
+                offset += 32;
+            }
+
+            while ((word & 0xFF) == 0)
+            {
+                word >>= 8;
+                offset += 8;
+            }
+
+            while ((word & 1) == 0)
+            {
+                word >>= 1;
+                ++offset;
+            }
+
+            return offset;
+        }
+
+        public bool TestBit(
+            int n)
+        {
+            if (n < 0)
+                throw new ArithmeticException("Bit position must not be negative");
+
+            if (sign < 0)
+                return !Not().TestBit(n);
+
+            int wordNum = n / 32;
+            if (wordNum >= magnitude.Length)
+                return false;
+
+            int word = magnitude[magnitude.Length - 1 - wordNum];
+            return ((word >> (n % 32)) & 1) > 0;
+        }
+
+        public BigInteger Or(
+            BigInteger value)
+        {
+            if (this.sign == 0)
+                return value;
+
+            if (value.sign == 0)
+                return this;
+
+            int[] aMag = this.sign > 0
+                ? this.magnitude
+                : Add(One).magnitude;
+
+            int[] bMag = value.sign > 0
+                ? value.magnitude
+                : value.Add(One).magnitude;
+
+            bool resultNeg = sign < 0 || value.sign < 0;
+            int resultLength = System.Math.Max(aMag.Length, bMag.Length);
+            int[] resultMag = new int[resultLength];
+
+            int aStart = resultMag.Length - aMag.Length;
+            int bStart = resultMag.Length - bMag.Length;
+
+            for (int i = 0; i < resultMag.Length; ++i)
+            {
+                int aWord = i >= aStart ? aMag[i - aStart] : 0;
+                int bWord = i >= bStart ? bMag[i - bStart] : 0;
+
+                if (this.sign < 0)
+                {
+                    aWord = ~aWord;
+                }
+
+                if (value.sign < 0)
+                {
+                    bWord = ~bWord;
+                }
+
+                resultMag[i] = aWord | bWord;
+
+                if (resultNeg)
+                {
+                    resultMag[i] = ~resultMag[i];
+                }
+            }
+
+            BigInteger result = new BigInteger(1, resultMag, true);
+
+            // TODO Optimise this case
+            if (resultNeg)
+            {
+                result = result.Not();
+            }
+
+            return result;
+        }
+
+        public BigInteger Xor(
+            BigInteger value)
+        {
+            if (this.sign == 0)
+                return value;
+
+            if (value.sign == 0)
+                return this;
+
+            int[] aMag = this.sign > 0
+                ? this.magnitude
+                : Add(One).magnitude;
+
+            int[] bMag = value.sign > 0
+                ? value.magnitude
+                : value.Add(One).magnitude;
+
+            // TODO Can just replace with sign != value.sign?
+            bool resultNeg = (sign < 0 && value.sign >= 0) || (sign >= 0 && value.sign < 0);
+            int resultLength = System.Math.Max(aMag.Length, bMag.Length);
+            int[] resultMag = new int[resultLength];
+
+            int aStart = resultMag.Length - aMag.Length;
+            int bStart = resultMag.Length - bMag.Length;
+
+            for (int i = 0; i < resultMag.Length; ++i)
+            {
+                int aWord = i >= aStart ? aMag[i - aStart] : 0;
+                int bWord = i >= bStart ? bMag[i - bStart] : 0;
+
+                if (this.sign < 0)
+                {
+                    aWord = ~aWord;
+                }
+
+                if (value.sign < 0)
+                {
+                    bWord = ~bWord;
+                }
+
+                resultMag[i] = aWord ^ bWord;
+
+                if (resultNeg)
+                {
+                    resultMag[i] = ~resultMag[i];
+                }
+            }
+
+            BigInteger result = new BigInteger(1, resultMag, true);
+
+            // TODO Optimise this case
+            if (resultNeg)
+            {
+                result = result.Not();
+            }
+
+            return result;
+        }
+
+        public BigInteger SetBit(
+            int n)
+        {
+            if (n < 0)
+                throw new ArithmeticException("Bit address less than zero");
+
+            if (TestBit(n))
+                return this;
+
+            // TODO Handle negative values and zero
+            if (sign > 0 && n < (BitLength - 1))
+                return FlipExistingBit(n);
+
+            return Or(One.ShiftLeft(n));
+        }
+
+        public BigInteger ClearBit(
+            int n)
+        {
+            if (n < 0)
+                throw new ArithmeticException("Bit address less than zero");
+
+            if (!TestBit(n))
+                return this;
+
+            // TODO Handle negative values
+            if (sign > 0 && n < (BitLength - 1))
+                return FlipExistingBit(n);
+
+            return AndNot(One.ShiftLeft(n));
+        }
+
+        public BigInteger FlipBit(
+            int n)
+        {
+            if (n < 0)
+                throw new ArithmeticException("Bit address less than zero");
+
+            // TODO Handle negative values and zero
+            if (sign > 0 && n < (BitLength - 1))
+                return FlipExistingBit(n);
+
+            return Xor(One.ShiftLeft(n));
+        }
+
+        private BigInteger FlipExistingBit(
+            int n)
+        {
+            Debug.Assert(sign > 0);
+            Debug.Assert(n >= 0);
+            Debug.Assert(n < BitLength - 1);
+
+            int[] mag = (int[]) this.magnitude.Clone();
+            mag[mag.Length - 1 - (n >> 5)] ^= (1 << (n & 31)); // Flip bit
+            //mag[mag.Length - 1 - (n / 32)] ^= (1 << (n % 32));
+            return new BigInteger(this.sign, mag, false);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ECAlgorithms.cs b/BouncyCastle.AxCrypt/src/math/ec/ECAlgorithms.cs
new file mode 100644
index 0000000..3c911b1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ECAlgorithms.cs
@@ -0,0 +1,459 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Math.Field;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public class ECAlgorithms
+    {
+        public static bool IsF2mCurve(ECCurve c)
+        {
+            IFiniteField field = c.Field;
+            return field.Dimension > 1 && field.Characteristic.Equals(BigInteger.Two)
+                && field is IPolynomialExtensionField;
+        }
+
+        public static bool IsFpCurve(ECCurve c)
+        {
+            return c.Field.Dimension == 1;
+        }
+
+        public static ECPoint SumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+        {
+            if (ps == null || ks == null || ps.Length != ks.Length || ps.Length < 1)
+                throw new ArgumentException("point and scalar arrays should be non-null, and of equal, non-zero, length");
+
+            int count = ps.Length;
+            switch (count)
+            {
+                case 1:
+                    return ps[0].Multiply(ks[0]);
+                case 2:
+                    return SumOfTwoMultiplies(ps[0], ks[0], ps[1], ks[1]);
+                default:
+                    break;
+            }
+
+            ECPoint p = ps[0];
+            ECCurve c = p.Curve;
+
+            ECPoint[] imported = new ECPoint[count];
+            imported[0] = p;
+            for (int i = 1; i < count; ++i)
+            {
+                imported[i] = ImportPoint(c, ps[i]);
+            }
+
+            GlvEndomorphism glvEndomorphism = c.GetEndomorphism() as GlvEndomorphism;
+            if (glvEndomorphism != null)
+            {
+                return ValidatePoint(ImplSumOfMultipliesGlv(imported, ks, glvEndomorphism));
+            }
+
+            return ValidatePoint(ImplSumOfMultiplies(imported, ks));
+        }
+
+        public static ECPoint SumOfTwoMultiplies(ECPoint P, BigInteger a, ECPoint Q, BigInteger b)
+        {
+            ECCurve cp = P.Curve;
+            Q = ImportPoint(cp, Q);
+
+            // Point multiplication for Koblitz curves (using WTNAF) beats Shamir's trick
+            if (cp is F2mCurve)
+            {
+                F2mCurve f2mCurve = (F2mCurve) cp;
+                if (f2mCurve.IsKoblitz)
+                {
+                    return ValidatePoint(P.Multiply(a).Add(Q.Multiply(b)));
+                }
+            }
+
+            GlvEndomorphism glvEndomorphism = cp.GetEndomorphism() as GlvEndomorphism;
+            if (glvEndomorphism != null)
+            {
+                return ValidatePoint(
+                    ImplSumOfMultipliesGlv(new ECPoint[] { P, Q }, new BigInteger[] { a, b }, glvEndomorphism));
+            }
+
+            return ValidatePoint(ImplShamirsTrickWNaf(P, a, Q, b));
+        }
+
+        /*
+        * "Shamir's Trick", originally due to E. G. Straus
+        * (Addition chains of vectors. American Mathematical Monthly,
+        * 71(7):806-808, Aug./Sept. 1964)
+        *  
+        * Input: The points P, Q, scalar k = (km?, ... , k1, k0)
+        * and scalar l = (lm?, ... , l1, l0).
+        * Output: R = k * P + l * Q.
+        * 1: Z <- P + Q
+        * 2: R <- O
+        * 3: for i from m-1 down to 0 do
+        * 4:        R <- R + R        {point doubling}
+        * 5:        if (ki = 1) and (li = 0) then R <- R + P end if
+        * 6:        if (ki = 0) and (li = 1) then R <- R + Q end if
+        * 7:        if (ki = 1) and (li = 1) then R <- R + Z end if
+        * 8: end for
+        * 9: return R
+        */
+        public static ECPoint ShamirsTrick(ECPoint P, BigInteger k, ECPoint Q, BigInteger l)
+        {
+            ECCurve cp = P.Curve;
+            Q = ImportPoint(cp, Q);
+
+            return ValidatePoint(ImplShamirsTrickJsf(P, k, Q, l));
+        }
+
+        public static ECPoint ImportPoint(ECCurve c, ECPoint p)
+        {
+            ECCurve cp = p.Curve;
+            if (!c.Equals(cp))
+                throw new ArgumentException("Point must be on the same curve");
+
+            return c.ImportPoint(p);
+        }
+
+        public static void MontgomeryTrick(ECFieldElement[] zs, int off, int len)
+        {
+            /*
+             * Uses the "Montgomery Trick" to invert many field elements, with only a single actual
+             * field inversion. See e.g. the paper:
+             * "Fast Multi-scalar Multiplication Methods on Elliptic Curves with Precomputation Strategy Using Montgomery Trick"
+             * by Katsuyuki Okeya, Kouichi Sakurai.
+             */
+
+            ECFieldElement[] c = new ECFieldElement[len];
+            c[0] = zs[off];
+
+            int i = 0;
+            while (++i < len)
+            {
+                c[i] = c[i - 1].Multiply(zs[off + i]);
+            }
+
+            ECFieldElement u = c[--i].Invert();
+
+            while (i > 0)
+            {
+                int j = off + i--;
+                ECFieldElement tmp = zs[j];
+                zs[j] = c[i].Multiply(u);
+                u = u.Multiply(tmp);
+            }
+
+            zs[off] = u;
+        }
+
+        /**
+         * Simple shift-and-add multiplication. Serves as reference implementation
+         * to verify (possibly faster) implementations, and for very small scalars.
+         * 
+         * @param p
+         *            The point to multiply.
+         * @param k
+         *            The multiplier.
+         * @return The result of the point multiplication <code>kP</code>.
+         */
+        public static ECPoint ReferenceMultiply(ECPoint p, BigInteger k)
+        {
+            BigInteger x = k.Abs();
+            ECPoint q = p.Curve.Infinity;
+            int t = x.BitLength;
+            if (t > 0)
+            {
+                if (x.TestBit(0))
+                {
+                    q = p;
+                }
+                for (int i = 1; i < t; i++)
+                {
+                    p = p.Twice();
+                    if (x.TestBit(i))
+                    {
+                        q = q.Add(p);
+                    }
+                }
+            }
+            return k.SignValue < 0 ? q.Negate() : q;
+        }
+
+        public static ECPoint ValidatePoint(ECPoint p)
+        {
+            if (!p.IsValid())
+                throw new ArgumentException("Invalid point", "p");
+
+            return p;
+        }
+
+        internal static ECPoint ImplShamirsTrickJsf(ECPoint P, BigInteger k, ECPoint Q, BigInteger l)
+        {
+            ECCurve curve = P.Curve;
+            ECPoint infinity = curve.Infinity;
+
+            // TODO conjugate co-Z addition (ZADDC) can return both of these
+            ECPoint PaddQ = P.Add(Q);
+            ECPoint PsubQ = P.Subtract(Q);
+
+            ECPoint[] points = new ECPoint[] { Q, PsubQ, P, PaddQ };
+            curve.NormalizeAll(points);
+
+            ECPoint[] table = new ECPoint[] {
+            points[3].Negate(), points[2].Negate(), points[1].Negate(),
+            points[0].Negate(), infinity, points[0],
+            points[1], points[2], points[3] };
+
+            byte[] jsf = WNafUtilities.GenerateJsf(k, l);
+
+            ECPoint R = infinity;
+
+            int i = jsf.Length;
+            while (--i >= 0)
+            {
+                int jsfi = jsf[i];
+
+                // NOTE: The shifting ensures the sign is extended correctly
+                int kDigit = ((jsfi << 24) >> 28), lDigit = ((jsfi << 28) >> 28);
+
+                int index = 4 + (kDigit * 3) + lDigit;
+                R = R.TwicePlus(table[index]);
+            }
+
+            return R;
+        }
+
+        internal static ECPoint ImplShamirsTrickWNaf(ECPoint P, BigInteger k,
+            ECPoint Q, BigInteger l)
+        {
+            bool negK = k.SignValue < 0, negL = l.SignValue < 0;
+
+            k = k.Abs();
+            l = l.Abs();
+
+            int widthP = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(k.BitLength)));
+            int widthQ = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(l.BitLength)));
+
+            WNafPreCompInfo infoP = WNafUtilities.Precompute(P, widthP, true);
+            WNafPreCompInfo infoQ = WNafUtilities.Precompute(Q, widthQ, true);
+
+            ECPoint[] preCompP = negK ? infoP.PreCompNeg : infoP.PreComp;
+            ECPoint[] preCompQ = negL ? infoQ.PreCompNeg : infoQ.PreComp;
+            ECPoint[] preCompNegP = negK ? infoP.PreComp : infoP.PreCompNeg;
+            ECPoint[] preCompNegQ = negL ? infoQ.PreComp : infoQ.PreCompNeg;
+
+            byte[] wnafP = WNafUtilities.GenerateWindowNaf(widthP, k);
+            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(widthQ, l);
+
+            return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+        }
+
+        internal static ECPoint ImplShamirsTrickWNaf(ECPoint P, BigInteger k, ECPointMap pointMapQ, BigInteger l)
+        {
+            bool negK = k.SignValue < 0, negL = l.SignValue < 0;
+
+            k = k.Abs();
+            l = l.Abs();
+
+            int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(System.Math.Max(k.BitLength, l.BitLength))));
+
+            ECPoint Q = WNafUtilities.MapPointWithPrecomp(P, width, true, pointMapQ);
+            WNafPreCompInfo infoP = WNafUtilities.GetWNafPreCompInfo(P);
+            WNafPreCompInfo infoQ = WNafUtilities.GetWNafPreCompInfo(Q);
+
+            ECPoint[] preCompP = negK ? infoP.PreCompNeg : infoP.PreComp;
+            ECPoint[] preCompQ = negL ? infoQ.PreCompNeg : infoQ.PreComp;
+            ECPoint[] preCompNegP = negK ? infoP.PreComp : infoP.PreCompNeg;
+            ECPoint[] preCompNegQ = negL ? infoQ.PreComp : infoQ.PreCompNeg;
+
+            byte[] wnafP = WNafUtilities.GenerateWindowNaf(width, k);
+            byte[] wnafQ = WNafUtilities.GenerateWindowNaf(width, l);
+
+            return ImplShamirsTrickWNaf(preCompP, preCompNegP, wnafP, preCompQ, preCompNegQ, wnafQ);
+        }
+
+        private static ECPoint ImplShamirsTrickWNaf(ECPoint[] preCompP, ECPoint[] preCompNegP, byte[] wnafP,
+            ECPoint[] preCompQ, ECPoint[] preCompNegQ, byte[] wnafQ)
+        {
+            int len = System.Math.Max(wnafP.Length, wnafQ.Length);
+
+            ECCurve curve = preCompP[0].Curve;
+            ECPoint infinity = curve.Infinity;
+
+            ECPoint R = infinity;
+            int zeroes = 0;
+
+            for (int i = len - 1; i >= 0; --i)
+            {
+                int wiP = i < wnafP.Length ? (int)(sbyte)wnafP[i] : 0;
+                int wiQ = i < wnafQ.Length ? (int)(sbyte)wnafQ[i] : 0;
+
+                if ((wiP | wiQ) == 0)
+                {
+                    ++zeroes;
+                    continue;
+                }
+
+                ECPoint r = infinity;
+                if (wiP != 0)
+                {
+                    int nP = System.Math.Abs(wiP);
+                    ECPoint[] tableP = wiP < 0 ? preCompNegP : preCompP;
+                    r = r.Add(tableP[nP >> 1]);
+                }
+                if (wiQ != 0)
+                {
+                    int nQ = System.Math.Abs(wiQ);
+                    ECPoint[] tableQ = wiQ < 0 ? preCompNegQ : preCompQ;
+                    r = r.Add(tableQ[nQ >> 1]);
+                }
+
+                if (zeroes > 0)
+                {
+                    R = R.TimesPow2(zeroes);
+                    zeroes = 0;
+                }
+
+                R = R.TwicePlus(r);
+            }
+
+            if (zeroes > 0)
+            {
+                R = R.TimesPow2(zeroes);
+            }
+
+            return R;
+        }
+
+        internal static ECPoint ImplSumOfMultiplies(ECPoint[] ps, BigInteger[] ks)
+        {
+            int count = ps.Length;
+            bool[] negs = new bool[count];
+            WNafPreCompInfo[] infos = new WNafPreCompInfo[count];
+            byte[][] wnafs = new byte[count][];
+
+            for (int i = 0; i < count; ++i)
+            {
+                BigInteger ki = ks[i]; negs[i] = ki.SignValue < 0; ki = ki.Abs();
+
+                int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(ki.BitLength)));
+                infos[i] = WNafUtilities.Precompute(ps[i], width, true);
+                wnafs[i] = WNafUtilities.GenerateWindowNaf(width, ki);
+            }
+
+            return ImplSumOfMultiplies(negs, infos, wnafs);
+        }
+
+        internal static ECPoint ImplSumOfMultipliesGlv(ECPoint[] ps, BigInteger[] ks, GlvEndomorphism glvEndomorphism)
+        {
+            BigInteger n = ps[0].Curve.Order;
+
+            int len = ps.Length;
+
+            BigInteger[] abs = new BigInteger[len << 1];
+            for (int i = 0, j = 0; i < len; ++i)
+            {
+                BigInteger[] ab = glvEndomorphism.DecomposeScalar(ks[i].Mod(n));
+                abs[j++] = ab[0];
+                abs[j++] = ab[1];
+            }
+
+            ECPointMap pointMap = glvEndomorphism.PointMap;
+            if (glvEndomorphism.HasEfficientPointMap)
+            {
+                return ECAlgorithms.ImplSumOfMultiplies(ps, pointMap, abs);
+            }
+
+            ECPoint[] pqs = new ECPoint[len << 1];
+            for (int i = 0, j = 0; i < len; ++i)
+            {
+                ECPoint p = ps[i], q = pointMap.Map(p);
+                pqs[j++] = p;
+                pqs[j++] = q;
+            }
+
+            return ECAlgorithms.ImplSumOfMultiplies(pqs, abs);
+        }
+
+        internal static ECPoint ImplSumOfMultiplies(ECPoint[] ps, ECPointMap pointMap, BigInteger[] ks)
+        {
+            int halfCount = ps.Length, fullCount = halfCount << 1;
+
+            bool[] negs = new bool[fullCount];
+            WNafPreCompInfo[] infos = new WNafPreCompInfo[fullCount];
+            byte[][] wnafs = new byte[fullCount][];
+
+            for (int i = 0; i < halfCount; ++i)
+            {
+                int j0 = i << 1, j1 = j0 + 1;
+
+                BigInteger kj0 = ks[j0]; negs[j0] = kj0.SignValue < 0; kj0 = kj0.Abs();
+                BigInteger kj1 = ks[j1]; negs[j1] = kj1.SignValue < 0; kj1 = kj1.Abs();
+
+                int width = System.Math.Max(2, System.Math.Min(16, WNafUtilities.GetWindowSize(System.Math.Max(kj0.BitLength, kj1.BitLength))));
+
+                ECPoint P = ps[i], Q = WNafUtilities.MapPointWithPrecomp(P, width, true, pointMap);
+                infos[j0] = WNafUtilities.GetWNafPreCompInfo(P);
+                infos[j1] = WNafUtilities.GetWNafPreCompInfo(Q);
+                wnafs[j0] = WNafUtilities.GenerateWindowNaf(width, kj0);
+                wnafs[j1] = WNafUtilities.GenerateWindowNaf(width, kj1);
+            }
+
+            return ImplSumOfMultiplies(negs, infos, wnafs);
+        }
+
+        private static ECPoint ImplSumOfMultiplies(bool[] negs, WNafPreCompInfo[] infos, byte[][] wnafs)
+        {
+            int len = 0, count = wnafs.Length;
+            for (int i = 0; i < count; ++i)
+            {
+                len = System.Math.Max(len, wnafs[i].Length);
+            }
+
+            ECCurve curve = infos[0].PreComp[0].Curve;
+            ECPoint infinity = curve.Infinity;
+
+            ECPoint R = infinity;
+            int zeroes = 0;
+
+            for (int i = len - 1; i >= 0; --i)
+            {
+                ECPoint r = infinity;
+
+                for (int j = 0; j < count; ++j)
+                {
+                    byte[] wnaf = wnafs[j];
+                    int wi = i < wnaf.Length ? (int)(sbyte)wnaf[i] : 0;
+                    if (wi != 0)
+                    {
+                        int n = System.Math.Abs(wi);
+                        WNafPreCompInfo info = infos[j];
+                        ECPoint[] table = (wi < 0 == negs[j]) ? info.PreComp : info.PreCompNeg;
+                        r = r.Add(table[n >> 1]);
+                    }
+                }
+
+                if (r == infinity)
+                {
+                    ++zeroes;
+                    continue;
+                }
+
+                if (zeroes > 0)
+                {
+                    R = R.TimesPow2(zeroes);
+                    zeroes = 0;
+                }
+
+                R = R.TwicePlus(r);
+            }
+
+            if (zeroes > 0)
+            {
+                R = R.TimesPow2(zeroes);
+            }
+
+            return R;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ECCurve.cs b/BouncyCastle.AxCrypt/src/math/ec/ECCurve.cs
new file mode 100644
index 0000000..eaa3e0c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ECCurve.cs
@@ -0,0 +1,1111 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Math.EC.Abc;
+using Org.BouncyCastle.Math.EC.Endo;
+using Org.BouncyCastle.Math.EC.Multiplier;
+using Org.BouncyCastle.Math.Field;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    /// <remarks>Base class for an elliptic curve.</remarks>
+    public abstract class ECCurve
+    {
+        public const int COORD_AFFINE = 0;
+        public const int COORD_HOMOGENEOUS = 1;
+        public const int COORD_JACOBIAN = 2;
+        public const int COORD_JACOBIAN_CHUDNOVSKY = 3;
+        public const int COORD_JACOBIAN_MODIFIED = 4;
+        public const int COORD_LAMBDA_AFFINE = 5;
+        public const int COORD_LAMBDA_PROJECTIVE = 6;
+        public const int COORD_SKEWED = 7;
+
+        public static int[] GetAllCoordinateSystems()
+        {
+            return new int[]{ COORD_AFFINE, COORD_HOMOGENEOUS, COORD_JACOBIAN, COORD_JACOBIAN_CHUDNOVSKY,
+                COORD_JACOBIAN_MODIFIED, COORD_LAMBDA_AFFINE, COORD_LAMBDA_PROJECTIVE, COORD_SKEWED };
+        }
+
+        public class Config
+        {
+            protected ECCurve outer;
+            protected int coord;
+            protected ECEndomorphism endomorphism;
+            protected ECMultiplier multiplier;
+
+            internal Config(ECCurve outer, int coord, ECEndomorphism endomorphism, ECMultiplier multiplier)
+            {
+                this.outer = outer;
+                this.coord = coord;
+                this.endomorphism = endomorphism;
+                this.multiplier = multiplier;
+            }
+
+            public Config SetCoordinateSystem(int coord)
+            {
+                this.coord = coord;
+                return this;
+            }
+
+            public Config SetEndomorphism(ECEndomorphism endomorphism)
+            {
+                this.endomorphism = endomorphism;
+                return this;
+            }
+
+            public Config SetMultiplier(ECMultiplier multiplier)
+            {
+                this.multiplier = multiplier;
+                return this;
+            }
+
+            public ECCurve Create()
+            {
+                if (!outer.SupportsCoordinateSystem(coord))
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+
+                ECCurve c = outer.CloneCurve();
+                if (c == outer)
+                {
+                    throw new InvalidOperationException("implementation returned current curve");
+                }
+
+                c.m_coord = coord;
+                c.m_endomorphism = endomorphism;
+                c.m_multiplier = multiplier;
+
+                return c;
+            }
+        }
+
+        protected readonly IFiniteField m_field;
+        protected ECFieldElement m_a, m_b;
+        protected BigInteger m_order, m_cofactor;
+
+        protected int m_coord = COORD_AFFINE;
+        protected ECEndomorphism m_endomorphism = null;
+        protected ECMultiplier m_multiplier = null;
+
+        protected ECCurve(IFiniteField field)
+        {
+            this.m_field = field;
+        }
+
+        public abstract int FieldSize { get; }
+        public abstract ECFieldElement FromBigInteger(BigInteger x);
+
+        public virtual Config Configure()
+        {
+            return new Config(this, this.m_coord, this.m_endomorphism, this.m_multiplier);
+        }
+
+        public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y)
+        {
+            ECPoint p = CreatePoint(x, y);
+            if (!p.IsValid())
+            {
+                throw new ArgumentException("Invalid point coordinates");
+            }
+            return p;
+        }
+
+        [Obsolete("Per-point compression property will be removed")]
+        public virtual ECPoint ValidatePoint(BigInteger x, BigInteger y, bool withCompression)
+        {
+            ECPoint p = CreatePoint(x, y, withCompression);
+            if (!p.IsValid())
+            {
+                throw new ArgumentException("Invalid point coordinates");
+            }
+            return p;
+        }
+
+        public virtual ECPoint CreatePoint(BigInteger x, BigInteger y)
+        {
+            return CreatePoint(x, y, false);
+        }
+
+        [Obsolete("Per-point compression property will be removed")]
+        public virtual ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression)
+        {
+            return CreateRawPoint(FromBigInteger(x), FromBigInteger(y), withCompression);
+        }
+
+        protected abstract ECCurve CloneCurve();
+
+        protected internal abstract ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression);
+
+        protected internal abstract ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression);
+
+        protected virtual ECMultiplier CreateDefaultMultiplier()
+        {
+            GlvEndomorphism glvEndomorphism = m_endomorphism as GlvEndomorphism;
+            if (glvEndomorphism != null)
+            {
+                return new GlvMultiplier(this, glvEndomorphism);
+            }
+
+            return new WNafL2RMultiplier();
+        }
+
+        public virtual bool SupportsCoordinateSystem(int coord)
+        {
+            return coord == COORD_AFFINE;
+        }
+
+        public virtual PreCompInfo GetPreCompInfo(ECPoint point, string name)
+        {
+            CheckPoint(point);
+            lock (point)
+            {
+                IDictionary table = point.m_preCompTable;
+                return table == null ? null : (PreCompInfo)table[name];
+            }
+        }
+
+        /**
+         * Adds <code>PreCompInfo</code> for a point on this curve, under a given name. Used by
+         * <code>ECMultiplier</code>s to save the precomputation for this <code>ECPoint</code> for use
+         * by subsequent multiplication.
+         * 
+         * @param point
+         *            The <code>ECPoint</code> to store precomputations for.
+         * @param name
+         *            A <code>String</code> used to index precomputations of different types.
+         * @param preCompInfo
+         *            The values precomputed by the <code>ECMultiplier</code>.
+         */
+        public virtual void SetPreCompInfo(ECPoint point, string name, PreCompInfo preCompInfo)
+        {
+            CheckPoint(point);
+            lock (point)
+            {
+                IDictionary table = point.m_preCompTable;
+                if (null == table)
+                {
+                    point.m_preCompTable = table = Platform.CreateHashtable(4);
+                }
+                table[name] = preCompInfo;
+            }
+        }
+
+        public virtual ECPoint ImportPoint(ECPoint p)
+        {
+            if (this == p.Curve)
+            {
+                return p;
+            }
+            if (p.IsInfinity)
+            {
+                return Infinity;
+            }
+
+            // TODO Default behaviour could be improved if the two curves have the same coordinate system by copying any Z coordinates.
+            p = p.Normalize();
+
+            return ValidatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), p.IsCompressed);
+        }
+
+        /**
+         * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+         * coordinates reflect those of the equivalent point in an affine coordinate system. Where more
+         * than one point is to be normalized, this method will generally be more efficient than
+         * normalizing each point separately.
+         * 
+         * @param points
+         *            An array of points that will be updated in place with their normalized versions,
+         *            where necessary
+         */
+        public virtual void NormalizeAll(ECPoint[] points)
+        {
+            CheckPoints(points);
+
+            if (this.CoordinateSystem == ECCurve.COORD_AFFINE)
+            {
+                return;
+            }
+
+            /*
+             * Figure out which of the points actually need to be normalized
+             */
+            ECFieldElement[] zs = new ECFieldElement[points.Length];
+            int[] indices = new int[points.Length];
+            int count = 0;
+            for (int i = 0; i < points.Length; ++i)
+            {
+                ECPoint p = points[i];
+                if (null != p && !p.IsNormalized())
+                {
+                    zs[count] = p.GetZCoord(0);
+                    indices[count++] = i;
+                }
+            }
+
+            if (count == 0)
+            {
+                return;
+            }
+
+            ECAlgorithms.MontgomeryTrick(zs, 0, count);
+
+            for (int j = 0; j < count; ++j)
+            {
+                int index = indices[j];
+                points[index] = points[index].Normalize(zs[j]);
+            }
+        }
+
+        public abstract ECPoint Infinity { get; }
+
+        public virtual IFiniteField Field
+        {
+            get { return m_field; }
+        }
+
+        public virtual ECFieldElement A
+        {
+            get { return m_a; }
+        }
+
+        public virtual ECFieldElement B
+        {
+            get { return m_b; }
+        }
+
+        public virtual BigInteger Order
+        {
+            get { return m_order; }
+        }
+
+        public virtual BigInteger Cofactor
+        {
+            get { return m_cofactor; }
+        }
+
+        public virtual int CoordinateSystem
+        {
+            get { return m_coord; }
+        }
+
+        protected virtual void CheckPoint(ECPoint point)
+        {
+            if (null == point || (this != point.Curve))
+                throw new ArgumentException("must be non-null and on this curve", "point");
+        }
+
+        protected virtual void CheckPoints(ECPoint[] points)
+        {
+            if (points == null)
+                throw new ArgumentNullException("points");
+
+            for (int i = 0; i < points.Length; ++i)
+            {
+                ECPoint point = points[i];
+                if (null != point && this != point.Curve)
+                    throw new ArgumentException("entries must be null or on this curve", "points");
+            }
+        }
+
+        public virtual bool Equals(ECCurve other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Field.Equals(other.Field)
+                && A.ToBigInteger().Equals(other.A.ToBigInteger())
+                && B.ToBigInteger().Equals(other.B.ToBigInteger());
+        }
+
+        public override bool Equals(object obj) 
+        {
+            return Equals(obj as ECCurve);
+        }
+
+        public override int GetHashCode()
+        {
+            return Field.GetHashCode()
+                ^ Integers.RotateLeft(A.ToBigInteger().GetHashCode(), 8)
+                ^ Integers.RotateLeft(B.ToBigInteger().GetHashCode(), 16);
+        }
+
+        protected abstract ECPoint DecompressPoint(int yTilde, BigInteger X1);
+
+        public virtual ECEndomorphism GetEndomorphism()
+        {
+            return m_endomorphism;
+        }
+
+        /**
+         * Sets the default <code>ECMultiplier</code>, unless already set. 
+         */
+        public virtual ECMultiplier GetMultiplier()
+        {
+            lock (this)
+            {
+                if (this.m_multiplier == null)
+                {
+                    this.m_multiplier = CreateDefaultMultiplier();
+                }
+                return this.m_multiplier;
+            }
+        }
+
+        /**
+         * Decode a point on this curve from its ASN.1 encoding. The different
+         * encodings are taken account of, including point compression for
+         * <code>F<sub>p</sub></code> (X9.62 s 4.2.1 pg 17).
+         * @return The decoded point.
+         */
+        public virtual ECPoint DecodePoint(byte[] encoded)
+        {
+            ECPoint p = null;
+            int expectedLength = (FieldSize + 7) / 8;
+
+            byte type = encoded[0];
+            switch (type)
+            {
+                case 0x00: // infinity
+                {
+                    if (encoded.Length != 1)
+                        throw new ArgumentException("Incorrect length for infinity encoding", "encoded");
+
+                    p = Infinity;
+                    break;
+                }
+
+                case 0x02: // compressed
+                case 0x03: // compressed
+                {
+                    if (encoded.Length != (expectedLength + 1))
+                        throw new ArgumentException("Incorrect length for compressed encoding", "encoded");
+
+                    int yTilde = type & 1;
+                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+
+                    p = DecompressPoint(yTilde, X);
+                    if (!p.SatisfiesCofactor())
+                        throw new ArgumentException("Invalid point");
+
+                    break;
+                }
+
+                case 0x04: // uncompressed
+                {
+                    if (encoded.Length != (2 * expectedLength + 1))
+                        throw new ArgumentException("Incorrect length for uncompressed encoding", "encoded");
+
+                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+                    BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
+
+                    p = ValidatePoint(X, Y);
+                    break;
+                }
+
+                case 0x06: // hybrid
+                case 0x07: // hybrid
+                {
+                    if (encoded.Length != (2 * expectedLength + 1))
+                        throw new ArgumentException("Incorrect length for hybrid encoding", "encoded");
+
+                    BigInteger X = new BigInteger(1, encoded, 1, expectedLength);
+                    BigInteger Y = new BigInteger(1, encoded, 1 + expectedLength, expectedLength);
+
+                    if (Y.TestBit(0) != (type == 0x07))
+                        throw new ArgumentException("Inconsistent Y coordinate in hybrid encoding", "encoded");
+
+                    p = ValidatePoint(X, Y);
+                    break;
+                }
+
+                default:
+                    throw new FormatException("Invalid point encoding " + type);
+            }
+
+            if (type != 0x00 && p.IsInfinity)
+                throw new ArgumentException("Invalid infinity encoding", "encoded");
+
+            return p;
+        }
+    }
+
+    public abstract class AbstractFpCurve
+        : ECCurve
+    {
+        protected AbstractFpCurve(BigInteger q)
+            : base(FiniteFields.GetPrimeField(q))
+        {
+        }
+
+        protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+        {
+            ECFieldElement x = FromBigInteger(X1);
+            ECFieldElement rhs = x.Square().Add(A).Multiply(x).Add(B);
+            ECFieldElement y = rhs.Sqrt();
+
+            /*
+             * If y is not a square, then we haven't got a point on the curve
+             */
+            if (y == null)
+                throw new ArgumentException("Invalid point compression");
+
+            if (y.TestBitZero() != (yTilde == 1))
+            {
+                // Use the other root
+                y = y.Negate();
+            }
+
+            return CreateRawPoint(x, y, true);
+        }
+    }
+
+    /**
+     * Elliptic curve over Fp
+     */
+    public class FpCurve
+        : AbstractFpCurve
+    {
+        private const int FP_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+
+        protected readonly BigInteger m_q, m_r;
+        protected readonly FpPoint m_infinity;
+
+        public FpCurve(BigInteger q, BigInteger a, BigInteger b)
+            : this(q, a, b, null, null)
+        {
+        }
+
+        public FpCurve(BigInteger q, BigInteger a, BigInteger b, BigInteger order, BigInteger cofactor)
+            : base(q)
+        {
+            this.m_q = q;
+            this.m_r = FpFieldElement.CalculateResidue(q);
+            this.m_infinity = new FpPoint(this, null, null);
+
+            this.m_a = FromBigInteger(a);
+            this.m_b = FromBigInteger(b);
+            this.m_order = order;
+            this.m_cofactor = cofactor;
+            this.m_coord = FP_DEFAULT_COORDS;
+        }
+
+        protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b)
+            : this(q, r, a, b, null, null)
+        {
+        }
+
+        protected FpCurve(BigInteger q, BigInteger r, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
+            : base(q)
+        {
+            this.m_q = q;
+            this.m_r = r;
+            this.m_infinity = new FpPoint(this, null, null);
+
+            this.m_a = a;
+            this.m_b = b;
+            this.m_order = order;
+            this.m_cofactor = cofactor;
+            this.m_coord = FP_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new FpCurve(m_q, m_r, m_a, m_b, m_order, m_cofactor);
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_AFFINE:
+                case COORD_HOMOGENEOUS:
+                case COORD_JACOBIAN:
+                case COORD_JACOBIAN_MODIFIED:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return m_q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return m_q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new FpFieldElement(this.m_q, this.m_r, x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new FpPoint(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new FpPoint(this, x, y, zs, withCompression);
+        }
+
+        public override ECPoint ImportPoint(ECPoint p)
+        {
+            if (this != p.Curve && this.CoordinateSystem == COORD_JACOBIAN && !p.IsInfinity)
+            {
+                switch (p.Curve.CoordinateSystem)
+                {
+                    case COORD_JACOBIAN:
+                    case COORD_JACOBIAN_CHUDNOVSKY:
+                    case COORD_JACOBIAN_MODIFIED:
+                        return new FpPoint(this,
+                            FromBigInteger(p.RawXCoord.ToBigInteger()),
+                            FromBigInteger(p.RawYCoord.ToBigInteger()),
+                            new ECFieldElement[] { FromBigInteger(p.GetZCoord(0).ToBigInteger()) },
+                            p.IsCompressed);
+                    default:
+                        break;
+                }
+            }
+
+            return base.ImportPoint(p);
+        }
+    }
+
+    public abstract class AbstractF2mCurve
+        : ECCurve
+    {
+        private static IFiniteField BuildField(int m, int k1, int k2, int k3)
+        {
+            if (k1 == 0)
+            {
+                throw new ArgumentException("k1 must be > 0");
+            }
+
+            if (k2 == 0)
+            {
+                if (k3 != 0)
+                {
+                    throw new ArgumentException("k3 must be 0 if k2 == 0");
+                }
+
+                return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, m });
+            }
+
+            if (k2 <= k1)
+            {
+                throw new ArgumentException("k2 must be > k1");
+            }
+
+            if (k3 <= k2)
+            {
+                throw new ArgumentException("k3 must be > k2");
+            }
+
+            return FiniteFields.GetBinaryExtensionField(new int[]{ 0, k1, k2, k3, m });
+        }
+
+        protected AbstractF2mCurve(int m, int k1, int k2, int k3)
+            : base(BuildField(m, k1, k2, k3))
+        {
+        }
+    }
+
+    /**
+     * Elliptic curves over F2m. The Weierstrass equation is given by
+     * <code>y<sup>2</sup> + xy = x<sup>3</sup> + ax<sup>2</sup> + b</code>.
+     */
+    public class F2mCurve
+        : AbstractF2mCurve
+    {
+        private const int F2M_DEFAULT_COORDS = COORD_LAMBDA_PROJECTIVE;
+
+        /**
+         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+         */
+        private readonly int m;
+
+        /**
+         * TPB: The integer <code>k</code> where <code>x<sup>m</sup> +
+         * x<sup>k</sup> + 1</code> represents the reduction polynomial
+         * <code>f(z)</code>.<br/>
+         * PPB: The integer <code>k1</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.<br/>
+         */
+        private readonly int k1;
+
+        /**
+         * TPB: Always set to <code>0</code><br/>
+         * PPB: The integer <code>k2</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.<br/>
+         */
+        private readonly int k2;
+
+        /**
+         * TPB: Always set to <code>0</code><br/>
+         * PPB: The integer <code>k3</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.<br/>
+         */
+        private readonly int k3;
+
+        /**
+         * The point at infinity on this curve.
+         */
+        protected readonly F2mPoint m_infinity;
+
+        /**
+         * The parameter <code>μ</code> of the elliptic curve if this is
+         * a Koblitz curve.
+         */
+        private sbyte mu = 0;
+
+        /**
+         * The auxiliary values <code>s<sub>0</sub></code> and
+         * <code>s<sub>1</sub></code> used for partial modular reduction for
+         * Koblitz curves.
+         */
+        private BigInteger[] si = null;
+
+        /**
+         * Constructor for Trinomial Polynomial Basis (TPB).
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+         * x<sup>k</sup> + 1</code> represents the reduction
+         * polynomial <code>f(z)</code>.
+         * @param a The coefficient <code>a</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param b The coefficient <code>b</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         */
+        public F2mCurve(
+            int			m,
+            int			k,
+            BigInteger	a,
+            BigInteger	b)
+            : this(m, k, 0, 0, a, b, null, null)
+        {
+        }
+
+        /**
+         * Constructor for Trinomial Polynomial Basis (TPB).
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+         * x<sup>k</sup> + 1</code> represents the reduction
+         * polynomial <code>f(z)</code>.
+         * @param a The coefficient <code>a</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param b The coefficient <code>b</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param order The order of the main subgroup of the elliptic curve.
+         * @param cofactor The cofactor of the elliptic curve, i.e.
+         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+         */
+        public F2mCurve(
+            int			m, 
+            int			k, 
+            BigInteger	a, 
+            BigInteger	b,
+            BigInteger	order,
+            BigInteger	cofactor)
+            : this(m, k, 0, 0, a, b, order, cofactor)
+        {
+        }
+
+        /**
+         * Constructor for Pentanomial Polynomial Basis (PPB).
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param a The coefficient <code>a</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param b The coefficient <code>b</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         */
+        public F2mCurve(
+            int			m,
+            int			k1,
+            int			k2,
+            int			k3,
+            BigInteger	a,
+            BigInteger	b)
+            : this(m, k1, k2, k3, a, b, null, null)
+        {
+        }
+
+        /**
+         * Constructor for Pentanomial Polynomial Basis (PPB).
+         * @param m  The exponent <code>m</code> of
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+         * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+         * represents the reduction polynomial <code>f(z)</code>.
+         * @param a The coefficient <code>a</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param b The coefficient <code>b</code> in the Weierstrass equation
+         * for non-supersingular elliptic curves over
+         * <code>F<sub>2<sup>m</sup></sub></code>.
+         * @param order The order of the main subgroup of the elliptic curve.
+         * @param cofactor The cofactor of the elliptic curve, i.e.
+         * <code>#E<sub>a</sub>(F<sub>2<sup>m</sup></sub>) = h * n</code>.
+         */
+        public F2mCurve(
+            int			m, 
+            int			k1, 
+            int			k2, 
+            int			k3,
+            BigInteger	a, 
+            BigInteger	b,
+            BigInteger	order,
+            BigInteger	cofactor)
+            : base(m, k1, k2, k3)
+        {
+            this.m = m;
+            this.k1 = k1;
+            this.k2 = k2;
+            this.k3 = k3;
+            this.m_order = order;
+            this.m_cofactor = cofactor;
+            this.m_infinity = new F2mPoint(this, null, null);
+
+            if (k1 == 0)
+                throw new ArgumentException("k1 must be > 0");
+
+            if (k2 == 0)
+            {
+                if (k3 != 0)
+                    throw new ArgumentException("k3 must be 0 if k2 == 0");
+            }
+            else
+            {
+                if (k2 <= k1)
+                    throw new ArgumentException("k2 must be > k1");
+
+                if (k3 <= k2)
+                    throw new ArgumentException("k3 must be > k2");
+            }
+
+            this.m_a = FromBigInteger(a);
+            this.m_b = FromBigInteger(b);
+            this.m_coord = F2M_DEFAULT_COORDS;
+        }
+
+        protected F2mCurve(int m, int k1, int k2, int k3, ECFieldElement a, ECFieldElement b, BigInteger order, BigInteger cofactor)
+            : base(m, k1, k2, k3)
+        {
+            this.m = m;
+            this.k1 = k1;
+            this.k2 = k2;
+            this.k3 = k3;
+            this.m_order = order;
+            this.m_cofactor = cofactor;
+
+            this.m_infinity = new F2mPoint(this, null, null);
+            this.m_a = a;
+            this.m_b = b;
+            this.m_coord = F2M_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new F2mCurve(m, k1, k2, k3, m_a, m_b, m_order, m_cofactor);
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_AFFINE:
+                case COORD_HOMOGENEOUS:
+                case COORD_LAMBDA_PROJECTIVE:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        protected override ECMultiplier CreateDefaultMultiplier()
+        {
+            if (IsKoblitz)
+            {
+                return new WTauNafMultiplier();
+            }
+
+            return base.CreateDefaultMultiplier();
+        }
+
+        public override int FieldSize
+        {
+            get { return m; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new F2mFieldElement(this.m, this.k1, this.k2, this.k3, x);
+        }
+
+        [Obsolete("Per-point compression property will be removed")]
+        public override ECPoint CreatePoint(BigInteger x, BigInteger y, bool withCompression)
+        {
+            ECFieldElement X = FromBigInteger(x), Y = FromBigInteger(y);
+
+            switch (this.CoordinateSystem)
+            {
+                case COORD_LAMBDA_AFFINE:
+                case COORD_LAMBDA_PROJECTIVE:
+                    {
+                        if (X.IsZero)
+                        {
+                            if (!Y.Square().Equals(B))
+                                throw new ArgumentException();
+                        }
+                        else
+                        {
+                            // Y becomes Lambda (X + Y/X) here
+                            Y = Y.Divide(X).Add(X);
+                        }
+                        break;
+                    }
+                default:
+                    {
+                        break;
+                    }
+            }
+
+            return CreateRawPoint(X, Y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new F2mPoint(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new F2mPoint(this, x, y, zs, withCompression);
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        /**
+         * Returns true if this is a Koblitz curve (ABC curve).
+         * @return true if this is a Koblitz curve (ABC curve), false otherwise
+         */
+        public virtual bool IsKoblitz
+        {
+            get
+            {
+                return m_order != null && m_cofactor != null && m_b.IsOne && (m_a.IsZero || m_a.IsOne);
+            }
+        }
+
+        /**
+         * Returns the parameter <code>μ</code> of the elliptic curve.
+         * @return <code>μ</code> of the elliptic curve.
+         * @throws ArgumentException if the given ECCurve is not a
+         * Koblitz curve.
+         */
+        internal virtual sbyte GetMu()
+        {
+            if (mu == 0)
+            {
+                lock (this)
+                {
+                    if (mu == 0)
+                    {
+                        mu = Tnaf.GetMu(this);
+                    }
+                }
+            }
+
+            return mu;
+        }
+
+        /**
+         * @return the auxiliary values <code>s<sub>0</sub></code> and
+         * <code>s<sub>1</sub></code> used for partial modular reduction for
+         * Koblitz curves.
+         */
+        internal virtual BigInteger[] GetSi()
+        {
+            if (si == null)
+            {
+                lock (this)
+                {
+                    if (si == null)
+                    {
+                        si = Tnaf.GetSi(this);
+                    }
+                }
+            }
+            return si;
+        }
+
+        protected override ECPoint DecompressPoint(int yTilde, BigInteger X1)
+        {
+            ECFieldElement xp = FromBigInteger(X1), yp = null;
+            if (xp.IsZero)
+            {
+                yp = m_b.Sqrt();
+            }
+            else
+            {
+                ECFieldElement beta = xp.Square().Invert().Multiply(B).Add(A).Add(xp);
+                ECFieldElement z = SolveQuadradicEquation(beta);
+
+                if (z != null)
+                {
+                    if (z.TestBitZero() != (yTilde == 1))
+                    {
+                        z = z.AddOne();
+                    }
+
+                    switch (this.CoordinateSystem)
+                    {
+                        case COORD_LAMBDA_AFFINE:
+                        case COORD_LAMBDA_PROJECTIVE:
+                        {
+                            yp = z.Add(xp);
+                            break;
+                        }
+                        default:
+                        {
+                            yp = z.Multiply(xp);
+                            break;
+                        }
+                    }
+                }
+            }
+
+            if (yp == null)
+                throw new ArgumentException("Invalid point compression");
+
+            return CreateRawPoint(xp, yp, true);
+        }
+
+        /**
+         * Solves a quadratic equation <code>z<sup>2</sup> + z = beta</code>(X9.62
+         * D.1.6) The other solution is <code>z + 1</code>.
+         *
+         * @param beta
+         *            The value to solve the qradratic equation for.
+         * @return the solution for <code>z<sup>2</sup> + z = beta</code> or
+         *         <code>null</code> if no solution exists.
+         */
+        private ECFieldElement SolveQuadradicEquation(ECFieldElement beta)
+        {
+            if (beta.IsZero)
+            {
+                return beta;
+            }
+
+            ECFieldElement zeroElement = FromBigInteger(BigInteger.Zero);
+
+            ECFieldElement z = null;
+            ECFieldElement gamma = null;
+
+            Random rand = new Random();
+            do
+            {
+                ECFieldElement t = FromBigInteger(new BigInteger(m, rand));
+                z = zeroElement;
+                ECFieldElement w = beta;
+                for (int i = 1; i <= m - 1; i++)
+                {
+                    ECFieldElement w2 = w.Square();
+                    z = z.Square().Add(w2.Multiply(t));
+                    w = w2.Add(beta);
+                }
+                if (!w.IsZero)
+                {
+                    return null;
+                }
+                gamma = z.Square().Add(z);
+            }
+            while (gamma.IsZero);
+
+            return z;
+        }
+
+        public int M
+        {
+            get { return m; }
+        }
+
+        /**
+         * Return true if curve uses a Trinomial basis.
+         *
+         * @return true if curve Trinomial, false otherwise.
+         */
+        public bool IsTrinomial()
+        {
+            return k2 == 0 && k3 == 0;
+        }
+
+        public int K1
+        {
+            get { return k1; }
+        }
+
+        public int K2
+        {
+            get { return k2; }
+        }
+
+        public int K3
+        {
+            get { return k3; }
+        }
+
+        [Obsolete("Use 'Order' property instead")]
+        public BigInteger N
+        {
+            get { return m_order; }
+        }
+
+        [Obsolete("Use 'Cofactor' property instead")]
+        public BigInteger H
+        {
+            get { return m_cofactor; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ECFieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/ECFieldElement.cs
new file mode 100644
index 0000000..e589fc7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ECFieldElement.cs
@@ -0,0 +1,917 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public abstract class ECFieldElement
+    {
+        public abstract BigInteger ToBigInteger();
+        public abstract string FieldName { get; }
+        public abstract int FieldSize { get; }
+        public abstract ECFieldElement Add(ECFieldElement b);
+        public abstract ECFieldElement AddOne();
+        public abstract ECFieldElement Subtract(ECFieldElement b);
+        public abstract ECFieldElement Multiply(ECFieldElement b);
+        public abstract ECFieldElement Divide(ECFieldElement b);
+        public abstract ECFieldElement Negate();
+        public abstract ECFieldElement Square();
+        public abstract ECFieldElement Invert();
+        public abstract ECFieldElement Sqrt();
+
+        public virtual int BitLength
+        {
+            get { return ToBigInteger().BitLength; }
+        }
+
+        public virtual bool IsOne
+        {
+            get { return BitLength == 1; }
+        }
+
+        public virtual bool IsZero
+        {
+            get { return 0 == ToBigInteger().SignValue; }
+        }
+
+        public virtual ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            return Multiply(b).Subtract(x.Multiply(y));
+        }
+
+        public virtual ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            return Multiply(b).Add(x.Multiply(y));
+        }
+
+        public virtual ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            return Square().Subtract(x.Multiply(y));
+        }
+
+        public virtual ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            return Square().Add(x.Multiply(y));
+        }
+
+        public virtual bool TestBitZero()
+        {
+            return ToBigInteger().TestBit(0);
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as ECFieldElement);
+        }
+
+        public virtual bool Equals(ECFieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return ToBigInteger().Equals(other.ToBigInteger());
+        }
+
+        public override int GetHashCode()
+        {
+            return ToBigInteger().GetHashCode();
+        }
+
+        public override string ToString()
+        {
+            return this.ToBigInteger().ToString(16);
+        }
+
+        public virtual byte[] GetEncoded()
+        {
+            return BigIntegers.AsUnsignedByteArray((FieldSize + 7) / 8, ToBigInteger());
+        }
+    }
+
+    public class FpFieldElement
+        : ECFieldElement
+    {
+        private readonly BigInteger q, r, x;
+
+        internal static BigInteger CalculateResidue(BigInteger p)
+        {
+            int bitLength = p.BitLength;
+            if (bitLength >= 96)
+            {
+                BigInteger firstWord = p.ShiftRight(bitLength - 64);
+                if (firstWord.LongValue == -1L)
+                {
+                    return BigInteger.One.ShiftLeft(bitLength).Subtract(p);
+                }
+                if ((bitLength & 7) == 0)
+                {
+                    return BigInteger.One.ShiftLeft(bitLength << 1).Divide(p).Negate();
+                }
+            }
+            return null;
+        }
+
+        [Obsolete("Use ECCurve.FromBigInteger to construct field elements")]
+        public FpFieldElement(BigInteger q, BigInteger x)
+            : this(q, CalculateResidue(q), x)
+        {
+        }
+
+        internal FpFieldElement(BigInteger q, BigInteger r, BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(q) >= 0)
+                throw new ArgumentException("value invalid in Fp field element", "x");
+
+            this.q = q;
+            this.r = r;
+            this.x = x;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return x;
+        }
+
+        /**
+         * return the field name for this field.
+         *
+         * @return the string "Fp".
+         */
+        public override string FieldName
+        {
+            get { return "Fp"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECFieldElement Add(
+            ECFieldElement b)
+        {
+            return new FpFieldElement(q, r, ModAdd(x, b.ToBigInteger()));
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            BigInteger x2 = x.Add(BigInteger.One);
+            if (x2.CompareTo(q) == 0)
+            {
+                x2 = BigInteger.Zero;
+            }
+            return new FpFieldElement(q, r, x2);
+        }
+
+        public override ECFieldElement Subtract(
+            ECFieldElement b)
+        {
+            return new FpFieldElement(q, r, ModSubtract(x, b.ToBigInteger()));
+        }
+
+        public override ECFieldElement Multiply(
+            ECFieldElement b)
+        {
+            return new FpFieldElement(q, r, ModMult(x, b.ToBigInteger()));
+        }
+
+        public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
+            BigInteger ab = ax.Multiply(bx);
+            BigInteger xy = xx.Multiply(yx);
+            return new FpFieldElement(q, r, ModReduce(ab.Subtract(xy)));
+        }
+
+        public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            BigInteger ax = this.x, bx = b.ToBigInteger(), xx = x.ToBigInteger(), yx = y.ToBigInteger();
+            BigInteger ab = ax.Multiply(bx);
+            BigInteger xy = xx.Multiply(yx);
+            BigInteger sum = ab.Add(xy);
+            if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
+            {
+                sum = sum.Subtract(q.ShiftLeft(q.BitLength));
+            }
+            return new FpFieldElement(q, r, ModReduce(sum));
+        }
+
+        public override ECFieldElement Divide(
+            ECFieldElement b)
+        {
+            return new FpFieldElement(q, r, ModMult(x, ModInverse(b.ToBigInteger())));
+        }
+
+        public override ECFieldElement Negate()
+        {
+            return x.SignValue == 0 ? this : new FpFieldElement(q, r, q.Subtract(x));
+        }
+
+        public override ECFieldElement Square()
+        {
+            return new FpFieldElement(q, r, ModMult(x, x));
+        }
+
+        public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
+            BigInteger aa = ax.Multiply(ax);
+            BigInteger xy = xx.Multiply(yx);
+            return new FpFieldElement(q, r, ModReduce(aa.Subtract(xy)));
+        }
+
+        public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            BigInteger ax = this.x, xx = x.ToBigInteger(), yx = y.ToBigInteger();
+            BigInteger aa = ax.Multiply(ax);
+            BigInteger xy = xx.Multiply(yx);
+            BigInteger sum = aa.Add(xy);
+            if (r != null && r.SignValue < 0 && sum.BitLength > (q.BitLength << 1))
+            {
+                sum = sum.Subtract(q.ShiftLeft(q.BitLength));
+            }
+            return new FpFieldElement(q, r, ModReduce(sum));
+        }
+
+        public override ECFieldElement Invert()
+        {
+            // TODO Modular inversion can be faster for a (Generalized) Mersenne Prime.
+            return new FpFieldElement(q, r, ModInverse(x));
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation
+         * returns the right value - if none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            if (IsZero || IsOne)
+                return this;
+
+            if (!q.TestBit(0))
+                throw Platform.CreateNotImplementedException("even value of q");
+
+            if (q.TestBit(1)) // q == 4m + 3
+            {
+                BigInteger e = q.ShiftRight(2).Add(BigInteger.One);
+                return CheckSqrt(new FpFieldElement(q, r, x.ModPow(e, q)));
+            }
+
+            if (q.TestBit(2)) // q == 8m + 5
+            {
+                BigInteger t1 = x.ModPow(q.ShiftRight(3), q);
+                BigInteger t2 = ModMult(t1, x);
+                BigInteger t3 = ModMult(t2, t1);
+
+                if (t3.Equals(BigInteger.One))
+                {
+                    return CheckSqrt(new FpFieldElement(q, r, t2));
+                }
+
+                // TODO This is constant and could be precomputed
+                BigInteger t4 = BigInteger.Two.ModPow(q.ShiftRight(2), q);
+
+                BigInteger y = ModMult(t2, t4);
+
+                return CheckSqrt(new FpFieldElement(q, r, y));
+            }
+
+            // q == 8m + 1
+
+            BigInteger legendreExponent = q.ShiftRight(1);
+            if (!(x.ModPow(legendreExponent, q).Equals(BigInteger.One)))
+                return null;
+
+            BigInteger X = this.x;
+            BigInteger fourX = ModDouble(ModDouble(X)); ;
+
+            BigInteger k = legendreExponent.Add(BigInteger.One), qMinusOne = q.Subtract(BigInteger.One);
+
+            BigInteger U, V;
+            Random rand = new Random();
+            do
+            {
+                BigInteger P;
+                do
+                {
+                    P = new BigInteger(q.BitLength, rand);
+                }
+                while (P.CompareTo(q) >= 0
+                    || !ModReduce(P.Multiply(P).Subtract(fourX)).ModPow(legendreExponent, q).Equals(qMinusOne));
+
+                BigInteger[] result = LucasSequence(P, X, k);
+                U = result[0];
+                V = result[1];
+
+                if (ModMult(V, V).Equals(fourX))
+                {
+                    return new FpFieldElement(q, r, ModHalfAbs(V));
+                }
+            }
+            while (U.Equals(BigInteger.One) || U.Equals(qMinusOne));
+
+            return null;
+        }
+
+        private ECFieldElement CheckSqrt(ECFieldElement z)
+        {
+            return z.Square().Equals(this) ? z : null;
+        }
+
+        private BigInteger[] LucasSequence(
+            BigInteger	P,
+            BigInteger	Q,
+            BigInteger	k)
+        {
+            // TODO Research and apply "common-multiplicand multiplication here"
+
+            int n = k.BitLength;
+            int s = k.GetLowestSetBit();
+
+            Debug.Assert(k.TestBit(s));
+
+            BigInteger Uh = BigInteger.One;
+            BigInteger Vl = BigInteger.Two;
+            BigInteger Vh = P;
+            BigInteger Ql = BigInteger.One;
+            BigInteger Qh = BigInteger.One;
+
+            for (int j = n - 1; j >= s + 1; --j)
+            {
+                Ql = ModMult(Ql, Qh);
+
+                if (k.TestBit(j))
+                {
+                    Qh = ModMult(Ql, Q);
+                    Uh = ModMult(Uh, Vh);
+                    Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
+                    Vh = ModReduce(Vh.Multiply(Vh).Subtract(Qh.ShiftLeft(1)));
+                }
+                else
+                {
+                    Qh = Ql;
+                    Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
+                    Vh = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
+                    Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
+                }
+            }
+
+            Ql = ModMult(Ql, Qh);
+            Qh = ModMult(Ql, Q);
+            Uh = ModReduce(Uh.Multiply(Vl).Subtract(Ql));
+            Vl = ModReduce(Vh.Multiply(Vl).Subtract(P.Multiply(Ql)));
+            Ql = ModMult(Ql, Qh);
+
+            for (int j = 1; j <= s; ++j)
+            {
+                Uh = ModMult(Uh, Vl);
+                Vl = ModReduce(Vl.Multiply(Vl).Subtract(Ql.ShiftLeft(1)));
+                Ql = ModMult(Ql, Ql);
+            }
+
+            return new BigInteger[] { Uh, Vl };
+        }
+
+        protected virtual BigInteger ModAdd(BigInteger x1, BigInteger x2)
+        {
+            BigInteger x3 = x1.Add(x2);
+            if (x3.CompareTo(q) >= 0)
+            {
+                x3 = x3.Subtract(q);
+            }
+            return x3;
+        }
+
+        protected virtual BigInteger ModDouble(BigInteger x)
+        {
+            BigInteger _2x = x.ShiftLeft(1);
+            if (_2x.CompareTo(q) >= 0)
+            {
+                _2x = _2x.Subtract(q);
+            }
+            return _2x;
+        }
+
+        protected virtual BigInteger ModHalf(BigInteger x)
+        {
+            if (x.TestBit(0))
+            {
+                x = q.Add(x);
+            }
+            return x.ShiftRight(1);
+        }
+
+        protected virtual BigInteger ModHalfAbs(BigInteger x)
+        {
+            if (x.TestBit(0))
+            {
+                x = q.Subtract(x);
+            }
+            return x.ShiftRight(1);
+        }
+
+        protected virtual BigInteger ModInverse(BigInteger x)
+        {
+            int bits = FieldSize;
+            int len = (bits + 31) >> 5;
+            uint[] p = Nat.FromBigInteger(bits, q);
+            uint[] n = Nat.FromBigInteger(bits, x);
+            uint[] z = Nat.Create(len);
+            Mod.Invert(p, n, z);
+            return Nat.ToBigInteger(len, z);
+        }
+
+        protected virtual BigInteger ModMult(BigInteger x1, BigInteger x2)
+        {
+            return ModReduce(x1.Multiply(x2));
+        }
+
+        protected virtual BigInteger ModReduce(BigInteger x)
+        {
+            if (r == null)
+            {
+                x = x.Mod(q);
+            }
+            else
+            {
+                bool negative = x.SignValue < 0;
+                if (negative)
+                {
+                    x = x.Abs();
+                }
+                int qLen = q.BitLength;
+                if (r.SignValue > 0)
+                {
+                    BigInteger qMod = BigInteger.One.ShiftLeft(qLen);
+                    bool rIsOne = r.Equals(BigInteger.One);
+                    while (x.BitLength > (qLen + 1))
+                    {
+                        BigInteger u = x.ShiftRight(qLen);
+                        BigInteger v = x.Remainder(qMod);
+                        if (!rIsOne)
+                        {
+                            u = u.Multiply(r);
+                        }
+                        x = u.Add(v);
+                    }
+                }
+                else
+                {
+                    int d = ((qLen - 1) & 31) + 1;
+                    BigInteger mu = r.Negate();
+                    BigInteger u = mu.Multiply(x.ShiftRight(qLen - d));
+                    BigInteger quot = u.ShiftRight(qLen + d);
+                    BigInteger v = quot.Multiply(q);
+                    BigInteger bk1 = BigInteger.One.ShiftLeft(qLen + d);
+                    v = v.Remainder(bk1);
+                    x = x.Remainder(bk1);
+                    x = x.Subtract(v);
+                    if (x.SignValue < 0)
+                    {
+                        x = x.Add(bk1);
+                    }
+                }
+                while (x.CompareTo(q) >= 0)
+                {
+                    x = x.Subtract(q);
+                }
+                if (negative && x.SignValue != 0)
+                {
+                    x = q.Subtract(x);
+                }
+            }
+            return x;
+        }
+
+        protected virtual BigInteger ModSubtract(BigInteger x1, BigInteger x2)
+        {
+            BigInteger x3 = x1.Subtract(x2);
+            if (x3.SignValue < 0)
+            {
+                x3 = x3.Add(q);
+            }
+            return x3;
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            FpFieldElement other = obj as FpFieldElement;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        public virtual bool Equals(
+            FpFieldElement other)
+        {
+            return q.Equals(other.q) && base.Equals(other);
+        }
+
+        public override int GetHashCode()
+        {
+            return q.GetHashCode() ^ base.GetHashCode();
+        }
+    }
+
+    /**
+     * Class representing the Elements of the finite field
+     * <code>F<sub>2<sup>m</sup></sub></code> in polynomial basis (PB)
+     * representation. Both trinomial (Tpb) and pentanomial (Ppb) polynomial
+     * basis representations are supported. Gaussian normal basis (GNB)
+     * representation is not supported.
+     */
+    public class F2mFieldElement
+        : ECFieldElement
+    {
+        /**
+         * Indicates gaussian normal basis representation (GNB). Number chosen
+         * according to X9.62. GNB is not implemented at present.
+         */
+        public const int Gnb = 1;
+
+        /**
+         * Indicates trinomial basis representation (Tpb). Number chosen
+         * according to X9.62.
+         */
+        public const int Tpb = 2;
+
+        /**
+         * Indicates pentanomial basis representation (Ppb). Number chosen
+         * according to X9.62.
+         */
+        public const int Ppb = 3;
+
+        /**
+         * Tpb or Ppb.
+         */
+        private int representation;
+
+        /**
+         * The exponent <code>m</code> of <code>F<sub>2<sup>m</sup></sub></code>.
+         */
+        private int m;
+
+        private int[] ks;
+
+        /**
+         * The <code>LongArray</code> holding the bits.
+         */
+        private LongArray x;
+
+        /**
+            * Constructor for Ppb.
+            * @param m  The exponent <code>m</code> of
+            * <code>F<sub>2<sup>m</sup></sub></code>.
+            * @param k1 The integer <code>k1</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.
+            * @param k2 The integer <code>k2</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.
+            * @param k3 The integer <code>k3</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.
+            * @param x The BigInteger representing the value of the field element.
+            */
+        public F2mFieldElement(
+            int			m,
+            int			k1,
+            int			k2,
+            int			k3,
+            BigInteger	x)
+        {
+            if ((k2 == 0) && (k3 == 0))
+            {
+                this.representation = Tpb;
+                this.ks = new int[] { k1 };
+            }
+            else
+            {
+                if (k2 >= k3)
+                    throw new ArgumentException("k2 must be smaller than k3");
+                if (k2 <= 0)
+                    throw new ArgumentException("k2 must be larger than 0");
+
+                this.representation = Ppb;
+                this.ks = new int[] { k1, k2, k3 };
+            }
+
+            this.m = m;
+            this.x = new LongArray(x);
+        }
+
+        /**
+            * Constructor for Tpb.
+            * @param m  The exponent <code>m</code> of
+            * <code>F<sub>2<sup>m</sup></sub></code>.
+            * @param k The integer <code>k</code> where <code>x<sup>m</sup> +
+            * x<sup>k</sup> + 1</code> represents the reduction
+            * polynomial <code>f(z)</code>.
+            * @param x The BigInteger representing the value of the field element.
+            */
+        public F2mFieldElement(
+            int			m,
+            int			k,
+            BigInteger	x)
+            : this(m, k, 0, 0, x)
+        {
+            // Set k1 to k, and set k2 and k3 to 0
+        }
+
+        private F2mFieldElement(int m, int[] ks, LongArray x)
+        {
+            this.m = m;
+            this.representation = (ks.Length == 1) ? Tpb : Ppb;
+            this.ks = ks;
+            this.x = x;
+        }
+
+        public override int BitLength
+        {
+            get { return x.Degree(); }
+        }
+
+        public override bool IsOne
+        {
+            get { return x.IsOne(); }
+        }
+
+        public override bool IsZero
+        {
+            get { return x.IsZero(); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return x.TestBitZero();
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return x.ToBigInteger();
+        }
+
+        public override string FieldName
+        {
+            get { return "F2m"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return m; }
+        }
+
+        /**
+        * Checks, if the ECFieldElements <code>a</code> and <code>b</code>
+        * are elements of the same field <code>F<sub>2<sup>m</sup></sub></code>
+        * (having the same representation).
+        * @param a field element.
+        * @param b field element to be compared.
+        * @throws ArgumentException if <code>a</code> and <code>b</code>
+        * are not elements of the same field
+        * <code>F<sub>2<sup>m</sup></sub></code> (having the same
+        * representation).
+        */
+        public static void CheckFieldElements(
+            ECFieldElement	a,
+            ECFieldElement	b)
+        {
+            if (!(a is F2mFieldElement) || !(b is F2mFieldElement))
+            {
+                throw new ArgumentException("Field elements are not "
+                    + "both instances of F2mFieldElement");
+            }
+
+            F2mFieldElement aF2m = (F2mFieldElement)a;
+            F2mFieldElement bF2m = (F2mFieldElement)b;
+
+            if (aF2m.representation != bF2m.representation)
+            {
+                // Should never occur
+                throw new ArgumentException("One of the F2m field elements has incorrect representation");
+            }
+
+            if ((aF2m.m != bF2m.m) || !Arrays.AreEqual(aF2m.ks, bF2m.ks))
+            {
+                throw new ArgumentException("Field elements are not elements of the same field F2m");
+            }
+        }
+
+        public override ECFieldElement Add(
+            ECFieldElement b)
+        {
+            // No check performed here for performance reasons. Instead the
+            // elements involved are checked in ECPoint.F2m
+            // checkFieldElements(this, b);
+            LongArray iarrClone = this.x.Copy();
+            F2mFieldElement bF2m = (F2mFieldElement)b;
+            iarrClone.AddShiftedByWords(bF2m.x, 0);
+            return new F2mFieldElement(m, ks, iarrClone);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            return new F2mFieldElement(m, ks, x.AddOne());
+        }
+
+        public override ECFieldElement Subtract(
+            ECFieldElement b)
+        {
+            // Addition and subtraction are the same in F2m
+            return Add(b);
+        }
+
+        public override ECFieldElement Multiply(
+            ECFieldElement b)
+        {
+            // Right-to-left comb multiplication in the LongArray
+            // Input: Binary polynomials a(z) and b(z) of degree at most m-1
+            // Output: c(z) = a(z) * b(z) mod f(z)
+
+            // No check performed here for performance reasons. Instead the
+            // elements involved are checked in ECPoint.F2m
+            // checkFieldElements(this, b);
+            return new F2mFieldElement(m, ks, x.ModMultiply(((F2mFieldElement)b).x, m, ks));
+        }
+
+        public override ECFieldElement MultiplyMinusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            return MultiplyPlusProduct(b, x, y);
+        }
+
+        public override ECFieldElement MultiplyPlusProduct(ECFieldElement b, ECFieldElement x, ECFieldElement y)
+        {
+            LongArray ax = this.x, bx = ((F2mFieldElement)b).x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
+
+            LongArray ab = ax.Multiply(bx, m, ks);
+            LongArray xy = xx.Multiply(yx, m, ks);
+
+            if (ab == ax || ab == bx)
+            {
+                ab = (LongArray)ab.Copy();
+            }
+
+            ab.AddShiftedByWords(xy, 0);
+            ab.Reduce(m, ks);
+
+            return new F2mFieldElement(m, ks, ab);
+        }
+
+        public override ECFieldElement Divide(
+            ECFieldElement b)
+        {
+            // There may be more efficient implementations
+            ECFieldElement bInv = b.Invert();
+            return Multiply(bInv);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            // -x == x holds for all x in F2m
+            return this;
+        }
+
+        public override ECFieldElement Square()
+        {
+            return new F2mFieldElement(m, ks, x.ModSquare(m, ks));
+        }
+
+        public override ECFieldElement SquareMinusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            return SquarePlusProduct(x, y);
+        }
+
+        public override ECFieldElement SquarePlusProduct(ECFieldElement x, ECFieldElement y)
+        {
+            LongArray ax = this.x, xx = ((F2mFieldElement)x).x, yx = ((F2mFieldElement)y).x;
+
+            LongArray aa = ax.Square(m, ks);
+            LongArray xy = xx.Multiply(yx, m, ks);
+
+            if (aa == ax)
+            {
+                aa = (LongArray)aa.Copy();
+            }
+
+            aa.AddShiftedByWords(xy, 0);
+            aa.Reduce(m, ks);
+
+            return new F2mFieldElement(m, ks, aa);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            return new F2mFieldElement(this.m, this.ks, this.x.ModInverse(m, ks));
+        }
+
+        public override ECFieldElement Sqrt()
+        {
+            LongArray x1 = this.x;
+            if (x1.IsOne() || x1.IsZero())
+            {
+                return this;
+            }
+
+            LongArray x2 = x1.ModSquareN(m - 1, m, ks);
+            return new F2mFieldElement(m, ks, x2);
+        }
+
+        /**
+            * @return the representation of the field
+            * <code>F<sub>2<sup>m</sup></sub></code>, either of
+            * {@link F2mFieldElement.Tpb} (trinomial
+            * basis representation) or
+            * {@link F2mFieldElement.Ppb} (pentanomial
+            * basis representation).
+            */
+        public int Representation
+        {
+            get { return this.representation; }
+        }
+
+        /**
+            * @return the degree <code>m</code> of the reduction polynomial
+            * <code>f(z)</code>.
+            */
+        public int M
+        {
+            get { return this.m; }
+        }
+
+        /**
+            * @return Tpb: The integer <code>k</code> where <code>x<sup>m</sup> +
+            * x<sup>k</sup> + 1</code> represents the reduction polynomial
+            * <code>f(z)</code>.<br/>
+            * Ppb: The integer <code>k1</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.<br/>
+            */
+        public int K1
+        {
+            get { return this.ks[0]; }
+        }
+
+        /**
+            * @return Tpb: Always returns <code>0</code><br/>
+            * Ppb: The integer <code>k2</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.<br/>
+            */
+        public int K2
+        {
+            get { return this.ks.Length >= 2 ? this.ks[1] : 0; }
+        }
+
+        /**
+            * @return Tpb: Always set to <code>0</code><br/>
+            * Ppb: The integer <code>k3</code> where <code>x<sup>m</sup> +
+            * x<sup>k3</sup> + x<sup>k2</sup> + x<sup>k1</sup> + 1</code>
+            * represents the reduction polynomial <code>f(z)</code>.<br/>
+            */
+        public int K3
+        {
+            get { return this.ks.Length >= 3 ? this.ks[2] : 0; }
+        }
+
+        public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+            F2mFieldElement other = obj as F2mFieldElement;
+
+            if (other == null)
+                return false;
+
+            return Equals(other);
+        }
+
+        public virtual bool Equals(
+            F2mFieldElement other)
+        {
+            return ((this.m == other.m)
+                && (this.representation == other.representation)
+                && Arrays.AreEqual(this.ks, other.ks)
+                && (this.x.Equals(other.x)));
+        }
+
+        public override int GetHashCode()
+        {
+            return x.GetHashCode() ^ m ^ Arrays.GetHashCode(ks);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ECPoint.cs b/BouncyCastle.AxCrypt/src/math/ec/ECPoint.cs
new file mode 100644
index 0000000..3e206e6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ECPoint.cs
@@ -0,0 +1,2089 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.Text;
+
+using Org.BouncyCastle.Math.EC.Multiplier;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    /**
+     * base class for points on elliptic curves.
+     */
+    public abstract class ECPoint
+    {
+        protected static ECFieldElement[] EMPTY_ZS = new ECFieldElement[0];
+
+        protected static ECFieldElement[] GetInitialZCoords(ECCurve curve)
+        {
+            // Cope with null curve, most commonly used by implicitlyCa
+            int coord = null == curve ? ECCurve.COORD_AFFINE : curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                case ECCurve.COORD_LAMBDA_AFFINE:
+                    return EMPTY_ZS;
+                default:
+                    break;
+            }
+
+            ECFieldElement one = curve.FromBigInteger(BigInteger.One);
+
+            switch (coord)
+            {
+                case ECCurve.COORD_HOMOGENEOUS:
+                case ECCurve.COORD_JACOBIAN:
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                    return new ECFieldElement[] { one };
+                case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+                    return new ECFieldElement[] { one, one, one };
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                    return new ECFieldElement[] { one, curve.A };
+                default:
+                    throw new ArgumentException("unknown coordinate system");
+            }
+        }
+
+        protected internal readonly ECCurve m_curve;
+        protected internal readonly ECFieldElement m_x, m_y;
+        protected internal readonly ECFieldElement[] m_zs;
+        protected internal readonly bool m_withCompression;
+
+        // Dictionary is (string -> PreCompInfo)
+        protected internal IDictionary m_preCompTable = null;
+
+        protected ECPoint(ECCurve curve, ECFieldElement	x, ECFieldElement y, bool withCompression)
+            : this(curve, x, y, GetInitialZCoords(curve), withCompression)
+        {
+        }
+
+        internal ECPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            this.m_curve = curve;
+            this.m_x = x;
+            this.m_y = y;
+            this.m_zs = zs;
+            this.m_withCompression = withCompression;
+        }
+
+        protected internal bool SatisfiesCofactor()
+        {
+            BigInteger h = Curve.Cofactor;
+            return h == null || h.Equals(BigInteger.One) || !ECAlgorithms.ReferenceMultiply(this, h).IsInfinity;
+        }
+
+        protected abstract bool SatisfiesCurveEquation();
+
+        public ECPoint GetDetachedPoint()
+        {
+            return Normalize().Detach();
+        }
+
+        public virtual ECCurve Curve
+        {
+            get { return m_curve; }
+        }
+
+        protected abstract ECPoint Detach();
+
+        protected virtual int CurveCoordinateSystem
+        {
+            get
+            {
+                // Cope with null curve, most commonly used by implicitlyCa
+                return null == m_curve ? ECCurve.COORD_AFFINE : m_curve.CoordinateSystem;
+            }
+        }
+
+        /**
+         * Normalizes this point, and then returns the affine x-coordinate.
+         * 
+         * Note: normalization can be expensive, this method is deprecated in favour
+         * of caller-controlled normalization.
+         */
+        [Obsolete("Use AffineXCoord, or Normalize() and XCoord, instead")]
+        public virtual ECFieldElement X
+        {
+            get { return Normalize().XCoord; }
+        }
+
+        /**
+         * Normalizes this point, and then returns the affine y-coordinate.
+         * 
+         * Note: normalization can be expensive, this method is deprecated in favour
+         * of caller-controlled normalization.
+         */
+        [Obsolete("Use AffineYCoord, or Normalize() and YCoord, instead")]
+        public virtual ECFieldElement Y
+        {
+            get { return Normalize().YCoord; }
+        }
+
+        /**
+         * Returns the affine x-coordinate after checking that this point is normalized.
+         * 
+         * @return The affine x-coordinate of this point
+         * @throws IllegalStateException if the point is not normalized
+         */
+        public virtual ECFieldElement AffineXCoord
+        {
+            get
+            {
+                CheckNormalized();
+                return XCoord;
+            }
+        }
+
+        /**
+         * Returns the affine y-coordinate after checking that this point is normalized
+         * 
+         * @return The affine y-coordinate of this point
+         * @throws IllegalStateException if the point is not normalized
+         */
+        public virtual ECFieldElement AffineYCoord
+        {
+            get
+            {
+                CheckNormalized();
+                return YCoord;
+            }
+        }
+
+        /**
+         * Returns the x-coordinate.
+         * 
+         * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+         * affine coordinate system; use Normalize() to get a point where the coordinates have their
+         * affine values, or use AffineXCoord if you expect the point to already have been normalized.
+         * 
+         * @return the x-coordinate of this point
+         */
+        public virtual ECFieldElement XCoord
+        {
+            get { return m_x; }
+        }
+
+        /**
+         * Returns the y-coordinate.
+         * 
+         * Caution: depending on the curve's coordinate system, this may not be the same value as in an
+         * affine coordinate system; use Normalize() to get a point where the coordinates have their
+         * affine values, or use AffineYCoord if you expect the point to already have been normalized.
+         * 
+         * @return the y-coordinate of this point
+         */
+        public virtual ECFieldElement YCoord
+        {
+            get { return m_y; }
+        }
+
+        public virtual ECFieldElement GetZCoord(int index)
+        {
+            return (index < 0 || index >= m_zs.Length) ? null : m_zs[index];
+        }
+
+        public virtual ECFieldElement[] GetZCoords()
+        {
+            int zsLen = m_zs.Length;
+            if (zsLen == 0)
+            {
+                return m_zs;
+            }
+            ECFieldElement[] copy = new ECFieldElement[zsLen];
+            Array.Copy(m_zs, 0, copy, 0, zsLen);
+            return copy;
+        }
+
+        protected internal ECFieldElement RawXCoord
+        {
+            get { return m_x; }
+        }
+
+        protected internal ECFieldElement RawYCoord
+        {
+            get { return m_y; }
+        }
+
+        protected internal ECFieldElement[] RawZCoords
+        {
+            get { return m_zs; }
+        }
+
+        protected virtual void CheckNormalized()
+        {
+            if (!IsNormalized())
+                throw new InvalidOperationException("point not in normal form");
+        }
+
+        public virtual bool IsNormalized()
+        {
+            int coord = this.CurveCoordinateSystem;
+
+            return coord == ECCurve.COORD_AFFINE
+                || coord == ECCurve.COORD_LAMBDA_AFFINE
+                || IsInfinity
+                || RawZCoords[0].IsOne;
+        }
+
+        /**
+         * Normalization ensures that any projective coordinate is 1, and therefore that the x, y
+         * coordinates reflect those of the equivalent point in an affine coordinate system.
+         * 
+         * @return a new ECPoint instance representing the same point, but with normalized coordinates
+         */
+        public virtual ECPoint Normalize()
+        {
+            if (this.IsInfinity)
+            {
+                return this;
+            }
+
+            switch (this.CurveCoordinateSystem)
+            {
+                case ECCurve.COORD_AFFINE:
+                case ECCurve.COORD_LAMBDA_AFFINE:
+                {
+                    return this;
+                }
+                default:
+                {
+                    ECFieldElement Z1 = RawZCoords[0];
+                    if (Z1.IsOne)
+                    {
+                        return this;
+                    }
+
+                    return Normalize(Z1.Invert());
+                }
+            }
+        }
+
+        internal virtual ECPoint Normalize(ECFieldElement zInv)
+        {
+            switch (this.CurveCoordinateSystem)
+            {
+                case ECCurve.COORD_HOMOGENEOUS:
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    return CreateScaledPoint(zInv, zInv);
+                }
+                case ECCurve.COORD_JACOBIAN:
+                case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                {
+                    ECFieldElement zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv);
+                    return CreateScaledPoint(zInv2, zInv3);
+                }
+                default:
+                {
+                    throw new InvalidOperationException("not a projective coordinate system");
+                }
+            }
+        }
+
+        protected virtual ECPoint CreateScaledPoint(ECFieldElement sx, ECFieldElement sy)
+        {
+            return Curve.CreateRawPoint(RawXCoord.Multiply(sx), RawYCoord.Multiply(sy), IsCompressed);
+        }
+
+        public bool IsInfinity
+        {
+            get { return m_x == null && m_y == null; }
+        }
+
+        public bool IsCompressed
+        {
+            get { return m_withCompression; }
+        }
+
+        public bool IsValid()
+        {
+            if (IsInfinity)
+                return true;
+
+            // TODO Sanity-check the field elements
+
+            ECCurve curve = Curve;
+            if (curve != null)
+            {
+                if (!SatisfiesCurveEquation())
+                    return false;
+
+                if (!SatisfiesCofactor())
+                    return false;
+            }
+
+            return true;
+        }
+
+        public virtual ECPoint ScaleX(ECFieldElement scale)
+        {
+            return IsInfinity
+                ? this
+                : Curve.CreateRawPoint(RawXCoord.Multiply(scale), RawYCoord, RawZCoords, IsCompressed);
+        }
+
+        public virtual ECPoint ScaleY(ECFieldElement scale)
+        {
+            return IsInfinity
+                ? this
+                : Curve.CreateRawPoint(RawXCoord, RawYCoord.Multiply(scale), RawZCoords, IsCompressed);
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as ECPoint);
+        }
+
+        public virtual bool Equals(ECPoint other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+
+            ECCurve c1 = this.Curve, c2 = other.Curve;
+            bool n1 = (null == c1), n2 = (null == c2);
+            bool i1 = IsInfinity, i2 = other.IsInfinity;
+
+            if (i1 || i2)
+            {
+                return (i1 && i2) && (n1 || n2 || c1.Equals(c2));
+            }
+
+            ECPoint p1 = this, p2 = other;
+            if (n1 && n2)
+            {
+                // Points with null curve are in affine form, so already normalized
+            }
+            else if (n1)
+            {
+                p2 = p2.Normalize();
+            }
+            else if (n2)
+            {
+                p1 = p1.Normalize();
+            }
+            else if (!c1.Equals(c2))
+            {
+                return false;
+            }
+            else
+            {
+                // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+                ECPoint[] points = new ECPoint[] { this, c1.ImportPoint(p2) };
+
+                // TODO This is a little strong, really only requires coZNormalizeAll to get Zs equal
+                c1.NormalizeAll(points);
+
+                p1 = points[0];
+                p2 = points[1];
+            }
+
+            return p1.XCoord.Equals(p2.XCoord) && p1.YCoord.Equals(p2.YCoord);
+        }
+
+        public override int GetHashCode()
+        {
+            ECCurve c = this.Curve;
+            int hc = (null == c) ? 0 : ~c.GetHashCode();
+
+            if (!this.IsInfinity)
+            {
+                // TODO Consider just requiring already normalized, to avoid silent performance degradation
+
+                ECPoint p = Normalize();
+
+                hc ^= p.XCoord.GetHashCode() * 17;
+                hc ^= p.YCoord.GetHashCode() * 257;
+            }
+
+            return hc;
+        }
+
+        public override string ToString()
+        {
+            if (this.IsInfinity)
+            {
+                return "INF";
+            }
+
+            StringBuilder sb = new StringBuilder();
+            sb.Append('(');
+            sb.Append(RawXCoord);
+            sb.Append(',');
+            sb.Append(RawYCoord);
+            for (int i = 0; i < m_zs.Length; ++i)
+            {
+                sb.Append(',');
+                sb.Append(m_zs[i]);
+            }
+            sb.Append(')');
+            return sb.ToString();
+        }
+
+        public virtual byte[] GetEncoded()
+        {
+            return GetEncoded(m_withCompression);
+        }
+
+        public abstract byte[] GetEncoded(bool compressed);
+
+        protected internal abstract bool CompressionYTilde { get; }
+
+        public abstract ECPoint Add(ECPoint b);
+        public abstract ECPoint Subtract(ECPoint b);
+        public abstract ECPoint Negate();
+
+        public virtual ECPoint TimesPow2(int e)
+        {
+            if (e < 0)
+                throw new ArgumentException("cannot be negative", "e");
+
+            ECPoint p = this;
+            while (--e >= 0)
+            {
+                p = p.Twice();
+            }
+            return p;
+        }
+
+        public abstract ECPoint Twice();
+        public abstract ECPoint Multiply(BigInteger b);
+
+        public virtual ECPoint TwicePlus(ECPoint b)
+        {
+            return Twice().Add(b);
+        }
+
+        public virtual ECPoint ThreeTimes()
+        {
+            return TwicePlus(this);
+        }
+    }
+
+    public abstract class ECPointBase
+        : ECPoint
+    {
+        protected internal ECPointBase(
+            ECCurve			curve,
+            ECFieldElement	x,
+            ECFieldElement	y,
+            bool			withCompression)
+            : base(curve, x, y, withCompression)
+        {
+        }
+
+        protected internal ECPointBase(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        /**
+         * return the field element encoded with point compression. (S 4.3.6)
+         */
+        public override byte[] GetEncoded(bool compressed)
+        {
+            if (this.IsInfinity)
+            {
+                return new byte[1];
+            }
+
+            ECPoint normed = Normalize();
+
+            byte[] X = normed.XCoord.GetEncoded();
+
+            if (compressed)
+            {
+                byte[] PO = new byte[X.Length + 1];
+                PO[0] = (byte)(normed.CompressionYTilde ? 0x03 : 0x02);
+                Array.Copy(X, 0, PO, 1, X.Length);
+                return PO;
+            }
+
+            byte[] Y = normed.YCoord.GetEncoded();
+
+            {
+                byte[] PO = new byte[X.Length + Y.Length + 1];
+                PO[0] = 0x04;
+                Array.Copy(X, 0, PO, 1, X.Length);
+                Array.Copy(Y, 0, PO, X.Length + 1, Y.Length);
+                return PO;
+            }
+        }
+
+        /**
+         * Multiplies this <code>ECPoint</code> by the given number.
+         * @param k The multiplicator.
+         * @return <code>k * this</code>.
+         */
+        public override ECPoint Multiply(BigInteger k)
+        {
+            return this.Curve.GetMultiplier().Multiply(this, k);
+        }
+    }
+
+    public abstract class AbstractFpPoint
+        : ECPointBase
+    {
+        protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+        }
+
+        protected AbstractFpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected internal override bool CompressionYTilde
+        {
+            get { return this.AffineYCoord.TestBitZero(); }
+        }
+
+        protected override bool SatisfiesCurveEquation()
+        {
+            ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = Curve.A, B = Curve.B;
+            ECFieldElement lhs = Y.Square();
+
+            switch (CurveCoordinateSystem)
+            {
+            case ECCurve.COORD_AFFINE:
+                break;
+            case ECCurve.COORD_HOMOGENEOUS:
+            {
+                ECFieldElement Z = this.RawZCoords[0];
+                if (!Z.IsOne)
+                {
+                    ECFieldElement Z2 = Z.Square(), Z3 = Z.Multiply(Z2);
+                    lhs = lhs.Multiply(Z);
+                    A = A.Multiply(Z2);
+                    B = B.Multiply(Z3);
+                }
+                break;
+            }
+            case ECCurve.COORD_JACOBIAN:
+            case ECCurve.COORD_JACOBIAN_CHUDNOVSKY:
+            case ECCurve.COORD_JACOBIAN_MODIFIED:
+            {
+                ECFieldElement Z = this.RawZCoords[0];
+                if (!Z.IsOne)
+                {
+                    ECFieldElement Z2 = Z.Square(), Z4 = Z2.Square(), Z6 = Z2.Multiply(Z4);
+                    A = A.Multiply(Z4);
+                    B = B.Multiply(Z6);
+                }
+                break;
+            }
+            default:
+                throw new InvalidOperationException("unsupported coordinate system");
+            }
+
+            ECFieldElement rhs = X.Square().Add(A).Multiply(X).Add(B);
+            return lhs.Equals(rhs);
+        }
+
+        public override ECPoint Subtract(ECPoint b)
+        {
+            if (b.IsInfinity)
+                return this;
+
+            // Add -b
+            return Add(b.Negate());
+        }
+    }
+
+    /**
+     * Elliptic curve points over Fp
+     */
+    public class FpPoint
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes without point compression.
+         *
+         * @param curve the curve to use
+         * @param x affine x co-ordinate
+         * @param y affine y co-ordinate
+         */
+        public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compression.
+         *
+         * @param curve the curve to use
+         * @param x affine x co-ordinate
+         * @param y affine y co-ordinate
+         * @param withCompression if true encode with point compression
+         */
+        public FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal FpPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new FpPoint(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECFieldElement GetZCoord(int index)
+        {
+            if (index == 1 && ECCurve.COORD_JACOBIAN_MODIFIED == this.CurveCoordinateSystem)
+            {
+                return GetJacobianModifiedW();
+            }
+
+            return base.GetZCoord(index);
+        }
+
+        // B.3 pg 62
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            ECFieldElement X1 = this.RawXCoord, Y1 = this.RawYCoord;
+            ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1);
+
+                    if (dx.IsZero)
+                    {
+                        if (dy.IsZero)
+                        {
+                            // this == b, i.e. this must be doubled
+                            return Twice();
+                        }
+
+                        // this == -b, i.e. the result is the point at infinity
+                        return Curve.Infinity;
+                    }
+
+                    ECFieldElement gamma = dy.Divide(dx);
+                    ECFieldElement X3 = gamma.Square().Subtract(X1).Subtract(X2);
+                    ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1);
+
+                    return new FpPoint(Curve, X3, Y3, IsCompressed);
+                }
+
+                case ECCurve.COORD_HOMOGENEOUS:
+                {
+                    ECFieldElement Z1 = this.RawZCoords[0];
+                    ECFieldElement Z2 = b.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+                    bool Z2IsOne = Z2.IsOne;
+
+                    ECFieldElement u1 = Z1IsOne ? Y2 : Y2.Multiply(Z1);
+                    ECFieldElement u2 = Z2IsOne ? Y1 : Y1.Multiply(Z2);
+                    ECFieldElement u = u1.Subtract(u2);
+                    ECFieldElement v1 = Z1IsOne ? X2 : X2.Multiply(Z1);
+                    ECFieldElement v2 = Z2IsOne ? X1 : X1.Multiply(Z2);
+                    ECFieldElement v = v1.Subtract(v2);
+
+                    // Check if b == this or b == -this
+                    if (v.IsZero)
+                    {
+                        if (u.IsZero)
+                        {
+                            // this == b, i.e. this must be doubled
+                            return this.Twice();
+                        }
+
+                        // this == -b, i.e. the result is the point at infinity
+                        return curve.Infinity;
+                    }
+
+                    // TODO Optimize for when w == 1
+                    ECFieldElement w = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2);
+                    ECFieldElement vSquared = v.Square();
+                    ECFieldElement vCubed = vSquared.Multiply(v);
+                    ECFieldElement vSquaredV2 = vSquared.Multiply(v2);
+                    ECFieldElement A = u.Square().Multiply(w).Subtract(vCubed).Subtract(Two(vSquaredV2));
+
+                    ECFieldElement X3 = v.Multiply(A);
+                    ECFieldElement Y3 = vSquaredV2.Subtract(A).MultiplyMinusProduct(u, u2, vCubed);
+                    ECFieldElement Z3 = vCubed.Multiply(w);
+
+                    return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+
+                case ECCurve.COORD_JACOBIAN:
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                {
+                    ECFieldElement Z1 = this.RawZCoords[0];
+                    ECFieldElement Z2 = b.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+
+                    ECFieldElement X3, Y3, Z3, Z3Squared = null;
+
+                    if (!Z1IsOne && Z1.Equals(Z2))
+                    {
+                        // TODO Make this available as public method coZAdd?
+
+                        ECFieldElement dx = X1.Subtract(X2), dy = Y1.Subtract(Y2);
+                        if (dx.IsZero)
+                        {
+                            if (dy.IsZero)
+                            {
+                                return Twice();
+                            }
+                            return curve.Infinity;
+                        }
+
+                        ECFieldElement C = dx.Square();
+                        ECFieldElement W1 = X1.Multiply(C), W2 = X2.Multiply(C);
+                        ECFieldElement A1 = W1.Subtract(W2).Multiply(Y1);
+
+                        X3 = dy.Square().Subtract(W1).Subtract(W2);
+                        Y3 = W1.Subtract(X3).Multiply(dy).Subtract(A1);
+                        Z3 = dx;
+
+                        if (Z1IsOne)
+                        {
+                            Z3Squared = C;
+                        }
+                        else
+                        {
+                            Z3 = Z3.Multiply(Z1);
+                        }
+                    }
+                    else
+                    {
+                        ECFieldElement Z1Squared, U2, S2;
+                        if (Z1IsOne)
+                        {
+                            Z1Squared = Z1; U2 = X2; S2 = Y2;
+                        }
+                        else
+                        {
+                            Z1Squared = Z1.Square();
+                            U2 = Z1Squared.Multiply(X2);
+                            ECFieldElement Z1Cubed = Z1Squared.Multiply(Z1);
+                            S2 = Z1Cubed.Multiply(Y2);
+                        }
+
+                        bool Z2IsOne = Z2.IsOne;
+                        ECFieldElement Z2Squared, U1, S1;
+                        if (Z2IsOne)
+                        {
+                            Z2Squared = Z2; U1 = X1; S1 = Y1;
+                        }
+                        else
+                        {
+                            Z2Squared = Z2.Square();
+                            U1 = Z2Squared.Multiply(X1);
+                            ECFieldElement Z2Cubed = Z2Squared.Multiply(Z2);
+                            S1 = Z2Cubed.Multiply(Y1);
+                        }
+
+                        ECFieldElement H = U1.Subtract(U2);
+                        ECFieldElement R = S1.Subtract(S2);
+
+                        // Check if b == this or b == -this
+                        if (H.IsZero)
+                        {
+                            if (R.IsZero)
+                            {
+                                // this == b, i.e. this must be doubled
+                                return this.Twice();
+                            }
+
+                            // this == -b, i.e. the result is the point at infinity
+                            return curve.Infinity;
+                        }
+
+                        ECFieldElement HSquared = H.Square();
+                        ECFieldElement G = HSquared.Multiply(H);
+                        ECFieldElement V = HSquared.Multiply(U1);
+
+                        X3 = R.Square().Add(G).Subtract(Two(V));
+                        Y3 = V.Subtract(X3).MultiplyMinusProduct(R, G, S1);
+
+                        Z3 = H;
+                        if (!Z1IsOne)
+                        {
+                            Z3 = Z3.Multiply(Z1);
+                        }
+                        if (!Z2IsOne)
+                        {
+                            Z3 = Z3.Multiply(Z2);
+                        }
+
+                        // Alternative calculation of Z3 using fast square
+                        //X3 = four(X3);
+                        //Y3 = eight(Y3);
+                        //Z3 = doubleProductFromSquares(Z1, Z2, Z1Squared, Z2Squared).Multiply(H);
+
+                        if (Z3 == H)
+                        {
+                            Z3Squared = HSquared;
+                        }
+                    }
+
+                    ECFieldElement[] zs;
+                    if (coord == ECCurve.COORD_JACOBIAN_MODIFIED)
+                    {
+                        // TODO If the result will only be used in a subsequent addition, we don't need W3
+                        ECFieldElement W3 = CalculateJacobianModifiedW(Z3, Z3Squared);
+
+                        zs = new ECFieldElement[] { Z3, W3 };
+                    }
+                    else
+                    {
+                        zs = new ECFieldElement[] { Z3 };
+                    }
+
+                    return new FpPoint(curve, X3, Y3, zs, IsCompressed);
+                }
+
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+
+        // B.3 pg 62
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero) 
+                return curve.Infinity;
+
+            int coord = curve.CoordinateSystem;
+
+            ECFieldElement X1 = this.RawXCoord;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement X1Squared = X1.Square();
+                    ECFieldElement gamma = Three(X1Squared).Add(this.Curve.A).Divide(Two(Y1));
+                    ECFieldElement X3 = gamma.Square().Subtract(Two(X1));
+                    ECFieldElement Y3 = gamma.Multiply(X1.Subtract(X3)).Subtract(Y1);
+
+                    return new FpPoint(Curve, X3, Y3, IsCompressed);
+                }
+
+                case ECCurve.COORD_HOMOGENEOUS:
+                {
+                    ECFieldElement Z1 = this.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+
+                    // TODO Optimize for small negative a4 and -3
+                    ECFieldElement w = curve.A;
+                    if (!w.IsZero && !Z1IsOne)
+                    {
+                        w = w.Multiply(Z1.Square());
+                    }
+                    w = w.Add(Three(X1.Square()));
+
+                    ECFieldElement s = Z1IsOne ? Y1 : Y1.Multiply(Z1);
+                    ECFieldElement t = Z1IsOne ? Y1.Square() : s.Multiply(Y1);
+                    ECFieldElement B = X1.Multiply(t);
+                    ECFieldElement _4B = Four(B);
+                    ECFieldElement h = w.Square().Subtract(Two(_4B));
+
+                    ECFieldElement _2s = Two(s);
+                    ECFieldElement X3 = h.Multiply(_2s);
+                    ECFieldElement _2t = Two(t);
+                    ECFieldElement Y3 = _4B.Subtract(h).Multiply(w).Subtract(Two(_2t.Square()));
+                    ECFieldElement _4sSquared = Z1IsOne ? Two(_2t) : _2s.Square();
+                    ECFieldElement Z3 = Two(_4sSquared).Multiply(s);
+
+                    return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+
+                case ECCurve.COORD_JACOBIAN:
+                {
+                    ECFieldElement Z1 = this.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+
+                    ECFieldElement Y1Squared = Y1.Square();
+                    ECFieldElement T = Y1Squared.Square();
+
+                    ECFieldElement a4 = curve.A;
+                    ECFieldElement a4Neg = a4.Negate();
+
+                    ECFieldElement M, S;
+                    if (a4Neg.ToBigInteger().Equals(BigInteger.ValueOf(3)))
+                    {
+                        ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square();
+                        M = Three(X1.Add(Z1Squared).Multiply(X1.Subtract(Z1Squared)));
+                        S = Four(Y1Squared.Multiply(X1));
+                    }
+                    else
+                    {
+                        ECFieldElement X1Squared = X1.Square();
+                        M = Three(X1Squared);
+                        if (Z1IsOne)
+                        {
+                            M = M.Add(a4);
+                        }
+                        else if (!a4.IsZero)
+                        {
+                            ECFieldElement Z1Squared = Z1IsOne ? Z1 : Z1.Square();
+                            ECFieldElement Z1Pow4 = Z1Squared.Square();
+                            if (a4Neg.BitLength < a4.BitLength)
+                            {
+                                M = M.Subtract(Z1Pow4.Multiply(a4Neg));
+                            }
+                            else
+                            {
+                                M = M.Add(Z1Pow4.Multiply(a4));
+                            }
+                        }
+                        //S = two(doubleProductFromSquares(X1, Y1Squared, X1Squared, T));
+                        S = Four(X1.Multiply(Y1Squared));
+                    }
+
+                    ECFieldElement X3 = M.Square().Subtract(Two(S));
+                    ECFieldElement Y3 = S.Subtract(X3).Multiply(M).Subtract(Eight(T));
+
+                    ECFieldElement Z3 = Two(Y1);
+                    if (!Z1IsOne)
+                    {
+                        Z3 = Z3.Multiply(Z1);
+                    }
+
+                    // Alternative calculation of Z3 using fast square
+                    //ECFieldElement Z3 = doubleProductFromSquares(Y1, Z1, Y1Squared, Z1Squared);
+
+                    return new FpPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                {
+                    return TwiceJacobianModified(true);
+                }
+
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement X1 = this.RawXCoord;
+                    ECFieldElement X2 = b.RawXCoord, Y2 = b.RawYCoord;
+
+                    ECFieldElement dx = X2.Subtract(X1), dy = Y2.Subtract(Y1);
+
+                    if (dx.IsZero)
+                    {
+                        if (dy.IsZero)
+                        {
+                            // this == b i.e. the result is 3P
+                            return ThreeTimes();
+                        }
+
+                        // this == -b, i.e. the result is P
+                        return this;
+                    }
+
+                    /*
+                     * Optimized calculation of 2P + Q, as described in "Trading Inversions for
+                     * Multiplications in Elliptic Curve Cryptography", by Ciet, Joye, Lauter, Montgomery.
+                     */
+
+                    ECFieldElement X = dx.Square(), Y = dy.Square();
+                    ECFieldElement d = X.Multiply(Two(X1).Add(X2)).Subtract(Y);
+                    if (d.IsZero)
+                    {
+                        return Curve.Infinity;
+                    }
+
+                    ECFieldElement D = d.Multiply(dx);
+                    ECFieldElement I = D.Invert();
+                    ECFieldElement L1 = d.Multiply(I).Multiply(dy);
+                    ECFieldElement L2 = Two(Y1).Multiply(X).Multiply(dx).Multiply(I).Subtract(L1);
+                    ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X2);
+                    ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1);
+
+                    return new FpPoint(Curve, X4, Y4, IsCompressed);
+                }
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                {
+                    return TwiceJacobianModified(false).Add(b);
+                }
+                default:
+                {
+                    return Twice().Add(b);
+                }
+            }
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return this;
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement X1 = this.RawXCoord;
+
+                    ECFieldElement _2Y1 = Two(Y1);
+                    ECFieldElement X = _2Y1.Square();
+                    ECFieldElement Z = Three(X1.Square()).Add(Curve.A);
+                    ECFieldElement Y = Z.Square();
+
+                    ECFieldElement d = Three(X1).Multiply(X).Subtract(Y);
+                    if (d.IsZero)
+                    {
+                        return Curve.Infinity;
+                    }
+
+                    ECFieldElement D = d.Multiply(_2Y1);
+                    ECFieldElement I = D.Invert();
+                    ECFieldElement L1 = d.Multiply(I).Multiply(Z);
+                    ECFieldElement L2 = X.Square().Multiply(I).Subtract(L1);
+
+                    ECFieldElement X4 = (L2.Subtract(L1)).Multiply(L1.Add(L2)).Add(X1);
+                    ECFieldElement Y4 = (X1.Subtract(X4)).Multiply(L2).Subtract(Y1);
+                    return new FpPoint(Curve, X4, Y4, IsCompressed);
+                }
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                {
+                    return TwiceJacobianModified(false).Add(this);
+                }
+                default:
+                {
+                    // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+                    return Twice().Add(this);
+                }
+            }
+        }
+
+        public override ECPoint TimesPow2(int e)
+        {
+            if (e < 0)
+                throw new ArgumentException("cannot be negative", "e");
+            if (e == 0 || this.IsInfinity)
+                return this;
+            if (e == 1)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero) 
+                return curve.Infinity;
+
+            int coord = curve.CoordinateSystem;
+
+            ECFieldElement W1 = curve.A;
+            ECFieldElement X1 = this.RawXCoord;
+            ECFieldElement Z1 = this.RawZCoords.Length < 1 ? curve.FromBigInteger(BigInteger.One) : this.RawZCoords[0];
+
+            if (!Z1.IsOne)
+            {
+                switch (coord)
+                {
+                case ECCurve.COORD_HOMOGENEOUS:
+                    ECFieldElement Z1Sq = Z1.Square();
+                    X1 = X1.Multiply(Z1);
+                    Y1 = Y1.Multiply(Z1Sq);
+                    W1 = CalculateJacobianModifiedW(Z1, Z1Sq);
+                    break;
+                case ECCurve.COORD_JACOBIAN:
+                    W1 = CalculateJacobianModifiedW(Z1, null);
+                    break;
+                case ECCurve.COORD_JACOBIAN_MODIFIED:
+                    W1 = GetJacobianModifiedW();
+                    break;
+                }
+            }
+
+            for (int i = 0; i < e; ++i)
+            {
+                if (Y1.IsZero) 
+                    return curve.Infinity;
+
+                ECFieldElement X1Squared = X1.Square();
+                ECFieldElement M = Three(X1Squared);
+                ECFieldElement _2Y1 = Two(Y1);
+                ECFieldElement _2Y1Squared = _2Y1.Multiply(Y1);
+                ECFieldElement S = Two(X1.Multiply(_2Y1Squared));
+                ECFieldElement _4T = _2Y1Squared.Square();
+                ECFieldElement _8T = Two(_4T);
+
+                if (!W1.IsZero)
+                {
+                    M = M.Add(W1);
+                    W1 = Two(_8T.Multiply(W1));
+                }
+
+                X1 = M.Square().Subtract(Two(S));
+                Y1 = M.Multiply(S.Subtract(X1)).Subtract(_8T);
+                Z1 = Z1.IsOne ? _2Y1 : _2Y1.Multiply(Z1);
+            }
+
+            switch (coord)
+            {
+            case ECCurve.COORD_AFFINE:
+                ECFieldElement zInv = Z1.Invert(), zInv2 = zInv.Square(), zInv3 = zInv2.Multiply(zInv);
+                return new FpPoint(curve, X1.Multiply(zInv2), Y1.Multiply(zInv3), IsCompressed);
+            case ECCurve.COORD_HOMOGENEOUS:
+                X1 = X1.Multiply(Z1);
+                Z1 = Z1.Multiply(Z1.Square());
+                return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1 }, IsCompressed);
+            case ECCurve.COORD_JACOBIAN:
+                return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1 }, IsCompressed);
+            case ECCurve.COORD_JACOBIAN_MODIFIED:
+                return new FpPoint(curve, X1, Y1, new ECFieldElement[] { Z1, W1 }, IsCompressed);
+            default:
+                throw new InvalidOperationException("unsupported coordinate system");
+            }
+        }
+
+        protected virtual ECFieldElement Two(ECFieldElement x)
+        {
+            return x.Add(x);
+        }
+
+        protected virtual ECFieldElement Three(ECFieldElement x)
+        {
+            return Two(x).Add(x);
+        }
+
+        protected virtual ECFieldElement Four(ECFieldElement x)
+        {
+            return Two(Two(x));
+        }
+
+        protected virtual ECFieldElement Eight(ECFieldElement x)
+        {
+            return Four(Two(x));
+        }
+
+        protected virtual ECFieldElement DoubleProductFromSquares(ECFieldElement a, ECFieldElement b,
+            ECFieldElement aSquared, ECFieldElement bSquared)
+        {
+            /*
+             * NOTE: If squaring in the field is faster than multiplication, then this is a quicker
+             * way to calculate 2.A.B, if A^2 and B^2 are already known.
+             */
+            return a.Add(b).Square().Subtract(aSquared).Subtract(bSquared);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            ECCurve curve = Curve;
+            int coord = curve.CoordinateSystem;
+
+            if (ECCurve.COORD_AFFINE != coord)
+            {
+                return new FpPoint(curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+            }
+
+            return new FpPoint(curve, RawXCoord, RawYCoord.Negate(), IsCompressed);
+        }
+
+        protected virtual ECFieldElement CalculateJacobianModifiedW(ECFieldElement Z, ECFieldElement ZSquared)
+        {
+            ECFieldElement a4 = this.Curve.A;
+            if (a4.IsZero || Z.IsOne)
+                return a4;
+
+            if (ZSquared == null)
+            {
+                ZSquared = Z.Square();
+            }
+
+            ECFieldElement W = ZSquared.Square();
+            ECFieldElement a4Neg = a4.Negate();
+            if (a4Neg.BitLength < a4.BitLength)
+            {
+                W = W.Multiply(a4Neg).Negate();
+            }
+            else
+            {
+                W = W.Multiply(a4);
+            }
+            return W;
+        }
+
+        protected virtual ECFieldElement GetJacobianModifiedW()
+        {
+            ECFieldElement[] ZZ = this.RawZCoords;
+            ECFieldElement W = ZZ[1];
+            if (W == null)
+            {
+                // NOTE: Rarely, TwicePlus will result in the need for a lazy W1 calculation here
+                ZZ[1] = W = CalculateJacobianModifiedW(ZZ[0], null);
+            }
+            return W;
+        }
+
+        protected virtual FpPoint TwiceJacobianModified(bool calculateW)
+        {
+            ECFieldElement X1 = this.RawXCoord, Y1 = this.RawYCoord, Z1 = this.RawZCoords[0], W1 = GetJacobianModifiedW();
+
+            ECFieldElement X1Squared = X1.Square();
+            ECFieldElement M = Three(X1Squared).Add(W1);
+            ECFieldElement _2Y1 = Two(Y1);
+            ECFieldElement _2Y1Squared = _2Y1.Multiply(Y1);
+            ECFieldElement S = Two(X1.Multiply(_2Y1Squared));
+            ECFieldElement X3 = M.Square().Subtract(Two(S));
+            ECFieldElement _4T = _2Y1Squared.Square();
+            ECFieldElement _8T = Two(_4T);
+            ECFieldElement Y3 = M.Multiply(S.Subtract(X3)).Subtract(_8T);
+            ECFieldElement W3 = calculateW ? Two(_8T.Multiply(W1)) : null;
+            ECFieldElement Z3 = Z1.IsOne ? _2Y1 : _2Y1.Multiply(Z1);
+
+            return new FpPoint(this.Curve, X3, Y3, new ECFieldElement[] { Z3, W3 }, IsCompressed);
+        }
+    }
+
+    public abstract class AbstractF2mPoint 
+        : ECPointBase
+    {
+        protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+        }
+
+        protected AbstractF2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override bool SatisfiesCurveEquation()
+        {
+            ECCurve curve = Curve;
+            ECFieldElement X = this.RawXCoord, Y = this.RawYCoord, A = curve.A, B = curve.B;
+            ECFieldElement lhs, rhs;
+
+            int coord = curve.CoordinateSystem;
+            if (coord == ECCurve.COORD_LAMBDA_PROJECTIVE)
+            {
+                ECFieldElement Z = this.RawZCoords[0];
+                bool ZIsOne = Z.IsOne;
+
+                if (X.IsZero)
+                {
+                    // NOTE: For x == 0, we expect the affine-y instead of the lambda-y 
+                    lhs = Y.Square();
+                    rhs = B;
+                    if (!ZIsOne)
+                    {
+                        ECFieldElement Z2 = Z.Square();
+                        rhs = rhs.Multiply(Z2);
+                    }
+                }
+                else
+                {
+                    ECFieldElement L = Y, X2 = X.Square();
+                    if (ZIsOne)
+                    {
+                        lhs = L.Square().Add(L).Add(A);
+                        rhs = X2.Square().Add(B);
+                    }
+                    else
+                    {
+                        ECFieldElement Z2 = Z.Square(), Z4 = Z2.Square();
+                        lhs = L.Add(Z).MultiplyPlusProduct(L, A, Z2);
+                        // TODO If sqrt(b) is precomputed this can be simplified to a single square
+                        rhs = X2.SquarePlusProduct(B, Z4);
+                    }
+                    lhs = lhs.Multiply(X2);
+                }
+            }
+            else
+            {
+                lhs = Y.Add(X).Multiply(Y);
+
+                switch (coord)
+                {
+                    case ECCurve.COORD_AFFINE:
+                        break;
+                    case ECCurve.COORD_HOMOGENEOUS:
+                        {
+                            ECFieldElement Z = this.RawZCoords[0];
+                            if (!Z.IsOne)
+                            {
+                                ECFieldElement Z2 = Z.Square(), Z3 = Z.Multiply(Z2);
+                                lhs = lhs.Multiply(Z);
+                                A = A.Multiply(Z);
+                                B = B.Multiply(Z3);
+                            }
+                            break;
+                        }
+                    default:
+                        throw new InvalidOperationException("unsupported coordinate system");
+                }
+
+                rhs = X.Add(A).Multiply(X.Square()).Add(B);
+            }
+
+            return lhs.Equals(rhs);
+        }
+    }
+
+    /**
+     * Elliptic curve points over F2m
+     */
+    public class F2mPoint
+        : AbstractF2mPoint
+    {
+        /**
+         * @param curve base curve
+         * @param x x point
+         * @param y y point
+         */
+        public F2mPoint(
+            ECCurve			curve,
+            ECFieldElement	x,
+            ECFieldElement	y)
+            :  this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * @param curve base curve
+         * @param x x point
+         * @param y y point
+         * @param withCompression true if encode with point compression.
+         */
+        public F2mPoint(
+            ECCurve			curve,
+            ECFieldElement	x,
+            ECFieldElement	y,
+            bool			withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+            {
+                throw new ArgumentException("Exactly one of the field elements is null");
+            }
+
+            if (x != null)
+            {
+                // Check if x and y are elements of the same field
+                F2mFieldElement.CheckFieldElements(x, y);
+
+                // Check if x and a are elements of the same field
+                if (curve != null)
+                {
+                    F2mFieldElement.CheckFieldElements(x, curve.A);
+                }
+            }
+        }
+
+        internal F2mPoint(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        /**
+         * Constructor for point at infinity
+         */
+        [Obsolete("Use ECCurve.Infinity property")]
+        public F2mPoint(
+            ECCurve curve)
+            : this(curve, null, null)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new F2mPoint(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECFieldElement YCoord
+        {
+            get
+            {
+                int coord = this.CurveCoordinateSystem;
+
+                switch (coord)
+                {
+                    case ECCurve.COORD_LAMBDA_AFFINE:
+                    case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                    {
+                        ECFieldElement X = RawXCoord, L = RawYCoord;
+
+                        if (this.IsInfinity || X.IsZero)
+                            return L;
+
+                        // Y is actually Lambda (X + Y/X) here; convert to affine value on the fly
+                        ECFieldElement Y = L.Add(X).Multiply(X);
+                        if (ECCurve.COORD_LAMBDA_PROJECTIVE == coord)
+                        {
+                            ECFieldElement Z = RawZCoords[0];
+                            if (!Z.IsOne)
+                            {
+                                Y = Y.Divide(Z);
+                            }
+                        }
+                        return Y;
+                    }
+                    default:
+                    {
+                        return RawYCoord;
+                    }
+                }
+            }
+        }
+
+        public override ECPoint ScaleX(ECFieldElement scale)
+        {
+            if (this.IsInfinity)
+                return this;
+
+            switch (CurveCoordinateSystem)
+            {
+            case ECCurve.COORD_LAMBDA_AFFINE:
+            {
+                // Y is actually Lambda (X + Y/X) here
+                ECFieldElement X = RawXCoord, L = RawYCoord;
+
+                ECFieldElement X2 = X.Multiply(scale);
+                ECFieldElement L2 = L.Add(X).Divide(scale).Add(X2);
+
+                return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
+            }
+            case ECCurve.COORD_LAMBDA_PROJECTIVE:
+            {
+                // Y is actually Lambda (X + Y/X) here
+                ECFieldElement X = RawXCoord, L = RawYCoord, Z = RawZCoords[0];
+
+                // We scale the Z coordinate also, to avoid an inversion
+                ECFieldElement X2 = X.Multiply(scale.Square());
+                ECFieldElement L2 = L.Add(X).Add(X2);
+                ECFieldElement Z2 = Z.Multiply(scale);
+
+                return Curve.CreateRawPoint(X, L2, new ECFieldElement[] { Z2 }, IsCompressed);
+            }
+            default:
+            {
+                return base.ScaleX(scale);
+            }
+            }
+        }
+
+        public override ECPoint ScaleY(ECFieldElement scale)
+        {
+            if (this.IsInfinity)
+                return this;
+
+            switch (CurveCoordinateSystem)
+            {
+            case ECCurve.COORD_LAMBDA_AFFINE:
+            case ECCurve.COORD_LAMBDA_PROJECTIVE:
+            {
+                ECFieldElement X = RawXCoord, L = RawYCoord;
+
+                // Y is actually Lambda (X + Y/X) here
+                ECFieldElement L2 = L.Add(X).Multiply(scale).Add(X);
+
+                return Curve.CreateRawPoint(X, L2, RawZCoords, IsCompressed);
+            }
+            default:
+            {
+                return base.ScaleY(scale);
+            }
+            }
+        }
+
+        protected internal override bool CompressionYTilde
+        {
+            get
+            {
+                ECFieldElement X = this.RawXCoord;
+                if (X.IsZero)
+                {
+                    return false;
+                }
+
+                ECFieldElement Y = this.RawYCoord;
+
+                switch (this.CurveCoordinateSystem)
+                {
+                    case ECCurve.COORD_LAMBDA_AFFINE:
+                    case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                    {
+                        // Y is actually Lambda (X + Y/X) here
+                        return Y.TestBitZero() != X.TestBitZero();
+                    }
+                    default:
+                    {
+                        return Y.Divide(X).TestBitZero();
+                    }
+                }
+            }
+        }
+
+        /**
+         * Check, if two <code>ECPoint</code>s can be added or subtracted.
+         * @param a The first <code>ECPoint</code> to check.
+         * @param b The second <code>ECPoint</code> to check.
+         * @throws IllegalArgumentException if <code>a</code> and <code>b</code>
+         * cannot be added.
+         */
+        private static void CheckPoints(
+            ECPoint	a,
+            ECPoint	b)
+        {
+            // Check, if points are on the same curve
+            if (!a.Curve.Equals(b.Curve))
+                throw new ArgumentException("Only points on the same curve can be added or subtracted");
+
+//			F2mFieldElement.CheckFieldElements(a.x, b.x);
+        }
+
+        /* (non-Javadoc)
+         * @see org.bouncycastle.math.ec.ECPoint#add(org.bouncycastle.math.ec.ECPoint)
+         */
+        public override ECPoint Add(ECPoint b)
+        {
+            CheckPoints(this, b);
+            return AddSimple((F2mPoint) b);
+        }
+
+        /**
+         * Adds another <code>ECPoints.F2m</code> to <code>this</code> without
+         * checking if both points are on the same curve. Used by multiplication
+         * algorithms, because there all points are a multiple of the same point
+         * and hence the checks can be omitted.
+         * @param b The other <code>ECPoints.F2m</code> to add to
+         * <code>this</code>.
+         * @return <code>this + b</code>
+         */
+        internal F2mPoint AddSimple(F2mPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            ECFieldElement X1 = this.RawXCoord;
+            ECFieldElement X2 = b.RawXCoord;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement Y1 = this.RawYCoord;
+                    ECFieldElement Y2 = b.RawYCoord;
+
+                    ECFieldElement dx = X1.Add(X2), dy = Y1.Add(Y2);
+                    if (dx.IsZero)
+                    {
+                        if (dy.IsZero)
+                        {
+                            return (F2mPoint)Twice();
+                        }
+
+                        return (F2mPoint)curve.Infinity;
+                    }
+
+                    ECFieldElement L = dy.Divide(dx);
+
+                    ECFieldElement X3 = L.Square().Add(L).Add(dx).Add(curve.A);
+                    ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+
+                    return new F2mPoint(curve, X3, Y3, IsCompressed);
+                }
+                case ECCurve.COORD_HOMOGENEOUS:
+                {
+                    ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+                    ECFieldElement Y2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+                    ECFieldElement U1 = Y2, V1 = X2;
+                    if (!Z1IsOne)
+                    {
+                        U1 = U1.Multiply(Z1);
+                        V1 = V1.Multiply(Z1);
+                    }
+
+                    bool Z2IsOne = Z2.IsOne;
+                    ECFieldElement U2 = Y1, V2 = X1;
+                    if (!Z2IsOne)
+                    {
+                        U2 = U2.Multiply(Z2);
+                        V2 = V2.Multiply(Z2);
+                    }
+
+                    ECFieldElement U = U1.Add(U2);
+                    ECFieldElement V = V1.Add(V2);
+
+                    if (V.IsZero)
+                    {
+                        if (U.IsZero)
+                        {
+                            return (F2mPoint)Twice();
+                        }
+
+                        return (F2mPoint)curve.Infinity;
+                    }
+
+                    ECFieldElement VSq = V.Square();
+                    ECFieldElement VCu = VSq.Multiply(V);
+                    ECFieldElement W = Z1IsOne ? Z2 : Z2IsOne ? Z1 : Z1.Multiply(Z2);
+                    ECFieldElement uv = U.Add(V);
+                    ECFieldElement A = uv.MultiplyPlusProduct(U, VSq, curve.A).Multiply(W).Add(VCu);
+
+                    ECFieldElement X3 = V.Multiply(A);
+                    ECFieldElement VSqZ2 = Z2IsOne ? VSq : VSq.Multiply(Z2);
+                    ECFieldElement Y3 = U.MultiplyPlusProduct(X1, V, Y1).MultiplyPlusProduct(VSqZ2, uv, A);
+                    ECFieldElement Z3 = VCu.Multiply(W);
+
+                    return new F2mPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    if (X1.IsZero)
+                    {
+                        if (X2.IsZero)
+                            return (F2mPoint)curve.Infinity;
+
+                        return b.AddSimple(this);
+                    }
+
+                    ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+                    ECFieldElement L2 = b.RawYCoord, Z2 = b.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+                    ECFieldElement U2 = X2, S2 = L2;
+                    if (!Z1IsOne)
+                    {
+                        U2 = U2.Multiply(Z1);
+                        S2 = S2.Multiply(Z1);
+                    }
+
+                    bool Z2IsOne = Z2.IsOne;
+                    ECFieldElement U1 = X1, S1 = L1;
+                    if (!Z2IsOne)
+                    {
+                        U1 = U1.Multiply(Z2);
+                        S1 = S1.Multiply(Z2);
+                    }
+
+                    ECFieldElement A = S1.Add(S2);
+                    ECFieldElement B = U1.Add(U2);
+
+                    if (B.IsZero)
+                    {
+                        if (A.IsZero)
+                        {
+                            return (F2mPoint)Twice();
+                        }
+
+                        return (F2mPoint)curve.Infinity;
+                    }
+
+                    ECFieldElement X3, L3, Z3;
+                    if (X2.IsZero)
+                    {
+                        // TODO This can probably be optimized quite a bit
+                        ECPoint p = this.Normalize();
+                        X1 = p.RawXCoord;
+                        ECFieldElement Y1 = p.YCoord;
+
+                        ECFieldElement Y2 = L2;
+                        ECFieldElement L = Y1.Add(Y2).Divide(X1);
+
+                        X3 = L.Square().Add(L).Add(X1).Add(curve.A);
+                        if (X3.IsZero)
+                        {
+                            return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed);
+                        }
+
+                        ECFieldElement Y3 = L.Multiply(X1.Add(X3)).Add(X3).Add(Y1);
+                        L3 = Y3.Divide(X3).Add(X3);
+                        Z3 = curve.FromBigInteger(BigInteger.One);
+                    }
+                    else
+                    {
+                        B = B.Square();
+
+                        ECFieldElement AU1 = A.Multiply(U1);
+                        ECFieldElement AU2 = A.Multiply(U2);
+
+                        X3 = AU1.Multiply(AU2);
+                        if (X3.IsZero)
+                        {
+                            return new F2mPoint(curve, X3, curve.B.Sqrt(), IsCompressed);
+                        }
+
+                        ECFieldElement ABZ2 = A.Multiply(B);
+                        if (!Z2IsOne)
+                        {
+                            ABZ2 = ABZ2.Multiply(Z2);
+                        }
+
+                        L3 = AU2.Add(B).SquarePlusProduct(ABZ2, L1.Add(Z1));
+
+                        Z3 = ABZ2;
+                        if (!Z1IsOne)
+                        {
+                            Z3 = Z3.Multiply(Z1);
+                        }
+                    }
+
+                    return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see org.bouncycastle.math.ec.ECPoint#subtract(org.bouncycastle.math.ec.ECPoint)
+         */
+        public override ECPoint Subtract(
+            ECPoint b)
+        {
+            CheckPoints(this, b);
+            return SubtractSimple((F2mPoint) b);
+        }
+
+        /**
+         * Subtracts another <code>ECPoints.F2m</code> from <code>this</code>
+         * without checking if both points are on the same curve. Used by
+         * multiplication algorithms, because there all points are a multiple
+         * of the same point and hence the checks can be omitted.
+         * @param b The other <code>ECPoints.F2m</code> to subtract from
+         * <code>this</code>.
+         * @return <code>this - b</code>
+         */
+        internal F2mPoint SubtractSimple(
+            F2mPoint b)
+        {
+            if (b.IsInfinity)
+                return this;
+
+            // Add -b
+            return AddSimple((F2mPoint) b.Negate());
+        }
+
+        public virtual F2mPoint Tau()
+        {
+            if (this.IsInfinity)
+            {
+                return this;
+            }
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            ECFieldElement X1 = this.RawXCoord;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                case ECCurve.COORD_LAMBDA_AFFINE:
+                {
+                    ECFieldElement Y1 = this.RawYCoord;
+                    return new F2mPoint(curve, X1.Square(), Y1.Square(), IsCompressed);
+                }
+                case ECCurve.COORD_HOMOGENEOUS:
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+                    return new F2mPoint(curve, X1.Square(), Y1.Square(), new ECFieldElement[] { Z1.Square() }, IsCompressed);
+                }
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+
+        /* (non-Javadoc)
+         * @see Org.BouncyCastle.Math.EC.ECPoint#twice()
+         */
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            ECFieldElement X1 = this.RawXCoord;
+            if (X1.IsZero)
+            {
+                // A point with X == 0 is it's own additive inverse
+                return curve.Infinity;
+            }
+
+            int coord = curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement Y1 = this.RawYCoord;
+
+                    ECFieldElement L1 = Y1.Divide(X1).Add(X1);
+
+                    ECFieldElement X3 = L1.Square().Add(L1).Add(curve.A);
+                    ECFieldElement Y3 = X1.SquarePlusProduct(X3, L1.AddOne());
+
+                    return new F2mPoint(curve, X3, Y3, IsCompressed);
+                }
+                case ECCurve.COORD_HOMOGENEOUS:
+                {
+                    ECFieldElement Y1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+                    ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+                    ECFieldElement Y1Z1 = Z1IsOne ? Y1 : Y1.Multiply(Z1);
+
+                    ECFieldElement X1Sq = X1.Square();
+                    ECFieldElement S = X1Sq.Add(Y1Z1);
+                    ECFieldElement V = X1Z1;
+                    ECFieldElement vSquared = V.Square();
+                    ECFieldElement sv = S.Add(V);
+                    ECFieldElement h = sv.MultiplyPlusProduct(S, vSquared, curve.A);
+
+                    ECFieldElement X3 = V.Multiply(h);
+                    ECFieldElement Y3 = X1Sq.Square().MultiplyPlusProduct(V, h, sv);
+                    ECFieldElement Z3 = V.Multiply(vSquared);
+
+                    return new F2mPoint(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+
+                    bool Z1IsOne = Z1.IsOne;
+                    ECFieldElement L1Z1 = Z1IsOne ? L1 : L1.Multiply(Z1);
+                    ECFieldElement Z1Sq = Z1IsOne ? Z1 : Z1.Square();
+                    ECFieldElement a = curve.A;
+                    ECFieldElement aZ1Sq = Z1IsOne ? a : a.Multiply(Z1Sq);
+                    ECFieldElement T = L1.Square().Add(L1Z1).Add(aZ1Sq);
+                    if (T.IsZero)
+                    {
+                        return new F2mPoint(curve, T, curve.B.Sqrt(), IsCompressed);
+                    }
+
+                    ECFieldElement X3 = T.Square();
+                    ECFieldElement Z3 = Z1IsOne ? T : T.Multiply(Z1Sq);
+
+                    ECFieldElement b = curve.B;
+                    ECFieldElement L3;
+                    if (b.BitLength < (curve.FieldSize >> 1))
+                    {
+                        ECFieldElement t1 = L1.Add(X1).Square();
+                        ECFieldElement t2;
+                        if (b.IsOne)
+                        {
+                            t2 = aZ1Sq.Add(Z1Sq).Square();
+                        }
+                        else
+                        {
+                            // TODO Can be calculated with one square if we pre-compute sqrt(b)
+                            t2 = aZ1Sq.SquarePlusProduct(b, Z1Sq.Square());
+                        }
+                        L3 = t1.Add(T).Add(Z1Sq).Multiply(t1).Add(t2).Add(X3);
+                        if (a.IsZero)
+                        {
+                            L3 = L3.Add(Z3);
+                        }
+                        else if (!a.IsOne)
+                        {
+                            L3 = L3.Add(a.AddOne().Multiply(Z3));
+                        }
+                    }
+                    else
+                    {
+                        ECFieldElement X1Z1 = Z1IsOne ? X1 : X1.Multiply(Z1);
+                        L3 = X1Z1.SquarePlusProduct(T, L1Z1).Add(X3).Add(Z3);
+                    }
+
+                    return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            ECFieldElement X1 = this.RawXCoord;
+            if (X1.IsZero)
+            {
+                // A point with X == 0 is it's own additive inverse
+                return b;
+            }
+
+            int coord = curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    // NOTE: twicePlus() only optimized for lambda-affine argument
+                    ECFieldElement X2 = b.RawXCoord, Z2 = b.RawZCoords[0];
+                    if (X2.IsZero || !Z2.IsOne)
+                    {
+                        return Twice().Add(b);
+                    }
+
+                    ECFieldElement L1 = this.RawYCoord, Z1 = this.RawZCoords[0];
+                    ECFieldElement L2 = b.RawYCoord;
+
+                    ECFieldElement X1Sq = X1.Square();
+                    ECFieldElement L1Sq = L1.Square();
+                    ECFieldElement Z1Sq = Z1.Square();
+                    ECFieldElement L1Z1 = L1.Multiply(Z1);
+
+                    ECFieldElement T = curve.A.Multiply(Z1Sq).Add(L1Sq).Add(L1Z1);
+                    ECFieldElement L2plus1 = L2.AddOne();
+                    ECFieldElement A = curve.A.Add(L2plus1).Multiply(Z1Sq).Add(L1Sq).MultiplyPlusProduct(T, X1Sq, Z1Sq);
+                    ECFieldElement X2Z1Sq = X2.Multiply(Z1Sq);
+                    ECFieldElement B = X2Z1Sq.Add(T).Square();
+
+                    if (B.IsZero)
+                    {
+                        if (A.IsZero)
+                        {
+                            return b.Twice();
+                        }
+
+                        return curve.Infinity;
+                    }
+
+                    if (A.IsZero)
+                    {
+                        return new F2mPoint(curve, A, curve.B.Sqrt(), IsCompressed);
+                    }
+
+                    ECFieldElement X3 = A.Square().Multiply(X2Z1Sq);
+                    ECFieldElement Z3 = A.Multiply(B).Multiply(Z1Sq);
+                    ECFieldElement L3 = A.Add(B).Square().MultiplyPlusProduct(T, L2plus1, Z3);
+
+                    return new F2mPoint(curve, X3, L3, new ECFieldElement[] { Z3 }, IsCompressed);
+                }
+                default:
+                {
+                    return Twice().Add(b);
+                }
+            }
+        }
+
+        public override ECPoint Negate()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECFieldElement X = this.RawXCoord;
+            if (X.IsZero)
+                return this;
+
+            ECCurve curve = this.Curve;
+            int coord = curve.CoordinateSystem;
+
+            switch (coord)
+            {
+                case ECCurve.COORD_AFFINE:
+                {
+                    ECFieldElement Y = this.RawYCoord;
+                    return new F2mPoint(curve, X, Y.Add(X), IsCompressed);
+                }
+                case ECCurve.COORD_HOMOGENEOUS:
+                {
+                    ECFieldElement Y = this.RawYCoord, Z = this.RawZCoords[0];
+                    return new F2mPoint(curve, X, Y.Add(X), new ECFieldElement[] { Z }, IsCompressed);
+                }
+                case ECCurve.COORD_LAMBDA_AFFINE:
+                {
+                    ECFieldElement L = this.RawYCoord;
+                    return new F2mPoint(curve, X, L.AddOne(), IsCompressed);
+                }
+                case ECCurve.COORD_LAMBDA_PROJECTIVE:
+                {
+                    // L is actually Lambda (X + Y/X) here
+                    ECFieldElement L = this.RawYCoord, Z = this.RawZCoords[0];
+                    return new F2mPoint(curve, X, L.Add(Z), new ECFieldElement[] { Z }, IsCompressed);
+                }
+                default:
+                {
+                    throw new InvalidOperationException("unsupported coordinate system");
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ECPointMap.cs b/BouncyCastle.AxCrypt/src/math/ec/ECPointMap.cs
new file mode 100644
index 0000000..e78c800
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ECPointMap.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public interface ECPointMap
+    {
+        ECPoint Map(ECPoint p);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/IntArray.cs b/BouncyCastle.AxCrypt/src/math/ec/IntArray.cs
new file mode 100644
index 0000000..1089966
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/IntArray.cs
@@ -0,0 +1,485 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Math.EC
+{
+	internal class IntArray
+    {
+        // TODO make m fixed for the IntArray, and hence compute T once and for all
+
+		// TODO Use uint's internally?
+		private int[] m_ints;
+
+		public IntArray(int intLen)
+		{
+			m_ints = new int[intLen];
+		}
+
+		private IntArray(int[] ints)
+		{
+			m_ints = ints;
+		}
+
+		public IntArray(BigInteger bigInt)
+			: this(bigInt, 0)
+		{
+		}
+
+		public IntArray(BigInteger bigInt, int minIntLen)
+		{
+			if (bigInt.SignValue == -1)
+				throw new ArgumentException("Only positive Integers allowed", "bigint");
+
+			if (bigInt.SignValue == 0)
+			{
+				m_ints = new int[] { 0 };
+				return;
+			}
+
+			byte[] barr = bigInt.ToByteArrayUnsigned();
+			int barrLen = barr.Length;
+
+			int intLen = (barrLen + 3) / 4;
+			m_ints = new int[System.Math.Max(intLen, minIntLen)];
+
+			int rem = barrLen % 4;
+			int barrI = 0;
+
+			if (0 < rem)
+			{
+				int temp = (int) barr[barrI++];
+				while (barrI < rem)
+				{
+					temp = temp << 8 | (int) barr[barrI++];
+				}
+				m_ints[--intLen] = temp;
+			}
+
+			while (intLen > 0)
+			{
+				int temp = (int) barr[barrI++];
+				for (int i = 1; i < 4; i++)
+				{
+					temp = temp << 8 | (int) barr[barrI++];
+				}
+				m_ints[--intLen] = temp;
+			}
+		}
+
+		public int GetUsedLength()
+		{
+			int highestIntPos = m_ints.Length;
+
+			if (highestIntPos < 1)
+				return 0;
+
+			// Check if first element will act as sentinel
+			if (m_ints[0] != 0)
+			{
+				while (m_ints[--highestIntPos] == 0)
+				{
+				}
+				return highestIntPos + 1;
+			}
+
+			do
+			{
+				if (m_ints[--highestIntPos] != 0)
+				{
+					return highestIntPos + 1;
+				}
+			}
+			while (highestIntPos > 0);
+
+			return 0;
+		}
+
+		public int BitLength
+		{
+			get
+			{
+				// JDK 1.5: see Integer.numberOfLeadingZeros()
+				int intLen = GetUsedLength();
+				if (intLen == 0)
+					return 0;
+
+				int last = intLen - 1;
+				uint highest = (uint) m_ints[last];
+				int bits = (last << 5) + 1;
+
+				// A couple of binary search steps
+				if (highest > 0x0000ffff)
+				{
+					if (highest > 0x00ffffff)
+					{
+						bits += 24;
+						highest >>= 24;
+					}
+					else
+					{
+						bits += 16;
+						highest >>= 16;
+					}
+				}
+				else if (highest > 0x000000ff)
+				{
+					bits += 8;
+					highest >>= 8;
+				}
+
+				while (highest > 1)
+				{
+					++bits;
+					highest >>= 1;
+				}
+
+				return bits;
+			}
+		}
+
+		private int[] resizedInts(int newLen)
+		{
+			int[] newInts = new int[newLen];
+			int oldLen = m_ints.Length;
+			int copyLen = oldLen < newLen ? oldLen : newLen;
+			Array.Copy(m_ints, 0, newInts, 0, copyLen);
+			return newInts;
+		}
+
+		public BigInteger ToBigInteger()
+		{
+			int usedLen = GetUsedLength();
+			if (usedLen == 0)
+			{
+				return BigInteger.Zero;
+			}
+
+			int highestInt = m_ints[usedLen - 1];
+			byte[] temp = new byte[4];
+			int barrI = 0;
+			bool trailingZeroBytesDone = false;
+			for (int j = 3; j >= 0; j--)
+			{
+				byte thisByte = (byte)((int)((uint) highestInt >> (8 * j)));
+				if (trailingZeroBytesDone || (thisByte != 0))
+				{
+					trailingZeroBytesDone = true;
+					temp[barrI++] = thisByte;
+				}
+			}
+
+			int barrLen = 4 * (usedLen - 1) + barrI;
+			byte[] barr = new byte[barrLen];
+			for (int j = 0; j < barrI; j++)
+			{
+				barr[j] = temp[j];
+			}
+			// Highest value int is done now
+
+			for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+			{
+				for (int j = 3; j >= 0; j--)
+				{
+					barr[barrI++] = (byte)((int)((uint)m_ints[iarrJ] >> (8 * j)));
+				}
+			}
+			return new BigInteger(1, barr);
+		}
+
+		public void ShiftLeft()
+		{
+			int usedLen = GetUsedLength();
+			if (usedLen == 0)
+			{
+				return;
+			}
+			if (m_ints[usedLen - 1] < 0)
+			{
+				// highest bit of highest used byte is set, so shifting left will
+				// make the IntArray one byte longer
+				usedLen++;
+				if (usedLen > m_ints.Length)
+				{
+					// make the m_ints one byte longer, because we need one more
+					// byte which is not available in m_ints
+					m_ints = resizedInts(m_ints.Length + 1);
+				}
+			}
+
+			bool carry = false;
+			for (int i = 0; i < usedLen; i++)
+			{
+				// nextCarry is true if highest bit is set
+				bool nextCarry = m_ints[i] < 0;
+				m_ints[i] <<= 1;
+				if (carry)
+				{
+					// set lowest bit
+					m_ints[i] |= 1;
+				}
+				carry = nextCarry;
+			}
+		}
+
+		public IntArray ShiftLeft(int n)
+		{
+			int usedLen = GetUsedLength();
+			if (usedLen == 0)
+			{
+				return this;
+			}
+
+			if (n == 0)
+			{
+				return this;
+			}
+
+			if (n > 31)
+			{
+				throw new ArgumentException("shiftLeft() for max 31 bits "
+					+ ", " + n + "bit shift is not possible", "n");
+			}
+
+			int[] newInts = new int[usedLen + 1];
+
+			int nm32 = 32 - n;
+			newInts[0] = m_ints[0] << n;
+			for (int i = 1; i < usedLen; i++)
+			{
+				newInts[i] = (m_ints[i] << n) | (int)((uint)m_ints[i - 1] >> nm32);
+			}
+			newInts[usedLen] = (int)((uint)m_ints[usedLen - 1] >> nm32);
+
+			return new IntArray(newInts);
+		}
+
+		public void AddShifted(IntArray other, int shift)
+		{
+			int usedLenOther = other.GetUsedLength();
+			int newMinUsedLen = usedLenOther + shift;
+			if (newMinUsedLen > m_ints.Length)
+			{
+				m_ints = resizedInts(newMinUsedLen);
+				//Console.WriteLine("Resize required");
+			}
+
+			for (int i = 0; i < usedLenOther; i++)
+			{
+				m_ints[i + shift] ^= other.m_ints[i];
+			}
+		}
+
+		public int Length
+		{
+			get { return m_ints.Length; }
+		}
+
+		public bool TestBit(int n)
+		{
+			// theInt = n / 32
+			int theInt = n >> 5;
+			// theBit = n % 32
+			int theBit = n & 0x1F;
+			int tester = 1 << theBit;
+			return ((m_ints[theInt] & tester) != 0);
+		}
+
+		public void FlipBit(int n)
+		{
+			// theInt = n / 32
+			int theInt = n >> 5;
+			// theBit = n % 32
+			int theBit = n & 0x1F;
+			int flipper = 1 << theBit;
+			m_ints[theInt] ^= flipper;
+		}
+
+		public void SetBit(int n)
+		{
+			// theInt = n / 32
+			int theInt = n >> 5;
+			// theBit = n % 32
+			int theBit = n & 0x1F;
+			int setter = 1 << theBit;
+			m_ints[theInt] |= setter;
+		}
+
+		public IntArray Multiply(IntArray other, int m)
+		{
+			// Lenght of c is 2m bits rounded up to the next int (32 bit)
+			int t = (m + 31) >> 5;
+			if (m_ints.Length < t)
+			{
+				m_ints = resizedInts(t);
+			}
+
+			IntArray b = new IntArray(other.resizedInts(other.Length + 1));
+			IntArray c = new IntArray((m + m + 31) >> 5);
+			// IntArray c = new IntArray(t + t);
+			int testBit = 1;
+			for (int k = 0; k < 32; k++)
+			{
+				for (int j = 0; j < t; j++)
+				{
+					if ((m_ints[j] & testBit) != 0)
+					{
+						// The kth bit of m_ints[j] is set
+						c.AddShifted(b, j);
+					}
+				}
+				testBit <<= 1;
+				b.ShiftLeft();
+			}
+			return c;
+		}
+
+		// public IntArray multiplyLeftToRight(IntArray other, int m) {
+		// // Lenght of c is 2m bits rounded up to the next int (32 bit)
+		// int t = (m + 31) / 32;
+		// if (m_ints.Length < t) {
+		// m_ints = resizedInts(t);
+		// }
+		//
+		// IntArray b = new IntArray(other.resizedInts(other.getLength() + 1));
+		// IntArray c = new IntArray((m + m + 31) / 32);
+		// // IntArray c = new IntArray(t + t);
+		// int testBit = 1 << 31;
+		// for (int k = 31; k >= 0; k--) {
+		// for (int j = 0; j < t; j++) {
+		// if ((m_ints[j] & testBit) != 0) {
+		// // The kth bit of m_ints[j] is set
+		// c.addShifted(b, j);
+		// }
+		// }
+		// testBit >>>= 1;
+		// if (k > 0) {
+		// c.shiftLeft();
+		// }
+		// }
+		// return c;
+		// }
+
+		// TODO note, redPol.Length must be 3 for TPB and 5 for PPB
+		public void Reduce(int m, int[] redPol)
+		{
+			for (int i = m + m - 2; i >= m; i--)
+			{
+				if (TestBit(i))
+				{
+					int bit = i - m;
+					FlipBit(bit);
+					FlipBit(i);
+					int l = redPol.Length;
+					while (--l >= 0)
+					{
+						FlipBit(redPol[l] + bit);
+					}
+				}
+			}
+			m_ints = resizedInts((m + 31) >> 5);
+		}
+
+		public IntArray Square(int m)
+		{
+			// TODO make the table static readonly
+			int[] table = { 0x0, 0x1, 0x4, 0x5, 0x10, 0x11, 0x14, 0x15, 0x40,
+									0x41, 0x44, 0x45, 0x50, 0x51, 0x54, 0x55 };
+
+			int t = (m + 31) >> 5;
+			if (m_ints.Length < t)
+			{
+				m_ints = resizedInts(t);
+			}
+
+			IntArray c = new IntArray(t + t);
+
+			// TODO twice the same code, put in separate private method
+			for (int i = 0; i < t; i++)
+			{
+				int v0 = 0;
+				for (int j = 0; j < 4; j++)
+				{
+					v0 = (int)((uint) v0 >> 8);
+					int u = (int)((uint)m_ints[i] >> (j * 4)) & 0xF;
+					int w = table[u] << 24;
+					v0 |= w;
+				}
+				c.m_ints[i + i] = v0;
+
+				v0 = 0;
+				int upper = (int)((uint) m_ints[i] >> 16);
+				for (int j = 0; j < 4; j++)
+				{
+					v0 = (int)((uint) v0 >> 8);
+					int u = (int)((uint)upper >> (j * 4)) & 0xF;
+					int w = table[u] << 24;
+					v0 |= w;
+				}
+				c.m_ints[i + i + 1] = v0;
+			}
+			return c;
+		}
+
+		public override bool Equals(object o)
+		{
+			if (!(o is IntArray))
+			{
+				return false;
+			}
+			IntArray other = (IntArray) o;
+			int usedLen = GetUsedLength();
+			if (other.GetUsedLength() != usedLen)
+			{
+				return false;
+			}
+			for (int i = 0; i < usedLen; i++)
+			{
+				if (m_ints[i] != other.m_ints[i])
+				{
+					return false;
+				}
+			}
+			return true;
+		}
+
+		public override int GetHashCode()
+		{
+			int i = GetUsedLength();
+			int hc = i;
+			while (--i >= 0)
+			{
+				hc *= 17;
+				hc ^= m_ints[i];
+			}
+			return hc;
+		}
+
+		internal IntArray Copy()
+		{
+			return new IntArray((int[]) m_ints.Clone());
+		}
+
+		public override string ToString()
+		{
+			int usedLen = GetUsedLength();
+			if (usedLen == 0)
+			{
+				return "0";
+			}
+
+			StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[usedLen - 1], 2));
+			for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+			{
+				string hexString = Convert.ToString(m_ints[iarrJ], 2);
+
+				// Add leading zeroes, except for highest significant int
+				for (int i = hexString.Length; i < 8; i++)
+				{
+					hexString = "0" + hexString;
+				}
+				sb.Append(hexString);
+			}
+			return sb.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/LongArray.cs b/BouncyCastle.AxCrypt/src/math/ec/LongArray.cs
new file mode 100644
index 0000000..c4e3dac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/LongArray.cs
@@ -0,0 +1,2201 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    internal class LongArray
+    {
+        //private static long DEInterleave_MASK = 0x5555555555555555L;
+
+        /*
+         * This expands 8 bit indices into 16 bit contents (high bit 14), by inserting 0s between bits.
+         * In a binary field, this operation is the same as squaring an 8 bit number.
+         */
+        private static readonly int[] INTERLEAVE2_TABLE = new int[]
+        {
+            0x0000, 0x0001, 0x0004, 0x0005, 0x0010, 0x0011, 0x0014, 0x0015,
+            0x0040, 0x0041, 0x0044, 0x0045, 0x0050, 0x0051, 0x0054, 0x0055,
+            0x0100, 0x0101, 0x0104, 0x0105, 0x0110, 0x0111, 0x0114, 0x0115,
+            0x0140, 0x0141, 0x0144, 0x0145, 0x0150, 0x0151, 0x0154, 0x0155,
+            0x0400, 0x0401, 0x0404, 0x0405, 0x0410, 0x0411, 0x0414, 0x0415,
+            0x0440, 0x0441, 0x0444, 0x0445, 0x0450, 0x0451, 0x0454, 0x0455,
+            0x0500, 0x0501, 0x0504, 0x0505, 0x0510, 0x0511, 0x0514, 0x0515,
+            0x0540, 0x0541, 0x0544, 0x0545, 0x0550, 0x0551, 0x0554, 0x0555,
+            0x1000, 0x1001, 0x1004, 0x1005, 0x1010, 0x1011, 0x1014, 0x1015,
+            0x1040, 0x1041, 0x1044, 0x1045, 0x1050, 0x1051, 0x1054, 0x1055,
+            0x1100, 0x1101, 0x1104, 0x1105, 0x1110, 0x1111, 0x1114, 0x1115,
+            0x1140, 0x1141, 0x1144, 0x1145, 0x1150, 0x1151, 0x1154, 0x1155,
+            0x1400, 0x1401, 0x1404, 0x1405, 0x1410, 0x1411, 0x1414, 0x1415,
+            0x1440, 0x1441, 0x1444, 0x1445, 0x1450, 0x1451, 0x1454, 0x1455,
+            0x1500, 0x1501, 0x1504, 0x1505, 0x1510, 0x1511, 0x1514, 0x1515,
+            0x1540, 0x1541, 0x1544, 0x1545, 0x1550, 0x1551, 0x1554, 0x1555,
+            0x4000, 0x4001, 0x4004, 0x4005, 0x4010, 0x4011, 0x4014, 0x4015,
+            0x4040, 0x4041, 0x4044, 0x4045, 0x4050, 0x4051, 0x4054, 0x4055,
+            0x4100, 0x4101, 0x4104, 0x4105, 0x4110, 0x4111, 0x4114, 0x4115,
+            0x4140, 0x4141, 0x4144, 0x4145, 0x4150, 0x4151, 0x4154, 0x4155,
+            0x4400, 0x4401, 0x4404, 0x4405, 0x4410, 0x4411, 0x4414, 0x4415,
+            0x4440, 0x4441, 0x4444, 0x4445, 0x4450, 0x4451, 0x4454, 0x4455,
+            0x4500, 0x4501, 0x4504, 0x4505, 0x4510, 0x4511, 0x4514, 0x4515,
+            0x4540, 0x4541, 0x4544, 0x4545, 0x4550, 0x4551, 0x4554, 0x4555,
+            0x5000, 0x5001, 0x5004, 0x5005, 0x5010, 0x5011, 0x5014, 0x5015,
+            0x5040, 0x5041, 0x5044, 0x5045, 0x5050, 0x5051, 0x5054, 0x5055,
+            0x5100, 0x5101, 0x5104, 0x5105, 0x5110, 0x5111, 0x5114, 0x5115,
+            0x5140, 0x5141, 0x5144, 0x5145, 0x5150, 0x5151, 0x5154, 0x5155,
+            0x5400, 0x5401, 0x5404, 0x5405, 0x5410, 0x5411, 0x5414, 0x5415,
+            0x5440, 0x5441, 0x5444, 0x5445, 0x5450, 0x5451, 0x5454, 0x5455,
+            0x5500, 0x5501, 0x5504, 0x5505, 0x5510, 0x5511, 0x5514, 0x5515,
+            0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
+        };
+
+        /*
+         * This expands 7 bit indices into 21 bit contents (high bit 18), by inserting 0s between bits.
+         */
+        private static readonly int[] INTERLEAVE3_TABLE = new  int[]
+        {
+            0x00000, 0x00001, 0x00008, 0x00009, 0x00040, 0x00041, 0x00048, 0x00049,
+            0x00200, 0x00201, 0x00208, 0x00209, 0x00240, 0x00241, 0x00248, 0x00249,
+            0x01000, 0x01001, 0x01008, 0x01009, 0x01040, 0x01041, 0x01048, 0x01049,
+            0x01200, 0x01201, 0x01208, 0x01209, 0x01240, 0x01241, 0x01248, 0x01249,
+            0x08000, 0x08001, 0x08008, 0x08009, 0x08040, 0x08041, 0x08048, 0x08049,
+            0x08200, 0x08201, 0x08208, 0x08209, 0x08240, 0x08241, 0x08248, 0x08249,
+            0x09000, 0x09001, 0x09008, 0x09009, 0x09040, 0x09041, 0x09048, 0x09049,
+            0x09200, 0x09201, 0x09208, 0x09209, 0x09240, 0x09241, 0x09248, 0x09249,
+            0x40000, 0x40001, 0x40008, 0x40009, 0x40040, 0x40041, 0x40048, 0x40049,
+            0x40200, 0x40201, 0x40208, 0x40209, 0x40240, 0x40241, 0x40248, 0x40249,
+            0x41000, 0x41001, 0x41008, 0x41009, 0x41040, 0x41041, 0x41048, 0x41049,
+            0x41200, 0x41201, 0x41208, 0x41209, 0x41240, 0x41241, 0x41248, 0x41249,
+            0x48000, 0x48001, 0x48008, 0x48009, 0x48040, 0x48041, 0x48048, 0x48049,
+            0x48200, 0x48201, 0x48208, 0x48209, 0x48240, 0x48241, 0x48248, 0x48249,
+            0x49000, 0x49001, 0x49008, 0x49009, 0x49040, 0x49041, 0x49048, 0x49049,
+            0x49200, 0x49201, 0x49208, 0x49209, 0x49240, 0x49241, 0x49248, 0x49249
+        };
+
+        /*
+         * This expands 8 bit indices into 32 bit contents (high bit 28), by inserting 0s between bits.
+         */
+        private static readonly int[] INTERLEAVE4_TABLE = new int[]
+        {
+            0x00000000, 0x00000001, 0x00000010, 0x00000011, 0x00000100, 0x00000101, 0x00000110, 0x00000111,
+            0x00001000, 0x00001001, 0x00001010, 0x00001011, 0x00001100, 0x00001101, 0x00001110, 0x00001111,
+            0x00010000, 0x00010001, 0x00010010, 0x00010011, 0x00010100, 0x00010101, 0x00010110, 0x00010111,
+            0x00011000, 0x00011001, 0x00011010, 0x00011011, 0x00011100, 0x00011101, 0x00011110, 0x00011111,
+            0x00100000, 0x00100001, 0x00100010, 0x00100011, 0x00100100, 0x00100101, 0x00100110, 0x00100111,
+            0x00101000, 0x00101001, 0x00101010, 0x00101011, 0x00101100, 0x00101101, 0x00101110, 0x00101111,
+            0x00110000, 0x00110001, 0x00110010, 0x00110011, 0x00110100, 0x00110101, 0x00110110, 0x00110111,
+            0x00111000, 0x00111001, 0x00111010, 0x00111011, 0x00111100, 0x00111101, 0x00111110, 0x00111111,
+            0x01000000, 0x01000001, 0x01000010, 0x01000011, 0x01000100, 0x01000101, 0x01000110, 0x01000111,
+            0x01001000, 0x01001001, 0x01001010, 0x01001011, 0x01001100, 0x01001101, 0x01001110, 0x01001111,
+            0x01010000, 0x01010001, 0x01010010, 0x01010011, 0x01010100, 0x01010101, 0x01010110, 0x01010111,
+            0x01011000, 0x01011001, 0x01011010, 0x01011011, 0x01011100, 0x01011101, 0x01011110, 0x01011111,
+            0x01100000, 0x01100001, 0x01100010, 0x01100011, 0x01100100, 0x01100101, 0x01100110, 0x01100111,
+            0x01101000, 0x01101001, 0x01101010, 0x01101011, 0x01101100, 0x01101101, 0x01101110, 0x01101111,
+            0x01110000, 0x01110001, 0x01110010, 0x01110011, 0x01110100, 0x01110101, 0x01110110, 0x01110111,
+            0x01111000, 0x01111001, 0x01111010, 0x01111011, 0x01111100, 0x01111101, 0x01111110, 0x01111111,
+            0x10000000, 0x10000001, 0x10000010, 0x10000011, 0x10000100, 0x10000101, 0x10000110, 0x10000111,
+            0x10001000, 0x10001001, 0x10001010, 0x10001011, 0x10001100, 0x10001101, 0x10001110, 0x10001111,
+            0x10010000, 0x10010001, 0x10010010, 0x10010011, 0x10010100, 0x10010101, 0x10010110, 0x10010111,
+            0x10011000, 0x10011001, 0x10011010, 0x10011011, 0x10011100, 0x10011101, 0x10011110, 0x10011111,
+            0x10100000, 0x10100001, 0x10100010, 0x10100011, 0x10100100, 0x10100101, 0x10100110, 0x10100111,
+            0x10101000, 0x10101001, 0x10101010, 0x10101011, 0x10101100, 0x10101101, 0x10101110, 0x10101111,
+            0x10110000, 0x10110001, 0x10110010, 0x10110011, 0x10110100, 0x10110101, 0x10110110, 0x10110111,
+            0x10111000, 0x10111001, 0x10111010, 0x10111011, 0x10111100, 0x10111101, 0x10111110, 0x10111111,
+            0x11000000, 0x11000001, 0x11000010, 0x11000011, 0x11000100, 0x11000101, 0x11000110, 0x11000111,
+            0x11001000, 0x11001001, 0x11001010, 0x11001011, 0x11001100, 0x11001101, 0x11001110, 0x11001111,
+            0x11010000, 0x11010001, 0x11010010, 0x11010011, 0x11010100, 0x11010101, 0x11010110, 0x11010111,
+            0x11011000, 0x11011001, 0x11011010, 0x11011011, 0x11011100, 0x11011101, 0x11011110, 0x11011111,
+            0x11100000, 0x11100001, 0x11100010, 0x11100011, 0x11100100, 0x11100101, 0x11100110, 0x11100111,
+            0x11101000, 0x11101001, 0x11101010, 0x11101011, 0x11101100, 0x11101101, 0x11101110, 0x11101111,
+            0x11110000, 0x11110001, 0x11110010, 0x11110011, 0x11110100, 0x11110101, 0x11110110, 0x11110111,
+            0x11111000, 0x11111001, 0x11111010, 0x11111011, 0x11111100, 0x11111101, 0x11111110, 0x11111111
+        };
+
+        /*
+         * This expands 7 bit indices into 35 bit contents (high bit 30), by inserting 0s between bits.
+         */
+        private static readonly int[] INTERLEAVE5_TABLE = new int[] {
+            0x00000000, 0x00000001, 0x00000020, 0x00000021, 0x00000400, 0x00000401, 0x00000420, 0x00000421,
+            0x00008000, 0x00008001, 0x00008020, 0x00008021, 0x00008400, 0x00008401, 0x00008420, 0x00008421,
+            0x00100000, 0x00100001, 0x00100020, 0x00100021, 0x00100400, 0x00100401, 0x00100420, 0x00100421,
+            0x00108000, 0x00108001, 0x00108020, 0x00108021, 0x00108400, 0x00108401, 0x00108420, 0x00108421,
+            0x02000000, 0x02000001, 0x02000020, 0x02000021, 0x02000400, 0x02000401, 0x02000420, 0x02000421,
+            0x02008000, 0x02008001, 0x02008020, 0x02008021, 0x02008400, 0x02008401, 0x02008420, 0x02008421,
+            0x02100000, 0x02100001, 0x02100020, 0x02100021, 0x02100400, 0x02100401, 0x02100420, 0x02100421,
+            0x02108000, 0x02108001, 0x02108020, 0x02108021, 0x02108400, 0x02108401, 0x02108420, 0x02108421,
+            0x40000000, 0x40000001, 0x40000020, 0x40000021, 0x40000400, 0x40000401, 0x40000420, 0x40000421,
+            0x40008000, 0x40008001, 0x40008020, 0x40008021, 0x40008400, 0x40008401, 0x40008420, 0x40008421,
+            0x40100000, 0x40100001, 0x40100020, 0x40100021, 0x40100400, 0x40100401, 0x40100420, 0x40100421,
+            0x40108000, 0x40108001, 0x40108020, 0x40108021, 0x40108400, 0x40108401, 0x40108420, 0x40108421,
+            0x42000000, 0x42000001, 0x42000020, 0x42000021, 0x42000400, 0x42000401, 0x42000420, 0x42000421,
+            0x42008000, 0x42008001, 0x42008020, 0x42008021, 0x42008400, 0x42008401, 0x42008420, 0x42008421,
+            0x42100000, 0x42100001, 0x42100020, 0x42100021, 0x42100400, 0x42100401, 0x42100420, 0x42100421,
+            0x42108000, 0x42108001, 0x42108020, 0x42108021, 0x42108400, 0x42108401, 0x42108420, 0x42108421
+        };
+
+        /*
+         * This expands 9 bit indices into 63 bit (long) contents (high bit 56), by inserting 0s between bits.
+         */
+        private static readonly long[] INTERLEAVE7_TABLE = new long[]
+        {
+            0x0000000000000000L, 0x0000000000000001L, 0x0000000000000080L, 0x0000000000000081L,
+            0x0000000000004000L, 0x0000000000004001L, 0x0000000000004080L, 0x0000000000004081L,
+            0x0000000000200000L, 0x0000000000200001L, 0x0000000000200080L, 0x0000000000200081L,
+            0x0000000000204000L, 0x0000000000204001L, 0x0000000000204080L, 0x0000000000204081L,
+            0x0000000010000000L, 0x0000000010000001L, 0x0000000010000080L, 0x0000000010000081L,
+            0x0000000010004000L, 0x0000000010004001L, 0x0000000010004080L, 0x0000000010004081L,
+            0x0000000010200000L, 0x0000000010200001L, 0x0000000010200080L, 0x0000000010200081L,
+            0x0000000010204000L, 0x0000000010204001L, 0x0000000010204080L, 0x0000000010204081L,
+            0x0000000800000000L, 0x0000000800000001L, 0x0000000800000080L, 0x0000000800000081L,
+            0x0000000800004000L, 0x0000000800004001L, 0x0000000800004080L, 0x0000000800004081L,
+            0x0000000800200000L, 0x0000000800200001L, 0x0000000800200080L, 0x0000000800200081L,
+            0x0000000800204000L, 0x0000000800204001L, 0x0000000800204080L, 0x0000000800204081L,
+            0x0000000810000000L, 0x0000000810000001L, 0x0000000810000080L, 0x0000000810000081L,
+            0x0000000810004000L, 0x0000000810004001L, 0x0000000810004080L, 0x0000000810004081L,
+            0x0000000810200000L, 0x0000000810200001L, 0x0000000810200080L, 0x0000000810200081L,
+            0x0000000810204000L, 0x0000000810204001L, 0x0000000810204080L, 0x0000000810204081L,
+            0x0000040000000000L, 0x0000040000000001L, 0x0000040000000080L, 0x0000040000000081L,
+            0x0000040000004000L, 0x0000040000004001L, 0x0000040000004080L, 0x0000040000004081L,
+            0x0000040000200000L, 0x0000040000200001L, 0x0000040000200080L, 0x0000040000200081L,
+            0x0000040000204000L, 0x0000040000204001L, 0x0000040000204080L, 0x0000040000204081L,
+            0x0000040010000000L, 0x0000040010000001L, 0x0000040010000080L, 0x0000040010000081L,
+            0x0000040010004000L, 0x0000040010004001L, 0x0000040010004080L, 0x0000040010004081L,
+            0x0000040010200000L, 0x0000040010200001L, 0x0000040010200080L, 0x0000040010200081L,
+            0x0000040010204000L, 0x0000040010204001L, 0x0000040010204080L, 0x0000040010204081L,
+            0x0000040800000000L, 0x0000040800000001L, 0x0000040800000080L, 0x0000040800000081L,
+            0x0000040800004000L, 0x0000040800004001L, 0x0000040800004080L, 0x0000040800004081L,
+            0x0000040800200000L, 0x0000040800200001L, 0x0000040800200080L, 0x0000040800200081L,
+            0x0000040800204000L, 0x0000040800204001L, 0x0000040800204080L, 0x0000040800204081L,
+            0x0000040810000000L, 0x0000040810000001L, 0x0000040810000080L, 0x0000040810000081L,
+            0x0000040810004000L, 0x0000040810004001L, 0x0000040810004080L, 0x0000040810004081L,
+            0x0000040810200000L, 0x0000040810200001L, 0x0000040810200080L, 0x0000040810200081L,
+            0x0000040810204000L, 0x0000040810204001L, 0x0000040810204080L, 0x0000040810204081L,
+            0x0002000000000000L, 0x0002000000000001L, 0x0002000000000080L, 0x0002000000000081L,
+            0x0002000000004000L, 0x0002000000004001L, 0x0002000000004080L, 0x0002000000004081L,
+            0x0002000000200000L, 0x0002000000200001L, 0x0002000000200080L, 0x0002000000200081L,
+            0x0002000000204000L, 0x0002000000204001L, 0x0002000000204080L, 0x0002000000204081L,
+            0x0002000010000000L, 0x0002000010000001L, 0x0002000010000080L, 0x0002000010000081L,
+            0x0002000010004000L, 0x0002000010004001L, 0x0002000010004080L, 0x0002000010004081L,
+            0x0002000010200000L, 0x0002000010200001L, 0x0002000010200080L, 0x0002000010200081L,
+            0x0002000010204000L, 0x0002000010204001L, 0x0002000010204080L, 0x0002000010204081L,
+            0x0002000800000000L, 0x0002000800000001L, 0x0002000800000080L, 0x0002000800000081L,
+            0x0002000800004000L, 0x0002000800004001L, 0x0002000800004080L, 0x0002000800004081L,
+            0x0002000800200000L, 0x0002000800200001L, 0x0002000800200080L, 0x0002000800200081L,
+            0x0002000800204000L, 0x0002000800204001L, 0x0002000800204080L, 0x0002000800204081L,
+            0x0002000810000000L, 0x0002000810000001L, 0x0002000810000080L, 0x0002000810000081L,
+            0x0002000810004000L, 0x0002000810004001L, 0x0002000810004080L, 0x0002000810004081L,
+            0x0002000810200000L, 0x0002000810200001L, 0x0002000810200080L, 0x0002000810200081L,
+            0x0002000810204000L, 0x0002000810204001L, 0x0002000810204080L, 0x0002000810204081L,
+            0x0002040000000000L, 0x0002040000000001L, 0x0002040000000080L, 0x0002040000000081L,
+            0x0002040000004000L, 0x0002040000004001L, 0x0002040000004080L, 0x0002040000004081L,
+            0x0002040000200000L, 0x0002040000200001L, 0x0002040000200080L, 0x0002040000200081L,
+            0x0002040000204000L, 0x0002040000204001L, 0x0002040000204080L, 0x0002040000204081L,
+            0x0002040010000000L, 0x0002040010000001L, 0x0002040010000080L, 0x0002040010000081L,
+            0x0002040010004000L, 0x0002040010004001L, 0x0002040010004080L, 0x0002040010004081L,
+            0x0002040010200000L, 0x0002040010200001L, 0x0002040010200080L, 0x0002040010200081L,
+            0x0002040010204000L, 0x0002040010204001L, 0x0002040010204080L, 0x0002040010204081L,
+            0x0002040800000000L, 0x0002040800000001L, 0x0002040800000080L, 0x0002040800000081L,
+            0x0002040800004000L, 0x0002040800004001L, 0x0002040800004080L, 0x0002040800004081L,
+            0x0002040800200000L, 0x0002040800200001L, 0x0002040800200080L, 0x0002040800200081L,
+            0x0002040800204000L, 0x0002040800204001L, 0x0002040800204080L, 0x0002040800204081L,
+            0x0002040810000000L, 0x0002040810000001L, 0x0002040810000080L, 0x0002040810000081L,
+            0x0002040810004000L, 0x0002040810004001L, 0x0002040810004080L, 0x0002040810004081L,
+            0x0002040810200000L, 0x0002040810200001L, 0x0002040810200080L, 0x0002040810200081L,
+            0x0002040810204000L, 0x0002040810204001L, 0x0002040810204080L, 0x0002040810204081L,
+            0x0100000000000000L, 0x0100000000000001L, 0x0100000000000080L, 0x0100000000000081L,
+            0x0100000000004000L, 0x0100000000004001L, 0x0100000000004080L, 0x0100000000004081L,
+            0x0100000000200000L, 0x0100000000200001L, 0x0100000000200080L, 0x0100000000200081L,
+            0x0100000000204000L, 0x0100000000204001L, 0x0100000000204080L, 0x0100000000204081L,
+            0x0100000010000000L, 0x0100000010000001L, 0x0100000010000080L, 0x0100000010000081L,
+            0x0100000010004000L, 0x0100000010004001L, 0x0100000010004080L, 0x0100000010004081L,
+            0x0100000010200000L, 0x0100000010200001L, 0x0100000010200080L, 0x0100000010200081L,
+            0x0100000010204000L, 0x0100000010204001L, 0x0100000010204080L, 0x0100000010204081L,
+            0x0100000800000000L, 0x0100000800000001L, 0x0100000800000080L, 0x0100000800000081L,
+            0x0100000800004000L, 0x0100000800004001L, 0x0100000800004080L, 0x0100000800004081L,
+            0x0100000800200000L, 0x0100000800200001L, 0x0100000800200080L, 0x0100000800200081L,
+            0x0100000800204000L, 0x0100000800204001L, 0x0100000800204080L, 0x0100000800204081L,
+            0x0100000810000000L, 0x0100000810000001L, 0x0100000810000080L, 0x0100000810000081L,
+            0x0100000810004000L, 0x0100000810004001L, 0x0100000810004080L, 0x0100000810004081L,
+            0x0100000810200000L, 0x0100000810200001L, 0x0100000810200080L, 0x0100000810200081L,
+            0x0100000810204000L, 0x0100000810204001L, 0x0100000810204080L, 0x0100000810204081L,
+            0x0100040000000000L, 0x0100040000000001L, 0x0100040000000080L, 0x0100040000000081L,
+            0x0100040000004000L, 0x0100040000004001L, 0x0100040000004080L, 0x0100040000004081L,
+            0x0100040000200000L, 0x0100040000200001L, 0x0100040000200080L, 0x0100040000200081L,
+            0x0100040000204000L, 0x0100040000204001L, 0x0100040000204080L, 0x0100040000204081L,
+            0x0100040010000000L, 0x0100040010000001L, 0x0100040010000080L, 0x0100040010000081L,
+            0x0100040010004000L, 0x0100040010004001L, 0x0100040010004080L, 0x0100040010004081L,
+            0x0100040010200000L, 0x0100040010200001L, 0x0100040010200080L, 0x0100040010200081L,
+            0x0100040010204000L, 0x0100040010204001L, 0x0100040010204080L, 0x0100040010204081L,
+            0x0100040800000000L, 0x0100040800000001L, 0x0100040800000080L, 0x0100040800000081L,
+            0x0100040800004000L, 0x0100040800004001L, 0x0100040800004080L, 0x0100040800004081L,
+            0x0100040800200000L, 0x0100040800200001L, 0x0100040800200080L, 0x0100040800200081L,
+            0x0100040800204000L, 0x0100040800204001L, 0x0100040800204080L, 0x0100040800204081L,
+            0x0100040810000000L, 0x0100040810000001L, 0x0100040810000080L, 0x0100040810000081L,
+            0x0100040810004000L, 0x0100040810004001L, 0x0100040810004080L, 0x0100040810004081L,
+            0x0100040810200000L, 0x0100040810200001L, 0x0100040810200080L, 0x0100040810200081L,
+            0x0100040810204000L, 0x0100040810204001L, 0x0100040810204080L, 0x0100040810204081L,
+            0x0102000000000000L, 0x0102000000000001L, 0x0102000000000080L, 0x0102000000000081L,
+            0x0102000000004000L, 0x0102000000004001L, 0x0102000000004080L, 0x0102000000004081L,
+            0x0102000000200000L, 0x0102000000200001L, 0x0102000000200080L, 0x0102000000200081L,
+            0x0102000000204000L, 0x0102000000204001L, 0x0102000000204080L, 0x0102000000204081L,
+            0x0102000010000000L, 0x0102000010000001L, 0x0102000010000080L, 0x0102000010000081L,
+            0x0102000010004000L, 0x0102000010004001L, 0x0102000010004080L, 0x0102000010004081L,
+            0x0102000010200000L, 0x0102000010200001L, 0x0102000010200080L, 0x0102000010200081L,
+            0x0102000010204000L, 0x0102000010204001L, 0x0102000010204080L, 0x0102000010204081L,
+            0x0102000800000000L, 0x0102000800000001L, 0x0102000800000080L, 0x0102000800000081L,
+            0x0102000800004000L, 0x0102000800004001L, 0x0102000800004080L, 0x0102000800004081L,
+            0x0102000800200000L, 0x0102000800200001L, 0x0102000800200080L, 0x0102000800200081L,
+            0x0102000800204000L, 0x0102000800204001L, 0x0102000800204080L, 0x0102000800204081L,
+            0x0102000810000000L, 0x0102000810000001L, 0x0102000810000080L, 0x0102000810000081L,
+            0x0102000810004000L, 0x0102000810004001L, 0x0102000810004080L, 0x0102000810004081L,
+            0x0102000810200000L, 0x0102000810200001L, 0x0102000810200080L, 0x0102000810200081L,
+            0x0102000810204000L, 0x0102000810204001L, 0x0102000810204080L, 0x0102000810204081L,
+            0x0102040000000000L, 0x0102040000000001L, 0x0102040000000080L, 0x0102040000000081L,
+            0x0102040000004000L, 0x0102040000004001L, 0x0102040000004080L, 0x0102040000004081L,
+            0x0102040000200000L, 0x0102040000200001L, 0x0102040000200080L, 0x0102040000200081L,
+            0x0102040000204000L, 0x0102040000204001L, 0x0102040000204080L, 0x0102040000204081L,
+            0x0102040010000000L, 0x0102040010000001L, 0x0102040010000080L, 0x0102040010000081L,
+            0x0102040010004000L, 0x0102040010004001L, 0x0102040010004080L, 0x0102040010004081L,
+            0x0102040010200000L, 0x0102040010200001L, 0x0102040010200080L, 0x0102040010200081L,
+            0x0102040010204000L, 0x0102040010204001L, 0x0102040010204080L, 0x0102040010204081L,
+            0x0102040800000000L, 0x0102040800000001L, 0x0102040800000080L, 0x0102040800000081L,
+            0x0102040800004000L, 0x0102040800004001L, 0x0102040800004080L, 0x0102040800004081L,
+            0x0102040800200000L, 0x0102040800200001L, 0x0102040800200080L, 0x0102040800200081L,
+            0x0102040800204000L, 0x0102040800204001L, 0x0102040800204080L, 0x0102040800204081L,
+            0x0102040810000000L, 0x0102040810000001L, 0x0102040810000080L, 0x0102040810000081L,
+            0x0102040810004000L, 0x0102040810004001L, 0x0102040810004080L, 0x0102040810004081L,
+            0x0102040810200000L, 0x0102040810200001L, 0x0102040810200080L, 0x0102040810200081L,
+            0x0102040810204000L, 0x0102040810204001L, 0x0102040810204080L, 0x0102040810204081L
+        };
+
+        // For toString(); must have length 64
+        private const string ZEROES = "0000000000000000000000000000000000000000000000000000000000000000";
+
+        internal static readonly byte[] BitLengths =
+        {
+            0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
+            5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+            6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+            8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8
+        };
+
+        // TODO make m fixed for the LongArray, and hence compute T once and for all
+
+        private long[] m_ints;
+
+        public LongArray(int intLen)
+        {
+            m_ints = new long[intLen];
+        }
+
+        public LongArray(long[] ints)
+        {
+            m_ints = ints;
+        }
+
+        public LongArray(long[] ints, int off, int len)
+        {
+            if (off == 0 && len == ints.Length)
+            {
+                m_ints = ints;
+            }
+            else
+            {
+                m_ints = new long[len];
+                Array.Copy(ints, off, m_ints, 0, len);
+            }
+        }
+
+        public LongArray(BigInteger bigInt)
+        {
+            if (bigInt == null || bigInt.SignValue < 0)
+            {
+                throw new ArgumentException("invalid F2m field value", "bigInt");
+            }
+
+            if (bigInt.SignValue == 0)
+            {
+                m_ints = new long[] { 0L };
+                return;
+            }
+
+            byte[] barr = bigInt.ToByteArray();
+            int barrLen = barr.Length;
+            int barrStart = 0;
+            if (barr[0] == 0)
+            {
+                // First byte is 0 to enforce highest (=sign) bit is zero.
+                // In this case ignore barr[0].
+                barrLen--;
+                barrStart = 1;
+            }
+            int intLen = (barrLen + 7) / 8;
+            m_ints = new long[intLen];
+
+            int iarrJ = intLen - 1;
+            int rem = barrLen % 8 + barrStart;
+            long temp = 0;
+            int barrI = barrStart;
+            if (barrStart < rem)
+            {
+                for (; barrI < rem; barrI++)
+                {
+                    temp <<= 8;
+                    uint barrBarrI = barr[barrI];
+                    temp |= barrBarrI;
+                }
+                m_ints[iarrJ--] = temp;
+            }
+
+            for (; iarrJ >= 0; iarrJ--)
+            {
+                temp = 0;
+                for (int i = 0; i < 8; i++)
+                {
+                    temp <<= 8;
+                    uint barrBarrI = barr[barrI++];
+                    temp |= barrBarrI;
+                }
+                m_ints[iarrJ] = temp;
+            }
+        }
+
+        public bool IsOne()
+        {
+            long[] a = m_ints;
+            if (a[0] != 1L)
+            {
+                return false;
+            }
+            for (int i = 1; i < a.Length; ++i)
+            {
+                if (a[i] != 0L)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public bool IsZero()
+        {
+            long[] a = m_ints;
+            for (int i = 0; i < a.Length; ++i)
+            {
+                if (a[i] != 0L)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public int GetUsedLength()
+        {
+            return GetUsedLengthFrom(m_ints.Length);
+        }
+
+        public int GetUsedLengthFrom(int from)
+        {
+            long[] a = m_ints;
+            from = System.Math.Min(from, a.Length);
+
+            if (from < 1)
+            {
+                return 0;
+            }
+
+            // Check if first element will act as sentinel
+            if (a[0] != 0)
+            {
+                while (a[--from] == 0)
+                {
+                }
+                return from + 1;
+            }
+
+            do
+            {
+                if (a[--from] != 0)
+                {
+                    return from + 1;
+                }
+            }
+            while (from > 0);
+
+            return 0;
+        }
+
+        public int Degree()
+        {
+            int i = m_ints.Length;
+            long w;
+            do
+            {
+                if (i == 0)
+                {
+                    return 0;
+                }
+                w = m_ints[--i];
+            }
+            while (w == 0);
+
+            return (i << 6) + BitLength(w);
+        }
+
+        private int DegreeFrom(int limit)
+        {
+            int i = (int)(((uint)limit + 62) >> 6);
+            long w;
+            do
+            {
+                if (i == 0)
+                {
+                    return 0;
+                }
+                w = m_ints[--i];
+            }
+            while (w == 0);
+
+            return (i << 6) + BitLength(w);
+        }
+
+    //    private int lowestCoefficient()
+    //    {
+    //        for (int i = 0; i < m_ints.Length; ++i)
+    //        {
+    //            long mi = m_ints[i];
+    //            if (mi != 0)
+    //            {
+    //                int j = 0;
+    //                while ((mi & 0xFFL) == 0)
+    //                {
+    //                    j += 8;
+    //                    mi >>>= 8;
+    //                }
+    //                while ((mi & 1L) == 0)
+    //                {
+    //                    ++j;
+    //                    mi >>>= 1;
+    //                }
+    //                return (i << 6) + j;
+    //            }
+    //        }
+    //        return -1;
+    //    }
+
+        private static int BitLength(long w)
+        {
+            int u = (int)((ulong)w >> 32), b;
+            if (u == 0)
+            {
+                u = (int)w;
+                b = 0;
+            }
+            else
+            {
+                b = 32;
+            }
+
+            int t = (int)((uint)u >> 16), k;
+            if (t == 0)
+            {
+                t = (int)((uint)u >> 8);
+                k = (t == 0) ? BitLengths[u] : 8 + BitLengths[t];
+            }
+            else
+            {
+                int v = (int)((uint)t >> 8);
+                k = (v == 0) ? 16 + BitLengths[t] : 24 + BitLengths[v];
+            }
+
+            return b + k;
+        }
+
+        private long[] ResizedInts(int newLen)
+        {
+            long[] newInts = new long[newLen];
+            Array.Copy(m_ints, 0, newInts, 0, System.Math.Min(m_ints.Length, newLen));
+            return newInts;
+        }
+
+        public BigInteger ToBigInteger()
+        {
+            int usedLen = GetUsedLength();
+            if (usedLen == 0)
+            {
+                return BigInteger.Zero;
+            }
+
+            long highestInt = m_ints[usedLen - 1];
+            byte[] temp = new byte[8];
+            int barrI = 0;
+            bool trailingZeroBytesDone = false;
+            for (int j = 7; j >= 0; j--)
+            {
+                byte thisByte = (byte)((ulong)highestInt >> (8 * j));
+                if (trailingZeroBytesDone || (thisByte != 0))
+                {
+                    trailingZeroBytesDone = true;
+                    temp[barrI++] = thisByte;
+                }
+            }
+
+            int barrLen = 8 * (usedLen - 1) + barrI;
+            byte[] barr = new byte[barrLen];
+            for (int j = 0; j < barrI; j++)
+            {
+                barr[j] = temp[j];
+            }
+            // Highest value int is done now
+
+            for (int iarrJ = usedLen - 2; iarrJ >= 0; iarrJ--)
+            {
+                long mi = m_ints[iarrJ];
+                for (int j = 7; j >= 0; j--)
+                {
+                    barr[barrI++] = (byte)((ulong)mi >> (8 * j));
+                }
+            }
+            return new BigInteger(1, barr);
+        }
+
+    //    private static long shiftUp(long[] x, int xOff, int count)
+    //    {
+    //        long prev = 0;
+    //        for (int i = 0; i < count; ++i)
+    //        {
+    //            long next = x[xOff + i];
+    //            x[xOff + i] = (next << 1) | prev;
+    //            prev = next >>> 63;
+    //        }
+    //        return prev;
+    //    }
+
+        private static long ShiftUp(long[] x, int xOff, int count, int shift)
+        {
+            int shiftInv = 64 - shift;
+            long prev = 0;
+            for (int i = 0; i < count; ++i)
+            {
+                long next = x[xOff + i];
+                x[xOff + i] = (next << shift) | prev;
+                prev = (long)((ulong)next >> shiftInv);
+            }
+            return prev;
+        }
+
+        private static long ShiftUp(long[] x, int xOff, long[] z, int zOff, int count, int shift)
+        {
+            int shiftInv = 64 - shift;
+            long prev = 0;
+            for (int i = 0; i < count; ++i)
+            {
+                long next = x[xOff + i];
+                z[zOff + i] = (next << shift) | prev;
+                prev = (long)((ulong)next >> shiftInv);
+            }
+            return prev;
+        }
+
+        public LongArray AddOne()
+        {
+            if (m_ints.Length == 0)
+            {
+                return new LongArray(new long[]{ 1L });
+            }
+
+            int resultLen = System.Math.Max(1, GetUsedLength());
+            long[] ints = ResizedInts(resultLen);
+            ints[0] ^= 1L;
+            return new LongArray(ints);
+        }
+
+    //    private void addShiftedByBits(LongArray other, int bits)
+    //    {
+    //        int words = bits >>> 6;
+    //        int shift = bits & 0x3F;
+    //
+    //        if (shift == 0)
+    //        {
+    //            addShiftedByWords(other, words);
+    //            return;
+    //        }
+    //
+    //        int otherUsedLen = other.GetUsedLength();
+    //        if (otherUsedLen == 0)
+    //        {
+    //            return;
+    //        }
+    //
+    //        int minLen = otherUsedLen + words + 1;
+    //        if (minLen > m_ints.Length)
+    //        {
+    //            m_ints = resizedInts(minLen);
+    //        }
+    //
+    //        long carry = addShiftedByBits(m_ints, words, other.m_ints, 0, otherUsedLen, shift);
+    //        m_ints[otherUsedLen + words] ^= carry;
+    //    }
+
+        private void AddShiftedByBitsSafe(LongArray other, int otherDegree, int bits)
+        {
+            int otherLen = (int)((uint)(otherDegree + 63) >> 6);
+
+            int words = (int)((uint)bits >> 6);
+            int shift = bits & 0x3F;
+
+            if (shift == 0)
+            {
+                Add(m_ints, words, other.m_ints, 0, otherLen);
+                return;
+            }
+
+            long carry = AddShiftedUp(m_ints, words, other.m_ints, 0, otherLen, shift);
+            if (carry != 0L)
+            {
+                m_ints[otherLen + words] ^= carry;
+            }
+        }
+
+        private static long AddShiftedUp(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+        {
+            int shiftInv = 64 - shift;
+            long prev = 0;
+            for (int i = 0; i < count; ++i)
+            {
+                long next = y[yOff + i];
+                x[xOff + i] ^= (next << shift) | prev;
+                prev = (long)((ulong)next >> shiftInv);
+            }
+            return prev;
+        }
+
+        private static long AddShiftedDown(long[] x, int xOff, long[] y, int yOff, int count, int shift)
+        {
+            int shiftInv = 64 - shift;
+            long prev = 0;
+            int i = count;
+            while (--i >= 0)
+            {
+                long next = y[yOff + i];
+                x[xOff + i] ^= (long)((ulong)next >> shift) | prev;
+                prev = next << shiftInv;
+            }
+            return prev;
+        }
+
+        public void AddShiftedByWords(LongArray other, int words)
+        {
+            int otherUsedLen = other.GetUsedLength();
+            if (otherUsedLen == 0)
+            {
+                return;
+            }
+
+            int minLen = otherUsedLen + words;
+            if (minLen > m_ints.Length)
+            {
+                m_ints = ResizedInts(minLen);
+            }
+
+            Add(m_ints, words, other.m_ints, 0, otherUsedLen);
+        }
+
+        private static void Add(long[] x, int xOff, long[] y, int yOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                x[xOff + i] ^= y[yOff + i];
+            }
+        }
+
+        private static void Add(long[] x, int xOff, long[] y, int yOff, long[] z, int zOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                z[zOff + i] = x[xOff + i] ^ y[yOff + i];
+            }
+        }
+
+        private static void AddBoth(long[] x, int xOff, long[] y1, int y1Off, long[] y2, int y2Off, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                x[xOff + i] ^= y1[y1Off + i] ^ y2[y2Off + i];
+            }
+        }
+
+        private static void Distribute(long[] x, int src, int dst1, int dst2, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                long v = x[src + i];
+                x[dst1 + i] ^= v;
+                x[dst2 + i] ^= v;
+            }
+        }
+
+        public int Length
+        {
+            get { return m_ints.Length; }
+        }
+
+        private static void FlipWord(long[] buf, int off, int bit, long word)
+        {
+            int n = off + (int)((uint)bit >> 6);
+            int shift = bit & 0x3F;
+            if (shift == 0)
+            {
+                buf[n] ^= word;
+            }
+            else
+            {
+                buf[n] ^= word << shift;
+                word = (long)((ulong)word >> (64 - shift));
+                if (word != 0)
+                {
+                    buf[++n] ^= word;
+                }
+            }
+        }
+
+    //    private static long getWord(long[] buf, int off, int len, int bit)
+    //    {
+    //        int n = off + (bit >>> 6);
+    //        int shift = bit & 0x3F;
+    //        if (shift == 0)
+    //        {
+    //            return buf[n];
+    //        }
+    //        long result = buf[n] >>> shift;
+    //        if (++n < len)
+    //        {
+    //            result |= buf[n] << (64 - shift);
+    //        }
+    //        return result;
+    //    }
+
+        public bool TestBitZero()
+        {
+            return m_ints.Length > 0 && (m_ints[0] & 1L) != 0;
+        }
+
+        private static bool TestBit(long[] buf, int off, int n)
+        {
+            // theInt = n / 64
+            int theInt = (int)((uint)n >> 6);
+            // theBit = n % 64
+            int theBit = n & 0x3F;
+            long tester = 1L << theBit;
+            return (buf[off + theInt] & tester) != 0;
+        }
+
+        private static void FlipBit(long[] buf, int off, int n)
+        {
+            // theInt = n / 64
+            int theInt = (int)((uint)n >> 6);
+            // theBit = n % 64
+            int theBit = n & 0x3F;
+            long flipper = 1L << theBit;
+            buf[off + theInt] ^= flipper;
+        }
+
+    //    private static void SetBit(long[] buf, int off, int n)
+    //    {
+    //        // theInt = n / 64
+    //        int theInt = n >>> 6;
+    //        // theBit = n % 64
+    //        int theBit = n & 0x3F;
+    //        long setter = 1L << theBit;
+    //        buf[off + theInt] |= setter;
+    //    }
+    //
+    //    private static void ClearBit(long[] buf, int off, int n)
+    //    {
+    //        // theInt = n / 64
+    //        int theInt = n >>> 6;
+    //        // theBit = n % 64
+    //        int theBit = n & 0x3F;
+    //        long setter = 1L << theBit;
+    //        buf[off + theInt] &= ~setter;
+    //    }
+
+        private static void MultiplyWord(long a, long[] b, int bLen, long[] c, int cOff)
+        {
+            if ((a & 1L) != 0L)
+            {
+                Add(c, cOff, b, 0, bLen);
+            }
+            int k = 1;
+            while ((a = (long)((ulong)a >> 1)) != 0L)
+            {
+                if ((a & 1L) != 0L)
+                {
+                    long carry = AddShiftedUp(c, cOff, b, 0, bLen, k);
+                    if (carry != 0L)
+                    {
+                        c[cOff + bLen] ^= carry;
+                    }
+                }
+                ++k;
+            }
+        }
+
+        public LongArray ModMultiplyLD(LongArray other, int m, int[] ks)
+        {
+            /*
+             * Find out the degree of each argument and handle the zero cases
+             */
+            int aDeg = Degree();
+            if (aDeg == 0)
+            {
+                return this;
+            }
+            int bDeg = other.Degree();
+            if (bDeg == 0)
+            {
+                return other;
+            }
+
+            /*
+             * Swap if necessary so that A is the smaller argument
+             */
+            LongArray A = this, B = other;
+            if (aDeg > bDeg)
+            {
+                A = other; B = this;
+                int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+            }
+
+            /*
+             * Establish the word lengths of the arguments and result
+             */
+            int aLen = (int)((uint)(aDeg + 63) >> 6);
+            int bLen = (int)((uint)(bDeg + 63) >> 6);
+            int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
+
+            if (aLen == 1)
+            {
+                long a0 = A.m_ints[0];
+                if (a0 == 1L)
+                {
+                    return B;
+                }
+
+                /*
+                 * Fast path for small A, with performance dependent only on the number of set bits
+                 */
+                long[] c0 = new long[cLen];
+                MultiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+                /*
+                 * Reduce the raw answer against the reduction coefficients
+                 */
+                return ReduceResult(c0, 0, cLen, m, ks);
+            }
+
+            /*
+             * Determine if B will get bigger during shifting
+             */
+            int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
+
+            /*
+             * Lookup table for the offset of each B in the tables
+             */
+            int[] ti = new int[16];
+
+            /*
+             * Precompute table of all 4-bit products of B
+             */
+            long[] T0 = new long[bMax << 4];
+            int tOff = bMax;
+            ti[1] = tOff;
+            Array.Copy(B.m_ints, 0, T0, tOff, bLen);
+            for (int i = 2; i < 16; ++i)
+            {
+                ti[i] = (tOff += bMax);
+                if ((i & 1) == 0)
+                {
+                    ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
+                }
+                else
+                {
+                    Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+                }
+            }
+
+            /*
+             * Second table with all 4-bit products of B shifted 4 bits
+             */
+            long[] T1 = new long[T0.Length];
+            ShiftUp(T0, 0, T1, 0, T0.Length, 4);
+    //        shiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+            long[] a = A.m_ints;
+            long[] c = new long[cLen];
+
+            int MASK = 0xF;
+
+            /*
+             * Lopez-Dahab algorithm
+             */
+
+            for (int k = 56; k >= 0; k -= 8)
+            {
+                for (int j = 1; j < aLen; j += 2)
+                {
+                    int aVal = (int)((ulong)a[j] >> k);
+                    int u = aVal & MASK;
+                    int v = (int)((uint)aVal >> 4) & MASK;
+                    AddBoth(c, j - 1, T0, ti[u], T1, ti[v], bMax);
+                }
+                ShiftUp(c, 0, cLen, 8);
+            }
+
+            for (int k = 56; k >= 0; k -= 8)
+            {
+                for (int j = 0; j < aLen; j += 2)
+                {
+                    int aVal = (int)((ulong)a[j] >> k);
+                    int u = aVal & MASK;
+                    int v = (int)((uint)aVal >> 4) & MASK;
+                    AddBoth(c, j, T0, ti[u], T1, ti[v], bMax);
+                }
+                if (k > 0)
+                {
+                    ShiftUp(c, 0, cLen, 8);
+                }
+            }
+
+            /*
+             * Finally the raw answer is collected, reduce it against the reduction coefficients
+             */
+            return ReduceResult(c, 0, cLen, m, ks);
+        }
+
+        public LongArray ModMultiply(LongArray other, int m, int[] ks)
+        {
+            /*
+             * Find out the degree of each argument and handle the zero cases
+             */
+            int aDeg = Degree();
+            if (aDeg == 0)
+            {
+                return this;
+            }
+            int bDeg = other.Degree();
+            if (bDeg == 0)
+            {
+                return other;
+            }
+
+            /*
+             * Swap if necessary so that A is the smaller argument
+             */
+            LongArray A = this, B = other;
+            if (aDeg > bDeg)
+            {
+                A = other; B = this;
+                int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+            }
+
+            /*
+             * Establish the word lengths of the arguments and result
+             */
+            int aLen = (int)((uint)(aDeg + 63) >> 6);
+            int bLen = (int)((uint)(bDeg + 63) >> 6);
+            int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
+
+            if (aLen == 1)
+            {
+                long a0 = A.m_ints[0];
+                if (a0 == 1L)
+                {
+                    return B;
+                }
+
+                /*
+                 * Fast path for small A, with performance dependent only on the number of set bits
+                 */
+                long[] c0 = new long[cLen];
+                MultiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+                /*
+                 * Reduce the raw answer against the reduction coefficients
+                 */
+                return ReduceResult(c0, 0, cLen, m, ks);
+            }
+
+            /*
+             * Determine if B will get bigger during shifting
+             */
+            int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
+
+            /*
+             * Lookup table for the offset of each B in the tables
+             */
+            int[] ti = new int[16];
+
+            /*
+             * Precompute table of all 4-bit products of B
+             */
+            long[] T0 = new long[bMax << 4];
+            int tOff = bMax;
+            ti[1] = tOff;
+            Array.Copy(B.m_ints, 0, T0, tOff, bLen);
+            for (int i = 2; i < 16; ++i)
+            {
+                ti[i] = (tOff += bMax);
+                if ((i & 1) == 0)
+                {
+                    ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
+                }
+                else
+                {
+                    Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+                }
+            }
+
+            /*
+             * Second table with all 4-bit products of B shifted 4 bits
+             */
+            long[] T1 = new long[T0.Length];
+            ShiftUp(T0, 0, T1, 0, T0.Length, 4);
+    //        ShiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+            long[] a = A.m_ints;
+            long[] c = new long[cLen << 3];
+
+            int MASK = 0xF;
+
+            /*
+             * Lopez-Dahab (Modified) algorithm
+             */
+
+            for (int aPos = 0; aPos < aLen; ++aPos)
+            {
+                long aVal = a[aPos];
+                int cOff = aPos;
+                for (;;)
+                {
+                    int u = (int)aVal & MASK;
+                    aVal = (long)((ulong)aVal >> 4);
+                    int v = (int)aVal & MASK;
+                    AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+                    aVal = (long)((ulong)aVal >> 4);
+                    if (aVal == 0L)
+                    {
+                        break;
+                    }
+                    cOff += cLen;
+                }
+            }
+
+            {
+                int cOff = c.Length;
+                while ((cOff -= cLen) != 0)
+                {
+                    AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+                }
+            }
+
+            /*
+             * Finally the raw answer is collected, reduce it against the reduction coefficients
+             */
+            return ReduceResult(c, 0, cLen, m, ks);
+        }
+
+        public LongArray ModMultiplyAlt(LongArray other, int m, int[] ks)
+        {
+            /*
+             * Find out the degree of each argument and handle the zero cases
+             */
+            int aDeg = Degree();
+            if (aDeg == 0)
+            {
+                return this;
+            }
+            int bDeg = other.Degree();
+            if (bDeg == 0)
+            {
+                return other;
+            }
+
+            /*
+             * Swap if necessary so that A is the smaller argument
+             */
+            LongArray A = this, B = other;
+            if (aDeg > bDeg)
+            {
+                A = other; B = this;
+                int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+            }
+
+            /*
+             * Establish the word lengths of the arguments and result
+             */
+            int aLen = (int)((uint)(aDeg + 63) >> 6);
+            int bLen = (int)((uint)(bDeg + 63) >> 6);
+            int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
+
+            if (aLen == 1)
+            {
+                long a0 = A.m_ints[0];
+                if (a0 == 1L)
+                {
+                    return B;
+                }
+
+                /*
+                 * Fast path for small A, with performance dependent only on the number of set bits
+                 */
+                long[] c0 = new long[cLen];
+                MultiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+                /*
+                 * Reduce the raw answer against the reduction coefficients
+                 */
+                return ReduceResult(c0, 0, cLen, m, ks);
+            }
+
+            // NOTE: This works, but is slower than width 4 processing
+    //        if (aLen == 2)
+    //        {
+    //            /*
+    //             * Use common-multiplicand optimization to save ~1/4 of the adds
+    //             */
+    //            long a1 = A.m_ints[0], a2 = A.m_ints[1];
+    //            long aa = a1 & a2; a1 ^= aa; a2 ^= aa;
+    //
+    //            long[] b = B.m_ints;
+    //            long[] c = new long[cLen];
+    //            multiplyWord(aa, b, bLen, c, 1);
+    //            add(c, 0, c, 1, cLen - 1);
+    //            multiplyWord(a1, b, bLen, c, 0);
+    //            multiplyWord(a2, b, bLen, c, 1);
+    //
+    //            /*
+    //             * Reduce the raw answer against the reduction coefficients
+    //             */
+    //            return ReduceResult(c, 0, cLen, m, ks);
+    //        }
+
+            /*
+             * Determine the parameters of the Interleaved window algorithm: the 'width' in bits to
+             * process together, the number of evaluation 'positions' implied by that width, and the
+             * 'top' position at which the regular window algorithm stops.
+             */
+            int width, positions, top, banks;
+
+            // NOTE: width 4 is the fastest over the entire range of sizes used in current crypto 
+    //        width = 1; positions = 64; top = 64; banks = 4;
+    //        width = 2; positions = 32; top = 64; banks = 4;
+    //        width = 3; positions = 21; top = 63; banks = 3;
+            width = 4; positions = 16; top = 64; banks = 8;
+    //        width = 5; positions = 13; top = 65; banks = 7;
+    //        width = 7; positions = 9; top = 63; banks = 9;
+    //        width = 8; positions = 8; top = 64; banks = 8;
+
+            /*
+             * Determine if B will get bigger during shifting
+             */
+            int shifts = top < 64 ? positions : positions - 1;
+            int bMax = (int)((uint)(bDeg + shifts + 63) >> 6);
+
+            int bTotal = bMax * banks, stride = width * banks;
+
+            /*
+             * Create a single temporary buffer, with an offset table to find the positions of things in it 
+             */
+            int[] ci = new int[1 << width];
+            int cTotal = aLen;
+            {
+                ci[0] = cTotal;
+                cTotal += bTotal;
+                ci[1] = cTotal;
+                for (int i = 2; i < ci.Length; ++i)
+                {
+                    cTotal += cLen;
+                    ci[i] = cTotal;
+                }
+                cTotal += cLen;
+            }
+            // NOTE: Provide a safe dump for "high zeroes" since we are adding 'bMax' and not 'bLen'
+            ++cTotal;
+
+            long[] c = new long[cTotal];
+
+            // Prepare A in Interleaved form, according to the chosen width
+            Interleave(A.m_ints, 0, c, 0, aLen, width);
+
+            // Make a working copy of B, since we will be shifting it
+            {
+                int bOff = aLen;
+                Array.Copy(B.m_ints, 0, c, bOff, bLen);
+                for (int bank = 1; bank < banks; ++bank)
+                {
+                    ShiftUp(c, aLen, c, bOff += bMax, bMax, bank);
+                }
+            }
+
+            /*
+             * The main loop analyzes the Interleaved windows in A, and for each non-zero window
+             * a single word-array XOR is performed to a carefully selected slice of 'c'. The loop is
+             * breadth-first, checking the lowest window in each word, then looping again for the
+             * next higher window position.
+             */
+            int MASK = (1 << width) - 1;
+
+            int k = 0;
+            for (;;)
+            {
+                int aPos = 0;
+                do
+                {
+                    long aVal = (long)((ulong)c[aPos] >> k);
+                    int bank = 0, bOff = aLen;
+                    for (;;)
+                    {
+                        int index = (int)(aVal) & MASK;
+                        if (index != 0)
+                        {
+                            /*
+                             * Add to a 'c' buffer based on the bit-pattern of 'index'. Since A is in
+                             * Interleaved form, the bits represent the current B shifted by 0, 'positions',
+                             * 'positions' * 2, ..., 'positions' * ('width' - 1)
+                             */
+                            Add(c, aPos + ci[index], c, bOff, bMax);
+                        }
+                        if (++bank == banks)
+                        {
+                            break;
+                        }
+                        bOff += bMax;
+                        aVal = (long)((ulong)aVal >> width);
+                    }
+                }
+                while (++aPos < aLen);
+
+                if ((k += stride) >= top)
+                {
+                    if (k >= 64)
+                    {
+                        break;
+                    }
+
+                    /*
+                     * Adjustment for window setups with top == 63, the final bit (if any) is processed
+                     * as the top-bit of a window
+                     */
+                    k = 64 - width;
+                    MASK &= MASK << (top - k);
+                }
+
+                /*
+                 * After each position has been checked for all words of A, B is shifted up 1 place
+                 */
+                ShiftUp(c, aLen, bTotal, banks);
+            }
+
+            int ciPos = ci.Length;
+            while (--ciPos > 1)
+            {
+                if ((ciPos & 1L) == 0L)
+                {
+                    /*
+                     * For even numbers, shift contents and add to the half-position
+                     */
+                    AddShiftedUp(c, ci[(uint)ciPos >> 1], c, ci[ciPos], cLen, positions);
+                }
+                else
+                {
+                    /*
+                     * For odd numbers, 'distribute' contents to the result and the next-lowest position
+                     */
+                    Distribute(c, ci[ciPos], ci[ciPos - 1], ci[1], cLen);
+                }
+            }
+
+            /*
+             * Finally the raw answer is collected, reduce it against the reduction coefficients
+             */
+            return ReduceResult(c, ci[1], cLen, m, ks);
+        }
+
+        public LongArray ModReduce(int m, int[] ks)
+        {
+            long[] buf = Arrays.Clone(m_ints);
+            int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks);
+            return new LongArray(buf, 0, rLen);
+        }
+
+        public LongArray Multiply(LongArray other, int m, int[] ks)
+        {
+            /*
+             * Find out the degree of each argument and handle the zero cases
+             */
+            int aDeg = Degree();
+            if (aDeg == 0)
+            {
+                return this;
+            }
+            int bDeg = other.Degree();
+            if (bDeg == 0)
+            {
+                return other;
+            }
+
+            /*
+             * Swap if necessary so that A is the smaller argument
+             */
+            LongArray A = this, B = other;
+            if (aDeg > bDeg)
+            {
+                A = other; B = this;
+                int tmp = aDeg; aDeg = bDeg; bDeg = tmp;
+            }
+
+            /*
+             * Establish the word lengths of the arguments and result
+             */
+            int aLen = (int)((uint)(aDeg + 63) >> 6);
+            int bLen = (int)((uint)(bDeg + 63) >> 6);
+            int cLen = (int)((uint)(aDeg + bDeg + 62) >> 6);
+
+            if (aLen == 1)
+            {
+                long a0 = A.m_ints[0];
+                if (a0 == 1L)
+                {
+                    return B;
+                }
+
+                /*
+                 * Fast path for small A, with performance dependent only on the number of set bits
+                 */
+                long[] c0 = new long[cLen];
+                MultiplyWord(a0, B.m_ints, bLen, c0, 0);
+
+                /*
+                 * Reduce the raw answer against the reduction coefficients
+                 */
+                //return ReduceResult(c0, 0, cLen, m, ks);
+                return new LongArray(c0, 0, cLen);
+            }
+
+            /*
+             * Determine if B will get bigger during shifting
+             */
+            int bMax = (int)((uint)(bDeg + 7 + 63) >> 6);
+
+            /*
+             * Lookup table for the offset of each B in the tables
+             */
+            int[] ti = new int[16];
+
+            /*
+             * Precompute table of all 4-bit products of B
+             */
+            long[] T0 = new long[bMax << 4];
+            int tOff = bMax;
+            ti[1] = tOff;
+            Array.Copy(B.m_ints, 0, T0, tOff, bLen);
+            for (int i = 2; i < 16; ++i)
+            {
+                ti[i] = (tOff += bMax);
+                if ((i & 1) == 0)
+                {
+                    ShiftUp(T0, (int)((uint)tOff >> 1), T0, tOff, bMax, 1);
+                }
+                else
+                {
+                    Add(T0, bMax, T0, tOff - bMax, T0, tOff, bMax);
+                }
+            }
+
+            /*
+             * Second table with all 4-bit products of B shifted 4 bits
+             */
+            long[] T1 = new long[T0.Length];
+            ShiftUp(T0, 0, T1, 0, T0.Length, 4);
+            //        ShiftUp(T0, bMax, T1, bMax, tOff, 4);
+
+            long[] a = A.m_ints;
+            long[] c = new long[cLen << 3];
+
+            int MASK = 0xF;
+
+            /*
+             * Lopez-Dahab (Modified) algorithm
+             */
+
+            for (int aPos = 0; aPos < aLen; ++aPos)
+            {
+                long aVal = a[aPos];
+                int cOff = aPos;
+                for (; ; )
+                {
+                    int u = (int)aVal & MASK;
+                    aVal = (long)((ulong)aVal >> 4);
+                    int v = (int)aVal & MASK;
+                    AddBoth(c, cOff, T0, ti[u], T1, ti[v], bMax);
+                    aVal = (long)((ulong)aVal >> 4);
+                    if (aVal == 0L)
+                    {
+                        break;
+                    }
+                    cOff += cLen;
+                }
+            }
+
+            {
+                int cOff = c.Length;
+                while ((cOff -= cLen) != 0)
+                {
+                    AddShiftedUp(c, cOff - cLen, c, cOff, cLen, 8);
+                }
+            }
+
+            /*
+             * Finally the raw answer is collected, reduce it against the reduction coefficients
+             */
+            //return ReduceResult(c, 0, cLen, m, ks);
+            return new LongArray(c, 0, cLen);
+        }
+
+        public void Reduce(int m, int[] ks)
+        {
+            long[] buf = m_ints;
+            int rLen = ReduceInPlace(buf, 0, buf.Length, m, ks);
+            if (rLen < buf.Length)
+            {
+                m_ints = new long[rLen];
+                Array.Copy(buf, 0, m_ints, 0, rLen);
+            }
+        }
+
+        private static LongArray ReduceResult(long[] buf, int off, int len, int m, int[] ks)
+        {
+            int rLen = ReduceInPlace(buf, off, len, m, ks);
+            return new LongArray(buf, off, rLen);
+        }
+
+    //    private static void deInterleave(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+    //    {
+    //        for (int i = 0; i < count; ++i)
+    //        {
+    //            z[zOff + i] = deInterleave(x[zOff + i], rounds);
+    //        }
+    //    }
+    //
+    //    private static long deInterleave(long x, int rounds)
+    //    {
+    //        while (--rounds >= 0)
+    //        {
+    //            x = deInterleave32(x & DEInterleave_MASK) | (deInterleave32((x >>> 1) & DEInterleave_MASK) << 32);
+    //        }
+    //        return x;
+    //    }
+    //
+    //    private static long deInterleave32(long x)
+    //    {
+    //        x = (x | (x >>> 1)) & 0x3333333333333333L;
+    //        x = (x | (x >>> 2)) & 0x0F0F0F0F0F0F0F0FL;
+    //        x = (x | (x >>> 4)) & 0x00FF00FF00FF00FFL;
+    //        x = (x | (x >>> 8)) & 0x0000FFFF0000FFFFL;
+    //        x = (x | (x >>> 16)) & 0x00000000FFFFFFFFL;
+    //        return x;
+    //    }
+
+        private static int ReduceInPlace(long[] buf, int off, int len, int m, int[] ks)
+        {
+            int mLen = (m + 63) >> 6;
+            if (len < mLen)
+            {
+                return len;
+            }
+
+            int numBits = System.Math.Min(len << 6, (m << 1) - 1); // TODO use actual degree?
+            int excessBits = (len << 6) - numBits;
+            while (excessBits >= 64)
+            {
+                --len;
+                excessBits -= 64;
+            }
+
+            int kLen = ks.Length, kMax = ks[kLen - 1], kNext = kLen > 1 ? ks[kLen - 2] : 0;
+            int wordWiseLimit = System.Math.Max(m, kMax + 64);
+            int vectorableWords = (excessBits + System.Math.Min(numBits - wordWiseLimit, m - kNext)) >> 6;
+            if (vectorableWords > 1)
+            {
+                int vectorWiseWords = len - vectorableWords;
+                ReduceVectorWise(buf, off, len, vectorWiseWords, m, ks);
+                while (len > vectorWiseWords)
+                {
+                    buf[off + --len] = 0L;
+                }
+                numBits = vectorWiseWords << 6;
+            }
+
+            if (numBits > wordWiseLimit)
+            {
+                ReduceWordWise(buf, off, len, wordWiseLimit, m, ks);
+                numBits = wordWiseLimit;
+            }
+
+            if (numBits > m)
+            {
+                ReduceBitWise(buf, off, numBits, m, ks);
+            }
+
+            return mLen;
+        }
+
+        private static void ReduceBitWise(long[] buf, int off, int BitLength, int m, int[] ks)
+        {
+            while (--BitLength >= m)
+            {
+                if (TestBit(buf, off, BitLength))
+                {
+                    ReduceBit(buf, off, BitLength, m, ks);
+                }
+            }
+        }
+
+        private static void ReduceBit(long[] buf, int off, int bit, int m, int[] ks)
+        {
+            FlipBit(buf, off, bit);
+            int n = bit - m;
+            int j = ks.Length;
+            while (--j >= 0)
+            {
+                FlipBit(buf, off, ks[j] + n);
+            }
+            FlipBit(buf, off, n);
+        }
+
+        private static void ReduceWordWise(long[] buf, int off, int len, int toBit, int m, int[] ks)
+        {
+            int toPos = (int)((uint)toBit >> 6);
+
+            while (--len > toPos)
+            {
+                long word = buf[off + len];
+                if (word != 0)
+                {
+                    buf[off + len] = 0;
+                    ReduceWord(buf, off, (len << 6), word, m, ks);
+                }
+            }
+
+            {
+                int partial = toBit & 0x3F;
+                long word = (long)((ulong)buf[off + toPos] >> partial);
+                if (word != 0)
+                {
+                    buf[off + toPos] ^= word << partial;
+                    ReduceWord(buf, off, toBit, word, m, ks);
+                }
+            }
+        }
+
+        private static void ReduceWord(long[] buf, int off, int bit, long word, int m, int[] ks)
+        {
+            int offset = bit - m;
+            int j = ks.Length;
+            while (--j >= 0)
+            {
+                FlipWord(buf, off, offset + ks[j], word);
+            }
+            FlipWord(buf, off, offset, word);
+        }
+
+        private static void ReduceVectorWise(long[] buf, int off, int len, int words, int m, int[] ks)
+        {
+            /*
+             * NOTE: It's important we go from highest coefficient to lowest, because for the highest
+             * one (only) we allow the ranges to partially overlap, and therefore any changes must take
+             * effect for the subsequent lower coefficients.
+             */
+            int baseBit = (words << 6) - m;
+            int j = ks.Length;
+            while (--j >= 0)
+            {
+                FlipVector(buf, off, buf, off + words, len - words, baseBit + ks[j]);
+            }
+            FlipVector(buf, off, buf, off + words, len - words, baseBit);
+        }
+
+        private static void FlipVector(long[] x, int xOff, long[] y, int yOff, int yLen, int bits)
+        {
+            xOff += (int)((uint)bits >> 6);
+            bits &= 0x3F;
+
+            if (bits == 0)
+            {
+                Add(x, xOff, y, yOff, yLen);
+            }
+            else
+            {
+                long carry = AddShiftedDown(x, xOff + 1, y, yOff, yLen, 64 - bits);
+                x[xOff] ^= carry;
+            }
+        }
+
+        public LongArray ModSquare(int m, int[] ks)
+        {
+            int len = GetUsedLength();
+            if (len == 0)
+            {
+                return this;
+            }
+
+            int _2len = len << 1;
+            long[] r = new long[_2len];
+
+            int pos = 0;
+            while (pos < _2len)
+            {
+                long mi = m_ints[(uint)pos >> 1];
+                r[pos++] = Interleave2_32to64((int)mi);
+                r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32));
+            }
+
+            return new LongArray(r, 0, ReduceInPlace(r, 0, r.Length, m, ks));
+        }
+
+        public LongArray ModSquareN(int n, int m, int[] ks)
+        {
+            int len = GetUsedLength();
+            if (len == 0)
+            {
+                return this;
+            }
+    
+            int mLen = (m + 63) >> 6;
+            long[] r = new long[mLen << 1];
+            Array.Copy(m_ints, 0, r, 0, len);
+    
+            while (--n >= 0)
+            {
+                SquareInPlace(r, len, m, ks);
+                len = ReduceInPlace(r, 0, r.Length, m, ks);
+            }
+    
+            return new LongArray(r, 0, len);
+        }
+
+        public LongArray Square(int m, int[] ks)
+        {
+            int len = GetUsedLength();
+            if (len == 0)
+            {
+                return this;
+            }
+
+            int _2len = len << 1;
+            long[] r = new long[_2len];
+
+            int pos = 0;
+            while (pos < _2len)
+            {
+                long mi = m_ints[(uint)pos >> 1];
+                r[pos++] = Interleave2_32to64((int)mi);
+                r[pos++] = Interleave2_32to64((int)((ulong)mi >> 32));
+            }
+
+            return new LongArray(r, 0, r.Length);
+        }
+
+        private static void SquareInPlace(long[] x, int xLen, int m, int[] ks)
+        {
+            int pos = xLen << 1;
+            while (--xLen >= 0)
+            {
+                long xVal = x[xLen];
+                x[--pos] = Interleave2_32to64((int)((ulong)xVal >> 32));
+                x[--pos] = Interleave2_32to64((int)xVal);
+            }
+        }
+
+        private static void Interleave(long[] x, int xOff, long[] z, int zOff, int count, int width)
+        {
+            switch (width)
+            {
+            case 3:
+                Interleave3(x, xOff, z, zOff, count);
+                break;
+            case 5:
+                Interleave5(x, xOff, z, zOff, count);
+                break;
+            case 7:
+                Interleave7(x, xOff, z, zOff, count);
+                break;
+            default:
+                Interleave2_n(x, xOff, z, zOff, count, BitLengths[width] - 1);
+                break;
+            }
+        }
+
+        private static void Interleave3(long[] x, int xOff, long[] z, int zOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                z[zOff + i] = Interleave3(x[xOff + i]);
+            }
+        }
+
+        private static long Interleave3(long x)
+        {
+            long z = x & (1L << 63);
+            return z
+                | Interleave3_21to63((int)x & 0x1FFFFF)
+                | Interleave3_21to63((int)((ulong)x >> 21) & 0x1FFFFF) << 1
+                | Interleave3_21to63((int)((ulong)x >> 42) & 0x1FFFFF) << 2;
+
+    //        int zPos = 0, wPos = 0, xPos = 0;
+    //        for (;;)
+    //        {
+    //            z |= ((x >>> xPos) & 1L) << zPos;
+    //            if (++zPos == 63)
+    //            {
+    //                String sz2 = Long.toBinaryString(z);
+    //                return z;
+    //            }
+    //            if ((xPos += 21) >= 63)
+    //            {
+    //                xPos = ++wPos;
+    //            }
+    //        }
+        }
+
+        private static long Interleave3_21to63(int x)
+        {
+            int r00 = INTERLEAVE3_TABLE[x & 0x7F];
+            int r21 = INTERLEAVE3_TABLE[((uint)x >> 7) & 0x7F];
+            int r42 = INTERLEAVE3_TABLE[(uint)x >> 14];
+            return (r42 & 0xFFFFFFFFL) << 42 | (r21 & 0xFFFFFFFFL) << 21 | (r00 & 0xFFFFFFFFL);
+        }
+
+        private static void Interleave5(long[] x, int xOff, long[] z, int zOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                z[zOff + i] = Interleave5(x[xOff + i]);
+            }
+        }
+
+        private static long Interleave5(long x)
+        {
+            return Interleave3_13to65((int)x & 0x1FFF)
+                | Interleave3_13to65((int)((ulong)x >> 13) & 0x1FFF) << 1
+                | Interleave3_13to65((int)((ulong)x >> 26) & 0x1FFF) << 2
+                | Interleave3_13to65((int)((ulong)x >> 39) & 0x1FFF) << 3
+                | Interleave3_13to65((int)((ulong)x >> 52) & 0x1FFF) << 4;
+
+    //        long z = 0;
+    //        int zPos = 0, wPos = 0, xPos = 0;
+    //        for (;;)
+    //        {
+    //            z |= ((x >>> xPos) & 1L) << zPos;
+    //            if (++zPos == 64)
+    //            {
+    //                return z;
+    //            }
+    //            if ((xPos += 13) >= 64)
+    //            {
+    //                xPos = ++wPos;
+    //            }
+    //        }
+        }
+
+        private static long Interleave3_13to65(int x)
+        {
+            int r00 = INTERLEAVE5_TABLE[x & 0x7F];
+            int r35 = INTERLEAVE5_TABLE[(uint)x >> 7];
+            return (r35 & 0xFFFFFFFFL) << 35 | (r00 & 0xFFFFFFFFL);
+        }
+
+        private static void Interleave7(long[] x, int xOff, long[] z, int zOff, int count)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                z[zOff + i] = Interleave7(x[xOff + i]);
+            }
+        }
+
+        private static long Interleave7(long x)
+        {
+            long z = x & (1L << 63);
+            return z
+                | INTERLEAVE7_TABLE[(int)x & 0x1FF]
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 9) & 0x1FF] << 1
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 18) & 0x1FF] << 2
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 27) & 0x1FF] << 3
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 36) & 0x1FF] << 4
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 45) & 0x1FF] << 5
+                | INTERLEAVE7_TABLE[(int)((ulong)x >> 54) & 0x1FF] << 6;
+
+    //        int zPos = 0, wPos = 0, xPos = 0;
+    //        for (;;)
+    //        {
+    //            z |= ((x >>> xPos) & 1L) << zPos;
+    //            if (++zPos == 63)
+    //            {
+    //                return z;
+    //            }
+    //            if ((xPos += 9) >= 63)
+    //            {
+    //                xPos = ++wPos;
+    //            }
+    //        }
+        }
+
+        private static void Interleave2_n(long[] x, int xOff, long[] z, int zOff, int count, int rounds)
+        {
+            for (int i = 0; i < count; ++i)
+            {
+                z[zOff + i] = Interleave2_n(x[xOff + i], rounds);
+            }
+        }
+
+        private static long Interleave2_n(long x, int rounds)
+        {
+            while (rounds > 1)
+            {
+                rounds -= 2;
+                x = Interleave4_16to64((int)x & 0xFFFF)
+                    | Interleave4_16to64((int)((ulong)x >> 16) & 0xFFFF) << 1
+                    | Interleave4_16to64((int)((ulong)x >> 32) & 0xFFFF) << 2
+                    | Interleave4_16to64((int)((ulong)x >> 48) & 0xFFFF) << 3;
+            }
+            if (rounds > 0)
+            {
+                x = Interleave2_32to64((int)x) | Interleave2_32to64((int)((ulong)x >> 32)) << 1;
+            }
+            return x;
+        }
+
+        private static long Interleave4_16to64(int x)
+        {
+            int r00 = INTERLEAVE4_TABLE[x & 0xFF];
+            int r32 = INTERLEAVE4_TABLE[(uint)x >> 8];
+            return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+        }
+
+        private static long Interleave2_32to64(int x)
+        {
+            int r00 = INTERLEAVE2_TABLE[x & 0xFF] | INTERLEAVE2_TABLE[((uint)x >> 8) & 0xFF] << 16;
+            int r32 = INTERLEAVE2_TABLE[((uint)x >> 16) & 0xFF] | INTERLEAVE2_TABLE[(uint)x >> 24] << 16;
+            return (r32 & 0xFFFFFFFFL) << 32 | (r00 & 0xFFFFFFFFL);
+        }
+
+    //    private static LongArray ExpItohTsujii2(LongArray B, int n, int m, int[] ks)
+    //    {
+    //        LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+    //        int scale = 1;
+    //
+    //        int numTerms = n;
+    //        while (numTerms > 1)
+    //        {
+    //            if ((numTerms & 1) != 0)
+    //            {
+    //                t3 = t3.ModMultiply(t1, m, ks);
+    //                t1 = t1.modSquareN(scale, m, ks);
+    //            }
+    //
+    //            LongArray t2 = t1.modSquareN(scale, m, ks);
+    //            t1 = t1.ModMultiply(t2, m, ks);
+    //            numTerms >>>= 1; scale <<= 1;
+    //        }
+    //
+    //        return t3.ModMultiply(t1, m, ks);
+    //    }
+    //
+    //    private static LongArray ExpItohTsujii23(LongArray B, int n, int m, int[] ks)
+    //    {
+    //        LongArray t1 = B, t3 = new LongArray(new long[]{ 1L });
+    //        int scale = 1;
+    //
+    //        int numTerms = n;
+    //        while (numTerms > 1)
+    //        {
+    //            bool m03 = numTerms % 3 == 0;
+    //            bool m14 = !m03 && (numTerms & 1) != 0;
+    //
+    //            if (m14)
+    //            {
+    //                t3 = t3.ModMultiply(t1, m, ks);
+    //                t1 = t1.modSquareN(scale, m, ks);
+    //            }
+    //
+    //            LongArray t2 = t1.modSquareN(scale, m, ks);
+    //            t1 = t1.ModMultiply(t2, m, ks);
+    //
+    //            if (m03)
+    //            {
+    //                t2 = t2.modSquareN(scale, m, ks);
+    //                t1 = t1.ModMultiply(t2, m, ks);
+    //                numTerms /= 3; scale *= 3;
+    //            }
+    //            else
+    //            {
+    //                numTerms >>>= 1; scale <<= 1;
+    //            }
+    //        }
+    //
+    //        return t3.ModMultiply(t1, m, ks);
+    //    }
+    //
+    //    private static LongArray ExpItohTsujii235(LongArray B, int n, int m, int[] ks)
+    //    {
+    //        LongArray t1 = B, t4 = new LongArray(new long[]{ 1L });
+    //        int scale = 1;
+    //
+    //        int numTerms = n;
+    //        while (numTerms > 1)
+    //        {
+    //            if (numTerms % 5 == 0)
+    //            {
+    ////                t1 = ExpItohTsujii23(t1, 5, m, ks);
+    //
+    //                LongArray t3 = t1;
+    //                t1 = t1.modSquareN(scale, m, ks);
+    //
+    //                LongArray t2 = t1.modSquareN(scale, m, ks);
+    //                t1 = t1.ModMultiply(t2, m, ks);
+    //                t2 = t1.modSquareN(scale << 1, m, ks);
+    //                t1 = t1.ModMultiply(t2, m, ks);
+    //
+    //                t1 = t1.ModMultiply(t3, m, ks);
+    //
+    //                numTerms /= 5; scale *= 5;
+    //                continue;
+    //            }
+    //
+    //            bool m03 = numTerms % 3 == 0;
+    //            bool m14 = !m03 && (numTerms & 1) != 0;
+    //
+    //            if (m14)
+    //            {
+    //                t4 = t4.ModMultiply(t1, m, ks);
+    //                t1 = t1.modSquareN(scale, m, ks);
+    //            }
+    //
+    //            LongArray t2 = t1.modSquareN(scale, m, ks);
+    //            t1 = t1.ModMultiply(t2, m, ks);
+    //
+    //            if (m03)
+    //            {
+    //                t2 = t2.modSquareN(scale, m, ks);
+    //                t1 = t1.ModMultiply(t2, m, ks);
+    //                numTerms /= 3; scale *= 3;
+    //            }
+    //            else
+    //            {
+    //                numTerms >>>= 1; scale <<= 1;
+    //            }
+    //        }
+    //
+    //        return t4.ModMultiply(t1, m, ks);
+    //    }
+
+        public LongArray ModInverse(int m, int[] ks)
+        {
+            /*
+             * Fermat's Little Theorem
+             */
+    //        LongArray A = this;
+    //        LongArray B = A.modSquare(m, ks);
+    //        LongArray R0 = B, R1 = B;
+    //        for (int i = 2; i < m; ++i)
+    //        {
+    //            R1 = R1.modSquare(m, ks);
+    //            R0 = R0.ModMultiply(R1, m, ks);
+    //        }
+    //
+    //        return R0;
+
+            /*
+             * Itoh-Tsujii
+             */
+    //        LongArray B = modSquare(m, ks);
+    //        switch (m)
+    //        {
+    //        case 409:
+    //            return ExpItohTsujii23(B, m - 1, m, ks);
+    //        case 571:
+    //            return ExpItohTsujii235(B, m - 1, m, ks);
+    //        case 163:
+    //        case 233:
+    //        case 283:
+    //        default:
+    //            return ExpItohTsujii2(B, m - 1, m, ks);
+    //        }
+
+            /*
+             * Inversion in F2m using the extended Euclidean algorithm
+             * 
+             * Input: A nonzero polynomial a(z) of degree at most m-1
+             * Output: a(z)^(-1) mod f(z)
+             */
+            int uzDegree = Degree();
+            if (uzDegree == 0)
+            {
+                throw new InvalidOperationException();
+            }
+            if (uzDegree == 1)
+            {
+                return this;
+            }
+
+            // u(z) := a(z)
+            LongArray uz = (LongArray)Copy();
+
+            int t = (m + 63) >> 6;
+
+            // v(z) := f(z)
+            LongArray vz = new LongArray(t);
+            ReduceBit(vz.m_ints, 0, m, m, ks);
+
+            // g1(z) := 1, g2(z) := 0
+            LongArray g1z = new LongArray(t);
+            g1z.m_ints[0] = 1L;
+            LongArray g2z = new LongArray(t);
+
+            int[] uvDeg = new int[]{ uzDegree, m + 1 };
+            LongArray[] uv = new LongArray[]{ uz, vz };
+
+            int[] ggDeg = new int[]{ 1, 0 };
+            LongArray[] gg = new LongArray[]{ g1z, g2z };
+
+            int b = 1;
+            int duv1 = uvDeg[b];
+            int dgg1 = ggDeg[b];
+            int j = duv1 - uvDeg[1 - b];
+
+            for (;;)
+            {
+                if (j < 0)
+                {
+                    j = -j;
+                    uvDeg[b] = duv1;
+                    ggDeg[b] = dgg1;
+                    b = 1 - b;
+                    duv1 = uvDeg[b];
+                    dgg1 = ggDeg[b];
+                }
+
+                uv[b].AddShiftedByBitsSafe(uv[1 - b], uvDeg[1 - b], j);
+
+                int duv2 = uv[b].DegreeFrom(duv1);
+                if (duv2 == 0)
+                {
+                    return gg[1 - b];
+                }
+
+                {
+                    int dgg2 = ggDeg[1 - b];
+                    gg[b].AddShiftedByBitsSafe(gg[1 - b], dgg2, j);
+                    dgg2 += j;
+
+                    if (dgg2 > dgg1)
+                    {
+                        dgg1 = dgg2;
+                    }
+                    else if (dgg2 == dgg1)
+                    {
+                        dgg1 = gg[b].DegreeFrom(dgg1);
+                    }
+                }
+
+                j += (duv2 - duv1);
+                duv1 = duv2;
+            }
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as LongArray);
+        }
+
+        public virtual bool Equals(LongArray other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            int usedLen = GetUsedLength();
+            if (other.GetUsedLength() != usedLen)
+            {
+                return false;
+            }
+            for (int i = 0; i < usedLen; i++)
+            {
+                if (m_ints[i] != other.m_ints[i])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public override int GetHashCode()
+        {
+            int usedLen = GetUsedLength();
+            int hash = 1;
+            for (int i = 0; i < usedLen; i++)
+            {
+                long mi = m_ints[i];
+                hash *= 31;
+                hash ^= (int)mi;
+                hash *= 31;
+                hash ^= (int)((ulong)mi >> 32);
+            }
+            return hash;
+        }
+
+        public LongArray Copy()
+        {
+            return new LongArray(Arrays.Clone(m_ints));
+        }
+
+        public override string ToString()
+        {
+            int i = GetUsedLength();
+            if (i == 0)
+            {
+                return "0";
+            }
+
+            StringBuilder sb = new StringBuilder(Convert.ToString(m_ints[--i], 2));
+            while (--i >= 0)
+            {
+                string s = Convert.ToString(m_ints[i], 2);
+
+                // Add leading zeroes, except for highest significant word
+                int len = s.Length;
+                if (len < 64)
+                {
+                    sb.Append(ZEROES.Substring(len));
+                }
+
+                sb.Append(s);
+            }
+            return sb.ToString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/Mod.cs b/BouncyCastle.AxCrypt/src/math/ec/Mod.cs
new file mode 100644
index 0000000..80534ca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/Mod.cs
@@ -0,0 +1,184 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    internal abstract class Mod
+    {
+        public static void Invert(uint[] p, uint[] x, uint[] z)
+        {
+            int len = p.Length;
+            if (Nat.IsZero(len, x))
+                throw new ArgumentException("cannot be 0", "x");
+            if (Nat.IsOne(len, x))
+            {
+                Array.Copy(x, 0, z, 0, len);
+                return;
+            }
+
+            uint[] u = Nat.Copy(len, x);
+            uint[] a = Nat.Create(len);
+            a[0] = 1;
+            int ac = 0;
+
+            if ((u[0] & 1) == 0)
+            {
+                InversionStep(p, u, len, a, ref ac);
+            }
+            if (Nat.IsOne(len, u))
+            {
+                InversionResult(p, ac, a, z);
+                return;
+            }
+
+            uint[] v = Nat.Copy(len, p);
+            uint[] b = Nat.Create(len);
+            int bc = 0;
+
+            int uvLen = len;
+
+            for (;;)
+            {
+                while (u[uvLen - 1] == 0 && v[uvLen - 1] == 0)
+                {
+                    --uvLen;
+                }
+
+                if (Nat.Gte(len, u, v))
+                {
+                    Nat.SubFrom(len, v, u);
+                    Debug.Assert((u[0] & 1) == 0);
+                    ac += Nat.SubFrom(len, b, a) - bc;
+                    InversionStep(p, u, uvLen, a, ref ac);
+                    if (Nat.IsOne(len, u))
+                    {
+                        InversionResult(p, ac, a, z);
+                        return;
+                    }
+                }
+                else
+                {
+                    Nat.SubFrom(len, u, v);
+                    Debug.Assert((v[0] & 1) == 0);
+                    bc += Nat.SubFrom(len, a, b) - ac;
+                    InversionStep(p, v, uvLen, b, ref bc);
+                    if (Nat.IsOne(len, v))
+                    {
+                        InversionResult(p, bc, b, z);
+                        return;
+                    }
+                }
+            }
+        }
+
+        public static uint[] Random(uint[] p)
+        {
+            int len = p.Length;
+            Random rand = new Random();
+            uint[] s = Nat.Create(len);
+
+            uint m = p[len - 1];
+            m |= m >> 1;
+            m |= m >> 2;
+            m |= m >> 4;
+            m |= m >> 8;
+            m |= m >> 16;
+
+            do
+            {
+                byte[] bytes = new byte[len << 2];
+                rand.NextBytes(bytes);
+                Pack.BE_To_UInt32(bytes, 0, s);
+                s[len - 1] &= m;
+            }
+            while (Nat.Gte(len, s, p));
+
+            return s;
+        }
+
+        public static void Add(uint[] p, uint[] x, uint[] y, uint[] z)
+        {
+            int len = p.Length;
+            uint c = Nat.Add(len, x, y, z);
+            if (c != 0)
+            {
+                Nat.SubFrom(len, p, z);
+            }
+        }
+
+        public static void Subtract(uint[] p, uint[] x, uint[] y, uint[] z)
+        {
+            int len = p.Length;
+            int c = Nat.Sub(len, x, y, z);
+            if (c != 0)
+            {
+                Nat.AddTo(len, p, z);
+            }
+        }
+
+        private static void InversionResult(uint[] p, int ac, uint[] a, uint[] z)
+        {
+            if (ac < 0)
+            {
+                Nat.Add(p.Length, a, p, z);
+            }
+            else
+            {
+                Array.Copy(a, 0, z, 0, p.Length);
+            }
+        }
+
+        private static void InversionStep(uint[] p, uint[] u, int uLen, uint[] x, ref int xc)
+        {
+            int len = p.Length;
+            int count = 0;
+            while (u[0] == 0)
+            {
+                Nat.ShiftDownWord(uLen, u, 0);
+                count += 32;
+            }
+
+            {
+                int zeroes = GetTrailingZeroes(u[0]);
+                if (zeroes > 0)
+                {
+                    Nat.ShiftDownBits(uLen, u, zeroes, 0);
+                    count += zeroes;
+                }
+            }
+
+            for (int i = 0; i < count; ++i)
+            {
+                if ((x[0] & 1) != 0)
+                {
+                    if (xc < 0)
+                    {
+                        xc += (int)Nat.AddTo(len, p, x);
+                    }
+                    else
+                    {
+                        xc += Nat.SubFrom(len, p, x);
+                    }
+                }
+
+                Debug.Assert(xc == 0 || xc == -1);
+                Nat.ShiftDownBit(len, x, (uint)xc);
+            }
+        }
+
+        private static int GetTrailingZeroes(uint x)
+        {
+            Debug.Assert(x != 0);
+            int count = 0;
+            while ((x & 1) == 0)
+            {
+                x >>= 1;
+                ++count;
+            }
+            return count;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/Nat.cs b/BouncyCastle.AxCrypt/src/math/ec/Nat.cs
new file mode 100644
index 0000000..17b632f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/Nat.cs
@@ -0,0 +1,1013 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    internal abstract class Nat
+    {
+        private const ulong M = 0xFFFFFFFFUL;
+
+        public static uint Add(int len, uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[i] + y[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint Add33At(int len, uint x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            ulong c = (ulong)z[zPos + 0] + x;
+            z[zPos + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zPos + 1] + 1;
+            z[zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zPos + 2);
+        }
+
+        public static uint Add33At(int len, uint x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            ulong c = (ulong)z[zOff + zPos] + x;
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zOff + zPos + 1] + 1;
+            z[zOff + zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2);
+        }
+
+        public static uint Add33To(int len, uint x, uint[] z)
+        {
+            ulong c = (ulong)z[0] + x;
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[1] + 1;
+            z[1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, 2);
+        }
+
+        public static uint Add33To(int len, uint x, uint[] z, int zOff)
+        {
+            ulong c = (ulong)z[zOff + 0] + x;
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zOff + 1] + 1;
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, 2);
+        }
+
+        public static uint AddBothTo(int len, uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[i] + y[i] + z[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[xOff + i] + y[yOff + i] + z[zOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint AddDWordAt(int len, ulong x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            ulong c = (ulong)z[zPos + 0] + (x & M);
+            z[zPos + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zPos + 1] + (x >> 32);
+            z[zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zPos + 2);
+        }
+
+        public static uint AddDWordAt(int len, ulong x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            ulong c = (ulong)z[zOff + zPos] + (x & M);
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zOff + zPos + 1] + (x >> 32);
+            z[zOff + zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 2);
+        }
+
+        public static uint AddDWordTo(int len, ulong x, uint[] z)
+        {
+            ulong c = (ulong)z[0] + (x & M);
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[1] + (x >> 32);
+            z[1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, 2);
+        }
+
+        public static uint AddDWordTo(int len, ulong x, uint[] z, int zOff)
+        {
+            ulong c = (ulong)z[zOff + 0] + (x & M);
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zOff + 1] + (x >> 32);
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, 2);
+        }
+
+        public static uint AddTo(int len, uint[] x, uint[] z)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[i] + z[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint AddTo(int len, uint[] x, int xOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (ulong)x[xOff + i] + z[zOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (uint)c;
+        }
+
+        public static uint AddWordAt(int len, uint x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 1));
+            ulong c = (ulong)x + z[zPos];
+            z[zPos] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zPos + 1);
+        }
+
+        public static uint AddWordAt(int len, uint x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 1));
+            ulong c = (ulong)x + z[zOff + zPos];
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, zPos + 1);
+        }
+
+        public static uint AddWordTo(int len, uint x, uint[] z)
+        {
+            ulong c = (ulong)x + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, 1);
+        }
+
+        public static uint AddWordTo(int len, uint x, uint[] z, int zOff)
+        {
+            ulong c = (ulong)x + z[zOff];
+            z[zOff] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zOff, 1);
+        }
+
+        public static void Copy(int len, uint[] x, uint[] z)
+        {
+            Array.Copy(x, 0, z, 0, len);
+        }
+
+        public static uint[] Copy(int len, uint[] x)
+        {
+            uint[] z = new uint[len];
+            Array.Copy(x, 0, z, 0, len);
+            return z;
+        }
+
+        public static uint[] Create(int len)
+        {
+            return new uint[len];
+        }
+
+        public static int Dec(int len, uint[] z)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                if (--z[i] != uint.MaxValue)
+                {
+                    return 0;
+                }
+            }
+            return -1;
+        }
+
+        public static int Dec(int len, uint[] x, uint[] z)
+        {
+            int i = 0;
+            while (i < len)
+            {
+                uint c = x[i] - 1;
+                z[i] = c;
+                ++i;
+                if (c != uint.MaxValue)
+                {
+                    while (i < len)
+                    {
+                        z[i] = x[i];
+                        ++i;
+                    }
+                    return 0;
+                }
+            }
+            return -1;
+        }
+
+        public static int DecAt(int len, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= len);
+            for (int i = zPos; i < len; ++i)
+            {
+                if (--z[i] != uint.MaxValue)
+                {
+                    return 0;
+                }
+            }
+            return -1;
+        }
+
+        public static int DecAt(int len, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= len);
+            for (int i = zPos; i < len; ++i)
+            {
+                if (--z[zOff + i] != uint.MaxValue)
+                {
+                    return 0;
+                }
+            }
+            return -1;
+        }
+
+        public static bool Eq(int len, uint[] x, uint[] y)
+        {
+            for (int i = len - 1; i >= 0; --i)
+            {
+                if (x[i] != y[i])
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static uint[] FromBigInteger(int bits, BigInteger x)
+        {
+            if (x.SignValue < 0 || x.BitLength > bits)
+                throw new ArgumentException();
+
+            int len = (bits + 31) >> 5;
+            uint[] z = Create(len);
+            int i = 0;
+            while (x.SignValue != 0)
+            {
+                z[i++] = (uint)x.IntValue;
+                x = x.ShiftRight(32);
+            }
+            return z;
+        }
+
+        public static uint GetBit(uint[] x, int bit)
+        {
+            if (bit == 0)
+            {
+                return x[0] & 1;
+            }
+            int w = bit >> 5;
+            if (w < 0 || w >= x.Length)
+            {
+                return 0;
+            }
+            int b = bit & 31;
+            return (x[w] >> b) & 1;
+        }
+
+        public static bool Gte(int len, uint[] x, uint[] y)
+        {
+            for (int i = len - 1; i >= 0; --i)
+            {
+                uint x_i = x[i], y_i = y[i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static uint Inc(int len, uint[] z)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                if (++z[i] != uint.MinValue)
+                {
+                    return 0;
+                }
+            }
+            return 1;
+        }
+
+        public static uint Inc(int len, uint[] x, uint[] z)
+        {
+            int i = 0;
+            while (i < len)
+            {
+                uint c = x[i] + 1;
+                z[i] = c;
+                ++i;
+                if (c != 0)
+                {
+                    while (i < len)
+                    {
+                        z[i] = x[i];
+                        ++i;
+                    }
+                    return 0;
+                }
+            }
+            return 1;
+        }
+
+        public static uint IncAt(int len, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= len);
+            for (int i = zPos; i < len; ++i)
+            {
+                if (++z[i] != uint.MinValue)
+                {
+                    return 0;
+                }
+            }
+            return 1;
+        }
+
+        public static uint IncAt(int len, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= len);
+            for (int i = zPos; i < len; ++i)
+            {
+                if (++z[zOff + i] != uint.MinValue)
+                {
+                    return 0;
+                }
+            }
+            return 1;
+        }
+
+        public static bool IsOne(int len, uint[] x)
+        {
+            if (x[0] != 1)
+            {
+                return false;
+            }
+            for (int i = 1; i < len; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsZero(int len, uint[] x)
+        {
+            if (x[0] != 0)
+            {
+                return false;
+            }
+            for (int i = 1; i < len; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static void Mul(int len, uint[] x, uint[] y, uint[] zz)
+        {
+            zz[len] = (uint)MulWord(len, x[0], y, zz);
+
+            for (int i = 1; i < len; ++i)
+            {
+                zz[i + len] = (uint)MulWordAddTo(len, x[i], y, 0, zz, i);
+            }
+        }
+
+        public static void Mul(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            zz[zzOff + len] = (uint)MulWord(len, x[xOff], y, yOff, zz, zzOff);
+
+            for (int i = 1; i < len; ++i)
+            {
+                zz[zzOff + i + len] = (uint)MulWordAddTo(len, x[xOff + i], y, yOff, zz, zzOff + i);
+            }
+        }
+
+        public static uint Mul31BothAdd(int len, uint a, uint[] x, uint b, uint[] y, uint[] z, int zOff)
+        {
+            ulong c = 0, aVal = (ulong)a, bVal = (ulong)b;
+            int i = 0;
+            do
+            {
+                c += aVal * x[i] + bVal * y[i] + z[zOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < len);
+            return (uint)c;
+        }
+
+        public static uint MulWord(int len, uint x, uint[] y, uint[] z)
+        {
+            ulong c = 0, xVal = (ulong)x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < len);
+            return (uint)c;
+        }
+
+        public static uint MulWord(int len, uint x, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = (ulong)x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[yOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < len);
+            return (uint)c;
+        }
+
+        public static uint MulWordAddTo(int len, uint x, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = (ulong)x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[yOff + i] + z[zOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < len);
+            return (uint)c;
+        }
+
+        public static uint MulWordDwordAddAt(int len, uint x, ulong y, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 3));
+            ulong c = 0, xVal = (ulong)x;
+            c += xVal * (uint)y + z[zPos + 0];
+            z[zPos + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * (y >> 32) + z[zPos + 1];
+            z[zPos + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)z[zPos + 2];
+            z[zPos + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : IncAt(len, z, zPos + 3);
+        }
+
+        public static uint ShiftDownBit(int len, uint[] z, uint c)
+        {
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = z[i];
+                z[i] = (next >> 1) | (c << 31);
+                c = next;
+            }
+            return c << 31;
+        }
+
+        public static uint ShiftDownBit(int len, uint[] z, int zOff, uint c)
+        {
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = z[zOff + i];
+                z[zOff + i] = (next >> 1) | (c << 31);
+                c = next;
+            }
+            return c << 31;
+        }
+
+        public static uint ShiftDownBit(int len, uint[] x, uint c, uint[] z)
+        {
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = x[i];
+                z[i] = (next >> 1) | (c << 31);
+                c = next;
+            }
+            return c << 31;
+        }
+
+        public static uint ShiftDownBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff)
+        {
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = x[xOff + i];
+                z[zOff + i] = (next >> 1) | (c << 31);
+                c = next;
+            }
+            return c << 31;
+        }
+
+        public static uint ShiftDownBits(int len, uint[] z, int bits, uint c)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = z[i];
+                z[i] = (next >> bits) | (c << -bits);
+                c = next;
+            }
+            return c << -bits;
+        }
+
+        public static uint ShiftDownBits(int len, uint[] z, int zOff, int bits, uint c)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = z[zOff + i];
+                z[zOff + i] = (next >> bits) | (c << -bits);
+                c = next;
+            }
+            return c << -bits;
+        }
+
+        public static uint ShiftDownBits(int len, uint[] x, int bits, uint c, uint[] z)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = x[i];
+                z[i] = (next >> bits) | (c << -bits);
+                c = next;
+            }
+            return c << -bits;
+        }
+
+        public static uint ShiftDownBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = x[xOff + i];
+                z[zOff + i] = (next >> bits) | (c << -bits);
+                c = next;
+            }
+            return c << -bits;
+        }
+
+        public static uint ShiftDownWord(int len, uint[] z, uint c)
+        {
+            int i = len;
+            while (--i >= 0)
+            {
+                uint next = z[i];
+                z[i] = c;
+                c = next;
+            }
+            return c;
+        }
+
+        public static uint ShiftUpBit(int len, uint[] z, uint c)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = z[i];
+                z[i] = (next << 1) | (c >> 31);
+                c = next;
+            }
+            return c >> 31;
+        }
+
+        public static uint ShiftUpBit(int len, uint[] z, int zOff, uint c)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = z[zOff + i];
+                z[zOff + i] = (next << 1) | (c >> 31);
+                c = next;
+            }
+            return c >> 31;
+        }
+
+        public static uint ShiftUpBit(int len, uint[] x, uint c, uint[] z)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = x[i];
+                z[i] = (next << 1) | (c >> 31);
+                c = next;
+            }
+            return c >> 31;
+        }
+
+        public static uint ShiftUpBit(int len, uint[] x, int xOff, uint c, uint[] z, int zOff)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = x[xOff + i];
+                z[zOff + i] = (next << 1) | (c >> 31);
+                c = next;
+            }
+            return c >> 31;
+        }
+
+        public static uint ShiftUpBits(int len, uint[] z, int bits, uint c)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = z[i];
+                z[i] = (next << bits) | (c >> -bits);
+                c = next;
+            }
+            return c >> -bits;
+        }
+
+        public static uint ShiftUpBits(int len, uint[] z, int zOff, int bits, uint c)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = z[zOff + i];
+                z[zOff + i] = (next << bits) | (c >> -bits);
+                c = next;
+            }
+            return c >> -bits;
+        }
+
+        public static uint ShiftUpBits(int len, uint[] x, int bits, uint c, uint[] z)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = x[i];
+                z[i] = (next << bits) | (c >> -bits);
+                c = next;
+            }
+            return c >> -bits;
+        }
+
+        public static uint ShiftUpBits(int len, uint[] x, int xOff, int bits, uint c, uint[] z, int zOff)
+        {
+            Debug.Assert(bits > 0 && bits < 32);
+            for (int i = 0; i < len; ++i)
+            {
+                uint next = x[xOff + i];
+                z[zOff + i] = (next << bits) | (c >> -bits);
+                c = next;
+            }
+            return c >> -bits;
+        }
+
+        public static void Square(int len, uint[] x, uint[] zz)
+        {
+            int extLen = len << 1;
+            uint c = 0;
+            int j = len, k = extLen;
+            do
+            {
+                ulong xVal = (ulong)x[--j];
+                ulong p = xVal * xVal;
+                zz[--k] = (c << 31) | (uint)(p >> 33);
+                zz[--k] = (uint)(p >> 1);
+                c = (uint)p;
+            }
+            while (j > 0);
+
+            for (int i = 1; i < len; ++i)
+            {
+                c = SquareWordAdd(x, i, zz);
+                AddWordAt(extLen, c, zz, i << 1);
+            }
+
+            ShiftUpBit(extLen, zz, x[0] << 31);
+        }
+
+        public static void Square(int len, uint[] x, int xOff, uint[] zz, int zzOff)
+        {
+            int extLen = len << 1;
+            uint c = 0;
+            int j = len, k = extLen;
+            do
+            {
+                ulong xVal = (ulong)x[xOff + --j];
+                ulong p = xVal * xVal;
+                zz[zzOff + --k] = (c << 31) | (uint)(p >> 33);
+                zz[zzOff + --k] = (uint)(p >> 1);
+                c = (uint)p;
+            }
+            while (j > 0);
+
+            for (int i = 1; i < len; ++i)
+            {
+                c = SquareWordAdd(x, xOff, i, zz, zzOff);
+                AddWordAt(extLen, c, zz, zzOff, i << 1);
+            }
+
+            ShiftUpBit(extLen, zz, zzOff, x[xOff] << 31);
+        }
+
+        public static uint SquareWordAdd(uint[] x, int xPos, uint[] z)
+        {
+            ulong c = 0, xVal = (ulong)x[xPos];
+            int i = 0;
+            do
+            {
+                c += xVal * x[i] + z[xPos + i];
+                z[xPos + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < xPos);
+            return (uint)c;
+        }
+
+        public static uint SquareWordAdd(uint[] x, int xOff, int xPos, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = (ulong)x[xOff + xPos];
+            int i = 0;
+            do
+            {
+                c += xVal * (x[xOff + i] & M) + (z[xPos + zOff] & M);
+                z[xPos + zOff] = (uint)c;
+                c >>= 32;
+                ++zOff;
+            }
+            while (++i < xPos);
+            return (uint)c;
+        }
+
+        public static int Sub(int len, uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)x[i] - y[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int Sub(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)x[xOff + i] - y[yOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+        public static int Sub33At(int len, uint x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            long c = (long)z[zPos + 0] - x;
+            z[zPos + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zPos + 1] - 1;
+            z[zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zPos + 2);
+        }
+
+        public static int Sub33At(int len, uint x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            long c = (long)z[zOff + zPos] - x;
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + zPos + 1] - 1;
+            z[zOff + zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 2);
+        }
+
+        public static int Sub33From(int len, uint x, uint[] z)
+        {
+            long c = (long)z[0] - x;
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - 1;
+            z[1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, 2);
+        }
+
+        public static int Sub33From(int len, uint x, uint[] z, int zOff)
+        {
+            long c = (long)z[zOff + 0] - x;
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 1] - 1;
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zOff, 2);
+        }
+
+        public static int SubBothFrom(int len, uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)z[i] - x[i] - y[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int SubBothFrom(int len, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)z[zOff + i] - x[xOff + i] - y[yOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int SubDWordAt(int len, ulong x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            long c = (long)z[zPos + 0] - (long)(x & M);
+            z[zPos + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zPos + 1] - (long)(x >> 32);
+            z[zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zPos + 2);
+        }
+
+        public static int SubDWordAt(int len, ulong x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 2));
+            long c = (long)z[zOff + zPos] - (long)(x & M);
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + zPos + 1] - (long)(x >> 32);
+            z[zOff + zPos + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z,  zOff, zPos + 2);
+        }
+
+        public static int SubDWordFrom(int len, ulong x, uint[] z)
+        {
+            long c = (long)z[0] - (long)(x & M);
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - (long)(x >> 32);
+            z[1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, 2);
+        }
+
+        public static int SubDWordFrom(int len, ulong x, uint[] z, int zOff)
+        {
+            long c = (long)z[zOff + 0] - (long)(x & M);
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 1] - (long)(x >> 32);
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zOff, 2);
+        }
+
+        public static int SubFrom(int len, uint[] x, uint[] z)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)z[i] - x[i];
+                z[i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int SubFrom(int len, uint[] x, int xOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            for (int i = 0; i < len; ++i)
+            {
+                c += (long)z[zOff + i] - x[xOff + i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            return (int)c;
+        }
+
+        public static int SubWordAt(int len, uint x, uint[] z, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 1));
+            long c = (long)z[zPos] - x;
+            z[zPos] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zPos + 1);
+        }
+
+        public static int SubWordAt(int len, uint x, uint[] z, int zOff, int zPos)
+        {
+            Debug.Assert(zPos <= (len - 1));
+            long c = (long)z[zOff + zPos] - x;
+            z[zOff + zPos] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zOff, zPos + 1);
+        }
+
+        public static int SubWordFrom(int len, uint x, uint[] z)
+        {
+            long c = (long)z[0] - x;
+            z[0] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, 1);
+        }
+
+        public static int SubWordFrom(int len, uint x, uint[] z, int zOff)
+        {
+            long c = (long)z[zOff + 0] - x;
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : DecAt(len, z, zOff, 1);
+        }
+
+        public static BigInteger ToBigInteger(int len, uint[] x)
+        {
+            byte[] bs = new byte[len << 2];
+            for (int i = 0; i < len; ++i)
+            {
+                uint x_i = x[i];
+                if (x_i != 0)
+                {
+                    Pack.UInt32_To_BE(x_i, bs, (len - 1 - i) << 2);
+                }
+            }
+            return new BigInteger(1, bs);
+        }
+
+        public static void Zero(int len, uint[] z)
+        {
+            for (int i = 0; i < len; ++i)
+            {
+                z[i] = 0;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ScaleXPointMap.cs b/BouncyCastle.AxCrypt/src/math/ec/ScaleXPointMap.cs
new file mode 100644
index 0000000..f8a363b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ScaleXPointMap.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public class ScaleXPointMap
+        : ECPointMap
+    {
+        protected readonly ECFieldElement scale;
+
+        public ScaleXPointMap(ECFieldElement scale)
+        {
+            this.scale = scale;
+        }
+
+        public virtual ECPoint Map(ECPoint p)
+        {
+            return p.ScaleX(scale);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/ScaleYPointMap.cs b/BouncyCastle.AxCrypt/src/math/ec/ScaleYPointMap.cs
new file mode 100644
index 0000000..1c4795b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/ScaleYPointMap.cs
@@ -0,0 +1,20 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC
+{
+    public class ScaleYPointMap
+        : ECPointMap
+    {
+        protected readonly ECFieldElement scale;
+
+        public ScaleYPointMap(ECFieldElement scale)
+        {
+            this.scale = scale;
+        }
+
+        public virtual ECPoint Map(ECPoint p)
+        {
+            return p.ScaleY(scale);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/abc/SimpleBigDecimal.cs b/BouncyCastle.AxCrypt/src/math/ec/abc/SimpleBigDecimal.cs
new file mode 100644
index 0000000..d5664db
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/abc/SimpleBigDecimal.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Math.EC.Abc
+{
+	/**
+	* Class representing a simple version of a big decimal. A
+	* <code>SimpleBigDecimal</code> is basically a
+	* {@link java.math.BigInteger BigInteger} with a few digits on the right of
+	* the decimal point. The number of (binary) digits on the right of the decimal
+	* point is called the <code>scale</code> of the <code>SimpleBigDecimal</code>.
+	* Unlike in {@link java.math.BigDecimal BigDecimal}, the scale is not adjusted
+	* automatically, but must be set manually. All <code>SimpleBigDecimal</code>s
+	* taking part in the same arithmetic operation must have equal scale. The
+	* result of a multiplication of two <code>SimpleBigDecimal</code>s returns a
+	* <code>SimpleBigDecimal</code> with double scale.
+	*/
+	internal class SimpleBigDecimal
+		//	: Number
+	{
+		//	private static final long serialVersionUID = 1L;
+
+		private readonly BigInteger	bigInt;
+		private readonly int		scale;
+
+		/**
+		* Returns a <code>SimpleBigDecimal</code> representing the same numerical
+		* value as <code>value</code>.
+		* @param value The value of the <code>SimpleBigDecimal</code> to be
+		* created. 
+		* @param scale The scale of the <code>SimpleBigDecimal</code> to be
+		* created. 
+		* @return The such created <code>SimpleBigDecimal</code>.
+		*/
+		public static SimpleBigDecimal GetInstance(BigInteger val, int scale)
+		{
+			return new SimpleBigDecimal(val.ShiftLeft(scale), scale);
+		}
+
+		/**
+		* Constructor for <code>SimpleBigDecimal</code>. The value of the
+		* constructed <code>SimpleBigDecimal</code> Equals <code>bigInt / 
+		* 2<sup>scale</sup></code>.
+		* @param bigInt The <code>bigInt</code> value parameter.
+		* @param scale The scale of the constructed <code>SimpleBigDecimal</code>.
+		*/
+		public SimpleBigDecimal(BigInteger bigInt, int scale)
+		{
+			if (scale < 0)
+				throw new ArgumentException("scale may not be negative");
+
+			this.bigInt = bigInt;
+			this.scale = scale;
+		}
+
+		private SimpleBigDecimal(SimpleBigDecimal limBigDec)
+		{
+			bigInt = limBigDec.bigInt;
+			scale = limBigDec.scale;
+		}
+
+		private void CheckScale(SimpleBigDecimal b)
+		{
+			if (scale != b.scale)
+				throw new ArgumentException("Only SimpleBigDecimal of same scale allowed in arithmetic operations");
+		}
+
+		public SimpleBigDecimal AdjustScale(int newScale)
+		{
+			if (newScale < 0)
+				throw new ArgumentException("scale may not be negative");
+
+			if (newScale == scale)
+				return this;
+
+			return new SimpleBigDecimal(bigInt.ShiftLeft(newScale - scale), newScale);
+		}
+
+		public SimpleBigDecimal Add(SimpleBigDecimal b)
+		{
+			CheckScale(b);
+			return new SimpleBigDecimal(bigInt.Add(b.bigInt), scale);
+		}
+
+		public SimpleBigDecimal Add(BigInteger b)
+		{
+			return new SimpleBigDecimal(bigInt.Add(b.ShiftLeft(scale)), scale);
+		}
+
+		public SimpleBigDecimal Negate()
+		{
+			return new SimpleBigDecimal(bigInt.Negate(), scale);
+		}
+
+		public SimpleBigDecimal Subtract(SimpleBigDecimal b)
+		{
+			return Add(b.Negate());
+		}
+
+		public SimpleBigDecimal Subtract(BigInteger b)
+		{
+			return new SimpleBigDecimal(bigInt.Subtract(b.ShiftLeft(scale)), scale);
+		}
+
+		public SimpleBigDecimal Multiply(SimpleBigDecimal b)
+		{
+			CheckScale(b);
+			return new SimpleBigDecimal(bigInt.Multiply(b.bigInt), scale + scale);
+		}
+
+		public SimpleBigDecimal Multiply(BigInteger b)
+		{
+			return new SimpleBigDecimal(bigInt.Multiply(b), scale);
+		}
+
+		public SimpleBigDecimal Divide(SimpleBigDecimal b)
+		{
+			CheckScale(b);
+			BigInteger dividend = bigInt.ShiftLeft(scale);
+			return new SimpleBigDecimal(dividend.Divide(b.bigInt), scale);
+		}
+
+		public SimpleBigDecimal Divide(BigInteger b)
+		{
+			return new SimpleBigDecimal(bigInt.Divide(b), scale);
+		}
+
+		public SimpleBigDecimal ShiftLeft(int n)
+		{
+			return new SimpleBigDecimal(bigInt.ShiftLeft(n), scale);
+		}
+
+		public int CompareTo(SimpleBigDecimal val)
+		{
+			CheckScale(val);
+			return bigInt.CompareTo(val.bigInt);
+		}
+
+		public int CompareTo(BigInteger val)
+		{
+			return bigInt.CompareTo(val.ShiftLeft(scale));
+		}
+
+		public BigInteger Floor()
+		{
+			return bigInt.ShiftRight(scale);
+		}
+
+		public BigInteger Round()
+		{
+			SimpleBigDecimal oneHalf = new SimpleBigDecimal(BigInteger.One, 1);
+			return Add(oneHalf.AdjustScale(scale)).Floor();
+		}
+
+		public int IntValue
+		{
+			get { return Floor().IntValue; }
+		}
+
+		public long LongValue
+		{
+			get { return Floor().LongValue; }
+		}
+
+//		public double doubleValue()
+//		{
+//			return new Double(ToString()).doubleValue();
+//		}
+//
+//		public float floatValue()
+//		{
+//			return new Float(ToString()).floatValue();
+//		}
+
+		public int Scale
+		{
+			get { return scale; }
+		}
+
+		public override string ToString()
+		{
+			if (scale == 0)
+				return bigInt.ToString();
+
+			BigInteger floorBigInt = Floor();
+	        
+			BigInteger fract = bigInt.Subtract(floorBigInt.ShiftLeft(scale));
+			if (bigInt.SignValue < 0)
+			{
+				fract = BigInteger.One.ShiftLeft(scale).Subtract(fract);
+			}
+
+			if ((floorBigInt.SignValue == -1) && (!(fract.Equals(BigInteger.Zero))))
+			{
+				floorBigInt = floorBigInt.Add(BigInteger.One);
+			}
+			string leftOfPoint = floorBigInt.ToString();
+
+			char[] fractCharArr = new char[scale];
+				string fractStr = fract.ToString(2);
+			int fractLen = fractStr.Length;
+			int zeroes = scale - fractLen;
+			for (int i = 0; i < zeroes; i++)
+			{
+				fractCharArr[i] = '0';
+			}
+			for (int j = 0; j < fractLen; j++)
+			{
+				fractCharArr[zeroes + j] = fractStr[j];
+			}
+			string rightOfPoint = new string(fractCharArr);
+
+			StringBuilder sb = new StringBuilder(leftOfPoint);
+			sb.Append(".");
+			sb.Append(rightOfPoint);
+
+			return sb.ToString();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (this == obj)
+				return true;
+
+			SimpleBigDecimal other = obj as SimpleBigDecimal;
+
+			if (other == null)
+				return false;
+
+			return bigInt.Equals(other.bigInt)
+				&& scale == other.scale;
+		}
+
+		public override int GetHashCode()
+		{
+			return bigInt.GetHashCode() ^ scale;
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/abc/Tnaf.cs b/BouncyCastle.AxCrypt/src/math/ec/abc/Tnaf.cs
new file mode 100644
index 0000000..9f16886
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/abc/Tnaf.cs
@@ -0,0 +1,828 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Abc
+{
+    /**
+    * Class holding methods for point multiplication based on the window
+    * τ-adic nonadjacent form (WTNAF). The algorithms are based on the
+    * paper "Improved Algorithms for Arithmetic on Anomalous Binary Curves"
+    * by Jerome A. Solinas. The paper first appeared in the Proceedings of
+    * Crypto 1997.
+    */
+    internal class Tnaf
+    {
+        private static readonly BigInteger MinusOne = BigInteger.One.Negate();
+        private static readonly BigInteger MinusTwo = BigInteger.Two.Negate();
+        private static readonly BigInteger MinusThree = BigInteger.Three.Negate();
+        private static readonly BigInteger Four = BigInteger.ValueOf(4);
+
+        /**
+        * The window width of WTNAF. The standard value of 4 is slightly less
+        * than optimal for running time, but keeps space requirements for
+        * precomputation low. For typical curves, a value of 5 or 6 results in
+        * a better running time. When changing this value, the
+        * <code>α<sub>u</sub></code>'s must be computed differently, see
+        * e.g. "Guide to Elliptic Curve Cryptography", Darrel Hankerson,
+        * Alfred Menezes, Scott Vanstone, Springer-Verlag New York Inc., 2004,
+        * p. 121-122
+        */
+        public const sbyte Width = 4;
+
+        /**
+        * 2<sup>4</sup>
+        */
+        public const sbyte Pow2Width = 16;
+
+        /**
+        * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+        * of <code>ZTauElement</code>s.
+        */
+        public static readonly ZTauElement[] Alpha0 =
+        {
+            null,
+            new ZTauElement(BigInteger.One, BigInteger.Zero), null,
+            new ZTauElement(MinusThree, MinusOne), null,
+            new ZTauElement(MinusOne, MinusOne), null,
+            new ZTauElement(BigInteger.One, MinusOne), null
+        };
+
+        /**
+        * The <code>α<sub>u</sub></code>'s for <code>a=0</code> as an array
+        * of TNAFs.
+        */
+        public static readonly sbyte[][] Alpha0Tnaf =
+        {
+            null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, 1}
+        };
+
+        /**
+        * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+        * of <code>ZTauElement</code>s.
+        */
+        public static readonly ZTauElement[] Alpha1 =
+        {
+            null,
+            new ZTauElement(BigInteger.One, BigInteger.Zero), null,
+            new ZTauElement(MinusThree, BigInteger.One), null,
+            new ZTauElement(MinusOne, BigInteger.One), null,
+            new ZTauElement(BigInteger.One, BigInteger.One), null
+        };
+
+        /**
+        * The <code>α<sub>u</sub></code>'s for <code>a=1</code> as an array
+        * of TNAFs.
+        */
+        public static readonly sbyte[][] Alpha1Tnaf =
+        {
+            null, new sbyte[]{1}, null, new sbyte[]{-1, 0, 1}, null, new sbyte[]{1, 0, 1}, null, new sbyte[]{-1, 0, 0, -1}
+        };
+
+        /**
+        * Computes the norm of an element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code>.
+        * @param mu The parameter <code>μ</code> of the elliptic curve.
+        * @param lambda The element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code>.
+        * @return The norm of <code>λ</code>.
+        */
+        public static BigInteger Norm(sbyte mu, ZTauElement lambda)
+        {
+            BigInteger norm;
+
+            // s1 = u^2
+            BigInteger s1 = lambda.u.Multiply(lambda.u);
+
+            // s2 = u * v
+            BigInteger s2 = lambda.u.Multiply(lambda.v);
+
+            // s3 = 2 * v^2
+            BigInteger s3 = lambda.v.Multiply(lambda.v).ShiftLeft(1);
+
+            if (mu == 1)
+            {
+                norm = s1.Add(s2).Add(s3);
+            }
+            else if (mu == -1)
+            {
+                norm = s1.Subtract(s2).Add(s3);
+            }
+            else
+            {
+                throw new ArgumentException("mu must be 1 or -1");
+            }
+
+            return norm;
+        }
+
+        /**
+        * Computes the norm of an element <code>λ</code> of
+        * <code><b>R</b>[τ]</code>, where <code>λ = u + vτ</code>
+        * and <code>u</code> and <code>u</code> are real numbers (elements of
+        * <code><b>R</b></code>). 
+        * @param mu The parameter <code>μ</code> of the elliptic curve.
+        * @param u The real part of the element <code>λ</code> of
+        * <code><b>R</b>[τ]</code>.
+        * @param v The <code>τ</code>-adic part of the element
+        * <code>λ</code> of <code><b>R</b>[τ]</code>.
+        * @return The norm of <code>λ</code>.
+        */
+        public static SimpleBigDecimal Norm(sbyte mu, SimpleBigDecimal u, SimpleBigDecimal v)
+        {
+            SimpleBigDecimal norm;
+
+            // s1 = u^2
+            SimpleBigDecimal s1 = u.Multiply(u);
+
+            // s2 = u * v
+            SimpleBigDecimal s2 = u.Multiply(v);
+
+            // s3 = 2 * v^2
+            SimpleBigDecimal s3 = v.Multiply(v).ShiftLeft(1);
+
+            if (mu == 1)
+            {
+                norm = s1.Add(s2).Add(s3);
+            }
+            else if (mu == -1)
+            {
+                norm = s1.Subtract(s2).Add(s3);
+            }
+            else
+            {
+                throw new ArgumentException("mu must be 1 or -1");
+            }
+
+            return norm;
+        }
+
+        /**
+        * Rounds an element <code>λ</code> of <code><b>R</b>[τ]</code>
+        * to an element of <code><b>Z</b>[τ]</code>, such that their difference
+        * has minimal norm. <code>λ</code> is given as
+        * <code>λ = λ<sub>0</sub> + λ<sub>1</sub>τ</code>.
+        * @param lambda0 The component <code>λ<sub>0</sub></code>.
+        * @param lambda1 The component <code>λ<sub>1</sub></code>.
+        * @param mu The parameter <code>μ</code> of the elliptic curve. Must
+        * equal 1 or -1.
+        * @return The rounded element of <code><b>Z</b>[τ]</code>.
+        * @throws ArgumentException if <code>lambda0</code> and
+        * <code>lambda1</code> do not have same scale.
+        */
+        public static ZTauElement Round(SimpleBigDecimal lambda0,
+            SimpleBigDecimal lambda1, sbyte mu)
+        {
+            int scale = lambda0.Scale;
+            if (lambda1.Scale != scale)
+                throw new ArgumentException("lambda0 and lambda1 do not have same scale");
+
+            if (!((mu == 1) || (mu == -1)))
+                throw new ArgumentException("mu must be 1 or -1");
+
+            BigInteger f0 = lambda0.Round();
+            BigInteger f1 = lambda1.Round();
+
+            SimpleBigDecimal eta0 = lambda0.Subtract(f0);
+            SimpleBigDecimal eta1 = lambda1.Subtract(f1);
+
+            // eta = 2*eta0 + mu*eta1
+            SimpleBigDecimal eta = eta0.Add(eta0);
+            if (mu == 1)
+            {
+                eta = eta.Add(eta1);
+            }
+            else
+            {
+                // mu == -1
+                eta = eta.Subtract(eta1);
+            }
+
+            // check1 = eta0 - 3*mu*eta1
+            // check2 = eta0 + 4*mu*eta1
+            SimpleBigDecimal threeEta1 = eta1.Add(eta1).Add(eta1);
+            SimpleBigDecimal fourEta1 = threeEta1.Add(eta1);
+            SimpleBigDecimal check1;
+            SimpleBigDecimal check2;
+            if (mu == 1)
+            {
+                check1 = eta0.Subtract(threeEta1);
+                check2 = eta0.Add(fourEta1);
+            }
+            else
+            {
+                // mu == -1
+                check1 = eta0.Add(threeEta1);
+                check2 = eta0.Subtract(fourEta1);
+            }
+
+            sbyte h0 = 0;
+            sbyte h1 = 0;
+
+            // if eta >= 1
+            if (eta.CompareTo(BigInteger.One) >= 0)
+            {
+                if (check1.CompareTo(MinusOne) < 0)
+                {
+                    h1 = mu;
+                }
+                else
+                {
+                    h0 = 1;
+                }
+            }
+            else
+            {
+                // eta < 1
+                if (check2.CompareTo(BigInteger.Two) >= 0)
+                {
+                    h1 = mu;
+                }
+            }
+
+            // if eta < -1
+            if (eta.CompareTo(MinusOne) < 0)
+            {
+                if (check1.CompareTo(BigInteger.One) >= 0)
+                {
+                    h1 = (sbyte)-mu;
+                }
+                else
+                {
+                    h0 = -1;
+                }
+            }
+            else
+            {
+                // eta >= -1
+                if (check2.CompareTo(MinusTwo) < 0)
+                {
+                    h1 = (sbyte)-mu;
+                }
+            }
+
+            BigInteger q0 = f0.Add(BigInteger.ValueOf(h0));
+            BigInteger q1 = f1.Add(BigInteger.ValueOf(h1));
+            return new ZTauElement(q0, q1);
+        }
+
+        /**
+        * Approximate division by <code>n</code>. For an integer
+        * <code>k</code>, the value <code>λ = s k / n</code> is
+        * computed to <code>c</code> bits of accuracy.
+        * @param k The parameter <code>k</code>.
+        * @param s The curve parameter <code>s<sub>0</sub></code> or
+        * <code>s<sub>1</sub></code>.
+        * @param vm The Lucas Sequence element <code>V<sub>m</sub></code>.
+        * @param a The parameter <code>a</code> of the elliptic curve.
+        * @param m The bit length of the finite field
+        * <code><b>F</b><sub>m</sub></code>.
+        * @param c The number of bits of accuracy, i.e. the scale of the returned
+        * <code>SimpleBigDecimal</code>.
+        * @return The value <code>λ = s k / n</code> computed to
+        * <code>c</code> bits of accuracy.
+        */
+        public static SimpleBigDecimal ApproximateDivisionByN(BigInteger k,
+            BigInteger s, BigInteger vm, sbyte a, int m, int c)
+        {
+            int _k = (m + 5)/2 + c;
+            BigInteger ns = k.ShiftRight(m - _k - 2 + a);
+
+            BigInteger gs = s.Multiply(ns);
+
+            BigInteger hs = gs.ShiftRight(m);
+
+            BigInteger js = vm.Multiply(hs);
+
+            BigInteger gsPlusJs = gs.Add(js);
+            BigInteger ls = gsPlusJs.ShiftRight(_k-c);
+            if (gsPlusJs.TestBit(_k-c-1))
+            {
+                // round up
+                ls = ls.Add(BigInteger.One);
+            }
+
+            return new SimpleBigDecimal(ls, c);
+        }
+
+        /**
+        * Computes the <code>τ</code>-adic NAF (non-adjacent form) of an
+        * element <code>λ</code> of <code><b>Z</b>[τ]</code>.
+        * @param mu The parameter <code>μ</code> of the elliptic curve.
+        * @param lambda The element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code>.
+        * @return The <code>τ</code>-adic NAF of <code>λ</code>.
+        */
+        public static sbyte[] TauAdicNaf(sbyte mu, ZTauElement lambda)
+        {
+            if (!((mu == 1) || (mu == -1))) 
+                throw new ArgumentException("mu must be 1 or -1");
+
+            BigInteger norm = Norm(mu, lambda);
+
+            // Ceiling of log2 of the norm 
+            int log2Norm = norm.BitLength;
+
+            // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
+            int maxLength = log2Norm > 30 ? log2Norm + 4 : 34;
+
+            // The array holding the TNAF
+            sbyte[] u = new sbyte[maxLength];
+            int i = 0;
+
+            // The actual length of the TNAF
+            int length = 0;
+
+            BigInteger r0 = lambda.u;
+            BigInteger r1 = lambda.v;
+
+            while(!((r0.Equals(BigInteger.Zero)) && (r1.Equals(BigInteger.Zero))))
+            {
+                // If r0 is odd
+                if (r0.TestBit(0)) 
+                {
+                    u[i] = (sbyte) BigInteger.Two.Subtract((r0.Subtract(r1.ShiftLeft(1))).Mod(Four)).IntValue;
+
+                    // r0 = r0 - u[i]
+                    if (u[i] == 1)
+                    {
+                        r0 = r0.ClearBit(0);
+                    }
+                    else
+                    {
+                        // u[i] == -1
+                        r0 = r0.Add(BigInteger.One);
+                    }
+                    length = i;
+                }
+                else
+                {
+                    u[i] = 0;
+                }
+
+                BigInteger t = r0;
+                BigInteger s = r0.ShiftRight(1);
+                if (mu == 1) 
+                {
+                    r0 = r1.Add(s);
+                }
+                else
+                {
+                    // mu == -1
+                    r0 = r1.Subtract(s);
+                }
+
+                r1 = t.ShiftRight(1).Negate();
+                i++;
+            }
+
+            length++;
+
+            // Reduce the TNAF array to its actual length
+            sbyte[] tnaf = new sbyte[length];
+            Array.Copy(u, 0, tnaf, 0, length);
+            return tnaf;
+        }
+
+        /**
+        * Applies the operation <code>τ()</code> to an
+        * <code>F2mPoint</code>. 
+        * @param p The F2mPoint to which <code>τ()</code> is applied.
+        * @return <code>τ(p)</code>
+        */
+        public static F2mPoint Tau(F2mPoint p)
+        {
+            return p.Tau();
+        }
+
+        /**
+        * Returns the parameter <code>μ</code> of the elliptic curve.
+        * @param curve The elliptic curve from which to obtain <code>μ</code>.
+        * The curve must be a Koblitz curve, i.e. <code>a</code> Equals
+        * <code>0</code> or <code>1</code> and <code>b</code> Equals
+        * <code>1</code>. 
+        * @return <code>μ</code> of the elliptic curve.
+        * @throws ArgumentException if the given ECCurve is not a Koblitz
+        * curve.
+        */
+        public static sbyte GetMu(F2mCurve curve)
+        {
+            BigInteger a = curve.A.ToBigInteger();
+
+            sbyte mu;
+            if (a.SignValue == 0)
+            {
+                mu = -1;
+            }
+            else if (a.Equals(BigInteger.One))
+            {
+                mu = 1;
+            }
+            else
+            {
+                throw new ArgumentException("No Koblitz curve (ABC), TNAF multiplication not possible");
+            }
+            return mu;
+        }
+
+        /**
+        * Calculates the Lucas Sequence elements <code>U<sub>k-1</sub></code> and
+        * <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code> and
+        * <code>V<sub>k</sub></code>.
+        * @param mu The parameter <code>μ</code> of the elliptic curve.
+        * @param k The index of the second element of the Lucas Sequence to be
+        * returned.
+        * @param doV If set to true, computes <code>V<sub>k-1</sub></code> and
+        * <code>V<sub>k</sub></code>, otherwise <code>U<sub>k-1</sub></code> and
+        * <code>U<sub>k</sub></code>.
+        * @return An array with 2 elements, containing <code>U<sub>k-1</sub></code>
+        * and <code>U<sub>k</sub></code> or <code>V<sub>k-1</sub></code>
+        * and <code>V<sub>k</sub></code>.
+        */
+        public static BigInteger[] GetLucas(sbyte mu, int k, bool doV)
+        {
+            if (!(mu == 1 || mu == -1)) 
+                throw new ArgumentException("mu must be 1 or -1");
+
+            BigInteger u0;
+            BigInteger u1;
+            BigInteger u2;
+
+            if (doV)
+            {
+                u0 = BigInteger.Two;
+                u1 = BigInteger.ValueOf(mu);
+            }
+            else
+            {
+                u0 = BigInteger.Zero;
+                u1 = BigInteger.One;
+            }
+
+            for (int i = 1; i < k; i++)
+            {
+                // u2 = mu*u1 - 2*u0;
+                BigInteger s = null;
+                if (mu == 1)
+                {
+                    s = u1;
+                }
+                else
+                {
+                    // mu == -1
+                    s = u1.Negate();
+                }
+                
+                u2 = s.Subtract(u0.ShiftLeft(1));
+                u0 = u1;
+                u1 = u2;
+                //            System.out.println(i + ": " + u2);
+                //            System.out.println();
+            }
+
+            BigInteger[] retVal = {u0, u1};
+            return retVal;
+        }
+
+        /**
+        * Computes the auxiliary value <code>t<sub>w</sub></code>. If the width is
+        * 4, then for <code>mu = 1</code>, <code>t<sub>w</sub> = 6</code> and for
+        * <code>mu = -1</code>, <code>t<sub>w</sub> = 10</code> 
+        * @param mu The parameter <code>μ</code> of the elliptic curve.
+        * @param w The window width of the WTNAF.
+        * @return the auxiliary value <code>t<sub>w</sub></code>
+        */
+        public static BigInteger GetTw(sbyte mu, int w) 
+        {
+            if (w == 4)
+            {
+                if (mu == 1)
+                {
+                    return BigInteger.ValueOf(6);
+                }
+                else
+                {
+                    // mu == -1
+                    return BigInteger.ValueOf(10);
+                }
+            }
+            else
+            {
+                // For w <> 4, the values must be computed
+                BigInteger[] us = GetLucas(mu, w, false);
+                BigInteger twoToW = BigInteger.Zero.SetBit(w);
+                BigInteger u1invert = us[1].ModInverse(twoToW);
+                BigInteger tw;
+                tw = BigInteger.Two.Multiply(us[0]).Multiply(u1invert).Mod(twoToW);
+                //System.out.println("mu = " + mu);
+                //System.out.println("tw = " + tw);
+                return tw;
+            }
+        }
+
+        /**
+        * Computes the auxiliary values <code>s<sub>0</sub></code> and
+        * <code>s<sub>1</sub></code> used for partial modular reduction. 
+        * @param curve The elliptic curve for which to compute
+        * <code>s<sub>0</sub></code> and <code>s<sub>1</sub></code>.
+        * @throws ArgumentException if <code>curve</code> is not a
+        * Koblitz curve (Anomalous Binary Curve, ABC).
+        */
+        public static BigInteger[] GetSi(F2mCurve curve)
+        {
+            if (!curve.IsKoblitz)
+                throw new ArgumentException("si is defined for Koblitz curves only");
+
+            int m = curve.M;
+            int a = curve.A.ToBigInteger().IntValue;
+            sbyte mu = curve.GetMu();
+            int h = curve.Cofactor.IntValue;
+            int index = m + 3 - a;
+            BigInteger[] ui = GetLucas(mu, index, false);
+
+            BigInteger dividend0;
+            BigInteger dividend1;
+            if (mu == 1)
+            {
+                dividend0 = BigInteger.One.Subtract(ui[1]);
+                dividend1 = BigInteger.One.Subtract(ui[0]);
+            }
+            else if (mu == -1)
+            {
+                dividend0 = BigInteger.One.Add(ui[1]);
+                dividend1 = BigInteger.One.Add(ui[0]);
+            }
+            else
+            {
+                throw new ArgumentException("mu must be 1 or -1");
+            }
+
+            BigInteger[] si = new BigInteger[2];
+
+            if (h == 2)
+            {
+                si[0] = dividend0.ShiftRight(1);
+                si[1] = dividend1.ShiftRight(1).Negate();
+            }
+            else if (h == 4)
+            {
+                si[0] = dividend0.ShiftRight(2);
+                si[1] = dividend1.ShiftRight(2).Negate();
+            }
+            else
+            {
+                throw new ArgumentException("h (Cofactor) must be 2 or 4");
+            }
+
+            return si;
+        }
+
+        /**
+        * Partial modular reduction modulo
+        * <code>(τ<sup>m</sup> - 1)/(τ - 1)</code>.
+        * @param k The integer to be reduced.
+        * @param m The bitlength of the underlying finite field.
+        * @param a The parameter <code>a</code> of the elliptic curve.
+        * @param s The auxiliary values <code>s<sub>0</sub></code> and
+        * <code>s<sub>1</sub></code>.
+        * @param mu The parameter μ of the elliptic curve.
+        * @param c The precision (number of bits of accuracy) of the partial
+        * modular reduction.
+        * @return <code>ρ := k partmod (τ<sup>m</sup> - 1)/(τ - 1)</code>
+        */
+        public static ZTauElement PartModReduction(BigInteger k, int m, sbyte a,
+            BigInteger[] s, sbyte mu, sbyte c)
+        {
+            // d0 = s[0] + mu*s[1]; mu is either 1 or -1
+            BigInteger d0;
+            if (mu == 1)
+            {
+                d0 = s[0].Add(s[1]);
+            }
+            else
+            {
+                d0 = s[0].Subtract(s[1]);
+            }
+
+            BigInteger[] v = GetLucas(mu, m, true);
+            BigInteger vm = v[1];
+
+            SimpleBigDecimal lambda0 = ApproximateDivisionByN(
+                k, s[0], vm, a, m, c);
+            
+            SimpleBigDecimal lambda1 = ApproximateDivisionByN(
+                k, s[1], vm, a, m, c);
+
+            ZTauElement q = Round(lambda0, lambda1, mu);
+
+            // r0 = n - d0*q0 - 2*s1*q1
+            BigInteger r0 = k.Subtract(d0.Multiply(q.u)).Subtract(
+                BigInteger.ValueOf(2).Multiply(s[1]).Multiply(q.v));
+
+            // r1 = s1*q0 - s0*q1
+            BigInteger r1 = s[1].Multiply(q.u).Subtract(s[0].Multiply(q.v));
+            
+            return new ZTauElement(r0, r1);
+        }
+
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by a <code>BigInteger</code> using the reduced <code>τ</code>-adic
+        * NAF (RTNAF) method.
+        * @param p The F2mPoint to Multiply.
+        * @param k The <code>BigInteger</code> by which to Multiply <code>p</code>.
+        * @return <code>k * p</code>
+        */
+        public static F2mPoint MultiplyRTnaf(F2mPoint p, BigInteger k)
+        {
+            F2mCurve curve = (F2mCurve) p.Curve;
+            int m = curve.M;
+            sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
+            sbyte mu = curve.GetMu();
+            BigInteger[] s = curve.GetSi();
+            ZTauElement rho = PartModReduction(k, m, a, s, mu, (sbyte)10);
+
+            return MultiplyTnaf(p, rho);
+        }
+
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+        * using the <code>τ</code>-adic NAF (TNAF) method.
+        * @param p The F2mPoint to Multiply.
+        * @param lambda The element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code>.
+        * @return <code>λ * p</code>
+        */
+        public static F2mPoint MultiplyTnaf(F2mPoint p, ZTauElement lambda)
+        {
+            F2mCurve curve = (F2mCurve)p.Curve;
+            sbyte mu = curve.GetMu();
+            sbyte[] u = TauAdicNaf(mu, lambda);
+
+            F2mPoint q = MultiplyFromTnaf(p, u);
+
+            return q;
+        }
+
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+        * using the <code>τ</code>-adic NAF (TNAF) method, given the TNAF
+        * of <code>λ</code>.
+        * @param p The F2mPoint to Multiply.
+        * @param u The the TNAF of <code>λ</code>..
+        * @return <code>λ * p</code>
+        */
+        public static F2mPoint MultiplyFromTnaf(F2mPoint p, sbyte[] u)
+        {
+            F2mCurve curve = (F2mCurve)p.Curve;
+            F2mPoint q = (F2mPoint) curve.Infinity;
+            for (int i = u.Length - 1; i >= 0; i--)
+            {
+                q = Tau(q);
+                if (u[i] == 1)
+                {
+                    q = (F2mPoint)q.AddSimple(p);
+                }
+                else if (u[i] == -1)
+                {
+                    q = (F2mPoint)q.SubtractSimple(p);
+                }
+            }
+            return q;
+        }
+
+        /**
+        * Computes the <code>[τ]</code>-adic window NAF of an element
+        * <code>λ</code> of <code><b>Z</b>[τ]</code>.
+        * @param mu The parameter μ of the elliptic curve.
+        * @param lambda The element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code> of which to compute the
+        * <code>[τ]</code>-adic NAF.
+        * @param width The window width of the resulting WNAF.
+        * @param pow2w 2<sup>width</sup>.
+        * @param tw The auxiliary value <code>t<sub>w</sub></code>.
+        * @param alpha The <code>α<sub>u</sub></code>'s for the window width.
+        * @return The <code>[τ]</code>-adic window NAF of
+        * <code>λ</code>.
+        */
+        public static sbyte[] TauAdicWNaf(sbyte mu, ZTauElement lambda,
+            sbyte width, BigInteger pow2w, BigInteger tw, ZTauElement[] alpha)
+        {
+            if (!((mu == 1) || (mu == -1))) 
+                throw new ArgumentException("mu must be 1 or -1");
+
+            BigInteger norm = Norm(mu, lambda);
+
+            // Ceiling of log2 of the norm 
+            int log2Norm = norm.BitLength;
+
+            // If length(TNAF) > 30, then length(TNAF) < log2Norm + 3.52
+            int maxLength = log2Norm > 30 ? log2Norm + 4 + width : 34 + width;
+
+            // The array holding the TNAF
+            sbyte[] u = new sbyte[maxLength];
+
+            // 2^(width - 1)
+            BigInteger pow2wMin1 = pow2w.ShiftRight(1);
+
+            // Split lambda into two BigIntegers to simplify calculations
+            BigInteger r0 = lambda.u;
+            BigInteger r1 = lambda.v;
+            int i = 0;
+
+            // while lambda <> (0, 0)
+            while (!((r0.Equals(BigInteger.Zero))&&(r1.Equals(BigInteger.Zero))))
+            {
+                // if r0 is odd
+                if (r0.TestBit(0)) 
+                {
+                    // uUnMod = r0 + r1*tw Mod 2^width
+                    BigInteger uUnMod
+                        = r0.Add(r1.Multiply(tw)).Mod(pow2w);
+                    
+                    sbyte uLocal;
+                    // if uUnMod >= 2^(width - 1)
+                    if (uUnMod.CompareTo(pow2wMin1) >= 0)
+                    {
+                        uLocal = (sbyte) uUnMod.Subtract(pow2w).IntValue;
+                    }
+                    else
+                    {
+                        uLocal = (sbyte) uUnMod.IntValue;
+                    }
+                    // uLocal is now in [-2^(width-1), 2^(width-1)-1]
+
+                    u[i] = uLocal;
+                    bool s = true;
+                    if (uLocal < 0) 
+                    {
+                        s = false;
+                        uLocal = (sbyte)-uLocal;
+                    }
+                    // uLocal is now >= 0
+
+                    if (s) 
+                    {
+                        r0 = r0.Subtract(alpha[uLocal].u);
+                        r1 = r1.Subtract(alpha[uLocal].v);
+                    }
+                    else
+                    {
+                        r0 = r0.Add(alpha[uLocal].u);
+                        r1 = r1.Add(alpha[uLocal].v);
+                    }
+                }
+                else
+                {
+                    u[i] = 0;
+                }
+
+                BigInteger t = r0;
+
+                if (mu == 1)
+                {
+                    r0 = r1.Add(r0.ShiftRight(1));
+                }
+                else
+                {
+                    // mu == -1
+                    r0 = r1.Subtract(r0.ShiftRight(1));
+                }
+                r1 = t.ShiftRight(1).Negate();
+                i++;
+            }
+            return u;
+        }
+
+        /**
+        * Does the precomputation for WTNAF multiplication.
+        * @param p The <code>ECPoint</code> for which to do the precomputation.
+        * @param a The parameter <code>a</code> of the elliptic curve.
+        * @return The precomputation array for <code>p</code>. 
+        */
+        public static F2mPoint[] GetPreComp(F2mPoint p, sbyte a)
+        {
+            F2mPoint[] pu;
+            pu = new F2mPoint[16];
+            pu[1] = p;
+            sbyte[][] alphaTnaf;
+            if (a == 0)
+            {
+                alphaTnaf = Tnaf.Alpha0Tnaf;
+            }
+            else
+            {
+                // a == 1
+                alphaTnaf = Tnaf.Alpha1Tnaf;
+            }
+
+            int precompLen = alphaTnaf.Length;
+            for (int i = 3; i < precompLen; i = i + 2)
+            {
+                pu[i] = Tnaf.MultiplyFromTnaf(p, alphaTnaf[i]);
+            }
+            
+            return pu;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/abc/ZTauElement.cs b/BouncyCastle.AxCrypt/src/math/ec/abc/ZTauElement.cs
new file mode 100644
index 0000000..4fcbf1b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/abc/ZTauElement.cs
@@ -0,0 +1,36 @@
+namespace Org.BouncyCastle.Math.EC.Abc
+{
+	/**
+	* Class representing an element of <code><b>Z</b>[τ]</code>. Let
+	* <code>λ</code> be an element of <code><b>Z</b>[τ]</code>. Then
+	* <code>λ</code> is given as <code>λ = u + vτ</code>. The
+	* components <code>u</code> and <code>v</code> may be used directly, there
+	* are no accessor methods.
+	* Immutable class.
+	*/
+	internal class ZTauElement 
+	{
+		/**
+		* The "real" part of <code>λ</code>.
+		*/
+		public readonly BigInteger u;
+
+		/**
+		* The "<code>τ</code>-adic" part of <code>λ</code>.
+		*/
+		public readonly BigInteger v;
+
+		/**
+		* Constructor for an element <code>λ</code> of
+		* <code><b>Z</b>[τ]</code>.
+		* @param u The "real" part of <code>λ</code>.
+		* @param v The "<code>τ</code>-adic" part of
+		* <code>λ</code>.
+		*/
+		public ZTauElement(BigInteger u, BigInteger v)
+		{
+			this.u = u;
+			this.v = v;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519.cs
new file mode 100644
index 0000000..712b68f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Custom.Sec;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Djb
+{
+    internal class Curve25519
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = Nat256.ToBigInteger(Curve25519Field.P);
+
+        private const int Curve25519_DEFAULT_COORDS = COORD_JACOBIAN_MODIFIED;
+
+        protected readonly Curve25519Point m_infinity;
+
+        public Curve25519()
+            : base(q)
+        {
+            this.m_infinity = new Curve25519Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA984914A144")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("7B425ED097B425ED097B425ED097B425ED097B425ED097B4260B5E9C7710C864")));
+            this.m_order = new BigInteger(1, Hex.Decode("1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED"));
+            this.m_cofactor = BigInteger.ValueOf(8);
+            this.m_coord = Curve25519_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new Curve25519();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+            case COORD_JACOBIAN_MODIFIED:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new Curve25519FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new Curve25519Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new Curve25519Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Field.cs
new file mode 100644
index 0000000..809e51b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Field.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Math.EC.Custom.Sec;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Djb
+{
+    internal class Curve25519Field
+    {
+        // 2^255 - 2^4 - 2^1 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0x7FFFFFFF };
+        private const uint P7 = 0x7FFFFFFF;
+        private static readonly uint[] PExt = new uint[]{ 0x00000169, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+            0x00000000, 0x00000000, 0x00000000, 0xFFFFFFED, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0x3FFFFFFF };
+        private const uint PInv = 0x13;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            Nat256.Add(x, y, z);
+            if (Nat256.Gte(z, P))
+            {
+                SubPFrom(z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            Nat.Add(16, xx, yy, zz);
+            if (Nat.Gte(16, zz, PExt))
+            {
+                SubPExtFrom(zz);
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            Nat.Inc(8, x, z);
+            if (Nat256.Gte(z, P))
+            {
+                SubPFrom(z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat256.FromBigInteger(x);
+            while (Nat256.Gte(z, P))
+            {
+                Nat256.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(8, x, 0, z);
+            }
+            else
+            {
+                Nat256.Add(x, P, z);
+                Nat.ShiftDownBit(8, z, 0);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            Nat256.MulAddTo(x, y, zz);
+            if (Nat.Gte(16, zz, PExt))
+            {
+                SubPExtFrom(zz);
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat256.IsZero(x))
+            {
+                Nat256.Zero(z);
+            }
+            else
+            {
+                Nat256.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            Debug.Assert(xx[15] >> 30 == 0);
+
+            uint xx07 = xx[7];
+            Nat.ShiftUpBit(8, xx, 8, xx07, z, 0);
+            uint c = Nat256.MulByWordAddTo(PInv, xx, z) << 1;
+            uint z7 = z[7];
+            c += (z7 >> 31) - (xx07 >> 31);
+            z7 &= P7;
+            z7 += Nat.AddWordTo(7, c * PInv, z);
+            z[7] = z7;
+            if (z7 >= P7 && Nat256.Gte(z, P))
+            {
+                SubPFrom(z);
+            }
+        }
+
+        public static void Reduce27(uint x, uint[] z)
+        {
+            Debug.Assert(x >> 26 == 0);
+
+            uint z7 = z[7];
+            uint c = (x << 1 | z7 >> 31);
+            z7 &= P7;
+            z7 += Nat.AddWordTo(7, c * PInv, z);
+            z[7] = z7;
+            if (z7 >= P7 && Nat256.Gte(z, P))
+            {
+                SubPFrom(z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat256.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat256.Sub(x, y, z);
+            if (c != 0)
+            {
+                AddPTo(z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(16, xx, yy, zz);
+            if (c != 0)
+            {
+                AddPExtTo(zz);
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            Nat.ShiftUpBit(8, x, 0, z);
+            if (Nat256.Gte(z, P))
+            {
+                SubPFrom(z);
+            }
+        }
+
+        private static uint AddPTo(uint[] z)
+        {
+            long c = (long)z[0] - PInv;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.DecAt(7, z, 1);
+            }
+            c += (long)z[7] + (P7 + 1);
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        private static uint AddPExtTo(uint[] zz)
+        {
+            long c = (long)zz[0] + PExt[0];
+            zz[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.IncAt(8, zz, 1);
+            }
+            c += (long)zz[8] - PInv;
+            zz[8] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.DecAt(15, zz, 9);
+            }
+            c += (long)zz[15] + (PExt[15] + 1);
+            zz[15] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        private static int SubPFrom(uint[] z)
+        {
+            long c = (long)z[0] + PInv;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.IncAt(7, z, 1);
+            }
+            c += (long)z[7] - (P7 + 1);
+            z[7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        private static int SubPExtFrom(uint[] zz)
+        {
+            long c = (long)zz[0] - PExt[0];
+            zz[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.DecAt(8, zz, 1);
+            }
+            c += (long)zz[8] + PInv;
+            zz[8] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c = Nat.IncAt(15, zz, 9);
+            }
+            c += (long)zz[15] - (PExt[15] + 1);
+            zz[15] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519FieldElement.cs
new file mode 100644
index 0000000..8d5a803
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519FieldElement.cs
@@ -0,0 +1,233 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Custom.Sec;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Djb
+{
+    internal class Curve25519FieldElement
+        :   ECFieldElement
+    {
+        public static readonly BigInteger Q = Curve25519.q;
+
+        // Calculated as ECConstants.TWO.modPow(Q.shiftRight(2), Q)
+        private static readonly uint[] PRECOMP_POW2 = new uint[]{ 0x4a0ea0b0, 0xc4ee1b27, 0xad2fe478, 0x2f431806,
+            0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480 };
+
+        protected internal readonly uint[] x;
+
+        public Curve25519FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for Curve25519FieldElement", "x");
+
+            this.x = Curve25519Field.FromBigInteger(x);
+        }
+
+        public Curve25519FieldElement()
+        {
+            this.x = Nat256.Create();
+        }
+
+        protected internal Curve25519FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat256.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat256.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat256.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat256.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "Curve25519Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.Add(x, ((Curve25519FieldElement)b).x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.AddOne(x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.Subtract(x, ((Curve25519FieldElement)b).x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.Multiply(x, ((Curve25519FieldElement)b).x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat256.Create();
+            Mod.Invert(Curve25519Field.P, ((Curve25519FieldElement)b).x, z);
+            Curve25519Field.Multiply(z, x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.Negate(x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat256.Create();
+            Curve25519Field.Square(x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new Curve25519FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat256.Create();
+            Mod.Invert(Curve25519Field.P, x, z);
+            return new Curve25519FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            /*
+             * Q == 8m + 5, so we use Pocklington's method for this case.
+             *
+             * First, raise this element to the exponent 2^252 - 2^1 (i.e. m + 1)
+             * 
+             * Breaking up the exponent's binary representation into "repunits", we get:
+             * { 251 1s } { 1 0s }
+             * 
+             * Therefore we need an addition chain containing 251 (the lengths of the repunits)
+             * We use: 1, 2, 3, 4, 7, 11, 15, 30, 60, 120, 131, [251]
+             */
+
+            uint[] x1 = this.x;
+            if (Nat256.IsZero(x1) || Nat256.IsOne(x1))
+                return this;
+
+            uint[] x2 = Nat256.Create();
+            Curve25519Field.Square(x1, x2);
+            Curve25519Field.Multiply(x2, x1, x2);
+            uint[] x3 = x2;
+            Curve25519Field.Square(x2, x3);
+            Curve25519Field.Multiply(x3, x1, x3);
+            uint[] x4 = Nat256.Create();
+            Curve25519Field.Square(x3, x4);
+            Curve25519Field.Multiply(x4, x1, x4);
+            uint[] x7 = Nat256.Create();
+            Curve25519Field.SquareN(x4, 3, x7);
+            Curve25519Field.Multiply(x7, x3, x7);
+            uint[] x11 = x3;
+            Curve25519Field.SquareN(x7, 4, x11);
+            Curve25519Field.Multiply(x11, x4, x11);
+            uint[] x15 = x7;
+            Curve25519Field.SquareN(x11, 4, x15);
+            Curve25519Field.Multiply(x15, x4, x15);
+            uint[] x30 = x4;
+            Curve25519Field.SquareN(x15, 15, x30);
+            Curve25519Field.Multiply(x30, x15, x30);
+            uint[] x60 = x15;
+            Curve25519Field.SquareN(x30, 30, x60);
+            Curve25519Field.Multiply(x60, x30, x60);
+            uint[] x120 = x30;
+            Curve25519Field.SquareN(x60, 60, x120);
+            Curve25519Field.Multiply(x120, x60, x120);
+            uint[] x131 = x60;
+            Curve25519Field.SquareN(x120, 11, x131);
+            Curve25519Field.Multiply(x131, x11, x131);
+            uint[] x251 = x11;
+            Curve25519Field.SquareN(x131, 120, x251);
+            Curve25519Field.Multiply(x251, x120, x251);
+
+            uint[] t1 = x251;
+            Curve25519Field.Square(t1, t1);
+
+            uint[] t2 = x120;
+            Curve25519Field.Square(t1, t2);
+
+            if (Nat256.Eq(x1, t2))
+            {
+                return new Curve25519FieldElement(t1);
+            }
+
+            /*
+             * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
+             * which is ((4x)^(m + 1))/2 mod Q
+             */
+            Curve25519Field.Multiply(t1, PRECOMP_POW2, t1);
+
+            Curve25519Field.Square(t1, t2);
+
+            if (Nat256.Eq(x1, t2))
+            {
+                return new Curve25519FieldElement(t1);
+            }
+
+            return null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as Curve25519FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as Curve25519FieldElement);
+        }
+
+        public virtual bool Equals(Curve25519FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat256.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 8);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Point.cs
new file mode 100644
index 0000000..bfec1d1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/djb/Curve25519Point.cs
@@ -0,0 +1,313 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Custom.Sec;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Djb
+{
+    internal class Curve25519Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve the curve to use
+         * @param x affine x co-ordinate
+         * @param y affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.CreatePoint to construct points
+         */
+        public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve the curve to use
+         * @param x affine x co-ordinate
+         * @param y affine y co-ordinate
+         * @param withCompression if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer {@link #getEncoded(bool)}
+         */
+        public Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal Curve25519Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new Curve25519Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECFieldElement GetZCoord(int index)
+        {
+            if (index == 1)
+            {
+                return GetJacobianModifiedW();
+            }
+
+            return base.GetZCoord(index);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            Curve25519FieldElement X1 = (Curve25519FieldElement)this.RawXCoord, Y1 = (Curve25519FieldElement)this.RawYCoord,
+                Z1 = (Curve25519FieldElement)this.RawZCoords[0];
+            Curve25519FieldElement X2 = (Curve25519FieldElement)b.RawXCoord, Y2 = (Curve25519FieldElement)b.RawYCoord,
+                Z2 = (Curve25519FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat256.CreateExt();
+            uint[] t2 = Nat256.Create();
+            uint[] t3 = Nat256.Create();
+            uint[] t4 = Nat256.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                Curve25519Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                Curve25519Field.Multiply(S2, X2.x, U2);
+
+                Curve25519Field.Multiply(S2, Z1.x, S2);
+                Curve25519Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                Curve25519Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                Curve25519Field.Multiply(S1, X1.x, U1);
+
+                Curve25519Field.Multiply(S1, Z2.x, S1);
+                Curve25519Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat256.Create();
+            Curve25519Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            Curve25519Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat256.IsZero(H))
+            {
+                if (Nat256.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = Nat256.Create();
+            Curve25519Field.Square(H, HSquared);
+
+            uint[] G = Nat256.Create();
+            Curve25519Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            Curve25519Field.Multiply(HSquared, U1, V);
+
+            Curve25519Field.Negate(G, G);
+            Nat256.Mul(S1, G, tt1);
+
+            c = Nat256.AddBothTo(V, V, G);
+            Curve25519Field.Reduce27(c, G);
+
+            Curve25519FieldElement X3 = new Curve25519FieldElement(t4);
+            Curve25519Field.Square(R, X3.x);
+            Curve25519Field.Subtract(X3.x, G, X3.x);
+
+            Curve25519FieldElement Y3 = new Curve25519FieldElement(G);
+            Curve25519Field.Subtract(V, X3.x, Y3.x);
+            Curve25519Field.MultiplyAddToExt(Y3.x, R, tt1);
+            Curve25519Field.Reduce(tt1, Y3.x);
+
+            Curve25519FieldElement Z3 = new Curve25519FieldElement(H);
+            if (!Z1IsOne)
+            {
+                Curve25519Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                Curve25519Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            uint[] Z3Squared = (Z1IsOne && Z2IsOne) ? HSquared : null;
+
+            // TODO If the result will only be used in a subsequent addition, we don't need W3
+            Curve25519FieldElement W3 = CalculateJacobianModifiedW((Curve25519FieldElement)Z3, Z3Squared);
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3, W3 };
+
+            return new Curve25519Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            return TwiceJacobianModified(true);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return TwiceJacobianModified(false).Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            return TwiceJacobianModified(false).Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new Curve25519Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+
+        protected virtual Curve25519FieldElement CalculateJacobianModifiedW(Curve25519FieldElement Z, uint[] ZSquared)
+        {
+            Curve25519FieldElement a4 = (Curve25519FieldElement)this.Curve.A;
+            if (Z.IsOne)
+                return a4;
+
+            Curve25519FieldElement W = new Curve25519FieldElement();
+            if (ZSquared == null)
+            {
+                ZSquared = W.x;
+                Curve25519Field.Square(Z.x, ZSquared);
+            }
+            Curve25519Field.Square(ZSquared, W.x);
+            Curve25519Field.Multiply(W.x, a4.x, W.x);
+            return W;
+        }
+
+        protected virtual Curve25519FieldElement GetJacobianModifiedW()
+        {
+            ECFieldElement[] ZZ = this.RawZCoords;
+            Curve25519FieldElement W = (Curve25519FieldElement)ZZ[1];
+            if (W == null)
+            {
+                // NOTE: Rarely, TwicePlus will result in the need for a lazy W1 calculation here
+                ZZ[1] = W = CalculateJacobianModifiedW((Curve25519FieldElement)ZZ[0], null);
+            }
+            return W;
+        }
+
+        protected virtual Curve25519Point TwiceJacobianModified(bool calculateW)
+        {
+            Curve25519FieldElement X1 = (Curve25519FieldElement)this.RawXCoord, Y1 = (Curve25519FieldElement)this.RawYCoord,
+                Z1 = (Curve25519FieldElement)this.RawZCoords[0], W1 = GetJacobianModifiedW();
+
+            uint c;
+
+            uint[] M = Nat256.Create();
+            Curve25519Field.Square(X1.x, M);
+            c = Nat256.AddBothTo(M, M, M);
+            c += Nat256.AddTo(W1.x, M);
+            Curve25519Field.Reduce27(c, M);
+
+            uint[] _2Y1 = Nat256.Create();
+            Curve25519Field.Twice(Y1.x, _2Y1);
+
+            uint[] _2Y1Squared = Nat256.Create();
+            Curve25519Field.Multiply(_2Y1, Y1.x, _2Y1Squared);
+
+            uint[] S = Nat256.Create();
+            Curve25519Field.Multiply(_2Y1Squared, X1.x, S);
+            Curve25519Field.Twice(S, S);
+
+            uint[] _8T = Nat256.Create();
+            Curve25519Field.Square(_2Y1Squared, _8T);
+            Curve25519Field.Twice(_8T, _8T);
+
+            Curve25519FieldElement X3 = new Curve25519FieldElement(_2Y1Squared);
+            Curve25519Field.Square(M, X3.x);
+            Curve25519Field.Subtract(X3.x, S, X3.x);
+            Curve25519Field.Subtract(X3.x, S, X3.x);
+
+            Curve25519FieldElement Y3 = new Curve25519FieldElement(S);
+            Curve25519Field.Subtract(S, X3.x, Y3.x);
+            Curve25519Field.Multiply(Y3.x, M, Y3.x);
+            Curve25519Field.Subtract(Y3.x, _8T, Y3.x);
+
+            Curve25519FieldElement Z3 = new Curve25519FieldElement(_2Y1);
+            if (!Nat256.IsOne(Z1.x))
+            {
+                Curve25519Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            Curve25519FieldElement W3 = null;
+            if (calculateW)
+            {
+                W3 = new Curve25519FieldElement(_8T);
+                Curve25519Field.Multiply(W3.x, W1.x, W3.x);
+                Curve25519Field.Twice(W3.x, W3.x);
+            }
+
+            return new Curve25519Point(this.Curve, X3, Y3, new ECFieldElement[] { Z3, W3 }, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat192.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat192.cs
new file mode 100644
index 0000000..94d7ed1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat192.cs
@@ -0,0 +1,962 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal abstract class Nat192
+    {
+        private const ulong M = 0xFFFFFFFFUL;
+
+        public static uint Add(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn)
+        {
+            ulong c = cIn;
+            c += (ulong)x[xOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff)
+        {
+            ulong c = 0;
+            c += (ulong)u[uOff + 0] + v[vOff + 0];
+            u[uOff + 0] = (uint)c;
+            v[vOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 1] + v[vOff + 1];
+            u[uOff + 1] = (uint)c;
+            v[vOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 2] + v[vOff + 2];
+            u[uOff + 2] = (uint)c;
+            v[vOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 3] + v[vOff + 3];
+            u[uOff + 3] = (uint)c;
+            v[vOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 4] + v[vOff + 4];
+            u[uOff + 4] = (uint)c;
+            v[vOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 5] + v[vOff + 5];
+            u[uOff + 5] = (uint)c;
+            v[vOff + 5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static void Copy(uint[] x, uint[] z)
+        {
+            z[0] = x[0];
+            z[1] = x[1];
+            z[2] = x[2];
+            z[3] = x[3];
+            z[4] = x[4];
+            z[5] = x[5];
+        }
+
+        public static uint[] Create()
+        {
+            return new uint[6];
+        }
+
+        public static uint[] CreateExt()
+        {
+            return new uint[12];
+        }
+
+        public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            bool pos = Gte(x, xOff, y, yOff);
+            if (pos)
+            {
+                Sub(x, xOff, y, yOff, z, zOff);
+            }
+            else
+            {
+                Sub(y, yOff, x, xOff, z, zOff);
+            }
+            return pos;
+        }
+
+        public static bool Eq(uint[] x, uint[] y)
+        {
+            for (int i = 5; i >= 0; --i)
+            {
+                if (x[i] != y[i])
+                    return false;
+            }
+            return true;
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            if (x.SignValue < 0 || x.BitLength > 192)
+                throw new ArgumentException();
+
+            uint[] z = Create();
+            int i = 0;
+            while (x.SignValue != 0)
+            {
+                z[i++] = (uint)x.IntValue;
+                x = x.ShiftRight(32);
+            }
+            return z;
+        }
+
+        public static uint GetBit(uint[] x, int bit)
+        {
+            if (bit == 0)
+            {
+                return x[0] & 1;
+            }
+            int w = bit >> 5;
+            if (w < 0 || w >= 6)
+            {
+                return 0;
+            }
+            int b = bit & 31;
+            return (x[w] >> b) & 1;
+        }
+
+        public static bool Gte(uint[] x, uint[] y)
+        {
+            for (int i = 5; i >= 0; --i)
+            {
+                uint x_i = x[i], y_i = y[i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool Gte(uint[] x, int xOff, uint[] y, int yOff)
+        {
+            for (int i = 5; i >= 0; --i)
+            {
+                uint x_i = x[xOff + i], y_i = y[yOff + i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool IsOne(uint[] x)
+        {
+            if (x[0] != 1)
+            {
+                return false;
+            }
+            for (int i = 1; i < 6; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsZero(uint[] x)
+        {
+            for (int i = 0; i < 6; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static void Mul(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+
+            {
+                ulong c = 0, x_0 = x[0];
+                c += x_0 * y_0;
+                zz[0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[5] = (uint)c;
+                c >>= 32;
+                zz[6] = (uint)c;
+            }
+
+            for (int i = 1; i < 6; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                zz[i + 6] = (uint)c;
+            }
+        }
+
+        public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+
+            {
+                ulong c = 0, x_0 = x[xOff + 0];
+                c += x_0 * y_0;
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 6] = (uint)c;
+            }
+
+            for (int i = 1; i < 6; ++i)
+            {
+                ++zzOff;
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 6] = (uint)c;
+            }
+        }
+
+        public static uint MulAddTo(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+
+            ulong zc = 0;
+            for (int i = 0; i < 6; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                c += zc + zz[i + 6];
+                zz[i + 6] = (uint)c;
+                zc = c >> 32;
+            }
+            return (uint)zc;
+        }
+
+        public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+
+            ulong zc = 0;
+            for (int i = 0; i < 6; ++i)
+            {
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += zc + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)c;
+                zc = c >> 32;
+                ++zzOff;
+            }
+            return (uint)zc;
+        }
+
+        public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            Debug.Assert(w >> 31 == 0);
+
+            ulong c = 0, wVal = w;
+            ulong x0 = x[xOff + 0];
+            c += wVal * x0 + y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong x1 = x[xOff + 1];
+            c += wVal * x1 + x0 + y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            ulong x2 = x[xOff + 2];
+            c += wVal * x2 + x1 + y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            ulong x3 = x[xOff + 3];
+            c += wVal * x3 + x2 + y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            ulong x4 = x[xOff + 4];
+            c += wVal * x4 + x3 + y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            ulong x5 = x[xOff + 5];
+            c += wVal * x5 + x4 + y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += x5;
+            return c;
+        }
+
+        public static uint MulWordAddExt(uint x, uint[] yy, int yyOff, uint[] zz, int zzOff)
+        {
+            Debug.Assert(yyOff <= 6);
+            Debug.Assert(zzOff <= 6);
+            ulong c = 0, xVal = x;
+            c += xVal * yy[yyOff + 0] + zz[zzOff + 0];
+            zz[zzOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * yy[yyOff + 1] + zz[zzOff + 1];
+            zz[zzOff + 1] = (uint)c;
+            c >>= 32;
+            c += xVal * yy[yyOff + 2] + zz[zzOff + 2];
+            zz[zzOff + 2] = (uint)c;
+            c >>= 32;
+            c += xVal * yy[yyOff + 3] + zz[zzOff + 3];
+            zz[zzOff + 3] = (uint)c;
+            c >>= 32;
+            c += xVal * yy[yyOff + 4] + zz[zzOff + 4];
+            zz[zzOff + 4] = (uint)c;
+            c >>= 32;
+            c += xVal * yy[yyOff + 5] + zz[zzOff + 5];
+            zz[zzOff + 5] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <= 2);
+            ulong c = 0, xVal = x;
+            ulong y00 = y & M;
+            c += xVal * y00 + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong y01 = y >> 32;
+            c += xVal * y01 + y00 + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += y01 + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 4);
+        }
+
+        public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <=3);
+            ulong c = 0, yVal = y;
+            c += yVal * x + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += yVal + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3);
+        }
+
+        public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(zOff <= 3);
+            ulong c = 0, xVal = x;
+            c += xVal * y + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * (y >> 32) + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(6, z, zOff, 3);
+        }
+
+        public static uint MulWord(uint x, uint[] y, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < 6);
+            return (uint)c;
+        }
+
+        public static void Square(uint[] x, uint[] zz)
+        {
+            ulong x_0 = x[0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 5, j = 12;
+                do
+                {
+                    ulong xVal = x[i--];
+                    ulong p = xVal * xVal;
+                    zz[--j] = (c << 31) | (uint)(p >> 33);
+                    zz[--j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[1];
+            ulong zz_2 = zz[2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[2];
+            ulong zz_3 = zz[3];
+            ulong zz_4 = zz[4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[3];
+            ulong zz_5 = zz[5];
+            ulong zz_6 = zz[6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[4];
+            ulong zz_7 = zz[7];
+            ulong zz_8 = zz[8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[5];
+            ulong zz_9 = zz[9];
+            ulong zz_10 = zz[10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_10 += zz_9 >> 32;
+            }
+
+            w = (uint)zz_6;
+            zz[6] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_7;
+            zz[7] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_8;
+            zz[8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[10] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[11] + (uint)(zz_10 >> 32);
+            zz[11] = (w << 1) | c;
+        }
+
+        public static void Square(uint[] x, int xOff, uint[] zz, int zzOff)
+        {
+            ulong x_0 = x[xOff + 0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 5, j = 12;
+                do
+                {
+                    ulong xVal = x[xOff + i--];
+                    ulong p = xVal * xVal;
+                    zz[zzOff + --j] = (c << 31) | (uint)(p >> 33);
+                    zz[zzOff + --j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[zzOff + 0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[xOff + 1];
+            ulong zz_2 = zz[zzOff + 2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[zzOff + 1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[xOff + 2];
+            ulong zz_3 = zz[zzOff + 3];
+            ulong zz_4 = zz[zzOff + 4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[zzOff + 2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[xOff + 3];
+            ulong zz_5 = zz[zzOff + 5];
+            ulong zz_6 = zz[zzOff + 6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[zzOff + 3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[xOff + 4];
+            ulong zz_7 = zz[zzOff + 7];
+            ulong zz_8 = zz[zzOff + 8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[zzOff + 4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[xOff + 5];
+            ulong zz_9 = zz[zzOff + 9];
+            ulong zz_10 = zz[zzOff + 10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[zzOff + 5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_10 += zz_9 >> 32;
+            }
+
+            w = (uint)zz_6;
+            zz[zzOff + 6] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_7;
+            zz[zzOff + 7] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_8;
+            zz[zzOff + 8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[zzOff + 9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[zzOff + 10] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[zzOff + 11] + (uint)(zz_10 >> 32);
+            zz[zzOff + 11] = (w << 1) | c;
+        }
+
+        public static int Sub(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)x[xOff + 0] - y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 1] - y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 2] - y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 3] - y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 4] - y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 5] - y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubBothFrom(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)z[zOff + 0] - x[xOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 1] - x[xOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 2] - x[xOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 3] - x[xOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 4] - x[xOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 5] - x[xOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static BigInteger ToBigInteger(uint[] x)
+        {
+            byte[] bs = new byte[24];
+            for (int i = 0; i < 6; ++i)
+            {
+                uint x_i = x[i];
+                if (x_i != 0)
+                {
+                    Pack.UInt32_To_BE(x_i, bs, (5 - i) << 2);
+                }
+            }
+            return new BigInteger(1, bs);
+        }
+
+        public static void Zero(uint[] z)
+        {
+            z[0] = 0;
+            z[1] = 0;
+            z[2] = 0;
+            z[3] = 0;
+            z[4] = 0;
+            z[5] = 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat224.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat224.cs
new file mode 100644
index 0000000..d5b916a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat224.cs
@@ -0,0 +1,1176 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal abstract class Nat224
+    {
+        private const ulong M = 0xFFFFFFFFUL;
+
+        public static uint Add(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            c += (ulong)x[xOff + 0] + y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + y[6] + z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn)
+        {
+            ulong c = cIn;
+            c += (ulong)x[xOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff)
+        {
+            ulong c = 0;
+            c += (ulong)u[uOff + 0] + v[vOff + 0];
+            u[uOff + 0] = (uint)c;
+            v[vOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 1] + v[vOff + 1];
+            u[uOff + 1] = (uint)c;
+            v[vOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 2] + v[vOff + 2];
+            u[uOff + 2] = (uint)c;
+            v[vOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 3] + v[vOff + 3];
+            u[uOff + 3] = (uint)c;
+            v[vOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 4] + v[vOff + 4];
+            u[uOff + 4] = (uint)c;
+            v[vOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 5] + v[vOff + 5];
+            u[uOff + 5] = (uint)c;
+            v[vOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 6] + v[vOff + 6];
+            u[uOff + 6] = (uint)c;
+            v[vOff + 6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static void Copy(uint[] x, uint[] z)
+        {
+            z[0] = x[0];
+            z[1] = x[1];
+            z[2] = x[2];
+            z[3] = x[3];
+            z[4] = x[4];
+            z[5] = x[5];
+            z[6] = x[6];
+        }
+
+        public static uint[] Create()
+        {
+            return new uint[7];
+        }
+
+        public static uint[] CreateExt()
+        {
+            return new uint[14];
+        }
+
+        public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            bool pos = Gte(x, xOff, y, yOff);
+            if (pos)
+            {
+                Sub(x, xOff, y, yOff, z, zOff);
+            }
+            else
+            {
+                Sub(y, yOff, x, xOff, z, zOff);
+            }
+            return pos;
+        }
+
+        public static bool Eq(uint[] x, uint[] y)
+        {
+            for (int i = 6; i >= 0; --i)
+            {
+                if (x[i] != y[i])
+                    return false;
+            }
+            return true;
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            if (x.SignValue < 0 || x.BitLength > 224)
+                throw new ArgumentException();
+
+            uint[] z = Create();
+            int i = 0;
+            while (x.SignValue != 0)
+            {
+                z[i++] = (uint)x.IntValue;
+                x = x.ShiftRight(32);
+            }
+            return z;
+        }
+
+        public static uint GetBit(uint[] x, int bit)
+        {
+            if (bit == 0)
+            {
+                return x[0] & 1;
+            }
+            int w = bit >> 5;
+            if (w < 0 || w >= 7)
+            {
+                return 0;
+            }
+            int b = bit & 31;
+            return (x[w] >> b) & 1;
+        }
+
+        public static bool Gte(uint[] x, uint[] y)
+        {
+            for (int i = 6; i >= 0; --i)
+            {
+                uint x_i = x[i], y_i = y[i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool Gte(uint[] x, int xOff, uint[] y, int yOff)
+        {
+            for (int i = 6; i >= 0; --i)
+            {
+                uint x_i = x[xOff + i], y_i = y[yOff + i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool IsOne(uint[] x)
+        {
+            if (x[0] != 1)
+            {
+                return false;
+            }
+            for (int i = 1; i < 7; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsZero(uint[] x)
+        {
+            for (int i = 0; i < 7; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static void Mul(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+            ulong y_6 = y[6];
+
+            {
+                ulong c = 0, x_0 = x[0];
+                c += x_0 * y_0;
+                zz[0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[5] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_6;
+                zz[6] = (uint)c;
+                c >>= 32;
+                zz[7] = (uint)c;
+            }
+
+            for (int i = 1; i < 7; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[i + 6];
+                zz[i + 6] = (uint)c;
+                c >>= 32;
+                zz[i + 7] = (uint)c;
+            }
+        }
+
+        public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+            ulong y_6 = y[yOff + 6];
+
+            {
+                ulong c = 0, x_0 = x[xOff + 0];
+                c += x_0 * y_0;
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_6;
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 7] = (uint)c;
+            }
+
+            for (int i = 1; i < 7; ++i)
+            {
+                ++zzOff;
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 7] = (uint)c;
+            }
+        }
+
+        public static uint MulAddTo(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+            ulong y_6 = y[6];
+
+            ulong zc = 0;
+            for (int i = 0; i < 7; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[i + 6];
+                zz[i + 6] = (uint)c;
+                c >>= 32;
+                c += zc + zz[i + 7];
+                zz[i + 7] = (uint)c;
+                zc = c >> 32;
+            }
+            return (uint)zc;
+        }
+
+        public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+            ulong y_6 = y[yOff + 6];
+
+            ulong zc = 0;
+            for (int i = 0; i < 7; ++i)
+            {
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                c += zc + zz[zzOff + 7];
+                zz[zzOff + 7] = (uint)c;
+                zc = c >> 32;
+                ++zzOff;
+            }
+            return (uint)zc;
+        }
+
+        public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            Debug.Assert(w >> 31 == 0);
+
+            ulong c = 0, wVal = w;
+            ulong x0 = x[xOff + 0];
+            c += wVal * x0 + y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong x1 = x[xOff + 1];
+            c += wVal * x1 + x0 + y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            ulong x2 = x[xOff + 2];
+            c += wVal * x2 + x1 + y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            ulong x3 = x[xOff + 3];
+            c += wVal * x3 + x2 + y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            ulong x4 = x[xOff + 4];
+            c += wVal * x4 + x3 + y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            ulong x5 = x[xOff + 5];
+            c += wVal * x5 + x4 + y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            ulong x6 = x[xOff + 6];
+            c += wVal * x6 + x5 + y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += x6;
+            return c;
+        }
+
+        public static uint MulByWord(uint x, uint[] z)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * (ulong)z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint MulByWordAddTo(uint x, uint[] y, uint[] z)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * (ulong)z[0] + y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[1] + y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[2] + y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[3] + y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[4] + y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[5] + y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[6] + y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * y[yOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <= 3);
+            ulong c = 0, xVal = x;
+            ulong y00 = y & M;
+            c += xVal * y00 + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong y01 = y >> 32;
+            c += xVal * y01 + y00 + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += y01 + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 4);
+        }
+
+        public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <= 4);
+            ulong c = 0, yVal = y;
+            c += yVal * x + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += yVal + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3);
+        }
+
+        public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(zOff <= 4);
+            ulong c = 0, xVal = x;
+            c += xVal * y + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * (y >> 32) + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(7, z, zOff, 3);
+        }
+
+        public static uint MulWord(uint x, uint[] y, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < 7);
+            return (uint)c;
+        }
+
+        public static void Square(uint[] x, uint[] zz)
+        {
+            ulong x_0 = x[0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 6, j = 14;
+                do
+                {
+                    ulong xVal = x[i--];
+                    ulong p = xVal * xVal;
+                    zz[--j] = (c << 31) | (uint)(p >> 33);
+                    zz[--j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[1];
+            ulong zz_2 = zz[2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[2];
+            ulong zz_3 = zz[3];
+            ulong zz_4 = zz[4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[3];
+            ulong zz_5 = zz[5];
+            ulong zz_6 = zz[6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[4];
+            ulong zz_7 = zz[7];
+            ulong zz_8 = zz[8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[5];
+            ulong zz_9 = zz[9];
+            ulong zz_10 = zz[10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_6 &= M;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_8 &= M;
+                zz_10 += zz_9 >> 32;
+                zz_9 &= M;
+            }
+
+            ulong x_6 = x[6];
+            ulong zz_11 = zz[11];
+            ulong zz_12 = zz[12];
+            {
+                zz_6 += x_6 * x_0;
+                w = (uint)zz_6;
+                zz[6] = (w << 1) | c;
+                c = w >> 31;
+                zz_7 += (zz_6 >> 32) + x_6 * x_1;
+                zz_8 += (zz_7 >> 32) + x_6 * x_2;
+                zz_9 += (zz_8 >> 32) + x_6 * x_3;
+                zz_10 += (zz_9 >> 32) + x_6 * x_4;
+                zz_11 += (zz_10 >> 32) + x_6 * x_5;
+                zz_12 += zz_11 >> 32;
+            }
+
+            w = (uint)zz_7;
+            zz[7] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_8;
+            zz[8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[10] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_11;
+            zz[11] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_12;
+            zz[12] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[13] + (uint)(zz_12 >> 32);
+            zz[13] = (w << 1) | c;
+        }
+
+        public static void Square(uint[] x, int xOff, uint[] zz, int zzOff)
+        {
+            ulong x_0 = x[xOff + 0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 6, j = 14;
+                do
+                {
+                    ulong xVal = x[xOff + i--];
+                    ulong p = xVal * xVal;
+                    zz[zzOff + --j] = (c << 31) | (uint)(p >> 33);
+                    zz[zzOff + --j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[zzOff + 0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[xOff + 1];
+            ulong zz_2 = zz[zzOff + 2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[zzOff + 1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[xOff + 2];
+            ulong zz_3 = zz[zzOff + 3];
+            ulong zz_4 = zz[zzOff + 4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[zzOff + 2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[xOff + 3];
+            ulong zz_5 = zz[zzOff + 5];
+            ulong zz_6 = zz[zzOff + 6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[zzOff + 3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[xOff + 4];
+            ulong zz_7 = zz[zzOff + 7];
+            ulong zz_8 = zz[zzOff + 8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[zzOff + 4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[xOff + 5];
+            ulong zz_9 = zz[zzOff + 9];
+            ulong zz_10 = zz[zzOff + 10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[zzOff + 5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_6 &= M;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_8 &= M;
+                zz_10 += zz_9 >> 32;
+                zz_9 &= M;
+            }
+
+            ulong x_6 = x[xOff + 6];
+            ulong zz_11 = zz[zzOff + 11];
+            ulong zz_12 = zz[zzOff + 12];
+            {
+                zz_6 += x_6 * x_0;
+                w = (uint)zz_6;
+                zz[zzOff + 6] = (w << 1) | c;
+                c = w >> 31;
+                zz_7 += (zz_6 >> 32) + x_6 * x_1;
+                zz_8 += (zz_7 >> 32) + x_6 * x_2;
+                zz_9 += (zz_8 >> 32) + x_6 * x_3;
+                zz_10 += (zz_9 >> 32) + x_6 * x_4;
+                zz_11 += (zz_10 >> 32) + x_6 * x_5;
+                zz_12 += zz_11 >> 32;
+            }
+
+            w = (uint)zz_7;
+            zz[zzOff + 7] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_8;
+            zz[zzOff + 8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[zzOff + 9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[zzOff + 10] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_11;
+            zz[zzOff + 11] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_12;
+            zz[zzOff + 12] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[zzOff + 13] + (uint)(zz_12 >> 32);
+            zz[zzOff + 13] = (w << 1) | c;
+        }
+
+        public static int Sub(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)x[6] - y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)x[xOff + 0] - y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 1] - y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 2] - y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 3] - y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 4] - y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 5] - y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 6] - y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubBothFrom(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)z[6] - x[6] - y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)z[6] - x[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)z[zOff + 0] - x[xOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 1] - x[xOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 2] - x[xOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 3] - x[xOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 4] - x[xOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 5] - x[xOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 6] - x[xOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static BigInteger ToBigInteger(uint[] x)
+        {
+            byte[] bs = new byte[28];
+            for (int i = 0; i < 7; ++i)
+            {
+                uint x_i = x[i];
+                if (x_i != 0)
+                {
+                    Pack.UInt32_To_BE(x_i, bs, (6 - i) << 2);
+                }
+            }
+            return new BigInteger(1, bs);
+        }
+
+        public static void Zero(uint[] z)
+        {
+            z[0] = 0;
+            z[1] = 0;
+            z[2] = 0;
+            z[3] = 0;
+            z[4] = 0;
+            z[5] = 0;
+            z[6] = 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat256.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat256.cs
new file mode 100644
index 0000000..bd2d6da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat256.cs
@@ -0,0 +1,1300 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Crypto.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal abstract class Nat256
+    {
+        private const ulong M = 0xFFFFFFFFUL;
+
+        public static uint Add(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[7] + y[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint Add(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            c += (ulong)x[xOff + 0] + y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 7] + y[yOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(uint[] x, uint[] y, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + y[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + y[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + y[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + y[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + y[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + y[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + y[6] + z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[7] + y[7] + z[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddBothTo(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0;
+            c += (ulong)x[xOff + 0] + y[yOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + y[yOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + y[yOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + y[yOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + y[yOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + y[yOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + y[yOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 7] + y[yOff + 7] + z[zOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, uint[] z)
+        {
+            ulong c = 0;
+            c += (ulong)x[0] + z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[1] + z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[2] + z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[3] + z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[4] + z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[5] + z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[6] + z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[7] + z[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddTo(uint[] x, int xOff, uint[] z, int zOff, uint cIn)
+        {
+            ulong c = cIn;
+            c += (ulong)x[xOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += (ulong)x[xOff + 7] + z[zOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint AddToEachOther(uint[] u, int uOff, uint[] v, int vOff)
+        {
+            ulong c = 0;
+            c += (ulong)u[uOff + 0] + v[vOff + 0];
+            u[uOff + 0] = (uint)c;
+            v[vOff + 0] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 1] + v[vOff + 1];
+            u[uOff + 1] = (uint)c;
+            v[vOff + 1] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 2] + v[vOff + 2];
+            u[uOff + 2] = (uint)c;
+            v[vOff + 2] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 3] + v[vOff + 3];
+            u[uOff + 3] = (uint)c;
+            v[vOff + 3] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 4] + v[vOff + 4];
+            u[uOff + 4] = (uint)c;
+            v[vOff + 4] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 5] + v[vOff + 5];
+            u[uOff + 5] = (uint)c;
+            v[vOff + 5] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 6] + v[vOff + 6];
+            u[uOff + 6] = (uint)c;
+            v[vOff + 6] = (uint)c;
+            c >>= 32;
+            c += (ulong)u[uOff + 7] + v[vOff + 7];
+            u[uOff + 7] = (uint)c;
+            v[vOff + 7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static void Copy(uint[] x, uint[] z)
+        {
+            z[0] = x[0];
+            z[1] = x[1];
+            z[2] = x[2];
+            z[3] = x[3];
+            z[4] = x[4];
+            z[5] = x[5];
+            z[6] = x[6];
+            z[7] = x[7];
+        }
+
+        public static uint[] Create()
+        {
+            return new uint[8];
+        }
+
+        public static uint[] CreateExt()
+        {
+            return new uint[16];
+        }
+
+        public static bool Diff(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            bool pos = Gte(x, xOff, y, yOff);
+            if (pos)
+            {
+                Sub(x, xOff, y, yOff, z, zOff);
+            }
+            else
+            {
+                Sub(y, yOff, x, xOff, z, zOff);
+            }
+            return pos;
+        }
+
+        public static bool Eq(uint[] x, uint[] y)
+        {
+            for (int i = 7; i >= 0; --i)
+            {
+                if (x[i] != y[i])
+                    return false;
+            }
+            return true;
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            if (x.SignValue < 0 || x.BitLength > 256)
+                throw new ArgumentException();
+
+            uint[] z = Create();
+            int i = 0;
+            while (x.SignValue != 0)
+            {
+                z[i++] = (uint)x.IntValue;
+                x = x.ShiftRight(32);
+            }
+            return z;
+        }
+
+        public static uint GetBit(uint[] x, int bit)
+        {
+            if (bit == 0)
+            {
+                return x[0] & 1;
+            }
+            if ((bit & 255) != bit)
+            {
+                return 0;
+            }
+            int w = bit >> 5;
+            int b = bit & 31;
+            return (x[w] >> b) & 1;
+        }
+
+        public static bool Gte(uint[] x, uint[] y)
+        {
+            for (int i = 7; i >= 0; --i)
+            {
+                uint x_i = x[i], y_i = y[i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool Gte(uint[] x, int xOff, uint[] y, int yOff)
+        {
+            for (int i = 7; i >= 0; --i)
+            {
+                uint x_i = x[xOff + i], y_i = y[yOff + i];
+                if (x_i < y_i)
+                    return false;
+                if (x_i > y_i)
+                    return true;
+            }
+            return true;
+        }
+
+        public static bool IsOne(uint[] x)
+        {
+            if (x[0] != 1)
+            {
+                return false;
+            }
+            for (int i = 1; i < 8; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static bool IsZero(uint[] x)
+        {
+            for (int i = 0; i < 8; ++i)
+            {
+                if (x[i] != 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        public static void Mul(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+            ulong y_6 = y[6];
+            ulong y_7 = y[7];
+
+            {
+                ulong c = 0, x_0 = x[0];
+                c += x_0 * y_0;
+                zz[0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[5] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_6;
+                zz[6] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_7;
+                zz[7] = (uint)c;
+                c >>= 32;
+                zz[8] = (uint)c;
+            }
+
+            for (int i = 1; i < 8; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[i + 6];
+                zz[i + 6] = (uint)c;
+                c >>= 32;
+                c += x_i * y_7 + zz[i + 7];
+                zz[i + 7] = (uint)c;
+                c >>= 32;
+                zz[i + 8] = (uint)c;
+            }
+        }
+
+        public static void Mul(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+            ulong y_6 = y[yOff + 6];
+            ulong y_7 = y[yOff + 7];
+
+            {
+                ulong c = 0, x_0 = x[xOff + 0];
+                c += x_0 * y_0;
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_1;
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_2;
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_3;
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_4;
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_5;
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_6;
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                c += x_0 * y_7;
+                zz[zzOff + 7] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 8] = (uint)c;
+            }
+
+            for (int i = 1; i < 8; ++i)
+            {
+                ++zzOff;
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                c += x_i * y_7 + zz[zzOff + 7];
+                zz[zzOff + 7] = (uint)c;
+                c >>= 32;
+                zz[zzOff + 8] = (uint)c;
+            }
+        }
+
+        public static uint MulAddTo(uint[] x, uint[] y, uint[] zz)
+        {
+            ulong y_0 = y[0];
+            ulong y_1 = y[1];
+            ulong y_2 = y[2];
+            ulong y_3 = y[3];
+            ulong y_4 = y[4];
+            ulong y_5 = y[5];
+            ulong y_6 = y[6];
+            ulong y_7 = y[7];
+
+            ulong zc = 0;
+            for (int i = 0; i < 8; ++i)
+            {
+                ulong c = 0, x_i = x[i];
+                c += x_i * y_0 + zz[i + 0];
+                zz[i + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[i + 1];
+                zz[i + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[i + 2];
+                zz[i + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[i + 3];
+                zz[i + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[i + 4];
+                zz[i + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[i + 5];
+                zz[i + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[i + 6];
+                zz[i + 6] = (uint)c;
+                c >>= 32;
+                c += x_i * y_7 + zz[i + 7];
+                zz[i + 7] = (uint)c;
+                c >>= 32;
+                c += zc + zz[i + 8];
+                zz[i + 8] = (uint)c;
+                zc = c >> 32;
+            }
+            return (uint)zc;
+        }
+
+        public static uint MulAddTo(uint[] x, int xOff, uint[] y, int yOff, uint[] zz, int zzOff)
+        {
+            ulong y_0 = y[yOff + 0];
+            ulong y_1 = y[yOff + 1];
+            ulong y_2 = y[yOff + 2];
+            ulong y_3 = y[yOff + 3];
+            ulong y_4 = y[yOff + 4];
+            ulong y_5 = y[yOff + 5];
+            ulong y_6 = y[yOff + 6];
+            ulong y_7 = y[yOff + 7];
+
+            ulong zc = 0;
+            for (int i = 0; i < 8; ++i)
+            {
+                ulong c = 0, x_i = x[xOff + i];
+                c += x_i * y_0 + zz[zzOff + 0];
+                zz[zzOff + 0] = (uint)c;
+                c >>= 32;
+                c += x_i * y_1 + zz[zzOff + 1];
+                zz[zzOff + 1] = (uint)c;
+                c >>= 32;
+                c += x_i * y_2 + zz[zzOff + 2];
+                zz[zzOff + 2] = (uint)c;
+                c >>= 32;
+                c += x_i * y_3 + zz[zzOff + 3];
+                zz[zzOff + 3] = (uint)c;
+                c >>= 32;
+                c += x_i * y_4 + zz[zzOff + 4];
+                zz[zzOff + 4] = (uint)c;
+                c >>= 32;
+                c += x_i * y_5 + zz[zzOff + 5];
+                zz[zzOff + 5] = (uint)c;
+                c >>= 32;
+                c += x_i * y_6 + zz[zzOff + 6];
+                zz[zzOff + 6] = (uint)c;
+                c >>= 32;
+                c += x_i * y_7 + zz[zzOff + 7];
+                zz[zzOff + 7] = (uint)c;
+                c >>= 32;
+                c += zc + zz[zzOff + 8];
+                zz[zzOff + 8] = (uint)c;
+                zc = c >> 32;
+                ++zzOff;
+            }
+            return (uint)zc;
+        }
+
+        public static ulong Mul33Add(uint w, uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            Debug.Assert(w >> 31 == 0);
+
+            ulong c = 0, wVal = w;
+            ulong x0 = x[xOff + 0];
+            c += wVal * x0 + y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong x1 = x[xOff + 1];
+            c += wVal * x1 + x0 + y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            ulong x2 = x[xOff + 2];
+            c += wVal * x2 + x1 + y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            ulong x3 = x[xOff + 3];
+            c += wVal * x3 + x2 + y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            ulong x4 = x[xOff + 4];
+            c += wVal * x4 + x3 + y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            ulong x5 = x[xOff + 5];
+            c += wVal * x5 + x4 + y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            ulong x6 = x[xOff + 6];
+            c += wVal * x6 + x5 + y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            ulong x7 = x[xOff + 7];
+            c += wVal * x7 + x6 + y[yOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            c += x7;
+            return c;
+        }
+
+        public static uint MulByWord(uint x, uint[] z)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * (ulong)z[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint MulByWordAddTo(uint x, uint[] y, uint[] z)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * (ulong)z[0] + y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[1] + y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[2] + y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[3] + y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[4] + y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[5] + y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[6] + y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += xVal * (ulong)z[7] + y[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint MulWordAddTo(uint x, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = x;
+            c += xVal * y[yOff + 0] + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 1] + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 2] + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 3] + z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 4] + z[zOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 5] + z[zOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 6] + z[zOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += xVal * y[yOff + 7] + z[zOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (uint)c;
+        }
+
+        public static uint Mul33DWordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <= 4);
+            ulong c = 0, xVal = x;
+            ulong y00 = y & M;
+            c += xVal * y00 + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            ulong y01 = y >> 32;
+            c += xVal * y01 + y00 + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += y01 + z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 4);
+        }
+
+        public static uint Mul33WordAdd(uint x, uint y, uint[] z, int zOff)
+        {
+            Debug.Assert(x >> 31 == 0);
+            Debug.Assert(zOff <= 5);
+            ulong c = 0, yVal = y;
+            c += yVal * x + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += yVal + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3);
+        }
+
+        public static uint MulWordDwordAdd(uint x, ulong y, uint[] z, int zOff)
+        {
+            Debug.Assert(zOff <= 5);
+            ulong c = 0, xVal = x;
+            c += xVal * y + z[zOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += xVal * (y >> 32) + z[zOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += z[zOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            return c == 0 ? 0 : Nat.IncAt(8, z, zOff, 3);
+        }
+
+        public static uint MulWord(uint x, uint[] y, uint[] z, int zOff)
+        {
+            ulong c = 0, xVal = x;
+            int i = 0;
+            do
+            {
+                c += xVal * y[i];
+                z[zOff + i] = (uint)c;
+                c >>= 32;
+            }
+            while (++i < 8);
+            return (uint)c;
+        }
+
+        public static void Square(uint[] x, uint[] zz)
+        {
+            ulong x_0 = x[0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 7, j = 16;
+                do
+                {
+                    ulong xVal = x[i--];
+                    ulong p = xVal * xVal;
+                    zz[--j] = (c << 31) | (uint)(p >> 33);
+                    zz[--j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[1];
+            ulong zz_2 = zz[2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[2];
+            ulong zz_3 = zz[3];
+            ulong zz_4 = zz[4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[3];
+            ulong zz_5 = zz[5];
+            ulong zz_6 = zz[6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[4];
+            ulong zz_7 = zz[7];
+            ulong zz_8 = zz[8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[5];
+            ulong zz_9 = zz[9];
+            ulong zz_10 = zz[10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_6 &= M;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_8 &= M;
+                zz_10 += zz_9 >> 32;
+                zz_9 &= M;
+            }
+
+            ulong x_6 = x[6];
+            ulong zz_11 = zz[11];
+            ulong zz_12 = zz[12];
+            {
+                zz_6 += x_6 * x_0;
+                w = (uint)zz_6;
+                zz[6] = (w << 1) | c;
+                c = w >> 31;
+                zz_7 += (zz_6 >> 32) + x_6 * x_1;
+                zz_8 += (zz_7 >> 32) + x_6 * x_2;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_6 * x_3;
+                zz_8 &= M;
+                zz_10 += (zz_9 >> 32) + x_6 * x_4;
+                zz_9 &= M;
+                zz_11 += (zz_10 >> 32) + x_6 * x_5;
+                zz_10 &= M;
+                zz_12 += zz_11 >> 32;
+                zz_11 &= M;
+            }
+
+            ulong x_7 = x[7];
+            ulong zz_13 = zz[13];
+            ulong zz_14 = zz[14];
+            {
+                zz_7 += x_7 * x_0;
+                w = (uint)zz_7;
+                zz[7] = (w << 1) | c;
+                c = w >> 31;
+                zz_8 += (zz_7 >> 32) + x_7 * x_1;
+                zz_9 += (zz_8 >> 32) + x_7 * x_2;
+                zz_10 += (zz_9 >> 32) + x_7 * x_3;
+                zz_11 += (zz_10 >> 32) + x_7 * x_4;
+                zz_12 += (zz_11 >> 32) + x_7 * x_5;
+                zz_13 += (zz_12 >> 32) + x_7 * x_6;
+                zz_14 += zz_13 >> 32;
+            }
+
+            w = (uint)zz_8;
+            zz[8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[10] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_11;
+            zz[11] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_12;
+            zz[12] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_13;
+            zz[13] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_14;
+            zz[14] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[15] + (uint)(zz_14 >> 32);
+            zz[15] = (w << 1) | c;
+        }
+
+        public static void Square(uint[] x, int xOff, uint[] zz, int zzOff)
+        {
+            ulong x_0 = x[xOff + 0];
+            ulong zz_1;
+
+            uint c = 0, w;
+            {
+                int i = 7, j = 16;
+                do
+                {
+                    ulong xVal = x[xOff + i--];
+                    ulong p = xVal * xVal;
+                    zz[zzOff + --j] = (c << 31) | (uint)(p >> 33);
+                    zz[zzOff + --j] = (uint)(p >> 1);
+                    c = (uint)p;
+                }
+                while (i > 0);
+
+                {
+                    ulong p = x_0 * x_0;
+                    zz_1 = (ulong)(c << 31) | (p >> 33);
+                    zz[zzOff + 0] = (uint)p;
+                    c = (uint)(p >> 32) & 1;
+                }
+            }
+
+            ulong x_1 = x[xOff + 1];
+            ulong zz_2 = zz[zzOff + 2];
+
+            {
+                zz_1 += x_1 * x_0;
+                w = (uint)zz_1;
+                zz[zzOff + 1] = (w << 1) | c;
+                c = w >> 31;
+                zz_2 += zz_1 >> 32;
+            }
+
+            ulong x_2 = x[xOff + 2];
+            ulong zz_3 = zz[zzOff + 3];
+            ulong zz_4 = zz[zzOff + 4];
+            {
+                zz_2 += x_2 * x_0;
+                w = (uint)zz_2;
+                zz[zzOff + 2] = (w << 1) | c;
+                c = w >> 31;
+                zz_3 += (zz_2 >> 32) + x_2 * x_1;
+                zz_4 += zz_3 >> 32;
+                zz_3 &= M;
+            }
+
+            ulong x_3 = x[xOff + 3];
+            ulong zz_5 = zz[zzOff + 5];
+            ulong zz_6 = zz[zzOff + 6];
+            {
+                zz_3 += x_3 * x_0;
+                w = (uint)zz_3;
+                zz[zzOff + 3] = (w << 1) | c;
+                c = w >> 31;
+                zz_4 += (zz_3 >> 32) + x_3 * x_1;
+                zz_5 += (zz_4 >> 32) + x_3 * x_2;
+                zz_4 &= M;
+                zz_6 += zz_5 >> 32;
+                zz_5 &= M;
+            }
+
+            ulong x_4 = x[xOff + 4];
+            ulong zz_7 = zz[zzOff + 7];
+            ulong zz_8 = zz[zzOff + 8];
+            {
+                zz_4 += x_4 * x_0;
+                w = (uint)zz_4;
+                zz[zzOff + 4] = (w << 1) | c;
+                c = w >> 31;
+                zz_5 += (zz_4 >> 32) + x_4 * x_1;
+                zz_6 += (zz_5 >> 32) + x_4 * x_2;
+                zz_5 &= M;
+                zz_7 += (zz_6 >> 32) + x_4 * x_3;
+                zz_6 &= M;
+                zz_8 += zz_7 >> 32;
+                zz_7 &= M;
+            }
+
+            ulong x_5 = x[xOff + 5];
+            ulong zz_9 = zz[zzOff + 9];
+            ulong zz_10 = zz[zzOff + 10];
+            {
+                zz_5 += x_5 * x_0;
+                w = (uint)zz_5;
+                zz[zzOff + 5] = (w << 1) | c;
+                c = w >> 31;
+                zz_6 += (zz_5 >> 32) + x_5 * x_1;
+                zz_7 += (zz_6 >> 32) + x_5 * x_2;
+                zz_6 &= M;
+                zz_8 += (zz_7 >> 32) + x_5 * x_3;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_5 * x_4;
+                zz_8 &= M;
+                zz_10 += zz_9 >> 32;
+                zz_9 &= M;
+            }
+
+            ulong x_6 = x[xOff + 6];
+            ulong zz_11 = zz[zzOff + 11];
+            ulong zz_12 = zz[zzOff + 12];
+            {
+                zz_6 += x_6 * x_0;
+                w = (uint)zz_6;
+                zz[zzOff + 6] = (w << 1) | c;
+                c = w >> 31;
+                zz_7 += (zz_6 >> 32) + x_6 * x_1;
+                zz_8 += (zz_7 >> 32) + x_6 * x_2;
+                zz_7 &= M;
+                zz_9 += (zz_8 >> 32) + x_6 * x_3;
+                zz_8 &= M;
+                zz_10 += (zz_9 >> 32) + x_6 * x_4;
+                zz_9 &= M;
+                zz_11 += (zz_10 >> 32) + x_6 * x_5;
+                zz_10 &= M;
+                zz_12 += zz_11 >> 32;
+                zz_11 &= M;
+            }
+
+            ulong x_7 = x[xOff + 7];
+            ulong zz_13 = zz[zzOff + 13];
+            ulong zz_14 = zz[zzOff + 14];
+            {
+                zz_7 += x_7 * x_0;
+                w = (uint)zz_7;
+                zz[zzOff + 7] = (w << 1) | c;
+                c = w >> 31;
+                zz_8 += (zz_7 >> 32) + x_7 * x_1;
+                zz_9 += (zz_8 >> 32) + x_7 * x_2;
+                zz_10 += (zz_9 >> 32) + x_7 * x_3;
+                zz_11 += (zz_10 >> 32) + x_7 * x_4;
+                zz_12 += (zz_11 >> 32) + x_7 * x_5;
+                zz_13 += (zz_12 >> 32) + x_7 * x_6;
+                zz_14 += zz_13 >> 32;
+            }
+
+            w = (uint)zz_8;
+            zz[zzOff + 8] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_9;
+            zz[zzOff + 9] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_10;
+            zz[zzOff + 10] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_11;
+            zz[zzOff + 11] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_12;
+            zz[zzOff + 12] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_13;
+            zz[zzOff + 13] = (w << 1) | c;
+            c = w >> 31;
+            w = (uint)zz_14;
+            zz[zzOff + 14] = (w << 1) | c;
+            c = w >> 31;
+            w = zz[zzOff + 15] + (uint)(zz_14 >> 32);
+            zz[zzOff + 15] = (w << 1) | c;
+        }
+
+        public static int Sub(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)x[6] - y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (long)x[7] - y[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int Sub(uint[] x, int xOff, uint[] y, int yOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)x[xOff + 0] - y[yOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 1] - y[yOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 2] - y[yOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 3] - y[yOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 4] - y[yOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 5] - y[yOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 6] - y[yOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += (long)x[xOff + 7] - y[yOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubBothFrom(uint[] x, uint[] y, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0] - y[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1] - y[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2] - y[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3] - y[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4] - y[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5] - y[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)z[6] - x[6] - y[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (long)z[7] - x[7] - y[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, uint[] z)
+        {
+            long c = 0;
+            c += (long)z[0] - x[0];
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - x[1];
+            z[1] = (uint)c;
+            c >>= 32;
+            c += (long)z[2] - x[2];
+            z[2] = (uint)c;
+            c >>= 32;
+            c += (long)z[3] - x[3];
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - x[4];
+            z[4] = (uint)c;
+            c >>= 32;
+            c += (long)z[5] - x[5];
+            z[5] = (uint)c;
+            c >>= 32;
+            c += (long)z[6] - x[6];
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (long)z[7] - x[7];
+            z[7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static int SubFrom(uint[] x, int xOff, uint[] z, int zOff)
+        {
+            long c = 0;
+            c += (long)z[zOff + 0] - x[xOff + 0];
+            z[zOff + 0] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 1] - x[xOff + 1];
+            z[zOff + 1] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 2] - x[xOff + 2];
+            z[zOff + 2] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 3] - x[xOff + 3];
+            z[zOff + 3] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 4] - x[xOff + 4];
+            z[zOff + 4] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 5] - x[xOff + 5];
+            z[zOff + 5] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 6] - x[xOff + 6];
+            z[zOff + 6] = (uint)c;
+            c >>= 32;
+            c += (long)z[zOff + 7] - x[xOff + 7];
+            z[zOff + 7] = (uint)c;
+            c >>= 32;
+            return (int)c;
+        }
+
+        public static BigInteger ToBigInteger(uint[] x)
+        {
+            byte[] bs = new byte[32];
+            for (int i = 0; i < 8; ++i)
+            {
+                uint x_i = x[i];
+                if (x_i != 0)
+                {
+                    Pack.UInt32_To_BE(x_i, bs, (7 - i) << 2);
+                }
+            }
+            return new BigInteger(1, bs);
+        }
+
+        public static void Zero(uint[] z)
+        {
+            z[0] = 0;
+            z[1] = 0;
+            z[2] = 0;
+            z[3] = 0;
+            z[4] = 0;
+            z[5] = 0;
+            z[6] = 0;
+            z[7] = 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat384.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat384.cs
new file mode 100644
index 0000000..dd93e68
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat384.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal abstract class Nat384
+    {
+        public static void Mul(uint[] x, uint[] y, uint[] zz)
+        {
+            Nat192.Mul(x, y, zz);
+            Nat192.Mul(x, 6, y, 6, zz, 12);
+
+            uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12);
+            uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0);
+            c18 += Nat192.AddTo(zz, 18, zz, 12, c12);
+
+            uint[] dx = Nat192.Create(), dy = Nat192.Create();
+            bool neg = Nat192.Diff(x, 6, x, 0, dx, 0) != Nat192.Diff(y, 6, y, 0, dy, 0);
+
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Mul(dx, dy, tt);
+
+            c18 += neg ? Nat.AddTo(12, tt, 0, zz, 6) : (uint)Nat.SubFrom(12, tt, 0, zz, 6);
+            Nat.AddWordAt(24, c18, zz, 18);
+        }
+
+        public static void Square(uint[] x, uint[] zz)
+        {
+            Nat192.Square(x, zz);
+            Nat192.Square(x, 6, zz, 12);
+
+            uint c18 = Nat192.AddToEachOther(zz, 6, zz, 12);
+            uint c12 = c18 + Nat192.AddTo(zz, 0, zz, 6, 0);
+            c18 += Nat192.AddTo(zz, 18, zz, 12, c12);
+
+            uint[] dx = Nat192.Create();
+            Nat192.Diff(x, 6, x, 0, dx, 0);
+
+            uint[] m = Nat192.CreateExt();
+            Nat192.Square(dx, m);
+
+            c18 += (uint)Nat.SubFrom(12, m, 0, zz, 6);
+            Nat.AddWordAt(24, c18, zz, 18);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat512.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat512.cs
new file mode 100644
index 0000000..46e10f9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/Nat512.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal abstract class Nat512
+    {
+        public static void Mul(uint[] x, uint[] y, uint[] zz)
+        {
+            Nat256.Mul(x, y, zz);
+            Nat256.Mul(x, 8, y, 8, zz, 16);
+
+            uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16);
+            uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0);
+            c24 += Nat256.AddTo(zz, 24, zz, 16, c16);
+
+            uint[] dx = Nat256.Create(), dy = Nat256.Create();
+            bool neg = Nat256.Diff(x, 8, x, 0, dx, 0) != Nat256.Diff(y, 8, y, 0, dy, 0);
+
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Mul(dx, dy, tt);
+
+            c24 += neg ? Nat.AddTo(16, tt, 0, zz, 8) : (uint)Nat.SubFrom(16, tt, 0, zz, 8);
+            Nat.AddWordAt(32, c24, zz, 24); 
+        }
+
+        public static void Square(uint[] x, uint[] zz)
+        {
+            Nat256.Square(x, zz);
+            Nat256.Square(x, 8, zz, 16);
+
+            uint c24 = Nat256.AddToEachOther(zz, 8, zz, 16);
+            uint c16 = c24 + Nat256.AddTo(zz, 0, zz, 8, 0);
+            c24 += Nat256.AddTo(zz, 24, zz, 16, c16);
+
+            uint[] dx = Nat256.Create();
+            Nat256.Diff(x, 8, x, 0, dx, 0);
+
+            uint[] m = Nat256.CreateExt();
+            Nat256.Square(dx, m);
+
+            c24 += (uint)Nat.SubFrom(16, m, 0, zz, 8);
+            Nat.AddWordAt(32, c24, zz, 24); 
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Curve.cs
new file mode 100644
index 0000000..81f7719
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Curve.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192K1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37"));
+
+        private const int SECP192K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP192K1Point m_infinity;
+
+        public SecP192K1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP192K1Point(this, null, null);
+
+            this.m_a = FromBigInteger(BigInteger.Zero);
+            this.m_b = FromBigInteger(BigInteger.ValueOf(3));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SECP192K1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP192K1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_JACOBIAN:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP192K1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP192K1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP192K1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Field.cs
new file mode 100644
index 0000000..d5ca903
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Field.cs
@@ -0,0 +1,176 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192K1Field
+    {
+        // 2^192 - 2^32 - 2^12 - 2^8 - 2^7 - 2^6 - 2^3 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFEE37, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x013C4FD1, 0x00002392, 0x00000001, 0x00000000, 0x00000000,
+            0x00000000, 0xFFFFDC6E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFEC3B02F, 0xFFFFDC6D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0x00002391, 0x00000002 };
+        private const uint P5 = 0xFFFFFFFF;
+        private const uint PExt11 = 0xFFFFFFFF;
+        private const uint PInv33 = 0x11C9;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat192.Add(x, y, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                Nat.Add33To(6, PInv33, z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(12, xx, yy, zz);
+            if (c != 0 || (zz[11] == PExt11 && Nat.Gte(12, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(6, x, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                Nat.Add33To(6, PInv33, z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat192.FromBigInteger(x);
+            if (z[5] == P5 && Nat192.Gte(z, P))
+            {
+                Nat192.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(6, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat192.Add(x, P, z);
+                Nat.ShiftDownBit(6, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat192.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[11] == PExt11 && Nat.Gte(12, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat192.IsZero(x))
+            {
+                Nat192.Zero(z);
+            }
+            else
+            {
+                Nat192.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            ulong cc = Nat192.Mul33Add(PInv33, xx, 6, xx, 0, z, 0);
+            uint c = Nat192.Mul33DWordAdd(PInv33, cc, z, 0);
+
+            Debug.Assert(c == 0 || c == 1);
+
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                Nat.Add33To(6, PInv33, z);
+            }
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            if ((x != 0 && Nat192.Mul33WordAdd(PInv33, x, z, 0) != 0)
+                || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                Nat.Add33To(6, PInv33, z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat192.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat192.Sub(x, y, z);
+            if (c != 0)
+            {
+                Nat.Sub33From(6, PInv33, z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(12, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(6, x, 0, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                Nat.Add33To(6, PInv33, z);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1FieldElement.cs
new file mode 100644
index 0000000..78886dd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1FieldElement.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192K1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP192K1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP192K1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP192K1FieldElement", "x");
+
+            this.x = SecP192K1Field.FromBigInteger(x);
+        }
+
+        public SecP192K1FieldElement()
+        {
+            this.x = Nat192.Create();
+        }
+
+        protected internal SecP192K1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat192.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat192.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat192.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat192.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP192K1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.Add(x, ((SecP192K1FieldElement)b).x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.AddOne(x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.Subtract(x, ((SecP192K1FieldElement)b).x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.Multiply(x, ((SecP192K1FieldElement)b).x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat192.Create();
+            Mod.Invert(SecP192K1Field.P, ((SecP192K1FieldElement)b).x, z);
+            SecP192K1Field.Multiply(z, x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.Negate(x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat192.Create();
+            SecP192K1Field.Square(x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP192K1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat192.Create();
+            Mod.Invert(SecP192K1Field.P, x, z);
+            return new SecP192K1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            /*
+             * Raise this element to the exponent 2^190 - 2^30 - 2^10 - 2^6 - 2^5 - 2^4 - 2^1
+             * 
+             * Breaking up the exponent's binary representation into "repunits", we get:
+             * { 159 1s } { 1 0s } { 19 1s } { 1 0s } { 3 1s } { 3 0s} { 3 1s } { 1 0s }
+             * 
+             * Therefore we need an addition chain containing 3, 19, 159 (the lengths of the repunits)
+             * We use: 1, 2, [3], 6, 8, 16, [19], 35, 70, 140, [159]
+             */
+
+            uint[] x1 = this.x;
+            if (Nat192.IsZero(x1) || Nat192.IsOne(x1))
+                return this;
+
+            uint[] x2 = Nat192.Create();
+            SecP192K1Field.Square(x1, x2);
+            SecP192K1Field.Multiply(x2, x1, x2);
+            uint[] x3 = Nat192.Create();
+            SecP192K1Field.Square(x2, x3);
+            SecP192K1Field.Multiply(x3, x1, x3);
+            uint[] x6 = Nat192.Create();
+            SecP192K1Field.SquareN(x3, 3, x6);
+            SecP192K1Field.Multiply(x6, x3, x6);
+            uint[] x8 = x6;
+            SecP192K1Field.SquareN(x6, 2, x8);
+            SecP192K1Field.Multiply(x8, x2, x8);
+            uint[] x16 = x2;
+            SecP192K1Field.SquareN(x8, 8, x16);
+            SecP192K1Field.Multiply(x16, x8, x16);
+            uint[] x19 = x8;
+            SecP192K1Field.SquareN(x16, 3, x19);
+            SecP192K1Field.Multiply(x19, x3, x19);
+            uint[] x35 = Nat192.Create();
+            SecP192K1Field.SquareN(x19, 16, x35);
+            SecP192K1Field.Multiply(x35, x16, x35);
+            uint[] x70 = x16;
+            SecP192K1Field.SquareN(x35, 35, x70);
+            SecP192K1Field.Multiply(x70, x35, x70);
+            uint[] x140 = x35;
+            SecP192K1Field.SquareN(x70, 70, x140);
+            SecP192K1Field.Multiply(x140, x70, x140);
+            uint[] x159 = x70;
+            SecP192K1Field.SquareN(x140, 19, x159);
+            SecP192K1Field.Multiply(x159, x19, x159);
+
+            uint[] t1 = x159;
+            SecP192K1Field.SquareN(t1, 20, t1);
+            SecP192K1Field.Multiply(t1, x19, t1);
+            SecP192K1Field.SquareN(t1, 4, t1);
+            SecP192K1Field.Multiply(t1, x3, t1);
+            SecP192K1Field.SquareN(t1, 6, t1);
+            SecP192K1Field.Multiply(t1, x3, t1);
+            SecP192K1Field.Square(t1, t1);
+
+            uint[] t2 = x3;
+            SecP192K1Field.Square(t1, t2);
+
+            return Nat192.Eq(x1, t2) ? new SecP192K1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP192K1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP192K1FieldElement);
+        }
+
+        public virtual bool Equals(SecP192K1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat192.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 6);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Point.cs
new file mode 100644
index 0000000..648aca5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192K1Point.cs
@@ -0,0 +1,265 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192K1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP192K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+            bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP192K1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.RawXCoord, Y1 = (SecP192K1FieldElement)this.RawYCoord;
+            SecP192K1FieldElement X2 = (SecP192K1FieldElement)b.RawXCoord, Y2 = (SecP192K1FieldElement)b.RawYCoord;
+
+            SecP192K1FieldElement Z1 = (SecP192K1FieldElement)this.RawZCoords[0];
+            SecP192K1FieldElement Z2 = (SecP192K1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat192.CreateExt();
+            uint[] t2 = Nat192.Create();
+            uint[] t3 = Nat192.Create();
+            uint[] t4 = Nat192.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP192K1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP192K1Field.Multiply(S2, X2.x, U2);
+
+                SecP192K1Field.Multiply(S2, Z1.x, S2);
+                SecP192K1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP192K1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP192K1Field.Multiply(S1, X1.x, U1);
+
+                SecP192K1Field.Multiply(S1, Z2.x, S1);
+                SecP192K1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat192.Create();
+            SecP192K1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP192K1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat192.IsZero(H))
+            {
+                if (Nat192.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP192K1Field.Square(H, HSquared);
+
+            uint[] G = Nat192.Create();
+            SecP192K1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP192K1Field.Multiply(HSquared, U1, V);
+
+            SecP192K1Field.Negate(G, G);
+            Nat192.Mul(S1, G, tt1);
+
+            c = Nat192.AddBothTo(V, V, G);
+            SecP192K1Field.Reduce32(c, G);
+
+            SecP192K1FieldElement X3 = new SecP192K1FieldElement(t4);
+            SecP192K1Field.Square(R, X3.x);
+            SecP192K1Field.Subtract(X3.x, G, X3.x);
+
+            SecP192K1FieldElement Y3 = new SecP192K1FieldElement(G);
+            SecP192K1Field.Subtract(V, X3.x, Y3.x);
+            SecP192K1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP192K1Field.Reduce(tt1, Y3.x);
+
+            SecP192K1FieldElement Z3 = new SecP192K1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP192K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP192K1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP192K1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP192K1FieldElement Y1 = (SecP192K1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP192K1FieldElement X1 = (SecP192K1FieldElement)this.RawXCoord, Z1 = (SecP192K1FieldElement)this.RawZCoords[0];
+
+            uint c;
+
+            uint[] Y1Squared = Nat192.Create();
+            SecP192K1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat192.Create();
+            SecP192K1Field.Square(Y1Squared, T);
+
+            uint[] M = Nat192.Create();
+            SecP192K1Field.Square(X1.x, M);
+            c = Nat192.AddBothTo(M, M, M);
+            SecP192K1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP192K1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(6, S, 2, 0);
+            SecP192K1Field.Reduce32(c, S);
+
+            uint[] t1 = Nat192.Create();
+            c = Nat.ShiftUpBits(6, T, 3, 0, t1);
+            SecP192K1Field.Reduce32(c, t1);
+
+            SecP192K1FieldElement X3 = new SecP192K1FieldElement(T);
+            SecP192K1Field.Square(M, X3.x);
+            SecP192K1Field.Subtract(X3.x, S, X3.x);
+            SecP192K1Field.Subtract(X3.x, S, X3.x);
+
+            SecP192K1FieldElement Y3 = new SecP192K1FieldElement(S);
+            SecP192K1Field.Subtract(S, X3.x, Y3.x);
+            SecP192K1Field.Multiply(Y3.x, M, Y3.x);
+            SecP192K1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP192K1FieldElement Z3 = new SecP192K1FieldElement(M);
+            SecP192K1Field.Twice(Y1.x, Z3.x);
+            if (!Z1.IsOne)
+            {
+                SecP192K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP192K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP192K1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Curve.cs
new file mode 100644
index 0000000..cb3a981
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Curve.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192R1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"));
+
+        private const int SecP192R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP192R1Point m_infinity;
+
+        public SecP192R1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP192R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1")));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831"));
+            this.m_cofactor = BigInteger.One;
+
+            this.m_coord = SecP192R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP192R1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+            case COORD_JACOBIAN:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP192R1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP192R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP192R1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Field.cs
new file mode 100644
index 0000000..85e3a03
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Field.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192R1Field
+    {
+        // 2^192 - 2^64 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001,
+            0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFE,
+            0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000002 };
+        private const uint P5 = 0xFFFFFFFF;
+        private const uint PExt11 = 0xFFFFFFFF;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat192.Add(x, y, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(12, xx, yy, zz);
+            if (c != 0 || (zz[11] == PExt11 && Nat.Gte(12, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(6, x, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat192.FromBigInteger(x);
+            if (z[5] == P5 && Nat192.Gte(z, P))
+            {
+                Nat192.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(6, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat192.Add(x, P, z);
+                Nat.ShiftDownBit(6, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat192.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[11] == PExt11 && Nat.Gte(12, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat192.IsZero(x))
+            {
+                Nat192.Zero(z);
+            }
+            else
+            {
+                Nat192.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            ulong xx06 = xx[6], xx07 = xx[7], xx08 = xx[8];
+            ulong xx09 = xx[9], xx10 = xx[10], xx11 = xx[11];
+
+            ulong t0 = xx06 + xx10;
+            ulong t1 = xx07 + xx11;
+
+            ulong cc = 0;
+            cc += (ulong)xx[0] + t0;
+            uint z0 = (uint)cc;
+            cc >>= 32;
+            cc += (ulong)xx[1] + t1;
+            z[1] = (uint)cc;
+            cc >>= 32;
+
+            t0 += xx08;
+            t1 += xx09;
+
+            cc += (ulong)xx[2] + t0;
+            ulong z2 = (uint)cc;
+            cc >>= 32;
+            cc += (ulong)xx[3] + t1;
+            z[3] = (uint)cc;
+            cc >>= 32;
+
+            t0 -= xx06;
+            t1 -= xx07;
+
+            cc += (ulong)xx[4] + t0;
+            z[4] = (uint)cc;
+            cc >>= 32;
+            cc += (ulong)xx[5] + t1;
+            z[5] = (uint)cc;
+            cc >>= 32;
+
+            z2 += cc;
+
+            cc += z0;
+            z[0] = (uint)cc;
+            cc >>= 32;
+            if (cc != 0)
+            {
+                cc += z[1];
+                z[1] = (uint)cc;
+                z2 += cc >> 32;
+            }
+            z[2] = (uint)z2;
+            cc  = z2 >> 32;
+
+            Debug.Assert(cc == 0 || cc == 1);
+
+            if ((cc != 0 && Nat.IncAt(6, z, 3) != 0)
+                || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            ulong cc = 0;
+
+            if (x != 0)
+            {
+                cc += (ulong)z[0] + x;
+                z[0] = (uint)cc;
+                cc >>= 32;
+                if (cc != 0)
+                {
+                    cc += (ulong)z[1];
+                    z[1] = (uint)cc;
+                    cc >>= 32;
+                }
+                cc += (ulong)z[2] + x;
+                z[2] = (uint)cc;
+                cc >>= 32;
+
+                Debug.Assert(cc == 0 || cc == 1);
+            }
+
+            if ((cc != 0 && Nat.IncAt(6, z, 3) != 0)
+                || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat192.CreateExt();
+            Nat192.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat192.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat192.Sub(x, y, z);
+            if (c != 0)
+            {
+                SubPInvFrom(z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(12, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(12, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(6, x, 0, z);
+            if (c != 0 || (z[5] == P5 && Nat192.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        private static void AddPInvTo(uint[] z)
+        {
+            long c = (long)z[0] + 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[2] + 1;
+            z[2] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.IncAt(6, z, 3);
+            }
+        }
+
+        private static void SubPInvFrom(uint[] z)
+        {
+            long c = (long)z[0] - 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[2] - 1;
+            z[2] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.DecAt(6, z, 3);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1FieldElement.cs
new file mode 100644
index 0000000..020c5cd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1FieldElement.cs
@@ -0,0 +1,187 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192R1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP192R1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP192R1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP192R1FieldElement", "x");
+
+            this.x = SecP192R1Field.FromBigInteger(x);
+        }
+
+        public SecP192R1FieldElement()
+        {
+            this.x = Nat192.Create();
+        }
+
+        protected internal SecP192R1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat192.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat192.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat192.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat192.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP192R1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.Add(x, ((SecP192R1FieldElement)b).x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.AddOne(x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.Subtract(x, ((SecP192R1FieldElement)b).x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.Multiply(x, ((SecP192R1FieldElement)b).x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat192.Create();
+            Mod.Invert(SecP192R1Field.P, ((SecP192R1FieldElement)b).x, z);
+            SecP192R1Field.Multiply(z, x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.Negate(x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat192.Create();
+            SecP192R1Field.Square(x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP192R1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat192.Create();
+            Mod.Invert(SecP192R1Field.P, x, z);
+            return new SecP192R1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            // Raise this element to the exponent 2^190 - 2^62
+
+            uint[] x1 = this.x;
+            if (Nat192.IsZero(x1) || Nat192.IsOne(x1))
+                return this;
+
+            uint[] t1 = Nat192.Create();
+            uint[] t2 = Nat192.Create();
+
+            SecP192R1Field.Square(x1, t1);
+            SecP192R1Field.Multiply(t1, x1, t1);
+
+            SecP192R1Field.SquareN(t1, 2, t2);
+            SecP192R1Field.Multiply(t2, t1, t2);
+
+            SecP192R1Field.SquareN(t2, 4, t1);
+            SecP192R1Field.Multiply(t1, t2, t1);
+
+            SecP192R1Field.SquareN(t1, 8, t2);
+            SecP192R1Field.Multiply(t2, t1, t2);
+
+            SecP192R1Field.SquareN(t2, 16, t1);
+            SecP192R1Field.Multiply(t1, t2, t1);
+
+            SecP192R1Field.SquareN(t1, 32, t2);
+            SecP192R1Field.Multiply(t2, t1, t2);
+
+            SecP192R1Field.SquareN(t2, 64, t1);
+            SecP192R1Field.Multiply(t1, t2, t1);
+
+            SecP192R1Field.SquareN(t1, 62, t1);
+            SecP192R1Field.Square(t1, t2);
+
+            return Nat192.Eq(x1, t2) ? new SecP192R1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP192R1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP192R1FieldElement);
+        }
+
+        public virtual bool Equals(SecP192R1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat192.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 6);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Point.cs
new file mode 100644
index 0000000..797a8de
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP192R1Point.cs
@@ -0,0 +1,277 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP192R1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP192R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP192R1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.RawXCoord, Y1 = (SecP192R1FieldElement)this.RawYCoord;
+            SecP192R1FieldElement X2 = (SecP192R1FieldElement)b.RawXCoord, Y2 = (SecP192R1FieldElement)b.RawYCoord;
+
+            SecP192R1FieldElement Z1 = (SecP192R1FieldElement)this.RawZCoords[0];
+            SecP192R1FieldElement Z2 = (SecP192R1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat192.CreateExt();
+            uint[] t2 = Nat192.Create();
+            uint[] t3 = Nat192.Create();
+            uint[] t4 = Nat192.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP192R1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP192R1Field.Multiply(S2, X2.x, U2);
+
+                SecP192R1Field.Multiply(S2, Z1.x, S2);
+                SecP192R1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP192R1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP192R1Field.Multiply(S1, X1.x, U1);
+
+                SecP192R1Field.Multiply(S1, Z2.x, S1);
+                SecP192R1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat192.Create();
+            SecP192R1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP192R1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat192.IsZero(H))
+            {
+                if (Nat192.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP192R1Field.Square(H, HSquared);
+
+            uint[] G = Nat192.Create();
+            SecP192R1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP192R1Field.Multiply(HSquared, U1, V);
+
+            SecP192R1Field.Negate(G, G);
+            Nat192.Mul(S1, G, tt1);
+
+            c = Nat192.AddBothTo(V, V, G);
+            SecP192R1Field.Reduce32(c, G);
+
+            SecP192R1FieldElement X3 = new SecP192R1FieldElement(t4);
+            SecP192R1Field.Square(R, X3.x);
+            SecP192R1Field.Subtract(X3.x, G, X3.x);
+
+            SecP192R1FieldElement Y3 = new SecP192R1FieldElement(G);
+            SecP192R1Field.Subtract(V, X3.x, Y3.x);
+            SecP192R1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP192R1Field.Reduce(tt1, Y3.x);
+
+            SecP192R1FieldElement Z3 = new SecP192R1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP192R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP192R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP192R1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP192R1FieldElement Y1 = (SecP192R1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP192R1FieldElement X1 = (SecP192R1FieldElement)this.RawXCoord, Z1 = (SecP192R1FieldElement)this.RawZCoords[0];
+
+            uint c;
+            uint[] t1 = Nat192.Create();
+            uint[] t2 = Nat192.Create();
+
+            uint[] Y1Squared = Nat192.Create();
+            SecP192R1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat192.Create();
+            SecP192R1Field.Square(Y1Squared, T);
+
+            bool Z1IsOne = Z1.IsOne;
+
+            uint[] Z1Squared = Z1.x;
+            if (!Z1IsOne)
+            {
+                Z1Squared = t2;
+                SecP192R1Field.Square(Z1.x, Z1Squared);
+            }
+
+            SecP192R1Field.Subtract(X1.x, Z1Squared, t1);
+
+            uint[] M = t2;
+            SecP192R1Field.Add(X1.x, Z1Squared, M);
+            SecP192R1Field.Multiply(M, t1, M);
+            c = Nat192.AddBothTo(M, M, M);
+            SecP192R1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP192R1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(6, S, 2, 0);
+            SecP192R1Field.Reduce32(c, S);
+
+            c = Nat.ShiftUpBits(6, T, 3, 0, t1);
+            SecP192R1Field.Reduce32(c, t1);
+
+            SecP192R1FieldElement X3 = new SecP192R1FieldElement(T);
+            SecP192R1Field.Square(M, X3.x);
+            SecP192R1Field.Subtract(X3.x, S, X3.x);
+            SecP192R1Field.Subtract(X3.x, S, X3.x);
+
+            SecP192R1FieldElement Y3 = new SecP192R1FieldElement(S);
+            SecP192R1Field.Subtract(S, X3.x, Y3.x);
+            SecP192R1Field.Multiply(Y3.x, M, Y3.x);
+            SecP192R1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP192R1FieldElement Z3 = new SecP192R1FieldElement(M);
+            SecP192R1Field.Twice(Y1.x, Z3.x);
+            if (!Z1IsOne)
+            {
+                SecP192R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP192R1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP192R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Curve.cs
new file mode 100644
index 0000000..d4be7d8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Curve.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224K1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D"));
+
+        private const int SECP224K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP224K1Point m_infinity;
+
+        public SecP224K1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP224K1Point(this, null, null);
+
+            this.m_a = FromBigInteger(BigInteger.Zero);
+            this.m_b = FromBigInteger(BigInteger.ValueOf(5));
+            this.m_order = new BigInteger(1, Hex.Decode("010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SECP224K1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP224K1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_JACOBIAN:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP224K1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP224K1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP224K1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Field.cs
new file mode 100644
index 0000000..a55810c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Field.cs
@@ -0,0 +1,177 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224K1Field
+    {
+        // 2^224 - 2^32 - 2^12 - 2^11 - 2^9 - 2^7 - 2^4 - 2 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFE56D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x02C23069, 0x00003526, 0x00000001, 0x00000000, 0x00000000,
+            0x00000000, 0x00000000, 0xFFFFCADA, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFD3DCF97, 0xFFFFCAD9, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF, 0x00003525, 0x00000002 };
+        private const uint P6 = 0xFFFFFFFF;
+        private const uint PExt13 = 0xFFFFFFFF;
+        private const uint PInv33 = 0x1A93;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat224.Add(x, y, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                Nat.Add33To(7, PInv33, z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(14, xx, yy, zz);
+            if (c != 0 || (zz[13] == PExt13 && Nat.Gte(14, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(7, x, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                Nat.Add33To(7, PInv33, z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat224.FromBigInteger(x);
+            if (z[6] == P6 && Nat224.Gte(z, P))
+            {
+                Nat224.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(7, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat224.Add(x, P, z);
+                Nat.ShiftDownBit(7, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat224.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[13] == PExt13 && Nat.Gte(14, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat224.IsZero(x))
+            {
+                Nat224.Zero(z);
+            }
+            else
+            {
+                Nat224.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            ulong cc = Nat224.Mul33Add(PInv33, xx, 7, xx, 0, z, 0);
+            uint c = Nat224.Mul33DWordAdd(PInv33, cc, z, 0);
+
+            Debug.Assert(c == 0 || c == 1);
+
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                Nat.Add33To(7, PInv33, z);
+            }
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            if ((x != 0 && Nat224.Mul33WordAdd(PInv33, x, z, 0) != 0)
+                || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                Nat.Add33To(7, PInv33, z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat224.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat224.Sub(x, y, z);
+            if (c != 0)
+            {
+                Nat.Sub33From(7, PInv33, z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(14, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(7, x, 0, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                Nat.Add33To(7, PInv33, z);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1FieldElement.cs
new file mode 100644
index 0000000..72ff4b0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1FieldElement.cs
@@ -0,0 +1,241 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224K1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP224K1Curve.q;
+
+        // Calculated as BigInteger.Two.ModPow(Q.ShiftRight(2), Q)
+        private static readonly uint[] PRECOMP_POW2 = new uint[]{ 0x33bfd202, 0xdcfad133, 0x2287624a, 0xc3811ba8,
+            0xa85558fc, 0x1eaef5d7, 0x8edf154c };
+
+        protected internal readonly uint[] x;
+
+        public SecP224K1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP224K1FieldElement", "x");
+
+            this.x = SecP224K1Field.FromBigInteger(x);
+        }
+
+        public SecP224K1FieldElement()
+        {
+            this.x = Nat224.Create();
+        }
+
+        protected internal SecP224K1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat224.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat224.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat224.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat224.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP224K1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.Add(x, ((SecP224K1FieldElement)b).x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.AddOne(x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.Subtract(x, ((SecP224K1FieldElement)b).x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.Multiply(x, ((SecP224K1FieldElement)b).x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat224.Create();
+            Mod.Invert(SecP224K1Field.P, ((SecP224K1FieldElement)b).x, z);
+            SecP224K1Field.Multiply(z, x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.Negate(x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat224.Create();
+            SecP224K1Field.Square(x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP224K1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat224.Create();
+            Mod.Invert(SecP224K1Field.P, x, z);
+            return new SecP224K1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            /*
+             * Q == 8m + 5, so we use Pocklington's method for this case.
+             *
+             * First, raise this element to the exponent 2^221 - 2^29 - 2^9 - 2^8 - 2^6 - 2^4 - 2^1 (i.e. m + 1)
+             * 
+             * Breaking up the exponent's binary representation into "repunits", we get:
+             * { 191 1s } { 1 0s } { 19 1s } { 2 0s } { 1 1s } { 1 0s} { 1 1s } { 1 0s} { 3 1s } { 1 0s}
+             * 
+             * Therefore we need an addition chain containing 1, 3, 19, 191 (the lengths of the repunits)
+             * We use: [1], 2, [3], 4, 8, 11, [19], 23, 42, 84, 107, [191]
+             */
+
+            uint[] x1 = this.x;
+            if (Nat224.IsZero(x1) || Nat224.IsOne(x1))
+                return this;
+
+            uint[] x2 = Nat224.Create();
+            SecP224K1Field.Square(x1, x2);
+            SecP224K1Field.Multiply(x2, x1, x2);
+            uint[] x3 = x2;
+            SecP224K1Field.Square(x2, x3);
+            SecP224K1Field.Multiply(x3, x1, x3);
+            uint[] x4 = Nat224.Create();
+            SecP224K1Field.Square(x3, x4);
+            SecP224K1Field.Multiply(x4, x1, x4);
+            uint[] x8 = Nat224.Create();
+            SecP224K1Field.SquareN(x4, 4, x8);
+            SecP224K1Field.Multiply(x8, x4, x8);
+            uint[] x11 = Nat224.Create();
+            SecP224K1Field.SquareN(x8, 3, x11);
+            SecP224K1Field.Multiply(x11, x3, x11);
+            uint[] x19 = x11;
+            SecP224K1Field.SquareN(x11, 8, x19);
+            SecP224K1Field.Multiply(x19, x8, x19);
+            uint[] x23 = x8;
+            SecP224K1Field.SquareN(x19, 4, x23);
+            SecP224K1Field.Multiply(x23, x4, x23);
+            uint[] x42 = x4;
+            SecP224K1Field.SquareN(x23, 19, x42);
+            SecP224K1Field.Multiply(x42, x19, x42);
+            uint[] x84 = Nat224.Create();
+            SecP224K1Field.SquareN(x42, 42, x84);
+            SecP224K1Field.Multiply(x84, x42, x84);
+            uint[] x107 = x42;
+            SecP224K1Field.SquareN(x84, 23, x107);
+            SecP224K1Field.Multiply(x107, x23, x107);
+            uint[] x191 = x23;
+            SecP224K1Field.SquareN(x107, 84, x191);
+            SecP224K1Field.Multiply(x191, x84, x191);
+
+            uint[] t1 = x191;
+            SecP224K1Field.SquareN(t1, 20, t1);
+            SecP224K1Field.Multiply(t1, x19, t1);
+            SecP224K1Field.SquareN(t1, 3, t1);
+            SecP224K1Field.Multiply(t1, x1, t1);
+            SecP224K1Field.SquareN(t1, 2, t1);
+            SecP224K1Field.Multiply(t1, x1, t1);
+            SecP224K1Field.SquareN(t1, 4, t1);
+            SecP224K1Field.Multiply(t1, x3, t1);
+            SecP224K1Field.Square(t1, t1);
+
+            uint[] t2 = x84;
+            SecP224K1Field.Square(t1, t2);
+
+            if (Nat224.Eq(x1, t2))
+            {
+                return new SecP224K1FieldElement(t1);
+            }
+
+            /*
+             * If the first guess is incorrect, we multiply by a precomputed power of 2 to get the second guess,
+             * which is ((4x)^(m + 1))/2 mod Q
+             */
+            SecP224K1Field.Multiply(t1, PRECOMP_POW2, t1);
+
+            SecP224K1Field.Square(t1, t2);
+
+            if (Nat224.Eq(x1, t2))
+            {
+                return new SecP224K1FieldElement(t1);
+            }
+
+            return null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP224K1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP224K1FieldElement);
+        }
+
+        public virtual bool Equals(SecP224K1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat224.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 7);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Point.cs
new file mode 100644
index 0000000..8cbd296
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224K1Point.cs
@@ -0,0 +1,265 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224K1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP224K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+            bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP224K1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.RawXCoord, Y1 = (SecP224K1FieldElement)this.RawYCoord;
+            SecP224K1FieldElement X2 = (SecP224K1FieldElement)b.RawXCoord, Y2 = (SecP224K1FieldElement)b.RawYCoord;
+
+            SecP224K1FieldElement Z1 = (SecP224K1FieldElement)this.RawZCoords[0];
+            SecP224K1FieldElement Z2 = (SecP224K1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat224.CreateExt();
+            uint[] t2 = Nat224.Create();
+            uint[] t3 = Nat224.Create();
+            uint[] t4 = Nat224.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP224K1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP224K1Field.Multiply(S2, X2.x, U2);
+
+                SecP224K1Field.Multiply(S2, Z1.x, S2);
+                SecP224K1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP224K1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP224K1Field.Multiply(S1, X1.x, U1);
+
+                SecP224K1Field.Multiply(S1, Z2.x, S1);
+                SecP224K1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat224.Create();
+            SecP224K1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP224K1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat224.IsZero(H))
+            {
+                if (Nat224.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP224K1Field.Square(H, HSquared);
+
+            uint[] G = Nat224.Create();
+            SecP224K1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP224K1Field.Multiply(HSquared, U1, V);
+
+            SecP224K1Field.Negate(G, G);
+            Nat224.Mul(S1, G, tt1);
+
+            c = Nat224.AddBothTo(V, V, G);
+            SecP224K1Field.Reduce32(c, G);
+
+            SecP224K1FieldElement X3 = new SecP224K1FieldElement(t4);
+            SecP224K1Field.Square(R, X3.x);
+            SecP224K1Field.Subtract(X3.x, G, X3.x);
+
+            SecP224K1FieldElement Y3 = new SecP224K1FieldElement(G);
+            SecP224K1Field.Subtract(V, X3.x, Y3.x);
+            SecP224K1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP224K1Field.Reduce(tt1, Y3.x);
+
+            SecP224K1FieldElement Z3 = new SecP224K1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP224K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP224K1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP224K1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP224K1FieldElement Y1 = (SecP224K1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP224K1FieldElement X1 = (SecP224K1FieldElement)this.RawXCoord, Z1 = (SecP224K1FieldElement)this.RawZCoords[0];
+
+            uint c;
+
+            uint[] Y1Squared = Nat224.Create();
+            SecP224K1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat224.Create();
+            SecP224K1Field.Square(Y1Squared, T);
+
+            uint[] M = Nat224.Create();
+            SecP224K1Field.Square(X1.x, M);
+            c = Nat224.AddBothTo(M, M, M);
+            SecP224K1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP224K1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(7, S, 2, 0);
+            SecP224K1Field.Reduce32(c, S);
+
+            uint[] t1 = Nat224.Create();
+            c = Nat.ShiftUpBits(7, T, 3, 0, t1);
+            SecP224K1Field.Reduce32(c, t1);
+
+            SecP224K1FieldElement X3 = new SecP224K1FieldElement(T);
+            SecP224K1Field.Square(M, X3.x);
+            SecP224K1Field.Subtract(X3.x, S, X3.x);
+            SecP224K1Field.Subtract(X3.x, S, X3.x);
+
+            SecP224K1FieldElement Y3 = new SecP224K1FieldElement(S);
+            SecP224K1Field.Subtract(S, X3.x, Y3.x);
+            SecP224K1Field.Multiply(Y3.x, M, Y3.x);
+            SecP224K1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP224K1FieldElement Z3 = new SecP224K1FieldElement(M);
+            SecP224K1Field.Twice(Y1.x, Z3.x);
+            if (!Z1.IsOne)
+            {
+                SecP224K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP224K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP224K1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Curve.cs
new file mode 100644
index 0000000..cda8781
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Curve.cs
@@ -0,0 +1,78 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224R1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"));
+
+        private const int SecP224R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP224R1Point m_infinity;
+
+        public SecP224R1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP224R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4")));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D"));
+            this.m_cofactor = BigInteger.One;
+
+            this.m_coord = SecP224R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP224R1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_JACOBIAN:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP224R1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP224R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP224R1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Field.cs
new file mode 100644
index 0000000..559593c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Field.cs
@@ -0,0 +1,295 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224R1Field
+    {
+        // 2^224 - 2^96 + 1
+        internal static readonly uint[] P = new uint[] { 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+            0xFFFFFFFF, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0x00000000,
+            0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001 };
+        private const uint P6 = 0xFFFFFFFF;
+        private const uint PExt13 = 0xFFFFFFFF;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat224.Add(x, y, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(14, xx, yy, zz);
+            if (c != 0 || (zz[13] == PExt13 && Nat.Gte(14, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(7, x, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat224.FromBigInteger(x);
+            if (z[6] == P6 && Nat224.Gte(z, P))
+            {
+                Nat224.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(7, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat224.Add(x, P, z);
+                Nat.ShiftDownBit(7, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat224.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[13] == PExt13 && Nat.Gte(14, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat224.IsZero(x))
+            {
+                Nat224.Zero(z);
+            }
+            else
+            {
+                Nat224.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            long xx10 = xx[10], xx11 = xx[11], xx12 = xx[12], xx13 = xx[13];
+
+            const long n = 1;
+
+            long t0 = (long)xx[7] + xx11 - n;
+            long t1 = (long)xx[8] + xx12;
+            long t2 = (long)xx[9] + xx13;
+
+            long cc = 0;
+            cc += (long)xx[0] - t0;
+            long z0 = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[1] - t1;
+            z[1] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[2] - t2;
+            z[2] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[3] + t0 - xx10;
+            long z3 = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[4] + t1 - xx11;
+            z[4] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[5] + t2 - xx12;
+            z[5] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[6] + xx10 - xx13;
+            z[6] = (uint)cc;
+            cc >>= 32;
+            cc += n;
+
+            Debug.Assert(cc >= 0);
+
+            z3 += cc;
+
+            z0 -= cc;
+            z[0] = (uint)z0;
+            cc = z0 >> 32;
+            if (cc != 0)
+            {
+                cc += (long)z[1];
+                z[1] = (uint)cc;
+                cc >>= 32;
+                cc += (long)z[2];
+                z[2] = (uint)cc;
+                z3 += cc >> 32;
+            }
+            z[3] = (uint)z3;
+            cc = z3 >> 32;
+
+            Debug.Assert(cc == 0 || cc == 1);
+
+            if ((cc != 0 && Nat.IncAt(7, z, 4) != 0)
+                || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            long cc = 0;
+
+            if (x != 0)
+            {
+                long xx07 = x;
+
+                cc += (long)z[0] - xx07;
+                z[0] = (uint)cc;
+                cc >>= 32;
+                if (cc != 0)
+                {
+                    cc += (long)z[1];
+                    z[1] = (uint)cc;
+                    cc >>= 32;
+                    cc += (long)z[2];
+                    z[2] = (uint)cc;
+                    cc >>= 32;
+                }
+                cc += (long)z[3] + xx07;
+                z[3] = (uint)cc;
+                cc >>= 32;
+
+                Debug.Assert(cc == 0 || cc == 1);
+            }
+
+            if ((cc != 0 && Nat.IncAt(7, z, 4) != 0)
+                || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat224.CreateExt();
+            Nat224.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat224.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat224.Sub(x, y, z);
+            if (c != 0)
+            {
+                SubPInvFrom(z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(14, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(14, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(7, x, 0, z);
+            if (c != 0 || (z[6] == P6 && Nat224.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        private static void AddPInvTo(uint[] z)
+        {
+            long c = (long)z[0] - 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] + 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.IncAt(7, z, 4);
+            }
+        }
+
+        private static void SubPInvFrom(uint[] z)
+        {
+            long c = (long)z[0] + 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] - 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.DecAt(7, z, 4);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1FieldElement.cs
new file mode 100644
index 0000000..06f47cd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1FieldElement.cs
@@ -0,0 +1,268 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224R1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP224R1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP224R1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP224R1FieldElement", "x");
+
+            this.x = SecP224R1Field.FromBigInteger(x);
+        }
+
+        public SecP224R1FieldElement()
+        {
+            this.x = Nat224.Create();
+        }
+
+        protected internal SecP224R1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat224.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat224.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat224.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat224.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP224R1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.Add(x, ((SecP224R1FieldElement)b).x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.AddOne(x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.Subtract(x, ((SecP224R1FieldElement)b).x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.Multiply(x, ((SecP224R1FieldElement)b).x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat224.Create();
+            Mod.Invert(SecP224R1Field.P, ((SecP224R1FieldElement)b).x, z);
+            SecP224R1Field.Multiply(z, x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.Negate(x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat224.Create();
+            SecP224R1Field.Square(x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP224R1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat224.Create();
+            Mod.Invert(SecP224R1Field.P, x, z);
+            return new SecP224R1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            uint[] c = this.x;
+            if (Nat224.IsZero(c) || Nat224.IsOne(c))
+                return this;
+
+            uint[] nc = Nat224.Create();
+            SecP224R1Field.Negate(c, nc);
+
+            uint[] r = Mod.Random(SecP224R1Field.P);
+            uint[] t = Nat224.Create();
+
+            if (!IsSquare(c))
+                return null;
+
+            while (!TrySqrt(nc, r, t))
+            {
+                SecP224R1Field.AddOne(r, r);
+            }
+
+            SecP224R1Field.Square(t, r);
+
+            return Nat224.Eq(c, r) ? new SecP224R1FieldElement(t) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP224R1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP224R1FieldElement);
+        }
+
+        public virtual bool Equals(SecP224R1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat224.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 7);
+        }
+
+        private static bool IsSquare(uint[] x)
+        {
+            uint[] t1 = Nat224.Create();
+            uint[] t2 = Nat224.Create();
+            Nat224.Copy(x, t1);
+
+            for (int i = 0; i < 7; ++i)
+            {
+                Nat224.Copy(t1, t2);
+                SecP224R1Field.SquareN(t1, 1 << i, t1);
+                SecP224R1Field.Multiply(t1, t2, t1);
+            }
+
+            SecP224R1Field.SquareN(t1, 95, t1);
+            return Nat224.IsOne(t1);
+        }
+
+        private static void RM(uint[] nc, uint[] d0, uint[] e0, uint[] d1, uint[] e1, uint[] f1, uint[] t)
+        {
+            SecP224R1Field.Multiply(e1, e0, t);
+            SecP224R1Field.Multiply(t, nc, t);
+            SecP224R1Field.Multiply(d1, d0, f1);
+            SecP224R1Field.Add(f1, t, f1);
+            SecP224R1Field.Multiply(d1, e0, t);
+            Nat224.Copy(f1, d1);
+            SecP224R1Field.Multiply(e1, d0, e1);
+            SecP224R1Field.Add(e1, t, e1);
+            SecP224R1Field.Square(e1, f1);
+            SecP224R1Field.Multiply(f1, nc, f1);
+        }
+
+        private static void RP(uint[] nc, uint[] d1, uint[] e1, uint[] f1, uint[] t)
+        {
+            Nat224.Copy(nc, f1);
+
+            uint[] d0 = Nat224.Create();
+            uint[] e0 = Nat224.Create();
+
+            for (int i = 0; i < 7; ++i)
+            {
+                Nat224.Copy(d1, d0);
+                Nat224.Copy(e1, e0);
+
+                int j = 1 << i;
+                while (--j >= 0)
+                {
+                    RS(d1, e1, f1, t);
+                }
+
+                RM(nc, d0, e0, d1, e1, f1, t);
+            }
+        }
+
+        private static void RS(uint[] d, uint[] e, uint[] f, uint[] t)
+        {
+            SecP224R1Field.Multiply(e, d, e);
+            SecP224R1Field.Twice(e, e);
+            SecP224R1Field.Square(d, t);
+            SecP224R1Field.Add(f, t, d);
+            SecP224R1Field.Multiply(f, t, f);
+            uint c = Nat.ShiftUpBits(7, f, 2, 0);
+            SecP224R1Field.Reduce32(c, f);
+        }
+
+        private static bool TrySqrt(uint[] nc, uint[] r, uint[] t)
+        {
+            uint[] d1 = Nat224.Create();
+            Nat224.Copy(r, d1);
+            uint[] e1 = Nat224.Create();
+            e1[0] = 1;
+            uint[] f1 = Nat224.Create();
+            RP(nc, d1, e1, f1, t);
+
+            uint[] d0 = Nat224.Create();
+            uint[] e0 = Nat224.Create();
+
+            for (int k = 1; k < 96; ++k)
+            {
+                Nat224.Copy(d1, d0);
+                Nat224.Copy(e1, e0);
+
+                RS(d1, e1, f1, t);
+
+                if (Nat224.IsZero(d1))
+                {
+                    Mod.Invert(SecP224R1Field.P, e0, t);
+                    SecP224R1Field.Multiply(t, d0, t);
+                    return true;
+                }
+            }
+
+            return false;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Point.cs
new file mode 100644
index 0000000..c3f4efb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP224R1Point.cs
@@ -0,0 +1,277 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP224R1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP224R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP224R1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.RawXCoord, Y1 = (SecP224R1FieldElement)this.RawYCoord;
+            SecP224R1FieldElement X2 = (SecP224R1FieldElement)b.RawXCoord, Y2 = (SecP224R1FieldElement)b.RawYCoord;
+
+            SecP224R1FieldElement Z1 = (SecP224R1FieldElement)this.RawZCoords[0];
+            SecP224R1FieldElement Z2 = (SecP224R1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat224.CreateExt();
+            uint[] t2 = Nat224.Create();
+            uint[] t3 = Nat224.Create();
+            uint[] t4 = Nat224.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP224R1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP224R1Field.Multiply(S2, X2.x, U2);
+
+                SecP224R1Field.Multiply(S2, Z1.x, S2);
+                SecP224R1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP224R1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP224R1Field.Multiply(S1, X1.x, U1);
+
+                SecP224R1Field.Multiply(S1, Z2.x, S1);
+                SecP224R1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat224.Create();
+            SecP224R1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP224R1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat224.IsZero(H))
+            {
+                if (Nat224.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP224R1Field.Square(H, HSquared);
+
+            uint[] G = Nat224.Create();
+            SecP224R1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP224R1Field.Multiply(HSquared, U1, V);
+
+            SecP224R1Field.Negate(G, G);
+            Nat224.Mul(S1, G, tt1);
+
+            c = Nat224.AddBothTo(V, V, G);
+            SecP224R1Field.Reduce32(c, G);
+
+            SecP224R1FieldElement X3 = new SecP224R1FieldElement(t4);
+            SecP224R1Field.Square(R, X3.x);
+            SecP224R1Field.Subtract(X3.x, G, X3.x);
+
+            SecP224R1FieldElement Y3 = new SecP224R1FieldElement(G);
+            SecP224R1Field.Subtract(V, X3.x, Y3.x);
+            SecP224R1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP224R1Field.Reduce(tt1, Y3.x);
+
+            SecP224R1FieldElement Z3 = new SecP224R1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP224R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP224R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP224R1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP224R1FieldElement Y1 = (SecP224R1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP224R1FieldElement X1 = (SecP224R1FieldElement)this.RawXCoord, Z1 = (SecP224R1FieldElement)this.RawZCoords[0];
+
+            uint c;
+            uint[] t1 = Nat224.Create();
+            uint[] t2 = Nat224.Create();
+
+            uint[] Y1Squared = Nat224.Create();
+            SecP224R1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat224.Create();
+            SecP224R1Field.Square(Y1Squared, T);
+
+            bool Z1IsOne = Z1.IsOne;
+
+            uint[] Z1Squared = Z1.x;
+            if (!Z1IsOne)
+            {
+                Z1Squared = t2;
+                SecP224R1Field.Square(Z1.x, Z1Squared);
+            }
+
+            SecP224R1Field.Subtract(X1.x, Z1Squared, t1);
+
+            uint[] M = t2;
+            SecP224R1Field.Add(X1.x, Z1Squared, M);
+            SecP224R1Field.Multiply(M, t1, M);
+            c = Nat224.AddBothTo(M, M, M);
+            SecP224R1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP224R1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(7, S, 2, 0);
+            SecP224R1Field.Reduce32(c, S);
+
+            c = Nat.ShiftUpBits(7, T, 3, 0, t1);
+            SecP224R1Field.Reduce32(c, t1);
+
+            SecP224R1FieldElement X3 = new SecP224R1FieldElement(T);
+            SecP224R1Field.Square(M, X3.x);
+            SecP224R1Field.Subtract(X3.x, S, X3.x);
+            SecP224R1Field.Subtract(X3.x, S, X3.x);
+
+            SecP224R1FieldElement Y3 = new SecP224R1FieldElement(S);
+            SecP224R1Field.Subtract(S, X3.x, Y3.x);
+            SecP224R1Field.Multiply(Y3.x, M, Y3.x);
+            SecP224R1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP224R1FieldElement Z3 = new SecP224R1FieldElement(M);
+            SecP224R1Field.Twice(Y1.x, Z3.x);
+            if (!Z1IsOne)
+            {
+                SecP224R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP224R1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP224R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Curve.cs
new file mode 100644
index 0000000..59e2cef
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Curve.cs
@@ -0,0 +1,75 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256K1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F"));
+
+        private const int SECP256K1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP256K1Point m_infinity;
+
+        public SecP256K1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP256K1Point(this, null, null);
+
+            this.m_a = FromBigInteger(BigInteger.Zero);
+            this.m_b = FromBigInteger(BigInteger.ValueOf(7));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SECP256K1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP256K1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+            case COORD_JACOBIAN:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP256K1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP256K1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP256K1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Field.cs
new file mode 100644
index 0000000..ba3a070
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Field.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256K1Field
+    {
+        // 2^256 - 2^32 - 2^9 - 2^8 - 2^7 - 2^6 - 2^4 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFC2F, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x000E90A1, 0x000007A2, 0x00000001, 0x00000000, 0x00000000,
+            0x00000000, 0x00000000, 0x00000000, 0xFFFFF85E, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFFF16F5F, 0xFFFFF85D, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x000007A1, 0x00000002 };
+        private const uint P7 = 0xFFFFFFFF;
+        private const uint PExt15 = 0xFFFFFFFF;
+        private const uint PInv33 = 0x3D1;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat256.Add(x, y, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                Nat.Add33To(8, PInv33, z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(16, xx, yy, zz);
+            if (c != 0 || (zz[15] == PExt15 && Nat.Gte(16, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(16, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(8, x, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                Nat.Add33To(8, PInv33, z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat256.FromBigInteger(x);
+            if (z[7] == P7 && Nat256.Gte(z, P))
+            {
+                Nat256.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(8, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat256.Add(x, P, z);
+                Nat.ShiftDownBit(8, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat256.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[15] == PExt15 && Nat.Gte(16, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(16, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat256.IsZero(x))
+            {
+                Nat256.Zero(z);
+            }
+            else
+            {
+                Nat256.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            ulong cc = Nat256.Mul33Add(PInv33, xx, 8, xx, 0, z, 0);
+            uint c = Nat256.Mul33DWordAdd(PInv33, cc, z, 0);
+
+            Debug.Assert(c == 0 || c == 1);
+
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                Nat.Add33To(8, PInv33, z);
+            }
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            if ((x != 0 && Nat256.Mul33WordAdd(PInv33, x, z, 0) != 0)
+                || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                Nat.Add33To(8, PInv33, z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat256.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat256.Sub(x, y, z);
+            if (c != 0)
+            {
+                Nat.Sub33From(8, PInv33, z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(16, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(16, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(8, x, 0, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                Nat.Add33To(8, PInv33, z);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1FieldElement.cs
new file mode 100644
index 0000000..d9a039a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1FieldElement.cs
@@ -0,0 +1,213 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256K1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP256K1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP256K1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP256K1FieldElement", "x");
+
+            this.x = SecP256K1Field.FromBigInteger(x);
+        }
+
+        public SecP256K1FieldElement()
+        {
+            this.x = Nat256.Create();
+        }
+
+        protected internal SecP256K1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat256.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat256.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat256.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat256.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP256K1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.Add(x, ((SecP256K1FieldElement)b).x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.AddOne(x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.Subtract(x, ((SecP256K1FieldElement)b).x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.Multiply(x, ((SecP256K1FieldElement)b).x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat256.Create();
+            Mod.Invert(SecP256K1Field.P, ((SecP256K1FieldElement)b).x, z);
+            SecP256K1Field.Multiply(z, x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.Negate(x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat256.Create();
+            SecP256K1Field.Square(x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP256K1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat256.Create();
+            Mod.Invert(SecP256K1Field.P, x, z);
+            return new SecP256K1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            /*
+             * Raise this element to the exponent 2^254 - 2^30 - 2^7 - 2^6 - 2^5 - 2^4 - 2^2
+             * 
+             * Breaking up the exponent's binary representation into "repunits", we get:
+             * { 223 1s } { 1 0s } { 22 1s } { 4 0s } { 2 1s } { 2 0s}
+             * 
+             * Therefore we need an addition chain containing 2, 22, 223 (the lengths of the repunits)
+             * We use: 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
+             */
+
+            uint[] x1 = this.x;
+            if (Nat256.IsZero(x1) || Nat256.IsOne(x1))
+                return this;
+
+            uint[] x2 = Nat256.Create();
+            SecP256K1Field.Square(x1, x2);
+            SecP256K1Field.Multiply(x2, x1, x2);
+            uint[] x3 = Nat256.Create();
+            SecP256K1Field.Square(x2, x3);
+            SecP256K1Field.Multiply(x3, x1, x3);
+            uint[] x6 = Nat256.Create();
+            SecP256K1Field.SquareN(x3, 3, x6);
+            SecP256K1Field.Multiply(x6, x3, x6);
+            uint[] x9 = x6;
+            SecP256K1Field.SquareN(x6, 3, x9);
+            SecP256K1Field.Multiply(x9, x3, x9);
+            uint[] x11 = x9;
+            SecP256K1Field.SquareN(x9, 2, x11);
+            SecP256K1Field.Multiply(x11, x2, x11);
+            uint[] x22 = Nat256.Create();
+            SecP256K1Field.SquareN(x11, 11, x22);
+            SecP256K1Field.Multiply(x22, x11, x22);
+            uint[] x44 = x11;
+            SecP256K1Field.SquareN(x22, 22, x44);
+            SecP256K1Field.Multiply(x44, x22, x44);
+            uint[] x88 = Nat256.Create();
+            SecP256K1Field.SquareN(x44, 44, x88);
+            SecP256K1Field.Multiply(x88, x44, x88);
+            uint[] x176 = Nat256.Create();
+            SecP256K1Field.SquareN(x88, 88, x176);
+            SecP256K1Field.Multiply(x176, x88, x176);
+            uint[] x220 = x88;
+            SecP256K1Field.SquareN(x176, 44, x220);
+            SecP256K1Field.Multiply(x220, x44, x220);
+            uint[] x223 = x44;
+            SecP256K1Field.SquareN(x220, 3, x223);
+            SecP256K1Field.Multiply(x223, x3, x223);
+
+            uint[] t1 = x223;
+            SecP256K1Field.SquareN(t1, 23, t1);
+            SecP256K1Field.Multiply(t1, x22, t1);
+            SecP256K1Field.SquareN(t1, 6, t1);
+            SecP256K1Field.Multiply(t1, x2, t1);
+            SecP256K1Field.SquareN(t1, 2, t1);
+
+            uint[] t2 = x2;
+            SecP256K1Field.Square(t1, t2);
+
+            return Nat256.Eq(x1, t2) ? new SecP256K1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP256K1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP256K1FieldElement);
+        }
+
+        public virtual bool Equals(SecP256K1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat256.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 8);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Point.cs
new file mode 100644
index 0000000..3165682
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256K1Point.cs
@@ -0,0 +1,265 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256K1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP256K1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs,
+            bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP256K1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.RawXCoord, Y1 = (SecP256K1FieldElement)this.RawYCoord;
+            SecP256K1FieldElement X2 = (SecP256K1FieldElement)b.RawXCoord, Y2 = (SecP256K1FieldElement)b.RawYCoord;
+
+            SecP256K1FieldElement Z1 = (SecP256K1FieldElement)this.RawZCoords[0];
+            SecP256K1FieldElement Z2 = (SecP256K1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat256.CreateExt();
+            uint[] t2 = Nat256.Create();
+            uint[] t3 = Nat256.Create();
+            uint[] t4 = Nat256.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP256K1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP256K1Field.Multiply(S2, X2.x, U2);
+
+                SecP256K1Field.Multiply(S2, Z1.x, S2);
+                SecP256K1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP256K1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP256K1Field.Multiply(S1, X1.x, U1);
+
+                SecP256K1Field.Multiply(S1, Z2.x, S1);
+                SecP256K1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat256.Create();
+            SecP256K1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP256K1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat256.IsZero(H))
+            {
+                if (Nat256.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP256K1Field.Square(H, HSquared);
+
+            uint[] G = Nat256.Create();
+            SecP256K1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP256K1Field.Multiply(HSquared, U1, V);
+
+            SecP256K1Field.Negate(G, G);
+            Nat256.Mul(S1, G, tt1);
+
+            c = Nat256.AddBothTo(V, V, G);
+            SecP256K1Field.Reduce32(c, G);
+
+            SecP256K1FieldElement X3 = new SecP256K1FieldElement(t4);
+            SecP256K1Field.Square(R, X3.x);
+            SecP256K1Field.Subtract(X3.x, G, X3.x);
+
+            SecP256K1FieldElement Y3 = new SecP256K1FieldElement(G);
+            SecP256K1Field.Subtract(V, X3.x, Y3.x);
+            SecP256K1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP256K1Field.Reduce(tt1, Y3.x);
+
+            SecP256K1FieldElement Z3 = new SecP256K1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP256K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP256K1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP256K1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP256K1FieldElement Y1 = (SecP256K1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP256K1FieldElement X1 = (SecP256K1FieldElement)this.RawXCoord, Z1 = (SecP256K1FieldElement)this.RawZCoords[0];
+
+            uint c;
+
+            uint[] Y1Squared = Nat256.Create();
+            SecP256K1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat256.Create();
+            SecP256K1Field.Square(Y1Squared, T);
+
+            uint[] M = Nat256.Create();
+            SecP256K1Field.Square(X1.x, M);
+            c = Nat256.AddBothTo(M, M, M);
+            SecP256K1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP256K1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(8, S, 2, 0);
+            SecP256K1Field.Reduce32(c, S);
+
+            uint[] t1 = Nat256.Create();
+            c = Nat.ShiftUpBits(8, T, 3, 0, t1);
+            SecP256K1Field.Reduce32(c, t1);
+
+            SecP256K1FieldElement X3 = new SecP256K1FieldElement(T);
+            SecP256K1Field.Square(M, X3.x);
+            SecP256K1Field.Subtract(X3.x, S, X3.x);
+            SecP256K1Field.Subtract(X3.x, S, X3.x);
+
+            SecP256K1FieldElement Y3 = new SecP256K1FieldElement(S);
+            SecP256K1Field.Subtract(S, X3.x, Y3.x);
+            SecP256K1Field.Multiply(Y3.x, M, Y3.x);
+            SecP256K1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP256K1FieldElement Z3 = new SecP256K1FieldElement(M);
+            SecP256K1Field.Twice(Y1.x, Z3.x);
+            if (!Z1.IsOne)
+            {
+                SecP256K1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP256K1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP256K1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Curve.cs
new file mode 100644
index 0000000..6b3448f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Curve.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256R1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"));
+
+        private const int SecP256R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP256R1Point m_infinity;
+
+        public SecP256R1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP256R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B")));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SecP256R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP256R1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+            case COORD_JACOBIAN:
+                return true;
+            default:
+                return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP256R1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP256R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP256R1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Field.cs
new file mode 100644
index 0000000..9ed9dcd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Field.cs
@@ -0,0 +1,309 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256R1Field
+    {
+        // 2^256 - 2^224 + 2^192 + 2^96 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000,
+            0x00000001, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001, 0x00000001, 0xFFFFFFFE,
+            0x00000002, 0xFFFFFFFE };
+        internal const uint P7 = 0xFFFFFFFF;
+        internal const uint PExt15 = 0xFFFFFFFE;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat256.Add(x, y, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(16, xx, yy, zz);
+            if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt)))
+            {
+                Nat.SubFrom(16, PExt, zz);
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(8, x, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat256.FromBigInteger(x);
+            if (z[7] == P7 && Nat256.Gte(z, P))
+            {
+                Nat256.SubFrom(P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(8, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat256.Add(x, P, z);
+                Nat.ShiftDownBit(8, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void MultiplyAddToExt(uint[] x, uint[] y, uint[] zz)
+        {
+            uint c = Nat256.MulAddTo(x, y, zz);
+            if (c != 0 || (zz[15] >= PExt15 && Nat.Gte(16, zz, PExt)))
+            {
+                Nat.SubFrom(16, PExt, zz);
+            }
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat256.IsZero(x))
+            {
+                Nat256.Zero(z);
+            }
+            else
+            {
+                Nat256.Sub(P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            long xx08 = xx[8], xx09 = xx[9], xx10 = xx[10], xx11 = xx[11];
+            long xx12 = xx[12], xx13 = xx[13], xx14 = xx[14], xx15 = xx[15];
+
+            const long n = 6;
+
+            xx08 -= n;
+
+            long t0 = xx08 + xx09;
+            long t1 = xx09 + xx10;
+            long t2 = xx10 + xx11 - xx15;
+            long t3 = xx11 + xx12;
+            long t4 = xx12 + xx13;
+            long t5 = xx13 + xx14;
+            long t6 = xx14 + xx15;
+
+            long cc = 0;
+            cc += (long)xx[0] + t0 - t3 - t5;
+            z[0] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[1] + t1 - t4 - t6;
+            z[1] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[2] + t2 - t5;
+            z[2] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[3] + (t3 << 1) + xx13 - xx15 - t0;
+            z[3] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[4] + (t4 << 1) + xx14 - t1;
+            z[4] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[5] + (t5 << 1) - t2;
+            z[5] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[6] + (t6 << 1) + t5 - t0;
+            z[6] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[7] + (xx15 << 1) + xx08 - t2 - t4;
+            z[7] = (uint)cc;
+            cc >>= 32;
+            cc += n;
+
+            Debug.Assert(cc >= 0);
+
+            Reduce32((uint)cc, z);
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            long cc = 0;
+
+            if (x != 0)
+            {
+                long xx08 = x;
+
+                cc += (long)z[0] + xx08;
+                z[0] = (uint)cc;
+                cc >>= 32;
+                if (cc != 0)
+                {
+                    cc += (long)z[1];
+                    z[1] = (uint)cc;
+                    cc >>= 32;
+                    cc += (long)z[2];
+                    z[2] = (uint)cc;
+                    cc >>= 32;
+                }
+                cc += (long)z[3] - xx08;
+                z[3] = (uint)cc;
+                cc >>= 32;
+                if (cc != 0)
+                {
+                    cc += (long)z[4];
+                    z[4] = (uint)cc;
+                    cc >>= 32;
+                    cc += (long)z[5];
+                    z[5] = (uint)cc;
+                    cc >>= 32;
+                }
+                cc += (long)z[6] - xx08;
+                z[6] = (uint)cc;
+                cc >>= 32;
+                cc += (long)z[7] + xx08;
+                z[7] = (uint)cc;
+                cc >>= 32;
+
+                Debug.Assert(cc == 0 || cc == 1);
+            }
+
+            if (cc != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat256.CreateExt();
+            Nat256.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat256.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat256.Sub(x, y, z);
+            if (c != 0)
+            {
+                SubPInvFrom(z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(16, xx, yy, zz);
+            if (c != 0)
+            {
+                Nat.AddTo(16, PExt, zz);
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(8, x, 0, z);
+            if (c != 0 || (z[7] == P7 && Nat256.Gte(z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        private static void AddPInvTo(uint[] z)
+        {
+            long c = (long)z[0] + 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] - 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[4];
+                z[4] = (uint)c;
+                c >>= 32;
+                c += (long)z[5];
+                z[5] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[6] - 1;
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (long)z[7] + 1;
+            z[7] = (uint)c;
+            //c >>= 32;
+        }
+
+        private static void SubPInvFrom(uint[] z)
+        {
+            long c = (long)z[0] - 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[1];
+                z[1] = (uint)c;
+                c >>= 32;
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] + 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[4];
+                z[4] = (uint)c;
+                c >>= 32;
+                c += (long)z[5];
+                z[5] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[6] + 1;
+            z[6] = (uint)c;
+            c >>= 32;
+            c += (long)z[7] - 1;
+            z[7] = (uint)c;
+            //c >>= 32;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1FieldElement.cs
new file mode 100644
index 0000000..b22763c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1FieldElement.cs
@@ -0,0 +1,187 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256R1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP256R1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP256R1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP256R1FieldElement", "x");
+
+            this.x = SecP256R1Field.FromBigInteger(x);
+        }
+
+        public SecP256R1FieldElement()
+        {
+            this.x = Nat256.Create();
+        }
+
+        protected internal SecP256R1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat256.IsZero(x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat256.IsOne(x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat256.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat256.ToBigInteger(x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP256R1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.Add(x, ((SecP256R1FieldElement)b).x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.AddOne(x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.Subtract(x, ((SecP256R1FieldElement)b).x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.Multiply(x, ((SecP256R1FieldElement)b).x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat256.Create();
+            Mod.Invert(SecP256R1Field.P, ((SecP256R1FieldElement)b).x, z);
+            SecP256R1Field.Multiply(z, x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.Negate(x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat256.Create();
+            SecP256R1Field.Square(x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP256R1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat256.Create();
+            Mod.Invert(SecP256R1Field.P, x, z);
+            return new SecP256R1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            // Raise this element to the exponent 2^254 - 2^222 + 2^190 + 2^94
+
+            uint[] x1 = this.x;
+            if (Nat256.IsZero(x1) || Nat256.IsOne(x1))
+                return this;
+
+            uint[] t1 = Nat256.Create();
+            uint[] t2 = Nat256.Create();
+
+            SecP256R1Field.Square(x1, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 2, t2);
+            SecP256R1Field.Multiply(t2, t1, t2);
+
+            SecP256R1Field.SquareN(t2, 4, t1);
+            SecP256R1Field.Multiply(t1, t2, t1);
+
+            SecP256R1Field.SquareN(t1, 8, t2);
+            SecP256R1Field.Multiply(t2, t1, t2);
+
+            SecP256R1Field.SquareN(t2, 16, t1);
+            SecP256R1Field.Multiply(t1, t2, t1);
+
+            SecP256R1Field.SquareN(t1, 32, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 96, t1);
+            SecP256R1Field.Multiply(t1, x1, t1);
+
+            SecP256R1Field.SquareN(t1, 94, t1);
+            SecP256R1Field.Multiply(t1, t1, t2);
+
+            return Nat256.Eq(x1, t2) ? new SecP256R1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP256R1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP256R1FieldElement);
+        }
+
+        public virtual bool Equals(SecP256R1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat256.Eq(x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 8);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Point.cs
new file mode 100644
index 0000000..1de4a0b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP256R1Point.cs
@@ -0,0 +1,277 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP256R1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP256R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP256R1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.RawXCoord, Y1 = (SecP256R1FieldElement)this.RawYCoord;
+            SecP256R1FieldElement X2 = (SecP256R1FieldElement)b.RawXCoord, Y2 = (SecP256R1FieldElement)b.RawYCoord;
+
+            SecP256R1FieldElement Z1 = (SecP256R1FieldElement)this.RawZCoords[0];
+            SecP256R1FieldElement Z2 = (SecP256R1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat256.CreateExt();
+            uint[] t2 = Nat256.Create();
+            uint[] t3 = Nat256.Create();
+            uint[] t4 = Nat256.Create();
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP256R1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP256R1Field.Multiply(S2, X2.x, U2);
+
+                SecP256R1Field.Multiply(S2, Z1.x, S2);
+                SecP256R1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP256R1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP256R1Field.Multiply(S1, X1.x, U1);
+
+                SecP256R1Field.Multiply(S1, Z2.x, S1);
+                SecP256R1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat256.Create();
+            SecP256R1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP256R1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat256.IsZero(H))
+            {
+                if (Nat256.IsZero(R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP256R1Field.Square(H, HSquared);
+
+            uint[] G = Nat256.Create();
+            SecP256R1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP256R1Field.Multiply(HSquared, U1, V);
+
+            SecP256R1Field.Negate(G, G);
+            Nat256.Mul(S1, G, tt1);
+
+            c = Nat256.AddBothTo(V, V, G);
+            SecP256R1Field.Reduce32(c, G);
+
+            SecP256R1FieldElement X3 = new SecP256R1FieldElement(t4);
+            SecP256R1Field.Square(R, X3.x);
+            SecP256R1Field.Subtract(X3.x, G, X3.x);
+
+            SecP256R1FieldElement Y3 = new SecP256R1FieldElement(G);
+            SecP256R1Field.Subtract(V, X3.x, Y3.x);
+            SecP256R1Field.MultiplyAddToExt(Y3.x, R, tt1);
+            SecP256R1Field.Reduce(tt1, Y3.x);
+
+            SecP256R1FieldElement Z3 = new SecP256R1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP256R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP256R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[]{ Z3 };
+
+            return new SecP256R1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP256R1FieldElement Y1 = (SecP256R1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP256R1FieldElement X1 = (SecP256R1FieldElement)this.RawXCoord, Z1 = (SecP256R1FieldElement)this.RawZCoords[0];
+
+            uint c;
+            uint[] t1 = Nat256.Create();
+            uint[] t2 = Nat256.Create();
+
+            uint[] Y1Squared = Nat256.Create();
+            SecP256R1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat256.Create();
+            SecP256R1Field.Square(Y1Squared, T);
+
+            bool Z1IsOne = Z1.IsOne;
+
+            uint[] Z1Squared = Z1.x;
+            if (!Z1IsOne)
+            {
+                Z1Squared = t2;
+                SecP256R1Field.Square(Z1.x, Z1Squared);
+            }
+
+            SecP256R1Field.Subtract(X1.x, Z1Squared, t1);
+
+            uint[] M = t2;
+            SecP256R1Field.Add(X1.x, Z1Squared, M);
+            SecP256R1Field.Multiply(M, t1, M);
+            c = Nat256.AddBothTo(M, M, M);
+            SecP256R1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP256R1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(8, S, 2, 0);
+            SecP256R1Field.Reduce32(c, S);
+
+            c = Nat.ShiftUpBits(8, T, 3, 0, t1);
+            SecP256R1Field.Reduce32(c, t1);
+
+            SecP256R1FieldElement X3 = new SecP256R1FieldElement(T);
+            SecP256R1Field.Square(M, X3.x);
+            SecP256R1Field.Subtract(X3.x, S, X3.x);
+            SecP256R1Field.Subtract(X3.x, S, X3.x);
+
+            SecP256R1FieldElement Y3 = new SecP256R1FieldElement(S);
+            SecP256R1Field.Subtract(S, X3.x, Y3.x);
+            SecP256R1Field.Multiply(Y3.x, M, Y3.x);
+            SecP256R1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP256R1FieldElement Z3 = new SecP256R1FieldElement(M);
+            SecP256R1Field.Twice(Y1.x, Z3.x);
+            if (!Z1IsOne)
+            {
+                SecP256R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP256R1Point(curve, X3, Y3, new ECFieldElement[]{ Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP256R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Curve.cs
new file mode 100644
index 0000000..7fd5827
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Curve.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP384R1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"));
+
+        private const int SecP384R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP384R1Point m_infinity;
+
+        public SecP384R1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP384R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF")));
+            this.m_order = new BigInteger(1, Hex.Decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SecP384R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP384R1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_JACOBIAN:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP384R1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP384R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP384R1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Field.cs
new file mode 100644
index 0000000..508b01e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Field.cs
@@ -0,0 +1,292 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP384R1Field
+    {
+            // 2^384 - 2^128 - 2^96 + 2^32 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        internal static readonly uint[] PExt = new uint[]{ 0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
+            0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFE, 0x00000001, 0x00000000,
+            0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };
+        private static readonly uint[] PExtInv = new uint[]{ 0xFFFFFFFF, 0x00000001, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0x00000001,
+            0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001, 0xFFFFFFFE, 0xFFFFFFFF,
+            0x00000001, 0x00000002 };
+        private const uint P11 = 0xFFFFFFFF;
+        private const uint PExt23 = 0xFFFFFFFF;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat.Add(12, x, y, z);
+            if (c != 0 || (z[11] == P11 && Nat.Gte(12, z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void AddExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            uint c = Nat.Add(24, xx, yy, zz);
+            if (c != 0 || (zz[23] == PExt23 && Nat.Gte(24, zz, PExt)))
+            {
+                if (Nat.AddTo(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.IncAt(24, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(12, x, z);
+            if (c != 0 || (z[11] == P11 && Nat.Gte(12, z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat.FromBigInteger(384, x);
+            if (z[11] == P11 && Nat.Gte(12, z, P))
+            {
+                Nat.SubFrom(12, P, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            if ((x[0] & 1) == 0)
+            {
+                Nat.ShiftDownBit(12, x, 0, z);
+            }
+            else
+            {
+                uint c = Nat.Add(12, x, P, z);
+                Nat.ShiftDownBit(12, z, c);
+            }
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat.Create(24);
+            Nat384.Mul(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat.IsZero(12, x))
+            {
+                Nat.Zero(12, z);
+            }
+            else
+            {
+                Nat.Sub(12, P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            long xx16 = xx[16], xx17 = xx[17], xx18 = xx[18], xx19 = xx[19];
+            long xx20 = xx[20], xx21 = xx[21], xx22 = xx[22], xx23 = xx[23];
+
+            const long n = 1;
+
+            long t0 = (long)xx[12] + xx20 - n;
+            long t1 = (long)xx[13] + xx22;
+            long t2 = (long)xx[14] + xx22 + xx23;
+            long t3 = (long)xx[15] + xx23;
+            long t4 = xx17 + xx21;
+            long t5 = xx21 - xx23;
+            long t6 = xx22 - xx23;
+
+            long cc = 0;
+            cc += (long)xx[0] + t0 + t5;
+            z[0] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[1] + xx23 - t0 + t1;
+            z[1] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[2] - xx21 - t1 + t2;
+            z[2] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[3] + t0 - t2 + t3 + t5;
+            z[3] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[4] + xx16 + xx21 + t0 + t1 - t3 + t5;
+            z[4] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[5] - xx16 + t1 + t2 + t4;
+            z[5] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[6] + xx18 - xx17 + t2 + t3;
+            z[6] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[7] + xx16 + xx19 - xx18 + t3;
+            z[7] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[8] + xx16 + xx17 + xx20 - xx19;
+            z[8] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[9] + xx18 - xx20 + t4;
+            z[9] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[10] + xx18 + xx19 - t5 + t6;
+            z[10] = (uint)cc;
+            cc >>= 32;
+            cc += (long)xx[11] + xx19 + xx20 - t6;
+            z[11] = (uint)cc;
+            cc >>= 32;
+            cc += n;
+
+            Debug.Assert(cc >= 0);
+
+            Reduce32((uint)cc, z);
+        }
+
+        public static void Reduce32(uint x, uint[] z)
+        {
+            long cc = 0;
+
+            if (x != 0)
+            {
+                long xx12 = x;
+
+                cc += (long)z[0] + xx12;
+                z[0] = (uint)cc;
+                cc >>= 32;
+                cc += (long)z[1] - xx12;
+                z[1] = (uint)cc;
+                cc >>= 32;
+                if (cc != 0)
+                {
+                    cc += (long)z[2];
+                    z[2] = (uint)cc;
+                    cc >>= 32;
+                }
+                cc += (long)z[3] + xx12;
+                z[3] = (uint)cc;
+                cc >>= 32;
+                cc += (long)z[4] + xx12;
+                z[4] = (uint)cc;
+                cc >>= 32;
+
+                Debug.Assert(cc == 0 || cc == 1);
+            }
+
+            if ((cc != 0 && Nat.IncAt(12, z, 5) != 0)
+                || (z[11] == P11 && Nat.Gte(12, z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat.Create(24);
+            Nat384.Square(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+
+            uint[] tt = Nat.Create(24);
+            Nat384.Square(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                Nat384.Square(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat.Sub(12, x, y, z);
+            if (c != 0)
+            {
+                SubPInvFrom(z);
+            }
+        }
+
+        public static void SubtractExt(uint[] xx, uint[] yy, uint[] zz)
+        {
+            int c = Nat.Sub(24, xx, yy, zz);
+            if (c != 0)
+            {
+                if (Nat.SubFrom(PExtInv.Length, PExtInv, zz) != 0)
+                {
+                    Nat.DecAt(24, zz, PExtInv.Length);
+                }
+            }
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint c = Nat.ShiftUpBit(12, x, 0, z);
+            if (c != 0 || (z[11] == P11 && Nat.Gte(12, z, P)))
+            {
+                AddPInvTo(z);
+            }
+        }
+
+        private static void AddPInvTo(uint[] z)
+        {
+            long c = (long)z[0] + 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] - 1;
+            z[1] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] + 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] + 1;
+            z[4] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.IncAt(12, z, 5);
+            }
+        }
+
+        private static void SubPInvFrom(uint[] z)
+        {
+            long c = (long)z[0] - 1;
+            z[0] = (uint)c;
+            c >>= 32;
+            c += (long)z[1] + 1;
+            z[1] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                c += (long)z[2];
+                z[2] = (uint)c;
+                c >>= 32;
+            }
+            c += (long)z[3] - 1;
+            z[3] = (uint)c;
+            c >>= 32;
+            c += (long)z[4] - 1;
+            z[4] = (uint)c;
+            c >>= 32;
+            if (c != 0)
+            {
+                Nat.DecAt(12, z, 5);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1FieldElement.cs
new file mode 100644
index 0000000..4008697
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1FieldElement.cs
@@ -0,0 +1,209 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP384R1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP384R1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP384R1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP384R1FieldElement", "x");
+
+            this.x = SecP384R1Field.FromBigInteger(x);
+        }
+
+        public SecP384R1FieldElement()
+        {
+            this.x = Nat.Create(12);
+        }
+
+        protected internal SecP384R1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat.IsZero(12, x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat.IsOne(12, x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat.ToBigInteger(12, x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP384R1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.Add(x, ((SecP384R1FieldElement)b).x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.AddOne(x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.Subtract(x, ((SecP384R1FieldElement)b).x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.Multiply(x, ((SecP384R1FieldElement)b).x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat.Create(12);
+            Mod.Invert(SecP384R1Field.P, ((SecP384R1FieldElement)b).x, z);
+            SecP384R1Field.Multiply(z, x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.Negate(x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat.Create(12);
+            SecP384R1Field.Square(x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP384R1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat.Create(12);
+            Mod.Invert(SecP384R1Field.P, x, z);
+            return new SecP384R1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            // Raise this element to the exponent 2^382 - 2^126 - 2^94 + 2^30
+
+            uint[] x1 = this.x;
+            if (Nat.IsZero(12, x1) || Nat.IsOne(12, x1))
+                return this;
+
+            uint[] t1 = Nat.Create(12);
+            uint[] t2 = Nat.Create(12);
+            uint[] t3 = Nat.Create(12);
+            uint[] t4 = Nat.Create(12);
+
+            SecP384R1Field.Square(x1, t1);
+            SecP384R1Field.Multiply(t1, x1, t1);
+
+            SecP384R1Field.SquareN(t1, 2, t2);
+            SecP384R1Field.Multiply(t2, t1, t2);
+
+            SecP384R1Field.Square(t2, t2);
+            SecP384R1Field.Multiply(t2, x1, t2);
+
+            SecP384R1Field.SquareN(t2, 5, t3);
+            SecP384R1Field.Multiply(t3, t2, t3);
+
+            SecP384R1Field.SquareN(t3, 5, t4);
+            SecP384R1Field.Multiply(t4, t2, t4);
+
+            SecP384R1Field.SquareN(t4, 15, t2);
+            SecP384R1Field.Multiply(t2, t4, t2);
+
+            SecP384R1Field.SquareN(t2, 2, t3);
+            SecP384R1Field.Multiply(t1, t3, t1);
+
+            SecP384R1Field.SquareN(t3, 28, t3);
+            SecP384R1Field.Multiply(t2, t3, t2);
+
+            SecP384R1Field.SquareN(t2, 60, t3);
+            SecP384R1Field.Multiply(t3, t2, t3);
+
+            uint[] r = t2;
+
+            SecP384R1Field.SquareN(t3, 120, r);
+            SecP384R1Field.Multiply(r, t3, r);
+
+            SecP384R1Field.SquareN(r, 15, r);
+            SecP384R1Field.Multiply(r, t4, r);
+
+            SecP384R1Field.SquareN(r, 33, r);
+            SecP384R1Field.Multiply(r, t1, r);
+
+            SecP384R1Field.SquareN(r, 64, r);
+            SecP384R1Field.Multiply(r, x1, r);
+
+            SecP384R1Field.SquareN(r, 30, t1);
+            SecP384R1Field.Square(t1, t2);
+
+            return Nat.Eq(12, x1, t2) ? new SecP384R1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP384R1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP384R1FieldElement);
+        }
+
+        public virtual bool Equals(SecP384R1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat.Eq(12, x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 12);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Point.cs
new file mode 100644
index 0000000..68c6016
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP384R1Point.cs
@@ -0,0 +1,278 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP384R1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP384R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP384R1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.RawXCoord, Y1 = (SecP384R1FieldElement)this.RawYCoord;
+            SecP384R1FieldElement X2 = (SecP384R1FieldElement)b.RawXCoord, Y2 = (SecP384R1FieldElement)b.RawYCoord;
+
+            SecP384R1FieldElement Z1 = (SecP384R1FieldElement)this.RawZCoords[0];
+            SecP384R1FieldElement Z2 = (SecP384R1FieldElement)b.RawZCoords[0];
+
+            uint c;
+            uint[] tt1 = Nat.Create(24);
+            uint[] tt2 = Nat.Create(24);
+            uint[] t3 = Nat.Create(12);
+            uint[] t4 = Nat.Create(12);
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP384R1Field.Square(Z1.x, S2);
+
+                U2 = tt2;
+                SecP384R1Field.Multiply(S2, X2.x, U2);
+
+                SecP384R1Field.Multiply(S2, Z1.x, S2);
+                SecP384R1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP384R1Field.Square(Z2.x, S1);
+
+                U1 = tt1;
+                SecP384R1Field.Multiply(S1, X1.x, U1);
+
+                SecP384R1Field.Multiply(S1, Z2.x, S1);
+                SecP384R1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat.Create(12);
+            SecP384R1Field.Subtract(U1, U2, H);
+
+            uint[] R = Nat.Create(12);
+            SecP384R1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat.IsZero(12, H))
+            {
+                if (Nat.IsZero(12, R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP384R1Field.Square(H, HSquared);
+
+            uint[] G = Nat.Create(12);
+            SecP384R1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP384R1Field.Multiply(HSquared, U1, V);
+
+            SecP384R1Field.Negate(G, G);
+            Nat384.Mul(S1, G, tt1);
+
+            c = Nat.AddBothTo(12, V, V, G);
+            SecP384R1Field.Reduce32(c, G);
+
+            SecP384R1FieldElement X3 = new SecP384R1FieldElement(t4);
+            SecP384R1Field.Square(R, X3.x);
+            SecP384R1Field.Subtract(X3.x, G, X3.x);
+
+            SecP384R1FieldElement Y3 = new SecP384R1FieldElement(G);
+            SecP384R1Field.Subtract(V, X3.x, Y3.x);
+            Nat384.Mul(Y3.x, R, tt2);
+            SecP384R1Field.AddExt(tt1, tt2, tt1);
+            SecP384R1Field.Reduce(tt1, Y3.x);
+
+            SecP384R1FieldElement Z3 = new SecP384R1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP384R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP384R1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP384R1FieldElement Y1 = (SecP384R1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP384R1FieldElement X1 = (SecP384R1FieldElement)this.RawXCoord, Z1 = (SecP384R1FieldElement)this.RawZCoords[0];
+
+            uint c;
+            uint[] t1 = Nat.Create(12);
+            uint[] t2 = Nat.Create(12);
+
+            uint[] Y1Squared = Nat.Create(12);
+            SecP384R1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat.Create(12);
+            SecP384R1Field.Square(Y1Squared, T);
+
+            bool Z1IsOne = Z1.IsOne;
+
+            uint[] Z1Squared = Z1.x;
+            if (!Z1IsOne)
+            {
+                Z1Squared = t2;
+                SecP384R1Field.Square(Z1.x, Z1Squared);
+            }
+
+            SecP384R1Field.Subtract(X1.x, Z1Squared, t1);
+
+            uint[] M = t2;
+            SecP384R1Field.Add(X1.x, Z1Squared, M);
+            SecP384R1Field.Multiply(M, t1, M);
+            c = Nat.AddBothTo(12, M, M, M);
+            SecP384R1Field.Reduce32(c, M);
+
+            uint[] S = Y1Squared;
+            SecP384R1Field.Multiply(Y1Squared, X1.x, S);
+            c = Nat.ShiftUpBits(12, S, 2, 0);
+            SecP384R1Field.Reduce32(c, S);
+
+            c = Nat.ShiftUpBits(12, T, 3, 0, t1);
+            SecP384R1Field.Reduce32(c, t1);
+
+            SecP384R1FieldElement X3 = new SecP384R1FieldElement(T);
+            SecP384R1Field.Square(M, X3.x);
+            SecP384R1Field.Subtract(X3.x, S, X3.x);
+            SecP384R1Field.Subtract(X3.x, S, X3.x);
+
+            SecP384R1FieldElement Y3 = new SecP384R1FieldElement(S);
+            SecP384R1Field.Subtract(S, X3.x, Y3.x);
+            SecP384R1Field.Multiply(Y3.x, M, Y3.x);
+            SecP384R1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP384R1FieldElement Z3 = new SecP384R1FieldElement(M);
+            SecP384R1Field.Twice(Y1.x, Z3.x);
+            if (!Z1IsOne)
+            {
+                SecP384R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP384R1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP384R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Curve.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Curve.cs
new file mode 100644
index 0000000..e5083c7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Curve.cs
@@ -0,0 +1,77 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP521R1Curve
+        : AbstractFpCurve
+    {
+        public static readonly BigInteger q = new BigInteger(1,
+            Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"));
+
+        private const int SecP521R1_DEFAULT_COORDS = COORD_JACOBIAN;
+
+        protected readonly SecP521R1Point m_infinity;
+
+        public SecP521R1Curve()
+            : base(q)
+        {
+            this.m_infinity = new SecP521R1Point(this, null, null);
+
+            this.m_a = FromBigInteger(new BigInteger(1,
+                Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC")));
+            this.m_b = FromBigInteger(new BigInteger(1,
+                Hex.Decode("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00")));
+            this.m_order = new BigInteger(1, Hex.Decode("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409"));
+            this.m_cofactor = BigInteger.One;
+            this.m_coord = SecP521R1_DEFAULT_COORDS;
+        }
+
+        protected override ECCurve CloneCurve()
+        {
+            return new SecP521R1Curve();
+        }
+
+        public override bool SupportsCoordinateSystem(int coord)
+        {
+            switch (coord)
+            {
+                case COORD_JACOBIAN:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public virtual BigInteger Q
+        {
+            get { return q; }
+        }
+
+        public override ECPoint Infinity
+        {
+            get { return m_infinity; }
+        }
+
+        public override int FieldSize
+        {
+            get { return q.BitLength; }
+        }
+
+        public override ECFieldElement FromBigInteger(BigInteger x)
+        {
+            return new SecP521R1FieldElement(x);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, bool withCompression)
+        {
+            return new SecP521R1Point(this, x, y, withCompression);
+        }
+
+        protected internal override ECPoint CreateRawPoint(ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+        {
+            return new SecP521R1Point(this, x, y, zs, withCompression);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Field.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Field.cs
new file mode 100644
index 0000000..3568156
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Field.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Diagnostics;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP521R1Field
+    {
+        // 2^521 - 1
+        internal static readonly uint[] P = new uint[]{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+            0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x1FF };
+        private const int P16 = 0x1FF;
+
+        public static void Add(uint[] x, uint[] y, uint[] z)
+        {
+            uint c = Nat.Add(16, x, y, z) + x[16] + y[16];
+            if (c > P16 || (c == P16 && Nat.Eq(16, z, P)))
+            {
+                c += Nat.Inc(16, z);
+                c &= P16;
+            }
+            z[16] = c;
+        }
+
+        public static void AddOne(uint[] x, uint[] z)
+        {
+            uint c = Nat.Inc(16, x, z) + x[16];
+            if (c > P16 || (c == P16 && Nat.Eq(16, z, P)))
+            {
+                c += Nat.Inc(16, z);
+                c &= P16;
+            }
+            z[16] = c;
+        }
+
+        public static uint[] FromBigInteger(BigInteger x)
+        {
+            uint[] z = Nat.FromBigInteger(521, x);
+            if (Nat.Eq(17, z, P))
+            {
+                Nat.Zero(17, z);
+            }
+            return z;
+        }
+
+        public static void Half(uint[] x, uint[] z)
+        {
+            uint x16 = x[16];
+            uint c = Nat.ShiftDownBit(16, x, x16, z);
+            z[16] = (x16 >> 1) | (c >> 23);
+        }
+
+        public static void Multiply(uint[] x, uint[] y, uint[] z)
+        {
+            uint[] tt = Nat.Create(33);
+            ImplMultiply(x, y, tt);
+            Reduce(tt, z);
+        }
+
+        public static void Negate(uint[] x, uint[] z)
+        {
+            if (Nat.IsZero(17, x))
+            {
+                Nat.Zero(17, z);
+            }
+            else
+            {
+                Nat.Sub(17, P, x, z);
+            }
+        }
+
+        public static void Reduce(uint[] xx, uint[] z)
+        {
+            Debug.Assert(xx[32] >> 18 == 0);
+            uint xx32 = xx[32];
+            uint c = Nat.ShiftDownBits(16, xx, 16, 9, xx32, z, 0) >> 23;
+            c += xx32 >> 9;
+            c += Nat.AddTo(16, xx, z);
+            if (c > P16 || (c == P16 && Nat.Eq(16, z, P)))
+            {
+                c += Nat.Inc(16, z);
+                c &= P16;
+            }
+            z[16] = c;
+        }
+
+        public static void Reduce23(uint[] z)
+        {
+            uint z16 = z[16];
+            uint c = Nat.AddWordTo(16, z16 >> 9, z) + (z16 & P16);
+            if (c > P16 || (c == P16 && Nat.Eq(16, z, P)))
+            {
+                c += Nat.Inc(16, z);
+                c &= P16;
+            }
+            z[16] = c;
+        }
+
+        public static void Square(uint[] x, uint[] z)
+        {
+            uint[] tt = Nat.Create(33);
+            ImplSquare(x, tt);
+            Reduce(tt, z);
+        }
+
+        public static void SquareN(uint[] x, int n, uint[] z)
+        {
+            Debug.Assert(n > 0);
+            uint[] tt = Nat.Create(33);
+            ImplSquare(x, tt);
+            Reduce(tt, z);
+
+            while (--n > 0)
+            {
+                ImplSquare(z, tt);
+                Reduce(tt, z);
+            }
+        }
+
+        public static void Subtract(uint[] x, uint[] y, uint[] z)
+        {
+            int c = Nat.Sub(16, x, y, z) + (int)(x[16] - y[16]);
+            if (c < 0)
+            {
+                c += Nat.Dec(16, z);
+                c &= P16;
+            }
+            z[16] = (uint)c;
+        }
+
+        public static void Twice(uint[] x, uint[] z)
+        {
+            uint x16 = x[16];
+            uint c = Nat.ShiftUpBit(16, x, x16 << 23, z) | (x16 << 1);
+            z[16] = c & P16;
+        }
+
+        protected static void ImplMultiply(uint[] x, uint[] y, uint[] zz)
+        {
+            Nat512.Mul(x, y, zz);
+
+            uint x16 = x[16], y16 = y[16];
+            zz[32] = Nat.Mul31BothAdd(16, x16, y, y16, x, zz, 16) + (x16 * y16);
+        }
+
+        protected static void ImplSquare(uint[] x, uint[] zz)
+        {
+            Nat512.Square(x, zz);
+
+            uint x16 = x[16];
+            zz[32] = Nat.MulWordAddTo(16, x16 << 1, x, 0, zz, 16) + (x16 * x16);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1FieldElement.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1FieldElement.cs
new file mode 100644
index 0000000..83a6159
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1FieldElement.cs
@@ -0,0 +1,166 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP521R1FieldElement
+        : ECFieldElement
+    {
+        public static readonly BigInteger Q = SecP521R1Curve.q;
+
+        protected internal readonly uint[] x;
+
+        public SecP521R1FieldElement(BigInteger x)
+        {
+            if (x == null || x.SignValue < 0 || x.CompareTo(Q) >= 0)
+                throw new ArgumentException("value invalid for SecP521R1FieldElement", "x");
+
+            this.x = SecP521R1Field.FromBigInteger(x);
+        }
+
+        public SecP521R1FieldElement()
+        {
+            this.x = Nat.Create(17);
+        }
+
+        protected internal SecP521R1FieldElement(uint[] x)
+        {
+            this.x = x;
+        }
+
+        public override bool IsZero
+        {
+            get { return Nat.IsZero(17, x); }
+        }
+
+        public override bool IsOne
+        {
+            get { return Nat.IsOne(17, x); }
+        }
+
+        public override bool TestBitZero()
+        {
+            return Nat.GetBit(x, 0) == 1;
+        }
+
+        public override BigInteger ToBigInteger()
+        {
+            return Nat.ToBigInteger(17, x);
+        }
+
+        public override string FieldName
+        {
+            get { return "SecP521R1Field"; }
+        }
+
+        public override int FieldSize
+        {
+            get { return Q.BitLength; }
+        }
+
+        public override ECFieldElement Add(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.Add(x, ((SecP521R1FieldElement)b).x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement AddOne()
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.AddOne(x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Subtract(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.Subtract(x, ((SecP521R1FieldElement)b).x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Multiply(ECFieldElement b)
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.Multiply(x, ((SecP521R1FieldElement)b).x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Divide(ECFieldElement b)
+        {
+            //return Multiply(b.Invert());
+            uint[] z = Nat.Create(17);
+            Mod.Invert(SecP521R1Field.P, ((SecP521R1FieldElement)b).x, z);
+            SecP521R1Field.Multiply(z, x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Negate()
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.Negate(x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Square()
+        {
+            uint[] z = Nat.Create(17);
+            SecP521R1Field.Square(x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        public override ECFieldElement Invert()
+        {
+            //return new SecP521R1FieldElement(ToBigInteger().ModInverse(Q));
+            uint[] z = Nat.Create(17);
+            Mod.Invert(SecP521R1Field.P, x, z);
+            return new SecP521R1FieldElement(z);
+        }
+
+        /**
+         * return a sqrt root - the routine verifies that the calculation returns the right value - if
+         * none exists it returns null.
+         */
+        public override ECFieldElement Sqrt()
+        {
+            // Raise this element to the exponent 2^519
+
+            uint[] x1 = this.x;
+            if (Nat.IsZero(17, x1) || Nat.IsOne(17, x1))
+                return this;
+
+            uint[] t1 = Nat.Create(17);
+            uint[] t2 = Nat.Create(17);
+
+            SecP521R1Field.SquareN(x1, 519, t1);
+            SecP521R1Field.Square(t1, t2);
+
+            return Nat.Eq(17, x1, t2) ? new SecP521R1FieldElement(t1) : null;
+        }
+
+        public override bool Equals(object obj)
+        {
+            return Equals(obj as SecP521R1FieldElement);
+        }
+
+        public override bool Equals(ECFieldElement other)
+        {
+            return Equals(other as SecP521R1FieldElement);
+        }
+
+        public virtual bool Equals(SecP521R1FieldElement other)
+        {
+            if (this == other)
+                return true;
+            if (null == other)
+                return false;
+            return Nat.Eq(17, x, other.x);
+        }
+
+        public override int GetHashCode()
+        {
+            return Q.GetHashCode() ^ Arrays.GetHashCode(x, 0, 17);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Point.cs b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Point.cs
new file mode 100644
index 0000000..fb1996c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/custom/sec/SecP521R1Point.cs
@@ -0,0 +1,273 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Custom.Sec
+{
+    internal class SecP521R1Point
+        : AbstractFpPoint
+    {
+        /**
+         * Create a point which encodes with point compression.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * 
+         * @deprecated Use ECCurve.createPoint to construct points
+         */
+        public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y)
+            : this(curve, x, y, false)
+        {
+        }
+
+        /**
+         * Create a point that encodes with or without point compresion.
+         * 
+         * @param curve
+         *            the curve to use
+         * @param x
+         *            affine x co-ordinate
+         * @param y
+         *            affine y co-ordinate
+         * @param withCompression
+         *            if true encode with point compression
+         * 
+         * @deprecated per-point compression property will be removed, refer
+         *             {@link #getEncoded(bool)}
+         */
+        public SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, bool withCompression)
+            : base(curve, x, y, withCompression)
+        {
+            if ((x == null) != (y == null))
+                throw new ArgumentException("Exactly one of the field elements is null");
+        }
+
+        internal SecP521R1Point(ECCurve curve, ECFieldElement x, ECFieldElement y, ECFieldElement[] zs, bool withCompression)
+            : base(curve, x, y, zs, withCompression)
+        {
+        }
+
+        protected override ECPoint Detach()
+        {
+            return new SecP521R1Point(null, AffineXCoord, AffineYCoord);
+        }
+
+        public override ECPoint Add(ECPoint b)
+        {
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return this;
+            if (this == b)
+                return Twice();
+
+            ECCurve curve = this.Curve;
+
+            SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.RawXCoord, Y1 = (SecP521R1FieldElement)this.RawYCoord;
+            SecP521R1FieldElement X2 = (SecP521R1FieldElement)b.RawXCoord, Y2 = (SecP521R1FieldElement)b.RawYCoord;
+
+            SecP521R1FieldElement Z1 = (SecP521R1FieldElement)this.RawZCoords[0];
+            SecP521R1FieldElement Z2 = (SecP521R1FieldElement)b.RawZCoords[0];
+
+            uint[] t1 = Nat.Create(17);
+            uint[] t2 = Nat.Create(17);
+            uint[] t3 = Nat.Create(17);
+            uint[] t4 = Nat.Create(17);
+
+            bool Z1IsOne = Z1.IsOne;
+            uint[] U2, S2;
+            if (Z1IsOne)
+            {
+                U2 = X2.x;
+                S2 = Y2.x;
+            }
+            else
+            {
+                S2 = t3;
+                SecP521R1Field.Square(Z1.x, S2);
+
+                U2 = t2;
+                SecP521R1Field.Multiply(S2, X2.x, U2);
+
+                SecP521R1Field.Multiply(S2, Z1.x, S2);
+                SecP521R1Field.Multiply(S2, Y2.x, S2);
+            }
+
+            bool Z2IsOne = Z2.IsOne;
+            uint[] U1, S1;
+            if (Z2IsOne)
+            {
+                U1 = X1.x;
+                S1 = Y1.x;
+            }
+            else
+            {
+                S1 = t4;
+                SecP521R1Field.Square(Z2.x, S1);
+
+                U1 = t1;
+                SecP521R1Field.Multiply(S1, X1.x, U1);
+
+                SecP521R1Field.Multiply(S1, Z2.x, S1);
+                SecP521R1Field.Multiply(S1, Y1.x, S1);
+            }
+
+            uint[] H = Nat.Create(17);
+            SecP521R1Field.Subtract(U1, U2, H);
+
+            uint[] R = t2;
+            SecP521R1Field.Subtract(S1, S2, R);
+
+            // Check if b == this or b == -this
+            if (Nat.IsZero(17, H))
+            {
+                if (Nat.IsZero(17, R))
+                {
+                    // this == b, i.e. this must be doubled
+                    return this.Twice();
+                }
+
+                // this == -b, i.e. the result is the point at infinity
+                return curve.Infinity;
+            }
+
+            uint[] HSquared = t3;
+            SecP521R1Field.Square(H, HSquared);
+
+            uint[] G = Nat.Create(17);
+            SecP521R1Field.Multiply(HSquared, H, G);
+
+            uint[] V = t3;
+            SecP521R1Field.Multiply(HSquared, U1, V);
+
+            SecP521R1Field.Multiply(S1, G, t1);
+
+            SecP521R1FieldElement X3 = new SecP521R1FieldElement(t4);
+            SecP521R1Field.Square(R, X3.x);
+            SecP521R1Field.Add(X3.x, G, X3.x);
+            SecP521R1Field.Subtract(X3.x, V, X3.x);
+            SecP521R1Field.Subtract(X3.x, V, X3.x);
+
+            SecP521R1FieldElement Y3 = new SecP521R1FieldElement(G);
+            SecP521R1Field.Subtract(V, X3.x, Y3.x);
+            SecP521R1Field.Multiply(Y3.x, R, t2);
+            SecP521R1Field.Subtract(t2, t1, Y3.x);
+
+            SecP521R1FieldElement Z3 = new SecP521R1FieldElement(H);
+            if (!Z1IsOne)
+            {
+                SecP521R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+            if (!Z2IsOne)
+            {
+                SecP521R1Field.Multiply(Z3.x, Z2.x, Z3.x);
+            }
+
+            ECFieldElement[] zs = new ECFieldElement[] { Z3 };
+
+            return new SecP521R1Point(curve, X3, Y3, zs, IsCompressed);
+        }
+
+        public override ECPoint Twice()
+        {
+            if (this.IsInfinity)
+                return this;
+
+            ECCurve curve = this.Curve;
+
+            SecP521R1FieldElement Y1 = (SecP521R1FieldElement)this.RawYCoord;
+            if (Y1.IsZero)
+                return curve.Infinity;
+
+            SecP521R1FieldElement X1 = (SecP521R1FieldElement)this.RawXCoord, Z1 = (SecP521R1FieldElement)this.RawZCoords[0];
+
+            uint[] t1 = Nat.Create(17);
+            uint[] t2 = Nat.Create(17);
+
+            uint[] Y1Squared = Nat.Create(17);
+            SecP521R1Field.Square(Y1.x, Y1Squared);
+
+            uint[] T = Nat.Create(17);
+            SecP521R1Field.Square(Y1Squared, T);
+
+            bool Z1IsOne = Z1.IsOne;
+
+            uint[] Z1Squared = Z1.x;
+            if (!Z1IsOne)
+            {
+                Z1Squared = t2;
+                SecP521R1Field.Square(Z1.x, Z1Squared);
+            }
+
+            SecP521R1Field.Subtract(X1.x, Z1Squared, t1);
+
+            uint[] M = t2;
+            SecP521R1Field.Add(X1.x, Z1Squared, M);
+            SecP521R1Field.Multiply(M, t1, M);
+            Nat.AddBothTo(17, M, M, M);
+            SecP521R1Field.Reduce23(M);
+
+            uint[] S = Y1Squared;
+            SecP521R1Field.Multiply(Y1Squared, X1.x, S);
+            Nat.ShiftUpBits(17, S, 2, 0);
+            SecP521R1Field.Reduce23(S);
+
+            Nat.ShiftUpBits(17, T, 3, 0, t1);
+            SecP521R1Field.Reduce23(t1);
+
+            SecP521R1FieldElement X3 = new SecP521R1FieldElement(T);
+            SecP521R1Field.Square(M, X3.x);
+            SecP521R1Field.Subtract(X3.x, S, X3.x);
+            SecP521R1Field.Subtract(X3.x, S, X3.x);
+
+            SecP521R1FieldElement Y3 = new SecP521R1FieldElement(S);
+            SecP521R1Field.Subtract(S, X3.x, Y3.x);
+            SecP521R1Field.Multiply(Y3.x, M, Y3.x);
+            SecP521R1Field.Subtract(Y3.x, t1, Y3.x);
+
+            SecP521R1FieldElement Z3 = new SecP521R1FieldElement(M);
+            SecP521R1Field.Twice(Y1.x, Z3.x);
+            if (!Z1IsOne)
+            {
+                SecP521R1Field.Multiply(Z3.x, Z1.x, Z3.x);
+            }
+
+            return new SecP521R1Point(curve, X3, Y3, new ECFieldElement[] { Z3 }, IsCompressed);
+        }
+
+        public override ECPoint TwicePlus(ECPoint b)
+        {
+            if (this == b)
+                return ThreeTimes();
+            if (this.IsInfinity)
+                return b;
+            if (b.IsInfinity)
+                return Twice();
+
+            ECFieldElement Y1 = this.RawYCoord;
+            if (Y1.IsZero)
+                return b;
+
+            return Twice().Add(b);
+        }
+
+        public override ECPoint ThreeTimes()
+        {
+            if (this.IsInfinity || this.RawYCoord.IsZero)
+                return this;
+
+            // NOTE: Be careful about recursions between TwicePlus and ThreeTimes
+            return Twice().Add(this);
+        }
+
+        public override ECPoint Negate()
+        {
+            if (IsInfinity)
+                return this;
+
+            return new SecP521R1Point(Curve, RawXCoord, RawYCoord.Negate(), RawZCoords, IsCompressed);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/endo/ECEndomorphism.cs b/BouncyCastle.AxCrypt/src/math/ec/endo/ECEndomorphism.cs
new file mode 100644
index 0000000..dfb3213
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/endo/ECEndomorphism.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public interface ECEndomorphism
+    {
+        ECPointMap PointMap { get; }
+
+        bool HasEfficientPointMap { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/endo/GlvEndomorphism.cs b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvEndomorphism.cs
new file mode 100644
index 0000000..f65bdd6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvEndomorphism.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public interface GlvEndomorphism
+        :   ECEndomorphism
+    {
+        BigInteger[] DecomposeScalar(BigInteger k);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBEndomorphism.cs b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBEndomorphism.cs
new file mode 100644
index 0000000..d234d88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBEndomorphism.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class GlvTypeBEndomorphism
+        :   GlvEndomorphism
+    {
+        protected readonly ECCurve m_curve;
+        protected readonly GlvTypeBParameters m_parameters;
+        protected readonly ECPointMap m_pointMap;
+
+        public GlvTypeBEndomorphism(ECCurve curve, GlvTypeBParameters parameters)
+        {
+            this.m_curve = curve;
+            this.m_parameters = parameters;
+            this.m_pointMap = new ScaleXPointMap(curve.FromBigInteger(parameters.Beta));
+        }
+
+        public virtual BigInteger[] DecomposeScalar(BigInteger k)
+        {
+            int bits = m_parameters.Bits;
+            BigInteger b1 = CalculateB(k, m_parameters.G1, bits);
+            BigInteger b2 = CalculateB(k, m_parameters.G2, bits);
+
+            BigInteger[] v1 = m_parameters.V1, v2 = m_parameters.V2;
+            BigInteger a = k.Subtract((b1.Multiply(v1[0])).Add(b2.Multiply(v2[0])));
+            BigInteger b = (b1.Multiply(v1[1])).Add(b2.Multiply(v2[1])).Negate();
+
+            return new BigInteger[]{ a, b };
+        }
+
+        public virtual ECPointMap PointMap
+        {
+            get { return m_pointMap; }
+        }
+
+        public virtual bool HasEfficientPointMap
+        {
+            get { return true; }
+        }
+
+        protected virtual BigInteger CalculateB(BigInteger k, BigInteger g, int t)
+        {
+            bool negative = (g.SignValue < 0);
+            BigInteger b = k.Multiply(g.Abs());
+            bool extra = b.TestBit(t - 1);
+            b = b.ShiftRight(t);
+            if (extra)
+            {
+                b = b.Add(BigInteger.One);
+            }
+            return negative ? b.Negate() : b;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBParameters.cs b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBParameters.cs
new file mode 100644
index 0000000..f93dfaf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/endo/GlvTypeBParameters.cs
@@ -0,0 +1,60 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Endo
+{
+    public class GlvTypeBParameters
+    {
+        protected readonly BigInteger m_beta;
+        protected readonly BigInteger m_lambda;
+        protected readonly BigInteger[] m_v1, m_v2;
+        protected readonly BigInteger m_g1, m_g2;
+        protected readonly int m_bits;
+
+        public GlvTypeBParameters(BigInteger beta, BigInteger lambda, BigInteger[] v1, BigInteger[] v2,
+            BigInteger g1, BigInteger g2, int bits)
+        {
+            this.m_beta = beta;
+            this.m_lambda = lambda;
+            this.m_v1 = v1;
+            this.m_v2 = v2;
+            this.m_g1 = g1;
+            this.m_g2 = g2;
+            this.m_bits = bits;
+        }
+
+        public virtual BigInteger Beta
+        {
+            get { return m_beta; }
+        }
+
+        public virtual BigInteger Lambda
+        {
+            get { return m_lambda; }
+        }
+
+        public virtual BigInteger[] V1
+        {
+            get { return m_v1; }
+        }
+
+        public virtual BigInteger[] V2
+        {
+            get { return m_v2; }
+        }
+
+        public virtual BigInteger G1
+        {
+            get { return m_g1; }
+        }
+
+        public virtual BigInteger G2
+        {
+            get { return m_g2; }
+        }
+
+        public virtual int Bits
+        {
+            get { return m_bits; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/AbstractECMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/AbstractECMultiplier.cs
new file mode 100644
index 0000000..5178813
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/AbstractECMultiplier.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public abstract class AbstractECMultiplier
+        : ECMultiplier
+    {
+        public virtual ECPoint Multiply(ECPoint p, BigInteger k)
+        {
+            int sign = k.SignValue;
+            if (sign == 0 || p.IsInfinity)
+                return p.Curve.Infinity;
+
+            ECPoint positive = MultiplyPositive(p, k.Abs());
+            ECPoint result = sign > 0 ? positive : positive.Negate();
+
+            /*
+             * Although the various multipliers ought not to produce invalid output under normal
+             * circumstances, a final check here is advised to guard against fault attacks.
+             */
+            return ECAlgorithms.ValidatePoint(result);
+        }
+
+        protected abstract ECPoint MultiplyPositive(ECPoint p, BigInteger k);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/DoubleAddMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/DoubleAddMultiplier.cs
new file mode 100644
index 0000000..18a72c0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/DoubleAddMultiplier.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class DoubleAddMultiplier
+        : AbstractECMultiplier
+    {
+        /**
+         * Joye's double-add algorithm.
+         */
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECPoint[] R = new ECPoint[]{ p.Curve.Infinity, p };
+
+            int n = k.BitLength;
+            for (int i = 0; i < n; ++i)
+            {
+                int b = k.TestBit(i) ? 1 : 0;
+                int bp = 1 - b;
+                R[bp] = R[bp].TwicePlus(R[b]);
+            }
+
+            return R[0];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/ECMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ECMultiplier.cs
new file mode 100644
index 0000000..8d6136b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ECMultiplier.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+    * Interface for classes encapsulating a point multiplication algorithm
+    * for <code>ECPoint</code>s.
+    */
+    public interface ECMultiplier
+    {
+        /**
+         * Multiplies the <code>ECPoint p</code> by <code>k</code>, i.e.
+         * <code>p</code> is added <code>k</code> times to itself.
+         * @param p The <code>ECPoint</code> to be multiplied.
+         * @param k The factor by which <code>p</code> is multiplied.
+         * @return <code>p</code> multiplied by <code>k</code>.
+         */
+        ECPoint Multiply(ECPoint p, BigInteger k);
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointCombMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointCombMultiplier.cs
new file mode 100644
index 0000000..a8ef5a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointCombMultiplier.cs
@@ -0,0 +1,59 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class FixedPointCombMultiplier
+        : AbstractECMultiplier
+    {
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECCurve c = p.Curve;
+            int size = FixedPointUtilities.GetCombSize(c);
+
+            if (k.BitLength > size)
+            {
+                /*
+                 * TODO The comb works best when the scalars are less than the (possibly unknown) order.
+                 * Still, if we want to handle larger scalars, we could allow customization of the comb
+                 * size, or alternatively we could deal with the 'extra' bits either by running the comb
+                 * multiple times as necessary, or by using an alternative multiplier as prelude.
+                 */
+                throw new InvalidOperationException("fixed-point comb doesn't support scalars larger than the curve order");
+            }
+
+            int minWidth = GetWidthForCombSize(size);
+
+            FixedPointPreCompInfo info = FixedPointUtilities.Precompute(p, minWidth);
+            ECPoint[] lookupTable = info.PreComp;
+            int width = info.Width;
+
+            int d = (size + width - 1) / width;
+
+            ECPoint R = c.Infinity;
+
+            int top = d * width - 1;
+            for (int i = 0; i < d; ++i)
+            {
+                int index = 0;
+
+                for (int j = top - i; j >= 0; j -= d)
+                {
+                    index <<= 1;
+                    if (k.TestBit(j))
+                    {
+                        index |= 1;
+                    }
+                }
+
+                R = R.TwicePlus(lookupTable[index]);
+            }
+
+            return R;
+        }
+
+        protected virtual int GetWidthForCombSize(int combSize)
+        {
+            return combSize > 257 ? 6 : 5;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointPreCompInfo.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointPreCompInfo.cs
new file mode 100644
index 0000000..56a6326
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointPreCompInfo.cs
@@ -0,0 +1,34 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+     * Class holding precomputation data for fixed-point multiplications.
+     */
+    public class FixedPointPreCompInfo
+        : PreCompInfo
+    {
+        /**
+         * Array holding the precomputed <code>ECPoint</code>s used for a fixed
+         * point multiplication.
+         */
+        protected ECPoint[] m_preComp = null;
+
+        /**
+         * The width used for the precomputation. If a larger width precomputation
+         * is already available this may be larger than was requested, so calling
+         * code should refer to the actual width.
+         */
+        protected int m_width = -1;
+
+        public virtual ECPoint[] PreComp
+        {
+            get { return m_preComp; }
+            set { this.m_preComp = value; }
+        }
+
+        public virtual int Width
+        {
+            get { return m_width; }
+            set { this.m_width = value; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointUtilities.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointUtilities.cs
new file mode 100644
index 0000000..d927d01
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FixedPointUtilities.cs
@@ -0,0 +1,72 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class FixedPointUtilities
+    {
+        public static readonly string PRECOMP_NAME = "bc_fixed_point";
+
+        public static int GetCombSize(ECCurve c)
+        {
+            BigInteger order = c.Order;
+            return order == null ? c.FieldSize + 1 : order.BitLength;
+        }
+
+        public static FixedPointPreCompInfo GetFixedPointPreCompInfo(PreCompInfo preCompInfo)
+        {
+            if ((preCompInfo != null) && (preCompInfo is FixedPointPreCompInfo))
+            {
+                return (FixedPointPreCompInfo)preCompInfo;
+            }
+
+            return new FixedPointPreCompInfo();
+        }
+
+        public static FixedPointPreCompInfo Precompute(ECPoint p, int minWidth)
+        {
+            ECCurve c = p.Curve;
+
+            int n = 1 << minWidth;
+            FixedPointPreCompInfo info = GetFixedPointPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
+            ECPoint[] lookupTable = info.PreComp;
+
+            if (lookupTable == null || lookupTable.Length < n)
+            {
+                int bits = GetCombSize(c);
+                int d = (bits + minWidth - 1) / minWidth;
+
+                ECPoint[] pow2Table = new ECPoint[minWidth];
+                pow2Table[0] = p;
+                for (int i = 1; i < minWidth; ++i)
+                {
+                    pow2Table[i] = pow2Table[i - 1].TimesPow2(d);
+                }
+    
+                c.NormalizeAll(pow2Table);
+    
+                lookupTable = new ECPoint[n];
+                lookupTable[0] = c.Infinity;
+
+                for (int bit = minWidth - 1; bit >= 0; --bit)
+                {
+                    ECPoint pow2 = pow2Table[bit];
+
+                    int step = 1 << bit;
+                    for (int i = step; i < n; i += (step << 1))
+                    {
+                        lookupTable[i] = lookupTable[i - step].Add(pow2);
+                    }
+                }
+
+                c.NormalizeAll(lookupTable);
+
+                info.PreComp = lookupTable;
+                info.Width = minWidth;
+
+                c.SetPreCompInfo(p, PRECOMP_NAME, info);
+            }
+
+            return info;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/FpNafMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FpNafMultiplier.cs
new file mode 100644
index 0000000..f5a9850
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/FpNafMultiplier.cs
@@ -0,0 +1,39 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+	/**
+	* Class implementing the NAF (Non-Adjacent Form) multiplication algorithm.
+	*/
+	internal class FpNafMultiplier
+		: ECMultiplier
+	{
+		/**
+		* D.3.2 pg 101
+		* @see org.bouncycastle.math.ec.multiplier.ECMultiplier#multiply(org.bouncycastle.math.ec.ECPoint, java.math.BigInteger)
+		*/
+		public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
+		{
+			// TODO Probably should try to add this
+			// BigInteger e = k.Mod(n); // n == order of p
+			BigInteger e = k;
+			BigInteger h = e.Multiply(BigInteger.Three);
+
+			ECPoint neg = p.Negate();
+			ECPoint R = p;
+
+			for (int i = h.BitLength - 2; i > 0; --i)
+			{             
+				R = R.Twice();
+
+				bool hBit = h.TestBit(i);
+				bool eBit = e.TestBit(i);
+
+				if (hBit != eBit)
+				{
+					R = R.Add(hBit ? p : neg);
+				}
+			}
+
+			return R;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/GlvMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/GlvMultiplier.cs
new file mode 100644
index 0000000..f190494
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/GlvMultiplier.cs
@@ -0,0 +1,40 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Endo;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class GlvMultiplier
+        :   AbstractECMultiplier
+    {
+        protected readonly ECCurve curve;
+        protected readonly GlvEndomorphism glvEndomorphism;
+
+        public GlvMultiplier(ECCurve curve, GlvEndomorphism glvEndomorphism)
+        {
+            if (curve == null || curve.Order == null)
+                throw new ArgumentException("Need curve with known group order", "curve");
+
+            this.curve = curve;
+            this.glvEndomorphism = glvEndomorphism;
+        }
+
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            if (!curve.Equals(p.Curve))
+                throw new InvalidOperationException();
+
+            BigInteger n = p.Curve.Order;
+            BigInteger[] ab = glvEndomorphism.DecomposeScalar(k.Mod(n));
+            BigInteger a = ab[0], b = ab[1];
+
+            ECPointMap pointMap = glvEndomorphism.PointMap;
+            if (glvEndomorphism.HasEfficientPointMap)
+            {
+                return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap, b);
+            }
+
+            return ECAlgorithms.ImplShamirsTrickWNaf(p, a, pointMap.Map(p), b);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/MixedNafR2LMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/MixedNafR2LMultiplier.cs
new file mode 100644
index 0000000..a4c2018
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/MixedNafR2LMultiplier.cs
@@ -0,0 +1,75 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+     * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left) using
+     * mixed coordinates.
+     */
+    public class MixedNafR2LMultiplier 
+        : AbstractECMultiplier
+    {
+        protected readonly int additionCoord, doublingCoord;
+
+        /**
+         * By default, addition will be done in Jacobian coordinates, and doubling will be done in
+         * Modified Jacobian coordinates (independent of the original coordinate system of each point).
+         */
+        public MixedNafR2LMultiplier()
+            : this(ECCurve.COORD_JACOBIAN, ECCurve.COORD_JACOBIAN_MODIFIED)
+        {
+        }
+
+        public MixedNafR2LMultiplier(int additionCoord, int doublingCoord)
+        {
+            this.additionCoord = additionCoord;
+            this.doublingCoord = doublingCoord;
+        }
+
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECCurve curveOrig = p.Curve;
+
+            ECCurve curveAdd = ConfigureCurve(curveOrig, additionCoord);
+            ECCurve curveDouble = ConfigureCurve(curveOrig, doublingCoord);
+
+            int[] naf = WNafUtilities.GenerateCompactNaf(k);
+
+            ECPoint Ra = curveAdd.Infinity;
+            ECPoint Td = curveDouble.ImportPoint(p);
+
+            int zeroes = 0;
+            for (int i = 0; i < naf.Length; ++i)
+            {
+                int ni = naf[i];
+                int digit = ni >> 16;
+                zeroes += ni & 0xFFFF;
+
+                Td = Td.TimesPow2(zeroes);
+
+                ECPoint Tj = curveAdd.ImportPoint(Td);
+                if (digit < 0)
+                {
+                    Tj = Tj.Negate();
+                }
+
+                Ra = Ra.Add(Tj);
+
+                zeroes = 1;
+            }
+
+            return curveOrig.ImportPoint(Ra);
+        }
+
+        protected virtual ECCurve ConfigureCurve(ECCurve c, int coord)
+        {
+            if (c.CoordinateSystem == coord)
+                return c;
+
+            if (!c.SupportsCoordinateSystem(coord))
+                throw new ArgumentException("Coordinate system " + coord + " not supported by this curve", "coord");
+
+            return c.Configure().SetCoordinateSystem(coord).Create();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs
new file mode 100644
index 0000000..e2470a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/MontgomeryLadderMultiplier.cs
@@ -0,0 +1,25 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class MontgomeryLadderMultiplier 
+        : AbstractECMultiplier
+    {
+        /**
+         * Montgomery ladder.
+         */
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECPoint[] R = new ECPoint[]{ p.Curve.Infinity, p };
+
+            int n = k.BitLength;
+            int i = n;
+            while (--i >= 0)
+            {
+                int b = k.TestBit(i) ? 1 : 0;
+                int bp = 1 - b;
+                R[bp] = R[bp].Add(R[b]);
+                R[b] = R[b].Twice();
+            }
+            return R[0];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafL2RMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafL2RMultiplier.cs
new file mode 100644
index 0000000..ac80cf9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafL2RMultiplier.cs
@@ -0,0 +1,30 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+     * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (left-to-right).
+     */
+    public class NafL2RMultiplier
+        : AbstractECMultiplier
+    {
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            int[] naf = WNafUtilities.GenerateCompactNaf(k);
+
+            ECPoint addP = p.Normalize(), subP = addP.Negate();
+
+            ECPoint R = p.Curve.Infinity;
+
+            int i = naf.Length;
+            while (--i >= 0)
+            {
+                int ni = naf[i];
+                int digit = ni >> 16, zeroes = ni & 0xFFFF;
+
+                R = R.TwicePlus(digit < 0 ? subP : addP);
+                R = R.TimesPow2(zeroes);
+            }
+
+            return R;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafR2LMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafR2LMultiplier.cs
new file mode 100644
index 0000000..1fa69fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/NafR2LMultiplier.cs
@@ -0,0 +1,31 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+     * Class implementing the NAF (Non-Adjacent Form) multiplication algorithm (right-to-left).
+     */
+    public class NafR2LMultiplier 
+        : AbstractECMultiplier
+    {
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            int[] naf = WNafUtilities.GenerateCompactNaf(k);
+
+            ECPoint R0 = p.Curve.Infinity, R1 = p;
+
+            int zeroes = 0;
+            for (int i = 0; i < naf.Length; ++i)
+            {
+                int ni = naf[i];
+                int digit = ni >> 16;
+                zeroes += ni & 0xFFFF;
+
+                R1 = R1.TimesPow2(zeroes);
+                R0 = R0.Add(digit < 0 ? R1.Negate() : R1);
+
+                zeroes = 1;
+            }
+
+            return R0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/PreCompInfo.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/PreCompInfo.cs
new file mode 100644
index 0000000..5c32892
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/PreCompInfo.cs
@@ -0,0 +1,11 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+	/**
+	* Interface for classes storing precomputation data for multiplication
+	* algorithms. Used as a Memento (see GOF patterns) for
+	* <code>WNafMultiplier</code>.
+	*/
+	public interface PreCompInfo
+	{
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/ReferenceMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ReferenceMultiplier.cs
new file mode 100644
index 0000000..4848ada
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ReferenceMultiplier.cs
@@ -0,0 +1,11 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class ReferenceMultiplier
+        : AbstractECMultiplier
+    {
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            return ECAlgorithms.ReferenceMultiply(p, k);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafL2RMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafL2RMultiplier.cs
new file mode 100644
index 0000000..f671f6a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafL2RMultiplier.cs
@@ -0,0 +1,98 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+    * Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+    * algorithm.
+    */
+    public class WNafL2RMultiplier
+        : AbstractECMultiplier
+    {
+        /**
+         * Multiplies <code>this</code> by an integer <code>k</code> using the
+         * Window NAF method.
+         * @param k The integer by which <code>this</code> is multiplied.
+         * @return A new <code>ECPoint</code> which equals <code>this</code>
+         * multiplied by <code>k</code>.
+         */
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            // Clamp the window width in the range [2, 16]
+            int width = System.Math.Max(2, System.Math.Min(16, GetWindowSize(k.BitLength)));
+
+            WNafPreCompInfo wnafPreCompInfo = WNafUtilities.Precompute(p, width, true);
+            ECPoint[] preComp = wnafPreCompInfo.PreComp;
+            ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
+
+            int[] wnaf = WNafUtilities.GenerateCompactWindowNaf(width, k);
+
+            ECPoint R = p.Curve.Infinity;
+
+            int i = wnaf.Length;
+
+            /*
+             * NOTE: We try to optimize the first window using the precomputed points to substitute an
+             * addition for 2 or more doublings.
+             */
+            if (i > 1)
+            {
+                int wi = wnaf[--i];
+                int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+                int n = System.Math.Abs(digit);
+                ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+
+                // Optimization can only be used for values in the lower half of the table
+                if ((n << 2) < (1 << width))
+                {
+                    int highest = LongArray.BitLengths[n];
+
+                    // TODO Get addition/doubling cost ratio from curve and compare to 'scale' to see if worth substituting?
+                    int scale = width - highest;
+                    int lowBits = n ^ (1 << (highest - 1));
+
+                    int i1 = ((1 << (width - 1)) - 1);
+                    int i2 = (lowBits << scale) + 1;
+                    R = table[i1 >> 1].Add(table[i2 >> 1]);
+
+                    zeroes -= scale;
+
+                    //Console.WriteLine("Optimized: 2^" + scale + " * " + n + " = " + i1 + " + " + i2);
+                }
+                else
+                {
+                    R = table[n >> 1];
+                }
+
+                R = R.TimesPow2(zeroes);
+            }
+
+            while (i > 0)
+            {
+                int wi = wnaf[--i];
+                int digit = wi >> 16, zeroes = wi & 0xFFFF;
+
+                int n = System.Math.Abs(digit);
+                ECPoint[] table = digit < 0 ? preCompNeg : preComp;
+                ECPoint r = table[n >> 1];
+
+                R = R.TwicePlus(r);
+                R = R.TimesPow2(zeroes);
+            }
+
+            return R;
+        }
+
+        /**
+         * Determine window width to use for a scalar multiplication of the given size.
+         * 
+         * @param bits the bit-length of the scalar to multiply by
+         * @return the window size to use
+         */
+        protected virtual int GetWindowSize(int bits)
+        {
+            return WNafUtilities.GetWindowSize(bits);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafMultiplier.cs
new file mode 100644
index 0000000..b5cf34b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafMultiplier.cs
@@ -0,0 +1,241 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+	/**
+	* Class implementing the WNAF (Window Non-Adjacent Form) multiplication
+	* algorithm.
+	*/
+	internal class WNafMultiplier
+		: ECMultiplier 
+	{
+		/**
+		* Computes the Window NAF (non-adjacent Form) of an integer.
+		* @param width The width <code>w</code> of the Window NAF. The width is
+		* defined as the minimal number <code>w</code>, such that for any
+		* <code>w</code> consecutive digits in the resulting representation, at
+		* most one is non-zero.
+		* @param k The integer of which the Window NAF is computed.
+		* @return The Window NAF of the given width, such that the following holds:
+		* <code>k = −<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+		* </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+		* returned <code>sbyte[]</code>.
+		*/
+		public sbyte[] WindowNaf(sbyte width, BigInteger k)
+		{
+			// The window NAF is at most 1 element longer than the binary
+			// representation of the integer k. sbyte can be used instead of short or
+			// int unless the window width is larger than 8. For larger width use
+			// short or int. However, a width of more than 8 is not efficient for
+			// m = log2(q) smaller than 2305 Bits. Note: Values for m larger than
+			// 1000 Bits are currently not used in practice.
+			sbyte[] wnaf = new sbyte[k.BitLength + 1];
+
+			// 2^width as short and BigInteger
+			short pow2wB = (short)(1 << width);
+			BigInteger pow2wBI = BigInteger.ValueOf(pow2wB);
+
+			int i = 0;
+
+			// The actual length of the WNAF
+			int length = 0;
+
+			// while k >= 1
+			while (k.SignValue > 0)
+			{
+				// if k is odd
+				if (k.TestBit(0))
+				{
+					// k Mod 2^width
+					BigInteger remainder = k.Mod(pow2wBI);
+
+					// if remainder > 2^(width - 1) - 1
+					if (remainder.TestBit(width - 1))
+					{
+						wnaf[i] = (sbyte)(remainder.IntValue - pow2wB);
+					}
+					else
+					{
+						wnaf[i] = (sbyte)remainder.IntValue;
+					}
+					// wnaf[i] is now in [-2^(width-1), 2^(width-1)-1]
+
+					k = k.Subtract(BigInteger.ValueOf(wnaf[i]));
+					length = i;
+				}
+				else
+				{
+					wnaf[i] = 0;
+				}
+
+				// k = k/2
+				k = k.ShiftRight(1);
+				i++;
+			}
+
+			length++;
+
+			// Reduce the WNAF array to its actual length
+			sbyte[] wnafShort = new sbyte[length];
+			Array.Copy(wnaf, 0, wnafShort, 0, length);
+			return wnafShort;
+		}
+
+		/**
+		* Multiplies <code>this</code> by an integer <code>k</code> using the
+		* Window NAF method.
+		* @param k The integer by which <code>this</code> is multiplied.
+		* @return A new <code>ECPoint</code> which equals <code>this</code>
+		* multiplied by <code>k</code>.
+		*/
+		public ECPoint Multiply(ECPoint p, BigInteger k, PreCompInfo preCompInfo)
+		{
+			WNafPreCompInfo wnafPreCompInfo;
+
+			if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
+			{
+				wnafPreCompInfo = (WNafPreCompInfo)preCompInfo;
+			}
+			else
+			{
+				// Ignore empty PreCompInfo or PreCompInfo of incorrect type
+				wnafPreCompInfo = new WNafPreCompInfo();
+			}
+
+			// floor(log2(k))
+			int m = k.BitLength;
+
+			// width of the Window NAF
+			sbyte width;
+
+			// Required length of precomputation array
+			int reqPreCompLen;
+
+			// Determine optimal width and corresponding length of precomputation
+			// array based on literature values
+			if (m < 13)
+			{
+				width = 2;
+				reqPreCompLen = 1;
+			}
+			else
+			{
+				if (m < 41)
+				{
+					width = 3;
+					reqPreCompLen = 2;
+				}
+				else
+				{
+					if (m < 121)
+					{
+						width = 4;
+						reqPreCompLen = 4;
+					}
+					else
+					{
+						if (m < 337)
+						{
+							width = 5;
+							reqPreCompLen = 8;
+						}
+						else
+						{
+							if (m < 897)
+							{
+								width = 6;
+								reqPreCompLen = 16;
+							}
+							else
+							{
+								if (m < 2305)
+								{
+									width = 7;
+									reqPreCompLen = 32;
+								}
+								else 
+								{
+									width = 8;
+									reqPreCompLen = 127;
+								}
+							}
+						}
+					}
+				}
+			}
+
+			// The length of the precomputation array
+			int preCompLen = 1;
+
+			ECPoint[] preComp = wnafPreCompInfo.GetPreComp();
+			ECPoint twiceP = wnafPreCompInfo.GetTwiceP();
+
+			// Check if the precomputed ECPoints already exist
+			if (preComp == null)
+			{
+				// Precomputation must be performed from scratch, create an empty
+				// precomputation array of desired length
+				preComp = new ECPoint[]{ p };
+			}
+			else
+			{
+				// Take the already precomputed ECPoints to start with
+				preCompLen = preComp.Length;
+			}
+
+			if (twiceP == null)
+			{
+				// Compute twice(p)
+				twiceP = p.Twice();
+			}
+
+			if (preCompLen < reqPreCompLen)
+			{
+				// Precomputation array must be made bigger, copy existing preComp
+				// array into the larger new preComp array
+				ECPoint[] oldPreComp = preComp;
+				preComp = new ECPoint[reqPreCompLen];
+				Array.Copy(oldPreComp, 0, preComp, 0, preCompLen);
+
+				for (int i = preCompLen; i < reqPreCompLen; i++)
+				{
+					// Compute the new ECPoints for the precomputation array.
+					// The values 1, 3, 5, ..., 2^(width-1)-1 times p are
+					// computed
+					preComp[i] = twiceP.Add(preComp[i - 1]);
+				}            
+			}
+
+			// Compute the Window NAF of the desired width
+			sbyte[] wnaf = WindowNaf(width, k);
+			int l = wnaf.Length;
+
+			// Apply the Window NAF to p using the precomputed ECPoint values.
+			ECPoint q = p.Curve.Infinity;
+			for (int i = l - 1; i >= 0; i--)
+			{
+				q = q.Twice();
+
+				if (wnaf[i] != 0)
+				{
+					if (wnaf[i] > 0)
+					{
+						q = q.Add(preComp[(wnaf[i] - 1)/2]);
+					}
+					else
+					{
+						// wnaf[i] < 0
+						q = q.Subtract(preComp[(-wnaf[i] - 1)/2]);
+					}
+				}
+			}
+
+			// Set PreCompInfo in ECPoint, such that it is available for next
+			// multiplication.
+			wnafPreCompInfo.SetPreComp(preComp);
+			wnafPreCompInfo.SetTwiceP(twiceP);
+			p.SetPreCompInfo(wnafPreCompInfo);
+			return q;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafPreCompInfo.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafPreCompInfo.cs
new file mode 100644
index 0000000..7e0a731
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafPreCompInfo.cs
@@ -0,0 +1,46 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+    * Class holding precomputation data for the WNAF (Window Non-Adjacent Form)
+    * algorithm.
+    */
+    public class WNafPreCompInfo
+        : PreCompInfo 
+    {
+        /**
+         * Array holding the precomputed <code>ECPoint</code>s used for a Window
+         * NAF multiplication.
+         */
+        protected ECPoint[] m_preComp = null;
+
+        /**
+         * Array holding the negations of the precomputed <code>ECPoint</code>s used
+         * for a Window NAF multiplication.
+         */
+        protected ECPoint[] m_preCompNeg = null;
+
+        /**
+         * Holds an <code>ECPoint</code> representing Twice(this). Used for the
+         * Window NAF multiplication to create or extend the precomputed values.
+         */
+        protected ECPoint m_twice = null;
+
+        public virtual ECPoint[] PreComp
+        {
+            get { return m_preComp; }
+            set { this.m_preComp = value; }
+        }
+
+        public virtual ECPoint[] PreCompNeg
+        {
+            get { return m_preCompNeg; }
+            set { this.m_preCompNeg = value; }
+        }
+
+        public virtual ECPoint Twice
+        {
+            get { return m_twice; }
+            set { this.m_twice = value; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafUtilities.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafUtilities.cs
new file mode 100644
index 0000000..865b907
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WNafUtilities.cs
@@ -0,0 +1,469 @@
+using System;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public abstract class WNafUtilities
+    {
+        public static readonly string PRECOMP_NAME = "bc_wnaf";
+
+        private static readonly int[] DEFAULT_WINDOW_SIZE_CUTOFFS = new int[]{ 13, 41, 121, 337, 897, 2305 };
+
+        private static readonly byte[] EMPTY_BYTES = new byte[0];
+        private static readonly int[] EMPTY_INTS = new int[0];
+
+        public static int[] GenerateCompactNaf(BigInteger k)
+        {
+            if ((k.BitLength >> 16) != 0)
+                throw new ArgumentException("must have bitlength < 2^16", "k");
+            if (k.SignValue == 0)
+                return EMPTY_INTS;
+
+            BigInteger _3k = k.ShiftLeft(1).Add(k);
+
+            int bits = _3k.BitLength;
+            int[] naf = new int[bits >> 1];
+
+            BigInteger diff = _3k.Xor(k);
+
+            int highBit = bits - 1, length = 0, zeroes = 0;
+            for (int i = 1; i < highBit; ++i)
+            {
+                if (!diff.TestBit(i))
+                {
+                    ++zeroes;
+                    continue;
+                }
+
+                int digit = k.TestBit(i) ? -1 : 1;
+                naf[length++] = (digit << 16) | zeroes;
+                zeroes = 1;
+                ++i;
+            }
+
+            naf[length++] = (1 << 16) | zeroes;
+
+            if (naf.Length > length)
+            {
+                naf = Trim(naf, length);
+            }
+
+            return naf;
+        }
+
+        public static int[] GenerateCompactWindowNaf(int width, BigInteger k)
+        {
+            if (width == 2)
+            {
+                return GenerateCompactNaf(k);
+            }
+
+            if (width < 2 || width > 16)
+                throw new ArgumentException("must be in the range [2, 16]", "width");
+            if ((k.BitLength >> 16) != 0)
+                throw new ArgumentException("must have bitlength < 2^16", "k");
+            if (k.SignValue == 0)
+                return EMPTY_INTS;
+
+            int[] wnaf = new int[k.BitLength / width + 1];
+
+            // 2^width and a mask and sign bit set accordingly
+            int pow2 = 1 << width;
+            int mask = pow2 - 1;
+            int sign = pow2 >> 1;
+
+            bool carry = false;
+            int length = 0, pos = 0;
+
+            while (pos <= k.BitLength)
+            {
+                if (k.TestBit(pos) == carry)
+                {
+                    ++pos;
+                    continue;
+                }
+
+                k = k.ShiftRight(pos);
+
+                int digit = k.IntValue & mask;
+                if (carry)
+                {
+                    ++digit;
+                }
+
+                carry = (digit & sign) != 0;
+                if (carry)
+                {
+                    digit -= pow2;
+                }
+
+                int zeroes = length > 0 ? pos - 1 : pos;
+                wnaf[length++] = (digit << 16) | zeroes;
+                pos = width;
+            }
+
+            // Reduce the WNAF array to its actual length
+            if (wnaf.Length > length)
+            {
+                wnaf = Trim(wnaf, length);
+            }
+
+            return wnaf;
+        }
+
+        public static byte[] GenerateJsf(BigInteger g, BigInteger h)
+        {
+            int digits = System.Math.Max(g.BitLength, h.BitLength) + 1;
+            byte[] jsf = new byte[digits];
+
+            BigInteger k0 = g, k1 = h;
+            int j = 0, d0 = 0, d1 = 0;
+
+            int offset = 0;
+            while ((d0 | d1) != 0 || k0.BitLength > offset || k1.BitLength > offset)
+            {
+                int n0 = ((int)((uint)k0.IntValue >> offset) + d0) & 7;
+                int n1 = ((int)((uint)k1.IntValue >> offset) + d1) & 7;
+
+                int u0 = n0 & 1;
+                if (u0 != 0)
+                {
+                    u0 -= (n0 & 2);
+                    if ((n0 + u0) == 4 && (n1 & 3) == 2)
+                    {
+                        u0 = -u0;
+                    }
+                }
+
+                int u1 = n1 & 1;
+                if (u1 != 0)
+                {
+                    u1 -= (n1 & 2);
+                    if ((n1 + u1) == 4 && (n0 & 3) == 2)
+                    {
+                        u1 = -u1;
+                    }
+                }
+
+                if ((d0 << 1) == 1 + u0)
+                {
+                    d0 ^= 1;
+                }
+                if ((d1 << 1) == 1 + u1)
+                {
+                    d1 ^= 1;
+                }
+
+                if (++offset == 30)
+                {
+                    offset = 0;
+                    k0 = k0.ShiftRight(30);
+                    k1 = k1.ShiftRight(30);
+                }
+
+                jsf[j++] = (byte)((u0 << 4) | (u1 & 0xF));
+            }
+
+            // Reduce the JSF array to its actual length
+            if (jsf.Length > j)
+            {
+                jsf = Trim(jsf, j);
+            }
+
+            return jsf;
+        }
+
+        public static byte[] GenerateNaf(BigInteger k)
+        {
+            if (k.SignValue == 0)
+                return EMPTY_BYTES;
+
+            BigInteger _3k = k.ShiftLeft(1).Add(k);
+
+            int digits = _3k.BitLength - 1;
+            byte[] naf = new byte[digits];
+
+            BigInteger diff = _3k.Xor(k);
+
+            for (int i = 1; i < digits; ++i)
+            {
+                if (diff.TestBit(i))
+                {
+                    naf[i - 1] = (byte)(k.TestBit(i) ? -1 : 1);
+                    ++i;
+                }
+            }
+
+            naf[digits - 1] = 1;
+
+            return naf;
+        }
+
+        /**
+         * Computes the Window NAF (non-adjacent Form) of an integer.
+         * @param width The width <code>w</code> of the Window NAF. The width is
+         * defined as the minimal number <code>w</code>, such that for any
+         * <code>w</code> consecutive digits in the resulting representation, at
+         * most one is non-zero.
+         * @param k The integer of which the Window NAF is computed.
+         * @return The Window NAF of the given width, such that the following holds:
+         * <code>k = &sum;<sub>i=0</sub><sup>l-1</sup> k<sub>i</sub>2<sup>i</sup>
+         * </code>, where the <code>k<sub>i</sub></code> denote the elements of the
+         * returned <code>byte[]</code>.
+         */
+        public static byte[] GenerateWindowNaf(int width, BigInteger k)
+        {
+            if (width == 2)
+            {
+                return GenerateNaf(k);
+            }
+
+            if (width < 2 || width > 8)
+                throw new ArgumentException("must be in the range [2, 8]", "width");
+            if (k.SignValue == 0)
+                return EMPTY_BYTES;
+
+            byte[] wnaf = new byte[k.BitLength + 1];
+
+            // 2^width and a mask and sign bit set accordingly
+            int pow2 = 1 << width;
+            int mask = pow2 - 1;
+            int sign = pow2 >> 1;
+
+            bool carry = false;
+            int length = 0, pos = 0;
+
+            while (pos <= k.BitLength)
+            {
+                if (k.TestBit(pos) == carry)
+                {
+                    ++pos;
+                    continue;
+                }
+
+                k = k.ShiftRight(pos);
+
+                int digit = k.IntValue & mask;
+                if (carry)
+                {
+                    ++digit;
+                }
+
+                carry = (digit & sign) != 0;
+                if (carry)
+                {
+                    digit -= pow2;
+                }
+
+                length += (length > 0) ? pos - 1 : pos;
+                wnaf[length++] = (byte)digit;
+                pos = width;
+            }
+
+            // Reduce the WNAF array to its actual length
+            if (wnaf.Length > length)
+            {
+                wnaf = Trim(wnaf, length);
+            }
+        
+            return wnaf;
+        }
+
+        public static int GetNafWeight(BigInteger k)
+        {
+            if (k.SignValue == 0)
+                return 0;
+
+            BigInteger _3k = k.ShiftLeft(1).Add(k);
+            BigInteger diff = _3k.Xor(k);
+
+            return diff.BitCount;
+        }
+
+        public static WNafPreCompInfo GetWNafPreCompInfo(ECPoint p)
+        {
+            return GetWNafPreCompInfo(p.Curve.GetPreCompInfo(p, PRECOMP_NAME));
+        }
+
+        public static WNafPreCompInfo GetWNafPreCompInfo(PreCompInfo preCompInfo)
+        {
+            if ((preCompInfo != null) && (preCompInfo is WNafPreCompInfo))
+            {
+                return (WNafPreCompInfo)preCompInfo;
+            }
+
+            return new WNafPreCompInfo();
+        }
+
+        /**
+         * Determine window width to use for a scalar multiplication of the given size.
+         * 
+         * @param bits the bit-length of the scalar to multiply by
+         * @return the window size to use
+         */
+        public static int GetWindowSize(int bits)
+        {
+            return GetWindowSize(bits, DEFAULT_WINDOW_SIZE_CUTOFFS);
+        }
+
+        /**
+         * Determine window width to use for a scalar multiplication of the given size.
+         * 
+         * @param bits the bit-length of the scalar to multiply by
+         * @param windowSizeCutoffs a monotonically increasing list of bit sizes at which to increment the window width
+         * @return the window size to use
+         */
+        public static int GetWindowSize(int bits, int[] windowSizeCutoffs)
+        {
+            int w = 0;
+            for (; w < windowSizeCutoffs.Length; ++w)
+            {
+                if (bits < windowSizeCutoffs[w])
+                {
+                    break;
+                }
+            }
+            return w + 2;
+        }
+
+        public static ECPoint MapPointWithPrecomp(ECPoint p, int width, bool includeNegated,
+            ECPointMap pointMap)
+        {
+            ECCurve c = p.Curve;
+            WNafPreCompInfo wnafPreCompP = Precompute(p, width, includeNegated);
+
+            ECPoint q = pointMap.Map(p);
+            WNafPreCompInfo wnafPreCompQ = GetWNafPreCompInfo(c.GetPreCompInfo(q, PRECOMP_NAME));
+
+            ECPoint twiceP = wnafPreCompP.Twice;
+            if (twiceP != null)
+            {
+                ECPoint twiceQ = pointMap.Map(twiceP);
+                wnafPreCompQ.Twice = twiceQ;
+            }
+
+            ECPoint[] preCompP = wnafPreCompP.PreComp;
+            ECPoint[] preCompQ = new ECPoint[preCompP.Length];
+            for (int i = 0; i < preCompP.Length; ++i)
+            {
+                preCompQ[i] = pointMap.Map(preCompP[i]);
+            }
+            wnafPreCompQ.PreComp = preCompQ;
+
+            if (includeNegated)
+            {
+                ECPoint[] preCompNegQ = new ECPoint[preCompQ.Length];
+                for (int i = 0; i < preCompNegQ.Length; ++i)
+                {
+                    preCompNegQ[i] = preCompQ[i].Negate();
+                }
+                wnafPreCompQ.PreCompNeg = preCompNegQ;
+            }
+
+            c.SetPreCompInfo(q, PRECOMP_NAME, wnafPreCompQ);
+
+            return q;
+        }
+
+        public static WNafPreCompInfo Precompute(ECPoint p, int width, bool includeNegated)
+        {
+            ECCurve c = p.Curve;
+            WNafPreCompInfo wnafPreCompInfo = GetWNafPreCompInfo(c.GetPreCompInfo(p, PRECOMP_NAME));
+            
+            ECPoint[] preComp = wnafPreCompInfo.PreComp;
+            if (preComp == null)
+            {
+                preComp = new ECPoint[]{ p };
+            }
+
+            int preCompLen = preComp.Length;
+            int reqPreCompLen = 1 << System.Math.Max(0, width - 2);
+
+            if (preCompLen < reqPreCompLen)
+            {
+                preComp = ResizeTable(preComp, reqPreCompLen);
+                if (reqPreCompLen == 2)
+                {
+                    preComp[1] = preComp[0].ThreeTimes();
+                }
+                else
+                {
+                    ECPoint twiceP = wnafPreCompInfo.Twice;
+                    if (twiceP == null)
+                    {
+                        twiceP = preComp[0].Twice();
+                        wnafPreCompInfo.Twice = twiceP;
+                    }
+
+                    for (int i = preCompLen; i < reqPreCompLen; i++)
+                    {
+                        /*
+                         * Compute the new ECPoints for the precomputation array. The values 1, 3, 5, ...,
+                         * 2^(width-1)-1 times p are computed
+                         */
+                        preComp[i] = twiceP.Add(preComp[i - 1]);
+                    }
+                }
+
+                /*
+                 * Having oft-used operands in affine form makes operations faster.
+                 */
+                c.NormalizeAll(preComp);
+            }
+
+            wnafPreCompInfo.PreComp = preComp;
+
+            if (includeNegated)
+            {
+                ECPoint[] preCompNeg = wnafPreCompInfo.PreCompNeg;
+
+                int pos;
+                if (preCompNeg == null)
+                {
+                    pos = 0;
+                    preCompNeg = new ECPoint[reqPreCompLen]; 
+                }
+                else
+                {
+                    pos = preCompNeg.Length;
+                    if (pos < reqPreCompLen)
+                    {
+                        preCompNeg = ResizeTable(preCompNeg, reqPreCompLen);
+                    }
+                }
+
+                while (pos < reqPreCompLen)
+                {
+                    preCompNeg[pos] = preComp[pos].Negate();
+                    ++pos;
+                }
+
+                wnafPreCompInfo.PreCompNeg = preCompNeg;
+            }
+
+            c.SetPreCompInfo(p, PRECOMP_NAME, wnafPreCompInfo);
+
+            return wnafPreCompInfo;
+        }
+
+        private static byte[] Trim(byte[] a, int length)
+        {
+            byte[] result = new byte[length];
+            Array.Copy(a, 0, result, 0, result.Length);
+            return result;
+        }
+
+        private static int[] Trim(int[] a, int length)
+        {
+            int[] result = new int[length];
+            Array.Copy(a, 0, result, 0, result.Length);
+            return result;
+        }
+
+        private static ECPoint[] ResizeTable(ECPoint[] a, int length)
+        {
+            ECPoint[] result = new ECPoint[length];
+            Array.Copy(a, 0, result, 0, a.Length);
+            return result;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafMultiplier.cs
new file mode 100644
index 0000000..dda778e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafMultiplier.cs
@@ -0,0 +1,116 @@
+using System;
+
+using Org.BouncyCastle.Math.EC.Abc;
+
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+    * Class implementing the WTNAF (Window
+    * <code>τ</code>-adic Non-Adjacent Form) algorithm.
+    */
+    public class WTauNafMultiplier
+        : AbstractECMultiplier
+    {
+        // TODO Create WTauNafUtilities class and move various functionality into it
+        internal static readonly string PRECOMP_NAME = "bc_wtnaf";
+
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by <code>k</code> using the reduced <code>τ</code>-adic NAF (RTNAF)
+        * method.
+        * @param p The F2mPoint to multiply.
+        * @param k The integer by which to multiply <code>k</code>.
+        * @return <code>p</code> multiplied by <code>k</code>.
+        */
+        protected override ECPoint MultiplyPositive(ECPoint point, BigInteger k)
+        {
+            if (!(point is F2mPoint))
+                throw new ArgumentException("Only F2mPoint can be used in WTauNafMultiplier");
+
+            F2mPoint p = (F2mPoint)point;
+            F2mCurve curve = (F2mCurve)p.Curve;
+            int m = curve.M;
+            sbyte a = (sbyte) curve.A.ToBigInteger().IntValue;
+            sbyte mu = curve.GetMu();
+            BigInteger[] s = curve.GetSi();
+
+            ZTauElement rho = Tnaf.PartModReduction(k, m, a, s, mu, (sbyte)10);
+
+            return MultiplyWTnaf(p, rho, curve.GetPreCompInfo(p, PRECOMP_NAME), a, mu);
+        }
+
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by an element <code>λ</code> of <code><b>Z</b>[τ]</code> using
+        * the <code>τ</code>-adic NAF (TNAF) method.
+        * @param p The F2mPoint to multiply.
+        * @param lambda The element <code>λ</code> of
+        * <code><b>Z</b>[τ]</code> of which to compute the
+        * <code>[τ]</code>-adic NAF.
+        * @return <code>p</code> multiplied by <code>λ</code>.
+        */
+        private F2mPoint MultiplyWTnaf(F2mPoint p, ZTauElement lambda,
+            PreCompInfo preCompInfo, sbyte a, sbyte mu)
+        {
+            ZTauElement[] alpha = (a == 0) ? Tnaf.Alpha0 : Tnaf.Alpha1;
+
+            BigInteger tw = Tnaf.GetTw(mu, Tnaf.Width);
+
+            sbyte[]u = Tnaf.TauAdicWNaf(mu, lambda, Tnaf.Width,
+                BigInteger.ValueOf(Tnaf.Pow2Width), tw, alpha);
+
+            return MultiplyFromWTnaf(p, u, preCompInfo);
+        }
+        
+        /**
+        * Multiplies a {@link org.bouncycastle.math.ec.F2mPoint F2mPoint}
+        * by an element <code>λ</code> of <code><b>Z</b>[τ]</code>
+        * using the window <code>τ</code>-adic NAF (TNAF) method, given the
+        * WTNAF of <code>λ</code>.
+        * @param p The F2mPoint to multiply.
+        * @param u The the WTNAF of <code>λ</code>..
+        * @return <code>λ * p</code>
+        */
+        private static F2mPoint MultiplyFromWTnaf(F2mPoint p, sbyte[] u, PreCompInfo preCompInfo)
+        {
+            F2mCurve curve = (F2mCurve)p.Curve;
+            sbyte a = (sbyte)curve.A.ToBigInteger().IntValue;
+
+            F2mPoint[] pu;
+            if ((preCompInfo == null) || !(preCompInfo is WTauNafPreCompInfo))
+            {
+                pu = Tnaf.GetPreComp(p, a);
+
+                WTauNafPreCompInfo pre = new WTauNafPreCompInfo();
+                pre.PreComp = pu;
+                curve.SetPreCompInfo(p, PRECOMP_NAME, pre);
+            }
+            else
+            {
+                pu = ((WTauNafPreCompInfo)preCompInfo).PreComp;
+            }
+
+            // q = infinity
+            F2mPoint q = (F2mPoint)curve.Infinity;
+            for (int i = u.Length - 1; i >= 0; i--)
+            {
+                q = Tnaf.Tau(q);
+                sbyte ui = u[i];
+                if (ui != 0)
+                {
+                    if (ui > 0)
+                    {
+                        q = q.AddSimple(pu[ui]);
+                    }
+                    else
+                    {
+                        // u[i] < 0
+                        q = q.SubtractSimple(pu[-ui]);
+                    }
+                }
+            }
+
+            return q;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafPreCompInfo.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafPreCompInfo.cs
new file mode 100644
index 0000000..3c18404
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/WTauNafPreCompInfo.cs
@@ -0,0 +1,24 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    /**
+     * Class holding precomputation data for the WTNAF (Window
+     * <code>τ</code>-adic Non-Adjacent Form) algorithm.
+     */
+    public class WTauNafPreCompInfo
+        : PreCompInfo
+    {
+        /**
+         * Array holding the precomputed <code>F2mPoint</code>s used for the
+         * WTNAF multiplication in <code>
+         * {@link org.bouncycastle.math.ec.multiplier.WTauNafMultiplier.multiply()
+         * WTauNafMultiplier.multiply()}</code>.
+         */
+        protected F2mPoint[] m_preComp;
+
+        public virtual F2mPoint[] PreComp
+        {
+            get { return m_preComp; }
+            set { this.m_preComp = value; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs
new file mode 100644
index 0000000..554ac61
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitL2RMultiplier.cs
@@ -0,0 +1,29 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class ZSignedDigitL2RMultiplier 
+        : AbstractECMultiplier
+    {
+        /**
+         * 'Zeroless' Signed Digit Left-to-Right.
+         */
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECPoint addP = p.Normalize(), subP = addP.Negate();
+
+            ECPoint R0 = addP;
+
+            int n = k.BitLength;
+            int s = k.GetLowestSetBit();
+
+            int i = n;
+            while (--i > s)
+            {
+                R0 = R0.TwicePlus(k.TestBit(i) ? addP : subP);
+            }
+
+            R0 = R0.TimesPow2(s);
+
+            return R0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs
new file mode 100644
index 0000000..91c06cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/ec/multiplier/ZSignedDigitR2LMultiplier.cs
@@ -0,0 +1,30 @@
+namespace Org.BouncyCastle.Math.EC.Multiplier
+{
+    public class ZSignedDigitR2LMultiplier 
+        : AbstractECMultiplier
+    {
+        /**
+         * 'Zeroless' Signed Digit Right-to-Left.
+         */
+        protected override ECPoint MultiplyPositive(ECPoint p, BigInteger k)
+        {
+            ECPoint R0 = p.Curve.Infinity, R1 = p;
+
+            int n = k.BitLength;
+            int s = k.GetLowestSetBit();
+
+            R1 = R1.TimesPow2(s);
+
+            int i = s;
+            while (++i < n)
+            {
+                R0 = R0.Add(k.TestBit(i) ? R1 : R1.Negate());
+                R1 = R1.Twice();
+            }
+
+            R0 = R0.Add(R1);
+
+            return R0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/FiniteFields.cs b/BouncyCastle.AxCrypt/src/math/field/FiniteFields.cs
new file mode 100644
index 0000000..7b84569
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/FiniteFields.cs
@@ -0,0 +1,54 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    public abstract class FiniteFields
+    {
+        internal static readonly IFiniteField GF_2 = new PrimeField(BigInteger.ValueOf(2));
+        internal static readonly IFiniteField GF_3 = new PrimeField(BigInteger.ValueOf(3));
+
+        public static IPolynomialExtensionField GetBinaryExtensionField(int[] exponents)
+        {
+            if (exponents[0] != 0)
+            {
+                throw new ArgumentException("Irreducible polynomials in GF(2) must have constant term", "exponents");
+            }
+            for (int i = 1; i < exponents.Length; ++i)
+            {
+                if (exponents[i] <= exponents[i - 1])
+                {
+                    throw new ArgumentException("Polynomial exponents must be montonically increasing", "exponents");
+                }
+            }
+
+            return new GenericPolynomialExtensionField(GF_2, new GF2Polynomial(exponents));
+        }
+
+    //    public static IPolynomialExtensionField GetTernaryExtensionField(Term[] terms)
+    //    {
+    //        return new GenericPolynomialExtensionField(GF_3, new GF3Polynomial(terms));
+    //    }
+
+        public static IFiniteField GetPrimeField(BigInteger characteristic)
+        {
+            int bitLength = characteristic.BitLength;
+            if (characteristic.SignValue <= 0 || bitLength < 2)
+            {
+                throw new ArgumentException("Must be >= 2", "characteristic");
+            }
+
+            if (bitLength < 3)
+            {
+                switch (characteristic.IntValue)
+                {
+                case 2:
+                    return GF_2;
+                case 3:
+                    return GF_3;
+                }
+            }
+
+            return new PrimeField(characteristic);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/GF2Polynomial.cs b/BouncyCastle.AxCrypt/src/math/field/GF2Polynomial.cs
new file mode 100644
index 0000000..c062d50
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/GF2Polynomial.cs
@@ -0,0 +1,46 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    internal class GF2Polynomial
+        : IPolynomial
+    {
+        protected readonly int[] exponents;
+
+        internal GF2Polynomial(int[] exponents)
+        {
+            this.exponents = Arrays.Clone(exponents);
+        }
+
+        public virtual int Degree
+        {
+            get { return exponents[exponents.Length - 1]; }
+        }
+
+        public virtual int[] GetExponentsPresent()
+        {
+            return Arrays.Clone(exponents);
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+            GF2Polynomial other = obj as GF2Polynomial;
+            if (null == other)
+            {
+                return false;
+            }
+            return Arrays.AreEqual(exponents, other.exponents);
+        }
+
+        public override int GetHashCode()
+        {
+            return Arrays.GetHashCode(exponents);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/GenericPolynomialExtensionField.cs b/BouncyCastle.AxCrypt/src/math/field/GenericPolynomialExtensionField.cs
new file mode 100644
index 0000000..13ef571
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/GenericPolynomialExtensionField.cs
@@ -0,0 +1,63 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    internal class GenericPolynomialExtensionField
+        : IPolynomialExtensionField
+    {
+        protected readonly IFiniteField subfield;
+        protected readonly IPolynomial minimalPolynomial;
+
+        internal GenericPolynomialExtensionField(IFiniteField subfield, IPolynomial polynomial)
+        {
+            this.subfield = subfield;
+            this.minimalPolynomial = polynomial;
+        }
+
+        public virtual BigInteger Characteristic
+        {
+            get { return subfield.Characteristic; }
+        }
+
+        public virtual int Dimension
+        {
+            get { return subfield.Dimension * minimalPolynomial.Degree; }
+        }
+
+        public virtual IFiniteField Subfield
+        {
+            get { return subfield; }
+        }
+
+        public virtual int Degree
+        {
+            get { return minimalPolynomial.Degree; }
+        }
+
+        public virtual IPolynomial MinimalPolynomial
+        {
+            get { return minimalPolynomial; }
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+            GenericPolynomialExtensionField other = obj as GenericPolynomialExtensionField;
+            if (null == other)
+            {
+                return false;
+            }
+            return subfield.Equals(other.subfield) && minimalPolynomial.Equals(other.minimalPolynomial);
+        }
+
+        public override int GetHashCode()
+        {
+            return subfield.GetHashCode() ^ Integers.RotateLeft(minimalPolynomial.GetHashCode(), 16);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/IExtensionField.cs b/BouncyCastle.AxCrypt/src/math/field/IExtensionField.cs
new file mode 100644
index 0000000..17f45c1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/IExtensionField.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    public interface IExtensionField
+        : IFiniteField
+    {
+        IFiniteField Subfield { get; }
+
+        int Degree { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/IFiniteField.cs b/BouncyCastle.AxCrypt/src/math/field/IFiniteField.cs
new file mode 100644
index 0000000..b618be7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/IFiniteField.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    public interface IFiniteField
+    {
+        BigInteger Characteristic { get; }
+
+        int Dimension { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/IPolynomial.cs b/BouncyCastle.AxCrypt/src/math/field/IPolynomial.cs
new file mode 100644
index 0000000..ad6dfb6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/IPolynomial.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    public interface IPolynomial
+    {
+        int Degree { get; }
+
+        //BigInteger[] GetCoefficients();
+
+        int[] GetExponentsPresent();
+
+        //Term[] GetNonZeroTerms();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/IPolynomialExtensionField.cs b/BouncyCastle.AxCrypt/src/math/field/IPolynomialExtensionField.cs
new file mode 100644
index 0000000..3818c18
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/IPolynomialExtensionField.cs
@@ -0,0 +1,10 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    public interface IPolynomialExtensionField
+        : IExtensionField
+    {
+        IPolynomial MinimalPolynomial { get; }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/math/field/PrimeField.cs b/BouncyCastle.AxCrypt/src/math/field/PrimeField.cs
new file mode 100644
index 0000000..f6ba629
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/math/field/PrimeField.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Math.Field
+{
+    internal class PrimeField
+        : IFiniteField
+    {
+        protected readonly BigInteger characteristic;
+
+        internal PrimeField(BigInteger characteristic)
+        {
+            this.characteristic = characteristic;
+        }
+
+        public virtual BigInteger Characteristic
+        {
+            get { return characteristic; }
+        }
+
+        public virtual int Dimension
+        {
+            get { return 1; }
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (this == obj)
+            {
+                return true;
+            }
+            PrimeField other = obj as PrimeField;
+            if (null == other)
+            {
+                return false;
+            }
+            return characteristic.Equals(other.characteristic);
+        }
+
+        public override int GetHashCode()
+        {
+            return characteristic.GetHashCode();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPResp.cs b/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPResp.cs
new file mode 100644
index 0000000..4253726
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPResp.cs
@@ -0,0 +1,220 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/// <remarks>
+	/// <code>
+	/// BasicOcspResponse ::= SEQUENCE {
+	///		tbsResponseData		ResponseData,
+	///		signatureAlgorithm	AlgorithmIdentifier,
+	///		signature			BIT STRING,
+	///		certs				[0] EXPLICIT SEQUENCE OF Certificate OPTIONAL
+	/// }
+	/// </code>
+	/// </remarks>
+	public class BasicOcspResp
+		: X509ExtensionBase
+	{
+		private readonly BasicOcspResponse	resp;
+		private readonly ResponseData		data;
+//		private readonly X509Certificate[]	chain;
+
+		public BasicOcspResp(
+			BasicOcspResponse resp)
+		{
+			this.resp = resp;
+			this.data = resp.TbsResponseData;
+		}
+
+		/// <returns>The DER encoding of the tbsResponseData field.</returns>
+		/// <exception cref="OcspException">In the event of an encoding error.</exception>
+		public byte[] GetTbsResponseData()
+		{
+			try
+			{
+				return data.GetDerEncoded();
+			}
+			catch (IOException e)
+			{
+				throw new OcspException("problem encoding tbsResponseData", e);
+			}
+		}
+
+		public int Version
+		{
+			get { return data.Version.Value.IntValue + 1; }
+		}
+
+		public RespID ResponderId
+		{
+			get { return new RespID(data.ResponderID); }
+		}
+
+		public DateTime ProducedAt
+		{
+			get { return data.ProducedAt.ToDateTime(); }
+		}
+
+		public SingleResp[] Responses
+		{
+			get
+			{
+				Asn1Sequence s = data.Responses;
+				SingleResp[] rs = new SingleResp[s.Count];
+
+				for (int i = 0; i != rs.Length; i++)
+				{
+					rs[i] = new SingleResp(SingleResponse.GetInstance(s[i]));
+				}
+
+				return rs;
+			}
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return data.ResponseExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return ResponseExtensions;
+		}
+
+		public string SignatureAlgName
+		{
+			get { return OcspUtilities.GetAlgorithmName(resp.SignatureAlgorithm.ObjectID); }
+		}
+
+		public string SignatureAlgOid
+		{
+			get { return resp.SignatureAlgorithm.ObjectID.Id; }
+		}
+
+		[Obsolete("RespData class is no longer required as all functionality is available on this class")]
+		public RespData GetResponseData()
+		{
+			return new RespData(data);
+		}
+
+		public byte[] GetSignature()
+		{
+			return resp.Signature.GetBytes();
+		}
+
+		private IList GetCertList()
+		{
+			// load the certificates and revocation lists if we have any
+
+			IList certs = Platform.CreateArrayList();
+			Asn1Sequence s = resp.Certs;
+
+			if (s != null)
+			{
+				foreach (Asn1Encodable ae in s)
+				{
+					try
+					{
+						certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded()));
+					}
+					catch (IOException ex)
+					{
+						throw new OcspException("can't re-encode certificate!", ex);
+					}
+					catch (CertificateException ex)
+					{
+						throw new OcspException("can't re-encode certificate!", ex);
+					}
+				}
+			}
+
+			return certs;
+		}
+
+		public X509Certificate[] GetCerts()
+		{
+			IList certs = GetCertList();
+            X509Certificate[] result = new X509Certificate[certs.Count];
+            for (int i = 0; i < certs.Count; ++i)
+            {
+                result[i] = (X509Certificate)certs[i];
+            }
+            return result;
+		}
+
+		/// <returns>The certificates, if any, associated with the response.</returns>
+		/// <exception cref="OcspException">In the event of an encoding error.</exception>
+		public IX509Store GetCertificates(
+			string type)
+		{
+			try
+			{
+				return X509StoreFactory.Create(
+					"Certificate/" + type,
+					new X509CollectionStoreParameters(this.GetCertList()));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("can't setup the CertStore", e);
+			}
+		}
+
+		/// <summary>
+		/// Verify the signature against the tbsResponseData object we contain.
+		/// </summary>
+		public bool Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			try
+			{
+				ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgName);
+				signature.Init(false, publicKey);
+				byte[] bs = data.GetDerEncoded();
+				signature.BlockUpdate(bs, 0, bs.Length);
+
+				return signature.VerifySignature(this.GetSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing sig: " + e, e);
+			}
+		}
+
+		/// <returns>The ASN.1 encoded representation of this object.</returns>
+		public byte[] GetEncoded()
+		{
+			return resp.GetEncoded();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			BasicOcspResp other = obj as BasicOcspResp;
+
+			if (other == null)
+				return false;
+
+			return resp.Equals(other.resp);
+		}
+
+		public override int GetHashCode()
+		{
+			return resp.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPRespGenerator.cs b/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPRespGenerator.cs
new file mode 100644
index 0000000..5ff4bd9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/BasicOCSPRespGenerator.cs
@@ -0,0 +1,318 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * Generator for basic OCSP response objects.
+	 */
+	public class BasicOcspRespGenerator
+	{
+		private readonly IList list = Platform.CreateArrayList();
+
+		private X509Extensions responseExtensions;
+		private RespID responderID;
+
+		private class ResponseObject
+		{
+			internal CertificateID         certId;
+			internal CertStatus            certStatus;
+			internal DerGeneralizedTime    thisUpdate;
+			internal DerGeneralizedTime    nextUpdate;
+			internal X509Extensions        extensions;
+
+			public ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DateTime			thisUpdate,
+				X509Extensions		extensions)
+				: this(certId, certStatus, new DerGeneralizedTime(thisUpdate), null, extensions)
+			{
+			}
+
+			public ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DateTime			thisUpdate,
+				DateTime			nextUpdate,
+				X509Extensions		extensions)
+				: this(certId, certStatus, new DerGeneralizedTime(thisUpdate), new DerGeneralizedTime(nextUpdate), extensions)
+			{
+			}
+
+			private ResponseObject(
+				CertificateID		certId,
+				CertificateStatus	certStatus,
+				DerGeneralizedTime	thisUpdate,
+				DerGeneralizedTime	nextUpdate,
+				X509Extensions		extensions)
+			{
+				this.certId = certId;
+
+				if (certStatus == null)
+				{
+					this.certStatus = new CertStatus();
+				}
+				else if (certStatus is UnknownStatus)
+				{
+					this.certStatus = new CertStatus(2, DerNull.Instance);
+				}
+				else
+				{
+					RevokedStatus rs = (RevokedStatus) certStatus;
+					CrlReason revocationReason = rs.HasRevocationReason
+						?	new CrlReason(rs.RevocationReason)
+						:	null;
+
+					this.certStatus = new CertStatus(
+						new RevokedInfo(new DerGeneralizedTime(rs.RevocationTime), revocationReason));
+				}
+
+				this.thisUpdate = thisUpdate;
+				this.nextUpdate = nextUpdate;
+
+				this.extensions = extensions;
+			}
+
+			public SingleResponse ToResponse()
+			{
+				return new SingleResponse(certId.ToAsn1Object(), certStatus, thisUpdate, nextUpdate, extensions);
+			}
+		}
+
+		/**
+		 * basic constructor
+		 */
+		public BasicOcspRespGenerator(
+			RespID responderID)
+		{
+			this.responderID = responderID;
+		}
+
+		/**
+		 * construct with the responderID to be the SHA-1 keyHash of the passed in public key.
+		 */
+		public BasicOcspRespGenerator(
+			AsymmetricKeyParameter publicKey)
+		{
+			this.responderID = new RespID(publicKey);
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param certStatus status of the certificate - null if okay
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, null));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, singleExtensions));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param nextUpdate date when next update should be requested
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			DateTime			nextUpdate,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, DateTime.UtcNow, nextUpdate, singleExtensions));
+		}
+
+		/**
+		 * Add a response for a particular Certificate ID.
+		 *
+		 * @param certID certificate ID details
+		 * @param thisUpdate date this response was valid on
+		 * @param nextUpdate date when next update should be requested
+		 * @param certStatus status of the certificate - null if okay
+		 * @param singleExtensions optional extensions
+		 */
+		public void AddResponse(
+			CertificateID		certID,
+			CertificateStatus	certStatus,
+			DateTime			thisUpdate,
+			DateTime			nextUpdate,
+			X509Extensions		singleExtensions)
+		{
+			list.Add(new ResponseObject(certID, certStatus, thisUpdate, nextUpdate, singleExtensions));
+		}
+
+		/**
+		 * Set the extensions for the response.
+		 *
+		 * @param responseExtensions the extension object to carry.
+		 */
+		public void SetResponseExtensions(
+			X509Extensions responseExtensions)
+		{
+			this.responseExtensions = responseExtensions;
+		}
+
+		private BasicOcspResp GenerateResponse(
+			string					signatureName,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				producedAt,
+			SecureRandom			random)
+		{
+			DerObjectIdentifier signingAlgorithm;
+			try
+			{
+				signingAlgorithm = OcspUtilities.GetAlgorithmOid(signatureName);
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("unknown signing algorithm specified", e);
+			}
+
+			Asn1EncodableVector responses = new Asn1EncodableVector();
+
+			foreach (ResponseObject respObj in list)
+			{
+				try
+				{
+					responses.Add(respObj.ToResponse());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating Request", e);
+				}
+			}
+
+			ResponseData tbsResp = new ResponseData(responderID.ToAsn1Object(), new DerGeneralizedTime(producedAt), new DerSequence(responses), responseExtensions);
+
+			ISigner sig = null;
+
+			try
+			{
+				sig = SignerUtilities.GetSigner(signatureName);
+
+				if (random != null)
+				{
+					sig.Init(true, new ParametersWithRandom(privateKey, random));
+				}
+				else
+				{
+					sig.Init(true, privateKey);
+				}
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception creating signature: " + e, e);
+			}
+
+			DerBitString bitSig = null;
+
+			try
+			{
+				byte[] encoded = tbsResp.GetDerEncoded();
+				sig.BlockUpdate(encoded, 0, encoded.Length);
+
+				bitSig = new DerBitString(sig.GenerateSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing TBSRequest: " + e, e);
+			}
+
+			AlgorithmIdentifier sigAlgId = OcspUtilities.GetSigAlgID(signingAlgorithm);
+
+			DerSequence chainSeq = null;
+			if (chain != null && chain.Length > 0)
+			{
+				Asn1EncodableVector v = new Asn1EncodableVector();
+				try
+				{
+					for (int i = 0; i != chain.Length; i++)
+					{
+						v.Add(
+							X509CertificateStructure.GetInstance(
+								Asn1Object.FromByteArray(chain[i].GetEncoded())));
+					}
+				}
+				catch (IOException e)
+				{
+					throw new OcspException("error processing certs", e);
+				}
+				catch (CertificateEncodingException e)
+				{
+					throw new OcspException("error encoding certs", e);
+				}
+
+				chainSeq = new DerSequence(v);
+			}
+
+			return new BasicOcspResp(new BasicOcspResponse(tbsResp, sigAlgId, bitSig, chainSeq));
+		}
+
+		public BasicOcspResp Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				thisUpdate)
+		{
+			return Generate(signingAlgorithm, privateKey, chain, thisUpdate, null);
+		}
+
+		public BasicOcspResp Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			DateTime				producedAt,
+			SecureRandom			random)
+		{
+			if (signingAlgorithm == null)
+			{
+				throw new ArgumentException("no signing algorithm specified");
+			}
+
+			return GenerateResponse(signingAlgorithm, privateKey, chain, producedAt, random);
+		}
+
+		/**
+		 * Return an IEnumerable of the signature names supported by the generator.
+		 *
+		 * @return an IEnumerable containing recognised names.
+		 */
+		public IEnumerable SignatureAlgNames
+		{
+			get { return OcspUtilities.AlgNames; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/CertificateID.cs b/BouncyCastle.AxCrypt/src/ocsp/CertificateID.cs
new file mode 100644
index 0000000..a8f0357
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/CertificateID.cs
@@ -0,0 +1,141 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class CertificateID
+	{
+		public const string HashSha1 = "1.3.14.3.2.26";
+
+		private readonly CertID id;
+
+		public CertificateID(
+			CertID id)
+		{
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			this.id = id;
+		}
+
+		/**
+		 * create from an issuer certificate and the serial number of the
+		 * certificate it signed.
+		 * @exception OcspException if any problems occur creating the id fields.
+		 */
+		public CertificateID(
+			string			hashAlgorithm,
+			X509Certificate	issuerCert,
+			BigInteger		serialNumber)
+		{
+			AlgorithmIdentifier hashAlg = new AlgorithmIdentifier(
+				new DerObjectIdentifier(hashAlgorithm), DerNull.Instance);
+
+			this.id = CreateCertID(hashAlg, issuerCert, new DerInteger(serialNumber));
+		}
+
+		public string HashAlgOid
+		{
+			get { return id.HashAlgorithm.ObjectID.Id; }
+		}
+
+		public byte[] GetIssuerNameHash()
+		{
+			return id.IssuerNameHash.GetOctets();
+		}
+
+		public byte[] GetIssuerKeyHash()
+		{
+			return id.IssuerKeyHash.GetOctets();
+		}
+
+		/**
+		 * return the serial number for the certificate associated
+		 * with this request.
+		 */
+		public BigInteger SerialNumber
+		{
+			get { return id.SerialNumber.Value; }
+		}
+
+		public bool MatchesIssuer(
+			X509Certificate	issuerCert)
+		{
+			return CreateCertID(id.HashAlgorithm, issuerCert, id.SerialNumber).Equals(id);
+		}
+
+		public CertID ToAsn1Object()
+		{
+			return id;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			CertificateID other = obj as CertificateID;
+
+			if (other == null)
+				return false;
+
+			return id.ToAsn1Object().Equals(other.id.ToAsn1Object());
+		}
+
+		public override int GetHashCode()
+		{
+			return id.ToAsn1Object().GetHashCode();
+		}
+
+
+		/**
+		 * Create a new CertificateID for a new serial number derived from a previous one
+		 * calculated for the same CA certificate.
+		 *
+		 * @param original the previously calculated CertificateID for the CA.
+		 * @param newSerialNumber the serial number for the new certificate of interest.
+		 *
+		 * @return a new CertificateID for newSerialNumber
+		 */
+		public static CertificateID DeriveCertificateID(CertificateID original, BigInteger newSerialNumber)
+		{
+			return new CertificateID(new CertID(original.id.HashAlgorithm, original.id.IssuerNameHash,
+				original.id.IssuerKeyHash, new DerInteger(newSerialNumber)));
+		}
+
+        private static CertID CreateCertID(
+			AlgorithmIdentifier	hashAlg,
+			X509Certificate		issuerCert,
+			DerInteger			serialNumber)
+		{
+			try
+			{
+				String hashAlgorithm = hashAlg.ObjectID.Id;
+
+				X509Name issuerName = PrincipalUtilities.GetSubjectX509Principal(issuerCert);
+				byte[] issuerNameHash = DigestUtilities.CalculateDigest(
+					hashAlgorithm, issuerName.GetEncoded());
+
+				AsymmetricKeyParameter issuerKey = issuerCert.GetPublicKey();
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(issuerKey);
+				byte[] issuerKeyHash = DigestUtilities.CalculateDigest(
+					hashAlgorithm, info.PublicKeyData.GetBytes());
+
+				return new CertID(hashAlg, new DerOctetString(issuerNameHash),
+					new DerOctetString(issuerKeyHash), serialNumber);
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("problem creating ID: " + e, e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/CertificateStatus.cs b/BouncyCastle.AxCrypt/src/ocsp/CertificateStatus.cs
new file mode 100644
index 0000000..edfcc25
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/CertificateStatus.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public abstract class CertificateStatus
+	{
+		public static readonly CertificateStatus Good = null;
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPException.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPException.cs
new file mode 100644
index 0000000..db53e55
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class OcspException
+		: Exception
+	{
+		public OcspException()
+		{
+		}
+
+		public OcspException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public OcspException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPReq.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPReq.cs
new file mode 100644
index 0000000..84808e5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPReq.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * <pre>
+	 * OcspRequest     ::=     SEQUENCE {
+	 *       tbsRequest                  TBSRequest,
+	 *       optionalSignature   [0]     EXPLICIT Signature OPTIONAL }
+	 *
+	 *   TBSRequest      ::=     SEQUENCE {
+	 *       version             [0]     EXPLICIT Version DEFAULT v1,
+	 *       requestorName       [1]     EXPLICIT GeneralName OPTIONAL,
+	 *       requestList                 SEQUENCE OF Request,
+	 *       requestExtensions   [2]     EXPLICIT Extensions OPTIONAL }
+	 *
+	 *   Signature       ::=     SEQUENCE {
+	 *       signatureAlgorithm      AlgorithmIdentifier,
+	 *       signature               BIT STRING,
+	 *       certs               [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL}
+	 *
+	 *   Version         ::=             INTEGER  {  v1(0) }
+	 *
+	 *   Request         ::=     SEQUENCE {
+	 *       reqCert                     CertID,
+	 *       singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
+	 *
+	 *   CertID          ::=     SEQUENCE {
+	 *       hashAlgorithm       AlgorithmIdentifier,
+	 *       issuerNameHash      OCTET STRING, -- Hash of Issuer's DN
+	 *       issuerKeyHash       OCTET STRING, -- Hash of Issuers public key
+	 *       serialNumber        CertificateSerialNumber }
+	 * </pre>
+	 */
+	public class OcspReq
+		: X509ExtensionBase
+	{
+		private OcspRequest req;
+
+		public OcspReq(
+			OcspRequest req)
+		{
+			this.req = req;
+		}
+
+		public OcspReq(
+			byte[] req)
+			: this(new Asn1InputStream(req))
+		{
+		}
+
+		public OcspReq(
+			Stream inStr)
+			: this(new Asn1InputStream(inStr))
+		{
+		}
+
+		private OcspReq(
+			Asn1InputStream aIn)
+		{
+			try
+			{
+				this.req = OcspRequest.GetInstance(aIn.ReadObject());
+			}
+			catch (ArgumentException e)
+			{
+				throw new IOException("malformed request: " + e.Message);
+			}
+			catch (InvalidCastException e)
+			{
+				throw new IOException("malformed request: " + e.Message);
+			}
+		}
+
+		/**
+		 * Return the DER encoding of the tbsRequest field.
+		 * @return DER encoding of tbsRequest
+		 * @throws OcspException in the event of an encoding error.
+		 */
+		public byte[] GetTbsRequest()
+		{
+			try
+			{
+				return req.TbsRequest.GetEncoded();
+			}
+			catch (IOException e)
+			{
+				throw new OcspException("problem encoding tbsRequest", e);
+			}
+		}
+
+		public int Version
+		{
+			get { return req.TbsRequest.Version.Value.IntValue + 1; }
+		}
+
+		public GeneralName RequestorName
+		{
+			get { return GeneralName.GetInstance(req.TbsRequest.RequestorName); }
+		}
+
+		public Req[] GetRequestList()
+		{
+			Asn1Sequence seq = req.TbsRequest.RequestList;
+			Req[] requests = new Req[seq.Count];
+
+			for (int i = 0; i != requests.Length; i++)
+			{
+				requests[i] = new Req(Request.GetInstance(seq[i]));
+			}
+
+			return requests;
+		}
+
+		public X509Extensions RequestExtensions
+		{
+			get { return X509Extensions.GetInstance(req.TbsRequest.RequestExtensions); }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return RequestExtensions;
+		}
+
+		/**
+		 * return the object identifier representing the signature algorithm
+		 */
+		public string SignatureAlgOid
+		{
+			get
+			{
+				if (!this.IsSigned)
+					return null;
+
+				return req.OptionalSignature.SignatureAlgorithm.ObjectID.Id;
+			}
+		}
+
+		public byte[] GetSignature()
+		{
+			if (!this.IsSigned)
+				return null;
+
+			return req.OptionalSignature.SignatureValue.GetBytes();
+		}
+
+		private IList GetCertList()
+		{
+			// load the certificates if we have any
+
+			IList certs = Platform.CreateArrayList();
+			Asn1Sequence s = req.OptionalSignature.Certs;
+
+			if (s != null)
+			{
+				foreach (Asn1Encodable ae in s)
+				{
+					try
+					{
+						certs.Add(new X509CertificateParser().ReadCertificate(ae.GetEncoded()));
+					}
+					catch (Exception e)
+					{
+						throw new OcspException("can't re-encode certificate!", e);
+					}
+				}
+			}
+
+			return certs;
+		}
+
+		public X509Certificate[] GetCerts()
+		{
+			if (!this.IsSigned)
+				return null;
+
+			IList certs = this.GetCertList();
+            X509Certificate[] result = new X509Certificate[certs.Count];
+            for (int i = 0; i < certs.Count; ++i)
+            {
+                result[i] = (X509Certificate)certs[i];
+            }
+            return result;
+		}
+
+		/**
+		 * If the request is signed return a possibly empty CertStore containing the certificates in the
+		 * request. If the request is not signed the method returns null.
+		 *
+		 * @return null if not signed, a CertStore otherwise
+		 * @throws OcspException
+		 */
+		public IX509Store GetCertificates(
+			string type)
+		{
+			if (!this.IsSigned)
+				return null;
+
+			try
+			{
+				return X509StoreFactory.Create(
+					"Certificate/" + type,
+					new X509CollectionStoreParameters(this.GetCertList()));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("can't setup the CertStore", e);
+			}
+		}
+
+		/**
+		 * Return whether or not this request is signed.
+		 *
+		 * @return true if signed false otherwise.
+		 */
+		public bool IsSigned
+		{
+			get { return req.OptionalSignature != null; }
+		}
+
+		/**
+		 * Verify the signature against the TBSRequest object we contain.
+		 */
+		public bool Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			if (!this.IsSigned)
+				throw new OcspException("attempt to Verify signature on unsigned object");
+
+			try
+			{
+				ISigner signature = SignerUtilities.GetSigner(this.SignatureAlgOid);
+
+				signature.Init(false, publicKey);
+
+				byte[] encoded = req.TbsRequest.GetEncoded();
+
+				signature.BlockUpdate(encoded, 0, encoded.Length);
+
+				return signature.VerifySignature(this.GetSignature());
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("exception processing sig: " + e, e);
+			}
+		}
+
+		/**
+		 * return the ASN.1 encoded representation of this object.
+		 */
+		public byte[] GetEncoded()
+		{
+			return req.GetEncoded();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPReqGenerator.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPReqGenerator.cs
new file mode 100644
index 0000000..8032a45
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPReqGenerator.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class OcspReqGenerator
+	{
+		private IList			list = Platform.CreateArrayList();
+		private GeneralName		requestorName = null;
+		private X509Extensions	requestExtensions = null;
+
+		private class RequestObject
+		{
+			internal CertificateID certId;
+			internal X509Extensions extensions;
+
+			public RequestObject(
+				CertificateID	certId,
+				X509Extensions	extensions)
+			{
+				this.certId = certId;
+				this.extensions = extensions;
+			}
+
+			public Request ToRequest()
+			{
+				return new Request(certId.ToAsn1Object(), extensions);
+			}
+		}
+
+		/**
+		 * Add a request for the given CertificateID.
+		 *
+		 * @param certId certificate ID of interest
+		 */
+		public void AddRequest(
+			CertificateID certId)
+		{
+			list.Add(new RequestObject(certId, null));
+		}
+
+		/**
+		 * Add a request with extensions
+		 *
+		 * @param certId certificate ID of interest
+		 * @param singleRequestExtensions the extensions to attach to the request
+		 */
+		public void AddRequest(
+			CertificateID   certId,
+			X509Extensions  singleRequestExtensions)
+		{
+			list.Add(new RequestObject(certId, singleRequestExtensions));
+		}
+
+		/**
+		* Set the requestor name to the passed in X509Principal
+		*
+		* @param requestorName a X509Principal representing the requestor name.
+		*/
+		public void SetRequestorName(
+		    X509Name requestorName)
+		{
+		    try
+		    {
+		        this.requestorName = new GeneralName(GeneralName.DirectoryName, requestorName);
+		    }
+		    catch (Exception e)
+		    {
+		        throw new ArgumentException("cannot encode principal", e);
+		    }
+		}
+
+		public void SetRequestorName(
+			GeneralName requestorName)
+		{
+			this.requestorName = requestorName;
+		}
+
+		public void SetRequestExtensions(
+			X509Extensions requestExtensions)
+		{
+			this.requestExtensions = requestExtensions;
+		}
+
+		private OcspReq GenerateRequest(
+			DerObjectIdentifier		signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			SecureRandom			random)
+		{
+			Asn1EncodableVector requests = new Asn1EncodableVector();
+
+			foreach (RequestObject reqObj in list)
+			{
+				try
+				{
+					requests.Add(reqObj.ToRequest());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating Request", e);
+				}
+			}
+
+			TbsRequest tbsReq = new TbsRequest(requestorName, new DerSequence(requests), requestExtensions);
+
+			ISigner sig = null;
+			Signature signature = null;
+
+			if (signingAlgorithm != null)
+			{
+				if (requestorName == null)
+				{
+					throw new OcspException("requestorName must be specified if request is signed.");
+				}
+
+				try
+				{
+					sig = SignerUtilities.GetSigner(signingAlgorithm.Id);
+					if (random != null)
+					{
+						sig.Init(true, new ParametersWithRandom(privateKey, random));
+					}
+					else
+					{
+						sig.Init(true, privateKey);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception creating signature: " + e, e);
+				}
+
+				DerBitString bitSig = null;
+
+				try
+				{
+					byte[] encoded = tbsReq.GetEncoded();
+					sig.BlockUpdate(encoded, 0, encoded.Length);
+
+					bitSig = new DerBitString(sig.GenerateSignature());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("exception processing TBSRequest: " + e, e);
+				}
+
+				AlgorithmIdentifier sigAlgId = new AlgorithmIdentifier(signingAlgorithm, DerNull.Instance);
+
+				if (chain != null && chain.Length > 0)
+				{
+					Asn1EncodableVector v = new Asn1EncodableVector();
+					try
+					{
+						for (int i = 0; i != chain.Length; i++)
+						{
+							v.Add(
+								X509CertificateStructure.GetInstance(
+									Asn1Object.FromByteArray(chain[i].GetEncoded())));
+						}
+					}
+					catch (IOException e)
+					{
+						throw new OcspException("error processing certs", e);
+					}
+					catch (CertificateEncodingException e)
+					{
+						throw new OcspException("error encoding certs", e);
+					}
+
+					signature = new Signature(sigAlgId, bitSig, new DerSequence(v));
+				}
+				else
+				{
+					signature = new Signature(sigAlgId, bitSig);
+				}
+			}
+
+			return new OcspReq(new OcspRequest(tbsReq, signature));
+		}
+
+		/**
+		 * Generate an unsigned request
+		 *
+		 * @return the OcspReq
+		 * @throws OcspException
+		 */
+		public OcspReq Generate()
+		{
+			return GenerateRequest(null, null, null, null);
+		}
+
+		public OcspReq Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain)
+		{
+			return Generate(signingAlgorithm, privateKey, chain, null);
+		}
+
+		public OcspReq Generate(
+			string					signingAlgorithm,
+			AsymmetricKeyParameter	privateKey,
+			X509Certificate[]		chain,
+			SecureRandom			random)
+		{
+			if (signingAlgorithm == null)
+				throw new ArgumentException("no signing algorithm specified");
+
+			try
+			{
+				DerObjectIdentifier oid = OcspUtilities.GetAlgorithmOid(signingAlgorithm);
+
+				return GenerateRequest(oid, privateKey, chain, random);
+			}
+			catch (ArgumentException)
+			{
+				throw new ArgumentException("unknown signing algorithm specified: " + signingAlgorithm);
+			}
+		}
+
+		/**
+		 * Return an IEnumerable of the signature names supported by the generator.
+		 *
+		 * @return an IEnumerable containing recognised names.
+		 */
+		public IEnumerable SignatureAlgNames
+		{
+			get { return OcspUtilities.AlgNames; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPResp.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPResp.cs
new file mode 100644
index 0000000..dc99c6a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPResp.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class OcspResp
+	{
+		private OcspResponse resp;
+
+		public OcspResp(
+			OcspResponse resp)
+		{
+			this.resp = resp;
+		}
+
+		public OcspResp(
+			byte[] resp)
+			: this(new Asn1InputStream(resp))
+		{
+		}
+
+		public OcspResp(
+			Stream inStr)
+			: this(new Asn1InputStream(inStr))
+		{
+		}
+
+		private OcspResp(
+			Asn1InputStream aIn)
+		{
+			try
+			{
+				this.resp = OcspResponse.GetInstance(aIn.ReadObject());
+			}
+			catch (Exception e)
+			{
+				throw new IOException("malformed response: " + e.Message, e);
+			}
+		}
+
+		public int Status
+		{
+			get { return this.resp.ResponseStatus.Value.IntValue; }
+		}
+
+		public object GetResponseObject()
+		{
+			ResponseBytes rb = this.resp.ResponseBytes;
+
+			if (rb == null)
+				return null;
+
+			if (rb.ResponseType.Equals(OcspObjectIdentifiers.PkixOcspBasic))
+			{
+				try
+				{
+					return new BasicOcspResp(
+						BasicOcspResponse.GetInstance(
+							Asn1Object.FromByteArray(rb.Response.GetOctets())));
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("problem decoding object: " + e, e);
+				}
+			}
+
+			return rb.Response;
+		}
+
+		/**
+		* return the ASN.1 encoded representation of this object.
+		*/
+		public byte[] GetEncoded()
+		{
+			return resp.GetEncoded();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			OcspResp other = obj as OcspResp;
+
+			if (other == null)
+				return false;
+
+			return resp.Equals(other.resp);
+		}
+
+		public override int GetHashCode()
+		{
+			return resp.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPRespGenerator.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPRespGenerator.cs
new file mode 100644
index 0000000..e0eb9ae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPRespGenerator.cs
@@ -0,0 +1,54 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * base generator for an OCSP response - at the moment this only supports the
+	 * generation of responses containing BasicOCSP responses.
+	 */
+	public class OCSPRespGenerator
+	{
+		public const int Successful			= 0;	// Response has valid confirmations
+		public const int MalformedRequest	= 1;	// Illegal confirmation request
+		public const int InternalError		= 2;	// Internal error in issuer
+		public const int TryLater			= 3;	// Try again later
+		// (4) is not used
+		public const int SigRequired		= 5;	// Must sign the request
+		public const int Unauthorized		= 6;	// Request unauthorized
+
+		public OcspResp Generate(
+			int     status,
+			object  response)
+		{
+			if (response == null)
+			{
+				return new OcspResp(new OcspResponse(new OcspResponseStatus(status),null));
+			}
+			if (response is BasicOcspResp)
+			{
+				BasicOcspResp r = (BasicOcspResp)response;
+				Asn1OctetString octs;
+
+				try
+				{
+					octs = new DerOctetString(r.GetEncoded());
+				}
+				catch (Exception e)
+				{
+					throw new OcspException("can't encode object.", e);
+				}
+
+				ResponseBytes rb = new ResponseBytes(
+					OcspObjectIdentifiers.PkixOcspBasic, octs);
+
+				return new OcspResp(new OcspResponse(
+					new OcspResponseStatus(status), rb));
+			}
+
+			throw new OcspException("unknown response object");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPRespStatus.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPRespStatus.cs
new file mode 100644
index 0000000..9c00c70
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPRespStatus.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	[Obsolete("Use version with correct spelling 'OcspRespStatus'")]
+	public abstract class OcscpRespStatus : OcspRespStatus
+	{
+	}
+
+	public abstract class OcspRespStatus
+	{
+		/**
+		 * note 4 is not used.
+		 */
+		public const int Successful = 0;		// --Response has valid confirmations
+		public const int MalformedRequest = 1;	// --Illegal confirmation request
+		public const int InternalError = 2;		// --Internal error in issuer
+		public const int TryLater = 3;			// --Try again later
+		public const int SigRequired = 5;		// --Must sign the request
+		public const int Unauthorized = 6;		//  --Request unauthorized
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/OCSPUtil.cs b/BouncyCastle.AxCrypt/src/ocsp/OCSPUtil.cs
new file mode 100644
index 0000000..cbc1e95
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/OCSPUtil.cs
@@ -0,0 +1,132 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	class OcspUtilities
+	{
+		private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+		private static readonly ISet noParams = new HashSet();
+
+		static OcspUtilities()
+		{
+			algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+			algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+			algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+			algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+			algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+			algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+			algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+
+			oids.Add(PkcsObjectIdentifiers.MD2WithRsaEncryption, "MD2WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.MD5WithRsaEncryption, "MD5WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption, "SHA1WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160, "RIPEMD160WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128, "RIPEMD128WITHRSA");
+			oids.Add(TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256, "RIPEMD256WITHRSA");
+			oids.Add(X9ObjectIdentifiers.IdDsaWithSha1, "SHA1WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512WITHECDSA");
+			oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411WITHGOST3410");
+
+			//
+			// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+			// The parameters field SHALL be NULL for RSA based signature algorithms.
+			//
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+			noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha224);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+		}
+
+		internal static DerObjectIdentifier GetAlgorithmOid(
+			string algorithmName)
+		{
+			algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+            if (algorithms.Contains(algorithmName))
+			{
+				return (DerObjectIdentifier)algorithms[algorithmName];
+			}
+
+			return new DerObjectIdentifier(algorithmName);
+		}
+
+
+		internal static string GetAlgorithmName(
+			DerObjectIdentifier oid)
+		{
+			if (oids.Contains(oid))
+			{
+				return (string)oids[oid];
+			}
+
+			return oid.Id;
+		}
+
+		internal static AlgorithmIdentifier GetSigAlgID(
+			DerObjectIdentifier sigOid)
+		{
+			if (noParams.Contains(sigOid))
+			{
+				return new AlgorithmIdentifier(sigOid);
+			}
+
+			return new AlgorithmIdentifier(sigOid, DerNull.Instance);
+		}
+
+		internal static IEnumerable AlgNames
+		{
+			get { return new EnumerableProxy(algorithms.Keys); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/Req.cs b/BouncyCastle.AxCrypt/src/ocsp/Req.cs
new file mode 100644
index 0000000..68fd9f1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/Req.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class Req
+		: X509ExtensionBase
+	{
+		private Request req;
+
+		public Req(
+			Request req)
+		{
+			this.req = req;
+		}
+
+		public CertificateID GetCertID()
+		{
+			return new CertificateID(req.ReqCert);
+		}
+
+		public X509Extensions SingleRequestExtensions
+		{
+			get { return req.SingleRequestExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return SingleRequestExtensions;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/RespData.cs b/BouncyCastle.AxCrypt/src/ocsp/RespData.cs
new file mode 100644
index 0000000..105726c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/RespData.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class RespData
+		: X509ExtensionBase
+	{
+		internal readonly ResponseData data;
+
+		public RespData(
+			ResponseData data)
+		{
+			this.data = data;
+		}
+
+		public int Version
+		{
+			get { return data.Version.Value.IntValue + 1; }
+		}
+
+		public RespID GetResponderId()
+		{
+			return new RespID(data.ResponderID);
+		}
+
+		public DateTime ProducedAt
+		{
+			get { return data.ProducedAt.ToDateTime(); }
+		}
+
+		public SingleResp[] GetResponses()
+		{
+			Asn1Sequence s = data.Responses;
+			SingleResp[] rs = new SingleResp[s.Count];
+
+			for (int i = 0; i != rs.Length; i++)
+			{
+				rs[i] = new SingleResp(SingleResponse.GetInstance(s[i]));
+			}
+
+			return rs;
+		}
+
+		public X509Extensions ResponseExtensions
+		{
+			get { return data.ResponseExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return ResponseExtensions;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/RespID.cs b/BouncyCastle.AxCrypt/src/ocsp/RespID.cs
new file mode 100644
index 0000000..3238b26
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/RespID.cs
@@ -0,0 +1,72 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * Carrier for a ResponderID.
+	 */
+	public class RespID
+	{
+		internal readonly ResponderID id;
+
+		public RespID(
+			ResponderID id)
+		{
+			this.id = id;
+		}
+
+		public RespID(
+			X509Name name)
+		{
+	        this.id = new ResponderID(name);
+		}
+
+		public RespID(
+			AsymmetricKeyParameter publicKey)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+
+				byte[] keyHash = DigestUtilities.CalculateDigest("SHA1", info.PublicKeyData.GetBytes());
+
+				this.id = new ResponderID(new DerOctetString(keyHash));
+			}
+			catch (Exception e)
+			{
+				throw new OcspException("problem creating ID: " + e, e);
+			}
+		}
+
+		public ResponderID ToAsn1Object()
+		{
+			return id;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			RespID other = obj as RespID;
+
+			if (other == null)
+				return false;
+
+			return id.Equals(other.id);
+		}
+
+		public override int GetHashCode()
+		{
+			return id.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/RevokedStatus.cs b/BouncyCastle.AxCrypt/src/ocsp/RevokedStatus.cs
new file mode 100644
index 0000000..6e5ad1b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/RevokedStatus.cs
@@ -0,0 +1,58 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * wrapper for the RevokedInfo object
+	 */
+	public class RevokedStatus
+		: CertificateStatus
+	{
+		internal readonly RevokedInfo info;
+
+		public RevokedStatus(
+			RevokedInfo info)
+		{
+			this.info = info;
+		}
+
+		public RevokedStatus(
+			DateTime	revocationDate,
+			int			reason)
+		{
+			this.info = new RevokedInfo(new DerGeneralizedTime(revocationDate), new CrlReason(reason));
+		}
+
+		public DateTime RevocationTime
+		{
+			get { return info.RevocationTime.ToDateTime(); }
+		}
+
+		public bool HasRevocationReason
+		{
+			get { return (info.RevocationReason != null); }
+		}
+
+		/**
+		 * return the revocation reason. Note: this field is optional, test for it
+		 * with hasRevocationReason() first.
+		 * @exception InvalidOperationException if a reason is asked for and none is avaliable
+		 */
+		public int RevocationReason
+		{
+			get
+			{
+				if (info.RevocationReason == null)
+				{
+					throw new InvalidOperationException("attempt to get a reason where none is available");
+				}
+
+				return info.RevocationReason.Value.IntValue;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/SingleResp.cs b/BouncyCastle.AxCrypt/src/ocsp/SingleResp.cs
new file mode 100644
index 0000000..b8979c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/SingleResp.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	public class SingleResp
+		: X509ExtensionBase
+	{
+		internal readonly SingleResponse resp;
+
+		public SingleResp(
+			SingleResponse resp)
+		{
+			this.resp = resp;
+		}
+
+		public CertificateID GetCertID()
+		{
+			return new CertificateID(resp.CertId);
+		}
+
+		/**
+		 * Return the status object for the response - null indicates good.
+		 *
+		 * @return the status object for the response, null if it is good.
+		 */
+		public object GetCertStatus()
+		{
+			CertStatus s = resp.CertStatus;
+
+			if (s.TagNo == 0)
+			{
+				return null;            // good
+			}
+
+			if (s.TagNo == 1)
+			{
+				return new RevokedStatus(RevokedInfo.GetInstance(s.Status));
+			}
+
+			return new UnknownStatus();
+		}
+
+		public DateTime ThisUpdate
+		{
+			get { return resp.ThisUpdate.ToDateTime(); }
+		}
+
+		/**
+		* return the NextUpdate value - note: this is an optional field so may
+		* be returned as null.
+		*
+		* @return nextUpdate, or null if not present.
+		*/
+		public DateTimeObject NextUpdate
+		{
+			get
+			{
+				return resp.NextUpdate == null
+					?	null
+					:	new DateTimeObject(resp.NextUpdate.ToDateTime());
+			}
+		}
+
+		public X509Extensions SingleExtensions
+		{
+			get { return resp.SingleExtensions; }
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return SingleExtensions;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/ocsp/UnknownStatus.cs b/BouncyCastle.AxCrypt/src/ocsp/UnknownStatus.cs
new file mode 100644
index 0000000..c0f7a3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/ocsp/UnknownStatus.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Ocsp
+{
+	/**
+	 * wrapper for the UnknownInfo object
+	 */
+	public class UnknownStatus
+		: CertificateStatus
+	{
+		public UnknownStatus()
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/IStreamGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/IStreamGenerator.cs
new file mode 100644
index 0000000..379213a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/IStreamGenerator.cs
@@ -0,0 +1,7 @@
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public interface IStreamGenerator
+	{
+		void Close();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PGPKeyRing.cs b/BouncyCastle.AxCrypt/src/openpgp/PGPKeyRing.cs
new file mode 100644
index 0000000..6426f3f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PGPKeyRing.cs
@@ -0,0 +1,79 @@
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public abstract class PgpKeyRing
+		: PgpObject
+	{
+		internal PgpKeyRing()
+		{
+		}
+
+		internal static TrustPacket ReadOptionalTrustPacket(
+			BcpgInputStream bcpgInput)
+		{
+			return (bcpgInput.NextPacketTag() == PacketTag.Trust)
+				?	(TrustPacket) bcpgInput.ReadPacket()
+				:	null;
+		}
+
+		internal static IList ReadSignaturesAndTrust(
+			BcpgInputStream	bcpgInput)
+		{
+			try
+			{
+				IList sigList = Platform.CreateArrayList();
+
+				while (bcpgInput.NextPacketTag() == PacketTag.Signature)
+				{
+					SignaturePacket signaturePacket = (SignaturePacket) bcpgInput.ReadPacket();
+					TrustPacket trustPacket = ReadOptionalTrustPacket(bcpgInput);
+
+					sigList.Add(new PgpSignature(signaturePacket, trustPacket));
+				}
+
+				return sigList;
+			}
+			catch (PgpException e)
+			{
+				throw new IOException("can't create signature object: " + e.Message, e);
+			}
+		}
+
+		internal static void ReadUserIDs(
+			BcpgInputStream	bcpgInput,
+			out IList       ids,
+			out IList       idTrusts,
+			out IList       idSigs)
+		{
+			ids = Platform.CreateArrayList();
+            idTrusts = Platform.CreateArrayList();
+            idSigs = Platform.CreateArrayList();
+
+			while (bcpgInput.NextPacketTag() == PacketTag.UserId
+				|| bcpgInput.NextPacketTag() == PacketTag.UserAttribute)
+			{
+				Packet obj = bcpgInput.ReadPacket();
+				if (obj is UserIdPacket)
+				{
+					UserIdPacket id = (UserIdPacket)obj;
+					ids.Add(id.GetId());
+				}
+				else
+				{
+					UserAttributePacket user = (UserAttributePacket) obj;
+					ids.Add(new PgpUserAttributeSubpacketVector(user.GetSubpackets()));
+				}
+
+				idTrusts.Add(
+					ReadOptionalTrustPacket(bcpgInput));
+
+				idSigs.Add(
+					ReadSignaturesAndTrust(bcpgInput));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PGPObject.cs b/BouncyCastle.AxCrypt/src/openpgp/PGPObject.cs
new file mode 100644
index 0000000..d38276c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PGPObject.cs
@@ -0,0 +1,9 @@
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public abstract class PgpObject
+	{
+		internal PgpObject()
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs
new file mode 100644
index 0000000..9d56c8b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PGPUserAttributeSubpacketVectorGenerator.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Bcpg.Attr;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public class PgpUserAttributeSubpacketVectorGenerator
+	{
+		private IList list = Platform.CreateArrayList();
+
+		public virtual void SetImageAttribute(
+			ImageAttrib.Format	imageType,
+			byte[]				imageData)
+		{
+			if (imageData == null)
+				throw new ArgumentException("attempt to set null image", "imageData");
+
+			list.Add(new ImageAttrib(imageType, imageData));
+		}
+
+        public virtual PgpUserAttributeSubpacketVector Generate()
+		{
+            UserAttributeSubpacket[] a = new UserAttributeSubpacket[list.Count];
+            for (int i = 0; i < list.Count; ++i)
+            {
+                a[i] = (UserAttributeSubpacket)list[i];
+            }
+            return new PgpUserAttributeSubpacketVector(a);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedData.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedData.cs
new file mode 100644
index 0000000..e64a17c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedData.cs
@@ -0,0 +1,50 @@
+using System.IO;
+
+using Org.BouncyCastle.Apache.Bzip2;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Compressed data objects</remarks>
+    public class PgpCompressedData
+		: PgpObject
+    {
+        private readonly CompressedDataPacket data;
+
+		public PgpCompressedData(
+            BcpgInputStream bcpgInput)
+        {
+            data = (CompressedDataPacket) bcpgInput.ReadPacket();
+        }
+
+		/// <summary>The algorithm used for compression</summary>
+        public CompressionAlgorithmTag Algorithm
+        {
+			get { return data.Algorithm; }
+        }
+
+		/// <summary>Get the raw input stream contained in the object.</summary>
+        public Stream GetInputStream()
+        {
+            return data.GetInputStream();
+        }
+
+		/// <summary>Return an uncompressed input stream which allows reading of the compressed data.</summary>
+        public Stream GetDataStream()
+        {
+            switch (Algorithm)
+            {
+				case CompressionAlgorithmTag.Uncompressed:
+					return GetInputStream();
+				case CompressionAlgorithmTag.Zip:
+					return new ZInputStream(GetInputStream(), true);
+                case CompressionAlgorithmTag.ZLib:
+					return new ZInputStream(GetInputStream());
+				case CompressionAlgorithmTag.BZip2:
+					return new CBZip2InputStream(GetInputStream());
+                default:
+                    throw new PgpException("can't recognise compression algorithm: " + Algorithm);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedDataGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedDataGenerator.cs
new file mode 100644
index 0000000..e3a8893
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpCompressedDataGenerator.cs
@@ -0,0 +1,204 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Apache.Bzip2;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Class for producing compressed data packets.</remarks>
+	public class PgpCompressedDataGenerator
+		: IStreamGenerator
+	{
+		private readonly CompressionAlgorithmTag algorithm;
+		private readonly int compression;
+
+		private Stream dOut;
+		private BcpgOutputStream pkOut;
+
+		public PgpCompressedDataGenerator(
+			CompressionAlgorithmTag algorithm)
+			: this(algorithm, JZlib.Z_DEFAULT_COMPRESSION)
+		{
+		}
+
+		public PgpCompressedDataGenerator(
+			CompressionAlgorithmTag	algorithm,
+			int						compression)
+		{
+			switch (algorithm)
+			{
+				case CompressionAlgorithmTag.Uncompressed:
+				case CompressionAlgorithmTag.Zip:
+				case CompressionAlgorithmTag.ZLib:
+				case CompressionAlgorithmTag.BZip2:
+					break;
+				default:
+					throw new ArgumentException("unknown compression algorithm", "algorithm");
+			}
+
+			if (compression != JZlib.Z_DEFAULT_COMPRESSION)
+			{
+				if ((compression < JZlib.Z_NO_COMPRESSION) || (compression > JZlib.Z_BEST_COMPRESSION))
+				{
+					throw new ArgumentException("unknown compression level: " + compression);
+				}
+			}
+
+			this.algorithm = algorithm;
+			this.compression = compression;
+		}
+
+		/// <summary>
+		/// <p>
+		/// Return an output stream which will save the data being written to
+		/// the compressed object.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// </summary>
+		/// <param name="outStr">Stream to be used for output.</param>
+		/// <returns>A Stream for output of the compressed data.</returns>
+		/// <exception cref="ArgumentNullException"></exception>
+		/// <exception cref="InvalidOperationException"></exception>
+		/// <exception cref="IOException"></exception>
+		public Stream Open(
+			Stream outStr)
+		{
+			if (dOut != null)
+				throw new InvalidOperationException("generator already in open state");
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData);
+
+			doOpen();
+
+			return new WrappedGeneratorStream(this, dOut);
+		}
+
+		/// <summary>
+		/// <p>
+		/// Return an output stream which will compress the data as it is written to it.
+		/// The stream will be written out in chunks according to the size of the passed in buffer.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// <p>
+		/// <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+		/// bytes worth of the buffer will be used.
+		/// </p>
+		/// <p>
+		/// <b>Note</b>: using this may break compatibility with RFC 1991 compliant tools.
+		/// Only recent OpenPGP implementations are capable of accepting these streams.
+		/// </p>
+		/// </summary>
+		/// <param name="outStr">Stream to be used for output.</param>
+		/// <param name="buffer">The buffer to use.</param>
+		/// <returns>A Stream for output of the compressed data.</returns>
+		/// <exception cref="ArgumentNullException"></exception>
+		/// <exception cref="InvalidOperationException"></exception>
+		/// <exception cref="IOException"></exception>
+		/// <exception cref="PgpException"></exception>
+		public Stream Open(
+			Stream	outStr,
+			byte[]	buffer)
+		{
+			if (dOut != null)
+				throw new InvalidOperationException("generator already in open state");
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+			if (buffer == null)
+				throw new ArgumentNullException("buffer");
+
+			this.pkOut = new BcpgOutputStream(outStr, PacketTag.CompressedData, buffer);
+
+			doOpen();
+
+			return new WrappedGeneratorStream(this, dOut);
+		}
+
+		private void doOpen()
+		{
+			pkOut.WriteByte((byte) algorithm);
+
+			switch (algorithm)
+			{
+				case CompressionAlgorithmTag.Uncompressed:
+					dOut = pkOut;
+					break;
+				case CompressionAlgorithmTag.Zip:
+					dOut = new SafeZOutputStream(pkOut, compression, true);
+					break;
+				case CompressionAlgorithmTag.ZLib:
+					dOut = new SafeZOutputStream(pkOut, compression, false);
+					break;
+				case CompressionAlgorithmTag.BZip2:
+					dOut = new SafeCBZip2OutputStream(pkOut);
+					break;
+				default:
+					// Constructor should guard against this possibility
+					throw new InvalidOperationException();
+			}
+		}
+
+		/// <summary>Close the compressed object.</summary>summary>
+		public void Close()
+		{
+			if (dOut != null)
+			{
+				if (dOut != pkOut)
+				{
+                    dOut.Dispose();
+                    dOut.Flush();
+				}
+
+				dOut = null;
+
+				pkOut.Finish();
+				pkOut.Flush();
+				pkOut = null;
+			}
+		}
+
+		private class SafeCBZip2OutputStream : CBZip2OutputStream
+		{
+			public SafeCBZip2OutputStream(Stream output)
+				: base(output)
+			{
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+		            Finish();
+		        }
+		        base.Dispose(disposing);
+		    }
+		}
+
+		private class SafeZOutputStream : ZOutputStream
+		{
+			public SafeZOutputStream(Stream output, int level, bool nowrap)
+				: base(output, level, nowrap)
+			{
+			}
+
+		    protected override void Dispose(bool disposing)
+		    {
+		        if (disposing)
+		        {
+		            Finish();
+		            End();
+		        }
+		    }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpDataValidationException.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpDataValidationException.cs
new file mode 100644
index 0000000..aab5165
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpDataValidationException.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// Thrown if the IV at the start of a data stream indicates the wrong key is being used.
+	/// </remarks>
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PgpDataValidationException
+        : PgpException
+	{
+		public PgpDataValidationException() : base() {}
+		public PgpDataValidationException(string message) : base(message) {}
+		public PgpDataValidationException(string message, Exception exception) : base(message, exception) {}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedData.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedData.cs
new file mode 100644
index 0000000..0d237b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedData.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+    public abstract class PgpEncryptedData
+    {
+		internal class TruncatedStream
+			: BaseInputStream
+		{
+			private const int LookAheadSize = 22;
+			private const int LookAheadBufSize = 512;
+			private const int LookAheadBufLimit = LookAheadBufSize - LookAheadSize;
+
+			private readonly Stream inStr;
+			private readonly byte[] lookAhead = new byte[LookAheadBufSize];
+			private int bufStart, bufEnd;
+
+			internal TruncatedStream(
+				Stream inStr)
+			{
+				int numRead = Streams.ReadFully(inStr, lookAhead, 0, lookAhead.Length);
+
+				if (numRead < LookAheadSize)
+					throw new EndOfStreamException();
+
+				this.inStr = inStr;
+				this.bufStart = 0;
+				this.bufEnd = numRead - LookAheadSize;
+			}
+
+			private int FillBuffer()
+			{
+				if (bufEnd < LookAheadBufLimit)
+					return 0;
+
+				Debug.Assert(bufStart == LookAheadBufLimit);
+				Debug.Assert(bufEnd == LookAheadBufLimit);
+
+				Array.Copy(lookAhead, LookAheadBufLimit, lookAhead, 0, LookAheadSize);
+				bufEnd = Streams.ReadFully(inStr, lookAhead, LookAheadSize, LookAheadBufLimit);
+				bufStart = 0;
+				return bufEnd;
+			}
+
+			public override int ReadByte()
+			{
+				if (bufStart < bufEnd)
+					return lookAhead[bufStart++];
+
+				if (FillBuffer() < 1)
+					return -1;
+
+				return lookAhead[bufStart++];
+			}
+
+			public override int Read(byte[] buf, int off, int len)
+			{
+				int avail = bufEnd - bufStart;
+
+				int pos = off;
+				while (len > avail)
+				{
+					Array.Copy(lookAhead, bufStart, buf, pos, avail);
+
+					bufStart += avail;
+					pos += avail;
+					len -= avail;
+
+					if ((avail = FillBuffer()) < 1)
+						return pos - off;
+				}
+
+				Array.Copy(lookAhead, bufStart, buf, pos, len);
+				bufStart += len;
+
+				return pos + len - off;;
+			}
+
+			internal byte[] GetLookAhead()
+			{
+				byte[] temp = new byte[LookAheadSize];
+				Array.Copy(lookAhead, bufStart, temp, 0, LookAheadSize);
+				return temp;
+			}
+		}
+
+		internal InputStreamPacket	encData;
+        internal Stream				encStream;
+        internal TruncatedStream	truncStream;
+
+		internal PgpEncryptedData(
+            InputStreamPacket encData)
+        {
+            this.encData = encData;
+        }
+
+		/// <summary>Return the raw input stream for the data stream.</summary>
+        public virtual Stream GetInputStream()
+        {
+            return encData.GetInputStream();
+        }
+
+		/// <summary>Return true if the message is integrity protected.</summary>
+		/// <returns>True, if there is a modification detection code namespace associated
+		/// with this stream.</returns>
+        public bool IsIntegrityProtected()
+        {
+			return encData is SymmetricEncIntegrityPacket;
+        }
+
+		/// <summary>Note: This can only be called after the message has been read.</summary>
+		/// <returns>True, if the message verifies, false otherwise</returns>
+        public bool Verify()
+        {
+            if (!IsIntegrityProtected())
+                throw new PgpException("data not integrity protected.");
+
+			DigestStream dIn = (DigestStream) encStream;
+
+			//
+            // make sure we are at the end.
+            //
+            while (encStream.ReadByte() >= 0)
+            {
+				// do nothing
+            }
+
+			//
+            // process the MDC packet
+            //
+			byte[] lookAhead = truncStream.GetLookAhead();
+
+			IDigest hash = dIn.ReadDigest();
+			hash.BlockUpdate(lookAhead, 0, 2);
+			byte[] digest = DigestUtilities.DoFinal(hash);
+
+			byte[] streamDigest = new byte[digest.Length];
+			Array.Copy(lookAhead, 2, streamDigest, 0, streamDigest.Length);
+
+			return Arrays.ConstantTimeAreEqual(digest, streamDigest);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataGenerator.cs
new file mode 100644
index 0000000..f46f99d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataGenerator.cs
@@ -0,0 +1,506 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Generator for encrypted objects.</remarks>
+    public class PgpEncryptedDataGenerator
+		: IStreamGenerator
+    {
+		private BcpgOutputStream	pOut;
+        private CipherStream		cOut;
+        private IBufferedCipher		c;
+        private bool				withIntegrityPacket;
+        private bool				oldFormat;
+        private DigestStream		digestOut;
+
+		private abstract class EncMethod
+            : ContainedPacket
+        {
+            protected byte[]                    sessionInfo;
+            protected SymmetricKeyAlgorithmTag  encAlgorithm;
+            protected KeyParameter              key;
+
+			public abstract void AddSessionInfo(byte[] si, SecureRandom random);
+        }
+
+        private class PbeMethod
+            : EncMethod
+        {
+            private S2k s2k;
+
+            internal PbeMethod(
+                SymmetricKeyAlgorithmTag  encAlgorithm,
+                S2k                       s2k,
+                KeyParameter              key)
+            {
+                this.encAlgorithm = encAlgorithm;
+                this.s2k = s2k;
+                this.key = key;
+            }
+
+            public KeyParameter GetKey()
+            {
+                return key;
+            }
+
+			public override void AddSessionInfo(
+                byte[]			si,
+				SecureRandom	random)
+            {
+                string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
+                IBufferedCipher c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
+
+				byte[] iv = new byte[c.GetBlockSize()];
+                c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), random));
+
+				this.sessionInfo = c.DoFinal(si, 0, si.Length - 2);
+			}
+
+			public override void Encode(BcpgOutputStream pOut)
+            {
+                SymmetricKeyEncSessionPacket pk = new SymmetricKeyEncSessionPacket(
+                    encAlgorithm, s2k, sessionInfo);
+
+				pOut.WritePacket(pk);
+            }
+        }
+
+		private class PubMethod
+            : EncMethod
+        {
+			internal PgpPublicKey pubKey;
+            internal BigInteger[] data;
+
+			internal PubMethod(
+                PgpPublicKey pubKey)
+            {
+                this.pubKey = pubKey;
+            }
+
+			public override void AddSessionInfo(
+                byte[]			si,
+				SecureRandom	random)
+            {
+                IBufferedCipher c;
+
+				switch (pubKey.Algorithm)
+                {
+                    case PublicKeyAlgorithmTag.RsaEncrypt:
+                    case PublicKeyAlgorithmTag.RsaGeneral:
+                        c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
+                        break;
+                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                    case PublicKeyAlgorithmTag.ElGamalGeneral:
+                        c = CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
+                        break;
+                    case PublicKeyAlgorithmTag.Dsa:
+                        throw new PgpException("Can't use DSA for encryption.");
+                    case PublicKeyAlgorithmTag.ECDsa:
+                        throw new PgpException("Can't use ECDSA for encryption.");
+                    default:
+                        throw new PgpException("unknown asymmetric algorithm: " + pubKey.Algorithm);
+                }
+
+				AsymmetricKeyParameter akp = pubKey.GetKey();
+
+				c.Init(true, new ParametersWithRandom(akp, random));
+
+				byte[] encKey = c.DoFinal(si);
+
+				switch (pubKey.Algorithm)
+                {
+                    case PublicKeyAlgorithmTag.RsaEncrypt:
+                    case PublicKeyAlgorithmTag.RsaGeneral:
+						data = new BigInteger[]{ new BigInteger(1, encKey) };
+                        break;
+                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                    case PublicKeyAlgorithmTag.ElGamalGeneral:
+						int halfLength = encKey.Length / 2;
+						data = new BigInteger[]
+						{
+							new BigInteger(1, encKey, 0, halfLength),
+							new BigInteger(1, encKey, halfLength, halfLength)
+						};
+                        break;
+                    default:
+                        throw new PgpException("unknown asymmetric algorithm: " + encAlgorithm);
+                }
+            }
+
+			public override void Encode(BcpgOutputStream pOut)
+            {
+                PublicKeyEncSessionPacket pk = new PublicKeyEncSessionPacket(
+                    pubKey.KeyId, pubKey.Algorithm, data);
+
+				pOut.WritePacket(pk);
+            }
+        }
+
+		private readonly IList methods = Platform.CreateArrayList();
+        private readonly SymmetricKeyAlgorithmTag defAlgorithm;
+        private readonly SecureRandom rand;
+
+		public PgpEncryptedDataGenerator(
+			SymmetricKeyAlgorithmTag encAlgorithm)
+		{
+			this.defAlgorithm = encAlgorithm;
+			this.rand = new SecureRandom();
+		}
+
+		public PgpEncryptedDataGenerator(
+			SymmetricKeyAlgorithmTag	encAlgorithm,
+			bool						withIntegrityPacket)
+		{
+			this.defAlgorithm = encAlgorithm;
+			this.withIntegrityPacket = withIntegrityPacket;
+			this.rand = new SecureRandom();
+		}
+
+		/// <summary>Existing SecureRandom constructor.</summary>
+		/// <param name="encAlgorithm">The symmetric algorithm to use.</param>
+		/// <param name="rand">Source of randomness.</param>
+        public PgpEncryptedDataGenerator(
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            SecureRandom				rand)
+        {
+            this.defAlgorithm = encAlgorithm;
+            this.rand = rand;
+        }
+
+		/// <summary>Creates a cipher stream which will have an integrity packet associated with it.</summary>
+        public PgpEncryptedDataGenerator(
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            bool						withIntegrityPacket,
+            SecureRandom				rand)
+        {
+            this.defAlgorithm = encAlgorithm;
+            this.rand = rand;
+            this.withIntegrityPacket = withIntegrityPacket;
+        }
+
+		/// <summary>Base constructor.</summary>
+		/// <param name="encAlgorithm">The symmetric algorithm to use.</param>
+		/// <param name="rand">Source of randomness.</param>
+		/// <param name="oldFormat">PGP 2.6.x compatibility required.</param>
+        public PgpEncryptedDataGenerator(
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            SecureRandom				rand,
+            bool						oldFormat)
+        {
+            this.defAlgorithm = encAlgorithm;
+            this.rand = rand;
+            this.oldFormat = oldFormat;
+        }
+
+		/// <summary>
+		/// Add a PBE encryption method to the encrypted object using the default algorithm (S2K_SHA1).
+		/// </summary>
+		public void AddMethod(
+			char[] passPhrase) 
+		{
+			AddMethod(passPhrase, HashAlgorithmTag.Sha1);
+		}
+
+		/// <summary>Add a PBE encryption method to the encrypted object.</summary>
+        public void AddMethod(
+ 			char[]				passPhrase,
+			HashAlgorithmTag	s2kDigest)
+        {
+            byte[] iv = new byte[8];
+			rand.NextBytes(iv);
+
+			S2k s2k = new S2k(s2kDigest, iv, 0x60);
+
+			methods.Add(new PbeMethod(defAlgorithm, s2k, PgpUtilities.MakeKeyFromPassPhrase(defAlgorithm, s2k, passPhrase)));
+        }
+
+		/// <summary>Add a public key encrypted session key to the encrypted object.</summary>
+        public void AddMethod(
+            PgpPublicKey key)
+        {
+			if (!key.IsEncryptionKey)
+            {
+                throw new ArgumentException("passed in key not an encryption key!");
+            }
+
+			methods.Add(new PubMethod(key));
+        }
+
+		private void AddCheckSum(
+            byte[] sessionInfo)
+        {
+			Debug.Assert(sessionInfo != null);
+			Debug.Assert(sessionInfo.Length >= 3);
+
+			int check = 0;
+
+			for (int i = 1; i < sessionInfo.Length - 2; i++)
+            {
+                check += sessionInfo[i];
+            }
+
+			sessionInfo[sessionInfo.Length - 2] = (byte)(check >> 8);
+            sessionInfo[sessionInfo.Length - 1] = (byte)(check);
+        }
+
+		private byte[] CreateSessionInfo(
+			SymmetricKeyAlgorithmTag	algorithm,
+			KeyParameter				key)
+		{
+			byte[] keyBytes = key.GetKey();
+			byte[] sessionInfo = new byte[keyBytes.Length + 3];
+			sessionInfo[0] = (byte) algorithm;
+			keyBytes.CopyTo(sessionInfo, 1);
+			AddCheckSum(sessionInfo);
+			return sessionInfo;
+		}
+
+		/// <summary>
+		/// <p>
+		/// If buffer is non null stream assumed to be partial, otherwise the length will be used
+		/// to output a fixed length packet.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// </summary>
+        private Stream Open(
+            Stream	outStr,
+            long	length,
+            byte[]	buffer)
+        {
+			if (cOut != null)
+				throw new InvalidOperationException("generator already in open state");
+			if (methods.Count == 0)
+				throw new InvalidOperationException("No encryption methods specified");
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			pOut = new BcpgOutputStream(outStr);
+
+			KeyParameter key;
+
+			if (methods.Count == 1)
+            {
+                if (methods[0] is PbeMethod)
+                {
+                    PbeMethod m = (PbeMethod)methods[0];
+
+					key = m.GetKey();
+                }
+                else
+                {
+                    key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
+
+					byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);
+                    PubMethod m = (PubMethod)methods[0];
+
+                    try
+                    {
+                        m.AddSessionInfo(sessionInfo, rand);
+                    }
+                    catch (Exception e)
+                    {
+                        throw new PgpException("exception encrypting session key", e);
+                    }
+                }
+
+				pOut.WritePacket((ContainedPacket)methods[0]);
+            }
+            else // multiple methods
+            {
+                key = PgpUtilities.MakeRandomKey(defAlgorithm, rand);
+				byte[] sessionInfo = CreateSessionInfo(defAlgorithm, key);
+
+				for (int i = 0; i != methods.Count; i++)
+                {
+                    EncMethod m = (EncMethod)methods[i];
+
+                    try
+                    {
+                        m.AddSessionInfo(sessionInfo, rand);
+                    }
+                    catch (Exception e)
+                    {
+                        throw new PgpException("exception encrypting session key", e);
+                    }
+
+                    pOut.WritePacket(m);
+                }
+            }
+
+            string cName = PgpUtilities.GetSymmetricCipherName(defAlgorithm);
+			if (cName == null)
+            {
+                throw new PgpException("null cipher specified");
+            }
+
+			try
+            {
+                if (withIntegrityPacket)
+                {
+                    cName += "/CFB/NoPadding";
+                }
+                else
+                {
+                    cName += "/OpenPGPCFB/NoPadding";
+                }
+
+                c = CipherUtilities.GetCipher(cName);
+
+				// TODO Confirm the IV should be all zero bytes (not inLineIv - see below)
+				byte[] iv = new byte[c.GetBlockSize()];
+                c.Init(true, new ParametersWithRandom(new ParametersWithIV(key, iv), rand));
+
+                if (buffer == null)
+                {
+                    //
+                    // we have to Add block size + 2 for the Generated IV and + 1 + 22 if integrity protected
+                    //
+                    if (withIntegrityPacket)
+                    {
+                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, length + c.GetBlockSize() + 2 + 1 + 22);
+                        pOut.WriteByte(1);        // version number
+                    }
+                    else
+                    {
+                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, length + c.GetBlockSize() + 2, oldFormat);
+                    }
+                }
+                else
+                {
+                    if (withIntegrityPacket)
+                    {
+                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricEncryptedIntegrityProtected, buffer);
+                        pOut.WriteByte(1);        // version number
+                    }
+                    else
+                    {
+                        pOut = new BcpgOutputStream(outStr, PacketTag.SymmetricKeyEncrypted, buffer);
+                    }
+                }
+
+				int blockSize = c.GetBlockSize();
+				byte[] inLineIv = new byte[blockSize + 2];
+                rand.NextBytes(inLineIv, 0, blockSize);
+				Array.Copy(inLineIv, inLineIv.Length - 4, inLineIv, inLineIv.Length - 2, 2);
+
+				Stream myOut = cOut = new CipherStream(pOut, null, c);
+
+				if (withIntegrityPacket)
+                {
+					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
+					IDigest digest = DigestUtilities.GetDigest(digestName);
+					myOut = digestOut = new DigestStream(myOut, null, digest);
+                }
+
+				myOut.Write(inLineIv, 0, inLineIv.Length);
+
+				return new WrappedGeneratorStream(this, myOut);
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception creating cipher", e);
+            }
+        }
+
+		/// <summary>
+		/// <p>
+		/// Return an output stream which will encrypt the data as it is written to it.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// </summary>
+        public Stream Open(
+            Stream	outStr,
+            long	length)
+        {
+            return Open(outStr, length, null);
+        }
+
+		/// <summary>
+		/// <p>
+		/// Return an output stream which will encrypt the data as it is written to it.
+		/// The stream will be written out in chunks according to the size of the passed in buffer.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// <p>
+		/// <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+		/// bytes worth of the buffer will be used.
+		/// </p>
+		/// </summary>
+        public Stream Open(
+            Stream	outStr,
+            byte[]	buffer)
+        {
+            return Open(outStr, 0, buffer);
+        }
+
+		/// <summary>
+		/// <p>
+		/// Close off the encrypted object - this is equivalent to calling Close() on the stream
+		/// returned by the Open() method.
+		/// </p>
+		/// <p>
+		/// <b>Note</b>: This does not close the underlying output stream, only the stream on top of
+		/// it created by the Open() method.
+		/// </p>
+		/// </summary>
+        public void Close()
+        {
+            if (cOut != null)
+            {
+				// TODO Should this all be under the try/catch block?
+                if (digestOut != null)
+                {
+                    //
+                    // hand code a mod detection packet
+                    //
+                    BcpgOutputStream bOut = new BcpgOutputStream(
+						digestOut, PacketTag.ModificationDetectionCode, 20);
+
+                    bOut.Flush();
+                    digestOut.Flush();
+
+					// TODO
+					byte[] dig = DigestUtilities.DoFinal(digestOut.WriteDigest());
+					cOut.Write(dig, 0, dig.Length);
+                }
+
+				cOut.Flush();
+
+				try
+                {
+					pOut.Write(c.DoFinal());
+                    pOut.Finish();
+                }
+                catch (Exception e)
+                {
+                    throw new IOException(e.Message, e);
+                }
+
+				cOut = null;
+				pOut = null;
+            }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataList.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataList.cs
new file mode 100644
index 0000000..8dded7c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpEncryptedDataList.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A holder for a list of PGP encryption method packets.</remarks>
+    public class PgpEncryptedDataList
+		: PgpObject
+    {
+        private IList list = Platform.CreateArrayList();
+        private InputStreamPacket data;
+
+		public PgpEncryptedDataList(
+            BcpgInputStream bcpgInput)
+        {
+            while (bcpgInput.NextPacketTag() == PacketTag.PublicKeyEncryptedSession
+                || bcpgInput.NextPacketTag() == PacketTag.SymmetricKeyEncryptedSessionKey)
+            {
+                list.Add(bcpgInput.ReadPacket());
+            }
+
+			data = (InputStreamPacket)bcpgInput.ReadPacket();
+
+			for (int i = 0; i != list.Count; i++)
+            {
+                if (list[i] is SymmetricKeyEncSessionPacket)
+                {
+                    list[i] = new PgpPbeEncryptedData((SymmetricKeyEncSessionPacket) list[i], data);
+                }
+                else
+                {
+                    list[i] = new PgpPublicKeyEncryptedData((PublicKeyEncSessionPacket) list[i], data);
+                }
+            }
+        }
+
+		public PgpEncryptedData this[int index]
+		{
+			get { return (PgpEncryptedData) list[index]; }
+		}
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public object Get(int index)
+        {
+            return this[index];
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+        {
+			get { return list.Count; }
+        }
+
+		public int Count
+		{
+			get { return list.Count; }
+		}
+
+		public bool IsEmpty
+        {
+			get { return list.Count == 0; }
+        }
+
+		public IEnumerable GetEncryptedDataObjects()
+        {
+            return new EnumerableProxy(list);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpException.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpException.cs
new file mode 100644
index 0000000..378b16a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpException.cs
@@ -0,0 +1,22 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Generic exception class for PGP encoding/decoding problems.</remarks>
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PgpException
+		: Exception
+	{
+		public PgpException() : base() {}
+		public PgpException(string message) : base(message) {}
+		public PgpException(string message, Exception exception) : base(message, exception) {}
+
+		[Obsolete("Use InnerException property")]
+		public Exception UnderlyingException
+		{
+			get { return InnerException; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpExperimental.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpExperimental.cs
new file mode 100644
index 0000000..db1d060
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpExperimental.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public class PgpExperimental
+		: PgpObject
+	{
+		//private readonly ExperimentalPacket p;
+
+		public PgpExperimental(
+			BcpgInputStream bcpgIn)
+		{
+			/*p = (ExperimentalPacket)*/ bcpgIn.ReadPacket();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpKeyFlags.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyFlags.cs
new file mode 100644
index 0000000..ea18006
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyFlags.cs
@@ -0,0 +1,13 @@
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Key flag values for the KeyFlags subpacket.</remarks>
+    public abstract class PgpKeyFlags
+    {
+        public const int CanCertify = 0x01; // This key may be used to certify other keys.
+        public const int CanSign = 0x02; // This key may be used to sign data.
+        public const int CanEncryptCommunications = 0x04; // This key may be used to encrypt communications.
+        public const int CanEncryptStorage = 0x08; // This key may be used to encrypt storage.
+        public const int MaybeSplit = 0x10; // The private component of this key may have been split by a secret-sharing mechanism.
+        public const int MaybeShared = 0x80; // The private component of this key may be in the possession of more than one person.
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpKeyPair.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyPair.cs
new file mode 100644
index 0000000..6efb03a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyPair.cs
@@ -0,0 +1,67 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// General class to handle JCA key pairs and convert them into OpenPGP ones.
+	/// <p>
+	/// A word for the unwary, the KeyId for an OpenPGP public key is calculated from
+	/// a hash that includes the time of creation, if you pass a different date to the
+	/// constructor below with the same public private key pair the KeyIs will not be the
+	/// same as for previous generations of the key, so ideally you only want to do
+	/// this once.
+	/// </p>
+	/// </remarks>
+    public class PgpKeyPair
+    {
+        private readonly PgpPublicKey	pub;
+        private readonly PgpPrivateKey	priv;
+
+		public PgpKeyPair(
+            PublicKeyAlgorithmTag	algorithm,
+            AsymmetricCipherKeyPair	keyPair,
+            DateTime				time)
+			: this(algorithm, keyPair.Public, keyPair.Private, time)
+        {
+        }
+
+		public PgpKeyPair(
+            PublicKeyAlgorithmTag	algorithm,
+            AsymmetricKeyParameter	pubKey,
+            AsymmetricKeyParameter	privKey,
+            DateTime				time)
+        {
+            this.pub = new PgpPublicKey(algorithm, pubKey, time);
+			this.priv = new PgpPrivateKey(privKey, pub.KeyId);
+        }
+
+		/// <summary>Create a key pair from a PgpPrivateKey and a PgpPublicKey.</summary>
+		/// <param name="pub">The public key.</param>
+		/// <param name="priv">The private key.</param>
+        public PgpKeyPair(
+            PgpPublicKey	pub,
+            PgpPrivateKey	priv)
+        {
+            this.pub = pub;
+            this.priv = priv;
+        }
+
+		/// <summary>The keyId associated with this key pair.</summary>
+        public long KeyId
+        {
+            get { return pub.KeyId; }
+        }
+
+		public PgpPublicKey PublicKey
+        {
+			get { return pub; }
+        }
+
+		public PgpPrivateKey PrivateKey
+        {
+			get { return priv; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpKeyRingGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyRingGenerator.cs
new file mode 100644
index 0000000..0842345
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyRingGenerator.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// Generator for a PGP master and subkey ring.
+	/// This class will generate both the secret and public key rings
+	/// </remarks>
+    public class PgpKeyRingGenerator
+    {
+        private IList					    keys = Platform.CreateArrayList();
+        //private string                      id;
+        private SymmetricKeyAlgorithmTag	encAlgorithm;
+        //private int                         certificationLevel;
+        private char[]                      passPhrase;
+		private bool						useSha1;
+		private PgpKeyPair                  masterKey;
+        private PgpSignatureSubpacketVector hashedPacketVector;
+        private PgpSignatureSubpacketVector unhashedPacketVector;
+        private SecureRandom				rand;
+
+		/// <summary>
+		/// Create a new key ring generator using old style checksumming. It is recommended to use
+		/// SHA1 checksumming where possible.
+		/// </summary>
+		/// <param name="certificationLevel">The certification level for keys on this ring.</param>
+		/// <param name="masterKey">The master key pair.</param>
+		/// <param name="id">The id to be associated with the ring.</param>
+		/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+		/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+		/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
+		/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+		/// <param name="rand">input secured random.</param>
+		public PgpKeyRingGenerator(
+			int							certificationLevel,
+			PgpKeyPair					masterKey,
+			string						id,
+			SymmetricKeyAlgorithmTag	encAlgorithm,
+			char[]						passPhrase,
+			PgpSignatureSubpacketVector	hashedPackets,
+			PgpSignatureSubpacketVector	unhashedPackets,
+			SecureRandom				rand)
+			: this(certificationLevel, masterKey, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
+		{
+		}
+
+		/// <summary>
+		/// Create a new key ring generator.
+		/// </summary>
+		/// <param name="certificationLevel">The certification level for keys on this ring.</param>
+		/// <param name="masterKey">The master key pair.</param>
+		/// <param name="id">The id to be associated with the ring.</param>
+		/// <param name="encAlgorithm">The algorithm to be used to protect secret keys.</param>
+		/// <param name="passPhrase">The passPhrase to be used to protect secret keys.</param>
+		/// <param name="useSha1">Checksum the secret keys with SHA1 rather than the older 16 bit checksum.</param>
+		/// <param name="hashedPackets">Packets to be included in the certification hash.</param>
+		/// <param name="unhashedPackets">Packets to be attached unhashed to the certification.</param>
+		/// <param name="rand">input secured random.</param>
+        public PgpKeyRingGenerator(
+            int							certificationLevel,
+            PgpKeyPair					masterKey,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+			bool						useSha1,
+			PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+        {
+            //this.certificationLevel = certificationLevel;
+            this.masterKey = masterKey;
+            //this.id = id;
+            this.encAlgorithm = encAlgorithm;
+            this.passPhrase = passPhrase;
+			this.useSha1 = useSha1;
+			this.hashedPacketVector = hashedPackets;
+            this.unhashedPacketVector = unhashedPackets;
+            this.rand = rand;
+
+			keys.Add(new PgpSecretKey(certificationLevel, masterKey, id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand));
+        }
+
+		/// <summary>Add a subkey to the key ring to be generated with default certification.</summary>
+        public void AddSubKey(
+            PgpKeyPair keyPair)
+        {
+			AddSubKey(keyPair, this.hashedPacketVector, this.unhashedPacketVector);
+		}
+
+		/// <summary>
+		/// Add a subkey with specific hashed and unhashed packets associated with it and
+		/// default certification.
+		/// </summary>
+		/// <param name="keyPair">Public/private key pair.</param>
+		/// <param name="hashedPackets">Hashed packet values to be included in certification.</param>
+		/// <param name="unhashedPackets">Unhashed packets values to be included in certification.</param>
+		/// <exception cref="PgpException"></exception>
+		public void AddSubKey(
+			PgpKeyPair					keyPair,
+			PgpSignatureSubpacketVector	hashedPackets,
+			PgpSignatureSubpacketVector	unhashedPackets)
+		{
+			try
+            {
+                PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+					masterKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+
+				//
+                // Generate the certification
+                //
+                sGen.InitSign(PgpSignature.SubkeyBinding, masterKey.PrivateKey);
+
+				sGen.SetHashedSubpackets(hashedPackets);
+                sGen.SetUnhashedSubpackets(unhashedPackets);
+
+				IList subSigs = Platform.CreateArrayList();
+
+				subSigs.Add(sGen.GenerateCertification(masterKey.PublicKey, keyPair.PublicKey));
+
+				keys.Add(new PgpSecretKey(keyPair.PrivateKey, new PgpPublicKey(keyPair.PublicKey, null, subSigs), encAlgorithm, passPhrase, useSha1, rand));
+			}
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("exception adding subkey: ", e);
+            }
+        }
+
+		/// <summary>Return the secret key ring.</summary>
+        public PgpSecretKeyRing GenerateSecretKeyRing()
+        {
+            return new PgpSecretKeyRing(keys);
+        }
+
+		/// <summary>Return the public key ring that corresponds to the secret key ring.</summary>
+        public PgpPublicKeyRing GeneratePublicKeyRing()
+        {
+            IList pubKeys = Platform.CreateArrayList();
+
+            IEnumerator enumerator = keys.GetEnumerator();
+            enumerator.MoveNext();
+
+			PgpSecretKey pgpSecretKey = (PgpSecretKey) enumerator.Current;
+			pubKeys.Add(pgpSecretKey.PublicKey);
+
+			while (enumerator.MoveNext())
+            {
+                pgpSecretKey = (PgpSecretKey) enumerator.Current;
+
+				PgpPublicKey k = new PgpPublicKey(pgpSecretKey.PublicKey);
+				k.publicPk = new PublicSubkeyPacket(
+					k.Algorithm, k.CreationTime, k.publicPk.Key);
+
+				pubKeys.Add(k);
+			}
+
+			return new PgpPublicKeyRing(pubKeys);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpKeyValidationException.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyValidationException.cs
new file mode 100644
index 0000000..d6419b2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpKeyValidationException.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// Thrown if the key checksum is invalid.
+	/// </remarks>
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PgpKeyValidationException
+		: PgpException
+	{
+		public PgpKeyValidationException() : base() {}
+		public PgpKeyValidationException(string message) : base(message) {}
+		public PgpKeyValidationException(string message, Exception exception) : base(message, exception) {}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralData.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralData.cs
new file mode 100644
index 0000000..79bbc39
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralData.cs
@@ -0,0 +1,63 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <summary>Class for processing literal data objects.</summary>
+    public class PgpLiteralData
+		: PgpObject
+    {
+        public const char Binary = 'b';
+        public const char Text = 't';
+		public const char Utf8 = 'u';
+
+		/// <summary>The special name indicating a "for your eyes only" packet.</summary>
+        public const string Console = "_CONSOLE";
+
+		private LiteralDataPacket data;
+
+		public PgpLiteralData(
+            BcpgInputStream bcpgInput)
+        {
+            data = (LiteralDataPacket) bcpgInput.ReadPacket();
+        }
+
+		/// <summary>The format of the data stream - Binary or Text</summary>
+        public int Format
+        {
+            get { return data.Format; }
+        }
+
+		/// <summary>The file name that's associated with the data stream.</summary>
+        public string FileName
+        {
+			get { return data.FileName; }
+        }
+
+		/// Return the file name as an unintrepreted byte array.
+		public byte[] GetRawFileName()
+		{
+			return data.GetRawFileName();
+		}
+
+		/// <summary>The modification time for the file.</summary>
+        public DateTime ModificationTime
+        {
+			get { return DateTimeUtilities.UnixMsToDateTime(data.ModificationTime); }
+        }
+
+		/// <summary>The raw input stream for the data stream.</summary>
+        public Stream GetInputStream()
+        {
+            return data.GetInputStream();
+        }
+
+		/// <summary>The input stream representing the data stream.</summary>
+        public Stream GetDataStream()
+        {
+            return GetInputStream();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralDataGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralDataGenerator.cs
new file mode 100644
index 0000000..20c6706
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpLiteralDataGenerator.cs
@@ -0,0 +1,182 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Class for producing literal data packets.</remarks>
+    public class PgpLiteralDataGenerator
+		: IStreamGenerator
+	{
+        public const char Binary = PgpLiteralData.Binary;
+        public const char Text = PgpLiteralData.Text;
+		public const char Utf8 = PgpLiteralData.Utf8;
+
+		/// <summary>The special name indicating a "for your eyes only" packet.</summary>
+        public const string Console = PgpLiteralData.Console;
+
+		private BcpgOutputStream pkOut;
+        private bool oldFormat;
+
+		public PgpLiteralDataGenerator()
+        {
+        }
+
+		/// <summary>
+		/// Generates literal data objects in the old format.
+		/// This is important if you need compatibility with PGP 2.6.x.
+		/// </summary>
+		/// <param name="oldFormat">If true, uses old format.</param>
+        public PgpLiteralDataGenerator(
+            bool oldFormat)
+        {
+            this.oldFormat = oldFormat;
+        }
+
+		private void WriteHeader(
+            BcpgOutputStream	outStr,
+            char				format,
+            byte[]				encName,
+            long				modificationTime)
+        {
+			outStr.Write(
+				(byte) format,
+				(byte) encName.Length);
+
+			outStr.Write(encName);
+
+			long modDate = modificationTime / 1000L;
+
+			outStr.Write(
+				(byte)(modDate >> 24),
+				(byte)(modDate >> 16),
+				(byte)(modDate >> 8),
+				(byte)modDate);
+        }
+
+		/// <summary>
+		/// <p>
+		/// Open a literal data packet, returning a stream to store the data inside the packet.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// </summary>
+		/// <param name="outStr">The stream we want the packet in.</param>
+		/// <param name="format">The format we are using.</param>
+		/// <param name="name">The name of the 'file'.</param>
+		/// <param name="length">The length of the data we will write.</param>
+		/// <param name="modificationTime">The time of last modification we want stored.</param>
+        public Stream Open(
+            Stream		outStr,
+            char		format,
+            string		name,
+            long		length,
+            DateTime	modificationTime)
+        {
+			if (pkOut != null)
+				throw new InvalidOperationException("generator already in open state");
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			// Do this first, since it might throw an exception
+			long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
+
+            byte[] encName = Strings.ToUtf8ByteArray(name);
+
+            pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData,
+				length + 2 + encName.Length + 4, oldFormat);
+
+			WriteHeader(pkOut, format, encName, unixMs);
+
+			return new WrappedGeneratorStream(this, pkOut);
+        }
+
+        /// <summary>
+		/// <p>
+		/// Open a literal data packet, returning a stream to store the data inside the packet,
+		/// as an indefinite length stream. The stream is written out as a series of partial
+		/// packets with a chunk size determined by the size of the passed in buffer.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// <p>
+		/// <b>Note</b>: if the buffer is not a power of 2 in length only the largest power of 2
+		/// bytes worth of the buffer will be used.</p>
+		/// </summary>
+		/// <param name="outStr">The stream we want the packet in.</param>
+		/// <param name="format">The format we are using.</param>
+		/// <param name="name">The name of the 'file'.</param>
+		/// <param name="modificationTime">The time of last modification we want stored.</param>
+		/// <param name="buffer">The buffer to use for collecting data to put into chunks.</param>
+        public Stream Open(
+            Stream		outStr,
+            char		format,
+            string		name,
+            DateTime	modificationTime,
+            byte[]		buffer)
+        {
+			if (pkOut != null)
+				throw new InvalidOperationException("generator already in open state");
+			if (outStr == null)
+				throw new ArgumentNullException("outStr");
+
+			// Do this first, since it might throw an exception
+			long unixMs = DateTimeUtilities.DateTimeToUnixMs(modificationTime);
+
+            byte[] encName = Strings.ToUtf8ByteArray(name);
+
+			pkOut = new BcpgOutputStream(outStr, PacketTag.LiteralData, buffer);
+
+            WriteHeader(pkOut, format, encName, unixMs);
+
+			return new WrappedGeneratorStream(this, pkOut);
+		}
+
+#if !PCL
+		/// <summary>
+		/// <p>
+		/// Open a literal data packet for the passed in <c>FileInfo</c> object, returning
+		/// an output stream for saving the file contents.
+		/// </p>
+		/// <p>
+		/// The stream created can be closed off by either calling Close()
+		/// on the stream or Close() on the generator. Closing the returned
+		/// stream does not close off the Stream parameter <c>outStr</c>.
+		/// </p>
+		/// </summary>
+		/// <param name="outStr">The stream we want the packet in.</param>
+		/// <param name="format">The format we are using.</param>
+		/// <param name="file">The <c>FileInfo</c> object containg the packet details.</param>
+		public Stream Open(
+            Stream		outStr,
+            char		format,
+            FileInfo	file)
+        {
+			return Open(outStr, format, file.Name, file.Length, file.LastWriteTime);
+        }
+#endif
+
+		/// <summary>
+		/// Close the literal data packet - this is equivalent to calling Close()
+		/// on the stream returned by the Open() method.
+		/// </summary>
+        public void Close()
+        {
+			if (pkOut != null)
+			{
+				pkOut.Finish();
+				pkOut.Flush();
+				pkOut = null;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpMarker.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpMarker.cs
new file mode 100644
index 0000000..99fa4c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpMarker.cs
@@ -0,0 +1,18 @@
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// A PGP marker packet - in general these should be ignored other than where
+	/// the idea is to preserve the original input stream.
+	/// </remarks>
+    public class PgpMarker
+		: PgpObject
+    {
+        //private readonly MarkerPacket p;
+
+		public PgpMarker(
+            BcpgInputStream bcpgIn)
+        {
+            /*p = (MarkerPacket)*/ bcpgIn.ReadPacket();
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpObjectFactory.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpObjectFactory.cs
new file mode 100644
index 0000000..c5c6fcb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpObjectFactory.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+    /// General class for reading a PGP object stream.
+    /// <p>
+    /// Note: if this class finds a PgpPublicKey or a PgpSecretKey it
+    /// will create a PgpPublicKeyRing, or a PgpSecretKeyRing for each
+    /// key found. If all you are trying to do is read a key ring file use
+    /// either PgpPublicKeyRingBundle or PgpSecretKeyRingBundle.</p>
+	/// </remarks>
+	public class PgpObjectFactory
+    {
+        private readonly BcpgInputStream bcpgIn;
+
+		public PgpObjectFactory(
+            Stream inputStream)
+        {
+            this.bcpgIn = BcpgInputStream.Wrap(inputStream);
+        }
+
+        public PgpObjectFactory(
+            byte[] bytes)
+            : this(new MemoryStream(bytes, false))
+        {
+        }
+
+		/// <summary>Return the next object in the stream, or null if the end is reached.</summary>
+		/// <exception cref="IOException">On a parse error</exception>
+        public PgpObject NextPgpObject()
+        {
+            PacketTag tag = bcpgIn.NextPacketTag();
+
+            if ((int) tag == -1) return null;
+
+            switch (tag)
+            {
+                case PacketTag.Signature:
+                {
+                    IList l = Platform.CreateArrayList();
+
+                    while (bcpgIn.NextPacketTag() == PacketTag.Signature)
+                    {
+                        try
+                        {
+                            l.Add(new PgpSignature(bcpgIn));
+                        }
+                        catch (PgpException e)
+                        {
+                            throw new IOException("can't create signature object: " + e);
+                        }
+                    }
+
+                    PgpSignature[] sigs = new PgpSignature[l.Count];
+                    for (int i = 0; i < l.Count; ++i)
+                    {
+                        sigs[i] = (PgpSignature)l[i];
+                    }
+					return new PgpSignatureList(sigs);
+                }
+                case PacketTag.SecretKey:
+                    try
+                    {
+                        return new PgpSecretKeyRing(bcpgIn);
+                    }
+                    catch (PgpException e)
+                    {
+                        throw new IOException("can't create secret key object: " + e);
+                    }
+                case PacketTag.PublicKey:
+                    return new PgpPublicKeyRing(bcpgIn);
+				// TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing
+//				case PacketTag.PublicSubkey:
+//					return PgpPublicKeyRing.ReadSubkey(bcpgIn);
+                case PacketTag.CompressedData:
+                    return new PgpCompressedData(bcpgIn);
+                case PacketTag.LiteralData:
+                    return new PgpLiteralData(bcpgIn);
+                case PacketTag.PublicKeyEncryptedSession:
+                case PacketTag.SymmetricKeyEncryptedSessionKey:
+                    return new PgpEncryptedDataList(bcpgIn);
+                case PacketTag.OnePassSignature:
+                {
+                    IList l = Platform.CreateArrayList();
+
+                    while (bcpgIn.NextPacketTag() == PacketTag.OnePassSignature)
+                    {
+                        try
+                        {
+                            l.Add(new PgpOnePassSignature(bcpgIn));
+                        }
+                        catch (PgpException e)
+                        {
+							throw new IOException("can't create one pass signature object: " + e);
+						}
+                    }
+
+                    PgpOnePassSignature[] sigs = new PgpOnePassSignature[l.Count];
+                    for (int i = 0; i < l.Count; ++i)
+                    {
+                        sigs[i] = (PgpOnePassSignature)l[i];
+                    }
+					return new PgpOnePassSignatureList(sigs);
+                }
+                case PacketTag.Marker:
+                    return new PgpMarker(bcpgIn);
+                case PacketTag.Experimental1:
+                case PacketTag.Experimental2:
+                case PacketTag.Experimental3:
+                case PacketTag.Experimental4:
+					return new PgpExperimental(bcpgIn);
+            }
+
+            throw new IOException("unknown object in stream " + bcpgIn.NextPacketTag());
+        }
+
+		[Obsolete("Use NextPgpObject() instead")]
+		public object NextObject()
+		{
+			return NextPgpObject();
+		}
+
+		/// <summary>
+		/// Return all available objects in a list.
+		/// </summary>
+		/// <returns>An <c>IList</c> containing all objects from this factory, in order.</returns>
+		public IList AllPgpObjects()
+		{
+            IList result = Platform.CreateArrayList();
+			PgpObject pgpObject;
+			while ((pgpObject = NextPgpObject()) != null)
+			{
+				result.Add(pgpObject);
+			}
+			return result;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignature.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignature.cs
new file mode 100644
index 0000000..68fc599
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignature.cs
@@ -0,0 +1,179 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A one pass signature object.</remarks>
+    public class PgpOnePassSignature
+    {
+        private OnePassSignaturePacket sigPack;
+        private int signatureType;
+		private ISigner sig;
+		private byte lastb;
+
+		internal PgpOnePassSignature(
+            BcpgInputStream bcpgInput)
+            : this((OnePassSignaturePacket) bcpgInput.ReadPacket())
+        {
+        }
+
+		internal PgpOnePassSignature(
+            OnePassSignaturePacket sigPack)
+        {
+            this.sigPack = sigPack;
+            this.signatureType = sigPack.SignatureType;
+        }
+
+		/// <summary>Initialise the signature object for verification.</summary>
+        public void InitVerify(
+            PgpPublicKey pubKey)
+        {
+			lastb = 0;
+
+			try
+			{
+				sig = SignerUtilities.GetSigner(
+					PgpUtilities.GetSignatureName(sigPack.KeyAlgorithm, sigPack.HashAlgorithm));
+			}
+			catch (Exception e)
+			{
+				throw new PgpException("can't set up signature object.",  e);
+			}
+
+			try
+            {
+                sig.Init(false, pubKey.GetKey());
+            }
+			catch (InvalidKeyException e)
+            {
+                throw new PgpException("invalid key.", e);
+            }
+        }
+
+		public void Update(
+            byte b)
+        {
+			if (signatureType == PgpSignature.CanonicalTextDocument)
+			{
+				doCanonicalUpdateByte(b);
+			}
+			else
+			{
+				sig.Update(b);
+			}
+        }
+
+		private void doCanonicalUpdateByte(
+			byte b)
+		{
+			if (b == '\r')
+			{
+				doUpdateCRLF();
+			}
+			else if (b == '\n')
+			{
+				if (lastb != '\r')
+				{
+					doUpdateCRLF();
+				}
+			}
+			else
+			{
+				sig.Update(b);
+			}
+
+			lastb = b;
+		}
+
+		private void doUpdateCRLF()
+		{
+			sig.Update((byte)'\r');
+			sig.Update((byte)'\n');
+		}
+
+		public void Update(
+            byte[] bytes)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+                for (int i = 0; i != bytes.Length; i++)
+                {
+                    doCanonicalUpdateByte(bytes[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(bytes, 0, bytes.Length);
+            }
+        }
+
+        public void Update(
+            byte[]  bytes,
+            int     off,
+            int     length)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+                int finish = off + length;
+
+                for (int i = off; i != finish; i++)
+                {
+                    doCanonicalUpdateByte(bytes[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(bytes, off, length);
+            }
+        }
+
+		/// <summary>Verify the calculated signature against the passed in PgpSignature.</summary>
+        public bool Verify(
+            PgpSignature pgpSig)
+        {
+            byte[] trailer = pgpSig.GetSignatureTrailer();
+
+			sig.BlockUpdate(trailer, 0, trailer.Length);
+
+			return sig.VerifySignature(pgpSig.GetSignature());
+        }
+
+        public long KeyId
+        {
+			get { return sigPack.KeyId; }
+        }
+
+		public int SignatureType
+        {
+            get { return sigPack.SignatureType; }
+        }
+
+		public HashAlgorithmTag HashAlgorithm
+		{
+			get { return sigPack.HashAlgorithm; }
+		}
+
+		public PublicKeyAlgorithmTag KeyAlgorithm
+		{
+			get { return sigPack.KeyAlgorithm; }
+		}
+
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+            Encode(bOut);
+
+            return bOut.ToArray();
+        }
+
+		public void Encode(
+            Stream outStr)
+        {
+            BcpgOutputStream.Wrap(outStr).WritePacket(sigPack);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignatureList.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignatureList.cs
new file mode 100644
index 0000000..37c4288
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpOnePassSignatureList.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Holder for a list of PgpOnePassSignature objects.</remarks>
+    public class PgpOnePassSignatureList
+		: PgpObject
+    {
+        private readonly PgpOnePassSignature[] sigs;
+
+		public PgpOnePassSignatureList(
+            PgpOnePassSignature[] sigs)
+        {
+			this.sigs = (PgpOnePassSignature[]) sigs.Clone();
+        }
+
+		public PgpOnePassSignatureList(
+            PgpOnePassSignature sig)
+        {
+			this.sigs = new PgpOnePassSignature[]{ sig };
+        }
+
+		public PgpOnePassSignature this[int index]
+		{
+			get { return sigs[index]; }
+		}
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public PgpOnePassSignature Get(
+            int index)
+        {
+            return this[index];
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+        {
+			get { return sigs.Length; }
+        }
+
+		public int Count
+		{
+			get { return sigs.Length; }
+		}
+
+		public bool IsEmpty
+        {
+			get { return (sigs.Length == 0); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPbeEncryptedData.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPbeEncryptedData.cs
new file mode 100644
index 0000000..c5fe894
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPbeEncryptedData.cs
@@ -0,0 +1,135 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A password based encryption object.</remarks>
+    public class PgpPbeEncryptedData
+        : PgpEncryptedData
+    {
+        private readonly SymmetricKeyEncSessionPacket keyData;
+
+		internal PgpPbeEncryptedData(
+			SymmetricKeyEncSessionPacket	keyData,
+			InputStreamPacket				encData)
+			: base(encData)
+		{
+			this.keyData = keyData;
+		}
+
+		/// <summary>Return the raw input stream for the data stream.</summary>
+		public override Stream GetInputStream()
+		{
+			return encData.GetInputStream();
+		}
+
+		/// <summary>Return the decrypted input stream, using the passed in passphrase.</summary>
+        public Stream GetDataStream(
+            char[] passPhrase)
+        {
+			try
+			{
+				SymmetricKeyAlgorithmTag keyAlgorithm = keyData.EncAlgorithm;
+
+				KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(
+					keyAlgorithm, keyData.S2k, passPhrase);
+
+
+				byte[] secKeyData = keyData.GetSecKeyData();
+				if (secKeyData != null && secKeyData.Length > 0)
+				{
+					IBufferedCipher keyCipher = CipherUtilities.GetCipher(
+						PgpUtilities.GetSymmetricCipherName(keyAlgorithm) + "/CFB/NoPadding");
+
+					keyCipher.Init(false,
+						new ParametersWithIV(key, new byte[keyCipher.GetBlockSize()]));
+
+					byte[] keyBytes = keyCipher.DoFinal(secKeyData);
+
+					keyAlgorithm = (SymmetricKeyAlgorithmTag) keyBytes[0];
+
+					key = ParameterUtilities.CreateKeyParameter(
+						PgpUtilities.GetSymmetricCipherName(keyAlgorithm),
+						keyBytes, 1, keyBytes.Length - 1);
+				}
+
+
+				IBufferedCipher c = CreateStreamCipher(keyAlgorithm);
+
+				byte[] iv = new byte[c.GetBlockSize()];
+
+				c.Init(false, new ParametersWithIV(key, iv));
+
+				encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c, null));
+
+				if (encData is SymmetricEncIntegrityPacket)
+				{
+					truncStream = new TruncatedStream(encStream);
+
+					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
+					IDigest digest = DigestUtilities.GetDigest(digestName);
+
+					encStream = new DigestStream(truncStream, digest, null);
+				}
+
+				if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
+					throw new EndOfStreamException("unexpected end of stream.");
+
+				int v1 = encStream.ReadByte();
+				int v2 = encStream.ReadByte();
+
+				if (v1 < 0 || v2 < 0)
+					throw new EndOfStreamException("unexpected end of stream.");
+
+
+				// Note: the oracle attack on the "quick check" bytes is not deemed
+				// a security risk for PBE (see PgpPublicKeyEncryptedData)
+
+				bool repeatCheckPassed =
+						iv[iv.Length - 2] == (byte)v1
+					&&	iv[iv.Length - 1] == (byte)v2;
+
+				// Note: some versions of PGP appear to produce 0 for the extra
+				// bytes rather than repeating the two previous bytes
+				bool zeroesCheckPassed =
+						v1 == 0
+					&&	v2 == 0;
+
+				if (!repeatCheckPassed && !zeroesCheckPassed)
+				{
+					throw new PgpDataValidationException("quick check failed.");
+				}
+
+
+				return encStream;
+			}
+			catch (PgpException e)
+			{
+				throw e;
+			}
+			catch (Exception e)
+			{
+				throw new PgpException("Exception creating cipher", e);
+			}
+		}
+
+		private IBufferedCipher CreateStreamCipher(
+			SymmetricKeyAlgorithmTag keyAlgorithm)
+		{
+			string mode = (encData is SymmetricEncIntegrityPacket)
+				? "CFB"
+				: "OpenPGPCFB";
+
+			string cName = PgpUtilities.GetSymmetricCipherName(keyAlgorithm)
+				+ "/" + mode + "/NoPadding";
+
+			return CipherUtilities.GetCipher(cName);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPrivateKey.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPrivateKey.cs
new file mode 100644
index 0000000..154c87c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPrivateKey.cs
@@ -0,0 +1,42 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>General class to contain a private key for use with other OpenPGP objects.</remarks>
+    public class PgpPrivateKey
+    {
+        private readonly long keyId;
+        private readonly AsymmetricKeyParameter privateKey;
+
+		/// <summary>
+		/// Create a PgpPrivateKey from a regular private key and the ID of its
+		/// associated public key.
+		/// </summary>
+		/// <param name="privateKey">Private key to use.</param>
+		/// <param name="keyId">ID of the corresponding public key.</param>
+		public PgpPrivateKey(
+            AsymmetricKeyParameter	privateKey,
+            long					keyId)
+        {
+			if (!privateKey.IsPrivate)
+				throw new ArgumentException("Expected a private key", "privateKey");
+
+			this.privateKey = privateKey;
+            this.keyId = keyId;
+        }
+
+		/// <summary>The keyId associated with the contained private key.</summary>
+        public long KeyId
+        {
+			get { return keyId; }
+        }
+
+		/// <summary>The contained private key.</summary>
+        public AsymmetricKeyParameter Key
+        {
+			get { return privateKey; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKey.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKey.cs
new file mode 100644
index 0000000..b072014
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKey.cs
@@ -0,0 +1,890 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>General class to handle a PGP public key object.</remarks>
+    public class PgpPublicKey
+    {
+		private static readonly int[] MasterKeyCertificationTypes = new int[]
+		{
+			PgpSignature.PositiveCertification,
+			PgpSignature.CasualCertification,
+			PgpSignature.NoCertification,
+			PgpSignature.DefaultCertification
+		};
+
+		private long				keyId;
+        private byte[]				fingerprint;
+        private int					keyStrength;
+
+		internal PublicKeyPacket	publicPk;
+        internal TrustPacket		trustPk;
+        internal IList			    keySigs = Platform.CreateArrayList();
+        internal IList			    ids = Platform.CreateArrayList();
+        internal IList              idTrusts = Platform.CreateArrayList();
+        internal IList              idSigs = Platform.CreateArrayList();
+        internal IList			    subSigs;
+
+		private void Init()
+        {
+            IBcpgKey key = publicPk.Key;
+
+			if (publicPk.Version <= 3)
+            {
+                RsaPublicBcpgKey rK = (RsaPublicBcpgKey) key;
+
+				this.keyId = rK.Modulus.LongValue;
+
+				try
+                {
+                    IDigest digest = DigestUtilities.GetDigest("MD5");
+
+					byte[] bytes = rK.Modulus.ToByteArrayUnsigned();
+					digest.BlockUpdate(bytes, 0, bytes.Length);
+
+					bytes = rK.PublicExponent.ToByteArrayUnsigned();
+					digest.BlockUpdate(bytes, 0, bytes.Length);
+
+					this.fingerprint = DigestUtilities.DoFinal(digest);
+                }
+				//catch (NoSuchAlgorithmException)
+				catch (Exception e)
+                {
+                    throw new IOException("can't find MD5", e);
+                }
+
+				this.keyStrength = rK.Modulus.BitLength;
+            }
+            else
+            {
+                byte[] kBytes = publicPk.GetEncodedContents();
+
+				try
+                {
+                    IDigest digest = DigestUtilities.GetDigest("SHA1");
+
+					digest.Update(0x99);
+                    digest.Update((byte)(kBytes.Length >> 8));
+                    digest.Update((byte)kBytes.Length);
+                    digest.BlockUpdate(kBytes, 0, kBytes.Length);
+                    this.fingerprint = DigestUtilities.DoFinal(digest);
+                }
+                catch (Exception e)
+                {
+                    throw new IOException("can't find SHA1", e);
+                }
+
+				this.keyId = (long)(((ulong)fingerprint[fingerprint.Length - 8] << 56)
+                    | ((ulong)fingerprint[fingerprint.Length - 7] << 48)
+                    | ((ulong)fingerprint[fingerprint.Length - 6] << 40)
+                    | ((ulong)fingerprint[fingerprint.Length - 5] << 32)
+                    | ((ulong)fingerprint[fingerprint.Length - 4] << 24)
+                    | ((ulong)fingerprint[fingerprint.Length - 3] << 16)
+                    | ((ulong)fingerprint[fingerprint.Length - 2] << 8)
+                    | (ulong)fingerprint[fingerprint.Length - 1]);
+
+				if (key is RsaPublicBcpgKey)
+                {
+                    this.keyStrength = ((RsaPublicBcpgKey)key).Modulus.BitLength;
+                }
+                else if (key is DsaPublicBcpgKey)
+                {
+                    this.keyStrength = ((DsaPublicBcpgKey)key).P.BitLength;
+                }
+                else if (key is ElGamalPublicBcpgKey)
+                {
+                    this.keyStrength = ((ElGamalPublicBcpgKey)key).P.BitLength;
+                }
+            }
+        }
+
+		/// <summary>
+		/// Create a PgpPublicKey from the passed in lightweight one.
+		/// </summary>
+		/// <remarks>
+		/// Note: the time passed in affects the value of the key's keyId, so you probably only want
+		/// to do this once for a lightweight key, or make sure you keep track of the time you used.
+		/// </remarks>
+		/// <param name="algorithm">Asymmetric algorithm type representing the public key.</param>
+		/// <param name="pubKey">Actual public key to associate.</param>
+		/// <param name="time">Date of creation.</param>
+		/// <exception cref="ArgumentException">If <c>pubKey</c> is not public.</exception>
+		/// <exception cref="PgpException">On key creation problem.</exception>
+        public PgpPublicKey(
+            PublicKeyAlgorithmTag	algorithm,
+            AsymmetricKeyParameter	pubKey,
+            DateTime				time)
+        {
+			if (pubKey.IsPrivate)
+				throw new ArgumentException("Expected a public key", "pubKey");
+
+			IBcpgKey bcpgKey;
+            if (pubKey is RsaKeyParameters)
+            {
+                RsaKeyParameters rK = (RsaKeyParameters) pubKey;
+
+				bcpgKey = new RsaPublicBcpgKey(rK.Modulus, rK.Exponent);
+            }
+            else if (pubKey is DsaPublicKeyParameters)
+            {
+                DsaPublicKeyParameters dK = (DsaPublicKeyParameters) pubKey;
+                DsaParameters dP = dK.Parameters;
+
+				bcpgKey = new DsaPublicBcpgKey(dP.P, dP.Q, dP.G, dK.Y);
+            }
+            else if (pubKey is ElGamalPublicKeyParameters)
+            {
+                ElGamalPublicKeyParameters eK = (ElGamalPublicKeyParameters) pubKey;
+                ElGamalParameters eS = eK.Parameters;
+
+				bcpgKey = new ElGamalPublicBcpgKey(eS.P, eS.G, eK.Y);
+            }
+            else
+            {
+                throw new PgpException("unknown key class");
+            }
+
+			this.publicPk = new PublicKeyPacket(algorithm, time, bcpgKey);
+            this.ids = Platform.CreateArrayList();
+            this.idSigs = Platform.CreateArrayList();
+
+			try
+            {
+                Init();
+            }
+            catch (IOException e)
+            {
+                throw new PgpException("exception calculating keyId", e);
+            }
+        }
+
+		/// <summary>Constructor for a sub-key.</summary>
+        internal PgpPublicKey(
+            PublicKeyPacket	publicPk,
+            TrustPacket		trustPk,
+            IList           sigs)
+        {
+            this.publicPk = publicPk;
+            this.trustPk = trustPk;
+            this.subSigs = sigs;
+
+			Init();
+        }
+
+		internal PgpPublicKey(
+            PgpPublicKey	key,
+            TrustPacket		trust,
+            IList           subSigs)
+        {
+            this.publicPk = key.publicPk;
+            this.trustPk = trust;
+            this.subSigs = subSigs;
+
+			this.fingerprint = key.fingerprint;
+            this.keyId = key.keyId;
+            this.keyStrength = key.keyStrength;
+        }
+
+		/// <summary>Copy constructor.</summary>
+		/// <param name="pubKey">The public key to copy.</param>
+        internal PgpPublicKey(
+            PgpPublicKey pubKey)
+        {
+            this.publicPk = pubKey.publicPk;
+
+			this.keySigs = Platform.CreateArrayList(pubKey.keySigs);
+            this.ids = Platform.CreateArrayList(pubKey.ids);
+            this.idTrusts = Platform.CreateArrayList(pubKey.idTrusts);
+            this.idSigs = Platform.CreateArrayList(pubKey.idSigs.Count);
+            for (int i = 0; i != pubKey.idSigs.Count; i++)
+            {
+                this.idSigs.Add(Platform.CreateArrayList((IList)pubKey.idSigs[i]));
+            }
+
+			if (pubKey.subSigs != null)
+            {
+                this.subSigs = Platform.CreateArrayList(pubKey.subSigs.Count);
+                for (int i = 0; i != pubKey.subSigs.Count; i++)
+                {
+                    this.subSigs.Add(pubKey.subSigs[i]);
+                }
+            }
+
+			this.fingerprint = pubKey.fingerprint;
+            this.keyId = pubKey.keyId;
+            this.keyStrength = pubKey.keyStrength;
+        }
+
+		internal PgpPublicKey(
+            PublicKeyPacket	publicPk,
+            TrustPacket		trustPk,
+            IList		    keySigs,
+            IList		    ids,
+            IList           idTrusts,
+            IList           idSigs)
+        {
+            this.publicPk = publicPk;
+            this.trustPk = trustPk;
+            this.keySigs = keySigs;
+            this.ids = ids;
+            this.idTrusts = idTrusts;
+            this.idSigs = idSigs;
+
+			Init();
+        }
+
+		internal PgpPublicKey(
+            PublicKeyPacket	publicPk,
+            IList           ids,
+            IList           idSigs)
+        {
+            this.publicPk = publicPk;
+            this.ids = ids;
+            this.idSigs = idSigs;
+            Init();
+        }
+
+		/// <summary>The version of this key.</summary>
+        public int Version
+        {
+			get { return publicPk.Version; }
+        }
+
+		/// <summary>The creation time of this key.</summary>
+		public DateTime CreationTime
+        {
+			get { return publicPk.GetTime(); }
+        }
+
+		/// <summary>The number of valid days from creation time - zero means no expiry.</summary>
+        public int ValidDays
+        {
+			get
+			{
+				if (publicPk.Version > 3)
+				{
+					return (int)(GetValidSeconds() / (24 * 60 * 60));
+				}
+
+				return publicPk.ValidDays;
+			}
+        }
+
+		/// <summary>Return the trust data associated with the public key, if present.</summary>
+		/// <returns>A byte array with trust data, null otherwise.</returns>
+		public byte[] GetTrustData()
+		{
+			if (trustPk == null)
+			{
+				return null;
+			}
+
+			return trustPk.GetLevelAndTrustAmount();
+		}
+
+		/// <summary>The number of valid seconds from creation time - zero means no expiry.</summary>
+		public long GetValidSeconds()
+        {
+			if (publicPk.Version > 3)
+			{
+				if (IsMasterKey)
+				{
+					for (int i = 0; i != MasterKeyCertificationTypes.Length; i++)
+					{
+						long seconds = GetExpirationTimeFromSig(true, MasterKeyCertificationTypes[i]);
+
+						if (seconds >= 0)
+						{
+							return seconds;
+						}
+					}
+				}
+				else
+				{
+					long seconds = GetExpirationTimeFromSig(false, PgpSignature.SubkeyBinding);
+
+					if (seconds >= 0)
+					{
+						return seconds;
+					}
+				}
+
+				return 0;
+			}
+
+			return (long) publicPk.ValidDays * 24 * 60 * 60;
+        }
+
+		private long GetExpirationTimeFromSig(
+			bool	selfSigned,
+			int		signatureType)
+		{
+			foreach (PgpSignature sig in GetSignaturesOfType(signatureType))
+			{
+				if (!selfSigned || sig.KeyId == KeyId)
+				{
+					PgpSignatureSubpacketVector hashed = sig.GetHashedSubPackets();
+
+					if (hashed != null)
+					{
+						return hashed.GetKeyExpirationTime();
+					}
+
+					return 0;
+				}
+			}
+
+			return -1;
+		}
+
+		/// <summary>The keyId associated with the public key.</summary>
+        public long KeyId
+        {
+            get { return keyId; }
+        }
+
+		/// <summary>The fingerprint of the key</summary>
+        public byte[] GetFingerprint()
+        {
+			return (byte[]) fingerprint.Clone();
+        }
+
+		/// <summary>
+		/// Check if this key has an algorithm type that makes it suitable to use for encryption.
+		/// </summary>
+		/// <remarks>
+		/// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+		/// determining the preferred use of the key.
+		/// </remarks>
+		/// <returns>
+		/// <c>true</c> if this key algorithm is suitable for encryption.
+		/// </returns>
+		public bool IsEncryptionKey
+        {
+            get
+            {
+				switch (publicPk.Algorithm)
+				{
+					case PublicKeyAlgorithmTag.ElGamalEncrypt:
+					case PublicKeyAlgorithmTag.ElGamalGeneral:
+					case PublicKeyAlgorithmTag.RsaEncrypt:
+					case PublicKeyAlgorithmTag.RsaGeneral:
+						return true;
+					default:
+						return false;
+				}
+            }
+        }
+
+		/// <summary>True, if this is a master key.</summary>
+        public bool IsMasterKey
+        {
+            get { return subSigs == null; }
+        }
+
+		/// <summary>The algorithm code associated with the public key.</summary>
+        public PublicKeyAlgorithmTag Algorithm
+        {
+			get { return publicPk.Algorithm; }
+        }
+
+		/// <summary>The strength of the key in bits.</summary>
+        public int BitStrength
+        {
+            get { return keyStrength; }
+        }
+
+		/// <summary>The public key contained in the object.</summary>
+		/// <returns>A lightweight public key.</returns>
+		/// <exception cref="PgpException">If the key algorithm is not recognised.</exception>
+        public AsymmetricKeyParameter GetKey()
+        {
+            try
+            {
+                switch (publicPk.Algorithm)
+                {
+                    case PublicKeyAlgorithmTag.RsaEncrypt:
+                    case PublicKeyAlgorithmTag.RsaGeneral:
+                    case PublicKeyAlgorithmTag.RsaSign:
+                        RsaPublicBcpgKey rsaK = (RsaPublicBcpgKey) publicPk.Key;
+                        return new RsaKeyParameters(false, rsaK.Modulus, rsaK.PublicExponent);
+                    case PublicKeyAlgorithmTag.Dsa:
+                        DsaPublicBcpgKey dsaK = (DsaPublicBcpgKey) publicPk.Key;
+                        return new DsaPublicKeyParameters(dsaK.Y, new DsaParameters(dsaK.P, dsaK.Q, dsaK.G));
+                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                    case PublicKeyAlgorithmTag.ElGamalGeneral:
+                        ElGamalPublicBcpgKey elK = (ElGamalPublicBcpgKey) publicPk.Key;
+                        return new ElGamalPublicKeyParameters(elK.Y, new ElGamalParameters(elK.P, elK.G));
+                    default:
+                        throw new PgpException("unknown public key algorithm encountered");
+                }
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("exception constructing public key", e);
+            }
+        }
+
+		/// <summary>Allows enumeration of any user IDs associated with the key.</summary>
+		/// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        public IEnumerable GetUserIds()
+        {
+            IList temp = Platform.CreateArrayList();
+
+			foreach (object o in ids)
+			{
+				if (o is string)
+				{
+					temp.Add(o);
+                }
+            }
+
+			return new EnumerableProxy(temp);
+        }
+
+		/// <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+		/// <returns>An <c>IEnumerable</c> of <c>PgpUserAttributeSubpacketVector</c> objects.</returns>
+        public IEnumerable GetUserAttributes()
+        {
+            IList temp = Platform.CreateArrayList();
+
+			foreach (object o in ids)
+			{
+				if (o is PgpUserAttributeSubpacketVector)
+				{
+					temp.Add(o);
+				}
+			}
+
+			return new EnumerableProxy(temp);
+        }
+
+		/// <summary>Allows enumeration of any signatures associated with the passed in id.</summary>
+		/// <param name="id">The ID to be matched.</param>
+		/// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        public IEnumerable GetSignaturesForId(
+            string id)
+        {
+			if (id == null)
+				throw new ArgumentNullException("id");
+
+			for (int i = 0; i != ids.Count; i++)
+            {
+                if (id.Equals(ids[i]))
+                {
+                    return new EnumerableProxy((IList)idSigs[i]);
+                }
+            }
+
+			return null;
+        }
+
+		/// <summary>Allows enumeration of signatures associated with the passed in user attributes.</summary>
+		/// <param name="userAttributes">The vector of user attributes to be matched.</param>
+		/// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        public IEnumerable GetSignaturesForUserAttribute(
+            PgpUserAttributeSubpacketVector userAttributes)
+        {
+            for (int i = 0; i != ids.Count; i++)
+            {
+                if (userAttributes.Equals(ids[i]))
+                {
+                    return new EnumerableProxy((IList) idSigs[i]);
+                }
+            }
+
+			return null;
+        }
+
+		/// <summary>Allows enumeration of signatures of the passed in type that are on this key.</summary>
+		/// <param name="signatureType">The type of the signature to be returned.</param>
+		/// <returns>An <c>IEnumerable</c> of <c>PgpSignature</c> objects.</returns>
+        public IEnumerable GetSignaturesOfType(
+            int signatureType)
+        {
+            IList temp = Platform.CreateArrayList();
+
+			foreach (PgpSignature sig in GetSignatures())
+            {
+                if (sig.SignatureType == signatureType)
+                {
+                    temp.Add(sig);
+                }
+            }
+
+			return new EnumerableProxy(temp);
+        }
+
+		/// <summary>Allows enumeration of all signatures/certifications associated with this key.</summary>
+		/// <returns>An <c>IEnumerable</c> with all signatures/certifications.</returns>
+        public IEnumerable GetSignatures()
+        {
+			IList sigs;
+			if (subSigs != null)
+			{
+				sigs = subSigs;
+			}
+			else
+			{
+                sigs = Platform.CreateArrayList(keySigs);
+
+				foreach (ICollection extraSigs in idSigs)
+				{
+                    CollectionUtilities.AddRange(sigs, extraSigs);
+				}
+			}
+
+			return new EnumerableProxy(sigs);
+        }
+
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+            Encode(bOut);
+            return bOut.ToArray();
+        }
+
+		public void Encode(
+            Stream outStr)
+        {
+            BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+			bcpgOut.WritePacket(publicPk);
+            if (trustPk != null)
+            {
+                bcpgOut.WritePacket(trustPk);
+            }
+
+			if (subSigs == null)    // not a sub-key
+            {
+				foreach (PgpSignature keySig in keySigs)
+				{
+					keySig.Encode(bcpgOut);
+				}
+
+				for (int i = 0; i != ids.Count; i++)
+                {
+                    if (ids[i] is string)
+                    {
+                        string id = (string) ids[i];
+
+						bcpgOut.WritePacket(new UserIdPacket(id));
+                    }
+                    else
+                    {
+                        PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector)ids[i];
+                        bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
+                    }
+
+					if (idTrusts[i] != null)
+                    {
+                        bcpgOut.WritePacket((ContainedPacket)idTrusts[i]);
+                    }
+
+					foreach (PgpSignature sig in (IList) idSigs[i])
+					{
+						sig.Encode(bcpgOut);
+					}
+                }
+            }
+            else
+            {
+				foreach (PgpSignature subSig in subSigs)
+				{
+					subSig.Encode(bcpgOut);
+				}
+            }
+        }
+
+		/// <summary>Check whether this (sub)key has a revocation signature on it.</summary>
+		/// <returns>True, if this (sub)key has been revoked.</returns>
+        public bool IsRevoked()
+        {
+            int ns = 0;
+            bool revoked = false;
+            if (IsMasterKey)	// Master key
+            {
+                while (!revoked && (ns < keySigs.Count))
+                {
+                    if (((PgpSignature)keySigs[ns++]).SignatureType == PgpSignature.KeyRevocation)
+                    {
+                        revoked = true;
+                    }
+                }
+            }
+            else	// Sub-key
+            {
+                while (!revoked && (ns < subSigs.Count))
+                {
+                    if (((PgpSignature)subSigs[ns++]).SignatureType == PgpSignature.SubkeyRevocation)
+                    {
+                        revoked = true;
+                    }
+                }
+            }
+            return revoked;
+        }
+
+		/// <summary>Add a certification for an id to the given public key.</summary>
+		/// <param name="key">The key the certification is to be added to.</param>
+		/// <param name="id">The ID the certification is associated with.</param>
+		/// <param name="certification">The new certification.</param>
+		/// <returns>The re-certified key.</returns>
+        public static PgpPublicKey AddCertification(
+            PgpPublicKey	key,
+            string			id,
+            PgpSignature	certification)
+        {
+			return AddCert(key, id, certification);
+		}
+
+		/// <summary>Add a certification for the given UserAttributeSubpackets to the given public key.</summary>
+		/// <param name="key">The key the certification is to be added to.</param>
+		/// <param name="userAttributes">The attributes the certification is associated with.</param>
+		/// <param name="certification">The new certification.</param>
+		/// <returns>The re-certified key.</returns>
+		public static PgpPublicKey AddCertification(
+			PgpPublicKey					key,
+			PgpUserAttributeSubpacketVector	userAttributes,
+			PgpSignature					certification)
+		{
+			return AddCert(key, userAttributes, certification);
+		}
+
+		private static PgpPublicKey AddCert(
+			PgpPublicKey	key,
+			object			id,
+			PgpSignature	certification)
+		{
+			PgpPublicKey returnKey = new PgpPublicKey(key);
+			IList sigList = null;
+
+			for (int i = 0; i != returnKey.ids.Count; i++)
+			{
+				if (id.Equals(returnKey.ids[i]))
+				{
+					sigList = (IList) returnKey.idSigs[i];
+				}
+			}
+
+			if (sigList != null)
+			{
+				sigList.Add(certification);
+			}
+			else
+			{
+				sigList = Platform.CreateArrayList();
+				sigList.Add(certification);
+				returnKey.ids.Add(id);
+				returnKey.idTrusts.Add(null);
+				returnKey.idSigs.Add(sigList);
+			}
+
+			return returnKey;
+		}
+
+		/// <summary>
+		/// Remove any certifications associated with a user attribute subpacket on a key.
+		/// </summary>
+		/// <param name="key">The key the certifications are to be removed from.</param>
+		/// <param name="userAttributes">The attributes to be removed.</param>
+		/// <returns>
+		/// The re-certified key, or null if the user attribute subpacket was not found on the key.
+		/// </returns>
+		public static PgpPublicKey RemoveCertification(
+			PgpPublicKey					key,
+			PgpUserAttributeSubpacketVector	userAttributes)
+		{
+			return RemoveCert(key, userAttributes);
+		}
+
+		/// <summary>Remove any certifications associated with a given ID on a key.</summary>
+		/// <param name="key">The key the certifications are to be removed from.</param>
+		/// <param name="id">The ID that is to be removed.</param>
+		/// <returns>The re-certified key, or null if the ID was not found on the key.</returns>
+        public static PgpPublicKey RemoveCertification(
+            PgpPublicKey	key,
+            string			id)
+        {
+			return RemoveCert(key, id);
+		}
+
+		private static PgpPublicKey RemoveCert(
+			PgpPublicKey	key,
+			object			id)
+		{
+			PgpPublicKey returnKey = new PgpPublicKey(key);
+            bool found = false;
+
+			for (int i = 0; i < returnKey.ids.Count; i++)
+            {
+                if (id.Equals(returnKey.ids[i]))
+                {
+                    found = true;
+                    returnKey.ids.RemoveAt(i);
+                    returnKey.idTrusts.RemoveAt(i);
+                    returnKey.idSigs.RemoveAt(i);
+                }
+            }
+
+			return found ? returnKey : null;
+        }
+
+		/// <summary>Remove a certification associated with a given ID on a key.</summary>
+		/// <param name="key">The key the certifications are to be removed from.</param>
+		/// <param name="id">The ID that the certfication is to be removed from.</param>
+		/// <param name="certification">The certfication to be removed.</param>
+		/// <returns>The re-certified key, or null if the certification was not found.</returns>
+        public static PgpPublicKey RemoveCertification(
+            PgpPublicKey	key,
+            string			id,
+            PgpSignature	certification)
+        {
+			return RemoveCert(key, id, certification);
+		}
+
+		/// <summary>Remove a certification associated with a given user attributes on a key.</summary>
+		/// <param name="key">The key the certifications are to be removed from.</param>
+		/// <param name="userAttributes">The user attributes that the certfication is to be removed from.</param>
+		/// <param name="certification">The certification to be removed.</param>
+		/// <returns>The re-certified key, or null if the certification was not found.</returns>
+		public static PgpPublicKey RemoveCertification(
+			PgpPublicKey					key,
+			PgpUserAttributeSubpacketVector	userAttributes,
+			PgpSignature					certification)
+		{
+			return RemoveCert(key, userAttributes, certification);
+		}
+
+		private static PgpPublicKey RemoveCert(
+			PgpPublicKey	key,
+			object			id,
+			PgpSignature	certification)
+		{
+			PgpPublicKey returnKey = new PgpPublicKey(key);
+            bool found = false;
+
+			for (int i = 0; i < returnKey.ids.Count; i++)
+            {
+                if (id.Equals(returnKey.ids[i]))
+                {
+                    IList certs = (IList) returnKey.idSigs[i];
+                    found = certs.Contains(certification);
+
+					if (found)
+					{
+						certs.Remove(certification);
+					}
+                }
+            }
+
+			return found ? returnKey : null;
+        }
+
+		/// <summary>Add a revocation or some other key certification to a key.</summary>
+		/// <param name="key">The key the revocation is to be added to.</param>
+		/// <param name="certification">The key signature to be added.</param>
+		/// <returns>The new changed public key object.</returns>
+        public static PgpPublicKey AddCertification(
+            PgpPublicKey	key,
+            PgpSignature	certification)
+        {
+            if (key.IsMasterKey)
+            {
+                if (certification.SignatureType == PgpSignature.SubkeyRevocation)
+                {
+                    throw new ArgumentException("signature type incorrect for master key revocation.");
+                }
+            }
+            else
+            {
+                if (certification.SignatureType == PgpSignature.KeyRevocation)
+                {
+                    throw new ArgumentException("signature type incorrect for sub-key revocation.");
+                }
+            }
+
+			PgpPublicKey returnKey = new PgpPublicKey(key);
+
+			if (returnKey.subSigs != null)
+            {
+                returnKey.subSigs.Add(certification);
+            }
+            else
+            {
+                returnKey.keySigs.Add(certification);
+            }
+
+			return returnKey;
+        }
+
+		/// <summary>Remove a certification from the key.</summary>
+		/// <param name="key">The key the certifications are to be removed from.</param>
+		/// <param name="certification">The certfication to be removed.</param>
+		/// <returns>The modified key, null if the certification was not found.</returns>
+		public static PgpPublicKey RemoveCertification(
+			PgpPublicKey	key,
+			PgpSignature	certification)
+		{
+			PgpPublicKey returnKey = new PgpPublicKey(key);
+			IList sigs = returnKey.subSigs != null
+				?	returnKey.subSigs
+				:	returnKey.keySigs;
+
+//			bool found = sigs.Remove(certification);
+			int pos = sigs.IndexOf(certification);
+			bool found = pos >= 0;
+
+			if (found)
+			{
+				sigs.RemoveAt(pos);
+			}
+			else
+			{
+				foreach (String id in key.GetUserIds())
+				{
+					foreach (object sig in key.GetSignaturesForId(id))
+					{
+						// TODO Is this the right type of equality test?
+						if (certification == sig)
+						{
+							found = true;
+							returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+						}
+					}
+				}
+
+				if (!found)
+				{
+					foreach (PgpUserAttributeSubpacketVector id in key.GetUserAttributes())
+					{
+						foreach (object sig in key.GetSignaturesForUserAttribute(id))
+						{
+							// TODO Is this the right type of equality test?
+							if (certification == sig)
+							{
+								found = true;
+								returnKey = PgpPublicKey.RemoveCertification(returnKey, id, certification);
+							}
+						}
+					}
+				}
+			}
+
+			return returnKey;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyEncryptedData.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyEncryptedData.cs
new file mode 100644
index 0000000..b6504cb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyEncryptedData.cs
@@ -0,0 +1,252 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A public key encrypted data object.</remarks>
+    public class PgpPublicKeyEncryptedData
+        : PgpEncryptedData
+    {
+        private PublicKeyEncSessionPacket keyData;
+
+		internal PgpPublicKeyEncryptedData(
+            PublicKeyEncSessionPacket	keyData,
+            InputStreamPacket			encData)
+            : base(encData)
+        {
+            this.keyData = keyData;
+        }
+
+		private static IBufferedCipher GetKeyCipher(
+            PublicKeyAlgorithmTag algorithm)
+        {
+            try
+            {
+                switch (algorithm)
+                {
+                    case PublicKeyAlgorithmTag.RsaEncrypt:
+                    case PublicKeyAlgorithmTag.RsaGeneral:
+                        return CipherUtilities.GetCipher("RSA//PKCS1Padding");
+                    case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                    case PublicKeyAlgorithmTag.ElGamalGeneral:
+                        return CipherUtilities.GetCipher("ElGamal/ECB/PKCS1Padding");
+                    default:
+                        throw new PgpException("unknown asymmetric algorithm: " + algorithm);
+                }
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception creating cipher", e);
+            }
+        }
+
+		private bool ConfirmCheckSum(
+            byte[] sessionInfo)
+        {
+            int check = 0;
+
+			for (int i = 1; i != sessionInfo.Length - 2; i++)
+            {
+                check += sessionInfo[i] & 0xff;
+            }
+
+			return (sessionInfo[sessionInfo.Length - 2] == (byte)(check >> 8))
+                && (sessionInfo[sessionInfo.Length - 1] == (byte)(check));
+        }
+
+		/// <summary>The key ID for the key used to encrypt the data.</summary>
+        public long KeyId
+        {
+			get { return keyData.KeyId; }
+        }
+
+		/// <summary>
+		/// Return the algorithm code for the symmetric algorithm used to encrypt the data.
+		/// </summary>
+		public SymmetricKeyAlgorithmTag GetSymmetricAlgorithm(
+			PgpPrivateKey privKey)
+		{
+			byte[] plain = fetchSymmetricKeyData(privKey);
+
+			return (SymmetricKeyAlgorithmTag) plain[0];
+		}
+
+		/// <summary>Return the decrypted data stream for the packet.</summary>
+        public Stream GetDataStream(
+            PgpPrivateKey privKey)
+        {
+			byte[] plain = fetchSymmetricKeyData(privKey);
+
+			IBufferedCipher c2;
+			string cipherName = PgpUtilities.GetSymmetricCipherName((SymmetricKeyAlgorithmTag) plain[0]);
+			string cName = cipherName;
+
+			try
+            {
+                if (encData is SymmetricEncIntegrityPacket)
+                {
+					cName += "/CFB/NoPadding";
+                }
+                else
+                {
+					cName += "/OpenPGPCFB/NoPadding";
+                }
+
+				c2 = CipherUtilities.GetCipher(cName);
+			}
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("exception creating cipher", e);
+            }
+
+			if (c2 == null)
+				return encData.GetInputStream();
+
+			try
+            {
+				KeyParameter key = ParameterUtilities.CreateKeyParameter(
+					cipherName, plain, 1, plain.Length - 3);
+
+				byte[] iv = new byte[c2.GetBlockSize()];
+
+				c2.Init(false, new ParametersWithIV(key, iv));
+
+                encStream = BcpgInputStream.Wrap(new CipherStream(encData.GetInputStream(), c2, null));
+
+				if (encData is SymmetricEncIntegrityPacket)
+                {
+                    truncStream = new TruncatedStream(encStream);
+
+					string digestName = PgpUtilities.GetDigestName(HashAlgorithmTag.Sha1);
+					IDigest digest = DigestUtilities.GetDigest(digestName);
+
+					encStream = new DigestStream(truncStream, digest, null);
+                }
+
+				if (Streams.ReadFully(encStream, iv, 0, iv.Length) < iv.Length)
+					throw new EndOfStreamException("unexpected end of stream.");
+
+				int v1 = encStream.ReadByte();
+                int v2 = encStream.ReadByte();
+
+				if (v1 < 0 || v2 < 0)
+                    throw new EndOfStreamException("unexpected end of stream.");
+
+				// Note: the oracle attack on the "quick check" bytes is deemed
+				// a security risk for typical public key encryption usages,
+				// therefore we do not perform the check.
+
+//				bool repeatCheckPassed =
+//					iv[iv.Length - 2] == (byte)v1
+//					&&	iv[iv.Length - 1] == (byte)v2;
+//
+//				// Note: some versions of PGP appear to produce 0 for the extra
+//				// bytes rather than repeating the two previous bytes
+//				bool zeroesCheckPassed =
+//					v1 == 0
+//					&&	v2 == 0;
+//
+//				if (!repeatCheckPassed && !zeroesCheckPassed)
+//				{
+//					throw new PgpDataValidationException("quick check failed.");
+//				}
+
+				return encStream;
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception starting decryption", e);
+            }
+		}
+
+		private byte[] fetchSymmetricKeyData(
+			PgpPrivateKey privKey)
+		{
+			IBufferedCipher c1 = GetKeyCipher(keyData.Algorithm);
+
+			try
+			{
+				c1.Init(false, privKey.Key);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new PgpException("error setting asymmetric cipher", e);
+			}
+
+			BigInteger[] keyD = keyData.GetEncSessionKey();
+
+			if (keyData.Algorithm == PublicKeyAlgorithmTag.RsaEncrypt
+				|| keyData.Algorithm == PublicKeyAlgorithmTag.RsaGeneral)
+			{
+				c1.ProcessBytes(keyD[0].ToByteArrayUnsigned());
+			}
+			else
+			{
+				ElGamalPrivateKeyParameters k = (ElGamalPrivateKeyParameters)privKey.Key;
+				int size = (k.Parameters.P.BitLength + 7) / 8;
+
+				byte[] bi = keyD[0].ToByteArray();
+
+				int diff = bi.Length - size;
+				if (diff >= 0)
+				{
+					c1.ProcessBytes(bi, diff, size);
+				}
+				else
+				{
+					byte[] zeros = new byte[-diff];
+					c1.ProcessBytes(zeros);
+					c1.ProcessBytes(bi);
+				}
+
+				bi = keyD[1].ToByteArray();
+
+				diff = bi.Length - size;
+				if (diff >= 0)
+				{
+					c1.ProcessBytes(bi, diff, size);
+				}
+				else
+				{
+					byte[] zeros = new byte[-diff];
+					c1.ProcessBytes(zeros);
+					c1.ProcessBytes(bi);
+				}
+			}
+
+			byte[] plain;
+			try
+			{
+				plain = c1.DoFinal();
+			}
+			catch (Exception e)
+			{
+				throw new PgpException("exception decrypting secret key", e);
+			}
+
+			if (!ConfirmCheckSum(plain))
+				throw new PgpKeyValidationException("key checksum failed");
+
+			return plain;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRing.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRing.cs
new file mode 100644
index 0000000..7b1ac93
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRing.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+    /// <remarks>
+    /// Class to hold a single master public key and its subkeys.
+    /// <p>
+    /// Often PGP keyring files consist of multiple master keys, if you are trying to process
+    /// or construct one of these you should use the <c>PgpPublicKeyRingBundle</c> class.
+    /// </p>
+    /// </remarks>
+    public class PgpPublicKeyRing
+        : PgpKeyRing
+    {
+        private readonly IList keys;
+
+        public PgpPublicKeyRing(
+            byte[] encoding)
+            : this(new MemoryStream(encoding, false))
+        {
+        }
+
+        internal PgpPublicKeyRing(
+            IList pubKeys)
+        {
+            this.keys = pubKeys;
+        }
+
+        public PgpPublicKeyRing(
+            Stream inputStream)
+        {
+            this.keys = Platform.CreateArrayList();
+
+            BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
+
+            PacketTag initialTag = bcpgInput.NextPacketTag();
+            if (initialTag != PacketTag.PublicKey && initialTag != PacketTag.PublicSubkey)
+            {
+                throw new IOException("public key ring doesn't start with public key tag: "
+                    + "tag 0x" + ((int)initialTag).ToString("X"));
+            }
+
+            PublicKeyPacket pubPk = (PublicKeyPacket) bcpgInput.ReadPacket();;
+            TrustPacket trustPk = ReadOptionalTrustPacket(bcpgInput);
+
+            // direct signatures and revocations
+            IList keySigs = ReadSignaturesAndTrust(bcpgInput);
+
+            IList ids, idTrusts, idSigs;
+            ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
+
+            keys.Add(new PgpPublicKey(pubPk, trustPk, keySigs, ids, idTrusts, idSigs));
+
+
+            // Read subkeys
+            while (bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
+            {
+                keys.Add(ReadSubkey(bcpgInput));
+            }
+        }
+
+        /// <summary>Return the first public key in the ring.</summary>
+        public virtual PgpPublicKey GetPublicKey()
+        {
+            return (PgpPublicKey) keys[0];
+        }
+
+        /// <summary>Return the public key referred to by the passed in key ID if it is present.</summary>
+        public virtual PgpPublicKey GetPublicKey(
+            long keyId)
+        {
+            foreach (PgpPublicKey k in keys)
+            {
+                if (keyId == k.KeyId)
+                {
+                    return k;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>Allows enumeration of all the public keys.</summary>
+        /// <returns>An <c>IEnumerable</c> of <c>PgpPublicKey</c> objects.</returns>
+        public virtual IEnumerable GetPublicKeys()
+        {
+            return new EnumerableProxy(keys);
+        }
+
+        public virtual byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+            Encode(bOut);
+
+            return bOut.ToArray();
+        }
+
+        public virtual void Encode(
+            Stream outStr)
+        {
+            if (outStr == null)
+                throw new ArgumentNullException("outStr");
+
+            foreach (PgpPublicKey k in keys)
+            {
+                k.Encode(outStr);
+            }
+        }
+
+        /// <summary>
+        /// Returns a new key ring with the public key passed in either added or
+        /// replacing an existing one.
+        /// </summary>
+        /// <param name="pubRing">The public key ring to be modified.</param>
+        /// <param name="pubKey">The public key to be inserted.</param>
+        /// <returns>A new <c>PgpPublicKeyRing</c></returns>
+        public static PgpPublicKeyRing InsertPublicKey(
+            PgpPublicKeyRing	pubRing,
+            PgpPublicKey		pubKey)
+        {
+            IList keys = Platform.CreateArrayList(pubRing.keys);
+            bool found = false;
+            bool masterFound = false;
+
+            for (int i = 0; i != keys.Count; i++)
+            {
+                PgpPublicKey key = (PgpPublicKey) keys[i];
+
+                if (key.KeyId == pubKey.KeyId)
+                {
+                    found = true;
+                    keys[i] = pubKey;
+                }
+                if (key.IsMasterKey)
+                {
+                    masterFound = true;
+                }
+            }
+
+            if (!found)
+            {
+                if (pubKey.IsMasterKey)
+                {
+                    if (masterFound)
+                        throw new ArgumentException("cannot add a master key to a ring that already has one");
+
+                    keys.Insert(0, pubKey);
+                }
+                else
+                {
+                    keys.Add(pubKey);
+                }
+            }
+
+            return new PgpPublicKeyRing(keys);
+        }
+
+        /// <summary>Returns a new key ring with the public key passed in removed from the key ring.</summary>
+        /// <param name="pubRing">The public key ring to be modified.</param>
+        /// <param name="pubKey">The public key to be removed.</param>
+        /// <returns>A new <c>PgpPublicKeyRing</c>, or null if pubKey is not found.</returns>
+        public static PgpPublicKeyRing RemovePublicKey(
+            PgpPublicKeyRing	pubRing,
+            PgpPublicKey		pubKey)
+        {
+            IList keys = Platform.CreateArrayList(pubRing.keys);
+            bool found = false;
+
+            for (int i = 0; i < keys.Count; i++)
+            {
+                PgpPublicKey key = (PgpPublicKey) keys[i];
+
+                if (key.KeyId == pubKey.KeyId)
+                {
+                    found = true;
+                    keys.RemoveAt(i);
+                }
+            }
+
+            return found ? new PgpPublicKeyRing(keys) : null;
+        }
+
+        internal static PgpPublicKey ReadSubkey(BcpgInputStream bcpgInput)
+        {
+            PublicKeyPacket	pk = (PublicKeyPacket) bcpgInput.ReadPacket();
+            TrustPacket kTrust = ReadOptionalTrustPacket(bcpgInput);
+
+            // PGP 8 actually leaves out the signature.
+            IList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+            return new PgpPublicKey(pk, kTrust, sigList);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRingBundle.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRingBundle.cs
new file mode 100644
index 0000000..519a2f8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpPublicKeyRingBundle.cs
@@ -0,0 +1,279 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+	/// If you want to read an entire public key file in one hit this is the class for you.
+	/// </remarks>
+    public class PgpPublicKeyRingBundle
+    {
+        private readonly IDictionary pubRings;
+        private readonly IList order;
+
+		private PgpPublicKeyRingBundle(
+            IDictionary	pubRings,
+            IList       order)
+        {
+            this.pubRings = pubRings;
+            this.order = order;
+        }
+
+		public PgpPublicKeyRingBundle(
+            byte[] encoding)
+            : this(new MemoryStream(encoding, false))
+        {
+        }
+
+		/// <summary>Build a PgpPublicKeyRingBundle from the passed in input stream.</summary>
+		/// <param name="inputStream">Input stream containing data.</param>
+		/// <exception cref="IOException">If a problem parsing the stream occurs.</exception>
+		/// <exception cref="PgpException">If an object is encountered which isn't a PgpPublicKeyRing.</exception>
+		public PgpPublicKeyRingBundle(
+            Stream inputStream)
+			: this(new PgpObjectFactory(inputStream).AllPgpObjects())
+		{
+        }
+
+		public PgpPublicKeyRingBundle(
+            IEnumerable e)
+        {
+			this.pubRings = Platform.CreateHashtable();
+			this.order = Platform.CreateArrayList();
+
+			foreach (object obj in e)
+            {
+				PgpPublicKeyRing pgpPub = obj as PgpPublicKeyRing;
+
+				if (pgpPub == null)
+				{
+					throw new PgpException(obj.GetType().FullName + " found where PgpPublicKeyRing expected");
+				}
+
+				long key = pgpPub.GetPublicKey().KeyId;
+                pubRings.Add(key, pgpPub);
+				order.Add(key);
+            }
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+		{
+			get { return order.Count; }
+		}
+
+		/// <summary>Return the number of key rings in this collection.</summary>
+        public int Count
+        {
+			get { return order.Count; }
+        }
+
+		/// <summary>Allow enumeration of the public key rings making up this collection.</summary>
+        public IEnumerable GetKeyRings()
+        {
+			return new EnumerableProxy(pubRings.Values);
+        }
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+		public IEnumerable GetKeyRings(
+			string userId)
+		{
+			return GetKeyRings(userId, false, false);
+		}
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+        public IEnumerable GetKeyRings(
+            string	userId,
+            bool	matchPartial)
+        {
+			return GetKeyRings(userId, matchPartial, false);
+        }
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+		/// <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+		public IEnumerable GetKeyRings(
+			string	userId,
+			bool	matchPartial,
+			bool	ignoreCase)
+		{
+			IList rings = Platform.CreateArrayList();
+
+			if (ignoreCase)
+			{
+                userId = Platform.ToLowerInvariant(userId);
+			}
+
+			foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+			{
+				foreach (string nextUserID in pubRing.GetPublicKey().GetUserIds())
+				{
+					string next = nextUserID;
+					if (ignoreCase)
+					{
+                        next = Platform.ToLowerInvariant(next);
+                    }
+
+					if (matchPartial)
+					{
+						if (next.IndexOf(userId) > -1)
+						{
+							rings.Add(pubRing);
+						}
+					}
+					else
+					{
+						if (next.Equals(userId))
+						{
+							rings.Add(pubRing);
+						}
+					}
+				}
+			}
+
+			return new EnumerableProxy(rings);
+		}
+
+		/// <summary>Return the PGP public key associated with the given key id.</summary>
+		/// <param name="keyId">The ID of the public key to return.</param>
+        public PgpPublicKey GetPublicKey(
+            long keyId)
+        {
+            foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+            {
+                PgpPublicKey pub = pubRing.GetPublicKey(keyId);
+
+				if (pub != null)
+                {
+                    return pub;
+                }
+            }
+
+			return null;
+        }
+
+		/// <summary>Return the public key ring which contains the key referred to by keyId</summary>
+		/// <param name="keyId">key ID to match against</param>
+        public PgpPublicKeyRing GetPublicKeyRing(
+            long keyId)
+        {
+            if (pubRings.Contains(keyId))
+            {
+                return (PgpPublicKeyRing)pubRings[keyId];
+            }
+
+			foreach (PgpPublicKeyRing pubRing in GetKeyRings())
+            {
+                PgpPublicKey pub = pubRing.GetPublicKey(keyId);
+
+                if (pub != null)
+                {
+                    return pubRing;
+                }
+            }
+
+			return null;
+        }
+
+		/// <summary>
+		/// Return true if a key matching the passed in key ID is present, false otherwise.
+		/// </summary>
+		/// <param name="keyID">key ID to look for.</param>
+		public bool Contains(
+			long keyID)
+		{
+			return GetPublicKey(keyID) != null;
+		}
+
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+			Encode(bOut);
+
+			return bOut.ToArray();
+        }
+
+		public void Encode(
+            Stream outStr)
+        {
+			BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+			foreach (long key in order)
+            {
+                PgpPublicKeyRing sec = (PgpPublicKeyRing) pubRings[key];
+
+				sec.Encode(bcpgOut);
+            }
+        }
+
+		/// <summary>
+		/// Return a new bundle containing the contents of the passed in bundle and
+		/// the passed in public key ring.
+		/// </summary>
+		/// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be added to.</param>
+		/// <param name="publicKeyRing">The key ring to be added.</param>
+		/// <returns>A new <c>PgpPublicKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        public static PgpPublicKeyRingBundle AddPublicKeyRing(
+            PgpPublicKeyRingBundle  bundle,
+            PgpPublicKeyRing        publicKeyRing)
+        {
+            long key = publicKeyRing.GetPublicKey().KeyId;
+
+			if (bundle.pubRings.Contains(key))
+            {
+                throw new ArgumentException("Bundle already contains a key with a keyId for the passed in ring.");
+            }
+
+			IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings);
+            IList newOrder = Platform.CreateArrayList(bundle.order);
+
+			newPubRings[key] = publicKeyRing;
+
+			newOrder.Add(key);
+
+			return new PgpPublicKeyRingBundle(newPubRings, newOrder);
+        }
+
+		/// <summary>
+		/// Return a new bundle containing the contents of the passed in bundle with
+		/// the passed in public key ring removed.
+		/// </summary>
+		/// <param name="bundle">The <c>PgpPublicKeyRingBundle</c> the key ring is to be removed from.</param>
+		/// <param name="publicKeyRing">The key ring to be removed.</param>
+		/// <returns>A new <c>PgpPublicKeyRingBundle</c> not containing the passed in key ring.</returns>
+		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        public static PgpPublicKeyRingBundle RemovePublicKeyRing(
+            PgpPublicKeyRingBundle	bundle,
+            PgpPublicKeyRing		publicKeyRing)
+        {
+            long key = publicKeyRing.GetPublicKey().KeyId;
+
+			if (!bundle.pubRings.Contains(key))
+            {
+                throw new ArgumentException("Bundle does not contain a key with a keyId for the passed in ring.");
+            }
+
+			IDictionary newPubRings = Platform.CreateHashtable(bundle.pubRings);
+            IList newOrder = Platform.CreateArrayList(bundle.order);
+
+			newPubRings.Remove(key);
+			newOrder.Remove(key);
+
+			return new PgpPublicKeyRingBundle(newPubRings, newOrder);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKey.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKey.cs
new file mode 100644
index 0000000..872316d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKey.cs
@@ -0,0 +1,702 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+    /// <remarks>General class to handle a PGP secret key object.</remarks>
+    public class PgpSecretKey
+    {
+        private readonly SecretKeyPacket	secret;
+        private readonly PgpPublicKey		pub;
+
+        internal PgpSecretKey(
+            SecretKeyPacket	secret,
+            PgpPublicKey	pub)
+        {
+            this.secret = secret;
+            this.pub = pub;
+        }
+
+        internal PgpSecretKey(
+            PgpPrivateKey				privKey,
+            PgpPublicKey				pubKey,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            bool						useSha1,
+            SecureRandom				rand)
+            : this(privKey, pubKey, encAlgorithm, passPhrase, useSha1, rand, false)
+        {
+        }
+
+        internal PgpSecretKey(
+            PgpPrivateKey				privKey,
+            PgpPublicKey				pubKey,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            bool						useSha1,
+            SecureRandom				rand,
+            bool						isMasterKey)
+        {
+            BcpgObject secKey;
+
+            this.pub = pubKey;
+
+            switch (pubKey.Algorithm)
+            {
+                case PublicKeyAlgorithmTag.RsaEncrypt:
+                case PublicKeyAlgorithmTag.RsaSign:
+                case PublicKeyAlgorithmTag.RsaGeneral:
+                    RsaPrivateCrtKeyParameters rsK = (RsaPrivateCrtKeyParameters) privKey.Key;
+                    secKey = new RsaSecretBcpgKey(rsK.Exponent, rsK.P, rsK.Q);
+                    break;
+                case PublicKeyAlgorithmTag.Dsa:
+                    DsaPrivateKeyParameters dsK = (DsaPrivateKeyParameters) privKey.Key;
+                    secKey = new DsaSecretBcpgKey(dsK.X);
+                    break;
+                case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                case PublicKeyAlgorithmTag.ElGamalGeneral:
+                    ElGamalPrivateKeyParameters esK = (ElGamalPrivateKeyParameters) privKey.Key;
+                    secKey = new ElGamalSecretBcpgKey(esK.X);
+                    break;
+                default:
+                    throw new PgpException("unknown key class");
+            }
+
+            try
+            {
+                MemoryStream bOut = new MemoryStream();
+                BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+                pOut.WriteObject(secKey);
+
+                byte[] keyData = bOut.ToArray();
+                byte[] checksumData = Checksum(useSha1, keyData, keyData.Length);
+
+                keyData = Arrays.Concatenate(keyData, checksumData);
+
+                if (encAlgorithm == SymmetricKeyAlgorithmTag.Null)
+                {
+                    if (isMasterKey)
+                    {
+                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
+                    }
+                    else
+                    {
+                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, null, null, keyData);
+                    }
+                }
+                else
+                {
+                    S2k s2k;
+                    byte[] iv;
+
+                    byte[] encData;
+                    if (pub.Version >= 4)
+                    {
+                        encData = EncryptKeyData(keyData, encAlgorithm, passPhrase, rand, out s2k, out iv);
+                    }
+                    else
+                    {
+                        // TODO v3 RSA key encryption
+                        throw Platform.CreateNotImplementedException("v3 RSA");
+                    }
+
+                    int s2kUsage = useSha1
+                        ?	SecretKeyPacket.UsageSha1
+                        :	SecretKeyPacket.UsageChecksum;
+
+                    if (isMasterKey)
+                    {
+                        this.secret = new SecretKeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
+                    }
+                    else
+                    {
+                        this.secret = new SecretSubkeyPacket(pub.publicPk, encAlgorithm, s2kUsage, s2k, iv, encData);
+                    }
+                }
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception encrypting key", e);
+            }
+        }
+
+        public PgpSecretKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(certificationLevel, keyPair, id, encAlgorithm, passPhrase, false, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        public PgpSecretKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            bool						useSha1,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(keyPair.PrivateKey, CertifiedPublicKey(certificationLevel, keyPair, id, hashedPackets, unhashedPackets), encAlgorithm, passPhrase, useSha1, rand, true)
+        {
+        }
+
+        private static PgpPublicKey CertifiedPublicKey(
+            int							certificationLevel,
+            PgpKeyPair					keyPair,
+            string						id,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets)
+        {
+            PgpSignatureGenerator sGen;
+            try
+            {
+                sGen = new PgpSignatureGenerator(keyPair.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Creating signature generator: " + e.Message, e);
+            }
+
+            //
+            // Generate the certification
+            //
+            sGen.InitSign(certificationLevel, keyPair.PrivateKey);
+
+            sGen.SetHashedSubpackets(hashedPackets);
+            sGen.SetUnhashedSubpackets(unhashedPackets);
+
+            try
+            {
+                PgpSignature certification = sGen.GenerateCertification(id, keyPair.PublicKey);
+                return PgpPublicKey.AddCertification(keyPair.PublicKey, id, certification);
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception doing certification: " + e.Message, e);
+            }
+        }
+
+        public PgpSecretKey(
+            int							certificationLevel,
+            PublicKeyAlgorithmTag		algorithm,
+            AsymmetricKeyParameter		pubKey,
+            AsymmetricKeyParameter		privKey,
+            DateTime					time,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(certificationLevel,
+                new PgpKeyPair(algorithm, pubKey, privKey, time),
+                id, encAlgorithm, passPhrase, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        public PgpSecretKey(
+            int							certificationLevel,
+            PublicKeyAlgorithmTag		algorithm,
+            AsymmetricKeyParameter		pubKey,
+            AsymmetricKeyParameter		privKey,
+            DateTime					time,
+            string						id,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            bool						useSha1,
+            PgpSignatureSubpacketVector	hashedPackets,
+            PgpSignatureSubpacketVector	unhashedPackets,
+            SecureRandom				rand)
+            : this(certificationLevel, new PgpKeyPair(algorithm, pubKey, privKey, time), id, encAlgorithm, passPhrase, useSha1, hashedPackets, unhashedPackets, rand)
+        {
+        }
+
+        /// <summary>
+        /// Check if this key has an algorithm type that makes it suitable to use for signing.
+        /// </summary>
+        /// <remarks>
+        /// Note: with version 4 keys KeyFlags subpackets should also be considered when present for
+        /// determining the preferred use of the key.
+        /// </remarks>
+        /// <returns>
+        /// <c>true</c> if this key algorithm is suitable for use with signing.
+        /// </returns>
+        public bool IsSigningKey
+        {
+            get
+            {
+                switch (pub.Algorithm)
+                {
+                    case PublicKeyAlgorithmTag.RsaGeneral:
+                    case PublicKeyAlgorithmTag.RsaSign:
+                    case PublicKeyAlgorithmTag.Dsa:
+                    case PublicKeyAlgorithmTag.ECDsa:
+                    case PublicKeyAlgorithmTag.ElGamalGeneral:
+                        return true;
+                    default:
+                        return false;
+                }
+            }
+        }
+
+        /// <summary>True, if this is a master key.</summary>
+        public bool IsMasterKey
+        {
+            get { return pub.IsMasterKey; }
+        }
+
+        /// <summary>Detect if the Secret Key's Private Key is empty or not</summary>
+        public bool IsPrivateKeyEmpty
+        {
+            get
+            {
+                byte[] secKeyData = secret.GetSecretKeyData();
+
+                return secKeyData == null || secKeyData.Length < 1;
+            }
+        }
+
+        /// <summary>The algorithm the key is encrypted with.</summary>
+        public SymmetricKeyAlgorithmTag KeyEncryptionAlgorithm
+        {
+            get { return secret.EncAlgorithm; }
+        }
+
+        /// <summary>The key ID of the public key associated with this key.</summary>
+        public long KeyId
+        {
+            get { return pub.KeyId; }
+        }
+
+        /// <summary>The public key associated with this key.</summary>
+        public PgpPublicKey PublicKey
+        {
+            get { return pub; }
+        }
+
+        /// <summary>Allows enumeration of any user IDs associated with the key.</summary>
+        /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        public IEnumerable UserIds
+        {
+            get { return pub.GetUserIds(); }
+        }
+
+        /// <summary>Allows enumeration of any user attribute vectors associated with the key.</summary>
+        /// <returns>An <c>IEnumerable</c> of <c>string</c> objects.</returns>
+        public IEnumerable UserAttributes
+        {
+            get { return pub.GetUserAttributes(); }
+        }
+
+        private byte[] ExtractKeyData(
+            char[] passPhrase)
+        {
+            SymmetricKeyAlgorithmTag alg = secret.EncAlgorithm;
+            byte[] encData = secret.GetSecretKeyData();
+
+            if (alg == SymmetricKeyAlgorithmTag.Null)
+                // TODO Check checksum here?
+                return encData;
+
+            IBufferedCipher c = null;
+            try
+            {
+                string cName = PgpUtilities.GetSymmetricCipherName(alg);
+                c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception creating cipher", e);
+            }
+
+            // TODO Factor this block out as 'decryptData'
+            try
+            {
+                KeyParameter key = PgpUtilities.MakeKeyFromPassPhrase(secret.EncAlgorithm, secret.S2k, passPhrase);
+                byte[] iv = secret.GetIV();
+                byte[] data;
+
+                if (secret.PublicKeyPacket.Version >= 4)
+                {
+                    c.Init(false, new ParametersWithIV(key, iv));
+
+                    data = c.DoFinal(encData);
+
+                    bool useSha1 = secret.S2kUsage == SecretKeyPacket.UsageSha1;
+                    byte[] check = Checksum(useSha1, data, (useSha1) ? data.Length - 20 : data.Length - 2);
+
+                    for (int i = 0; i != check.Length; i++)
+                    {
+                        if (check[i] != data[data.Length - check.Length + i])
+                        {
+                            throw new PgpException("Checksum mismatch at " + i + " of " + check.Length);
+                        }
+                    }
+                }
+                else // version 2 or 3, RSA only.
+                {
+                    data = new byte[encData.Length];
+
+                    iv = Arrays.Clone(iv);
+
+                    //
+                    // read in the four numbers
+                    //
+                    int pos = 0;
+
+                    for (int i = 0; i != 4; i++)
+                    {
+                        c.Init(false, new ParametersWithIV(key, iv));
+
+                        int encLen = (((encData[pos] << 8) | (encData[pos + 1] & 0xff)) + 7) / 8;
+
+                        data[pos] = encData[pos];
+                        data[pos + 1] = encData[pos + 1];
+                        pos += 2;
+
+                        c.DoFinal(encData, pos, encLen, data, pos);
+                        pos += encLen;
+
+                        if (i != 3)
+                        {
+                            Array.Copy(encData, pos - iv.Length, iv, 0, iv.Length);
+                        }
+                    }
+
+                    //
+                    // verify and copy checksum
+                    //
+
+                    data[pos] = encData[pos];
+                    data[pos + 1] = encData[pos + 1];
+
+                    int cs = ((encData[pos] << 8) & 0xff00) | (encData[pos + 1] & 0xff);
+                    int calcCs = 0;
+                    for (int j = 0; j < pos; j++)
+                    {
+                        calcCs += data[j] & 0xff;
+                    }
+
+                    calcCs &= 0xffff;
+                    if (calcCs != cs)
+                    {
+                        throw new PgpException("Checksum mismatch: passphrase wrong, expected "
+                            + cs.ToString("X")
+                            + " found " + calcCs.ToString("X"));
+                    }
+                }
+
+                return data;
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception decrypting key", e);
+            }
+        }
+
+        /// <summary>Extract a <c>PgpPrivateKey</c> from this secret key's encrypted contents.</summary>
+        public PgpPrivateKey ExtractPrivateKey(
+            char[] passPhrase)
+        {
+            if (IsPrivateKeyEmpty)
+                return null;
+
+            PublicKeyPacket pubPk = secret.PublicKeyPacket;
+            try
+            {
+                byte[] data = ExtractKeyData(passPhrase);
+                BcpgInputStream bcpgIn = BcpgInputStream.Wrap(new MemoryStream(data, false));
+                AsymmetricKeyParameter privateKey;
+                switch (pubPk.Algorithm)
+                {
+                case PublicKeyAlgorithmTag.RsaEncrypt:
+                case PublicKeyAlgorithmTag.RsaGeneral:
+                case PublicKeyAlgorithmTag.RsaSign:
+                    RsaPublicBcpgKey rsaPub = (RsaPublicBcpgKey)pubPk.Key;
+                    RsaSecretBcpgKey rsaPriv = new RsaSecretBcpgKey(bcpgIn);
+                    RsaPrivateCrtKeyParameters rsaPrivSpec = new RsaPrivateCrtKeyParameters(
+                        rsaPriv.Modulus,
+                        rsaPub.PublicExponent,
+                        rsaPriv.PrivateExponent,
+                        rsaPriv.PrimeP,
+                        rsaPriv.PrimeQ,
+                        rsaPriv.PrimeExponentP,
+                        rsaPriv.PrimeExponentQ,
+                        rsaPriv.CrtCoefficient);
+                    privateKey = rsaPrivSpec;
+                    break;
+                case PublicKeyAlgorithmTag.Dsa:
+                    DsaPublicBcpgKey dsaPub = (DsaPublicBcpgKey)pubPk.Key;
+                    DsaSecretBcpgKey dsaPriv = new DsaSecretBcpgKey(bcpgIn);
+                    DsaParameters dsaParams = new DsaParameters(dsaPub.P, dsaPub.Q, dsaPub.G);
+                    privateKey = new DsaPrivateKeyParameters(dsaPriv.X, dsaParams);
+                    break;
+                case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                case PublicKeyAlgorithmTag.ElGamalGeneral:
+                    ElGamalPublicBcpgKey elPub = (ElGamalPublicBcpgKey)pubPk.Key;
+                    ElGamalSecretBcpgKey elPriv = new ElGamalSecretBcpgKey(bcpgIn);
+                    ElGamalParameters elParams = new ElGamalParameters(elPub.P, elPub.G);
+                    privateKey = new ElGamalPrivateKeyParameters(elPriv.X, elParams);
+                    break;
+                default:
+                    throw new PgpException("unknown public key algorithm encountered");
+                }
+
+                return new PgpPrivateKey(privateKey, KeyId);
+            }
+            catch (PgpException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception constructing key", e);
+            }
+        }
+
+        private static byte[] Checksum(
+            bool	useSha1,
+            byte[]	bytes,
+            int		length)
+        {
+            if (useSha1)
+            {
+                try
+                {
+                    IDigest dig = DigestUtilities.GetDigest("SHA1");
+                    dig.BlockUpdate(bytes, 0, length);
+                    return DigestUtilities.DoFinal(dig);
+                }
+                //catch (NoSuchAlgorithmException e)
+                catch (Exception e)
+                {
+                    throw new PgpException("Can't find SHA-1", e);
+                }
+            }
+            else
+            {
+                int Checksum = 0;
+                for (int i = 0; i != length; i++)
+                {
+                    Checksum += bytes[i];
+                }
+
+                return new byte[] { (byte)(Checksum >> 8), (byte)Checksum };
+            }
+        }
+
+        public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+            Encode(bOut);
+            return bOut.ToArray();
+        }
+
+        public void Encode(
+            Stream outStr)
+        {
+            BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+            bcpgOut.WritePacket(secret);
+            if (pub.trustPk != null)
+            {
+                bcpgOut.WritePacket(pub.trustPk);
+            }
+
+            if (pub.subSigs == null) // is not a sub key
+            {
+                foreach (PgpSignature keySig in pub.keySigs)
+                {
+                    keySig.Encode(bcpgOut);
+                }
+
+                for (int i = 0; i != pub.ids.Count; i++)
+                {
+                    object pubID = pub.ids[i];
+                    if (pubID is string)
+                    {
+                        string id = (string) pubID;
+                        bcpgOut.WritePacket(new UserIdPacket(id));
+                    }
+                    else
+                    {
+                        PgpUserAttributeSubpacketVector v = (PgpUserAttributeSubpacketVector) pubID;
+                        bcpgOut.WritePacket(new UserAttributePacket(v.ToSubpacketArray()));
+                    }
+
+                    if (pub.idTrusts[i] != null)
+                    {
+                        bcpgOut.WritePacket((ContainedPacket)pub.idTrusts[i]);
+                    }
+
+                    foreach (PgpSignature sig in (IList) pub.idSigs[i])
+                    {
+                        sig.Encode(bcpgOut);
+                    }
+                }
+            }
+            else
+            {
+                foreach (PgpSignature subSig in pub.subSigs)
+                {
+                    subSig.Encode(bcpgOut);
+                }
+            }
+
+            // TODO Check that this is right/necessary
+            //bcpgOut.Finish();
+        }
+
+        /// <summary>
+        /// Return a copy of the passed in secret key, encrypted using a new password
+        /// and the passed in algorithm.
+        /// </summary>
+        /// <param name="key">The PgpSecretKey to be copied.</param>
+        /// <param name="oldPassPhrase">The current password for the key.</param>
+        /// <param name="newPassPhrase">The new password for the key.</param>
+        /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+        /// <param name="rand">Source of randomness.</param>
+        public static PgpSecretKey CopyWithNewPassword(
+            PgpSecretKey				key,
+            char[]						oldPassPhrase,
+            char[]						newPassPhrase,
+            SymmetricKeyAlgorithmTag	newEncAlgorithm,
+            SecureRandom				rand)
+        {
+            if (key.IsPrivateKeyEmpty)
+                throw new PgpException("no private key in this SecretKey - public key present only.");
+
+            byte[]	rawKeyData = key.ExtractKeyData(oldPassPhrase);
+            int		s2kUsage = key.secret.S2kUsage;
+            byte[]	iv = null;
+            S2k		s2k = null;
+            byte[]	keyData;
+            PublicKeyPacket pubKeyPacket = key.secret.PublicKeyPacket;
+
+            if (newEncAlgorithm == SymmetricKeyAlgorithmTag.Null)
+            {
+                s2kUsage = SecretKeyPacket.UsageNone;
+                if (key.secret.S2kUsage == SecretKeyPacket.UsageSha1)   // SHA-1 hash, need to rewrite Checksum
+                {
+                    keyData = new byte[rawKeyData.Length - 18];
+
+                    Array.Copy(rawKeyData, 0, keyData, 0, keyData.Length - 2);
+
+                    byte[] check = Checksum(false, keyData, keyData.Length - 2);
+
+                    keyData[keyData.Length - 2] = check[0];
+                    keyData[keyData.Length - 1] = check[1];
+                }
+                else
+                {
+                    keyData = rawKeyData;
+                }
+            }
+            else
+            {
+                try
+                {
+                    if (pubKeyPacket.Version >= 4)
+                    {
+                        keyData = EncryptKeyData(rawKeyData, newEncAlgorithm, newPassPhrase, rand, out s2k, out iv);
+                    }
+                    else
+                    {
+                        // TODO v3 RSA key encryption
+                        throw Platform.CreateNotImplementedException("v3 RSA");
+                    }
+                }
+                catch (PgpException e)
+                {
+                    throw e;
+                }
+                catch (Exception e)
+                {
+                    throw new PgpException("Exception encrypting key", e);
+                }
+            }
+
+            SecretKeyPacket secret;
+            if (key.secret is SecretSubkeyPacket)
+            {
+                secret = new SecretSubkeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData);
+            }
+            else
+            {
+                secret = new SecretKeyPacket(pubKeyPacket, newEncAlgorithm, s2kUsage, s2k, iv, keyData);
+            }
+
+            return new PgpSecretKey(secret, key.pub);
+        }
+
+        /// <summary>Replace the passed the public key on the passed in secret key.</summary>
+        /// <param name="secretKey">Secret key to change.</param>
+        /// <param name="publicKey">New public key.</param>
+        /// <returns>A new secret key.</returns>
+        /// <exception cref="ArgumentException">If KeyId's do not match.</exception>
+        public static PgpSecretKey ReplacePublicKey(
+            PgpSecretKey	secretKey,
+            PgpPublicKey	publicKey)
+        {
+            if (publicKey.KeyId != secretKey.KeyId)
+                throw new ArgumentException("KeyId's do not match");
+
+            return new PgpSecretKey(secretKey.secret, publicKey);
+        }
+
+        private static byte[] EncryptKeyData(
+            byte[]						rawKeyData,
+            SymmetricKeyAlgorithmTag	encAlgorithm,
+            char[]						passPhrase,
+            SecureRandom				random,
+            out S2k						s2k,
+            out byte[]					iv)
+        {
+            IBufferedCipher c;
+            try
+            {
+                string cName = PgpUtilities.GetSymmetricCipherName(encAlgorithm);
+                c = CipherUtilities.GetCipher(cName + "/CFB/NoPadding");
+            }
+            catch (Exception e)
+            {
+                throw new PgpException("Exception creating cipher", e);
+            }
+
+            byte[] s2kIV = new byte[8];
+            random.NextBytes(s2kIV);
+            s2k = new S2k(HashAlgorithmTag.Sha1, s2kIV, 0x60);
+
+            KeyParameter kp = PgpUtilities.MakeKeyFromPassPhrase(encAlgorithm, s2k, passPhrase);
+
+            iv = new byte[c.GetBlockSize()];
+            random.NextBytes(iv);
+
+            c.Init(true, new ParametersWithRandom(new ParametersWithIV(kp, iv), random));
+
+            return c.DoFinal(rawKeyData);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRing.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRing.cs
new file mode 100644
index 0000000..70cd721
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRing.cs
@@ -0,0 +1,308 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+    /// <remarks>
+    /// Class to hold a single master secret key and its subkeys.
+    /// <p>
+    /// Often PGP keyring files consist of multiple master keys, if you are trying to process
+    /// or construct one of these you should use the <c>PgpSecretKeyRingBundle</c> class.
+    /// </p>
+    /// </remarks>
+    public class PgpSecretKeyRing
+        : PgpKeyRing
+    {
+        private readonly IList keys;
+        private readonly IList extraPubKeys;
+
+        internal PgpSecretKeyRing(
+            IList keys)
+            : this(keys, Platform.CreateArrayList())
+        {
+        }
+
+        private PgpSecretKeyRing(
+            IList	keys,
+            IList	extraPubKeys)
+        {
+            this.keys = keys;
+            this.extraPubKeys = extraPubKeys;
+        }
+
+        public PgpSecretKeyRing(
+            byte[] encoding)
+            : this(new MemoryStream(encoding))
+        {
+        }
+
+        public PgpSecretKeyRing(
+            Stream inputStream)
+        {
+            this.keys = Platform.CreateArrayList();
+            this.extraPubKeys = Platform.CreateArrayList();
+
+            BcpgInputStream bcpgInput = BcpgInputStream.Wrap(inputStream);
+
+            PacketTag initialTag = bcpgInput.NextPacketTag();
+            if (initialTag != PacketTag.SecretKey && initialTag != PacketTag.SecretSubkey)
+            {
+                throw new IOException("secret key ring doesn't start with secret key tag: "
+                    + "tag 0x" + ((int)initialTag).ToString("X"));
+            }
+
+            SecretKeyPacket secret = (SecretKeyPacket) bcpgInput.ReadPacket();
+
+            //
+            // ignore GPG comment packets if found.
+            //
+            while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
+            {
+                bcpgInput.ReadPacket();
+            }
+
+            TrustPacket trust = ReadOptionalTrustPacket(bcpgInput);
+
+            // revocation and direct signatures
+            IList keySigs = ReadSignaturesAndTrust(bcpgInput);
+
+            IList ids, idTrusts, idSigs;
+            ReadUserIDs(bcpgInput, out ids, out idTrusts, out idSigs);
+
+            keys.Add(new PgpSecretKey(secret, new PgpPublicKey(secret.PublicKeyPacket, trust, keySigs, ids, idTrusts, idSigs)));
+
+
+            // Read subkeys
+            while (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey
+                || bcpgInput.NextPacketTag() == PacketTag.PublicSubkey)
+            {
+                if (bcpgInput.NextPacketTag() == PacketTag.SecretSubkey)
+                {
+                    SecretSubkeyPacket sub = (SecretSubkeyPacket) bcpgInput.ReadPacket();
+
+                    //
+                    // ignore GPG comment packets if found.
+                    //
+                    while (bcpgInput.NextPacketTag() == PacketTag.Experimental2)
+                    {
+                        bcpgInput.ReadPacket();
+                    }
+
+                    TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
+                    IList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+                    keys.Add(new PgpSecretKey(sub, new PgpPublicKey(sub.PublicKeyPacket, subTrust, sigList)));
+                }
+                else
+                {
+                    PublicSubkeyPacket sub = (PublicSubkeyPacket) bcpgInput.ReadPacket();
+
+                    TrustPacket subTrust = ReadOptionalTrustPacket(bcpgInput);
+                    IList sigList = ReadSignaturesAndTrust(bcpgInput);
+
+                    extraPubKeys.Add(new PgpPublicKey(sub, subTrust, sigList));
+                }
+            }
+        }
+
+        /// <summary>Return the public key for the master key.</summary>
+        public PgpPublicKey GetPublicKey()
+        {
+            return ((PgpSecretKey) keys[0]).PublicKey;
+        }
+
+        /// <summary>Return the master private key.</summary>
+        public PgpSecretKey GetSecretKey()
+        {
+            return (PgpSecretKey) keys[0];
+        }
+
+        /// <summary>Allows enumeration of the secret keys.</summary>
+        /// <returns>An <c>IEnumerable</c> of <c>PgpSecretKey</c> objects.</returns>
+        public IEnumerable GetSecretKeys()
+        {
+            return new EnumerableProxy(keys);
+        }
+
+        public PgpSecretKey GetSecretKey(
+            long keyId)
+        {
+            foreach (PgpSecretKey k in keys)
+            {
+                if (keyId == k.KeyId)
+                {
+                    return k;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Return an iterator of the public keys in the secret key ring that
+        /// have no matching private key. At the moment only personal certificate data
+        /// appears in this fashion.
+        /// </summary>
+        /// <returns>An <c>IEnumerable</c> of unattached, or extra, public keys.</returns>
+        public IEnumerable GetExtraPublicKeys()
+        {
+            return new EnumerableProxy(extraPubKeys);
+        }
+
+        public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+            Encode(bOut);
+
+            return bOut.ToArray();
+        }
+
+        public void Encode(
+            Stream outStr)
+        {
+            if (outStr == null)
+                throw new ArgumentNullException("outStr");
+
+            foreach (PgpSecretKey key in keys)
+            {
+                key.Encode(outStr);
+            }
+            foreach (PgpPublicKey extraPubKey in extraPubKeys)
+            {
+                extraPubKey.Encode(outStr);
+            }
+        }
+
+        /// <summary>
+        /// Replace the public key set on the secret ring with the corresponding key off the public ring.
+        /// </summary>
+        /// <param name="secretRing">Secret ring to be changed.</param>
+        /// <param name="publicRing">Public ring containing the new public key set.</param>
+        public static PgpSecretKeyRing ReplacePublicKeys(
+            PgpSecretKeyRing	secretRing,
+            PgpPublicKeyRing	publicRing)
+        {
+            IList newList = Platform.CreateArrayList(secretRing.keys.Count);
+
+            foreach (PgpSecretKey sk in secretRing.keys)
+            {
+                PgpPublicKey pk = publicRing.GetPublicKey(sk.KeyId);
+
+                newList.Add(PgpSecretKey.ReplacePublicKey(sk, pk));
+            }
+
+            return new PgpSecretKeyRing(newList);
+        }
+
+        /// <summary>
+        /// Return a copy of the passed in secret key ring, with the master key and sub keys encrypted
+        /// using a new password and the passed in algorithm.
+        /// </summary>
+        /// <param name="ring">The <c>PgpSecretKeyRing</c> to be copied.</param>
+        /// <param name="oldPassPhrase">The current password for key.</param>
+        /// <param name="newPassPhrase">The new password for the key.</param>
+        /// <param name="newEncAlgorithm">The algorithm to be used for the encryption.</param>
+        /// <param name="rand">Source of randomness.</param>
+        public static PgpSecretKeyRing CopyWithNewPassword(
+            PgpSecretKeyRing			ring,
+            char[]						oldPassPhrase,
+            char[]						newPassPhrase,
+            SymmetricKeyAlgorithmTag	newEncAlgorithm,
+            SecureRandom				rand)
+        {
+            IList newKeys = Platform.CreateArrayList(ring.keys.Count);
+            foreach (PgpSecretKey secretKey in ring.GetSecretKeys())
+            {
+                if (secretKey.IsPrivateKeyEmpty)
+                {
+                    newKeys.Add(secretKey);
+                }
+                else
+                {
+                    newKeys.Add(PgpSecretKey.CopyWithNewPassword(secretKey, oldPassPhrase, newPassPhrase, newEncAlgorithm, rand));
+                }
+            }
+
+            return new PgpSecretKeyRing(newKeys, ring.extraPubKeys);
+        }
+
+        /// <summary>
+        /// Returns a new key ring with the secret key passed in either added or
+        /// replacing an existing one with the same key ID.
+        /// </summary>
+        /// <param name="secRing">The secret key ring to be modified.</param>
+        /// <param name="secKey">The secret key to be inserted.</param>
+        /// <returns>A new <c>PgpSecretKeyRing</c></returns>
+        public static PgpSecretKeyRing InsertSecretKey(
+            PgpSecretKeyRing  secRing,
+            PgpSecretKey      secKey)
+        {
+            IList keys = Platform.CreateArrayList(secRing.keys);
+            bool found = false;
+            bool masterFound = false;
+
+            for (int i = 0; i != keys.Count; i++)
+            {
+                PgpSecretKey key = (PgpSecretKey) keys[i];
+
+                if (key.KeyId == secKey.KeyId)
+                {
+                    found = true;
+                    keys[i] = secKey;
+                }
+                if (key.IsMasterKey)
+                {
+                    masterFound = true;
+                }
+            }
+
+            if (!found)
+            {
+                if (secKey.IsMasterKey)
+                {
+                    if (masterFound)
+                        throw new ArgumentException("cannot add a master key to a ring that already has one");
+
+                    keys.Insert(0, secKey);
+                }
+                else
+                {
+                    keys.Add(secKey);
+                }
+            }
+
+            return new PgpSecretKeyRing(keys, secRing.extraPubKeys);
+        }
+
+        /// <summary>Returns a new key ring with the secret key passed in removed from the key ring.</summary>
+        /// <param name="secRing">The secret key ring to be modified.</param>
+        /// <param name="secKey">The secret key to be removed.</param>
+        /// <returns>A new <c>PgpSecretKeyRing</c>, or null if secKey is not found.</returns>
+        public static PgpSecretKeyRing RemoveSecretKey(
+            PgpSecretKeyRing  secRing,
+            PgpSecretKey      secKey)
+        {
+            IList keys = Platform.CreateArrayList(secRing.keys);
+            bool found = false;
+
+            for (int i = 0; i < keys.Count; i++)
+            {
+                PgpSecretKey key = (PgpSecretKey)keys[i];
+
+                if (key.KeyId == secKey.KeyId)
+                {
+                    found = true;
+                    keys.RemoveAt(i);
+                }
+            }
+
+            return found ? new PgpSecretKeyRing(keys, secRing.extraPubKeys) : null;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRingBundle.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRingBundle.cs
new file mode 100644
index 0000000..12c7c09
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSecretKeyRingBundle.cs
@@ -0,0 +1,281 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>
+	/// Often a PGP key ring file is made up of a succession of master/sub-key key rings.
+	/// If you want to read an entire secret key file in one hit this is the class for you.
+	/// </remarks>
+    public class PgpSecretKeyRingBundle
+    {
+        private readonly IDictionary secretRings;
+        private readonly IList order;
+
+		private PgpSecretKeyRingBundle(
+            IDictionary	secretRings,
+            IList       order)
+        {
+            this.secretRings = secretRings;
+            this.order = order;
+        }
+
+		public PgpSecretKeyRingBundle(
+            byte[] encoding)
+            : this(new MemoryStream(encoding, false))
+		{
+        }
+
+		/// <summary>Build a PgpSecretKeyRingBundle from the passed in input stream.</summary>
+		/// <param name="inputStream">Input stream containing data.</param>
+		/// <exception cref="IOException">If a problem parsing the stream occurs.</exception>
+		/// <exception cref="PgpException">If an object is encountered which isn't a PgpSecretKeyRing.</exception>
+		public PgpSecretKeyRingBundle(
+            Stream inputStream)
+			: this(new PgpObjectFactory(inputStream).AllPgpObjects())
+        {
+        }
+
+		public PgpSecretKeyRingBundle(
+            IEnumerable e)
+        {
+			this.secretRings = Platform.CreateHashtable();
+            this.order = Platform.CreateArrayList();
+
+			foreach (object obj in e)
+			{
+				PgpSecretKeyRing pgpSecret = obj as PgpSecretKeyRing;
+
+				if (pgpSecret == null)
+				{
+					throw new PgpException(obj.GetType().FullName + " found where PgpSecretKeyRing expected");
+				}
+
+				long key = pgpSecret.GetPublicKey().KeyId;
+				secretRings.Add(key, pgpSecret);
+				order.Add(key);
+			}
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+		{
+			get { return order.Count; }
+		}
+
+		/// <summary>Return the number of rings in this collection.</summary>
+		public int Count
+        {
+			get { return order.Count; }
+        }
+
+		/// <summary>Allow enumeration of the secret key rings making up this collection.</summary>
+		public IEnumerable GetKeyRings()
+        {
+            return new EnumerableProxy(secretRings.Values);
+        }
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+		public IEnumerable GetKeyRings(
+			string userId)
+		{
+			return GetKeyRings(userId, false, false);
+		}
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+		public IEnumerable GetKeyRings(
+            string	userId,
+            bool	matchPartial)
+        {
+			return GetKeyRings(userId, matchPartial, false);
+        }
+
+		/// <summary>Allow enumeration of the key rings associated with the passed in userId.</summary>
+		/// <param name="userId">The user ID to be matched.</param>
+		/// <param name="matchPartial">If true, userId need only be a substring of an actual ID string to match.</param>
+		/// <param name="ignoreCase">If true, case is ignored in user ID comparisons.</param>
+		/// <returns>An <c>IEnumerable</c> of key rings which matched (possibly none).</returns>
+		public IEnumerable GetKeyRings(
+			string	userId,
+			bool	matchPartial,
+			bool	ignoreCase)
+		{
+            IList rings = Platform.CreateArrayList();
+
+			if (ignoreCase)
+			{
+                userId = Platform.ToLowerInvariant(userId);
+            }
+
+			foreach (PgpSecretKeyRing secRing in GetKeyRings())
+			{
+				foreach (string nextUserID in secRing.GetSecretKey().UserIds)
+				{
+					string next = nextUserID;
+					if (ignoreCase)
+					{
+                        next = Platform.ToLowerInvariant(next);
+                    }
+
+					if (matchPartial)
+					{
+						if (next.IndexOf(userId) > -1)
+						{
+							rings.Add(secRing);
+						}
+					}
+					else
+					{
+						if (next.Equals(userId))
+						{
+							rings.Add(secRing);
+						}
+					}
+				}
+			}
+
+			return new EnumerableProxy(rings);
+		}
+
+		/// <summary>Return the PGP secret key associated with the given key id.</summary>
+		/// <param name="keyId">The ID of the secret key to return.</param>
+		public PgpSecretKey GetSecretKey(
+            long keyId)
+        {
+            foreach (PgpSecretKeyRing secRing in GetKeyRings())
+            {
+                PgpSecretKey sec = secRing.GetSecretKey(keyId);
+
+				if (sec != null)
+                {
+                    return sec;
+                }
+            }
+
+            return null;
+        }
+
+		/// <summary>Return the secret key ring which contains the key referred to by keyId</summary>
+		/// <param name="keyId">The ID of the secret key</param>
+		public PgpSecretKeyRing GetSecretKeyRing(
+            long keyId)
+        {
+            long id = keyId;
+
+            if (secretRings.Contains(id))
+            {
+                return (PgpSecretKeyRing) secretRings[id];
+            }
+
+			foreach (PgpSecretKeyRing secretRing in GetKeyRings())
+            {
+                PgpSecretKey secret = secretRing.GetSecretKey(keyId);
+
+                if (secret != null)
+                {
+                    return secretRing;
+                }
+            }
+
+            return null;
+        }
+
+		/// <summary>
+		/// Return true if a key matching the passed in key ID is present, false otherwise.
+		/// </summary>
+		/// <param name="keyID">key ID to look for.</param>
+		public bool Contains(
+			long keyID)
+		{
+			return GetSecretKey(keyID) != null;
+		}
+
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+			Encode(bOut);
+
+			return bOut.ToArray();
+        }
+
+		public void Encode(
+			Stream outStr)
+        {
+			BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStr);
+
+			foreach (long key in order)
+            {
+                PgpSecretKeyRing pub = (PgpSecretKeyRing) secretRings[key];
+
+				pub.Encode(bcpgOut);
+            }
+        }
+
+		/// <summary>
+		/// Return a new bundle containing the contents of the passed in bundle and
+		/// the passed in secret key ring.
+		/// </summary>
+		/// <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be added to.</param>
+		/// <param name="secretKeyRing">The key ring to be added.</param>
+		/// <returns>A new <c>PgpSecretKeyRingBundle</c> merging the current one with the passed in key ring.</returns>
+		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is already present.</exception>
+        public static PgpSecretKeyRingBundle AddSecretKeyRing(
+            PgpSecretKeyRingBundle  bundle,
+            PgpSecretKeyRing        secretKeyRing)
+        {
+            long key = secretKeyRing.GetPublicKey().KeyId;
+
+            if (bundle.secretRings.Contains(key))
+            {
+                throw new ArgumentException("Collection already contains a key with a keyId for the passed in ring.");
+            }
+
+            IDictionary newSecretRings = Platform.CreateHashtable(bundle.secretRings);
+            IList newOrder = Platform.CreateArrayList(bundle.order);
+
+            newSecretRings[key] = secretKeyRing;
+            newOrder.Add(key);
+
+            return new PgpSecretKeyRingBundle(newSecretRings, newOrder);
+        }
+
+		/// <summary>
+		/// Return a new bundle containing the contents of the passed in bundle with
+		/// the passed in secret key ring removed.
+		/// </summary>
+		/// <param name="bundle">The <c>PgpSecretKeyRingBundle</c> the key ring is to be removed from.</param>
+		/// <param name="secretKeyRing">The key ring to be removed.</param>
+		/// <returns>A new <c>PgpSecretKeyRingBundle</c> not containing the passed in key ring.</returns>
+		/// <exception cref="ArgumentException">If the keyId for the passed in key ring is not present.</exception>
+        public static PgpSecretKeyRingBundle RemoveSecretKeyRing(
+            PgpSecretKeyRingBundle  bundle,
+            PgpSecretKeyRing        secretKeyRing)
+        {
+            long key = secretKeyRing.GetPublicKey().KeyId;
+
+			if (!bundle.secretRings.Contains(key))
+            {
+                throw new ArgumentException("Collection does not contain a key with a keyId for the passed in ring.");
+            }
+
+            IDictionary newSecretRings = Platform.CreateHashtable(bundle.secretRings);
+            IList newOrder = Platform.CreateArrayList(bundle.order);
+
+			newSecretRings.Remove(key);
+			newOrder.Remove(key);
+
+			return new PgpSecretKeyRingBundle(newSecretRings, newOrder);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSignature.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSignature.cs
new file mode 100644
index 0000000..3bb6f2f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSignature.cs
@@ -0,0 +1,422 @@
+using System;
+using System.IO;
+using Org.BouncyCastle.Asn1;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A PGP signature object.</remarks>
+    public class PgpSignature
+    {
+        public const int BinaryDocument = 0x00;
+        public const int CanonicalTextDocument = 0x01;
+        public const int StandAlone = 0x02;
+
+        public const int DefaultCertification = 0x10;
+        public const int NoCertification = 0x11;
+        public const int CasualCertification = 0x12;
+        public const int PositiveCertification = 0x13;
+
+        public const int SubkeyBinding = 0x18;
+		public const int PrimaryKeyBinding = 0x19;
+		public const int DirectKey = 0x1f;
+        public const int KeyRevocation = 0x20;
+        public const int SubkeyRevocation = 0x28;
+        public const int CertificationRevocation = 0x30;
+        public const int Timestamp = 0x40;
+
+        private readonly SignaturePacket	sigPck;
+        private readonly int				signatureType;
+        private readonly TrustPacket		trustPck;
+
+		private ISigner	sig;
+		private byte	lastb; // Initial value anything but '\r'
+
+		internal PgpSignature(
+            BcpgInputStream bcpgInput)
+            : this((SignaturePacket)bcpgInput.ReadPacket())
+        {
+        }
+
+		internal PgpSignature(
+            SignaturePacket sigPacket)
+			: this(sigPacket, null)
+        {
+        }
+
+        internal PgpSignature(
+            SignaturePacket	sigPacket,
+            TrustPacket		trustPacket)
+        {
+			if (sigPacket == null)
+				throw new ArgumentNullException("sigPacket");
+
+			this.sigPck = sigPacket;
+			this.signatureType = sigPck.SignatureType;
+			this.trustPck = trustPacket;
+        }
+
+		private void GetSig()
+        {
+            this.sig = SignerUtilities.GetSigner(
+				PgpUtilities.GetSignatureName(sigPck.KeyAlgorithm, sigPck.HashAlgorithm));
+        }
+
+		/// <summary>The OpenPGP version number for this signature.</summary>
+		public int Version
+		{
+			get { return sigPck.Version; }
+		}
+
+		/// <summary>The key algorithm associated with this signature.</summary>
+		public PublicKeyAlgorithmTag KeyAlgorithm
+		{
+			get { return sigPck.KeyAlgorithm; }
+		}
+
+		/// <summary>The hash algorithm associated with this signature.</summary>
+		public HashAlgorithmTag HashAlgorithm
+		{
+			get { return sigPck.HashAlgorithm; }
+		}
+
+		public void InitVerify(
+            PgpPublicKey pubKey)
+        {
+			lastb = 0;
+            if (sig == null)
+            {
+                GetSig();
+            }
+            try
+            {
+                sig.Init(false, pubKey.GetKey());
+            }
+            catch (InvalidKeyException e)
+            {
+                throw new PgpException("invalid key.", e);
+            }
+        }
+
+        public void Update(
+            byte b)
+        {
+            if (signatureType == CanonicalTextDocument)
+            {
+				doCanonicalUpdateByte(b);
+            }
+            else
+            {
+                sig.Update(b);
+            }
+        }
+
+		private void doCanonicalUpdateByte(
+			byte b)
+		{
+			if (b == '\r')
+			{
+				doUpdateCRLF();
+			}
+			else if (b == '\n')
+			{
+				if (lastb != '\r')
+				{
+					doUpdateCRLF();
+				}
+			}
+			else
+			{
+				sig.Update(b);
+			}
+
+			lastb = b;
+		}
+
+		private void doUpdateCRLF()
+		{
+			sig.Update((byte)'\r');
+			sig.Update((byte)'\n');
+		}
+
+		public void Update(
+            params byte[] bytes)
+        {
+			Update(bytes, 0, bytes.Length);
+        }
+
+		public void Update(
+            byte[]	bytes,
+            int		off,
+            int		length)
+        {
+            if (signatureType == CanonicalTextDocument)
+            {
+                int finish = off + length;
+
+				for (int i = off; i != finish; i++)
+                {
+                    doCanonicalUpdateByte(bytes[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(bytes, off, length);
+            }
+        }
+
+		public bool Verify()
+        {
+            byte[] trailer = GetSignatureTrailer();
+            sig.BlockUpdate(trailer, 0, trailer.Length);
+
+			return sig.VerifySignature(GetSignature());
+        }
+
+		private void UpdateWithIdData(
+			int		header,
+			byte[]	idBytes)
+		{
+			this.Update(
+				(byte) header,
+				(byte)(idBytes.Length >> 24),
+				(byte)(idBytes.Length >> 16),
+				(byte)(idBytes.Length >> 8),
+				(byte)(idBytes.Length));
+			this.Update(idBytes);
+		}
+
+		private void UpdateWithPublicKey(
+			PgpPublicKey key)
+		{
+			byte[] keyBytes = GetEncodedPublicKey(key);
+
+			this.Update(
+				(byte) 0x99,
+				(byte)(keyBytes.Length >> 8),
+				(byte)(keyBytes.Length));
+			this.Update(keyBytes);
+		}
+
+		/// <summary>
+		/// Verify the signature as certifying the passed in public key as associated
+		/// with the passed in user attributes.
+		/// </summary>
+		/// <param name="userAttributes">User attributes the key was stored under.</param>
+		/// <param name="key">The key to be verified.</param>
+		/// <returns>True, if the signature matches, false otherwise.</returns>
+		public bool VerifyCertification(
+			PgpUserAttributeSubpacketVector	userAttributes,
+			PgpPublicKey					key)
+		{
+			UpdateWithPublicKey(key);
+
+			//
+			// hash in the userAttributes
+			//
+			try
+			{
+				MemoryStream bOut = new MemoryStream();
+				foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray())
+				{
+					packet.Encode(bOut);
+				}
+				UpdateWithIdData(0xd1, bOut.ToArray());
+			}
+			catch (IOException e)
+			{
+				throw new PgpException("cannot encode subpacket array", e);
+			}
+
+			this.Update(sigPck.GetSignatureTrailer());
+
+			return sig.VerifySignature(this.GetSignature());
+		}
+
+		/// <summary>
+		/// Verify the signature as certifying the passed in public key as associated
+		/// with the passed in ID.
+		/// </summary>
+		/// <param name="id">ID the key was stored under.</param>
+		/// <param name="key">The key to be verified.</param>
+		/// <returns>True, if the signature matches, false otherwise.</returns>
+        public bool VerifyCertification(
+            string			id,
+            PgpPublicKey	key)
+        {
+			UpdateWithPublicKey(key);
+
+			//
+            // hash in the id
+            //
+            UpdateWithIdData(0xb4, Strings.ToUtf8ByteArray(id));
+
+			Update(sigPck.GetSignatureTrailer());
+
+			return sig.VerifySignature(GetSignature());
+        }
+
+		/// <summary>Verify a certification for the passed in key against the passed in master key.</summary>
+		/// <param name="masterKey">The key we are verifying against.</param>
+		/// <param name="pubKey">The key we are verifying.</param>
+		/// <returns>True, if the certification is valid, false otherwise.</returns>
+        public bool VerifyCertification(
+            PgpPublicKey	masterKey,
+            PgpPublicKey	pubKey)
+        {
+			UpdateWithPublicKey(masterKey);
+			UpdateWithPublicKey(pubKey);
+
+			Update(sigPck.GetSignatureTrailer());
+
+			return sig.VerifySignature(GetSignature());
+        }
+
+		/// <summary>Verify a key certification, such as revocation, for the passed in key.</summary>
+		/// <param name="pubKey">The key we are checking.</param>
+		/// <returns>True, if the certification is valid, false otherwise.</returns>
+        public bool VerifyCertification(
+            PgpPublicKey pubKey)
+        {
+            if (SignatureType != KeyRevocation
+                && SignatureType != SubkeyRevocation)
+            {
+                throw new InvalidOperationException("signature is not a key signature");
+            }
+
+			UpdateWithPublicKey(pubKey);
+
+            Update(sigPck.GetSignatureTrailer());
+
+			return sig.VerifySignature(GetSignature());
+        }
+
+		public int SignatureType
+        {
+			get { return sigPck.SignatureType; }
+        }
+
+		/// <summary>The ID of the key that created the signature.</summary>
+        public long KeyId
+        {
+            get { return sigPck.KeyId; }
+        }
+
+		[Obsolete("Use 'CreationTime' property instead")]
+		public DateTime GetCreationTime()
+		{
+			return CreationTime;
+		}
+
+		/// <summary>The creation time of this signature.</summary>
+        public DateTime CreationTime
+        {
+			get { return DateTimeUtilities.UnixMsToDateTime(sigPck.CreationTime); }
+        }
+
+		public byte[] GetSignatureTrailer()
+        {
+            return sigPck.GetSignatureTrailer();
+        }
+
+		/// <summary>
+		/// Return true if the signature has either hashed or unhashed subpackets.
+		/// </summary>
+		public bool HasSubpackets
+		{
+			get
+			{
+				return sigPck.GetHashedSubPackets() != null
+					|| sigPck.GetUnhashedSubPackets() != null;
+			}
+		}
+
+		public PgpSignatureSubpacketVector GetHashedSubPackets()
+        {
+            return createSubpacketVector(sigPck.GetHashedSubPackets());
+        }
+
+		public PgpSignatureSubpacketVector GetUnhashedSubPackets()
+        {
+            return createSubpacketVector(sigPck.GetUnhashedSubPackets());
+        }
+
+		private PgpSignatureSubpacketVector createSubpacketVector(SignatureSubpacket[] pcks)
+		{
+			return pcks == null ? null : new PgpSignatureSubpacketVector(pcks);
+		}
+
+		public byte[] GetSignature()
+        {
+            MPInteger[] sigValues = sigPck.GetSignature();
+            byte[] signature;
+
+			if (sigValues != null)
+			{
+				if (sigValues.Length == 1)    // an RSA signature
+				{
+					signature = sigValues[0].Value.ToByteArrayUnsigned();
+				}
+				else
+				{
+					try
+					{
+						signature = new DerSequence(
+							new DerInteger(sigValues[0].Value),
+							new DerInteger(sigValues[1].Value)).GetEncoded();
+					}
+					catch (IOException e)
+					{
+						throw new PgpException("exception encoding DSA sig.", e);
+					}
+				}
+			}
+			else
+			{
+				signature = sigPck.GetSignatureBytes();
+			}
+
+			return signature;
+        }
+
+		// TODO Handle the encoding stuff by subclassing BcpgObject?
+		public byte[] GetEncoded()
+        {
+            MemoryStream bOut = new MemoryStream();
+
+			Encode(bOut);
+
+			return bOut.ToArray();
+        }
+
+		public void Encode(
+            Stream outStream)
+        {
+            BcpgOutputStream bcpgOut = BcpgOutputStream.Wrap(outStream);
+
+			bcpgOut.WritePacket(sigPck);
+
+			if (trustPck != null)
+            {
+                bcpgOut.WritePacket(trustPck);
+            }
+        }
+
+		private byte[] GetEncodedPublicKey(
+			PgpPublicKey pubKey) 
+		{
+			try
+			{
+				return pubKey.publicPk.GetEncodedContents();
+			}
+			catch (IOException e)
+			{
+				throw new PgpException("exception preparing key.", e);
+			}
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureGenerator.cs
new file mode 100644
index 0000000..c530968
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureGenerator.cs
@@ -0,0 +1,393 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Generator for PGP signatures.</remarks>
+	// TODO Should be able to implement ISigner?
+    public class PgpSignatureGenerator
+    {
+		private static readonly SignatureSubpacket[] EmptySignatureSubpackets = new SignatureSubpacket[0];
+
+		private PublicKeyAlgorithmTag	keyAlgorithm;
+        private HashAlgorithmTag		hashAlgorithm;
+        private PgpPrivateKey			privKey;
+        private ISigner					sig;
+        private IDigest					dig;
+        private int						signatureType;
+        private byte					lastb;
+
+		private SignatureSubpacket[] unhashed = EmptySignatureSubpackets;
+        private SignatureSubpacket[] hashed = EmptySignatureSubpackets;
+
+		/// <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        public PgpSignatureGenerator(
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm)
+        {
+            this.keyAlgorithm = keyAlgorithm;
+            this.hashAlgorithm = hashAlgorithm;
+
+			dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm));
+            sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm));
+        }
+
+		/// <summary>Initialise the generator for signing.</summary>
+        public void InitSign(
+            int				sigType,
+            PgpPrivateKey	key)
+        {
+			InitSign(sigType, key, null);
+        }
+
+		/// <summary>Initialise the generator for signing.</summary>
+		public void InitSign(
+			int				sigType,
+			PgpPrivateKey	key,
+			SecureRandom	random)
+		{
+			this.privKey = key;
+			this.signatureType = sigType;
+
+			try
+			{
+				ICipherParameters cp = key.Key;
+				if (random != null)
+				{
+					cp = new ParametersWithRandom(key.Key, random);
+				}
+
+				sig.Init(true, cp);
+			}
+			catch (InvalidKeyException e)
+			{
+				throw new PgpException("invalid key.", e);
+			}
+
+			dig.Reset();
+			lastb = 0;
+		}
+
+		public void Update(
+            byte b)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+				doCanonicalUpdateByte(b);
+            }
+            else
+            {
+				doUpdateByte(b);
+            }
+        }
+
+		private void doCanonicalUpdateByte(
+			byte b)
+		{
+			if (b == '\r')
+			{
+				doUpdateCRLF();
+			}
+			else if (b == '\n')
+			{
+				if (lastb != '\r')
+				{
+					doUpdateCRLF();
+				}
+			}
+			else
+			{
+				doUpdateByte(b);
+			}
+
+			lastb = b;
+		}
+
+		private void doUpdateCRLF()
+		{
+			doUpdateByte((byte)'\r');
+			doUpdateByte((byte)'\n');
+		}
+
+		private void doUpdateByte(
+			byte b)
+		{
+			sig.Update(b);
+			dig.Update(b);
+		}
+
+		public void Update(
+            params byte[] b)
+        {
+			Update(b, 0, b.Length);
+        }
+
+		public void Update(
+            byte[]	b,
+            int		off,
+            int		len)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+                int finish = off + len;
+
+				for (int i = off; i != finish; i++)
+                {
+                    doCanonicalUpdateByte(b[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(b, off, len);
+                dig.BlockUpdate(b, off, len);
+            }
+        }
+
+		public void SetHashedSubpackets(
+            PgpSignatureSubpacketVector hashedPackets)
+        {
+			hashed = hashedPackets == null
+				?	EmptySignatureSubpackets
+				:	hashedPackets.ToSubpacketArray();
+        }
+
+		public void SetUnhashedSubpackets(
+            PgpSignatureSubpacketVector unhashedPackets)
+        {
+			unhashed = unhashedPackets == null
+				?	EmptySignatureSubpackets
+				:	unhashedPackets.ToSubpacketArray();
+        }
+
+		/// <summary>Return the one pass header associated with the current signature.</summary>
+        public PgpOnePassSignature GenerateOnePassVersion(
+            bool isNested)
+        {
+            return new PgpOnePassSignature(
+				new OnePassSignaturePacket(
+					signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested));
+        }
+
+		/// <summary>Return a signature object containing the current signature state.</summary>
+        public PgpSignature Generate()
+        {
+			SignatureSubpacket[] hPkts = hashed, unhPkts = unhashed;
+
+			if (!packetPresent(hashed, SignatureSubpacketTag.CreationTime))
+			{
+				hPkts = insertSubpacket(hPkts, new SignatureCreationTime(false, DateTime.UtcNow));
+			}
+
+			if (!packetPresent(hashed, SignatureSubpacketTag.IssuerKeyId)
+				&& !packetPresent(unhashed, SignatureSubpacketTag.IssuerKeyId))
+			{
+				unhPkts = insertSubpacket(unhPkts, new IssuerKeyId(false, privKey.KeyId));
+			}
+
+			int version = 4;
+			byte[] hData;
+
+			try
+            {
+				MemoryStream hOut = new MemoryStream();
+
+				for (int i = 0; i != hPkts.Length; i++)
+				{
+					hPkts[i].Encode(hOut);
+				}
+
+				byte[] data = hOut.ToArray();
+
+				MemoryStream sOut = new MemoryStream(data.Length + 6);
+				sOut.WriteByte((byte)version);
+                sOut.WriteByte((byte)signatureType);
+                sOut.WriteByte((byte)keyAlgorithm);
+                sOut.WriteByte((byte)hashAlgorithm);
+				sOut.WriteByte((byte)(data.Length >> 8));
+                sOut.WriteByte((byte)data.Length);
+                sOut.Write(data, 0, data.Length);
+
+				hData = sOut.ToArray();
+			}
+            catch (IOException e)
+            {
+                throw new PgpException("exception encoding hashed data.", e);
+            }
+
+			sig.BlockUpdate(hData, 0, hData.Length);
+            dig.BlockUpdate(hData, 0, hData.Length);
+
+			hData = new byte[]
+			{
+				(byte) version,
+				0xff,
+				(byte)(hData.Length >> 24),
+				(byte)(hData.Length >> 16),
+				(byte)(hData.Length >> 8),
+				(byte) hData.Length
+			};
+
+			sig.BlockUpdate(hData, 0, hData.Length);
+            dig.BlockUpdate(hData, 0, hData.Length);
+
+			byte[] sigBytes = sig.GenerateSignature();
+			byte[] digest = DigestUtilities.DoFinal(dig);
+			byte[] fingerPrint = new byte[] { digest[0], digest[1] };
+
+			// an RSA signature
+			bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign
+				|| keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral;
+
+			MPInteger[] sigValues = isRsa
+				?	PgpUtilities.RsaSigToMpi(sigBytes)
+				:	PgpUtilities.DsaSigToMpi(sigBytes);
+
+			return new PgpSignature(
+				new SignaturePacket(signatureType, privKey.KeyId, keyAlgorithm,
+					hashAlgorithm, hPkts, unhPkts, fingerPrint, sigValues));
+        }
+
+		/// <summary>Generate a certification for the passed in ID and key.</summary>
+		/// <param name="id">The ID we are certifying against the public key.</param>
+		/// <param name="pubKey">The key we are certifying against the ID.</param>
+		/// <returns>The certification.</returns>
+        public PgpSignature GenerateCertification(
+            string			id,
+            PgpPublicKey	pubKey)
+        {
+			UpdateWithPublicKey(pubKey);
+
+			//
+            // hash in the id
+            //
+			UpdateWithIdData(0xb4, Strings.ToUtf8ByteArray(id));
+
+            return Generate();
+        }
+
+		/// <summary>Generate a certification for the passed in userAttributes.</summary>
+		/// <param name="userAttributes">The ID we are certifying against the public key.</param>
+		/// <param name="pubKey">The key we are certifying against the ID.</param>
+		/// <returns>The certification.</returns>
+		public PgpSignature GenerateCertification(
+			PgpUserAttributeSubpacketVector	userAttributes,
+			PgpPublicKey					pubKey)
+		{
+			UpdateWithPublicKey(pubKey);
+
+			//
+			// hash in the attributes
+			//
+			try
+			{
+				MemoryStream bOut = new MemoryStream();
+				foreach (UserAttributeSubpacket packet in userAttributes.ToSubpacketArray())
+				{
+					packet.Encode(bOut);
+				}
+				UpdateWithIdData(0xd1, bOut.ToArray());
+			}
+			catch (IOException e)
+			{
+				throw new PgpException("cannot encode subpacket array", e);
+			}
+
+			return this.Generate();
+		}
+
+		/// <summary>Generate a certification for the passed in key against the passed in master key.</summary>
+		/// <param name="masterKey">The key we are certifying against.</param>
+		/// <param name="pubKey">The key we are certifying.</param>
+		/// <returns>The certification.</returns>
+        public PgpSignature GenerateCertification(
+            PgpPublicKey	masterKey,
+            PgpPublicKey	pubKey)
+        {
+			UpdateWithPublicKey(masterKey);
+			UpdateWithPublicKey(pubKey);
+
+			return Generate();
+        }
+
+		/// <summary>Generate a certification, such as a revocation, for the passed in key.</summary>
+		/// <param name="pubKey">The key we are certifying.</param>
+		/// <returns>The certification.</returns>
+        public PgpSignature GenerateCertification(
+            PgpPublicKey pubKey)
+        {
+			UpdateWithPublicKey(pubKey);
+
+			return Generate();
+        }
+
+		private byte[] GetEncodedPublicKey(
+			PgpPublicKey pubKey) 
+		{
+			try
+			{
+				return pubKey.publicPk.GetEncodedContents();
+			}
+			catch (IOException e)
+			{
+				throw new PgpException("exception preparing key.", e);
+			}
+		}
+
+		private bool packetPresent(
+			SignatureSubpacket[]	packets,
+			SignatureSubpacketTag	type)
+		{
+			for (int i = 0; i != packets.Length; i++)
+			{
+				if (packets[i].SubpacketType == type)
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		private SignatureSubpacket[] insertSubpacket(
+			SignatureSubpacket[]	packets,
+			SignatureSubpacket		subpacket)
+		{
+			SignatureSubpacket[] tmp = new SignatureSubpacket[packets.Length + 1];
+			tmp[0] = subpacket;
+			packets.CopyTo(tmp, 1);
+			return tmp;
+		}
+
+		private void UpdateWithIdData(
+			int		header,
+			byte[]	idBytes)
+		{
+			this.Update(
+				(byte) header,
+				(byte)(idBytes.Length >> 24),
+				(byte)(idBytes.Length >> 16),
+				(byte)(idBytes.Length >> 8),
+				(byte)(idBytes.Length));
+			this.Update(idBytes);
+		}
+
+		private void UpdateWithPublicKey(
+			PgpPublicKey key)
+		{
+			byte[] keyBytes = GetEncodedPublicKey(key);
+
+			this.Update(
+				(byte) 0x99,
+				(byte)(keyBytes.Length >> 8),
+				(byte)(keyBytes.Length));
+			this.Update(keyBytes);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureList.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureList.cs
new file mode 100644
index 0000000..61976fc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureList.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>A list of PGP signatures - normally in the signature block after literal data.</remarks>
+    public class PgpSignatureList
+		: PgpObject
+    {
+        private PgpSignature[] sigs;
+
+		public PgpSignatureList(
+            PgpSignature[] sigs)
+        {
+            this.sigs = (PgpSignature[]) sigs.Clone();
+        }
+
+		public PgpSignatureList(
+            PgpSignature sig)
+        {
+			this.sigs = new PgpSignature[]{ sig };
+        }
+
+		public PgpSignature this[int index]
+		{
+			get { return sigs[index]; }
+		}
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public PgpSignature Get(
+            int index)
+        {
+            return this[index];
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+        {
+			get { return sigs.Length; }
+        }
+
+		public int Count
+		{
+			get { return sigs.Length; }
+		}
+
+		public bool IsEmpty
+        {
+			get { return (sigs.Length == 0); }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketGenerator.cs
new file mode 100644
index 0000000..4adf640
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketGenerator.cs
@@ -0,0 +1,193 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Generator for signature subpackets.</remarks>
+    public class PgpSignatureSubpacketGenerator
+    {
+        private IList list = Platform.CreateArrayList();
+
+		public void SetRevocable(
+            bool	isCritical,
+            bool	isRevocable)
+        {
+            list.Add(new Revocable(isCritical, isRevocable));
+        }
+
+		public void SetExportable(
+            bool	isCritical,
+            bool	isExportable)
+        {
+            list.Add(new Exportable(isCritical, isExportable));
+        }
+
+		/// <summary>
+		/// Add a TrustSignature packet to the signature. The values for depth and trust are largely
+		/// installation dependent but there are some guidelines in RFC 4880 - 5.2.3.13.
+		/// </summary>
+		/// <param name="isCritical">true if the packet is critical.</param>
+		/// <param name="depth">depth level.</param>
+		/// <param name="trustAmount">trust amount.</param>
+		public void SetTrust(
+            bool	isCritical,
+            int		depth,
+            int		trustAmount)
+        {
+            list.Add(new TrustSignature(isCritical, depth, trustAmount));
+        }
+
+		/// <summary>
+		/// Set the number of seconds a key is valid for after the time of its creation.
+		/// A value of zero means the key never expires.
+		/// </summary>
+		/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+		/// <param name="seconds">The number of seconds the key is valid, or zero if no expiry.</param>
+        public void SetKeyExpirationTime(
+            bool	isCritical,
+            long	seconds)
+        {
+            list.Add(new KeyExpirationTime(isCritical, seconds));
+        }
+
+		/// <summary>
+		/// Set the number of seconds a signature is valid for after the time of its creation.
+		/// A value of zero means the signature never expires.
+		/// </summary>
+		/// <param name="isCritical">True, if should be treated as critical, false otherwise.</param>
+		/// <param name="seconds">The number of seconds the signature is valid, or zero if no expiry.</param>
+        public void SetSignatureExpirationTime(
+            bool	isCritical,
+            long	seconds)
+        {
+            list.Add(new SignatureExpirationTime(isCritical, seconds));
+        }
+
+		/// <summary>
+		/// Set the creation time for the signature.
+		/// <p>
+		/// Note: this overrides the generation of a creation time when the signature
+		/// is generated.</p>
+		/// </summary>
+		public void SetSignatureCreationTime(
+			bool		isCritical,
+			DateTime	date)
+		{
+			list.Add(new SignatureCreationTime(isCritical, date));
+		}
+
+		public void SetPreferredHashAlgorithms(
+            bool	isCritical,
+            int[]	algorithms)
+        {
+            list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredHashAlgorithms, isCritical, algorithms));
+        }
+
+		public void SetPreferredSymmetricAlgorithms(
+            bool	isCritical,
+            int[]	algorithms)
+        {
+            list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredSymmetricAlgorithms, isCritical, algorithms));
+        }
+
+		public void SetPreferredCompressionAlgorithms(
+            bool	isCritical,
+            int[]	algorithms)
+        {
+            list.Add(new PreferredAlgorithms(SignatureSubpacketTag.PreferredCompressionAlgorithms, isCritical, algorithms));
+        }
+
+		public void SetKeyFlags(
+            bool	isCritical,
+            int		flags)
+        {
+            list.Add(new KeyFlags(isCritical, flags));
+        }
+
+		public void SetSignerUserId(
+            bool	isCritical,
+            string	userId)
+        {
+            if (userId == null)
+                throw new ArgumentNullException("userId");
+
+			list.Add(new SignerUserId(isCritical, userId));
+        }
+
+		public void SetEmbeddedSignature(
+			bool			isCritical,
+			PgpSignature	pgpSignature)
+		{
+			byte[] sig = pgpSignature.GetEncoded();
+			byte[] data;
+
+			// TODO Should be >= ?
+			if (sig.Length - 1 > 256)
+			{
+				data = new byte[sig.Length - 3];
+			}
+			else
+			{
+				data = new byte[sig.Length - 2];
+			}
+
+			Array.Copy(sig, sig.Length - data.Length, data, 0, data.Length);
+
+			list.Add(new EmbeddedSignature(isCritical, data));
+		}
+
+		public void SetPrimaryUserId(
+            bool	isCritical,
+            bool	isPrimaryUserId)
+        {
+            list.Add(new PrimaryUserId(isCritical, isPrimaryUserId));
+        }
+
+		public void SetNotationData(
+			bool	isCritical,
+			bool	isHumanReadable,
+			string	notationName,
+			string	notationValue)
+		{
+			list.Add(new NotationData(isCritical, isHumanReadable, notationName, notationValue));
+		}
+
+		/// <summary>
+		/// Sets revocation reason sub packet
+		/// </summary>	    
+		public void SetRevocationReason(bool isCritical, RevocationReasonTag reason,
+			string description)
+		{
+			list.Add(new RevocationReason(isCritical, reason, description));
+		}
+
+		/// <summary>
+		/// Sets revocation key sub packet
+		/// </summary>	
+		public void SetRevocationKey(bool isCritical, PublicKeyAlgorithmTag keyAlgorithm, byte[] fingerprint)
+		{
+			list.Add(new RevocationKey(isCritical, RevocationKeyTag.ClassDefault, keyAlgorithm, fingerprint));
+		}
+
+		/// <summary>
+		/// Sets issuer key sub packet
+		/// </summary>	
+		public void SetIssuerKeyID(bool isCritical, long keyID)
+		{
+			list.Add(new IssuerKeyId(isCritical, keyID));
+		}    
+
+		public PgpSignatureSubpacketVector Generate()
+        {
+            SignatureSubpacket[] a = new SignatureSubpacket[list.Count];
+            for (int i = 0; i < list.Count; ++i)
+            {
+                a[i] = (SignatureSubpacket)list[i];
+            }
+            return new PgpSignatureSubpacketVector(a);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketVector.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketVector.cs
new file mode 100644
index 0000000..68fe4b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpSignatureSubpacketVector.cs
@@ -0,0 +1,229 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Container for a list of signature subpackets.</remarks>
+    public class PgpSignatureSubpacketVector
+    {
+        private readonly SignatureSubpacket[] packets;
+
+		internal PgpSignatureSubpacketVector(
+            SignatureSubpacket[] packets)
+        {
+            this.packets = packets;
+        }
+
+		public SignatureSubpacket GetSubpacket(
+            SignatureSubpacketTag type)
+        {
+            for (int i = 0; i != packets.Length; i++)
+            {
+                if (packets[i].SubpacketType == type)
+                {
+                    return packets[i];
+                }
+            }
+
+			return null;
+        }
+
+		/**
+		 * Return true if a particular subpacket type exists.
+		 *
+		 * @param type type to look for.
+		 * @return true if present, false otherwise.
+		 */
+		public bool HasSubpacket(
+			SignatureSubpacketTag type)
+		{
+			return GetSubpacket(type) != null;
+		}
+
+		/**
+		 * Return all signature subpackets of the passed in type.
+		 * @param type subpacket type code
+		 * @return an array of zero or more matching subpackets.
+		 */
+		public SignatureSubpacket[] GetSubpackets(
+			SignatureSubpacketTag type)
+		{
+            int count = 0;
+            for (int i = 0; i < packets.Length; ++i)
+            {
+                if (packets[i].SubpacketType == type)
+                {
+                    ++count;
+                }
+            }
+
+            SignatureSubpacket[] result = new SignatureSubpacket[count];
+
+            int pos = 0;
+            for (int i = 0; i < packets.Length; ++i)
+            {
+                if (packets[i].SubpacketType == type)
+                {
+                    result[pos++] = packets[i];
+                }
+            }
+
+            return result;
+        }
+
+        public NotationData[] GetNotationDataOccurences()
+		{
+			SignatureSubpacket[] notations = GetSubpackets(SignatureSubpacketTag.NotationData);
+			NotationData[] vals = new NotationData[notations.Length];
+
+			for (int i = 0; i < notations.Length; i++)
+			{
+				vals[i] = (NotationData) notations[i];
+			}
+
+			return vals;
+		}
+
+		public long GetIssuerKeyId()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.IssuerKeyId);
+
+            return p == null ? 0 : ((IssuerKeyId) p).KeyId;
+        }
+
+		public bool HasSignatureCreationTime()
+		{
+			return GetSubpacket(SignatureSubpacketTag.CreationTime) != null;
+		}
+
+		public DateTime GetSignatureCreationTime()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.CreationTime);
+
+            if (p == null)
+            {
+                throw new PgpException("SignatureCreationTime not available");
+            }
+
+            return ((SignatureCreationTime)p).GetTime();
+        }
+
+		/// <summary>
+		/// Return the number of seconds a signature is valid for after its creation date.
+		/// A value of zero means the signature never expires.
+		/// </summary>
+		/// <returns>Seconds a signature is valid for.</returns>
+        public long GetSignatureExpirationTime()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.ExpireTime);
+
+			return p == null ? 0 : ((SignatureExpirationTime) p).Time;
+        }
+
+		/// <summary>
+		/// Return the number of seconds a key is valid for after its creation date.
+		/// A value of zero means the key never expires.
+		/// </summary>
+		/// <returns>Seconds a signature is valid for.</returns>
+        public long GetKeyExpirationTime()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.KeyExpireTime);
+
+			return p == null ? 0 : ((KeyExpirationTime) p).Time;
+        }
+
+		public int[] GetPreferredHashAlgorithms()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredHashAlgorithms);
+
+			return p == null ? null : ((PreferredAlgorithms) p).GetPreferences();
+        }
+
+		public int[] GetPreferredSymmetricAlgorithms()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredSymmetricAlgorithms);
+
+            return p == null ? null : ((PreferredAlgorithms) p).GetPreferences();
+        }
+
+		public int[] GetPreferredCompressionAlgorithms()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.PreferredCompressionAlgorithms);
+
+            return p == null ? null : ((PreferredAlgorithms) p).GetPreferences();
+        }
+
+		public int GetKeyFlags()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.KeyFlags);
+
+            return p == null ? 0 : ((KeyFlags) p).Flags;
+        }
+
+		public string GetSignerUserId()
+        {
+            SignatureSubpacket p = GetSubpacket(SignatureSubpacketTag.SignerUserId);
+
+			return p == null ? null : ((SignerUserId) p).GetId();
+        }
+
+		public bool IsPrimaryUserId()
+		{
+			PrimaryUserId primaryId = (PrimaryUserId)
+				this.GetSubpacket(SignatureSubpacketTag.PrimaryUserId);
+
+			if (primaryId != null)
+			{
+				return primaryId.IsPrimaryUserId();
+			}
+
+			return false;
+		}
+
+		public SignatureSubpacketTag[] GetCriticalTags()
+        {
+            int count = 0;
+            for (int i = 0; i != packets.Length; i++)
+            {
+                if (packets[i].IsCritical())
+                {
+                    count++;
+                }
+            }
+
+			SignatureSubpacketTag[] list = new SignatureSubpacketTag[count];
+
+			count = 0;
+
+			for (int i = 0; i != packets.Length; i++)
+            {
+                if (packets[i].IsCritical())
+                {
+                    list[count++] = packets[i].SubpacketType;
+                }
+            }
+
+			return list;
+        }
+
+		[Obsolete("Use 'Count' property instead")]
+		public int Size
+		{
+			get { return packets.Length; }
+		}
+
+		/// <summary>Return the number of packets this vector contains.</summary>
+		public int Count
+		{
+			get { return packets.Length; }
+		}
+
+		internal SignatureSubpacket[] ToSubpacketArray()
+        {
+            return packets;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpUserAttributeSubpacketVector.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpUserAttributeSubpacketVector.cs
new file mode 100644
index 0000000..4cdbeda
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpUserAttributeSubpacketVector.cs
@@ -0,0 +1,81 @@
+using Org.BouncyCastle.Bcpg.Attr;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Container for a list of user attribute subpackets.</remarks>
+    public class PgpUserAttributeSubpacketVector
+    {
+        private readonly UserAttributeSubpacket[] packets;
+
+		internal PgpUserAttributeSubpacketVector(
+            UserAttributeSubpacket[] packets)
+        {
+            this.packets = packets;
+        }
+
+		public UserAttributeSubpacket GetSubpacket(
+            UserAttributeSubpacketTag type)
+        {
+            for (int i = 0; i != packets.Length; i++)
+            {
+                if (packets[i].SubpacketType == type)
+                {
+                    return packets[i];
+                }
+            }
+
+			return null;
+        }
+
+		public ImageAttrib GetImageAttribute()
+        {
+            UserAttributeSubpacket p = GetSubpacket(UserAttributeSubpacketTag.ImageAttribute);
+
+            return p == null ? null : (ImageAttrib) p;
+        }
+
+		internal UserAttributeSubpacket[] ToSubpacketArray()
+        {
+            return packets;
+        }
+
+		public override bool Equals(
+            object obj)
+        {
+            if (obj == this)
+                return true;
+
+			PgpUserAttributeSubpacketVector other = obj as PgpUserAttributeSubpacketVector;
+
+			if (other == null)
+				return false;
+
+			if (other.packets.Length != packets.Length)
+            {
+                return false;
+            }
+
+			for (int i = 0; i != packets.Length; i++)
+            {
+                if (!other.packets[i].Equals(packets[i]))
+                {
+                    return false;
+                }
+            }
+
+			return true;
+        }
+
+		public override int GetHashCode()
+        {
+            int code = 0;
+
+			foreach (object o in packets)
+			{
+				code ^= o.GetHashCode();
+			}
+
+			return code;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpUtilities.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpUtilities.cs
new file mode 100644
index 0000000..cd53cc0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpUtilities.cs
@@ -0,0 +1,437 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Basic utility class.</remarks>
+    public sealed class PgpUtilities
+    {
+        private PgpUtilities()
+        {
+        }
+
+		public static MPInteger[] DsaSigToMpi(
+			byte[] encoding)
+		{
+			DerInteger i1, i2;
+
+			try
+			{
+				Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+				i1 = (DerInteger) s[0];
+				i2 = (DerInteger) s[1];
+			}
+			catch (IOException e)
+			{
+				throw new PgpException("exception encoding signature", e);
+			}
+
+			return new MPInteger[]{ new MPInteger(i1.Value), new MPInteger(i2.Value) };
+		}
+
+		public static MPInteger[] RsaSigToMpi(
+			byte[] encoding)
+		{
+			return new MPInteger[]{ new MPInteger(new BigInteger(1, encoding)) };
+		}
+
+		public static string GetDigestName(
+            HashAlgorithmTag hashAlgorithm)
+        {
+            switch (hashAlgorithm)
+            {
+				case HashAlgorithmTag.Sha1:
+					return "SHA1";
+				case HashAlgorithmTag.MD2:
+					return "MD2";
+				case HashAlgorithmTag.MD5:
+					return "MD5";
+				case HashAlgorithmTag.RipeMD160:
+					return "RIPEMD160";
+				case HashAlgorithmTag.Sha224:
+					return "SHA224";
+				case HashAlgorithmTag.Sha256:
+					return "SHA256";
+				case HashAlgorithmTag.Sha384:
+					return "SHA384";
+				case HashAlgorithmTag.Sha512:
+					return "SHA512";
+				default:
+					throw new PgpException("unknown hash algorithm tag in GetDigestName: " + hashAlgorithm);
+			}
+        }
+
+		public static string GetSignatureName(
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm)
+        {
+            string encAlg;
+			switch (keyAlgorithm)
+            {
+				case PublicKeyAlgorithmTag.RsaGeneral:
+				case PublicKeyAlgorithmTag.RsaSign:
+					encAlg = "RSA";
+					break;
+				case PublicKeyAlgorithmTag.Dsa:
+					encAlg = "DSA";
+					break;
+				case PublicKeyAlgorithmTag.ElGamalEncrypt: // in some malformed cases.
+				case PublicKeyAlgorithmTag.ElGamalGeneral:
+					encAlg = "ElGamal";
+					break;
+				default:
+					throw new PgpException("unknown algorithm tag in signature:" + keyAlgorithm);
+            }
+
+			return GetDigestName(hashAlgorithm) + "with" + encAlg;
+        }
+
+	public static string GetSymmetricCipherName(
+            SymmetricKeyAlgorithmTag algorithm)
+        {
+            switch (algorithm)
+            {
+				case SymmetricKeyAlgorithmTag.Null:
+					return null;
+				case SymmetricKeyAlgorithmTag.TripleDes:
+					return "DESEDE";
+				case SymmetricKeyAlgorithmTag.Idea:
+					return "IDEA";
+				case SymmetricKeyAlgorithmTag.Cast5:
+					return "CAST5";
+				case SymmetricKeyAlgorithmTag.Blowfish:
+					return "Blowfish";
+				case SymmetricKeyAlgorithmTag.Safer:
+					return "SAFER";
+				case SymmetricKeyAlgorithmTag.Des:
+					return "DES";
+				case SymmetricKeyAlgorithmTag.Aes128:
+					return "AES";
+				case SymmetricKeyAlgorithmTag.Aes192:
+					return "AES";
+				case SymmetricKeyAlgorithmTag.Aes256:
+					return "AES";
+				case SymmetricKeyAlgorithmTag.Twofish:
+					return "Twofish";
+				case SymmetricKeyAlgorithmTag.Camellia128:
+					return "Camellia";
+				case SymmetricKeyAlgorithmTag.Camellia192:
+					return "Camellia";
+				case SymmetricKeyAlgorithmTag.Camellia256:
+					return "Camellia";
+				default:
+					throw new PgpException("unknown symmetric algorithm: " + algorithm);
+            }
+        }
+
+	public static int GetKeySize(SymmetricKeyAlgorithmTag algorithm)
+        {
+            int keySize;
+            switch (algorithm)
+            {
+                case SymmetricKeyAlgorithmTag.Des:
+                    keySize = 64;
+                    break;
+                case SymmetricKeyAlgorithmTag.Idea:
+                case SymmetricKeyAlgorithmTag.Cast5:
+                case SymmetricKeyAlgorithmTag.Blowfish:
+                case SymmetricKeyAlgorithmTag.Safer:
+                case SymmetricKeyAlgorithmTag.Aes128:
+                case SymmetricKeyAlgorithmTag.Camellia128:
+                    keySize = 128;
+                    break;
+                case SymmetricKeyAlgorithmTag.TripleDes:
+                case SymmetricKeyAlgorithmTag.Aes192:
+                case SymmetricKeyAlgorithmTag.Camellia192:
+                    keySize = 192;
+                    break;
+                case SymmetricKeyAlgorithmTag.Aes256:
+                case SymmetricKeyAlgorithmTag.Twofish:
+                case SymmetricKeyAlgorithmTag.Camellia256:
+                    keySize = 256;
+                    break;
+                default:
+                    throw new PgpException("unknown symmetric algorithm: " + algorithm);
+            }
+
+			return keySize;
+        }
+
+		public static KeyParameter MakeKey(
+			SymmetricKeyAlgorithmTag	algorithm,
+			byte[]						keyBytes)
+		{
+			string algName = GetSymmetricCipherName(algorithm);
+
+			return ParameterUtilities.CreateKeyParameter(algName, keyBytes);
+		}
+
+		public static KeyParameter MakeRandomKey(
+            SymmetricKeyAlgorithmTag	algorithm,
+            SecureRandom				random)
+        {
+            int keySize = GetKeySize(algorithm);
+            byte[] keyBytes = new byte[(keySize + 7) / 8];
+            random.NextBytes(keyBytes);
+			return MakeKey(algorithm, keyBytes);
+        }
+
+		public static KeyParameter MakeKeyFromPassPhrase(
+            SymmetricKeyAlgorithmTag	algorithm,
+            S2k							s2k,
+            char[]						passPhrase)
+        {
+			int keySize = GetKeySize(algorithm);
+			byte[] pBytes = Strings.ToByteArray(new string(passPhrase));
+			byte[] keyBytes = new byte[(keySize + 7) / 8];
+
+			int generatedBytes = 0;
+            int loopCount = 0;
+
+			while (generatedBytes < keyBytes.Length)
+            {
+				IDigest digest;
+				if (s2k != null)
+                {
+					string digestName = GetDigestName(s2k.HashAlgorithm);
+
+                    try
+                    {
+						digest = DigestUtilities.GetDigest(digestName);
+                    }
+                    catch (Exception e)
+                    {
+                        throw new PgpException("can't find S2k digest", e);
+                    }
+
+					for (int i = 0; i != loopCount; i++)
+                    {
+                        digest.Update(0);
+                    }
+
+					byte[] iv = s2k.GetIV();
+
+					switch (s2k.Type)
+                    {
+						case S2k.Simple:
+							digest.BlockUpdate(pBytes, 0, pBytes.Length);
+							break;
+						case S2k.Salted:
+							digest.BlockUpdate(iv, 0, iv.Length);
+							digest.BlockUpdate(pBytes, 0, pBytes.Length);
+							break;
+						case S2k.SaltedAndIterated:
+							long count = s2k.IterationCount;
+							digest.BlockUpdate(iv, 0, iv.Length);
+							digest.BlockUpdate(pBytes, 0, pBytes.Length);
+
+							count -= iv.Length + pBytes.Length;
+
+							while (count > 0)
+							{
+								if (count < iv.Length)
+								{
+									digest.BlockUpdate(iv, 0, (int)count);
+									break;
+								}
+								else
+								{
+									digest.BlockUpdate(iv, 0, iv.Length);
+									count -= iv.Length;
+								}
+
+								if (count < pBytes.Length)
+								{
+									digest.BlockUpdate(pBytes, 0, (int)count);
+									count = 0;
+								}
+								else
+								{
+									digest.BlockUpdate(pBytes, 0, pBytes.Length);
+									count -= pBytes.Length;
+								}
+							}
+							break;
+						default:
+							throw new PgpException("unknown S2k type: " + s2k.Type);
+                    }
+                }
+                else
+                {
+                    try
+                    {
+                        digest = DigestUtilities.GetDigest("MD5");
+
+						for (int i = 0; i != loopCount; i++)
+                        {
+                            digest.Update(0);
+                        }
+
+						digest.BlockUpdate(pBytes, 0, pBytes.Length);
+                    }
+                    catch (Exception e)
+                    {
+                        throw new PgpException("can't find MD5 digest", e);
+                    }
+                }
+
+				byte[] dig = DigestUtilities.DoFinal(digest);
+
+				if (dig.Length > (keyBytes.Length - generatedBytes))
+                {
+                    Array.Copy(dig, 0, keyBytes, generatedBytes, keyBytes.Length - generatedBytes);
+                }
+                else
+                {
+                    Array.Copy(dig, 0, keyBytes, generatedBytes, dig.Length);
+                }
+
+				generatedBytes += dig.Length;
+
+				loopCount++;
+            }
+
+			Array.Clear(pBytes, 0, pBytes.Length);
+
+			return MakeKey(algorithm, keyBytes);
+        }
+
+#if !PCL
+		/// <summary>Write out the passed in file as a literal data packet.</summary>
+        public static void WriteFileToLiteralData(
+            Stream		output,
+            char		fileType,
+            FileInfo	file)
+        {
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+			Stream pOut = lData.Open(output, fileType, file.Name, file.Length, file.LastWriteTime);
+			PipeFileContents(file, pOut, 4096);
+        }
+
+		/// <summary>Write out the passed in file as a literal data packet in partial packet format.</summary>
+        public static void WriteFileToLiteralData(
+            Stream		output,
+            char		fileType,
+            FileInfo	file,
+            byte[]		buffer)
+        {
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+            Stream pOut = lData.Open(output, fileType, file.Name, file.LastWriteTime, buffer);
+			PipeFileContents(file, pOut, buffer.Length);
+        }
+
+		private static void PipeFileContents(FileInfo file, Stream pOut, int bufSize)
+		{
+			FileStream inputStream = file.OpenRead();
+			byte[] buf = new byte[bufSize];
+
+			int len;
+            while ((len = inputStream.Read(buf, 0, buf.Length)) > 0)
+            {
+                pOut.Write(buf, 0, len);
+            }
+
+			pOut.Close();
+			inputStream.Close();
+		}
+#endif
+
+		private const int ReadAhead = 60;
+
+		private static bool IsPossiblyBase64(
+            int ch)
+        {
+            return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
+                    || (ch >= '0' && ch <= '9') || (ch == '+') || (ch == '/')
+                    || (ch == '\r') || (ch == '\n');
+        }
+
+		/// <summary>
+		/// Return either an ArmoredInputStream or a BcpgInputStream based on whether
+		/// the initial characters of the stream are binary PGP encodings or not.
+		/// </summary>
+        public static Stream GetDecoderStream(
+            Stream inputStream)
+        {
+			// TODO Remove this restriction?
+			if (!inputStream.CanSeek)
+				throw new ArgumentException("inputStream must be seek-able", "inputStream");
+
+			long markedPos = inputStream.Position;
+
+			int ch = inputStream.ReadByte();
+            if ((ch & 0x80) != 0)
+            {
+                inputStream.Position = markedPos;
+
+				return inputStream;
+            }
+            else
+            {
+                if (!IsPossiblyBase64(ch))
+                {
+                    inputStream.Position = markedPos;
+
+					return new ArmoredInputStream(inputStream);
+                }
+
+				byte[]	buf = new byte[ReadAhead];
+                int		count = 1;
+                int		index = 1;
+
+				buf[0] = (byte)ch;
+                while (count != ReadAhead && (ch = inputStream.ReadByte()) >= 0)
+                {
+                    if (!IsPossiblyBase64(ch))
+                    {
+                        inputStream.Position = markedPos;
+
+						return new ArmoredInputStream(inputStream);
+                    }
+
+					if (ch != '\n' && ch != '\r')
+                    {
+                        buf[index++] = (byte)ch;
+                    }
+
+					count++;
+                }
+
+				inputStream.Position = markedPos;
+
+				//
+                // nothing but new lines, little else, assume regular armoring
+                //
+                if (count < 4)
+                {
+                    return new ArmoredInputStream(inputStream);
+                }
+
+				//
+                // test our non-blank data
+                //
+                byte[] firstBlock = new byte[8];
+				Array.Copy(buf, 0, firstBlock, 0, firstBlock.Length);
+				byte[] decoded = Base64.Decode(firstBlock);
+
+				//
+                // it's a base64 PGP block.
+                //
+				bool hasHeaders = (decoded[0] & 0x80) == 0;
+
+				return new ArmoredInputStream(inputStream, hasHeaders);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/PgpV3SignatureGenerator.cs b/BouncyCastle.AxCrypt/src/openpgp/PgpV3SignatureGenerator.cs
new file mode 100644
index 0000000..fc8b42d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/PgpV3SignatureGenerator.cs
@@ -0,0 +1,199 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	/// <remarks>Generator for old style PGP V3 Signatures.</remarks>
+	// TODO Should be able to implement ISigner?
+	public class PgpV3SignatureGenerator
+    {
+        private PublicKeyAlgorithmTag keyAlgorithm;
+        private HashAlgorithmTag hashAlgorithm;
+        private PgpPrivateKey privKey;
+        private ISigner sig;
+        private IDigest    dig;
+        private int signatureType;
+        private byte lastb;
+
+		/// <summary>Create a generator for the passed in keyAlgorithm and hashAlgorithm codes.</summary>
+        public PgpV3SignatureGenerator(
+            PublicKeyAlgorithmTag	keyAlgorithm,
+            HashAlgorithmTag		hashAlgorithm)
+        {
+            this.keyAlgorithm = keyAlgorithm;
+            this.hashAlgorithm = hashAlgorithm;
+
+            dig = DigestUtilities.GetDigest(PgpUtilities.GetDigestName(hashAlgorithm));
+            sig = SignerUtilities.GetSigner(PgpUtilities.GetSignatureName(keyAlgorithm, hashAlgorithm));
+        }
+
+		/// <summary>Initialise the generator for signing.</summary>
+		public void InitSign(
+			int				sigType,
+			PgpPrivateKey	key)
+		{
+			InitSign(sigType, key, null);
+		}
+
+		/// <summary>Initialise the generator for signing.</summary>
+        public void InitSign(
+            int				sigType,
+            PgpPrivateKey	key,
+			SecureRandom	random)
+        {
+            this.privKey = key;
+            this.signatureType = sigType;
+
+			try
+            {
+				ICipherParameters cp = key.Key;
+				if (random != null)
+				{
+					cp = new ParametersWithRandom(key.Key, random);
+				}
+
+				sig.Init(true, cp);
+            }
+            catch (InvalidKeyException e)
+            {
+                throw new PgpException("invalid key.", e);
+            }
+
+			dig.Reset();
+            lastb = 0;
+        }
+
+		public void Update(
+            byte b)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+				doCanonicalUpdateByte(b);
+            }
+            else
+            {
+				doUpdateByte(b);
+            }
+        }
+
+		private void doCanonicalUpdateByte(
+			byte b)
+		{
+			if (b == '\r')
+			{
+				doUpdateCRLF();
+			}
+			else if (b == '\n')
+			{
+				if (lastb != '\r')
+				{
+					doUpdateCRLF();
+				}
+			}
+			else
+			{
+				doUpdateByte(b);
+			}
+
+			lastb = b;
+		}
+
+		private void doUpdateCRLF()
+		{
+			doUpdateByte((byte)'\r');
+			doUpdateByte((byte)'\n');
+		}
+
+		private void doUpdateByte(
+			byte b)
+		{
+			sig.Update(b);
+			dig.Update(b);
+		}
+
+		public void Update(
+            byte[] b)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+                for (int i = 0; i != b.Length; i++)
+                {
+                    doCanonicalUpdateByte(b[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(b, 0, b.Length);
+                dig.BlockUpdate(b, 0, b.Length);
+            }
+        }
+
+		public void Update(
+            byte[]	b,
+            int		off,
+            int		len)
+        {
+            if (signatureType == PgpSignature.CanonicalTextDocument)
+            {
+                int finish = off + len;
+
+				for (int i = off; i != finish; i++)
+                {
+                    doCanonicalUpdateByte(b[i]);
+                }
+            }
+            else
+            {
+                sig.BlockUpdate(b, off, len);
+                dig.BlockUpdate(b, off, len);
+            }
+        }
+
+		/// <summary>Return the one pass header associated with the current signature.</summary>
+        public PgpOnePassSignature GenerateOnePassVersion(
+            bool isNested)
+        {
+            return new PgpOnePassSignature(
+				new OnePassSignaturePacket(signatureType, hashAlgorithm, keyAlgorithm, privKey.KeyId, isNested));
+        }
+
+		/// <summary>Return a V3 signature object containing the current signature state.</summary>
+        public PgpSignature Generate()
+        {
+            long creationTime = DateTimeUtilities.CurrentUnixMs() / 1000L;
+
+			byte[] hData = new byte[]
+			{
+				(byte) signatureType,
+				(byte)(creationTime >> 24),
+				(byte)(creationTime >> 16),
+				(byte)(creationTime >> 8),
+				(byte) creationTime
+			};
+
+			sig.BlockUpdate(hData, 0, hData.Length);
+            dig.BlockUpdate(hData, 0, hData.Length);
+
+			byte[] sigBytes = sig.GenerateSignature();
+			byte[] digest = DigestUtilities.DoFinal(dig);
+			byte[] fingerPrint = new byte[]{ digest[0], digest[1] };
+
+			// an RSA signature
+			bool isRsa = keyAlgorithm == PublicKeyAlgorithmTag.RsaSign
+                || keyAlgorithm == PublicKeyAlgorithmTag.RsaGeneral;
+
+			MPInteger[] sigValues = isRsa
+				?	PgpUtilities.RsaSigToMpi(sigBytes)
+				:	PgpUtilities.DsaSigToMpi(sigBytes);
+
+			return new PgpSignature(
+				new SignaturePacket(3, signatureType, privKey.KeyId, keyAlgorithm,
+					hashAlgorithm, creationTime * 1000L, fingerPrint, sigValues));
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openpgp/WrappedGeneratorStream.cs b/BouncyCastle.AxCrypt/src/openpgp/WrappedGeneratorStream.cs
new file mode 100644
index 0000000..e577974
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openpgp/WrappedGeneratorStream.cs
@@ -0,0 +1,29 @@
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp
+{
+	public class WrappedGeneratorStream
+		: FilterStream
+	{
+		private readonly IStreamGenerator gen;
+
+		public WrappedGeneratorStream(
+			IStreamGenerator	gen,
+			Stream				str)
+			: base(str)
+		{
+			this.gen = gen;
+		}
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            gen.Close();
+	        }
+	   //     base.Dispose(disposing);
+	    }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/EncryptionException.cs b/BouncyCastle.AxCrypt/src/openssl/EncryptionException.cs
new file mode 100644
index 0000000..c4a6ec0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/EncryptionException.cs
@@ -0,0 +1,25 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class EncryptionException
+		: IOException
+	{
+		public EncryptionException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public EncryptionException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/IPasswordFinder.cs b/BouncyCastle.AxCrypt/src/openssl/IPasswordFinder.cs
new file mode 100644
index 0000000..4fcef1b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/IPasswordFinder.cs
@@ -0,0 +1,9 @@
+using System;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+	public interface IPasswordFinder
+	{
+		char[] GetPassword();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/MiscPemGenerator.cs b/BouncyCastle.AxCrypt/src/openssl/MiscPemGenerator.cs
new file mode 100644
index 0000000..6b91e8b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/MiscPemGenerator.cs
@@ -0,0 +1,276 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO.Pem;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+    /**
+    * PEM generator for the original set of PEM objects used in Open SSL.
+    */
+    public class MiscPemGenerator
+        : PemObjectGenerator
+    {
+        private object obj;
+        private string algorithm;
+        private char[] password;
+        private SecureRandom random;
+
+        public MiscPemGenerator(object obj)
+        {
+            this.obj = obj;
+        }
+
+        public MiscPemGenerator(
+            object			obj,
+            string			algorithm,
+            char[]			password,
+            SecureRandom	random)
+        {
+            this.obj = obj;
+            this.algorithm = algorithm;
+            this.password = password;
+            this.random = random;
+        }
+
+        private static PemObject CreatePemObject(object obj)
+        {
+            if (obj == null)
+                throw new ArgumentNullException("obj");
+
+            if (obj is AsymmetricCipherKeyPair)
+            {
+                return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private);
+            }
+
+            string type;
+            byte[] encoding;
+
+            if (obj is PemObject)
+                return (PemObject)obj;
+
+            if (obj is PemObjectGenerator)
+                return ((PemObjectGenerator)obj).Generate();
+
+            if (obj is X509Certificate)
+            {
+                // TODO Should we prefer "X509 CERTIFICATE" here?
+                type = "CERTIFICATE";
+                try
+                {
+                    encoding = ((X509Certificate)obj).GetEncoded();
+                }
+                catch (CertificateEncodingException e)
+                {
+                    throw new IOException("Cannot Encode object: " + e.ToString());
+                }
+            }
+            else if (obj is X509Crl)
+            {
+                type = "X509 CRL";
+                try
+                {
+                    encoding = ((X509Crl)obj).GetEncoded();
+                }
+                catch (CrlException e)
+                {
+                    throw new IOException("Cannot Encode object: " + e.ToString());
+                }
+            }
+            else if (obj is AsymmetricKeyParameter)
+            {
+                AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj;
+                if (akp.IsPrivate)
+                {
+                    string keyType;
+                    encoding = EncodePrivateKey(akp, out keyType);
+
+                    type = keyType + " PRIVATE KEY";
+                }
+                else
+                {
+                    type = "PUBLIC KEY";
+
+                    encoding = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(akp).GetDerEncoded();
+                }
+            }
+            else if (obj is IX509AttributeCertificate)
+            {
+                type = "ATTRIBUTE CERTIFICATE";
+                encoding = ((X509V2AttributeCertificate)obj).GetEncoded();
+            }
+            else if (obj is Pkcs10CertificationRequest)
+            {
+                type = "CERTIFICATE REQUEST";
+                encoding = ((Pkcs10CertificationRequest)obj).GetEncoded();
+            }
+            else if (obj is Asn1.Cms.ContentInfo)
+            {
+                type = "PKCS7";
+                encoding = ((Asn1.Cms.ContentInfo)obj).GetEncoded();
+            }
+            else
+            {
+                throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName);
+            }
+
+            return new PemObject(type, encoding);
+        }
+
+//		private string GetHexEncoded(byte[] bytes)
+//		{
+//			bytes = Hex.Encode(bytes);
+//
+//			char[] chars = new char[bytes.Length];
+//
+//			for (int i = 0; i != bytes.Length; i++)
+//			{
+//				chars[i] = (char)bytes[i];
+//			}
+//
+//			return new string(chars);
+//		}
+
+        private static PemObject CreatePemObject(
+            object			obj,
+            string			algorithm,
+            char[]			password,
+            SecureRandom	random)
+        {
+            if (obj == null)
+                throw new ArgumentNullException("obj");
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+            if (password == null)
+                throw new ArgumentNullException("password");
+            if (random == null)
+                throw new ArgumentNullException("random");
+
+            if (obj is AsymmetricCipherKeyPair)
+            {
+                return CreatePemObject(((AsymmetricCipherKeyPair)obj).Private, algorithm, password, random);
+            }
+
+            string type = null;
+            byte[] keyData = null;
+
+            if (obj is AsymmetricKeyParameter)
+            {
+                AsymmetricKeyParameter akp = (AsymmetricKeyParameter) obj;
+                if (akp.IsPrivate)
+                {
+                    string keyType;
+                    keyData = EncodePrivateKey(akp, out keyType);
+
+                    type = keyType + " PRIVATE KEY";
+                }
+            }
+
+            if (type == null || keyData == null)
+            {
+                // TODO Support other types?
+                throw new PemGenerationException("Object type not supported: " + obj.GetType().FullName);
+            }
+
+
+            string dekAlgName = Platform.ToUpperInvariant(algorithm);
+
+            // Note: For backward compatibility
+            if (dekAlgName == "DESEDE")
+            {
+                dekAlgName = "DES-EDE3-CBC";
+            }
+
+            int ivLength = dekAlgName.StartsWith("AES-") ? 16 : 8;
+
+            byte[] iv = new byte[ivLength];
+            random.NextBytes(iv);
+
+            byte[] encData = PemUtilities.Crypt(true, keyData, password, dekAlgName, iv);
+
+            IList headers = Platform.CreateArrayList(2);
+
+            headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
+            headers.Add(new PemHeader("DEK-Info", dekAlgName + "," + Hex.ToHexString(iv)));
+
+            return new PemObject(type, headers, encData);
+        }
+
+        private static byte[] EncodePrivateKey(
+            AsymmetricKeyParameter	akp,
+            out string				keyType)
+        {
+            PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(akp);
+            AlgorithmIdentifier algID = info.PrivateKeyAlgorithm;
+            DerObjectIdentifier oid = algID.ObjectID;
+
+            if (oid.Equals(X9ObjectIdentifiers.IdDsa))
+            {
+                keyType = "DSA";
+
+                DsaParameter p = DsaParameter.GetInstance(algID.Parameters);
+
+                BigInteger x = ((DsaPrivateKeyParameters) akp).X;
+                BigInteger y = p.G.ModPow(x, p.P);
+
+                // TODO Create an ASN1 object somewhere for this?
+                return new DerSequence(
+                    new DerInteger(0),
+                    new DerInteger(p.P),
+                    new DerInteger(p.Q),
+                    new DerInteger(p.G),
+                    new DerInteger(y),
+                    new DerInteger(x)).GetEncoded();
+            }
+
+            if (oid.Equals(PkcsObjectIdentifiers.RsaEncryption))
+            {
+                keyType = "RSA";
+            }
+            else if (oid.Equals(CryptoProObjectIdentifiers.GostR3410x2001)
+                || oid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+            {
+                keyType = "EC";
+            }
+            else
+            {
+                throw new ArgumentException("Cannot handle private key of type: " + akp.GetType().FullName, "akp");
+            }
+
+            return info.ParsePrivateKey().GetEncoded();
+        }
+
+        public PemObject Generate()
+        {
+            try
+            {
+                if (algorithm != null)
+                {
+                    return CreatePemObject(obj, algorithm, password, random);
+                }
+
+                return CreatePemObject(obj);
+            }
+            catch (IOException e)
+            {
+                throw new PemGenerationException("encoding exception", e);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/PEMException.cs b/BouncyCastle.AxCrypt/src/openssl/PEMException.cs
new file mode 100644
index 0000000..4d33a2a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/PEMException.cs
@@ -0,0 +1,25 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PemException
+		: IOException
+	{
+		public PemException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public PemException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/PEMReader.cs b/BouncyCastle.AxCrypt/src/openssl/PEMReader.cs
new file mode 100644
index 0000000..9d35608
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/PEMReader.cs
@@ -0,0 +1,400 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO.Pem;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+    /**
+    * Class for reading OpenSSL PEM encoded streams containing 
+    * X509 certificates, PKCS8 encoded keys and PKCS7 objects.
+    * <p>
+    * In the case of PKCS7 objects the reader will return a CMS ContentInfo object. Keys and
+    * Certificates will be returned using the appropriate java.security type.</p>
+    */
+    public class PemReader
+        : Org.BouncyCastle.Utilities.IO.Pem.PemReader
+    {
+//		private static readonly IDictionary parsers = new Hashtable();
+
+        static PemReader()
+        {
+//			parsers.Add("CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
+//			parsers.Add("NEW CERTIFICATE REQUEST", new PKCS10CertificationRequestParser());
+//			parsers.Add("CERTIFICATE", new X509CertificateParser(provider));
+//			parsers.Add("X509 CERTIFICATE", new X509CertificateParser(provider));
+//			parsers.Add("X509 CRL", new X509CRLParser(provider));
+//			parsers.Add("PKCS7", new PKCS7Parser());
+//			parsers.Add("ATTRIBUTE CERTIFICATE", new X509AttributeCertificateParser());
+//			parsers.Add("EC PARAMETERS", new ECNamedCurveSpecParser());
+//			parsers.Add("PUBLIC KEY", new PublicKeyParser(provider));
+//			parsers.Add("RSA PUBLIC KEY", new RSAPublicKeyParser(provider));
+//			parsers.Add("RSA PRIVATE KEY", new RSAKeyPairParser(provider));
+//			parsers.Add("DSA PRIVATE KEY", new DSAKeyPairParser(provider));
+//			parsers.Add("EC PRIVATE KEY", new ECDSAKeyPairParser(provider));
+//			parsers.Add("ENCRYPTED PRIVATE KEY", new EncryptedPrivateKeyParser(provider));
+//			parsers.Add("PRIVATE KEY", new PrivateKeyParser(provider));
+        }
+
+        private readonly IPasswordFinder pFinder;
+
+        /**
+        * Create a new PemReader
+        *
+        * @param reader the Reader
+        */
+        public PemReader(
+            TextReader reader)
+            : this(reader, null)
+        {
+        }
+
+        /**
+        * Create a new PemReader with a password finder
+        *
+        * @param reader the Reader
+        * @param pFinder the password finder
+        */
+        public PemReader(
+            TextReader		reader,
+            IPasswordFinder	pFinder)
+            : base(reader)
+        {
+            this.pFinder = pFinder;
+        }
+
+        public object ReadObject()
+        {
+            PemObject obj = ReadPemObject();
+
+            if (obj == null)
+                return null;
+
+            // TODO Follow Java build and map to parser objects?
+//			if (parsers.Contains(obj.Type))
+//				return ((PemObjectParser)parsers[obj.Type]).ParseObject(obj);
+
+            if (obj.Type.EndsWith("PRIVATE KEY"))
+                return ReadPrivateKey(obj);
+
+            switch (obj.Type)
+            {
+                case "PUBLIC KEY":
+                    return ReadPublicKey(obj);
+                case "RSA PUBLIC KEY":
+                    return ReadRsaPublicKey(obj);
+                case "CERTIFICATE REQUEST":
+                case "NEW CERTIFICATE REQUEST":
+                    return ReadCertificateRequest(obj);
+                case "CERTIFICATE":
+                case "X509 CERTIFICATE":
+                    return ReadCertificate(obj);
+                case "PKCS7":
+                    return ReadPkcs7(obj);
+                case "X509 CRL":
+                    return ReadCrl(obj);
+                case "ATTRIBUTE CERTIFICATE":
+                    return ReadAttributeCertificate(obj);
+                // TODO Add back in when tests done, and return type issue resolved
+                //case "EC PARAMETERS":
+                //	return ReadECParameters(obj);
+                default:
+                    throw new IOException("unrecognised object: " + obj.Type);
+            }
+        }
+
+        private AsymmetricKeyParameter ReadRsaPublicKey(PemObject pemObject)
+        {
+            RsaPublicKeyStructure rsaPubStructure = RsaPublicKeyStructure.GetInstance(
+                Asn1Object.FromByteArray(pemObject.Content));
+
+            return new RsaKeyParameters(
+                false, // not private
+                rsaPubStructure.Modulus, 
+                rsaPubStructure.PublicExponent);
+        }
+
+        private AsymmetricKeyParameter ReadPublicKey(PemObject pemObject)
+        {
+            return PublicKeyFactory.CreateKey(pemObject.Content);
+        }
+
+        /**
+        * Reads in a X509Certificate.
+        *
+        * @return the X509Certificate
+        * @throws IOException if an I/O error occured
+        */
+        private X509Certificate ReadCertificate(PemObject pemObject)
+        {
+            try
+            {
+                return new X509CertificateParser().ReadCertificate(pemObject.Content);
+            }
+            catch (Exception e)
+            {
+                throw new PemException("problem parsing cert: " + e.ToString());
+            }
+        }
+
+        /**
+        * Reads in a X509CRL.
+        *
+        * @return the X509Certificate
+        * @throws IOException if an I/O error occured
+        */
+        private X509Crl ReadCrl(PemObject pemObject)
+        {
+            try
+            {
+                return new X509CrlParser().ReadCrl(pemObject.Content);
+            }
+            catch (Exception e)
+            {
+                throw new PemException("problem parsing cert: " + e.ToString());
+            }
+        }
+
+        /**
+        * Reads in a PKCS10 certification request.
+        *
+        * @return the certificate request.
+        * @throws IOException if an I/O error occured
+        */
+        private Pkcs10CertificationRequest ReadCertificateRequest(PemObject pemObject)
+        {
+            try
+            {
+                return new Pkcs10CertificationRequest(pemObject.Content);
+            }
+            catch (Exception e)
+            {
+                throw new PemException("problem parsing cert: " + e.ToString());
+            }
+        }
+
+        /**
+        * Reads in a X509 Attribute Certificate.
+        *
+        * @return the X509 Attribute Certificate
+        * @throws IOException if an I/O error occured
+        */
+        private IX509AttributeCertificate ReadAttributeCertificate(PemObject pemObject)
+        {
+            return new X509V2AttributeCertificate(pemObject.Content);
+        }
+
+        /**
+        * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS
+        * API.
+        *
+        * @return the X509Certificate
+        * @throws IOException if an I/O error occured
+        */
+        // TODO Consider returning Asn1.Pkcs.ContentInfo
+        private Asn1.Cms.ContentInfo ReadPkcs7(PemObject pemObject)
+        {
+            try
+            {
+                return Asn1.Cms.ContentInfo.GetInstance(
+                    Asn1Object.FromByteArray(pemObject.Content));
+            }
+            catch (Exception e)
+            {
+                throw new PemException("problem parsing PKCS7 object: " + e.ToString());
+            }
+        }
+
+        /**
+        * Read a Key Pair
+        */
+        private object ReadPrivateKey(PemObject pemObject)
+        {
+            //
+            // extract the key
+            //
+            Debug.Assert(pemObject.Type.EndsWith("PRIVATE KEY"));
+
+            string type = pemObject.Type.Substring(0, pemObject.Type.Length - "PRIVATE KEY".Length).Trim();
+            byte[] keyBytes = pemObject.Content;
+
+            IDictionary fields = Platform.CreateHashtable();
+            foreach (PemHeader header in pemObject.Headers)
+            {
+                fields[header.Name] = header.Value;
+            }
+
+            string procType = (string) fields["Proc-Type"];
+
+            if (procType == "4,ENCRYPTED")
+            {
+                if (pFinder == null)
+                    throw new PasswordException("No password finder specified, but a password is required");
+
+                char[] password = pFinder.GetPassword();
+
+                if (password == null)
+                    throw new PasswordException("Password is null, but a password is required");
+
+                string dekInfo = (string) fields["DEK-Info"];
+                string[] tknz = dekInfo.Split(',');
+
+                string dekAlgName = tknz[0].Trim();
+                byte[] iv = Hex.Decode(tknz[1].Trim());
+
+                keyBytes = PemUtilities.Crypt(false, keyBytes, password, dekAlgName, iv);
+            }
+
+            try
+            {
+                AsymmetricKeyParameter pubSpec, privSpec;
+                Asn1Sequence seq = Asn1Sequence.GetInstance(keyBytes);
+
+                switch (type)
+                {
+                    case "RSA":
+                    {
+                        if (seq.Count != 9)
+                            throw new PemException("malformed sequence in RSA private key");
+
+                        RsaPrivateKeyStructure rsa = new RsaPrivateKeyStructure(seq);
+
+                        pubSpec = new RsaKeyParameters(false, rsa.Modulus, rsa.PublicExponent);
+                        privSpec = new RsaPrivateCrtKeyParameters(
+                            rsa.Modulus, rsa.PublicExponent, rsa.PrivateExponent,
+                            rsa.Prime1, rsa.Prime2, rsa.Exponent1, rsa.Exponent2,
+                            rsa.Coefficient);
+
+                        break;
+                    }
+
+                    case "DSA":
+                    {
+                        if (seq.Count != 6)
+                            throw new PemException("malformed sequence in DSA private key");
+
+                        // TODO Create an ASN1 object somewhere for this?
+                        //DerInteger v = (DerInteger)seq[0];
+                        DerInteger p = (DerInteger)seq[1];
+                        DerInteger q = (DerInteger)seq[2];
+                        DerInteger g = (DerInteger)seq[3];
+                        DerInteger y = (DerInteger)seq[4];
+                        DerInteger x = (DerInteger)seq[5];
+
+                        DsaParameters parameters = new DsaParameters(p.Value, q.Value, g.Value);
+
+                        privSpec = new DsaPrivateKeyParameters(x.Value, parameters);
+                        pubSpec = new DsaPublicKeyParameters(y.Value, parameters);
+
+                        break;
+                    }
+
+                    case "EC":
+                    {
+                        ECPrivateKeyStructure pKey = new ECPrivateKeyStructure(seq);
+                        AlgorithmIdentifier algId = new AlgorithmIdentifier(
+                            X9ObjectIdentifiers.IdECPublicKey, pKey.GetParameters());
+
+                        PrivateKeyInfo privInfo = new PrivateKeyInfo(algId, pKey.ToAsn1Object());
+
+                        // TODO Are the keys returned here ECDSA, as Java version forces?
+                        privSpec = PrivateKeyFactory.CreateKey(privInfo);
+
+                        DerBitString pubKey = pKey.GetPublicKey();
+                        if (pubKey != null)
+                        {
+                            SubjectPublicKeyInfo pubInfo = new SubjectPublicKeyInfo(algId, pubKey.GetBytes());
+
+                            // TODO Are the keys returned here ECDSA, as Java version forces?
+                            pubSpec = PublicKeyFactory.CreateKey(pubInfo);
+                        }
+                        else
+                        {
+                            pubSpec = ECKeyPairGenerator.GetCorrespondingPublicKey(
+                                (ECPrivateKeyParameters)privSpec);
+                        }
+
+                        break;
+                    }
+
+                    case "ENCRYPTED":
+                    {
+                        char[] password = pFinder.GetPassword();
+
+                        if (password == null)
+                            throw new PasswordException("Password is null, but a password is required");
+
+                        return PrivateKeyFactory.DecryptKey(password, EncryptedPrivateKeyInfo.GetInstance(seq));
+                    }
+
+                    case "":
+                    {
+                        return PrivateKeyFactory.CreateKey(PrivateKeyInfo.GetInstance(seq));
+                    }
+
+                    default:
+                        throw new ArgumentException("Unknown key type: " + type, "type");
+                }
+
+                return new AsymmetricCipherKeyPair(pubSpec, privSpec);
+            }
+            catch (IOException e)
+            {
+                throw e;
+            }
+            catch (Exception e)
+            {
+                throw new PemException(
+                    "problem creating " + type + " private key: " + e.ToString());
+            }
+        }
+
+        // TODO Add an equivalent class for ECNamedCurveParameterSpec?
+        //private ECNamedCurveParameterSpec ReadECParameters(
+//		private X9ECParameters ReadECParameters(PemObject pemObject)
+//		{
+//			DerObjectIdentifier oid = (DerObjectIdentifier)Asn1Object.FromByteArray(pemObject.Content);
+//
+//			//return ECNamedCurveTable.getParameterSpec(oid.Id);
+//			return GetCurveParameters(oid.Id);
+//		}
+
+        //private static ECDomainParameters GetCurveParameters(
+        private static X9ECParameters GetCurveParameters(
+            string name)
+        {
+            // TODO ECGost3410NamedCurves support (returns ECDomainParameters though)
+
+            X9ECParameters ecP = CustomNamedCurves.GetByName(name);
+            if (ecP == null)
+            {
+                ecP = ECNamedCurveTable.GetByName(name);
+            }
+
+            if (ecP == null)
+                throw new Exception("unknown curve name: " + name);
+
+            //return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
+            return ecP;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/PEMUtilities.cs b/BouncyCastle.AxCrypt/src/openssl/PEMUtilities.cs
new file mode 100644
index 0000000..b58e5e7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/PEMUtilities.cs
@@ -0,0 +1,158 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+	internal sealed class PemUtilities
+	{
+		private enum PemBaseAlg { AES_128, AES_192, AES_256, BF, DES, DES_EDE, DES_EDE3, RC2, RC2_40, RC2_64 };
+		private enum PemMode { CBC, CFB, ECB, OFB };
+
+		static PemUtilities()
+		{
+			// Signal to obfuscation tools not to change enum constants
+			((PemBaseAlg)Enums.GetArbitraryValue(typeof(PemBaseAlg))).ToString();
+			((PemMode)Enums.GetArbitraryValue(typeof(PemMode))).ToString();
+		}
+
+		private static void ParseDekAlgName(
+			string			dekAlgName,
+			out PemBaseAlg	baseAlg,
+			out PemMode		mode)
+		{
+			try
+			{
+				mode = PemMode.ECB;
+
+				if (dekAlgName == "DES-EDE" || dekAlgName == "DES-EDE3")
+				{
+					baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName);
+					return;
+				}
+
+				int pos = dekAlgName.LastIndexOf('-');
+				if (pos >= 0)
+				{
+					baseAlg = (PemBaseAlg)Enums.GetEnumValue(typeof(PemBaseAlg), dekAlgName.Substring(0, pos));
+					mode = (PemMode)Enums.GetEnumValue(typeof(PemMode), dekAlgName.Substring(pos + 1));
+					return;
+				}
+			}
+			catch (ArgumentException)
+			{
+			}
+
+			throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
+		}
+
+		internal static byte[] Crypt(
+			bool	encrypt,
+			byte[]	bytes,
+			char[]	password,
+			string	dekAlgName,
+			byte[]	iv)
+		{
+			PemBaseAlg baseAlg;
+			PemMode mode;
+			ParseDekAlgName(dekAlgName, out baseAlg, out mode);
+
+			string padding;
+			switch (mode)
+			{
+				case PemMode.CBC:
+				case PemMode.ECB:
+					padding = "PKCS5Padding";
+					break;
+				case PemMode.CFB:
+				case PemMode.OFB:
+					padding = "NoPadding";
+					break;
+				default:
+					throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
+			}
+
+			string algorithm;
+
+			byte[] salt = iv;
+			switch (baseAlg)
+			{
+				case PemBaseAlg.AES_128:
+				case PemBaseAlg.AES_192:
+				case PemBaseAlg.AES_256:
+					algorithm = "AES";
+					if (salt.Length > 8)
+					{
+						salt = new byte[8];
+						Array.Copy(iv, 0, salt, 0, salt.Length);
+					}
+					break;
+				case PemBaseAlg.BF:
+					algorithm = "BLOWFISH";
+					break;
+				case PemBaseAlg.DES:
+					algorithm = "DES";
+					break;
+				case PemBaseAlg.DES_EDE:
+				case PemBaseAlg.DES_EDE3:
+					algorithm = "DESede";
+					break;
+				case PemBaseAlg.RC2:
+				case PemBaseAlg.RC2_40:
+				case PemBaseAlg.RC2_64:
+					algorithm = "RC2";
+					break;
+				default:
+					throw new EncryptionException("Unknown DEK algorithm: " + dekAlgName);
+			}
+
+			string cipherName = algorithm + "/" + mode + "/" + padding;
+			IBufferedCipher cipher = CipherUtilities.GetCipher(cipherName);
+
+			ICipherParameters cParams = GetCipherParameters(password, baseAlg, salt);
+
+			if (mode != PemMode.ECB)
+			{
+				cParams = new ParametersWithIV(cParams, iv);
+			}
+
+			cipher.Init(encrypt, cParams);
+
+			return cipher.DoFinal(bytes);
+		}
+
+		private static ICipherParameters GetCipherParameters(
+			char[]		password,
+			PemBaseAlg	baseAlg,
+			byte[]		salt)
+		{
+			string algorithm;
+			int keyBits;
+			switch (baseAlg)
+			{
+				case PemBaseAlg.AES_128:		keyBits = 128;	algorithm = "AES128";	break;
+				case PemBaseAlg.AES_192:		keyBits = 192;	algorithm = "AES192";	break;
+				case PemBaseAlg.AES_256:		keyBits = 256;	algorithm = "AES256";	break;
+				case PemBaseAlg.BF:				keyBits = 128;	algorithm = "BLOWFISH";	break;
+				case PemBaseAlg.DES:			keyBits = 64;	algorithm = "DES";		break;
+				case PemBaseAlg.DES_EDE:		keyBits = 128;	algorithm = "DESEDE";	break;
+				case PemBaseAlg.DES_EDE3:		keyBits = 192;	algorithm = "DESEDE3";	break;
+				case PemBaseAlg.RC2:			keyBits = 128;	algorithm = "RC2";		break;
+				case PemBaseAlg.RC2_40:			keyBits = 40;	algorithm = "RC2";		break;
+				case PemBaseAlg.RC2_64:			keyBits = 64;	algorithm = "RC2";		break;
+				default:
+					return null;
+			}
+
+			OpenSslPbeParametersGenerator pGen = new OpenSslPbeParametersGenerator();
+
+			pGen.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt);
+
+			return pGen.GenerateDerivedParameters(algorithm, keyBits);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/PEMWriter.cs b/BouncyCastle.AxCrypt/src/openssl/PEMWriter.cs
new file mode 100644
index 0000000..aefb018
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/PEMWriter.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO.Pem;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+	/// <remarks>General purpose writer for OpenSSL PEM objects.</remarks>
+	public class PemWriter
+		: Org.BouncyCastle.Utilities.IO.Pem.PemWriter
+	{
+		/// <param name="writer">The TextWriter object to write the output to.</param>
+		public PemWriter(
+			TextWriter writer)
+			: base(writer)
+		{
+		}
+
+		public void WriteObject(
+			object obj) 
+		{
+			try
+			{
+				base.WriteObject(new MiscPemGenerator(obj));
+			}
+			catch (PemGenerationException e)
+			{
+				if (e.InnerException is IOException)
+					throw (IOException)e.InnerException;
+
+				throw e;
+			}
+		}
+
+		public void WriteObject(
+			object			obj,
+			string			algorithm,
+			char[]			password,
+			SecureRandom	random)
+		{
+			base.WriteObject(new MiscPemGenerator(obj, algorithm, password, random));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/PasswordException.cs b/BouncyCastle.AxCrypt/src/openssl/PasswordException.cs
new file mode 100644
index 0000000..fba958a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/PasswordException.cs
@@ -0,0 +1,25 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PasswordException
+		: IOException
+	{
+		public PasswordException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public PasswordException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/openssl/Pkcs8Generator.cs b/BouncyCastle.AxCrypt/src/openssl/Pkcs8Generator.cs
new file mode 100644
index 0000000..d03ea08
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/openssl/Pkcs8Generator.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO.Pem;
+
+namespace Org.BouncyCastle.OpenSsl
+{
+	public class Pkcs8Generator
+		: PemObjectGenerator
+	{
+		// FIXME See PbeUtilities static constructor
+//		public static readonly string Aes128Cbc = NistObjectIdentifiers.IdAes128Cbc.Id;
+//		public static readonly string Aes192Cbc = NistObjectIdentifiers.IdAes192Cbc.Id;
+//		public static readonly string Aes256Cbc = NistObjectIdentifiers.IdAes256Cbc.Id;
+//
+//		public static readonly string Des3Cbc = PkcsObjectIdentifiers.DesEde3Cbc.Id;
+
+		public static readonly string PbeSha1_RC4_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id;
+		public static readonly string PbeSha1_RC4_40 = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id;
+		public static readonly string PbeSha1_3DES = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id;
+		public static readonly string PbeSha1_2DES = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id;
+		public static readonly string PbeSha1_RC2_128 = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id;
+		public static readonly string PbeSha1_RC2_40 = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id;
+
+		private char[]					password;
+		private string					algorithm;
+		private int						iterationCount;
+		private AsymmetricKeyParameter	privKey;
+		private SecureRandom			random;
+
+		/**
+		* Constructor for an unencrypted private key PEM object.
+		*
+		* @param key private key to be encoded.
+		*/
+		public Pkcs8Generator(AsymmetricKeyParameter privKey)
+		{
+			this.privKey = privKey;
+		}
+
+		/**
+		* Constructor for an encrypted private key PEM object.
+		*
+		* @param key       private key to be encoded
+		* @param algorithm encryption algorithm to use
+		* @param provider  provider to use
+		* @throws NoSuchAlgorithmException if algorithm/mode cannot be found
+		*/
+		public Pkcs8Generator(AsymmetricKeyParameter privKey, string algorithm)
+		{
+			// TODO Check privKey.IsPrivate
+			this.privKey = privKey;
+			this.algorithm = algorithm;
+			this.iterationCount = 2048;
+		}
+
+		public SecureRandom SecureRandom
+		{
+			set { this.random = value; }
+		}
+
+		public char[] Password
+		{
+			set { this.password = value; }
+		}
+
+		public int IterationCount
+		{
+			set { this.iterationCount = value; }
+		}
+
+		public PemObject Generate()
+		{
+			if (algorithm == null)
+			{
+				PrivateKeyInfo pki = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privKey);
+
+				return new PemObject("PRIVATE KEY", pki.GetEncoded());
+			}
+
+			// TODO Theoretically, the amount of salt needed depends on the algorithm
+			byte[] salt = new byte[20];
+			if (random == null)
+			{
+				random = new SecureRandom();
+			}
+			random.NextBytes(salt);
+
+			try
+			{
+				EncryptedPrivateKeyInfo epki = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+					algorithm, password, salt, iterationCount, privKey);
+	
+				return new PemObject("ENCRYPTED PRIVATE KEY", epki.GetEncoded());
+			}
+			catch (Exception e)
+			{
+				throw new PemGenerationException("Couldn't encrypt private key", e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/AsymmetricKeyEntry.cs b/BouncyCastle.AxCrypt/src/pkcs/AsymmetricKeyEntry.cs
new file mode 100644
index 0000000..1c37631
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/AsymmetricKeyEntry.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public class AsymmetricKeyEntry
+        : Pkcs12Entry
+    {
+        private readonly AsymmetricKeyParameter key;
+
+		public AsymmetricKeyEntry(
+            AsymmetricKeyParameter key)
+			: base(Platform.CreateHashtable())
+        {
+            this.key = key;
+        }
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public AsymmetricKeyEntry(
+            AsymmetricKeyParameter key,
+            Hashtable attributes)
+			: base(attributes)
+        {
+            this.key = key;
+        }
+#endif
+
+        public AsymmetricKeyEntry(
+            AsymmetricKeyParameter  key,
+            IDictionary             attributes)
+			: base(attributes)
+        {
+            this.key = key;
+        }
+
+		public AsymmetricKeyParameter Key
+        {
+            get { return this.key; }
+        }
+
+		public override bool Equals(object obj)
+		{
+			AsymmetricKeyEntry other = obj as AsymmetricKeyEntry;
+
+			if (other == null)
+				return false;
+
+			return key.Equals(other.key);
+		}
+
+		public override int GetHashCode()
+		{
+			return ~key.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/EncryptedPrivateKeyInfoFactory.cs b/BouncyCastle.AxCrypt/src/pkcs/EncryptedPrivateKeyInfoFactory.cs
new file mode 100644
index 0000000..b6b7bac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/EncryptedPrivateKeyInfoFactory.cs
@@ -0,0 +1,64 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public sealed class EncryptedPrivateKeyInfoFactory
+    {
+        private EncryptedPrivateKeyInfoFactory()
+        {
+        }
+
+        public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+            DerObjectIdentifier		algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+            return CreateEncryptedPrivateKeyInfo(
+                algorithm.Id, passPhrase, salt, iterationCount,
+                PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
+        }
+
+        public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+            string					algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+            return CreateEncryptedPrivateKeyInfo(
+                algorithm, passPhrase, salt, iterationCount,
+                PrivateKeyInfoFactory.CreatePrivateKeyInfo(key));
+        }
+
+        public static EncryptedPrivateKeyInfo CreateEncryptedPrivateKeyInfo(
+            string			algorithm,
+            char[]			passPhrase,
+            byte[]			salt,
+            int				iterationCount,
+            PrivateKeyInfo	keyInfo)
+        {
+            IBufferedCipher cipher = PbeUtilities.CreateEngine(algorithm) as IBufferedCipher;
+            if (cipher == null)
+                throw new Exception("Unknown encryption algorithm: " + algorithm);
+
+            Asn1Encodable pbeParameters = PbeUtilities.GenerateAlgorithmParameters(
+                algorithm, salt, iterationCount);
+            ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters(
+                algorithm, passPhrase, pbeParameters);
+            cipher.Init(true, cipherParameters);
+            byte[] encoding = cipher.DoFinal(keyInfo.GetEncoded());
+
+            DerObjectIdentifier oid = PbeUtilities.GetObjectIdentifier(algorithm);
+            AlgorithmIdentifier algID = new AlgorithmIdentifier(oid, pbeParameters);
+            return new EncryptedPrivateKeyInfo(algID, encoding);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/PKCS12StoreBuilder.cs b/BouncyCastle.AxCrypt/src/pkcs/PKCS12StoreBuilder.cs
new file mode 100644
index 0000000..c8fa0f6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/PKCS12StoreBuilder.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Org.BouncyCastle.Pkcs
+{
+	public class Pkcs12StoreBuilder
+	{
+		private DerObjectIdentifier	keyAlgorithm = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc;
+		private DerObjectIdentifier	certAlgorithm = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc;
+		private bool useDerEncoding = false;
+
+		public Pkcs12StoreBuilder()
+		{
+		}
+
+		public Pkcs12Store Build()
+		{
+			return new Pkcs12Store(keyAlgorithm, certAlgorithm, useDerEncoding);
+		}
+
+		public Pkcs12StoreBuilder SetCertAlgorithm(DerObjectIdentifier certAlgorithm)
+		{
+			this.certAlgorithm = certAlgorithm;
+			return this;
+		}
+
+		public Pkcs12StoreBuilder SetKeyAlgorithm(DerObjectIdentifier keyAlgorithm)
+		{
+			this.keyAlgorithm = keyAlgorithm;
+			return this;
+		}
+
+		public Pkcs12StoreBuilder SetUseDerEncoding(bool useDerEncoding)
+		{
+			this.useDerEncoding = useDerEncoding;
+			return this;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequest.cs b/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequest.cs
new file mode 100644
index 0000000..9f24eb1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequest.cs
@@ -0,0 +1,465 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkcs
+{
+	/// <remarks>
+	/// A class for verifying and creating Pkcs10 Certification requests.
+	/// </remarks>
+	/// <code>
+	/// CertificationRequest ::= Sequence {
+	///   certificationRequestInfo  CertificationRequestInfo,
+	///   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+	///   signature                 BIT STRING
+	/// }
+	///
+	/// CertificationRequestInfo ::= Sequence {
+	///   version             Integer { v1(0) } (v1,...),
+	///   subject             Name,
+	///   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+	///   attributes          [0] Attributes{{ CRIAttributes }}
+	///  }
+	///
+	///  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+	///
+	///  Attr { ATTRIBUTE:IOSet } ::= Sequence {
+	///    type    ATTRIBUTE.&id({IOSet}),
+	///    values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+	///  }
+	/// </code>
+	/// see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+	public class Pkcs10CertificationRequest
+		: CertificationRequest
+	{
+		protected static readonly IDictionary algorithms = Platform.CreateHashtable();
+        protected static readonly IDictionary exParams = Platform.CreateHashtable();
+        protected static readonly IDictionary keyAlgorithms = Platform.CreateHashtable();
+        protected static readonly IDictionary oids = Platform.CreateHashtable();
+		protected static readonly ISet noParams = new HashSet();
+
+		static Pkcs10CertificationRequest()
+		{
+			algorithms.Add("MD2WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.2"));
+			algorithms.Add("MD2WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.2"));
+			algorithms.Add("MD5WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.4"));
+			algorithms.Add("MD5WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.4"));
+			algorithms.Add("RSAWITHMD5", new DerObjectIdentifier("1.2.840.113549.1.1.4"));
+			algorithms.Add("SHA1WITHRSAENCRYPTION", new DerObjectIdentifier("1.2.840.113549.1.1.5"));
+			algorithms.Add("SHA1WITHRSA", new DerObjectIdentifier("1.2.840.113549.1.1.5"));
+			algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("RSAWITHSHA1", new DerObjectIdentifier("1.2.840.113549.1.1.5"));
+			algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("SHA1WITHDSA", new DerObjectIdentifier("1.2.840.10040.4.3"));
+			algorithms.Add("DSAWITHSHA1", new DerObjectIdentifier("1.2.840.10040.4.3"));
+			algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+			algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+			algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
+			algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
+			algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+			algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+			algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+			algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+			algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3410WITHGOST3411", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+			algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+			algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+			//
+			// reverse mappings
+			//
+			oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.5"), "SHA1WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption, "SHA224WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption, "SHA256WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption, "SHA384WITHRSA");
+			oids.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption, "SHA512WITHRSA");
+			oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94, "GOST3411WITHGOST3410");
+			oids.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001, "GOST3411WITHECGOST3410");
+
+			oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.4"), "MD5WITHRSA");
+			oids.Add(new DerObjectIdentifier("1.2.840.113549.1.1.2"), "MD2WITHRSA");
+			oids.Add(new DerObjectIdentifier("1.2.840.10040.4.3"), "SHA1WITHDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha1, "SHA1WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha224, "SHA224WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha256, "SHA256WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha384, "SHA384WITHECDSA");
+			oids.Add(X9ObjectIdentifiers.ECDsaWithSha512, "SHA512WITHECDSA");
+			oids.Add(OiwObjectIdentifiers.Sha1WithRsa, "SHA1WITHRSA");
+			oids.Add(OiwObjectIdentifiers.DsaWithSha1, "SHA1WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha224, "SHA224WITHDSA");
+			oids.Add(NistObjectIdentifiers.DsaWithSha256, "SHA256WITHDSA");
+
+			//
+			// key types
+			//
+			keyAlgorithms.Add(PkcsObjectIdentifiers.RsaEncryption, "RSA");
+			keyAlgorithms.Add(X9ObjectIdentifiers.IdDsa, "DSA");
+
+			//
+			// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+			// The parameters field SHALL be NULL for RSA based signature algorithms.
+			//
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+			noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha224);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+
+			//
+			// RFC 4491
+			//
+			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+			//
+			// explicit params
+			//
+			AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+			exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
+
+			AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
+			exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
+
+			AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
+			exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
+
+			AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
+			exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
+
+			AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
+			exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
+		}
+
+		private static RsassaPssParameters CreatePssParams(
+			AlgorithmIdentifier	hashAlgId,
+			int					saltSize)
+		{
+			return new RsassaPssParameters(
+				hashAlgId,
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
+				new DerInteger(saltSize),
+				new DerInteger(1));
+		}
+
+		protected Pkcs10CertificationRequest()
+		{
+		}
+
+		public Pkcs10CertificationRequest(
+			byte[] encoded)
+			: base((Asn1Sequence) Asn1Object.FromByteArray(encoded))
+		{
+		}
+
+		public Pkcs10CertificationRequest(
+			Asn1Sequence seq)
+			: base(seq)
+		{
+		}
+
+		public Pkcs10CertificationRequest(
+			Stream input)
+			: base((Asn1Sequence) Asn1Object.FromStream(input))
+		{
+		}
+
+		/// <summary>
+		/// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+		/// </summary>
+		///<param name="signatureAlgorithm">Name of Sig Alg.</param>
+		/// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+		/// <param name="publicKey">Public Key to be included in cert reqest.</param>
+		/// <param name="attributes">ASN1Set of Attributes.</param>
+		/// <param name="signingKey">Matching Private key for nominated (above) public key to be used to sign the request.</param>
+		public Pkcs10CertificationRequest(
+			string					signatureAlgorithm,
+			X509Name				subject,
+			AsymmetricKeyParameter	publicKey,
+			Asn1Set					attributes,
+			AsymmetricKeyParameter	signingKey)
+		{
+			if (signatureAlgorithm == null)
+				throw new ArgumentNullException("signatureAlgorithm");
+			if (subject == null)
+				throw new ArgumentNullException("subject");
+			if (publicKey == null)
+				throw new ArgumentNullException("publicKey");
+			if (publicKey.IsPrivate)
+				throw new ArgumentException("expected public key", "publicKey");
+			if (!signingKey.IsPrivate)
+				throw new ArgumentException("key for signing must be private", "signingKey");
+
+//			DerObjectIdentifier sigOid = SignerUtilities.GetObjectIdentifier(signatureAlgorithm);
+			string algorithmName = Platform.ToUpperInvariant(signatureAlgorithm);
+			DerObjectIdentifier sigOid = (DerObjectIdentifier) algorithms[algorithmName];
+
+			if (sigOid == null)
+			{
+				try
+				{
+					sigOid = new DerObjectIdentifier(algorithmName);
+				}
+				catch (Exception e)
+				{
+					throw new ArgumentException("Unknown signature type requested", e);
+				}
+			}
+
+			if (noParams.Contains(sigOid))
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid);
+			}
+			else if (exParams.Contains(algorithmName))
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
+			}
+			else
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance);
+			}
+
+			SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+
+			this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
+
+			ISigner sig = SignerUtilities.GetSigner(signatureAlgorithm);
+
+			sig.Init(true, signingKey);
+
+			try
+			{
+				// Encode.
+				byte[] b = reqInfo.GetDerEncoded();
+				sig.BlockUpdate(b, 0, b.Length);
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("exception encoding TBS cert request", e);
+			}
+
+			// Generate Signature.
+			sigBits = new DerBitString(sig.GenerateSignature());
+		}
+
+//        internal Pkcs10CertificationRequest(
+//        	Asn1InputStream seqStream)
+//        {
+//			Asn1Sequence seq = (Asn1Sequence) seqStream.ReadObject();
+//            try
+//            {
+//                this.reqInfo = CertificationRequestInfo.GetInstance(seq[0]);
+//                this.sigAlgId = AlgorithmIdentifier.GetInstance(seq[1]);
+//                this.sigBits = (DerBitString) seq[2];
+//            }
+//            catch (Exception ex)
+//            {
+//                throw new ArgumentException("Create From Asn1Sequence: " + ex.Message);
+//            }
+//        }
+
+		/// <summary>
+		/// Get the public key.
+		/// </summary>
+		/// <returns>The public key.</returns>
+		public AsymmetricKeyParameter GetPublicKey()
+		{
+			return PublicKeyFactory.CreateKey(reqInfo.SubjectPublicKeyInfo);
+		}
+
+		/// <summary>
+		/// Verify Pkcs10 Cert Request is valid.
+		/// </summary>
+		/// <returns>true = valid.</returns>
+		public bool Verify()
+		{
+			return Verify(this.GetPublicKey());
+		}
+
+		public bool Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			ISigner sig;
+
+			try
+			{
+				sig = SignerUtilities.GetSigner(GetSignatureName(sigAlgId));
+			}
+			catch (Exception e)
+			{
+				// try an alternate
+				string alt = (string) oids[sigAlgId.ObjectID];
+
+				if (alt != null)
+				{
+					sig = SignerUtilities.GetSigner(alt);
+				}
+				else
+				{
+					throw e;
+				}
+			}
+
+			SetSignatureParameters(sig, sigAlgId.Parameters);
+
+			sig.Init(false, publicKey);
+
+			try
+			{
+				byte[] b = reqInfo.GetDerEncoded();
+				sig.BlockUpdate(b, 0, b.Length);
+			}
+			catch (Exception e)
+			{
+				throw new SignatureException("exception encoding TBS cert request", e);
+			}
+
+			return sig.VerifySignature(sigBits.GetBytes());
+		}
+
+//        /// <summary>
+//        /// Get the Der Encoded Pkcs10 Certification Request.
+//        /// </summary>
+//        /// <returns>A byte array.</returns>
+//        public byte[] GetEncoded()
+//        {
+//        	return new CertificationRequest(reqInfo, sigAlgId, sigBits).GetDerEncoded();
+//        }
+
+		// TODO Figure out how to set parameters on an ISigner
+		private void SetSignatureParameters(
+			ISigner			signature,
+			Asn1Encodable	asn1Params)
+		{
+			if (asn1Params != null && !(asn1Params is Asn1Null))
+			{
+//				AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm());
+//
+//				try
+//				{
+//					sigParams.init(asn1Params.ToAsn1Object().GetDerEncoded());
+//				}
+//				catch (IOException e)
+//				{
+//					throw new SignatureException("IOException decoding parameters: " + e.Message);
+//				}
+
+				if (signature.AlgorithmName.EndsWith("MGF1"))
+				{
+					throw Platform.CreateNotImplementedException("signature algorithm with MGF1");
+
+//					try
+//					{
+//						signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
+//					}
+//					catch (GeneralSecurityException e)
+//					{
+//						throw new SignatureException("Exception extracting parameters: " + e.getMessage());
+//					}
+				}
+			}
+		}
+
+		internal static string GetSignatureName(
+			AlgorithmIdentifier sigAlgId)
+		{
+			Asn1Encodable asn1Params = sigAlgId.Parameters;
+
+			if (asn1Params != null && !(asn1Params is Asn1Null))
+			{
+				if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+				{
+					RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(asn1Params);
+					return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+				}
+			}
+
+			return sigAlgId.ObjectID.Id;
+		}
+
+		private static string GetDigestAlgName(
+			DerObjectIdentifier digestAlgOID)
+		{
+			if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
+			{
+				return "MD5";
+			}
+			else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
+			{
+				return "SHA1";
+			}
+			else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
+			{
+				return "SHA224";
+			}
+			else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
+			{
+				return "SHA256";
+			}
+			else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
+			{
+				return "SHA384";
+			}
+			else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
+			{
+				return "SHA512";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
+			{
+				return "RIPEMD128";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
+			{
+				return "RIPEMD160";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
+			{
+				return "RIPEMD256";
+			}
+			else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
+			{
+				return "GOST3411";
+			}
+			else
+			{
+				return digestAlgOID.Id;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs b/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs
new file mode 100644
index 0000000..ecbb4ab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/Pkcs10CertificationRequestDelaySigned.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkcs
+{
+	/// <remarks>
+	/// A class for creating and verifying Pkcs10 Certification requests (this is an extension on <see cref="Pkcs10CertificationRequest"/>).
+	/// The requests are made using delay signing. This is useful for situations where
+	/// the private key is in another environment and not directly accessible (e.g. HSM)
+	/// So the first step creates the request, then the signing is done outside this
+	/// object and the signature is then used to complete the request.
+	/// </remarks>
+	/// <code>
+	/// CertificationRequest ::= Sequence {
+	///   certificationRequestInfo  CertificationRequestInfo,
+	///   signatureAlgorithm        AlgorithmIdentifier{{ SignatureAlgorithms }},
+	///   signature                 BIT STRING
+	/// }
+	///
+	/// CertificationRequestInfo ::= Sequence {
+	///   version             Integer { v1(0) } (v1,...),
+	///   subject             Name,
+	///   subjectPKInfo   SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
+	///   attributes          [0] Attributes{{ CRIAttributes }}
+	///  }
+	///
+	///  Attributes { ATTRIBUTE:IOSet } ::= Set OF Attr{{ IOSet }}
+	///
+	///  Attr { ATTRIBUTE:IOSet } ::= Sequence {
+	///    type    ATTRIBUTE.&id({IOSet}),
+	///    values  Set SIZE(1..MAX) OF ATTRIBUTE.&Type({IOSet}{\@type})
+	///  }
+	/// </code>
+	/// see <a href="http://www.rsasecurity.com/rsalabs/node.asp?id=2132"/>
+	public class Pkcs10CertificationRequestDelaySigned : Pkcs10CertificationRequest
+	{
+		protected Pkcs10CertificationRequestDelaySigned()
+			: base()
+		{
+		}
+		public Pkcs10CertificationRequestDelaySigned(
+			byte[] encoded)
+			: base(encoded)
+		{
+		}
+		public Pkcs10CertificationRequestDelaySigned(
+			Asn1Sequence seq)
+			: base(seq)
+		{
+		}
+		public Pkcs10CertificationRequestDelaySigned(
+			Stream input)
+			: base(input)
+		{
+		}
+		public Pkcs10CertificationRequestDelaySigned(
+			string					signatureAlgorithm,
+			X509Name				subject,
+			AsymmetricKeyParameter	publicKey,
+			Asn1Set					attributes,
+			AsymmetricKeyParameter	signingKey)
+			: base(signatureAlgorithm, subject, publicKey, attributes, signingKey)
+		{
+		}
+		/// <summary>
+		/// Instantiate a Pkcs10CertificationRequest object with the necessary credentials.
+		/// </summary>
+		/// <param name="signatureAlgorithm">Name of Sig Alg.</param>
+		/// <param name="subject">X509Name of subject eg OU="My unit." O="My Organisatioin" C="au" </param>
+		/// <param name="publicKey">Public Key to be included in cert reqest.</param>
+		/// <param name="attributes">ASN1Set of Attributes.</param>
+		/// <remarks>
+        /// After the object is constructed use the <see cref="GetDataToSign"/> and finally the
+        /// SignRequest methods to finalize the request.
+		/// </remarks>
+		public Pkcs10CertificationRequestDelaySigned(
+			string					signatureAlgorithm,
+			X509Name				subject,
+			AsymmetricKeyParameter	publicKey,
+			Asn1Set					attributes)
+		{
+			if (signatureAlgorithm == null)
+				throw new ArgumentNullException("signatureAlgorithm");
+			if (subject == null)
+				throw new ArgumentNullException("subject");
+			if (publicKey == null)
+				throw new ArgumentNullException("publicKey");
+			if (publicKey.IsPrivate)
+				throw new ArgumentException("expected public key", "publicKey");
+//			DerObjectIdentifier sigOid = SignerUtilities.GetObjectIdentifier(signatureAlgorithm);
+			string algorithmName = Platform.ToUpperInvariant(signatureAlgorithm);
+			DerObjectIdentifier sigOid = (DerObjectIdentifier) algorithms[algorithmName];
+			if (sigOid == null)
+			{
+				try
+				{
+					sigOid = new DerObjectIdentifier(algorithmName);
+				}
+				catch (Exception e)
+				{
+					throw new ArgumentException("Unknown signature type requested", e);
+				}
+			}
+			if (noParams.Contains(sigOid))
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid);
+			}
+			else if (exParams.Contains(algorithmName))
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
+			}
+			else
+			{
+				this.sigAlgId = new AlgorithmIdentifier(sigOid, DerNull.Instance);
+			}
+			SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey);
+			this.reqInfo = new CertificationRequestInfo(subject, pubInfo, attributes);
+		}
+		public byte[] GetDataToSign()
+		{
+			return reqInfo.GetDerEncoded();
+		}
+		public void SignRequest(byte[] signedData)
+		{
+			//build the signature from the signed data
+			sigBits = new DerBitString(signedData);
+		}
+		public void SignRequest(DerBitString signedData)
+		{
+			//build the signature from the signed data
+			sigBits = signedData;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Entry.cs b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Entry.cs
new file mode 100644
index 0000000..5dcc94e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Entry.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public abstract class Pkcs12Entry
+    {
+        private readonly IDictionary attributes;
+
+		protected internal Pkcs12Entry(
+            IDictionary attributes)
+        {
+            this.attributes = attributes;
+
+			foreach (DictionaryEntry entry in attributes)
+			{
+				if (!(entry.Key is string))
+					throw new ArgumentException("Attribute keys must be of type: " + typeof(string).FullName, "attributes");
+				if (!(entry.Value is Asn1Encodable))
+					throw new ArgumentException("Attribute values must be of type: " + typeof(Asn1Encodable).FullName, "attributes");
+			}
+        }
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public Asn1Encodable GetBagAttribute(
+            DerObjectIdentifier oid)
+        {
+            return (Asn1Encodable)this.attributes[oid.Id];
+        }
+
+		[Obsolete("Use 'object[index]' syntax instead")]
+		public Asn1Encodable GetBagAttribute(
+            string oid)
+        {
+            return (Asn1Encodable)this.attributes[oid];
+        }
+
+		[Obsolete("Use 'BagAttributeKeys' property")]
+        public IEnumerator GetBagAttributeKeys()
+        {
+            return this.attributes.Keys.GetEnumerator();
+        }
+
+		public Asn1Encodable this[
+			DerObjectIdentifier oid]
+		{
+			get { return (Asn1Encodable) this.attributes[oid.Id]; }
+		}
+
+		public Asn1Encodable this[
+			string oid]
+		{
+			get { return (Asn1Encodable) this.attributes[oid]; }
+		}
+
+		public IEnumerable BagAttributeKeys
+		{
+			get { return new EnumerableProxy(this.attributes.Keys); }
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Store.cs b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Store.cs
new file mode 100644
index 0000000..7e9976c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Store.cs
@@ -0,0 +1,1228 @@
+using System;
+using System.Collections;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public class Pkcs12Store
+    {
+        private readonly IgnoresCaseHashtable	keys = new IgnoresCaseHashtable();
+        private readonly IDictionary            localIds = Platform.CreateHashtable();
+        private readonly IgnoresCaseHashtable	certs = new IgnoresCaseHashtable();
+        private readonly IDictionary            chainCerts = Platform.CreateHashtable();
+        private readonly IDictionary            keyCerts = Platform.CreateHashtable();
+        private readonly DerObjectIdentifier	keyAlgorithm;
+        private readonly DerObjectIdentifier	certAlgorithm;
+        private readonly bool					useDerEncoding;
+
+        private const int MinIterations = 1024;
+        private const int SaltSize = 20;
+
+        private static SubjectKeyIdentifier CreateSubjectKeyID(
+            AsymmetricKeyParameter pubKey)
+        {
+            return new SubjectKeyIdentifier(
+                SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey));
+        }
+
+        internal class CertId
+        {
+            private readonly byte[] id;
+
+            internal CertId(
+                AsymmetricKeyParameter pubKey)
+            {
+                this.id = CreateSubjectKeyID(pubKey).GetKeyIdentifier();
+            }
+
+            internal CertId(
+                byte[] id)
+            {
+                this.id = id;
+            }
+
+            internal byte[] Id
+            {
+                get { return id; }
+            }
+
+            public override int GetHashCode()
+            {
+                return Arrays.GetHashCode(id);
+            }
+
+            public override bool Equals(
+                object obj)
+            {
+                if (obj == this)
+                    return true;
+
+                CertId other = obj as CertId;
+
+                if (other == null)
+                    return false;
+
+                return Arrays.AreEqual(id, other.id);
+            }
+        }
+
+        internal Pkcs12Store(
+            DerObjectIdentifier	keyAlgorithm,
+            DerObjectIdentifier	certAlgorithm,
+            bool				useDerEncoding)
+        {
+            this.keyAlgorithm = keyAlgorithm;
+            this.certAlgorithm = certAlgorithm;
+            this.useDerEncoding = useDerEncoding;
+        }
+
+        // TODO Consider making obsolete
+//		[Obsolete("Use 'Pkcs12StoreBuilder' instead")]
+        public Pkcs12Store()
+            : this(PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc,
+                PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc, false)
+        {
+        }
+
+        // TODO Consider making obsolete
+//		[Obsolete("Use 'Pkcs12StoreBuilder' and 'Load' method instead")]
+        public Pkcs12Store(
+            Stream	input,
+            char[]	password)
+            : this()
+        {
+            Load(input, password);
+        }
+
+        public void Load(
+            Stream	input,
+            char[]	password)
+        {
+            if (input == null)
+                throw new ArgumentNullException("input");
+            if (password == null)
+                throw new ArgumentNullException("password");
+
+            Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromStream(input);
+            Pfx bag = new Pfx(obj);
+            ContentInfo info = bag.AuthSafe;
+            bool unmarkedKey = false;
+            bool wrongPkcs12Zero = false;
+
+            if (bag.MacData != null) // check the mac code
+            {
+                MacData mData = bag.MacData;
+                DigestInfo dInfo = mData.Mac;
+                AlgorithmIdentifier algId = dInfo.AlgorithmID;
+                byte[] salt = mData.GetSalt();
+                int itCount = mData.IterationCount.IntValue;
+
+                byte[] data = ((Asn1OctetString) info.Content).GetOctets();
+
+                byte[] mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, false, data);
+                byte[] dig = dInfo.GetDigest();
+
+                if (!Arrays.ConstantTimeAreEqual(mac, dig))
+                {
+                    if (password.Length > 0)
+                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
+
+                    // Try with incorrect zero length password
+                    mac = CalculatePbeMac(algId.ObjectID, salt, itCount, password, true, data);
+
+                    if (!Arrays.ConstantTimeAreEqual(mac, dig))
+                        throw new IOException("PKCS12 key store MAC invalid - wrong password or corrupted file.");
+
+                    wrongPkcs12Zero = true;
+                }
+            }
+
+            keys.Clear();
+            localIds.Clear();
+
+            IList chain = Platform.CreateArrayList();
+
+            if (info.ContentType.Equals(PkcsObjectIdentifiers.Data))
+            {
+                byte[] octs = ((Asn1OctetString)info.Content).GetOctets();
+                AuthenticatedSafe authSafe = new AuthenticatedSafe(
+                    (Asn1Sequence) Asn1OctetString.FromByteArray(octs));
+                ContentInfo[] cis = authSafe.GetContentInfo();
+
+                foreach (ContentInfo ci in cis)
+                {
+                    DerObjectIdentifier oid = ci.ContentType;
+
+                    if (oid.Equals(PkcsObjectIdentifiers.Data))
+                    {
+                        byte[] octets = ((Asn1OctetString)ci.Content).GetOctets();
+                        Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets);
+
+                        foreach (Asn1Sequence subSeq in seq)
+                        {
+                            SafeBag b = new SafeBag(subSeq);
+
+                            if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
+                            {
+                                EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);
+                                PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
+                                    password, wrongPkcs12Zero, eIn);
+                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo);
+
+                                //
+                                // set the attributes on the key
+                                //
+                                IDictionary attributes = Platform.CreateHashtable();
+                                AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes);
+                                string alias = null;
+                                Asn1OctetString localId = null;
+
+                                if (b.BagAttributes != null)
+                                {
+                                    foreach (Asn1Sequence sq in b.BagAttributes)
+                                    {
+                                        DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0];
+                                        Asn1Set attrSet = (Asn1Set) sq[1];
+                                        Asn1Encodable attr = null;
+
+                                        if (attrSet.Count > 0)
+                                        {
+                                            // TODO We should be adding all attributes in the set
+                                            attr = attrSet[0];
+
+                                            // TODO We might want to "merge" attribute sets with
+                                            // the same OID - currently, differing values give an error
+                                            if (attributes.Contains(aOid.Id))
+                                            {
+                                                // OK, but the value has to be the same
+                                                if (!attributes[aOid.Id].Equals(attr))
+                                                {
+                                                    throw new IOException("attempt to add existing attribute with different value");
+                                                }
+                                            }
+                                            else
+                                            {
+                                                attributes.Add(aOid.Id, attr);
+                                            }
+
+                                            if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
+                                            {
+                                                alias = ((DerBmpString)attr).GetString();
+                                                // TODO Do these in a separate loop, just collect aliases here
+                                                keys[alias] = pkcs12Key;
+                                            }
+                                            else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
+                                            {
+                                                localId = (Asn1OctetString)attr;
+                                            }
+                                        }
+                                    }
+                                }
+
+                                if (localId != null)
+                                {
+                                    string name = Hex.ToHexString(localId.GetOctets());
+
+                                    if (alias == null)
+                                    {
+                                        keys[name] = pkcs12Key;
+                                    }
+                                    else
+                                    {
+                                        // TODO There may have been more than one alias
+                                        localIds[alias] = name;
+                                    }
+                                }
+                                else
+                                {
+                                    unmarkedKey = true;
+                                    keys["unmarked"] = pkcs12Key;
+                                }
+                            }
+                            else if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
+                            {
+                                chain.Add(b);
+                            }
+                            else
+                            {
+                                Debug.WriteLine("extra " + b.BagID);
+                                Debug.WriteLine("extra " + Asn1Dump.DumpAsString(b));
+                            }
+                        }
+                    }
+                    else if (oid.Equals(PkcsObjectIdentifiers.EncryptedData))
+                    {
+                        EncryptedData d = EncryptedData.GetInstance(ci.Content);
+                        byte[] octets = CryptPbeData(false, d.EncryptionAlgorithm,
+                            password, wrongPkcs12Zero, d.Content.GetOctets());
+                        Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets);
+
+                        foreach (Asn1Sequence subSeq in seq)
+                        {
+                            SafeBag b = new SafeBag(subSeq);
+
+                            if (b.BagID.Equals(PkcsObjectIdentifiers.CertBag))
+                            {
+                                chain.Add(b);
+                            }
+                            else if (b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
+                            {
+                                EncryptedPrivateKeyInfo eIn = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);
+                                PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(
+                                    password, wrongPkcs12Zero, eIn);
+                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privInfo);
+
+                                //
+                                // set the attributes on the key
+                                //
+                                IDictionary attributes = Platform.CreateHashtable();
+                                AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes);
+                                string alias = null;
+                                Asn1OctetString localId = null;
+
+                                foreach (Asn1Sequence sq in b.BagAttributes)
+                                {
+                                    DerObjectIdentifier aOid = (DerObjectIdentifier) sq[0];
+                                    Asn1Set attrSet = (Asn1Set) sq[1];
+                                    Asn1Encodable attr = null;
+
+                                    if (attrSet.Count > 0)
+                                    {
+                                        // TODO We should be adding all attributes in the set
+                                        attr = attrSet[0];
+
+                                        // TODO We might want to "merge" attribute sets with
+                                        // the same OID - currently, differing values give an error
+                                        if (attributes.Contains(aOid.Id))
+                                        {
+                                            // OK, but the value has to be the same
+                                            if (!attributes[aOid.Id].Equals(attr))
+                                            {
+                                                throw new IOException("attempt to add existing attribute with different value");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            attributes.Add(aOid.Id, attr);
+                                        }
+
+                                        if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
+                                        {
+                                            alias = ((DerBmpString)attr).GetString();
+                                            // TODO Do these in a separate loop, just collect aliases here
+                                            keys[alias] = pkcs12Key;
+                                        }
+                                        else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
+                                        {
+                                            localId = (Asn1OctetString)attr;
+                                        }
+                                    }
+                                }
+
+                                // TODO Should we be checking localIds != null here
+                                // as for PkcsObjectIdentifiers.Data version above?
+
+                                string name = Hex.ToHexString(localId.GetOctets());
+
+                                if (alias == null)
+                                {
+                                    keys[name] = pkcs12Key;
+                                }
+                                else
+                                {
+                                    // TODO There may have been more than one alias
+                                    localIds[alias] = name;
+                                }
+                            }
+                            else if (b.BagID.Equals(PkcsObjectIdentifiers.KeyBag))
+                            {
+                                PrivateKeyInfo privKeyInfo = PrivateKeyInfo.GetInstance(b.BagValue);
+                                AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyInfo);
+
+                                //
+                                // set the attributes on the key
+                                //
+                                string alias = null;
+                                Asn1OctetString localId = null;
+                                IDictionary attributes = Platform.CreateHashtable();
+                                AsymmetricKeyEntry pkcs12Key = new AsymmetricKeyEntry(privKey, attributes);
+
+                                foreach (Asn1Sequence sq in b.BagAttributes)
+                                {
+                                    DerObjectIdentifier aOid = DerObjectIdentifier.GetInstance(sq[0]);
+                                    Asn1Set attrSet = Asn1Set.GetInstance(sq[1]);
+                                    Asn1Encodable attr = null;
+
+                                    if (attrSet.Count > 0)
+                                    {
+                                        // TODO We should be adding all attributes in the set
+                                        attr = attrSet[0];
+
+                                        // TODO We might want to "merge" attribute sets with
+                                        // the same OID - currently, differing values give an error
+                                        if (attributes.Contains(aOid.Id))
+                                        {
+                                            // OK, but the value has to be the same
+                                            if (!attributes[aOid.Id].Equals(attr))
+                                            {
+                                                throw new IOException("attempt to add existing attribute with different value");
+                                            }
+                                        }
+                                        else
+                                        {
+                                            attributes.Add(aOid.Id, attr);
+                                        }
+
+                                        if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
+                                        {
+                                            alias = ((DerBmpString)attr).GetString();
+                                            // TODO Do these in a separate loop, just collect aliases here
+                                            keys[alias] = pkcs12Key;
+                                        }
+                                        else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
+                                        {
+                                            localId = (Asn1OctetString)attr;
+                                        }
+                                    }
+                                }
+
+                                // TODO Should we be checking localIds != null here
+                                // as for PkcsObjectIdentifiers.Data version above?
+
+                                string name = Hex.ToHexString(localId.GetOctets());
+
+                                if (alias == null)
+                                {
+                                    keys[name] = pkcs12Key;
+                                }
+                                else
+                                {
+                                    // TODO There may have been more than one alias
+                                    localIds[alias] = name;
+                                }
+                            }
+                            else
+                            {
+                                Debug.WriteLine("extra " + b.BagID);
+                                Debug.WriteLine("extra " + Asn1Dump.DumpAsString(b));
+                            }
+                        }
+                    }
+                    else
+                    {
+                        Debug.WriteLine("extra " + oid);
+                        Debug.WriteLine("extra " + Asn1Dump.DumpAsString(ci.Content));
+                    }
+                }
+            }
+
+            certs.Clear();
+            chainCerts.Clear();
+            keyCerts.Clear();
+
+            foreach (SafeBag b in chain)
+            {
+                CertBag cb = new CertBag((Asn1Sequence)b.BagValue);
+                byte[] octets = ((Asn1OctetString) cb.CertValue).GetOctets();
+                X509Certificate cert = new X509CertificateParser().ReadCertificate(octets);
+
+                //
+                // set the attributes
+                //
+                IDictionary attributes = Platform.CreateHashtable();
+                Asn1OctetString localId = null;
+                string alias = null;
+
+                if (b.BagAttributes != null)
+                {
+                    foreach (Asn1Sequence sq in b.BagAttributes)
+                    {
+                        DerObjectIdentifier aOid = DerObjectIdentifier.GetInstance(sq[0]);
+                        Asn1Set attrSet = Asn1Set.GetInstance(sq[1]);
+
+                        if (attrSet.Count > 0)
+                        {
+                            // TODO We should be adding all attributes in the set
+                            Asn1Encodable attr = attrSet[0];
+
+                            // TODO We might want to "merge" attribute sets with
+                            // the same OID - currently, differing values give an error
+                            if (attributes.Contains(aOid.Id))
+                            {
+                                // OK, but the value has to be the same
+                                if (!attributes[aOid.Id].Equals(attr))
+                                {
+                                    throw new IOException("attempt to add existing attribute with different value");
+                                }
+                            }
+                            else
+                            {
+                                attributes.Add(aOid.Id, attr);
+                            }
+
+                            if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName))
+                            {
+                                alias = ((DerBmpString)attr).GetString();
+                            }
+                            else if (aOid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID))
+                            {
+                                localId = (Asn1OctetString)attr;
+                            }
+                        }
+                    }
+                }
+
+                CertId certId = new CertId(cert.GetPublicKey());
+                X509CertificateEntry pkcs12Cert = new X509CertificateEntry(cert, attributes);
+
+                chainCerts[certId] = pkcs12Cert;
+
+                if (unmarkedKey)
+                {
+                    if (keyCerts.Count == 0)
+                    {
+                        string name = Hex.ToHexString(certId.Id);
+
+                        keyCerts[name] = pkcs12Cert;
+
+                        object temp = keys["unmarked"];
+                        keys.Remove("unmarked");
+                        keys[name] = temp;
+                    }
+                }
+                else
+                {
+                    if (localId != null)
+                    {
+                        string name = Hex.ToHexString(localId.GetOctets());
+
+                        keyCerts[name] = pkcs12Cert;
+                    }
+
+                    if (alias != null)
+                    {
+                        // TODO There may have been more than one alias
+                        certs[alias] = pkcs12Cert;
+                    }
+                }
+            }
+        }
+
+        public AsymmetricKeyEntry GetKey(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            return (AsymmetricKeyEntry)keys[alias];
+        }
+
+        public bool IsCertificateEntry(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            return (certs[alias] != null && keys[alias] == null);
+        }
+
+        public bool IsKeyEntry(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            return (keys[alias] != null);
+        }
+
+        private IDictionary GetAliasesTable()
+        {
+            IDictionary tab = Platform.CreateHashtable();
+
+            foreach (string key in certs.Keys)
+            {
+                tab[key] = "cert";
+            }
+
+            foreach (string a in keys.Keys)
+            {
+                if (tab[a] == null)
+                {
+                    tab[a] = "key";
+                }
+            }
+
+            return tab;
+        }
+
+        public IEnumerable Aliases
+        {
+            get { return new EnumerableProxy(GetAliasesTable().Keys); }
+        }
+
+        public bool ContainsAlias(
+            string alias)
+        {
+            return certs[alias] != null || keys[alias] != null;
+        }
+
+        /**
+         * simply return the cert entry for the private key
+         */
+        public X509CertificateEntry GetCertificate(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            X509CertificateEntry c = (X509CertificateEntry) certs[alias];
+
+            //
+            // look up the key table - and try the local key id
+            //
+            if (c == null)
+            {
+                string id = (string)localIds[alias];
+                if (id != null)
+                {
+                    c = (X509CertificateEntry)keyCerts[id];
+                }
+                else
+                {
+                    c = (X509CertificateEntry)keyCerts[alias];
+                }
+            }
+
+            return c;
+        }
+
+        public string GetCertificateAlias(
+            X509Certificate cert)
+        {
+            if (cert == null)
+                throw new ArgumentNullException("cert");
+
+            foreach (DictionaryEntry entry in certs)
+            {
+                X509CertificateEntry entryValue = (X509CertificateEntry) entry.Value;
+                if (entryValue.Certificate.Equals(cert))
+                {
+                    return (string) entry.Key;
+                }
+            }
+
+            foreach (DictionaryEntry entry in keyCerts)
+            {
+                X509CertificateEntry entryValue = (X509CertificateEntry) entry.Value;
+                if (entryValue.Certificate.Equals(cert))
+                {
+                    return (string) entry.Key;
+                }
+            }
+
+            return null;
+        }
+
+        public X509CertificateEntry[] GetCertificateChain(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            if (!IsKeyEntry(alias))
+            {
+                return null;
+            }
+
+            X509CertificateEntry c = GetCertificate(alias);
+
+            if (c != null)
+            {
+                IList cs = Platform.CreateArrayList();
+
+                while (c != null)
+                {
+                    X509Certificate x509c = c.Certificate;
+                    X509CertificateEntry nextC = null;
+
+                    Asn1OctetString ext = x509c.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
+                    if (ext != null)
+                    {
+                        AuthorityKeyIdentifier id = AuthorityKeyIdentifier.GetInstance(
+                            Asn1Object.FromByteArray(ext.GetOctets()));
+
+                        if (id.GetKeyIdentifier() != null)
+                        {
+                            nextC = (X509CertificateEntry) chainCerts[new CertId(id.GetKeyIdentifier())];
+                        }
+                    }
+
+                    if (nextC == null)
+                    {
+                        //
+                        // no authority key id, try the Issuer DN
+                        //
+                        X509Name i = x509c.IssuerDN;
+                        X509Name s = x509c.SubjectDN;
+
+                        if (!i.Equivalent(s))
+                        {
+                            foreach (CertId certId in chainCerts.Keys)
+                            {
+                                X509CertificateEntry x509CertEntry = (X509CertificateEntry) chainCerts[certId];
+
+                                X509Certificate crt = x509CertEntry.Certificate;
+
+                                X509Name sub = crt.SubjectDN;
+                                if (sub.Equivalent(i))
+                                {
+                                    try
+                                    {
+                                        x509c.Verify(crt.GetPublicKey());
+
+                                        nextC = x509CertEntry;
+                                        break;
+                                    }
+                                    catch (InvalidKeyException)
+                                    {
+                                        // TODO What if it doesn't verify?
+                                    }
+                                }
+                            }
+                        }
+                    }
+
+                    cs.Add(c);
+                    if (nextC != c) // self signed - end of the chain
+                    {
+                        c = nextC;
+                    }
+                    else
+                    {
+                        c = null;
+                    }
+                }
+
+                X509CertificateEntry[] result = new X509CertificateEntry[cs.Count];
+                for (int i = 0; i < cs.Count; ++i)
+                {
+                    result[i] = (X509CertificateEntry)cs[i];
+                }
+                return result;
+            }
+
+            return null;
+        }
+
+        public void SetCertificateEntry(
+            string					alias,
+            X509CertificateEntry	certEntry)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+            if (certEntry == null)
+                throw new ArgumentNullException("certEntry");
+            if (keys[alias] != null)
+                throw new ArgumentException("There is a key entry with the name " + alias + ".");
+
+            certs[alias] = certEntry;
+            chainCerts[new CertId(certEntry.Certificate.GetPublicKey())] = certEntry;
+        }
+
+        public void SetKeyEntry(
+            string					alias,
+            AsymmetricKeyEntry		keyEntry,
+            X509CertificateEntry[]	chain)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+            if (keyEntry == null)
+                throw new ArgumentNullException("keyEntry");
+            if (keyEntry.Key.IsPrivate && (chain == null))
+                throw new ArgumentException("No certificate chain for private key");
+
+            if (keys[alias] != null)
+            {
+                DeleteEntry(alias);
+            }
+
+            keys[alias] = keyEntry;
+            certs[alias] = chain[0];
+
+            for (int i = 0; i != chain.Length; i++)
+            {
+                chainCerts[new CertId(chain[i].Certificate.GetPublicKey())] = chain[i];
+            }
+        }
+
+        public void DeleteEntry(
+            string alias)
+        {
+            if (alias == null)
+                throw new ArgumentNullException("alias");
+
+            AsymmetricKeyEntry k = (AsymmetricKeyEntry)keys[alias];
+            if (k != null)
+            {
+                keys.Remove(alias);
+            }
+
+            X509CertificateEntry c = (X509CertificateEntry)certs[alias];
+
+            if (c != null)
+            {
+                certs.Remove(alias);
+                chainCerts.Remove(new CertId(c.Certificate.GetPublicKey()));
+            }
+
+            if (k != null)
+            {
+                string id = (string)localIds[alias];
+                if (id != null)
+                {
+                    localIds.Remove(alias);
+                    c = (X509CertificateEntry)keyCerts[id];
+                }
+                if (c != null)
+                {
+                    keyCerts.Remove(id);
+                    chainCerts.Remove(new CertId(c.Certificate.GetPublicKey()));
+                }
+            }
+
+            if (c == null && k == null)
+            {
+                throw new ArgumentException("no such entry as " + alias);
+            }
+        }
+
+        public bool IsEntryOfType(
+            string	alias,
+            Type	entryType)
+        {
+            if (entryType == typeof(X509CertificateEntry))
+                return IsCertificateEntry(alias);
+
+            if (entryType == typeof(AsymmetricKeyEntry))
+                return IsKeyEntry(alias) && GetCertificate(alias) != null;
+
+            return false;
+        }
+
+        [Obsolete("Use 'Count' property instead")]
+        public int Size()
+        {
+            return Count;
+        }
+
+        public int Count
+        {
+            // TODO Seems a little inefficient
+            get { return GetAliasesTable().Count; }
+        }
+
+        public void Save(
+            Stream			stream,
+            char[]			password,
+            SecureRandom	random)
+        {
+            if (stream == null)
+                throw new ArgumentNullException("stream");
+            if (password == null)
+                throw new ArgumentNullException("password");
+            if (random == null)
+                throw new ArgumentNullException("random");
+
+            //
+            // handle the key
+            //
+            Asn1EncodableVector keyS = new Asn1EncodableVector();
+            foreach (string name in keys.Keys)
+            {
+                byte[] kSalt = new byte[SaltSize];
+                random.NextBytes(kSalt);
+
+                AsymmetricKeyEntry privKey = (AsymmetricKeyEntry) keys[name];
+                EncryptedPrivateKeyInfo kInfo =
+                    EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+                    keyAlgorithm, password, kSalt, MinIterations, privKey.Key);
+
+                Asn1EncodableVector kName = new Asn1EncodableVector();
+
+                foreach (string oid in privKey.BagAttributeKeys)
+                {
+                    Asn1Encodable entry = privKey[oid];
+
+                    // NB: Ignore any existing FriendlyName
+                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
+                        continue;
+
+                    kName.Add(
+                        new DerSequence(
+                            new DerObjectIdentifier(oid),
+                            new DerSet(entry)));
+                }
+
+                //
+                // make sure we are using the local alias on store
+                //
+                // NB: We always set the FriendlyName based on 'name'
+                //if (privKey[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
+                {
+                    kName.Add(
+                        new DerSequence(
+                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
+                            new DerSet(new DerBmpString(name))));
+                }
+
+                //
+                // make sure we have a local key-id
+                //
+                if (privKey[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
+                {
+                    X509CertificateEntry ct = GetCertificate(name);
+                    AsymmetricKeyParameter pubKey = ct.Certificate.GetPublicKey();
+                    SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey);
+
+                    kName.Add(
+                        new DerSequence(
+                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
+                            new DerSet(subjectKeyID)));
+                }
+
+                SafeBag kBag = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, kInfo.ToAsn1Object(), new DerSet(kName));
+                keyS.Add(kBag);
+            }
+
+            byte[] derEncodedBytes = new DerSequence(keyS).GetDerEncoded();
+
+            BerOctetString keyString = new BerOctetString(derEncodedBytes);
+
+            //
+            // certificate processing
+            //
+            byte[] cSalt = new byte[SaltSize];
+
+            random.NextBytes(cSalt);
+
+            Asn1EncodableVector	certSeq = new Asn1EncodableVector();
+            Pkcs12PbeParams		cParams = new Pkcs12PbeParams(cSalt, MinIterations);
+            AlgorithmIdentifier	cAlgId = new AlgorithmIdentifier(certAlgorithm, cParams.ToAsn1Object());
+            ISet				doneCerts = new HashSet();
+
+            foreach (string name in keys.Keys)
+            {
+                X509CertificateEntry certEntry = GetCertificate(name);
+                CertBag cBag = new CertBag(
+                    PkcsObjectIdentifiers.X509Certificate,
+                    new DerOctetString(certEntry.Certificate.GetEncoded()));
+
+                Asn1EncodableVector fName = new Asn1EncodableVector();
+
+                foreach (string oid in certEntry.BagAttributeKeys)
+                {
+                    Asn1Encodable entry = certEntry[oid];
+
+                    // NB: Ignore any existing FriendlyName
+                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
+                        continue;
+
+                    fName.Add(
+                        new DerSequence(
+                            new DerObjectIdentifier(oid),
+                            new DerSet(entry)));
+                }
+
+                //
+                // make sure we are using the local alias on store
+                //
+                // NB: We always set the FriendlyName based on 'name'
+                //if (certEntry[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
+                {
+                    fName.Add(
+                        new DerSequence(
+                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
+                            new DerSet(new DerBmpString(name))));
+                }
+
+                //
+                // make sure we have a local key-id
+                //
+                if (certEntry[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
+                {
+                    AsymmetricKeyParameter pubKey = certEntry.Certificate.GetPublicKey();
+                    SubjectKeyIdentifier subjectKeyID = CreateSubjectKeyID(pubKey);
+
+                    fName.Add(
+                        new DerSequence(
+                            PkcsObjectIdentifiers.Pkcs9AtLocalKeyID,
+                            new DerSet(subjectKeyID)));
+                }
+
+                SafeBag sBag = new SafeBag(
+                    PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));
+
+                certSeq.Add(sBag);
+
+                doneCerts.Add(certEntry.Certificate);
+            }
+
+            foreach (string certId in certs.Keys)
+            {
+                X509CertificateEntry cert = (X509CertificateEntry)certs[certId];
+
+                if (keys[certId] != null)
+                    continue;
+
+                CertBag cBag = new CertBag(
+                    PkcsObjectIdentifiers.X509Certificate,
+                    new DerOctetString(cert.Certificate.GetEncoded()));
+
+                Asn1EncodableVector fName = new Asn1EncodableVector();
+
+                foreach (string oid in cert.BagAttributeKeys)
+                {
+                    // a certificate not immediately linked to a key doesn't require
+                    // a localKeyID and will confuse some PKCS12 implementations.
+                    //
+                    // If we find one, we'll prune it out.
+                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
+                        continue;
+
+                    Asn1Encodable entry = cert[oid];
+
+                    // NB: Ignore any existing FriendlyName
+                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id))
+                        continue;
+
+                    fName.Add(
+                        new DerSequence(
+                            new DerObjectIdentifier(oid),
+                            new DerSet(entry)));
+                }
+
+                //
+                // make sure we are using the local alias on store
+                //
+                // NB: We always set the FriendlyName based on 'certId'
+                //if (cert[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] == null)
+                {
+                    fName.Add(
+                        new DerSequence(
+                            PkcsObjectIdentifiers.Pkcs9AtFriendlyName,
+                            new DerSet(new DerBmpString(certId))));
+                }
+
+                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag,
+                    cBag.ToAsn1Object(), new DerSet(fName));
+
+                certSeq.Add(sBag);
+
+                doneCerts.Add(cert.Certificate);
+            }
+
+            foreach (CertId certId in chainCerts.Keys)
+            {
+                X509CertificateEntry cert = (X509CertificateEntry)chainCerts[certId];
+
+                if (doneCerts.Contains(cert.Certificate))
+                    continue;
+
+                CertBag cBag = new CertBag(
+                    PkcsObjectIdentifiers.X509Certificate,
+                    new DerOctetString(cert.Certificate.GetEncoded()));
+
+                Asn1EncodableVector fName = new Asn1EncodableVector();
+
+                foreach (string oid in cert.BagAttributeKeys)
+                {
+                    // a certificate not immediately linked to a key doesn't require
+                    // a localKeyID and will confuse some PKCS12 implementations.
+                    //
+                    // If we find one, we'll prune it out.
+                    if (oid.Equals(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id))
+                        continue;
+
+                    fName.Add(
+                        new DerSequence(
+                            new DerObjectIdentifier(oid),
+                            new DerSet(cert[oid])));
+                }
+
+                SafeBag sBag = new SafeBag(PkcsObjectIdentifiers.CertBag, cBag.ToAsn1Object(), new DerSet(fName));
+
+                certSeq.Add(sBag);
+            }
+
+            derEncodedBytes = new DerSequence(certSeq).GetDerEncoded();
+
+            byte[] certBytes = CryptPbeData(true, cAlgId, password, false, derEncodedBytes);
+
+            EncryptedData cInfo = new EncryptedData(PkcsObjectIdentifiers.Data, cAlgId, new BerOctetString(certBytes));
+
+            ContentInfo[] info = new ContentInfo[]
+            {
+                new ContentInfo(PkcsObjectIdentifiers.Data, keyString),
+                new ContentInfo(PkcsObjectIdentifiers.EncryptedData, cInfo.ToAsn1Object())
+            };
+
+            byte[] data = new AuthenticatedSafe(info).GetEncoded(
+                useDerEncoding ? Asn1Encodable.Der : Asn1Encodable.Ber);
+
+            ContentInfo mainInfo = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(data));
+
+            //
+            // create the mac
+            //
+            byte[] mSalt = new byte[20];
+            random.NextBytes(mSalt);
+
+            byte[] mac = CalculatePbeMac(OiwObjectIdentifiers.IdSha1,
+                mSalt, MinIterations, password, false, data);
+
+            AlgorithmIdentifier algId = new AlgorithmIdentifier(
+                OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+            DigestInfo dInfo = new DigestInfo(algId, mac);
+
+            MacData mData = new MacData(dInfo, mSalt, MinIterations);
+
+            //
+            // output the Pfx
+            //
+            Pfx pfx = new Pfx(mainInfo, mData);
+
+            DerOutputStream derOut;
+            if (useDerEncoding)
+            {
+                derOut = new DerOutputStream(stream);
+            }
+            else
+            {
+                derOut = new BerOutputStream(stream);
+            }
+
+            derOut.WriteObject(pfx);
+        }
+
+        internal static byte[] CalculatePbeMac(
+            DerObjectIdentifier	oid,
+            byte[]				salt,
+            int					itCount,
+            char[]				password,
+            bool				wrongPkcs12Zero,
+            byte[]				data)
+        {
+            Asn1Encodable asn1Params = PbeUtilities.GenerateAlgorithmParameters(
+                oid, salt, itCount);
+            ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+                oid, password, wrongPkcs12Zero, asn1Params);
+
+            IMac mac = (IMac) PbeUtilities.CreateEngine(oid);
+            mac.Init(cipherParams);
+            return MacUtilities.DoFinal(mac, data);
+        }
+
+        private static byte[] CryptPbeData(
+            bool				forEncryption,
+            AlgorithmIdentifier	algId,
+            char[]				password,
+            bool				wrongPkcs12Zero,
+            byte[]				data)
+        {
+            IBufferedCipher cipher = PbeUtilities.CreateEngine(algId.ObjectID) as IBufferedCipher;
+
+            if (cipher == null)
+                throw new Exception("Unknown encryption algorithm: " + algId.ObjectID);
+
+            Pkcs12PbeParams pbeParameters = Pkcs12PbeParams.GetInstance(algId.Parameters);
+            ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+                algId.ObjectID, password, wrongPkcs12Zero, pbeParameters);
+            cipher.Init(forEncryption, cipherParams);
+            return cipher.DoFinal(data);
+        }
+
+        private class IgnoresCaseHashtable
+            : IEnumerable
+        {
+            private readonly IDictionary orig = Platform.CreateHashtable();
+            private readonly IDictionary keys = Platform.CreateHashtable();
+
+            public void Clear()
+            {
+                orig.Clear();
+                keys.Clear();
+            }
+
+            public IEnumerator GetEnumerator()
+            {
+                return orig.GetEnumerator();
+            }
+
+            public ICollection Keys
+            {
+                get { return orig.Keys; }
+            }
+
+            public object Remove(
+                string alias)
+            {
+                string lower = Platform.ToLowerInvariant(alias);
+                string k = (string) keys[lower];
+
+                if (k == null)
+                    return null;
+
+                keys.Remove(lower);
+
+                object o = orig[k];
+                orig.Remove(k);
+                return o;
+            }
+
+            public object this[
+                string alias]
+            {
+                get
+                {
+                    string lower = Platform.ToLowerInvariant(alias);
+                    string k = (string)keys[lower];
+
+                    if (k == null)
+                        return null;
+
+                    return orig[k];
+                }
+                set
+                {
+                    string lower = Platform.ToLowerInvariant(alias);
+                    string k = (string)keys[lower];
+                    if (k != null)
+                    {
+                        orig.Remove(k);
+                    }
+                    keys[lower] = alias;
+                    orig[alias] = value;
+                }
+            }
+
+            public ICollection Values
+            {
+                get { return orig.Values; }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Utilities.cs b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Utilities.cs
new file mode 100644
index 0000000..d35c8b6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/Pkcs12Utilities.cs
@@ -0,0 +1,77 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Pkcs
+{
+	/**
+	 * Utility class for reencoding PKCS#12 files to definite length.
+	 */
+	public class Pkcs12Utilities
+	{
+		/**
+		 * Just re-encode the outer layer of the PKCS#12 file to definite length encoding.
+		 *
+		 * @param berPKCS12File - original PKCS#12 file
+		 * @return a byte array representing the DER encoding of the PFX structure
+		 * @throws IOException
+		 */
+		public static byte[] ConvertToDefiniteLength(
+			byte[] berPkcs12File)
+		{
+			Pfx pfx = new Pfx(Asn1Sequence.GetInstance(Asn1Object.FromByteArray(berPkcs12File)));
+
+			return pfx.GetEncoded(Asn1Encodable.Der);
+		}
+
+		/**
+		* Re-encode the PKCS#12 structure to definite length encoding at the inner layer
+		* as well, recomputing the MAC accordingly.
+		*
+		* @param berPKCS12File - original PKCS12 file.
+		* @param provider - provider to use for MAC calculation.
+		* @return a byte array representing the DER encoding of the PFX structure.
+		* @throws IOException on parsing, encoding errors.
+		*/
+		public static byte[] ConvertToDefiniteLength(
+			byte[]	berPkcs12File,
+			char[]	passwd)
+		{
+			Pfx pfx = new Pfx(Asn1Sequence.GetInstance(Asn1Object.FromByteArray(berPkcs12File)));
+
+			ContentInfo info = pfx.AuthSafe;
+
+			Asn1OctetString content = Asn1OctetString.GetInstance(info.Content);
+			Asn1Object obj = Asn1Object.FromByteArray(content.GetOctets());
+
+			info = new ContentInfo(info.ContentType, new DerOctetString(obj.GetEncoded(Asn1Encodable.Der)));
+
+			MacData mData = pfx.MacData;
+
+			try
+			{
+				int itCount = mData.IterationCount.IntValue;
+				byte[] data = Asn1OctetString.GetInstance(info.Content).GetOctets();
+				byte[] res = Pkcs12Store.CalculatePbeMac(
+					mData.Mac.AlgorithmID.ObjectID, mData.GetSalt(), itCount, passwd, false, data);
+
+				AlgorithmIdentifier algId = new AlgorithmIdentifier(
+					mData.Mac.AlgorithmID.ObjectID, DerNull.Instance);
+				DigestInfo dInfo = new DigestInfo(algId, res);
+
+				mData = new MacData(dInfo, mData.GetSalt(), itCount);
+			}
+			catch (Exception e)
+			{
+				throw new IOException("error constructing MAC: " + e.ToString());
+			}
+
+			pfx = new Pfx(info, mData);
+
+			return pfx.GetEncoded(Asn1Encodable.Der);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/pkcs/PrivateKeyInfoFactory.cs b/BouncyCastle.AxCrypt/src/pkcs/PrivateKeyInfoFactory.cs
new file mode 100644
index 0000000..723d50f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/PrivateKeyInfoFactory.cs
@@ -0,0 +1,208 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public sealed class PrivateKeyInfoFactory
+    {
+        private PrivateKeyInfoFactory()
+        {
+        }
+
+        public static PrivateKeyInfo CreatePrivateKeyInfo(
+            AsymmetricKeyParameter key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+            if (!key.IsPrivate)
+                throw new ArgumentException("Public key passed - private key expected", "key");
+
+            if (key is ElGamalPrivateKeyParameters)
+            {
+                ElGamalPrivateKeyParameters _key = (ElGamalPrivateKeyParameters)key;
+                return new PrivateKeyInfo(
+                    new AlgorithmIdentifier(
+                    OiwObjectIdentifiers.ElGamalAlgorithm,
+                    new ElGamalParameter(
+                    _key.Parameters.P,
+                    _key.Parameters.G).ToAsn1Object()),
+                    new DerInteger(_key.X));
+            }
+
+            if (key is DsaPrivateKeyParameters)
+            {
+                DsaPrivateKeyParameters _key = (DsaPrivateKeyParameters)key;
+                return new PrivateKeyInfo(
+                    new AlgorithmIdentifier(
+                    X9ObjectIdentifiers.IdDsa,
+                    new DsaParameter(
+                    _key.Parameters.P,
+                    _key.Parameters.Q,
+                    _key.Parameters.G).ToAsn1Object()),
+                    new DerInteger(_key.X));
+            }
+
+            if (key is DHPrivateKeyParameters)
+            {
+                DHPrivateKeyParameters _key = (DHPrivateKeyParameters)key;
+
+                DHParameter p = new DHParameter(
+                    _key.Parameters.P, _key.Parameters.G, _key.Parameters.L);
+
+                return new PrivateKeyInfo(
+                    new AlgorithmIdentifier(_key.AlgorithmOid, p.ToAsn1Object()),
+                    new DerInteger(_key.X));
+            }
+
+            if (key is RsaKeyParameters)
+            {
+                AlgorithmIdentifier algID = new AlgorithmIdentifier(
+                    PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance);
+
+                RsaPrivateKeyStructure keyStruct;
+                if (key is RsaPrivateCrtKeyParameters)
+                {
+                    RsaPrivateCrtKeyParameters _key = (RsaPrivateCrtKeyParameters)key;
+
+                    keyStruct = new RsaPrivateKeyStructure(
+                        _key.Modulus,
+                        _key.PublicExponent,
+                        _key.Exponent,
+                        _key.P,
+                        _key.Q,
+                        _key.DP,
+                        _key.DQ,
+                        _key.QInv);
+                }
+                else
+                {
+                    RsaKeyParameters _key = (RsaKeyParameters) key;
+
+                    keyStruct = new RsaPrivateKeyStructure(
+                        _key.Modulus,
+                        BigInteger.Zero,
+                        _key.Exponent,
+                        BigInteger.Zero,
+                        BigInteger.Zero,
+                        BigInteger.Zero,
+                        BigInteger.Zero,
+                        BigInteger.Zero);
+                }
+
+                return new PrivateKeyInfo(algID, keyStruct.ToAsn1Object());
+            }
+
+            if (key is ECPrivateKeyParameters)
+            {
+                ECPrivateKeyParameters _key = (ECPrivateKeyParameters)key;
+                AlgorithmIdentifier algID;
+                ECPrivateKeyStructure ec;
+
+                if (_key.AlgorithmName == "ECGOST3410")
+                {
+                    if (_key.PublicKeyParamSet == null)
+                        throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+                    Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+                        _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+
+                    algID = new AlgorithmIdentifier(
+                        CryptoProObjectIdentifiers.GostR3410x2001,
+                        gostParams.ToAsn1Object());
+
+                    // TODO Do we need to pass any parameters here?
+                    ec = new ECPrivateKeyStructure(_key.D);
+                }
+                else
+                {
+                    X962Parameters x962;
+                    if (_key.PublicKeyParamSet == null)
+                    {
+                        ECDomainParameters kp = _key.Parameters;
+                        X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed());
+
+                        x962 = new X962Parameters(ecP);
+                    }
+                    else
+                    {
+                        x962 = new X962Parameters(_key.PublicKeyParamSet);
+                    }
+
+                    Asn1Object x962Object = x962.ToAsn1Object();
+
+                    // TODO Possible to pass the publicKey bitstring here?
+                    ec = new ECPrivateKeyStructure(_key.D, x962Object);
+
+                    algID = new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, x962Object);
+                }
+
+                return new PrivateKeyInfo(algID, ec.ToAsn1Object());
+            }
+
+            if (key is Gost3410PrivateKeyParameters)
+            {
+                Gost3410PrivateKeyParameters _key = (Gost3410PrivateKeyParameters)key;
+
+                if (_key.PublicKeyParamSet == null)
+                    throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+                byte[] keyEnc = _key.X.ToByteArrayUnsigned();
+                byte[] keyBytes = new byte[keyEnc.Length];
+
+                for (int i = 0; i != keyBytes.Length; i++)
+                {
+                    keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian
+                }
+
+                Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
+                    _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet, null);
+
+                AlgorithmIdentifier algID = new AlgorithmIdentifier(
+                    CryptoProObjectIdentifiers.GostR3410x94,
+                    algParams.ToAsn1Object());
+
+                return new PrivateKeyInfo(algID, new DerOctetString(keyBytes));
+            }
+
+            throw new ArgumentException("Class provided is not convertible: " + key.GetType().FullName);
+        }
+
+        public static PrivateKeyInfo CreatePrivateKeyInfo(
+            char[]					passPhrase,
+            EncryptedPrivateKeyInfo	encInfo)
+        {
+            return CreatePrivateKeyInfo(passPhrase, false, encInfo);
+        }
+
+        public static PrivateKeyInfo CreatePrivateKeyInfo(
+            char[]					passPhrase,
+            bool					wrongPkcs12Zero,
+            EncryptedPrivateKeyInfo	encInfo)
+        {
+            AlgorithmIdentifier algID = encInfo.EncryptionAlgorithm;
+
+            IBufferedCipher cipher = PbeUtilities.CreateEngine(algID) as IBufferedCipher;
+            if (cipher == null)
+                throw new Exception("Unknown encryption algorithm: " + algID.ObjectID);
+
+            ICipherParameters cipherParameters = PbeUtilities.GenerateCipherParameters(
+                algID, passPhrase, wrongPkcs12Zero);
+            cipher.Init(false, cipherParameters);
+            byte[] keyBytes = cipher.DoFinal(encInfo.GetEncryptedData());
+
+            return PrivateKeyInfo.GetInstance(keyBytes);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkcs/X509CertificateEntry.cs b/BouncyCastle.AxCrypt/src/pkcs/X509CertificateEntry.cs
new file mode 100644
index 0000000..a621619
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkcs/X509CertificateEntry.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkcs
+{
+    public class X509CertificateEntry
+        : Pkcs12Entry
+    {
+        private readonly X509Certificate cert;
+
+		public X509CertificateEntry(
+            X509Certificate cert)
+			: base(Platform.CreateHashtable())
+        {
+            this.cert = cert;
+        }
+
+#if !SILVERLIGHT
+        [Obsolete]
+        public X509CertificateEntry(
+            X509Certificate	cert,
+            Hashtable		attributes)
+			: base(attributes)
+        {
+            this.cert = cert;
+        }
+#endif
+
+        public X509CertificateEntry(
+            X509Certificate cert,
+            IDictionary     attributes)
+			: base(attributes)
+        {
+            this.cert = cert;
+        }
+
+		public X509Certificate Certificate
+        {
+			get { return this.cert; }
+        }
+
+		public override bool Equals(object obj)
+		{
+			X509CertificateEntry other = obj as X509CertificateEntry;
+
+			if (other == null)
+				return false;
+
+			return cert.Equals(other.cert);
+		}
+
+		public override int GetHashCode()
+		{
+			return ~cert.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/CertStatus.cs b/BouncyCastle.AxCrypt/src/pkix/CertStatus.cs
new file mode 100644
index 0000000..4f40b7b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/CertStatus.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Pkix
+{
+    public class CertStatus
+    {
+        public const int Unrevoked = 11;
+
+        public const int Undetermined = 12;
+
+        private int status = Unrevoked;
+
+        DateTimeObject revocationDate = null;
+
+        /// <summary>
+        /// Returns the revocationDate.
+        /// </summary>
+         public DateTimeObject RevocationDate
+        {
+            get { return revocationDate; }
+            set { this.revocationDate = value; }
+        }
+
+		/// <summary>
+        /// Returns the certStatus.
+        /// </summary>
+        public int Status
+        {
+            get { return status; }
+            set { this.status = value; }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertChecker.cs b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertChecker.cs
new file mode 100644
index 0000000..a6eab84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertChecker.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkix
+{
+	public abstract class PkixAttrCertChecker
+	{
+		/**
+		 * Returns an immutable <code>Set</code> of X.509 attribute certificate
+		 * extensions that this <code>PkixAttrCertChecker</code> supports or
+		 * <code>null</code> if no extensions are supported.
+		 * <p>
+		 * Each element of the set is a <code>String</code> representing the
+		 * Object Identifier (OID) of the X.509 extension that is supported.
+		 * </p>
+		 * <p>
+		 * All X.509 attribute certificate extensions that a
+		 * <code>PkixAttrCertChecker</code> might possibly be able to process
+		 * should be included in the set.
+		 * </p>
+		 * 
+		 * @return an immutable <code>Set</code> of X.509 extension OIDs (in
+		 *         <code>String</code> format) supported by this
+		 *         <code>PkixAttrCertChecker</code>, or <code>null</code> if no
+		 *         extensions are supported
+		 */
+		public abstract ISet GetSupportedExtensions();
+
+		/**
+		* Performs checks on the specified attribute certificate. Every handled
+		* extension is rmeoved from the <code>unresolvedCritExts</code>
+		* collection.
+		* 
+		* @param attrCert The attribute certificate to be checked.
+		* @param certPath The certificate path which belongs to the attribute
+		*            certificate issuer public key certificate.
+		* @param holderCertPath The certificate path which belongs to the holder
+		*            certificate.
+		* @param unresolvedCritExts a <code>Collection</code> of OID strings
+		*            representing the current set of unresolved critical extensions
+		* @throws CertPathValidatorException if the specified attribute certificate
+		*             does not pass the check.
+		*/
+		public abstract void Check(IX509AttributeCertificate attrCert, PkixCertPath certPath,
+			PkixCertPath holderCertPath, ICollection unresolvedCritExts);
+
+		/**
+		* Returns a clone of this object.
+		* 
+		* @return a copy of this <code>PkixAttrCertChecker</code>
+		*/
+		public abstract PkixAttrCertChecker Clone();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathBuilder.cs b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathBuilder.cs
new file mode 100644
index 0000000..646cc5d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathBuilder.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	public class PkixAttrCertPathBuilder
+	{
+		/**
+		* Build and validate a CertPath using the given parameter.
+		*
+		* @param params PKIXBuilderParameters object containing all information to
+		*            build the CertPath
+		*/
+		public virtual PkixCertPathBuilderResult Build(
+			PkixBuilderParameters pkixParams)
+		{
+			// search target certificates
+
+			IX509Selector certSelect = pkixParams.GetTargetConstraints();
+			if (!(certSelect is X509AttrCertStoreSelector))
+			{
+				throw new PkixCertPathBuilderException(
+					"TargetConstraints must be an instance of "
+					+ typeof(X509AttrCertStoreSelector).FullName
+					+ " for "
+					+ typeof(PkixAttrCertPathBuilder).FullName + " class.");
+			}
+
+			ICollection targets;
+			try
+			{
+				targets = PkixCertPathValidatorUtilities.FindCertificates(
+					(X509AttrCertStoreSelector)certSelect, pkixParams.GetStores());
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathBuilderException("Error finding target attribute certificate.", e);
+			}
+
+			if (targets.Count == 0)
+			{
+				throw new PkixCertPathBuilderException(
+					"No attribute certificate found matching targetContraints.");
+			}
+
+			PkixCertPathBuilderResult result = null;
+
+			// check all potential target certificates
+			foreach (IX509AttributeCertificate cert in targets)
+			{
+				X509CertStoreSelector selector = new X509CertStoreSelector();
+				X509Name[] principals = cert.Issuer.GetPrincipals();
+				ISet issuers = new HashSet();
+				for (int i = 0; i < principals.Length; i++)
+				{
+					try
+					{
+						selector.Subject = principals[i];
+
+						issuers.AddAll(PkixCertPathValidatorUtilities.FindCertificates(selector, pkixParams.GetStores()));
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathBuilderException(
+							"Public key certificate for attribute certificate cannot be searched.",
+							e);
+					}
+				}
+
+				if (issuers.IsEmpty)
+					throw new PkixCertPathBuilderException("Public key certificate for attribute certificate cannot be found.");
+
+                IList certPathList = Platform.CreateArrayList();
+
+				foreach (X509Certificate issuer in issuers)
+				{
+					result = Build(cert, issuer, pkixParams, certPathList);
+
+					if (result != null)
+						break;
+				}
+
+				if (result != null)
+					break;
+			}
+
+			if (result == null && certPathException != null)
+			{
+				throw new PkixCertPathBuilderException(
+					"Possible certificate chain could not be validated.",
+					certPathException);
+			}
+
+			if (result == null && certPathException == null)
+			{
+				throw new PkixCertPathBuilderException(
+					"Unable to find certificate chain.");
+			}
+
+			return result;
+		}
+
+		private Exception certPathException;
+
+		private PkixCertPathBuilderResult Build(
+			IX509AttributeCertificate	attrCert,
+			X509Certificate				tbvCert,
+			PkixBuilderParameters		pkixParams,
+			IList						tbvPath)
+		{
+			// If tbvCert is readily present in tbvPath, it indicates having run
+			// into a cycle in the
+			// PKI graph.
+			if (tbvPath.Contains(tbvCert))
+				return null;
+
+			// step out, the certificate is not allowed to appear in a certification
+			// chain
+			if (pkixParams.GetExcludedCerts().Contains(tbvCert))
+				return null;
+
+			// test if certificate path exceeds maximum length
+			if (pkixParams.MaxPathLength != -1)
+			{
+				if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
+					return null;
+			}
+
+			tbvPath.Add(tbvCert);
+
+			PkixCertPathBuilderResult builderResult = null;
+
+//			X509CertificateParser certParser = new X509CertificateParser();
+			PkixAttrCertPathValidator validator = new PkixAttrCertPathValidator();
+
+			try
+			{
+				// check whether the issuer of <tbvCert> is a TrustAnchor
+				if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
+				{
+					PkixCertPath certPath = new PkixCertPath(tbvPath);
+					PkixCertPathValidatorResult result;
+
+					try
+					{
+						result = validator.Validate(certPath, pkixParams);
+					}
+					catch (Exception e)
+					{
+						throw new Exception("Certification path could not be validated.", e);
+					}
+
+					return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
+						result.PolicyTree, result.SubjectPublicKey);
+				}
+				else
+				{
+					// add additional X.509 stores from locations in certificate
+					try
+					{
+						PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(tbvCert, pkixParams);
+					}
+					catch (CertificateParsingException e)
+					{
+						throw new Exception("No additional X.509 stores can be added from certificate locations.", e);
+					}
+
+					// try to get the issuer certificate from one of the stores
+					ISet issuers = new HashSet();
+					try
+					{
+						issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
+					}
+					catch (Exception e)
+					{
+						throw new Exception("Cannot find issuer certificate for certificate in certification path.", e);
+					}
+
+					if (issuers.IsEmpty)
+						throw new Exception("No issuer certificate for certificate in certification path found.");
+
+					foreach (X509Certificate issuer in issuers)
+					{
+						// if untrusted self signed certificate continue
+						if (PkixCertPathValidatorUtilities.IsSelfIssued(issuer))
+							continue;
+
+						builderResult = Build(attrCert, issuer, pkixParams, tbvPath);
+
+						if (builderResult != null)
+							break;
+					}
+				}
+			}
+			catch (Exception e)
+			{
+				certPathException = new Exception("No valid certification path could be build.", e);
+			}
+
+			if (builderResult == null)
+			{
+				tbvPath.Remove(tbvCert);
+			}
+
+			return builderResult;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathValidator.cs b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathValidator.cs
new file mode 100644
index 0000000..5f53bcd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixAttrCertPathValidator.cs
@@ -0,0 +1,76 @@
+using System;
+
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/**
+	* CertPathValidatorSpi implementation for X.509 Attribute Certificates la RFC 3281.
+	* 
+	* @see org.bouncycastle.x509.ExtendedPkixParameters
+	*/
+	public class PkixAttrCertPathValidator
+	//    extends CertPathValidatorSpi
+	{
+		/**
+		* Validates an attribute certificate with the given certificate path.
+		* 
+		* <p>
+		* <code>params</code> must be an instance of
+		* <code>ExtendedPkixParameters</code>.
+		* </p><p>
+		* The target constraints in the <code>params</code> must be an
+		* <code>X509AttrCertStoreSelector</code> with at least the attribute
+		* certificate criterion set. Obey that also target informations may be
+		* necessary to correctly validate this attribute certificate.
+		* </p><p>
+		* The attribute certificate issuer must be added to the trusted attribute
+		* issuers with {@link ExtendedPkixParameters#setTrustedACIssuers(Set)}.
+		* </p>
+		* @param certPath The certificate path which belongs to the attribute
+		*            certificate issuer public key certificate.
+		* @param params The PKIX parameters.
+		* @return A <code>PKIXCertPathValidatorResult</code> of the result of
+		*         validating the <code>certPath</code>.
+		* @throws InvalidAlgorithmParameterException if <code>params</code> is
+		*             inappropriate for this validator.
+		* @throws CertPathValidatorException if the verification fails.
+		*/
+		public virtual PkixCertPathValidatorResult Validate(
+			PkixCertPath	certPath,
+			PkixParameters	pkixParams)
+		{
+			IX509Selector certSelect = pkixParams.GetTargetConstraints();
+			if (!(certSelect is X509AttrCertStoreSelector))
+			{
+				throw new ArgumentException(
+					"TargetConstraints must be an instance of " + typeof(X509AttrCertStoreSelector).FullName,
+					"pkixParams");
+			}
+			IX509AttributeCertificate attrCert = ((X509AttrCertStoreSelector) certSelect).AttributeCert;
+
+			PkixCertPath holderCertPath = Rfc3281CertPathUtilities.ProcessAttrCert1(attrCert, pkixParams);
+			PkixCertPathValidatorResult result = Rfc3281CertPathUtilities.ProcessAttrCert2(certPath, pkixParams);
+			X509Certificate issuerCert = (X509Certificate)certPath.Certificates[0];
+			Rfc3281CertPathUtilities.ProcessAttrCert3(issuerCert, pkixParams);
+			Rfc3281CertPathUtilities.ProcessAttrCert4(issuerCert, pkixParams);
+			Rfc3281CertPathUtilities.ProcessAttrCert5(attrCert, pkixParams);
+			// 6 already done in X509AttrCertStoreSelector
+			Rfc3281CertPathUtilities.ProcessAttrCert7(attrCert, certPath, holderCertPath, pkixParams);
+			Rfc3281CertPathUtilities.AdditionalChecks(attrCert, pkixParams);
+			DateTime date;
+			try
+			{
+				date = PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(pkixParams, null, -1);
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Could not get validity date from attribute certificate.", e);
+			}
+			Rfc3281CertPathUtilities.CheckCrls(attrCert, pkixParams, issuerCert, date, certPath.Certificates);
+			return result;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixBuilderParameters.cs b/BouncyCastle.AxCrypt/src/pkix/PkixBuilderParameters.cs
new file mode 100644
index 0000000..32fc043
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixBuilderParameters.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509.Store;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+    /// Summary description for PkixBuilderParameters.
+	/// </summary>
+	public class PkixBuilderParameters
+		: PkixParameters
+	{
+		private int maxPathLength = 5;
+
+		private ISet excludedCerts = new HashSet();
+
+		/**
+		* Returns an instance of <code>PkixBuilderParameters</code>.
+		* <p>
+		* This method can be used to get a copy from other
+		* <code>PKIXBuilderParameters</code>, <code>PKIXParameters</code>,
+		* and <code>ExtendedPKIXParameters</code> instances.
+		* </p>
+		*
+		* @param pkixParams The PKIX parameters to create a copy of.
+		* @return An <code>PkixBuilderParameters</code> instance.
+		*/
+		public static PkixBuilderParameters GetInstance(
+			PkixParameters pkixParams)
+		{
+			PkixBuilderParameters parameters = new PkixBuilderParameters(
+				pkixParams.GetTrustAnchors(),
+				new X509CertStoreSelector(pkixParams.GetTargetCertConstraints()));
+			parameters.SetParams(pkixParams);
+			return parameters;
+		}
+
+		public PkixBuilderParameters(
+			ISet			trustAnchors,
+			IX509Selector	targetConstraints)
+			: base(trustAnchors)
+		{
+			SetTargetCertConstraints(targetConstraints);
+		}
+
+		public virtual int MaxPathLength
+		{
+			get { return maxPathLength; }
+			set
+			{
+				if (value < -1)
+				{
+					throw new InvalidParameterException(
+						"The maximum path length parameter can not be less than -1.");
+				}
+				this.maxPathLength = value;
+			}
+		}
+
+		/// <summary>
+		/// Excluded certificates are not used for building a certification path.
+		/// </summary>
+		/// <returns>the excluded certificates.</returns>
+		public virtual ISet GetExcludedCerts()
+		{
+			return new HashSet(excludedCerts);
+		}
+
+		/// <summary>
+		/// Sets the excluded certificates which are not used for building a
+		/// certification path. If the <code>ISet</code> is <code>null</code> an
+		/// empty set is assumed.
+		/// </summary>
+		/// <remarks>
+		/// The given set is cloned to protect it against subsequent modifications.
+		/// </remarks>
+		/// <param name="excludedCerts">The excluded certificates to set.</param>
+		public virtual void SetExcludedCerts(
+			ISet excludedCerts)
+		{
+			if (excludedCerts == null)
+			{
+				excludedCerts = new HashSet();
+			}
+			else
+			{
+				this.excludedCerts = new HashSet(excludedCerts);
+			}
+		}
+
+		/**
+		* Can alse handle <code>ExtendedPKIXBuilderParameters</code> and
+		* <code>PKIXBuilderParameters</code>.
+		* 
+		* @param params Parameters to set.
+		* @see org.bouncycastle.x509.ExtendedPKIXParameters#setParams(java.security.cert.PKIXParameters)
+		*/
+		protected override void SetParams(
+			PkixParameters parameters)
+		{
+			base.SetParams(parameters);
+			if (parameters is PkixBuilderParameters)
+			{
+				PkixBuilderParameters _params = (PkixBuilderParameters) parameters;
+				maxPathLength = _params.maxPathLength;
+				excludedCerts = new HashSet(_params.excludedCerts);
+			}
+		}
+
+		/**
+		* Makes a copy of this <code>PKIXParameters</code> object. Changes to the
+		* copy will not affect the original and vice versa.
+		*
+		* @return a copy of this <code>PKIXParameters</code> object
+		*/
+		public override object Clone()
+		{
+			PkixBuilderParameters parameters = new PkixBuilderParameters(
+				GetTrustAnchors(), GetTargetCertConstraints());
+			parameters.SetParams(this);
+			return parameters;
+		}
+
+		public override string ToString()
+		{
+			string nl = Platform.NewLine;
+			StringBuilder s = new StringBuilder();
+			s.Append("PkixBuilderParameters [" + nl);
+			s.Append(base.ToString());
+			s.Append("  Maximum Path Length: ");
+			s.Append(MaxPathLength);
+			s.Append(nl + "]" + nl);
+			return s.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPath.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPath.cs
new file mode 100644
index 0000000..aca6b73
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPath.cs
@@ -0,0 +1,460 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/**
+	 * An immutable sequence of certificates (a certification path).<br />
+	 * <br />
+	 * This is an abstract class that defines the methods common to all CertPaths.
+	 * Subclasses can handle different kinds of certificates (X.509, PGP, etc.).<br />
+	 * <br />
+	 * All CertPath objects have a type, a list of Certificates, and one or more
+	 * supported encodings. Because the CertPath class is immutable, a CertPath
+	 * cannot change in any externally visible way after being constructed. This
+	 * stipulation applies to all public fields and methods of this class and any
+	 * added or overridden by subclasses.<br />
+	 * <br />
+	 * The type is a string that identifies the type of Certificates in the
+	 * certification path. For each certificate cert in a certification path
+	 * certPath, cert.getType().equals(certPath.getType()) must be true.<br />
+	 * <br />
+	 * The list of Certificates is an ordered List of zero or more Certificates.
+	 * This List and all of the Certificates contained in it must be immutable.<br />
+	 * <br />
+	 * Each CertPath object must support one or more encodings so that the object
+	 * can be translated into a byte array for storage or transmission to other
+	 * parties. Preferably, these encodings should be well-documented standards
+	 * (such as PKCS#7). One of the encodings supported by a CertPath is considered
+	 * the default encoding. This encoding is used if no encoding is explicitly
+	 * requested (for the {@link #getEncoded()} method, for instance).<br />
+	 * <br />
+	 * All CertPath objects are also Serializable. CertPath objects are resolved
+	 * into an alternate {@link CertPathRep} object during serialization. This
+	 * allows a CertPath object to be serialized into an equivalent representation
+	 * regardless of its underlying implementation.<br />
+	 * <br />
+	 * CertPath objects can be created with a CertificateFactory or they can be
+	 * returned by other classes, such as a CertPathBuilder.<br />
+	 * <br />
+	 * By convention, X.509 CertPaths (consisting of X509Certificates), are ordered
+	 * starting with the target certificate and ending with a certificate issued by
+	 * the trust anchor. That is, the issuer of one certificate is the subject of
+	 * the following one. The certificate representing the
+	 * {@link TrustAnchor TrustAnchor} should not be included in the certification
+	 * path. Unvalidated X.509 CertPaths may not follow these conventions. PKIX
+	 * CertPathValidators will detect any departure from these conventions that
+	 * cause the certification path to be invalid and throw a
+	 * CertPathValidatorException.<br />
+	 * <br />
+	 * <strong>Concurrent Access</strong><br />
+	 * <br />
+	 * All CertPath objects must be thread-safe. That is, multiple threads may
+	 * concurrently invoke the methods defined in this class on a single CertPath
+	 * object (or more than one) with no ill effects. This is also true for the List
+	 * returned by CertPath.getCertificates.<br />
+	 * <br />
+	 * Requiring CertPath objects to be immutable and thread-safe allows them to be
+	 * passed around to various pieces of code without worrying about coordinating
+	 * access. Providing this thread-safety is generally not difficult, since the
+	 * CertPath and List objects in question are immutable.
+	 *
+	 * @see CertificateFactory
+	 * @see CertPathBuilder
+	 */
+	/// <summary>
+	/// CertPath implementation for X.509 certificates.
+	/// </summary>
+	public class PkixCertPath
+//		: CertPath
+	{
+		internal static readonly IList certPathEncodings;
+
+        static PkixCertPath()
+        {
+            IList encodings = Platform.CreateArrayList();
+            encodings.Add("PkiPath");
+            encodings.Add("PEM");
+            encodings.Add("PKCS7");
+            certPathEncodings = CollectionUtilities.ReadOnly(encodings);
+        }
+
+        private readonly IList certificates;
+
+		/**
+		 * @param certs
+		 */
+		private static IList SortCerts(
+			IList certs)
+		{
+			if (certs.Count < 2)
+				return certs;
+
+			X509Name issuer = ((X509Certificate)certs[0]).IssuerDN;
+			bool okay = true;
+
+			for (int i = 1; i != certs.Count; i++)
+			{
+				X509Certificate cert = (X509Certificate)certs[i];
+
+				if (issuer.Equivalent(cert.SubjectDN, true))
+				{
+					issuer = ((X509Certificate)certs[i]).IssuerDN;
+				}
+				else
+				{
+					okay = false;
+					break;
+				}
+			}
+
+			if (okay)
+				return certs;
+
+			// find end-entity cert
+            IList retList = Platform.CreateArrayList(certs.Count);
+            IList orig = Platform.CreateArrayList(certs);
+
+			for (int i = 0; i < certs.Count; i++)
+			{
+				X509Certificate cert = (X509Certificate)certs[i];
+				bool           found = false;
+
+				X509Name subject = cert.SubjectDN;
+				foreach (X509Certificate c in certs)
+				{
+					if (c.IssuerDN.Equivalent(subject, true))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				if (!found)
+				{
+					retList.Add(cert);
+					certs.RemoveAt(i);
+				}
+			}
+
+			// can only have one end entity cert - something's wrong, give up.
+			if (retList.Count > 1)
+				return orig;
+
+			for (int i = 0; i != retList.Count; i++)
+			{
+				issuer = ((X509Certificate)retList[i]).IssuerDN;
+
+				for (int j = 0; j < certs.Count; j++)
+				{
+					X509Certificate c = (X509Certificate)certs[j];
+					if (issuer.Equivalent(c.SubjectDN, true))
+					{
+						retList.Add(c);
+						certs.RemoveAt(j);
+						break;
+					}
+				}
+			}
+
+			// make sure all certificates are accounted for.
+			if (certs.Count > 0)
+				return orig;
+
+			return retList;
+		}
+
+		/**
+		 * Creates a CertPath of the specified type.
+		 * This constructor is protected because most users should use
+		 * a CertificateFactory to create CertPaths.
+		 * @param type the standard name of the type of Certificatesin this path
+		 **/
+		public PkixCertPath(
+			ICollection certificates)
+//			: base("X.509")
+		{
+			this.certificates = SortCerts(Platform.CreateArrayList(certificates));
+		}
+
+		public PkixCertPath(
+			Stream inStream)
+			: this(inStream, "PkiPath")
+		{
+		}
+
+		/**
+		 * Creates a CertPath of the specified type.
+		 * This constructor is protected because most users should use
+		 * a CertificateFactory to create CertPaths.
+		 *
+		 * @param type the standard name of the type of Certificatesin this path
+		 **/
+		public PkixCertPath(
+			Stream	inStream,
+			string	encoding)
+//			: base("X.509")
+		{
+            string upper = encoding.ToUpper();
+
+            IList certs;
+			try
+			{
+				if (upper.Equals("PkiPath".ToUpper()))
+				{
+					Asn1InputStream derInStream = new Asn1InputStream(inStream);
+					Asn1Object derObject = derInStream.ReadObject();
+					if (!(derObject is Asn1Sequence))
+					{
+						throw new CertificateException(
+							"input stream does not contain a ASN1 SEQUENCE while reading PkiPath encoded data to load CertPath");
+					}
+
+                    certs = Platform.CreateArrayList();
+
+                    foreach (Asn1Encodable ae in (Asn1Sequence)derObject)
+                    {
+                        byte[] derBytes = ae.GetEncoded(Asn1Encodable.Der);
+                        Stream certInStream = new MemoryStream(derBytes, false);
+
+                        // TODO Is inserting at the front important (list will be sorted later anyway)?
+                        certs.Insert(0, new X509CertificateParser().ReadCertificate(certInStream));
+					}
+				}
+                else if (upper.Equals("PKCS7") || upper.Equals("PEM"))
+				{
+                    certs = Platform.CreateArrayList(new X509CertificateParser().ReadCertificates(inStream));
+				}
+				else
+				{
+					throw new CertificateException("unsupported encoding: " + encoding);
+				}
+			}
+			catch (IOException ex)
+			{
+				throw new CertificateException(
+					"IOException throw while decoding CertPath:\n"
+					+ ex.ToString());
+			}
+
+			this.certificates = SortCerts(certs);
+		}
+
+		/**
+		 * Returns an iteration of the encodings supported by this
+		 * certification path, with the default encoding
+		 * first. Attempts to modify the returned Iterator via its
+		 * remove method result in an UnsupportedOperationException.
+		 *
+		 * @return an Iterator over the names of the supported encodings (as Strings)
+		 **/
+		public virtual IEnumerable Encodings
+		{
+            get { return new EnumerableProxy(certPathEncodings); }
+		}
+
+		/**
+		* Compares this certification path for equality with the specified object.
+		* Two CertPaths are equal if and only if their types are equal and their
+		* certificate Lists (and by implication the Certificates in those Lists)
+		* are equal. A CertPath is never equal to an object that is not a CertPath.<br />
+		* <br />
+		* This algorithm is implemented by this method. If it is overridden, the
+		* behavior specified here must be maintained.
+		*
+		* @param other
+		*            the object to test for equality with this certification path
+		*
+		* @return true if the specified object is equal to this certification path,
+		*         false otherwise
+		*
+		* @see Object#hashCode() Object.hashCode()
+		*/
+		public override bool Equals(
+			object obj)
+		{
+			if (this == obj)
+				return true;
+
+			PkixCertPath other = obj as PkixCertPath;
+			if (other == null)
+				return false;
+
+//			if (!this.Type.Equals(other.Type))
+//				return false;
+
+			//return this.Certificates.Equals(other.Certificates);
+
+			// TODO Extract this to a utility class
+			IList thisCerts = this.Certificates;
+			IList otherCerts = other.Certificates;
+
+			if (thisCerts.Count != otherCerts.Count)
+				return false;
+
+			IEnumerator e1 = thisCerts.GetEnumerator();
+			IEnumerator e2 = thisCerts.GetEnumerator();
+
+			while (e1.MoveNext())
+			{
+				e2.MoveNext();
+
+				if (!Platform.Equals(e1.Current, e2.Current))
+					return false;
+			}
+
+			return true;
+		}
+
+		public override int GetHashCode()
+		{
+			// FIXME?
+			return this.Certificates.GetHashCode();
+		}
+
+		/**
+		 * Returns the encoded form of this certification path, using
+		 * the default encoding.
+		 *
+		 * @return the encoded bytes
+		 * @exception CertificateEncodingException if an encoding error occurs
+		 **/
+		public virtual byte[] GetEncoded()
+		{
+			foreach (object enc in Encodings)
+			{
+				if (enc is string)
+				{
+					return GetEncoded((string)enc);
+				}
+			}
+			return null;
+		}
+
+		/**
+		 * Returns the encoded form of this certification path, using
+		 * the specified encoding.
+		 *
+		 * @param encoding the name of the encoding to use
+		 * @return the encoded bytes
+		 * @exception CertificateEncodingException if an encoding error
+		 * occurs or the encoding requested is not supported
+		 *
+		 */
+		public virtual byte[] GetEncoded(
+			string encoding)
+		{
+			if (Platform.CompareIgnoreCase(encoding, "PkiPath") == 0)
+			{
+				Asn1EncodableVector v = new Asn1EncodableVector();
+
+				for (int i = certificates.Count - 1; i >= 0; i--)
+				{
+					v.Add(ToAsn1Object((X509Certificate) certificates[i]));
+				}
+
+				return ToDerEncoded(new DerSequence(v));
+			}
+            else if (Platform.CompareIgnoreCase(encoding, "PKCS7") == 0)
+			{
+				Asn1.Pkcs.ContentInfo encInfo = new Asn1.Pkcs.ContentInfo(
+					PkcsObjectIdentifiers.Data, null);
+
+				Asn1EncodableVector v = new Asn1EncodableVector();
+				for (int i = 0; i != certificates.Count; i++)
+				{
+					v.Add(ToAsn1Object((X509Certificate)certificates[i]));
+				}
+
+				Asn1.Pkcs.SignedData sd = new Asn1.Pkcs.SignedData(
+					new DerInteger(1),
+					new DerSet(),
+					encInfo,
+					new DerSet(v),
+					null,
+					new DerSet());
+
+				return ToDerEncoded(new Asn1.Pkcs.ContentInfo(PkcsObjectIdentifiers.SignedData, sd));
+			}
+            else if (Platform.CompareIgnoreCase(encoding, "PEM") == 0)
+			{
+				MemoryStream bOut = new MemoryStream();
+				PemWriter pWrt = new PemWriter(new StreamWriter(bOut));
+
+				try
+				{
+					for (int i = 0; i != certificates.Count; i++)
+					{
+						pWrt.WriteObject(certificates[i]);
+					}
+
+					pWrt.Writer.Dispose();
+				}
+				catch (Exception)
+				{
+					throw new CertificateEncodingException("can't encode certificate for PEM encoded path");
+				}
+
+				return bOut.ToArray();
+			}
+			else
+			{
+				throw new CertificateEncodingException("unsupported encoding: " + encoding);
+			}
+		}
+
+		/// <summary>
+		/// Returns the list of certificates in this certification
+		/// path.
+		/// </summary>
+		public virtual IList Certificates
+		{
+            get { return CollectionUtilities.ReadOnly(certificates); }
+		}
+
+		/**
+		 * Return a DERObject containing the encoded certificate.
+		 *
+		 * @param cert the X509Certificate object to be encoded
+		 *
+		 * @return the DERObject
+		 **/
+		private Asn1Object ToAsn1Object(
+			X509Certificate cert)
+		{
+			try
+			{
+				return Asn1Object.FromByteArray(cert.GetEncoded());
+			}
+			catch (Exception e)
+			{
+				throw new CertificateEncodingException("Exception while encoding certificate", e);
+			}
+		}
+
+		private byte[] ToDerEncoded(Asn1Encodable obj)
+		{
+			try
+			{
+				return obj.GetEncoded(Asn1Encodable.Der);
+			}
+			catch (IOException e)
+			{
+				throw new CertificateEncodingException("Exception thrown", e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilder.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilder.cs
new file mode 100644
index 0000000..7082fe4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilder.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Asn1.IsisMtt;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/**
+	* Implements the PKIX CertPathBuilding algorithm for BouncyCastle.
+	*
+	* @see CertPathBuilderSpi
+	*/
+	public class PkixCertPathBuilder
+		//		: CertPathBuilderSpi
+	{
+		/**
+		 * Build and validate a CertPath using the given parameter.
+		 *
+		 * @param params PKIXBuilderParameters object containing all information to
+		 *            build the CertPath
+		 */
+		public virtual PkixCertPathBuilderResult Build(
+			PkixBuilderParameters pkixParams)
+		{
+			// search target certificates
+
+			IX509Selector certSelect = pkixParams.GetTargetCertConstraints();
+			if (!(certSelect is X509CertStoreSelector))
+			{
+				throw new PkixCertPathBuilderException(
+					"TargetConstraints must be an instance of "
+					+ typeof(X509CertStoreSelector).FullName + " for "
+					+ this.GetType() + " class.");
+			}
+
+			ISet targets = new HashSet();
+			try
+			{
+				targets.AddAll(PkixCertPathValidatorUtilities.FindCertificates((X509CertStoreSelector)certSelect, pkixParams.GetStores()));
+				// TODO Should this include an entry for pkixParams.GetAdditionalStores() too?
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathBuilderException(
+					"Error finding target certificate.", e);
+			}
+
+			if (targets.IsEmpty)
+				throw new PkixCertPathBuilderException("No certificate found matching targetContraints.");
+
+			PkixCertPathBuilderResult result = null;
+			IList certPathList = Platform.CreateArrayList();
+
+			// check all potential target certificates
+			foreach (X509Certificate cert in targets)
+			{
+				result = Build(cert, pkixParams, certPathList);
+
+				if (result != null)
+					break;
+			}
+
+			if (result == null && certPathException != null)
+			{
+				throw new PkixCertPathBuilderException(certPathException.Message, certPathException.InnerException);
+			}
+
+			if (result == null && certPathException == null)
+			{
+				throw new PkixCertPathBuilderException("Unable to find certificate chain.");
+			}
+
+			return result;
+		}
+
+		private Exception certPathException;
+
+		protected virtual PkixCertPathBuilderResult Build(
+			X509Certificate			tbvCert,
+			PkixBuilderParameters	pkixParams,
+			IList					tbvPath)
+		{
+			// If tbvCert is readily present in tbvPath, it indicates having run
+			// into a cycle in the PKI graph.
+			if (tbvPath.Contains(tbvCert))
+				return null;
+
+			// step out, the certificate is not allowed to appear in a certification
+			// chain.
+			if (pkixParams.GetExcludedCerts().Contains(tbvCert))
+				return null;
+
+			// test if certificate path exceeds maximum length
+			if (pkixParams.MaxPathLength != -1)
+			{
+				if (tbvPath.Count - 1 > pkixParams.MaxPathLength)
+					return null;
+			}
+
+			tbvPath.Add(tbvCert);
+
+//			X509CertificateParser certParser = new X509CertificateParser();
+			PkixCertPathBuilderResult builderResult = null;
+			PkixCertPathValidator validator = new PkixCertPathValidator();
+
+			try
+			{
+				// check whether the issuer of <tbvCert> is a TrustAnchor
+				if (PkixCertPathValidatorUtilities.FindTrustAnchor(tbvCert, pkixParams.GetTrustAnchors()) != null)
+				{
+					// exception message from possibly later tried certification
+					// chains
+					PkixCertPath certPath = null;
+					try
+					{
+						certPath = new PkixCertPath(tbvPath);
+					}
+					catch (Exception e)
+					{
+						throw new Exception(
+							"Certification path could not be constructed from certificate list.",
+							e);
+					}
+
+					PkixCertPathValidatorResult result = null;
+					try
+					{
+						result = (PkixCertPathValidatorResult)validator.Validate(
+							certPath, pkixParams);
+					}
+					catch (Exception e)
+					{
+						throw new Exception(
+							"Certification path could not be validated.", e);
+					}
+
+					return new PkixCertPathBuilderResult(certPath, result.TrustAnchor,
+						result.PolicyTree, result.SubjectPublicKey);
+				}
+				else
+				{
+					// add additional X.509 stores from locations in certificate
+					try
+					{
+						PkixCertPathValidatorUtilities.AddAdditionalStoresFromAltNames(
+							tbvCert, pkixParams);
+					}
+					catch (CertificateParsingException e)
+					{
+						throw new Exception(
+							"No additiontal X.509 stores can be added from certificate locations.",
+							e);
+					}
+
+					// try to get the issuer certificate from one of the stores
+					HashSet issuers = new HashSet();
+					try
+					{
+						issuers.AddAll(PkixCertPathValidatorUtilities.FindIssuerCerts(tbvCert, pkixParams));
+					}
+					catch (Exception e)
+					{
+						throw new Exception(
+							"Cannot find issuer certificate for certificate in certification path.",
+							e);
+					}
+
+					if (issuers.IsEmpty)
+						throw new Exception("No issuer certificate for certificate in certification path found.");
+
+					foreach (X509Certificate issuer in issuers)
+					{
+						builderResult = Build(issuer, pkixParams, tbvPath);
+
+						if (builderResult != null)
+							break;
+					}
+				}
+			}
+			catch (Exception e)
+			{
+				certPathException = e;
+			}
+
+			if (builderResult == null)
+			{
+				tbvPath.Remove(tbvCert);
+			}
+
+			return builderResult;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderException.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderException.cs
new file mode 100644
index 0000000..5a4944d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderException.cs
@@ -0,0 +1,22 @@
+using System;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixCertPathBuilderException.
+	/// </summary>
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PkixCertPathBuilderException : GeneralSecurityException
+	{
+		public PkixCertPathBuilderException() : base() { }
+		
+		public PkixCertPathBuilderException(string message) : base(message)	{ }  
+
+		public PkixCertPathBuilderException(string message, Exception exception) : base(message, exception) { }
+		
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderResult.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderResult.cs
new file mode 100644
index 0000000..f800303
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathBuilderResult.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkix;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixCertPathBuilderResult.
+	/// </summary>
+	public class PkixCertPathBuilderResult
+		: PkixCertPathValidatorResult//, ICertPathBuilderResult
+	{
+		private PkixCertPath certPath;
+		
+		public PkixCertPathBuilderResult(
+			PkixCertPath			certPath,
+			TrustAnchor				trustAnchor,
+			PkixPolicyNode			policyTree,
+			AsymmetricKeyParameter	subjectPublicKey)
+			: base(trustAnchor, policyTree, subjectPublicKey)
+		{			
+			if (certPath == null)
+				throw new ArgumentNullException("certPath");
+
+			this.certPath = certPath;
+		}
+
+		public PkixCertPath CertPath
+		{
+            get { return certPath; }
+		}
+
+		public override string ToString()
+		{
+			StringBuilder s = new StringBuilder();
+			s.Append("SimplePKIXCertPathBuilderResult: [\n");
+			s.Append("  Certification Path: ").Append(CertPath).Append('\n');
+			s.Append("  Trust Anchor: ").Append(this.TrustAnchor.TrustedCert.IssuerDN.ToString()).Append('\n');
+			s.Append("  Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]");
+			return s.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathChecker.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathChecker.cs
new file mode 100644
index 0000000..f22738d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathChecker.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkix
+{
+    public abstract class PkixCertPathChecker
+    {
+        protected PkixCertPathChecker()
+        {
+        }
+
+        /**
+         * Initializes the internal state of this <code>PKIXCertPathChecker</code>.
+         * <p>
+         * The <code>forward</code> flag specifies the order that certificates
+         * will be passed to the {@link #check check} method (forward or reverse). A
+         * <code>PKIXCertPathChecker</code> <b>must</b> support reverse checking
+         * and <b>may</b> support forward checking.
+		 * </p>
+         * 
+         * @param forward
+         *            the order that certificates are presented to the
+         *            <code>check</code> method. If <code>true</code>,
+         *            certificates are presented from target to most-trusted CA
+         *            (forward); if <code>false</code>, from most-trusted CA to
+         *            target (reverse).
+         * @exception CertPathValidatorException
+         *                if this <code>PKIXCertPathChecker</code> is unable to
+         *                check certificates in the specified order; it should never
+         *                be thrown if the forward flag is false since reverse
+         *                checking must be supported
+         */
+        public abstract void Init(bool forward);
+        //throws CertPathValidatorException;
+
+        /**
+         * Indicates if forward checking is supported. Forward checking refers to
+         * the ability of the <code>PKIXCertPathChecker</code> to perform its
+         * checks when certificates are presented to the <code>check</code> method
+         * in the forward direction (from target to most-trusted CA).
+         * 
+         * @return <code>true</code> if forward checking is supported,
+         *         <code>false</code> otherwise
+         */
+        public abstract bool IsForwardCheckingSupported();
+
+        /**
+         * Returns an immutable <code>Set</code> of X.509 certificate extensions
+         * that this <code>PKIXCertPathChecker</code> supports (i.e. recognizes,
+         * is able to process), or <code>null</code> if no extensions are
+         * supported.
+         * <p>
+         * Each element of the set is a <code>String</code> representing the
+         * Object Identifier (OID) of the X.509 extension that is supported. The OID
+         * is represented by a set of nonnegative integers separated by periods.
+         * </p><p>
+         * All X.509 certificate extensions that a <code>PKIXCertPathChecker</code>
+         * might possibly be able to process should be included in the set.
+		 * </p>
+         * 
+         * @return an immutable <code>Set</code> of X.509 extension OIDs (in
+         *         <code>String</code> format) supported by this
+         *         <code>PKIXCertPathChecker</code>, or <code>null</code> if no
+         *         extensions are supported
+         */
+        public abstract ISet GetSupportedExtensions();
+
+        /**
+         * Performs the check(s) on the specified certificate using its internal
+         * state and removes any critical extensions that it processes from the
+         * specified collection of OID strings that represent the unresolved
+         * critical extensions. The certificates are presented in the order
+         * specified by the <code>init</code> method.
+         * 
+         * @param cert
+         *            the <code>Certificate</code> to be checked
+         * @param unresolvedCritExts
+         *            a <code>Collection</code> of OID strings representing the
+         *            current set of unresolved critical extensions
+         * @exception CertPathValidatorException
+         *                if the specified certificate does not pass the check
+         */
+        public abstract void Check(X509Certificate cert, ICollection unresolvedCritExts);
+        //throws CertPathValidatorException;
+
+        /**
+         * Returns a clone of this object. Calls the <code>Object.clone()</code>
+         * method. All subclasses which maintain state must support and override
+         * this method, if necessary.
+         * 
+         * @return a copy of this <code>PKIXCertPathChecker</code>
+         */
+        public virtual object Clone()
+        {
+			// TODO Check this
+			return base.MemberwiseClone();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidator.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidator.cs
new file mode 100644
index 0000000..550699e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidator.cs
@@ -0,0 +1,420 @@
+using System;
+using System.Collections;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/**
+	 * The <i>Service Provider Interface</i> (<b>SPI</b>)
+	 * for the {@link CertPathValidator CertPathValidator} class. All
+	 * <code>CertPathValidator</code> implementations must include a class (the
+	 * SPI class) that extends this class (<code>CertPathValidatorSpi</code>)
+	 * and implements all of its methods. In general, instances of this class
+	 * should only be accessed through the <code>CertPathValidator</code> class.
+	 * For details, see the Java Cryptography Architecture.<br />
+	 * <br />
+	 * <b>Concurrent Access</b><br />
+	 * <br />
+	 * Instances of this class need not be protected against concurrent
+	 * access from multiple threads. Threads that need to access a single
+	 * <code>CertPathValidatorSpi</code> instance concurrently should synchronize
+	 * amongst themselves and provide the necessary locking before calling the
+	 * wrapping <code>CertPathValidator</code> object.<br />
+	 * <br />
+	 * However, implementations of <code>CertPathValidatorSpi</code> may still
+	 * encounter concurrency issues, since multiple threads each
+	 * manipulating a different <code>CertPathValidatorSpi</code> instance need not
+	 * synchronize.
+	 */
+	/// <summary>
+    /// CertPathValidatorSpi implementation for X.509 Certificate validation a la RFC
+    /// 3280.
+    /// </summary>
+    public class PkixCertPathValidator
+    {
+        public virtual PkixCertPathValidatorResult Validate(
+			PkixCertPath	certPath,
+			PkixParameters	paramsPkix)
+        {
+			if (paramsPkix.GetTrustAnchors() == null)
+            {
+                throw new ArgumentException(
+					"trustAnchors is null, this is not allowed for certification path validation.",
+					"parameters");
+            }
+
+            //
+            // 6.1.1 - inputs
+            //
+
+            //
+            // (a)
+            //
+            IList certs = certPath.Certificates;
+            int n = certs.Count;
+
+            if (certs.Count == 0)
+                throw new PkixCertPathValidatorException("Certification path is empty.", null, certPath, 0);
+
+			//
+            // (b)
+            //
+            // DateTime validDate = PkixCertPathValidatorUtilities.GetValidDate(paramsPkix);
+
+            //
+            // (c)
+            //
+            ISet userInitialPolicySet = paramsPkix.GetInitialPolicies();
+
+            //
+            // (d)
+            //
+            TrustAnchor trust;
+            try
+            {
+                trust = PkixCertPathValidatorUtilities.FindTrustAnchor(
+					(X509Certificate)certs[certs.Count - 1],
+					paramsPkix.GetTrustAnchors());
+            }
+            catch (Exception e)
+            {
+                throw new PkixCertPathValidatorException(e.Message, e, certPath, certs.Count - 1);
+            }
+
+            if (trust == null)
+                throw new PkixCertPathValidatorException("Trust anchor for certification path not found.", null, certPath, -1);
+
+			//
+            // (e), (f), (g) are part of the paramsPkix object.
+            //
+            IEnumerator certIter;
+            int index = 0;
+            int i;
+            // Certificate for each interation of the validation loop
+            // Signature information for each iteration of the validation loop
+            //
+            // 6.1.2 - setup
+            //
+
+            //
+            // (a)
+            //
+            IList[] policyNodes = new IList[n + 1];
+            for (int j = 0; j < policyNodes.Length; j++)
+            {
+                policyNodes[j] = Platform.CreateArrayList();
+            }
+
+            ISet policySet = new HashSet();
+
+            policySet.Add(Rfc3280CertPathUtilities.ANY_POLICY);
+
+            PkixPolicyNode validPolicyTree = new PkixPolicyNode(Platform.CreateArrayList(), 0, policySet, null, new HashSet(),
+                    Rfc3280CertPathUtilities.ANY_POLICY, false);
+
+            policyNodes[0].Add(validPolicyTree);
+
+            //
+            // (b) and (c)
+            //
+            PkixNameConstraintValidator nameConstraintValidator = new PkixNameConstraintValidator();
+
+            // (d)
+            //
+            int explicitPolicy;
+            ISet acceptablePolicies = new HashSet();
+
+            if (paramsPkix.IsExplicitPolicyRequired)
+            {
+                explicitPolicy = 0;
+            }
+            else
+            {
+                explicitPolicy = n + 1;
+            }
+
+            //
+            // (e)
+            //
+            int inhibitAnyPolicy;
+
+            if (paramsPkix.IsAnyPolicyInhibited)
+            {
+                inhibitAnyPolicy = 0;
+            }
+            else
+            {
+                inhibitAnyPolicy = n + 1;
+            }
+
+            //
+            // (f)
+            //
+            int policyMapping;
+
+            if (paramsPkix.IsPolicyMappingInhibited)
+            {
+                policyMapping = 0;
+            }
+            else
+            {
+                policyMapping = n + 1;
+            }
+
+            //
+            // (g), (h), (i), (j)
+            //
+            AsymmetricKeyParameter workingPublicKey;
+            X509Name workingIssuerName;
+
+            X509Certificate sign = trust.TrustedCert;
+            try
+            {
+                if (sign != null)
+                {
+                    workingIssuerName = sign.SubjectDN;
+                    workingPublicKey = sign.GetPublicKey();
+                }
+                else
+                {
+                    workingIssuerName = new X509Name(trust.CAName);
+                    workingPublicKey = trust.CAPublicKey;
+                }
+            }
+            catch (ArgumentException ex)
+            {
+                throw new PkixCertPathValidatorException("Subject of trust anchor could not be (re)encoded.", ex, certPath,
+                        -1);
+            }
+
+            //AlgorithmIdentifier workingAlgId = null;
+            try
+            {
+                /*workingAlgId = */PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
+            }
+            catch (PkixCertPathValidatorException e)
+            {
+                throw new PkixCertPathValidatorException(
+                        "Algorithm identifier of public key of trust anchor could not be read.", e, certPath, -1);
+            }
+
+//			DerObjectIdentifier workingPublicKeyAlgorithm = workingAlgId.ObjectID;
+//			Asn1Encodable workingPublicKeyParameters = workingAlgId.Parameters;
+
+            //
+            // (k)
+            //
+            int maxPathLength = n;
+
+            //
+            // 6.1.3
+            //
+
+			X509CertStoreSelector certConstraints = paramsPkix.GetTargetCertConstraints();
+            if (certConstraints != null && !certConstraints.Match((X509Certificate)certs[0]))
+            {
+                throw new PkixCertPathValidatorException(
+					"Target certificate in certification path does not match targetConstraints.", null, certPath, 0);
+            }
+
+            //
+            // initialize CertPathChecker's
+            //
+            IList pathCheckers = paramsPkix.GetCertPathCheckers();
+            certIter = pathCheckers.GetEnumerator();
+
+            while (certIter.MoveNext())
+            {
+                ((PkixCertPathChecker)certIter.Current).Init(false);
+            }
+
+            X509Certificate cert = null;
+
+            for (index = certs.Count - 1; index >= 0; index--)
+            {
+                // try
+                // {
+                //
+                // i as defined in the algorithm description
+                //
+                i = n - index;
+
+                //
+                // set certificate to be checked in this round
+                // sign and workingPublicKey and workingIssuerName are set
+                // at the end of the for loop and initialized the
+                // first time from the TrustAnchor
+                //
+                cert = (X509Certificate)certs[index];
+
+                //
+                // 6.1.3
+                //
+
+                Rfc3280CertPathUtilities.ProcessCertA(certPath, paramsPkix, index, workingPublicKey,
+					workingIssuerName, sign);
+
+                Rfc3280CertPathUtilities.ProcessCertBC(certPath, index, nameConstraintValidator);
+
+                validPolicyTree = Rfc3280CertPathUtilities.ProcessCertD(certPath, index,
+					acceptablePolicies, validPolicyTree, policyNodes, inhibitAnyPolicy);
+
+                validPolicyTree = Rfc3280CertPathUtilities.ProcessCertE(certPath, index, validPolicyTree);
+
+                Rfc3280CertPathUtilities.ProcessCertF(certPath, index, validPolicyTree, explicitPolicy);
+
+                //
+                // 6.1.4
+                //
+
+                if (i != n)
+                {
+                    if (cert != null && cert.Version == 1)
+                    {
+                        throw new PkixCertPathValidatorException(
+							"Version 1 certificates can't be used as CA ones.", null, certPath, index);
+                    }
+
+                    Rfc3280CertPathUtilities.PrepareNextCertA(certPath, index);
+
+                    validPolicyTree = Rfc3280CertPathUtilities.PrepareCertB(certPath, index, policyNodes,
+						validPolicyTree, policyMapping);
+
+                    Rfc3280CertPathUtilities.PrepareNextCertG(certPath, index, nameConstraintValidator);
+
+                    // (h)
+                    explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertH1(certPath, index, explicitPolicy);
+                    policyMapping = Rfc3280CertPathUtilities.PrepareNextCertH2(certPath, index, policyMapping);
+                    inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertH3(certPath, index, inhibitAnyPolicy);
+
+                    //
+                    // (i)
+                    //
+                    explicitPolicy = Rfc3280CertPathUtilities.PrepareNextCertI1(certPath, index, explicitPolicy);
+                    policyMapping = Rfc3280CertPathUtilities.PrepareNextCertI2(certPath, index, policyMapping);
+
+                    // (j)
+                    inhibitAnyPolicy = Rfc3280CertPathUtilities.PrepareNextCertJ(certPath, index, inhibitAnyPolicy);
+
+                    // (k)
+                    Rfc3280CertPathUtilities.PrepareNextCertK(certPath, index);
+
+                    // (l)
+                    maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertL(certPath, index, maxPathLength);
+
+                    // (m)
+                    maxPathLength = Rfc3280CertPathUtilities.PrepareNextCertM(certPath, index, maxPathLength);
+
+                    // (n)
+                    Rfc3280CertPathUtilities.PrepareNextCertN(certPath, index);
+
+					ISet criticalExtensions1 = cert.GetCriticalExtensionOids();
+
+					if (criticalExtensions1 != null)
+					{
+						criticalExtensions1 = new HashSet(criticalExtensions1);
+
+						// these extensions are handled by the algorithm
+						criticalExtensions1.Remove(X509Extensions.KeyUsage.Id);
+						criticalExtensions1.Remove(X509Extensions.CertificatePolicies.Id);
+						criticalExtensions1.Remove(X509Extensions.PolicyMappings.Id);
+						criticalExtensions1.Remove(X509Extensions.InhibitAnyPolicy.Id);
+						criticalExtensions1.Remove(X509Extensions.IssuingDistributionPoint.Id);
+						criticalExtensions1.Remove(X509Extensions.DeltaCrlIndicator.Id);
+						criticalExtensions1.Remove(X509Extensions.PolicyConstraints.Id);
+						criticalExtensions1.Remove(X509Extensions.BasicConstraints.Id);
+						criticalExtensions1.Remove(X509Extensions.SubjectAlternativeName.Id);
+						criticalExtensions1.Remove(X509Extensions.NameConstraints.Id);
+					}
+					else
+					{
+						criticalExtensions1 = new HashSet();
+					}
+
+					// (o)
+					Rfc3280CertPathUtilities.PrepareNextCertO(certPath, index, criticalExtensions1, pathCheckers);
+
+					// set signing certificate for next round
+                    sign = cert;
+
+                    // (c)
+                    workingIssuerName = sign.SubjectDN;
+
+                    // (d)
+                    try
+                    {
+                        workingPublicKey = PkixCertPathValidatorUtilities.GetNextWorkingKey(certPath.Certificates, index);
+                    }
+                    catch (PkixCertPathValidatorException e)
+                    {
+                        throw new PkixCertPathValidatorException("Next working key could not be retrieved.", e, certPath, index);
+                    }
+
+                    /*workingAlgId = */PkixCertPathValidatorUtilities.GetAlgorithmIdentifier(workingPublicKey);
+                    // (f)
+//                    workingPublicKeyAlgorithm = workingAlgId.ObjectID;
+                    // (e)
+//                    workingPublicKeyParameters = workingAlgId.Parameters;
+                }
+            }
+
+            //
+            // 6.1.5 Wrap-up procedure
+            //
+
+            explicitPolicy = Rfc3280CertPathUtilities.WrapupCertA(explicitPolicy, cert);
+
+            explicitPolicy = Rfc3280CertPathUtilities.WrapupCertB(certPath, index + 1, explicitPolicy);
+
+            //
+            // (c) (d) and (e) are already done
+            //
+
+            //
+            // (f)
+            //
+            ISet criticalExtensions = cert.GetCriticalExtensionOids();
+
+            if (criticalExtensions != null)
+            {
+                criticalExtensions = new HashSet(criticalExtensions);
+
+                // Requires .Id
+                // these extensions are handled by the algorithm
+                criticalExtensions.Remove(X509Extensions.KeyUsage.Id);
+                criticalExtensions.Remove(X509Extensions.CertificatePolicies.Id);
+                criticalExtensions.Remove(X509Extensions.PolicyMappings.Id);
+                criticalExtensions.Remove(X509Extensions.InhibitAnyPolicy.Id);
+                criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
+                criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);
+                criticalExtensions.Remove(X509Extensions.PolicyConstraints.Id);
+                criticalExtensions.Remove(X509Extensions.BasicConstraints.Id);
+                criticalExtensions.Remove(X509Extensions.SubjectAlternativeName.Id);
+                criticalExtensions.Remove(X509Extensions.NameConstraints.Id);
+                criticalExtensions.Remove(X509Extensions.CrlDistributionPoints.Id);
+            }
+            else
+            {
+                criticalExtensions = new HashSet();
+            }
+
+            Rfc3280CertPathUtilities.WrapupCertF(certPath, index + 1, pathCheckers, criticalExtensions);
+
+            PkixPolicyNode intersection = Rfc3280CertPathUtilities.WrapupCertG(certPath, paramsPkix, userInitialPolicySet,
+                    index + 1, policyNodes, validPolicyTree, acceptablePolicies);
+
+            if ((explicitPolicy > 0) || (intersection != null))
+            {
+				return new PkixCertPathValidatorResult(trust, intersection, cert.GetPublicKey());
+			}
+
+			throw new PkixCertPathValidatorException("Path processing failed on policy.", null, certPath, index);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorException.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorException.cs
new file mode 100644
index 0000000..35522c6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorException.cs
@@ -0,0 +1,221 @@
+using System;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/**
+	 * An exception indicating one of a variety of problems encountered when 
+	 * validating a certification path. <br />
+	 * <br />
+	 * A <code>CertPathValidatorException</code> provides support for wrapping
+	 * exceptions. The {@link #getCause getCause} method returns the throwable, 
+	 * if any, that caused this exception to be thrown. <br />
+	 * <br />
+	 * A <code>CertPathValidatorException</code> may also include the 
+	 * certification path that was being validated when the exception was thrown 
+	 * and the index of the certificate in the certification path that caused the 
+	 * exception to be thrown. Use the {@link #getCertPath getCertPath} and
+	 * {@link #getIndex getIndex} methods to retrieve this information.<br />
+	 * <br />
+	 * <b>Concurrent Access</b><br />
+	 * <br />
+	 * Unless otherwise specified, the methods defined in this class are not
+	 * thread-safe. Multiple threads that need to access a single
+	 * object concurrently should synchronize amongst themselves and
+	 * provide the necessary locking. Multiple threads each manipulating
+	 * separate objects need not synchronize.
+	 *
+	 * @see CertPathValidator
+	 **/
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PkixCertPathValidatorException
+        : GeneralSecurityException
+	{
+		private Exception cause;
+		private PkixCertPath certPath;
+		private int index = -1;
+
+		public PkixCertPathValidatorException() : base() { }
+
+		/// <summary>
+		/// Creates a <code>PkixCertPathValidatorException</code> with the given detail
+		/// message. A detail message is a <code>String</code> that describes this
+		/// particular exception. 
+		/// </summary>
+		/// <param name="message">the detail message</param>
+		public PkixCertPathValidatorException(string message) : base(message) { }
+
+		/// <summary>
+		/// Creates a <code>PkixCertPathValidatorException</code> with the specified
+		/// detail message and cause.
+		/// </summary>
+		/// <param name="message">the detail message</param>
+		/// <param name="cause">the cause (which is saved for later retrieval by the
+		/// {@link #getCause getCause()} method). (A <code>null</code>
+		/// value is permitted, and indicates that the cause is
+		/// nonexistent or unknown.)</param>
+		public PkixCertPathValidatorException(string message, Exception cause) : base(message)
+		{
+			this.cause = cause;
+		}
+
+		/// <summary>
+		/// Creates a <code>PkixCertPathValidatorException</code> with the specified
+		/// detail message, cause, certification path, and index.
+		/// </summary>
+		/// <param name="message">the detail message (or <code>null</code> if none)</param>
+		/// <param name="cause">the cause (or <code>null</code> if none)</param>
+		/// <param name="certPath">the certification path that was in the process of being
+		/// validated when the error was encountered</param>
+		/// <param name="index">the index of the certificate in the certification path that</param>																																																																																   * 
+		public PkixCertPathValidatorException(
+			string			message,
+			Exception		cause,
+			PkixCertPath	certPath,
+			int				index)
+			: base(message)
+		{
+			if (certPath == null && index != -1)
+			{
+				throw new ArgumentNullException(
+					"certPath = null and index != -1");
+			}
+			if (index < -1
+				|| (certPath != null && index >= certPath.Certificates.Count))
+			{
+				throw new IndexOutOfRangeException(
+					" index < -1 or out of bound of certPath.getCertificates()");
+			}
+
+			this.cause = cause;
+			this.certPath = certPath;
+			this.index = index;
+		}
+
+		//
+		// Prints a stack trace to a <code>PrintWriter</code>, including the
+		// backtrace of the cause, if any.
+		// 
+		// @param pw
+		//            the <code>PrintWriter</code> to use for output
+		//
+		//		public void printStackTrace(PrintWriter pw)
+		//		{
+		//			super.printStackTrace(pw);
+		//			if (getCause() != null)
+		//			{
+		//				getCause().printStackTrace(pw);
+		//			}
+		//	}
+		//}
+
+
+		//	/**
+		//	 * Creates a <code>CertPathValidatorException</code> that wraps the
+		//	 * specified throwable. This allows any exception to be converted into a
+		//	 * <code>CertPathValidatorException</code>, while retaining information
+		//	 * about the wrapped exception, which may be useful for debugging. The
+		//	 * detail message is set to (<code>cause==null ? null : cause.toString()
+		//	 * </code>)
+		//	 * (which typically contains the class and detail message of cause).
+		//	 * 
+		//	 * @param cause
+		//	 *            the cause (which is saved for later retrieval by the
+		//	 *            {@link #getCause getCause()} method). (A <code>null</code>
+		//	 *            value is permitted, and indicates that the cause is
+		//	 *            nonexistent or unknown.)
+		//	 */
+		//	public PkixCertPathValidatorException(Throwable cause)
+		//	{
+		//		this.cause = cause;
+		//	}
+		//
+
+		/// <summary>
+		/// Returns the detail message for this <code>CertPathValidatorException</code>.
+		/// </summary>
+		/// <returns>the detail message, or <code>null</code> if neither the message nor cause were specified</returns>
+		public override string Message
+		{
+			get
+			{
+				string message = base.Message;
+
+				if (message != null)
+				{
+					return message;
+				}
+
+				if (cause != null)
+				{
+					return cause.Message;
+				}
+
+				return null;
+			}
+		}
+
+	/**
+	 * Returns the certification path that was being validated when the
+	 * exception was thrown.
+	 * 
+	 * @return the <code>CertPath</code> that was being validated when the
+	 *         exception was thrown (or <code>null</code> if not specified)
+	 */
+		public PkixCertPath CertPath
+		{
+			get { return certPath; }
+		}
+
+	/**
+	 * Returns the index of the certificate in the certification path that
+	 * caused the exception to be thrown. Note that the list of certificates in
+	 * a <code>CertPath</code> is zero based. If no index has been set, -1 is
+	 * returned.
+	 * 
+	 * @return the index that has been set, or -1 if none has been set
+	 */
+	public int Index
+	{
+        get { return index; }
+	}
+
+//	/**
+//	 * Returns the cause of this <code>CertPathValidatorException</code> or
+//	 * <code>null</code> if the cause is nonexistent or unknown.
+//	 * 
+//	 * @return the cause of this throwable or <code>null</code> if the cause
+//	 *         is nonexistent or unknown.
+//	 */
+//	public Throwable getCause()
+//	{
+//		return cause;
+//	}
+//
+//	/**
+//	 * Returns a string describing this exception, including a description of
+//	 * the internal (wrapped) cause if there is one.
+//	 * 
+//	 * @return a string representation of this
+//	 *         <code>CertPathValidatorException</code>
+//	 */
+//	public String toString()
+//	{
+//		StringBuffer sb = new StringBuffer();
+//		String s = getMessage();
+//		if (s != null)
+//		{
+//			sb.append(s);
+//		}
+//		if (getIndex() >= 0)
+//		{
+//			sb.append("index in certpath: ").append(getIndex()).append('\n');
+//			sb.append(getCertPath());
+//		}
+//		return sb.toString();
+//	}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorResult.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorResult.cs
new file mode 100644
index 0000000..c7d81c7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorResult.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixCertPathValidatorResult.
+	/// </summary>
+	public class PkixCertPathValidatorResult
+		//: ICertPathValidatorResult
+	{
+		private TrustAnchor trustAnchor;
+		private PkixPolicyNode policyTree;
+		private AsymmetricKeyParameter subjectPublicKey;
+
+		public PkixPolicyNode PolicyTree
+		{
+			get { return this.policyTree; }
+		}
+
+		public TrustAnchor TrustAnchor
+		{
+			get { return this.trustAnchor; }
+		}
+
+		public AsymmetricKeyParameter SubjectPublicKey
+		{
+			get { return this.subjectPublicKey; }
+		}
+
+		public PkixCertPathValidatorResult(
+			TrustAnchor				trustAnchor,
+			PkixPolicyNode			policyTree,
+			AsymmetricKeyParameter	subjectPublicKey)
+		{
+			if (subjectPublicKey == null)
+			{
+				throw new NullReferenceException("subjectPublicKey must be non-null");
+			}
+			if (trustAnchor == null)
+			{
+				throw new NullReferenceException("trustAnchor must be non-null");
+			}
+			
+			this.trustAnchor = trustAnchor;
+			this.policyTree = policyTree;
+			this.subjectPublicKey = subjectPublicKey;
+		}
+
+		public object Clone()
+		{
+			return new PkixCertPathValidatorResult(this.TrustAnchor, this.PolicyTree, this.SubjectPublicKey);
+		}
+
+		public override String ToString() 
+		{
+			StringBuilder sB = new StringBuilder();
+			sB.Append("PKIXCertPathValidatorResult: [ \n");
+			sB.Append("  Trust Anchor: ").Append(this.TrustAnchor).Append('\n');
+			sB.Append("  Policy Tree: ").Append(this.PolicyTree).Append('\n');
+			sB.Append("  Subject Public Key: ").Append(this.SubjectPublicKey).Append("\n]");
+			return sB.ToString();
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorUtilities.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorUtilities.cs
new file mode 100644
index 0000000..f4ae510
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCertPathValidatorUtilities.cs
@@ -0,0 +1,1194 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.IsisMtt;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixCertPathValidatorUtilities.
+	/// </summary>
+	public class PkixCertPathValidatorUtilities
+	{
+		private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities();
+
+		internal static readonly string ANY_POLICY = "2.5.29.32.0";
+
+		internal static readonly string CRL_NUMBER = X509Extensions.CrlNumber.Id;
+
+		/// <summary>
+		/// key usage bits
+		/// </summary>
+		internal static readonly int KEY_CERT_SIGN = 5;
+		internal static readonly int CRL_SIGN = 6;
+
+		internal static readonly string[] crlReasons = new string[]
+		{
+			"unspecified",
+			"keyCompromise",
+			"cACompromise",
+			"affiliationChanged",
+			"superseded",
+			"cessationOfOperation",
+			"certificateHold",
+			"unknown",
+			"removeFromCRL",
+			"privilegeWithdrawn",
+			"aACompromise"
+		};
+
+		/// <summary>
+		/// Search the given Set of TrustAnchor's for one that is the
+		/// issuer of the given X509 certificate.
+		/// </summary>
+		/// <param name="cert">the X509 certificate</param>
+		/// <param name="trustAnchors">a Set of TrustAnchor's</param>
+		/// <returns>the <code>TrustAnchor</code> object if found or
+		/// <code>null</code> if not.
+		/// </returns>
+		/// @exception
+		internal static TrustAnchor FindTrustAnchor(
+			X509Certificate	cert,
+			ISet			trustAnchors)
+		{
+			IEnumerator iter = trustAnchors.GetEnumerator();
+			TrustAnchor trust = null;
+			AsymmetricKeyParameter trustPublicKey = null;
+			Exception invalidKeyEx = null;
+
+			X509CertStoreSelector certSelectX509 = new X509CertStoreSelector();
+
+			try
+			{
+				certSelectX509.Subject = GetIssuerPrincipal(cert);
+			}
+			catch (IOException ex)
+			{
+				throw new Exception("Cannot set subject search criteria for trust anchor.", ex);
+			}
+
+			while (iter.MoveNext() && trust == null)
+			{
+				trust = (TrustAnchor) iter.Current;
+				if (trust.TrustedCert != null)
+				{
+					if (certSelectX509.Match(trust.TrustedCert))
+					{
+						trustPublicKey = trust.TrustedCert.GetPublicKey();
+					}
+					else
+					{
+						trust = null;
+					}
+				}
+				else if (trust.CAName != null && trust.CAPublicKey != null)
+				{
+					try
+					{
+						X509Name certIssuer = GetIssuerPrincipal(cert);
+						X509Name caName = new X509Name(trust.CAName);
+
+						if (certIssuer.Equivalent(caName, true))
+						{
+							trustPublicKey = trust.CAPublicKey;
+						}
+						else
+						{
+							trust = null;
+						}
+					}
+					catch (InvalidParameterException)
+					{
+						trust = null;
+					}
+				}
+				else
+				{
+					trust = null;
+				}
+
+				if (trustPublicKey != null)
+				{
+					try
+					{
+						cert.Verify(trustPublicKey);
+					}
+					catch (Exception ex)
+					{
+						invalidKeyEx = ex;
+						trust = null;
+					}
+				}
+			}
+
+			if (trust == null && invalidKeyEx != null)
+			{
+				throw new Exception("TrustAnchor found but certificate validation failed.", invalidKeyEx);
+			}
+
+			return trust;
+		}
+
+		internal static void AddAdditionalStoresFromAltNames(
+			X509Certificate	cert,
+			PkixParameters	pkixParams)
+		{
+			// if in the IssuerAltName extension an URI
+			// is given, add an additinal X.509 store
+			if (cert.GetIssuerAlternativeNames() != null)
+			{
+				IEnumerator it = cert.GetIssuerAlternativeNames().GetEnumerator();
+				while (it.MoveNext())
+				{
+					// look for URI
+					IList list = (IList)it.Current;
+					//if (list[0].Equals(new Integer(GeneralName.UniformResourceIdentifier)))
+					if (list[0].Equals(GeneralName.UniformResourceIdentifier))
+					{
+						// found
+						string temp = (string)list[1];
+						PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation(temp, pkixParams);
+					}
+				}
+			}
+		}
+
+		internal static DateTime GetValidDate(PkixParameters paramsPKIX)
+		{
+			DateTimeObject validDate = paramsPKIX.Date;
+
+			if (validDate == null)
+				return DateTime.UtcNow;
+
+			return validDate.Value;
+		}
+
+		/// <summary>
+		/// Returns the issuer of an attribute certificate or certificate.
+		/// </summary>
+		/// <param name="cert">The attribute certificate or certificate.</param>
+		/// <returns>The issuer as <code>X500Principal</code>.</returns>
+		internal static X509Name GetIssuerPrincipal(
+			object cert)
+		{
+			if (cert is X509Certificate)
+			{
+				return ((X509Certificate)cert).IssuerDN;
+			}
+			else
+			{
+				return ((IX509AttributeCertificate)cert).Issuer.GetPrincipals()[0];
+			}
+		}
+
+		internal static bool IsSelfIssued(
+			X509Certificate cert)
+		{
+			return cert.SubjectDN.Equivalent(cert.IssuerDN, true);
+		}
+
+		internal static AlgorithmIdentifier GetAlgorithmIdentifier(
+			AsymmetricKeyParameter key)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(key);
+
+				return info.AlgorithmID;
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Subject public key cannot be decoded.", e);
+			}
+		}
+
+		internal static bool IsAnyPolicy(
+			ISet policySet)
+		{
+			return policySet == null || policySet.Contains(ANY_POLICY) || policySet.Count == 0;
+		}
+
+		internal static void AddAdditionalStoreFromLocation(
+			string			location,
+			PkixParameters	pkixParams)
+		{
+			if (pkixParams.IsAdditionalLocationsEnabled)
+			{
+				try
+				{
+					if (location.StartsWith("ldap://"))
+					{
+						// ldap://directory.d-trust.net/CN=D-TRUST
+						// Qualified CA 2003 1:PN,O=D-Trust GmbH,C=DE
+						// skip "ldap://"
+//						location = location.Substring(7);
+						// after first / baseDN starts
+//						string url;//, baseDN;
+//						int slashPos = location.IndexOf('/');
+//						if (slashPos != -1)
+//						{
+//							url = "ldap://" + location.Substring(0, slashPos);
+//							baseDN = location.Substring(slashPos);
+//						}
+//						else
+//						{
+//							url = "ldap://" + location;
+//							baseDN = nsull;
+//						}
+
+						throw Platform.CreateNotImplementedException("LDAP cert/CRL stores");
+
+						// use all purpose parameters
+						//X509LDAPCertStoreParameters ldapParams = new X509LDAPCertStoreParameters.Builder(
+						//                                url, baseDN).build();
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CERTIFICATE/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CRL/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "ATTRIBUTECERTIFICATE/LDAP", ldapParams));
+						//pkixParams.AddAdditionalStore(X509Store.getInstance(
+						//    "CERTIFICATEPAIR/LDAP", ldapParams));
+					}
+				}
+				catch (Exception)
+				{
+					// cannot happen
+					throw new Exception("Exception adding X.509 stores.");
+				}
+			}
+		}
+
+		private static BigInteger GetSerialNumber(
+			object cert)
+		{
+			if (cert is X509Certificate)
+			{
+				return ((X509Certificate)cert).SerialNumber;
+			}
+			else
+			{
+				return ((X509V2AttributeCertificate)cert).SerialNumber;
+			}
+		}
+
+		//
+		// policy checking
+		//
+
+		internal static ISet GetQualifierSet(Asn1Sequence qualifiers)
+		{
+			ISet pq = new HashSet();
+
+			if (qualifiers == null)
+			{
+				return pq;
+			}
+
+			foreach (Asn1Encodable ae in qualifiers)
+			{
+				try
+				{
+//					pq.Add(PolicyQualifierInfo.GetInstance(Asn1Object.FromByteArray(ae.GetEncoded())));
+					pq.Add(PolicyQualifierInfo.GetInstance(ae.ToAsn1Object()));
+				}
+				catch (IOException ex)
+				{
+					throw new PkixCertPathValidatorException("Policy qualifier info cannot be decoded.", ex);
+				}
+			}
+
+			return pq;
+		}
+
+		internal static PkixPolicyNode RemovePolicyNode(
+			PkixPolicyNode validPolicyTree,
+			IList[] policyNodes,
+			PkixPolicyNode _node)
+		{
+			PkixPolicyNode _parent = (PkixPolicyNode)_node.Parent;
+
+			if (validPolicyTree == null)
+			{
+				return null;
+			}
+
+			if (_parent == null)
+			{
+				for (int j = 0; j < policyNodes.Length; j++)
+				{
+                    policyNodes[j] = Platform.CreateArrayList();
+				}
+
+				return null;
+			}
+			else
+			{
+				_parent.RemoveChild(_node);
+				RemovePolicyNodeRecurse(policyNodes, _node);
+
+				return validPolicyTree;
+			}
+		}
+
+		private static void RemovePolicyNodeRecurse(IList[] policyNodes, PkixPolicyNode _node)
+		{
+			policyNodes[_node.Depth].Remove(_node);
+
+			if (_node.HasChildren)
+			{
+				foreach (PkixPolicyNode _child in _node.Children)
+				{
+					RemovePolicyNodeRecurse(policyNodes, _child);
+				}
+			}
+		}
+
+		internal static void PrepareNextCertB1(
+			int i,
+			IList[] policyNodes,
+			string id_p,
+			IDictionary m_idp,
+			X509Certificate cert)
+		{
+			bool idp_found = false;
+			IEnumerator nodes_i = policyNodes[i].GetEnumerator();
+			while (nodes_i.MoveNext())
+			{
+				PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
+				if (node.ValidPolicy.Equals(id_p))
+				{
+					idp_found = true;
+					node.ExpectedPolicies = (ISet)m_idp[id_p];
+					break;
+				}
+			}
+
+			if (!idp_found)
+			{
+				nodes_i = policyNodes[i].GetEnumerator();
+				while (nodes_i.MoveNext())
+				{
+					PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
+					if (ANY_POLICY.Equals(node.ValidPolicy))
+					{
+						ISet pq = null;
+						Asn1Sequence policies = null;
+						try
+						{
+							policies = DerSequence.GetInstance(GetExtensionValue(cert, X509Extensions.CertificatePolicies));
+						}
+						catch (Exception e)
+						{
+							throw new Exception("Certificate policies cannot be decoded.", e);
+						}
+
+						IEnumerator enm = policies.GetEnumerator();
+						while (enm.MoveNext())
+						{
+							PolicyInformation pinfo = null;
+
+							try
+							{
+								pinfo = PolicyInformation.GetInstance(enm.Current);
+							}
+							catch (Exception ex)
+							{
+								throw new Exception("Policy information cannot be decoded.", ex);
+							}
+
+							if (ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id))
+							{
+								try
+								{
+									pq = GetQualifierSet(pinfo.PolicyQualifiers);
+								}
+								catch (PkixCertPathValidatorException ex)
+								{
+									throw new PkixCertPathValidatorException(
+										"Policy qualifier info set could not be built.", ex);
+								}
+								break;
+							}
+						}
+						bool ci = false;
+						ISet critExtOids = cert.GetCriticalExtensionOids();
+						if (critExtOids != null)
+						{
+							ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id);
+						}
+
+						PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
+						if (ANY_POLICY.Equals(p_node.ValidPolicy))
+						{
+							PkixPolicyNode c_node = new PkixPolicyNode(
+                                Platform.CreateArrayList(), i,
+								(ISet)m_idp[id_p],
+								p_node, pq, id_p, ci);
+							p_node.AddChild(c_node);
+							policyNodes[i].Add(c_node);
+						}
+						break;
+					}
+				}
+			}
+		}
+
+		internal static PkixPolicyNode PrepareNextCertB2(
+			int				i,
+			IList[]			policyNodes,
+			string			id_p,
+			PkixPolicyNode	validPolicyTree)
+		{
+			int pos = 0;
+
+			// Copy to avoid RemoveAt calls interfering with enumeration
+            foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i]))
+			{
+				if (node.ValidPolicy.Equals(id_p))
+				{
+					PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
+					p_node.RemoveChild(node);
+
+					// Removal of element at current iterator position not supported in C#
+					//nodes_i.remove();
+					policyNodes[i].RemoveAt(pos);
+
+					for (int k = (i - 1); k >= 0; k--)
+					{
+						IList nodes = policyNodes[k];
+						for (int l = 0; l < nodes.Count; l++)
+						{
+							PkixPolicyNode node2 = (PkixPolicyNode)nodes[l];
+							if (!node2.HasChildren)
+							{
+								validPolicyTree = RemovePolicyNode(validPolicyTree, policyNodes, node2);
+								if (validPolicyTree == null)
+									break;
+							}
+						}
+					}
+				}
+				else
+				{
+					++pos;
+				}
+			}
+			return validPolicyTree;
+		}
+
+		internal static void GetCertStatus(
+			DateTime validDate,
+			X509Crl crl,
+			Object cert,
+			CertStatus certStatus)
+		{
+			X509Crl bcCRL = null;
+
+			try
+			{
+				bcCRL = new X509Crl(CertificateList.GetInstance((Asn1Sequence)Asn1Sequence.FromByteArray(crl.GetEncoded())));
+			}
+			catch (Exception exception)
+			{
+				throw new Exception("Bouncy Castle X509Crl could not be created.", exception);
+			}
+
+			X509CrlEntry crl_entry = (X509CrlEntry)bcCRL.GetRevokedCertificate(GetSerialNumber(cert));
+
+			if (crl_entry == null)
+				return;
+
+			X509Name issuer = GetIssuerPrincipal(cert);
+
+			if (issuer.Equivalent(crl_entry.GetCertificateIssuer(), true)
+				|| issuer.Equivalent(crl.IssuerDN, true))
+			{
+				DerEnumerated reasonCode = null;
+				if (crl_entry.HasExtensions)
+				{
+					try
+					{
+						reasonCode = DerEnumerated.GetInstance(
+							GetExtensionValue(crl_entry, X509Extensions.ReasonCode));
+					}
+					catch (Exception e)
+					{
+						throw new Exception(
+							"Reason code CRL entry extension could not be decoded.",
+							e);
+					}
+				}
+
+				// for reason keyCompromise, caCompromise, aACompromise or
+				// unspecified
+				if (!(validDate.Ticks < crl_entry.RevocationDate.Ticks)
+					|| reasonCode == null
+					|| reasonCode.Value.TestBit(0)
+					|| reasonCode.Value.TestBit(1)
+					|| reasonCode.Value.TestBit(2)
+					|| reasonCode.Value.TestBit(8))
+				{
+					if (reasonCode != null) // (i) or (j) (1)
+					{
+						certStatus.Status = reasonCode.Value.SignValue;
+					}
+					else // (i) or (j) (2)
+					{
+						certStatus.Status = CrlReason.Unspecified;
+					}
+					certStatus.RevocationDate = new DateTimeObject(crl_entry.RevocationDate);
+				}
+			}
+		}
+
+		/**
+		* Return the next working key inheriting DSA parameters if necessary.
+		* <p>
+		* This methods inherits DSA parameters from the indexed certificate or
+		* previous certificates in the certificate chain to the returned
+		* <code>PublicKey</code>. The list is searched upwards, meaning the end
+		* certificate is at position 0 and previous certificates are following.
+		* </p>
+		* <p>
+		* If the indexed certificate does not contain a DSA key this method simply
+		* returns the public key. If the DSA key already contains DSA parameters
+		* the key is also only returned.
+		* </p>
+		*
+		* @param certs The certification path.
+		* @param index The index of the certificate which contains the public key
+		*            which should be extended with DSA parameters.
+		* @return The public key of the certificate in list position
+		*         <code>index</code> extended with DSA parameters if applicable.
+		* @throws Exception if DSA parameters cannot be inherited.
+		*/
+		internal static AsymmetricKeyParameter GetNextWorkingKey(
+			IList	certs,
+			int		index)
+		{
+			//Only X509Certificate
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			AsymmetricKeyParameter pubKey = cert.GetPublicKey();
+
+			if (!(pubKey is DsaPublicKeyParameters))
+				return pubKey;
+
+			DsaPublicKeyParameters dsaPubKey = (DsaPublicKeyParameters)pubKey;
+
+			if (dsaPubKey.Parameters != null)
+				return dsaPubKey;
+
+			for (int i = index + 1; i < certs.Count; i++)
+			{
+				X509Certificate parentCert = (X509Certificate)certs[i];
+				pubKey = parentCert.GetPublicKey();
+
+				if (!(pubKey is DsaPublicKeyParameters))
+				{
+					throw new PkixCertPathValidatorException(
+						"DSA parameters cannot be inherited from previous certificate.");
+				}
+
+				DsaPublicKeyParameters prevDSAPubKey = (DsaPublicKeyParameters)pubKey;
+
+				if (prevDSAPubKey.Parameters == null)
+					continue;
+
+				DsaParameters dsaParams = prevDSAPubKey.Parameters;
+
+				try
+				{
+					return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams);
+				}
+				catch (Exception exception)
+				{
+					throw new Exception(exception.Message);
+				}
+			}
+
+			throw new PkixCertPathValidatorException("DSA parameters cannot be inherited from previous certificate.");
+		}
+
+		internal static DateTime GetValidCertDateFromValidityModel(
+			PkixParameters	paramsPkix,
+			PkixCertPath	certPath,
+			int				index)
+		{
+			if (paramsPkix.ValidityModel != PkixParameters.ChainValidityModel)
+			{
+				return GetValidDate(paramsPkix);
+			}
+
+			// if end cert use given signing/encryption/... time
+			if (index <= 0)
+			{
+				return PkixCertPathValidatorUtilities.GetValidDate(paramsPkix);
+				// else use time when previous cert was created
+			}
+
+			if (index - 1 == 0)
+			{
+				DerGeneralizedTime dateOfCertgen = null;
+				try
+				{
+					X509Certificate cert = (X509Certificate)certPath.Certificates[index - 1];
+					Asn1OctetString extVal = cert.GetExtensionValue(
+						IsisMttObjectIdentifiers.IdIsisMttATDateOfCertGen);
+					dateOfCertgen = DerGeneralizedTime.GetInstance(extVal);
+				}
+				catch (ArgumentException)
+				{
+					throw new Exception(
+						"Date of cert gen extension could not be read.");
+				}
+				if (dateOfCertgen != null)
+				{
+					try
+					{
+						return dateOfCertgen.ToDateTime();
+					}
+					catch (ArgumentException e)
+					{
+						throw new Exception(
+							"Date from date of cert gen extension could not be parsed.",
+							e);
+					}
+				}
+			}
+
+			return ((X509Certificate)certPath.Certificates[index - 1]).NotBefore;
+		}
+
+		/// <summary>
+		/// Return a Collection of all certificates or attribute certificates found
+		/// in the X509Store's that are matching the certSelect criteriums.
+		/// </summary>
+		/// <param name="certSelect">a {@link Selector} object that will be used to select
+		/// the certificates</param>
+		/// <param name="certStores">a List containing only X509Store objects. These
+		/// are used to search for certificates.</param>
+		/// <returns>a Collection of all found <see cref="X509Certificate"/> or
+		/// <see cref="Org.BouncyCastle.X509.IX509AttributeCertificate"/> objects.
+		/// May be empty but never <code>null</code>.</returns>
+		/// <exception cref="Exception"></exception>
+		internal static ICollection FindCertificates(
+			X509CertStoreSelector	certSelect,
+			IList					certStores)
+		{
+			ISet certs = new HashSet();
+
+			foreach (IX509Store certStore in certStores)
+			{
+				try
+				{
+//					certs.AddAll(certStore.GetMatches(certSelect));
+					foreach (X509Certificate c in certStore.GetMatches(certSelect))
+					{
+						certs.Add(c);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Problem while picking certificates from X.509 store.", e);
+				}
+			}
+
+			return certs;
+		}
+
+		/**
+		* Add the CRL issuers from the cRLIssuer field of the distribution point or
+		* from the certificate if not given to the issuer criterion of the
+		* <code>selector</code>.
+		* <p>
+		* The <code>issuerPrincipals</code> are a collection with a single
+		* <code>X500Principal</code> for <code>X509Certificate</code>s. For
+		* {@link X509AttributeCertificate}s the issuer may contain more than one
+		* <code>X500Principal</code>.
+		* </p>
+		*
+		* @param dp The distribution point.
+		* @param issuerPrincipals The issuers of the certificate or attribute
+		*            certificate which contains the distribution point.
+		* @param selector The CRL selector.
+		* @param pkixParams The PKIX parameters containing the cert stores.
+		* @throws Exception if an exception occurs while processing.
+		* @throws ClassCastException if <code>issuerPrincipals</code> does not
+		* contain only <code>X500Principal</code>s.
+		*/
+		internal static void GetCrlIssuersFromDistributionPoint(
+			DistributionPoint		dp,
+			ICollection				issuerPrincipals,
+			X509CrlStoreSelector	selector,
+			PkixParameters			pkixParams)
+		{
+            IList issuers = Platform.CreateArrayList();
+			// indirect CRL
+			if (dp.CrlIssuer != null)
+			{
+				GeneralName[] genNames = dp.CrlIssuer.GetNames();
+				// look for a DN
+				for (int j = 0; j < genNames.Length; j++)
+				{
+					if (genNames[j].TagNo == GeneralName.DirectoryName)
+					{
+						try
+						{
+							issuers.Add(X509Name.GetInstance(genNames[j].Name.ToAsn1Object()));
+						}
+						catch (IOException e)
+						{
+							throw new Exception(
+								"CRL issuer information from distribution point cannot be decoded.",
+								e);
+						}
+					}
+				}
+			}
+			else
+			{
+				/*
+				 * certificate issuer is CRL issuer, distributionPoint field MUST be
+				 * present.
+				 */
+				if (dp.DistributionPointName == null)
+				{
+					throw new Exception(
+						"CRL issuer is omitted from distribution point but no distributionPoint field present.");
+				}
+
+				// add and check issuer principals
+				for (IEnumerator it = issuerPrincipals.GetEnumerator(); it.MoveNext(); )
+				{
+					issuers.Add((X509Name)it.Current);
+				}
+			}
+			// TODO: is not found although this should correctly add the rel name. selector of Sun is buggy here or PKI test case is invalid
+			// distributionPoint
+			//        if (dp.getDistributionPoint() != null)
+			//        {
+			//            // look for nameRelativeToCRLIssuer
+			//            if (dp.getDistributionPoint().getType() == DistributionPointName.NAME_RELATIVE_TO_CRL_ISSUER)
+			//            {
+			//                // append fragment to issuer, only one
+			//                // issuer can be there, if this is given
+			//                if (issuers.size() != 1)
+			//                {
+			//                    throw new AnnotatedException(
+			//                        "nameRelativeToCRLIssuer field is given but more than one CRL issuer is given.");
+			//                }
+			//                DEREncodable relName = dp.getDistributionPoint().getName();
+			//                Iterator it = issuers.iterator();
+			//                List issuersTemp = new ArrayList(issuers.size());
+			//                while (it.hasNext())
+			//                {
+			//                    Enumeration e = null;
+			//                    try
+			//                    {
+			//                        e = ASN1Sequence.getInstance(
+			//                            new ASN1InputStream(((X500Principal) it.next())
+			//                                .getEncoded()).readObject()).getObjects();
+			//                    }
+			//                    catch (IOException ex)
+			//                    {
+			//                        throw new AnnotatedException(
+			//                            "Cannot decode CRL issuer information.", ex);
+			//                    }
+			//                    ASN1EncodableVector v = new ASN1EncodableVector();
+			//                    while (e.hasMoreElements())
+			//                    {
+			//                        v.add((DEREncodable) e.nextElement());
+			//                    }
+			//                    v.add(relName);
+			//                    issuersTemp.add(new X500Principal(new DERSequence(v)
+			//                        .getDEREncoded()));
+			//                }
+			//                issuers.clear();
+			//                issuers.addAll(issuersTemp);
+			//            }
+			//        }
+
+			selector.Issuers = issuers;
+		}
+
+		/**
+		 * Fetches complete CRLs according to RFC 3280.
+		 *
+		 * @param dp The distribution point for which the complete CRL
+		 * @param cert The <code>X509Certificate</code> or
+		 *            {@link org.bouncycastle.x509.X509AttributeCertificate} for
+		 *            which the CRL should be searched.
+		 * @param currentDate The date for which the delta CRLs must be valid.
+		 * @param paramsPKIX The extended PKIX parameters.
+		 * @return A <code>Set</code> of <code>X509CRL</code>s with complete
+		 *         CRLs.
+		 * @throws Exception if an exception occurs while picking the CRLs
+		 *             or no CRLs are found.
+		 */
+		internal static ISet GetCompleteCrls(
+			DistributionPoint	dp,
+			object				cert,
+			DateTime			currentDate,
+			PkixParameters		paramsPKIX)
+		{
+			X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
+			try
+			{
+				ISet issuers = new HashSet();
+				if (cert is X509V2AttributeCertificate)
+				{
+					issuers.Add(((X509V2AttributeCertificate)cert)
+						.Issuer.GetPrincipals()[0]);
+				}
+				else
+				{
+					issuers.Add(GetIssuerPrincipal(cert));
+				}
+				PkixCertPathValidatorUtilities.GetCrlIssuersFromDistributionPoint(dp, issuers, crlselect, paramsPKIX);
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Could not get issuer information from distribution point.", e);
+			}
+
+			if (cert is X509Certificate)
+			{
+				crlselect.CertificateChecking = (X509Certificate)cert;
+			}
+			else if (cert is X509V2AttributeCertificate)
+			{
+				crlselect.AttrCertChecking = (IX509AttributeCertificate)cert;
+			}
+
+			crlselect.CompleteCrlEnabled = true;
+			ISet crls = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);
+
+			if (crls.IsEmpty)
+			{
+				if (cert is IX509AttributeCertificate)
+				{
+					IX509AttributeCertificate aCert = (IX509AttributeCertificate)cert;
+
+					throw new Exception("No CRLs found for issuer \"" + aCert.Issuer.GetPrincipals()[0] + "\"");
+				}
+				else
+				{
+					X509Certificate xCert = (X509Certificate)cert;
+
+					throw new Exception("No CRLs found for issuer \"" + xCert.IssuerDN + "\"");
+				}
+			}
+
+			return crls;
+		}
+
+		/**
+		 * Fetches delta CRLs according to RFC 3280 section 5.2.4.
+		 *
+		 * @param currentDate The date for which the delta CRLs must be valid.
+		 * @param paramsPKIX The extended PKIX parameters.
+		 * @param completeCRL The complete CRL the delta CRL is for.
+		 * @return A <code>Set</code> of <code>X509CRL</code>s with delta CRLs.
+		 * @throws Exception if an exception occurs while picking the delta
+		 *             CRLs.
+		 */
+		internal static ISet GetDeltaCrls(
+			DateTime		currentDate,
+			PkixParameters	paramsPKIX,
+			X509Crl			completeCRL)
+		{
+			X509CrlStoreSelector deltaSelect = new X509CrlStoreSelector();
+
+			// 5.2.4 (a)
+			try
+			{
+                IList deltaSelectIssuer = Platform.CreateArrayList();
+				deltaSelectIssuer.Add(completeCRL.IssuerDN);
+				deltaSelect.Issuers = deltaSelectIssuer;
+			}
+			catch (IOException e)
+			{
+				throw new Exception("Cannot extract issuer from CRL.", e);
+			}
+
+			BigInteger completeCRLNumber = null;
+			try
+			{
+				Asn1Object asn1Object = GetExtensionValue(completeCRL, X509Extensions.CrlNumber);
+				if (asn1Object != null)
+				{
+					completeCRLNumber = CrlNumber.GetInstance(asn1Object).PositiveValue;
+				}
+			}
+			catch (Exception e)
+			{
+				throw new Exception(
+					"CRL number extension could not be extracted from CRL.", e);
+			}
+
+			// 5.2.4 (b)
+			byte[] idp = null;
+
+			try
+			{
+				Asn1Object obj = GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint);
+				if (obj != null)
+				{
+					idp = obj.GetDerEncoded();
+				}
+			}
+			catch (Exception e)
+			{
+				throw new Exception(
+					"Issuing distribution point extension value could not be read.",
+					e);
+			}
+
+			// 5.2.4 (d)
+
+			deltaSelect.MinCrlNumber = (completeCRLNumber == null)
+				?	null
+				:	completeCRLNumber.Add(BigInteger.One);
+
+			deltaSelect.IssuingDistributionPoint = idp;
+			deltaSelect.IssuingDistributionPointEnabled = true;
+
+			// 5.2.4 (c)
+			deltaSelect.MaxBaseCrlNumber = completeCRLNumber;
+
+			// find delta CRLs
+			ISet temp = CrlUtilities.FindCrls(deltaSelect, paramsPKIX, currentDate);
+
+			ISet result = new HashSet();
+
+			foreach (X509Crl crl in temp)
+			{
+				if (isDeltaCrl(crl))
+				{
+					result.Add(crl);
+				}
+			}
+
+			return result;
+		}
+
+		private static bool isDeltaCrl(
+			X509Crl crl)
+		{
+			ISet critical = crl.GetCriticalExtensionOids();
+
+			return critical.Contains(X509Extensions.DeltaCrlIndicator.Id);
+		}
+
+		internal static ICollection FindCertificates(
+			X509AttrCertStoreSelector	certSelect,
+			IList						certStores)
+		{
+			ISet certs = new HashSet();
+
+			foreach (IX509Store certStore in certStores)
+			{
+				try
+				{
+//					certs.AddAll(certStore.GetMatches(certSelect));
+					foreach (X509V2AttributeCertificate ac in certStore.GetMatches(certSelect))
+					{
+						certs.Add(ac);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Problem while picking certificates from X.509 store.", e);
+				}
+			}
+
+			return certs;
+		}
+
+		internal static void AddAdditionalStoresFromCrlDistributionPoint(
+			CrlDistPoint	crldp,
+			PkixParameters	pkixParams)
+		{
+			if (crldp != null)
+			{
+				DistributionPoint[] dps = null;
+				try
+				{
+					dps = crldp.GetDistributionPoints();
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Distribution points could not be read.", e);
+				}
+				for (int i = 0; i < dps.Length; i++)
+				{
+					DistributionPointName dpn = dps[i].DistributionPointName;
+					// look for URIs in fullName
+					if (dpn != null)
+					{
+						if (dpn.PointType == DistributionPointName.FullName)
+						{
+							GeneralName[] genNames = GeneralNames.GetInstance(
+								dpn.Name).GetNames();
+							// look for an URI
+							for (int j = 0; j < genNames.Length; j++)
+							{
+								if (genNames[j].TagNo == GeneralName.UniformResourceIdentifier)
+								{
+									string location = DerIA5String.GetInstance(
+										genNames[j].Name).GetString();
+									PkixCertPathValidatorUtilities.AddAdditionalStoreFromLocation(
+										location, pkixParams);
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+
+		internal static bool ProcessCertD1i(
+			int					index,
+			IList[]				policyNodes,
+			DerObjectIdentifier	pOid,
+			ISet				pq)
+		{
+			IList policyNodeVec = policyNodes[index - 1];
+
+			for (int j = 0; j < policyNodeVec.Count; j++)
+			{
+				PkixPolicyNode node = (PkixPolicyNode)policyNodeVec[j];
+				ISet expectedPolicies = node.ExpectedPolicies;
+
+				if (expectedPolicies.Contains(pOid.Id))
+				{
+					ISet childExpectedPolicies = new HashSet();
+					childExpectedPolicies.Add(pOid.Id);
+
+                    PkixPolicyNode child = new PkixPolicyNode(Platform.CreateArrayList(),
+						index,
+						childExpectedPolicies,
+						node,
+						pq,
+						pOid.Id,
+						false);
+					node.AddChild(child);
+					policyNodes[index].Add(child);
+
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		internal static void ProcessCertD1ii(
+			int					index,
+			IList[]				policyNodes,
+			DerObjectIdentifier _poid,
+			ISet				_pq)
+		{
+			IList policyNodeVec = policyNodes[index - 1];
+
+			for (int j = 0; j < policyNodeVec.Count; j++)
+			{
+				PkixPolicyNode _node = (PkixPolicyNode)policyNodeVec[j];
+
+				if (ANY_POLICY.Equals(_node.ValidPolicy))
+				{
+					ISet _childExpectedPolicies = new HashSet();
+					_childExpectedPolicies.Add(_poid.Id);
+
+                    PkixPolicyNode _child = new PkixPolicyNode(Platform.CreateArrayList(),
+						index,
+						_childExpectedPolicies,
+						_node,
+						_pq,
+						_poid.Id,
+						false);
+					_node.AddChild(_child);
+					policyNodes[index].Add(_child);
+					return;
+				}
+			}
+		}
+
+		/**
+		* Find the issuer certificates of a given certificate.
+		*
+		* @param cert
+		*            The certificate for which an issuer should be found.
+		* @param pkixParams
+		* @return A <code>Collection</code> object containing the issuer
+		*         <code>X509Certificate</code>s. Never <code>null</code>.
+		*
+		* @exception Exception
+		*                if an error occurs.
+		*/
+		internal static ICollection FindIssuerCerts(
+			X509Certificate			cert,
+			PkixBuilderParameters	pkixParams)
+		{
+			X509CertStoreSelector certSelect = new X509CertStoreSelector();
+			ISet certs = new HashSet();
+			try
+			{
+				certSelect.Subject = cert.IssuerDN;
+			}
+			catch (IOException ex)
+			{
+				throw new Exception(
+					"Subject criteria for certificate selector to find issuer certificate could not be set.", ex);
+			}
+
+			try
+			{
+                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetStores()));
+                certs.AddAll(PkixCertPathValidatorUtilities.FindCertificates(certSelect, pkixParams.GetAdditionalStores()));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Issuer certificate cannot be searched.", e);
+			}
+
+			return certs;
+		}
+
+		/// <summary>
+		/// Extract the value of the given extension, if it exists.
+		/// </summary>
+		/// <param name="ext">The extension object.</param>
+		/// <param name="oid">The object identifier to obtain.</param>
+		/// <returns>Asn1Object</returns>
+		/// <exception cref="Exception">if the extension cannot be read.</exception>
+		internal static Asn1Object GetExtensionValue(
+			IX509Extension		ext,
+			DerObjectIdentifier	oid)
+		{
+			Asn1OctetString bytes = ext.GetExtensionValue(oid);
+
+			if (bytes == null)
+				return null;
+
+			return X509ExtensionUtilities.FromExtensionValue(bytes);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixCrlUtilities.cs b/BouncyCastle.AxCrypt/src/pkix/PkixCrlUtilities.cs
new file mode 100644
index 0000000..c386b8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixCrlUtilities.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	public class PkixCrlUtilities
+	{
+		public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix, DateTime currentDate)
+		{
+			ISet initialSet = new HashSet();
+
+			// get complete CRL(s)
+			try
+			{
+				initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetAdditionalStores()));
+				initialSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores()));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Exception obtaining complete CRLs.", e);
+			}
+
+			ISet finalSet = new HashSet();
+			DateTime validityDate = currentDate;
+
+			if (paramsPkix.Date != null)
+			{
+				validityDate = paramsPkix.Date.Value;
+			}
+
+			// based on RFC 5280 6.3.3
+			foreach (X509Crl crl in initialSet)
+			{
+				if (crl.NextUpdate.Value.CompareTo(validityDate) > 0)
+				{
+					X509Certificate cert = crlselect.CertificateChecking;
+
+					if (cert != null)
+					{
+						if (crl.ThisUpdate.CompareTo(cert.NotAfter) < 0)
+						{
+							finalSet.Add(crl);
+						}
+					}
+					else
+					{
+						finalSet.Add(crl);
+					}
+				}
+			}
+
+			return finalSet;
+		}
+
+		public virtual ISet FindCrls(X509CrlStoreSelector crlselect, PkixParameters paramsPkix)
+		{
+			ISet completeSet = new HashSet();
+
+			// get complete CRL(s)
+			try
+			{
+				completeSet.AddAll(FindCrls(crlselect, paramsPkix.GetStores()));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Exception obtaining complete CRLs.", e);
+			}
+
+			return completeSet;
+		}
+
+		/// <summary>
+		/// crl checking
+		/// Return a Collection of all CRLs found in the X509Store's that are
+		/// matching the crlSelect criteriums.
+		/// </summary>
+		/// <param name="crlSelect">a {@link X509CRLStoreSelector} object that will be used
+		/// to select the CRLs</param>
+		/// <param name="crlStores">a List containing only {@link org.bouncycastle.x509.X509Store
+		/// X509Store} objects. These are used to search for CRLs</param>
+		/// <returns>a Collection of all found {@link X509CRL X509CRL} objects. May be
+		/// empty but never <code>null</code>.
+		/// </returns>
+		private ICollection FindCrls(X509CrlStoreSelector crlSelect, IList crlStores)
+		{
+			ISet crls = new HashSet();
+
+			Exception lastException = null;
+			bool foundValidStore = false;
+
+			foreach (IX509Store store in crlStores)
+			{
+				try
+				{
+					crls.AddAll(store.GetMatches(crlSelect));
+					foundValidStore = true;
+				}
+				catch (X509StoreException e)
+				{
+					lastException = new Exception("Exception searching in X.509 CRL store.", e);
+				}
+			}
+
+	        if (!foundValidStore && lastException != null)
+	            throw lastException;
+
+			return crls;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidator.cs b/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidator.cs
new file mode 100644
index 0000000..535f951
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidator.cs
@@ -0,0 +1,1937 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Pkix
+{
+    public class PkixNameConstraintValidator
+    {
+        private ISet excludedSubtreesDN = new HashSet();
+
+        private ISet excludedSubtreesDNS = new HashSet();
+
+        private ISet excludedSubtreesEmail = new HashSet();
+
+        private ISet excludedSubtreesURI = new HashSet();
+
+        private ISet excludedSubtreesIP = new HashSet();
+
+        private ISet permittedSubtreesDN;
+
+        private ISet permittedSubtreesDNS;
+
+        private ISet permittedSubtreesEmail;
+
+        private ISet permittedSubtreesURI;
+
+        private ISet permittedSubtreesIP;
+
+        public PkixNameConstraintValidator()
+        {
+        }
+
+        private static bool WithinDNSubtree(
+            Asn1Sequence dns,
+            Asn1Sequence subtree)
+        {
+            if (subtree.Count < 1)
+            {
+                return false;
+            }
+
+            if (subtree.Count > dns.Count)
+            {
+                return false;
+            }
+
+            for (int j = subtree.Count - 1; j >= 0; j--)
+            {
+                if (!(subtree[j].Equals(dns[j])))
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        public void CheckPermittedDN(Asn1Sequence dns)
+        //throws PkixNameConstraintValidatorException
+        {
+            CheckPermittedDN(permittedSubtreesDN, dns);
+        }
+
+        public void CheckExcludedDN(Asn1Sequence dns)
+        //throws PkixNameConstraintValidatorException
+        {
+            CheckExcludedDN(excludedSubtreesDN, dns);
+        }
+
+        private void CheckPermittedDN(ISet permitted, Asn1Sequence dns)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (permitted == null)
+            {
+                return;
+            }
+
+            if ((permitted.Count == 0) && dns.Count == 0)
+            {
+                return;
+            }
+
+            IEnumerator it = permitted.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                Asn1Sequence subtree = (Asn1Sequence)it.Current;
+
+                if (WithinDNSubtree(dns, subtree))
+                {
+                    return;
+                }
+            }
+
+            throw new PkixNameConstraintValidatorException(
+                "Subject distinguished name is not from a permitted subtree");
+        }
+
+        private void CheckExcludedDN(ISet excluded, Asn1Sequence dns)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (excluded.IsEmpty)
+            {
+                return;
+            }
+
+            IEnumerator it = excluded.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                Asn1Sequence subtree = (Asn1Sequence)it.Current;
+
+                if (WithinDNSubtree(dns, subtree))
+                {
+                    throw new PkixNameConstraintValidatorException(
+                        "Subject distinguished name is from an excluded subtree");
+                }
+            }
+        }
+
+        private ISet IntersectDN(ISet permitted, ISet dns)
+        {
+            ISet intersect = new HashSet();
+            for (IEnumerator it = dns.GetEnumerator(); it.MoveNext(); )
+            {
+                Asn1Sequence dn = Asn1Sequence.GetInstance(((GeneralSubtree)it
+                    .Current).Base.Name.ToAsn1Object());
+                if (permitted == null)
+                {
+                    if (dn != null)
+                    {
+                        intersect.Add(dn);
+                    }
+                }
+                else
+                {
+                    IEnumerator _iter = permitted.GetEnumerator();
+                    while (_iter.MoveNext())
+                    {
+                        Asn1Sequence subtree = (Asn1Sequence)_iter.Current;
+
+                        if (WithinDNSubtree(dn, subtree))
+                        {
+                            intersect.Add(dn);
+                        }
+                        else if (WithinDNSubtree(subtree, dn))
+                        {
+                            intersect.Add(subtree);
+                        }
+                    }
+                }
+            }
+            return intersect;
+        }
+
+        private ISet UnionDN(ISet excluded, Asn1Sequence dn)
+        {
+            if (excluded.IsEmpty)
+            {
+                if (dn == null)
+                {
+                    return excluded;
+                }
+                excluded.Add(dn);
+
+                return excluded;
+            }
+            else
+            {
+                ISet intersect = new HashSet();
+
+                IEnumerator it = excluded.GetEnumerator();
+                while (it.MoveNext())
+                {
+                    Asn1Sequence subtree = (Asn1Sequence)it.Current;
+
+                    if (WithinDNSubtree(dn, subtree))
+                    {
+                        intersect.Add(subtree);
+                    }
+                    else if (WithinDNSubtree(subtree, dn))
+                    {
+                        intersect.Add(dn);
+                    }
+                    else
+                    {
+                        intersect.Add(subtree);
+                        intersect.Add(dn);
+                    }
+                }
+
+                return intersect;
+            }
+        }
+
+        private ISet IntersectEmail(ISet permitted, ISet emails)
+        {
+            ISet intersect = new HashSet();
+            for (IEnumerator it = emails.GetEnumerator(); it.MoveNext(); )
+            {
+                String email = ExtractNameAsString(((GeneralSubtree)it.Current)
+                    .Base);
+
+                if (permitted == null)
+                {
+                    if (email != null)
+                    {
+                        intersect.Add(email);
+                    }
+                }
+                else
+                {
+                    IEnumerator it2 = permitted.GetEnumerator();
+                    while (it2.MoveNext())
+                    {
+                        String _permitted = (String)it2.Current;
+
+                        intersectEmail(email, _permitted, intersect);
+                    }
+                }
+            }
+            return intersect;
+        }
+
+        private ISet UnionEmail(ISet excluded, String email)
+        {
+            if (excluded.IsEmpty)
+            {
+                if (email == null)
+                {
+                    return excluded;
+                }
+                excluded.Add(email);
+                return excluded;
+            }
+            else
+            {
+                ISet union = new HashSet();
+
+                IEnumerator it = excluded.GetEnumerator();
+                while (it.MoveNext())
+                {
+                    String _excluded = (String)it.Current;
+
+                    unionEmail(_excluded, email, union);
+                }
+
+                return union;
+            }
+        }
+
+        /**
+         * Returns the intersection of the permitted IP ranges in
+         * <code>permitted</code> with <code>ip</code>.
+         *
+         * @param permitted A <code>Set</code> of permitted IP addresses with
+         *                  their subnet mask as byte arrays.
+         * @param ips       The IP address with its subnet mask.
+         * @return The <code>Set</code> of permitted IP ranges intersected with
+         *         <code>ip</code>.
+         */
+        private ISet IntersectIP(ISet permitted, ISet ips)
+        {
+            ISet intersect = new HashSet();
+            for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); )
+            {
+                byte[] ip = Asn1OctetString.GetInstance(
+                    ((GeneralSubtree)it.Current).Base.Name).GetOctets();
+                if (permitted == null)
+                {
+                    if (ip != null)
+                    {
+                        intersect.Add(ip);
+                    }
+                }
+                else
+                {
+                    IEnumerator it2 = permitted.GetEnumerator();
+                    while (it2.MoveNext())
+                    {
+                        byte[] _permitted = (byte[])it2.Current;
+                        intersect.AddAll(IntersectIPRange(_permitted, ip));
+                    }
+                }
+            }
+            return intersect;
+        }
+
+        /**
+         * Returns the union of the excluded IP ranges in <code>excluded</code>
+         * with <code>ip</code>.
+         *
+         * @param excluded A <code>Set</code> of excluded IP addresses with their
+         *                 subnet mask as byte arrays.
+         * @param ip       The IP address with its subnet mask.
+         * @return The <code>Set</code> of excluded IP ranges unified with
+         *         <code>ip</code> as byte arrays.
+         */
+        private ISet UnionIP(ISet excluded, byte[] ip)
+        {
+            if (excluded.IsEmpty)
+            {
+                if (ip == null)
+                {
+                    return excluded;
+                }
+                excluded.Add(ip);
+
+                return excluded;
+            }
+            else
+            {
+                ISet union = new HashSet();
+
+                IEnumerator it = excluded.GetEnumerator();
+                while (it.MoveNext())
+                {
+                    byte[] _excluded = (byte[])it.Current;
+                    union.AddAll(UnionIPRange(_excluded, ip));
+                }
+
+                return union;
+            }
+        }
+
+        /**
+         * Calculates the union if two IP ranges.
+         *
+         * @param ipWithSubmask1 The first IP address with its subnet mask.
+         * @param ipWithSubmask2 The second IP address with its subnet mask.
+         * @return A <code>Set</code> with the union of both addresses.
+         */
+        private ISet UnionIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
+        {
+            ISet set = new HashSet();
+
+            // difficult, adding always all IPs is not wrong
+            if (Org.BouncyCastle.Utilities.Arrays.AreEqual(ipWithSubmask1, ipWithSubmask2))
+            {
+                set.Add(ipWithSubmask1);
+            }
+            else
+            {
+                set.Add(ipWithSubmask1);
+                set.Add(ipWithSubmask2);
+            }
+            return set;
+        }
+
+        /**
+         * Calculates the interesction if two IP ranges.
+         *
+         * @param ipWithSubmask1 The first IP address with its subnet mask.
+         * @param ipWithSubmask2 The second IP address with its subnet mask.
+         * @return A <code>Set</code> with the single IP address with its subnet
+         *         mask as a byte array or an empty <code>Set</code>.
+         */
+        private ISet IntersectIPRange(byte[] ipWithSubmask1, byte[] ipWithSubmask2)
+    {
+        if (ipWithSubmask1.Length != ipWithSubmask2.Length)
+        {
+            //Collections.EMPTY_SET;
+            return new HashSet();
+        }
+
+        byte[][] temp = ExtractIPsAndSubnetMasks(ipWithSubmask1, ipWithSubmask2);
+        byte[] ip1 = temp[0];
+        byte[] subnetmask1 = temp[1];
+        byte[] ip2 = temp[2];
+        byte[] subnetmask2 = temp[3];
+
+        byte[][] minMax = MinMaxIPs(ip1, subnetmask1, ip2, subnetmask2);
+        byte[] min;
+        byte[] max;
+        max = Min(minMax[1], minMax[3]);
+        min = Max(minMax[0], minMax[2]);
+
+        // minimum IP address must be bigger than max
+        if (CompareTo(min, max) == 1)
+        {
+            //return Collections.EMPTY_SET;
+            return new HashSet();
+        }
+        // OR keeps all significant bits
+        byte[] ip = Or(minMax[0], minMax[2]);
+        byte[] subnetmask = Or(subnetmask1, subnetmask2);
+
+            //return new HashSet( ICollectionsingleton(IpWithSubnetMask(ip, subnetmask));
+        ISet hs = new HashSet();
+        hs.Add(IpWithSubnetMask(ip, subnetmask));
+
+            return hs;
+    }
+
+        /**
+         * Concatenates the IP address with its subnet mask.
+         *
+         * @param ip         The IP address.
+         * @param subnetMask Its subnet mask.
+         * @return The concatenated IP address with its subnet mask.
+         */
+        private byte[] IpWithSubnetMask(byte[] ip, byte[] subnetMask)
+        {
+            int ipLength = ip.Length;
+            byte[] temp = new byte[ipLength * 2];
+            Array.Copy(ip, 0, temp, 0, ipLength);
+            Array.Copy(subnetMask, 0, temp, ipLength, ipLength);
+            return temp;
+        }
+
+        /**
+         * Splits the IP addresses and their subnet mask.
+         *
+         * @param ipWithSubmask1 The first IP address with the subnet mask.
+         * @param ipWithSubmask2 The second IP address with the subnet mask.
+         * @return An array with two elements. Each element contains the IP address
+         *         and the subnet mask in this order.
+         */
+        private byte[][] ExtractIPsAndSubnetMasks(
+            byte[] ipWithSubmask1,
+            byte[] ipWithSubmask2)
+    {
+        int ipLength = ipWithSubmask1.Length / 2;
+        byte[] ip1 = new byte[ipLength];
+        byte[] subnetmask1 = new byte[ipLength];
+        Array.Copy(ipWithSubmask1, 0, ip1, 0, ipLength);
+        Array.Copy(ipWithSubmask1, ipLength, subnetmask1, 0, ipLength);
+
+        byte[] ip2 = new byte[ipLength];
+        byte[] subnetmask2 = new byte[ipLength];
+        Array.Copy(ipWithSubmask2, 0, ip2, 0, ipLength);
+        Array.Copy(ipWithSubmask2, ipLength, subnetmask2, 0, ipLength);
+        return new byte[][]
+            {ip1, subnetmask1, ip2, subnetmask2};
+    }
+
+        /**
+         * Based on the two IP addresses and their subnet masks the IP range is
+         * computed for each IP address - subnet mask pair and returned as the
+         * minimum IP address and the maximum address of the range.
+         *
+         * @param ip1         The first IP address.
+         * @param subnetmask1 The subnet mask of the first IP address.
+         * @param ip2         The second IP address.
+         * @param subnetmask2 The subnet mask of the second IP address.
+         * @return A array with two elements. The first/second element contains the
+         *         min and max IP address of the first/second IP address and its
+         *         subnet mask.
+         */
+        private byte[][] MinMaxIPs(
+            byte[] ip1,
+            byte[] subnetmask1,
+            byte[] ip2,
+            byte[] subnetmask2)
+        {
+            int ipLength = ip1.Length;
+            byte[] min1 = new byte[ipLength];
+            byte[] max1 = new byte[ipLength];
+
+            byte[] min2 = new byte[ipLength];
+            byte[] max2 = new byte[ipLength];
+
+            for (int i = 0; i < ipLength; i++)
+            {
+                min1[i] = (byte)(ip1[i] & subnetmask1[i]);
+                max1[i] = (byte)(ip1[i] & subnetmask1[i] | ~subnetmask1[i]);
+
+                min2[i] = (byte)(ip2[i] & subnetmask2[i]);
+                max2[i] = (byte)(ip2[i] & subnetmask2[i] | ~subnetmask2[i]);
+            }
+
+            return new byte[][] { min1, max1, min2, max2 };
+        }
+
+        private void CheckPermittedEmail(ISet permitted, String email)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (permitted == null)
+            {
+                return;
+            }
+
+            IEnumerator it = permitted.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = ((String)it.Current);
+
+                if (EmailIsConstrained(email, str))
+                {
+                    return;
+                }
+            }
+
+            if (email.Length == 0 && permitted.Count == 0)
+            {
+                return;
+            }
+
+            throw new PkixNameConstraintValidatorException(
+                "Subject email address is not from a permitted subtree.");
+        }
+
+        private void CheckExcludedEmail(ISet excluded, String email)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (excluded.IsEmpty)
+            {
+                return;
+            }
+
+            IEnumerator it = excluded.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = (String)it.Current;
+
+                if (EmailIsConstrained(email, str))
+                {
+                    throw new PkixNameConstraintValidatorException(
+                        "Email address is from an excluded subtree.");
+                }
+            }
+        }
+
+        /**
+         * Checks if the IP <code>ip</code> is included in the permitted ISet
+         * <code>permitted</code>.
+         *
+         * @param permitted A <code>Set</code> of permitted IP addresses with
+         *                  their subnet mask as byte arrays.
+         * @param ip        The IP address.
+         * @throws PkixNameConstraintValidatorException
+         *          if the IP is not permitted.
+         */
+        private void CheckPermittedIP(ISet permitted, byte[] ip)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (permitted == null)
+            {
+                return;
+            }
+
+            IEnumerator it = permitted.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                byte[] ipWithSubnet = (byte[])it.Current;
+
+                if (IsIPConstrained(ip, ipWithSubnet))
+                {
+                    return;
+                }
+            }
+            if (ip.Length == 0 && permitted.Count == 0)
+            {
+                return;
+            }
+            throw new PkixNameConstraintValidatorException(
+                "IP is not from a permitted subtree.");
+        }
+
+        /**
+         * Checks if the IP <code>ip</code> is included in the excluded ISet
+         * <code>excluded</code>.
+         *
+         * @param excluded A <code>Set</code> of excluded IP addresses with their
+         *                 subnet mask as byte arrays.
+         * @param ip       The IP address.
+         * @throws PkixNameConstraintValidatorException
+         *          if the IP is excluded.
+         */
+        private void checkExcludedIP(ISet excluded, byte[] ip)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (excluded.IsEmpty)
+            {
+                return;
+            }
+
+            IEnumerator it = excluded.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                byte[] ipWithSubnet = (byte[])it.Current;
+
+                if (IsIPConstrained(ip, ipWithSubnet))
+                {
+                    throw new PkixNameConstraintValidatorException(
+                        "IP is from an excluded subtree.");
+                }
+            }
+        }
+
+        /**
+         * Checks if the IP address <code>ip</code> is constrained by
+         * <code>constraint</code>.
+         *
+         * @param ip         The IP address.
+         * @param constraint The constraint. This is an IP address concatenated with
+         *                   its subnetmask.
+         * @return <code>true</code> if constrained, <code>false</code>
+         *         otherwise.
+         */
+        private bool IsIPConstrained(byte[] ip, byte[] constraint)
+        {
+            int ipLength = ip.Length;
+
+            if (ipLength != (constraint.Length / 2))
+            {
+                return false;
+            }
+
+            byte[] subnetMask = new byte[ipLength];
+            Array.Copy(constraint, ipLength, subnetMask, 0, ipLength);
+
+            byte[] permittedSubnetAddress = new byte[ipLength];
+
+            byte[] ipSubnetAddress = new byte[ipLength];
+
+            // the resulting IP address by applying the subnet mask
+            for (int i = 0; i < ipLength; i++)
+            {
+                permittedSubnetAddress[i] = (byte)(constraint[i] & subnetMask[i]);
+                ipSubnetAddress[i] = (byte)(ip[i] & subnetMask[i]);
+            }
+
+            return Org.BouncyCastle.Utilities.Arrays.AreEqual(permittedSubnetAddress, ipSubnetAddress);
+        }
+
+        private bool EmailIsConstrained(String email, String constraint)
+        {
+            String sub = email.Substring(email.IndexOf('@') + 1);
+            // a particular mailbox
+            if (constraint.IndexOf('@') != -1)
+            {
+                if (email.ToUpper().Equals(constraint.ToUpper()))
+                {
+                    return true;
+                }
+            }
+            // on particular host
+            else if (!(constraint[0].Equals('.')))
+            {
+                if (sub.ToUpper().Equals(constraint.ToUpper()))
+                {
+                    return true;
+                }
+            }
+            // address in sub domain
+            else if (WithinDomain(sub, constraint))
+            {
+                return true;
+            }
+            return false;
+        }
+
+        private bool WithinDomain(String testDomain, String domain)
+        {
+            String tempDomain = domain;
+            if (tempDomain.StartsWith("."))
+            {
+                tempDomain = tempDomain.Substring(1);
+            }
+            String[] domainParts = tempDomain.Split('.'); // Strings.split(tempDomain, '.');
+            String[] testDomainParts = testDomain.Split('.'); // Strings.split(testDomain, '.');
+
+            // must have at least one subdomain
+            if (testDomainParts.Length <= domainParts.Length)
+            {
+                return false;
+            }
+
+            int d = testDomainParts.Length - domainParts.Length;
+            for (int i = -1; i < domainParts.Length; i++)
+            {
+                if (i == -1)
+                {
+                    if (testDomainParts[i + d].Equals(""))
+                    {
+                        return false;
+                    }
+                }
+                else if (!(Platform.CompareIgnoreCase(testDomainParts[i + d], domainParts[i]) == 0))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private void CheckPermittedDNS(ISet permitted, String dns)
+        //throws PkixNameConstraintValidatorException
+        {
+            if (permitted == null)
+            {
+                return;
+            }
+
+            IEnumerator it = permitted.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = ((String)it.Current);
+
+                // is sub domain
+                if (WithinDomain(dns, str) || dns.ToUpper().Equals(str.ToUpper()))
+                {
+                    return;
+                }
+            }
+            if (dns.Length == 0 && permitted.Count == 0)
+            {
+                return;
+            }
+            throw new PkixNameConstraintValidatorException(
+                "DNS is not from a permitted subtree.");
+        }
+
+        private void checkExcludedDNS(ISet excluded, String dns)
+        //     throws PkixNameConstraintValidatorException
+        {
+            if (excluded.IsEmpty)
+            {
+                return;
+            }
+
+            IEnumerator it = excluded.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = ((String)it.Current);
+
+                // is sub domain or the same
+				if (WithinDomain(dns, str) || (Platform.CompareIgnoreCase(dns, str) == 0))
+                {
+                    throw new PkixNameConstraintValidatorException(
+                        "DNS is from an excluded subtree.");
+                }
+            }
+        }
+
+        /**
+         * The common part of <code>email1</code> and <code>email2</code> is
+         * added to the union <code>union</code>. If <code>email1</code> and
+         * <code>email2</code> have nothing in common they are added both.
+         *
+         * @param email1 Email address constraint 1.
+         * @param email2 Email address constraint 2.
+         * @param union  The union.
+         */
+        private void unionEmail(String email1, String email2, ISet union)
+        {
+            // email1 is a particular address
+            if (email1.IndexOf('@') != -1)
+            {
+                String _sub = email1.Substring(email1.IndexOf('@') + 1);
+                // both are a particular mailbox
+                if (email2.IndexOf('@') != -1)
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(_sub, email2))
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(_sub, email2) == 0)
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+            }
+            // email1 specifies a domain
+            else if (email1.StartsWith("."))
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (WithinDomain(_sub, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2) || Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email2);
+                    }
+                    else if (WithinDomain(email2, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                else
+                {
+                    if (WithinDomain(email2, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+            }
+            // email specifies a host
+            else
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (Platform.CompareIgnoreCase(_sub, email1) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2))
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+            }
+        }
+
+        private void unionURI(String email1, String email2, ISet union)
+        {
+            // email1 is a particular address
+            if (email1.IndexOf('@') != -1)
+            {
+                String _sub = email1.Substring(email1.IndexOf('@') + 1);
+                // both are a particular mailbox
+                if (email2.IndexOf('@') != -1)
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(_sub, email2))
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(_sub, email2) == 0)
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+
+                    }
+                }
+            }
+            // email1 specifies a domain
+            else if (email1.StartsWith("."))
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (WithinDomain(_sub, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2) || Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email2);
+                    }
+                    else if (WithinDomain(email2, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                else
+                {
+                    if (WithinDomain(email2, email1))
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+            }
+            // email specifies a host
+            else
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (Platform.CompareIgnoreCase(_sub, email1) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2))
+                    {
+                        union.Add(email2);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        union.Add(email1);
+                    }
+                    else
+                    {
+                        union.Add(email1);
+                        union.Add(email2);
+                    }
+                }
+            }
+        }
+
+        private ISet intersectDNS(ISet permitted, ISet dnss)
+        {
+            ISet intersect = new HashSet();
+            for (IEnumerator it = dnss.GetEnumerator(); it.MoveNext(); )
+            {
+                String dns = ExtractNameAsString(((GeneralSubtree)it.Current)
+                    .Base);
+                if (permitted == null)
+                {
+                    if (dns != null)
+                    {
+                        intersect.Add(dns);
+                    }
+                }
+                else
+                {
+                    IEnumerator _iter = permitted.GetEnumerator();
+                    while (_iter.MoveNext())
+                    {
+                        String _permitted = (String)_iter.Current;
+
+                        if (WithinDomain(_permitted, dns))
+                        {
+                            intersect.Add(_permitted);
+                        }
+                        else if (WithinDomain(dns, _permitted))
+                        {
+                            intersect.Add(dns);
+                        }
+                    }
+                }
+            }
+
+            return intersect;
+        }
+
+        protected ISet unionDNS(ISet excluded, String dns)
+        {
+            if (excluded.IsEmpty)
+            {
+                if (dns == null)
+                {
+                    return excluded;
+                }
+                excluded.Add(dns);
+
+                return excluded;
+            }
+            else
+            {
+                ISet union = new HashSet();
+
+                IEnumerator _iter = excluded.GetEnumerator();
+                while (_iter.MoveNext())
+                {
+                    String _permitted = (String)_iter.Current;
+
+                    if (WithinDomain(_permitted, dns))
+                    {
+                        union.Add(dns);
+                    }
+                    else if (WithinDomain(dns, _permitted))
+                    {
+                        union.Add(_permitted);
+                    }
+                    else
+                    {
+                        union.Add(_permitted);
+                        union.Add(dns);
+                    }
+                }
+
+                return union;
+            }
+        }
+
+        /**
+         * The most restricting part from <code>email1</code> and
+         * <code>email2</code> is added to the intersection <code>intersect</code>.
+         *
+         * @param email1    Email address constraint 1.
+         * @param email2    Email address constraint 2.
+         * @param intersect The intersection.
+         */
+        private void intersectEmail(String email1, String email2, ISet intersect)
+        {
+            // email1 is a particular address
+            if (email1.IndexOf('@') != -1)
+            {
+                String _sub = email1.Substring(email1.IndexOf('@') + 1);
+                // both are a particular mailbox
+                if (email2.IndexOf('@') != -1)
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(_sub, email2))
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(_sub, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+            }
+            // email specifies a domain
+            else if (email1.StartsWith("."))
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (WithinDomain(_sub, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2) || (Platform.CompareIgnoreCase(email1, email2) == 0))
+                    {
+                        intersect.Add(email1);
+                    }
+                    else if (WithinDomain(email2, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                else
+                {
+                    if (WithinDomain(email2, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+            }
+            // email1 specifies a host
+            else
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email2.IndexOf('@') + 1);
+                    if (Platform.CompareIgnoreCase(_sub, email1) == 0)
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2))
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+            }
+        }
+
+        private void checkExcludedURI(ISet excluded, String uri)
+        //       throws PkixNameConstraintValidatorException
+        {
+            if (excluded.IsEmpty)
+            {
+                return;
+            }
+
+            IEnumerator it = excluded.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = ((String)it.Current);
+
+                if (IsUriConstrained(uri, str))
+                {
+                    throw new PkixNameConstraintValidatorException(
+                        "URI is from an excluded subtree.");
+                }
+            }
+        }
+
+        private ISet intersectURI(ISet permitted, ISet uris)
+        {
+            ISet intersect = new HashSet();
+            for (IEnumerator it = uris.GetEnumerator(); it.MoveNext(); )
+            {
+                String uri = ExtractNameAsString(((GeneralSubtree)it.Current)
+                    .Base);
+                if (permitted == null)
+                {
+                    if (uri != null)
+                    {
+                        intersect.Add(uri);
+                    }
+                }
+                else
+                {
+                    IEnumerator _iter = permitted.GetEnumerator();
+                    while (_iter.MoveNext())
+                    {
+                        String _permitted = (String)_iter.Current;
+                        intersectURI(_permitted, uri, intersect);
+                    }
+                }
+            }
+            return intersect;
+        }
+
+        private ISet unionURI(ISet excluded, String uri)
+        {
+            if (excluded.IsEmpty)
+            {
+                if (uri == null)
+                {
+                    return excluded;
+                }
+                excluded.Add(uri);
+
+                return excluded;
+            }
+            else
+            {
+                ISet union = new HashSet();
+
+                IEnumerator _iter = excluded.GetEnumerator();
+                while (_iter.MoveNext())
+                {
+                    String _excluded = (String)_iter.Current;
+
+                    unionURI(_excluded, uri, union);
+                }
+
+                return union;
+            }
+        }
+
+        private void intersectURI(String email1, String email2, ISet intersect)
+        {
+            // email1 is a particular address
+            if (email1.IndexOf('@') != -1)
+            {
+                String _sub = email1.Substring(email1.IndexOf('@') + 1);
+                // both are a particular mailbox
+                if (email2.IndexOf('@') != -1)
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(_sub, email2))
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(_sub, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+            }
+            // email specifies a domain
+            else if (email1.StartsWith("."))
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email1.IndexOf('@') + 1);
+                    if (WithinDomain(_sub, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2) || (Platform.CompareIgnoreCase(email1, email2) == 0))
+                    {
+                        intersect.Add(email1);
+                    }
+                    else if (WithinDomain(email2, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                else
+                {
+                    if (WithinDomain(email2, email1))
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+            }
+            // email1 specifies a host
+            else
+            {
+                if (email2.IndexOf('@') != -1)
+                {
+                    String _sub = email2.Substring(email2.IndexOf('@') + 1);
+                    if (Platform.CompareIgnoreCase(_sub, email1) == 0)
+                    {
+                        intersect.Add(email2);
+                    }
+                }
+                // email2 specifies a domain
+                else if (email2.StartsWith("."))
+                {
+                    if (WithinDomain(email1, email2))
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+                // email2 specifies a particular host
+                else
+                {
+                    if (Platform.CompareIgnoreCase(email1, email2) == 0)
+                    {
+                        intersect.Add(email1);
+                    }
+                }
+            }
+        }
+
+        private void CheckPermittedURI(ISet permitted, String uri)
+        //        throws PkixNameConstraintValidatorException
+        {
+            if (permitted == null)
+            {
+                return;
+            }
+
+            IEnumerator it = permitted.GetEnumerator();
+
+            while (it.MoveNext())
+            {
+                String str = ((String)it.Current);
+
+                if (IsUriConstrained(uri, str))
+                {
+                    return;
+                }
+            }
+            if (uri.Length == 0 && permitted.Count == 0)
+            {
+                return;
+            }
+            throw new PkixNameConstraintValidatorException(
+                "URI is not from a permitted subtree.");
+        }
+
+        private bool IsUriConstrained(String uri, String constraint)
+        {
+            String host = ExtractHostFromURL(uri);
+            // a host
+            if (!constraint.StartsWith("."))
+            {
+                if (Platform.CompareIgnoreCase(host, constraint) == 0)
+                {
+                    return true;
+                }
+            }
+
+            // in sub domain or domain
+            else if (WithinDomain(host, constraint))
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        private static String ExtractHostFromURL(String url)
+        {
+            // see RFC 1738
+            // remove ':' after protocol, e.g. http:
+            String sub = url.Substring(url.IndexOf(':') + 1);
+            // extract host from Common Internet Scheme Syntax, e.g. http://
+            if (sub.IndexOf("//") != -1)
+            {
+                sub = sub.Substring(sub.IndexOf("//") + 2);
+            }
+            // first remove port, e.g. http://test.com:21
+            if (sub.LastIndexOf(':') != -1)
+            {
+                sub = sub.Substring(0, sub.LastIndexOf(':'));
+            }
+            // remove user and password, e.g. http://john:password@test.com
+            sub = sub.Substring(sub.IndexOf(':') + 1);
+            sub = sub.Substring(sub.IndexOf('@') + 1);
+            // remove local parts, e.g. http://test.com/bla
+            if (sub.IndexOf('/') != -1)
+            {
+                sub = sub.Substring(0, sub.IndexOf('/'));
+            }
+            return sub;
+        }
+
+        /**
+         * Checks if the given GeneralName is in the permitted ISet.
+         *
+         * @param name The GeneralName
+         * @throws PkixNameConstraintValidatorException
+         *          If the <code>name</code>
+         */
+        public void checkPermitted(GeneralName name)
+        //        throws PkixNameConstraintValidatorException
+        {
+            switch (name.TagNo)
+            {
+                case 1:
+                    CheckPermittedEmail(permittedSubtreesEmail,
+                        ExtractNameAsString(name));
+                    break;
+                case 2:
+                    CheckPermittedDNS(permittedSubtreesDNS, DerIA5String.GetInstance(
+                        name.Name).GetString());
+                    break;
+                case 4:
+                    CheckPermittedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
+                    break;
+                case 6:
+                    CheckPermittedURI(permittedSubtreesURI, DerIA5String.GetInstance(
+                        name.Name).GetString());
+                    break;
+                case 7:
+                    byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets();
+
+                    CheckPermittedIP(permittedSubtreesIP, ip);
+                    break;
+            }
+        }
+
+        /**
+         * Check if the given GeneralName is contained in the excluded ISet.
+         *
+         * @param name The GeneralName.
+         * @throws PkixNameConstraintValidatorException
+         *          If the <code>name</code> is
+         *          excluded.
+         */
+        public void checkExcluded(GeneralName name)
+        //        throws PkixNameConstraintValidatorException
+        {
+            switch (name.TagNo)
+            {
+                case 1:
+                    CheckExcludedEmail(excludedSubtreesEmail, ExtractNameAsString(name));
+                    break;
+                case 2:
+                    checkExcludedDNS(excludedSubtreesDNS, DerIA5String.GetInstance(
+                        name.Name).GetString());
+                    break;
+                case 4:
+                    CheckExcludedDN(Asn1Sequence.GetInstance(name.Name.ToAsn1Object()));
+                    break;
+                case 6:
+                    checkExcludedURI(excludedSubtreesURI, DerIA5String.GetInstance(
+                        name.Name).GetString());
+                    break;
+                case 7:
+                    byte[] ip = Asn1OctetString.GetInstance(name.Name).GetOctets();
+
+                    checkExcludedIP(excludedSubtreesIP, ip);
+                    break;
+            }
+        }
+
+        /**
+         * Updates the permitted ISet of these name constraints with the intersection
+         * with the given subtree.
+         *
+         * @param permitted The permitted subtrees
+         */
+
+        public void IntersectPermittedSubtree(Asn1Sequence permitted)
+        {
+            IDictionary subtreesMap = Platform.CreateHashtable();
+
+            // group in ISets in a map ordered by tag no.
+            for (IEnumerator e = permitted.GetEnumerator(); e.MoveNext(); )
+            {
+                GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current);
+
+                int tagNo = subtree.Base.TagNo;
+                if (subtreesMap[tagNo] == null)
+                {
+                    subtreesMap[tagNo] = new HashSet();
+                }
+
+                ((ISet)subtreesMap[tagNo]).Add(subtree);
+            }
+
+            for (IEnumerator it = subtreesMap.GetEnumerator(); it.MoveNext(); )
+            {
+                DictionaryEntry entry = (DictionaryEntry)it.Current;
+
+                // go through all subtree groups
+                switch ((int)entry.Key )
+                {
+                    case 1:
+                        permittedSubtreesEmail = IntersectEmail(permittedSubtreesEmail,
+                            (ISet)entry.Value);
+                        break;
+                    case 2:
+                        permittedSubtreesDNS = intersectDNS(permittedSubtreesDNS,
+                            (ISet)entry.Value);
+                        break;
+                    case 4:
+                        permittedSubtreesDN = IntersectDN(permittedSubtreesDN,
+                            (ISet)entry.Value);
+                        break;
+                    case 6:
+                        permittedSubtreesURI = intersectURI(permittedSubtreesURI,
+                            (ISet)entry.Value);
+                        break;
+                    case 7:
+                        permittedSubtreesIP = IntersectIP(permittedSubtreesIP,
+                            (ISet)entry.Value);
+                        break;
+                }
+            }
+        }
+
+        private String ExtractNameAsString(GeneralName name)
+        {
+            return DerIA5String.GetInstance(name.Name).GetString();
+        }
+
+        public void IntersectEmptyPermittedSubtree(int nameType)
+        {
+            switch (nameType)
+            {
+                case 1:
+                    permittedSubtreesEmail = new HashSet();
+                    break;
+                case 2:
+                    permittedSubtreesDNS = new HashSet();
+                    break;
+                case 4:
+                    permittedSubtreesDN = new HashSet();
+                    break;
+                case 6:
+                    permittedSubtreesURI = new HashSet();
+                    break;
+                case 7:
+                    permittedSubtreesIP = new HashSet();
+                    break;
+            }
+        }
+
+        /**
+         * Adds a subtree to the excluded ISet of these name constraints.
+         *
+         * @param subtree A subtree with an excluded GeneralName.
+         */
+        public void AddExcludedSubtree(GeneralSubtree subtree)
+        {
+            GeneralName subTreeBase = subtree.Base;
+
+            switch (subTreeBase.TagNo)
+            {
+                case 1:
+                    excludedSubtreesEmail = UnionEmail(excludedSubtreesEmail,
+                        ExtractNameAsString(subTreeBase));
+                    break;
+                case 2:
+                    excludedSubtreesDNS = unionDNS(excludedSubtreesDNS,
+                        ExtractNameAsString(subTreeBase));
+                    break;
+                case 4:
+                    excludedSubtreesDN = UnionDN(excludedSubtreesDN,
+                        (Asn1Sequence)subTreeBase.Name.ToAsn1Object());
+                    break;
+                case 6:
+                    excludedSubtreesURI = unionURI(excludedSubtreesURI,
+                        ExtractNameAsString(subTreeBase));
+                    break;
+                case 7:
+                    excludedSubtreesIP = UnionIP(excludedSubtreesIP, Asn1OctetString
+                        .GetInstance(subTreeBase.Name).GetOctets());
+                    break;
+            }
+        }
+
+        /**
+         * Returns the maximum IP address.
+         *
+         * @param ip1 The first IP address.
+         * @param ip2 The second IP address.
+         * @return The maximum IP address.
+         */
+        private static byte[] Max(byte[] ip1, byte[] ip2)
+        {
+            for (int i = 0; i < ip1.Length; i++)
+            {
+                if ((ip1[i] & 0xFFFF) > (ip2[i] & 0xFFFF))
+                {
+                    return ip1;
+                }
+            }
+            return ip2;
+        }
+
+        /**
+         * Returns the minimum IP address.
+         *
+         * @param ip1 The first IP address.
+         * @param ip2 The second IP address.
+         * @return The minimum IP address.
+         */
+        private static byte[] Min(byte[] ip1, byte[] ip2)
+        {
+            for (int i = 0; i < ip1.Length; i++)
+            {
+                if ((ip1[i] & 0xFFFF) < (ip2[i] & 0xFFFF))
+                {
+                    return ip1;
+                }
+            }
+            return ip2;
+        }
+
+        /**
+         * Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1
+         * is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1
+         * otherwise.
+         *
+         * @param ip1 The first IP address.
+         * @param ip2 The second IP address.
+         * @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise.
+         */
+        private static int CompareTo(byte[] ip1, byte[] ip2)
+        {
+            if (Org.BouncyCastle.Utilities.Arrays.AreEqual(ip1, ip2))
+            {
+                return 0;
+            }
+            if (Org.BouncyCastle.Utilities.Arrays.AreEqual(Max(ip1, ip2), ip1))
+            {
+                return 1;
+            }
+            return -1;
+        }
+
+        /**
+         * Returns the logical OR of the IP addresses <code>ip1</code> and
+         * <code>ip2</code>.
+         *
+         * @param ip1 The first IP address.
+         * @param ip2 The second IP address.
+         * @return The OR of <code>ip1</code> and <code>ip2</code>.
+         */
+        private static byte[] Or(byte[] ip1, byte[] ip2)
+        {
+            byte[] temp = new byte[ip1.Length];
+            for (int i = 0; i < ip1.Length; i++)
+            {
+                temp[i] = (byte)(ip1[i] | ip2[i]);
+            }
+            return temp;
+        }
+
+		[Obsolete("Use GetHashCode instead")]
+		public int HashCode()
+		{
+			return GetHashCode();
+		}
+
+		public override int GetHashCode()
+        {
+            return HashCollection(excludedSubtreesDN)
+                + HashCollection(excludedSubtreesDNS)
+                + HashCollection(excludedSubtreesEmail)
+                + HashCollection(excludedSubtreesIP)
+                + HashCollection(excludedSubtreesURI)
+                + HashCollection(permittedSubtreesDN)
+                + HashCollection(permittedSubtreesDNS)
+                + HashCollection(permittedSubtreesEmail)
+                + HashCollection(permittedSubtreesIP)
+                + HashCollection(permittedSubtreesURI);
+        }
+
+        private int HashCollection(ICollection coll)
+        {
+            if (coll == null)
+            {
+                return 0;
+            }
+            int hash = 0;
+            IEnumerator it1 = coll.GetEnumerator();
+            while (it1.MoveNext())
+            {
+                Object o = it1.Current;
+                if (o is byte[])
+                {
+                    hash += Org.BouncyCastle.Utilities.Arrays.GetHashCode((byte[])o);
+                }
+                else
+                {
+                    hash += o.GetHashCode();
+                }
+            }
+            return hash;
+        }
+
+		public override bool Equals(Object o)
+		{
+			if (!(o is PkixNameConstraintValidator))
+				return false;
+
+			PkixNameConstraintValidator constraintValidator = (PkixNameConstraintValidator)o;
+
+			return CollectionsAreEqual(constraintValidator.excludedSubtreesDN, excludedSubtreesDN)
+				&& CollectionsAreEqual(constraintValidator.excludedSubtreesDNS, excludedSubtreesDNS)
+				&& CollectionsAreEqual(constraintValidator.excludedSubtreesEmail, excludedSubtreesEmail)
+				&& CollectionsAreEqual(constraintValidator.excludedSubtreesIP, excludedSubtreesIP)
+				&& CollectionsAreEqual(constraintValidator.excludedSubtreesURI, excludedSubtreesURI)
+				&& CollectionsAreEqual(constraintValidator.permittedSubtreesDN, permittedSubtreesDN)
+				&& CollectionsAreEqual(constraintValidator.permittedSubtreesDNS, permittedSubtreesDNS)
+				&& CollectionsAreEqual(constraintValidator.permittedSubtreesEmail, permittedSubtreesEmail)
+				&& CollectionsAreEqual(constraintValidator.permittedSubtreesIP, permittedSubtreesIP)
+				&& CollectionsAreEqual(constraintValidator.permittedSubtreesURI, permittedSubtreesURI);
+		}
+
+        private bool CollectionsAreEqual(ICollection coll1, ICollection coll2)
+        {
+            if (coll1 == coll2)
+            {
+                return true;
+            }
+            if (coll1 == null || coll2 == null)
+            {
+                return false;
+            }
+            if (coll1.Count != coll2.Count)
+            {
+                return false;
+            }
+            IEnumerator it1 = coll1.GetEnumerator();
+
+            while (it1.MoveNext())
+            {
+                Object a = it1.Current;
+                IEnumerator it2 = coll2.GetEnumerator();
+                bool found = false;
+                while (it2.MoveNext())
+                {
+                    Object b = it2.Current;
+                    if (SpecialEquals(a, b))
+                    {
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        private bool SpecialEquals(Object o1, Object o2)
+        {
+            if (o1 == o2)
+            {
+                return true;
+            }
+            if (o1 == null || o2 == null)
+            {
+                return false;
+            }
+            if ((o1 is byte[]) && (o2 is byte[]))
+            {
+                return Org.BouncyCastle.Utilities.Arrays.AreEqual((byte[])o1, (byte[])o2);
+            }
+            else
+            {
+                return o1.Equals(o2);
+            }
+        }
+
+        /**
+         * Stringifies an IPv4 or v6 address with subnet mask.
+         *
+         * @param ip The IP with subnet mask.
+         * @return The stringified IP address.
+         */
+        private String StringifyIP(byte[] ip)
+        {
+            String temp = "";
+            for (int i = 0; i < ip.Length / 2; i++)
+            {
+                //temp += Integer.toString(ip[i] & 0x00FF) + ".";
+                temp += (ip[i] & 0x00FF) + ".";
+            }
+            temp = temp.Substring(0, temp.Length - 1);
+            temp += "/";
+            for (int i = ip.Length / 2; i < ip.Length; i++)
+            {
+                //temp += Integer.toString(ip[i] & 0x00FF) + ".";
+                temp += (ip[i] & 0x00FF) + ".";
+            }
+            temp = temp.Substring(0, temp.Length - 1);
+            return temp;
+        }
+
+        private String StringifyIPCollection(ISet ips)
+        {
+            String temp = "";
+            temp += "[";
+            for (IEnumerator it = ips.GetEnumerator(); it.MoveNext(); )
+            {
+                temp += StringifyIP((byte[])it.Current) + ",";
+            }
+            if (temp.Length > 1)
+            {
+                temp = temp.Substring(0, temp.Length - 1);
+            }
+            temp += "]";
+
+            return temp;
+        }
+
+        public override String ToString()
+        {
+            String temp = "";
+
+            temp += "permitted:\n";
+            if (permittedSubtreesDN != null)
+            {
+                temp += "DN:\n";
+                temp += permittedSubtreesDN.ToString() + "\n";
+            }
+            if (permittedSubtreesDNS != null)
+            {
+                temp += "DNS:\n";
+                temp += permittedSubtreesDNS.ToString() + "\n";
+            }
+            if (permittedSubtreesEmail != null)
+            {
+                temp += "Email:\n";
+                temp += permittedSubtreesEmail.ToString() + "\n";
+            }
+            if (permittedSubtreesURI != null)
+            {
+                temp += "URI:\n";
+                temp += permittedSubtreesURI.ToString() + "\n";
+            }
+            if (permittedSubtreesIP != null)
+            {
+                temp += "IP:\n";
+                temp += StringifyIPCollection(permittedSubtreesIP) + "\n";
+            }
+            temp += "excluded:\n";
+            if (!(excludedSubtreesDN.IsEmpty))
+            {
+                temp += "DN:\n";
+                temp += excludedSubtreesDN.ToString() + "\n";
+            }
+            if (!excludedSubtreesDNS.IsEmpty)
+            {
+                temp += "DNS:\n";
+                temp += excludedSubtreesDNS.ToString() + "\n";
+            }
+            if (!excludedSubtreesEmail.IsEmpty)
+            {
+                temp += "Email:\n";
+                temp += excludedSubtreesEmail.ToString() + "\n";
+            }
+            if (!excludedSubtreesURI.IsEmpty)
+            {
+                temp += "URI:\n";
+                temp += excludedSubtreesURI.ToString() + "\n";
+            }
+            if (!excludedSubtreesIP.IsEmpty)
+            {
+                temp += "IP:\n";
+                temp += StringifyIPCollection(excludedSubtreesIP) + "\n";
+            }
+            return temp;
+        }
+
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidatorException.cs b/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidatorException.cs
new file mode 100644
index 0000000..432d7bd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixNameConstraintValidatorException.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Pkix
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PkixNameConstraintValidatorException
+        : Exception
+    {
+        public PkixNameConstraintValidatorException(String msg)
+            : base(msg)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixParameters.cs b/BouncyCastle.AxCrypt/src/pkix/PkixParameters.cs
new file mode 100644
index 0000000..6df1b64
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixParameters.cs
@@ -0,0 +1,893 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixParameters.
+	/// </summary>
+	public class PkixParameters
+//		: ICertPathParameters
+	{
+		/**
+		* This is the default PKIX validity model. Actually there are two variants
+		* of this: The PKIX model and the modified PKIX model. The PKIX model
+		* verifies that all involved certificates must have been valid at the
+		* current time. The modified PKIX model verifies that all involved
+		* certificates were valid at the signing time. Both are indirectly choosen
+		* with the {@link PKIXParameters#setDate(java.util.Date)} method, so this
+		* methods sets the Date when <em>all</em> certificates must have been
+		* valid.
+		*/
+		public const int PkixValidityModel = 0;
+
+		/**
+		* This model uses the following validity model. Each certificate must have
+		* been valid at the moment where is was used. That means the end
+		* certificate must have been valid at the time the signature was done. The
+		* CA certificate which signed the end certificate must have been valid,
+		* when the end certificate was signed. The CA (or Root CA) certificate must
+		* have been valid, when the CA certificate was signed and so on. So the
+		* {@link PKIXParameters#setDate(java.util.Date)} method sets the time, when
+		* the <em>end certificate</em> must have been valid. <p/> It is used e.g.
+		* in the German signature law.
+		*/
+		public const int ChainValidityModel = 1;
+
+		private ISet trustAnchors;
+		private DateTimeObject date;
+		private IList certPathCheckers;
+		private bool revocationEnabled = true;
+		private ISet initialPolicies;
+		//private bool checkOnlyEECertificateCrl = false;
+		private bool explicitPolicyRequired = false;
+		private bool anyPolicyInhibited = false;
+		private bool policyMappingInhibited = false;
+		private bool policyQualifiersRejected = true;
+		private IX509Selector certSelector;
+		private IList stores;
+		private IX509Selector selector;
+		private bool additionalLocationsEnabled;
+		private IList additionalStores;
+		private ISet trustedACIssuers;
+		private ISet necessaryACAttributes;
+		private ISet prohibitedACAttributes;
+		private ISet attrCertCheckers;
+		private int validityModel = PkixValidityModel;
+		private bool useDeltas = false;
+
+		/**
+		 * Creates an instance of PKIXParameters with the specified Set of
+		 * most-trusted CAs. Each element of the set is a TrustAnchor.<br />
+		 * <br />
+		 * Note that the Set is copied to protect against subsequent modifications.
+		 *
+		 * @param trustAnchors
+		 *            a Set of TrustAnchors
+		 *
+		 * @exception InvalidAlgorithmParameterException
+		 *                if the specified Set is empty
+		 *                <code>(trustAnchors.isEmpty() == true)</code>
+		 * @exception NullPointerException
+		 *                if the specified Set is <code>null</code>
+		 * @exception ClassCastException
+		 *                if any of the elements in the Set are not of type
+		 *                <code>java.security.cert.TrustAnchor</code>
+		 */
+		public PkixParameters(
+			ISet trustAnchors)
+		{
+			SetTrustAnchors(trustAnchors);
+
+			this.initialPolicies = new HashSet();
+			this.certPathCheckers = Platform.CreateArrayList();
+            this.stores = Platform.CreateArrayList();
+			this.additionalStores = Platform.CreateArrayList();
+			this.trustedACIssuers = new HashSet();
+			this.necessaryACAttributes = new HashSet();
+			this.prohibitedACAttributes = new HashSet();
+			this.attrCertCheckers = new HashSet();
+		}
+
+//		// TODO implement for other keystores (see Java build)?
+//		/**
+//		 * Creates an instance of <code>PKIXParameters</code> that
+//		 * populates the set of most-trusted CAs from the trusted
+//		 * certificate entries contained in the specified <code>KeyStore</code>.
+//		 * Only keystore entries that contain trusted <code>X509Certificates</code>
+//		 * are considered; all other certificate types are ignored.
+//		 *
+//		 * @param keystore a <code>KeyStore</code> from which the set of
+//		 * most-trusted CAs will be populated
+//		 * @throws KeyStoreException if the keystore has not been initialized
+//		 * @throws InvalidAlgorithmParameterException if the keystore does
+//		 * not contain at least one trusted certificate entry
+//		 * @throws NullPointerException if the keystore is <code>null</code>
+//		 */
+//		public PkixParameters(
+//			Pkcs12Store keystore)
+////			throws KeyStoreException, InvalidAlgorithmParameterException
+//		{
+//			if (keystore == null)
+//				throw new ArgumentNullException("keystore");
+//			ISet trustAnchors = new HashSet();
+//			foreach (string alias in keystore.Aliases)
+//			{
+//				if (keystore.IsCertificateEntry(alias))
+//				{
+//					X509CertificateEntry x509Entry = keystore.GetCertificate(alias);
+//					trustAnchors.Add(new TrustAnchor(x509Entry.Certificate, null));
+//				}
+//			}
+//			SetTrustAnchors(trustAnchors);
+//
+//			this.initialPolicies = new HashSet();
+//			this.certPathCheckers = new ArrayList();
+//			this.stores = new ArrayList();
+//			this.additionalStores = new ArrayList();
+//			this.trustedACIssuers = new HashSet();
+//			this.necessaryACAttributes = new HashSet();
+//			this.prohibitedACAttributes = new HashSet();
+//			this.attrCertCheckers = new HashSet();
+//		}
+
+		public virtual bool IsRevocationEnabled
+		{
+			get { return revocationEnabled; }
+			set { revocationEnabled = value; }
+		}
+
+		public virtual bool IsExplicitPolicyRequired
+		{
+			get { return explicitPolicyRequired; }
+			set { this.explicitPolicyRequired = value; }
+		}
+
+		public virtual bool IsAnyPolicyInhibited
+		{
+			get { return anyPolicyInhibited; }
+			set { this.anyPolicyInhibited = value; }
+		}
+
+		public virtual bool IsPolicyMappingInhibited
+		{
+			get { return policyMappingInhibited; }
+			set { this.policyMappingInhibited = value; }
+		}
+
+		public virtual bool IsPolicyQualifiersRejected
+		{
+			get { return policyQualifiersRejected; }
+			set { this.policyQualifiersRejected = value; }
+		}
+
+		//public bool IsCheckOnlyEECertificateCrl
+		//{
+		//	get { return this.checkOnlyEECertificateCrl; }
+		//	set { this.checkOnlyEECertificateCrl = value; }
+		//}
+
+		public virtual DateTimeObject Date
+		{
+			get { return this.date; }
+			set { this.date = value; }
+		}
+
+		// Returns a Set of the most-trusted CAs.
+		public virtual ISet GetTrustAnchors()
+		{
+			return new HashSet(this.trustAnchors);
+		}
+
+		// Sets the set of most-trusted CAs.
+		// Set is copied to protect against subsequent modifications.
+		public virtual void SetTrustAnchors(
+			ISet tas)
+		{
+			if (tas == null)
+				throw new ArgumentNullException("value");
+			if (tas.IsEmpty)
+				throw new ArgumentException("non-empty set required", "value");
+
+			// Explicit copy to enforce type-safety
+			this.trustAnchors = new HashSet();
+			foreach (TrustAnchor ta in tas)
+			{
+				if (ta != null)
+				{
+					trustAnchors.Add(ta);
+				}
+			}
+		}
+
+		/**
+		* Returns the required constraints on the target certificate. The
+		* constraints are returned as an instance of CertSelector. If
+		* <code>null</code>, no constraints are defined.<br />
+		* <br />
+		* Note that the CertSelector returned is cloned to protect against
+		* subsequent modifications.
+		*
+		* @return a CertSelector specifying the constraints on the target
+		*         certificate (or <code>null</code>)
+		*
+		* @see #setTargetCertConstraints(CertSelector)
+		*/
+		public virtual X509CertStoreSelector GetTargetCertConstraints()
+		{
+			if (certSelector == null)
+			{
+				return null;
+			}
+
+			return (X509CertStoreSelector)certSelector.Clone();
+		}
+
+		/**
+		 * Sets the required constraints on the target certificate. The constraints
+		 * are specified as an instance of CertSelector. If null, no constraints are
+		 * defined.<br />
+		 * <br />
+		 * Note that the CertSelector specified is cloned to protect against
+		 * subsequent modifications.
+		 *
+		 * @param selector
+		 *            a CertSelector specifying the constraints on the target
+		 *            certificate (or <code>null</code>)
+		 *
+		 * @see #getTargetCertConstraints()
+		 */
+		public virtual void SetTargetCertConstraints(
+			IX509Selector selector)
+		{
+			if (selector == null)
+			{
+				certSelector = null;
+			}
+			else
+			{
+				certSelector = (IX509Selector)selector.Clone();
+			}
+		}
+
+		/**
+		* Returns an immutable Set of initial policy identifiers (OID strings),
+		* indicating that any one of these policies would be acceptable to the
+		* certificate user for the purposes of certification path processing. The
+		* default return value is an empty <code>Set</code>, which is
+		* interpreted as meaning that any policy would be acceptable.
+		*
+		* @return an immutable <code>Set</code> of initial policy OIDs in String
+		*         format, or an empty <code>Set</code> (implying any policy is
+		*         acceptable). Never returns <code>null</code>.
+		*
+		* @see #setInitialPolicies(java.util.Set)
+		*/
+		public virtual ISet GetInitialPolicies()
+		{
+			ISet returnSet = initialPolicies;
+
+			// TODO Can it really be null?
+			if (initialPolicies == null)
+			{
+				returnSet = new HashSet();
+			}
+
+			return new HashSet(returnSet);
+		}
+
+		/**
+		* Sets the <code>Set</code> of initial policy identifiers (OID strings),
+		* indicating that any one of these policies would be acceptable to the
+		* certificate user for the purposes of certification path processing. By
+		* default, any policy is acceptable (i.e. all policies), so a user that
+		* wants to allow any policy as acceptable does not need to call this
+		* method, or can call it with an empty <code>Set</code> (or
+		* <code>null</code>).<br />
+		* <br />
+		* Note that the Set is copied to protect against subsequent modifications.<br />
+		* <br />
+		*
+		* @param initialPolicies
+		*            a Set of initial policy OIDs in String format (or
+		*            <code>null</code>)
+		*
+		* @exception ClassCastException
+		*                if any of the elements in the set are not of type String
+		*
+		* @see #getInitialPolicies()
+		*/
+		public virtual void SetInitialPolicies(
+			ISet initialPolicies)
+		{
+			this.initialPolicies = new HashSet();
+			if (initialPolicies != null)
+			{
+				foreach (string obj in initialPolicies)
+				{
+					if (obj != null)
+					{
+						this.initialPolicies.Add(obj);
+					}
+				}
+			}
+		}
+
+		/**
+		* Sets a <code>List</code> of additional certification path checkers. If
+		* the specified List contains an object that is not a PKIXCertPathChecker,
+		* it is ignored.<br />
+		* <br />
+		* Each <code>PKIXCertPathChecker</code> specified implements additional
+		* checks on a certificate. Typically, these are checks to process and
+		* verify private extensions contained in certificates. Each
+		* <code>PKIXCertPathChecker</code> should be instantiated with any
+		* initialization parameters needed to execute the check.<br />
+		* <br />
+		* This method allows sophisticated applications to extend a PKIX
+		* <code>CertPathValidator</code> or <code>CertPathBuilder</code>. Each
+		* of the specified PKIXCertPathCheckers will be called, in turn, by a PKIX
+		* <code>CertPathValidator</code> or <code>CertPathBuilder</code> for
+		* each certificate processed or validated.<br />
+		* <br />
+		* Regardless of whether these additional PKIXCertPathCheckers are set, a
+		* PKIX <code>CertPathValidator</code> or <code>CertPathBuilder</code>
+		* must perform all of the required PKIX checks on each certificate. The one
+		* exception to this rule is if the RevocationEnabled flag is set to false
+		* (see the {@link #setRevocationEnabled(boolean) setRevocationEnabled}
+		* method).<br />
+		* <br />
+		* Note that the List supplied here is copied and each PKIXCertPathChecker
+		* in the list is cloned to protect against subsequent modifications.
+		*
+		* @param checkers
+		*            a List of PKIXCertPathCheckers. May be null, in which case no
+		*            additional checkers will be used.
+		* @exception ClassCastException
+		*                if any of the elements in the list are not of type
+		*                <code>java.security.cert.PKIXCertPathChecker</code>
+		* @see #getCertPathCheckers()
+		*/
+		public virtual void SetCertPathCheckers(IList checkers)
+		{
+            certPathCheckers = Platform.CreateArrayList();
+			if (checkers != null)
+			{
+				foreach (PkixCertPathChecker obj in checkers)
+				{
+					certPathCheckers.Add(obj.Clone());
+				}
+			}
+		}
+
+		/**
+		 * Returns the List of certification path checkers. Each PKIXCertPathChecker
+		 * in the returned IList is cloned to protect against subsequent modifications.
+		 *
+		 * @return an immutable List of PKIXCertPathCheckers (may be empty, but not
+		 *         <code>null</code>)
+		 *
+		 * @see #setCertPathCheckers(java.util.List)
+		 */
+		public virtual IList GetCertPathCheckers()
+		{
+			IList checkers = Platform.CreateArrayList();
+			foreach (PkixCertPathChecker obj in certPathCheckers)
+			{
+				checkers.Add(obj.Clone());
+			}
+			return checkers;
+		}
+
+		/**
+		 * Adds a <code>PKIXCertPathChecker</code> to the list of certification
+		 * path checkers. See the {@link #setCertPathCheckers setCertPathCheckers}
+		 * method for more details.
+		 * <p>
+		 * Note that the <code>PKIXCertPathChecker</code> is cloned to protect
+		 * against subsequent modifications.</p>
+		 *
+		 * @param checker a <code>PKIXCertPathChecker</code> to add to the list of
+		 * checks. If <code>null</code>, the checker is ignored (not added to list).
+		 */
+		public virtual void AddCertPathChecker(
+			PkixCertPathChecker checker)
+		{
+			if (checker != null)
+			{
+				certPathCheckers.Add(checker.Clone());
+			}
+		}
+
+		public virtual object Clone()
+		{
+			// FIXME Check this whole method against the Java implementation!
+
+			PkixParameters parameters = new PkixParameters(GetTrustAnchors());
+			parameters.SetParams(this);
+			return parameters;
+
+
+//			PkixParameters obj = new PkixParameters(new HashSet());
+////			(PkixParameters) this.MemberwiseClone();
+//			obj.x509Stores = new ArrayList(x509Stores);
+//			obj.certPathCheckers = new ArrayList(certPathCheckers);
+//
+//			//Iterator iter = certPathCheckers.iterator();
+//			//obj.certPathCheckers = new ArrayList();
+//			//while (iter.hasNext())
+//			//{
+//			//	obj.certPathCheckers.add(((PKIXCertPathChecker)iter.next())
+//			//		.clone());
+//			//}
+//			//if (initialPolicies != null)
+//			//{
+//			//	obj.initialPolicies = new HashSet(initialPolicies);
+//			//}
+////			if (trustAnchors != null)
+////			{
+////				obj.trustAnchors = new HashSet(trustAnchors);
+////			}
+////			if (certSelector != null)
+////			{
+////				obj.certSelector = (X509CertStoreSelector) certSelector.Clone();
+////			}
+//			return obj;
+		}
+
+		/**
+		* Method to support <code>Clone()</code> under J2ME.
+		* <code>super.Clone()</code> does not exist and fields are not copied.
+		*
+		* @param params Parameters to set. If this are
+		*            <code>ExtendedPkixParameters</code> they are copied to.
+		*/
+		protected virtual void SetParams(
+			PkixParameters parameters)
+		{
+			Date = parameters.Date;
+			SetCertPathCheckers(parameters.GetCertPathCheckers());
+			IsAnyPolicyInhibited = parameters.IsAnyPolicyInhibited;
+			IsExplicitPolicyRequired = parameters.IsExplicitPolicyRequired;
+			IsPolicyMappingInhibited = parameters.IsPolicyMappingInhibited;
+			IsRevocationEnabled = parameters.IsRevocationEnabled;
+			SetInitialPolicies(parameters.GetInitialPolicies());
+			IsPolicyQualifiersRejected = parameters.IsPolicyQualifiersRejected;
+			SetTargetCertConstraints(parameters.GetTargetCertConstraints());
+			SetTrustAnchors(parameters.GetTrustAnchors());
+
+			validityModel = parameters.validityModel;
+			useDeltas = parameters.useDeltas;
+			additionalLocationsEnabled = parameters.additionalLocationsEnabled;
+			selector = parameters.selector == null ? null
+				: (IX509Selector) parameters.selector.Clone();
+			stores = Platform.CreateArrayList(parameters.stores);
+            additionalStores = Platform.CreateArrayList(parameters.additionalStores);
+			trustedACIssuers = new HashSet(parameters.trustedACIssuers);
+			prohibitedACAttributes = new HashSet(parameters.prohibitedACAttributes);
+			necessaryACAttributes = new HashSet(parameters.necessaryACAttributes);
+			attrCertCheckers = new HashSet(parameters.attrCertCheckers);
+		}
+
+		/**
+		 * Whether delta CRLs should be used for checking the revocation status.
+		 * Defaults to <code>false</code>.
+		 */
+		public virtual bool IsUseDeltasEnabled
+		{
+			get { return useDeltas; }
+			set { useDeltas = value; }
+		}
+
+		/**
+		* The validity model.
+		* @see #CHAIN_VALIDITY_MODEL
+		* @see #PKIX_VALIDITY_MODEL
+		*/
+		public virtual int ValidityModel
+		{
+			get { return validityModel; }
+			set { validityModel = value; }
+		}
+
+		/**
+		* Sets the Bouncy Castle Stores for finding CRLs, certificates, attribute
+		* certificates or cross certificates.
+		* <p>
+		* The <code>IList</code> is cloned.
+		* </p>
+		*
+		* @param stores A list of stores to use.
+		* @see #getStores
+		* @throws ClassCastException if an element of <code>stores</code> is not
+		*             a {@link Store}.
+		*/
+		public virtual void SetStores(
+			IList stores)
+		{
+			if (stores == null)
+			{
+                this.stores = Platform.CreateArrayList();
+			}
+			else
+			{
+				foreach (object obj in stores)
+				{
+					if (!(obj is IX509Store))
+					{
+						throw new InvalidCastException(
+							"All elements of list must be of type " + typeof(IX509Store).FullName);
+					}
+				}
+                this.stores = Platform.CreateArrayList(stores);
+			}
+		}
+
+		/**
+		* Adds a Bouncy Castle {@link Store} to find CRLs, certificates, attribute
+		* certificates or cross certificates.
+		* <p>
+		* This method should be used to add local stores, like collection based
+		* X.509 stores, if available. Local stores should be considered first,
+		* before trying to use additional (remote) locations, because they do not
+		* need possible additional network traffic.
+		* </p><p>
+		* If <code>store</code> is <code>null</code> it is ignored.
+		* </p>
+		*
+		* @param store The store to add.
+		* @see #getStores
+		*/
+		public virtual void AddStore(
+			IX509Store store)
+		{
+			if (store != null)
+			{
+				stores.Add(store);
+			}
+		}
+
+		/**
+		* Adds an additional Bouncy Castle {@link Store} to find CRLs, certificates,
+		* attribute certificates or cross certificates.
+		* <p>
+		* You should not use this method. This method is used for adding additional
+		* X.509 stores, which are used to add (remote) locations, e.g. LDAP, found
+		* during X.509 object processing, e.g. in certificates or CRLs. This method
+		* is used in PKIX certification path processing.
+		* </p><p>
+		* If <code>store</code> is <code>null</code> it is ignored.
+		* </p>
+		*
+		* @param store The store to add.
+		* @see #getStores()
+		*/
+		public virtual void AddAdditionalStore(
+			IX509Store store)
+		{
+			if (store != null)
+			{
+				additionalStores.Add(store);
+			}
+		}
+
+		/**
+		* Returns an <code>IList</code> of additional Bouncy Castle
+		* <code>Store</code>s used for finding CRLs, certificates, attribute
+		* certificates or cross certificates.
+		*
+		* @return an immutable <code>IList</code> of additional Bouncy Castle
+		*         <code>Store</code>s. Never <code>null</code>.
+		*
+		* @see #addAddionalStore(Store)
+		*/
+		public virtual IList GetAdditionalStores()
+		{
+            return Platform.CreateArrayList(additionalStores);
+		}
+
+		/**
+		* Returns an <code>IList</code> of Bouncy Castle
+		* <code>Store</code>s used for finding CRLs, certificates, attribute
+		* certificates or cross certificates.
+		*
+		* @return an immutable <code>IList</code> of Bouncy Castle
+		*         <code>Store</code>s. Never <code>null</code>.
+		*
+		* @see #setStores(IList)
+		*/
+		public virtual IList GetStores()
+		{
+            return Platform.CreateArrayList(stores);
+		}
+
+		/**
+		* Returns if additional {@link X509Store}s for locations like LDAP found
+		* in certificates or CRLs should be used.
+		*
+		* @return Returns <code>true</code> if additional stores are used.
+		*/
+		public virtual bool IsAdditionalLocationsEnabled
+		{
+			get { return additionalLocationsEnabled; }
+		}
+
+		/**
+		* Sets if additional {@link X509Store}s for locations like LDAP found in
+		* certificates or CRLs should be used.
+		*
+		* @param enabled <code>true</code> if additional stores are used.
+		*/
+		public virtual void SetAdditionalLocationsEnabled(
+			bool enabled)
+		{
+			additionalLocationsEnabled = enabled;
+		}
+
+		/**
+		* Returns the required constraints on the target certificate or attribute
+		* certificate. The constraints are returned as an instance of
+		* <code>IX509Selector</code>. If <code>null</code>, no constraints are
+		* defined.
+		*
+		* <p>
+		* The target certificate in a PKIX path may be a certificate or an
+		* attribute certificate.
+		* </p><p>
+		* Note that the <code>IX509Selector</code> returned is cloned to protect
+		* against subsequent modifications.
+		* </p>
+		* @return a <code>IX509Selector</code> specifying the constraints on the
+		*         target certificate or attribute certificate (or <code>null</code>)
+		* @see #setTargetConstraints
+		* @see X509CertStoreSelector
+		* @see X509AttributeCertStoreSelector
+		*/
+		public virtual IX509Selector GetTargetConstraints()
+		{
+			if (selector != null)
+			{
+				return (IX509Selector) selector.Clone();
+			}
+			else
+			{
+				return null;
+			}
+		}
+
+		/**
+		* Sets the required constraints on the target certificate or attribute
+		* certificate. The constraints are specified as an instance of
+		* <code>IX509Selector</code>. If <code>null</code>, no constraints are
+		* defined.
+		* <p>
+		* The target certificate in a PKIX path may be a certificate or an
+		* attribute certificate.
+		* </p><p>
+		* Note that the <code>IX509Selector</code> specified is cloned to protect
+		* against subsequent modifications.
+		* </p>
+		*
+		* @param selector a <code>IX509Selector</code> specifying the constraints on
+		*            the target certificate or attribute certificate (or
+		*            <code>null</code>)
+		* @see #getTargetConstraints
+		* @see X509CertStoreSelector
+		* @see X509AttributeCertStoreSelector
+		*/
+		public virtual void SetTargetConstraints(IX509Selector selector)
+		{
+			if (selector != null)
+			{
+				this.selector = (IX509Selector) selector.Clone();
+			}
+			else
+			{
+				this.selector = null;
+			}
+		}
+
+		/**
+		* Returns the trusted attribute certificate issuers. If attribute
+		* certificates is verified the trusted AC issuers must be set.
+		* <p>
+		* The returned <code>ISet</code> consists of <code>TrustAnchor</code>s.
+		* </p><p>
+		* The returned <code>ISet</code> is immutable. Never <code>null</code>
+		* </p>
+		*
+		* @return Returns an immutable set of the trusted AC issuers.
+		*/
+		public virtual ISet GetTrustedACIssuers()
+		{
+			return new HashSet(trustedACIssuers);
+		}
+
+		/**
+		* Sets the trusted attribute certificate issuers. If attribute certificates
+		* is verified the trusted AC issuers must be set.
+		* <p>
+		* The <code>trustedACIssuers</code> must be a <code>ISet</code> of
+		* <code>TrustAnchor</code>
+		* </p><p>
+		* The given set is cloned.
+		* </p>
+		*
+		* @param trustedACIssuers The trusted AC issuers to set. Is never
+		*            <code>null</code>.
+		* @throws ClassCastException if an element of <code>stores</code> is not
+		*             a <code>TrustAnchor</code>.
+		*/
+		public virtual void SetTrustedACIssuers(
+			ISet trustedACIssuers)
+		{
+			if (trustedACIssuers == null)
+			{
+				this.trustedACIssuers = new HashSet();
+			}
+			else
+			{
+				foreach (object obj in trustedACIssuers)
+				{
+					if (!(obj is TrustAnchor))
+					{
+						throw new InvalidCastException("All elements of set must be "
+							+ "of type " + typeof(TrustAnchor).Name + ".");
+					}
+				}
+				this.trustedACIssuers = new HashSet(trustedACIssuers);
+			}
+		}
+
+		/**
+		* Returns the neccessary attributes which must be contained in an attribute
+		* certificate.
+		* <p>
+		* The returned <code>ISet</code> is immutable and contains
+		* <code>String</code>s with the OIDs.
+		* </p>
+		*
+		* @return Returns the necessary AC attributes.
+		*/
+		public virtual ISet GetNecessaryACAttributes()
+		{
+			return new HashSet(necessaryACAttributes);
+		}
+
+		/**
+		* Sets the neccessary which must be contained in an attribute certificate.
+		* <p>
+		* The <code>ISet</code> must contain <code>String</code>s with the
+		* OIDs.
+		* </p><p>
+		* The set is cloned.
+		* </p>
+		*
+		* @param necessaryACAttributes The necessary AC attributes to set.
+		* @throws ClassCastException if an element of
+		*             <code>necessaryACAttributes</code> is not a
+		*             <code>String</code>.
+		*/
+		public virtual void SetNecessaryACAttributes(
+			ISet necessaryACAttributes)
+		{
+			if (necessaryACAttributes == null)
+			{
+				this.necessaryACAttributes = new HashSet();
+			}
+			else
+			{
+				foreach (object obj in necessaryACAttributes)
+				{
+					if (!(obj is string))
+					{
+						throw new InvalidCastException("All elements of set must be "
+							+ "of type string.");
+					}
+				}
+				this.necessaryACAttributes = new HashSet(necessaryACAttributes);
+			}
+		}
+
+		/**
+		* Returns the attribute certificates which are not allowed.
+		* <p>
+		* The returned <code>ISet</code> is immutable and contains
+		* <code>String</code>s with the OIDs.
+		* </p>
+		*
+		* @return Returns the prohibited AC attributes. Is never <code>null</code>.
+		*/
+		public virtual ISet GetProhibitedACAttributes()
+		{
+			return new HashSet(prohibitedACAttributes);
+		}
+
+		/**
+		* Sets the attribute certificates which are not allowed.
+		* <p>
+		* The <code>ISet</code> must contain <code>String</code>s with the
+		* OIDs.
+		* </p><p>
+		* The set is cloned.
+		* </p>
+		*
+		* @param prohibitedACAttributes The prohibited AC attributes to set.
+		* @throws ClassCastException if an element of
+		*             <code>prohibitedACAttributes</code> is not a
+		*             <code>String</code>.
+		*/
+		public virtual void SetProhibitedACAttributes(
+			ISet prohibitedACAttributes)
+		{
+			if (prohibitedACAttributes == null)
+			{
+				this.prohibitedACAttributes = new HashSet();
+			}
+			else
+			{
+				foreach (object obj in prohibitedACAttributes)
+				{
+					if (!(obj is String))
+					{
+						throw new InvalidCastException("All elements of set must be "
+							+ "of type string.");
+					}
+				}
+				this.prohibitedACAttributes = new HashSet(prohibitedACAttributes);
+			}
+		}
+
+		/**
+		* Returns the attribute certificate checker. The returned set contains
+		* {@link PKIXAttrCertChecker}s and is immutable.
+		*
+		* @return Returns the attribute certificate checker. Is never
+		*         <code>null</code>.
+		*/
+		public virtual ISet GetAttrCertCheckers()
+		{
+			return new HashSet(attrCertCheckers);
+		}
+
+		/**
+		* Sets the attribute certificate checkers.
+		* <p>
+		* All elements in the <code>ISet</code> must a {@link PKIXAttrCertChecker}.
+		* </p>
+		* <p>
+		* The given set is cloned.
+		* </p>
+		*
+		* @param attrCertCheckers The attribute certificate checkers to set. Is
+		*            never <code>null</code>.
+		* @throws ClassCastException if an element of <code>attrCertCheckers</code>
+		*             is not a <code>PKIXAttrCertChecker</code>.
+		*/
+		public virtual void SetAttrCertCheckers(
+			ISet attrCertCheckers)
+		{
+			if (attrCertCheckers == null)
+			{
+				this.attrCertCheckers = new HashSet();
+			}
+			else
+			{
+				foreach (object obj in attrCertCheckers)
+				{
+					if (!(obj is PkixAttrCertChecker))
+					{
+						throw new InvalidCastException("All elements of set must be "
+							+ "of type " + typeof(PkixAttrCertChecker).FullName + ".");
+					}
+				}
+				this.attrCertCheckers = new HashSet(attrCertCheckers);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/PkixPolicyNode.cs b/BouncyCastle.AxCrypt/src/pkix/PkixPolicyNode.cs
new file mode 100644
index 0000000..fc5b82f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/PkixPolicyNode.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// Summary description for PkixPolicyNode.
+	/// </summary>
+	public class PkixPolicyNode
+//		: IPolicyNode
+	{
+		protected IList				mChildren;
+		protected int				mDepth;
+		protected ISet				mExpectedPolicies;
+		protected PkixPolicyNode	mParent;
+		protected ISet				mPolicyQualifiers;
+		protected string			mValidPolicy;
+		protected bool				mCritical;
+
+		public virtual int Depth
+		{
+			get { return this.mDepth; }
+		}
+
+		public virtual IEnumerable Children
+		{
+			get { return new EnumerableProxy(mChildren); }
+		}
+
+		public virtual bool IsCritical
+		{
+			get { return this.mCritical; }
+			set { this.mCritical = value; }
+		}
+
+		public virtual ISet PolicyQualifiers
+		{
+			get { return new HashSet(this.mPolicyQualifiers); }
+		}
+
+		public virtual string ValidPolicy
+		{
+			get { return this.mValidPolicy; }
+		}
+
+		public virtual bool HasChildren
+		{
+			get { return mChildren.Count != 0; }
+		}
+
+		public virtual ISet ExpectedPolicies
+		{
+			get { return new HashSet(this.mExpectedPolicies); }
+			set { this.mExpectedPolicies = new HashSet(value); }
+		}
+
+		public virtual PkixPolicyNode Parent
+		{
+			get { return this.mParent; }
+			set { this.mParent = value; }
+		}
+
+		/// Constructors
+		public PkixPolicyNode(
+			IList			children,
+			int				depth,
+			ISet			expectedPolicies,
+			PkixPolicyNode	parent,
+			ISet			policyQualifiers,
+			string			validPolicy,
+			bool			critical)
+		{
+            if (children == null)
+            {
+                this.mChildren = Platform.CreateArrayList();
+            }
+            else
+            {
+                this.mChildren = Platform.CreateArrayList(children);
+            }
+
+            this.mDepth = depth;
+			this.mExpectedPolicies = expectedPolicies;
+			this.mParent = parent;
+			this.mPolicyQualifiers = policyQualifiers;
+			this.mValidPolicy = validPolicy;
+			this.mCritical = critical;
+		}
+
+		public virtual void AddChild(
+			PkixPolicyNode child)
+		{
+			child.Parent = this;
+			mChildren.Add(child);
+		}
+
+		public virtual void RemoveChild(
+			PkixPolicyNode child)
+		{
+			mChildren.Remove(child);
+		}
+
+		public override string ToString()
+		{
+			return ToString("");
+		}
+
+		public virtual string ToString(
+			string indent)
+		{
+			StringBuilder buf = new StringBuilder();
+			buf.Append(indent);
+			buf.Append(mValidPolicy);
+			buf.Append(" {");
+			buf.Append(Platform.NewLine);
+
+			foreach (PkixPolicyNode child in mChildren)
+			{
+				buf.Append(child.ToString(indent + "    "));
+			}
+
+			buf.Append(indent);
+			buf.Append("}");
+			buf.Append(Platform.NewLine);
+			return buf.ToString();
+		}
+
+		public virtual object Clone()
+		{
+			return Copy();
+		}
+
+		public virtual PkixPolicyNode Copy()
+		{
+			PkixPolicyNode node = new PkixPolicyNode(
+                Platform.CreateArrayList(),
+				mDepth,
+				new HashSet(mExpectedPolicies),
+				null,
+				new HashSet(mPolicyQualifiers),
+				mValidPolicy,
+				mCritical);
+
+			foreach (PkixPolicyNode child in mChildren)
+			{
+				PkixPolicyNode copy = child.Copy();
+				copy.Parent = node;
+				node.AddChild(copy);
+			}
+
+			return node;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/ReasonsMask.cs b/BouncyCastle.AxCrypt/src/pkix/ReasonsMask.cs
new file mode 100644
index 0000000..e389bfe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/ReasonsMask.cs
@@ -0,0 +1,96 @@
+using System;
+
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// This class helps to handle CRL revocation reasons mask. Each CRL handles a
+	/// certain set of revocation reasons.
+	/// </summary>
+	internal class ReasonsMask
+	{
+		private int _reasons;
+
+		/// <summary>
+		/// Constructs are reason mask with the reasons.
+		/// </summary>
+		/// <param name="reasons">The reasons.</param>
+		internal ReasonsMask(
+			int reasons)
+		{
+			_reasons = reasons;
+		}
+
+		/// <summary>
+		/// A reason mask with no reason.
+		/// </summary>
+		internal ReasonsMask()
+			: this(0)
+		{
+		}
+
+		/// <summary>
+		/// A mask with all revocation reasons.
+		/// </summary>
+		internal static readonly ReasonsMask AllReasons = new ReasonsMask(
+				ReasonFlags.AACompromise | ReasonFlags.AffiliationChanged | ReasonFlags.CACompromise
+			|	ReasonFlags.CertificateHold | ReasonFlags.CessationOfOperation
+			|	ReasonFlags.KeyCompromise | ReasonFlags.PrivilegeWithdrawn | ReasonFlags.Unused
+			|	ReasonFlags.Superseded);
+
+		/**
+		 * Adds all reasons from the reasons mask to this mask.
+		 *
+		 * @param mask The reasons mask to add.
+		 */
+		internal void AddReasons(
+			ReasonsMask mask)
+		{
+			_reasons = _reasons | mask.Reasons.IntValue;
+		}
+
+		/// <summary>
+		/// Returns <code>true</code> if this reasons mask contains all possible
+		/// reasons.
+		/// </summary>
+		/// <returns>true if this reasons mask contains all possible reasons.
+		/// </returns>
+		internal bool IsAllReasons
+		{
+			get { return _reasons == AllReasons._reasons; }
+		}
+
+		/// <summary>
+		/// Intersects this mask with the given reasons mask.
+		/// </summary>
+		/// <param name="mask">mask The mask to intersect with.</param>
+		/// <returns>The intersection of this and teh given mask.</returns>
+		internal ReasonsMask Intersect(
+			ReasonsMask mask)
+		{
+			ReasonsMask _mask = new ReasonsMask();
+			_mask.AddReasons(new ReasonsMask(_reasons & mask.Reasons.IntValue));
+			return _mask;
+		}
+
+		/// <summary>
+		/// Returns <c>true</c> if the passed reasons mask has new reasons.
+		/// </summary>
+		/// <param name="mask">The reasons mask which should be tested for new reasons.</param>
+		/// <returns><c>true</c> if the passed reasons mask has new reasons.</returns>
+		internal bool HasNewReasons(
+			ReasonsMask mask)
+		{
+			return ((_reasons | mask.Reasons.IntValue ^ _reasons) != 0);
+		}
+
+		/// <summary>
+		/// Returns the reasons in this mask.
+		/// </summary>
+		public ReasonFlags Reasons
+		{
+			get { return new ReasonFlags(_reasons); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/Rfc3280CertPathUtilities.cs b/BouncyCastle.AxCrypt/src/pkix/Rfc3280CertPathUtilities.cs
new file mode 100644
index 0000000..c6f3fbf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/Rfc3280CertPathUtilities.cs
@@ -0,0 +1,2448 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	public class Rfc3280CertPathUtilities
+	{
+		private static readonly PkixCrlUtilities CrlUtilities = new PkixCrlUtilities();
+
+		internal static readonly string ANY_POLICY = "2.5.29.32.0";
+
+		// key usage bits
+		internal static readonly int KEY_CERT_SIGN = 5;
+		internal static readonly int CRL_SIGN = 6;
+
+		/**
+		* If the complete CRL includes an issuing distribution point (IDP) CRL
+		* extension check the following:
+		* <p>
+		* (i) If the distribution point name is present in the IDP CRL extension
+		* and the distribution field is present in the DP, then verify that one of
+		* the names in the IDP matches one of the names in the DP. If the
+		* distribution point name is present in the IDP CRL extension and the
+		* distribution field is omitted from the DP, then verify that one of the
+		* names in the IDP matches one of the names in the cRLIssuer field of the
+		* DP.
+		* </p>
+		* <p>
+		* (ii) If the onlyContainsUserCerts boolean is asserted in the IDP CRL
+		* extension, verify that the certificate does not include the basic
+		* constraints extension with the cA boolean asserted.
+		* </p>
+		* <p>
+		* (iii) If the onlyContainsCACerts boolean is asserted in the IDP CRL
+		* extension, verify that the certificate includes the basic constraints
+		* extension with the cA boolean asserted.
+		* </p>
+		* <p>
+		* (iv) Verify that the onlyContainsAttributeCerts boolean is not asserted.
+		* </p>
+		*
+		* @param dp   The distribution point.
+		* @param cert The certificate.
+		* @param crl  The CRL.
+		* @throws AnnotatedException if one of the conditions is not met or an error occurs.
+		*/
+		internal static void ProcessCrlB2(
+			DistributionPoint	dp,
+			object				cert,
+			X509Crl				crl)
+		{
+			IssuingDistributionPoint idp = null;
+			try
+			{
+				idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("0 Issuing distribution point extension could not be decoded.", e);
+			}
+			// (b) (2) (i)
+			// distribution point name is present
+			if (idp != null)
+			{
+				if (idp.DistributionPoint != null)
+				{
+					// make list of names
+					DistributionPointName dpName = IssuingDistributionPoint.GetInstance(idp).DistributionPoint;
+					IList names = Platform.CreateArrayList();
+
+					if (dpName.PointType == DistributionPointName.FullName)
+					{
+						GeneralName[] genNames = GeneralNames.GetInstance(dpName.Name).GetNames();
+						for (int j = 0; j < genNames.Length; j++)
+						{
+							names.Add(genNames[j]);
+						}
+					}
+					if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer)
+					{
+						Asn1EncodableVector vec = new Asn1EncodableVector();
+						try
+						{
+							IEnumerator e = Asn1Sequence.GetInstance(
+								Asn1Sequence.FromByteArray(crl.IssuerDN.GetEncoded())).GetEnumerator();
+							while (e.MoveNext())
+							{
+								vec.Add((Asn1Encodable)e.Current);
+							}
+						}
+						catch (IOException e)
+						{
+							throw new Exception("Could not read CRL issuer.", e);
+						}
+						vec.Add(dpName.Name);
+						names.Add(new GeneralName(X509Name.GetInstance(new DerSequence(vec))));
+					}
+					bool matches = false;
+					// verify that one of the names in the IDP matches one
+					// of the names in the DP.
+					if (dp.DistributionPointName != null)
+					{
+						dpName = dp.DistributionPointName;
+						GeneralName[] genNames = null;
+						if (dpName.PointType == DistributionPointName.FullName)
+						{
+							genNames = GeneralNames.GetInstance(dpName.Name).GetNames();
+						}
+						if (dpName.PointType == DistributionPointName.NameRelativeToCrlIssuer)
+						{
+							if (dp.CrlIssuer != null)
+							{
+								genNames = dp.CrlIssuer.GetNames();
+							}
+							else
+							{
+								genNames = new GeneralName[1];
+								try
+								{
+									genNames[0] = new GeneralName(
+										PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert));
+								}
+								catch (IOException e)
+								{
+									throw new Exception("Could not read certificate issuer.", e);
+								}
+							}
+							for (int j = 0; j < genNames.Length; j++)
+							{
+								IEnumerator e = Asn1Sequence.GetInstance(genNames[j].Name.ToAsn1Object()).GetEnumerator();
+								Asn1EncodableVector vec = new Asn1EncodableVector();
+								while (e.MoveNext())
+								{
+									vec.Add((Asn1Encodable)e.Current);
+								}
+								vec.Add(dpName.Name);
+								genNames[j] = new GeneralName(X509Name.GetInstance(new DerSequence(vec)));
+							}
+						}
+						if (genNames != null)
+						{
+							for (int j = 0; j < genNames.Length; j++)
+							{
+								if (names.Contains(genNames[j]))
+								{
+									matches = true;
+									break;
+								}
+							}
+						}
+						if (!matches)
+						{
+							throw new Exception(
+								"No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
+						}
+					}
+						// verify that one of the names in
+						// the IDP matches one of the names in the cRLIssuer field of
+						// the DP
+					else
+					{
+						if (dp.CrlIssuer == null)
+						{
+							throw new Exception("Either the cRLIssuer or the distributionPoint field must "
+								+ "be contained in DistributionPoint.");
+						}
+						GeneralName[] genNames = dp.CrlIssuer.GetNames();
+						for (int j = 0; j < genNames.Length; j++)
+						{
+							if (names.Contains(genNames[j]))
+							{
+								matches = true;
+								break;
+							}
+						}
+						if (!matches)
+						{
+							throw new Exception(
+								"No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
+						}
+					}
+				}
+				BasicConstraints bc = null;
+				try
+				{
+					bc = BasicConstraints.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(
+						(IX509Extension)cert, X509Extensions.BasicConstraints));
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Basic constraints extension could not be decoded.", e);
+				}
+
+				//if (cert is X509Certificate)
+				{
+					// (b) (2) (ii)
+					if (idp.OnlyContainsUserCerts && ((bc != null) && bc.IsCA()))
+					{
+						throw new Exception("CA Cert CRL only contains user certificates.");
+					}
+
+					// (b) (2) (iii)
+					if (idp.OnlyContainsCACerts && (bc == null || !bc.IsCA()))
+					{
+						throw new Exception("End CRL only contains CA certificates.");
+					}
+				}
+
+				// (b) (2) (iv)
+				if (idp.OnlyContainsAttributeCerts)
+				{
+					throw new Exception("onlyContainsAttributeCerts boolean is asserted.");
+				}
+			}
+		}
+
+		internal static void ProcessCertBC(
+			PkixCertPath				certPath,
+			int							index,
+			PkixNameConstraintValidator	nameConstraintValidator)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			int n = certs.Count;
+			// i as defined in the algorithm description
+			int i = n - index;
+			//
+			// (b), (c) permitted and excluded subtree checking.
+			//
+			if (!(PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (i < n)))
+			{
+				X509Name principal = cert.SubjectDN;
+				Asn1InputStream aIn = new Asn1InputStream(principal.GetEncoded());
+				Asn1Sequence dns;
+
+				try
+				{
+					dns = DerSequence.GetInstance(aIn.ReadObject());
+				}
+				catch (Exception e)
+				{
+					throw new PkixCertPathValidatorException(
+						"Exception extracting subject name when checking subtrees.", e, certPath, index);
+				}
+
+				try
+				{
+					nameConstraintValidator.CheckPermittedDN(dns);
+					nameConstraintValidator.CheckExcludedDN(dns);
+				}
+				catch (PkixNameConstraintValidatorException e)
+				{
+					throw new PkixCertPathValidatorException(
+						"Subtree check for certificate subject failed.", e, certPath, index);
+				}
+
+				GeneralNames altName = null;
+				try
+				{
+					altName = GeneralNames.GetInstance(
+						PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.SubjectAlternativeName));
+				}
+				catch (Exception e)
+				{
+					throw new PkixCertPathValidatorException(
+						"Subject alternative name extension could not be decoded.", e, certPath, index);
+				}
+
+				IList emails = X509Name.GetInstance(dns).GetValueList(X509Name.EmailAddress);
+				foreach (string email in emails)
+				{
+					GeneralName emailAsGeneralName = new GeneralName(GeneralName.Rfc822Name, email);
+					try
+					{
+						nameConstraintValidator.checkPermitted(emailAsGeneralName);
+						nameConstraintValidator.checkExcluded(emailAsGeneralName);
+					}
+					catch (PkixNameConstraintValidatorException ex)
+					{
+						throw new PkixCertPathValidatorException(
+							"Subtree check for certificate subject alternative email failed.", ex, certPath, index);
+					}
+				}
+				if (altName != null)
+				{
+					GeneralName[] genNames = null;
+					try
+					{
+						genNames = altName.GetNames();
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Subject alternative name contents could not be decoded.", e, certPath, index);
+					}
+					foreach (GeneralName genName in genNames)
+					{
+						try
+						{
+							nameConstraintValidator.checkPermitted(genName);
+							nameConstraintValidator.checkExcluded(genName);
+						}
+						catch (PkixNameConstraintValidatorException e)
+						{
+							throw new PkixCertPathValidatorException(
+								"Subtree check for certificate subject alternative name failed.", e, certPath, index);
+						}
+					}
+				}
+			}
+		}
+
+		internal static void PrepareNextCertA(
+			PkixCertPath	certPath,
+			int				index)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			//
+			//
+			// (a) check the policy mappings
+			//
+			Asn1Sequence pm = null;
+			try
+			{
+				pm = Asn1Sequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings));
+			}
+			catch (Exception ex)
+			{
+				throw new PkixCertPathValidatorException(
+					"Policy mappings extension could not be decoded.", ex, certPath, index);
+			}
+			if (pm != null)
+			{
+				Asn1Sequence mappings = pm;
+
+				for (int j = 0; j < mappings.Count; j++)
+				{
+					DerObjectIdentifier issuerDomainPolicy = null;
+					DerObjectIdentifier subjectDomainPolicy = null;
+					try
+					{
+						Asn1Sequence mapping = DerSequence.GetInstance(mappings[j]);
+
+						issuerDomainPolicy = DerObjectIdentifier.GetInstance(mapping[0]);
+						subjectDomainPolicy = DerObjectIdentifier.GetInstance(mapping[1]);
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Policy mappings extension contents could not be decoded.", e, certPath, index);
+					}
+
+					if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(issuerDomainPolicy.Id))
+						throw new PkixCertPathValidatorException(
+							"IssuerDomainPolicy is anyPolicy", null, certPath, index);
+
+					if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(subjectDomainPolicy.Id))
+						throw new PkixCertPathValidatorException(
+							"SubjectDomainPolicy is anyPolicy,", null, certPath, index);
+				}
+			}
+		}
+
+		internal static PkixPolicyNode ProcessCertD(
+			PkixCertPath	certPath,
+			int				index,
+			ISet			acceptablePolicies,
+			PkixPolicyNode	validPolicyTree,
+			IList[]			policyNodes,
+			int				inhibitAnyPolicy)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			int n = certs.Count;
+			// i as defined in the algorithm description
+			int i = n - index;
+			//
+			// (d) policy Information checking against initial policy and
+			// policy mapping
+			//
+			Asn1Sequence certPolicies = null;
+			try
+			{
+				certPolicies = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Could not read certificate policies extension from certificate.", e, certPath, index);
+			}
+			if (certPolicies != null && validPolicyTree != null)
+			{
+				//
+				// (d) (1)
+				//
+				ISet pols = new HashSet();
+
+				foreach (Asn1Encodable ae in certPolicies)
+				{
+					PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
+					DerObjectIdentifier pOid = pInfo.PolicyIdentifier;
+
+					pols.Add(pOid.Id);
+
+					if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(pOid.Id))
+					{
+						ISet pq = null;
+						try
+						{
+							pq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers);
+						}
+						catch (PkixCertPathValidatorException ex)
+						{
+							throw new PkixCertPathValidatorException(
+								"Policy qualifier info set could not be build.", ex, certPath, index);
+						}
+
+						bool match = PkixCertPathValidatorUtilities.ProcessCertD1i(i, policyNodes, pOid, pq);
+
+						if (!match)
+						{
+							PkixCertPathValidatorUtilities.ProcessCertD1ii(i, policyNodes, pOid, pq);
+						}
+					}
+				}
+
+				if (acceptablePolicies.IsEmpty || acceptablePolicies.Contains(Rfc3280CertPathUtilities.ANY_POLICY))
+				{
+					acceptablePolicies.Clear();
+					acceptablePolicies.AddAll(pols);
+				}
+				else
+				{
+					ISet t1 = new HashSet();
+
+					foreach (object o in acceptablePolicies)
+					{
+						if (pols.Contains(o))
+						{
+							t1.Add(o);
+						}
+					}
+					acceptablePolicies.Clear();
+					acceptablePolicies.AddAll(t1);
+				}
+
+				//
+				// (d) (2)
+				//
+				if ((inhibitAnyPolicy > 0) || ((i < n) && PkixCertPathValidatorUtilities.IsSelfIssued(cert)))
+				{
+					foreach (Asn1Encodable ae in certPolicies)
+					{
+						PolicyInformation pInfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
+						if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pInfo.PolicyIdentifier.Id))
+						{
+							ISet _apq = PkixCertPathValidatorUtilities.GetQualifierSet(pInfo.PolicyQualifiers);
+							IList _nodes = policyNodes[i - 1];
+
+							for (int k = 0; k < _nodes.Count; k++)
+							{
+								PkixPolicyNode _node = (PkixPolicyNode)_nodes[k];
+
+								IEnumerator  _policySetIter = _node.ExpectedPolicies.GetEnumerator();
+								while (_policySetIter.MoveNext())
+								{
+									object _tmp = _policySetIter.Current;
+
+									string _policy;
+									if (_tmp is string)
+									{
+										_policy = (string)_tmp;
+									}
+									else if (_tmp is DerObjectIdentifier)
+									{
+										_policy = ((DerObjectIdentifier)_tmp).Id;
+									}
+									else
+									{
+										continue;
+									}
+
+									bool _found = false;
+
+									foreach (PkixPolicyNode _child in _node.Children)
+									{
+										if (_policy.Equals(_child.ValidPolicy))
+										{
+											_found = true;
+										}
+									}
+
+									if (!_found)
+									{
+										ISet _newChildExpectedPolicies = new HashSet();
+										_newChildExpectedPolicies.Add(_policy);
+
+										PkixPolicyNode _newChild = new PkixPolicyNode(Platform.CreateArrayList(), i,
+											_newChildExpectedPolicies, _node, _apq, _policy, false);
+										_node.AddChild(_newChild);
+										policyNodes[i].Add(_newChild);
+									}
+								}
+							}
+							break;
+						}
+					}
+				}
+
+				PkixPolicyNode _validPolicyTree = validPolicyTree;
+				//
+				// (d) (3)
+				//
+				for (int j = (i - 1); j >= 0; j--)
+				{
+					IList nodes = policyNodes[j];
+
+					for (int k = 0; k < nodes.Count; k++)
+					{
+						PkixPolicyNode node = (PkixPolicyNode)nodes[k];
+						if (!node.HasChildren)
+						{
+							_validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(_validPolicyTree, policyNodes,
+								node);
+							if (_validPolicyTree == null)
+							{
+								break;
+							}
+						}
+					}
+				}
+
+				//
+				// d (4)
+				//
+				ISet criticalExtensionOids = cert.GetCriticalExtensionOids();
+
+				if (criticalExtensionOids != null)
+				{
+					bool critical = criticalExtensionOids.Contains(X509Extensions.CertificatePolicies.Id);
+
+					IList nodes = policyNodes[i];
+					for (int j = 0; j < nodes.Count; j++)
+					{
+						PkixPolicyNode node = (PkixPolicyNode)nodes[j];
+						node.IsCritical = critical;
+					}
+				}
+				return _validPolicyTree;
+			}
+			return null;
+		}
+
+		/**
+		* If the DP includes cRLIssuer, then verify that the issuer field in the
+		* complete CRL matches cRLIssuer in the DP and that the complete CRL
+		* contains an
+		*      g distribution point extension with the indirectCRL
+		* boolean asserted. Otherwise, verify that the CRL issuer matches the
+		* certificate issuer.
+		*
+		* @param dp   The distribution point.
+		* @param cert The certificate ot attribute certificate.
+		* @param crl  The CRL for <code>cert</code>.
+		* @throws AnnotatedException if one of the above conditions does not apply or an error
+		*                            occurs.
+		*/
+		internal static void ProcessCrlB1(
+			DistributionPoint	dp,
+			object				cert,
+			X509Crl				crl)
+		{
+			Asn1Object idp = PkixCertPathValidatorUtilities.GetExtensionValue(
+				crl, X509Extensions.IssuingDistributionPoint);
+
+			bool isIndirect = false;
+			if (idp != null)
+			{
+				if (IssuingDistributionPoint.GetInstance(idp).IsIndirectCrl)
+				{
+					isIndirect = true;
+				}
+			}
+			byte[] issuerBytes = crl.IssuerDN.GetEncoded();
+
+			bool matchIssuer = false;
+			if (dp.CrlIssuer != null)
+			{
+				GeneralName[] genNames = dp.CrlIssuer.GetNames();
+				for (int j = 0; j < genNames.Length; j++)
+				{
+					if (genNames[j].TagNo == GeneralName.DirectoryName)
+					{
+						try
+						{
+							if (Org.BouncyCastle.Utilities.Arrays.AreEqual(genNames[j].Name.ToAsn1Object().GetEncoded(), issuerBytes))
+							{
+								matchIssuer = true;
+							}
+						}
+						catch (IOException e)
+						{
+							throw new Exception(
+								"CRL issuer information from distribution point cannot be decoded.", e);
+						}
+					}
+				}
+				if (matchIssuer && !isIndirect)
+				{
+					throw new Exception("Distribution point contains cRLIssuer field but CRL is not indirect.");
+				}
+				if (!matchIssuer)
+				{
+					throw new Exception("CRL issuer of CRL does not match CRL issuer of distribution point.");
+				}
+			}
+			else
+			{
+				if (crl.IssuerDN.Equivalent(PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert), true))
+				{
+					matchIssuer = true;
+				}
+			}
+			if (!matchIssuer)
+			{
+				throw new Exception("Cannot find matching CRL issuer for certificate.");
+			}
+		}
+
+		internal static ReasonsMask ProcessCrlD(
+			X509Crl				crl,
+			DistributionPoint	dp)
+			//throws AnnotatedException
+		{
+			IssuingDistributionPoint idp = null;
+			try
+			{
+				idp = IssuingDistributionPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.IssuingDistributionPoint));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("issuing distribution point extension could not be decoded.", e);
+			}
+
+			// (d) (1)
+			if (idp != null && idp.OnlySomeReasons != null && dp.Reasons != null)
+			{
+				return new ReasonsMask(dp.Reasons.IntValue).Intersect(new ReasonsMask(idp.OnlySomeReasons
+					.IntValue));
+			}
+			// (d) (4)
+			if ((idp == null || idp.OnlySomeReasons == null) && dp.Reasons == null)
+			{
+				return ReasonsMask.AllReasons;
+			}
+
+			// (d) (2) and (d)(3)
+
+			ReasonsMask dpReasons = null;
+
+			if (dp.Reasons == null)
+			{
+				dpReasons = ReasonsMask.AllReasons;
+			}
+			else
+			{
+				dpReasons = new ReasonsMask(dp.Reasons.IntValue);
+			}
+
+			ReasonsMask idpReasons = null;
+
+			if (idp == null)
+			{
+				idpReasons = ReasonsMask.AllReasons;
+			}
+			else
+			{
+				idpReasons = new ReasonsMask(idp.OnlySomeReasons.IntValue);
+			}
+
+			return dpReasons.Intersect(idpReasons);
+		}
+
+		/**
+		* Obtain and validate the certification path for the complete CRL issuer.
+		* If a key usage extension is present in the CRL issuer's certificate,
+		* verify that the cRLSign bit is set.
+		*
+		* @param crl                CRL which contains revocation information for the certificate
+		*                           <code>cert</code>.
+		* @param cert               The attribute certificate or certificate to check if it is
+		*                           revoked.
+		* @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+		* @param defaultCRLSignKey  The public key of the issuer certificate
+		*                           <code>defaultCRLSignCert</code>.
+		* @param paramsPKIX         paramsPKIX PKIX parameters.
+		* @param certPathCerts      The certificates on the certification path.
+		* @return A <code>Set</code> with all keys of possible CRL issuer
+		*         certificates.
+		* @throws AnnotatedException if the CRL is not valid or the status cannot be checked or
+		*                            some error occurs.
+		*/
+		internal static ISet ProcessCrlF(
+			X509Crl					crl,
+			object					cert,
+			X509Certificate			defaultCRLSignCert,
+			AsymmetricKeyParameter	defaultCRLSignKey,
+			PkixParameters			paramsPKIX,
+			IList					certPathCerts)
+		{
+			// (f)
+
+			// get issuer from CRL
+			X509CertStoreSelector selector = new X509CertStoreSelector();
+			try
+			{
+				selector.Subject = crl.IssuerDN;
+			}
+			catch (IOException e)
+			{
+				throw new Exception(
+					"Subject criteria for certificate selector to find issuer certificate for CRL could not be set.", e);
+			}
+
+			// get CRL signing certs
+			IList coll = Platform.CreateArrayList();
+
+			try
+			{
+                CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetStores()));
+                CollectionUtilities.AddRange(coll, PkixCertPathValidatorUtilities.FindCertificates(selector, paramsPKIX.GetAdditionalStores()));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("Issuer certificate for CRL cannot be searched.", e);
+			}
+
+			coll.Add(defaultCRLSignCert);
+
+			IEnumerator cert_it = coll.GetEnumerator();
+
+            IList validCerts = Platform.CreateArrayList();
+            IList validKeys = Platform.CreateArrayList();
+
+			while (cert_it.MoveNext())
+			{
+				X509Certificate signingCert = (X509Certificate)cert_it.Current;
+
+				/*
+				 * CA of the certificate, for which this CRL is checked, has also
+				 * signed CRL, so skip the path validation, because is already done
+				 */
+				if (signingCert.Equals(defaultCRLSignCert))
+				{
+					validCerts.Add(signingCert);
+					validKeys.Add(defaultCRLSignKey);
+					continue;
+				}
+				try
+				{
+//					CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX");
+					PkixCertPathBuilder builder = new PkixCertPathBuilder();
+					selector = new X509CertStoreSelector();
+					selector.Certificate = signingCert;
+
+					PkixParameters temp = (PkixParameters)paramsPKIX.Clone();
+					temp.SetTargetCertConstraints(selector);
+
+					PkixBuilderParameters parameters = (PkixBuilderParameters)
+						PkixBuilderParameters.GetInstance(temp);
+
+					/*
+					 * if signingCert is placed not higher on the cert path a
+					 * dependency loop results. CRL for cert is checked, but
+					 * signingCert is needed for checking the CRL which is dependent
+					 * on checking cert because it is higher in the cert path and so
+					 * signing signingCert transitively. so, revocation is disabled,
+					 * forgery attacks of the CRL are detected in this outer loop
+					 * for all other it must be enabled to prevent forgery attacks
+					 */
+					if (certPathCerts.Contains(signingCert))
+					{
+						parameters.IsRevocationEnabled = false;
+					}
+					else
+					{
+						parameters.IsRevocationEnabled = true;
+					}
+					IList certs = builder.Build(parameters).CertPath.Certificates;
+					validCerts.Add(signingCert);
+					validKeys.Add(PkixCertPathValidatorUtilities.GetNextWorkingKey(certs, 0));
+				}
+				catch (PkixCertPathBuilderException e)
+				{
+					throw new Exception("Internal error.", e);
+				}
+				catch (PkixCertPathValidatorException e)
+				{
+					throw new Exception("Public key of issuer certificate of CRL could not be retrieved.", e);
+				}
+				//catch (Exception e)
+				//{
+				//    throw new Exception(e.Message);
+				//}
+			}
+
+			ISet checkKeys = new HashSet();
+
+			Exception lastException = null;
+			for (int i = 0; i < validCerts.Count; i++)
+			{
+				X509Certificate signCert = (X509Certificate)validCerts[i];
+				bool[] keyusage = signCert.GetKeyUsage();
+
+				if (keyusage != null && (keyusage.Length < 7 || !keyusage[CRL_SIGN]))
+				{
+					lastException = new Exception(
+						"Issuer certificate key usage extension does not permit CRL signing.");
+				}
+				else
+				{
+					checkKeys.Add(validKeys[i]);
+				}
+			}
+
+			if ((checkKeys.Count == 0) && lastException == null)
+			{
+				throw new Exception("Cannot find a valid issuer certificate.");
+			}
+			if ((checkKeys.Count == 0) && lastException != null)
+			{
+				throw lastException;
+			}
+
+			return checkKeys;
+		}
+
+		internal static AsymmetricKeyParameter ProcessCrlG(
+			X509Crl	crl,
+			ISet	keys)
+		{
+			Exception lastException = null;
+			foreach (AsymmetricKeyParameter key in keys)
+			{
+				try
+				{
+					crl.Verify(key);
+					return key;
+				}
+				catch (Exception e)
+				{
+					lastException = e;
+				}
+			}
+			throw new Exception("Cannot verify CRL.", lastException);
+		}
+
+		internal static X509Crl ProcessCrlH(
+			ISet					deltaCrls,
+			AsymmetricKeyParameter	key)
+		{
+			Exception lastException = null;
+			foreach (X509Crl crl in deltaCrls)
+			{
+				try
+				{
+					crl.Verify(key);
+					return crl;
+				}
+				catch (Exception e)
+				{
+					lastException = e;
+				}
+			}
+			if (lastException != null)
+			{
+				throw new Exception("Cannot verify delta CRL.", lastException);
+			}
+			return null;
+		}
+
+		/**
+		* Checks a distribution point for revocation information for the
+		* certificate <code>cert</code>.
+		*
+		* @param dp                 The distribution point to consider.
+		* @param paramsPKIX         PKIX parameters.
+		* @param cert               Certificate to check if it is revoked.
+		* @param validDate          The date when the certificate revocation status should be
+		*                           checked.
+		* @param defaultCRLSignCert The issuer certificate of the certificate <code>cert</code>.
+		* @param defaultCRLSignKey  The public key of the issuer certificate
+		*                           <code>defaultCRLSignCert</code>.
+		* @param certStatus         The current certificate revocation status.
+		* @param reasonMask         The reasons mask which is already checked.
+		* @param certPathCerts      The certificates of the certification path.
+		* @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+		*                            or some error occurs.
+		*/
+		private static void CheckCrl(
+			DistributionPoint dp,
+			PkixParameters paramsPKIX,
+			X509Certificate cert,
+			DateTime validDate,
+			X509Certificate defaultCRLSignCert,
+			AsymmetricKeyParameter defaultCRLSignKey,
+			CertStatus certStatus,
+			ReasonsMask reasonMask,
+			IList certPathCerts)
+			//throws AnnotatedException
+		{
+			DateTime currentDate = DateTime.UtcNow;
+
+			if (validDate.Ticks > currentDate.Ticks)
+			{
+				throw new Exception("Validation time is in future.");
+			}
+
+			// (a)
+			/*
+			 * We always get timely valid CRLs, so there is no step (a) (1).
+			 * "locally cached" CRLs are assumed to be in getStore(), additional
+			 * CRLs must be enabled in the ExtendedPKIXParameters and are in
+			 * getAdditionalStore()
+			 */
+
+			ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, cert, currentDate, paramsPKIX);
+			bool validCrlFound = false;
+			Exception lastException = null;
+
+			IEnumerator crl_iter = crls.GetEnumerator();
+
+			while (crl_iter.MoveNext() && certStatus.Status == CertStatus.Unrevoked && !reasonMask.IsAllReasons)
+			{
+				try
+				{
+					X509Crl crl = (X509Crl)crl_iter.Current;
+
+					// (d)
+					ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp);
+
+					// (e)
+					/*
+					 * The reasons mask is updated at the end, so only valid CRLs
+					 * can update it. If this CRL does not contain new reasons it
+					 * must be ignored.
+					 */
+					if (!interimReasonsMask.HasNewReasons(reasonMask))
+					{
+						continue;
+					}
+
+					// (f)
+					ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, cert, defaultCRLSignCert, defaultCRLSignKey,
+						paramsPKIX, certPathCerts);
+					// (g)
+					AsymmetricKeyParameter key = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys);
+
+					X509Crl deltaCRL = null;
+
+					if (paramsPKIX.IsUseDeltasEnabled)
+					{
+						// get delta CRLs
+						ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl);
+						// we only want one valid delta CRL
+						// (h)
+						deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, key);
+					}
+
+					/*
+					 * CRL must be be valid at the current time, not the validation
+					 * time. If a certificate is revoked with reason keyCompromise,
+					 * cACompromise, it can be used for forgery, also for the past.
+					 * This reason may not be contained in older CRLs.
+					 */
+
+					/*
+					 * in the chain model signatures stay valid also after the
+					 * certificate has been expired, so they do not have to be in
+					 * the CRL validity time
+					 */
+
+					if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel)
+					{
+						/*
+						 * if a certificate has expired, but was revoked, it is not
+						 * more in the CRL, so it would be regarded as valid if the
+						 * first check is not done
+						 */
+						if (cert.NotAfter.Ticks < crl.ThisUpdate.Ticks)
+						{
+							throw new Exception("No valid CRL for current time found.");
+						}
+					}
+
+					Rfc3280CertPathUtilities.ProcessCrlB1(dp, cert, crl);
+
+					// (b) (2)
+					Rfc3280CertPathUtilities.ProcessCrlB2(dp, cert, crl);
+
+					// (c)
+					Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX);
+
+					// (i)
+					Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL, cert, certStatus, paramsPKIX);
+
+					// (j)
+					Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, cert, certStatus);
+
+					// (k)
+					if (certStatus.Status == CrlReason.RemoveFromCrl)
+					{
+						certStatus.Status = CertStatus.Unrevoked;
+					}
+
+					// update reasons mask
+					reasonMask.AddReasons(interimReasonsMask);
+
+					ISet criticalExtensions = crl.GetCriticalExtensionOids();
+
+					if (criticalExtensions != null)
+					{
+						criticalExtensions = new HashSet(criticalExtensions);
+						criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
+						criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);
+
+						if (!criticalExtensions.IsEmpty)
+							throw new Exception("CRL contains unsupported critical extensions.");
+					}
+
+					if (deltaCRL != null)
+					{
+						criticalExtensions = deltaCRL.GetCriticalExtensionOids();
+						if (criticalExtensions != null)
+						{
+							criticalExtensions = new HashSet(criticalExtensions);
+							criticalExtensions.Remove(X509Extensions.IssuingDistributionPoint.Id);
+							criticalExtensions.Remove(X509Extensions.DeltaCrlIndicator.Id);
+
+							if (!criticalExtensions.IsEmpty)
+								throw new Exception("Delta CRL contains unsupported critical extension.");
+						}
+					}
+
+					validCrlFound = true;
+				}
+				catch (Exception e)
+				{
+					lastException = e;
+				}
+			}
+			if (!validCrlFound)
+			{
+				throw lastException;
+			}
+		}
+
+		/**
+		 * Checks a certificate if it is revoked.
+		 *
+		 * @param paramsPKIX       PKIX parameters.
+		 * @param cert             Certificate to check if it is revoked.
+		 * @param validDate        The date when the certificate revocation status should be
+		 *                         checked.
+		 * @param sign             The issuer certificate of the certificate <code>cert</code>.
+		 * @param workingPublicKey The public key of the issuer certificate <code>sign</code>.
+		 * @param certPathCerts    The certificates of the certification path.
+		 * @throws AnnotatedException if the certificate is revoked or the status cannot be checked
+		 *                            or some error occurs.
+		 */
+		protected static void CheckCrls(
+			PkixParameters			paramsPKIX,
+			X509Certificate			cert,
+			DateTime				validDate,
+			X509Certificate			sign,
+			AsymmetricKeyParameter	workingPublicKey,
+			IList					certPathCerts)
+		{
+			Exception lastException = null;
+			CrlDistPoint crldp = null;
+
+			try
+			{
+				crldp = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CrlDistributionPoints));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("CRL distribution point extension could not be read.", e);
+			}
+
+			try
+			{
+				PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
+			}
+			catch (Exception e)
+			{
+				throw new Exception(
+					"No additional CRL locations could be decoded from CRL distribution point extension.", e);
+			}
+			CertStatus certStatus = new CertStatus();
+			ReasonsMask reasonsMask = new ReasonsMask();
+
+			bool validCrlFound = false;
+
+			// for each distribution point
+			if (crldp != null)
+			{
+				DistributionPoint[] dps = null;
+				try
+				{
+					dps = crldp.GetDistributionPoints();
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Distribution points could not be read.", e);
+				}
+				if (dps != null)
+				{
+					for (int i = 0; i < dps.Length && certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons; i++)
+					{
+						PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();
+						try
+						{
+							CheckCrl(dps[i], paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask, certPathCerts);
+							validCrlFound = true;
+						}
+						catch (Exception e)
+						{
+							lastException = e;
+						}
+					}
+				}
+			}
+
+			/*
+			 * If the revocation status has not been determined, repeat the process
+			 * above with any available CRLs not specified in a distribution point
+			 * but issued by the certificate issuer.
+			 */
+
+			if (certStatus.Status == CertStatus.Unrevoked && !reasonsMask.IsAllReasons)
+			{
+				try
+				{
+					/*
+					 * assume a DP with both the reasons and the cRLIssuer fields
+					 * omitted and a distribution point name of the certificate
+					 * issuer.
+					 */
+					Asn1Object issuer = null;
+					try
+					{
+						issuer = new Asn1InputStream(cert.IssuerDN.GetEncoded()).ReadObject();
+					}
+					catch (Exception e)
+					{
+						throw new Exception("Issuer from certificate for CRL could not be reencoded.", e);
+					}
+					DistributionPoint dp = new DistributionPoint(new DistributionPointName(0, new GeneralNames(
+						new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
+					PkixParameters paramsPKIXClone = (PkixParameters)paramsPKIX.Clone();
+
+					CheckCrl(dp, paramsPKIXClone, cert, validDate, sign, workingPublicKey, certStatus, reasonsMask,
+						certPathCerts);
+
+					validCrlFound = true;
+				}
+				catch (Exception e)
+				{
+					lastException = e;
+				}
+			}
+
+			if (!validCrlFound)
+			{
+				throw lastException;
+			}
+			if (certStatus.Status != CertStatus.Unrevoked)
+			{
+				// This format is enforced by the NistCertPath tests
+                string formattedDate = certStatus.RevocationDate.Value.ToString(
+                    "ddd MMM dd HH:mm:ss K yyyy");
+                string message = "Certificate revocation after " + formattedDate;
+				message += ", reason: " + CrlReasons[certStatus.Status];
+				throw new Exception(message);
+			}
+
+			if (!reasonsMask.IsAllReasons && certStatus.Status == CertStatus.Unrevoked)
+			{
+				certStatus.Status = CertStatus.Undetermined;
+			}
+
+			if (certStatus.Status == CertStatus.Undetermined)
+			{
+				throw new Exception("Certificate status could not be determined.");
+			}
+		}
+
+		internal static PkixPolicyNode PrepareCertB(
+			PkixCertPath	certPath,
+			int				index,
+			IList[]			policyNodes,
+			PkixPolicyNode	validPolicyTree,
+			int				policyMapping)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			int n = certs.Count;
+			// i as defined in the algorithm description
+			int i = n - index;
+			// (b)
+			//
+			Asn1Sequence pm = null;
+			try
+			{
+				pm = (Asn1Sequence)Asn1Sequence.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyMappings));
+			}
+			catch (Exception ex)
+			{
+				throw new PkixCertPathValidatorException(
+					"Policy mappings extension could not be decoded.", ex, certPath, index);
+			}
+			PkixPolicyNode _validPolicyTree = validPolicyTree;
+			if (pm != null)
+			{
+				Asn1Sequence mappings = (Asn1Sequence)pm;
+				IDictionary m_idp = Platform.CreateHashtable();
+				ISet s_idp = new HashSet();
+
+				for (int j = 0; j < mappings.Count; j++)
+				{
+					Asn1Sequence mapping = (Asn1Sequence) mappings[j];
+					string id_p = ((DerObjectIdentifier) mapping[0]).Id;
+					string sd_p = ((DerObjectIdentifier) mapping[1]).Id;
+					ISet tmp;
+
+					if (!m_idp.Contains(id_p))
+					{
+						tmp = new HashSet();
+						tmp.Add(sd_p);
+						m_idp[id_p] = tmp;
+						s_idp.Add(id_p);
+					}
+					else
+					{
+						tmp = (ISet)m_idp[id_p];
+						tmp.Add(sd_p);
+					}
+				}
+
+				IEnumerator it_idp = s_idp.GetEnumerator();
+				while (it_idp.MoveNext())
+				{
+					string id_p = (string)it_idp.Current;
+
+					//
+					// (1)
+					//
+					if (policyMapping > 0)
+					{
+						bool idp_found = false;
+						IEnumerator nodes_i = policyNodes[i].GetEnumerator();
+
+						while (nodes_i.MoveNext())
+						{
+							PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
+							if (node.ValidPolicy.Equals(id_p))
+							{
+								idp_found = true;
+								node.ExpectedPolicies = (ISet)m_idp[id_p];
+								break;
+							}
+						}
+
+						if (!idp_found)
+						{
+							nodes_i = policyNodes[i].GetEnumerator();
+							while (nodes_i.MoveNext())
+							{
+								PkixPolicyNode node = (PkixPolicyNode)nodes_i.Current;
+								if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(node.ValidPolicy))
+								{
+									ISet pq = null;
+									Asn1Sequence policies = null;
+									try
+									{
+										policies = (Asn1Sequence)PkixCertPathValidatorUtilities.GetExtensionValue(cert,
+											X509Extensions.CertificatePolicies);
+									}
+									catch (Exception e)
+									{
+										throw new PkixCertPathValidatorException(
+											"Certificate policies extension could not be decoded.", e, certPath, index);
+									}
+
+									foreach (Asn1Encodable ae in policies)
+									{
+										PolicyInformation pinfo = null;
+										try
+										{
+											pinfo = PolicyInformation.GetInstance(ae.ToAsn1Object());
+										}
+										catch (Exception ex)
+										{
+											throw new PkixCertPathValidatorException(
+												"Policy information could not be decoded.", ex, certPath, index);
+										}
+										if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(pinfo.PolicyIdentifier.Id))
+										{
+											try
+											{
+												pq = PkixCertPathValidatorUtilities
+													.GetQualifierSet(pinfo.PolicyQualifiers);
+											}
+											catch (PkixCertPathValidatorException ex)
+											{
+												throw new PkixCertPathValidatorException(
+													"Policy qualifier info set could not be decoded.", ex, certPath,
+													index);
+											}
+											break;
+										}
+									}
+									bool ci = false;
+									ISet critExtOids = cert.GetCriticalExtensionOids();
+									if (critExtOids != null)
+									{
+										ci = critExtOids.Contains(X509Extensions.CertificatePolicies.Id);
+									}
+
+									PkixPolicyNode p_node = (PkixPolicyNode)node.Parent;
+									if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(p_node.ValidPolicy))
+									{
+										PkixPolicyNode c_node = new PkixPolicyNode(Platform.CreateArrayList(), i,
+											(ISet)m_idp[id_p], p_node, pq, id_p, ci);
+										p_node.AddChild(c_node);
+										policyNodes[i].Add(c_node);
+									}
+									break;
+								}
+							}
+						}
+
+						//
+						// (2)
+						//
+					}
+					else if (policyMapping <= 0)
+					{
+                        foreach (PkixPolicyNode node in Platform.CreateArrayList(policyNodes[i]))
+                        {
+							if (node.ValidPolicy.Equals(id_p))
+							{
+								node.Parent.RemoveChild(node);
+
+                                for (int k = i - 1; k >= 0; k--)
+								{
+                                    foreach (PkixPolicyNode node2 in Platform.CreateArrayList(policyNodes[k]))
+									{
+										if (!node2.HasChildren)
+										{
+											_validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(
+												_validPolicyTree, policyNodes, node2);
+
+                                            if (_validPolicyTree == null)
+												break;
+										}
+									}
+								}
+							}
+						}
+					}
+				}
+			}
+			return _validPolicyTree;
+		}
+
+		internal static ISet[] ProcessCrlA1ii(
+			DateTime		currentDate,
+			PkixParameters	paramsPKIX,
+			X509Certificate	cert,
+			X509Crl			crl)
+		{
+			ISet deltaSet = new HashSet();
+			X509CrlStoreSelector crlselect = new X509CrlStoreSelector();
+			crlselect.CertificateChecking = cert;
+
+			try
+			{
+				IList issuer = Platform.CreateArrayList();
+				issuer.Add(crl.IssuerDN);
+				crlselect.Issuers = issuer;
+			}
+			catch (IOException e)
+			{
+				throw new Exception("Cannot extract issuer from CRL." + e, e);
+			}
+
+			crlselect.CompleteCrlEnabled = true;
+			ISet completeSet = CrlUtilities.FindCrls(crlselect, paramsPKIX, currentDate);
+
+			if (paramsPKIX.IsUseDeltasEnabled)
+			{
+				// get delta CRL(s)
+				try
+				{
+					deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Exception obtaining delta CRLs.", e);
+				}
+			}
+
+			return new ISet[]{ completeSet, deltaSet };
+		}
+
+		internal static ISet ProcessCrlA1i(
+			DateTime		currentDate,
+			PkixParameters	paramsPKIX,
+			X509Certificate	cert,
+			X509Crl			crl)
+		{
+			ISet deltaSet = new HashSet();
+			if (paramsPKIX.IsUseDeltasEnabled)
+			{
+				CrlDistPoint freshestCRL = null;
+				try
+				{
+					freshestCRL = CrlDistPoint.GetInstance(
+						PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.FreshestCrl));
+				}
+				catch (Exception e)
+				{
+					throw new Exception("Freshest CRL extension could not be decoded from certificate.", e);
+				}
+
+				if (freshestCRL == null)
+				{
+					try
+					{
+						freshestCRL = CrlDistPoint.GetInstance(PkixCertPathValidatorUtilities.GetExtensionValue(crl, X509Extensions.FreshestCrl));
+					}
+					catch (Exception e)
+					{
+						throw new Exception("Freshest CRL extension could not be decoded from CRL.", e);
+					}
+				}
+				if (freshestCRL != null)
+				{
+					try
+					{
+						PkixCertPathValidatorUtilities.AddAdditionalStoresFromCrlDistributionPoint(freshestCRL, paramsPKIX);
+					}
+					catch (Exception e)
+					{
+						throw new Exception(
+							"No new delta CRL locations could be added from Freshest CRL extension.", e);
+					}
+					// get delta CRL(s)
+					try
+					{
+						deltaSet.AddAll(PkixCertPathValidatorUtilities.GetDeltaCrls(currentDate, paramsPKIX, crl));
+					}
+					catch (Exception e)
+					{
+						throw new Exception("Exception obtaining delta CRLs.", e);
+					}
+				}
+			}
+			return deltaSet;
+		}
+
+		internal static void ProcessCertF(
+			PkixCertPath	certPath,
+			int				index,
+			PkixPolicyNode	validPolicyTree,
+			int				explicitPolicy)
+		{
+			//
+			// (f)
+			//
+			if (explicitPolicy <= 0 && validPolicyTree == null)
+			{
+				throw new PkixCertPathValidatorException(
+					"No valid policy tree found when one expected.", null, certPath, index);
+			}
+		}
+
+		internal static void ProcessCertA(
+			PkixCertPath			certPath,
+			PkixParameters			paramsPKIX,
+			int						index,
+			AsymmetricKeyParameter	workingPublicKey,
+			X509Name				workingIssuerName,
+			X509Certificate			sign)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			//
+			// (a) verify
+			//
+			try
+			{
+				// (a) (1)
+				//
+				cert.Verify(workingPublicKey);
+			}
+			catch (GeneralSecurityException e)
+			{
+				throw new PkixCertPathValidatorException("Could not validate certificate signature.", e, certPath, index);
+			}
+
+			try
+			{
+				// (a) (2)
+				//
+				cert.CheckValidity(PkixCertPathValidatorUtilities
+					.GetValidCertDateFromValidityModel(paramsPKIX, certPath, index));
+			}
+			catch (CertificateExpiredException e)
+			{
+				throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
+			}
+			catch (CertificateNotYetValidException e)
+			{
+				throw new PkixCertPathValidatorException("Could not validate certificate: " + e.Message, e, certPath, index);
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Could not validate time of certificate.", e, certPath, index);
+			}
+
+			//
+			// (a) (3)
+			//
+			if (paramsPKIX.IsRevocationEnabled)
+			{
+				try
+				{
+					CheckCrls(paramsPKIX, cert, PkixCertPathValidatorUtilities.GetValidCertDateFromValidityModel(paramsPKIX,
+						certPath, index), sign, workingPublicKey, certs);
+				}
+				catch (Exception e)
+				{
+					Exception cause = e.InnerException;
+					if (cause == null)
+					{
+						cause = e;
+					}
+					throw new PkixCertPathValidatorException(e.Message, cause, certPath, index);
+				}
+			}
+
+			//
+			// (a) (4) name chaining
+			//
+			X509Name issuer = PkixCertPathValidatorUtilities.GetIssuerPrincipal(cert);
+			if (!issuer.Equivalent(workingIssuerName, true))
+			{
+				throw new PkixCertPathValidatorException("IssuerName(" + issuer
+					+ ") does not match SubjectName(" + workingIssuerName + ") of signing certificate.", null,
+					certPath, index);
+			}
+		}
+
+		internal static int PrepareNextCertI1(
+			PkixCertPath	certPath,
+			int				index,
+			int				explicitPolicy)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			//
+			// (i)
+			//
+			Asn1Sequence pc = null;
+			try
+			{
+				pc = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Policy constraints extension cannot be decoded.", e, certPath, index);
+			}
+
+			int tmpInt;
+
+			if (pc != null)
+			{
+				IEnumerator policyConstraints = pc.GetEnumerator();
+
+				while (policyConstraints.MoveNext())
+				{
+					try
+					{
+						Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
+						if (constraint.TagNo == 0)
+						{
+							tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+							if (tmpInt < explicitPolicy)
+							{
+								return tmpInt;
+							}
+							break;
+						}
+					}
+					catch (ArgumentException e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Policy constraints extension contents cannot be decoded.", e, certPath, index);
+					}
+				}
+			}
+			return explicitPolicy;
+		}
+
+		internal static int PrepareNextCertI2(
+			PkixCertPath	certPath,
+			int				index,
+			int				policyMapping)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (i)
+			//
+			Asn1Sequence pc = null;
+			try
+			{
+				pc = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Policy constraints extension cannot be decoded.", e, certPath, index);
+			}
+
+			int tmpInt;
+
+			if (pc != null)
+			{
+				IEnumerator policyConstraints = pc.GetEnumerator();
+
+				while (policyConstraints.MoveNext())
+				{
+					try
+					{
+						Asn1TaggedObject constraint = Asn1TaggedObject.GetInstance(policyConstraints.Current);
+						if (constraint.TagNo == 1)
+						{
+							tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+							if (tmpInt < policyMapping)
+							{
+								return tmpInt;
+							}
+							break;
+						}
+					}
+					catch (ArgumentException e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Policy constraints extension contents cannot be decoded.", e, certPath, index);
+					}
+				}
+			}
+			return policyMapping;
+		}
+
+		internal static void PrepareNextCertG(
+			PkixCertPath				certPath,
+			int							index,
+			PkixNameConstraintValidator	nameConstraintValidator)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (g) handle the name constraints extension
+			//
+			NameConstraints nc = null;
+			try
+			{
+				Asn1Sequence ncSeq = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.NameConstraints));
+				if (ncSeq != null)
+				{
+					nc = new NameConstraints(ncSeq);
+				}
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Name constraints extension could not be decoded.", e, certPath, index);
+			}
+			if (nc != null)
+			{
+				//
+				// (g) (1) permitted subtrees
+				//
+				Asn1Sequence permitted = nc.PermittedSubtrees;
+				if (permitted != null)
+				{
+					try
+					{
+						nameConstraintValidator.IntersectPermittedSubtree(permitted);
+					}
+					catch (Exception ex)
+					{
+						throw new PkixCertPathValidatorException(
+							"Permitted subtrees cannot be build from name constraints extension.", ex, certPath, index);
+					}
+				}
+
+				//
+				// (g) (2) excluded subtrees
+				//
+				Asn1Sequence excluded = nc.ExcludedSubtrees;
+				if (excluded != null)
+				{
+					IEnumerator e = excluded.GetEnumerator();
+					try
+					{
+						while (e.MoveNext())
+						{
+							GeneralSubtree subtree = GeneralSubtree.GetInstance(e.Current);
+							nameConstraintValidator.AddExcludedSubtree(subtree);
+						}
+					}
+					catch (Exception ex)
+					{
+						throw new PkixCertPathValidatorException(
+							"Excluded subtrees cannot be build from name constraints extension.", ex, certPath, index);
+					}
+				}
+			}
+		}
+
+		internal static int PrepareNextCertJ(
+			PkixCertPath	certPath,
+			int				index,
+			int				inhibitAnyPolicy)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (j)
+			//
+			DerInteger iap = null;
+			try
+			{
+				iap = DerInteger.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.InhibitAnyPolicy));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Inhibit any-policy extension cannot be decoded.", e, certPath, index);
+			}
+
+			if (iap != null)
+			{
+				int _inhibitAnyPolicy = iap.Value.IntValue;
+
+				if (_inhibitAnyPolicy < inhibitAnyPolicy)
+					return _inhibitAnyPolicy;
+			}
+			return inhibitAnyPolicy;
+		}
+
+		internal static void PrepareNextCertK(
+			PkixCertPath	certPath,
+			int				index)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			//
+			// (k)
+			//
+			BasicConstraints bc = null;
+			try
+			{
+				bc = BasicConstraints.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath,
+					index);
+			}
+			if (bc != null)
+			{
+				if (!(bc.IsCA()))
+					throw new PkixCertPathValidatorException("Not a CA certificate");
+			}
+			else
+			{
+				throw new PkixCertPathValidatorException("Intermediate certificate lacks BasicConstraints");
+			}
+		}
+
+		internal static int PrepareNextCertL(
+			PkixCertPath	certPath,
+			int				index,
+			int				maxPathLength)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			//
+			// (l)
+			//
+			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
+			{
+				if (maxPathLength <= 0)
+				{
+					throw new PkixCertPathValidatorException("Max path length not greater than zero", null, certPath, index);
+				}
+
+				return maxPathLength - 1;
+			}
+			return maxPathLength;
+		}
+
+		internal static int PrepareNextCertM(
+			PkixCertPath	certPath,
+			int				index,
+			int				maxPathLength)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (m)
+			//
+			BasicConstraints bc = null;
+			try
+			{
+				bc = BasicConstraints.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.BasicConstraints));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Basic constraints extension cannot be decoded.", e, certPath,
+					index);
+			}
+			if (bc != null)
+			{
+				BigInteger _pathLengthConstraint = bc.PathLenConstraint;
+
+				if (_pathLengthConstraint != null)
+				{
+					int _plc = _pathLengthConstraint.IntValue;
+
+					if (_plc < maxPathLength)
+					{
+						return _plc;
+					}
+				}
+			}
+			return maxPathLength;
+		}
+
+		internal static void PrepareNextCertN(
+			PkixCertPath	certPath,
+			int				index)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (n)
+			//
+			bool[] _usage = cert.GetKeyUsage();
+
+			if ((_usage != null) && !_usage[Rfc3280CertPathUtilities.KEY_CERT_SIGN])
+			{
+				throw new PkixCertPathValidatorException(
+					"Issuer certificate keyusage extension is critical and does not permit key signing.", null,
+					certPath, index);
+			}
+		}
+
+		internal static void PrepareNextCertO(
+			PkixCertPath	certPath,
+			int				index,
+			ISet			criticalExtensions,
+			IList			pathCheckers)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (o)
+			//
+			IEnumerator tmpIter = pathCheckers.GetEnumerator();
+			while (tmpIter.MoveNext())
+			{
+				try
+				{
+					((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions);
+				}
+				catch (PkixCertPathValidatorException e)
+				{
+					throw new PkixCertPathValidatorException(e.Message, e.InnerException, certPath, index);
+				}
+			}
+			if (!criticalExtensions.IsEmpty)
+			{
+				throw new PkixCertPathValidatorException("Certificate has unsupported critical extension.", null, certPath,
+					index);
+			}
+		}
+
+		internal static int PrepareNextCertH1(
+			PkixCertPath	certPath,
+			int				index,
+			int				explicitPolicy)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (h)
+			//
+			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
+			{
+				//
+				// (1)
+				//
+				if (explicitPolicy != 0)
+					return explicitPolicy - 1;
+			}
+			return explicitPolicy;
+		}
+
+		internal static int PrepareNextCertH2(
+			PkixCertPath	certPath,
+			int				index,
+			int				policyMapping)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (h)
+			//
+			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
+			{
+				//
+				// (2)
+				//
+				if (policyMapping != 0)
+					return policyMapping - 1;
+			}
+			return policyMapping;
+		}
+
+
+		internal static int PrepareNextCertH3(
+			PkixCertPath	certPath,
+			int				index,
+			int				inhibitAnyPolicy)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (h)
+			//
+			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert))
+			{
+				//
+				// (3)
+				//
+				if (inhibitAnyPolicy != 0)
+					return inhibitAnyPolicy - 1;
+			}
+			return inhibitAnyPolicy;
+		}
+
+		internal static int WrapupCertA(
+			int				explicitPolicy,
+			X509Certificate	cert)
+		{
+			//
+			// (a)
+			//
+			if (!PkixCertPathValidatorUtilities.IsSelfIssued(cert) && (explicitPolicy != 0))
+			{
+				explicitPolicy--;
+			}
+			return explicitPolicy;
+		}
+
+		internal static int WrapupCertB(
+			PkixCertPath	certPath,
+			int				index,
+			int				explicitPolicy)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (b)
+			//
+			int tmpInt;
+			Asn1Sequence pc = null;
+			try
+			{
+				pc = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.PolicyConstraints));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Policy constraints could not be decoded.", e, certPath, index);
+			}
+
+			if (pc != null)
+			{
+				IEnumerator policyConstraints = pc.GetEnumerator();
+
+				while (policyConstraints.MoveNext())
+				{
+					Asn1TaggedObject constraint = (Asn1TaggedObject)policyConstraints.Current;
+					switch (constraint.TagNo)
+					{
+						case 0:
+							try
+							{
+								tmpInt = DerInteger.GetInstance(constraint, false).Value.IntValue;
+							}
+							catch (Exception e)
+							{
+								throw new PkixCertPathValidatorException(
+									"Policy constraints requireExplicitPolicy field could not be decoded.", e, certPath,
+									index);
+							}
+							if (tmpInt == 0)
+							{
+								return 0;
+							}
+							break;
+					}
+				}
+			}
+			return explicitPolicy;
+		}
+
+		internal static void WrapupCertF(
+			PkixCertPath	certPath,
+			int				index,
+			IList			pathCheckers,
+			ISet			criticalExtensions)
+			//throws CertPathValidatorException
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+			IEnumerator tmpIter = pathCheckers.GetEnumerator();
+
+			while (tmpIter.MoveNext())
+			{
+				try
+				{
+					((PkixCertPathChecker)tmpIter.Current).Check(cert, criticalExtensions);
+				}
+				catch (PkixCertPathValidatorException e)
+				{
+					throw new PkixCertPathValidatorException("Additional certificate path checker failed.", e, certPath,
+						index);
+				}
+			}
+
+			if (!criticalExtensions.IsEmpty)
+			{
+				throw new PkixCertPathValidatorException("Certificate has unsupported critical extension",
+					null, certPath, index);
+			}
+		}
+
+		internal static PkixPolicyNode WrapupCertG(
+			PkixCertPath	certPath,
+			PkixParameters	paramsPKIX,
+			ISet			userInitialPolicySet,
+			int				index,
+			IList[]			policyNodes,
+			PkixPolicyNode	validPolicyTree,
+			ISet			acceptablePolicies)
+		{
+			int n = certPath.Certificates.Count;
+
+			//
+			// (g)
+			//
+			PkixPolicyNode intersection;
+
+			//
+			// (g) (i)
+			//
+			if (validPolicyTree == null)
+			{
+				if (paramsPKIX.IsExplicitPolicyRequired)
+				{
+					throw new PkixCertPathValidatorException(
+						"Explicit policy requested but none available.", null, certPath, index);
+				}
+				intersection = null;
+			}
+			else if (PkixCertPathValidatorUtilities.IsAnyPolicy(userInitialPolicySet)) // (g)
+				// (ii)
+			{
+				if (paramsPKIX.IsExplicitPolicyRequired)
+				{
+					if (acceptablePolicies.IsEmpty)
+					{
+						throw new PkixCertPathValidatorException(
+							"Explicit policy requested but none available.", null, certPath, index);
+					}
+					else
+					{
+						ISet _validPolicyNodeSet = new HashSet();
+
+						for (int j = 0; j < policyNodes.Length; j++)
+						{
+							IList _nodeDepth = policyNodes[j];
+
+							for (int k = 0; k < _nodeDepth.Count; k++)
+							{
+								PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k];
+
+								if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy))
+								{
+									foreach (object o in _node.Children)
+									{
+										_validPolicyNodeSet.Add(o);
+									}
+								}
+							}
+						}
+
+						foreach (PkixPolicyNode _node in _validPolicyNodeSet)
+						{
+							string _validPolicy = _node.ValidPolicy;
+
+							if (!acceptablePolicies.Contains(_validPolicy))
+							{
+								// TODO?
+								// validPolicyTree =
+								// removePolicyNode(validPolicyTree, policyNodes,
+								// _node);
+							}
+						}
+						if (validPolicyTree != null)
+						{
+							for (int j = (n - 1); j >= 0; j--)
+							{
+								IList nodes = policyNodes[j];
+
+								for (int k = 0; k < nodes.Count; k++)
+								{
+									PkixPolicyNode node = (PkixPolicyNode)nodes[k];
+									if (!node.HasChildren)
+									{
+										validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree,
+											policyNodes, node);
+									}
+								}
+							}
+						}
+					}
+				}
+
+				intersection = validPolicyTree;
+			}
+			else
+			{
+				//
+				// (g) (iii)
+				//
+				// This implementation is not exactly same as the one described in
+				// RFC3280.
+				// However, as far as the validation result is concerned, both
+				// produce
+				// adequate result. The only difference is whether AnyPolicy is
+				// remain
+				// in the policy tree or not.
+				//
+				// (g) (iii) 1
+				//
+				ISet _validPolicyNodeSet = new HashSet();
+
+				for (int j = 0; j < policyNodes.Length; j++)
+				{
+					IList _nodeDepth = policyNodes[j];
+
+					for (int k = 0; k < _nodeDepth.Count; k++)
+					{
+						PkixPolicyNode _node = (PkixPolicyNode)_nodeDepth[k];
+
+						if (Rfc3280CertPathUtilities.ANY_POLICY.Equals(_node.ValidPolicy))
+						{
+							foreach (PkixPolicyNode _c_node in _node.Children)
+							{
+								if (!Rfc3280CertPathUtilities.ANY_POLICY.Equals(_c_node.ValidPolicy))
+								{
+									_validPolicyNodeSet.Add(_c_node);
+								}
+							}
+						}
+					}
+				}
+
+				//
+				// (g) (iii) 2
+				//
+				IEnumerator _vpnsIter = _validPolicyNodeSet.GetEnumerator();
+				while (_vpnsIter.MoveNext())
+				{
+					PkixPolicyNode _node = (PkixPolicyNode)_vpnsIter.Current;
+					string _validPolicy = _node.ValidPolicy;
+
+					if (!userInitialPolicySet.Contains(_validPolicy))
+					{
+						validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes, _node);
+					}
+				}
+
+				//
+				// (g) (iii) 4
+				//
+				if (validPolicyTree != null)
+				{
+					for (int j = (n - 1); j >= 0; j--)
+					{
+						IList nodes = policyNodes[j];
+
+						for (int k = 0; k < nodes.Count; k++)
+						{
+							PkixPolicyNode node = (PkixPolicyNode)nodes[k];
+							if (!node.HasChildren)
+							{
+								validPolicyTree = PkixCertPathValidatorUtilities.RemovePolicyNode(validPolicyTree, policyNodes,
+									node);
+							}
+						}
+					}
+				}
+
+				intersection = validPolicyTree;
+			}
+			return intersection;
+		}
+
+		/**
+		* If use-deltas is set, verify the issuer and scope of the delta CRL.
+		*
+		* @param deltaCRL    The delta CRL.
+		* @param completeCRL The complete CRL.
+		* @param pkixParams  The PKIX paramaters.
+		* @throws AnnotatedException if an exception occurs.
+		*/
+		internal static void ProcessCrlC(
+			X509Crl			deltaCRL,
+			X509Crl			completeCRL,
+			PkixParameters	pkixParams)
+		{
+			if (deltaCRL == null)
+				return;
+
+			IssuingDistributionPoint completeidp = null;
+			try
+			{
+				completeidp = IssuingDistributionPoint.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(completeCRL, X509Extensions.IssuingDistributionPoint));
+			}
+			catch (Exception e)
+			{
+				throw new Exception("000 Issuing distribution point extension could not be decoded.", e);
+			}
+
+			if (pkixParams.IsUseDeltasEnabled)
+			{
+				// (c) (1)
+				if (!deltaCRL.IssuerDN.Equivalent(completeCRL.IssuerDN, true))
+					throw new Exception("Complete CRL issuer does not match delta CRL issuer.");
+
+				// (c) (2)
+				IssuingDistributionPoint deltaidp = null;
+				try
+				{
+					deltaidp = IssuingDistributionPoint.GetInstance(
+						PkixCertPathValidatorUtilities.GetExtensionValue(deltaCRL, X509Extensions.IssuingDistributionPoint));
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Issuing distribution point extension from delta CRL could not be decoded.", e);
+				}
+
+				if (!Platform.Equals(completeidp, deltaidp))
+				{
+					throw new Exception(
+						"Issuing distribution point extension from delta CRL and complete CRL does not match.");
+				}
+
+				// (c) (3)
+				Asn1Object completeKeyIdentifier = null;
+				try
+				{
+					completeKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue(
+						completeCRL, X509Extensions.AuthorityKeyIdentifier);
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Authority key identifier extension could not be extracted from complete CRL.", e);
+				}
+
+				Asn1Object deltaKeyIdentifier = null;
+				try
+				{
+					deltaKeyIdentifier = PkixCertPathValidatorUtilities.GetExtensionValue(
+						deltaCRL, X509Extensions.AuthorityKeyIdentifier);
+				}
+				catch (Exception e)
+				{
+					throw new Exception(
+						"Authority key identifier extension could not be extracted from delta CRL.", e);
+				}
+
+				if (completeKeyIdentifier == null)
+					throw new Exception("CRL authority key identifier is null.");
+
+				if (deltaKeyIdentifier == null)
+					throw new Exception("Delta CRL authority key identifier is null.");
+
+				if (!completeKeyIdentifier.Equals(deltaKeyIdentifier))
+				{
+					throw new Exception(
+						"Delta CRL authority key identifier does not match complete CRL authority key identifier.");
+				}
+			}
+		}
+
+		internal static void ProcessCrlI(
+			DateTime		validDate,
+			X509Crl			deltacrl,
+			object			cert,
+			CertStatus		certStatus,
+			PkixParameters	pkixParams)
+		{
+			if (pkixParams.IsUseDeltasEnabled && deltacrl != null)
+			{
+				PkixCertPathValidatorUtilities.GetCertStatus(validDate, deltacrl, cert, certStatus);
+			}
+		}
+
+		internal static void ProcessCrlJ(
+			DateTime	validDate,
+			X509Crl		completecrl,
+			object		cert,
+			CertStatus	certStatus)
+		{
+			if (certStatus.Status == CertStatus.Unrevoked)
+			{
+				PkixCertPathValidatorUtilities.GetCertStatus(validDate, completecrl, cert, certStatus);
+			}
+		}
+
+		internal static PkixPolicyNode ProcessCertE(
+			PkixCertPath	certPath,
+			int				index,
+			PkixPolicyNode	validPolicyTree)
+		{
+			IList certs = certPath.Certificates;
+			X509Certificate cert = (X509Certificate)certs[index];
+
+			//
+			// (e)
+			//
+			Asn1Sequence certPolicies = null;
+			try
+			{
+				certPolicies = DerSequence.GetInstance(
+					PkixCertPathValidatorUtilities.GetExtensionValue(cert, X509Extensions.CertificatePolicies));
+			}
+			catch (Exception e)
+			{
+				throw new PkixCertPathValidatorException("Could not read certificate policies extension from certificate.",
+					e, certPath, index);
+			}
+			if (certPolicies == null)
+			{
+				validPolicyTree = null;
+			}
+			return validPolicyTree;
+		}
+
+		internal static readonly string[] CrlReasons = new string[]
+		{
+			"unspecified",
+			"keyCompromise",
+			"cACompromise",
+			"affiliationChanged",
+			"superseded",
+			"cessationOfOperation",
+			"certificateHold",
+			"unknown",
+			"removeFromCRL",
+			"privilegeWithdrawn",
+			"aACompromise"
+		};
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/Rfc3281CertPathUtilities.cs b/BouncyCastle.AxCrypt/src/pkix/Rfc3281CertPathUtilities.cs
new file mode 100644
index 0000000..101ef5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/Rfc3281CertPathUtilities.cs
@@ -0,0 +1,608 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Pkix
+{
+	internal class Rfc3281CertPathUtilities
+	{
+		internal static void ProcessAttrCert7(
+			IX509AttributeCertificate	attrCert,
+			PkixCertPath				certPath,
+			PkixCertPath				holderCertPath,
+			PkixParameters				pkixParams)
+		{
+			// TODO:
+			// AA Controls
+			// Attribute encryption
+			// Proxy
+			ISet critExtOids = attrCert.GetCriticalExtensionOids();
+
+			// 7.1
+			// process extensions
+
+			// target information checked in step 6 / X509AttributeCertStoreSelector
+			if (critExtOids.Contains(X509Extensions.TargetInformation.Id))
+			{
+				try
+				{
+					TargetInformation.GetInstance(PkixCertPathValidatorUtilities
+						.GetExtensionValue(attrCert, X509Extensions.TargetInformation));
+				}
+				catch (Exception e)
+				{
+					throw new PkixCertPathValidatorException(
+						"Target information extension could not be read.", e);
+				}
+			}
+			critExtOids.Remove(X509Extensions.TargetInformation.Id);
+			foreach (PkixAttrCertChecker checker in pkixParams.GetAttrCertCheckers())
+			{
+				checker.Check(attrCert, certPath, holderCertPath, critExtOids);
+			}
+			if (!critExtOids.IsEmpty)
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate contains unsupported critical extensions: "
+						+ critExtOids);
+			}
+		}
+
+		/**
+		* Checks if an attribute certificate is revoked.
+		* 
+		* @param attrCert Attribute certificate to check if it is revoked.
+		* @param paramsPKIX PKIX parameters.
+		* @param issuerCert The issuer certificate of the attribute certificate
+		*            <code>attrCert</code>.
+		* @param validDate The date when the certificate revocation status should
+		*            be checked.
+		* @param certPathCerts The certificates of the certification path to be
+		*            checked.
+		* 
+		* @throws CertPathValidatorException if the certificate is revoked or the
+		*             status cannot be checked or some error occurs.
+		*/
+		internal static void CheckCrls(
+			IX509AttributeCertificate	attrCert,
+			PkixParameters				paramsPKIX,
+			X509Certificate				issuerCert,
+			DateTime					validDate,
+			IList						certPathCerts)
+		{
+			if (paramsPKIX.IsRevocationEnabled)
+			{
+				// check if revocation is available
+				if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) == null)
+				{
+					CrlDistPoint crldp = null;
+					try
+					{
+						crldp = CrlDistPoint.GetInstance(
+							PkixCertPathValidatorUtilities.GetExtensionValue(
+								attrCert, X509Extensions.CrlDistributionPoints));
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"CRL distribution point extension could not be read.", e);
+					}
+					try
+					{
+						PkixCertPathValidatorUtilities
+							.AddAdditionalStoresFromCrlDistributionPoint(crldp, paramsPKIX);
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"No additional CRL locations could be decoded from CRL distribution point extension.", e);
+					}
+					CertStatus certStatus = new CertStatus();
+					ReasonsMask reasonsMask = new ReasonsMask();
+
+					Exception lastException = null;
+					bool validCrlFound = false;
+					// for each distribution point
+					if (crldp != null)
+					{
+						DistributionPoint[] dps = null;
+						try
+						{
+							dps = crldp.GetDistributionPoints();
+						}
+						catch (Exception e)
+						{
+							throw new PkixCertPathValidatorException(
+								"Distribution points could not be read.", e);
+						}
+						try
+						{
+							for (int i = 0; i < dps.Length
+								&& certStatus.Status == CertStatus.Unrevoked
+								&& !reasonsMask.IsAllReasons; i++)
+							{
+								PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX
+									.Clone();
+								CheckCrl(dps[i], attrCert, paramsPKIXClone,
+									validDate, issuerCert, certStatus, reasonsMask,
+									certPathCerts);
+								validCrlFound = true;
+							}
+						}
+						catch (Exception e)
+						{
+							lastException = new Exception(
+								"No valid CRL for distribution point found.", e);
+						}
+					}
+
+					/*
+					* If the revocation status has not been determined, repeat the
+					* process above with any available CRLs not specified in a
+					* distribution point but issued by the certificate issuer.
+					*/
+
+					if (certStatus.Status == CertStatus.Unrevoked
+						&& !reasonsMask.IsAllReasons)
+					{
+						try
+						{
+							/*
+							* assume a DP with both the reasons and the cRLIssuer
+							* fields omitted and a distribution point name of the
+							* certificate issuer.
+							*/
+							Asn1Object issuer = null;
+							try
+							{
+								issuer = new Asn1InputStream(
+									attrCert.Issuer.GetPrincipals()[0].GetEncoded()).ReadObject();
+							}
+							catch (Exception e)
+							{
+								throw new Exception(
+									"Issuer from certificate for CRL could not be reencoded.",
+									e);
+							}
+							DistributionPoint dp = new DistributionPoint(
+								new DistributionPointName(0, new GeneralNames(
+									new GeneralName(GeneralName.DirectoryName, issuer))), null, null);
+							PkixParameters paramsPKIXClone = (PkixParameters) paramsPKIX.Clone();
+							CheckCrl(dp, attrCert, paramsPKIXClone, validDate,
+								issuerCert, certStatus, reasonsMask, certPathCerts);
+							validCrlFound = true;
+						}
+						catch (Exception e)
+						{
+							lastException = new Exception(
+								"No valid CRL for distribution point found.", e);
+						}
+					}
+
+					if (!validCrlFound)
+					{
+						throw new PkixCertPathValidatorException(
+							"No valid CRL found.", lastException);
+					}
+					if (certStatus.Status != CertStatus.Unrevoked)
+					{
+                        // This format is enforced by the NistCertPath tests
+                        string formattedDate = certStatus.RevocationDate.Value.ToString(
+                            "ddd MMM dd HH:mm:ss K yyyy");
+                        string message = "Attribute certificate revocation after "
+							+ formattedDate;
+						message += ", reason: "
+							+ Rfc3280CertPathUtilities.CrlReasons[certStatus.Status];
+						throw new PkixCertPathValidatorException(message);
+					}
+					if (!reasonsMask.IsAllReasons
+						&& certStatus.Status == CertStatus.Unrevoked)
+					{
+						certStatus.Status = CertStatus.Undetermined;
+					}
+					if (certStatus.Status == CertStatus.Undetermined)
+					{
+						throw new PkixCertPathValidatorException(
+							"Attribute certificate status could not be determined.");
+					}
+
+				}
+				else
+				{
+					if (attrCert.GetExtensionValue(X509Extensions.CrlDistributionPoints) != null
+						|| attrCert.GetExtensionValue(X509Extensions.AuthorityInfoAccess) != null)
+					{
+						throw new PkixCertPathValidatorException(
+							"No rev avail extension is set, but also an AC revocation pointer.");
+					}
+				}
+			}
+		}
+
+		internal static void AdditionalChecks(
+			IX509AttributeCertificate	attrCert,
+			PkixParameters				pkixParams)
+		{
+			// 1
+			foreach (string oid in pkixParams.GetProhibitedACAttributes())
+			{
+				if (attrCert.GetAttributes(oid) != null)
+				{
+					throw new PkixCertPathValidatorException(
+						"Attribute certificate contains prohibited attribute: "
+							+ oid + ".");
+				}
+			}
+			foreach (string oid in pkixParams.GetNecessaryACAttributes())
+			{
+				if (attrCert.GetAttributes(oid) == null)
+				{
+					throw new PkixCertPathValidatorException(
+						"Attribute certificate does not contain necessary attribute: "
+							+ oid + ".");
+				}
+			}
+		}
+
+		internal static void ProcessAttrCert5(
+			IX509AttributeCertificate	attrCert,
+			PkixParameters				pkixParams)
+		{
+			try
+			{
+				attrCert.CheckValidity(PkixCertPathValidatorUtilities.GetValidDate(pkixParams));
+			}
+			catch (CertificateExpiredException e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate is not valid.", e);
+			}
+			catch (CertificateNotYetValidException e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate is not valid.", e);
+			}
+		}
+
+		internal static void ProcessAttrCert4(
+			X509Certificate	acIssuerCert,
+			PkixParameters	pkixParams)
+		{
+			ISet set = pkixParams.GetTrustedACIssuers();
+			bool trusted = false;
+			foreach (TrustAnchor anchor in set)
+			{
+                IDictionary symbols = X509Name.RFC2253Symbols;
+                if (acIssuerCert.SubjectDN.ToString(false, symbols).Equals(anchor.CAName)
+					|| acIssuerCert.Equals(anchor.TrustedCert))
+				{
+					trusted = true;
+				}
+			}
+			if (!trusted)
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate issuer is not directly trusted.");
+			}
+		}
+
+		internal static void ProcessAttrCert3(
+			X509Certificate	acIssuerCert,
+			PkixParameters	pkixParams)
+		{
+			if (acIssuerCert.GetKeyUsage() != null
+				&& (!acIssuerCert.GetKeyUsage()[0] && !acIssuerCert.GetKeyUsage()[1]))
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate issuer public key cannot be used to validate digital signatures.");
+			}
+			if (acIssuerCert.GetBasicConstraints() != -1)
+			{
+				throw new PkixCertPathValidatorException(
+					"Attribute certificate issuer is also a public key certificate issuer.");
+			}
+		}
+
+		internal static PkixCertPathValidatorResult ProcessAttrCert2(
+			PkixCertPath	certPath,
+			PkixParameters	pkixParams)
+		{
+			PkixCertPathValidator validator = new PkixCertPathValidator();
+
+			try
+			{
+				return validator.Validate(certPath, pkixParams);
+			}
+			catch (PkixCertPathValidatorException e)
+			{
+				throw new PkixCertPathValidatorException(
+					"Certification path for issuer certificate of attribute certificate could not be validated.",
+					e);
+			}
+		}
+
+		/**
+		* Searches for a holder public key certificate and verifies its
+		* certification path.
+		* 
+		* @param attrCert the attribute certificate.
+		* @param pkixParams The PKIX parameters.
+		* @return The certificate path of the holder certificate.
+		* @throws Exception if
+		*             <ul>
+		*             <li>no public key certificate can be found although holder
+		*             information is given by an entity name or a base certificate
+		*             ID</li>
+		*             <li>support classes cannot be created</li>
+		*             <li>no certification path for the public key certificate can
+		*             be built</li>
+		*             </ul>
+		*/
+		internal static PkixCertPath ProcessAttrCert1(
+			IX509AttributeCertificate	attrCert,
+			PkixParameters				pkixParams)
+		{
+			PkixCertPathBuilderResult result = null;
+			// find holder PKCs
+			ISet holderPKCs = new HashSet();
+			if (attrCert.Holder.GetIssuer() != null)
+			{
+				X509CertStoreSelector selector = new X509CertStoreSelector();
+				selector.SerialNumber = attrCert.Holder.SerialNumber;
+				X509Name[] principals = attrCert.Holder.GetIssuer();
+				for (int i = 0; i < principals.Length; i++)
+				{
+					try
+					{
+//						if (principals[i] is X500Principal)
+						{
+							selector.Issuer = principals[i];
+						}
+						holderPKCs.AddAll(PkixCertPathValidatorUtilities
+							.FindCertificates(selector, pkixParams.GetStores()));
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Public key certificate for attribute certificate cannot be searched.",
+							e);
+					}
+				}
+				if (holderPKCs.IsEmpty)
+				{
+					throw new PkixCertPathValidatorException(
+						"Public key certificate specified in base certificate ID for attribute certificate cannot be found.");
+				}
+			}
+			if (attrCert.Holder.GetEntityNames() != null)
+			{
+				X509CertStoreSelector selector = new X509CertStoreSelector();
+				X509Name[] principals = attrCert.Holder.GetEntityNames();
+				for (int i = 0; i < principals.Length; i++)
+				{
+					try
+					{
+//						if (principals[i] is X500Principal)
+						{
+							selector.Issuer = principals[i];
+						}
+						holderPKCs.AddAll(PkixCertPathValidatorUtilities
+							.FindCertificates(selector, pkixParams.GetStores()));
+					}
+					catch (Exception e)
+					{
+						throw new PkixCertPathValidatorException(
+							"Public key certificate for attribute certificate cannot be searched.",
+							e);
+					}
+				}
+				if (holderPKCs.IsEmpty)
+				{
+					throw new PkixCertPathValidatorException(
+						"Public key certificate specified in entity name for attribute certificate cannot be found.");
+				}
+			}
+
+			// verify cert paths for PKCs
+			PkixBuilderParameters parameters = (PkixBuilderParameters)
+				PkixBuilderParameters.GetInstance(pkixParams);
+
+			PkixCertPathValidatorException lastException = null;
+			foreach (X509Certificate cert in holderPKCs)
+			{
+				X509CertStoreSelector selector = new X509CertStoreSelector();
+				selector.Certificate = cert;
+				parameters.SetTargetConstraints(selector);
+
+				PkixCertPathBuilder builder = new PkixCertPathBuilder();
+
+				try
+				{
+					result = builder.Build(PkixBuilderParameters.GetInstance(parameters));
+				}
+				catch (PkixCertPathBuilderException e)
+				{
+					lastException = new PkixCertPathValidatorException(
+						"Certification path for public key certificate of attribute certificate could not be build.",
+						e);
+				}
+			}
+			if (lastException != null)
+			{
+				throw lastException;
+			}
+			return result.CertPath;
+		}
+
+		/**
+		* 
+		* Checks a distribution point for revocation information for the
+		* certificate <code>attrCert</code>.
+		* 
+		* @param dp The distribution point to consider.
+		* @param attrCert The attribute certificate which should be checked.
+		* @param paramsPKIX PKIX parameters.
+		* @param validDate The date when the certificate revocation status should
+		*            be checked.
+		* @param issuerCert Certificate to check if it is revoked.
+		* @param reasonMask The reasons mask which is already checked.
+		* @param certPathCerts The certificates of the certification path to be
+		*            checked.
+		* @throws Exception if the certificate is revoked or the status
+		*             cannot be checked or some error occurs.
+		*/
+		private static void CheckCrl(
+			DistributionPoint			dp,
+			IX509AttributeCertificate	attrCert,
+			PkixParameters				paramsPKIX,
+			DateTime					validDate,
+			X509Certificate				issuerCert,
+			CertStatus					certStatus,
+			ReasonsMask					reasonMask,
+			IList						certPathCerts)
+		{
+			/*
+			* 4.3.6 No Revocation Available
+			* 
+			* The noRevAvail extension, defined in [X.509-2000], allows an AC
+			* issuer to indicate that no revocation information will be made
+			* available for this AC.
+			*/
+			if (attrCert.GetExtensionValue(X509Extensions.NoRevAvail) != null)
+			{
+				return;
+			}
+
+			DateTime currentDate = DateTime.UtcNow;
+			if (validDate.CompareTo(currentDate) > 0)
+			{
+				throw new Exception("Validation time is in future.");
+			}
+
+			// (a)
+			/*
+			* We always get timely valid CRLs, so there is no step (a) (1).
+			* "locally cached" CRLs are assumed to be in getStore(), additional
+			* CRLs must be enabled in the ExtendedPkixParameters and are in
+			* getAdditionalStore()
+			*/
+			ISet crls = PkixCertPathValidatorUtilities.GetCompleteCrls(dp, attrCert,
+				currentDate, paramsPKIX);
+			bool validCrlFound = false;
+			Exception lastException = null;
+
+			IEnumerator crl_iter = crls.GetEnumerator();
+
+			while (crl_iter.MoveNext()
+				&& certStatus.Status == CertStatus.Unrevoked
+				&& !reasonMask.IsAllReasons)
+			{
+				try
+				{
+					X509Crl crl = (X509Crl) crl_iter.Current;
+
+					// (d)
+					ReasonsMask interimReasonsMask = Rfc3280CertPathUtilities.ProcessCrlD(crl, dp);
+
+					// (e)
+					/*
+					* The reasons mask is updated at the end, so only valid CRLs
+					* can update it. If this CRL does not contain new reasons it
+					* must be ignored.
+					*/
+					if (!interimReasonsMask.HasNewReasons(reasonMask))
+					{
+						continue;
+					}
+
+					// (f)
+					ISet keys = Rfc3280CertPathUtilities.ProcessCrlF(crl, attrCert,
+						null, null, paramsPKIX, certPathCerts);
+					// (g)
+					AsymmetricKeyParameter pubKey = Rfc3280CertPathUtilities.ProcessCrlG(crl, keys);
+
+					X509Crl deltaCRL = null;
+
+					if (paramsPKIX.IsUseDeltasEnabled)
+					{
+						// get delta CRLs
+						ISet deltaCRLs = PkixCertPathValidatorUtilities.GetDeltaCrls(
+							currentDate, paramsPKIX, crl);
+						// we only want one valid delta CRL
+						// (h)
+						deltaCRL = Rfc3280CertPathUtilities.ProcessCrlH(deltaCRLs, pubKey);
+					}
+
+					/*
+					* CRL must be be valid at the current time, not the validation
+					* time. If a certificate is revoked with reason keyCompromise,
+					* cACompromise, it can be used for forgery, also for the past.
+					* This reason may not be contained in older CRLs.
+					*/
+
+					/*
+					* in the chain model signatures stay valid also after the
+					* certificate has been expired, so they do not have to be in
+					* the CRL vality time
+					*/
+					if (paramsPKIX.ValidityModel != PkixParameters.ChainValidityModel)
+					{
+						/*
+						* if a certificate has expired, but was revoked, it is not
+						* more in the CRL, so it would be regarded as valid if the
+						* first check is not done
+						*/
+						if (attrCert.NotAfter.CompareTo(crl.ThisUpdate) < 0)
+						{
+							throw new Exception(
+								"No valid CRL for current time found.");
+						}
+					}
+
+					Rfc3280CertPathUtilities.ProcessCrlB1(dp, attrCert, crl);
+
+					// (b) (2)
+					Rfc3280CertPathUtilities.ProcessCrlB2(dp, attrCert, crl);
+
+					// (c)
+					Rfc3280CertPathUtilities.ProcessCrlC(deltaCRL, crl, paramsPKIX);
+
+					// (i)
+					Rfc3280CertPathUtilities.ProcessCrlI(validDate, deltaCRL,
+						attrCert, certStatus, paramsPKIX);
+
+					// (j)
+					Rfc3280CertPathUtilities.ProcessCrlJ(validDate, crl, attrCert,
+						certStatus);
+
+					// (k)
+					if (certStatus.Status == CrlReason.RemoveFromCrl)
+					{
+						certStatus.Status = CertStatus.Unrevoked;
+					}
+
+					// update reasons mask
+					reasonMask.AddReasons(interimReasonsMask);
+					validCrlFound = true;
+				}
+				catch (Exception e)
+				{
+					lastException = e;
+				}
+			}
+			if (!validCrlFound)
+			{
+				throw lastException;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/pkix/TrustAnchor.cs b/BouncyCastle.AxCrypt/src/pkix/TrustAnchor.cs
new file mode 100644
index 0000000..22078ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/pkix/TrustAnchor.cs
@@ -0,0 +1,259 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkix
+{
+	/// <summary>
+	/// A trust anchor or most-trusted Certification Authority (CA).
+	/// 
+	/// This class represents a "most-trusted CA", which is used as a trust anchor
+	/// for validating X.509 certification paths. A most-trusted CA includes the
+	/// public key of the CA, the CA's name, and any constraints upon the set of
+	/// paths which may be validated using this key. These parameters can be
+	/// specified in the form of a trusted X509Certificate or as individual
+	/// parameters.
+	/// </summary>
+	public class TrustAnchor
+	{
+		private readonly AsymmetricKeyParameter pubKey;
+		private readonly string caName;
+		private readonly X509Name caPrincipal;
+		private readonly X509Certificate trustedCert;
+		private byte[] ncBytes;
+		private NameConstraints nc;
+
+		/// <summary>
+		/// Creates an instance of TrustAnchor with the specified X509Certificate and
+	    /// optional name constraints, which are intended to be used as additional
+	    /// constraints when validating an X.509 certification path.
+	    ///	The name constraints are specified as a byte array. This byte array
+	    ///	should contain the DER encoded form of the name constraints, as they
+	    ///	would appear in the NameConstraints structure defined in RFC 2459 and
+	    ///	X.509. The ASN.1 definition of this structure appears below.
+	    ///	
+	    ///	<pre>
+	    ///	NameConstraints ::= SEQUENCE {
+	    ///		permittedSubtrees       [0]     GeneralSubtrees OPTIONAL,
+	    ///		excludedSubtrees        [1]     GeneralSubtrees OPTIONAL }
+	    ///	   
+        /// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
+        /// 
+        ///		GeneralSubtree ::= SEQUENCE {
+        ///		base                    GeneralName,
+        ///		minimum         [0]     BaseDistance DEFAULT 0,
+        ///		maximum         [1]     BaseDistance OPTIONAL }
+        ///		
+        ///		BaseDistance ::= INTEGER (0..MAX)
+		///
+		///		GeneralName ::= CHOICE {
+		///		otherName                       [0]     OtherName,
+		///		rfc822Name                      [1]     IA5String,
+		///		dNSName                         [2]     IA5String,
+		///		x400Address                     [3]     ORAddress,
+		///		directoryName                   [4]     Name,
+		///		ediPartyName                    [5]     EDIPartyName,
+		///		uniformResourceIdentifier       [6]     IA5String,
+		///		iPAddress                       [7]     OCTET STRING,
+		///		registeredID                    [8]     OBJECT IDENTIFIER}
+		///	</pre>
+		///	
+		///	Note that the name constraints byte array supplied is cloned to protect
+		///	against subsequent modifications.
+		/// </summary>
+		/// <param name="trustedCert">a trusted X509Certificate</param>
+		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+		/// NameConstraints extension to be used for checking name
+		/// constraints. Only the value of the extension is included, not
+		/// the OID or criticality flag. Specify null to omit the
+		/// parameter.</param>
+		/// <exception cref="ArgumentNullException">if the specified X509Certificate is null</exception>
+		public TrustAnchor(
+			X509Certificate	trustedCert,
+			byte[]			nameConstraints)
+		{
+			if (trustedCert == null)
+				throw new ArgumentNullException("trustedCert");
+
+			this.trustedCert = trustedCert;
+			this.pubKey = null;
+			this.caName = null;
+			this.caPrincipal = null;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Creates an instance of <c>TrustAnchor</c> where the
+		/// most-trusted CA is specified as an X500Principal and public key.
+		/// </summary>
+		/// <remarks>
+		/// <p>
+		/// Name constraints are an optional parameter, and are intended to be used
+		/// as additional constraints when validating an X.509 certification path.
+		/// </p><p>
+		/// The name constraints are specified as a byte array. This byte array
+		/// contains the DER encoded form of the name constraints, as they
+		/// would appear in the NameConstraints structure defined in RFC 2459
+		/// and X.509. The ASN.1 notation for this structure is supplied in the
+		/// documentation for the other constructors.
+		/// </p><p>
+		/// Note that the name constraints byte array supplied here is cloned to
+		/// protect against subsequent modifications.
+		/// </p>
+		/// </remarks>
+		/// <param name="caPrincipal">the name of the most-trusted CA as X509Name</param>
+		/// <param name="pubKey">the public key of the most-trusted CA</param>
+		/// <param name="nameConstraints">
+		/// a byte array containing the ASN.1 DER encoding of a NameConstraints extension to
+		/// be used for checking name constraints. Only the value of the extension is included,
+		/// not the OID or criticality flag. Specify <c>null</c> to omit the parameter.
+		/// </param>
+		/// <exception cref="ArgumentNullException">
+		/// if <c>caPrincipal</c> or <c>pubKey</c> is null
+		/// </exception>
+		public TrustAnchor(
+			X509Name				caPrincipal,
+			AsymmetricKeyParameter	pubKey,
+			byte[]					nameConstraints) 
+		{
+			if (caPrincipal == null)
+				throw new ArgumentNullException("caPrincipal");
+			if (pubKey == null)
+				throw new ArgumentNullException("pubKey");
+
+			this.trustedCert = null;
+			this.caPrincipal = caPrincipal;
+			this.caName = caPrincipal.ToString();
+			this.pubKey = pubKey;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Creates an instance of <code>TrustAnchor</code> where the most-trusted
+		/// CA is specified as a distinguished name and public key. Name constraints
+		/// are an optional parameter, and are intended to be used as additional
+		/// constraints when validating an X.509 certification path.
+		/// <br/>
+		/// The name constraints are specified as a byte array. This byte array
+		/// contains the DER encoded form of the name constraints, as they would
+		/// appear in the NameConstraints structure defined in RFC 2459 and X.509.
+		/// </summary>
+		/// <param name="caName">the X.500 distinguished name of the most-trusted CA in RFC
+		/// 2253 string format</param>
+		/// <param name="pubKey">the public key of the most-trusted CA</param>
+		/// <param name="nameConstraints">a byte array containing the ASN.1 DER encoding of a
+		/// NameConstraints extension to be used for checking name
+		/// constraints. Only the value of the extension is included, not 
+		/// the OID or criticality flag. Specify null to omit the 
+		/// parameter.</param>
+		/// throws NullPointerException, IllegalArgumentException
+		public TrustAnchor(
+			string					caName,
+			AsymmetricKeyParameter	pubKey,
+			byte[]					nameConstraints)
+		{
+			if (caName == null)
+				throw new ArgumentNullException("caName");
+			if (pubKey == null)
+				throw new ArgumentNullException("pubKey");
+			if (caName.Length == 0)
+				throw new ArgumentException("caName can not be an empty string");
+
+			this.caPrincipal = new X509Name(caName);
+			this.pubKey = pubKey;
+			this.caName = caName;
+			this.trustedCert = null;
+			setNameConstraints(nameConstraints);
+		}
+
+		/// <summary>
+		/// Returns the most-trusted CA certificate.
+		/// </summary>
+		public X509Certificate TrustedCert
+		{
+			get { return this.trustedCert; }
+		}
+
+		/// <summary>
+		/// Returns the name of the most-trusted CA as an X509Name.
+		/// </summary>
+		public X509Name CA
+		{
+			get { return this.caPrincipal; }
+		}
+
+		/// <summary>
+		/// Returns the name of the most-trusted CA in RFC 2253 string format.
+		/// </summary>
+		public string CAName
+		{
+			get { return this.caName; }
+		}
+
+		/// <summary>
+		/// Returns the public key of the most-trusted CA.
+		/// </summary>
+		public AsymmetricKeyParameter CAPublicKey
+		{
+			get { return this.pubKey; }
+		}
+
+		/// <summary>
+		/// Decode the name constraints and clone them if not null.
+		/// </summary>
+		private void setNameConstraints(
+			byte[] bytes) 
+		{
+			if (bytes == null) 
+			{
+				ncBytes = null;
+				nc = null;
+			} 
+			else 
+			{
+				ncBytes = (byte[]) bytes.Clone();
+				// validate DER encoding
+				//nc = new NameConstraintsExtension(Boolean.FALSE, bytes);
+				nc = NameConstraints.GetInstance(Asn1Object.FromByteArray(bytes));
+			}
+		}
+
+		public byte[] GetNameConstraints
+		{
+			get { return Arrays.Clone(ncBytes); }
+		}
+
+		/// <summary>
+		/// Returns a formatted string describing the <code>TrustAnchor</code>.
+		/// </summary>
+		/// <returns>a formatted string describing the <code>TrustAnchor</code></returns>
+		public override string ToString()
+		{
+			// TODO Some of the sub-objects might not implement ToString() properly
+			string nl = Platform.NewLine;
+			StringBuilder sb = new StringBuilder();
+			sb.Append("[");
+			sb.Append(nl);
+			if (this.pubKey != null)
+			{
+				sb.Append("  Trusted CA Public Key: ").Append(this.pubKey).Append(nl);
+				sb.Append("  Trusted CA Issuer Name: ").Append(this.caName).Append(nl);
+			}
+			else
+			{
+				sb.Append("  Trusted CA cert: ").Append(this.TrustedCert).Append(nl);
+			}
+			if (nc != null)
+			{
+				sb.Append("  Name Constraints: ").Append(nc).Append(nl);
+			}
+			return sb.ToString();
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/security/AgreementUtilities.cs b/BouncyCastle.AxCrypt/src/security/AgreementUtilities.cs
new file mode 100644
index 0000000..4c61ac3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/AgreementUtilities.cs
@@ -0,0 +1,105 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+	/// <remarks>
+	///  Utility class for creating IBasicAgreement objects from their names/Oids
+	/// </remarks>
+	public sealed class AgreementUtilities
+	{
+		private AgreementUtilities()
+		{
+		}
+
+		private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+		static AgreementUtilities()
+		{
+			//algorithms[X9ObjectIdentifiers.DHSinglePassCofactorDHSha1KdfScheme.Id] = ?;
+			algorithms[X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme.Id] = "ECDHWITHSHA1KDF";
+			algorithms[X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme.Id] = "ECMQVWITHSHA1KDF";
+		}
+
+		public static IBasicAgreement GetBasicAgreement(
+			DerObjectIdentifier oid)
+		{
+			return GetBasicAgreement(oid.Id);
+		}
+
+		public static IBasicAgreement GetBasicAgreement(
+			string algorithm)
+		{
+			string upper = Platform.ToUpperInvariant(algorithm);
+			string mechanism = (string) algorithms[upper];
+
+			if (mechanism == null)
+			{
+				mechanism = upper;
+			}
+
+			if (mechanism == "DH" || mechanism == "DIFFIEHELLMAN")
+				return new DHBasicAgreement();
+
+			if (mechanism == "ECDH")
+				return new ECDHBasicAgreement();
+
+			if (mechanism == "ECDHC")
+				return new ECDHCBasicAgreement();
+
+			if (mechanism == "ECMQV")
+				return new ECMqvBasicAgreement();
+
+			throw new SecurityUtilityException("Basic Agreement " + algorithm + " not recognised.");
+		}
+
+		public static IBasicAgreement GetBasicAgreementWithKdf(
+			DerObjectIdentifier oid,
+			string				wrapAlgorithm)
+		{
+			return GetBasicAgreementWithKdf(oid.Id, wrapAlgorithm);
+		}
+
+		public static IBasicAgreement GetBasicAgreementWithKdf(
+			string agreeAlgorithm,
+			string wrapAlgorithm)
+		{
+			string upper = Platform.ToUpperInvariant(agreeAlgorithm);
+			string mechanism = (string) algorithms[upper];
+
+			if (mechanism == null)
+			{
+				mechanism = upper;
+			}
+
+			// 'DHWITHSHA1KDF' retained for backward compatibility
+			if (mechanism == "DHWITHSHA1KDF" || mechanism == "ECDHWITHSHA1KDF")
+				return new ECDHWithKdfBasicAgreement(
+					wrapAlgorithm,
+					new ECDHKekGenerator(
+						new Sha1Digest()));
+
+			if (mechanism == "ECMQVWITHSHA1KDF")
+				return new ECMqvWithKdfBasicAgreement(
+					wrapAlgorithm,
+					new ECDHKekGenerator(
+						new Sha1Digest()));
+
+			throw new SecurityUtilityException("Basic Agreement (with KDF) " + agreeAlgorithm + " not recognised.");
+		}
+
+		public static string GetAlgorithmName(
+			DerObjectIdentifier oid)
+		{
+			return (string) algorithms[oid.Id];
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/CipherUtilities.cs b/BouncyCastle.AxCrypt/src/security/CipherUtilities.cs
new file mode 100644
index 0000000..cdb711f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/CipherUtilities.cs
@@ -0,0 +1,735 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Cipher Utility class contains methods that can not be specifically grouped into other classes.
+    /// </remarks>
+    public sealed class CipherUtilities
+    {
+        private enum CipherAlgorithm {
+            AES,
+            ARC4,
+            BLOWFISH,
+            CAMELLIA,
+            CAST5,
+            CAST6,
+            DES,
+            DESEDE,
+            ELGAMAL,
+            GOST28147,
+            HC128,
+            HC256,
+            IDEA,
+            NOEKEON,
+            PBEWITHSHAAND128BITRC4,
+            PBEWITHSHAAND40BITRC4,
+            RC2,
+            RC5,
+            RC5_64,
+            RC6,
+            RIJNDAEL,
+            RSA,
+            SALSA20,
+            SEED,
+            SERPENT,
+            SKIPJACK,
+            TEA,
+            TWOFISH,
+            VMPC,
+            VMPC_KSA3,
+            XTEA,
+        };
+        
+        private enum CipherMode { ECB, NONE, CBC, CCM, CFB, CTR, CTS, EAX, GCM, GOFB, OCB, OFB, OPENPGPCFB, SIC };
+        private enum CipherPadding
+        {
+            NOPADDING,
+            RAW,
+            ISO10126PADDING,
+            ISO10126D2PADDING,
+            ISO10126_2PADDING,
+            ISO7816_4PADDING,
+            ISO9797_1PADDING,
+            ISO9796_1,
+            ISO9796_1PADDING,
+            OAEP,
+            OAEPPADDING,
+            OAEPWITHMD5ANDMGF1PADDING,
+            OAEPWITHSHA1ANDMGF1PADDING,
+            OAEPWITHSHA_1ANDMGF1PADDING,
+            OAEPWITHSHA224ANDMGF1PADDING,
+            OAEPWITHSHA_224ANDMGF1PADDING,
+            OAEPWITHSHA256ANDMGF1PADDING,
+            OAEPWITHSHA_256ANDMGF1PADDING,
+            OAEPWITHSHA384ANDMGF1PADDING,
+            OAEPWITHSHA_384ANDMGF1PADDING,
+            OAEPWITHSHA512ANDMGF1PADDING,
+            OAEPWITHSHA_512ANDMGF1PADDING,
+            PKCS1,
+            PKCS1PADDING,
+            PKCS5,
+            PKCS5PADDING,
+            PKCS7,
+            PKCS7PADDING,
+            TBCPADDING,
+            WITHCTS,
+            X923PADDING,
+            ZEROBYTEPADDING,
+        };
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static CipherUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((CipherAlgorithm)Enums.GetArbitraryValue(typeof(CipherAlgorithm))).ToString();
+            ((CipherMode)Enums.GetArbitraryValue(typeof(CipherMode))).ToString();
+            ((CipherPadding)Enums.GetArbitraryValue(typeof(CipherPadding))).ToString();
+
+            // TODO Flesh out the list of aliases
+
+            algorithms[NistObjectIdentifiers.IdAes128Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Ecb.Id] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS7"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS7PADDING"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS5"] = "AES/ECB/PKCS7PADDING";
+            algorithms["AES//PKCS5PADDING"] = "AES/ECB/PKCS7PADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "AES/CBC/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "AES/CBC/PKCS7PADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "AES/CBC/PKCS7PADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Ofb.Id] = "AES/OFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Ofb.Id] = "AES/OFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Ofb.Id] = "AES/OFB/NOPADDING";
+
+            algorithms[NistObjectIdentifiers.IdAes128Cfb.Id] = "AES/CFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes192Cfb.Id] = "AES/CFB/NOPADDING";
+            algorithms[NistObjectIdentifiers.IdAes256Cfb.Id] = "AES/CFB/NOPADDING";
+
+            algorithms["RSA/ECB/PKCS1"] = "RSA//PKCS1PADDING";
+            algorithms["RSA/ECB/PKCS1PADDING"] = "RSA//PKCS1PADDING";
+            algorithms[PkcsObjectIdentifiers.RsaEncryption.Id] = "RSA//PKCS1PADDING";
+            algorithms[PkcsObjectIdentifiers.IdRsaesOaep.Id] = "RSA//OAEPPADDING";
+
+            algorithms[OiwObjectIdentifiers.DesCbc.Id] = "DES/CBC";
+            algorithms[OiwObjectIdentifiers.DesCfb.Id] = "DES/CFB";
+            algorithms[OiwObjectIdentifiers.DesEcb.Id] = "DES/ECB";
+            algorithms[OiwObjectIdentifiers.DesOfb.Id] = "DES/OFB";
+            algorithms[OiwObjectIdentifiers.DesEde.Id] = "DESEDE";
+            algorithms["TDEA"] = "DESEDE";
+            algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDE/CBC";
+            algorithms[PkcsObjectIdentifiers.RC2Cbc.Id] = "RC2/CBC";
+            algorithms["1.3.6.1.4.1.188.7.1.1.2"] = "IDEA/CBC";
+            algorithms["1.2.840.113533.7.66.10"] = "CAST5/CBC";
+
+            algorithms["RC4"] = "ARC4";
+            algorithms["ARCFOUR"] = "ARC4";
+            algorithms["1.2.840.113549.3.4"] = "ARC4";
+
+
+
+            algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEWITHSHAAND128BITRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEWITHSHAAND128BITRC4";
+            algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEWITHSHAAND40BITRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEWITHSHAAND40BITRC4";
+
+            algorithms["PBEWITHSHA1ANDDES"] = "PBEWITHSHA1ANDDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEWITHSHA1ANDDES-CBC";
+            algorithms["PBEWITHSHA1ANDRC2"] = "PBEWITHSHA1ANDRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEWITHSHA1ANDRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms["PBEWITHSHAAND3KEYTRIPLEDES"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+            algorithms["PBEWITHSHA1ANDDESEDE"] = "PBEWITHSHAAND3-KEYTRIPLEDES-CBC";
+
+            algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEWITHSHAAND2-KEYTRIPLEDES-CBC";
+
+            algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEWITHSHAAND128BITRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEWITHSHAAND128BITRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEWITHSHAAND40BITRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEWITHSHAAND40BITRC2-CBC";
+
+            algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEWITHSHAAND128BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEWITHSHAAND192BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEWITHSHAAND256BITAES-CBC-BC";
+
+            algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEWITHSHA256AND128BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEWITHSHA256AND192BITAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEWITHSHA256AND256BITAES-CBC-BC";
+
+
+            algorithms["GOST"] = "GOST28147";
+            algorithms["GOST-28147"] = "GOST28147";
+            algorithms[CryptoProObjectIdentifiers.GostR28147Cbc.Id] = "GOST28147/CBC/PKCS7PADDING";
+
+            algorithms["RC5-32"] = "RC5";
+
+            algorithms[NttObjectIdentifiers.IdCamellia128Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+            algorithms[NttObjectIdentifiers.IdCamellia192Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+            algorithms[NttObjectIdentifiers.IdCamellia256Cbc.Id] = "CAMELLIA/CBC/PKCS7PADDING";
+
+            algorithms[KisaObjectIdentifiers.IdSeedCbc.Id] = "SEED/CBC/PKCS7PADDING";
+
+            algorithms["1.3.6.1.4.1.3029.1.2"] = "BLOWFISH/CBC";
+        }
+
+        private CipherUtilities()
+        {
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        // TODO Don't really want to support this
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            if (mechanism == null)
+                throw new ArgumentNullException("mechanism");
+
+            mechanism = Platform.ToUpperInvariant(mechanism);
+            string aliased = (string) algorithms[mechanism];
+
+            if (aliased != null)
+                mechanism = aliased;
+
+            return (DerObjectIdentifier) oids[mechanism];
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static IBufferedCipher GetCipher(
+            DerObjectIdentifier oid)
+        {
+            return GetCipher(oid.Id);
+        }
+
+        public static IBufferedCipher GetCipher(
+            string algorithm)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            algorithm = Platform.ToUpperInvariant(algorithm);
+
+            {
+                string aliased = (string) algorithms[algorithm];
+
+                if (aliased != null)
+                    algorithm = aliased;
+            }
+
+            IBasicAgreement iesAgreement = null;
+            if (algorithm == "IES")
+            {
+                iesAgreement = new DHBasicAgreement();
+            }
+            else if (algorithm == "ECIES")
+            {
+                iesAgreement = new ECDHBasicAgreement();
+            }
+
+            if (iesAgreement != null)
+            {
+                return new BufferedIesCipher(
+                    new IesEngine(
+                    iesAgreement,
+                    new Kdf2BytesGenerator(
+                    new Sha1Digest()),
+                    new HMac(
+                    new Sha1Digest())));
+            }
+
+
+
+            if (algorithm.StartsWith("PBE"))
+            {
+                if (algorithm.EndsWith("-CBC"))
+                {
+                    if (algorithm == "PBEWITHSHA1ANDDES-CBC")
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new DesEngine()));
+                    }
+                    else if (algorithm == "PBEWITHSHA1ANDRC2-CBC")
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new RC2Engine()));
+                    }
+                    else if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND2-KEYTRIPLEDES-CBC", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new DesEdeEngine()));
+                    }
+                    else if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND128BITRC2-CBC", "PBEWITHSHAAND40BITRC2-CBC"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new RC2Engine()));
+                    }
+                }
+                else if (algorithm.EndsWith("-BC") || algorithm.EndsWith("-OPENSSL"))
+                {
+                    if (Strings.IsOneOf(algorithm,
+                        "PBEWITHSHAAND128BITAES-CBC-BC",
+                        "PBEWITHSHAAND192BITAES-CBC-BC",
+                        "PBEWITHSHAAND256BITAES-CBC-BC",
+                        "PBEWITHSHA256AND128BITAES-CBC-BC",
+                        "PBEWITHSHA256AND192BITAES-CBC-BC",
+                        "PBEWITHSHA256AND256BITAES-CBC-BC",
+                        "PBEWITHMD5AND128BITAES-CBC-OPENSSL",
+                        "PBEWITHMD5AND192BITAES-CBC-OPENSSL",
+                        "PBEWITHMD5AND256BITAES-CBC-OPENSSL"))
+                    {
+                        return new PaddedBufferedBlockCipher(
+                            new CbcBlockCipher(new AesFastEngine()));
+                    }
+                }
+            }
+
+
+
+            string[] parts = algorithm.Split('/');
+
+            IBlockCipher blockCipher = null;
+            IAsymmetricBlockCipher asymBlockCipher = null;
+            IStreamCipher streamCipher = null;
+
+            string algorithmName = parts[0];
+
+            {
+                string aliased = (string)algorithms[algorithmName];
+
+                if (aliased != null)
+                    algorithmName = aliased;
+            }
+
+            CipherAlgorithm cipherAlgorithm;
+            try
+            {
+                cipherAlgorithm = (CipherAlgorithm)Enums.GetEnumValue(typeof(CipherAlgorithm), algorithmName);
+            }
+            catch (ArgumentException)
+            {
+                throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+            }
+
+            switch (cipherAlgorithm)
+            {
+                case CipherAlgorithm.AES:
+                    blockCipher = new AesFastEngine();
+                    break;
+                case CipherAlgorithm.ARC4:
+                    streamCipher = new RC4Engine();
+                    break;
+                case CipherAlgorithm.BLOWFISH:
+                    blockCipher = new BlowfishEngine();
+                    break;
+                case CipherAlgorithm.CAMELLIA:
+                    blockCipher = new CamelliaEngine();
+                    break;
+                case CipherAlgorithm.CAST5:
+                    blockCipher = new Cast5Engine();
+                    break;
+                case CipherAlgorithm.CAST6:
+                    blockCipher = new Cast6Engine();
+                    break;
+                case CipherAlgorithm.DES:
+                    blockCipher = new DesEngine();
+                    break;
+                case CipherAlgorithm.DESEDE:
+                    blockCipher = new DesEdeEngine();
+                    break;
+                case CipherAlgorithm.ELGAMAL:
+                    asymBlockCipher = new ElGamalEngine();
+                    break;
+                case CipherAlgorithm.GOST28147:
+                    blockCipher = new Gost28147Engine();
+                    break;
+                case CipherAlgorithm.HC128:
+                    streamCipher = new HC128Engine();
+                    break;
+                case CipherAlgorithm.HC256:
+                    streamCipher = new HC256Engine();
+                    break;
+                case CipherAlgorithm.IDEA:
+                    blockCipher = new IdeaEngine();
+                    break;
+                case CipherAlgorithm.NOEKEON:
+                    blockCipher = new NoekeonEngine();
+                    break;
+                case CipherAlgorithm.PBEWITHSHAAND128BITRC4:
+                case CipherAlgorithm.PBEWITHSHAAND40BITRC4:
+                    streamCipher = new RC4Engine();
+                    break;
+                case CipherAlgorithm.RC2:
+                    blockCipher = new RC2Engine();
+                    break;
+                case CipherAlgorithm.RC5:
+                    blockCipher = new RC532Engine();
+                    break;
+                case CipherAlgorithm.RC5_64:
+                    blockCipher = new RC564Engine();
+                    break;
+                case CipherAlgorithm.RC6:
+                    blockCipher = new RC6Engine();
+                    break;
+                case CipherAlgorithm.RIJNDAEL:
+                    blockCipher = new RijndaelEngine();
+                    break;
+                case CipherAlgorithm.RSA:
+                    asymBlockCipher = new RsaBlindedEngine();
+                    break;
+                case CipherAlgorithm.SALSA20:
+                    streamCipher = new Salsa20Engine();
+                    break;
+                case CipherAlgorithm.SEED:
+                    blockCipher = new SeedEngine();
+                    break;
+                case CipherAlgorithm.SERPENT:
+                    blockCipher = new SerpentEngine();
+                    break;
+                case CipherAlgorithm.SKIPJACK:
+                    blockCipher = new SkipjackEngine();
+                    break;
+                case CipherAlgorithm.TEA:
+                    blockCipher = new TeaEngine();
+                    break;
+                case CipherAlgorithm.TWOFISH:
+                    blockCipher = new TwofishEngine();
+                    break;
+                case CipherAlgorithm.VMPC:
+                    streamCipher = new VmpcEngine();
+                    break;
+                case CipherAlgorithm.VMPC_KSA3:
+                    streamCipher = new VmpcKsa3Engine();
+                    break;
+                case CipherAlgorithm.XTEA:
+                    blockCipher = new XteaEngine();
+                    break;
+                default:
+                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+            }
+
+            if (streamCipher != null)
+            {
+                if (parts.Length > 1)
+                    throw new ArgumentException("Modes and paddings not used for stream ciphers");
+
+                return new BufferedStreamCipher(streamCipher);
+            }
+
+
+            bool cts = false;
+            bool padded = true;
+            IBlockCipherPadding padding = null;
+            IAeadBlockCipher aeadBlockCipher = null;
+
+            if (parts.Length > 2)
+            {
+                if (streamCipher != null)
+                    throw new ArgumentException("Paddings not used for stream ciphers");
+
+                string paddingName = parts[2];
+
+                CipherPadding cipherPadding;
+                if (paddingName == "")
+                {
+                    cipherPadding = CipherPadding.RAW;
+                }
+                else if (paddingName == "X9.23PADDING")
+                {
+                    cipherPadding = CipherPadding.X923PADDING;
+                }
+                else
+                {
+                    try
+                    {
+                        cipherPadding = (CipherPadding)Enums.GetEnumValue(typeof(CipherPadding), paddingName);
+                    }
+                    catch (ArgumentException)
+                    {
+                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                    }
+                }
+
+                switch (cipherPadding)
+                {
+                    case CipherPadding.NOPADDING:
+                        padded = false;
+                        break;
+                    case CipherPadding.RAW:
+                        break;
+                    case CipherPadding.ISO10126PADDING:
+                    case CipherPadding.ISO10126D2PADDING:
+                    case CipherPadding.ISO10126_2PADDING:
+                        padding = new ISO10126d2Padding();
+                        break;
+                    case CipherPadding.ISO7816_4PADDING:
+                    case CipherPadding.ISO9797_1PADDING:
+                        padding = new ISO7816d4Padding();
+                        break;
+                    case CipherPadding.ISO9796_1:
+                    case CipherPadding.ISO9796_1PADDING:
+                        asymBlockCipher = new ISO9796d1Encoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.OAEP:
+                    case CipherPadding.OAEPPADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.OAEPWITHMD5ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new MD5Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA1ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_1ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha1Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA224ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_224ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha224Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA256ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_256ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha256Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA384ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_384ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha384Digest());
+                        break;
+                    case CipherPadding.OAEPWITHSHA512ANDMGF1PADDING:
+                    case CipherPadding.OAEPWITHSHA_512ANDMGF1PADDING:
+                        asymBlockCipher = new OaepEncoding(asymBlockCipher, new Sha512Digest());
+                        break;
+                    case CipherPadding.PKCS1:
+                    case CipherPadding.PKCS1PADDING:
+                        asymBlockCipher = new Pkcs1Encoding(asymBlockCipher);
+                        break;
+                    case CipherPadding.PKCS5:
+                    case CipherPadding.PKCS5PADDING:
+                    case CipherPadding.PKCS7:
+                    case CipherPadding.PKCS7PADDING:
+                        padding = new Pkcs7Padding();
+                        break;
+                    case CipherPadding.TBCPADDING:
+                        padding = new TbcPadding();
+                        break;
+                    case CipherPadding.WITHCTS:
+                        cts = true;
+                        break;
+                    case CipherPadding.X923PADDING:
+                        padding = new X923Padding();
+                        break;
+                    case CipherPadding.ZEROBYTEPADDING:
+                        padding = new ZeroBytePadding();
+                        break;
+                    default:
+                        throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                }
+            }
+
+            string mode = "";
+            if (parts.Length > 1)
+            {
+                mode = parts[1];
+
+                int di = GetDigitIndex(mode);
+                string modeName = di >= 0 ? mode.Substring(0, di) : mode;
+
+                try
+                {
+                    CipherMode cipherMode = modeName == ""
+                        ? CipherMode.NONE
+                        : (CipherMode)Enums.GetEnumValue(typeof(CipherMode), modeName);
+
+                    switch (cipherMode)
+                    {
+                        case CipherMode.ECB:
+                        case CipherMode.NONE:
+                            break;
+                        case CipherMode.CBC:
+                            blockCipher = new CbcBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CCM:
+                            aeadBlockCipher = new CcmBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CFB:
+                        {
+                            int bits = (di < 0)
+                                ?	8 * blockCipher.GetBlockSize()
+                                :	int.Parse(mode.Substring(di));
+    
+                            blockCipher = new CfbBlockCipher(blockCipher, bits);
+                            break;
+                        }
+                        case CipherMode.CTR:
+                            blockCipher = new SicBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.CTS:
+                            cts = true;
+                            blockCipher = new CbcBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.EAX:
+                            aeadBlockCipher = new EaxBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.GCM:
+                            aeadBlockCipher = new GcmBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.GOFB:
+                            blockCipher = new GOfbBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.OCB:
+                            aeadBlockCipher = new OcbBlockCipher(blockCipher, CreateBlockCipher(cipherAlgorithm));
+                            break;
+                        case CipherMode.OFB:
+                        {
+                            int bits = (di < 0)
+                                ?	8 * blockCipher.GetBlockSize()
+                                :	int.Parse(mode.Substring(di));
+    
+                            blockCipher = new OfbBlockCipher(blockCipher, bits);
+                            break;
+                        }
+                        case CipherMode.OPENPGPCFB:
+                            blockCipher = new OpenPgpCfbBlockCipher(blockCipher);
+                            break;
+                        case CipherMode.SIC:
+                            if (blockCipher.GetBlockSize() < 16)
+                            {
+                                throw new ArgumentException("Warning: SIC-Mode can become a twotime-pad if the blocksize of the cipher is too small. Use a cipher with a block size of at least 128 bits (e.g. AES)");
+                            }
+                            blockCipher = new SicBlockCipher(blockCipher);
+                            break;
+                        default:
+                            throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                    }
+                }
+                catch (ArgumentException)
+                {
+                    throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+                }
+            }
+
+            if (aeadBlockCipher != null)
+            {
+                if (cts)
+                    throw new SecurityUtilityException("CTS mode not valid for AEAD ciphers.");
+                if (padded && parts.Length > 2 && parts[2] != "")
+                    throw new SecurityUtilityException("Bad padding specified for AEAD cipher.");
+
+                return new BufferedAeadBlockCipher(aeadBlockCipher);
+            }
+
+            if (blockCipher != null)
+            {
+                if (cts)
+                {
+                    return new CtsBlockCipher(blockCipher);
+                }
+
+                if (padding != null)
+                {
+                    return new PaddedBufferedBlockCipher(blockCipher, padding);
+                }
+
+                if (!padded || blockCipher.IsPartialBlockOkay)
+                {
+                    return new BufferedBlockCipher(blockCipher);
+                }
+
+                return new PaddedBufferedBlockCipher(blockCipher);
+            }
+
+            if (asymBlockCipher != null)
+            {
+                return new BufferedAsymmetricBlockCipher(asymBlockCipher);
+            }
+
+            throw new SecurityUtilityException("Cipher " + algorithm + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private static int GetDigitIndex(
+            string s)
+        {
+            for (int i = 0; i < s.Length; ++i)
+            {
+                if (char.IsDigit(s[i]))
+                    return i;
+            }
+
+            return -1;
+        }
+
+        private static IBlockCipher CreateBlockCipher(CipherAlgorithm cipherAlgorithm)
+        {
+            switch (cipherAlgorithm)
+            {
+                case CipherAlgorithm.AES: return new AesFastEngine();
+                case CipherAlgorithm.BLOWFISH: return new BlowfishEngine();
+                case CipherAlgorithm.CAMELLIA: return new CamelliaEngine();
+                case CipherAlgorithm.CAST5: return new Cast5Engine();
+                case CipherAlgorithm.CAST6: return new Cast6Engine();
+                case CipherAlgorithm.DES: return new DesEngine();
+                case CipherAlgorithm.DESEDE: return new DesEdeEngine();
+                case CipherAlgorithm.GOST28147: return new Gost28147Engine();
+                case CipherAlgorithm.IDEA: return new IdeaEngine();
+                case CipherAlgorithm.NOEKEON: return new NoekeonEngine();
+                case CipherAlgorithm.RC2: return new RC2Engine();
+                case CipherAlgorithm.RC5: return new RC532Engine();
+                case CipherAlgorithm.RC5_64: return new RC564Engine();
+                case CipherAlgorithm.RC6: return new RC6Engine();
+                case CipherAlgorithm.RIJNDAEL: return new RijndaelEngine();
+                case CipherAlgorithm.SEED: return new SeedEngine();
+                case CipherAlgorithm.SERPENT: return new SerpentEngine();
+                case CipherAlgorithm.SKIPJACK: return new SkipjackEngine();
+                case CipherAlgorithm.TEA: return new TeaEngine();
+                case CipherAlgorithm.TWOFISH: return new TwofishEngine();
+                case CipherAlgorithm.XTEA: return new XteaEngine();
+                default:
+                    throw new SecurityUtilityException("Cipher " + cipherAlgorithm + " not recognised or not a block cipher");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/DigestUtilities.cs b/BouncyCastle.AxCrypt/src/security/DigestUtilities.cs
new file mode 100644
index 0000000..ec3f639
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/DigestUtilities.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating IDigest objects from their names/Oids
+    /// </remarks>
+    public sealed class DigestUtilities
+    {
+        private enum DigestAlgorithm {
+            GOST3411,
+            MD2, MD4, MD5,
+            RIPEMD128, RIPEMD160, RIPEMD256, RIPEMD320,
+            SHA_1, SHA_224, SHA_256, SHA_384, SHA_512,
+            SHA_512_224, SHA_512_256,
+            SHA3_224, SHA3_256, SHA3_384, SHA3_512,
+            TIGER,
+            WHIRLPOOL,
+        };
+
+        private DigestUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static DigestUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((DigestAlgorithm)Enums.GetArbitraryValue(typeof(DigestAlgorithm))).ToString();
+
+            algorithms[PkcsObjectIdentifiers.MD2.Id] = "MD2";
+            algorithms[PkcsObjectIdentifiers.MD4.Id] = "MD4";
+            algorithms[PkcsObjectIdentifiers.MD5.Id] = "MD5";
+
+            algorithms["SHA1"] = "SHA-1";
+            algorithms[OiwObjectIdentifiers.IdSha1.Id] = "SHA-1";
+            algorithms["SHA224"] = "SHA-224";
+            algorithms[NistObjectIdentifiers.IdSha224.Id] = "SHA-224";
+            algorithms["SHA256"] = "SHA-256";
+            algorithms[NistObjectIdentifiers.IdSha256.Id] = "SHA-256";
+            algorithms["SHA384"] = "SHA-384";
+            algorithms[NistObjectIdentifiers.IdSha384.Id] = "SHA-384";
+            algorithms["SHA512"] = "SHA-512";
+            algorithms[NistObjectIdentifiers.IdSha512.Id] = "SHA-512";
+            algorithms["SHA512/224"] = "SHA-512/224";
+            algorithms[NistObjectIdentifiers.IdSha512_224.Id] = "SHA-512/224";
+            algorithms["SHA512/256"] = "SHA-512/256";
+            algorithms[NistObjectIdentifiers.IdSha512_256.Id] = "SHA-512/256";
+
+            algorithms["RIPEMD-128"] = "RIPEMD128";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "RIPEMD128";
+            algorithms["RIPEMD-160"] = "RIPEMD160";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "RIPEMD160";
+            algorithms["RIPEMD-256"] = "RIPEMD256";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "RIPEMD256";
+            algorithms["RIPEMD-320"] = "RIPEMD320";
+//			algorithms[TeleTrusTObjectIdentifiers.RipeMD320.Id] = "RIPEMD320";
+
+            algorithms[CryptoProObjectIdentifiers.GostR3411.Id] = "GOST3411";
+
+
+
+            oids["MD2"] = PkcsObjectIdentifiers.MD2;
+            oids["MD4"] = PkcsObjectIdentifiers.MD4;
+            oids["MD5"] = PkcsObjectIdentifiers.MD5;
+            oids["SHA-1"] = OiwObjectIdentifiers.IdSha1;
+            oids["SHA-224"] = NistObjectIdentifiers.IdSha224;
+            oids["SHA-256"] = NistObjectIdentifiers.IdSha256;
+            oids["SHA-384"] = NistObjectIdentifiers.IdSha384;
+            oids["SHA-512"] = NistObjectIdentifiers.IdSha512;
+            oids["SHA-512/224"] = NistObjectIdentifiers.IdSha512_224;
+            oids["SHA-512/256"] = NistObjectIdentifiers.IdSha512_256;
+            oids["RIPEMD128"] = TeleTrusTObjectIdentifiers.RipeMD128;
+            oids["RIPEMD160"] = TeleTrusTObjectIdentifiers.RipeMD160;
+            oids["RIPEMD256"] = TeleTrusTObjectIdentifiers.RipeMD256;
+            oids["GOST3411"] = CryptoProObjectIdentifiers.GostR3411;
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a given digest mechanism.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the digest meanism.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            if (mechanism == null)
+                throw new System.ArgumentNullException("mechanism");
+
+            mechanism = Platform.ToUpperInvariant(mechanism);
+            string aliased = (string) algorithms[mechanism];
+
+            if (aliased != null)
+                mechanism = aliased;
+
+            return (DerObjectIdentifier) oids[mechanism];
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static IDigest GetDigest(
+            DerObjectIdentifier id)
+        {
+            return GetDigest(id.Id);
+        }
+
+        public static IDigest GetDigest(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            string mechanism = (string) algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            try
+            {
+                DigestAlgorithm digestAlgorithm = (DigestAlgorithm)Enums.GetEnumValue(
+                    typeof(DigestAlgorithm), mechanism);
+
+                switch (digestAlgorithm)
+                {
+                    case DigestAlgorithm.GOST3411:      return new Gost3411Digest();
+                    case DigestAlgorithm.MD2:		    return new MD2Digest();
+                    case DigestAlgorithm.MD4:		    return new MD4Digest();
+                    case DigestAlgorithm.MD5:		    return new MD5Digest();
+                    case DigestAlgorithm.RIPEMD128:	    return new RipeMD128Digest();
+                    case DigestAlgorithm.RIPEMD160:	    return new RipeMD160Digest();
+                    case DigestAlgorithm.RIPEMD256:	    return new RipeMD256Digest();
+                    case DigestAlgorithm.RIPEMD320:	    return new RipeMD320Digest();
+                    case DigestAlgorithm.SHA_1:		    return new Sha1Digest();
+                    case DigestAlgorithm.SHA_224:	    return new Sha224Digest();
+                    case DigestAlgorithm.SHA_256:	    return new Sha256Digest();
+                    case DigestAlgorithm.SHA_384:	    return new Sha384Digest();
+                    case DigestAlgorithm.SHA_512:	    return new Sha512Digest();
+                    case DigestAlgorithm.SHA_512_224:   return new Sha512tDigest(224);
+                    case DigestAlgorithm.SHA_512_256:   return new Sha512tDigest(256);
+                    case DigestAlgorithm.SHA3_224:      return new Sha3Digest(224);
+                    case DigestAlgorithm.SHA3_256:      return new Sha3Digest(256);
+                    case DigestAlgorithm.SHA3_384:      return new Sha3Digest(384);
+                    case DigestAlgorithm.SHA3_512:      return new Sha3Digest(512);
+                    case DigestAlgorithm.TIGER:         return new TigerDigest();
+                    case DigestAlgorithm.WHIRLPOOL:     return new WhirlpoolDigest();
+                }
+            }
+            catch (ArgumentException)
+            {
+            }
+
+            throw new SecurityUtilityException("Digest " + mechanism + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        public static byte[] CalculateDigest(string algorithm, byte[] input)
+        {
+            IDigest digest = GetDigest(algorithm);
+            digest.BlockUpdate(input, 0, input.Length);
+            return DoFinal(digest);
+        }
+
+        public static byte[] DoFinal(
+            IDigest digest)
+        {
+            byte[] b = new byte[digest.GetDigestSize()];
+            digest.DoFinal(b, 0);
+            return b;
+        }
+
+        public static byte[] DoFinal(
+            IDigest	digest,
+            byte[]	input)
+        {
+            digest.BlockUpdate(input, 0, input.Length);
+            return DoFinal(digest);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/DotNetUtilities.cs b/BouncyCastle.AxCrypt/src/security/DotNetUtilities.cs
new file mode 100644
index 0000000..d50e17d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/DotNetUtilities.cs
@@ -0,0 +1,243 @@
+#if !(NETCF_1_0 || SILVERLIGHT)
+
+using System;
+using System.Security.Cryptography;
+using SystemX509 = System.Security.Cryptography.X509Certificates;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Security
+{
+	/// <summary>
+	/// A class containing methods to interface the BouncyCastle world to the .NET Crypto world.
+	/// </summary>
+	public sealed class DotNetUtilities
+	{
+		private DotNetUtilities()
+		{
+		}
+
+		/// <summary>
+		/// Create an System.Security.Cryptography.X509Certificate from an X509Certificate Structure.
+		/// </summary>
+		/// <param name="x509Struct"></param>
+		/// <returns>A System.Security.Cryptography.X509Certificate.</returns>
+		public static SystemX509.X509Certificate ToX509Certificate(
+			X509CertificateStructure x509Struct)
+		{
+			return new SystemX509.X509Certificate(x509Struct.GetDerEncoded());
+		}
+
+		public static SystemX509.X509Certificate ToX509Certificate(
+			X509Certificate x509Cert)
+		{
+			return new SystemX509.X509Certificate(x509Cert.GetEncoded());
+		}
+
+		public static X509Certificate FromX509Certificate(
+			SystemX509.X509Certificate x509Cert)
+		{
+			return new X509CertificateParser().ReadCertificate(x509Cert.GetRawCertData());
+		}
+
+		public static AsymmetricCipherKeyPair GetDsaKeyPair(
+			DSA dsa)
+		{
+			return GetDsaKeyPair(dsa.ExportParameters(true));
+		}
+
+		public static AsymmetricCipherKeyPair GetDsaKeyPair(
+			DSAParameters dp)
+		{
+			DsaValidationParameters validationParameters = (dp.Seed != null)
+				?	new DsaValidationParameters(dp.Seed, dp.Counter)
+				:	null;
+
+			DsaParameters parameters = new DsaParameters(
+				new BigInteger(1, dp.P),
+				new BigInteger(1, dp.Q),
+				new BigInteger(1, dp.G),
+				validationParameters);
+
+			DsaPublicKeyParameters pubKey = new DsaPublicKeyParameters(
+				new BigInteger(1, dp.Y),
+				parameters);
+
+			DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters(
+				new BigInteger(1, dp.X),
+				parameters);
+
+			return new AsymmetricCipherKeyPair(pubKey, privKey);
+		}
+
+		public static DsaPublicKeyParameters GetDsaPublicKey(
+			DSA dsa)
+		{
+			return GetDsaPublicKey(dsa.ExportParameters(false));
+		}
+
+		public static DsaPublicKeyParameters GetDsaPublicKey(
+			DSAParameters dp)
+		{
+			DsaValidationParameters validationParameters = (dp.Seed != null)
+				?	new DsaValidationParameters(dp.Seed, dp.Counter)
+				:	null;
+
+			DsaParameters parameters = new DsaParameters(
+				new BigInteger(1, dp.P),
+				new BigInteger(1, dp.Q),
+				new BigInteger(1, dp.G),
+				validationParameters);
+
+			return new DsaPublicKeyParameters(
+				new BigInteger(1, dp.Y),
+				parameters);
+		}
+
+		public static AsymmetricCipherKeyPair GetRsaKeyPair(
+			RSA rsa)
+		{
+			return GetRsaKeyPair(rsa.ExportParameters(true));
+		}
+
+		public static AsymmetricCipherKeyPair GetRsaKeyPair(
+			RSAParameters rp)
+		{
+			BigInteger modulus = new BigInteger(1, rp.Modulus);
+			BigInteger pubExp = new BigInteger(1, rp.Exponent);
+
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				modulus,
+				pubExp);
+
+			RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+				modulus,
+				pubExp,
+				new BigInteger(1, rp.D),
+				new BigInteger(1, rp.P),
+				new BigInteger(1, rp.Q),
+				new BigInteger(1, rp.DP),
+				new BigInteger(1, rp.DQ),
+				new BigInteger(1, rp.InverseQ));
+
+			return new AsymmetricCipherKeyPair(pubKey, privKey);
+		}
+
+		public static RsaKeyParameters GetRsaPublicKey(
+			RSA rsa)
+		{
+			return GetRsaPublicKey(rsa.ExportParameters(false));
+		}
+
+		public static RsaKeyParameters GetRsaPublicKey(
+			RSAParameters rp)
+		{
+			return new RsaKeyParameters(
+				false,
+				new BigInteger(1, rp.Modulus),
+				new BigInteger(1, rp.Exponent));
+		}
+
+		public static AsymmetricCipherKeyPair GetKeyPair(AsymmetricAlgorithm privateKey)
+		{
+			if (privateKey is DSA)
+			{
+				return GetDsaKeyPair((DSA)privateKey);
+			}
+
+			if (privateKey is RSA)
+			{
+				return GetRsaKeyPair((RSA)privateKey);
+			}
+
+			throw new ArgumentException("Unsupported algorithm specified", "privateKey");
+		}
+
+		public static RSA ToRSA(RsaKeyParameters rsaKey)
+		{
+            // TODO This appears to not work for private keys (when no CRT info)
+            return CreateRSAProvider(ToRSAParameters(rsaKey));
+        }
+
+		public static RSA ToRSA(RsaPrivateCrtKeyParameters privKey)
+		{
+            return CreateRSAProvider(ToRSAParameters(privKey));
+        }
+
+        public static RSA ToRSA(RsaPrivateKeyStructure privKey)
+        {
+            return CreateRSAProvider(ToRSAParameters(privKey));
+        }
+
+        public static RSAParameters ToRSAParameters(RsaKeyParameters rsaKey)
+		{
+			RSAParameters rp = new RSAParameters();
+			rp.Modulus = rsaKey.Modulus.ToByteArrayUnsigned();
+			if (rsaKey.IsPrivate)
+				rp.D = ConvertRSAParametersField(rsaKey.Exponent, rp.Modulus.Length);
+			else
+				rp.Exponent = rsaKey.Exponent.ToByteArrayUnsigned();
+			return rp;
+		}
+
+		public static RSAParameters ToRSAParameters(RsaPrivateCrtKeyParameters privKey)
+		{
+			RSAParameters rp = new RSAParameters();
+			rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
+			rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
+			rp.P = privKey.P.ToByteArrayUnsigned();
+			rp.Q = privKey.Q.ToByteArrayUnsigned();
+			rp.D = ConvertRSAParametersField(privKey.Exponent, rp.Modulus.Length);
+			rp.DP = ConvertRSAParametersField(privKey.DP, rp.P.Length);
+			rp.DQ = ConvertRSAParametersField(privKey.DQ, rp.Q.Length);
+			rp.InverseQ = ConvertRSAParametersField(privKey.QInv, rp.Q.Length);
+			return rp;
+		}
+
+        public static RSAParameters ToRSAParameters(RsaPrivateKeyStructure privKey)
+        {
+            RSAParameters rp = new RSAParameters();
+            rp.Modulus = privKey.Modulus.ToByteArrayUnsigned();
+            rp.Exponent = privKey.PublicExponent.ToByteArrayUnsigned();
+            rp.P = privKey.Prime1.ToByteArrayUnsigned();
+            rp.Q = privKey.Prime2.ToByteArrayUnsigned();
+            rp.D = ConvertRSAParametersField(privKey.PrivateExponent, rp.Modulus.Length);
+            rp.DP = ConvertRSAParametersField(privKey.Exponent1, rp.P.Length);
+            rp.DQ = ConvertRSAParametersField(privKey.Exponent2, rp.Q.Length);
+            rp.InverseQ = ConvertRSAParametersField(privKey.Coefficient, rp.Q.Length);
+            return rp;
+        }
+
+        // TODO Move functionality to more general class
+		private static byte[] ConvertRSAParametersField(BigInteger n, int size)
+		{
+			byte[] bs = n.ToByteArrayUnsigned();
+
+			if (bs.Length == size)
+				return bs;
+
+			if (bs.Length > size)
+				throw new ArgumentException("Specified size too small", "size");
+
+			byte[] padded = new byte[size];
+			Array.Copy(bs, 0, padded, size - bs.Length, bs.Length);
+			return padded;
+		}
+
+        private static RSA CreateRSAProvider(RSAParameters rp)
+        {
+            RSACryptoServiceProvider rsaCsp = new RSACryptoServiceProvider();
+            rsaCsp.ImportParameters(rp);
+            return rsaCsp;
+        }
+	}
+}
+
+#endif
diff --git a/BouncyCastle.AxCrypt/src/security/GeneralSecurityException.cs b/BouncyCastle.AxCrypt/src/security/GeneralSecurityException.cs
new file mode 100644
index 0000000..2c3f2a5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/GeneralSecurityException.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class GeneralSecurityException
+		: Exception
+	{
+		public GeneralSecurityException()
+			: base()
+		{
+		}
+
+		public GeneralSecurityException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public GeneralSecurityException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/GeneratorUtilities.cs b/BouncyCastle.AxCrypt/src/security/GeneratorUtilities.cs
new file mode 100644
index 0000000..45fbc94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/GeneratorUtilities.cs
@@ -0,0 +1,349 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class GeneratorUtilities
+    {
+        private GeneratorUtilities()
+        {
+        }
+
+        private static readonly IDictionary kgAlgorithms = Platform.CreateHashtable();
+        private static readonly IDictionary kpgAlgorithms = Platform.CreateHashtable();
+        private static readonly IDictionary defaultKeySizes = Platform.CreateHashtable();
+
+        static GeneratorUtilities()
+        {
+            //
+            // key generators.
+            //
+            AddKgAlgorithm("AES",
+                "AESWRAP");
+            AddKgAlgorithm("AES128",
+                "2.16.840.1.101.3.4.2",
+                NistObjectIdentifiers.IdAes128Cbc,
+                NistObjectIdentifiers.IdAes128Cfb,
+                NistObjectIdentifiers.IdAes128Ecb,
+                NistObjectIdentifiers.IdAes128Ofb,
+                NistObjectIdentifiers.IdAes128Wrap);
+            AddKgAlgorithm("AES192",
+                "2.16.840.1.101.3.4.22",
+                NistObjectIdentifiers.IdAes192Cbc,
+                NistObjectIdentifiers.IdAes192Cfb,
+                NistObjectIdentifiers.IdAes192Ecb,
+                NistObjectIdentifiers.IdAes192Ofb,
+                NistObjectIdentifiers.IdAes192Wrap);
+            AddKgAlgorithm("AES256",
+                "2.16.840.1.101.3.4.42",
+                NistObjectIdentifiers.IdAes256Cbc,
+                NistObjectIdentifiers.IdAes256Cfb,
+                NistObjectIdentifiers.IdAes256Ecb,
+                NistObjectIdentifiers.IdAes256Ofb,
+                NistObjectIdentifiers.IdAes256Wrap);
+            AddKgAlgorithm("BLOWFISH",
+                "1.3.6.1.4.1.3029.1.2");
+            AddKgAlgorithm("CAMELLIA",
+                "CAMELLIAWRAP");
+            AddKgAlgorithm("CAMELLIA128",
+                NttObjectIdentifiers.IdCamellia128Cbc,
+                NttObjectIdentifiers.IdCamellia128Wrap);
+            AddKgAlgorithm("CAMELLIA192",
+                NttObjectIdentifiers.IdCamellia192Cbc,
+                NttObjectIdentifiers.IdCamellia192Wrap);
+            AddKgAlgorithm("CAMELLIA256",
+                NttObjectIdentifiers.IdCamellia256Cbc,
+                NttObjectIdentifiers.IdCamellia256Wrap);
+            AddKgAlgorithm("CAST5",
+                "1.2.840.113533.7.66.10");
+            AddKgAlgorithm("CAST6");
+            AddKgAlgorithm("DES",
+                OiwObjectIdentifiers.DesCbc,
+                OiwObjectIdentifiers.DesCfb,
+                OiwObjectIdentifiers.DesEcb,
+                OiwObjectIdentifiers.DesOfb);
+            AddKgAlgorithm("DESEDE",
+                "DESEDEWRAP",
+                "TDEA",
+                OiwObjectIdentifiers.DesEde);
+            AddKgAlgorithm("DESEDE3",
+                PkcsObjectIdentifiers.DesEde3Cbc,
+                PkcsObjectIdentifiers.IdAlgCms3DesWrap);
+            AddKgAlgorithm("GOST28147",
+                "GOST",
+                "GOST-28147",
+                CryptoProObjectIdentifiers.GostR28147Cbc);
+            AddKgAlgorithm("HC128");
+            AddKgAlgorithm("HC256");
+            AddKgAlgorithm("IDEA",
+                "1.3.6.1.4.1.188.7.1.1.2");
+            AddKgAlgorithm("NOEKEON");
+            AddKgAlgorithm("RC2",
+                PkcsObjectIdentifiers.RC2Cbc,
+                PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
+            AddKgAlgorithm("RC4",
+                "ARC4",
+                "1.2.840.113549.3.4");
+            AddKgAlgorithm("RC5",
+                "RC5-32");
+            AddKgAlgorithm("RC5-64");
+            AddKgAlgorithm("RC6");
+            AddKgAlgorithm("RIJNDAEL");
+            AddKgAlgorithm("SALSA20");
+            AddKgAlgorithm("SEED",
+                KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
+                KisaObjectIdentifiers.IdSeedCbc);
+            AddKgAlgorithm("SERPENT");
+            AddKgAlgorithm("SKIPJACK");
+            AddKgAlgorithm("TEA");
+            AddKgAlgorithm("TWOFISH");
+            AddKgAlgorithm("VMPC");
+            AddKgAlgorithm("VMPC-KSA3");
+            AddKgAlgorithm("XTEA");
+
+            //
+            // HMac key generators
+            //
+            AddHMacKeyGenerator("MD2");
+            AddHMacKeyGenerator("MD4");
+            AddHMacKeyGenerator("MD5",
+                IanaObjectIdentifiers.HmacMD5);
+            AddHMacKeyGenerator("SHA1",
+                PkcsObjectIdentifiers.IdHmacWithSha1,
+                IanaObjectIdentifiers.HmacSha1);
+            AddHMacKeyGenerator("SHA224",
+                PkcsObjectIdentifiers.IdHmacWithSha224);
+            AddHMacKeyGenerator("SHA256",
+                PkcsObjectIdentifiers.IdHmacWithSha256);
+            AddHMacKeyGenerator("SHA384",
+                PkcsObjectIdentifiers.IdHmacWithSha384);
+            AddHMacKeyGenerator("SHA512",
+                PkcsObjectIdentifiers.IdHmacWithSha512);
+            AddHMacKeyGenerator("SHA512/224");
+            AddHMacKeyGenerator("SHA512/256");
+            AddHMacKeyGenerator("SHA3-224");
+            AddHMacKeyGenerator("SHA3-256");
+            AddHMacKeyGenerator("SHA3-384");
+            AddHMacKeyGenerator("SHA3-512");
+            AddHMacKeyGenerator("RIPEMD128");
+            AddHMacKeyGenerator("RIPEMD160",
+                IanaObjectIdentifiers.HmacRipeMD160);
+            AddHMacKeyGenerator("TIGER",
+                IanaObjectIdentifiers.HmacTiger);
+
+
+
+            //
+            // key pair generators.
+            //
+            AddKpgAlgorithm("DH",
+                "DIFFIEHELLMAN");
+            AddKpgAlgorithm("DSA");
+            AddKpgAlgorithm("EC",
+                // TODO Should this be an alias for ECDH?
+                X9ObjectIdentifiers.DHSinglePassStdDHSha1KdfScheme);
+            AddKpgAlgorithm("ECDH",
+                "ECIES");
+            AddKpgAlgorithm("ECDHC");
+            AddKpgAlgorithm("ECMQV",
+                X9ObjectIdentifiers.MqvSinglePassSha1KdfScheme);
+            AddKpgAlgorithm("ECDSA");
+            AddKpgAlgorithm("ECGOST3410",
+                "ECGOST-3410",
+                "GOST-3410-2001");
+            AddKpgAlgorithm("ELGAMAL");
+            AddKpgAlgorithm("GOST3410",
+                "GOST-3410",
+                "GOST-3410-94");
+            AddKpgAlgorithm("RSA",
+                "1.2.840.113549.1.1.1");
+
+            AddDefaultKeySizeEntries(64, "DES");
+            AddDefaultKeySizeEntries(80, "SKIPJACK");
+            AddDefaultKeySizeEntries(128, "AES128", "BLOWFISH", "CAMELLIA128", "CAST5", "DESEDE",
+                "HC128", "HMACMD2", "HMACMD4", "HMACMD5", "HMACRIPEMD128", "IDEA", "NOEKEON",
+                "RC2", "RC4", "RC5", "SALSA20", "SEED", "TEA", "XTEA", "VMPC", "VMPC-KSA3");
+            AddDefaultKeySizeEntries(160, "HMACRIPEMD160", "HMACSHA1");
+            AddDefaultKeySizeEntries(192, "AES", "AES192", "CAMELLIA192", "DESEDE3", "HMACTIGER",
+                "RIJNDAEL", "SERPENT");
+            AddDefaultKeySizeEntries(224, "HMACSHA224");
+            AddDefaultKeySizeEntries(256, "AES256", "CAMELLIA", "CAMELLIA256", "CAST6", "GOST28147",
+                "HC256", "HMACSHA256", "RC5-64", "RC6", "TWOFISH");
+            AddDefaultKeySizeEntries(384, "HMACSHA384");
+            AddDefaultKeySizeEntries(512, "HMACSHA512");
+            AddDefaultKeySizeEntries(224, "HMACSHA512/224");
+            AddDefaultKeySizeEntries(256, "HMACSHA512/256");
+        }
+
+        private static void AddDefaultKeySizeEntries(int size, params string[] algorithms)
+        {
+            foreach (string algorithm in algorithms)
+            {
+                defaultKeySizes.Add(algorithm, size);
+            }
+        }
+
+        private static void AddKgAlgorithm(
+            string			canonicalName,
+            params object[] aliases)
+        {
+            kgAlgorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                kgAlgorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddKpgAlgorithm(
+            string			canonicalName,
+            params object[] aliases)
+        {
+            kpgAlgorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                kpgAlgorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddHMacKeyGenerator(
+            string			algorithm,
+            params object[]	aliases)
+        {
+            string mainName = "HMAC" + algorithm;
+
+            kgAlgorithms[mainName] = mainName;
+            kgAlgorithms["HMAC-" + algorithm] = mainName;
+            kgAlgorithms["HMAC/" + algorithm] = mainName;
+
+            foreach (object alias in aliases)
+            {
+                kgAlgorithms[alias.ToString()] = mainName;
+            }
+        }
+
+        // TODO Consider making this public
+        internal static string GetCanonicalKeyGeneratorAlgorithm(
+            string algorithm)
+        {
+            return (string) kgAlgorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        // TODO Consider making this public
+        internal static string GetCanonicalKeyPairGeneratorAlgorithm(
+            string algorithm)
+        {
+            return (string)kpgAlgorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        public static CipherKeyGenerator GetKeyGenerator(
+            DerObjectIdentifier oid)
+        {
+            return GetKeyGenerator(oid.Id);
+        }
+
+        public static CipherKeyGenerator GetKeyGenerator(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+
+            int defaultKeySize = FindDefaultKeySize(canonicalName);
+            if (defaultKeySize == -1)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm
+                    + " (" + canonicalName + ") not supported.");
+
+            if (canonicalName == "DES")
+                return new DesKeyGenerator(defaultKeySize);
+
+            if (canonicalName == "DESEDE" || canonicalName == "DESEDE3")
+                return new DesEdeKeyGenerator(defaultKeySize);
+
+            return new CipherKeyGenerator(defaultKeySize);
+        }
+
+        public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+            DerObjectIdentifier oid)
+        {
+            return GetKeyPairGenerator(oid.Id);
+        }
+
+        public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyPairGenerator " + algorithm + " not recognised.");
+
+            if (canonicalName == "DH")
+                return new DHKeyPairGenerator();
+
+            if (canonicalName == "DSA")
+                return new DsaKeyPairGenerator();
+
+            // "EC", "ECDH", "ECDHC", "ECDSA", "ECGOST3410", "ECMQV"
+            if (canonicalName.StartsWith("EC"))
+                return new ECKeyPairGenerator(canonicalName);
+
+            if (canonicalName == "ELGAMAL")
+                return new ElGamalKeyPairGenerator();
+
+            if (canonicalName == "GOST3410")
+                return new Gost3410KeyPairGenerator();
+
+            if (canonicalName == "RSA")
+                return new RsaKeyPairGenerator();
+
+            throw new SecurityUtilityException("KeyPairGenerator " + algorithm
+                + " (" + canonicalName + ") not supported.");
+        }
+
+        internal static int GetDefaultKeySize(
+            DerObjectIdentifier oid)
+        {
+            return GetDefaultKeySize(oid.Id);
+        }
+
+        internal static int GetDefaultKeySize(
+            string algorithm)
+        {
+            string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
+
+            if (canonicalName == null)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm + " not recognised.");
+
+            int defaultKeySize = FindDefaultKeySize(canonicalName);
+            if (defaultKeySize == -1)
+                throw new SecurityUtilityException("KeyGenerator " + algorithm
+                    + " (" + canonicalName + ") not supported.");
+
+            return defaultKeySize;
+        }
+
+        private static int FindDefaultKeySize(
+            string canonicalName)
+        {
+            if (!defaultKeySizes.Contains(canonicalName))
+                return -1;
+
+            return (int)defaultKeySizes[canonicalName];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/InvalidKeyException.cs b/BouncyCastle.AxCrypt/src/security/InvalidKeyException.cs
new file mode 100644
index 0000000..4d4488e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/InvalidKeyException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class InvalidKeyException : KeyException
+	{
+		public InvalidKeyException() : base() { }
+		public InvalidKeyException(string message) : base(message) { }
+		public InvalidKeyException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/InvalidParameterException.cs b/BouncyCastle.AxCrypt/src/security/InvalidParameterException.cs
new file mode 100644
index 0000000..57a912d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/InvalidParameterException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class InvalidParameterException : KeyException
+	{
+		public InvalidParameterException() : base() { }
+		public InvalidParameterException(string message) : base(message) { }
+		public InvalidParameterException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/KeyException.cs b/BouncyCastle.AxCrypt/src/security/KeyException.cs
new file mode 100644
index 0000000..9304c1c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/KeyException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class KeyException : GeneralSecurityException
+	{
+		public KeyException() : base() { }
+		public KeyException(string message) : base(message) { }
+		public KeyException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/MacUtilities.cs b/BouncyCastle.AxCrypt/src/security/MacUtilities.cs
new file mode 100644
index 0000000..d1f8c89
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/MacUtilities.cs
@@ -0,0 +1,246 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating HMac object from their names/Oids
+    /// </remarks>
+    public sealed class MacUtilities
+    {
+        private MacUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static MacUtilities()
+        {
+            algorithms[IanaObjectIdentifiers.HmacMD5.Id] = "HMAC-MD5";
+            algorithms[IanaObjectIdentifiers.HmacRipeMD160.Id] = "HMAC-RIPEMD160";
+            algorithms[IanaObjectIdentifiers.HmacSha1.Id] = "HMAC-SHA1";
+            algorithms[IanaObjectIdentifiers.HmacTiger.Id] = "HMAC-TIGER";
+
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha1.Id] = "HMAC-SHA1";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha224.Id] = "HMAC-SHA224";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha256.Id] = "HMAC-SHA256";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha384.Id] = "HMAC-SHA384";
+            algorithms[PkcsObjectIdentifiers.IdHmacWithSha512.Id] = "HMAC-SHA512";
+
+            // TODO AESMAC?
+
+            algorithms["DES"] = "DESMAC";
+            algorithms["DES/CFB8"] = "DESMAC/CFB8";
+            algorithms["DES64"] = "DESMAC64";
+            algorithms["DESEDE"] = "DESEDEMAC";
+            algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "DESEDEMAC";
+            algorithms["DESEDE/CFB8"] = "DESEDEMAC/CFB8";
+            algorithms["DESISO9797MAC"] = "DESWITHISO9797";
+            algorithms["DESEDE64"] = "DESEDEMAC64";
+
+            algorithms["DESEDE64WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            algorithms["DESEDEISO9797ALG1MACWITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+            algorithms["DESEDEISO9797ALG1WITHISO7816-4PADDING"] = "DESEDEMAC64WITHISO7816-4PADDING";
+
+            algorithms["ISO9797ALG3"] = "ISO9797ALG3MAC";
+            algorithms["ISO9797ALG3MACWITHISO7816-4PADDING"] = "ISO9797ALG3WITHISO7816-4PADDING";
+
+            algorithms["SKIPJACK"] = "SKIPJACKMAC";
+            algorithms["SKIPJACK/CFB8"] = "SKIPJACKMAC/CFB8";
+            algorithms["IDEA"] = "IDEAMAC";
+            algorithms["IDEA/CFB8"] = "IDEAMAC/CFB8";
+            algorithms["RC2"] = "RC2MAC";
+            algorithms["RC2/CFB8"] = "RC2MAC/CFB8";
+            algorithms["RC5"] = "RC5MAC";
+            algorithms["RC5/CFB8"] = "RC5MAC/CFB8";
+            algorithms["GOST28147"] = "GOST28147MAC";
+            algorithms["VMPC"] = "VMPCMAC";
+            algorithms["VMPC-MAC"] = "VMPCMAC";
+            algorithms["SIPHASH"] = "SIPHASH-2-4";
+
+            algorithms["PBEWITHHMACSHA"] = "PBEWITHHMACSHA1";
+            algorithms["1.3.14.3.2.26"] = "PBEWITHHMACSHA1";
+        }
+
+//		/// <summary>
+//		/// Returns a ObjectIdentifier for a given digest mechanism.
+//		/// </summary>
+//		/// <param name="mechanism">A string representation of the digest meanism.</param>
+//		/// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+//		public static DerObjectIdentifier GetObjectIdentifier(
+//			string mechanism)
+//		{
+//			mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)];
+//
+//			if (mechanism != null)
+//			{
+//				return (DerObjectIdentifier)oids[mechanism];
+//			}
+//
+//			return null;
+//		}
+
+//		public static ICollection Algorithms
+//		{
+//			get { return oids.Keys; }
+//		}
+
+        public static IMac GetMac(
+            DerObjectIdentifier id)
+        {
+            return GetMac(id.Id);
+        }
+
+        public static IMac GetMac(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+
+            string mechanism = (string) algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            if (mechanism.StartsWith("PBEWITH"))
+            {
+                mechanism = mechanism.Substring("PBEWITH".Length);
+            }
+
+            if (mechanism.StartsWith("HMAC"))
+            {
+                string digestName;
+                if (mechanism.StartsWith("HMAC-") || mechanism.StartsWith("HMAC/"))
+                {
+                    digestName = mechanism.Substring(5);
+                }
+                else
+                {
+                    digestName = mechanism.Substring(4);
+                }
+
+                return new HMac(DigestUtilities.GetDigest(digestName));
+            }
+
+            if (mechanism == "AESCMAC")
+            {
+                return new CMac(new AesFastEngine());
+            }
+            if (mechanism == "DESMAC")
+            {
+                return new CbcBlockCipherMac(new DesEngine());
+            }
+            if (mechanism == "DESMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new DesEngine());
+            }
+            if (mechanism == "DESMAC64")
+            {
+                return new CbcBlockCipherMac(new DesEngine(), 64);
+            }
+            if (mechanism == "DESEDECMAC")
+            {
+                return new CMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new DesEdeEngine());
+            }
+            if (mechanism == "DESEDEMAC64")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine(), 64);
+            }
+            if (mechanism == "DESEDEMAC64WITHISO7816-4PADDING")
+            {
+                return new CbcBlockCipherMac(new DesEdeEngine(), 64, new ISO7816d4Padding());
+            }
+            if (mechanism == "DESWITHISO9797"
+                || mechanism == "ISO9797ALG3MAC")
+            {
+                return new ISO9797Alg3Mac(new DesEngine());
+            }
+            if (mechanism == "ISO9797ALG3WITHISO7816-4PADDING")
+            {
+                return new ISO9797Alg3Mac(new DesEngine(), new ISO7816d4Padding());
+            }
+            if (mechanism == "SKIPJACKMAC")
+            {
+                return new CbcBlockCipherMac(new SkipjackEngine());
+            }
+            if (mechanism == "SKIPJACKMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new SkipjackEngine());
+            }
+            if (mechanism == "IDEAMAC")
+            {
+                return new CbcBlockCipherMac(new IdeaEngine());
+            }
+            if (mechanism == "IDEAMAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new IdeaEngine());
+            }
+            if (mechanism == "RC2MAC")
+            {
+                return new CbcBlockCipherMac(new RC2Engine());
+            }
+            if (mechanism == "RC2MAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new RC2Engine());
+            }
+            if (mechanism == "RC5MAC")
+            {
+                return new CbcBlockCipherMac(new RC532Engine());
+            }
+            if (mechanism == "RC5MAC/CFB8")
+            {
+                return new CfbBlockCipherMac(new RC532Engine());
+            }
+            if (mechanism == "GOST28147MAC")
+            {
+                return new Gost28147Mac();
+            }
+            if (mechanism == "VMPCMAC")
+            {
+                return new VmpcMac();
+            }
+            if (mechanism == "SIPHASH-2-4")
+            {
+                return new SipHash();
+            }
+            throw new SecurityUtilityException("Mac " + mechanism + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        public static byte[] DoFinal(IMac mac)
+        {
+            byte[] b = new byte[mac.GetMacSize()];
+            mac.DoFinal(b, 0);
+            return b;
+        }
+
+        public static byte[] DoFinal(IMac mac, byte[] input)
+        {
+            mac.BlockUpdate(input, 0, input.Length);
+            return DoFinal(mac);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/NoSuchAlgorithmException.cs b/BouncyCastle.AxCrypt/src/security/NoSuchAlgorithmException.cs
new file mode 100644
index 0000000..d120c5f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/NoSuchAlgorithmException.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+	[Obsolete("Never thrown")]
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class NoSuchAlgorithmException : GeneralSecurityException
+	{
+		public NoSuchAlgorithmException() : base() {}
+		public NoSuchAlgorithmException(string message) : base(message) {}
+		public NoSuchAlgorithmException(string message, Exception exception) : base(message, exception) {}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/ParameterUtilities.cs b/BouncyCastle.AxCrypt/src/security/ParameterUtilities.cs
new file mode 100644
index 0000000..b2d7c0d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/ParameterUtilities.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class ParameterUtilities
+    {
+        private ParameterUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary basicIVSizes = Platform.CreateHashtable();
+
+        static ParameterUtilities()
+        {
+            AddAlgorithm("AES",
+                "AESWRAP");
+            AddAlgorithm("AES128",
+                "2.16.840.1.101.3.4.2",
+                NistObjectIdentifiers.IdAes128Cbc,
+                NistObjectIdentifiers.IdAes128Cfb,
+                NistObjectIdentifiers.IdAes128Ecb,
+                NistObjectIdentifiers.IdAes128Ofb,
+                NistObjectIdentifiers.IdAes128Wrap);
+            AddAlgorithm("AES192",
+                "2.16.840.1.101.3.4.22",
+                NistObjectIdentifiers.IdAes192Cbc,
+                NistObjectIdentifiers.IdAes192Cfb,
+                NistObjectIdentifiers.IdAes192Ecb,
+                NistObjectIdentifiers.IdAes192Ofb,
+                NistObjectIdentifiers.IdAes192Wrap);
+            AddAlgorithm("AES256",
+                "2.16.840.1.101.3.4.42",
+                NistObjectIdentifiers.IdAes256Cbc,
+                NistObjectIdentifiers.IdAes256Cfb,
+                NistObjectIdentifiers.IdAes256Ecb,
+                NistObjectIdentifiers.IdAes256Ofb,
+                NistObjectIdentifiers.IdAes256Wrap);
+            AddAlgorithm("BLOWFISH",
+                "1.3.6.1.4.1.3029.1.2");
+            AddAlgorithm("CAMELLIA",
+                "CAMELLIAWRAP");
+            AddAlgorithm("CAMELLIA128",
+                NttObjectIdentifiers.IdCamellia128Cbc,
+                NttObjectIdentifiers.IdCamellia128Wrap);
+            AddAlgorithm("CAMELLIA192",
+                NttObjectIdentifiers.IdCamellia192Cbc,
+                NttObjectIdentifiers.IdCamellia192Wrap);
+            AddAlgorithm("CAMELLIA256",
+                NttObjectIdentifiers.IdCamellia256Cbc,
+                NttObjectIdentifiers.IdCamellia256Wrap);
+            AddAlgorithm("CAST5",
+                "1.2.840.113533.7.66.10");
+            AddAlgorithm("CAST6");
+            AddAlgorithm("DES",
+                OiwObjectIdentifiers.DesCbc,
+                OiwObjectIdentifiers.DesCfb,
+                OiwObjectIdentifiers.DesEcb,
+                OiwObjectIdentifiers.DesOfb);
+            AddAlgorithm("DESEDE",
+                "DESEDEWRAP",
+                "TDEA",
+                OiwObjectIdentifiers.DesEde,
+                PkcsObjectIdentifiers.IdAlgCms3DesWrap);
+            AddAlgorithm("DESEDE3",
+                PkcsObjectIdentifiers.DesEde3Cbc);
+            AddAlgorithm("GOST28147",
+                "GOST",
+                "GOST-28147",
+                CryptoProObjectIdentifiers.GostR28147Cbc);
+            AddAlgorithm("HC128");
+            AddAlgorithm("HC256");
+            AddAlgorithm("IDEA",
+                "1.3.6.1.4.1.188.7.1.1.2");
+            AddAlgorithm("NOEKEON");
+            AddAlgorithm("RC2",
+                PkcsObjectIdentifiers.RC2Cbc,
+                PkcsObjectIdentifiers.IdAlgCmsRC2Wrap);
+            AddAlgorithm("RC4",
+                "ARC4",
+                "1.2.840.113549.3.4");
+            AddAlgorithm("RC5",
+                "RC5-32");
+            AddAlgorithm("RC5-64");
+            AddAlgorithm("RC6");
+            AddAlgorithm("RIJNDAEL");
+            AddAlgorithm("SALSA20");
+            AddAlgorithm("SEED",
+                KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap,
+                KisaObjectIdentifiers.IdSeedCbc);
+            AddAlgorithm("SERPENT");
+            AddAlgorithm("SKIPJACK");
+            AddAlgorithm("TEA");
+            AddAlgorithm("TWOFISH");
+            AddAlgorithm("VMPC");
+            AddAlgorithm("VMPC-KSA3");
+            AddAlgorithm("XTEA");
+
+            AddBasicIVSizeEntries(8, "BLOWFISH", "DES", "DESEDE", "DESEDE3");
+            AddBasicIVSizeEntries(16, "AES", "AES128", "AES192", "AES256",
+                "CAMELLIA", "CAMELLIA128", "CAMELLIA192", "CAMELLIA256", "NOEKEON", "SEED");
+
+            // TODO These algorithms support an IV
+            // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+            // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+        }
+
+        private static void AddAlgorithm(
+            string			canonicalName,
+            params object[]	aliases)
+        {
+            algorithms[canonicalName] = canonicalName;
+
+            foreach (object alias in aliases)
+            {
+                algorithms[alias.ToString()] = canonicalName;
+            }
+        }
+
+        private static void AddBasicIVSizeEntries(int size, params string[] algorithms)
+        {
+            foreach (string algorithm in algorithms)
+            {
+                basicIVSizes.Add(algorithm, size);
+            }
+        }
+
+        public static string GetCanonicalAlgorithmName(
+            string algorithm)
+        {
+            return (string) algorithms[Platform.ToUpperInvariant(algorithm)];
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            DerObjectIdentifier algOid,
+            byte[]				keyBytes)
+        {
+            return CreateKeyParameter(algOid.Id, keyBytes, 0, keyBytes.Length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            string	algorithm,
+            byte[]	keyBytes)
+        {
+            return CreateKeyParameter(algorithm, keyBytes, 0, keyBytes.Length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            DerObjectIdentifier algOid,
+            byte[]				keyBytes,
+            int					offset,
+            int					length)
+        {
+            return CreateKeyParameter(algOid.Id, keyBytes, offset, length);
+        }
+
+        public static KeyParameter CreateKeyParameter(
+            string	algorithm,
+            byte[]	keyBytes,
+            int		offset,
+            int		length)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            if (canonical == "DES")
+                return new DesParameters(keyBytes, offset, length);
+
+            if (canonical == "DESEDE" || canonical =="DESEDE3")
+                return new DesEdeParameters(keyBytes, offset, length);
+
+            if (canonical == "RC2")
+                return new RC2Parameters(keyBytes, offset, length);
+
+            return new KeyParameter(keyBytes, offset, length);
+        }
+
+        public static ICipherParameters GetCipherParameters(
+            DerObjectIdentifier	algOid,
+            ICipherParameters	key,
+            Asn1Object			asn1Params)
+        {
+            return GetCipherParameters(algOid.Id, key, asn1Params);
+        }
+
+        public static ICipherParameters GetCipherParameters(
+            string				algorithm,
+            ICipherParameters	key,
+            Asn1Object			asn1Params)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            byte[] iv = null;
+
+            try
+            {
+                // TODO These algorithms support an IV
+                // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+                // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+
+                int basicIVKeySize = FindBasicIVSize(canonical);
+                if (basicIVKeySize != -1
+                    || canonical == "RIJNDAEL" || canonical == "SKIPJACK" || canonical == "TWOFISH")
+                {
+                    iv = ((Asn1OctetString) asn1Params).GetOctets();
+                }
+                else if (canonical == "CAST5")
+                {
+                    iv = Cast5CbcParameters.GetInstance(asn1Params).GetIV();
+                }
+                else if (canonical == "IDEA")
+                {
+                    iv = IdeaCbcPar.GetInstance(asn1Params).GetIV();
+                }
+                else if (canonical == "RC2")
+                {
+                    iv = RC2CbcParameter.GetInstance(asn1Params).GetIV();
+                }
+            }
+            catch (Exception e)
+            {
+                throw new ArgumentException("Could not process ASN.1 parameters", e);
+            }
+
+            if (iv != null)
+            {
+                return new ParametersWithIV(key, iv);
+            }
+
+            throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+        }
+
+        public static Asn1Encodable GenerateParameters(
+            DerObjectIdentifier algID,
+            SecureRandom		random)
+        {
+            return GenerateParameters(algID.Id, random);
+        }
+
+        public static Asn1Encodable GenerateParameters(
+            string			algorithm,
+            SecureRandom	random)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            string canonical = GetCanonicalAlgorithmName(algorithm);
+
+            if (canonical == null)
+                throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+
+            // TODO These algorithms support an IV
+            // but JCE doesn't seem to provide an AlgorithmParametersGenerator for them
+            // "RIJNDAEL", "SKIPJACK", "TWOFISH"
+
+            int basicIVKeySize = FindBasicIVSize(canonical);
+            if (basicIVKeySize != -1)
+                return CreateIVOctetString(random, basicIVKeySize);
+
+            if (canonical == "CAST5")
+                return new Cast5CbcParameters(CreateIV(random, 8), 128);
+
+            if (canonical == "IDEA")
+                return new IdeaCbcPar(CreateIV(random, 8));
+
+            if (canonical == "RC2")
+                return new RC2CbcParameter(CreateIV(random, 8));
+
+            throw new SecurityUtilityException("Algorithm " + algorithm + " not recognised.");
+        }
+
+        private static Asn1OctetString CreateIVOctetString(
+            SecureRandom	random,
+            int				ivLength)
+        {
+            return new DerOctetString(CreateIV(random, ivLength));
+        }
+
+        private static byte[] CreateIV(
+            SecureRandom	random,
+            int				ivLength)
+        {
+            byte[] iv = new byte[ivLength];
+            random.NextBytes(iv);
+            return iv;
+        }
+
+        private static int FindBasicIVSize(
+            string canonicalName)
+        {
+            if (!basicIVSizes.Contains(canonicalName))
+                return -1;
+
+            return (int)basicIVSizes[canonicalName];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/PbeUtilities.cs b/BouncyCastle.AxCrypt/src/security/PbeUtilities.cs
new file mode 100644
index 0000000..56d68ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/PbeUtilities.cs
@@ -0,0 +1,663 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.BC;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <summary>
+    ///
+    /// </summary>
+    public sealed class PbeUtilities
+    {
+        private PbeUtilities()
+        {
+        }
+
+        const string Pkcs5S1 = "Pkcs5S1";
+        const string Pkcs5S2 = "Pkcs5S2";
+        const string Pkcs12 = "Pkcs12";
+        const string OpenSsl = "OpenSsl";
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary algorithmType = Platform.CreateHashtable();
+        private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static PbeUtilities()
+        {
+            algorithms["PKCS5SCHEME1"] = "Pkcs5scheme1";
+            algorithms["PKCS5SCHEME2"] = "Pkcs5scheme2";
+            algorithms[PkcsObjectIdentifiers.IdPbeS2.Id] = "Pkcs5scheme2";
+//			algorithms[PkcsObjectIdentifiers.IdPbkdf2.Id] = "Pkcs5scheme2";
+
+            // FIXME Add support for these? (see Pkcs8Generator)
+//			algorithms[PkcsObjectIdentifiers.DesEde3Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes128Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes192Cbc.Id] = "Pkcs5scheme2";
+//			algorithms[NistObjectIdentifiers.IdAes256Cbc.Id] = "Pkcs5scheme2";
+
+            algorithms["PBEWITHMD2ANDDES-CBC"] = "PBEwithMD2andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD2AndDesCbc.Id] = "PBEwithMD2andDES-CBC";
+            algorithms["PBEWITHMD2ANDRC2-CBC"] = "PBEwithMD2andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc.Id] = "PBEwithMD2andRC2-CBC";
+            algorithms["PBEWITHMD5ANDDES-CBC"] = "PBEwithMD5andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD5AndDesCbc.Id] = "PBEwithMD5andDES-CBC";
+            algorithms["PBEWITHMD5ANDRC2-CBC"] = "PBEwithMD5andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc.Id] = "PBEwithMD5andRC2-CBC";
+            algorithms["PBEWITHSHA1ANDDES"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA-1ANDDES"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA-1ANDDES-CBC"] = "PBEwithSHA-1andDES-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndDesCbc.Id] = "PBEwithSHA-1andDES-CBC";
+            algorithms["PBEWITHSHA1ANDRC2"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA-1ANDRC2"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PBEWITHSHA-1ANDRC2-CBC"] = "PBEwithSHA-1andRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc.Id] = "PBEwithSHA-1andRC2-CBC";
+            algorithms["PKCS12"] = "Pkcs12";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes128_cbc.Id] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes192_cbc.Id] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha1_pkcs12_aes256_cbc.Id] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes128_cbc.Id] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes192_cbc.Id] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms[BCObjectIdentifiers.bc_pbe_sha256_pkcs12_aes256_cbc.Id] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHA1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHA-1AND128BITRC4"] = "PBEwithSHA-1and128bitRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4.Id] = "PBEwithSHA-1and128bitRC4";
+            algorithms["PBEWITHSHAAND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHA1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHA-1AND40BITRC4"] = "PBEwithSHA-1and40bitRC4";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4.Id] = "PBEwithSHA-1and40bitRC4";
+            algorithms["PBEWITHSHAAND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND3-KEYDESEDE-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND3-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id] = "PBEwithSHA-1and3-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND2-KEYDESEDE-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHA-1AND2-KEYTRIPLEDES-CBC"] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc.Id] = "PBEwithSHA-1and2-keyDESEDE-CBC";
+            algorithms["PBEWITHSHAAND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHA1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHA-1AND128BITRC2-CBC"] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc.Id] = "PBEwithSHA-1and128bitRC2-CBC";
+            algorithms["PBEWITHSHAAND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHA1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHA-1AND40BITRC2-CBC"] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms[PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc.Id] = "PBEwithSHA-1and40bitRC2-CBC";
+            algorithms["PBEWITHSHAAND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND128BITAES-CBC-BC"] = "PBEwithSHA-1and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND192BITAES-CBC-BC"] = "PBEwithSHA-1and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHAAND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-1AND256BITAES-CBC-BC"] = "PBEwithSHA-1and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND128BITAES-CBC-BC"] = "PBEwithSHA-256and128bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND192BITAES-CBC-BC"] = "PBEwithSHA-256and192bitAES-CBC-BC";
+            algorithms["PBEWITHSHA256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHA-256AND256BITAES-CBC-BC"] = "PBEwithSHA-256and256bitAES-CBC-BC";
+            algorithms["PBEWITHSHAANDIDEA"] = "PBEwithSHA-1andIDEA-CBC";
+            algorithms["PBEWITHSHAANDIDEA-CBC"] = "PBEwithSHA-1andIDEA-CBC";
+            algorithms["PBEWITHSHAANDTWOFISH"] = "PBEwithSHA-1andTWOFISH-CBC";
+            algorithms["PBEWITHSHAANDTWOFISH-CBC"] = "PBEwithSHA-1andTWOFISH-CBC";
+            algorithms["PBEWITHHMACSHA1"] = "PBEwithHmacSHA-1";
+            algorithms["PBEWITHHMACSHA-1"] = "PBEwithHmacSHA-1";
+            algorithms[OiwObjectIdentifiers.IdSha1.Id] = "PBEwithHmacSHA-1";
+            algorithms["PBEWITHHMACSHA224"] = "PBEwithHmacSHA-224";
+            algorithms["PBEWITHHMACSHA-224"] = "PBEwithHmacSHA-224";
+            algorithms[NistObjectIdentifiers.IdSha224.Id] = "PBEwithHmacSHA-224";
+            algorithms["PBEWITHHMACSHA256"] = "PBEwithHmacSHA-256";
+            algorithms["PBEWITHHMACSHA-256"] = "PBEwithHmacSHA-256";
+            algorithms[NistObjectIdentifiers.IdSha256.Id] = "PBEwithHmacSHA-256";
+            algorithms["PBEWITHHMACRIPEMD128"] = "PBEwithHmacRipeMD128";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD128.Id] = "PBEwithHmacRipeMD128";
+            algorithms["PBEWITHHMACRIPEMD160"] = "PBEwithHmacRipeMD160";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD160.Id] = "PBEwithHmacRipeMD160";
+            algorithms["PBEWITHHMACRIPEMD256"] = "PBEwithHmacRipeMD256";
+            algorithms[TeleTrusTObjectIdentifiers.RipeMD256.Id] = "PBEwithHmacRipeMD256";
+            algorithms["PBEWITHHMACTIGER"] = "PBEwithHmacTiger";
+
+            algorithms["PBEWITHMD5AND128BITAES-CBC-OPENSSL"] = "PBEwithMD5and128bitAES-CBC-OpenSSL";
+            algorithms["PBEWITHMD5AND192BITAES-CBC-OPENSSL"] = "PBEwithMD5and192bitAES-CBC-OpenSSL";
+            algorithms["PBEWITHMD5AND256BITAES-CBC-OPENSSL"] = "PBEwithMD5and256bitAES-CBC-OpenSSL";
+
+            algorithmType["Pkcs5scheme1"] = Pkcs5S1;
+            algorithmType["Pkcs5scheme2"] = Pkcs5S2;
+            algorithmType["PBEwithMD2andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD2andRC2-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD5andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithMD5andRC2-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithSHA-1andDES-CBC"] = Pkcs5S1;
+            algorithmType["PBEwithSHA-1andRC2-CBC"] = Pkcs5S1;
+            algorithmType["Pkcs12"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitRC4"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and40bitRC4"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and3-keyDESEDE-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and2-keyDESEDE-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitRC2-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and40bitRC2-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and128bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and192bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1and256bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and128bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and192bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-256and256bitAES-CBC-BC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1andIDEA-CBC"] = Pkcs12;
+            algorithmType["PBEwithSHA-1andTWOFISH-CBC"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-1"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-224"] = Pkcs12;
+            algorithmType["PBEwithHmacSHA-256"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD128"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD160"] = Pkcs12;
+            algorithmType["PBEwithHmacRipeMD256"] = Pkcs12;
+            algorithmType["PBEwithHmacTiger"] = Pkcs12;
+
+            algorithmType["PBEwithMD5and128bitAES-CBC-OpenSSL"] = OpenSsl;
+            algorithmType["PBEwithMD5and192bitAES-CBC-OpenSSL"] = OpenSsl;
+            algorithmType["PBEwithMD5and256bitAES-CBC-OpenSSL"] = OpenSsl;
+
+            oids["PBEwithMD2andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndDesCbc;
+            oids["PBEwithMD2andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD2AndRC2Cbc;
+            oids["PBEwithMD5andDES-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndDesCbc;
+            oids["PBEwithMD5andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithMD5AndRC2Cbc;
+            oids["PBEwithSHA-1andDES-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndDesCbc;
+            oids["PBEwithSHA-1andRC2-CBC"] = PkcsObjectIdentifiers.PbeWithSha1AndRC2Cbc;
+            oids["PBEwithSHA-1and128bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC4;
+            oids["PBEwithSHA-1and40bitRC4"] = PkcsObjectIdentifiers.PbeWithShaAnd40BitRC4;
+            oids["PBEwithSHA-1and3-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc;
+            oids["PBEwithSHA-1and2-keyDESEDE-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd2KeyTripleDesCbc;
+            oids["PBEwithSHA-1and128bitRC2-CBC"] = PkcsObjectIdentifiers.PbeWithShaAnd128BitRC2Cbc;
+            oids["PBEwithSHA-1and40bitRC2-CBC"] = PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc;
+            oids["PBEwithHmacSHA-1"] = OiwObjectIdentifiers.IdSha1;
+            oids["PBEwithHmacSHA-224"] = NistObjectIdentifiers.IdSha224;
+            oids["PBEwithHmacSHA-256"] = NistObjectIdentifiers.IdSha256;
+            oids["PBEwithHmacRipeMD128"] = TeleTrusTObjectIdentifiers.RipeMD128;
+            oids["PBEwithHmacRipeMD160"] = TeleTrusTObjectIdentifiers.RipeMD160;
+            oids["PBEwithHmacRipeMD256"] = TeleTrusTObjectIdentifiers.RipeMD256;
+            oids["Pkcs5scheme2"] = PkcsObjectIdentifiers.IdPbeS2;
+        }
+
+        static PbeParametersGenerator MakePbeGenerator(
+            string	type,
+            IDigest	digest,
+            byte[]	key,
+            byte[]	salt,
+            int		iterationCount)
+        {
+            PbeParametersGenerator generator;
+
+            if (type.Equals(Pkcs5S1))
+            {
+                generator = new Pkcs5S1ParametersGenerator(digest);
+            }
+            else if (type.Equals(Pkcs5S2))
+            {
+                generator = new Pkcs5S2ParametersGenerator();
+            }
+            else if (type.Equals(Pkcs12))
+            {
+                generator = new Pkcs12ParametersGenerator(digest);
+            }
+            else if (type.Equals(OpenSsl))
+            {
+                generator = new OpenSslPbeParametersGenerator();
+            }
+            else
+            {
+                throw new ArgumentException("Unknown PBE type: " + type, "type");
+            }
+
+            generator.Init(key, salt, iterationCount);
+            return generator;
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            mechanism = (string) algorithms[Platform.ToUpperInvariant(mechanism)];
+            if (mechanism != null)
+            {
+                return (DerObjectIdentifier)oids[mechanism];
+            }
+            return null;
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static bool IsPkcs12(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs12.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPkcs5Scheme1(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs5S1.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPkcs5Scheme2(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && Pkcs5S2.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsOpenSsl(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && OpenSsl.Equals(algorithmType[mechanism]);
+        }
+
+        public static bool IsPbeAlgorithm(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            return mechanism != null && algorithmType[mechanism] != null;
+        }
+
+        public static Asn1Encodable GenerateAlgorithmParameters(
+            DerObjectIdentifier algorithmOid,
+            byte[]              salt,
+            int                 iterationCount)
+        {
+            return GenerateAlgorithmParameters(algorithmOid.Id, salt, iterationCount);
+        }
+
+        public static Asn1Encodable GenerateAlgorithmParameters(
+            string  algorithm,
+            byte[]  salt,
+            int     iterationCount)
+        {
+            if (IsPkcs12(algorithm))
+            {
+                return new Pkcs12PbeParams(salt, iterationCount);
+            }
+            else if (IsPkcs5Scheme2(algorithm))
+            {
+                return new Pbkdf2Params(salt, iterationCount);
+            }
+            else
+            {
+                return new PbeParameter(salt, iterationCount);
+            }
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            DerObjectIdentifier algorithmOid,
+            char[]              password,
+            Asn1Encodable       pbeParameters)
+        {
+            return GenerateCipherParameters(algorithmOid.Id, password, false, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            DerObjectIdentifier algorithmOid,
+            char[]              password,
+            bool				wrongPkcs12Zero,
+            Asn1Encodable       pbeParameters)
+        {
+            return GenerateCipherParameters(algorithmOid.Id, password, wrongPkcs12Zero, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            AlgorithmIdentifier algID,
+            char[]              password)
+        {
+            return GenerateCipherParameters(algID.ObjectID.Id, password, false, algID.Parameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            AlgorithmIdentifier algID,
+            char[]              password,
+            bool				wrongPkcs12Zero)
+        {
+            return GenerateCipherParameters(algID.ObjectID.Id, password, wrongPkcs12Zero, algID.Parameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            string          algorithm,
+            char[]          password,
+            Asn1Encodable   pbeParameters)
+        {
+            return GenerateCipherParameters(algorithm, password, false, pbeParameters);
+        }
+
+        public static ICipherParameters GenerateCipherParameters(
+            string          algorithm,
+            char[]          password,
+            bool			wrongPkcs12Zero,
+            Asn1Encodable   pbeParameters)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            byte[] keyBytes = null;
+            byte[] salt = null;
+            int iterationCount = 0;
+
+            if (IsPkcs12(mechanism))
+            {
+                Pkcs12PbeParams pbeParams = Pkcs12PbeParams.GetInstance(pbeParameters);
+                salt = pbeParams.GetIV();
+                iterationCount = pbeParams.Iterations.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs12PasswordToBytes(password, wrongPkcs12Zero);
+            }
+            else if (IsPkcs5Scheme2(mechanism))
+            {
+                // See below
+            }
+            else
+            {
+                PbeParameter pbeParams = PbeParameter.GetInstance(pbeParameters);
+                salt = pbeParams.GetSalt();
+                iterationCount = pbeParams.IterationCount.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password);
+            }
+
+            ICipherParameters parameters = null;
+
+            if (IsPkcs5Scheme2(mechanism))
+            {
+                PbeS2Parameters s2p = PbeS2Parameters.GetInstance(pbeParameters.ToAsn1Object());
+                AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
+                DerObjectIdentifier encOid = encScheme.ObjectID;
+                Asn1Object encParams = encScheme.Parameters.ToAsn1Object();
+
+                // TODO What about s2p.KeyDerivationFunc.ObjectID?
+                Pbkdf2Params pbeParams = Pbkdf2Params.GetInstance(s2p.KeyDerivationFunc.Parameters.ToAsn1Object());
+
+                byte[] iv;
+                if (encOid.Equals(PkcsObjectIdentifiers.RC2Cbc)) // PKCS5.B.2.3
+                {
+                    RC2CbcParameter rc2Params = RC2CbcParameter.GetInstance(encParams);
+                    iv = rc2Params.GetIV();
+                }
+                else
+                {
+                    iv = Asn1OctetString.GetInstance(encParams).GetOctets();
+                }
+
+                salt = pbeParams.GetSalt();
+                iterationCount = pbeParams.IterationCount.IntValue;
+                keyBytes = PbeParametersGenerator.Pkcs5PasswordToBytes(password);
+
+                int keyLength = pbeParams.KeyLength != null
+                    ?	pbeParams.KeyLength.IntValue * 8
+                    :	GeneratorUtilities.GetDefaultKeySize(encOid);
+
+                PbeParametersGenerator gen = MakePbeGenerator(
+                    (string)algorithmType[mechanism], null, keyBytes, salt, iterationCount);
+
+                parameters = gen.GenerateDerivedParameters(encOid.Id, keyLength);
+
+                if (iv != null)
+                {
+                    // FIXME? OpenSSL weirdness with IV of zeros (for ECB keys?)
+                    if (Arrays.AreEqual(iv, new byte[iv.Length]))
+                    {
+                        //Console.Error.Write("***** IV all 0 (length " + iv.Length + ") *****");
+                    }
+                    else
+                    {
+                        parameters = new ParametersWithIV(parameters, iv);
+                    }
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithSHA-1"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], new Sha1Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithSHA-1and128bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and192bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and256bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and128bitRC4"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC4", 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and40bitRC4"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC4", 40);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and3-keyDESEDE-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DESEDE", 192, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and2-keyDESEDE-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DESEDE", 128, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and128bitRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 128, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1and40bitRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 40, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithSHA-1andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithSHA-256"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], new Sha256Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithSHA-256and128bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-256and192bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithSHA-256and256bitAES-CBC-BC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithMD5"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string)algorithmType[mechanism], new MD5Digest(), keyBytes, salt, iterationCount);
+
+                if (mechanism.Equals("PBEwithMD5andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD5andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD5and128bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 128, 128);
+                }
+                else if (mechanism.Equals("PBEwithMD5and192bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 192, 128);
+                }
+                else if (mechanism.Equals("PBEwithMD5and256bitAES-CBC-OpenSSL"))
+                {
+                    parameters = generator.GenerateDerivedParameters("AES", 256, 128);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithMD2"))
+            {
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string)algorithmType[mechanism], new MD2Digest(), keyBytes, salt, iterationCount);
+                if (mechanism.Equals("PBEwithMD2andDES-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("DES", 64, 64);
+                }
+                else if (mechanism.Equals("PBEwithMD2andRC2-CBC"))
+                {
+                    parameters = generator.GenerateDerivedParameters("RC2", 64, 64);
+                }
+            }
+            else if (mechanism.StartsWith("PBEwithHmac"))
+            {
+                string digestName = mechanism.Substring("PBEwithHmac".Length);
+                IDigest digest = DigestUtilities.GetDigest(digestName);
+
+                PbeParametersGenerator generator = MakePbeGenerator(
+                    (string) algorithmType[mechanism], digest, keyBytes, salt, iterationCount);
+
+                int bitLen = digest.GetDigestSize() * 8;
+                parameters = generator.GenerateDerivedMacParameters(bitLen);
+            }
+
+            Array.Clear(keyBytes, 0, keyBytes.Length);
+
+            return FixDesParity(mechanism, parameters);
+        }
+
+        public static object CreateEngine(
+            DerObjectIdentifier algorithmOid)
+        {
+            return CreateEngine(algorithmOid.Id);
+        }
+
+        public static object CreateEngine(
+            AlgorithmIdentifier algID)
+        {
+            string algorithm = algID.ObjectID.Id;
+
+            if (IsPkcs5Scheme2(algorithm))
+            {
+                PbeS2Parameters s2p = PbeS2Parameters.GetInstance(algID.Parameters.ToAsn1Object());
+                AlgorithmIdentifier encScheme = s2p.EncryptionScheme;
+                return CipherUtilities.GetCipher(encScheme.ObjectID);
+            }
+
+            return CreateEngine(algorithm);
+        }
+
+        public static object CreateEngine(
+            string algorithm)
+        {
+            string mechanism = (string)algorithms[Platform.ToUpperInvariant(algorithm)];
+
+            if (mechanism.StartsWith("PBEwithHmac"))
+            {
+                string digestName = mechanism.Substring("PBEwithHmac".Length);
+
+                return MacUtilities.GetMac("HMAC/" + digestName);
+            }
+
+            if (mechanism.StartsWith("PBEwithMD2")
+                ||	mechanism.StartsWith("PBEwithMD5")
+                ||	mechanism.StartsWith("PBEwithSHA-1")
+                ||	mechanism.StartsWith("PBEwithSHA-256"))
+            {
+                if (mechanism.EndsWith("AES-CBC-BC") || mechanism.EndsWith("AES-CBC-OPENSSL"))
+                {
+                    return CipherUtilities.GetCipher("AES/CBC");
+                }
+
+                if (mechanism.EndsWith("DES-CBC"))
+                {
+                    return CipherUtilities.GetCipher("DES/CBC");
+                }
+
+                if (mechanism.EndsWith("DESEDE-CBC"))
+                {
+                    return CipherUtilities.GetCipher("DESEDE/CBC");
+                }
+
+                if (mechanism.EndsWith("RC2-CBC"))
+                {
+                    return CipherUtilities.GetCipher("RC2/CBC");
+                }
+
+                if (mechanism.EndsWith("RC4"))
+                {
+                    return CipherUtilities.GetCipher("RC4");
+                }
+            }
+
+            return null;
+        }
+
+        public static string GetEncodingName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private static ICipherParameters FixDesParity(string mechanism, ICipherParameters parameters)
+        {
+            if (!mechanism.EndsWith("DES-CBC") & !mechanism.EndsWith("DESEDE-CBC"))
+            {
+                return parameters;
+            }
+
+            if (parameters is ParametersWithIV)
+            {
+                ParametersWithIV ivParams = (ParametersWithIV)parameters;
+                return new ParametersWithIV(FixDesParity(mechanism, ivParams.Parameters), ivParams.GetIV());
+            }
+
+            KeyParameter kParam = (KeyParameter)parameters;
+            byte[] keyBytes = kParam.GetKey();
+            DesParameters.SetOddParity(keyBytes);
+            return new KeyParameter(keyBytes);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/PrivateKeyFactory.cs b/BouncyCastle.AxCrypt/src/security/PrivateKeyFactory.cs
new file mode 100644
index 0000000..1cfa37a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/PrivateKeyFactory.cs
@@ -0,0 +1,224 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class PrivateKeyFactory
+    {
+        private PrivateKeyFactory()
+        {
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            byte[] privateKeyInfoData)
+        {
+            return CreateKey(
+                PrivateKeyInfo.GetInstance(
+                    Asn1Object.FromByteArray(privateKeyInfoData)));
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            Stream inStr)
+        {
+            return CreateKey(
+                PrivateKeyInfo.GetInstance(
+                    Asn1Object.FromStream(inStr)));
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            PrivateKeyInfo keyInfo)
+        {
+            AlgorithmIdentifier algID = keyInfo.PrivateKeyAlgorithm;
+            DerObjectIdentifier algOid = algID.ObjectID;
+
+            // TODO See RSAUtil.isRsaOid in Java build
+            if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
+                || algOid.Equals(X509ObjectIdentifiers.IdEARsa)
+                || algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss)
+                || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
+            {
+                RsaPrivateKeyStructure keyStructure = new RsaPrivateKeyStructure(
+                    Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey()));
+
+                return new RsaPrivateCrtKeyParameters(
+                    keyStructure.Modulus,
+                    keyStructure.PublicExponent,
+                    keyStructure.PrivateExponent,
+                    keyStructure.Prime1,
+                    keyStructure.Prime2,
+                    keyStructure.Exponent1,
+                    keyStructure.Exponent2,
+                    keyStructure.Coefficient);
+            }
+            // TODO?
+//			else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
+            else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
+            {
+                DHParameter para = new DHParameter(
+                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+                DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey();
+
+                BigInteger lVal = para.L;
+                int l = lVal == null ? 0 : lVal.IntValue;
+                DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
+
+                return new DHPrivateKeyParameters(derX.Value, dhParams, algOid);
+            }
+            else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
+            {
+                ElGamalParameter  para = new ElGamalParameter(
+                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+                DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey();
+
+                return new ElGamalPrivateKeyParameters(
+                    derX.Value,
+                    new ElGamalParameters(para.P, para.G));
+            }
+            else if (algOid.Equals(X9ObjectIdentifiers.IdDsa))
+            {
+                DerInteger derX = (DerInteger)keyInfo.ParsePrivateKey();
+                Asn1Encodable ae = algID.Parameters;
+
+                DsaParameters parameters = null;
+                if (ae != null)
+                {
+                    DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
+                    parameters = new DsaParameters(para.P, para.Q, para.G);
+                }
+
+                return new DsaPrivateKeyParameters(derX.Value, parameters);
+            }
+            else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+            {
+                X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+
+                X9ECParameters x9;
+                if (para.IsNamedCurve)
+                {
+                    x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters);
+                }
+                else
+                {
+                    x9 = new X9ECParameters((Asn1Sequence)para.Parameters);
+                }
+
+                ECPrivateKeyStructure ec = new ECPrivateKeyStructure(
+                    Asn1Sequence.GetInstance(keyInfo.ParsePrivateKey()));
+                BigInteger d = ec.GetKey();
+
+                if (para.IsNamedCurve)
+                {
+                    return new ECPrivateKeyParameters("EC", d, (DerObjectIdentifier)para.Parameters);
+                }
+
+                ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H,  x9.GetSeed());
+                return new ECPrivateKeyParameters(d, dParams);
+            }
+            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+            {
+                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+                Asn1Object privKey = keyInfo.ParsePrivateKey();
+                ECPrivateKeyStructure ec;
+
+                if (privKey is DerInteger)
+                {
+                    // TODO Do we need to pass any parameters here?
+                    ec = new ECPrivateKeyStructure(((DerInteger)privKey).Value);
+                }
+                else
+                {
+                    ec = ECPrivateKeyStructure.GetInstance(privKey);
+                }
+
+                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+                if (ecP == null)
+                    throw new ArgumentException("Unrecognized curve OID for GostR3410x2001 private key");
+
+                return new ECPrivateKeyParameters("ECGOST3410", ec.GetKey(), gostParams.PublicKeyParamSet);
+            }
+            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
+            {
+                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+
+                DerOctetString derX = (DerOctetString)keyInfo.ParsePrivateKey();
+                BigInteger x = new BigInteger(1, Arrays.Reverse(derX.GetOctets()));
+
+                return new Gost3410PrivateKeyParameters(x, gostParams.PublicKeyParamSet);
+            }
+            else
+            {
+                throw new SecurityUtilityException("algorithm identifier in key not recognised");
+            }
+        }
+
+        public static AsymmetricKeyParameter DecryptKey(
+            char[]					passPhrase,
+            EncryptedPrivateKeyInfo	encInfo)
+        {
+            return CreateKey(PrivateKeyInfoFactory.CreatePrivateKeyInfo(passPhrase, encInfo));
+        }
+
+        public static AsymmetricKeyParameter DecryptKey(
+            char[]	passPhrase,
+            byte[]	encryptedPrivateKeyInfoData)
+        {
+            return DecryptKey(passPhrase, Asn1Object.FromByteArray(encryptedPrivateKeyInfoData));
+        }
+
+        public static AsymmetricKeyParameter DecryptKey(
+            char[]	passPhrase,
+            Stream	encryptedPrivateKeyInfoStream)
+        {
+            return DecryptKey(passPhrase, Asn1Object.FromStream(encryptedPrivateKeyInfoStream));
+        }
+
+        private static AsymmetricKeyParameter DecryptKey(
+            char[]		passPhrase,
+            Asn1Object	asn1Object)
+        {
+            return DecryptKey(passPhrase, EncryptedPrivateKeyInfo.GetInstance(asn1Object));
+        }
+
+        public static byte[] EncryptKey(
+            DerObjectIdentifier		algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+            return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+                algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
+        }
+
+        public static byte[] EncryptKey(
+            string					algorithm,
+            char[]					passPhrase,
+            byte[]					salt,
+            int						iterationCount,
+            AsymmetricKeyParameter	key)
+        {
+            return EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+                algorithm, passPhrase, salt, iterationCount, key).GetEncoded();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/PublicKeyFactory.cs b/BouncyCastle.AxCrypt/src/security/PublicKeyFactory.cs
new file mode 100644
index 0000000..8c0be4f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/PublicKeyFactory.cs
@@ -0,0 +1,253 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+
+namespace Org.BouncyCastle.Security
+{
+    public sealed class PublicKeyFactory
+    {
+        private PublicKeyFactory()
+        {
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            byte[] keyInfoData)
+        {
+            return CreateKey(
+                SubjectPublicKeyInfo.GetInstance(
+                    Asn1Object.FromByteArray(keyInfoData)));
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            Stream inStr)
+        {
+            return CreateKey(
+                SubjectPublicKeyInfo.GetInstance(
+                    Asn1Object.FromStream(inStr)));
+        }
+
+        public static AsymmetricKeyParameter CreateKey(
+            SubjectPublicKeyInfo keyInfo)
+        {
+            AlgorithmIdentifier algID = keyInfo.AlgorithmID;
+            DerObjectIdentifier algOid = algID.ObjectID;
+
+            // TODO See RSAUtil.isRsaOid in Java build
+            if (algOid.Equals(PkcsObjectIdentifiers.RsaEncryption)
+                || algOid.Equals(X509ObjectIdentifiers.IdEARsa)
+                || algOid.Equals(PkcsObjectIdentifiers.IdRsassaPss)
+                || algOid.Equals(PkcsObjectIdentifiers.IdRsaesOaep))
+            {
+                RsaPublicKeyStructure pubKey = RsaPublicKeyStructure.GetInstance(
+                    keyInfo.GetPublicKey());
+
+                return new RsaKeyParameters(false, pubKey.Modulus, pubKey.PublicExponent);
+            }
+            else if (algOid.Equals(X9ObjectIdentifiers.DHPublicNumber))
+            {
+                Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
+
+                DHPublicKey dhPublicKey = DHPublicKey.GetInstance(keyInfo.GetPublicKey());
+
+                BigInteger y = dhPublicKey.Y.Value;
+
+                if (IsPkcsDHParam(seq))
+                    return ReadPkcsDHParam(algOid, y, seq);
+
+                DHDomainParameters dhParams = DHDomainParameters.GetInstance(seq);
+
+                BigInteger p = dhParams.P.Value;
+                BigInteger g = dhParams.G.Value;
+                BigInteger q = dhParams.Q.Value;
+
+                BigInteger j = null;
+                if (dhParams.J != null)
+                {
+                    j = dhParams.J.Value;
+                }
+
+                DHValidationParameters validation = null;
+                DHValidationParms dhValidationParms = dhParams.ValidationParms;
+                if (dhValidationParms != null)
+                {
+                    byte[] seed = dhValidationParms.Seed.GetBytes();
+                    BigInteger pgenCounter = dhValidationParms.PgenCounter.Value;
+
+                    // TODO Check pgenCounter size?
+
+                    validation = new DHValidationParameters(seed, pgenCounter.IntValue);
+                }
+
+                return new DHPublicKeyParameters(y, new DHParameters(p, g, q, j, validation));
+            }
+            else if (algOid.Equals(PkcsObjectIdentifiers.DhKeyAgreement))
+            {
+                Asn1Sequence seq = Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object());
+
+                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+
+                return ReadPkcsDHParam(algOid, derY.Value, seq);
+            }
+            else if (algOid.Equals(OiwObjectIdentifiers.ElGamalAlgorithm))
+            {
+                ElGamalParameter para = new ElGamalParameter(
+                    Asn1Sequence.GetInstance(algID.Parameters.ToAsn1Object()));
+                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+
+                return new ElGamalPublicKeyParameters(
+                    derY.Value,
+                    new ElGamalParameters(para.P, para.G));
+            }
+            else if (algOid.Equals(X9ObjectIdentifiers.IdDsa)
+                || algOid.Equals(OiwObjectIdentifiers.DsaWithSha1))
+            {
+                DerInteger derY = (DerInteger) keyInfo.GetPublicKey();
+                Asn1Encodable ae = algID.Parameters;
+
+                DsaParameters parameters = null;
+                if (ae != null)
+                {
+                    DsaParameter para = DsaParameter.GetInstance(ae.ToAsn1Object());
+                    parameters = new DsaParameters(para.P, para.Q, para.G);
+                }
+
+                return new DsaPublicKeyParameters(derY.Value, parameters);
+            }
+            else if (algOid.Equals(X9ObjectIdentifiers.IdECPublicKey))
+            {
+                X962Parameters para = new X962Parameters(algID.Parameters.ToAsn1Object());
+
+                X9ECParameters x9;
+                if (para.IsNamedCurve)
+                {
+                    x9 = ECKeyPairGenerator.FindECCurveByOid((DerObjectIdentifier)para.Parameters);
+                }
+                else
+                {
+                    x9 = new X9ECParameters((Asn1Sequence)para.Parameters);
+                }
+
+                Asn1OctetString key = new DerOctetString(keyInfo.PublicKeyData.GetBytes());
+                X9ECPoint derQ = new X9ECPoint(x9.Curve, key);
+                ECPoint q = derQ.Point;
+
+                if (para.IsNamedCurve)
+                {
+                    return new ECPublicKeyParameters("EC", q, (DerObjectIdentifier)para.Parameters);
+                }
+
+                ECDomainParameters dParams = new ECDomainParameters(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+                return new ECPublicKeyParameters(q, dParams);
+            }
+            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x2001))
+            {
+                Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+                    (Asn1Sequence) algID.Parameters);
+
+                Asn1OctetString key;
+                try
+                {
+                    key = (Asn1OctetString) keyInfo.GetPublicKey();
+                }
+                catch (IOException)
+                {
+                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                }
+
+                byte[] keyEnc = key.GetOctets();
+                byte[] x = new byte[32];
+                byte[] y = new byte[32];
+
+                for (int i = 0; i != y.Length; i++)
+                {
+                    x[i] = keyEnc[32 - 1 - i];
+                }
+
+                for (int i = 0; i != x.Length; i++)
+                {
+                    y[i] = keyEnc[64 - 1 - i];
+                }
+
+                ECDomainParameters ecP = ECGost3410NamedCurves.GetByOid(gostParams.PublicKeyParamSet);
+
+                if (ecP == null)
+                    return null;
+
+                ECPoint q = ecP.Curve.CreatePoint(new BigInteger(1, x), new BigInteger(1, y));
+
+                return new ECPublicKeyParameters("ECGOST3410", q, gostParams.PublicKeyParamSet);
+            }
+            else if (algOid.Equals(CryptoProObjectIdentifiers.GostR3410x94))
+            {
+                Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
+                    (Asn1Sequence) algID.Parameters);
+
+                DerOctetString derY;
+                try
+                {
+                    derY = (DerOctetString) keyInfo.GetPublicKey();
+                }
+                catch (IOException)
+                {
+                    throw new ArgumentException("invalid info structure in GOST3410 public key");
+                }
+
+                byte[] keyEnc = derY.GetOctets();
+                byte[] keyBytes = new byte[keyEnc.Length];
+
+                for (int i = 0; i != keyEnc.Length; i++)
+                {
+                    keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // was little endian
+                }
+
+                BigInteger y = new BigInteger(1, keyBytes);
+
+                return new Gost3410PublicKeyParameters(y, algParams.PublicKeyParamSet);
+            }
+            else
+            {
+                throw new SecurityUtilityException("algorithm identifier in key not recognised: " + algOid);
+            }
+        }
+
+        private static bool IsPkcsDHParam(Asn1Sequence seq)
+        {
+            if (seq.Count == 2)
+                return true;
+
+            if (seq.Count > 3)
+                return false;
+
+            DerInteger l = DerInteger.GetInstance(seq[2]);
+            DerInteger p = DerInteger.GetInstance(seq[0]);
+
+            return l.Value.CompareTo(BigInteger.ValueOf(p.Value.BitLength)) <= 0;
+        }
+
+        private static DHPublicKeyParameters ReadPkcsDHParam(DerObjectIdentifier algOid,
+            BigInteger y, Asn1Sequence seq)
+        {
+            DHParameter para = new DHParameter(seq);
+
+            BigInteger lVal = para.L;
+            int l = lVal == null ? 0 : lVal.IntValue;
+            DHParameters dhParams = new DHParameters(para.P, para.G, null, l);
+
+            return new DHPublicKeyParameters(y, dhParams, algOid);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/SecureRandom.cs b/BouncyCastle.AxCrypt/src/security/SecureRandom.cs
new file mode 100644
index 0000000..ac9d981
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/SecureRandom.cs
@@ -0,0 +1,228 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    public class SecureRandom
+		: Random
+    {
+		// Note: all objects of this class should be deriving their random data from
+		// a single generator appropriate to the digest being used.
+		private static readonly IRandomGenerator sha1Generator = new DigestRandomGenerator(new Sha1Digest());
+		private static readonly IRandomGenerator sha256Generator = new DigestRandomGenerator(new Sha256Digest());
+
+		private static readonly SecureRandom[] master = { null };
+		private static SecureRandom Master
+		{
+			get
+			{
+				if (master[0] == null)
+				{
+					IRandomGenerator gen = sha256Generator;
+					gen = new ReversedWindowGenerator(gen, 32);
+					SecureRandom sr = master[0] = new SecureRandom(gen);
+
+					sr.SetSeed(DateTime.Now.Ticks);
+					sr.SetSeed(new ThreadedSeedGenerator().GenerateSeed(24, true));
+					sr.GenerateSeed(1 + sr.Next(32));
+				}
+
+				return master[0];
+			}
+		}
+
+		public static SecureRandom GetInstance(
+			string algorithm)
+		{
+			// TODO Compared to JDK, we don't auto-seed if the client forgets - problem?
+
+			// TODO Support all digests more generally, by stripping PRNG and calling DigestUtilities?
+			string drgName = Platform.ToUpperInvariant(algorithm);
+
+			IRandomGenerator drg = null;
+			if (drgName == "SHA1PRNG")
+			{
+				drg = sha1Generator;
+			}
+			else if (drgName == "SHA256PRNG")
+			{
+				drg = sha256Generator;
+			}
+
+			if (drg != null)
+			{
+				return new SecureRandom(drg);
+			}
+
+			throw new ArgumentException("Unrecognised PRNG algorithm: " + algorithm, "algorithm");
+		}
+
+		public static byte[] GetSeed(
+			int length)
+		{
+			return Master.GenerateSeed(length);
+		}
+
+		protected IRandomGenerator generator;
+
+		public SecureRandom()
+			: this(sha1Generator)
+        {
+			SetSeed(GetSeed(8));
+		}
+
+		public SecureRandom(
+			byte[] inSeed)
+			: this(sha1Generator)
+        {
+			SetSeed(inSeed);
+        }
+
+		/// <summary>Use the specified instance of IRandomGenerator as random source.</summary>
+		/// <remarks>
+		/// This constructor performs no seeding of either the <c>IRandomGenerator</c> or the
+		/// constructed <c>SecureRandom</c>. It is the responsibility of the client to provide
+		/// proper seed material as necessary/appropriate for the given <c>IRandomGenerator</c>
+		/// implementation.
+		/// </remarks>
+		/// <param name="generator">The source to generate all random bytes from.</param>
+		public SecureRandom(
+			IRandomGenerator generator)
+			: base(0)
+		{
+			this.generator = generator;
+		}
+
+		public virtual byte[] GenerateSeed(
+			int length)
+		{
+			SetSeed(DateTime.Now.Ticks);
+
+			byte[] rv = new byte[length];
+			NextBytes(rv);
+			return rv;
+		}
+
+		public virtual void SetSeed(
+			byte[] inSeed)
+        {
+			generator.AddSeedMaterial(inSeed);
+        }
+
+        public virtual void SetSeed(
+			long seed)
+        {
+			generator.AddSeedMaterial(seed);
+		}
+
+		public override int Next()
+		{
+			for (;;)
+			{
+				int i = NextInt() & int.MaxValue;
+
+				if (i != int.MaxValue)
+					return i;
+			}
+		}
+
+		public override int Next(
+			int maxValue)
+		{
+			if (maxValue < 2)
+			{
+				if (maxValue < 0)
+					throw new ArgumentOutOfRangeException("maxValue", "cannot be negative");
+
+				return 0;
+			}
+
+			// Test whether maxValue is a power of 2
+			if ((maxValue & -maxValue) == maxValue)
+			{
+				int val = NextInt() & int.MaxValue;
+				long lr = ((long) maxValue * (long) val) >> 31;
+				return (int) lr;
+			}
+
+			int bits, result;
+			do
+			{
+				bits = NextInt() & int.MaxValue;
+				result = bits % maxValue;
+			}
+			while (bits - result + (maxValue - 1) < 0); // Ignore results near overflow
+
+			return result;
+		}
+
+		public override int Next(
+			int	minValue,
+			int	maxValue)
+		{
+			if (maxValue <= minValue)
+			{
+				if (maxValue == minValue)
+					return minValue;
+
+				throw new ArgumentException("maxValue cannot be less than minValue");
+			}
+
+			int diff = maxValue - minValue;
+			if (diff > 0)
+				return minValue + Next(diff);
+
+			for (;;)
+			{
+				int i = NextInt();
+
+				if (i >= minValue && i < maxValue)
+					return i;
+			}
+		}
+
+		public override void NextBytes(
+			byte[] buffer)
+        {
+			generator.NextBytes(buffer);
+        }
+
+		public virtual void NextBytes(
+			byte[]	buffer,
+			int		start,
+			int		length)
+		{
+			generator.NextBytes(buffer, start, length);
+		}
+
+		private static readonly double DoubleScale = System.Math.Pow(2.0, 64.0);
+
+		public override double NextDouble()
+		{
+			return Convert.ToDouble((ulong) NextLong()) / DoubleScale;
+		}
+
+		public virtual int NextInt()
+        {
+			byte[] intBytes = new byte[4];
+            NextBytes(intBytes);
+
+			int result = 0;
+            for (int i = 0; i < 4; i++)
+            {
+                result = (result << 8) + (intBytes[i] & 0xff);
+            }
+
+			return result;
+        }
+
+		public virtual long NextLong()
+		{
+			return ((long)(uint) NextInt() << 32) | (long)(uint) NextInt();
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/SecurityUtilityException.cs b/BouncyCastle.AxCrypt/src/security/SecurityUtilityException.cs
new file mode 100644
index 0000000..02a3e80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/SecurityUtilityException.cs
@@ -0,0 +1,36 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class SecurityUtilityException
+		: Exception
+    {
+        /**
+        * base constructor.
+        */
+        public SecurityUtilityException()
+        {
+        }
+
+		/**
+         * create a SecurityUtilityException with the given message.
+         *
+         * @param message the message to be carried with the exception.
+         */
+        public SecurityUtilityException(
+            string message)
+			: base(message)
+        {
+        }
+
+		public SecurityUtilityException(
+            string		message,
+            Exception	exception)
+			: base(message, exception)
+        {
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/SignatureException.cs b/BouncyCastle.AxCrypt/src/security/SignatureException.cs
new file mode 100644
index 0000000..cea3c59
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/SignatureException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class SignatureException : GeneralSecurityException
+	{
+		public SignatureException() : base() { }
+		public SignatureException(string message) : base(message) { }
+		public SignatureException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/SignerUtilities.cs b/BouncyCastle.AxCrypt/src/security/SignerUtilities.cs
new file mode 100644
index 0000000..0cf113f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/SignerUtilities.cs
@@ -0,0 +1,546 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <summary>
+    ///  Signer Utility class contains methods that can not be specifically grouped into other classes.
+    /// </summary>
+    public sealed class SignerUtilities
+    {
+        private SignerUtilities()
+        {
+        }
+
+        internal static readonly IDictionary algorithms = Platform.CreateHashtable();
+        internal static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static SignerUtilities()
+        {
+            algorithms["MD2WITHRSA"] = "MD2withRSA";
+            algorithms["MD2WITHRSAENCRYPTION"] = "MD2withRSA";
+            algorithms[PkcsObjectIdentifiers.MD2WithRsaEncryption.Id] = "MD2withRSA";
+
+            algorithms["MD4WITHRSA"] = "MD4withRSA";
+            algorithms["MD4WITHRSAENCRYPTION"] = "MD4withRSA";
+            algorithms[PkcsObjectIdentifiers.MD4WithRsaEncryption.Id] = "MD4withRSA";
+
+            algorithms["MD5WITHRSA"] = "MD5withRSA";
+            algorithms["MD5WITHRSAENCRYPTION"] = "MD5withRSA";
+            algorithms[PkcsObjectIdentifiers.MD5WithRsaEncryption.Id] = "MD5withRSA";
+
+            algorithms["SHA1WITHRSA"] = "SHA-1withRSA";
+            algorithms["SHA1WITHRSAENCRYPTION"] = "SHA-1withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id] = "SHA-1withRSA";
+            algorithms["SHA-1WITHRSA"] = "SHA-1withRSA";
+
+            algorithms["SHA224WITHRSA"] = "SHA-224withRSA";
+            algorithms["SHA224WITHRSAENCRYPTION"] = "SHA-224withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id] = "SHA-224withRSA";
+            algorithms["SHA-224WITHRSA"] = "SHA-224withRSA";
+
+            algorithms["SHA256WITHRSA"] = "SHA-256withRSA";
+            algorithms["SHA256WITHRSAENCRYPTION"] = "SHA-256withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id] = "SHA-256withRSA";
+            algorithms["SHA-256WITHRSA"] = "SHA-256withRSA";
+
+            algorithms["SHA384WITHRSA"] = "SHA-384withRSA";
+            algorithms["SHA384WITHRSAENCRYPTION"] = "SHA-384withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id] = "SHA-384withRSA";
+            algorithms["SHA-384WITHRSA"] = "SHA-384withRSA";
+
+            algorithms["SHA512WITHRSA"] = "SHA-512withRSA";
+            algorithms["SHA512WITHRSAENCRYPTION"] = "SHA-512withRSA";
+            algorithms[PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id] = "SHA-512withRSA";
+            algorithms["SHA-512WITHRSA"] = "SHA-512withRSA";
+
+            algorithms["PSSWITHRSA"] = "PSSwithRSA";
+            algorithms["RSASSA-PSS"] = "PSSwithRSA";
+            algorithms[PkcsObjectIdentifiers.IdRsassaPss.Id] = "PSSwithRSA";
+            algorithms["RSAPSS"] = "PSSwithRSA";
+
+            algorithms["SHA1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1";
+            algorithms["SHA-1WITHRSAANDMGF1"] = "SHA-1withRSAandMGF1";
+            algorithms["SHA1WITHRSA/PSS"] = "SHA-1withRSAandMGF1";
+            algorithms["SHA-1WITHRSA/PSS"] = "SHA-1withRSAandMGF1";
+
+            algorithms["SHA224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1";
+            algorithms["SHA-224WITHRSAANDMGF1"] = "SHA-224withRSAandMGF1";
+            algorithms["SHA224WITHRSA/PSS"] = "SHA-224withRSAandMGF1";
+            algorithms["SHA-224WITHRSA/PSS"] = "SHA-224withRSAandMGF1";
+
+            algorithms["SHA256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1";
+            algorithms["SHA-256WITHRSAANDMGF1"] = "SHA-256withRSAandMGF1";
+            algorithms["SHA256WITHRSA/PSS"] = "SHA-256withRSAandMGF1";
+            algorithms["SHA-256WITHRSA/PSS"] = "SHA-256withRSAandMGF1";
+
+            algorithms["SHA384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1";
+            algorithms["SHA-384WITHRSAANDMGF1"] = "SHA-384withRSAandMGF1";
+            algorithms["SHA384WITHRSA/PSS"] = "SHA-384withRSAandMGF1";
+            algorithms["SHA-384WITHRSA/PSS"] = "SHA-384withRSAandMGF1";
+
+            algorithms["SHA512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1";
+            algorithms["SHA-512WITHRSAANDMGF1"] = "SHA-512withRSAandMGF1";
+            algorithms["SHA512WITHRSA/PSS"] = "SHA-512withRSAandMGF1";
+            algorithms["SHA-512WITHRSA/PSS"] = "SHA-512withRSAandMGF1";
+
+            algorithms["RIPEMD128WITHRSA"] = "RIPEMD128withRSA";
+            algorithms["RIPEMD128WITHRSAENCRYPTION"] = "RIPEMD128withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128.Id] = "RIPEMD128withRSA";
+
+            algorithms["RIPEMD160WITHRSA"] = "RIPEMD160withRSA";
+            algorithms["RIPEMD160WITHRSAENCRYPTION"] = "RIPEMD160withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160.Id] = "RIPEMD160withRSA";
+
+            algorithms["RIPEMD256WITHRSA"] = "RIPEMD256withRSA";
+            algorithms["RIPEMD256WITHRSAENCRYPTION"] = "RIPEMD256withRSA";
+            algorithms[TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256.Id] = "RIPEMD256withRSA";
+
+            algorithms["NONEWITHRSA"] = "RSA";
+            algorithms["RSAWITHNONE"] = "RSA";
+            algorithms["RAWRSA"] = "RSA";
+
+            algorithms["RAWRSAPSS"] = "RAWRSASSA-PSS";
+            algorithms["NONEWITHRSAPSS"] = "RAWRSASSA-PSS";
+            algorithms["NONEWITHRSASSA-PSS"] = "RAWRSASSA-PSS";
+
+            algorithms["NONEWITHDSA"] = "NONEwithDSA";
+            algorithms["DSAWITHNONE"] = "NONEwithDSA";
+            algorithms["RAWDSA"] = "NONEwithDSA";
+
+            algorithms["DSA"] = "SHA-1withDSA";
+            algorithms["DSAWITHSHA1"] = "SHA-1withDSA";
+            algorithms["DSAWITHSHA-1"] = "SHA-1withDSA";
+            algorithms["SHA/DSA"] = "SHA-1withDSA";
+            algorithms["SHA1/DSA"] = "SHA-1withDSA";
+            algorithms["SHA-1/DSA"] = "SHA-1withDSA";
+            algorithms["SHA1WITHDSA"] = "SHA-1withDSA";
+            algorithms["SHA-1WITHDSA"] = "SHA-1withDSA";
+            algorithms[X9ObjectIdentifiers.IdDsaWithSha1.Id] = "SHA-1withDSA";
+
+            algorithms["DSAWITHSHA224"] = "SHA-224withDSA";
+            algorithms["DSAWITHSHA-224"] = "SHA-224withDSA";
+            algorithms["SHA224/DSA"] = "SHA-224withDSA";
+            algorithms["SHA-224/DSA"] = "SHA-224withDSA";
+            algorithms["SHA224WITHDSA"] = "SHA-224withDSA";
+            algorithms["SHA-224WITHDSA"] = "SHA-224withDSA";
+            algorithms[NistObjectIdentifiers.DsaWithSha224.Id] = "SHA-224withDSA";
+
+            algorithms["DSAWITHSHA256"] = "SHA-256withDSA";
+            algorithms["DSAWITHSHA-256"] = "SHA-256withDSA";
+            algorithms["SHA256/DSA"] = "SHA-256withDSA";
+            algorithms["SHA-256/DSA"] = "SHA-256withDSA";
+            algorithms["SHA256WITHDSA"] = "SHA-256withDSA";
+            algorithms["SHA-256WITHDSA"] = "SHA-256withDSA";
+            algorithms[NistObjectIdentifiers.DsaWithSha256.Id] = "SHA-256withDSA";
+
+            algorithms["DSAWITHSHA384"] = "SHA-384withDSA";
+            algorithms["DSAWITHSHA-384"] = "SHA-384withDSA";
+            algorithms["SHA384/DSA"] = "SHA-384withDSA";
+            algorithms["SHA-384/DSA"] = "SHA-384withDSA";
+            algorithms["SHA384WITHDSA"] = "SHA-384withDSA";
+            algorithms["SHA-384WITHDSA"] = "SHA-384withDSA";
+            algorithms[NistObjectIdentifiers.DsaWithSha384.Id] = "SHA-384withDSA";
+
+            algorithms["DSAWITHSHA512"] = "SHA-512withDSA";
+            algorithms["DSAWITHSHA-512"] = "SHA-512withDSA";
+            algorithms["SHA512/DSA"] = "SHA-512withDSA";
+            algorithms["SHA-512/DSA"] = "SHA-512withDSA";
+            algorithms["SHA512WITHDSA"] = "SHA-512withDSA";
+            algorithms["SHA-512WITHDSA"] = "SHA-512withDSA";
+            algorithms[NistObjectIdentifiers.DsaWithSha512.Id] = "SHA-512withDSA";
+
+            algorithms["NONEWITHECDSA"] = "NONEwithECDSA";
+            algorithms["ECDSAWITHNONE"] = "NONEwithECDSA";
+
+            algorithms["ECDSA"] = "SHA-1withECDSA";
+            algorithms["SHA1/ECDSA"] = "SHA-1withECDSA";
+            algorithms["SHA-1/ECDSA"] = "SHA-1withECDSA";
+            algorithms["ECDSAWITHSHA1"] = "SHA-1withECDSA";
+            algorithms["ECDSAWITHSHA-1"] = "SHA-1withECDSA";
+            algorithms["SHA1WITHECDSA"] = "SHA-1withECDSA";
+            algorithms["SHA-1WITHECDSA"] = "SHA-1withECDSA";
+            algorithms[X9ObjectIdentifiers.ECDsaWithSha1.Id] = "SHA-1withECDSA";
+            algorithms[TeleTrusTObjectIdentifiers.ECSignWithSha1.Id] = "SHA-1withECDSA";
+
+            algorithms["SHA224/ECDSA"] = "SHA-224withECDSA";
+            algorithms["SHA-224/ECDSA"] = "SHA-224withECDSA";
+            algorithms["ECDSAWITHSHA224"] = "SHA-224withECDSA";
+            algorithms["ECDSAWITHSHA-224"] = "SHA-224withECDSA";
+            algorithms["SHA224WITHECDSA"] = "SHA-224withECDSA";
+            algorithms["SHA-224WITHECDSA"] = "SHA-224withECDSA";
+            algorithms[X9ObjectIdentifiers.ECDsaWithSha224.Id] = "SHA-224withECDSA";
+
+            algorithms["SHA256/ECDSA"] = "SHA-256withECDSA";
+            algorithms["SHA-256/ECDSA"] = "SHA-256withECDSA";
+            algorithms["ECDSAWITHSHA256"] = "SHA-256withECDSA";
+            algorithms["ECDSAWITHSHA-256"] = "SHA-256withECDSA";
+            algorithms["SHA256WITHECDSA"] = "SHA-256withECDSA";
+            algorithms["SHA-256WITHECDSA"] = "SHA-256withECDSA";
+            algorithms[X9ObjectIdentifiers.ECDsaWithSha256.Id] = "SHA-256withECDSA";
+
+            algorithms["SHA384/ECDSA"] = "SHA-384withECDSA";
+            algorithms["SHA-384/ECDSA"] = "SHA-384withECDSA";
+            algorithms["ECDSAWITHSHA384"] = "SHA-384withECDSA";
+            algorithms["ECDSAWITHSHA-384"] = "SHA-384withECDSA";
+            algorithms["SHA384WITHECDSA"] = "SHA-384withECDSA";
+            algorithms["SHA-384WITHECDSA"] = "SHA-384withECDSA";
+            algorithms[X9ObjectIdentifiers.ECDsaWithSha384.Id] = "SHA-384withECDSA";
+
+            algorithms["SHA512/ECDSA"] = "SHA-512withECDSA";
+            algorithms["SHA-512/ECDSA"] = "SHA-512withECDSA";
+            algorithms["ECDSAWITHSHA512"] = "SHA-512withECDSA";
+            algorithms["ECDSAWITHSHA-512"] = "SHA-512withECDSA";
+            algorithms["SHA512WITHECDSA"] = "SHA-512withECDSA";
+            algorithms["SHA-512WITHECDSA"] = "SHA-512withECDSA";
+            algorithms[X9ObjectIdentifiers.ECDsaWithSha512.Id] = "SHA-512withECDSA";
+
+            algorithms["RIPEMD160/ECDSA"] = "RIPEMD160withECDSA";
+            algorithms["ECDSAWITHRIPEMD160"] = "RIPEMD160withECDSA";
+            algorithms["RIPEMD160WITHECDSA"] = "RIPEMD160withECDSA";
+            algorithms[TeleTrusTObjectIdentifiers.ECSignWithRipeMD160.Id] = "RIPEMD160withECDSA";
+
+            algorithms["GOST-3410"] = "GOST3410";
+            algorithms["GOST-3410-94"] = "GOST3410";
+            algorithms["GOST3411WITHGOST3410"] = "GOST3410";
+            algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94.Id] = "GOST3410";
+
+            algorithms["ECGOST-3410"] = "ECGOST3410";
+            algorithms["ECGOST-3410-2001"] = "ECGOST3410";
+            algorithms["GOST3411WITHECGOST3410"] = "ECGOST3410";
+            algorithms[CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001.Id] = "ECGOST3410";
+
+
+
+            oids["MD2withRSA"] = PkcsObjectIdentifiers.MD2WithRsaEncryption;
+            oids["MD4withRSA"] = PkcsObjectIdentifiers.MD4WithRsaEncryption;
+            oids["MD5withRSA"] = PkcsObjectIdentifiers.MD5WithRsaEncryption;
+
+            oids["SHA-1withRSA"] = PkcsObjectIdentifiers.Sha1WithRsaEncryption;
+            oids["SHA-224withRSA"] = PkcsObjectIdentifiers.Sha224WithRsaEncryption;
+            oids["SHA-256withRSA"] = PkcsObjectIdentifiers.Sha256WithRsaEncryption;
+            oids["SHA-384withRSA"] = PkcsObjectIdentifiers.Sha384WithRsaEncryption;
+            oids["SHA-512withRSA"] = PkcsObjectIdentifiers.Sha512WithRsaEncryption;
+
+            oids["PSSwithRSA"] = PkcsObjectIdentifiers.IdRsassaPss;
+            oids["SHA-1withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+            oids["SHA-224withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+            oids["SHA-256withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+            oids["SHA-384withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+            oids["SHA-512withRSAandMGF1"] = PkcsObjectIdentifiers.IdRsassaPss;
+
+            oids["RIPEMD128withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128;
+            oids["RIPEMD160withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160;
+            oids["RIPEMD256withRSA"] = TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256;
+
+            oids["SHA-1withDSA"] = X9ObjectIdentifiers.IdDsaWithSha1;
+
+            oids["SHA-1withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha1;
+            oids["SHA-224withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha224;
+            oids["SHA-256withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha256;
+            oids["SHA-384withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha384;
+            oids["SHA-512withECDSA"] = X9ObjectIdentifiers.ECDsaWithSha512;
+
+            oids["GOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94;
+            oids["ECGOST3410"] = CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001;
+        }
+
+        /// <summary>
+        /// Returns a ObjectIdentifier for a give encoding.
+        /// </summary>
+        /// <param name="mechanism">A string representation of the encoding.</param>
+        /// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
+        // TODO Don't really want to support this
+        public static DerObjectIdentifier GetObjectIdentifier(
+            string mechanism)
+        {
+            if (mechanism == null)
+                throw new ArgumentNullException("mechanism");
+
+            mechanism = Platform.ToUpperInvariant(mechanism);
+            string aliased = (string) algorithms[mechanism];
+
+            if (aliased != null)
+                mechanism = aliased;
+
+            return (DerObjectIdentifier) oids[mechanism];
+        }
+
+        public static ICollection Algorithms
+        {
+            get { return oids.Keys; }
+        }
+
+        public static Asn1Encodable GetDefaultX509Parameters(
+            DerObjectIdentifier id)
+        {
+            return GetDefaultX509Parameters(id.Id);
+        }
+
+        public static Asn1Encodable GetDefaultX509Parameters(
+            string algorithm)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            algorithm = Platform.ToUpperInvariant(algorithm);
+
+            string mechanism = (string) algorithms[algorithm];
+
+            if (mechanism == null)
+                mechanism = algorithm;
+
+            if (mechanism == "PSSwithRSA")
+            {
+                // TODO The Sha1Digest here is a default. In JCE version, the actual digest
+                // to be used can be overridden by subsequent parameter settings.
+                return GetPssX509Parameters("SHA-1");
+            }
+
+            if (mechanism.EndsWith("withRSAandMGF1"))
+            {
+                string digestName = mechanism.Substring(0, mechanism.Length - "withRSAandMGF1".Length);
+                return GetPssX509Parameters(digestName);
+            }
+
+            return DerNull.Instance;
+        }
+
+        private static Asn1Encodable GetPssX509Parameters(
+            string	digestName)
+        {
+            AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(
+                DigestUtilities.GetObjectIdentifier(digestName), DerNull.Instance);
+
+            // TODO Is it possible for the MGF hash alg to be different from the PSS one?
+            AlgorithmIdentifier maskGenAlgorithm = new AlgorithmIdentifier(
+                PkcsObjectIdentifiers.IdMgf1, hashAlgorithm);
+
+            int saltLen = DigestUtilities.GetDigest(digestName).GetDigestSize();
+            return new RsassaPssParameters(hashAlgorithm, maskGenAlgorithm,
+                new DerInteger(saltLen), new DerInteger(1));
+        }
+
+        public static ISigner GetSigner(
+            DerObjectIdentifier id)
+        {
+            return GetSigner(id.Id);
+        }
+
+        public static ISigner GetSigner(
+            string algorithm)
+        {
+            if (algorithm == null)
+                throw new ArgumentNullException("algorithm");
+
+            algorithm = Platform.ToUpperInvariant(algorithm);
+
+            string mechanism = (string) algorithms[algorithm];
+
+            if (mechanism == null)
+                mechanism = algorithm;
+
+            if (mechanism.Equals("RSA"))
+            {
+                return (new RsaDigestSigner(new NullDigest(), (AlgorithmIdentifier)null));
+            }
+            if (mechanism.Equals("MD2withRSA"))
+            {
+                return (new RsaDigestSigner(new MD2Digest()));
+            }
+            if (mechanism.Equals("MD4withRSA"))
+            {
+                return (new RsaDigestSigner(new MD4Digest()));
+            }
+            if (mechanism.Equals("MD5withRSA"))
+            {
+                return (new RsaDigestSigner(new MD5Digest()));
+            }
+            if (mechanism.Equals("SHA-1withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-224withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA-256withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA-384withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA-512withRSA"))
+            {
+                return (new RsaDigestSigner(new Sha512Digest()));
+            }
+            if (mechanism.Equals("RIPEMD128withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD128Digest()));
+            }
+            if (mechanism.Equals("RIPEMD160withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD160Digest()));
+            }
+            if (mechanism.Equals("RIPEMD256withRSA"))
+            {
+                return (new RsaDigestSigner(new RipeMD256Digest()));
+            }
+
+            if (mechanism.Equals("RAWRSASSA-PSS"))
+            {
+                // TODO Add support for other parameter settings
+                return PssSigner.CreateRawSigner(new RsaBlindedEngine(), new Sha1Digest());
+            }
+            if (mechanism.Equals("PSSwithRSA"))
+            {
+                // TODO The Sha1Digest here is a default. In JCE version, the actual digest
+                // to be used can be overridden by subsequent parameter settings.
+                return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-1withRSAandMGF1"))
+            {
+                return (new PssSigner(new RsaBlindedEngine(), new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-224withRSAandMGF1"))
+            {
+                return (new PssSigner(new RsaBlindedEngine(), new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA-256withRSAandMGF1"))
+            {
+                return (new PssSigner(new RsaBlindedEngine(), new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA-384withRSAandMGF1"))
+            {
+                return (new PssSigner(new RsaBlindedEngine(), new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA-512withRSAandMGF1"))
+            {
+                return (new PssSigner(new RsaBlindedEngine(), new Sha512Digest()));
+            }
+
+            if (mechanism.Equals("NONEwithDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new NullDigest()));
+            }
+            if (mechanism.Equals("SHA-1withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-224withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA-256withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA-384withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA-512withDSA"))
+            {
+                return (new DsaDigestSigner(new DsaSigner(), new Sha512Digest()));
+            }
+
+            if (mechanism.Equals("NONEwithECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new NullDigest()));
+            }
+            if (mechanism.Equals("SHA-1withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA-224withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA-256withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA-384withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA-512withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new Sha512Digest()));
+            }
+
+            if (mechanism.Equals("RIPEMD160withECDSA"))
+            {
+                return (new DsaDigestSigner(new ECDsaSigner(), new RipeMD160Digest()));
+            }
+
+            if (mechanism.Equals("SHA1WITHECNR"))
+            {
+                return (new DsaDigestSigner(new ECNRSigner(), new Sha1Digest()));
+            }
+            if (mechanism.Equals("SHA224WITHECNR"))
+            {
+                return (new DsaDigestSigner(new ECNRSigner(), new Sha224Digest()));
+            }
+            if (mechanism.Equals("SHA256WITHECNR"))
+            {
+                return (new DsaDigestSigner(new ECNRSigner(), new Sha256Digest()));
+            }
+            if (mechanism.Equals("SHA384WITHECNR"))
+            {
+                return (new DsaDigestSigner(new ECNRSigner(), new Sha384Digest()));
+            }
+            if (mechanism.Equals("SHA512WITHECNR"))
+            {
+                return (new DsaDigestSigner(new ECNRSigner(), new Sha512Digest()));
+            }
+
+            if (mechanism.Equals("GOST3410"))
+            {
+                return new Gost3410DigestSigner(new Gost3410Signer(), new Gost3411Digest());
+            }
+            if (mechanism.Equals("ECGOST3410"))
+            {
+                return new Gost3410DigestSigner(new ECGost3410Signer(), new Gost3411Digest());
+            }
+
+            if (mechanism.Equals("SHA1WITHRSA/ISO9796-2"))
+            {
+                return new Iso9796d2Signer(new RsaBlindedEngine(), new Sha1Digest(), true);
+            }
+            if (mechanism.Equals("MD5WITHRSA/ISO9796-2"))
+            {
+                return new Iso9796d2Signer(new RsaBlindedEngine(), new MD5Digest(), true);
+            }
+            if (mechanism.Equals("RIPEMD160WITHRSA/ISO9796-2"))
+            {
+                return new Iso9796d2Signer(new RsaBlindedEngine(), new RipeMD160Digest(), true);
+            }
+
+            throw new SecurityUtilityException("Signer " + algorithm + " not recognised.");
+        }
+
+        public static string GetEncodingName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/WrapperUtilities.cs b/BouncyCastle.AxCrypt/src/security/WrapperUtilities.cs
new file mode 100644
index 0000000..ce31ea5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/WrapperUtilities.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security
+{
+    /// <remarks>
+    ///  Utility class for creating IWrapper objects from their names/Oids
+    /// </remarks>
+    public sealed class WrapperUtilities
+    {
+        private enum WrapAlgorithm { AESWRAP, CAMELLIAWRAP, DESEDEWRAP, RC2WRAP, SEEDWRAP,
+            DESEDERFC3211WRAP, AESRFC3211WRAP, CAMELLIARFC3211WRAP };
+
+        private WrapperUtilities()
+        {
+        }
+
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        //private static readonly IDictionary oids = Platform.CreateHashtable();
+
+        static WrapperUtilities()
+        {
+            // Signal to obfuscation tools not to change enum constants
+            ((WrapAlgorithm)Enums.GetArbitraryValue(typeof(WrapAlgorithm))).ToString();
+
+            algorithms[NistObjectIdentifiers.IdAes128Wrap.Id] = "AESWRAP";
+            algorithms[NistObjectIdentifiers.IdAes192Wrap.Id] = "AESWRAP";
+            algorithms[NistObjectIdentifiers.IdAes256Wrap.Id] = "AESWRAP";
+
+            algorithms[NttObjectIdentifiers.IdCamellia128Wrap.Id] = "CAMELLIAWRAP";
+            algorithms[NttObjectIdentifiers.IdCamellia192Wrap.Id] = "CAMELLIAWRAP";
+            algorithms[NttObjectIdentifiers.IdCamellia256Wrap.Id] = "CAMELLIAWRAP";
+
+            algorithms[PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id] = "DESEDEWRAP";
+            algorithms["TDEAWRAP"] = "DESEDEWRAP";
+
+            algorithms[PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id] = "RC2WRAP";
+
+            algorithms[KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id] = "SEEDWRAP";
+        }
+
+        public static IWrapper GetWrapper(
+            DerObjectIdentifier oid)
+        {
+            return GetWrapper(oid.Id);
+        }
+
+        public static IWrapper GetWrapper(
+            string algorithm)
+        {
+            string upper = Platform.ToUpperInvariant(algorithm);
+            string mechanism = (string)algorithms[upper];
+
+            if (mechanism == null)
+            {
+                mechanism = upper;
+            }
+
+            try
+            {
+                WrapAlgorithm wrapAlgorithm = (WrapAlgorithm)Enums.GetEnumValue(
+                    typeof(WrapAlgorithm), mechanism);
+
+                switch (wrapAlgorithm)
+                {
+                    case WrapAlgorithm.AESWRAP:				return new AesWrapEngine();
+                    case WrapAlgorithm.CAMELLIAWRAP:		return new CamelliaWrapEngine();
+                    case WrapAlgorithm.DESEDEWRAP:			return new DesEdeWrapEngine();
+                    case WrapAlgorithm.RC2WRAP:				return new RC2WrapEngine();
+                    case WrapAlgorithm.SEEDWRAP:			return new SeedWrapEngine();
+                    case WrapAlgorithm.DESEDERFC3211WRAP:	return new Rfc3211WrapEngine(new DesEdeEngine());
+                    case WrapAlgorithm.AESRFC3211WRAP:		return new Rfc3211WrapEngine(new AesFastEngine());
+                    case WrapAlgorithm.CAMELLIARFC3211WRAP:	return new Rfc3211WrapEngine(new CamelliaEngine());
+                }
+            }
+            catch (ArgumentException)
+            {
+            }
+
+            // Create an IBufferedCipher and use it as IWrapper (via BufferedCipherWrapper)
+            IBufferedCipher blockCipher = CipherUtilities.GetCipher(algorithm);
+
+            if (blockCipher != null)
+                return new BufferedCipherWrapper(blockCipher);
+
+            throw new SecurityUtilityException("Wrapper " + algorithm + " not recognised.");
+        }
+
+        public static string GetAlgorithmName(
+            DerObjectIdentifier oid)
+        {
+            return (string) algorithms[oid.Id];
+        }
+
+        private class BufferedCipherWrapper
+            : IWrapper
+        {
+            private readonly IBufferedCipher cipher;
+            private bool forWrapping;
+
+            public BufferedCipherWrapper(
+                IBufferedCipher cipher)
+            {
+                this.cipher = cipher;
+            }
+
+            public string AlgorithmName
+            {
+                get { return cipher.AlgorithmName; }
+            }
+
+            public void Init(
+                bool				forWrapping,
+                ICipherParameters	parameters)
+            {
+                this.forWrapping = forWrapping;
+
+                cipher.Init(forWrapping, parameters);
+            }
+
+            public byte[] Wrap(
+                byte[]	input,
+                int		inOff,
+                int		length)
+            {
+                if (!forWrapping)
+                    throw new InvalidOperationException("Not initialised for wrapping");
+
+                return cipher.DoFinal(input, inOff, length);
+            }
+
+            public byte[] Unwrap(
+                byte[]	input,
+                int		inOff,
+                int		length)
+            {
+                if (forWrapping)
+                    throw new InvalidOperationException("Not initialised for unwrapping");
+
+                return cipher.DoFinal(input, inOff, length);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CertificateEncodingException.cs b/BouncyCastle.AxCrypt/src/security/cert/CertificateEncodingException.cs
new file mode 100644
index 0000000..a2909b0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CertificateEncodingException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateEncodingException : CertificateException
+	{
+		public CertificateEncodingException() : base() { }
+		public CertificateEncodingException(string msg) : base(msg) { }
+		public CertificateEncodingException(string msg, Exception e) : base(msg, e) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CertificateException.cs b/BouncyCastle.AxCrypt/src/security/cert/CertificateException.cs
new file mode 100644
index 0000000..441c598
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CertificateException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateException : GeneralSecurityException
+	{
+		public CertificateException() : base() { }
+		public CertificateException(string message) : base(message) { }
+		public CertificateException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CertificateExpiredException.cs b/BouncyCastle.AxCrypt/src/security/cert/CertificateExpiredException.cs
new file mode 100644
index 0000000..c893c07
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CertificateExpiredException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateExpiredException : CertificateException
+	{
+		public CertificateExpiredException() : base() { }
+		public CertificateExpiredException(string message) : base(message) { }
+		public CertificateExpiredException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CertificateNotYetValidException.cs b/BouncyCastle.AxCrypt/src/security/cert/CertificateNotYetValidException.cs
new file mode 100644
index 0000000..a0081ce
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CertificateNotYetValidException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateNotYetValidException : CertificateException
+	{
+		public CertificateNotYetValidException() : base() { }
+		public CertificateNotYetValidException(string message) : base(message) { }
+		public CertificateNotYetValidException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CertificateParsingException.cs b/BouncyCastle.AxCrypt/src/security/cert/CertificateParsingException.cs
new file mode 100644
index 0000000..8d8ed1e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CertificateParsingException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CertificateParsingException : CertificateException
+	{
+		public CertificateParsingException() : base() { }
+		public CertificateParsingException(string message) : base(message) { }
+		public CertificateParsingException(string message, Exception exception) : base(message, exception) { }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/security/cert/CrlException.cs b/BouncyCastle.AxCrypt/src/security/cert/CrlException.cs
new file mode 100644
index 0000000..0df007b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/security/cert/CrlException.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Security.Certificates
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class CrlException : GeneralSecurityException
+	{
+		public CrlException() : base() { }
+		public CrlException(string msg) : base(msg) {}
+		public CrlException(string msg, Exception e) : base(msg, e) {}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/GenTimeAccuracy.cs b/BouncyCastle.AxCrypt/src/tsp/GenTimeAccuracy.cs
new file mode 100644
index 0000000..8a2f299
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/GenTimeAccuracy.cs
@@ -0,0 +1,33 @@
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Tsp;
+
+namespace Org.BouncyCastle.Tsp
+{
+	public class GenTimeAccuracy
+	{
+		private Accuracy accuracy;
+
+		public GenTimeAccuracy(
+			Accuracy accuracy)
+		{
+			this.accuracy = accuracy;
+		}
+
+		public int Seconds { get { return GetTimeComponent(accuracy.Seconds); } }
+
+		public int Millis { get { return GetTimeComponent(accuracy.Millis); } }
+
+		public int Micros { get { return GetTimeComponent(accuracy.Micros); } }
+
+		private int GetTimeComponent(
+			DerInteger time)
+		{
+			return time == null ? 0 : time.Value.IntValue;
+		}
+
+		public override string ToString()
+		{
+			return Seconds + "." + Millis.ToString("000") + Micros.ToString("000");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TSPAlgorithms.cs b/BouncyCastle.AxCrypt/src/tsp/TSPAlgorithms.cs
new file mode 100644
index 0000000..e3dfc79
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TSPAlgorithms.cs
@@ -0,0 +1,48 @@
+using System.Collections;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tsp
+{
+	/**
+	 * Recognised hash algorithms for the time stamp protocol.
+	 */
+	public abstract class TspAlgorithms
+	{
+		public static readonly string MD5 = PkcsObjectIdentifiers.MD5.Id;
+
+		public static readonly string Sha1 = OiwObjectIdentifiers.IdSha1.Id;
+
+		public static readonly string Sha224 = NistObjectIdentifiers.IdSha224.Id;
+		public static readonly string Sha256 = NistObjectIdentifiers.IdSha256.Id;
+		public static readonly string Sha384 = NistObjectIdentifiers.IdSha384.Id;
+		public static readonly string Sha512 = NistObjectIdentifiers.IdSha512.Id;
+
+		public static readonly string RipeMD128 = TeleTrusTObjectIdentifiers.RipeMD128.Id;
+		public static readonly string RipeMD160 = TeleTrusTObjectIdentifiers.RipeMD160.Id;
+		public static readonly string RipeMD256 = TeleTrusTObjectIdentifiers.RipeMD256.Id;
+
+		public static readonly string Gost3411 = CryptoProObjectIdentifiers.GostR3411.Id;
+
+		public static readonly IList Allowed;
+
+		static TspAlgorithms()
+		{
+			string[] algs = new string[]
+			{
+				Gost3411, MD5, Sha1, Sha224, Sha256, Sha384, Sha512, RipeMD128, RipeMD160, RipeMD256
+			};
+
+			Allowed = Platform.CreateArrayList();
+			foreach (string alg in algs)
+			{
+				Allowed.Add(alg);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TSPException.cs b/BouncyCastle.AxCrypt/src/tsp/TSPException.cs
new file mode 100644
index 0000000..3917e96
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TSPException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.Tsp
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class TspException
+		: Exception
+	{
+		public TspException()
+		{
+		}
+
+		public TspException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public TspException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TSPUtil.cs b/BouncyCastle.AxCrypt/src/tsp/TSPUtil.cs
new file mode 100644
index 0000000..1026914
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TSPUtil.cs
@@ -0,0 +1,202 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tsp
+{
+	public class TspUtil
+	{
+		private static ISet EmptySet = CollectionUtilities.ReadOnly(new HashSet());
+		private static IList EmptyList = CollectionUtilities.ReadOnly(Platform.CreateArrayList());
+
+		private static readonly IDictionary digestLengths = Platform.CreateHashtable();
+        private static readonly IDictionary digestNames = Platform.CreateHashtable();
+
+		static TspUtil()
+		{
+			digestLengths.Add(PkcsObjectIdentifiers.MD5.Id, 16);
+			digestLengths.Add(OiwObjectIdentifiers.IdSha1.Id, 20);
+			digestLengths.Add(NistObjectIdentifiers.IdSha224.Id, 28);
+			digestLengths.Add(NistObjectIdentifiers.IdSha256.Id, 32);
+			digestLengths.Add(NistObjectIdentifiers.IdSha384.Id, 48);
+			digestLengths.Add(NistObjectIdentifiers.IdSha512.Id, 64);
+			digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, 16);
+			digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, 20);
+			digestLengths.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, 32);
+			digestLengths.Add(CryptoProObjectIdentifiers.GostR3411.Id, 32);
+
+			digestNames.Add(PkcsObjectIdentifiers.MD5.Id, "MD5");
+			digestNames.Add(OiwObjectIdentifiers.IdSha1.Id, "SHA1");
+			digestNames.Add(NistObjectIdentifiers.IdSha224.Id, "SHA224");
+			digestNames.Add(NistObjectIdentifiers.IdSha256.Id, "SHA256");
+			digestNames.Add(NistObjectIdentifiers.IdSha384.Id, "SHA384");
+			digestNames.Add(NistObjectIdentifiers.IdSha512.Id, "SHA512");
+			digestNames.Add(PkcsObjectIdentifiers.Sha1WithRsaEncryption.Id, "SHA1");
+			digestNames.Add(PkcsObjectIdentifiers.Sha224WithRsaEncryption.Id, "SHA224");
+			digestNames.Add(PkcsObjectIdentifiers.Sha256WithRsaEncryption.Id, "SHA256");
+			digestNames.Add(PkcsObjectIdentifiers.Sha384WithRsaEncryption.Id, "SHA384");
+			digestNames.Add(PkcsObjectIdentifiers.Sha512WithRsaEncryption.Id, "SHA512");
+			digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD128.Id, "RIPEMD128");
+			digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD160.Id, "RIPEMD160");
+			digestNames.Add(TeleTrusTObjectIdentifiers.RipeMD256.Id, "RIPEMD256");
+			digestNames.Add(CryptoProObjectIdentifiers.GostR3411.Id, "GOST3411");
+		}
+
+
+	    /**
+	     * Fetches the signature time-stamp attributes from a SignerInformation object.
+	     * Checks that the MessageImprint for each time-stamp matches the signature field.
+	     * (see RFC 3161 Appendix A).
+	     *
+	     * @param signerInfo a SignerInformation to search for time-stamps
+	     * @return a collection of TimeStampToken objects
+	     * @throws TSPValidationException
+	     */
+		public static ICollection GetSignatureTimestamps(
+			SignerInformation signerInfo)
+		{
+			IList timestamps = Platform.CreateArrayList();
+
+			Asn1.Cms.AttributeTable unsignedAttrs = signerInfo.UnsignedAttributes;
+			if (unsignedAttrs != null)
+			{
+				foreach (Asn1.Cms.Attribute tsAttr in unsignedAttrs.GetAll(
+					PkcsObjectIdentifiers.IdAASignatureTimeStampToken))
+				{
+					foreach (Asn1Encodable asn1 in tsAttr.AttrValues)
+					{
+						try
+						{
+							Asn1.Cms.ContentInfo contentInfo = Asn1.Cms.ContentInfo.GetInstance(
+								asn1.ToAsn1Object());
+							TimeStampToken timeStampToken = new TimeStampToken(contentInfo);
+							TimeStampTokenInfo tstInfo = timeStampToken.TimeStampInfo;
+
+							byte[] expectedDigest = DigestUtilities.CalculateDigest(
+								GetDigestAlgName(tstInfo.MessageImprintAlgOid),
+							    signerInfo.GetSignature());
+
+							if (!Arrays.ConstantTimeAreEqual(expectedDigest, tstInfo.GetMessageImprintDigest()))
+								throw new TspValidationException("Incorrect digest in message imprint");
+
+							timestamps.Add(timeStampToken);
+						}
+						catch (SecurityUtilityException)
+						{
+							throw new TspValidationException("Unknown hash algorithm specified in timestamp");
+						}
+						catch (Exception)
+						{
+							throw new TspValidationException("Timestamp could not be parsed");
+						}
+					}
+				}
+			}
+
+			return timestamps;
+		}
+
+		/**
+		 * Validate the passed in certificate as being of the correct type to be used
+		 * for time stamping. To be valid it must have an ExtendedKeyUsage extension
+		 * which has a key purpose identifier of id-kp-timeStamping.
+		 *
+		 * @param cert the certificate of interest.
+		 * @throws TspValidationException if the certicate fails on one of the check points.
+		 */
+		public static void ValidateCertificate(
+			X509Certificate cert)
+		{
+			if (cert.Version != 3)
+				throw new ArgumentException("Certificate must have an ExtendedKeyUsage extension.");
+
+			Asn1OctetString ext = cert.GetExtensionValue(X509Extensions.ExtendedKeyUsage);
+			if (ext == null)
+				throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension.");
+
+			if (!cert.GetCriticalExtensionOids().Contains(X509Extensions.ExtendedKeyUsage.Id))
+				throw new TspValidationException("Certificate must have an ExtendedKeyUsage extension marked as critical.");
+
+			try
+			{
+				ExtendedKeyUsage extKey = ExtendedKeyUsage.GetInstance(
+					Asn1Object.FromByteArray(ext.GetOctets()));
+
+				if (!extKey.HasKeyPurposeId(KeyPurposeID.IdKPTimeStamping) || extKey.Count != 1)
+					throw new TspValidationException("ExtendedKeyUsage not solely time stamping.");
+			}
+			catch (IOException)
+			{
+				throw new TspValidationException("cannot process ExtendedKeyUsage extension");
+			}
+		}
+
+		/// <summary>
+		/// Return the digest algorithm using one of the standard JCA string
+		/// representations rather than the algorithm identifier (if possible).
+		/// </summary>
+		internal static string GetDigestAlgName(
+			string digestAlgOID)
+		{
+			string digestName = (string) digestNames[digestAlgOID];
+
+			return digestName != null ? digestName : digestAlgOID;
+		}
+
+		internal static int GetDigestLength(
+			string digestAlgOID)
+		{
+			if (!digestLengths.Contains(digestAlgOID))
+				throw new TspException("digest algorithm cannot be found.");
+
+			return (int)digestLengths[digestAlgOID];
+		}
+
+		internal static IDigest CreateDigestInstance(
+			String digestAlgOID)
+		{
+	        string digestName = GetDigestAlgName(digestAlgOID);
+
+			return DigestUtilities.GetDigest(digestName);
+		}
+
+		internal static ISet GetCriticalExtensionOids(X509Extensions extensions)
+		{
+			if (extensions == null)
+				return EmptySet;
+
+			return CollectionUtilities.ReadOnly(new HashSet(extensions.GetCriticalExtensionOids()));
+		}
+
+		internal static ISet GetNonCriticalExtensionOids(X509Extensions extensions)
+		{
+			if (extensions == null)
+				return EmptySet;
+
+			// TODO: should probably produce a set that imposes correct ordering
+			return CollectionUtilities.ReadOnly(new HashSet(extensions.GetNonCriticalExtensionOids()));
+		}
+		
+		internal static IList GetExtensionOids(X509Extensions extensions)
+		{
+			if (extensions == null)
+				return EmptyList;
+
+			return CollectionUtilities.ReadOnly(Platform.CreateArrayList(extensions.GetExtensionOids()));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TSPValidationException.cs b/BouncyCastle.AxCrypt/src/tsp/TSPValidationException.cs
new file mode 100644
index 0000000..8ef2ec6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TSPValidationException.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace Org.BouncyCastle.Tsp
+{
+	/**
+	 * Exception thrown if a TSP request or response fails to validate.
+	 * <p>
+	 * If a failure code is associated with the exception it can be retrieved using
+	 * the getFailureCode() method.</p>
+	 */
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class TspValidationException
+		: TspException
+	{
+		private int failureCode;
+
+		public TspValidationException(
+			string message)
+			: base(message)
+		{
+			this.failureCode = -1;
+		}
+
+		public TspValidationException(
+			string	message,
+			int		failureCode)
+			: base(message)
+		{
+			this.failureCode = failureCode;
+		}
+
+		/**
+		 * Return the failure code associated with this exception - if one is set.
+		 *
+		 * @return the failure code if set, -1 otherwise.
+		 */
+		public int FailureCode
+		{
+			get { return failureCode; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampRequest.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampRequest.cs
new file mode 100644
index 0000000..6b96993
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampRequest.cs
@@ -0,0 +1,196 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tsp
+{
+	/**
+	 * Base class for an RFC 3161 Time Stamp Request.
+	 */
+	public class TimeStampRequest
+		: X509ExtensionBase
+	{
+		private TimeStampReq req;
+		private X509Extensions extensions;
+
+		public TimeStampRequest(
+			TimeStampReq req)
+		{
+			this.req = req;
+			this.extensions = req.Extensions;
+		}
+
+		/**
+		* Create a TimeStampRequest from the past in byte array.
+		*
+		* @param req byte array containing the request.
+		* @throws IOException if the request is malformed.
+		*/
+		public TimeStampRequest(
+			byte[] req)
+			: this(new Asn1InputStream(req))
+		{
+		}
+
+		/**
+		* Create a TimeStampRequest from the past in input stream.
+		*
+		* @param in input stream containing the request.
+		* @throws IOException if the request is malformed.
+		*/
+		public TimeStampRequest(
+			Stream input)
+			: this(new Asn1InputStream(input))
+		{
+		}
+
+		private TimeStampRequest(
+			Asn1InputStream str)
+		{
+			try
+			{
+				this.req = TimeStampReq.GetInstance(str.ReadObject());
+			}
+			catch (InvalidCastException e)
+			{
+				throw new IOException("malformed request: " + e);
+			}
+			catch (ArgumentException e)
+			{
+				throw new IOException("malformed request: " + e);
+			}
+		}
+
+		public int Version
+		{
+			get { return req.Version.Value.IntValue; }
+		}
+
+		public string MessageImprintAlgOid
+		{
+			get { return req.MessageImprint.HashAlgorithm.ObjectID.Id; }
+		}
+
+		public byte[] GetMessageImprintDigest()
+		{
+			return req.MessageImprint.GetHashedMessage();
+		}
+
+		public string ReqPolicy
+		{
+			get
+			{
+				return req.ReqPolicy == null
+					?	null
+					:	req.ReqPolicy.Id;
+			}
+		}
+
+		public BigInteger Nonce
+		{
+			get
+			{
+				return req.Nonce == null
+					?	null
+					:	req.Nonce.Value;
+			}
+		}
+
+		public bool CertReq
+		{
+			get
+			{
+				return req.CertReq == null
+					?	false
+					:	req.CertReq.IsTrue;
+			}
+		}
+
+		/**
+		* Validate the timestamp request, checking the digest to see if it is of an
+		* accepted type and whether it is of the correct length for the algorithm specified.
+		*
+		* @param algorithms a set of string OIDS giving accepted algorithms.
+		* @param policies if non-null a set of policies we are willing to sign under.
+		* @param extensions if non-null a set of extensions we are willing to accept.
+		* @throws TspException if the request is invalid, or processing fails.
+		*/
+		public void Validate(
+			IList algorithms,
+			IList policies,
+			IList extensions)
+		{
+			if (!algorithms.Contains(this.MessageImprintAlgOid))
+			{
+				throw new TspValidationException("request contains unknown algorithm.", PkiFailureInfo.BadAlg);
+			}
+
+			if (policies != null && this.ReqPolicy != null && !policies.Contains(this.ReqPolicy))
+			{
+				throw new TspValidationException("request contains unknown policy.", PkiFailureInfo.UnacceptedPolicy);
+			}
+
+			if (this.Extensions != null && extensions != null)
+			{
+				foreach (DerObjectIdentifier oid in this.Extensions.ExtensionOids)
+				{
+					if (!extensions.Contains(oid.Id))
+					{
+						throw new TspValidationException("request contains unknown extension.",
+							PkiFailureInfo.UnacceptedExtension);
+					}
+				}
+			}
+
+			int digestLength = TspUtil.GetDigestLength(this.MessageImprintAlgOid);
+
+			if (digestLength != this.GetMessageImprintDigest().Length)
+			{
+				throw new TspValidationException("imprint digest the wrong length.",
+					PkiFailureInfo.BadDataFormat);
+			}
+		}
+
+		/**
+		 * return the ASN.1 encoded representation of this object.
+		 */
+		public byte[] GetEncoded()
+		{
+			return req.GetEncoded();
+		}
+
+		internal X509Extensions Extensions
+		{
+			get { return req.Extensions; }
+		}
+		
+		public virtual bool HasExtensions
+		{
+			get { return extensions != null; }
+		}
+
+		public virtual X509Extension GetExtension(DerObjectIdentifier oid)
+		{
+			return extensions == null ? null : extensions.GetExtension(oid);
+		}
+
+		public virtual IList GetExtensionOids()
+		{
+			return TspUtil.GetExtensionOids(extensions);
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return Extensions;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampRequestGenerator.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampRequestGenerator.cs
new file mode 100644
index 0000000..2c698e4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampRequestGenerator.cs
@@ -0,0 +1,139 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tsp
+{
+	/**
+	 * Generator for RFC 3161 Time Stamp Request objects.
+	 */
+	public class TimeStampRequestGenerator
+	{
+		private DerObjectIdentifier reqPolicy;
+
+		private DerBoolean certReq;
+
+		private IDictionary extensions = Platform.CreateHashtable();
+        private IList       extOrdering = Platform.CreateArrayList();
+
+		public void SetReqPolicy(
+			string reqPolicy)
+		{
+			this.reqPolicy = new DerObjectIdentifier(reqPolicy);
+		}
+
+		public void SetCertReq(
+			bool certReq)
+		{
+			this.certReq = DerBoolean.GetInstance(certReq);
+		}
+
+		/**
+		 * add a given extension field for the standard extensions tag (tag 3)
+		 * @throws IOException
+		 */
+		[Obsolete("Use method taking DerObjectIdentifier")]
+		public void AddExtension(
+			string			oid,
+			bool			critical,
+			Asn1Encodable	value)
+		{
+			this.AddExtension(oid, critical, value.GetEncoded());
+		}
+
+		/**
+		* add a given extension field for the standard extensions tag
+		* The value parameter becomes the contents of the octet string associated
+		* with the extension.
+		*/
+		[Obsolete("Use method taking DerObjectIdentifier")]
+		public void AddExtension(
+			string	oid,
+			bool	critical,
+			byte[]	value)
+		{
+			DerObjectIdentifier derOid = new DerObjectIdentifier(oid);
+			extensions[derOid] = new X509Extension(critical, new DerOctetString(value));
+			extOrdering.Add(derOid);
+		}
+
+		/**
+		 * add a given extension field for the standard extensions tag (tag 3)
+		 * @throws IOException
+		 */
+		public virtual void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			Asn1Encodable 		extValue)
+		{
+			this.AddExtension(oid, critical, extValue.GetEncoded());
+		}
+
+		/**
+		 * add a given extension field for the standard extensions tag
+		 * The value parameter becomes the contents of the octet string associated
+		 * with the extension.
+		 */
+		public virtual void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			byte[]				extValue)
+		{
+			extensions.Add(oid, new X509Extension(critical, new DerOctetString(extValue)));
+			extOrdering.Add(oid);
+		}
+
+		public TimeStampRequest Generate(
+			string	digestAlgorithm,
+			byte[]	digest)
+		{
+			return this.Generate(digestAlgorithm, digest, null);
+		}
+
+		public TimeStampRequest Generate(
+			string		digestAlgorithmOid,
+			byte[]		digest,
+			BigInteger	nonce)
+		{
+			if (digestAlgorithmOid == null)
+			{
+				throw new ArgumentException("No digest algorithm specified");
+			}
+
+			DerObjectIdentifier digestAlgOid = new DerObjectIdentifier(digestAlgorithmOid);
+
+			AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOid, DerNull.Instance);
+			MessageImprint messageImprint = new MessageImprint(algID, digest);
+
+			X509Extensions  ext = null;
+
+			if (extOrdering.Count != 0)
+			{
+				ext = new X509Extensions(extOrdering, extensions);
+			}
+
+			DerInteger derNonce = nonce == null
+				?	null
+				:	new DerInteger(nonce);
+
+			return new TimeStampRequest(
+				new TimeStampReq(messageImprint, reqPolicy, derNonce, certReq, ext));
+		}
+
+		public virtual TimeStampRequest Generate(DerObjectIdentifier digestAlgorithm, byte[] digest)
+		{
+			return Generate(digestAlgorithm.Id, digest);
+		}
+
+		public virtual TimeStampRequest Generate(DerObjectIdentifier digestAlgorithm, byte[] digest, BigInteger nonce)
+		{
+			return Generate(digestAlgorithm.Id, digest, nonce);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampResponse.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampResponse.cs
new file mode 100644
index 0000000..0695211
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampResponse.cs
@@ -0,0 +1,184 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Tsp
+{
+	/**
+	 * Base class for an RFC 3161 Time Stamp Response object.
+	 */
+	public class TimeStampResponse
+	{
+		private TimeStampResp	resp;
+		private TimeStampToken	timeStampToken;
+
+		public TimeStampResponse(
+			TimeStampResp resp)
+		{
+			this.resp = resp;
+
+			if (resp.TimeStampToken != null)
+			{
+				timeStampToken = new TimeStampToken(resp.TimeStampToken);
+			}
+		}
+
+		/**
+		* Create a TimeStampResponse from a byte array containing an ASN.1 encoding.
+		*
+		* @param resp the byte array containing the encoded response.
+		* @throws TspException if the response is malformed.
+		* @throws IOException if the byte array doesn't represent an ASN.1 encoding.
+		*/
+		public TimeStampResponse(
+			byte[] resp)
+			: this(readTimeStampResp(new Asn1InputStream(resp)))
+		{
+		}
+
+		/**
+		 * Create a TimeStampResponse from an input stream containing an ASN.1 encoding.
+		 *
+		 * @param input the input stream containing the encoded response.
+		 * @throws TspException if the response is malformed.
+		 * @throws IOException if the stream doesn't represent an ASN.1 encoding.
+		 */
+		public TimeStampResponse(
+			Stream input)
+			: this(readTimeStampResp(new Asn1InputStream(input)))
+		{
+		}
+
+		private static TimeStampResp readTimeStampResp(
+			Asn1InputStream input)
+		{
+			try
+			{
+				return TimeStampResp.GetInstance(input.ReadObject());
+			}
+			catch (ArgumentException e)
+			{
+				throw new TspException("malformed timestamp response: " + e, e);
+			}
+			catch (InvalidCastException e)
+			{
+				throw new TspException("malformed timestamp response: " + e, e);
+			}
+		}
+
+		public int Status
+		{
+			get { return resp.Status.Status.IntValue; }
+		}
+
+		public string GetStatusString()
+		{
+			if (resp.Status.StatusString == null)
+			{
+				return null;
+			}
+
+			StringBuilder statusStringBuf = new StringBuilder();
+			PkiFreeText text = resp.Status.StatusString;
+			for (int i = 0; i != text.Count; i++)
+			{
+				statusStringBuf.Append(text[i].GetString());
+			}
+
+			return statusStringBuf.ToString();
+		}
+
+		public PkiFailureInfo GetFailInfo()
+		{
+			if (resp.Status.FailInfo == null)
+			{
+				return null;
+			}
+
+			return new PkiFailureInfo(resp.Status.FailInfo);
+		}
+
+		public TimeStampToken TimeStampToken
+		{
+			get { return timeStampToken; }
+		}
+
+		/**
+		 * Check this response against to see if it a well formed response for
+		 * the passed in request. Validation will include checking the time stamp
+		 * token if the response status is GRANTED or GRANTED_WITH_MODS.
+		 *
+		 * @param request the request to be checked against
+		 * @throws TspException if the request can not match this response.
+		 */
+		public void Validate(
+			TimeStampRequest request)
+		{
+			TimeStampToken tok = this.TimeStampToken;
+
+			if (tok != null)
+			{
+				TimeStampTokenInfo tstInfo = tok.TimeStampInfo;
+
+				if (request.Nonce != null && !request.Nonce.Equals(tstInfo.Nonce))
+				{
+					throw new TspValidationException("response contains wrong nonce value.");
+				}
+
+				if (this.Status != (int) PkiStatus.Granted && this.Status != (int) PkiStatus.GrantedWithMods)
+				{
+					throw new TspValidationException("time stamp token found in failed request.");
+				}
+
+				if (!Arrays.ConstantTimeAreEqual(request.GetMessageImprintDigest(), tstInfo.GetMessageImprintDigest()))
+				{
+					throw new TspValidationException("response for different message imprint digest.");
+				}
+
+				if (!tstInfo.MessageImprintAlgOid.Equals(request.MessageImprintAlgOid))
+				{
+					throw new TspValidationException("response for different message imprint algorithm.");
+				}
+
+				Asn1.Cms.Attribute scV1 = tok.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificate];
+				Asn1.Cms.Attribute scV2 = tok.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2];
+
+				if (scV1 == null && scV2 == null)
+				{
+					throw new TspValidationException("no signing certificate attribute present.");
+				}
+
+				if (scV1 != null && scV2 != null)
+				{
+					/*
+					 * RFC 5035 5.4. If both attributes exist in a single message,
+					 * they are independently evaluated. 
+					 */
+				}
+
+				if (request.ReqPolicy != null && !request.ReqPolicy.Equals(tstInfo.Policy))
+				{
+					throw new TspValidationException("TSA policy wrong for request.");
+				}
+			}
+			else if (this.Status == (int) PkiStatus.Granted || this.Status == (int) PkiStatus.GrantedWithMods)
+			{
+				throw new TspValidationException("no time stamp token found and one expected.");
+			}
+		}
+
+		/**
+		 * return the ASN.1 encoded representation of this object.
+		 */
+		public byte[] GetEncoded()
+		{
+			return resp.GetEncoded();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampResponseGenerator.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampResponseGenerator.cs
new file mode 100644
index 0000000..8d798de
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampResponseGenerator.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Tsp
+{
+    /**
+     * Generator for RFC 3161 Time Stamp Responses.
+     */
+    public class TimeStampResponseGenerator
+    {
+        private PkiStatus status;
+
+        private Asn1EncodableVector statusStrings;
+
+        private int failInfo;
+        private TimeStampTokenGenerator tokenGenerator;
+        private IList acceptedAlgorithms;
+        private IList acceptedPolicies;
+        private IList acceptedExtensions;
+
+        public TimeStampResponseGenerator(
+            TimeStampTokenGenerator tokenGenerator,
+            IList acceptedAlgorithms)
+            : this(tokenGenerator, acceptedAlgorithms, null, null)
+        {
+        }
+
+        public TimeStampResponseGenerator(
+            TimeStampTokenGenerator tokenGenerator,
+            IList acceptedAlgorithms,
+            IList acceptedPolicy)
+            : this(tokenGenerator, acceptedAlgorithms, acceptedPolicy, null)
+        {
+        }
+
+        public TimeStampResponseGenerator(
+            TimeStampTokenGenerator tokenGenerator,
+            IList acceptedAlgorithms,
+            IList acceptedPolicies,
+            IList acceptedExtensions)
+        {
+            this.tokenGenerator = tokenGenerator;
+            this.acceptedAlgorithms = acceptedAlgorithms;
+            this.acceptedPolicies = acceptedPolicies;
+            this.acceptedExtensions = acceptedExtensions;
+
+            statusStrings = new Asn1EncodableVector();
+        }
+
+        private void AddStatusString(string statusString)
+        {
+            statusStrings.Add(new DerUtf8String(statusString));
+        }
+
+        private void SetFailInfoField(int field)
+        {
+            failInfo |= field;
+        }
+
+        private PkiStatusInfo GetPkiStatusInfo()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                new DerInteger((int)status));
+
+            if (statusStrings.Count > 0)
+            {
+                v.Add(new PkiFreeText(new DerSequence(statusStrings)));
+            }
+
+            if (failInfo != 0)
+            {
+                v.Add(new FailInfo(failInfo));
+            }
+
+            return new PkiStatusInfo(new DerSequence(v));
+        }
+
+        public TimeStampResponse Generate(
+            TimeStampRequest request,
+            BigInteger serialNumber,
+            DateTime genTime)
+        {
+            return Generate(request, serialNumber, new DateTimeObject(genTime));
+        }
+
+        /**
+         * Return an appropriate TimeStampResponse.
+         * <p>
+         * If genTime is null a timeNotAvailable error response will be returned.
+         *
+         * @param request the request this response is for.
+         * @param serialNumber serial number for the response token.
+         * @param genTime generation time for the response token.
+         * @param provider provider to use for signature calculation.
+         * @return
+         * @throws NoSuchAlgorithmException
+         * @throws NoSuchProviderException
+         * @throws TSPException
+         * </p>
+         */
+        public TimeStampResponse Generate(
+            TimeStampRequest request,
+            BigInteger serialNumber,
+            DateTimeObject genTime)
+        {
+            TimeStampResp resp;
+
+            try
+            {
+                if (genTime == null)
+                    throw new TspValidationException("The time source is not available.",
+                        PkiFailureInfo.TimeNotAvailable);
+
+                request.Validate(acceptedAlgorithms, acceptedPolicies, acceptedExtensions);
+
+                this.status = PkiStatus.Granted;
+                this.AddStatusString("Operation Okay");
+
+                PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo();
+
+                ContentInfo tstTokenContentInfo;
+                try
+                {
+                    TimeStampToken token = tokenGenerator.Generate(request, serialNumber, genTime.Value);
+                    byte[] encoded = token.ToCmsSignedData().GetEncoded();
+
+                    tstTokenContentInfo = ContentInfo.GetInstance(Asn1Object.FromByteArray(encoded));
+                }
+                catch (IOException e)
+                {
+                    throw new TspException("Timestamp token received cannot be converted to ContentInfo", e);
+                }
+
+                resp = new TimeStampResp(pkiStatusInfo, tstTokenContentInfo);
+            }
+            catch (TspValidationException e)
+            {
+                status = PkiStatus.Rejection;
+
+                this.SetFailInfoField(e.FailureCode);
+                this.AddStatusString(e.Message);
+
+                PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo();
+
+                resp = new TimeStampResp(pkiStatusInfo, null);
+            }
+
+            try
+            {
+                return new TimeStampResponse(resp);
+            }
+            catch (IOException e)
+            {
+                throw new TspException("created badly formatted response!", e);
+            }
+        }
+
+        class FailInfo
+            : DerBitString
+        {
+            internal FailInfo(
+                int failInfoValue)
+                : base(GetBytes(failInfoValue), GetPadBits(failInfoValue))
+            {
+            }
+        }
+
+        /**
+         * Generate a TimeStampResponse with chosen status and FailInfoField.
+         *
+         * @param status the PKIStatus to set.
+         * @param failInfoField the FailInfoField to set.
+         * @param statusString an optional string describing the failure.
+         * @return a TimeStampResponse with a failInfoField and optional statusString
+         * @throws TSPException in case the response could not be created
+         */
+        public TimeStampResponse GenerateFailResponse(PkiStatus status, int failInfoField, string statusString)
+        {
+            this.status = status;
+
+            this.SetFailInfoField(failInfoField);
+
+            if (statusString != null)
+            {
+                this.AddStatusString(statusString);
+            }
+
+            PkiStatusInfo pkiStatusInfo = GetPkiStatusInfo();
+
+            TimeStampResp resp = new TimeStampResp(pkiStatusInfo, null);
+
+            try
+            {
+                return new TimeStampResponse(resp);
+            }
+            catch (IOException e)
+            {
+                throw new TspException("created badly formatted response!", e);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampToken.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampToken.cs
new file mode 100644
index 0000000..51a9592
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampToken.cs
@@ -0,0 +1,305 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ess;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tsp
+{
+	public class TimeStampToken
+	{
+		private readonly CmsSignedData		tsToken;
+		private readonly SignerInformation	tsaSignerInfo;
+//		private readonly DateTime			genTime;
+		private readonly TimeStampTokenInfo	tstInfo;
+		private readonly CertID				certID;
+
+		public TimeStampToken(
+			Asn1.Cms.ContentInfo contentInfo)
+			: this(new CmsSignedData(contentInfo))
+		{
+		}
+
+		public TimeStampToken(
+			CmsSignedData signedData)
+		{
+			this.tsToken = signedData;
+
+			if (!this.tsToken.SignedContentType.Equals(PkcsObjectIdentifiers.IdCTTstInfo))
+			{
+				throw new TspValidationException("ContentInfo object not for a time stamp.");
+			}
+
+			ICollection signers = tsToken.GetSignerInfos().GetSigners();
+
+			if (signers.Count != 1)
+			{
+				throw new ArgumentException("Time-stamp token signed by "
+					+ signers.Count
+					+ " signers, but it must contain just the TSA signature.");
+			}
+
+
+			IEnumerator signerEnum = signers.GetEnumerator();
+
+			signerEnum.MoveNext();
+			tsaSignerInfo = (SignerInformation) signerEnum.Current;
+
+			try
+			{
+				CmsProcessable content = tsToken.SignedContent;
+				MemoryStream bOut = new MemoryStream();
+
+				content.Write(bOut);
+
+				this.tstInfo = new TimeStampTokenInfo(
+					TstInfo.GetInstance(
+						Asn1Object.FromByteArray(bOut.ToArray())));
+
+				Asn1.Cms.Attribute attr = tsaSignerInfo.SignedAttributes[
+					PkcsObjectIdentifiers.IdAASigningCertificate];
+
+//				if (attr == null)
+//				{
+//					throw new TspValidationException(
+//						"no signing certificate attribute found, time stamp invalid.");
+//				}
+//
+//				SigningCertificate signCert = SigningCertificate.GetInstance(
+//					attr.AttrValues[0]);
+//
+//				this.certID = EssCertID.GetInstance(signCert.GetCerts()[0]);
+
+				if (attr != null)
+				{
+					SigningCertificate signCert = SigningCertificate.GetInstance(attr.AttrValues[0]);
+
+					this.certID = new CertID(EssCertID.GetInstance(signCert.GetCerts()[0]));
+				}
+				else
+				{
+					attr = tsaSignerInfo.SignedAttributes[PkcsObjectIdentifiers.IdAASigningCertificateV2];
+
+					if (attr == null)
+						throw new TspValidationException("no signing certificate attribute found, time stamp invalid.");
+
+					SigningCertificateV2 signCertV2 = SigningCertificateV2.GetInstance(attr.AttrValues[0]);
+
+					this.certID = new CertID(EssCertIDv2.GetInstance(signCertV2.GetCerts()[0]));
+				}
+			}
+			catch (CmsException e)
+			{
+				throw new TspException(e.Message, e.InnerException);
+			}
+		}
+
+		public TimeStampTokenInfo TimeStampInfo
+		{
+			get { return tstInfo; }
+		}
+
+		public SignerID SignerID
+		{
+			get { return tsaSignerInfo.SignerID; }
+		}
+
+		public Asn1.Cms.AttributeTable SignedAttributes
+		{
+			get { return tsaSignerInfo.SignedAttributes; }
+		}
+
+		public Asn1.Cms.AttributeTable UnsignedAttributes
+		{
+			get { return tsaSignerInfo.UnsignedAttributes; }
+		}
+
+		public IX509Store GetCertificates(
+			string type)
+		{
+			return tsToken.GetCertificates(type);
+		}
+
+		public IX509Store GetCrls(
+			string type)
+		{
+			return tsToken.GetCrls(type);
+		}
+
+	    public IX509Store GetAttributeCertificates(
+			string type)
+	    {
+	        return tsToken.GetAttributeCertificates(type);
+	    }
+
+		/**
+		 * Validate the time stamp token.
+		 * <p>
+		 * To be valid the token must be signed by the passed in certificate and
+		 * the certificate must be the one referred to by the SigningCertificate
+		 * attribute included in the hashed attributes of the token. The
+		 * certificate must also have the ExtendedKeyUsageExtension with only
+		 * KeyPurposeID.IdKPTimeStamping and have been valid at the time the
+		 * timestamp was created.
+		 * </p>
+		 * <p>
+		 * A successful call to validate means all the above are true.
+		 * </p>
+		 */
+		public void Validate(
+			X509Certificate cert)
+		{
+			try
+			{
+				byte[] hash = DigestUtilities.CalculateDigest(
+					certID.GetHashAlgorithmName(), cert.GetEncoded());
+
+				if (!Arrays.ConstantTimeAreEqual(certID.GetCertHash(), hash))
+				{
+					throw new TspValidationException("certificate hash does not match certID hash.");
+				}
+
+				if (certID.IssuerSerial != null)
+				{
+					if (!certID.IssuerSerial.Serial.Value.Equals(cert.SerialNumber))
+					{
+						throw new TspValidationException("certificate serial number does not match certID for signature.");
+					}
+
+					GeneralName[] names = certID.IssuerSerial.Issuer.GetNames();
+					X509Name principal = PrincipalUtilities.GetIssuerX509Principal(cert);
+					bool found = false;
+
+					for (int i = 0; i != names.Length; i++)
+					{
+						if (names[i].TagNo == 4
+							&& X509Name.GetInstance(names[i].Name).Equivalent(principal))
+						{
+							found = true;
+							break;
+						}
+					}
+
+					if (!found)
+					{
+						throw new TspValidationException("certificate name does not match certID for signature. ");
+					}
+				}
+
+				TspUtil.ValidateCertificate(cert);
+
+				cert.CheckValidity(tstInfo.GenTime);
+
+				if (!tsaSignerInfo.Verify(cert))
+				{
+					throw new TspValidationException("signature not created by certificate.");
+				}
+			}
+			catch (CmsException e)
+			{
+				if (e.InnerException != null)
+				{
+					throw new TspException(e.Message, e.InnerException);
+				}
+
+				throw new TspException("CMS exception: " + e, e);
+			}
+			catch (CertificateEncodingException e)
+			{
+				throw new TspException("problem processing certificate: " + e, e);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new TspException("cannot find algorithm: " + e.Message, e);
+			}
+		}
+
+		/**
+		 * Return the underlying CmsSignedData object.
+		 *
+		 * @return the underlying CMS structure.
+		 */
+		public CmsSignedData ToCmsSignedData()
+		{
+			return tsToken;
+		}
+
+		/**
+		 * Return a ASN.1 encoded byte stream representing the encoded object.
+		 *
+		 * @throws IOException if encoding fails.
+		 */
+		public byte[] GetEncoded()
+		{
+			return tsToken.GetEncoded();
+		}
+
+
+		// perhaps this should be done using an interface on the ASN.1 classes...
+		private class CertID
+		{
+			private EssCertID certID;
+			private EssCertIDv2 certIDv2;
+
+			internal CertID(EssCertID certID)
+			{
+				this.certID = certID;
+				this.certIDv2 = null;
+			}
+
+			internal CertID(EssCertIDv2 certID)
+			{
+				this.certIDv2 = certID;
+				this.certID = null;
+			}
+
+			public string GetHashAlgorithmName()
+			{
+				if (certID != null)
+					return "SHA-1";
+
+				if (NistObjectIdentifiers.IdSha256.Equals(certIDv2.HashAlgorithm.ObjectID))
+					return "SHA-256";
+
+				return certIDv2.HashAlgorithm.ObjectID.Id;
+			}
+
+			public AlgorithmIdentifier GetHashAlgorithm()
+			{
+				return (certID != null)
+					?	new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1)
+					:	certIDv2.HashAlgorithm;
+			}
+
+			public byte[] GetCertHash()
+			{
+				return certID != null
+					?	certID.GetCertHash()
+					:	certIDv2.GetCertHash();
+			}
+
+			public IssuerSerial IssuerSerial
+			{
+				get
+				{
+					return certID != null
+						?	certID.IssuerSerial
+						:	certIDv2.IssuerSerial;
+				}
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenGenerator.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenGenerator.cs
new file mode 100644
index 0000000..07eddd4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenGenerator.cs
@@ -0,0 +1,245 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ess;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tsp
+{
+	public class TimeStampTokenGenerator
+	{
+		private int accuracySeconds = -1;
+		private int accuracyMillis = -1;
+		private int accuracyMicros = -1;
+		private bool ordering = false;
+		private GeneralName tsa = null;
+		private string tsaPolicyOID;
+
+		private AsymmetricKeyParameter	key;
+		private X509Certificate			cert;
+		private string					digestOID;
+		private Asn1.Cms.AttributeTable	signedAttr;
+		private Asn1.Cms.AttributeTable	unsignedAttr;
+		private IX509Store				x509Certs;
+		private IX509Store				x509Crls;
+
+		/**
+		 * basic creation - only the default attributes will be included here.
+		 */
+		public TimeStampTokenGenerator(
+			AsymmetricKeyParameter	key,
+			X509Certificate			cert,
+			string					digestOID,
+			string					tsaPolicyOID)
+			: this(key, cert, digestOID, tsaPolicyOID, null, null)
+		{
+		}
+
+		/**
+		 * create with a signer with extra signed/unsigned attributes.
+		 */
+		public TimeStampTokenGenerator(
+			AsymmetricKeyParameter	key,
+			X509Certificate			cert,
+			string					digestOID,
+			string					tsaPolicyOID,
+			Asn1.Cms.AttributeTable	signedAttr,
+			Asn1.Cms.AttributeTable	unsignedAttr)
+		{
+			this.key = key;
+			this.cert = cert;
+			this.digestOID = digestOID;
+			this.tsaPolicyOID = tsaPolicyOID;
+			this.unsignedAttr = unsignedAttr;
+
+			TspUtil.ValidateCertificate(cert);
+
+			//
+			// Add the ESSCertID attribute
+			//
+			IDictionary signedAttrs;
+			if (signedAttr != null)
+			{
+				signedAttrs = signedAttr.ToDictionary();
+			}
+			else
+			{
+				signedAttrs = Platform.CreateHashtable();
+			}
+
+			try
+			{
+				byte[] hash = DigestUtilities.CalculateDigest("SHA-1", cert.GetEncoded());
+
+				EssCertID essCertid = new EssCertID(hash);
+
+				Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(
+					PkcsObjectIdentifiers.IdAASigningCertificate,
+					new DerSet(new SigningCertificate(essCertid)));
+
+				signedAttrs[attr.AttrType] = attr;
+			}
+			catch (CertificateEncodingException e)
+			{
+				throw new TspException("Exception processing certificate.", e);
+			}
+			catch (SecurityUtilityException e)
+			{
+				throw new TspException("Can't find a SHA-1 implementation.", e);
+			}
+
+			this.signedAttr = new Asn1.Cms.AttributeTable(signedAttrs);
+		}
+
+		public void SetCertificates(
+			IX509Store certificates)
+		{
+			this.x509Certs = certificates;
+		}
+
+		public void SetCrls(
+			IX509Store crls)
+		{
+			this.x509Crls = crls;
+		}
+
+		public void SetAccuracySeconds(
+			int accuracySeconds)
+		{
+			this.accuracySeconds = accuracySeconds;
+		}
+
+		public void SetAccuracyMillis(
+			int accuracyMillis)
+		{
+			this.accuracyMillis = accuracyMillis;
+		}
+
+		public void SetAccuracyMicros(
+			int accuracyMicros)
+		{
+			this.accuracyMicros = accuracyMicros;
+		}
+
+		public void SetOrdering(
+			bool ordering)
+		{
+			this.ordering = ordering;
+		}
+
+		public void SetTsa(
+			GeneralName tsa)
+		{
+			this.tsa = tsa;
+		}
+
+		//------------------------------------------------------------------------------
+
+		public TimeStampToken Generate(
+			TimeStampRequest	request,
+			BigInteger			serialNumber,
+			DateTime			genTime)
+		{
+			DerObjectIdentifier digestAlgOID = new DerObjectIdentifier(request.MessageImprintAlgOid);
+
+			AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DerNull.Instance);
+			MessageImprint messageImprint = new MessageImprint(algID, request.GetMessageImprintDigest());
+
+			Accuracy accuracy = null;
+			if (accuracySeconds > 0 || accuracyMillis > 0 || accuracyMicros > 0)
+			{
+				DerInteger seconds = null;
+				if (accuracySeconds > 0)
+				{
+					seconds = new DerInteger(accuracySeconds);
+				}
+
+				DerInteger millis = null;
+				if (accuracyMillis > 0)
+				{
+					millis = new DerInteger(accuracyMillis);
+				}
+
+				DerInteger micros = null;
+				if (accuracyMicros > 0)
+				{
+					micros = new DerInteger(accuracyMicros);
+				}
+
+				accuracy = new Accuracy(seconds, millis, micros);
+			}
+
+			DerBoolean derOrdering = null;
+			if (ordering)
+			{
+				derOrdering = DerBoolean.GetInstance(ordering);
+			}
+
+			DerInteger nonce = null;
+			if (request.Nonce != null)
+			{
+				nonce = new DerInteger(request.Nonce);
+			}
+
+			DerObjectIdentifier tsaPolicy = new DerObjectIdentifier(tsaPolicyOID);
+			if (request.ReqPolicy != null)
+			{
+				tsaPolicy = new DerObjectIdentifier(request.ReqPolicy);
+			}
+
+			TstInfo tstInfo = new TstInfo(tsaPolicy, messageImprint,
+				new DerInteger(serialNumber), new DerGeneralizedTime(genTime), accuracy,
+				derOrdering, nonce, tsa, request.Extensions);
+
+			try
+			{
+				CmsSignedDataGenerator signedDataGenerator = new CmsSignedDataGenerator();
+
+				byte[] derEncodedTstInfo = tstInfo.GetDerEncoded();
+
+				if (request.CertReq)
+				{
+					signedDataGenerator.AddCertificates(x509Certs);
+				}
+
+				signedDataGenerator.AddCrls(x509Crls);
+				signedDataGenerator.AddSigner(key, cert, digestOID, signedAttr, unsignedAttr);
+
+				CmsSignedData signedData = signedDataGenerator.Generate(
+					PkcsObjectIdentifiers.IdCTTstInfo.Id,
+					new CmsProcessableByteArray(derEncodedTstInfo),
+					true);
+
+				return new TimeStampToken(signedData);
+			}
+			catch (CmsException cmsEx)
+			{
+				throw new TspException("Error generating time-stamp token", cmsEx);
+			}
+			catch (IOException e)
+			{
+				throw new TspException("Exception encoding info", e);
+			}
+			catch (X509StoreException e)
+			{
+				throw new TspException("Exception handling CertStore", e);
+			}
+//			catch (InvalidAlgorithmParameterException e)
+//			{
+//				throw new TspException("Exception handling CertStore CRLs", e);
+//			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenInfo.cs b/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenInfo.cs
new file mode 100644
index 0000000..5027a87
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/tsp/TimeStampTokenInfo.cs
@@ -0,0 +1,107 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Tsp
+{
+	public class TimeStampTokenInfo
+	{
+		private TstInfo		tstInfo;
+		private DateTime	genTime;
+
+		public TimeStampTokenInfo(
+			TstInfo tstInfo)
+		{
+			this.tstInfo = tstInfo;
+
+			try
+			{
+				this.genTime = tstInfo.GenTime.ToDateTime();
+			}
+			catch (Exception e)
+			{
+				throw new TspException("unable to parse genTime field: " + e.Message);
+			}
+		}
+
+		public bool IsOrdered
+		{
+			get { return tstInfo.Ordering.IsTrue; }
+		}
+
+		public Accuracy Accuracy
+		{
+			get { return tstInfo.Accuracy; }
+		}
+
+		public DateTime GenTime
+		{
+			get { return genTime; }
+		}
+
+		public GenTimeAccuracy GenTimeAccuracy
+		{
+			get
+			{
+				return this.Accuracy == null
+					?	null
+					:	new GenTimeAccuracy(this.Accuracy);
+			}
+		}
+
+		public string Policy
+		{
+			get { return tstInfo.Policy.Id; }
+		}
+
+		public BigInteger SerialNumber
+		{
+			get { return tstInfo.SerialNumber.Value; }
+		}
+
+		public GeneralName Tsa
+		{
+			get { return tstInfo.Tsa; }
+		}
+
+		/**
+		 * @return the nonce value, null if there isn't one.
+		 */
+		public BigInteger Nonce
+		{
+			get
+			{
+				return tstInfo.Nonce == null
+					?	null
+					:	tstInfo.Nonce.Value;
+			}
+		}
+
+		public AlgorithmIdentifier HashAlgorithm
+		{
+			get { return tstInfo.MessageImprint.HashAlgorithm; }
+		}
+
+		public string MessageImprintAlgOid
+		{
+			get { return tstInfo.MessageImprint.HashAlgorithm.ObjectID.Id; }
+		}
+
+		public byte[] GetMessageImprintDigest()
+		{
+			return tstInfo.MessageImprint.GetHashedMessage();
+		}
+
+		public byte[] GetEncoded()
+		{
+			return tstInfo.GetEncoded();
+		}
+
+		public TstInfo TstInfo
+		{
+			get { return tstInfo; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/Arrays.cs b/BouncyCastle.AxCrypt/src/util/Arrays.cs
new file mode 100644
index 0000000..27fd18d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Arrays.cs
@@ -0,0 +1,612 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Utilities
+{
+    /// <summary> General array utilities.</summary>
+    public abstract class Arrays
+    {
+        public static bool AreEqual(
+            bool[]  a,
+            bool[]  b)
+        {
+            if (a == b)
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return HaveSameContents(a, b);
+        }
+
+        public static bool AreEqual(
+            char[] a,
+            char[] b)
+        {
+            if (a == b)
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return HaveSameContents(a, b);
+        }
+
+        /// <summary>
+        /// Are two arrays equal.
+        /// </summary>
+        /// <param name="a">Left side.</param>
+        /// <param name="b">Right side.</param>
+        /// <returns>True if equal.</returns>
+        public static bool AreEqual(
+            byte[]	a,
+            byte[]	b)
+        {
+            if (a == b)
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return HaveSameContents(a, b);
+        }
+
+        [Obsolete("Use 'AreEqual' method instead")]
+        public static bool AreSame(
+            byte[]	a,
+            byte[]	b)
+        {
+            return AreEqual(a, b);
+        }
+
+        /// <summary>
+        /// A constant time equals comparison - does not terminate early if
+        /// test will fail.
+        /// </summary>
+        /// <param name="a">first array</param>
+        /// <param name="b">second array</param>
+        /// <returns>true if arrays equal, false otherwise.</returns>
+        public static bool ConstantTimeAreEqual(
+            byte[]	a,
+            byte[]	b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            int cmp = 0;
+            while (i != 0)
+            {
+                --i;
+                cmp |= (a[i] ^ b[i]);
+            }
+            return cmp == 0;
+        }
+
+        public static bool AreEqual(
+            int[]	a,
+            int[]	b)
+        {
+            if (a == b)
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return HaveSameContents(a, b);
+        }
+
+        [CLSCompliantAttribute(false)]
+        public static bool AreEqual(uint[] a, uint[] b)
+        {
+            if (a == b)
+                return true;
+
+            if (a == null || b == null)
+                return false;
+
+            return HaveSameContents(a, b);
+        }
+
+        private static bool HaveSameContents(
+            bool[] a,
+            bool[] b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            while (i != 0)
+            {
+                --i;
+                if (a[i] != b[i])
+                    return false;
+            }
+            return true;
+        }
+
+        private static bool HaveSameContents(
+            char[] a,
+            char[] b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            while (i != 0)
+            {
+                --i;
+                if (a[i] != b[i])
+                    return false;
+            }
+            return true;
+        }
+
+        private static bool HaveSameContents(
+            byte[]	a,
+            byte[]	b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            while (i != 0)
+            {
+                --i;
+                if (a[i] != b[i])
+                    return false;
+            }
+            return true;
+        }
+
+        private static bool HaveSameContents(
+            int[]	a,
+            int[]	b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            while (i != 0)
+            {
+                --i;
+                if (a[i] != b[i])
+                    return false;
+            }
+            return true;
+        }
+
+        private static bool HaveSameContents(uint[] a, uint[] b)
+        {
+            int i = a.Length;
+            if (i != b.Length)
+                return false;
+            while (i != 0)
+            {
+                --i;
+                if (a[i] != b[i])
+                    return false;
+            }
+            return true;
+        }
+
+        public static string ToString(
+            object[] a)
+        {
+            StringBuilder sb = new StringBuilder('[');
+            if (a.Length > 0)
+            {
+                sb.Append(a[0]);
+                for (int index = 1; index < a.Length; ++index)
+                {
+                    sb.Append(", ").Append(a[index]);
+                }
+            }
+            sb.Append(']');
+            return sb.ToString();
+        }
+
+        public static int GetHashCode(byte[] data)
+        {
+            if (data == null)
+            {
+                return 0;
+            }
+
+            int i = data.Length;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= data[i];
+            }
+
+            return hc;
+        }
+
+        public static int GetHashCode(byte[] data, int off, int len)
+        {
+            if (data == null)
+            {
+                return 0;
+            }
+
+            int i = len;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= data[off + i];
+            }
+
+            return hc;
+        }
+
+        public static int GetHashCode(int[] data)
+        {
+            if (data == null)
+                return 0;
+
+            int i = data.Length;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= data[i];
+            }
+
+            return hc;
+        }
+
+        public static int GetHashCode(int[] data, int off, int len)
+        {
+            if (data == null)
+                return 0;
+
+            int i = len;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= data[off + i];
+            }
+
+            return hc;
+        }
+
+        [CLSCompliantAttribute(false)]
+        public static int GetHashCode(uint[] data)
+        {
+            if (data == null)
+                return 0;
+
+            int i = data.Length;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= (int)data[i];
+            }
+
+            return hc;
+        }
+
+        [CLSCompliantAttribute(false)]
+        public static int GetHashCode(uint[] data, int off, int len)
+        {
+            if (data == null)
+                return 0;
+
+            int i = len;
+            int hc = i + 1;
+
+            while (--i >= 0)
+            {
+                hc *= 257;
+                hc ^= (int)data[off + i];
+            }
+
+            return hc;
+        }
+
+        public static byte[] Clone(
+            byte[] data)
+        {
+            return data == null ? null : (byte[])data.Clone();
+        }
+
+        public static byte[] Clone(
+            byte[] data, 
+            byte[] existing)
+        {
+            if (data == null)
+            {
+                return null;
+            }
+            if ((existing == null) || (existing.Length != data.Length))
+            {
+                return Clone(data);
+            }
+            Array.Copy(data, 0, existing, 0, existing.Length);
+            return existing;
+        }
+
+        public static int[] Clone(
+            int[] data)
+        {
+            return data == null ? null : (int[])data.Clone();
+        }
+
+        public static long[] Clone(long[] data)
+        {
+            return data == null ? null : (long[])data.Clone();
+        }
+
+        [CLSCompliantAttribute(false)]
+        public static ulong[] Clone(
+            ulong[] data)
+        {
+            return data == null ? null : (ulong[]) data.Clone();
+        }
+
+        [CLSCompliantAttribute(false)]
+        public static ulong[] Clone(
+            ulong[] data, 
+            ulong[] existing)
+        {
+            if (data == null)
+            {
+                return null;
+            }
+            if ((existing == null) || (existing.Length != data.Length))
+            {
+                return Clone(data);
+            }
+            Array.Copy(data, 0, existing, 0, existing.Length);
+            return existing;
+        }
+
+        public static bool Contains(byte[] a, byte n)
+        {
+            for (int i = 0; i < a.Length; ++i)
+            {
+                if (a[i] == n)
+                    return true;
+            }
+            return false;
+        }
+
+        public static bool Contains(short[] a, short n)
+        {
+            for (int i = 0; i < a.Length; ++i)
+            {
+                if (a[i] == n)
+                    return true;
+            }
+            return false;
+        }
+
+        public static bool Contains(int[] a, int n)
+        {
+            for (int i = 0; i < a.Length; ++i)
+            {
+                if (a[i] == n)
+                    return true;
+            }
+            return false;
+        }
+
+        public static void Fill(
+            byte[]	buf,
+            byte	b)
+        {
+            int i = buf.Length;
+            while (i > 0)
+            {
+                buf[--i] = b;
+            }
+        }
+
+        public static byte[] CopyOf(byte[] data, int newLength)
+        {
+            byte[] tmp = new byte[newLength];
+            Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length));
+            return tmp;
+        }
+
+        public static char[] CopyOf(char[] data, int newLength)
+        {
+            char[] tmp = new char[newLength];
+            Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length));
+            return tmp;
+        }
+
+        public static int[] CopyOf(int[] data, int newLength)
+        {
+            int[] tmp = new int[newLength];
+            Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length));
+            return tmp;
+        }
+
+        public static long[] CopyOf(long[] data, int newLength)
+        {
+            long[] tmp = new long[newLength];
+            Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length));
+            return tmp;
+        }
+
+        public static BigInteger[] CopyOf(BigInteger[] data, int newLength)
+        {
+            BigInteger[] tmp = new BigInteger[newLength];
+            Array.Copy(data, 0, tmp, 0, System.Math.Min(newLength, data.Length));
+            return tmp;
+        }
+
+        /**
+         * Make a copy of a range of bytes from the passed in data array. The range can
+         * extend beyond the end of the input array, in which case the return array will
+         * be padded with zeroes.
+         *
+         * @param data the array from which the data is to be copied.
+         * @param from the start index at which the copying should take place.
+         * @param to the final index of the range (exclusive).
+         *
+         * @return a new byte array containing the range given.
+         */
+        public static byte[] CopyOfRange(byte[] data, int from, int to)
+        {
+            int newLength = GetLength(from, to);
+            byte[] tmp = new byte[newLength];
+            Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from));
+            return tmp;
+        }
+
+        public static int[] CopyOfRange(int[] data, int from, int to)
+        {
+            int newLength = GetLength(from, to);
+            int[] tmp = new int[newLength];
+            Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from));
+            return tmp;
+        }
+
+        public static long[] CopyOfRange(long[] data, int from, int to)
+        {
+            int newLength = GetLength(from, to);
+            long[] tmp = new long[newLength];
+            Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from));
+            return tmp;
+        }
+
+        public static BigInteger[] CopyOfRange(BigInteger[] data, int from, int to)
+        {
+            int newLength = GetLength(from, to);
+            BigInteger[] tmp = new BigInteger[newLength];
+            Array.Copy(data, from, tmp, 0, System.Math.Min(newLength, data.Length - from));
+            return tmp;
+        }
+
+        private static int GetLength(int from, int to)
+        {
+            int newLength = to - from;
+            if (newLength < 0)
+                throw new ArgumentException(from + " > " + to);
+            return newLength;
+        }
+
+        public static byte[] Append(byte[] a, byte b)
+        {
+            if (a == null)
+                return new byte[] { b };
+
+            int length = a.Length;
+            byte[] result = new byte[length + 1];
+            Array.Copy(a, 0, result, 0, length);
+            result[length] = b;
+            return result;
+        }
+
+        public static short[] Append(short[] a, short b)
+        {
+            if (a == null)
+                return new short[] { b };
+
+            int length = a.Length;
+            short[] result = new short[length + 1];
+            Array.Copy(a, 0, result, 0, length);
+            result[length] = b;
+            return result;
+        }
+
+        public static int[] Append(int[] a, int b)
+        {
+            if (a == null)
+                return new int[] { b };
+
+            int length = a.Length;
+            int[] result = new int[length + 1];
+            Array.Copy(a, 0, result, 0, length);
+            result[length] = b;
+            return result;
+        }
+
+        public static byte[] Concatenate(byte[] a, byte[] b)
+        {
+            if (a == null)
+                return Clone(b);
+            if (b == null)
+                return Clone(a);
+
+            byte[] rv = new byte[a.Length + b.Length];
+            Array.Copy(a, 0, rv, 0, a.Length);
+            Array.Copy(b, 0, rv, a.Length, b.Length);
+            return rv;
+        }
+
+        public static int[] Concatenate(int[] a, int[] b)
+        {
+            if (a == null)
+                return Clone(b);
+            if (b == null)
+                return Clone(a);
+
+            int[] rv = new int[a.Length + b.Length];
+            Array.Copy(a, 0, rv, 0, a.Length);
+            Array.Copy(b, 0, rv, a.Length, b.Length);
+            return rv;
+        }
+
+        public static byte[] Prepend(byte[] a, byte b)
+        {
+            if (a == null)
+                return new byte[] { b };
+
+            int length = a.Length;
+            byte[] result = new byte[length + 1];
+            Array.Copy(a, 0, result, 1, length);
+            result[0] = b;
+            return result;
+        }
+
+        public static short[] Prepend(short[] a, short b)
+        {
+            if (a == null)
+                return new short[] { b };
+
+            int length = a.Length;
+            short[] result = new short[length + 1];
+            Array.Copy(a, 0, result, 1, length);
+            result[0] = b;
+            return result;
+        }
+
+        public static int[] Prepend(int[] a, int b)
+        {
+            if (a == null)
+                return new int[] { b };
+
+            int length = a.Length;
+            int[] result = new int[length + 1];
+            Array.Copy(a, 0, result, 1, length);
+            result[0] = b;
+            return result;
+        }
+
+        public static byte[] Reverse(byte[] a)
+        {
+            if (a == null)
+                return null;
+
+            int p1 = 0, p2 = a.Length;
+            byte[] result = new byte[p2];
+
+            while (--p2 >= 0)
+            {
+                result[p2] = a[p1++];
+            }
+
+            return result;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/BigIntegers.cs b/BouncyCastle.AxCrypt/src/util/BigIntegers.cs
new file mode 100644
index 0000000..f2d0425
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/BigIntegers.cs
@@ -0,0 +1,90 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Utilities
+{
+    /**
+     * BigInteger utilities.
+     */
+    public abstract class BigIntegers
+    {
+        private const int MaxIterations = 1000;
+
+        /**
+        * Return the passed in value as an unsigned byte array.
+        *
+        * @param value value to be converted.
+        * @return a byte array without a leading zero byte if present in the signed encoding.
+        */
+        public static byte[] AsUnsignedByteArray(
+            BigInteger n)
+        {
+            return n.ToByteArrayUnsigned();
+        }
+
+        /**
+         * Return the passed in value as an unsigned byte array of specified length, zero-extended as necessary.
+         *
+         * @param length desired length of result array.
+         * @param n value to be converted.
+         * @return a byte array of specified length, with leading zeroes as necessary given the size of n.
+         */
+        public static byte[] AsUnsignedByteArray(int length, BigInteger n)
+        {
+            byte[] bytes = n.ToByteArrayUnsigned();
+
+            if (bytes.Length > length)
+                throw new ArgumentException("standard length exceeded", "n");
+
+            if (bytes.Length == length)
+                return bytes;
+
+            byte[] tmp = new byte[length];
+            Array.Copy(bytes, 0, tmp, tmp.Length - bytes.Length, bytes.Length);
+            return tmp;
+        }
+
+        /**
+        * Return a random BigInteger not less than 'min' and not greater than 'max'
+        * 
+        * @param min the least value that may be generated
+        * @param max the greatest value that may be generated
+        * @param random the source of randomness
+        * @return a random BigInteger value in the range [min,max]
+        */
+        public static BigInteger CreateRandomInRange(
+            BigInteger		min,
+            BigInteger		max,
+            // TODO Should have been just Random class
+            SecureRandom	random)
+        {
+            int cmp = min.CompareTo(max);
+            if (cmp >= 0)
+            {
+                if (cmp > 0)
+                    throw new ArgumentException("'min' may not be greater than 'max'");
+
+                return min;
+            }
+
+            if (min.BitLength > max.BitLength / 2)
+            {
+                return CreateRandomInRange(BigInteger.Zero, max.Subtract(min), random).Add(min);
+            }
+
+            for (int i = 0; i < MaxIterations; ++i)
+            {
+                BigInteger x = new BigInteger(max.BitLength, random);
+                if (x.CompareTo(min) >= 0 && x.CompareTo(max) <= 0)
+                {
+                    return x;
+                }
+            }
+
+            // fall back to a faster (restricted) method
+            return new BigInteger(max.Subtract(min).BitLength - 1, random).Add(min);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/Enums.cs b/BouncyCastle.AxCrypt/src/util/Enums.cs
new file mode 100644
index 0000000..d943acd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Enums.cs
@@ -0,0 +1,69 @@
+using System;
+using System.Text;
+
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
+using System.Collections;
+using System.Reflection;
+#endif
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Utilities
+{
+    internal abstract class Enums
+    {
+        internal static Enum GetEnumValue(System.Type enumType, string s)
+        {
+            if (!enumType.IsEnum)
+                throw new ArgumentException("Not an enumeration type", "enumType");
+
+            // We only want to parse single named constants
+            if (s.Length > 0 && char.IsLetter(s[0]) && s.IndexOf(',') < 0)
+            {
+                s = s.Replace('-', '_');
+                s = s.Replace('/', '_');
+
+#if NETCF_1_0
+                FieldInfo field = enumType.GetField(s, BindingFlags.Static | BindingFlags.Public);
+                if (field != null)
+                {
+                    return (Enum)field.GetValue(null);
+                }
+#else
+                return (Enum)Enum.Parse(enumType, s, false);
+#endif		
+            }
+
+            throw new ArgumentException();
+        }
+
+        internal static Array GetEnumValues(System.Type enumType)
+        {
+            if (!enumType.IsEnum)
+                throw new ArgumentException("Not an enumeration type", "enumType");
+
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT && !PCL
+            IList result = Platform.CreateArrayList();
+            FieldInfo[] fields = enumType.GetFields(BindingFlags.Static | BindingFlags.Public);
+            foreach (FieldInfo field in fields)
+            {
+                // Note: Argument to GetValue() ignored since the fields are static,
+                //     but Silverlight for Windows Phone throws exception if we pass null
+                result.Add(field.GetValue(enumType));
+            }
+            object[] arr = new object[result.Count];
+            result.CopyTo(arr, 0);
+            return arr;
+#else
+            return Enum.GetValues(enumType);
+#endif
+        }
+
+        internal static Enum GetArbitraryValue(System.Type enumType)
+        {
+            Array values = GetEnumValues(enumType);
+            int pos = (int)(DateTimeUtilities.CurrentUnixMs() & int.MaxValue) % values.Length;
+            return (Enum)values.GetValue(pos);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/IMemoable.cs b/BouncyCastle.AxCrypt/src/util/IMemoable.cs
new file mode 100644
index 0000000..cc8a2e5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/IMemoable.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+	public interface IMemoable
+	{
+		/// <summary>
+		/// Produce a copy of this object with its configuration and in its current state.
+		/// </summary>
+		/// <remarks>
+		/// The returned object may be used simply to store the state, or may be used as a similar object
+		/// starting from the copied state.
+		/// </remarks>
+		IMemoable Copy();
+
+		/// <summary>
+		/// Restore a copied object state into this object.
+		/// </summary>
+		/// <remarks>
+		/// Implementations of this method <em>should</em> try to avoid or minimise memory allocation to perform the reset.
+		/// </remarks>
+		/// <param name="other">an object originally {@link #copy() copied} from an object of the same type as this instance.</param>
+		/// <exception cref="InvalidCastException">if the provided object is not of the correct type.</exception>
+		/// <exception cref="MemoableResetException">if the <b>other</b> parameter is in some other way invalid.</exception>
+		void Reset(IMemoable other);
+	}
+
+}
+
diff --git a/BouncyCastle.AxCrypt/src/util/Integers.cs b/BouncyCastle.AxCrypt/src/util/Integers.cs
new file mode 100644
index 0000000..ccbf872
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Integers.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+    public abstract class Integers
+    {
+        public static int RotateLeft(int i, int distance)
+        {
+            return (i << distance) ^ (int)((uint)i >> -distance);
+        }
+
+        public static int RotateRight(int i, int distance)
+        {
+            return (int)((uint)i >> distance) ^ (i << -distance);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/MemoableResetException.cs b/BouncyCastle.AxCrypt/src/util/MemoableResetException.cs
new file mode 100644
index 0000000..99554f6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/MemoableResetException.cs
@@ -0,0 +1,27 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+    /**
+     * Exception to be thrown on a failure to reset an object implementing Memoable.
+     * <p>
+     * The exception extends InvalidCastException to enable users to have a single handling case,
+     * only introducing specific handling of this one if required.
+     * </p>
+     */
+    public class MemoableResetException
+        : InvalidCastException
+    {
+        /**
+         * Basic Constructor.
+         *
+         * @param msg message to be associated with this exception.
+         */
+        public MemoableResetException(string msg)
+            : base(msg)
+        {
+        }
+    }
+
+}
+
diff --git a/BouncyCastle.AxCrypt/src/util/Platform.cs b/BouncyCastle.AxCrypt/src/util/Platform.cs
new file mode 100644
index 0000000..17c2786
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Platform.cs
@@ -0,0 +1,179 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+#if SILVERLIGHT
+using System.Collections.Generic;
+#else
+using System.Collections;
+#endif
+
+namespace Org.BouncyCastle.Utilities
+{
+    internal abstract class Platform
+    {
+#if NETCF_1_0 || NETCF_2_0
+        private static string GetNewLine()
+        {
+            MemoryStream buf = new MemoryStream();
+            StreamWriter w = new StreamWriter(buf, Encoding.UTF8);
+            w.WriteLine();
+            w.Close();
+            byte[] bs = buf.ToArray();
+            return Encoding.UTF8.GetString(bs, 0, bs.Length);
+        }
+#else
+        private static string GetNewLine()
+        {
+            return Environment.NewLine;
+        }
+#endif
+
+        internal static int CompareIgnoreCase(string a, string b)
+        {
+#if SILVERLIGHT
+            return String.Compare(a, b, StringComparison.OrdinalIgnoreCase);
+#else
+            return String.Compare(a, b, true);
+#endif
+        }
+
+#if NETCF_1_0 || NETCF_2_0 || SILVERLIGHT
+        internal static string GetEnvironmentVariable(
+            string variable)
+        {
+            return null;
+        }
+#else
+        internal static string GetEnvironmentVariable(
+            string variable)
+        {
+            try
+            {
+                return Environment.GetEnvironmentVariable(variable);
+            }
+            catch (System.Security.SecurityException)
+            {
+                // We don't have the required permission to read this environment variable,
+                // which is fine, just act as if it's not set
+                return null;
+            }
+        }
+#endif
+
+#if NETCF_1_0
+        internal static Exception CreateNotImplementedException(
+            string message)
+        {
+            return new Exception("Not implemented: " + message);
+        }
+
+        internal static bool Equals(
+            object	a,
+            object	b)
+        {
+            return a == b || (a != null && b != null && a.Equals(b));
+        }
+#else
+        internal static Exception CreateNotImplementedException(
+            string message)
+        {
+            return new NotImplementedException(message);
+        }
+#endif
+
+#if SILVERLIGHT
+        internal static System.Collections.IList CreateArrayList()
+        {
+            return new List<object>();
+        }
+        internal static System.Collections.IList CreateArrayList(int capacity)
+        {
+            return new List<object>(capacity);
+        }
+        internal static System.Collections.IList CreateArrayList(System.Collections.ICollection collection)
+        {
+            System.Collections.IList result = new List<object>(collection.Count);
+            foreach (object o in collection)
+            {
+                result.Add(o);
+            }
+            return result;
+        }
+        internal static System.Collections.IList CreateArrayList(System.Collections.IEnumerable collection)
+        {
+            System.Collections.IList result = new List<object>();
+            foreach (object o in collection)
+            {
+                result.Add(o);
+            }
+            return result;
+        }
+        internal static System.Collections.IDictionary CreateHashtable()
+        {
+            return new Dictionary<object, object>();
+        }
+        internal static System.Collections.IDictionary CreateHashtable(int capacity)
+        {
+            return new Dictionary<object, object>(capacity);
+        }
+        internal static System.Collections.IDictionary CreateHashtable(System.Collections.IDictionary dictionary)
+        {
+            System.Collections.IDictionary result = new Dictionary<object, object>(dictionary.Count);
+            foreach (System.Collections.DictionaryEntry entry in dictionary)
+            {
+                result.Add(entry.Key, entry.Value);
+            }
+            return result;
+        }
+#else
+        internal static System.Collections.IList CreateArrayList()
+        {
+            return new ArrayList();
+        }
+        internal static System.Collections.IList CreateArrayList(int capacity)
+        {
+            return new ArrayList(capacity);
+        }
+        internal static System.Collections.IList CreateArrayList(System.Collections.ICollection collection)
+        {
+            return new ArrayList(collection);
+        }
+        internal static System.Collections.IList CreateArrayList(System.Collections.IEnumerable collection)
+        {
+            ArrayList result = new ArrayList();
+            foreach (object o in collection)
+            {
+                result.Add(o);
+            }
+            return result;
+        }
+        internal static System.Collections.IDictionary CreateHashtable()
+        {
+            return new Hashtable();
+        }
+        internal static System.Collections.IDictionary CreateHashtable(int capacity)
+        {
+            return new Hashtable(capacity);
+        }
+        internal static System.Collections.IDictionary CreateHashtable(System.Collections.IDictionary dictionary)
+        {
+            return new Hashtable(dictionary);
+        }
+#endif
+
+        internal static string ToLowerInvariant(string s)
+        {
+            
+            return s.ToLowerInvariant();
+        }
+
+        internal static string ToUpperInvariant(string s)
+        {
+            return s.ToUpperInvariant();
+        }
+
+        internal static readonly string NewLine = GetNewLine();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/Strings.cs b/BouncyCastle.AxCrypt/src/util/Strings.cs
new file mode 100644
index 0000000..a6080f4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Strings.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Utilities
+{
+    /// <summary> General string utilities.</summary>
+    public abstract class Strings
+    {
+        internal static bool IsOneOf(string s, params string[] candidates)
+        {
+            foreach (string candidate in candidates)
+            {
+                if (s == candidate)
+                    return true;
+            }
+            return false;
+        }
+
+        public static string FromByteArray(
+            byte[] bs)
+        {
+            char[] cs = new char[bs.Length];
+            for (int i = 0; i < cs.Length; ++i)
+            {
+                cs[i] = Convert.ToChar(bs[i]);
+            }
+            return new string(cs);
+        }
+
+        public static byte[] ToByteArray(
+            char[] cs)
+        {
+            byte[] bs = new byte[cs.Length];
+            for (int i = 0; i < bs.Length; ++i)
+            {
+                bs[i] = Convert.ToByte(cs[i]);
+            }
+            return bs;
+        }
+
+        public static byte[] ToByteArray(
+            string s)
+        {
+            byte[] bs = new byte[s.Length];
+            for (int i = 0; i < bs.Length; ++i)
+            {
+                bs[i] = Convert.ToByte(s[i]);
+            }
+            return bs;
+        }
+
+        public static string FromAsciiByteArray(
+            byte[] bytes)
+        {
+#if SILVERLIGHT
+            // TODO Check for non-ASCII bytes in input?
+            return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
+#else
+            return Encoding.ASCII.GetString(bytes, 0, bytes.Length);
+#endif
+        }
+
+        public static byte[] ToAsciiByteArray(
+            char[] cs)
+        {
+#if SILVERLIGHT
+            // TODO Check for non-ASCII characters in input?
+            return Encoding.UTF8.GetBytes(cs);
+#else
+            return Encoding.ASCII.GetBytes(cs);
+#endif
+        }
+
+        public static byte[] ToAsciiByteArray(
+            string s)
+        {
+#if SILVERLIGHT
+            // TODO Check for non-ASCII characters in input?
+            return Encoding.UTF8.GetBytes(s);
+#else
+            return Encoding.ASCII.GetBytes(s);
+#endif
+        }
+
+        public static string FromUtf8ByteArray(
+            byte[] bytes)
+        {
+            return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
+        }
+
+        public static byte[] ToUtf8ByteArray(
+            char[] cs)
+        {
+            return Encoding.UTF8.GetBytes(cs);
+        }
+
+        public static byte[] ToUtf8ByteArray(
+            string s)
+        {
+            return Encoding.UTF8.GetBytes(s);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/Times.cs b/BouncyCastle.AxCrypt/src/util/Times.cs
new file mode 100644
index 0000000..99a78d2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/Times.cs
@@ -0,0 +1,14 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities
+{
+    public sealed class Times
+    {
+        private static long NanosecondsPerTick = 100L;
+
+        public static long NanoTime()
+        {
+            return DateTime.UtcNow.Ticks * NanosecondsPerTick;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/CollectionUtilities.cs b/BouncyCastle.AxCrypt/src/util/collections/CollectionUtilities.cs
new file mode 100644
index 0000000..18fcb67
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/CollectionUtilities.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections;
+using System.Text;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+    public abstract class CollectionUtilities
+    {
+        public static void AddRange(IList to, IEnumerable range)
+        {
+            foreach (object o in range)
+            {
+                to.Add(o);
+            }
+        }
+
+        public static bool CheckElementsAreOfType(IEnumerable e, Type t)
+        {
+            foreach (object o in e)
+            {
+                if (!t.IsInstanceOfType(o))
+                    return false;
+            }
+            return true;
+        }
+
+        public static IDictionary ReadOnly(IDictionary d)
+        {
+            return new UnmodifiableDictionaryProxy(d);
+        }
+
+        public static IList ReadOnly(IList l)
+        {
+            return new UnmodifiableListProxy(l);
+        }
+
+        public static ISet ReadOnly(ISet s)
+        {
+            return new UnmodifiableSetProxy(s);
+        }
+
+        public static string ToString(IEnumerable c)
+        {
+            StringBuilder sb = new StringBuilder("[");
+
+            IEnumerator e = c.GetEnumerator();
+
+            if (e.MoveNext())
+            {
+                sb.Append(e.Current.ToString());
+
+                while (e.MoveNext())
+                {
+                    sb.Append(", ");
+                    sb.Append(e.Current.ToString());
+                }
+            }
+
+            sb.Append(']');
+
+            return sb.ToString();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/EmptyEnumerable.cs b/BouncyCastle.AxCrypt/src/util/collections/EmptyEnumerable.cs
new file mode 100644
index 0000000..a61a078
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/EmptyEnumerable.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public sealed class EmptyEnumerable
+		: IEnumerable
+	{
+		public static readonly IEnumerable Instance = new EmptyEnumerable();
+
+		private EmptyEnumerable()
+		{
+		}
+
+		public IEnumerator GetEnumerator()
+		{
+			return EmptyEnumerator.Instance;
+		}
+	}
+
+	public sealed class EmptyEnumerator
+		: IEnumerator
+	{
+		public static readonly IEnumerator Instance = new EmptyEnumerator();
+
+		private EmptyEnumerator()
+		{
+		}
+
+		public bool MoveNext()
+		{
+			return false;
+		}
+
+		public void Reset()
+		{
+		}
+
+		public object Current
+		{
+			get { throw new InvalidOperationException("No elements"); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/EnumerableProxy.cs b/BouncyCastle.AxCrypt/src/util/collections/EnumerableProxy.cs
new file mode 100644
index 0000000..9eec4af
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/EnumerableProxy.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public sealed class EnumerableProxy
+		: IEnumerable
+	{
+		private readonly IEnumerable inner;
+
+		public EnumerableProxy(
+			IEnumerable inner)
+		{
+			if (inner == null)
+				throw new ArgumentNullException("inner");
+
+			this.inner = inner;
+		}
+
+		public IEnumerator GetEnumerator()
+		{
+			return inner.GetEnumerator();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/HashSet.cs b/BouncyCastle.AxCrypt/src/util/collections/HashSet.cs
new file mode 100644
index 0000000..1facb58
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/HashSet.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public class HashSet
+		: ISet
+	{
+		private readonly IDictionary impl = Platform.CreateHashtable();
+
+		public HashSet()
+		{
+		}
+
+		public HashSet(IEnumerable s)
+		{
+			foreach (object o in s)
+			{
+				Add(o);
+			}
+		}
+
+		public virtual void Add(object o)
+		{
+			impl[o] = null;
+		}
+
+		public virtual void AddAll(IEnumerable e)
+		{
+			foreach (object o in e)
+			{
+				Add(o);
+			}
+		}
+
+		public virtual void Clear()
+		{
+			impl.Clear();
+		}
+
+		public virtual bool Contains(object o)
+		{
+			return impl.Contains(o);
+		}
+
+		public virtual void CopyTo(Array array, int index)
+		{
+			impl.Keys.CopyTo(array, index);
+		}
+
+		public virtual int Count
+		{
+			get { return impl.Count; }
+		}
+
+		public virtual IEnumerator GetEnumerator()
+		{
+			return impl.Keys.GetEnumerator();
+		}
+
+		public virtual bool IsEmpty
+		{
+			get { return impl.Count == 0; }
+		}
+
+		public virtual bool IsFixedSize
+		{
+			get { return impl.IsFixedSize; }
+		}
+
+		public virtual bool IsReadOnly
+		{
+			get { return impl.IsReadOnly; }
+		}
+
+		public virtual bool IsSynchronized
+		{
+			get { return impl.IsSynchronized; }
+		}
+
+		public virtual void Remove(object o)
+		{
+			impl.Remove(o);
+		}
+
+		public virtual void RemoveAll(IEnumerable e)
+		{
+			foreach (object o in e)
+			{
+				Remove(o);
+			}
+		}
+
+		public virtual object SyncRoot
+		{
+			get { return impl.SyncRoot; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/ISet.cs b/BouncyCastle.AxCrypt/src/util/collections/ISet.cs
new file mode 100644
index 0000000..1f8edba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/ISet.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public interface ISet
+		: ICollection
+	{
+		void Add(object o);
+		void AddAll(IEnumerable e);
+		void Clear();
+		bool Contains(object o);
+		bool IsEmpty { get; }
+		bool IsFixedSize { get; }
+		bool IsReadOnly { get; }
+		void Remove(object o);
+		void RemoveAll(IEnumerable e);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/LinkedDictionary.cs b/BouncyCastle.AxCrypt/src/util/collections/LinkedDictionary.cs
new file mode 100644
index 0000000..933d38d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/LinkedDictionary.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public class LinkedDictionary
+		: IDictionary
+	{
+		internal readonly IDictionary hash = Platform.CreateHashtable();
+		internal readonly IList keys = Platform.CreateArrayList();
+
+		public LinkedDictionary()
+		{
+		}
+
+		public virtual void Add(object k, object v)
+		{
+			hash.Add(k, v);
+			keys.Add(k);
+		}
+
+		public virtual void Clear()
+		{
+			hash.Clear();
+			keys.Clear();
+		}
+
+		public virtual bool Contains(object k)
+		{
+			return hash.Contains(k);
+		}
+
+		public virtual void CopyTo(Array array, int index)
+		{
+			foreach (object k in keys)
+			{
+				array.SetValue(hash[k], index++);
+			}
+		}
+
+		public virtual int Count
+		{
+			get { return hash.Count; }
+		}
+
+		IEnumerator IEnumerable.GetEnumerator()
+		{
+			return GetEnumerator();
+		}
+
+		public virtual IDictionaryEnumerator GetEnumerator()
+		{
+			return new LinkedDictionaryEnumerator(this);
+		}
+
+		public virtual void Remove(object k)
+		{
+			hash.Remove(k);
+			keys.Remove(k);
+		}
+
+		public virtual bool IsFixedSize
+		{
+			get { return false; }
+		}
+
+		public virtual bool IsReadOnly
+		{
+			get { return false; }
+		}
+
+		public virtual bool IsSynchronized
+		{
+			get { return false; }
+		}
+
+		public virtual object SyncRoot
+		{
+			get { return false; }
+		}
+
+		public virtual ICollection Keys
+		{
+            get { return Platform.CreateArrayList(keys); }
+		}
+
+		public virtual ICollection Values
+		{
+			// NB: Order has to be the same as for Keys property
+			get
+			{
+                IList values = Platform.CreateArrayList(keys.Count);
+				foreach (object k in keys)
+				{
+					values.Add(hash[k]);
+				}
+				return values;
+			}
+		}
+
+		public virtual object this[object k]
+		{
+			get
+			{
+				return hash[k];
+			}
+			set
+			{
+				if (!hash.Contains(k))
+					keys.Add(k);
+				hash[k] = value;
+			}
+		}
+	}
+
+	internal class LinkedDictionaryEnumerator : IDictionaryEnumerator
+	{
+		private readonly LinkedDictionary parent;
+		private int pos = -1;
+
+		internal LinkedDictionaryEnumerator(LinkedDictionary parent)
+		{
+			this.parent = parent;
+		}
+
+		public virtual object Current
+		{
+			get { return Entry; }
+		}
+
+		public virtual DictionaryEntry Entry
+		{
+			get
+			{
+				object k = CurrentKey;
+				return new DictionaryEntry(k, parent.hash[k]);
+			}
+		}
+
+		public virtual object Key
+		{
+			get
+			{
+				return CurrentKey;
+			}
+		}
+
+		public virtual bool MoveNext()
+		{
+			if (pos >= parent.keys.Count)
+				return false;
+			return ++pos < parent.keys.Count;
+		}
+
+		public virtual void Reset()
+		{
+			this.pos = -1;
+		}
+
+		public virtual object Value
+		{
+			get
+			{
+				return parent.hash[CurrentKey];
+			}
+		}
+
+		private object CurrentKey
+		{
+			get
+			{
+				if (pos < 0 || pos >= parent.keys.Count)
+					throw new InvalidOperationException();
+				return parent.keys[pos];
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionary.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionary.cs
new file mode 100644
index 0000000..0bdf70a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionary.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public abstract class UnmodifiableDictionary
+		: IDictionary
+	{
+		protected UnmodifiableDictionary()
+		{
+		}
+
+		public virtual void Add(object k, object v)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void Clear()
+		{
+			throw new NotSupportedException();
+		}
+
+		public abstract bool Contains(object k);
+
+		public abstract void CopyTo(Array array, int index);
+
+		public abstract int Count { get; }
+
+		IEnumerator IEnumerable.GetEnumerator()
+		{
+			return GetEnumerator();
+		}
+
+		public abstract IDictionaryEnumerator GetEnumerator();
+
+		public virtual void Remove(object k)
+		{
+			throw new NotSupportedException();
+		}
+
+		public abstract bool IsFixedSize { get; }
+
+		public virtual bool IsReadOnly
+		{
+			get { return true; }
+		}
+
+		public abstract bool IsSynchronized { get; }
+
+		public abstract object SyncRoot { get; }
+
+		public abstract ICollection Keys { get; }
+
+		public abstract ICollection Values { get; }
+
+		public virtual object this[object k]
+		{
+			get { return GetValue(k); }
+			set { throw new NotSupportedException(); }
+		}
+
+		protected abstract object GetValue(object k);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionaryProxy.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionaryProxy.cs
new file mode 100644
index 0000000..0fca909
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableDictionaryProxy.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public class UnmodifiableDictionaryProxy
+		: UnmodifiableDictionary
+	{
+		private readonly IDictionary d;
+
+		public UnmodifiableDictionaryProxy(IDictionary d)
+		{
+			this.d = d;
+		}
+
+		public override bool Contains(object k)
+		{
+			return d.Contains(k);
+		}
+
+		public override void CopyTo(Array array, int index)
+		{
+			d.CopyTo(array, index);
+		}
+
+		public override int Count
+		{
+			get { return d.Count; }
+		}
+
+		public override IDictionaryEnumerator GetEnumerator()
+		{
+			return d.GetEnumerator();
+		}
+
+		public override bool IsFixedSize
+		{
+			get { return d.IsFixedSize; }
+		}
+
+		public override bool IsSynchronized
+		{
+			get { return d.IsSynchronized; }
+		}
+
+		public override object SyncRoot
+		{
+			get { return d.SyncRoot; }
+		}
+
+		public override ICollection Keys
+		{
+			get { return d.Keys; }
+		}
+
+		public override ICollection Values
+		{
+			get { return d.Values; }
+		}
+
+		protected override object GetValue(object k)
+		{
+			return d[k];
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableList.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableList.cs
new file mode 100644
index 0000000..28e49ea
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableList.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public abstract class UnmodifiableList
+		: IList
+	{
+		protected UnmodifiableList()
+		{
+		}
+
+		public virtual int Add(object o)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void Clear()
+		{
+			throw new NotSupportedException();
+		}
+
+		public abstract bool Contains(object o);
+
+		public abstract void CopyTo(Array array, int index);
+
+		public abstract int Count { get; }
+
+		public abstract IEnumerator GetEnumerator();
+
+		public abstract int IndexOf(object o);
+
+		public virtual void Insert(int i, object o)
+		{
+			throw new NotSupportedException();
+		}
+
+		public abstract bool IsFixedSize { get; }
+
+		public virtual bool IsReadOnly
+		{
+			get { return true; }
+		}
+
+		public abstract bool IsSynchronized { get; }
+
+		public virtual void Remove(object o)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void RemoveAt(int i)
+		{
+			throw new NotSupportedException();
+		}
+
+		public abstract object SyncRoot { get; }
+		
+		public virtual object this[int i]
+		{
+			get { return GetValue(i); }
+			set { throw new NotSupportedException(); }
+		}
+
+		protected abstract object GetValue(int i);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableListProxy.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableListProxy.cs
new file mode 100644
index 0000000..9d00737
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableListProxy.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public class UnmodifiableListProxy
+		: UnmodifiableList
+	{
+		private readonly IList l;
+
+		public UnmodifiableListProxy(IList l)
+		{
+			this.l = l;
+		}
+
+		public override bool Contains(object o)
+		{
+			return l.Contains(o);
+		}
+
+		public override void CopyTo(Array array, int index)
+		{
+			l.CopyTo(array, index);
+		}
+
+		public override int Count
+		{
+			get { return l.Count; }
+		}
+
+		public override IEnumerator GetEnumerator()
+		{
+			return l.GetEnumerator();
+		}
+
+		public override int IndexOf(object o)
+		{
+			return l.IndexOf(o);
+		}
+
+		public override bool IsFixedSize
+		{
+			get { return l.IsFixedSize; }
+		}
+
+		public override bool IsSynchronized
+		{
+			get { return l.IsSynchronized; }
+		}
+
+		public override object SyncRoot
+		{
+			get { return l.SyncRoot; }
+		}
+
+		protected override object GetValue(int i)
+		{
+			return l[i];
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSet.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSet.cs
new file mode 100644
index 0000000..8792815
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSet.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public abstract class UnmodifiableSet
+		: ISet
+	{
+		protected UnmodifiableSet()
+		{
+		}
+
+		public virtual void Add(object o)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void AddAll(IEnumerable e)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void Clear()
+		{
+			throw new NotSupportedException();
+		}
+		
+		public abstract bool Contains(object o);
+
+		public abstract void CopyTo(Array array, int index);
+
+		public abstract int Count { get; }
+
+		public abstract IEnumerator GetEnumerator();
+
+		public abstract bool IsEmpty { get; }
+
+		public abstract bool IsFixedSize { get; }
+
+		public virtual bool IsReadOnly
+		{
+			get { return true; }
+		}
+
+		public abstract bool IsSynchronized { get; }
+
+		public abstract object SyncRoot { get; }
+
+		public virtual void Remove(object o)
+		{
+			throw new NotSupportedException();
+		}
+
+		public virtual void RemoveAll(IEnumerable e)
+		{
+			throw new NotSupportedException();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSetProxy.cs b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSetProxy.cs
new file mode 100644
index 0000000..e119e29
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/collections/UnmodifiableSetProxy.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+	public class UnmodifiableSetProxy
+		: UnmodifiableSet
+	{
+		private readonly ISet s;
+
+		public UnmodifiableSetProxy (ISet s)
+		{
+			this.s = s;
+		}
+
+		public override bool Contains(object o)
+		{
+			return s.Contains(o);
+		}
+
+		public override void CopyTo(Array array, int index)
+		{
+			s.CopyTo(array, index);
+		}
+
+		public override int Count
+		{
+			get { return s.Count; }
+		}
+
+		public override IEnumerator GetEnumerator()
+		{
+			return s.GetEnumerator();
+		}
+
+		public override bool IsEmpty
+		{
+			get { return s.IsEmpty; }
+		}
+
+		public override bool IsFixedSize
+		{
+			get { return s.IsFixedSize; }
+		}
+
+		public override bool IsSynchronized
+		{
+			get { return s.IsSynchronized; }
+		}
+
+		public override object SyncRoot
+		{
+			get { return s.SyncRoot; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/date/DateTimeObject.cs b/BouncyCastle.AxCrypt/src/util/date/DateTimeObject.cs
new file mode 100644
index 0000000..793376b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/date/DateTimeObject.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Date
+{
+	public sealed class DateTimeObject
+	{
+		private readonly DateTime dt;
+
+		public DateTimeObject(
+			DateTime dt)
+		{
+			this.dt = dt;
+		}
+
+		public DateTime Value
+		{
+			get { return dt; }
+		}
+
+		public override string ToString()
+		{
+			return dt.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/date/DateTimeUtilities.cs b/BouncyCastle.AxCrypt/src/util/date/DateTimeUtilities.cs
new file mode 100644
index 0000000..311ad5d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/date/DateTimeUtilities.cs
@@ -0,0 +1,47 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Date
+{
+	public class DateTimeUtilities
+	{
+		public static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1);
+
+		private DateTimeUtilities()
+		{
+		}
+
+		/// <summary>
+		/// Return the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC) for a given DateTime value.
+		/// </summary>
+		/// <param name="dateTime">A UTC DateTime value not before epoch.</param>
+		/// <returns>Number of whole milliseconds after epoch.</returns>
+		/// <exception cref="ArgumentException">'dateTime' is before epoch.</exception>
+		public static long DateTimeToUnixMs(
+			DateTime dateTime)
+		{
+			if (dateTime.CompareTo(UnixEpoch) < 0)
+				throw new ArgumentException("DateTime value may not be before the epoch", "dateTime");
+
+			return (dateTime.Ticks - UnixEpoch.Ticks) / TimeSpan.TicksPerMillisecond;
+		}
+
+		/// <summary>
+		/// Create a DateTime value from the number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+		/// </summary>
+		/// <param name="unixMs">Number of milliseconds since the epoch.</param>
+		/// <returns>A UTC DateTime value</returns>
+		public static DateTime UnixMsToDateTime(
+			long unixMs)
+		{
+			return new DateTime(unixMs * TimeSpan.TicksPerMillisecond + UnixEpoch.Ticks);
+		}
+
+		/// <summary>
+		/// Return the current number of milliseconds since the Unix epoch (1 Jan., 1970 UTC).
+		/// </summary>
+		public static long CurrentUnixMs()
+		{
+			return DateTimeToUnixMs(DateTime.UtcNow);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/Base64.cs b/BouncyCastle.AxCrypt/src/util/encoders/Base64.cs
new file mode 100644
index 0000000..ccecd8d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/Base64.cs
@@ -0,0 +1,120 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    public sealed class Base64
+    {
+        private Base64()
+        {
+        }
+
+        public static string ToBase64String(
+            byte[] data)
+        {
+            return Convert.ToBase64String(data, 0, data.Length);
+        }
+
+        public static string ToBase64String(
+            byte[] data,
+            int off,
+            int length)
+        {
+            return Convert.ToBase64String(data, off, length);
+        }
+
+        /**
+         * encode the input data producing a base 64 encoded byte array.
+         *
+         * @return a byte array containing the base 64 encoded data.
+         */
+        public static byte[] Encode(
+            byte[] data)
+        {
+            return Encode(data, 0, data.Length);
+        }
+
+        /**
+         * encode the input data producing a base 64 encoded byte array.
+         *
+         * @return a byte array containing the base 64 encoded data.
+         */
+        public static byte[] Encode(
+            byte[] data,
+            int off,
+            int length)
+        {
+            string s = Convert.ToBase64String(data, off, length);
+            return Strings.ToAsciiByteArray(s);
+        }
+
+        /**
+         * Encode the byte data to base 64 writing it to the given output stream.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Encode(
+            byte[]	data,
+            Stream	outStream)
+        {
+            byte[] encoded = Encode(data);
+            outStream.Write(encoded, 0, encoded.Length);
+            return encoded.Length;
+        }
+
+        /**
+         * Encode the byte data to base 64 writing it to the given output stream.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Encode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            byte[] encoded = Encode(data, off, length);
+            outStream.Write(encoded, 0, encoded.Length);
+            return encoded.Length;
+        }
+
+        /**
+         * decode the base 64 encoded input data. It is assumed the input data is valid.
+         *
+         * @return a byte array representing the decoded data.
+         */
+        public static byte[] Decode(
+            byte[] data)
+        {
+            string s = Strings.FromAsciiByteArray(data);
+            return Convert.FromBase64String(s);
+        }
+
+        /**
+         * decode the base 64 encoded string data - whitespace will be ignored.
+         *
+         * @return a byte array representing the decoded data.
+         */
+        public static byte[] Decode(
+            string data)
+        {
+            return Convert.FromBase64String(data);
+        }
+
+        /**
+         * decode the base 64 encoded string data writing it to the given output stream,
+         * whitespace characters will be ignored.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Decode(
+            string	data,
+            Stream	outStream)
+        {
+            byte[] decoded = Decode(data);
+            outStream.Write(decoded, 0, decoded.Length);
+            return decoded.Length;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/Base64Encoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/Base64Encoder.cs
new file mode 100644
index 0000000..7b53df2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/Base64Encoder.cs
@@ -0,0 +1,324 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    public class Base64Encoder
+        : IEncoder
+    {
+        protected readonly byte[] encodingTable =
+        {
+            (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G',
+            (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N',
+            (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U',
+            (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z',
+            (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g',
+            (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n',
+            (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u',
+            (byte)'v',
+            (byte)'w', (byte)'x', (byte)'y', (byte)'z',
+            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6',
+            (byte)'7', (byte)'8', (byte)'9',
+            (byte)'+', (byte)'/'
+        };
+
+        protected byte padding = (byte)'=';
+
+        /*
+        * set up the decoding table.
+        */
+        protected readonly byte[] decodingTable = new byte[128];
+
+        protected void InitialiseDecodingTable()
+        {
+            Arrays.Fill(decodingTable, (byte)0xff);
+
+            for (int i = 0; i < encodingTable.Length; i++)
+            {
+                decodingTable[encodingTable[i]] = (byte)i;
+            }
+        }
+
+        public Base64Encoder()
+        {
+            InitialiseDecodingTable();
+        }
+
+        /**
+        * encode the input data producing a base 64 output stream.
+        *
+        * @return the number of bytes produced.
+        */
+        public int Encode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            int modulus = length % 3;
+            int dataLength = (length - modulus);
+            int a1, a2, a3;
+
+            for (int i = off; i < off + dataLength; i += 3)
+            {
+                a1 = data[i] & 0xff;
+                a2 = data[i + 1] & 0xff;
+                a3 = data[i + 2] & 0xff;
+
+                outStream.WriteByte(encodingTable[(int) ((uint) a1 >> 2) & 0x3f]);
+                outStream.WriteByte(encodingTable[((a1 << 4) | (int) ((uint) a2 >> 4)) & 0x3f]);
+                outStream.WriteByte(encodingTable[((a2 << 2) | (int) ((uint) a3 >> 6)) & 0x3f]);
+                outStream.WriteByte(encodingTable[a3 & 0x3f]);
+            }
+
+            /*
+            * process the tail end.
+            */
+            int b1, b2, b3;
+            int d1, d2;
+
+            switch (modulus)
+            {
+                case 0:        /* nothing left to do */
+                    break;
+                case 1:
+                    d1 = data[off + dataLength] & 0xff;
+                    b1 = (d1 >> 2) & 0x3f;
+                    b2 = (d1 << 4) & 0x3f;
+
+                    outStream.WriteByte(encodingTable[b1]);
+                    outStream.WriteByte(encodingTable[b2]);
+                    outStream.WriteByte(padding);
+                    outStream.WriteByte(padding);
+                    break;
+                case 2:
+                    d1 = data[off + dataLength] & 0xff;
+                    d2 = data[off + dataLength + 1] & 0xff;
+
+                    b1 = (d1 >> 2) & 0x3f;
+                    b2 = ((d1 << 4) | (d2 >> 4)) & 0x3f;
+                    b3 = (d2 << 2) & 0x3f;
+
+                    outStream.WriteByte(encodingTable[b1]);
+                    outStream.WriteByte(encodingTable[b2]);
+                    outStream.WriteByte(encodingTable[b3]);
+                    outStream.WriteByte(padding);
+                    break;
+            }
+
+            return (dataLength / 3) * 4 + ((modulus == 0) ? 0 : 4);
+        }
+
+        private bool ignore(
+            char c)
+        {
+            return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
+        }
+
+        /**
+        * decode the base 64 encoded byte data writing it to the given output stream,
+        * whitespace characters will be ignored.
+        *
+        * @return the number of bytes produced.
+        */
+        public int Decode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            byte b1, b2, b3, b4;
+            int outLen = 0;
+
+            int end = off + length;
+
+            while (end > off)
+            {
+                if (!ignore((char)data[end - 1]))
+                {
+                    break;
+                }
+
+                end--;
+            }
+
+            int  i = off;
+            int  finish = end - 4;
+
+            i = nextI(data, i, finish);
+
+            while (i < finish)
+            {
+                b1 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b2 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b3 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b4 = decodingTable[data[i++]];
+
+                if ((b1 | b2 | b3 | b4) >= 0x80)
+                    throw new IOException("invalid characters encountered in base64 data");
+
+                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
+                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
+                outStream.WriteByte((byte)((b3 << 6) | b4));
+
+                outLen += 3;
+
+                i = nextI(data, i, finish);
+            }
+
+            outLen += decodeLastBlock(outStream, (char)data[end - 4], (char)data[end - 3], (char)data[end - 2], (char)data[end - 1]);
+
+            return outLen;
+        }
+
+        private int nextI(
+            byte[]	data,
+            int		i,
+            int		finish)
+        {
+            while ((i < finish) && ignore((char)data[i]))
+            {
+                i++;
+            }
+            return i;
+        }
+
+        /**
+        * decode the base 64 encoded string data writing it to the given output stream,
+        * whitespace characters will be ignored.
+        *
+        * @return the number of bytes produced.
+        */
+        public int DecodeString(
+            string	data,
+            Stream	outStream)
+        {
+            // Platform Implementation
+//			byte[] bytes = Convert.FromBase64String(data);
+//			outStream.Write(bytes, 0, bytes.Length);
+//			return bytes.Length;
+
+            byte b1, b2, b3, b4;
+            int length = 0;
+
+            int end = data.Length;
+
+            while (end > 0)
+            {
+                if (!ignore(data[end - 1]))
+                {
+                    break;
+                }
+
+                end--;
+            }
+
+            int  i = 0;
+            int  finish = end - 4;
+
+            i = nextI(data, i, finish);
+
+            while (i < finish)
+            {
+                b1 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b2 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b3 = decodingTable[data[i++]];
+
+                i = nextI(data, i, finish);
+
+                b4 = decodingTable[data[i++]];
+
+                if ((b1 | b2 | b3 | b4) >= 0x80)
+                    throw new IOException("invalid characters encountered in base64 data");
+
+                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
+                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
+                outStream.WriteByte((byte)((b3 << 6) | b4));
+
+                length += 3;
+
+                i = nextI(data, i, finish);
+            }
+
+            length += decodeLastBlock(outStream, data[end - 4], data[end - 3], data[end - 2], data[end - 1]);
+
+            return length;
+        }
+
+        private int decodeLastBlock(
+            Stream	outStream,
+            char	c1,
+            char	c2,
+            char	c3,
+            char	c4)
+        {
+            if (c3 == padding)
+            {
+                byte b1 = decodingTable[c1];
+                byte b2 = decodingTable[c2];
+
+                if ((b1 | b2) >= 0x80)
+                    throw new IOException("invalid characters encountered at end of base64 data");
+
+                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
+
+                return 1;
+            }
+
+            if (c4 == padding)
+            {
+                byte b1 = decodingTable[c1];
+                byte b2 = decodingTable[c2];
+                byte b3 = decodingTable[c3];
+
+                if ((b1 | b2 | b3) >= 0x80)
+                    throw new IOException("invalid characters encountered at end of base64 data");
+
+                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
+                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
+
+                return 2;
+            }
+
+            {
+                byte b1 = decodingTable[c1];
+                byte b2 = decodingTable[c2];
+                byte b3 = decodingTable[c3];
+                byte b4 = decodingTable[c4];
+
+                if ((b1 | b2 | b3 | b4) >= 0x80)
+                    throw new IOException("invalid characters encountered at end of base64 data");
+
+                outStream.WriteByte((byte)((b1 << 2) | (b2 >> 4)));
+                outStream.WriteByte((byte)((b2 << 4) | (b3 >> 2)));
+                outStream.WriteByte((byte)((b3 << 6) | b4));
+
+                return 3;
+            }
+        }
+
+        private int nextI(string data, int i, int finish)
+        {
+            while ((i < finish) && ignore(data[i]))
+            {
+                i++;
+            }
+            return i;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/BufferedDecoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/BufferedDecoder.cs
new file mode 100644
index 0000000..633cf1e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/BufferedDecoder.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    /// <summary>
+    ///  A buffering class to allow translation from one format to another to
+    ///     be done in discrete chunks.
+    /// </summary>
+    public class BufferedDecoder
+    {
+        internal byte[]        buffer;
+        internal int           bufOff;
+
+        internal ITranslator   translator;
+
+        /// <summary>
+        /// Create a buffered Decoder.
+        /// </summary>
+        /// <param name="translator">The translater to use.</param>
+        /// <param name="bufferSize">The size of the buffer.</param>
+        public BufferedDecoder(
+            ITranslator translator,
+            int         bufferSize)
+        {
+            this.translator = translator;
+
+            if ((bufferSize % translator.GetEncodedBlockSize()) != 0)
+            {
+                throw new ArgumentException("buffer size not multiple of input block size");
+            }
+
+            buffer = new byte[bufferSize];
+//            bufOff = 0;
+        }
+
+        /// <summary>
+        /// Process one byte of data.
+        /// </summary>
+        /// <param name="input">Data in.</param>
+        /// <param name="output">Byte array for the output.</param>
+        /// <param name="outOff">The offset in the output byte array to start writing from.</param>
+        /// <returns>The amount of output bytes.</returns>
+        public int ProcessByte(
+            byte        input,
+            byte[]      output,
+            int         outOff)
+        {
+            int         resultLen = 0;
+
+            buffer[bufOff++] = input;
+
+            if (bufOff == buffer.Length)
+            {
+                resultLen = translator.Decode(buffer, 0, buffer.Length, output, outOff);
+                bufOff = 0;
+            }
+
+            return resultLen;
+        }
+
+
+        /// <summary>
+        /// Process data from a byte array.
+        /// </summary>
+        /// <param name="input">The input data.</param>
+        /// <param name="inOff">Start position within input data array.</param>
+        /// <param name="len">Amount of data to process from input data array.</param>
+        /// <param name="outBytes">Array to store output.</param>
+        /// <param name="outOff">Position in output array to start writing from.</param>
+        /// <returns>The amount of output bytes.</returns>
+        public int ProcessBytes(
+            byte[]      input,
+            int         inOff,
+            int         len,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            if (len < 0)
+            {
+            throw new ArgumentException("Can't have a negative input length!");
+            }
+
+            int resultLen = 0;
+            int gapLen = buffer.Length - bufOff;
+
+            if (len > gapLen)
+            {
+                Array.Copy(input, inOff, buffer, bufOff, gapLen);
+
+                resultLen += translator.Decode(buffer, 0, buffer.Length, outBytes, outOff);
+
+                bufOff = 0;
+
+                len -= gapLen;
+                inOff += gapLen;
+                outOff += resultLen;
+
+                int chunkSize = len - (len % buffer.Length);
+
+                resultLen += translator.Decode(input, inOff, chunkSize, outBytes, outOff);
+
+                len -= chunkSize;
+                inOff += chunkSize;
+            }
+
+            if (len != 0)
+            {
+                Array.Copy(input, inOff, buffer, bufOff, len);
+
+                bufOff += len;
+            }
+
+            return resultLen;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/BufferedEncoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/BufferedEncoder.cs
new file mode 100644
index 0000000..5c3b1ab
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/BufferedEncoder.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    /// <summary>
+    /// A class that allows encoding of data using a specific encoder to be processed in chunks.
+    /// </summary>
+    public class BufferedEncoder
+    {
+        internal byte[]        Buffer;
+        internal int           bufOff;
+
+        internal ITranslator   translator;
+
+
+        /// <summary>
+        /// Create.
+        /// </summary>
+        /// <param name="translator">The translator to use.</param>
+        /// <param name="bufferSize">Size of the chunks.</param>
+        public BufferedEncoder(
+            ITranslator translator,
+            int         bufferSize)
+        {
+            this.translator = translator;
+
+            if ((bufferSize % translator.GetEncodedBlockSize()) != 0)
+            {
+                throw new ArgumentException("buffer size not multiple of input block size");
+            }
+
+            Buffer = new byte[bufferSize];
+//            bufOff = 0;
+        }
+
+
+        /// <summary>
+        /// Process one byte of data.
+        /// </summary>
+        /// <param name="input">The byte.</param>
+        /// <param name="outBytes">An array to store output in.</param>
+        /// <param name="outOff">Offset within output array to start writing from.</param>
+        /// <returns></returns>
+        public int ProcessByte(
+            byte        input,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            int         resultLen = 0;
+
+            Buffer[bufOff++] = input;
+
+            if (bufOff == Buffer.Length)
+            {
+                resultLen = translator.Encode(Buffer, 0, Buffer.Length, outBytes, outOff);
+                bufOff = 0;
+            }
+
+            return resultLen;
+        }
+
+        /// <summary>
+        /// Process data from a byte array.
+        /// </summary>
+        /// <param name="input">Input data Byte array containing data to be processed.</param>
+        /// <param name="inOff">Start position within input data array.</param>
+        /// <param name="len">Amount of input data to be processed.</param>
+        /// <param name="outBytes">Output data array.</param>
+        /// <param name="outOff">Offset within output data array to start writing to.</param>
+        /// <returns>The amount of data written.</returns>
+        public int ProcessBytes(
+            byte[]      input,
+            int         inOff,
+            int         len,
+            byte[]      outBytes,
+            int         outOff)
+        {
+            if (len < 0)
+            {
+            throw new ArgumentException("Can't have a negative input length!");
+            }
+
+            int resultLen = 0;
+            int gapLen = Buffer.Length - bufOff;
+
+            if (len > gapLen)
+            {
+                Array.Copy(input, inOff, Buffer, bufOff, gapLen);
+
+                resultLen += translator.Encode(Buffer, 0, Buffer.Length, outBytes, outOff);
+
+                bufOff = 0;
+
+                len -= gapLen;
+                inOff += gapLen;
+                outOff += resultLen;
+
+                int chunkSize = len - (len % Buffer.Length);
+
+                resultLen += translator.Encode(input, inOff, chunkSize, outBytes, outOff);
+
+                len -= chunkSize;
+                inOff += chunkSize;
+            }
+
+            if (len != 0)
+            {
+                Array.Copy(input, inOff, Buffer, bufOff, len);
+
+                bufOff += len;
+            }
+
+            return resultLen;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/Hex.cs b/BouncyCastle.AxCrypt/src/util/encoders/Hex.cs
new file mode 100644
index 0000000..3540a9d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/Hex.cs
@@ -0,0 +1,130 @@
+using System;
+using System.IO;
+using System.Text;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    /// <summary>
+    /// Class to decode and encode Hex.
+    /// </summary>
+    public sealed class Hex
+    {
+        private static readonly IEncoder encoder = new HexEncoder();
+
+        private Hex()
+        {
+        }
+
+        public static string ToHexString(
+            byte[] data)
+        {
+            return ToHexString(data, 0, data.Length);
+        }
+
+        public static string ToHexString(
+            byte[]	data,
+            int		off,
+            int		length)
+        {
+            byte[] hex = Encode(data, off, length);
+            return Strings.FromAsciiByteArray(hex);
+        }
+
+        /**
+         * encode the input data producing a Hex encoded byte array.
+         *
+         * @return a byte array containing the Hex encoded data.
+         */
+        public static byte[] Encode(
+            byte[] data)
+        {
+            return Encode(data, 0, data.Length);
+        }
+
+        /**
+         * encode the input data producing a Hex encoded byte array.
+         *
+         * @return a byte array containing the Hex encoded data.
+         */
+        public static byte[] Encode(
+            byte[]	data,
+            int		off,
+            int		length)
+        {
+            MemoryStream bOut = new MemoryStream(length * 2);
+
+            encoder.Encode(data, off, length, bOut);
+
+            return bOut.ToArray();
+        }
+
+        /**
+         * Hex encode the byte data writing it to the given output stream.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Encode(
+            byte[]	data,
+            Stream	outStream)
+        {
+            return encoder.Encode(data, 0, data.Length, outStream);
+        }
+
+        /**
+         * Hex encode the byte data writing it to the given output stream.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Encode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            return encoder.Encode(data, off, length, outStream);
+        }
+
+        /**
+         * decode the Hex encoded input data. It is assumed the input data is valid.
+         *
+         * @return a byte array representing the decoded data.
+         */
+        public static byte[] Decode(
+            byte[] data)
+        {
+            MemoryStream bOut = new MemoryStream((data.Length + 1) / 2);
+
+            encoder.Decode(data, 0, data.Length, bOut);
+
+            return bOut.ToArray();
+        }
+
+        /**
+         * decode the Hex encoded string data - whitespace will be ignored.
+         *
+         * @return a byte array representing the decoded data.
+         */
+        public static byte[] Decode(
+            string data)
+        {
+            MemoryStream bOut = new MemoryStream((data.Length + 1) / 2);
+
+            encoder.DecodeString(data, bOut);
+
+            return bOut.ToArray();
+        }
+
+        /**
+         * decode the Hex encoded string data writing it to the given output stream,
+         * whitespace characters will be ignored.
+         *
+         * @return the number of bytes produced.
+         */
+        public static int Decode(
+            string	data,
+            Stream	outStream)
+        {
+            return encoder.DecodeString(data, outStream);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/HexEncoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/HexEncoder.cs
new file mode 100644
index 0000000..af526e0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/HexEncoder.cs
@@ -0,0 +1,176 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    public class HexEncoder
+        : IEncoder
+    {
+        protected readonly byte[] encodingTable =
+        {
+            (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+            (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+        };
+
+        /*
+         * set up the decoding table.
+         */
+        protected readonly byte[] decodingTable = new byte[128];
+
+        protected void InitialiseDecodingTable()
+        {
+            Arrays.Fill(decodingTable, (byte)0xff);
+
+            for (int i = 0; i < encodingTable.Length; i++)
+            {
+                decodingTable[encodingTable[i]] = (byte)i;
+            }
+
+            decodingTable['A'] = decodingTable['a'];
+            decodingTable['B'] = decodingTable['b'];
+            decodingTable['C'] = decodingTable['c'];
+            decodingTable['D'] = decodingTable['d'];
+            decodingTable['E'] = decodingTable['e'];
+            decodingTable['F'] = decodingTable['f'];
+        }
+
+        public HexEncoder()
+        {
+            InitialiseDecodingTable();
+        }
+
+        /**
+        * encode the input data producing a Hex output stream.
+        *
+        * @return the number of bytes produced.
+        */
+        public int Encode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            for (int i = off; i < (off + length); i++)
+            {
+                int v = data[i];
+
+                outStream.WriteByte(encodingTable[v >> 4]);
+                outStream.WriteByte(encodingTable[v & 0xf]);
+            }
+
+            return length * 2;
+        }
+
+        private static bool Ignore(char c)
+        {
+            return c == '\n' || c =='\r' || c == '\t' || c == ' ';
+        }
+
+        /**
+        * decode the Hex encoded byte data writing it to the given output stream,
+        * whitespace characters will be ignored.
+        *
+        * @return the number of bytes produced.
+        */
+        public int Decode(
+            byte[]	data,
+            int		off,
+            int		length,
+            Stream	outStream)
+        {
+            byte b1, b2;
+            int outLen = 0;
+            int end = off + length;
+
+            while (end > off)
+            {
+                if (!Ignore((char)data[end - 1]))
+                {
+                    break;
+                }
+
+                end--;
+            }
+
+            int i = off;
+            while (i < end)
+            {
+                while (i < end && Ignore((char)data[i]))
+                {
+                    i++;
+                }
+
+                b1 = decodingTable[data[i++]];
+
+                while (i < end && Ignore((char)data[i]))
+                {
+                    i++;
+                }
+
+                b2 = decodingTable[data[i++]];
+
+                if ((b1 | b2) >= 0x80)
+                    throw new IOException("invalid characters encountered in Hex data");
+
+                outStream.WriteByte((byte)((b1 << 4) | b2));
+
+                outLen++;
+            }
+
+            return outLen;
+        }
+
+        /**
+        * decode the Hex encoded string data writing it to the given output stream,
+        * whitespace characters will be ignored.
+        *
+        * @return the number of bytes produced.
+        */
+        public int DecodeString(
+            string	data,
+            Stream	outStream)
+        {
+            byte    b1, b2;
+            int     length = 0;
+
+            int     end = data.Length;
+
+            while (end > 0)
+            {
+                if (!Ignore(data[end - 1]))
+                {
+                    break;
+                }
+
+                end--;
+            }
+
+            int i = 0;
+            while (i < end)
+            {
+                while (i < end && Ignore(data[i]))
+                {
+                    i++;
+                }
+
+                b1 = decodingTable[data[i++]];
+
+                while (i < end && Ignore(data[i]))
+                {
+                    i++;
+                }
+
+                b2 = decodingTable[data[i++]];
+
+                if ((b1 | b2) >= 0x80)
+                    throw new IOException("invalid characters encountered in Hex data");
+
+                outStream.WriteByte((byte)((b1 << 4) | b2));
+
+                length++;
+            }
+
+            return length;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/HexTranslator.cs b/BouncyCastle.AxCrypt/src/util/encoders/HexTranslator.cs
new file mode 100644
index 0000000..9775b69
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/HexTranslator.cs
@@ -0,0 +1,108 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    /// <summary>
+    /// A hex translator.
+    /// </summary>
+    public class HexTranslator : ITranslator
+    {
+        private static readonly byte[]   hexTable =
+            {
+                (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+                (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+            };
+
+        /// <summary>
+        /// Return encoded block size.
+        /// </summary>
+        /// <returns>2</returns>
+        public int GetEncodedBlockSize()
+        {
+            return 2;
+        }
+
+        /// <summary>
+        /// Encode some data.
+        /// </summary>
+        /// <param name="input">Input data array.</param>
+        /// <param name="inOff">Start position within input data array.</param>
+        /// <param name="length">The amount of data to process.</param>
+        /// <param name="outBytes">The output data array.</param>
+        /// <param name="outOff">The offset within the output data array to start writing from.</param>
+        /// <returns>Amount of data encoded.</returns>
+        public int Encode(
+            byte[]  input,
+            int     inOff,
+            int     length,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            for (int i = 0, j = 0; i < length; i++, j += 2)
+            {
+                outBytes[outOff + j] = hexTable[(input[inOff] >> 4) & 0x0f];
+                outBytes[outOff + j + 1] = hexTable[input[inOff] & 0x0f];
+
+                inOff++;
+            }
+
+            return length * 2;
+        }
+
+        /// <summary>
+        /// Returns the decoded block size.
+        /// </summary>
+        /// <returns>1</returns>
+        public int GetDecodedBlockSize()
+        {
+            return 1;
+        }
+
+        /// <summary>
+        /// Decode data from a byte array.
+        /// </summary>
+        /// <param name="input">The input data array.</param>
+        /// <param name="inOff">Start position within input data array.</param>
+        /// <param name="length">The amounty of data to process.</param>
+        /// <param name="outBytes">The output data array.</param>
+        /// <param name="outOff">The position within the output data array to start writing from.</param>
+        /// <returns>The amount of data written.</returns>
+        public int Decode(
+            byte[]  input,
+            int     inOff,
+            int     length,
+            byte[]  outBytes,
+            int     outOff)
+        {
+            int halfLength = length / 2;
+            byte left, right;
+            for (int i = 0; i < halfLength; i++)
+            {
+                left  = input[inOff + i * 2];
+                right = input[inOff + i * 2 + 1];
+
+                if (left < (byte)'a')
+                {
+                    outBytes[outOff] = (byte)((left - '0') << 4);
+                }
+                else
+                {
+                    outBytes[outOff] = (byte)((left - 'a' + 10) << 4);
+                }
+                if (right < (byte)'a')
+                {
+                    outBytes[outOff] += (byte)(right - '0');
+                }
+                else
+                {
+                    outBytes[outOff] += (byte)(right - 'a' + 10);
+                }
+
+                outOff++;
+            }
+
+            return halfLength;
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/IEncoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/IEncoder.cs
new file mode 100644
index 0000000..5887d5d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/IEncoder.cs
@@ -0,0 +1,18 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+	/**
+	 * Encode and decode byte arrays (typically from binary to 7-bit ASCII
+	 * encodings).
+	 */
+	public interface IEncoder
+	{
+		int Encode(byte[] data, int off, int length, Stream outStream);
+
+		int Decode(byte[] data, int off, int length, Stream outStream);
+
+		int DecodeString(string data, Stream outStream);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/Translator.cs b/BouncyCastle.AxCrypt/src/util/encoders/Translator.cs
new file mode 100644
index 0000000..10bd24b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/Translator.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+    /// <summary>
+    /// Translator interface.
+    /// </summary>
+    public interface ITranslator
+    {
+        int GetEncodedBlockSize();
+
+        int Encode(byte[] input, int inOff, int length, byte[] outBytes, int outOff);
+
+        int GetDecodedBlockSize();
+
+        int Decode(byte[] input, int inOff, int length, byte[] outBytes, int outOff);
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64.cs b/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64.cs
new file mode 100644
index 0000000..94195ef
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64.cs
@@ -0,0 +1,127 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+	/**
+	* Convert binary data to and from UrlBase64 encoding.  This is identical to
+	* Base64 encoding, except that the padding character is "." and the other 
+	* non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+	* <p>
+	* The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+	* data that is safe for use as an URL parameter. Base64 encoding does not
+	* produce encoded values that are safe for use in URLs, since "/" can be 
+	* interpreted as a path delimiter; "+" is the encoded form of a space; and
+	* "=" is used to separate a name from the corresponding value in an URL 
+	* parameter.
+	* </p>
+	*/
+	public class UrlBase64
+	{
+		private static readonly IEncoder encoder = new UrlBase64Encoder();
+
+		/**
+		* Encode the input data producing a URL safe base 64 encoded byte array.
+		*
+		* @return a byte array containing the URL safe base 64 encoded data.
+		*/
+		public static byte[] Encode(
+			byte[] data)
+		{
+			MemoryStream bOut = new MemoryStream();
+
+			try
+			{
+				encoder.Encode(data, 0, data.Length, bOut);
+			}
+			catch (IOException e)
+			{
+				throw new Exception("exception encoding URL safe base64 string: " + e.Message, e);
+			}
+
+			return bOut.ToArray();
+		}
+
+		/**
+		* Encode the byte data writing it to the given output stream.
+		*
+		* @return the number of bytes produced.
+		*/
+		public static int Encode(
+			byte[]	data,
+			Stream	outStr)
+		{
+			return encoder.Encode(data, 0, data.Length, outStr);
+		}
+
+		/**
+		* Decode the URL safe base 64 encoded input data - white space will be ignored.
+		*
+		* @return a byte array representing the decoded data.
+		*/
+		public static byte[] Decode(
+			byte[] data)
+		{
+			MemoryStream bOut = new MemoryStream();
+
+			try
+			{
+				encoder.Decode(data, 0, data.Length, bOut);
+			}
+			catch (IOException e)
+			{
+				throw new Exception("exception decoding URL safe base64 string: " + e.Message, e);
+			}
+
+			return bOut.ToArray();
+		}
+
+		/**
+		* decode the URL safe base 64 encoded byte data writing it to the given output stream,
+		* whitespace characters will be ignored.
+		*
+		* @return the number of bytes produced.
+		*/
+		public static int Decode(
+			byte[]	data,
+			Stream	outStr)
+		{
+			return encoder.Decode(data, 0, data.Length, outStr);
+		}
+
+		/**
+		* decode the URL safe base 64 encoded string data - whitespace will be ignored.
+		*
+		* @return a byte array representing the decoded data.
+		*/
+		public static byte[] Decode(
+			string data)
+		{
+			MemoryStream bOut = new MemoryStream();
+
+			try
+			{
+				encoder.DecodeString(data, bOut);
+			}
+			catch (IOException e)
+			{
+				throw new Exception("exception decoding URL safe base64 string: " + e.Message, e);
+			}
+	        
+			return bOut.ToArray();
+		}
+	    
+		/**
+		* Decode the URL safe base 64 encoded string data writing it to the given output stream,
+		* whitespace characters will be ignored.
+		*
+		* @return the number of bytes produced.
+		*/
+		public static int Decode(
+			string	data,
+			Stream	outStr)
+		{
+			return encoder.DecodeString(data, outStr);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64Encoder.cs b/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64Encoder.cs
new file mode 100644
index 0000000..5611a83
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/encoders/UrlBase64Encoder.cs
@@ -0,0 +1,31 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Encoders
+{
+	/**
+	* Convert binary data to and from UrlBase64 encoding.  This is identical to
+	* Base64 encoding, except that the padding character is "." and the other 
+	* non-alphanumeric characters are "-" and "_" instead of "+" and "/".
+	* <p>
+	* The purpose of UrlBase64 encoding is to provide a compact encoding of binary
+	* data that is safe for use as an URL parameter. Base64 encoding does not
+	* produce encoded values that are safe for use in URLs, since "/" can be 
+	* interpreted as a path delimiter; "+" is the encoded form of a space; and
+	* "=" is used to separate a name from the corresponding value in an URL 
+	* parameter.
+	* </p>
+	*/
+	public class UrlBase64Encoder
+		: Base64Encoder
+	{
+		public UrlBase64Encoder()
+		{
+			encodingTable[encodingTable.Length - 2] = (byte) '-';
+			encodingTable[encodingTable.Length - 1] = (byte) '_';
+			padding = (byte) '.';
+			// we must re-create the decoding table with the new encoded values.
+			InitialiseDecodingTable();
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/io/BaseInputStream.cs b/BouncyCastle.AxCrypt/src/util/io/BaseInputStream.cs
new file mode 100644
index 0000000..2407bba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/BaseInputStream.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+    public abstract class BaseInputStream : Stream
+    {
+		private bool closed;
+
+		public sealed override bool CanRead { get { return !closed; } }
+        public sealed override bool CanSeek { get { return false; } }
+        public sealed override bool CanWrite { get { return false; } }
+		protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                closed = true;
+            }
+
+            base.Dispose(disposing);
+        }
+
+        public sealed override void Flush() {}
+        public sealed override long Length { get { throw new NotSupportedException(); } }
+        public sealed override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+
+        public override int Read(byte[] buffer, int offset, int count)
+        {
+            int pos = offset;
+            try
+            {
+                int end = offset + count;
+                while (pos < end)
+                {
+                    int b = ReadByte();
+                    if (b == -1) break;
+                    buffer[pos++] = (byte) b;
+                }
+            }
+            catch (IOException)
+            {
+                if (pos == offset) throw;
+            }
+            return pos - offset;
+        }
+
+        public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+        public sealed override void SetLength(long value) { throw new NotSupportedException(); }
+        public sealed override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/BaseOutputStream.cs b/BouncyCastle.AxCrypt/src/util/io/BaseOutputStream.cs
new file mode 100644
index 0000000..56ce847
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/BaseOutputStream.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+    public abstract class BaseOutputStream : Stream
+    {
+		private bool closed;
+
+		public sealed override bool CanRead { get { return false; } }
+        public sealed override bool CanSeek { get { return false; } }
+        public sealed override bool CanWrite { get { return !closed; } }
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                closed = true;
+            }
+            base.Dispose(disposing);
+        }
+        public override void Flush() {}
+        public sealed override long Length { get { throw new NotSupportedException(); } }
+        public sealed override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+        public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+        public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+        public sealed override void SetLength(long value) { throw new NotSupportedException(); }
+
+        public override void Write(byte[] buffer, int offset, int count)
+        {
+            Debug.Assert(buffer != null);
+            Debug.Assert(0 <= offset && offset <= buffer.Length);
+            Debug.Assert(count >= 0);
+
+            int end = offset + count;
+
+            Debug.Assert(0 <= end && end <= buffer.Length);
+
+            for (int i = offset; i < end; ++i)
+            {
+                this.WriteByte(buffer[i]);
+            }
+        }
+
+		public virtual void Write(params byte[] buffer)
+		{
+			Write(buffer, 0, buffer.Length);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/NullOutputStream.cs b/BouncyCastle.AxCrypt/src/util/io/NullOutputStream.cs
new file mode 100644
index 0000000..13877fa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/NullOutputStream.cs
@@ -0,0 +1,18 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+	internal class NullOutputStream
+		: BaseOutputStream
+	{
+		public override void WriteByte(byte b)
+		{
+			// do nothing
+		}
+
+		public override void Write(byte[] buffer, int offset, int count)
+		{
+			// do nothing
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/PushbackStream.cs b/BouncyCastle.AxCrypt/src/util/io/PushbackStream.cs
new file mode 100644
index 0000000..9546942
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/PushbackStream.cs
@@ -0,0 +1,52 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+	public class PushbackStream
+		: FilterStream
+	{
+		private int buf = -1;
+
+		public PushbackStream(
+			Stream s)
+			: base(s)
+		{
+		}
+
+		public override int ReadByte()
+		{
+			if (buf != -1)
+			{
+				int tmp = buf;
+				buf = -1;
+				return tmp;
+			}
+
+			return base.ReadByte();
+		}
+
+		public override int Read(byte[] buffer, int offset, int count)
+		{
+			if (buf != -1 && count > 0)
+			{
+				// TODO Can this case be made more efficient?
+				buffer[offset] = (byte) buf;
+				buf = -1;
+				return 1;
+			}
+
+			return base.Read(buffer, offset, count);
+		}
+
+		public virtual void Unread(int b)
+		{
+			if (buf != -1)
+				throw new InvalidOperationException("Can only push back one byte");
+
+			buf = b & 0xFF;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/StreamOverflowException.cs b/BouncyCastle.AxCrypt/src/util/io/StreamOverflowException.cs
new file mode 100644
index 0000000..d8fcb55
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/StreamOverflowException.cs
@@ -0,0 +1,30 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class StreamOverflowException
+		: IOException
+	{
+		public StreamOverflowException()
+			: base()
+		{
+		}
+
+		public StreamOverflowException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public StreamOverflowException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/Streams.cs b/BouncyCastle.AxCrypt/src/util/io/Streams.cs
new file mode 100644
index 0000000..ee95d3b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/Streams.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+	public sealed class Streams
+	{
+		private const int BufferSize = 512;
+
+		private Streams()
+		{
+		}
+
+		public static void Drain(Stream inStr)
+		{
+			byte[] bs = new byte[BufferSize];
+			while (inStr.Read(bs, 0, bs.Length) > 0)
+			{
+			}
+		}
+
+		public static byte[] ReadAll(Stream inStr)
+		{
+			MemoryStream buf = new MemoryStream();
+			PipeAll(inStr, buf);
+			return buf.ToArray();
+		}
+
+		public static byte[] ReadAllLimited(Stream inStr, int limit)
+		{
+			MemoryStream buf = new MemoryStream();
+			PipeAllLimited(inStr, limit, buf);
+			return buf.ToArray();
+		}
+
+		public static int ReadFully(Stream inStr, byte[] buf)
+		{
+			return ReadFully(inStr, buf, 0, buf.Length);
+		}
+
+		public static int ReadFully(Stream inStr, byte[] buf, int off, int len)
+		{
+			int totalRead = 0;
+			while (totalRead < len)
+			{
+				int numRead = inStr.Read(buf, off + totalRead, len - totalRead);
+				if (numRead < 1)
+					break;
+				totalRead += numRead;
+			}
+			return totalRead;
+		}
+
+		public static void PipeAll(Stream inStr, Stream outStr)
+		{
+			byte[] bs = new byte[BufferSize];
+			int numRead;
+			while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0)
+			{
+				outStr.Write(bs, 0, numRead);
+			}
+		}
+
+		/// <summary>
+		/// Pipe all bytes from <c>inStr</c> to <c>outStr</c>, throwing <c>StreamFlowException</c> if greater
+		/// than <c>limit</c> bytes in <c>inStr</c>.
+		/// </summary>
+		/// <param name="inStr">
+		/// A <see cref="Stream"/>
+		/// </param>
+		/// <param name="limit">
+		/// A <see cref="System.Int64"/>
+		/// </param>
+		/// <param name="outStr">
+		/// A <see cref="Stream"/>
+		/// </param>
+		/// <returns>The number of bytes actually transferred, if not greater than <c>limit</c></returns>
+		/// <exception cref="IOException"></exception>
+		public static long PipeAllLimited(Stream inStr, long limit, Stream outStr)
+		{
+			byte[] bs = new byte[BufferSize];
+			long total = 0;
+			int numRead;
+			while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0)
+			{
+				total += numRead;
+				if (total > limit)
+					throw new StreamOverflowException("Data Overflow");
+				outStr.Write(bs, 0, numRead);
+			}
+			return total;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/TeeInputStream.cs b/BouncyCastle.AxCrypt/src/util/io/TeeInputStream.cs
new file mode 100644
index 0000000..aeed3ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/TeeInputStream.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+	public class TeeInputStream
+		: BaseInputStream
+	{
+		private readonly Stream input, tee;
+
+		public TeeInputStream(Stream input, Stream tee)
+		{
+			Debug.Assert(input.CanRead);
+			Debug.Assert(tee.CanWrite);
+
+			this.input = input;
+			this.tee = tee;
+		}
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+	            input.Dispose();
+	            tee.Dispose();
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		public override int Read(byte[] buf, int off, int len)
+		{
+			int i = input.Read(buf, off, len);
+
+			if (i > 0)
+			{
+				tee.Write(buf, off, i);
+			}
+
+			return i;
+		}
+
+		public override int ReadByte()
+		{
+			int i = input.ReadByte();
+
+			if (i >= 0)
+			{
+				tee.WriteByte((byte)i);
+			}
+
+			return i;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/TeeOutputStream.cs b/BouncyCastle.AxCrypt/src/util/io/TeeOutputStream.cs
new file mode 100644
index 0000000..cebca89
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/TeeOutputStream.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+    public class TeeOutputStream
+		: BaseOutputStream
+	{
+		private readonly Stream output, tee;
+
+		public TeeOutputStream(Stream output, Stream tee)
+		{
+			Debug.Assert(output.CanWrite);
+			Debug.Assert(tee.CanWrite);
+
+			this.output = output;
+			this.tee = tee;
+		}
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                output.Dispose();
+                tee.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+        
+		public override void Write(byte[] buffer, int offset, int count)
+		{
+			output.Write(buffer, offset, count);
+			tee.Write(buffer, offset, count);
+		}
+
+		public override void WriteByte(byte b)
+		{
+			output.WriteByte(b);
+			tee.WriteByte(b);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemGenerationException.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemGenerationException.cs
new file mode 100644
index 0000000..b8edc62
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemGenerationException.cs
@@ -0,0 +1,29 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class PemGenerationException
+		: Exception
+	{
+		public PemGenerationException()
+			: base()
+		{
+		}
+
+		public PemGenerationException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public PemGenerationException(
+			string		message,
+			Exception	exception)
+			: base(message, exception)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemHeader.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemHeader.cs
new file mode 100644
index 0000000..72da8a4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemHeader.cs
@@ -0,0 +1,55 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	public class PemHeader
+	{
+		private string name;
+		private string val;
+
+		public PemHeader(string name, string val)
+		{
+			this.name = name;
+			this.val = val;
+		}
+
+		public virtual string Name
+		{
+			get { return name; }
+		}
+
+		public virtual string Value
+		{
+			get { return val; }
+		}
+
+		public override int GetHashCode()
+		{
+			return GetHashCode(this.name) + 31 * GetHashCode(this.val);
+		}
+
+		public override bool Equals(object obj)
+		{
+			if (obj == this)
+				return true;
+
+			if (!(obj is PemHeader))
+				return false;
+
+			PemHeader other = (PemHeader)obj;
+
+			return Platform.Equals(this.name, other.name)
+				&& Platform.Equals(this.val, other.val);
+		}
+
+		private int GetHashCode(string s)
+		{
+			if (s == null)
+			{
+				return 1;
+			}
+
+			return s.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemObject.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemObject.cs
new file mode 100644
index 0000000..41212f9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemObject.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	public class PemObject
+		: PemObjectGenerator
+	{
+		private string		type;
+		private IList		headers;
+		private byte[]		content;
+
+		public PemObject(string type, byte[] content)
+			: this(type, Platform.CreateArrayList(), content)
+		{
+		}
+
+		public PemObject(String type, IList headers, byte[] content)
+		{
+			this.type = type;
+            this.headers = Platform.CreateArrayList(headers);
+			this.content = content;
+		}
+
+		public string Type
+		{
+			get { return type; }
+		}
+
+		public IList Headers
+		{
+			get { return headers; }
+		}
+
+		public byte[] Content
+		{
+			get { return content; }
+		}
+
+		public PemObject Generate()
+		{
+			return this;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectGenerator.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectGenerator.cs
new file mode 100644
index 0000000..6f9bfc1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectGenerator.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	public interface PemObjectGenerator
+	{
+		/// <returns>
+		/// A <see cref="PemObject"/>
+		/// </returns>
+		/// <exception cref="PemGenerationException"></exception>
+		PemObject Generate();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectParser.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectParser.cs
new file mode 100644
index 0000000..91d26dc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemObjectParser.cs
@@ -0,0 +1,17 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	public interface PemObjectParser
+	{
+		/// <param name="obj">
+		/// A <see cref="PemObject"/>
+		/// </param>
+		/// <returns>
+		/// A <see cref="System.Object"/>
+		/// </returns>
+		/// <exception cref="IOException"></exception>
+		object ParseObject(PemObject obj);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemReader.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemReader.cs
new file mode 100644
index 0000000..b328470
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemReader.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	public class PemReader
+	{
+		private const string BeginString = "-----BEGIN ";
+		private const string EndString = "-----END ";
+
+		private readonly TextReader reader;
+
+		public PemReader(TextReader reader)
+		{
+			if (reader == null)
+				throw new ArgumentNullException("reader");
+
+			this.reader = reader;
+		}
+
+		public TextReader Reader
+		{
+			get { return reader; }
+		}
+
+		/// <returns>
+		/// A <see cref="PemObject"/>
+		/// </returns>
+		/// <exception cref="IOException"></exception>
+		public PemObject ReadPemObject()
+		{
+			string line = reader.ReadLine();
+
+			if (line != null && line.StartsWith(BeginString))
+			{
+				line = line.Substring(BeginString.Length);
+				int index = line.IndexOf('-');
+				string type = line.Substring(0, index);
+
+				if (index > 0)
+					return LoadObject(type);
+			}
+
+			return null;
+		}
+
+		private PemObject LoadObject(string type)
+		{
+			string endMarker = EndString + type;
+			IList headers = Platform.CreateArrayList();
+			StringBuilder buf = new StringBuilder();
+
+			string line;
+			while ((line = reader.ReadLine()) != null
+				&& line.IndexOf(endMarker) == -1)
+			{
+				int colonPos = line.IndexOf(':');
+
+				if (colonPos == -1)
+				{
+					buf.Append(line.Trim());
+				}
+				else
+				{
+					// Process field
+					string fieldName = line.Substring(0, colonPos).Trim();
+
+					if (fieldName.StartsWith("X-"))
+						fieldName = fieldName.Substring(2);
+
+					string fieldValue = line.Substring(colonPos + 1).Trim();
+
+					headers.Add(new PemHeader(fieldName, fieldValue));
+				}
+			}
+
+			if (line == null)
+			{
+				throw new IOException(endMarker + " not found");
+			}
+
+			if (buf.Length % 4 != 0)
+			{
+				throw new IOException("base64 data appears to be truncated");
+			}
+
+			return new PemObject(type, headers, Base64.Decode(buf.ToString()));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/io/pem/PemWriter.cs b/BouncyCastle.AxCrypt/src/util/io/pem/PemWriter.cs
new file mode 100644
index 0000000..e85b315
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/io/pem/PemWriter.cs
@@ -0,0 +1,120 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem
+{
+	/**
+	* A generic PEM writer, based on RFC 1421
+	*/
+	public class PemWriter
+	{
+		private const int LineLength = 64;
+
+		private readonly TextWriter	writer;
+		private readonly int		nlLength;
+		private char[]				buf = new char[LineLength];
+		
+		/**
+		 * Base constructor.
+		 *
+		 * @param out output stream to use.
+		 */
+		public PemWriter(TextWriter writer)
+		{
+			if (writer == null)
+				throw new ArgumentNullException("writer");
+
+			this.writer = writer;
+			this.nlLength = Platform.NewLine.Length;
+		}
+
+		public TextWriter Writer
+		{
+			get { return writer; }
+		}
+
+		/**
+		 * Return the number of bytes or characters required to contain the
+		 * passed in object if it is PEM encoded.
+		 *
+		 * @param obj pem object to be output
+		 * @return an estimate of the number of bytes
+		 */
+		public int GetOutputSize(PemObject obj)
+		{
+			// BEGIN and END boundaries.
+			int size = (2 * (obj.Type.Length + 10 + nlLength)) + 6 + 4;
+
+			if (obj.Headers.Count > 0)
+			{
+				foreach (PemHeader header in obj.Headers)
+				{
+					size += header.Name.Length + ": ".Length + header.Value.Length + nlLength;
+				}
+
+				size += nlLength;
+			}
+
+			// base64 encoding
+			int dataLen = ((obj.Content.Length + 2) / 3) * 4;
+
+			size += dataLen + (((dataLen + LineLength - 1) / LineLength) * nlLength);
+
+			return size;
+		}
+
+		public void WriteObject(PemObjectGenerator objGen)
+		{
+			PemObject obj = objGen.Generate();
+
+			WritePreEncapsulationBoundary(obj.Type);
+
+			if (obj.Headers.Count > 0)
+			{
+				foreach (PemHeader header in obj.Headers)
+				{
+					writer.Write(header.Name);
+					writer.Write(": ");
+					writer.WriteLine(header.Value);
+				}
+
+				writer.WriteLine();
+			}
+
+			WriteEncoded(obj.Content);
+			WritePostEncapsulationBoundary(obj.Type);
+		}
+
+		private void WriteEncoded(byte[] bytes)
+		{
+			bytes = Base64.Encode(bytes);
+
+			for (int i = 0; i < bytes.Length; i += buf.Length)
+			{
+				int index = 0;
+				while (index != buf.Length)
+				{
+					if ((i + index) >= bytes.Length)
+						break;
+
+					buf[index] = (char)bytes[i + index];
+					index++;
+				}
+				writer.WriteLine(buf, 0, index);
+			}
+		}
+
+		private void WritePreEncapsulationBoundary(string type)
+		{
+			writer.WriteLine("-----BEGIN " + type + "-----");
+		}
+
+		private void WritePostEncapsulationBoundary(string type)
+		{
+			writer.WriteLine("-----END " + type + "-----");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/net/IPAddress.cs b/BouncyCastle.AxCrypt/src/util/net/IPAddress.cs
new file mode 100644
index 0000000..2a30a15
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/net/IPAddress.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Globalization;
+
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Utilities.Net
+{
+	public class IPAddress
+	{
+		/**
+		 * Validate the given IPv4 or IPv6 address.
+		 *
+		 * @param address the IP address as a string.
+		 *
+		 * @return true if a valid address, false otherwise
+		 */
+		public static bool IsValid(
+			string address)
+		{
+			return IsValidIPv4(address) || IsValidIPv6(address);
+		}
+
+		/**
+		 * Validate the given IPv4 or IPv6 address and netmask.
+		 *
+		 * @param address the IP address as a string.
+		 *
+		 * @return true if a valid address with netmask, false otherwise
+		 */
+		public static bool IsValidWithNetMask(
+			string address)
+		{
+			return IsValidIPv4WithNetmask(address) || IsValidIPv6WithNetmask(address);
+		}
+
+		/**
+		 * Validate the given IPv4 address.
+		 * 
+		 * @param address the IP address as a string.
+		 *
+		 * @return true if a valid IPv4 address, false otherwise
+		 */
+		public static bool IsValidIPv4(
+			string address)
+		{
+			try
+			{
+				return unsafeIsValidIPv4(address);
+			}
+			catch (FormatException) {}
+			catch (OverflowException) {}
+			return false;
+		}
+
+		private static bool unsafeIsValidIPv4(
+			string address)
+		{
+			if (address.Length == 0)
+				return false;
+
+			int octets = 0;
+			string temp = address + ".";
+
+			int pos;
+			int start = 0;
+			while (start < temp.Length
+				&& (pos = temp.IndexOf('.', start)) > start)
+			{
+				if (octets == 4)
+					return false;
+
+				string octetStr = temp.Substring(start, pos - start);
+				int octet = Int32.Parse(octetStr);
+
+				if (octet < 0 || octet > 255)
+					return false;
+
+				start = pos + 1;
+				octets++;
+			}
+
+			return octets == 4;
+		}
+
+		public static bool IsValidIPv4WithNetmask(
+			string address)
+		{
+			int index = address.IndexOf("/");
+			string mask = address.Substring(index + 1);
+
+			return (index > 0) && IsValidIPv4(address.Substring(0, index))
+				&& (IsValidIPv4(mask) || IsMaskValue(mask, 32));
+		}
+
+		public static bool IsValidIPv6WithNetmask(
+			string address)
+		{
+			int index = address.IndexOf("/");
+			string mask = address.Substring(index + 1);
+
+			return (index > 0) && (IsValidIPv6(address.Substring(0, index))
+				&& (IsValidIPv6(mask) || IsMaskValue(mask, 128)));
+		}
+
+		private static bool IsMaskValue(
+			string	component,
+			int		size)
+		{
+			int val = Int32.Parse(component);
+			try
+			{
+				return val >= 0 && val <= size;
+			}
+			catch (FormatException) {}
+			catch (OverflowException) {}
+			return false;
+		}
+
+		/**
+		 * Validate the given IPv6 address.
+		 *
+		 * @param address the IP address as a string.
+		 *
+		 * @return true if a valid IPv4 address, false otherwise
+		 */
+		public static bool IsValidIPv6(
+			string address)
+		{
+			try
+			{
+				return unsafeIsValidIPv6(address);
+			}
+			catch (FormatException) {}
+			catch (OverflowException) {}
+			return false;
+		}
+
+		private static bool unsafeIsValidIPv6(
+			string address)
+		{
+			if (address.Length == 0)
+			{
+				return false;
+			}
+
+			int octets = 0;
+
+			string temp = address + ":";
+			bool doubleColonFound = false;
+			int pos;
+			int start = 0;
+			while (start < temp.Length
+				&& (pos = temp.IndexOf(':', start)) >= start)
+			{
+				if (octets == 8)
+				{
+					return false;
+				}
+
+				if (start != pos)
+				{
+					string value = temp.Substring(start, pos - start);
+
+					if (pos == (temp.Length - 1) && value.IndexOf('.') > 0)
+					{
+						if (!IsValidIPv4(value))
+						{
+							return false;
+						}
+
+						octets++; // add an extra one as address covers 2 words.
+					}
+					else
+					{
+						string octetStr = temp.Substring(start, pos - start);
+						int octet = Int32.Parse(octetStr, NumberStyles.AllowHexSpecifier);
+
+						if (octet < 0 || octet > 0xffff)
+							return false;
+					}
+				}
+				else
+				{
+					if (pos != 1 && pos != temp.Length - 1 && doubleColonFound)
+					{
+						return false;
+					}
+					doubleColonFound = true;
+				}
+				start = pos + 1;
+				octets++;
+			}
+
+			return octets == 8 || doubleColonFound;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/Adler32.cs b/BouncyCastle.AxCrypt/src/util/zlib/Adler32.cs
new file mode 100644
index 0000000..c38258f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/Adler32.cs
@@ -0,0 +1,88 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class Adler32{
+
+        // largest prime smaller than 65536
+        private const int BASE=65521; 
+        // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+        private const int NMAX=5552;
+
+        internal long adler32(long adler, byte[] buf, int index, int len){
+            if(buf == null){ return 1L; }
+
+            long s1=adler&0xffff;
+            long s2=(adler>>16)&0xffff;
+            int k;
+
+            while(len > 0) {
+                k=len<NMAX?len:NMAX;
+                len-=k;
+                while(k>=16){
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    s1+=buf[index++]&0xff; s2+=s1;
+                    k-=16;
+                }
+                if(k!=0){
+                    do{
+                        s1+=buf[index++]&0xff; s2+=s1;
+                    }
+                    while(--k!=0);
+                }
+                s1%=BASE;
+                s2%=BASE;
+            }
+            return (s2<<16)|s1;
+        }
+
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/Deflate.cs b/BouncyCastle.AxCrypt/src/util/zlib/Deflate.cs
new file mode 100644
index 0000000..ca04309
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/Deflate.cs
@@ -0,0 +1,1640 @@
+using System;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    public sealed class Deflate{
+
+        private const int MAX_MEM_LEVEL=9;
+
+        private const int Z_DEFAULT_COMPRESSION=-1;
+
+        private const int MAX_WBITS=15;            // 32K LZ77 window
+        private const int DEF_MEM_LEVEL=8;
+
+        internal class Config{
+            internal int good_length; // reduce lazy search above this match length
+            internal int max_lazy;    // do not perform lazy search above this match length
+            internal int nice_length; // quit search above this match length
+            internal int max_chain;
+            internal int func;
+            internal Config(int good_length, int max_lazy, 
+                int nice_length, int max_chain, int func){
+                this.good_length=good_length;
+                this.max_lazy=max_lazy;
+                this.nice_length=nice_length;
+                this.max_chain=max_chain;
+                this.func=func;
+            }
+        }
+  
+        private const int STORED=0;
+        private const int FAST=1;
+        private const int SLOW=2;
+        private static readonly Config[] config_table;
+
+		static Deflate(){
+            config_table=new Config[10];
+            //                         good  lazy  nice  chain
+            config_table[0]=new Config(0,    0,    0,    0, STORED);
+            config_table[1]=new Config(4,    4,    8,    4, FAST);
+            config_table[2]=new Config(4,    5,   16,    8, FAST);
+            config_table[3]=new Config(4,    6,   32,   32, FAST);
+
+            config_table[4]=new Config(4,    4,   16,   16, SLOW);
+            config_table[5]=new Config(8,   16,   32,   32, SLOW);
+            config_table[6]=new Config(8,   16,  128,  128, SLOW);
+            config_table[7]=new Config(8,   32,  128,  256, SLOW);
+            config_table[8]=new Config(32, 128,  258, 1024, SLOW);
+            config_table[9]=new Config(32, 258,  258, 4096, SLOW);
+        }
+
+        private static readonly String[] z_errmsg = {
+                                               "need dictionary",     // Z_NEED_DICT       2
+                                               "stream end",          // Z_STREAM_END      1
+                                               "",                    // Z_OK              0
+                                               "file error",          // Z_ERRNO         (-1)
+                                               "stream error",        // Z_STREAM_ERROR  (-2)
+                                               "data error",          // Z_DATA_ERROR    (-3)
+                                               "insufficient memory", // Z_MEM_ERROR     (-4)
+                                               "buffer error",        // Z_BUF_ERROR     (-5)
+                                               "incompatible version",// Z_VERSION_ERROR (-6)
+                                               ""
+                                           };
+
+        // block not completed, need more input or more output
+        private const int NeedMore=0; 
+
+        // block flush performed
+        private const int BlockDone=1; 
+
+        // finish started, need only more output at next deflate
+        private const int FinishStarted=2;
+
+        // finish done, accept no more input or output
+        private const int FinishDone=3;
+
+        // preset dictionary flag in zlib header
+        private const int PRESET_DICT=0x20;
+
+        private const int Z_FILTERED=1;
+        private const int Z_HUFFMAN_ONLY=2;
+        private const int Z_DEFAULT_STRATEGY=0;
+
+        private const int Z_NO_FLUSH=0;
+        private const int Z_PARTIAL_FLUSH=1;
+        private const int Z_SYNC_FLUSH=2;
+        private const int Z_FULL_FLUSH=3;
+        private const int Z_FINISH=4;
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        private const int INIT_STATE=42;
+        private const int BUSY_STATE=113;
+        private const int FINISH_STATE=666;
+
+        // The deflate compression method
+        private const int Z_DEFLATED=8;
+
+        private const int STORED_BLOCK=0;
+        private const int STATIC_TREES=1;
+        private const int DYN_TREES=2;
+
+        // The three kinds of block type
+        private const int Z_BINARY=0;
+        private const int Z_ASCII=1;
+        private const int Z_UNKNOWN=2;
+
+        private const int Buf_size=8*2;
+
+        // repeat previous bit length 3-6 times (2 bits of repeat count)
+        private const int REP_3_6=16; 
+
+        // repeat a zero length 3-10 times  (3 bits of repeat count)
+        private const int REPZ_3_10=17; 
+
+        // repeat a zero length 11-138 times  (7 bits of repeat count)
+        private const int REPZ_11_138=18; 
+
+        private const int MIN_MATCH=3;
+        private const int MAX_MATCH=258;
+        private const int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1);
+
+        private const int MAX_BITS=15;
+        private const int D_CODES=30;
+        private const int BL_CODES=19;
+        private const int LENGTH_CODES=29;
+        private const int LITERALS=256;
+        private const int L_CODES=(LITERALS+1+LENGTH_CODES);
+        private const int HEAP_SIZE=(2*L_CODES+1);
+
+        private const int END_BLOCK=256;
+
+        internal ZStream strm;         // pointer back to this zlib stream
+        internal int status;           // as the name implies
+        internal byte[] pending_buf;   // output still pending
+        internal int pending_buf_size; // size of pending_buf
+        internal int pending_out;      // next pending byte to output to the stream
+        internal int pending;          // nb of bytes in the pending buffer
+        internal int noheader;         // suppress zlib header and adler32
+        internal byte data_type;       // UNKNOWN, BINARY or ASCII
+        internal byte method;          // STORED (for zip only) or DEFLATED
+        internal int last_flush;       // value of flush param for previous deflate call
+
+        internal int w_size;           // LZ77 window size (32K by default)
+        internal int w_bits;           // log2(w_size)  (8..16)
+        internal int w_mask;           // w_size - 1
+
+        internal byte[] window;
+        // Sliding window. Input bytes are read into the second half of the window,
+        // and move to the first half later to keep a dictionary of at least wSize
+        // bytes. With this organization, matches are limited to a distance of
+        // wSize-MAX_MATCH bytes, but this ensures that IO is always
+        // performed with a length multiple of the block size. Also, it limits
+        // the window size to 64K, which is quite useful on MSDOS.
+        // To do: use the user input buffer as sliding window.
+
+        internal int window_size;
+        // Actual size of window: 2*wSize, except when the user input buffer
+        // is directly used as sliding window.
+
+        internal short[] prev;
+        // Link to older string with same hash index. To limit the size of this
+        // array to 64K, this link is maintained only for the last 32K strings.
+        // An index in this array is thus a window index modulo 32K.
+
+        internal short[] head; // Heads of the hash chains or NIL.
+
+        internal int ins_h;          // hash index of string to be inserted
+        internal int hash_size;      // number of elements in hash table
+        internal int hash_bits;      // log2(hash_size)
+        internal int hash_mask;      // hash_size-1
+
+        // Number of bits by which ins_h must be shifted at each input
+        // step. It must be such that after MIN_MATCH steps, the oldest
+        // byte no longer takes part in the hash key, that is:
+        // hash_shift * MIN_MATCH >= hash_bits
+        internal int hash_shift;
+
+        // Window position at the beginning of the current output block. Gets
+        // negative when the window is moved backwards.
+
+        internal int block_start;
+
+        internal int match_length;           // length of best match
+        internal int prev_match;             // previous match
+        internal int match_available;        // set if previous match exists
+        internal int strstart;               // start of string to insert
+        internal int match_start;            // start of matching string
+        internal int lookahead;              // number of valid bytes ahead in window
+
+        // Length of the best match at previous step. Matches not greater than this
+        // are discarded. This is used in the lazy match evaluation.
+        internal int prev_length;
+
+        // To speed up deflation, hash chains are never searched beyond this
+        // length.  A higher limit improves compression ratio but degrades the speed.
+        internal int max_chain_length;
+
+        // Attempt to find a better match only when the current match is strictly
+        // smaller than this value. This mechanism is used only for compression
+        // levels >= 4.
+        internal int max_lazy_match;
+
+        // Insert new strings in the hash table only if the match length is not
+        // greater than this length. This saves time but degrades compression.
+        // max_insert_length is used only for compression levels <= 3.
+
+        internal int level;    // compression level (1..9)
+        internal int strategy; // favor or force Huffman coding
+
+        // Use a faster search when the previous match is longer than this
+        internal int good_match;
+
+        // Stop searching when current match exceeds this
+        internal int nice_match;
+
+        internal short[] dyn_ltree;       // literal and length tree
+        internal short[] dyn_dtree;       // distance tree
+        internal short[] bl_tree;         // Huffman tree for bit lengths
+
+        internal Tree l_desc=new Tree();  // desc for literal tree
+        internal Tree d_desc=new Tree();  // desc for distance tree
+        internal Tree bl_desc=new Tree(); // desc for bit length tree
+
+        // number of codes at each bit length for an optimal tree
+        internal short[] bl_count=new short[MAX_BITS+1];
+
+        // heap used to build the Huffman trees
+        internal int[] heap=new int[2*L_CODES+1];
+
+        internal int heap_len;               // number of elements in the heap
+        internal int heap_max;               // element of largest frequency
+        // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+        // The same heap array is used to build all trees.
+
+        // Depth of each subtree used as tie breaker for trees of equal frequency
+        internal byte[] depth=new byte[2*L_CODES+1];
+
+        internal int l_buf;               // index for literals or lengths */
+
+        // Size of match buffer for literals/lengths.  There are 4 reasons for
+        // limiting lit_bufsize to 64K:
+        //   - frequencies can be kept in 16 bit counters
+        //   - if compression is not successful for the first block, all input
+        //     data is still in the window so we can still emit a stored block even
+        //     when input comes from standard input.  (This can also be done for
+        //     all blocks if lit_bufsize is not greater than 32K.)
+        //   - if compression is not successful for a file smaller than 64K, we can
+        //     even emit a stored file instead of a stored block (saving 5 bytes).
+        //     This is applicable only for zip (not gzip or zlib).
+        //   - creating new Huffman trees less frequently may not provide fast
+        //     adaptation to changes in the input data statistics. (Take for
+        //     example a binary file with poorly compressible code followed by
+        //     a highly compressible string table.) Smaller buffer sizes give
+        //     fast adaptation but have of course the overhead of transmitting
+        //     trees more frequently.
+        //   - I can't count above 4
+        internal int lit_bufsize;
+
+        internal int last_lit;      // running index in l_buf
+
+        // Buffer for distances. To simplify the code, d_buf and l_buf have
+        // the same number of elements. To use different lengths, an extra flag
+        // array would be necessary.
+
+        internal int d_buf;         // index of pendig_buf
+
+        internal int opt_len;        // bit length of current block with optimal trees
+        internal int static_len;     // bit length of current block with static trees
+        internal int matches;        // number of string matches in current block
+        internal int last_eob_len;   // bit length of EOB code for last block
+
+        // Output buffer. bits are inserted starting at the bottom (least
+        // significant bits).
+        internal uint bi_buf;
+
+        // Number of valid bits in bi_buf.  All bits above the last valid bit
+        // are always zero.
+        internal int bi_valid;
+
+        internal Deflate(){
+            dyn_ltree=new short[HEAP_SIZE*2];
+            dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree
+            bl_tree=new short[(2*BL_CODES+1)*2];  // Huffman tree for bit lengths
+        }
+
+        internal void lm_init() {
+            window_size=2*w_size;
+
+            head[hash_size-1]=0;
+            for(int i=0; i<hash_size-1; i++){
+                head[i]=0;
+            }
+
+            // Set the default configuration parameters:
+            max_lazy_match   = Deflate.config_table[level].max_lazy;
+            good_match       = Deflate.config_table[level].good_length;
+            nice_match       = Deflate.config_table[level].nice_length;
+            max_chain_length = Deflate.config_table[level].max_chain;
+
+            strstart = 0;
+            block_start = 0;
+            lookahead = 0;
+            match_length = prev_length = MIN_MATCH-1;
+            match_available = 0;
+            ins_h = 0;
+        }
+
+        // Initialize the tree data structures for a new zlib stream.
+        internal void tr_init(){
+
+            l_desc.dyn_tree = dyn_ltree;
+            l_desc.stat_desc = StaticTree.static_l_desc;
+
+            d_desc.dyn_tree = dyn_dtree;
+            d_desc.stat_desc = StaticTree.static_d_desc;
+
+            bl_desc.dyn_tree = bl_tree;
+            bl_desc.stat_desc = StaticTree.static_bl_desc;
+
+            bi_buf = 0;
+            bi_valid = 0;
+            last_eob_len = 8; // enough lookahead for inflate
+
+            // Initialize the first block of the first file:
+            init_block();
+        }
+
+        internal void init_block(){
+            // Initialize the trees.
+            for(int i = 0; i < L_CODES; i++) dyn_ltree[i*2] = 0;
+            for(int i= 0; i < D_CODES; i++) dyn_dtree[i*2] = 0;
+            for(int i= 0; i < BL_CODES; i++) bl_tree[i*2] = 0;
+
+            dyn_ltree[END_BLOCK*2] = 1;
+            opt_len = static_len = 0;
+            last_lit = matches = 0;
+        }
+
+        // Restore the heap property by moving down the tree starting at node k,
+        // exchanging a node with the smallest of its two sons if necessary, stopping
+        // when the heap property is re-established (each father smaller than its
+        // two sons).
+        internal void pqdownheap(short[] tree,  // the tree to restore
+            int k          // node to move down
+            ){
+            int v = heap[k];
+            int j = k << 1;  // left son of k
+            while (j <= heap_len) {
+                // Set j to the smallest of the two sons:
+                if (j < heap_len &&
+                    smaller(tree, heap[j+1], heap[j], depth)){
+                    j++;
+                }
+                // Exit if v is smaller than both sons
+                if(smaller(tree, v, heap[j], depth)) break;
+
+                // Exchange v with the smallest son
+                heap[k]=heap[j];  k = j;
+                // And continue down the tree, setting j to the left son of k
+                j <<= 1;
+            }
+            heap[k] = v;
+        }
+
+        internal static bool smaller(short[] tree, int n, int m, byte[] depth){
+            short tn2=tree[n*2];
+            short tm2=tree[m*2];
+            return (tn2<tm2 ||
+                (tn2==tm2 && depth[n] <= depth[m]));
+        }
+
+        // Scan a literal or distance tree to determine the frequencies of the codes
+        // in the bit length tree.
+        internal void scan_tree (short[] tree,// the tree to be scanned
+            int max_code // and its largest code of non zero frequency
+            ){
+            int n;                     // iterates over all tree elements
+            int prevlen = -1;          // last emitted length
+            int curlen;                // length of current code
+            int nextlen = tree[0*2+1]; // length of next code
+            int count = 0;             // repeat count of the current code
+            int max_count = 7;         // max repeat count
+            int min_count = 4;         // min repeat count
+
+            if (nextlen == 0){ max_count = 138; min_count = 3; }
+            tree[(max_code+1)*2+1] = -1; // guard
+
+            for(n = 0; n <= max_code; n++) {
+                curlen = nextlen; nextlen = tree[(n+1)*2+1];
+                if(++count < max_count && curlen == nextlen) {
+                    continue;
+                }
+                else if(count < min_count) {
+                    bl_tree[curlen*2] += (short)count;
+                }
+                else if(curlen != 0) {
+                    if(curlen != prevlen) bl_tree[curlen*2]++;
+                    bl_tree[REP_3_6*2]++;
+                }
+                else if(count <= 10) {
+                    bl_tree[REPZ_3_10*2]++;
+                }
+                else{
+                    bl_tree[REPZ_11_138*2]++;
+                }
+                count = 0; prevlen = curlen;
+                if(nextlen == 0) {
+                    max_count = 138; min_count = 3;
+                }
+                else if(curlen == nextlen) {
+                    max_count = 6; min_count = 3;
+                }
+                else{
+                    max_count = 7; min_count = 4;
+                }
+            }
+        }
+
+        // Construct the Huffman tree for the bit lengths and return the index in
+        // bl_order of the last bit length code to send.
+        internal int build_bl_tree(){
+            int max_blindex;  // index of last bit length code of non zero freq
+
+            // Determine the bit length frequencies for literal and distance trees
+            scan_tree(dyn_ltree, l_desc.max_code);
+            scan_tree(dyn_dtree, d_desc.max_code);
+
+            // Build the bit length tree:
+            bl_desc.build_tree(this);
+            // opt_len now includes the length of the tree representations, except
+            // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+            // Determine the number of bit length codes to send. The pkzip format
+            // requires that at least 4 bit length codes be sent. (appnote.txt says
+            // 3 but the actual value used is 4.)
+            for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) {
+                if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break;
+            }
+            // Update opt_len to include the bit length tree and counts
+            opt_len += 3*(max_blindex+1) + 5+5+4;
+
+            return max_blindex;
+        }
+
+
+        // Send the header for a block using dynamic Huffman trees: the counts, the
+        // lengths of the bit length codes, the literal tree and the distance tree.
+        // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+        internal void send_all_trees(int lcodes, int dcodes, int blcodes){
+            int rank;                    // index in bl_order
+
+            send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt
+            send_bits(dcodes-1,   5);
+            send_bits(blcodes-4,  4); // not -3 as stated in appnote.txt
+            for (rank = 0; rank < blcodes; rank++) {
+                send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3);
+            }
+            send_tree(dyn_ltree, lcodes-1); // literal tree
+            send_tree(dyn_dtree, dcodes-1); // distance tree
+        }
+
+        // Send a literal or distance tree in compressed form, using the codes in
+        // bl_tree.
+        internal void send_tree (short[] tree,// the tree to be sent
+            int max_code // and its largest code of non zero frequency
+            ){
+            int n;                     // iterates over all tree elements
+            int prevlen = -1;          // last emitted length
+            int curlen;                // length of current code
+            int nextlen = tree[0*2+1]; // length of next code
+            int count = 0;             // repeat count of the current code
+            int max_count = 7;         // max repeat count
+            int min_count = 4;         // min repeat count
+
+            if (nextlen == 0){ max_count = 138; min_count = 3; }
+
+            for (n = 0; n <= max_code; n++) {
+                curlen = nextlen; nextlen = tree[(n+1)*2+1];
+                if(++count < max_count && curlen == nextlen) {
+                    continue;
+                }
+                else if(count < min_count) {
+                    do { send_code(curlen, bl_tree); } while (--count != 0);
+                }
+                else if(curlen != 0){
+                    if(curlen != prevlen){
+                        send_code(curlen, bl_tree); count--;
+                    }
+                    send_code(REP_3_6, bl_tree); 
+                    send_bits(count-3, 2);
+                }
+                else if(count <= 10){
+                    send_code(REPZ_3_10, bl_tree); 
+                    send_bits(count-3, 3);
+                }
+                else{
+                    send_code(REPZ_11_138, bl_tree);
+                    send_bits(count-11, 7);
+                }
+                count = 0; prevlen = curlen;
+                if(nextlen == 0){
+                    max_count = 138; min_count = 3;
+                }
+                else if(curlen == nextlen){
+                    max_count = 6; min_count = 3;
+                }
+                else{
+                    max_count = 7; min_count = 4;
+                }
+            }
+        }
+
+        // Output a byte on the stream.
+        // IN assertion: there is enough room in pending_buf.
+        internal void put_byte(byte[] p, int start, int len){
+            System.Array.Copy(p, start, pending_buf, pending, len);
+            pending+=len;
+        }
+
+        internal void put_byte(byte c){
+            pending_buf[pending++]=c;
+        }
+        internal void put_short(int w) {
+            pending_buf[pending++]=(byte)(w/*&0xff*/);
+            pending_buf[pending++]=(byte)(w>>8);
+        }
+        internal void putShortMSB(int b){
+            pending_buf[pending++]=(byte)(b>>8);
+            pending_buf[pending++]=(byte)(b/*&0xff*/);
+        }   
+
+        internal void send_code(int c, short[] tree){
+            int c2=c*2;
+            send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff));
+        }
+
+        internal void send_bits(int val, int length){
+            if (bi_valid > Buf_size - length) {
+                bi_buf |= (uint)(val << bi_valid);
+                pending_buf[pending++]=(byte)(bi_buf/*&0xff*/);
+                pending_buf[pending++]=(byte)(bi_buf>>8);
+                bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+                bi_valid += length - Buf_size;
+            } else {
+                bi_buf |= (uint)(val << bi_valid);
+                bi_valid += length;
+            }
+//            int len = length;
+//            if (bi_valid > (int)Buf_size - len) {
+//                int val = value;
+//                //      bi_buf |= (val << bi_valid);
+//                bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+//                put_short(bi_buf);
+//                bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+//                bi_valid += len - Buf_size;
+//            } else {
+//                //      bi_buf |= (value) << bi_valid;
+//                bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+//                bi_valid += len;
+//            }
+        }
+
+        // Send one empty static block to give enough lookahead for inflate.
+        // This takes 10 bits, of which 7 may remain in the bit buffer.
+        // The current inflate code requires 9 bits of lookahead. If the
+        // last two codes for the previous block (real code plus EOB) were coded
+        // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+        // the last real code. In this case we send two empty static blocks instead
+        // of one. (There are no problems if the previous block is stored or fixed.)
+        // To simplify the code, we assume the worst case of last real code encoded
+        // on one bit only.
+        internal void _tr_align(){
+            send_bits(STATIC_TREES<<1, 3);
+            send_code(END_BLOCK, StaticTree.static_ltree);
+
+            bi_flush();
+
+            // Of the 10 bits for the empty block, we have already sent
+            // (10 - bi_valid) bits. The lookahead for the last real code (before
+            // the EOB of the previous block) was thus at least one plus the length
+            // of the EOB plus what we have just sent of the empty static block.
+            if (1 + last_eob_len + 10 - bi_valid < 9) {
+                send_bits(STATIC_TREES<<1, 3);
+                send_code(END_BLOCK, StaticTree.static_ltree);
+                bi_flush();
+            }
+            last_eob_len = 7;
+        }
+
+
+        // Save the match info and tally the frequency counts. Return true if
+        // the current block must be flushed.
+        internal bool _tr_tally (int dist, // distance of matched string
+            int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+            ){
+
+            pending_buf[d_buf+last_lit*2] = (byte)(dist>>8);
+            pending_buf[d_buf+last_lit*2+1] = (byte)dist;
+
+            pending_buf[l_buf+last_lit] = (byte)lc; last_lit++;
+
+            if (dist == 0) {
+                // lc is the unmatched char
+                dyn_ltree[lc*2]++;
+            } 
+            else {
+                matches++;
+                // Here, lc is the match length - MIN_MATCH
+                dist--;             // dist = match distance - 1
+                dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++;
+                dyn_dtree[Tree.d_code(dist)*2]++;
+            }
+
+            if ((last_lit & 0x1fff) == 0 && level > 2) {
+                // Compute an upper bound for the compressed length
+                int out_length = last_lit*8;
+                int in_length = strstart - block_start;
+                int dcode;
+                for (dcode = 0; dcode < D_CODES; dcode++) {
+                    out_length += (int)((int)dyn_dtree[dcode*2] *
+                        (5L+Tree.extra_dbits[dcode]));
+                }
+                out_length >>= 3;
+                if ((matches < (last_lit/2)) && out_length < in_length/2) return true;
+            }
+
+            return (last_lit == lit_bufsize-1);
+            // We avoid equality with lit_bufsize because of wraparound at 64K
+            // on 16 bit machines and because stored blocks are restricted to
+            // 64K-1 bytes.
+        }
+
+        // Send the block data compressed using the given Huffman trees
+        internal void compress_block(short[] ltree, short[] dtree){
+            int  dist;      // distance of matched string
+            int lc;         // match length or unmatched char (if dist == 0)
+            int lx = 0;     // running index in l_buf
+            int code;       // the code to send
+            int extra;      // number of extra bits to send
+
+            if (last_lit != 0){
+                do{
+                    dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)|
+                        (pending_buf[d_buf+lx*2+1]&0xff);
+                    lc=(pending_buf[l_buf+lx])&0xff; lx++;
+
+                    if(dist == 0){
+                        send_code(lc, ltree); // send a literal byte
+                    } 
+                    else{
+                        // Here, lc is the match length - MIN_MATCH
+                        code = Tree._length_code[lc];
+
+                        send_code(code+LITERALS+1, ltree); // send the length code
+                        extra = Tree.extra_lbits[code];
+                        if(extra != 0){
+                            lc -= Tree.base_length[code];
+                            send_bits(lc, extra);       // send the extra length bits
+                        }
+                        dist--; // dist is now the match distance - 1
+                        code = Tree.d_code(dist);
+
+                        send_code(code, dtree);       // send the distance code
+                        extra = Tree.extra_dbits[code];
+                        if (extra != 0) {
+                            dist -= Tree.base_dist[code];
+                            send_bits(dist, extra);   // send the extra distance bits
+                        }
+                    } // literal or match pair ?
+
+                    // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+                }
+                while (lx < last_lit);
+            }
+
+            send_code(END_BLOCK, ltree);
+            last_eob_len = ltree[END_BLOCK*2+1];
+        }
+
+        // Set the data type to ASCII or BINARY, using a crude approximation:
+        // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+        // IN assertion: the fields freq of dyn_ltree are set and the total of all
+        // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+        internal void set_data_type(){
+            int n = 0;
+            int  ascii_freq = 0;
+            int  bin_freq = 0;
+            while(n<7){ bin_freq += dyn_ltree[n*2]; n++;}
+            while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;}
+            while(n<LITERALS){ bin_freq += dyn_ltree[n*2]; n++;}
+            data_type=(byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+        }
+
+        // Flush the bit buffer, keeping at most 7 bits in it.
+        internal void bi_flush(){
+            if (bi_valid == 16) {
+                pending_buf[pending++]=(byte)(bi_buf/*&0xff*/);
+                pending_buf[pending++]=(byte)(bi_buf>>8);
+                bi_buf=0;
+                bi_valid=0;
+            }
+            else if (bi_valid >= 8) {
+                pending_buf[pending++]=(byte)(bi_buf);
+                bi_buf>>=8;
+                bi_buf &= 0x00ff;
+                bi_valid-=8;
+            }
+        }
+
+        // Flush the bit buffer and align the output on a byte boundary
+        internal void bi_windup(){
+            if (bi_valid > 8) {
+                pending_buf[pending++]=(byte)(bi_buf);
+                pending_buf[pending++]=(byte)(bi_buf>>8);
+            } else if (bi_valid > 0) {
+                pending_buf[pending++]=(byte)(bi_buf);
+            }
+            bi_buf = 0;
+            bi_valid = 0;
+        }
+
+        // Copy a stored block, storing first the length and its
+        // one's complement if requested.
+        internal void copy_block(int buf,         // the input data
+            int len,         // its length
+            bool header   // true if block header must be written
+            ){
+            //int index=0;
+            bi_windup();      // align on byte boundary
+            last_eob_len = 8; // enough lookahead for inflate
+
+            if (header) {
+                put_short((short)len);   
+                put_short((short)~len);
+            }
+
+            //  while(len--!=0) {
+            //    put_byte(window[buf+index]);
+            //    index++;
+            //  }
+            put_byte(window, buf, len);
+        }
+
+        internal void flush_block_only(bool eof){
+            _tr_flush_block(block_start>=0 ? block_start : -1,
+                strstart-block_start,
+                eof);
+            block_start=strstart;
+            strm.flush_pending();
+        }
+
+        // Copy without compression as much as possible from the input stream, return
+        // the current block state.
+        // This function does not insert new strings in the dictionary since
+        // uncompressible data is probably not useful. This function is used
+        // only for the level=0 compression option.
+        // NOTE: this function should be optimized to avoid extra copying from
+        // window to pending_buf.
+        internal int deflate_stored(int flush){
+            // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+            // to pending_buf_size, and each stored block has a 5 byte header:
+
+            int max_block_size = 0xffff;
+            int max_start;
+
+            if(max_block_size > pending_buf_size - 5) {
+                max_block_size = pending_buf_size - 5;
+            }
+
+            // Copy as much as possible from input to output:
+            while(true){
+                // Fill the window as much as possible:
+                if(lookahead<=1){
+                    fill_window();
+                    if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore;
+                    if(lookahead==0) break; // flush the current block
+                }
+
+                strstart+=lookahead;
+                lookahead=0;
+
+                // Emit a stored block if pending_buf will be full:
+                max_start=block_start+max_block_size;
+                if(strstart==0|| strstart>=max_start) {
+                    // strstart == 0 is possible when wraparound on 16-bit machine
+                    lookahead = (int)(strstart-max_start);
+                    strstart = (int)max_start;
+      
+                    flush_block_only(false);
+                    if(strm.avail_out==0) return NeedMore;
+
+                }
+
+                // Flush if we may have to slide, otherwise block_start may become
+                // negative and the data will be gone:
+                if(strstart-block_start >= w_size-MIN_LOOKAHEAD) {
+                    flush_block_only(false);
+                    if(strm.avail_out==0) return NeedMore;
+                }
+            }
+
+            flush_block_only(flush == Z_FINISH);
+            if(strm.avail_out==0)
+                return (flush == Z_FINISH) ? FinishStarted : NeedMore;
+
+            return flush == Z_FINISH ? FinishDone : BlockDone;
+        }
+
+        // Send a stored block
+        internal void _tr_stored_block(int buf,        // input block
+            int stored_len, // length of input block
+            bool eof     // true if this is the last block for a file
+            ){
+            send_bits((STORED_BLOCK<<1)+(eof?1:0), 3);  // send block type
+            copy_block(buf, stored_len, true);          // with header
+        }
+
+        // Determine the best encoding for the current block: dynamic trees, static
+        // trees or store, and output the encoded block to the zip file.
+        internal void _tr_flush_block(int buf,        // input block, or NULL if too old
+            int stored_len, // length of input block
+            bool eof     // true if this is the last block for a file
+            ) {
+            int opt_lenb, static_lenb;// opt_len and static_len in bytes
+            int max_blindex = 0;      // index of last bit length code of non zero freq
+
+            // Build the Huffman trees unless a stored block is forced
+            if(level > 0) {
+                // Check if the file is ascii or binary
+                if(data_type == Z_UNKNOWN) set_data_type();
+
+                // Construct the literal and distance trees
+                l_desc.build_tree(this);
+
+                d_desc.build_tree(this);
+
+                // At this point, opt_len and static_len are the total bit lengths of
+                // the compressed block data, excluding the tree representations.
+
+                // Build the bit length tree for the above two trees, and get the index
+                // in bl_order of the last bit length code to send.
+                max_blindex=build_bl_tree();
+
+                // Determine the best encoding. Compute first the block length in bytes
+                opt_lenb=(opt_len+3+7)>>3;
+                static_lenb=(static_len+3+7)>>3;
+
+                if(static_lenb<=opt_lenb) opt_lenb=static_lenb;
+            }
+            else {
+                opt_lenb=static_lenb=stored_len+5; // force a stored block
+            }
+
+            if(stored_len+4<=opt_lenb && buf != -1){
+                // 4: two words for the lengths
+                // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+                // Otherwise we can't have processed more than WSIZE input bytes since
+                // the last block flush, because compression would have been
+                // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+                // transform a block into a stored block.
+                _tr_stored_block(buf, stored_len, eof);
+            }
+            else if(static_lenb == opt_lenb){
+                send_bits((STATIC_TREES<<1)+(eof?1:0), 3);
+                compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
+            }
+            else{
+                send_bits((DYN_TREES<<1)+(eof?1:0), 3);
+                send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
+                compress_block(dyn_ltree, dyn_dtree);
+            }
+
+            // The above check is made mod 2^32, for files larger than 512 MB
+            // and uLong implemented on 32 bits.
+
+            init_block();
+
+            if(eof){
+                bi_windup();
+            }
+        }
+
+        // Fill the window when the lookahead becomes insufficient.
+        // Updates strstart and lookahead.
+        //
+        // IN assertion: lookahead < MIN_LOOKAHEAD
+        // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+        //    At least one byte has been read, or avail_in == 0; reads are
+        //    performed for at least two bytes (required for the zip translate_eol
+        //    option -- not supported here).
+        internal void fill_window(){
+            int n, m;
+            int p;
+            int more;    // Amount of free space at the end of the window.
+
+            do{
+                more = (window_size-lookahead-strstart);
+
+                // Deal with !@#$% 64K limit:
+                if(more==0 && strstart==0 && lookahead==0){
+                    more = w_size;
+                } 
+                else if(more==-1) {
+                    // Very unlikely, but possible on 16 bit machine if strstart == 0
+                    // and lookahead == 1 (input done one byte at time)
+                    more--;
+
+                    // If the window is almost full and there is insufficient lookahead,
+                    // move the upper half to the lower one to make room in the upper half.
+                }
+                else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) {
+                    System.Array.Copy(window, w_size, window, 0, w_size);
+                    match_start-=w_size;
+                    strstart-=w_size; // we now have strstart >= MAX_DIST
+                    block_start-=w_size;
+
+                    // Slide the hash table (could be avoided with 32 bit values
+                    // at the expense of memory usage). We slide even when level == 0
+                    // to keep the hash table consistent if we switch back to level > 0
+                    // later. (Using level 0 permanently is not an optimal usage of
+                    // zlib, so we don't care about this pathological case.)
+
+                    n = hash_size;
+                    p=n;
+                    do {
+                        m = (head[--p]&0xffff);
+                        head[p]=(short)(m>=w_size ? (m-w_size) : 0);
+                    }
+                    while (--n != 0);
+
+                    n = w_size;
+                    p = n;
+                    do {
+                        m = (prev[--p]&0xffff);
+                        prev[p] = (short)(m >= w_size ? (m-w_size) : 0);
+                        // If n is not on any hash chain, prev[n] is garbage but
+                        // its value will never be used.
+                    }
+                    while (--n!=0);
+                    more += w_size;
+                }
+
+                if (strm.avail_in == 0) return;
+
+                // If there was no sliding:
+                //    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+                //    more == window_size - lookahead - strstart
+                // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+                // => more >= window_size - 2*WSIZE + 2
+                // In the BIG_MEM or MMAP case (not yet supported),
+                //   window_size == input_size + MIN_LOOKAHEAD  &&
+                //   strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+                // Otherwise, window_size == 2*WSIZE so more >= 2.
+                // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+                n = strm.read_buf(window, strstart + lookahead, more);
+                lookahead += n;
+
+                // Initialize the hash value now that we have some input:
+                if(lookahead >= MIN_MATCH) {
+                    ins_h = window[strstart]&0xff;
+                    ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask;
+                }
+                // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+                // but this is not important since only literal bytes will be emitted.
+            }
+            while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0);
+        }
+
+        // Compress as much as possible from the input stream, return the current
+        // block state.
+        // This function does not perform lazy evaluation of matches and inserts
+        // new strings in the dictionary only for unmatched strings or for short
+        // matches. It is used only for the fast compression options.
+        internal int deflate_fast(int flush){
+            //    short hash_head = 0; // head of the hash chain
+            int hash_head = 0; // head of the hash chain
+            bool bflush;      // set if current block must be flushed
+
+            while(true){
+                // Make sure that we always have enough lookahead, except
+                // at the end of the input file. We need MAX_MATCH bytes
+                // for the next match, plus MIN_MATCH bytes to insert the
+                // string following the next match.
+                if(lookahead < MIN_LOOKAHEAD){
+                    fill_window();
+                    if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH){
+                        return NeedMore;
+                    }
+                    if(lookahead == 0) break; // flush the current block
+                }
+
+                // Insert the string window[strstart .. strstart+2] in the
+                // dictionary, and set hash_head to the head of the hash chain:
+                if(lookahead >= MIN_MATCH){
+                    ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;
+
+                    //  prev[strstart&w_mask]=hash_head=head[ins_h];
+                    hash_head=(head[ins_h]&0xffff);
+                    prev[strstart&w_mask]=head[ins_h];
+                    head[ins_h]=(short)strstart;
+                }
+
+                // Find the longest match, discarding those <= prev_length.
+                // At this point we have always match_length < MIN_MATCH
+
+                if(hash_head!=0L && 
+                    ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD
+                    ){
+                    // To simplify the code, we prevent matches with the string
+                    // of window index 0 (in particular we have to avoid a match
+                    // of the string with itself at the start of the input file).
+                    if(strategy != Z_HUFFMAN_ONLY){
+                        match_length=longest_match (hash_head);
+                    }
+                    // longest_match() sets match_start
+                }
+                if(match_length>=MIN_MATCH){
+                    //        check_match(strstart, match_start, match_length);
+
+                    bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH);
+
+                    lookahead -= match_length;
+
+                    // Insert new strings in the hash table only if the match length
+                    // is not too large. This saves time but degrades compression.
+                    if(match_length <= max_lazy_match &&
+                        lookahead >= MIN_MATCH) {
+                        match_length--; // string at strstart already in hash table
+                        do{
+                            strstart++;
+
+                            ins_h=((ins_h<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;
+                            //      prev[strstart&w_mask]=hash_head=head[ins_h];
+                            hash_head=(head[ins_h]&0xffff);
+                            prev[strstart&w_mask]=head[ins_h];
+                            head[ins_h]=(short)strstart;
+
+                            // strstart never exceeds WSIZE-MAX_MATCH, so there are
+                            // always MIN_MATCH bytes ahead.
+                        }
+                        while (--match_length != 0);
+                        strstart++; 
+                    }
+                    else{
+                        strstart += match_length;
+                        match_length = 0;
+                        ins_h = window[strstart]&0xff;
+
+                        ins_h=(((ins_h)<<hash_shift)^(window[strstart+1]&0xff))&hash_mask;
+                        // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+                        // matter since it will be recomputed at next deflate call.
+                    }
+                }
+                else {
+                    // No match, output a literal byte
+
+                    bflush=_tr_tally(0, window[strstart]&0xff);
+                    lookahead--;
+                    strstart++; 
+                }
+                if (bflush){
+
+                    flush_block_only(false);
+                    if(strm.avail_out==0) return NeedMore;
+                }
+            }
+
+            flush_block_only(flush == Z_FINISH);
+            if(strm.avail_out==0){
+                if(flush == Z_FINISH) return FinishStarted;
+                else return NeedMore;
+            }
+            return flush==Z_FINISH ? FinishDone : BlockDone;
+        }
+
+        // Same as above, but achieves better compression. We use a lazy
+        // evaluation for matches: a match is finally adopted only if there is
+        // no better match at the next window position.
+        internal int deflate_slow(int flush){
+            //    short hash_head = 0;    // head of hash chain
+            int hash_head = 0;    // head of hash chain
+            bool bflush;         // set if current block must be flushed
+
+            // Process the input block.
+            while(true){
+                // Make sure that we always have enough lookahead, except
+                // at the end of the input file. We need MAX_MATCH bytes
+                // for the next match, plus MIN_MATCH bytes to insert the
+                // string following the next match.
+
+                if (lookahead < MIN_LOOKAHEAD) {
+                    fill_window();
+                    if(lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) {
+                        return NeedMore;
+                    }
+                    if(lookahead == 0) break; // flush the current block
+                }
+
+                // Insert the string window[strstart .. strstart+2] in the
+                // dictionary, and set hash_head to the head of the hash chain:
+
+                if(lookahead >= MIN_MATCH) {
+                    ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff)) & hash_mask;
+                    //  prev[strstart&w_mask]=hash_head=head[ins_h];
+                    hash_head=(head[ins_h]&0xffff);
+                    prev[strstart&w_mask]=head[ins_h];
+                    head[ins_h]=(short)strstart;
+                }
+
+                // Find the longest match, discarding those <= prev_length.
+                prev_length = match_length; prev_match = match_start;
+                match_length = MIN_MATCH-1;
+
+                if (hash_head != 0 && prev_length < max_lazy_match &&
+                    ((strstart-hash_head)&0xffff) <= w_size-MIN_LOOKAHEAD
+                    ){
+                    // To simplify the code, we prevent matches with the string
+                    // of window index 0 (in particular we have to avoid a match
+                    // of the string with itself at the start of the input file).
+
+                    if(strategy != Z_HUFFMAN_ONLY) {
+                        match_length = longest_match(hash_head);
+                    }
+                    // longest_match() sets match_start
+
+                    if (match_length <= 5 && (strategy == Z_FILTERED ||
+                        (match_length == MIN_MATCH &&
+                        strstart - match_start > 4096))) {
+
+                        // If prev_match is also MIN_MATCH, match_start is garbage
+                        // but we will ignore the current match anyway.
+                        match_length = MIN_MATCH-1;
+                    }
+                }
+
+                // If there was a match at the previous step and the current
+                // match is not better, output the previous match:
+                if(prev_length >= MIN_MATCH && match_length <= prev_length) {
+                    int max_insert = strstart + lookahead - MIN_MATCH;
+                    // Do not insert strings in hash table beyond this.
+
+                    //          check_match(strstart-1, prev_match, prev_length);
+
+                    bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
+
+                    // Insert in hash table all strings up to the end of the match.
+                    // strstart-1 and strstart are already inserted. If there is not
+                    // enough lookahead, the last two strings are not inserted in
+                    // the hash table.
+                    lookahead -= prev_length-1;
+                    prev_length -= 2;
+                    do{
+                        if(++strstart <= max_insert) {
+                            ins_h=(((ins_h)<<hash_shift)^(window[(strstart)+(MIN_MATCH-1)]&0xff))&hash_mask;
+                            //prev[strstart&w_mask]=hash_head=head[ins_h];
+                            hash_head=(head[ins_h]&0xffff);
+                            prev[strstart&w_mask]=head[ins_h];
+                            head[ins_h]=(short)strstart;
+                        }
+                    }
+                    while(--prev_length != 0);
+                    match_available = 0;
+                    match_length = MIN_MATCH-1;
+                    strstart++;
+
+                    if (bflush){
+                        flush_block_only(false);
+                        if(strm.avail_out==0) return NeedMore;
+                    }
+                } else if (match_available!=0) {
+
+                    // If there was no match at the previous position, output a
+                    // single literal. If there was a match but the current match
+                    // is longer, truncate the previous match to a single literal.
+
+                    bflush=_tr_tally(0, window[strstart-1]&0xff);
+
+                    if (bflush) {
+                        flush_block_only(false);
+                    }
+                    strstart++;
+                    lookahead--;
+                    if(strm.avail_out == 0) return NeedMore;
+                } else {
+                    // There is no previous match to compare with, wait for
+                    // the next step to decide.
+
+                    match_available = 1;
+                    strstart++;
+                    lookahead--;
+                }
+            }
+
+            if(match_available!=0) {
+                bflush=_tr_tally(0, window[strstart-1]&0xff);
+                match_available = 0;
+            }
+            flush_block_only(flush == Z_FINISH);
+
+            if(strm.avail_out==0){
+                if(flush == Z_FINISH) return FinishStarted;
+                else return NeedMore;
+            }
+
+            return flush == Z_FINISH ? FinishDone : BlockDone;
+        }
+
+        internal int longest_match(int cur_match){
+            int chain_length = max_chain_length; // max hash chain length
+            int scan = strstart;                 // current string
+            int match;                           // matched string
+            int len;                             // length of current match
+            int best_len = prev_length;          // best match length so far
+            int limit = strstart>(w_size-MIN_LOOKAHEAD) ?
+                strstart-(w_size-MIN_LOOKAHEAD) : 0;
+            int nice_match=this.nice_match;
+
+            // Stop when cur_match becomes <= limit. To simplify the code,
+            // we prevent matches with the string of window index 0.
+
+            int wmask = w_mask;
+
+            int strend = strstart + MAX_MATCH;
+            byte scan_end1 = window[scan+best_len-1];
+            byte scan_end = window[scan+best_len];
+
+            // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+            // It is easy to get rid of this optimization if necessary.
+
+            // Do not waste too much time if we already have a good match:
+            if (prev_length >= good_match) {
+                chain_length >>= 2;
+            }
+
+            // Do not look for matches beyond the end of the input. This is necessary
+            // to make deflate deterministic.
+            if (nice_match > lookahead) nice_match = lookahead;
+
+            do {
+                match = cur_match;
+
+                // Skip to next match if the match length cannot increase
+                // or if the match length is less than 2:
+                if (window[match+best_len]   != scan_end  ||
+                    window[match+best_len-1] != scan_end1 ||
+                    window[match]       != window[scan]     ||
+                    window[++match]     != window[scan+1])      continue;
+
+                // The check at best_len-1 can be removed because it will be made
+                // again later. (This heuristic is not always a win.)
+                // It is not necessary to compare scan[2] and match[2] since they
+                // are always equal when the other bytes match, given that
+                // the hash keys are equal and that HASH_BITS >= 8.
+                scan += 2; match++;
+
+                // We check for insufficient lookahead only every 8th comparison;
+                // the 256th check will be made at strstart+258.
+                do {
+                } while (window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    window[++scan] == window[++match] &&
+                    scan < strend);
+
+                len = MAX_MATCH - (int)(strend - scan);
+                scan = strend - MAX_MATCH;
+
+                if(len>best_len) {
+                    match_start = cur_match;
+                    best_len = len;
+                    if (len >= nice_match) break;
+                    scan_end1  = window[scan+best_len-1];
+                    scan_end   = window[scan+best_len];
+                }
+
+            } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit
+                && --chain_length != 0);
+
+            if (best_len <= lookahead) return best_len;
+            return lookahead;
+        }
+    
+        internal int deflateInit(ZStream strm, int level, int bits){
+            return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL,
+                Z_DEFAULT_STRATEGY);
+        }
+        internal int deflateInit(ZStream strm, int level){
+            return deflateInit(strm, level, MAX_WBITS);
+        }
+        internal int deflateInit2(ZStream strm, int level, int method,  int windowBits,
+            int memLevel, int strategy){
+            int noheader = 0;
+            //    byte[] my_version=ZLIB_VERSION;
+
+            //
+            //  if (version == null || version[0] != my_version[0]
+            //  || stream_size != sizeof(z_stream)) {
+            //  return Z_VERSION_ERROR;
+            //  }
+
+            strm.msg = null;
+
+            if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+            if (windowBits < 0) { // undocumented feature: suppress zlib header
+                noheader = 1;
+                windowBits = -windowBits;
+            }
+
+            if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || 
+                method != Z_DEFLATED ||
+                windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
+                strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+                return Z_STREAM_ERROR;
+            }
+
+            strm.dstate = (Deflate)this;
+
+            this.noheader = noheader;
+            w_bits = windowBits;
+            w_size = 1 << w_bits;
+            w_mask = w_size - 1;
+
+            hash_bits = memLevel + 7;
+            hash_size = 1 << hash_bits;
+            hash_mask = hash_size - 1;
+            hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+            window = new byte[w_size*2];
+            prev = new short[w_size];
+            head = new short[hash_size];
+
+            lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+            // We overlay pending_buf and d_buf+l_buf. This works since the average
+            // output size for (length,distance) codes is <= 24 bits.
+            pending_buf = new byte[lit_bufsize*4];
+            pending_buf_size = lit_bufsize*4;
+
+            d_buf = lit_bufsize/2;
+            l_buf = (1+2)*lit_bufsize;
+
+            this.level = level;
+
+            //System.out.println("level="+level);
+
+            this.strategy = strategy;
+            this.method = (byte)method;
+
+            return deflateReset(strm);
+        }
+
+        internal int deflateReset(ZStream strm){
+            strm.total_in = strm.total_out = 0;
+            strm.msg = null; //
+            strm.data_type = Z_UNKNOWN;
+
+            pending = 0;
+            pending_out = 0;
+
+            if(noheader < 0) {
+                noheader = 0; // was set to -1 by deflate(..., Z_FINISH);
+            }
+            status = (noheader!=0) ? BUSY_STATE : INIT_STATE;
+            strm.adler=strm._adler.adler32(0, null, 0, 0);
+
+            last_flush = Z_NO_FLUSH;
+
+            tr_init();
+            lm_init();
+            return Z_OK;
+        }
+
+        internal int deflateEnd(){
+            if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){
+                return Z_STREAM_ERROR;
+            }
+            // Deallocate in reverse order of allocations:
+            pending_buf=null;
+            head=null;
+            prev=null;
+            window=null;
+            // free
+            // dstate=null;
+            return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+        }
+
+        internal int deflateParams(ZStream strm, int _level, int _strategy){
+            int err=Z_OK;
+
+            if(_level == Z_DEFAULT_COMPRESSION){
+                _level = 6;
+            }
+            if(_level < 0 || _level > 9 || 
+                _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
+                return Z_STREAM_ERROR;
+            }
+
+            if(config_table[level].func!=config_table[_level].func &&
+                strm.total_in != 0) {
+                // Flush the last buffer:
+                err = strm.deflate(Z_PARTIAL_FLUSH);
+            }
+
+            if(level != _level) {
+                level = _level;
+                max_lazy_match   = config_table[level].max_lazy;
+                good_match       = config_table[level].good_length;
+                nice_match       = config_table[level].nice_length;
+                max_chain_length = config_table[level].max_chain;
+            }
+            strategy = _strategy;
+            return err;
+        }
+
+        internal int deflateSetDictionary (ZStream strm, byte[] dictionary, int dictLength){
+            int length = dictLength;
+            int index=0;
+
+            if(dictionary == null || status != INIT_STATE)
+                return Z_STREAM_ERROR;
+
+            strm.adler=strm._adler.adler32(strm.adler, dictionary, 0, dictLength);
+
+            if(length < MIN_MATCH) return Z_OK;
+            if(length > w_size-MIN_LOOKAHEAD){
+                length = w_size-MIN_LOOKAHEAD;
+                index=dictLength-length; // use the tail of the dictionary
+            }
+            System.Array.Copy(dictionary, index, window, 0, length);
+            strstart = length;
+            block_start = length;
+
+            // Insert all strings in the hash table (except for the last two bytes).
+            // s->lookahead stays null, so s->ins_h will be recomputed at the next
+            // call of fill_window.
+
+            ins_h = window[0]&0xff;
+            ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask;
+
+            for(int n=0; n<=length-MIN_MATCH; n++){
+                ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask;
+                prev[n&w_mask]=head[ins_h];
+                head[ins_h]=(short)n;
+            }
+            return Z_OK;
+        }
+
+        internal int deflate(ZStream strm, int flush){
+            int old_flush;
+
+            if(flush>Z_FINISH || flush<0){
+                return Z_STREAM_ERROR;
+            }
+
+            if(strm.next_out == null ||
+                (strm.next_in == null && strm.avail_in != 0) ||
+                (status == FINISH_STATE && flush != Z_FINISH)) {
+                strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)];
+                return Z_STREAM_ERROR;
+            }
+            if(strm.avail_out == 0){
+                strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+                return Z_BUF_ERROR;
+            }
+
+            this.strm = strm; // just in case
+            old_flush = last_flush;
+            last_flush = flush;
+
+            // Write the zlib header
+            if(status == INIT_STATE) {
+                int header = (Z_DEFLATED+((w_bits-8)<<4))<<8;
+                int level_flags=((level-1)&0xff)>>1;
+
+                if(level_flags>3) level_flags=3;
+                header |= (level_flags<<6);
+                if(strstart!=0) header |= PRESET_DICT;
+                header+=31-(header % 31);
+
+                status=BUSY_STATE;
+                putShortMSB(header);
+
+
+                // Save the adler32 of the preset dictionary:
+                if(strstart!=0){
+                    putShortMSB((int)(strm.adler>>16));
+                    putShortMSB((int)(strm.adler&0xffff));
+                }
+                strm.adler=strm._adler.adler32(0, null, 0, 0);
+            }
+
+            // Flush as much pending output as possible
+            if(pending != 0) {
+                strm.flush_pending();
+                if(strm.avail_out == 0) {
+                    //System.out.println("  avail_out==0");
+                    // Since avail_out is 0, deflate will be called again with
+                    // more output space, but possibly with both pending and
+                    // avail_in equal to zero. There won't be anything to do,
+                    // but this is not an error situation so make sure we
+                    // return OK instead of BUF_ERROR at next call of deflate:
+                    last_flush = -1;
+                    return Z_OK;
+                }
+
+                // Make sure there is something to do and avoid duplicate consecutive
+                // flushes. For repeated and useless calls with Z_FINISH, we keep
+                // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+            }
+            else if(strm.avail_in==0 && flush <= old_flush &&
+                flush != Z_FINISH) {
+                strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+                return Z_BUF_ERROR;
+            }
+
+            // User must not provide more input after the first FINISH:
+            if(status == FINISH_STATE && strm.avail_in != 0) {
+                strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+                return Z_BUF_ERROR;
+            }
+
+            // Start a new block or continue the current one.
+            if(strm.avail_in!=0 || lookahead!=0 ||
+                (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
+                int bstate=-1;
+                switch(config_table[level].func){
+                    case STORED: 
+                        bstate = deflate_stored(flush);
+                        break;
+                    case FAST: 
+                        bstate = deflate_fast(flush);
+                        break;
+                    case SLOW: 
+                        bstate = deflate_slow(flush);
+                        break;
+                    default:
+                        break;
+                }
+
+                if (bstate==FinishStarted || bstate==FinishDone) {
+                    status = FINISH_STATE;
+                }
+                if (bstate==NeedMore || bstate==FinishStarted) {
+                    if(strm.avail_out == 0) {
+                        last_flush = -1; // avoid BUF_ERROR next call, see above
+                    }
+                    return Z_OK;
+                    // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+                    // of deflate should use the same flush parameter to make sure
+                    // that the flush is complete. So we don't have to output an
+                    // empty block here, this will be done at next call. This also
+                    // ensures that for a very small output buffer, we emit at most
+                    // one empty block.
+                }
+
+                if (bstate==BlockDone) {
+                    if(flush == Z_PARTIAL_FLUSH) {
+                        _tr_align();
+                    } 
+                    else { // FULL_FLUSH or SYNC_FLUSH
+                        _tr_stored_block(0, 0, false);
+                        // For a full flush, this empty block will be recognized
+                        // as a special marker by inflate_sync().
+                        if(flush == Z_FULL_FLUSH) {
+                            //state.head[s.hash_size-1]=0;
+                            for(int i=0; i<hash_size/*-1*/; i++)  // forget history
+                                head[i]=0;
+                        }
+                    }
+                    strm.flush_pending();
+                    if(strm.avail_out == 0) {
+                        last_flush = -1; // avoid BUF_ERROR at next call, see above
+                        return Z_OK;
+                    }
+                }
+            }
+
+            if(flush!=Z_FINISH) return Z_OK;
+            if(noheader!=0) return Z_STREAM_END;
+
+            // Write the zlib trailer (adler32)
+            putShortMSB((int)(strm.adler>>16));
+            putShortMSB((int)(strm.adler&0xffff));
+            strm.flush_pending();
+
+            // If avail_out is zero, the application will call deflate again
+            // to flush the rest.
+            noheader = -1; // write the trailer only once!
+            return pending != 0 ? Z_OK : Z_STREAM_END;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/InfBlocks.cs b/BouncyCastle.AxCrypt/src/util/zlib/InfBlocks.cs
new file mode 100644
index 0000000..479d9b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/InfBlocks.cs
@@ -0,0 +1,618 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class InfBlocks{
+        private const int MANY=1440;
+
+        // And'ing with mask[n] masks the lower n bits
+        private static readonly int[] inflate_mask = {
+                                                0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+                                                0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+                                                0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+                                                0x00007fff, 0x0000ffff
+                                            };
+
+        // Table for deflate from PKZIP's appnote.txt.
+        static readonly int[] border = { // Order of the bit length code lengths
+                                  16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+                              };
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        private const int TYPE=0;  // get type bits (3, including end bit)
+        private const int LENS=1;  // get lengths for stored
+        private const int STORED=2;// processing stored block
+        private const int TABLE=3; // get table lengths
+        private const int BTREE=4; // get bit lengths tree for a dynamic block
+        private const int DTREE=5; // get length, distance trees for a dynamic block
+        private const int CODES=6; // processing fixed or dynamic block
+        private const int DRY=7;   // output remaining window bytes
+        private const int DONE=8;  // finished last block, done
+        private const int BAD=9;   // ot a data error--stuck here
+
+        internal int mode;            // current inflate_block mode 
+
+        internal int left;            // if STORED, bytes left to copy 
+
+        internal int table;           // table lengths (14 bits) 
+        internal int index;           // index into blens (or border) 
+        internal int[] blens;         // bit lengths of codes 
+        internal int[] bb=new int[1]; // bit length tree depth 
+        internal int[] tb=new int[1]; // bit length decoding tree 
+
+        internal InfCodes codes=new InfCodes();      // if CODES, current state 
+
+        int last;            // true if this block is the last block 
+
+        // mode independent information 
+        internal int bitk;            // bits in bit buffer 
+        internal int bitb;            // bit buffer 
+        internal int[] hufts;         // single malloc for tree space 
+        internal byte[] window;       // sliding window 
+        internal int end;             // one byte after sliding window 
+        internal int read;            // window read pointer 
+        internal int write;           // window write pointer 
+        internal Object checkfn;      // check function 
+        internal long check;          // check on output 
+
+        internal InfTree inftree=new InfTree();
+
+        internal InfBlocks(ZStream z, Object checkfn, int w){
+            hufts=new int[MANY*3];
+            window=new byte[w];
+            end=w;
+            this.checkfn = checkfn;
+            mode = TYPE;
+            reset(z, null);
+        }
+
+        internal void reset(ZStream z, long[] c){
+            if(c!=null) c[0]=check;
+            if(mode==BTREE || mode==DTREE){
+            }
+            if(mode==CODES){
+                codes.free(z);
+            }
+            mode=TYPE;
+            bitk=0;
+            bitb=0;
+            read=write=0;
+
+            if(checkfn != null)
+                z.adler=check=z._adler.adler32(0L, null, 0, 0);
+        }
+
+        internal int proc(ZStream z, int r){
+            int t;              // temporary storage
+            int b;              // bit buffer
+            int k;              // bits in bit buffer
+            int p;              // input data pointer
+            int n;              // bytes available there
+            int q;              // output window write pointer
+            int m; {              // bytes to end of window or read pointer
+
+            // copy input/output information to locals (UPDATE macro restores)
+     p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} {
+     q=write;m=(int)(q<read?read-q-1:end-q);}
+
+            // process input based on current state
+            while(true){
+                switch (mode){
+                    case TYPE:
+
+                        while(k<(3)){
+                            if(n!=0){
+                                r=Z_OK;
+                            }
+                            else{
+                                bitb=b; bitk=k; 
+                                z.avail_in=n;
+                                z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                write=q;
+                                return inflate_flush(z,r);
+                            };
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+                        t = (int)(b & 7);
+                        last = t & 1;
+
+                    switch (t >> 1){
+                        case 0: {                         // stored 
+           b>>=(3);k-=(3);}
+                            t = k & 7; {                    // go to byte boundary
+
+           b>>=(t);k-=(t);}
+                            mode = LENS;                  // get length of stored block
+                            break;
+                        case 1: {                         // fixed
+                            int[] bl=new int[1];
+                            int[] bd=new int[1];
+                            int[][] tl=new int[1][];
+                            int[][] td=new int[1][];
+
+                            InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
+                            codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+                        } {
+
+           b>>=(3);k-=(3);}
+
+                            mode = CODES;
+                            break;
+                        case 2: {                         // dynamic
+
+           b>>=(3);k-=(3);}
+
+                            mode = TABLE;
+                            break;
+                        case 3: {                         // illegal
+
+           b>>=(3);k-=(3);}
+                            mode = BAD;
+                            z.msg = "invalid block type";
+                            r = Z_DATA_ERROR;
+
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                    }
+                        break;
+                    case LENS:
+
+                        while(k<(32)){
+                            if(n!=0){
+                                r=Z_OK;
+                            }
+                            else{
+                                bitb=b; bitk=k; 
+                                z.avail_in=n;
+                                z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                write=q;
+                                return inflate_flush(z,r);
+                            };
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        if ((((~b) >> 16) & 0xffff) != (b & 0xffff)){
+                            mode = BAD;
+                            z.msg = "invalid stored block lengths";
+                            r = Z_DATA_ERROR;
+
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                        }
+                        left = (b & 0xffff);
+                        b = k = 0;                       // dump bits
+                        mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
+                        break;
+                    case STORED:
+                        if (n == 0){
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                        }
+
+                        if(m==0){
+                            if(q==end&&read!=0){
+                                q=0; m=(int)(q<read?read-q-1:end-q);
+                            }
+                            if(m==0){
+                                write=q; 
+                                r=inflate_flush(z,r);
+                                q=write;m=(int)(q<read?read-q-1:end-q);
+                                if(q==end&&read!=0){
+                                    q=0; m=(int)(q<read?read-q-1:end-q);
+                                }
+                                if(m==0){
+                                    bitb=b; bitk=k; 
+                                    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    write=q;
+                                    return inflate_flush(z,r);
+                                }
+                            }
+                        }
+                        r=Z_OK;
+
+                        t = left;
+                        if(t>n) t = n;
+                        if(t>m) t = m;
+                        System.Array.Copy(z.next_in, p, window, q, t);
+                        p += t;  n -= t;
+                        q += t;  m -= t;
+                        if ((left -= t) != 0)
+                            break;
+                        mode = last!=0 ? DRY : TYPE;
+                        break;
+                    case TABLE:
+
+                        while(k<(14)){
+                            if(n!=0){
+                                r=Z_OK;
+                            }
+                            else{
+                                bitb=b; bitk=k; 
+                                z.avail_in=n;
+                                z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                write=q;
+                                return inflate_flush(z,r);
+                            };
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        table = t = (b & 0x3fff);
+                        if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) {
+                            mode = BAD;
+                            z.msg = "too many length or distance symbols";
+                            r = Z_DATA_ERROR;
+
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                        }
+                        t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+                        if(blens==null || blens.Length<t){
+                            blens=new int[t];
+                        }
+                        else{
+                            for(int i=0; i<t; i++){blens[i]=0;}
+                        } {
+
+	 b>>=(14);k-=(14);}
+
+                        index = 0;
+                        mode = BTREE;
+                        goto case BTREE;
+                    case BTREE:
+                        while (index < 4 + (table >> 10)){
+                            while(k<(3)){
+                                if(n!=0){
+                                    r=Z_OK;
+                                }
+                                else{
+                                    bitb=b; bitk=k; 
+                                    z.avail_in=n;
+                                    z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    write=q;
+                                    return inflate_flush(z,r);
+                                };
+                                n--;
+                                b|=(z.next_in[p++]&0xff)<<k;
+                                k+=8;
+                            }
+
+                            blens[border[index++]] = b&7; {
+
+	   b>>=(3);k-=(3);}
+                        }
+
+                        while(index < 19){
+                            blens[border[index++]] = 0;
+                        }
+
+                        bb[0] = 7;
+                        t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
+                        if (t != Z_OK){
+                            r = t;
+                            if (r == Z_DATA_ERROR){
+                                blens=null;
+                                mode = BAD;
+                            }
+
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                        }
+
+                        index = 0;
+                        mode = DTREE;
+                        goto case DTREE;
+                    case DTREE:
+                        while (true){
+                            t = table;
+                            if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
+                                break;
+                            }
+
+                            int i, j, c;
+
+                            t = bb[0];
+
+                            while(k<(t)){
+                                if(n!=0){
+                                    r=Z_OK;
+                                }
+                                else{
+                                    bitb=b; bitk=k; 
+                                    z.avail_in=n;
+                                    z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    write=q;
+                                    return inflate_flush(z,r);
+                                };
+                                n--;
+                                b|=(z.next_in[p++]&0xff)<<k;
+                                k+=8;
+                            }
+
+                            if(tb[0]==-1){
+                                //System.err.println("null...");
+                            }
+
+                            t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
+                            c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
+
+                            if (c < 16){
+                                b>>=(t);k-=(t);
+                                blens[index++] = c;
+                            }
+                            else { // c == 16..18
+                                i = c == 18 ? 7 : c - 14;
+                                j = c == 18 ? 11 : 3;
+
+                                while(k<(t+i)){
+                                    if(n!=0){
+                                        r=Z_OK;
+                                    }
+                                    else{
+                                        bitb=b; bitk=k; 
+                                        z.avail_in=n;
+                                        z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                        write=q;
+                                        return inflate_flush(z,r);
+                                    };
+                                    n--;
+                                    b|=(z.next_in[p++]&0xff)<<k;
+                                    k+=8;
+                                }
+
+                                b>>=(t);k-=(t);
+
+                                j += (b & inflate_mask[i]);
+
+                                b>>=(i);k-=(i);
+
+                                i = index;
+                                t = table;
+                                if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+                                    (c == 16 && i < 1)){
+                                    blens=null;
+                                    mode = BAD;
+                                    z.msg = "invalid bit length repeat";
+                                    r = Z_DATA_ERROR;
+
+                                    bitb=b; bitk=k; 
+                                    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    write=q;
+                                    return inflate_flush(z,r);
+                                }
+
+                                c = c == 16 ? blens[i-1] : 0;
+                                do{
+                                    blens[i++] = c;
+                                }
+                                while (--j!=0);
+                                index = i;
+                            }
+                        }
+
+                        tb[0]=-1; {
+                        int[] bl=new int[1];
+                        int[] bd=new int[1];
+                        int[] tl=new int[1];
+                        int[] td=new int[1];
+                        bl[0] = 9;         // must be <= 9 for lookahead assumptions
+                        bd[0] = 6;         // must be <= 9 for lookahead assumptions
+
+                        t = table;
+                        t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 
+                            1 + ((t >> 5) & 0x1f),
+                            blens, bl, bd, tl, td, hufts, z);
+
+                        if (t != Z_OK){
+                            if (t == Z_DATA_ERROR){
+                                blens=null;
+                                mode = BAD;
+                            }
+                            r = t;
+
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z,r);
+                        }
+                        codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+                    }
+                        mode = CODES;
+                        goto case CODES;
+                    case CODES:
+                        bitb=b; bitk=k;
+                        z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        write=q;
+
+                        if ((r = codes.proc(this, z, r)) != Z_STREAM_END){
+                            return inflate_flush(z, r);
+                        }
+                        r = Z_OK;
+                        codes.free(z);
+
+                        p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
+                        q=write;m=(int)(q<read?read-q-1:end-q);
+
+                        if (last==0){
+                            mode = TYPE;
+                            break;
+                        }
+                        mode = DRY;
+                        goto case DRY;
+                    case DRY:
+                        write=q; 
+                        r=inflate_flush(z, r); 
+                        q=write; m=(int)(q<read?read-q-1:end-q);
+                        if (read != write){
+                            bitb=b; bitk=k; 
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            write=q;
+                            return inflate_flush(z, r);
+                        }
+                        mode = DONE;
+                        goto case DONE;
+                    case DONE:
+                        r = Z_STREAM_END;
+
+                        bitb=b; bitk=k; 
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        write=q;
+                        return inflate_flush(z, r);
+                    case BAD:
+                        r = Z_DATA_ERROR;
+
+                        bitb=b; bitk=k; 
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        write=q;
+                        return inflate_flush(z, r);
+
+                    default:
+                        r = Z_STREAM_ERROR;
+
+                        bitb=b; bitk=k; 
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        write=q;
+                        return inflate_flush(z, r);
+                }
+            }
+        }
+
+        internal void free(ZStream z){
+            reset(z, null);
+            window=null;
+            hufts=null;
+            //ZFREE(z, s);
+        }
+
+        internal void set_dictionary(byte[] d, int start, int n){
+            System.Array.Copy(d, start, window, 0, n);
+            read = write = n;
+        }
+
+        // Returns true if inflate is currently at the end of a block generated
+        // by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+        internal int sync_point(){
+            return mode == LENS ? 1 : 0;
+        }
+
+        // copy as much as possible from the sliding window to the output area
+        internal int inflate_flush(ZStream z, int r){
+            int n;
+            int p;
+            int q;
+
+            // local copies of source and destination pointers
+            p = z.next_out_index;
+            q = read;
+
+            // compute number of bytes to copy as far as end of window
+            n = (int)((q <= write ? write : end) - q);
+            if (n > z.avail_out) n = z.avail_out;
+            if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
+
+            // update counters
+            z.avail_out -= n;
+            z.total_out += n;
+
+            // update check information
+            if(checkfn != null)
+                z.adler=check=z._adler.adler32(check, window, q, n);
+
+            // copy as far as end of window
+            System.Array.Copy(window, q, z.next_out, p, n);
+            p += n;
+            q += n;
+
+            // see if more to copy at beginning of window
+            if (q == end){
+                // wrap pointers
+                q = 0;
+                if (write == end)
+                    write = 0;
+
+                // compute bytes to copy
+                n = write - q;
+                if (n > z.avail_out) n = z.avail_out;
+                if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
+
+                // update counters
+                z.avail_out -= n;
+                z.total_out += n;
+
+                // update check information
+                if(checkfn != null)
+                    z.adler=check=z._adler.adler32(check, window, q, n);
+
+                // copy
+                System.Array.Copy(window, q, z.next_out, p, n);
+                p += n;
+                q += n;
+            }
+
+            // update pointers
+            z.next_out_index = p;
+            read = q;
+
+            // done
+            return r;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/InfCodes.cs b/BouncyCastle.AxCrypt/src/util/zlib/InfCodes.cs
new file mode 100644
index 0000000..6fcafe4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/InfCodes.cs
@@ -0,0 +1,611 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class InfCodes{
+
+        private static readonly int[] inflate_mask = {
+                                                0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+                                                0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+                                                0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+                                                0x00007fff, 0x0000ffff
+                                            };
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        // waiting for "i:"=input,
+        //             "o:"=output,
+        //             "x:"=nothing
+        private const int START=0;  // x: set up for LEN
+        private const int LEN=1;    // i: get length/literal/eob next
+        private const int LENEXT=2; // i: getting length extra (have base)
+        private const int DIST=3;   // i: get distance next
+        private const int DISTEXT=4;// i: getting distance extra
+        private const int COPY=5;   // o: copying bytes in window, waiting for space
+        private const int LIT=6;    // o: got literal, waiting for output space
+        private const int WASH=7;   // o: got eob, possibly still output waiting
+        private const int END=8;    // x: got eob and all data flushed
+        private const int BADCODE=9;// x: got error
+
+        int mode;      // current inflate_codes mode
+
+        // mode dependent information
+        int len;
+
+        int[] tree; // pointer into tree
+        int tree_index=0;
+        int need;   // bits needed
+
+        int lit;
+
+        // if EXT or COPY, where and how much
+        int get;              // bits to get for extra
+        int dist;             // distance back to copy from
+
+        byte lbits;           // ltree bits decoded per branch
+        byte dbits;           // dtree bits decoder per branch
+        int[] ltree;          // literal/length/eob tree
+        int ltree_index;      // literal/length/eob tree
+        int[] dtree;          // distance tree
+        int dtree_index;      // distance tree
+
+        internal InfCodes(){
+        }
+        internal void init(int bl, int bd,
+            int[] tl, int tl_index,
+            int[] td, int td_index, ZStream z){
+            mode=START;
+            lbits=(byte)bl;
+            dbits=(byte)bd;
+            ltree=tl;
+            ltree_index=tl_index;
+            dtree = td;
+            dtree_index=td_index;
+            tree=null;
+        }
+
+        internal int proc(InfBlocks s, ZStream z, int r){ 
+            int j;              // temporary storage
+            int tindex;         // temporary pointer
+            int e;              // extra bits or operation
+            int b=0;            // bit buffer
+            int k=0;            // bits in bit buffer
+            int p=0;            // input data pointer
+            int n;              // bytes available there
+            int q;              // output window write pointer
+            int m;              // bytes to end of window or read pointer
+            int f;              // pointer to copy strings from
+
+            // copy input/output information to locals (UPDATE macro restores)
+            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+            // process input and output based on current state
+            while (true){
+                switch (mode){
+                        // waiting for "i:"=input, "o:"=output, "x:"=nothing
+                    case START:         // x: set up for LEN
+                        if (m >= 258 && n >= 10){
+
+                            s.bitb=b;s.bitk=k;
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            s.write=q;
+                            r = inflate_fast(lbits, dbits, 
+                                ltree, ltree_index, 
+                                dtree, dtree_index,
+                                s, z);
+
+                            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+                            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                            if (r != Z_OK){
+                                mode = r == Z_STREAM_END ? WASH : BADCODE;
+                                break;
+                            }
+                        }
+                        need = lbits;
+                        tree = ltree;
+                        tree_index=ltree_index;
+
+                        mode = LEN;
+                        goto case LEN;
+                    case LEN:           // i: get length/literal/eob next
+                        j = need;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        tindex=(tree_index+(b&inflate_mask[j]))*3;
+
+                        b>>=(tree[tindex+1]);
+                        k-=(tree[tindex+1]);
+
+                        e=tree[tindex];
+
+                        if(e == 0){               // literal
+                            lit = tree[tindex+2];
+                            mode = LIT;
+                            break;
+                        }
+                        if((e & 16)!=0 ){          // length
+                            get = e & 15;
+                            len = tree[tindex+2];
+                            mode = LENEXT;
+                            break;
+                        }
+                        if ((e & 64) == 0){        // next table
+                            need = e;
+                            tree_index = tindex/3+tree[tindex+2];
+                            break;
+                        }
+                        if ((e & 32)!=0){               // end of block
+                            mode = WASH;
+                            break;
+                        }
+                        mode = BADCODE;        // invalid code
+                        z.msg = "invalid literal/length code";
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case LENEXT:        // i: getting length extra (have base)
+                        j = get;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        len += (b & inflate_mask[j]);
+
+                        b>>=j;
+                        k-=j;
+
+                        need = dbits;
+                        tree = dtree;
+                        tree_index=dtree_index;
+                        mode = DIST;
+                        goto case DIST;
+                    case DIST:          // i: get distance next
+                        j = need;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        tindex=(tree_index+(b & inflate_mask[j]))*3;
+
+                        b>>=tree[tindex+1];
+                        k-=tree[tindex+1];
+
+                        e = (tree[tindex]);
+                        if((e & 16)!=0){               // distance
+                            get = e & 15;
+                            dist = tree[tindex+2];
+                            mode = DISTEXT;
+                            break;
+                        }
+                        if ((e & 64) == 0){        // next table
+                            need = e;
+                            tree_index = tindex/3 + tree[tindex+2];
+                            break;
+                        }
+                        mode = BADCODE;        // invalid code
+                        z.msg = "invalid distance code";
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case DISTEXT:       // i: getting distance extra
+                        j = get;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        dist += (b & inflate_mask[j]);
+
+                        b>>=j;
+                        k-=j;
+
+                        mode = COPY;
+                        goto case COPY;
+                    case COPY:          // o: copying bytes in window, waiting for space
+                        f = q - dist;
+                        while(f < 0){     // modulo window size-"while" instead
+                            f += s.end;     // of "if" handles invalid distances
+                        }
+                        while (len!=0){
+
+                            if(m==0){
+                                if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                                if(m==0){
+                                    s.write=q; r=s.inflate_flush(z,r);
+                                    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                                    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+
+                                    if(m==0){
+                                        s.bitb=b;s.bitk=k;
+                                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                        s.write=q;
+                                        return s.inflate_flush(z,r);
+                                    }  
+                                }
+                            }
+
+                            s.window[q++]=s.window[f++]; m--;
+
+                            if (f == s.end)
+                                f = 0;
+                            len--;
+                        }
+                        mode = START;
+                        break;
+                    case LIT:           // o: got literal, waiting for output space
+                        if(m==0){
+                            if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                            if(m==0){
+                                s.write=q; r=s.inflate_flush(z,r);
+                                q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                                if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                                if(m==0){
+                                    s.bitb=b;s.bitk=k;
+                                    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    s.write=q;
+                                    return s.inflate_flush(z,r);
+                                }
+                            }
+                        }
+                        r=Z_OK;
+
+                        s.window[q++]=(byte)lit; m--;
+
+                        mode = START;
+                        break;
+                    case WASH:           // o: got eob, possibly more output
+                        if (k > 7){        // return unused byte, if any
+                            k -= 8;
+                            n++;
+                            p--;             // can always return one
+                        }
+
+                        s.write=q; r=s.inflate_flush(z,r);
+                        q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                        if (s.read != s.write){
+                            s.bitb=b;s.bitk=k;
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            s.write=q;
+                            return s.inflate_flush(z,r);
+                        }
+                        mode = END;
+                        goto case END;
+                    case END:
+                        r = Z_STREAM_END;
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case BADCODE:       // x: got error
+
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    default:
+                        r = Z_STREAM_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+                }
+            }
+        }
+
+        internal void free(ZStream z){
+            //  ZFREE(z, c);
+        }
+
+        // Called with number of bytes left to write in window at least 258
+        // (the maximum string length) and number of input bytes available
+        // at least ten.  The ten bytes are six bytes for the longest length/
+        // distance pair plus four bytes for overloading the bit buffer.
+
+        internal int inflate_fast(int bl, int bd, 
+            int[] tl, int tl_index,
+            int[] td, int td_index,
+            InfBlocks s, ZStream z){
+            int t;                // temporary pointer
+            int[] tp;             // temporary pointer
+            int tp_index;         // temporary pointer
+            int e;                // extra bits or operation
+            int b;                // bit buffer
+            int k;                // bits in bit buffer
+            int p;                // input data pointer
+            int n;                // bytes available there
+            int q;                // output window write pointer
+            int m;                // bytes to end of window or read pointer
+            int ml;               // mask for literal/length tree
+            int md;               // mask for distance tree
+            int c;                // bytes to copy
+            int d;                // distance back to copy from
+            int r;                // copy source pointer
+
+            int tp_index_t_3;     // (tp_index+t)*3
+
+            // load input, output, bit values
+            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+            // initialize masks
+            ml = inflate_mask[bl];
+            md = inflate_mask[bd];
+
+            // do until not enough input or output space for fast loop
+            do {                          // assume called with m >= 258 && n >= 10
+                // get literal/length code
+            while(k<(20)){              // max bits for literal/length code
+                n--;
+                b|=(z.next_in[p++]&0xff)<<k;k+=8;
+            }
+
+                t= b&ml;
+                tp=tl; 
+                tp_index=tl_index;
+                tp_index_t_3=(tp_index+t)*3;
+                if ((e = tp[tp_index_t_3]) == 0){
+                    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                    s.window[q++] = (byte)tp[tp_index_t_3+2];
+                    m--;
+                    continue;
+                }
+                do {
+
+                    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                    if((e&16)!=0){
+                        e &= 15;
+                        c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
+
+                        b>>=e; k-=e;
+
+                        // decode distance base of block to copy
+                        while(k<(15)){           // max bits for distance code
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;k+=8;
+                        }
+
+                        t= b&md;
+                        tp=td;
+                        tp_index=td_index;
+                        tp_index_t_3=(tp_index+t)*3;
+                        e = tp[tp_index_t_3];
+
+                        do {
+
+                            b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                            if((e&16)!=0){
+                                // get extra bits to add to distance base
+                                e &= 15;
+                                while(k<(e)){         // get extra bits (up to 13)
+                                    n--;
+                                    b|=(z.next_in[p++]&0xff)<<k;k+=8;
+                                }
+
+                                d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
+
+                                b>>=(e); k-=(e);
+
+                                // do the copy
+                                m -= c;
+                                if (q >= d){                // offset before dest
+                                    //  just copy
+                                    r=q-d;
+                                    if(q-r>0 && 2>(q-r)){           
+                                        s.window[q++]=s.window[r++]; // minimum count is three,
+                                        s.window[q++]=s.window[r++]; // so unroll loop a little
+                                        c-=2;
+                                    }
+                                    else{
+                                        System.Array.Copy(s.window, r, s.window, q, 2);
+                                        q+=2; r+=2; c-=2;
+                                    }
+                                }
+                                else{                  // else offset after destination
+                                    r=q-d;
+                                    do{
+                                        r+=s.end;          // force pointer in window
+                                    }while(r<0);         // covers invalid distances
+                                    e=s.end-r;
+                                    if(c>e){             // if source crosses,
+                                        c-=e;              // wrapped copy
+                                        if(q-r>0 && e>(q-r)){           
+                                            do{s.window[q++] = s.window[r++];}
+                                            while(--e!=0);
+                                        }
+                                        else{
+                                            System.Array.Copy(s.window, r, s.window, q, e);
+                                            q+=e; r+=e; e=0;
+                                        }
+                                        r = 0;                  // copy rest from start of window
+                                    }
+
+                                }
+
+                                // copy all or what's left
+                                if(q-r>0 && c>(q-r)){           
+                                    do{s.window[q++] = s.window[r++];}
+                                    while(--c!=0);
+                                }
+                                else{
+                                    System.Array.Copy(s.window, r, s.window, q, c);
+                                    q+=c; r+=c; c=0;
+                                }
+                                break;
+                            }
+                            else if((e&64)==0){
+                                t+=tp[tp_index_t_3+2];
+                                t+=(b&inflate_mask[e]);
+                                tp_index_t_3=(tp_index+t)*3;
+                                e=tp[tp_index_t_3];
+                            }
+                            else{
+                                z.msg = "invalid distance code";
+
+                                c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+
+                                return Z_DATA_ERROR;
+                            }
+                        }
+                        while(true);
+                        break;
+                    }
+
+                    if((e&64)==0){
+                        t+=tp[tp_index_t_3+2];
+                        t+=(b&inflate_mask[e]);
+                        tp_index_t_3=(tp_index+t)*3;
+                        if((e=tp[tp_index_t_3])==0){
+
+                            b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                            s.window[q++]=(byte)tp[tp_index_t_3+2];
+                            m--;
+                            break;
+                        }
+                    }
+                    else if((e&32)!=0){
+
+                        c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+ 
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+
+                        return Z_STREAM_END;
+                    }
+                    else{
+                        z.msg="invalid literal/length code";
+
+                        c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+
+                        return Z_DATA_ERROR;
+                    }
+                } 
+                while(true);
+            } 
+            while(m>=258 && n>= 10);
+
+            // not enough input or output--restore pointers and return
+            c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+            s.bitb=b;s.bitk=k;
+            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+            s.write=q;
+
+            return Z_OK;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/InfTree.cs b/BouncyCastle.AxCrypt/src/util/zlib/InfTree.cs
new file mode 100644
index 0000000..6ed7d19
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/InfTree.cs
@@ -0,0 +1,523 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class InfTree{
+
+        private const int MANY=1440;
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        private const int fixed_bl = 9;
+        private const int fixed_bd = 5;
+
+		static readonly int[] fixed_tl = {
+                                    96,7,256, 0,8,80, 0,8,16, 84,8,115,
+                                    82,7,31, 0,8,112, 0,8,48, 0,9,192,
+                                    80,7,10, 0,8,96, 0,8,32, 0,9,160,
+                                    0,8,0, 0,8,128, 0,8,64, 0,9,224,
+                                    80,7,6, 0,8,88, 0,8,24, 0,9,144,
+                                    83,7,59, 0,8,120, 0,8,56, 0,9,208,
+                                    81,7,17, 0,8,104, 0,8,40, 0,9,176,
+                                    0,8,8, 0,8,136, 0,8,72, 0,9,240,
+                                    80,7,4, 0,8,84, 0,8,20, 85,8,227,
+                                    83,7,43, 0,8,116, 0,8,52, 0,9,200,
+                                    81,7,13, 0,8,100, 0,8,36, 0,9,168,
+                                    0,8,4, 0,8,132, 0,8,68, 0,9,232,
+                                    80,7,8, 0,8,92, 0,8,28, 0,9,152,
+                                    84,7,83, 0,8,124, 0,8,60, 0,9,216,
+                                    82,7,23, 0,8,108, 0,8,44, 0,9,184,
+                                    0,8,12, 0,8,140, 0,8,76, 0,9,248,
+                                    80,7,3, 0,8,82, 0,8,18, 85,8,163,
+                                    83,7,35, 0,8,114, 0,8,50, 0,9,196,
+                                    81,7,11, 0,8,98, 0,8,34, 0,9,164,
+                                    0,8,2, 0,8,130, 0,8,66, 0,9,228,
+                                    80,7,7, 0,8,90, 0,8,26, 0,9,148,
+                                    84,7,67, 0,8,122, 0,8,58, 0,9,212,
+                                    82,7,19, 0,8,106, 0,8,42, 0,9,180,
+                                    0,8,10, 0,8,138, 0,8,74, 0,9,244,
+                                    80,7,5, 0,8,86, 0,8,22, 192,8,0,
+                                    83,7,51, 0,8,118, 0,8,54, 0,9,204,
+                                    81,7,15, 0,8,102, 0,8,38, 0,9,172,
+                                    0,8,6, 0,8,134, 0,8,70, 0,9,236,
+                                    80,7,9, 0,8,94, 0,8,30, 0,9,156,
+                                    84,7,99, 0,8,126, 0,8,62, 0,9,220,
+                                    82,7,27, 0,8,110, 0,8,46, 0,9,188,
+                                    0,8,14, 0,8,142, 0,8,78, 0,9,252,
+                                    96,7,256, 0,8,81, 0,8,17, 85,8,131,
+                                    82,7,31, 0,8,113, 0,8,49, 0,9,194,
+                                    80,7,10, 0,8,97, 0,8,33, 0,9,162,
+                                    0,8,1, 0,8,129, 0,8,65, 0,9,226,
+                                    80,7,6, 0,8,89, 0,8,25, 0,9,146,
+                                    83,7,59, 0,8,121, 0,8,57, 0,9,210,
+                                    81,7,17, 0,8,105, 0,8,41, 0,9,178,
+                                    0,8,9, 0,8,137, 0,8,73, 0,9,242,
+                                    80,7,4, 0,8,85, 0,8,21, 80,8,258,
+                                    83,7,43, 0,8,117, 0,8,53, 0,9,202,
+                                    81,7,13, 0,8,101, 0,8,37, 0,9,170,
+                                    0,8,5, 0,8,133, 0,8,69, 0,9,234,
+                                    80,7,8, 0,8,93, 0,8,29, 0,9,154,
+                                    84,7,83, 0,8,125, 0,8,61, 0,9,218,
+                                    82,7,23, 0,8,109, 0,8,45, 0,9,186,
+                                    0,8,13, 0,8,141, 0,8,77, 0,9,250,
+                                    80,7,3, 0,8,83, 0,8,19, 85,8,195,
+                                    83,7,35, 0,8,115, 0,8,51, 0,9,198,
+                                    81,7,11, 0,8,99, 0,8,35, 0,9,166,
+                                    0,8,3, 0,8,131, 0,8,67, 0,9,230,
+                                    80,7,7, 0,8,91, 0,8,27, 0,9,150,
+                                    84,7,67, 0,8,123, 0,8,59, 0,9,214,
+                                    82,7,19, 0,8,107, 0,8,43, 0,9,182,
+                                    0,8,11, 0,8,139, 0,8,75, 0,9,246,
+                                    80,7,5, 0,8,87, 0,8,23, 192,8,0,
+                                    83,7,51, 0,8,119, 0,8,55, 0,9,206,
+                                    81,7,15, 0,8,103, 0,8,39, 0,9,174,
+                                    0,8,7, 0,8,135, 0,8,71, 0,9,238,
+                                    80,7,9, 0,8,95, 0,8,31, 0,9,158,
+                                    84,7,99, 0,8,127, 0,8,63, 0,9,222,
+                                    82,7,27, 0,8,111, 0,8,47, 0,9,190,
+                                    0,8,15, 0,8,143, 0,8,79, 0,9,254,
+                                    96,7,256, 0,8,80, 0,8,16, 84,8,115,
+                                    82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+                                    80,7,10, 0,8,96, 0,8,32, 0,9,161,
+                                    0,8,0, 0,8,128, 0,8,64, 0,9,225,
+                                    80,7,6, 0,8,88, 0,8,24, 0,9,145,
+                                    83,7,59, 0,8,120, 0,8,56, 0,9,209,
+                                    81,7,17, 0,8,104, 0,8,40, 0,9,177,
+                                    0,8,8, 0,8,136, 0,8,72, 0,9,241,
+                                    80,7,4, 0,8,84, 0,8,20, 85,8,227,
+                                    83,7,43, 0,8,116, 0,8,52, 0,9,201,
+                                    81,7,13, 0,8,100, 0,8,36, 0,9,169,
+                                    0,8,4, 0,8,132, 0,8,68, 0,9,233,
+                                    80,7,8, 0,8,92, 0,8,28, 0,9,153,
+                                    84,7,83, 0,8,124, 0,8,60, 0,9,217,
+                                    82,7,23, 0,8,108, 0,8,44, 0,9,185,
+                                    0,8,12, 0,8,140, 0,8,76, 0,9,249,
+                                    80,7,3, 0,8,82, 0,8,18, 85,8,163,
+                                    83,7,35, 0,8,114, 0,8,50, 0,9,197,
+                                    81,7,11, 0,8,98, 0,8,34, 0,9,165,
+                                    0,8,2, 0,8,130, 0,8,66, 0,9,229,
+                                    80,7,7, 0,8,90, 0,8,26, 0,9,149,
+                                    84,7,67, 0,8,122, 0,8,58, 0,9,213,
+                                    82,7,19, 0,8,106, 0,8,42, 0,9,181,
+                                    0,8,10, 0,8,138, 0,8,74, 0,9,245,
+                                    80,7,5, 0,8,86, 0,8,22, 192,8,0,
+                                    83,7,51, 0,8,118, 0,8,54, 0,9,205,
+                                    81,7,15, 0,8,102, 0,8,38, 0,9,173,
+                                    0,8,6, 0,8,134, 0,8,70, 0,9,237,
+                                    80,7,9, 0,8,94, 0,8,30, 0,9,157,
+                                    84,7,99, 0,8,126, 0,8,62, 0,9,221,
+                                    82,7,27, 0,8,110, 0,8,46, 0,9,189,
+                                    0,8,14, 0,8,142, 0,8,78, 0,9,253,
+                                    96,7,256, 0,8,81, 0,8,17, 85,8,131,
+                                    82,7,31, 0,8,113, 0,8,49, 0,9,195,
+                                    80,7,10, 0,8,97, 0,8,33, 0,9,163,
+                                    0,8,1, 0,8,129, 0,8,65, 0,9,227,
+                                    80,7,6, 0,8,89, 0,8,25, 0,9,147,
+                                    83,7,59, 0,8,121, 0,8,57, 0,9,211,
+                                    81,7,17, 0,8,105, 0,8,41, 0,9,179,
+                                    0,8,9, 0,8,137, 0,8,73, 0,9,243,
+                                    80,7,4, 0,8,85, 0,8,21, 80,8,258,
+                                    83,7,43, 0,8,117, 0,8,53, 0,9,203,
+                                    81,7,13, 0,8,101, 0,8,37, 0,9,171,
+                                    0,8,5, 0,8,133, 0,8,69, 0,9,235,
+                                    80,7,8, 0,8,93, 0,8,29, 0,9,155,
+                                    84,7,83, 0,8,125, 0,8,61, 0,9,219,
+                                    82,7,23, 0,8,109, 0,8,45, 0,9,187,
+                                    0,8,13, 0,8,141, 0,8,77, 0,9,251,
+                                    80,7,3, 0,8,83, 0,8,19, 85,8,195,
+                                    83,7,35, 0,8,115, 0,8,51, 0,9,199,
+                                    81,7,11, 0,8,99, 0,8,35, 0,9,167,
+                                    0,8,3, 0,8,131, 0,8,67, 0,9,231,
+                                    80,7,7, 0,8,91, 0,8,27, 0,9,151,
+                                    84,7,67, 0,8,123, 0,8,59, 0,9,215,
+                                    82,7,19, 0,8,107, 0,8,43, 0,9,183,
+                                    0,8,11, 0,8,139, 0,8,75, 0,9,247,
+                                    80,7,5, 0,8,87, 0,8,23, 192,8,0,
+                                    83,7,51, 0,8,119, 0,8,55, 0,9,207,
+                                    81,7,15, 0,8,103, 0,8,39, 0,9,175,
+                                    0,8,7, 0,8,135, 0,8,71, 0,9,239,
+                                    80,7,9, 0,8,95, 0,8,31, 0,9,159,
+                                    84,7,99, 0,8,127, 0,8,63, 0,9,223,
+                                    82,7,27, 0,8,111, 0,8,47, 0,9,191,
+                                    0,8,15, 0,8,143, 0,8,79, 0,9,255
+                                };
+        static readonly int[] fixed_td = {
+                                    80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+                                    81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+                                    80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+                                    82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+                                    80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+                                    81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+                                    80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+                                    82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+                                };
+
+        // Tables for deflate from PKZIP's appnote.txt.
+        static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+                                  3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+                                  35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+                              };
+
+        // see note #13 above about 258
+        static readonly int[] cplext = { // Extra bits for literal codes 257..285
+                                  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+                                  3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112  // 112==invalid
+                              };
+
+        static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+                                  1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+                                  257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+                                  8193, 12289, 16385, 24577
+                              };
+
+        static readonly int[] cpdext = { // Extra bits for distance codes
+                                  0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+                                  7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+                                  12, 12, 13, 13};
+
+        // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+        const int BMAX=15;         // maximum bit length of any code
+
+        int[] hn = null;  // hufts used in space
+        int[] v = null;   // work area for huft_build 
+        int[] c = null;   // bit length count table
+        int[] r = null;   // table entry for structure assignment
+        int[] u = null;   // table stack
+        int[] x = null;   // bit offsets, then code stack
+
+        private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
+            int bindex, 
+            int n,   // number of codes (assumed <= 288)
+            int s,   // number of simple-valued codes (0..s-1)
+            int[] d, // list of base values for non-simple codes
+            int[] e, // list of extra bits for non-simple codes
+            int[] t, // result: starting table
+            int[] m, // maximum lookup bits, returns actual
+            int[] hp,// space for trees
+            int[] hn,// hufts used in space
+            int[] v  // working area: values in order of bit length
+            ){
+            // Given a list of code lengths and a maximum table size, make a set of
+            // tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+            // if the given code set is incomplete (the tables are still built in this
+            // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+            // lengths), or Z_MEM_ERROR if not enough memory.
+
+            int a;                       // counter for codes of length k
+            int f;                       // i repeats in table every f entries
+            int g;                       // maximum code length
+            int h;                       // table level
+            int i;                       // counter, current code
+            int j;                       // counter
+            int k;                       // number of bits in current code
+            int l;                       // bits per table (returned in m)
+            int mask;                    // (1 << w) - 1, to avoid cc -O bug on HP
+            int p;                       // pointer into c[], b[], or v[]
+            int q;                       // points to current table
+            int w;                       // bits before this table == (l * h)
+            int xp;                      // pointer into x
+            int y;                       // number of dummy codes added
+            int z;                       // number of entries in current table
+
+            // Generate counts for each bit length
+
+            p = 0; i = n;
+            do {
+                c[b[bindex+p]]++; p++; i--;   // assume all entries <= BMAX
+            }while(i!=0);
+
+            if(c[0] == n){                // null input--all zero length codes
+                t[0] = -1;
+                m[0] = 0;
+                return Z_OK;
+            }
+
+            // Find minimum and maximum length, bound *m by those
+            l = m[0];
+            for (j = 1; j <= BMAX; j++)
+                if(c[j]!=0) break;
+            k = j;                        // minimum code length
+            if(l < j){
+                l = j;
+            }
+            for (i = BMAX; i!=0; i--){
+                if(c[i]!=0) break;
+            }
+            g = i;                        // maximum code length
+            if(l > i){
+                l = i;
+            }
+            m[0] = l;
+
+            // Adjust last length count to fill out codes, if needed
+            for (y = 1 << j; j < i; j++, y <<= 1){
+                if ((y -= c[j]) < 0){
+                    return Z_DATA_ERROR;
+                }
+            }
+            if ((y -= c[i]) < 0){
+                return Z_DATA_ERROR;
+            }
+            c[i] += y;
+
+            // Generate starting offsets into the value table for each length
+            x[1] = j = 0;
+            p = 1;  xp = 2;
+            while (--i!=0) {                 // note that i == g from above
+                x[xp] = (j += c[p]);
+                xp++;
+                p++;
+            }
+
+            // Make a table of values in order of bit lengths
+            i = 0; p = 0;
+            do {
+                if ((j = b[bindex+p]) != 0){
+                    v[x[j]++] = i;
+                }
+                p++;
+            }
+            while (++i < n);
+            n = x[g];                     // set n to length of v
+
+            // Generate the Huffman codes and for each, make the table entries
+            x[0] = i = 0;                 // first Huffman code is zero
+            p = 0;                        // grab values in bit order
+            h = -1;                       // no tables yet--level -1
+            w = -l;                       // bits decoded == (l * h)
+            u[0] = 0;                     // just to keep compilers happy
+            q = 0;                        // ditto
+            z = 0;                        // ditto
+
+            // go through the bit lengths (k already is bits in shortest code)
+            for (; k <= g; k++){
+                a = c[k];
+                while (a--!=0){
+                    // here i is the Huffman code of length k bits for value *p
+                    // make tables up to required level
+                    while (k > w + l){
+                        h++;
+                        w += l;                 // previous table always l bits
+                        // compute minimum size table less than or equal to l bits
+                        z = g - w;
+                        z = (z > l) ? l : z;        // table size upper limit
+                        if((f=1<<(j=k-w))>a+1){     // try a k-w bit table
+                            // too few codes for k-w bit table
+                            f -= a + 1;               // deduct codes from patterns left
+                            xp = k;
+                            if(j < z){
+                                while (++j < z){        // try smaller tables up to z bits
+                                    if((f <<= 1) <= c[++xp])
+                                        break;              // enough codes to use up j bits
+                                    f -= c[xp];           // else deduct codes from patterns
+                                }
+                            }
+                        }
+                        z = 1 << j;                 // table entries for j-bit table
+
+                        // allocate new table
+                        if (hn[0] + z > MANY){       // (note: doesn't matter for fixed)
+                            return Z_DATA_ERROR;       // overflow of MANY
+                        }
+                        u[h] = q = /*hp+*/ hn[0];   // DEBUG
+                        hn[0] += z;
+ 
+                        // connect to last table, if there is one
+                        if(h!=0){
+                            x[h]=i;           // save pattern for backing up
+                            r[0]=(byte)j;     // bits in this table
+                            r[1]=(byte)l;     // bits to dump before this table
+                            j=i>>(w - l);
+                            r[2] = (int)(q - u[h-1] - j);               // offset to this table
+                            System.Array.Copy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
+                        }
+                        else{
+                            t[0] = q;               // first table is returned result
+                        }
+                    }
+
+                    // set up table entry in r
+                    r[1] = (byte)(k - w);
+                    if (p >= n){
+                        r[0] = 128 + 64;      // out of values--invalid code
+                    }
+                    else if (v[p] < s){
+                        r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64);  // 256 is end-of-block
+                        r[2] = v[p++];          // simple code is just the value
+                    }
+                    else{
+                        r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
+                        r[2]=d[v[p++] - s];
+                    }
+
+                    // fill code-like entries with r
+                    f=1<<(k-w);
+                    for (j=i>>w;j<z;j+=f){
+                        System.Array.Copy(r, 0, hp, (q+j)*3, 3);
+                    }
+
+                    // backwards increment the k-bit code i
+                    for (j = 1 << (k - 1); (i & j)!=0; j >>= 1){
+                        i ^= j;
+                    }
+                    i ^= j;
+
+                    // backup over finished tables
+                    mask = (1 << w) - 1;      // needed on HP, cc -O bug
+                    while ((i & mask) != x[h]){
+                        h--;                    // don't need to update q
+                        w -= l;
+                        mask = (1 << w) - 1;
+                    }
+                }
+            }
+            // Return Z_BUF_ERROR if we were given an incomplete table
+            return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+        }
+
+        internal int inflate_trees_bits(int[] c,  // 19 code lengths
+            int[] bb, // bits tree desired/actual depth
+            int[] tb, // bits tree result
+            int[] hp, // space for trees
+            ZStream z // for messages
+            ){
+            int result;
+            initWorkArea(19);
+            hn[0]=0;
+            result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+            if(result == Z_DATA_ERROR){
+                z.msg = "oversubscribed dynamic bit lengths tree";
+            }
+            else if(result == Z_BUF_ERROR || bb[0] == 0){
+                z.msg = "incomplete dynamic bit lengths tree";
+                result = Z_DATA_ERROR;
+            }
+            return result;
+        }
+
+        internal int inflate_trees_dynamic(int nl,   // number of literal/length codes
+            int nd,   // number of distance codes
+            int[] c,  // that many (total) code lengths
+            int[] bl, // literal desired/actual bit depth
+            int[] bd, // distance desired/actual bit depth 
+            int[] tl, // literal/length tree result
+            int[] td, // distance tree result
+            int[] hp, // space for trees
+            ZStream z // for messages
+            ){
+            int result;
+
+            // build literal/length tree
+            initWorkArea(288);
+            hn[0]=0;
+            result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+            if (result != Z_OK || bl[0] == 0){
+                if(result == Z_DATA_ERROR){
+                    z.msg = "oversubscribed literal/length tree";
+                }
+                else if (result != Z_MEM_ERROR){
+                    z.msg = "incomplete literal/length tree";
+                    result = Z_DATA_ERROR;
+                }
+                return result;
+            }
+
+            // build distance tree
+            initWorkArea(288);
+            result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+            if (result != Z_OK || (bd[0] == 0 && nl > 257)){
+                if (result == Z_DATA_ERROR){
+                    z.msg = "oversubscribed distance tree";
+                }
+                else if (result == Z_BUF_ERROR) {
+                    z.msg = "incomplete distance tree";
+                    result = Z_DATA_ERROR;
+                }
+                else if (result != Z_MEM_ERROR){
+                    z.msg = "empty distance tree with lengths";
+                    result = Z_DATA_ERROR;
+                }
+                return result;
+            }
+
+            return Z_OK;
+        }
+
+        internal static int inflate_trees_fixed(int[] bl,  //literal desired/actual bit depth
+            int[] bd,  //distance desired/actual bit depth
+            int[][] tl,//literal/length tree result
+            int[][] td,//distance tree result 
+            ZStream z  //for memory allocation
+            ){
+            bl[0]=fixed_bl;
+            bd[0]=fixed_bd;
+            tl[0]=fixed_tl;
+            td[0]=fixed_td;
+            return Z_OK;
+        }
+
+        private void initWorkArea(int vsize){
+            if(hn==null){
+                hn=new int[1];
+                v=new int[vsize];
+                c=new int[BMAX+1];
+                r=new int[3];
+                u=new int[BMAX];
+                x=new int[BMAX+1];
+            }
+            if(v.Length<vsize){ v=new int[vsize]; }
+            for(int i=0; i<vsize; i++){v[i]=0;}
+            for(int i=0; i<BMAX+1; i++){c[i]=0;}
+            for(int i=0; i<3; i++){r[i]=0;}
+            //  for(int i=0; i<BMAX; i++){u[i]=0;}
+            System.Array.Copy(c, 0, u, 0, BMAX);
+            //  for(int i=0; i<BMAX+1; i++){x[i]=0;}
+            System.Array.Copy(c, 0, x, 0, BMAX+1);
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/Inflate.cs b/BouncyCastle.AxCrypt/src/util/zlib/Inflate.cs
new file mode 100644
index 0000000..ac87893
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/Inflate.cs
@@ -0,0 +1,387 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class Inflate{
+  
+        private const int MAX_WBITS=15; // 32K LZ77 window
+
+        // preset dictionary flag in zlib header
+        private const int PRESET_DICT=0x20;
+
+        internal const int Z_NO_FLUSH=0;
+        internal const int Z_PARTIAL_FLUSH=1;
+        internal const int Z_SYNC_FLUSH=2;
+        internal const int Z_FULL_FLUSH=3;
+        internal const int Z_FINISH=4;
+
+        private const int Z_DEFLATED=8;
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        private const int METHOD=0;   // waiting for method byte
+        private const int FLAG=1;     // waiting for flag byte
+        private const int DICT4=2;    // four dictionary check bytes to go
+        private const int DICT3=3;    // three dictionary check bytes to go
+        private const int DICT2=4;    // two dictionary check bytes to go
+        private const int DICT1=5;    // one dictionary check byte to go
+        private const int DICT0=6;    // waiting for inflateSetDictionary
+        private const int BLOCKS=7;   // decompressing blocks
+        private const int CHECK4=8;   // four check bytes to go
+        private const int CHECK3=9;   // three check bytes to go
+        private const int CHECK2=10;  // two check bytes to go
+        private const int CHECK1=11;  // one check byte to go
+        private const int DONE=12;    // finished check, done
+        private const int BAD=13;     // got an error--stay here
+
+        internal int mode;                            // current inflate mode
+
+        // mode dependent information
+        internal int method;        // if FLAGS, method byte
+
+        // if CHECK, check values to compare
+        internal long[] was=new long[1] ; // computed check value
+        internal long need;               // stream check value
+
+        // if BAD, inflateSync's marker bytes count
+        internal int marker;
+
+        // mode independent information
+        internal int  nowrap;          // flag for no wrapper
+        internal int wbits;            // log2(window size)  (8..15, defaults to 15)
+
+        internal InfBlocks blocks;     // current inflate_blocks state
+
+        internal int inflateReset(ZStream z){
+            if(z == null || z.istate == null) return Z_STREAM_ERROR;
+    
+            z.total_in = z.total_out = 0;
+            z.msg = null;
+            z.istate.mode = z.istate.nowrap!=0 ? BLOCKS : METHOD;
+            z.istate.blocks.reset(z, null);
+            return Z_OK;
+        }
+
+        internal int inflateEnd(ZStream z){
+            if(blocks != null)
+                blocks.free(z);
+            blocks=null;
+            //    ZFREE(z, z->state);
+            return Z_OK;
+        }
+
+        internal int inflateInit(ZStream z, int w){
+            z.msg = null;
+            blocks = null;
+
+            // handle undocumented nowrap option (no zlib header or check)
+            nowrap = 0;
+            if(w < 0){
+                w = - w;
+                nowrap = 1;
+            }
+
+            // set window size
+            if(w<8 ||w>15){
+                inflateEnd(z);
+                return Z_STREAM_ERROR;
+            }
+            wbits=w;
+
+            z.istate.blocks=new InfBlocks(z, 
+                z.istate.nowrap!=0 ? null : this,
+                1<<w);
+
+            // reset state
+            inflateReset(z);
+            return Z_OK;
+        }
+
+        internal int inflate(ZStream z, int f){
+            int r;
+            int b;
+
+            if(z == null || z.istate == null || z.next_in == null)
+                return Z_STREAM_ERROR;
+            f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+            r = Z_BUF_ERROR;
+            while (true){
+                //System.out.println("mode: "+z.istate.mode);
+                switch (z.istate.mode){
+                    case METHOD:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        if(((z.istate.method = z.next_in[z.next_in_index++])&0xf)!=Z_DEFLATED){
+                            z.istate.mode = BAD;
+                            z.msg="unknown compression method";
+                            z.istate.marker = 5;       // can't try inflateSync
+                            break;
+                        }
+                        if((z.istate.method>>4)+8>z.istate.wbits){
+                            z.istate.mode = BAD;
+                            z.msg="invalid window size";
+                            z.istate.marker = 5;       // can't try inflateSync
+                            break;
+                        }
+                        z.istate.mode=FLAG;
+                        goto case FLAG;
+                    case FLAG:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        b = (z.next_in[z.next_in_index++])&0xff;
+
+                        if((((z.istate.method << 8)+b) % 31)!=0){
+                            z.istate.mode = BAD;
+                            z.msg = "incorrect header check";
+                            z.istate.marker = 5;       // can't try inflateSync
+                            break;
+                        }
+
+                        if((b&PRESET_DICT)==0){
+                            z.istate.mode = BLOCKS;
+                            break;
+                        }
+                        z.istate.mode = DICT4;
+                        goto case DICT4;
+                    case DICT4:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
+                        z.istate.mode=DICT3;
+                        goto case DICT3;
+                    case DICT3:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
+                        z.istate.mode=DICT2;
+                        goto case DICT2;
+                    case DICT2:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
+                        z.istate.mode=DICT1;
+                        goto case DICT1;
+                    case DICT1:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need += (z.next_in[z.next_in_index++]&0xffL);
+                        z.adler = z.istate.need;
+                        z.istate.mode = DICT0;
+                        return Z_NEED_DICT;
+                    case DICT0:
+                        z.istate.mode = BAD;
+                        z.msg = "need dictionary";
+                        z.istate.marker = 0;       // can try inflateSync
+                        return Z_STREAM_ERROR;
+                    case BLOCKS:
+
+                        r = z.istate.blocks.proc(z, r);
+                        if(r == Z_DATA_ERROR){
+                            z.istate.mode = BAD;
+                            z.istate.marker = 0;     // can try inflateSync
+                            break;
+                        }
+                        if(r == Z_OK){
+                            r = f;
+                        }
+                        if(r != Z_STREAM_END){
+                            return r;
+                        }
+                        r = f;
+                        z.istate.blocks.reset(z, z.istate.was);
+                        if(z.istate.nowrap!=0){
+                            z.istate.mode=DONE;
+                            break;
+                        }
+                        z.istate.mode=CHECK4;
+                        goto case CHECK4;
+                    case CHECK4:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
+                        z.istate.mode=CHECK3;
+                        goto case CHECK3;
+                    case CHECK3:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
+                        z.istate.mode = CHECK2;
+                        goto case CHECK2;
+                    case CHECK2:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
+                        z.istate.mode = CHECK1;
+                        goto case CHECK1;
+                    case CHECK1:
+
+                        if(z.avail_in==0)return r;r=f;
+
+                        z.avail_in--; z.total_in++;
+                        z.istate.need+=(z.next_in[z.next_in_index++]&0xffL);
+
+                        if(((int)(z.istate.was[0])) != ((int)(z.istate.need))){
+                            z.istate.mode = BAD;
+                            z.msg = "incorrect data check";
+                            z.istate.marker = 5;       // can't try inflateSync
+                            break;
+                        }
+
+                        z.istate.mode = DONE;
+                        goto case DONE;
+                    case DONE:
+                        return Z_STREAM_END;
+                    case BAD:
+                        return Z_DATA_ERROR;
+                    default:
+                        return Z_STREAM_ERROR;
+                }
+            }
+        }
+
+
+        internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength){
+            int index=0;
+            int length = dictLength;
+            if(z==null || z.istate == null|| z.istate.mode != DICT0)
+                return Z_STREAM_ERROR;
+
+            if(z._adler.adler32(1L, dictionary, 0, dictLength)!=z.adler){
+                return Z_DATA_ERROR;
+            }
+
+            z.adler = z._adler.adler32(0, null, 0, 0);
+
+            if(length >= (1<<z.istate.wbits)){
+                length = (1<<z.istate.wbits)-1;
+                index=dictLength - length;
+            }
+            z.istate.blocks.set_dictionary(dictionary, index, length);
+            z.istate.mode = BLOCKS;
+            return Z_OK;
+        }
+
+        private static readonly byte[] mark = {(byte)0, (byte)0, (byte)0xff, (byte)0xff};
+
+        internal int inflateSync(ZStream z){
+            int n;       // number of bytes to look at
+            int p;       // pointer to bytes
+            int m;       // number of marker bytes found in a row
+            long r, w;   // temporaries to save total_in and total_out
+
+            // set up
+            if(z == null || z.istate == null)
+                return Z_STREAM_ERROR;
+            if(z.istate.mode != BAD){
+                z.istate.mode = BAD;
+                z.istate.marker = 0;
+            }
+            if((n=z.avail_in)==0)
+                return Z_BUF_ERROR;
+            p=z.next_in_index;
+            m=z.istate.marker;
+
+            // search
+            while (n!=0 && m < 4){
+                if(z.next_in[p] == mark[m]){
+                    m++;
+                }
+                else if(z.next_in[p]!=0){
+                    m = 0;
+                }
+                else{
+                    m = 4 - m;
+                }
+                p++; n--;
+            }
+
+            // restore
+            z.total_in += p-z.next_in_index;
+            z.next_in_index = p;
+            z.avail_in = n;
+            z.istate.marker = m;
+
+            // return no joy or set up to restart on a new block
+            if(m != 4){
+                return Z_DATA_ERROR;
+            }
+            r=z.total_in;  w=z.total_out;
+            inflateReset(z);
+            z.total_in=r;  z.total_out = w;
+            z.istate.mode = BLOCKS;
+            return Z_OK;
+        }
+
+        // Returns true if inflate is currently at the end of a block generated
+        // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+        // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+        // but removes the length bytes of the resulting empty stored block. When
+        // decompressing, PPP checks that at the end of input packet, inflate is
+        // waiting for these length bytes.
+        internal int inflateSyncPoint(ZStream z){
+            if(z == null || z.istate == null || z.istate.blocks == null)
+                return Z_STREAM_ERROR;
+            return z.istate.blocks.sync_point();
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/JZlib.cs b/BouncyCastle.AxCrypt/src/util/zlib/JZlib.cs
new file mode 100644
index 0000000..4f2cfda
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/JZlib.cs
@@ -0,0 +1,73 @@
+using System;
+/*
+ * $Id: JZlib.cs,v 1.3 2011-02-15 05:46:04 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    public sealed class JZlib{
+        private const String _version="1.0.7";
+        public static String version()
+		{
+			return _version;
+		}
+
+        // compression levels
+        public const int Z_NO_COMPRESSION=0;
+        public const int Z_BEST_SPEED=1;
+        public const int Z_BEST_COMPRESSION=9;
+        public const int Z_DEFAULT_COMPRESSION=-1;
+
+        // compression strategy
+        public const int Z_FILTERED=1;
+        public const int Z_HUFFMAN_ONLY=2;
+        public const int Z_DEFAULT_STRATEGY=0;
+
+        public const int Z_NO_FLUSH=0;
+        public const int Z_PARTIAL_FLUSH=1;
+        public const int Z_SYNC_FLUSH=2;
+        public const int Z_FULL_FLUSH=3;
+        public const int Z_FINISH=4;
+
+        public const int Z_OK=0;
+        public const int Z_STREAM_END=1;
+        public const int Z_NEED_DICT=2;
+        public const int Z_ERRNO=-1;
+        public const int Z_STREAM_ERROR=-2;
+        public const int Z_DATA_ERROR=-3;
+        public const int Z_MEM_ERROR=-4;
+        public const int Z_BUF_ERROR=-5;
+        public const int Z_VERSION_ERROR=-6;
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/StaticTree.cs b/BouncyCastle.AxCrypt/src/util/zlib/StaticTree.cs
new file mode 100644
index 0000000..097735d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/StaticTree.cs
@@ -0,0 +1,152 @@
+using System;
+/*
+ * $Id: StaticTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class StaticTree{
+        private const int MAX_BITS=15;
+
+        private const int BL_CODES=19;
+        private const int D_CODES=30;
+        private const int LITERALS=256;
+        private const int LENGTH_CODES=29;
+        private const int L_CODES=(LITERALS+1+LENGTH_CODES);
+
+        // Bit length codes must not exceed MAX_BL_BITS bits
+        internal const int MAX_BL_BITS=7; 
+
+        internal static readonly short[] static_ltree = {
+                                                   12,  8, 140,  8,  76,  8, 204,  8,  44,  8,
+                                                   172,  8, 108,  8, 236,  8,  28,  8, 156,  8,
+                                                   92,  8, 220,  8,  60,  8, 188,  8, 124,  8,
+                                                   252,  8,   2,  8, 130,  8,  66,  8, 194,  8,
+                                                   34,  8, 162,  8,  98,  8, 226,  8,  18,  8,
+                                                   146,  8,  82,  8, 210,  8,  50,  8, 178,  8,
+                                                   114,  8, 242,  8,  10,  8, 138,  8,  74,  8,
+                                                   202,  8,  42,  8, 170,  8, 106,  8, 234,  8,
+                                                   26,  8, 154,  8,  90,  8, 218,  8,  58,  8,
+                                                   186,  8, 122,  8, 250,  8,   6,  8, 134,  8,
+                                                   70,  8, 198,  8,  38,  8, 166,  8, 102,  8,
+                                                   230,  8,  22,  8, 150,  8,  86,  8, 214,  8,
+                                                   54,  8, 182,  8, 118,  8, 246,  8,  14,  8,
+                                                   142,  8,  78,  8, 206,  8,  46,  8, 174,  8,
+                                                   110,  8, 238,  8,  30,  8, 158,  8,  94,  8,
+                                                   222,  8,  62,  8, 190,  8, 126,  8, 254,  8,
+                                                   1,  8, 129,  8,  65,  8, 193,  8,  33,  8,
+                                                   161,  8,  97,  8, 225,  8,  17,  8, 145,  8,
+                                                   81,  8, 209,  8,  49,  8, 177,  8, 113,  8,
+                                                   241,  8,   9,  8, 137,  8,  73,  8, 201,  8,
+                                                   41,  8, 169,  8, 105,  8, 233,  8,  25,  8,
+                                                   153,  8,  89,  8, 217,  8,  57,  8, 185,  8,
+                                                   121,  8, 249,  8,   5,  8, 133,  8,  69,  8,
+                                                   197,  8,  37,  8, 165,  8, 101,  8, 229,  8,
+                                                   21,  8, 149,  8,  85,  8, 213,  8,  53,  8,
+                                                   181,  8, 117,  8, 245,  8,  13,  8, 141,  8,
+                                                   77,  8, 205,  8,  45,  8, 173,  8, 109,  8,
+                                                   237,  8,  29,  8, 157,  8,  93,  8, 221,  8,
+                                                   61,  8, 189,  8, 125,  8, 253,  8,  19,  9,
+                                                   275,  9, 147,  9, 403,  9,  83,  9, 339,  9,
+                                                   211,  9, 467,  9,  51,  9, 307,  9, 179,  9,
+                                                   435,  9, 115,  9, 371,  9, 243,  9, 499,  9,
+                                                   11,  9, 267,  9, 139,  9, 395,  9,  75,  9,
+                                                   331,  9, 203,  9, 459,  9,  43,  9, 299,  9,
+                                                   171,  9, 427,  9, 107,  9, 363,  9, 235,  9,
+                                                   491,  9,  27,  9, 283,  9, 155,  9, 411,  9,
+                                                   91,  9, 347,  9, 219,  9, 475,  9,  59,  9,
+                                                   315,  9, 187,  9, 443,  9, 123,  9, 379,  9,
+                                                   251,  9, 507,  9,   7,  9, 263,  9, 135,  9,
+                                                   391,  9,  71,  9, 327,  9, 199,  9, 455,  9,
+                                                   39,  9, 295,  9, 167,  9, 423,  9, 103,  9,
+                                                   359,  9, 231,  9, 487,  9,  23,  9, 279,  9,
+                                                   151,  9, 407,  9,  87,  9, 343,  9, 215,  9,
+                                                   471,  9,  55,  9, 311,  9, 183,  9, 439,  9,
+                                                   119,  9, 375,  9, 247,  9, 503,  9,  15,  9,
+                                                   271,  9, 143,  9, 399,  9,  79,  9, 335,  9,
+                                                   207,  9, 463,  9,  47,  9, 303,  9, 175,  9,
+                                                   431,  9, 111,  9, 367,  9, 239,  9, 495,  9,
+                                                   31,  9, 287,  9, 159,  9, 415,  9,  95,  9,
+                                                   351,  9, 223,  9, 479,  9,  63,  9, 319,  9,
+                                                   191,  9, 447,  9, 127,  9, 383,  9, 255,  9,
+                                                   511,  9,   0,  7,  64,  7,  32,  7,  96,  7,
+                                                   16,  7,  80,  7,  48,  7, 112,  7,   8,  7,
+                                                   72,  7,  40,  7, 104,  7,  24,  7,  88,  7,
+                                                   56,  7, 120,  7,   4,  7,  68,  7,  36,  7,
+                                                   100,  7,  20,  7,  84,  7,  52,  7, 116,  7,
+                                                   3,  8, 131,  8,  67,  8, 195,  8,  35,  8,
+                                                   163,  8,  99,  8, 227,  8
+                                               };
+
+        internal static readonly short[] static_dtree = {
+                                                   0, 5, 16, 5,  8, 5, 24, 5,  4, 5,
+                                                   20, 5, 12, 5, 28, 5,  2, 5, 18, 5,
+                                                   10, 5, 26, 5,  6, 5, 22, 5, 14, 5,
+                                                   30, 5,  1, 5, 17, 5,  9, 5, 25, 5,
+                                                   5, 5, 21, 5, 13, 5, 29, 5,  3, 5,
+                                                   19, 5, 11, 5, 27, 5,  7, 5, 23, 5
+                                               };
+
+        internal static readonly StaticTree static_l_desc =
+            new StaticTree(static_ltree, Tree.extra_lbits,
+            LITERALS+1, L_CODES, MAX_BITS);
+
+        internal static readonly StaticTree static_d_desc =
+            new StaticTree(static_dtree, Tree.extra_dbits,
+            0,  D_CODES, MAX_BITS);
+
+        internal static readonly StaticTree static_bl_desc =
+            new StaticTree(null, Tree.extra_blbits,
+            0, BL_CODES, MAX_BL_BITS);
+
+        internal short[] static_tree;     // static tree or null
+        internal int[] extra_bits;        // extra bits for each code or null
+        internal int extra_base;          // base index for extra_bits
+        internal int elems;               // max number of elements in the tree
+        internal int max_length;          // max bit length for the codes
+
+        internal StaticTree(short[] static_tree,
+            int[] extra_bits,
+            int extra_base,
+            int elems,
+            int max_length
+            ){
+            this.static_tree=static_tree;
+            this.extra_bits=extra_bits;
+            this.extra_base=extra_base;
+            this.elems=elems;
+            this.max_length=max_length;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/Tree.cs b/BouncyCastle.AxCrypt/src/util/zlib/Tree.cs
new file mode 100644
index 0000000..29d0a30
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/Tree.cs
@@ -0,0 +1,367 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class Tree{
+        private const int MAX_BITS=15;
+        private const int BL_CODES=19;
+        private const int D_CODES=30;
+        private const int LITERALS=256;
+        private const int LENGTH_CODES=29;
+        private const int L_CODES=(LITERALS+1+LENGTH_CODES);
+        private const int HEAP_SIZE=(2*L_CODES+1);
+
+        // Bit length codes must not exceed MAX_BL_BITS bits
+        internal const int MAX_BL_BITS=7; 
+
+        // end of block literal code
+        internal const int END_BLOCK=256; 
+
+        // repeat previous bit length 3-6 times (2 bits of repeat count)
+        internal const int REP_3_6=16; 
+
+        // repeat a zero length 3-10 times  (3 bits of repeat count)
+        internal const int REPZ_3_10=17; 
+
+        // repeat a zero length 11-138 times  (7 bits of repeat count)
+        internal const int REPZ_11_138=18; 
+
+        // extra bits for each length code
+        internal static readonly int[] extra_lbits={
+                                             0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+                                         };
+
+        // extra bits for each distance code
+        internal static readonly int[] extra_dbits={
+                                             0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+                                         };
+
+        // extra bits for each bit length code
+        internal static readonly int[] extra_blbits={
+                                              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+                                          };
+
+        internal static readonly byte[] bl_order={
+                                            16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+
+        // The lengths of the bit length codes are sent in order of decreasing
+        // probability, to avoid transmitting the lengths for unused bit
+        // length codes.
+
+        internal const int Buf_size=8*2;
+
+        // see definition of array dist_code below
+        internal const int DIST_CODE_LEN=512;
+
+        internal static readonly byte[] _dist_code = {
+                                                0,  1,  2,  3,  4,  4,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  8,
+                                                8,  8,  8,  8,  9,  9,  9,  9,  9,  9,  9,  9, 10, 10, 10, 10, 10, 10, 10, 10,
+                                                10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+                                                11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+                                                12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+                                                13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+                                                13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+                                                14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+                                                14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+                                                14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+                                                15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+                                                15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+                                                15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  0,  0, 16, 17,
+                                                18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+                                                23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+                                                24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+                                                26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+                                                26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+                                                27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+                                                27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+                                                28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+                                                28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+                                                28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+                                                29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+                                                29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+                                                29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+                                            };
+
+        internal static readonly byte[] _length_code={
+                                                0,  1,  2,  3,  4,  5,  6,  7,  8,  8,  9,  9, 10, 10, 11, 11, 12, 12, 12, 12,
+                                                13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+                                                17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+                                                19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+                                                21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+                                                22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+                                                23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+                                                24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+                                                25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+                                                25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+                                                26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+                                                26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+                                                27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+                                            };
+
+        internal static readonly int[] base_length = {
+                                               0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+                                               64, 80, 96, 112, 128, 160, 192, 224, 0
+                                           };
+
+        internal static readonly int[] base_dist = {
+                                             0,   1,      2,     3,     4,    6,     8,    12,    16,     24,
+                                             32,  48,     64,    96,   128,  192,   256,   384,   512,    768,
+                                             1024, 1536,  2048,  3072,  4096,  6144,  8192, 12288, 16384, 24576
+                                         };
+
+        // Mapping from a distance to a distance code. dist is the distance - 1 and
+        // must not have side effects. _dist_code[256] and _dist_code[257] are never
+        // used.
+        internal static int d_code(int dist){
+            return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]);
+        }
+
+        internal short[] dyn_tree;      // the dynamic tree
+        internal int     max_code;      // largest code with non zero frequency
+        internal StaticTree stat_desc;  // the corresponding static tree
+
+        // Compute the optimal bit lengths for a tree and update the total bit length
+        // for the current block.
+        // IN assertion: the fields freq and dad are set, heap[heap_max] and
+        //    above are the tree nodes sorted by increasing frequency.
+        // OUT assertions: the field len is set to the optimal bit length, the
+        //     array bl_count contains the frequencies for each bit length.
+        //     The length opt_len is updated; static_len is also updated if stree is
+        //     not null.
+        internal void gen_bitlen(Deflate s){
+            short[] tree = dyn_tree;
+            short[] stree = stat_desc.static_tree;
+            int[] extra = stat_desc.extra_bits;
+            int based = stat_desc.extra_base;
+            int max_length = stat_desc.max_length;
+            int h;              // heap index
+            int n, m;           // iterate over the tree elements
+            int bits;           // bit length
+            int xbits;          // extra bits
+            short f;            // frequency
+            int overflow = 0;   // number of elements with bit length too large
+
+            for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+            // In a first pass, compute the optimal bit lengths (which may
+            // overflow in the case of the bit length tree).
+            tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap
+
+            for(h=s.heap_max+1; h<HEAP_SIZE; h++){
+                n = s.heap[h];
+                bits = tree[tree[n*2+1]*2+1] + 1;
+                if (bits > max_length){ bits = max_length; overflow++; }
+                tree[n*2+1] = (short)bits;
+                // We overwrite tree[n*2+1] which is no longer needed
+
+                if (n > max_code) continue;  // not a leaf node
+
+                s.bl_count[bits]++;
+                xbits = 0;
+                if (n >= based) xbits = extra[n-based];
+                f = tree[n*2];
+                s.opt_len += f * (bits + xbits);
+                if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits);
+            }
+            if (overflow == 0) return;
+
+            // This happens for example on obj2 and pic of the Calgary corpus
+            // Find the first bit length which could increase:
+            do {
+                bits = max_length-1;
+            while(s.bl_count[bits]==0) bits--;
+                s.bl_count[bits]--;      // move one leaf down the tree
+                s.bl_count[bits+1]+=2;   // move one overflow item as its brother
+                s.bl_count[max_length]--;
+                // The brother of the overflow item also moves one step up,
+                // but this does not affect bl_count[max_length]
+                overflow -= 2;
+            }
+            while (overflow > 0);
+
+            for (bits = max_length; bits != 0; bits--) {
+                n = s.bl_count[bits];
+                while (n != 0) {
+                    m = s.heap[--h];
+                    if (m > max_code) continue;
+                    if (tree[m*2+1] != bits) {
+                        s.opt_len += (int)(((long)bits - (long)tree[m*2+1])*(long)tree[m*2]);
+                        tree[m*2+1] = (short)bits;
+                    }
+                    n--;
+                }
+            }
+        }
+
+        // Construct one Huffman tree and assigns the code bit strings and lengths.
+        // Update the total bit length for the current block.
+        // IN assertion: the field freq is set for all tree elements.
+        // OUT assertions: the fields len and code are set to the optimal bit length
+        //     and corresponding code. The length opt_len is updated; static_len is
+        //     also updated if stree is not null. The field max_code is set.
+        internal void build_tree(Deflate s){
+            short[] tree=dyn_tree;
+            short[] stree=stat_desc.static_tree;
+            int elems=stat_desc.elems;
+            int n, m;          // iterate over heap elements
+            int max_code=-1;   // largest code with non zero frequency
+            int node;          // new node being created
+
+            // Construct the initial heap, with least frequent element in
+            // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+            // heap[0] is not used.
+            s.heap_len = 0;
+            s.heap_max = HEAP_SIZE;
+
+            for(n=0; n<elems; n++) {
+                if(tree[n*2] != 0) {
+                    s.heap[++s.heap_len] = max_code = n;
+                    s.depth[n] = 0;
+                }
+                else{
+                    tree[n*2+1] = 0;
+                }
+            }
+
+            // The pkzip format requires that at least one distance code exists,
+            // and that at least one bit should be sent even if there is only one
+            // possible code. So to avoid special checks later on we force at least
+            // two codes of non zero frequency.
+            while (s.heap_len < 2) {
+                node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+                tree[node*2] = 1;
+                s.depth[node] = 0;
+                s.opt_len--; if (stree!=null) s.static_len -= stree[node*2+1];
+                // node is 0 or 1 so it does not have extra bits
+            }
+            this.max_code = max_code;
+
+            // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+            // establish sub-heaps of increasing lengths:
+
+            for(n=s.heap_len/2;n>=1; n--)
+                s.pqdownheap(tree, n);
+
+            // Construct the Huffman tree by repeatedly combining the least two
+            // frequent nodes.
+
+            node=elems;                 // next internal node of the tree
+            do{
+                // n = node of least frequency
+                n=s.heap[1];
+                s.heap[1]=s.heap[s.heap_len--];
+                s.pqdownheap(tree, 1);
+                m=s.heap[1];                // m = node of next least frequency
+
+                s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+                s.heap[--s.heap_max] = m;
+
+                // Create a new node father of n and m
+                tree[node*2] = (short)(tree[n*2] + tree[m*2]);
+                s.depth[node] = (byte)(System.Math.Max(s.depth[n],s.depth[m])+1);
+                tree[n*2+1] = tree[m*2+1] = (short)node;
+
+                // and insert the new node in the heap
+                s.heap[1] = node++;
+                s.pqdownheap(tree, 1);
+            }
+            while(s.heap_len>=2);
+
+            s.heap[--s.heap_max] = s.heap[1];
+
+            // At this point, the fields freq and dad are set. We can now
+            // generate the bit lengths.
+
+            gen_bitlen(s);
+
+            // The field len is now set, we can generate the bit codes
+            gen_codes(tree, max_code, s.bl_count);
+        }
+
+        // Generate the codes for a given tree and bit counts (which need not be
+        // optimal).
+        // IN assertion: the array bl_count contains the bit length statistics for
+        // the given tree and the field len is set for all tree elements.
+        // OUT assertion: the field code is set for all tree elements of non
+        //     zero code length.
+        internal static void gen_codes(short[] tree, // the tree to decorate
+            int max_code, // largest code with non zero frequency
+            short[] bl_count // number of codes at each bit length
+            ){
+            short[] next_code=new short[MAX_BITS+1]; // next code value for each bit length
+            short code = 0;            // running code value
+            int bits;                  // bit index
+            int n;                     // code index
+
+            // The distribution counts are first used to generate the code values
+            // without bit reversal.
+            for (bits = 1; bits <= MAX_BITS; bits++) {
+                next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1);
+            }
+
+            // Check that the bit counts in bl_count are consistent. The last code
+            // must be all ones.
+            //Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
+            //        "inconsistent bit counts");
+            //Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
+
+            for (n = 0;  n <= max_code; n++) {
+                int len = tree[n*2+1];
+                if (len == 0) continue;
+                // Now reverse the bits
+                tree[n*2] = (short)(bi_reverse(next_code[len]++, len));
+            }
+        }
+
+        // Reverse the first len bits of a code, using straightforward code (a faster
+        // method would use a table)
+        // IN assertion: 1 <= len <= 15
+        internal static int bi_reverse(int code, // the value to invert
+            int len   // its bit length
+            ){
+            int res = 0;
+            do{
+                res|=code&1;
+                code>>=1;
+                res<<=1;
+            } 
+            while(--len>0);
+            return res>>1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/ZDeflaterOutputStream.cs b/BouncyCastle.AxCrypt/src/util/zlib/ZDeflaterOutputStream.cs
new file mode 100644
index 0000000..544ba86
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/ZDeflaterOutputStream.cs
@@ -0,0 +1,158 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+    /// <summary>
+    /// Summary description for DeflaterOutputStream.
+    /// </summary>
+    [Obsolete("Use 'ZOutputStream' instead")]
+    public class ZDeflaterOutputStream : Stream {
+        protected ZStream z=new ZStream();
+        protected int flushLevel=JZlib.Z_NO_FLUSH;
+        private const int BUFSIZE = 4192;
+        protected byte[] buf=new byte[BUFSIZE];
+        private byte[] buf1=new byte[1];
+
+        protected Stream outp;
+
+        public ZDeflaterOutputStream(Stream outp) : this(outp, 6, false) {
+        }
+    
+        public ZDeflaterOutputStream(Stream outp, int level) : this(outp, level, false) {
+        }
+    
+        public ZDeflaterOutputStream(Stream outp, int level, bool nowrap) {
+            this.outp=outp;
+            z.deflateInit(level, nowrap);
+        }
+    
+    
+        public override bool CanRead {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanRead getter implementation
+                return false;
+            }
+        }
+    
+        public override bool CanSeek {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanSeek getter implementation
+                return false;
+            }
+        }
+    
+        public override bool CanWrite {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanWrite getter implementation
+                return true;
+            }
+        }
+    
+        public override long Length {
+            get {
+                // TODO:  Add DeflaterOutputStream.Length getter implementation
+                return 0;
+            }
+        }
+    
+        public override long Position {
+            get {
+                // TODO:  Add DeflaterOutputStream.Position getter implementation
+                return 0;
+            }
+            set {
+                // TODO:  Add DeflaterOutputStream.Position setter implementation
+            }
+        }
+    
+        public override void Write(byte[] b, int off, int len) {
+            if(len==0)
+                return;
+            int err;
+            z.next_in=b;
+            z.next_in_index=off;
+            z.avail_in=len;
+            do{
+                z.next_out=buf;
+                z.next_out_index=0;
+                z.avail_out=BUFSIZE;
+                err=z.deflate(flushLevel);
+                if(err!=JZlib.Z_OK)
+                    throw new IOException("deflating: "+z.msg);
+				if (z.avail_out < BUFSIZE)
+				{
+					outp.Write(buf, 0, BUFSIZE-z.avail_out);
+				}
+            }
+            while(z.avail_in>0 || z.avail_out==0);
+        }
+    
+        public override long Seek(long offset, SeekOrigin origin) {
+            // TODO:  Add DeflaterOutputStream.Seek implementation
+            return 0;
+        }
+    
+        public override void SetLength(long value) {
+            // TODO:  Add DeflaterOutputStream.SetLength implementation
+
+        }
+    
+        public override int Read(byte[] buffer, int offset, int count) {
+            // TODO:  Add DeflaterOutputStream.Read implementation
+            return 0;
+        }
+    
+        public override void Flush() {
+            outp.Flush();
+        }
+    
+        public override void WriteByte(byte b) {
+            buf1[0]=(byte)b;
+            Write(buf1, 0, 1);
+        }
+
+        public void Finish() {
+            int err;
+            do{
+                z.next_out=buf;
+                z.next_out_index=0;
+                z.avail_out=BUFSIZE;
+                err=z.deflate(JZlib.Z_FINISH);
+                if(err!=JZlib.Z_STREAM_END && err != JZlib.Z_OK)
+                    throw new IOException("deflating: "+z.msg);
+                if(BUFSIZE-z.avail_out>0){
+                    outp.Write(buf, 0, BUFSIZE-z.avail_out);
+                }
+            }
+            while(z.avail_in>0 || z.avail_out==0);
+            Flush();
+        }
+
+        public void End() {
+            if(z==null)
+                return;
+            z.deflateEnd();
+            z.free();
+            z=null;
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                try
+                {
+                    try { Finish(); }
+                    catch (IOException) { }
+                }
+                finally
+                {
+                    End();
+                    outp.Dispose();
+                    outp = null;
+                }
+            }
+            base.Dispose(disposing);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/ZInflaterInputStream.cs b/BouncyCastle.AxCrypt/src/util/zlib/ZInflaterInputStream.cs
new file mode 100644
index 0000000..9e82954
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/ZInflaterInputStream.cs
@@ -0,0 +1,132 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+    /// <summary>
+    /// Summary description for DeflaterOutputStream.
+    /// </summary>
+    [Obsolete("Use 'ZInputStream' instead")]
+    public class ZInflaterInputStream : Stream {
+        protected ZStream z=new ZStream();
+        protected int flushLevel=JZlib.Z_NO_FLUSH;
+        private const int BUFSIZE = 4192;
+        protected byte[] buf=new byte[BUFSIZE];
+        private byte[] buf1=new byte[1];
+
+        protected Stream inp=null;
+        private bool nomoreinput=false;
+
+        public ZInflaterInputStream(Stream inp) : this(inp, false) {
+        }
+    
+        public ZInflaterInputStream(Stream inp, bool nowrap) {
+            this.inp=inp;
+            z.inflateInit(nowrap);
+            z.next_in=buf;
+            z.next_in_index=0;
+            z.avail_in=0;
+        }
+    
+        public override bool CanRead {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanRead getter implementation
+                return true;
+            }
+        }
+    
+        public override bool CanSeek {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanSeek getter implementation
+                return false;
+            }
+        }
+    
+        public override bool CanWrite {
+            get {
+                // TODO:  Add DeflaterOutputStream.CanWrite getter implementation
+                return false;
+            }
+        }
+    
+        public override long Length {
+            get {
+                // TODO:  Add DeflaterOutputStream.Length getter implementation
+                return 0;
+            }
+        }
+    
+        public override long Position {
+            get {
+                // TODO:  Add DeflaterOutputStream.Position getter implementation
+                return 0;
+            }
+            set {
+                // TODO:  Add DeflaterOutputStream.Position setter implementation
+            }
+        }
+    
+        public override void Write(byte[] b, int off, int len) {
+        }
+    
+        public override long Seek(long offset, SeekOrigin origin) {
+            // TODO:  Add DeflaterOutputStream.Seek implementation
+            return 0;
+        }
+    
+        public override void SetLength(long value) {
+            // TODO:  Add DeflaterOutputStream.SetLength implementation
+
+        }
+    
+        public override int Read(byte[] b, int off, int len) {
+            if(len==0)
+                return(0);
+            int err;
+            z.next_out=b;
+            z.next_out_index=off;
+            z.avail_out=len;
+            do {
+                if((z.avail_in==0)&&(!nomoreinput)) { // if buffer is empty and more input is avaiable, refill it
+                    z.next_in_index=0;
+                    z.avail_in=inp.Read(buf, 0, BUFSIZE);//(BUFSIZE<z.avail_out ? BUFSIZE : z.avail_out));
+                    if(z.avail_in<=0) {
+                        z.avail_in=0;
+                        nomoreinput=true;
+                    }
+                }
+                err=z.inflate(flushLevel);
+                if(nomoreinput&&(err==JZlib.Z_BUF_ERROR))
+                    return(0);
+                if(err!=JZlib.Z_OK && err!=JZlib.Z_STREAM_END)
+                    throw new IOException("inflating: "+z.msg);
+                if((nomoreinput||err==JZlib.Z_STREAM_END)&&(z.avail_out==len))
+                    return(0);
+            } 
+            while(z.avail_out==len&&err==JZlib.Z_OK);
+            //System.err.print("("+(len-z.avail_out)+")");
+            return(len-z.avail_out);
+        }
+    
+        public override void Flush() {
+            inp.Flush();
+        }
+    
+        public override void WriteByte(byte b) {
+        }
+
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+            {
+                inp.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+    
+        public override int ReadByte() {
+            if(Read(buf1, 0, 1)<=0)
+                return -1;
+            return(buf1[0]&0xFF);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/ZInputStream.cs b/BouncyCastle.AxCrypt/src/util/zlib/ZInputStream.cs
new file mode 100644
index 0000000..671cf68
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/ZInputStream.cs
@@ -0,0 +1,197 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+	public class ZInputStream
+		: Stream
+	{
+		private const int BufferSize = 512;
+
+		protected ZStream z = new ZStream();
+		protected int flushLevel = JZlib.Z_NO_FLUSH;
+		// TODO Allow custom buf
+		protected byte[] buf = new byte[BufferSize];
+		protected byte[] buf1 = new byte[1];
+		protected bool compress;
+
+		protected Stream input;
+		protected bool closed;
+
+		private bool nomoreinput = false;
+
+		public ZInputStream(Stream input)
+			: this(input, false)
+		{
+		}
+
+		public ZInputStream(Stream input, bool nowrap)
+		{
+			Debug.Assert(input.CanRead);
+
+			this.input = input;
+			this.z.inflateInit(nowrap);
+			this.compress = false;
+			this.z.next_in = buf;
+			this.z.next_in_index = 0;
+			this.z.avail_in = 0;
+		}
+
+		public ZInputStream(Stream input, int level)
+		{
+			Debug.Assert(input.CanRead);
+			
+			this.input = input;
+			this.z.deflateInit(level);
+			this.compress = true;
+			this.z.next_in = buf;
+			this.z.next_in_index = 0;
+			this.z.avail_in = 0;
+		}
+
+		/*public int available() throws IOException {
+		return inf.finished() ? 0 : 1;
+		}*/
+
+		public sealed override bool CanRead { get { return !closed; } }
+		public sealed override bool CanSeek { get { return false; } }
+		public sealed override bool CanWrite { get { return false; } }
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+                if (!closed)
+                {
+                    closed = true;
+                    input.Dispose();
+                }
+	        }
+	        base.Dispose(disposing);
+	    }
+
+		public sealed override void Flush() {}
+
+		public virtual int FlushMode
+		{
+			get { return flushLevel; }
+			set { this.flushLevel = value; }
+		}
+
+		public sealed override long Length { get { throw new NotSupportedException(); } }
+		public sealed override long Position
+		{
+			get { throw new NotSupportedException(); }
+			set { throw new NotSupportedException(); }
+		}
+
+		public override int Read(byte[]	b, int off, int len)
+		{
+			if (len==0)
+				return 0;
+
+			z.next_out = b;
+			z.next_out_index = off;
+			z.avail_out = len;
+
+			int err;
+			do
+			{
+				if (z.avail_in == 0 && !nomoreinput)
+				{
+					// if buffer is empty and more input is available, refill it
+					z.next_in_index = 0;
+					z.avail_in = input.Read(buf, 0, buf.Length); //(bufsize<z.avail_out ? bufsize : z.avail_out));
+
+					if (z.avail_in <= 0)
+					{
+						z.avail_in = 0;
+						nomoreinput = true;
+					}
+				}
+
+				err = compress
+					?	z.deflate(flushLevel)
+					:	z.inflate(flushLevel);
+
+				if (nomoreinput && err == JZlib.Z_BUF_ERROR)
+					return 0;
+				if (err != JZlib.Z_OK && err != JZlib.Z_STREAM_END)
+					// TODO
+//					throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+					throw new IOException((compress ? "de" : "in") + "flating: " + z.msg);
+				if ((nomoreinput || err == JZlib.Z_STREAM_END) && z.avail_out == len)
+					return 0;
+			} 
+			while(z.avail_out == len && err == JZlib.Z_OK);
+			//Console.Error.WriteLine("("+(len-z.avail_out)+")");
+			return len - z.avail_out;
+		}
+
+		public override int ReadByte()
+		{
+			if (Read(buf1, 0, 1) <= 0)
+				return -1;
+			return buf1[0];
+		}
+
+//  public long skip(long n) throws IOException {
+//    int len=512;
+//    if(n<len)
+//      len=(int)n;
+//    byte[] tmp=new byte[len];
+//    return((long)read(tmp));
+//  }
+
+		public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+		public sealed override void SetLength(long value) { throw new NotSupportedException(); }
+
+		public virtual long TotalIn
+		{
+			get { return z.total_in; }
+		}
+
+		public virtual long TotalOut
+		{
+			get { return z.total_out; }
+		}
+
+		public sealed override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/ZOutputStream.cs b/BouncyCastle.AxCrypt/src/util/zlib/ZOutputStream.cs
new file mode 100644
index 0000000..2cef063
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/ZOutputStream.cs
@@ -0,0 +1,233 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZOutputStream.java
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+	public class ZOutputStream
+		: Stream
+	{
+		private const int BufferSize = 512;
+
+		protected ZStream z;
+		protected int flushLevel = JZlib.Z_NO_FLUSH;
+		// TODO Allow custom buf
+		protected byte[] buf = new byte[BufferSize];
+		protected byte[] buf1 = new byte[1];
+		protected bool compress;
+
+		protected Stream output;
+		protected bool closed;
+
+        public ZOutputStream(Stream output)
+			: this(output, null)
+        {
+        }
+
+        public ZOutputStream(Stream output, ZStream z)
+			: base()
+		{
+			Debug.Assert(output.CanWrite);
+
+            if (z == null)
+            {
+                z = new ZStream();
+                z.inflateInit();
+            }
+
+            this.output = output;
+            this.z = z;
+			this.compress = false;
+		}
+
+        public ZOutputStream(Stream output, int level)
+			: this(output, level, false)
+		{
+		}
+
+		public ZOutputStream(Stream output, int level, bool nowrap)
+			: base()
+		{
+			Debug.Assert(output.CanWrite);
+
+			this.output = output;
+            this.z = new ZStream();
+			this.z.deflateInit(level, nowrap);
+			this.compress = true;
+		}
+
+		public sealed override bool CanRead { get { return false; } }
+        public sealed override bool CanSeek { get { return false; } }
+        public sealed override bool CanWrite { get { return !closed; } }
+
+	    protected override void Dispose(bool disposing)
+	    {
+	        if (disposing)
+	        {
+                if (this.closed)
+                    return;
+
+                try
+                {
+                    try
+                    {
+                        Finish();
+                    }
+                    catch (IOException)
+                    {
+                        // Ignore
+                    }
+                }
+                finally
+                {
+                    this.closed = true;
+                    End();
+                    output.Dispose();
+                    output = null;
+                }
+	        }
+	        base.Dispose(disposing);
+	    }
+        
+		public virtual void End()
+		{
+			if (z == null)
+				return;
+			if (compress)
+				z.deflateEnd();
+			else
+				z.inflateEnd();
+			z.free();
+			z = null;
+		}
+
+		public virtual void Finish()
+		{
+			do
+			{
+				z.next_out = buf;
+				z.next_out_index = 0;
+				z.avail_out = buf.Length;
+
+				int err = compress
+					?	z.deflate(JZlib.Z_FINISH)
+					:	z.inflate(JZlib.Z_FINISH);
+
+				if (err != JZlib.Z_STREAM_END && err != JZlib.Z_OK)
+					// TODO
+//					throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+					throw new IOException((compress ? "de" : "in") + "flating: " + z.msg);
+
+				int count = buf.Length - z.avail_out;
+				if (count > 0)
+				{
+					output.Write(buf, 0, count);
+				}
+			}
+			while (z.avail_in > 0 || z.avail_out == 0);
+
+			Flush();
+		}
+
+		public override void Flush()
+		{
+			output.Flush();
+		}
+
+		public virtual int FlushMode
+		{
+			get { return flushLevel; }
+			set { this.flushLevel = value; }
+		}
+
+        public sealed override long Length { get { throw new NotSupportedException(); } }
+        public sealed override long Position
+        {
+            get { throw new NotSupportedException(); }
+            set { throw new NotSupportedException(); }
+        }
+        public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+        public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+        public sealed override void SetLength(long value) { throw new NotSupportedException(); }
+
+		public virtual long TotalIn
+		{
+			get { return z.total_in; }
+		}
+
+		public virtual long TotalOut
+		{
+			get { return z.total_out; }
+		}
+
+		public override void Write(byte[] b, int off, int len)
+		{
+			if (len == 0)
+				return;
+
+			z.next_in = b;
+			z.next_in_index = off;
+			z.avail_in = len;
+
+			do
+			{
+				z.next_out = buf;
+				z.next_out_index = 0;
+				z.avail_out = buf.Length;
+
+				int err = compress
+					?	z.deflate(flushLevel)
+					:	z.inflate(flushLevel);
+
+				if (err != JZlib.Z_OK)
+					// TODO
+//					throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+					throw new IOException((compress ? "de" : "in") + "flating: " + z.msg);
+
+				output.Write(buf, 0, buf.Length - z.avail_out);
+			}
+			while (z.avail_in > 0 || z.avail_out == 0);
+		}
+
+		public override void WriteByte(byte b)
+		{
+			buf1[0] = b;
+			Write(buf1, 0, 1);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/util/zlib/ZStream.cs b/BouncyCastle.AxCrypt/src/util/zlib/ZStream.cs
new file mode 100644
index 0000000..7ff9614
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/util/zlib/ZStream.cs
@@ -0,0 +1,214 @@
+using System;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup at gzip.org) and Mark Adler(madler at alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    public sealed class ZStream{
+
+        private const int MAX_WBITS=15;        // 32K LZ77 window
+        private const int DEF_WBITS=MAX_WBITS;
+
+        private const int Z_NO_FLUSH=0;
+        private const int Z_PARTIAL_FLUSH=1;
+        private const int Z_SYNC_FLUSH=2;
+        private const int Z_FULL_FLUSH=3;
+        private const int Z_FINISH=4;
+
+        private const int MAX_MEM_LEVEL=9;
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        public byte[] next_in;     // next input byte
+        public int next_in_index;
+        public int avail_in;       // number of bytes available at next_in
+        public long total_in;      // total nb of input bytes read so far
+
+        public byte[] next_out;    // next output byte should be put there
+        public int next_out_index;
+        public int avail_out;      // remaining free space at next_out
+        public long total_out;     // total nb of bytes output so far
+
+        public String msg;
+
+        internal Deflate dstate; 
+        internal Inflate istate; 
+
+        internal int data_type; // best guess about the data type: ascii or binary
+
+        public long adler;
+        internal Adler32 _adler=new Adler32();
+
+        public int inflateInit(){
+            return inflateInit(DEF_WBITS);
+        }
+        public int inflateInit(bool nowrap){
+            return inflateInit(DEF_WBITS, nowrap);
+        }
+        public int inflateInit(int w){
+            return inflateInit(w, false);
+        }
+
+        public int inflateInit(int w, bool nowrap){
+            istate=new Inflate();
+            return istate.inflateInit(this, nowrap?-w:w);
+        }
+
+        public int inflate(int f){
+            if(istate==null) return Z_STREAM_ERROR;
+            return istate.inflate(this, f);
+        }
+        public int inflateEnd(){
+            if(istate==null) return Z_STREAM_ERROR;
+            int ret=istate.inflateEnd(this);
+            istate = null;
+            return ret;
+        }
+        public int inflateSync(){
+            if(istate == null)
+                return Z_STREAM_ERROR;
+            return istate.inflateSync(this);
+        }
+        public int inflateSetDictionary(byte[] dictionary, int dictLength){
+            if(istate == null)
+                return Z_STREAM_ERROR;
+            return istate.inflateSetDictionary(this, dictionary, dictLength);
+        }
+
+        public int deflateInit(int level){
+            return deflateInit(level, MAX_WBITS);
+        }
+        public int deflateInit(int level, bool nowrap){
+            return deflateInit(level, MAX_WBITS, nowrap);
+        }
+        public int deflateInit(int level, int bits){
+            return deflateInit(level, bits, false);
+        }
+        public int deflateInit(int level, int bits, bool nowrap){
+            dstate=new Deflate();
+            return dstate.deflateInit(this, level, nowrap?-bits:bits);
+        }
+        public int deflate(int flush){
+            if(dstate==null){
+                return Z_STREAM_ERROR;
+            }
+            return dstate.deflate(this, flush);
+        }
+        public int deflateEnd(){
+            if(dstate==null) return Z_STREAM_ERROR;
+            int ret=dstate.deflateEnd();
+            dstate=null;
+            return ret;
+        }
+        public int deflateParams(int level, int strategy){
+            if(dstate==null) return Z_STREAM_ERROR;
+            return dstate.deflateParams(this, level, strategy);
+        }
+        public int deflateSetDictionary (byte[] dictionary, int dictLength){
+            if(dstate == null)
+                return Z_STREAM_ERROR;
+            return dstate.deflateSetDictionary(this, dictionary, dictLength);
+        }
+
+        // Flush as much pending output as possible. All deflate() output goes
+        // through this function so some applications may wish to modify it
+        // to avoid allocating a large strm->next_out buffer and copying into it.
+        // (See also read_buf()).
+        internal void flush_pending(){
+            int len=dstate.pending;
+
+            if(len>avail_out) len=avail_out;
+            if(len==0) return;
+
+            if(dstate.pending_buf.Length<=dstate.pending_out ||
+                next_out.Length<=next_out_index ||
+                dstate.pending_buf.Length<(dstate.pending_out+len) ||
+                next_out.Length<(next_out_index+len)){
+                //      System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+
+                //			 ", "+next_out.length+", "+next_out_index+", "+len);
+                //      System.out.println("avail_out="+avail_out);
+            }
+
+            System.Array.Copy(dstate.pending_buf, dstate.pending_out,
+                next_out, next_out_index, len);
+
+            next_out_index+=len;
+            dstate.pending_out+=len;
+            total_out+=len;
+            avail_out-=len;
+            dstate.pending-=len;
+            if(dstate.pending==0){
+                dstate.pending_out=0;
+            }
+        }
+
+        // Read a new buffer from the current input stream, update the adler32
+        // and total number of bytes read.  All deflate() input goes through
+        // this function so some applications may wish to modify it to avoid
+        // allocating a large strm->next_in buffer and copying from it.
+        // (See also flush_pending()).
+        internal int read_buf(byte[] buf, int start, int size) {
+            int len=avail_in;
+
+            if(len>size) len=size;
+            if(len==0) return 0;
+
+            avail_in-=len;
+
+            if(dstate.noheader==0) {
+                adler=_adler.adler32(adler, next_in, next_in_index, len);
+            }
+            System.Array.Copy(next_in, next_in_index, buf, start, len);
+            next_in_index  += len;
+            total_in += len;
+            return len;
+        }
+
+        public void free(){
+            next_in=null;
+            next_out=null;
+            msg=null;
+            _adler=null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/x509/AttributeCertificateHolder.cs b/BouncyCastle.AxCrypt/src/x509/AttributeCertificateHolder.cs
new file mode 100644
index 0000000..3a6af4c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/AttributeCertificateHolder.cs
@@ -0,0 +1,442 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <remarks>
+	/// The Holder object.
+	/// <pre>
+ 	/// Holder ::= SEQUENCE {
+ 	///		baseCertificateID   [0] IssuerSerial OPTIONAL,
+ 	///			-- the issuer and serial number of
+ 	///			-- the holder's Public Key Certificate
+ 	///		entityName          [1] GeneralNames OPTIONAL,
+ 	///			-- the name of the claimant or role
+ 	///		objectDigestInfo    [2] ObjectDigestInfo OPTIONAL
+ 	///			-- used to directly authenticate the holder,
+ 	///			-- for example, an executable
+ 	/// }
+	/// </pre>
+	/// </remarks>
+	public class AttributeCertificateHolder
+		//: CertSelector, Selector
+		: IX509Selector
+	{
+		internal readonly Holder holder;
+
+		internal AttributeCertificateHolder(
+			Asn1Sequence seq)
+		{
+			holder = Holder.GetInstance(seq);
+		}
+
+		public AttributeCertificateHolder(
+			X509Name	issuerName,
+			BigInteger	serialNumber)
+		{
+			holder = new Holder(
+				new IssuerSerial(
+					GenerateGeneralNames(issuerName),
+					new DerInteger(serialNumber)));
+		}
+
+		public AttributeCertificateHolder(
+			X509Certificate	cert)
+		{
+			X509Name name;
+			try
+			{
+				name = PrincipalUtilities.GetIssuerX509Principal(cert);
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException(e.Message);
+			}
+
+			holder = new Holder(new IssuerSerial(GenerateGeneralNames(name), new DerInteger(cert.SerialNumber)));
+		}
+
+		public AttributeCertificateHolder(
+			X509Name principal)
+		{
+			holder = new Holder(GenerateGeneralNames(principal));
+		}
+
+		/**
+		 * Constructs a holder for v2 attribute certificates with a hash value for
+		 * some type of object.
+		 * <p>
+		 * <code>digestedObjectType</code> can be one of the following:
+		 * <ul>
+		 * <li>0 - publicKey - A hash of the public key of the holder must be
+		 * passed.</li>
+		 * <li>1 - publicKeyCert - A hash of the public key certificate of the
+		 * holder must be passed.</li>
+		 * <li>2 - otherObjectDigest - A hash of some other object type must be
+		 * passed. <code>otherObjectTypeID</code> must not be empty.</li>
+		 * </ul>
+		 * </p>
+		 * <p>This cannot be used if a v1 attribute certificate is used.</p>
+		 *
+		 * @param digestedObjectType The digest object type.
+		 * @param digestAlgorithm The algorithm identifier for the hash.
+		 * @param otherObjectTypeID The object type ID if
+		 *            <code>digestedObjectType</code> is
+		 *            <code>otherObjectDigest</code>.
+		 * @param objectDigest The hash value.
+		 */
+		public AttributeCertificateHolder(
+			int		digestedObjectType,
+			string	digestAlgorithm,
+			string	otherObjectTypeID,
+			byte[]	objectDigest)
+		{
+			// TODO Allow 'objectDigest' to be null?
+
+			holder = new Holder(new ObjectDigestInfo(digestedObjectType, otherObjectTypeID,
+				new AlgorithmIdentifier(digestAlgorithm), Arrays.Clone(objectDigest)));
+		}
+
+		/**
+		 * Returns the digest object type if an object digest info is used.
+		 * <p>
+		 * <ul>
+		 * <li>0 - publicKey - A hash of the public key of the holder must be
+		 * passed.</li>
+		 * <li>1 - publicKeyCert - A hash of the public key certificate of the
+		 * holder must be passed.</li>
+		 * <li>2 - otherObjectDigest - A hash of some other object type must be
+		 * passed. <code>otherObjectTypeID</code> must not be empty.</li>
+		 * </ul>
+		 * </p>
+		 *
+		 * @return The digest object type or -1 if no object digest info is set.
+		 */
+		public int DigestedObjectType
+		{
+			get
+			{
+				ObjectDigestInfo odi = holder.ObjectDigestInfo;
+
+				return odi == null
+					?	-1
+					:	odi.DigestedObjectType.Value.IntValue;
+			}
+		}
+
+		/**
+		 * Returns the other object type ID if an object digest info is used.
+		 *
+		 * @return The other object type ID or <code>null</code> if no object
+		 *         digest info is set.
+		 */
+		public string DigestAlgorithm
+		{
+			get
+			{
+				ObjectDigestInfo odi = holder.ObjectDigestInfo;
+
+				return odi == null
+					?	null
+					:	odi.DigestAlgorithm.ObjectID.Id;
+			}
+		}
+
+		/**
+		 * Returns the hash if an object digest info is used.
+		 *
+		 * @return The hash or <code>null</code> if no object digest info is set.
+		 */
+		public byte[] GetObjectDigest()
+		{
+			ObjectDigestInfo odi = holder.ObjectDigestInfo;
+
+			return odi == null
+				?	null
+				:	odi.ObjectDigest.GetBytes();
+		}
+
+		/**
+		 * Returns the digest algorithm ID if an object digest info is used.
+		 *
+		 * @return The digest algorithm ID or <code>null</code> if no object
+		 *         digest info is set.
+		 */
+		public string OtherObjectTypeID
+		{
+			get
+			{
+				ObjectDigestInfo odi = holder.ObjectDigestInfo;
+
+				return odi == null
+					?	null
+					:	odi.OtherObjectTypeID.Id;
+			}
+		}
+
+		private GeneralNames GenerateGeneralNames(
+			X509Name principal)
+		{
+//			return GeneralNames.GetInstance(new DerSequence(new GeneralName(principal)));
+			return new GeneralNames(new GeneralName(principal));
+		}
+
+		private bool MatchesDN(
+			X509Name		subject,
+			GeneralNames	targets)
+		{
+			GeneralName[] names = targets.GetNames();
+
+			for (int i = 0; i != names.Length; i++)
+			{
+				GeneralName gn = names[i];
+
+				if (gn.TagNo == GeneralName.DirectoryName)
+				{
+					try
+					{
+						if (X509Name.GetInstance(gn.Name).Equivalent(subject))
+						{
+							return true;
+						}
+					}
+					catch (Exception)
+					{
+					}
+				}
+			}
+
+			return false;
+		}
+
+		private object[] GetNames(
+			GeneralName[] names)
+		{
+            int count = 0;
+            for (int i = 0; i != names.Length; i++)
+            {
+                if (names[i].TagNo == GeneralName.DirectoryName)
+                {
+                    ++count;
+                }
+            }
+
+            object[] result = new object[count];
+
+            int pos = 0;
+            for (int i = 0; i != names.Length; i++)
+            {
+                if (names[i].TagNo == GeneralName.DirectoryName)
+                {
+                    result[pos++] = X509Name.GetInstance(names[i].Name);
+                }
+            }
+
+            return result;
+        }
+
+		private X509Name[] GetPrincipals(
+			GeneralNames names)
+		{
+			object[] p = this.GetNames(names.GetNames());
+
+            int count = 0;
+
+            for (int i = 0; i != p.Length; i++)
+			{
+				if (p[i] is X509Name)
+				{
+                    ++count;
+				}
+			}
+
+            X509Name[] result = new X509Name[count];
+
+            int pos = 0;
+            for (int i = 0; i != p.Length; i++)
+            {
+                if (p[i] is X509Name)
+                {
+                    result[pos++] = (X509Name)p[i];
+                }
+            }
+
+            return result;
+        }
+
+		/**
+		 * Return any principal objects inside the attribute certificate holder entity names field.
+		 *
+		 * @return an array of IPrincipal objects (usually X509Name), null if no entity names field is set.
+		 */
+		public X509Name[] GetEntityNames()
+		{
+			if (holder.EntityName != null)
+			{
+				return GetPrincipals(holder.EntityName);
+			}
+
+			return null;
+		}
+
+		/**
+		 * Return the principals associated with the issuer attached to this holder
+		 *
+		 * @return an array of principals, null if no BaseCertificateID is set.
+		 */
+		public X509Name[] GetIssuer()
+		{
+			if (holder.BaseCertificateID != null)
+			{
+				return GetPrincipals(holder.BaseCertificateID.Issuer);
+			}
+
+			return null;
+		}
+
+		/**
+		 * Return the serial number associated with the issuer attached to this holder.
+		 *
+		 * @return the certificate serial number, null if no BaseCertificateID is set.
+		 */
+		public BigInteger SerialNumber
+		{
+			get
+			{
+				if (holder.BaseCertificateID != null)
+				{
+					return holder.BaseCertificateID.Serial.Value;
+				}
+
+				return null;
+			}
+		}
+
+		public object Clone()
+		{
+			return new AttributeCertificateHolder((Asn1Sequence)holder.ToAsn1Object());
+		}
+
+		public bool Match(
+//			Certificate cert)
+			X509Certificate x509Cert)
+		{
+//			if (!(cert is X509Certificate))
+//			{
+//				return false;
+//			}
+//
+//			X509Certificate x509Cert = (X509Certificate)cert;
+
+			try
+			{
+				if (holder.BaseCertificateID != null)
+				{
+					return holder.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber)
+						&& MatchesDN(PrincipalUtilities.GetIssuerX509Principal(x509Cert), holder.BaseCertificateID.Issuer);
+				}
+
+				if (holder.EntityName != null)
+				{
+					if (MatchesDN(PrincipalUtilities.GetSubjectX509Principal(x509Cert), holder.EntityName))
+					{
+						return true;
+					}
+				}
+
+				if (holder.ObjectDigestInfo != null)
+				{
+					IDigest md = null;
+					try
+					{
+						md = DigestUtilities.GetDigest(DigestAlgorithm);
+					}
+					catch (Exception)
+					{
+						return false;
+					}
+
+					switch (DigestedObjectType)
+					{
+						case ObjectDigestInfo.PublicKey:
+						{
+							// TODO: DSA Dss-parms
+
+							//byte[] b = x509Cert.GetPublicKey().getEncoded();
+							// TODO Is this the right way to encode?
+							byte[] b = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
+								x509Cert.GetPublicKey()).GetEncoded();
+							md.BlockUpdate(b, 0, b.Length);
+							break;
+						}
+
+						case ObjectDigestInfo.PublicKeyCert:
+						{
+							byte[] b = x509Cert.GetEncoded();
+							md.BlockUpdate(b, 0, b.Length);
+							break;
+						}
+
+						// TODO Default handler?
+					}
+
+					// TODO Shouldn't this be the other way around?
+					if (!Arrays.AreEqual(DigestUtilities.DoFinal(md), GetObjectDigest()))
+					{
+						return false;
+					}
+				}
+			}
+			catch (CertificateEncodingException)
+			{
+				return false;
+			}
+
+			return false;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+			{
+				return true;
+			}
+
+			if (!(obj is AttributeCertificateHolder))
+			{
+				return false;
+			}
+
+			AttributeCertificateHolder other = (AttributeCertificateHolder)obj;
+
+			return this.holder.Equals(other.holder);
+		}
+
+		public override int GetHashCode()
+		{
+			return this.holder.GetHashCode();
+		}
+
+		public bool Match(
+			object obj)
+		{
+			if (!(obj is X509Certificate))
+			{
+				return false;
+			}
+
+//			return Match((Certificate)obj);
+			return Match((X509Certificate)obj);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/AttributeCertificateIssuer.cs b/BouncyCastle.AxCrypt/src/x509/AttributeCertificateIssuer.cs
new file mode 100644
index 0000000..7df1416
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/AttributeCertificateIssuer.cs
@@ -0,0 +1,199 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * Carrying class for an attribute certificate issuer.
+	 */
+	public class AttributeCertificateIssuer
+		//: CertSelector, Selector
+		: IX509Selector
+	{
+		internal readonly Asn1Encodable form;
+
+		/**
+		 * Set the issuer directly with the ASN.1 structure.
+		 *
+		 * @param issuer The issuer
+		 */
+		public AttributeCertificateIssuer(
+			AttCertIssuer issuer)
+		{
+			form = issuer.Issuer;
+		}
+
+		public AttributeCertificateIssuer(
+			X509Name principal)
+		{
+//			form = new V2Form(GeneralNames.GetInstance(new DerSequence(new GeneralName(principal))));
+			form = new V2Form(new GeneralNames(new GeneralName(principal)));
+		}
+
+		private object[] GetNames()
+		{
+			GeneralNames name;
+			if (form is V2Form)
+			{
+				name = ((V2Form)form).IssuerName;
+			}
+			else
+			{
+				name = (GeneralNames)form;
+			}
+
+            GeneralName[] names = name.GetNames();
+
+            int count = 0;
+            for (int i = 0; i != names.Length; i++)
+            {
+                if (names[i].TagNo == GeneralName.DirectoryName)
+                {
+                    ++count;
+                }
+            }
+
+            object[] result = new object[count];
+
+            int pos = 0;
+            for (int i = 0; i != names.Length; i++)
+			{
+				if (names[i].TagNo == GeneralName.DirectoryName)
+				{
+                    result[pos++] = X509Name.GetInstance(names[i].Name);
+				}
+			}
+
+            return result;
+        }
+
+		/// <summary>Return any principal objects inside the attribute certificate issuer object.</summary>
+		/// <returns>An array of IPrincipal objects (usually X509Principal).</returns>
+		public X509Name[] GetPrincipals()
+		{
+			object[] p = this.GetNames();
+
+            int count = 0;
+            for (int i = 0; i != p.Length; i++)
+            {
+                if (p[i] is X509Name)
+                {
+                    ++count;
+                }
+            }
+
+            X509Name[] result = new X509Name[count];
+
+            int pos = 0;
+			for (int i = 0; i != p.Length; i++)
+			{
+				if (p[i] is X509Name)
+				{
+					result[pos++] = (X509Name)p[i];
+				}
+			}
+
+            return result;
+		}
+
+		private bool MatchesDN(
+			X509Name		subject,
+			GeneralNames	targets)
+		{
+			GeneralName[] names = targets.GetNames();
+
+			for (int i = 0; i != names.Length; i++)
+			{
+				GeneralName gn = names[i];
+
+				if (gn.TagNo == GeneralName.DirectoryName)
+				{
+					try
+					{
+						if (X509Name.GetInstance(gn.Name).Equivalent(subject))
+						{
+							return true;
+						}
+					}
+					catch (Exception)
+					{
+					}
+				}
+			}
+
+			return false;
+		}
+
+		public object Clone()
+		{
+			return new AttributeCertificateIssuer(AttCertIssuer.GetInstance(form));
+		}
+
+		public bool Match(
+//			Certificate cert)
+			X509Certificate x509Cert)
+		{
+//			if (!(cert is X509Certificate))
+//			{
+//				return false;
+//			}
+//
+//			X509Certificate x509Cert = (X509Certificate)cert;
+
+			if (form is V2Form)
+			{
+				V2Form issuer = (V2Form) form;
+				if (issuer.BaseCertificateID != null)
+				{
+					return issuer.BaseCertificateID.Serial.Value.Equals(x509Cert.SerialNumber)
+						&& MatchesDN(x509Cert.IssuerDN, issuer.BaseCertificateID.Issuer);
+				}
+
+				return MatchesDN(x509Cert.SubjectDN, issuer.IssuerName);
+			}
+
+			return MatchesDN(x509Cert.SubjectDN, (GeneralNames) form);
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+			{
+				return true;
+			}
+
+			if (!(obj is AttributeCertificateIssuer))
+			{
+				return false;
+			}
+
+			AttributeCertificateIssuer other = (AttributeCertificateIssuer)obj;
+
+			return this.form.Equals(other.form);
+		}
+
+		public override int GetHashCode()
+		{
+			return this.form.GetHashCode();
+		}
+
+		public bool Match(
+			object obj)
+		{
+			if (!(obj is X509Certificate))
+			{
+				return false;
+			}
+
+			//return Match((Certificate)obj);
+			return Match((X509Certificate)obj);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/IX509AttributeCertificate.cs b/BouncyCastle.AxCrypt/src/x509/IX509AttributeCertificate.cs
new file mode 100644
index 0000000..9a3004e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/IX509AttributeCertificate.cs
@@ -0,0 +1,57 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <remarks>Interface for an X.509 Attribute Certificate.</remarks>
+	public interface IX509AttributeCertificate
+		: IX509Extension
+	{
+		/// <summary>The version number for the certificate.</summary>
+		int Version { get; }
+
+		/// <summary>The serial number for the certificate.</summary>
+		BigInteger SerialNumber { get; }
+
+		/// <summary>The UTC DateTime before which the certificate is not valid.</summary>
+		DateTime NotBefore { get; }
+
+		/// <summary>The UTC DateTime after which the certificate is not valid.</summary>
+		DateTime NotAfter { get; }
+
+		/// <summary>The holder of the certificate.</summary>
+		AttributeCertificateHolder Holder { get; }
+
+		/// <summary>The issuer details for the certificate.</summary>
+		AttributeCertificateIssuer Issuer { get; }
+
+		/// <summary>Return the attributes contained in the attribute block in the certificate.</summary>
+		/// <returns>An array of attributes.</returns>
+		X509Attribute[] GetAttributes();
+
+		/// <summary>Return the attributes with the same type as the passed in oid.</summary>
+		/// <param name="oid">The object identifier we wish to match.</param>
+		/// <returns>An array of matched attributes, null if there is no match.</returns>
+		X509Attribute[] GetAttributes(string oid);
+
+		bool[] GetIssuerUniqueID();
+
+		bool IsValidNow { get; }
+		bool IsValid(DateTime date);
+
+		void CheckValidity();
+		void CheckValidity(DateTime date);
+
+		byte[] GetSignature();
+
+		void Verify(AsymmetricKeyParameter publicKey);
+
+		/// <summary>Return an ASN.1 encoded byte array representing the attribute certificate.</summary>
+		/// <returns>An ASN.1 encoded byte array.</returns>
+		/// <exception cref="IOException">If the certificate cannot be encoded.</exception>
+		byte[] GetEncoded();
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/IX509Extension.cs b/BouncyCastle.AxCrypt/src/x509/IX509Extension.cs
new file mode 100644
index 0000000..e861e87
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/IX509Extension.cs
@@ -0,0 +1,27 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.X509
+{
+	public interface IX509Extension
+	{
+		/// <summary>
+		/// Get all critical extension values, by oid
+		/// </summary>
+		/// <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+		ISet GetCriticalExtensionOids();
+
+		/// <summary>
+		/// Get all non-critical extension values, by oid
+		/// </summary>
+		/// <returns>IDictionary with string (OID) keys and Asn1OctetString values</returns>
+		ISet GetNonCriticalExtensionOids();
+
+		[Obsolete("Use version taking a DerObjectIdentifier instead")]
+		Asn1OctetString GetExtensionValue(string oid);
+
+		Asn1OctetString GetExtensionValue(DerObjectIdentifier oid);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/PEMParser.cs b/BouncyCastle.AxCrypt/src/x509/PEMParser.cs
new file mode 100644
index 0000000..8c117f3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/PEMParser.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.X509
+{
+	class PemParser
+	{
+		private readonly string _header1;
+		private readonly string _header2;
+		private readonly string _footer1;
+		private readonly string _footer2;
+
+		internal PemParser(
+			string type)
+		{
+			_header1 = "-----BEGIN " + type + "-----";
+			_header2 = "-----BEGIN X509 " + type + "-----";
+			_footer1 = "-----END " + type + "-----";
+			_footer2 = "-----END X509 " + type + "-----";
+		}
+
+		private string ReadLine(
+			Stream inStream)
+		{
+			int c;
+			StringBuilder l = new StringBuilder();
+
+			do
+			{
+				while (((c = inStream.ReadByte()) != '\r') && c != '\n' && (c >= 0))
+				{
+					if (c == '\r')
+					{
+						continue;
+					}
+
+					l.Append((char)c);
+				}
+			}
+			while (c >= 0 && l.Length == 0);
+
+			if (c < 0)
+			{
+				return null;
+			}
+
+			return l.ToString();
+		}
+
+		internal Asn1Sequence ReadPemObject(
+			Stream inStream)
+		{
+			string line;
+			StringBuilder pemBuf = new StringBuilder();
+
+			while ((line = ReadLine(inStream)) != null)
+			{
+				if (line.StartsWith(_header1) || line.StartsWith(_header2))
+				{
+					break;
+				}
+			}
+
+			while ((line = ReadLine(inStream)) != null)
+			{
+				if (line.StartsWith(_footer1) || line.StartsWith(_footer2))
+				{
+					break;
+				}
+
+				pemBuf.Append(line);
+			}
+
+			if (pemBuf.Length != 0)
+			{
+				Asn1Object o = Asn1Object.FromByteArray(Base64.Decode(pemBuf.ToString()));
+
+				if (!(o is Asn1Sequence))
+				{
+					throw new IOException("malformed PEM data encountered");
+				}
+
+				return (Asn1Sequence) o;
+			}
+
+			return null;
+		}
+	}
+}
+
diff --git a/BouncyCastle.AxCrypt/src/x509/PrincipalUtil.cs b/BouncyCastle.AxCrypt/src/x509/PrincipalUtil.cs
new file mode 100644
index 0000000..0edc4a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/PrincipalUtil.cs
@@ -0,0 +1,70 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <remarks>
+	/// A utility class that will extract X509Principal objects from X.509 certificates.
+	/// <p>
+	/// Use this in preference to trying to recreate a principal from a string, not all
+	/// DNs are what they should be, so it's best to leave them encoded where they
+	/// can be.</p>
+	/// </remarks>
+	public class PrincipalUtilities
+	{
+		/// <summary>Return the issuer of the given cert as an X509Principal.</summary>
+		public static X509Name GetIssuerX509Principal(
+			X509Certificate cert)
+		{
+			try
+			{
+				TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance(
+					Asn1Object.FromByteArray(cert.GetTbsCertificate()));
+
+				return tbsCert.Issuer;
+			}
+			catch (Exception e)
+			{
+				throw new CertificateEncodingException("Could not extract issuer", e);
+			}
+		}
+
+		/// <summary>Return the subject of the given cert as an X509Principal.</summary>
+		public static X509Name GetSubjectX509Principal(
+			X509Certificate cert)
+		{
+			try
+			{
+				TbsCertificateStructure tbsCert = TbsCertificateStructure.GetInstance(
+					Asn1Object.FromByteArray(cert.GetTbsCertificate()));
+
+				return tbsCert.Subject;
+			}
+			catch (Exception e)
+			{
+				throw new CertificateEncodingException("Could not extract subject", e);
+			}
+		}
+
+		/// <summary>Return the issuer of the given CRL as an X509Principal.</summary>
+		public static X509Name GetIssuerX509Principal(
+			X509Crl crl)
+		{
+			try
+			{
+				TbsCertificateList tbsCertList = TbsCertificateList.GetInstance(
+					Asn1Object.FromByteArray(crl.GetTbsCertList()));
+
+				return tbsCertList.Issuer;
+			}
+			catch (Exception e)
+			{
+				throw new CrlException("Could not extract issuer", e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/SubjectPublicKeyInfoFactory.cs b/BouncyCastle.AxCrypt/src/x509/SubjectPublicKeyInfoFactory.cs
new file mode 100644
index 0000000..bb6f378
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/SubjectPublicKeyInfoFactory.cs
@@ -0,0 +1,187 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509
+{
+    /// <summary>
+    /// A factory to produce Public Key Info Objects.
+    /// </summary>
+    public sealed class SubjectPublicKeyInfoFactory
+    {
+        private SubjectPublicKeyInfoFactory()
+        {
+        }
+
+        /// <summary>
+        /// Create a Subject Public Key Info object for a given public key.
+        /// </summary>
+        /// <param name="key">One of ElGammalPublicKeyParameters, DSAPublicKeyParameter, DHPublicKeyParameters, RsaKeyParameters or ECPublicKeyParameters</param>
+        /// <returns>A subject public key info object.</returns>
+        /// <exception cref="Exception">Throw exception if object provided is not one of the above.</exception>
+        public static SubjectPublicKeyInfo CreateSubjectPublicKeyInfo(
+            AsymmetricKeyParameter key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+            if (key.IsPrivate)
+                throw new ArgumentException("Private key passed - public key expected.", "key");
+
+            if (key is ElGamalPublicKeyParameters)
+            {
+                ElGamalPublicKeyParameters _key = (ElGamalPublicKeyParameters)key;
+                ElGamalParameters kp = _key.Parameters;
+
+                SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(
+                        OiwObjectIdentifiers.ElGamalAlgorithm,
+                        new ElGamalParameter(kp.P, kp.G).ToAsn1Object()),
+                        new DerInteger(_key.Y));
+
+                return info;
+            }
+
+            if (key is DsaPublicKeyParameters)
+            {
+                DsaPublicKeyParameters _key = (DsaPublicKeyParameters) key;
+                DsaParameters kp = _key.Parameters;
+                Asn1Encodable ae = kp == null
+                    ?	null
+                    :	new DsaParameter(kp.P, kp.Q, kp.G).ToAsn1Object();
+
+                return new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(X9ObjectIdentifiers.IdDsa, ae),
+                    new DerInteger(_key.Y));
+            }
+
+            if (key is DHPublicKeyParameters)
+            {
+                DHPublicKeyParameters _key = (DHPublicKeyParameters) key;
+                DHParameters kp = _key.Parameters;
+
+                SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(
+                        _key.AlgorithmOid,
+                        new DHParameter(kp.P, kp.G, kp.L).ToAsn1Object()),
+                        new DerInteger(_key.Y));
+
+                return info;
+            } // End of DH
+
+            if (key is RsaKeyParameters)
+            {
+                RsaKeyParameters _key = (RsaKeyParameters) key;
+
+                SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+                    new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
+                    new RsaPublicKeyStructure(_key.Modulus, _key.Exponent).ToAsn1Object());
+
+                return info;
+            } // End of RSA.
+
+            if (key is ECPublicKeyParameters)
+            {
+                ECPublicKeyParameters _key = (ECPublicKeyParameters) key;
+
+                if (_key.AlgorithmName == "ECGOST3410")
+                {
+                    if (_key.PublicKeyParamSet == null)
+                        throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+                    ECPoint q = _key.Q.Normalize();
+                    BigInteger bX = q.AffineXCoord.ToBigInteger();
+                    BigInteger bY = q.AffineYCoord.ToBigInteger();
+
+                    byte[] encKey = new byte[64];
+                    ExtractBytes(encKey, 0, bX);
+                    ExtractBytes(encKey, 32, bY);
+
+                    Gost3410PublicKeyAlgParameters gostParams = new Gost3410PublicKeyAlgParameters(
+                        _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+
+                    AlgorithmIdentifier algID = new AlgorithmIdentifier(
+                        CryptoProObjectIdentifiers.GostR3410x2001,
+                        gostParams.ToAsn1Object());
+
+                    return new SubjectPublicKeyInfo(algID, new DerOctetString(encKey));
+                }
+                else
+                {
+                    X962Parameters x962;
+                    if (_key.PublicKeyParamSet == null)
+                    {
+                        ECDomainParameters kp = _key.Parameters;
+                        X9ECParameters ecP = new X9ECParameters(kp.Curve, kp.G, kp.N, kp.H, kp.GetSeed());
+
+                        x962 = new X962Parameters(ecP);
+                    }
+                    else
+                    {
+                        x962 = new X962Parameters(_key.PublicKeyParamSet);
+                    }
+
+                    Asn1OctetString p = (Asn1OctetString)(new X9ECPoint(_key.Q).ToAsn1Object());
+
+                    AlgorithmIdentifier algID = new AlgorithmIdentifier(
+                        X9ObjectIdentifiers.IdECPublicKey, x962.ToAsn1Object());
+
+                    return new SubjectPublicKeyInfo(algID, p.GetOctets());
+                }
+            } // End of EC
+
+            if (key is Gost3410PublicKeyParameters)
+            {
+                Gost3410PublicKeyParameters _key = (Gost3410PublicKeyParameters) key;
+
+                if (_key.PublicKeyParamSet == null)
+                    throw Platform.CreateNotImplementedException("Not a CryptoPro parameter set");
+
+                byte[] keyEnc = _key.Y.ToByteArrayUnsigned();
+                byte[] keyBytes = new byte[keyEnc.Length];
+
+                for (int i = 0; i != keyBytes.Length; i++)
+                {
+                    keyBytes[i] = keyEnc[keyEnc.Length - 1 - i]; // must be little endian
+                }
+
+                Gost3410PublicKeyAlgParameters algParams = new Gost3410PublicKeyAlgParameters(
+                    _key.PublicKeyParamSet, CryptoProObjectIdentifiers.GostR3411x94CryptoProParamSet);
+
+                AlgorithmIdentifier algID = new AlgorithmIdentifier(
+                    CryptoProObjectIdentifiers.GostR3410x94,
+                    algParams.ToAsn1Object());
+
+                return new SubjectPublicKeyInfo(algID, new DerOctetString(keyBytes));
+            }
+
+            throw new ArgumentException("Class provided no convertible: " + key.GetType().FullName);
+        }
+
+        private static void ExtractBytes(
+            byte[]		encKey,
+            int			offset,
+            BigInteger	bI)
+        {
+            byte[] val = bI.ToByteArray();
+            int n = (bI.BitLength + 7) / 8;
+
+            for (int i = 0; i < n; ++i)
+            {
+                encKey[offset + i] = val[val.Length - 1 - i];
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509AttrCertParser.cs b/BouncyCastle.AxCrypt/src/x509/X509AttrCertParser.cs
new file mode 100644
index 0000000..a5c0736
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509AttrCertParser.cs
@@ -0,0 +1,173 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.X509
+{
+	public class X509AttrCertParser
+	{
+		private static readonly PemParser PemAttrCertParser = new PemParser("ATTRIBUTE CERTIFICATE");
+
+		private Asn1Set	sData;
+		private int		sDataObjectCount;
+		private Stream	currentStream;
+
+		private IX509AttributeCertificate ReadDerCertificate(
+			Asn1InputStream dIn)
+		{
+			Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
+
+			if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
+			{
+				if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
+				{
+					sData = SignedData.GetInstance(
+						Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates;
+
+					return GetCertificate();
+				}
+			}
+
+//			return new X509V2AttributeCertificate(seq.getEncoded());
+			return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq));
+		}
+
+		private IX509AttributeCertificate GetCertificate()
+		{
+			if (sData != null)
+			{
+				while (sDataObjectCount < sData.Count)
+				{
+					object obj = sData[sDataObjectCount++];
+
+					if (obj is Asn1TaggedObject && ((Asn1TaggedObject)obj).TagNo == 2)
+					{
+						//return new X509V2AttributeCertificate(
+						//	Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false).GetEncoded());
+						return new X509V2AttributeCertificate(
+							AttributeCertificate.GetInstance(
+								Asn1Sequence.GetInstance((Asn1TaggedObject)obj, false)));
+					}
+				}
+			}
+
+			return null;
+		}
+
+		private IX509AttributeCertificate ReadPemCertificate(
+			Stream inStream)
+		{
+			Asn1Sequence seq = PemAttrCertParser.ReadPemObject(inStream);
+
+			return seq == null
+				?	null
+				//:	new X509V2AttributeCertificate(seq.getEncoded());
+				:	new X509V2AttributeCertificate(AttributeCertificate.GetInstance(seq));
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public IX509AttributeCertificate ReadAttrCert(
+			byte[] input)
+		{
+			return ReadAttrCert(new MemoryStream(input, false));
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public ICollection ReadAttrCerts(
+			byte[] input)
+		{
+			return ReadAttrCerts(new MemoryStream(input, false));
+		}
+
+		/**
+		 * Generates a certificate object and initializes it with the data
+		 * read from the input stream inStream.
+		 */
+		public IX509AttributeCertificate ReadAttrCert(
+			Stream inStream)
+		{
+			if (inStream == null)
+				throw new ArgumentNullException("inStream");
+			if (!inStream.CanRead)
+				throw new ArgumentException("inStream must be read-able", "inStream");
+
+			if (currentStream == null)
+			{
+				currentStream = inStream;
+				sData = null;
+				sDataObjectCount = 0;
+			}
+			else if (currentStream != inStream) // reset if input stream has changed
+			{
+				currentStream = inStream;
+				sData = null;
+				sDataObjectCount = 0;
+			}
+
+			try
+			{
+				if (sData != null)
+				{
+					if (sDataObjectCount != sData.Count)
+					{
+						return GetCertificate();
+					}
+
+					sData = null;
+					sDataObjectCount = 0;
+					return null;
+				}
+
+				PushbackStream pis = new PushbackStream(inStream);
+				int tag = pis.ReadByte();
+
+				if (tag < 0)
+					return null;
+
+				pis.Unread(tag);
+
+				if (tag != 0x30)  // assume ascii PEM encoded.
+				{
+					return ReadPemCertificate(pis);
+				}
+
+				return ReadDerCertificate(new Asn1InputStream(pis));
+			}
+			catch (Exception e)
+			{
+				throw new CertificateException(e.ToString());
+			}
+		}
+
+		/**
+		 * Returns a (possibly empty) collection view of the certificates
+		 * read from the given input stream inStream.
+		 */
+		public ICollection ReadAttrCerts(
+			Stream inStream)
+		{
+			IX509AttributeCertificate attrCert;
+            IList attrCerts = Platform.CreateArrayList();
+
+			while ((attrCert = ReadAttrCert(inStream)) != null)
+			{
+				attrCerts.Add(attrCert);
+			}
+
+			return attrCerts;
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/src/x509/X509Attribute.cs b/BouncyCastle.AxCrypt/src/x509/X509Attribute.cs
new file mode 100644
index 0000000..248d66c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509Attribute.cs
@@ -0,0 +1,76 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * Class for carrying the values in an X.509 Attribute.
+	 */
+	public class X509Attribute
+		: Asn1Encodable
+	{
+		private readonly AttributeX509 attr;
+
+		/**
+		 * @param at an object representing an attribute.
+		 */
+		internal X509Attribute(
+			Asn1Encodable at)
+		{
+			this.attr = AttributeX509.GetInstance(at);
+		}
+
+		/**
+		 * Create an X.509 Attribute with the type given by the passed in oid and
+		 * the value represented by an ASN.1 Set containing value.
+		 *
+		 * @param oid type of the attribute
+		 * @param value value object to go into the atribute's value set.
+		 */
+		public X509Attribute(
+			string			oid,
+			Asn1Encodable	value)
+		{
+			this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value));
+		}
+
+		/**
+		 * Create an X.59 Attribute with the type given by the passed in oid and the
+		 * value represented by an ASN.1 Set containing the objects in value.
+		 *
+		 * @param oid type of the attribute
+		 * @param value vector of values to go in the attribute's value set.
+		 */
+		public X509Attribute(
+			string              oid,
+			Asn1EncodableVector value)
+		{
+			this.attr = new AttributeX509(new DerObjectIdentifier(oid), new DerSet(value));
+		}
+
+		public string Oid
+		{
+			get { return attr.AttrType.Id; }
+		}
+
+		public Asn1Encodable[] GetValues()
+		{
+			Asn1Set s = attr.AttrValues;
+			Asn1Encodable[] values = new Asn1Encodable[s.Count];
+
+			for (int i = 0; i != s.Count; i++)
+			{
+				values[i] = (Asn1Encodable)s[i];
+			}
+
+			return values;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return attr.ToAsn1Object();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509CertPairParser.cs b/BouncyCastle.AxCrypt/src/x509/X509CertPairParser.cs
new file mode 100644
index 0000000..8261259
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509CertPairParser.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.X509
+{
+	public class X509CertPairParser
+	{
+		private Stream currentStream;
+
+		private X509CertificatePair ReadDerCrossCertificatePair(
+			Stream inStream)
+		{
+			Asn1InputStream dIn = new Asn1InputStream(inStream);//, ProviderUtil.getReadLimit(in));
+			Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
+			CertificatePair pair = CertificatePair.GetInstance(seq);
+			return new X509CertificatePair(pair);
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public X509CertificatePair ReadCertPair(
+			byte[] input)
+		{
+			return ReadCertPair(new MemoryStream(input, false));
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public ICollection ReadCertPairs(
+			byte[] input)
+		{
+			return ReadCertPairs(new MemoryStream(input, false));
+		}
+
+		public X509CertificatePair ReadCertPair(
+			Stream inStream)
+		{
+			if (inStream == null)
+				throw new ArgumentNullException("inStream");
+			if (!inStream.CanRead)
+				throw new ArgumentException("inStream must be read-able", "inStream");
+
+			if (currentStream == null)
+			{
+				currentStream = inStream;
+			}
+			else if (currentStream != inStream) // reset if input stream has changed
+			{
+				currentStream = inStream;
+			}
+
+			try
+			{
+				PushbackStream pis = new PushbackStream(inStream);
+				int tag = pis.ReadByte();
+
+				if (tag < 0)
+					return null;
+
+				pis.Unread(tag);
+
+				return ReadDerCrossCertificatePair(pis);
+			}
+			catch (Exception e)
+			{
+				throw new CertificateException(e.ToString());
+			}
+		}
+
+		public ICollection ReadCertPairs(
+			Stream inStream)
+		{
+			X509CertificatePair certPair;
+			IList certPairs = Platform.CreateArrayList();
+
+			while ((certPair = ReadCertPair(inStream)) != null)
+			{
+				certPairs.Add(certPair);
+			}
+
+			return certPairs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509Certificate.cs b/BouncyCastle.AxCrypt/src/x509/X509Certificate.cs
new file mode 100644
index 0000000..f156f31
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509Certificate.cs
@@ -0,0 +1,595 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509
+{
+    /// <summary>
+    /// An Object representing an X509 Certificate.
+    /// Has static methods for loading Certificates encoded in many forms that return X509Certificate Objects.
+    /// </summary>
+    public class X509Certificate
+		:	X509ExtensionBase
+//		, PKCS12BagAttributeCarrier
+    {
+        private readonly X509CertificateStructure c;
+//        private Hashtable pkcs12Attributes = new Hashtable();
+//        private ArrayList pkcs12Ordering = new ArrayList();
+		private readonly BasicConstraints basicConstraints;
+		private readonly bool[] keyUsage;
+
+		private bool hashValueSet;
+		private int hashValue;
+
+		protected X509Certificate()
+		{
+		}
+
+		public X509Certificate(
+			X509CertificateStructure c)
+		{
+			this.c = c;
+
+			try
+			{
+				Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.19"));
+
+				if (str != null)
+				{
+					basicConstraints = BasicConstraints.GetInstance(
+						X509ExtensionUtilities.FromExtensionValue(str));
+				}
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException("cannot construct BasicConstraints: " + e);
+			}
+
+			try
+			{
+				Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.15"));
+
+				if (str != null)
+				{
+					DerBitString bits = DerBitString.GetInstance(
+						X509ExtensionUtilities.FromExtensionValue(str));
+
+					byte[] bytes = bits.GetBytes();
+					int length = (bytes.Length * 8) - bits.PadBits;
+
+					keyUsage = new bool[(length < 9) ? 9 : length];
+
+					for (int i = 0; i != length; i++)
+					{
+//						keyUsage[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
+						keyUsage[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0;
+					}
+				}
+				else
+				{
+					keyUsage = null;
+				}
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException("cannot construct KeyUsage: " + e);
+			}
+		}
+
+//		internal X509Certificate(
+//			Asn1Sequence seq)
+//        {
+//            this.c = X509CertificateStructure.GetInstance(seq);
+//        }
+
+//		/// <summary>
+//        /// Load certificate from byte array.
+//        /// </summary>
+//        /// <param name="encoded">Byte array containing encoded X509Certificate.</param>
+//        public X509Certificate(
+//            byte[] encoded)
+//			: this((Asn1Sequence) new Asn1InputStream(encoded).ReadObject())
+//		{
+//        }
+//
+//        /// <summary>
+//        /// Load certificate from Stream.
+//        /// Must be positioned at start of certificate.
+//        /// </summary>
+//        /// <param name="input"></param>
+//        public X509Certificate(
+//            Stream input)
+//			: this((Asn1Sequence) new Asn1InputStream(input).ReadObject())
+//        {
+//        }
+
+		public virtual X509CertificateStructure CertificateStructure
+		{
+			get { return c; }
+		}
+
+		/// <summary>
+        /// Return true if the current time is within the start and end times nominated on the certificate.
+        /// </summary>
+        /// <returns>true id certificate is valid for the current time.</returns>
+        public virtual bool IsValidNow
+        {
+			get { return IsValid(DateTime.UtcNow); }
+        }
+
+		/// <summary>
+        /// Return true if the nominated time is within the start and end times nominated on the certificate.
+        /// </summary>
+        /// <param name="time">The time to test validity against.</param>
+        /// <returns>True if certificate is valid for nominated time.</returns>
+        public virtual bool IsValid(
+			DateTime time)
+        {
+            return time.CompareTo(NotBefore) >= 0 && time.CompareTo(NotAfter) <= 0;
+        }
+
+		/// <summary>
+		/// Checks if the current date is within certificate's validity period.
+		/// </summary>
+		public virtual void CheckValidity()
+		{
+			this.CheckValidity(DateTime.UtcNow);
+		}
+
+		/// <summary>
+		/// Checks if the given date is within certificate's validity period.
+		/// </summary>
+		/// <exception cref="CertificateExpiredException">if the certificate is expired by given date</exception>
+		/// <exception cref="CertificateNotYetValidException">if the certificate is not yet valid on given date</exception>
+		public virtual void CheckValidity(
+			DateTime time)
+		{
+			if (time.CompareTo(NotAfter) > 0)
+				throw new CertificateExpiredException("certificate expired on " + c.EndDate.GetTime());
+			if (time.CompareTo(NotBefore) < 0)
+				throw new CertificateNotYetValidException("certificate not valid until " + c.StartDate.GetTime());
+		}
+
+		/// <summary>
+        /// Return the certificate's version.
+        /// </summary>
+        /// <returns>An integer whose value Equals the version of the cerficate.</returns>
+        public virtual int Version
+        {
+            get { return c.Version; }
+        }
+
+		/// <summary>
+        /// Return a <see cref="Org.BouncyCastle.Math.BigInteger">BigInteger</see> containing the serial number.
+        /// </summary>
+        /// <returns>The Serial number.</returns>
+        public virtual BigInteger SerialNumber
+        {
+            get { return c.SerialNumber.Value; }
+        }
+
+		/// <summary>
+        /// Get the Issuer Distinguished Name. (Who signed the certificate.)
+        /// </summary>
+        /// <returns>And X509Object containing name and value pairs.</returns>
+//        public IPrincipal IssuerDN
+		public virtual X509Name IssuerDN
+		{
+            get { return c.Issuer; }
+        }
+
+		/// <summary>
+        /// Get the subject of this certificate.
+        /// </summary>
+        /// <returns>An X509Name object containing name and value pairs.</returns>
+//        public IPrincipal SubjectDN
+		public virtual X509Name SubjectDN
+		{
+            get { return c.Subject; }
+        }
+
+		/// <summary>
+		/// The time that this certificate is valid from.
+		/// </summary>
+		/// <returns>A DateTime object representing that time in the local time zone.</returns>
+		public virtual DateTime NotBefore
+		{
+			get { return c.StartDate.ToDateTime(); }
+		}
+
+		/// <summary>
+        /// The time that this certificate is valid up to.
+        /// </summary>
+        /// <returns>A DateTime object representing that time in the local time zone.</returns>
+        public virtual DateTime NotAfter
+        {
+			get { return c.EndDate.ToDateTime(); }
+        }
+
+		/// <summary>
+		/// Return the Der encoded TbsCertificate data.
+		/// This is the certificate component less the signature.
+		/// To Get the whole certificate call the GetEncoded() member.
+		/// </summary>
+		/// <returns>A byte array containing the Der encoded Certificate component.</returns>
+		public virtual byte[] GetTbsCertificate()
+		{
+			return c.TbsCertificate.GetDerEncoded();
+		}
+
+		/// <summary>
+		/// The signature.
+		/// </summary>
+		/// <returns>A byte array containg the signature of the certificate.</returns>
+		public virtual byte[] GetSignature()
+		{
+			return c.Signature.GetBytes();
+		}
+
+		/// <summary>
+		/// A meaningful version of the Signature Algorithm. (EG SHA1WITHRSA)
+		/// </summary>
+		/// <returns>A sting representing the signature algorithm.</returns>
+		public virtual string SigAlgName
+		{
+			get { return SignerUtilities.GetEncodingName(c.SignatureAlgorithm.ObjectID); }
+		}
+
+		/// <summary>
+		/// Get the Signature Algorithms Object ID.
+		/// </summary>
+		/// <returns>A string containg a '.' separated object id.</returns>
+		public virtual string SigAlgOid
+		{
+			get { return c.SignatureAlgorithm.ObjectID.Id; }
+		}
+
+		/// <summary>
+		/// Get the signature algorithms parameters. (EG DSA Parameters)
+		/// </summary>
+		/// <returns>A byte array containing the Der encoded version of the parameters or null if there are none.</returns>
+		public virtual byte[] GetSigAlgParams()
+		{
+			if (c.SignatureAlgorithm.Parameters != null)
+			{
+				return c.SignatureAlgorithm.Parameters.GetDerEncoded();
+			}
+
+			return null;
+		}
+
+		/// <summary>
+		/// Get the issuers UID.
+		/// </summary>
+		/// <returns>A DerBitString.</returns>
+		public virtual DerBitString IssuerUniqueID
+		{
+			get { return c.TbsCertificate.IssuerUniqueID; }
+		}
+
+		/// <summary>
+		/// Get the subjects UID.
+		/// </summary>
+		/// <returns>A DerBitString.</returns>
+		public virtual DerBitString SubjectUniqueID
+		{
+			get { return c.TbsCertificate.SubjectUniqueID; }
+		}
+
+		/// <summary>
+		/// Get a key usage guidlines.
+		/// </summary>
+		public virtual bool[] GetKeyUsage()
+		{
+			return keyUsage == null ? null : (bool[]) keyUsage.Clone();
+		}
+
+		// TODO Replace with something that returns a list of DerObjectIdentifier
+		public virtual IList GetExtendedKeyUsage()
+		{
+			Asn1OctetString str = this.GetExtensionValue(new DerObjectIdentifier("2.5.29.37"));
+
+			if (str == null)
+				return null;
+
+			try
+			{
+				Asn1Sequence seq = Asn1Sequence.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(str));
+
+                IList list = Platform.CreateArrayList();
+
+				foreach (DerObjectIdentifier oid in seq)
+				{
+					list.Add(oid.Id);
+				}
+
+				return list;
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException("error processing extended key usage extension", e);
+			}
+		}
+
+		public virtual int GetBasicConstraints()
+		{
+			if (basicConstraints != null && basicConstraints.IsCA())
+			{
+				if (basicConstraints.PathLenConstraint == null)
+				{
+					return int.MaxValue;
+				}
+
+				return basicConstraints.PathLenConstraint.IntValue;
+			}
+
+			return -1;
+		}
+
+		public virtual ICollection GetSubjectAlternativeNames()
+		{
+			return GetAlternativeNames("2.5.29.17");
+		}
+
+		public virtual ICollection GetIssuerAlternativeNames()
+		{
+			return GetAlternativeNames("2.5.29.18");
+		}
+
+		protected virtual ICollection GetAlternativeNames(
+			string oid)
+		{
+			Asn1OctetString altNames = GetExtensionValue(new DerObjectIdentifier(oid));
+
+			if (altNames == null)
+				return null;
+
+			Asn1Object asn1Object = X509ExtensionUtilities.FromExtensionValue(altNames);
+
+			GeneralNames gns = GeneralNames.GetInstance(asn1Object);
+
+            IList result = Platform.CreateArrayList();
+			foreach (GeneralName gn in gns.GetNames())
+			{
+                IList entry = Platform.CreateArrayList();
+				entry.Add(gn.TagNo);
+				entry.Add(gn.Name.ToString());
+				result.Add(entry);
+			}
+			return result;
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return c.Version == 3
+				?	c.TbsCertificate.Extensions
+				:	null;
+		}
+
+		/// <summary>
+		/// Get the public key of the subject of the certificate.
+		/// </summary>
+		/// <returns>The public key parameters.</returns>
+		public virtual AsymmetricKeyParameter GetPublicKey()
+		{
+			return PublicKeyFactory.CreateKey(c.SubjectPublicKeyInfo);
+		}
+
+		/// <summary>
+		/// Return a Der encoded version of this certificate.
+		/// </summary>
+		/// <returns>A byte array.</returns>
+		public virtual byte[] GetEncoded()
+		{
+			return c.GetDerEncoded();
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			X509Certificate other = obj as X509Certificate;
+
+			if (other == null)
+				return false;
+
+			return c.Equals(other.c);
+
+			// NB: May prefer this implementation of Equals if more than one certificate implementation in play
+//			return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
+		}
+
+		public override int GetHashCode()
+		{
+			lock (this)
+			{
+				if (!hashValueSet)
+				{
+					hashValue = c.GetHashCode();
+					hashValueSet = true;
+				}
+			}
+
+			return hashValue;
+		}
+
+//		public void setBagAttribute(
+//			DERObjectIdentifier oid,
+//			DEREncodable        attribute)
+//		{
+//			pkcs12Attributes.put(oid, attribute);
+//			pkcs12Ordering.addElement(oid);
+//		}
+//
+//		public DEREncodable getBagAttribute(
+//			DERObjectIdentifier oid)
+//		{
+//			return (DEREncodable)pkcs12Attributes.get(oid);
+//		}
+//
+//		public Enumeration getBagAttributeKeys()
+//		{
+//			return pkcs12Ordering.elements();
+//		}
+
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			string nl = Platform.NewLine;
+
+			buf.Append("  [0]         Version: ").Append(this.Version).Append(nl);
+			buf.Append("         SerialNumber: ").Append(this.SerialNumber).Append(nl);
+			buf.Append("             IssuerDN: ").Append(this.IssuerDN).Append(nl);
+			buf.Append("           Start Date: ").Append(this.NotBefore).Append(nl);
+			buf.Append("           Final Date: ").Append(this.NotAfter).Append(nl);
+			buf.Append("            SubjectDN: ").Append(this.SubjectDN).Append(nl);
+			buf.Append("           Public Key: ").Append(this.GetPublicKey()).Append(nl);
+			buf.Append("  Signature Algorithm: ").Append(this.SigAlgName).Append(nl);
+
+			byte[] sig = this.GetSignature();
+			buf.Append("            Signature: ").Append(Hex.ToHexString(sig, 0, 20)).Append(nl);
+
+			for (int i = 20; i < sig.Length; i += 20)
+			{
+				int len = System.Math.Min(20, sig.Length - i);
+				buf.Append("                       ").Append(Hex.ToHexString(sig, i, len)).Append(nl);
+			}
+
+			X509Extensions extensions = c.TbsCertificate.Extensions;
+
+			if (extensions != null)
+			{
+				IEnumerator e = extensions.ExtensionOids.GetEnumerator();
+
+				if (e.MoveNext())
+				{
+					buf.Append("       Extensions: \n");
+				}
+
+				do
+				{
+					DerObjectIdentifier oid = (DerObjectIdentifier)e.Current;
+					X509Extension ext = extensions.GetExtension(oid);
+
+					if (ext.Value != null)
+					{
+						byte[] octs = ext.Value.GetOctets();
+						Asn1Object obj = Asn1Object.FromByteArray(octs);
+						buf.Append("                       critical(").Append(ext.IsCritical).Append(") ");
+						try
+						{
+							if (oid.Equals(X509Extensions.BasicConstraints))
+							{
+								buf.Append(BasicConstraints.GetInstance(obj));
+							}
+							else if (oid.Equals(X509Extensions.KeyUsage))
+							{
+								buf.Append(KeyUsage.GetInstance(obj));
+							}
+							else if (oid.Equals(MiscObjectIdentifiers.NetscapeCertType))
+							{
+								buf.Append(new NetscapeCertType((DerBitString) obj));
+							}
+							else if (oid.Equals(MiscObjectIdentifiers.NetscapeRevocationUrl))
+							{
+								buf.Append(new NetscapeRevocationUrl((DerIA5String) obj));
+							}
+							else if (oid.Equals(MiscObjectIdentifiers.VerisignCzagExtension))
+							{
+								buf.Append(new VerisignCzagExtension((DerIA5String) obj));
+							}
+							else
+							{
+								buf.Append(oid.Id);
+								buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj));
+								//buf.Append(" value = ").Append("*****").Append(nl);
+							}
+						}
+						catch (Exception)
+						{
+							buf.Append(oid.Id);
+							//buf.Append(" value = ").Append(new string(Hex.encode(ext.getValue().getOctets()))).Append(nl);
+							buf.Append(" value = ").Append("*****");
+						}
+					}
+
+					buf.Append(nl);
+				}
+				while (e.MoveNext());
+			}
+
+			return buf.ToString();
+		}
+
+		/// <summary>
+		/// Verify the certificate's signature using the nominated public key.
+		/// </summary>
+		/// <param name="key">An appropriate public key parameter object, RsaPublicKeyParameters, DsaPublicKeyParameters or ECDsaPublicKeyParameters</param>
+		/// <returns>True if the signature is valid.</returns>
+		/// <exception cref="Exception">If key submitted is not of the above nominated types.</exception>
+		public virtual void Verify(
+			AsymmetricKeyParameter key)
+		{
+			string sigName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
+			ISigner signature = SignerUtilities.GetSigner(sigName);
+
+			CheckSignature(key, signature);
+		}
+
+		protected virtual void CheckSignature(
+			AsymmetricKeyParameter	publicKey,
+			ISigner					signature)
+		{
+			if (!IsAlgIDEqual(c.SignatureAlgorithm, c.TbsCertificate.Signature))
+				throw new CertificateException("signature algorithm in TBS cert not same as outer cert");
+
+			Asn1Encodable parameters = c.SignatureAlgorithm.Parameters;
+
+			X509SignatureUtilities.SetSignatureParameters(signature, parameters);
+
+			signature.Init(false, publicKey);
+
+			byte[] b = this.GetTbsCertificate();
+			signature.BlockUpdate(b, 0, b.Length);
+
+			byte[] sig = this.GetSignature();
+			if (!signature.VerifySignature(sig))
+			{
+				throw new InvalidKeyException("Public key presented not for certificate signature");
+			}
+		}
+
+		private static bool IsAlgIDEqual(AlgorithmIdentifier id1, AlgorithmIdentifier id2)
+		{
+			if (!id1.ObjectID.Equals(id2.ObjectID))
+				return false;
+
+			Asn1Encodable p1 = id1.Parameters;
+			Asn1Encodable p2 = id2.Parameters;
+
+			if ((p1 == null) == (p2 == null))
+				return Platform.Equals(p1, p2);
+
+			// Exactly one of p1, p2 is null at this point
+			return p1 == null
+				?	p2.ToAsn1Object() is Asn1Null
+				:	p1.ToAsn1Object() is Asn1Null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509CertificatePair.cs b/BouncyCastle.AxCrypt/src/x509/X509CertificatePair.cs
new file mode 100644
index 0000000..fbeba4d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509CertificatePair.cs
@@ -0,0 +1,123 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <remarks>
+	/// This class contains a cross certificate pair. Cross certificates pairs may
+	/// contain two cross signed certificates from two CAs. A certificate from the
+	/// other CA to this CA is contained in the forward certificate, the certificate
+	/// from this CA to the other CA is contained in the reverse certificate.
+	/// </remarks>
+	public class X509CertificatePair
+	{
+		private readonly X509Certificate forward;
+		private readonly X509Certificate reverse;
+
+		/// <summary>Constructor</summary>
+		/// <param name="forward">Certificate from the other CA to this CA.</param>
+		/// <param name="reverse">Certificate from this CA to the other CA.</param>
+		public X509CertificatePair(
+			X509Certificate	forward,
+			X509Certificate	reverse)
+		{
+			this.forward = forward;
+			this.reverse = reverse;
+		}
+
+		/// <summary>Constructor from a ASN.1 CertificatePair structure.</summary>
+		/// <param name="pair">The <c>CertificatePair</c> ASN.1 object.</param>
+		public X509CertificatePair(
+			CertificatePair pair)
+		{
+			if (pair.Forward != null)
+			{
+				this.forward = new X509Certificate(pair.Forward);
+			}
+			if (pair.Reverse != null)
+			{
+				this.reverse = new X509Certificate(pair.Reverse);
+			}
+		}
+
+		public byte[] GetEncoded()
+		{
+			try
+			{
+				X509CertificateStructure f = null, r = null;
+
+				if (forward != null)
+				{
+					f = X509CertificateStructure.GetInstance(
+						Asn1Object.FromByteArray(forward.GetEncoded()));
+
+					if (f == null)
+						throw new CertificateEncodingException("unable to get encoding for forward");
+				}
+
+				if (reverse != null)
+				{
+					r = X509CertificateStructure.GetInstance(
+						Asn1Object.FromByteArray(reverse.GetEncoded()));
+
+					if (r == null)
+						throw new CertificateEncodingException("unable to get encoding for reverse");
+				}
+
+				return new CertificatePair(f, r).GetDerEncoded();
+			}
+			catch (Exception e)
+			{
+				// TODO
+//				throw new ExtCertificateEncodingException(e.toString(), e);
+				throw new CertificateEncodingException(e.Message, e);
+			}
+		}
+
+		/// <summary>Returns the certificate from the other CA to this CA.</summary>
+		public X509Certificate Forward
+		{
+			get { return forward; }
+		}
+
+		/// <summary>Returns the certificate from this CA to the other CA.</summary>
+		public X509Certificate Reverse
+		{
+			get { return reverse; }
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			X509CertificatePair other = obj as X509CertificatePair;
+
+			if (other == null)
+				return false;
+
+			return Platform.Equals(this.forward, other.forward)
+				&& Platform.Equals(this.reverse, other.reverse);
+		}
+
+		public override int GetHashCode()
+		{
+			int hash = -1;
+			if (forward != null)
+			{
+				hash ^= forward.GetHashCode();
+			}
+			if (reverse != null)
+			{
+				hash *= 17;
+				hash ^= reverse.GetHashCode();
+			}
+			return hash;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509CertificateParser.cs b/BouncyCastle.AxCrypt/src/x509/X509CertificateParser.cs
new file mode 100644
index 0000000..8f0e740
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509CertificateParser.cs
@@ -0,0 +1,183 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * class for dealing with X509 certificates.
+	 * <p>
+	 * At the moment this will deal with "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----"
+	 * base 64 encoded certs, as well as the BER binaries of certificates and some classes of PKCS#7
+	 * objects.</p>
+	 */
+	public class X509CertificateParser
+	{
+		private static readonly PemParser PemCertParser = new PemParser("CERTIFICATE");
+
+		private Asn1Set	sData;
+		private int		sDataObjectCount;
+		private Stream	currentStream;
+
+		private X509Certificate ReadDerCertificate(
+			Asn1InputStream dIn)
+		{
+			Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
+
+			if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
+			{
+				if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
+				{
+					sData = SignedData.GetInstance(
+						Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Certificates;
+
+					return GetCertificate();
+				}
+			}
+
+			return CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
+		}
+
+		private X509Certificate GetCertificate()
+		{
+			if (sData != null)
+			{
+				while (sDataObjectCount < sData.Count)
+				{
+					object obj = sData[sDataObjectCount++];
+
+					if (obj is Asn1Sequence)
+					{
+						return CreateX509Certificate(
+							X509CertificateStructure.GetInstance(obj));
+					}
+				}
+			}
+
+			return null;
+		}
+
+		private X509Certificate ReadPemCertificate(
+			Stream inStream)
+		{
+			Asn1Sequence seq = PemCertParser.ReadPemObject(inStream);
+
+			return seq == null
+				?	null
+				:	CreateX509Certificate(X509CertificateStructure.GetInstance(seq));
+		}
+
+		protected virtual X509Certificate CreateX509Certificate(
+			X509CertificateStructure c)
+		{
+			return new X509Certificate(c);
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public X509Certificate ReadCertificate(
+			byte[] input)
+		{
+			return ReadCertificate(new MemoryStream(input, false));
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public ICollection ReadCertificates(
+			byte[] input)
+		{
+			return ReadCertificates(new MemoryStream(input, false));
+		}
+
+		/**
+		 * Generates a certificate object and initializes it with the data
+		 * read from the input stream inStream.
+		 */
+		public X509Certificate ReadCertificate(
+			Stream inStream)
+		{
+			if (inStream == null)
+				throw new ArgumentNullException("inStream");
+			if (!inStream.CanRead)
+				throw new ArgumentException("inStream must be read-able", "inStream");
+
+			if (currentStream == null)
+			{
+				currentStream = inStream;
+				sData = null;
+				sDataObjectCount = 0;
+			}
+			else if (currentStream != inStream) // reset if input stream has changed
+			{
+				currentStream = inStream;
+				sData = null;
+				sDataObjectCount = 0;
+			}
+
+			try
+			{
+				if (sData != null)
+				{
+					if (sDataObjectCount != sData.Count)
+					{
+						return GetCertificate();
+					}
+
+					sData = null;
+					sDataObjectCount = 0;
+					return null;
+				}
+
+				PushbackStream pis = new PushbackStream(inStream);
+				int tag = pis.ReadByte();
+
+				if (tag < 0)
+					return null;
+
+				pis.Unread(tag);
+
+				if (tag != 0x30)  // assume ascii PEM encoded.
+				{
+					return ReadPemCertificate(pis);
+				}
+
+				return ReadDerCertificate(new Asn1InputStream(pis));
+			}
+			catch (Exception e)
+			{
+				throw new CertificateException("Failed to read certificate", e);
+			}
+		}
+
+		/**
+		 * Returns a (possibly empty) collection view of the certificates
+		 * read from the given input stream inStream.
+		 */
+		public ICollection ReadCertificates(
+			Stream inStream)
+		{
+			X509Certificate cert;
+            IList certs = Platform.CreateArrayList();
+
+			while ((cert = ReadCertificate(inStream)) != null)
+			{
+				certs.Add(cert);
+			}
+
+			return certs;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509Crl.cs b/BouncyCastle.AxCrypt/src/x509/X509Crl.cs
new file mode 100644
index 0000000..7d0e7aa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509Crl.cs
@@ -0,0 +1,403 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * The following extensions are listed in RFC 2459 as relevant to CRLs
+	 *
+	 * Authority Key Identifier
+	 * Issuer Alternative Name
+	 * CRL Number
+	 * Delta CRL Indicator (critical)
+	 * Issuing Distribution Point (critical)
+	 */
+	public class X509Crl
+		: X509ExtensionBase
+		// TODO Add interface Crl?
+	{
+		private readonly CertificateList c;
+		private readonly string sigAlgName;
+		private readonly byte[] sigAlgParams;
+		private readonly bool isIndirect;
+
+		public X509Crl(
+			CertificateList c)
+		{
+			this.c = c;
+
+			try
+			{
+				this.sigAlgName = X509SignatureUtilities.GetSignatureName(c.SignatureAlgorithm);
+
+				if (c.SignatureAlgorithm.Parameters != null)
+				{
+					this.sigAlgParams = ((Asn1Encodable)c.SignatureAlgorithm.Parameters).GetDerEncoded();
+				}
+				else
+				{
+					this.sigAlgParams = null;
+				}
+
+				this.isIndirect = IsIndirectCrl;
+			}
+			catch (Exception e)
+			{
+				throw new CrlException("CRL contents invalid: " + e);
+			}
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return Version == 2
+				?	c.TbsCertList.Extensions
+				:	null;
+		}
+
+		public virtual byte[] GetEncoded()
+		{
+			try
+			{
+				return c.GetDerEncoded();
+			}
+			catch (Exception e)
+			{
+				throw new CrlException(e.ToString());
+			}
+		}
+
+		public virtual void Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			if (!c.SignatureAlgorithm.Equals(c.TbsCertList.Signature))
+			{
+				throw new CrlException("Signature algorithm on CertificateList does not match TbsCertList.");
+			}
+
+			ISigner sig = SignerUtilities.GetSigner(SigAlgName);
+			sig.Init(false, publicKey);
+
+			byte[] encoded = this.GetTbsCertList();
+			sig.BlockUpdate(encoded, 0, encoded.Length);
+
+			if (!sig.VerifySignature(this.GetSignature()))
+			{
+				throw new SignatureException("CRL does not verify with supplied public key.");
+			}
+		}
+
+		public virtual int Version
+		{
+			get { return c.Version; }
+		}
+
+		public virtual X509Name IssuerDN
+		{
+			get { return c.Issuer; }
+		}
+
+		public virtual DateTime ThisUpdate
+		{
+			get { return c.ThisUpdate.ToDateTime(); }
+		}
+
+		public virtual DateTimeObject NextUpdate
+		{
+			get
+			{
+				return c.NextUpdate == null
+					?	null
+					:	new DateTimeObject(c.NextUpdate.ToDateTime());
+			}
+		}
+
+		private ISet LoadCrlEntries()
+		{
+			ISet entrySet = new HashSet();
+			IEnumerable certs = c.GetRevokedCertificateEnumeration();
+
+			X509Name previousCertificateIssuer = IssuerDN;
+			foreach (CrlEntry entry in certs)
+			{
+				X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer);
+				entrySet.Add(crlEntry);
+				previousCertificateIssuer = crlEntry.GetCertificateIssuer();
+			}
+
+			return entrySet;
+		}
+
+		public virtual X509CrlEntry GetRevokedCertificate(
+			BigInteger serialNumber)
+		{
+			IEnumerable certs = c.GetRevokedCertificateEnumeration();
+
+			X509Name previousCertificateIssuer = IssuerDN;
+			foreach (CrlEntry entry in certs)
+			{
+				X509CrlEntry crlEntry = new X509CrlEntry(entry, isIndirect, previousCertificateIssuer);
+
+				if (serialNumber.Equals(entry.UserCertificate.Value))
+				{
+					return crlEntry;
+				}
+
+				previousCertificateIssuer = crlEntry.GetCertificateIssuer();
+			}
+
+			return null;
+		}
+
+		public virtual ISet GetRevokedCertificates()
+		{
+			ISet entrySet = LoadCrlEntries();
+
+			if (entrySet.Count > 0)
+			{
+				return entrySet; // TODO? Collections.unmodifiableSet(entrySet);
+			}
+
+			return null;
+		}
+
+		public virtual byte[] GetTbsCertList()
+		{
+			try
+			{
+				return c.TbsCertList.GetDerEncoded();
+			}
+			catch (Exception e)
+			{
+				throw new CrlException(e.ToString());
+			}
+		}
+
+		public virtual byte[] GetSignature()
+		{
+			return c.Signature.GetBytes();
+		}
+
+		public virtual string SigAlgName
+		{
+			get { return sigAlgName; }
+		}
+
+		public virtual string SigAlgOid
+		{
+			get { return c.SignatureAlgorithm.ObjectID.Id; }
+		}
+
+		public virtual byte[] GetSigAlgParams()
+		{
+			return Arrays.Clone(sigAlgParams);
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			X509Crl other = obj as X509Crl;
+
+			if (other == null)
+				return false;
+
+			return c.Equals(other.c);
+
+			// NB: May prefer this implementation of Equals if more than one certificate implementation in play
+			//return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
+		}
+
+		public override int GetHashCode()
+		{
+			return c.GetHashCode();
+		}
+
+		/**
+		 * Returns a string representation of this CRL.
+		 *
+		 * @return a string representation of this CRL.
+		 */
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			string nl = Platform.NewLine;
+
+			buf.Append("              Version: ").Append(this.Version).Append(nl);
+			buf.Append("             IssuerDN: ").Append(this.IssuerDN).Append(nl);
+			buf.Append("          This update: ").Append(this.ThisUpdate).Append(nl);
+			buf.Append("          Next update: ").Append(this.NextUpdate).Append(nl);
+			buf.Append("  Signature Algorithm: ").Append(this.SigAlgName).Append(nl);
+
+			byte[] sig = this.GetSignature();
+
+			buf.Append("            Signature: ");
+			buf.Append(Hex.ToHexString(sig, 0, 20)).Append(nl);
+
+			for (int i = 20; i < sig.Length; i += 20)
+			{
+				int count = System.Math.Min(20, sig.Length - i);
+				buf.Append("                       ");
+				buf.Append(Hex.ToHexString(sig, i, count)).Append(nl);
+			}
+
+			X509Extensions extensions = c.TbsCertList.Extensions;
+
+			if (extensions != null)
+			{
+				IEnumerator e = extensions.ExtensionOids.GetEnumerator();
+
+				if (e.MoveNext())
+				{
+					buf.Append("           Extensions: ").Append(nl);
+				}
+
+				do
+				{
+					DerObjectIdentifier oid = (DerObjectIdentifier) e.Current;
+					X509Extension ext = extensions.GetExtension(oid);
+
+					if (ext.Value != null)
+					{
+						Asn1Object asn1Value = X509ExtensionUtilities.FromExtensionValue(ext.Value);
+
+						buf.Append("                       critical(").Append(ext.IsCritical).Append(") ");
+						try
+						{
+							if (oid.Equals(X509Extensions.CrlNumber))
+							{
+								buf.Append(new CrlNumber(DerInteger.GetInstance(asn1Value).PositiveValue)).Append(nl);
+							}
+							else if (oid.Equals(X509Extensions.DeltaCrlIndicator))
+							{
+								buf.Append(
+									"Base CRL: "
+									+ new CrlNumber(DerInteger.GetInstance(
+									asn1Value).PositiveValue))
+									.Append(nl);
+							}
+							else if (oid.Equals(X509Extensions.IssuingDistributionPoint))
+							{
+								buf.Append(IssuingDistributionPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
+							}
+							else if (oid.Equals(X509Extensions.CrlDistributionPoints))
+							{
+								buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
+							}
+							else if (oid.Equals(X509Extensions.FreshestCrl))
+							{
+								buf.Append(CrlDistPoint.GetInstance((Asn1Sequence) asn1Value)).Append(nl);
+							}
+							else
+							{
+								buf.Append(oid.Id);
+								buf.Append(" value = ").Append(
+									Asn1Dump.DumpAsString(asn1Value))
+									.Append(nl);
+							}
+						}
+						catch (Exception)
+						{
+							buf.Append(oid.Id);
+							buf.Append(" value = ").Append("*****").Append(nl);
+						}
+					}
+					else
+					{
+						buf.Append(nl);
+					}
+				}
+				while (e.MoveNext());
+			}
+
+			ISet certSet = GetRevokedCertificates();
+			if (certSet != null)
+			{
+				foreach (X509CrlEntry entry in certSet)
+				{
+					buf.Append(entry);
+					buf.Append(nl);
+				}
+			}
+
+			return buf.ToString();
+		}
+
+		/**
+		 * Checks whether the given certificate is on this CRL.
+		 *
+		 * @param cert the certificate to check for.
+		 * @return true if the given certificate is on this CRL,
+		 * false otherwise.
+		 */
+//		public bool IsRevoked(
+//			Certificate cert)
+//		{
+//			if (!cert.getType().Equals("X.509"))
+//			{
+//				throw new RuntimeException("X.509 CRL used with non X.509 Cert");
+//			}
+		public virtual bool IsRevoked(
+			X509Certificate cert)
+		{
+			CrlEntry[] certs = c.GetRevokedCertificates();
+
+			if (certs != null)
+			{
+//				BigInteger serial = ((X509Certificate)cert).SerialNumber;
+				BigInteger serial = cert.SerialNumber;
+
+				for (int i = 0; i < certs.Length; i++)
+				{
+					if (certs[i].UserCertificate.Value.Equals(serial))
+					{
+						return true;
+					}
+				}
+			}
+
+			return false;
+		}
+
+		protected virtual bool IsIndirectCrl
+		{
+			get
+			{
+				Asn1OctetString idp = GetExtensionValue(X509Extensions.IssuingDistributionPoint);
+				bool isIndirect = false;
+
+				try
+				{
+					if (idp != null)
+					{
+						isIndirect = IssuingDistributionPoint.GetInstance(
+							X509ExtensionUtilities.FromExtensionValue(idp)).IsIndirectCrl;
+					}
+				}
+				catch (Exception e)
+				{
+					// TODO
+//					throw new ExtCrlException("Exception reading IssuingDistributionPoint", e);
+					throw new CrlException("Exception reading IssuingDistributionPoint" + e);
+				}
+
+				return isIndirect;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509CrlEntry.cs b/BouncyCastle.AxCrypt/src/x509/X509CrlEntry.cs
new file mode 100644
index 0000000..caca294
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509CrlEntry.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * The following extensions are listed in RFC 2459 as relevant to CRL Entries
+	 *
+	 * ReasonCode Hode Instruction Code Invalidity Date Certificate Issuer
+	 * (critical)
+	 */
+	public class X509CrlEntry
+		: X509ExtensionBase
+	{
+		private CrlEntry	c;
+		private bool		isIndirect;
+		private X509Name	previousCertificateIssuer;
+		private X509Name	certificateIssuer;
+
+		public X509CrlEntry(
+			CrlEntry c)
+		{
+			this.c = c;
+			this.certificateIssuer = loadCertificateIssuer();
+		}
+
+		/**
+		* Constructor for CRLEntries of indirect CRLs. If <code>isIndirect</code>
+		* is <code>false</code> {@link #getCertificateIssuer()} will always
+		* return <code>null</code>, <code>previousCertificateIssuer</code> is
+		* ignored. If this <code>isIndirect</code> is specified and this CrlEntry
+		* has no certificate issuer CRL entry extension
+		* <code>previousCertificateIssuer</code> is returned by
+		* {@link #getCertificateIssuer()}.
+		*
+		* @param c
+		*            TbsCertificateList.CrlEntry object.
+		* @param isIndirect
+		*            <code>true</code> if the corresponding CRL is a indirect
+		*            CRL.
+		* @param previousCertificateIssuer
+		*            Certificate issuer of the previous CrlEntry.
+		*/
+		public X509CrlEntry(
+			CrlEntry		c,
+			bool			isIndirect,
+			X509Name		previousCertificateIssuer)
+		{
+			this.c = c;
+			this.isIndirect = isIndirect;
+			this.previousCertificateIssuer = previousCertificateIssuer;
+			this.certificateIssuer = loadCertificateIssuer();
+		}
+
+		private X509Name loadCertificateIssuer()
+		{
+			if (!isIndirect)
+			{
+				return null;
+			}
+
+			Asn1OctetString ext = GetExtensionValue(X509Extensions.CertificateIssuer);
+			if (ext == null)
+			{
+				return previousCertificateIssuer;
+			}
+
+			try
+			{
+				GeneralName[] names = GeneralNames.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(ext)).GetNames();
+
+				for (int i = 0; i < names.Length; i++)
+				{
+					if (names[i].TagNo == GeneralName.DirectoryName)
+					{
+						return X509Name.GetInstance(names[i].Name);
+					}
+				}
+			}
+			catch (Exception)
+			{
+			}
+
+			return null;
+		}
+
+		public X509Name GetCertificateIssuer()
+		{
+			return certificateIssuer;
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return c.Extensions;
+		}
+
+		public byte[] GetEncoded()
+		{
+			try
+			{
+				return c.GetDerEncoded();
+			}
+			catch (Exception e)
+			{
+				throw new CrlException(e.ToString());
+			}
+		}
+
+		public BigInteger SerialNumber
+		{
+			get { return c.UserCertificate.Value; }
+		}
+
+		public DateTime RevocationDate
+		{
+			get { return c.RevocationDate.ToDateTime(); }
+		}
+
+		public bool HasExtensions
+		{
+			get { return c.Extensions != null; }
+		}
+
+		public override string ToString()
+		{
+			StringBuilder buf = new StringBuilder();
+			string nl = Platform.NewLine;
+
+			buf.Append("        userCertificate: ").Append(this.SerialNumber).Append(nl);
+			buf.Append("         revocationDate: ").Append(this.RevocationDate).Append(nl);
+			buf.Append("      certificateIssuer: ").Append(this.GetCertificateIssuer()).Append(nl);
+
+			X509Extensions extensions = c.Extensions;
+
+			if (extensions != null)
+			{
+				IEnumerator e = extensions.ExtensionOids.GetEnumerator();
+				if (e.MoveNext())
+				{
+					buf.Append("   crlEntryExtensions:").Append(nl);
+
+					do
+					{
+						DerObjectIdentifier oid = (DerObjectIdentifier)e.Current;
+						X509Extension ext = extensions.GetExtension(oid);
+
+						if (ext.Value != null)
+						{
+							Asn1Object obj = Asn1Object.FromByteArray(ext.Value.GetOctets());
+
+							buf.Append("                       critical(")
+								.Append(ext.IsCritical)
+								.Append(") ");
+							try
+							{
+								if (oid.Equals(X509Extensions.ReasonCode))
+								{
+									buf.Append(new CrlReason(DerEnumerated.GetInstance(obj)));
+								}
+								else if (oid.Equals(X509Extensions.CertificateIssuer))
+								{
+									buf.Append("Certificate issuer: ").Append(
+										GeneralNames.GetInstance((Asn1Sequence)obj));
+								}
+								else 
+								{
+									buf.Append(oid.Id);
+									buf.Append(" value = ").Append(Asn1Dump.DumpAsString(obj));
+								}
+								buf.Append(nl);
+							}
+							catch (Exception)
+							{
+								buf.Append(oid.Id);
+								buf.Append(" value = ").Append("*****").Append(nl);
+							}
+						}
+						else
+						{
+							buf.Append(nl);
+						}
+					}
+					while (e.MoveNext());
+				}
+			}
+
+			return buf.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509CrlParser.cs b/BouncyCastle.AxCrypt/src/x509/X509CrlParser.cs
new file mode 100644
index 0000000..d830bb9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509CrlParser.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.X509
+{
+	public class X509CrlParser
+	{
+		private static readonly PemParser PemCrlParser = new PemParser("CRL");
+
+		private readonly bool lazyAsn1;
+
+		private Asn1Set	sCrlData;
+		private int		sCrlDataObjectCount;
+		private Stream	currentCrlStream;
+
+		public X509CrlParser()
+			: this(false)
+		{
+		}
+
+		public X509CrlParser(
+			bool lazyAsn1)
+		{
+			this.lazyAsn1 = lazyAsn1;
+		}
+
+		private X509Crl ReadPemCrl(
+			Stream inStream)
+		{
+			Asn1Sequence seq = PemCrlParser.ReadPemObject(inStream);
+
+			return seq == null
+				?	null
+				:	CreateX509Crl(CertificateList.GetInstance(seq));
+		}
+
+		private X509Crl ReadDerCrl(
+			Asn1InputStream dIn)
+		{
+			Asn1Sequence seq = (Asn1Sequence)dIn.ReadObject();
+
+			if (seq.Count > 1 && seq[0] is DerObjectIdentifier)
+			{
+				if (seq[0].Equals(PkcsObjectIdentifiers.SignedData))
+				{
+					sCrlData = SignedData.GetInstance(
+						Asn1Sequence.GetInstance((Asn1TaggedObject) seq[1], true)).Crls;
+
+					return GetCrl();
+				}
+			}
+
+			return CreateX509Crl(CertificateList.GetInstance(seq));
+		}
+
+		private X509Crl GetCrl()
+		{
+			if (sCrlData == null || sCrlDataObjectCount >= sCrlData.Count)
+			{
+				return null;
+			}
+
+			return CreateX509Crl(
+				CertificateList.GetInstance(
+					sCrlData[sCrlDataObjectCount++]));
+		}
+
+		protected virtual X509Crl CreateX509Crl(
+			CertificateList c)
+		{
+			return new X509Crl(c);
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public X509Crl ReadCrl(
+			byte[] input)
+		{
+			return ReadCrl(new MemoryStream(input, false));
+		}
+
+		/// <summary>
+		/// Create loading data from byte array.
+		/// </summary>
+		/// <param name="input"></param>
+		public ICollection ReadCrls(
+			byte[] input)
+		{
+			return ReadCrls(new MemoryStream(input, false));
+		}
+
+		/**
+		 * Generates a certificate revocation list (CRL) object and initializes
+		 * it with the data read from the input stream inStream.
+		 */
+		public X509Crl ReadCrl(
+			Stream inStream)
+		{
+			if (inStream == null)
+				throw new ArgumentNullException("inStream");
+			if (!inStream.CanRead)
+				throw new ArgumentException("inStream must be read-able", "inStream");
+
+			if (currentCrlStream == null)
+			{
+				currentCrlStream = inStream;
+				sCrlData = null;
+				sCrlDataObjectCount = 0;
+			}
+			else if (currentCrlStream != inStream) // reset if input stream has changed
+			{
+				currentCrlStream = inStream;
+				sCrlData = null;
+				sCrlDataObjectCount = 0;
+			}
+
+			try
+			{
+				if (sCrlData != null)
+				{
+					if (sCrlDataObjectCount != sCrlData.Count)
+					{
+						return GetCrl();
+					}
+
+					sCrlData = null;
+					sCrlDataObjectCount = 0;
+					return null;
+				}
+
+				PushbackStream pis = new PushbackStream(inStream);
+				int tag = pis.ReadByte();
+
+				if (tag < 0)
+					return null;
+
+				pis.Unread(tag);
+
+				if (tag != 0x30)	// assume ascii PEM encoded.
+				{
+					return ReadPemCrl(pis);
+				}
+
+				Asn1InputStream asn1 = lazyAsn1
+					?	new LazyAsn1InputStream(pis)
+					:	new Asn1InputStream(pis);
+
+				return ReadDerCrl(asn1);
+			}
+			catch (CrlException e)
+			{
+				throw e;
+			}
+			catch (Exception e)
+			{
+				throw new CrlException(e.ToString());
+			}
+		}
+
+		/**
+		 * Returns a (possibly empty) collection view of the CRLs read from
+		 * the given input stream inStream.
+		 *
+		 * The inStream may contain a sequence of DER-encoded CRLs, or
+		 * a PKCS#7 CRL set.  This is a PKCS#7 SignedData object, with the
+		 * only significant field being crls.  In particular the signature
+		 * and the contents are ignored.
+		 */
+		public ICollection ReadCrls(
+			Stream inStream)
+		{
+			X509Crl crl;
+			IList crls = Platform.CreateArrayList();
+
+			while ((crl = ReadCrl(inStream)) != null)
+			{
+				crls.Add(crl);
+			}
+
+			return crls;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509ExtensionBase.cs b/BouncyCastle.AxCrypt/src/x509/X509ExtensionBase.cs
new file mode 100644
index 0000000..aaf6695
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509ExtensionBase.cs
@@ -0,0 +1,82 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.X509
+{
+	public abstract class X509ExtensionBase
+		: IX509Extension
+	{
+		protected abstract X509Extensions GetX509Extensions();
+
+		protected virtual ISet GetExtensionOids(
+			bool critical)
+		{
+			X509Extensions extensions = GetX509Extensions();
+			if (extensions != null)
+			{
+				HashSet set = new HashSet();
+				foreach (DerObjectIdentifier oid in extensions.ExtensionOids)
+				{
+					X509Extension ext = extensions.GetExtension(oid);
+					if (ext.IsCritical == critical)
+					{
+						set.Add(oid.Id);
+					}
+				}
+
+				return set;
+			}
+
+			return null;
+		}
+
+		/// <summary>
+		/// Get non critical extensions.
+		/// </summary>
+		/// <returns>A set of non critical extension oids.</returns>
+		public virtual ISet GetNonCriticalExtensionOids()
+		{
+			return GetExtensionOids(false);
+		}
+
+		/// <summary>
+		/// Get any critical extensions.
+		/// </summary>
+		/// <returns>A sorted list of critical entension.</returns>
+		public virtual ISet GetCriticalExtensionOids()
+		{
+			return GetExtensionOids(true);
+		}
+
+		/// <summary>
+		/// Get the value of a given extension.
+		/// </summary>
+		/// <param name="oid">The object ID of the extension. </param>
+		/// <returns>An Asn1OctetString object if that extension is found or null if not.</returns>
+		[Obsolete("Use version taking a DerObjectIdentifier instead")]
+		public Asn1OctetString GetExtensionValue(
+			string oid)
+		{
+			return GetExtensionValue(new DerObjectIdentifier(oid));
+		}
+
+		public virtual Asn1OctetString GetExtensionValue(
+			DerObjectIdentifier oid)
+		{
+			X509Extensions exts = GetX509Extensions();
+			if (exts != null)
+			{
+				X509Extension ext = exts.GetExtension(oid);
+				if (ext != null)
+				{
+					return ext.Value;
+				}
+			}
+
+			return null;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509KeyUsage.cs b/BouncyCastle.AxCrypt/src/x509/X509KeyUsage.cs
new file mode 100644
index 0000000..e0a7b49
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509KeyUsage.cs
@@ -0,0 +1,59 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	 * A holding class for constructing an X509 Key Usage extension.
+	 *
+	 * <pre>
+	 *    id-ce-keyUsage OBJECT IDENTIFIER ::=  { id-ce 15 }
+	 *
+	 *    KeyUsage ::= BIT STRING {
+	 *         digitalSignature        (0),
+	 *         nonRepudiation          (1),
+	 *         keyEncipherment         (2),
+	 *         dataEncipherment        (3),
+	 *         keyAgreement            (4),
+	 *         keyCertSign             (5),
+	 *         cRLSign                 (6),
+	 *         encipherOnly            (7),
+	 *         decipherOnly            (8) }
+	 * </pre>
+	 */
+	public class X509KeyUsage
+		: Asn1Encodable
+	{
+		public const int DigitalSignature = 1 << 7;
+		public const int NonRepudiation   = 1 << 6;
+		public const int KeyEncipherment  = 1 << 5;
+		public const int DataEncipherment = 1 << 4;
+		public const int KeyAgreement     = 1 << 3;
+		public const int KeyCertSign      = 1 << 2;
+		public const int CrlSign          = 1 << 1;
+		public const int EncipherOnly     = 1 << 0;
+		public const int DecipherOnly     = 1 << 15;
+
+		private readonly int usage;
+
+		/**
+		 * Basic constructor.
+		 *
+		 * @param usage - the bitwise OR of the Key Usage flags giving the
+		 * allowed uses for the key.
+		 * e.g. (X509KeyUsage.keyEncipherment | X509KeyUsage.dataEncipherment)
+		 */
+		public X509KeyUsage(
+			int usage)
+		{
+			this.usage = usage;
+		}
+
+		public override Asn1Object ToAsn1Object()
+		{
+			return new KeyUsage(usage);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509SignatureUtil.cs b/BouncyCastle.AxCrypt/src/x509/X509SignatureUtil.cs
new file mode 100644
index 0000000..7a4ab14
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509SignatureUtil.cs
@@ -0,0 +1,128 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+
+namespace Org.BouncyCastle.X509
+{
+	internal class X509SignatureUtilities
+	{
+		private static readonly Asn1Null derNull = DerNull.Instance;
+
+		internal static void SetSignatureParameters(
+			ISigner			signature,
+			Asn1Encodable	parameters)
+		{
+			if (parameters != null && !derNull.Equals(parameters))
+			{
+				// TODO Put back in
+//				AlgorithmParameters sigParams = AlgorithmParameters.GetInstance(signature.getAlgorithm());
+//
+//				try
+//				{
+//					sigParams.Init(parameters.ToAsn1Object().GetDerEncoded());
+//				}
+//				catch (IOException e)
+//				{
+//					throw new SignatureException("IOException decoding parameters: " + e.Message);
+//				}
+//
+//				if (signature.getAlgorithm().EndsWith("MGF1"))
+//				{
+//					try
+//					{
+//						signature.setParameter(sigParams.getParameterSpec(PSSParameterSpec.class));
+//					}
+//					catch (GeneralSecurityException e)
+//					{
+//						throw new SignatureException("Exception extracting parameters: " + e.Message);
+//					}
+//				}
+			}
+		}
+
+		internal static string GetSignatureName(
+			AlgorithmIdentifier sigAlgId)
+		{
+			Asn1Encodable parameters = sigAlgId.Parameters;
+
+			if (parameters != null && !derNull.Equals(parameters))
+			{
+				if (sigAlgId.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+				{
+					RsassaPssParameters rsaParams = RsassaPssParameters.GetInstance(parameters);
+
+					return GetDigestAlgName(rsaParams.HashAlgorithm.ObjectID) + "withRSAandMGF1";
+				}
+				if (sigAlgId.ObjectID.Equals(X9ObjectIdentifiers.ECDsaWithSha2))
+				{
+					Asn1Sequence ecDsaParams = Asn1Sequence.GetInstance(parameters);
+
+					return GetDigestAlgName((DerObjectIdentifier)ecDsaParams[0]) + "withECDSA";
+				}
+			}
+
+			return sigAlgId.ObjectID.Id;
+		}
+
+		/**
+		 * Return the digest algorithm using one of the standard JCA string
+		 * representations rather than the algorithm identifier (if possible).
+		 */
+		private static string GetDigestAlgName(
+			DerObjectIdentifier digestAlgOID)
+		{
+			if (PkcsObjectIdentifiers.MD5.Equals(digestAlgOID))
+			{
+				return "MD5";
+			}
+			else if (OiwObjectIdentifiers.IdSha1.Equals(digestAlgOID))
+			{
+				return "SHA1";
+			}
+			else if (NistObjectIdentifiers.IdSha224.Equals(digestAlgOID))
+			{
+				return "SHA224";
+			}
+			else if (NistObjectIdentifiers.IdSha256.Equals(digestAlgOID))
+			{
+				return "SHA256";
+			}
+			else if (NistObjectIdentifiers.IdSha384.Equals(digestAlgOID))
+			{
+				return "SHA384";
+			}
+			else if (NistObjectIdentifiers.IdSha512.Equals(digestAlgOID))
+			{
+				return "SHA512";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD128.Equals(digestAlgOID))
+			{
+				return "RIPEMD128";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD160.Equals(digestAlgOID))
+			{
+				return "RIPEMD160";
+			}
+			else if (TeleTrusTObjectIdentifiers.RipeMD256.Equals(digestAlgOID))
+			{
+				return "RIPEMD256";
+			}
+			else if (CryptoProObjectIdentifiers.GostR3411.Equals(digestAlgOID))
+			{
+				return "GOST3411";
+			}
+			else
+			{
+				return digestAlgOID.Id;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509Utilities.cs b/BouncyCastle.AxCrypt/src/x509/X509Utilities.cs
new file mode 100644
index 0000000..52a122c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509Utilities.cs
@@ -0,0 +1,187 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.X509
+{
+	internal class X509Utilities
+	{
+        private static readonly IDictionary algorithms = Platform.CreateHashtable();
+        private static readonly IDictionary exParams = Platform.CreateHashtable();
+		private static readonly ISet        noParams = new HashSet();
+
+		static X509Utilities()
+		{
+			algorithms.Add("MD2WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD2WITHRSA", PkcsObjectIdentifiers.MD2WithRsaEncryption);
+			algorithms.Add("MD5WITHRSAENCRYPTION", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("MD5WITHRSA", PkcsObjectIdentifiers.MD5WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSA", PkcsObjectIdentifiers.Sha1WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA224WITHRSA", PkcsObjectIdentifiers.Sha224WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA256WITHRSA", PkcsObjectIdentifiers.Sha256WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA384WITHRSA", PkcsObjectIdentifiers.Sha384WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSAENCRYPTION", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA512WITHRSA", PkcsObjectIdentifiers.Sha512WithRsaEncryption);
+			algorithms.Add("SHA1WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA224WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA256WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA384WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("SHA512WITHRSAANDMGF1", PkcsObjectIdentifiers.IdRsassaPss);
+			algorithms.Add("RIPEMD160WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD160WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD160);
+			algorithms.Add("RIPEMD128WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD128WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD128);
+			algorithms.Add("RIPEMD256WITHRSAENCRYPTION", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("RIPEMD256WITHRSA", TeleTrusTObjectIdentifiers.RsaSignatureWithRipeMD256);
+			algorithms.Add("SHA1WITHDSA", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("DSAWITHSHA1", X9ObjectIdentifiers.IdDsaWithSha1);
+			algorithms.Add("SHA224WITHDSA", NistObjectIdentifiers.DsaWithSha224);
+			algorithms.Add("SHA256WITHDSA", NistObjectIdentifiers.DsaWithSha256);
+			algorithms.Add("SHA384WITHDSA", NistObjectIdentifiers.DsaWithSha384);
+			algorithms.Add("SHA512WITHDSA", NistObjectIdentifiers.DsaWithSha512);
+			algorithms.Add("SHA1WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("ECDSAWITHSHA1", X9ObjectIdentifiers.ECDsaWithSha1);
+			algorithms.Add("SHA224WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+			algorithms.Add("SHA256WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+			algorithms.Add("SHA384WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+			algorithms.Add("SHA512WITHECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+			algorithms.Add("GOST3411WITHGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3411WITHGOST3410-94", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			algorithms.Add("GOST3411WITHECGOST3410", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+			algorithms.Add("GOST3411WITHECGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+			algorithms.Add("GOST3411WITHGOST3410-2001", CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+			//
+			// According to RFC 3279, the ASN.1 encoding SHALL (id-dsa-with-sha1) or MUST (ecdsa-with-SHA*) omit the parameters field.
+			// The parameters field SHALL be NULL for RSA based signature algorithms.
+			//
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha1);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha224);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha256);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha384);
+			noParams.Add(X9ObjectIdentifiers.ECDsaWithSha512);
+			noParams.Add(X9ObjectIdentifiers.IdDsaWithSha1);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha224);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha256);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha384);
+			noParams.Add(NistObjectIdentifiers.DsaWithSha512);
+
+			//
+			// RFC 4491
+			//
+			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x94);
+			noParams.Add(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001);
+
+			//
+			// explicit params
+			//
+			AlgorithmIdentifier sha1AlgId = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+			exParams.Add("SHA1WITHRSAANDMGF1", CreatePssParams(sha1AlgId, 20));
+
+			AlgorithmIdentifier sha224AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance);
+			exParams.Add("SHA224WITHRSAANDMGF1", CreatePssParams(sha224AlgId, 28));
+
+			AlgorithmIdentifier sha256AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance);
+			exParams.Add("SHA256WITHRSAANDMGF1", CreatePssParams(sha256AlgId, 32));
+
+			AlgorithmIdentifier sha384AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance);
+			exParams.Add("SHA384WITHRSAANDMGF1", CreatePssParams(sha384AlgId, 48));
+
+			AlgorithmIdentifier sha512AlgId = new AlgorithmIdentifier(NistObjectIdentifiers.IdSha512, DerNull.Instance);
+			exParams.Add("SHA512WITHRSAANDMGF1", CreatePssParams(sha512AlgId, 64));
+		}
+
+		private static RsassaPssParameters CreatePssParams(
+			AlgorithmIdentifier	hashAlgId,
+			int					saltSize)
+		{
+			return new RsassaPssParameters(
+				hashAlgId,
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, hashAlgId),
+				new DerInteger(saltSize),
+				new DerInteger(1));
+		}
+
+		internal static DerObjectIdentifier GetAlgorithmOid(
+			string algorithmName)
+		{
+			algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+            if (algorithms.Contains(algorithmName))
+			{
+				return (DerObjectIdentifier) algorithms[algorithmName];
+			}
+
+			return new DerObjectIdentifier(algorithmName);
+		}
+
+		internal static AlgorithmIdentifier GetSigAlgID(
+			DerObjectIdentifier sigOid,
+			string				algorithmName)
+		{
+			if (noParams.Contains(sigOid))
+			{
+				return new AlgorithmIdentifier(sigOid);
+			}
+
+            algorithmName = Platform.ToUpperInvariant(algorithmName);
+
+			if (exParams.Contains(algorithmName))
+			{
+				return new AlgorithmIdentifier(sigOid, (Asn1Encodable) exParams[algorithmName]);
+			}
+
+			return new AlgorithmIdentifier(sigOid, DerNull.Instance);
+		}
+
+		internal static IEnumerable GetAlgNames()
+		{
+			return new EnumerableProxy(algorithms.Keys);
+		}
+
+		internal static byte[] GetSignatureForObject(
+			DerObjectIdentifier		sigOid, // TODO Redundant now?
+			string					sigName,
+			AsymmetricKeyParameter	privateKey,
+			SecureRandom			random,
+			Asn1Encodable			ae)
+		{
+			if (sigOid == null)
+				throw new ArgumentNullException("sigOid");
+
+			ISigner sig = SignerUtilities.GetSigner(sigName);
+
+			if (random != null)
+			{
+				sig.Init(true, new ParametersWithRandom(privateKey, random));
+			}
+			else
+			{
+				sig.Init(true, privateKey);
+			}
+
+			byte[] encoded = ae.GetDerEncoded();
+			sig.BlockUpdate(encoded, 0, encoded.Length);
+
+			return sig.GenerateSignature();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509V1CertificateGenerator.cs b/BouncyCastle.AxCrypt/src/x509/X509V1CertificateGenerator.cs
new file mode 100644
index 0000000..02b58a1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509V1CertificateGenerator.cs
@@ -0,0 +1,205 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <summary>
+	/// Class to Generate X509V1 Certificates.
+	/// </summary>
+	public class X509V1CertificateGenerator
+	{
+		private V1TbsCertificateGenerator   tbsGen;
+		private DerObjectIdentifier         sigOID;
+		private AlgorithmIdentifier         sigAlgId;
+		private string                      signatureAlgorithm;
+
+		/// <summary>
+		/// Default Constructor.
+		/// </summary>
+		public X509V1CertificateGenerator()
+		{
+			tbsGen = new V1TbsCertificateGenerator();
+		}
+
+		/// <summary>
+		/// Reset the generator.
+		/// </summary>
+		public void Reset()
+		{
+			tbsGen = new V1TbsCertificateGenerator();
+		}
+
+		/// <summary>
+		/// Set the certificate's serial number.
+		/// </summary>
+		/// <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+		/// You will be surprised how ugly a serial number collision can get.</remarks>
+		/// <param name="serialNumber">The serial number.</param>
+		public void SetSerialNumber(
+			BigInteger serialNumber)
+		{
+			if (serialNumber.SignValue <= 0)
+			{
+				throw new ArgumentException("serial number must be a positive integer", "serialNumber");
+			}
+
+			tbsGen.SetSerialNumber(new DerInteger(serialNumber));
+		}
+
+		/// <summary>
+		/// Set the issuer distinguished name.
+		/// The issuer is the entity whose private key is used to sign the certificate.
+		/// </summary>
+		/// <param name="issuer">The issuers DN.</param>
+		public void SetIssuerDN(
+			X509Name issuer)
+		{
+			tbsGen.SetIssuer(issuer);
+		}
+
+		/// <summary>
+		/// Set the date that this certificate is to be valid from.
+		/// </summary>
+		/// <param name="date"/>
+		public void SetNotBefore(
+			DateTime date)
+		{
+			tbsGen.SetStartDate(new Time(date));
+		}
+
+		/// <summary>
+		/// Set the date after which this certificate will no longer be valid.
+		/// </summary>
+		/// <param name="date"/>
+		public void SetNotAfter(
+			DateTime date)
+		{
+			tbsGen.SetEndDate(new Time(date));
+		}
+
+		/// <summary>
+		/// Set the subject distinguished name.
+		/// The subject describes the entity associated with the public key.
+		/// </summary>
+		/// <param name="subject"/>
+		public void SetSubjectDN(
+			X509Name subject)
+		{
+			tbsGen.SetSubject(subject);
+		}
+
+        /// <summary>
+        /// Set the public key that this certificate identifies.
+        /// </summary>
+        /// <param name="publicKey"/>
+		public void SetPublicKey(
+			AsymmetricKeyParameter publicKey)
+		{
+			try
+			{
+				tbsGen.SetSubjectPublicKeyInfo(
+					SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey));
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("unable to process key - " + e.ToString());
+			}
+		}
+
+		/// <summary>
+		/// Set the signature algorithm that will be used to sign this certificate.
+		/// This can be either a name or an OID, names are treated as case insensitive.
+		/// </summary>
+		/// <param name="signatureAlgorithm">string representation of the algorithm name</param>
+		public void SetSignatureAlgorithm(
+			string signatureAlgorithm)
+		{
+			this.signatureAlgorithm = signatureAlgorithm;
+
+			try
+			{
+				sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
+			}
+			catch (Exception)
+			{
+				throw new ArgumentException("Unknown signature type requested", "signatureAlgorithm");
+			}
+
+			sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
+
+			tbsGen.SetSignature(sigAlgId);
+		}
+
+		/// <summary>
+		/// Generate a new X509Certificate.
+		/// </summary>
+		/// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+		/// <returns>An X509Certificate.</returns>
+		public X509Certificate Generate(
+			AsymmetricKeyParameter privateKey)
+		{
+			return Generate(privateKey, null);
+		}
+
+        /// <summary>
+        /// Generate a new X509Certificate specifying a SecureRandom instance that you would like to use.
+        /// </summary>
+        /// <param name="privateKey">The private key of the issuer used to sign this certificate.</param>
+        /// <param name="random">The Secure Random you want to use.</param>
+        /// <returns>An X509Certificate.</returns>
+		public X509Certificate Generate(
+			AsymmetricKeyParameter	privateKey,
+			SecureRandom			random)
+		{
+			TbsCertificateStructure tbsCert = tbsGen.GenerateTbsCertificate();
+			byte[] signature;
+
+			try
+			{
+				signature = X509Utilities.GetSignatureForObject(
+					sigOID, signatureAlgorithm, privateKey, random, tbsCert);
+			}
+			catch (Exception e)
+			{
+				// TODO
+//				throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
+				throw new CertificateEncodingException("exception encoding TBS cert", e);
+			}
+
+			try
+			{
+				return GenerateJcaObject(tbsCert, signature);
+			}
+			catch (CertificateParsingException e)
+			{
+				// TODO
+				// throw new ExtCertificateEncodingException("exception producing certificate object", e);
+				throw new CertificateEncodingException("exception producing certificate object", e);
+			}
+		}
+
+		private X509Certificate GenerateJcaObject(
+			TbsCertificateStructure	tbsCert,
+			byte[]					signature)
+		{
+			return new X509Certificate(
+				new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
+		}
+
+		/// <summary>
+		/// Allows enumeration of the signature names supported by the generator.
+		/// </summary>
+		public IEnumerable SignatureAlgNames
+		{
+			get { return X509Utilities.GetAlgNames(); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificate.cs b/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificate.cs
new file mode 100644
index 0000000..117ac4c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificate.cs
@@ -0,0 +1,255 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <summary>An implementation of a version 2 X.509 Attribute Certificate.</summary>
+	public class X509V2AttributeCertificate
+		: X509ExtensionBase, IX509AttributeCertificate
+	{
+		private readonly AttributeCertificate cert;
+		private readonly DateTime notBefore;
+		private readonly DateTime notAfter;
+
+		private static AttributeCertificate GetObject(Stream input)
+		{
+			try
+			{
+				return AttributeCertificate.GetInstance(Asn1Object.FromStream(input));
+			}
+			catch (IOException e)
+			{
+				throw e;
+			}
+			catch (Exception e)
+			{
+				throw new IOException("exception decoding certificate structure", e);
+			}
+		}
+
+		public X509V2AttributeCertificate(
+			Stream encIn)
+			: this(GetObject(encIn))
+		{
+		}
+
+		public X509V2AttributeCertificate(
+			byte[] encoded)
+			: this(new MemoryStream(encoded, false))
+		{
+		}
+
+		internal X509V2AttributeCertificate(
+			AttributeCertificate cert)
+		{
+			this.cert = cert;
+
+			try
+			{
+				this.notAfter = cert.ACInfo.AttrCertValidityPeriod.NotAfterTime.ToDateTime();
+				this.notBefore = cert.ACInfo.AttrCertValidityPeriod.NotBeforeTime.ToDateTime();
+			}
+			catch (Exception e)
+			{
+				throw new IOException("invalid data structure in certificate!", e);
+			}
+		}
+
+		public virtual int Version
+		{
+			get { return cert.ACInfo.Version.Value.IntValue + 1; }
+		}
+
+		public virtual BigInteger SerialNumber
+		{
+			get { return cert.ACInfo.SerialNumber.Value; }
+		}
+
+		public virtual AttributeCertificateHolder Holder
+		{
+			get
+			{
+				return new AttributeCertificateHolder((Asn1Sequence)cert.ACInfo.Holder.ToAsn1Object());
+			}
+		}
+
+		public virtual AttributeCertificateIssuer Issuer
+		{
+			get
+			{
+				return new AttributeCertificateIssuer(cert.ACInfo.Issuer);
+			}
+		}
+
+		public virtual DateTime NotBefore
+		{
+			get { return notBefore; }
+		}
+
+		public virtual DateTime NotAfter
+		{
+			get { return notAfter; }
+		}
+
+		public virtual bool[] GetIssuerUniqueID()
+		{
+			DerBitString id = cert.ACInfo.IssuerUniqueID;
+
+			if (id != null)
+			{
+				byte[] bytes = id.GetBytes();
+				bool[] boolId = new bool[bytes.Length * 8 - id.PadBits];
+
+				for (int i = 0; i != boolId.Length; i++)
+				{
+					//boolId[i] = (bytes[i / 8] & (0x80 >>> (i % 8))) != 0;
+					boolId[i] = (bytes[i / 8] & (0x80 >> (i % 8))) != 0;
+				}
+
+				return boolId;
+			}
+
+			return null;
+		}
+
+		public virtual bool IsValidNow
+		{
+			get { return IsValid(DateTime.UtcNow); }
+		}
+
+		public virtual bool IsValid(
+			DateTime date)
+		{
+			return date.CompareTo(NotBefore) >= 0 && date.CompareTo(NotAfter) <= 0;
+		}
+
+		public virtual void CheckValidity()
+		{
+			this.CheckValidity(DateTime.UtcNow);
+		}
+
+		public virtual void CheckValidity(
+			DateTime date)
+		{
+			if (date.CompareTo(NotAfter) > 0)
+				throw new CertificateExpiredException("certificate expired on " + NotAfter);
+			if (date.CompareTo(NotBefore) < 0)
+				throw new CertificateNotYetValidException("certificate not valid until " + NotBefore);
+		}
+
+		public virtual byte[] GetSignature()
+		{
+			return cert.SignatureValue.GetBytes();
+		}
+
+		public virtual void Verify(
+			AsymmetricKeyParameter publicKey)
+		{
+			if (!cert.SignatureAlgorithm.Equals(cert.ACInfo.Signature))
+			{
+				throw new CertificateException("Signature algorithm in certificate info not same as outer certificate");
+			}
+
+			ISigner signature = SignerUtilities.GetSigner(cert.SignatureAlgorithm.ObjectID.Id);
+
+			signature.Init(false, publicKey);
+
+			try
+			{
+				byte[] b = cert.ACInfo.GetEncoded();
+				signature.BlockUpdate(b, 0, b.Length);
+			}
+			catch (IOException e)
+			{
+				throw new SignatureException("Exception encoding certificate info object", e);
+			}
+
+			if (!signature.VerifySignature(this.GetSignature()))
+			{
+				throw new InvalidKeyException("Public key presented not for certificate signature");
+			}
+		}
+
+		public virtual byte[] GetEncoded()
+		{
+			return cert.GetEncoded();
+		}
+
+		protected override X509Extensions GetX509Extensions()
+		{
+			return cert.ACInfo.Extensions;
+		}
+
+		public virtual X509Attribute[] GetAttributes()
+		{
+			Asn1Sequence seq = cert.ACInfo.Attributes;
+			X509Attribute[] attrs = new X509Attribute[seq.Count];
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				attrs[i] = new X509Attribute((Asn1Encodable)seq[i]);
+			}
+
+			return attrs;
+		}
+
+		public virtual X509Attribute[] GetAttributes(
+			string oid)
+		{
+			Asn1Sequence seq = cert.ACInfo.Attributes;
+			IList list = Platform.CreateArrayList();
+
+			for (int i = 0; i != seq.Count; i++)
+			{
+				X509Attribute attr = new X509Attribute((Asn1Encodable)seq[i]);
+				if (attr.Oid.Equals(oid))
+				{
+					list.Add(attr);
+				}
+			}
+
+			if (list.Count < 1)
+			{
+				return null;
+			}
+
+            X509Attribute[] result = new X509Attribute[list.Count];
+            for (int i = 0; i < list.Count; ++i)
+            {
+                result[i] = (X509Attribute)list[i];
+            }
+            return result;
+		}
+
+		public override bool Equals(
+			object obj)
+		{
+			if (obj == this)
+				return true;
+
+			X509V2AttributeCertificate other = obj as X509V2AttributeCertificate;
+
+			if (other == null)
+				return false;
+
+			return cert.Equals(other.cert);
+
+			// NB: May prefer this implementation of Equals if more than one certificate implementation in play
+			//return Arrays.AreEqual(this.GetEncoded(), other.GetEncoded());
+		}
+
+		public override int GetHashCode()
+		{
+			return cert.GetHashCode();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificateGenerator.cs b/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificateGenerator.cs
new file mode 100644
index 0000000..a683d5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509V2AttributeCertificateGenerator.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509
+{
+	/// <remarks>Class to produce an X.509 Version 2 AttributeCertificate.</remarks>
+	public class X509V2AttributeCertificateGenerator
+	{
+		private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
+
+		private V2AttributeCertificateInfoGenerator	acInfoGen;
+		private DerObjectIdentifier sigOID;
+		private AlgorithmIdentifier sigAlgId;
+		private string signatureAlgorithm;
+
+		public X509V2AttributeCertificateGenerator()
+		{
+			acInfoGen = new V2AttributeCertificateInfoGenerator();
+		}
+
+		/// <summary>Reset the generator</summary>
+		public void Reset()
+		{
+			acInfoGen = new V2AttributeCertificateInfoGenerator();
+			extGenerator.Reset();
+		}
+
+		/// <summary>Set the Holder of this Attribute Certificate.</summary>
+		public void SetHolder(
+			AttributeCertificateHolder holder)
+		{
+			acInfoGen.SetHolder(holder.holder);
+		}
+
+		/// <summary>Set the issuer.</summary>
+		public void SetIssuer(
+			AttributeCertificateIssuer issuer)
+		{
+			acInfoGen.SetIssuer(AttCertIssuer.GetInstance(issuer.form));
+		}
+
+		/// <summary>Set the serial number for the certificate.</summary>
+		public void SetSerialNumber(
+			BigInteger serialNumber)
+		{
+			acInfoGen.SetSerialNumber(new DerInteger(serialNumber));
+		}
+
+		public void SetNotBefore(
+			DateTime date)
+		{
+			acInfoGen.SetStartDate(new DerGeneralizedTime(date));
+		}
+
+		public void SetNotAfter(
+			DateTime date)
+		{
+			acInfoGen.SetEndDate(new DerGeneralizedTime(date));
+		}
+
+		/// <summary>
+		/// Set the signature algorithm. This can be either a name or an OID, names
+		/// are treated as case insensitive.
+		/// </summary>
+		/// <param name="signatureAlgorithm">The algorithm name.</param>
+		public void SetSignatureAlgorithm(
+			string signatureAlgorithm)
+		{
+			this.signatureAlgorithm = signatureAlgorithm;
+
+			try
+			{
+				sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
+			}
+			catch (Exception)
+			{
+				throw new ArgumentException("Unknown signature type requested");
+			}
+
+			sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
+
+			acInfoGen.SetSignature(sigAlgId);
+		}
+
+		/// <summary>Add an attribute.</summary>
+		public void AddAttribute(
+			X509Attribute attribute)
+		{
+			acInfoGen.AddAttribute(AttributeX509.GetInstance(attribute.ToAsn1Object()));
+		}
+
+		public void SetIssuerUniqueId(
+			bool[] iui)
+		{
+			// TODO convert bool array to bit string
+			//acInfoGen.SetIssuerUniqueID(iui);
+			throw Platform.CreateNotImplementedException("SetIssuerUniqueId()");
+		}
+
+		/// <summary>Add a given extension field for the standard extensions tag.</summary>
+		public void AddExtension(
+			string			oid,
+			bool			critical,
+			Asn1Encodable	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
+		}
+
+		/// <summary>
+		/// Add a given extension field for the standard extensions tag.
+		/// The value parameter becomes the contents of the octet string associated
+		/// with the extension.
+		/// </summary>
+		public void AddExtension(
+			string	oid,
+			bool	critical,
+			byte[]	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
+		}
+
+		/// <summary>
+		/// Generate an X509 certificate, based on the current issuer and subject.
+		/// </summary>
+		public IX509AttributeCertificate Generate(
+			AsymmetricKeyParameter publicKey)
+		{
+			return Generate(publicKey, null);
+		}
+
+		/// <summary>
+		/// Generate an X509 certificate, based on the current issuer and subject,
+		/// using the supplied source of randomness, if required.
+		/// </summary>
+		public IX509AttributeCertificate Generate(
+			AsymmetricKeyParameter	publicKey,
+			SecureRandom			random)
+		{
+			if (!extGenerator.IsEmpty)
+			{
+				acInfoGen.SetExtensions(extGenerator.Generate());
+			}
+
+			AttributeCertificateInfo acInfo = acInfoGen.GenerateAttributeCertificateInfo();
+
+			Asn1EncodableVector v = new Asn1EncodableVector();
+
+			v.Add(acInfo, sigAlgId);
+
+			try
+			{
+				v.Add(new DerBitString(X509Utilities.GetSignatureForObject(sigOID, signatureAlgorithm, publicKey, random, acInfo)));
+
+				return new X509V2AttributeCertificate(AttributeCertificate.GetInstance(new DerSequence(v)));
+			}
+			catch (Exception e)
+			{
+				// TODO
+//				throw new ExtCertificateEncodingException("constructed invalid certificate", e);
+				throw new CertificateEncodingException("constructed invalid certificate", e);
+			}
+		}
+
+		/// <summary>
+		/// Allows enumeration of the signature names supported by the generator.
+		/// </summary>
+		public IEnumerable SignatureAlgNames
+		{
+			get { return X509Utilities.GetAlgNames(); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509V2CRLGenerator.cs b/BouncyCastle.AxCrypt/src/x509/X509V2CRLGenerator.cs
new file mode 100644
index 0000000..a2293b3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509V2CRLGenerator.cs
@@ -0,0 +1,261 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.X509
+{
+	/**
+	* class to produce an X.509 Version 2 CRL.
+	*/
+	public class X509V2CrlGenerator
+	{
+		private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
+
+		private V2TbsCertListGenerator	tbsGen;
+		private DerObjectIdentifier		sigOID;
+		private AlgorithmIdentifier		sigAlgId;
+		private string					signatureAlgorithm;
+
+		public X509V2CrlGenerator()
+		{
+			tbsGen = new V2TbsCertListGenerator();
+		}
+
+		/**
+		* reset the generator
+		*/
+		public void Reset()
+		{
+			tbsGen = new V2TbsCertListGenerator();
+			extGenerator.Reset();
+		}
+
+		/**
+		* Set the issuer distinguished name - the issuer is the entity whose private key is used to sign the
+		* certificate.
+		*/
+		public void SetIssuerDN(
+			X509Name issuer)
+		{
+			tbsGen.SetIssuer(issuer);
+		}
+
+		public void SetThisUpdate(
+			DateTime date)
+		{
+			tbsGen.SetThisUpdate(new Time(date));
+		}
+
+		public void SetNextUpdate(
+			DateTime date)
+		{
+			tbsGen.SetNextUpdate(new Time(date));
+		}
+
+		/**
+		* Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+		* or 0 if CrlReason is not to be used
+		**/
+		public void AddCrlEntry(
+			BigInteger	userCertificate,
+			DateTime	revocationDate,
+			int			reason)
+		{
+			tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason);
+		}
+
+		/**
+		* Add a CRL entry with an Invalidity Date extension as well as a CrlReason extension.
+		* Reason being as indicated by CrlReason, i.e. CrlReason.KeyCompromise
+		* or 0 if CrlReason is not to be used
+		**/
+		public void AddCrlEntry(
+			BigInteger	userCertificate,
+			DateTime	revocationDate,
+			int			reason,
+			DateTime	invalidityDate)
+		{
+			tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), reason, new DerGeneralizedTime(invalidityDate));
+		}
+
+		/**
+		* Add a CRL entry with extensions.
+		**/
+		public void AddCrlEntry(
+			BigInteger		userCertificate,
+			DateTime		revocationDate,
+			X509Extensions	extensions)
+		{
+			tbsGen.AddCrlEntry(new DerInteger(userCertificate), new Time(revocationDate), extensions);
+		}
+
+		/**
+		* Add the CRLEntry objects contained in a previous CRL.
+		*
+		* @param other the X509Crl to source the other entries from.
+		*/
+		public void AddCrl(
+			X509Crl other)
+		{
+			if (other == null)
+				throw new ArgumentNullException("other");
+
+			ISet revocations = other.GetRevokedCertificates();
+
+			if (revocations != null)
+			{
+				foreach (X509CrlEntry entry in revocations)
+				{
+					try
+					{
+						tbsGen.AddCrlEntry(
+							Asn1Sequence.GetInstance(
+							Asn1Object.FromByteArray(entry.GetEncoded())));
+					}
+					catch (IOException e)
+					{
+						throw new CrlException("exception processing encoding of CRL", e);
+					}
+				}
+			}
+		}
+
+		/**
+		* Set the signature algorithm. This can be either a name or an oid, names
+		* are treated as case insensitive.
+		*
+		* @param signatureAlgorithm string representation of the algorithm name.
+		*/
+		public void SetSignatureAlgorithm(
+			string signatureAlgorithm)
+		{
+			this.signatureAlgorithm = signatureAlgorithm;
+
+			try
+			{
+				sigOID = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
+			}
+			catch (Exception e)
+			{
+				throw new ArgumentException("Unknown signature type requested", e);
+			}
+
+			sigAlgId = X509Utilities.GetSigAlgID(sigOID, signatureAlgorithm);
+
+			tbsGen.SetSignature(sigAlgId);
+		}
+
+		/**
+		* add a given extension field for the standard extensions tag (tag 0)
+		*/
+		public void AddExtension(
+			string			oid,
+			bool			critical,
+			Asn1Encodable	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
+		}
+
+		/**
+		* add a given extension field for the standard extensions tag (tag 0)
+		*/
+		public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			Asn1Encodable		extensionValue)
+		{
+			extGenerator.AddExtension(oid, critical, extensionValue);
+		}
+
+		/**
+		* add a given extension field for the standard extensions tag (tag 0)
+		*/
+		public void AddExtension(
+			string	oid,
+			bool	critical,
+			byte[]	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue));
+		}
+
+		/**
+		* add a given extension field for the standard extensions tag (tag 0)
+		*/
+		public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			byte[]				extensionValue)
+		{
+			extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue));
+		}
+
+		/// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+		/// <param name="privateKey">The key used for signing.</param>
+		public X509Crl Generate(
+			AsymmetricKeyParameter privateKey)
+		{
+			return Generate(privateKey, null);
+		}
+
+		/// <summary>Generate an X509 CRL, based on the current issuer and subject.</summary>
+		/// <param name="privateKey">The key used for signing.</param>
+		/// <param name="random">A user-defined source of randomness.</param>
+		public X509Crl Generate(
+			AsymmetricKeyParameter	privateKey,
+			SecureRandom			random)
+		{
+			TbsCertificateList tbsCrl = GenerateCertList();
+			byte[] signature;
+
+			try
+			{
+				signature = X509Utilities.GetSignatureForObject(
+					sigOID, signatureAlgorithm, privateKey, random, tbsCrl);
+			}
+			catch (IOException e)
+			{
+				// TODO
+//				throw new ExtCrlException("cannot generate CRL encoding", e);
+				throw new CrlException("cannot generate CRL encoding", e);
+			}
+
+			return GenerateJcaObject(tbsCrl, signature);
+		}
+
+		private TbsCertificateList GenerateCertList()
+		{
+			if (!extGenerator.IsEmpty)
+			{
+				tbsGen.SetExtensions(extGenerator.Generate());
+			}
+
+			return tbsGen.GenerateTbsCertList();
+		}
+
+		private X509Crl GenerateJcaObject(
+			TbsCertificateList	tbsCrl,
+			byte[]				signature)
+		{
+			return new X509Crl(
+				CertificateList.GetInstance(
+					new DerSequence(tbsCrl, sigAlgId, new DerBitString(signature))));
+		}
+
+		/// <summary>
+		/// Allows enumeration of the signature names supported by the generator.
+		/// </summary>
+		public IEnumerable SignatureAlgNames
+		{
+			get { return X509Utilities.GetAlgNames(); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/X509V3CertificateGenerator.cs b/BouncyCastle.AxCrypt/src/x509/X509V3CertificateGenerator.cs
new file mode 100644
index 0000000..bb0dd9c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/X509V3CertificateGenerator.cs
@@ -0,0 +1,346 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509
+{
+    /// <summary>
+    /// A class to Generate Version 3 X509Certificates.
+    /// </summary>
+    public class X509V3CertificateGenerator
+    {
+		private readonly X509ExtensionsGenerator extGenerator = new X509ExtensionsGenerator();
+
+		private V3TbsCertificateGenerator	tbsGen;
+        private DerObjectIdentifier			sigOid;
+        private AlgorithmIdentifier			sigAlgId;
+        private string						signatureAlgorithm;
+
+		public X509V3CertificateGenerator()
+        {
+            tbsGen = new V3TbsCertificateGenerator();
+        }
+
+		/// <summary>
+		/// Reset the Generator.
+		/// </summary>
+		public void Reset()
+		{
+			tbsGen = new V3TbsCertificateGenerator();
+			extGenerator.Reset();
+		}
+
+		/// <summary>
+        /// Set the certificate's serial number.
+        /// </summary>
+        /// <remarks>Make serial numbers long, if you have no serial number policy make sure the number is at least 16 bytes of secure random data.
+        /// You will be surprised how ugly a serial number collision can Get.</remarks>
+        /// <param name="serialNumber">The serial number.</param>
+        public void SetSerialNumber(
+			BigInteger serialNumber)
+        {
+			if (serialNumber.SignValue <= 0)
+			{
+				throw new ArgumentException("serial number must be a positive integer", "serialNumber");
+			}
+
+			tbsGen.SetSerialNumber(new DerInteger(serialNumber));
+        }
+
+		/// <summary>
+        /// Set the distinguished name of the issuer.
+        /// The issuer is the entity which is signing the certificate.
+        /// </summary>
+        /// <param name="issuer">The issuer's DN.</param>
+        public void SetIssuerDN(
+            X509Name issuer)
+        {
+            tbsGen.SetIssuer(issuer);
+        }
+
+		/// <summary>
+        /// Set the date that this certificate is to be valid from.
+        /// </summary>
+        /// <param name="date"/>
+        public void SetNotBefore(
+            DateTime date)
+        {
+            tbsGen.SetStartDate(new Time(date));
+        }
+
+        /// <summary>
+        /// Set the date after which this certificate will no longer be valid.
+        /// </summary>
+        /// <param name="date"/>
+        public void SetNotAfter(
+			DateTime date)
+        {
+            tbsGen.SetEndDate(new Time(date));
+        }
+
+		/// <summary>
+		/// Set the DN of the entity that this certificate is about.
+		/// </summary>
+		/// <param name="subject"/>
+        public void SetSubjectDN(
+			X509Name subject)
+        {
+            tbsGen.SetSubject(subject);
+        }
+
+		/// <summary>
+        /// Set the public key that this certificate identifies.
+        /// </summary>
+        /// <param name="publicKey"/>
+        public void SetPublicKey(
+			AsymmetricKeyParameter publicKey)
+        {
+            tbsGen.SetSubjectPublicKeyInfo(SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(publicKey));
+        }
+
+		/// <summary>
+        /// Set the signature algorithm that will be used to sign this certificate.
+        /// </summary>
+        /// <param name="signatureAlgorithm"/>
+        public void SetSignatureAlgorithm(
+			string signatureAlgorithm)
+        {
+			this.signatureAlgorithm = signatureAlgorithm;
+
+			try
+			{
+				sigOid = X509Utilities.GetAlgorithmOid(signatureAlgorithm);
+			}
+			catch (Exception)
+			{
+				throw new ArgumentException("Unknown signature type requested: " + signatureAlgorithm);
+			}
+
+			sigAlgId = X509Utilities.GetSigAlgID(sigOid, signatureAlgorithm);
+
+			tbsGen.SetSignature(sigAlgId);
+		}
+
+		/// <summary>
+		/// Set the subject unique ID - note: it is very rare that it is correct to do this.
+		/// </summary>
+		/// <param name="uniqueID"/>
+		public void SetSubjectUniqueID(
+			bool[] uniqueID)
+		{
+			tbsGen.SetSubjectUniqueID(booleanToBitString(uniqueID));
+		}
+
+		/// <summary>
+		/// Set the issuer unique ID - note: it is very rare that it is correct to do this.
+		/// </summary>
+		/// <param name="uniqueID"/>
+		public void SetIssuerUniqueID(
+			bool[] uniqueID)
+		{
+			tbsGen.SetIssuerUniqueID(booleanToBitString(uniqueID));
+		}
+
+		private DerBitString booleanToBitString(
+			bool[] id)
+		{
+			byte[] bytes = new byte[(id.Length + 7) / 8];
+
+			for (int i = 0; i != id.Length; i++)
+			{
+				if (id[i])
+				{
+					bytes[i / 8] |= (byte)(1 << ((7 - (i % 8))));
+				}
+			}
+
+			int pad = id.Length % 8;
+
+			if (pad == 0)
+			{
+				return new DerBitString(bytes);
+			}
+
+			return new DerBitString(bytes, 8 - pad);
+		}
+
+		/// <summary>
+		/// Add a given extension field for the standard extensions tag (tag 3).
+		/// </summary>
+		/// <param name="oid">string containing a dotted decimal Object Identifier.</param>
+		/// <param name="critical">Is it critical.</param>
+		/// <param name="extensionValue">The value.</param>
+		public void AddExtension(
+			string			oid,
+			bool			critical,
+			Asn1Encodable	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, extensionValue);
+		}
+
+		/// <summary>
+        /// Add an extension to this certificate.
+        /// </summary>
+        /// <param name="oid">Its Object Identifier.</param>
+        /// <param name="critical">Is it critical.</param>
+        /// <param name="extensionValue">The value.</param>
+        public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			Asn1Encodable		extensionValue)
+        {
+			extGenerator.AddExtension(oid, critical, extensionValue);
+        }
+
+		/// <summary>
+		/// Add an extension using a string with a dotted decimal OID.
+		/// </summary>
+		/// <param name="oid">string containing a dotted decimal Object Identifier.</param>
+		/// <param name="critical">Is it critical.</param>
+		/// <param name="extensionValue">byte[] containing the value of this extension.</param>
+		public void AddExtension(
+			string	oid,
+			bool	critical,
+			byte[]	extensionValue)
+		{
+			extGenerator.AddExtension(new DerObjectIdentifier(oid), critical, new DerOctetString(extensionValue));
+		}
+
+		/// <summary>
+        /// Add an extension to this certificate.
+        /// </summary>
+        /// <param name="oid">Its Object Identifier.</param>
+        /// <param name="critical">Is it critical.</param>
+        /// <param name="extensionValue">byte[] containing the value of this extension.</param>
+        public void AddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			byte[]				extensionValue)
+        {
+			extGenerator.AddExtension(oid, critical, new DerOctetString(extensionValue));
+        }
+
+		/// <summary>
+		/// Add a given extension field for the standard extensions tag (tag 3),
+		/// copying the extension value from another certificate.
+		/// </summary>
+		public void CopyAndAddExtension(
+			string			oid,
+			bool			critical,
+			X509Certificate	cert)
+		{
+			CopyAndAddExtension(new DerObjectIdentifier(oid), critical, cert);
+		}
+
+		/**
+		 * add a given extension field for the standard extensions tag (tag 3)
+		 * copying the extension value from another certificate.
+		 * @throws CertificateParsingException if the extension cannot be extracted.
+		 */
+		public void CopyAndAddExtension(
+			DerObjectIdentifier	oid,
+			bool				critical,
+			X509Certificate		cert)
+		{
+			Asn1OctetString extValue = cert.GetExtensionValue(oid);
+
+			if (extValue == null)
+			{
+				throw new CertificateParsingException("extension " + oid + " not present");
+			}
+
+			try
+			{
+				Asn1Encodable value = X509ExtensionUtilities.FromExtensionValue(extValue);
+
+				this.AddExtension(oid, critical, value);
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException(e.Message, e);
+			}
+		}
+
+		/// <summary>
+        /// Generate an X509Certificate.
+        /// </summary>
+        /// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+        /// <returns>An X509Certificate.</returns>
+        public X509Certificate Generate(
+			AsymmetricKeyParameter privateKey)
+        {
+            return Generate(privateKey, null);
+        }
+
+		/// <summary>
+		/// Generate an X509Certificate using your own SecureRandom.
+		/// </summary>
+		/// <param name="privateKey">The private key of the issuer that is signing this certificate.</param>
+		/// <param name="random">You Secure Random instance.</param>
+		/// <returns>An X509Certificate.</returns>
+		public X509Certificate Generate(
+			AsymmetricKeyParameter	privateKey,
+			SecureRandom			random)
+		{
+			TbsCertificateStructure tbsCert = GenerateTbsCert();
+			byte[] signature;
+
+			try
+			{
+				signature = X509Utilities.GetSignatureForObject(
+					sigOid, signatureAlgorithm, privateKey, random, tbsCert);
+			}
+			catch (Exception e)
+			{
+				// TODO
+//				throw new ExtCertificateEncodingException("exception encoding TBS cert", e);
+				throw new CertificateEncodingException("exception encoding TBS cert", e);
+			}
+
+			try
+			{
+				return GenerateJcaObject(tbsCert, signature);
+			}
+			catch (CertificateParsingException e)
+			{
+				// TODO
+				// throw new ExtCertificateEncodingException("exception producing certificate object", e);
+				throw new CertificateEncodingException("exception producing certificate object", e);
+			}
+		}
+
+		private TbsCertificateStructure GenerateTbsCert()
+		{
+			if (!extGenerator.IsEmpty)
+			{
+				tbsGen.SetExtensions(extGenerator.Generate());
+			}
+
+			return tbsGen.GenerateTbsCertificate();
+		}
+
+		private X509Certificate GenerateJcaObject(
+			TbsCertificateStructure	tbsCert,
+			byte[]					signature)
+		{
+			return new X509Certificate(
+				new X509CertificateStructure(tbsCert, sigAlgId, new DerBitString(signature)));
+		}
+
+		/// <summary>
+		/// Allows enumeration of the signature names supported by the generator.
+		/// </summary>
+		public IEnumerable SignatureAlgNames
+		{
+			get { return X509Utilities.GetAlgNames(); }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/extension/AuthorityKeyIdentifierStructure.cs b/BouncyCastle.AxCrypt/src/x509/extension/AuthorityKeyIdentifierStructure.cs
new file mode 100644
index 0000000..006dc00
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/extension/AuthorityKeyIdentifierStructure.cs
@@ -0,0 +1,102 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+
+namespace Org.BouncyCastle.X509.Extension
+{
+	/// <remarks>A high level authority key identifier.</remarks>
+	public class AuthorityKeyIdentifierStructure
+		: AuthorityKeyIdentifier
+	{
+		/**
+		 * Constructor which will take the byte[] returned from getExtensionValue()
+		 *
+		 * @param encodedValue a DER octet encoded string with the extension structure in it.
+		 * @throws IOException on parsing errors.
+		 */
+		// TODO Add a functional constructor from byte[]?
+		public AuthorityKeyIdentifierStructure(
+			Asn1OctetString encodedValue)
+			: base((Asn1Sequence) X509ExtensionUtilities.FromExtensionValue(encodedValue))
+		{
+		}
+
+		private static Asn1Sequence FromCertificate(
+			X509Certificate certificate)
+		{
+			try
+			{
+				GeneralName genName = new GeneralName(
+					PrincipalUtilities.GetIssuerX509Principal(certificate));
+
+				if (certificate.Version == 3)
+				{
+					Asn1OctetString ext = certificate.GetExtensionValue(X509Extensions.SubjectKeyIdentifier);
+
+					if (ext != null)
+					{
+						Asn1OctetString str = (Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(ext);
+
+						return (Asn1Sequence) new AuthorityKeyIdentifier(
+							str.GetOctets(), new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object();
+					}
+				}
+
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(
+					certificate.GetPublicKey());
+
+				return (Asn1Sequence) new AuthorityKeyIdentifier(
+					info, new GeneralNames(genName), certificate.SerialNumber).ToAsn1Object();
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException("Exception extracting certificate details", e);
+			}
+		}
+
+		private static Asn1Sequence FromKey(
+			AsymmetricKeyParameter pubKey)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
+
+				return (Asn1Sequence) new AuthorityKeyIdentifier(info).ToAsn1Object();
+			}
+			catch (Exception e)
+			{
+				throw new InvalidKeyException("can't process key: " + e);
+			}
+		}
+
+		/**
+		 * Create an AuthorityKeyIdentifier using the passed in certificate's public
+		 * key, issuer and serial number.
+		 *
+		 * @param certificate the certificate providing the information.
+		 * @throws CertificateParsingException if there is a problem processing the certificate
+		 */
+		public AuthorityKeyIdentifierStructure(
+			X509Certificate certificate)
+			: base(FromCertificate(certificate))
+		{
+		}
+
+		/**
+		 * Create an AuthorityKeyIdentifier using just the hash of the
+		 * public key.
+		 *
+		 * @param pubKey the key to generate the hash from.
+		 * @throws InvalidKeyException if there is a problem using the key.
+		 */
+		public AuthorityKeyIdentifierStructure(
+			AsymmetricKeyParameter pubKey)
+			: base(FromKey(pubKey))
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/extension/SubjectKeyIdentifierStructure.cs b/BouncyCastle.AxCrypt/src/x509/extension/SubjectKeyIdentifierStructure.cs
new file mode 100644
index 0000000..4c7b79a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/extension/SubjectKeyIdentifierStructure.cs
@@ -0,0 +1,49 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security.Certificates;
+
+namespace Org.BouncyCastle.X509.Extension
+{
+	/**
+	 * A high level subject key identifier.
+	 */
+	public class SubjectKeyIdentifierStructure
+		: SubjectKeyIdentifier
+	{
+		/**
+		 * Constructor which will take the byte[] returned from getExtensionValue()
+		 *
+		 * @param encodedValue a DER octet encoded string with the extension structure in it.
+		 * @throws IOException on parsing errors.
+		 */
+		public SubjectKeyIdentifierStructure(
+			Asn1OctetString encodedValue)
+			: base((Asn1OctetString) X509ExtensionUtilities.FromExtensionValue(encodedValue))
+		{
+		}
+
+		private static Asn1OctetString FromPublicKey(
+			AsymmetricKeyParameter pubKey)
+		{
+			try
+			{
+				SubjectPublicKeyInfo info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pubKey);
+
+				return (Asn1OctetString) new SubjectKeyIdentifier(info).ToAsn1Object();
+			}
+			catch (Exception e)
+			{
+				throw new CertificateParsingException("Exception extracting certificate details: " + e.ToString());
+			}
+		}
+
+		public SubjectKeyIdentifierStructure(
+			AsymmetricKeyParameter pubKey)
+			: base(FromPublicKey(pubKey))
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/extension/X509ExtensionUtil.cs b/BouncyCastle.AxCrypt/src/x509/extension/X509ExtensionUtil.cs
new file mode 100644
index 0000000..845a87b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/extension/X509ExtensionUtil.cs
@@ -0,0 +1,89 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Extension
+{
+	public class X509ExtensionUtilities
+	{
+		public static Asn1Object FromExtensionValue(
+			Asn1OctetString extensionValue)
+		{
+			return Asn1Object.FromByteArray(extensionValue.GetOctets());
+		}
+
+		public static ICollection GetIssuerAlternativeNames(
+			X509Certificate cert)
+		{
+			Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.IssuerAlternativeName);
+
+			return GetAlternativeName(extVal);
+		}
+
+		public static ICollection GetSubjectAlternativeNames(
+			X509Certificate cert)
+		{
+			Asn1OctetString extVal = cert.GetExtensionValue(X509Extensions.SubjectAlternativeName);
+
+			return GetAlternativeName(extVal);
+		}
+
+		private static ICollection GetAlternativeName(
+			Asn1OctetString extVal)
+		{
+			IList temp = Platform.CreateArrayList();
+
+			if (extVal != null)
+			{
+				try
+				{
+					Asn1Sequence seq = DerSequence.GetInstance(FromExtensionValue(extVal));
+
+					foreach (GeneralName genName in seq)
+					{
+                        IList list = Platform.CreateArrayList();
+						list.Add(genName.TagNo);
+
+						switch (genName.TagNo)
+						{
+							case GeneralName.EdiPartyName:
+							case GeneralName.X400Address:
+							case GeneralName.OtherName:
+								list.Add(genName.Name.ToAsn1Object());
+								break;
+							case GeneralName.DirectoryName:
+								list.Add(X509Name.GetInstance(genName.Name).ToString());
+								break;
+							case GeneralName.DnsName:
+							case GeneralName.Rfc822Name:
+							case GeneralName.UniformResourceIdentifier:
+								list.Add(((IAsn1String)genName.Name).GetString());
+								break;
+							case GeneralName.RegisteredID:
+								list.Add(DerObjectIdentifier.GetInstance(genName.Name).Id);
+								break;
+							case GeneralName.IPAddress:
+								list.Add(DerOctetString.GetInstance(genName.Name).GetOctets());
+								break;
+							default:
+								throw new IOException("Bad tag number: " + genName.TagNo);
+						}
+
+						temp.Add(list);
+					}
+				}
+				catch (Exception e)
+				{
+					throw new CertificateParsingException(e.Message);
+				}
+			}
+
+			return temp;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/IX509Selector.cs b/BouncyCastle.AxCrypt/src/x509/store/IX509Selector.cs
new file mode 100644
index 0000000..09f6f18
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/IX509Selector.cs
@@ -0,0 +1,15 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509Selector
+#if !SILVERLIGHT
+		: ICloneable
+#endif
+	{
+#if SILVERLIGHT
+        object Clone();
+#endif
+        bool Match(object obj);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/IX509Store.cs b/BouncyCastle.AxCrypt/src/x509/store/IX509Store.cs
new file mode 100644
index 0000000..e5c3a46
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/IX509Store.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509Store
+	{
+//		void Init(IX509StoreParameters parameters);
+		ICollection GetMatches(IX509Selector selector);
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/IX509StoreParameters.cs b/BouncyCastle.AxCrypt/src/x509/store/IX509StoreParameters.cs
new file mode 100644
index 0000000..aee3036
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/IX509StoreParameters.cs
@@ -0,0 +1,8 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public interface IX509StoreParameters
+	{
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/NoSuchStoreException.cs b/BouncyCastle.AxCrypt/src/x509/store/NoSuchStoreException.cs
new file mode 100644
index 0000000..02c5932
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/NoSuchStoreException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class NoSuchStoreException
+		: X509StoreException
+	{
+		public NoSuchStoreException()
+		{
+		}
+
+		public NoSuchStoreException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public NoSuchStoreException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509AttrCertStoreSelector.cs b/BouncyCastle.AxCrypt/src/x509/store/X509AttrCertStoreSelector.cs
new file mode 100644
index 0000000..9f1dc20
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509AttrCertStoreSelector.cs
@@ -0,0 +1,376 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/**
+	* This class is an <code>Selector</code> like implementation to select
+	* attribute certificates from a given set of criteria.
+	*
+	* @see org.bouncycastle.x509.X509AttributeCertificate
+	* @see org.bouncycastle.x509.X509Store
+	*/
+	public class X509AttrCertStoreSelector
+		: IX509Selector
+	{
+		// TODO: name constraints???
+
+		private IX509AttributeCertificate attributeCert;
+		private DateTimeObject attributeCertificateValid;
+		private AttributeCertificateHolder holder;
+		private AttributeCertificateIssuer issuer;
+		private BigInteger serialNumber;
+		private ISet targetNames = new HashSet();
+		private ISet targetGroups = new HashSet();
+
+		public X509AttrCertStoreSelector()
+		{
+		}
+
+		private X509AttrCertStoreSelector(
+			X509AttrCertStoreSelector o)
+		{
+			this.attributeCert = o.attributeCert;
+			this.attributeCertificateValid = o.attributeCertificateValid;
+			this.holder = o.holder;
+			this.issuer = o.issuer;
+			this.serialNumber = o.serialNumber;
+			this.targetGroups = new HashSet(o.targetGroups);
+			this.targetNames = new HashSet(o.targetNames);
+		}
+
+		/// <summary>
+		/// Decides if the given attribute certificate should be selected.
+		/// </summary>
+		/// <param name="obj">The attribute certificate to be checked.</param>
+		/// <returns><code>true</code> if the object matches this selector.</returns>
+		public bool Match(
+			object obj)
+		{
+			if (obj == null)
+				throw new ArgumentNullException("obj");
+
+			IX509AttributeCertificate attrCert = obj as IX509AttributeCertificate;
+
+			if (attrCert == null)
+				return false;
+
+			if (this.attributeCert != null && !this.attributeCert.Equals(attrCert))
+				return false;
+
+			if (serialNumber != null && !attrCert.SerialNumber.Equals(serialNumber))
+				return false;
+
+			if (holder != null && !attrCert.Holder.Equals(holder))
+				return false;
+
+			if (issuer != null && !attrCert.Issuer.Equals(issuer))
+				return false;
+
+			if (attributeCertificateValid != null && !attrCert.IsValid(attributeCertificateValid.Value))
+				return false;
+
+			if (targetNames.Count > 0 || targetGroups.Count > 0)
+			{
+				Asn1OctetString targetInfoExt = attrCert.GetExtensionValue(
+					X509Extensions.TargetInformation);
+
+				if (targetInfoExt != null)
+				{
+					TargetInformation targetinfo;
+					try
+					{
+						targetinfo = TargetInformation.GetInstance(
+							X509ExtensionUtilities.FromExtensionValue(targetInfoExt));
+					}
+					catch (Exception)
+					{
+						return false;
+					}
+
+					Targets[] targetss = targetinfo.GetTargetsObjects();
+
+					if (targetNames.Count > 0)
+					{
+						bool found = false;
+
+						for (int i = 0; i < targetss.Length && !found; i++)
+						{
+							Target[] targets = targetss[i].GetTargets();
+
+							for (int j = 0; j < targets.Length; j++)
+							{
+								GeneralName targetName = targets[j].TargetName;
+
+								if (targetName != null && targetNames.Contains(targetName))
+								{
+									found = true;
+									break;
+								}
+							}
+						}
+						if (!found)
+						{
+							return false;
+						}
+					}
+
+					if (targetGroups.Count > 0)
+					{
+						bool found = false;
+
+						for (int i = 0; i < targetss.Length && !found; i++)
+						{
+							Target[] targets = targetss[i].GetTargets();
+
+							for (int j = 0; j < targets.Length; j++)
+							{
+								GeneralName targetGroup = targets[j].TargetGroup;
+
+								if (targetGroup != null && targetGroups.Contains(targetGroup))
+								{
+									found = true;
+									break;
+								}
+							}
+						}
+
+						if (!found)
+						{
+							return false;
+						}
+					}
+				}
+			}
+
+			return true;
+		}
+
+		public object Clone()
+		{
+			return new X509AttrCertStoreSelector(this);
+		}
+
+		/// <summary>The attribute certificate which must be matched.</summary>
+		/// <remarks>If <c>null</c> is given, any will do.</remarks>
+		public IX509AttributeCertificate AttributeCert
+		{
+			get { return attributeCert; }
+			set { this.attributeCert = value; }
+		}
+
+		[Obsolete("Use AttributeCertificateValid instead")]
+		public DateTimeObject AttribueCertificateValid
+		{
+			get { return attributeCertificateValid; }
+			set { this.attributeCertificateValid = value; }
+		}
+
+		/// <summary>The criteria for validity</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public DateTimeObject AttributeCertificateValid
+		{
+			get { return attributeCertificateValid; }
+			set { this.attributeCertificateValid = value; }
+		}
+
+		/// <summary>The holder.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public AttributeCertificateHolder Holder
+		{
+			get { return holder; }
+			set { this.holder = value; }
+		}
+
+		/// <summary>The issuer.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public AttributeCertificateIssuer Issuer
+		{
+			get { return issuer; }
+			set { this.issuer = value; }
+		}
+
+		/// <summary>The serial number.</summary>
+		/// <remarks>If <c>null</c> is given any will do.</remarks>
+		public BigInteger SerialNumber
+		{
+			get { return serialNumber; }
+			set { this.serialNumber = value; }
+		}
+
+		/**
+		* Adds a target name criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target names.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name The name as a GeneralName (not <code>null</code>)
+		*/
+		public void AddTargetName(
+			GeneralName name)
+		{
+			targetNames.Add(name);
+		}
+
+		/**
+		* Adds a target name criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target names.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name a byte array containing the name in ASN.1 DER encoded form of a GeneralName
+		* @throws IOException if a parsing error occurs.
+		*/
+		public void AddTargetName(
+			byte[] name)
+		{
+			AddTargetName(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
+		}
+
+		/**
+		* Adds a collection with target names criteria. If <code>null</code> is
+		* given any will do.
+		* <p>
+		* The collection consists of either GeneralName objects or byte[] arrays representing
+		* DER encoded GeneralName structures.
+		* </p>
+		* 
+		* @param names A collection of target names.
+		* @throws IOException if a parsing error occurs.
+		* @see #AddTargetName(byte[])
+		* @see #AddTargetName(GeneralName)
+		*/
+		public void SetTargetNames(
+			IEnumerable names)
+		{
+			targetNames = ExtractGeneralNames(names);
+		}
+
+		/**
+		* Gets the target names. The collection consists of <code>List</code>s
+		* made up of an <code>Integer</code> in the first entry and a DER encoded
+		* byte array or a <code>String</code> in the second entry.
+		* <p>The returned collection is immutable.</p>
+		* 
+		* @return The collection of target names
+		* @see #setTargetNames(Collection)
+		*/
+		public IEnumerable GetTargetNames()
+		{
+			return new EnumerableProxy(targetNames);
+		}
+
+		/**
+		* Adds a target group criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target groups.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param group The group as GeneralName form (not <code>null</code>)
+		*/
+		public void AddTargetGroup(
+			GeneralName group)
+		{
+			targetGroups.Add(group);
+		}
+
+		/**
+		* Adds a target group criterion for the attribute certificate to the target
+		* information extension criteria. The <code>X509AttributeCertificate</code>
+		* must contain at least one of the specified target groups.
+		* <p>
+		* Each attribute certificate may contain a target information extension
+		* limiting the servers where this attribute certificate can be used. If
+		* this extension is not present, the attribute certificate is not targeted
+		* and may be accepted by any server.
+		* </p>
+		*
+		* @param name a byte array containing the group in ASN.1 DER encoded form of a GeneralName
+		* @throws IOException if a parsing error occurs.
+		*/
+		public void AddTargetGroup(
+			byte[] name)
+		{
+			AddTargetGroup(GeneralName.GetInstance(Asn1Object.FromByteArray(name)));
+		}
+
+		/**
+		* Adds a collection with target groups criteria. If <code>null</code> is
+		* given any will do.
+		* <p>
+		* The collection consists of <code>GeneralName</code> objects or <code>byte[]</code>
+		* representing DER encoded GeneralNames.
+		* </p>
+		*
+		* @param names A collection of target groups.
+		* @throws IOException if a parsing error occurs.
+		* @see #AddTargetGroup(byte[])
+		* @see #AddTargetGroup(GeneralName)
+		*/
+		public void SetTargetGroups(
+			IEnumerable names)
+		{
+			targetGroups = ExtractGeneralNames(names);
+		}
+
+		/**
+		* Gets the target groups. The collection consists of <code>List</code>s
+		* made up of an <code>Integer</code> in the first entry and a DER encoded
+		* byte array or a <code>String</code> in the second entry.
+		* <p>The returned collection is immutable.</p>
+		*
+		* @return The collection of target groups.
+		* @see #setTargetGroups(Collection)
+		*/
+		public IEnumerable GetTargetGroups()
+		{
+			return new EnumerableProxy(targetGroups);
+		}
+
+		private ISet ExtractGeneralNames(
+			IEnumerable names)
+		{
+			ISet result = new HashSet();
+
+			if (names != null)
+			{
+				foreach (object o in names)
+				{
+					if (o is GeneralName)
+					{
+						result.Add(o);
+					}
+					else
+					{
+						result.Add(GeneralName.GetInstance(Asn1Object.FromByteArray((byte[]) o)));
+					}
+				}
+			}
+
+			return result;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509CertPairStoreSelector.cs b/BouncyCastle.AxCrypt/src/x509/store/X509CertPairStoreSelector.cs
new file mode 100644
index 0000000..2796971
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509CertPairStoreSelector.cs
@@ -0,0 +1,92 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/// <remarks>
+	/// This class is an <code>IX509Selector</code> implementation to select
+	/// certificate pairs, which are e.g. used for cross certificates. The set of
+	/// criteria is given from two <code>X509CertStoreSelector</code> objects,
+	/// each of which, if present, must match the respective component of a pair.
+	/// </remarks>
+	public class X509CertPairStoreSelector
+		: IX509Selector
+	{
+		private static X509CertStoreSelector CloneSelector(
+			X509CertStoreSelector s)
+		{
+			return s == null ? null : (X509CertStoreSelector) s.Clone();
+		}
+
+		private X509CertificatePair certPair;
+		private X509CertStoreSelector forwardSelector;
+		private X509CertStoreSelector reverseSelector;
+
+		public X509CertPairStoreSelector()
+		{
+		}
+
+		private X509CertPairStoreSelector(
+			X509CertPairStoreSelector o)
+		{
+			this.certPair = o.CertPair;
+			this.forwardSelector = o.ForwardSelector;
+			this.reverseSelector = o.ReverseSelector;
+		}
+
+		/// <summary>The certificate pair which is used for testing on equality.</summary>
+		public X509CertificatePair CertPair
+		{
+			get { return certPair; }
+			set { this.certPair = value; }
+		}
+
+		/// <summary>The certificate selector for the forward part.</summary>
+		public X509CertStoreSelector ForwardSelector
+		{
+			get { return CloneSelector(forwardSelector); }
+			set { this.forwardSelector = CloneSelector(value); }
+		}
+
+		/// <summary>The certificate selector for the reverse part.</summary>
+		public X509CertStoreSelector ReverseSelector
+		{
+			get { return CloneSelector(reverseSelector); }
+			set { this.reverseSelector = CloneSelector(value); }
+		}
+
+		/// <summary>
+		/// Decides if the given certificate pair should be selected. If
+		/// <c>obj</c> is not a <code>X509CertificatePair</code>, this method
+		/// returns <code>false</code>.
+		/// </summary>
+		/// <param name="obj">The <code>X509CertificatePair</code> to be tested.</param>
+		/// <returns><code>true</code> if the object matches this selector.</returns>
+		public bool Match(
+			object obj)
+		{
+			if (obj == null)
+				throw new ArgumentNullException("obj");
+
+			X509CertificatePair pair = obj as X509CertificatePair;
+
+			if (pair == null)
+				return false;
+
+			if (certPair != null && !certPair.Equals(pair))
+				return false;
+
+			if (forwardSelector != null && !forwardSelector.Match(pair.Forward))
+				return false;
+
+			if (reverseSelector != null && !reverseSelector.Match(pair.Reverse))
+				return false;
+
+			return true;
+		}
+
+		public object Clone()
+		{
+			return new X509CertPairStoreSelector(this);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509CertStoreSelector.cs b/BouncyCastle.AxCrypt/src/x509/store/X509CertStoreSelector.cs
new file mode 100644
index 0000000..3874edf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509CertStoreSelector.cs
@@ -0,0 +1,337 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public class X509CertStoreSelector
+		: IX509Selector
+	{
+		// TODO Missing criteria?
+
+		private byte[] authorityKeyIdentifier;
+		private int basicConstraints = -1;
+		private X509Certificate certificate;
+		private DateTimeObject certificateValid;
+		private ISet extendedKeyUsage;
+		private X509Name issuer;
+		private bool[] keyUsage;
+		private ISet policy;
+		private DateTimeObject privateKeyValid;
+		private BigInteger serialNumber;
+		private X509Name subject;
+		private byte[] subjectKeyIdentifier;
+		private SubjectPublicKeyInfo subjectPublicKey;
+		private DerObjectIdentifier subjectPublicKeyAlgID;
+
+		public X509CertStoreSelector()
+		{
+		}
+
+		public X509CertStoreSelector(
+			X509CertStoreSelector o)
+		{
+			this.authorityKeyIdentifier = o.AuthorityKeyIdentifier;
+			this.basicConstraints = o.BasicConstraints;
+			this.certificate = o.Certificate;
+			this.certificateValid = o.CertificateValid;
+			this.extendedKeyUsage = o.ExtendedKeyUsage;
+			this.issuer = o.Issuer;
+			this.keyUsage = o.KeyUsage;
+			this.policy = o.Policy;
+			this.privateKeyValid = o.PrivateKeyValid;
+			this.serialNumber = o.SerialNumber;
+			this.subject = o.Subject;
+			this.subjectKeyIdentifier = o.SubjectKeyIdentifier;
+			this.subjectPublicKey = o.SubjectPublicKey;
+			this.subjectPublicKeyAlgID = o.SubjectPublicKeyAlgID;
+		}
+
+		public virtual object Clone()
+		{
+			return new X509CertStoreSelector(this);
+		}
+
+		public byte[] AuthorityKeyIdentifier
+		{
+			get { return Arrays.Clone(authorityKeyIdentifier); }
+			set { authorityKeyIdentifier = Arrays.Clone(value); }
+		}
+
+		public int BasicConstraints
+		{
+			get { return basicConstraints; }
+			set
+			{
+				if (value < -2)
+					throw new ArgumentException("value can't be less than -2", "value");
+
+				basicConstraints = value;
+			}
+		}
+
+		public X509Certificate Certificate
+		{
+			get { return certificate; }
+			set { this.certificate = value; }
+		}
+
+		public DateTimeObject CertificateValid
+		{
+			get { return certificateValid; }
+			set { certificateValid = value; }
+		}
+
+		public ISet ExtendedKeyUsage
+		{
+			get { return CopySet(extendedKeyUsage); }
+			set { extendedKeyUsage = CopySet(value); }
+		}
+
+		public X509Name Issuer
+		{
+			get { return issuer; }
+			set { issuer = value; }
+		}
+
+		[Obsolete("Avoid working with X509Name objects in string form")]
+		public string IssuerAsString
+		{
+			get { return issuer != null ? issuer.ToString() : null; }
+		}
+
+		public bool[] KeyUsage
+		{
+			get { return CopyBoolArray(keyUsage); }
+			set { keyUsage = CopyBoolArray(value); }
+		}
+
+		/// <summary>
+		/// An <code>ISet</code> of <code>DerObjectIdentifier</code> objects.
+		/// </summary>
+		public ISet Policy
+		{
+			get { return CopySet(policy); }
+			set { policy = CopySet(value); }
+		}
+
+		public DateTimeObject PrivateKeyValid
+		{
+			get { return privateKeyValid; }
+			set { privateKeyValid = value; }
+		}
+
+		public BigInteger SerialNumber
+		{
+			get { return serialNumber; }
+			set { serialNumber = value; }
+		}
+
+		public X509Name Subject
+		{
+			get { return subject; }
+			set { subject = value; }
+		}
+
+		public string SubjectAsString
+		{
+			get { return subject != null ? subject.ToString() : null; }
+		}
+
+		public byte[] SubjectKeyIdentifier
+		{
+			get { return Arrays.Clone(subjectKeyIdentifier); }
+			set { subjectKeyIdentifier = Arrays.Clone(value); }
+		}
+
+		public SubjectPublicKeyInfo SubjectPublicKey
+		{
+			get { return subjectPublicKey; }
+			set { subjectPublicKey = value; }
+		}
+
+		public DerObjectIdentifier SubjectPublicKeyAlgID
+		{
+			get { return subjectPublicKeyAlgID; }
+			set { subjectPublicKeyAlgID = value; }
+		}
+
+		public virtual bool Match(
+			object obj)
+		{
+			X509Certificate c = obj as X509Certificate;
+
+			if (c == null)
+				return false;
+
+			if (!MatchExtension(authorityKeyIdentifier, c, X509Extensions.AuthorityKeyIdentifier))
+				return false;
+
+			if (basicConstraints != -1)
+			{
+				int bc = c.GetBasicConstraints();
+
+				if (basicConstraints == -2)
+				{
+					if (bc != -1)
+						return false;
+				}
+				else
+				{
+					if (bc < basicConstraints)
+						return false;
+				}
+			}
+
+			if (certificate != null && !certificate.Equals(c))
+				return false;
+
+			if (certificateValid != null && !c.IsValid(certificateValid.Value))
+				return false;
+
+			if (extendedKeyUsage != null)
+			{
+				IList eku = c.GetExtendedKeyUsage();
+
+				// Note: if no extended key usage set, all key purposes are implicitly allowed
+
+				if (eku != null)
+				{
+					foreach (DerObjectIdentifier oid in extendedKeyUsage)
+					{
+						if (!eku.Contains(oid.Id))
+							return false;
+					}
+				}
+			}
+
+			if (issuer != null && !issuer.Equivalent(c.IssuerDN, true))
+				return false;
+
+			if (keyUsage != null)
+			{
+				bool[] ku = c.GetKeyUsage();
+
+				// Note: if no key usage set, all key purposes are implicitly allowed
+
+				if (ku != null)
+				{
+					for (int i = 0; i < 9; ++i)
+					{
+						if (keyUsage[i] && !ku[i])
+							return false;
+					}
+				}
+			}
+
+			if (policy != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CertificatePolicies);
+				if (extVal == null)
+					return false;
+
+				Asn1Sequence certPolicies = Asn1Sequence.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal));
+
+				if (policy.Count < 1 && certPolicies.Count < 1)
+					return false;
+
+				bool found = false;
+				foreach (PolicyInformation pi in certPolicies)
+				{
+					if (policy.Contains(pi.PolicyIdentifier))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				if (!found)
+					return false;
+			}
+
+			if (privateKeyValid != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.PrivateKeyUsagePeriod);
+				if (extVal == null)
+					return false;
+
+				PrivateKeyUsagePeriod pkup = PrivateKeyUsagePeriod.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal));
+
+				DateTime dt = privateKeyValid.Value;
+				DateTime notAfter = pkup.NotAfter.ToDateTime();
+				DateTime notBefore = pkup.NotBefore.ToDateTime();
+
+				if (dt.CompareTo(notAfter) > 0 || dt.CompareTo(notBefore) < 0)
+					return false;
+			}
+
+			if (serialNumber != null && !serialNumber.Equals(c.SerialNumber))
+				return false;
+
+			if (subject != null && !subject.Equivalent(c.SubjectDN, true))
+				return false;
+
+			if (!MatchExtension(subjectKeyIdentifier, c, X509Extensions.SubjectKeyIdentifier))
+				return false;
+
+			if (subjectPublicKey != null && !subjectPublicKey.Equals(GetSubjectPublicKey(c)))
+				return false;
+
+			if (subjectPublicKeyAlgID != null
+				&& !subjectPublicKeyAlgID.Equals(GetSubjectPublicKey(c).AlgorithmID))
+				return false;
+
+			return true;
+		}
+
+		internal static bool IssuersMatch(
+			X509Name	a,
+			X509Name	b)
+		{
+			return a == null ? b == null : a.Equivalent(b, true);
+		}
+
+		private static bool[] CopyBoolArray(
+			bool[] b)
+		{
+			return b == null ? null : (bool[]) b.Clone();
+		}
+
+		private static ISet CopySet(
+			ISet s)
+		{
+			return s == null ? null : new HashSet(s);
+		}
+
+		private static SubjectPublicKeyInfo GetSubjectPublicKey(
+			X509Certificate c)
+		{
+			return SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(c.GetPublicKey());
+		}
+
+		private static bool MatchExtension(
+			byte[]				b,
+			X509Certificate		c,
+			DerObjectIdentifier	oid)
+		{
+			if (b == null)
+				return true;
+
+			Asn1OctetString extVal = c.GetExtensionValue(oid);
+
+			if (extVal == null)
+				return false;
+
+			return Arrays.AreEqual(b, extVal.GetOctets());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStore.cs b/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStore.cs
new file mode 100644
index 0000000..9217314
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStore.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/**
+	 * A simple collection backed store.
+	 */
+	internal class X509CollectionStore
+		: IX509Store
+	{
+		private ICollection _local;
+
+		/**
+		 * Basic constructor.
+		 *
+		 * @param collection - initial contents for the store, this is copied.
+		 */
+		internal X509CollectionStore(
+			ICollection collection)
+		{
+			_local = Platform.CreateArrayList(collection);
+		}
+
+		/**
+		 * Return the matches in the collection for the passed in selector.
+		 *
+		 * @param selector the selector to match against.
+		 * @return a possibly empty collection of matching objects.
+		 */
+		public ICollection GetMatches(
+			IX509Selector selector)
+		{
+			if (selector == null)
+			{
+                return Platform.CreateArrayList(_local);
+			}
+
+            IList result = Platform.CreateArrayList();
+			foreach (object obj in _local)
+			{
+				if (selector.Match(obj))
+					result.Add(obj);
+			}
+
+			return result;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStoreParameters.cs b/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStoreParameters.cs
new file mode 100644
index 0000000..7fd047a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509CollectionStoreParameters.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	/// <remarks>This class contains a collection for collection based <code>X509Store</code>s.</remarks>
+	public class X509CollectionStoreParameters
+		: IX509StoreParameters
+	{
+		private readonly IList collection;
+
+		/// <summary>
+		/// Constructor.
+		/// <p>
+		/// The collection is copied.
+		/// </p>
+		/// </summary>
+		/// <param name="collection">The collection containing X.509 object types.</param>
+		/// <exception cref="ArgumentNullException">If collection is null.</exception>
+		public X509CollectionStoreParameters(
+			ICollection collection)
+		{
+			if (collection == null)
+				throw new ArgumentNullException("collection");
+
+			this.collection = Platform.CreateArrayList(collection);
+		}
+
+		// TODO Do we need to be able to Clone() these, and should it really be shallow?
+//		/**
+//		* Returns a shallow clone. The returned contents are not copied, so adding
+//		* or removing objects will effect this.
+//		*
+//		* @return a shallow clone.
+//		*/
+//		public object Clone()
+//		{
+//			return new X509CollectionStoreParameters(collection);
+//		}
+
+		/// <summary>Returns a copy of the <code>ICollection</code>.</summary>
+		public ICollection GetCollection()
+		{
+			return Platform.CreateArrayList(collection);
+		}
+
+		/// <summary>Returns a formatted string describing the parameters.</summary>
+		public override string ToString()
+		{
+			StringBuilder sb = new StringBuilder();
+			sb.Append("X509CollectionStoreParameters: [\n");
+			sb.Append("  collection: " + collection + "\n");
+			sb.Append("]");
+			return sb.ToString();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509CrlStoreSelector.cs b/BouncyCastle.AxCrypt/src/x509/store/X509CrlStoreSelector.cs
new file mode 100644
index 0000000..c4b0062
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509CrlStoreSelector.cs
@@ -0,0 +1,283 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public class X509CrlStoreSelector
+		: IX509Selector
+	{
+		// TODO Missing criteria?
+
+		private X509Certificate certificateChecking;
+		private DateTimeObject dateAndTime;
+		private ICollection issuers;
+		private BigInteger maxCrlNumber;
+		private BigInteger minCrlNumber;
+
+		private IX509AttributeCertificate attrCertChecking;
+		private bool completeCrlEnabled;
+		private bool deltaCrlIndicatorEnabled;
+		private byte[] issuingDistributionPoint;
+		private bool issuingDistributionPointEnabled;
+		private BigInteger maxBaseCrlNumber;
+
+		public X509CrlStoreSelector()
+		{
+		}
+
+		public X509CrlStoreSelector(
+			X509CrlStoreSelector o)
+		{
+			this.certificateChecking = o.CertificateChecking;
+			this.dateAndTime = o.DateAndTime;
+			this.issuers = o.Issuers;
+			this.maxCrlNumber = o.MaxCrlNumber;
+			this.minCrlNumber = o.MinCrlNumber;
+
+			this.deltaCrlIndicatorEnabled = o.DeltaCrlIndicatorEnabled;
+			this.completeCrlEnabled = o.CompleteCrlEnabled;
+			this.maxBaseCrlNumber = o.MaxBaseCrlNumber;
+			this.attrCertChecking = o.AttrCertChecking;
+			this.issuingDistributionPointEnabled = o.IssuingDistributionPointEnabled;
+			this.issuingDistributionPoint = o.IssuingDistributionPoint;
+		}
+
+		public virtual object Clone()
+		{
+			return new X509CrlStoreSelector(this);
+		}
+
+		public X509Certificate CertificateChecking
+		{
+			get { return certificateChecking; }
+			set { certificateChecking = value; }
+		}
+
+		public DateTimeObject DateAndTime
+		{
+			get { return dateAndTime; }
+			set { dateAndTime = value; }
+		}
+
+		/// <summary>
+		/// An <code>ICollection</code> of <code>X509Name</code> objects
+		/// </summary>
+		public ICollection Issuers
+		{
+			get { return Platform.CreateArrayList(issuers); }
+            set { issuers = Platform.CreateArrayList(value); }
+		}
+
+		public BigInteger MaxCrlNumber
+		{
+			get { return maxCrlNumber; }
+			set { maxCrlNumber = value; }
+		}
+
+		public BigInteger MinCrlNumber
+		{
+			get { return minCrlNumber; }
+			set { minCrlNumber = value; }
+		}
+
+		/**
+		 * The attribute certificate being checked. This is not a criterion.
+		 * Rather, it is optional information that may help a {@link X509Store} find
+		 * CRLs that would be relevant when checking revocation for the specified
+		 * attribute certificate. If <code>null</code> is specified, then no such
+		 * optional information is provided.
+		 *
+		 * @param attrCert the <code>IX509AttributeCertificate</code> being checked (or
+		 *             <code>null</code>)
+		 * @see #getAttrCertificateChecking()
+		 */
+		public IX509AttributeCertificate AttrCertChecking
+		{
+			get { return attrCertChecking; }
+			set { this.attrCertChecking = value; }
+		}
+
+		/**
+		 * If <code>true</code> only complete CRLs are returned. Defaults to
+		 * <code>false</code>.
+		 *
+		 * @return <code>true</code> if only complete CRLs are returned.
+		 */
+		public bool CompleteCrlEnabled
+		{
+			get { return completeCrlEnabled; }
+			set { this.completeCrlEnabled = value; }
+		}
+
+		/**
+		 * Returns if this selector must match CRLs with the delta CRL indicator
+		 * extension set. Defaults to <code>false</code>.
+		 *
+		 * @return Returns <code>true</code> if only CRLs with the delta CRL
+		 *         indicator extension are selected.
+		 */
+		public bool DeltaCrlIndicatorEnabled
+		{
+			get { return deltaCrlIndicatorEnabled; }
+			set { this.deltaCrlIndicatorEnabled = value; }
+		}
+
+		/**
+		 * The issuing distribution point.
+		 * <p>
+		 * The issuing distribution point extension is a CRL extension which
+		 * identifies the scope and the distribution point of a CRL. The scope
+		 * contains among others information about revocation reasons contained in
+		 * the CRL. Delta CRLs and complete CRLs must have matching issuing
+		 * distribution points.</p>
+		 * <p>
+		 * The byte array is cloned to protect against subsequent modifications.</p>
+		 * <p>
+		 * You must also enable or disable this criteria with
+		 * {@link #setIssuingDistributionPointEnabled(bool)}.</p>
+		 *
+		 * @param issuingDistributionPoint The issuing distribution point to set.
+		 *                                 This is the DER encoded OCTET STRING extension value.
+		 * @see #getIssuingDistributionPoint()
+		 */
+		public byte[] IssuingDistributionPoint
+		{
+			get { return Arrays.Clone(issuingDistributionPoint); }
+			set { this.issuingDistributionPoint = Arrays.Clone(value); }
+		}
+
+		/**
+		 * Whether the issuing distribution point criteria should be applied.
+		 * Defaults to <code>false</code>.
+		 * <p>
+		 * You may also set the issuing distribution point criteria if not a missing
+		 * issuing distribution point should be assumed.</p>
+		 *
+		 * @return Returns if the issuing distribution point check is enabled.
+		 */
+		public bool IssuingDistributionPointEnabled
+		{
+			get { return issuingDistributionPointEnabled; }
+			set { this.issuingDistributionPointEnabled = value; }
+		}
+
+		/**
+		 * The maximum base CRL number. Defaults to <code>null</code>.
+		 *
+		 * @return Returns the maximum base CRL number.
+		 * @see #setMaxBaseCRLNumber(BigInteger)
+		 */
+		public BigInteger MaxBaseCrlNumber
+		{
+			get { return maxBaseCrlNumber; }
+			set { this.maxBaseCrlNumber = value; }
+		}
+
+		public virtual bool Match(
+			object obj)
+		{
+			X509Crl c = obj as X509Crl;
+
+			if (c == null)
+				return false;
+
+			if (dateAndTime != null)
+			{
+				DateTime dt = dateAndTime.Value;
+				DateTime tu = c.ThisUpdate;
+				DateTimeObject nu = c.NextUpdate;
+
+				if (dt.CompareTo(tu) < 0 || nu == null || dt.CompareTo(nu.Value) >= 0)
+					return false;
+			}
+
+			if (issuers != null)
+			{
+				X509Name i = c.IssuerDN;
+
+				bool found = false;
+
+				foreach (X509Name issuer in issuers)
+				{
+					if (issuer.Equivalent(i, true))
+					{
+						found = true;
+						break;
+					}
+				}
+
+				if (!found)
+					return false;
+			}
+
+			if (maxCrlNumber != null || minCrlNumber != null)
+			{
+				Asn1OctetString extVal = c.GetExtensionValue(X509Extensions.CrlNumber);
+				if (extVal == null)
+					return false;
+
+				BigInteger cn = CrlNumber.GetInstance(
+					X509ExtensionUtilities.FromExtensionValue(extVal)).PositiveValue;
+
+				if (maxCrlNumber != null && cn.CompareTo(maxCrlNumber) > 0)
+					return false;
+
+				if (minCrlNumber != null && cn.CompareTo(minCrlNumber) < 0)
+					return false;
+			}
+
+			DerInteger dci = null;
+			try
+			{
+				Asn1OctetString bytes = c.GetExtensionValue(X509Extensions.DeltaCrlIndicator);
+				if (bytes != null)
+				{
+					dci = DerInteger.GetInstance(X509ExtensionUtilities.FromExtensionValue(bytes));
+				}
+			}
+			catch (Exception)
+			{
+				return false;
+			}
+
+			if (dci == null)
+			{
+				if (DeltaCrlIndicatorEnabled)
+					return false;
+			}
+			else
+			{
+				if (CompleteCrlEnabled)
+					return false;
+
+				if (maxBaseCrlNumber != null && dci.PositiveValue.CompareTo(maxBaseCrlNumber) > 0)
+					return false;
+			}
+
+			if (issuingDistributionPointEnabled)
+			{
+				Asn1OctetString idp = c.GetExtensionValue(X509Extensions.IssuingDistributionPoint);
+				if (issuingDistributionPoint == null)
+				{
+					if (idp != null)
+						return false;
+				}
+				else
+				{
+					if (!Arrays.AreEqual(idp.GetOctets(), issuingDistributionPoint))
+						return false;
+				}
+			}
+
+			return true;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509StoreException.cs b/BouncyCastle.AxCrypt/src/x509/store/X509StoreException.cs
new file mode 100644
index 0000000..f781291
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509StoreException.cs
@@ -0,0 +1,28 @@
+using System;
+
+namespace Org.BouncyCastle.X509.Store
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class X509StoreException
+		: Exception
+	{
+		public X509StoreException()
+		{
+		}
+
+		public X509StoreException(
+			string message)
+			: base(message)
+		{
+		}
+
+		public X509StoreException(
+			string		message,
+			Exception	e)
+			: base(message, e)
+		{
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/src/x509/store/X509StoreFactory.cs b/BouncyCastle.AxCrypt/src/x509/store/X509StoreFactory.cs
new file mode 100644
index 0000000..96f22be
--- /dev/null
+++ b/BouncyCastle.AxCrypt/src/x509/store/X509StoreFactory.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.X509.Store
+{
+	public sealed class X509StoreFactory
+	{
+		private X509StoreFactory()
+		{
+		}
+
+		public static IX509Store Create(
+			string					type,
+			IX509StoreParameters	parameters)
+		{
+			if (type == null)
+				throw new ArgumentNullException("type");
+
+			string[] parts = Platform.ToUpperInvariant(type).Split('/');
+
+            if (parts.Length < 2)
+				throw new ArgumentException("type");
+
+			if (parts[1] != "COLLECTION")
+				throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+
+			X509CollectionStoreParameters p = (X509CollectionStoreParameters) parameters;
+			ICollection coll = p.GetCollection();
+
+			switch (parts[0])
+			{
+				case "ATTRIBUTECERTIFICATE":
+					checkCorrectType(coll, typeof(IX509AttributeCertificate));
+					break;
+				case "CERTIFICATE":
+					checkCorrectType(coll, typeof(X509Certificate));
+					break;
+				case "CERTIFICATEPAIR":
+					checkCorrectType(coll, typeof(X509CertificatePair));
+					break;
+				case "CRL":
+					checkCorrectType(coll, typeof(X509Crl));
+					break;
+				default:
+					throw new NoSuchStoreException("X.509 store type '" + type + "' not available.");
+			}
+
+			return new X509CollectionStore(coll);
+		}
+
+		private static void checkCorrectType(ICollection coll, Type t)
+		{
+			foreach (object o in coll)
+			{
+				if (!t.IsInstanceOfType(o))
+					throw new InvalidCastException("Can't cast object to type: " + t.FullName);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/README.txt b/BouncyCastle.AxCrypt/test/data/PKITS/README.txt
new file mode 100644
index 0000000..00a124b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/PKITS/README.txt
@@ -0,0 +1,3 @@
+PKITS test data from http://csrc.nist.gov/pki/testing/x509paths.html
+
+For more details please check the website above.
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt
new file mode 100644
index 0000000..6c40491
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesNoPoliciesTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt
new file mode 100644
index 0000000..41b6d15
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt
new file mode 100644
index 0000000..9210106
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesSamePoliciesTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt
new file mode 100644
index 0000000..a7f9d22
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AllCertificatesanyPolicyTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/AnyPolicyTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AnyPolicyTest14EE.crt
new file mode 100644
index 0000000..b5961c7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/AnyPolicyTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt
new file mode 100644
index 0000000..6afe5dd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLIssuerNameCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLSignatureCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLSignatureCACert.crt
new file mode 100644
index 0000000..bfac8a4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadCRLSignatureCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadSignedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadSignedCACert.crt
new file mode 100644
index 0000000..abf7f31
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadSignedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotAfterDateCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotAfterDateCACert.crt
new file mode 100644
index 0000000..d8babc2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotAfterDateCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotBeforeDateCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotBeforeDateCACert.crt
new file mode 100644
index 0000000..9b4cd82
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BadnotBeforeDateCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt
new file mode 100644
index 0000000..4188114
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt
new file mode 100644
index 0000000..7c1b139
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedCRLSigningKeyCRLCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt
new file mode 100644
index 0000000..b4ccbe8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt
new file mode 100644
index 0000000..336a1ca
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedNewKeyOldWithNewCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt
new file mode 100644
index 0000000..78953d6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt
new file mode 100644
index 0000000..853dc06
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/BasicSelfIssuedOldKeyNewWithOldCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt
new file mode 100644
index 0000000..8bc7036
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/CPSPointerQualifierTest20EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSACACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSACACert.crt
new file mode 100644
index 0000000..a1f9e05
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSACACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSAParametersInheritedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSAParametersInheritedCACert.crt
new file mode 100644
index 0000000..7eae486
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DSAParametersInheritedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt
new file mode 100644
index 0000000..6aa6ae5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt
new file mode 100644
index 0000000..8cd24ec
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt
new file mode 100644
index 0000000..6af794d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt
new file mode 100644
index 0000000..4315046
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt
new file mode 100644
index 0000000..8caf46a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt
new file mode 100644
index 0000000..f49721d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt
new file mode 100644
index 0000000..49a38a5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/DifferentPoliciesTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt
new file mode 100644
index 0000000..c22228a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GeneralizedTimeCRLnextUpdateCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodCACert.crt
new file mode 100644
index 0000000..5aecbc0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCACert.crt
new file mode 100644
index 0000000..09c98aa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt
new file mode 100644
index 0000000..2540cd4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/GoodsubCAPanyPolicyMapping1to2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt
new file mode 100644
index 0000000..749f7cc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLIssuerNameTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt
new file mode 100644
index 0000000..3c4d2cb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBadCRLSignatureTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt
new file mode 100644
index 0000000..7919115
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt
new file mode 100644
index 0000000..b242bad
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedCRLSigningKeyTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt
new file mode 100644
index 0000000..e75d978
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedNewWithOldTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt
new file mode 100644
index 0000000..ed30001
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidBasicSelfIssuedOldWithNewTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt
new file mode 100644
index 0000000..8d337bd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCASignatureTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt
new file mode 100644
index 0000000..6f6748d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotAfterDateTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt
new file mode 100644
index 0000000..e7b01de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidCAnotBeforeDateTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt
new file mode 100644
index 0000000..3f86eef
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest31EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt
new file mode 100644
index 0000000..805205b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest33EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt
new file mode 100644
index 0000000..eff3779
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNSnameConstraintsTest38EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt
new file mode 100644
index 0000000..7c1dd9c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest28EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt
new file mode 100644
index 0000000..bdf08ad
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNandRFC822nameConstraintsTest29EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt
new file mode 100644
index 0000000..5ff84a4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt
new file mode 100644
index 0000000..11ec10f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt
new file mode 100644
index 0000000..08c3050
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt
new file mode 100644
index 0000000..28ab465
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest15EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt
new file mode 100644
index 0000000..56e42d0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest16EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt
new file mode 100644
index 0000000..f9f53b9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest17EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt
new file mode 100644
index 0000000..15fbe8f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest20EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt
new file mode 100644
index 0000000..8daf2f2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt
new file mode 100644
index 0000000..52cd999
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt
new file mode 100644
index 0000000..799760b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt
new file mode 100644
index 0000000..d874621
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt
new file mode 100644
index 0000000..18314bd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDNnameConstraintsTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt
new file mode 100644
index 0000000..bcc900c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidDSASignatureTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt
new file mode 100644
index 0000000..e21461e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEESignatureTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt
new file mode 100644
index 0000000..46269d0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotAfterDateTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt
new file mode 100644
index 0000000..f1bf1d1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidEEnotBeforeDateTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt
new file mode 100644
index 0000000..31965f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest23EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt
new file mode 100644
index 0000000..b9b87a6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidIDPwithindirectCRLTest26EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt
new file mode 100644
index 0000000..1c84dce
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidLongSerialNumberTest18EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt
new file mode 100644
index 0000000..49aab72
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingFromanyPolicyTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt
new file mode 100644
index 0000000..0a56c5e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMappingToanyPolicyTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt
new file mode 100644
index 0000000..7af5ce5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingCRLTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt
new file mode 100644
index 0000000..f5d8703
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidMissingbasicConstraintsTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt
new file mode 100644
index 0000000..9c40a33
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingOrderTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt
new file mode 100644
index 0000000..f7ae3b0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNameChainingTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt
new file mode 100644
index 0000000..2d323b4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidNegativeSerialNumberTest15EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt
new file mode 100644
index 0000000..858db72
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidOldCRLnextUpdateTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt
new file mode 100644
index 0000000..ef227b8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt
new file mode 100644
index 0000000..58ace91
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt
new file mode 100644
index 0000000..c0dd555
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidPolicyMappingTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt
new file mode 100644
index 0000000..d8134e0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest22EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt
new file mode 100644
index 0000000..b71c6a3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest24EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt
new file mode 100644
index 0000000..0ffdf26
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRFC822nameConstraintsTest26EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt
new file mode 100644
index 0000000..65a0a1a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedCATest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt
new file mode 100644
index 0000000..80ea4d3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidRevokedEETest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt
new file mode 100644
index 0000000..21c32e9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt
new file mode 100644
index 0000000..d57f0cb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitAnyPolicyTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt
new file mode 100644
index 0000000..577998c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt
new file mode 100644
index 0000000..621c325
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt
new file mode 100644
index 0000000..98f8160
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt
new file mode 100644
index 0000000..b802772
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedinhibitPolicyMappingTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt
new file mode 100644
index 0000000..9fba63a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedpathLenConstraintTest16EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt
new file mode 100644
index 0000000..a1b58ff
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt
new file mode 100644
index 0000000..108f38c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSelfIssuedrequireExplicitPolicyTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt
new file mode 100644
index 0000000..8671cc6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest20EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt
new file mode 100644
index 0000000..b8faa4a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidSeparateCertificateandCRLKeysTest21EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt
new file mode 100644
index 0000000..5313fc9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest35EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt
new file mode 100644
index 0000000..81fd01d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidURInameConstraintsTest37EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt
new file mode 100644
index 0000000..6170dae
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLEntryExtensionTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt
new file mode 100644
index 0000000..8c8dfc0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt
new file mode 100644
index 0000000..83c1b6a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCRLExtensionTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt
new file mode 100644
index 0000000..65c7a68
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidUnknownCriticalCertificateExtensionTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt
new file mode 100644
index 0000000..206892c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidWrongCRLTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt
new file mode 100644
index 0000000..25b925a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt
new file mode 100644
index 0000000..5d8f863
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcAFalseTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt
new file mode 100644
index 0000000..1cb9f59
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest27EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt
new file mode 100644
index 0000000..7e08a55
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest31EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt
new file mode 100644
index 0000000..ec020a1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest32EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt
new file mode 100644
index 0000000..b309b80
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest34EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt
new file mode 100644
index 0000000..257daab
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidcRLIssuerTest35EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt
new file mode 100644
index 0000000..30e49a4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLIndicatorNoBaseTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt
new file mode 100644
index 0000000..d60e4f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt
new file mode 100644
index 0000000..27ce111
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt
new file mode 100644
index 0000000..a7edcf8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt
new file mode 100644
index 0000000..0e247f2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt
new file mode 100644
index 0000000..e5b34e4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddeltaCRLTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt
new file mode 100644
index 0000000..c61a646
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt
new file mode 100644
index 0000000..5310332
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt
new file mode 100644
index 0000000..9236346
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt
new file mode 100644
index 0000000..3520f6a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt
new file mode 100644
index 0000000..5982bb6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvaliddistributionPointTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt
new file mode 100644
index 0000000..b6fe661
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt
new file mode 100644
index 0000000..e6a924a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt
new file mode 100644
index 0000000..20c40a4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt
new file mode 100644
index 0000000..03c8a32
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitAnyPolicyTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt
new file mode 100644
index 0000000..f028a76
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt
new file mode 100644
index 0000000..3393af5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt
new file mode 100644
index 0000000..3746814
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt
new file mode 100644
index 0000000..9f7eafa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidinhibitPolicyMappingTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt
new file mode 100644
index 0000000..888f7e2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalcRLSignFalseTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt
new file mode 100644
index 0000000..43b0d95
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageCriticalkeyCertSignFalseTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt
new file mode 100644
index 0000000..fbfb4c4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalcRLSignFalseTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt
new file mode 100644
index 0000000..a9da414
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidkeyUsageNotCriticalkeyCertSignFalseTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt
new file mode 100644
index 0000000..60e0f7d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsAttributeCertsTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt
new file mode 100644
index 0000000..c0ada12
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsCACertsTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt
new file mode 100644
index 0000000..acf1199
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlyContainsUserCertsTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt
new file mode 100644
index 0000000..45460ee
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest15EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt
new file mode 100644
index 0000000..b82e84e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest16EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt
new file mode 100644
index 0000000..d29a9ff
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest17EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt
new file mode 100644
index 0000000..431d600
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest20EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt
new file mode 100644
index 0000000..68bf8f9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidonlySomeReasonsTest21EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt
new file mode 100644
index 0000000..788389d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt
new file mode 100644
index 0000000..01ea4d0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt
new file mode 100644
index 0000000..2316416
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt
new file mode 100644
index 0000000..7164f04
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt
new file mode 100644
index 0000000..eec5f9d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt
new file mode 100644
index 0000000..6a063a6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidpathLenConstraintTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt
new file mode 100644
index 0000000..634a08e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000CRLnextUpdateTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt
new file mode 100644
index 0000000..88916af
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Invalidpre2000UTCEEnotAfterDateTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt
new file mode 100644
index 0000000..38f98e4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt
new file mode 100644
index 0000000..ca3ea17
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/InvalidrequireExplicitPolicyTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/LongSerialNumberCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/LongSerialNumberCACert.crt
new file mode 100644
index 0000000..6aaf3d0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/LongSerialNumberCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/Mapping1to2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Mapping1to2CACert.crt
new file mode 100644
index 0000000..a458115
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Mapping1to2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt
new file mode 100644
index 0000000..812da59
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingFromanyPolicyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingToanyPolicyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingToanyPolicyCACert.crt
new file mode 100644
index 0000000..42effeb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MappingToanyPolicyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt
new file mode 100644
index 0000000..17ebf25
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/MissingbasicConstraintsCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/NameOrderingCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NameOrderingCACert.crt
new file mode 100644
index 0000000..6b744db
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NameOrderingCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/NegativeSerialNumberCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NegativeSerialNumberCACert.crt
new file mode 100644
index 0000000..57fc933
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NegativeSerialNumberCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoCRLCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoCRLCACert.crt
new file mode 100644
index 0000000..acd908c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoCRLCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoPoliciesCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoPoliciesCACert.crt
new file mode 100644
index 0000000..5e2a3fc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoPoliciesCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt
new file mode 100644
index 0000000..bf4f814
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/NoissuingDistributionPointCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt
new file mode 100644
index 0000000..c9fb043
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/OldCRLnextUpdateCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt
new file mode 100644
index 0000000..56d136c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/OverlappingPoliciesTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3CACert.crt
new file mode 100644
index 0000000..f9ed7b7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subCACert.crt
new file mode 100644
index 0000000..2029d6b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt
new file mode 100644
index 0000000..50e7fcd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P12Mapping1to3subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234CACert.crt
new file mode 100644
index 0000000..d7b3028
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234subCACert.crt
new file mode 100644
index 0000000..8648dde
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1Mapping1to234subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt
new file mode 100644
index 0000000..85e39fe
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/P1anyPolicyMapping1to2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt
new file mode 100644
index 0000000..5abbb78
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PanyPolicyMapping1to2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234CACert.crt
new file mode 100644
index 0000000..9a5eb5b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt
new file mode 100644
index 0000000..9b38545
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subCAP123Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt
new file mode 100644
index 0000000..4990a9b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP1234subsubCAP123P12Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123CACert.crt
new file mode 100644
index 0000000..03509d1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt
new file mode 100644
index 0000000..0009819
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subCAP12Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt
new file mode 100644
index 0000000..669c181
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt
new file mode 100644
index 0000000..faa7516
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubCAP12P2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt
new file mode 100644
index 0000000..44346d5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP123subsubsubCAP12P2P1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12CACert.crt
new file mode 100644
index 0000000..27bf524
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt
new file mode 100644
index 0000000..9a24328
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subCAP1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt
new file mode 100644
index 0000000..49cc0ed
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP12subsubCAP1P2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt
new file mode 100644
index 0000000..ccbedc6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCACert.crt
new file mode 100644
index 0000000..ce66a79
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP2subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP3CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP3CACert.crt
new file mode 100644
index 0000000..90c4d26
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/PoliciesP3CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt
new file mode 100644
index 0000000..fa0e1c8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280MandatoryAttributeTypesCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt
new file mode 100644
index 0000000..973373b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RFC3280OptionalAttributeTypesCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/RevokedsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RevokedsubCACert.crt
new file mode 100644
index 0000000..edbd547
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RevokedsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt
new file mode 100644
index 0000000..658f20c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/RolloverfromPrintableStringtoUTF8StringCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt
new file mode 100644
index 0000000..67135a6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CRLSigningCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt
new file mode 100644
index 0000000..c05f92c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCA2CertificateSigningCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt
new file mode 100644
index 0000000..8c7200f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCRLSigningCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt
new file mode 100644
index 0000000..10deedd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/SeparateCertificateandCRLKeysCertificateSigningCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/TrustAnchorRootCertificate.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/TrustAnchorRootCertificate.crt
new file mode 100644
index 0000000..21f520e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/TrustAnchorRootCertificate.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/TwoCRLsCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/TwoCRLsCACert.crt
new file mode 100644
index 0000000..c6389d3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/TwoCRLsCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UIDCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UIDCACert.crt
new file mode 100644
index 0000000..d852bc0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UIDCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt
new file mode 100644
index 0000000..c59715d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringCaseInsensitiveMatchCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt
new file mode 100644
index 0000000..68d49e0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UTF8StringEncodedNamesCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt
new file mode 100644
index 0000000..8c81c37
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLEntryExtensionCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt
new file mode 100644
index 0000000..db7d39e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UnknownCRLExtensionCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt
new file mode 100644
index 0000000..e912cdf
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest15EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt
new file mode 100644
index 0000000..ec04e1f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest16EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt
new file mode 100644
index 0000000..f78a47d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest17EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt
new file mode 100644
index 0000000..cc5cf5a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest18EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt
new file mode 100644
index 0000000..3df534a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/UserNoticeQualifierTest19EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt
new file mode 100644
index 0000000..034de7f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedCRLSigningKeyTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt
new file mode 100644
index 0000000..199afb7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt
new file mode 100644
index 0000000..d432316
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedNewWithOldTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt
new file mode 100644
index 0000000..b54a8b0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidBasicSelfIssuedOldWithNewTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt
new file mode 100644
index 0000000..26985c9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidCertificatePathTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt
new file mode 100644
index 0000000..ec7d43d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest30EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt
new file mode 100644
index 0000000..ed88860
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNSnameConstraintsTest32EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt
new file mode 100644
index 0000000..73759dc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNandRFC822nameConstraintsTest27EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt
new file mode 100644
index 0000000..1af47ba
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt
new file mode 100644
index 0000000..ff249f0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt
new file mode 100644
index 0000000..b658d67
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest18EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt
new file mode 100644
index 0000000..f4e2b84
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest19EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt
new file mode 100644
index 0000000..4c86f9b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt
new file mode 100644
index 0000000..beb4013
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt
new file mode 100644
index 0000000..b68b6f7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt
new file mode 100644
index 0000000..9aff6e8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDNnameConstraintsTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt
new file mode 100644
index 0000000..8fe2af4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSAParameterInheritanceTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt
new file mode 100644
index 0000000..5b1cbc8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidDSASignaturesTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt
new file mode 100644
index 0000000..a22f2e6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimeCRLnextUpdateTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt
new file mode 100644
index 0000000..15689c1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotAfterDateTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt
new file mode 100644
index 0000000..385bb1e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidGeneralizedTimenotBeforeDateTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt
new file mode 100644
index 0000000..6706cf1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest22EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt
new file mode 100644
index 0000000..bea72fe
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest24EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt
new file mode 100644
index 0000000..994c90a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidIDPwithindirectCRLTest25EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt
new file mode 100644
index 0000000..11ba787
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest16EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt
new file mode 100644
index 0000000..75504db
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidLongSerialNumberTest17EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt
new file mode 100644
index 0000000..5b63387
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingCapitalizationTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt
new file mode 100644
index 0000000..2aef73c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt
new file mode 100644
index 0000000..6890cdd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameChainingWhitespaceTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt
new file mode 100644
index 0000000..3cddea4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNameUIDsTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt
new file mode 100644
index 0000000..139a086
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNegativeSerialNumberTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt
new file mode 100644
index 0000000..bd8ca38
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidNoissuingDistributionPointTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt
new file mode 100644
index 0000000..9d19ad1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt
new file mode 100644
index 0000000..76b9fe5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest12EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt
new file mode 100644
index 0000000..7db3305
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt
new file mode 100644
index 0000000..57bf426
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt
new file mode 100644
index 0000000..436cb9e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt
new file mode 100644
index 0000000..c835b0b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt
new file mode 100644
index 0000000..faaeb9e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt
new file mode 100644
index 0000000..2cd4433
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt
new file mode 100644
index 0000000..4debc29
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidPolicyMappingTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt
new file mode 100644
index 0000000..c3e9776
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280MandatoryAttributeTypesTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt
new file mode 100644
index 0000000..f33c9d5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC3280OptionalAttributeTypesTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt
new file mode 100644
index 0000000..743e9eb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest21EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt
new file mode 100644
index 0000000..f8703ed
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest23EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt
new file mode 100644
index 0000000..e89ae7f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRFC822nameConstraintsTest25EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt
new file mode 100644
index 0000000..924d2f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidRolloverfromPrintableStringtoUTF8StringTest10EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt
new file mode 100644
index 0000000..2e7e995
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt
new file mode 100644
index 0000000..7640247
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitAnyPolicyTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt
new file mode 100644
index 0000000..b4b282d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedinhibitPolicyMappingTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt
new file mode 100644
index 0000000..0bad35f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest15EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt
new file mode 100644
index 0000000..1535ef8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedpathLenConstraintTest17EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt
new file mode 100644
index 0000000..781ce0d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSelfIssuedrequireExplicitPolicyTest6EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt
new file mode 100644
index 0000000..fda1819
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidSeparateCertificateandCRLKeysTest19EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt
new file mode 100644
index 0000000..e04433a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidTwoCRLsTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt
new file mode 100644
index 0000000..b554f91
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest34EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt
new file mode 100644
index 0000000..8b1f00f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidURInameConstraintsTest36EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt
new file mode 100644
index 0000000..8a9d0ca
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringCaseInsensitiveMatchTest11EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt
new file mode 100644
index 0000000..c901690
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUTF8StringEncodedNamesTest9EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt
new file mode 100644
index 0000000..6ee8d1e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidUnknownNotCriticalCertificateExtensionTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt
new file mode 100644
index 0000000..543710f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidbasicConstraintsNotCriticalTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt
new file mode 100644
index 0000000..1448aa4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest28EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt
new file mode 100644
index 0000000..ec442e1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest29EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt
new file mode 100644
index 0000000..2dc2367
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest30EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt
new file mode 100644
index 0000000..65b2844
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidcRLIssuerTest33EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt
new file mode 100644
index 0000000..0d24df0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt
new file mode 100644
index 0000000..2bdaaf2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt
new file mode 100644
index 0000000..3f67921
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt
new file mode 100644
index 0000000..6586128
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddeltaCRLTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt
new file mode 100644
index 0000000..487cc2f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt
new file mode 100644
index 0000000..3782e79
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt
new file mode 100644
index 0000000..07a8c49
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest5EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt
new file mode 100644
index 0000000..948f37f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValiddistributionPointTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt
new file mode 100644
index 0000000..dc61d52
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitAnyPolicyTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt
new file mode 100644
index 0000000..fc432a1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt
new file mode 100644
index 0000000..dce6927
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidinhibitPolicyMappingTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt
new file mode 100644
index 0000000..bddbb9a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidkeyUsageNotCriticalTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt
new file mode 100644
index 0000000..f35f5de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlyContainsCACertsTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt
new file mode 100644
index 0000000..7c0e1de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest18EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt
new file mode 100644
index 0000000..f3a811c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidonlySomeReasonsTest19EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt
new file mode 100644
index 0000000..dcf8834
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest13EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt
new file mode 100644
index 0000000..66fe256
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest14EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt
new file mode 100644
index 0000000..5f689ea
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest7EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt
new file mode 100644
index 0000000..2357beb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidpathLenConstraintTest8EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt
new file mode 100644
index 0000000..5a61499
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/Validpre2000UTCnotBeforeDateTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt
new file mode 100644
index 0000000..1039926
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest1EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt
new file mode 100644
index 0000000..451c2d8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest2EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt
new file mode 100644
index 0000000..a2fa2f1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/ValidrequireExplicitPolicyTest4EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/WrongCRLCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/WrongCRLCACert.crt
new file mode 100644
index 0000000..4cc5195
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/WrongCRLCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/anyPolicyCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/anyPolicyCACert.crt
new file mode 100644
index 0000000..4d9fb79
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/anyPolicyCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt
new file mode 100644
index 0000000..12a8b50
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsCriticalcAFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt
new file mode 100644
index 0000000..8f9da1e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt
new file mode 100644
index 0000000..ca61262
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/basicConstraintsNotCriticalcAFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA1Cert.crt
new file mode 100644
index 0000000..47f74eb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA2Cert.crt
new file mode 100644
index 0000000..a99dd40
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA3Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA3Cert.crt
new file mode 100644
index 0000000..eeaaa36
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLCA3Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt
new file mode 100644
index 0000000..5ec06b3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/deltaCRLIndicatorNoBaseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint1CACert.crt
new file mode 100644
index 0000000..1e74bed
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint2CACert.crt
new file mode 100644
index 0000000..a6d37be
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/distributionPoint2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA1Cert.crt
new file mode 100644
index 0000000..ef079f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA2Cert.crt
new file mode 100644
index 0000000..4bfc0b5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3Cert.crt
new file mode 100644
index 0000000..f0787f0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt
new file mode 100644
index 0000000..f808993
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA3cRLIssuerCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4Cert.crt
new file mode 100644
index 0000000..6ebe43c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt
new file mode 100644
index 0000000..0468b08
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA4cRLIssuerCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA5Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA5Cert.crt
new file mode 100644
index 0000000..90ba7d7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA5Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA6Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA6Cert.crt
new file mode 100644
index 0000000..3c5781e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/indirectCRLCA6Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt
new file mode 100644
index 0000000..4749689
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy0CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt
new file mode 100644
index 0000000..8d35b0e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt
new file mode 100644
index 0000000..0362dde
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt
new file mode 100644
index 0000000..1d24bc1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1SelfIssuedsubCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt
new file mode 100644
index 0000000..af02467
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt
new file mode 100644
index 0000000..e8590f7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt
new file mode 100644
index 0000000..75bc59e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subCAIAP5Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt
new file mode 100644
index 0000000..cbf40ff
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy1subsubCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt
new file mode 100644
index 0000000..3765f6e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt
new file mode 100644
index 0000000..f75006d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt
new file mode 100644
index 0000000..f2898ea
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicy5subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt
new file mode 100644
index 0000000..850d649
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitAnyPolicyTest3EE.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt
new file mode 100644
index 0000000..b4934e8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt
new file mode 100644
index 0000000..79f45b8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping0subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt
new file mode 100644
index 0000000..57dd683
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt
new file mode 100644
index 0000000..1e6bd70
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt
new file mode 100644
index 0000000..e683468
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subCAIPM5Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt
new file mode 100644
index 0000000..f73f4d2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt
new file mode 100644
index 0000000..fe32eda
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P12subsubCAIPM5Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt
new file mode 100644
index 0000000..b3bff46
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt
new file mode 100644
index 0000000..399bd82
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt
new file mode 100644
index 0000000..cd2ce94
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1SelfIssuedsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt
new file mode 100644
index 0000000..31d9af5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt
new file mode 100644
index 0000000..13e78f0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping1P1subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt
new file mode 100644
index 0000000..86ea426
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt
new file mode 100644
index 0000000..788622c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt
new file mode 100644
index 0000000..d4a025e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt
new file mode 100644
index 0000000..2c0e6e8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/inhibitPolicyMapping5subsubsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt
new file mode 100644
index 0000000..a50545a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalcRLSignFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt
new file mode 100644
index 0000000..f6824d3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageCriticalkeyCertSignFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt
new file mode 100644
index 0000000..344f7d9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt
new file mode 100644
index 0000000..c02d6f4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalcRLSignFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt
new file mode 100644
index 0000000..b9c46b5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/keyUsageNotCriticalkeyCertSignFalseCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1CACert.crt
new file mode 100644
index 0000000..5379f1f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt
new file mode 100644
index 0000000..75f1f7e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt
new file mode 100644
index 0000000..670291b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt
new file mode 100644
index 0000000..a010eee
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt
new file mode 100644
index 0000000..b31c28a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN1subCA3Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN2CACert.crt
new file mode 100644
index 0000000..3aab55b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3CACert.crt
new file mode 100644
index 0000000..f1af18e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt
new file mode 100644
index 0000000..e40c5f0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt
new file mode 100644
index 0000000..9424745
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN3subCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN4CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN4CACert.crt
new file mode 100644
index 0000000..141eb72
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN4CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN5CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN5CACert.crt
new file mode 100644
index 0000000..a0d0628
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDN5CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt
new file mode 100644
index 0000000..10f0b35
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt
new file mode 100644
index 0000000..83fabc5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsDNS2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt
new file mode 100644
index 0000000..07fcc37
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt
new file mode 100644
index 0000000..2001bfa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt
new file mode 100644
index 0000000..e372369
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsRFC822CA3Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI1CACert.crt
new file mode 100644
index 0000000..d0dbca5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI2CACert.crt
new file mode 100644
index 0000000..bf988e6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/nameConstraintsURI2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt
new file mode 100644
index 0000000..6855fbe
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsAttributeCertsCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsCACertsCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsCACertsCACert.crt
new file mode 100644
index 0000000..055d8aa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsCACertsCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt
new file mode 100644
index 0000000..f8fc85e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlyContainsUserCertsCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt
new file mode 100644
index 0000000..26ee389
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt
new file mode 100644
index 0000000..3c444e1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt
new file mode 100644
index 0000000..3b09699
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA3Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt
new file mode 100644
index 0000000..4889d5c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/onlySomeReasonsCA4Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0CACert.crt
new file mode 100644
index 0000000..73c9433
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt
new file mode 100644
index 0000000..f66228e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt
new file mode 100644
index 0000000..c5cdea3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCA2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCACert.crt
new file mode 100644
index 0000000..c51de22
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint0subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1CACert.crt
new file mode 100644
index 0000000..b1da15b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt
new file mode 100644
index 0000000..02aeffa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt
new file mode 100644
index 0000000..0a94f5f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1SelfIssuedsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1subCACert.crt
new file mode 100644
index 0000000..a84fb53
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint1subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6CACert.crt
new file mode 100644
index 0000000..d89052b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt
new file mode 100644
index 0000000..4b22016
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA0Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt
new file mode 100644
index 0000000..b25ba34
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA1Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt
new file mode 100644
index 0000000..ca87ee8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subCA4Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt
new file mode 100644
index 0000000..2b88eb6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA00Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt
new file mode 100644
index 0000000..de511c4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA11Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt
new file mode 100644
index 0000000..c6e6096
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubCA41Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt
new file mode 100644
index 0000000..9c9dc4e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA11XCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt
new file mode 100644
index 0000000..2729261
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pathLenConstraint6subsubsubCA41XCert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt
new file mode 100644
index 0000000..1a79b81
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/pre2000CRLnextUpdateCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt
new file mode 100644
index 0000000..0eb93be
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt
new file mode 100644
index 0000000..f96129e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt
new file mode 100644
index 0000000..c0d9b49
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt
new file mode 100644
index 0000000..497d53a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy0subsubsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt
new file mode 100644
index 0000000..b3406b1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt
new file mode 100644
index 0000000..1544bbb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt
new file mode 100644
index 0000000..0166d99
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt
new file mode 100644
index 0000000..8018f6a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy10subsubsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt
new file mode 100644
index 0000000..7ec4e49
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt
new file mode 100644
index 0000000..285a05c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt
new file mode 100644
index 0000000..f29b37f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2SelfIssuedsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt
new file mode 100644
index 0000000..a1f20a3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy2subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt
new file mode 100644
index 0000000..c2a9c46
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt
new file mode 100644
index 0000000..9f9ea5b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt
new file mode 100644
index 0000000..3d0f278
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt
new file mode 100644
index 0000000..a14f9d4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy4subsubsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt
new file mode 100644
index 0000000..ef2010b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt
new file mode 100644
index 0000000..99d31d1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt
new file mode 100644
index 0000000..99afa4d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt
new file mode 100644
index 0000000..9abe48d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy5subsubsubCACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt
new file mode 100644
index 0000000..cac6bb6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7CACert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt
new file mode 100644
index 0000000..d55d884
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subCARE2Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt
new file mode 100644
index 0000000..1c9aec8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubCARE2RE4Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt
new file mode 100644
index 0000000..ecd5f45
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/certs/requireExplicitPolicy7subsubsubCARE2RE4Cert.crt differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl
new file mode 100644
index 0000000..d4871b5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLIssuerNameCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLSignatureCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLSignatureCACRL.crl
new file mode 100644
index 0000000..b1658c3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadCRLSignatureCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadSignedCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadSignedCACRL.crl
new file mode 100644
index 0000000..e0ded9b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadSignedCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotAfterDateCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotAfterDateCACRL.crl
new file mode 100644
index 0000000..1ec2a0e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotAfterDateCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl
new file mode 100644
index 0000000..1a96d0f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BadnotBeforeDateCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl
new file mode 100644
index 0000000..fed4864
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl
new file mode 100644
index 0000000..053471f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedCRLSigningKeyCRLCertCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl
new file mode 100644
index 0000000..7370ed2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedNewKeyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl
new file mode 100644
index 0000000..dee6183
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl
new file mode 100644
index 0000000..4e7e014
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/BasicSelfIssuedOldKeySelfIssuedCertCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSACACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSACACRL.crl
new file mode 100644
index 0000000..46463c8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSACACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl
new file mode 100644
index 0000000..5bf7245
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/DSAParametersInheritedCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl
new file mode 100644
index 0000000..40387d3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GeneralizedTimeCRLnextUpdateCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodCACRL.crl
new file mode 100644
index 0000000..2fdc3cc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCACRL.crl
new file mode 100644
index 0000000..963d703
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl
new file mode 100644
index 0000000..9c5d1b2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/GoodsubCAPanyPolicyMapping1to2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/LongSerialNumberCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/LongSerialNumberCACRL.crl
new file mode 100644
index 0000000..55f39b8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/LongSerialNumberCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/Mapping1to2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/Mapping1to2CACRL.crl
new file mode 100644
index 0000000..36e07e1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/Mapping1to2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl
new file mode 100644
index 0000000..025b6bb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingFromanyPolicyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl
new file mode 100644
index 0000000..99f1253
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MappingToanyPolicyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl
new file mode 100644
index 0000000..f91729c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/MissingbasicConstraintsCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/NameOrderCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NameOrderCACRL.crl
new file mode 100644
index 0000000..4cd2015
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NameOrderCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl
new file mode 100644
index 0000000..99514d7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NegativeSerialNumberCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoPoliciesCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoPoliciesCACRL.crl
new file mode 100644
index 0000000..b77586b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoPoliciesCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl
new file mode 100644
index 0000000..c7d5b1d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/NoissuingDistributionPointCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl
new file mode 100644
index 0000000..f121dff
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/OldCRLnextUpdateCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3CACRL.crl
new file mode 100644
index 0000000..451d198
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl
new file mode 100644
index 0000000..b063e6b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl
new file mode 100644
index 0000000..6dcdf05
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P12Mapping1to3subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234CACRL.crl
new file mode 100644
index 0000000..70febec
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl
new file mode 100644
index 0000000..8ee7799
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1Mapping1to234subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl
new file mode 100644
index 0000000..8cf52dc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/P1anyPolicyMapping1to2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl
new file mode 100644
index 0000000..51482de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PanyPolicyMapping1to2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234CACRL.crl
new file mode 100644
index 0000000..48c6b1a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl
new file mode 100644
index 0000000..aa84263
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subCAP123CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl
new file mode 100644
index 0000000..ae1a019
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP1234subsubCAP123P12CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123CACRL.crl
new file mode 100644
index 0000000..deb3706
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl
new file mode 100644
index 0000000..ecd65f8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subCAP12CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl
new file mode 100644
index 0000000..51f09f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP12P1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl
new file mode 100644
index 0000000..5d6fb36
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubCAP2P2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl
new file mode 100644
index 0000000..07908f6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP123subsubsubCAP12P2P1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12CACRL.crl
new file mode 100644
index 0000000..5b090b0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl
new file mode 100644
index 0000000..d2f29b7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subCAP1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl
new file mode 100644
index 0000000..bd4cf75
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP12subsubCAP1P2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl
new file mode 100644
index 0000000..774bc73
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCACRL.crl
new file mode 100644
index 0000000..7d7ba76
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP2subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP3CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP3CACRL.crl
new file mode 100644
index 0000000..9d81c6d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/PoliciesP3CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl
new file mode 100644
index 0000000..63ed655
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280MandatoryAttributeTypesCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl
new file mode 100644
index 0000000..e088ab1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RFC3280OptionalAttributeTypesCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/RevokedsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RevokedsubCACRL.crl
new file mode 100644
index 0000000..c77ffa3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RevokedsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl
new file mode 100644
index 0000000..c7f5c7a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/RolloverfromPrintableStringtoUTF8StringCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl
new file mode 100644
index 0000000..a85f99f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl
new file mode 100644
index 0000000..4d159dd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/SeparateCertificateandCRLKeysCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/TrustAnchorRootCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TrustAnchorRootCRL.crl
new file mode 100644
index 0000000..3ba3df6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TrustAnchorRootCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCABadCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCABadCRL.crl
new file mode 100644
index 0000000..fba92fa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCABadCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl
new file mode 100644
index 0000000..fcb7488
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/TwoCRLsCAGoodCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/UIDCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UIDCACRL.crl
new file mode 100644
index 0000000..0da091a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UIDCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl
new file mode 100644
index 0000000..9ee2a23
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringCaseInsensitiveMatchCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl
new file mode 100644
index 0000000..3d7de00
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UTF8StringEncodedNamesCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl
new file mode 100644
index 0000000..efbdae4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLEntryExtensionCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl
new file mode 100644
index 0000000..de71113
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/UnknownCRLExtensionCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/WrongCRLCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/WrongCRLCACRL.crl
new file mode 100644
index 0000000..3ba3df6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/WrongCRLCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/anyPolicyCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/anyPolicyCACRL.crl
new file mode 100644
index 0000000..8506ea1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/anyPolicyCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl
new file mode 100644
index 0000000..15a7e3d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsCriticalcAFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl
new file mode 100644
index 0000000..9e5ac62
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl
new file mode 100644
index 0000000..dfbbec9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/basicConstraintsNotCriticalcAFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1CRL.crl
new file mode 100644
index 0000000..fb562aa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl
new file mode 100644
index 0000000..9a76c5c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA1deltaCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2CRL.crl
new file mode 100644
index 0000000..36d66fe
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl
new file mode 100644
index 0000000..713d54a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA2deltaCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3CRL.crl
new file mode 100644
index 0000000..4527c9a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl
new file mode 100644
index 0000000..bfb3c1d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLCA3deltaCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl
new file mode 100644
index 0000000..b9a591e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/deltaCRLIndicatorNoBaseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint1CACRL.crl
new file mode 100644
index 0000000..1be74de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint2CACRL.crl
new file mode 100644
index 0000000..5bdc149
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/distributionPoint2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA1CRL.crl
new file mode 100644
index 0000000..6eed456
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3CRL.crl
new file mode 100644
index 0000000..02be179
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl
new file mode 100644
index 0000000..166a457
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA3cRLIssuerCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl
new file mode 100644
index 0000000..b870a7f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA4cRLIssuerCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA5CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA5CRL.crl
new file mode 100644
index 0000000..25c2e81
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/indirectCRLCA5CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl
new file mode 100644
index 0000000..301f745
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy0CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl
new file mode 100644
index 0000000..ab13645
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl
new file mode 100644
index 0000000..46c0e0c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl
new file mode 100644
index 0000000..1ee4b77
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl
new file mode 100644
index 0000000..af4fff0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subCAIAP5CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl
new file mode 100644
index 0000000..3b6b35c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy1subsubCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl
new file mode 100644
index 0000000..07f5e3d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl
new file mode 100644
index 0000000..373bdeb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl
new file mode 100644
index 0000000..e56b61c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitAnyPolicy5subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl
new file mode 100644
index 0000000..1ebad70
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl
new file mode 100644
index 0000000..e3f4f97
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping0subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl
new file mode 100644
index 0000000..5291d66
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl
new file mode 100644
index 0000000..9c155a9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl
new file mode 100644
index 0000000..dc7fe68
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subCAIPM5CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl
new file mode 100644
index 0000000..9fcab42
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl
new file mode 100644
index 0000000..ebcdc5b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P12subsubCAIPM5CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl
new file mode 100644
index 0000000..36c2b79
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl
new file mode 100644
index 0000000..1fa7ac9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl
new file mode 100644
index 0000000..3b1ac99
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping1P1subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl
new file mode 100644
index 0000000..a19deb7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl
new file mode 100644
index 0000000..c3ef691
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl
new file mode 100644
index 0000000..45df218
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl
new file mode 100644
index 0000000..3ca93d4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/inhibitPolicyMapping5subsubsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl
new file mode 100644
index 0000000..6f02f80
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalcRLSignFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl
new file mode 100644
index 0000000..4abda76
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageCriticalkeyCertSignFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl
new file mode 100644
index 0000000..358e4e6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl
new file mode 100644
index 0000000..707c73c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalcRLSignFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl
new file mode 100644
index 0000000..5e817b6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/keyUsageNotCriticalkeyCertSignFalseCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl
new file mode 100644
index 0000000..10c7389
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl
new file mode 100644
index 0000000..9d33b7c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl
new file mode 100644
index 0000000..7a3949e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl
new file mode 100644
index 0000000..22aa2f9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN1subCA3CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl
new file mode 100644
index 0000000..da6fe6f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl
new file mode 100644
index 0000000..83fd3a5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl
new file mode 100644
index 0000000..8c6fb50
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl
new file mode 100644
index 0000000..1797663
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN3subCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl
new file mode 100644
index 0000000..ae9f73a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN4CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl
new file mode 100644
index 0000000..46dbb88
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDN5CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl
new file mode 100644
index 0000000..94fa45e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl
new file mode 100644
index 0000000..2140931
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsDNS2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl
new file mode 100644
index 0000000..a4b0473
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl
new file mode 100644
index 0000000..2042f6f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl
new file mode 100644
index 0000000..8f207e5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsRFC822CA3CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl
new file mode 100644
index 0000000..b19c9de
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl
new file mode 100644
index 0000000..3dbc011
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/nameConstraintsURI2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl
new file mode 100644
index 0000000..0993754
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsAttributeCertsCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl
new file mode 100644
index 0000000..621dfa9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsCACertsCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl
new file mode 100644
index 0000000..1aee7c2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlyContainsUserCertsCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl
new file mode 100644
index 0000000..3d5ff65
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1compromiseCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl
new file mode 100644
index 0000000..83cce82
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA1otherreasonsCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl
new file mode 100644
index 0000000..eb408f2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL1.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl
new file mode 100644
index 0000000..e333d26
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA2CRL2.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl
new file mode 100644
index 0000000..6837068
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3compromiseCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl
new file mode 100644
index 0000000..ef4ee3e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA3otherreasonsCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl
new file mode 100644
index 0000000..45fcc0b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4compromiseCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl
new file mode 100644
index 0000000..0fca681
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/onlySomeReasonsCA4otherreasonsCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0CACRL.crl
new file mode 100644
index 0000000..1e52e65
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl
new file mode 100644
index 0000000..69488c7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCA2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl
new file mode 100644
index 0000000..0029579
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint0subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1CACRL.crl
new file mode 100644
index 0000000..9c06980
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl
new file mode 100644
index 0000000..61d0076
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint1subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6CACRL.crl
new file mode 100644
index 0000000..779c2b7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl
new file mode 100644
index 0000000..30fee13
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA0CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl
new file mode 100644
index 0000000..71eafbb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA1CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl
new file mode 100644
index 0000000..8d14b0c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subCA4CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl
new file mode 100644
index 0000000..24ecdde
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA00CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl
new file mode 100644
index 0000000..51b4ab7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA11CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl
new file mode 100644
index 0000000..9e4e181
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubCA41CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl
new file mode 100644
index 0000000..5891e63
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA11XCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl
new file mode 100644
index 0000000..217e5e5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pathLenConstraint6subsubsubCA41XCRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl
new file mode 100644
index 0000000..6315186
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/pre2000CRLnextUpdateCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl
new file mode 100644
index 0000000..5ac2d27
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl
new file mode 100644
index 0000000..569ff3e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl
new file mode 100644
index 0000000..c614cbb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl
new file mode 100644
index 0000000..910c035
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy0subsubsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl
new file mode 100644
index 0000000..7bfbf76
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl
new file mode 100644
index 0000000..bc4845d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl
new file mode 100644
index 0000000..802a652
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl
new file mode 100644
index 0000000..6f84d39
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy10subsubsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl
new file mode 100644
index 0000000..e14cdaa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl
new file mode 100644
index 0000000..8830917
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy2subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl
new file mode 100644
index 0000000..c6817a3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl
new file mode 100644
index 0000000..d1f5ad1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl
new file mode 100644
index 0000000..7203b19
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl
new file mode 100644
index 0000000..467e004
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy4subsubsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl
new file mode 100644
index 0000000..96848db
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl
new file mode 100644
index 0000000..8bb7c1d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl
new file mode 100644
index 0000000..143dab5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl
new file mode 100644
index 0000000..8a9c8b3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy5subsubsubCACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl
new file mode 100644
index 0000000..43870fb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7CACRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl
new file mode 100644
index 0000000..48c70c0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subCARE2CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl
new file mode 100644
index 0000000..3808af6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubCARE2RE4CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl
new file mode 100644
index 0000000..4ed5b0a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/PKITS/crls/requireExplicitPolicy7subsubsubCARE2RE4CRL.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/asn1/masterlist-content.data b/BouncyCastle.AxCrypt/test/data/asn1/masterlist-content.data
new file mode 100644
index 0000000..d462f0d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/asn1/masterlist-content.data differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignData.data b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignData.data
new file mode 100644
index 0000000..ab51e84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignData.data
@@ -0,0 +1 @@
+This is a test message
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1.sig
new file mode 100644
index 0000000..1ecfd01
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1Enc.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1Enc.sig
new file mode 100644
index 0000000..2f7e7b6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA1Enc.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256.sig
new file mode 100644
index 0000000..114c592
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256Enc.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256Enc.sig
new file mode 100644
index 0000000..28bb811
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA256Enc.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512.sig
new file mode 100644
index 0000000..eb3429b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512Enc.sig b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512Enc.sig
new file mode 100644
index 0000000..91556c6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/PSSSignDataSHA512Enc.sig differ
diff --git a/BouncyCastle.AxCrypt/test/data/cms/sigs/counterSig.p7m b/BouncyCastle.AxCrypt/test/data/cms/sigs/counterSig.p7m
new file mode 100644
index 0000000..7d82b99
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/cms/sigs/counterSig.p7m differ
diff --git a/BouncyCastle.AxCrypt/test/data/hc256/hc128/ecrypt_HC-128.txt b/BouncyCastle.AxCrypt/test/data/hc256/hc128/ecrypt_HC-128.txt
new file mode 100644
index 0000000..fbc2fbd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/hc256/hc128/ecrypt_HC-128.txt
@@ -0,0 +1,2337 @@
+********************************************************************************
+*                          ECRYPT Stream Cipher Project                        *
+********************************************************************************
+
+Primitive Name: HC-128
+======================
+Profile: S3___
+Key size: 128 bits
+IV size: 128 bits
+
+Test vectors -- set 1
+=====================
+
+(stream is generated by encrypting 512 zero bytes)
+
+Set 1, vector#  0:
+                         key = 80000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 378602B98F32A74847515654AE0DE7ED
+                               8F72BC34776A065103E51595521FFE47
+                               F9AF0A4CB47999CFA26D33BF80954598
+                               9D53DEBFE7A9EFD8B9109CA6EFADDF83
+            stream[192..255] = E7F8DCC6A1D42ECF6A49651F7C610657
+                               B1DF6E58FBEF6A246D6D4CAA83858839
+                               86325BE2B4185B4D63D4BF766C5F4B73
+                               0B89C3CD66018155DFE9D37B6F5C1251
+            stream[256..319] = 6D21763B2FEBADB212AC71388FF93586
+                               48AA1A0E874D3B6932D7F80A5657F88D
+                               A44BDC16AA21E531E3E473CFE6FCA9EE
+                               20739339CE4F2DAC793210C8CC20897F
+            stream[448..511] = 5BB39DF39C64BFA13F2AAE924D3DF4FA
+                               22899838ADB609806C022C36180A3E46
+                               A547CFF7F4DE1151A81AED3646B2D86E
+                               1F0F3C22C92D3459593ED599D1A535DF
+                  xor-digest = 1EFC3423B31F67D397923613A1169F54
+                               A35193C9A31484D48204A8380D19984A
+                               AB3C53E44D0511C1CA13A3823A0B2C24
+                               7602797C533F0D5251CD5FF60D4A4F5E
+
+Set 1, vector#  9:
+                         key = 00400000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 80978AC0647C7C5E3716B3B3DD9A3FD6
+                               EE0EC133F29A0F2F92E3F7AEFFE8CAD2
+                               789DB433255F7A9F2A9D0873B8932032
+                               A7FD7EE6D07C903738B78E88DC173674
+            stream[192..255] = E314E449A75D8CD4FB0BF8BB133915EF
+                               0471D3824CCB9CF828F2086EED1E09EF
+                               78E510E0D7362275CFECE3F2D79F5B37
+                               8C8F21D3817083098E1D3918DC49EB13
+            stream[256..319] = BD9BD906D4AC9B0A0A68C1371DDD0BAB
+                               7D36784577856634034D9A7BAF3A8B06
+                               1C29904A896A82526CCAED7899FCBCE2
+                               619E6AEDA6D79B55C6EE7C97353486F0
+            stream[448..511] = 163E7EDB8F4A866A0E1C991883B2A966
+                               0DF6C547BA4C3E2D59AC014170872C73
+                               220303B5AB4D7321CA0C25DF3E18D5D9
+                               1D6B52A5C2369F4F764B7E4649674F89
+                  xor-digest = 2F1B2356F1149C6EE7694E217332E4CA
+                               33E47D0DB237E71D542A4BFDE033137D
+                               C8085B39215AF06840E542E501FC0584
+                               257B7F6DCD6297CABF03026A95A6E27D
+
+Set 1, vector# 18:
+                         key = 00002000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 94DAB13AE0D2F9A65283C6AE98733110
+                               1C4EE45EC812AD67DDF3D1F026B51B17
+                               2D366C7E3B2D55E5AE7010A279D35B03
+                               83B77E96C6B2434C3E6DDC2401D64AEC
+            stream[192..255] = 8199B6243A278FA6C07B430B6FFAAD83
+                               C2A40A1115DEB693B446504AD35615CD
+                               C4881D06F2EC1EC5C189BC37C0F6AABC
+                               C349FD461023A1B840C40B7E96A481E4
+            stream[256..319] = A2FF8C499364E1E900EAE72A98399585
+                               6C609132B14C83B191D49BF251E73EE2
+                               0FC48469A1E72416F803CCB7C933A880
+                               F8343A8DE2AB9492190E86194680B21C
+            stream[448..511] = C442F7A0791CCC0F7E8D4CC454829E6C
+                               26811BE74AF8BC70276C4901277753CF
+                               E44FACC0ECB82E9E5803CD08A316D9EE
+                               5B0A016185BEEF9FE94A3E64C8BCB161
+                  xor-digest = 53170F85C0661EBB8E0C595C6405CE21
+                               B9F19433C791DB8A71883E4E6BA31656
+                               2268C2110CCF228AF6634A80599B6A0E
+                               24106DBA30C3098EE57A10B1604511E7
+
+Set 1, vector# 27:
+                         key = 00000010000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0D3549E38106BC69495957DE0722C36F
+                               B3362CB8BB2ECAAB49C99AA5455C4DC7
+                               363E990AE7FCAB1F4648413DDC698D79
+                               294F3FF36FD83C299AEE2772D34D057F
+            stream[192..255] = 3239C047E0DA62024EC64B1D8E8A5E0F
+                               6E89062774AB24D2B69A17FC7F4C6EA8
+                               85F71AEEF1B7A36A559EEE29D422CD4E
+                               98733C99CF47472F1E4A406EC58A80EA
+            stream[256..319] = 1B1F13FBB383683E26371ECB23F49D0D
+                               E3B0A224D96A1A87D63A6737614F0415
+                               DBAA27AE8107DA06E5BB62D96FE4502D
+                               7B92EB6B5AF180CE8C2373920C77292B
+            stream[448..511] = CDA9A705E95B0656600EE8CC654127ED
+                               0A8E362FACAC68B18C0C25CA57929F2B
+                               1761F0706FCB0E066338507BD04C7F62
+                               0FC91BB6AD77D569E30547959578216A
+                  xor-digest = 6D339778DCB212787325D09BA20110C9
+                               A9CAE09E5915DFB1F74BA59E9C610FEC
+                               7989F18AF4CE86AC3D135659F46DB2D3
+                               59C08FC80B14E10AEC6B6701F661E86B
+
+Set 1, vector# 36:
+                         key = 00000000080000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A4E7B46F89DD8205C71F6453B1ED3924
+                               5D7FBB100E7EBE4D1D27E69047AF47DB
+                               3575B3A580FB9591A5F794306CDFA3E1
+                               A0A61905827D5ED980F49932A5ABA561
+            stream[192..255] = 364556E21E20C5816ED375B9C12C0603
+                               B680F2A4972EDA77AF198A2F015ECEA4
+                               7171028016B99EEABE1DAA2131711466
+                               6D3C1558218D95A8068E1780BF738C2D
+            stream[256..319] = 84F5E62E1E8D4AD21DFE9B3537172D6E
+                               3F4539DD15B5A55B38373E9787F0A4DE
+                               5F4D90B0D56C0E1F8A5F9C282A1F5567
+                               342BF864960F27E5311A4FBE3B85CDF8
+            stream[448..511] = FB062A1FD5E64D97489F24A4F12193CA
+                               9C6F4711C993C13742EEF14D88009DCD
+                               FA40D295DB8959D1562DE734ED1AEF4C
+                               90D136852F37A4115757F21F40977025
+                  xor-digest = FB8B62297F1B5E510091057F075AD348
+                               54FD949E9E35712E2F455D25AA7EC559
+                               D55FFCC3D6832865EBDA17EEF34A2CCE
+                               C6758E6449BDE9D70B5071B2A1D5094D
+
+Set 1, vector# 45:
+                         key = 00000000000400000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DFAB6AB2296BDEB8D8B3F6A790F3885F
+                               093BAD3BE4E0BD63E43F69535F5E77CA
+                               DBA06B447471B03D6A47D6BCB5AE4D40
+                               03B8AF7738AB8EB4D5B9C6040A434A71
+            stream[192..255] = 9313979FA86022D65C61D902DC0D4F9F
+                               98C1D026B710B03123812FEABEE5C0ED
+                               8973F8B97CF7E281EEE0A5135A01F0B1
+                               4C6DC27B352CB349273EE5E34541C518
+            stream[256..319] = B53E875AA400CB453C7DBF5CEEEE4D69
+                               31763C844FEDD960E5410FC3A5E51B19
+                               7D252502EDBE71D457461A9D0033E26E
+                               C7F78BD9C39580695914941737645754
+            stream[448..511] = DED32F71701CB0AB10C3062F1A15571A
+                               E70F2E3AC7A533CF7C962B2F4C256A9E
+                               12EA7D7F7DEA955DE6C7CA512A7EB4B1
+                               80CE31FDD1F38BD486EF438D52B791A8
+                  xor-digest = B0EBC9D8BCC2DC7E20BBB7063FA84B6C
+                               109A619BE7EC9DF5C9C6182AD692DED1
+                               0F24329DA2E5C346A659F2DF60BA0F2F
+                               E0169D173C4C75D26363A0D7DB40A195
+
+Set 1, vector# 54:
+                         key = 00000000000002000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9D5E9AA4795B8B5E97E415BD1F14E697
+                               3D5E1D148EC12743699A48DADD6EF61A
+                               4643E9A7C2D2F88D50A8B9A63E003367
+                               ADDD8DCC464EB1C0FA6C23D244E725C9
+            stream[192..255] = 8DC91C4A6B3E6B88EB7EE1E0F7345718
+                               6C80BCCEED7197FC98CB118EE13D9AE5
+                               3EC8C6917F38FEE09C5C6F08E475E058
+                               51D1E7D4EF0B24AB263F0AB5656E3E82
+            stream[256..319] = BC2875569BEA6623C7E16A6A87C972C1
+                               1EE3782148A48D51F6D9E32CFB42812A
+                               2D20A318F0D699C9E760159F591EB9DC
+                               9EF3429A2613FD30EF2C839FFFAC5D0C
+            stream[448..511] = 6733FAE7B9AE358748DCD6937D494F21
+                               46315B363CC50E362C5F585FD350C462
+                               BD99DD69F2644043100A9E690302CF26
+                               4436B96CC818B659555DE0ABCBCB911F
+                  xor-digest = ECCE54CD5721D18E47CAE60E30741660
+                               1F03D46F90A1110614728849445E66B9
+                               ADA53954F9E8DCB746CC4BCD4D82EA34
+                               30767E2CF9BE6BF81E19382DB5A7677E
+
+Set 1, vector# 63:
+                         key = 00000000000000010000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A88EADE3DE0EB0BA73CE09E995540BF3
+                               B8DF7485F028B1C3C15D1F813E2C5413
+                               5B004E1804EB6FD248505C998B5F2CCD
+                               B3EC043B40FE7A532981F932D107776F
+            stream[192..255] = D81CAE569DEC3E6D22C83F043B64FC88
+                               0B04116A646BBADC38B28848D17028D3
+                               11535C1AE172CD85A9B2D3ED4D728FCD
+                               0A5289DA14D823578E5B8984AEE42671
+            stream[256..319] = 18FF81D6F5D7678998B48A51CF0D024F
+                               5872A5C1084E20182A8C255938339D34
+                               6798356AD957663C089939F896330C12
+                               747C08E2BF752B4103661B98229FB5CF
+            stream[448..511] = 9B797430B254C3F4DDB6AA211254ED75
+                               13A7403B62D5D1E2452E43DBCC7B50C8
+                               266F82A5155D405A5B7E15E921AD8154
+                               362799FFE25F1E7ADE3434B0862E9D10
+                  xor-digest = 983E10E11689266E4569A99855A4F642
+                               9094FAEBEBCD68434BD771C8528FDC62
+                               D357A379A0D6D78B9543E9A4CCAA42CD
+                               DC719C3C880A358B409477D670F55EBF
+
+Set 1, vector# 72:
+                         key = 00000000000000000080000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7ECBBF2FD6D7E521A15DD022D0988F7E
+                               319AC64A9ED55C72E2817AD91F778221
+                               98A55A9E9BFC9D01C0BF8BCD9828001A
+                               18AED8C48E3F6633FA541B74A1799C62
+            stream[192..255] = 1BC71E27C8EAF24C12E78A4F9FC8E000
+                               625AE2FA2AB74483C8EE3ABB69C77B13
+                               7DF6C9213A1EA8D6557F0C1688154B87
+                               BE22F1B87AEE346AF7AFDE02C4C2C776
+            stream[256..319] = D2AF220214395745FA09AF2FBBCDB112
+                               0A588713476B29479F48B92F278BF39B
+                               3048630F0EC091D1188E7CEFD4C6F8D2
+                               709187581999E5DEE22745D21C03BCA3
+            stream[448..511] = 995534950559F7F3D01A718891ABC639
+                               3D64688DE7FDA76C1DCF2B81F6934EE9
+                               4BE1DE90F720E073DB9E54DC101BF513
+                               5ED06CA4684A73A506553CB8713E4FEC
+                  xor-digest = 2E87F43F3622E1A512D0E540939727EA
+                               A035F7D7C136FFD565BF639C00165F7B
+                               6C33B969DDD106EC9D4CFAB1FA0D5618
+                               FD17C64CC68E94DAF7DB9791B7DE16A9
+
+Set 1, vector# 81:
+                         key = 00000000000000000000400000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2AAC5C088CC1EC5D579779B7EEEB7F9D
+                               AEC2DF6224B8E39F9E74511E4E8CAD0E
+                               59E0BEFCFCFA73DA661B53350A470887
+                               11B1ADC5304481515256C94204EAD340
+            stream[192..255] = AA9240B5E98DD28D7CC6FDF07C61E536
+                               069C5D4B818A96DFF41939A57DF9FE45
+                               32F384A624B236064C1AFF1A37C8CE01
+                               23B87B7903EBB91D6D83C69C684090B5
+            stream[256..319] = FD816941100F6CCA2EFF27C275753702
+                               8B371BB985E878229621CA3D0B4E6BF9
+                               1F74BAF0C05F661C93B819092CF475E0
+                               C61EE25FC5FF6CC9BE274834E718EDC1
+            stream[448..511] = 0A2B3B21DE9AE621B9DA45091AA26213
+                               EE2E560D32FA4CB8ADC6DD1AF7EA11DE
+                               B4905EAC39580A5A89A68F85BED6CFFE
+                               820A79E20265488FBC9E266ADA0C4CFA
+                  xor-digest = 60ABAD1341AA90112B53568014827D64
+                               A4A39E7CCCD78943018C685D0CC4DEB7
+                               EE7A203B7C88ED8996EA7B2EEBBECC7D
+                               86E53A4B5E0646BA59CA88144B032C9F
+
+Set 1, vector# 90:
+                         key = 00000000000000000000002000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CB3DF6C584DC8826BAD57EC5B98D644D
+                               AFE6C749F0463744EE1CB03EC81DDEC4
+                               4B4948C634552BF4760A0976C67BB2D4
+                               C53F7A7805FDCC68C3ADB7ADBDF9B509
+            stream[192..255] = 0ABC3A02DEDCEE79E8C26D3667B085C5
+                               30FD86A2CAB845CCD323075D7D6FD7A7
+                               05E7532A5F630BDC205B1DE61DC29243
+                               A2DDC2750F9AF32EF0CD794EC074AA83
+            stream[256..319] = FC4AD0FCAB98C2F3379E3A3D1B35DEE3
+                               93B60A327A41BD5147DD17F315DBB5F6
+                               625D67ACCF9A460C2CFDAD84403D4163
+                               EFF59D1356C144E6237A09044BCFF8CB
+            stream[448..511] = EFDAD499C277519887424DBEFAD5DB2C
+                               97C97CE5E512871B5CA81D9408F59B39
+                               9E23B24AA57DC934C2F539CBCC6A9EE9
+                               750B3A5D08ACEAFDED87C325D01CE866
+                  xor-digest = 7D8E173BD06363238A383D72422F5FAB
+                               941BA41199C462C2110E29E62350C9AD
+                               15780C3BC2B9092641A4702B9A696430
+                               E38F7D0F6FFD1AE59B82787A3A69CA0E
+
+Set 1, vector# 99:
+                         key = 00000000000000000000000010000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = EBF5E178FA8E2E45F53B73AB15C2D54F
+                               A48DEAC9529BDA434E857A809CC7C0F9
+                               D8F372BAE323FBF79874EC53EAD3928E
+                               DB203A64C601A99BEE4C07473DDD3B23
+            stream[192..255] = D461188EA8C5F22E8649B6FA7B68274C
+                               D97EF513C81DA77CBAC826D9D20D9968
+                               716FBDA415BBF064DBFCB7D5AE12F72D
+                               4DD1FC3670A553EE6F23CFDA400F6D9A
+            stream[256..319] = 031589CA9A8B0C09BD0CB167D3D49C2F
+                               873AA718E0C9B3A3A515A9D196C5382F
+                               BB6CA5E3190FC20084F5A4D22DD92095
+                               8E3A1883E30F7BFB55B40747B495FD49
+            stream[448..511] = CF106A7EB0FD339B8EB67F09E2A27AFE
+                               A4117C472AA64CF1A41850062266B48F
+                               92CB46600E87E811121959B19999BFE9
+                               1C68A664A4C28ACC8AE5E6EA477D0A2F
+                  xor-digest = 2480D3C1DCD26EE2B05D964B3CD526C8
+                               4E39E6FF48EC793FB82F4AF928073D1D
+                               80887F9AED832951D4AB2FDB518B548F
+                               EB5A42FE6454C19FCC101019B598A808
+
+Set 1, vector#108:
+                         key = 00000000000000000000000000080000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2EABC4033A51B3901B6340BE32F808EE
+                               A319582F21A7CF6633570E82AC879B60
+                               3E438847D9E3719EAB71F8E3247FEFA5
+                               C07B2282AA2FA80CEFFA8E076304FEBA
+            stream[192..255] = F178E16CCB405A8025FA50215B109BFC
+                               9CE3A655DAD91BCC64D89BE115D4BC84
+                               261DC0E440DAF6028D3AFEA13C9D53B1
+                               C38E2AA48153CCF3DD9791563E45A98C
+            stream[256..319] = 284E211A092241828DB7204310536167
+                               653D66987537E004201DFF6290CD8C37
+                               84AA31D76477908455CD4E1C51F907AC
+                               69893D7FD3D626989526F4E6891E82A0
+            stream[448..511] = 043F1740552381D9A01C882DD0D542B4
+                               8EE86ECF6B5D2A23B8EAECCA55224664
+                               5702B29F7CAB606417CDCCAFD9B63ACB
+                               CEC56E95C945B72DC457103B2C378A28
+                  xor-digest = 1A56CC2BC61F1A802CDF26A84BD37A9C
+                               86F903637E5A1BB21B5829994628B000
+                               2A356A4D150DC529907786BAABD0C733
+                               4500BE0DDC9D487EC6356B2ACD65946E
+
+Set 1, vector#117:
+                         key = 00000000000000000000000000000400
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BA81D9884075FC9E2F9938392EB10354
+                               1AD1D4A599A6DAC3E33EEC59235C3559
+                               4448E3DAB3B5A5F56DAF7B86B63EF376
+                               3728193CCE74807DC7E26087D87BF7D8
+            stream[192..255] = 1F91ECF0B6E889D6FD6FA97510D2EE3F
+                               91552978AC896D69B10A923F6F5CCA67
+                               8320765AA5CDD2ABB4A5FB3CAF86C76E
+                               12280CABB4E74C8543C9D5B1D9B8268C
+            stream[256..319] = 31BF924BBD38F9FE050E17E50EB66C45
+                               081DC5CF49F0F02610828A91F31D0B29
+                               AAB0D6123D69347ADA5CFB37C8AE5E70
+                               38453B5194EA285F798179A875F75E70
+            stream[448..511] = 78F5C37A21EEBAB00F7A80656D72AE39
+                               5566B8114BA6EC8BCFE8C46D0CEB4C6A
+                               BDE4E4F0F131BAC671F8186821CA01E8
+                               69FAB184E938B93B56D1AA3C1D68D3AB
+                  xor-digest = EFA43D76919EF92EED6AA30B4FD2E37D
+                               461D4377618426C2912493665FBB004E
+                               0C92A654CB660FB709681F460DD61825
+                               C7A7089737F5F5DA10023049A0595DBE
+
+Set 1, vector#126:
+                         key = 00000000000000000000000000000002
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 23C1F447C5496B37512923D74B61CF71
+                               015A25988370C0F4E0E48194E4C3B72D
+                               0C9519F6A88D8AE9DD319A3C9160A6B5
+                               51FFBAF27D374B3E6F624344D06BD06B
+            stream[192..255] = 019E730A2D0DD92CB417B1FCF42D2352
+                               058F3B059E1FA4C489909E0B9B90944D
+                               9816E45E992893244CDEB5EA6AF79703
+                               F70CEC7C3E770D2A8310127B3EEA9026
+            stream[256..319] = 3BA682C375554002E718ECEAE6768648
+                               2442D9643AEB6E4D518A5146263B6BEC
+                               0577A4A0CCD7995F10B7F1312926C613
+                               B4BCFA28D37B85C7FE6CC64A26DBCD47
+            stream[448..511] = 41D18A4275E2E4DBACDD91D3F79A186F
+                               6B2F48BBB64D47186C32910E86914BB8
+                               74688AEE59998D8CF7635DDED58EA9E5
+                               C51DF64956C951C1F9123DC1C97A4027
+                  xor-digest = E7A40A98E52ACDD2CAD780E71312F128
+                               8A73CDDD2CABD28EB767A045871861B7
+                               680C64DE4986F508E8CAA04B49630B3B
+                               DF931CAF478B2C3470E483F3D2EA71A8
+
+Test vectors -- set 2
+=====================
+
+Set 2, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 82001573A003FD3B7FD72FFB0EAF63AA
+                               C62F12DEB629DCA72785A66268EC758B
+                               1EDB36900560898178E0AD009ABF1F49
+                               1330DC1C246E3D6CB264F6900271D59C
+            stream[192..255] = 76F5E28163A6F72F4AB72FCD90C69EED
+                               EF6D5C73539F14E7CA0BF6A9F229F12D
+                               1492EFCFDAD11EE26DE44F0E843178D2
+                               C989D4F21FE9B53C03C12874E83A7026
+            stream[256..319] = 3CDC1D88EDA836767090FB77DAE5ECC0
+                               0F5BF5CA8879733FAC19E8DE5C725636
+                               7E39E8C9C4EFCDD75DFA9660BBBEB584
+                               B5593DFF4566EAC37E857D9B9E21FF06
+            stream[448..511] = 713B389BD7E1651A450C051B77F83A96
+                               DA277A370FCEBC4303A18AB1C5FF5342
+                               B319F0593A67F2BE6DE7D256CEC89F65
+                               61FF60B8AB8621B6720206975269023F
+                  xor-digest = 4943A339E572249ED48A06F45BD60AC5
+                               26F1ED970617DC9DB29EFE99ACEC6C7B
+                               82C8F548503C3DC16E79C4D7D7B7C6C6
+                               08CE84DC170A72286CEA1148D180A7BD
+
+Set 2, vector#  9:
+                         key = 09090909090909090909090909090909
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4C76978E4BC79261F8608B3E5327AEB4
+                               4F2F0305D5F6B6326E0127F00C50DEDB
+                               85F5915ED2D70C9BECA2866AEBE6D154
+                               A4CCD80AC88588CAF24FC805974C96A7
+            stream[192..255] = 5875CA142FA9AC13170031C71A3619EA
+                               ECC3D6E0692AC276E2CA29864643D364
+                               56DFA39E1782D487F49402AE32CB739F
+                               AE267CFC438495B292D21E6B4A21774B
+            stream[256..319] = 8CEB212AE637E8DE29AD64E7D0719338
+                               F41AFEB1F1022F30BE485B348722B7F5
+                               A57DE6F253C6B0828C6FB1EF6C59EEC5
+                               FAC3D7FCBAB8C6BDAE2310CE77ECA503
+            stream[448..511] = 4810F2AEA6804ED4820E5B9E7ADD1F44
+                               37EF320686F108947B42991ACC7C4887
+                               635E57E9AA90EF29F831D7959936DD95
+                               0F466666BB84280764F5557582FAC149
+                  xor-digest = 7EA2FDE204E339B9C85051F22A46587B
+                               3619F4F9AE11426F5470D9EAA1629476
+                               FF156BF2727CB6306E62BABB4A68E9AF
+                               610D50C8034C5D4E23BCAC487F3DCA03
+
+Set 2, vector# 18:
+                         key = 12121212121212121212121212121212
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 38F35C0172088DC537AE80089719655F
+                               E8671884235DB1F6477D776B8DD158A6
+                               F6914C168E9EDF0B1020C63EA1851D2E
+                               FE1A343C98ED4B4B23E52451B9BDC3D6
+            stream[192..255] = E88226EA0CA8B620A68402F83A1475C2
+                               54C875FD5D27C935130FDE6DCE3EA050
+                               4F121A7EBF6B572D6EB41240A65CD001
+                               5007AFF6C2A8827CC0841A6170C08467
+            stream[256..319] = 0ECB78E446AB9C763315031C95E570B5
+                               5A5D89BA13A228B80D86797BE378D766
+                               59B47D48AF0FDB4C3D439311963B0A0E
+                               1311E6FA792B089EE4797D9AD023FF5A
+            stream[448..511] = 44C71180BEDC7E3CD29F80B9922C1733
+                               5D815207E848FD528572CF61612A42E0
+                               AD4AEC01D042461A8C30ED194940F82F
+                               A442DFD9061C03A1B72592894A0C73BA
+                  xor-digest = 127E8501304A0632B8FA27A23BB97321
+                               BCD67F699D39A35A4324D5E8AD368E0D
+                               CF134D13FBBADE2FA930AFCA7D15FEC0
+                               B2682F0B09AAB3373069F6DAB9EA112C
+
+Set 2, vector# 27:
+                         key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B90DA1C325244BDA08C319AA6B4ED7E8
+                               3DEF56BF03ADFB2A46E9041F4498BE2C
+                               4B9F76E7AF98697B2835F2F4D4585320
+                               36844D8FA3F34121D9BF624556A52BCB
+            stream[192..255] = ED912457955FE3EDB032F4E7C452A13D
+                               52361DAA3154A756B1C00B0079DBF782
+                               AD089F2C090691BF7B66695538402EFF
+                               893D27969913F25177C01F4CA2FF5195
+            stream[256..319] = 0127342854571D0640F2C283104FD6E4
+                               4FF9B9198492414C1803E36F01A2E79E
+                               3EF76F350542EFEA11419692B6A708F2
+                               0A6D938306E9212B8F047207E7C5782D
+            stream[448..511] = B297A467A6D2770B2609C7DC1EA505F8
+                               3A36223731550282001144B4DF3363BD
+                               49802CCDF59D22FC7C2CB7913B4FEFB9
+                               49128A2BED699B55D24E5B26C52BE674
+                  xor-digest = 711ED121D562F49A3D3F66FE95540DC1
+                               A58F5703108A7C484A53EDC9FA7455D0
+                               D356D9EA792AC30009754E94CF63493A
+                               8AA3BEADC0E7D671DAC10390C841F9EE
+
+Set 2, vector# 36:
+                         key = 24242424242424242424242424242424
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 38D294B5B1ED0A38C5430A355A5A5949
+                               0137741305AD7EB6159A1B97A956648F
+                               B27C16F507D5D5FF8E2B779BFF22CFD8
+                               DB4C7CF7FA78CBB20445D2F94518174E
+            stream[192..255] = FE70A06921BC304689079DDFB4CD4BBE
+                               FC64B0C8E014A65F6D84A804E8F8F1A1
+                               371D470977F033ADCA960346B189E848
+                               C899CD90446D5074C3C1EE48DD40F0C9
+            stream[256..319] = C9B90ED55AD83A8DE0547000ABD0A633
+                               653ED5D3B62EB16D2C3E176952786205
+                               AA702C32FC37DCDB714D8BB81E488438
+                               43B805F2FF5ECE2E6C0A4A4BA5746561
+            stream[448..511] = 396490C2E87DDA2FC2F9FD4D2E468A91
+                               A826ED3FB2AEE07DAB6E33EBB5D657B3
+                               2488B38BEE6E316DEA6439979112CC62
+                               0989E9907AD83A9479DF253A75FC6683
+                  xor-digest = 5478F54C1B95FFD16C6C873F900181F4
+                               EE33E5CB58CD28259E19645FF36B4419
+                               FF92A289E9C355E769D0CF6F004BB256
+                               E5134627E4E99459CA3916BC1216312E
+
+Set 2, vector# 45:
+                         key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0188DFBDAB2AA5D4996601E8CBC5AEE1
+                               5254491641DCF5DEB7414FC751D52E56
+                               C253A98157200CE0C142C355AB961015
+                               04991380F77C287212145552C000CFA2
+            stream[192..255] = 6957E2069E8F1042C6A46AC8ECAD2439
+                               0DB5739043E911FB9BBE4A7071A88B14
+                               2867E45971D7C19BAAC4333BC176230A
+                               A67A081EA89728380B00F5173E866B89
+            stream[256..319] = B47E8222962EDF8B3CF7E4DF469C81F0
+                               40431EE27D2CCC1C5D2B048C6E986681
+                               9656F8E23714A227341795A9B881A776
+                               9434923C01D25B4B2D60D0EA89580F82
+            stream[448..511] = 89E48ABDB1A7F5BF17EC7304A951B1E5
+                               D152EA7EE181DD9866ABD782C7FCF238
+                               66871D0B1EA30527CC178D0FBB0E6D8A
+                               C5CDAFB27F01B7B6AA68413B3E7DCA6D
+                  xor-digest = DFB99C93E6B26D2F079414A370EFCA10
+                               5468E93AB8983DE0AAA1AEE3F8FCD068
+                               3C20753931A9B13F48F10C9F71F99638
+                               1AACA39469AD3EC6BC8B2ACB1DB9ECC9
+
+Set 2, vector# 54:
+                         key = 36363636363636363636363636363636
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 6EC768666ADE02892FF522A9422F5B3D
+                               D802727755D64C602C5BE156DCCC690D
+                               D0237CF95B191BD29BEE5E030E1EB4B2
+                               CA981BED69F2F4FEBA39C9658450D21A
+            stream[192..255] = D62AED496AD8BC9EAE570843460EFF9F
+                               8CAA155E3B1619341D43D416A89C85EF
+                               2186E398467C6763C6B38AE8AC642391
+                               39FC7D77C5DE1BF0304237527ECEF79E
+            stream[256..319] = FD2A2505BC2484CD26A953A460D43EB3
+                               500DB0572509C1409AFB25DAF7A08E96
+                               8C45901DD9943AC3558FE2D956045AFA
+                               EC7FE93AFA7AC461E348A6FF67DFD8B9
+            stream[448..511] = 1A9AAF97AD789E4003BF48E9B723EBCE
+                               F2DB13513398FF8161D929F64C5603BE
+                               2D0B89D1B94E2C4A91468EF743C2A745
+                               98093DC6EB5069213A1423FBD5526B80
+                  xor-digest = 93DD39B5F82C8B105C9A1D3CA17AEB09
+                               21E77AF3235E3DC1F626D690D9306698
+                               60DB7382B38C6F3EE0F250DBB67E8001
+                               078938ACC2DCDFE3DC5E2F33FB4EEE51
+
+Set 2, vector# 63:
+                         key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 6D05510EF24AC345594E94F58E6F5024
+                               1B40AA1CD6A62F35BC303CACBB263253
+                               CDDF54462EC606D6969E4CC5FB719A7C
+                               107DB872A5119566BF72FE37363E60E8
+            stream[192..255] = A1626164C36C6AB010B9A2B944ED8839
+                               13A3B9522F66429A75F5E30A03961871
+                               26AF86AEF382E3944B0414B274859B4A
+                               93881386E6A3E780802B0E6894739442
+            stream[256..319] = CBC22EEB532BE4B8B80D7F10A00FFFC6
+                               22A02B7426DBF648AF398444B8F8D2FD
+                               E4265F1B50CB43B003DDB0256D9E0A10
+                               99BCDBDE162E8AA37B107B316B9673C3
+            stream[448..511] = A7F2D829EF3BEADAE6D84CA26C81E618
+                               6F70F3D9DA4E208754EFAA5A0441D87C
+                               7AE36AF993E7225A9C68764C87B5DA4C
+                               C08B54A245A296EBF399B91331A6F286
+                  xor-digest = 55A30CB34036E3A22AAE25981272C8F3
+                               6392347B5FCE8101A66023C5B324867B
+                               783EA103A714E749F14375CE64985A0B
+                               8ACECA137560D12E941228D04A968513
+
+Set 2, vector# 72:
+                         key = 48484848484848484848484848484848
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 89C61A1182BC868BEDA3FE4A76CD679D
+                               A3DF3A656AAD3AF83BB55C0F0455AFCA
+                               1B3FBAD0B91F7B1F209E5F74FDBD700D
+                               9417BF9B4A22BD3B7C94317C20ACCFE6
+            stream[192..255] = 1C312223B46A20BAB52F110E04AB324A
+                               068E6DBDB1EABEA92CDC5063E38B7EB9
+                               A7DB50FC4CC626761CC00B7D821EB0E2
+                               D40F7C8DD10F5A975A14689151B38B77
+            stream[256..319] = B38D45E3CEC551950D662FAE4241E3BC
+                               5FC8FFA67A472B1048F45D594EA0715A
+                               5B1DE277264D72251A3C5024C914A0A8
+                               14747D714F8CC583105013382518A0F5
+            stream[448..511] = 42D47BDA13625C17FC6E972E68F3AA7C
+                               F8F9F12B900AB9E474C0295B48879DCC
+                               0832FD53C3C90B641454AB4BA90DD7D4
+                               1748F4AACC9AB1E1CDA8007B3B18B1F1
+                  xor-digest = 131A1E29ACA16C3A409ED6E201559CF3
+                               3CD05312376DBF6796D39E2877D23255
+                               F3308D3419CBEA800F1F2E9DF7AA36CD
+                               03AC3D6BD228A165A885824941D764C6
+
+Set 2, vector# 81:
+                         key = 51515151515151515151515151515151
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 70977581BC650C5D03F1B3A02672C384
+                               250692C2AC94EA0F4A43723E88FE587C
+                               00B5319F87223F6817C36F21FB852995
+                               5CCCAE243D65792A55D6F047DDE1999E
+            stream[192..255] = C00B41DD0BE80054F46ECE559526ED5F
+                               A87E7196A3A20698F5048183F91ABACC
+                               9E50AB64D437F05375CE78D75469EB7D
+                               478810E1C792CE3BA0C253FB1E549A0C
+            stream[256..319] = C95C6CE222392307CABC95202CE59EEB
+                               160A25C482F4608616C80B50A9D0B771
+                               732262DA67BE8319486F73E4B1FE3DBD
+                               1B7C97516F0ED02F1F4ABE9141329925
+            stream[448..511] = 93984394395B47A34FBEDD96E50A1F67
+                               7DCFB1845CFAFEB7DD83A9A7BFA35C7E
+                               48E44C38F9D33B3CFBB763A79048F6F7
+                               B6F32386329AC979F7EDF8828734A116
+                  xor-digest = DF2A33DFE7C90E76DB4E4F2D9AE2AB69
+                               EA16664B5E0031D800913B6572E1E2C9
+                               AD4A31D6BB088AA082195F8B4DA56605
+                               D32A19916474C042F755AB11EE56F6E1
+
+Set 2, vector# 90:
+                         key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A266B810953284ECAD69E960C9AC8FC7
+                               0B94798E55BF7D2EF54EE50319574C28
+                               7DF798958FD653B5E5BBAC0519D3F40C
+                               4372DB7204A3FFF89F6E70BE245C30B4
+            stream[192..255] = 72979FA8747EC91B68EECED4820CE7F3
+                               8EF0F20240D8E04C5004D10880BBE17F
+                               673A427D0FD62E8331BA633890D062CD
+                               FE584ECEB2884AB4086E3AD04F9C1137
+            stream[256..319] = 77E9FD26E216E6F22D32AA89E4D02C33
+                               482570BE05C0E1FAD59DCDC5A3F1315D
+                               B2FE99C4863DE4512EDBBF45DDF51CB2
+                               EF472481D6BB7EF8C7AA09E45B03F45F
+            stream[448..511] = 0386E999B6EDB2E52F86B3792A8BD15A
+                               FBC40B44D6EAFAA0D562C6FB2BD16BAA
+                               3F77F968925DA020D36A109A67ECEFA1
+                               CC278F022B93169006D79C0F56351DEC
+                  xor-digest = 35BCB2796B3AD76E59C2BDA7EBD7B47D
+                               C99236FAF5F2186188114C1A958185C6
+                               48BA837A3B839CCCF55FBA67B21DB031
+                               D7BAB7AF52A98676CFE3EE4249A530DA
+
+Set 2, vector# 99:
+                         key = 63636363636363636363636363636363
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 14F782FCF5C88052A93AEF40492669AF
+                               7C92F72147C2AB2C18217144055C9868
+                               3E2FBB80775B54D119A9A06AE72EEFAB
+                               999E85F3AE12804FABCAE539A8585492
+            stream[192..255] = 663FFAE38877EF1898973355FA27E9E7
+                               0BC0034A88C1ABBD2847C46335C18113
+                               47F42E18C1295D07D5F75909F0B1C0AB
+                               45EEBED3356A930E018E262655074944
+            stream[256..319] = 6ECB3BB43DC1C4A3FFE0EAECE58B07B7
+                               1CB5C7763DF420859853C7973778F63B
+                               10EB1B854BB8CF1DA0D5DCE6EA0D5816
+                               BA0508E7A1694ABDE04A706A008252D8
+            stream[448..511] = A68ECAAD1CF25C78522FB75D08C8CFEE
+                               561C2CAA9E0D44EEDB121228F4809F50
+                               996B9DB89E2E2F8547578F83015C55F4
+                               ABE82F371A5E02CC97FC35FE7DA49AD3
+                  xor-digest = 83F0BDBDF9A82287A650BC70A0C8F38D
+                               92868DF38D150E4268526A0A51D3A9A6
+                               FDA27D6FDE8A1A55E856DC891B35ECA9
+                               1D583E0470419BAB5C0B9ED4886342B4
+
+Set 2, vector#108:
+                         key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 359B9D751379BECE129238C22647B90F
+                               A849534C9395EDFA5F2121963D2F0B68
+                               D9C6469AC8A192FACBA7C27762B22D8E
+                               39171D3D01D6BB41CC4F2AC318407D65
+            stream[192..255] = BB4795A89BA6AC0869B2BBA5891FC1E6
+                               890F13DCDE5CBBCB22A85014E554BF10
+                               DCB0873D79A79438F39DB467E23EE1E6
+                               2D2A549DC86B89FA3DF53BA5E5195718
+            stream[256..319] = 7AD5CF48C01B51572FFE4E0D23FF158E
+                               46941F1B1BB5D7DED2BFE80BCC48A6CF
+                               3DBB186AD1D3F911ACD8426B2A1219A3
+                               032104E3EE70717FA7D547014FD334AC
+            stream[448..511] = 6320933C389A66B5BD72DD69BA492432
+                               01861F3524C529DC2869127BA41DEEEC
+                               FCA5D5BA7521DED5166E70FCEC72A564
+                               545FE45F29A2DA9DCCD5AB80DFD119D1
+                  xor-digest = 9E1E8A8A4FE661C660DA51134D1C8A65
+                               3824DC5A99715E88F17245436F07E283
+                               E481D9B0A314B2DC9821930C80F8A184
+                               2F33F4219525F3DD063CB9C32D9AAC60
+
+Set 2, vector#117:
+                         key = 75757575757575757575757575757575
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CD479075E614524CA0B4A73BA48632FB
+                               01C8E9DA532912094D14606F08B81C0A
+                               CD7556942CC4FE4900C4419E8F618AED
+                               B53261B5B97603DC21F5FC8D57887F0E
+            stream[192..255] = E69AFA41D5DCC57CEE46FFF86551AE30
+                               D7A4B7CD2082BA8B9F446BA1A8E01B55
+                               D924E0D788A01D7C75B819D8B88C4074
+                               E97E1781061DDB3AF084A45E5A2D67D7
+            stream[256..319] = 27F75AB01FE45DBF6E661D39159A8727
+                               15AB7D7CB1275A11AA3C8CD55708A67A
+                               DCBE98FD8E1DF1F787F099881C87A3C2
+                               A0135088B99B21631AD115A8247BD280
+            stream[448..511] = A75C019250930742A65637B2E60A43E4
+                               1891CE1252082CA86891A684C19304EB
+                               7D57EAA4F8DF4686D05E886C5496C37F
+                               C224455AAE45F071FA654FC88CCBE17D
+                  xor-digest = F5C14A26F22546515005E433E1F825E3
+                               6395F5B59566C11C79F0435389DD7745
+                               793F8C925E68A9836B6E7B03C0639FCC
+                               CCBB3C1758E28E9DBAB1D9F733AEE7DD
+
+Set 2, vector#126:
+                         key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1AFC41EB0B3A1AE62127B62AE3B7219F
+                               C34C0A9D904D21F071424A7D07A55E4A
+                               69AB9FB401909372445844A367C2ED44
+                               69C12FFED293DE61619AF98FC5F159AC
+            stream[192..255] = 48080F88453788279BEAAD61B24BA5EE
+                               28F0044B5AAEBA5DD6844E2F57A0F3A7
+                               AF19BE8E7F6DF5BA7D74DEEF01CD5B09
+                               C928410B02532F66C19A3E677B04AFEB
+            stream[256..319] = 5D493BE7C17B1D6075F0CFF7C738CDAE
+                               8B5BB6126A1FDD8ED2FAD3A1502BBA0E
+                               CAD26485BD94EC5FA852AC74FBABB070
+                               FBC0604F69C11F5725F644FD14E5D001
+            stream[448..511] = 7D3D74044FEC8DF49C8A505CF1E5413F
+                               A63F53ED43F4B90DB3CAB6EC08E65821
+                               F1384E84490C6E5631B021145565D234
+                               67010AD6C9A5C729C774BFCAE2D43DC0
+                  xor-digest = E2B8D71D68ABBFA49D04DFC8A3DFC390
+                               FAFFCED207BCEB9EC4B6C435A9757AF4
+                               ADAF3E0734268365C82DE978634696B8
+                               D61EF69FAF3EF62CFCE89672F1CA7497
+
+Set 2, vector#135:
+                         key = 87878787878787878787878787878787
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DFD7B8D57A6AE51A401FA8DF38395B37
+                               17507AF28A9A771149C034F3361E0203
+                               ECE88C484F44DEB8370D9E77994EBE6B
+                               E05CA8E05E3DCF545EFBA53859C2FBF3
+            stream[192..255] = 42996981385309DC8884D65CF2103D64
+                               F76567EC51266A6DE5BEBC362529B782
+                               C95D92A17CF4567454422BC72D20BA56
+                               9DBCCA81DCD694B2B3DD88A988004875
+            stream[256..319] = 43C31B1EEAA67D7506A6CAE07CF9EB0C
+                               838C72494C14012F58B80D0F4D159379
+                               68C860E32A029B3B0CA040AAEE262CE2
+                               9C50046E1CE83FF36120D3CE81EA3BB6
+            stream[448..511] = BA8D089901F2F5C83E1CD485BC178F12
+                               88D1B700A7EE749DDA9A96910529EB5F
+                               057BC8FCBCD0D542FC3781E0FA742C3E
+                               C616578C8ED918E8F104EDC142BC7B7B
+                  xor-digest = C9D6AB2D64CC7BDB01F89F08047749AC
+                               38856667B53C87F8B501CBB5F18DDB84
+                               820D409D5A44FBEF505213981D86241D
+                               279C6749D1D0B756BAE39390D754AB21
+
+Set 2, vector#144:
+                         key = 90909090909090909090909090909090
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C60205FE3662A0905EA10CE1D17527A2
+                               7565D227C895A8C9426069A9F0F48894
+                               A96AB80039477BD604762F5F2CB2903C
+                               7642EA714B27B365DFBFAF60A6E249BD
+            stream[192..255] = 88DC912DB28D5A2700EB74CE8011A307
+                               E2A0B8FA2E9B50E38899B4AF1A0F3BA1
+                               79CF4DFE87DA0BCC1E76D9A56DB789FB
+                               18E439849D6B8B6850D0CF8A17726FEF
+            stream[256..319] = 2247A96C32B9BDC5DB41E7670DEC0A51
+                               73EFD83F345DE71CE0A2192354395576
+                               4101D73BCB2051C08DA70CA5100C7194
+                               D22A6C3DADF313369CAF8E545E97E25A
+            stream[448..511] = 83089E1CCDEF294EDAC0006D6CF49475
+                               E93324D10A6EA635B2C19D285B58226F
+                               AE271B6166A5818C6C567CDDE508B9C5
+                               264C2A6D5A8A4C7D6754CD11A58A6588
+                  xor-digest = 2B89AACFAAFFFCC15076A79EA8D983CF
+                               FA2CBE2BBAB4BC70464E9801B585FA23
+                               618864E62E573F51F1119D32E509A507
+                               458DB29422896E0A29E44D2A96FC0B64
+
+Set 2, vector#153:
+                         key = 99999999999999999999999999999999
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A6A3260212BC1A9FCD7336F1DEA05D75
+                               A48B1B1662F61B1CF1589A91AA66EB82
+                               25F58E77BFE7DB10AC31F318ABBDA7B2
+                               FBA88A57CA8AAFB83A3ACD0D78AE9944
+            stream[192..255] = C960FEA579A48D263C514DC4D7173B8C
+                               A325A16B02C87086EFC38F3271087B48
+                               BC51FC4B8FE936BB87336D54D35E8B60
+                               F8300334D0A78B48D2E97751CA571ADC
+            stream[256..319] = DB1859630B7E5D59366E95EE9F680F48
+                               1EEB9B880A3E82C85046552A844E5784
+                               3D4BBBC50923E806A1E2B03499C4F869
+                               9035913D5993757A5CE2A94311A22C17
+            stream[448..511] = 792B3AFBA5A9EC89C8119FB8F1CD552D
+                               6ADFCD61B70481760EB52878CB907367
+                               B2A5082FD963F56ACCD0F5FE6B67ED48
+                               EE81ACCBF066DD4178D39E001A6A2027
+                  xor-digest = 45E67FC4B7FCCEE700CDDE0404160E21
+                               DBFA6280DCFDAD3865FEC930EFF1B3FD
+                               799161C8812EB27F6A24985298994FD6
+                               5605325D0979CD798F0ECE18886C6E8B
+
+Set 2, vector#162:
+                         key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 94DF00B66C81CEF99E47BCB9AA6B2E48
+                               CCB408E20D878C56A9328D2422F1436B
+                               CCB7C8B04F8AA12BCF1DEE965EF098F3
+                               F78540213E755C86FA33B6117BE9E81F
+            stream[192..255] = DB745EADFB31EAE7A699A84FCD41EF80
+                               DCDC25334225F7B3E5D49FF58503C60A
+                               2FD73212719EA17F61F60271C9347E19
+                               3A894816DBD39A313AEA33F56311309F
+            stream[256..319] = 75410B6F256D7E9D2C4DEA9F24766E0D
+                               1FC3EBC67A5EEC72BD45140C41C3ACF7
+                               C517E9D8BE1B0AA06668012FB1C388F8
+                               098FA03173EC61CCF0252F793E42B4F5
+            stream[448..511] = E41DEDE3241806F3ACE001D8ABA5C290
+                               8C8D3DCC7E33A4031571D6F5BCAEBDBD
+                               0DA77831AFE34A4300B5677EC615FC18
+                               00A2CA80FEC9CB40AA33DAA1D20D80F6
+                  xor-digest = 8A80F6234BB7430D1EA7C6A6998D03C7
+                               CBBEBEA27F9C329012E19B0B62BC5077
+                               CB64AF18099DFB4113C6430B842BF529
+                               0DDE3BC0DF45CF836D766D03B6CDD43E
+
+Set 2, vector#171:
+                         key = ABABABABABABABABABABABABABABABAB
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 77BAAA833D320DD2E8C8D36D4C1025BA
+                               07DB396F663C2E50CBC43E640EF93977
+                               97ABF342CF471B758DC6A1472C817068
+                               BC7E30B49004DED1F763DE141C33A0BE
+            stream[192..255] = 018E53C65112E8C3CD374B892B21C1EA
+                               80408F1A21AF4EF02AC7CA5A6A55D130
+                               0B947E0A93D8980BC2070B082EFC3125
+                               E37F2A7D1A5BF0A8C8D154B84D6FC933
+            stream[256..319] = 0EA8A2C53BCFCD5350B3CC2CA07C0041
+                               53B4AEC461D18419071470D8F4BC7404
+                               F34FB030DCBC4E01B98DEEFEDAC031A9
+                               41C395538E95867A13EAC71EBCDADBDB
+            stream[448..511] = 1832583CC5A02147E6CB3FC2E5157A83
+                               3BD5513D14333DE552B5E1517527E4BA
+                               7069DE68F47D7A28CD2DD2808DF110AE
+                               1F53353B654E4ADD055032D8323FE829
+                  xor-digest = 14C12CE94857C60659ACC9DB6FFA02AF
+                               11840A7E2859DB05FA6436D7B3E9779F
+                               D21CA43BBDB9F721B5164485FEBE4034
+                               7CA303DF12630D6E967C0DFD7653ABFE
+
+Set 2, vector#180:
+                         key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1C1BA750879B3BC214CB843962A0006F
+                               54E3B0F682FBDD7AECC21EDC208994F7
+                               E738B69FDDE5E90964CCE34D7351188B
+                               B3D788F435747FAA13EE208030893252
+            stream[192..255] = F358238286724199C183D8C960D730C7
+                               2058248249104960DD2899886625C5AB
+                               4844D768FB2594F2CCB751280478364D
+                               C78E631B5ED11343A104338AB8E28958
+            stream[256..319] = 0AF1A0C7A000092FB1CDA9CE6D145DDF
+                               C37D1078C00008392BE73C2F34DC05B9
+                               9FC4954071AAB16AEBA5A0D8498D411B
+                               5C1DAE961DC2A74B8FC992DAEFBAD292
+            stream[448..511] = CF358444795D941D450F2A6F86811CBC
+                               2492263D5964C4A45A26AEE228739BDE
+                               3BC223FE507EB5B9AC6983E213F529D7
+                               86473A4DB0764DCA5A27AB7B011A5393
+                  xor-digest = 78714C06C8C4C206EC238D4E679D96CE
+                               4C258C46C1EAB4E23D2E55A0061CD767
+                               9AFC8C85AB4862D39768DFFB3A0FC583
+                               0BD203F66B03BE4FD491E1FE0DD83FFD
+
+Set 2, vector#189:
+                         key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AA10D434183C285709EC2706371DCE5D
+                               5F8C6FF0CA2B01281550AFE875413B25
+                               14D34846E658F9F11BED0F93A427FD96
+                               8C62380A46FE8E3F7E023318E989BF31
+            stream[192..255] = 2AB885D3EA66AEDC476DC5C59C3D4888
+                               2D39907B51878917B7DCF351CDD30963
+                               6AD8614DA701B89EC9B141696F77E815
+                               F95B15AD77B96513E5ED6C7F10EDE616
+            stream[256..319] = 39270D1BAC8A3028E55097217ABAA158
+                               1C0B8874A21E42533720F0F4350CAA8F
+                               1940A83B17D328BF0FD50BF8E62EDBD9
+                               5DF959FA4CEE952B6098D48277968AB0
+            stream[448..511] = 21DD7B64EBEF256536E95403EE0CCD20
+                               B062193EBCD72EDDCB1B0DE9308D048C
+                               B3F3C653DD93D01F3B266252B11F32A1
+                               59AFE3B00369FDA024DBF392921FD1CE
+                  xor-digest = 1A748746F13675F5125F0151D0AD6349
+                               7D23517B99000CB5479645F19889E407
+                               FC770983F7537AF86564F5B323E0DFCB
+                               FAEAA53AF258F151C871C83B5BEB7AE7
+
+Set 2, vector#198:
+                         key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D4CE9B9AB39183E530A347FE5B435895
+                               4899F18A43A1AD9F249522F7B8243359
+                               EB61ACCC30BB40203D3B5730736D38BE
+                               057C15D6A2DCCD005395C16CEF85FADC
+            stream[192..255] = 459CA305A8F73AA0931A56D914A51CCB
+                               3C6B22C1C35392464BD2BCDA1FB37050
+                               E2181510546024C753222E678A7CCDB0
+                               77DC88DD7C947210897021A72E437DBD
+            stream[256..319] = 8537F62AC5AD1CDC7C6C910D45111165
+                               5219E461238002391B54E7A8BD6BF323
+                               1E2CE93AA581D9A8E755B33A382FE56E
+                               9FAC3D9F3370226EFB99701B4D0668B1
+            stream[448..511] = 192691D070C8E3966467F1DAD89D5D8A
+                               E345230E9828C9BECF681DC7AC0B7AE9
+                               88656C7333BE93F103D7EE505F05C5C1
+                               FD8CEA2D27407EE265CD59F6BB5ED7F8
+                  xor-digest = 41A75368279FA64F63FC895FDC49DF18
+                               1EB48E780AAE9C2F548C825BBB276803
+                               A4479CBFF22E79E35701B24B47B45777
+                               26B5455C804E802B62704655B77D20F9
+
+Set 2, vector#207:
+                         key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 430EEE25DFCA972E12DF2FA3FD1F9A61
+                               CA16B3EA67C5131D701360C9BBF2ABCB
+                               F2431D01590B300CF462A68FEC3C6E9F
+                               1F6A5BBB416EE0A098D2995711C9772C
+            stream[192..255] = 97D49334BC2482B1BEF901BA4A91738C
+                               F6DD9F917862984616DA7C2FA3F9BEE5
+                               1329AAADFD5B88A224C7B4EECF1BDAD2
+                               EE33E2C7060C1EE0E8A4E21D78D08942
+            stream[256..319] = 79C06E2806BB38FE558E926E4A2C11DA
+                               903DC06D384D033984D2F7516ECB2657
+                               4D5B5629B79C8D38E71F9A01B9526EB1
+                               7E3FDB48B37B6338BCCBC914B7804935
+            stream[448..511] = DA2A78E621FE1D105DBD0F7CD45AFD51
+                               366533D03C446005EF100DFCD9789C5A
+                               06A00A7379A4D45AAEC1CC337F61C532
+                               DE26B1D028E72C399097A04FD7FF087C
+                  xor-digest = F3833AF5AD9FF9AC9B227B1C9D0EF385
+                               0B22FF5A0F307EB25654BFB63C61E802
+                               2134A69091E5C5DC1E04C56BA2009B97
+                               DC9D02339578603D8EE4F50D1320247D
+
+Set 2, vector#216:
+                         key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7960EC96803829CE052CCF5B8205D09E
+                               A417C075068FE91982283DA19533A61B
+                               EAB72F7CC93AEB22AF97AA3B4A5B337D
+                               36C96BCBB23A073F57F2F378B7309758
+            stream[192..255] = CABCE57DB1AFA7127A13498FE1FF87BF
+                               DF1C40DC7F8D69D46EF62996C2AADE35
+                               526377F4A09FB10B4260EF7B5E700470
+                               1729CD1F0732748CDAFFC14AB6910617
+            stream[256..319] = 01898230BE3F6E682480C8333700A2C5
+                               1FD38AD27EBBF60CF2DF71B22C827708
+                               3A1476E7FCF3348FD5E4E9EEE6CE61EB
+                               818DED1BA0C09FB96C5B7C799C1656F7
+            stream[448..511] = E49D27417583CC79299ECD18751AA540
+                               C7831C3A0252292EEA8242590714DFF9
+                               4833393BCC56403144E68A6BB08AAF35
+                               2F71C6AEA9256EB5AB5250DED6366AA8
+                  xor-digest = E6D998D7F3BF7EEBE45844EFD7EEA371
+                               4405D07D6EBF2D5F7F5435E4F557AB4F
+                               7571015CEBDC2CE0A199D7FF8B0DCAB2
+                               B9BACAEABE852E667EFD2E82A219FFC3
+
+Set 2, vector#225:
+                         key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E9AB7EE17B4734823A1522F5D78EBFC7
+                               2F8112F67325BC5C12778C6F8302ED9F
+                               BB545EF47EBF2B12380935AD8048B90D
+                               4B7DBC7759E27C205C94202EB64F8E0A
+            stream[192..255] = 5B775277917681D67800B3249E7A82EF
+                               C5500F49E7507CFA0696D94FFB021CF4
+                               EC6955663CC37F9B2FF7A0345A71FEFF
+                               3712836C66A05C3C6FB9A03EC3D52260
+            stream[256..319] = 11ECB0057615CC8244B2251E87449CCF
+                               0CE7805F669C762F46EF54E8E992737A
+                               BC668204D49ADA49E51E592B79B34BEE
+                               248CE41C72E8A60366C9951B74986FA2
+            stream[448..511] = 3BD82780875577B7ED9C603A240F1944
+                               5C3090E36926793F769B11E3C6C8C993
+                               697E2A0C1793AC4F39DEC882DACE3375
+                               D17B72FE40B82FB95575F9B7A17B24A0
+                  xor-digest = 996E394453A2CDE7CF809216337D1ECA
+                               FF5FFA7414AAACEFFFFFD30CCDA5E424
+                               2223AD119B3EA56D50248E7E7C0BE002
+                               9640304D08A2B3D44386CEA0098D6738
+
+Set 2, vector#234:
+                         key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 79D2D1270B77A586ED9C3897C2875842
+                               16498EA183465A96FA1D783BF1B1B070
+                               B46091CC3879E9ABF97ED22A72FBFF2F
+                               F8C72DF9A3832C927FFDE6FD43D6C1BB
+            stream[192..255] = 4CB1C6953204F5F279F9F334AE8BE696
+                               26201C8EBD488E6204DCC9823E022A15
+                               23DADDA98E6A1A19BD42B37047A2906D
+                               19EF12702530DF4B7E597367B4463DA3
+            stream[256..319] = 51500A31B349274BBF9A6E324773E5A4
+                               2E91DA8482D306C7F13EE3E1975F7BC0
+                               D9006964367F4D8B28B389652455951C
+                               402AB51A4ABD06262E0E3A7A8FA3A7AE
+            stream[448..511] = 01F28C4729556AE8227B306930175707
+                               C75BF589B3711AACAD836615D666A66D
+                               255B40302E0DD5021EC4A15BCCAACA95
+                               565BF3FB68BCF02D265F911ACDF6BA0E
+                  xor-digest = 3B5FF103A75AFD640DEA7B686359CBBB
+                               A888AB60348CE2FDF301267E415129BE
+                               46D088D9222139E96DA8D804DA3691FC
+                               C546981BF65265FE04366053229BD030
+
+Set 2, vector#243:
+                         key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D8AA78A091BFB8D90FCA94705DD86B4D
+                               FBB2673A5ACCBDC4F69A21C3B06A0594
+                               F470F70DCCA273A2A72C167659B7E0A2
+                               76CC3BCC20AB889E682D4E2B70BEC4A9
+            stream[192..255] = FD6974FE135C1E11DDC82F2DCF5CBB27
+                               AF0A8A55084407C3315B47FA41D2C240
+                               372C7C4B03F8F90C3201B2269D18CFF4
+                               C70A13722F46FFC34727779CEDD17FA8
+            stream[256..319] = 6433E61D5773ECF30ECF8DA06F8F11BB
+                               717B268E2C283FDC7B2F7841040EEEF8
+                               29216193392BA5D99405A744FB571B6A
+                               71A6EA188B3BF5CDF9D601ABE3312FA6
+            stream[448..511] = B238D39267ED812D37AC81E6D2B29D21
+                               45F9337A6E2CB426C8B43BC795832FA7
+                               8D94B5E1E83C19D40D3C2B4B670F3C1A
+                               D504DA82D6E83A71BC5E431152B485EC
+                  xor-digest = DE1C9B7BAE92989BCDC7AD0D527CC6D9
+                               4F138C8C2A1A06C1AE28405C867191CF
+                               444F45770CC216226ACB13D2A0A2B8DF
+                               FD81B93AAB20EE7C19E631D9635AD0B9
+
+Set 2, vector#252:
+                         key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F61BEE71B1353E8E198E9300CC720C88
+                               977F23274ABF7F9DEF298B97EF43FFA5
+                               CDFEB51DAC7224EE6DE64CE0966B358C
+                               9786762BE880BF00BD48FB1D3D1FCB99
+            stream[192..255] = 019B52D05CEC5CFC74F2D26ADA3D2F18
+                               B4B44D3EC9359A132AE18B33510C249E
+                               D56D0AA2BE16C6213BE2ED47514B70A4
+                               DD5FB07C317757F5981009F70EEDCF39
+            stream[256..319] = 4221E9421F2C68EC8B59660512EA0442
+                               64FF35D22DEC65E1ED18E3D8BA359A78
+                               92FB5566DA0DA25CD5A3409EF6A6F020
+                               59DD632A793886C0032864F16D827A36
+            stream[448..511] = 71330EEACEE6E27994023E212D1B8A42
+                               045C29F141E4C696F74A0E7500B45E82
+                               A0ED1F4DF8C78A93D8D6033B780BC22A
+                               F4D8029B82AB447E0D5EEE3405EB0D22
+                  xor-digest = AB84F0A0D9D1E8D810E76517E5A0B80D
+                               0B2832EE12AEC48B5DA48B78DC4D2278
+                               710DF7664ADD91B1FAF3F14F3951344F
+                               08515E7D43F8EB677B5CF18C487A697F
+
+Test vectors -- set 3
+=====================
+
+Set 3, vector#  0:
+                         key = 000102030405060708090A0B0C0D0E0F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CCF2DFC47B94B1C67DA07BE50ECBEBE5
+                               9F470BFA68058E55529EC8041EAA2107
+                               A15DBCFF20B1E54B36ADEDB49356FE2D
+                               4BA86FA2C6FE08DD1E260D7D20A3D93C
+            stream[192..255] = E5EE7048E8EC8C7904138C6E355D3956
+                               1D8A1B824D62DD5267918237E9225416
+                               2A192BD543327B9D786F973479F88DDF
+                               152974B2FCD44DF9B77E1E9D8595F29E
+            stream[256..319] = ABEDDC8F46C83EF0B3D159B3A1BC6E1A
+                               4535744E20D82A2013A3013F864D4B43
+                               01C54F2BB0F03C775738875C1116642F
+                               4E6BC1D551145D40A8F978207F44BF89
+            stream[448..511] = 804C09F0973A24FAD6B4E7398C57B11D
+                               E670AB2AEAA63822D70C7109E2E1CA58
+                               42E2251424C23525980A7E7132BA889C
+                               C2604FCD9F443A1A194646730FE349E7
+                  xor-digest = ADBA33559432364C670A33CBBDA0C0D6
+                               D75C6C986D073C473C96286F5058ECB9
+                               5B78052C26C5BCDD6138334201B05458
+                               135B363B8ADA8CDB3AE0C565C9235646
+
+Set 3, vector#  9:
+                         key = 090A0B0C0D0E0F101112131415161718
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 759D5A8381CB183CB0A01B4A85FBD793
+                               EC9580339CECC9BDF7DC52F67D8D635F
+                               1F590575EFB26F906424962D99880E45
+                               AF25D68181C9652EFA590E8B1E0FA578
+            stream[192..255] = 3FA014E6416459F15B5527380E5B513A
+                               CC38193B9A26CC24C59CD6866EFE8010
+                               30C950DC2D55B70495D4C11296D9609D
+                               670E41CCC20EA01349E28A2651318A1E
+            stream[256..319] = 675B1A11D7F20A18C137EEEB2D3593F1
+                               7D1A284A076E4E18BF8B622738962236
+                               C3F07D4AB453EB4FF0E3A0BD89E21AE5
+                               CD17432F149B386CD29011D6864B3B83
+            stream[448..511] = C2C4385B74B6A38A18590A5A596DBDA7
+                               294C4DE7B15EE36F4481E275AE2C11A8
+                               17181DA10309BE5B366852035C227BBB
+                               C61F001560F03F2B361B5B8E0FADE6F9
+                  xor-digest = 26A33A713972455A92FF0E6D65C7A7C8
+                               537BD0D9F8EEC96E03C3B39C5F9307FE
+                               F8956D1EC10BEAF467BA86A26E846ECE
+                               F4F330FBD9D6DAF5306DE538F0F76C0E
+
+Set 3, vector# 18:
+                         key = 12131415161718191A1B1C1D1E1F2021
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 27D21507A4F5E2C39050B1D752574ECD
+                               5BDC31D6E8708D1AD950E3E48C53A059
+                               9FE6F7B5CD7A6AB95AB9C3FE0EF154E9
+                               68882B10A2613A283C9310579F444F19
+            stream[192..255] = CFD6E486D72760DD5FD1D246C5C150BD
+                               622052B7F1938C3EA510F3D0EE47B494
+                               FE8854A833EBB2C7E579EE3925B19AE9
+                               EED77434CF7B7AA00833904A78AED517
+            stream[256..319] = C6FDE37C40A1FF7B4EA3A8DD64E7A1D0
+                               7C4F25C04CE05A3C09F6EE012B458A9F
+                               93FF21C9EDE67FF06918CA541DD24C87
+                               19931323F1C87EBC38F56308A2F5E076
+            stream[448..511] = 1E9D3E112C8CCCE11ABA19E941E48173
+                               EAC5840A3025A88EE79DF2514EDCFBD1
+                               3A581C507EA3769FC0498EFC7447C0D8
+                               9135E602E06512D25EC773A20C4D1F2B
+                  xor-digest = 122C8ABB06E644953AE81EF78CF4EF6C
+                               A1322AF81186B8C27EB199B5EA7814EF
+                               E6F0C6EF98781CC12FF7A988F135F3C3
+                               28BB53B6D2612B1786D4B24D63BCAD01
+
+Set 3, vector# 27:
+                         key = 1B1C1D1E1F202122232425262728292A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B98764C4BEE54B7CE1722955D29F7265
+                               74D3B6D2A7F51847A8A5F2BD78218DD4
+                               13BAE5A9B76EB7C2140E6D728D430CE3
+                               EE77FA5446B53D887A600B8C2A954DFC
+            stream[192..255] = CA3AD141894C09B6DF333C6C42729339
+                               45AA6F7F13EA64C1E3043F2AB64FA18B
+                               A3CF16B35E853FC98A67DEB1A9A60B1F
+                               EFF93767C87E583C8B50BA0B80B69AEF
+            stream[256..319] = 0D03AEE4BC0E4260B48C43614AE1327B
+                               4FAA2F0813F188DA28C3CF15C433EE59
+                               881DD500A53768C5A1231991386E1470
+                               2295243CF3E18638B60CCC4513C83077
+            stream[448..511] = 4E190889B78B6CECDDCC675FCD336592
+                               8D01D945C8B9737CEDC144005A7E2E6C
+                               921256F89098BB560D39BEAF700CA5DA
+                               4F4535ACCE3439D9223E357DAD2983A5
+                  xor-digest = 2261129A59B37D3C9FA15E35B9DA02E8
+                               B6044084F0EEDA1A62641BD8BEAE9293
+                               A57E89120CEF2CBE5594C47F96E46C5A
+                               E6FADA330126A4EDE047E40153D5A182
+
+Set 3, vector# 36:
+                         key = 2425262728292A2B2C2D2E2F30313233
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F8088D4E53936A40E21B3AAC1E6D975F
+                               13BCA7E4D6CF7D926F6B9AAC562790D8
+                               E2B66C05A075737B75F8E171C70E1507
+                               94437B818F59052FE5ED87BBADFAD509
+            stream[192..255] = 19686CA73474C6F626390DA198824970
+                               9FE43AD003953D102437DFE11DFDBC64
+                               432929F934A0758B2964EC3B7CFB8C1A
+                               BE23C6B12132B155D3922719DF28ACC6
+            stream[256..319] = 55EA041FDC9CD8438EB7B9C2C5381785
+                               57E53ACC75CA512B88D8531E07DF4C15
+                               35F60851AC242CD46F56DD35241D51AC
+                               6DA52A3BEF555E2844DD4EAFAFE3CE63
+            stream[448..511] = FDFB1D76CEA5E3FD0C5EE1FDA1717684
+                               2120C48956F28A583B291712DEFC158E
+                               FA26FC4A833D31B0EB59F61D942E99D4
+                               AF4BB42D0C0448CF8CDDBEB336738414
+                  xor-digest = E49BAC9E963F83F3AE70026DA7DA496A
+                               0764267F7F5A8A23F7AB32EA0F54D459
+                               32367E47527DF738F7255CC890F15FF5
+                               8160EC0C1A27260856A822810AE63F2C
+
+Set 3, vector# 45:
+                         key = 2D2E2F303132333435363738393A3B3C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 67F1B4269C402D69FFB8B84559E60033
+                               07B153631D650E01A3B265739130F184
+                               4F6126FA1F957C7FF5AAD71C2E3BDE25
+                               94DB87780773B4A4DB3E44D231D46AE2
+            stream[192..255] = 5BF80BBE842FA08B4B2EDEEE74626A19
+                               69CDEF41D1E731FDCFC906F320A2CAC2
+                               8B79B585B0F70A5AB48CBC5C9478E5EC
+                               B14A387D5DB8E60E4EFC86785274E437
+            stream[256..319] = 5DC02CB76EAE6800980E204AD9A315F7
+                               A65C57E2F38DEFCC29FB1153E7A4586B
+                               E9FB7FEA650E326A5593568957BCD278
+                               A93FEC168D48372068B9A2E41EE10C61
+            stream[448..511] = 61D55EB5278689230193C990EC5E65A1
+                               DDA93955026C14BC32E80036055A31BA
+                               118911DAFA9FA9160D4C37524F5EFFD1
+                               2D575FF005967C3EACFDCC9D8889A198
+                  xor-digest = 9B327699C5FB098D15CFF2AAE321D095
+                               A569B6D87AB1BD20FC8FD94AABFCDF2C
+                               521D3D5657857A6E197B55F371351525
+                               171D23F4DC242408730057CE67BE8E58
+
+Set 3, vector# 54:
+                         key = 363738393A3B3C3D3E3F404142434445
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D9B96EA262807FB3F5A8675D81B1A006
+                               1D717D345EB2B91F607B853A5A38DB2B
+                               ECDD26626A33477BF07BF9C57FE95100
+                               A1F142F70DA7DC86E063A58AEB090B2A
+            stream[192..255] = 597883FB531AA34A2EDB6D83AB2A304A
+                               FE522A9EA6914C556618B3094874E021
+                               2316FA67BEAF7ECE4BCF350A817DEA50
+                               FEF5B76E72E2596A149D99B6971B069B
+            stream[256..319] = 6090A1AF397F2BC3ED551450EF28472A
+                               F60EE5F2B4BEC18A8B1ADF21A6A476F6
+                               8C11F76405ED62ABB7BC585BEA4B0A47
+                               988A09A1D93CE2CE95B82C9C1B60E650
+            stream[448..511] = 49F88E9C5E53BF43EA422682ECA42968
+                               6D794754E65DCE9306D3D9FF206BDAC6
+                               442655D27EF6166CB095DA4C301FB7EE
+                               F1F5FA0225EB84CE61BF3856062A4EF1
+                  xor-digest = A71B962E13E66A678C5B56E19099CED2
+                               A15480838832FA6361C3C0B5BF47C1C0
+                               DC954A7CA8D7484D7889FC760227B418
+                               73EB611B5AD62FB622F5FB75FE412A44
+
+Set 3, vector# 63:
+                         key = 3F404142434445464748494A4B4C4D4E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CF11B1510C81A296CB185B1BA6436112
+                               832AD2EB68B70E52CD68F9D394F5165B
+                               94DE467FFDE4EBAB6AFB180EE7A2116A
+                               1E73AB81AE4528273D0D93DD05025D70
+            stream[192..255] = 26E9F1C007EA49793D701F21696FDE8D
+                               B72D317BB958F86A35E7BBAC80D62CE7
+                               0879213503B04FEB1FBF3987847745F9
+                               DDA9310DB36AB8F485FEBE9FA6C1C7FB
+            stream[256..319] = 25C98B6441F90615C6078D82B5D72F61
+                               828ACCFC365CD5EC17D5CEE488A51192
+                               8826B334A1D7BEFAD7528BC5CFD32B82
+                               87F4EC603E21F528B51999F222817DF0
+            stream[448..511] = E2CB68B1CFB640B76DBFC5CDFD192AD0
+                               A7E8BE14ECDF6E20F1C8FD444D073108
+                               6932BFEF0EFBCB7F64E5CE79CA4AAD15
+                               846081CB229C74013CA0D498DDC69703
+                  xor-digest = 4BB7025AEEE0FC3ADE977F13A0853FBD
+                               9F43393A6A0B7C91534F5F2A47009D63
+                               79D0B9440D5A36A82974EE70BCF3634D
+                               131E754FC6BFB8DA62A05B3F4D1E9FED
+
+Set 3, vector# 72:
+                         key = 48494A4B4C4D4E4F5051525354555657
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0CD34EBF2677F222A589B77FC7284567
+                               C3CD391D85E3CBD04F43DCCFF830F0D9
+                               5C9C97371376B180AC2235DE4EF2E377
+                               8242ECD6A257FA02F2055CC7116A006E
+            stream[192..255] = 0CEA97153979B13DFBFC3F04D311D677
+                               9380FCA517161003A82CF5E00CAD8438
+                               18341CAF98A5BB7CC4D4E487A5878A3E
+                               F0D490EFD4834ACB92EE0FBAA3144270
+            stream[256..319] = 700797B741FF36DD80F72A889696436B
+                               A900033C957BEBA6BB3EE71AE3D79A83
+                               FB4EF28F39B0B3A0E36719059774E6AB
+                               CDB4447CB3CE6CF78E30EE239F537140
+            stream[448..511] = 44EE572970D5AB8C094D434DF6489171
+                               B657A51C610D370EE9517370780D81CF
+                               47A666A1556AC7B254DBFCB2D1352365
+                               F62B950D9457E4E364EA980C3832AF75
+                  xor-digest = C794C46A6A1C155D6922A7CCF4327038
+                               B48618EE29326A7555AC2A00122D4E83
+                               A4F17AB72F9A133F48750BF43344D561
+                               E71C69844840FE83889B542FC83D5132
+
+Set 3, vector# 81:
+                         key = 5152535455565758595A5B5C5D5E5F60
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AA9A1800F63A3D6EE6FAAE48B615175F
+                               F4EC441EFAADB6273B38087417E9528E
+                               BB3E9A8D9E81C6B7863D26C24CACF50D
+                               BAE956DD15EE335C99CDC981B4182545
+            stream[192..255] = 6F8CB1506073F5BF7E656C25BB46A689
+                               73EFED2E87229204BDB09910180C279F
+                               23341A1FBB0C40705C1EDCDE8E1BD8D5
+                               AF9F503901071A857F8315ED2F963114
+            stream[256..319] = 3EB29DC8A63E3B61A6EB1062F189BD53
+                               54A7DDBB22A6C3B7857D80E5A761836C
+                               4A91EC1C994FBAF781AC65B1840DD892
+                               2A82AF4D6DCE1004B3FDCDE790018C31
+            stream[448..511] = 00A6E02F4DCAEEE2FC77318AB9619246
+                               64E1DF835DD62629D035C44A1E147D6B
+                               809D6C60983B9767B92A10E35A651786
+                               B0B0E1B8FE8BCBBEF4D02BC625E5B402
+                  xor-digest = CBF02F452CCC84F5D8D3556876B7902F
+                               324BB22F3C676D3D5C5FEA182A4582EC
+                               57BB18419D8F82CC8C43737F3B356C73
+                               CC9452557FDE07F9CB3BCC06041C4279
+
+Set 3, vector# 90:
+                         key = 5A5B5C5D5E5F60616263646566676869
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E5605A67C46B013408F53D1D8A583699
+                               389267A63163901506FDB6150CAB719E
+                               D591787D8CEEBF1EB13E73F6A5D3DBCA
+                               CC916D41738008C5453132A472931D9D
+            stream[192..255] = 0D04AC34DE63ACD3D554E568B4E423D9
+                               76B22FD4C32464BBA143163B225AE996
+                               4658EF46C19E5C95CA14D9677098C303
+                               7C37E77446E8878A5F8794E00FD2E0F8
+            stream[256..319] = 1915755636B9E8CFDF50F532F6FD6C66
+                               60CA7E53C6037A532A39E56E61C6067F
+                               99C864B32049F95CC142B019BAA37720
+                               1A0C28D747CAAB42E81073F14818EF1E
+            stream[448..511] = 820E743AC49AF76E030EACE4D0BD568E
+                               781B2AB82257DF8C407C159CFFC13D12
+                               7B869E6E48C5A6BE72A5F1A9877564E3
+                               CE22D770D9FFE839BA4BFB8D297D3795
+                  xor-digest = F98873945A95030C43B22CE430D520EE
+                               F6E4F2FF30F2545693C7765D5EB19AC7
+                               A096799EDB90D661B1379264D5B42729
+                               E2CB5479FE63BA9B8D409AB98696248C
+
+Set 3, vector# 99:
+                         key = 636465666768696A6B6C6D6E6F707172
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2ACCA4B94538608F318E142FA9DA9DAE
+                               F2DA0FE10DC27C804C0DCEA927CBFBFC
+                               4F9AF87F67D962130A2DE073D4CBD1C2
+                               70A836BE81FF2EFA6CF910E6F558485A
+            stream[192..255] = 586AC09D4C7285B3CC8A49BBF978D086
+                               C628229659DA298476EBED38C7FCD86B
+                               59FEE45D41F480258A44C0615DBA2DA5
+                               E64B178A2E7EE3B02A316245152F72CE
+            stream[256..319] = 1988E499CFD61EC2699181A520C1C829
+                               3F0AE76B30C4BD0279C937D53054F646
+                               B318B13703EA193F63BC83BCD501C083
+                               D31B8E2DCBCAA5CB4B9ACF15EE740010
+            stream[448..511] = 797DB54E1E718B6ECAB6F928C3CF507A
+                               A8E58832933F404CE1331FD469643E78
+                               3F8BC3004AC7AFC5EF036F8B5D4DB5EE
+                               16BA7F94C39A39237EF93BAE10E427D1
+                  xor-digest = 75197D3AF308890C381051938649CF93
+                               157F5E1200E87F7A0CCE920B1A378415
+                               F1DBF671C49324EF517ACDE52BDDA9DB
+                               BACFB24EB2DDA3582DFF0F0DA9A7CC8D
+
+Set 3, vector#108:
+                         key = 6C6D6E6F707172737475767778797A7B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5B1C1C98D5EC2E066FE163A010AB06CB
+                               D81E8E237F4486C3C57C7DDFE9CC4E2B
+                               6C0C016EB38630B09823CFE1804D969B
+                               3CF93666F785BF5EED450D6CCAA1ECAC
+            stream[192..255] = 5519D71CA1AD10191586664DDFF26BCA
+                               7CEE6FA4C728BC0487FFF71236DD947C
+                               C7F84A9ADE9ACBDDB04CA4576AA11CD1
+                               19F676BC908335BE454957280423AB9C
+            stream[256..319] = BCBAFB8D31351D748DAEB21A4927FCC0
+                               D206C0DFD1EF6CE6425808BCBEAEE26D
+                               DF29CD37EF61A6C186E33E432298CB7E
+                               94A598588A7649C3639D3EEA43A4EFD9
+            stream[448..511] = 6FED1CDB9C109AC353D8F0A92B8DE388
+                               EF089BB8805D6622CBF93F4E70939039
+                               536C12BB7952550B4A9F62B8F99A3522
+                               FE12D79D52456E5E2B58D899CCC0A683
+                  xor-digest = 9A528A131B2DC7999743397DD1191EF6
+                               306AC8B7D333276AA11FC5F952DA12C4
+                               890509B6B3324B57117736A2FE462B97
+                               3676D4AB0F9EC5F40389BD1631DA30C2
+
+Set 3, vector#117:
+                         key = 75767778797A7B7C7D7E7F8081828384
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 19DD8D2D6FED84E4C8983761323019B5
+                               6EFBFDDE9D0DD65ACF8EA7064D876159
+                               34CA7A8690CD9B688A3A7E2739C0DD40
+                               87E931669B47FAE65582F217B703F744
+            stream[192..255] = 118247263D78B35C87001EE80D0855A5
+                               4BB82A2538BDC4CE4E0508BA9C1AFF2D
+                               F6E3BD124EE8EBBE9C5F8CFF809B22C7
+                               EC14FADC932266458D049847E4BBDA57
+            stream[256..319] = 3ED5D1F9FC223FAF7C35165CB00DC41A
+                               948089FE364B824970DB5C8EEB277D5F
+                               E1D7EBE4133BC0B5C9AA277360AB3D59
+                               D990F5F7F8FB2D4839F8DF8F91BC8CD5
+            stream[448..511] = CA652B9B5179E5FD45CDD84F778BCA9F
+                               A5E029B0D5F8F8DC9F6848EC6FB90CB8
+                               B5D6D1F65BAF94B02FAD8F432901B2C8
+                               1DF0A7BE680810CBAC3FAEA492EB49C7
+                  xor-digest = 1D54E85686E20E556FF40B2C310505C8
+                               B3E341EE7DB6BEE6761CF0FF87D56DE0
+                               3C08007AC388112D542875E0F56BC435
+                               EF698DE5F550B2E6DADB7CF899C670C7
+
+Set 3, vector#126:
+                         key = 7E7F808182838485868788898A8B8C8D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A865C1EC58AEB098342D771FD9DC8CC6
+                               257144135060E17F794154163B5B50E0
+                               C175DADFE996D8D9EDC24F528B403EBD
+                               31B181DA7621E80465F5609656D2F6BE
+            stream[192..255] = 6E369A08D533239B1813FB1E64FE4016
+                               D5A168E7B082AC17782FD536B1614EEF
+                               9B96114431A8A20901442B17D359AA8A
+                               616CDFF610EB376A01A5424443724BC5
+            stream[256..319] = A6A4AAC9510367507B3ACD133FF4621F
+                               EF8117A2F74CE892273D852801F6B788
+                               3B4CFA27124C42D424131AFFF2890AF9
+                               B7EB6F70917407991169997C9014C6B8
+            stream[448..511] = 54DA1A3C64310F07888F043684AC5081
+                               B35962F34CF46D8B1BF8CB9079A0CB7C
+                               3AE2998F6A247D758D7C435F2A509E9A
+                               164A0CB7F1D9FCF1DFF99D2C7074198C
+                  xor-digest = 44F37D188FB59A4BB0BBD69BE1592797
+                               65135A26C7EC258CB2FFCA9BCCFDC005
+                               E9971F4128215E73D9EAD8C6B0465C98
+                               DFB9065DCD07E83DEC0001A737CF8DFD
+
+Set 3, vector#135:
+                         key = 8788898A8B8C8D8E8F90919293949596
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0707B0C6C7CFDB502FBA27A9179AC77A
+                               8EC79404E4DF30E46B0512EAE40876BA
+                               A0129C7C6A7D61A264654AD3C7822B68
+                               80AAEF7CEAB7CDC898F11F217BF705BE
+            stream[192..255] = FE4ED3B451213FDF4847305FEB8E9FE1
+                               2C359E24DC7AC0957DF2558D300FB0CE
+                               D38A9983F6CA936514983BD48F80A596
+                               A2CE35993ACA48ABC500BE4E766699FD
+            stream[256..319] = C5BF4DC95100E2D7F6792F6AF5F31371
+                               53D418611ED358EB8646CC359FF18770
+                               93C18CF26FC4DD646ECA8C4A199539C6
+                               64C92D30F2F3D652DD2E4CF66A6F1725
+            stream[448..511] = 588425C16BD8DDA6D1D34950A40E35C1
+                               2CBC1F62542B3D3F6AE4069DA42CFE09
+                               8B36BAFC94356A4EFFA655EF8DFC281D
+                               F47FA499717D95FF7CA81EA175E2D6FE
+                  xor-digest = 4F543EF4ACADF04EDCEAB6841B794C70
+                               B9CA52B336CA4D6696E5AF632271367C
+                               29815CA30CB0528546FAB08A6AF9016A
+                               9B25460BD71FC1D00C516961D3A0B448
+
+Set 3, vector#144:
+                         key = 909192939495969798999A9B9C9D9E9F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C95BF1BBEAC136B08DB163D8A12CC5D1
+                               53D2C485C257E16BB5EAD3B93BA84D32
+                               352DD608CE457C3BBC55864B1FAE0296
+                               1180FA7063C3E9AA05A471F89E9E8C92
+            stream[192..255] = 112D3B048885FE87290E91C2288A605C
+                               669795CAB3F78FE8C6E15204E0FEFB5C
+                               9D0C690C2CC57882AA3C276E94414DE9
+                               376531151D9BE1DAC6D784E95FB196B5
+            stream[256..319] = A073295F2907C05C3CC3A17B8E404338
+                               0BC74C10864FE1EC6F043DDEA356CB48
+                               4159EF66A944668B55131F4BE61D7F4B
+                               4EDA1CCC0CDFBDFFD79B9A37D4E0DD01
+            stream[448..511] = 42834D089F1518A4E6167174E844E51F
+                               C31BE2238B7C2F306F1DCC3FF7DD30E6
+                               E9B0CD089B9F9280EE40D3416339E1D3
+                               47F0E29593168593203825261191D02E
+                  xor-digest = 86960034091CFB6A6767B53B66713632
+                               C6272B95347CB92D8D084E8794984516
+                               4AA48669D26826E2C84907C2CEA78727
+                               B0D3C9E240A361FFA661F00670C3060D
+
+Set 3, vector#153:
+                         key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = FB01986DB035CCE47390DB060C6A31D8
+                               3C9E93F728E785ECECE34E41D81133A2
+                               69C5917545B1FF479F4C45BD1F6AA46F
+                               3F9591C54F3D67A8BA7AB6DD9D7D07FC
+            stream[192..255] = A056ECB565EEEE24B5C42C501D78882D
+                               A9AF1A9B5BE4DAD286E695A23D516D52
+                               CA83FEDE7CA0853C01D8043CDEE992FA
+                               1F71C90DD5C3C95ADD5FED24575A4DDC
+            stream[256..319] = FBDC6515174B6E51F3A9804AA2C34DD6
+                               C03F0EB5202CC36D5602D58A2630390B
+                               C9D7A452680F152767F4558B3160BFBC
+                               EFD49175AB0FCF62D2FCB8E78E1CECA6
+            stream[448..511] = 774009D68AE972386F6F4D0467963670
+                               3E08B4CA05B801C5FC84376343B505F3
+                               37B9052F7280733BDCC026529F48BDA4
+                               765D1FB436CDB3DA0FB69F148894E8A9
+                  xor-digest = 41CCA3720EF5CE5F8EFABE447C3BEC9E
+                               DA338E5ED14ED24B21F66BC010077475
+                               16C61E91AC9E3501F2E8D9DE2E619ECD
+                               F995AFBA554A8AF21E89EAAD9FBE9913
+
+Set 3, vector#162:
+                         key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0DB9C95EF6FA9E4F256789098C2F589E
+                               F5F2C63E8F38F81661A22842C4058E42
+                               D62675CF0F435C6441A905C46A5E2B55
+                               98D87AA7483D5036DBC6DA6F795B95F6
+            stream[192..255] = A195496ABF83B1EA9BAC8FD119F0514D
+                               5C01B2A262090DC52DD00AE0689DA3E7
+                               D9AD502FA2F3740EA254E8542296A3C9
+                               DD4D7ED40EBDAF2237157BB197887DCC
+            stream[256..319] = D5E1BC7E5C9B1F47FE69662C94D2C83A
+                               8B92217E877379F8BAB56CDBD5406CF8
+                               C18E1E2F223226EB9ED272BB66F7AD60
+                               ECEE3CA6C84A5E1BBA1DA733066C0D6F
+            stream[448..511] = C79F97FE9EEC3023430857F95A1541EC
+                               BEEA487C1C072F81736CF02AE97D1A77
+                               2C81A69FD2C58D85976DE47F09958BCD
+                               4382435A952C27B45EC6E387EB0A0333
+                  xor-digest = 65E3A3C2314794333A620A28C23D5EBE
+                               884D04CCEC9F7EC8892535B5E937C9F1
+                               D2B993451DC35047872F562C9ED5EBA8
+                               AD36B8B67325032A2C135495CF8A1683
+
+Set 3, vector#171:
+                         key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 505F4C9084D6F5C640C214EFED9E2DF0
+                               8EEF8241ACAE98072B5B3EDB72F1687D
+                               586B2569DC7F58DED2C2BCD134CB6CF3
+                               D80A7A879D7878C080A5BAD5ABA1DCCF
+            stream[192..255] = F38E694DB538EA115B3F765694B7F647
+                               BD16B1E50C927528B13FA2EB811E8E8A
+                               B7A56FCACD80B1E7861733E0F8289E5B
+                               3C461080A858FCAFC85748DC11CA007B
+            stream[256..319] = DEE9825C69B6F6210381ED04A152A029
+                               A7ABC8D6C23D2895B968142E3A9C4D16
+                               8059A067F309C2E9491426BD0953E4B5
+                               A6E545EE62D4E9363205FA50ADECE92E
+            stream[448..511] = E2C07AC69B0D646D013AB6129A979A80
+                               0977C0B2E3505CD4DB4CCB4C2D02A936
+                               DDE87099B8F69301CB8A441A1CE6EEB7
+                               9EB73A32F54D1B3AA1A5FAFAAEB0BFF5
+                  xor-digest = 58B7C17AF5B37A6806E8019BBC243F2F
+                               779B2961C0FF27B78EA54587FDA31F4D
+                               43AA70643AEB9BA547F814C57107B760
+                               8D3DD6B06C6CA5BC0FE55A31274B4B5B
+
+Set 3, vector#180:
+                         key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F43EB3DC7366C02A6EAA1BA286589786
+                               3A2221D8679C3F0399B2119FB09D2717
+                               8C262A1CAA0711E961209288EB03BC19
+                               FF9FF74773B10AC28295FF3BEF1E2B70
+            stream[192..255] = 453BA5A1529349A29B1CC75B9835E642
+                               9587A1E06F96A5E575BEDFC7CB6E6C79
+                               C7174D10F908C1688E9CDF6973971A89
+                               2764D7412F054D772BF3B97B194717B0
+            stream[256..319] = B2353310A194E71847B541FA5A301E56
+                               6678FF7148960C4C2EE2139A338EDC4F
+                               082A79EC59E094AE01E3D9585033350F
+                               7E7255838EA448658ACD1D1B56546188
+            stream[448..511] = 647B02009ED90BB30849D5136432AD33
+                               759097A5BB30DAA7D768FD7F7F5FFCE8
+                               513975CE19501ECD4E194A1C172F7A01
+                               E75BE6598CB0BBE4DEE6E1C364BF9C36
+                  xor-digest = 890A2D288B3BDE3AB9B9214DDFA6BB03
+                               390FDC8925358A0C99C44543C8EAF224
+                               64635D46AE1FCE0CA494A6BC7F127F23
+                               2B8EC742C518A73F6B2DE22F2F564749
+
+Set 3, vector#189:
+                         key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 17638771CE9C92633C8820B9FF9A7D20
+                               C0BB3ADE5D49E16EE463A6F768D0191F
+                               F624A8E1E36DBE1F35EDB6EBA4587DA0
+                               AD633F1E6CA8072A3871C580037F202C
+            stream[192..255] = 36358F7049F57244EEF847ECC80803B4
+                               A9EDB8B97CF098F87B047D02FAE2043A
+                               B4370B7C4E87777E049A79CA833A2F40
+                               DF221E8B34B710591A24937D19F39BDA
+            stream[256..319] = EC6A73C4A816CA1C3D1DC0B2A1AE5409
+                               AFEA32DD3B961BCE9F27FDF8B46E8300
+                               28C2C75C0596D1394E579BB4239FBAD7
+                               258C7BC7FB9E1C5465439177E454FA6E
+            stream[448..511] = 1A5ED8E740246F0744218C31668F081D
+                               333CB2C4416504584CA1AB6E7C56C82C
+                               AEACD22E01CCC23C1A9E8BE94AF90C7E
+                               DEEE590D8F75C9A1EB2134CC1A44AE0A
+                  xor-digest = 2D664EC9400F9864BFB1CECE43DF3971
+                               B8EEECEFE3507CE09F6572A9C9743EB8
+                               58B433A6FD2DF24605BB505B4D732050
+                               8C89F38BAD818FB3893383DE2C1ABE08
+
+Set 3, vector#198:
+                         key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AECDF83CEAFC62A35AAE0B56DB5E6608
+                               3ED8144A470316E5768F898741181B39
+                               BE1B44248B79446A2B8551A7F71009F3
+                               4BA3799E8967A961169A2949979698BF
+            stream[192..255] = 1162529D235C48CBA87E0FAED1209825
+                               4F0C650835F5A0C44B01FC1AB0A53ACE
+                               496709D34D632E42A98CDA3A14E033AC
+                               F01E869A8263D0921619C26D3EC150EA
+            stream[256..319] = 30F569D183A30142A2C85002A7768DB1
+                               1B12025C41B0331458BE45DC53608B11
+                               63E130EC0D6940C2DA7BCB40881270F1
+                               1D79B941B6DBD4B53A093CDB9DC3BB08
+            stream[448..511] = 6170D203CCDDB9E93F3BBA8E195214E2
+                               485BCD5E96031B5848C433D2BAF4AD4E
+                               2050902F0E6F0D71D034909B58EF6E3A
+                               D8D72DFF40449A96F9DB8A2691FA02ED
+                  xor-digest = 8D8C29A1126A2C135938D456B61C1C22
+                               88F42EA3CC4AE32C2D9AF46A3393EA9D
+                               13719D95D2EE3F62D261807FBD4B504A
+                               A189EF6CEDF6DE1CBD0C9223DC485044
+
+Set 3, vector#207:
+                         key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 03FA3028E50F89A3A26FE0C9A59D4D8F
+                               CD4F6664621464876D0DD0070C3C4A4F
+                               BEA73FCF1858F583277C9A8AB098DBD2
+                               CE9DC0BD491A0069D48812B45D99BF6D
+            stream[192..255] = 4BFA1D3877F91E02E7B59C2BA54E80EE
+                               88FD0217E82EDB379B54F8AAD1B87308
+                               E908A3740DD0A6BED98D95A89579E18D
+                               B12960A3E8C2DCF39F84BFE48CD9D8EF
+            stream[256..319] = DF87530FE64F198DE0F5685C24E6F752
+                               776A64B5355FDCC7A734A195350A05EF
+                               A9BCBDC50D12A81CB89F49F330EB2796
+                               F3C0EC3A2AA823AB1787B4AE2E9F4B84
+            stream[448..511] = B62D2660AF636D037FF77CB2DA14EEED
+                               1DA4C10E4C34C3A170F00753256F021C
+                               6B8058A71680B8AC68F0E7B73D491E77
+                               21CB13DA097FBA6630DC814920993501
+                  xor-digest = BFCA05D3C5A76AF3016B56245C890022
+                               F173D207ABFA1355C4AC75CD44440227
+                               40BDF92FA07711FFFB49C3FE49F63375
+                               F242014728E308CE8261AB6971D82EBD
+
+Set 3, vector#216:
+                         key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3FF2373E4F64EA27FD8C86D971D6C497
+                               9AA558C47B291B686BA3EB4C848320B4
+                               C2614E739FC890F78FBAF82DDD01EFE8
+                               D93CF5A5068A0BCC4FE41F87B4FE82D7
+            stream[192..255] = 7BD47D4550A516BA255A572D948C143F
+                               8B46F2FDEE81E80D21E9A64A27A89FC6
+                               B00BF842251F5094326BA41055D83D75
+                               3A7A4DC88643BB8D8207CF4E6B5D6360
+            stream[256..319] = 9EC176E21634E97E52F5D8D42BEC590A
+                               5F4A6D0671BE640B7AC3C790AC521911
+                               3862151C7EE904BBA1B1254CA5FF8A72
+                               83EE9F0A3CBA3A0A38F3CBCECA7AC751
+            stream[448..511] = B87FC33D6F13852603A069DD88143790
+                               4922F8B3B98D383B7082257077DCDD01
+                               1B2B0390F6B680719D91B815A0421DBD
+                               5F3687097C63BD0AB1B59EBC12441A43
+                  xor-digest = 819FEAE72A30198453E6B7E0566459FA
+                               3A325C59B0B1BEC7B1311FEABEFAFD0A
+                               F7EA6A01603CD81DE8E338740573C01D
+                               94D57B04AC8F4D5CF26DDCFB7A9A85CA
+
+Set 3, vector#225:
+                         key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B378200C66DABE0FB33FFC336DB91F9F
+                               25F65CE152EC1D11738AE1DFA2B419AC
+                               31AA2F559A63CE39B8829E2E880437F5
+                               7D83E3680EB41CF262A6F8025EC8E733
+            stream[192..255] = 739C9F273A1A8312214B4B3FFD58615D
+                               AF751344F8D36BBD79A11BBA93BD0AA3
+                               34CA56667A6B4A98B6209F0765D9E4A5
+                               163756D6AC6861A8DE65777B9B5F4950
+            stream[256..319] = E7C1F35E0596EAAF7954E0C7F0423C54
+                               60E23A0106FEC3F1C4EBC571AE016BD4
+                               B232C2E0A8C079EA1A5DE6A2D18B1B79
+                               5E69ED4DE32AE2011805A439493223DC
+            stream[448..511] = 91D8B977B8BD9F8E84C097AB9454FFE7
+                               794908D3B1D98729036CF2DB77056F10
+                               582C1D1EB084EC97943117FA428C5B9A
+                               7ED1736E05BCBB55E9E0ED1FD0113860
+                  xor-digest = B05B91E712072C9FE4AE5C4BCFF3AAFC
+                               954380E58A9F264458EE46ACE1194032
+                               2B1CAAF21117E26A6B490A1C93761A49
+                               92982F4277E36ED3C4B74D31D3BB2ABA
+
+Set 3, vector#234:
+                         key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 77D958F664235976A8696CDBF0A3362C
+                               BCF3EA19D524F379B02D403F79F9A067
+                               BBE8F1365B0BCE68699E0A0DA273F117
+                               2EDA63B4558B062EF10743740825665C
+            stream[192..255] = 99B50E13CEA45209DB8FF0F3FFDB568C
+                               7EFDB1E021435065668313F23A57DD75
+                               0676F550EB7C5C5FDD65EBA84B00AA02
+                               E41039EBCB5AF806339054EC8E9C9567
+            stream[256..319] = 64CAF7DF8BDAA26D9BC8B49F99CAA94A
+                               0ABCD947E23AD676E3CFC95B4461CA78
+                               C17DF55D2ED805AF80B24BB57E3372A5
+                               4F7BD4B4A1A0F65581BF0D409198199F
+            stream[448..511] = 98595F685F9884606A085383B2437A8F
+                               8D8B7536D30C693B13FDE9F19DB847E5
+                               22B1C305A9BBDBB1F0D402A7794460E8
+                               DF5A4E719CDF48986C7E0B91A801742F
+                  xor-digest = 54D02F27FFB007DF1686027BFE0F4978
+                               01C265DAFA66F72EA530F37F82E8F25B
+                               35B6D7E2BBEB36F4DCB98C7526A727F1
+                               452296BB074B8BCFB878A5299E052B9B
+
+Set 3, vector#243:
+                         key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CCFFAD20ADF1C4B744BC6B2EC9CB29B9
+                               12F5577164F188BEAD1B8F5884619756
+                               350C6514969354F92C33DBEB3553E546
+                               D00B7321409CF15C2B1BF1D30E1B808E
+            stream[192..255] = 5D2AB87447F536F42DC3423A3F5E0C3D
+                               354B648D49A1D613E741FCA61E450D7F
+                               4777CB7F19557AFB0E3A49E8005255A3
+                               EF71C5389A5455AAD803CAA30C75E263
+            stream[256..319] = 53764B5DDEF40B7C66414E2855FB5D70
+                               BCE612CB71A7478D3C8D6B42918BB8E1
+                               4B12B5D48BF8C464B60214CE96E1CB2B
+                               6055A167B6BC4BEC2FE87B4C31441CAC
+            stream[448..511] = 2E4FCCA6545573B051885454D384B365
+                               546DE212F89E14DFF2B27A97FA3D5CD3
+                               BA797DAE4815E8E01629F4A95321E1B1
+                               ACAE5AFBB2E1FF74D0FA5A31E09A76BF
+                  xor-digest = 4DCE3E84B2FB36C6A268933805F307D3
+                               6B9F8B2ED75BDFA9528F14E96CDCD7EF
+                               77AD88BB08CD19BEA854C1F66216EB4F
+                               CF23FEC02A128FFBE7219244A72FF66C
+
+Set 3, vector#252:
+                         key = FCFDFEFF000102030405060708090A0B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 87E3FC12C86A001AD83DC4B364F49F3A
+                               331C286890826198B6D4937E6804F17E
+                               A9701A1AE8BD09185C1803649959AF65
+                               1726A25C54533924E6112F923056F09E
+            stream[192..255] = D6E5A2371EC564FD24213259599665D7
+                               9A31404C3493E005F611116C7F7B48FA
+                               CC6A949BB1746BC5EFE93D6114A1AD5D
+                               444A9A0391368106BEC2D5DAB96343D2
+            stream[256..319] = DBB63AE5E1B11D8A014CDECDE7B03DE9
+                               D59A473563285D52DBAD3E7E4C1E99BE
+                               C455E7CAE251B3AF52234CD9DE49BA55
+                               2B19E5A721C994EA57AFF2239B42C0F1
+            stream[448..511] = 339B85580D35BA903A85D2B45249FC31
+                               182D7E1B894DE9584906C2E210319EA1
+                               168E2E9C582CEBFCD96BEAD69E22CAD1
+                               E9C5AD2D5E3B708DC1F6B7E36F6E65EE
+                  xor-digest = B3DA36B9D7E12E6761A1C7F8533370F1
+                               E1D4C4EBA89ACFCE4F24FAC989A7BA87
+                               A1E0E61BD5A89895C04513D4813FE066
+                               6542738B77319BC7282D3209CE08CEF0
+
+Test vectors -- set 4
+=====================
+
+Set 4, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B1B7CB35C1FFBE7A34E645B05C98501F
+                               2364C719BD94186DCD66351EDEDB5179
+                               169D2EFD6BF03AE1B149DA229BE5C961
+                               37C10C3210F8FF34B51A366E437DE0F3
+        stream[65472..65535] = 5610AC7C3006ABADD3E0AB13B3D7E945
+                               586A00964AD6DF9939835FD46D8B2327
+                               15E447AA5D5CC4BAD03A495DC38BBF1A
+                               5C86A7D608D397694BCCCB029ACD1883
+        stream[65536..65599] = 1D7469F8EC3D021C5FB418A0D46A19C4
+                               A632A7C1BF298B500ACC2D5C39384F5E
+                               7837C964465FBF3990602BE3381FF556
+                               38114E41DC091B0AC1BC51FC6E70F98E
+      stream[131008..131071] = 5F1A8DD0D98D377C1378785F9EA7A3E4
+                               B17C9625EFE2650D845A4BAC7723B193
+                               A3AAC199A1950D7CB1D66380A566A8BE
+                               BBCEB0DD7A700C5ED74E55E29933FC6F
+                  xor-digest = 3E9A70E4A49AE98473313B957F781F09
+                               237A172CEFC9068D4F95CABB57358B7F
+                               40839FFF4258C8BEB466A975B4261753
+                               02BD1F4B9D4621436213703A3B99A719
+
+Set 4, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 54182309BD782DEE44FB59B0EC694920
+                               2B372AF8D715271A96D87867E65A067F
+                               A5E52B455B76D400537B5D47C4AC318E
+                               EE4C2ABE29F56107C213071C85828605
+        stream[65472..65535] = F7D1475B3FA625D86467D4C24915038C
+                               43D9B81A13E7A08B333B8232D7F849B3
+                               1442C014F49EC5814E15B607F11A73A9
+                               61C04D305B2F71B7B22DB9D6055B7371
+        stream[65536..65599] = CA286F0F05CD6C3BDDDE6108C8A0AECB
+                               F6ED3FE2A39A976D7970FD100A242464
+                               42D867162B87DF26EC2B04A990AA7305
+                               94C8072994E80B2D6426B90AD0873B61
+      stream[131008..131071] = B1FE56B55C9BB460B8EF4F9157B227DE
+                               AACACFAE9009C61C16754EDC913AE3D0
+                               BEB00C99095C48A12F4485E9AD56BE6A
+                               6F9C214ED11E94086F32F945C0C3F6EF
+                  xor-digest = 4667B465D4CD7E215B6594B648B05EE4
+                               7D2770A69F5FB3A49AD66C1C823F2E6A
+                               AAEAF0680A232F35EA7CAE919F477301
+                               0AE66193179E51600ED840D5047F5493
+
+Set 4, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 203C7A9050F5E4F98CB72D913B8E7FB9
+                               BB2635F8ECCDBFCD231B4EDCA96A24A9
+                               9F71BDD76CE42B982228ADCF9385C702
+                               C2A767488DF42D5DBD8DF2884225367B
+        stream[65472..65535] = 94E590E29B3A371E5638E55DA4AAA1D2
+                               F2369CF9EF69EAA0331B4AB01FC1D7E4
+                               D27A41EEF2C15C51256EA111933BB71B
+                               5E948DE575258966A03ADC426A3AE9E1
+        stream[65536..65599] = BCE13EAD9E39CCB67374B7D845B1B347
+                               DAF7C440162CEA622CCA3E34E9BFE35E
+                               10828358DB1F595C19A0A0CD16C127AC
+                               D49903A5159564038BDA4EF156F9D004
+      stream[131008..131071] = A4300187C3E146EC1C0F3568C147D668
+                               D00BAF2EF5E1F71686DC491745C6FC68
+                               27F54AFEF7B2DBF9F65D5FE549B96919
+                               4BDA10595556840647DD2A4BA22EAB63
+                  xor-digest = C575DB999E785911A2AEAEA074EA0CD9
+                               2BA978DA488A3657341572F1B33E8009
+                               07977C738874012CE18E487514FBBFFC
+                               A2E645EB4632862812B7596ABAF1ACE6
+
+Set 4, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4A82E7937D7C52907515CDDDC1E8445F
+                               D0ECAD783B25079AEDF9D694CE70B723
+                               792E33F6FFFD438EECFD3DF933AB48CA
+                               7EFBB13A31C1E3E86249B8F9D188B7A3
+        stream[65472..65535] = FD302A0A44AE5D3BD5554C508BD70D8C
+                               A1803BE72ED426B8D57CC13F899A846E
+                               5A7A326AB25645EE27A84973BDDB82EC
+                               103AB97C16080C5FB117E10A8E252A4A
+        stream[65536..65599] = FAF43B81BC56F7E44BF5FD5F49581FC3
+                               51244ED84492382D28A591C022073350
+                               4F7B0267105D68566E9FCE5B52B7EC5F
+                               12A9131FACDC489279F8AA8E9E8E0A2A
+      stream[131008..131071] = 37C98A0BB719D5E166BF79AD35EBA109
+                               9560BFD07144560F4BB91C88B34C008D
+                               E7665BCA98D7B65562B57CED509684C2
+                               6AE9011D0A9D674F30E7F9DC37E680D1
+                  xor-digest = 7139AAF66BE2A8CF28852D9FEDDF47AE
+                               E1E229905F11F191AD60CDD2E1C9433F
+                               41F1D4BC92B10C8B988824C86B04100A
+                               EFF77A48980691C5636814E04F1A656E
+
+Test vectors -- set 5
+=====================
+
+Set 5, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 80000000000000000000000000000000
+               stream[0..63] = 337F8611C6ED615FC2E7D28C6DAAAF1B
+                               2382AE24592D1E61218220A3775F529A
+                               7F050B7D4262E3600940F167742FBE4C
+                               B0C147B3C0592523B890E76F59AFA3A8
+            stream[192..255] = 47B4B94D6032E42E28BA280B06863134
+                               0E65EF25AAE97BCFF5CA83096477B186
+                               352757FAF40E7DC007FAF51484B54651
+                               2B089A7BD3359258F3E8C0E3DE07C316
+            stream[256..319] = CAC4ED541686A3BA14A68CAE81C0B1D0
+                               D973129F8FD712F1E344CC7815614B23
+                               4412F351202D4FC7B622D905B8AC50D6
+                               59613FD8799443F89A8E403EB46F7492
+            stream[448..511] = 5C4ED1241AB7210EF543DC2732594AD5
+                               CC5A18AA3AB2CCB9B2BF17CAC28F6105
+                               1152291EB8674493A12C0B3CC2C7EE09
+                               F1A258C5E078080F5EA70F3F587BEC5A
+                  xor-digest = 4EF4B4DCF35FB72D210AE0546DD4A3FD
+                               9FE632736122E80559A32FC165E9166B
+                               59E2BB15A066307C88DD32611EC849E2
+                               A54DA4B47C5E52AC26375D2585EBE798
+
+Set 5, vector#  9:
+                         key = 00000000000000000000000000000000
+                          IV = 00400000000000000000000000000000
+               stream[0..63] = 982727CC7FECD8C15B09E6967B624366
+                               FC902BBFBF9C608B240626B735C6009B
+                               B6969A8D40EFD0546B056B181561034F
+                               B51A6D7C7BCB34447CF5CC560824BAA3
+            stream[192..255] = E8E61B734A6EC0DDCB4DF3248749B14B
+                               6CCCDADB8F24A090B7E5A49603C475AE
+                               8B6F8353E12FE7D8CB3EDA81E6DE9778
+                               2C52BDA59FCF4CFB2BBAB2D196E08C85
+            stream[256..319] = 06594AA97EDE3ABCD9458DEF29A7FEEE
+                               91965BACFA6A272B31BB644596DC5C66
+                               8F93AAF38F1EFA50D88A9517DFB4B409
+                               9E91F5A1B07C9CA8F36330840A6FCF76
+            stream[448..511] = 32784F6FB85DB3ECA696DD98D75A5031
+                               B3ACD087ABEB6489F20429EBBADF8D87
+                               B0D7C4D54A8A80FA835B5FCDB901CF32
+                               E60269C5DE89409A61ABAAB00B7D8B79
+                  xor-digest = D696A18B23B0927FCA5B766F8C19CE2D
+                               C98F40963485D0A77D92D0096334B9F3
+                               834491F8FB7C5D8BEC499F28A37B7DB3
+                               8E8A6291C1A6F73938B7AF2B74425996
+
+Set 5, vector# 18:
+                         key = 00000000000000000000000000000000
+                          IV = 00002000000000000000000000000000
+               stream[0..63] = B3EC726B0BD04F969BB34A0DFB1AF9A0
+                               880ED66663BC845BEC2CEA9BDDCB0E3C
+                               E6FD6CFE389D544D863AD6B55F45F4BB
+                               14BA866A72D63E4FA83246498EF685FE
+            stream[192..255] = 549E7B93702F139AA76FFF7CBB04EAD4
+                               C091015E6455A9855E3EBE4AB1A80737
+                               9E3E9C9418B909CC26E53470CD323FCD
+                               ECE6BAF53D45BA80C4F03A412FF160C6
+            stream[256..319] = 9599223B02F81DF5D31CE7FC6FD92D70
+                               71ADB8985B61709E6769EF5065905E46
+                               B0AE83DEF7EAEEF01A49D5D855035AF8
+                               6AC78AF9C14A3F8409773252EAC28D4D
+            stream[448..511] = 2C58AF08679A8AE28AF30688B33C417A
+                               392A6E8D6658D262EE24B479CBC4BA4A
+                               C5DCA537CCE7B110489817F9D2858D95
+                               E006D338BA92D7FD664F9CC773AB67D3
+                  xor-digest = E52013C82C2088C5B76988031F0A0930
+                               6322244F357700E3D3BDC71A2385B4BA
+                               F6894A2B177F7BA78D5935521CDB5689
+                               31F7706AE3413B10128CB903D7E27160
+
+Set 5, vector# 27:
+                         key = 00000000000000000000000000000000
+                          IV = 00000010000000000000000000000000
+               stream[0..63] = 6727DB24106CABD6C3A14001BC9E3B5F
+                               90A47B78181576CF5398D8F190CEFC10
+                               6615BDE30159225DD3E14A2F827DA07D
+                               C230D11AFEE96855EE06FB02D23998D9
+            stream[192..255] = 7B9AD4C2472D5816B963BC168F725083
+                               0E900C4E4994711DF7FA494A04A7CB58
+                               C9CAD5513E8C554B47060D9256B4F276
+                               2CD9790666A3C831FE1A9250C2C1F1B2
+            stream[256..319] = F8B0EF0C84EC8375A17C8C36B9F75690
+                               30D6D04687514709215F79B102304807
+                               3FA3F284155CD677B30FEDE6EE33DA7E
+                               5B35636C0F8E981AACF01CFA4E7B00C8
+            stream[448..511] = 023E93B9B5A526DA400CA8A818E506A9
+                               F5B0438F91264727C4FD5CA2FD4A845F
+                               3F2A6E0617A5619CCB0B691C2AE2F459
+                               A7F4764CFEBB22D8FC6AE8E28B08DD4E
+                  xor-digest = A6BB0A1FA9D79299B2FCD3AB9DFE04C7
+                               9BD7B88BB1A49AA7227E9BBD0A211677
+                               283EE5CF808DB24D05227305E67915E8
+                               74CB03402736AC8FFCD746B5AA4DD032
+
+Set 5, vector# 36:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000080000000000000000000000
+               stream[0..63] = 4BBA6A59AD3C1A7298CB38F244AEB7AB
+                               431AC1FEC2D091C4952794AAE9DA762B
+                               0873BEBD04FE1CD68D08654F1DFDD956
+                               59EF5E09238984D834F2631D67E16EB1
+            stream[192..255] = 945C61BFC21691064FDA05A6162869E6
+                               82800A1DB8E19818C2AB13A9280C8CCD
+                               BF9508894CCDE69ABC8A3F0CB2BA545D
+                               3A6D6E7D6E8B5E53683DC3E0018BE954
+            stream[256..319] = CD87390C68404079BCE794A554FC4DE9
+                               695AA78E626CF79094CF0374765C1ADF
+                               8C4054AD4B76535008F8466C806D1775
+                               1987361A852DB77F2CDDDDB34D00A15B
+            stream[448..511] = 319081F4D93C649E6D1D8C4999E0A03C
+                               F4AB23E4EB796B337C84898D6D9F083E
+                               70038515611FA040E686B893D89E28DB
+                               862C6D36F791F27EE05ED97AC636E836
+                  xor-digest = 1B86F56D5C6DDA97E2909873A042A48A
+                               C3C102D22F88E8648C0A7DAB5C34C98F
+                               CDF03CD03B6106095E3BA34969B67886
+                               8AB4D93CF24042F52DB659591D72D0C7
+
+Set 5, vector# 45:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000400000000000000000000
+               stream[0..63] = 2DD3C3CF5E6965EA02C31ED6FC539EEC
+                               E0B8D48345113E978230ACFE35089F9C
+                               D8EC821843DBC90E54010C16A8AEB245
+                               5881FC16B5CC21032958DAD18EF55469
+            stream[192..255] = B9299DC95D2F192F1C53FF23432158DC
+                               2746F64242CF9368D90FA217289BF31E
+                               6F08692251CCF86B2DEB7ADDD14D8E37
+                               0E4D877637A2D499924146D89CB77F44
+            stream[256..319] = A6F9EDFBA2E22CEF8E14BFE5B31ECD14
+                               4114A045BAAF0458BF149F073DF191E7
+                               022A9E518212876F7D6C99F1DDFACCD7
+                               8E0DE69FD43FFD26EBB7E240B5F4B864
+            stream[448..511] = AD29FD814401DB358AC8B2A911E743A7
+                               A594C9781D4F6560E29D8B67AB38D8E1
+                               67AC71AA3855D5BE67998E0B797A64BB
+                               1B26558FD861B845E9B08FA071DDCD75
+                  xor-digest = 2DE49729E28C8B4585BAFB291E77B7FA
+                               6CA9E489C437133EABC613D0893822FD
+                               70A8F88BF6A3D29BA6503F17F055A003
+                               A42605780A79501BB62C35C922DFB1C5
+
+Set 5, vector# 54:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000002000000000000000000
+               stream[0..63] = 8D3CF6CD521B43CF76A6ACA2A036B791
+                               7E06F44E8DE525306C6508C1FE2E3C29
+                               50A53F63B11B57596B76E97C1EB01612
+                               3D33B57CF93E839A169AC49207BB42A2
+            stream[192..255] = C009E0DECD6948B8F29A72F1A2BCAAFF
+                               04043B6B76B623CF977679D74186BB4A
+                               B1C3529D94A5DD5CCDC20AAEC056492E
+                               7B9F9A9EE087187C52C7651F890A0DBA
+            stream[256..319] = DF5DAAFC6D650B0A47AFDD7BEF56634D
+                               13AC2D1442AA1F082715882F9D303170
+                               8D338A7CFB14B100E3D3C645334C5D4C
+                               BA9534475D4BA687956B00E8EAB587AA
+            stream[448..511] = FB2CB04310DC73C7B7312C840123FB0A
+                               783F10FB63F507EEBB012E19A0FBEA30
+                               C324904C02E301F4CE2CC2A1198C0C14
+                               A725FAB705C5176CF19EB2184DF9825A
+                  xor-digest = 3B3136B100FF460D92A0FDEFE864662B
+                               324D7B8C7C3DAA46EBF02F8BD0960345
+                               A1FA8F9B7AB8DF16BC7FDF6B6AA0C61F
+                               FB1C7A599A6474A916A8BB9E4FAB9856
+
+Set 5, vector# 63:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000010000000000000000
+               stream[0..63] = CF1667BC6BF8ECCC72ED756D4623E979
+                               6A8E559E27ECE3DE4FD85DAA60757C33
+                               0C33EE95AFEE6A53D730671F695C0B04
+                               B5968DC2501F48D9A2DB7E20CCEEF297
+            stream[192..255] = BE8163A51FB1FD786E1E5197B5F3FA74
+                               900AE8111592D24733B562187D399B95
+                               79D5F751D722784832AA471C4445FA5E
+                               F2725E23A251EDAE66D60203CB862095
+            stream[256..319] = 8592AA7309D37B63AC539BE5B997AD26
+                               3F6C38DD169535E7BFB1C19965919F55
+                               F4502C5995FF7DEF3021D07A37B9E7C0
+                               FA5E8AD9AECF2B072EE1DE2F2E26DB1A
+            stream[448..511] = F05E64D5CF14CF99154EF83E27CFA2F9
+                               2B269E8E164F1B563F4AFC48C40B5FF8
+                               F40BFC7E59EF0F0B923F7474F30AC114
+                               95EBE3EE8630A214776286D01A20DA23
+                  xor-digest = 46136E7DE5C7186F1F3D04FAA100B991
+                               8FE7E8E02B36C72A92E5650F93F5D936
+                               5675B0D3BD84E5C3E7F5CA7E70ED55FD
+                               027C83E1CB1AF8BDBD1FF1905A6EB596
+
+Set 5, vector# 72:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000080000000000000
+               stream[0..63] = 583E7BA16D617DAD9F2A4A6A7BCB630E
+                               4248E8368A6F45F6BE8CF22C65964D34
+                               49A7AC0EDE8957127CDCCD3AFD666426
+                               B8BD2391698525CD3620558076F61EC5
+            stream[192..255] = 8CE8D0EAF9944E68D7EEA0F83ED86CBF
+                               F87B99C8D87C40FBDA48E777976FB669
+                               CF6A68533BA7875DAD0BCDEEDBD4D136
+                               DCA8A9C9C1C6B30C5CB7B7C5846755BE
+            stream[256..319] = 534AD0B12F8CD7797CAC9E23B1618AA1
+                               B707F28D000422CA73196498C86D51FD
+                               A63DFC791446094F4E146EA451F60B3B
+                               C2711F81B137FF4C0521F94447A486E7
+            stream[448..511] = 540F0CF1CAA5D5CA270FB71BE97FCF9F
+                               F1F30C2F454BA29561F7B7C2D8ABF189
+                               30D107F71560B26CB7E9E416F90604E8
+                               510D29FC0AAFD94EEF254F0F4C0C43C8
+                  xor-digest = 0986B6D195197767683FB8221A50BCA4
+                               A375BC5989C24422855F465CE537FDB3
+                               3894E7383CE580D8204694DD1E82D623
+                               774AD356957E36042735848BBA9649A8
+
+Set 5, vector# 81:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000400000000000
+               stream[0..63] = FF9484C54337D0F0CB2342A7E73B21E8
+                               BA933A679CAA5549AE6218B7E0FCC88F
+                               CEB6CF2158E19C1D30F4E0B0A2D5E052
+                               E4C73F2F2FF423417E67F49F45BEA7C2
+            stream[192..255] = 6AA4E5586B608D3F0E4A394AC7818949
+                               E538604293010925AB3D69AFCD1979C8
+                               A8289CC46776E762452246B54C6C7D3F
+                               E7BA43B8D901D2B55F2F7CE520DF99DB
+            stream[256..319] = AF841581E66BCB36AEEE07534A83B519
+                               60D0DE9740D320D1ED3C542B64FB122F
+                               506B6F573F40AF29A61DC42FE183EEB3
+                               A5D55D0272659028B9B5B353A6292105
+            stream[448..511] = 3E463ED75242C21811F9C2492A71D6B3
+                               E5B2BE3E50151A990F841EF0350259B6
+                               9C727194154288C62DF02075AEEB2598
+                               577A5C0B134EC1206F66AA96233D1BF0
+                  xor-digest = 0C45BDB39F8C038AC8E2E3C41A80FBF7
+                               7B74C948861E7D58F7A89ACCCB4A2D04
+                               7D370BD42B65DE42293C58BDFBC003EE
+                               58D71CA3D01313E8A74C7BEF66CAAC76
+
+Set 5, vector# 90:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000002000000000
+               stream[0..63] = 8C4921B72A3D11BE4DF4E326B9BF85C7
+                               351CF85FE98039D5BFDB889DC5721B17
+                               C02EFE07FACD2F43E95D6EC63F4001EC
+                               FE7355EB565B6E2CEAC64A995324DABC
+            stream[192..255] = 933FFDF78D118A083FB7CE405D042D3F
+                               9173B28879BF4A37A878EF2351622F42
+                               80D218DE417B8503954E991A31BDF73E
+                               B26903D1F7C7361F34D7F01656243B58
+            stream[256..319] = 88E77D9A5FA78C7E348DFE0A66AF1B92
+                               FF564670DCEC867E24AC78CAC005DAF1
+                               5953DEAEAF2C476C2DA514CF79A474DC
+                               D4E68AAA0D52394762953A8A63A0B3A1
+            stream[448..511] = 5FF4F24F6BC7585D16582944166C453D
+                               59A3CA9F9625A5946EE81F561CA183F4
+                               F6D5258F138E994DF848F532F613092E
+                               89FD262FA4899091596A1031913C6C5E
+                  xor-digest = 4770E4B7DB5C5FF7F64BAB6334A13E4F
+                               9DA6686EB2945463852513C770ED64DA
+                               4A0C3D96403F4CD1E96B7FA6495BE23E
+                               15506374CE556E7B50D3ED8A92A643E6
+
+Set 5, vector# 99:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000010000000
+               stream[0..63] = A59AA0661087A6F3498D18BA156FD4EC
+                               E5709F5CF1FF25B006382B250E4481FD
+                               050F68B95D56E1EAF77C619914F30269
+                               4FC8C2461200D9AD357F21E9DA08F489
+            stream[192..255] = 941E849E313B8E214DD6CD1C10FD8D18
+                               05C1892B15623CE0724A3028F978215F
+                               7B6264D4D5CBBEFE12920BCCFD204134
+                               1AF60D460B73D9493BA2AE7B314CAA41
+            stream[256..319] = 2F27FA6FC61D2D84C008DE836B0CDB1A
+                               EB0E62D5E327F88B8A62BFBE70789189
+                               9E1335D20E495D2181253647B0333CA6
+                               6833552B89571E3BC25190C791341940
+            stream[448..511] = 9DACDBDBC8258B52C41788ABA3A7D08E
+                               5D7919C0B583F6AE89036A4EBFFB3AC9
+                               7CD9E9B15E8C811EB6F2BDC7713115A4
+                               5291C4BCA5DE179ECC779093B30870A0
+                  xor-digest = 2C7C5D79F8BC2D8E7B62DCE74340120A
+                               EAEFEA33114403A970F1A51AD9EC9F9F
+                               63F630E74DD83AE5C6824089982685E4
+                               28FF20C49689DAA995D7AF2E80502425
+
+Set 5, vector#108:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000080000
+               stream[0..63] = 869923A0917A8FBD8F45FF074E83FA79
+                               D665A9A44C769CC200A66C254B2D4B98
+                               7D34D66E52EF7A9C7ABFDD7548F08631
+                               49C7CE742F6CA599ECD0BFEB55CC8B6A
+            stream[192..255] = 75386882B941CDA70FDB6D02F165B3C3
+                               B0C7B0A8E4ECB161BBC745EA1AFBF382
+                               C0C09725D0DAE6316C7B956577EE7F97
+                               C4A102B04437F24D2090FDB00B78523F
+            stream[256..319] = 04FBECD2FDE606BC32E46FD0B9950F93
+                               A742DC2534886A3B17C8EEC5CDD28B04
+                               5A03E7C5764EC92C1DC8AAC5F9D5483E
+                               A9890C7322739BC7C73CF8158619F669
+            stream[448..511] = FC322AC5E5635C8DC56895BAFD43A01D
+                               77807CC8CE57DAA306E7DDCC58B24309
+                               4497AFBA51F8EA62922C697FC2EE8945
+                               4926D4975219A40B2D6C9A9620634741
+                  xor-digest = D2E239BDF9A2E04082567893D06DCFB0
+                               4FE50753793F21380F6A91354836C508
+                               837A15527F914190F6F97BA87510180D
+                               67B13994803013B2E4D4A307D80E8EC0
+
+Set 5, vector#117:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000400
+               stream[0..63] = F350AB2F8E1B96AC93F1FAAED04BFB0A
+                               59EC1F7B95383E44878AFFBC5CA7D4AF
+                               2EE76CEFB67906469C9FAA59F4DDD24E
+                               D16796DCAE66011584E8A4B139E016ED
+            stream[192..255] = 48D1D8F4583937C77BDC1757C3DFF07F
+                               D0CD430F3667E37A6D4CE89217729AA5
+                               E480DEF30227A363C800A3153617B04B
+                               50322B06B795B0EEEA039A796C7B6664
+            stream[256..319] = 4DE5C06008FBF0D54EE2E2052AF4EFB1
+                               94AEE33EE7F133F225CDCF2C504AD2AE
+                               AFBB2A2AC50D7F27022DA8D83D6B44F8
+                               4545E8BD15E33CE531C3A7E076B39BED
+            stream[448..511] = 837C91FB8773A4DE4FE79D163FFBD186
+                               2A361B96D79AADDE5AE964A62B3D9CCD
+                               1DDF29D845EB581C33E3ECF1CAC4AE15
+                               3C75E0C5ABAA960389FF0C92205CF575
+                  xor-digest = 29B708C591EA72969C5EAF624B943D55
+                               3A55CD66F13E5E762D6808F5A58D77E8
+                               8CE91C0A7EABDEE8F30C05F4D48C0257
+                               9B38612376DB9E26AE70591760E395AB
+
+Set 5, vector#126:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000002
+               stream[0..63] = 073CD91D0183F07259608257E8267FA7
+                               8799B748A5FEDA25FD40B463F15639E4
+                               CBA06A504C5D4E80A542366DDFDA8EEE
+                               B21BE97CC2FFDFD5FC93792A7CF1C2F7
+            stream[192..255] = D310A845416E7E187D3404B763B46BFA
+                               7EB62B04A06DFD0AC6E9871EB8D74F32
+                               73D7488C8D2197515DBF84ED8EBD3F24
+                               A4B3B69DABB27A3CDA6DEECF2F58EEB7
+            stream[256..319] = A8058C140D6692480614EAEE7AD97DA5
+                               F4423B249C2F0413DF35530CDC40417D
+                               FA6D5007FB9488A073F0631AEC501E15
+                               A94EEF50A2744693EDF07273C5621056
+            stream[448..511] = 44220A7B36E147C5C3F41FD72FD88F50
+                               ECCC2364563085D3409C5508DEE719CE
+                               327EBEEF70917036C37A534B764A4DBB
+                               39B77EDE8C115448096C7E2BF2EC6720
+                  xor-digest = 07C9AF7BD2DBDE982D011798BCF014FE
+                               F9334DAF537AF14589BF2328C45D327A
+                               755F902A389BE04970AF515D5718C891
+                               A77AA50A46D1DD737489E298182BA245
+
+Test vectors -- set 6
+=====================
+
+Set 6, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 0D74DB42A91077DE45AC137AE148AF16
+               stream[0..63] = 2E1ED12A8551C05AF41FF39D8F9DF933
+                               122B5235D48FC2A6F20037E69BDBBCE8
+                               05782EFC16C455A4B3FF06142317535E
+                               F876104C32445138CB26EBC2F88A684C
+        stream[65472..65535] = 1D92C4EBF6A256F0D0B0365160D72E90
+                               CA10D7086C58BE13E9325A5088F447D1
+                               572466248CD275A736B83674739899CA
+                               3146963E00E170C6B9DC8B2BE912A5C2
+        stream[65536..65599] = 878A21CA440BA0D659F24A5C986D6CF0
+                               3EA0DD962337935BA0932FAD9599EF61
+                               D805800038AFE4208394C73AA044262C
+                               18490F742A2B7424ED56EF3D1B0F53AF
+      stream[131008..131071] = 99387AFF42EE8C9D4D8400808322114C
+                               F4DF77CDAA363B0E4AFD0D8FF17D3D2C
+                               3303984867021922368A76F7CBD20266
+                               5A962140C8E6C1336CC4071B38ABB957
+                  xor-digest = 0FF8DA8AE74C2F194FE35FEA66F69380
+                               BF1D368CC0282F6E570477EB426F1858
+                               204DD9752E48E32C1F40A2ED3BE10FF6
+                               B5C80216884D0357AFA002E01B7B5FE8
+
+Set 6, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 167DE44BB21980E74EB51C83EA51B81F
+               stream[0..63] = 4F864BF3C96D0363B1903F0739189138
+                               F6ED2BC0AF583FEEA0CEA66BA7E06E63
+                               FB28BF8B3CA0031D24ABB511C57DD17B
+                               FC2861C32400072CB680DF2E58A5CECC
+        stream[65472..65535] = A27D9CFEEBB098C44E94F477A5AA9FB6
+                               286339533CF62E2781B574B9CCC53619
+                               CA27303E83FF9D986EFDB5D0AECC93C2
+                               F249325A37779D894549C0408B6A47E1
+        stream[65536..65599] = 36893EF2C9173CABEA2B5BB027938EA6
+                               0004121DDD27E79DB469B6402B4C23AB
+                               C08066B24EF0242234F9439019DADF4D
+                               000A8B68FD539F2B6C8087AAF89C76C6
+      stream[131008..131071] = 8FD0EB93722FCD5093AD826167F0F158
+                               E2A7B86751E85D796D5269866FD317B9
+                               523032CBB52F6978DC7E0933A2312E40
+                               57E0C9B1366C98941867D2EB0CD8CAF9
+                  xor-digest = 63DCDFC74EE1C446705C01CF185C7F23
+                               E083DDD7A70E2685DC1E051F2AAC63EC
+                               7E64399369B7D1CE49A732F594B6A587
+                               3B89E848F70A3AA9B04D219BAF14807F
+
+Set 6, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 1F86ED54BB2289F057BE258CF35AC128
+               stream[0..63] = 82168AB0023B79AAF1E6B4D823855E14
+                               A7084378036A951B1CFEF35173875ED8
+                               6CB66AB8410491A08582BE40080C3102
+                               193BA567F9E95D096C3CC60927DD7901
+        stream[65472..65535] = 2A30BFDE279B750D56B0B10A79BDA0DB
+                               21C246D133F4B91E4ECAF80DA7AAC425
+                               646523F6BB762D688BFE2DB1852B77E7
+                               733BC1005CF3D7CFAEC4BD966DCA6773
+        stream[65536..65599] = 991EC57DE1BDFFE2C70A0196A8902C91
+                               D3CE6C63E4B8D81C83AABE7BF370D1B5
+                               4D0B72B0C3C857621A7BBE2B72EBD81F
+                               50B25E08A9D492AFDDD37B983E9E2E4A
+      stream[131008..131071] = BC301B9FD7C554C592EFD092A435C2C6
+                               E74CBBF905CE424FE5872EEFE8DC62BF
+                               F93C3917BD37D142CFCA623B84C2652E
+                               0E61BB5C5D5387AD95EBA7A5ADF16F81
+                  xor-digest = F8F5AA473428C00F7F71E4D1BF1976DC
+                               2856619D2E1CD79BDE2FA1FCE880E816
+                               09B8D5AC28691FB90718E0981C3BB2BF
+                               A7E5888E44A0FEDAE7D481AA3AA684AA
+
+Set 6, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 288FF65DC42B92F960C72E95FC63CA31
+               stream[0..63] = 1CD8AEDDFE52E217E835D0B7E84E2922
+                               D04B1ADBCA53C4522B1AA604C42856A9
+                               0AF83E2614BCE65C0AECABDD8975B557
+                               00D6A26D52FFF0888DA38F1DE20B77B7
+        stream[65472..65535] = BB599F93F4F244D717CA9818212B06D5
+                               6D99AD4CA1F78725DBA89EA1D1F05B27
+                               093A17D745396D8CFD0256CD50674046
+                               13108E2200A8F1C49075B376A7460515
+        stream[65536..65599] = 996C074A7C7C524F539037A8A9F3D193
+                               3BC311B548BD567F8AE1B4325C51C5F3
+                               4B0DE1B4A4651829108CA92AE23D57C7
+                               0EAFA766097DB0539BE77E6500703746
+      stream[131008..131071] = 43EF1ADFE8265C46FF7FBA43B78F899F
+                               22C3B9F069B786982145D601627CDC49
+                               2D27BB8D70FF6DA908F2606A0C44690C
+                               8502F9CFB3BD6CBFC9205470E3ABA387
+                  xor-digest = B097BF56D79F1A343F61F7B66AC405AA
+                               6242493ECECBA06876276B36ABDDBFC3
+                               76D8C370503A8B8FF6D121D2FFC4959C
+                               6A96721616782688FFCBC748C9A168A1
+
+
+
+End of test vectors
diff --git a/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt
new file mode 100644
index 0000000..6460df6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_128IV.txt
@@ -0,0 +1,2337 @@
+********************************************************************************
+*                          ECRYPT Stream Cipher Project                        *
+********************************************************************************
+
+Primitive Name: HC-256
+======================
+Profile: S3___
+Key size: 128 bits
+IV size: 128 bits
+
+Test vectors -- set 1
+=====================
+
+(stream is generated by encrypting 512 zero bytes)
+
+Set 1, vector#  0:
+                         key = 80000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F1B055D7BF34DE7E524D23B5556B743A
+                               EAF06AE9076FD2F48389039C4B24C38D
+                               DFC3AC63A148755FB3CF0CB8FB1EDEEA
+                               63CD484036FFAC3F5F99FC7A10335060
+            stream[192..255] = 2541F0EDA5633B4F47C6B74CDCC612AE
+                               CD27E46B2C8FC9036A09C6FFB5891168
+                               7A8FAEDC225E34C45B6E081EF5279FE7
+                               3271CED417549740EAEC6616C2B6A57F
+            stream[256..319] = 0C8C0567803E2537804BFA15742D3E08
+                               A29985688DF3D6B4C3044464C1D1F2CD
+                               4CBBC470C9A0FB05665CDED63C58E466
+                               896F80ACC020F134CB622487D40E0AF8
+            stream[448..511] = 1FD448C788A21BD30D4B6BC5D8AEF296
+                               2772940557B9434E0FAF636D576B0737
+                               1FF3AC12884BB431F396CF7C189D9AAE
+                               D42797128CE645FE841A4CAABA429324
+                  xor-digest = A3F66A36C20A496A0D4D537B6106662A
+                               DEB5AE1E35FD1486EAB6039F443E5D8A
+                               C6A2D4A2C2E2A9F335E2E468AD8BA51E
+                               550E41533332E6929EC18CE35BBF741A
+
+Set 1, vector#  9:
+                         key = 00400000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9244D2B190FE8C4BD0E17247C4F1D282
+                               3FECA8DBE546637E34BCA99236D09F79
+                               5A8905A1E0FA94E6C51F7DC0C90FFAE1
+                               A8EBD4C99CC96FB3252DE0A0FB03F971
+            stream[192..255] = BC0ADD787A5EA52E28B45192399DDDE5
+                               CEC4E283181408E554FC714586FB641E
+                               B36F3727358BDD8223B5ADC9B9EF1044
+                               0F7CD97FCF2ABA75AA9972B277CD6656
+            stream[256..319] = C9F6315DA3CBAE23D32685C5549274E6
+                               9C17FB2E46746C5D3260FF2E00FB234A
+                               A460776CB0E7AC3AF0D297825C1796AC
+                               0B689DB219443BF4C0D4D19CD70A49E5
+            stream[448..511] = FBFDF6D40BF2DA0EBB04D52C117E9EBD
+                               6FEF88D39B8EF8B31082EE9B19D50219
+                               183DC962391FA4F602A2510BB476EF4A
+                               A44439F61D589933A1F3F633C96E56FA
+                  xor-digest = 49B435E6FA51A0AF8DC94CF1DE09F8D9
+                               AD76E08C061B54CCD62EF98ABE85969F
+                               3FC41DB934AF9DBC5F32748623639D3E
+                               B15124F13DA8B008CA5016ED61917563
+
+Set 1, vector# 18:
+                         key = 00002000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9D74BE686C2DE8B207E8D82E49236A3D
+                               E86F5A7EE231B4239080FC9A55FA44ED
+                               7737FA7472B318A4F36FB788E863247F
+                               7067C20DCA632FF051789E9EB99CF409
+            stream[192..255] = 4876774DBB886B72E54EE8160D8BA8DF
+                               6DB032B2A9BA0B79CF82426CEADE421F
+                               EF5ABE9976E909DBADA0442FFC7BBA2B
+                               009F7240941F0C209853A514B0BE9062
+            stream[256..319] = F2499CCE5D3268F4C5515C365D2F4411
+                               B0AA99ED01E7D5328BF0672584AC65CB
+                               E47BCA14C3EB1F838ABDB7C611677BC3
+                               7382E84D05848B9838A166A42E96B016
+            stream[448..511] = C855EF5D1CC991D2DDC892AD8319E39B
+                               734E43E443F5910D03BB79CCEBE70569
+                               F92BBC63363943BEF88BFA5809B3759E
+                               6BA4ECA1FAAC572228458A229DD5BA06
+                  xor-digest = F125B88E0B5F143B836AFD7AC822E027
+                               FF44B736E32627D90FA05F3DB98576E1
+                               9EC41AAF9D61ADE2BF00E38CA4EC2A54
+                               49EE0655FEAE777D67EE127E8A5F8CD8
+
+Set 1, vector# 27:
+                         key = 00000010000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CC447BF1B5D138025BEA2B269E625C4A
+                               D4451F3851F04F118499040C6E564E38
+                               5C5FE17FA7AFAE9FA559CA4835AC1F40
+                               1C045AD439B400BB41984DFE7E4D4CC4
+            stream[192..255] = EEC14B65E027BC2A96E566BB89218A89
+                               31C4AE0BA5C444929EF852EF7E400AC5
+                               D8B3CFC62DEBBC2B20A7B32E350E3839
+                               2953B7839AACC06B2018280770F84B65
+            stream[256..319] = 8870B4F9A62B37A1929973D3975D7ED0
+                               505AA43002B14B55A541EAE00148651A
+                               111D6E5A1581F85FFBC2304783EBF5AC
+                               E924CD8111056B1069F13100DE15EB13
+            stream[448..511] = 1513F3B7A2458674CBA2B566F3AD6169
+                               2BA4EE30687A07AF2FD0D340D92384F5
+                               F5BFD9B8DF2F7098A209C280F6D5AEFF
+                               BC07D167720DB47B4B649C8593E6F40C
+                  xor-digest = FB5EE30BAE44FDFDF105796FB8A66F69
+                               64D502230C191FF9AAF5A4447533D02F
+                               05A3772B99F9FA2A075DBB8BA59D8D5F
+                               F819784D487C305280DF2F19EEA8BD47
+
+Set 1, vector# 36:
+                         key = 00000000080000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 831F1DAB278C6226785209C0AD34759B
+                               9F205B7BC6B987DD145B949336A8FA0E
+                               4550BC1737DAE7DD7D12E2C062BF9693
+                               F08C2FB808A1F0A5887A06B93D132BBC
+            stream[192..255] = 76631E9D4A673D09B9769251433D5EFF
+                               3114AA59E1A9B7E21B4123DE3E34FBF8
+                               4ED6E80EC29B4F75B53A63902C373EB3
+                               D644B8823789743CA407FFEBA4A1AA75
+            stream[256..319] = ABD84B2A5479CDBC5587FB9EEC5DC661
+                               5A3CC6136314F67AD2C96803E8E4BE92
+                               E33DC35F0DBF3C401AA5D7A9F46E54CA
+                               A7ECD68E561BC08E6A5B847A82777E4B
+            stream[448..511] = 9ED1D44510201727B2E92B55DBE06BA1
+                               46762AB34937364B2157292CE68B9D78
+                               3D3C3FFD1FDCA836E4C4FEC750B10668
+                               600C26AC05B4DED64F8CC2EAA0D22052
+                  xor-digest = 843D7B97B3316595111DCBDE3DC13DA4
+                               C14402936D68035CDAF9A1C168120B34
+                               0EBA1FC47E957C5F69F369B4C2ADC4AE
+                               37E743226D72A9F122EC8E00BCAAA126
+
+Set 1, vector# 45:
+                         key = 00000000000400000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D2D629E84843638274ACB79FA257DD9C
+                               D48A08B823DC9F175CD92C5236B9D230
+                               5931FDEC5A8F531B1ADF30DE0527AD2D
+                               0D2B253D008913558E0FECCA7D7BEA4F
+            stream[192..255] = 6F9322E84D69CFD6A1E589283CD028D1
+                               E2A114B719FB2E18E732B97629313772
+                               CD2F2F8AF77EDB5B4360E4B679441346
+                               03C59E88C042713C3E403E5D93F9BBC2
+            stream[256..319] = EE7BED6C85B20E0A39C103D0B6949F4F
+                               5F6FE0DF2BCE315CCCEF6E537C488525
+                               BFC27FD249A6D36548C558153661861A
+                               78422A563166BBD0D72D6D7876FB4DB4
+            stream[448..511] = D2CFFCD4185EB1D8E15B629225B9C278
+                               6E7BFEACBFE29D7AF396B3D5917A8038
+                               7263018C7E98F49A1D5FA4B64B8E2AA0
+                               7192ADE0376388E8295AE5B54CC51389
+                  xor-digest = A26BEFF2FD72BE47175C1B6F3D749CEB
+                               0E3472FB0FD5E173DE66A5BB60357565
+                               505E3AA44A67651DCA75DFB6F0AFCFE3
+                               F4C89F064FC42D7C2953694B0CD47832
+
+Set 1, vector# 54:
+                         key = 00000000000002000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DD1649517BE76EFF747658F0ACF5D354
+                               2C7FFD52F09FF7DDDFBC48487450607B
+                               CB90ACC3406D0302E84450FC0BFEC660
+                               9BD44C7FFF670D69C9B19FA50C62EBE3
+            stream[192..255] = EEACF8ABD7D48E285A6658C255A6196B
+                               66B091773A9F81807A119DC24023D5C9
+                               041AF75F2C078C5246BC5F50B622A678
+                               64EB7A07DA6A8764437E20C7E1E0E579
+            stream[256..319] = BF55E777AC644A0938D438FA374360ED
+                               F842BECB027FA3A0F364B9150FFBEB47
+                               09FE2D2056A6CD5A7076172152484BEF
+                               A86EC7DDE657307580BC6F9ACEDA4C73
+            stream[448..511] = AB4CF968EC00E7F08553A10270A7D439
+                               68B0BC79C2DAE278AF1CB81FD516CCA6
+                               F5B8A47271FAAC3223F02DB4D0D5945F
+                               9C13A47906B03B80878CB0596D37CC47
+                  xor-digest = 76ADECA36B9401DDD5CBDEE821B70FD6
+                               65EB9CDB1E3F25C0BE90DEC49C03A9CF
+                               4049CD34F9550B28E0187B0AD47D86D4
+                               88DE4617EDB5F03C67FA2E7B9D20AA25
+
+Set 1, vector# 63:
+                         key = 00000000000000010000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C0CEF6E3CA9F0D523587FF47973FE896
+                               9FEB08773E3C694FBAC4804B37121B31
+                               06B99ECC2A08603EBA72EB3DC650E8F3
+                               462119F4685EF4CEA18D5765A6F22765
+            stream[192..255] = 79E92E248BA61D72C610876D3078F1CC
+                               CAD662F2423E7EECA813133136A64E54
+                               A1B6A151BECD2B815EAD959DE8E8DC62
+                               8F388D366103296A058CF60F525D6467
+            stream[256..319] = 03BD62A0892D939C1C28C4EB490F87B2
+                               527536AD6790AAA6C3CC50013E2BB883
+                               5710EAB7916FD89896B7983B326AE271
+                               AF9ECF975CDBBB968D076685BAA3343D
+            stream[448..511] = 98762E306A2B9D488FFB671D3975551E
+                               A06A6CFC5DB719B888E3164387EC922F
+                               12BC31A8DCAB8AC0CD6E12212CDA3B13
+                               4CF7F870221D6CDAC2B222AF4FD93DEE
+                  xor-digest = 606FA49585621E34BCC3748C06B51FE5
+                               A8AF320BFB83A4D1D3AEC6373519B28F
+                               2048A975732BA8DEBDFC5F85B84E7C3A
+                               EC0FCC9B1FA9EBB9D79D6B18BA2D70B7
+
+Set 1, vector# 72:
+                         key = 00000000000000000080000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 33A81D48866B04388451BC2730A2980B
+                               5F5BE248369911340E6C024A1F94D4FE
+                               ACFB246F7C0B9E27A40772D68DB36DE1
+                               7E87AEF19C8A68854A46B3F654E0AEC8
+            stream[192..255] = F67C60413B25FF7CB8647D1E9C361696
+                               3B23ECE23A9DBFEC644E855AEC5212F2
+                               D336E6F074EEC8FF5F8D4FC6398AEB9D
+                               BCAF6C29FDFE6E69A03D906C527FB0B5
+            stream[256..319] = 263D512137BAB758F646C71058D02B20
+                               3920965D84E52A99B50FFE79305E491C
+                               E0D61EF71F7A07937CEC8590B758F63E
+                               B3EB5890E8678F170C2E95B827FD8DDE
+            stream[448..511] = 023AD00A87D3D9441D4E8CB603F5CDDD
+                               AE8F3EBFEFB9C5435B72B9B8D03ACDF1
+                               E4A0FB796FF8401854998015905B878C
+                               99B3EDC7DD33A86AD4EA6AD208440C5D
+                  xor-digest = 5DAC8E3446BB3B0DCFB3F0A3A3E788C6
+                               07FA7436C63BF7AC9FAFCF4A231AFAC7
+                               75A3A810EA0FD4E5E6A5B8FE5D165A80
+                               798A9F58EE1AD27016E867D2E774507A
+
+Set 1, vector# 81:
+                         key = 00000000000000000000400000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B33EA681CA88C80EAD8F2D57C87EA42B
+                               742550FF8AD2B01BDF945BF160AF763B
+                               15D6B3BD92E6CF3E6A2B61A7D4BB94AC
+                               E3DAB365E4EA50EBFD2654E60CE849BE
+            stream[192..255] = E97318BDF61934188A94BCFB4441809D
+                               36C37D1A43BDBB3EB06FFE143B6153FE
+                               C8453A13387923F434CFC7AAF8CBA097
+                               7D796DE95EEFED3B2126B611F477619F
+            stream[256..319] = 4183971367E71731111D2212520306E1
+                               1CBEB05BE6FDB338414C826A8E359C7E
+                               CC680F317C12C6EDE6B443E68B4767AB
+                               4190E95E1AE4E4FFE61707BE742775C1
+            stream[448..511] = 56841724B7D7F95809456EDC1D3A532F
+                               E1C6BA252017DA90EEC71FEE9A639A89
+                               4CB7E1575494BC8B44FE4C5DAF90FF4C
+                               A32E03D6399BCB3D9D25B62764A4977D
+                  xor-digest = 3E80587D70A53AFFB96A62F6493B9BE0
+                               1C25339CBFF7784F5100A7922EE3E6B9
+                               9D17B026C0EE69C5383F63E0E5AEE9DB
+                               5814E2C526192AEFE17004AAA1996280
+
+Set 1, vector# 90:
+                         key = 00000000000000000000002000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 51A7510726D12FE9574095633A3710E6
+                               3EB8196622BC808B8A18800E208648C9
+                               F7031F8171B71F37613753A5E49B37C1
+                               CBC7933A52CAD48601E91CA198EC19EB
+            stream[192..255] = 286EF1C4F74C993A7D783E86527CDFE5
+                               213CE4DF7EC72544685291D8108C7621
+                               50D488AEF761D819781814F4501553CC
+                               B45EDDA85828C33C4D0608169AD20B2A
+            stream[256..319] = 89DF5C916612EF0ACC1035EB75752239
+                               ADE08E0D63B622EA52CC997DC8178C4C
+                               4E57951FC8C6659A225E88502742B888
+                               1F300FC9F278AA3D9C1063A83CF33C44
+            stream[448..511] = B2DE3AE2941AFBDB21D80ABB0EB852D3
+                               A076D98C696F886C302D96D6AD226CA3
+                               7B3213B3E641632B728A0AC7131B74FE
+                               F733D1B18666D36A02C148FC98AD2E89
+                  xor-digest = 01090125BA6C43AAA3910B650D046F37
+                               E04896E9D2BC276D969A10C1B26FAD48
+                               8A2CA5E59044ADDF698588A561557669
+                               A4EF25E1BB85C0A9D63F69FBB2924F83
+
+Set 1, vector# 99:
+                         key = 00000000000000000000000010000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 545E2C75365948B40FFF042EB6919907
+                               6E63EE636CB343C51AF6C17BA24E1BF5
+                               C045B0893B8CBDF6A4068F8574513676
+                               80000B10BA11666A546D8DC75374F5BB
+            stream[192..255] = 9805DCB5596FADF01224553F3A8DCC5C
+                               909D1A5EC2C29BA0DB86A46ABF70BAF4
+                               4A171739309A923428EA7BA8EFCA5CB0
+                               B0B8A5EFE9A4A39BE0EA6CEA782DD862
+            stream[256..319] = 531EE320A584EE1E4E0701400F86DC29
+                               69531C2BB1BC922CFA9E0919A05B84C2
+                               46495A7C358015724B62A986220DFA17
+                               6BF39FE4263A9D27D93F3737CC1D5C59
+            stream[448..511] = 92CC0D63772783AF62E642A5849CE7AF
+                               4D21EC815D644F88887242F4F5F7E1DC
+                               55E241D72691ED50D59CB3E2FE68A856
+                               7696F8B8E3099642D70EC3945B8BA656
+                  xor-digest = 855CFA62E449250845472BCE9453BA45
+                               F91601ABA6BB715B079D407E05D94CF5
+                               93B5A1E2C12C04C78AB719339AFC11C5
+                               213E17ED9DC2B0B9CCF751E0613D4F2C
+
+Set 1, vector#108:
+                         key = 00000000000000000000000000080000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F9748DADA2741A7CA30EFA167ED09978
+                               71619682AB68CB400A74BFD642180CC7
+                               F3499CE2CC86AB7727786DD01AB8D08E
+                               8774C5A3CFB4738FF1E3243DECF720FD
+            stream[192..255] = 5AA20B305F5D6363180CDCD4E16427E7
+                               2E3DFD73D2C4E2498008F6E0FA9CE3BB
+                               D751F6EB8DD5F48EB42B994688601E3D
+                               2CEB3DE19BF16C4BD7FD4B331FC93473
+            stream[256..319] = 81E3D9BB421CB09A9139534C6E430668
+                               FCFCB87E48CFA085D4FA1AB316CD5AB6
+                               35294E434852C1509C1023A85B26622C
+                               68BE19944CA3233A4D3272710A791E3D
+            stream[448..511] = A499D228204BC22C32047DF550E2CCC0
+                               260ECB7BA32E8F5CBA2C1D9A09D1F38D
+                               FB30815BA3C9A8D3243CFE7AC4A14B1A
+                               D6AA67D3EC0A5CB617FAD57E41A2A0DF
+                  xor-digest = 0324B7F1BD990F8DBF19C021CCDF741A
+                               1B4A9C3C3940CC59CD715F0B2CC31C08
+                               82E5B93721AC98B00F7B45FCCF19FFA9
+                               782B7D7FC048F0756A29B066B472B394
+
+Set 1, vector#117:
+                         key = 00000000000000000000000000000400
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7EA95775329E2D1163E30F429FECAEF4
+                               CA177BB4D3C4D1AEFA6B5A01904266F7
+                               7D7B7243B9DB1490245EC05129CA2DBE
+                               E3A98885DAD0B43B0E725DDA39B444EB
+            stream[192..255] = 78ED15A7B4A8151F384C740B844115CF
+                               D4FA31F9BC16E22158B0F896E70C0F73
+                               F74AA5EF024F6B386ED71239CBD57996
+                               4583C37104AD8C7E5C812C378AF00F98
+            stream[256..319] = 292FF21E49659AF99AB21753BA2A2B28
+                               25DDB156D4F7AFC1888FBE8376AE4C6B
+                               905D5916121E9F9D76C83FB146ADA735
+                               2AAAB6E89CE9398C484D69D1A33F0C97
+            stream[448..511] = A50FF5FC20C57F8297C9CE2599A3E6CE
+                               3193746E8C45FD9AECA0C5A0FB3BF70F
+                               5981B5BA8D2FA57677EF65B535FC3E65
+                               405BECF0A508445E36A7B6DE2BB56106
+                  xor-digest = D9650FA5D128620134828E1C99D9678C
+                               CFD5BDFADC46A5E79D47AC5967B8A1CF
+                               32F7DB65B949C88CCEE0D96D960A110E
+                               FF1D09EF5549B88D5B53ED46D4C2F296
+
+Set 1, vector#126:
+                         key = 00000000000000000000000000000002
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 25874CF64ABA4536844F815F486F9DEF
+                               927E325CFF2FAC48134A4D30824C5BF1
+                               EC75F8FEFC624AFCC717BF2C8EAAE374
+                               0AF399C2653389DBE31F9FF5D451D362
+            stream[192..255] = B151A1EDCCB8B4A3CA9BC98F19EFE637
+                               BE2D6A97A8F794091E7FFF06E7B4E574
+                               46B81E8C787BB77E461592160C44B5AB
+                               49329142D01A1CD5CFC6681F93DF1E33
+            stream[256..319] = 29B2B0C04E07D33EC3146E60AA305F0C
+                               2288913B55DDC18FC17EE836B39193DB
+                               87089DF2BAC4185A57E910331864E25B
+                               540BBC968099900F7BF18645A28A419B
+            stream[448..511] = 286FCC98B40EA26BFCBE5CDEE52B30F5
+                               810CFB26E756C628B56B3B5ACDA49E07
+                               192592CA2241C6C5193221EDA36CB0E7
+                               B5C3132F08087DF0673D3101FC559962
+                  xor-digest = DBF1D7E0AC062FE6BA9834F0AE41ABA2
+                               B28B41FDFEF914F070007B0A48EE9D9F
+                               E69DB8395BECDBA7B545201318177A49
+                               7D343A317B5A37A9DF98DD25C84DF948
+
+Test vectors -- set 2
+=====================
+
+Set 2, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951
+                               53F06534801F89F24E74248B720B4818
+                               CD9227ECEBCF4DBF8DBF6977E4AE14FA
+                               E8504C7BC8A9F3EA6C0106F5327E6981
+            stream[192..255] = 30DA9453A90909A5675D6B691CB0990F
+                               C423CDD8222EB47245BBB67BCA2B9C10
+                               8D1F016DF0CF8CEAF6829910916DBC1E
+                               113D11E91BEC3D85C47E3042EC865658
+            stream[256..319] = CAFED71B892EDBE13388CEF6A3365797
+                               E0D88C0D3A5B91BE4CBAF5162F69558F
+                               DBB45CA6F8C8D4C371D62736EC244584
+                               60131F54854F3EC804AA9A38E6ADE281
+            stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F
+                               2C3EA0F56AF46ED93DFAA4E16F5F0831
+                               2D77BD0E9122043CD6A202CBA9351F6A
+                               0E8E6263F4017355136A0C551E6FD0F8
+                  xor-digest = 023D719F61C193E4CCD87755C87F9604
+                               C5A29DD7E31637B3DD70D43441D48CC7
+                               D474013C85EEAB1897C80ED0A0272543
+                               F951C72E3954616CB5D6B51FC24F4B0F
+
+Set 2, vector#  9:
+                         key = 09090909090909090909090909090909
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081
+                               2145B56AEA46EB283A25A4C9E3D8BEB4
+                               821B418F06F2B9DCDF1A85AB8C02CD14
+                               62E1BBCAEC9AB0E99AA6AFF918BA627C
+            stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58
+                               11FA9BB02CECF7440239FBB0497347EF
+                               D8F1A8AA71AFC70ECCD64E81388E6E87
+                               9521C2B47AD84F9CFD9E240D8D2F3001
+            stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD
+                               3C8D6A2EFDAA9CC11BFCC61D94F6104A
+                               4091B3634FA57AB0AB9B209F22DA5529
+                               75C3C322DEBE4AE68623BFE1B2BB7F0A
+            stream[448..511] = 35B290F85EBA78A978750690C4747E8F
+                               72621951483772E8B89876CC5D55F3AB
+                               02D9B8FB35C741279FF9B5B571B26329
+                               4D011F813CB5B209CA1A22D532BF09B7
+                  xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34
+                               F6CD0A795B8347E1441CEBEE35540D41
+                               64FC2B95D71FD47A2C4ADF732261EE52
+                               8125BE374FA4A90132CC1063971A2862
+
+Set 2, vector# 18:
+                         key = 12121212121212121212121212121212
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD
+                               BD8853C329B3A881B489090853FE0F43
+                               89DA105F0ADFA9CF51DA2521C40FD2B8
+                               FB0BF80B93E3F2B3D8A8EB1C615E0FA6
+            stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D
+                               43A82A80DAEDBF29C048639BA38B690B
+                               7ED11323E3C0A8E77A16356705431EC9
+                               9F2CB7F7E1ED3B83EAF2CAEC00B00755
+            stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417
+                               376F334E6AEF9C187012C8AD2B94BE7C
+                               00A876756EB232510FD0798E72EEC87F
+                               75EC1467C07B3A1EFB0D51A5FA65E382
+            stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B
+                               AAFD131432CFD7D2F675E03320395313
+                               AD4ED96E9052FE6B2D2A17428660A25E
+                               EE642B712800BE3F7E44F21A1E6A03AC
+                  xor-digest = EF4E84DBD66497B142EEAC56B830FF78
+                               0465CEE20B9CFAF5727D4B3A588F4D00
+                               AAF718330CFF35508C44C1ADB8476625
+                               2CC3AA6AAAE74F8BF1DDB6D4AADA425E
+
+Set 2, vector# 27:
+                         key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676
+                               263C1CB9AB941119B19D15EBA3462F56
+                               2F69220595DE5E0E7C595FA40F1F06B2
+                               6EC32252AF05310809DDDFAE2E24B170
+            stream[192..255] = B29A740B51B4EA1080666337D5551484
+                               FFED6860A5125DC0573C8F90F23A98E0
+                               BA7B3E4C28C2CEFB1C33D2C36D1B7625
+                               64B9A67240CF174347A4C8D868F00F6F
+            stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6
+                               537C06AFB23354F054E25457B729B534
+                               CD10B2ABD45BE3E38DAF1B7A9103268F
+                               4FDB4C0FC9A80A003FCB907E8F249AE0
+            stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39
+                               F62D54311207B617B727FCCE1B2E762A
+                               060810C4DEF672E7D76083E3E4BED0D1
+                               0BAFD27CDFD2C937E660190D36B3FD7B
+                  xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C
+                               18CC5E1E3F6A317ED7257887446EF734
+                               65CA15F51AF5E077B7915062391D8497
+                               8F437985DD08F5FA3A8D74B3227A6EEF
+
+Set 2, vector# 36:
+                         key = 24242424242424242424242424242424
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C845BA29D542FBED2D021C85188E119F
+                               D34967B79D9F44635DD45D2E41DC5AFB
+                               B237AD2FA0E4CF4202D83DF3073C578D
+                               2AA8A32D30FB45DE28F23CEB85E50FBF
+            stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297
+                               FD12081B4B23F0A32CE5B3196173C7CA
+                               7EDD03F9637E08CA501C4850C15B207D
+                               7AA724377396CED2357B572BBF9E69AA
+            stream[256..319] = E484AF567EF80BAE77461855294E9280
+                               EF57E7366605785034D639D6DE3EBB0D
+                               E21886D0E1E0679BC2E2C9C2D9201484
+                               4A452B6AD3F1AC8B7762FF3C0E405B3B
+            stream[448..511] = 595D9855200786BB575FF7977509F395
+                               7879CA1F19619A99174BF013CB62F85B
+                               FF2C3C4FE724E26DD0C10D7635A2491A
+                               9E7E868D9DAD9201465AA178184D06AC
+                  xor-digest = 08737B82505F46F4FF282EF42F387AA8
+                               0450058F5314389BB73733BC163D75D5
+                               D32FC6408F8DE5F6ED2050027D605FAC
+                               A7119FC2DC1B6D3E84E8048DCC42FBD2
+
+Set 2, vector# 45:
+                         key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E
+                               6E6320101999BCE5550C2BBC9BC65D91
+                               FAA2D72FA4BF46B6EE916244048B1D09
+                               A115E3AB6C00BAC8EE382B58859E8157
+            stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82
+                               0C18B867C561E96DF4ADADC5A4375E44
+                               5A34F9457E5F8C9A337A0C88DF0F723A
+                               D4509F1449DF2C6AEC0EADF4C7A8139A
+            stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8
+                               452A1A893EF034C51750388D294947EE
+                               3F505839C69C1708E8323C449C39A96B
+                               FC9EC91B0E1CAA8112057EB0389FDFD2
+            stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC
+                               EDD92C4461EFBA5CF1664B9AF54857BE
+                               C3D00319E5E8A89A8322831151EE1D52
+                               D8585AC79CB60B61ED2C852D04BB0FB1
+                  xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D
+                               2363BC12259B0FDB2BD8F052A572ECA8
+                               D1EF62AA9A48497805A413742B5AF5A2
+                               6DC9FF624B49E5D6FE58BBE5251B4983
+
+Set 2, vector# 54:
+                         key = 36363636363636363636363636363636
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340
+                               42D4F07DA4D5EB05554CB7426D65C5EC
+                               A93C2D321175B6F72FCBEBA6E38CB098
+                               B72534F7D534B1AADD97B77E8513B482
+            stream[192..255] = B2466A173F436C8433F264CBF125B8E4
+                               C10BC81BD46B5C21FA161CB2AE07D27B
+                               F66812A2C2FCB2B14C23E413CEF4E591
+                               AD52EF810A000B42E5C1B76EEBB17739
+            stream[256..319] = ECBED2058DC50223614EB8635B834C3B
+                               B176719C18CA5E3D087A93E5CDF81123
+                               C6FB819CCAFB5042AADFED5E3C33116A
+                               FD92AA21031165A22F4751C423B8B945
+            stream[448..511] = 758BD9435DE607867DA256064C304C8E
+                               DDDF5B64173CF2C98B2842992F8C5FE1
+                               A37C3227B7F37D49A39F9FF929A883FD
+                               56DB8B1A174E1E55FCB21C9E1164C20B
+                  xor-digest = 31761A49503946701D35306FBCBE10E2
+                               02967E7EC14A328B4DB19FE79F03553F
+                               13A012B7297B2D02F18A216AD24A682B
+                               299518C3769123EE86A4937DAA9FC39B
+
+Set 2, vector# 63:
+                         key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B
+                               26A4E7E34C0CA9CB9399F655E566383E
+                               246143F57776C8E08951E87F76091FE7
+                               2356CC901F09A07895A890AECF047B3F
+            stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF
+                               C862100A07E55FB449BCFA2D9BD48658
+                               958B37B3EA3565FA66824102A14B5770
+                               5E3914E0680E116ED58212CBF61028E3
+            stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701
+                               057710F24C01E680F58090B8E949AF01
+                               8970A43A698A04C0C8639FAA665DA3AA
+                               562B2C5C3A03BCC38FE75DC1821ED718
+            stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948
+                               821FBB049DAD15B988A77C0247868A38
+                               2056B66F47B0195FA30C9DB5A2334A9D
+                               CD7C0D22E479FAE1BBCDFFE60F261C7F
+                  xor-digest = 94D41CCAD940CED3C854DA0796DC62E5
+                               6B566A980E34F353CFFD0F53AE9E34FF
+                               A6A057645FE66D86BE30F93805D9E2B5
+                               D78C68EEBF61CE387277A51EB2EF835B
+
+Set 2, vector# 72:
+                         key = 48484848484848484848484848484848
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E45194379659D1D8904DB3698AF8B245
+                               762910B7FBD019AD1AA20A6C433B4C80
+                               308A9EA68697631646BF3A2107C4E7FE
+                               2235E8F3262A9DFD3F5CC23FEB0B2DAB
+            stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA
+                               4E947598C4757976F6F61DA5F0DAC8BC
+                               DDF72F08BA2F446FA37F9A490F6A2B6D
+                               79227C93271D6B763DA7B2A907220A42
+            stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74
+                               A43D83AB8ECBAC5206D108F869561D70
+                               F151A0037F8E28951B5026643F8B2D6D
+                               56A62E259F04A5EA304791A9468E66AF
+            stream[448..511] = F70794C084E6EDC07BA0347413B05FC9
+                               FC46994CA820CE4FC037ADBA50EAA9AD
+                               55064ACB7308CFCE3F35AD5C7C628362
+                               F4210FBC2D3264F734728626BABF5356
+                  xor-digest = 31815B36BA034BB1941DB1E45A941A59
+                               7C3882F34BD3BF441CAE8A9790B05BCA
+                               72049FD10C09A14AC9DB867A82C38A5F
+                               524C72F783DFD16980DBCDEB486FAE96
+
+Set 2, vector# 81:
+                         key = 51515151515151515151515151515151
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6
+                               FF53889A9979ABA8F23AA51DB1EDB8E9
+                               D08F696C1100799A7D004DEF1CA94110
+                               FCF0C054B0C131E6FAE0FE2F2DBF22B3
+            stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC
+                               55A5F3F19C5A10E12EBE46DD84F10385
+                               33837693588D584FDAF86E3A217C3CFF
+                               020278736F1A90CE07F0DCE4329005B9
+            stream[256..319] = 135FAD68B5282FE59B28D2DF66463632
+                               06CA92E84A73FA131EDDCE89A5C23B4D
+                               08FA57D455BDB32F8ED58DAF3EF288A2
+                               7C72020E35DAE19B446E4C52DCDAC5B1
+            stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D
+                               18F2111002891D3229102D72605B9BEE
+                               F5DA36059B0DBBA7646927650305431B
+                               FDA4A97570CD0C484BF1E974B157ED7F
+                  xor-digest = 5125E77698C0DAA89A7E47DC5D038D40
+                               7B732CE56CEB674CE653A1B6661B2740
+                               0C092AFF83BEEE4FC4543B9D725C9387
+                               2F89AA338222ED677BF59397200AB304
+
+Set 2, vector# 90:
+                         key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21
+                               75E9AD91482965B651B495AEE819CC6E
+                               C42AFE2C20EEACCEC4E90710D17210E0
+                               4CC6832905985322C8007F872D3E58E1
+            stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560
+                               D692A020F0A66F609374ABDCD1343722
+                               05F19CA04EBDD3009844BC540C1B2B41
+                               66D45E8A2E822B906DA34649E7FEEBB3
+            stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF
+                               CE2CFE99506677A956AEC86BD290B6AF
+                               C5298A448D0DEFA99AA5CD26D318982F
+                               E786D809C713D5A55B42CA6650191DDC
+            stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225
+                               EF6E3C21705EC9FB24873916A2C24668
+                               963C03FE097DA8224A42A99E5DFFDC17
+                               68CF518DE49CCAC8A70216C62C9CBA6D
+                  xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5
+                               5FF58B296071D5D39349A531E41F0BA9
+                               893A1722B6102740BC5FE394A49363B9
+                               6A626AB43FD6A288CD9B23F7255279F8
+
+Set 2, vector# 99:
+                         key = 63636363636363636363636363636363
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333
+                               BCB02E3AD8797377AE1F1B4D6DDB86E6
+                               2A59791CB553550E0492FAB42C7A2C42
+                               3157C5092D2DD37D46589F17FBD86584
+            stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91
+                               4122EEE5736BCD12061C77DF5B0122B5
+                               1784E946B4E93470170ACDD7E2779591
+                               57BCC9B9F3E11E88BC2F740AA0C10C97
+            stream[256..319] = FF22D8196AB3DF662210D12D0FE79255
+                               6DCD39611C07F089979CF7D693A30CA3
+                               5B795B7F6D64931916E717C8BFB92114
+                               DB75118BDB51D142CE8133415C6B3456
+            stream[448..511] = 971F007EFE17662D95F47F4F28266516
+                               B22A1E50755EEF19149DE3A3121F5FEC
+                               E0D9DFE7A055026CA44193542D7687EC
+                               695B97769BF02F92C1EF3D904A8010C6
+                  xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163
+                               C8D54A4CA36748C74721C7B6E1649A31
+                               4B5B7A4BD43E7C3D2A22F0C8446C7892
+                               90D54D421D37CB16400E59CC86215CC8
+
+Set 2, vector#108:
+                         key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6
+                               54BC11ECF0010D2AEB9F899130F4AC2A
+                               38EBC15C8831D591E6675DC1CE7A471C
+                               4B869FE83CBF37AC70BAAE5D4AC607F9
+            stream[192..255] = 518F298A6008532EEFECB3DCF72103BD
+                               5E3F84FEB6EA2311E8C19A2E93A9C3C3
+                               BB1DA7DBA78D5618D1C4FA5B0B202728
+                               62645A361E55494D66C9359E41E5809B
+            stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A
+                               89BB20CCD92E7F13FDD816DD4E4963C2
+                               C5FC2570CBB8BB5C70848B73001F508F
+                               47AF179528200F51CDC6E4854EAA63C3
+            stream[448..511] = 844B1D15FBFD1264169279ACD525611F
+                               A39C7BB41F1E7A1C09090625F7926E51
+                               23A4CD7FE1A3F37ADC67AC437BF0A5AE
+                               FFFC6FB0ABF39D9908145004AA5B958D
+                  xor-digest = EC67596C9DEF4012A2D543842829306A
+                               4285A3B8038818F265065DC848BD80FE
+                               C27C2F66A57B27F7FA8AC912001EC954
+                               05BC6E93D7E555C59060F5D2E294D103
+
+Set 2, vector#117:
+                         key = 75757575757575757575757575757575
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 91D2772A18995DB3C0801DD3740F4466
+                               F9535E5BECB93DDCA0E94D19C0B57BDD
+                               0FFBA9DAF0B11D55C852927F8BA560EC
+                               4999E25848D08FCA7275E7E8571A5F1C
+            stream[192..255] = 72E64FF10CA9F07CC493715724DA7610
+                               9E4358E8B0CAE451348B784A162DF036
+                               AB9796724D17FDBF356031D080A6631C
+                               D1E8D217B041AD2EDF427972653206B2
+            stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3
+                               344956C29D10374E502C2EDD177ECE5E
+                               6625BAD9630DAD57976216CD69865058
+                               130B132FEC1AB0C350DF4DACE4C7724A
+            stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90
+                               E402466550B518A177CD05985D238827
+                               BD92EE7EC22C274F19E682F85ABDAD95
+                               D0EBB3DB6C6134408353C8B0472C9A1D
+                  xor-digest = 9A6C893F2108D13A29373DEDA65386C4
+                               AC356BDDD4A3178952F9126E322B7AE6
+                               83C94F1A131CBEAFF26549D9F84CF04A
+                               1241FA374B055B0ADE7E49E8EC669E65
+
+Set 2, vector#126:
+                         key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3
+                               059C5CC575D806B9029CCE3FA45A246E
+                               0EBD3AB2F2E324FE36ADC3B56AE2F7EF
+                               C710AA964CB87381386C2A88B1308035
+            stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E
+                               20BEB18D9C84187C347F43B17E0924F1
+                               2348F825E106E57A00258CE4415294D9
+                               4323A9812D8A71359CEC1001BAA0D567
+            stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5
+                               32D62E779FA0D2D08F8ABB6B0183A4DA
+                               4EE0329215F261D953150B9AB9FCBE2F
+                               568AAE361EAA8636ECC01A63F007977F
+            stream[448..511] = E7C44F44E06321A20E25F73E2069757C
+                               90499DB7E60025CF6D2D445E53A665F3
+                               08EC96F6FE73C0AC90D7E4A712E18C2D
+                               3DED46DFBAFA24C4B0B329E52C525976
+                  xor-digest = 22035341489FA6EEB2A6488CA42F4043
+                               57477C3F55569A1224EC39B1019E90C8
+                               21D37D78ED4DCEAF6EA70724C3751760
+                               38CF25DE4F84BABD80424D83A310881B
+
+Set 2, vector#135:
+                         key = 87878787878787878787878787878787
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191
+                               3C69F2275EB97A1402EDF16C6FBE19BE
+                               79D65360445BCB63676E6553B609A065
+                               0155C3B22DD1975AC0F3F65063A2E16E
+            stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB
+                               3373B816DA256CAAC37914B0C161E4E4
+                               5F5ADBE444098A5B2A4CFD4251D79918
+                               987BB834BB50F0834EF4985F356B92A2
+            stream[256..319] = D89642D25DF97D149AE07EA18BA39497
+                               8935978AC34C1DF9F444986D7505DB4C
+                               7E08DB3616B84CD52E7DD7FB108C36B8
+                               B50C2573172F4D3500B6D62A9D20B82A
+            stream[448..511] = A2C17FE7371604556F796429C6BE0688
+                               8611638B310F3E9FAF484BA9EE29C16D
+                               2F842EAF33AFEC557B68D2F453569187
+                               A6F4CD204A0E7A733E81AB7CE9FCAE81
+                  xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B
+                               6E3A61977A7C6AC2F033B826AB9A9957
+                               66671D2A1025CDF8E2824B2F58CB221D
+                               2A68679239D90152FF7D0D39B33FAB93
+
+Set 2, vector#144:
+                         key = 90909090909090909090909090909090
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6
+                               71A6D390BC7099A708D370DCD0E3D143
+                               A0334619EBD5C7DA9EF6301F29273F85
+                               2DFA3C580ED65C6E952F88A0B7FE368E
+            stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B
+                               445792061AA0539DA69ED0B77B970C0B
+                               482156A5DEE4082A61364BF06E692399
+                               FB9F4411FEC515291F8949B20F57229E
+            stream[256..319] = 993E815F299D4841518119BFF88F6EFB
+                               F3DB9BAE60238BDE2845DE4DBA6D79DB
+                               C9E42BA5C3C004AE4546FD86C660FFC8
+                               FD6A8A349669FFE3D9E5BDF8E50A407D
+            stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2
+                               1274F4A6D814B5440C74D53A3FF0735D
+                               EF01B14AE4188E215CE7337C04871688
+                               7159695A241BFB9D6B489FE9E23B2AD8
+                  xor-digest = 0BD5739ED28778023E6303FD88DAABC4
+                               0FA0A211A1A5C5F230D9E67DDD9EA517
+                               FEBCDF0BDBC107291B6CF3ACD8B862B8
+                               4BF15400493A54036E97FDEBB9A1DB2C
+
+Set 2, vector#153:
+                         key = 99999999999999999999999999999999
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC
+                               BE99E7E515650511FF7016A0EF287ADE
+                               5A03839C4F83F05FAC3B0B24D4E3F602
+                               3251F8D9CC4530A805F8A6A912EFAB1C
+            stream[192..255] = 792823ACE2C0DDB266A118068AE295CD
+                               716E424D3B98A9DB2501A3F5DF7DC70A
+                               3BD2C6E664D5E13317D6F57B8774C903
+                               D407D2BB6014E0F971141E89569C5868
+            stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB
+                               304C81FA9DDE0C21592247C4098D9347
+                               1DA30294DE8C100E5B17A199F744CAC2
+                               4E33490FC7F223FD6B4923056117C6D9
+            stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59
+                               349AF2BB1DA2BA622B9824F729929098
+                               BD19DFC05D0D9454F604960C027752F9
+                               7812E53DE6AC6CD2751AB331703646AF
+                  xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2
+                               DC458E7E517637596FC8FB710E2E5636
+                               DB1F14848CB12793D54ABD0856B22F3A
+                               ADFA8C33AD08B8CC5292DD76913CB105
+
+Set 2, vector#162:
+                         key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229
+                               8A8806402755660C4A30CD216A500BB6
+                               AE975E08EC62D08425A8A62A71B00215
+                               DE35E5178902348698528CB82296F009
+            stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C
+                               E4F7E1B3E78C3A5DF07592F45B968BEF
+                               F95B8B257DAF2B468284627AF4481FD2
+                               67BE0B164DD86721DC8C1607A0607EF0
+            stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3
+                               9C056162B626F383F3E77B5C98C0FBE9
+                               119A7C335C333E6490126AC2510CDFAA
+                               86441C72D1DD9ACBCD3FEFC0D0C794C7
+            stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754
+                               246C065AD23A8D709161FC74B34E23DB
+                               B918EAFA4465125D3780BF0B5803AACA
+                               037AA0A14D977141B611A6CA2278B634
+                  xor-digest = FEFDA1A6E95920B93380CC24FAE214C5
+                               6B009ADCB176D519CA4B8538EDFC95D1
+                               6CA06B730B28A230F0085FE43CBEE2FA
+                               2EE5DCD74D66F5CBB59F256CC1ED885A
+
+Set 2, vector#171:
+                         key = ABABABABABABABABABABABABABABABAB
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 22E1A884ED2C67CCB2977105649B6544
+                               367858D1A730AA2FA96703FA406B337A
+                               B2159A389BEF48D8A215D870B2968E16
+                               B11571F12BEC0A07FA7D3B9790987EC7
+            stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74
+                               B27776E9250B8B063E52E169C7B76A15
+                               0D699278AA4124427B5EB6AFC4AD5DBF
+                               600FEAAA98A88DFF297DACA5ACB4878F
+            stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484
+                               976B640E60CCD6ABFB908583ABEC3E75
+                               2878371EBB5374C9B37A63E0768AE10B
+                               D857253D940AC408EF49EDD590E806AE
+            stream[448..511] = F012E429C44D5DC03B88123855B62C0E
+                               90E06759306017B5773752973850531B
+                               C480316CBBAEDE6353AD5FB298349AA9
+                               16AC0221A4CE1E4729BFB9C230AAF9FB
+                  xor-digest = D73B872315F9052C67C4CFC5CD912DBD
+                               60DA32FD06D9C8E804968E688898200C
+                               1D979DFFCE52E1C3B3309B58D12BDBB3
+                               D3EBA2954D1587D720E004E12EB4A13B
+
+Set 2, vector#180:
+                         key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88
+                               D2EF924014F7445ED922E9C021571909
+                               D7E6BFCAEE0724F2A9C522C4BDE4BBE9
+                               FE53FE592C0FEB80D2C7A51FB8BE9EF3
+            stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484
+                               0D22CDDFF39EB0E3D5FDF74C6E7B3394
+                               A0A4271D780DE6DEE9AC58B4903EEDD2
+                               6DD14E14A4DFE506748D5DCA6DDF4C5A
+            stream[256..319] = E79D99119996FBB5163335E2F79F0502
+                               7AEA5372136E7B3C5BE1F4A673A2DC74
+                               60834B81BE6C4976C4A727C8E6046A64
+                               4CAF42EEA6A068B7E532581E9037BE9F
+            stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614
+                               9F3EE55A136EFA3B417DB63D2487DF82
+                               794E161B3153DDB2E1E4F385E1A848C7
+                               729FF5CB1CB58D5E73FAB1F2DCEEE5AD
+                  xor-digest = 2F3C231B0228C274255F3BD314ECC7F3
+                               1B9C49177009AFF2CD88F807092D77E3
+                               C74C1B9B8650F581EC7603F4D6E70955
+                               1B00C3192414C04AB0AD8B0B9BCFE988
+
+Set 2, vector#189:
+                         key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410
+                               DED6D4E331633C5621B94E7EBD15E856
+                               04AB202A553EFED55A548C7AFFCD2550
+                               60315FD50A305D8BCAC9C077229D34AC
+            stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF
+                               3CFD130D5B6A9CE37BEBA429AD137A82
+                               44D0586FEB16D086F533D1885A82F73C
+                               F2AD2C645591F80ED09942F0A08D898C
+            stream[256..319] = C214B6AC700164FA66DE346A27A99463
+                               C5B6C0E43A9057384BE168E163058FCB
+                               6E7DEC871C6531EFC8B8D581EF92757E
+                               219294D39E0C9C8276440BE56C3D9941
+            stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE
+                               4C8D2171695C9CF97E2936A8BB320670
+                               015825547A508EB43D96F2EE1EE2CB34
+                               4E120F001500F8ACC3E19E30455D09D0
+                  xor-digest = FE5928C74EA21F23E29171E5AAACA20C
+                               DD8571E907763C96B99A8C11F9A1D2F5
+                               78F68A6C440996995F7AB6E69B3CCE33
+                               CF8CE0C16F54355696D47DBF82EA8D56
+
+Set 2, vector#198:
+                         key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 75559677D7C762F6CFED942D800F2FAB
+                               AB5F3892DC2C79922E96FD34FE511C11
+                               251C8EB7C639E531CE08A8C99F62E7BC
+                               F68FBAFF99D62348FF91CCFEC2710055
+            stream[192..255] = 149806A4D862EEA81F0208D927339E5E
+                               C98E9C2A6E0DB85CC0380DED7EC5B8AC
+                               4ADAE76AEB9C7B7264C3834316209615
+                               25221D58C0174577110596FF89C8FC69
+            stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B
+                               3CDD19BF89B31FF75A814F470BF97E0E
+                               1293B750B769F5BDD750DE5025D7534C
+                               AD541A1F26C6AE9AC2FD3237C156AEBB
+            stream[448..511] = 0958243E88921B81F04AE63658E52D76
+                               CF2638495B3A6B970633A7C8F67B8CF9
+                               AC378082F72FC63BEA02881CC5B28D9D
+                               C8C261C78B2872B5EBFC82336D6E1A28
+                  xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7
+                               0028A08A00EF935C06A8B3632DAD5914
+                               84E44E372A753F8E630741266C0F4218
+                               4923608103042C70ED4ECC5112B9AF6B
+
+Set 2, vector#207:
+                         key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28
+                               98C701CBF5E88F1F3DCB6B873E5CAEEF
+                               23024ADA678E1A2CA9E25AA8B476CF4F
+                               9FCBC297FF03A9B94A5A736274EA776C
+            stream[192..255] = 73B9891D1770289A67D6338909FB6282
+                               9A425B7947FC30DC52B11E398E85B1EB
+                               537E1C02898FEBFC15A9172C254CA55A
+                               AA1B56EA856F47E37E2F252D92D94ED8
+            stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4
+                               38B63B9F436FE00CC075C585297B8F90
+                               E6062358D29641FF9C28EED4A23FC53A
+                               6B5C60C2AF1E8146DB27CCF5F43BA838
+            stream[448..511] = 642541A9733946827D79BBD815C03C17
+                               6357BD6E81E9A61FFFD4A0BF6863AC71
+                               72AEFB92C1F235641BBE1457B724A6AA
+                               AF9FAC687552A778B034C4A4F8E41ADE
+                  xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668
+                               BD0BC5A97655978E79056B3D25DF3E79
+                               5D5D8BE5D1AAE877F2E7D03225CB6609
+                               6EFE11CBCB728039A243E326437CE73B
+
+Set 2, vector#216:
+                         key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F
+                               1F7BDFBB81428FFEE9FBE14DF5F5F3D8
+                               A044EF53A868D989E16165A0F2B95E8D
+                               83439BB4805A125AD0CA7994AE11B852
+            stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184
+                               EE7A7F4B822A1C955A69E238022AA313
+                               276C2003E27AEF1B4F94B33A6428685B
+                               F048B357EAB297B7DD98E612F054A317
+            stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C
+                               978B976BE1B6CB0D15C0324D6B70D265
+                               385B615B3EA97A55D94C47F53FF40861
+                               4460857AC9568556AE54A52546B41B5A
+            stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6
+                               5BE2BF56D2B78A401D5761E2F3AF8B18
+                               A2B1089864999D9B99E5BF6959F8F802
+                               975FBF204D6159CF23F3706CAF0D9BA5
+                  xor-digest = 0957D6887501D4360C430614B67D99B5
+                               32849E2F5C69CE8A9F3F707A2B5438BD
+                               0C1237B5617FB525CC9C043A10DBB265
+                               3C3F0A353E89A19838B8F68542E09526
+
+Set 2, vector#225:
+                         key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A
+                               50CF101BF065F69F3E78BEF5D689B1D1
+                               D306FF41EB3E78BEB75C4200937CFE60
+                               E89E370680C519B2F64E23516ADF8062
+            stream[192..255] = AA30580A210B87727BE17EC52AAAD037
+                               3E0DD11FBFC89B37825CA4D6F9E8D433
+                               E3EA54C37D678B58CE834AFA310F6D4D
+                               06B4603F12DBF38595AC76511D0B13CF
+            stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC
+                               8FC9B09DAA6F418D3434BFBBFF6BFFFB
+                               F93F8A963F2F51CC487BE868F010EC0B
+                               EE17A480542A301E33B36F59BEE13D91
+            stream[448..511] = 672048756C221C12DA6178BE711B3371
+                               525A92BC9A219CABC5501B0DA4CC248B
+                               8742E8BCBD6F5A1CFE522F3DF3BED6B6
+                               5D60D1AC737ADC582C2CB9751521828B
+                  xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB
+                               3F418EBEB69509D69B2594E964759D15
+                               104F674CD44681AFECC3B4939CA0A0C9
+                               DD7AA5726653ED3FBFC833DDB0C87B42
+
+Set 2, vector#234:
+                         key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2479A8F2872A813D16D15F060D300237
+                               25297B812F6F3B97D74D9716E4403A5A
+                               684D2BFD1E15275470FEDADF1578277E
+                               44C6C06B8A5FCE3D0CCC5E13BF49947C
+            stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3
+                               132D4B0065A563288F848E05EB45E48B
+                               D15C069C02F90B4FC10AEBF1AF4BF90E
+                               2CF7F48C8CD7A8091014131EBC21FBE8
+            stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C
+                               EC170B064429EB832924CDA9C47B5174
+                               9BFEF80D96FAE36DDA65659FEA1CC06B
+                               4EA3A1601A3304AA4DDBEB62381FD4DB
+            stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145
+                               BFBCDBAE19F5281CD0E6AA37419778DA
+                               64DDF68726DD7F4D78BBBFF4576C2AAD
+                               93F477A2AB2C3CA8A381F30BB944C7B0
+                  xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070
+                               9EC7E9B89DB8EEA11045ACC5FF003DC9
+                               CD3318BB6F9675EEF20E15490F525066
+                               AF8380C663B60EDBAE30663C94C39892
+
+Set 2, vector#243:
+                         key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CC3701E703946194401D1BA23AD99B5D
+                               F3F856138E142D4B9C23DC9F252A277B
+                               D62DAA33A71A0C61079AD5A20562291A
+                               B6EC92C66D7BE6A17E27D4DDB48EFD31
+            stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903
+                               D565423614409AD11E821B83F5B35D83
+                               F26F3EF9EC1766FEA9C21C09E0AE248F
+                               4BA01E48BCE09D06471593B3466703DD
+            stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF
+                               96CDC215EF1A62FAA29A5608C852FFA1
+                               18B473C5A7319446F3ED2E8AB39A533D
+                               714325D1B14E838C9EC6E037DB0DD93C
+            stream[448..511] = 4FF3B43841B17A279002EFB07324625B
+                               7E937D480DC73F12836195110ECB4DB5
+                               CD31CA4F92F612A95E82815328DA7D5E
+                               4DCC5BB6791603EDA64C57B5A5AAA04C
+                  xor-digest = 9202B874C48D4B1A9E857E645EE8F884
+                               D971CE97923AC024ABEFB944E34550CE
+                               31712BB832F9174F86FCD369E75CA9AD
+                               85095F43A4B7F33AB641BD6912D2C59C
+
+Set 2, vector#252:
+                         key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F374DA745A5CF93A567027609E5D3B1D
+                               5C3C8A4D15203705D978AD42279F6548
+                               51FF713F5120CC93D044EF717F5A75E4
+                               98DBEF559E5F157A8C819E213E93B3F4
+            stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9
+                               175AEAA99D55485954B265B5CAB86509
+                               C810E664766A8E6C90D4BEE3A58B1815
+                               9076959FFFA2F30EEB12343E9E7778C5
+            stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC
+                               418DA96336991A27DADA74FDA987B867
+                               B125C53C0E4E2889FDFEFBFB48797A22
+                               2836B2EA42793CE2BFFD568F6234B368
+            stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36
+                               4CD2D730DC8D7E183EC55A777C2445EB
+                               BA7E9CD95C8F3A206B73C422AC2E2C08
+                               15A8C6FED156FFF93B63DE512EF69725
+                  xor-digest = 467EDA43B849054EE747A532ED0D9AA4
+                               6EA1BF2B6AF19F481D6E3D55EBAA96FC
+                               6629FE65B5EC4B5EB6A155A6D60FEA32
+                               F04F8230E26390F1C8FA53D47B68FEAE
+
+Test vectors -- set 3
+=====================
+
+Set 3, vector#  0:
+                         key = 000102030405060708090A0B0C0D0E0F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0315CE93BE05F88212B413335CA65F33
+                               6387BA612421C7BE8276299CC178EC31
+                               2143C503A9F2644685882201137BBBD7
+                               3A2385F0AD14B690281B54B8DC064150
+            stream[192..255] = 8B663563AE31DCE7AC61BF4943466774
+                               E9EE784644AA761B9D8AA9B8E04D4C91
+                               75650DDF130454DD60724864DF2FB6B4
+                               31F947F8FCA83F6D3B113BC413D3CC10
+            stream[256..319] = 35EE3D4294E5660A99A1A1C9254D27A4
+                               B42FEA8CBD5C5BD8B902E1B1BFEF17D6
+                               ADC9B6B924C7C53D44A5C58210989BE8
+                               72E532300EA9115CD2AAC8024779B3FC
+            stream[448..511] = 402F841F64827A197FC56EE9C180F5D1
+                               075107622178407B063F70C6C860C6EA
+                               E3016D56F7CDC13A109283F5F4FC9420
+                               6C62BC3D1012EA03EE08EBE8C2DC074A
+                  xor-digest = 6815E00D7D3414FCB103EA82B38FD4F4
+                               68A453E84A520B7119E9D3A4C938BF0B
+                               AC26F7F73EDA7F3E2F20FBA551C15205
+                               EBBF2F6BFE6DBAF95061F0AB3988DD57
+
+Set 3, vector#  9:
+                         key = 090A0B0C0D0E0F101112131415161718
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E695E5417AEC9FBFC0EB0909435E79C6
+                               76AB8E2F28C556CC2C81CFC5F7A2A6F1
+                               254EC0CD2CFAFC257907723557C1DF5A
+                               D81D1E3D201410A12A5FA3A6160F266F
+            stream[192..255] = E3D590D9AF3869FFCBE2A4B8C77A09F6
+                               211193F83B8A43714CCFC02D014376C5
+                               A44FF7C061471AE208F04DCAA89792FF
+                               AE7096EAC47898C1011095DE9B55682F
+            stream[256..319] = 0F31D78C0B86D246FE105AA6D9B93CE0
+                               257E75CC0D2A0BE96B9156555D8A407E
+                               01F47AFF719CC894EE111C32672B0404
+                               B5F26C1DB1D7D0F9E470900AE53B192E
+            stream[448..511] = 1A01733BB8EACDF2B2F4322FB54FB6CB
+                               C92989248FF31BBAAA8304ECC4AF9A39
+                               CAB21BB66E0A144D8B77C537BD52DDD8
+                               C5B0909CC6423D4F243E5AFE6E22D07D
+                  xor-digest = F8C3BF6905A19184D14039E4B7FCFACF
+                               2EFA004B35B55DD04F56199C6C9DE1B4
+                               458C5EFAC45C6062BA1EB726426987ED
+                               88FA899849CF5F6CEF60119F6A68AF9B
+
+Set 3, vector# 18:
+                         key = 12131415161718191A1B1C1D1E1F2021
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3C189DEDA71E56926CA2C3A2974C4FAA
+                               B7EA3C1250E768CEA797ABD6477B59F0
+                               E5494635CB4700A95BBD54B0E93D12A6
+                               423DF8F34BC6B3BE705ED6704BA33894
+            stream[192..255] = F21E411ACF063846BF68F61F7673710D
+                               CFBF8088E2A815F406E17C4BF4E839AA
+                               D2EB9D137B0F7889E68F4B5C8160199A
+                               7C9C697EA6A1794E954ACB535A72B255
+            stream[256..319] = BD7E1C4A54C911E84067AB00F8427810
+                               BDBF4029E78D424E65F477BEB457900D
+                               0EA49B639863BAEB1427A161B8C629D3
+                               55097F5DFFB24BB97329A73B144DB7CA
+            stream[448..511] = A4D9A80D0055F2D8C55D2A49B39DCA69
+                               9A5652C43258152B42BECDE07F21F8D0
+                               EAAC565DCDE549CA4A9A27D82F5AF4BB
+                               1EEB1B0A53A58E50C3E83CBCDCB980F5
+                  xor-digest = FF451365606D0117E15FC2721F40C9CC
+                               0FBF6442A771F8FC3B06186C35C6CA13
+                               B30F65FC84B9A38A6FBA2B6F16541B0A
+                               0D77BDB4F696894B2B73CCCB8D6FA3B7
+
+Set 3, vector# 27:
+                         key = 1B1C1D1E1F202122232425262728292A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BE4A26D09D47D25416355FB7FF60AA06
+                               3B3CDE5374780F2C66514A0CAA07406A
+                               88490A2E3D6294A799C9BAAAA1B10ACB
+                               88FF4F6F70EF1F4F67D591040244FEE8
+            stream[192..255] = 54F1AB7235B6440D6A7FC7851E3FFDA8
+                               6CAF44E3F57E1E9406908064FDDA3A3A
+                               3C7AA1CB6ECAAF376C5F290EA02844EA
+                               779A225131F24D2E7D34AD0342399FED
+            stream[256..319] = 81AC4F45FC40CE7E1FF890F5EFF2B583
+                               36F71D1911C7E0227AD8E4DFF7369B41
+                               A8C266B3468A78773C4C40A3EEA6B724
+                               97662462F48835FAC7B6C77CEFD39A65
+            stream[448..511] = CACFA9A51224F533C600BEFF1EC03C7C
+                               7C22EDF93E8596128F8709F0CED4E291
+                               997229AC5542FD2CC9B1167C3D2BB57D
+                               9B08B82C0FC41D93B7CE2211C5E2D534
+                  xor-digest = 0D949205B6024DAC1D215F2AEA7CB484
+                               3FAA9A1719398AB8828A28BD2568369A
+                               C78A224AAD95BAE6A6333C4C13D630B9
+                               42AA52099F6EFD6871B1E45C8DC68AC7
+
+Set 3, vector# 36:
+                         key = 2425262728292A2B2C2D2E2F30313233
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 65906EA9CC0080D2044671D22C7DE242
+                               F764184ABE8DADBCD550225BFD541D6A
+                               762C7A5268EA0ECE51D18269E71A4CCC
+                               054AF634616204C81AE7E515719775DF
+            stream[192..255] = 9ED75834EBBD9576E11DCE8C583ECEDD
+                               2B8780FE98B44E9F08BBE96922C77BEF
+                               08DCE0DFD7C77C42236885BE6EDC8343
+                               24EAED350AA5A513009272818CBC4BE5
+            stream[256..319] = EB1D998260B3AF4472DE59E1C9DD359A
+                               B346B32DCE36C92C9B7BD808BAB76AB1
+                               EDCA2827557501BE0FE28F6498B33B9A
+                               F4EA48786F3158E8047A32A03AE1CD90
+            stream[448..511] = D06B1B9B8110FB9809F5887A35CB24BB
+                               80EDE203AE648AF9FA348B18D8A15B8E
+                               E98E8AB98A7AC5BF71FDEAA1A6E978F6
+                               7D5734AA7FA88E8DA44C861E2F54E585
+                  xor-digest = E77DF8C1D5F46F8896DD00187C840B0A
+                               E4404581DD053C6F39323815729DCE90
+                               0D85C2D8C97D0A3B57CF622F81077B80
+                               92988EFFA36CA176F7393D1E38AAB206
+
+Set 3, vector# 45:
+                         key = 2D2E2F303132333435363738393A3B3C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3FBFE9A391DE0CE5AAEBF9DA3A15EB99
+                               D6CBAD0341CB78042C89F5D5B0B555C8
+                               A400DC47FD19F40493B348CB51430B44
+                               D05AFCA9D399709EFAB8ED2587F72E85
+            stream[192..255] = 68969047EE54910C44F8B5718E993234
+                               D814C27C0B59EE09F0D35B58352AA6C6
+                               594F605C25C16CDDC29A354A1C6F5948
+                               AE497C093E2D41C211E4C1417DFAAFC4
+            stream[256..319] = 0DD68E08A25ACA4448DF4B562EEBB855
+                               14E41F1F560C479542FE62C2DCBCF03C
+                               30AF180FB71E65A9A09C551551A33942
+                               53558C2440084E6B4CB664A4EAFCAB66
+            stream[448..511] = D93B80D67B6484030103CDD72536E695
+                               E7BAF8B1115109D5D5517BD1E06F4236
+                               A3551688F5C0D78B2CB080AC072B4C48
+                               94A2AF54AD9D816E2068AC569BCD2AE2
+                  xor-digest = 7C071BF395B48A023A7B708A9651EC8F
+                               0C9A00DE8BD9D0764C7F1F394AA2B747
+                               3EF87BF792D5B89AE0548EB9C1344DAB
+                               DF2E4EC6064D50EE1622160D6DD7ADFE
+
+Set 3, vector# 54:
+                         key = 363738393A3B3C3D3E3F404142434445
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 64468807E7EFE78E11B0231D8D7AE80D
+                               BFF3FAE444A60496C8F2DA202941686B
+                               95C48457C1F9DE1AD2FE581336AE36AB
+                               CA574BCB9619CDDB96E4499409516635
+            stream[192..255] = A7DBFEAD9B969D334705B6C53A0CDBC2
+                               21E0BB92854B0B107CC39F8C6E4761C3
+                               EACC8D8C5741AA4243C5BE1A79971A0A
+                               5A23F2BEDE9F3628CB9099B8C7EA9324
+            stream[256..319] = 1A44FB18740973F3124EA805C90C4B27
+                               4EE788D43F4B894B01F63C13410EC204
+                               2607241E87555B0E1A6FF33AF0DB010B
+                               8ADF607E6353FCF74F568E0BAF0F4455
+            stream[448..511] = 11568B95495E520EB6BE106986A07C57
+                               8FDF21463607619E5AAF117D84611E75
+                               F8979F59E60B43C0A37BC24429892742
+                               0D206274DA45EBBA7660422DA45294CD
+                  xor-digest = A70B9BFC683AF2716E17980A49C4F747
+                               AC25992BA7BCA5E5C2AE162497E4E8BB
+                               62C837F64EEBE4A55B5705F115CBA057
+                               C560B1AF0A733B5631E23442601A741F
+
+Set 3, vector# 63:
+                         key = 3F404142434445464748494A4B4C4D4E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 35865AF843244DD2F95CDF7C9BD54471
+                               9C8432538842C28F93AA21F6E10F8B18
+                               31C2AA7EC010A66E539CF65BE55120BF
+                               090233750995003C7AE414DA6D55F86C
+            stream[192..255] = 190F215FD14E44CD141E47A2322D324A
+                               A63A7B512A77C20A02D3BFC1EF8273C8
+                               F65226CBD1BF32A104D1AFEFD6719E4B
+                               DD6355B044EC8D0CE95023C61007E6BB
+            stream[256..319] = BD02130F7CFDBDBC2171BBDEAB501136
+                               B2364F5879E6E9CCA7E75AD81105D9E4
+                               87E9175B62AFCAD79B23D392B2E9C418
+                               437527118797602E629A70CC869AB7EC
+            stream[448..511] = 1F0DF396B5CA6EC9767B0674B2C7A9C9
+                               133CF872DA39DE78F56D41C7F2FF6B50
+                               716717E995D42C51D6A2ED66FA6CC7DA
+                               92E9B3B4D1F130E699C430CFC96969BB
+                  xor-digest = 70291060FEA7D40B5C3FF731FAF7630F
+                               D9BBED1A7FC25A05E6B3F632E6FD6B91
+                               1F1010E1BEC69F16D44C5183E38BE8DA
+                               8949A4D8AA85F5149C203F8C92887875
+
+Set 3, vector# 72:
+                         key = 48494A4B4C4D4E4F5051525354555657
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BFFC0703408DF6EB169656D09A5400DD
+                               9C4BAF06A3BC7220E45814104B6D9000
+                               9585BF9B0CD988E94B8C5026D07AD7F5
+                               7D81364775D54D808A5C18453B62A2A1
+            stream[192..255] = 5FC95B73A4C91DB20B93319E420B4C5B
+                               A9DE1873C81C835CB455970A90921594
+                               F9635EF4F411C9ACB4298F75B2CC84F9
+                               7F52182F7F001A1EDF72A68FA1ADE313
+            stream[256..319] = FB24E97B0CCFE15644BAAFF342C55FDF
+                               64434708407AA6D73576E842D5ADF4A2
+                               6B32D329A2DC9F1451C4BF3E9599E9E6
+                               4E5E65F73E09E4F1254BA0DDD8E6C52C
+            stream[448..511] = E2EB303CD0A67C99CDCEE86BEA581FF7
+                               093C9228900B563C6D10B20BF99D3911
+                               D47C805D1447C8F233D3FDD27CF0DA42
+                               D42E0389E2CCE99A274AD9D20B9C6102
+                  xor-digest = F83FB58CAEC8B13BC25C152FCF24E10E
+                               392A197FDA05A6A20E14093EA0B34C5D
+                               FAE102266465324F5AC07FFCECC8E618
+                               D0BB60761A26D5FD59D188097A2348F3
+
+Set 3, vector# 81:
+                         key = 5152535455565758595A5B5C5D5E5F60
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 84076D83A841C8C6ADDE3B5D9FDD6529
+                               4D0F92B549112F0A6DE05236F732E81B
+                               3C8E92229C411D2295129ECD18DD08DD
+                               C98BA78D9BAFF6271D95E1F361EF699A
+            stream[192..255] = 7063A52FB2729433D8A7BF30F27E6EF6
+                               F17C2A422E60A737270787985508D062
+                               4E678A597845CA9EF939F4B8966BD99F
+                               B8633FEA673CE7BFD2ACFB5942D7EDD9
+            stream[256..319] = 4FCE866E8C2359C53F0429F569D02DAE
+                               E99A4062246B633D4C502DC897AD8025
+                               38C95D49D3B1FA94F4E92441357B622A
+                               6264F50D5554BBE42191AB3D6073A8AF
+            stream[448..511] = 2F7C38BD00309FC81D28D84EE4355216
+                               D97A823CC46FAB9DCAF621E4128F9CB8
+                               838BF02E0EF940EFE96860CC0B996044
+                               42CACFD3306335241C1B4B65E790233E
+                  xor-digest = 44038A33AF0013BB34CBCFB77F7E060B
+                               96F5134DFCDBF04EB8F7F29B15C3FDA0
+                               F766DC940FF548C23712625793851A94
+                               294CC7201E1EDC6056C12A46524C6FD0
+
+Set 3, vector# 90:
+                         key = 5A5B5C5D5E5F60616263646566676869
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E811CA3DD1DD0057AD3A1794D3F9CCB6
+                               362049B1692D6ACFE1A6A0FCC99C7A04
+                               3AB9932A146B4040AC9F8E2F0A227C7E
+                               C60B1F35D60EA14483BAE1F8D1AC7FE1
+            stream[192..255] = 865B05E224133AFC45043F05F8082FEA
+                               487BF63BCFB96DA3EE26960061446669
+                               B1C92C6BC5905BD1EB57D579CB62A220
+                               2F35CEB603658237AF1908132A25971C
+            stream[256..319] = A84BE383FC852F1BF44130EAD15B3548
+                               56737C7EA68A0700A22D357FBA70E031
+                               BDC0FE8EC36C41790A8B7706A00CA338
+                               603E054A83881599D718B1911D1CE9D4
+            stream[448..511] = 9286C3479F9A17B51D8749257F59E892
+                               CE7C3EB8638B29C17D779811F01EA405
+                               257062A5F28BCDA1862FE653C7607350
+                               9A87D12EDC5CAAFF9E8F9F76DA0BEDE2
+                  xor-digest = D629CA4708BEF7EED04BB5531DDF9C64
+                               BA4981C9A705D59C4B2391E94B79CFCD
+                               058406845D81E7EBC097330C01FCBCF8
+                               D78940893B4FA38554A32D861AE96D04
+
+Set 3, vector# 99:
+                         key = 636465666768696A6B6C6D6E6F707172
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B89516368AFEEEC12434F76AD1E1ECA8
+                               FF6FEF7B46D05EDD6041C7B8C1E3A33D
+                               2818E38113592B615E980304D93435DF
+                               BDD5676225173331C3667F30AA2A3D2C
+            stream[192..255] = 249528FA392B19B6811711F523D27578
+                               F1BDE75CA167DDEC08303906B64FAC0F
+                               B2912A7A0EDBEDAF9FEDA420DEA330CA
+                               7302F5780827CB11B15A4DD333FD7099
+            stream[256..319] = CECC1B5077BCB9E129B01D8D75089B41
+                               64E76DBC9C8CF2E4D2F17A6248522A51
+                               FCFBFBC992F75D613307F4DD6472B6DF
+                               C8A5B29F1068FC0F1C3F8964B0E09170
+            stream[448..511] = 8B26C436E918B099E4D3A7D4D3395E49
+                               056A8A29130667A32C6A2B0FD08A482F
+                               8F7538ED90374846FFD2E1C733AFFDA1
+                               12148C9718F3F208344D5FC20128AE2C
+                  xor-digest = EAA0ACA59CF63BC27082BD52D6757FD7
+                               620A7AC5AA2FAEC52646978E2057C5FC
+                               F60B36C09D87419C1D1A64133357DB05
+                               6B96C854F38C36DD657524FD09729341
+
+Set 3, vector#108:
+                         key = 6C6D6E6F707172737475767778797A7B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 741C607A6BD38F93B33244C8B7F05D78
+                               46F6A05CEE5A87762480DE123D3BEE63
+                               240928FFC75ECD9AD1785B1664DCB59B
+                               A12F3B64C93BD4FC8C67C0934E5B0ABD
+            stream[192..255] = 3BDB31A701DD7F2E929803C3A47896F0
+                               9E5F569A32AA829E505E34BB7232597D
+                               B838F543A34CC288F9518BE16A228D42
+                               BED0CA3CE0C6E7FF9AEE63625C699B9A
+            stream[256..319] = 1CB7FE159EC1A57043BD142236DC0A18
+                               0CEF37316A6E96354AE319142282F19C
+                               1550EB645DA8F7BEE2ABAE4EAAC0BA29
+                               893E722A6F8E0A9B34368DF56C5845B4
+            stream[448..511] = B6DF810D69EAFB7F2360F6ECB50C5861
+                               7D32B3F495B3E4424045E88CFA0871A2
+                               9314121CC78B98B456ADF53E540346B1
+                               214AE2ADB65C552273F1FA498FA74101
+                  xor-digest = D35A8AE5783348824175BD34F2E16FBB
+                               975E7695DC6C4FF1ED763D404B0D4D30
+                               07AAF01E988BC85DB2FDD017691D3BB9
+                               811355C3C7A6156197AF57B794DCE85D
+
+Set 3, vector#117:
+                         key = 75767778797A7B7C7D7E7F8081828384
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = EA9DA2D5BD4B6E070479ABF8CA2D1B3A
+                               6B968A025D010944FEB51AB2E507F86B
+                               111F8A351A3F32CE1FBC4A75AC34F722
+                               1B5190F2390073084F8153E00BB98D0E
+            stream[192..255] = 0AE0DC3D0E2D3F5F93E446BEBECC4F60
+                               862D190829A209966E132DD029ED6998
+                               DEF4F613F3D53D0A36CFBA2CFE345DCF
+                               013B6CFFEC0116FFC1659A57FB42E0BE
+            stream[256..319] = 5A7FF46C335912389D8B88437CEFD27B
+                               76706405F45F87C91390273D9B70CC5D
+                               89FDFA85E20EC82B98A79BFF5FBF6AB1
+                               4F61F2C1289CD7B8357126C8E13271AD
+            stream[448..511] = 9398E699F5AD8FF31A50C8EFB9DF0D0C
+                               FD612B951A203C1BF85C62AB5AF1C412
+                               42BFD0A55F21820C6F917EC90A8FCAB2
+                               E774A93713A99C7900B80A2BF496D0AF
+                  xor-digest = 05D9732FF20A61E19428873830DA7282
+                               819234F22FE7DFD8871C21CF10C08EF0
+                               7C0413898DB144861B0CCB62992DF40B
+                               29A0A4688C91275F0A198AF39899E362
+
+Set 3, vector#126:
+                         key = 7E7F808182838485868788898A8B8C8D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 8C4F8495C7231AAEB704E7AB9E79E748
+                               6CB5BC85D3622B8A2E2CB778BBFDACD4
+                               CEF73CC485D8E08406F5986A28706CD0
+                               56D085201DEDB875573B57629B8541C6
+            stream[192..255] = CC6374A744E9205CA39BCD678074B844
+                               16346A7E54F9B87905BADD2FACE7B9F4
+                               B0A366AA3F632A7A67AD8AAC4827C9BB
+                               A1E801A8786BC4FAC2ADE6A6AD6A45F4
+            stream[256..319] = 4F52AAB001BE94A60761CDE0334F8A84
+                               C617195B084E441070E343CEC3189CF6
+                               D6D955F9AD649A3891BDFFACA0A6E6E7
+                               7291396670BA07469D267EB80E48353A
+            stream[448..511] = 673AF85AD5A9A3F26CBABCE9BEBBAE21
+                               E0B6DCCC3256227FC0EAEDF343CC7E9A
+                               8896023DF073E88EEEF135BE34CF67A5
+                               5FB51D3A1754B15A7C4E2CCCB4C8D51C
+                  xor-digest = 2BD4B8BF9B7E79B0EB53318396B03575
+                               0AC918A6A05BBA499D81C9EFD32A0FCA
+                               34A83FC801CD6475A774091F33AE7689
+                               B9FE28645F545E9A9531F528085926F1
+
+Set 3, vector#135:
+                         key = 8788898A8B8C8D8E8F90919293949596
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BDF2E95B80FDF304C3C4A8081391EDC9
+                               7F9553F93C27788F03797EDEBB8F59EC
+                               2FB2FCCA7727CA1CAEBF5C8DA8719492
+                               F1369D96B2FEFA23D89400CF7CA667EC
+            stream[192..255] = 6AB7500D876A4924DE59800345AD69FB
+                               BA1690733713BF372E0108D9FB65B0E4
+                               50BB89899AB84198381623094F823FF4
+                               8BF9A09F0FCA23684E78654F3D231173
+            stream[256..319] = 34ED638D249BB1AB8B16D350309AE32B
+                               9FB62CAB0EC7AB9D5F3C12C9A6502497
+                               6323EBBBC4CF308FFA68A3D4D8D3959E
+                               AFD3BE46E36072FD15A5DC3FCDECA6D1
+            stream[448..511] = A8BA33AF6CF545424E607A7FC4CBA593
+                               CB05B38C836B21D85B6FB1894926A459
+                               8D71AB424A5A582A491747FED94125D1
+                               08D6C693EC9E4BDE2F418810A921B54F
+                  xor-digest = 84F29F11524741D39779025D792AB735
+                               07963EAA0FA8EE220ECD3592E1320567
+                               BFE76EFC3356860192DDC5F06B94E552
+                               43D659D49FB94C30AB69AB5E9C370A5B
+
+Set 3, vector#144:
+                         key = 909192939495969798999A9B9C9D9E9F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1C03A0D6CB75670CD7D978B2E371857E
+                               27E597B15B905D5F4F4384FEC227073B
+                               5A56D8C0C4AF767F267DDEFF86AA036C
+                               41EB6170603AEB3E3C1EF3E176CED812
+            stream[192..255] = 6447D1E067550DEC9E8AE89DB02B85B4
+                               3DD7E511C8B98438BAA50CFAF7CDBB68
+                               757DA1D03A29B9EC6BD633E17BEBC8EB
+                               2D8D453F583E4D183AF30C9F47C8DD56
+            stream[256..319] = B324756101C28D9FC4D1F065F1D000F4
+                               1155514EDB30A7FE36C26B18FD93D6D2
+                               0470A41B6F8D2E8BE140568BF72223F0
+                               981CEB9D100B21C8B751BA6B2816B2D0
+            stream[448..511] = 304AADCAE0CE80E91E3558974A944663
+                               D1E2253977CD7B0D1BFAA138DD81A501
+                               D7EADD8FC834931A44642BA9873AC1B2
+                               47A454EE71F7AD8671BC15E088D01532
+                  xor-digest = 5980D43A91C09B20B0F3323F1750CB47
+                               118550920627B6C512AC5CC53AA6AD25
+                               68EE1EFE702FEDE7CADBFA25B32696FA
+                               12A18CCDE35A1B679F709F28920DF92C
+
+Set 3, vector#153:
+                         key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C2083A758037E850A6FE642EFDE59AED
+                               F51F3002BEE2E69DBDB538BE2D93EE8B
+                               27A1CC89672DC14C44DADE531A88A769
+                               5DC730A2CDF3096DE7F4BD08A1ABA918
+            stream[192..255] = F4D19950E6365AE6BE8011A24B9D803A
+                               D9A8547D452D8B0B8C51676E207DF323
+                               808B5A094A2FDEA5DBC86BFCA576E98E
+                               D0E049834CBE0B3AFAD6892B542EC7AF
+            stream[256..319] = 8F2A026EB2165F39E27DB86607878926
+                               4EC8F42A09E8C80B317FD4F1E32AF4C3
+                               73B7F5160C635ECABE495B01A3488E27
+                               94D226E2D86C4654810C08B2FC42610D
+            stream[448..511] = A1D17725577B7A4FD3D1A280BA2B5C0C
+                               386FCFA09E110F00C85ECA05CC142644
+                               4D8EB87CCDC2B23D1CDBBFFF822B5555
+                               11055B93ADC9168B7353CAE10551AF14
+                  xor-digest = 7B4E8A6123216818A218FBD50D8540B0
+                               A0B62DC114F25DD476680F85DEEA9306
+                               4CBC4526C7A8832D4BC534684A403FE7
+                               B80E7F20D967ECE044085B554C158AFA
+
+Set 3, vector#162:
+                         key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 6FB232154275843C74BB886D09CBE0EC
+                               CCC539DD6DEC1EC6F31578B80DD3BAD8
+                               5C992CB1A0B4EA40B3EE0C5174E36A74
+                               E1CDCAB13830453984E4365A6C599F72
+            stream[192..255] = 2682C05E19F6D8FC4DDB15B2F8385B52
+                               C5A4A70FF5A0063CD696AADBF8505122
+                               6F696746D4F8C314543BC3869B1E7F9B
+                               1C0D004655FB6585723CD1EA7A700A60
+            stream[256..319] = D6BA4C5A33B8C2DE342DE48E26AE7B14
+                               8E91552D0E05AC9458ED0010E6FF53AE
+                               EDE70E910165B5986876799E60B7E6BF
+                               3109B9BAF7EE3670497FA7CAFCB14733
+            stream[448..511] = 70C4E8AB8E8BA681A2A06F319CBC952E
+                               E3E78DA589369FEEF8A6BC6D976BECFE
+                               E6C7143337758929FCA7E0945892411B
+                               047C2CC2F2AA284E95733DD94D46B89B
+                  xor-digest = E2D3DD6AC908FF3BAE4791A50F717B63
+                               FB3F1F380CC738E2B1626FD026C9BEBC
+                               33957AF4ED6E8B9864EEEAE262FC6168
+                               9A34FA14A35BD915B6945F35BC3D5573
+
+Set 3, vector#171:
+                         key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D25BF02A1BB050E0D15246C2EFB3EB89
+                               390BB913916D347586DCDF71D6792CC6
+                               BF72F6F6A9B779BD8833C468684B4480
+                               52E153D11A0CE183CB337450C4482F6B
+            stream[192..255] = 07980A2C57E9094C5334016A782C830E
+                               B59420086EF9D36542A97220A5EEFE42
+                               026B39B1F00A78992ECA17FCDDCEEA2F
+                               88A15F934A1C65EFB770C2FB9712FFF2
+            stream[256..319] = 8C0AF45C68CB7CA8CFF1AB18F2F9659D
+                               E49DB5C4E3609B50C06F94FC01C059B5
+                               40E302FA8604F030701FE3C833617E0B
+                               094D0BBF10580F7C1C7047E86FBF93E2
+            stream[448..511] = 4D4BEFAB68D63085A05C729F54468567
+                               2C2A9452DF6B4B651A29FBC29513E3C9
+                               635DFD75EAC87A5B1362E99033304EF5
+                               DF42420DFD49C1830D66F4F90928F1AE
+                  xor-digest = 9A7DD8AA5D9E9DA4F34AFBDE9D909CE5
+                               DEBC05D2F930FF08AEEE4096B2E1E453
+                               8587B88E535A217E986F31965C5965DE
+                               3BF4A7F99B3B9D938D2C1AF7DFEFA14A
+
+Set 3, vector#180:
+                         key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5FB2BFB5B9CC4F84D7641B4555DA4A7F
+                               C07C0053E7AD2CF2187F7F34ED4068AC
+                               6D5B43A5FA41437C05C65550786D60F9
+                               A737F44BE450A1F416C1B1A49890C609
+            stream[192..255] = 8EDCA89958225E39CF796EE587877A55
+                               F9B7A7381241597CA6280F7617A11922
+                               9268F95BB326585AB59F08BFCE8B5638
+                               B3A0D32A761C796060DFEBB5BCE859D5
+            stream[256..319] = 09601C099BAC574564E4CC6FD659776E
+                               4726FB22E0025C37873042866B913C03
+                               285EA24E37847F9AF6C838B82FE651D4
+                               EC5FBD40A256E6C765757B6A3CD08C92
+            stream[448..511] = CA5AC4ED4FBEF0D754F033B5267B9FDF
+                               3CA52B131E118174F70CD4F833A5ABBB
+                               198DBCDF18BABB0B0CC37ECFC8D93AA1
+                               5949FBB21974169B46D545F0ED03C71D
+                  xor-digest = 5DAFDEBC75291BA8F55B4A370756B28F
+                               554FEADDB7888F2834BA1EF221E917F5
+                               F631D5BD789701282DCF16FA450D250B
+                               52C627741369DA654E237B8D7F4A8BA0
+
+Set 3, vector#189:
+                         key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E9EAE6C4903004A2AFCD05FE2E3E7F95
+                               FF8BD2888C4AEBB81CDBBCB7488C54E5
+                               B50467FA82B0CA7EA923C608074E1B45
+                               6452821FC36789C8061E99E8A0C0B579
+            stream[192..255] = 1EC898A6958F23C186261F833BB3EF0B
+                               3C185AE8138311B6AB42098E9C6C7FE1
+                               0306DADE1DBF2B1C3215DEBD88AF1CBD
+                               2D805B8006FA0DCF136E225AE3D91AA3
+            stream[256..319] = 55566604D1C85FFE1D29810B6C49F019
+                               69ACB59765A3FBA2B0B9880064606E47
+                               18BC5F08C32EFC250FEE91FB88077A2E
+                               0840615CCF627C64FBB500B7B800B9CD
+            stream[448..511] = 707821EFE4119A32CFD99F7ED7CEC018
+                               C8EE90493FD9268A83E5482DAF9A646E
+                               8765D8199A56A12ECA50775099179D70
+                               B72A3CEC8F0EFF1AFD074F04548874E3
+                  xor-digest = A51E3C9C948B68A1543FDD1F158DD419
+                               195AE7662739446D9FD543681A866A6C
+                               F09756FF4E0C59BDEFFBF98D53F193A1
+                               77D7BF19320063B8AEEC8A544D5D72C7
+
+Set 3, vector#198:
+                         key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = EAA9729F0222A16C750540C605974B55
+                               4FA622F67C71FBA40236A71AC19706F7
+                               9E3792F4B444A39C9C1C902FDBD81898
+                               096338F6A8EB7C934B9558D48AC53301
+            stream[192..255] = 3B5E53787C050061000E3622876AA126
+                               00971A76253833C53B9DABA976169395
+                               3944B5050AB17E492E185737D67581B8
+                               B1C766D50C5B0C2B0D8C78A781E77D89
+            stream[256..319] = 175C28764FEAF8396B3CD34C829D0D0B
+                               E9CE0D75E79017A96C4E7B158B171BE9
+                               4C906FD4BD4946E6DEEC3C78B34C0754
+                               9E85AFCD958AF345E0B432F33C86AA76
+            stream[448..511] = 37BDD665CD9D5A8A8190AC3EEF981379
+                               AD5311E15F853A8A89840879165147A2
+                               807AFABB6236CEA9319DB32344987889
+                               5744A506CA76CE69D9E474840529D667
+                  xor-digest = 4CAAE8F441F6EF3DB6971E274181F8F0
+                               4D7BC603E040833E77921A393EA13F0F
+                               ADFF07AEC94555224F6204874027106A
+                               6D7DDF0546F300D3E84AC87699ED40D2
+
+Set 3, vector#207:
+                         key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 83AC8C40850F4FCA5452871C954AA61F
+                               31A9BD276D39EEC03EC5977A71FDAC38
+                               368D110C57C1A19F2A7461BBFA88E372
+                               F78103F9FFAC1361AC2D2AD84C6AA3E8
+            stream[192..255] = 48E95C2FCFC79C91BACD0C41F626F05E
+                               F80E076E359299EB5272A2F688F96F6B
+                               3147C5A19A99D562A11E953CB2A90911
+                               205A7760B5C8CD959EE6C183A8C1420D
+            stream[256..319] = 974A4DE50EB45F6144DAFFA6B4A68E39
+                               48838434497B8F9700FC42005F3C2FB5
+                               A79984CC2E770C5400EA21AA4EC05751
+                               80A288499879E50462225BE03D677875
+            stream[448..511] = 09823B2D55E26C49E42FC0820D7BA081
+                               5A7EA9380637A2AE2C0D29253EEDB884
+                               9BF4F54D64677F08A1763EFFD904B62D
+                               B3843B0ADE885C00640D16A99E28DCC0
+                  xor-digest = E73D8783F926558E0C1E1B0D3FD86CFA
+                               974CD70EBAACC0CEA2D977E9AFCCD384
+                               935584D2FFEDEA813E6234112CAA1401
+                               71E99BCFE61A7D0E430D4D3F75AA3E28
+
+Set 3, vector#216:
+                         key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5DE3EC7E6D724976985B426D722D93E6
+                               1F40F5F17EA14B298AC898CBD69F2BBA
+                               5705E1D0CEF7B7122362FCC0D5106D54
+                               25D51F51E29C938C592D9E862DEE9E33
+            stream[192..255] = E079C49AC8F160A9D529F30151AAA7A3
+                               1D137E03DF4C23F8734AAC3B20BF8520
+                               90E3C2529761EB4D67AEF1CC46399947
+                               1240DEE8343D6355B5D7377A7934B019
+            stream[256..319] = DF574E03ADD1DCBD0712D2748C93CD72
+                               D8488396AE3D3275E5A53CAF3EC112E9
+                               50A79494F25B9EC111FE9A7A68A5AEA9
+                               63A4F87B37F822B79D954436368D8E20
+            stream[448..511] = CCEF4C93BCEB2494EB4C70F5E301E980
+                               C494AF8C117F291DD09E3960D2C5A7F1
+                               9928C08F2F51C419E734DE9AADD25C81
+                               3579A7F0B8B367A49B97DED5793E4DCB
+                  xor-digest = 868706BC1A5F3D0BDF96E10324EC36FE
+                               01596216B0B8BBFF69C5BDAF69D0F38E
+                               FE89FFC32D34D142F413A5BEA7AB38ED
+                               22436C62F86C540101DC0267FAF67904
+
+Set 3, vector#225:
+                         key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 45A0736DB4A28A3A6DD181FEF3485F2C
+                               918C65663597C49F4FB23CA550C77CAF
+                               7B331B5D183844278E0D959EA024CC21
+                               CE1A84923E6E782472BA1645BEDFC60D
+            stream[192..255] = E9EE0DFD717F72FD8899D23E87E77DD9
+                               F9DA66B4645AAD8D8C3B489B0A637449
+                               80020326469B4C6403012B6E315CD35A
+                               4344934D720467F30B61C8AEE5C3C342
+            stream[256..319] = 94A2BA2B744CB83A29004AE21470212F
+                               67C2FD18F227FC017131D7F4DD0AB412
+                               48C59BADAE2E408584DF35C603192E37
+                               344C52664DD68B9231661F304F483F41
+            stream[448..511] = 6A29174A1099BF8759D2F5F9BA60816A
+                               B290252AEE08339BE0021033DED03C46
+                               9C8E28AAFAFDC67A7F2219C8942B004E
+                               47263842BEBB47EC6B0666ACCC884591
+                  xor-digest = 7A7411EE5D174907B1138575FCC7479F
+                               AF3437BBF098CCB5D8D25F49E6788374
+                               CBC9CC5812982CBEAF59111813430BEF
+                               56D9DEEDB6C935804013759CFAAC40E4
+
+Set 3, vector#234:
+                         key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C430C2A9FC44DE1563B1679C1A2DFA98
+                               91D01A302C5165EC13B26F6EE4F25437
+                               264AE9E18C98BE112BF560C72024827B
+                               85665C491C47BB396B5AEC66CFCCA371
+            stream[192..255] = 60F3A13B9EBF8784CC81C132E004A179
+                               BEA0606D4C2C830077A50004FB0487E6
+                               E179D81FD9784DC3783ABF86523FE4A4
+                               68930272980E3B46F865E4729DD34773
+            stream[256..319] = 44BC861136F6856B1C74C1CC13753B82
+                               A75E34EB40C518400B507D99B42E488C
+                               8A1F2F590E029EF48DAF2674FDB053AE
+                               5C0967923102EB964602256F70A9CC9D
+            stream[448..511] = 0EE3ADBC4CCC63A8B67C7812CD294183
+                               A2E9D4EF0D65F854FE66CF9D76A34F91
+                               867B27336F8EEC2E2CD30CCB98AD5769
+                               77B07C73C833B51753BB9B0DF08C4834
+                  xor-digest = 7F848C96AE9310B5282712493AD7E13E
+                               2B4581545E625A4DCD98576C75835058
+                               6C621244B6CD439F8E62625ECD9460D3
+                               A18BC2F5DCD9FA7E8CF7880CCFD1A44C
+
+Set 3, vector#243:
+                         key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B9B3501C75EE296AE858573B63C4888F
+                               72B18683CBCD6B95602D51E4388D6DD3
+                               7129169A5209202E2C6EDEB5026B6511
+                               55E4747DD706DDF248A8705D50D38A29
+            stream[192..255] = 12F90D1028010D8296DD0D6ECC4F2354
+                               89856C315555279BD0A4E3161178AAAE
+                               BD849EC0A90903CCFE9DC7CC821C1CAA
+                               D63A45A1D0C0247F1FB1423877FE9A32
+            stream[256..319] = 9F0608162C6315D206B5EFB0E40291AD
+                               E882445B9F34154F6E21B9FA23356DD4
+                               79DFFB16482F6A4F28A8A0629E8B1D78
+                               EAA473CB126FB3727B826B4B3D6175E6
+            stream[448..511] = F26FAB00C37C03AE33209E19F865B135
+                               115A5E254A6B5C1A4896987EAC35C2F4
+                               327822E165AC6BF99F535055ED74833B
+                               C1FFEB32588D8995CEF0708E2D3CF832
+                  xor-digest = 87243F1D4D08D7EE39213D1A4B9E2458
+                               368339A11E364345B4367F84154B36DA
+                               03A3728A7EBD4237897F9D1A19CCFE92
+                               B9D67D3A4A755E6EA8382041D4827A17
+
+Set 3, vector#252:
+                         key = FCFDFEFF000102030405060708090A0B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 05A90DAF1A6B6B60CD3B999A11FEEE39
+                               6D38983ECDA326EC9229D2A1EC722B0C
+                               3C0539DDBF6A4CF62B9BAFEA6C60A29D
+                               4AB63BBBC88987E9A74AE2F71B1E8DE2
+            stream[192..255] = 0AE6673D9F99C5EC9A4532B2B9786CB9
+                               E948A206CB992335FE868BB2271DCA5F
+                               9AB75995A7E7D46F8EA6693765C93D90
+                               9D41C24EF4856252986DDFCBE65D2D11
+            stream[256..319] = D8B07A866003059BAEE90378AD5EFFD5
+                               2732755E79402B50BA0F26A038B3D9C8
+                               1481C19080CB39FE840F8E7313D0C034
+                               9FEA4AA4801225630AAED3E522D6F920
+            stream[448..511] = DED21140E5A3C0C4615D7153DF9381F7
+                               269616817A273BFD984AA5E7CD9D9CA1
+                               9C28E51F4C03C262F5BB4175C799236F
+                               DA69AB27590857C0F270CE4BBFE02D5E
+                  xor-digest = 2D47DA3161389F5F54FAB37F391C21CD
+                               63A748112A1AB415670524B6CB93DA0B
+                               6B54C541ED59F3A54DE238C3FADB3236
+                               3871F6DB1A507B33C1B8F280B0C04B1A
+
+Test vectors -- set 4
+=====================
+
+Set 4, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 114265E078311C062B518148B4530F73
+                               DC9B95DCC41C214F8C9486473DC46847
+                               71819020010586A750426A0E633BC787
+                               6E228E2353AC0A68533C85A742387800
+        stream[65472..65535] = 196F53D41603BF286D1D11F012E564E9
+                               3C7FEEEC9539A015D49475DD8CC73C84
+                               2F85521B4DD9789A813A59D444AEC702
+                               164F669C59B43B5115202D08662D4EC2
+        stream[65536..65599] = 8A7B672621B0B77E8BA8EB9A71DB4558
+                               A78364244F182519F89D25D3012CF8C4
+                               E429DD543C8DC56C6DB8FA5E351BF615
+                               106B51F9FD00F54018A94DAA91D76715
+      stream[131008..131071] = 33EC15BB2C553646CAED9ABD83F37ADF
+                               AD3B3313A074B69FEAD405BAF897C3A3
+                               E12BFB2F4CC3136ACFDA284DA1E780DA
+                               B3E4D34C053302989FE6A79A1EB0F5D2
+                  xor-digest = D899BF7CD2972EBB7333D4E57DC809A1
+                               B717373577B15544443915B36ED162E1
+                               25452584F3E0C2B62164092219FBA924
+                               31C1FF2A14C8E2E437427DACF80A200E
+
+Set 4, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 8EA023E23D94434EAA064A4BE52866DB
+                               57EFB7B200DAFF5AF2AA72D3E55EE5F4
+                               5060FA89024F259CD2490C628452B1F0
+                               91020DE10263BA86838B2E388F5AD040
+        stream[65472..65535] = 5BE1EAE0077FCE5C2C21120EFD560A96
+                               27C3DA9462BE42580065C9E51B7D36C1
+                               D9D717DADF4A3122A08303A8E27721E2
+                               1DADC91138A2461713998AEE26F811D5
+        stream[65536..65599] = 482694A9797978003DFDA5183F00FF97
+                               9F38894BC92DC88418FF68156117A2B4
+                               EF10D76923A734ABCAD1A5B4224BBD08
+                               836E3765321045C3BF6A352371F82CAE
+      stream[131008..131071] = 614BC8A38C5F9E8507595E8F5A03484E
+                               C9DEC6CF52DECFAB008327527B822365
+                               A2038FF09411D7B952417C8C7375289A
+                               244D50703B73577EC272827A21BB917F
+                  xor-digest = CA9E6EC13B679609EA778447EEA1157C
+                               B366A08AC5A96A73D0B5E182DF24EBD9
+                               FC297219A0AF67591BFD68B1721B5970
+                               8EBEB3655791107FD2A0F2F2E341FCC4
+
+Set 4, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5BD3D0625CEAA75ECFC9828179F7B73B
+                               288A208D60A2297F2C328DB0789BC869
+                               4E50F50E8797F8C7A49E24F72A3AC359
+                               796E6188C71A9B3DB88DAEB1BB2C77D3
+        stream[65472..65535] = 726C7D7AD756CF567E0E8F812A282675
+                               7E75D593C7FCBB45F842020AD59F2B53
+                               888354CEF541411B92C3AF6D57ADE7E9
+                               273805927DEEBE552B32D10754C9D2E5
+        stream[65536..65599] = 5703464C0AED290E65815D8D04098B0E
+                               22D2FA825ACD4391B56CA64CB8201BE5
+                               7B4FB9ED6BB7608BD820436146339559
+                               E7464BC13A8AE3167AFCDA58E3C017AE
+      stream[131008..131071] = FFC5787A10E340B07D08160D2C4F653E
+                               407857845A0D68D1EED8EAC0116CC376
+                               E33AF8A1120D8DCAD6C86B757AC50393
+                               46AADEFF012BD0DAA294DD240D87A98C
+                  xor-digest = B3BAA21AA82617D3BB9C2612E177CB71
+                               51A51790D97FE33C3F33C01B32091758
+                               5766643C125293E1F75D6BA3C46AB381
+                               75A2A4934D4C115A6A1547932B077A58
+
+Set 4, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AC5DEC8B95C89F4794B7289C69FABE29
+                               F4AA64476D057873D87BD524666F62F6
+                               B71B5131BFB897AE64F2D500437E1798
+                               A742E7B7D06B8089F3DB2453D008C554
+        stream[65472..65535] = A2F58800E24BA8B754C64BAD9252BEC3
+                               ED1273598EEF4C6FE42FE2CADB81F220
+                               26A90BC88B43F2F1FD2E054E8EEECF57
+                               A114D087D5228CB276FD5F4FA3ECF4FB
+        stream[65536..65599] = 5C67BC8E188170A57DB85ACD2F7121A3
+                               7D83F1A708ADC54C14064A9559FE7E1E
+                               3F9E60B9670EA4394521B11D8283EE42
+                               12874323628EAEF0B90FC4653106D68F
+      stream[131008..131071] = 8AA6F8A20F7D4A0B7EBAF6A7336B6D76
+                               731E65DCCD179BD53F6B879E70B8776C
+                               6A8EA30BFF09BA3026B3827EDB9F9C2C
+                               0F96655D8B84EF725D0603F8CCE3C2F6
+                  xor-digest = 458DB66B656320F5F7E4FEB12E748C0A
+                               59F0CD8A7ACAECC25479C309628EC0B5
+                               3B441B831B484FD3180C52F63EDA1858
+                               7C232B195356996DC29DE6DF54E5BB37
+
+Test vectors -- set 5
+=====================
+
+Set 5, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 80000000000000000000000000000000
+               stream[0..63] = 04740F92C2470701F289669A25BF9092
+                               EB4212FEACF66DAB6B1D520977945F8C
+                               6D350BF26A1CA35EB37FA53B0BA2CBF6
+                               6AC07A8C75D494B4B8281CFBAD4937BF
+            stream[192..255] = 5E47F5F506AA34E7D296C6911FCD3D43
+                               31A032269214ECEFDDB492C47A51C4B4
+                               DE9EF0A63A6EB32AF1DF1C5576A93F19
+                               02B7BB89F10D8C7CDFF9C097D3D49148
+            stream[256..319] = 015494CB3CC9BDE8A2981B25C06DD18B
+                               52FA7B94CBE24C152FC60762290329C9
+                               E58C4E5148585F417733737059E310D9
+                               309D0CEF48D2F1589994657A081BA6D7
+            stream[448..511] = 3B67C1B37D96E1076595660D61340EC8
+                               DDE8F492134270951D9D4B260C8E2254
+                               A7FE8C10DE837A617A8E261FBBF42259
+                               C636B3DEEA0F373FE7C2CA2B01EE3FC3
+                  xor-digest = A8CC89F06815EFF6A91CA276BEBA7F41
+                               75F842F85BEAE99F4335A3B85FB28394
+                               8B7EE3C659274C6B784035B94886BF9A
+                               5C1483941B20170EE3A374E39006C09B
+
+Set 5, vector#  9:
+                         key = 00000000000000000000000000000000
+                          IV = 00400000000000000000000000000000
+               stream[0..63] = C25BA6DE4C87FE5360BCDEF864F3F778
+                               598A6A584325D5E6C44EEA4464D7580C
+                               9B8D42B5B3634F739D6A53D15FA41070
+                               D1DD4621BF87F53F42107618D9742FD4
+            stream[192..255] = 4A3808B0619C9D94E19F3AEA0BEF3839
+                               21D7E2BED05F1128A82D9DC010654ECF
+                               65199A645606CC44FDAE763694E6757F
+                               8FF864CBE4204D45102E465F16CAB8EC
+            stream[256..319] = 3097394E0CD0A9DAA28EA873566E42A8
+                               710C28366C2B41B6BF6687D881094676
+                               9970A5BA54D28D7BF772C4FED13A9F5C
+                               6E7AD3F6948667D6C2DF981955F73293
+            stream[448..511] = E685BC2ACD3A67791416E78699C83D31
+                               852EBCB1C1AF71B926D9161CB6D894BC
+                               8C5E85C7E30A0896369BAE50C1112D4C
+                               CC583E44A8275F44B7ED140E9721C7F8
+                  xor-digest = D9B51AAF4A9B75508FCD02443EFE2267
+                               1148C73264776B5513860BCE8547370B
+                               2BA66E82CCDB15F3DEB0F0728411B765
+                               1A098C23202745C19B045C58AB196309
+
+Set 5, vector# 18:
+                         key = 00000000000000000000000000000000
+                          IV = 00002000000000000000000000000000
+               stream[0..63] = EE43BB5B79EAFB54B823DE95B71F3BD2
+                               F2A7CBB6D28E9BED590C20A2C52F9B2C
+                               74EEB9A1A48474D5DA4964EEE0BB98E4
+                               88030E213A4482BD1A8CAD4CF8A962CB
+            stream[192..255] = 150C4D68BF29DD27A2E6FFDFBD6984F4
+                               3AB56AACC08AC0C0149008F0882292EC
+                               A5359CCF4C257ADD4FC535E41D6F67CA
+                               E5210068F77A5D5F32A23B17F79EB7A5
+            stream[256..319] = FEA319287C29AB84585D4BF38DCFA71F
+                               A36253AD7F4BF58398731713614D0047
+                               F85A465C6915E05232A5FE5AE7A559EC
+                               42733403ECF6B11E4D5E8F4A8288A3E3
+            stream[448..511] = 79CE66DD3F77D40889906EAB1F671B2F
+                               98D9FBF8693C1EAFC89D19209408F3B2
+                               7CD83CB3B9F33151DD4A8D79911255FD
+                               3CCBA14918744B0ACB93A5F96AC9AB38
+                  xor-digest = E1E3F49B342F873263F585EC34969176
+                               2CC46C17FDEE0B32224BB77A8EC82A87
+                               816DC612439E998476F50E876481EE6C
+                               B32ADBCF6A5D50FA16355AF63AA30D66
+
+Set 5, vector# 27:
+                         key = 00000000000000000000000000000000
+                          IV = 00000010000000000000000000000000
+               stream[0..63] = FB8F4925A4F922119A6F29F8DDC2338C
+                               0AEF333B55919AF0D0D9B1DB61BA2E5E
+                               4CFB394E15F6A78E01B5C4AB043225FD
+                               9C8F50AB1BFDB16F944C2660995AA4DE
+            stream[192..255] = 87767D451D81D5B40503913508C2448B
+                               7CC093982642089843D7D9C3DA05598F
+                               7AEFC5B70ECCE327B20658D6301F4D6B
+                               E58FA5CE0525C9CE8E93FC0B387AE5C6
+            stream[256..319] = D146E4312CC11F11916ED9FF8EA8ABCD
+                               E0736DDD0A8AF3E067CDED397E429D30
+                               8F2DBF848C5C1653EA969B608CE01275
+                               53573C88DDD32937EF6F8B0864C581B4
+            stream[448..511] = CE919096A83BF3702D8899787DA7BC23
+                               43F1F10833F16E3EB467440B4921BA1D
+                               96845B6B4141E1CA85364E2D508456A0
+                               E399DD048E72685389FD7EF3F78B655F
+                  xor-digest = 00333EC3A59AD0B8FCA054A08340BF91
+                               906512917E72BED76BEFFE29FC011632
+                               082CDCB1A656FB817F968E26063279CC
+                               ABA796307912984BFC267325DB84F621
+
+Set 5, vector# 36:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000080000000000000000000000
+               stream[0..63] = 202723F8212AB20D9369C2E1EEF8553D
+                               C468854873D04FDD32641E324DCB4EE0
+                               883AC1D40D7C9C7783DF4132093724DA
+                               113B1CB12144E00509FD5D36957A4E1A
+            stream[192..255] = E6717FE0A77F9043607A1A7665716225
+                               C8D417FFE2CD7572083C7C552B79DB6F
+                               ABEBBC2D4D36AB319407982187C248F4
+                               83596AC071C0B0CED08686603B024E7B
+            stream[256..319] = 8C59D97F7A093EA2D0AB890923AE4DBD
+                               D40C33508838A3966FBA360E776670C4
+                               DEED8BC8CA57592463781550BCFD1E28
+                               818E7C33A3AEC43775ED0A984044E9D8
+            stream[448..511] = 0A3DC66754E02423C6EC1C1DD26CE11E
+                               FD70C386729C8290DF358C69087CA7DF
+                               D11F5E0D37A313F74B09F29C552CAC0A
+                               5621556828B0145A6A1D43F563AFF672
+                  xor-digest = 6673BA5866E8E96FB48FAC88D307079E
+                               77AC03692B23070EB5BB9D04FA94B9C9
+                               6C2F958E834DEB51C6ADCE432BFB9632
+                               9B3151E0A89EB72019A4522233B8FFE2
+
+Set 5, vector# 45:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000400000000000000000000
+               stream[0..63] = 95AE241C4E9B6690C319D1FD828BE454
+                               52F18F061C1B1E13AA409829E194D70C
+                               AD5BBACA2738B508A5398DF6C2552497
+                               6D143DF0405F68037C285A0E19FEC9CC
+            stream[192..255] = C0E2D5C6B614E4A498F46D5399DCE7EB
+                               7DFAFAC62794F5C39864C521B8DB574C
+                               149E35D1F0EA36EA7F24EF8FD855FDCB
+                               9CCC79F1ABB13EC33E00A9E137809C05
+            stream[256..319] = 285907400C1A86AA9942ABD7BEA8EEC8
+                               BB6AF2F9667D424C1DD56349C99FC65E
+                               8A00893AE529D7BA492089EB6B525964
+                               E9CAF15221A342C4F88697D818AC0F1A
+            stream[448..511] = 13D511737F3A092643E94E74F6C76241
+                               0007158FEF40C63B33E10360FFB3B152
+                               8BD8B33093D722BDCAC1FA99D16D1C27
+                               6E59E428601F256542BD3E7A4A135152
+                  xor-digest = 1D1352487AB5081A28DF23B1B19D5ED1
+                               192F08964E4C0F048AFA9CAA8BF17185
+                               D7B97AD6003E2FD2DCCAD492FF3FBE5A
+                               5CD7AAC627DFE7CC6D0972D423B67128
+
+Set 5, vector# 54:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000002000000000000000000
+               stream[0..63] = ECA0F29C3F5C4D62ACBD601C3042673F
+                               6F8B17C946FE8FEEEB0089059765F067
+                               5AF3E5DADF6DECDA20F72AF486E7E967
+                               40B2DBF22B57FCCDFE571B2D8989C95B
+            stream[192..255] = D2BDF6ED912478A3C53713389C9DFA5A
+                               9272D030543295E8CF6F0929F1A56041
+                               EA22BD04E0DD810F43D9D28D94254F04
+                               F73DFF3B766DB55100EFC9697FA844C7
+            stream[256..319] = C7CE1CD4D8C42FA36724A49107A78630
+                               A60E15673A42C57B609740EC8DE78EE0
+                               B48F2644DC0DD1E80FB8326DDBCC7191
+                               5E6C8DEEFCCB1FBE1456532840A89DB6
+            stream[448..511] = 337650A0B03D30C9697CE85449B0F995
+                               668FB2B73E37E1A550E07632F9F5AA3B
+                               04D61AC41F8A830299FB8F70FAA0419A
+                               42C4589D71C965DDB3A9D000667616AA
+                  xor-digest = 7A26C50BA37BD9F38281FD2DA3CC14F2
+                               E1FFEEC9D7776E87D99053B531EEF792
+                               0C0BF834EA9A0065AF38422A40A31BEF
+                               AFAA17AD565F685BD6E505C7E02FB895
+
+Set 5, vector# 63:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000010000000000000000
+               stream[0..63] = 567919917583CE03DBDA69907CBAE562
+                               107FBBABB4DFC81A3A15438C94AC0C28
+                               8CC35A91DED9A79ADF4EF2670A55699C
+                               000994EF33674B578F5D77928A43416F
+            stream[192..255] = 13D0EC5B7302C0D8AB329E7AADFC3FDE
+                               1D24A80B751948C4BCEF516D94DF7AB2
+                               2B1D9E076BBFE367CBED341B2A5A3BA2
+                               D48735F83855460F9D9953279BFC2AA8
+            stream[256..319] = 5EFFE922E2FE25410E8050A973C3FAE2
+                               EE372E9686B6E7B35294B52A579CDB43
+                               9D5CA7F1EABFEB4303DFD7DFBCC812DB
+                               9D70CD0698D1ED051E1E32C855EB39EE
+            stream[448..511] = 91A01C0EF63716515DB8B71273CA4399
+                               1654AAEF2AFD4DEF25E21A08D5385766
+                               D8C29514065FFF00B07DCB32D1A20830
+                               3C3402963EF252A4CAF5CA31A50BE591
+                  xor-digest = 9232F83FB054098FBED8474939476CEA
+                               5E9FC269E7B248E56B14F56CB396BE74
+                               C2B2203D1802D9515EEE232FD612FE21
+                               11C291A46A89D54B2E5437E643239636
+
+Set 5, vector# 72:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000080000000000000
+               stream[0..63] = 507958BFA08EB41F4D18F519E36FC476
+                               5BB8DC6CFCA36290CE9AB8B165D7AF72
+                               CBF49DCF8BA2D145D7935EDD2CD2242A
+                               7B7FCCB85B4C8625532D84B4BC602515
+            stream[192..255] = B2B06A7C3977D4A1A39892E832A32A55
+                               3EE6E52DB24DC453835893A55D0FF3A2
+                               949B8B96688237E13DBBB2D0C9038AFE
+                               8B9D18CCAF62019ACB908499D292F280
+            stream[256..319] = 1D28AADF7B262A1EEEC11D39F4325CAA
+                               6181F9FA1A6C65F3BEF4F1614B0DF599
+                               EC92E5B6B42A931352965CFFC025F68F
+                               DB2D6D0181F259F12989E5FB23ADAE8E
+            stream[448..511] = F60E3DAD5004E31F6DC89292ECF517F1
+                               CD18AF7E79E775334F4644A09346AAF0
+                               F2B4F5C1DD03555A6D27C43AE53EA7BC
+                               7167F793190071C7AB7B5330A6C6CAD0
+                  xor-digest = 5A65D44021E67626E62FE87B8547210E
+                               F736490C0D51485A8EF0E1CCBB512DC6
+                               0FC18114A29AF923EE3E85655771D6C0
+                               7CFE342A52190C540BE3409853F12065
+
+Set 5, vector# 81:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000400000000000
+               stream[0..63] = 2416B634134170CB4F67F431BC94612B
+                               5F2F72545DAED2356081C91A26554614
+                               5FF2526D8D8FC7D02D8BCDD9AE03187A
+                               9E404C360E115CE949667987AC73624F
+            stream[192..255] = 4D456233EC7E761891A56BF9F9659533
+                               22375C169D7F16DD81D8D69B12092F47
+                               09703B85AA3184827935B60C1E5987A3
+                               C4C2EDFEAD4F777B53989C469B575EB4
+            stream[256..319] = 5F9CDDCBE09CD759B346AAADA2436887
+                               0D47BD8859CB9225B61AD9F99197FB14
+                               B5D625F5DBE0955DCBAA5B874A7C89C0
+                               07BF926AEE571CCD7E20635ED4FF312C
+            stream[448..511] = 642391D8851A9BDBDCA37B9587D5D0A4
+                               877EDEC31D6EB78AA3F1E068B0ECE877
+                               D83EA29906D0C0816EDF7EC5BB417A3E
+                               F3DDAA2145CB37CEEAF8C07DDEE0AAD9
+                  xor-digest = DF93E4E01EA55D18AB8AB1A927A5B5AE
+                               9ACB871B7493DC283581262771852013
+                               EE54288580A03B3991126BE8BC20C5D2
+                               230F00D8216CFB632271750F4FD2595A
+
+Set 5, vector# 90:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000002000000000
+               stream[0..63] = 4981C83E26859DEDB32D84C7BE32830E
+                               784376A12FA6D0077D4CB47ECBA08A92
+                               C841D45D6CDAA3F1FB48C6FE747B0F67
+                               1B32C2B35BE69497737FE4B98770DEE9
+            stream[192..255] = 1FA51FFD0360615EFEB03042AE8E4210
+                               D3D38B4EF07536BAFE43C0585818F012
+                               8F8B3F8CA8DADBDF049688253066C74B
+                               01849C5BD85DCE27C0138D24E8B8B198
+            stream[256..319] = 2D8C58008EE94CFEA1EC545C26466D39
+                               D7BFD5B226E32F1270B5BD3677818B7E
+                               CFD98BDEA26488248B10418C1F854159
+                               8F42C6CC237885A1DEAC5C33F22C27CD
+            stream[448..511] = 94502058B5828AE4F4CDC0516E5B5143
+                               1F07EE1ECAD7CA266C931327BE6BF1B7
+                               A34810220CE00497D7BB9600FC524999
+                               CDEB6DDE8919B03064EB56B3766DAFCB
+                  xor-digest = 1DEDBE0B7B6099DCF285B3C30E91AA0F
+                               7859496E034A1EA1AAE3D3D13C2061C6
+                               0878E595B63D849B7DB77BE7E0C08157
+                               94232B645BE946E5D8278B14427172AD
+
+Set 5, vector# 99:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000010000000
+               stream[0..63] = B84C72BF69B601FB1804CE333C5A2C19
+                               25BC8A5877DF9E574295380611D03FD2
+                               46D2EBB58CC6E918F4DB1B1A0E39642B
+                               D6B39DC76764E18108497E4CC4394057
+            stream[192..255] = AA84DF8195B3F7564D0715517476085D
+                               1B40511A72340DFEAE5134C7BB8F39CE
+                               03E6EE15217986C7E4788453EF054027
+                               8CBF6336073092EF661C13C7EA8B4850
+            stream[256..319] = A7F0C413EE143F55C6356519AE620A9F
+                               4CEF8432C51E2677EB5D700CE333F314
+                               ACA374D86A8FD4A67BDC31C1B0DA2AB1
+                               B20E6DB91E7F85DC13E348314A4FC782
+            stream[448..511] = 3445E08F13D09A1AC09EEB65451F4504
+                               0AFFDE94F6C2667BC4D8FCBECD6C6565
+                               F09FD05EC660DD38307F856AACC95549
+                               AEBCF31B3FBE84FFB3261D7FEF7A3379
+                  xor-digest = 360199B22EB28401FB4F621E37800801
+                               FE69C809D83BE29A50FD1A476B6AAF02
+                               54B1F4B048CB6423182C390B8EDFF1FD
+                               9CE49C26727F0D68EB837C19F58F3F42
+
+Set 5, vector#108:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000080000
+               stream[0..63] = BC618F4A557E5B7CB75B3572FFC31CD8
+                               4DB96FD22E281C198DD33B5E9E419099
+                               BE30E84ED61C0EDEC04B1E16E06B40E2
+                               372E0EA1A48DC55BFBFBE3355B566AB9
+            stream[192..255] = 33372015C7E5749D98A92CC55CC22206
+                               90BEC9878D3CA0AC50765D0B4457CE50
+                               9BCE196BF0388599E692B99EA8169474
+                               546F10891A3FCE22DFF0AF9733C2A2EE
+            stream[256..319] = 382684F74B0F02F7B987D37F6BAD97F4
+                               20B4811FFC744CBB9F00C2855A609FC7
+                               7CD24D0137304B95217E25FF45AFA4CF
+                               28E4335D29DA392D26DBD341A44C082A
+            stream[448..511] = B0B2B619708435C5DB45FFADD2FE4449
+                               E603FA9785E1F521E364DEA0B127F72F
+                               6C8A956CAF2AC9ABCE9772ECC58D3E36
+                               2E758BDE3678D4F4C9804CAF11129BE4
+                  xor-digest = 80FC64E2441F6CA9C0F4C207007FD0E2
+                               5F1C0514D203A1B01A6EEFD1055CA355
+                               0174FAAD47ED0956A736A9404164ED85
+                               CBEB31F80561AAFC4ED8EDC9829D83A9
+
+Set 5, vector#117:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000400
+               stream[0..63] = 69FEF0D5DD7CFA6590821B6C12E239E3
+                               5DCDE7B218A66CF3C75ED278092A6228
+                               143EC00BC16DC2FDB8CD9DDBD802AB56
+                               A4011F6A8CF432F2D34657AB84DEFA4C
+            stream[192..255] = 312EBF427B3D22A22EE1F85D89E12AE7
+                               07160C9BBF4073E538171365290B499B
+                               8904B01801CC897FF09A520449A44D0D
+                               34622DB8477EF1E73DCF15417478FA03
+            stream[256..319] = 83CF222FDBEB77FFC6E282C1212D8D1E
+                               014865E9C1251FC07E901A41A50A3AF9
+                               F8E130394F621B739578C7E238866431
+                               10827799C75F08C47664B09B477F31A8
+            stream[448..511] = 4130A8F8015F082EE8712B6D61178CAE
+                               B1D3CF90AC2DB9F2D402F65E8395DE95
+                               DA0605E8540E553CFFBD029AD5BA8FB7
+                               5950C2FB29097E13ED4A1B1818E0D07D
+                  xor-digest = 21FA07F8AA2FBC12F5B2B14E034C2AB4
+                               54D7D8DA66EB0308D9AB024DBFA414B3
+                               38F36D188D33C71E888FFE1A6AC620CD
+                               55B33C1A146AB8FD275584589BD65606
+
+Set 5, vector#126:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000002
+               stream[0..63] = 0CF41A77C30118D0931FF3142132A627
+                               7A778D3BCF7466EFE56238B166A57043
+                               2DB3B222523330233F81836282A27B40
+                               F6823BD076D84DC3B831DD78828F0FD5
+            stream[192..255] = 38A0C28325566FBAEF5AB3D50D54F407
+                               91182DEF4FC945992AA0D62134451914
+                               F07F16E86E20DB119692966E6CD6165B
+                               79BE7CE6C45D1248F2E0432393BFA726
+            stream[256..319] = DE91DACF57B176EF6E59E485DF02A20E
+                               3A4EE5FF44B1AA3D7F36265221CC71EB
+                               FB9565AA4F269B7DBF3CB9631CCBAAA4
+                               BBBB6BFABB97E52954958D4E7A283F20
+            stream[448..511] = 8FFDC8CCBF864721D6C98E1896FA052D
+                               15141D9C3DFEB48AE91B2436C5C3D088
+                               931470CE951B66C38998F15CF23BED01
+                               F6D95D84150D482C0C289A8E5B2C7C10
+                  xor-digest = 03DA7ADC3E5931928D3FD89E1E0876AF
+                               9D4CE659175E671D6D80EEA78F241AB2
+                               86CE3C26DAE267D91DB556AE0CAA60E0
+                               2B481282E6470A7A161AC8E84C2311EB
+
+Test vectors -- set 6
+=====================
+
+Set 6, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 0D74DB42A91077DE45AC137AE148AF16
+               stream[0..63] = 425A5E6F68EC055F38383ADC5CA9C048
+                               D6455C56A5ACED215E22665185E497EB
+                               3A2F5C0D45057169965EA37FE19F5D83
+                               C95C4BEE11E8FA89545A38DD9D18AD6D
+        stream[65472..65535] = EFFA27F50B0B4C4AB3C7855CD5DD9EFD
+                               B61783161678C9728B9032C2CB09A0B2
+                               D2578C53BF3C3E67D382BC89D824D63B
+                               20E62F414E4AC36472A16F4992DF4496
+        stream[65536..65599] = 0111EEC218892B446FDFDBA9D0C734DF
+                               C209D35FA86C1BEAC0D266E5DC4B3243
+                               68B4263BA7A3517805D1501B36450FFA
+                               1544812EBC0B9DDED93F5D45C4D83FFC
+      stream[131008..131071] = D966650E1A27DF3CB71B1E64CD3E7EEC
+                               2D3EEEA2953E2FC5571B4380EA3BAEB5
+                               3F014B4EE071A426E4A518E1AF335BD3
+                               76309236760E0DF6184B3E34BF861458
+                  xor-digest = B234A4CB646B0C2792023EABCD3E974F
+                               1E5BF1D5DD8E07E5C11BCC47BF1F1DCD
+                               BFFA3605A37008813029BFC32D1EEC11
+                               FE775D9889560C847C79ABB5C7181E6D
+
+Set 6, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 167DE44BB21980E74EB51C83EA51B81F
+               stream[0..63] = 5C1C44F155CF8595D52D003B7CE6C584
+                               F04708B55E3A8B952379A4F03C6C5118
+                               E0848F52C846BEF459335EEF7033CF25
+                               AC643ED139A9383B9DE13A5652E2B754
+        stream[65472..65535] = C4710CE8066A43B7E7FFBC8190CA79ED
+                               5E14AEC2C153F83966322553D5D4824E
+                               782AA1C91400027395D74B3A39DA1925
+                               C6A757E36B48A8F1FFF12321602379CA
+        stream[65536..65599] = DF29C91A08AB080662764B01223C818B
+                               27DCB638FB2535DA034D325DF996F57A
+                               7F4C67BA94C72EA6C88112E575D55906
+                               3C900A87B205A8144FC1717D5ECEB77F
+      stream[131008..131071] = 63FD83511C8C39ED3968EEC5FD281279
+                               70626BB91625CEFA381AC48E166778DF
+                               63709701FDD99F4A547D8CD6F7324B29
+                               A9E0C025EA1BA007246941D3566D15F9
+                  xor-digest = 959850E75A99AA747502E7BA9D19D870
+                               5895593FCB7BFD7A7DD4FB218F17DC6A
+                               BC8B96520FE83F287429BE3B87D35D78
+                               C6F100D8A9561A149297CBC44306E5A4
+
+Set 6, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 1F86ED54BB2289F057BE258CF35AC128
+               stream[0..63] = 696FF80A8A547A2E215C6E0572821F70
+                               201A090460E7B36A48ED5CC976417DEC
+                               EE32E7102AC764805E4A1BED3DF7D786
+                               0B3BC625B121B5200629AB58799DC406
+        stream[65472..65535] = 7BF69658F0EA9905897C1460D30333D8
+                               DA83E3F1377FB75D015D927365C7316B
+                               307CD91A7167B87FB13DBD4739F88A20
+                               F7878C2A483A4FFE1AB4A60840EF3EEE
+        stream[65536..65599] = A55326496CDE23F447CA6A4D1BE0182F
+                               ABC30D61C7A9E655CD99273232CA6589
+                               FDDC8179038B720D5A12CB698FA50B28
+                               9E6CF476ECE2DE213F44F9F23E8AB4FF
+      stream[131008..131071] = FB47C745519AC58C91CA9081B1DB0CA2
+                               8662116EE04AC6C4171A4BD11572677E
+                               DA507990B45C145DD21A56E1FD8F7AE7
+                               1BC54AC550309631C12A80FBB27187C4
+                  xor-digest = 3B3E44A1154CA7C4B74A432D0427AA6B
+                               3B6D81FA45AB9D3A37CF075F57E62AFA
+                               15DCED3DB08B96F48A12B176ABF203D0
+                               922DACF266985DB9D52A9D4AA00614E2
+
+Set 6, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 288FF65DC42B92F960C72E95FC63CA31
+               stream[0..63] = 0A12311E99506D44616A24E124676D15
+                               D06BB6A73EDDA4E9767952E1FF698BEC
+                               593FF8E2422D80C9C55DD660C6622CA9
+                               86140571D0958C070E2A8929C24E5562
+        stream[65472..65535] = 6BF87D409915D407FDAA06FED0EDA87B
+                               8CC4F20760B7669009795EC87DFA6BB2
+                               9825706AA3ED93F4197B28587D042223
+                               7D1F6761D7F8D8F8B3E0421AE9EBB9BF
+        stream[65536..65599] = 290EBBC73FA33ED00E0BD9CCAE6ABDB5
+                               EB5E86C533BF3E69D24AE720D0FE30AB
+                               F92B57C1EBAEBE8DCD0DE7EBBA5E8CB6
+                               67669D286E0B8F8A3A53C3192D2DCE67
+      stream[131008..131071] = B6082022254F783C501C08370D8F5678
+                               CA2F08825D4F7D09BF0868CE44DB1F5F
+                               AE8D30C6380C3A20B1EEBD4083E58BC7
+                               A4EAEAA9D54117253784E4917C3A7039
+                  xor-digest = 2181364DEDEDCA0C6F51A4634490FD9E
+                               3E89D0D30AE94F5E75730E4B9E82FF68
+                               5D82723A59CA0879C6B80588AD312CDE
+                               18723B80828EA4914BEE062A68EFDCBA
+
+
+
+End of test vectors
diff --git a/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt
new file mode 100644
index 0000000..a4784ed
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_128K_256IV.txt
@@ -0,0 +1,2783 @@
+********************************************************************************
+*                          ECRYPT Stream Cipher Project                        *
+********************************************************************************
+
+Primitive Name: HC-256
+======================
+Profile: S3___
+Key size: 128 bits
+IV size: 256 bits
+
+Test vectors -- set 1
+=====================
+
+(stream is generated by encrypting 512 zero bytes)
+
+Set 1, vector#  0:
+                         key = 80000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F1B055D7BF34DE7E524D23B5556B743A
+                               EAF06AE9076FD2F48389039C4B24C38D
+                               DFC3AC63A148755FB3CF0CB8FB1EDEEA
+                               63CD484036FFAC3F5F99FC7A10335060
+            stream[192..255] = 2541F0EDA5633B4F47C6B74CDCC612AE
+                               CD27E46B2C8FC9036A09C6FFB5891168
+                               7A8FAEDC225E34C45B6E081EF5279FE7
+                               3271CED417549740EAEC6616C2B6A57F
+            stream[256..319] = 0C8C0567803E2537804BFA15742D3E08
+                               A29985688DF3D6B4C3044464C1D1F2CD
+                               4CBBC470C9A0FB05665CDED63C58E466
+                               896F80ACC020F134CB622487D40E0AF8
+            stream[448..511] = 1FD448C788A21BD30D4B6BC5D8AEF296
+                               2772940557B9434E0FAF636D576B0737
+                               1FF3AC12884BB431F396CF7C189D9AAE
+                               D42797128CE645FE841A4CAABA429324
+                  xor-digest = A3F66A36C20A496A0D4D537B6106662A
+                               DEB5AE1E35FD1486EAB6039F443E5D8A
+                               C6A2D4A2C2E2A9F335E2E468AD8BA51E
+                               550E41533332E6929EC18CE35BBF741A
+
+Set 1, vector#  9:
+                         key = 00400000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 9244D2B190FE8C4BD0E17247C4F1D282
+                               3FECA8DBE546637E34BCA99236D09F79
+                               5A8905A1E0FA94E6C51F7DC0C90FFAE1
+                               A8EBD4C99CC96FB3252DE0A0FB03F971
+            stream[192..255] = BC0ADD787A5EA52E28B45192399DDDE5
+                               CEC4E283181408E554FC714586FB641E
+                               B36F3727358BDD8223B5ADC9B9EF1044
+                               0F7CD97FCF2ABA75AA9972B277CD6656
+            stream[256..319] = C9F6315DA3CBAE23D32685C5549274E6
+                               9C17FB2E46746C5D3260FF2E00FB234A
+                               A460776CB0E7AC3AF0D297825C1796AC
+                               0B689DB219443BF4C0D4D19CD70A49E5
+            stream[448..511] = FBFDF6D40BF2DA0EBB04D52C117E9EBD
+                               6FEF88D39B8EF8B31082EE9B19D50219
+                               183DC962391FA4F602A2510BB476EF4A
+                               A44439F61D589933A1F3F633C96E56FA
+                  xor-digest = 49B435E6FA51A0AF8DC94CF1DE09F8D9
+                               AD76E08C061B54CCD62EF98ABE85969F
+                               3FC41DB934AF9DBC5F32748623639D3E
+                               B15124F13DA8B008CA5016ED61917563
+
+Set 1, vector# 18:
+                         key = 00002000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 9D74BE686C2DE8B207E8D82E49236A3D
+                               E86F5A7EE231B4239080FC9A55FA44ED
+                               7737FA7472B318A4F36FB788E863247F
+                               7067C20DCA632FF051789E9EB99CF409
+            stream[192..255] = 4876774DBB886B72E54EE8160D8BA8DF
+                               6DB032B2A9BA0B79CF82426CEADE421F
+                               EF5ABE9976E909DBADA0442FFC7BBA2B
+                               009F7240941F0C209853A514B0BE9062
+            stream[256..319] = F2499CCE5D3268F4C5515C365D2F4411
+                               B0AA99ED01E7D5328BF0672584AC65CB
+                               E47BCA14C3EB1F838ABDB7C611677BC3
+                               7382E84D05848B9838A166A42E96B016
+            stream[448..511] = C855EF5D1CC991D2DDC892AD8319E39B
+                               734E43E443F5910D03BB79CCEBE70569
+                               F92BBC63363943BEF88BFA5809B3759E
+                               6BA4ECA1FAAC572228458A229DD5BA06
+                  xor-digest = F125B88E0B5F143B836AFD7AC822E027
+                               FF44B736E32627D90FA05F3DB98576E1
+                               9EC41AAF9D61ADE2BF00E38CA4EC2A54
+                               49EE0655FEAE777D67EE127E8A5F8CD8
+
+Set 1, vector# 27:
+                         key = 00000010000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CC447BF1B5D138025BEA2B269E625C4A
+                               D4451F3851F04F118499040C6E564E38
+                               5C5FE17FA7AFAE9FA559CA4835AC1F40
+                               1C045AD439B400BB41984DFE7E4D4CC4
+            stream[192..255] = EEC14B65E027BC2A96E566BB89218A89
+                               31C4AE0BA5C444929EF852EF7E400AC5
+                               D8B3CFC62DEBBC2B20A7B32E350E3839
+                               2953B7839AACC06B2018280770F84B65
+            stream[256..319] = 8870B4F9A62B37A1929973D3975D7ED0
+                               505AA43002B14B55A541EAE00148651A
+                               111D6E5A1581F85FFBC2304783EBF5AC
+                               E924CD8111056B1069F13100DE15EB13
+            stream[448..511] = 1513F3B7A2458674CBA2B566F3AD6169
+                               2BA4EE30687A07AF2FD0D340D92384F5
+                               F5BFD9B8DF2F7098A209C280F6D5AEFF
+                               BC07D167720DB47B4B649C8593E6F40C
+                  xor-digest = FB5EE30BAE44FDFDF105796FB8A66F69
+                               64D502230C191FF9AAF5A4447533D02F
+                               05A3772B99F9FA2A075DBB8BA59D8D5F
+                               F819784D487C305280DF2F19EEA8BD47
+
+Set 1, vector# 36:
+                         key = 00000000080000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 831F1DAB278C6226785209C0AD34759B
+                               9F205B7BC6B987DD145B949336A8FA0E
+                               4550BC1737DAE7DD7D12E2C062BF9693
+                               F08C2FB808A1F0A5887A06B93D132BBC
+            stream[192..255] = 76631E9D4A673D09B9769251433D5EFF
+                               3114AA59E1A9B7E21B4123DE3E34FBF8
+                               4ED6E80EC29B4F75B53A63902C373EB3
+                               D644B8823789743CA407FFEBA4A1AA75
+            stream[256..319] = ABD84B2A5479CDBC5587FB9EEC5DC661
+                               5A3CC6136314F67AD2C96803E8E4BE92
+                               E33DC35F0DBF3C401AA5D7A9F46E54CA
+                               A7ECD68E561BC08E6A5B847A82777E4B
+            stream[448..511] = 9ED1D44510201727B2E92B55DBE06BA1
+                               46762AB34937364B2157292CE68B9D78
+                               3D3C3FFD1FDCA836E4C4FEC750B10668
+                               600C26AC05B4DED64F8CC2EAA0D22052
+                  xor-digest = 843D7B97B3316595111DCBDE3DC13DA4
+                               C14402936D68035CDAF9A1C168120B34
+                               0EBA1FC47E957C5F69F369B4C2ADC4AE
+                               37E743226D72A9F122EC8E00BCAAA126
+
+Set 1, vector# 45:
+                         key = 00000000000400000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = D2D629E84843638274ACB79FA257DD9C
+                               D48A08B823DC9F175CD92C5236B9D230
+                               5931FDEC5A8F531B1ADF30DE0527AD2D
+                               0D2B253D008913558E0FECCA7D7BEA4F
+            stream[192..255] = 6F9322E84D69CFD6A1E589283CD028D1
+                               E2A114B719FB2E18E732B97629313772
+                               CD2F2F8AF77EDB5B4360E4B679441346
+                               03C59E88C042713C3E403E5D93F9BBC2
+            stream[256..319] = EE7BED6C85B20E0A39C103D0B6949F4F
+                               5F6FE0DF2BCE315CCCEF6E537C488525
+                               BFC27FD249A6D36548C558153661861A
+                               78422A563166BBD0D72D6D7876FB4DB4
+            stream[448..511] = D2CFFCD4185EB1D8E15B629225B9C278
+                               6E7BFEACBFE29D7AF396B3D5917A8038
+                               7263018C7E98F49A1D5FA4B64B8E2AA0
+                               7192ADE0376388E8295AE5B54CC51389
+                  xor-digest = A26BEFF2FD72BE47175C1B6F3D749CEB
+                               0E3472FB0FD5E173DE66A5BB60357565
+                               505E3AA44A67651DCA75DFB6F0AFCFE3
+                               F4C89F064FC42D7C2953694B0CD47832
+
+Set 1, vector# 54:
+                         key = 00000000000002000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DD1649517BE76EFF747658F0ACF5D354
+                               2C7FFD52F09FF7DDDFBC48487450607B
+                               CB90ACC3406D0302E84450FC0BFEC660
+                               9BD44C7FFF670D69C9B19FA50C62EBE3
+            stream[192..255] = EEACF8ABD7D48E285A6658C255A6196B
+                               66B091773A9F81807A119DC24023D5C9
+                               041AF75F2C078C5246BC5F50B622A678
+                               64EB7A07DA6A8764437E20C7E1E0E579
+            stream[256..319] = BF55E777AC644A0938D438FA374360ED
+                               F842BECB027FA3A0F364B9150FFBEB47
+                               09FE2D2056A6CD5A7076172152484BEF
+                               A86EC7DDE657307580BC6F9ACEDA4C73
+            stream[448..511] = AB4CF968EC00E7F08553A10270A7D439
+                               68B0BC79C2DAE278AF1CB81FD516CCA6
+                               F5B8A47271FAAC3223F02DB4D0D5945F
+                               9C13A47906B03B80878CB0596D37CC47
+                  xor-digest = 76ADECA36B9401DDD5CBDEE821B70FD6
+                               65EB9CDB1E3F25C0BE90DEC49C03A9CF
+                               4049CD34F9550B28E0187B0AD47D86D4
+                               88DE4617EDB5F03C67FA2E7B9D20AA25
+
+Set 1, vector# 63:
+                         key = 00000000000000010000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C0CEF6E3CA9F0D523587FF47973FE896
+                               9FEB08773E3C694FBAC4804B37121B31
+                               06B99ECC2A08603EBA72EB3DC650E8F3
+                               462119F4685EF4CEA18D5765A6F22765
+            stream[192..255] = 79E92E248BA61D72C610876D3078F1CC
+                               CAD662F2423E7EECA813133136A64E54
+                               A1B6A151BECD2B815EAD959DE8E8DC62
+                               8F388D366103296A058CF60F525D6467
+            stream[256..319] = 03BD62A0892D939C1C28C4EB490F87B2
+                               527536AD6790AAA6C3CC50013E2BB883
+                               5710EAB7916FD89896B7983B326AE271
+                               AF9ECF975CDBBB968D076685BAA3343D
+            stream[448..511] = 98762E306A2B9D488FFB671D3975551E
+                               A06A6CFC5DB719B888E3164387EC922F
+                               12BC31A8DCAB8AC0CD6E12212CDA3B13
+                               4CF7F870221D6CDAC2B222AF4FD93DEE
+                  xor-digest = 606FA49585621E34BCC3748C06B51FE5
+                               A8AF320BFB83A4D1D3AEC6373519B28F
+                               2048A975732BA8DEBDFC5F85B84E7C3A
+                               EC0FCC9B1FA9EBB9D79D6B18BA2D70B7
+
+Set 1, vector# 72:
+                         key = 00000000000000000080000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 33A81D48866B04388451BC2730A2980B
+                               5F5BE248369911340E6C024A1F94D4FE
+                               ACFB246F7C0B9E27A40772D68DB36DE1
+                               7E87AEF19C8A68854A46B3F654E0AEC8
+            stream[192..255] = F67C60413B25FF7CB8647D1E9C361696
+                               3B23ECE23A9DBFEC644E855AEC5212F2
+                               D336E6F074EEC8FF5F8D4FC6398AEB9D
+                               BCAF6C29FDFE6E69A03D906C527FB0B5
+            stream[256..319] = 263D512137BAB758F646C71058D02B20
+                               3920965D84E52A99B50FFE79305E491C
+                               E0D61EF71F7A07937CEC8590B758F63E
+                               B3EB5890E8678F170C2E95B827FD8DDE
+            stream[448..511] = 023AD00A87D3D9441D4E8CB603F5CDDD
+                               AE8F3EBFEFB9C5435B72B9B8D03ACDF1
+                               E4A0FB796FF8401854998015905B878C
+                               99B3EDC7DD33A86AD4EA6AD208440C5D
+                  xor-digest = 5DAC8E3446BB3B0DCFB3F0A3A3E788C6
+                               07FA7436C63BF7AC9FAFCF4A231AFAC7
+                               75A3A810EA0FD4E5E6A5B8FE5D165A80
+                               798A9F58EE1AD27016E867D2E774507A
+
+Set 1, vector# 81:
+                         key = 00000000000000000000400000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B33EA681CA88C80EAD8F2D57C87EA42B
+                               742550FF8AD2B01BDF945BF160AF763B
+                               15D6B3BD92E6CF3E6A2B61A7D4BB94AC
+                               E3DAB365E4EA50EBFD2654E60CE849BE
+            stream[192..255] = E97318BDF61934188A94BCFB4441809D
+                               36C37D1A43BDBB3EB06FFE143B6153FE
+                               C8453A13387923F434CFC7AAF8CBA097
+                               7D796DE95EEFED3B2126B611F477619F
+            stream[256..319] = 4183971367E71731111D2212520306E1
+                               1CBEB05BE6FDB338414C826A8E359C7E
+                               CC680F317C12C6EDE6B443E68B4767AB
+                               4190E95E1AE4E4FFE61707BE742775C1
+            stream[448..511] = 56841724B7D7F95809456EDC1D3A532F
+                               E1C6BA252017DA90EEC71FEE9A639A89
+                               4CB7E1575494BC8B44FE4C5DAF90FF4C
+                               A32E03D6399BCB3D9D25B62764A4977D
+                  xor-digest = 3E80587D70A53AFFB96A62F6493B9BE0
+                               1C25339CBFF7784F5100A7922EE3E6B9
+                               9D17B026C0EE69C5383F63E0E5AEE9DB
+                               5814E2C526192AEFE17004AAA1996280
+
+Set 1, vector# 90:
+                         key = 00000000000000000000002000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 51A7510726D12FE9574095633A3710E6
+                               3EB8196622BC808B8A18800E208648C9
+                               F7031F8171B71F37613753A5E49B37C1
+                               CBC7933A52CAD48601E91CA198EC19EB
+            stream[192..255] = 286EF1C4F74C993A7D783E86527CDFE5
+                               213CE4DF7EC72544685291D8108C7621
+                               50D488AEF761D819781814F4501553CC
+                               B45EDDA85828C33C4D0608169AD20B2A
+            stream[256..319] = 89DF5C916612EF0ACC1035EB75752239
+                               ADE08E0D63B622EA52CC997DC8178C4C
+                               4E57951FC8C6659A225E88502742B888
+                               1F300FC9F278AA3D9C1063A83CF33C44
+            stream[448..511] = B2DE3AE2941AFBDB21D80ABB0EB852D3
+                               A076D98C696F886C302D96D6AD226CA3
+                               7B3213B3E641632B728A0AC7131B74FE
+                               F733D1B18666D36A02C148FC98AD2E89
+                  xor-digest = 01090125BA6C43AAA3910B650D046F37
+                               E04896E9D2BC276D969A10C1B26FAD48
+                               8A2CA5E59044ADDF698588A561557669
+                               A4EF25E1BB85C0A9D63F69FBB2924F83
+
+Set 1, vector# 99:
+                         key = 00000000000000000000000010000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 545E2C75365948B40FFF042EB6919907
+                               6E63EE636CB343C51AF6C17BA24E1BF5
+                               C045B0893B8CBDF6A4068F8574513676
+                               80000B10BA11666A546D8DC75374F5BB
+            stream[192..255] = 9805DCB5596FADF01224553F3A8DCC5C
+                               909D1A5EC2C29BA0DB86A46ABF70BAF4
+                               4A171739309A923428EA7BA8EFCA5CB0
+                               B0B8A5EFE9A4A39BE0EA6CEA782DD862
+            stream[256..319] = 531EE320A584EE1E4E0701400F86DC29
+                               69531C2BB1BC922CFA9E0919A05B84C2
+                               46495A7C358015724B62A986220DFA17
+                               6BF39FE4263A9D27D93F3737CC1D5C59
+            stream[448..511] = 92CC0D63772783AF62E642A5849CE7AF
+                               4D21EC815D644F88887242F4F5F7E1DC
+                               55E241D72691ED50D59CB3E2FE68A856
+                               7696F8B8E3099642D70EC3945B8BA656
+                  xor-digest = 855CFA62E449250845472BCE9453BA45
+                               F91601ABA6BB715B079D407E05D94CF5
+                               93B5A1E2C12C04C78AB719339AFC11C5
+                               213E17ED9DC2B0B9CCF751E0613D4F2C
+
+Set 1, vector#108:
+                         key = 00000000000000000000000000080000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F9748DADA2741A7CA30EFA167ED09978
+                               71619682AB68CB400A74BFD642180CC7
+                               F3499CE2CC86AB7727786DD01AB8D08E
+                               8774C5A3CFB4738FF1E3243DECF720FD
+            stream[192..255] = 5AA20B305F5D6363180CDCD4E16427E7
+                               2E3DFD73D2C4E2498008F6E0FA9CE3BB
+                               D751F6EB8DD5F48EB42B994688601E3D
+                               2CEB3DE19BF16C4BD7FD4B331FC93473
+            stream[256..319] = 81E3D9BB421CB09A9139534C6E430668
+                               FCFCB87E48CFA085D4FA1AB316CD5AB6
+                               35294E434852C1509C1023A85B26622C
+                               68BE19944CA3233A4D3272710A791E3D
+            stream[448..511] = A499D228204BC22C32047DF550E2CCC0
+                               260ECB7BA32E8F5CBA2C1D9A09D1F38D
+                               FB30815BA3C9A8D3243CFE7AC4A14B1A
+                               D6AA67D3EC0A5CB617FAD57E41A2A0DF
+                  xor-digest = 0324B7F1BD990F8DBF19C021CCDF741A
+                               1B4A9C3C3940CC59CD715F0B2CC31C08
+                               82E5B93721AC98B00F7B45FCCF19FFA9
+                               782B7D7FC048F0756A29B066B472B394
+
+Set 1, vector#117:
+                         key = 00000000000000000000000000000400
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 7EA95775329E2D1163E30F429FECAEF4
+                               CA177BB4D3C4D1AEFA6B5A01904266F7
+                               7D7B7243B9DB1490245EC05129CA2DBE
+                               E3A98885DAD0B43B0E725DDA39B444EB
+            stream[192..255] = 78ED15A7B4A8151F384C740B844115CF
+                               D4FA31F9BC16E22158B0F896E70C0F73
+                               F74AA5EF024F6B386ED71239CBD57996
+                               4583C37104AD8C7E5C812C378AF00F98
+            stream[256..319] = 292FF21E49659AF99AB21753BA2A2B28
+                               25DDB156D4F7AFC1888FBE8376AE4C6B
+                               905D5916121E9F9D76C83FB146ADA735
+                               2AAAB6E89CE9398C484D69D1A33F0C97
+            stream[448..511] = A50FF5FC20C57F8297C9CE2599A3E6CE
+                               3193746E8C45FD9AECA0C5A0FB3BF70F
+                               5981B5BA8D2FA57677EF65B535FC3E65
+                               405BECF0A508445E36A7B6DE2BB56106
+                  xor-digest = D9650FA5D128620134828E1C99D9678C
+                               CFD5BDFADC46A5E79D47AC5967B8A1CF
+                               32F7DB65B949C88CCEE0D96D960A110E
+                               FF1D09EF5549B88D5B53ED46D4C2F296
+
+Set 1, vector#126:
+                         key = 00000000000000000000000000000002
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 25874CF64ABA4536844F815F486F9DEF
+                               927E325CFF2FAC48134A4D30824C5BF1
+                               EC75F8FEFC624AFCC717BF2C8EAAE374
+                               0AF399C2653389DBE31F9FF5D451D362
+            stream[192..255] = B151A1EDCCB8B4A3CA9BC98F19EFE637
+                               BE2D6A97A8F794091E7FFF06E7B4E574
+                               46B81E8C787BB77E461592160C44B5AB
+                               49329142D01A1CD5CFC6681F93DF1E33
+            stream[256..319] = 29B2B0C04E07D33EC3146E60AA305F0C
+                               2288913B55DDC18FC17EE836B39193DB
+                               87089DF2BAC4185A57E910331864E25B
+                               540BBC968099900F7BF18645A28A419B
+            stream[448..511] = 286FCC98B40EA26BFCBE5CDEE52B30F5
+                               810CFB26E756C628B56B3B5ACDA49E07
+                               192592CA2241C6C5193221EDA36CB0E7
+                               B5C3132F08087DF0673D3101FC559962
+                  xor-digest = DBF1D7E0AC062FE6BA9834F0AE41ABA2
+                               B28B41FDFEF914F070007B0A48EE9D9F
+                               E69DB8395BECDBA7B545201318177A49
+                               7D343A317B5A37A9DF98DD25C84DF948
+
+Test vectors -- set 2
+=====================
+
+Set 2, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951
+                               53F06534801F89F24E74248B720B4818
+                               CD9227ECEBCF4DBF8DBF6977E4AE14FA
+                               E8504C7BC8A9F3EA6C0106F5327E6981
+            stream[192..255] = 30DA9453A90909A5675D6B691CB0990F
+                               C423CDD8222EB47245BBB67BCA2B9C10
+                               8D1F016DF0CF8CEAF6829910916DBC1E
+                               113D11E91BEC3D85C47E3042EC865658
+            stream[256..319] = CAFED71B892EDBE13388CEF6A3365797
+                               E0D88C0D3A5B91BE4CBAF5162F69558F
+                               DBB45CA6F8C8D4C371D62736EC244584
+                               60131F54854F3EC804AA9A38E6ADE281
+            stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F
+                               2C3EA0F56AF46ED93DFAA4E16F5F0831
+                               2D77BD0E9122043CD6A202CBA9351F6A
+                               0E8E6263F4017355136A0C551E6FD0F8
+                  xor-digest = 023D719F61C193E4CCD87755C87F9604
+                               C5A29DD7E31637B3DD70D43441D48CC7
+                               D474013C85EEAB1897C80ED0A0272543
+                               F951C72E3954616CB5D6B51FC24F4B0F
+
+Set 2, vector#  9:
+                         key = 09090909090909090909090909090909
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081
+                               2145B56AEA46EB283A25A4C9E3D8BEB4
+                               821B418F06F2B9DCDF1A85AB8C02CD14
+                               62E1BBCAEC9AB0E99AA6AFF918BA627C
+            stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58
+                               11FA9BB02CECF7440239FBB0497347EF
+                               D8F1A8AA71AFC70ECCD64E81388E6E87
+                               9521C2B47AD84F9CFD9E240D8D2F3001
+            stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD
+                               3C8D6A2EFDAA9CC11BFCC61D94F6104A
+                               4091B3634FA57AB0AB9B209F22DA5529
+                               75C3C322DEBE4AE68623BFE1B2BB7F0A
+            stream[448..511] = 35B290F85EBA78A978750690C4747E8F
+                               72621951483772E8B89876CC5D55F3AB
+                               02D9B8FB35C741279FF9B5B571B26329
+                               4D011F813CB5B209CA1A22D532BF09B7
+                  xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34
+                               F6CD0A795B8347E1441CEBEE35540D41
+                               64FC2B95D71FD47A2C4ADF732261EE52
+                               8125BE374FA4A90132CC1063971A2862
+
+Set 2, vector# 18:
+                         key = 12121212121212121212121212121212
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD
+                               BD8853C329B3A881B489090853FE0F43
+                               89DA105F0ADFA9CF51DA2521C40FD2B8
+                               FB0BF80B93E3F2B3D8A8EB1C615E0FA6
+            stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D
+                               43A82A80DAEDBF29C048639BA38B690B
+                               7ED11323E3C0A8E77A16356705431EC9
+                               9F2CB7F7E1ED3B83EAF2CAEC00B00755
+            stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417
+                               376F334E6AEF9C187012C8AD2B94BE7C
+                               00A876756EB232510FD0798E72EEC87F
+                               75EC1467C07B3A1EFB0D51A5FA65E382
+            stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B
+                               AAFD131432CFD7D2F675E03320395313
+                               AD4ED96E9052FE6B2D2A17428660A25E
+                               EE642B712800BE3F7E44F21A1E6A03AC
+                  xor-digest = EF4E84DBD66497B142EEAC56B830FF78
+                               0465CEE20B9CFAF5727D4B3A588F4D00
+                               AAF718330CFF35508C44C1ADB8476625
+                               2CC3AA6AAAE74F8BF1DDB6D4AADA425E
+
+Set 2, vector# 27:
+                         key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676
+                               263C1CB9AB941119B19D15EBA3462F56
+                               2F69220595DE5E0E7C595FA40F1F06B2
+                               6EC32252AF05310809DDDFAE2E24B170
+            stream[192..255] = B29A740B51B4EA1080666337D5551484
+                               FFED6860A5125DC0573C8F90F23A98E0
+                               BA7B3E4C28C2CEFB1C33D2C36D1B7625
+                               64B9A67240CF174347A4C8D868F00F6F
+            stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6
+                               537C06AFB23354F054E25457B729B534
+                               CD10B2ABD45BE3E38DAF1B7A9103268F
+                               4FDB4C0FC9A80A003FCB907E8F249AE0
+            stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39
+                               F62D54311207B617B727FCCE1B2E762A
+                               060810C4DEF672E7D76083E3E4BED0D1
+                               0BAFD27CDFD2C937E660190D36B3FD7B
+                  xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C
+                               18CC5E1E3F6A317ED7257887446EF734
+                               65CA15F51AF5E077B7915062391D8497
+                               8F437985DD08F5FA3A8D74B3227A6EEF
+
+Set 2, vector# 36:
+                         key = 24242424242424242424242424242424
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C845BA29D542FBED2D021C85188E119F
+                               D34967B79D9F44635DD45D2E41DC5AFB
+                               B237AD2FA0E4CF4202D83DF3073C578D
+                               2AA8A32D30FB45DE28F23CEB85E50FBF
+            stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297
+                               FD12081B4B23F0A32CE5B3196173C7CA
+                               7EDD03F9637E08CA501C4850C15B207D
+                               7AA724377396CED2357B572BBF9E69AA
+            stream[256..319] = E484AF567EF80BAE77461855294E9280
+                               EF57E7366605785034D639D6DE3EBB0D
+                               E21886D0E1E0679BC2E2C9C2D9201484
+                               4A452B6AD3F1AC8B7762FF3C0E405B3B
+            stream[448..511] = 595D9855200786BB575FF7977509F395
+                               7879CA1F19619A99174BF013CB62F85B
+                               FF2C3C4FE724E26DD0C10D7635A2491A
+                               9E7E868D9DAD9201465AA178184D06AC
+                  xor-digest = 08737B82505F46F4FF282EF42F387AA8
+                               0450058F5314389BB73733BC163D75D5
+                               D32FC6408F8DE5F6ED2050027D605FAC
+                               A7119FC2DC1B6D3E84E8048DCC42FBD2
+
+Set 2, vector# 45:
+                         key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E
+                               6E6320101999BCE5550C2BBC9BC65D91
+                               FAA2D72FA4BF46B6EE916244048B1D09
+                               A115E3AB6C00BAC8EE382B58859E8157
+            stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82
+                               0C18B867C561E96DF4ADADC5A4375E44
+                               5A34F9457E5F8C9A337A0C88DF0F723A
+                               D4509F1449DF2C6AEC0EADF4C7A8139A
+            stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8
+                               452A1A893EF034C51750388D294947EE
+                               3F505839C69C1708E8323C449C39A96B
+                               FC9EC91B0E1CAA8112057EB0389FDFD2
+            stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC
+                               EDD92C4461EFBA5CF1664B9AF54857BE
+                               C3D00319E5E8A89A8322831151EE1D52
+                               D8585AC79CB60B61ED2C852D04BB0FB1
+                  xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D
+                               2363BC12259B0FDB2BD8F052A572ECA8
+                               D1EF62AA9A48497805A413742B5AF5A2
+                               6DC9FF624B49E5D6FE58BBE5251B4983
+
+Set 2, vector# 54:
+                         key = 36363636363636363636363636363636
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340
+                               42D4F07DA4D5EB05554CB7426D65C5EC
+                               A93C2D321175B6F72FCBEBA6E38CB098
+                               B72534F7D534B1AADD97B77E8513B482
+            stream[192..255] = B2466A173F436C8433F264CBF125B8E4
+                               C10BC81BD46B5C21FA161CB2AE07D27B
+                               F66812A2C2FCB2B14C23E413CEF4E591
+                               AD52EF810A000B42E5C1B76EEBB17739
+            stream[256..319] = ECBED2058DC50223614EB8635B834C3B
+                               B176719C18CA5E3D087A93E5CDF81123
+                               C6FB819CCAFB5042AADFED5E3C33116A
+                               FD92AA21031165A22F4751C423B8B945
+            stream[448..511] = 758BD9435DE607867DA256064C304C8E
+                               DDDF5B64173CF2C98B2842992F8C5FE1
+                               A37C3227B7F37D49A39F9FF929A883FD
+                               56DB8B1A174E1E55FCB21C9E1164C20B
+                  xor-digest = 31761A49503946701D35306FBCBE10E2
+                               02967E7EC14A328B4DB19FE79F03553F
+                               13A012B7297B2D02F18A216AD24A682B
+                               299518C3769123EE86A4937DAA9FC39B
+
+Set 2, vector# 63:
+                         key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B
+                               26A4E7E34C0CA9CB9399F655E566383E
+                               246143F57776C8E08951E87F76091FE7
+                               2356CC901F09A07895A890AECF047B3F
+            stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF
+                               C862100A07E55FB449BCFA2D9BD48658
+                               958B37B3EA3565FA66824102A14B5770
+                               5E3914E0680E116ED58212CBF61028E3
+            stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701
+                               057710F24C01E680F58090B8E949AF01
+                               8970A43A698A04C0C8639FAA665DA3AA
+                               562B2C5C3A03BCC38FE75DC1821ED718
+            stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948
+                               821FBB049DAD15B988A77C0247868A38
+                               2056B66F47B0195FA30C9DB5A2334A9D
+                               CD7C0D22E479FAE1BBCDFFE60F261C7F
+                  xor-digest = 94D41CCAD940CED3C854DA0796DC62E5
+                               6B566A980E34F353CFFD0F53AE9E34FF
+                               A6A057645FE66D86BE30F93805D9E2B5
+                               D78C68EEBF61CE387277A51EB2EF835B
+
+Set 2, vector# 72:
+                         key = 48484848484848484848484848484848
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E45194379659D1D8904DB3698AF8B245
+                               762910B7FBD019AD1AA20A6C433B4C80
+                               308A9EA68697631646BF3A2107C4E7FE
+                               2235E8F3262A9DFD3F5CC23FEB0B2DAB
+            stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA
+                               4E947598C4757976F6F61DA5F0DAC8BC
+                               DDF72F08BA2F446FA37F9A490F6A2B6D
+                               79227C93271D6B763DA7B2A907220A42
+            stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74
+                               A43D83AB8ECBAC5206D108F869561D70
+                               F151A0037F8E28951B5026643F8B2D6D
+                               56A62E259F04A5EA304791A9468E66AF
+            stream[448..511] = F70794C084E6EDC07BA0347413B05FC9
+                               FC46994CA820CE4FC037ADBA50EAA9AD
+                               55064ACB7308CFCE3F35AD5C7C628362
+                               F4210FBC2D3264F734728626BABF5356
+                  xor-digest = 31815B36BA034BB1941DB1E45A941A59
+                               7C3882F34BD3BF441CAE8A9790B05BCA
+                               72049FD10C09A14AC9DB867A82C38A5F
+                               524C72F783DFD16980DBCDEB486FAE96
+
+Set 2, vector# 81:
+                         key = 51515151515151515151515151515151
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6
+                               FF53889A9979ABA8F23AA51DB1EDB8E9
+                               D08F696C1100799A7D004DEF1CA94110
+                               FCF0C054B0C131E6FAE0FE2F2DBF22B3
+            stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC
+                               55A5F3F19C5A10E12EBE46DD84F10385
+                               33837693588D584FDAF86E3A217C3CFF
+                               020278736F1A90CE07F0DCE4329005B9
+            stream[256..319] = 135FAD68B5282FE59B28D2DF66463632
+                               06CA92E84A73FA131EDDCE89A5C23B4D
+                               08FA57D455BDB32F8ED58DAF3EF288A2
+                               7C72020E35DAE19B446E4C52DCDAC5B1
+            stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D
+                               18F2111002891D3229102D72605B9BEE
+                               F5DA36059B0DBBA7646927650305431B
+                               FDA4A97570CD0C484BF1E974B157ED7F
+                  xor-digest = 5125E77698C0DAA89A7E47DC5D038D40
+                               7B732CE56CEB674CE653A1B6661B2740
+                               0C092AFF83BEEE4FC4543B9D725C9387
+                               2F89AA338222ED677BF59397200AB304
+
+Set 2, vector# 90:
+                         key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21
+                               75E9AD91482965B651B495AEE819CC6E
+                               C42AFE2C20EEACCEC4E90710D17210E0
+                               4CC6832905985322C8007F872D3E58E1
+            stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560
+                               D692A020F0A66F609374ABDCD1343722
+                               05F19CA04EBDD3009844BC540C1B2B41
+                               66D45E8A2E822B906DA34649E7FEEBB3
+            stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF
+                               CE2CFE99506677A956AEC86BD290B6AF
+                               C5298A448D0DEFA99AA5CD26D318982F
+                               E786D809C713D5A55B42CA6650191DDC
+            stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225
+                               EF6E3C21705EC9FB24873916A2C24668
+                               963C03FE097DA8224A42A99E5DFFDC17
+                               68CF518DE49CCAC8A70216C62C9CBA6D
+                  xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5
+                               5FF58B296071D5D39349A531E41F0BA9
+                               893A1722B6102740BC5FE394A49363B9
+                               6A626AB43FD6A288CD9B23F7255279F8
+
+Set 2, vector# 99:
+                         key = 63636363636363636363636363636363
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333
+                               BCB02E3AD8797377AE1F1B4D6DDB86E6
+                               2A59791CB553550E0492FAB42C7A2C42
+                               3157C5092D2DD37D46589F17FBD86584
+            stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91
+                               4122EEE5736BCD12061C77DF5B0122B5
+                               1784E946B4E93470170ACDD7E2779591
+                               57BCC9B9F3E11E88BC2F740AA0C10C97
+            stream[256..319] = FF22D8196AB3DF662210D12D0FE79255
+                               6DCD39611C07F089979CF7D693A30CA3
+                               5B795B7F6D64931916E717C8BFB92114
+                               DB75118BDB51D142CE8133415C6B3456
+            stream[448..511] = 971F007EFE17662D95F47F4F28266516
+                               B22A1E50755EEF19149DE3A3121F5FEC
+                               E0D9DFE7A055026CA44193542D7687EC
+                               695B97769BF02F92C1EF3D904A8010C6
+                  xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163
+                               C8D54A4CA36748C74721C7B6E1649A31
+                               4B5B7A4BD43E7C3D2A22F0C8446C7892
+                               90D54D421D37CB16400E59CC86215CC8
+
+Set 2, vector#108:
+                         key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6
+                               54BC11ECF0010D2AEB9F899130F4AC2A
+                               38EBC15C8831D591E6675DC1CE7A471C
+                               4B869FE83CBF37AC70BAAE5D4AC607F9
+            stream[192..255] = 518F298A6008532EEFECB3DCF72103BD
+                               5E3F84FEB6EA2311E8C19A2E93A9C3C3
+                               BB1DA7DBA78D5618D1C4FA5B0B202728
+                               62645A361E55494D66C9359E41E5809B
+            stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A
+                               89BB20CCD92E7F13FDD816DD4E4963C2
+                               C5FC2570CBB8BB5C70848B73001F508F
+                               47AF179528200F51CDC6E4854EAA63C3
+            stream[448..511] = 844B1D15FBFD1264169279ACD525611F
+                               A39C7BB41F1E7A1C09090625F7926E51
+                               23A4CD7FE1A3F37ADC67AC437BF0A5AE
+                               FFFC6FB0ABF39D9908145004AA5B958D
+                  xor-digest = EC67596C9DEF4012A2D543842829306A
+                               4285A3B8038818F265065DC848BD80FE
+                               C27C2F66A57B27F7FA8AC912001EC954
+                               05BC6E93D7E555C59060F5D2E294D103
+
+Set 2, vector#117:
+                         key = 75757575757575757575757575757575
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 91D2772A18995DB3C0801DD3740F4466
+                               F9535E5BECB93DDCA0E94D19C0B57BDD
+                               0FFBA9DAF0B11D55C852927F8BA560EC
+                               4999E25848D08FCA7275E7E8571A5F1C
+            stream[192..255] = 72E64FF10CA9F07CC493715724DA7610
+                               9E4358E8B0CAE451348B784A162DF036
+                               AB9796724D17FDBF356031D080A6631C
+                               D1E8D217B041AD2EDF427972653206B2
+            stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3
+                               344956C29D10374E502C2EDD177ECE5E
+                               6625BAD9630DAD57976216CD69865058
+                               130B132FEC1AB0C350DF4DACE4C7724A
+            stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90
+                               E402466550B518A177CD05985D238827
+                               BD92EE7EC22C274F19E682F85ABDAD95
+                               D0EBB3DB6C6134408353C8B0472C9A1D
+                  xor-digest = 9A6C893F2108D13A29373DEDA65386C4
+                               AC356BDDD4A3178952F9126E322B7AE6
+                               83C94F1A131CBEAFF26549D9F84CF04A
+                               1241FA374B055B0ADE7E49E8EC669E65
+
+Set 2, vector#126:
+                         key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3
+                               059C5CC575D806B9029CCE3FA45A246E
+                               0EBD3AB2F2E324FE36ADC3B56AE2F7EF
+                               C710AA964CB87381386C2A88B1308035
+            stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E
+                               20BEB18D9C84187C347F43B17E0924F1
+                               2348F825E106E57A00258CE4415294D9
+                               4323A9812D8A71359CEC1001BAA0D567
+            stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5
+                               32D62E779FA0D2D08F8ABB6B0183A4DA
+                               4EE0329215F261D953150B9AB9FCBE2F
+                               568AAE361EAA8636ECC01A63F007977F
+            stream[448..511] = E7C44F44E06321A20E25F73E2069757C
+                               90499DB7E60025CF6D2D445E53A665F3
+                               08EC96F6FE73C0AC90D7E4A712E18C2D
+                               3DED46DFBAFA24C4B0B329E52C525976
+                  xor-digest = 22035341489FA6EEB2A6488CA42F4043
+                               57477C3F55569A1224EC39B1019E90C8
+                               21D37D78ED4DCEAF6EA70724C3751760
+                               38CF25DE4F84BABD80424D83A310881B
+
+Set 2, vector#135:
+                         key = 87878787878787878787878787878787
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191
+                               3C69F2275EB97A1402EDF16C6FBE19BE
+                               79D65360445BCB63676E6553B609A065
+                               0155C3B22DD1975AC0F3F65063A2E16E
+            stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB
+                               3373B816DA256CAAC37914B0C161E4E4
+                               5F5ADBE444098A5B2A4CFD4251D79918
+                               987BB834BB50F0834EF4985F356B92A2
+            stream[256..319] = D89642D25DF97D149AE07EA18BA39497
+                               8935978AC34C1DF9F444986D7505DB4C
+                               7E08DB3616B84CD52E7DD7FB108C36B8
+                               B50C2573172F4D3500B6D62A9D20B82A
+            stream[448..511] = A2C17FE7371604556F796429C6BE0688
+                               8611638B310F3E9FAF484BA9EE29C16D
+                               2F842EAF33AFEC557B68D2F453569187
+                               A6F4CD204A0E7A733E81AB7CE9FCAE81
+                  xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B
+                               6E3A61977A7C6AC2F033B826AB9A9957
+                               66671D2A1025CDF8E2824B2F58CB221D
+                               2A68679239D90152FF7D0D39B33FAB93
+
+Set 2, vector#144:
+                         key = 90909090909090909090909090909090
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6
+                               71A6D390BC7099A708D370DCD0E3D143
+                               A0334619EBD5C7DA9EF6301F29273F85
+                               2DFA3C580ED65C6E952F88A0B7FE368E
+            stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B
+                               445792061AA0539DA69ED0B77B970C0B
+                               482156A5DEE4082A61364BF06E692399
+                               FB9F4411FEC515291F8949B20F57229E
+            stream[256..319] = 993E815F299D4841518119BFF88F6EFB
+                               F3DB9BAE60238BDE2845DE4DBA6D79DB
+                               C9E42BA5C3C004AE4546FD86C660FFC8
+                               FD6A8A349669FFE3D9E5BDF8E50A407D
+            stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2
+                               1274F4A6D814B5440C74D53A3FF0735D
+                               EF01B14AE4188E215CE7337C04871688
+                               7159695A241BFB9D6B489FE9E23B2AD8
+                  xor-digest = 0BD5739ED28778023E6303FD88DAABC4
+                               0FA0A211A1A5C5F230D9E67DDD9EA517
+                               FEBCDF0BDBC107291B6CF3ACD8B862B8
+                               4BF15400493A54036E97FDEBB9A1DB2C
+
+Set 2, vector#153:
+                         key = 99999999999999999999999999999999
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC
+                               BE99E7E515650511FF7016A0EF287ADE
+                               5A03839C4F83F05FAC3B0B24D4E3F602
+                               3251F8D9CC4530A805F8A6A912EFAB1C
+            stream[192..255] = 792823ACE2C0DDB266A118068AE295CD
+                               716E424D3B98A9DB2501A3F5DF7DC70A
+                               3BD2C6E664D5E13317D6F57B8774C903
+                               D407D2BB6014E0F971141E89569C5868
+            stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB
+                               304C81FA9DDE0C21592247C4098D9347
+                               1DA30294DE8C100E5B17A199F744CAC2
+                               4E33490FC7F223FD6B4923056117C6D9
+            stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59
+                               349AF2BB1DA2BA622B9824F729929098
+                               BD19DFC05D0D9454F604960C027752F9
+                               7812E53DE6AC6CD2751AB331703646AF
+                  xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2
+                               DC458E7E517637596FC8FB710E2E5636
+                               DB1F14848CB12793D54ABD0856B22F3A
+                               ADFA8C33AD08B8CC5292DD76913CB105
+
+Set 2, vector#162:
+                         key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229
+                               8A8806402755660C4A30CD216A500BB6
+                               AE975E08EC62D08425A8A62A71B00215
+                               DE35E5178902348698528CB82296F009
+            stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C
+                               E4F7E1B3E78C3A5DF07592F45B968BEF
+                               F95B8B257DAF2B468284627AF4481FD2
+                               67BE0B164DD86721DC8C1607A0607EF0
+            stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3
+                               9C056162B626F383F3E77B5C98C0FBE9
+                               119A7C335C333E6490126AC2510CDFAA
+                               86441C72D1DD9ACBCD3FEFC0D0C794C7
+            stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754
+                               246C065AD23A8D709161FC74B34E23DB
+                               B918EAFA4465125D3780BF0B5803AACA
+                               037AA0A14D977141B611A6CA2278B634
+                  xor-digest = FEFDA1A6E95920B93380CC24FAE214C5
+                               6B009ADCB176D519CA4B8538EDFC95D1
+                               6CA06B730B28A230F0085FE43CBEE2FA
+                               2EE5DCD74D66F5CBB59F256CC1ED885A
+
+Set 2, vector#171:
+                         key = ABABABABABABABABABABABABABABABAB
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 22E1A884ED2C67CCB2977105649B6544
+                               367858D1A730AA2FA96703FA406B337A
+                               B2159A389BEF48D8A215D870B2968E16
+                               B11571F12BEC0A07FA7D3B9790987EC7
+            stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74
+                               B27776E9250B8B063E52E169C7B76A15
+                               0D699278AA4124427B5EB6AFC4AD5DBF
+                               600FEAAA98A88DFF297DACA5ACB4878F
+            stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484
+                               976B640E60CCD6ABFB908583ABEC3E75
+                               2878371EBB5374C9B37A63E0768AE10B
+                               D857253D940AC408EF49EDD590E806AE
+            stream[448..511] = F012E429C44D5DC03B88123855B62C0E
+                               90E06759306017B5773752973850531B
+                               C480316CBBAEDE6353AD5FB298349AA9
+                               16AC0221A4CE1E4729BFB9C230AAF9FB
+                  xor-digest = D73B872315F9052C67C4CFC5CD912DBD
+                               60DA32FD06D9C8E804968E688898200C
+                               1D979DFFCE52E1C3B3309B58D12BDBB3
+                               D3EBA2954D1587D720E004E12EB4A13B
+
+Set 2, vector#180:
+                         key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88
+                               D2EF924014F7445ED922E9C021571909
+                               D7E6BFCAEE0724F2A9C522C4BDE4BBE9
+                               FE53FE592C0FEB80D2C7A51FB8BE9EF3
+            stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484
+                               0D22CDDFF39EB0E3D5FDF74C6E7B3394
+                               A0A4271D780DE6DEE9AC58B4903EEDD2
+                               6DD14E14A4DFE506748D5DCA6DDF4C5A
+            stream[256..319] = E79D99119996FBB5163335E2F79F0502
+                               7AEA5372136E7B3C5BE1F4A673A2DC74
+                               60834B81BE6C4976C4A727C8E6046A64
+                               4CAF42EEA6A068B7E532581E9037BE9F
+            stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614
+                               9F3EE55A136EFA3B417DB63D2487DF82
+                               794E161B3153DDB2E1E4F385E1A848C7
+                               729FF5CB1CB58D5E73FAB1F2DCEEE5AD
+                  xor-digest = 2F3C231B0228C274255F3BD314ECC7F3
+                               1B9C49177009AFF2CD88F807092D77E3
+                               C74C1B9B8650F581EC7603F4D6E70955
+                               1B00C3192414C04AB0AD8B0B9BCFE988
+
+Set 2, vector#189:
+                         key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410
+                               DED6D4E331633C5621B94E7EBD15E856
+                               04AB202A553EFED55A548C7AFFCD2550
+                               60315FD50A305D8BCAC9C077229D34AC
+            stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF
+                               3CFD130D5B6A9CE37BEBA429AD137A82
+                               44D0586FEB16D086F533D1885A82F73C
+                               F2AD2C645591F80ED09942F0A08D898C
+            stream[256..319] = C214B6AC700164FA66DE346A27A99463
+                               C5B6C0E43A9057384BE168E163058FCB
+                               6E7DEC871C6531EFC8B8D581EF92757E
+                               219294D39E0C9C8276440BE56C3D9941
+            stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE
+                               4C8D2171695C9CF97E2936A8BB320670
+                               015825547A508EB43D96F2EE1EE2CB34
+                               4E120F001500F8ACC3E19E30455D09D0
+                  xor-digest = FE5928C74EA21F23E29171E5AAACA20C
+                               DD8571E907763C96B99A8C11F9A1D2F5
+                               78F68A6C440996995F7AB6E69B3CCE33
+                               CF8CE0C16F54355696D47DBF82EA8D56
+
+Set 2, vector#198:
+                         key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 75559677D7C762F6CFED942D800F2FAB
+                               AB5F3892DC2C79922E96FD34FE511C11
+                               251C8EB7C639E531CE08A8C99F62E7BC
+                               F68FBAFF99D62348FF91CCFEC2710055
+            stream[192..255] = 149806A4D862EEA81F0208D927339E5E
+                               C98E9C2A6E0DB85CC0380DED7EC5B8AC
+                               4ADAE76AEB9C7B7264C3834316209615
+                               25221D58C0174577110596FF89C8FC69
+            stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B
+                               3CDD19BF89B31FF75A814F470BF97E0E
+                               1293B750B769F5BDD750DE5025D7534C
+                               AD541A1F26C6AE9AC2FD3237C156AEBB
+            stream[448..511] = 0958243E88921B81F04AE63658E52D76
+                               CF2638495B3A6B970633A7C8F67B8CF9
+                               AC378082F72FC63BEA02881CC5B28D9D
+                               C8C261C78B2872B5EBFC82336D6E1A28
+                  xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7
+                               0028A08A00EF935C06A8B3632DAD5914
+                               84E44E372A753F8E630741266C0F4218
+                               4923608103042C70ED4ECC5112B9AF6B
+
+Set 2, vector#207:
+                         key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28
+                               98C701CBF5E88F1F3DCB6B873E5CAEEF
+                               23024ADA678E1A2CA9E25AA8B476CF4F
+                               9FCBC297FF03A9B94A5A736274EA776C
+            stream[192..255] = 73B9891D1770289A67D6338909FB6282
+                               9A425B7947FC30DC52B11E398E85B1EB
+                               537E1C02898FEBFC15A9172C254CA55A
+                               AA1B56EA856F47E37E2F252D92D94ED8
+            stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4
+                               38B63B9F436FE00CC075C585297B8F90
+                               E6062358D29641FF9C28EED4A23FC53A
+                               6B5C60C2AF1E8146DB27CCF5F43BA838
+            stream[448..511] = 642541A9733946827D79BBD815C03C17
+                               6357BD6E81E9A61FFFD4A0BF6863AC71
+                               72AEFB92C1F235641BBE1457B724A6AA
+                               AF9FAC687552A778B034C4A4F8E41ADE
+                  xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668
+                               BD0BC5A97655978E79056B3D25DF3E79
+                               5D5D8BE5D1AAE877F2E7D03225CB6609
+                               6EFE11CBCB728039A243E326437CE73B
+
+Set 2, vector#216:
+                         key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F
+                               1F7BDFBB81428FFEE9FBE14DF5F5F3D8
+                               A044EF53A868D989E16165A0F2B95E8D
+                               83439BB4805A125AD0CA7994AE11B852
+            stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184
+                               EE7A7F4B822A1C955A69E238022AA313
+                               276C2003E27AEF1B4F94B33A6428685B
+                               F048B357EAB297B7DD98E612F054A317
+            stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C
+                               978B976BE1B6CB0D15C0324D6B70D265
+                               385B615B3EA97A55D94C47F53FF40861
+                               4460857AC9568556AE54A52546B41B5A
+            stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6
+                               5BE2BF56D2B78A401D5761E2F3AF8B18
+                               A2B1089864999D9B99E5BF6959F8F802
+                               975FBF204D6159CF23F3706CAF0D9BA5
+                  xor-digest = 0957D6887501D4360C430614B67D99B5
+                               32849E2F5C69CE8A9F3F707A2B5438BD
+                               0C1237B5617FB525CC9C043A10DBB265
+                               3C3F0A353E89A19838B8F68542E09526
+
+Set 2, vector#225:
+                         key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A
+                               50CF101BF065F69F3E78BEF5D689B1D1
+                               D306FF41EB3E78BEB75C4200937CFE60
+                               E89E370680C519B2F64E23516ADF8062
+            stream[192..255] = AA30580A210B87727BE17EC52AAAD037
+                               3E0DD11FBFC89B37825CA4D6F9E8D433
+                               E3EA54C37D678B58CE834AFA310F6D4D
+                               06B4603F12DBF38595AC76511D0B13CF
+            stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC
+                               8FC9B09DAA6F418D3434BFBBFF6BFFFB
+                               F93F8A963F2F51CC487BE868F010EC0B
+                               EE17A480542A301E33B36F59BEE13D91
+            stream[448..511] = 672048756C221C12DA6178BE711B3371
+                               525A92BC9A219CABC5501B0DA4CC248B
+                               8742E8BCBD6F5A1CFE522F3DF3BED6B6
+                               5D60D1AC737ADC582C2CB9751521828B
+                  xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB
+                               3F418EBEB69509D69B2594E964759D15
+                               104F674CD44681AFECC3B4939CA0A0C9
+                               DD7AA5726653ED3FBFC833DDB0C87B42
+
+Set 2, vector#234:
+                         key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 2479A8F2872A813D16D15F060D300237
+                               25297B812F6F3B97D74D9716E4403A5A
+                               684D2BFD1E15275470FEDADF1578277E
+                               44C6C06B8A5FCE3D0CCC5E13BF49947C
+            stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3
+                               132D4B0065A563288F848E05EB45E48B
+                               D15C069C02F90B4FC10AEBF1AF4BF90E
+                               2CF7F48C8CD7A8091014131EBC21FBE8
+            stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C
+                               EC170B064429EB832924CDA9C47B5174
+                               9BFEF80D96FAE36DDA65659FEA1CC06B
+                               4EA3A1601A3304AA4DDBEB62381FD4DB
+            stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145
+                               BFBCDBAE19F5281CD0E6AA37419778DA
+                               64DDF68726DD7F4D78BBBFF4576C2AAD
+                               93F477A2AB2C3CA8A381F30BB944C7B0
+                  xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070
+                               9EC7E9B89DB8EEA11045ACC5FF003DC9
+                               CD3318BB6F9675EEF20E15490F525066
+                               AF8380C663B60EDBAE30663C94C39892
+
+Set 2, vector#243:
+                         key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CC3701E703946194401D1BA23AD99B5D
+                               F3F856138E142D4B9C23DC9F252A277B
+                               D62DAA33A71A0C61079AD5A20562291A
+                               B6EC92C66D7BE6A17E27D4DDB48EFD31
+            stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903
+                               D565423614409AD11E821B83F5B35D83
+                               F26F3EF9EC1766FEA9C21C09E0AE248F
+                               4BA01E48BCE09D06471593B3466703DD
+            stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF
+                               96CDC215EF1A62FAA29A5608C852FFA1
+                               18B473C5A7319446F3ED2E8AB39A533D
+                               714325D1B14E838C9EC6E037DB0DD93C
+            stream[448..511] = 4FF3B43841B17A279002EFB07324625B
+                               7E937D480DC73F12836195110ECB4DB5
+                               CD31CA4F92F612A95E82815328DA7D5E
+                               4DCC5BB6791603EDA64C57B5A5AAA04C
+                  xor-digest = 9202B874C48D4B1A9E857E645EE8F884
+                               D971CE97923AC024ABEFB944E34550CE
+                               31712BB832F9174F86FCD369E75CA9AD
+                               85095F43A4B7F33AB641BD6912D2C59C
+
+Set 2, vector#252:
+                         key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F374DA745A5CF93A567027609E5D3B1D
+                               5C3C8A4D15203705D978AD42279F6548
+                               51FF713F5120CC93D044EF717F5A75E4
+                               98DBEF559E5F157A8C819E213E93B3F4
+            stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9
+                               175AEAA99D55485954B265B5CAB86509
+                               C810E664766A8E6C90D4BEE3A58B1815
+                               9076959FFFA2F30EEB12343E9E7778C5
+            stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC
+                               418DA96336991A27DADA74FDA987B867
+                               B125C53C0E4E2889FDFEFBFB48797A22
+                               2836B2EA42793CE2BFFD568F6234B368
+            stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36
+                               4CD2D730DC8D7E183EC55A777C2445EB
+                               BA7E9CD95C8F3A206B73C422AC2E2C08
+                               15A8C6FED156FFF93B63DE512EF69725
+                  xor-digest = 467EDA43B849054EE747A532ED0D9AA4
+                               6EA1BF2B6AF19F481D6E3D55EBAA96FC
+                               6629FE65B5EC4B5EB6A155A6D60FEA32
+                               F04F8230E26390F1C8FA53D47B68FEAE
+
+Test vectors -- set 3
+=====================
+
+Set 3, vector#  0:
+                         key = 000102030405060708090A0B0C0D0E0F
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0315CE93BE05F88212B413335CA65F33
+                               6387BA612421C7BE8276299CC178EC31
+                               2143C503A9F2644685882201137BBBD7
+                               3A2385F0AD14B690281B54B8DC064150
+            stream[192..255] = 8B663563AE31DCE7AC61BF4943466774
+                               E9EE784644AA761B9D8AA9B8E04D4C91
+                               75650DDF130454DD60724864DF2FB6B4
+                               31F947F8FCA83F6D3B113BC413D3CC10
+            stream[256..319] = 35EE3D4294E5660A99A1A1C9254D27A4
+                               B42FEA8CBD5C5BD8B902E1B1BFEF17D6
+                               ADC9B6B924C7C53D44A5C58210989BE8
+                               72E532300EA9115CD2AAC8024779B3FC
+            stream[448..511] = 402F841F64827A197FC56EE9C180F5D1
+                               075107622178407B063F70C6C860C6EA
+                               E3016D56F7CDC13A109283F5F4FC9420
+                               6C62BC3D1012EA03EE08EBE8C2DC074A
+                  xor-digest = 6815E00D7D3414FCB103EA82B38FD4F4
+                               68A453E84A520B7119E9D3A4C938BF0B
+                               AC26F7F73EDA7F3E2F20FBA551C15205
+                               EBBF2F6BFE6DBAF95061F0AB3988DD57
+
+Set 3, vector#  9:
+                         key = 090A0B0C0D0E0F101112131415161718
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E695E5417AEC9FBFC0EB0909435E79C6
+                               76AB8E2F28C556CC2C81CFC5F7A2A6F1
+                               254EC0CD2CFAFC257907723557C1DF5A
+                               D81D1E3D201410A12A5FA3A6160F266F
+            stream[192..255] = E3D590D9AF3869FFCBE2A4B8C77A09F6
+                               211193F83B8A43714CCFC02D014376C5
+                               A44FF7C061471AE208F04DCAA89792FF
+                               AE7096EAC47898C1011095DE9B55682F
+            stream[256..319] = 0F31D78C0B86D246FE105AA6D9B93CE0
+                               257E75CC0D2A0BE96B9156555D8A407E
+                               01F47AFF719CC894EE111C32672B0404
+                               B5F26C1DB1D7D0F9E470900AE53B192E
+            stream[448..511] = 1A01733BB8EACDF2B2F4322FB54FB6CB
+                               C92989248FF31BBAAA8304ECC4AF9A39
+                               CAB21BB66E0A144D8B77C537BD52DDD8
+                               C5B0909CC6423D4F243E5AFE6E22D07D
+                  xor-digest = F8C3BF6905A19184D14039E4B7FCFACF
+                               2EFA004B35B55DD04F56199C6C9DE1B4
+                               458C5EFAC45C6062BA1EB726426987ED
+                               88FA899849CF5F6CEF60119F6A68AF9B
+
+Set 3, vector# 18:
+                         key = 12131415161718191A1B1C1D1E1F2021
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3C189DEDA71E56926CA2C3A2974C4FAA
+                               B7EA3C1250E768CEA797ABD6477B59F0
+                               E5494635CB4700A95BBD54B0E93D12A6
+                               423DF8F34BC6B3BE705ED6704BA33894
+            stream[192..255] = F21E411ACF063846BF68F61F7673710D
+                               CFBF8088E2A815F406E17C4BF4E839AA
+                               D2EB9D137B0F7889E68F4B5C8160199A
+                               7C9C697EA6A1794E954ACB535A72B255
+            stream[256..319] = BD7E1C4A54C911E84067AB00F8427810
+                               BDBF4029E78D424E65F477BEB457900D
+                               0EA49B639863BAEB1427A161B8C629D3
+                               55097F5DFFB24BB97329A73B144DB7CA
+            stream[448..511] = A4D9A80D0055F2D8C55D2A49B39DCA69
+                               9A5652C43258152B42BECDE07F21F8D0
+                               EAAC565DCDE549CA4A9A27D82F5AF4BB
+                               1EEB1B0A53A58E50C3E83CBCDCB980F5
+                  xor-digest = FF451365606D0117E15FC2721F40C9CC
+                               0FBF6442A771F8FC3B06186C35C6CA13
+                               B30F65FC84B9A38A6FBA2B6F16541B0A
+                               0D77BDB4F696894B2B73CCCB8D6FA3B7
+
+Set 3, vector# 27:
+                         key = 1B1C1D1E1F202122232425262728292A
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BE4A26D09D47D25416355FB7FF60AA06
+                               3B3CDE5374780F2C66514A0CAA07406A
+                               88490A2E3D6294A799C9BAAAA1B10ACB
+                               88FF4F6F70EF1F4F67D591040244FEE8
+            stream[192..255] = 54F1AB7235B6440D6A7FC7851E3FFDA8
+                               6CAF44E3F57E1E9406908064FDDA3A3A
+                               3C7AA1CB6ECAAF376C5F290EA02844EA
+                               779A225131F24D2E7D34AD0342399FED
+            stream[256..319] = 81AC4F45FC40CE7E1FF890F5EFF2B583
+                               36F71D1911C7E0227AD8E4DFF7369B41
+                               A8C266B3468A78773C4C40A3EEA6B724
+                               97662462F48835FAC7B6C77CEFD39A65
+            stream[448..511] = CACFA9A51224F533C600BEFF1EC03C7C
+                               7C22EDF93E8596128F8709F0CED4E291
+                               997229AC5542FD2CC9B1167C3D2BB57D
+                               9B08B82C0FC41D93B7CE2211C5E2D534
+                  xor-digest = 0D949205B6024DAC1D215F2AEA7CB484
+                               3FAA9A1719398AB8828A28BD2568369A
+                               C78A224AAD95BAE6A6333C4C13D630B9
+                               42AA52099F6EFD6871B1E45C8DC68AC7
+
+Set 3, vector# 36:
+                         key = 2425262728292A2B2C2D2E2F30313233
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 65906EA9CC0080D2044671D22C7DE242
+                               F764184ABE8DADBCD550225BFD541D6A
+                               762C7A5268EA0ECE51D18269E71A4CCC
+                               054AF634616204C81AE7E515719775DF
+            stream[192..255] = 9ED75834EBBD9576E11DCE8C583ECEDD
+                               2B8780FE98B44E9F08BBE96922C77BEF
+                               08DCE0DFD7C77C42236885BE6EDC8343
+                               24EAED350AA5A513009272818CBC4BE5
+            stream[256..319] = EB1D998260B3AF4472DE59E1C9DD359A
+                               B346B32DCE36C92C9B7BD808BAB76AB1
+                               EDCA2827557501BE0FE28F6498B33B9A
+                               F4EA48786F3158E8047A32A03AE1CD90
+            stream[448..511] = D06B1B9B8110FB9809F5887A35CB24BB
+                               80EDE203AE648AF9FA348B18D8A15B8E
+                               E98E8AB98A7AC5BF71FDEAA1A6E978F6
+                               7D5734AA7FA88E8DA44C861E2F54E585
+                  xor-digest = E77DF8C1D5F46F8896DD00187C840B0A
+                               E4404581DD053C6F39323815729DCE90
+                               0D85C2D8C97D0A3B57CF622F81077B80
+                               92988EFFA36CA176F7393D1E38AAB206
+
+Set 3, vector# 45:
+                         key = 2D2E2F303132333435363738393A3B3C
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3FBFE9A391DE0CE5AAEBF9DA3A15EB99
+                               D6CBAD0341CB78042C89F5D5B0B555C8
+                               A400DC47FD19F40493B348CB51430B44
+                               D05AFCA9D399709EFAB8ED2587F72E85
+            stream[192..255] = 68969047EE54910C44F8B5718E993234
+                               D814C27C0B59EE09F0D35B58352AA6C6
+                               594F605C25C16CDDC29A354A1C6F5948
+                               AE497C093E2D41C211E4C1417DFAAFC4
+            stream[256..319] = 0DD68E08A25ACA4448DF4B562EEBB855
+                               14E41F1F560C479542FE62C2DCBCF03C
+                               30AF180FB71E65A9A09C551551A33942
+                               53558C2440084E6B4CB664A4EAFCAB66
+            stream[448..511] = D93B80D67B6484030103CDD72536E695
+                               E7BAF8B1115109D5D5517BD1E06F4236
+                               A3551688F5C0D78B2CB080AC072B4C48
+                               94A2AF54AD9D816E2068AC569BCD2AE2
+                  xor-digest = 7C071BF395B48A023A7B708A9651EC8F
+                               0C9A00DE8BD9D0764C7F1F394AA2B747
+                               3EF87BF792D5B89AE0548EB9C1344DAB
+                               DF2E4EC6064D50EE1622160D6DD7ADFE
+
+Set 3, vector# 54:
+                         key = 363738393A3B3C3D3E3F404142434445
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 64468807E7EFE78E11B0231D8D7AE80D
+                               BFF3FAE444A60496C8F2DA202941686B
+                               95C48457C1F9DE1AD2FE581336AE36AB
+                               CA574BCB9619CDDB96E4499409516635
+            stream[192..255] = A7DBFEAD9B969D334705B6C53A0CDBC2
+                               21E0BB92854B0B107CC39F8C6E4761C3
+                               EACC8D8C5741AA4243C5BE1A79971A0A
+                               5A23F2BEDE9F3628CB9099B8C7EA9324
+            stream[256..319] = 1A44FB18740973F3124EA805C90C4B27
+                               4EE788D43F4B894B01F63C13410EC204
+                               2607241E87555B0E1A6FF33AF0DB010B
+                               8ADF607E6353FCF74F568E0BAF0F4455
+            stream[448..511] = 11568B95495E520EB6BE106986A07C57
+                               8FDF21463607619E5AAF117D84611E75
+                               F8979F59E60B43C0A37BC24429892742
+                               0D206274DA45EBBA7660422DA45294CD
+                  xor-digest = A70B9BFC683AF2716E17980A49C4F747
+                               AC25992BA7BCA5E5C2AE162497E4E8BB
+                               62C837F64EEBE4A55B5705F115CBA057
+                               C560B1AF0A733B5631E23442601A741F
+
+Set 3, vector# 63:
+                         key = 3F404142434445464748494A4B4C4D4E
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 35865AF843244DD2F95CDF7C9BD54471
+                               9C8432538842C28F93AA21F6E10F8B18
+                               31C2AA7EC010A66E539CF65BE55120BF
+                               090233750995003C7AE414DA6D55F86C
+            stream[192..255] = 190F215FD14E44CD141E47A2322D324A
+                               A63A7B512A77C20A02D3BFC1EF8273C8
+                               F65226CBD1BF32A104D1AFEFD6719E4B
+                               DD6355B044EC8D0CE95023C61007E6BB
+            stream[256..319] = BD02130F7CFDBDBC2171BBDEAB501136
+                               B2364F5879E6E9CCA7E75AD81105D9E4
+                               87E9175B62AFCAD79B23D392B2E9C418
+                               437527118797602E629A70CC869AB7EC
+            stream[448..511] = 1F0DF396B5CA6EC9767B0674B2C7A9C9
+                               133CF872DA39DE78F56D41C7F2FF6B50
+                               716717E995D42C51D6A2ED66FA6CC7DA
+                               92E9B3B4D1F130E699C430CFC96969BB
+                  xor-digest = 70291060FEA7D40B5C3FF731FAF7630F
+                               D9BBED1A7FC25A05E6B3F632E6FD6B91
+                               1F1010E1BEC69F16D44C5183E38BE8DA
+                               8949A4D8AA85F5149C203F8C92887875
+
+Set 3, vector# 72:
+                         key = 48494A4B4C4D4E4F5051525354555657
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BFFC0703408DF6EB169656D09A5400DD
+                               9C4BAF06A3BC7220E45814104B6D9000
+                               9585BF9B0CD988E94B8C5026D07AD7F5
+                               7D81364775D54D808A5C18453B62A2A1
+            stream[192..255] = 5FC95B73A4C91DB20B93319E420B4C5B
+                               A9DE1873C81C835CB455970A90921594
+                               F9635EF4F411C9ACB4298F75B2CC84F9
+                               7F52182F7F001A1EDF72A68FA1ADE313
+            stream[256..319] = FB24E97B0CCFE15644BAAFF342C55FDF
+                               64434708407AA6D73576E842D5ADF4A2
+                               6B32D329A2DC9F1451C4BF3E9599E9E6
+                               4E5E65F73E09E4F1254BA0DDD8E6C52C
+            stream[448..511] = E2EB303CD0A67C99CDCEE86BEA581FF7
+                               093C9228900B563C6D10B20BF99D3911
+                               D47C805D1447C8F233D3FDD27CF0DA42
+                               D42E0389E2CCE99A274AD9D20B9C6102
+                  xor-digest = F83FB58CAEC8B13BC25C152FCF24E10E
+                               392A197FDA05A6A20E14093EA0B34C5D
+                               FAE102266465324F5AC07FFCECC8E618
+                               D0BB60761A26D5FD59D188097A2348F3
+
+Set 3, vector# 81:
+                         key = 5152535455565758595A5B5C5D5E5F60
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 84076D83A841C8C6ADDE3B5D9FDD6529
+                               4D0F92B549112F0A6DE05236F732E81B
+                               3C8E92229C411D2295129ECD18DD08DD
+                               C98BA78D9BAFF6271D95E1F361EF699A
+            stream[192..255] = 7063A52FB2729433D8A7BF30F27E6EF6
+                               F17C2A422E60A737270787985508D062
+                               4E678A597845CA9EF939F4B8966BD99F
+                               B8633FEA673CE7BFD2ACFB5942D7EDD9
+            stream[256..319] = 4FCE866E8C2359C53F0429F569D02DAE
+                               E99A4062246B633D4C502DC897AD8025
+                               38C95D49D3B1FA94F4E92441357B622A
+                               6264F50D5554BBE42191AB3D6073A8AF
+            stream[448..511] = 2F7C38BD00309FC81D28D84EE4355216
+                               D97A823CC46FAB9DCAF621E4128F9CB8
+                               838BF02E0EF940EFE96860CC0B996044
+                               42CACFD3306335241C1B4B65E790233E
+                  xor-digest = 44038A33AF0013BB34CBCFB77F7E060B
+                               96F5134DFCDBF04EB8F7F29B15C3FDA0
+                               F766DC940FF548C23712625793851A94
+                               294CC7201E1EDC6056C12A46524C6FD0
+
+Set 3, vector# 90:
+                         key = 5A5B5C5D5E5F60616263646566676869
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E811CA3DD1DD0057AD3A1794D3F9CCB6
+                               362049B1692D6ACFE1A6A0FCC99C7A04
+                               3AB9932A146B4040AC9F8E2F0A227C7E
+                               C60B1F35D60EA14483BAE1F8D1AC7FE1
+            stream[192..255] = 865B05E224133AFC45043F05F8082FEA
+                               487BF63BCFB96DA3EE26960061446669
+                               B1C92C6BC5905BD1EB57D579CB62A220
+                               2F35CEB603658237AF1908132A25971C
+            stream[256..319] = A84BE383FC852F1BF44130EAD15B3548
+                               56737C7EA68A0700A22D357FBA70E031
+                               BDC0FE8EC36C41790A8B7706A00CA338
+                               603E054A83881599D718B1911D1CE9D4
+            stream[448..511] = 9286C3479F9A17B51D8749257F59E892
+                               CE7C3EB8638B29C17D779811F01EA405
+                               257062A5F28BCDA1862FE653C7607350
+                               9A87D12EDC5CAAFF9E8F9F76DA0BEDE2
+                  xor-digest = D629CA4708BEF7EED04BB5531DDF9C64
+                               BA4981C9A705D59C4B2391E94B79CFCD
+                               058406845D81E7EBC097330C01FCBCF8
+                               D78940893B4FA38554A32D861AE96D04
+
+Set 3, vector# 99:
+                         key = 636465666768696A6B6C6D6E6F707172
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B89516368AFEEEC12434F76AD1E1ECA8
+                               FF6FEF7B46D05EDD6041C7B8C1E3A33D
+                               2818E38113592B615E980304D93435DF
+                               BDD5676225173331C3667F30AA2A3D2C
+            stream[192..255] = 249528FA392B19B6811711F523D27578
+                               F1BDE75CA167DDEC08303906B64FAC0F
+                               B2912A7A0EDBEDAF9FEDA420DEA330CA
+                               7302F5780827CB11B15A4DD333FD7099
+            stream[256..319] = CECC1B5077BCB9E129B01D8D75089B41
+                               64E76DBC9C8CF2E4D2F17A6248522A51
+                               FCFBFBC992F75D613307F4DD6472B6DF
+                               C8A5B29F1068FC0F1C3F8964B0E09170
+            stream[448..511] = 8B26C436E918B099E4D3A7D4D3395E49
+                               056A8A29130667A32C6A2B0FD08A482F
+                               8F7538ED90374846FFD2E1C733AFFDA1
+                               12148C9718F3F208344D5FC20128AE2C
+                  xor-digest = EAA0ACA59CF63BC27082BD52D6757FD7
+                               620A7AC5AA2FAEC52646978E2057C5FC
+                               F60B36C09D87419C1D1A64133357DB05
+                               6B96C854F38C36DD657524FD09729341
+
+Set 3, vector#108:
+                         key = 6C6D6E6F707172737475767778797A7B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 741C607A6BD38F93B33244C8B7F05D78
+                               46F6A05CEE5A87762480DE123D3BEE63
+                               240928FFC75ECD9AD1785B1664DCB59B
+                               A12F3B64C93BD4FC8C67C0934E5B0ABD
+            stream[192..255] = 3BDB31A701DD7F2E929803C3A47896F0
+                               9E5F569A32AA829E505E34BB7232597D
+                               B838F543A34CC288F9518BE16A228D42
+                               BED0CA3CE0C6E7FF9AEE63625C699B9A
+            stream[256..319] = 1CB7FE159EC1A57043BD142236DC0A18
+                               0CEF37316A6E96354AE319142282F19C
+                               1550EB645DA8F7BEE2ABAE4EAAC0BA29
+                               893E722A6F8E0A9B34368DF56C5845B4
+            stream[448..511] = B6DF810D69EAFB7F2360F6ECB50C5861
+                               7D32B3F495B3E4424045E88CFA0871A2
+                               9314121CC78B98B456ADF53E540346B1
+                               214AE2ADB65C552273F1FA498FA74101
+                  xor-digest = D35A8AE5783348824175BD34F2E16FBB
+                               975E7695DC6C4FF1ED763D404B0D4D30
+                               07AAF01E988BC85DB2FDD017691D3BB9
+                               811355C3C7A6156197AF57B794DCE85D
+
+Set 3, vector#117:
+                         key = 75767778797A7B7C7D7E7F8081828384
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = EA9DA2D5BD4B6E070479ABF8CA2D1B3A
+                               6B968A025D010944FEB51AB2E507F86B
+                               111F8A351A3F32CE1FBC4A75AC34F722
+                               1B5190F2390073084F8153E00BB98D0E
+            stream[192..255] = 0AE0DC3D0E2D3F5F93E446BEBECC4F60
+                               862D190829A209966E132DD029ED6998
+                               DEF4F613F3D53D0A36CFBA2CFE345DCF
+                               013B6CFFEC0116FFC1659A57FB42E0BE
+            stream[256..319] = 5A7FF46C335912389D8B88437CEFD27B
+                               76706405F45F87C91390273D9B70CC5D
+                               89FDFA85E20EC82B98A79BFF5FBF6AB1
+                               4F61F2C1289CD7B8357126C8E13271AD
+            stream[448..511] = 9398E699F5AD8FF31A50C8EFB9DF0D0C
+                               FD612B951A203C1BF85C62AB5AF1C412
+                               42BFD0A55F21820C6F917EC90A8FCAB2
+                               E774A93713A99C7900B80A2BF496D0AF
+                  xor-digest = 05D9732FF20A61E19428873830DA7282
+                               819234F22FE7DFD8871C21CF10C08EF0
+                               7C0413898DB144861B0CCB62992DF40B
+                               29A0A4688C91275F0A198AF39899E362
+
+Set 3, vector#126:
+                         key = 7E7F808182838485868788898A8B8C8D
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 8C4F8495C7231AAEB704E7AB9E79E748
+                               6CB5BC85D3622B8A2E2CB778BBFDACD4
+                               CEF73CC485D8E08406F5986A28706CD0
+                               56D085201DEDB875573B57629B8541C6
+            stream[192..255] = CC6374A744E9205CA39BCD678074B844
+                               16346A7E54F9B87905BADD2FACE7B9F4
+                               B0A366AA3F632A7A67AD8AAC4827C9BB
+                               A1E801A8786BC4FAC2ADE6A6AD6A45F4
+            stream[256..319] = 4F52AAB001BE94A60761CDE0334F8A84
+                               C617195B084E441070E343CEC3189CF6
+                               D6D955F9AD649A3891BDFFACA0A6E6E7
+                               7291396670BA07469D267EB80E48353A
+            stream[448..511] = 673AF85AD5A9A3F26CBABCE9BEBBAE21
+                               E0B6DCCC3256227FC0EAEDF343CC7E9A
+                               8896023DF073E88EEEF135BE34CF67A5
+                               5FB51D3A1754B15A7C4E2CCCB4C8D51C
+                  xor-digest = 2BD4B8BF9B7E79B0EB53318396B03575
+                               0AC918A6A05BBA499D81C9EFD32A0FCA
+                               34A83FC801CD6475A774091F33AE7689
+                               B9FE28645F545E9A9531F528085926F1
+
+Set 3, vector#135:
+                         key = 8788898A8B8C8D8E8F90919293949596
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BDF2E95B80FDF304C3C4A8081391EDC9
+                               7F9553F93C27788F03797EDEBB8F59EC
+                               2FB2FCCA7727CA1CAEBF5C8DA8719492
+                               F1369D96B2FEFA23D89400CF7CA667EC
+            stream[192..255] = 6AB7500D876A4924DE59800345AD69FB
+                               BA1690733713BF372E0108D9FB65B0E4
+                               50BB89899AB84198381623094F823FF4
+                               8BF9A09F0FCA23684E78654F3D231173
+            stream[256..319] = 34ED638D249BB1AB8B16D350309AE32B
+                               9FB62CAB0EC7AB9D5F3C12C9A6502497
+                               6323EBBBC4CF308FFA68A3D4D8D3959E
+                               AFD3BE46E36072FD15A5DC3FCDECA6D1
+            stream[448..511] = A8BA33AF6CF545424E607A7FC4CBA593
+                               CB05B38C836B21D85B6FB1894926A459
+                               8D71AB424A5A582A491747FED94125D1
+                               08D6C693EC9E4BDE2F418810A921B54F
+                  xor-digest = 84F29F11524741D39779025D792AB735
+                               07963EAA0FA8EE220ECD3592E1320567
+                               BFE76EFC3356860192DDC5F06B94E552
+                               43D659D49FB94C30AB69AB5E9C370A5B
+
+Set 3, vector#144:
+                         key = 909192939495969798999A9B9C9D9E9F
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 1C03A0D6CB75670CD7D978B2E371857E
+                               27E597B15B905D5F4F4384FEC227073B
+                               5A56D8C0C4AF767F267DDEFF86AA036C
+                               41EB6170603AEB3E3C1EF3E176CED812
+            stream[192..255] = 6447D1E067550DEC9E8AE89DB02B85B4
+                               3DD7E511C8B98438BAA50CFAF7CDBB68
+                               757DA1D03A29B9EC6BD633E17BEBC8EB
+                               2D8D453F583E4D183AF30C9F47C8DD56
+            stream[256..319] = B324756101C28D9FC4D1F065F1D000F4
+                               1155514EDB30A7FE36C26B18FD93D6D2
+                               0470A41B6F8D2E8BE140568BF72223F0
+                               981CEB9D100B21C8B751BA6B2816B2D0
+            stream[448..511] = 304AADCAE0CE80E91E3558974A944663
+                               D1E2253977CD7B0D1BFAA138DD81A501
+                               D7EADD8FC834931A44642BA9873AC1B2
+                               47A454EE71F7AD8671BC15E088D01532
+                  xor-digest = 5980D43A91C09B20B0F3323F1750CB47
+                               118550920627B6C512AC5CC53AA6AD25
+                               68EE1EFE702FEDE7CADBFA25B32696FA
+                               12A18CCDE35A1B679F709F28920DF92C
+
+Set 3, vector#153:
+                         key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C2083A758037E850A6FE642EFDE59AED
+                               F51F3002BEE2E69DBDB538BE2D93EE8B
+                               27A1CC89672DC14C44DADE531A88A769
+                               5DC730A2CDF3096DE7F4BD08A1ABA918
+            stream[192..255] = F4D19950E6365AE6BE8011A24B9D803A
+                               D9A8547D452D8B0B8C51676E207DF323
+                               808B5A094A2FDEA5DBC86BFCA576E98E
+                               D0E049834CBE0B3AFAD6892B542EC7AF
+            stream[256..319] = 8F2A026EB2165F39E27DB86607878926
+                               4EC8F42A09E8C80B317FD4F1E32AF4C3
+                               73B7F5160C635ECABE495B01A3488E27
+                               94D226E2D86C4654810C08B2FC42610D
+            stream[448..511] = A1D17725577B7A4FD3D1A280BA2B5C0C
+                               386FCFA09E110F00C85ECA05CC142644
+                               4D8EB87CCDC2B23D1CDBBFFF822B5555
+                               11055B93ADC9168B7353CAE10551AF14
+                  xor-digest = 7B4E8A6123216818A218FBD50D8540B0
+                               A0B62DC114F25DD476680F85DEEA9306
+                               4CBC4526C7A8832D4BC534684A403FE7
+                               B80E7F20D967ECE044085B554C158AFA
+
+Set 3, vector#162:
+                         key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 6FB232154275843C74BB886D09CBE0EC
+                               CCC539DD6DEC1EC6F31578B80DD3BAD8
+                               5C992CB1A0B4EA40B3EE0C5174E36A74
+                               E1CDCAB13830453984E4365A6C599F72
+            stream[192..255] = 2682C05E19F6D8FC4DDB15B2F8385B52
+                               C5A4A70FF5A0063CD696AADBF8505122
+                               6F696746D4F8C314543BC3869B1E7F9B
+                               1C0D004655FB6585723CD1EA7A700A60
+            stream[256..319] = D6BA4C5A33B8C2DE342DE48E26AE7B14
+                               8E91552D0E05AC9458ED0010E6FF53AE
+                               EDE70E910165B5986876799E60B7E6BF
+                               3109B9BAF7EE3670497FA7CAFCB14733
+            stream[448..511] = 70C4E8AB8E8BA681A2A06F319CBC952E
+                               E3E78DA589369FEEF8A6BC6D976BECFE
+                               E6C7143337758929FCA7E0945892411B
+                               047C2CC2F2AA284E95733DD94D46B89B
+                  xor-digest = E2D3DD6AC908FF3BAE4791A50F717B63
+                               FB3F1F380CC738E2B1626FD026C9BEBC
+                               33957AF4ED6E8B9864EEEAE262FC6168
+                               9A34FA14A35BD915B6945F35BC3D5573
+
+Set 3, vector#171:
+                         key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = D25BF02A1BB050E0D15246C2EFB3EB89
+                               390BB913916D347586DCDF71D6792CC6
+                               BF72F6F6A9B779BD8833C468684B4480
+                               52E153D11A0CE183CB337450C4482F6B
+            stream[192..255] = 07980A2C57E9094C5334016A782C830E
+                               B59420086EF9D36542A97220A5EEFE42
+                               026B39B1F00A78992ECA17FCDDCEEA2F
+                               88A15F934A1C65EFB770C2FB9712FFF2
+            stream[256..319] = 8C0AF45C68CB7CA8CFF1AB18F2F9659D
+                               E49DB5C4E3609B50C06F94FC01C059B5
+                               40E302FA8604F030701FE3C833617E0B
+                               094D0BBF10580F7C1C7047E86FBF93E2
+            stream[448..511] = 4D4BEFAB68D63085A05C729F54468567
+                               2C2A9452DF6B4B651A29FBC29513E3C9
+                               635DFD75EAC87A5B1362E99033304EF5
+                               DF42420DFD49C1830D66F4F90928F1AE
+                  xor-digest = 9A7DD8AA5D9E9DA4F34AFBDE9D909CE5
+                               DEBC05D2F930FF08AEEE4096B2E1E453
+                               8587B88E535A217E986F31965C5965DE
+                               3BF4A7F99B3B9D938D2C1AF7DFEFA14A
+
+Set 3, vector#180:
+                         key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 5FB2BFB5B9CC4F84D7641B4555DA4A7F
+                               C07C0053E7AD2CF2187F7F34ED4068AC
+                               6D5B43A5FA41437C05C65550786D60F9
+                               A737F44BE450A1F416C1B1A49890C609
+            stream[192..255] = 8EDCA89958225E39CF796EE587877A55
+                               F9B7A7381241597CA6280F7617A11922
+                               9268F95BB326585AB59F08BFCE8B5638
+                               B3A0D32A761C796060DFEBB5BCE859D5
+            stream[256..319] = 09601C099BAC574564E4CC6FD659776E
+                               4726FB22E0025C37873042866B913C03
+                               285EA24E37847F9AF6C838B82FE651D4
+                               EC5FBD40A256E6C765757B6A3CD08C92
+            stream[448..511] = CA5AC4ED4FBEF0D754F033B5267B9FDF
+                               3CA52B131E118174F70CD4F833A5ABBB
+                               198DBCDF18BABB0B0CC37ECFC8D93AA1
+                               5949FBB21974169B46D545F0ED03C71D
+                  xor-digest = 5DAFDEBC75291BA8F55B4A370756B28F
+                               554FEADDB7888F2834BA1EF221E917F5
+                               F631D5BD789701282DCF16FA450D250B
+                               52C627741369DA654E237B8D7F4A8BA0
+
+Set 3, vector#189:
+                         key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E9EAE6C4903004A2AFCD05FE2E3E7F95
+                               FF8BD2888C4AEBB81CDBBCB7488C54E5
+                               B50467FA82B0CA7EA923C608074E1B45
+                               6452821FC36789C8061E99E8A0C0B579
+            stream[192..255] = 1EC898A6958F23C186261F833BB3EF0B
+                               3C185AE8138311B6AB42098E9C6C7FE1
+                               0306DADE1DBF2B1C3215DEBD88AF1CBD
+                               2D805B8006FA0DCF136E225AE3D91AA3
+            stream[256..319] = 55566604D1C85FFE1D29810B6C49F019
+                               69ACB59765A3FBA2B0B9880064606E47
+                               18BC5F08C32EFC250FEE91FB88077A2E
+                               0840615CCF627C64FBB500B7B800B9CD
+            stream[448..511] = 707821EFE4119A32CFD99F7ED7CEC018
+                               C8EE90493FD9268A83E5482DAF9A646E
+                               8765D8199A56A12ECA50775099179D70
+                               B72A3CEC8F0EFF1AFD074F04548874E3
+                  xor-digest = A51E3C9C948B68A1543FDD1F158DD419
+                               195AE7662739446D9FD543681A866A6C
+                               F09756FF4E0C59BDEFFBF98D53F193A1
+                               77D7BF19320063B8AEEC8A544D5D72C7
+
+Set 3, vector#198:
+                         key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = EAA9729F0222A16C750540C605974B55
+                               4FA622F67C71FBA40236A71AC19706F7
+                               9E3792F4B444A39C9C1C902FDBD81898
+                               096338F6A8EB7C934B9558D48AC53301
+            stream[192..255] = 3B5E53787C050061000E3622876AA126
+                               00971A76253833C53B9DABA976169395
+                               3944B5050AB17E492E185737D67581B8
+                               B1C766D50C5B0C2B0D8C78A781E77D89
+            stream[256..319] = 175C28764FEAF8396B3CD34C829D0D0B
+                               E9CE0D75E79017A96C4E7B158B171BE9
+                               4C906FD4BD4946E6DEEC3C78B34C0754
+                               9E85AFCD958AF345E0B432F33C86AA76
+            stream[448..511] = 37BDD665CD9D5A8A8190AC3EEF981379
+                               AD5311E15F853A8A89840879165147A2
+                               807AFABB6236CEA9319DB32344987889
+                               5744A506CA76CE69D9E474840529D667
+                  xor-digest = 4CAAE8F441F6EF3DB6971E274181F8F0
+                               4D7BC603E040833E77921A393EA13F0F
+                               ADFF07AEC94555224F6204874027106A
+                               6D7DDF0546F300D3E84AC87699ED40D2
+
+Set 3, vector#207:
+                         key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 83AC8C40850F4FCA5452871C954AA61F
+                               31A9BD276D39EEC03EC5977A71FDAC38
+                               368D110C57C1A19F2A7461BBFA88E372
+                               F78103F9FFAC1361AC2D2AD84C6AA3E8
+            stream[192..255] = 48E95C2FCFC79C91BACD0C41F626F05E
+                               F80E076E359299EB5272A2F688F96F6B
+                               3147C5A19A99D562A11E953CB2A90911
+                               205A7760B5C8CD959EE6C183A8C1420D
+            stream[256..319] = 974A4DE50EB45F6144DAFFA6B4A68E39
+                               48838434497B8F9700FC42005F3C2FB5
+                               A79984CC2E770C5400EA21AA4EC05751
+                               80A288499879E50462225BE03D677875
+            stream[448..511] = 09823B2D55E26C49E42FC0820D7BA081
+                               5A7EA9380637A2AE2C0D29253EEDB884
+                               9BF4F54D64677F08A1763EFFD904B62D
+                               B3843B0ADE885C00640D16A99E28DCC0
+                  xor-digest = E73D8783F926558E0C1E1B0D3FD86CFA
+                               974CD70EBAACC0CEA2D977E9AFCCD384
+                               935584D2FFEDEA813E6234112CAA1401
+                               71E99BCFE61A7D0E430D4D3F75AA3E28
+
+Set 3, vector#216:
+                         key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 5DE3EC7E6D724976985B426D722D93E6
+                               1F40F5F17EA14B298AC898CBD69F2BBA
+                               5705E1D0CEF7B7122362FCC0D5106D54
+                               25D51F51E29C938C592D9E862DEE9E33
+            stream[192..255] = E079C49AC8F160A9D529F30151AAA7A3
+                               1D137E03DF4C23F8734AAC3B20BF8520
+                               90E3C2529761EB4D67AEF1CC46399947
+                               1240DEE8343D6355B5D7377A7934B019
+            stream[256..319] = DF574E03ADD1DCBD0712D2748C93CD72
+                               D8488396AE3D3275E5A53CAF3EC112E9
+                               50A79494F25B9EC111FE9A7A68A5AEA9
+                               63A4F87B37F822B79D954436368D8E20
+            stream[448..511] = CCEF4C93BCEB2494EB4C70F5E301E980
+                               C494AF8C117F291DD09E3960D2C5A7F1
+                               9928C08F2F51C419E734DE9AADD25C81
+                               3579A7F0B8B367A49B97DED5793E4DCB
+                  xor-digest = 868706BC1A5F3D0BDF96E10324EC36FE
+                               01596216B0B8BBFF69C5BDAF69D0F38E
+                               FE89FFC32D34D142F413A5BEA7AB38ED
+                               22436C62F86C540101DC0267FAF67904
+
+Set 3, vector#225:
+                         key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 45A0736DB4A28A3A6DD181FEF3485F2C
+                               918C65663597C49F4FB23CA550C77CAF
+                               7B331B5D183844278E0D959EA024CC21
+                               CE1A84923E6E782472BA1645BEDFC60D
+            stream[192..255] = E9EE0DFD717F72FD8899D23E87E77DD9
+                               F9DA66B4645AAD8D8C3B489B0A637449
+                               80020326469B4C6403012B6E315CD35A
+                               4344934D720467F30B61C8AEE5C3C342
+            stream[256..319] = 94A2BA2B744CB83A29004AE21470212F
+                               67C2FD18F227FC017131D7F4DD0AB412
+                               48C59BADAE2E408584DF35C603192E37
+                               344C52664DD68B9231661F304F483F41
+            stream[448..511] = 6A29174A1099BF8759D2F5F9BA60816A
+                               B290252AEE08339BE0021033DED03C46
+                               9C8E28AAFAFDC67A7F2219C8942B004E
+                               47263842BEBB47EC6B0666ACCC884591
+                  xor-digest = 7A7411EE5D174907B1138575FCC7479F
+                               AF3437BBF098CCB5D8D25F49E6788374
+                               CBC9CC5812982CBEAF59111813430BEF
+                               56D9DEEDB6C935804013759CFAAC40E4
+
+Set 3, vector#234:
+                         key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C430C2A9FC44DE1563B1679C1A2DFA98
+                               91D01A302C5165EC13B26F6EE4F25437
+                               264AE9E18C98BE112BF560C72024827B
+                               85665C491C47BB396B5AEC66CFCCA371
+            stream[192..255] = 60F3A13B9EBF8784CC81C132E004A179
+                               BEA0606D4C2C830077A50004FB0487E6
+                               E179D81FD9784DC3783ABF86523FE4A4
+                               68930272980E3B46F865E4729DD34773
+            stream[256..319] = 44BC861136F6856B1C74C1CC13753B82
+                               A75E34EB40C518400B507D99B42E488C
+                               8A1F2F590E029EF48DAF2674FDB053AE
+                               5C0967923102EB964602256F70A9CC9D
+            stream[448..511] = 0EE3ADBC4CCC63A8B67C7812CD294183
+                               A2E9D4EF0D65F854FE66CF9D76A34F91
+                               867B27336F8EEC2E2CD30CCB98AD5769
+                               77B07C73C833B51753BB9B0DF08C4834
+                  xor-digest = 7F848C96AE9310B5282712493AD7E13E
+                               2B4581545E625A4DCD98576C75835058
+                               6C621244B6CD439F8E62625ECD9460D3
+                               A18BC2F5DCD9FA7E8CF7880CCFD1A44C
+
+Set 3, vector#243:
+                         key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B9B3501C75EE296AE858573B63C4888F
+                               72B18683CBCD6B95602D51E4388D6DD3
+                               7129169A5209202E2C6EDEB5026B6511
+                               55E4747DD706DDF248A8705D50D38A29
+            stream[192..255] = 12F90D1028010D8296DD0D6ECC4F2354
+                               89856C315555279BD0A4E3161178AAAE
+                               BD849EC0A90903CCFE9DC7CC821C1CAA
+                               D63A45A1D0C0247F1FB1423877FE9A32
+            stream[256..319] = 9F0608162C6315D206B5EFB0E40291AD
+                               E882445B9F34154F6E21B9FA23356DD4
+                               79DFFB16482F6A4F28A8A0629E8B1D78
+                               EAA473CB126FB3727B826B4B3D6175E6
+            stream[448..511] = F26FAB00C37C03AE33209E19F865B135
+                               115A5E254A6B5C1A4896987EAC35C2F4
+                               327822E165AC6BF99F535055ED74833B
+                               C1FFEB32588D8995CEF0708E2D3CF832
+                  xor-digest = 87243F1D4D08D7EE39213D1A4B9E2458
+                               368339A11E364345B4367F84154B36DA
+                               03A3728A7EBD4237897F9D1A19CCFE92
+                               B9D67D3A4A755E6EA8382041D4827A17
+
+Set 3, vector#252:
+                         key = FCFDFEFF000102030405060708090A0B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 05A90DAF1A6B6B60CD3B999A11FEEE39
+                               6D38983ECDA326EC9229D2A1EC722B0C
+                               3C0539DDBF6A4CF62B9BAFEA6C60A29D
+                               4AB63BBBC88987E9A74AE2F71B1E8DE2
+            stream[192..255] = 0AE6673D9F99C5EC9A4532B2B9786CB9
+                               E948A206CB992335FE868BB2271DCA5F
+                               9AB75995A7E7D46F8EA6693765C93D90
+                               9D41C24EF4856252986DDFCBE65D2D11
+            stream[256..319] = D8B07A866003059BAEE90378AD5EFFD5
+                               2732755E79402B50BA0F26A038B3D9C8
+                               1481C19080CB39FE840F8E7313D0C034
+                               9FEA4AA4801225630AAED3E522D6F920
+            stream[448..511] = DED21140E5A3C0C4615D7153DF9381F7
+                               269616817A273BFD984AA5E7CD9D9CA1
+                               9C28E51F4C03C262F5BB4175C799236F
+                               DA69AB27590857C0F270CE4BBFE02D5E
+                  xor-digest = 2D47DA3161389F5F54FAB37F391C21CD
+                               63A748112A1AB415670524B6CB93DA0B
+                               6B54C541ED59F3A54DE238C3FADB3236
+                               3871F6DB1A507B33C1B8F280B0C04B1A
+
+Test vectors -- set 4
+=====================
+
+Set 4, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 114265E078311C062B518148B4530F73
+                               DC9B95DCC41C214F8C9486473DC46847
+                               71819020010586A750426A0E633BC787
+                               6E228E2353AC0A68533C85A742387800
+        stream[65472..65535] = 196F53D41603BF286D1D11F012E564E9
+                               3C7FEEEC9539A015D49475DD8CC73C84
+                               2F85521B4DD9789A813A59D444AEC702
+                               164F669C59B43B5115202D08662D4EC2
+        stream[65536..65599] = 8A7B672621B0B77E8BA8EB9A71DB4558
+                               A78364244F182519F89D25D3012CF8C4
+                               E429DD543C8DC56C6DB8FA5E351BF615
+                               106B51F9FD00F54018A94DAA91D76715
+      stream[131008..131071] = 33EC15BB2C553646CAED9ABD83F37ADF
+                               AD3B3313A074B69FEAD405BAF897C3A3
+                               E12BFB2F4CC3136ACFDA284DA1E780DA
+                               B3E4D34C053302989FE6A79A1EB0F5D2
+                  xor-digest = D899BF7CD2972EBB7333D4E57DC809A1
+                               B717373577B15544443915B36ED162E1
+                               25452584F3E0C2B62164092219FBA924
+                               31C1FF2A14C8E2E437427DACF80A200E
+
+Set 4, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 8EA023E23D94434EAA064A4BE52866DB
+                               57EFB7B200DAFF5AF2AA72D3E55EE5F4
+                               5060FA89024F259CD2490C628452B1F0
+                               91020DE10263BA86838B2E388F5AD040
+        stream[65472..65535] = 5BE1EAE0077FCE5C2C21120EFD560A96
+                               27C3DA9462BE42580065C9E51B7D36C1
+                               D9D717DADF4A3122A08303A8E27721E2
+                               1DADC91138A2461713998AEE26F811D5
+        stream[65536..65599] = 482694A9797978003DFDA5183F00FF97
+                               9F38894BC92DC88418FF68156117A2B4
+                               EF10D76923A734ABCAD1A5B4224BBD08
+                               836E3765321045C3BF6A352371F82CAE
+      stream[131008..131071] = 614BC8A38C5F9E8507595E8F5A03484E
+                               C9DEC6CF52DECFAB008327527B822365
+                               A2038FF09411D7B952417C8C7375289A
+                               244D50703B73577EC272827A21BB917F
+                  xor-digest = CA9E6EC13B679609EA778447EEA1157C
+                               B366A08AC5A96A73D0B5E182DF24EBD9
+                               FC297219A0AF67591BFD68B1721B5970
+                               8EBEB3655791107FD2A0F2F2E341FCC4
+
+Set 4, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 5BD3D0625CEAA75ECFC9828179F7B73B
+                               288A208D60A2297F2C328DB0789BC869
+                               4E50F50E8797F8C7A49E24F72A3AC359
+                               796E6188C71A9B3DB88DAEB1BB2C77D3
+        stream[65472..65535] = 726C7D7AD756CF567E0E8F812A282675
+                               7E75D593C7FCBB45F842020AD59F2B53
+                               888354CEF541411B92C3AF6D57ADE7E9
+                               273805927DEEBE552B32D10754C9D2E5
+        stream[65536..65599] = 5703464C0AED290E65815D8D04098B0E
+                               22D2FA825ACD4391B56CA64CB8201BE5
+                               7B4FB9ED6BB7608BD820436146339559
+                               E7464BC13A8AE3167AFCDA58E3C017AE
+      stream[131008..131071] = FFC5787A10E340B07D08160D2C4F653E
+                               407857845A0D68D1EED8EAC0116CC376
+                               E33AF8A1120D8DCAD6C86B757AC50393
+                               46AADEFF012BD0DAA294DD240D87A98C
+                  xor-digest = B3BAA21AA82617D3BB9C2612E177CB71
+                               51A51790D97FE33C3F33C01B32091758
+                               5766643C125293E1F75D6BA3C46AB381
+                               75A2A4934D4C115A6A1547932B077A58
+
+Set 4, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = AC5DEC8B95C89F4794B7289C69FABE29
+                               F4AA64476D057873D87BD524666F62F6
+                               B71B5131BFB897AE64F2D500437E1798
+                               A742E7B7D06B8089F3DB2453D008C554
+        stream[65472..65535] = A2F58800E24BA8B754C64BAD9252BEC3
+                               ED1273598EEF4C6FE42FE2CADB81F220
+                               26A90BC88B43F2F1FD2E054E8EEECF57
+                               A114D087D5228CB276FD5F4FA3ECF4FB
+        stream[65536..65599] = 5C67BC8E188170A57DB85ACD2F7121A3
+                               7D83F1A708ADC54C14064A9559FE7E1E
+                               3F9E60B9670EA4394521B11D8283EE42
+                               12874323628EAEF0B90FC4653106D68F
+      stream[131008..131071] = 8AA6F8A20F7D4A0B7EBAF6A7336B6D76
+                               731E65DCCD179BD53F6B879E70B8776C
+                               6A8EA30BFF09BA3026B3827EDB9F9C2C
+                               0F96655D8B84EF725D0603F8CCE3C2F6
+                  xor-digest = 458DB66B656320F5F7E4FEB12E748C0A
+                               59F0CD8A7ACAECC25479C309628EC0B5
+                               3B441B831B484FD3180C52F63EDA1858
+                               7C232B195356996DC29DE6DF54E5BB37
+
+Test vectors -- set 5
+=====================
+
+Set 5, vector#  0:
+                         key = 00000000000000000000000000000000
+                          IV = 80000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 635990D909A80CE2A75E521ABF588B6E
+                               85320D2C722D1C93B42AFBE6358D6E2B
+                               F2BE933BC961FB50F9A2B55389A08CD7
+                               A0131F89CF0E61D0C7071DEA6D8DD4C2
+            stream[192..255] = 0F92D4DCC222BFC7020CA6BC3D044F69
+                               12D9A93668C65401C570A01D6BF6B3BC
+                               A6F00F6FF46AAE3C09C6158EF05A520D
+                               F8D55FF27CDB7AEB5D03C1FFCE7B95ED
+            stream[256..319] = 664CCED71B27680F9458952173BE0043
+                               D3C27F35F9CEE7AE9D783ABA671C4FC6
+                               8F2815DC904316BEB39020F646041276
+                               5BE5500A60DE2209961755C1BF96E1E2
+            stream[448..511] = 8F02C1FB389DD1C5F0CB730ADA528D37
+                               DD778C4782C7B5DF1961F97CC82B63E2
+                               9CF4BE512EE27B50781E297D1633D700
+                               1298F13FD8AF9D1EA83F831A70EE50EA
+                  xor-digest = 3F9A4D249220E1AC8E559399FCA23DD1
+                               1A250DCDA841502F5FEF0F5D4EFE7E46
+                               D9B1E5E4312903E290D695C2B681949F
+                               480D45F78FD69597570338049464FECA
+
+Set 5, vector#  9:
+                         key = 00000000000000000000000000000000
+                          IV = 00400000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 8E932D78DCDE35F1E5B8B2E863859A64
+                               7AEE8B0867F6F221B09C37B7A78B4043
+                               D055164B1FF1608EC17F3F148FEBBFF5
+                               A9FCE4158B33D2CAA4AC5FE5551C788A
+            stream[192..255] = 7034BE31CED03DEFAB3F69A24E622BDD
+                               9B202ADAF05D0324EE933064ED6D965B
+                               937FBC8405F0D7236AC28C320CE66C06
+                               C5B93EC581FDD59ED40102C651495EBD
+            stream[256..319] = 37C4EB0E72191FF0F70C8A70F475061E
+                               A0BEDD8A9AF1901FC6BB5482B5A29469
+                               06E8C40249E02784896D5D42387127DA
+                               CDF1657A66E0D43E6F69632519D1D3A1
+            stream[448..511] = 8CBE98126AE27A51146FE05F40CEA89A
+                               39781F515D621DD48B6D6234F9AFAFF3
+                               6FB862084F5249BCC0018E8FBC090121
+                               E227FF494BC180FF68EA2B134E7B00D6
+                  xor-digest = 24556A29026E3CAE101E7112B2FE5BCD
+                               3D925460B66A9EADDC271E39C317DC27
+                               51DC9254491F76F9163AF09AA5372F34
+                               1B76D54C09DEC9419F839E5C50F1957C
+
+Set 5, vector# 18:
+                         key = 00000000000000000000000000000000
+                          IV = 00002000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = AC05D72564EDC8EB439A95579D04BF65
+                               592AB1024152B9B14D71B18FEB5374A4
+                               C07AA2F58EB2E45F737580241CFB9C0B
+                               842F8CC9230B540FC50A590DEBDC29D8
+            stream[192..255] = 48AB7E018380336AD0CFF37379D9E370
+                               5B0C938600C6713FF4CF5C142F640FF9
+                               72CF147E7C38389DF426FBF560E7DEF8
+                               41B4B1CFE6A4E2DB4A85505C931FFFBF
+            stream[256..319] = E9C6536F67F4B3053B353170CC5B77B3
+                               06A47B759A5FEE5BE45842C01E11519E
+                               5746B056C86D8A6712446949DFFE6935
+                               8E4512E7BBD6E6F544CACA98BDC723E9
+            stream[448..511] = 731EF8977E1307CB5FE80BD4F89025A5
+                               AFEE3E54F7CCEE6556A211097498827F
+                               6219704F96652420BB9EE830DB3DD940
+                               96987BAEC5A43526FCBCD85C9BFDB209
+                  xor-digest = A37E582543E75640DD988C7FB5579D43
+                               9C41669EBCCA5580184743BD54D24CBE
+                               E32F2B1433CDBE51E8208C78FD739CC5
+                               4E2A37E16A7AE4F2193ABC4F04C35D23
+
+Set 5, vector# 27:
+                         key = 00000000000000000000000000000000
+                          IV = 00000010000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0B295517E5A2E100C262736DAE920F2D
+                               26C40787AFEA87FC34C27D6E0BF98A62
+                               53B695751F9095C8766184EA44042F2D
+                               6DE099A80C75DB1F33F53EFE578A8F0B
+            stream[192..255] = B54C4F2EDF17A1EC22F536586A5BD691
+                               2008DA6642C84AFC8ACD35A7DAE73F79
+                               C835D83F4C0C3B1E510D1BB42013A872
+                               8E4899A8CE134625698CAB31852AA7D2
+            stream[256..319] = BBE2221921E73DC79E795AC0AF9B890F
+                               FE88A14DA29DE45FA38F4C3E94E6BE9D
+                               98238BFB181FE664B4147CDDC125FD06
+                               D11A65F1975A0D781024DE1EF026DFE7
+            stream[448..511] = 83E61FCEEB1367635632B45BC73B8B39
+                               165015E7A6B8D9851390D4CA9DCCB935
+                               F09BDF52883FF37BC77DE94842E39BBE
+                               0BE530FC9D3B4564E11B7EBAC8083818
+                  xor-digest = 55242D44DFDB1A747071F1C825DB5620
+                               EDE1AF37B6D73A22264B14F7D35E4412
+                               4A6242C5AD34B54E98738D6CC90FE355
+                               BB9402DD017B6678FCC0EF27CF5D67C2
+
+Set 5, vector# 36:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000080000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B89065FE0B458C64FD6EDC6A893C8C81
+                               83578E7D37BE97E6FF82E45110A25960
+                               49A817CDE859B67B56CB80768D6DD275
+                               6EC368FBABC35C8B51C62AC92F913281
+            stream[192..255] = 0E0AB045409ADA1A9540504550404B8B
+                               2C38384E577F2DCAD5316CE7E806A0F1
+                               21D2A3298F71F301340F3C0A9CDD4815
+                               936F16B4EC229E63451980646D45E3AB
+            stream[256..319] = 1DC37BCE039878BA2E5938E4563D2523
+                               7350E41C8EF9262A9EF7D7FED7E22F45
+                               DC3E98EC981D2BCCC1185857C627EE20
+                               C86DFEF500756B241320798764C3C09A
+            stream[448..511] = 9A0082CDB35BB3CB1C74CE337D944D3B
+                               2C833B4F786A92DEA4445A2E5E101384
+                               AEA834F5E01C1B37EF8291D039875A3E
+                               21D613FC71212DE686AE52295B773E42
+                  xor-digest = F94584BB343C6BD6BE3AA1EF799989CD
+                               93F6DDB6A9AC7E2EDFC92460F0905E6E
+                               AA3E81F6E173C7F9FCE8FB5D7B261A58
+                               3FF006AD017A09FBA3B3D084285169A6
+
+Set 5, vector# 45:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000400000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 486343B348F2A1726617D6E93989B000
+                               B41FC9707E2A99C7FE5CE9423DC3004B
+                               67EB02F45B368F87FF2C4CC0C59D1728
+                               9F713E714E049CFD8E5D593255092A7B
+            stream[192..255] = A1A3127E632EF47679F52224E6D5A16A
+                               6E0598271F36F4DAA98B115535E77C71
+                               84170D2DB4B8C5D804790A666D105108
+                               81213A0684DD4AF03DE7707702F4F73A
+            stream[256..319] = C917B1577463E05F34350C4C7F6CBB5B
+                               D63B2D74EAF1500832132CA1A1F289C4
+                               3D93BFDC5E9D91897D2F7E05740F3C95
+                               0AD872A93DAF3850A452410FBD706A92
+            stream[448..511] = 11646E84240BB95D1B14694785E7E119
+                               848855E462DD14176442B8595CF602C2
+                               D1F4A2E09B8D7DE28382D1DA4DB3B1E5
+                               910DAE6ACC02E79FEB07A8E55747046B
+                  xor-digest = 65E9982A725056B8FBC275052EA48C00
+                               69A1BA0939831C4014E81AAF14F66FB0
+                               E01FC0C70A49C4533ACBF304A5309F4B
+                               60D6B310BC66C6684BD5B9C83F994E95
+
+Set 5, vector# 54:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000002000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = ACAB34102EDDB67B8A5D8B135BAC15CB
+                               1CD52AE386364C709C2B9D6BD322D7B8
+                               477577B4958D448A3BEBA473D861E592
+                               CA15371AEA0F500361CBDD865488A7A5
+            stream[192..255] = F25DAF77D7D734E5486A1AAE01794FB3
+                               C17099E01489A5B4213EFAE6D745B798
+                               77939C7A178D1FF09EB2C42A8A3CE51D
+                               59D501B36BF9E4960BF3FC8D50F5A847
+            stream[256..319] = 1C9C6F63998627AE1AA7E8F0B2D73A99
+                               707256CDB12E3AB239EFA72AEC516FBD
+                               6DECC9375EAAC634707A139E59B32B51
+                               5D25ED6951FF4228A11DC87E8DE61385
+            stream[448..511] = 6A997977A25F4E9E0D9AFD8C20B56EE1
+                               C702C301528E332BF8F5E7DBEEE5CC28
+                               C9E12E1A8BD7A2118A0F31F800B574A8
+                               2FC44FE19B20F1D3396432DBB02DACC1
+                  xor-digest = 0B2BA364EE76F0549A10200D129196B8
+                               E2B69667999FADFAD55CA479AE679C56
+                               54A453C43898443B9DF2835AE806C2A5
+                               EF30CB8AC25DBA756A705F66759029FA
+
+Set 5, vector# 63:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000010000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4DD010482D0DB2D09D76872D25F73B26
+                               749FFE70B9674587FC4CEDBA5966D217
+                               489244D0177F676188A1762C430DD8F1
+                               5ED9F7BB67F2E8A79F7633DB7B45CFF3
+            stream[192..255] = 3587F0A7B9F410D45357626BE10B4EAB
+                               FF8798FECA5F91F3AD2543B301B5C301
+                               F84404071C7BC77AC31E423E1AB1E2AC
+                               2CFAA37DBC2A1316D16A5C7BFED1A77B
+            stream[256..319] = BFC632891511228ADBA0211EF390A7F8
+                               08A12AC6BDD7C2E29DF27025EBA1A6EE
+                               00B9718FF2BC003904C1C28878894AE0
+                               E5CE5E9F55CAA522EBEF5747C755CB73
+            stream[448..511] = 513D9FFA86D8AFC20E4870DE0E9B330D
+                               76F02E44A6C4D7C5270B89C6BAC9426B
+                               5A12666244C0CC5A641118B93F72668A
+                               B7C53CD7FAB0940F1B37A85015DC91BE
+                  xor-digest = CACA8BD50E28720128B57B37D45DFB02
+                               206D53785FCE81205AEA085466142DB4
+                               A17F841156916294F3B7CA93CD99CB12
+                               93FF593B5105D2822CA9BC3BAF178935
+
+Set 5, vector# 72:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000080000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4DB6CB1D5BA89BA45BA8E3DFCEFC444B
+                               7D97C73F53EBC50BC46047CD76499CF1
+                               FAB51AA6C8B24118AC4EC8E49192B41A
+                               2812AA1A4325418AA6C69F6143F0A6B9
+            stream[192..255] = 33FB647044F3918513212D3538C31662
+                               1DD9F3A10C0589CB718564CED7ECC391
+                               D9701C7A23AD48E05A79BE9E32F60819
+                               3E57FA8D8EDDF9F43F38BF8BBCBAF52D
+            stream[256..319] = 79F3525A6EE300764DE481C20A40135E
+                               94362F56DBF4C5AFD214F9D4039A0899
+                               F74A7D7C27494B39D1B0145B9F691B5F
+                               F436F2AE8B335EC62CCB0FF506E0240D
+            stream[448..511] = FFE0E6B8D741377FF1A02764FEE3D681
+                               6CD020C6DDA5097989137E9BCFFFD35E
+                               0E6379AD2ED3D9D298C6B98DEA82DE6C
+                               2B66529C860DD4ED56265CA09B16A8A3
+                  xor-digest = BEC66A4FEB220D732F04AE0B98FCDE2C
+                               0B70613BAD57D7590E007E84AC546B09
+                               AF1D5BEB509CFE5523254B5FC8CC2672
+                               215C67477AFF14D0788DB166C5B4B12B
+
+Set 5, vector# 81:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000400000000000
+                               00000000000000000000000000000000
+               stream[0..63] = ED4C49EAEBE78999C0DBC4674757D435
+                               B056A45036DC51B390A6C87B3CE8BCE8
+                               2C7DD348C7775D2402EBE359E7895FEB
+                               B9F44DB5D0F7B40AC207A3CA750EF25A
+            stream[192..255] = 32F897ACB5CE63D1A64781524B1CB4FF
+                               9E595EEF93A3206A0D1B4E6F4ED7501D
+                               2DDFCA31B4FC1A33F589167B070FC003
+                               F67C528B6AB99ED308EC3CEF82B4E2F0
+            stream[256..319] = 57CE29261DAB385309C97955261874B7
+                               676349DEDF7582B7654D1A8DAA570EA5
+                               9745D2167F2AE1ED538F1D0ECE53AA38
+                               379F9AE542EBE229D561E34ACB28FA14
+            stream[448..511] = 667E22A8BE7BB84CA1B1C0848E5F22D7
+                               E98E54A79D5A960C33D07357199AF1AD
+                               53F3F803EA698127C22F75F31C40656F
+                               8C28818775B3D88460CFD29798187537
+                  xor-digest = C68E7F4A7CDB68892794933392C1BA84
+                               5B6B7CF52B8421137EE0220BA67C91E9
+                               81B47F9BFC39FDFF9DD48F3617F2D523
+                               0680B87D18A821A09525FDB79DE6FED2
+
+Set 5, vector# 90:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000002000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 80FC6D794178A189EC423AF926622982
+                               60C44DC5DD5AC91F779D02958366CFE2
+                               C5551DE2A5D635353757AFDDE68DF592
+                               A034D87C871D7D871264BB0F89E99536
+            stream[192..255] = 0BEF31DBC3F3DBCC5B3D28BE296384D5
+                               D33DD0AD9A80D4AB8F58274B4397A658
+                               94F67376AD8DCEC19BC2C74A835D9F70
+                               1F4C60DC256DBA4E83B21D36B66F5DC8
+            stream[256..319] = 625DDFD8D922D848380D45D6D7E730BB
+                               049666B3900E4305218BB7089D059FD5
+                               825F9EAA3AC047A006F1353C37AFD11E
+                               0143DD68CBE9543B959E26ECB4C649A1
+            stream[448..511] = 636E6EB97E3127EB703D5170D2C8FAF8
+                               63E8C333F5EFEFCF9063E3D770FF9E0F
+                               2B37396CEC935239797FE430DA4CFFB2
+                               9B19D833687318DF01750DD2F3D942B5
+                  xor-digest = 0865679CB53BC2845A0B71AB820F61AA
+                               9B99E100AC7F0358D5B610C09EC52C7F
+                               8C7C5D973CB85B18F8990F3BDBFBDCBD
+                               13071BB3AB3F329E75A44E80320BF86E
+
+Set 5, vector# 99:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000010000000
+                               00000000000000000000000000000000
+               stream[0..63] = FC2DEE44B15BD914C17DADE6645A0250
+                               2F40B39C0C6AA26C0250D328112AC67A
+                               0C55D48700EFE67EFBCED927B62427C1
+                               41DB8089774E2DE23C5FDDFD66D39BC3
+            stream[192..255] = B6A4D34FC81937580BFC32E04C8E2B20
+                               309AF3E2152B98BD748A344D4537788D
+                               35B16DD2C01444CAAAB8684916705C88
+                               FE75C53D75713FFFFA2693E91395F919
+            stream[256..319] = 9E619BB0045C58C2D303F79E659CF5E2
+                               011D619E0CB10CFDD53AEE6812DD780E
+                               36407CFE9BFC1C73C27CBBD491BB6A7E
+                               8918023EFD6E2227C0C840F1DFA5924A
+            stream[448..511] = 2A320747019AE86A59D5422B634448E0
+                               B43C41457428AC7A4E5D0C9D7327B44B
+                               BBB6F64CC2423299C009E5B24DDF10C9
+                               F87F2A525ACF803C50837EF6C2FF3D34
+                  xor-digest = 3737C19DCC04C7C72EC9280D53C17E64
+                               E9F4B1E47980711DC64FE6D3E7DD05E0
+                               DEFF339F38868B1F7CFFAD4298127949
+                               11EAD4D34047B22B07C397A37F6BD2A0
+
+Set 5, vector#108:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000080000
+                               00000000000000000000000000000000
+               stream[0..63] = 84F71EA20D46B3802A787C1322DE6A79
+                               34587F447AE7FE277362497E4FDB69CE
+                               129EC4D8D80ABD0C15026EED3DFE2B6F
+                               C48C5DF09CBE035E348A22F8A2AB7DAA
+            stream[192..255] = 6444791C6DE062EB9A494AEB910A458A
+                               DE3D834BD6F87F26A9D6F99FD970C820
+                               ED9FE0DF88A924F97945B0EB10E5D464
+                               559AA278DAF6A942651E06C66D33F7A0
+            stream[256..319] = 1878644E35B3BC562F82647D45C84317
+                               769BACDB95DCEACA456727616BC90FF5
+                               E78FEE1EFB86A714CFCDE79AA9E66FAC
+                               D600B0FC5C471569BBEB5692E7D9616D
+            stream[448..511] = 54BD56C4F0F3A0CB89A678F2912E5B21
+                               C2B225030E82A90470EB6040F50A818D
+                               C91F65BFFCEA3F9041BF110A762DE3D4
+                               B41A8D1E18CAC776063B2DC93BC2D02E
+                  xor-digest = 52E18382B88883C5648E067675468200
+                               2AA9AC5C18A856E89175C449A6033501
+                               87FA4C17A4D36269340F0877385A35AC
+                               4B7FEF6E1463D34BCDF3597618FAF352
+
+Set 5, vector#117:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000400
+                               00000000000000000000000000000000
+               stream[0..63] = 3F40E9A3C872ED15A6AA296F716E095B
+                               F39153C7C6F4ECE6F550AD35582083A1
+                               CA0DC3CD817AE3946E43AA9C8700420F
+                               F0DFC21B34F4E5E40B3EA14299EF468D
+            stream[192..255] = 853C4A895DCBE411B9B2E340B0AB55AC
+                               8EEEC42885768110ED7E1CCADC10121D
+                               8DE12AFD0DCA4507A8A7A2650FF68C6B
+                               5DB1DD670C8C68365E846934D16A46CC
+            stream[256..319] = 565AEFAC0325093EF87FDC51413BD5E8
+                               56AB6C90FCE7D3C6EEB7E58F22AF63D6
+                               73BCF3840D611A5E1102E9A4108CB902
+                               5A1D837510A971536231CA247965379B
+            stream[448..511] = 887287B62116FE2A28957ECC71DE5BA9
+                               CBBC16DBFA4EC141EB617F9314FCD238
+                               91C4237FA35871C0C795E2F3A4197DB4
+                               F81BA4A29759BEB5FA2277CBB9169734
+                  xor-digest = 78E564BE9E7102E2CB009D7A540395C6
+                               188C8499B7E96C0AD709C3BA2C341741
+                               6EED55AB00AE5719F25CFA06F1488E83
+                               798F18BFD755B9061AFB4EA5D864FC24
+
+Set 5, vector#126:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000002
+                               00000000000000000000000000000000
+               stream[0..63] = F4C281D9C88A7FD6B2CBA9EB0366C594
+                               59327932DBEF8118A7A680D0F0AA41A3
+                               735FE0874F047D2B071B5B9E755A7B6A
+                               9426353B923A5913C647A88B642B2C00
+            stream[192..255] = C7DAC2AE7631D11EB21EF15FDCD3EEDE
+                               7DC98A7060613A643EE8A944EEB6C7D1
+                               EDE08538E1BA6092ACDE0C648D29AF5C
+                               309CFCBC4F40A713FA58D93C954961AE
+            stream[256..319] = D1647D6453798B7E15A49199134384B5
+                               C9BDEBF7F859F6460C2666F297410070
+                               E68307CA78790EF01D160D94B69729D6
+                               90A4FE477A27AFF8B254875C98116485
+            stream[448..511] = C6D3DCBD0E9D4746B142C819867E0A14
+                               8B81FEE3D1007E907F8E9D597EAD63F7
+                               A87E6F224C67CF8162C4E92FC1BE44EA
+                               FE3715B3C1C432CC660CCF1536A20F46
+                  xor-digest = 59FDF05B6D16079B7E18F6A8CE0C58FF
+                               AD7C985C01A12C07D1ECEA740A92F761
+                               FDAC3F96357498B5F5FBA91DE6502A86
+                               1332A1B3E85C5E72444A2168C25D6FEB
+
+Set 5, vector#135:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               01000000000000000000000000000000
+               stream[0..63] = 494BAFEFE4FBF2C406F55FFB436105BA
+                               09211B71DA446A0F5436E6DBF42F8E1C
+                               C805E797C9987C14997083E9004473E1
+                               B2B3729DE9B483361CD38CC78C982533
+            stream[192..255] = 3C04C6633F7D8B714E8549AEA1851035
+                               A520EB6422F42B2C840C74CF51A13FA2
+                               9C1875212E8DC07774D6911415F1C305
+                               9826A05DA9F09942273CDB592F7E3A6E
+            stream[256..319] = 1FF6BEFD79A7E5BA0DF64948BA0ECE7D
+                               ABFB3883BF8A95D3E76DEA30550F5C3A
+                               2B67FE2AB78DF091E758E498418EF514
+                               089283275588A41AD20D53E6394635A5
+            stream[448..511] = A4D10D3B6AFDF415D49FB6ADA1245812
+                               1DA1365ECEBDB6C2508F1EB92E91E8EF
+                               90892E6FCC9E70AB9A2EC4D49A11C197
+                               68E6B4C154A4D65C55AFD38B2BE3F4DE
+                  xor-digest = 91D4EA4C6ECE28536C415A6AF46DC432
+                               3B6DC2DC98C3A3FE2BFE53C8FF556C16
+                               0197D655357512A808415BF757AB3A84
+                               6BE7865622D32B7DE3867B3B096408DB
+
+Set 5, vector#144:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00008000000000000000000000000000
+               stream[0..63] = 521913EA655235FA0E713B0DA3ECB98F
+                               7AB817E70827D29E75E3BF2729EC2AAB
+                               8747B8FE0FC9489B6E0EFF45EF985980
+                               CC0189D9D0F2EF34E809D992E7695D9E
+            stream[192..255] = D265AAD80EC96DFF08859F93B236136A
+                               BE146981E919C0554D64FBB7D03DC9AC
+                               9021F2A1B39866567D8BA1DBE2C3CD21
+                               E5C4C94085F7083F4C640E918C4004F1
+            stream[256..319] = 7DCD3CF623332365E6CF2D92FD147BE4
+                               1E532F51F939C921DD4492E026993E56
+                               843ECBF0925CC52D56084E7F2B538653
+                               2020DEE6FE7E85D4A89AEEBD5F3EAAAB
+            stream[448..511] = 00E20611C7ADFC3BD9E59B9E6D7ADB03
+                               F87FAAB01D7771B89299BDC59E1E2EAD
+                               FC9FDE416B62FEF07AB7A816AF261E77
+                               FCF79DBEB09323D44B5956CD93AAA990
+                  xor-digest = 0578B3E20EBF98D89E2DE82A6EA8E34B
+                               424E526CF419713F0AA662B852E58BB6
+                               7ED570D75534E1F23F85F160690A464F
+                               122CCBFA5CD1DCC0969F2E57D65D64F8
+
+Set 5, vector#153:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000040000000000000000000000000
+               stream[0..63] = 2617095641B825094DE44205319CA853
+                               418588D5B6BFC05A2713CF898DC42B3D
+                               6ABDDF4C287235438A48BDDA49E5ECF7
+                               EFA235A23BF667289612893708704F08
+            stream[192..255] = 04F668517ADC1AF6E31DE6B7007ABAC3
+                               59A2DD6DD61755C6CA7053E05FBBA2AC
+                               D9AF682EFC71391EDA4A5872B53D7CFB
+                               BD35ACB719169283EFD9FF9E172269C4
+            stream[256..319] = BCBA3F15D83B9AD41317AB9EF7DFDF0F
+                               FF05CDB058AB08D7BBD720723E969CAD
+                               79F16D26DF0222CFF4249B839EB9F9F1
+                               422EDAFB8EC285F27E347B7B4C9B2C23
+            stream[448..511] = F15F17F38917DFCA9141314047595C17
+                               047F91E4859D849E9A6339F640E3633B
+                               6A1B62D089B24062BA5987C3FAAB6633
+                               99698CDE6FE7A461F127AF67B2C5CFBA
+                  xor-digest = 68B2369B45F059964A1FD3822DAF61B7
+                               82A9FBA7EB563F83DEC4D058CA5D8931
+                               EC74AF4043FEA803B696791C8E0A675B
+                               DD8982AEA862BB76847E1DE12F2A5E86
+
+Set 5, vector#162:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000200000000000000000000000
+               stream[0..63] = B090CC267B29A95ADFAF6BE3E147D647
+                               21ECACBF6B7D0C4061D17FB7DE0A6662
+                               6D6F9FC167FB3FFF237C240AA03FAD55
+                               13B6DA848F22796DB501A8FB89F2B85D
+            stream[192..255] = 1CB95ED9AADFA0E1FFE5704BE69CBA3C
+                               9593746AE87F36A786E5EBE18A1D3B25
+                               F4785EEF4DB439472035BF053687C5F1
+                               0B60EF55A76DD1994FBB482BBD250755
+            stream[256..319] = 826BE3D679C872536D55C3F0E49C2624
+                               D41726A4525A50CF91EB71E7CEC5AC47
+                               F3834358E2296CF0D04B8D8CE8A701B6
+                               6AFBBB8776DB2B75F1CFA01231B365FA
+            stream[448..511] = 244DB28A98619907AFFDCCAF303A3795
+                               3B6D21EE6D22780C4D3C939C084E4181
+                               1FFCD8F2DA2E6A2243BD0B5428FB86C1
+                               F0EA2E8C8B6950ED961F4FA8CDFDCD17
+                  xor-digest = AAAFCEB42F2EF40C4B5462307085434E
+                               E4399F87B4AE5CA828A952A851F47913
+                               A51430A8BB9B3CD0A4B2F12E297F51E8
+                               FE0B1A6FE0F21177EAD9284087D3706A
+
+Set 5, vector#171:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000001000000000000000000000
+               stream[0..63] = 0F4309F63F237DBB51567573126F09E8
+                               E49990F26E541EF888B9F2922FE9D280
+                               C8FF4874C0D4FA3F41034B82E2E026C4
+                               594A79C2B689BC502C41244DC1AD472D
+            stream[192..255] = 95DCF9685E429DEC2833E1B5E78823BB
+                               ACD9332D668C4B342B89A290E1CA6127
+                               B0E5125E44445A1156A70B27966C3E0B
+                               4E0BCBDD9F4561998A5CBCFAA05C7459
+            stream[256..319] = 0886E9887182156005548CA1A08B57C0
+                               E9FA76C2A694E1CEE22E9B715E99B115
+                               9AE064DE644FD580E8356164A45EA1C4
+                               3DD85E16158B5130AA103267C8118105
+            stream[448..511] = F8AF6F9992781BB09808B7AF404F6546
+                               6FA697C2A1BC9BF64F8D6B6D8CA0B856
+                               6B64E6BF0500F6D80113D9457855FDCE
+                               1791C7436F5FF41ADA87562C175942D6
+                  xor-digest = 8D32FFAA409C8CCDA6892C388D5D654B
+                               4AD50ED00BA649737BA8F350811A2AE5
+                               5C89463C7D63F1F1F16C4007826C2CF0
+                               E4BD9453A60D88BE86F60BADC3E71E98
+
+Set 5, vector#180:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000008000000000000000000
+               stream[0..63] = EBABC8B756971D46C1A5E86CC7AEB329
+                               4DEDACFC795F2AE02CCAF68B933DEF4A
+                               19E96BA64DF14EB6FE67CA48861B49BC
+                               16052E33C8B47556DFBD96037B7DE5F2
+            stream[192..255] = 0438A8CF718F4C52E33DA087FFEC01E0
+                               459D26757D5DF55D5D7BC9BA88F57EC0
+                               4B84D854374F95317CBDDEE928A2CCAB
+                               E4BA1BBBF47776B29890DF00D864FBD2
+            stream[256..319] = BC4A80F9CACFE63D2E54044ACFF39F97
+                               2C69015058AD3F81CBBA28FB0987FFCF
+                               9CD1F6AE4F0602BAE2B828D3FA162936
+                               23CF3AC2950BD651F7E467DF8B454BD6
+            stream[448..511] = EDC95FB80C9FED4A73D6EE9B2CD74BB7
+                               E6DEB9E7868D40FC49BD1C52838457F0
+                               88DCB29C2107066D55A80908EFD1392A
+                               B4F2F13C0A79F67E58C91A89A5C88991
+                  xor-digest = BECD7FD2014BB9A25701E69F9788FC84
+                               1AA9DA56CDE1CD93DF45D28F29D32E22
+                               F488B0C2D9FE95B267CBFD35EDB2F6E3
+                               05DFA5A2CF09D7E2D13348BC0C9405E2
+
+Set 5, vector#189:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000040000000000000000
+               stream[0..63] = F28A15A90386237127A5682EB09E0E58
+                               30709455034A7189AC9710DBB50D5012
+                               9EB4E0E9036D4504054B281F3FE9F45F
+                               C80116B8FFC0B42F9A636A399B7A8BD1
+            stream[192..255] = 1219EF9BDC250E88BD0A62DDCF9AA1DB
+                               B62E19FBA748DFE1035C6A5B3B94954E
+                               1370487A455916F7DAB451F79C5E1298
+                               F549CE005A1321E6B136B59BAD9EBCD5
+            stream[256..319] = EBBE81DAE5637C4C7EE6FF9251D5407E
+                               DF7E8EAE384D1E588CAD39AD9F763004
+                               9A8E028120B5065B658EF3E2B357E52F
+                               F18891819EEE3EE021BD1AF08A4B1F53
+            stream[448..511] = 50086FCFCF5EFFEDC4A52B0212B7321A
+                               8664F2976493868F13D7CFDFB7583E99
+                               EBA70778A83CB88850D45B300F7F6A80
+                               E721860560B2FA642B2E77C7F7AB0662
+                  xor-digest = 336516670616300FD5FB014C1076B53F
+                               6637AD0EFB453615924396785CA4D284
+                               B03F526FC2179FF3BFB0A1A2ACFFD87E
+                               EDC4C8360DFFC132CE6A502EB173A0D4
+
+Set 5, vector#198:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000200000000000000
+               stream[0..63] = 93261A7231FD030CEAA974BBF8F3A721
+                               33334C5F3B25D5831B203C353A566D80
+                               DA578081A047E28DDF8E4BD5B68BE4A7
+                               FDE4BB3A4875BA84553AE120ED77C9CF
+            stream[192..255] = DEC4B603E6A6F911B68E5C1265FA2004
+                               71B296A647D20C13E42202C1A3AAE880
+                               305F969BB88002C8FC00CC5DBE40AA06
+                               4AF85646AA8C7F7191FE26FAA2918A95
+            stream[256..319] = 849431145F27957D53CD355501363E4C
+                               5F191DA666B77364E5866CAA16A9DEF0
+                               DDB9BC266EF41DB0C2A7642B9E8DD27D
+                               60DEA6E69052D4BDE9FC83B2578C72E7
+            stream[448..511] = 5556EF9874E3150FC539C9BD3BAFD308
+                               8FB347D5E38DB318A72AE0C6B6FB4163
+                               082545A9AD8872AC383A78230729D083
+                               31BFC3F2C80DA20617435FFDF2529A7D
+                  xor-digest = BA9CA5F3C27246F931824A9A425F2390
+                               E183188FEDE5BE3591053ADCC933E1F3
+                               DDF5627A94F80F8922F53E951490E96B
+                               F51491ED2D6DA26F3BF69CC41B8C0C98
+
+Set 5, vector#207:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000001000000000000
+               stream[0..63] = C449AF4CD437641A3B40D0E0E7B5696D
+                               CE973B3B217E02DC20B2F5573FDDF78F
+                               E6E55D75CFAB8EE04C8962376D22A843
+                               A80BB79C8B8D8B500C4B6DA27748C398
+            stream[192..255] = D5C92B62B0818165096551DF2B007F66
+                               2DF953742EF0BBE97982FF9D3EE83E1B
+                               87EC9D710CF1700262B1CAA9C68A897A
+                               8AB4A162DB0443A43962EECFE5B4C0DF
+            stream[256..319] = 3B8CC7E847669AC6858B7BB716206386
+                               40D8C2DD259EE4970A5F254077101271
+                               DF745AD7F57712065E2D03B9D7220591
+                               5C8C033A4F9146EE561B4179DB465989
+            stream[448..511] = BA4ECB7D74CEE56CF1D5AB636BBD6421
+                               C30A51DABDCED17C8D50F5293424AFCE
+                               33AF71095CAAD3913A8A3A12286A8E91
+                               89DAFCC1E2E744FBF4B526E910B5F2CF
+                  xor-digest = FAD57A608E04CD71B176BBFADED7B229
+                               D855A8025E963B55FB83EC7311427779
+                               490F25D34C6385FE1C036FF0807E136F
+                               40C10588678E2414163AF1819EF7D3C9
+
+Set 5, vector#216:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000008000000000
+               stream[0..63] = 989F302DF6BF8C63F9EB69D2625115B1
+                               2CCDA42A2D33BC6F21BD55E0594DBAAD
+                               9A294DDFD6710E36000C27FEA7E03440
+                               C8A6E728716D0DF14E825B798A6C420C
+            stream[192..255] = 3F3140320AA02367512E7C1789F5C03D
+                               83CC634354237E78E16B1A64DBDFA6EF
+                               0697B28BDFFAEC311C6E2089BCF64203
+                               A2EC7BF3CA922080380241A47A673634
+            stream[256..319] = 6049048A5307D55D6DB387A6149C7B23
+                               0AE33195D53E0026103EB44489BB86C6
+                               BAEC7A0D920CAE25B1E7B9F07C07C4AF
+                               6485FF281C7B7FE1D61E660AE55C20EA
+            stream[448..511] = A6DCBEC85525FA19FA6066470B4CD83F
+                               17D42DB3353B327BF3DD6E7D047CD752
+                               71E79CCBD46E757F3654C2506C2B593A
+                               BC93B8985C491017A8E616D69E8974FD
+                  xor-digest = 55BE97FD8317A47742F8F3BB762160AA
+                               7FDFBA371864823D93EF6C029D457AC1
+                               2D679CB424DA9EAF8E4FE28271C66F06
+                               1E91D8F2EF41733AC1084F54330C9786
+
+Set 5, vector#225:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000040000000
+               stream[0..63] = B8989CF76BB1AE894699604320C14706
+                               E20C8BD86C016B5E2EF705AEC54C6023
+                               2A9AA961C10914A8D910D517059A93F9
+                               78C537767A057E0E11DBB5C9BBC4EFA9
+            stream[192..255] = 83FC232D21D0DB82747D9EDFEDFB58E2
+                               BB37362FA2B4E1AA0C9A58AE521EFC86
+                               C512831CC6D2E85FBD96FD3B60D1D153
+                               E83DDC6C5755899CF96FDF69E3732E4E
+            stream[256..319] = 201DDE5D82B754341A3452BF7DDDBF6F
+                               167B2A087900EF40E4268A80217D7310
+                               F1E9E25C707A1EC05219E3CCFEC0F6F5
+                               28CD98534F6C579A1ACD3171D131D87B
+            stream[448..511] = C2F68B5F03B0045FEE0FC92DA08F8545
+                               762F73E553D2F539C64B88D4FAC9B011
+                               DE0504D66007A115E428F627A667FA2E
+                               296F222734FA0F905548058897DEA990
+                  xor-digest = 7DFA65F57FD58891C5576B3CC7002513
+                               C1A983E9D31317B681604DA09F176AAC
+                               4FD78CE84EB9427BE8D6A63058582F16
+                               148D55B3C2544CF4DB9306699CA74D80
+
+Set 5, vector#234:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000200000
+               stream[0..63] = 307B13F3D3EEEA4C8FAF34416689F354
+                               AD26336D6B33DFC5AA004420D2DEAA69
+                               F69E531EB6D672AD62B2A6A136046373
+                               F70272E84E14CABA9AEA3102863A0B10
+            stream[192..255] = 8E4DA19FEDAD4C842917ECD5E7256097
+                               C2F524324D8A974D4185D8B11B611C72
+                               6C39DDB5E58180971DA181D36A289CBC
+                               1937E8F020645EC8D0363A58C6147F38
+            stream[256..319] = 012A99871D6C4CB7328C1374F37D0BE3
+                               DCC2232F6484A22C8F330D77316A1756
+                               71DF7CB32773F25D772BFE9DED5981B2
+                               0C3F0DDB2879AF61E7549F03AE26D233
+            stream[448..511] = 47C6CA462D35580BC0C78C6427FB96F3
+                               BB762662F5B52FB3938CCCEAC35884C1
+                               54F5BBF513970FC08F51C91059A757B9
+                               A8B6F1EFE467FAADA8D4DF68C6AC1942
+                  xor-digest = 6409F8C255BAE6167686F5F9C7EB2349
+                               0FC7BA4DCBC80006B57A5F56CA9F907F
+                               849C2A0FB0D74CAAFC0E2D4367E2912E
+                               BA6487D8A48DA60E48277A20E326266A
+
+Set 5, vector#243:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000001000
+               stream[0..63] = 543BAEFA799FA0CF5295B92EF3FDC07D
+                               69B87C1B5FF0A9F25B32F8FCC473D04D
+                               54B6E467D6183F25E3664A330889889F
+                               A530E354B6E53EBC78354100637A62C3
+            stream[192..255] = E15997D1E7C0FA38333DEE2EE2477A4F
+                               AD32F0810E8D3D65EAFB110C2B8D0948
+                               59DC45C4AA38B8050A87C23782E1A26C
+                               C193985BB0C3E754A528BEAAE1508D76
+            stream[256..319] = A94F1BD38219097B70EC0700A64B0ADC
+                               7BA8883B5C2C3BBABD0497E80D53121A
+                               2DC5A5C6A77913330EF5469871BABF86
+                               0A09F1474D893ADC28B473EE508F473F
+            stream[448..511] = A43AC01FC186AB42241ED3729E7EEA39
+                               F0823D124E8CB696E2F4B047A6B71164
+                               5B803623CD0371C4975217B3CBD7D9B2
+                               FD89D3B6BD23FD11FEC0B03B9CC22AC0
+                  xor-digest = 792A5EDB6E7FDBE99B7EC2119665C2F2
+                               34038F561BB1923F3BF493AE35CE2006
+                               55B8EE47490B53EBB481AB7C6B82FACB
+                               233AD86D74385FA108C94666CD34C164
+
+Set 5, vector#252:
+                         key = 00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000008
+               stream[0..63] = CB4377099B2D7CD6A982A1B1A53E05F2
+                               E097164EDCB381468C21D8F0615A654A
+                               45A4D09B7C0218A19496EA71CEEEAE5A
+                               886307DB0026C96049B60E5154F99AA4
+            stream[192..255] = 25FCE0B7E28D5D0D1654D912DBB21AE0
+                               288CCC71396CA5AA36AC44AB08EC72A1
+                               01E5B189535C1987B79DE4C4E32DB7FA
+                               48ACBC8F854868FC287E03D54752230C
+            stream[256..319] = D3B02A39A4E467C44C109E1E25593278
+                               2E9B3CCB02D6F107C9263A24E113FAEF
+                               847A9064E1AD1EC8881EFEB239CAD6C4
+                               E90ACEC36A7E87E002F35D477CD63F2B
+            stream[448..511] = 7D4282D7E11439C04ACFF087708DA22D
+                               236F1A08A6343704DA4D24EA3582253A
+                               35419183A915B571DDE80C1DEE2B8A13
+                               76EE973234FFF6A0DD91D31037F51C72
+                  xor-digest = D52720D8DF114235D99E5292E14DE96F
+                               9D8478E016CD40EBA25C4B9D8E11713E
+                               FE9AC151E1F39377FCC07D06E9BF6931
+                               6EFD7E27F87E9F76DCBF7831CC3FA98B
+
+Test vectors -- set 6
+=====================
+
+Set 6, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                          IV = 0D74DB42A91077DE45AC137AE148AF16
+                               7DE44BB21980E74EB51C83EA51B81F86
+               stream[0..63] = 914AEBA9E4BE90FD07AA58B6E2536B59
+                               0DD63BA810A2B96BAD5DAC1818722BEC
+                               61725C75B9E6194F57D3D2BBFE795E73
+                               90405CA97249262093234239E35ED9E4
+        stream[65472..65535] = 346C1A7D71DBB8FB69EA78F07D60A9A7
+                               20D0ED544149AF102C12678D4AE0C5DF
+                               E3521B7344F91977799085008EA00432
+                               772C0B4ABEC1DB2C47608F9A29CC76EA
+        stream[65536..65599] = 6F3B93E808687BE8E37A635E15B13052
+                               60ED65488A59125D84726219AEE62087
+                               47C6672C585759BA60BFD7F55AB975D4
+                               B61596A506F8763F715F27A36082DB51
+      stream[131008..131071] = C64CAD1578C28BF19F11B14F3D33C681
+                               A85D28A4B2D547652A7179C31127C306
+                               DC04BE79BC1DA0279C69F9418311E57C
+                               0F13D9E993008796EA10607A63BDC772
+                  xor-digest = A67B88BA16F74643B49BB149E6E214F4
+                               624BDC9559CEE75DDCDA01CD343FEB4F
+                               A8F6D62492037A0939B7F745FED8C3F4
+                               93102B006D3AF8167E38D1A216B0AE0C
+
+Set 6, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                          IV = 167DE44BB21980E74EB51C83EA51B81F
+                               86ED54BB2289F057BE258CF35AC1288F
+               stream[0..63] = 0B739B0FB68C82FE4120545C8930AB02
+                               F7C1F08E6C5A1EF913F58148283C873C
+                               346703A489B00BACD14E9CF30D8EA149
+                               14937EEA9074DE932F4847E69D793D3F
+        stream[65472..65535] = ABA9A96B26DC34C1684B1B9E565D7292
+                               0B3467672185FC0C000710265DAD5A9F
+                               FDC7D5D42E412170046AB05591C19998
+                               F8AA47E5C634E5719B74936526EF6960
+        stream[65536..65599] = 286FA01C6BA9498FA55E3AB7B7481D21
+                               05D82DBD03CCD59760690DC89EFF5B3F
+                               9D3FE06CD3E8D9C2C77EA2581AA5790A
+                               6D1457D534A1090799EA0B1B3BAB059D
+      stream[131008..131071] = 8FEA40A11790CFB0BA2F199B01F68FB9
+                               33874E294F7A08F319B87D0990317915
+                               C12CE3C47A19001FDAEF72DFD5AE2174
+                               72FA2DC47D492393792C407716CD965E
+                  xor-digest = 7362D014CAB8247E7F5A7476238D5C0E
+                               931B2F9D79D03E773994BBDB93B4447A
+                               81770D6D1EFABAFFB756ACA945D929C7
+                               5CFE214A53F2FE7EF78D76B2FDDC2267
+
+Set 6, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                          IV = 1F86ED54BB2289F057BE258CF35AC128
+                               8FF65DC42B92F960C72E95FC63CA3198
+               stream[0..63] = E6A0C18EE34238191E39B2DD0F0066DD
+                               D7C0033F82C388043CF13C72CCFB9DBB
+                               553D782AAFC983F419649CC9B29510C6
+                               03302235278AC3F1CE5405829F7E63B5
+        stream[65472..65535] = 16B4B4A51FDD9B41DCB8A1CBDFBE8D5E
+                               5E2F60F7ACFE5761826E68F7C4DDACC6
+                               7E0AD9A0B431F089FFE1E5780A66945D
+                               9E3C32136992ED78B8D8F9E7C38DA359
+        stream[65536..65599] = A450FCA398BC87C0079DA4D71E1BF0D5
+                               490FDAC094BF45C7F0FE0BF28017DD19
+                               BD3894BC0E54DEC98F57BBBE71EE25D4
+                               D96A2E1A003CADC37775CA370DA2898E
+      stream[131008..131071] = 17D7D66A32B7A47676FE3BCB180CBF52
+                               C4585015CD9D994C56E6DFA854D9DA76
+                               9AB45C8CFE938901BAEE5CFCE73D8604
+                               A0773736C3336C40355472B6F9208FAB
+                  xor-digest = 9727B576E6090D39333BCC2B993D0F16
+                               CD0508D7273BE022E907C99E93A17FA7
+                               23AB9CDDA9A4D310C8E5A9BAD26767AA
+                               8FF3C514AD1852DC6749F10FE663C9EF
+
+Set 6, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                          IV = 288FF65DC42B92F960C72E95FC63CA31
+                               98FF66CD349B0269D0379E056CD33AA1
+               stream[0..63] = 857EB9871D1CB2623103A4D04443CEF6
+                               5AED61EAF8264866A7B3276F6B5DA8B8
+                               D2E7C63E3213CEA9BD3333E4687C6962
+                               5D2B980D0E28EA54492148AA16EE6FF4
+        stream[65472..65535] = D498F0830A147DF5D15C6DEDC76E0687
+                               20D8A1A57F27DF19895CAFDC92846955
+                               CA942F39F64524E5F70B4B1D3F7B76C9
+                               55877A81311CFBE09AA0E9EABF0403A5
+        stream[65536..65599] = C850035DB7C0750E015EA60DC1EFD84A
+                               79C830EFD07675C0664039C90EBA1442
+                               5C523DCC60A47E60716F7F302BFD4BF0
+                               2A2DBB2CE29DCA01A1AC7B1EE9815727
+      stream[131008..131071] = 6D580F0D0C722DA5F901321F57C3F438
+                               109F2D2F46ED5572298B40F28C204252
+                               6429F5436DC67F15C0427C8EE7FBF49A
+                               8B5674674E1840E0E664E73C429B36F5
+                  xor-digest = 65367188C7BD2B0064CCED9E64FB7531
+                               EFE91EE531F4203B9C367A79B015B4B1
+                               F79349D68DD316899F5B39A867765747
+                               49461826B9511C99C0BB569F7455601C
+
+
+
+End of test vectors
diff --git a/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt
new file mode 100644
index 0000000..46a86d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_128IV.txt
@@ -0,0 +1,2783 @@
+********************************************************************************
+*                          ECRYPT Stream Cipher Project                        *
+********************************************************************************
+
+Primitive Name: HC-256
+======================
+Profile: S3___
+Key size: 256 bits
+IV size: 128 bits
+
+Test vectors -- set 1
+=====================
+
+(stream is generated by encrypting 512 zero bytes)
+
+Set 1, vector#  0:
+                         key = 80000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 240146C5EA6C72A8DFC93E54E8811C32
+                               A85E0BF7291BDDC0DBEAE086D051D5B0
+                               5CC9DD5C311ED2F7E8484CC477C68BC8
+                               C5D3F3450553F5327253768E958C0C55
+            stream[192..255] = 26C5976C37B009E57BE86064A99E8F59
+                               F9536410FAA9BF625D8DD2ABC9AABF09
+                               DF6B5EFC76CC6200F9E321E327AB0703
+                               2C78B351C5F7EEEFF2C6E374521CFF6E
+            stream[256..319] = 2F72E0E6E710D807D5120AD686DAADC3
+                               A5C1544557A4BA6B1D61F90FECD55328
+                               3C8F91B801DC435C5FFB1F8B33A23644
+                               8E21217C367108893D13AD41EA8F20F5
+            stream[448..511] = 68320BFC459C78596162EF5FEE2CF46C
+                               79EAFC681AE91F875672350C59D33D6F
+                               9E0CEEFE42EA9A0485E3E41C241CDE84
+                               9849DEC99219729D91270358B2F83F38
+                  xor-digest = 19E8083DE3499286788AE3A6DFE90AC7
+                               B77084682ED86D8039A67663CDC9ACCE
+                               D297F22C10FF7E4FAD773337B008A32B
+                               A7176F733045DE44782F04C1DDF28776
+
+Set 1, vector#  9:
+                         key = 00400000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4B1E2D728E06D7356F151D10DE9CBFB3
+                               C66A1E5B5ECD926E33F56B14CEDBFCC5
+                               40CD6D1089DD8E5CF008E4AAA3C4C89D
+                               11B136FB5656B5D4818D1BD1E562BB38
+            stream[192..255] = D5E6B5482535DB7F9352933242C164D7
+                               6528DF7AA013A4FC2F2B8C2D7DC0202F
+                               85774C16FAF22D5071A875B6A671D4B1
+                               A8C396AA5D2F14AFF9C4CD6C1DB89175
+            stream[256..319] = 3D0FCC3C90DE0328FD0C752458996FF2
+                               DF822E496CA42A7D7EBF3D958676A41D
+                               83A16EF3150B8C4C8F1763560B314287
+                               54B4A2EA5C4F74783BF8809F3A624664
+            stream[448..511] = 2D68526D25483C2A1F0B6F7101507804
+                               C9619E267F1FFF28C934D19201351465
+                               31D13592BC9F1739A0B090718052E4A0
+                               CAE9E0FA4555F2FAD27EC8AA2F14CC60
+                  xor-digest = D3C3131E402BCBA54DCE0AD35C5FD241
+                               3ED7056BF67B5163CBE6C9EAA9D27535
+                               7D2BFB7B2843DFE92709F047675CE06F
+                               5201611BCB8FF15C76D0E328D46345E4
+
+Set 1, vector# 18:
+                         key = 00002000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4A0CCA5AD387D49DF33FE8BE69FAD669
+                               270E3E6CF724F53FC3E509A2CEF1D174
+                               A67C2EF4B9D2C9B8A8177BBFBAA2C45F
+                               BDD25CBECBDB59A402FE3C4835854CAF
+            stream[192..255] = CA0F19D9996E6D3518D28D8169968ED2
+                               B03D118D4BC1C5E1847BA6EFE6A32D6A
+                               32BAF71A4C27B0BBC9B9BA03FE044D7A
+                               C9785A69E3B0E5B3B26AABE3AB093965
+            stream[256..319] = 6FD1A9F1EA228C39625FC0CBB2D4BF8F
+                               2C0EF1F37D4FAC56D8024D1B4F2AF33B
+                               8AB0D452F5155ADD5F0FEEED8104AD55
+                               9946D2E274ADE44170F5113630200B57
+            stream[448..511] = 5DA1476A1CBADD0797DD7EB9C0E563B9
+                               EEA2C55860C42C2C0A6B38B9344BA0C2
+                               345C7143D9A7E5BCDF9FA2606098DEA2
+                               142632258F844AA1A77CC9950D5ABD7F
+                  xor-digest = 0CCEB42D4045C09C45CD6C27B88606BA
+                               ECF7F6B30F50004AB2ACDAF89849519F
+                               61482EC4AAA2CF58C4206A228FA23AFE
+                               DD3BD50BC9C04744940A238966C2926B
+
+Set 1, vector# 27:
+                         key = 00000010000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 77CB199A639DE60664225AD1DB954B5F
+                               70DC01305D2D4073BE772B0863175EBB
+                               64FAB80EF324DBC85A9EF827EBAC7A5F
+                               CB088619C246CECE6F92B89A2122B6AB
+            stream[192..255] = 84C1E9B365F1CD23AFD5711BDF2B6F26
+                               F988A6CE29450108FD6814802355217D
+                               F6F329FCB3F5997401019BAE0AE43760
+                               ED6B658FCB4280F5A070728411EDA4CC
+            stream[256..319] = D0AD4A851E7A60DC789762A554A8FA76
+                               77FA610F4D868CFF1AB6025B2ECDECE8
+                               C554B4C0BDF543F58A1DD7CC68FD7AA6
+                               7EFCFD59D55372E85131D6284E7949AF
+            stream[448..511] = CF7F791090D04350930AA1E1A53B70E2
+                               691A231595E83F8BAB9613BDBAD868AB
+                               197D5E06B3397CC3D81F56B87BC7521E
+                               B0BE346552DABEBA863D5C81D7245C8B
+                  xor-digest = 2C77C0ED1F5AE20A97388ACA5300918D
+                               6246B04429F298E64A75828EDBD01900
+                               FC70CC103C31E0BB67B06D04128686AC
+                               5C5FA63FE714FC4DF18C551BDF81862F
+
+Set 1, vector# 36:
+                         key = 00000000080000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 54A5A2E883714170B471C0651D74A9F7
+                               D51287C89FB345DE0AF7003C3871425E
+                               FC885F033D79BAC9716B1ED5C637BD9B
+                               0F16FD8D613BFFAB634F0EC2497D7B3C
+            stream[192..255] = C7FBA70B19B749BBD0C84C7D31A5AA44
+                               155623116C44CD53D2E640034211E730
+                               277402F62D1FF1578236A2646AFE6108
+                               2C958D9D01C065D7335EF9C29415AD42
+            stream[256..319] = 2385E2A7070FEC7399BB3CEEA43C8D0F
+                               54D3607FC1C21BF173642287C1FC2C96
+                               D37695A7B1310E5E918EBE37113348B1
+                               707BB39E401A10FF14EF020CB7C44261
+            stream[448..511] = 5A87EF81C2CFA70D86B147E9587467B5
+                               22FCDB4EAF0353E11F73F3BCC1EA6C09
+                               E962A87A0842B9225E164DB0CD1A3BA3
+                               DA8C02E6746CD3AE0BC4754ADBE7EF6D
+                  xor-digest = A65BBEA2E397048E4714A8AB3C19EE6E
+                               91B9EB8048F35FA7AB9E003E9359BE0E
+                               C3EDA827AF485C23A941F7D656C76CA2
+                               5D12044923E43E61E7DDEBE7D9C87E3F
+
+Set 1, vector# 45:
+                         key = 00000000000400000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = FF81E156907CC2C01EE23F79F936809E
+                               3F88AC15CC01BDDDA378CC1BD2317444
+                               200E4E2C63E15FF07B0B40721970E7CA
+                               68F748A95A965EEC606318447BB31C2F
+            stream[192..255] = 4C4C42A330AD444388FCA4009CC0B196
+                               84AEC3EE65138A747FE86526A263969D
+                               87CCDDCC4C9A0EBDE2D088CCCEBE76F0
+                               52BAC07636937B1567637ADB498F7F8F
+            stream[256..319] = F550BCDF67C8E9C17B800487DF83A4BC
+                               73B809C4F3279D4CFE857780412F0F7B
+                               B838A9F0322BBA84D7AC51E469C5012E
+                               D774E52E3507C7D069F5169F0403C577
+            stream[448..511] = 9D92715109A301AD47BF2376D65E2519
+                               78E12098B0DEA5B779079A0FAAC4DB42
+                               5BA9EB00301A5F964336F7EE9C0D9667
+                               C4F0DBAE14BED3E49A6A746FCB186C65
+                  xor-digest = AD2264EC651E311BAC5FB36434773F5B
+                               4A4777B2B7F811A755269FDA8339DC97
+                               7A8C6A5F66E8737DD16A88DAB8545110
+                               EAE275892A767BCAC0757C396A690F67
+
+Set 1, vector# 54:
+                         key = 00000000000002000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3DC3C1A1A40E721F8A3A66960DB2C0F0
+                               6D8B7C07FE90D67C26F86200D6A1A1D9
+                               ADE4D53A35F7A016A506D9C62D344D49
+                               5C6DEAAE053247103B8F202B85A5036D
+            stream[192..255] = 9B83E56BB5E10B5C6C05C4B450B64FA5
+                               9C52AA63E207592999CBB48355517F05
+                               C93EA878BFAECE58CBCB948E81BEFD89
+                               AE0C5C13359C6CF5A673B4EDE28FAF0B
+            stream[256..319] = 388163F9F26536BE1221A46834CC77FE
+                               03D021C570A9DA36CD528E887ECEB2A4
+                               7146A8A930D6AC04694A0B9AE50FF55A
+                               41AD3B3D3E53F982563B5B458C078C0E
+            stream[448..511] = 3B0FF94C0C9FA0EB8B8CC1C691D04180
+                               5AB6436BAFCE8C16A1351883C88E945F
+                               8F912FF79CFCEFF7374936E830C9440D
+                               C676A5F00BB50EDB34F810AFFD9CA8B3
+                  xor-digest = 879534CEDD8CDBDDDE2E2216D55529AC
+                               1189B1C34A76ECEC179B8A240E890F8C
+                               640738DC37C14E4B950B9D8C507685B1
+                               28CF4782EC424A3712F54F6265A41E7B
+
+Set 1, vector# 63:
+                         key = 00000000000000010000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 12F0A17DEA167676992DFF2E7D812878
+                               629579519578EAFD885F212C7E04F035
+                               AF03732C3DA8CFB7B73054662F0593E7
+                               E40133706F04B1329BC3155DACD296AC
+            stream[192..255] = 41BB89D0BE44055E23813783C3EC4487
+                               2D102D6EE94475AAFFC7FEB8DE6849A2
+                               6B50DE77EB9B0B96EC9EA0216D13D64B
+                               1264A83D6B571A92948A5E35446B0503
+            stream[256..319] = 15E9C9168AF4AEF7F2EF1E832F40110B
+                               A8C08DE71D4F0AAA3A5C2FC59BF41005
+                               ECA654EB7F316B757FEAD5B0F4BF41F2
+                               C6D035A88B5477632F34D7F904B2939A
+            stream[448..511] = 8A2D446044F7930B696DBA896BA6CE69
+                               8F8B01E4282BCCDC4740BB6AB6ECF7B8
+                               9CA1CFCB5745B6577D0F440AAB7985BE
+                               BEC5DBEBD8B028B15DEA138F09018297
+                  xor-digest = 89CFE7E84993C6B608EAAECBAECD7847
+                               472703F3CD97F9315BA9CA13204B616C
+                               AAC0F37EBD1C58186620710FD6AE5EFC
+                               B7CBADA19AF8C0F7E1FB24913C2300FB
+
+Set 1, vector# 72:
+                         key = 00000000000000000080000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7BC411ECF4AC2EF2C9B8C5B7CCFD791A
+                               E8250119E08C1B7F7A82F576FF66FC9A
+                               9D9BDB7570EAF276A60A3BC7E7BCBB86
+                               7A791A48F9E742D7D7480FBA67DCDA6E
+            stream[192..255] = F85A8E3219AE1E5F20A4FFC6814458C9
+                               5A4ECFE7FE739E151A45247A136E3BB6
+                               9C11987BB5D13B1B9A3077C8F4ADC9AA
+                               A555FC9725339E02390B9C9F75E1F38C
+            stream[256..319] = 8A2E88E0A773EA00C11138710BF12ED2
+                               7797AE7863B1EC84801D11B5B3914786
+                               F1D547382DAA9D5215CD4CBC783C700A
+                               9B09FCCFED28899D2F2EC148CEFA39B2
+            stream[448..511] = 95E3BA3237F370A4E0850F2CA0FCEC89
+                               E9D832CA6DC6A062BE7ADA8D8AEFD55D
+                               2BC7A3F46BF81DEA5DD9155E8D8FE918
+                               B5DFB1926460AB69663856EEBCD4C338
+                  xor-digest = ECE252DA29D20602D138E13C004D8B66
+                               8B09FD764B7D84FB83B8F4D924504D60
+                               277BAFC521A8AB0464E4EFC6BBB9E4B9
+                               A206C38154AE3A57B84D2D39CF45616E
+
+Set 1, vector# 81:
+                         key = 00000000000000000000400000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 139C2843F0BCBDD32C685F4EE2C7AF4D
+                               E6BC79789B77B1CA6CD94A01645EA243
+                               5B491F27C27D4EEB96FEA0ACE65C0D8B
+                               BAA642B5A07245BCD0930588FFC92A50
+            stream[192..255] = 5C76EB0D5323A7AAAA228F7718BB6736
+                               5B344559C24BEDEB2CA66414B5E81795
+                               428D55868611AF9AC7EA0E7424984037
+                               3251BF5206C361AA3631DEDA52DDD519
+            stream[256..319] = EAB18EFED266D4788015DBDD20A75058
+                               FA4DE35C1DC774ABABC476BCB0AA2CB1
+                               214E5463F4E20E7B999ED475D77DBA9D
+                               70FFCA0C7971CAEC3B285EE8F9F37C02
+            stream[448..511] = 081083D9AC30C9DB4E53597D64249D7B
+                               CCD847495A928CF4CE876237D92ED5E9
+                               E3D723EFC663CA0DDF34DABB941F42C1
+                               B48EFD59DDCAE71A1B82358A3328644A
+                  xor-digest = C08714035439EFBE455BAE68EEDDA0D2
+                               A6968F18827B214A097221C3A77F80AA
+                               E1DD9F3C72FA66C16EE278A76C19107B
+                               37CC32346DBDD29FB30059A8FC732DED
+
+Set 1, vector# 90:
+                         key = 00000000000000000000002000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AD897A3C509B66728342A817D745460F
+                               6A258386FECF71DB95ADC716B8BC0462
+                               22C4EE887334718534E719F36454E440
+                               F9EC44A2DC38345CEEA9425BF5F10123
+            stream[192..255] = B32235522391A0BE105A993923760C6F
+                               BBDA849213C628776BCC5364F28EE5BA
+                               D498F186C3C57A8DBE5355C2A38DDB82
+                               54B321636EAD186788DF1BFC5B6F85F6
+            stream[256..319] = 499CC51B20538B14A05E490B6D5D10D9
+                               11079F58E3603A84AE6689293E3AEC56
+                               7545823F0B085469CAFFF01D2AFC5076
+                               C155F8B4B7DB4C49A9A993964928D11E
+            stream[448..511] = 65983D36E97AEF89C3A75616F7C098B7
+                               5CFD9C531AFF8184010E2CFD45163312
+                               FFBCF5AC70139CF12D97325CCEFD0B01
+                               FBE571FFBD7DC21B54D4B277A2205E56
+                  xor-digest = 90CD243B35747378B85B99474EE0BB3F
+                               CE7574CC19BEC5220255523276CDECE4
+                               5A16EF44C414ADF1D1CBE264872419CC
+                               EAF664CC74D36072E9B975FF40074006
+
+Set 1, vector# 99:
+                         key = 00000000000000000000000010000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 26F731F36F626943D4CBBD605CB67FBF
+                               E9301F24AA4E93EDB2D0DBB3FB17E8C8
+                               623054B3003BB12E1C8607FB53315AF0
+                               A139CDC381753A14342AB90AFDF43E67
+            stream[192..255] = C3B755D009DE9965D36B4111308B25EF
+                               39A137E373BA0E90E5AE2748115F29FC
+                               562A6F6894BFEA59587F991DD105DE1F
+                               67F62A73A72A4802ACE727335467F503
+            stream[256..319] = BA815578D19B3B384BA7AA7B972B1FC1
+                               7244FA75A4CFDC8C30ABBFDF6861F356
+                               6A9B68A6F60A61E6DC8E046FE75373E4
+                               B45EAC193127CBA3AC4F22345BFDCCFE
+            stream[448..511] = 99C68AC554291FCDC03F300D69CE68D8
+                               C4D4DFF5FB2D4C3079992D40FFCC9683
+                               DE471E6F2A406DCE03AF8EA17B7AE905
+                               12F1368B8EFDA838274812C4F134E2E6
+                  xor-digest = 01AB73AE53306196763ACB9ACFF9A624
+                               B83A7B339DB517AEB408292627EEBC43
+                               FCA6397320F50E96ECC3595B13BFED85
+                               1309458EFE35FA1167C2CCCC6A4CA83D
+
+Set 1, vector#108:
+                         key = 00000000000000000000000000080000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 031A1BAA02280255F0413D76F945138B
+                               C0835BFE7CA64B16AD090454F098B8CF
+                               34B1EE138E03C3CCD9FF918A58D06AD9
+                               2D7F3FB57D2E161A863A0C25391CCABF
+            stream[192..255] = 6810368C2B2A091C6FB3EBB76E960AC3
+                               BFD678F028EB6FC0F5B36C2D386A21A8
+                               FE46A5AE09DB0BD75359A8482EB6F5DF
+                               ADE199B796520807D60D9D93995EAFE7
+            stream[256..319] = 0F2CDD428FF6DF2A4621A8423E09939B
+                               014BEBC0ADBB8CE71B5E587DA408ED43
+                               04A12BD535257322122EEA2840A9447E
+                               CB1B6D3550ED14EE31424F5404B2B5B0
+            stream[448..511] = C63FCB06883F3AC65612EDF28C875477
+                               1D383D42A553EAFA37ECCE26061EC5AD
+                               C6FE3BF23E06CFDB14EC1DD996A7D4E3
+                               FCF7A0B9ACC69F37ADF428B434994595
+                  xor-digest = 463386D0F7A1306E87F3221C4ECC0597
+                               9474F620AF3563686ED5DEE291155225
+                               56B9372496638BA1631982D6B3F58CAE
+                               27810BB7AA93351B838D54EE761A8C94
+
+Set 1, vector#117:
+                         key = 00000000000000000000000000000400
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = AA4E7E8171A8E0AEDA6049999E0A06C2
+                               FFA43B9ADC5E9DCE4ECD8FC1D27BE792
+                               6FBE2ABB69A6B69D8C213A793C77096F
+                               D4DF7BBDBCDF007C914B7C817837D99C
+            stream[192..255] = FC90E3C82B8E7228C1ADC2F555068372
+                               4307902A0750149CE0B2EFD2CCFE9875
+                               DABE60E1B85CA117D05E4BD4F45B42E4
+                               55A9F42C60910C9BFF8DF8FAB53C81E1
+            stream[256..319] = 9BD976B88E9E5E23D0D40779644BB3F4
+                               CE5C6B16FA6D955C32369DFD19D632BC
+                               7730683D562320E39F75D8D8BD074968
+                               9ECAF0DCDCD99FF4C3939092E9576144
+            stream[448..511] = 51BE9CC1362669C0F79D2D88A42DBED6
+                               C3315002380AEB647C8F9C4036590527
+                               1D8915B985B8BE9CC1C5C7652139E609
+                               651EAC8A14DF661D9869982AE5735E9F
+                  xor-digest = 0B0C84D430687F488F8E45DECECD6D7F
+                               1947E32AC49BDD2139F5413E08A88F31
+                               F9AF6599498431F155AA10B7EC09F095
+                               8A5AFDAD486D2E6D50AF77FE98E33738
+
+Set 1, vector#126:
+                         key = 00000000000000000000000000000002
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 52F49050156E957C605656B2DF88EE1A
+                               5E3ADA99F9793B65456C4C6C322B8B5A
+                               28DCC91EE0E711BC33E0C13354542227
+                               613665CFA3A825B943444401EFB06ACB
+            stream[192..255] = D0907F5D5939D7B544476E299605972F
+                               FE422C64BC6343F9C81093AD0E3ACC72
+                               F4B67314892E36764736C0715E4D3438
+                               36BDB105214F5F8925F321F5FD865EE2
+            stream[256..319] = 96EEDA75474D65615795185B1BEE8D44
+                               A687420304B260E4C70FE7F542967325
+                               1826EAE010981F6262EE6CB639996467
+                               5F6B23825748128617721752283C16DB
+            stream[448..511] = D926085A441E507207850AFF3008D59D
+                               F7C9D3B69687D18CCFF2C2E09D4E4EA7
+                               FF0B72C04A86B80923DAE187FFB99170
+                               DBD4902AF77EEC42866A83B519F092FF
+                  xor-digest = 1E068ACCA6062CF26ECEC79F149BE139
+                               24AF8BF44377EAD1550B1560E4A1006A
+                               A6986C61581FF9E47D58F2E52434911D
+                               5AFCF914DBBAE183D02DDA3210768984
+
+Set 1, vector#135:
+                         key = 00000000000000000000000000000000
+                               01000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = EF5BBD7A620E8052F05DC269309AA7CF
+                               8AFD4AB2B941D905AEEFC721562E00D7
+                               04CA70113C8A90FA12A0C9B9CD1B9F9E
+                               6176602CC08B66410A8BB0F5E9837C27
+            stream[192..255] = AB843B43856FC77C1EC09C0DD2248617
+                               820344BD2CA0B025C39B0EBD5A750A6C
+                               7BDCE863C068E0D3A937A5B2C5B6ADFC
+                               609F6DF7778D88238B89288B2768DE99
+            stream[256..319] = 5E6AFBE41F47F35CA9298C973E613174
+                               529D9BEFA6D0713A5BFFD96B70D39044
+                               413E24FE57B01C426E8988EC365FEFEC
+                               1422CDFB956B12C6A799F5FDD4EE43D5
+            stream[448..511] = AA960C189C0A20870901D4E2F1901D0F
+                               A28AF3D974E14FB70736C191D4C9CA26
+                               48EEBA776339F80D57A8B783419E61B7
+                               52541CB296B4CD31C55DE3D34CEF0D31
+                  xor-digest = F163BB7ABD3914204ABAF08B844ECF05
+                               A36B7B37B8345115EFAA2AB2E7763E6A
+                               E044A83597C023FB41EFAEFBB63E4195
+                               B60AEA6399DEBC94C75BE883B3623733
+
+Set 1, vector#144:
+                         key = 00000000000000000000000000000000
+                               00008000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9198011FAAD874AD77CD0C98DD99C7BA
+                               01B75CF9DE1E26321EC6AD293C73C675
+                               69A349157FD47672C5326276BA40F4C5
+                               0CF8D98134D0BC13879E9EC267110FDE
+            stream[192..255] = A9B3BEEA161ED996C44F6D3B93431C6F
+                               54DCD5DB88E62CA10D1067B9CB5D21DC
+                               D7E04C48D88DF54E1370D1C24C871BD3
+                               BDF9B956315996F95867D1E2494370CD
+            stream[256..319] = D09ECB5DF5B0526372B57CDF5DCA6AE0
+                               F005D2E2F27D50398E3D1D7FF2100BAA
+                               D6F2C03E431345A4F41CEF3E8D3F14CD
+                               C76A423720A936D27322559289F13D92
+            stream[448..511] = 5E8FE7964B052B6D27216E37C49CC913
+                               450FAE159C087E34CF67E8B0B8F516D6
+                               3C0B544CA29F9BCB2B48D3894D69DE3E
+                               1460783E82EB67990FFB7F92DA48E449
+                  xor-digest = 5515E37A3F274746847F551ECB7DB4BC
+                               2BC32237050BEE9AF2AD1BD8577034D3
+                               4A23AB8A2FFD00C7B8CB7D5CA0AB2421
+                               E7CECB2801A1B73A44FF3E798ACA8443
+
+Set 1, vector#153:
+                         key = 00000000000000000000000000000000
+                               00000040000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 02858548ED24761DC0AEC6752076D095
+                               7E78EF1FCFFD8E756C747586A3B59C22
+                               F42A9FCA9F103C3054E0B4F6EEC82101
+                               971F2A6F9611F7541152FA3BD7774474
+            stream[192..255] = C32ADE80873D1190E9807C25D73EC5B7
+                               C208AC693D98A664FF4D11205650F7FA
+                               A36B153BC1A3F0EE0F4319F2100F7F27
+                               31856BFAE36110C12EF0361259641D74
+            stream[256..319] = B8F74AD5930D1F2CEA6B9F7E4E775DF0
+                               AA97744677E5C96B9E55AD77BFAC5E8E
+                               E9BA7A19607D9EC52DEEBECD185DAE13
+                               E304743019D831849F111602EE6EC34B
+            stream[448..511] = 513303A57165287E793DB91F49C9A8ED
+                               522389F03634930512744884BCA45F4C
+                               ACB60FD077BF2C050D4002162FB811EC
+                               4AA855793CFF2E30665188471FFE0847
+                  xor-digest = 7EABCDBDA34E51E3A61D2F3340884BBB
+                               600E1D30216B7117081B3E5D04FD4523
+                               706D4F34C5FD604134DC89F570D6119D
+                               DBB7C5FB7CA90E38AC157832C3C956BD
+
+Set 1, vector#162:
+                         key = 00000000000000000000000000000000
+                               00000000200000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 689E48A85A40BD161BEC710F9B2457FD
+                               276F1156EBC10BB851A8517AFDBD692D
+                               E4827BAAFF218AF886439ED976147EBB
+                               BB1074BD599A80F6324C87BAC987B8C5
+            stream[192..255] = D9BA3E74CBAA58CA97DA3D3B1051BDF3
+                               29F6CD837B72022D2EAB5D20B02F53DC
+                               4755C764C50756A7101998C187E4F0F8
+                               F17A0C6797976C4FF1BA17B3D03C2218
+            stream[256..319] = F6F9B6F0F6E1D756C0242B48BC55EDE3
+                               3038BABF72FCDD5122C61804996F5ED0
+                               86A78B33C517CCED9C34580AA54AC03E
+                               BD0F9698A234787DFE97FCD3D9B7CEBE
+            stream[448..511] = C31091C4C5AD605BA90963B1D469E501
+                               412FEECDE3EA8EE834F188793A98F830
+                               81F8C941F11676E007074B40EB15DDB5
+                               67D93E954422376F2E3039F4E4115D70
+                  xor-digest = DF047B3EE7F2AAACE9D5A2B0F6A1EA0B
+                               97E815E9B9BDD3B7862ECB414E9C08E9
+                               BA0109B1D6866C9D7D6D3DC9FAE5F51A
+                               48DE7B9077DA489B7982BA69228483A2
+
+Set 1, vector#171:
+                         key = 00000000000000000000000000000000
+                               00000000001000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1F8F707DDF0121AE4DF26A6ABDC195A7
+                               CB9CC8479588D2D436C52483DA54744A
+                               2880E3DC622180D36B64CC053CC245D8
+                               0700EC62ABCA6944BF89C7DE1A532A3C
+            stream[192..255] = CB2D934DD1414C60550CEA6FFA776312
+                               3C9336F99F16F8B5B8E60D5D0CE54A35
+                               E752A4887A03EEC95050E50B58F5C8C2
+                               FD814DE76D3F66B907C77C9B646EFD13
+            stream[256..319] = 10306DD8B3EA307496D7BEB7A679D53C
+                               3650ADC53991D0565856F51DA82CEB45
+                               AFB460D6F90877557E17F534C3375FD9
+                               F96D13AB77FA3996998F5DC6F5D3C9A3
+            stream[448..511] = 42F4D1F669741750B24A44F82990E6AD
+                               065E7B07B2194C96E7578F7A754E52A5
+                               86C820FFDDBA671A7B08D65B51D8736F
+                               D0DA8E81CC69BB8A56565C43845C0AF4
+                  xor-digest = C0535BC269BB39AC2ADCC50C62F87B6F
+                               2C9351DAD49813529A27BAEC163A1D8B
+                               778670F0FF1610A4688F86851050C9B7
+                               275B087A0B5CE01B602F8D1D25C29392
+
+Set 1, vector#180:
+                         key = 00000000000000000000000000000000
+                               00000000000008000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 899C1C50A80E374AE884F10BBD17D036
+                               1632D89938FDB7E4BCFBE1050D5E948C
+                               CF4631EDFEFD2F140FC3FBFCC096CD68
+                               1F6C1B0CE9E395FDEC56295AE331D8D0
+            stream[192..255] = 2F60CFD4D07E58DBC5127A98D2B1DDD6
+                               1F216F61F70AF12427108906AFEDA4AB
+                               B439A99765EB84E43D06EB7B3D984A3B
+                               53D8C054745A6E3B61F8444C84C7F30D
+            stream[256..319] = 1A92F3B4F6C4684201FA4AF201259AC2
+                               53637B41B734062C298E6F932DBDAC5E
+                               999FEC21B63539B5FAFC312D0CCE6137
+                               04AB3CE65E241A1C34D12ECCC840973C
+            stream[448..511] = 83A75C2E2C6D40FAEA049322DC1B2251
+                               306A8906A37DD30182C328D50E7B7AAF
+                               89671DD776C9C730EEE0DACEAC7D7038
+                               4A93426090F31EB851976B8B2ECA1FBA
+                  xor-digest = 6D85E7DA2069F1308D20A56DB17F3629
+                               09E80EA6A045DBE61FB037C3C8B9D448
+                               526A37A431A8BE49CE4F10B8CF6A33B8
+                               82E6ACD6309BA1B716810715666C6CDA
+
+Set 1, vector#189:
+                         key = 00000000000000000000000000000000
+                               00000000000000040000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F9E151BE5EA0F532E56958F173B8F104
+                               DC9E73D8FA289CC2F84C4BB10E8EA769
+                               57FBC8F539365B9E9518F8787D6CF927
+                               55F0C2B2845318337F36B80E22C59FD6
+            stream[192..255] = 27FAFEBD2EBCD2B67AB18BCFB7F8DC96
+                               F54C8A765B0E4B3DDC3013B599DEF791
+                               287FF3C0F48F339DA04B667E54696485
+                               D48751A001B548727338AD6FB82EAE42
+            stream[256..319] = 09DC2AFADEECB86278C64DDCA51EEF97
+                               C10B9852DB5F33A19C99C0D4F36D2959
+                               DE247E4DB356E67F2951E0309F18D6D7
+                               27D2A1BADCC44DC320E2AA80E1834198
+            stream[448..511] = 4103D8455B6DAE658915FACFF2F3F1F2
+                               856E2343143671565936301E9D1F635F
+                               EA732C9A096C3E955D33770E244ACEA4
+                               094E390239489F4D4F0A1F3C26A1589D
+                  xor-digest = 8DF4EC7886C386E5A0D7201A3E731E95
+                               5D1E281321C2B592E31681CC95D173A7
+                               C92E6112197C6A605F494F6E9C4AE73A
+                               21B966CBAB1628794F0E44202742EACE
+
+Set 1, vector#198:
+                         key = 00000000000000000000000000000000
+                               00000000000000000200000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 8B9B0CC804CB353F49564926E3FD846F
+                               A4758692FB110A428FAA3132F4C606CC
+                               A41CA937FDE463D9FEC51F419D60AE60
+                               1E8EDB30AB09E0B08D0143D885161B16
+            stream[192..255] = DC6DFDC4E36FC1D4BD87F731F761BCC3
+                               9837A790DBB766040B4508778C5CFC82
+                               8EF9EC4D76BE3AE0967DBC844A2D252C
+                               B942E97A2C6A185ECF4E1200BF9BC826
+            stream[256..319] = A9DE78C2204B712A9803594B872F29E9
+                               5E8962D7D719702FB3279F053D311292
+                               26A14FB06058AEEB6D283EE0A272C6F2
+                               D392B102E294A7CDF24928D5281D024E
+            stream[448..511] = EB822D7BDDA456BB6E109ECD330D4FB5
+                               1259D7042935BD5DFC787E903758C27C
+                               E9E9B191957E721A7013D36E5A29C09A
+                               3433205956A55460D1498124B2800423
+                  xor-digest = 10128D9A5EEA1D93E65462702DB15A8A
+                               23D0FDFCC5B0871639D704DEB9F580C1
+                               C88213CA166F3BBB89D0926CAE7E64C1
+                               0A24041A42B9D50CB0537A0585EE574D
+
+Set 1, vector#207:
+                         key = 00000000000000000000000000000000
+                               00000000000000000001000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DD4CCBD0B5068DF0193F50C11D2576E1
+                               A70040D6C2CDB98061498891D1791E63
+                               C4B5103A52146CE27D8F721E147EA612
+                               7E5BAE1FCD3DCD9053D5FF5EBA328BBF
+            stream[192..255] = 541F008D78EC1ADC5D1B930CC99D4A3D
+                               61BD60AAB9DDC8AF8594FCA129410232
+                               92BC44EE064E44E88A07ACD1B742666A
+                               D147F14102D23578E3B7DC00905586D1
+            stream[256..319] = 6834D2FB6BF3B46C0552AD83275CE6EB
+                               9482C2DFE40C6B1FD6F743CAC8F40A91
+                               5BA9A90FBE7CC0153D53C444D3F7A23D
+                               CDC3134E237F63E5A07C99C10B8EE87A
+            stream[448..511] = 9F75BC84091695FDAA2579AF9D34B2A7
+                               2B82D39A1E7FCFC4D18D6898A9CD3296
+                               0D50AF1B720E1347A0848782BE6AECC4
+                               684CCA05B893951A65EB7CB37F5FE240
+                  xor-digest = 12F358C7C4C697199F9AF17040115522
+                               062514A5DC3584BC515AAA4474A1D85B
+                               47A6A2D8C39E8234A5D11860BC1036E3
+                               957920C03E9A47E61AAFB058A9850559
+
+Set 1, vector#216:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000008000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C5958694DB1D54B95101A9F48660CB26
+                               8EDADED85C6239098248E0867117607C
+                               D5278E5B5D9CDA7BE8A6BBDCE61215B6
+                               2A93FFF627B28B271CF2275E54EA1CD0
+            stream[192..255] = D9B69B25B5729759F3180FF17421092B
+                               0740B2E1307FA9141915CB8C30C0C322
+                               A1E4710674EE715DF3AC89F447442A7F
+                               845E154393273BA47F2322BC661D1755
+            stream[256..319] = 49412E5F3C9B5B52FF790CBE82D6F037
+                               217A13B7744740A887F7C1FBE3714DEA
+                               2A4EA4A5F444B2EC3C0B160A251CB44F
+                               8DCA914FBB80F72BC8D009F1C7E001EA
+            stream[448..511] = E1C2BE8C64D6BFE081EDD30681763928
+                               85939DD7EBC13E16D83C8E7FF65EDBC5
+                               90FA3904068784806E20F0A61CC73839
+                               E3BACD410F59D3848F5A628EE030FC4E
+                  xor-digest = 54092B3D64197BD598F9050B44D2E785
+                               029F29F46822B72ECA40182E8ABDABA8
+                               751054FC50250DF5AF5AC75F4C51D1D5
+                               D2BE298770C353A7C5D608D1149F1452
+
+Set 1, vector#225:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000040000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 633A6CAC516B7A84CFF8F5702CD9BC81
+                               BCE328741675EBA0FD1368190AB6BEEA
+                               7C8B0256CEDF9E5CC6F9249511AB87AD
+                               ED95BF8E11182B8BEB75FFA279C3F706
+            stream[192..255] = C3F700538A4EEA17773E74D10CE4493E
+                               FB0417B380ED4229F651D6A9BE0AC617
+                               AF66C576B7D06F2210EF226462004D90
+                               E753D805AB198B73B0CCD752C7E57A2A
+            stream[256..319] = 30A11289A9E0C854B980BE044F07E945
+                               06D772861896D0F75D739647FFB939C8
+                               13FE4BE5C8DF84F64827306D0DD82415
+                               E104F787F30CD097EED7DB9340A0F47E
+            stream[448..511] = C2134984733448DD577DC48B5EE5D761
+                               0A54AB6C32E3BB782849D8E7E8B522B8
+                               0D6444342ADD9709D7434F9B4C18C6E0
+                               15AE97DF8F3D29FA6D85DA387157E223
+                  xor-digest = 8613454AD0B424AB6EFCEA96C0802B6F
+                               47F1E98C52BC68DA25E653431CE31078
+                               1658BC45DCC2EB43C4ACF8395727133D
+                               12A127D4CBAABAF24BA44930A58A87B6
+
+Set 1, vector#234:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000200000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 6A0F095C0E23FD6F8DCAEDAE5314141A
+                               0F1CE1C1BD6A16E81FEFF72F0753A5AF
+                               C1C54DFC0DD6ED99F1D416BE3C5EF341
+                               454C18D49729E80EE99F37734817658C
+            stream[192..255] = 05A4DF5BE8A35DC623D107728F28C789
+                               3DE0E75268B3E1F94C07AE50CA0891D6
+                               2B1E764CB41062391B33929273CE6B6D
+                               1C9CEFB35C37AB2FA8EC18749B5292B0
+            stream[256..319] = 41C8AF9ADA46F7BE8EA72BB3B8661B78
+                               2BE5649F18F216B75A0071A6617200B8
+                               463B08F986D706AD140E27C8F4E040BD
+                               6BFB4872D758363281C62AE8C4B64E33
+            stream[448..511] = 58CDA35476767EF58748A504B0E4A38B
+                               64162AD422A0DEC0434D879898558C77
+                               1A8243DC43B15FF996B4C8CAD3C47C6F
+                               26F00C71ADFB538D9A983B7B624D6E62
+                  xor-digest = 240A699AF4DDBB56A4C502A9175C0E3A
+                               BBD654D0717A1F6F6847381B978AE8C8
+                               0EB7CA07A481DFF8606A31BD6B489AE7
+                               89763068D641BAEADCBDA9ECAC465ABC
+
+Set 1, vector#243:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000001000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B3C91DA5911D7D7A4BC16A66988AFD3C
+                               8462A9E9BD0D95C9B9884DD14801E464
+                               C27048FEB5F70B28013099F0A31255A4
+                               9EACE528A13CB5DD067E520D183133BC
+            stream[192..255] = 756EDB0542FE1F11B159C7081D9CD742
+                               2F0E5862D39E2CF1517B2F6F39AE5245
+                               D659A5B93EB8FA8C8FB751B378BB0DEB
+                               481B874663624C8DC15E6A1A64376340
+            stream[256..319] = 436613C9293D5DCB204B46899CF23E65
+                               698BCC3003FE064FD1263EEBC59DDBAC
+                               536566855510FA802128F0A968A2E359
+                               FB68EAFD6AA89D394B32BF6069E92EFC
+            stream[448..511] = 033FF40203ACAEDFBF561A674EE74D97
+                               A535A448AFF94C8C167200E5CA626388
+                               DB1BD6EBD4A1D83CF352E97CD8F02671
+                               18E57B71D33930EC2752D2F262A55F9D
+                  xor-digest = 2CEEE4705688B20B3AF71F285DB9361B
+                               0EC945296B97F3A050C31C54E9A07CA6
+                               498B92917617571928E2663CBBAE21AD
+                               8DD880A037A024E46B6581974838AE1A
+
+Set 1, vector#252:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000008
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A6AFA8AA02C3AE7F29E61202B4A5C25B
+                               6F74BCC176702C9C1D610FF722527A6E
+                               721ED90B871AEEC71EB62B24A8F24357
+                               07765F7724BA03173F51C9B66C9F4BDE
+            stream[192..255] = 002B8929A54C1370067A36DB9057807D
+                               DB747C2A4CE19BC085DDC517AADE3B97
+                               BB1B35F2BAA6A18E8154CD80DA6F9F4B
+                               0DBFD3EA5F69D5ED3B5770C6221A8D66
+            stream[256..319] = AADBBFDFC6FCC6072747BB528EBEEF34
+                               6DA76885CF1616ECFB89D3A134769902
+                               904AA12744DD404F268B0B4B34700928
+                               E3C4B3665B9CFBAD9C528EA06F89CCDA
+            stream[448..511] = DD5453BD0D99E7D2CFC558EA969A4E35
+                               743AFA96D570026106C5CF40037B1325
+                               40C909C1278DAC8369B1AC257FD8D868
+                               3648B4F22F7C66282BAC49D8D23626EB
+                  xor-digest = B3F2AD900155FD5D39768B4F4B7F8E5A
+                               1C557936F2B5F06966DCB884AFF7F01C
+                               7AFC073C20EAF85363DFF41357E626B3
+                               B19607224467413D185A05E7BFBC5F0D
+
+Test vectors -- set 2
+=====================
+
+Set 2, vector#  0:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951
+                               53F06534801F89F24E74248B720B4818
+                               CD9227ECEBCF4DBF8DBF6977E4AE14FA
+                               E8504C7BC8A9F3EA6C0106F5327E6981
+            stream[192..255] = 30DA9453A90909A5675D6B691CB0990F
+                               C423CDD8222EB47245BBB67BCA2B9C10
+                               8D1F016DF0CF8CEAF6829910916DBC1E
+                               113D11E91BEC3D85C47E3042EC865658
+            stream[256..319] = CAFED71B892EDBE13388CEF6A3365797
+                               E0D88C0D3A5B91BE4CBAF5162F69558F
+                               DBB45CA6F8C8D4C371D62736EC244584
+                               60131F54854F3EC804AA9A38E6ADE281
+            stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F
+                               2C3EA0F56AF46ED93DFAA4E16F5F0831
+                               2D77BD0E9122043CD6A202CBA9351F6A
+                               0E8E6263F4017355136A0C551E6FD0F8
+                  xor-digest = 023D719F61C193E4CCD87755C87F9604
+                               C5A29DD7E31637B3DD70D43441D48CC7
+                               D474013C85EEAB1897C80ED0A0272543
+                               F951C72E3954616CB5D6B51FC24F4B0F
+
+Set 2, vector#  9:
+                         key = 09090909090909090909090909090909
+                               09090909090909090909090909090909
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081
+                               2145B56AEA46EB283A25A4C9E3D8BEB4
+                               821B418F06F2B9DCDF1A85AB8C02CD14
+                               62E1BBCAEC9AB0E99AA6AFF918BA627C
+            stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58
+                               11FA9BB02CECF7440239FBB0497347EF
+                               D8F1A8AA71AFC70ECCD64E81388E6E87
+                               9521C2B47AD84F9CFD9E240D8D2F3001
+            stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD
+                               3C8D6A2EFDAA9CC11BFCC61D94F6104A
+                               4091B3634FA57AB0AB9B209F22DA5529
+                               75C3C322DEBE4AE68623BFE1B2BB7F0A
+            stream[448..511] = 35B290F85EBA78A978750690C4747E8F
+                               72621951483772E8B89876CC5D55F3AB
+                               02D9B8FB35C741279FF9B5B571B26329
+                               4D011F813CB5B209CA1A22D532BF09B7
+                  xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34
+                               F6CD0A795B8347E1441CEBEE35540D41
+                               64FC2B95D71FD47A2C4ADF732261EE52
+                               8125BE374FA4A90132CC1063971A2862
+
+Set 2, vector# 18:
+                         key = 12121212121212121212121212121212
+                               12121212121212121212121212121212
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD
+                               BD8853C329B3A881B489090853FE0F43
+                               89DA105F0ADFA9CF51DA2521C40FD2B8
+                               FB0BF80B93E3F2B3D8A8EB1C615E0FA6
+            stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D
+                               43A82A80DAEDBF29C048639BA38B690B
+                               7ED11323E3C0A8E77A16356705431EC9
+                               9F2CB7F7E1ED3B83EAF2CAEC00B00755
+            stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417
+                               376F334E6AEF9C187012C8AD2B94BE7C
+                               00A876756EB232510FD0798E72EEC87F
+                               75EC1467C07B3A1EFB0D51A5FA65E382
+            stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B
+                               AAFD131432CFD7D2F675E03320395313
+                               AD4ED96E9052FE6B2D2A17428660A25E
+                               EE642B712800BE3F7E44F21A1E6A03AC
+                  xor-digest = EF4E84DBD66497B142EEAC56B830FF78
+                               0465CEE20B9CFAF5727D4B3A588F4D00
+                               AAF718330CFF35508C44C1ADB8476625
+                               2CC3AA6AAAE74F8BF1DDB6D4AADA425E
+
+Set 2, vector# 27:
+                         key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                               1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676
+                               263C1CB9AB941119B19D15EBA3462F56
+                               2F69220595DE5E0E7C595FA40F1F06B2
+                               6EC32252AF05310809DDDFAE2E24B170
+            stream[192..255] = B29A740B51B4EA1080666337D5551484
+                               FFED6860A5125DC0573C8F90F23A98E0
+                               BA7B3E4C28C2CEFB1C33D2C36D1B7625
+                               64B9A67240CF174347A4C8D868F00F6F
+            stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6
+                               537C06AFB23354F054E25457B729B534
+                               CD10B2ABD45BE3E38DAF1B7A9103268F
+                               4FDB4C0FC9A80A003FCB907E8F249AE0
+            stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39
+                               F62D54311207B617B727FCCE1B2E762A
+                               060810C4DEF672E7D76083E3E4BED0D1
+                               0BAFD27CDFD2C937E660190D36B3FD7B
+                  xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C
+                               18CC5E1E3F6A317ED7257887446EF734
+                               65CA15F51AF5E077B7915062391D8497
+                               8F437985DD08F5FA3A8D74B3227A6EEF
+
+Set 2, vector# 36:
+                         key = 24242424242424242424242424242424
+                               24242424242424242424242424242424
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C845BA29D542FBED2D021C85188E119F
+                               D34967B79D9F44635DD45D2E41DC5AFB
+                               B237AD2FA0E4CF4202D83DF3073C578D
+                               2AA8A32D30FB45DE28F23CEB85E50FBF
+            stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297
+                               FD12081B4B23F0A32CE5B3196173C7CA
+                               7EDD03F9637E08CA501C4850C15B207D
+                               7AA724377396CED2357B572BBF9E69AA
+            stream[256..319] = E484AF567EF80BAE77461855294E9280
+                               EF57E7366605785034D639D6DE3EBB0D
+                               E21886D0E1E0679BC2E2C9C2D9201484
+                               4A452B6AD3F1AC8B7762FF3C0E405B3B
+            stream[448..511] = 595D9855200786BB575FF7977509F395
+                               7879CA1F19619A99174BF013CB62F85B
+                               FF2C3C4FE724E26DD0C10D7635A2491A
+                               9E7E868D9DAD9201465AA178184D06AC
+                  xor-digest = 08737B82505F46F4FF282EF42F387AA8
+                               0450058F5314389BB73733BC163D75D5
+                               D32FC6408F8DE5F6ED2050027D605FAC
+                               A7119FC2DC1B6D3E84E8048DCC42FBD2
+
+Set 2, vector# 45:
+                         key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                               2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E
+                               6E6320101999BCE5550C2BBC9BC65D91
+                               FAA2D72FA4BF46B6EE916244048B1D09
+                               A115E3AB6C00BAC8EE382B58859E8157
+            stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82
+                               0C18B867C561E96DF4ADADC5A4375E44
+                               5A34F9457E5F8C9A337A0C88DF0F723A
+                               D4509F1449DF2C6AEC0EADF4C7A8139A
+            stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8
+                               452A1A893EF034C51750388D294947EE
+                               3F505839C69C1708E8323C449C39A96B
+                               FC9EC91B0E1CAA8112057EB0389FDFD2
+            stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC
+                               EDD92C4461EFBA5CF1664B9AF54857BE
+                               C3D00319E5E8A89A8322831151EE1D52
+                               D8585AC79CB60B61ED2C852D04BB0FB1
+                  xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D
+                               2363BC12259B0FDB2BD8F052A572ECA8
+                               D1EF62AA9A48497805A413742B5AF5A2
+                               6DC9FF624B49E5D6FE58BBE5251B4983
+
+Set 2, vector# 54:
+                         key = 36363636363636363636363636363636
+                               36363636363636363636363636363636
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340
+                               42D4F07DA4D5EB05554CB7426D65C5EC
+                               A93C2D321175B6F72FCBEBA6E38CB098
+                               B72534F7D534B1AADD97B77E8513B482
+            stream[192..255] = B2466A173F436C8433F264CBF125B8E4
+                               C10BC81BD46B5C21FA161CB2AE07D27B
+                               F66812A2C2FCB2B14C23E413CEF4E591
+                               AD52EF810A000B42E5C1B76EEBB17739
+            stream[256..319] = ECBED2058DC50223614EB8635B834C3B
+                               B176719C18CA5E3D087A93E5CDF81123
+                               C6FB819CCAFB5042AADFED5E3C33116A
+                               FD92AA21031165A22F4751C423B8B945
+            stream[448..511] = 758BD9435DE607867DA256064C304C8E
+                               DDDF5B64173CF2C98B2842992F8C5FE1
+                               A37C3227B7F37D49A39F9FF929A883FD
+                               56DB8B1A174E1E55FCB21C9E1164C20B
+                  xor-digest = 31761A49503946701D35306FBCBE10E2
+                               02967E7EC14A328B4DB19FE79F03553F
+                               13A012B7297B2D02F18A216AD24A682B
+                               299518C3769123EE86A4937DAA9FC39B
+
+Set 2, vector# 63:
+                         key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                               3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B
+                               26A4E7E34C0CA9CB9399F655E566383E
+                               246143F57776C8E08951E87F76091FE7
+                               2356CC901F09A07895A890AECF047B3F
+            stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF
+                               C862100A07E55FB449BCFA2D9BD48658
+                               958B37B3EA3565FA66824102A14B5770
+                               5E3914E0680E116ED58212CBF61028E3
+            stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701
+                               057710F24C01E680F58090B8E949AF01
+                               8970A43A698A04C0C8639FAA665DA3AA
+                               562B2C5C3A03BCC38FE75DC1821ED718
+            stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948
+                               821FBB049DAD15B988A77C0247868A38
+                               2056B66F47B0195FA30C9DB5A2334A9D
+                               CD7C0D22E479FAE1BBCDFFE60F261C7F
+                  xor-digest = 94D41CCAD940CED3C854DA0796DC62E5
+                               6B566A980E34F353CFFD0F53AE9E34FF
+                               A6A057645FE66D86BE30F93805D9E2B5
+                               D78C68EEBF61CE387277A51EB2EF835B
+
+Set 2, vector# 72:
+                         key = 48484848484848484848484848484848
+                               48484848484848484848484848484848
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E45194379659D1D8904DB3698AF8B245
+                               762910B7FBD019AD1AA20A6C433B4C80
+                               308A9EA68697631646BF3A2107C4E7FE
+                               2235E8F3262A9DFD3F5CC23FEB0B2DAB
+            stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA
+                               4E947598C4757976F6F61DA5F0DAC8BC
+                               DDF72F08BA2F446FA37F9A490F6A2B6D
+                               79227C93271D6B763DA7B2A907220A42
+            stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74
+                               A43D83AB8ECBAC5206D108F869561D70
+                               F151A0037F8E28951B5026643F8B2D6D
+                               56A62E259F04A5EA304791A9468E66AF
+            stream[448..511] = F70794C084E6EDC07BA0347413B05FC9
+                               FC46994CA820CE4FC037ADBA50EAA9AD
+                               55064ACB7308CFCE3F35AD5C7C628362
+                               F4210FBC2D3264F734728626BABF5356
+                  xor-digest = 31815B36BA034BB1941DB1E45A941A59
+                               7C3882F34BD3BF441CAE8A9790B05BCA
+                               72049FD10C09A14AC9DB867A82C38A5F
+                               524C72F783DFD16980DBCDEB486FAE96
+
+Set 2, vector# 81:
+                         key = 51515151515151515151515151515151
+                               51515151515151515151515151515151
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6
+                               FF53889A9979ABA8F23AA51DB1EDB8E9
+                               D08F696C1100799A7D004DEF1CA94110
+                               FCF0C054B0C131E6FAE0FE2F2DBF22B3
+            stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC
+                               55A5F3F19C5A10E12EBE46DD84F10385
+                               33837693588D584FDAF86E3A217C3CFF
+                               020278736F1A90CE07F0DCE4329005B9
+            stream[256..319] = 135FAD68B5282FE59B28D2DF66463632
+                               06CA92E84A73FA131EDDCE89A5C23B4D
+                               08FA57D455BDB32F8ED58DAF3EF288A2
+                               7C72020E35DAE19B446E4C52DCDAC5B1
+            stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D
+                               18F2111002891D3229102D72605B9BEE
+                               F5DA36059B0DBBA7646927650305431B
+                               FDA4A97570CD0C484BF1E974B157ED7F
+                  xor-digest = 5125E77698C0DAA89A7E47DC5D038D40
+                               7B732CE56CEB674CE653A1B6661B2740
+                               0C092AFF83BEEE4FC4543B9D725C9387
+                               2F89AA338222ED677BF59397200AB304
+
+Set 2, vector# 90:
+                         key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                               5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21
+                               75E9AD91482965B651B495AEE819CC6E
+                               C42AFE2C20EEACCEC4E90710D17210E0
+                               4CC6832905985322C8007F872D3E58E1
+            stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560
+                               D692A020F0A66F609374ABDCD1343722
+                               05F19CA04EBDD3009844BC540C1B2B41
+                               66D45E8A2E822B906DA34649E7FEEBB3
+            stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF
+                               CE2CFE99506677A956AEC86BD290B6AF
+                               C5298A448D0DEFA99AA5CD26D318982F
+                               E786D809C713D5A55B42CA6650191DDC
+            stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225
+                               EF6E3C21705EC9FB24873916A2C24668
+                               963C03FE097DA8224A42A99E5DFFDC17
+                               68CF518DE49CCAC8A70216C62C9CBA6D
+                  xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5
+                               5FF58B296071D5D39349A531E41F0BA9
+                               893A1722B6102740BC5FE394A49363B9
+                               6A626AB43FD6A288CD9B23F7255279F8
+
+Set 2, vector# 99:
+                         key = 63636363636363636363636363636363
+                               63636363636363636363636363636363
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333
+                               BCB02E3AD8797377AE1F1B4D6DDB86E6
+                               2A59791CB553550E0492FAB42C7A2C42
+                               3157C5092D2DD37D46589F17FBD86584
+            stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91
+                               4122EEE5736BCD12061C77DF5B0122B5
+                               1784E946B4E93470170ACDD7E2779591
+                               57BCC9B9F3E11E88BC2F740AA0C10C97
+            stream[256..319] = FF22D8196AB3DF662210D12D0FE79255
+                               6DCD39611C07F089979CF7D693A30CA3
+                               5B795B7F6D64931916E717C8BFB92114
+                               DB75118BDB51D142CE8133415C6B3456
+            stream[448..511] = 971F007EFE17662D95F47F4F28266516
+                               B22A1E50755EEF19149DE3A3121F5FEC
+                               E0D9DFE7A055026CA44193542D7687EC
+                               695B97769BF02F92C1EF3D904A8010C6
+                  xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163
+                               C8D54A4CA36748C74721C7B6E1649A31
+                               4B5B7A4BD43E7C3D2A22F0C8446C7892
+                               90D54D421D37CB16400E59CC86215CC8
+
+Set 2, vector#108:
+                         key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                               6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6
+                               54BC11ECF0010D2AEB9F899130F4AC2A
+                               38EBC15C8831D591E6675DC1CE7A471C
+                               4B869FE83CBF37AC70BAAE5D4AC607F9
+            stream[192..255] = 518F298A6008532EEFECB3DCF72103BD
+                               5E3F84FEB6EA2311E8C19A2E93A9C3C3
+                               BB1DA7DBA78D5618D1C4FA5B0B202728
+                               62645A361E55494D66C9359E41E5809B
+            stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A
+                               89BB20CCD92E7F13FDD816DD4E4963C2
+                               C5FC2570CBB8BB5C70848B73001F508F
+                               47AF179528200F51CDC6E4854EAA63C3
+            stream[448..511] = 844B1D15FBFD1264169279ACD525611F
+                               A39C7BB41F1E7A1C09090625F7926E51
+                               23A4CD7FE1A3F37ADC67AC437BF0A5AE
+                               FFFC6FB0ABF39D9908145004AA5B958D
+                  xor-digest = EC67596C9DEF4012A2D543842829306A
+                               4285A3B8038818F265065DC848BD80FE
+                               C27C2F66A57B27F7FA8AC912001EC954
+                               05BC6E93D7E555C59060F5D2E294D103
+
+Set 2, vector#117:
+                         key = 75757575757575757575757575757575
+                               75757575757575757575757575757575
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 91D2772A18995DB3C0801DD3740F4466
+                               F9535E5BECB93DDCA0E94D19C0B57BDD
+                               0FFBA9DAF0B11D55C852927F8BA560EC
+                               4999E25848D08FCA7275E7E8571A5F1C
+            stream[192..255] = 72E64FF10CA9F07CC493715724DA7610
+                               9E4358E8B0CAE451348B784A162DF036
+                               AB9796724D17FDBF356031D080A6631C
+                               D1E8D217B041AD2EDF427972653206B2
+            stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3
+                               344956C29D10374E502C2EDD177ECE5E
+                               6625BAD9630DAD57976216CD69865058
+                               130B132FEC1AB0C350DF4DACE4C7724A
+            stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90
+                               E402466550B518A177CD05985D238827
+                               BD92EE7EC22C274F19E682F85ABDAD95
+                               D0EBB3DB6C6134408353C8B0472C9A1D
+                  xor-digest = 9A6C893F2108D13A29373DEDA65386C4
+                               AC356BDDD4A3178952F9126E322B7AE6
+                               83C94F1A131CBEAFF26549D9F84CF04A
+                               1241FA374B055B0ADE7E49E8EC669E65
+
+Set 2, vector#126:
+                         key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                               7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3
+                               059C5CC575D806B9029CCE3FA45A246E
+                               0EBD3AB2F2E324FE36ADC3B56AE2F7EF
+                               C710AA964CB87381386C2A88B1308035
+            stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E
+                               20BEB18D9C84187C347F43B17E0924F1
+                               2348F825E106E57A00258CE4415294D9
+                               4323A9812D8A71359CEC1001BAA0D567
+            stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5
+                               32D62E779FA0D2D08F8ABB6B0183A4DA
+                               4EE0329215F261D953150B9AB9FCBE2F
+                               568AAE361EAA8636ECC01A63F007977F
+            stream[448..511] = E7C44F44E06321A20E25F73E2069757C
+                               90499DB7E60025CF6D2D445E53A665F3
+                               08EC96F6FE73C0AC90D7E4A712E18C2D
+                               3DED46DFBAFA24C4B0B329E52C525976
+                  xor-digest = 22035341489FA6EEB2A6488CA42F4043
+                               57477C3F55569A1224EC39B1019E90C8
+                               21D37D78ED4DCEAF6EA70724C3751760
+                               38CF25DE4F84BABD80424D83A310881B
+
+Set 2, vector#135:
+                         key = 87878787878787878787878787878787
+                               87878787878787878787878787878787
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191
+                               3C69F2275EB97A1402EDF16C6FBE19BE
+                               79D65360445BCB63676E6553B609A065
+                               0155C3B22DD1975AC0F3F65063A2E16E
+            stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB
+                               3373B816DA256CAAC37914B0C161E4E4
+                               5F5ADBE444098A5B2A4CFD4251D79918
+                               987BB834BB50F0834EF4985F356B92A2
+            stream[256..319] = D89642D25DF97D149AE07EA18BA39497
+                               8935978AC34C1DF9F444986D7505DB4C
+                               7E08DB3616B84CD52E7DD7FB108C36B8
+                               B50C2573172F4D3500B6D62A9D20B82A
+            stream[448..511] = A2C17FE7371604556F796429C6BE0688
+                               8611638B310F3E9FAF484BA9EE29C16D
+                               2F842EAF33AFEC557B68D2F453569187
+                               A6F4CD204A0E7A733E81AB7CE9FCAE81
+                  xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B
+                               6E3A61977A7C6AC2F033B826AB9A9957
+                               66671D2A1025CDF8E2824B2F58CB221D
+                               2A68679239D90152FF7D0D39B33FAB93
+
+Set 2, vector#144:
+                         key = 90909090909090909090909090909090
+                               90909090909090909090909090909090
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6
+                               71A6D390BC7099A708D370DCD0E3D143
+                               A0334619EBD5C7DA9EF6301F29273F85
+                               2DFA3C580ED65C6E952F88A0B7FE368E
+            stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B
+                               445792061AA0539DA69ED0B77B970C0B
+                               482156A5DEE4082A61364BF06E692399
+                               FB9F4411FEC515291F8949B20F57229E
+            stream[256..319] = 993E815F299D4841518119BFF88F6EFB
+                               F3DB9BAE60238BDE2845DE4DBA6D79DB
+                               C9E42BA5C3C004AE4546FD86C660FFC8
+                               FD6A8A349669FFE3D9E5BDF8E50A407D
+            stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2
+                               1274F4A6D814B5440C74D53A3FF0735D
+                               EF01B14AE4188E215CE7337C04871688
+                               7159695A241BFB9D6B489FE9E23B2AD8
+                  xor-digest = 0BD5739ED28778023E6303FD88DAABC4
+                               0FA0A211A1A5C5F230D9E67DDD9EA517
+                               FEBCDF0BDBC107291B6CF3ACD8B862B8
+                               4BF15400493A54036E97FDEBB9A1DB2C
+
+Set 2, vector#153:
+                         key = 99999999999999999999999999999999
+                               99999999999999999999999999999999
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC
+                               BE99E7E515650511FF7016A0EF287ADE
+                               5A03839C4F83F05FAC3B0B24D4E3F602
+                               3251F8D9CC4530A805F8A6A912EFAB1C
+            stream[192..255] = 792823ACE2C0DDB266A118068AE295CD
+                               716E424D3B98A9DB2501A3F5DF7DC70A
+                               3BD2C6E664D5E13317D6F57B8774C903
+                               D407D2BB6014E0F971141E89569C5868
+            stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB
+                               304C81FA9DDE0C21592247C4098D9347
+                               1DA30294DE8C100E5B17A199F744CAC2
+                               4E33490FC7F223FD6B4923056117C6D9
+            stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59
+                               349AF2BB1DA2BA622B9824F729929098
+                               BD19DFC05D0D9454F604960C027752F9
+                               7812E53DE6AC6CD2751AB331703646AF
+                  xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2
+                               DC458E7E517637596FC8FB710E2E5636
+                               DB1F14848CB12793D54ABD0856B22F3A
+                               ADFA8C33AD08B8CC5292DD76913CB105
+
+Set 2, vector#162:
+                         key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                               A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229
+                               8A8806402755660C4A30CD216A500BB6
+                               AE975E08EC62D08425A8A62A71B00215
+                               DE35E5178902348698528CB82296F009
+            stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C
+                               E4F7E1B3E78C3A5DF07592F45B968BEF
+                               F95B8B257DAF2B468284627AF4481FD2
+                               67BE0B164DD86721DC8C1607A0607EF0
+            stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3
+                               9C056162B626F383F3E77B5C98C0FBE9
+                               119A7C335C333E6490126AC2510CDFAA
+                               86441C72D1DD9ACBCD3FEFC0D0C794C7
+            stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754
+                               246C065AD23A8D709161FC74B34E23DB
+                               B918EAFA4465125D3780BF0B5803AACA
+                               037AA0A14D977141B611A6CA2278B634
+                  xor-digest = FEFDA1A6E95920B93380CC24FAE214C5
+                               6B009ADCB176D519CA4B8538EDFC95D1
+                               6CA06B730B28A230F0085FE43CBEE2FA
+                               2EE5DCD74D66F5CBB59F256CC1ED885A
+
+Set 2, vector#171:
+                         key = ABABABABABABABABABABABABABABABAB
+                               ABABABABABABABABABABABABABABABAB
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 22E1A884ED2C67CCB2977105649B6544
+                               367858D1A730AA2FA96703FA406B337A
+                               B2159A389BEF48D8A215D870B2968E16
+                               B11571F12BEC0A07FA7D3B9790987EC7
+            stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74
+                               B27776E9250B8B063E52E169C7B76A15
+                               0D699278AA4124427B5EB6AFC4AD5DBF
+                               600FEAAA98A88DFF297DACA5ACB4878F
+            stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484
+                               976B640E60CCD6ABFB908583ABEC3E75
+                               2878371EBB5374C9B37A63E0768AE10B
+                               D857253D940AC408EF49EDD590E806AE
+            stream[448..511] = F012E429C44D5DC03B88123855B62C0E
+                               90E06759306017B5773752973850531B
+                               C480316CBBAEDE6353AD5FB298349AA9
+                               16AC0221A4CE1E4729BFB9C230AAF9FB
+                  xor-digest = D73B872315F9052C67C4CFC5CD912DBD
+                               60DA32FD06D9C8E804968E688898200C
+                               1D979DFFCE52E1C3B3309B58D12BDBB3
+                               D3EBA2954D1587D720E004E12EB4A13B
+
+Set 2, vector#180:
+                         key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                               B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88
+                               D2EF924014F7445ED922E9C021571909
+                               D7E6BFCAEE0724F2A9C522C4BDE4BBE9
+                               FE53FE592C0FEB80D2C7A51FB8BE9EF3
+            stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484
+                               0D22CDDFF39EB0E3D5FDF74C6E7B3394
+                               A0A4271D780DE6DEE9AC58B4903EEDD2
+                               6DD14E14A4DFE506748D5DCA6DDF4C5A
+            stream[256..319] = E79D99119996FBB5163335E2F79F0502
+                               7AEA5372136E7B3C5BE1F4A673A2DC74
+                               60834B81BE6C4976C4A727C8E6046A64
+                               4CAF42EEA6A068B7E532581E9037BE9F
+            stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614
+                               9F3EE55A136EFA3B417DB63D2487DF82
+                               794E161B3153DDB2E1E4F385E1A848C7
+                               729FF5CB1CB58D5E73FAB1F2DCEEE5AD
+                  xor-digest = 2F3C231B0228C274255F3BD314ECC7F3
+                               1B9C49177009AFF2CD88F807092D77E3
+                               C74C1B9B8650F581EC7603F4D6E70955
+                               1B00C3192414C04AB0AD8B0B9BCFE988
+
+Set 2, vector#189:
+                         key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                               BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410
+                               DED6D4E331633C5621B94E7EBD15E856
+                               04AB202A553EFED55A548C7AFFCD2550
+                               60315FD50A305D8BCAC9C077229D34AC
+            stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF
+                               3CFD130D5B6A9CE37BEBA429AD137A82
+                               44D0586FEB16D086F533D1885A82F73C
+                               F2AD2C645591F80ED09942F0A08D898C
+            stream[256..319] = C214B6AC700164FA66DE346A27A99463
+                               C5B6C0E43A9057384BE168E163058FCB
+                               6E7DEC871C6531EFC8B8D581EF92757E
+                               219294D39E0C9C8276440BE56C3D9941
+            stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE
+                               4C8D2171695C9CF97E2936A8BB320670
+                               015825547A508EB43D96F2EE1EE2CB34
+                               4E120F001500F8ACC3E19E30455D09D0
+                  xor-digest = FE5928C74EA21F23E29171E5AAACA20C
+                               DD8571E907763C96B99A8C11F9A1D2F5
+                               78F68A6C440996995F7AB6E69B3CCE33
+                               CF8CE0C16F54355696D47DBF82EA8D56
+
+Set 2, vector#198:
+                         key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                               C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 75559677D7C762F6CFED942D800F2FAB
+                               AB5F3892DC2C79922E96FD34FE511C11
+                               251C8EB7C639E531CE08A8C99F62E7BC
+                               F68FBAFF99D62348FF91CCFEC2710055
+            stream[192..255] = 149806A4D862EEA81F0208D927339E5E
+                               C98E9C2A6E0DB85CC0380DED7EC5B8AC
+                               4ADAE76AEB9C7B7264C3834316209615
+                               25221D58C0174577110596FF89C8FC69
+            stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B
+                               3CDD19BF89B31FF75A814F470BF97E0E
+                               1293B750B769F5BDD750DE5025D7534C
+                               AD541A1F26C6AE9AC2FD3237C156AEBB
+            stream[448..511] = 0958243E88921B81F04AE63658E52D76
+                               CF2638495B3A6B970633A7C8F67B8CF9
+                               AC378082F72FC63BEA02881CC5B28D9D
+                               C8C261C78B2872B5EBFC82336D6E1A28
+                  xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7
+                               0028A08A00EF935C06A8B3632DAD5914
+                               84E44E372A753F8E630741266C0F4218
+                               4923608103042C70ED4ECC5112B9AF6B
+
+Set 2, vector#207:
+                         key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                               CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28
+                               98C701CBF5E88F1F3DCB6B873E5CAEEF
+                               23024ADA678E1A2CA9E25AA8B476CF4F
+                               9FCBC297FF03A9B94A5A736274EA776C
+            stream[192..255] = 73B9891D1770289A67D6338909FB6282
+                               9A425B7947FC30DC52B11E398E85B1EB
+                               537E1C02898FEBFC15A9172C254CA55A
+                               AA1B56EA856F47E37E2F252D92D94ED8
+            stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4
+                               38B63B9F436FE00CC075C585297B8F90
+                               E6062358D29641FF9C28EED4A23FC53A
+                               6B5C60C2AF1E8146DB27CCF5F43BA838
+            stream[448..511] = 642541A9733946827D79BBD815C03C17
+                               6357BD6E81E9A61FFFD4A0BF6863AC71
+                               72AEFB92C1F235641BBE1457B724A6AA
+                               AF9FAC687552A778B034C4A4F8E41ADE
+                  xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668
+                               BD0BC5A97655978E79056B3D25DF3E79
+                               5D5D8BE5D1AAE877F2E7D03225CB6609
+                               6EFE11CBCB728039A243E326437CE73B
+
+Set 2, vector#216:
+                         key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                               D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F
+                               1F7BDFBB81428FFEE9FBE14DF5F5F3D8
+                               A044EF53A868D989E16165A0F2B95E8D
+                               83439BB4805A125AD0CA7994AE11B852
+            stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184
+                               EE7A7F4B822A1C955A69E238022AA313
+                               276C2003E27AEF1B4F94B33A6428685B
+                               F048B357EAB297B7DD98E612F054A317
+            stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C
+                               978B976BE1B6CB0D15C0324D6B70D265
+                               385B615B3EA97A55D94C47F53FF40861
+                               4460857AC9568556AE54A52546B41B5A
+            stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6
+                               5BE2BF56D2B78A401D5761E2F3AF8B18
+                               A2B1089864999D9B99E5BF6959F8F802
+                               975FBF204D6159CF23F3706CAF0D9BA5
+                  xor-digest = 0957D6887501D4360C430614B67D99B5
+                               32849E2F5C69CE8A9F3F707A2B5438BD
+                               0C1237B5617FB525CC9C043A10DBB265
+                               3C3F0A353E89A19838B8F68542E09526
+
+Set 2, vector#225:
+                         key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                               E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A
+                               50CF101BF065F69F3E78BEF5D689B1D1
+                               D306FF41EB3E78BEB75C4200937CFE60
+                               E89E370680C519B2F64E23516ADF8062
+            stream[192..255] = AA30580A210B87727BE17EC52AAAD037
+                               3E0DD11FBFC89B37825CA4D6F9E8D433
+                               E3EA54C37D678B58CE834AFA310F6D4D
+                               06B4603F12DBF38595AC76511D0B13CF
+            stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC
+                               8FC9B09DAA6F418D3434BFBBFF6BFFFB
+                               F93F8A963F2F51CC487BE868F010EC0B
+                               EE17A480542A301E33B36F59BEE13D91
+            stream[448..511] = 672048756C221C12DA6178BE711B3371
+                               525A92BC9A219CABC5501B0DA4CC248B
+                               8742E8BCBD6F5A1CFE522F3DF3BED6B6
+                               5D60D1AC737ADC582C2CB9751521828B
+                  xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB
+                               3F418EBEB69509D69B2594E964759D15
+                               104F674CD44681AFECC3B4939CA0A0C9
+                               DD7AA5726653ED3FBFC833DDB0C87B42
+
+Set 2, vector#234:
+                         key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                               EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2479A8F2872A813D16D15F060D300237
+                               25297B812F6F3B97D74D9716E4403A5A
+                               684D2BFD1E15275470FEDADF1578277E
+                               44C6C06B8A5FCE3D0CCC5E13BF49947C
+            stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3
+                               132D4B0065A563288F848E05EB45E48B
+                               D15C069C02F90B4FC10AEBF1AF4BF90E
+                               2CF7F48C8CD7A8091014131EBC21FBE8
+            stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C
+                               EC170B064429EB832924CDA9C47B5174
+                               9BFEF80D96FAE36DDA65659FEA1CC06B
+                               4EA3A1601A3304AA4DDBEB62381FD4DB
+            stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145
+                               BFBCDBAE19F5281CD0E6AA37419778DA
+                               64DDF68726DD7F4D78BBBFF4576C2AAD
+                               93F477A2AB2C3CA8A381F30BB944C7B0
+                  xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070
+                               9EC7E9B89DB8EEA11045ACC5FF003DC9
+                               CD3318BB6F9675EEF20E15490F525066
+                               AF8380C663B60EDBAE30663C94C39892
+
+Set 2, vector#243:
+                         key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                               F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CC3701E703946194401D1BA23AD99B5D
+                               F3F856138E142D4B9C23DC9F252A277B
+                               D62DAA33A71A0C61079AD5A20562291A
+                               B6EC92C66D7BE6A17E27D4DDB48EFD31
+            stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903
+                               D565423614409AD11E821B83F5B35D83
+                               F26F3EF9EC1766FEA9C21C09E0AE248F
+                               4BA01E48BCE09D06471593B3466703DD
+            stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF
+                               96CDC215EF1A62FAA29A5608C852FFA1
+                               18B473C5A7319446F3ED2E8AB39A533D
+                               714325D1B14E838C9EC6E037DB0DD93C
+            stream[448..511] = 4FF3B43841B17A279002EFB07324625B
+                               7E937D480DC73F12836195110ECB4DB5
+                               CD31CA4F92F612A95E82815328DA7D5E
+                               4DCC5BB6791603EDA64C57B5A5AAA04C
+                  xor-digest = 9202B874C48D4B1A9E857E645EE8F884
+                               D971CE97923AC024ABEFB944E34550CE
+                               31712BB832F9174F86FCD369E75CA9AD
+                               85095F43A4B7F33AB641BD6912D2C59C
+
+Set 2, vector#252:
+                         key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                               FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F374DA745A5CF93A567027609E5D3B1D
+                               5C3C8A4D15203705D978AD42279F6548
+                               51FF713F5120CC93D044EF717F5A75E4
+                               98DBEF559E5F157A8C819E213E93B3F4
+            stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9
+                               175AEAA99D55485954B265B5CAB86509
+                               C810E664766A8E6C90D4BEE3A58B1815
+                               9076959FFFA2F30EEB12343E9E7778C5
+            stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC
+                               418DA96336991A27DADA74FDA987B867
+                               B125C53C0E4E2889FDFEFBFB48797A22
+                               2836B2EA42793CE2BFFD568F6234B368
+            stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36
+                               4CD2D730DC8D7E183EC55A777C2445EB
+                               BA7E9CD95C8F3A206B73C422AC2E2C08
+                               15A8C6FED156FFF93B63DE512EF69725
+                  xor-digest = 467EDA43B849054EE747A532ED0D9AA4
+                               6EA1BF2B6AF19F481D6E3D55EBAA96FC
+                               6629FE65B5EC4B5EB6A155A6D60FEA32
+                               F04F8230E26390F1C8FA53D47B68FEAE
+
+Test vectors -- set 3
+=====================
+
+Set 3, vector#  0:
+                         key = 000102030405060708090A0B0C0D0E0F
+                               101112131415161718191A1B1C1D1E1F
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 7CB997D6E1B46DD7C0A9629B441C3771
+                               14D6C18F230291FA7EF0B039AEDCC9AA
+                               A4AE05BA13F3931E3F8373AA320A8BCF
+                               28E825B2084D0FA486BE52C92C3C6F14
+            stream[192..255] = FD4DC85E176D76062323B2F5B31E219B
+                               786596F3DC0A2AFD31AB48C5F911605D
+                               556399114B0779F43221FE5BDA899627
+                               BA6498C210D5AEC5FEC8733357571F77
+            stream[256..319] = F00E84A92BEA966DC8359FA63B12E8E4
+                               F5611F6C8CDD04CE9D605D770B2EAE49
+                               D6976272057CF275EB5B4CC434EA9B0B
+                               8CD9FEA22D7E919097CBB36C5D239BE6
+            stream[448..511] = 110560BCF38CC42478036CC228E9DBD7
+                               4C44863DAFC81B528AEA2893FDBAC7BB
+                               2F68CCDF566E1602623EC9AE283EA69C
+                               C032E90E409F368E28401AE6905BD4F8
+                  xor-digest = 9CCCCDF3F7D712D6E3931068138F9A9F
+                               8640478BEDFC3C7CD0802954234DD07F
+                               99F4B072D9847DEC2E16FAD0ACCB3609
+                               16243175C84A317191A98AFF5EFCEED2
+
+Set 3, vector#  9:
+                         key = 090A0B0C0D0E0F101112131415161718
+                               191A1B1C1D1E1F202122232425262728
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0889D6D9E155FC208941B945F2B15362
+                               3CE5C79122C1085FC172836FA9B06C0B
+                               50910CACF399EFC9CD9CC484786AAC8B
+                               377972E9A90D7EDD40A59FE1B942710A
+            stream[192..255] = A540BDE9860D8687A45D8CF22E00299A
+                               36BE590AC92E70BA03B8A5F2898C2D1A
+                               B9B1E5C87C4B10C9B6E08EB868AE3B10
+                               3BB95C30831B903A3A9620ED16B96210
+            stream[256..319] = 90E2A684D3960A4B1DA5DF19BF569288
+                               5A23892F2003AF2319FED9C8D37B8702
+                               7E61290E013FDF93683829DB99C177F0
+                               222EDD6A0FE3D5F7F903D3CC15C6C6DF
+            stream[448..511] = AFE7454BF77E3CE1050ABFC2E25F9B15
+                               011F33B93660EA4AB5E7BFC513F2D787
+                               27F8008ABC1E14B06C36F7750AE88C1D
+                               7AA2F6EB9F2E925CD6CBDEC5FBA3EEA8
+                  xor-digest = F1A8C58EA8459686DC5BFA2A81E80653
+                               EF6141903898D1A3C7298358A79D674B
+                               A971C106CAB035722F246D3E67D34543
+                               3E71DD374DAF73036EE55E6C0ECE5FA3
+
+Set 3, vector# 18:
+                         key = 12131415161718191A1B1C1D1E1F2021
+                               22232425262728292A2B2C2D2E2F3031
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = EB11D29C989FB09961A673D8412360B4
+                               F4E6DF0169A3CE207656A7C72D6FB8D0
+                               95CB3A7A6CECDC2E167CD35F62A00110
+                               EF09FD32B61A8B405A3F55A1313F0DFC
+            stream[192..255] = 8ED27EA005A3E298560C829380D4F1E9
+                               F0C7FD5285F04AE6FD66C94CC07C8C51
+                               EE8163B7414A52B0594C5F7F80104D95
+                               0858C9A52F3C156ADAA025C00B180429
+            stream[256..319] = 12DA63247282599F2C50B172CDB4F31B
+                               20952134800FB8BCE743BBA90E6485BA
+                               057A9C5E0989A8FDCEF1C88DD54E920F
+                               7028EB284306FE6A87B0FE063DAB9557
+            stream[448..511] = CD447E9F58BAFB77F6E02AB5A692120D
+                               EC4F7BD597DE5C54523A7944DBA6A3C8
+                               D00000D3E70F7D9292B7135A7F054812
+                               4B98680DEF6631D2D10E0E7B08F188BB
+                  xor-digest = 6EF765CB84937D5E829A1A1664EBD23C
+                               B474FEA3C5AB137F2D9B35BBE0816EDD
+                               B26EC14D74EFD0F9768C521A6FAAF122
+                               B5E34A36344FF0F0DB3CC2F2780D05E8
+
+Set 3, vector# 27:
+                         key = 1B1C1D1E1F202122232425262728292A
+                               2B2C2D2E2F303132333435363738393A
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A71D4189D1338531D3C03D00A480C8B8
+                               49C779B7E113FD8D59516164C161EAE3
+                               AEBF74542FFFDC2FF8C2666FD5AAE413
+                               19072673F958F498F8FB9743BE46863B
+            stream[192..255] = B0B3803396AFF1646369B6FAE62EDBCE
+                               5254E7C8FEE88F9EEE5D8A7B6D44ADC8
+                               B89895198E3C147FAE0C9B8325EB3501
+                               6EADF77C5D7F402CF3168448D2A59E23
+            stream[256..319] = C1CCE6956C8257947C004528F568E3CA
+                               BE9ABF891E2FC2B52D9A1E6EC97A22B1
+                               FFD1C77E50A17CB47014C9EDA1853AFC
+                               11526F6268102780ACB3E0F120398AD0
+            stream[448..511] = 765857312C8994EF6BC7259673F02E38
+                               B7E0A764FB70534190033FB1BA86D5BA
+                               3BC6851DB596970A2F60831EA1A31CAA
+                               96085680CBCFADD9C5F0330CB72AB5E2
+                  xor-digest = 30EF19DE0E750BBF6AB3FC924742CDCF
+                               62B2FE5F25983BB9777C727679CAA39B
+                               1280AB468051463E7EB287AEEFA5AD0B
+                               9C9DFCA45A3124D5F41F4B0AF5849E62
+
+Set 3, vector# 36:
+                         key = 2425262728292A2B2C2D2E2F30313233
+                               3435363738393A3B3C3D3E3F40414243
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2B9B987B7CADACD2FA50A53A9F9F44CF
+                               4ED11B3E25FE57F1372C6D570B470AFF
+                               5FCF3BEB89D0692D873EFEBD26EAF3E1
+                               1B6892913F0CB27F3CA9BA20AF7A98F8
+            stream[192..255] = 0148F54B1D24F3D69A2086D6938898F5
+                               25BDB1B1F78C5F92BA21FCE803A52591
+                               FCEC9A1AFB0FB3B081CDB1D79D254845
+                               40EB9D624B5E113A4F143716722687ED
+            stream[256..319] = 271FF1107AA8968E0ADDA5371F40224A
+                               D8E134AF80D5ACDC9803B1B3A9819BF4
+                               8ECC3A68B303E1275FA97222F7E984EF
+                               9C73899433230FD746DA6101DE37ADA2
+            stream[448..511] = A66D3BB64C35C71BBAA3F5410F388253
+                               2B32897B1CC1AD610F3AA195CDC1EB82
+                               0262E817374384BFBE200339B284ADF4
+                               BFF6960B6A41AFA9D7C9B67B19C14C37
+                  xor-digest = 3CF10A4A8BA3E0DA3C0B63F1B913B57F
+                               BE47580DF7D90B13459A9BC98B93B014
+                               1185E910EDC0A5B37206542B17CAB8CE
+                               F050A4ED3D7097B6A0738095E4BF7A77
+
+Set 3, vector# 45:
+                         key = 2D2E2F303132333435363738393A3B3C
+                               3D3E3F404142434445464748494A4B4C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = F32665A4C73608E133D85712D2CC9A76
+                               6D2B83311B3F44564A56A97ACC9B6492
+                               B282A2E62A435A7B7799073E010C78C9
+                               4B7B5BD1B25994D1CE31B51CBB13BE90
+            stream[192..255] = C9F24592930A0A9148486D77C1FFAAA4
+                               4E4EECB088D6AD38D73B195E576BEE56
+                               E2CDA968FEB85D19BF89391813501B02
+                               EAB39A2E78B8CC7456EE60EAC3454051
+            stream[256..319] = D8E1D09F074708379189BBFEB1E24053
+                               E0BB5980FFD0371265320C3047F0ED36
+                               A65CA8D0DDF20DC25B552E1882811C77
+                               6613DBB4297DC6C89E31529DFCD17C82
+            stream[448..511] = 8012813E7879B3E99C40821A97469BF3
+                               9D2EF3B888E3118275F47F8C78A5F7CA
+                               19A98B1817D2D7734E69C5ED43773D68
+                               FA100E2C37F40FF8E018DBA52C5C239C
+                  xor-digest = 8AFB9CD876AF4F9693FF4FF511D89957
+                               C8BB31D9DE3F21B726667681F805FFF0
+                               4B50850696D6C2E5C271D199CF49F1E6
+                               D366C7824273E99360BD5A294E415F0F
+
+Set 3, vector# 54:
+                         key = 363738393A3B3C3D3E3F404142434445
+                               464748494A4B4C4D4E4F505152535455
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = C72B0F98EE5C2D44260E929C70DBF174
+                               02C03543483178C8BC129D67FE2746E2
+                               E881F8439E2A11EBB3716ADB16207BBB
+                               91454A71C444445CE64003F0BB1F481D
+            stream[192..255] = 5590F4278E78AD19293525095C2F76E3
+                               B35A3858CB5912B62304180225BDC985
+                               ED955521436DEC441B9C742B3C5F4CBE
+                               94B99689048AF93E48472980D058807F
+            stream[256..319] = FBAB34E9F432546EC8C52750DA4D2278
+                               4C1323D4E3F4E9B63E65A7E3C8B2637B
+                               AA5D0A3B897113F68C63CCB78B5AB40D
+                               0A0DC3EF1EB09DF5C4770B343B6B5155
+            stream[448..511] = 78B0144CDF2692F0D0F164ECC8621F5D
+                               A00C401007B82AAE7753712FD6185E9D
+                               7ADC8CFEA6D5BBC2F3EDB8BF2C77718B
+                               6A424BAFD30C30934FC645FF05704BB1
+                  xor-digest = 835B5361A9C1F88223DE7BCA09030CD4
+                               67065AAE99198645029CC0AB9B9BD579
+                               14332392ED7A433A64D95B44CE228860
+                               7E029235580276BCAE88F37418FB641C
+
+Set 3, vector# 63:
+                         key = 3F404142434445464748494A4B4C4D4E
+                               4F505152535455565758595A5B5C5D5E
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 804025A410EFFBA58647A9F4B443BFC6
+                               1CDDC30CA04DA8DAB3EC6A098A830D68
+                               2683B59B76C60C09938E67CB41385315
+                               E2504B024DB808923B0909EFC25F0927
+            stream[192..255] = 7A4661190129E3F349DA7B44DAAFC388
+                               5E4BEEAC9308844DDA45E8E06637246A
+                               0E6C8C7D94C5F710CB78CC6E0CA82870
+                               8CA77B6266B41E3ED6BAA2940F1977A5
+            stream[256..319] = A3EBC22126B6069C674DB604F8C22B54
+                               DA68FB4390617E86C4FF089344BD0DB3
+                               887B3438E8EF8207FD89B2A485C0B383
+                               22AEB69750AD054F843DCA7995BB58A9
+            stream[448..511] = BAC68211F125B57B8CE5E42E644997F5
+                               2FD4B8A7D5CBF89ED2F6B5F4D4C7FA5D
+                               0CC34212160C6BA536BB7604C184367F
+                               2E088528F3B3A0A1B20F9249711162B1
+                  xor-digest = F628E74D1EB94591694631F1B2F12234
+                               38B056789D5C2ABD8CF34D9FA7B8C304
+                               5A8C2298B7BEBB90C7CC86895693118B
+                               2A43B7E8AC7E534DA7965EA720F19180
+
+Set 3, vector# 72:
+                         key = 48494A4B4C4D4E4F5051525354555657
+                               58595A5B5C5D5E5F6061626364656667
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 40409D9AD4CFCEAEB8FF613D32B59180
+                               F5DFBBF44C1B7209AD1AD5AE94DBBF3A
+                               83EAB34D2617ABCC396880BD5F5D220F
+                               F434DD575E66CA74BA32862293113C5D
+            stream[192..255] = 42D9EDDAF89B93DAB4AA790BC9C45BAC
+                               5E94575E175C2EB1CC08BB39019E25C0
+                               9B0F4F435ACE371BD9235C61C56A362C
+                               B1A64EE58F4938D59073C5A8A1BA679A
+            stream[256..319] = E40477D1B6C901AFCC4A2C429845C7B9
+                               0DF890C317A5B9D6368672C58E0BD5B2
+                               7E42DA77BDC2BF47F9AD195F7C192B53
+                               24FEF88E6B3DD1669A068E3FCB58B203
+            stream[448..511] = 7616AA094DFFD4BCF94E03C9CCF95C31
+                               8F247AEBDE281334F8E6F46271070BC0
+                               1AC838D8FCFE18865DD30949C68052C8
+                               6E93815B4EA9480B2D0B6A5D9888E597
+                  xor-digest = 1FE60024F188CC243F7D8221D990ECE3
+                               29E89847C9BD60AF23061E9C27C4908F
+                               B00D8813E680F00665658CEB077BEFAB
+                               5DEB41D3547DD645DEDBB3BF5D7B651E
+
+Set 3, vector# 81:
+                         key = 5152535455565758595A5B5C5D5E5F60
+                               6162636465666768696A6B6C6D6E6F70
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1B8DA47812BF2353C17C89AAA8695E9F
+                               F553BBA44087D262FA0C710B69765F12
+                               FFE190625F58DA899B56FA7AB5E0E674
+                               4CA2B073517B9577712D7155E16A874C
+            stream[192..255] = CD2BB4A6C3D7211773421014611B677C
+                               C0A8107544ABF4F914F825891E52DDDD
+                               76EFDBEE614573FF9674EBC154A3283B
+                               439ED8197E1EE0705955A8B6C8AFF8BD
+            stream[256..319] = A626C40CD2C48AAB016C29020096DE28
+                               F03842E785BCE9D9E385D0B13B63F82D
+                               789588FFAB07B8CC0FFC62AA86D37CAE
+                               5CF8FD43B575F9F4D6E07465B700D47B
+            stream[448..511] = 16A3C84858207E141022D228079D6067
+                               2784EBB56E3B84F7DF07EFC69060E27C
+                               D1311E51F5893AE6BFF80D34464DC60F
+                               61985F8F88164CCA69EFAE568BEB546F
+                  xor-digest = A24EEDA74185884C5B287663C3F5F031
+                               2743CCAC657C702A29E0C20BDDE304AE
+                               A54A9292B447039D50479B6CE475115B
+                               8791854540E15D642859D10561AEF26A
+
+Set 3, vector# 90:
+                         key = 5A5B5C5D5E5F60616263646566676869
+                               6A6B6C6D6E6F70717273747576777879
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3F7261A3A4691A73441762D113EB7817
+                               4C515A96C5C93C514EE559E7F78A633A
+                               01F0891910D44A7EBB18768E3B912488
+                               6069CB5304E79ACA89F62EFEC4EAC11A
+            stream[192..255] = 5F11904F72123CE29D1D883AE5CD2A89
+                               2AB26C9167A24A57D6F64BDE3A8E1A93
+                               7C5347C585226DB44B6252AEBF3CCAAF
+                               2D5E60C56FBBA6068B35AA6A61C84A44
+            stream[256..319] = CD6C5B784854E0121933E77C700D9C1D
+                               7452999F859798499A339F78FCF84615
+                               A3190A2F558CC529E636922A1B75A3A1
+                               AF280FB3F486303093DC1564EA0B6D3F
+            stream[448..511] = 61B8163A84540727204F0B18D9CAED3F
+                               B5FA87089FF4E721D2EC34D21C59B93F
+                               95297725780DF04A5FE405FEBAE80AB9
+                               B8307B9A74774E76063F9218CE243002
+                  xor-digest = 944EF8435F32FF2A67CDA5FBDFE02C81
+                               0997D9C8192633A193D6122A051B801C
+                               15555BDF410917B9E5DB86F4DE8B9874
+                               3E9F92F903543AD14087F4E13A915DE0
+
+Set 3, vector# 99:
+                         key = 636465666768696A6B6C6D6E6F707172
+                               737475767778797A7B7C7D7E7F808182
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 71BA7454CF7F6CC93C89EB22B9D608EA
+                               0FACBB4358DD007421DAC1E65EE99161
+                               C542DF02611AF497B2D53748D0129C0F
+                               5B9704C8A6017507EEFB26B6287662CB
+            stream[192..255] = 92D5D35B2E02D204E68C1AD6C018DBA6
+                               7A1C90F563AEFC3D031FD3F7D4F5E2F4
+                               C47D326A9C49A0B2ADF03D9E7E429AA3
+                               ABF253E623BFB9EB040B5F5CF1FF68DF
+            stream[256..319] = D6C22BEA96DF94CE9D5D34E6231CE4F9
+                               A2D2F6097540F9A9160DE139E2E80D0E
+                               5AFE08131FE10F0DD7367E43D314D7F2
+                               2321B5F89DC64F286576BA599A58F48C
+            stream[448..511] = 43DC3ACAE02DBF68AB5B65A81630474C
+                               639FC4DD36FBED518B6471F7C3E70FDE
+                               23CF1E128B51538DE0D5A47F20A554F2
+                               09668FE28B0C4884888FAC438960CE7F
+                  xor-digest = 7B0EF650F3847E3EB15EA1CB64EE7189
+                               AA5B04F527661C00F4603E48CBE59F7F
+                               48498D80F6C5ED956ABBF97E6910EFB8
+                               341C7BC2E81E66A4B9474BE420DFA5A6
+
+Set 3, vector#108:
+                         key = 6C6D6E6F707172737475767778797A7B
+                               7C7D7E7F808182838485868788898A8B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3C4CBA573D803324D099BE1F436F944F
+                               EE506CE77EBC01FAF0060B76FA5D2005
+                               05CE94AA15F3C4B1E0194264CF13878E
+                               FD36288EA4C2ECBEEB76828EB460AED7
+            stream[192..255] = FFA464FA648309E295314DEF7169DC60
+                               F63C90AEE9F27B534E11D25AEC454823
+                               DF6BD39C1F9CB46276C630C129536506
+                               187251D638D3867E96A84BD570F78461
+            stream[256..319] = 6BE88BD0D2257CF7EBF7100B442F68C1
+                               ACB94B6F8991C1461D318BB80E59A6EB
+                               8009DFF46B8E339A0CD4FB285ED1E433
+                               5FDBD65537D9CF1FBB0F9F10E17952D0
+            stream[448..511] = 909997D084DE4F6C910D57DB89E1EB56
+                               AB3F9974E3DB5935D59917CACCAA31CC
+                               E009324E52334BDD6CA971AF49982122
+                               B195229DF0BFE2C508E981D303061B2A
+                  xor-digest = 8B2B49D564662BFB29A9F4E1A3DC7664
+                               774D41168EA27505A2A518DD94C2A507
+                               0D28E1E69DA2F084DAB024E8EE2D022D
+                               BC73071B8559BE2FCBC2AE3605696482
+
+Set 3, vector#117:
+                         key = 75767778797A7B7C7D7E7F8081828384
+                               85868788898A8B8C8D8E8F9091929394
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 6EE8B7E51036B951205064348C222881
+                               624E9FF59DFED40AC6CDEA0945A39E72
+                               AD05FA929F7AB69BE8234567734F8F96
+                               D74DE6038A463BD8FB86224F5CEA0D45
+            stream[192..255] = DD9CD1757A95E616E99590E76620E9DF
+                               0BF811F73B70C5CE982FC9CECEFFC6BA
+                               F7DCA30517A9BDF44515262ACF297AA2
+                               2CAC3F216C12A9D0D6912578DC672D18
+            stream[256..319] = 0B7DE245062DCC9B1D8A945CD9A04938
+                               EB9BB258B4B7BCC263487B3599B1C6BE
+                               7FDE752D65345F00DF90896DF53244A5
+                               AB111134B36A99E2D2200B4D2003A520
+            stream[448..511] = 2566E8427BBAC7F0A35C6E4BCDD326C9
+                               D7164A9E1F767038A09A75B5076E05AD
+                               C51F008E9E3184FA4DC6E4764B381944
+                               BCB96B57FCE2339A01501BDEED46F8E3
+                  xor-digest = CC16803D36710AFDB1DEBC653DA7DD12
+                               F45B02349B87C3006DDCAC1635956846
+                               E4D7D6064D19012724BBF836A7DB7A3E
+                               3C12E6288F546EF316406D9C5E844BAC
+
+Set 3, vector#126:
+                         key = 7E7F808182838485868788898A8B8C8D
+                               8E8F909192939495969798999A9B9C9D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4F4169DF51C9865A20D7E79DEFF7B121
+                               BD61F4C79AFEDD0598F55E9D9A3615AD
+                               19292095DDD83904B3683722A3337BF3
+                               4E98F63EB19927155E176F2E8D5560B3
+            stream[192..255] = CF82F8F2A46A898915B3E371BE941811
+                               682A8A0A20837AF471B5CAA4B4FB01E7
+                               F2B0CA9ED3BA70BE305587F1ED995946
+                               223032F94BB2ED7D418C95F202887E6B
+            stream[256..319] = 219C121E08F7458BD657AC4131221C78
+                               43DB5817B17344922C54A002F3F67574
+                               BEE5F7FFC7EFC5615444B51FDDEE8B71
+                               981FBFF658D2504BB53C13D0342258E4
+            stream[448..511] = 55C2A93F43F260EABBC1A173AAF80A95
+                               A7EA74CCEF6E29C52957AB2247126336
+                               CEA5BD0D08F873AAF733B3A11885F04C
+                               58542B4C8ED3E1BB7F7918C4E92926FB
+                  xor-digest = F69FE6EFBB4A6E65B517445069859EAC
+                               A9C19FCB9C1771E75266E5B4C39019DB
+                               E959AD97F2B8D7F1688FD0AC04AA7C2E
+                               602F28A63DEAA49A7BE1422B47CFBE00
+
+Set 3, vector#135:
+                         key = 8788898A8B8C8D8E8F90919293949596
+                               9798999A9B9C9D9E9FA0A1A2A3A4A5A6
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 3305344A71266B450B2CDEB049A048D2
+                               6171B39A88C25CFC0821E4F4EFE378B0
+                               702DA31652B5E1BAD9FF4C19C20BF329
+                               639D5942DD2209DB1D1474B6A7B41B76
+            stream[192..255] = BBD9714BF2C343B11DD7943DD8CDA8B4
+                               C6A913F1DBE21A0582B3FCFDE91B61A9
+                               8863AAC17D07D8F98AE8E71BA5636251
+                               49FAB3EA775D3C7735BFC732C3C42571
+            stream[256..319] = 473F161607321838FEB9359B0006068F
+                               9D88B1A073DA14E60AAF1501F3A27350
+                               53E3FCC794893257CC3C1D4E1E3CF609
+                               975E865CA46C892823C838822AF0CD2B
+            stream[448..511] = 89F37A53F18778084307D0BB71E5712D
+                               32F0F3B7C2201D01D892F6BF6068E4B5
+                               394995CE6BFACF08587ADA39CC647DAB
+                               9B12F5505055F372FDC4607F0355DBAF
+                  xor-digest = C9E7E4A4D6782C02AAC4F47AF1D142AF
+                               FAE569B755E880C6B8A5773EFC0E63D2
+                               3D7A113738CDB1A0544175861401149C
+                               753D723CC1EF515A9323DDE4B4A765C8
+
+Set 3, vector#144:
+                         key = 909192939495969798999A9B9C9D9E9F
+                               A0A1A2A3A4A5A6A7A8A9AAABACADAEAF
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = B7954C45CF301CCAED3F1E7E77DCE45F
+                               2D41B3B1C1F28F0308B8AB4293B64A60
+                               AA7936DDF062613DC1C454033D2A40A5
+                               E99BD975A26185A7F419E7B337028FAC
+            stream[192..255] = 27AF957AC6C514514C24664AA0C9C23D
+                               B1EE30950177389876FE4FF2E1739912
+                               A09E20A2098751049C8925334960A324
+                               5ABB50F3D333587B67F153DB145B5F6C
+            stream[256..319] = D94FAF9FCB753E992B898178373A36D6
+                               23C6BE2420AC2EA848130073F086164C
+                               9B4E69B024991FFA8FAE94E3C2FB16F9
+                               D747320A748DE9FAE4FE9E6A7E7D5659
+            stream[448..511] = F664AFD3EDC0FAE88016C8A028E98D34
+                               A27843372C6BF8F51C7B49B94A11274A
+                               6A161D776E6C1FF05358F28426C3579E
+                               053B4137F8C4CAE07B994B80DA06DA27
+                  xor-digest = 521594487B583F5F71DA10E2316187F2
+                               2A4885A69D522F82F7FD0D5F93F69B2A
+                               060EB60965AC010BC489B401F02C26E4
+                               FE3F82B83C964B4DB4E0E6BC2CE4B865
+
+Set 3, vector#153:
+                         key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8
+                               A9AAABACADAEAFB0B1B2B3B4B5B6B7B8
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = A5E320FF65811FF5E8934F3AC73B3733
+                               77D3AC52446F64646946BFB8F6DEFE3A
+                               04E859DCCD9F421D2DF541F588B9C204
+                               A9846C7AA1C017D637D7C5E244602105
+            stream[192..255] = BB16A9BDCA0D4BCA589A34F9278AE55D
+                               6A7711EC87563C9F394638041CBB0E40
+                               4CD2149218D501D3B62421CBF81C6576
+                               FA659C2878839FCD6C8DD1BA38F46E6B
+            stream[256..319] = 58B4004C53EE64CD45BC4A1F11F700AF
+                               0EA5ED86C4BBC145C8F588B7F708427C
+                               D2292D76329E4DB1F289DADA687B7784
+                               DABCCD29B8C464CE021856FD06554F76
+            stream[448..511] = 1113D37AB2964AAE6586AEE1B060F0C1
+                               02EB3AF048A59CB709792C9080183CFD
+                               2A1A47277F413F1219B5AAD7C8BC8079
+                               246BD1D6F98C11997E4ED0F68E165D9C
+                  xor-digest = 512F4852425DBF91234DA31986732CC3
+                               1F9649A1965E22E18CF38979EE6D92B0
+                               83333422A92F841C25F827782FD7BDB2
+                               8F4B40AD5EE53C37192651A86F03A17E
+
+Set 3, vector#162:
+                         key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1
+                               B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 96328CAA099502092359F397972568F8
+                               EE2FF1C4305EA06FFD8CC125CB10BE85
+                               65EA30B621437AD4CF9CE731185720F2
+                               0CFE17DD45E6361A8212EECB346D391F
+            stream[192..255] = 74F26B7A37D673DA0B78B38938C5C1EA
+                               2AC666612468F63B540EE7B17548F8BF
+                               60A9845BECCD7222620FDF7BE904FE24
+                               7D2B7EA749C9590133CD6A218F6EF624
+            stream[256..319] = 8F8AA7A4C64C3AEC5E85581C53E3FA64
+                               22CEB927E370C7B0F98F038E7ACF4D05
+                               B54430D91B0A2CDC001BFDDDCD0081AF
+                               35B67E5BEE6B8E113F36E3B23CE29F57
+            stream[448..511] = 53E20B4B90B2DDAB40DC30643AA5F539
+                               70ADB65DD0B64CECF3D3B4C0567DC818
+                               0362FE9CDF920526C59725AE861940A8
+                               A32C35382571F2FF20E7FBC504E1DF9D
+                  xor-digest = 8C7C45F50A151D551E9EC81EDFDD5B2F
+                               E676E14253FF38EBEA12395040643211
+                               3254B0B7298AF77F8F9F4203B971EBC9
+                               B9850152A96C97BD4FA7BE8592670903
+
+Set 3, vector#171:
+                         key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA
+                               BBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CA
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E8DBC8E5D18C5BB2B152A6AE9487AF35
+                               E2044F30EE8189659043923E579C70CD
+                               4A5590968600AAB0F021F7AF283D61B4
+                               13C739DCFC22632E1F6CD553D4F21976
+            stream[192..255] = 8675941731B385016430C9A157007EBB
+                               E9BD8BBBEC44081C1F5E73C7E783AE90
+                               1A7F56A20E5DECD1E94E1C92A07CD2B9
+                               91619BC3358AB812D58E0B98EA288D03
+            stream[256..319] = 8D09462E5B1154175513CE7FAE1AAE89
+                               EA2AFDFDF1B39D69FDF60B1954BF81E1
+                               62F29468E07C251E2D174E9CE924A5F4
+                               8A470D1808C68ECE534CC08204C5A2E6
+            stream[448..511] = 60C5FD4C1831F0EFD70EFF86A5D38D96
+                               2C402453561D0021A51F07D40A7D3B8A
+                               DF455CE484E89437DFADC52A52741B80
+                               ED0EFA9AE4FC39659F8300AE9292B9CE
+                  xor-digest = 12E57044A8E7F02EBF6912BB73836FFB
+                               C4A2F47AE1B824AC97C1237B1B14DEFF
+                               12B5B87DF14A8B5B6C85C0481BD69DDB
+                               FD76FA307F4C1F7D21E60C0BCFECD3E5
+
+Set 3, vector#180:
+                         key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3
+                               C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 540980C2A3794C04B93696B90E48999D
+                               ED8E1D3F4720918C80C95B9AC0E911F4
+                               6593C4A920AB291D98891374EF286286
+                               2386B5FE17654278EC413AAFF1C384DC
+            stream[192..255] = F3E036D7620669F851A1B58BCE57B079
+                               F5D75829EDA4E68C36F086CBF2E5DD78
+                               F7F30C1AD9E4CB3C01B7F2FBF53A8AFE
+                               957786B2D3E9CCFE7D6FB24397803BC0
+            stream[256..319] = 1AADB95F07E6268BD82ECF3453DB5014
+                               9745CCEEA9F1887B5F257594ABBFFF43
+                               C3187BD9A9FFBCCACEBD7A21FF90D18B
+                               57FCBAA64B8FECB56D5A7FE05BF03E3E
+            stream[448..511] = 4170D41CAC2A7AA5A3C9228BF386B9C5
+                               57795DB5D1AE547A31C553F55DE02E6E
+                               B69D76A984F4F1D84F29D5CB98190C01
+                               441DEEFABDBFE405F22FFDE734D9497A
+                  xor-digest = CE103B99AA95B51D2D6CC54A15833E34
+                               A11778F5E05BB7AB61505D473228069F
+                               CB40015BCFDD3E1D0D5E1F832791C8DD
+                               3184273D1B4C67D800EF5FF004660440
+
+Set 3, vector#189:
+                         key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC
+                               CDCECFD0D1D2D3D4D5D6D7D8D9DADBDC
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = CA30678AC97B4591E287FF8B5E28A838
+                               611D654A4EC592328039E3A1DFE90FAB
+                               BA5A37133E821E0960520EEC850B6962
+                               B0378E77770681ACC0929D16DD260925
+            stream[192..255] = 79FD1893EBF30CC2CA9C5AE92B0C063D
+                               894EAE4BD50BF462420081D1CAC57A5B
+                               AA92E73D3B3CEA147E1F7127AE1F6FA8
+                               E9B302A068F26157C904E0AA7B7A072F
+            stream[256..319] = 6880FCE56677345CF1CFB2D38F890C15
+                               FE33D377922AE43348F5590B84426EC9
+                               0DC2A3863136790EBB7BD9493D2F0808
+                               CA9287CF95AAF366A11D6E7A556FDB02
+            stream[448..511] = F385299A7038DA8A90058C510727F3E4
+                               524A2D95D217A1C199552753F253D45D
+                               81DA40431910DD54B619A15C5C302411
+                               613D28D53493AD836251F0047FB911DC
+                  xor-digest = F3D10E261AC596959B4AACBCF335D043
+                               FFF65E2651F046D300C19510E1677F1D
+                               45F287DFB8C17055A012C234B6EB04C5
+                               76ED2EDE12DFFE6EBA4A39A64DDC573A
+
+Set 3, vector#198:
+                         key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5
+                               D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = D5EC301FD496586D54D9B21FA23DECB2
+                               B25DCC0784BF77DE84898AF96023647B
+                               F1618234A239F63FBF3478FD6EB79299
+                               66BA9B670C64118444C95D31405873C9
+            stream[192..255] = D455D37F435FD0FDD6E1EDF8BAC28D2E
+                               DAF587F938C49A5F58C32CE8D5B8A4EB
+                               884B016E54277300D461FA21512E7695
+                               D2D7489A4560FC7A72A510219DF1C5C4
+            stream[256..319] = A7B93D8B7787B6C8F80EDCE72D4D644F
+                               0C6400C3AD0443FDD19C3F3675083F4C
+                               E5ED87032B1813DDFF758854C8D889A4
+                               6FDC61C210058DB72D838A0913D80611
+            stream[448..511] = 94232F4284F46DD2E7933F9635C26C48
+                               6CB935031095777F59BDAECC4FDB4109
+                               9037C38C91620586DE93B66EC7376502
+                               6853B7390CA516B694583447DD863310
+                  xor-digest = 8596C088FA66361FD90A2132CE33FD52
+                               34910610DB006D223B0574F21BF1CD4E
+                               C282C67B24AF6DB0DB70BAFF65D5D8D2
+                               1C3955D466EA2B49C5E8EB7E07475919
+
+Set 3, vector#207:
+                         key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE
+                               DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = DBA2DF9ACC53C3EDBB566C28F689D7AA
+                               EF631CB44EA91610A94685FBD862C9D9
+                               BFCF512BCECF36E035E2E577F6BF6EF9
+                               E4B0E7623E0DB23B10055677C7B9F857
+            stream[192..255] = 8C78C9714577E497E3CDFE3ADE19F03F
+                               D2DAA3211C1E9E5D9F21FD1ED696354A
+                               B7552BFC7FC675FAFE7A739F6E60A839
+                               547F8F15BA5EC6F75BB05606BBF209CC
+            stream[256..319] = B23F187B1BFB5A728BDBD78B75C3265B
+                               B04C6B350A4DA4EB021D6191263F052B
+                               CAE73E5776002FF05DEC3D341AA20D2C
+                               FA523E6B92329A979BE06CF4F848A1B5
+            stream[448..511] = 7E2ADEA91939388D36B3F97DC87C2A86
+                               BDE7BB4884C40D8A202964ECC7440987
+                               1C64B03EAD0F46A3A1CD2CB935DCCD67
+                               0B43292D5B852B7A1B3D1F853EF22EC7
+                  xor-digest = 1AC1E42C2DF9858537D0A1BE3B2AC094
+                               54136E53AE56B006395969C7F999B2E2
+                               DE1DAE62740FF339DFC8769F67AEF352
+                               C4726B4AD4BAAEE56AB8C55FACE34860
+
+Set 3, vector#216:
+                         key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7
+                               E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = BB00F8ECA9A10D2B137257E86B455DBD
+                               F9A6A861F19533E38C3C9F54195AB803
+                               171D35043FC9C4204AFC9A8E72EDA4CD
+                               60220B2EDDEBD5482D7833979C15B685
+            stream[192..255] = 6CCE94C2BEBFD223AFB7AF1110F0F6C4
+                               01AFC533BABD84F8C4A54E8A239A194B
+                               B56E0CAFDCC59B9B5103471DCEB9F706
+                               7801D79530B7CF40F2DEC73A169C7481
+            stream[256..319] = 5144745E042B76A6B62E78C92FFC1C0E
+                               E59979CE4B2E4B2CAFFDFCC5E75510A9
+                               201E8A97A6A1729E35CA81D8645FC118
+                               177DA5FACA0293B972AC0957C43BB1FD
+            stream[448..511] = DCF9B6116FA5EB9CFDBFC8C97EFD89B5
+                               268C0D529141FC3C8262B8BE38E94973
+                               A21919D498FCC3896B0FB4CEB24D9E2A
+                               F728003C36838638888FFF1D0D526B37
+                  xor-digest = 99EF8A7D0B8D08E976EFBAE56F7CAA91
+                               B1FFC7428EA56B7A697AA3B621AA8DBD
+                               52681C7A9A415049AFB6B7D8AABAD024
+                               0F9C3112092816F4C69D36B1300ED3E6
+
+Set 3, vector#225:
+                         key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0
+                               F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF00
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = E3DAA6E498609DDC5A31BC0B6ACC880B
+                               695097D2CE2D1FD162C7802DC0D00BE3
+                               C0126CF947CEDBA7833421D70A914BD6
+                               C33B0A77BE8BA10879D664F054C29302
+            stream[192..255] = 0015EFCCDC554D042531FD570C6B26D9
+                               059F4F4DA675BCD12C038E4A8D16737B
+                               AAB0D7992340F4EE4324959E96930934
+                               21234D41F56A995C928F82944B46BB19
+            stream[256..319] = 8CE7098F4C64DF2E8A170DA3D02CD99E
+                               0169B99A261D1072FA116ED39244EDBE
+                               73EB9F1CDCF8CCDAA9E94C0DA9C6EDC5
+                               426751AB8300836435BC6F727F793281
+            stream[448..511] = ADF85AF30894BD0207DB4BF72D9DBAC9
+                               144EF6B24E515D96475897EADE40A92C
+                               79B818499B8CC328859561D79D727423
+                               BA81055F3387608E56173AA27D286924
+                  xor-digest = F47ABED85910334919B5868D4531FC15
+                               24D61CB16C23920750C73E2B08A4B5C8
+                               C621482F6D9F01EB59763C5F89AC1514
+                               F6CA4C40216D6385F304E9514B014C02
+
+Set 3, vector#234:
+                         key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9
+                               FAFBFCFDFEFF00010203040506070809
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4728A29A2F2BD276FDE176CF4A38BE65
+                               B84BDD41F065DAFEA8302334CEF92A5A
+                               306EF904DADFE92E3E975EF9EEC9B3C8
+                               4AFC167545A0CFCCB6B1CA688967D8EE
+            stream[192..255] = 734153A78089B6E6EC0F520D39BC3FAA
+                               E1DBAD30CBDA32395E51E500CE4E118E
+                               23BC8CFDB08D443F1932EDEC52CDF3E2
+                               1D021DB791A56A7C16FDA02912FE744C
+            stream[256..319] = C511914A4BD9B29488B7FB1E62DBF905
+                               01C0D85C5A238448065C188F0A4134CF
+                               6A1FE1DAE57DB8BDF89FBF7FA66F3E32
+                               14CC9658DB292E4562A1761B9EA77570
+            stream[448..511] = 946944DF8E41BD585723CA1C03909E01
+                               783617D9D1129220ADAE7E5487AF4B54
+                               FF6593B37BB77AB0025C28727AE5933E
+                               E3873824E46F2209D26936FC5566B21C
+                  xor-digest = 34E04FBDE6E3DF6EE14BD179226D51B0
+                               1513510665589CB794C0C08391FA5929
+                               37B390E86BB4A72D427F58A1EFE10F6F
+                               D8A14A6F38ADE34331C8AC6AECA5DAB3
+
+Set 3, vector#243:
+                         key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102
+                               030405060708090A0B0C0D0E0F101112
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 2AC7F22D838F68107877E90869F98797
+                               493171C8A5EC2E51D536A1578659DC16
+                               BB2F644C290B0F006BFE3FA0FE0CE917
+                               D32E94643848867B230270F54D0037B5
+            stream[192..255] = D21F7FE6E368989CC75E8D9080579385
+                               E31680302BA8B9B2F56984FD49B01F4A
+                               DD36AE4A28EBE23B5567BF5A539E2621
+                               1AA8588507916CCB572611C352E73E42
+            stream[256..319] = 25823586A7212D44811C75023193864D
+                               85DFA17EB7D5A34BD1CDD3260B5D53A5
+                               56EE2E2A06F84E95CC7323379FB924E9
+                               9E1A3F724F8C480A1F40B2C4A6FCD433
+            stream[448..511] = C1DA25F3B4FBF8B2917103E6274FAE81
+                               A5BF4086A161A7786BBD5A33662E48AD
+                               6EB9A944CCA57C51AE266BAF756EA506
+                               AE077AF0AD8B577A5A02F5563FEBA2DF
+                  xor-digest = 6176BC64072356BDF719676CD2ACF288
+                               CE2DC1272ED9C4685A5CBB7327669724
+                               DC8BB64BEBA04564A7879F7B9AD5A936
+                               C4BC1AA4007A0F85A5B5B945B418BC61
+
+Set 3, vector#252:
+                         key = FCFDFEFF000102030405060708090A0B
+                               0C0D0E0F101112131415161718191A1B
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 0854D9B674256934E204484C6D59668E
+                               1C94891FEAF6E08A92038E41EBA38292
+                               D19FDBF852400123237BD7DA620767D3
+                               43C2FAAEB08A394EFD1E7C1A3776B1A7
+            stream[192..255] = 4BBDDBE675E0F9D7DE0BC1B0E0C64FE4
+                               52F95ADE61D5CF2EB805894B3CC3285E
+                               6C6AAB72DAFF826D945B05FC4D4A6BF9
+                               37B352262AC12B7E6F92D5FBC4ABDA05
+            stream[256..319] = 7BD11CF4273EA16E01154EF9615B88D9
+                               C52535D2F0C7FD394D94AA7EE542B448
+                               9A046F2625011EE75F874641D1C5A709
+                               B7FD1DDDCCB2A6F1A47B65361A9B0D6F
+            stream[448..511] = 0AB902B571D11B5F2F24CDC7616143F8
+                               45E7DF2050B263D7A841DA170E17C00B
+                               4A20221D7ACCDCB0E131108D94D903FD
+                               7E2F7988445A7DB54F653186D69F3CCC
+                  xor-digest = 1266CF54E8BFFC95F1CD3C532BD8EAE3
+                               BF000577A811DA58A41AAD9164CCDEFC
+                               401C1B6BD2BDD9E992707718A9802B55
+                               33D7A8F490DF116FBCD8C85E9B580487
+
+Test vectors -- set 4
+=====================
+
+Set 4, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                               3083D6297CCF2275C81B6EC11467BA0D
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 1C43EFA7A2CA90F5E8F9A4F09D4C9077
+                               D5ABD79341FD75BB2DF9F13CA0B1CD6E
+                               065FA86938D971D8FAC8A3C34D08CA2D
+                               1BA08BE56D633951BD0338A227321CAF
+        stream[65472..65535] = 428908B703282E38E1BFDE62C6B0D8A1
+                               BD2AB1F5117C85703E9B656FDEAD2660
+                               4B7B8EAAE16423A3BFE542AB13748DC8
+                               35D81F981CD344015E0DF47BD180541A
+        stream[65536..65599] = 9D6D72F46C846D9BBF3AEEB463B9EF42
+                               F84915D664A20FB78AD94B61FEB7D63E
+                               5411A81D1E8F32BE3044E109C68B9EB5
+                               EC0BF180EF18BF3191D933F86045036B
+      stream[131008..131071] = E462CD92492726928381769FF205DC17
+                               AE7D31E1B82810F3CCB541B58C5F58D1
+                               38DB708C5F5BF07A0432868A1AA40A07
+                               601FCD1A07DE3071E8CE082833F0B02D
+                  xor-digest = CDCA2F92BF75499E49B586BDA7D9306C
+                               12F111D1A9F183A83B5A07549D5F976E
+                               815F96BD716CCAC7178282CA8BEFF4F5
+                               85DAFA9BDDDF8E6420DFDBA2573F0494
+
+Set 4, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                               3588DB2E81D4277ACD2073C6196CBF12
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 4F7D4E56036A57A303A9C7D978290216
+                               297AC26C187E4F07678EC0069C34F93E
+                               072D734DBA239D81E566D1E6DCD09B5C
+                               A132714291631C227E391EC0385A3A64
+        stream[65472..65535] = C508DDD76C070F712FABA944BCB0F5CE
+                               EB645825C520197867623ED5263E22B5
+                               6270F0A878AC7FE03145DD2BF528E1AD
+                               784086FEFAA0D82F0F3571CEEDD3341B
+        stream[65536..65599] = B10CF49FE9266BBCA007C8DB526E760E
+                               79AA4D6A3B29FE82B8698C732FBB81AD
+                               1A27B2AEB06D05F3CF17E875BC0BBAC5
+                               67762275EE650D03F62B29529F3C3E23
+      stream[131008..131071] = 42B4F20EBAFB2C792006BD163064EC7C
+                               F363DD996CDF839CCE61E739C3817B4E
+                               36D311A4C94C7918E82F5158D3A75844
+                               A5603742E33D7FC3AF018660E6B1185C
+                  xor-digest = FB3EDA7C75E0AACEDD95B625F7EEDA62
+                               3DDC94983A9B084645253C0BC72FBF9A
+                               67072228194F96C1E81004CB438D6381
+                               A5C7E9E7D134FB8B67DEF27462AD3335
+
+Set 4, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                               3A8DE03386D92C7FD22578CB1E71C417
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 23DE914D641DC0DCB4F818C687803858
+                               A6673E284F8323787756DAC9352BE031
+                               28BC6149A59785F6AADF92FC68761E8A
+                               862AEDF29E851BF5422A83EE5EABFEE3
+        stream[65472..65535] = D12E0C470A955DDAA7E851F43DA35B08
+                               15D442DBBEDEECE3ADE18FABF08B4443
+                               77ACFE9F138F8725CEA27B0F0ECCB4E2
+                               E5D6E476F88CAB4743E8E43CE2D48F4B
+        stream[65536..65599] = 26635796620003DE67406BF741B93D68
+                               318F9A23FE823B2374E8BD8008EDD7BE
+                               2F750707A3835BBA7DAC45E06537DF8E
+                               53DFCDB928EA34CC08D2841FE3E492C3
+      stream[131008..131071] = D3DFCE281FDC69F7800E765CB0B33D78
+                               8BBDC17DFD11F929295C26AB7ECF21B6
+                               7D4B4EFCC18ECDB8134175A7F198EB12
+                               F7913DAF22D73A4139D5B807C18310A9
+                  xor-digest = BB2C8E7BB894DEFD1D5A7D37C01E8EE5
+                               FD4E052CDF1DDF5FDA90C9818DE71B3E
+                               34392EC3858ADF718F463808ABF841B6
+                               90F49D35A51BE5067B162E72D0101F97
+
+Set 4, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                               3F92E5388BDE3184D72A7DD02376C91C
+                          IV = 00000000000000000000000000000000
+               stream[0..63] = 818C35D2FD72D12115F91BFD32F843E7
+                               ED4D7110D1ADF517226BE797E037AF93
+                               C190025A5E82FA0341667D68FC09E238
+                               49D5A7A9526CA142D60F71C3AEE3A106
+        stream[65472..65535] = F011E9CEE99D94BDD4484408A0FF91DE
+                               EFDC8D8C04ED2B86C51F21058E912C11
+                               F19890E174018308962F5827D2FC1E2B
+                               82BA65688C111AAB5C749D8ABAEC022C
+        stream[65536..65599] = EC2EF21014AACB6215083F784E3ED65D
+                               774124FE60188930E1A90405EAFC8F1C
+                               E75D54AA7D81400E026D799CE06EF532
+                               8002BCF5A10D43E6FB6F80A9D72634E1
+      stream[131008..131071] = 80BC6F7F6B0A7A357F770E7690D94A9D
+                               B8CBA32EA36E124FDCC66ECE8786F95C
+                               22263F09645864087FF4AF97944A226A
+                               CB63DAD316F8CFEF96504AD306C512BE
+                  xor-digest = CB8D4C35D79CCF1D741B9DA09EDA305F
+                               5FA43F9AE9D0E1F576D5C59AFB8471F9
+                               7822C6ACAA197FF01347E397C0382195
+                               865AFAF5F1690B373AA2603C39A13CC0
+
+Test vectors -- set 5
+=====================
+
+Set 5, vector#  0:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 80000000000000000000000000000000
+               stream[0..63] = 04740F92C2470701F289669A25BF9092
+                               EB4212FEACF66DAB6B1D520977945F8C
+                               6D350BF26A1CA35EB37FA53B0BA2CBF6
+                               6AC07A8C75D494B4B8281CFBAD4937BF
+            stream[192..255] = 5E47F5F506AA34E7D296C6911FCD3D43
+                               31A032269214ECEFDDB492C47A51C4B4
+                               DE9EF0A63A6EB32AF1DF1C5576A93F19
+                               02B7BB89F10D8C7CDFF9C097D3D49148
+            stream[256..319] = 015494CB3CC9BDE8A2981B25C06DD18B
+                               52FA7B94CBE24C152FC60762290329C9
+                               E58C4E5148585F417733737059E310D9
+                               309D0CEF48D2F1589994657A081BA6D7
+            stream[448..511] = 3B67C1B37D96E1076595660D61340EC8
+                               DDE8F492134270951D9D4B260C8E2254
+                               A7FE8C10DE837A617A8E261FBBF42259
+                               C636B3DEEA0F373FE7C2CA2B01EE3FC3
+                  xor-digest = A8CC89F06815EFF6A91CA276BEBA7F41
+                               75F842F85BEAE99F4335A3B85FB28394
+                               8B7EE3C659274C6B784035B94886BF9A
+                               5C1483941B20170EE3A374E39006C09B
+
+Set 5, vector#  9:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00400000000000000000000000000000
+               stream[0..63] = C25BA6DE4C87FE5360BCDEF864F3F778
+                               598A6A584325D5E6C44EEA4464D7580C
+                               9B8D42B5B3634F739D6A53D15FA41070
+                               D1DD4621BF87F53F42107618D9742FD4
+            stream[192..255] = 4A3808B0619C9D94E19F3AEA0BEF3839
+                               21D7E2BED05F1128A82D9DC010654ECF
+                               65199A645606CC44FDAE763694E6757F
+                               8FF864CBE4204D45102E465F16CAB8EC
+            stream[256..319] = 3097394E0CD0A9DAA28EA873566E42A8
+                               710C28366C2B41B6BF6687D881094676
+                               9970A5BA54D28D7BF772C4FED13A9F5C
+                               6E7AD3F6948667D6C2DF981955F73293
+            stream[448..511] = E685BC2ACD3A67791416E78699C83D31
+                               852EBCB1C1AF71B926D9161CB6D894BC
+                               8C5E85C7E30A0896369BAE50C1112D4C
+                               CC583E44A8275F44B7ED140E9721C7F8
+                  xor-digest = D9B51AAF4A9B75508FCD02443EFE2267
+                               1148C73264776B5513860BCE8547370B
+                               2BA66E82CCDB15F3DEB0F0728411B765
+                               1A098C23202745C19B045C58AB196309
+
+Set 5, vector# 18:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00002000000000000000000000000000
+               stream[0..63] = EE43BB5B79EAFB54B823DE95B71F3BD2
+                               F2A7CBB6D28E9BED590C20A2C52F9B2C
+                               74EEB9A1A48474D5DA4964EEE0BB98E4
+                               88030E213A4482BD1A8CAD4CF8A962CB
+            stream[192..255] = 150C4D68BF29DD27A2E6FFDFBD6984F4
+                               3AB56AACC08AC0C0149008F0882292EC
+                               A5359CCF4C257ADD4FC535E41D6F67CA
+                               E5210068F77A5D5F32A23B17F79EB7A5
+            stream[256..319] = FEA319287C29AB84585D4BF38DCFA71F
+                               A36253AD7F4BF58398731713614D0047
+                               F85A465C6915E05232A5FE5AE7A559EC
+                               42733403ECF6B11E4D5E8F4A8288A3E3
+            stream[448..511] = 79CE66DD3F77D40889906EAB1F671B2F
+                               98D9FBF8693C1EAFC89D19209408F3B2
+                               7CD83CB3B9F33151DD4A8D79911255FD
+                               3CCBA14918744B0ACB93A5F96AC9AB38
+                  xor-digest = E1E3F49B342F873263F585EC34969176
+                               2CC46C17FDEE0B32224BB77A8EC82A87
+                               816DC612439E998476F50E876481EE6C
+                               B32ADBCF6A5D50FA16355AF63AA30D66
+
+Set 5, vector# 27:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000010000000000000000000000000
+               stream[0..63] = FB8F4925A4F922119A6F29F8DDC2338C
+                               0AEF333B55919AF0D0D9B1DB61BA2E5E
+                               4CFB394E15F6A78E01B5C4AB043225FD
+                               9C8F50AB1BFDB16F944C2660995AA4DE
+            stream[192..255] = 87767D451D81D5B40503913508C2448B
+                               7CC093982642089843D7D9C3DA05598F
+                               7AEFC5B70ECCE327B20658D6301F4D6B
+                               E58FA5CE0525C9CE8E93FC0B387AE5C6
+            stream[256..319] = D146E4312CC11F11916ED9FF8EA8ABCD
+                               E0736DDD0A8AF3E067CDED397E429D30
+                               8F2DBF848C5C1653EA969B608CE01275
+                               53573C88DDD32937EF6F8B0864C581B4
+            stream[448..511] = CE919096A83BF3702D8899787DA7BC23
+                               43F1F10833F16E3EB467440B4921BA1D
+                               96845B6B4141E1CA85364E2D508456A0
+                               E399DD048E72685389FD7EF3F78B655F
+                  xor-digest = 00333EC3A59AD0B8FCA054A08340BF91
+                               906512917E72BED76BEFFE29FC011632
+                               082CDCB1A656FB817F968E26063279CC
+                               ABA796307912984BFC267325DB84F621
+
+Set 5, vector# 36:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000080000000000000000000000
+               stream[0..63] = 202723F8212AB20D9369C2E1EEF8553D
+                               C468854873D04FDD32641E324DCB4EE0
+                               883AC1D40D7C9C7783DF4132093724DA
+                               113B1CB12144E00509FD5D36957A4E1A
+            stream[192..255] = E6717FE0A77F9043607A1A7665716225
+                               C8D417FFE2CD7572083C7C552B79DB6F
+                               ABEBBC2D4D36AB319407982187C248F4
+                               83596AC071C0B0CED08686603B024E7B
+            stream[256..319] = 8C59D97F7A093EA2D0AB890923AE4DBD
+                               D40C33508838A3966FBA360E776670C4
+                               DEED8BC8CA57592463781550BCFD1E28
+                               818E7C33A3AEC43775ED0A984044E9D8
+            stream[448..511] = 0A3DC66754E02423C6EC1C1DD26CE11E
+                               FD70C386729C8290DF358C69087CA7DF
+                               D11F5E0D37A313F74B09F29C552CAC0A
+                               5621556828B0145A6A1D43F563AFF672
+                  xor-digest = 6673BA5866E8E96FB48FAC88D307079E
+                               77AC03692B23070EB5BB9D04FA94B9C9
+                               6C2F958E834DEB51C6ADCE432BFB9632
+                               9B3151E0A89EB72019A4522233B8FFE2
+
+Set 5, vector# 45:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000400000000000000000000
+               stream[0..63] = 95AE241C4E9B6690C319D1FD828BE454
+                               52F18F061C1B1E13AA409829E194D70C
+                               AD5BBACA2738B508A5398DF6C2552497
+                               6D143DF0405F68037C285A0E19FEC9CC
+            stream[192..255] = C0E2D5C6B614E4A498F46D5399DCE7EB
+                               7DFAFAC62794F5C39864C521B8DB574C
+                               149E35D1F0EA36EA7F24EF8FD855FDCB
+                               9CCC79F1ABB13EC33E00A9E137809C05
+            stream[256..319] = 285907400C1A86AA9942ABD7BEA8EEC8
+                               BB6AF2F9667D424C1DD56349C99FC65E
+                               8A00893AE529D7BA492089EB6B525964
+                               E9CAF15221A342C4F88697D818AC0F1A
+            stream[448..511] = 13D511737F3A092643E94E74F6C76241
+                               0007158FEF40C63B33E10360FFB3B152
+                               8BD8B33093D722BDCAC1FA99D16D1C27
+                               6E59E428601F256542BD3E7A4A135152
+                  xor-digest = 1D1352487AB5081A28DF23B1B19D5ED1
+                               192F08964E4C0F048AFA9CAA8BF17185
+                               D7B97AD6003E2FD2DCCAD492FF3FBE5A
+                               5CD7AAC627DFE7CC6D0972D423B67128
+
+Set 5, vector# 54:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000002000000000000000000
+               stream[0..63] = ECA0F29C3F5C4D62ACBD601C3042673F
+                               6F8B17C946FE8FEEEB0089059765F067
+                               5AF3E5DADF6DECDA20F72AF486E7E967
+                               40B2DBF22B57FCCDFE571B2D8989C95B
+            stream[192..255] = D2BDF6ED912478A3C53713389C9DFA5A
+                               9272D030543295E8CF6F0929F1A56041
+                               EA22BD04E0DD810F43D9D28D94254F04
+                               F73DFF3B766DB55100EFC9697FA844C7
+            stream[256..319] = C7CE1CD4D8C42FA36724A49107A78630
+                               A60E15673A42C57B609740EC8DE78EE0
+                               B48F2644DC0DD1E80FB8326DDBCC7191
+                               5E6C8DEEFCCB1FBE1456532840A89DB6
+            stream[448..511] = 337650A0B03D30C9697CE85449B0F995
+                               668FB2B73E37E1A550E07632F9F5AA3B
+                               04D61AC41F8A830299FB8F70FAA0419A
+                               42C4589D71C965DDB3A9D000667616AA
+                  xor-digest = 7A26C50BA37BD9F38281FD2DA3CC14F2
+                               E1FFEEC9D7776E87D99053B531EEF792
+                               0C0BF834EA9A0065AF38422A40A31BEF
+                               AFAA17AD565F685BD6E505C7E02FB895
+
+Set 5, vector# 63:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000010000000000000000
+               stream[0..63] = 567919917583CE03DBDA69907CBAE562
+                               107FBBABB4DFC81A3A15438C94AC0C28
+                               8CC35A91DED9A79ADF4EF2670A55699C
+                               000994EF33674B578F5D77928A43416F
+            stream[192..255] = 13D0EC5B7302C0D8AB329E7AADFC3FDE
+                               1D24A80B751948C4BCEF516D94DF7AB2
+                               2B1D9E076BBFE367CBED341B2A5A3BA2
+                               D48735F83855460F9D9953279BFC2AA8
+            stream[256..319] = 5EFFE922E2FE25410E8050A973C3FAE2
+                               EE372E9686B6E7B35294B52A579CDB43
+                               9D5CA7F1EABFEB4303DFD7DFBCC812DB
+                               9D70CD0698D1ED051E1E32C855EB39EE
+            stream[448..511] = 91A01C0EF63716515DB8B71273CA4399
+                               1654AAEF2AFD4DEF25E21A08D5385766
+                               D8C29514065FFF00B07DCB32D1A20830
+                               3C3402963EF252A4CAF5CA31A50BE591
+                  xor-digest = 9232F83FB054098FBED8474939476CEA
+                               5E9FC269E7B248E56B14F56CB396BE74
+                               C2B2203D1802D9515EEE232FD612FE21
+                               11C291A46A89D54B2E5437E643239636
+
+Set 5, vector# 72:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000080000000000000
+               stream[0..63] = 507958BFA08EB41F4D18F519E36FC476
+                               5BB8DC6CFCA36290CE9AB8B165D7AF72
+                               CBF49DCF8BA2D145D7935EDD2CD2242A
+                               7B7FCCB85B4C8625532D84B4BC602515
+            stream[192..255] = B2B06A7C3977D4A1A39892E832A32A55
+                               3EE6E52DB24DC453835893A55D0FF3A2
+                               949B8B96688237E13DBBB2D0C9038AFE
+                               8B9D18CCAF62019ACB908499D292F280
+            stream[256..319] = 1D28AADF7B262A1EEEC11D39F4325CAA
+                               6181F9FA1A6C65F3BEF4F1614B0DF599
+                               EC92E5B6B42A931352965CFFC025F68F
+                               DB2D6D0181F259F12989E5FB23ADAE8E
+            stream[448..511] = F60E3DAD5004E31F6DC89292ECF517F1
+                               CD18AF7E79E775334F4644A09346AAF0
+                               F2B4F5C1DD03555A6D27C43AE53EA7BC
+                               7167F793190071C7AB7B5330A6C6CAD0
+                  xor-digest = 5A65D44021E67626E62FE87B8547210E
+                               F736490C0D51485A8EF0E1CCBB512DC6
+                               0FC18114A29AF923EE3E85655771D6C0
+                               7CFE342A52190C540BE3409853F12065
+
+Set 5, vector# 81:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000400000000000
+               stream[0..63] = 2416B634134170CB4F67F431BC94612B
+                               5F2F72545DAED2356081C91A26554614
+                               5FF2526D8D8FC7D02D8BCDD9AE03187A
+                               9E404C360E115CE949667987AC73624F
+            stream[192..255] = 4D456233EC7E761891A56BF9F9659533
+                               22375C169D7F16DD81D8D69B12092F47
+                               09703B85AA3184827935B60C1E5987A3
+                               C4C2EDFEAD4F777B53989C469B575EB4
+            stream[256..319] = 5F9CDDCBE09CD759B346AAADA2436887
+                               0D47BD8859CB9225B61AD9F99197FB14
+                               B5D625F5DBE0955DCBAA5B874A7C89C0
+                               07BF926AEE571CCD7E20635ED4FF312C
+            stream[448..511] = 642391D8851A9BDBDCA37B9587D5D0A4
+                               877EDEC31D6EB78AA3F1E068B0ECE877
+                               D83EA29906D0C0816EDF7EC5BB417A3E
+                               F3DDAA2145CB37CEEAF8C07DDEE0AAD9
+                  xor-digest = DF93E4E01EA55D18AB8AB1A927A5B5AE
+                               9ACB871B7493DC283581262771852013
+                               EE54288580A03B3991126BE8BC20C5D2
+                               230F00D8216CFB632271750F4FD2595A
+
+Set 5, vector# 90:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000002000000000
+               stream[0..63] = 4981C83E26859DEDB32D84C7BE32830E
+                               784376A12FA6D0077D4CB47ECBA08A92
+                               C841D45D6CDAA3F1FB48C6FE747B0F67
+                               1B32C2B35BE69497737FE4B98770DEE9
+            stream[192..255] = 1FA51FFD0360615EFEB03042AE8E4210
+                               D3D38B4EF07536BAFE43C0585818F012
+                               8F8B3F8CA8DADBDF049688253066C74B
+                               01849C5BD85DCE27C0138D24E8B8B198
+            stream[256..319] = 2D8C58008EE94CFEA1EC545C26466D39
+                               D7BFD5B226E32F1270B5BD3677818B7E
+                               CFD98BDEA26488248B10418C1F854159
+                               8F42C6CC237885A1DEAC5C33F22C27CD
+            stream[448..511] = 94502058B5828AE4F4CDC0516E5B5143
+                               1F07EE1ECAD7CA266C931327BE6BF1B7
+                               A34810220CE00497D7BB9600FC524999
+                               CDEB6DDE8919B03064EB56B3766DAFCB
+                  xor-digest = 1DEDBE0B7B6099DCF285B3C30E91AA0F
+                               7859496E034A1EA1AAE3D3D13C2061C6
+                               0878E595B63D849B7DB77BE7E0C08157
+                               94232B645BE946E5D8278B14427172AD
+
+Set 5, vector# 99:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000010000000
+               stream[0..63] = B84C72BF69B601FB1804CE333C5A2C19
+                               25BC8A5877DF9E574295380611D03FD2
+                               46D2EBB58CC6E918F4DB1B1A0E39642B
+                               D6B39DC76764E18108497E4CC4394057
+            stream[192..255] = AA84DF8195B3F7564D0715517476085D
+                               1B40511A72340DFEAE5134C7BB8F39CE
+                               03E6EE15217986C7E4788453EF054027
+                               8CBF6336073092EF661C13C7EA8B4850
+            stream[256..319] = A7F0C413EE143F55C6356519AE620A9F
+                               4CEF8432C51E2677EB5D700CE333F314
+                               ACA374D86A8FD4A67BDC31C1B0DA2AB1
+                               B20E6DB91E7F85DC13E348314A4FC782
+            stream[448..511] = 3445E08F13D09A1AC09EEB65451F4504
+                               0AFFDE94F6C2667BC4D8FCBECD6C6565
+                               F09FD05EC660DD38307F856AACC95549
+                               AEBCF31B3FBE84FFB3261D7FEF7A3379
+                  xor-digest = 360199B22EB28401FB4F621E37800801
+                               FE69C809D83BE29A50FD1A476B6AAF02
+                               54B1F4B048CB6423182C390B8EDFF1FD
+                               9CE49C26727F0D68EB837C19F58F3F42
+
+Set 5, vector#108:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000080000
+               stream[0..63] = BC618F4A557E5B7CB75B3572FFC31CD8
+                               4DB96FD22E281C198DD33B5E9E419099
+                               BE30E84ED61C0EDEC04B1E16E06B40E2
+                               372E0EA1A48DC55BFBFBE3355B566AB9
+            stream[192..255] = 33372015C7E5749D98A92CC55CC22206
+                               90BEC9878D3CA0AC50765D0B4457CE50
+                               9BCE196BF0388599E692B99EA8169474
+                               546F10891A3FCE22DFF0AF9733C2A2EE
+            stream[256..319] = 382684F74B0F02F7B987D37F6BAD97F4
+                               20B4811FFC744CBB9F00C2855A609FC7
+                               7CD24D0137304B95217E25FF45AFA4CF
+                               28E4335D29DA392D26DBD341A44C082A
+            stream[448..511] = B0B2B619708435C5DB45FFADD2FE4449
+                               E603FA9785E1F521E364DEA0B127F72F
+                               6C8A956CAF2AC9ABCE9772ECC58D3E36
+                               2E758BDE3678D4F4C9804CAF11129BE4
+                  xor-digest = 80FC64E2441F6CA9C0F4C207007FD0E2
+                               5F1C0514D203A1B01A6EEFD1055CA355
+                               0174FAAD47ED0956A736A9404164ED85
+                               CBEB31F80561AAFC4ED8EDC9829D83A9
+
+Set 5, vector#117:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000400
+               stream[0..63] = 69FEF0D5DD7CFA6590821B6C12E239E3
+                               5DCDE7B218A66CF3C75ED278092A6228
+                               143EC00BC16DC2FDB8CD9DDBD802AB56
+                               A4011F6A8CF432F2D34657AB84DEFA4C
+            stream[192..255] = 312EBF427B3D22A22EE1F85D89E12AE7
+                               07160C9BBF4073E538171365290B499B
+                               8904B01801CC897FF09A520449A44D0D
+                               34622DB8477EF1E73DCF15417478FA03
+            stream[256..319] = 83CF222FDBEB77FFC6E282C1212D8D1E
+                               014865E9C1251FC07E901A41A50A3AF9
+                               F8E130394F621B739578C7E238866431
+                               10827799C75F08C47664B09B477F31A8
+            stream[448..511] = 4130A8F8015F082EE8712B6D61178CAE
+                               B1D3CF90AC2DB9F2D402F65E8395DE95
+                               DA0605E8540E553CFFBD029AD5BA8FB7
+                               5950C2FB29097E13ED4A1B1818E0D07D
+                  xor-digest = 21FA07F8AA2FBC12F5B2B14E034C2AB4
+                               54D7D8DA66EB0308D9AB024DBFA414B3
+                               38F36D188D33C71E888FFE1A6AC620CD
+                               55B33C1A146AB8FD275584589BD65606
+
+Set 5, vector#126:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000002
+               stream[0..63] = 0CF41A77C30118D0931FF3142132A627
+                               7A778D3BCF7466EFE56238B166A57043
+                               2DB3B222523330233F81836282A27B40
+                               F6823BD076D84DC3B831DD78828F0FD5
+            stream[192..255] = 38A0C28325566FBAEF5AB3D50D54F407
+                               91182DEF4FC945992AA0D62134451914
+                               F07F16E86E20DB119692966E6CD6165B
+                               79BE7CE6C45D1248F2E0432393BFA726
+            stream[256..319] = DE91DACF57B176EF6E59E485DF02A20E
+                               3A4EE5FF44B1AA3D7F36265221CC71EB
+                               FB9565AA4F269B7DBF3CB9631CCBAAA4
+                               BBBB6BFABB97E52954958D4E7A283F20
+            stream[448..511] = 8FFDC8CCBF864721D6C98E1896FA052D
+                               15141D9C3DFEB48AE91B2436C5C3D088
+                               931470CE951B66C38998F15CF23BED01
+                               F6D95D84150D482C0C289A8E5B2C7C10
+                  xor-digest = 03DA7ADC3E5931928D3FD89E1E0876AF
+                               9D4CE659175E671D6D80EEA78F241AB2
+                               86CE3C26DAE267D91DB556AE0CAA60E0
+                               2B481282E6470A7A161AC8E84C2311EB
+
+Test vectors -- set 6
+=====================
+
+Set 6, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                               3083D6297CCF2275C81B6EC11467BA0D
+                          IV = 0D74DB42A91077DE45AC137AE148AF16
+               stream[0..63] = 544B400E28A1A4D9E30A3E5BCB5C9FA5
+                               CA066389C693177C4FC721937D0DA5FC
+                               AABF39ED84E1FAD63ADD0C9A86749ED9
+                               86759F8ACD0A5AF2E17B4E3CD5831B44
+        stream[65472..65535] = 6D2242273AEDC611159912EE0EC5D023
+                               44498AB4F513AAFB96E8C240C1F13B12
+                               EFABCDAD424200A53017DA7D34E9AB86
+                               9D099D239AFB45D067BF94A92E7D1007
+        stream[65536..65599] = 403105F52BF3456E08C2C698505E2639
+                               4594A257DC6BCF7E26A9AE184CDC8952
+                               C34D29E116809C91DCEF4B0FE57D87DD
+                               9385BF387732E49E265E67BDCB138D53
+      stream[131008..131071] = 86758A037E90380C2DF4DB0A7E13A115
+                               C0F83A664D5B6270306ED5B9A445D612
+                               DD0F9300603362F2574D8E262650D539
+                               708E2FB5D2CFABD3F365E23783271D2A
+                  xor-digest = 8513C47FCA708D9B3CECFEE6BEA39154
+                               1843C72A2BB767C926EEADB4D3708537
+                               B24A36FBF20273487B312095D6C6D866
+                               C61B0E56F71029E7F71FD091D65C6CB8
+
+Set 6, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                               3588DB2E81D4277ACD2073C6196CBF12
+                          IV = 167DE44BB21980E74EB51C83EA51B81F
+               stream[0..63] = 2C832BE30736D5F5514EA4A748E30EB6
+                               57F418886DF2E25A739E13B6C1B24736
+                               96B44CC2B3A054CE4E6D9817BCE6BE97
+                               E77D0B984C0F039329ADB559266270F8
+        stream[65472..65535] = FD7637AC01D2FFBB5AA389D6E9EE4E39
+                               4E81AF774491678E7A0181B1AD063B22
+                               6CD1703ADE35B17F1A8D4E8B6E0E0138
+                               66A75498C93A19ED37DC0398B61573C3
+        stream[65536..65599] = 318AA03B81B6C5C334E80811384A07F6
+                               BB7D0AB3FBAA1ED873BA2E01F920C1EA
+                               FF35AAB02AE0D4F9612E8171BFE63755
+                               421ECDB540189C2A10027D4199E35959
+      stream[131008..131071] = 7F688C0421F127D0CF5B773AA1B27A74
+                               0ACA0254CABEE4095809FA854A06D746
+                               AA06E56EE3A6AB471F4C46B0528B5D94
+                               BBB9E3BB989E01FE459F3190E2942FF7
+                  xor-digest = 97D161DDF9E98C70E6B63BD4DA8629FA
+                               BA4ACDF112E28FA029DA508F1709E977
+                               F57F3942997822020307071636BFBEE1
+                               AC7E3D9C97717474A8092576536DD8DC
+
+Set 6, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                               3A8DE03386D92C7FD22578CB1E71C417
+                          IV = 1F86ED54BB2289F057BE258CF35AC128
+               stream[0..63] = 31B2E5B938120CA131A0635F2A471710
+                               CDCB494678339BFC7710746BBCDF2700
+                               A0286EA735766D17E9FA270C63AC1C4F
+                               405101CAAFACD6C2BC4306E37E9516C3
+        stream[65472..65535] = E5AD2ACAE7BF99837475EFEB7C8F327C
+                               55811CDE424E7A5AFE33086CAFB6A63E
+                               6607C005DFDB8DB13181CD3FF8584823
+                               F0D6EC38083DFC3C7A8140DEB47372B8
+        stream[65536..65599] = 662728BE1DA1099208BE1BDBE7E5F28E
+                               8E2F112E527D2F48E2C9AF565729524A
+                               175A37A38F5CBB1761D21E907CC62BFC
+                               B3A4ADA96EEA24624C501D237F461E93
+      stream[131008..131071] = 609AD32104EC8FB79D91299D3B3B2942
+                               3E09F451597C0BBA26FA2FE97B9B3BD8
+                               0A8907A8236E245E8BA2332C6D027F66
+                               12DDE13BF4A149A1A6CE2DFA9F8A148F
+                  xor-digest = B245B3176CE7C0690A7CFB4C61C84E06
+                               041650BD4A199986D3AC4DDD80A1C806
+                               2FD17F9EA40D25E86EAC53CA4FF8487D
+                               A4379DB9BABAE6109859D9757A992100
+
+Set 6, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                               3F92E5388BDE3184D72A7DD02376C91C
+                          IV = 288FF65DC42B92F960C72E95FC63CA31
+               stream[0..63] = 8863C707A53A4201F070ECEF33DAD759
+                               712F20660A288C80E6E9073CD850CF84
+                               C96AC6DE9F11F0BA176C395E871C42D0
+                               420FE1D3E9E23C8E9EB4DAAD6C677C50
+        stream[65472..65535] = C9B8301378C62DC67A932B81147E76AD
+                               54A93FFDE7B04E82548B6344B8F63897
+                               3FCDCCE6F69AA0A25BA0BD527EE7C613
+                               5A89C5CEAA4BC69ADE9DDE839FDB47BE
+        stream[65536..65599] = 7079E98749DF66D72B8BBB1DD7A6B7D0
+                               6094E8723BB74D38A7223B2557B8BE25
+                               4313AFD06D79814BEED4F40DC9211D50
+                               165A8CA279AA2CB8A1393099B72607B0
+      stream[131008..131071] = 6C30F5011144AF9AE0D27E2D39E51372
+                               783A5BAEFB58F43578D0FFD947457C87
+                               F138CE84D42891A4BFD1F438735771B0
+                               FD495DF941B8BCE83C2EE9F11C18C04B
+                  xor-digest = 7E9DD203303EE6807075D16469FCDEE3
+                               C5BB95A359D4338AD06546061FA12F3F
+                               C24AAE71EE63F3D892AE93E5E327FE7C
+                               1C168CCEC2BD1CCAF905E5CB2DD75C29
+
+
+
+End of test vectors
diff --git a/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt
new file mode 100644
index 0000000..1555407
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/hc256/hc256/ecrypt_HC-256_256K_256IV.txt
@@ -0,0 +1,3257 @@
+********************************************************************************
+*                          ECRYPT Stream Cipher Project                        *
+********************************************************************************
+
+Primitive Name: HC-256
+======================
+Profile: S3___
+Key size: 256 bits
+IV size: 256 bits
+
+Test vectors -- set 1
+=====================
+
+(stream is generated by encrypting 512 zero bytes)
+
+Set 1, vector#  0:
+                         key = 80000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 240146C5EA6C72A8DFC93E54E8811C32
+                               A85E0BF7291BDDC0DBEAE086D051D5B0
+                               5CC9DD5C311ED2F7E8484CC477C68BC8
+                               C5D3F3450553F5327253768E958C0C55
+            stream[192..255] = 26C5976C37B009E57BE86064A99E8F59
+                               F9536410FAA9BF625D8DD2ABC9AABF09
+                               DF6B5EFC76CC6200F9E321E327AB0703
+                               2C78B351C5F7EEEFF2C6E374521CFF6E
+            stream[256..319] = 2F72E0E6E710D807D5120AD686DAADC3
+                               A5C1544557A4BA6B1D61F90FECD55328
+                               3C8F91B801DC435C5FFB1F8B33A23644
+                               8E21217C367108893D13AD41EA8F20F5
+            stream[448..511] = 68320BFC459C78596162EF5FEE2CF46C
+                               79EAFC681AE91F875672350C59D33D6F
+                               9E0CEEFE42EA9A0485E3E41C241CDE84
+                               9849DEC99219729D91270358B2F83F38
+                  xor-digest = 19E8083DE3499286788AE3A6DFE90AC7
+                               B77084682ED86D8039A67663CDC9ACCE
+                               D297F22C10FF7E4FAD773337B008A32B
+                               A7176F733045DE44782F04C1DDF28776
+
+Set 1, vector#  9:
+                         key = 00400000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4B1E2D728E06D7356F151D10DE9CBFB3
+                               C66A1E5B5ECD926E33F56B14CEDBFCC5
+                               40CD6D1089DD8E5CF008E4AAA3C4C89D
+                               11B136FB5656B5D4818D1BD1E562BB38
+            stream[192..255] = D5E6B5482535DB7F9352933242C164D7
+                               6528DF7AA013A4FC2F2B8C2D7DC0202F
+                               85774C16FAF22D5071A875B6A671D4B1
+                               A8C396AA5D2F14AFF9C4CD6C1DB89175
+            stream[256..319] = 3D0FCC3C90DE0328FD0C752458996FF2
+                               DF822E496CA42A7D7EBF3D958676A41D
+                               83A16EF3150B8C4C8F1763560B314287
+                               54B4A2EA5C4F74783BF8809F3A624664
+            stream[448..511] = 2D68526D25483C2A1F0B6F7101507804
+                               C9619E267F1FFF28C934D19201351465
+                               31D13592BC9F1739A0B090718052E4A0
+                               CAE9E0FA4555F2FAD27EC8AA2F14CC60
+                  xor-digest = D3C3131E402BCBA54DCE0AD35C5FD241
+                               3ED7056BF67B5163CBE6C9EAA9D27535
+                               7D2BFB7B2843DFE92709F047675CE06F
+                               5201611BCB8FF15C76D0E328D46345E4
+
+Set 1, vector# 18:
+                         key = 00002000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4A0CCA5AD387D49DF33FE8BE69FAD669
+                               270E3E6CF724F53FC3E509A2CEF1D174
+                               A67C2EF4B9D2C9B8A8177BBFBAA2C45F
+                               BDD25CBECBDB59A402FE3C4835854CAF
+            stream[192..255] = CA0F19D9996E6D3518D28D8169968ED2
+                               B03D118D4BC1C5E1847BA6EFE6A32D6A
+                               32BAF71A4C27B0BBC9B9BA03FE044D7A
+                               C9785A69E3B0E5B3B26AABE3AB093965
+            stream[256..319] = 6FD1A9F1EA228C39625FC0CBB2D4BF8F
+                               2C0EF1F37D4FAC56D8024D1B4F2AF33B
+                               8AB0D452F5155ADD5F0FEEED8104AD55
+                               9946D2E274ADE44170F5113630200B57
+            stream[448..511] = 5DA1476A1CBADD0797DD7EB9C0E563B9
+                               EEA2C55860C42C2C0A6B38B9344BA0C2
+                               345C7143D9A7E5BCDF9FA2606098DEA2
+                               142632258F844AA1A77CC9950D5ABD7F
+                  xor-digest = 0CCEB42D4045C09C45CD6C27B88606BA
+                               ECF7F6B30F50004AB2ACDAF89849519F
+                               61482EC4AAA2CF58C4206A228FA23AFE
+                               DD3BD50BC9C04744940A238966C2926B
+
+Set 1, vector# 27:
+                         key = 00000010000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 77CB199A639DE60664225AD1DB954B5F
+                               70DC01305D2D4073BE772B0863175EBB
+                               64FAB80EF324DBC85A9EF827EBAC7A5F
+                               CB088619C246CECE6F92B89A2122B6AB
+            stream[192..255] = 84C1E9B365F1CD23AFD5711BDF2B6F26
+                               F988A6CE29450108FD6814802355217D
+                               F6F329FCB3F5997401019BAE0AE43760
+                               ED6B658FCB4280F5A070728411EDA4CC
+            stream[256..319] = D0AD4A851E7A60DC789762A554A8FA76
+                               77FA610F4D868CFF1AB6025B2ECDECE8
+                               C554B4C0BDF543F58A1DD7CC68FD7AA6
+                               7EFCFD59D55372E85131D6284E7949AF
+            stream[448..511] = CF7F791090D04350930AA1E1A53B70E2
+                               691A231595E83F8BAB9613BDBAD868AB
+                               197D5E06B3397CC3D81F56B87BC7521E
+                               B0BE346552DABEBA863D5C81D7245C8B
+                  xor-digest = 2C77C0ED1F5AE20A97388ACA5300918D
+                               6246B04429F298E64A75828EDBD01900
+                               FC70CC103C31E0BB67B06D04128686AC
+                               5C5FA63FE714FC4DF18C551BDF81862F
+
+Set 1, vector# 36:
+                         key = 00000000080000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 54A5A2E883714170B471C0651D74A9F7
+                               D51287C89FB345DE0AF7003C3871425E
+                               FC885F033D79BAC9716B1ED5C637BD9B
+                               0F16FD8D613BFFAB634F0EC2497D7B3C
+            stream[192..255] = C7FBA70B19B749BBD0C84C7D31A5AA44
+                               155623116C44CD53D2E640034211E730
+                               277402F62D1FF1578236A2646AFE6108
+                               2C958D9D01C065D7335EF9C29415AD42
+            stream[256..319] = 2385E2A7070FEC7399BB3CEEA43C8D0F
+                               54D3607FC1C21BF173642287C1FC2C96
+                               D37695A7B1310E5E918EBE37113348B1
+                               707BB39E401A10FF14EF020CB7C44261
+            stream[448..511] = 5A87EF81C2CFA70D86B147E9587467B5
+                               22FCDB4EAF0353E11F73F3BCC1EA6C09
+                               E962A87A0842B9225E164DB0CD1A3BA3
+                               DA8C02E6746CD3AE0BC4754ADBE7EF6D
+                  xor-digest = A65BBEA2E397048E4714A8AB3C19EE6E
+                               91B9EB8048F35FA7AB9E003E9359BE0E
+                               C3EDA827AF485C23A941F7D656C76CA2
+                               5D12044923E43E61E7DDEBE7D9C87E3F
+
+Set 1, vector# 45:
+                         key = 00000000000400000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = FF81E156907CC2C01EE23F79F936809E
+                               3F88AC15CC01BDDDA378CC1BD2317444
+                               200E4E2C63E15FF07B0B40721970E7CA
+                               68F748A95A965EEC606318447BB31C2F
+            stream[192..255] = 4C4C42A330AD444388FCA4009CC0B196
+                               84AEC3EE65138A747FE86526A263969D
+                               87CCDDCC4C9A0EBDE2D088CCCEBE76F0
+                               52BAC07636937B1567637ADB498F7F8F
+            stream[256..319] = F550BCDF67C8E9C17B800487DF83A4BC
+                               73B809C4F3279D4CFE857780412F0F7B
+                               B838A9F0322BBA84D7AC51E469C5012E
+                               D774E52E3507C7D069F5169F0403C577
+            stream[448..511] = 9D92715109A301AD47BF2376D65E2519
+                               78E12098B0DEA5B779079A0FAAC4DB42
+                               5BA9EB00301A5F964336F7EE9C0D9667
+                               C4F0DBAE14BED3E49A6A746FCB186C65
+                  xor-digest = AD2264EC651E311BAC5FB36434773F5B
+                               4A4777B2B7F811A755269FDA8339DC97
+                               7A8C6A5F66E8737DD16A88DAB8545110
+                               EAE275892A767BCAC0757C396A690F67
+
+Set 1, vector# 54:
+                         key = 00000000000002000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3DC3C1A1A40E721F8A3A66960DB2C0F0
+                               6D8B7C07FE90D67C26F86200D6A1A1D9
+                               ADE4D53A35F7A016A506D9C62D344D49
+                               5C6DEAAE053247103B8F202B85A5036D
+            stream[192..255] = 9B83E56BB5E10B5C6C05C4B450B64FA5
+                               9C52AA63E207592999CBB48355517F05
+                               C93EA878BFAECE58CBCB948E81BEFD89
+                               AE0C5C13359C6CF5A673B4EDE28FAF0B
+            stream[256..319] = 388163F9F26536BE1221A46834CC77FE
+                               03D021C570A9DA36CD528E887ECEB2A4
+                               7146A8A930D6AC04694A0B9AE50FF55A
+                               41AD3B3D3E53F982563B5B458C078C0E
+            stream[448..511] = 3B0FF94C0C9FA0EB8B8CC1C691D04180
+                               5AB6436BAFCE8C16A1351883C88E945F
+                               8F912FF79CFCEFF7374936E830C9440D
+                               C676A5F00BB50EDB34F810AFFD9CA8B3
+                  xor-digest = 879534CEDD8CDBDDDE2E2216D55529AC
+                               1189B1C34A76ECEC179B8A240E890F8C
+                               640738DC37C14E4B950B9D8C507685B1
+                               28CF4782EC424A3712F54F6265A41E7B
+
+Set 1, vector# 63:
+                         key = 00000000000000010000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 12F0A17DEA167676992DFF2E7D812878
+                               629579519578EAFD885F212C7E04F035
+                               AF03732C3DA8CFB7B73054662F0593E7
+                               E40133706F04B1329BC3155DACD296AC
+            stream[192..255] = 41BB89D0BE44055E23813783C3EC4487
+                               2D102D6EE94475AAFFC7FEB8DE6849A2
+                               6B50DE77EB9B0B96EC9EA0216D13D64B
+                               1264A83D6B571A92948A5E35446B0503
+            stream[256..319] = 15E9C9168AF4AEF7F2EF1E832F40110B
+                               A8C08DE71D4F0AAA3A5C2FC59BF41005
+                               ECA654EB7F316B757FEAD5B0F4BF41F2
+                               C6D035A88B5477632F34D7F904B2939A
+            stream[448..511] = 8A2D446044F7930B696DBA896BA6CE69
+                               8F8B01E4282BCCDC4740BB6AB6ECF7B8
+                               9CA1CFCB5745B6577D0F440AAB7985BE
+                               BEC5DBEBD8B028B15DEA138F09018297
+                  xor-digest = 89CFE7E84993C6B608EAAECBAECD7847
+                               472703F3CD97F9315BA9CA13204B616C
+                               AAC0F37EBD1C58186620710FD6AE5EFC
+                               B7CBADA19AF8C0F7E1FB24913C2300FB
+
+Set 1, vector# 72:
+                         key = 00000000000000000080000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 7BC411ECF4AC2EF2C9B8C5B7CCFD791A
+                               E8250119E08C1B7F7A82F576FF66FC9A
+                               9D9BDB7570EAF276A60A3BC7E7BCBB86
+                               7A791A48F9E742D7D7480FBA67DCDA6E
+            stream[192..255] = F85A8E3219AE1E5F20A4FFC6814458C9
+                               5A4ECFE7FE739E151A45247A136E3BB6
+                               9C11987BB5D13B1B9A3077C8F4ADC9AA
+                               A555FC9725339E02390B9C9F75E1F38C
+            stream[256..319] = 8A2E88E0A773EA00C11138710BF12ED2
+                               7797AE7863B1EC84801D11B5B3914786
+                               F1D547382DAA9D5215CD4CBC783C700A
+                               9B09FCCFED28899D2F2EC148CEFA39B2
+            stream[448..511] = 95E3BA3237F370A4E0850F2CA0FCEC89
+                               E9D832CA6DC6A062BE7ADA8D8AEFD55D
+                               2BC7A3F46BF81DEA5DD9155E8D8FE918
+                               B5DFB1926460AB69663856EEBCD4C338
+                  xor-digest = ECE252DA29D20602D138E13C004D8B66
+                               8B09FD764B7D84FB83B8F4D924504D60
+                               277BAFC521A8AB0464E4EFC6BBB9E4B9
+                               A206C38154AE3A57B84D2D39CF45616E
+
+Set 1, vector# 81:
+                         key = 00000000000000000000400000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 139C2843F0BCBDD32C685F4EE2C7AF4D
+                               E6BC79789B77B1CA6CD94A01645EA243
+                               5B491F27C27D4EEB96FEA0ACE65C0D8B
+                               BAA642B5A07245BCD0930588FFC92A50
+            stream[192..255] = 5C76EB0D5323A7AAAA228F7718BB6736
+                               5B344559C24BEDEB2CA66414B5E81795
+                               428D55868611AF9AC7EA0E7424984037
+                               3251BF5206C361AA3631DEDA52DDD519
+            stream[256..319] = EAB18EFED266D4788015DBDD20A75058
+                               FA4DE35C1DC774ABABC476BCB0AA2CB1
+                               214E5463F4E20E7B999ED475D77DBA9D
+                               70FFCA0C7971CAEC3B285EE8F9F37C02
+            stream[448..511] = 081083D9AC30C9DB4E53597D64249D7B
+                               CCD847495A928CF4CE876237D92ED5E9
+                               E3D723EFC663CA0DDF34DABB941F42C1
+                               B48EFD59DDCAE71A1B82358A3328644A
+                  xor-digest = C08714035439EFBE455BAE68EEDDA0D2
+                               A6968F18827B214A097221C3A77F80AA
+                               E1DD9F3C72FA66C16EE278A76C19107B
+                               37CC32346DBDD29FB30059A8FC732DED
+
+Set 1, vector# 90:
+                         key = 00000000000000000000002000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = AD897A3C509B66728342A817D745460F
+                               6A258386FECF71DB95ADC716B8BC0462
+                               22C4EE887334718534E719F36454E440
+                               F9EC44A2DC38345CEEA9425BF5F10123
+            stream[192..255] = B32235522391A0BE105A993923760C6F
+                               BBDA849213C628776BCC5364F28EE5BA
+                               D498F186C3C57A8DBE5355C2A38DDB82
+                               54B321636EAD186788DF1BFC5B6F85F6
+            stream[256..319] = 499CC51B20538B14A05E490B6D5D10D9
+                               11079F58E3603A84AE6689293E3AEC56
+                               7545823F0B085469CAFFF01D2AFC5076
+                               C155F8B4B7DB4C49A9A993964928D11E
+            stream[448..511] = 65983D36E97AEF89C3A75616F7C098B7
+                               5CFD9C531AFF8184010E2CFD45163312
+                               FFBCF5AC70139CF12D97325CCEFD0B01
+                               FBE571FFBD7DC21B54D4B277A2205E56
+                  xor-digest = 90CD243B35747378B85B99474EE0BB3F
+                               CE7574CC19BEC5220255523276CDECE4
+                               5A16EF44C414ADF1D1CBE264872419CC
+                               EAF664CC74D36072E9B975FF40074006
+
+Set 1, vector# 99:
+                         key = 00000000000000000000000010000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 26F731F36F626943D4CBBD605CB67FBF
+                               E9301F24AA4E93EDB2D0DBB3FB17E8C8
+                               623054B3003BB12E1C8607FB53315AF0
+                               A139CDC381753A14342AB90AFDF43E67
+            stream[192..255] = C3B755D009DE9965D36B4111308B25EF
+                               39A137E373BA0E90E5AE2748115F29FC
+                               562A6F6894BFEA59587F991DD105DE1F
+                               67F62A73A72A4802ACE727335467F503
+            stream[256..319] = BA815578D19B3B384BA7AA7B972B1FC1
+                               7244FA75A4CFDC8C30ABBFDF6861F356
+                               6A9B68A6F60A61E6DC8E046FE75373E4
+                               B45EAC193127CBA3AC4F22345BFDCCFE
+            stream[448..511] = 99C68AC554291FCDC03F300D69CE68D8
+                               C4D4DFF5FB2D4C3079992D40FFCC9683
+                               DE471E6F2A406DCE03AF8EA17B7AE905
+                               12F1368B8EFDA838274812C4F134E2E6
+                  xor-digest = 01AB73AE53306196763ACB9ACFF9A624
+                               B83A7B339DB517AEB408292627EEBC43
+                               FCA6397320F50E96ECC3595B13BFED85
+                               1309458EFE35FA1167C2CCCC6A4CA83D
+
+Set 1, vector#108:
+                         key = 00000000000000000000000000080000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 031A1BAA02280255F0413D76F945138B
+                               C0835BFE7CA64B16AD090454F098B8CF
+                               34B1EE138E03C3CCD9FF918A58D06AD9
+                               2D7F3FB57D2E161A863A0C25391CCABF
+            stream[192..255] = 6810368C2B2A091C6FB3EBB76E960AC3
+                               BFD678F028EB6FC0F5B36C2D386A21A8
+                               FE46A5AE09DB0BD75359A8482EB6F5DF
+                               ADE199B796520807D60D9D93995EAFE7
+            stream[256..319] = 0F2CDD428FF6DF2A4621A8423E09939B
+                               014BEBC0ADBB8CE71B5E587DA408ED43
+                               04A12BD535257322122EEA2840A9447E
+                               CB1B6D3550ED14EE31424F5404B2B5B0
+            stream[448..511] = C63FCB06883F3AC65612EDF28C875477
+                               1D383D42A553EAFA37ECCE26061EC5AD
+                               C6FE3BF23E06CFDB14EC1DD996A7D4E3
+                               FCF7A0B9ACC69F37ADF428B434994595
+                  xor-digest = 463386D0F7A1306E87F3221C4ECC0597
+                               9474F620AF3563686ED5DEE291155225
+                               56B9372496638BA1631982D6B3F58CAE
+                               27810BB7AA93351B838D54EE761A8C94
+
+Set 1, vector#117:
+                         key = 00000000000000000000000000000400
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = AA4E7E8171A8E0AEDA6049999E0A06C2
+                               FFA43B9ADC5E9DCE4ECD8FC1D27BE792
+                               6FBE2ABB69A6B69D8C213A793C77096F
+                               D4DF7BBDBCDF007C914B7C817837D99C
+            stream[192..255] = FC90E3C82B8E7228C1ADC2F555068372
+                               4307902A0750149CE0B2EFD2CCFE9875
+                               DABE60E1B85CA117D05E4BD4F45B42E4
+                               55A9F42C60910C9BFF8DF8FAB53C81E1
+            stream[256..319] = 9BD976B88E9E5E23D0D40779644BB3F4
+                               CE5C6B16FA6D955C32369DFD19D632BC
+                               7730683D562320E39F75D8D8BD074968
+                               9ECAF0DCDCD99FF4C3939092E9576144
+            stream[448..511] = 51BE9CC1362669C0F79D2D88A42DBED6
+                               C3315002380AEB647C8F9C4036590527
+                               1D8915B985B8BE9CC1C5C7652139E609
+                               651EAC8A14DF661D9869982AE5735E9F
+                  xor-digest = 0B0C84D430687F488F8E45DECECD6D7F
+                               1947E32AC49BDD2139F5413E08A88F31
+                               F9AF6599498431F155AA10B7EC09F095
+                               8A5AFDAD486D2E6D50AF77FE98E33738
+
+Set 1, vector#126:
+                         key = 00000000000000000000000000000002
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 52F49050156E957C605656B2DF88EE1A
+                               5E3ADA99F9793B65456C4C6C322B8B5A
+                               28DCC91EE0E711BC33E0C13354542227
+                               613665CFA3A825B943444401EFB06ACB
+            stream[192..255] = D0907F5D5939D7B544476E299605972F
+                               FE422C64BC6343F9C81093AD0E3ACC72
+                               F4B67314892E36764736C0715E4D3438
+                               36BDB105214F5F8925F321F5FD865EE2
+            stream[256..319] = 96EEDA75474D65615795185B1BEE8D44
+                               A687420304B260E4C70FE7F542967325
+                               1826EAE010981F6262EE6CB639996467
+                               5F6B23825748128617721752283C16DB
+            stream[448..511] = D926085A441E507207850AFF3008D59D
+                               F7C9D3B69687D18CCFF2C2E09D4E4EA7
+                               FF0B72C04A86B80923DAE187FFB99170
+                               DBD4902AF77EEC42866A83B519F092FF
+                  xor-digest = 1E068ACCA6062CF26ECEC79F149BE139
+                               24AF8BF44377EAD1550B1560E4A1006A
+                               A6986C61581FF9E47D58F2E52434911D
+                               5AFCF914DBBAE183D02DDA3210768984
+
+Set 1, vector#135:
+                         key = 00000000000000000000000000000000
+                               01000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = EF5BBD7A620E8052F05DC269309AA7CF
+                               8AFD4AB2B941D905AEEFC721562E00D7
+                               04CA70113C8A90FA12A0C9B9CD1B9F9E
+                               6176602CC08B66410A8BB0F5E9837C27
+            stream[192..255] = AB843B43856FC77C1EC09C0DD2248617
+                               820344BD2CA0B025C39B0EBD5A750A6C
+                               7BDCE863C068E0D3A937A5B2C5B6ADFC
+                               609F6DF7778D88238B89288B2768DE99
+            stream[256..319] = 5E6AFBE41F47F35CA9298C973E613174
+                               529D9BEFA6D0713A5BFFD96B70D39044
+                               413E24FE57B01C426E8988EC365FEFEC
+                               1422CDFB956B12C6A799F5FDD4EE43D5
+            stream[448..511] = AA960C189C0A20870901D4E2F1901D0F
+                               A28AF3D974E14FB70736C191D4C9CA26
+                               48EEBA776339F80D57A8B783419E61B7
+                               52541CB296B4CD31C55DE3D34CEF0D31
+                  xor-digest = F163BB7ABD3914204ABAF08B844ECF05
+                               A36B7B37B8345115EFAA2AB2E7763E6A
+                               E044A83597C023FB41EFAEFBB63E4195
+                               B60AEA6399DEBC94C75BE883B3623733
+
+Set 1, vector#144:
+                         key = 00000000000000000000000000000000
+                               00008000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 9198011FAAD874AD77CD0C98DD99C7BA
+                               01B75CF9DE1E26321EC6AD293C73C675
+                               69A349157FD47672C5326276BA40F4C5
+                               0CF8D98134D0BC13879E9EC267110FDE
+            stream[192..255] = A9B3BEEA161ED996C44F6D3B93431C6F
+                               54DCD5DB88E62CA10D1067B9CB5D21DC
+                               D7E04C48D88DF54E1370D1C24C871BD3
+                               BDF9B956315996F95867D1E2494370CD
+            stream[256..319] = D09ECB5DF5B0526372B57CDF5DCA6AE0
+                               F005D2E2F27D50398E3D1D7FF2100BAA
+                               D6F2C03E431345A4F41CEF3E8D3F14CD
+                               C76A423720A936D27322559289F13D92
+            stream[448..511] = 5E8FE7964B052B6D27216E37C49CC913
+                               450FAE159C087E34CF67E8B0B8F516D6
+                               3C0B544CA29F9BCB2B48D3894D69DE3E
+                               1460783E82EB67990FFB7F92DA48E449
+                  xor-digest = 5515E37A3F274746847F551ECB7DB4BC
+                               2BC32237050BEE9AF2AD1BD8577034D3
+                               4A23AB8A2FFD00C7B8CB7D5CA0AB2421
+                               E7CECB2801A1B73A44FF3E798ACA8443
+
+Set 1, vector#153:
+                         key = 00000000000000000000000000000000
+                               00000040000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 02858548ED24761DC0AEC6752076D095
+                               7E78EF1FCFFD8E756C747586A3B59C22
+                               F42A9FCA9F103C3054E0B4F6EEC82101
+                               971F2A6F9611F7541152FA3BD7774474
+            stream[192..255] = C32ADE80873D1190E9807C25D73EC5B7
+                               C208AC693D98A664FF4D11205650F7FA
+                               A36B153BC1A3F0EE0F4319F2100F7F27
+                               31856BFAE36110C12EF0361259641D74
+            stream[256..319] = B8F74AD5930D1F2CEA6B9F7E4E775DF0
+                               AA97744677E5C96B9E55AD77BFAC5E8E
+                               E9BA7A19607D9EC52DEEBECD185DAE13
+                               E304743019D831849F111602EE6EC34B
+            stream[448..511] = 513303A57165287E793DB91F49C9A8ED
+                               522389F03634930512744884BCA45F4C
+                               ACB60FD077BF2C050D4002162FB811EC
+                               4AA855793CFF2E30665188471FFE0847
+                  xor-digest = 7EABCDBDA34E51E3A61D2F3340884BBB
+                               600E1D30216B7117081B3E5D04FD4523
+                               706D4F34C5FD604134DC89F570D6119D
+                               DBB7C5FB7CA90E38AC157832C3C956BD
+
+Set 1, vector#162:
+                         key = 00000000000000000000000000000000
+                               00000000200000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 689E48A85A40BD161BEC710F9B2457FD
+                               276F1156EBC10BB851A8517AFDBD692D
+                               E4827BAAFF218AF886439ED976147EBB
+                               BB1074BD599A80F6324C87BAC987B8C5
+            stream[192..255] = D9BA3E74CBAA58CA97DA3D3B1051BDF3
+                               29F6CD837B72022D2EAB5D20B02F53DC
+                               4755C764C50756A7101998C187E4F0F8
+                               F17A0C6797976C4FF1BA17B3D03C2218
+            stream[256..319] = F6F9B6F0F6E1D756C0242B48BC55EDE3
+                               3038BABF72FCDD5122C61804996F5ED0
+                               86A78B33C517CCED9C34580AA54AC03E
+                               BD0F9698A234787DFE97FCD3D9B7CEBE
+            stream[448..511] = C31091C4C5AD605BA90963B1D469E501
+                               412FEECDE3EA8EE834F188793A98F830
+                               81F8C941F11676E007074B40EB15DDB5
+                               67D93E954422376F2E3039F4E4115D70
+                  xor-digest = DF047B3EE7F2AAACE9D5A2B0F6A1EA0B
+                               97E815E9B9BDD3B7862ECB414E9C08E9
+                               BA0109B1D6866C9D7D6D3DC9FAE5F51A
+                               48DE7B9077DA489B7982BA69228483A2
+
+Set 1, vector#171:
+                         key = 00000000000000000000000000000000
+                               00000000001000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 1F8F707DDF0121AE4DF26A6ABDC195A7
+                               CB9CC8479588D2D436C52483DA54744A
+                               2880E3DC622180D36B64CC053CC245D8
+                               0700EC62ABCA6944BF89C7DE1A532A3C
+            stream[192..255] = CB2D934DD1414C60550CEA6FFA776312
+                               3C9336F99F16F8B5B8E60D5D0CE54A35
+                               E752A4887A03EEC95050E50B58F5C8C2
+                               FD814DE76D3F66B907C77C9B646EFD13
+            stream[256..319] = 10306DD8B3EA307496D7BEB7A679D53C
+                               3650ADC53991D0565856F51DA82CEB45
+                               AFB460D6F90877557E17F534C3375FD9
+                               F96D13AB77FA3996998F5DC6F5D3C9A3
+            stream[448..511] = 42F4D1F669741750B24A44F82990E6AD
+                               065E7B07B2194C96E7578F7A754E52A5
+                               86C820FFDDBA671A7B08D65B51D8736F
+                               D0DA8E81CC69BB8A56565C43845C0AF4
+                  xor-digest = C0535BC269BB39AC2ADCC50C62F87B6F
+                               2C9351DAD49813529A27BAEC163A1D8B
+                               778670F0FF1610A4688F86851050C9B7
+                               275B087A0B5CE01B602F8D1D25C29392
+
+Set 1, vector#180:
+                         key = 00000000000000000000000000000000
+                               00000000000008000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 899C1C50A80E374AE884F10BBD17D036
+                               1632D89938FDB7E4BCFBE1050D5E948C
+                               CF4631EDFEFD2F140FC3FBFCC096CD68
+                               1F6C1B0CE9E395FDEC56295AE331D8D0
+            stream[192..255] = 2F60CFD4D07E58DBC5127A98D2B1DDD6
+                               1F216F61F70AF12427108906AFEDA4AB
+                               B439A99765EB84E43D06EB7B3D984A3B
+                               53D8C054745A6E3B61F8444C84C7F30D
+            stream[256..319] = 1A92F3B4F6C4684201FA4AF201259AC2
+                               53637B41B734062C298E6F932DBDAC5E
+                               999FEC21B63539B5FAFC312D0CCE6137
+                               04AB3CE65E241A1C34D12ECCC840973C
+            stream[448..511] = 83A75C2E2C6D40FAEA049322DC1B2251
+                               306A8906A37DD30182C328D50E7B7AAF
+                               89671DD776C9C730EEE0DACEAC7D7038
+                               4A93426090F31EB851976B8B2ECA1FBA
+                  xor-digest = 6D85E7DA2069F1308D20A56DB17F3629
+                               09E80EA6A045DBE61FB037C3C8B9D448
+                               526A37A431A8BE49CE4F10B8CF6A33B8
+                               82E6ACD6309BA1B716810715666C6CDA
+
+Set 1, vector#189:
+                         key = 00000000000000000000000000000000
+                               00000000000000040000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F9E151BE5EA0F532E56958F173B8F104
+                               DC9E73D8FA289CC2F84C4BB10E8EA769
+                               57FBC8F539365B9E9518F8787D6CF927
+                               55F0C2B2845318337F36B80E22C59FD6
+            stream[192..255] = 27FAFEBD2EBCD2B67AB18BCFB7F8DC96
+                               F54C8A765B0E4B3DDC3013B599DEF791
+                               287FF3C0F48F339DA04B667E54696485
+                               D48751A001B548727338AD6FB82EAE42
+            stream[256..319] = 09DC2AFADEECB86278C64DDCA51EEF97
+                               C10B9852DB5F33A19C99C0D4F36D2959
+                               DE247E4DB356E67F2951E0309F18D6D7
+                               27D2A1BADCC44DC320E2AA80E1834198
+            stream[448..511] = 4103D8455B6DAE658915FACFF2F3F1F2
+                               856E2343143671565936301E9D1F635F
+                               EA732C9A096C3E955D33770E244ACEA4
+                               094E390239489F4D4F0A1F3C26A1589D
+                  xor-digest = 8DF4EC7886C386E5A0D7201A3E731E95
+                               5D1E281321C2B592E31681CC95D173A7
+                               C92E6112197C6A605F494F6E9C4AE73A
+                               21B966CBAB1628794F0E44202742EACE
+
+Set 1, vector#198:
+                         key = 00000000000000000000000000000000
+                               00000000000000000200000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 8B9B0CC804CB353F49564926E3FD846F
+                               A4758692FB110A428FAA3132F4C606CC
+                               A41CA937FDE463D9FEC51F419D60AE60
+                               1E8EDB30AB09E0B08D0143D885161B16
+            stream[192..255] = DC6DFDC4E36FC1D4BD87F731F761BCC3
+                               9837A790DBB766040B4508778C5CFC82
+                               8EF9EC4D76BE3AE0967DBC844A2D252C
+                               B942E97A2C6A185ECF4E1200BF9BC826
+            stream[256..319] = A9DE78C2204B712A9803594B872F29E9
+                               5E8962D7D719702FB3279F053D311292
+                               26A14FB06058AEEB6D283EE0A272C6F2
+                               D392B102E294A7CDF24928D5281D024E
+            stream[448..511] = EB822D7BDDA456BB6E109ECD330D4FB5
+                               1259D7042935BD5DFC787E903758C27C
+                               E9E9B191957E721A7013D36E5A29C09A
+                               3433205956A55460D1498124B2800423
+                  xor-digest = 10128D9A5EEA1D93E65462702DB15A8A
+                               23D0FDFCC5B0871639D704DEB9F580C1
+                               C88213CA166F3BBB89D0926CAE7E64C1
+                               0A24041A42B9D50CB0537A0585EE574D
+
+Set 1, vector#207:
+                         key = 00000000000000000000000000000000
+                               00000000000000000001000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DD4CCBD0B5068DF0193F50C11D2576E1
+                               A70040D6C2CDB98061498891D1791E63
+                               C4B5103A52146CE27D8F721E147EA612
+                               7E5BAE1FCD3DCD9053D5FF5EBA328BBF
+            stream[192..255] = 541F008D78EC1ADC5D1B930CC99D4A3D
+                               61BD60AAB9DDC8AF8594FCA129410232
+                               92BC44EE064E44E88A07ACD1B742666A
+                               D147F14102D23578E3B7DC00905586D1
+            stream[256..319] = 6834D2FB6BF3B46C0552AD83275CE6EB
+                               9482C2DFE40C6B1FD6F743CAC8F40A91
+                               5BA9A90FBE7CC0153D53C444D3F7A23D
+                               CDC3134E237F63E5A07C99C10B8EE87A
+            stream[448..511] = 9F75BC84091695FDAA2579AF9D34B2A7
+                               2B82D39A1E7FCFC4D18D6898A9CD3296
+                               0D50AF1B720E1347A0848782BE6AECC4
+                               684CCA05B893951A65EB7CB37F5FE240
+                  xor-digest = 12F358C7C4C697199F9AF17040115522
+                               062514A5DC3584BC515AAA4474A1D85B
+                               47A6A2D8C39E8234A5D11860BC1036E3
+                               957920C03E9A47E61AAFB058A9850559
+
+Set 1, vector#216:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000008000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C5958694DB1D54B95101A9F48660CB26
+                               8EDADED85C6239098248E0867117607C
+                               D5278E5B5D9CDA7BE8A6BBDCE61215B6
+                               2A93FFF627B28B271CF2275E54EA1CD0
+            stream[192..255] = D9B69B25B5729759F3180FF17421092B
+                               0740B2E1307FA9141915CB8C30C0C322
+                               A1E4710674EE715DF3AC89F447442A7F
+                               845E154393273BA47F2322BC661D1755
+            stream[256..319] = 49412E5F3C9B5B52FF790CBE82D6F037
+                               217A13B7744740A887F7C1FBE3714DEA
+                               2A4EA4A5F444B2EC3C0B160A251CB44F
+                               8DCA914FBB80F72BC8D009F1C7E001EA
+            stream[448..511] = E1C2BE8C64D6BFE081EDD30681763928
+                               85939DD7EBC13E16D83C8E7FF65EDBC5
+                               90FA3904068784806E20F0A61CC73839
+                               E3BACD410F59D3848F5A628EE030FC4E
+                  xor-digest = 54092B3D64197BD598F9050B44D2E785
+                               029F29F46822B72ECA40182E8ABDABA8
+                               751054FC50250DF5AF5AC75F4C51D1D5
+                               D2BE298770C353A7C5D608D1149F1452
+
+Set 1, vector#225:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000040000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 633A6CAC516B7A84CFF8F5702CD9BC81
+                               BCE328741675EBA0FD1368190AB6BEEA
+                               7C8B0256CEDF9E5CC6F9249511AB87AD
+                               ED95BF8E11182B8BEB75FFA279C3F706
+            stream[192..255] = C3F700538A4EEA17773E74D10CE4493E
+                               FB0417B380ED4229F651D6A9BE0AC617
+                               AF66C576B7D06F2210EF226462004D90
+                               E753D805AB198B73B0CCD752C7E57A2A
+            stream[256..319] = 30A11289A9E0C854B980BE044F07E945
+                               06D772861896D0F75D739647FFB939C8
+                               13FE4BE5C8DF84F64827306D0DD82415
+                               E104F787F30CD097EED7DB9340A0F47E
+            stream[448..511] = C2134984733448DD577DC48B5EE5D761
+                               0A54AB6C32E3BB782849D8E7E8B522B8
+                               0D6444342ADD9709D7434F9B4C18C6E0
+                               15AE97DF8F3D29FA6D85DA387157E223
+                  xor-digest = 8613454AD0B424AB6EFCEA96C0802B6F
+                               47F1E98C52BC68DA25E653431CE31078
+                               1658BC45DCC2EB43C4ACF8395727133D
+                               12A127D4CBAABAF24BA44930A58A87B6
+
+Set 1, vector#234:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000200000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 6A0F095C0E23FD6F8DCAEDAE5314141A
+                               0F1CE1C1BD6A16E81FEFF72F0753A5AF
+                               C1C54DFC0DD6ED99F1D416BE3C5EF341
+                               454C18D49729E80EE99F37734817658C
+            stream[192..255] = 05A4DF5BE8A35DC623D107728F28C789
+                               3DE0E75268B3E1F94C07AE50CA0891D6
+                               2B1E764CB41062391B33929273CE6B6D
+                               1C9CEFB35C37AB2FA8EC18749B5292B0
+            stream[256..319] = 41C8AF9ADA46F7BE8EA72BB3B8661B78
+                               2BE5649F18F216B75A0071A6617200B8
+                               463B08F986D706AD140E27C8F4E040BD
+                               6BFB4872D758363281C62AE8C4B64E33
+            stream[448..511] = 58CDA35476767EF58748A504B0E4A38B
+                               64162AD422A0DEC0434D879898558C77
+                               1A8243DC43B15FF996B4C8CAD3C47C6F
+                               26F00C71ADFB538D9A983B7B624D6E62
+                  xor-digest = 240A699AF4DDBB56A4C502A9175C0E3A
+                               BBD654D0717A1F6F6847381B978AE8C8
+                               0EB7CA07A481DFF8606A31BD6B489AE7
+                               89763068D641BAEADCBDA9ECAC465ABC
+
+Set 1, vector#243:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000001000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B3C91DA5911D7D7A4BC16A66988AFD3C
+                               8462A9E9BD0D95C9B9884DD14801E464
+                               C27048FEB5F70B28013099F0A31255A4
+                               9EACE528A13CB5DD067E520D183133BC
+            stream[192..255] = 756EDB0542FE1F11B159C7081D9CD742
+                               2F0E5862D39E2CF1517B2F6F39AE5245
+                               D659A5B93EB8FA8C8FB751B378BB0DEB
+                               481B874663624C8DC15E6A1A64376340
+            stream[256..319] = 436613C9293D5DCB204B46899CF23E65
+                               698BCC3003FE064FD1263EEBC59DDBAC
+                               536566855510FA802128F0A968A2E359
+                               FB68EAFD6AA89D394B32BF6069E92EFC
+            stream[448..511] = 033FF40203ACAEDFBF561A674EE74D97
+                               A535A448AFF94C8C167200E5CA626388
+                               DB1BD6EBD4A1D83CF352E97CD8F02671
+                               18E57B71D33930EC2752D2F262A55F9D
+                  xor-digest = 2CEEE4705688B20B3AF71F285DB9361B
+                               0EC945296B97F3A050C31C54E9A07CA6
+                               498B92917617571928E2663CBBAE21AD
+                               8DD880A037A024E46B6581974838AE1A
+
+Set 1, vector#252:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000008
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = A6AFA8AA02C3AE7F29E61202B4A5C25B
+                               6F74BCC176702C9C1D610FF722527A6E
+                               721ED90B871AEEC71EB62B24A8F24357
+                               07765F7724BA03173F51C9B66C9F4BDE
+            stream[192..255] = 002B8929A54C1370067A36DB9057807D
+                               DB747C2A4CE19BC085DDC517AADE3B97
+                               BB1B35F2BAA6A18E8154CD80DA6F9F4B
+                               0DBFD3EA5F69D5ED3B5770C6221A8D66
+            stream[256..319] = AADBBFDFC6FCC6072747BB528EBEEF34
+                               6DA76885CF1616ECFB89D3A134769902
+                               904AA12744DD404F268B0B4B34700928
+                               E3C4B3665B9CFBAD9C528EA06F89CCDA
+            stream[448..511] = DD5453BD0D99E7D2CFC558EA969A4E35
+                               743AFA96D570026106C5CF40037B1325
+                               40C909C1278DAC8369B1AC257FD8D868
+                               3648B4F22F7C66282BAC49D8D23626EB
+                  xor-digest = B3F2AD900155FD5D39768B4F4B7F8E5A
+                               1C557936F2B5F06966DCB884AFF7F01C
+                               7AFC073C20EAF85363DFF41357E626B3
+                               B19607224467413D185A05E7BFBC5F0D
+
+Test vectors -- set 2
+=====================
+
+Set 2, vector#  0:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 5B078985D8F6F30D42C5C02FA6B67951
+                               53F06534801F89F24E74248B720B4818
+                               CD9227ECEBCF4DBF8DBF6977E4AE14FA
+                               E8504C7BC8A9F3EA6C0106F5327E6981
+            stream[192..255] = 30DA9453A90909A5675D6B691CB0990F
+                               C423CDD8222EB47245BBB67BCA2B9C10
+                               8D1F016DF0CF8CEAF6829910916DBC1E
+                               113D11E91BEC3D85C47E3042EC865658
+            stream[256..319] = CAFED71B892EDBE13388CEF6A3365797
+                               E0D88C0D3A5B91BE4CBAF5162F69558F
+                               DBB45CA6F8C8D4C371D62736EC244584
+                               60131F54854F3EC804AA9A38E6ADE281
+            stream[448..511] = 531A0ED5D2A51DDC6499FE1BB6E2295F
+                               2C3EA0F56AF46ED93DFAA4E16F5F0831
+                               2D77BD0E9122043CD6A202CBA9351F6A
+                               0E8E6263F4017355136A0C551E6FD0F8
+                  xor-digest = 023D719F61C193E4CCD87755C87F9604
+                               C5A29DD7E31637B3DD70D43441D48CC7
+                               D474013C85EEAB1897C80ED0A0272543
+                               F951C72E3954616CB5D6B51FC24F4B0F
+
+Set 2, vector#  9:
+                         key = 09090909090909090909090909090909
+                               09090909090909090909090909090909
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F5C2926651AEED9AF1A9C2F04C03D081
+                               2145B56AEA46EB283A25A4C9E3D8BEB4
+                               821B418F06F2B9DCDF1A85AB8C02CD14
+                               62E1BBCAEC9AB0E99AA6AFF918BA627C
+            stream[192..255] = 3B3C6E78A8F381EE2C159FAE1C487C58
+                               11FA9BB02CECF7440239FBB0497347EF
+                               D8F1A8AA71AFC70ECCD64E81388E6E87
+                               9521C2B47AD84F9CFD9E240D8D2F3001
+            stream[256..319] = DB04FD01BC18D91E2D31237AD0FE26AD
+                               3C8D6A2EFDAA9CC11BFCC61D94F6104A
+                               4091B3634FA57AB0AB9B209F22DA5529
+                               75C3C322DEBE4AE68623BFE1B2BB7F0A
+            stream[448..511] = 35B290F85EBA78A978750690C4747E8F
+                               72621951483772E8B89876CC5D55F3AB
+                               02D9B8FB35C741279FF9B5B571B26329
+                               4D011F813CB5B209CA1A22D532BF09B7
+                  xor-digest = EA9BB65E87C987EA64BC3F4E710CCC34
+                               F6CD0A795B8347E1441CEBEE35540D41
+                               64FC2B95D71FD47A2C4ADF732261EE52
+                               8125BE374FA4A90132CC1063971A2862
+
+Set 2, vector# 18:
+                         key = 12121212121212121212121212121212
+                               12121212121212121212121212121212
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 397F8EC015ED573967938D1CEAFE9BBD
+                               BD8853C329B3A881B489090853FE0F43
+                               89DA105F0ADFA9CF51DA2521C40FD2B8
+                               FB0BF80B93E3F2B3D8A8EB1C615E0FA6
+            stream[192..255] = 68E7DBF465E3C6994D58B9937A866E4D
+                               43A82A80DAEDBF29C048639BA38B690B
+                               7ED11323E3C0A8E77A16356705431EC9
+                               9F2CB7F7E1ED3B83EAF2CAEC00B00755
+            stream[256..319] = DA51CF3A07EBE7E86E9DDDE5A47E7417
+                               376F334E6AEF9C187012C8AD2B94BE7C
+                               00A876756EB232510FD0798E72EEC87F
+                               75EC1467C07B3A1EFB0D51A5FA65E382
+            stream[448..511] = 0BF3C6FF6794887F2776FD632B83682B
+                               AAFD131432CFD7D2F675E03320395313
+                               AD4ED96E9052FE6B2D2A17428660A25E
+                               EE642B712800BE3F7E44F21A1E6A03AC
+                  xor-digest = EF4E84DBD66497B142EEAC56B830FF78
+                               0465CEE20B9CFAF5727D4B3A588F4D00
+                               AAF718330CFF35508C44C1ADB8476625
+                               2CC3AA6AAAE74F8BF1DDB6D4AADA425E
+
+Set 2, vector# 27:
+                         key = 1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                               1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B1B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 72BC8A6E1E61E704B142AA00812EE676
+                               263C1CB9AB941119B19D15EBA3462F56
+                               2F69220595DE5E0E7C595FA40F1F06B2
+                               6EC32252AF05310809DDDFAE2E24B170
+            stream[192..255] = B29A740B51B4EA1080666337D5551484
+                               FFED6860A5125DC0573C8F90F23A98E0
+                               BA7B3E4C28C2CEFB1C33D2C36D1B7625
+                               64B9A67240CF174347A4C8D868F00F6F
+            stream[256..319] = 555ABD5577A8909797FBA9769C03A0F6
+                               537C06AFB23354F054E25457B729B534
+                               CD10B2ABD45BE3E38DAF1B7A9103268F
+                               4FDB4C0FC9A80A003FCB907E8F249AE0
+            stream[448..511] = 3B29A43D9C795DAF1760CA9EB57C0B39
+                               F62D54311207B617B727FCCE1B2E762A
+                               060810C4DEF672E7D76083E3E4BED0D1
+                               0BAFD27CDFD2C937E660190D36B3FD7B
+                  xor-digest = 0B3B0B3C69F2E4BDA22E25AEF352234C
+                               18CC5E1E3F6A317ED7257887446EF734
+                               65CA15F51AF5E077B7915062391D8497
+                               8F437985DD08F5FA3A8D74B3227A6EEF
+
+Set 2, vector# 36:
+                         key = 24242424242424242424242424242424
+                               24242424242424242424242424242424
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C845BA29D542FBED2D021C85188E119F
+                               D34967B79D9F44635DD45D2E41DC5AFB
+                               B237AD2FA0E4CF4202D83DF3073C578D
+                               2AA8A32D30FB45DE28F23CEB85E50FBF
+            stream[192..255] = 15C910FDD3C590AED1ED7DA2A7969297
+                               FD12081B4B23F0A32CE5B3196173C7CA
+                               7EDD03F9637E08CA501C4850C15B207D
+                               7AA724377396CED2357B572BBF9E69AA
+            stream[256..319] = E484AF567EF80BAE77461855294E9280
+                               EF57E7366605785034D639D6DE3EBB0D
+                               E21886D0E1E0679BC2E2C9C2D9201484
+                               4A452B6AD3F1AC8B7762FF3C0E405B3B
+            stream[448..511] = 595D9855200786BB575FF7977509F395
+                               7879CA1F19619A99174BF013CB62F85B
+                               FF2C3C4FE724E26DD0C10D7635A2491A
+                               9E7E868D9DAD9201465AA178184D06AC
+                  xor-digest = 08737B82505F46F4FF282EF42F387AA8
+                               0450058F5314389BB73733BC163D75D5
+                               D32FC6408F8DE5F6ED2050027D605FAC
+                               A7119FC2DC1B6D3E84E8048DCC42FBD2
+
+Set 2, vector# 45:
+                         key = 2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                               2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D2D
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CA82A689535CA8BAE01BAFEBA6504B3E
+                               6E6320101999BCE5550C2BBC9BC65D91
+                               FAA2D72FA4BF46B6EE916244048B1D09
+                               A115E3AB6C00BAC8EE382B58859E8157
+            stream[192..255] = DE787B1CE01B0BC09801D78D1FFA3A82
+                               0C18B867C561E96DF4ADADC5A4375E44
+                               5A34F9457E5F8C9A337A0C88DF0F723A
+                               D4509F1449DF2C6AEC0EADF4C7A8139A
+            stream[256..319] = 7E1854FA15DF9D5827F1555F12B292C8
+                               452A1A893EF034C51750388D294947EE
+                               3F505839C69C1708E8323C449C39A96B
+                               FC9EC91B0E1CAA8112057EB0389FDFD2
+            stream[448..511] = C85B42B838FB9C3D4956C9E22FBD8FBC
+                               EDD92C4461EFBA5CF1664B9AF54857BE
+                               C3D00319E5E8A89A8322831151EE1D52
+                               D8585AC79CB60B61ED2C852D04BB0FB1
+                  xor-digest = C65A6BEBC4FE898DB8D6B8F6E8F3680D
+                               2363BC12259B0FDB2BD8F052A572ECA8
+                               D1EF62AA9A48497805A413742B5AF5A2
+                               6DC9FF624B49E5D6FE58BBE5251B4983
+
+Set 2, vector# 54:
+                         key = 36363636363636363636363636363636
+                               36363636363636363636363636363636
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 9F6BCFDE566A1B67C608F11B8461E340
+                               42D4F07DA4D5EB05554CB7426D65C5EC
+                               A93C2D321175B6F72FCBEBA6E38CB098
+                               B72534F7D534B1AADD97B77E8513B482
+            stream[192..255] = B2466A173F436C8433F264CBF125B8E4
+                               C10BC81BD46B5C21FA161CB2AE07D27B
+                               F66812A2C2FCB2B14C23E413CEF4E591
+                               AD52EF810A000B42E5C1B76EEBB17739
+            stream[256..319] = ECBED2058DC50223614EB8635B834C3B
+                               B176719C18CA5E3D087A93E5CDF81123
+                               C6FB819CCAFB5042AADFED5E3C33116A
+                               FD92AA21031165A22F4751C423B8B945
+            stream[448..511] = 758BD9435DE607867DA256064C304C8E
+                               DDDF5B64173CF2C98B2842992F8C5FE1
+                               A37C3227B7F37D49A39F9FF929A883FD
+                               56DB8B1A174E1E55FCB21C9E1164C20B
+                  xor-digest = 31761A49503946701D35306FBCBE10E2
+                               02967E7EC14A328B4DB19FE79F03553F
+                               13A012B7297B2D02F18A216AD24A682B
+                               299518C3769123EE86A4937DAA9FC39B
+
+Set 2, vector# 63:
+                         key = 3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                               3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 85C7FF83641ECF1C91B2D996D4EAFF6B
+                               26A4E7E34C0CA9CB9399F655E566383E
+                               246143F57776C8E08951E87F76091FE7
+                               2356CC901F09A07895A890AECF047B3F
+            stream[192..255] = 4CE0C6606195F7562D485E32E8E105AF
+                               C862100A07E55FB449BCFA2D9BD48658
+                               958B37B3EA3565FA66824102A14B5770
+                               5E3914E0680E116ED58212CBF61028E3
+            stream[256..319] = 3BB772A5A8DE2AB14CAC1ACBF45B1701
+                               057710F24C01E680F58090B8E949AF01
+                               8970A43A698A04C0C8639FAA665DA3AA
+                               562B2C5C3A03BCC38FE75DC1821ED718
+            stream[448..511] = C73DEA1F7BFE42DF75EA2681BEB31948
+                               821FBB049DAD15B988A77C0247868A38
+                               2056B66F47B0195FA30C9DB5A2334A9D
+                               CD7C0D22E479FAE1BBCDFFE60F261C7F
+                  xor-digest = 94D41CCAD940CED3C854DA0796DC62E5
+                               6B566A980E34F353CFFD0F53AE9E34FF
+                               A6A057645FE66D86BE30F93805D9E2B5
+                               D78C68EEBF61CE387277A51EB2EF835B
+
+Set 2, vector# 72:
+                         key = 48484848484848484848484848484848
+                               48484848484848484848484848484848
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E45194379659D1D8904DB3698AF8B245
+                               762910B7FBD019AD1AA20A6C433B4C80
+                               308A9EA68697631646BF3A2107C4E7FE
+                               2235E8F3262A9DFD3F5CC23FEB0B2DAB
+            stream[192..255] = 012611EBCFF9F839DDABF99D9D4757DA
+                               4E947598C4757976F6F61DA5F0DAC8BC
+                               DDF72F08BA2F446FA37F9A490F6A2B6D
+                               79227C93271D6B763DA7B2A907220A42
+            stream[256..319] = DDE54F9170D6A4702CAF45CC6F799F74
+                               A43D83AB8ECBAC5206D108F869561D70
+                               F151A0037F8E28951B5026643F8B2D6D
+                               56A62E259F04A5EA304791A9468E66AF
+            stream[448..511] = F70794C084E6EDC07BA0347413B05FC9
+                               FC46994CA820CE4FC037ADBA50EAA9AD
+                               55064ACB7308CFCE3F35AD5C7C628362
+                               F4210FBC2D3264F734728626BABF5356
+                  xor-digest = 31815B36BA034BB1941DB1E45A941A59
+                               7C3882F34BD3BF441CAE8A9790B05BCA
+                               72049FD10C09A14AC9DB867A82C38A5F
+                               524C72F783DFD16980DBCDEB486FAE96
+
+Set 2, vector# 81:
+                         key = 51515151515151515151515151515151
+                               51515151515151515151515151515151
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3C04E21F6937C4EF472BFDDA89F9CAF6
+                               FF53889A9979ABA8F23AA51DB1EDB8E9
+                               D08F696C1100799A7D004DEF1CA94110
+                               FCF0C054B0C131E6FAE0FE2F2DBF22B3
+            stream[192..255] = 9B4ED3EF9639B953186FC7E732E7A9EC
+                               55A5F3F19C5A10E12EBE46DD84F10385
+                               33837693588D584FDAF86E3A217C3CFF
+                               020278736F1A90CE07F0DCE4329005B9
+            stream[256..319] = 135FAD68B5282FE59B28D2DF66463632
+                               06CA92E84A73FA131EDDCE89A5C23B4D
+                               08FA57D455BDB32F8ED58DAF3EF288A2
+                               7C72020E35DAE19B446E4C52DCDAC5B1
+            stream[448..511] = 7D08FE1CAA0E8A0362669B310B99127D
+                               18F2111002891D3229102D72605B9BEE
+                               F5DA36059B0DBBA7646927650305431B
+                               FDA4A97570CD0C484BF1E974B157ED7F
+                  xor-digest = 5125E77698C0DAA89A7E47DC5D038D40
+                               7B732CE56CEB674CE653A1B6661B2740
+                               0C092AFF83BEEE4FC4543B9D725C9387
+                               2F89AA338222ED677BF59397200AB304
+
+Set 2, vector# 90:
+                         key = 5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                               5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A5A
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DA2E6F7FF0D1F1C87A97E028D3E20E21
+                               75E9AD91482965B651B495AEE819CC6E
+                               C42AFE2C20EEACCEC4E90710D17210E0
+                               4CC6832905985322C8007F872D3E58E1
+            stream[192..255] = 09B0A38E19DDDA08F7DFEF7D0FC80560
+                               D692A020F0A66F609374ABDCD1343722
+                               05F19CA04EBDD3009844BC540C1B2B41
+                               66D45E8A2E822B906DA34649E7FEEBB3
+            stream[256..319] = 6C8E2CE1D7FABA414432E75BA2EFE4AF
+                               CE2CFE99506677A956AEC86BD290B6AF
+                               C5298A448D0DEFA99AA5CD26D318982F
+                               E786D809C713D5A55B42CA6650191DDC
+            stream[448..511] = 845FEA0A88B521CCB8927C9457AD3225
+                               EF6E3C21705EC9FB24873916A2C24668
+                               963C03FE097DA8224A42A99E5DFFDC17
+                               68CF518DE49CCAC8A70216C62C9CBA6D
+                  xor-digest = A46BFD9D2D0BCC688A032F54733AB7C5
+                               5FF58B296071D5D39349A531E41F0BA9
+                               893A1722B6102740BC5FE394A49363B9
+                               6A626AB43FD6A288CD9B23F7255279F8
+
+Set 2, vector# 99:
+                         key = 63636363636363636363636363636363
+                               63636363636363636363636363636363
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CF0E05248AAD82F1C8CD2095ED2DA333
+                               BCB02E3AD8797377AE1F1B4D6DDB86E6
+                               2A59791CB553550E0492FAB42C7A2C42
+                               3157C5092D2DD37D46589F17FBD86584
+            stream[192..255] = 9E946626F1EAAEDA42E52422B4A84D91
+                               4122EEE5736BCD12061C77DF5B0122B5
+                               1784E946B4E93470170ACDD7E2779591
+                               57BCC9B9F3E11E88BC2F740AA0C10C97
+            stream[256..319] = FF22D8196AB3DF662210D12D0FE79255
+                               6DCD39611C07F089979CF7D693A30CA3
+                               5B795B7F6D64931916E717C8BFB92114
+                               DB75118BDB51D142CE8133415C6B3456
+            stream[448..511] = 971F007EFE17662D95F47F4F28266516
+                               B22A1E50755EEF19149DE3A3121F5FEC
+                               E0D9DFE7A055026CA44193542D7687EC
+                               695B97769BF02F92C1EF3D904A8010C6
+                  xor-digest = D1C4878BEFCE48888A43C6DDE7CC8163
+                               C8D54A4CA36748C74721C7B6E1649A31
+                               4B5B7A4BD43E7C3D2A22F0C8446C7892
+                               90D54D421D37CB16400E59CC86215CC8
+
+Set 2, vector#108:
+                         key = 6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                               6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 54F122FC8ECFB176E7F4CF172B2D78B6
+                               54BC11ECF0010D2AEB9F899130F4AC2A
+                               38EBC15C8831D591E6675DC1CE7A471C
+                               4B869FE83CBF37AC70BAAE5D4AC607F9
+            stream[192..255] = 518F298A6008532EEFECB3DCF72103BD
+                               5E3F84FEB6EA2311E8C19A2E93A9C3C3
+                               BB1DA7DBA78D5618D1C4FA5B0B202728
+                               62645A361E55494D66C9359E41E5809B
+            stream[256..319] = BAFFFC9206D1D813F3E2768F08D78B2A
+                               89BB20CCD92E7F13FDD816DD4E4963C2
+                               C5FC2570CBB8BB5C70848B73001F508F
+                               47AF179528200F51CDC6E4854EAA63C3
+            stream[448..511] = 844B1D15FBFD1264169279ACD525611F
+                               A39C7BB41F1E7A1C09090625F7926E51
+                               23A4CD7FE1A3F37ADC67AC437BF0A5AE
+                               FFFC6FB0ABF39D9908145004AA5B958D
+                  xor-digest = EC67596C9DEF4012A2D543842829306A
+                               4285A3B8038818F265065DC848BD80FE
+                               C27C2F66A57B27F7FA8AC912001EC954
+                               05BC6E93D7E555C59060F5D2E294D103
+
+Set 2, vector#117:
+                         key = 75757575757575757575757575757575
+                               75757575757575757575757575757575
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 91D2772A18995DB3C0801DD3740F4466
+                               F9535E5BECB93DDCA0E94D19C0B57BDD
+                               0FFBA9DAF0B11D55C852927F8BA560EC
+                               4999E25848D08FCA7275E7E8571A5F1C
+            stream[192..255] = 72E64FF10CA9F07CC493715724DA7610
+                               9E4358E8B0CAE451348B784A162DF036
+                               AB9796724D17FDBF356031D080A6631C
+                               D1E8D217B041AD2EDF427972653206B2
+            stream[256..319] = 4054F770C93FCAB533143FFCA8E4C0F3
+                               344956C29D10374E502C2EDD177ECE5E
+                               6625BAD9630DAD57976216CD69865058
+                               130B132FEC1AB0C350DF4DACE4C7724A
+            stream[448..511] = 40B4A4DD63F7B6E932482D0E6F5BBB90
+                               E402466550B518A177CD05985D238827
+                               BD92EE7EC22C274F19E682F85ABDAD95
+                               D0EBB3DB6C6134408353C8B0472C9A1D
+                  xor-digest = 9A6C893F2108D13A29373DEDA65386C4
+                               AC356BDDD4A3178952F9126E322B7AE6
+                               83C94F1A131CBEAFF26549D9F84CF04A
+                               1241FA374B055B0ADE7E49E8EC669E65
+
+Set 2, vector#126:
+                         key = 7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                               7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 87A7773A3514EB7F882F2C491E90DCF3
+                               059C5CC575D806B9029CCE3FA45A246E
+                               0EBD3AB2F2E324FE36ADC3B56AE2F7EF
+                               C710AA964CB87381386C2A88B1308035
+            stream[192..255] = 415D6F59DD004944D4E45FECC6F1F06E
+                               20BEB18D9C84187C347F43B17E0924F1
+                               2348F825E106E57A00258CE4415294D9
+                               4323A9812D8A71359CEC1001BAA0D567
+            stream[256..319] = 8E20F0D03F37EF4B2C5EE12B5F81F7C5
+                               32D62E779FA0D2D08F8ABB6B0183A4DA
+                               4EE0329215F261D953150B9AB9FCBE2F
+                               568AAE361EAA8636ECC01A63F007977F
+            stream[448..511] = E7C44F44E06321A20E25F73E2069757C
+                               90499DB7E60025CF6D2D445E53A665F3
+                               08EC96F6FE73C0AC90D7E4A712E18C2D
+                               3DED46DFBAFA24C4B0B329E52C525976
+                  xor-digest = 22035341489FA6EEB2A6488CA42F4043
+                               57477C3F55569A1224EC39B1019E90C8
+                               21D37D78ED4DCEAF6EA70724C3751760
+                               38CF25DE4F84BABD80424D83A310881B
+
+Set 2, vector#135:
+                         key = 87878787878787878787878787878787
+                               87878787878787878787878787878787
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CEC0C3852E3B98233EBCB975C10B1191
+                               3C69F2275EB97A1402EDF16C6FBE19BE
+                               79D65360445BCB63676E6553B609A065
+                               0155C3B22DD1975AC0F3F65063A2E16E
+            stream[192..255] = 5E12BA9DE76F9ABF061782EC1C4FBBAB
+                               3373B816DA256CAAC37914B0C161E4E4
+                               5F5ADBE444098A5B2A4CFD4251D79918
+                               987BB834BB50F0834EF4985F356B92A2
+            stream[256..319] = D89642D25DF97D149AE07EA18BA39497
+                               8935978AC34C1DF9F444986D7505DB4C
+                               7E08DB3616B84CD52E7DD7FB108C36B8
+                               B50C2573172F4D3500B6D62A9D20B82A
+            stream[448..511] = A2C17FE7371604556F796429C6BE0688
+                               8611638B310F3E9FAF484BA9EE29C16D
+                               2F842EAF33AFEC557B68D2F453569187
+                               A6F4CD204A0E7A733E81AB7CE9FCAE81
+                  xor-digest = A7C93087CA70DDFE5FA5F1F2F954320B
+                               6E3A61977A7C6AC2F033B826AB9A9957
+                               66671D2A1025CDF8E2824B2F58CB221D
+                               2A68679239D90152FF7D0D39B33FAB93
+
+Set 2, vector#144:
+                         key = 90909090909090909090909090909090
+                               90909090909090909090909090909090
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 7118889F6E46A6523BBEFCDB006B3BC6
+                               71A6D390BC7099A708D370DCD0E3D143
+                               A0334619EBD5C7DA9EF6301F29273F85
+                               2DFA3C580ED65C6E952F88A0B7FE368E
+            stream[192..255] = 31D61E133CA1AAE400CB2DBBAE93C75B
+                               445792061AA0539DA69ED0B77B970C0B
+                               482156A5DEE4082A61364BF06E692399
+                               FB9F4411FEC515291F8949B20F57229E
+            stream[256..319] = 993E815F299D4841518119BFF88F6EFB
+                               F3DB9BAE60238BDE2845DE4DBA6D79DB
+                               C9E42BA5C3C004AE4546FD86C660FFC8
+                               FD6A8A349669FFE3D9E5BDF8E50A407D
+            stream[448..511] = 0F9CEAC6BDCBB56B7E97DDC95877B2B2
+                               1274F4A6D814B5440C74D53A3FF0735D
+                               EF01B14AE4188E215CE7337C04871688
+                               7159695A241BFB9D6B489FE9E23B2AD8
+                  xor-digest = 0BD5739ED28778023E6303FD88DAABC4
+                               0FA0A211A1A5C5F230D9E67DDD9EA517
+                               FEBCDF0BDBC107291B6CF3ACD8B862B8
+                               4BF15400493A54036E97FDEBB9A1DB2C
+
+Set 2, vector#153:
+                         key = 99999999999999999999999999999999
+                               99999999999999999999999999999999
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 236ECC5AB83DB1C5CD1C5A888CFEA2DC
+                               BE99E7E515650511FF7016A0EF287ADE
+                               5A03839C4F83F05FAC3B0B24D4E3F602
+                               3251F8D9CC4530A805F8A6A912EFAB1C
+            stream[192..255] = 792823ACE2C0DDB266A118068AE295CD
+                               716E424D3B98A9DB2501A3F5DF7DC70A
+                               3BD2C6E664D5E13317D6F57B8774C903
+                               D407D2BB6014E0F971141E89569C5868
+            stream[256..319] = 2D6ECCF738FC00ECD5475EDA959A73BB
+                               304C81FA9DDE0C21592247C4098D9347
+                               1DA30294DE8C100E5B17A199F744CAC2
+                               4E33490FC7F223FD6B4923056117C6D9
+            stream[448..511] = E791A6BE7F7593788E5D627F5CDAAB59
+                               349AF2BB1DA2BA622B9824F729929098
+                               BD19DFC05D0D9454F604960C027752F9
+                               7812E53DE6AC6CD2751AB331703646AF
+                  xor-digest = B7C5CE0D2FF66533A1C948C425F33FF2
+                               DC458E7E517637596FC8FB710E2E5636
+                               DB1F14848CB12793D54ABD0856B22F3A
+                               ADFA8C33AD08B8CC5292DD76913CB105
+
+Set 2, vector#162:
+                         key = A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                               A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2A2
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 74490D19F13E7C6D1B25C6408E23F229
+                               8A8806402755660C4A30CD216A500BB6
+                               AE975E08EC62D08425A8A62A71B00215
+                               DE35E5178902348698528CB82296F009
+            stream[192..255] = 51A6EC18829928EE94C37A5CD030CC4C
+                               E4F7E1B3E78C3A5DF07592F45B968BEF
+                               F95B8B257DAF2B468284627AF4481FD2
+                               67BE0B164DD86721DC8C1607A0607EF0
+            stream[256..319] = 75C565D5A5A240B003273F99BEB3E4B3
+                               9C056162B626F383F3E77B5C98C0FBE9
+                               119A7C335C333E6490126AC2510CDFAA
+                               86441C72D1DD9ACBCD3FEFC0D0C794C7
+            stream[448..511] = 2D90CCF0B43239D725E3B53C31B82754
+                               246C065AD23A8D709161FC74B34E23DB
+                               B918EAFA4465125D3780BF0B5803AACA
+                               037AA0A14D977141B611A6CA2278B634
+                  xor-digest = FEFDA1A6E95920B93380CC24FAE214C5
+                               6B009ADCB176D519CA4B8538EDFC95D1
+                               6CA06B730B28A230F0085FE43CBEE2FA
+                               2EE5DCD74D66F5CBB59F256CC1ED885A
+
+Set 2, vector#171:
+                         key = ABABABABABABABABABABABABABABABAB
+                               ABABABABABABABABABABABABABABABAB
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 22E1A884ED2C67CCB2977105649B6544
+                               367858D1A730AA2FA96703FA406B337A
+                               B2159A389BEF48D8A215D870B2968E16
+                               B11571F12BEC0A07FA7D3B9790987EC7
+            stream[192..255] = 4C98DD259D03A40AF38E0ED0F37CBD74
+                               B27776E9250B8B063E52E169C7B76A15
+                               0D699278AA4124427B5EB6AFC4AD5DBF
+                               600FEAAA98A88DFF297DACA5ACB4878F
+            stream[256..319] = 5FC732A26406FF0DBC764ACB05C83484
+                               976B640E60CCD6ABFB908583ABEC3E75
+                               2878371EBB5374C9B37A63E0768AE10B
+                               D857253D940AC408EF49EDD590E806AE
+            stream[448..511] = F012E429C44D5DC03B88123855B62C0E
+                               90E06759306017B5773752973850531B
+                               C480316CBBAEDE6353AD5FB298349AA9
+                               16AC0221A4CE1E4729BFB9C230AAF9FB
+                  xor-digest = D73B872315F9052C67C4CFC5CD912DBD
+                               60DA32FD06D9C8E804968E688898200C
+                               1D979DFFCE52E1C3B3309B58D12BDBB3
+                               D3EBA2954D1587D720E004E12EB4A13B
+
+Set 2, vector#180:
+                         key = B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                               B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4B4
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BEF4DD0101F80A8F880BE0613B2AAF88
+                               D2EF924014F7445ED922E9C021571909
+                               D7E6BFCAEE0724F2A9C522C4BDE4BBE9
+                               FE53FE592C0FEB80D2C7A51FB8BE9EF3
+            stream[192..255] = 6B1966D3EE460999FF09001B0ADEC484
+                               0D22CDDFF39EB0E3D5FDF74C6E7B3394
+                               A0A4271D780DE6DEE9AC58B4903EEDD2
+                               6DD14E14A4DFE506748D5DCA6DDF4C5A
+            stream[256..319] = E79D99119996FBB5163335E2F79F0502
+                               7AEA5372136E7B3C5BE1F4A673A2DC74
+                               60834B81BE6C4976C4A727C8E6046A64
+                               4CAF42EEA6A068B7E532581E9037BE9F
+            stream[448..511] = 5C4F52E0E94884C829DA1FE88EF34614
+                               9F3EE55A136EFA3B417DB63D2487DF82
+                               794E161B3153DDB2E1E4F385E1A848C7
+                               729FF5CB1CB58D5E73FAB1F2DCEEE5AD
+                  xor-digest = 2F3C231B0228C274255F3BD314ECC7F3
+                               1B9C49177009AFF2CD88F807092D77E3
+                               C74C1B9B8650F581EC7603F4D6E70955
+                               1B00C3192414C04AB0AD8B0B9BCFE988
+
+Set 2, vector#189:
+                         key = BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                               BDBDBDBDBDBDBDBDBDBDBDBDBDBDBDBD
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 05AF4F98E9D526CD7912F3E8CAF45410
+                               DED6D4E331633C5621B94E7EBD15E856
+                               04AB202A553EFED55A548C7AFFCD2550
+                               60315FD50A305D8BCAC9C077229D34AC
+            stream[192..255] = 786D24EF3FBFF6883A4ECC4F40E445AF
+                               3CFD130D5B6A9CE37BEBA429AD137A82
+                               44D0586FEB16D086F533D1885A82F73C
+                               F2AD2C645591F80ED09942F0A08D898C
+            stream[256..319] = C214B6AC700164FA66DE346A27A99463
+                               C5B6C0E43A9057384BE168E163058FCB
+                               6E7DEC871C6531EFC8B8D581EF92757E
+                               219294D39E0C9C8276440BE56C3D9941
+            stream[448..511] = 22CF14F5BD70E719AFE76C53E5D611AE
+                               4C8D2171695C9CF97E2936A8BB320670
+                               015825547A508EB43D96F2EE1EE2CB34
+                               4E120F001500F8ACC3E19E30455D09D0
+                  xor-digest = FE5928C74EA21F23E29171E5AAACA20C
+                               DD8571E907763C96B99A8C11F9A1D2F5
+                               78F68A6C440996995F7AB6E69B3CCE33
+                               CF8CE0C16F54355696D47DBF82EA8D56
+
+Set 2, vector#198:
+                         key = C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                               C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6C6
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 75559677D7C762F6CFED942D800F2FAB
+                               AB5F3892DC2C79922E96FD34FE511C11
+                               251C8EB7C639E531CE08A8C99F62E7BC
+                               F68FBAFF99D62348FF91CCFEC2710055
+            stream[192..255] = 149806A4D862EEA81F0208D927339E5E
+                               C98E9C2A6E0DB85CC0380DED7EC5B8AC
+                               4ADAE76AEB9C7B7264C3834316209615
+                               25221D58C0174577110596FF89C8FC69
+            stream[256..319] = 137E527A0ACB8B96A9FA07890B60B78B
+                               3CDD19BF89B31FF75A814F470BF97E0E
+                               1293B750B769F5BDD750DE5025D7534C
+                               AD541A1F26C6AE9AC2FD3237C156AEBB
+            stream[448..511] = 0958243E88921B81F04AE63658E52D76
+                               CF2638495B3A6B970633A7C8F67B8CF9
+                               AC378082F72FC63BEA02881CC5B28D9D
+                               C8C261C78B2872B5EBFC82336D6E1A28
+                  xor-digest = 0084D7BED4953402FE8F7FF71A28CEC7
+                               0028A08A00EF935C06A8B3632DAD5914
+                               84E44E372A753F8E630741266C0F4218
+                               4923608103042C70ED4ECC5112B9AF6B
+
+Set 2, vector#207:
+                         key = CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                               CFCFCFCFCFCFCFCFCFCFCFCFCFCFCFCF
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0C46BF67A3DBA5DCCF8E4A7A65B6FE28
+                               98C701CBF5E88F1F3DCB6B873E5CAEEF
+                               23024ADA678E1A2CA9E25AA8B476CF4F
+                               9FCBC297FF03A9B94A5A736274EA776C
+            stream[192..255] = 73B9891D1770289A67D6338909FB6282
+                               9A425B7947FC30DC52B11E398E85B1EB
+                               537E1C02898FEBFC15A9172C254CA55A
+                               AA1B56EA856F47E37E2F252D92D94ED8
+            stream[256..319] = 6522D372F90F2DAC155D48F165B6DFA4
+                               38B63B9F436FE00CC075C585297B8F90
+                               E6062358D29641FF9C28EED4A23FC53A
+                               6B5C60C2AF1E8146DB27CCF5F43BA838
+            stream[448..511] = 642541A9733946827D79BBD815C03C17
+                               6357BD6E81E9A61FFFD4A0BF6863AC71
+                               72AEFB92C1F235641BBE1457B724A6AA
+                               AF9FAC687552A778B034C4A4F8E41ADE
+                  xor-digest = 9DDBC1E7D31379D027B4F3DFD72C3668
+                               BD0BC5A97655978E79056B3D25DF3E79
+                               5D5D8BE5D1AAE877F2E7D03225CB6609
+                               6EFE11CBCB728039A243E326437CE73B
+
+Set 2, vector#216:
+                         key = D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                               D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8D8
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DBD4E866F4E24E7F66816CAF625BD07F
+                               1F7BDFBB81428FFEE9FBE14DF5F5F3D8
+                               A044EF53A868D989E16165A0F2B95E8D
+                               83439BB4805A125AD0CA7994AE11B852
+            stream[192..255] = 7CACC4E7B9B1957ABB22ECB9D9D67184
+                               EE7A7F4B822A1C955A69E238022AA313
+                               276C2003E27AEF1B4F94B33A6428685B
+                               F048B357EAB297B7DD98E612F054A317
+            stream[256..319] = 286B484FA80A45EE4D5300DFBE173E8C
+                               978B976BE1B6CB0D15C0324D6B70D265
+                               385B615B3EA97A55D94C47F53FF40861
+                               4460857AC9568556AE54A52546B41B5A
+            stream[448..511] = B3AD999394343F6F0BDDD0B1FAE2E3A6
+                               5BE2BF56D2B78A401D5761E2F3AF8B18
+                               A2B1089864999D9B99E5BF6959F8F802
+                               975FBF204D6159CF23F3706CAF0D9BA5
+                  xor-digest = 0957D6887501D4360C430614B67D99B5
+                               32849E2F5C69CE8A9F3F707A2B5438BD
+                               0C1237B5617FB525CC9C043A10DBB265
+                               3C3F0A353E89A19838B8F68542E09526
+
+Set 2, vector#225:
+                         key = E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                               E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1E1
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = A6DF8DEE1EF7D1AF773AA3E9651B645A
+                               50CF101BF065F69F3E78BEF5D689B1D1
+                               D306FF41EB3E78BEB75C4200937CFE60
+                               E89E370680C519B2F64E23516ADF8062
+            stream[192..255] = AA30580A210B87727BE17EC52AAAD037
+                               3E0DD11FBFC89B37825CA4D6F9E8D433
+                               E3EA54C37D678B58CE834AFA310F6D4D
+                               06B4603F12DBF38595AC76511D0B13CF
+            stream[256..319] = 5F3E1A55116CB67BC91C8E37182EEEEC
+                               8FC9B09DAA6F418D3434BFBBFF6BFFFB
+                               F93F8A963F2F51CC487BE868F010EC0B
+                               EE17A480542A301E33B36F59BEE13D91
+            stream[448..511] = 672048756C221C12DA6178BE711B3371
+                               525A92BC9A219CABC5501B0DA4CC248B
+                               8742E8BCBD6F5A1CFE522F3DF3BED6B6
+                               5D60D1AC737ADC582C2CB9751521828B
+                  xor-digest = E7CA739E4DE0E74274E491CAA9BF5CAB
+                               3F418EBEB69509D69B2594E964759D15
+                               104F674CD44681AFECC3B4939CA0A0C9
+                               DD7AA5726653ED3FBFC833DDB0C87B42
+
+Set 2, vector#234:
+                         key = EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                               EAEAEAEAEAEAEAEAEAEAEAEAEAEAEAEA
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 2479A8F2872A813D16D15F060D300237
+                               25297B812F6F3B97D74D9716E4403A5A
+                               684D2BFD1E15275470FEDADF1578277E
+                               44C6C06B8A5FCE3D0CCC5E13BF49947C
+            stream[192..255] = DB2F9B25F9523FF5C2CCCB808EFE07F3
+                               132D4B0065A563288F848E05EB45E48B
+                               D15C069C02F90B4FC10AEBF1AF4BF90E
+                               2CF7F48C8CD7A8091014131EBC21FBE8
+            stream[256..319] = 84FAF79797E25BF2CFD54E58F5C7AC1C
+                               EC170B064429EB832924CDA9C47B5174
+                               9BFEF80D96FAE36DDA65659FEA1CC06B
+                               4EA3A1601A3304AA4DDBEB62381FD4DB
+            stream[448..511] = 2C8FC8D23E7DBBC37BB0811D1BC71145
+                               BFBCDBAE19F5281CD0E6AA37419778DA
+                               64DDF68726DD7F4D78BBBFF4576C2AAD
+                               93F477A2AB2C3CA8A381F30BB944C7B0
+                  xor-digest = A6D5F0DDFC0A43491D6D0A17C095C070
+                               9EC7E9B89DB8EEA11045ACC5FF003DC9
+                               CD3318BB6F9675EEF20E15490F525066
+                               AF8380C663B60EDBAE30663C94C39892
+
+Set 2, vector#243:
+                         key = F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                               F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3F3
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CC3701E703946194401D1BA23AD99B5D
+                               F3F856138E142D4B9C23DC9F252A277B
+                               D62DAA33A71A0C61079AD5A20562291A
+                               B6EC92C66D7BE6A17E27D4DDB48EFD31
+            stream[192..255] = D00665FC0A4ACC78758EF25B0B0D6903
+                               D565423614409AD11E821B83F5B35D83
+                               F26F3EF9EC1766FEA9C21C09E0AE248F
+                               4BA01E48BCE09D06471593B3466703DD
+            stream[256..319] = E8B4EEE2C8BBEDBA758C1C2D0889FDDF
+                               96CDC215EF1A62FAA29A5608C852FFA1
+                               18B473C5A7319446F3ED2E8AB39A533D
+                               714325D1B14E838C9EC6E037DB0DD93C
+            stream[448..511] = 4FF3B43841B17A279002EFB07324625B
+                               7E937D480DC73F12836195110ECB4DB5
+                               CD31CA4F92F612A95E82815328DA7D5E
+                               4DCC5BB6791603EDA64C57B5A5AAA04C
+                  xor-digest = 9202B874C48D4B1A9E857E645EE8F884
+                               D971CE97923AC024ABEFB944E34550CE
+                               31712BB832F9174F86FCD369E75CA9AD
+                               85095F43A4B7F33AB641BD6912D2C59C
+
+Set 2, vector#252:
+                         key = FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                               FCFCFCFCFCFCFCFCFCFCFCFCFCFCFCFC
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F374DA745A5CF93A567027609E5D3B1D
+                               5C3C8A4D15203705D978AD42279F6548
+                               51FF713F5120CC93D044EF717F5A75E4
+                               98DBEF559E5F157A8C819E213E93B3F4
+            stream[192..255] = B270F638AAB88DFF69D724F79B70CEC9
+                               175AEAA99D55485954B265B5CAB86509
+                               C810E664766A8E6C90D4BEE3A58B1815
+                               9076959FFFA2F30EEB12343E9E7778C5
+            stream[256..319] = B2CC84A1127B5333B30EC81CC14307FC
+                               418DA96336991A27DADA74FDA987B867
+                               B125C53C0E4E2889FDFEFBFB48797A22
+                               2836B2EA42793CE2BFFD568F6234B368
+            stream[448..511] = B70F4A10A1B75D499E8189C8B92AFB36
+                               4CD2D730DC8D7E183EC55A777C2445EB
+                               BA7E9CD95C8F3A206B73C422AC2E2C08
+                               15A8C6FED156FFF93B63DE512EF69725
+                  xor-digest = 467EDA43B849054EE747A532ED0D9AA4
+                               6EA1BF2B6AF19F481D6E3D55EBAA96FC
+                               6629FE65B5EC4B5EB6A155A6D60FEA32
+                               F04F8230E26390F1C8FA53D47B68FEAE
+
+Test vectors -- set 3
+=====================
+
+Set 3, vector#  0:
+                         key = 000102030405060708090A0B0C0D0E0F
+                               101112131415161718191A1B1C1D1E1F
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 7CB997D6E1B46DD7C0A9629B441C3771
+                               14D6C18F230291FA7EF0B039AEDCC9AA
+                               A4AE05BA13F3931E3F8373AA320A8BCF
+                               28E825B2084D0FA486BE52C92C3C6F14
+            stream[192..255] = FD4DC85E176D76062323B2F5B31E219B
+                               786596F3DC0A2AFD31AB48C5F911605D
+                               556399114B0779F43221FE5BDA899627
+                               BA6498C210D5AEC5FEC8733357571F77
+            stream[256..319] = F00E84A92BEA966DC8359FA63B12E8E4
+                               F5611F6C8CDD04CE9D605D770B2EAE49
+                               D6976272057CF275EB5B4CC434EA9B0B
+                               8CD9FEA22D7E919097CBB36C5D239BE6
+            stream[448..511] = 110560BCF38CC42478036CC228E9DBD7
+                               4C44863DAFC81B528AEA2893FDBAC7BB
+                               2F68CCDF566E1602623EC9AE283EA69C
+                               C032E90E409F368E28401AE6905BD4F8
+                  xor-digest = 9CCCCDF3F7D712D6E3931068138F9A9F
+                               8640478BEDFC3C7CD0802954234DD07F
+                               99F4B072D9847DEC2E16FAD0ACCB3609
+                               16243175C84A317191A98AFF5EFCEED2
+
+Set 3, vector#  9:
+                         key = 090A0B0C0D0E0F101112131415161718
+                               191A1B1C1D1E1F202122232425262728
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0889D6D9E155FC208941B945F2B15362
+                               3CE5C79122C1085FC172836FA9B06C0B
+                               50910CACF399EFC9CD9CC484786AAC8B
+                               377972E9A90D7EDD40A59FE1B942710A
+            stream[192..255] = A540BDE9860D8687A45D8CF22E00299A
+                               36BE590AC92E70BA03B8A5F2898C2D1A
+                               B9B1E5C87C4B10C9B6E08EB868AE3B10
+                               3BB95C30831B903A3A9620ED16B96210
+            stream[256..319] = 90E2A684D3960A4B1DA5DF19BF569288
+                               5A23892F2003AF2319FED9C8D37B8702
+                               7E61290E013FDF93683829DB99C177F0
+                               222EDD6A0FE3D5F7F903D3CC15C6C6DF
+            stream[448..511] = AFE7454BF77E3CE1050ABFC2E25F9B15
+                               011F33B93660EA4AB5E7BFC513F2D787
+                               27F8008ABC1E14B06C36F7750AE88C1D
+                               7AA2F6EB9F2E925CD6CBDEC5FBA3EEA8
+                  xor-digest = F1A8C58EA8459686DC5BFA2A81E80653
+                               EF6141903898D1A3C7298358A79D674B
+                               A971C106CAB035722F246D3E67D34543
+                               3E71DD374DAF73036EE55E6C0ECE5FA3
+
+Set 3, vector# 18:
+                         key = 12131415161718191A1B1C1D1E1F2021
+                               22232425262728292A2B2C2D2E2F3031
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = EB11D29C989FB09961A673D8412360B4
+                               F4E6DF0169A3CE207656A7C72D6FB8D0
+                               95CB3A7A6CECDC2E167CD35F62A00110
+                               EF09FD32B61A8B405A3F55A1313F0DFC
+            stream[192..255] = 8ED27EA005A3E298560C829380D4F1E9
+                               F0C7FD5285F04AE6FD66C94CC07C8C51
+                               EE8163B7414A52B0594C5F7F80104D95
+                               0858C9A52F3C156ADAA025C00B180429
+            stream[256..319] = 12DA63247282599F2C50B172CDB4F31B
+                               20952134800FB8BCE743BBA90E6485BA
+                               057A9C5E0989A8FDCEF1C88DD54E920F
+                               7028EB284306FE6A87B0FE063DAB9557
+            stream[448..511] = CD447E9F58BAFB77F6E02AB5A692120D
+                               EC4F7BD597DE5C54523A7944DBA6A3C8
+                               D00000D3E70F7D9292B7135A7F054812
+                               4B98680DEF6631D2D10E0E7B08F188BB
+                  xor-digest = 6EF765CB84937D5E829A1A1664EBD23C
+                               B474FEA3C5AB137F2D9B35BBE0816EDD
+                               B26EC14D74EFD0F9768C521A6FAAF122
+                               B5E34A36344FF0F0DB3CC2F2780D05E8
+
+Set 3, vector# 27:
+                         key = 1B1C1D1E1F202122232425262728292A
+                               2B2C2D2E2F303132333435363738393A
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = A71D4189D1338531D3C03D00A480C8B8
+                               49C779B7E113FD8D59516164C161EAE3
+                               AEBF74542FFFDC2FF8C2666FD5AAE413
+                               19072673F958F498F8FB9743BE46863B
+            stream[192..255] = B0B3803396AFF1646369B6FAE62EDBCE
+                               5254E7C8FEE88F9EEE5D8A7B6D44ADC8
+                               B89895198E3C147FAE0C9B8325EB3501
+                               6EADF77C5D7F402CF3168448D2A59E23
+            stream[256..319] = C1CCE6956C8257947C004528F568E3CA
+                               BE9ABF891E2FC2B52D9A1E6EC97A22B1
+                               FFD1C77E50A17CB47014C9EDA1853AFC
+                               11526F6268102780ACB3E0F120398AD0
+            stream[448..511] = 765857312C8994EF6BC7259673F02E38
+                               B7E0A764FB70534190033FB1BA86D5BA
+                               3BC6851DB596970A2F60831EA1A31CAA
+                               96085680CBCFADD9C5F0330CB72AB5E2
+                  xor-digest = 30EF19DE0E750BBF6AB3FC924742CDCF
+                               62B2FE5F25983BB9777C727679CAA39B
+                               1280AB468051463E7EB287AEEFA5AD0B
+                               9C9DFCA45A3124D5F41F4B0AF5849E62
+
+Set 3, vector# 36:
+                         key = 2425262728292A2B2C2D2E2F30313233
+                               3435363738393A3B3C3D3E3F40414243
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 2B9B987B7CADACD2FA50A53A9F9F44CF
+                               4ED11B3E25FE57F1372C6D570B470AFF
+                               5FCF3BEB89D0692D873EFEBD26EAF3E1
+                               1B6892913F0CB27F3CA9BA20AF7A98F8
+            stream[192..255] = 0148F54B1D24F3D69A2086D6938898F5
+                               25BDB1B1F78C5F92BA21FCE803A52591
+                               FCEC9A1AFB0FB3B081CDB1D79D254845
+                               40EB9D624B5E113A4F143716722687ED
+            stream[256..319] = 271FF1107AA8968E0ADDA5371F40224A
+                               D8E134AF80D5ACDC9803B1B3A9819BF4
+                               8ECC3A68B303E1275FA97222F7E984EF
+                               9C73899433230FD746DA6101DE37ADA2
+            stream[448..511] = A66D3BB64C35C71BBAA3F5410F388253
+                               2B32897B1CC1AD610F3AA195CDC1EB82
+                               0262E817374384BFBE200339B284ADF4
+                               BFF6960B6A41AFA9D7C9B67B19C14C37
+                  xor-digest = 3CF10A4A8BA3E0DA3C0B63F1B913B57F
+                               BE47580DF7D90B13459A9BC98B93B014
+                               1185E910EDC0A5B37206542B17CAB8CE
+                               F050A4ED3D7097B6A0738095E4BF7A77
+
+Set 3, vector# 45:
+                         key = 2D2E2F303132333435363738393A3B3C
+                               3D3E3F404142434445464748494A4B4C
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = F32665A4C73608E133D85712D2CC9A76
+                               6D2B83311B3F44564A56A97ACC9B6492
+                               B282A2E62A435A7B7799073E010C78C9
+                               4B7B5BD1B25994D1CE31B51CBB13BE90
+            stream[192..255] = C9F24592930A0A9148486D77C1FFAAA4
+                               4E4EECB088D6AD38D73B195E576BEE56
+                               E2CDA968FEB85D19BF89391813501B02
+                               EAB39A2E78B8CC7456EE60EAC3454051
+            stream[256..319] = D8E1D09F074708379189BBFEB1E24053
+                               E0BB5980FFD0371265320C3047F0ED36
+                               A65CA8D0DDF20DC25B552E1882811C77
+                               6613DBB4297DC6C89E31529DFCD17C82
+            stream[448..511] = 8012813E7879B3E99C40821A97469BF3
+                               9D2EF3B888E3118275F47F8C78A5F7CA
+                               19A98B1817D2D7734E69C5ED43773D68
+                               FA100E2C37F40FF8E018DBA52C5C239C
+                  xor-digest = 8AFB9CD876AF4F9693FF4FF511D89957
+                               C8BB31D9DE3F21B726667681F805FFF0
+                               4B50850696D6C2E5C271D199CF49F1E6
+                               D366C7824273E99360BD5A294E415F0F
+
+Set 3, vector# 54:
+                         key = 363738393A3B3C3D3E3F404142434445
+                               464748494A4B4C4D4E4F505152535455
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = C72B0F98EE5C2D44260E929C70DBF174
+                               02C03543483178C8BC129D67FE2746E2
+                               E881F8439E2A11EBB3716ADB16207BBB
+                               91454A71C444445CE64003F0BB1F481D
+            stream[192..255] = 5590F4278E78AD19293525095C2F76E3
+                               B35A3858CB5912B62304180225BDC985
+                               ED955521436DEC441B9C742B3C5F4CBE
+                               94B99689048AF93E48472980D058807F
+            stream[256..319] = FBAB34E9F432546EC8C52750DA4D2278
+                               4C1323D4E3F4E9B63E65A7E3C8B2637B
+                               AA5D0A3B897113F68C63CCB78B5AB40D
+                               0A0DC3EF1EB09DF5C4770B343B6B5155
+            stream[448..511] = 78B0144CDF2692F0D0F164ECC8621F5D
+                               A00C401007B82AAE7753712FD6185E9D
+                               7ADC8CFEA6D5BBC2F3EDB8BF2C77718B
+                               6A424BAFD30C30934FC645FF05704BB1
+                  xor-digest = 835B5361A9C1F88223DE7BCA09030CD4
+                               67065AAE99198645029CC0AB9B9BD579
+                               14332392ED7A433A64D95B44CE228860
+                               7E029235580276BCAE88F37418FB641C
+
+Set 3, vector# 63:
+                         key = 3F404142434445464748494A4B4C4D4E
+                               4F505152535455565758595A5B5C5D5E
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 804025A410EFFBA58647A9F4B443BFC6
+                               1CDDC30CA04DA8DAB3EC6A098A830D68
+                               2683B59B76C60C09938E67CB41385315
+                               E2504B024DB808923B0909EFC25F0927
+            stream[192..255] = 7A4661190129E3F349DA7B44DAAFC388
+                               5E4BEEAC9308844DDA45E8E06637246A
+                               0E6C8C7D94C5F710CB78CC6E0CA82870
+                               8CA77B6266B41E3ED6BAA2940F1977A5
+            stream[256..319] = A3EBC22126B6069C674DB604F8C22B54
+                               DA68FB4390617E86C4FF089344BD0DB3
+                               887B3438E8EF8207FD89B2A485C0B383
+                               22AEB69750AD054F843DCA7995BB58A9
+            stream[448..511] = BAC68211F125B57B8CE5E42E644997F5
+                               2FD4B8A7D5CBF89ED2F6B5F4D4C7FA5D
+                               0CC34212160C6BA536BB7604C184367F
+                               2E088528F3B3A0A1B20F9249711162B1
+                  xor-digest = F628E74D1EB94591694631F1B2F12234
+                               38B056789D5C2ABD8CF34D9FA7B8C304
+                               5A8C2298B7BEBB90C7CC86895693118B
+                               2A43B7E8AC7E534DA7965EA720F19180
+
+Set 3, vector# 72:
+                         key = 48494A4B4C4D4E4F5051525354555657
+                               58595A5B5C5D5E5F6061626364656667
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 40409D9AD4CFCEAEB8FF613D32B59180
+                               F5DFBBF44C1B7209AD1AD5AE94DBBF3A
+                               83EAB34D2617ABCC396880BD5F5D220F
+                               F434DD575E66CA74BA32862293113C5D
+            stream[192..255] = 42D9EDDAF89B93DAB4AA790BC9C45BAC
+                               5E94575E175C2EB1CC08BB39019E25C0
+                               9B0F4F435ACE371BD9235C61C56A362C
+                               B1A64EE58F4938D59073C5A8A1BA679A
+            stream[256..319] = E40477D1B6C901AFCC4A2C429845C7B9
+                               0DF890C317A5B9D6368672C58E0BD5B2
+                               7E42DA77BDC2BF47F9AD195F7C192B53
+                               24FEF88E6B3DD1669A068E3FCB58B203
+            stream[448..511] = 7616AA094DFFD4BCF94E03C9CCF95C31
+                               8F247AEBDE281334F8E6F46271070BC0
+                               1AC838D8FCFE18865DD30949C68052C8
+                               6E93815B4EA9480B2D0B6A5D9888E597
+                  xor-digest = 1FE60024F188CC243F7D8221D990ECE3
+                               29E89847C9BD60AF23061E9C27C4908F
+                               B00D8813E680F00665658CEB077BEFAB
+                               5DEB41D3547DD645DEDBB3BF5D7B651E
+
+Set 3, vector# 81:
+                         key = 5152535455565758595A5B5C5D5E5F60
+                               6162636465666768696A6B6C6D6E6F70
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 1B8DA47812BF2353C17C89AAA8695E9F
+                               F553BBA44087D262FA0C710B69765F12
+                               FFE190625F58DA899B56FA7AB5E0E674
+                               4CA2B073517B9577712D7155E16A874C
+            stream[192..255] = CD2BB4A6C3D7211773421014611B677C
+                               C0A8107544ABF4F914F825891E52DDDD
+                               76EFDBEE614573FF9674EBC154A3283B
+                               439ED8197E1EE0705955A8B6C8AFF8BD
+            stream[256..319] = A626C40CD2C48AAB016C29020096DE28
+                               F03842E785BCE9D9E385D0B13B63F82D
+                               789588FFAB07B8CC0FFC62AA86D37CAE
+                               5CF8FD43B575F9F4D6E07465B700D47B
+            stream[448..511] = 16A3C84858207E141022D228079D6067
+                               2784EBB56E3B84F7DF07EFC69060E27C
+                               D1311E51F5893AE6BFF80D34464DC60F
+                               61985F8F88164CCA69EFAE568BEB546F
+                  xor-digest = A24EEDA74185884C5B287663C3F5F031
+                               2743CCAC657C702A29E0C20BDDE304AE
+                               A54A9292B447039D50479B6CE475115B
+                               8791854540E15D642859D10561AEF26A
+
+Set 3, vector# 90:
+                         key = 5A5B5C5D5E5F60616263646566676869
+                               6A6B6C6D6E6F70717273747576777879
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3F7261A3A4691A73441762D113EB7817
+                               4C515A96C5C93C514EE559E7F78A633A
+                               01F0891910D44A7EBB18768E3B912488
+                               6069CB5304E79ACA89F62EFEC4EAC11A
+            stream[192..255] = 5F11904F72123CE29D1D883AE5CD2A89
+                               2AB26C9167A24A57D6F64BDE3A8E1A93
+                               7C5347C585226DB44B6252AEBF3CCAAF
+                               2D5E60C56FBBA6068B35AA6A61C84A44
+            stream[256..319] = CD6C5B784854E0121933E77C700D9C1D
+                               7452999F859798499A339F78FCF84615
+                               A3190A2F558CC529E636922A1B75A3A1
+                               AF280FB3F486303093DC1564EA0B6D3F
+            stream[448..511] = 61B8163A84540727204F0B18D9CAED3F
+                               B5FA87089FF4E721D2EC34D21C59B93F
+                               95297725780DF04A5FE405FEBAE80AB9
+                               B8307B9A74774E76063F9218CE243002
+                  xor-digest = 944EF8435F32FF2A67CDA5FBDFE02C81
+                               0997D9C8192633A193D6122A051B801C
+                               15555BDF410917B9E5DB86F4DE8B9874
+                               3E9F92F903543AD14087F4E13A915DE0
+
+Set 3, vector# 99:
+                         key = 636465666768696A6B6C6D6E6F707172
+                               737475767778797A7B7C7D7E7F808182
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 71BA7454CF7F6CC93C89EB22B9D608EA
+                               0FACBB4358DD007421DAC1E65EE99161
+                               C542DF02611AF497B2D53748D0129C0F
+                               5B9704C8A6017507EEFB26B6287662CB
+            stream[192..255] = 92D5D35B2E02D204E68C1AD6C018DBA6
+                               7A1C90F563AEFC3D031FD3F7D4F5E2F4
+                               C47D326A9C49A0B2ADF03D9E7E429AA3
+                               ABF253E623BFB9EB040B5F5CF1FF68DF
+            stream[256..319] = D6C22BEA96DF94CE9D5D34E6231CE4F9
+                               A2D2F6097540F9A9160DE139E2E80D0E
+                               5AFE08131FE10F0DD7367E43D314D7F2
+                               2321B5F89DC64F286576BA599A58F48C
+            stream[448..511] = 43DC3ACAE02DBF68AB5B65A81630474C
+                               639FC4DD36FBED518B6471F7C3E70FDE
+                               23CF1E128B51538DE0D5A47F20A554F2
+                               09668FE28B0C4884888FAC438960CE7F
+                  xor-digest = 7B0EF650F3847E3EB15EA1CB64EE7189
+                               AA5B04F527661C00F4603E48CBE59F7F
+                               48498D80F6C5ED956ABBF97E6910EFB8
+                               341C7BC2E81E66A4B9474BE420DFA5A6
+
+Set 3, vector#108:
+                         key = 6C6D6E6F707172737475767778797A7B
+                               7C7D7E7F808182838485868788898A8B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3C4CBA573D803324D099BE1F436F944F
+                               EE506CE77EBC01FAF0060B76FA5D2005
+                               05CE94AA15F3C4B1E0194264CF13878E
+                               FD36288EA4C2ECBEEB76828EB460AED7
+            stream[192..255] = FFA464FA648309E295314DEF7169DC60
+                               F63C90AEE9F27B534E11D25AEC454823
+                               DF6BD39C1F9CB46276C630C129536506
+                               187251D638D3867E96A84BD570F78461
+            stream[256..319] = 6BE88BD0D2257CF7EBF7100B442F68C1
+                               ACB94B6F8991C1461D318BB80E59A6EB
+                               8009DFF46B8E339A0CD4FB285ED1E433
+                               5FDBD65537D9CF1FBB0F9F10E17952D0
+            stream[448..511] = 909997D084DE4F6C910D57DB89E1EB56
+                               AB3F9974E3DB5935D59917CACCAA31CC
+                               E009324E52334BDD6CA971AF49982122
+                               B195229DF0BFE2C508E981D303061B2A
+                  xor-digest = 8B2B49D564662BFB29A9F4E1A3DC7664
+                               774D41168EA27505A2A518DD94C2A507
+                               0D28E1E69DA2F084DAB024E8EE2D022D
+                               BC73071B8559BE2FCBC2AE3605696482
+
+Set 3, vector#117:
+                         key = 75767778797A7B7C7D7E7F8081828384
+                               85868788898A8B8C8D8E8F9091929394
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 6EE8B7E51036B951205064348C222881
+                               624E9FF59DFED40AC6CDEA0945A39E72
+                               AD05FA929F7AB69BE8234567734F8F96
+                               D74DE6038A463BD8FB86224F5CEA0D45
+            stream[192..255] = DD9CD1757A95E616E99590E76620E9DF
+                               0BF811F73B70C5CE982FC9CECEFFC6BA
+                               F7DCA30517A9BDF44515262ACF297AA2
+                               2CAC3F216C12A9D0D6912578DC672D18
+            stream[256..319] = 0B7DE245062DCC9B1D8A945CD9A04938
+                               EB9BB258B4B7BCC263487B3599B1C6BE
+                               7FDE752D65345F00DF90896DF53244A5
+                               AB111134B36A99E2D2200B4D2003A520
+            stream[448..511] = 2566E8427BBAC7F0A35C6E4BCDD326C9
+                               D7164A9E1F767038A09A75B5076E05AD
+                               C51F008E9E3184FA4DC6E4764B381944
+                               BCB96B57FCE2339A01501BDEED46F8E3
+                  xor-digest = CC16803D36710AFDB1DEBC653DA7DD12
+                               F45B02349B87C3006DDCAC1635956846
+                               E4D7D6064D19012724BBF836A7DB7A3E
+                               3C12E6288F546EF316406D9C5E844BAC
+
+Set 3, vector#126:
+                         key = 7E7F808182838485868788898A8B8C8D
+                               8E8F909192939495969798999A9B9C9D
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4F4169DF51C9865A20D7E79DEFF7B121
+                               BD61F4C79AFEDD0598F55E9D9A3615AD
+                               19292095DDD83904B3683722A3337BF3
+                               4E98F63EB19927155E176F2E8D5560B3
+            stream[192..255] = CF82F8F2A46A898915B3E371BE941811
+                               682A8A0A20837AF471B5CAA4B4FB01E7
+                               F2B0CA9ED3BA70BE305587F1ED995946
+                               223032F94BB2ED7D418C95F202887E6B
+            stream[256..319] = 219C121E08F7458BD657AC4131221C78
+                               43DB5817B17344922C54A002F3F67574
+                               BEE5F7FFC7EFC5615444B51FDDEE8B71
+                               981FBFF658D2504BB53C13D0342258E4
+            stream[448..511] = 55C2A93F43F260EABBC1A173AAF80A95
+                               A7EA74CCEF6E29C52957AB2247126336
+                               CEA5BD0D08F873AAF733B3A11885F04C
+                               58542B4C8ED3E1BB7F7918C4E92926FB
+                  xor-digest = F69FE6EFBB4A6E65B517445069859EAC
+                               A9C19FCB9C1771E75266E5B4C39019DB
+                               E959AD97F2B8D7F1688FD0AC04AA7C2E
+                               602F28A63DEAA49A7BE1422B47CFBE00
+
+Set 3, vector#135:
+                         key = 8788898A8B8C8D8E8F90919293949596
+                               9798999A9B9C9D9E9FA0A1A2A3A4A5A6
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 3305344A71266B450B2CDEB049A048D2
+                               6171B39A88C25CFC0821E4F4EFE378B0
+                               702DA31652B5E1BAD9FF4C19C20BF329
+                               639D5942DD2209DB1D1474B6A7B41B76
+            stream[192..255] = BBD9714BF2C343B11DD7943DD8CDA8B4
+                               C6A913F1DBE21A0582B3FCFDE91B61A9
+                               8863AAC17D07D8F98AE8E71BA5636251
+                               49FAB3EA775D3C7735BFC732C3C42571
+            stream[256..319] = 473F161607321838FEB9359B0006068F
+                               9D88B1A073DA14E60AAF1501F3A27350
+                               53E3FCC794893257CC3C1D4E1E3CF609
+                               975E865CA46C892823C838822AF0CD2B
+            stream[448..511] = 89F37A53F18778084307D0BB71E5712D
+                               32F0F3B7C2201D01D892F6BF6068E4B5
+                               394995CE6BFACF08587ADA39CC647DAB
+                               9B12F5505055F372FDC4607F0355DBAF
+                  xor-digest = C9E7E4A4D6782C02AAC4F47AF1D142AF
+                               FAE569B755E880C6B8A5773EFC0E63D2
+                               3D7A113738CDB1A0544175861401149C
+                               753D723CC1EF515A9323DDE4B4A765C8
+
+Set 3, vector#144:
+                         key = 909192939495969798999A9B9C9D9E9F
+                               A0A1A2A3A4A5A6A7A8A9AAABACADAEAF
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B7954C45CF301CCAED3F1E7E77DCE45F
+                               2D41B3B1C1F28F0308B8AB4293B64A60
+                               AA7936DDF062613DC1C454033D2A40A5
+                               E99BD975A26185A7F419E7B337028FAC
+            stream[192..255] = 27AF957AC6C514514C24664AA0C9C23D
+                               B1EE30950177389876FE4FF2E1739912
+                               A09E20A2098751049C8925334960A324
+                               5ABB50F3D333587B67F153DB145B5F6C
+            stream[256..319] = D94FAF9FCB753E992B898178373A36D6
+                               23C6BE2420AC2EA848130073F086164C
+                               9B4E69B024991FFA8FAE94E3C2FB16F9
+                               D747320A748DE9FAE4FE9E6A7E7D5659
+            stream[448..511] = F664AFD3EDC0FAE88016C8A028E98D34
+                               A27843372C6BF8F51C7B49B94A11274A
+                               6A161D776E6C1FF05358F28426C3579E
+                               053B4137F8C4CAE07B994B80DA06DA27
+                  xor-digest = 521594487B583F5F71DA10E2316187F2
+                               2A4885A69D522F82F7FD0D5F93F69B2A
+                               060EB60965AC010BC489B401F02C26E4
+                               FE3F82B83C964B4DB4E0E6BC2CE4B865
+
+Set 3, vector#153:
+                         key = 999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8
+                               A9AAABACADAEAFB0B1B2B3B4B5B6B7B8
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = A5E320FF65811FF5E8934F3AC73B3733
+                               77D3AC52446F64646946BFB8F6DEFE3A
+                               04E859DCCD9F421D2DF541F588B9C204
+                               A9846C7AA1C017D637D7C5E244602105
+            stream[192..255] = BB16A9BDCA0D4BCA589A34F9278AE55D
+                               6A7711EC87563C9F394638041CBB0E40
+                               4CD2149218D501D3B62421CBF81C6576
+                               FA659C2878839FCD6C8DD1BA38F46E6B
+            stream[256..319] = 58B4004C53EE64CD45BC4A1F11F700AF
+                               0EA5ED86C4BBC145C8F588B7F708427C
+                               D2292D76329E4DB1F289DADA687B7784
+                               DABCCD29B8C464CE021856FD06554F76
+            stream[448..511] = 1113D37AB2964AAE6586AEE1B060F0C1
+                               02EB3AF048A59CB709792C9080183CFD
+                               2A1A47277F413F1219B5AAD7C8BC8079
+                               246BD1D6F98C11997E4ED0F68E165D9C
+                  xor-digest = 512F4852425DBF91234DA31986732CC3
+                               1F9649A1965E22E18CF38979EE6D92B0
+                               83333422A92F841C25F827782FD7BDB2
+                               8F4B40AD5EE53C37192651A86F03A17E
+
+Set 3, vector#162:
+                         key = A2A3A4A5A6A7A8A9AAABACADAEAFB0B1
+                               B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 96328CAA099502092359F397972568F8
+                               EE2FF1C4305EA06FFD8CC125CB10BE85
+                               65EA30B621437AD4CF9CE731185720F2
+                               0CFE17DD45E6361A8212EECB346D391F
+            stream[192..255] = 74F26B7A37D673DA0B78B38938C5C1EA
+                               2AC666612468F63B540EE7B17548F8BF
+                               60A9845BECCD7222620FDF7BE904FE24
+                               7D2B7EA749C9590133CD6A218F6EF624
+            stream[256..319] = 8F8AA7A4C64C3AEC5E85581C53E3FA64
+                               22CEB927E370C7B0F98F038E7ACF4D05
+                               B54430D91B0A2CDC001BFDDDCD0081AF
+                               35B67E5BEE6B8E113F36E3B23CE29F57
+            stream[448..511] = 53E20B4B90B2DDAB40DC30643AA5F539
+                               70ADB65DD0B64CECF3D3B4C0567DC818
+                               0362FE9CDF920526C59725AE861940A8
+                               A32C35382571F2FF20E7FBC504E1DF9D
+                  xor-digest = 8C7C45F50A151D551E9EC81EDFDD5B2F
+                               E676E14253FF38EBEA12395040643211
+                               3254B0B7298AF77F8F9F4203B971EBC9
+                               B9850152A96C97BD4FA7BE8592670903
+
+Set 3, vector#171:
+                         key = ABACADAEAFB0B1B2B3B4B5B6B7B8B9BA
+                               BBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CA
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E8DBC8E5D18C5BB2B152A6AE9487AF35
+                               E2044F30EE8189659043923E579C70CD
+                               4A5590968600AAB0F021F7AF283D61B4
+                               13C739DCFC22632E1F6CD553D4F21976
+            stream[192..255] = 8675941731B385016430C9A157007EBB
+                               E9BD8BBBEC44081C1F5E73C7E783AE90
+                               1A7F56A20E5DECD1E94E1C92A07CD2B9
+                               91619BC3358AB812D58E0B98EA288D03
+            stream[256..319] = 8D09462E5B1154175513CE7FAE1AAE89
+                               EA2AFDFDF1B39D69FDF60B1954BF81E1
+                               62F29468E07C251E2D174E9CE924A5F4
+                               8A470D1808C68ECE534CC08204C5A2E6
+            stream[448..511] = 60C5FD4C1831F0EFD70EFF86A5D38D96
+                               2C402453561D0021A51F07D40A7D3B8A
+                               DF455CE484E89437DFADC52A52741B80
+                               ED0EFA9AE4FC39659F8300AE9292B9CE
+                  xor-digest = 12E57044A8E7F02EBF6912BB73836FFB
+                               C4A2F47AE1B824AC97C1237B1B14DEFF
+                               12B5B87DF14A8B5B6C85C0481BD69DDB
+                               FD76FA307F4C1F7D21E60C0BCFECD3E5
+
+Set 3, vector#180:
+                         key = B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3
+                               C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 540980C2A3794C04B93696B90E48999D
+                               ED8E1D3F4720918C80C95B9AC0E911F4
+                               6593C4A920AB291D98891374EF286286
+                               2386B5FE17654278EC413AAFF1C384DC
+            stream[192..255] = F3E036D7620669F851A1B58BCE57B079
+                               F5D75829EDA4E68C36F086CBF2E5DD78
+                               F7F30C1AD9E4CB3C01B7F2FBF53A8AFE
+                               957786B2D3E9CCFE7D6FB24397803BC0
+            stream[256..319] = 1AADB95F07E6268BD82ECF3453DB5014
+                               9745CCEEA9F1887B5F257594ABBFFF43
+                               C3187BD9A9FFBCCACEBD7A21FF90D18B
+                               57FCBAA64B8FECB56D5A7FE05BF03E3E
+            stream[448..511] = 4170D41CAC2A7AA5A3C9228BF386B9C5
+                               57795DB5D1AE547A31C553F55DE02E6E
+                               B69D76A984F4F1D84F29D5CB98190C01
+                               441DEEFABDBFE405F22FFDE734D9497A
+                  xor-digest = CE103B99AA95B51D2D6CC54A15833E34
+                               A11778F5E05BB7AB61505D473228069F
+                               CB40015BCFDD3E1D0D5E1F832791C8DD
+                               3184273D1B4C67D800EF5FF004660440
+
+Set 3, vector#189:
+                         key = BDBEBFC0C1C2C3C4C5C6C7C8C9CACBCC
+                               CDCECFD0D1D2D3D4D5D6D7D8D9DADBDC
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = CA30678AC97B4591E287FF8B5E28A838
+                               611D654A4EC592328039E3A1DFE90FAB
+                               BA5A37133E821E0960520EEC850B6962
+                               B0378E77770681ACC0929D16DD260925
+            stream[192..255] = 79FD1893EBF30CC2CA9C5AE92B0C063D
+                               894EAE4BD50BF462420081D1CAC57A5B
+                               AA92E73D3B3CEA147E1F7127AE1F6FA8
+                               E9B302A068F26157C904E0AA7B7A072F
+            stream[256..319] = 6880FCE56677345CF1CFB2D38F890C15
+                               FE33D377922AE43348F5590B84426EC9
+                               0DC2A3863136790EBB7BD9493D2F0808
+                               CA9287CF95AAF366A11D6E7A556FDB02
+            stream[448..511] = F385299A7038DA8A90058C510727F3E4
+                               524A2D95D217A1C199552753F253D45D
+                               81DA40431910DD54B619A15C5C302411
+                               613D28D53493AD836251F0047FB911DC
+                  xor-digest = F3D10E261AC596959B4AACBCF335D043
+                               FFF65E2651F046D300C19510E1677F1D
+                               45F287DFB8C17055A012C234B6EB04C5
+                               76ED2EDE12DFFE6EBA4A39A64DDC573A
+
+Set 3, vector#198:
+                         key = C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5
+                               D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = D5EC301FD496586D54D9B21FA23DECB2
+                               B25DCC0784BF77DE84898AF96023647B
+                               F1618234A239F63FBF3478FD6EB79299
+                               66BA9B670C64118444C95D31405873C9
+            stream[192..255] = D455D37F435FD0FDD6E1EDF8BAC28D2E
+                               DAF587F938C49A5F58C32CE8D5B8A4EB
+                               884B016E54277300D461FA21512E7695
+                               D2D7489A4560FC7A72A510219DF1C5C4
+            stream[256..319] = A7B93D8B7787B6C8F80EDCE72D4D644F
+                               0C6400C3AD0443FDD19C3F3675083F4C
+                               E5ED87032B1813DDFF758854C8D889A4
+                               6FDC61C210058DB72D838A0913D80611
+            stream[448..511] = 94232F4284F46DD2E7933F9635C26C48
+                               6CB935031095777F59BDAECC4FDB4109
+                               9037C38C91620586DE93B66EC7376502
+                               6853B7390CA516B694583447DD863310
+                  xor-digest = 8596C088FA66361FD90A2132CE33FD52
+                               34910610DB006D223B0574F21BF1CD4E
+                               C282C67B24AF6DB0DB70BAFF65D5D8D2
+                               1C3955D466EA2B49C5E8EB7E07475919
+
+Set 3, vector#207:
+                         key = CFD0D1D2D3D4D5D6D7D8D9DADBDCDDDE
+                               DFE0E1E2E3E4E5E6E7E8E9EAEBECEDEE
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = DBA2DF9ACC53C3EDBB566C28F689D7AA
+                               EF631CB44EA91610A94685FBD862C9D9
+                               BFCF512BCECF36E035E2E577F6BF6EF9
+                               E4B0E7623E0DB23B10055677C7B9F857
+            stream[192..255] = 8C78C9714577E497E3CDFE3ADE19F03F
+                               D2DAA3211C1E9E5D9F21FD1ED696354A
+                               B7552BFC7FC675FAFE7A739F6E60A839
+                               547F8F15BA5EC6F75BB05606BBF209CC
+            stream[256..319] = B23F187B1BFB5A728BDBD78B75C3265B
+                               B04C6B350A4DA4EB021D6191263F052B
+                               CAE73E5776002FF05DEC3D341AA20D2C
+                               FA523E6B92329A979BE06CF4F848A1B5
+            stream[448..511] = 7E2ADEA91939388D36B3F97DC87C2A86
+                               BDE7BB4884C40D8A202964ECC7440987
+                               1C64B03EAD0F46A3A1CD2CB935DCCD67
+                               0B43292D5B852B7A1B3D1F853EF22EC7
+                  xor-digest = 1AC1E42C2DF9858537D0A1BE3B2AC094
+                               54136E53AE56B006395969C7F999B2E2
+                               DE1DAE62740FF339DFC8769F67AEF352
+                               C4726B4AD4BAAEE56AB8C55FACE34860
+
+Set 3, vector#216:
+                         key = D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7
+                               E8E9EAEBECEDEEEFF0F1F2F3F4F5F6F7
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = BB00F8ECA9A10D2B137257E86B455DBD
+                               F9A6A861F19533E38C3C9F54195AB803
+                               171D35043FC9C4204AFC9A8E72EDA4CD
+                               60220B2EDDEBD5482D7833979C15B685
+            stream[192..255] = 6CCE94C2BEBFD223AFB7AF1110F0F6C4
+                               01AFC533BABD84F8C4A54E8A239A194B
+                               B56E0CAFDCC59B9B5103471DCEB9F706
+                               7801D79530B7CF40F2DEC73A169C7481
+            stream[256..319] = 5144745E042B76A6B62E78C92FFC1C0E
+                               E59979CE4B2E4B2CAFFDFCC5E75510A9
+                               201E8A97A6A1729E35CA81D8645FC118
+                               177DA5FACA0293B972AC0957C43BB1FD
+            stream[448..511] = DCF9B6116FA5EB9CFDBFC8C97EFD89B5
+                               268C0D529141FC3C8262B8BE38E94973
+                               A21919D498FCC3896B0FB4CEB24D9E2A
+                               F728003C36838638888FFF1D0D526B37
+                  xor-digest = 99EF8A7D0B8D08E976EFBAE56F7CAA91
+                               B1FFC7428EA56B7A697AA3B621AA8DBD
+                               52681C7A9A415049AFB6B7D8AABAD024
+                               0F9C3112092816F4C69D36B1300ED3E6
+
+Set 3, vector#225:
+                         key = E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF0
+                               F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF00
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = E3DAA6E498609DDC5A31BC0B6ACC880B
+                               695097D2CE2D1FD162C7802DC0D00BE3
+                               C0126CF947CEDBA7833421D70A914BD6
+                               C33B0A77BE8BA10879D664F054C29302
+            stream[192..255] = 0015EFCCDC554D042531FD570C6B26D9
+                               059F4F4DA675BCD12C038E4A8D16737B
+                               AAB0D7992340F4EE4324959E96930934
+                               21234D41F56A995C928F82944B46BB19
+            stream[256..319] = 8CE7098F4C64DF2E8A170DA3D02CD99E
+                               0169B99A261D1072FA116ED39244EDBE
+                               73EB9F1CDCF8CCDAA9E94C0DA9C6EDC5
+                               426751AB8300836435BC6F727F793281
+            stream[448..511] = ADF85AF30894BD0207DB4BF72D9DBAC9
+                               144EF6B24E515D96475897EADE40A92C
+                               79B818499B8CC328859561D79D727423
+                               BA81055F3387608E56173AA27D286924
+                  xor-digest = F47ABED85910334919B5868D4531FC15
+                               24D61CB16C23920750C73E2B08A4B5C8
+                               C621482F6D9F01EB59763C5F89AC1514
+                               F6CA4C40216D6385F304E9514B014C02
+
+Set 3, vector#234:
+                         key = EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9
+                               FAFBFCFDFEFF00010203040506070809
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4728A29A2F2BD276FDE176CF4A38BE65
+                               B84BDD41F065DAFEA8302334CEF92A5A
+                               306EF904DADFE92E3E975EF9EEC9B3C8
+                               4AFC167545A0CFCCB6B1CA688967D8EE
+            stream[192..255] = 734153A78089B6E6EC0F520D39BC3FAA
+                               E1DBAD30CBDA32395E51E500CE4E118E
+                               23BC8CFDB08D443F1932EDEC52CDF3E2
+                               1D021DB791A56A7C16FDA02912FE744C
+            stream[256..319] = C511914A4BD9B29488B7FB1E62DBF905
+                               01C0D85C5A238448065C188F0A4134CF
+                               6A1FE1DAE57DB8BDF89FBF7FA66F3E32
+                               14CC9658DB292E4562A1761B9EA77570
+            stream[448..511] = 946944DF8E41BD585723CA1C03909E01
+                               783617D9D1129220ADAE7E5487AF4B54
+                               FF6593B37BB77AB0025C28727AE5933E
+                               E3873824E46F2209D26936FC5566B21C
+                  xor-digest = 34E04FBDE6E3DF6EE14BD179226D51B0
+                               1513510665589CB794C0C08391FA5929
+                               37B390E86BB4A72D427F58A1EFE10F6F
+                               D8A14A6F38ADE34331C8AC6AECA5DAB3
+
+Set 3, vector#243:
+                         key = F3F4F5F6F7F8F9FAFBFCFDFEFF000102
+                               030405060708090A0B0C0D0E0F101112
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 2AC7F22D838F68107877E90869F98797
+                               493171C8A5EC2E51D536A1578659DC16
+                               BB2F644C290B0F006BFE3FA0FE0CE917
+                               D32E94643848867B230270F54D0037B5
+            stream[192..255] = D21F7FE6E368989CC75E8D9080579385
+                               E31680302BA8B9B2F56984FD49B01F4A
+                               DD36AE4A28EBE23B5567BF5A539E2621
+                               1AA8588507916CCB572611C352E73E42
+            stream[256..319] = 25823586A7212D44811C75023193864D
+                               85DFA17EB7D5A34BD1CDD3260B5D53A5
+                               56EE2E2A06F84E95CC7323379FB924E9
+                               9E1A3F724F8C480A1F40B2C4A6FCD433
+            stream[448..511] = C1DA25F3B4FBF8B2917103E6274FAE81
+                               A5BF4086A161A7786BBD5A33662E48AD
+                               6EB9A944CCA57C51AE266BAF756EA506
+                               AE077AF0AD8B577A5A02F5563FEBA2DF
+                  xor-digest = 6176BC64072356BDF719676CD2ACF288
+                               CE2DC1272ED9C4685A5CBB7327669724
+                               DC8BB64BEBA04564A7879F7B9AD5A936
+                               C4BC1AA4007A0F85A5B5B945B418BC61
+
+Set 3, vector#252:
+                         key = FCFDFEFF000102030405060708090A0B
+                               0C0D0E0F101112131415161718191A1B
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0854D9B674256934E204484C6D59668E
+                               1C94891FEAF6E08A92038E41EBA38292
+                               D19FDBF852400123237BD7DA620767D3
+                               43C2FAAEB08A394EFD1E7C1A3776B1A7
+            stream[192..255] = 4BBDDBE675E0F9D7DE0BC1B0E0C64FE4
+                               52F95ADE61D5CF2EB805894B3CC3285E
+                               6C6AAB72DAFF826D945B05FC4D4A6BF9
+                               37B352262AC12B7E6F92D5FBC4ABDA05
+            stream[256..319] = 7BD11CF4273EA16E01154EF9615B88D9
+                               C52535D2F0C7FD394D94AA7EE542B448
+                               9A046F2625011EE75F874641D1C5A709
+                               B7FD1DDDCCB2A6F1A47B65361A9B0D6F
+            stream[448..511] = 0AB902B571D11B5F2F24CDC7616143F8
+                               45E7DF2050B263D7A841DA170E17C00B
+                               4A20221D7ACCDCB0E131108D94D903FD
+                               7E2F7988445A7DB54F653186D69F3CCC
+                  xor-digest = 1266CF54E8BFFC95F1CD3C532BD8EAE3
+                               BF000577A811DA58A41AAD9164CCDEFC
+                               401C1B6BD2BDD9E992707718A9802B55
+                               33D7A8F490DF116FBCD8C85E9B580487
+
+Test vectors -- set 4
+=====================
+
+Set 4, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                               3083D6297CCF2275C81B6EC11467BA0D
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 1C43EFA7A2CA90F5E8F9A4F09D4C9077
+                               D5ABD79341FD75BB2DF9F13CA0B1CD6E
+                               065FA86938D971D8FAC8A3C34D08CA2D
+                               1BA08BE56D633951BD0338A227321CAF
+        stream[65472..65535] = 428908B703282E38E1BFDE62C6B0D8A1
+                               BD2AB1F5117C85703E9B656FDEAD2660
+                               4B7B8EAAE16423A3BFE542AB13748DC8
+                               35D81F981CD344015E0DF47BD180541A
+        stream[65536..65599] = 9D6D72F46C846D9BBF3AEEB463B9EF42
+                               F84915D664A20FB78AD94B61FEB7D63E
+                               5411A81D1E8F32BE3044E109C68B9EB5
+                               EC0BF180EF18BF3191D933F86045036B
+      stream[131008..131071] = E462CD92492726928381769FF205DC17
+                               AE7D31E1B82810F3CCB541B58C5F58D1
+                               38DB708C5F5BF07A0432868A1AA40A07
+                               601FCD1A07DE3071E8CE082833F0B02D
+                  xor-digest = CDCA2F92BF75499E49B586BDA7D9306C
+                               12F111D1A9F183A83B5A07549D5F976E
+                               815F96BD716CCAC7178282CA8BEFF4F5
+                               85DAFA9BDDDF8E6420DFDBA2573F0494
+
+Set 4, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                               3588DB2E81D4277ACD2073C6196CBF12
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4F7D4E56036A57A303A9C7D978290216
+                               297AC26C187E4F07678EC0069C34F93E
+                               072D734DBA239D81E566D1E6DCD09B5C
+                               A132714291631C227E391EC0385A3A64
+        stream[65472..65535] = C508DDD76C070F712FABA944BCB0F5CE
+                               EB645825C520197867623ED5263E22B5
+                               6270F0A878AC7FE03145DD2BF528E1AD
+                               784086FEFAA0D82F0F3571CEEDD3341B
+        stream[65536..65599] = B10CF49FE9266BBCA007C8DB526E760E
+                               79AA4D6A3B29FE82B8698C732FBB81AD
+                               1A27B2AEB06D05F3CF17E875BC0BBAC5
+                               67762275EE650D03F62B29529F3C3E23
+      stream[131008..131071] = 42B4F20EBAFB2C792006BD163064EC7C
+                               F363DD996CDF839CCE61E739C3817B4E
+                               36D311A4C94C7918E82F5158D3A75844
+                               A5603742E33D7FC3AF018660E6B1185C
+                  xor-digest = FB3EDA7C75E0AACEDD95B625F7EEDA62
+                               3DDC94983A9B084645253C0BC72FBF9A
+                               67072228194F96C1E81004CB438D6381
+                               A5C7E9E7D134FB8B67DEF27462AD3335
+
+Set 4, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                               3A8DE03386D92C7FD22578CB1E71C417
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 23DE914D641DC0DCB4F818C687803858
+                               A6673E284F8323787756DAC9352BE031
+                               28BC6149A59785F6AADF92FC68761E8A
+                               862AEDF29E851BF5422A83EE5EABFEE3
+        stream[65472..65535] = D12E0C470A955DDAA7E851F43DA35B08
+                               15D442DBBEDEECE3ADE18FABF08B4443
+                               77ACFE9F138F8725CEA27B0F0ECCB4E2
+                               E5D6E476F88CAB4743E8E43CE2D48F4B
+        stream[65536..65599] = 26635796620003DE67406BF741B93D68
+                               318F9A23FE823B2374E8BD8008EDD7BE
+                               2F750707A3835BBA7DAC45E06537DF8E
+                               53DFCDB928EA34CC08D2841FE3E492C3
+      stream[131008..131071] = D3DFCE281FDC69F7800E765CB0B33D78
+                               8BBDC17DFD11F929295C26AB7ECF21B6
+                               7D4B4EFCC18ECDB8134175A7F198EB12
+                               F7913DAF22D73A4139D5B807C18310A9
+                  xor-digest = BB2C8E7BB894DEFD1D5A7D37C01E8EE5
+                               FD4E052CDF1DDF5FDA90C9818DE71B3E
+                               34392EC3858ADF718F463808ABF841B6
+                               90F49D35A51BE5067B162E72D0101F97
+
+Set 4, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                               3F92E5388BDE3184D72A7DD02376C91C
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 818C35D2FD72D12115F91BFD32F843E7
+                               ED4D7110D1ADF517226BE797E037AF93
+                               C190025A5E82FA0341667D68FC09E238
+                               49D5A7A9526CA142D60F71C3AEE3A106
+        stream[65472..65535] = F011E9CEE99D94BDD4484408A0FF91DE
+                               EFDC8D8C04ED2B86C51F21058E912C11
+                               F19890E174018308962F5827D2FC1E2B
+                               82BA65688C111AAB5C749D8ABAEC022C
+        stream[65536..65599] = EC2EF21014AACB6215083F784E3ED65D
+                               774124FE60188930E1A90405EAFC8F1C
+                               E75D54AA7D81400E026D799CE06EF532
+                               8002BCF5A10D43E6FB6F80A9D72634E1
+      stream[131008..131071] = 80BC6F7F6B0A7A357F770E7690D94A9D
+                               B8CBA32EA36E124FDCC66ECE8786F95C
+                               22263F09645864087FF4AF97944A226A
+                               CB63DAD316F8CFEF96504AD306C512BE
+                  xor-digest = CB8D4C35D79CCF1D741B9DA09EDA305F
+                               5FA43F9AE9D0E1F576D5C59AFB8471F9
+                               7822C6ACAA197FF01347E397C0382195
+                               865AFAF5F1690B373AA2603C39A13CC0
+
+Test vectors -- set 5
+=====================
+
+Set 5, vector#  0:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 80000000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 635990D909A80CE2A75E521ABF588B6E
+                               85320D2C722D1C93B42AFBE6358D6E2B
+                               F2BE933BC961FB50F9A2B55389A08CD7
+                               A0131F89CF0E61D0C7071DEA6D8DD4C2
+            stream[192..255] = 0F92D4DCC222BFC7020CA6BC3D044F69
+                               12D9A93668C65401C570A01D6BF6B3BC
+                               A6F00F6FF46AAE3C09C6158EF05A520D
+                               F8D55FF27CDB7AEB5D03C1FFCE7B95ED
+            stream[256..319] = 664CCED71B27680F9458952173BE0043
+                               D3C27F35F9CEE7AE9D783ABA671C4FC6
+                               8F2815DC904316BEB39020F646041276
+                               5BE5500A60DE2209961755C1BF96E1E2
+            stream[448..511] = 8F02C1FB389DD1C5F0CB730ADA528D37
+                               DD778C4782C7B5DF1961F97CC82B63E2
+                               9CF4BE512EE27B50781E297D1633D700
+                               1298F13FD8AF9D1EA83F831A70EE50EA
+                  xor-digest = 3F9A4D249220E1AC8E559399FCA23DD1
+                               1A250DCDA841502F5FEF0F5D4EFE7E46
+                               D9B1E5E4312903E290D695C2B681949F
+                               480D45F78FD69597570338049464FECA
+
+Set 5, vector#  9:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00400000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 8E932D78DCDE35F1E5B8B2E863859A64
+                               7AEE8B0867F6F221B09C37B7A78B4043
+                               D055164B1FF1608EC17F3F148FEBBFF5
+                               A9FCE4158B33D2CAA4AC5FE5551C788A
+            stream[192..255] = 7034BE31CED03DEFAB3F69A24E622BDD
+                               9B202ADAF05D0324EE933064ED6D965B
+                               937FBC8405F0D7236AC28C320CE66C06
+                               C5B93EC581FDD59ED40102C651495EBD
+            stream[256..319] = 37C4EB0E72191FF0F70C8A70F475061E
+                               A0BEDD8A9AF1901FC6BB5482B5A29469
+                               06E8C40249E02784896D5D42387127DA
+                               CDF1657A66E0D43E6F69632519D1D3A1
+            stream[448..511] = 8CBE98126AE27A51146FE05F40CEA89A
+                               39781F515D621DD48B6D6234F9AFAFF3
+                               6FB862084F5249BCC0018E8FBC090121
+                               E227FF494BC180FF68EA2B134E7B00D6
+                  xor-digest = 24556A29026E3CAE101E7112B2FE5BCD
+                               3D925460B66A9EADDC271E39C317DC27
+                               51DC9254491F76F9163AF09AA5372F34
+                               1B76D54C09DEC9419F839E5C50F1957C
+
+Set 5, vector# 18:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00002000000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = AC05D72564EDC8EB439A95579D04BF65
+                               592AB1024152B9B14D71B18FEB5374A4
+                               C07AA2F58EB2E45F737580241CFB9C0B
+                               842F8CC9230B540FC50A590DEBDC29D8
+            stream[192..255] = 48AB7E018380336AD0CFF37379D9E370
+                               5B0C938600C6713FF4CF5C142F640FF9
+                               72CF147E7C38389DF426FBF560E7DEF8
+                               41B4B1CFE6A4E2DB4A85505C931FFFBF
+            stream[256..319] = E9C6536F67F4B3053B353170CC5B77B3
+                               06A47B759A5FEE5BE45842C01E11519E
+                               5746B056C86D8A6712446949DFFE6935
+                               8E4512E7BBD6E6F544CACA98BDC723E9
+            stream[448..511] = 731EF8977E1307CB5FE80BD4F89025A5
+                               AFEE3E54F7CCEE6556A211097498827F
+                               6219704F96652420BB9EE830DB3DD940
+                               96987BAEC5A43526FCBCD85C9BFDB209
+                  xor-digest = A37E582543E75640DD988C7FB5579D43
+                               9C41669EBCCA5580184743BD54D24CBE
+                               E32F2B1433CDBE51E8208C78FD739CC5
+                               4E2A37E16A7AE4F2193ABC4F04C35D23
+
+Set 5, vector# 27:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000010000000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 0B295517E5A2E100C262736DAE920F2D
+                               26C40787AFEA87FC34C27D6E0BF98A62
+                               53B695751F9095C8766184EA44042F2D
+                               6DE099A80C75DB1F33F53EFE578A8F0B
+            stream[192..255] = B54C4F2EDF17A1EC22F536586A5BD691
+                               2008DA6642C84AFC8ACD35A7DAE73F79
+                               C835D83F4C0C3B1E510D1BB42013A872
+                               8E4899A8CE134625698CAB31852AA7D2
+            stream[256..319] = BBE2221921E73DC79E795AC0AF9B890F
+                               FE88A14DA29DE45FA38F4C3E94E6BE9D
+                               98238BFB181FE664B4147CDDC125FD06
+                               D11A65F1975A0D781024DE1EF026DFE7
+            stream[448..511] = 83E61FCEEB1367635632B45BC73B8B39
+                               165015E7A6B8D9851390D4CA9DCCB935
+                               F09BDF52883FF37BC77DE94842E39BBE
+                               0BE530FC9D3B4564E11B7EBAC8083818
+                  xor-digest = 55242D44DFDB1A747071F1C825DB5620
+                               EDE1AF37B6D73A22264B14F7D35E4412
+                               4A6242C5AD34B54E98738D6CC90FE355
+                               BB9402DD017B6678FCC0EF27CF5D67C2
+
+Set 5, vector# 36:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000080000000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = B89065FE0B458C64FD6EDC6A893C8C81
+                               83578E7D37BE97E6FF82E45110A25960
+                               49A817CDE859B67B56CB80768D6DD275
+                               6EC368FBABC35C8B51C62AC92F913281
+            stream[192..255] = 0E0AB045409ADA1A9540504550404B8B
+                               2C38384E577F2DCAD5316CE7E806A0F1
+                               21D2A3298F71F301340F3C0A9CDD4815
+                               936F16B4EC229E63451980646D45E3AB
+            stream[256..319] = 1DC37BCE039878BA2E5938E4563D2523
+                               7350E41C8EF9262A9EF7D7FED7E22F45
+                               DC3E98EC981D2BCCC1185857C627EE20
+                               C86DFEF500756B241320798764C3C09A
+            stream[448..511] = 9A0082CDB35BB3CB1C74CE337D944D3B
+                               2C833B4F786A92DEA4445A2E5E101384
+                               AEA834F5E01C1B37EF8291D039875A3E
+                               21D613FC71212DE686AE52295B773E42
+                  xor-digest = F94584BB343C6BD6BE3AA1EF799989CD
+                               93F6DDB6A9AC7E2EDFC92460F0905E6E
+                               AA3E81F6E173C7F9FCE8FB5D7B261A58
+                               3FF006AD017A09FBA3B3D084285169A6
+
+Set 5, vector# 45:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000400000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 486343B348F2A1726617D6E93989B000
+                               B41FC9707E2A99C7FE5CE9423DC3004B
+                               67EB02F45B368F87FF2C4CC0C59D1728
+                               9F713E714E049CFD8E5D593255092A7B
+            stream[192..255] = A1A3127E632EF47679F52224E6D5A16A
+                               6E0598271F36F4DAA98B115535E77C71
+                               84170D2DB4B8C5D804790A666D105108
+                               81213A0684DD4AF03DE7707702F4F73A
+            stream[256..319] = C917B1577463E05F34350C4C7F6CBB5B
+                               D63B2D74EAF1500832132CA1A1F289C4
+                               3D93BFDC5E9D91897D2F7E05740F3C95
+                               0AD872A93DAF3850A452410FBD706A92
+            stream[448..511] = 11646E84240BB95D1B14694785E7E119
+                               848855E462DD14176442B8595CF602C2
+                               D1F4A2E09B8D7DE28382D1DA4DB3B1E5
+                               910DAE6ACC02E79FEB07A8E55747046B
+                  xor-digest = 65E9982A725056B8FBC275052EA48C00
+                               69A1BA0939831C4014E81AAF14F66FB0
+                               E01FC0C70A49C4533ACBF304A5309F4B
+                               60D6B310BC66C6684BD5B9C83F994E95
+
+Set 5, vector# 54:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000002000000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = ACAB34102EDDB67B8A5D8B135BAC15CB
+                               1CD52AE386364C709C2B9D6BD322D7B8
+                               477577B4958D448A3BEBA473D861E592
+                               CA15371AEA0F500361CBDD865488A7A5
+            stream[192..255] = F25DAF77D7D734E5486A1AAE01794FB3
+                               C17099E01489A5B4213EFAE6D745B798
+                               77939C7A178D1FF09EB2C42A8A3CE51D
+                               59D501B36BF9E4960BF3FC8D50F5A847
+            stream[256..319] = 1C9C6F63998627AE1AA7E8F0B2D73A99
+                               707256CDB12E3AB239EFA72AEC516FBD
+                               6DECC9375EAAC634707A139E59B32B51
+                               5D25ED6951FF4228A11DC87E8DE61385
+            stream[448..511] = 6A997977A25F4E9E0D9AFD8C20B56EE1
+                               C702C301528E332BF8F5E7DBEEE5CC28
+                               C9E12E1A8BD7A2118A0F31F800B574A8
+                               2FC44FE19B20F1D3396432DBB02DACC1
+                  xor-digest = 0B2BA364EE76F0549A10200D129196B8
+                               E2B69667999FADFAD55CA479AE679C56
+                               54A453C43898443B9DF2835AE806C2A5
+                               EF30CB8AC25DBA756A705F66759029FA
+
+Set 5, vector# 63:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000010000000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4DD010482D0DB2D09D76872D25F73B26
+                               749FFE70B9674587FC4CEDBA5966D217
+                               489244D0177F676188A1762C430DD8F1
+                               5ED9F7BB67F2E8A79F7633DB7B45CFF3
+            stream[192..255] = 3587F0A7B9F410D45357626BE10B4EAB
+                               FF8798FECA5F91F3AD2543B301B5C301
+                               F84404071C7BC77AC31E423E1AB1E2AC
+                               2CFAA37DBC2A1316D16A5C7BFED1A77B
+            stream[256..319] = BFC632891511228ADBA0211EF390A7F8
+                               08A12AC6BDD7C2E29DF27025EBA1A6EE
+                               00B9718FF2BC003904C1C28878894AE0
+                               E5CE5E9F55CAA522EBEF5747C755CB73
+            stream[448..511] = 513D9FFA86D8AFC20E4870DE0E9B330D
+                               76F02E44A6C4D7C5270B89C6BAC9426B
+                               5A12666244C0CC5A641118B93F72668A
+                               B7C53CD7FAB0940F1B37A85015DC91BE
+                  xor-digest = CACA8BD50E28720128B57B37D45DFB02
+                               206D53785FCE81205AEA085466142DB4
+                               A17F841156916294F3B7CA93CD99CB12
+                               93FF593B5105D2822CA9BC3BAF178935
+
+Set 5, vector# 72:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000080000000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 4DB6CB1D5BA89BA45BA8E3DFCEFC444B
+                               7D97C73F53EBC50BC46047CD76499CF1
+                               FAB51AA6C8B24118AC4EC8E49192B41A
+                               2812AA1A4325418AA6C69F6143F0A6B9
+            stream[192..255] = 33FB647044F3918513212D3538C31662
+                               1DD9F3A10C0589CB718564CED7ECC391
+                               D9701C7A23AD48E05A79BE9E32F60819
+                               3E57FA8D8EDDF9F43F38BF8BBCBAF52D
+            stream[256..319] = 79F3525A6EE300764DE481C20A40135E
+                               94362F56DBF4C5AFD214F9D4039A0899
+                               F74A7D7C27494B39D1B0145B9F691B5F
+                               F436F2AE8B335EC62CCB0FF506E0240D
+            stream[448..511] = FFE0E6B8D741377FF1A02764FEE3D681
+                               6CD020C6DDA5097989137E9BCFFFD35E
+                               0E6379AD2ED3D9D298C6B98DEA82DE6C
+                               2B66529C860DD4ED56265CA09B16A8A3
+                  xor-digest = BEC66A4FEB220D732F04AE0B98FCDE2C
+                               0B70613BAD57D7590E007E84AC546B09
+                               AF1D5BEB509CFE5523254B5FC8CC2672
+                               215C67477AFF14D0788DB166C5B4B12B
+
+Set 5, vector# 81:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000400000000000
+                               00000000000000000000000000000000
+               stream[0..63] = ED4C49EAEBE78999C0DBC4674757D435
+                               B056A45036DC51B390A6C87B3CE8BCE8
+                               2C7DD348C7775D2402EBE359E7895FEB
+                               B9F44DB5D0F7B40AC207A3CA750EF25A
+            stream[192..255] = 32F897ACB5CE63D1A64781524B1CB4FF
+                               9E595EEF93A3206A0D1B4E6F4ED7501D
+                               2DDFCA31B4FC1A33F589167B070FC003
+                               F67C528B6AB99ED308EC3CEF82B4E2F0
+            stream[256..319] = 57CE29261DAB385309C97955261874B7
+                               676349DEDF7582B7654D1A8DAA570EA5
+                               9745D2167F2AE1ED538F1D0ECE53AA38
+                               379F9AE542EBE229D561E34ACB28FA14
+            stream[448..511] = 667E22A8BE7BB84CA1B1C0848E5F22D7
+                               E98E54A79D5A960C33D07357199AF1AD
+                               53F3F803EA698127C22F75F31C40656F
+                               8C28818775B3D88460CFD29798187537
+                  xor-digest = C68E7F4A7CDB68892794933392C1BA84
+                               5B6B7CF52B8421137EE0220BA67C91E9
+                               81B47F9BFC39FDFF9DD48F3617F2D523
+                               0680B87D18A821A09525FDB79DE6FED2
+
+Set 5, vector# 90:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000002000000000
+                               00000000000000000000000000000000
+               stream[0..63] = 80FC6D794178A189EC423AF926622982
+                               60C44DC5DD5AC91F779D02958366CFE2
+                               C5551DE2A5D635353757AFDDE68DF592
+                               A034D87C871D7D871264BB0F89E99536
+            stream[192..255] = 0BEF31DBC3F3DBCC5B3D28BE296384D5
+                               D33DD0AD9A80D4AB8F58274B4397A658
+                               94F67376AD8DCEC19BC2C74A835D9F70
+                               1F4C60DC256DBA4E83B21D36B66F5DC8
+            stream[256..319] = 625DDFD8D922D848380D45D6D7E730BB
+                               049666B3900E4305218BB7089D059FD5
+                               825F9EAA3AC047A006F1353C37AFD11E
+                               0143DD68CBE9543B959E26ECB4C649A1
+            stream[448..511] = 636E6EB97E3127EB703D5170D2C8FAF8
+                               63E8C333F5EFEFCF9063E3D770FF9E0F
+                               2B37396CEC935239797FE430DA4CFFB2
+                               9B19D833687318DF01750DD2F3D942B5
+                  xor-digest = 0865679CB53BC2845A0B71AB820F61AA
+                               9B99E100AC7F0358D5B610C09EC52C7F
+                               8C7C5D973CB85B18F8990F3BDBFBDCBD
+                               13071BB3AB3F329E75A44E80320BF86E
+
+Set 5, vector# 99:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000010000000
+                               00000000000000000000000000000000
+               stream[0..63] = FC2DEE44B15BD914C17DADE6645A0250
+                               2F40B39C0C6AA26C0250D328112AC67A
+                               0C55D48700EFE67EFBCED927B62427C1
+                               41DB8089774E2DE23C5FDDFD66D39BC3
+            stream[192..255] = B6A4D34FC81937580BFC32E04C8E2B20
+                               309AF3E2152B98BD748A344D4537788D
+                               35B16DD2C01444CAAAB8684916705C88
+                               FE75C53D75713FFFFA2693E91395F919
+            stream[256..319] = 9E619BB0045C58C2D303F79E659CF5E2
+                               011D619E0CB10CFDD53AEE6812DD780E
+                               36407CFE9BFC1C73C27CBBD491BB6A7E
+                               8918023EFD6E2227C0C840F1DFA5924A
+            stream[448..511] = 2A320747019AE86A59D5422B634448E0
+                               B43C41457428AC7A4E5D0C9D7327B44B
+                               BBB6F64CC2423299C009E5B24DDF10C9
+                               F87F2A525ACF803C50837EF6C2FF3D34
+                  xor-digest = 3737C19DCC04C7C72EC9280D53C17E64
+                               E9F4B1E47980711DC64FE6D3E7DD05E0
+                               DEFF339F38868B1F7CFFAD4298127949
+                               11EAD4D34047B22B07C397A37F6BD2A0
+
+Set 5, vector#108:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000080000
+                               00000000000000000000000000000000
+               stream[0..63] = 84F71EA20D46B3802A787C1322DE6A79
+                               34587F447AE7FE277362497E4FDB69CE
+                               129EC4D8D80ABD0C15026EED3DFE2B6F
+                               C48C5DF09CBE035E348A22F8A2AB7DAA
+            stream[192..255] = 6444791C6DE062EB9A494AEB910A458A
+                               DE3D834BD6F87F26A9D6F99FD970C820
+                               ED9FE0DF88A924F97945B0EB10E5D464
+                               559AA278DAF6A942651E06C66D33F7A0
+            stream[256..319] = 1878644E35B3BC562F82647D45C84317
+                               769BACDB95DCEACA456727616BC90FF5
+                               E78FEE1EFB86A714CFCDE79AA9E66FAC
+                               D600B0FC5C471569BBEB5692E7D9616D
+            stream[448..511] = 54BD56C4F0F3A0CB89A678F2912E5B21
+                               C2B225030E82A90470EB6040F50A818D
+                               C91F65BFFCEA3F9041BF110A762DE3D4
+                               B41A8D1E18CAC776063B2DC93BC2D02E
+                  xor-digest = 52E18382B88883C5648E067675468200
+                               2AA9AC5C18A856E89175C449A6033501
+                               87FA4C17A4D36269340F0877385A35AC
+                               4B7FEF6E1463D34BCDF3597618FAF352
+
+Set 5, vector#117:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000400
+                               00000000000000000000000000000000
+               stream[0..63] = 3F40E9A3C872ED15A6AA296F716E095B
+                               F39153C7C6F4ECE6F550AD35582083A1
+                               CA0DC3CD817AE3946E43AA9C8700420F
+                               F0DFC21B34F4E5E40B3EA14299EF468D
+            stream[192..255] = 853C4A895DCBE411B9B2E340B0AB55AC
+                               8EEEC42885768110ED7E1CCADC10121D
+                               8DE12AFD0DCA4507A8A7A2650FF68C6B
+                               5DB1DD670C8C68365E846934D16A46CC
+            stream[256..319] = 565AEFAC0325093EF87FDC51413BD5E8
+                               56AB6C90FCE7D3C6EEB7E58F22AF63D6
+                               73BCF3840D611A5E1102E9A4108CB902
+                               5A1D837510A971536231CA247965379B
+            stream[448..511] = 887287B62116FE2A28957ECC71DE5BA9
+                               CBBC16DBFA4EC141EB617F9314FCD238
+                               91C4237FA35871C0C795E2F3A4197DB4
+                               F81BA4A29759BEB5FA2277CBB9169734
+                  xor-digest = 78E564BE9E7102E2CB009D7A540395C6
+                               188C8499B7E96C0AD709C3BA2C341741
+                               6EED55AB00AE5719F25CFA06F1488E83
+                               798F18BFD755B9061AFB4EA5D864FC24
+
+Set 5, vector#126:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000002
+                               00000000000000000000000000000000
+               stream[0..63] = F4C281D9C88A7FD6B2CBA9EB0366C594
+                               59327932DBEF8118A7A680D0F0AA41A3
+                               735FE0874F047D2B071B5B9E755A7B6A
+                               9426353B923A5913C647A88B642B2C00
+            stream[192..255] = C7DAC2AE7631D11EB21EF15FDCD3EEDE
+                               7DC98A7060613A643EE8A944EEB6C7D1
+                               EDE08538E1BA6092ACDE0C648D29AF5C
+                               309CFCBC4F40A713FA58D93C954961AE
+            stream[256..319] = D1647D6453798B7E15A49199134384B5
+                               C9BDEBF7F859F6460C2666F297410070
+                               E68307CA78790EF01D160D94B69729D6
+                               90A4FE477A27AFF8B254875C98116485
+            stream[448..511] = C6D3DCBD0E9D4746B142C819867E0A14
+                               8B81FEE3D1007E907F8E9D597EAD63F7
+                               A87E6F224C67CF8162C4E92FC1BE44EA
+                               FE3715B3C1C432CC660CCF1536A20F46
+                  xor-digest = 59FDF05B6D16079B7E18F6A8CE0C58FF
+                               AD7C985C01A12C07D1ECEA740A92F761
+                               FDAC3F96357498B5F5FBA91DE6502A86
+                               1332A1B3E85C5E72444A2168C25D6FEB
+
+Set 5, vector#135:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               01000000000000000000000000000000
+               stream[0..63] = 494BAFEFE4FBF2C406F55FFB436105BA
+                               09211B71DA446A0F5436E6DBF42F8E1C
+                               C805E797C9987C14997083E9004473E1
+                               B2B3729DE9B483361CD38CC78C982533
+            stream[192..255] = 3C04C6633F7D8B714E8549AEA1851035
+                               A520EB6422F42B2C840C74CF51A13FA2
+                               9C1875212E8DC07774D6911415F1C305
+                               9826A05DA9F09942273CDB592F7E3A6E
+            stream[256..319] = 1FF6BEFD79A7E5BA0DF64948BA0ECE7D
+                               ABFB3883BF8A95D3E76DEA30550F5C3A
+                               2B67FE2AB78DF091E758E498418EF514
+                               089283275588A41AD20D53E6394635A5
+            stream[448..511] = A4D10D3B6AFDF415D49FB6ADA1245812
+                               1DA1365ECEBDB6C2508F1EB92E91E8EF
+                               90892E6FCC9E70AB9A2EC4D49A11C197
+                               68E6B4C154A4D65C55AFD38B2BE3F4DE
+                  xor-digest = 91D4EA4C6ECE28536C415A6AF46DC432
+                               3B6DC2DC98C3A3FE2BFE53C8FF556C16
+                               0197D655357512A808415BF757AB3A84
+                               6BE7865622D32B7DE3867B3B096408DB
+
+Set 5, vector#144:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00008000000000000000000000000000
+               stream[0..63] = 521913EA655235FA0E713B0DA3ECB98F
+                               7AB817E70827D29E75E3BF2729EC2AAB
+                               8747B8FE0FC9489B6E0EFF45EF985980
+                               CC0189D9D0F2EF34E809D992E7695D9E
+            stream[192..255] = D265AAD80EC96DFF08859F93B236136A
+                               BE146981E919C0554D64FBB7D03DC9AC
+                               9021F2A1B39866567D8BA1DBE2C3CD21
+                               E5C4C94085F7083F4C640E918C4004F1
+            stream[256..319] = 7DCD3CF623332365E6CF2D92FD147BE4
+                               1E532F51F939C921DD4492E026993E56
+                               843ECBF0925CC52D56084E7F2B538653
+                               2020DEE6FE7E85D4A89AEEBD5F3EAAAB
+            stream[448..511] = 00E20611C7ADFC3BD9E59B9E6D7ADB03
+                               F87FAAB01D7771B89299BDC59E1E2EAD
+                               FC9FDE416B62FEF07AB7A816AF261E77
+                               FCF79DBEB09323D44B5956CD93AAA990
+                  xor-digest = 0578B3E20EBF98D89E2DE82A6EA8E34B
+                               424E526CF419713F0AA662B852E58BB6
+                               7ED570D75534E1F23F85F160690A464F
+                               122CCBFA5CD1DCC0969F2E57D65D64F8
+
+Set 5, vector#153:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000040000000000000000000000000
+               stream[0..63] = 2617095641B825094DE44205319CA853
+                               418588D5B6BFC05A2713CF898DC42B3D
+                               6ABDDF4C287235438A48BDDA49E5ECF7
+                               EFA235A23BF667289612893708704F08
+            stream[192..255] = 04F668517ADC1AF6E31DE6B7007ABAC3
+                               59A2DD6DD61755C6CA7053E05FBBA2AC
+                               D9AF682EFC71391EDA4A5872B53D7CFB
+                               BD35ACB719169283EFD9FF9E172269C4
+            stream[256..319] = BCBA3F15D83B9AD41317AB9EF7DFDF0F
+                               FF05CDB058AB08D7BBD720723E969CAD
+                               79F16D26DF0222CFF4249B839EB9F9F1
+                               422EDAFB8EC285F27E347B7B4C9B2C23
+            stream[448..511] = F15F17F38917DFCA9141314047595C17
+                               047F91E4859D849E9A6339F640E3633B
+                               6A1B62D089B24062BA5987C3FAAB6633
+                               99698CDE6FE7A461F127AF67B2C5CFBA
+                  xor-digest = 68B2369B45F059964A1FD3822DAF61B7
+                               82A9FBA7EB563F83DEC4D058CA5D8931
+                               EC74AF4043FEA803B696791C8E0A675B
+                               DD8982AEA862BB76847E1DE12F2A5E86
+
+Set 5, vector#162:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000200000000000000000000000
+               stream[0..63] = B090CC267B29A95ADFAF6BE3E147D647
+                               21ECACBF6B7D0C4061D17FB7DE0A6662
+                               6D6F9FC167FB3FFF237C240AA03FAD55
+                               13B6DA848F22796DB501A8FB89F2B85D
+            stream[192..255] = 1CB95ED9AADFA0E1FFE5704BE69CBA3C
+                               9593746AE87F36A786E5EBE18A1D3B25
+                               F4785EEF4DB439472035BF053687C5F1
+                               0B60EF55A76DD1994FBB482BBD250755
+            stream[256..319] = 826BE3D679C872536D55C3F0E49C2624
+                               D41726A4525A50CF91EB71E7CEC5AC47
+                               F3834358E2296CF0D04B8D8CE8A701B6
+                               6AFBBB8776DB2B75F1CFA01231B365FA
+            stream[448..511] = 244DB28A98619907AFFDCCAF303A3795
+                               3B6D21EE6D22780C4D3C939C084E4181
+                               1FFCD8F2DA2E6A2243BD0B5428FB86C1
+                               F0EA2E8C8B6950ED961F4FA8CDFDCD17
+                  xor-digest = AAAFCEB42F2EF40C4B5462307085434E
+                               E4399F87B4AE5CA828A952A851F47913
+                               A51430A8BB9B3CD0A4B2F12E297F51E8
+                               FE0B1A6FE0F21177EAD9284087D3706A
+
+Set 5, vector#171:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000001000000000000000000000
+               stream[0..63] = 0F4309F63F237DBB51567573126F09E8
+                               E49990F26E541EF888B9F2922FE9D280
+                               C8FF4874C0D4FA3F41034B82E2E026C4
+                               594A79C2B689BC502C41244DC1AD472D
+            stream[192..255] = 95DCF9685E429DEC2833E1B5E78823BB
+                               ACD9332D668C4B342B89A290E1CA6127
+                               B0E5125E44445A1156A70B27966C3E0B
+                               4E0BCBDD9F4561998A5CBCFAA05C7459
+            stream[256..319] = 0886E9887182156005548CA1A08B57C0
+                               E9FA76C2A694E1CEE22E9B715E99B115
+                               9AE064DE644FD580E8356164A45EA1C4
+                               3DD85E16158B5130AA103267C8118105
+            stream[448..511] = F8AF6F9992781BB09808B7AF404F6546
+                               6FA697C2A1BC9BF64F8D6B6D8CA0B856
+                               6B64E6BF0500F6D80113D9457855FDCE
+                               1791C7436F5FF41ADA87562C175942D6
+                  xor-digest = 8D32FFAA409C8CCDA6892C388D5D654B
+                               4AD50ED00BA649737BA8F350811A2AE5
+                               5C89463C7D63F1F1F16C4007826C2CF0
+                               E4BD9453A60D88BE86F60BADC3E71E98
+
+Set 5, vector#180:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000008000000000000000000
+               stream[0..63] = EBABC8B756971D46C1A5E86CC7AEB329
+                               4DEDACFC795F2AE02CCAF68B933DEF4A
+                               19E96BA64DF14EB6FE67CA48861B49BC
+                               16052E33C8B47556DFBD96037B7DE5F2
+            stream[192..255] = 0438A8CF718F4C52E33DA087FFEC01E0
+                               459D26757D5DF55D5D7BC9BA88F57EC0
+                               4B84D854374F95317CBDDEE928A2CCAB
+                               E4BA1BBBF47776B29890DF00D864FBD2
+            stream[256..319] = BC4A80F9CACFE63D2E54044ACFF39F97
+                               2C69015058AD3F81CBBA28FB0987FFCF
+                               9CD1F6AE4F0602BAE2B828D3FA162936
+                               23CF3AC2950BD651F7E467DF8B454BD6
+            stream[448..511] = EDC95FB80C9FED4A73D6EE9B2CD74BB7
+                               E6DEB9E7868D40FC49BD1C52838457F0
+                               88DCB29C2107066D55A80908EFD1392A
+                               B4F2F13C0A79F67E58C91A89A5C88991
+                  xor-digest = BECD7FD2014BB9A25701E69F9788FC84
+                               1AA9DA56CDE1CD93DF45D28F29D32E22
+                               F488B0C2D9FE95B267CBFD35EDB2F6E3
+                               05DFA5A2CF09D7E2D13348BC0C9405E2
+
+Set 5, vector#189:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000040000000000000000
+               stream[0..63] = F28A15A90386237127A5682EB09E0E58
+                               30709455034A7189AC9710DBB50D5012
+                               9EB4E0E9036D4504054B281F3FE9F45F
+                               C80116B8FFC0B42F9A636A399B7A8BD1
+            stream[192..255] = 1219EF9BDC250E88BD0A62DDCF9AA1DB
+                               B62E19FBA748DFE1035C6A5B3B94954E
+                               1370487A455916F7DAB451F79C5E1298
+                               F549CE005A1321E6B136B59BAD9EBCD5
+            stream[256..319] = EBBE81DAE5637C4C7EE6FF9251D5407E
+                               DF7E8EAE384D1E588CAD39AD9F763004
+                               9A8E028120B5065B658EF3E2B357E52F
+                               F18891819EEE3EE021BD1AF08A4B1F53
+            stream[448..511] = 50086FCFCF5EFFEDC4A52B0212B7321A
+                               8664F2976493868F13D7CFDFB7583E99
+                               EBA70778A83CB88850D45B300F7F6A80
+                               E721860560B2FA642B2E77C7F7AB0662
+                  xor-digest = 336516670616300FD5FB014C1076B53F
+                               6637AD0EFB453615924396785CA4D284
+                               B03F526FC2179FF3BFB0A1A2ACFFD87E
+                               EDC4C8360DFFC132CE6A502EB173A0D4
+
+Set 5, vector#198:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000200000000000000
+               stream[0..63] = 93261A7231FD030CEAA974BBF8F3A721
+                               33334C5F3B25D5831B203C353A566D80
+                               DA578081A047E28DDF8E4BD5B68BE4A7
+                               FDE4BB3A4875BA84553AE120ED77C9CF
+            stream[192..255] = DEC4B603E6A6F911B68E5C1265FA2004
+                               71B296A647D20C13E42202C1A3AAE880
+                               305F969BB88002C8FC00CC5DBE40AA06
+                               4AF85646AA8C7F7191FE26FAA2918A95
+            stream[256..319] = 849431145F27957D53CD355501363E4C
+                               5F191DA666B77364E5866CAA16A9DEF0
+                               DDB9BC266EF41DB0C2A7642B9E8DD27D
+                               60DEA6E69052D4BDE9FC83B2578C72E7
+            stream[448..511] = 5556EF9874E3150FC539C9BD3BAFD308
+                               8FB347D5E38DB318A72AE0C6B6FB4163
+                               082545A9AD8872AC383A78230729D083
+                               31BFC3F2C80DA20617435FFDF2529A7D
+                  xor-digest = BA9CA5F3C27246F931824A9A425F2390
+                               E183188FEDE5BE3591053ADCC933E1F3
+                               DDF5627A94F80F8922F53E951490E96B
+                               F51491ED2D6DA26F3BF69CC41B8C0C98
+
+Set 5, vector#207:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000001000000000000
+               stream[0..63] = C449AF4CD437641A3B40D0E0E7B5696D
+                               CE973B3B217E02DC20B2F5573FDDF78F
+                               E6E55D75CFAB8EE04C8962376D22A843
+                               A80BB79C8B8D8B500C4B6DA27748C398
+            stream[192..255] = D5C92B62B0818165096551DF2B007F66
+                               2DF953742EF0BBE97982FF9D3EE83E1B
+                               87EC9D710CF1700262B1CAA9C68A897A
+                               8AB4A162DB0443A43962EECFE5B4C0DF
+            stream[256..319] = 3B8CC7E847669AC6858B7BB716206386
+                               40D8C2DD259EE4970A5F254077101271
+                               DF745AD7F57712065E2D03B9D7220591
+                               5C8C033A4F9146EE561B4179DB465989
+            stream[448..511] = BA4ECB7D74CEE56CF1D5AB636BBD6421
+                               C30A51DABDCED17C8D50F5293424AFCE
+                               33AF71095CAAD3913A8A3A12286A8E91
+                               89DAFCC1E2E744FBF4B526E910B5F2CF
+                  xor-digest = FAD57A608E04CD71B176BBFADED7B229
+                               D855A8025E963B55FB83EC7311427779
+                               490F25D34C6385FE1C036FF0807E136F
+                               40C10588678E2414163AF1819EF7D3C9
+
+Set 5, vector#216:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000008000000000
+               stream[0..63] = 989F302DF6BF8C63F9EB69D2625115B1
+                               2CCDA42A2D33BC6F21BD55E0594DBAAD
+                               9A294DDFD6710E36000C27FEA7E03440
+                               C8A6E728716D0DF14E825B798A6C420C
+            stream[192..255] = 3F3140320AA02367512E7C1789F5C03D
+                               83CC634354237E78E16B1A64DBDFA6EF
+                               0697B28BDFFAEC311C6E2089BCF64203
+                               A2EC7BF3CA922080380241A47A673634
+            stream[256..319] = 6049048A5307D55D6DB387A6149C7B23
+                               0AE33195D53E0026103EB44489BB86C6
+                               BAEC7A0D920CAE25B1E7B9F07C07C4AF
+                               6485FF281C7B7FE1D61E660AE55C20EA
+            stream[448..511] = A6DCBEC85525FA19FA6066470B4CD83F
+                               17D42DB3353B327BF3DD6E7D047CD752
+                               71E79CCBD46E757F3654C2506C2B593A
+                               BC93B8985C491017A8E616D69E8974FD
+                  xor-digest = 55BE97FD8317A47742F8F3BB762160AA
+                               7FDFBA371864823D93EF6C029D457AC1
+                               2D679CB424DA9EAF8E4FE28271C66F06
+                               1E91D8F2EF41733AC1084F54330C9786
+
+Set 5, vector#225:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000040000000
+               stream[0..63] = B8989CF76BB1AE894699604320C14706
+                               E20C8BD86C016B5E2EF705AEC54C6023
+                               2A9AA961C10914A8D910D517059A93F9
+                               78C537767A057E0E11DBB5C9BBC4EFA9
+            stream[192..255] = 83FC232D21D0DB82747D9EDFEDFB58E2
+                               BB37362FA2B4E1AA0C9A58AE521EFC86
+                               C512831CC6D2E85FBD96FD3B60D1D153
+                               E83DDC6C5755899CF96FDF69E3732E4E
+            stream[256..319] = 201DDE5D82B754341A3452BF7DDDBF6F
+                               167B2A087900EF40E4268A80217D7310
+                               F1E9E25C707A1EC05219E3CCFEC0F6F5
+                               28CD98534F6C579A1ACD3171D131D87B
+            stream[448..511] = C2F68B5F03B0045FEE0FC92DA08F8545
+                               762F73E553D2F539C64B88D4FAC9B011
+                               DE0504D66007A115E428F627A667FA2E
+                               296F222734FA0F905548058897DEA990
+                  xor-digest = 7DFA65F57FD58891C5576B3CC7002513
+                               C1A983E9D31317B681604DA09F176AAC
+                               4FD78CE84EB9427BE8D6A63058582F16
+                               148D55B3C2544CF4DB9306699CA74D80
+
+Set 5, vector#234:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000200000
+               stream[0..63] = 307B13F3D3EEEA4C8FAF34416689F354
+                               AD26336D6B33DFC5AA004420D2DEAA69
+                               F69E531EB6D672AD62B2A6A136046373
+                               F70272E84E14CABA9AEA3102863A0B10
+            stream[192..255] = 8E4DA19FEDAD4C842917ECD5E7256097
+                               C2F524324D8A974D4185D8B11B611C72
+                               6C39DDB5E58180971DA181D36A289CBC
+                               1937E8F020645EC8D0363A58C6147F38
+            stream[256..319] = 012A99871D6C4CB7328C1374F37D0BE3
+                               DCC2232F6484A22C8F330D77316A1756
+                               71DF7CB32773F25D772BFE9DED5981B2
+                               0C3F0DDB2879AF61E7549F03AE26D233
+            stream[448..511] = 47C6CA462D35580BC0C78C6427FB96F3
+                               BB762662F5B52FB3938CCCEAC35884C1
+                               54F5BBF513970FC08F51C91059A757B9
+                               A8B6F1EFE467FAADA8D4DF68C6AC1942
+                  xor-digest = 6409F8C255BAE6167686F5F9C7EB2349
+                               0FC7BA4DCBC80006B57A5F56CA9F907F
+                               849C2A0FB0D74CAAFC0E2D4367E2912E
+                               BA6487D8A48DA60E48277A20E326266A
+
+Set 5, vector#243:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000001000
+               stream[0..63] = 543BAEFA799FA0CF5295B92EF3FDC07D
+                               69B87C1B5FF0A9F25B32F8FCC473D04D
+                               54B6E467D6183F25E3664A330889889F
+                               A530E354B6E53EBC78354100637A62C3
+            stream[192..255] = E15997D1E7C0FA38333DEE2EE2477A4F
+                               AD32F0810E8D3D65EAFB110C2B8D0948
+                               59DC45C4AA38B8050A87C23782E1A26C
+                               C193985BB0C3E754A528BEAAE1508D76
+            stream[256..319] = A94F1BD38219097B70EC0700A64B0ADC
+                               7BA8883B5C2C3BBABD0497E80D53121A
+                               2DC5A5C6A77913330EF5469871BABF86
+                               0A09F1474D893ADC28B473EE508F473F
+            stream[448..511] = A43AC01FC186AB42241ED3729E7EEA39
+                               F0823D124E8CB696E2F4B047A6B71164
+                               5B803623CD0371C4975217B3CBD7D9B2
+                               FD89D3B6BD23FD11FEC0B03B9CC22AC0
+                  xor-digest = 792A5EDB6E7FDBE99B7EC2119665C2F2
+                               34038F561BB1923F3BF493AE35CE2006
+                               55B8EE47490B53EBB481AB7C6B82FACB
+                               233AD86D74385FA108C94666CD34C164
+
+Set 5, vector#252:
+                         key = 00000000000000000000000000000000
+                               00000000000000000000000000000000
+                          IV = 00000000000000000000000000000000
+                               00000000000000000000000000000008
+               stream[0..63] = CB4377099B2D7CD6A982A1B1A53E05F2
+                               E097164EDCB381468C21D8F0615A654A
+                               45A4D09B7C0218A19496EA71CEEEAE5A
+                               886307DB0026C96049B60E5154F99AA4
+            stream[192..255] = 25FCE0B7E28D5D0D1654D912DBB21AE0
+                               288CCC71396CA5AA36AC44AB08EC72A1
+                               01E5B189535C1987B79DE4C4E32DB7FA
+                               48ACBC8F854868FC287E03D54752230C
+            stream[256..319] = D3B02A39A4E467C44C109E1E25593278
+                               2E9B3CCB02D6F107C9263A24E113FAEF
+                               847A9064E1AD1EC8881EFEB239CAD6C4
+                               E90ACEC36A7E87E002F35D477CD63F2B
+            stream[448..511] = 7D4282D7E11439C04ACFF087708DA22D
+                               236F1A08A6343704DA4D24EA3582253A
+                               35419183A915B571DDE80C1DEE2B8A13
+                               76EE973234FFF6A0DD91D31037F51C72
+                  xor-digest = D52720D8DF114235D99E5292E14DE96F
+                               9D8478E016CD40EBA25C4B9D8E11713E
+                               FE9AC151E1F39377FCC07D06E9BF6931
+                               6EFD7E27F87E9F76DCBF7831CC3FA98B
+
+Test vectors -- set 6
+=====================
+
+Set 6, vector#  0:
+                         key = 0053A6F94C9FF24598EB3E91E4378ADD
+                               3083D6297CCF2275C81B6EC11467BA0D
+                          IV = 0D74DB42A91077DE45AC137AE148AF16
+                               7DE44BB21980E74EB51C83EA51B81F86
+               stream[0..63] = 23D9E70A45EB0127884D66D9F6F23C01
+                               D1F88AFD629270127247256C1FFF91E9
+                               1A797BD98ADD23AE15BEE6EEA3CEFDBF
+                               A3ED6D22D9C4F459DB10C40CDF4F4DFF
+        stream[65472..65535] = CFF0058C45807C1F4300D118FDFC3B21
+                               370936B39391791C92A821E1C8E8F248
+                               BBBF378679468218FF5F6560B79A6015
+                               82B81315DC19D8583263958B068BEA48
+        stream[65536..65599] = 871A09D393D8888EBEA453F518BD300D
+                               8233E906A31631D29A4A1834E268C3E4
+                               F65F4F65B1B9E55606BDF28A571CA4E7
+                               59BDE4718E1E13731663F5CAF1CB0F1E
+      stream[131008..131071] = 15360407DA7B389DF28C08B2221F5E0D
+                               96B34839325795A70A3F65D9CBB3848D
+                               8C0793A53E8C4D71D8B53B2923A90B37
+                               FE412A4485F0CC741E65743C6F1ECB4A
+                  xor-digest = C08A2B344B4A486BEB4568EFA585A481
+                               64C90A34752FC3523C3A99D764AE33D6
+                               825915067FD64D90EE81175416A3B4CE
+                               780426A44A4530994A1A8A83A5E9E243
+
+Set 6, vector#  1:
+                         key = 0558ABFE51A4F74A9DF04396E93C8FE2
+                               3588DB2E81D4277ACD2073C6196CBF12
+                          IV = 167DE44BB21980E74EB51C83EA51B81F
+                               86ED54BB2289F057BE258CF35AC1288F
+               stream[0..63] = C44B5262F2EAD9C018213127686DB742
+                               A72D3F2D61D18F0F4E7DE5B4F7ADABE0
+                               7E0C82033B139F02BAACB4E2F2D0BE30
+                               110C3A8A2B621523756692877C905DD0
+        stream[65472..65535] = 5989C607133DBC6C0F2DD022D4812ABF
+                               91111E266BBC8EF91F1759B3CFD73E12
+                               432C1334E3549EA54917BC0156672E13
+                               DBFDE5F0CE6C504EF4AB69A9C311FC79
+        stream[65536..65599] = 0D22D9DD0AAC594F812839C7C4D0B690
+                               7A19FE4985E1A0DCCA5930E6F5A70055
+                               452978828569A28AC62C30274CAAD865
+                               F4F8BC7E3F058B50C454F3CA360264AF
+      stream[131008..131071] = D17E6611F2754F60629B7CF29CF35888
+                               3765A08C62167AC620C1CBCD1058F527
+                               4B2D4335591F7962A0A76D5F430332AD
+                               C16B13E7EEA80188974860D2EE3BE81F
+                  xor-digest = B7163FD0F8A41562DCB10212DB9C97DF
+                               C25C6BEBEB6331F072118F046E508887
+                               FB82C0A3FF8B0E0B5765131BD58F3181
+                               AFB3803A2C1C8C70877AE29F74D433F4
+
+Set 6, vector#  2:
+                         key = 0A5DB00356A9FC4FA2F5489BEE4194E7
+                               3A8DE03386D92C7FD22578CB1E71C417
+                          IV = 1F86ED54BB2289F057BE258CF35AC128
+                               8FF65DC42B92F960C72E95FC63CA3198
+               stream[0..63] = 9D13AA06122F4F03AE60D507701F1ED0
+                               63D7530FF35EE76CAEDCBFB01D8A239E
+                               FA4A44B272DE9B4092E2AD56E87C3A60
+                               89F5A074D1F6E5B8FC6FABEE0C936F06
+        stream[65472..65535] = 85D7E59D15760E12C5E8D0D5CD9B46E7
+                               00F8E821C91CAC8C37A6200E61A71E84
+                               15932834C0A06DC7E5738E11A0F9A9C4
+                               38ECE66D8D5A654A754FC5858B28EE21
+        stream[65536..65599] = CEC10B6D37543B35CE32B152BE2928FD
+                               C8476E341F23AFB3B404D40EC0657A8E
+                               95F5CF7297EB1948385A5FB2FBBFAF66
+                               E252F35AA1DF199FED99DA532E5858E3
+      stream[131008..131071] = 9DF7785EB3E69ED977E6DCC59EDA18A7
+                               41029BCCC4590A46B8F9FAB96B5C4268
+                               2FE49EC0BF79FBB637E6DEEACC068E4C
+                               93D215555CF876E17F37968576C5D5FC
+                  xor-digest = 0B36039A89999715A7F53207DD60203A
+                               B397397C718C7057E82E36C05E49506C
+                               911F9596F2A5818E0ABE6BE666086DA7
+                               9B18E89A43C64B9227BF9DF65CD55C35
+
+Set 6, vector#  3:
+                         key = 0F62B5085BAE0154A7FA4DA0F34699EC
+                               3F92E5388BDE3184D72A7DD02376C91C
+                          IV = 288FF65DC42B92F960C72E95FC63CA31
+                               98FF66CD349B0269D0379E056CD33AA1
+               stream[0..63] = C8632038DA61679C4685288B37D3E232
+                               7BC2D28C266B041FE0CA0D3CFEED8FD5
+                               753259BAB757168F85EA96ADABD823CA
+                               4684E918423E091565713FEDDE2CCFE0
+        stream[65472..65535] = 340CA4A2B985CCB5C07964B36AB84409
+                               679FFBC616ECFCC672A0F61BBE94AD0F
+                               E6C065CFC069BCA7D33FF35BB2967D0F
+                               FE84BC6006E46D7CA0C1AAEE279E8C32
+        stream[65536..65599] = B5221331961267143AF1A5EC7D1118CD
+                               C96A4B088404F5B6C5BE7320C87C4E90
+                               F5333906AC759D7747EA06903525620B
+                               D05703033C5F1973809B9D674688461B
+      stream[131008..131071] = DF8934D8386B59B681CC9146E6EF9A7D
+                               765366267B4BDE3DE8DD15B714A397D4
+                               08432F2B975F6274132FECDA89E0FB32
+                               379023ACDA101452D30657E6D5059828
+                  xor-digest = 36D3E252F992C30C76818B3364613BE3
+                               7F84FC4B848272404E7D9E689BCB945A
+                               A85CBA790187A4FAF9811CB0824F2F46
+                               6DB05D3F96A0AF233486AD28A593AC24
+
+
+
+End of test vectors
diff --git a/BouncyCastle.AxCrypt/test/data/keys/README.txt b/BouncyCastle.AxCrypt/test/data/keys/README.txt
new file mode 100644
index 0000000..352170f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/keys/README.txt
@@ -0,0 +1,4 @@
+The pbes1 and pbes2 folders contain a series of encrypted private keys generated with openssl.
+
+The password for all keys is "12345678a".
+
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key
new file mode 100644
index 0000000..a765d9c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndDES_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key
new file mode 100644
index 0000000..40b449b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD2AndRC2_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key
new file mode 100644
index 0000000..f54557e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndDES_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key
new file mode 100644
index 0000000..595ee50
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithMD5AndRC2_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key
new file mode 100644
index 0000000..2eb164a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndDES_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key
new file mode 100644
index 0000000..c724d63
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbeWithSHA1AndRC2_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key
new file mode 100644
index 0000000..4455719
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC2_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key
new file mode 100644
index 0000000..efc0c1e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And128BitRC4.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key
new file mode 100644
index 0000000..ba349f1
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And2_Key_TripleDES_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key
new file mode 100644
index 0000000..a9098b7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And3_Key_TripleDES_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key
new file mode 100644
index 0000000..71dafa9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC2_CBC.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key
new file mode 100644
index 0000000..85a18e4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes1/pbe_WithSHA1And40BitRC4.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cbc.key
new file mode 100644
index 0000000..8b8fa28
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb.key
new file mode 100644
index 0000000..a30a3e3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb1.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb1.key
new file mode 100644
index 0000000..9b35154
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb1.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb8.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb8.key
new file mode 100644
index 0000000..dc974b0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-cfb8.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ecb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ecb.key
new file mode 100644
index 0000000..1a9dbfa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ecb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ofb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ofb.key
new file mode 100644
index 0000000..0cb9df7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-128-ofb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cbc.key
new file mode 100644
index 0000000..fa9b39b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb.key
new file mode 100644
index 0000000..ac21ae9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb1.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb1.key
new file mode 100644
index 0000000..c33f3ea
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb1.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb8.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb8.key
new file mode 100644
index 0000000..3101634
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-cfb8.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ecb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ecb.key
new file mode 100644
index 0000000..0a061a0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ecb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ofb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ofb.key
new file mode 100644
index 0000000..cdc4cb4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-192-ofb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cbc.key
new file mode 100644
index 0000000..393f892
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb.key
new file mode 100644
index 0000000..7e88cb7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb1.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb1.key
new file mode 100644
index 0000000..9a8e33f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb1.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb8.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb8.key
new file mode 100644
index 0000000..84643b6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-cfb8.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ecb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ecb.key
new file mode 100644
index 0000000..293bde5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ecb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ofb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ofb.key
new file mode 100644
index 0000000..f47d92f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes-256-ofb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes128.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes128.key
new file mode 100644
index 0000000..0711ff2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes128.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes192.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes192.key
new file mode 100644
index 0000000..6fea76e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes192.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes256.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes256.key
new file mode 100644
index 0000000..b449e07
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.aes256.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf-cbc.key
new file mode 100644
index 0000000..4b2601e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf.key
new file mode 100644
index 0000000..7fbb6ed
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.bf.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.blowfish.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.blowfish.key
new file mode 100644
index 0000000..2b19b24
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.blowfish.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast-cbc.key
new file mode 100644
index 0000000..383b6d4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast.key
new file mode 100644
index 0000000..208cc5f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast5-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast5-cbc.key
new file mode 100644
index 0000000..728de6f
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.cast5-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cbc.key
new file mode 100644
index 0000000..8c8f4bc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb.key
new file mode 100644
index 0000000..0cdba7c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb1.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb1.key
new file mode 100644
index 0000000..9474026
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb1.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb8.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb8.key
new file mode 100644
index 0000000..c5d5594
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-cfb8.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ecb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ecb.key
new file mode 100644
index 0000000..1798e4d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ecb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede.key
new file mode 100644
index 0000000..0ca0df8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede3-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede3-cbc.key
new file mode 100644
index 0000000..dd3579b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ede3-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ofb.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ofb.key
new file mode 100644
index 0000000..d92de62
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des-ofb.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des.key
new file mode 100644
index 0000000..3b4f3cb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des3.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des3.key
new file mode 100644
index 0000000..78ca4a5
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.des3.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-40-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-40-cbc.key
new file mode 100644
index 0000000..6f50f13
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-40-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-64-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-64-cbc.key
new file mode 100644
index 0000000..1a70f97
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-64-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-cbc.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-cbc.key
new file mode 100644
index 0000000..c8778c4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2-cbc.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2.key b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2.key
new file mode 100644
index 0000000..fef0f14
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/keys/pbes2/pbes2.rc2.key differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/README.txt b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/README.txt
new file mode 100644
index 0000000..9abffbf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/README.txt
@@ -0,0 +1,36 @@
+This archive contains material to help verify interoperability to the
+OpenPGP DSA2 design as implemented in GnuPG.
+
+Keys are located in the keys directory.  Included are:
+
+ 1024 bits, 160 bit q size (i.e. regular old DSA)
+ 2048 bits, 224 bit q size
+ 3072 bits, 256 bit q size
+ 7680 bits, 384 bit q size
+15360 bits, 512 bit q size
+
+All secret keys have the passphrase "test".
+
+Note the inclusion of 7680/384 and 15360/512 keys.  They're large,
+inconvenient and absurdly slow.  GnuPG will accept any size key, but
+will not generate DSA keys over 3072 bits.  I include these keys
+mainly for be-liberal-in-what-you-accept testing.
+
+There are are signatures issued by these keys in the sigs directory.
+The filenames indicate the key used to make the signature, and the
+number of bits of the hash.  In the case of the 1024-bit DSA key
+(160-bit q size), there are 5 signatures using different hashes.  This
+is to demonstrate hash truncation to fit in the 160-bit hash size of
+that key.
+
+File			Key size    Hash
+----------------------  ----------  -------
+dsa-1024-160-sign.gpg	 1024 bits  SHA-1
+dsa-1024-224-sign.gpg	 1024 bits  SHA-224 (truncated to 160 bits)
+dsa-1024-256-sign.gpg	 1024 bits  SHA-256 (truncated to 160 bits)
+dsa-1024-384-sign.gpg	 1024 bits  SHA-384 (truncated to 160 bits)
+dsa-1024-512-sign.gpg	 1024 bits  SHA-512 (truncated to 160 bits)
+dsa-2048-224-sign.gpg	 2048 bits  SHA-224
+dsa-3072-256-sign.gpg	 3072 bits  SHA-256
+dsa-7680-384-sign.gpg	 7680 bits  SHA-384
+dsa-15360-512-sign.gpg	15360 bits  SHA-512
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.pub b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.pub
new file mode 100644
index 0000000..3fec64e
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.pub differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.sec b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.sec
new file mode 100644
index 0000000..8ee1179
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-1024-160.sec differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.pub b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.pub
new file mode 100644
index 0000000..4f931c6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.pub differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.sec b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.sec
new file mode 100644
index 0000000..3c204bf
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-15360-512.sec differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.pub b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.pub
new file mode 100644
index 0000000..1c8dc69
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.pub differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.sec b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.sec
new file mode 100644
index 0000000..776edfc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-2048-224.sec differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.pub b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.pub
new file mode 100644
index 0000000..307205c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.pub differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.sec b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.sec
new file mode 100644
index 0000000..66008cb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-3072-256.sec differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.pub b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.pub
new file mode 100644
index 0000000..6c888a4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.pub differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.sec b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.sec
new file mode 100644
index 0000000..b57f5d9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/keys/DSA-7680-384.sec differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg
new file mode 100644
index 0000000..c906585
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-160-sign.gpg
@@ -0,0 +1 @@
+������$xp�=�)��
O���'�����g��T<�ꑚ����_��������(������b������a~�IbSZ/���겠�պe,
�����(��p̊=s�����K
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg
new file mode 100644
index 0000000..8485bd3
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-224-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg
new file mode 100644
index 0000000..bebe1fd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-256-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg
new file mode 100644
index 0000000..f84c303
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-384-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg
new file mode 100644
index 0000000..f700ce4
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-1024-512-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg
new file mode 100644
index 0000000..bbdb44c
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-15360-512-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg
new file mode 100644
index 0000000..d64c817
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-2048-224-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg
new file mode 100644
index 0000000..2da0271
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-3072-256-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg
new file mode 100644
index 0000000..f313c6a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/openpgp/dsa/sigs/dsa-7680-384-sign.gpg differ
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/README.txt b/BouncyCastle.AxCrypt/test/data/openssl/README.txt
new file mode 100644
index 0000000..03d9933
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/README.txt
@@ -0,0 +1,8 @@
+Some OpenSSL-generated files, all containing the same DSA or RSA key,
+with various types of encryption applied (as well as the unencrypted version).
+
+The password used for all the encrypted files is "changeit".
+
+The PKCS#8 files which contain ENCRYPTED PRIVATE KEY use this password for
+the EncryptedPrivateKeyInfo object stored in them.
+
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem
new file mode 100644
index 0000000..7af858e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,3D7028A746BE6B09694E16A222C543CB
+
+RkTEJRJjGfaMfNc876Tx1hD92cblJRj7TvUafRKnH0J3Zv7l67MSG/6rY5HD91HP
+s9i9Se+H8Sjn/HaUl3QTZv04egloNlL3MPSkI5fusR6maZGPVLRJBLfVKYQZVDja
+9YRe+ZhXMS8jTe/IhYMcTlQLBnnwmmgZC09Y9Wm39idu7lytOl3JBMgz0aUNA+P6
+lN2MtaQyIBXHbaqfNDGFn/r7+MH4CGw6MtrPzGqRJgGMHhV6T5o/x0nEU+loQVOK
+mPkSZTxBbn7xUb4JvFPnLTbsI4Cnre3QmfmDwkCAklQXqAIT9Ex1Slq8qaCc6TEf
+mWJQCYPUkpQOqyinR8o1VbYm3DFFvE5F+CktJrppqkQvAct0dQNjMTBFxUjCkZum
+qGfAslGPBREmmnsExm5GThYqA5LN+qo2prBtvt6Eso0i2jNiXA8bi5OfDzDr24R5
+/RKUdFPf7keaAjg9jSArwp6EfM3y3sj2riibwZlty2ckPJw3SwxIe6QSMwKRbKlh
+GJoi05/cO0NxQYhMmlwVN9v5+YpvWmT3CsFvCA+Zb5rXPx2AZpFv8YoHdQb0qyEs
+b5YuVoavL58+BWIPQpeYy/jttR5pEPpgM+C/6/1o4Cae4lwppP2OYFl1fsqyqbKh
+iadErB6QRaJCnfnhG6511CxY+vZtQE5EM36blOl/op+6G+36ApuqDtfA0C074daV
+uHfcqA/g5dODEJP+ps6yoWtM5lbd5bZZVidWhrU6Skbt0faF9w5ECF0qkYDGqF85
+qqFcaoimq+NP7EtUEFSneOee72zYALXyzjoEU9InktzDi0Oufojzc1gjhh7LbObw
+UBANPHTsbaL6FPTEs4a3JYSyat9m/R5GAaT0EBynHxvdQRGNhtEWFPkpGYUrAz9W
+0A9mNX1as8Jsxkh9wqjgOR6Xpbqh0aFHNnkodwV72H5ROga5EN8/bbuCBxInNzy8
+o9z19AnajR7vCW/p42QwsGfSolQgE3KBdqWsle81LcCPVQPQshXzcjgBHZbH9/mY
+M4bX4iEsC9yeNgoMcHtIagOKipsqd4nuPskutf07Mh71OXFuxsVyGcOBVhhdZCb0
+3ZYzVi+nzORPRZ93nPXipy3+NmoARk7mhXDgX9p1bPI=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem
new file mode 100644
index 0000000..de088f9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CFB,C0CCB782DF620FA388D9A356F8B7C346
+
+DftIvr+HZuCHBanw4n8P5ZajHAw1ldQkSgLxtxY0ZYhhVDLEqEqh6z+4ySjZz5SR
+KY7kYFo6yJnURurg3DAGvJ55s6jgyrRHQZkhiO1fBxhyarOfcBjJauJKDT4uhFtC
+LWZ7dqft3PlcHi09mFKjK+BYjULe1QkdrKQlV5FBpCj7ENuHqtfx//bV+IWWVnbu
+QRx4ec2nNCiS2qiI9Qg7fgMdXWrpJlr8Zvfmn0Mta3Dn9SWR9hK5J4d3xiBtaF0F
++BNuszy9poxnsRaORZYAsBh2vdLaQyn1gGdehlsWG4J2Zb5RHApYczJcp2AoPX4K
+j9wAzlfLRSZ4Lt5edShd1zf/iDxegBKQFFHTfPA6uu+fe38qckdxVyBdGaCCBvUz
+Quu2DjjXdCWWo8To5C28LVoVyAy+qJaX86vn7yw03/6n0y2dkydiB3u6wnucsom2
+HfLX+pdyarFoNvtCeSW3Y/1Eqd54dDhz3GrSTh6c7G+wiRziKpTduEmoZ+l+CIrl
+tWxmh59YTSeX4mi48+fxTA8xaVwD/j3VuA/jTOQWDW+DXU2z6OcAQ9rlOnT6Jad6
+P2El+vgLrIFbC4eJs2ry6bszqFJ4wieBVnazPCUADLSsXVwbFuO9oB4129y3Yg+U
+dE+lN24KV0kC/YIdO7c2PghaFY98CVrBX/oocHy4j122fHfboiPNh7S7n6cqJHh2
+JKKQK1qTdfULAN5ypecl27gWeM2i3ib2C5jJiOFUlwiAkZWLRJlsiJOk+b/rI5FD
+tM7yFanhEtcYumRRoSzKII3tF0h+z2AwzPdsyJDdASCzo/DmhB0fg0O8G0q/isNi
+VV2zL+w7mNmf79QsrGVA39Y+G/uKS2QPf3bGFthzYZwKH1M9hTN/do8wCCJJv7MR
+Ejnd32srumBOvGXnYtGuHnT3qRA1mj82B00bdfwCd09GGUr6mEQwfvsDOR3q4OfH
+eGCn9NkWKYvf/QAxCG9Vh7u62sUlXKS08hJcVAgBOzN10wFISTIOAvedt/q5GMvm
+nRuF/ixs6f6LNy/VgyztHoQ4vN4HBf8teDsbWSMDvlLkU6tQZjyuu8JkTjeDaqMv
+GbCzrRBldS3zMXX2OaWpZohi
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem
new file mode 100644
index 0000000..4f69fa7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-ECB,174C8C70B397BCF00CAECA7AAF7A0A73
+
+wzs0bJqGg+Scn00TgtgXyV6hopQKVWMEFnMpu6R/Sp1tbPVlr+m5+SppJFVyW3WJ
+YeFSwXzuVAsnbD9qIZpAlco1ZYpmRXaY6IfXJKYf58v2IrqkxVd6AwjGN2FloSNp
+b/DinJXJe807tNAkuBLQ/7QlkCv/BmZMeYBl60XYIH8LDF/T/ON2hREl49zr/GLY
+bwmVzgRpfl3c8QIt6Yl9uKOqCFJmMHD3YS+dT2RwuQwqY+U3DNzVoCci6Zjd+gL3
+eb/S6VstodSR55qF8Fkwt+sy5yL6XmhQaGWEgCwDwArN40MWIEpx4NaBxCcqHF7g
+o26bg6CZwY7Rv42RTHKHNPETegZneAMK+e1lNassSijak+A3ng9bxiBquWSKHe0i
+s265Rptr/GvQX0hLxmfjEjvL98dKVDZpvdBaWRqV2lS26jDPiFAHtVsXvF8uo25J
+1aS8FDHaD2DghC5aXTQRaVy1jlMTm2YZeVfiU6+7HVXBkLsVbShqEHxKylxgtB/1
+OAui+st60+o8lvRmn5dT2xnxLn81Bt4qron4pz0LdzC2xl0DqjhXyRsf7kdxr44h
+YN1YzmdU3fYFzQw+VmE8xECIjPukp+0HSb4n7BTGsWvqzntFIrzWGeRmNhjtMcwy
+YJoWGnz+WbxP3DJqSGNdFME7mNI/kaybIkOpbHLLlmgD7XWpeyGYtsU/rzrh5NXN
+YRj6Nf3TWI1zwS2xx95+/5vc5Df+sb1+/33J4hbGOx9KdfqoVlJZ16puvdTq97dF
+x8TVYxk2PfBJpvpChCsFlYBOB29F+kY2qoBKPbrvmFPsPCgI2q4gFuJ9pq1qyDbK
+pq9d1oewOOxR22VMQNGG7tL0tMmtXJ/z0n3Y1UE3aYiSG7apOhooBAQ8grpuwqbn
+mGTz6sYB8fHdCnedcxEUxxuFjXupmBcT2ulUjFZgFrG0SEMElgTDjtG21eurqPKh
+ZgxfkW+tM251WTi6sqjiQO8WYHlU7+XyO3BKfH5v3kz4qXxsmvKfh4UOfRy5f9YT
+Ft5oi1bos0soTvms0d8ckLt9Tph2wgoz3Sc++4DRcF53Ks9N6iUgtTpkEtmd/Uc2
+5+xewYmlfYO2qfiqiF/6dSVfDPjJYR/YLx8KBZ40/e0=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem
new file mode 100644
index 0000000..cddcea9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes128_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-OFB,B32C602DACAACE3A4C55B4600D974E5F
+
+w1+kMXURdxpREW3giZg+PooayvatT1Pf1bY/h0Wcm8z0w7zRtQOyjCOdEPNxsdd5
+ZYn3qEIOO+wkw0v0PdK1AaegJfYMbMpSp/iEyFXU/LHS0FpO7o8zmUiAvdeEKAFt
+Qk90gFBiyQyvWEWsp32KQH1/eDSeSLeQbfRfDbh70DkB4nUjYMW/eFL9E/cHCmdw
+0LKUpEycc4s8i/mWCYJF+cQd4J8RHK+Ose2+5z86kHTrbFSlTBEZEXPDRHl8ZsZE
+477A6/Ndy0Mq3+NgMLSl8xacs2v3itdza3AJREVOzvnRmV+NmWtYQ4MQrJrLg2yv
+wfAf4b2r+k8Igbpzn3NCEYolecGfyEWftzTsqTutlFO7RfeW8go4v2MvEsmHTphQ
+k2qaQkdSTFaA7a2O4PKezJap4RRCJhq1d5bw7RwkCpbRshsvrKQqGdTGJxEZZfGY
+6pOt/qRL9LVCGUVdTTdje7fx9okx0LvKo62eKcUBh/AwZGE+ue28g6/77iABuVtQ
+6kgJ3lQK3AQwKislF5cBC9MAkiIomsoVOKiP6+yX74XIa7T+3aWXlsY1oX13+kMW
+zijwOrc114Sus2eS3xSCOWLYN+0GECMrh2NDGDW6tx7i3R20BuEF/IwHob1qjbkz
+hnS8KrRY+174avQDeF1lMSBz4Wfi0O1IDuxWRDRT2z31E4E8EIoJh+73NZr7w6JA
+8usK8RkiJ4ypoOPtRegXX6GBG5UYgI5bn1Ms2X5xSUGIXgG8IwjHDbAAd5xLSWp+
+01HzUsR+6wA3MxYiybTU4eOKNMviM1G4gGsKeuGrDsNnidrHfSzVyOGVVHr51xRI
+9Xie4FX/VX8/7Q5RMsA8Y2eN/yeVwXup65JRhDD5LjILVMy7aA90KX7y/s8KIYae
+n6lB7PtcpRWwhdYSYtnlrJmYmrl55d6ZQtJm2/xjnOBd+igY4YKNjh11xBL8YNo3
+wBjW4/lgrlvC7kbLxO6JIWipPr/6F3bjvmeLclTAZxjM1NU5HhTScGaEA8A4bq4+
+6Jiw9ZUw+TDCOmntkgEublcCMjcAxrawWYO/5EWuOAOkyBsa7BbfsUv3pgPugz70
+qa/CEkshP5e/1VZgFq/BNFtb
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem
new file mode 100644
index 0000000..9b91632
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,7FA13403627D9E1FA02FF88F6D594679
+
+hZYB09uY4gjQFEHX8KGI33EzcJijYhBMNJCR9v8UK8IcQIITOfZxYV2BmrfQhuVh
+Kcar1JrQdnc4S7+UDFIjlLV9ErBCvIUQEflP2ByDhxl892EtVcoMKB3BJ2Rgi9mk
+32KhayXo5V2bu2kOv2nTAjp91LebDz/ylmhhJhI86BL0DLjnjTEl99v9OHQsMtb9
+cXZb51mwIynmqU7Wf+PchH83Yw0WOKs4MOrCtsqO9lL7Mf/MiSSiE+S/rpKLPXY0
+4aBxP6fw+HG57gPlNAvv/qKtJu8YgZDqVXhIKNDZRTSRX+B9R1Yo1tgmJVPhk/7x
+mmYUxIb7w9nqa5OrxzFHyNvo1U5dJcXyCEhvUZ3ImR1DZt/oGJYgrPd/8YcYbsNP
+LKmTLUKI5CARZ5KcOjfM8vpKqlfpCg3Yl1FaNIjM0eAhD6XrepLj3faAJW4/YEoZ
+SGMO5atbM0ERT9sNDJTG0iMW6xGL5l/6pzfsTKI/2yMaAeWAyvg1PySNoSH7s6CC
+CfqF0w0VpQEiOPb+qjtmjBDB/VW5kNrRiBQqZAgpO6mED0jAdg9o31tyuuaFDWzX
+41C2viVvxTx5A/xOtPvaDo9EMecc+7MpPLM2VhWhPDiDBYb8PCKqBOEwIyH119MN
+gQEC0IN/itc/J9ybHLCjrF1Rp83T3/XhAaXNVU9msBBpKNjawnwsUUj8gI0JRbx/
+5ehO32sQm8wkMyP/8iKDAqBRkDT3RIEmLi8ms+ZZRmLwGBkSZZzvOK3A5Dder4bp
+dIhOOetvoN6Bs9l1i6Dds64pwsy8IcnLLeNmOag+Qh8+pVUBNZ1zUV3KSizRKh5U
+dyT6VMILd2EAUJYLXs9HNFTtHZglRb96jQ3rkHGmAepeIVnJlNGKByvDUsJQDGl/
+bGNk5Ejz93ylY8JzR1GaYyFVIUU0qY8khbo7bSn/o6II+KjyTTyTkV28jTSD5dYe
+upGHOzmqpGi3Pzaz3DXpbLcMzwYrMP9FuXuqkVWToDs87DCfGqskKtko+zlTV7/P
+eBILwUawtXMJfYntkV247FffKgS3/BNkgEE+iNthOsFMSoqX/3ESBKJdJDfKRH0J
+BkYL8O0I7OwYzfU3gCWVZ8AvAhd+nSqp4H3QUK0QM2w=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem
new file mode 100644
index 0000000..9dd5b15
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CFB,3E445502677C77AC6ED115F8EFD9BBB7
+
+fJXVVcgxhZJXZANfEWDbVmz75ocICvntATRNVgt92sHgl1B2c4cgQC4Xmu7WM/Bc
+ocUlcSpWnoHtWRDumw2cwB+fDb5k3e9qb+aL2juzHkK+kYd2mkRjW8KSG6D8HIwq
+fpvV6NQmVrxI5+n+uabwfil8Ecg9V7GD6ta0QSgt0lc8clp01se+VDacX1uCB7zG
+NtJsr1wUM0SQbEWPEcpLUoYfK0qSO0h8fpnagKrNQLfzFbk85arkpD9XBzxpNO2p
+2fYsc3xZ0RkFauSZGt6ehu0jh1TZNPYDURvSn3uVrseLyR0Gt8LWp+hjIUp9Kpo2
+fLUVaH/7wxpdCAYzo4Ub/gHPfbxo2E5qYmE1oTJyAHplaDqSg8pbwJofiXl12gMM
+IyIC3SCHZJph7xqbKa+W/X4ChxYuN23ZMZ72cmqH4tH/j9IpKrpWEeqjxaj0EwDs
+R06Sz/qAqs9iDMKTkuFTMxGhc09DV9sN4NYczEIEas7gploOdryJGMCM96RtMDS1
+gjW21w0wyfqa7ogsDJJ2/HqKL73Zfn7l0jzmqya7YwcToEfKOSP+a2Q/y3Exr4KO
+FY5PLwKvpBaFcFzJoYhAaPphUzzAQuQFgXj34f4JU9bAXbf7ol7Swcv9JP9tN/mF
+n7z55BbPfC1EiyGyDjeUDWw4XIYF6LtRK3lnvn4uSZFXLmYMJJthwwC/yS+D65LW
+vsW9uuQ2qEfEC3hVbMPP+1KMgRkb9CVbSXBH+B7UoaUkGsJYzdSDeHZHbwiHgxqH
+jb6WcjtUjh7W2VO/MnHBrLg8dnC77OnR4IiqJq/6TenuSu0N/4mm73SH7BtYAugu
+ok/2H7GYfGfWjOnd+QvG/Vjsb+l9gtB6SXYFiWuThjB/sU4kHH8LUUOmGRlC3NDz
+w4pv+cR3tS1zX+evPL0BsZ3ynDSGRbMpss7xVooxIPacFwDN8kHUnWvIBpQKAizq
+blt1owc97vidf9OnZxUMpzw28/PZ+y/vRYSPQrde3kH8mJmu1FC6tLZnqzuCSsgR
+SJSr3/8qqSj3XrAW+nj0Y2P8lItNdFXex7j/RuX3eV5QIyK7uY+z8ZP4gf5q9w54
+p+dQi7Vx8acRjbsU+r85+MRR
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem
new file mode 100644
index 0000000..c7608e0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-ECB,C625A2E97BCB192B31A8E33CB0CD857C
+
+jM0PVjU2r063OACSZgLkaS9ppOj4idZ9hgkdMi58Oi+C5bfhZavbjROyxCG0EMGz
+HnAIRJ4pkJeZTnGElmOEFbaNPb42NAvcrYXAP4XNu5FbZ2SqGKwRnjjN8z7s8+Ip
+MrCyJsWycYy2BNaksJRaDNgazjKgqQxGFlQPJ+j99E4dk5QaduOCrf6YQ2G+1Q+m
+2/uqVujTwmverPnHDNhQI0ZYMY+l8+oVcPHIY3TR3ufecvrGkjFgKH0B+/L7gWSd
+ASvldEnWuFtPMiYnqCPtLgJNKSXO2nlumLc4Gz2ruvYKI1qGPXsVLIGnxISVLUzT
+VQz7NrRYwlvSLWdQNqbrEPvEu4q1KstqIkiPRoC98vG4+VRkf9AXAGqxA+vKYktP
+2Ui/SLhoC/seh9pxYXLsmqP+8bxcNM3VsJQoUUFM2PtfyvzBtuQ7mJQTSFSXgBym
+qXvzx749S4xOot+H6r/bCh8753MMEsgsM39jBsRm1zbaBjaNFG0UBdfFigHWh1zx
+4I44pIHu1AQDexjnfaUVrZFbys0CtM/Wy/3y0I3+mar1Wg3Rc1XL1PJzwDqBoZst
+vg1h0L5OPV1c4CekFnAEx+VI6ImxENoYtZCpbpt90kz3GxRY/eS8roS/SRJ7KizC
+p9bWEsUMwJ4Jl+xvV/VtVG96nKzlU13gkI6lMATYzImK4Fh7hH/LBy/UhNVL8X76
+3fo64CCwE3YkrWEmBDdxt/K8Knj4MUPjBgy/ETVRC7ziG0rUwRSd7zLOoEALMHig
+AtNX+juPvPU7yARw317Q9lZXeytf1AmGiFGjYZR/mduAa9M415uWm6zutIJEz+q8
+KV93bm18JUaQSrX4D6m8IgNhX0EfmRYAIFnB3rv+1rsb61q+4USk0L/1vKT/fGGm
+yvXMCA10N50wGS4wovMYQIl/giMEU8e88f+gqImU1kporgESIOUYUm9tOZ80w4R6
+ITlKCzRuoptMQBGZeJIWfWNLxwYq7NXKpvjNeSOeOqQ4fxhkzEetFERG/2hnszmM
+pqwoZBZQ8bb+T6cmJD1GuxoO3ev258WIUkEZTkFYK2Q/+QKymPZO4ATSAO4N2UqQ
+4TXRqUs4i+1f/BJU0ahnSgmzrynGmskUonKxt6T87lE=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem
new file mode 100644
index 0000000..5010035
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes192_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-OFB,7E4DC037A44E5DEE4E005CED36B18C16
+
+hvLtWTLg0+cMFDo3jN0yZc8S7fE6cDdZcBK0aRy+Eg+9kWlnmR/VYqG4xaich3VQ
+wkyhNpBSAoUHY8OKkB8hYsqbGkuKxQ6Db4IJlahCTFgb0yO2C7pUrtGDTvmXVq2n
+qJ4c+4CILeyzIp5yfy0dE8CAsZZcLEdSpPvaNK0VPZEPhelm4WdqqLozYVibR0KS
+2BbVO+E7yHGC/G3xtdbduuYpID1pLwyaebUCNgblggn6FJ0G2+Iu7lndmMU4B1Wr
+phvb+Fd1kL5421u8OOKRVLS2yMtlzbK2Mz7NclEzEs1m6K/xJUzztxImAxElBiiB
+YfOw5WLy278DuD1GCBkSuAKB4XWUtlq0+tJnCzAG0yrdMloKH1m+XF3MXFiRTXgE
+k08PcZchoNgGP51Rcg77skATP9OMamcjnkMx1B8YxTx9O5Vv/oSIjGQrr+t2np2t
+JU1dHTr9QrCeadSz+My0sjlZrL3ZisAwBbu6C0Zta1P1eB+i8ORZvm9HvmadcyyE
+y5oQWv7XwSfAQup/4uuAJ8bQBunIH/ajMF1WmD8rzLcUjG8W0rnBWUtjaxxBdkWv
+xBzgMPm7Q+L/5yhL/TMH3dkUBq+Cg5VQSe9EspNRGKBUgfKYk67Y343Mv91xKtX8
+8Tmh/WlnYXDv8QBnFJZXVnf8HeSFHsHDzfTgAmWHdhisTNwmgSFvBK5ghvhvkbXI
+UIPi+FgeB7P3ccFYnmoMq5qgK0Ki4lU6v57soDrjRl/NttfXdQEhLfWO1zXNANLk
+lqEhJSvBPZY4/FiOW4kNaZg2oRswz/+Bmp3amsK5TwBcI72rnH6SW5ADqPCcTP+h
+IrH4L9wnhOXw7QLk/h58JwiEc8suj5n0PJPQeHKajizd/EpUzVAuRTAl4GMvxLCY
+rALxeRaEXfJH5i/0UQydEvdU3ZP/LTibAqStXyVlSBZmKOg0GNQ+aAiHZyBnI3oq
+QuD0KuJi84ETMLU2baRydTbVlQDr8O0vxnCNlPkFFOqVpWyOyBgMctUfFJiM5c0l
+1UT6dc2F7NF5WOuoDCVw+Jp974CJuBSRGpdQKGms1Dvjwrtnf0ycstswXHvp2ZhV
+IVeCbT4WWh4f9bp6STkdquSc
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem
new file mode 100644
index 0000000..17289b2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,307CEE18F79CA333A38CA90E75B248C5
+
+qyg9Q1cX/FGOoP0NFzrCRLwmR6bai7JzDiCLFCthciYkMIWLIVzvyTg850YD3dw3
+Wusli8EQJig8DEpFSM0WBc1Rne8U4168nKuRnFUaP+VWuD4UpNDt66cT6dMoqATD
+kZGdd+p8ReO9TK9gO/ZZU4R+q3OUpjxX44szxj/EIVSgphi8R0rRSxl/yFRnGHyO
+xfpM9NxgMvBYlyxl5w1Lp/ictuF3D505nF/uuhzGL5a+WWhSnssMFHF9vxXTu21/
+3Cy0C3Qah9eV/C2oyAU7GGsXHIfqFqsgMjQN+cTFqMyFeg6g0J7hytDAgZVBXIFw
+UuzMbxUUZU9VHcZzwqstkg5BmUI3sgW6gibBUzuJrmo7uLrCvHyj9oehSMqeuPUC
+EXFqhw6Nb+jZMkvW9J9qFYG9eg3PQsDErIdVK8aWdLrLyc+O4gycOdMbR8aq/3Z4
+TlV7Ye650EvQ13bwZghZyKel6Rjt4P1MagGriNqCcLVVsyrRXAiqjq8cyJgYtoXF
+1VMBZz8ob2FH9+kvk2sb4+T22sTYwiqAVaLnCsuJ4dmS5wdBrhfF4oyHYV2KOVgG
+64GqxiF9/whvbAWSM4cU+KslKnWGZwz53LKleafrgeFJ2P1ldqnl0on5EQ/m9bzt
++GSGwzZGRmhf5NoyhaH+OCkq/h1UP+LZ5kDJCqH/l1JZbvJQkGNKzt1OroW17GnQ
+EgihXAmhy/xOAIZkz1XKa3bNvgS1F9yreAxJAvBHB0QzZ1HrablsaTKsZOtY1Qvq
+e2OdpJFm+SrI7RUtbp787Yl9pH2cLEdto+WH8gtgXloS+b11Q7broE42w9MIJrno
+kzs6eDWafSExTvpi+29OJEtK4PNezmhOxzTUIsG0/8d9Vd2WYqrLD34ze68X8qUa
+CoIXYP8VsQLoXVzX7VnMBYTQ+YOR0Ntq6pRj07RbJrNiOt8qcWGslzE17ERuCr0+
+ZFTGy77KOksKjLksvRj4oshQjRhVYZscPNnwKODFDvOPsGFjDoU2Sg+W8kcfE6Bc
+1RQwk4N0cjkC2JXXk61QQjh+efWRBqPN6va+ixUcsZSxndCIoBk4qtqtsyTFEcC7
+LdfCC96RGnXlvroiPHvrmJYN69JAyyRrnhiYfaaC98s=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem
new file mode 100644
index 0000000..06718a5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CFB,337D3978222A1367F5CFE08611416E9C
+
+GVmy9WG3oR1Vpfxnfpv1hFvXGzBgE+c4jplSw2BAlKnbznCPbZLc3WF/ZMv2851O
+iE/8sdcetzoAlm3jGPoDi6Y/FqMFmcbqtro7vUz/SVgi1HDI0FXjOTPtFe6xfzhv
+84qt5lz5VAUueTKFXEZHqM9tV7lHt1FX86VutNObn8pE7nAWVX/Xvq+qWUsEx0ik
+YjZjLY696pyz61hnxZE4jKZLRx/9a6vWYaVfzsEi2FLw9qAsw6ILp+xDaAeKa+Il
+YVkgDPi62NPr7cRX1WCiw+/feNYPgUfGiBNkd2mOnAr1yOXFM+YALw5V+q8I6ZKN
+k8R7skAzRZkwTJ9WaaFGD/UypYmhe2b9Jp2n0BMEn5RpW4o1DTIHmfMSUmUPp5w3
+HjbtdDUWIiuplrz7mUE2sez/3bMbcoiO2Ym9SInJKBrMFSvyasg403u4QESYQhC2
+Lwcocb5ixXoczHjef3CogL6BhL2oZwXCl3OBqpMOJJJKXUPRhN8bvgV41UIsiGtN
+TFUXqYdpbmMkxJNMGiD3mKWpSm2MMdQYnRlxNh0wXLi5sHckD/WS4yFrNsCIMVDT
+W094liK/Z7BmplY4TyqKhsRlFVQ4VOo/W0WNh7Ayp0siIfo8vHDyoQsnUkn/EUER
+UZG1lIy6/y1RSg15GWpdi1bvT9URjElh/U944LSYD28K2VU8aPKaRBokk+K3AyR6
+YhZRCBr6uIVZ8HDkBL5OW0eP69/jdbyc4MnWRa6C0d0boA7N639j+NQz9erYT6wu
+RkInmBbVfxQD6HLkMwiuU23qLP+QQTLkH7rQJmnRPSwAKEE8RiXWi4/TnYW7d0AC
+Bj8oaK6DO+J9t1pdj0IGluf52iUwAOf2Pxwvu44ovaF+yb2n3P7S5maDGLTV/xBW
+D6nEAct9cYj22/aRDTLdpOfG0L242vjQLnjrgezBLraa9eTy29hR5FU5ACH5sB72
+rxUSwoCHCJuNFSxC27QwZqeCFw51epwXxLv1CjqsQi2So12qH+vFVtL/1YrFBct0
+dzwbdNk0S6UyPRqfiOE/+Iszzahmb/GgskPJdfT5Y03FnpDWfOotpaAebrY4t6kz
+/gs8pxupvdKw4eWsxVCL9KOP
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem
new file mode 100644
index 0000000..ab0f64d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-ECB,267E98B92F05ECECABF28790E81DCFA0
+
+MkVFB5/gKxAksBI/g96MmN+ujdt0XFXC+7MI+0/OJ/H0LXlHlLpwfGlx/Je73Imt
+rOZveXf4I8sBCF1Z0Fhzb3TTTDxcastJGKWAVKaPzKkWdxNeUjx0kinbrkM7Spfa
+yG+wW+Srtfyi6LzEsbCduDK7hzfDnLbgKymdDeP0TVeJzEdXgXcV09a01GA+CEVX
+aHesQLNHyYm9nxFxK0fAnKo5r1I2JsozSWNTG3VNbiItxtfoJdXTn25I16qXjKzn
+MOn/A+RBpO+P01j4uk0q0SPJMlIYIX+RjgAoPiI5R5vSeucsdUJo1sWnSfqLc4yP
+vUG5wD/+lYrxsXiW61KdwIg3vy/ty5+GqwNgNvN0FZM8DvK+NQ9K/IpoW5RE4ioS
+ZNm1JpeGJiywsBf3Pi9mwR44tTVY0Jwa/TTQp1kEYGjhYXMIEvf+LUHwG5KO2wmD
+kDediMDUPaUx9K34eSpgIUln5d+1viMpC2VcDIg4tYjAODtGRxzgDUr3mbuoVl8f
+GqusTAdsNoIyilY44XxA2odHa4S8yXsx1f54P8fRYbA4Xo179LY1Nh7PwQPm+rI2
+mERkCsvns9jP1zJRuS1lYW1Dqjtxxq8Nt5RAsEwKQYLO4DfsuMZPblEXPAwSGb/N
+69xNs8ZFHm3KT1r7FdUrVpHk2vmqsetNa/g2wRTEuBmRCgrtTtEDWgdBNtDoHlBR
+pDIWgwNvt7oJIU0EbQkUgW8bmg1p7jxXN8Bk2QKZoOytxA4TB3fR1p92VkXzrkxn
+l+Z815BNfqnNCU5nNzLwk3jLgksZrDnLu4sXykIBC/bpP5fubnT7iJYh9h6ZGFeY
+QLUP//ssuZM2auNjTVykWUtAiglROzxnFZjMXEbujOKbm70Uj3YvAHjoKalkti9x
+MTj/vpR0xBv/iDtTFl12HIg+IEGL1PfX4xy2avvJO+XGFD4zcnrLfTMwtUJQjdQH
+dUMWP8VI266u+B6wGfcrhdCYqtvuLVUvbISU3YD/tP+esXh563kPnXd2UuaS3ErE
+/7Y/hzyUkDjJ2g37Hq3M4wbaEg/a6osDtfg73thDMadsbTLIDjHKgAgBv4umNtA8
++EaP0stzRH3ayHL/f4I5bHC8bMIAumKM6zap6tBiork=
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem
new file mode 100644
index 0000000..7192ffc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_aes256_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-OFB,A2D4D65382905DF6EEE7A315B10CF2D9
+
+CpLeywQMv8uZGrgJYM8rZ01awWHJWH/ZKkNi1rpQhaI1BAShQbIUvpY1IsMLa0/E
+g2+oj+Aa1UE4UDsAlzcfsKG9QHS8nOYWuLpU7VAyjC6wUPn0yI0sxxKRd4dmPIgW
+w3r0xO187yqLAjIZCj4y+3ANCjw+rLpZ5Zq8KAN4j6H1NEmzNoNVQbwY0hpsyxwE
+Tg7TkI5IyNKQSQC48EuZh16cJR48l36gzFOmZKr47gzS0zivvED4Vxdaey+WZkoF
+1XW4VbQGHRnLEn/I8rziic9E5pvvcZt6K2NwvzXrkS53ufFYZcgxNRxrdM4yLz+r
+20Unn2F2KqumB1RAliKo/PtudO7XfsPNc7rbF/stGhlxDWTyPU2HMX9tw3JkWDfG
+rRsG4RJOQgsx0Q73/7XPhgu1J2Wp39a/QI/IHwZ+rWIerdUPhs/MRRPoduAfSSZo
+r2z8OPJAlMWLwAjmmKDGhpTp/21n9xLo8tbvqmy8Frz+kAxAHXeHCTWUbxA+URKb
+s5NKQALX3wYHT9Xq0A27A/Zrqs5elqc/IQL58nU/Da3a3OfPB4+MNWeWU781ohhi
+VkBgMRbnQNCC8OPoeMd/At9GDEEj1rDxx49pJdMMwxXS04P43LiuNSmndCei2cQh
+/7cho8YTbdgjKF2kVCZvYXBVsu7Nn834kJw7eMH6slU+VM45jTkOTr2uLzKWrBL6
+YONiK2xdD9NlDcTsX4YRkt+dByJEcDAuvprVdnLKpFXAOWDLW6e0o0siuFIGBtgX
+NR5vA5llpOkladJk+j+dxX4u5Ql9KFPtD9uM05ik5VQCZN8pxy6On3GUeSdoAE9i
+i+rtgZofs39mZOTxhYr+Djnq3WiWntV91GImwhqiXxUBI/fs91+yy+FWphpGORaT
++Rab+cyvauBsdTAoSjjd5cNXXsztfDxEhLnZ1yWMQZxVgV7tcLevVo7e75pSZrN0
+/gMQAH1Fcxtbrdzg1fehLiqTEWp14lFyDCkqAqQ5C9niCqwyf8+6Axaukk4ImmP5
+n9eIykRezLizjA+GCe2oC1jXpVEEYVzOJpbBAwZqk/jlyNd0m01URxvhOaW1/M41
+uWDeQp7ljJrtiyMqD5P3STGR
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem
new file mode 100644
index 0000000..8b71187
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CBC,B23E9DCDF6361CCB
+
+BTPCHNUVRgsKo1up9Ktshx00vDANb05S4S0LPU/wzG8sj60db3bX7Uzr0PPy7ShH
+1zPv0PECYla1dh9nVBPOS4EQE3uHyzuDMTg0AsiR8TpysuI+a4y8XJeAhkU1DTD6
+YzmaodjbCrhautYUCzvcui/sWWXTUSWH/yrFOxaaxLpccacCssGlPc3Tmr5brPmO
+xaZvO32ii6z7WAP/WmyRoYH+BSqmUBhObolifBD5kg1ilPfCk3xMtz4lbJRWANsS
+r6YWPwo+qh1TIQWw40Kz4oQOteVNiwh/dvYGxMkd9Gs4J9nY5deKYExoWlYcci6N
+VOrGA6HBWzfFx/QWWGK77xE8yQ8HeeZUgkWwYoSyAmxjPWgCj+BT5gbYV3W9E6UR
+T3lsKGtI/lMW9N0DVcLdur0lLIBFiVbzxoUAL1SteLJ0mbu/Vnk4VhI5z5mOmSxo
+bU/HElXdjIhk7hdTU5PMNSKiAsxNh03NiPsTpEASMhz+oP8BuJZh6Zi/K3qMYH3u
+6BYmA+Ua23fFYd/kz2TclVwiQ1HQjO3+9l0aSgLhHFb3t0spYbx1Ld5+bAb8b30Q
+9w/fNab1mB6hFgaqruPErfI0K8BZ845oAiakZBfKnTRQxAlKNY5gWvSiPDWlkfIb
+uSBW6csh62iQM1/bcW0voR21NGS+WdQ3eg16vv0HMhmEXmEvtAuCGb6ZMqY117s/
+VciBymZzwdLKFjCqrLn6enYrT7uneOoq/8PaXD1rdMuKGL4W2LqGH+Q0RU+1hyBJ
+7ipTQqystqi6HUU2R1/PI4K73X0MMTB0Jfkd81S6GmjkMYCFCHmHXCdNULjbjzT4
+gppgVW5joIbLKNPHJ78lw4BuMxcAgptmtQBADnWZQNF/pBnIVAY/pdHgreIBTQ7R
+KL1/ATp3+gtGd37FOGZilhq8C4ML+w18M0iTUUfGg5svUvmtw+NpNWMijTJpu3Uo
+KqjMj3NbwCwu2b9qxwalC3qWOgAJf4Z784+i2GOvACk2Mw2QyXoZV8Qm520M+idR
+rj6DIfzEf/86TWH9IrGukDbJNB74QHgdXd9upyt4sL6uHMxPwz4nnhBB7I8B/Q59
+oB+3CBpYIANihDscUbiNSsw5/AXNtMuA
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem
new file mode 100644
index 0000000..8372cff
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CFB,A39496D20CA5F694
+
+A9ZO/WPm319cQ3hoxaEsmuGVDkMVhCuRzFfSWC4hVBsxKHd3FIw8xZpGSkEI7+aL
+cMtcyxTQn4jVV71Sw3vyb4N1+2i+DAd+63l8LztpTBQi1o2gTBqmqL9esV3shqWB
+JV7uyOi94olPea0Rf5PMRXx1bAZs9U0TV+5XHAQxM04lXRJajxiN9LBZ1OMRiUVu
+SdoHdXh077ylUQmgDaGQktWYuVH6leq7Yc9CF3nre6njFiUrpk61iPki7+/FgWzq
+vToqiYaWffy+1lB7sXcL88BtFaMWAOV5A48Mv05miTb00VbJqdKL+SDmu6j2Soxi
+Qk3k6Le0heXFHqqkURMKOrr6tepqKEjmy8WTELwMnuT5vNngMqDKpNyhdsIEJW69
++L0imi4fWIelCd7PMI1bbPAp2QsB8Rndjlfj3irVm0AtubL/rbep3JT0ezukoScd
+wLYNTlDdaLfEggry/1kYvPBMolU4xqDxg7C0quwYxLuycEFzU2QmWNtRn0xkfx+j
+ruApr4getT6q2fJznW7coiW+OE9Ik7JgtYUGEZuWFUeydDHa9PiJ34w9t/aw50Sk
+arATzKH66zM//g1zgzg31SmziKeE375skyQr2+1S9RajmdZzEUDL5ajsdrbALflf
+UPQNr0YEF92DRHsI4O39L/+k5fesiiU38u0NoKv5DDRb5T1lQeesDZCZBowQP5KP
++6o6lnj8kCeccpGX/eUukPXFl6mdddAJ/vLptHC1zaRp2dlKPRfedZkRm4Wduplh
+vQ+6oGqkjep0Q/LSRcVP69m91CZot86lAn9Ct0jfJu8o7Ua7KBeOB2k/rx1nUaZG
+BOjHQRaSvPA7FVKCP1UlT0GR2hTb/VcW3UQJ7fCY8E4hc1kPfoa/T+mf0JrHtlMm
+364YQh6KLgcsgVjsPBXnTN1+POH0Qy0xp/0VwQIQFWKwU7gsXprfs/uYx0uD2Ev1
+w9kIWLovIGmBh6HKptqTnjtdwhqueez5kb3MkrCMi3kqVmV1TEQoklz6eBbloXbX
+SyR5jivLmuaoCJOA3oQ/A+75bwcvUP4iULZbdTpM2rnURyljKNU9Hwxim0neZ0Zv
+4kiOZuhQKkGfj0gv5bRkDAZC
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem
new file mode 100644
index 0000000..58acd6f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-ECB,6105920EB281329C
+
+ungL+71R1VG+DP1CKuROEP1pESqlLeGoX/vupWbGTWR9VoK4v/9e1Bh96r+hEobm
+LvgsV1xhWrnyRMMw+W5bSJCfBH627SxqHltgxPhyKCNAf76cTIAdxxXgLZAxjtJi
+mjuBDTNHdJ8NiAxJKLL6dr/hh+Vt1Lk9Gr/x7UdocQnhxG+IZLDSOFdXnFb8EBtK
+kmAXXyOL14Rerywi6pmbxaculi/CihuFm4u6GXvunFjtP33eObzKLRub5ktbCtol
+97rbDoAAUsPPm4efu6Fs/3CE/BfvjUf+cmOYu6pIKQil9VHtxXloXwkeykI9Kl92
+uZVT+e9WEn6oZslAzCnjT/r69+V0Bf06AP0zkdTK7lRNBhmcR9fAgHpxz52GC2Bt
+xsqEzU7d+adCy1M73tT+bA2RBUnbA6BoCDHkvtmZTGV4mkAv11tVxU9Zqeglvi/w
+6QVDQYo/b9U8GVkQFo0oh4xNaAUNdT/i1OIy7d+6UR8k1S9+r6SGVwS3er20trWN
+8mAJ3dWiy3yLreggSqEvwHSpwrUQP8uxdTZOlFAy+xmwuEb3AgT4/sHQN7sJjAN9
+ISdzp+B5tBbM3kQgvEXUZckVykM7jgyv7SJ9DoDaYXvlfOVFo1oM3aWf57DcB8KH
+WIV94r4USVElJERYHH9sR61YtTi2lIi1zuAQZKCf3ShJcgU+vh2ZZ3vRPQhAMXjZ
+0Doi5uxi7HK/MVenO1CzNmsc6XQtyTtONqlJVmBoSq3Il8phMkMXnaOeNrQsT/1X
+PzbQ6MpWEr2WkKsQn5hNA9b8BIZ+cwk9zeFbhwLH5ewjO25BWJkFra4gGFJl+HZf
+vMNFjlnxuMjqM+Fjn3YH/O08P3nF/3ZGezqTCV8OJigB4Cdfbf9OrNtJSvCVsH1q
+YB/3+KOO5mKObH0Y+k1pvwZsXMkj7exAEHh+nFLldjo7tBAycqUHK0RaZ29TOjqH
+J6/4SSzMTJL5PF9Ayjtx0Vai4sFrjRGgnvdd8tddA/bWq6JC5i0yWIWjCEu0+b1q
+q8EHdE39+gbANJn2lKsEAOOt242bsjKR+bblijaaEgZXHZyALOThcEXxn1RaFFgC
+4Iv+DftZrU8lOiEvN8w00K6GDy9gbByG
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem
new file mode 100644
index 0000000..2558ae4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_blowfish_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-OFB,56A8F965C6533468
+
+91TyUkVkBxdl1ZXkXezMngH3YsE2cuXhiEFySx+dWZqFWcOQ3S6izXXqvk9B5sZg
+O95SFlZ917dU+SFACzB8dqwYo0QmxvH0zaAIMBguuYib6YZVCd8/ElX0vyEEo68O
+9V856HAks6w5WZk4zTC/75skb3tdLRWgG42oBlXHW7GsL6y29Dy3xvaWHJ3vpKXF
+HygbvR/TiSzhWj/jJB6V4kCQAAm99yyMxpmo3e4Wis5AwGgf9XyHJx0gUCeyNqez
+i6UJMGnYsHl1H67ltpN13trIXRcXTUDhFTadRz/suaR1R8IEefkpsnBEPnJwBuPY
+tUQzlolPKuwbPXFukpJrhi7It7dLsDsw5DUYvyOnHkDXJ4vFAIplCKdG0+KLaYKJ
+pXI8FH6X4M1YbIPTF+k1dhCAz7Cz+cEBA5hfJfSA4p7L6f9NBPWso3DDsyAbdPx9
+JJkVPtu0ofZHzYuD9nIhRsXjK9zaQXU0szLBdtGw7rfmPp3ftXeBcXDnO2ZdXL+j
+PK6CJm0ktjnUMKY8gpWahUUfImwebQ8+uQYv+NNn61rtfCaGQWMStXaNYgq54YLs
+D5ImRdvWm936tNUCeoik0yhPVlriNC4gKswRSUxD/nNIetsPl4FB4DIS/W5fvWZf
+WYKwW1UlpC/HagbUVIuZcOrAMFTG+zLYS617lzZh7Y7K87GJH+jVwgbYSbHHFWCp
+V215NLfofwlV5pFwq8djbeEnBhKi9SbGlZUyaZKKyDoIIEnwaxg8BoModBEWHyWp
+OUmw/v81TQu6RwJYxl1C1U9n5w4yjtXr5oowgu6WRYXwWXZtevtLkHrhcuWt21ud
+Cq42ojFrb0GqIcYWDXF3Wjp4nLZ4pIqg5kadpJpcFYx+fcL++Jnxs9l8Ohqwn1br
+/UvY+gTmTwnICapIwovVjN6p6cT6MAok82oemWPZNPYXVwVkGewCH3DWqfeRYsdg
+6gDWeIwyk2Eqn4bxFz40NrNZaLqcmQPaJVRReCV7Y0jQuQWqSYKkBHgFodf2GPMg
+DRqs7doN2MW7Is6qjyc8CDDzPcSuaqUz0gzohupDfD1vAtuoC0X6U+m/8NM3yuE5
+CKE8rofcKcxmFAr52CUUsJBL
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem
new file mode 100644
index 0000000..f6fb1c9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,7D7F5AED62DF7398
+
+PvrGaVyP4qWxH3LR5bOjrjTZN9KEZ7eujPyBYWV8pE7+kBc01RKaHuOfntMncXPj
+cTvtvPq4z/Odrme5s5fem88QAoxB2BqM0VNviUMcCcAG+hgsYjYWjUDdSY+piAD5
+dhPcTHfSwgkA16c9pd+vNojdDKHEXzIci/gdrkJQXi9z+Orfb++NluGFUjAvQNlh
+n+wi72AVwFaSPfguwAtWAZNmL37dZO8VzuCTkhciHaJSZFtS1G5rLBIo4JzW6AZI
+PLEENN8fE9C60WYkfQB0PI27ksTS2xPF2b7MeaBwdPRU++hwZ2QwXH7nYlCWn522
+8wg3/QWuFIMdqtKaOjjlwvQxApV7OouRCxIFnolM8HvpZ7HvEVVT6oqcsJG339FJ
+Ru60QxuVsnz6ykuP2OoGTtGZNYo5cgBSpXrpUSmOp8HHblWa6+FSatNkBf5MxJvv
+pMRxcYJ7ftFCGgpKI38GgeBPkpv9Rr8PUplZlgnXkZl8trhjb0hzAAJrMqPkMQ2m
+rOgsIWF+gK6MdnZdSnY1DktPYSFCkfJt0BZMGBDXcbr8RKHeV1vJNWAPOcmTsV/y
+nwzv9EA1KHeMnT+wQ54q7jkRtDLIS+zSWt3qW0fJQzNR3BrMBrsij6GfRZ++PL3v
+4y9D+cDFVX6LMXUDLK8kxZ11A5rSuL4HROtNnIQf/MItKNK4Y5c4PAKAMGLQpPS+
+5dgmKiu6jAIKUVT4BOEjMJ0P03JZKQkPxVB9GgLQLGCq77vz6NaTWhJmz+qTdZoL
+JCvAAShdkVa5gl4hzuvKnmY9VftsPVlOUthuO4NYimnjZs6p0sXZKnxQ4J4BpbkX
+mX5Fs6RU0YTQphu2v+NFhcPpYwRiwn15CVUDW61Sb87HZ5xAzwQrlpFY0LI4TqE9
+6ITUYzgpVVAlslKHNePMcjTj78V2MImHlq7xHSVPEGkkPlsDWxG0snZRkmM9aAu2
+g8kqf8MVngWbWhxqXHA35wunnaBhpBxAgqE4r2yAhyfCJNF3B01zwjt4LeTnduj7
+1ZA6EPechsSQUGQNGBoSbO5zVbIQaRZvAl2MwPU1YWCCbjaiDDRp9bHhX8vQbI/v
+4TRfKX8FUSai83qORQ+Ncshg+gYkeCJc
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem
new file mode 100644
index 0000000..c3af8d5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CFB,6215481F0FAE54A9
+
+4ZA2xcGT6hS0kQObPwTWmluIl2wTnoL2jRMbxrr7usOZSLYISprcATZWieEKLsu0
+kNNzIptFCmRDt0b8VlothTS2jBIh5nlu9LqvaUlIrVuMEn7umslWrLK8JWnHVKOO
+dMfqNcgmYlkbEfmmXLtlCbfQHT2kVlopD58yxf26FTQ+27l+hSX4wn2uD+xFUAcn
++9ZxAWQDhi2PYVKqTTPfhCPaKW7hjYdocADnIZg+1mhH++8fPxlDmBQBmMOid53Q
+WV9LI4Fps90d7GumX7qSUFZTkBKN3v+E2ahnoP2bTBQGkqWamKFTc/4uLCEGlSWU
+qXaGCy1AwPa9As1+B/jLkTstoslJppqvOooWW2R1o7JHqN44luXXQPZ+BcA7dSdf
+zRcMCpudB0AwHBy3mnUNuBlUjsf4rEpq51HPSS8duYow2I127uI8m8OCoZCaUVid
+msxVMSJIiDCiBi18EfCjMfGLtQVxJefMv2hmcAXQXSRDJTEw8Lrtm0Mtp7XK2B0A
+v8Kqpf3x+VBc770Xoy0K1/fe5oLdvJrJOLO5PVcVXIS9B/DTqIQ8ObABJPZ1sCKA
+sV8XebteS8fNXmFrVKBTmHBpUY8H5Z++VfDtKZZUBYSOqbFT+UU/+xJKlKICzFTo
+YWsmPTgFsu0Z7/PMyg/rccrb9fMWRXa8et0JGoF2NlYu+lkRb/nYPe84oS8RzZT1
+dtWJMiiom4xRgENDhV6/AmA9IuyXT3QbDfFB+ntdyk94U+Ms0ODNcdA4JmEa/f2k
+zFjtEGWHPH8Quit+zUt+8JnWSSFp0mjyA2ZtEj/6Qg5rqAZMdlpTo7rcuYOTHScn
+ic/H7V43SuMlRAM+xx1bGrNzjWUugHrVb7Kar56pSRPtSOQ00Dmz7gB8V5LU63n1
+YX3faatiPUNRG1dArcW36o9dZ5x8O5TErPHRJNYG+96UNoAzHMXoi5thuRyVbzne
+FpOqgxsryobcht7fwHuYgUq92QoY2qG6qMwHc2A3NrVFi8lJ0R83SN0lOzLebulu
++zDvrvkkRyH14uoAWi/o5IGBv1yIkO9vYApntrSO2aLnbevht9MuDJqW/Lkb579Y
+LG/sVwxTmBT6jdCgTdpd1ExE
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem
new file mode 100644
index 0000000..d17a90f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-ECB,1040C4105685E404
+
+66Uasevd2pON2SFWljlVyWqmErfZn4XomzLHlUoagIwnQUEgCBCCpUscES98fini
+roGF/iaY59JnUCMieugke7/GZF1C0aXbIReqds7S6VFfu4Ni1OQTkL4rIauHrWab
+vgoE4+18OlWw6Rc0wwJ8NT/NCOmb397yTeb0w8VYERyzpwSLXxQ0BCOq4vOUX7BT
+2ABX0moazjUSyTO9BQZpABF2SshxaWFbAc3QRwH4QnO1bm7Pv7b1rvjrvPZ9LxgN
+fwjXG+yfHFBBojbEtFvgXRsSSyV5WCmAgYLgk5/nIDFSnRQGty0OuP+itX7SUK1I
+PH/ZjdIwezMKbyuon9D1AvdOEC1xiKEdmJCWSokm0djIVNmYbv4dtfrQE6hYdMtt
+C0LbsT7ef+jl0xG3k+WK24OsBVhTaqj8axIPZIVLELOPlx4EMfaFQgUjgqf5vPhO
+x6RSSRy+poFwtjI6ip/xu7ygqmcY9COXCcSffk1vpw9v+6WcMaYmDLwBTrTCNsdI
+7i6VJa1GiCrsn5o6ydGgdRNkF0N0sUfGnSzRUgd3BGd/fvxhBmcxHUnr8srrHYm7
+D54VL0EUsP33F1VF2ELl94GlWqfAj8NGBDkTbpUcqOeL/ERxdUWfX5IEc3h7fprs
+UjjjQ+d3GRliRs27m4ZuLtGeDEhDtlTC6qtKyqgVziPMwG46tcqyFzhbLCErHNW1
+07JcoDRc1LkXImSeWgjjhskUX8nc2/q5giTVtGmiWMQwEc7aYQ1wPbVAIGPQ4PE2
+XB8zvvPEaj0wXs0JjicrfzUBo6cRbdfmWIfp+ZoTUfr+gS/aZm+VYt1G7v6u7Qel
+AtoSdpN623OvqIP5ZDjOKROmAdMbXkxwwusVNQhkbdTzDYNy/yJnJqUUlhsN0VTQ
+y+O8Fz7Q7fEYIk8Euz3Uf/BTVGbLSNSA9n++CJYg1nam1S51WhCXRDckDLR0c4C8
+v3zpJvaQYW+xZUmlzrYRQgxkfzv4+j9W+kZLgvitQizXfTsuDyO8gwIt2csfGkaL
+EgX2+oITD/sGoaSoGknY42ePI3pPXHlhBjPq6ZWZ7uh6Ia90nV1j/PAcOEoAspAh
+pEdIAkFJA76qN9JBnK7lRMFXu/EWtBjD
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem
new file mode 100644
index 0000000..2d36cbf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des1_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-OFB,BB20E846FFFBD3EF
+
+WeRgcZKkDTSxqvtZvx9WwUZYqXUUpY7siLG1Vm5jXPaEFOEQhmvGuNYn2cwwUYKD
+RMN5+sE51urDgI/xk6jdS9oZE6IlfkGeQSUoEOOfPVyVD/0/E2G0QTcKAAWB56K3
+setBb2ORbM2ZhetYUp1scaLObMEMQ5LrZaqtA/jUd2Pbs9D2MqafEH0Gde8e7mXy
+1fGNJWlj8XtAdmi2BeDKZHx5Hu0r/BOTic++L0Sv66wbjHw7RDji9Rdv/vyq6DIi
+0v0ZCexiNVed4mqD/3+8eGQ2z02UD7aZPy6T7E+b8kBuBi2ouB4HqgexVtz1L9x8
+VBBOBdpOLefwCZlNaeceg2kSIP9mMK919hlH472BO615YB4ugaCilUNLpvv9T85K
+s4hTB5oDcQH6W68mz44vWqSwED8JcdMYvivWY+3/zBSUvkyI8+8AErnVr8tvTX29
+aBhfegKV0MbRRRirj/EcxhUhtfgbAtllZ/Wpo0LWpIsHT0GeUfWdUerbFyh/8Tfr
+OQzC14xoLHdACDz5IDrLaLd87hZrKDJOELvzoSugg2W9NAzGbfoWJGVlvZ0miZcO
+teULyYcK/A7Wcba+jmFaXMrKVhNH0IuGcU+Pf1lYcchjAsdnrFMVRsNJ99QWlN0F
++dTyRgaiCInnmJqT83fI58dMmaJPpMeW26jItPWZWAA0vlQB1RgZ8C7i7V4keuVc
+0PYolX8WpLrrpUpJKOTdW6rmeHokJC46gOZoXEwZCSKUUgreROLgRN79RMBHKjoj
+0vSZWowgH82fNWYWQbJk5z4ldulWEVye3tQhRNsZarAWPFEteiKDTSkawmBpaA6q
+dJWiA+EdrVvnNmw5+xkbciMX0nj4xKsjRgPawdMFZaZNE3xu2LkrfGKDa1ne3JdL
+nDeyygGRDsl93oJ799maHaTLDyub0CMdyf2MssPLFklJdxwbtxNzbI0gt0NhZu43
+FDg91Z3hlAjg/Q2h1dVM22m3pnju2ygF11HUQdNExHlv5w8LWMeqWQ5j7WhSbM4c
+s2v5JURZ+jXFEf3jCs9h6pLlQNaipDkUQA/6DKHf0VbZJzKxBiRCwSP/YuQ6H3yP
+dHGRAd5CQnNc3Vv+yyRqQT56
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem
new file mode 100644
index 0000000..98d3682
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CBC,89A720DEE88FA71E
+
+ozUacsBZx7E1NCxbVYJJHQ0VTWl8RX0z/JzYNP58zcCIi3Cab2qlUshZP+Zb0Na9
+vlHabEqQCGsP8uLzneN6LDDaLmf+ucxKvCRrx5h8wl7DQcA5cAQhGofZuqChPqLj
+1lExS4ZaAi9lRL6aZhf6rgI/apkj+9Ky89sOqJxNhj66NgoOOh9XH1Uvrffv3jT9
+RxeVv5qYcAgfX4aIAM6KjC6iTZ8NyWmIoc8izYQycOsSAn6cqtdjmyc/264OZUd/
+1Tj5PG0q/Kinh9UBJ2F+pQgU4pDlWczXEIwtnmJ2mWyHBe2zuGWtP1uQFUIfwkEz
+KDTTFB0lm/00Xts+vGXgy2q+IvhqlOXfCkJGcP+OArLoyE8cu2xU4KS4qXUITSr0
+i3seUuTrda4aqrfyjNuM0tL/cUSEuT7aSlKdqSmRtYl9fTsmbCbndLKKuDJnxUrB
+ocXfuCEZNMQ/q/8DvwIX3l7RRIiJwqEg5+Ue/s2FTFJh4Iar/1gNQSApwToFHHhV
+XOU0pLY899B+1z10Nop7ELgJEKBK5+zMMBhB2t6nlMU3YojAH5qWEPa6D2Wr0Wu7
+x4DHqk0wEB6cDZ0PZGlWNOBP5bDB85GehAWKy73A73wYZCi9eCQnLh1Zjcjl+6T4
+fli2K+944sUKaUnY8sVT/20aXm1CRqNvgLknZMsg/eGZWX5F9+Jn/MviXmsH3LfE
+6VShEkNTFEsRUqF44Tvd2BZ6pObDPRDOkMgapzqdubujUesvb7LU3yNCRPBPngRT
+ZTXQynnbH0yfnFm6+0BYWtD5NeIzILwZfS6IRMSsCBMas5rCc7O2Iv0yhk/8K0f1
+Og1YH7pctbz1oAPmN/EgKZ1K36GTt33zfrwHpmKZ0jOWF90BQMgZ9dL+VyOMJYjL
+MiyetxwDdiP5TUUAKxXdr9t3AvxVPxL8aVjLb86kJ9HD+IgWUDqiROe88sD30Vww
+7R3sQhhl7drDGwUBj5MLCVhtE8Uli7HdaYC5CvuvlCAQN871whhk2gN27eqp81ou
+RB4kNaDK8qSn83ISnueg1jsQhUGy6B2Rx+rePxx3QwDsrMGf/u/tFJ1VcLlhmOJa
+svVKTMq88OAnZA1Hg6QlB03obSF9U6lJ
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem
new file mode 100644
index 0000000..edd5d8b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CFB,AC1BA482ADC9EB3E
+
+tPu6t71kZlKyKaRiXgAMCmyxL/P6dVH/sPVY3KDFI0FsAGoPZaD8s7BkLLOy30Y1
+66kmaaWiaPjQN2g5zMrszrXh4AXazrjMrmIJ2NksNXz7aiySFafyYjyCPA+LIu/n
+KnfoE42KYEmENgMSUV9sh/nlwYS8I6LWva384BIWaG3qnFgfZ4gwgiI/R+1/lPXa
+olOpnI5szYMiV+som2E+I8lgd+Ahf2rempMnuwyWTDmUvYWwst7F5bz9XbmJyeWY
+HDDaTPy2Q1yRYBRvLTm64iA0J9j1TpJnSNm0uIRTVOEIZfOwOx20tFjo7RREunAx
+mEm+kmn4AIYhw5RQE5XQQvD42X4MLyc0M94k5pQHvgJFypXeJ4VsH8pkd4bqfy91
+qiPiKdA7nWnbedExwiwSPOhjOLkmQrXjsMVmoqqexhckJfmNOaXYtnQ8cZc50HjB
+6ccsjyLdQbLx1KT3e/NgfH4VxW4/hbbt3p0HMIxTnwt2lNG3AoKmLlOYSecuA4PB
+EE6oOauIKyJM8pwMV0hfBQ/MUQOnhHG+dbTn0kW91fRZiVPPvJiJ4NmEwD3ks3jM
+pLYZRot1Cd2ksJ79G4NXDFakB2bZ8EwtlQUrQHwW/ykPwiwpqCCha1PUzgsmG3hK
+U8bDWWQMqXtpSmItno1mF0H2TZzdbLpRAZe2lu8/mwww1qZfPE+MLPnCp050+BCw
+Hbq8fF1WVpJvsE5CKzi7Ll7bSrJ6BslrlzL4mFnnGmuz/mbBIL0MO24FNyVGKQlI
+hEzGu8lgp53pG4oSUZ+79CWBkn8mesk6iEOWcFojLKrlhnxZ7mDxBYfDp/2Bmna4
+lFt53zmQHJeYiO4J2TEXOQxvDWvcOK/SnAoLXEhUCRP9vTQm2Ahj1QMmEVvEybOd
+mRpcaJXUOgirS7Ulwc6ZhW7MoFFnS3UluI+gS0oXRW6hCm6l9poDem4etU+IsG2m
+4k6MoMLrak9lSheB1uL+xC0S9k20CZH0X8Hj5atb4R7T5+lTle/fVw1RGdfil1NK
+/ytD+CLpSV15Z6VGVGlzfXTIXYgCIgbZpFxOZk2tsdUm0dPBjR/ZhdUh4ofaxA8K
+jE8HLuW7kCkvmEfdsJxuRVVQ
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem
new file mode 100644
index 0000000..35c220f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE,3D3D716B17DFBD33
+
+XDCVsv17xsOpLWONR8xKRYxnxvWs+bdU+2XCqoqH+cM/vR4+g4lqSPSAco0/LkyX
+q0/C7/BE7mN6fzUMiECYUKS2c739CBVwDJZJBVGbMNFexaQRmlSxqhmbQ60oalaG
+HZfpCLLHQvrOZ3O82aYuEfsbqJTEPkGm4lUn/5psQwudmu4qyv8GFR4wVpNcg9JB
+rDzesxi1aU6dgHSlLHrG5ot+lAITh40SCBQdwkcvixyDIi6l4FX2AyNrcQYmFGp1
+C3XaOn74ADLyo31Iy6rCb0KId6J+S+1aPUW2r1Xb6irI13/QYzIe8/fDfuyV7Ofq
+BKtHdu/oIfzl2X8BkuxJ0CEFxyyEE9majfItPnUEjX0Sn2PfOEwzq5LYYExpNuxe
+pHr9gtB+hSXC5t1b6ifv9PHErMNmBLdgLX/FT4PuL6URrn3LtydPcfW6XMkHtGgH
+zD/nnn8Kl1qXmkRbWHbREcOJB/O/Q53UwD26BsX+Sjwn2cfsgwQvZFzvmq/RwsCg
+Ej9FK80Tvn3ce+Kdt7LGUc9+KaH1OIn7qLcYu0Fhid/TzPCBPQffxpUJ1HylDaUz
+v1txJe3C//rg/42e5GUlKqf+/nzCmQeoaqZDG+VU3UKlngIYitlpwEq5fq/E8V35
+JeuHzFjYj0k9VNsOHY/4AqmEm9qi1yxb7WGINsysO+29RvfRD1bm2Zqhi/Mg7YBo
+8K1GowhW6uGFf+VCPORihMIxoT6xBU4xn2kX09EKrVdekrAi23QzslZXM6Ze0fxH
+7LlktJwah4/QFHwB5qXwmHq3lN4Nj1id+CElVZXjvbKvc4+mRd7VSn++05IFjTK5
+2r4FHifwpkGASJtVbF/7ZseaoOz9sHARx/MFSUp8kRZjOCzstWj6I0Fou51BTtRn
+1ZCey4e1eKVnV4F1XNdo27Aw9aZjF4Zn5hZfUPuUYBwN3W33l8FXRdYEoT/JpiQO
+8LS36SSZGVA0c6nanZoeDZsrPNtPJa8ANHR0QMwBDOwNr22uuJEG/nLvBfquG4HL
+Iy7nxBebe/0MXvsxK4OjjDzmYQL2msMlYffOABOVLCbtaPC/HBKUcmcpZ28WAzdN
+ArkPEcJFTgzI+hCAVG//uV59MkDnUZ+e
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem
new file mode 100644
index 0000000..d06c31f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des2_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-OFB,0472499818A0CFA5
+
+A+t7NfS0c6IsREc9+AzXRaMGW5GR2Ao+WBBxXdxNJZ2n6DWTcNHYL1VZsnVOoc9z
+N2PBfTjYQkNtehp4LDnypbooUI8gJ98T33PLkJ0/L03fs5iEiULcrpBLGc9gsNoO
++f0JcI4xNfE7bGvtveliBWBsn6KeCdwrdcOXziWGQCge0pftf7m4HZ/t/0ISfjXK
+x3ftgiwrvLSnCHfp50xXdN4FGRaIj/V+C50efu/hkAaZ4rCcTxgEcvi+TKdDjmcy
+MfxWmUmeGiT0MRongCZB7XH6g4sI3nwiDASLzvZ2dBysLD0wOhR+g8yumSH2RW5V
+rTr7JQANZzdZm4MpOv2fMCHzDcKEtPd+OlYMHegwE3p0y4CLeYByT4IdyKHVLiWx
+lwAKtZ15VlREgXqBIgrtG5ooEIIjdlabIckAhRc5yOX9sXsMePRyPgQSnG+nSbQ7
+6Y1l+3XueWXjsnr6SIXI5wbszM+TFbZAU6d9tb7B63R8ancHHSUgAbmSL7QpYZxD
+oNYseUzgPv62oMbX9VxiWJ5ZgwzS+D0zGALw3Tb/YVTxI+/VZ58ITZ59I1cg26HT
+H3P1thNPIee0zz3zewMdILgQLh5RWkJhn8/oawDhVVPBba72uw2nGF2aXwbLWx7G
+eJ94GeikGHOJby/J4G+0D2lLlI90jP8KB2fVqHxENGKSMLjZFERGvpiPTgHxWcgI
+SS3ORTxuJDzqG3qFfMhFwQnq6tbOsny27scEQZeNMGecfqGLWE+oclqfKKDQDm11
+JUQnsnFAT3cNFyd2bKefeN9co9NS1UTUw1m3gDH29kwmggFLwSccTFobrIoh5/le
+qiaHdEdmd1Fvp2nMAVufwmb6G1dizT37benyr5Gzc8CHZUMibFEIhjkmG8RQ4dyb
+Byai6j2gf6rzsbKiVtKqgCgMCw5LG8xypzitCBc0+DsYBnlAyS4hXYm41eqMtMsF
+vrP5uS50iDbAMBjuIpWdlRewjxEqiLPZofjbMGwbrvDu45LQ76rwLww5OUj6567b
+FJRcXQdyt/bWqB47GnAZq8NABCtY9HG77nTgqstOqYOOsdkuZC33JHAwTwa+b8tq
+2Y7Zo35CmITqLxfjr2IT5Yeu
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem
new file mode 100644
index 0000000..f73edf1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9BF24F7ACA100D50
+
+71AQTQlq7BkcUMR0+Ghc8O2ykT347aaFUD9BYHXBW7SzEq4th3itEQQ4QxflbgR0
+2XZQE+dNK+s891XnEkf+8ZIIQc4LKr4m3P1t8UeAQvMbHRfAQ1u2/fMf5xwYMqsW
+BscjoQ0lFOcb69nb24E4taRu+MRDF2+eah2hlbHGbsTezIm1VzFRX2C4mnWyfffX
+2WyJQPlZpvOY4kkv8tRvW+nbZ0P7bRjjxrSbCeUVI8X3m0fiCJ0fMVg1MMaj8JxD
+AgIKBBIJV8SYRw3NqiGk/mIlMq4Qtl8PWEFBRf30DRD8RIqOO0yV9Czu/u1hcmxN
+x1/ZExbwOFAFwE/GU+NMegFRXC4toNIU2Xo1C84URpAvVAwwe6SiqWFTSTEHnRu2
+N/tfJlaL2yFrfRnp6mcNN3T8Rk376skXk1zml8Deh6rNU254yK2CFRgm+79W+CeR
+Gb1wxDw0GQ07Zr6/hNBfpAND4qEdyxYAfJQYOCufXiFFxWp+99TGKN4T/+Ab5D2j
+zKmpYFPJj2vuULLPGIJPnCVNjM5v2KwbFY/95Jh3JEF255TORfj2P6HETcjZr0pD
+TCk13jxgKs3mq98Vr5LGEJ4nUcm4GoZayIbeaM7heJTWmvQyP6PRZIDWi5mHs7K2
+wGUrutGZcxzLtaQkavQPf79xt+0CI9D8Nuz4FrKMS2ng+rWLzT3be46f6hJaX1KP
+cy8RLQfaWpFGBPHr8UKhicOpdbGjxxfBUM7Jlg2o1hQIWmSuj53SygZ/EQnqBV7E
+GG+Gf3RDl1Ab9ncOr2WAA5TOQ/yVBEYXy2W3TDmxuwf/fWvwF2z4DLq/J7pieEM1
+b1IuOlcDWNu6eKAhsrq0t6I/wYNB/7qOmIcMxn1dzDHjic3uO65IMH2swXmk7tuZ
+ExdHGutPDZKYG3TgMyMYk3W9YeoEZAjF3TodOYNpmtaDmftjIuxlaYzmtkQCFHGh
+cRlnPXJwaExSYrySX+1zsuqU2QaLB0AyTlAgkUdiLQOzfmHtiHt4Pgyv/o1z/PgJ
+VTVyu2IFh75H6CnSQGgNHIH6QGN3mcMIZQ5G0U2r46X+7+nnodOky09H2Gq71nQf
+vSk1M2ZoaOuo437zG8SlEuPKimz/d+PH
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem
new file mode 100644
index 0000000..eb957ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CFB,DDDE26F919588654
+
+ulZ1WOcK/yY3ugpb4uN9s8ejFImurz+p4en3zaCfEMdv93V0JT2T/49e+OvIMaOz
+4ShAD3AO5zOXkZd5AUDI5Oi7mMIH2sUmhiJ+0xZMWITbAduYvt69lCGFchpQ/YRD
+G4jT1PY4WQX9o7nN1EYyPnH/vx4Rk6lnOZz7UNpK51SBSBk9lkF/d3bH3J2+pYaN
+G8VET28OIVTs4nqNdu8nxoE8u/Y3aW3FVsFCA/ZhmBD81Odb4rHAHCqJl00ApW91
+nvpTkTjfF9+EfdOE3mfLA4R7CEVWaqnfzvNrVCOILs3qSFGKbIBPBBBJbc4d4pEm
+G+8g5gimV+oL/Q6njSi8s8yV1WWf/nqK6EKd2JJglW700V8dbGHjhGChNTM4Px+C
+RfTF+kXcQZpcsax5ULUz+4KKD2Ub5EcWumg+LAe36VVTz/zDTxhTzsm0/iN68KTM
+jzKjIY9PkVIhZikVkp4s8pL97rL9Tota4OGMacPx3C58MSwJSg7fdUehAcnj+GC6
+Nfi+iHxVpJP4QnFi4BotFxlb2FoVhoh51YdaUehqD0IsoBxrQCmT8nVaz9asJMCY
+CRXNO/2pUpNJY0iGjHfvdmT/aRf+gmat41bX/1r6Xxujf09JF1iS5v/fpYQsshZc
+N+xysjZ8Bps2Kx57XSUTz3NrwMuliJgw6ZbDYBHGSSl2lueUanNArE4iLakuf5BK
+zuf7iVNTZEww904RhnA3HnivRH2b+Q1mWxTezSYZTs2Qr62mJ5ewiFjOlv6hPUfx
+T8/ka54Am8dHsgc3LUDK4pFFR0Nk82yU52FJPbGsggKZAde2tUnDgup6gNmzEjA7
+rSWxEfg53fHda79SQzrKaPGsuWr5b+cl20rGycqN54qZafKFah2tfCzgGdVZG+Yn
+Wq5wvZK7Elmjz+URvKitFhw39yscj4TLlEQ3K/jZVu5/lsyyu3imiUholwMCSuhV
+fg667XbT1qSw8KPWoloOSDQr60d2cK8Olg9DjfMgqmDxVHMuALB+O/dhJq4Jaa9c
+e6ycERign27Fv6j09/aAGrsaB9gMXCOmMhYGSoBUptjb2dx8mN/z3fEG9ykvaDiq
+i1+9GnfRKIYzfxTa3PCpA0B+
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem
new file mode 100644
index 0000000..1dc8182
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3,695F5DA31042DDE2
+
+dzOyRB2M6CfzgilwOWNhrea/0Zt1EmJSCDPXO7kQz0LpP3/keHgFL14NqxQU6puh
+gYn8TKE+H2f+l8xoNhT6kdRI5OZP85NlC/RvzcIPJkriBgMeLwsRCvhxg0EujRa8
+popm8yF2E8N9YPdz2CcrUW0mttVYeSy2YO/pi5rTJBeqqIjqFYjHPEmlnoNqboQk
+aflRKFw/rZgsE4gzoMKR/yso/GmSIXj48h9G9CyLWPFIDi8LdiiBG62wxK1TDFDI
+FIcU4KY8QyHSYc3DdYJJM2kXxvSy5BxbvWkD9cZS9+CuAvDyGI9dfF6g60f2tCA2
+AxIHRn78StCNbRN1xBfkqw0BremGo8G3H8w6FrdeS1rKzzYqAe3XhDO/uN/0aRAz
+Yact4CIYbZgMRhTJh6YhWma9UfYtxslmTNkxmMptS2SvOVSbhPFSQJFIVWaN105f
+HGmLwoRwV+Xd7nLX5hcR0Sozr58m/1FYun4c4797/bcGA5nDKQ9+u/GvOtqGhIU4
+EY5mkMhqt4MdDdKozQvATqWeSlESIFBZgG5sAQWuRJ9g2Pn1N2GTveY0ofIXV575
+WsharLOALP87zUur0E92LoBrbFAS7/nJ7T7F1Ye8ZoG88qs+vJy8SUVCrDjUqfgL
+90YHTKvmq3fJ+DO+40pLU+aiRBPin65h+5J0jW7f+eGpJV1S5dxIYKW0D1+PgcP5
+URVYuN+cGWROH4DN7zyIFPh1lls0GtAf1to+zBy9QYUFAjt2lB/oL/d8RRso4rHG
+8cUdXilKzAApI63nq0pKN2k9hAH5wGzxg3vWJCbsrXuqExsgZ0EFLR1IOX5ISCCZ
+g6TKiLDDSFBfWKTsix169JzCCptFwE+u8lY1b0A2ApCClXeS5+HvWlC/vtkuqCKj
+V51xSR7ltzosktG/gSc6wesbp0RlldK3Ee1l5Ld3sgoxFZd8aBuMVVfvqz0Li0ac
+883Yr9+nSvc9WspdytrfjcbUxmWtBxsDtVqhuIM4eNusUPY/L6FJhfX2kgjc8RNf
+MNJXiMOaTmQfVCTmKZDF1EN+4IZfdrudL+UoesTzasdlDXGKc5gCecWiQpn/hKto
+6YwKToh84r1R4gDcQGM+DL6wa1W5bVbD
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem
new file mode 100644
index 0000000..86f2019
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_des3_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-OFB,BB994897E99A8F6F
+
+Gx0S/6H98EIJK9lM7TBQrFejxjBVE0kcbBTVNTCJCuJ1Ik0s6+OqG1OFOLdXJWva
+M+k0WEWKhTAXtrrbzPiu01u+OVpIQ3xhgzt0rcU8UigfLLvMdqXoyuUTzCYHBraA
+ByJ0+Z9nK5r/OAJkq4gnRfhsDajZgOy8rZAdyIui9rom5emcx1GsnpW8WdRCuu5l
+kHEyaG5nHtUyZobZk1kNbkqelByCAFndV/eook4kycEytZWNPpFP+tUaXma92vDV
+sg3h2qODMr9ElrbvKYujOuFoO77BYM4oxlE/WtWpD29hmxaIgmnlvwUI7HerpZg8
+DbKYV/8ncRolxoE1GqO2dM2nLKaNKra+n5REJBpUDjwe/eV6dwcj5Uvk9nocEt55
+3qtmPbevuXga9mL5iTN8dm5RgrkzCX4LBu5fB3WviuseUBAqpKgq73RCutNM2gDm
+5CkV7Iar6tV+LgiUcgoo8RAnJbysFT6jQkGPYhABFKzdzrFFDDQUBpcLo6hgHpyb
+uQqjVXR69JFxdQpJSuc6cH60jzRQOvgwpCzpRiJL0mgXNXv51K87ucEzM81Z0UpG
+O4GYnsbo7PQfeLAE1PjP2B3xj8kgcRxWbHkQ/vIHTEAtJcXmAquULi+mNKAFb578
+qlBs77sLICgtpqBUzfoiH1ozcKHOJ3XB3yPYt7WKIxn3/rwqrgRDrPbyrrDmV+FC
+veepr8m8ZssbZjKy3z1js+jcvjKJOY6U/7Uc7IfZ6AjBXrkJIDEtn9RPoexG+av/
+P/LDsCF0ChhP44KZi5q5TLNvAmbvNL/7oogaSq9nw5hJYLiu2gScOAAv1h/j9yhE
+f2mz/xTHjr35m3Ax6wLPk2yS53PATS7XXQtWY8E0LJz7gOkSDvolwnyc5aRgS9WF
+H8DyqWi8vYzVLNd1qM1mAR55qrVhWnmlDmw+f2OJmP+6MNAoptW9nsUaeOk5xJVy
+QNSwJCjzp6ujIn5UhmrS2u59HW3hiW0J/O7aalBXYQxUv/qllKkrNmX8HlB/1r2C
+IniTw/Rd33TsNTBx8tqq9IpnAG4s51xHBeXT0+Sd4zNh+fIqAYLNuMllHMlM/oFu
+A7+h4TYAxEccchEha3GD6CMl
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem
new file mode 100644
index 0000000..8a7d018
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CBC,B0CBF8975CC514AC
+
+eH3gBb3Shpdi9fkBr66H3xWR0XnIrKhPU1KABtoaYxE3N7su3duXHlx4zpc3YyO3
+s2YwjN64PdGYgFdwrznf97SjdI+MSJgu2wMxxTwJwOltEPBdbvNWEpq8SLdfdlDv
++zndoR7YnMIhQPp5Hch07dhwpY0hn3RELxYf32ALEbe4+xG8/LZWUBoKdgOn+trk
+1Oh0VB3eupjtsdxDWMMN3Ar+l/1AfdBoaQcHg3UdO52U+mTc38QAaMA+9Gplkz+Z
+YwjWz4tyltvTDWGAYGuhxTPVt3IoSewGVHWxKezFujNEhj6wuJBTlpN5T1pALfbD
+JUiGEmBXOPcxwa3QKmVKJFcA+p5eOYY15sqsIhcaXxPgzjO6JQWMErkaOnyB9sHg
+fQTXHwMau2HqzjOM8Qa/lQyv9nf45IFupKoTT6Kja2WzAVxd9KGW+NZSAa+okRSr
+GQrsXrJBFl3+wKpXN3alj94GK6aqCBiyd3d+pp2NyM9TorZhfWxbQamPmQVaU4aF
++nJjB+lW30wPZM6Ik4UqsgXolYXZCtV4cOaZ7g9ub2AYmYCA6yIagRFfjuEs0/f2
+MNN+qu1Z0sg0oCCpqO9kVcnnC4jIaXvU0egZVlGZ51GP7iR5VsLmi3VTbebnsvT7
+x8XYI1WHYuANsSBNRJj7vmrolzVErsX90FInNcnc7o43KQGyeR4E+vSdqoLHbk3A
+2HL9YLDV5cdvGafL6faVKFxUaA5CWCFVtrV6MPJAm/xWs5nu3wr6aNsDk/0R4mqi
+vzQe9EjkMprrihpXqFGpTaehJQFgLaE3FwnxPeUFawqdKIqaKf+stx3i24LkDSPs
+ukLiYS7cPcDYXN9kI6a0fqGtT/gL7NVa/jxsrl5+da/alvm/Ai7TJsUUi8dMzqIy
+85Hv6xWyPrwCbar4Ehq1CopxWvINo1AnvajIkBHvh4EtK7B51stOO6yNEV7spYxb
+nze92IMAtRNWO/yp/p/nccy9PB8/e2v41T8EN4MJuDxGX4k4cG0k2IGzBDcBM1pC
+YfmkHzMBGPsq3CQ85balLEWQTgR5nr/8+TabxyloED/Sw7mLM4gqMmn2KukzMxT6
+qeiFiGtmv2TbD7OWkaLj1Mth/ns1Of8U
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem
new file mode 100644
index 0000000..acd0a47
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_cfb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CFB,CB9482EEE6EC0DA2
+
+Bo62wJPRVVYQKoP0egdW3dLX4yU/Dbkx8TtIsNxNFhdwpGWtEGzervoU73+6aaWF
+LME/HVPUh+iZPKh9HuwSiP0GtwJzCv8arDp09mxGJ7XFcqz3AS7T+K9A1OclVa5o
+LwQ6ynBtCsmgiVlS/haNjeONqCtpy0kERgathUclwQCLTnQBZmu/l2Pk8Gdtc1Tc
+osmKc6BDlPOyofTt/UnrhVuZxasrS7tKEnVn/iZr5mjUZAqmC2mJcWT5YNahJpfO
+rawRjukIUOm0feFwov45+joTSIGDsNTYD3OV/+BF4ZgBMm33ApAE31JFoweUcI03
+2l+WS5qtmcwuOYGp0Np0BWg09KVwNbIghfiVUEjnqy55PCVOFH1RZrmHhPndCvHQ
+BwAaac0yAtd5vFWjeUf+pTbDmkA44g5f5aO9uQuB58WWkB8JCFpGZLizK4ISy5ay
+dE8+SjVGiMSZBDfAmiEokoYymc7L8bkTIl5Jo4TuMmtFcHnfohZd6Nue3aRzNZHJ
+E/V81IxIytHRlMl/dZjSujPw9FgmXSip/U1s8ESIVOVoy93HnaifgRfkkGggxp4l
+S8QqBvJTAJrQ9ygO3PBjgdKGi1XWvhH1Y5EwPJ6Wor4zzltftELEs1O9xfBT/zeV
+GENfUZZU+5V5ICm4K844WoiTkH5OIWAi/ZLK9XRqchaGWvMpv9UwBy3c0KOx1O4f
+j1/8pbXDv1iey2USNL/Nbw3nanIG0dIbUZ2g2U/FeKtfCfVHu5LJY+v6njKl58X4
+mthqvCZyyJy2U31MYUUDN/lgNffwLnzFc1AxYyxDZwviKmAIN+Ylh5jbxuElCS1T
+bpVd1+4aber+qv9Ar9G/PJEt9ZdHR3RB/tsEXv7ORke+fVzlKFQu9PKo4k25U/mn
+qfBcwlut9rMu19xsjbowqHyYJbenyrF55d00pp6P037cOKLStJECtpgir6HgTpo2
+Oyavx3OIH7ypvcyaqhFUqZI2EiGOdBwbSBp/jCqOrnAwTKo9uMcnmrsKj6EpjJzO
+VGK0DoieTEQ9VzGbqZKK34NHidE4j/MYW9lGKAADSy7Ey0CllvumHiICWOn9aJYy
+ObB64C3p8NFEcW5SrTzPtXeD
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem
new file mode 100644
index 0000000..1ded3d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ecb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-ECB,4C5CF049EFF2E116
+
+M9XRNeRQW2K6U0bfpl3axdvsuTmsiFLkZ4C/76MLePY0HxePs3icSW82+t6awIpG
+gHfei8zevNlF331hGPW81XZAl8OaXWi+iGhIfKAInLKY//DBVI5dMTQUKTwBa87k
+oby7hLD+V4lVKr9o/tf2A43QjEkScVlxcofEnWUG84LkgXalsloaIAt7iu4qUMTA
+C1gTbkwex6bId97wvPQLvhFiOyrpsi5Nm98vEeJwMdb6dMNfLAd3Stjvhh5dGGaR
+BsRwDqgrkycYj6pOT0Zvg9fBxwLYeMk7PPo0bTEdY4itvpHXaRHcogsBJ62qnsFM
+mxk1opz6U0W9xKSNTCwLzg9xinRPXGDP5jz0zqE1nlQ1lrsPcsY+omKdaL/SGYlN
+vxDbm725eOoi1H0jsTGJsgcKJ7sKd6LTUEIAEsUvRAN+ro2zLhxteDP+gpCxTNRr
+ElOLddlDm6TB55lBkZVrH/0k/QQQ+L0lBi5Kgg/hE6oanMRGeKQvxhxRuBbK6tZB
+e0b0lffgZR0m49i3A+fTxa68lb6Lexggp6LAkheh6qOVAzSDWbk00fJ9SWNWO4oC
+9FNqu1yafLt3Xiyqv7iD1EOyGhYF8NDvbMpu+gM7qwbTPMjgXf9N9g+AxSbvrmHR
+5zGtJd+8BtU+139ZlsEv+cux1yxkYEypKm5MHfaa783b2zKuyOTMgOStvSOUgGhz
+c9dlWYPkgdgRkAMHzfIigHr9rQssde7pR7ZMlw75PxI7BI2ZF1Vj4weIkwH0SKFE
+fui/C67Uf78OHx4cVPANDk6cf4Ow8buH/vWjEX0p/jpOfNT9ZA6Otj0CyIQ56MjU
+L4nwFU7GqCbVkJtsHLI4sZmP4kH/3zuqVtwRTzQbQAWeTi6RCSwa8/amAStTPcX2
+WPRezgAtNzS1MBhileGuTP+opGdGOOp4AeCCJdFBzkEacRXylxdY7PUsCZI7mRSZ
+7AL1n9jbUbbgnl6zmqn7fybigjaTpLNSkVPOvVBxnNXxOW4n2HD4vA+q3a4d212X
+fWI+/y7mbYLLRs1LPPgjSLfPQ7Ye1Cj4KWy45Z9YBUtjdsEbaaHNp8TidgJKJuMJ
++sDQ3lvtJdIZZy26tzLf3ryE/+2KMTwG
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem
new file mode 100644
index 0000000..331542c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_128_ofb.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-OFB,F01B181DC9520301
+
+azqFQnexfYYO2tX4qlC6XLU2tPX5EdwOHsruz4uzVJmYFyRLlrgG57KkahVjWupu
+AHkkjhr9d9m/0/t2vFy5JEnF9WWcNA1nxqzfsaIKmnuCULzYzMWu1cFfTV2DZoAn
+npdxa/eYmcGRZ0u3aZHRGpGtP1y2sKvWmUInYCc69oigiEn1qyDkRE/tDAREh7C6
+DWRcva94GLj1igIHc61lBugZKBlchv+q8t02Ga1slM10QRg2dgAlF8uCPZe+NLUk
+8uOifATkKTsA8OsUgn9nRK9dH4FuZeD64NMCszOw7mYtjJ7YW0J0wYgC9BuEUcNm
+QTxellBcs/qSdi4pZWsO9JXxvoc0lTmvoiS0rL+JlB/UfubVQYq+C7ScVJeTUNKL
+6fF8hvfQzqDDjqx+qP4SgboAmIbL7tTJBeABnnhCOtaY5vSuT0l96rIQm/EZdlWD
+hXKcrhawaq6pqh/mV2S16e2gDRQyUX+jKvumTQhjN1+AkIb7EMR1ZLJFX1l343Fj
+5/V4D2+H3EZhbCdkz4uI6I0swDasUjtigcn19kOy5t1r49zpTJ3wxQptLRx4AXUZ
+zjVXVebGyFYSdu+Lks1VC9WDeisBW18kCg5IpOz3eo9ULBBQZnzSKS30OXlyO000
+/1Em8FPKSKYeST3SmI1aDObXOG/s4tyKTCj+e2VKROq8hDhJQUYUP0AgYkAnwURR
++XylYEfUrW9v758Kk3u82ZhEen/lLUQhWeXkzhVi44Lgih3Bjsm3jP5f7KO/5KfM
+UqECKIHR/p/H/klXPNmdFo919AFGcnxFjQCyhlv0Bl8FSc5FUkRl9TTLu+h5m/p2
+ONV63odsVGt2q/HmL+3hojX/BxSEP/8Mq1JHR4Dk0qqUpSxRtDw0XE9/LU6s9NZp
+zm6lkr5E2U6EN677bmem5QoxObNvc88EXGr0EvoWPnhh20lD3vQok7GBucnycoj0
+9NMmRUIflnj47quAGXI6LuTSzKqOOCZC4yNvdyRdil3DgyLLefr99m2WEe0HolDu
+pIyUsgHMlZC/YRVzqP/6DklhKDcvgWbBeqqhV1r/30rRkegHdsWiAEjmJadlBrJF
+szJZpa9obMH/q0xUH3AXXCkS
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem
new file mode 100644
index 0000000..d44bc86
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_40_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-40-CBC,7AFE1927D7FEE9F6
+
+WgKt23n2XggL+3rzABzjmOq8sdOYfFuuYUzP6UNH3zdXRt/fh24/WRgRw+WCa5/l
+3Tt0/spkkMsgkkDwPPVLu0MUhfoUQyErK0F+8HeEdA82C7uGIgst4E2MS4bRXPR6
+w9U2R88xdUaljjahEbSMUG7JXecjL0WG+zLVDpDqMdlKNcMz1tnQbO1JNLZCJlfX
+ZlVPslMmTTxs1sqYgDhkAgh3FwSsKMj51nvedVCq2bAtSmgnz/bFDLT4c6N4iLf5
+MXP5ZUMUtWCac1hXayVw4koOkuPELKi2/1vWe7qDWJfqhKmRT2DV0Z1GKPjQp3Q6
+kGnD8oVxbKfCQDI6PSMOeBcWu40Y1yTbBHBFJO5+MdWsNOQI6CZGJCHNu2ZbOd+w
+tIcxZZjy5d4uY869PxxVxO8TmCRUn9hham6qfTw5Mmh7bOyxqID3fXlyrcE7KRel
+dlL9eQuLcA7wtH5vqpy6V28yWculvP7qmXAGUd1gqSYHUs8kipf46ecFwieCNPEH
+x/6hDl38UsuixchyyJTp5u9L5cKPy5PWXv773xcPguk01YhlmqrpTNZsdoJ/CTBg
+gal+o01rXd6snhp7IwSAppCPwh4YJumwdPjF6jUlmB/2AStF6kGaOA6BbJ/lQlCa
+cHAUaVlTZEyzSGShBGJUAN2AughiOq+2POgr5IgeoC0NL8ieMg7bMYjn7+Np4yZN
+KGmT1jZo7OmyVdh9mheahXTT4Axihfmy+uPTECuGjq4X3DVv79OvSFRpHXIXLnX9
+QkizsJKZc6v3FM6o5tbMDbJyelzaj8Xn8ANrugYMC1R4XImDSel6Bgxni2gHuTEc
+WrrILWnNSmNjz/yziFdu5VuQmYaJ1e50uenmOxiSQhL+53UzhhGCrw4ooAOSF5or
+s87oY1HO2aYq784A5UZVYGA6mYFjDDQSsbwp1LYomjoTrwoJML3P9x5SnaSrkEEC
+3Gm0R/t7SkdMmJhRc28uYarO2qdwyBuhoYRxw9Z6bXeaUN2WhJ7hILCL0KKZE4vB
+DuKxE/KgD8ijKpkUn+6fizWau6Lm5mqxyMyEDnCDkvlvv7DMoqZRJvVWSddNMd6t
+T94SaIiCDOY3SuQCi1361GGbVH2dXH+X
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem
new file mode 100644
index 0000000..4a1ec98
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_rc2_64_cbc.pem
@@ -0,0 +1,23 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-64-CBC,6646FC6A291EFE41
+
+KWLSTeo6nX30rQ3WbgL/13WAEMCtaC32ksYorVhlN4ijjiDu5gEnmfLRNYK4c3LH
+IUJawIdZvHSVxjrKNjmKA18w+4kedYCCL9NbNswd5eO18wldFR5NlSI2FGggzANN
+OwJoHUOXggYxhc2/xbYHpQpl7gvJqZtAjyewyTDYeTC3VDFoB/JywQ/8vv1MN8Ce
+Zx1k6preAQrnqo/LEIm+GPUa9flzWZlCGTIC+obNkjJGZPuUKLM/1TqNsrum33aa
+gFwnz//khQULylIRwxfuOMCHTslFmrs/7MLLbJQyTa99S9kc+s2VDlaKWUn0BVe/
+MoCseykcuIcskavuj01SYySJU1YHBTu7RvhuYO8AQmnsAP3gWQUMvKy9aXmzsoC2
+0Nk3QCZiG+1hN423So4NPOh42OWbqrDls9PKhXvQ8H+58rAxW2s7OTN29Klo39ek
+w8SFjMEtt9kLNpwBCJrIlolXvhD5WQu6XbqI0CtoOrh2Ote1c4uN88HyIUi1Y2Op
+QsfLkKyx7yJcJrz356Ab5lbJKVpKJW+frEHI7rLlfJrj88uzsh1B7oPL/4fhaj84
+vNUfadRJ25ZivBiHHdUTrKk9CLsIDS/1DWM6sDclYjXiA7kgGNwJupOb2L6VEKPv
+eimiJ9ooKq00E96Dc8s23FteQqySNaUAcqDnAkS+ck6pXQECZs4uD79k4pck1SX4
+O20OIPo79pzcWrmYOrTIXH6ttOcB3lUQtB1fmcMT5RSJYVSKtgBxLPKhLcL18xfb
+1HbDkpdUqS0R/nK7ecMd/LP+UmMKPUyMUTfTUnlXZzsNsgIBkm1eDn9RkOGaV+oc
+wau6FWmxVSPs9Inb+7A+B/2bP0qyYnciKX41I/PClKGitm52ScJyrEN0XJhQ0O+C
+mPp9weJI3IwpDn/Mc46NQO9uk4rC2P9o1zfJXC38PlEDEC66a1Y6SEQOVN6iYkYm
+rVytxWjD4o5vC+GwYJPYrmkOg/SQK1AlK8TSpNC5TeRcZ8YIbPLRfKRUQvUVtFS0
+fyPK9zdariwubkiG1a9/NWCF9gN1/DPKFYy+p5Au2ICD0iTtOND9I/Yw8dqsjzsF
+4jhYQ+No+ytLYc4Zo+8s1RO7yduFz7XQ
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_unencrypted.pem b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_unencrypted.pem
new file mode 100644
index 0000000..ee815db
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/dsa/openssl_dsa_unencrypted.pem
@@ -0,0 +1,20 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIDPgIBAAKCAQEAyKItMopMK218pcmy6PkrMVXAv5dt07TdGBuNhVWpQ52ldK9X
+mL7CPKpo4Dy85EZRPvRNyOnhe+LRJZ+ReKntpEkEiar/ZsKVkUthPsiUMpoM5S79
+JK8iT8F9HdFjIFKaXGySBZ4xcrj8HQ/v75iolYCso+66Ybgjs9/nsWS0UQyGE6rc
+ibx7xPAtcbaGZUBaBtdkNER7+P2ueJwej89aNZxj+AKuvrWrArq6/5zOIhGR12wQ
+EQQjj7FQ66ZFivJ/AYsv1yXDS7mZBNp5eMuxk8Kmis/++HKcP7tdbVRnlfTGdBuN
+BMyOcBTIsE11jwikcI+KIbr9cEZoaikkm4KyuwIVAP4DZEC+/JZJ0PHSEtJTt6uz
+yn1hAoIBAHhLbqDib7zqaFBrNnbaBSNiltY3GxWM6uQT88NH9YWz3wXRb6i4KJFH
+9NtLbK0RF7MoQVprJY6LuGQHZ/e61Fs2EabDwT4vB2HT619fVUvDndbuSW6qfUR4
+y9kbG7zLkE4Mnym/ikmUwLABLA67cZUS9yjtcRXGpOkiTAQfCGBeUH6nWOFEaWjI
+fGNMQ5awKvZhIvGyN4Zvd+mE+199s/kAsCKFux2Sq9tYw3qS0Tw2IEebHsHvX7A3
+bvxV6p7czVxlO9+O0w7bBTekPpw1BnCYmPyy0H36g/7aF2V70UCWzER8zT1Pfh7d
+3P0hLqHYzX375l/7oxuDawtcDAV++iwCggEASajPdllHVQ8JvKdPH6qDkjC5XJTZ
+RK46mYm1cCu8Q9Dy9ZfL67CcJBpwKVHNC3sXmk4XPfs91AZf/t01qbMJvCrR8NHs
+jRyJkNIaMyDeWcFmO0KmMi374BQpFyIDQ6mK1y9BilneZ6gHDdfHMsKniLFW+SQf
+9hlwlArIPYuELu7riJhNcuRUTJEfybDHwM4/ht0IFbyUIFl00mMdTrozk+e/esEs
+QdWbx2UBjNs8meZPivFbT2HpQF1I0qZhtn3e7jcR5YatBQ3e4abnu1RrDc73q7d4
+g2SYQK3PmIWwxiFhJQTzeiQtl5rKzEn76knAydOtPVRgjXWzHUoW6Az0qwIVAMvw
+thRrEZxNdxELdnwW3rpYBm6B
+-----END DSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/eckey.pem b/BouncyCastle.AxCrypt/test/data/openssl/eckey.pem
new file mode 100644
index 0000000..8ceb3a8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/eckey.pem
@@ -0,0 +1,9 @@
+-----BEGIN EC PARAMETERS-----
+BgUrgQQAIg==
+-----END EC PARAMETERS-----
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMrjAwPp9R+KMUE
+hB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus
++w2sY8OIPQQWGb5i5LdAyi/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2d
+no1GMols5497in5gL5+zn0yMsRtyv5o=
+-----END EC PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/enckey.pem b/BouncyCastle.AxCrypt/test/data/openssl/enckey.pem
new file mode 100644
index 0000000..137fab3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/enckey.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIpII67Pp5Vs8CAggA
+MB0GCWCGSAFlAwQBKgQQBpkbyKLxdtlBlp6tm6lZoASCBND/h43o5NNNmTXWHN2+
+N9ncoFknxohgShAc8WHKMHt0SCEJab8E2IAxVkYFMOMpvi1KVldcveLlg7hcMIDm
+74pJmvXOW6b0bENvPMOxFadzr9NjO7j5ZT81dwNLz2pBLyiUMYElWl0LVnxKThQF
+qijJTDPcmTpFwDiUyTxzHxMx4DsoFYQulRBsZbRCAjsFpPM+OrOekSAyQHKMSbHU
+LvcdWCrSDRtKOyCeCPbBA4OzPJFyzep6trhbQii6rkddf9o54/oJut+LMuUblrHE
+2yMStfW0G5ZyI7AeOxAy1gKG/CQrvFHn/yhtyjkvPa0sYVGtR4pGew+cs9iIsdFk
+nXOf9frJMA2agQZKc4+rf66NPv+dxVecm40HIR3omk7EnxR8s6msXOOn4qnY7qae
+aq1M7pKNqCu6eW5560mW6buLpOkpm/kDbr4v9rfCX41b5rIRzOdfAt71FSJcHp6K
+FNojK86YsNJWYh9pnfDbjEk7346cCIeJVgICGTmL8Tg6TUy9wIB6eKUXmIG3fKjI
+Ep8OzYAU3/ae8vdmZqD12l3v75muRPs4bP1RdjaVrux5Xlq8TkzU21ixWG6Odj7I
+1jusSUjz16iR29XhLP/HI80GKYQMc2yHWcYQ1YVXyLzhnHYydrqjW5OTKZW01rbe
+9BC8XlRzKZJ4IOQMfSiZxcdERtImO86Kprl4du7gvWaTUGTyiQ721Q08GfFdVuAn
+OO/J8stTLv2Ee7ugTeAFA2+qpz2vAo5JIPOmqjNqI2ytPjLRb80B3tSVXT41OodT
+D4v5YbNpySMDpw2F052Wx37hl2wNxIP98U6aw3ZjJdM/YfLdGOJhdoRTBDAvygRU
+Di6F56sDvX8bdXDUZURMg+iMx3Noc5G3TB3JpYunm3BL9lwGWesrkDzg3Vs1J/6c
+4AMhAsw9+5tzvyGEDHnGZRg07K0eyWskDK0/Qb+vjSLOj8+QphM+EPCmugNnXRNo
+AdslIFoVfrcKruS1/DeSIesXvMd7sj2RH/xYDcAIGzmwbc+Ki4JTPuoZlF3pGMYE
+YkkYj2KHjJeX7CeUjCmU9Y7/jHp+fzlKsQAMQLVm8bRjDpvLA84RDJRoCPav333F
+YqRciZzMjfx2f6AJTCT+/8nv+DBiWcRtab1u6f+p1iDUa8bVt0Y8PB71gwAyonmY
+gp4A3fSilIlKEGsP2Hb4aU9V5vy1EZT0K0PuAY4yxGPmhedLCKdBqOuwQBxsLDP2
+YmXR5wQOsI0dVE8zogpgOGOEE9RXNAf7QV7pBOPNu4HQLNuZi22dKi+wkyMLsIR5
+dGEz7uDIaGQMvlprtOA02RON3gBnQTJAp7E/YMd7OldSBShRRGeIDw7yTrLoHwLI
+YnA5+ZwFLBPnOrnBC47CwgB2X/+ooL8/+yigoajZIIE5RvzuKRQGjC/ZgSHXSHrt
+mJKGerOR/3+OYYCTctTa3wTPVRc/vB1hZac9OPmnKpeywCJ4Q+jX+ZOhHOM671H6
+h9fLPd0tSE75gIkSuJqBuLV2TB1cp7BTnrZxLywCxC779lZBTVLctXu60kiIoW46
+zgEz1dyf22vfMN5ss0ybvBVCl8ROmrVr8ZWObzkj1MUyifDM8Tayd3uZ3SdHPo8L
+2G24+4bjyVdFjUvrBdzB5dNzAQ==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/pkcs7.pem b/BouncyCastle.AxCrypt/test/data/openssl/pkcs7.pem
new file mode 100644
index 0000000..6104acd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/pkcs7.pem
@@ -0,0 +1,54 @@
+-----BEGIN PKCS7-----
+MIIJogYJKoZIhvcNAQcDoIIJkzCCCY8CAQAxgfgwgfUCAQAwXjBZMQswCQYDVQQG
+EwJHQjESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYD
+VQQKEw5NeSBDb21wYW55IEx0ZDELMAkGA1UEAxMCWFgCAQAwDQYJKoZIhvcNAQEB
+BQAEgYAikb9cD39oDYpMHzLuqA4BonNpPx+jYtqlUIaJv30V03nUz1MLm7IH7TFt
+ZhL6BXAbdC2iwk62KVS66ZCLBKdsqtD3w9N2HtxTEW6AdaNHKNUb6z83yarNQGzB
+67llZjeCLeipP7RWIvBZcV0OoqCgLcpZkpZqzrmz5MjxTCmB/DCCCI0GCSqGSIb3
+DQEHATAUBggqhkiG9w0DBwQIja9nGhuQE1GAgghocswhe5MZRov9Zo1gnB25S0P8
+Mw3463VaOcb+ljX1mXkT3fivkBv0plLlmVT+m+CRgczup9p21+t1OqsdaITNIyrG
+hYSVETWyFA/Yn7dQupK+cdCaVLKC3lT8f13iPrU40wnbeo4ZKi2vbv/X3uU4fRMZ
+wSlyczFozcviUYURtA5MZaS2e6/2r1eLZcUlcZ0BDcuD+FNdryGbKztSWa2ye0Ym
+Uilu+GAZr5CQi3IxpRxDqrS+RUQZNllcg8nGZ2UP5W8FjH+Z568NJ7djoziCX0EH
+yd4vp+g0LRG2dkhGXIff4ufO2U3QOAgCIOuZmG5YSpRN2U7F6T8W/FwShFO1u+QH
+YduA3pA/5K+IDfCbEZDMWznd13lTEZQlLSXV7dLNCqpR30JWpGg956rJR0k2bT7G
+KFTXhSUK/Puac5y6IVmJwPxqAkjH+xjXpE32/AcRHi77La3nKp1aQEKo5uHg7HEg
+w160S1LUenJSqcmOuk5XWvM1wdsUJl5Qk4m9a0VyovLPm/RrnulMtUjRugxJLfZK
+27NivOrLl9h/Wm6BXYq4PohM5d+5zPYqupn5ipKHsA68Ps7rnDEGS3VzOQ32hqu4
+kdm6xI2zLWK0+6mQnusBPO0IAxtja6BPz8vTMlWjZtWZgEIMppQMhQJKBEQG6HTV
+z+/gkFds2pFO0v8pLcMBy9+8nqhzwGacymnupXJzB6l3gon2t/e2zJjAPKUSCbHI
+QhCjW2JK9tGKTbF40uYMUGMIPhxr7j1u4LKNEhKCNhlUz82NSsdJ00YNQdwuDMWN
+CTAE9/STmRGF3ZHT9KWmz5MQECp/pGORD7LtOQslbUYiMH5oCYP1jD8eM+KxCljv
+1pFPf+sZdpboAkdaXKcZVnKqOuPBP3Y1jBkLCZykgnXkVbEYM7gSdvsCGK52GcxH
+yi/gOhfOIgywmFB3B4Yk4mDtU84WpK5sVlrZ2vZuTaAmOHaTIkVMvkq30F/jpVy3
+OF4v9/EbEAJGv6rqHMhKmuIHP530CKtWkUUfGv7qQilZ1Qi6NyFJJTfb1bhyENJt
+j8A1QQFIYHDzMolmUoQgqOXJ/6xc9AtCv0fU2LijLUNFjB4rapJggo5UnZE98+Iq
+UAT7tWalpbFisOdX5Dy582hhvcFn/1DDpISXpF0kgE8TV/swkJ7zuu+hO/Yj1HNd
+cwG6NC9+wUCjaRqAobBtvPQyK666I8C12pnW0AeuqtznnZve2B0/a83ECS0tUmxC
+PO9zv9RNwcakynklrupw7B4PcXEaEbxpvHE+/zNLgfrPRggoFdqSIRFS9xQRPE9T
+uO7jEh+tyh70eLqce2jqKpRwxItZst3ABT5XarJ6vfGxxcs55sJG7xjv52xuMikY
+gOagSKpETRdkeE1aAmKwpa/vEFu2J4Oq1Aiv+D2Gc7G04cOsdc+6P+N9EEv70v0R
+3NA4vg3gTBcO3wxwnJZAS7GwUJOcrqC1cAaQkc5NR0lUx0lMzgWWDDS5qKX+YwIU
+7KEQiyhqQ74rkf6hxQyfesaBxqxCZZkikbwBHlDZwoPfwnfrV4X4/xyo3cqCqbhf
+FFlHOAXissz14wsTPh4XQumj5RZSnwj8gGK2xou9H9wMrwuZ2eAT/3L3OtbIr/Sz
+Cbp8Y95Tz8FgmrJXvygMVO1xv77PA1DzE9SLiLyB6TL8lsxFQ1ZF2D8JhpDeIPpj
+L0k2vTrmCgENJ+tCc0ngZO55ZgRbo1fbB/RUfkTRgEKF9WmJYnlXUVoh77kZ0cc9
+Y+KsueEZp1woSTywJb3tc/jXeRGSmcaWe6pa0DcfM50coV0y4lw1ednEV3zkA1r4
+zVtUBw8Xvr9GKcNfWdmqgIJKsQraq6WCeIxCPPJw708+/RERQBoUobXI4+Jatw/z
+XiV9SjrjK9nJ4H1YKyOjyz3SAbeYrgdgrTGvkETCPAALb+4Rg1FHymSMfDquwOsB
+63Mdl63DIkJpicA6CY6yk/LgOADQzEipjcdKqzQOjlb4hsQZxN83kzGJiWB0qZOL
+XVLrGXP4xRYS2bUFB0T8pon0K5qsZ9oKKf+HZaHMYkni43Ef9IRA0qeDl4FfAupA
+kL0lLnBjgGRHc6rMBy4qL18xRjTtR9hsn4Z/pYhIgqMm3QEVkK/aOgTOlwXHdIwu
++Hvzx0Y/BgMdCZSlrspPbQBDgrlWzr+PjcjEvDf3LYj9whtRJP5cXVxiYqi/SpCk
+Ghy47RfNYfkkJs/gbojlO/lDvM8oo+XPi22zAN6yFLuxr65lJZK7QIvabHvTkEIN
+wmpnWcRH+MwcFZO3yKt6lxY7nJWuW5hh8O7k4/oN0pNdGtv1/2XgXFOCREQ4CcPn
+Zm/vXULLCCh7oP+RyklnwyedvfeSfY4lpldwyHCIsYyYmfZHMw32zqH5jCnSxZA4
+fHBrblr4Mj/5jyHLUF5xGsJdm5RtDfwJWe6NelO/kJMs35UjA6dhSOfHEkw73M5P
+jcRo1OtYZGu19x2QguhILpZxuAvNtLpOt88z3PtsxA6Fc0BGpQXPJTYwtXiPf1lj
+fUd5KFsPohPJOIEJAaFHL3GTwmWFtK1dHofPQukiOTb6pC6yKlM/zGWLOyzTM4qP
+UvuUSwg1UY8GplCeqhCJNTieNmyY70vzG2CWcotAwRPeVbpa4MEWRXHf9ft4Mawb
+qn2J48iW4Zgh82vFHNYcGRjKRJqLzp4VBn/qpRaX+aWEsdXq4shRgFOAOKyQNMex
+GZyd9amkblqjEOOEzzxPUdmt8k+QEm+JC80NR2sv1mw80PqU/his5zUJ1Aj4tzkF
+fi4jy2nPNvVSpjWiAI6cpZsbdhdh9iayij4YdQg3HB20+1K9VcFnTmBqLKiBbG2o
+4oX2oNPE9Vr3H9Y8YaVoeUU+Kiqo5g==
+-----END PKCS7-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem
new file mode 100644
index 0000000..8111b0d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDIY6+Wgj6MqdEd
+Yq6FgH5xMgTBmFqAonR/eshjxY2C6MHs+WmCmNSDik2NgZWIaODvOF9uOEK2U0Zf
+JEG2LcZxoeIEgg/mfII2f4DLy1JYajm/llzwFBzAd/Rkcs3qwP2ba5VKn/pSqNLl
+nKHMXkXO+9SjfHDx95x2dK1dB8eGQGculOMcTm3uK7UlWNO4TSlwG9qHZ1aoM3GI
+g5C1fIpbxJqDVjFq6fFAapE3KRIWIQmKd3E5ICcDErqr/AapxnfO8UFNxVWSOLW7
+ZAfis4w/c8/EAgyQHw42R0dNyjUOZsToF8McCsOpRjGolSU8aUyqspvd8IWJPd5d
+6HBHueXNAgMBAAECggEAV3q9MpVVPQ79TTjBO2Km0D+nt+QMzk8dUHGHfZbGejmm
+Pw96shqJ24rK5FWHs+8lEwmnD3TcGsAr3mjzjtZY5U5oXtNwoYwFRElRLqZqIlLt
+NugrVltRWeyD8j30CuGJVQoYOGWyX9d3ielg8NjO3NcvMtembttLoKK68/vrbH11
+9W7wr5p8/xyMfyl9curnmCFk5QqJ1FBpjPWY05NDIBCUJB0tGAqViCpxEeWPSlvb
+xcElqWfdbtnsYUxYU+iOTHHotoKnz4nLHYK2/njMhlCEyMXfu1DJOd8rg5yXewJF
+v6NhXgWStSexAT1bZ17LROazVcHfWB9QmXF1Fm7vOQKBgQD+dZxPDOi3Y4gCFegn
+Z+epNyl2aPTkseEZxrIqPKLHsGxUfYjQqkX2RdfTrq2vf4vFlN6uCXhSlZKXfLH/
+iQ8FAzqenhVVHK2fv5xB0SE5zNmcHDrHshl+/zUNI2u5AMFECVO2SVbgoFjvgkou
+FolK8XUXfHfb4f732LUyYI0lEwKBgQDJmkWHhzekz3P5iWaAt1SH8bZpt2hqa6Bx
+A4VvMdtmjCxEDETN0Rb3CPYxw3qa3xGfW1y1j/49xi4gr69yaT2Tbca7PFGUmWRo
+OJwfCUB5uBUi6UVytK19OVKReOm4666x8P3YO4cxxSI/HeoSU0HR1kkX9rGmrsGN
+MgUQ15+FnwKBgAKf6/DUzUG3ARwkZbSiWb1hGEhkZMJHI29EoWnWHke5BiUI9nRQ
+jVAxADzqvFfnFOYA1xssddVEPbLaUmu0WjdPBTfFoaqzFQdkzpPPOGyENGpr0B9n
+MuQgdceg6eeKnnO5NOfYcdD3VnOCAInhKaFgRDjty7604hBkZ9oRLOOJAoGBAIJ+
+dmUMlGr80XADjTLh+DhqsA1r542DDv44LkXUetS9BOYjHuIuZnQO+/UoOBNJMsn4
+xGDNzN7FihQkRCeFkZL9arbFi3TpeUGw6vV38qEXE69eWVKvOuEkmpqJLphBDfom
+KNmvZopDtTAvt9SWybL+xp9ZUpK26ZfwebD2MU63AoGBAOa2Kt01DxoqiWiQP/ds
+Mc9wOw1zJsSmIK7wEiW3FkCz8uw3UgjF9ymYY/YAW3eZtuUpuxEzyENb9f21p4b2
+zYoZ7nCUo4TmVXxgCjiEWglg3b/R3xjQr1dAABhTeI8bXMv5r/tMUsnS79uKqwGD
+2Gc1syc3+055K4qcfZHH0XWu
+-----END PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem
new file mode 100644
index 0000000..fa3cff6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8/openssl_pkcs8_rsa_enc.pem
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIleYNcQVMEocCAggA
+MBQGCCqGSIb3DQMHBAjb8ZXri5RWRwSCBMjR3ICOxCzBu74U87lV1QXPNlnlHD2v
+TlRv2LNLPseEBAMiJkgP47rYwpzMmJjW5bNzCLxT0pYv2Z3/pXPUqy6aNJmOgCmU
+HvVGdz2jS+WYBtfijc1J6MkuvkhRIBxL4CYJidVurc5X/ebRu3BHbj9Kg/j5Hjx7
+DV4qTxZR8vbRFH+ETdnVqj3pCYNOeYXvV+S0W7IN3rKmEk2su3u19YhbwnZH7Ny2
+YMjAn9FaYT8bK+zlPBZBiQ8TuZxm/jxvW2ScQPLk1pRUs8WkDsaYY1gdg5XuKDND
+xA+mq5xskAMUliQmhJaYxlmv83QZ89JzSd44lLvnNeiaP2xjAhj10ZSVQ8eOXP63
+NfHr9Ehqne5k0CI2fGg78pp8vIihw5D4WjHR46NvmbL1KIlxuYi4nFMtc9aK1zgq
+3rhDL9m3fZZ9Rdd6lb1LN3ZOL8e54tL4KKVkl5jxhrThHujACB94remv6da2z6K1
+LZPuDwI0njzC6Y6LgyGgAP75NKNAH0UzbpPncZxBdhyI5mOgRZnTMNt1XoToXOHP
+CMR5JfKqpczhoJnfcQJhFy44E1NH+qBOsNQTpypDe7Qiz878e6ebfcmXID0OyU/j
+o8czO+1BVT1S2LoN+xpeWcyNYoT+BnRVC99G7vKUoOeo90zNzQQOAEyoAjAg/52Y
+JWnOqnaxDqa0uJ/BPmESFvxeYZypJtoTd/g7n45J4fGBSwiH05TB9PbLHD3YcfxR
+NorFiq/RVXMXkgOGv+2ovJ/A6GK5mS/r1xr4qKnnO44zqwaie/xdZpXuQfQ8ZS7H
+XLVWgbdGP7fbTW72mAG5UzUr6c6gwPo8g6aiOaOnRU32SswhLp4CFgiKFhhgZ4YW
+tLmWc1Lz92D8ctTMvXhV+z8NEPF+livmfANpyhXl6ErCr8jEnhGgj4r7BA19dUXC
+Tttq+Gpo05tMXqom8/6PbQ3Cg2iCT8RGk6v0p2ne3Dg1LlbnklEfV8/DbYO5tUD/
++BXZhF1otr/ZaSdz/jJ+GzmD9KvhheQHBikj1/KicYp1KHYfo9oZJT5ulBO1UX/w
+JbpLaarntLOqb5im6OdjkPFkklVV9m6EByrfd35BTEfowNaasEvrj/VpchGPo7yf
+eFB6HGeIFHNloG7xXn9rv4npJLJOleqmBgyb4cQAk2KwjEJ38LHOyXQL/+tfI5DK
+NKzoFH33dtHnP2ZwaAE5ffMYv284y06n09yOFqPi8YkeFs+UiFeV4Kcht1gUNkPo
+IOLhwfVxoc9H5CbIBC3emckvbpnuBT9+EefGU3pU9e9et60mQ8sp28vtx16rN/e9
+CiXhRXcLyQZxucmoLKXnyXgJbf3+nXcr4zMkNurqUisc+YVMALePkJCCsqRWPCvo
+vDqwMl8rkG3jAqmMJbtZCx7+vvnRnFQSE4BXOlzEQNPZK+EdlfvY5uvksIt93FF+
+E6CIPHW4ki/X6gTIR6piDKiNEle+2e/fJpYqk/pFuVfmiN50QXzrnLrPCznhzQ9V
+GN2j9/b8iKzBk5y4wMNkOS8LT2qdcJoJRzZBb4VV981GwFxhAagwM29wko4sdNG/
+vU4hrrm8WAfmp6d3/UdG6VdQj0O57z7BX6Vr91OBNw5RZKRkQvMu3Q5vCH7ZfYEj
++YM=
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/pkcs8test.pem b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8test.pem
new file mode 100644
index 0000000..1760693
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/pkcs8test.pem
@@ -0,0 +1,175 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDBvYyk4LsBVS3S
+34GZc8uuddHq7cUJx1lZaxWK7C6nnTNKJmJEhxW80VIukpo2RODL1hPFlgCJY3ch
+/4437UoG8ZNAE1BfuVMIkS1AX/l/KAyqUIX/bsXgvZch0Joo92KaPfDB7QA8VCGd
+NCcRaOnusDdsFDdF4/Mrd7/x+Ipkd56FXVEk14QGizFc86aNJrzXjy9ent34PTcS
+uGPXUX7pbiZj8gK9f77pDuH+JymqXdfBKz/x0T54i8N4QFfVp2LbGzeRnduaX4Ff
+79ikdo/XQYTPOYoDwgdiAR+n0+mvDNkI5rbukSLcz+xbWdkJ1ReHW/QQAiqQWK37
+4D1fFNrZAgMBAAECggEAGbH+GVAE/WRCs5kZIzUMapMNyE7It0dNPmLJdKdmeKyM
+xOTaW6Re6bAJakvfUBtKhT5bWPVQFOiwQD4Yqqo6Czm3AeSN4GQ/8v7uNX+FI6w4
+Ic6UNxCGBgyfIsj76TsGRNa6O74nLdkqrCLim5iCjjmo4Bi+S/Kzqaw0NO91y2Um
+9XyCzM7Oh4LukmF94pd5gZBQjjVEkEsw3+oQlOznm3rCNIhYSjfStnFZT5stvcIw
+BscQg386Wo+UvXV8zDI0qrAi0pNepVGsdpGGGUIHkogaF9HHElcSIAVBOQLhxvf5
+S27j3bvHBzWmmR/MgOsBH5+ZqQCTzVGJdzIzXkCRUQKBgQDkQIQNsRv0V44UriNr
+nageBkbjVFxczl5k2qN193qb0GalSOoeKcT9jsBO32mcaBd84vuueSNS69rGlj8+
+7rKyMsRAnjhbMJ0FCWv2muQjxZWEcTWV38wgXkbzos4fon19wQo3JPg0ikOjmGbK
+Z4EIJE0PIw6hjGrTXqc9wK4kgwKBgQDZSv2KVaTX80ZyLIOlbs5+CTAzlEde8+u+
+7LcFOvrrzeo86i6+65yvu395Dlm6PAhz0KocaUECeEDakdQHEDfvEf29BsU+p7fU
+kfNPotacAD7kNo2WenzH0mIhtBWchSUz1P3cIbq4Rxm4XPlAzMEXcDtFRqf+4wVV
+d8Thcjl8cwKBgQCKVGczfRC6Bo3/DoI86DFI8PjpMOlA/XjLmo3SIofWAnkS1pu8
+aAgQuwDlTBTPS25gq5doZ9X2nSXbkJcH5tW5lXbGypzQ9ydSNCGQNNLqswYoXAvj
+ptwpCbnqUdKl7W4sVl+AiBE8lkbj0KsLI6tZadahw9dMJLNhIk4s6KchTQKBgB4f
+PCh6GODq04AuVY2QX8WvBmSQEJjEHZEZBYIPHAumPut010gWJ2FhD5m7eIrNmapc
+aciIer+Z5fumrYrRH7/fcZpLnvpBi8VG+kC25SM5EX7XZSdQEY4txva/HSPWfULD
+KvHiJx02lgUttkvaVoYmQ8Elu1IlLG8drEhIalmrAoGAKLjcIIAcAhuE0QkstS/z
+ZiFhp7tCCrH5sVvXPJfxuKtEC3iTfgOoMywaX3SQGkOP5kVngziGemv1b493Vmek
+T8JLbnNbkooCvPsbMlMgcqZcb/5ckymabMaJBTqhYP4w/uRETNyjmb0uxX2CqXk0
+RoIdgWsw0IiLCNMn16z5O5w=
+-----END PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHzBJBgkqhkiG9w0BBQ0wPDAbBgkqhkiG9w0BBQwwDgQIGQp1RhqLV50CAggA
+MB0GCWCGSAFlAwQBAgQQhMfC5lWjUndHWVmSgLGLMgSCBNBZEZlGvXV9XjzWo0di
+IJof42XSh+mrOdRvUPUS0uPzctmnXZjhKdu42v5jrbyNdruqZsMXTnnQC/UW7Fox
+fp3JzOM5w7wEmgrJybOZgA5spNkiWDdlnmqKme34wEPKv+GPEuHj7w+Z4hc7MSdg
+T6Q3CJFLJDCEvfK70Gyxp6X90HN1riQQVxFOTSg9TJsnsvkOJ9Ju3VCTOqt3jlW0
+FEzrC3lV4AcxfWZct7tkqOTXygWMGinz7OqLxIcmlrF3oc0bLxEQzQuGCJIzrhKo
+3Lb73Xto/kC/uqbCdU+v1zafdKLI/0Uj3/GOGLUu/PeMo7VaHbAj/AOX63Yvj3zm
+WOgJwnOis5iP5rqL3lfdeJrkmE1w7xTLn9fUWXXr+qcVBLeZY30TE9wW9gRCDCka
+09ZVw9MnrodTgvWVSI3xHxjYin8GcxQ+VZTxQMQFHA2cyR60yMG+eGm5t3TZNHVW
+h3uqVxjbN7tMYbjUo1NdbINntOQZhqMje39ai3mWIhGPO09yfsw7ZRX9hhKlrIYo
+UQ4LcEgMZsZDDtAY+Mol7pYB7KpM2iftBT8KSkBLSlqpndl4PJHLUaNBgbNDP6py
+PB8FjPO49qPybeVCIgg3AswxJwGE9bXtO9SLcf/p6S0IWvVcWn+VV5sX+9Bav0eZ
+nCO0WJYrWcjUBzYJLWIDcPviYkoMkFrsFGUP0DA7OneLlW84YUh3AeqqJppb/qve
+UeUXZipLEHf+Z/ToGW+RzPQmFTVDqIx0FdQCi3EefBr3CbN/KtLdRjbP4kyeRGlw
+CUS+BWQ+W/NtVUfVmBvsSLtVfW1pevemt4FE9rP9qUa8KeRpOJIzF4kHUmHyDfp6
+rvQTSS6d3a+N1GyJA5/N4UM6g7FbVnbngPvM1hMNfK6xbIcxQJudBQa/bHqf8DXu
+61npKQYir+TmgDXlc9iD23M+TH2VgeunrFKuVMNVl4igH3+mcHyXpZ/EGM0KyIhq
+PJjPRKD0qcCvs4mPRiOx1wJbCYMdYfEF7sIlkQgKjbQZQyRlDKLkLl4pGWXxaqUm
+iyo6VpK2phKcA/hPYz10isRfy1WrKdNHW0B5DPyreko2H0akapfqMjROE0JHtVGs
+gKg0FrbZXUP+QuKm0V91ShA7c3mRfN2XNbxEc9JFzkDJs4JBxj2H7MxvPQyRrWE3
+sKsQWtr5AFpFb5p5kqCtyyu7ag9pGicqlaFuLda/PR0ykMrhMU4RBO0OulOGl8ZP
+9RC1GCArbSSUYH9xvwthGdaDylONVmHwunFMHs8pblTyo6FiKn1q7lIVXYO3AJ/5
+NfKgryp50SXq0p41i8Dtu+4R6CKx4xTMilPYKYDiDPCRtnwvckI/PshGMA/CHLzr
+LLZUlRt1iup5SDjqRIjquw/aDRe+Wy4AXXniHOnlSrNynHcJRWz+pnLT3Bi6Z2nQ
+ERY4pCIQ/ZdhAHHldFZ7WJ2wrwhf4MQ7sF20HLgXeUN3qj4xYcwR3CykU8f7dfI7
+TIo26asqsVDsVL02tr4dUrtm4J8yQsH8jD0nCpvGwJ9gswUBPmo9YreN82Kt/LSy
+YZISyo2BnoowEcAEGnZBf+PLwBeePeXC2/vrxHlMl7JPkPesEHtTuET034woXELi
+wO/DuStXmiIydT29G1n81zmdVw==
+-----END ENCRYPTED PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI7ITJ8AdDrO0CAggA
+MBQGCCqGSIb3DQMHBAinsLeB93eJ2QSCBMhi3oBwLoE4PNYkIpp3FVk6VHzs7SGQ
+u/KcyYQk0Shjbe/ykNJx72OVfzYemlcNpr4p9Jt3VbXxisiZyRs2m1Edqxzdt3zb
+AcRSVNIbph8V9mSZNBl2hR3GAsrbSTkwM4xzXCQRvA50z1DIABlVFR9AB/52JQ/f
+IQx9NrG6SxlzcNjJMzHpR46ELG0Z5EqPLrdyScVX7TEFWl2ue9P/MOhjfZH0/Wgk
+fFCFNoPsABQ6az/lTj1f7hkYMOIw2tayHAuAXTbqyuOVWhVfAqr3H/XuJvXspjDC
+SmIr9jIdJKOTNrJD1/rG4wnh9U0OHxceQqf+TJisWd12WVjwMZ1jIqjk0g+BQeId
+JJvuJTdVVGee1C3enPjG5qBiSJpD+BEsfk7YQFRzW5TzlzELIdkjru3k3cqSp+dX
+Hp1LT6E8TTcdX4wdhKWf7VV6sayleiaiB+9XufqU7FwnOJbe0sydnn8L7A07qFcs
+9WrXmCSCpB2bH0MYDvuauqHjpIZmaHUAUpXYUjjj8EnuhesJAz2bzO7fQ9rZAQ0D
+6Gq4SLbjTtOlpS2LZeNio5ibyeQkgNs76Tq0zdS+5fFnL/6tIIsJUbdZdLz/5isq
+j+SO+7TiGL8a5URZO2pc3Dh/TtjV/lSiI8qb/MMUAmCL0vWe/FKx3xx4dCrRfDX1
+GyeclEl4pWFqnwSQyHadr1nvnvGrG4/pcwrcnhNNb+Y80RIw15A/kNjsKP1f3XWr
+eHAp+YGqDbJ/RuvoVunoAx3PwA56NTQLMmzYakgQFEPtModtvHTQnLkGozg0VjWk
+TdkB7R8GS87IHpOUyrZcxKYDwOmhR2bHgtosvZ4XK+GAwjIGUzGKtg6MyMh3ynsP
+68Vaj4PgkvmItmdZKrvkinophdFqFlqCLLNf6NtaVUMfz3Ap/vmX+EK+2YWxezNa
+qFMNXO76xoKj+piF47vN7zjGsJ59yLLWZHO9J8hFLqSgArhVcV69j7JVMD3XugbG
+YEFudiVEwE8Kl190CVP1BX8DXYhMrrDL/4QD+jccgLfK20bWdaCtPOs6SxahhsvU
+wRX8hwf3QLiuZxfAIlVCn2eL+9QffJYETjfhAuvPK/HwM6+/n+9GpYc4Ezs593KJ
+9/mZLuMKc0b9tDc0dQ5ld7aNiWuWyP46Da9FWBdbjoiBOHIUp8h5METE1NuH2d1l
+THWYaD0OyOgyi2gosRkjJxqDp0IVxIymsKhX0K/EBcYuKiPKZLL8lCTdrzGlhRC7
+M7N99j2elk3k6BJYewdiklmWHEXFOFo8NWwLKKQPi/rSQHcJy1o4WBiXV5UOYJ2b
+50DAF52281ao7BZhYTt5JKy+KYvP9Znkk/Kklx79SHx/bSrXHZJCLoVJaWRFp332
+vQASx042mXMeNDPy7dC9NP3eSyv/niIUWI4t+ktUds1OmWIAMs+2gQqD0Eq7gAfu
+i8SKjiAXPADx57dg7loU0O9IyErJpY4HrvDLLMQaxLLpJxl3YSrgEVkrkEQvP0vv
+ktUR9qQbIJ3BGD3YuQ3cxAgKWaaZWdEJjKqalTYACS3mg/RHYAb0xnTUX7nkUch6
+D79p6fAhhWe9KG2f8tJVuHfUOnEBi1XR5755Vqt4xgUqMI82z4iqAU8ieBvYpy8G
+ImM=
+-----END ENCRYPTED PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6jAcBgoqhkiG9w0BDAEDMA4ECBztmnlgZpEhAgIIAASCBMggv6vLTkuAj/y7
+wLaJLezGOWe1JyFmhxfn6FMMNIZruIYUdoVNpsUzeOhedtawTszOOLtDtprsqvNz
+/oDWQs2B+JqpLjalfRfkjJjtzkkeij3mVNZH69XPabO/QXnHxjeW/S0Ps5gsIpsf
+6+eklLo7LI+KgVMWVIdZ5bC0P/FFi+Bf+sI20NQN3RchJMT8lKcV+2PHZQIb7diJ
+UuYPf3GRg9XtBb0pXssAC8Do84y1kKYj8xil3g4oe27jn1wlQ0+c8DeqXrXAcnIk
+/tFAfvNyO8EMfaP74vlDC4aATXY1O8UEAStTothbtahFNpFfB/9UbvKG0ac0KC4x
+43Ftv1H3xtyn9vVA4qDCmLK0cNDFKCRo+A41kEE6AKYKctbthhC0GMoj69EYPMhE
+Yg9+1Ev+qI2l8jB9kGbN6YlAkM4bUDHT98fFeS/wrCnzxmmiDD/rsHzv6cdkNw0z
+G5F+Wvf3cT1sVGd6RexVydmfzjEeP/6z9Xr3oMqW2CVY9mHFlq2dBkR1LR8Kju+l
+vWspR2YjzggylL8CpCpeCWzd7O0Q3sni3onHFwEen9fQ0GxM9FS0bH7Ty0+gf0jm
+ZFxwcHnH1mMOS5W4yg00Ri8QDgvz4M9BT+HLu+yId4QwGQFlQqg2+tLKsm9mVAnP
+0Ew+dV90r7/cRUCV0kUmbYissi39OHw5sOs0GDMUiNck77E0paBnTb0s+UzBIdnq
+wy+ojiDxhANB8iabKnfF/9fJ6XB0pxUQkXmKfFJZqpVzEq7ZVQLFPfyjJhQD4vTE
+jOG3PdamAFOjiBBqtxbBF5s+pLZL3sZhStugqJ1l63E5tgMcJ8w0czifLjjUULtG
+8O4V58yAkuqu8ICyhXXOA7Bhmn/vymBIS5VmxvR6NZA9qK9XEh5it1ngNZt3oc/e
+vclArrVbev8Q+Jz6X6aAbTsDleihsRrugGkWeZCjkFIYPKlA58FKmfB7xRcvkpYn
+8iuI1DJCiT99mF0YUjEkKWsbShUElR4ok474SsXt5gHtCtykXrncAPtouYPnXRuY
+MS9pYhgtoMhNPXotZwMsj+YvoWJBbeBgc7WgxZkcxbum3I3ns3E0+RCz1gAI6u7F
+ZUfLogdk+Og/wbv7B5NRncRT2UnWfOyyxlGtxrwqXxaOyIF9007F+Xe8NbRO/EAH
+1yFMdL1jA40lacQdbxrVDQ1nVXRGL6l0O51zWC2E3HkZMclTdWp1yoV3F4r5EY7b
+OLjdZ3ip/vWuMcaHpkP1lp41Q00oZpxkfhq6hrw5agpv1o9OTUr260nmHALDZ6dy
+2qWNqyFYyDuSSGB7spbBeuLq30WuXNO7kLBW3Z1MGq2AmOimUR8r79OkMBkZzZol
+IHgfjedxE/1uOmU5vcEnW/rGrFavTu9BvjoDLVV7/5Gc9z/q8CQbYW/cK77qD8ZC
+J22oFudz2qjl377LRIjmbZp5FvU1fIPy29/7LnuB1b3xfYvFwk/6YSM2FlT57HIL
+PmAHNYzW+Uwst0khEkzcagqqMDERcD/2WKedXUDNwxAm5AU8v31FYLLjeZfkmeNj
+NVYXzstYWgLPtUhODf63pGuILuxQFth4YrdZitda3RRCFI2F8NVFTADbwQWKZUMg
+KSVe9u9LXFxPNijyRpk=
+-----END ENCRYPTED PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE4zAcBgoqhkiG9w0BDAEBMA4ECMpfoO3NymimAgIIAASCBMG1ImpwNjYr+SIa
+FEBPpj57UpoC8FqFKe4bnFkYK+KVapykY/p6KRlo5GyZZHycWbLhQ6LDwCgsgPcp
+x/BTghqMvztLDtO+jIaEqcudX/dp0VhDZazeFJ3hYhjgmPCfTSEBYXAKmtdEPCri
+eRqO1FLw8rAX+n1dJg0wnPly6M8kY4KE331G87+IAynsbieaAVkVAFm4T5+kqLXz
+dC36WzcrpaXln15ydp4Ok7i0/TLcTCfVh5zGvlujKrogJ4EJyFzThyByrRWYAx+H
+3RdtjgL3zoMs7s8qXDVcmActX+PCdDz8w4lqkuG362TTdewDnEc3PQNJPjzWWhWk
+QZ1vbUa2lszxAnBSxHMEs0pvXy4Owboh/FCRJ+0kpZrnEzdNumn9jWWkFxkhZeZU
+BD1QHEyuVN4ZzG4Vr28uZham74RQOHZwv3hiLMKXC0K8A4VSfnWZGGXaa39J58N4
+LpPwORBJOv5haLzi1VZj/IzfN6oc5PnCS51+MYOFcLYf/2qvoQbB6SNw9PxpNf4E
+cgPxXMYJQcgSf2uDJwjsRLmAe8ChD2xvo357fhDZ/y+j4viB8pzKhX9uG16c1Wbo
+7BHnXdqrcbgeNgk4s9elWSr1kKb0gTSkqIRh42s4d51Zrb6qQjgwM0UfydfWyMu4
+y1acFtQPicFoIfvrKxnHEjwDLW3nOhxGL3ORL42U8ICJl8XzLRLYKMQnH6k/Idod
+thZO6v0habuoPp0ozYml77BmmFkdSoR9CZKweoA5Xb9KjeLGIoQk0Kg9Roxw/KV6
+3EBLrP6HLTex/QhhribaHUoz9i9tWKKWGwOl9JXeV/BM3P+JmW05h5LY4THBG68w
+7P+kFvmUAXl4SOd7AVMQCJeUKIbif+Wr7UnRM/G3lJtg3VSp3IkINW2WuUgfWSVw
+T/OUObFOKRZUKqEmPd3HYvlguVJM76jQ0uVi9XiEJtpNVo7UJWw5dk+V8obANxcu
+qNldaXJCDspJe9Ep0NqkfQIuXMZGQo3hcbirH0y3HlBBXdE40Oc6WA0fu/L2D/Ff
+sYCEaGZ0mBOuOi9CP9HailwAEL8Bf/3LsYBLSqKR1vjSC8n2bfD+Sy598QQ8Ti7C
+7XpuKBCAws+cVUnMQVuqckuEm454tQxlWNnmTqoKnIwlEw7atE3Fi7xd0Yk3xO2Z
+m/1+jLMfvUsYr9uYFWYt0SV7GTOHyfc9HWFb8Mtz9XvlA7RQ3gx5hNoovJeeK3Ho
+3f6h8S0BYFWOOvKXk27ZF9OgEqeRryH+B1y32n6AtgeZspnOLPlMTgmvjvqYiocA
+4iaTAoX5PGZuNKRqBhfiCLUT2AI6Coq+LjRdHn1mwLqBnagJFYsaXcTjZNKUr47M
+7kbXX5JC12d1lcCxkTqkhV88SZhgvPzt9J/3Kvx6iOMRinWfxGGFQqiTFEwvk5zI
+64aA80Z/N0jkhiibbsl/quQqi9Tlvqd1wpHcJ28t25H0eKWfiktvuxWRNj86JzHk
+ZMKv1ReqWrihQyfwSG4nvMKaSJSlwuzbb7D5g71bMCHdj9ZddgsWdu93mR7xv8Ok
+tatasiU0x4bZvqaOk7qjgHJCsK0dQHsfF5kIQJ1eC0akqRP1KfDs/Jskefr6e/PX
+1hql/nLztg==
+-----END ENCRYPTED PRIVATE KEY-----
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIE6TAbBgkqhkiG9w0BBQowDgQI3TbGvnzF0LACAggABIIEyLCaObV7h//eWCwg
+detit/l8jaBe2pHs/JPd1qJjnvAjqnSBVQjkbXjxU6ERAXC2IhQzF4ZlW29RrdLC
+ocxhHHM1Pt2+E2T+wiALFYidQIfawiobru3Tb8FN0QaFoyVZgUHzxeZUdot2ceW5
+TrP3PaNSWTnPl2boYy/TBlbw3W5QvmApHvA5RFR0uVqO6kASCPmThVTrutPVPsRo
+Z5QZCTgZWrPXzQmyUzF5z0uBY2i2jWDwZWso63UZh3A+7Au7hn/NAqKNDeN+TZqc
+nniJXD8PTJ8eNtrwk758lhbbrh7orAzy85e+WmHnmVWuZ88kULBiDdUFu+uUNaqD
+gukACGRDe0tGEq/CFKJVkSDvKPKrnBLHo4uBootK+Chj5iY8KMVVJ/IWGjgYL7Bo
+R5zZYos6qubuzfycRCWXHnR5cp3qqgO6oRubRXvWaYuOx5gf/trCK7dDVptYHSzB
+dK5CtlgOQY9mVM6THkgzPNKlaoaWXcAz2YdROMkqEvhGHWTnREuDRmqlsCQKSDkS
+ljyBFHVLEGFrqChnZmIi5x8M8rMQHTjQYYPatIUEr10suWz9So2fSNtrlbzXrk4c
+rQR3XFedszYSCoBVofW4Nt5iSdRldkYh+DGuKG40UKltCfu3EYl3xKgf6VB0quqI
+l6CjQY/XlDirwLVOE0zPTqKeMGsi4UW6Tecri07/48JWBZtYPLEj7LWTG59GmLPl
+LFMZd8JO0au/8UESxFBIg8lBVjGpNV8F3YdI0x/inZFaESKJqK3eNccBMSCIZVxY
++gE/8iNIn/bBGFWGxpJSVAjaGMjXnkRtYCcriTKchvWq8gljhRpTt8y/hEvHzmaM
+rUbY6jJyAJ9Jeso3nzpBetDUImZ89iN9LC6Znz0g2ot1iLEL9Lvtnayn4Aik6wfA
+Ha7R8qy8JjCpSJtV8/COtRrzbzcuZw5I3Hsm3cTCERP1zmNZbm0MFM7WJVMdXPUi
+1OS+vwlUvXt12dfxtABJG+wbsTQ9lPVGph+aixG1QvZVTq7eq0MWo+dJRev2656a
+5VcdmtVo1YiNCG2TniZjcIugksxbjwRdmOaxei7VPn0GuD+4oi5fon8IlpjosJJW
+FEc17IO7rqidXmeFttnnPLooAO5wajNVdAyuCs3HKJsnVLXZK42doWnNm7k+/uca
+K+ai0RHyQLqWfxcU2U78cVVhdgnmFU/9d/+gHhTfhzpCW029NlIgNuQTgU+mAiug
+27Mbrm2Q2f69SNXwWgKw2h6MfMsQxDNZI0vqbA6gvcmkwgbCrrZJr1rSl7dZaZuI
+ek7l/yG/dqyzUWKcHko6jL2OM16cKkVWTRv7o7Au8RrLA2G7BA+FpHt9ZnthzX6K
+LMPr6an9LMwjvnxD15YfENWphVqx7r0VYQnL3AfEinuJ9K4jyGZ1nny35jUHg1tF
+XQbVIBfxoMuSLUjDep9E+iyfL5Qogh2hlZ8HuXcRXb44BucBlwruDuJm8Ft6Q84k
++pw93biUrfEm/7SXIjC5+Daf+49fCrJbMQjfGUAxRxB63qkEtNo5AbLZMlujQxFt
+ByA2F5l6hq5cT97uCDPcYdW+QRr7Q+rFVy8sqxtp3K/D1LHX752yRqBl+pnf1tJA
+Dud9ALqr+fQhxbd3Hw==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem
new file mode 100644
index 0000000..e315053
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CBC,8DA91D5A71988E3D4431D9C2C009F249
+
+ZUo4tso7YF0+ayrQpLsgM4TN2H31b5g5ryj//QqqVG/WmvYgl56Vu7fDbYXytgnb
+PQoJLo+8iUI1d51nirw3RrtAx7Z9lrBu6mX+JBE7nwCVsjBVVlAx1B6d6Jwc20wj
+935VaUkwT3n0zZ1dwb9HLjEGUp82TIbiZ3KjWKnfER2AhFXJl3SzswA5Fvwe0AYm
+KTAEYaaxigTTPgltiEQDIvA/Pnh9ZHjh6rbM816Fa2hdk30wjU4U/KkTYbg4hdoV
+vLeQpYnMT2uICCuvNXq0cXXetfbgdMFsLTxvVElUZrjyMTsw1QtjijeM+gj1dbDj
+HGzR0k97Xj3q+84m+SoNW29zPLZzSaFDX4KdKKG2cHs9BTYJmzb0h7qP4pCXjGgF
+8V2iUDMs7BQlgNnOa9gwT7x7DN4HM6J0MIlNIiYQZnupqqYQTDR0rd+fhdIsXHkA
+qNZKI/4ep7voVIufSS8ZyoISES3f7dvs5nnM2C+QAtL+l/yaaqRdfUyn9BL1djaP
+akSRPXmHrmed8s8YamuhLHyf+GPL2uYpd4i1voA2KKYSx4PnfjH/F/8fXPZr3dNh
+sDtcjhgXHTNAEVVek9VOaHtlUNZEY0UcbP5uqBZta+wP2rBTC94DxIbN+k8A2SlP
+cKGkaRltjnPJAXWmwKMRm1J7vXngXYq0r5VUvnGPiUhFlQwAW5TUml4+1SMEUirZ
+y/Oh3AjhOus67uiAXAQoqlr9KykueXobFrhZjLCgRf7iDmP/t1eK40UyV83w85yz
+cORi8FNfqvCARz05qXwfhf2NBMTRbLNzKCGjS4iY0dLNk+QYNgJGoM4nFVkHYgbM
+pTThzpYgtRnxQf1mYTZFtqr8hRJqiRfexzCyk2JC3rDtEO8WUmNdvdKNN0KwCd4+
+dcVS8KzNov9fYMqiiol0dL89WBN1RN+hs7HnOJkNZZgaNVspOLCT4+SN5fLgtbJI
+BzbAgTK1ILrSom5fyzZcRkYwzIqNc97YhRYnxDp7vJFlgsBqySJgtdGUkTPrrzAO
+CCYyi/ukSVphPe+qRsvj9L4syZgpLRgDdZaW+BR0pbTUg2WQvZuKL5iMhfB8cbAC
++FjoKeSlxI68jukrAYHBNcco+qaAYrUaHsJFUsbf7j85DzHxnaA3M+P0i+LWJwOI
+3G751QR2CrjgK+QD7XUtUjBMrsVGlJmfaQsEm7+rtuPynXq+ArJrvgha4lc0GRD6
+yNDCTTMafuBnJ72wop1UEE8zGOsqERsgvOAL10J1s5KCcPHGwrDhjhr3/x1GI6/e
+H80zp/E9mPgzYQMfhl06s9SwyvsxFCIZAfrKIhq7lVqeEDiusYbe15kCLmTVNZ6C
+c/BhDc76vwek05AOLaZLGbdpMRwevbOn4WvUHV0o5Yr1h1IGZKx9BQYwFS65SDCg
+uxfM+dKulE6MWD2hPUP9s47+R812cBnHu5BVV+Cq52YygAiAP1+nfFw7TBKzqczo
+fnIsoL69JthqtkZiwl36uMmcoWwZM621ZqYFJI53WO57uhW0uuoyidQj8HoNG/re
+o3OyAgVO6sTFsw/Dwxo4WX2AKuIt9W2IJMFNC7aS7lH0iPrtiVC3FFXvuY5agipH
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem
new file mode 100644
index 0000000..8bd32ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-CFB,2F7AF90B0C0A420FFD62214EBEFC4CD5
+
+hciElffC9lqjzOx+aBT3DYY0/oZrI0Q34xfQg7IOTUPUAxrrT/UjHlToX56VIbRm
+PH2M5yoF88Ji7BI2V/Y2QRAjAYRFVjZvPO9ke4IGYI8xfnKRivfxLtW/YfaiKnqc
+7VyyO2UI2tYGm27+JJbGLR+GdaHmcnLmencGdS4Hn3KDQ9IK4eLLXrBPWyzGnxEZ
+qA2OWdzqodjppFCjlx892YJUsq+w3BXu5lkPoooTEoxB5RywZfngUY9Y+raN60S6
+zhjkaaJTEqAfnAsdVMUvzpkYpoH5LCO1vl4+XpKdeUu3wJ5p3D9TVc4kt6/V/MeL
+rHJVN8FKJKYddTlaP7xOmh4bivrJao6LzRUdnyxGL6SkVQ4ipitgWcSwFGgRQc1m
+/MzFmTATtC8tocSqXMY8nblp0/sabGhUSTGG+uBGddDr16D/8J5rb8cMCfR0KLPF
+3uwV89PbbqpS73IUKkolRjxslO74TPDT5ds0i+UV+J+AJM+9CnyY7WI3FgMlVvRn
+KwYJuihDzFjozJfe386XWYs2Joa3Eo0vbaVvp4hbHq5Gh7S2iiBpqy2uN0xxuZA9
+QB1XpLd+rOC0y5l1usuVc9kBlGsTiFVyBoZo/pWVlTU3z8Hzgv8p1TAJN6jgqVH7
+oMVgubXsz1XPHrrjjgZEEpxqzXtKJw3DKchGDfAn4VLTSrOINwMC5sR8l30OZVtD
+IdlmftUBhv2AeVUqkLsSMKGdeagfwoqOlfL4FKvSt4n8Vq+Hn9lY/S7n3cjM17YE
+YAgpBjX4PJqXsp8K5KmBHPQMB08jW+NQFABOprdes5bwflrERogdLZmQH4vxqUvs
+DFhHVJxo1wxeRDOftVgtxnmHzU+SaB9MgdWWhC/4pxx5uzqYi0Q2kSOZ27EXZNdh
+MgVX16W6jLUw9zaR1wJIJZU7SmhJOL1fxvt85RytaD28+JvPTNs2ffDpjPu0sXh9
+n0gYiWztuBNUv1m+LMpi1SPtHvtoZLhc++9g4BXoZevtgNl+FqvHs2Ob9w3yXqkT
+lyJQbqju674MaKXDoQ+3+tnXad8MRGCvIgmIUzmMZj3O7QcrBbDY/pbcxoEDOaKI
+SygvYvKfrBIKq6PuGsN1KHSMrjc2A4+wuTYy75xsai9YtwwT1tyIIeCv5NXbbtJq
+vW+nbSNYW+khIicBc+Ye+GFfUh2MXj+iC1lK+5i+1leKo4zLNFDmnXKgZ4jOOPMa
+FMYPZkwANQ6//tyP/qzLWGyBucIC/Ym9hUvi0HlYjjU3Z+Zv92vM+2+li4mtMy7M
+tdcm72bqsT3+1rtJKKRaYG/FiQizOGTDyhgV+JX9MEVwJPa+61V9jwkIPPR6iBrl
+u7NoFfSp666XbD+LurRh82vlS7KYOB2zimHFxI6nOHBsypJynqtgIzLg5N1+LhVz
+t+cxucW9eFvkEEXmjZwofqlxq9BDso587kKY+EpOkXrlnG/ha9XeZcyUipn+jQ0Q
+64Cb7LfvcU5UEXTcMh6BKkoeNP07O1ecpD1LXMGYFn2HsfYHigwwcZ7sm9oCCC9q
+vF/rjXg/oIMagmc6MZOjRE2eT9tpLRAaMynLiln7XS5u+Q8O3RexEw==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem
new file mode 100644
index 0000000..b6def08
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-ECB,3E3ACDA483AAD613760CC55C7DBFE582
+
+PJupElZP0QC92uiYotAm/CG6i8ypU5SXxc3zmrk7sBdxVU9JQXsIE/oIUK40AlFW
+cGuHWxxYkdYNtTpuwG/CVlsrq20YfpxQrl525f4pz8ETWt/P5+aLQ0TemEKr+LVE
+921o6LNstZpftQJbe3yMz0cFTjSfsxsHbadfUZUQzobr1XcbazPyhr5rrSntgIMy
+rJ5M4G6QrOEAIHfVVZ1oizlFnd4vjGOKk1i6APgEEqJTIyFWoCXEzDtaMcl97GEI
+EWGusd8DJrqpJKnohVoTZdOzLrnerJXEUEJ0cz+UjvljAYg2MBSJk5v6HCp8aWcc
+CCoWUbJp2933n4nLBq7EXTVmJ1pwbB4cjNM1oL2BznW/pdznrSRcw8qut35ikEKW
+mB97+IMVr03orl0uFjHBIch6cPLYkXKi5w7CO4vvJeqqPK+mCtckzgIlzsdTL7Pp
+tp+wrMBtG2Ibh2HeJuvvlFCgoYBY482aPu/4NMei2eqfs0p5g0bf67R/BiG2Sxxr
+4o8hmR14v+dzLsQeoKrr3RnMqfmrbqgdkUfgBomlsunHUu9u7jB70TuYsZk/COPn
+SgMM0T1pxEuHdXfyZPSS9u2SFGEhbW4zIuVz79Lo7h3sKdYJqmwmgOk1P3IL/nra
+YpcacWzmV0g/GK8O+2CSGvEh1+m0ffQac1Pd2Abjzg9jghshsBTVTpkcFI0UfkIm
+gpP/hwLONl5a1KJn7u/ltFPdZkJ5CWPe0ZQ1mqjhDaPnc8j7iuFzUilsWITLRof0
+KHUDsAZSV7gZ5G/Lh6DGZdlwfkD4b+2GOPayQ44mr4p2hdOque6Z/LEXtOv+UvvF
+kR9azOu2RXVTiDLL4c/ntltS6laT/nCg0goMs5NAis+3cxKd7Uk/yXBAulwR6wmy
+MIZuSM4gk2pqbt6TJWIfxl4ZtPwp+jYIpMZc47XQ7w5m7YSquJzjilaj+IDVPkhF
+TWTMf+Ucb4duBD39HZjBWAoLkF487M8KDtcxL60uHuhVJsKyYsb8b20ukA++c6aH
+0VqU3NB8VXH7De3pA08G51P+XLurlLUUr118STaEd4r7GR8FddFmSh5x+PSuVXut
+D2p2W7pfvS8OTuaMF0PZo0KkUq/TbTpvMcTax+G0DgGJqFFhqxNur6WoJyYbQE0M
+nX8USnuJhS+BRNPEXc5i14dWmZEeE8i2KGm8RlL3KZfyrpBk2zwnGs+WM8xAlBSY
+KnGO6bLvRaUl+8IT1nKfY30HLr2tX+F0fEM9Tn443VgsXkYnMoaPDU0aW6+J0lLE
+lTeqJn8MPVRbU0Ss/0Q2PQLpayHrR+ly6yxJPOY6Nc1eLkhXoB1DwiGh5Mp7J6+V
+R5UL4nRr40hZy+35sH1lf/+1mY95Rb1hAYP9r5K9dAvqkdUMSPz8rtzb/4gevLi2
+rxB5XyOHM/qZL9ySpJWjFPBwOtJ/EJioRTvnG+/8jdxXWBiGKdkGLKV8k1z7gOee
+ewq2/8n4HnzMm5YKdTesy6LuaO5TaOAUe89Eo/CxPgdM5YnxSxRsxunrPR8JMLYI
+V6xyNRRHLOy2ffGdJZ3nqbSOxCNiHW+Glh5I2jyrKG5Bs0S1jbt3l0hZKWSU8k5k
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem
new file mode 100644
index 0000000..2986eb2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes128_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-128-OFB,271025C313E6EFC0403320C73382F15B
+
+/L1xK2Hx7pYQBTuhHX1P/mkXqLAlbSSz58hL1E4oxsDJODiVH+ueTSKajA8+tbxG
+eBK4p0s5j1fp7SJ9m4QXBwvhCnis992H9kQws6U9gGFrofrYAniRFhX6yzvm86ee
+deQ2Pfcv+evGRPigkoeRSQGxSa40fJ+5cBs4G22cfrKabaEKxnLtQpqPG17JQ4/f
+LdrHz64IyJTgvV6LCzJxShO7vxwIXaA82HNR6Qp09WUXxLB1/pfQ8oQfZbTUkvWi
+CBdXWT42VZklPl7StNiAN9U85K/USIYkKG47CpJvWMYbWJ3Dt1EFiEFi/wmYTinv
+b2K0xUrVUKxAMfmVtr1wGSJA9P9AT0/sBO2vTn5ibXVVHibtAET+vGXLtpGqf89/
+RmcqNEFYxvLzoTyR2FONtVluAC2yk10cKHY/pzZwQyVfjcgMlbnrZz9Pp1Y6ntR5
+AfXpVR/qyYOaQ8BeMCXkfR79GPyCPV6txy3KE2mbajwamvL7eR0+0R3Q0lhVcWGp
+g91D1nbgVFkHGOugO+2yb8vLq9k7K84Za+TY9NCqCG6g0S46yAgZD2rqrAAO4UIf
+6+nno8TS41W5wmsdEarbRoIg7iIKaPKzEmRRurSdlj/s7MKHgQFoet/OdZuAQkV6
+FumyDmqekmPAgIIJEO2NdrWo87RWKCzc61Yl52qmWsqrJIHrPORMGdjdlLVxXXIE
+XZQot33Rx7/f0VZktYB5fWk08kjWQ0sKTDiHEp8Xobq/RDyMTm9TFIkeFm4rLkl6
+Zt2bzp7ssoKeYuJgpoRzUmGP83wgl+AaJZpupARdz5MlqXd5knuPTETFPaFIf98d
+r/sl/V4E1nh0x83HNOBrLlpKbeWocVV4zv22q4zemALPCOQKUPWulINQWAYiTPDA
+lBQhFRnJXSZYFUqFWpxjp3yIWCvTZd4wgX5IQpaJvG+ehRn0H4FR0hJukMG7Pn5y
+ye0M0XlvVYWfxhLRDK23iNkRzVIbIxZfxqaInpGvatcTHyb2vnVFateSGlXIk0wU
+GxgytnTGW2fZtCDOqeQxCL66nIkpqKhB2hJKaD5WIG7SUikjBblvVcN+gkj9IWML
+7LB7xjE+4cyt27Rt9QHuLchdgSScPnPTZhdX0iK1LVELlJQFx8WPZpfXwpQR/xz8
+tqAKOfyhOX2XxYYOoaNN+ffQ3mEnsVFx2uQOp7PvNjL06XdYP4p/AruzVnbqsDsG
+BIo+oo7PfepNw1jRxcmeoaMotIZ8Feq8H8QEARqQSnzRWAJZhV5D9ztmUtaeqyy4
+QDbgxBxdV0nLAWG7e54FMn5yJfjqq2pkBl69ZvR3N+F+L5/eWlEpalIoq2l8AffY
+gDxlGgp030MAyFYSLJNYj+UUwq8k5INaC0QKjARbBMblf0HOX4U6RBqrpzn2xyvU
+mlM6pTiO+mOpG9WLgQS9XTUk2te8n0vAVUTk4Camj94Vdl8JWFNsfJIgwE59hprg
+a3Pz4FosIcBbj1pYtlA9Lz3kIGe9U3z9rHeQHNxJ8agW8NKGvlzY/YBdb115UhnM
+WOVp5TkpF2MyE+TGWqXzwNo3GutaNVs5YO5nX3Mtx4ClRrsmQYVTMg==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem
new file mode 100644
index 0000000..b80686d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CBC,51C73DF9487965B976234C88321E3F30
+
+6yLkX7C2XTX5AE6KqWsB2Lmt+TMGsoHIH5BDl+o7Yjx7aBSzB9X9KPTsVoPmTCOg
++yhhV6am/yBImCdyuY8d9Q0A1kPIJTEkshgk5vc2KpW08blLCHSCjokEVbQ4TJDH
+bMtrEBVMU1g9KBTMuBpbu6MLVaFth2GTsqExX2gu7FB5EAKvEGhkmLudo1jKkgvR
+aiiyMd2CH2MTdatZtw5PrJmkhV/6RMZRKP8r9wkez8NN14ehmk5QDY2s/hj5uaEf
+xK0GXY6OcwoRo85PsOYhmOeFDqHKGRo9a0pPBy5ZaV4udj0QZekE1fziOxiPf6K8
+0BL50UUzQBW+3n0dIZbzlOiJQScQkjoxi0kc088FHXHf74VBoJUo6pckAu4OwpXW
+L4XLIGAr2Kv4OMiFSJOcaihyawE312B2URcAzVCO7skhTYHaC0fMYDJCGTc2D9rR
++V5tVfT1dG4xdB+p/b9TQyAu8PE10jT+tVNJqGsZRI8I3iOtyWsBcn4sQInpYFYU
+R/v2tgG4hDdq1beEY5N/ZaLsoSyFYZmwbzB+BVhPg0W/9s91/nYAQgOL6XrExQjF
+lZxS28ujAq1LDNzg0NDA2KsDGJF2TuST2stnxyvf23h8+KV2nZLOZXjhlVl/Nr5O
+WPm3gCmuPf8F6FPqM+zI4YBBRtvLRkXafUNuvc7PYVNiaPyuMh7I7U1EUUzTpkqi
+OI/YD4xv6DpDand/WEtLHaYfVYU6PAapLV0T28BoFITp/qxHYYnXVfhn4htSgiwW
+R1btcxWyNjsIedjb1LJ2EwEfuXqZmzDz51uDLBq3XQ/dbvDkDzfZR3O1KGaACxAT
+tAeAdnTnAVliWYQiJ7BHn4LTJZ0ERGL/R1xpQs4quki4WHtEBRRzP6BbmUYYhigO
+QwvTK9darP1Ev7miF5BkRnrzWqCQHNTlDB3i/RzIfIDChQbSZtrpZH/V/quPuPlO
+1353Q6D221UiChhw0+8GmIszbLwBkDq+Zr7/poUBAqHmTaA3LeiahACM55ATbg1+
+FKf0nvUL0SaEBAqFxSdQ1mnW83VCMlCE7Luh49BDl4/nufCdF+iv3cYRW2SDHPrU
+HELYYLz+b4QLl+XO2SgUYEkU9s1Z+eCKcVUXGzz6vZUsA8UwvYIy8b/1cz4Y5sZ4
+MLpEXnQRMwAjArh4fvmosAG+diC18H2asLWpUS5HBBrSb8lAqKPLl+n72SlZkFjE
+WP+qq3koz3EyJsjwH2qbpx5BLhTPcEVHl3DZ1eOQmCXcpSm/cqKp2MKQFubCC4rr
+nphTD8uYKCP3mJXB8vqIIO9ho7+GVlCHJdZGu+3bw1L89O6ZG6WClbY56eGz2xUn
+DBmikb9sppeYSs0eX+yQ9kjQRf/BGnRab2dSTGtDT7jp6cL+zWUUOawLHWS72XtN
+3XYSEvvAWPygwbBuAuw17pwPPmTXduRiJosR1lRk28FGsMwzbj4byXm77IO3vD80
+cyrAQ/bmSpvlmYEHvmRn9N7QT7SFANY4a03aBK2iuqZQUz/zeo3eyrJudBXIiwUz
+/ZRteBa6SQagqDsmfeuGCjgTFGVnutCokh9lajm9BZ1pZtCmHEDd7yz4Odx5CmxG
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem
new file mode 100644
index 0000000..00cbae5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-CFB,58F8574921C585278A50F7A2EA529595
+
+RQtPMTKDNttPq1R+DiwHrEK33FOfxK1Cst5x1jrDhXe5MObLhqbz4Ft2idjtG/vC
+pemznnZqQYKsuJl/Th6Ydsthkg7HH1pYLRstc/tWQTESa0RseHDtdw3e/Wxhm6DH
+pSqymOfRq8R7PQKPxboj9fjxeooWlA+RQxGdyRJ6gki6PljOD29C2hxZV4HuL2II
+tUn/cdzaGu6bCvpFDvDuFja3TRtIrHSbCq01uZg6XrFui7BuwJxxR5lERsauJ6RX
++lAvhwXqN4nsEQefvZc/GeTFzklsoJ+c3HJy7pN15nyfwNzmmH5EK7C4CdBJQymv
+MRwe9hY/LGXB5IFEgXvop9bh2qYk9tb/zb8aAHcLS9rwFsGOo+5+Yib3ds4GC5fx
+ILKH234g+hkhutao530kmWXFf7qup8lvTlBZueAWcIFdmBCsWjm8ejxQUZaPCqEY
+sZ1UMDw1HPX7/4TXdVNZWrxHisv0VWnhwJNflEcI/k/GR0/qUgkHnUPycWTtg0W2
+7ivs7D0EkIJy2OyFj5swWs+eqhsSDmd0BgGL0VduLB0voi1eU908Af3PllsTwf4D
+UaLFvOkllIbul+YweImT9TinmkWIFMZuNDR/PHjpbLN/39YkvSub6oS4LOgKEu1Y
+Xr779QOZHMcIP+PXoaxqOWls9hgI6M3PAH+gAjwF77OWIQIh8JZCibR6HWYcr/qo
+iFTzJGNN7P06s3IOek+YoHG1c0GoPsNungPOzthNnaAUcRyvZ1Yg8cy/nhrA8Eeo
+A4G/I241jr/Ex5jooykpeotV1/AMIF7qxFeTARQgObRi/fiR0r9rjaSMbOt4PlRv
+Ln0ZBqedtkkRBPRGO0VViSbUAUOq0oSb98FWqPFpcFl8tXRyqe9m/W2zACczZplz
+OySvRuASdKYpGk4DmMlQtS8wjzMYTesBx68OiZfw9W2nkH+Xapc4cH8hyb3+aXXb
+b53nbp59+mx4UwPOcrdzVHdKhDT3BjYrJTv9kHAY8yA4Nr08ZsO5tOeI7vF+bUKx
+kWu4AIEccB030iu87/xHXUEOBzsV6HzzT1TrZ5GKSh43vhRwoasYON2xlO6RuKCD
+Yv6GbcPd4lv2mv4lAaDXk5IThABHUL8yhqfwru4L43av5AwdslRKIvBM7UWrlXFe
+A/Hipy6jjcusGiOyH7WfWBFV2/f6NtX6lGuna03F/yMZcHI/HEK5RyhqOYOmcxfw
+A1eGKSqOnq9IJ6vXnF8PuRYKB9i8Ha0z5JmWkh/dX5dhTzwH6wOz4+bLgkgXBdhY
+jptSs5zsvrxGiLCbENPTjArsBbT5NISh+VTrrUtmA5BLPWx6d4NNJ5eBXTnpOIJr
+rxA0halZtFYKj0mp1ZgnVylHC45QDiwzDnhXra83RVrcgQjcX4npjKOaYZRQ5cKR
+2F1QdvoLvE9YqhjH0QFQWMWfvmLHGIDIDkSB6EyFsgzWdv6kIaiYsmdir5FzE8c5
+SvHvu28j1X4OL62AquOFKMXQVns1/jLp0KERx1EhrQChHUxpA/cbqNJbhjHoRQK6
+0zXWP9gNlyrSIKY4egyQmjcTDvNXVcSDu2o7EfnprNCYirFgsAbw5A==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem
new file mode 100644
index 0000000..106704e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-ECB,A3A4C4B92548B906A635B84B3D67591E
+
+E4I7KvCs0qknDw8D9ISQev5oQCNiHskfB/SvuKJ/qJoJP52qk+ajN9pNMp+011R+
+MRaMlK7tANTrQ0L/Yc6QNUZW2aHyiex0aoC4ien4ojgvqHfaP12dMxFhOoLctN+N
+zrAPSuQg2OEBiWxEoDqpgA7FTUbxPiJ3QdtwwOXS5kqAKIEIoNnCPCL+45uKBrP8
+encSI+nrZIXLFqGEukKZuFH9qzdF2leOKSmEW1kmwxMOfQLMVQMJyVzd19cCxU/1
+FZtPRRIzFlx4PlNYLKDpypSUavgo5V/o3UHk6vbP/Wd+Wy1ERwNliV7CTCCpOrBH
+qJezvhkbktiHQQ7+5zU0jsTzTlZcxATdm2ktyfEa5GKrCNfrmUYNwNSi8DC2Dn1x
+4z9r6OfKV3dKcSkgmFS3ZI97ZhrnMqpvo0h1kg8tuiboI9pPWp8OsLIvw5+jz707
+GLsl6hI0EX61YFc7bqeetnObgiaJMJxQJXHi0U+Z01GjZ+qgGb6USmQ1D8r34nuj
+4l88VYW4jBhxa/IFpzUoxIioKG58xQT+OK2Fi7BF/OJLQpj+3RA3YLqry0D+AOT+
+f+nDJepwrQ/CZtoQl53ssct+mDY0D1IU6u7ah9WdIuuptV7+WxutFfDpXsmErKcZ
+eILXaH5zK9iNVnVNQDmnVacjQt0x0Rm28wrjI5N7M8jGWKWi9PMLElx3BTo9EbON
+pJ6x6xshjmdCR3gOLo86CZGkoUM1eNGhJuihrl6HelcZxeFnuiNYnLb5hIaqDd1v
+NpFUQBRC6Q3jz85zIvVsiN2vIyak2OGDRs7r5dqb1x9QVz5tMjxuKe3t+rfX1FN1
+vCusACQQzOl6NdTgmm5Of+pMniOL/kRF78e7zva8vM1Qf31/z8wtq3gemt+pZstW
+WV/kRhIvY/p2Nm41TtltlctThbYquFTEy8gxhB/Cot2k7Z494+8UBVIn7SjsdDpU
+X+N24itXM9/sd1LHrXBSbBT5PzSBJFC5MS4Nt6qpvSKIRbyWINjUoTvbbUwoCo6g
+soYBPJR9KeAcQ8YdBOEXtFScq7c5ZPOGCj/+3p++Pk7yMmlxNPvs6HLjdHchjAYz
+jycK/uWYNLOwKS/AMxwi4R3i45pPgIRuwGdRyi17Z8kOKATdyQwScbPOShW9/066
+OA0rEORx3C9gMoKa9QYo3O9YLjA7NS1ERSY9c3X9anSgR7eSs+DLRwFiB3EHoCba
+ULqd3n7qBKgkQpVF60p34yKb3K8o5s0cIE7oAm3VdoI/O/RSs87rDmUbpuYzAA24
+mXRwBvPpwEhke5PoPeFIYmcWa4wUZOJWuF78U/tZw047vcLKgr60Z1s+DlQJvFXI
+tXkV3qS45f9UDaWQ15YNev9fq+x/1JDO1LjQ9AHANBjRQSzE9K6YpyIw/SZlbo1O
+xuFrE077EL3hrRNh00O2rtcrK53mAOKMX9D5xifIcN4/uD9AdwU24YvC44gij47m
+hSg5wz0RokMNGLKTXaJxJGs4+ZK8JWQs/Kf/V9j6j/i4iDWuy5Ra7+/dIU/Qy1ZW
+cc8Uo2ji4i2z+QyzbpbR/jBqO++lcV2byEVDy8Xp/0X2G9mY0ymIbm7ATTlzE2/b
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem
new file mode 100644
index 0000000..88dd91a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes192_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-192-OFB,9797077D8AC3052C37DE4D719CA8FC00
+
+SU3g1XmkcVhlJpQSWXdeHcHI8IQCQBg0oenT/35NKgWnFBlysqwGwl/pwgdDBmm4
+jLsPaE5Vanm4aqWv9DNhItOQokIbIkxF6qKeV3wNSNbTsSaG2LNphwMiLs9rw4G9
+3aFV+0THPLAy3BDTsB3NPuRqlOSVcwVrfaeMXQGhCOPGmsGDeczai1xH7eq1C1no
+KUqNMGdf8g1NuCmQnvswuTF9BCi6rIO0JRqLPTxoz/1emKfHhJFefpSj88zg3ucm
+cz6ZOAlsmWm1MQrktXd+odzpmjHtd1vNsgr4GSYUeVxxWQX4o8pVFqWqiQXii+HS
+ubtMARXAuFIGoM1RCMN8o7sJG00RbG7zNxfhHqe4wSkKgx3qEuusUDewXkDeYhHJ
+HGQCD1epByGHCZkLwBntccOqbCQoSNB0/PcFU6vJrtgVFl8N4VsNMRuLj2ZJ7uuL
+/EZ3qkLTk/Ek68++m2dtAdyj2KF1O4z2SFROSh7MCqWl2rYh4zZcBtGEfmQe5Pwz
++kPycc76ayzHO8Bjg6rl/16Ua5Wx7d6vy4Hg7JYb5eDmj2UGJ8p/z83KBdQnb1ku
+84ZjpYgmtjZ1vY8Z5iZqfZro9JBjWM4wFZIKNXcBniC7kBV9fRC5nzpjs6qWTPRb
+bd7PLMuyRZz9PO6cRuhqYlP5tYSGYYVhAMVutIqSrQVRDV8AnmblfPiOtT5lHC48
+GR/xPTIFxxVqsDmeyBzyXn9gzAJKgjTVCXNksXojM/ZMfDDvAF6m/Ntz/izp2CbI
+f2lcHgsm7SwVn2fvHikAugA9B6ixMCXygO0L5OEUDJW1e1fB7FMasjrwRorDsxsj
+JUNDW0KhUXWt/U8lNyfRm3oNUjQQU3x1iEymjQZV10ZO9DTn28fZOF70moUWnl0y
+ffELY1vLtLNP7Y5tcGNtJARSGnMUW99P7OKpLNXkhL8zE3DGEL1N+gDS1n81kzTH
+7hPjM6yR6gJQVsQrQmXrEpIlHQeGA99LYchzyVog14qMhvQItDlCsr5UIPwVwhMP
+LTA2LITZOYieRAqrv3vn+yFHYG4k9/C/xHwKHE/4pDw8bLn1o8thGv5ZW4yDsHGx
+n6F6vqJrkPW6vXkmwcgO5jK8JBbEpyzAPc6aSsibH3JF0ufsfs2hQ4bwb96OmU6v
+mukMLjQoi3BJC70Op1bpe7wtCELJw1oFvbZDoXLYsa3c06HK1M4rmzJQTIEBjqxd
+vs3g4L4CQ4RHAzlkjLrCF+wcBHt33586bDrt03qBEA7GSyAUu1NSM3UKjjM0OydG
+u8echgFIz6XetqDICHdN0r3ZWyICM/FgnVQhs39fCgafVJsy9C4p5jByUuDPvebP
++gvvVqkb+DGwfkKT3RUFAcYiNHdtIob3kmp8OJKTFk/nwdUwqUTEu3VFCmWog9ps
+oe/0KOL7j1Kn1xEFkOt5MdSFCcpbsYjQNi7F1gWAr1vMXDDPsSizsniGSvXZIYBt
+Pk5AH4MflqbHFofWClhGczSLi0FRiVPqWyudoU7LOesQhhN74Dn5IzkeAGtDL8r6
+4vC+G61PZdFXhLXQfOEL99hgJ2mjQP4rVqwdz143YE4/CUHmpq6d8g==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem
new file mode 100644
index 0000000..7b03203
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,1876F5A50C9046D504D47B2BF8951875
+
+BAPOppBjFxMrMU+NI00PbmXXutKdPAiP+If8JqX5xGQDB9bSt5Q9R2QkaMx8Z94f
+trVbp82iERyPYnwcnA1Av+pcZhKi/mYFgDBPP+dDLp8qKRFAWil0zc0U2jkfo0U7
+v8cpO5+oipkJ9RtjaTg3/XmrwCUFZH4KA6G+SUFc4Oxj8/dzQ5YUDtJ5iyArRlnr
+v4nsvP4OvsI5UFYwp/T97ks0KSmo6YLMpJwUBwcleX2vOhX8fd3thk9I+EbVVt/f
++JztCTwr4EsLxWe4XVmit9AKfLU0AhmcA20j2YXE1VFvRJdyr+gOGPD2SDoRgiZH
+rRBhfi7cou3QmZ5d43jFYoYCBc98blEV07umH0DXMTL8XSrfWNIjZf8uQR3+ZbHt
+W60jVdhOCEb40KoRTHQAMBQdgVVkrbXCFyc9NeVzzhPqyKXElGxLBjRB9u0h15DV
+WCJUdc9UGuHzFpVFzpEaehdm/7vl+SZXUzAOgAQDtL+ATsvZglyMx5y2UA+5L1eZ
+grA6e3tQFdBcv8w+WgYW37oAY2VkHKjoHs1TnR8z1t+OpVovnpcklawybh9Avv5J
+kXyZGc+lbbb2gvUw33VeYR8yIE4zBoePuhTFM3K4NfkBbKavBBXMjQlsdRzlt48r
+RqdFnpYc1XB4ZLP2VparhG+Q1UueVML8uBcd5F6X/0u9n78LfIITwRUpVoaLXRzs
+94Us0pbzWFDxqxtqKPZHLAVJOYvEOwZD5Haw/bwho73EHEx38MY7mk9T5PonsBko
+7Op6aEmKK1qfpJ1aPvy74UmIlVDHu5WEMkYx7nQL67gnFXHY0yKjmP6dc2y3+nfR
+qNK95RTaS9VbACRS+re+P9+Z3aAsQGvj3MA+4Q+qlscUmb8uk+M7tg9ADk0VSe1u
+Ts2x7UZroI61c+WzgsQzMAwm2QLPoKQcvv2b+iGD82enAtleTTHL9rkoS+KmNNU6
+hWL+AJ7HP9s/5+FJ7/4CD84pcLECXQ+f185vvE42TfdZmoq6NgSKrGVZPLxYnyjO
+qa2sTRzImZrXPtsnFEL9OBflWA+ZHaAGo4HJNxZW4Z90HJlAZN3isSZnE3jPToKP
+YFdHsPv5m/KpNa5luh4L3K41QWzLmPlRR0aygWM7/0fYkgxI8PnBeCp4OjoK6qHx
+VYTWMKJQTLyji3YwMr4CufFAVty3InUZzm+ALMFHqEORB6JqPTR9mtnR145FHtxE
+1z0LnEoDFEdGuLjtC57yR+lYS/vgMbtj4EqQ2zK93JaXvI2HxxOiZCZEDww262Bx
+QZo0vBoAd5vkMKmz5eAMpRVkguF1wN1RPvao7I2auJIHp/3zoaUowpZgtbmDHZFA
+Kddfc927GQRxtUH3QQVe1R6FFAa7JBHNeJsBvZu3bj3l/7BATzcne5OPhjZ/t8Sl
+hMqEBZuo0svrEc0w+e8dpbPEjuj8UwBmHYZWlALby5N+YJ1NEtLYmyHe2PFNXwK0
+2fo45CCSyl7YJrHD1ONJ0M804ML4nMwmYq6fOAaV9ufQBFqQQj/hyyE93blB8f2E
+I8LMN/SUKN06YU0nErN0PRdm7CkrS+kutn/Pz2H4oSbUZ67z4Ee1tpnVQjoDYdQU
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem
new file mode 100644
index 0000000..a616b68
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CFB,37639E4753C0E4CD43EEDEEA18AA66D7
+
+HKuYoKfUqTRf4sW12EzTuIFK5J1FkeJAD+ajYnKeKYneNiDbmDlQv0kIk12qBv6l
+LA0oBH62QKjUDKi/sg8NAO5CqYkN2ZB0gQurTgGT/jrvMkkkkwE0x1n69bGNScCN
+mkqMnAnjQqbo1xERzwqX5OWNTTb4iDLiPyjiUlQDONl14pe4x6zGpVziCVCQh8Q6
+rAPDryZBg/wQtPXNhNpk8MiTiSwe03wq10QP6W5TmUIKp3kD4OVfBxpW1N4znyIu
+unJDVcRdBf6XA+aL7plAsETL6F9Tx3Mxm5GaeaJcSOWWzKMvqYhAcEYwM01lx0w8
+LMMRUogny67ZqaLywXZWH6FCJGCnJK5oaJE+jlnKZ6xhbwAxMyxWRCZC9pF22ocI
+3IY602+shDOWZQDoihhddwPJejh+o3mVFEglco3YEByL7Cy6GvqxhctEEH7uKvlQ
+gXGb7srmOpeHHfP76N9afF2hn0mqyToakdZqgnlgT2jm4UDHJ1vQ+onIksV56I07
+tVMEmPhXQCIHhfKdzEgI/v8CiLL3W/g8r+20/5qyKCL5vPBLAxmRudYKbGkhm5pq
+GkzaSp1cKe4ipUfVc5OEUikOMCuadal0TUQZ+h658aBCxLWHNPdZCzNdY/bZLN9z
+XPhAzml/H6VOZyIxb9hm+FNESvqNKdlU2NaE7HW0ILKaDif7gsZhvogP4qNDp2P9
+xPANQh9UxpA16AUTUNOqk78t9aQVpbjZfAeGmcw6AxJ77uK649JgkEnKqcuxcDSi
+zn/8NGeaKow/bTW6jJJj7b4cMys32uxRjeeeClC0moQiy28OIJpRRCRJIs7Muka+
+dMBoNyftBnCONH+oqj+F5au3QPMwKH4v/4VpO3hcByXcqxegH+BPEZzzYJ1OnI3u
+dh9VlpTdC/CD+Gn3ZRqYbguSaqow1ZF+nlpD0xcs0IQjNEe2BVR7CULUFVXIgF44
+pTv96/LvbG1J9b0VuBr+iIp30FG9azd2xyn4O3lW2xk1uzvo/Wf1vDGvT6AYyXNG
+DQS1dGtIm3+sy975sNTlba5gWgh0YNHjeiQq19I6ZzLFhkvLKfh7zpx+R53YcqSY
+lXj62N0u2s4KUygqg14oiIUoEnNr+n7Pq0es/gYs34mY/KvlqA8Prax91BaoqqLW
+qHN5bEv90KdKaJlvdWsCUjA3wReeaQa+U737GMXaON9/oOJ02bWC8/OIzUPgfGRH
+v/8YL7kMnTd+Col0f+XxnebWSfJsAzT7mjfly+An9EjccTeiOon8submd+L8WySK
+lVvWzBD3l4HKjQkr/3/YtmpuymVZyeTzngVuSdw+iXWPmOOuXHyjyD2Htn5iNWch
+Zlw37a5sHhiFtpNZtOnhpmDbX9sgt68KJMB/E9Mh3JuWCaKZZ3Cv/22KA4KQRlNB
+FSvDDKJBrM1m599A6GPJisR+iC7g7asJQ8hI1OqaY69v8nP0Fo+Qk8+Ac1L/n/Vm
+RjksignkKjvqgWENNn5Bf9A9+zZrLLu9wJJLae7wIiw4UgsNob68sGjWdLyg+tab
+QTxd15H5VUIuD6pkeAI2qC+0sSw9V6LKm6pmEIIbp188CzApcsGBXA==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem
new file mode 100644
index 0000000..f679d6d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-ECB,C5DF56EE3F83A1F8C1AC805EA73D4D24
+
+ac22chm8+bxXpppAKfsrFJwCY0S4VPnXmFRqlAPZRuqBH9ylFcG+F8TuHdIsLeof
+q6s8yxkXa8y+/3hyqIZeMwN5Ai1Cas4P1iMwEtMUCMeaip5t0nf+yeCyx433hDSW
+dVnsdeuiFCiBUPUXfp6dCGO9kOLUEwu4wM4lIJkJ4QVyauO0/DwObQ6s6xEMFvQH
+GF1AFFTfW39CpZuS1rguG4hTxW6aNxjEaSKHJnzWu+kduMLJEaLUiL5+i/tUw937
+V8DhGdWU//1Q6KKLMr+5w0k9i/FhVxAGJZoZ5j79ToYORGr4jpkDPOvHaCydM6Iv
+JH0epC0wfG8L/dArNGLEftTpVVlvqHMpAlc0Rgvn+LtqstfyWFXqbQ90NBxC5Fs5
+xiGxKFGpkX4stoKIaOvFVw/hoCI/oxs8Eihz8u4QjBsl/3TdYQ6AUyfBGEWImy/y
+hh+QKCVOfzAmVGcffXYf7fvZETVgpo6tynxKVlSRXO9ZuzANJCC8jkUEOjc7jSKl
+jyMKQMNnQxyplgaFxnWIfs/snvlLQW8DlpMPH8xSkHkUgLKMWrSLB9Cisv0N7V5t
+Zl7Xxm3tOteLG73JxJKJkSZ9djlhkPvlvS///mvLQc6jse8EzY8peQMI1pYQu87U
+CvHVDOYn56SFVJmo2koER8FG8a1910NqdCKpNkzjqTl1Qbz7Z2VwghTslM7sUA2L
+AJP6PgdCkiGbi3oU8moPy3Nyg908j/17Bj9VyCXiegMAOxI6Kefim5Nn/sq+2/7Z
+MHIucQX6ka8KjEp9jvf7jvNC5WYxJkKIl+yzwAzqRQ395Lp1sun6jPfngnPQmkXY
+toeOeFvKlxaQu3QgNY7Hq9wwGbK/uo+rLK+Jbnt/75w7x5aGHQF3kf36epr3O/0l
+MyZPPx6sLblYcNQhBV8rnSey1WeO6105h61xTXdKV6To/m+RDZYvt+qs4z5SNQlj
+oKTezoQUh4J4QMg0EPhghyCS+/+cPMdnVnwX6Ds6nD2feX2CpN27xieGEp5ZhioG
+qWi6/59B38kBW2e60eQyL5f53bhWvywBg3HeUsXCD0ujtXBqPMuNnO6FU+/5Ohg5
+BAJ/bXaWiOkobmppBeaViidGv3NytL48ZIuQ1PZsYQajFb/k1SkyLebmeC2NYdO8
+VBWxAz5glgIKP11K9DJMD3n6PVl+ZyvlYZUGXjfUhOxHKVmNDHv2o5Pv8jf3WEhs
+yuWEoRECvfNlkDrmda0MxMhEYjeTysbxeX6fvwD2InzuFKhfzwh49p5LdZLurEm8
+DI8KBIXUx8g3svArJRvbVLyW0deMlXBY7h8Yc/2y7c5qBwfYrYhgazxVBfRqS3lt
+EsO2sa0V0GaGhPh7LUt+n1qDDYmaOfxOdpZoSLm/surciEQIQVNXt264YuFJS+ot
+vHWWVHzS1AZIgizu7NHRVeUmu4XEgT8vRsJYeogyG9o3U27L/lF1L5ysvYQjtvkd
+q5idZxCnY5RctE2wa5gjxPjmgbt1sUN23KOiPyz2cmXGBh/dwqEhIV6j7+WeS4/r
+SFBZBeGRHi8tACblT/6G9UB6FcycyD3hf317Zb3jXZLve17ozwRZRQ8aBkz07+iy
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem
new file mode 100644
index 0000000..34ed53b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_aes256_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-OFB,E6AB8D4FECB44185E26505049A97B0D6
+
+Fg8Nq9CxyVZmBNEiN9vBI+gsZL4lvWqCPaR5E+Po7acLxYGos4zIcmLCBa2X8lvM
+UInn087k98OAClm+0PvhZ64/AdDE952UclD/xiNvQCH25HGQy7wk/BxuOM5/FT0S
+rlV6RGMibelHpnv+yploYoHD8CSo77N4RHdEuepPwod2fGTKu5Cbbt1FBGU5LXWJ
+BrDMOlSN8P/rD5ePADhDsYnh86g4cBVHTb3MkrteLa0m1Szt47E6d3s+Ued8Cg5S
+7tiJOTFnXkmG87LsLZ0HDp6yML3g2gpTL/1Zhn9zS9lZc3cnkBfRJmttLBPjVCiB
+mStjlXnuJTDBdgQhJPJ4+2xJiR/ucFbCnUF/VICsl0hdz2Hd0PCOdhzj6U3jbRk4
+uI2sv5TV/E+e/Ppvdh2W8LISSBdIwp9CJf3se8RFz1dUXwTMGM50LKr/dpvy3T4m
+NMO/Cf/LyA7HBFJxjqf++wi5LPDXzROm1QHncvXNUjypNPND3RhP53pMeQ/Ffd04
+dw29zrmbyQKQOOac5Ss9Lj33Q/WzBgw5UxxxMxwRVDyfFpdz6JRfMrnj2c97auLI
+RI3euI9A9yRNxneBKTobS0EjYyqAiU6b5MbNwrybqvavbA/+ZMEg9Ylg7vtBOXpW
+YLLYFYPhWNEambOfNJi4tHcX8znGACxO/W7v3Ir+QFhw2IzSvntcMODKGaNKMGys
+HJ6mqKbmYidjhtKen1qHB5u2bukaGWUj2kjkv7jjuDK3ExsvB2PjEV5d0foPEwW7
+9QQeKc5pY4tOxFVA4qCq1tTzUhWr0mBkPhnFjc7XOLbu0sHYdr6ArZ3SadaNT12w
+LG2yg5r8BgmaUVTTQAzIiHhAQYZoCHAq+ohNocIikIh7lPE58DL2GPpEdXZsgzTi
+T+EUSkSw4VtIMmnWw5GNE3zCOxvx5qzhKiXVcnB+2+IF3nlHkQqFXcYNGhezZjnJ
+4FlR4FPzumRmMj1x0zmdbp7eTFpipUpKqJtC8iuea29pEl8opXDNhvmpmrT4/429
+7x8eJOjZhm8WL1dVpV2/Ikc9boEsYzHcBkY7kuaTqT8I9tdQ08ODo8UE5aReaFuZ
+vlBY4J+A4lltQ7qQ+sAk6gUMvlY8h/9L9gZiGbLe438Ndizskuwy+jAZAEx0f0cK
+YnTsZxBHPkWQXgBHMhe3BAAA+CZaXPps0SjD0yMQs7lkAgag6zBXW2vqttoJLU9R
+f6uP+BLwZCFDF1NtkROLV1oROnaGvMbHWcar2tw5qNe3BAsPQqGk8XnqwILz4IwX
+MN6QrjzbBC2jcL5jsxPZ/Tis9+wfI3t1Ke0EljYqA9RVWuC2KtRK+X3xOK6tWEK+
+QlagHRDI0Z0u0slCLjpB/ev9Ajqwlr0h25T5ucdsLd3FFEKZbzspdfsJuOXPM5la
+Uv9gpYIcuFrKcVbvuBPzt6NX/rp9gozZv7ZOnujjor6RDorHsfbgbEfcerydvJGu
+PRk788TkAB0LOE2wD2J2UO8+Ufp1qK9GWmtr0WFCazqFfeiorTh71iS7pwUt08so
+0BRkqfrfP6pXEcnh4p+LKh+dnbgIBD+KH0qHsyc0ci43byoOSDDHnQ==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem
new file mode 100644
index 0000000..e3f6e24
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CBC,E59962EBB3DD3C74
+
+1FpslA4+P9E8HcUUGpkIMWeZYV2XxCgOiSgCe2NAUiutcRkVAg9nPbzwnsQTbckx
+d5uOE/w53BURpxPkz3nNcike0sr3fa/MzaoRUDo0P4MU5bmAihjnZqhRllqvw4Zt
+BsyxjHVn54RaqZC4RNQUqwIHYZwJmHUi7Zk3+Sw7fivMZBr/AWqa66I2hk20+obB
+y5ubRjtjw6uaciPLIoMZksxoEwi5xv4KnQHAQnaihQ558RPpUwweqHXyOZPEC1Kx
+gNQPrTGc4Zm+CKqR4CceACSYzcYtechZpSQqn61emmtyhowDqXpqqjG2nimNihcI
+hbp5O+O3fKZFkJllB20xuaj0rK1NFF4aLiS3BK6aWeCZ6aXFawSvbQb6vGx+pQmP
+eQemfllRXXkT43CHUmMTaf6gKnz5DaxDBqdVP73dBa6UoWnxTrZcUNKiPUCvB3g1
+ciJePjBnsijb2Bh6jIwr7yghIbS65AYE/0V+5Duw360Fa1OqJkMuz5pKeJIUcYEZ
+3yuI22CZeorkvymKhrt1hUn5xLIKRZkWg7UbXG1WXCrGtPdJ+CxnwupHMdL8iMLi
+1haNeJ3E/PeMjehQRzSEEFwDljn/b1JtoWsEwnQPTPKY3505OWIhYRwRXLEo5n1y
+QEfktZ9UtIsJcIpfi7hMvbpp/7Njlu2MJKZ/1ZtvwVLoaXFTSivqcAkDdP7u5enb
+OJ4EaDWrRXS3Zj31fpYTV5p0fRaejFPevRNnYvMLRiSoFobd5MUrKjxpxPRCLiW7
+24BF9QY7C2Nso9yR7gNkzLw5x/725lGxa2ZD16nJmiECOaEB8ORVlilmjX2OQi66
+hpGVtjHMaoGr5IvBrtc7Q9aM0bdoFZD5I2mOm0hniNHG9es2IMByHWRAQFzOOLGH
+IFoIyW3OIuzK3cz8lMLsh/Hlbzo/3bpX0rbrn1XZULWAJ1oNzRJRi6a3Sw2YoIMh
+656IJB/fGRbG9CMVMl0T7onDUhZYLA/mV+xy2CjkQdPBjFpQUTn5YHu6zMU7gejo
+YSV/4esuUfhogLiqw7sPuCDqLL2UftN29xloQDTY6MlrkFb9jCciAwn02DAmsN4h
+7Utus3Z2N7gJnxt1dRecqr2o/agIINm3tMh0LK3/CydmlthZQNpsxMD7IqaWFfQR
+Uq7zQUfYZi0l2J6iy6FUHUokskqwgiNhMP2Z+uZ1xHUnoP7E0IZMHnVWEKBIQZ0d
+ddDucux1jOBlMwLqom3jYPjPkxoeSU2E0ozVNSOqsPnoKkz2qKnEHhea2sAPg4eX
+lsZ9ENQyQMZVapjic41BU/32pbrE/+JkK2Cc+dcLlrnHo+JpFeTdbleJhZ2JgXHW
+8r04vZHA7tQOc0KNR522Niu7dvOW302lwmfp7D5xfon62/AxVhos1DSZuNpVClm3
+V59lqeCBDm1yJwdM/946Eq45YJiTNTzYsPPFl25KNv+3+GKkhZ20GuLiaqprel3S
+MC5XbMJg4nc0LiAfDT/q1jO/EKZ5LzRRtkVvx1D8To6DAptyFoJSMKyFu79tQdfN
+371+sXEX1VjpEGxO2t/DUmuERIBdc9X7rPNOXSl31QxsXy4s73zcAhI94X8xrqYZ
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem
new file mode 100644
index 0000000..b3581da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-CFB,A6C793D28C38F56A
+
+sjmmZGwl3qF65MFuXEtiTkltbaXuionUsMtzc/XzyPPaIxcdl/03iR5Fix0hTY2Y
+/W9BntQGcycH7uNcoYwOUScTRr2BJncyoDXZaUx/WOQ6cDHuhRWWwpLpmitfsn1B
+SRvLdKddL1GE2nfG2xhCdN4N7pVPUwIahHye1AkaSJ4gur8tU0++mJQTjDo63xKB
+oTh3mZB0OCnelXtoYFKGFXNh5ouAPZgcE84breDJBoGReH6f4elkigtSx/J2QhgN
+vXERboYz/HHhHSRCtMSp0qLEQo+uLcFxZcSMQE12eglOOucht877V5n5RMLFT/3c
+DeZdg6D1b52UzaSjTvLm/jJCdkYqZf4SFuBgLHF/rEALQ1vBqDiKQ7QxuWz5ApPm
+P0ntscETngWuJ2g2M1EoxGehwNiJJEslYE/CB0Aky1XeUmUAUm++Q3QVfUA3G3C7
+pP7whQSr1Y7gL44EmttFCX+dX8GWXuZDXa399wijphVw+6bl0gp/hWRWriTern1D
++/4S78ddrci4slA+/Kkq423wjLNGZtOoy9cXRmFdbQlMfVaeu5U7LmrTQRrgGVM6
+GQjgNanXYhkCNubQ+v2Q6FflAdri8Ac8ZvFXxSIGZ3JG14cm072vOdp0/rCNkzSb
+fmtyzXUGgNgKzfp/GFvIXD04lLfeipzlUhNvDK8AKUNIctrMHZegpbfSm6HD6BiV
+rUFNLvr58WDK0eLeRxg4pFTCf9QXr9Q1v4MWehkn+LOTconhJtRictdlj+G2ymOQ
+LYgSRPPdXVNxlBI6u5WRtMxzZM6G3N8jkEvFfFsyeMtE+R0OsXiIwvGzdksnI/1F
+deQJzav9uMBj4A0bJuMQ3Ls8ydZNFU2RDofSU84bP/g6TzU8MpT7QXQXPD2jKdLp
+JouxtbRw+YY+9p0sk5PFYxti+T17jZN//pqiBrZUzvspwr5sWoa8BbA3bWE2gnXT
+cmx98wREJ3wWRx+t0k44084kD5/cvVH7MsAQ75XxGa0ofVj3crMCL29c+/QaUnhR
+GrdJ0sVJeIthiOQZZ5zBqG+IhJfG/jkKpweA9fkQ5gm+FoasTfDnAdSJjah7WfoO
+C6LKzNBB1FaOHqy4X6LUN5wraEOP+0OI3hKPdOB47yUzPF6FGneGk4BajDHG4RyT
+F2ZnG1aa+FRfakQ6l7ok4j+VPtDlCPY2jnT7muj2F78G69abNOS7ASXg5+PJzso0
+liaWo1d8TDfEazlDQvglDAKpzYw2mSbpJVmmbPSaVZxUARcIIaBqxu6xWepfdN8v
+qZGrOp7vTOuGu8f2YmWKd3+lcNm2CwwGYIPpuTFjtUuF7guKEdTffyj5tpOdo942
+RAy/F3tCy5zfZrI8SkSkx+wfZAnkUnI3xQNdKKVLCXcpBtQWht2UGO1G9W84OmFy
+eg21zeITIwPJZfUif9WHihdINSlfm0CiS+gDRzXukS4HgniPfS3NPo6HAepc2Gzr
+QUGF/ENern3v85DCEE/AebRaQN7liM+6Z55UZ4GOT3Tj64+Nth7MNQXqBYEmCS8P
+ndWvlalOs+vlj2Rl13IcSUOK8OOr6S7jeZhoutej1b4lbw8RwYBXGg==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem
new file mode 100644
index 0000000..bc3353e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-ECB,1E15270A7DD42BA2
+
+zz3p7Ml80hSdlJsI5RyvOScQlsGC1GLg3AK0dC/Hh0IKPTDF7a2OITL6H/y/3txz
+LJ6jAcobjRfVMWGAJUwFaSlE5QF5W1+RauV+M8oMmv+Mf2K/Urha6m63EauLEVWu
+IDtxj74qfQgyd//qWHU+XmWhhNEGk5MrH163VITZqpG3Qe9dYHdalh4TB/ILJqfN
+URKLjdz8L4YbL48dwK6UxargixQ3tfrvIdTr4mkMiquNlayTk9g5qXWnEXy+I1DB
+HweXveJeSUHhYRXdx37y2I8Bz8HcuZF5wODEDJJuYXy7a8Q+Ar0Ll/uQ4NXE3iI0
+NA8RA0caAlc+Du/xfzKdUgIPQaLt/sjhM4gPBDLlASUmO+PJfb1VYgDIbNbXiR9x
+92ePzennPnbhKsPcuZzXoc/jH2BiQwwRT2gLscZ86n9O1FNoaPAnYERlyNIVrQoC
+0Ll6NnGBM9Ls5k1royQQtZU2x5Yu5Q7DGcNqX2yI14AZrI4e9/Y0nEa+17WRD6eO
+fdaIC5dVrv8HZxlfzwFs33FpufovP2vlINWM3IqDjMf4FIQsoLdnmTsgoLRYm4JK
+zfcyiImXPt2iUrcybZHKa0EXYjrcoIVBS8YP1UTcG8WHnj3ploMxXOw0AmpXcznf
+sbLsaehbs4ugM5G358PMeWFXTv8K2YXRtArXHtkIYzA45zqWzpta5E7LiTQJfBRL
+VNtLja40a0gaajvROCekEzWhezZc7bu6RQ/XZXxBYHx9m7nhzKRkDlBrrJVpWSW7
+QmS0ptXblyt2tbaUtNLsi2SP7gP9ggTlc5hCpwygT+lxrcr6j18CiPgMYOgDmFY7
+gZ3jZ+HHd2+8GnimOai+r8wh1aW06/tLfIZxpIn4T9yGh/EMW/R1RTJjN0xe6oqw
+wC+TPUM2bMvDtAvdn8bYh3pVVLXnFa6LjhhgNvnx6wBoiBCJ4E9R1Ec0QA4jF/97
+B4e8TEv7PAFB+VGhIPnQqfsAqRfM88FwgZqSfZrBXKMVWA7I4fBeVD0cJQq8TwCz
+TY9Fi1YnomqTfacH1hf9KiX3j8OkfrhIM3+w26nE553/wOcO42YJ55NgnNXlQL2e
+e1s4uJ9lroATY2WqvgLy5Th8n5y6kVkjuODb/8hk3KXqiLqbUOmZCYLuT4ZHZ+Rk
+xtWuFpmFiuWgbg6Nr2t2KYXwD39pjGBRmmwMX1mBxmUD9NK28yO4HEgiPVzfn7sU
+1PWC7HpgPf797M2/N1gyUfrBbfw4OXWpycvmtJLXHEJi/p/H1bz0MuMJvPtNhzUO
+CP4jq0xbu9nT5eW9rD7kgvv10W+aUf314RcWKaLkOxkk2dTENjbviASce5X3ZU4l
+eGG2wtoHvCvHnNVj2ImKf0jbAL7dymVJlA1XwsLANAmk+9RGyVJgHn7ZkOfRVJmW
+VMfZ6AVeFY5BeJ0LCq1uE6QMClVx8fLN2iBEqamBNekcZ62Qz3b1R7ZbN2tlPKee
+JnLSouju6Mu8U9twVI2tr63OTh/a0XAjtlO0OAXuVcOmYOHT9fSjPdAAt3Rp50Sj
+PDvgN8s+qSkQKpx7C2OA9Wisrr71UrBrCfBhCOmN5gyWFg24PwwRKUnc1a8mT5Zx
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem
new file mode 100644
index 0000000..acbd8da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_blowfish_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: BF-OFB,B9F95E282FEAA06D
+
+StEkcUPp3txNaJlYBP+eVabWYcEzAkX64aj8vaDX64i7bVl4ospAs2stac7uXtXG
+IZLTqNNACoqC0jWWTDJca9vTEoqjDRKjN9yjXYfrovj5oKi79wfsSU29oH1dcKG8
+G4y8qNsA9TexRQDWTBxYO6EiQFVie9O3oXzjhO1hYwxldSWOV5ZRWoVmg16vAOxX
+Gx2W1twtjQXG/hp0HxosPkZteUDdhMZLWonYuqEw1oBC4iDG1Tjp0p5uSnb1gaIr
+pzZScikP0Z4/8CxiKV9/C1VNE70EHdAUYKjUx2PAbPaMFyO/sAXOy1INI7Wis7jh
+U2wKeXgCMRxmca4OMITcjDp6OGmKf41uWyTFwjO1scMvjSJsOZxNjAjcrZW1PPRA
+tvnhRpU9h1G9BOH2rM7VUI6zJ2FSNKG9R6M0WOQqxRegJzvK+YNLhw5lUzrbWOR0
+RdkKL15gfnuXqLTDTMuLX+aCDS1Mu/ZRmDqLWkJH4W1HJ4l2rBojX5fcbamueMyf
+Sbd1S7QtmF/B9LaGDEPMT12kOQHZkRBUYpyolK6BoMuRPYnGS0RkUwvIuPZA8uJU
+vHHuYRZsOA45YFEipyB/sek61bvqYy+8TaPxzpfj0fkh7AUSQmbk3qQRkQbltzqq
+/MkFShIzS7SUkyiowOet8fVjXDJPsw2bS3uOHC4zy2QQmhVKzCYWd4yCFl+WtJnZ
+eEkrZH2BpoCDEzKlex/NQlH9KBLOor221nJEVd5tkdWWZt71eGld20eFL3ewtDqV
+GJX8jFmR51vQL6NZ2Ehp/5zhearuBJ8VKJfFxIKSrbPjyCbEwUgYOyVHHyvYyMR/
+6hcflrUu1IFFwFhryg2bucAkdX9AhsO1dimxSgZKEFlZbihPBysCdUw3WRea57iS
+n/zqLrOm786KiWh0ndBgJ973g1x+OeuUvbNl/0yiO4Vjny6PkXcBOORu+ILEflzf
+UiEKyG8+cYzoYZjeiCFBxsA2+gZMdgjxVYF/lKzTqFkfpwYV+tF2K5N8W51cL8Is
+yhz5OHiENobjx3QeFCZ4LWDEXg1H8cA34i9oELbXtyG7W+hkZp0B9tRDrXcDwVWk
+4oYqWLNCQXqr1lL6cCuctKLdXbc1ibLt1nYGpJrPkPCbOshsI+iCMmulT23s+jqW
+TMW0RNb3wFjR5z9A1YTWfiqMKEcyzRhP6bEM/+WNmHE5LRefx+dnvZrVJzGZA/3k
+JAOpsxEPKv7YNR8N9yoAopRfFEOH4HYtLbsAA2sZfD6iVAXAAeiZ2Ehn+Bvek5lV
+5zIOtsXswRgzXvxXCPy0V5GWqMglbkUS2HGsWaHpxDSMbvBJuaSi2blZ16p3IICM
+7YcCLolKUaWqpXjhb3UypoYRwJs+40EiXid7aJ8rKoeId1SeETOwVWkz95NMiVK9
+5K37/OMvxOAdjAUxtmz/+v+twKfrUhYqP3Qkapy6FgA+qxnzpCFZZXrMKjpr99Pc
+QVNcvM/SKWB34jZGTo+Styc7d+iXDC1BUS/43Pvbka/Aa2IV/LPQA2pD44aP5l3V
+/tOfQFQWI0wCqpBPV8aXqGuqZU2ES0yc9DJ974a8NvS1cNWfsMcvNg==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem
new file mode 100644
index 0000000..2d2233e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,4629ADA1FF55BE00
+
+2093wYtiVZThSK/Ecf2pxfukmymwYi+yaWhMDfxz/O001tbrlC/emwfU7iprUPeD
+NJyyAV4GLjUBA51tfDqia3ATKaBfUtMQoC48+q/Lkr5KhLZEU0LLVuGrfvmDXmPb
+Ne9Ud8XZGnrDmvAFkguzK7cF4PFWUX3l5oYKinm8he7pA+t9RJ6QX7+BHKQHlWcR
+cT9e1iN7MykRD2Hh7YjSxg1uRlJ+1H5zIJBDjQ/WIUMj4EdNJriurt7eYY2XrP9M
+fyvTOBgYRHn6uQU0tdV0619j5yjEBpPTRf2M4RGOeNYGfvmk4RcyZPdnccDq5bWT
+w2XhhBPZMdCHmDPTCOwgfSvqBBX6OtH2EKd1aJQmtudMATPjA49Q2v9ZrgIQQxmA
+ZXIXuYH8wNPlzpm+abolucwIQhWJqr5TP5q7IKfYLD7FIjyrPBJecGoDuPB/Qp8x
+D9G73DKYgu3aYEFxcjs7tWwWe93pn7glEPmuybK2HP0iD5/YhXy9OUElAUZVBHXb
+WNyFdcdmyP/hcex5nI3Q27yM1auTS4Wpmvg9I5Psr1NN5ilWFNiJ0fr/YcOMpVsz
+NqQPuSLqxX5sg7X6m7MkE0/k8PfFO+tpy1cC/K18nnka8WgH4SJ+R1I8WXLKFznU
+X+mWcOaci2YBUHT7TWRzJ9/5bL0CEWlheabTjqbaV/4kiE5L0Wcbh/am56c2YAzi
+6MzassP58vp4hHXTyda94+Kj4ymYFbRBLqh9CVspolwDhy6e7ydcspGz/RRbuWrN
+Xc+lsExkvnLkYvkfmaAU/C5ME5PNjgM0kH0qXLyXPPtdKmwWrkGjElzaY2iajzpP
+XEmnYu4E8AsNdNg3HVcQfoUU7jFq1NeB4uibFrq8vh6VLmqGvK6XCul0gxJsfsh+
+j/38B1+5I97I0oplDZrAQMgek3BXegw6HZVqADC2KH4Jir50rYNCFrN1un9aohHG
+BdTzB1wGkjW2fJ/yrU5nkkTYcNhl9zU0D09XvFvXyeRdLzJL5eFqqZluwsPPw/TM
+CSwjTZbbeS2LvvstAsoYGfQTUr/E+BOXVpFmNg+94DBxwM7lCy57nG2Y6oIy8Qcb
+IfmF+wKMZEVJxy8O2uaCYUwU7qpucq1tz8l4bTo8wUctxw80Iflq7WYg/8V2ilro
+F1nSJ7gF0bn33KwlLxLy7akXiol8Rg6aOg+cAiMi2Apfg+5DXWrKf9YOwebDLOX3
+LWvDuMYRVccwVWsA+X4zUezGjVNuxjnjtsDfeiScf9QyliK8kjlMP/r+chrhFFzc
+LXARzcVfYCQhF6heOOY9YTHvcySV4NmgRKC/dlzvN4NMGh8VxWiEFDo7Vu8XTXpN
+7OiSd/BvmOism6emrC8zRMD8c1ZgCxuY1MOMVXRir/Qy1IWZXiYmI71mmJmRhE79
+Gn5JJ3aZ9xZmr34l296CWOBY/suTRvkrfyMRoSTC8Z9K5nbd+cm0MLzWMgiT5PAg
+cy6PHN9zVWInz/2z00qf+3lx45ZmMeVj2+2h1PFapXaCwvek3VgsXL2HUV/mKNcU
+ZH7mV8imvIopRSS4YQXB0Ophiv6i7lJWdKrSYd/Ac+Bt2E4z7q7y4wFNlZBvsBoO
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem
new file mode 100644
index 0000000..814ff89
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CFB,07BD7DC7BB2EAC98
+
+yH7T+ZIRWmzcMociF5wV3YjHWCUMs9C/GUrnBP37vvJrBDBB3x0u6aQMaOs0U1Ih
+xbGOweaw7cMag1HhafjVK9ZFZlYsCfXRZk6JdOvzPchDctQrnjkDxnwpOllmp0w4
+Mg9mYLuEvN968Tx2TS26va/rPAu3xxA8mrcCuSfyt6O9HteT1axwDpZzOktmnbYy
+xHQDRcpDXaXspP2sVTaZJ3oq/AMGfrFXCu2m9jFHcyZKmEm/DW2aLmfOI5I7gCLP
+1KMekkauODnQZEE2Iyi1SVbTBKH5DPp7yXAXWOtugBcWNHbMF9QHqKlMs5Hd2MYg
+doXtBSRRBc9pLdF1FMwHHjPFI+GZL3hurqcD+YyZJqYvzEgnI9dls2K8MzQKYKDn
+6VpDCNbEf8aC0QmvCLIjqei5fH2RVYeV2M4Db1GDmpRAIRJEq0fXf5ojAD0Mhv6p
+DZYsz+f/MLTGwce+HCWxZyAyfptdK2ScfvaH8mUr1OHd5IdvRudh5+9sCtch5xQL
+DFIp1eBRd+2gvLBMja7gBE/xHXoFZtTR8xORCwgYXVrLLf4wG27XLdKQVQiS8dpi
+E+xCtiZmZfxb/1Ly9yHP/ehWD9DmxRRr/n1QeGMjSlLSzffuLgt/0tftK5yOSZri
+Xc1T83n5rLqhBglNEvwR1ewsTgeIxkgZo7q/LFajrnGh4L62cIoLkLX3lG0jaEC5
+VTa06i0b7U1nJ6kiqjHuXzkZWjTim4V7p7r/SQtAGuK3s8AmqJH53EMmiK0zFq9Q
+ao1ewixzD4NplA2HY4kAAVRQMR7WWIRrV2wXRTqoKwITMbZ8Yio8PwgSjsYhuzwv
+Mct1CmTc2FcCH/+AZOqc2HNS4qwQVmwLnOLmsr7L9kgf9aPIl1hkn9KzC6GAU+fZ
+F+N0Ti7d+ZkNAtAUg8fi2Bf/rtPvxmyJp6QICI4Tj4MFpGIRWP5rLwU6XXNch0l1
+nAcIYFvzLNL1v0TDnDz/CFW7XSp4IaDl0OLyAt+JxnPuFOAo1wJOhUWHheGynEBP
+U3K4u+761XMdqHb1n14OSgfyynIuLM6WtnBDoevKX8v0dYjO6PnvcuZoRqs1sYKr
+D93XsV8uMv79Oo84xQPHpJrUIJVLDeE5GLFimD7rUPvMURg1IrFnGyfcMGTvsv9O
+us/B1dNmOHjG7eZwJ/8MDNsYcpwm7CQsTOJUZkQDN7MZOKJZJr2gQK659eULJwaZ
+lEkR2p6A51etvlSPZ2pjy2Mgxk/T0mX/mVprEvCkxFWGlAxys1UFWKHDOOP4rUZs
+iE7nxBMyW+4zHAcco4Nly5gryqWiW0gn99/I7+qQHkb5X6ydP+GKOHmUdcb8RPIH
+Ec3bV7mBtfYxDC/ouStuQdVC7jWGwU7PeQqoz4d3mhK8dfeOvpudiTD1BLw30LKE
+Dt8/tob6zIHMEA5NTu6g5cbfa0lhRH1tD+O/7RejWPwOTc1LbY2igvHoh5uWTo8G
+ufvYO41PElmJoujef4njSZHcMvHArinYdlWlvMIg52d7Y3lQTTztY2UeO6DKRHx8
+Qjda5g8SDiqgFktkl5r9FYfqMQFqheSgKnHaJ2oPPbwuJyuNdy2Rug==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem
new file mode 100644
index 0000000..91a3f49
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-ECB,451BC59702897B57
+
+lYkflQyHR1brYuUKx2oj0+L9fRwOhpKR6NMeH2nlLEMz1yntUt9DGuBRwP4RJs8o
+AHo7amQ1YzGpQCEZx3p+tMmk/hHRcRmU3ZeuP3SlGwpUmbMe3NI8I2dvh/qDL3Rb
+QParp+YK2vH/u/N2VPB11NvgwoUQpfS35vOhoLk3GUcupSKfbsbl/gn398DsgfoI
+d0qD5VSxNutst5I05pl4JFnL5+DBv1s9w68TdvAvBqWmsfhb4ei/mSp81e6ndxOR
+VLF5hgXauJjEHvI+c/ITF0roIyyxiMMjFd8IuIHbeznIjOWn4P5YcNcSswSG2wOz
+1wB0e8dlskukcUGqFS6W6mJzqb2TK1Eo+l0w2B2rNGX/MlGV9f6r7e0DQQFH0nCI
+nLS76C+WB5G6RA/7OMOWtsMnYSLldvXBxxZktcD1CNjyvuCOI5NK1KmG/Kajho6S
+/+A1mTs274pI6sIsCNl4ay2pfgwjZSWh95l8+YNt7o0C5lHudZ4hZHCDT8U2uCoe
+7dhj+KTuIS3VPI7lzruMZBGAj+haZ/cAEdqYGXizOle4MwKM5+lS8E5gEviTABua
+7jqhqbBE7CkN05Y3QmyE48yzi58hzSmiTOuAJ6jhB47A6Vsp/FpKFzfsK4BoD0Zh
+0ujT2BeJhtsFmPY6+RLtGITnl1498j9FTfy8ZNdrXEMxvp8SnEzlIKytLQyNoz7a
+tPCe1od1w+MUz0PHqDO/Av3YMULGLCUgnuZc0YjZv3P54FdC6si6KFEEqotIGD0j
+C24TXqlBpn8Qqkht/0TmzVHq6U7jynOjD1VUeB/gudPlHGLs468c7HzEzbpE5h0G
+1e5o6D5u9Nh1ItMObNrjt8NUxbi2/FX/Nkm3J1Ogno0ngzh15jZUfWFPAGkI1nho
+12F8Sf7YTBizPW+sd5hDbVejJURyoj/jt6UfiVKUg9iUgOW+ZzgkbD8RvC207xis
+QoF+2Lr8mPsNabUaFbsXmQ+6F0Pn05BzyBN2fyTxRt6u0CKmLE1fqkIuQywk83UD
+hBJfeewGoOGvoXDSy0ggIkjaRCsk//Xvntt5HEmKwc/wy/1Nzuu9H3C6n7qLqyNJ
+mPhrOGXt6C4LG1JscqS87z4VmhV7mol/Umdg00HRHs7l9qKRTePdlq52JL7oUws2
+CJs/UTaBHdbV2vh06qmymtEyNmQ+PrweEL5U/neyeYyrx6DsyUDdY1h1n+aKSEyR
+eittKv/pouPSLlIiMeY/DzQwN1ifoGsfYgJRst9Ry4MdlahpCTX+K7X6ryEOoJ/H
+1IEOm2aSlC3qEABUGo50IqiNF/PWugS7Qf/JzXAyjtcgQdW3cskNDCR7JVJDtATu
+0817ST0QXBL8qT1C3z843LcY1HpnQ1MiQvM3maDHCxuoEoUrRILWc59mc14gmowq
+g5XLMOLC/y5mX5LDqkxoKhoED9eM9/9EGSSy83dWWVZlGNLzu/JHBiWa3tVhas0U
+LytNa+kN8UfTC8KPe6i8euhauunLIKkq+MUBWy6agFR+jflE0zd0Av7Ox8HPbGe5
+0fraChwokeFM44fy5cOH7zENfng0jVUUreTpDtcfp390QW5Ca59J5/5P2aUBLZHi
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem
new file mode 100644
index 0000000..93766e7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des1_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-OFB,62D0879F9BE636D0
+
++iyQyk6TcPldmHOJyjJjsJ4BgdDqqdQYRzQWC/WfDLJyw3CXLquWDciAw5aCof3k
+b6R4PvJHzvG6j9jdlcv+yD5M3j9ZVHYkLL0fTZA/LEODUOTX74gNZfoz3FGarYIV
+TabFLgwQh4YJ0+Nb5N/oISaNszC+wxf20D4N445kvuHKbak7o2j+5ZzGId9zYIPU
+Jat1HygggKh9PtE4NildizyVVK5h8ws8qPWbe2/m00Hf5R2oP2YC3Afn6kqMuueJ
+RrvP9l26WboAKFED91xY3gJy8r3KkkLOJq9856BlndtgkA3USqRM31W6RvLqHUDy
+3l4ZY3wSTCdZIX+iHV6Qm3xYaIHNzYjHRcPQKdOVmEYiUSmAZmcavcsPC7sEfD7d
+OMEbrYrztF8iO90Myey/lJxo9RaL5PfWbtXqnXKUZtbcudEQd1fXM6gzdMm8AT4F
+eUSayg1/3AGEEHq2PH8kKtxnWAb7xBOgLbjTuC68f38dFw2P8iWZerG5lbLsFuwD
+YZ5eItuDhL8+dbFxisBX6H0lzcm0pwK1HCHOvSCcYfpWC4QrU08WbtI7NCqIuRWv
+4QOHU6SoNGW99BSnUlsqgLdIcsWsyTwiotZqusZV9AusdsGqU5ixwal4YX/8JRg+
+93EwnFnl1Y0Bj/yoAwNfvPlZhtjevsMnPEbrXbFEm0Xw1kdhOYokrx0hQWUmdt7m
+cFdmFBYQGsiKucvRpmInylrS41VQNbNySqQ5iGa+vDaPBMKZusvgPgwWSchotkzT
+qTQ7HNjszwR4eIjBOiBSvY5YXoa9H3irdmLn76mOyDMjaQyC9o/0tbAagLKADuF1
+Ui4Z/3WV67SuUoawqDJsYEWbOaNFX04wFby0k7oACoNxqoGFM3ITRzmxnz3ZyiPE
+DV/grOZICMLfTQ81VvE8/w+w697F6EJ8rY1yOznglP4GXrtIiXAaJbxEOhosyuN7
+HikpDQ3GRnPzXeg/Yngzpp8JMVdxKdEItcXnWd9uhB2Ok1vXH8LjhVkhrL76bJe7
+bhagz+LphPaLnkE5BPHKLUwL8bQQguz7ITfxsEFpWIHG5zCtpaQwdMEj2ePVubN8
+sfZ3qhDRNG8DdwXgCbCot16SKGuOawMMC5tsoeg3DFQ4MBDrKUv3C9nF8izTs1Zr
+3J7kWYrZg6+hVcJDgLS3t/lbFIhaNAULmep6wl4Vcp6nBqr395r8/uDroOpoBxoa
+BNjvFaztkRy3XmNHp3TOYLg5HZPWsK3KXOs0FvdTMEEsnoj3PXz6+hw0gMV6huYp
+o24r34gKiwdbrkbwLRnyh0oF6d3bPOZ9WnPgA2y2MB+slulA47+hOMcP9+WiQxE/
+eGd6TTRjMPopQXJw7/tZEf6qyVYLWfKJmI0tljsea48NocZdsek+e4ZsTW/iP0oZ
+wPDYNt95V64APcDZfNtfzydp0516KY7p624TanOXsxNNiBV6Nuqmd0dGhbmcRC8Q
+KNgGNvgjF3rhqrXZyFpnZNQewE7a87bgmO1O772QU6GmPUZr3nzPRwE/8+TNA9AP
+hHL9HtItZ3arx7eJ42obFrxj3uzpQ8WQo/cGLgQT0lz6u91xJyWi2A==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem
new file mode 100644
index 0000000..9dbe30d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CBC,A48C2683D96452DF
+
+dRu5UKxN6kr8aSBwZnynPwIA2y8Dgu6Xf2vCf0JswuFMJAwFGjiHoZTmIHuAjArK
+GWhiMl6ak552D/Nugz2SNgC3eJo/LOP/g2NIJnG09GuWOGXkiagjDKNbPCiIBPww
+STIBg5ilKV07lryS0FxQSUWsjI/2c0yxk/6MGSzQ6rrAWB4Cf843u482w6Hidr/E
+euPsqXJDtlQrKQ1gaMTJiOY9Y2H81b485MBN9BnKfDH4WHp49b/akcditst59fty
+FtzwyUTee9SGY6u7oKaUUe6sRzFOeeRR2TgWG5Bs5sne1AFFen2/q59Va/7/iXRd
+TOKKUGR4yj9gA+9EIpDF3n8Vn3G9LnTDFK0Xh1m61C1mQmXgEOqJGLVreFq4u1xq
+0J1yEZKoXreZJH95+gYAW5lmG+jNCMy0RO5PsTClx7G4XcIGFZAXi8sXfk3FYLT8
+nboMgQ8IXFjqO85FIVMt+xCpov+S8yOfPMOU63zxrynaXD2eGv7y2dTpeF3Mf4Ek
+be0YrQEWpCtYUdZ9AwA4N0/vkdp84/WZ3Aw/i+KUqYKtK2agkJYtarqj6iUweUvW
+GgWvZqNiTAd3sGcxffSbcdSRpuNttnBG77qAFgFiPXtvJu4wRkGlaxhwVTyUWK2E
+HvCEsssbzX4tZ6GUXScXv4zg3YaDP6HXsnBENl5SGXK8Uelett6PJhwH7bfpWysG
+Z1TD75uk6twThhtPURGG4GUaQ6cZ1RUsL9/y06v3ZmfUBxeVGLKwyMzlr2FTYenU
++LcvzriycweTLMO6llLVQH8XwlbAZ7JgndCjZodtFXhjhrS5Iu0sO6J2D7xFvL3q
+/Ym8PhhRStcVjijX+5+9aiA8AkXK3khP14T3yhPLu7iayl836Lh1+O1BHiYgr9Z6
+DdhCmO2Esa822yxyOdiwVlF+mYQylEZQy3D3kqqJytO9pn87cSvR3WbPtFOStlcs
+Htms8SdqLAamuWLGZiycPr87mSH2By2JED//80fNHdR1D7cvPU7oL/ClFMX/F3EW
+UJAwSXswmUxqccBR2hOJ6K3OvSIULoUn3awM/qPNTQL7rg++dSzUDbIiUywxuU9N
+nXkqfBVjoJTjafgWd39G3RdoK0ohf9QFj1nqYfaQGKy90cPVw/FdjRyszJWDUBTq
+jlKXnap6ZS9PGztjEoLqmFaFT75RUR49NnNtmcKmH0i6anjwFWEYBM61jox7gH+g
+W0r+0R2yijAspXHVpuibx9vdgkq/WR4A36t6DEMajOHM3SVzbPzkHTV5HyYQKnaw
+SZLSdUk8VwYkGSylm3f64PJLxBl7TNtrQhFLgR/9QXkhN7U2Qc7WxRQzhLQsLbtL
+qcBLGH34SGQarQZ5dfo3t+B6IIW2HvHNOiT9HQsIJTz4Er1SbLNH6bco7hud6aOA
+eSifKkWLp3SXXS6wjQZzsSGZ7Mws1DRcL9gEhb4tgIvopQK773AbQ1SJDEcmBpD1
+NmxrTbb1TngaW6u/79Nng84YEUiWNDKu3ovoe/HLVZoDr3tGmy5ch0jfA6NOxEn3
+KXZCiu/PjU005SLyLql5dcGzagjnnURDi7TLue/97xtpI/ac0vL868Cqfm0+e26H
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem
new file mode 100644
index 0000000..451670c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-CFB,36E0C8A965F07E25
+
+L0GHzT9XVnA03q7rlchpiD4JCgzISj+B9GxKCrKSJJBC8bRTgjgrwySMQyhdX1nw
+DiCtb9q7UCxQ/j0VvHuoA3OS1/Q95mwCsnjUXYAPiXeR0NMJkLgv1hFU8EjAJHY8
+ZenlgfC1RNoUONucq7v3F7jpsqBWrxjyDXFnWwe3edSfUzkfkG27NK6LPScjqdY6
+kJWAkHGpoGog7cYVBJ78LbYYHSBR+xfeFzhVMqB78mH8/Y/CGlKvXnPFpiJCY7Af
+zpd4/PJRVubXVyANc42k+0/E2oPOSKiwiKV79BxFw8g+NxkhRzXeCDuzvExKL457
+cuPNB0CQLSVNmOWKr6mA1bIBiJXgASzijsjkyoH62D/QoBo+kBT8W3hiHooSzJ89
+flhyknT+rVuAbFdPGqriS8siN/r4Qq/gbQIFhNe9jsSQesfr7lM3oK2EPGpDxstf
+eKc+EhHBlT4S9X+AilnjK5il2X5szyhOFZQ7RdAiqZ7X2KPNNqbeS2L530ZvlL+W
+Yw4qco88cilN276QQWCcrp3YcWv+MzawlNvfOOAb4GfUlR+njPxRAxM3rGVXiMn+
+6UL3X1SqZfADJOn57S4cDoP/A0i3FUfoPTwQW77LOAIzLSeMi7brQkZi5J9s5Izm
+OMcEi+GwBrkbPl67fKMnt3cHeFGJmOftrLZCt8HpGEdiQzP5iiC828XvLLxby5Ue
+BGoBILGIHL3OqkTVjBbSODKFZTIOQdVkqrWKyXlrfoI1meATptP7/GhdQP2DTW8B
+ppmNgtwIbGLg/AwNmGPdpL2mP5SZLIDJHd81BL00xPJFCR9wxXLk3hgm6auzAsZV
+FYjaIQ0Qza5kBCKNqu8ad8edqgp5Rj1/ZzfCWEkPRHD/lZ7nj9vuC/dMnPphohKz
+q8/L1+gbp8dwER7sEVBiWDE5u3lpSbx+1qkk2CwOjE9eBh2Mr6qLL2WIFb4YUvYI
+OAWIU1ftenOEjgjvYZcdeEOYT0UF6/avfHDPvkTIwl52UUhunbnqCjQM3qr18rbV
+8vB1bC64DxetUPhDymLqJCe4QVQajdO5BxQ2wwRjHlBi94nlAS/uOFV+WwqtFKZD
+TakruYhw3VjGxtnjukruMzNjDSqxd8Jabp1oTHY57C+aYQcBo34XAr+j+PQTPXEj
+GNL19MUMHJo/yk05NZfkyf3/+YtAV+/Gle7TlWWCV1nvEwrHPE4yCGi8j6qtCzBC
+TgpXl/lxJendZgVzIGGzMDemJgyrLNV6ar8TbOz6d5GDV3S84g2S7cToMVHX4Z8M
+bR53pt/KfH27Wdn68z3Zd7sT8R0g7yCVIc0BJgRrZ1aLnyKLSUk7iJULg3+B5NwK
+JNucRiU6mT5SUiyS5WjD6vZVDjggAx7H74DP04rzgzcHvTB2gzx1hFzw6WW9wcCk
+7+RiY0j13M/nD8UjW+pp/Ugk4Oc/bvxsA2tWQ1BeyF+KSNj/zjHMwN/sp1/of43X
+D+lcWS1hCwMiy79KQudrkc2DiYKWSIiXEFlblSJGiQz7SxybtO+D0PpVmlEYWiDF
+AAMz3hM+CrWcXIFNw86mHSsJHvYsSjbCB3ydG8L9OdATYsS3tZo38g==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem
new file mode 100644
index 0000000..c3f285f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE,8B0E5396F9D19442
+
+Ym7x4lqzxkC0K7f3nTtR7/ZVi0Vj36NLORWiJig0qvSmH1rhkkmMjssQqc17kWRT
+ttLj4D4s1ueQBlDFaumMrXloVp8c4zQS5jbHNmf+bUsom+HXGFHbjPC0usHm9TAl
+pPBWMCON5uUxoqJhw2mvrGSlkQhkkh3+Oiag6fxNxnN8Te/yTPC1XXCqIh7zRjCN
+q3wjkh8+0QP8ui2jK/2zrlbwvCyggs4q1YhVzWYiecFro1llb+CDCz0mzKEXj1MM
+MLyMdcooxXTb4t5PhkW87N8PSWXeJEJTxcWYbZ7bf+Bf68iHm6JChc/HTXZRLUfo
+3lACV21KTTI/614rLl44l/Ftg4HDSE4UV/J2JoenbRecljKXneeVj48Lmurc3zZa
+rj46e/pXEGfeEGmkuVnriWhRBcK8Mq33XfY870RsP+4bfxd2ykJYyxFZyoTT0sAU
+LJ4KIVZVc3/jB58CRBZDV4s6/cA0uHPhprtzEHSxp7vI9N4dQAWaUBMnDtPVC999
+QjVGYKRUUNp2S4XVLtMH3+jZ5ntvCTTabjuie/4TAxoUY45CwKjEFpWtDBEWBbXe
+zmIQYCE+o8hSVtt8DFWdz8+PGqF9QgWZ5iQtnp5hUKA4rVeaxF7+ktumTrwguZcZ
+6ZK+K3t4lcHyPZMQBoiWijmBLoRsoQ7NIFEE3sn9muV0XUz3hMCRapWsqS4fd3N0
+LRXrBmZuizqzaNBcDku7lBbembdW7EI9flzY/0Q0xRl7WjOdK6Nj4V2A2MblQoh1
+J+pvV9Tc4PANApNLcFZSPawOJVyUtmpX8QZYTe7QlXQrVIQE4HX4od1S3/ZlydfT
+DL8Atfec1sabrRFs1M86lJGnYxsvismLVH0VmkigWe+4sClAl5QrtCfGQepYmsYi
+jyVruF3FzbOCjcv04x4a4HyKRHeCVlsRlSq/njqCh0WSc7OMacpQJZVvsUYRCaS1
+7WhmzeiVNjgKXg5lPwta78Kh+XbQUtUGryQQrwOnbj0SDsho2hBTt/gbWDpxoQjL
+LGPHVxwqm0GZ4bw+4IXwltfei7MG/ceWxLZYk8ZTkc6r+w0+5HQFKZ3JuSKB3OLm
+rK0m87IybLY/Zfap/WLAmreRMUz/FbsY9Vjh3gt6NqrDhqLFYCyyUKZyKrWnVlIj
+j5vohFGbq968UYVavCZ2eqmtwWywsBXLOabypgrIUQhmCxOUBM7Mi2NVrTqn8uIO
+G5+mwzsy8imChv3Zk2/LafxPpajlu1MuC6CtMdZjV+zrGxJBEUxADaTJU7tTAWef
+lUjlZ4l/XO3vxSvv/F3yONmgKp1t3naS0ZxxYalcMRi6xTznW24r5voOAsVqIz5y
+Nl5FtPMSCBE4FONoUI4Gq1GAen2h2/Dz1Q3CMYAvJz/QfpZFu4DZ+jAUISU7URfL
+7P/lXQhg3onHVy5tgXhiXDhCCxY4pUPSy57eE32F+sIGeltoXU2Okx5/ey8ijr+i
+5URStFLeFp90ke/EhdOuhDoE++7G826ky3twqtSBTt4jU9IemH0agFU3PWIJffm3
++Ezce6LusooS8Bqs9rYXHHGe2q0oUNY3ipggOzx4Th4mwg1HzBQnD6FU33M/WyCw
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem
new file mode 100644
index 0000000..c34872d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des2_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE-OFB,0A4E382F6060AA1B
+
+hIbY73AFUCWIkdT7MEKMhr7+uSoSMO9wihHjhiHn01cq6kTe66Vy/z9dmTcgbK2q
+edRngIRyiTqyul1dhQ2ezVDisowHAtdiD7O2/Z+YiXc1hsuC/uELnYV1hTUg73Qb
+v760pWyH5AXNpqGsx2LLw+hstiiWVO+/Hs+CqtM/RgONfvUCzbyOQknDfSTDoVXB
+W4gEDKSDj+ydXm0ZmMS17DLCXgk4HBsJxyiK666l2TzB9pnzj6EDA6hDsiHfy3z4
++MxfcnLxWw9TJPxdLYVdw8WNWsXQd1JHQz/BQ/Hum4eNoYxLGgsV/hWQmkFil1XO
+GkPjF2z44fxN4FJjvQskrQox+5/gvnG+KamfvQt62qN16Z6ROZu5buPijxmXoecq
+gW6SyeFbnYFn27hglllax9awEEUtcJwi6OxKAkWD3REjqCfNAwcqoFqwkxlPN3IH
+00Rksn3P7cN5IqePVjSdwIhZtCfeBW2267oNxb870CDon7OlrUdK8KIjp/x5jKUs
+Pjehw1Ovtvn2YUQnTPvIYQsgdq3BMb9ETcnPDneCVweSxHxpb8ao2hyBMyYtQG8f
+LNqvLnjh7FUyRenf3XRbqka2w8B1CFTTErkMm9E0OPD8tMtDyakI+8fMJDkGhGI5
+jMwY2q98Z+Ef4wDifOi6qNklBlJwjvvybeqhqWOoXKbQMhnQPqFnLGjp5GQMczII
+m9a0anYSvmNKjRtD1LBL0KDMUgIx35U+7GKQfjrRTURYtAK8EITKUqYoWJWXUevR
+t9cikdwQ2yDuDH/C+a2eaEHJITerdW7ba/Rxzh50VdPq03uUNkN21VZEMjcU+GPB
+sLQ50j+gSFRMMzMfDx0G3wHoEJNAul8x2+umCUSpzPfC5D6kjbyREm/fWEuQkvL6
+AUCheoD7ouRR66R8syjIbeCKhjZEXUOvxxNYHSySrxHyiCGE5xCSVDlTzAutvcOn
+kivQqRlO1C6ZoEWbGr1SPoIoi0iMoh+TKZDgMy6/pRWVbELW5P9JnH8K+IreOIXd
+IgnCsqKZBVN4qRPrW8HtEwiWW7MsoXGjhpVl8wer8cNmcfPTo3x2l2+mjV2r0xEZ
+Xmv2LEtjDfIUP6yXuID4OrV6kpqSDax+wmujr8jlETKf0uEi4PZAXqhrgh/fgH2p
+VE+Ey0vnDaXcEhS0ketOGmBIYaKzWbMH9iX46YSkA++5/PavhlbCqZZN+906jwEW
+6MS7Nq1UBoUiql1Xa8AL0p/7QKZH2mgxpFcBeCHF4q6HhebbQbCpveJgBSR7/12H
+fJOIubovV6AOx2kBRAf27bii5iwMjfzC9IBE+GLCX3CXR+BLfOWutTcqbaBRdmQv
+K4yJqB/WHYcjlLKf/Q8+B6elmMc59NVUfStMszkIGlTzMFIkObLHH1NYPSC700rH
+ZkrdbRGfcncT2OcyFbWZ/tIvUER/aHjh/BvZ9s8UyEVEZzsFJI8HA66sJzZ3fKaM
+8P7nXXagyarILIzO90JIwkX+ip//QtpSDPkrUtii6Wj7n7RO0REe5N5+NA3A7WUs
+Aret+KXgmsOi2fnTmCFjVN2QgmQvOg8PGx0yYx8gxWog/NAmLCVMjw==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem
new file mode 100644
index 0000000..6a632f2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,6D7B3D8B829964B1
+
+mw05Vw0Y4gDohoiqd0xLN6ZKCalPCK2F0QFSyAVeoPY39y1RyKdsg8xt/qDx73jZ
+rgZb/fQLKs/W6SqCAAk/7EIBNTCWf+yD5TTdG9n8viNDSNXWdyq172rEnRV1CWGe
+beo+YjNDh6UlZ1FcXLj82TpZ9EokUKLabzNkY/coVPLlytqTSO5oZmbdreuUxOyJ
+ktQJUmGBmBY0aHJmV2wCkOFAXbzoSfo+SNPntEUNTa8i0cSIgmZd4/QS2Xfa8qRZ
+c2R2hNyVZygru5t8eckKj6uvj/Yszg6XqQby4ktK/cYfveS85CNlu03WfjfI5V78
+vY5efs3+NVJi2+ush4p4TfgT0PAKTWjXwpMEiGVlmxBoPoFGtTXY3Xp+64QICgTa
+MdrxPDDBw2yxmWAOpm58eeRqAN7Jd42qBxerJFiOUZxYPyRrQvro6fkldUlbPNon
+53Hzb+zHXv9xM5aUqfEjMO4HyprhKT/8aZgQiDE8fHgJhI/S2Ho6Fzqz2/uOHzBB
+gx0m8fM8puQ11eRxO+oSE4OSKbEQG0Uj66cHXY6FbJUhsLkGo9HdjLSGW67vx7RY
+Q3PQApOCFcXLecfkXrUaAEeRPNqZXjCkF6s8bfCOXD1cr9BulaGpiGxdspu5Tk9Q
+bLtoX5VHnW9VoIoFsIWs1G0h3WILs7ynCE2ttDSnIjYZhE6pRBiDHRs3J6dH/oOh
+c4dFaapkisk0BANJduvB7vLvvbJ0Xs42q+sRUCWzHNnJ3BqQZtL5f0dqu1AXafji
+qwxcbrEqJc1kOQ+iRAZ83nVlVkI/UgWzTceYPR24Q0PnAux1LkoIO/FWbhm62j3u
+xS669GX+GS9urX8oC3JUYT2n9dnPL8ouB77KfP6c0GVxR2hhiLYmyP2600C5q5DU
+6rdNm6fb75nrAmD0cgPxbdOB8zbgVvQuPXG8QnTO5Vvhp5ETgifIXPCIWwNHg5xL
+o2zrAdrNaio8FZUVPHOvMKE6Wl9QDMqnnShH+8VhLk7+LQpVDewBnWaMd8pK8qGn
+robl+i4HWtn20uZIDFyI4ioSa0S3Kanvd9TkchEbDjKAVi1QXdcD+q9O0AYt/X6n
+ygx2DGhkNYMrQmc+AIt7dAPa6RdZv50AAc0R3S0DBaxtd36pWugT4WIEexmuYj8S
+NbRNLuyjQMYCeFs/Ff4df0gmfeyH88YSlafnLyFhvv041LAbU52e/yExCEUvKr5J
+Oj2qVHJVe3eVW+FX8hsoUAte/a5foVe067dThfZDVp0TirozHAycgfKI600VF3Rh
+rvQiHzmXRoMptt5g/yLsTVYiKAF1n2hU9556sJPARFrG1xXoFFwhpzCS5t8ywniN
+6wwV+V0s4LSJFQJBFjLrreu9ZkYMdEOrekzqBohF5wG/BJILkN8hBmnD5gckbLIM
+QUzGTGxu+BIUi8JNkso0hwZDAKnYit+FVAs+5yU0NVQU6e3fW/+m48YI5gqFI+k0
+gIGmAyU6zaUJBJJQ4wc3+dOsy8sokqRhVmA59Tv20IKHh54zWq4ouFAg4Yc0bwK0
+1ua9GJMGTXN0+Trb7MKZQVKokyNA0RVCDN9AIfwCA5hDhJTahsO8Lp4Eolz2TFaQ
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem
new file mode 100644
index 0000000..129e02e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CFB,B99E3DD88C3A9D7B
+
+4Dsk+pNUGsgEqelOveMyrkoDb+khouKf83Yt4/qxX8CHs5q6i70NLViQWwqvIqQP
+g3h8Gs8cYKZfkEAFKP6BRFPy8EttnBCzhAdvLKrKFCZoDmhxC5ia+FxPLtNaDEb5
+6bgSoZ07KUMvfMZdnG5Kogex4DedqENVHBi2Rl3Dck1pAgxwzMntgHsluT4ht3id
+SgyUT/xAaMSwIklsjclR998N6V8Nilu8TDDf5X12RHOq/MSqGZ7yJC3Wb/dsirNs
+7jsEQwg9tIg5B/5hxjN12E4Ov7orIuO/WHNVtLznx1w1t/umPjLFn100Kln8GvfN
+jiGSB5TUz4t8r3deN7oDrGjoyr5OMnKWSsIwKcMsNSh9aTdkjIJBUUhIB2PStdX7
+WbeNXicNMQeteIrY+ZDDPpMbjsH1Kqcz5y9OWnvaXso5lSHLBp1IamCv/XbQcAPR
+zbnbN8DCOYAMcUiwcRAt0U+BNc1edX8VmCB0d4RQq5BTFbjGKqzo6yFVUOVLhiFg
+E8G3v8sTqUhJyH4Dmjn0oDMtfdplk30Ywg2wZAahnI9w+cZFvzqXshL3mGdu+rbb
+h7PkiJE5vS6/4VKA7pngsVanCRQa3btL43ekShth+DXwsziQixGD9HhTb2iYeF+u
+9niDPI5gzi9IfxIpb3QjR1xDJYAzKDDBA4gHhbEBSObByMsVzjS0+dwP9N6DV60v
+3x7RfO094FXxlVWSh2SMvz/sB9fsD9dCp/gadqHxhk2aJf7lfSU1C7EmM9hxGZku
+vR3J1QcSu2FMrvHyRzFZGKozSHq3QunOLno/KmY0ja1754NEkntGvPuB7LhGBNB6
+14NvQsl7qFw5wJxmEdY5rhVdz4PxLfjnMyvCiWlku83QIC51I5DbhRP7eG9rJSMw
+b7KFSQwmp2yzDeX+Ipd0JAgd14GvtmICKJVushO352O7mVnx3Jy1ZtJsonhzySz6
+1fGIvJI8jxZOdO7q1OD0bfrXS/kwdXnxoxn4pkjw3ZN3hdFTfAerVQ+qYJ7zIez5
+0lUihHNw1C/KRsggraOl9rTUNppcNtMYwKXCJOGXI2UEn8p3JIxEHLwXyOjTDfg/
+5oK2nPAmBdGsLb5ivJLPivmaqDXf7fdn0XBQQmtYUQRotlGmfpztujt/b2pL5YSE
+Uqginw65zyedjL6Aff3crvP8/CUR0JARx9vF12R+v2iAnDqVk/yqYpRqOp5elm1t
+yGB/PtpoRFsNU1hDnPZDu7kZV9oSeXaBDFOnHmX09qE2r869Aye1xOVmxiG5tm/u
+KGA+zlJVVpQSwnPc/qk17S0dvNAlgt6MH+vYlhKw8zk1nDCuavUK3hTFT+9w31cQ
+yjPdV4/K8seK4zIqpH4LZrC306/1/7BT5JXL6ZChATHaI68xwEY2GsEl/Ze0JrQv
+WpWSN/I269rUfaBDE6eFaiSDzq1xY+qyApHSTNPSPDHbFeCXz+puqv9lw0bJFnRJ
+nLsK2fUAKNvyCF18IydyhiGz42LYbwwjlEWuVsfWtgvftDebZRIfQFlj7DJwXfZU
+zcEOI5YyuQs+wFK/8b/bknF4xRpaXwt9Il7tcV07h96TDJV05illig==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem
new file mode 100644
index 0000000..bcdc5d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3,9675E5342C359F94
+
+aqJHsie4Ls1x3Tk73mbL7VyTembpkhx/a8Mc345TuZOZEkU9XYrkFMvhEB+jcVoo
+9ydosCL2d8xjDusry+vn5yF3iwE9HFHQ52M0/a5IH3sTtJ18BzAOi72ykGb2r6ly
+FzTq7xdXNihN19wHHnI98GKdxdQmNR9uITx8VRBbZdbRNGdJopS8zT96+AV1QAE6
+lyKKLA7qbATHR7JWQN2OYz05vGt48Vmq+da+qs5liEtx+GtNUxS5x8lAC6Llmq2s
+/Xv8X6kjYmxHSYWM2JyxsznGfdXKXe9f4Xxwyhedei6JgrTHa/JN/+tvgh5NWODK
+er1tLBRRA7atlSoB2AAegJC7gJRVOxRF4hiKX/19cfEpq8hF9+6EHGYm/IQRSI/J
+F0RGcnSdiddYbEb667qTkbLZi/d3Ih3KwKGww6ZzkHe/qPi230/cDR8tac26jmG8
+qoCwj+XCNOe9IUJsCN6RmLcFp4Tr4UVSsswxReN+xs5Ui+S3AY8IKscLSo+bB8gq
+DVBvVFUBTiF5/zO8q8H8Xv2c0aA3S9UQla+l3yoZygiUym+Q204Li+tDXiM602kr
+GGDA5/cGpQuit/7O51KF2OSwnnvLdu96qz0f9X+rq4QVNAy5PXcr2pj/y88UfSXN
+GAbogEXqpQzn0rmV1OWM8hsnOpN2DLcuZICCJFJc/BHO4elt65OfBjAvbxjhFU6s
+nJLUcR5EopLex46WwuucR6W6wjAuO8ET3cDV5L9wQI6DT+XItotk+yJyYawNPda7
+wfmxZ0o3qdcpRp7aw0ohfshRGJMuLnGVgLczU4hwO2/1LgRMnCywldacAfo8Ot8s
+WnC7d0jVOre2K67Omh4gLQTzikvFoxg5kjmFFxF+QOFakT/B3RMa9mgjtOlX0boK
+HepTxOtCaS+cZnL/fUCbWdnPxqooKid2DnVTNIXXBg3S97ReediwpSn6v6gU8QXI
+O0X/+syPkCRAOKLjCdgxFXRB1UA13v6iqeja9aXgzbUnk/MrT6G4ivAMsNS1cEdA
+KVKVpbiKchEpiiSiPyo7buZN6t3m4JnupU+UvcJAEFgdbPvP/kFvxywpPBcAycAM
+HgujJ9bE3OR1lfyHHTGF/f5lXGDzB0/ND8h7Pm+Bd0AFde79rCswhnR4oJsPLuij
+Uy499ouKhoxFTn3WMF6at2QLf36rfLHl41uSN0tky8trT9SE1PjX6yQUjl48bJh3
+MWUFPYBDfDPGTddENYo7hDmwoSLbE5WFxbAeJa86wgV/P4/QcDF0IPVa/wsDTPKR
+RIy7eNqxXBYhFeOBCkTKHMJ0XCawi4q2CAwo7RNuAmTrHOBN2hZOwYd6yoEQ4ALq
+70cflG8+rITJHOdAjXYAlcuuB1FjDWJjO1E3P9MwMfiFZBnJBsYkDT6ablfwgpaQ
+z9ngnzRqxIjqAxrRY9GdR3BEWgRIiKXljUgkk8qFSRIS1i3w+nHAipreOwizTVUw
+otTU++EjpQBracFsuGP6w9vcyhHOp3K+RzGYEQoh2vJm25lzUWBHvmVpCw5BBTms
+RgurNRdm1IlN+qSzriotjPuHr9Ucit7VFV/gXtmyJiNNPjTLpLQEZOUpz15eaFs+
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem
new file mode 100644
index 0000000..dad36ea
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_des3_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-OFB,C8F1482CB09D61BF
+
+0GfYpcSxvnnRri3s5PutcESsHTuupx6UcprKRS+B1neyPR7Ga0Z3mZ2/X0trJVpM
+cxJW4g/cU4TknCZLjIJlClYQenpPRH69yw6BTi6/pgUhKeGmQK9Oob6G1RMjS9lO
+MTb8DKz8P9GmDR4/3SvJwPU0aEM1EAmwGJV2beB2QWRhaPkAZBzeijYf+uYn0mgm
+hZwjU8tdwnNnCdUXdaHeRkeqFcL6OjJHV+U5SZaMbaky1U9lyIJL+GUQZkRfZzJD
+41Qt6yVtetTgzljtCtd4ix+RX6EYsWfZ3OVtwHGYpg28IdfJ3LVE//O9EkLZoBeg
+DyU9c0gDnQ8Dxl9VHGFwQvgdSEyJLvWDv+6RXvCX4Kb2Spy847yxqcfqDpjUhzgv
+C7FoBwswS0pkQzGXKgdM+WlBe9/GYOrzW08IYwrX88aihf50jXi472th6ILIkFHD
+6m419YsrmOeEMXGW/VIKxk8H8MGHwdvK82xewu8Ftgfx0WihfA70EyI28VLMQTAE
+MMHxxCWtdWWnmd1xiHQSX6vedPLXQKKt2AYxYmHQYfqNFMcvDc5uM5uM+mNkX0qt
+VL5PeYRYtdDtT5Xj4/acZD7X7DhqcOwvNll3J7PRdadNXKfjHR7iRP62YkIiESE5
+sCHhYXmtQqK2JUJr8a9M1QPhmAIF3FYr8wSFu/eWw8ooBaTxVoGCw70lT8LNHVql
+TYdW9sOnvUjz36oz6H+z55CNldor0tS/Bu5jNPOZ8F6j5r4xpTWi3d/UWLW7uBbw
+VTAG25EiFvQBXpJFqgRCBdD1Gcfoc+ZefLXQ1l0RJpRf1jJMkfSWvUWDRNm87PSs
+qTeDBzuLNx4A1wYcJ1H+R7ds5QK4moNlvv0hJrsqbOESpLv/XPcYrFgzms0b+Q1d
+uJEWjz38AgIJQxBxmoglzDSRx9OBh9D8HQ+aJLSVcz0dBmEOEtPjZn2AmxxccwCc
+NkMnAxXyNPEJhecTp2/lOOupQqMYTGe8aoiee3m01QPzfgL6m5p6IJdKzOKi0TGJ
+xNW6fD486B7i8d+VOnst6vnd4xiQ03gNNA654mrXIM881X5elqmoFWyup+Ct9lw5
+lxllAJGh7w+hf8P6mIsezOkZGieGhzrFnuLVM2srRDEId+shTV/0lZi4LhfDYroN
+VAbZ6bySn9fmP4Pn42zu4XjoZJffF74u8gFPo8oSFYg88tzjbPN9KAPInNxD6lBA
+cwp3vc1n71CEepmfeZFR6pm1wKRSupkOZNL/PV9rqsyP1pmPE3AEU7WYjNbf2ah0
+GE9f6dtLWcDP/3SssoSnZGy5SdqcNPymG9vOR+QD12YNxn7yA87HM3+swparlSYy
+Mhg1BuDXb5Q5XFVFdajFwAnXJblAIbuJAeHQ/mNCAnR3HNv/Qic2GF7X757MA+dP
+z86gFzJJtb7dtZ0WDQzzEVHgnfVHP5buXnHdepFLsETw9fp4ZjqPfHjLXIOvp9/9
+G9pmSzB1JL8kK8sexWgsMRnl2j2hUDYiVJ/LQjMzk2YLF5I0D5msNTAJvb/gFBdv
+ynVKUpIoJEfRaY7pxR3tufbzADNiqa8OUCGxZ8jo26j7XWDkunfGAw==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem
new file mode 100644
index 0000000..1763340
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CBC,C9CEE2FFE7D795D6
+
+hcUF0vilpOxap0mbziQfS/5kPdXsFb59D6myNYdLDAvBWUVAuu5g8iDDJIS8KPb2
+xvmWdXRhbsnfeQGcGWM1rMc7brutqefFp/OAJVymI0TpILMgef0abf49PEqNUa/N
+rYs2dd39fsyrJ0rcEWT2lBA/+GTLATB+16/9aCwjHjQ4L7d4Soh1laMo2K2Us6Eq
+pB8f6an5Y/vSIlnljl4upKOlcLItd//2ehQnkuEhI2Vafz+kX08Z3+OCLZfdNEq0
++8b5GbOvygEZbG+amZDB/tXnR1HB+AI7lR94PmM+h24COWAelatj2uPOGov54gXc
+iO7NDGoouysqfkfcMpuy5SkLVW4FoCAxfOl+LOU9p4x8+iaJt7Np+TO16dvX8MOL
+4WcIz4huaT125V38Q4UiB+WbsvQXrHRM4WCyJBGBhakr+FpNFdH1UPb9Unb+8UQL
+BeddEGT0l9AiSebT/JMKgFUOInQdKxOjg4NBp3asVEUeTGLeTN3o06zUoopzT0S3
+CHrpgvpZLf+4NATrFMw0HkcUK4GHZl/Q68C67qNGTc4B37eGcxzGo8QOyjXzKxL8
+Lh+Ry3eJpEXae5xDUn9yt8eqYI2vdwjA/3+XE6mRhu1sbPNJCcWo2kLZ0ibYgqdB
+FLsXBT8aoeKrW2p82OpehslbmswOKZgrPRYmNh1GAPz2jwBFfCEOLQYXAjCFViiL
+ipFLKLGt2dhjk5RbCraN6eYRn2XcIai/7dnaYxXkjOsNH4mmPzlzjhvRh/2E/r2Z
+hbTOoa2uFUtZHWtDXUz7ZzCJErJaA00ont37BksfHDdDw1HIt4z6Ut8Jm1cR5zPO
+pC7s7ohOS5j8Vr8j947bEXITC2ozcvVVZOCcHwF/PnUE1zx48HBp2m9NAZ8Bz3LS
+Zn799/RrNtJLnkheG0wIrizk72M5L9PZQ4FXlupfJ9c9XniaQ23GQFszagceDN8j
+z/MR4tTfdWRy/889lqZ6ccNmPAXdwwijC6Tw6V9HooN9m3++ZlbPfHpboQUp6+V0
+Wwq8gdnlYW/i++9n251xBsR7mQtFNXaYwFmLUTt9C8OobyWSsX/OaeQGbWiVnmAv
+vPkr7mh6g0ha/x+1vKgEOjqItJsGdspf8ePHQ3FaTkfFwhQ4eN9w4QR3uzM/7fnj
+ql3yA+G8ftpaU9omFbs+VqIVNej5tvjODQ02BbjSuRklAGxnReCS14vLwjg9BV6t
+Ow74oIttwlZof21BWsCISgybkPmMhkIhUNAAkHexzY3AiqjAtEGnpmvfZAX9zN8+
++Kg58DxudjHQwUO4cwP9p50NndrilBShkotdYIqekXn6h0frYuhspJVWwIVswNjX
+BuEZE5B+Otswbt/caj9C5tfsyKmnGToG4fpDdk0ItxRq2126crKQd49zZybyR3zR
+phLeduyS5h0oYNwTjq+Fg2Z+f6d/iyCAE8ynfqcAPK1WpM/02DBoLsOmve5BCSPB
+YYKdrKfkGbj4J2klrptGmqgctyW5jKGddE6NO4XFYV174rsdPoErNWWcfptHEMLR
+BWfopqdN/HMrpRLTkjx9rIeBJ0F+wQEEH1JehnWExSSSAhm/gzQc1kU/wihOStU4
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem
new file mode 100644
index 0000000..4284fff
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_cfb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-CFB,AEA62B1564D645C9
+
+NX4iex15O1Dwp6ADN+uFIycPB1ELvBDVRGh+OZnisNU9h+8dPO1cb3j2tkwLFK4i
+Pml4zz797d4I4GqdF2Y23dz2AoBrl2Lj0N0W01AlOGagh92pZ9dKjjU+S5N85OBw
+buDbADh16fSPW6Y88guWFXYBlGJ6HZFK/9D4CZmEfI2Pt9AwEIZ/JvWrs/zW5eGP
+YMFsLslsNu9TOIKF8iDnfcWM9MFpgwcFCIqTwyQ/+dka0hw33WsBREhFcNleLxhW
+NKBIMC6jNjpW916IClH5sBu7T8ps/7JVw4DUfpl8NAOaqJSicPGpZrGIZ9N9cfLp
+KD1XEy+yWc9ahV0mfiyOuzNnP2x9IEBdrk5uqJwIT9RuiFZixIH9MRuqAtrA5BIP
+dc2kw50AbXRghE0JdUEFfUm9zcRKdG366SgADnteNk/77gqI0OZJDD0XL9R/N3Tn
+uh3EI9joJciWDbEX0/751MfcLaa/EkI7quKMEyFGWvox9sKLLEKRUV6SfO/YX8ZM
+RV7ebJdW+Mxya/beG3Yb9TAYkrG2TT2+uhRqZlZllJQFnX7k5MxyfN5I+WJP7SEs
+Uy5PAkNv3h7DTV7dBFMy/gPYAooY4JzBnbq33af+w/VbhyhVid/hn9UAONahw7H/
+1Ao24IlYMza2fJ9yOn+ejLhjvwYIP5992cmElneqMdBfV+oaQTHtWUuVF6g4gJBw
+9QucqxH4JbYccwA1UiKIqkmOlePm5I57RbBw1OG/Un3SiPcAwiAW/UpI5yv8kNwq
+kZeWnD79kMBEW2pU1CTvf5f8aBmcgQykC0M8H25Jj2kVvj0EsRGx1LuQx3ZCSM9y
+sZejgZouYA1WuZaIsz+3t4fgYFiOHDxmSvPt6VtZAMJGmLB/Xa/PVI4rsyNv99wB
+UinlINhzeGKpYYHnUgN0PrRQl0LBR0TdrJ0eG1djEvflXsuAQVP7+gP+oCckkT2c
+pIVm2IzplT2wzsza6+o1SA5BF7RKI3A6IxySFEBJTeaiZnYeeJHxE2DJvU1Fe29G
+ML/lM02waLJNbIs0Vk/i+hyE1wtMwZetptG+En5TDzTkWlVSLSqW6LXVJ53J2E+q
+wypuz4akL8CaYRm4XTmIH3Tom3qSf7rdbL9gk8llZacFNqAl7x1C9zDUzKU0DAOg
+qPKAtD1s7Rtg+4p+5cIEAWD0TKX6DlXKC/EdYO1w0vmavGSvQrr+KENE4+/gIRst
+qlTCiEW2U+PPyOgpZAFF0g5y5Xw0Fea/0HwBBLfCiPKRmDHQIzWIEW7RkkNfQlHC
+iCTBoMRFDbwXJEI9XUu2N4RdmlP+84i6fSRWuzZGUACvzEnRJEc6H0FaaN+fX0wM
+Op5O2hcdA0YTGGmTLUAeajiQnqGRobC8jQL/WQRVwOiFU9rgy1K4Cu2T6eBubvVh
+gk/R12LezvD/KwLgQz1+vXa5Vgjp0xhpnLnJVzPqLG0Fmj3V4uRDc1Lvvl4uLJiR
+VFjFYlqxP6w+ToRqnrfbmUCuiq6pS9FQi2Tghd02P5TnZcyS2xF2X7o45gegMplS
+skPzTCON8140xpx6Flep3bHwzEI0CEwO8goVMc6x4a2Ggekjn/Nz2A==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem
new file mode 100644
index 0000000..d9609d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ecb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-ECB,270AFD04879E8434
+
+u8jYUJhoDMDNI5cHXhnJJ7Pm0lF+MrOl84maQOwfwZ5hBbjpx9s+z5SMYpWfz0yQ
+WlgBuGkaY1UNBDrwH6baA9/eqUzem9ZK+mYmjKC30OaumjKVJIB7cJfJf6Itcaom
+SH1W0kJYeDn7ANdmstOGxbr2TDCr0BXa+7j8cTo2TZX1rfsXcdmjQ+8Qa8zfQ3Q5
+FbrO+VNmAQwO7HeFjms38+ukJRW30EPibmbzx/YTCZ7XtCsXt6t6ggYja9Kvk/eI
+khwvFFk4g6Dv9YU+x2pyrkquIiTUo+jm3Vqhz2m0cGcqfynVEYn4fNPc27Ekw3uj
+CrprMgnfaX8QVx/EkpDYp7gpjcLYJObpUTcBo5iA7R3lpQ8itY1Ky7u6MMwQ2VHd
+XZcsS6b06mp2EW1CO951ZaPyma4AqoLl2gZ3zH4qPygp7uxrGdFdFSqrapVkDee/
+lLtj8Z+/g1IyVSIW2FP/SCoustCHcqeDDq70GKY9qiahNFybWn49vZAPB3HPM22f
+mCcw4ALiKr0S9oofxrb8PKxmDQMZAJqjc8qRMLktYh9rJLMoUG2bmQqpKmLLpx5q
+3CaKi3wofc005VcILyRgjumscAcpbTEz4vcR4jTwMPNP+WI8+AHtg0OcF+7hE8qc
+a9KTSsx3eJNbqq5UYxVjV/DcttNx9ENllnG+jEdttkaf+T9rJiayc0WPd+Eg0XlN
+ByBG0RCPQVJ9YH1Yke9HGE0FXv7FV6x4c22ePePcyE6VUNBoxdmXw+KRhRlvtXtM
+1fFMwUrY//jEpfbf193avTVVctDTLxDSmwY6eAMBm81uDTlpUm0q7l2rRuKzdgFd
+bG/MTOd/j7wtKJbQpbUfUNFtF6zjssPdGhJ3l+8Rg4xZyHWHgU5FYGodp9RsxUhm
+8AzoPDcVbbvu5YlPP+XvyEO1860fX6iSZKuOV+owjh2i51CPzsgX6OrOEb6/1rc3
+M5AkLVl4insmetdTqb9PHCgfD6bLYcDBj7Qnf4HEDQUGcRFe+jogOoSH40C5UgPq
+F83nXv6WYBb2Y97lhb44x7d1MzE1kkzQXlyf3QuZ0ZjOvm+LuOWkbQWmLj5JhFJv
+9CqY2MBL39EFamKjmmBmjrRsI9XMLHvB7VvT1hJPzxbF3UwDZ5BsA8IXSps0EjXR
+rZXSwo+vqTa3NlvysgvuJJUjwyf6mN2SVrNaKnZZ1OGFY1oQ3bmOgdI+SW9cpGzY
+Y8eFpaG2RAiOfBZ0JIyBUoHUH1MMMPw+Mh7KzIknP7O9htwiAWEvkcjWr7X6jpG8
+sBdBmszX3TMDTToQ6DvyjVRP7mJ39dV83bLI3EA+N8bJcTOcHijCvbzQM50WzMu1
+2UA9e6rG+ouQAgwaAHdR6bwm+Zr3e7MswZ0Q8/Snd1UdpyMyJ9nb031NSRSvkEyB
+ipu85/738J/g7tAIOJwwHeVWjL4lnrLC3CwbtvWAQ9Ox8Sjv848608GzQxFwHBHJ
+0NWgt/AfLYsq4bmmFWtqvqTjWeAeUsM+67UY8m6/kxhfRNNN3zZcckq2zlF7TRNU
+5AL/3KbVVLQl/7fD36m8AK5eImR+Gvom8ryzNacbNCL55ks0sycbICulXbdb0Jgm
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem
new file mode 100644
index 0000000..cafccf9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_128_ofb.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-OFB,E5989634C878E65D
+
+6o45POmHfE72UAdMBQrRIm2+oZCd8GmkmrFZMXYnVWP8ciNiGVQqUxVJS9j5Rx17
+8qxpNrzvcWEGWcgs9AOqog7YXHkxo/s/RIOKjUu0WhY59UrYcbkN7Rjyn3wSSD8X
+kN4Z2tz3iR8LnfljD2ApbR3yEYz2NvmifZzsac58R3LvuFg3Tsl0QetPSC7PfMUh
+B7dezaycDcx8QJy+nRPcqpGzeL/VVk3F4Hppc15gfdWtVellGcYsT0Z2Iu42I5nx
+HYFajRliBukH98M1d905lk1aNLDj54BBcq08JsDJN/V6DY+mUpJCFOK4DfP5WLJb
+/HCQg0wqsUmRHK3dVo09ilZa4OfrrRD5qTWr5boDngAqyD1r1fiHxcv7uU/HOSvt
+PU53frz38BA+w1pHtlE0TSG0oBe/+741kJtpvj/1Ts7nUeYJ/DGR4vmLpg4rnbZJ
+Yky5TaDV2LVLFR4syqombb3eiK5xbnjePCQFLwxYLQKZFINiS5zDr5mdjhWbIhpA
+7wg9BKNpUeXRDtntWXvEH9FmyIicbk670riEYEo/EniwrxW9f7MFhPUpOb9ktE56
+RnaU0EK9zUx1sIvcu7LVq1G2EVG8IrOKGcj4LHysBtg6PQW5mvN4AA5PZlc2Sux4
+L5Z6mJfwgBbBB4OuRXAYxHZbnfMTs75vL3d/HIcvSPcvb+7nfvNLiwlaBxaUfBFh
+fyDurHkMG6tBgE6OORgWraNEINJeOYcG2WK60qC4E8YfYCmc9V+28A//bsyRWyku
+xIDup68r+Os5RMRAaZrkIqaH+h4Oyd5RqcjLnAFF/wLGnNwSttYT8o7WwCf9ZCCy
+NFvHDWyWMUxonaWgvuSm9YPfh9/9CEsHkKh2RqBffFcZ1ktEiYaI+dGyty12QW2Y
+909pnCZkKsm1Lt3ts/xie20/gcwfsnvUC8OveKPaiCnJxDv3r9pMCNFPdcXo0GuR
+oadhn9r2CqNCDo+l6JWVRka2t8+yCAskZC7bKJnSeKlEDyn7A/2SLb196G2k9cve
+V2qQenhzuHmG5PEVfhLWQ7fL1BmJcRDuQlSmMGrdmOD4Zb0Truq0zpFL2qaMBQvb
+58hG5YkYehE25j8PpJYovOQA2hih6v9RytR2VKlTeYNFbREf1sdLfeIphB9tlHlp
+qZ7eOFAjjVzLsC4LmoCzWMaQuwNO1f3WiNdGVvulHkWqFnGS9bBBTahUUWI5SYiQ
+90vhSmJ7R7461rqWwn34Om5jlgRV4+2LhUbp+XdOyklujQYviHsOs8/wlg3lKr76
+SwrU5oYqlJ7FJoDq4IPpOnJaxsRjkr9foecgdqrU4SJKyJJDbkHNfoYq9r/aZJ21
+ruPFv5t021gJmWa87199GlhBZD8dxeXo0PT298Y3pmaaSdQIWLPeDAtc1R9EJLwD
+6+ydhg3ZVtSgXU0zQ2SRVMGhqoEXHDUrMtjKzuaZsYL57tqH6At6vWS+xA0CJBCw
+7GkDpM/lLGjyisFEQL73F0YmJPpb5s4izzCLUMxZQZ3u4T3f9OPRvAIUf8MiFJxh
+RJq2Is1gD7M8+dySkFeAbQ1STvLy29uIxKTE6BgNng5NrY03GuK/5A==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem
new file mode 100644
index 0000000..5a9eecf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_40_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-40-CBC,BA10EF99A1862AB2
+
+/CfoFtIX0zgNckXzuODWoCYVY6NoXOvu1jt7J5/BfSZUydRWKa2lpR3SWAUAesQX
+H/IK9Wkz4um0QgrHy2fmVaAS1G3ifwgQ9dhW1EMiCEAmuNwPsT2YBatSyxnzWjHa
+dv4eZ0Snk4DsS/Ajwn+Oc9uZ3u5gKnfYk3tXoZ9BDPQbgIz01UI/AyGHttB43brl
+e1C+zKgCSa5WB8wfxCJsKHDSEHx+qlipVvDk/pntc9m4AM0sp5wsHRw3i1iirQOw
+AG6qRs3Ro3jwajlEWPmJolhbRQWyA2rUfSIajElYFlFgxPLI10m0tO5M55VYXpWe
+cprQNe/TxK+YJTcBvyhFmP4Ha9NeC0Vq6aHiECpZ1uObH1brZ1bdYUsSGodRzGMC
+ucOkFDpsp9We48TAHqEGArCsKexxe1dDe8b+cxdvyv33ZI7dyr7DfHek3X7B2rHv
+tZYjgx0cKn8SNl9qdRync9wLqjL2R99sHgphkXUA7qLP7ZdvZEeAGs5NEuq5oyDj
+4aybPFJu/xvByOEZBwEtrixVJ/2h4KYF6g2vK5CgmnYrq8SUNGobt+oLv3FywKhQ
+AK/YvDt97wXNdPNqPciqCP9LIeo0B0cgxFIbOOE3mvYgPaUoTtZ48B/hpkY4flKR
+U7opVqbNl/pnh1OCI1ce/K5KPw0rvYgsEQ8Q04+dipPdmvONYGhcgHflS52xju6s
+RbosS+iET3a6BB8ydRS8V4oezbr7AgzoSv7Od6geru87fYpVW3WbGag4w+Xgil7u
+C22epy/AX8naBOsMa2QMCZ97avi/qhMFIERzhQJcxULff0lHQBq+HMGsSI8jMEiH
+d2OIERTWasAEPdoBnELO3l4oywb4NmSp09m9imihdgocDAQEXyLkjmRqkm5H3Tdm
+ALFIaSwU5SE/dk3T+BTmnfl+Anx7QNWTdg+ykfH8VHbs10A/K2zt6RyJGLdStfKq
+VWORUG7gYcVGIQrcJllxt3Jt4sG3t3rSKA5dukM7+D1d54ExiJN5DrnaQ4kX/v7O
+nENonLRtV1KqrH32R+tIuBVA8rbmyseVequTBQpkHbG/IczTG1k6p0Qye17XlnPl
+kEPE3CG8+1RMLvflA1rTimSh1WafHsDwvwmTAgdkG5btLlfTpPnoKDy2hPS4Pd0P
+mF7OPVfA0Hl/oEqP7bqyUxuwFrz7pZXQrKDS02nXaqVAP02nKsiEUZNo2kprAO2v
+9ceOhXP3M+ItlWeNcX5jKRaaLddQvj1ntOKqDMfRk4yWm9ro8/E56Fkrq7GpKrXL
+FCJJTdrWk6EcSfI6grVjPbZGBJiA+21G4IPQWskPkr9gLuE0E9I1UAdliYKXOrPK
+F1lZ1ZBpG1ZBe9H8Gr2sK42pzJoFJsOvGRjCxlHpf/gBoOADH/hcxvQqBGizEr0F
+kKraZWJnlL8qhDzfJ7YLMqzFsOu7uYQRqfOcv+66FqT/by9rD7dR/M03YJReupoL
+lynJfffGCG6aeM8hLZ8iizjIc/RzCY0QS4lLPkRVSRNt3Z8RNX/nFuYhYgOx38pu
+6dflN059kTC5iyjsI5Ka/Xzq69kR21qCcHOoq6IQqZ7q5RM4Cj0SCXw8/4jeT2xY
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem
new file mode 100644
index 0000000..7d09608
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_rc2_64_cbc.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: RC2-64-CBC,DA39EAD05DD48A5B
+
+mil5OpL9dVqnEoKF7dNjIRYLgDjCBmTDZ//Bmkd4aqkPszHaCoQqgyGYOuqWXdT2
+FAluu/fHMLDTizyr2Jh00ekcR3nmnGM3B0oDiEtq84YMHPWYopWkpId1ZaoqluUe
+6NP6Zew4DZ8mEQvOxIxBEZqk0ye6srtLszByw/dTy4i9S7l4oR8hx1i6Jj9lLXS1
+y24lC68igFNeIecggG8uwZBVmnHCldZGn6DBBqcC0b415+59vwGuvc+POy0Hog/4
+ADPuZcXEO2whVGyOjCF7CjhEFfo0CO2niwS9PiUIYNsUluwfS+y1qhw4VJ61sQ/q
+7cNHrD4NfZHGwpIRXk4c27YHS+JsxH8Kh61e/dQPoeTf5NBQs3PthFcx+hzlTBAq
+VK/4TtRRlnqTVFKRydpKo3cNGp8qm9Kvz6fr/yLb7CJvdoGDyHVO7JvT8nYL5gC0
+dvN2RySKXMrgmPS7uMAWjpnDCdNoOX4pRTRPEdBw8WsdXqnBqXM8tvrkolF9n3//
+lldN3sSGLiYM1cwD4dXlYJEJNaarelHk6vpJIU4A6gYyN9MQnv061jd7sibrTAjZ
+Rx06R0FrYFbfkp4yAmUbrPO5gdwZPBGS9XzkZmZr+S4u1fH7tTFxIlWNgxwSzsZJ
+P9LXM8Iy408gDn1AJlbT7WbdWfcFzqIsmauRIXE66TloS+485ro9zX7O27MumF8S
+hjD+cRMieUEREuAAlpNxZj5kcT3SpxfSdaAZtJv8OKeRHz796LRxlLmx3ZDAjgN5
+0H37gSCXJDP2a4YnsiI7th5fNba84t1Qt4Q36v6EZT2kscv0TB04ov1+4UX9jCQI
+zn2zxzJk42kkxRSEBP3BnZf/qV5t6/+BKmg1QGCmS5AkIIlCDjTPpAom3n7YH9LV
+ykAQ6Wcdo/7dGtghgaHbPGl3cXR1u7BI97GCU4vzRbW58ULh7KSC1xptDJrP7tPE
+6OwwYk5YZ6lmg54cLbQcxeFwYQg1dc4pYAgBppUFUB/uWeQrbJP8/FN/GlW0HTOU
+kUIz5pbI7nstb2hHrRMTtG4c0oGO1ACD2LigQo5Cl7jR0sBC3I2MB/JcBBwAHPVP
+tePpIdSAZjAYI+x7LFxxXvT7eXe+BU4ZLGLcTISGJjtsbJG1oJ/e7dPP5bLL+zjJ
+MrwoE6awH5GKOOxB0iUGce8jg8566qY4e2vbmVL4a2qRiKyLowr7Lcz01VzzE/RX
+0Ec1I8noUmsystH/57UMBuhZNFjW3LtTaw6vuTrrmFtdmJcGwars9tBtH0LPip9X
+xQbwIiTJZCyDjql7Ecgu2ncw7zHZzbHrmoEF7VEdPT4z21utXgzJ3HubvB7Agvyz
+sB+EXeUqwZHnyN0GdGd6sqlHkW7TP1XxMrjewUHjXuY4SvsosJ/GqMY7uKJXK/Lt
+0kqYrV/YDIVsJ2JqyxwXYYIqmZfQ2xXTLuESuesT7omKFh4cgwbYHd33YWRCsZJB
+7Og8d3ciguWDutd1LOgx7da2ZA+3UVz8X601GRpFD8YoZTo8QOayXFvv7L1F3oeK
+b0w11lT0npxstmeMQUkbxAyCnKrwpQagiwBzKlr9ymJvh/ot6sJ5bAFDvZBBKkQU
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_unencrypted.pem b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_unencrypted.pem
new file mode 100644
index 0000000..f540dcc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/rsa/openssl_rsa_unencrypted.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAyGOvloI+jKnRHWKuhYB+cTIEwZhagKJ0f3rIY8WNgujB7Plp
+gpjUg4pNjYGViGjg7zhfbjhCtlNGXyRBti3GcaHiBIIP5nyCNn+Ay8tSWGo5v5Zc
+8BQcwHf0ZHLN6sD9m2uVSp/6UqjS5ZyhzF5FzvvUo3xw8fecdnStXQfHhkBnLpTj
+HE5t7iu1JVjTuE0pcBvah2dWqDNxiIOQtXyKW8Sag1YxaunxQGqRNykSFiEJindx
+OSAnAxK6q/wGqcZ3zvFBTcVVkji1u2QH4rOMP3PPxAIMkB8ONkdHTco1DmbE6BfD
+HArDqUYxqJUlPGlMqrKb3fCFiT3eXehwR7nlzQIDAQABAoIBAFd6vTKVVT0O/U04
+wTtiptA/p7fkDM5PHVBxh32Wxno5pj8PerIaiduKyuRVh7PvJRMJpw903BrAK95o
+847WWOVOaF7TcKGMBURJUS6maiJS7TboK1ZbUVnsg/I99ArhiVUKGDhlsl/Xd4np
+YPDYztzXLzLXpm7bS6CiuvP762x9dfVu8K+afP8cjH8pfXLq55ghZOUKidRQaYz1
+mNOTQyAQlCQdLRgKlYgqcRHlj0pb28XBJaln3W7Z7GFMWFPojkxx6LaCp8+Jyx2C
+tv54zIZQhMjF37tQyTnfK4Ocl3sCRb+jYV4FkrUnsQE9W2dey0Tms1XB31gfUJlx
+dRZu7zkCgYEA/nWcTwzot2OIAhXoJ2fnqTcpdmj05LHhGcayKjyix7BsVH2I0KpF
+9kXX066tr3+LxZTergl4UpWSl3yx/4kPBQM6np4VVRytn7+cQdEhOczZnBw6x7IZ
+fv81DSNruQDBRAlTtklW4KBY74JKLhaJSvF1F3x32+H+99i1MmCNJRMCgYEAyZpF
+h4c3pM9z+YlmgLdUh/G2abdoamugcQOFbzHbZowsRAxEzdEW9wj2McN6mt8Rn1tc
+tY/+PcYuIK+vcmk9k23GuzxRlJlkaDicHwlAebgVIulFcrStfTlSkXjpuOuusfD9
+2DuHMcUiPx3qElNB0dZJF/axpq7BjTIFENefhZ8CgYACn+vw1M1BtwEcJGW0olm9
+YRhIZGTCRyNvRKFp1h5HuQYlCPZ0UI1QMQA86rxX5xTmANcbLHXVRD2y2lJrtFo3
+TwU3xaGqsxUHZM6TzzhshDRqa9AfZzLkIHXHoOnnip5zuTTn2HHQ91ZzggCJ4Smh
+YEQ47cu+tOIQZGfaESzjiQKBgQCCfnZlDJRq/NFwA40y4fg4arANa+eNgw7+OC5F
+1HrUvQTmIx7iLmZ0Dvv1KDgTSTLJ+MRgzczexYoUJEQnhZGS/Wq2xYt06XlBsOr1
+d/KhFxOvXllSrzrhJJqaiS6YQQ36JijZr2aKQ7UwL7fUlsmy/safWVKStumX8Hmw
+9jFOtwKBgQDmtirdNQ8aKolokD/3bDHPcDsNcybEpiCu8BIltxZAs/LsN1IIxfcp
+mGP2AFt3mbblKbsRM8hDW/X9taeG9s2KGe5wlKOE5lV8YAo4hFoJYN2/0d8Y0K9X
+QAAYU3iPG1zL+a/7TFLJ0u/biqsBg9hnNbMnN/tOeSuKnH2Rx9F1rg==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/openssl/test.pem b/BouncyCastle.AxCrypt/test/data/openssl/test.pem
new file mode 100644
index 0000000..c52453c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/openssl/test.pem
@@ -0,0 +1,133 @@
+-----BEGIN DSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,079DD7CA8A9BAA19
+
+jIqIT0DIvUlwvkREv6gnCTVFdOsoVwUS9nxcVuQ8JOwg+TB42GnhgZ5x6MFczgNd
+Dw9L60zono+ethYfYB91CdIcVULzvg61/DCAFDjIFPgOIYTVNmteUq75Dmt6wDTV
+4A07iMwjwBk+0YHaeVwcr0AkdvXEcVySOGdGrwy10K8Eq/kSndzm1Sm6tUCJ45+v
+zSUelLlT9fgRTmAbeowT1/tlt/q52bGTcXJzIWBxDuOxK5ASCTjk28kri9WeRUb/
+iCnXn+cqR3BvkDCdlhk2A6A6Q8U9vo0m1MPtwwsolz76jnxbtBNr6Sc+zcny0brP
+jCPMP1qF+IIk01N3YsAZ9mbJmXYoFf9B0VwNUjPudWlSqhvmzzanatevgZ9TID8G
+Mnltd2XsqIgdvu0JhhEJRC6n7hBvn+l7iwYKtBoK+rJmEWWttkoP82UGgjzjzqKa
+rEtdaZPUCEiBLqHPyiIaDWm5Pe4sZZqrV8Ix8vDLKK59ZUkgmYXyCul2yL/cfO5T
+gjMqh9EeQCrNsu3hJGuEEE3MlskQkCpEspm9qDGbKPkMno7CE37plVopx0o0oovE
+S8MZn0v2lIzV8yZ6krtcEA==
+-----END DSA PRIVATE KEY-----
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,9AC3CD3B4ED42426
+
+AzAvQsDkxXGdPMlFjqO0lYXSlypkfGJWIMqij00cZI1B6K7pMnBHo3wIYStlKDg2
+SMMTYwJfsbFA8+cyCyzsqVBQC63ZgEnStMrDOt/U0SGXNb/C4mFsf1ksnAI6y/3J
+3lhuPAZbMKCmANslivbj9gp4hSe828btXDhvIPKKJgKHhwHveeW9JDulySAN5KYn
+s4aeasvSWVBOYtefFaS+NzrXjDnPtOMX6TQDxd9CE8es1RQbU9Ze2CEa9S7l4coj
+0abWVTjxu55foDCDzbukkQm+eU0aaI4OoydoOCz6bcOfADgRx3/fJ9Z9IuS5w73O
+BiF8Z4S8e7GYpgsPVEqj06PuNH7t6bwzKC9U2FTiNcejZIYPqz21d9iA4hsEfFDd
+0DlXqYUKMazE+TjU8goss5cEqyLNDQmWLYLKUE2p8QmSZC/UqEsZ9pu1VZz3xpFT
+k2sju26HCV14XPG5oi9LpxDQaVRmXBMFxz5b+RmUwPfZuWntTzHQXuNyH2J3B9FN
+el8gaskt4hxHI28hB/eF0h7pOIBUDiR9n/BB+feOrNW8y7/ThSkdI3OK0+dyOzLg
+go9s7SGz5WLyy8FWevw0k2Is4IpCueTwclDrOAPixW+paHhDGIasnvvCsz5jGqQz
+4F4JPmA2ZYg/Z8dYob/ZeF/3KuJqFZAm9gseGS19sT7UzVvvmSf5IXOFfpb7VdRn
+ScFMRVr8PY9ANGh7zYg/8w+G3JJj4C7djA3RB/yOhK4KwbTz/2cnEDI26VREjKs0
+7/WPQXxr/oQ+XEBTnYuJZfa7o7orGL+6wA0Vk/GJqjA=
+-----END RSA PRIVATE KEY-----
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0
+ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsO4slP/KdZQsZyYn3asTWDtX
+E1YN+QQbbHELK7boPQa91YHv5DV/SgucThoXXCtSA45d3dQhrEbZ2+HRBarZIylk
+Nc+VmcV1qFX5KsD9wCYPMtdAYYog6jz259yCOKPDXPm787Q5t9h2zV3Ml1i0eWhC
+cdRYiWHQ5g20W4Bq3GsCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw
+EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAZGPA0Jyw49cHPJjG
+bloqKAPNlBO200AiRFsHnkOQ1DopJff3mW+FdszAc9g6rTB4/YAiM4r0E314e0vm
+XSlW2q8sp+c2XJO7PUIdJIuAUnvSmMb/uwXFP2SzLdjLcmymMsnFfjvwkht0K2it
+O5HuUDuhLnxEimGlUEBrfkdrsH0=
+-----END CERTIFICATE REQUEST-----
+-----BEGIN NEW CERTIFICATE REQUEST-----
+MIIBkDCB+gIBADAlMSMwIQYDVQQDExpSZXF1ZXN0ZWQgVGVzdCBDZXJ0aWZpY2F0
+ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsO4slP/KdZQsZyYn3asTWDtX
+E1YN+QQbbHELK7boPQa91YHv5DV/SgucThoXXCtSA45d3dQhrEbZ2+HRBarZIylk
+Nc+VmcV1qFX5KsD9wCYPMtdAYYog6jz259yCOKPDXPm787Q5t9h2zV3Ml1i0eWhC
+cdRYiWHQ5g20W4Bq3GsCAwEAAaAsMCoGCSqGSIb3DQEJDjEdMBswGQYDVR0RBBIw
+EIEOdGVzdEB0ZXN0LnRlc3QwDQYJKoZIhvcNAQELBQADgYEAZGPA0Jyw49cHPJjG
+bloqKAPNlBO200AiRFsHnkOQ1DopJff3mW+FdszAc9g6rTB4/YAiM4r0E314e0vm
+XSlW2q8sp+c2XJO7PUIdJIuAUnvSmMb/uwXFP2SzLdjLcmymMsnFfjvwkht0K2it
+O5HuUDuhLnxEimGlUEBrfkdrsH0=
+-----END NEW CERTIFICATE REQUEST-----
+-----BEGIN CERTIFICATE-----
+MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx
+ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY
+BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ
+d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2
+MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW
+BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM
+dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l
+Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv
+bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re
+Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO
+Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE
+7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy
+QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0
+ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw
+DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL
+iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4
+yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF
+5/8=
+-----END CERTIFICATE-----
+-----BEGIN X509 CERTIFICATE-----
+MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx
+ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY
+BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ
+d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2
+MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW
+BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM
+dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l
+Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv
+bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re
+Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO
+Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE
+7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy
+QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0
+ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw
+DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL
+iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4
+yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF
+5/8=
+-----END X509 CERTIFICATE-----
+-----BEGIN ATTRIBUTE CERTIFICATE-----
+MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl
+IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy
+aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV
+BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv
+dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw
+MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV
+MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI
+NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7
+eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G
+odUBlSsJwPPQjZSU
+-----END ATTRIBUTE CERTIFICATE-----
+-----BEGIN X509 CRL-----
+MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT
+F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw
+MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw
+MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw
+MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw
+MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw
+MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw
+MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw
+NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw
+NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF
+AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ
+wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt
+JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v
+-----END X509 CRL-----
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-EDE3-CBC,ADBCD679C6C6363E
+
+MmYmhTgKNKwwnA4AIskePMy+gp3Ch7Pn/UqRGjQypIyibbp/UFY+aSbQmvQNG2R9
+6Zj6cbBJGt/C2EYXk9UonUTA9Q+FVytkpR8ON6NHlSc2twrvDpqi7lpeSB9ywlH7
+WLffwNZMNsNHfcNK2slHf4RCmpqcGsXffHe45dQG0CI=
+-----END EC PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/3.1.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/3.1.bin
new file mode 100644
index 0000000..c4e92dd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/3.1.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/3.2.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/3.2.bin
new file mode 100644
index 0000000..9c82edf
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/3.2.bin
@@ -0,0 +1 @@
+0+	*�H��
�

This is some sample content.
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.1.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.1.bin
new file mode 100644
index 0000000..d99f79d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.1.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.10.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.10.bin
new file mode 100644
index 0000000..d3815bd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.10.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.11.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.11.bin
new file mode 100644
index 0000000..e203651
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.11.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.2.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.2.bin
new file mode 100644
index 0000000..c1b6024
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.2.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.3.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.3.bin
new file mode 100644
index 0000000..1bc6b15
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.3.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.4.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.4.bin
new file mode 100644
index 0000000..3245c11
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.4.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.5.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.5.bin
new file mode 100644
index 0000000..6608d9b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.5.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.6.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.6.bin
new file mode 100644
index 0000000..1a7eb95
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.6.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.7.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/4.7.bin
new file mode 100644
index 0000000..ea6b1df
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/4.7.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.8.eml b/BouncyCastle.AxCrypt/test/data/rfc4134/4.8.eml
new file mode 100644
index 0000000..206ebf0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/4.8.eml
@@ -0,0 +1,39 @@
+MIME-Version: 1.0
+To: User2 at examples.com
+From: aliceDss at examples.com
+Subject: Example 4.8
+Message-Id: <020906002550300.249 at examples.com>
+Date: Fri, 06 Sep 2002 00:25:21 -0300 
+Content-Type: multipart/signed;
+    micalg=SHA1;
+    boundary="----=_NextBoundry____Fri,_06_Sep_2002_00:25:21";
+    protocol="application/pkcs7-signature"
+
+This is a multi-part message in MIME format.
+
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21
+
+This is some sample content.
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21
+Content-Type: application/pkcs7-signature; name=smime.p7s
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7s
+
+MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGgggLgMIIC
+3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDTk5MDgxNzAx
+MTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2MIIBKwYHKoZIzjgE
+ATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lOFzSH4M1vNESNH+n6+koYkv
+4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iLVPE/sAcIR01diMPDtbPjVQh11Tl2
+EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5
++z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3q
+nMkhijt2FOnOLl2jB80jhbgvMAF8bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGB
+SmA5ujY5A4GEAAKBgFzjuVp1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/
++onyohs+JH09B41bY8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTS
+ljf2YUeyxDKE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E
+BAMCBsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfft
+Q3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM44BAMD
+MAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0NevTFjMGECAQEw
+GDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjOOAQDBC4wLAIUM/mGf6gk
+gp9Z0XtRdGimJeB/BxUCFGFFJqwYRt1WYcIOQoGiaowqGzVI
+
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21--
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/4.9.eml b/BouncyCastle.AxCrypt/test/data/rfc4134/4.9.eml
new file mode 100644
index 0000000..5431575
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/4.9.eml
@@ -0,0 +1,28 @@
+MIME-Version: 1.0
+To: User2 at examples.com
+From: aliceDss at examples.com
+Subject: Example 4.9
+Message-Id: <021031164540300.304 at examples.com>
+Date: Thu, 31 Oct 2002 16:45:14 -0300 
+Content-Type: application/pkcs7-mime; smime-type=signed-data;
+    name=smime.p7m
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7m
+
+MIIDmQYJKoZIhvcNAQcCoIIDijCCA4YCAQExCTAHBgUrDgMCGjAtBgkqhkiG9w0BBwGgIAQeDQpU
+aGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIIC4DCCAtwwggKboAMCAQICAgDIMAkGByqGSM44
+BAMwEjEQMA4GA1UEAxMHQ2FybERTUzAeFw05OTA4MTcwMTEwNDlaFw0zOTEyMzEyMzU5NTlaMBMx
+ETAPBgNVBAMTCEFsaWNlRFNTMIIBtjCCASsGByqGSM44BAEwggEeAoGBAIGNze2D6gqeOT7CSCij
+5EeT3Q7XqA7sU8WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg23j+bv7dM3F9piuR10DcMkQiV
+m96nXvn89J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dhDEeL3/nbCElzfy5FEbteQJllzzflvb
+AhUA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUiTKqOfs+bdlLWWpMdiM5BAI1XPLLGjDDHlBd
+3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oIXks+kPht6pzJIYo7dhTpzi5dowfNI4W4LzABfG1J
+iRGJNkS9+MiVSlNWteL5c+waYTYfEX/Cve3RUP+YdMLRgUpgObo2OQOBhAACgYBc47ladRSWC6l6
+3eM/qeysXty9txMRNKYWiSgRI9k0hmd1dRMSPUNbb+VRv/qJ8qIbPiR9PQeNW2PIu0WloErjhdbO
+BoA/6CN+GvIkq1MauCcNHu8Iv2YUgFxirGX6FYvxuzTU0pY39mFHssQyhPB+QUD9RqdjTjPypeL0
+8oPluKOBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFHBEPoIu
+b4feStN14z0gvEMrk/EfMB0GA1UdDgQWBBS+bKGz48H37UNwpM4TAeL945f+zTAfBgNVHREEGDAW
+gRRBbGljZURTU0BleGFtcGxlLmNvbTAJBgcqhkjOOAQDAzAAMC0CFFUMpBkfQiuJcSIzjYNqtT1n
+a79FAhUAn2FTUlQLXLLd2ud2HeIQUltDXr0xYzBhAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERTUwIC
+AMgwBwYFKw4DAhowCQYHKoZIzjgEAwQuMCwCFD1cSW6LIUFzeXle3YI5SKSBer/sAhQmCq7s/CTF
+HOEjgASeUjbMpx5g6A==
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/5.1.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/5.1.bin
new file mode 100644
index 0000000..9750174
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/5.1.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/5.2.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/5.2.bin
new file mode 100644
index 0000000..de17b01
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/5.2.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/5.3.eml b/BouncyCastle.AxCrypt/test/data/rfc4134/5.3.eml
new file mode 100644
index 0000000..55013ad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/5.3.eml
@@ -0,0 +1,19 @@
+MIME-Version: 1.0
+Message-Id: <00103112005203.00349 at amyemily.ig.com>
+Date: Tue, 31 Oct 2000 12:00:52 -0600 (Central Standard Time)
+From: User1
+To: User2
+Subject: Example 5.3
+Content-Type: application/pkcs7-mime;
+	name=smime.p7m;
+	smime-type=enveloped-data
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7m
+
+MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYXJsUlNB
+AhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8k
+bKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJ
+tuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJKoZI
+hvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4OxUk660cu1lXeCSFOSOpO
+J7FuVyU=
+
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/6.0.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/6.0.bin
new file mode 100644
index 0000000..dfbfaaa
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/6.0.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/7.1.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/7.1.bin
new file mode 100644
index 0000000..9184c58
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/7.1.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/7.2.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/7.2.bin
new file mode 100644
index 0000000..b95b341
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/7.2.bin differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer
new file mode 100644
index 0000000..7e96210
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/AliceDSSSignByCarlNoInherit.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivDSSSign.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivDSSSign.pri
new file mode 100644
index 0000000..e123ee7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivDSSSign.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivRSASign.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivRSASign.pri
new file mode 100644
index 0000000..c885108
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/AlicePrivRSASign.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/AliceRSASignByCarl.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/AliceRSASignByCarl.cer
new file mode 100644
index 0000000..848ba87
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/AliceRSASignByCarl.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/BobPrivRSAEncrypt.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/BobPrivRSAEncrypt.pri
new file mode 100644
index 0000000..b0805b8
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/BobPrivRSAEncrypt.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/BobRSASignByCarl.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/BobRSASignByCarl.cer
new file mode 100644
index 0000000..1068ab9
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/BobRSASignByCarl.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLEmpty.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLEmpty.crl
new file mode 100644
index 0000000..42af3a0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLEmpty.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForAll.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForAll.crl
new file mode 100644
index 0000000..52b818d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForAll.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForCarl.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForCarl.crl
new file mode 100644
index 0000000..2a4e794
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSCRLForCarl.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSSelf.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSSelf.cer
new file mode 100644
index 0000000..b47c682
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlDSSSelf.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivDSSSign.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivDSSSign.pri
new file mode 100644
index 0000000..4b1fdc0
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivDSSSign.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivRSASign.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivRSASign.pri
new file mode 100644
index 0000000..7fee220
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlPrivRSASign.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLEmpty.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLEmpty.crl
new file mode 100644
index 0000000..c3eb304
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLEmpty.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForAll.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForAll.crl
new file mode 100644
index 0000000..3708ccb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForAll.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForCarl.crl b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForCarl.crl
new file mode 100644
index 0000000..2ce8e4d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSACRLForCarl.crl differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSASelf.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSASelf.cer
new file mode 100644
index 0000000..ce6737d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/CarlRSASelf.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/DianeDSSSignByCarlInherit.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/DianeDSSSignByCarlInherit.cer
new file mode 100644
index 0000000..e0fa3ac
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/DianeDSSSignByCarlInherit.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivDSSSign.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivDSSSign.pri
new file mode 100644
index 0000000..68ddc95
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivDSSSign.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivRSASignEncrypt.pri b/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivRSASignEncrypt.pri
new file mode 100644
index 0000000..b7bcb29
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/DianePrivRSASignEncrypt.pri differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/DianeRSASignByCarl.cer b/BouncyCastle.AxCrypt/test/data/rfc4134/DianeRSASignByCarl.cer
new file mode 100644
index 0000000..062260a
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rfc4134/DianeRSASignByCarl.cer differ
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/ExContent.bin b/BouncyCastle.AxCrypt/test/data/rfc4134/ExContent.bin
new file mode 100644
index 0000000..22ddba6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/ExContent.bin
@@ -0,0 +1 @@
+This is some sample content.
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/data/rfc4134/rfc4134.txt b/BouncyCastle.AxCrypt/test/data/rfc4134/rfc4134.txt
new file mode 100644
index 0000000..a53cec5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rfc4134/rfc4134.txt
@@ -0,0 +1,7619 @@
+
+
+
+
+
+
+Network Working Group                                    P. Hoffman, Ed.
+Request for Comments: 4134                      Internet Mail Consortium
+Category: Informational                                        July 2005
+
+
+                      Examples of S/MIME Messages
+
+Status of This Memo
+
+   This memo provides information for the Internet community.  It does
+   not specify an Internet standard of any kind.  Distribution of this
+   memo is unlimited.
+
+Copyright Notice
+
+   Copyright (C) The Internet Society (2005).
+
+Abstract
+
+   This document gives examples of message bodies formatted using
+   S/MIME.  Specifically, it has examples of Cryptographic Message
+   Syntax (CMS) objects and S/MIME messages (including the MIME
+   formatting).  It includes examples of many common CMS formats.  The
+   purpose of this document is to help increase interoperability for
+   S/MIME and other protocols that rely on CMS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                      [Page 1]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+Table of Contents
+
+   1.  Introduction ................................................   3
+   2.  Constants Used in the Examples ..............................   3
+       2.1.  Content of Documents ..................................   4
+       2.2.  Private Keys ..........................................   4
+       2.3.  Certificates ..........................................  13
+       2.4.  CRLs ..................................................  33
+   3.  Trivial Examples ............................................  39
+       3.1.  ContentInfo with Data Type, BER .......................  39
+       3.2.  ContentInfo with Data Type, DER .......................  39
+   4.  Signed-data .................................................  39
+       4.1.  Basic Signed Content, DSS .............................  39
+       4.2.  Basic Signed Content, RSA .............................  44
+       4.3.  Basic Signed Content, Detached Content ................  49
+       4.4.  Fancier Signed Content ................................  53
+       4.5.  All RSA Signed Message ................................  68
+       4.6.  Multiple Signers ......................................  75
+       4.7.  Signing Using SKI .....................................  83
+       4.8.  S/MIME multipart/signed Message .......................  87
+       4.9.  S/MIME application/pkcs7-mime Signed Message ..........  88
+       4.10. SignedData with Attributes ............................  89
+       4.11. SignedData with Certificates Only ..................... 101
+   5.  Enveloped-data .............................................. 109
+       5.1.  Basic Encrypted Content, TripleDES and RSA ............ 109
+       5.2.  Basic Encrypted Content, RC2/128 and RSA .............. 110
+       5.3.  S/MIME application/pkcs7-mime Encrypted Message ....... 112
+   6.  Digested-data ............................................... 112
+   7.  Encrypted-data .............................................. 113
+       7.1.  Simple EncryptedData .................................. 113
+       7.2.  EncryptedData with Unprotected Attributes ............. 114
+   8.  Security Considerations ..................................... 115
+   9.  References .................................................. 115
+       9.1.  Normative References .................................. 115
+       9.2.  Informative References ................................ 115
+   A.  Binaries of the Examples .................................... 116
+       A.1.  How the Binaries and Extractor Works .................. 116
+       A.2.  Example Extraction Program ............................ 116
+   B.  Examples in Order of Appearance ............................. 118
+   C.  Acknowledgements ............................................ 135
+
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                      [Page 2]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+1.  Introduction
+
+   The examples in this document show the structure and format of CMS
+   message bodies, as described in [CMS].  They are useful to
+   implementors who use protocols that rely on CMS, such as the S/MIME
+   message format protocol.  There are also examples of simple S/MIME
+   messages [SMIME-MSG] (including the MIME headers).
+
+   Every example in this document has been checked by two different
+   implementors.  This strongly indicates (but does not assure) that the
+   examples are correct.  All CMS implementors must read the CMS
+   document carefully before implementing from it.  No one should use
+   the examples in this document as stand-alone explanations of how to
+   create CMS message bodies.
+
+   This document explicitly does not attempt to cover many PKIX [PKIX]
+   examples.  Documents with examples of that format may be forthcoming.
+   Also, note that [DVCS], which covers PKIX Data Validation and
+   Certification Server Protocols, has examples of formats for its
+   protocol.
+
+   The examples shown here were created and validated by many different
+   people over a long period of time.  Because of this, some of the
+   dates used in the examples are many years in the past.  This, plus
+   the fact that some of the certificates in the examples have very long
+   lifespans, may cause problems in some test situations.
+
+2.  Constants Used in the Examples
+
+   This section defines the data used in the rest of the document.  The
+   names of the constants indicate their use.  For example,
+   AlicePrivDSSSign is the private part of Alice's DSS signing key.
+
+   - Alice is the creator of the message bodies in this document.
+
+   - Bob is the recipient of the messages.
+
+   - Carl is a CA.
+
+   - Diane sometimes gets involved with these folks.
+
+   - Erica also sometimes gets involved.
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                      [Page 3]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+2.1.  Content of Documents
+
+   ExContent is the following sentence:
+
+      This is some sample content.
+
+   That is, it is the string of characters starting with "T" up to and
+   including the ".".
+
+   The hex for ExContent is
+
+   5468 6973 2069 7320 736f 6d65 2073 616d 706c 6520 636f 6e74 656e 742e
+
+   The MD5 hash of ExContent is
+
+   9898 cac8 fab7 691f f89d c207 24e7 4a04
+
+   The SHA-1 hash of ExContent is
+
+   406a ec08 5279 ba6e 1602 2d9e 0629 c022 9687 dd48
+
+2.2.  Private Keys
+
+   The following private keys are needed to create the samples.  To find
+   the public keys, see the certificates in the next section.
+
+   AlicePrivDSSSign =
+      0 30  331: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30  299:   SEQUENCE {
+     11 06    7:     OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :       (ANSI X9.57 algorithm)
+     20 30  286:     SEQUENCE {
+     24 02  129:       INTEGER
+               :         00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :         48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :         53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :         0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :         2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :         DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :         9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :         8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :         C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :         78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :         B5 E4 09 96 5C F3 7E 5B DB
+    156 02   21:       INTEGER
+               :         00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :         B8 37 21 2B 62 8B F7 93 CD
+
+
+
+Hoffman, Ed.                 Informational                      [Page 4]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    179 02  128:       INTEGER
+               :         26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :         4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :         CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :         AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :         7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :         3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :         E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :         01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :         95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :         1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :         D1 81 4A 60 39 BA 36 39
+               :       }
+               :     }
+    310 04   23:   OCTET STRING, encapsulates {
+    312 02   21:       INTEGER
+               :         00 BB 44 46 D1 A5 C9 46 07 2E D0 FE
+               :         7A D6 92 07 F0 9A 85 89 3F
+               :       }
+               :   }
+
+   AlicePrivRSASign =
+      0 30  630: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30   13:   SEQUENCE {
+      9 06    9:     OBJECT IDENTIFIER
+               :       rsaEncryption (1 2 840 113549 1 1 1)
+               :       (PKCS #1)
+     20 05    0:     NULL
+               :     }
+     22 04  608:   OCTET STRING, encapsulates {
+     26 30  604:       SEQUENCE {
+     30 02    1:         INTEGER 0
+     33 02  129:         INTEGER
+               :           00 E0 89 73 39 8D D8 F5 F5 E8 87 76
+               :           39 7F 4E B0 05 BB 53 83 DE 0F B7 AB
+               :           DC 7D C7 75 29 0D 05 2E 6D 12 DF A6
+               :           86 26 D4 D2 6F AA 58 29 FC 97 EC FA
+               :           82 51 0F 30 80 BE B1 50 9E 46 44 F1
+               :           2C BB D8 32 CF C6 68 6F 07 D9 B0 60
+               :           AC BE EE 34 09 6A 13 F5 F7 05 05 93
+               :           DF 5E BA 35 56 D9 61 FF 19 7F C9 81
+               :           E6 F8 6C EA 87 40 70 EF AC 6D 2C 74
+               :           9F 2D FA 55 3A B9 99 77 02 A6 48 52
+               :           8C 4E F3 57 38 57 74 57 5F
+    165 02    3:         INTEGER 65537
+    170 02  128:         INTEGER
+               :           00 A4 03 C3 27 47 76 34 34 6C A6 86
+
+
+
+Hoffman, Ed.                 Informational                      [Page 5]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           B5 79 49 01 4B 2E 8A D2 C8 62 B2 C7
+               :           D7 48 09 6A 8B 91 F7 36 F2 75 D6 E8
+               :           CD 15 90 60 27 31 47 35 64 4D 95 CD
+               :           67 63 CE B4 9F 56 AC 2F 37 6E 1C EE
+               :           0E BF 28 2D F4 39 90 6F 34 D8 6E 08
+               :           5B D5 65 6A D8 41 F3 13 D7 2D 39 5E
+               :           FE 33 CB FF 29 E4 03 0B 3D 05 A2 8F
+               :           B7 F1 8E A2 76 37 B0 79 57 D3 2F 2B
+               :           DE 87 06 22 7D 04 66 5E C9 1B AF 8B
+               :           1A C3 EC 91 44 AB 7F 21
+    301 02   65:         INTEGER
+               :           00 F6 D6 E0 22 21 4C 5F 0A 70 FF 27
+               :           FC E5 B3 50 6A 9D E5 0F B5 85 96 C6
+               :           40 FA A8 0A B4 9B 9B 0C 55 C2 01 1D
+               :           F9 37 82 8A 14 C8 F2 93 0E 92 CD A5
+               :           66 21 B9 3C D2 06 BF B4 55 31 C9 DC
+               :           AD CA 98 2D D1
+    368 02   65:         INTEGER
+               :           00 E8 DE B0 11 25 09 D2 02 51 01 DE
+               :           8A E8 98 50 F5 77 77 61 A4 45 93 6B
+               :           08 55 96 73 5D F4 C8 5B 12 93 22 73
+               :           8B 7F D3 70 7F F5 A4 AA BB 74 FD 3C
+               :           22 6A DA 38 91 2A 86 5B 6C 14 E8 AE
+               :           4C 9E FA 8E 2F
+    435 02   65:         INTEGER
+               :           00 97 4C F0 87 9B 17 7F EE 1B 83 1B
+               :           14 B6 0B 6A 90 5F 86 27 51 E1 B7 A0
+               :           7F F5 E4 88 E3 59 B9 F9 1E 9B D3 29
+               :           77 38 22 48 D7 22 B1 25 98 BA 3D 59
+               :           53 B7 FA 1E 20 B2 C8 51 16 23 75 93
+               :           51 E7 AB CD F1
+    502 02   64:         INTEGER
+               :           2C F0 24 5B FA A0 CD 85 22 EA D0 6E
+               :           4F FA 6C CD 21 D3 C8 E4 F1 84 44 48
+               :           64 73 D7 29 8F 7E 46 8C EC 15 DE E4
+               :           51 B3 94 E7 2C 99 2D 55 65 7B 24 EA
+               :           A3 62 1F 3E 6C 4D 67 41 11 3B E1 BE
+               :           E9 83 02 83
+    568 02   64:         INTEGER
+               :           58 88 D9 A1 50 38 84 6A AB 03 BC BB
+               :           DF 4B F4 9C 6F B8 B4 2A 25 FB F6 E4
+               :           05 2F 6E E2 88 89 21 6F 4B 25 9E D0
+               :           AB 50 93 CA BF 40 71 EC 21 25 C5 7F
+               :           FB 02 E9 21 96 B8 33 CD E2 C6 95 EE
+               :           6F 8D 5F 28
+               :         }
+               :       }
+               :   }
+
+
+
+Hoffman, Ed.                 Informational                      [Page 6]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   BobPrivRSAEncrypt =
+      0 30  645: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30   13:   SEQUENCE {
+      9 06    9:     OBJECT IDENTIFIER
+               :       rsaEncryption (1 2 840 113549 1 1 1)
+               :       (PKCS #1)
+     20 05    0:     NULL
+               :     }
+     22 04  608:   OCTET STRING, encapsulates {
+     26 30  604:       SEQUENCE {
+     30 02    1:         INTEGER 0
+     33 02  129:         INTEGER
+               :           00 A9 E1 67 98 3F 39 D5 5F F2 A0 93
+               :           41 5E A6 79 89 85 C8 35 5D 9A 91 5B
+               :           FB 1D 01 DA 19 70 26 17 0F BD A5 22
+               :           D0 35 85 6D 7A 98 66 14 41 5C CF B7
+               :           B7 08 3B 09 C9 91 B8 19 69 37 6D F9
+               :           65 1E 7B D9 A9 33 24 A3 7F 3B BB AF
+               :           46 01 86 36 34 32 CB 07 03 59 52 FC
+               :           85 8B 31 04 B8 CC 18 08 14 48 E6 4F
+               :           1C FB 5D 60 C4 E0 5C 1F 53 D3 7F 53
+               :           D8 69 01 F1 05 F8 7A 70 D1 BE 83 C6
+               :           5F 38 CF 1C 2C AA 6A A7 EB
+    165 02    3:         INTEGER 65537
+    170 02  128:         INTEGER
+               :           67 CD 48 4C 9A 0D 8F 98 C2 1B 65 FF
+               :           22 83 9C 6D F0 A6 06 1D BC ED A7 03
+               :           88 94 F2 1C 6B 0F 8B 35 DE 0E 82 78
+               :           30 CB E7 BA 6A 56 AD 77 C6 EB 51 79
+               :           70 79 0A A0 F4 FE 45 E0 A9 B2 F4 19
+               :           DA 87 98 D6 30 84 74 E4 FC 59 6C C1
+               :           C6 77 DC A9 91 D0 7C 30 A0 A2 C5 08
+               :           5E 21 71 43 FC 0D 07 3D F0 FA 6D 14
+               :           9E 4E 63 F0 17 58 79 1C 4B 98 1C 3D
+               :           3D B0 1B DF FA 25 3B A3 C0 2C 98 05
+               :           F6 10 09 D8 87 DB 03 19
+    301 02   65:         INTEGER
+               :           00 D0 C3 22 C6 DE A2 99 18 76 8F 8D
+               :           BC A6 75 D6 66 3F D4 8D 45 52 8C 76
+               :           F5 72 C4 EB F0 46 9A F1 3E 5C AA 55
+               :           0B 9B DA DD 6B 6D F8 FC 3B 3C 08 43
+               :           93 B5 5B FE CE EA FD 68 84 23 62 AF
+               :           F3 31 C2 B9 E5
+    368 02   65:         INTEGER
+               :           00 D0 51 FC 1E 22 B7 5B ED B5 8E 01
+               :           C8 D7 AB F2 58 D4 F7 82 94 F3 53 A8
+               :           19 45 CB 66 CA 28 19 5F E2 10 2B F3
+
+
+
+Hoffman, Ed.                 Informational                      [Page 7]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           8F EC 6A 30 74 F8 4D 11 F4 A7 C4 20
+               :           B5 47 21 DC 49 01 F9 0A 20 29 F0 24
+               :           08 84 60 7D 8F
+    435 02   64:         INTEGER
+               :           34 BA 64 C9 48 28 57 74 D7 55 50 DE
+               :           6A 48 EF 1B 2A 5A 1C 48 7B 1E 21 59
+               :           C3 60 3B 9B 97 A9 C0 EF 18 66 A9 4E
+               :           62 52 38 84 CE E5 09 88 48 94 69 C5
+               :           20 14 99 5A 57 FE 23 6C E4 A7 23 7B
+               :           D0 80 B7 85
+    501 02   65:         INTEGER
+               :           00 9E 2F B3 37 9A FB 0B 06 5D 57 E1
+               :           09 06 A4 5D D9 90 96 06 05 5F 24 06
+               :           40 72 9C 3A 88 85 9C 87 0F 9D 62 12
+               :           88 16 68 A8 35 1A 1B 43 E8 38 C0 98
+               :           69 AF 03 0A 48 32 04 4E E9 0F 8F 77
+               :           7D 34 30 25 07
+    568 02   64:         INTEGER
+               :           57 18 67 D6 0A D2 B5 AB C2 BA 7A E7
+               :           54 DA 9C 05 4F 81 D4 EF 01 89 1E 32
+               :           3D 69 CB 31 C4 52 C8 54 55 25 00 3B
+               :           1C 2A 7C 26 50 D5 E9 A6 D7 77 CB CF
+               :           15 F5 EE 0B D5 8D EE B3 AF 4C A1 7C
+               :           63 46 41 F6
+               :         }
+               :       }
+    634 A0   13:   [0] {
+    636 30   11:     SEQUENCE {
+    638 06    3:       OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :         (X.509 id-ce (2 5 29))
+    643 31    4:       SET {
+    645 03    2:         BIT STRING 0 unused bits
+               :           '00001000'B (bit 3)
+               :           Error: Spurious zero bits in bitstring.
+               :         }
+               :       }
+               :     }
+               :   }
+
+   CarlPrivDSSSign =
+      0 30  330: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30  299:   SEQUENCE {
+     11 06    7:     OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :       (ANSI X9.57 algorithm)
+     20 30  286:     SEQUENCE {
+     24 02  129:       INTEGER
+               :         00 B6 49 18 3E 8A 44 C1 29 71 94 4C
+
+
+
+Hoffman, Ed.                 Informational                      [Page 8]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :         01 C4 12 C1 7A 79 CB 54 4D AB 1E 81
+               :         FB C6 4C B3 0E 94 09 06 EB 01 D4 B1
+               :         C8 71 4B C7 45 C0 50 25 5D 9C FC DA
+               :         E4 6D D3 E2 86 48 84 82 7D BA 15 95
+               :         4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A
+               :         0A 8A BA 16 7B B9 50 01 48 93 8B EB
+               :         25 15 51 97 55 DC 8F 53 0E 10 A9 50
+               :         FC 70 B7 CD 30 54 FD DA DE A8 AA 22
+               :         B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9
+               :         AD E1 08 D4 6D 29 2D D6 E9
+    156 02   21:       INTEGER
+               :         00 DD C1 2F DF 53 CE 0B 34 60 77 3E
+               :         02 A4 BF 8A 5D 98 B9 10 D5
+    179 02  128:       INTEGER
+               :         0C EE 57 9B 4B BD DA B6 07 6A 74 37
+               :         4F 55 7F 9D ED BC 61 0D EB 46 59 3C
+               :         56 0B 2B 5B 0C 91 CE A5 62 52 69 CA
+               :         E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C
+               :         AD CB AE 45 E3 06 AC 8C 22 9D 9C 44
+               :         87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE
+               :         AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A
+               :         73 AA 7F 46 51 1F A9 42 16 9C 48 EB
+               :         8A 79 61 B4 D5 2F 53 22 44 63 1F 86
+               :         B8 A3 58 06 25 F8 29 C0 EF BA E0 75
+               :         F0 42 C4 63 65 52 9B 0A
+               :       }
+               :     }
+    310 04   22:   OCTET STRING, encapsulates {
+    312 02   20:       INTEGER
+               :         19 B3 38 A5 21 62 31 50 E5 7F B9 3E
+               :         08 46 78 D1 3E B5 E5 72
+               :       }
+               :   }
+
+   CarlPrivRSASign =
+      0 30  630: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30   13:   SEQUENCE {
+      9 06    9:     OBJECT IDENTIFIER
+               :       rsaEncryption (1 2 840 113549 1 1 1)
+               :       (PKCS #1)
+     20 05    0:     NULL
+               :     }
+     22 04  608:   OCTET STRING, encapsulates {
+     26 30  604:       SEQUENCE {
+     30 02    1:         INTEGER 0
+     33 02  129:         INTEGER
+               :           00 E4 4B FF 18 B8 24 57 F4 77 FF 6E
+
+
+
+Hoffman, Ed.                 Informational                      [Page 9]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           73 7B 93 71 5C BC 33 1A 92 92 72 23
+               :           D8 41 46 D0 CD 11 3A 04 B3 8E AF 82
+               :           9D BD 51 1E 17 7A F2 76 2C 2B 86 39
+               :           A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC
+               :           A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F
+               :           99 25 8F B8 4E AB B9 7D D5 96 65 DA
+               :           16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7
+               :           29 CB 82 DD AC 44 E9 AA 93 94 29 0E
+               :           F8 18 D6 C8 57 5E F2 76 C4 F2 11 60
+               :           38 B9 1B 3C 1D 97 C9 6A F1
+    165 02    3:         INTEGER 65537
+    170 02  129:         INTEGER
+               :           00 AE 73 E4 5B 5F 5B 66 5A C9 D7 C6
+               :           EF 38 5F 53 21 2A 2F 62 FE DE 29 9A
+               :           7A 86 67 36 E7 7D 62 78 75 3D 73 A0
+               :           BC 29 0E F3 8F BD C3 C9 C9 B6 F8 BA
+               :           D6 13 9B C3 97 7A CA 6A F0 B8 85 65
+               :           4E 0F BD A7 A8 F7 54 06 41 BD EB DC
+               :           20 77 90 DF 61 9B 9A 6F 74 DE EA 3B
+               :           D4 9C 87 60 ED 76 84 F1 6A 30 37 D5
+               :           E0 90 16 F8 80 47 C3 19 6B ED 75 77
+               :           BA 4A ED 39 B6 5D 02 47 3B 5F 1B C8
+               :           1C AB CB E8 F5 26 3F A4 81
+    302 02   65:         INTEGER
+               :           00 FF DF 09 A0 56 0B 42 52 9E C4 4D
+               :           93 B3 B0 49 BB DE E7 81 7D 28 99 D0
+               :           B1 48 BA 0B 39 E1 1C 7B 22 18 33 B6
+               :           40 F6 BF DC AE 1D D0 A1 AD 04 71 5A
+               :           61 0A 6E 3B CE 30 DA 36 9F 65 25 29
+               :           BB A7 0E 7F 0B
+    369 02   65:         INTEGER
+               :           00 E4 69 68 18 5F F9 57 D0 7C 66 89
+               :           0F BA 63 1D 72 CB 20 A4 81 76 64 89
+               :           CD 7D D1 C2 27 A9 2E AC 7A 56 9A 85
+               :           07 D9 30 03 A3 03 AB 7F 88 92 50 24
+               :           01 AA 1B 07 1F 20 4C B7 C9 7B 56 F7
+               :           B6 C2 7E AB 73
+    436 02   64:         INTEGER
+               :           57 36 6C 8F 8C 04 76 6C B6 D4 EE 24
+               :           44 00 F8 80 E2 AF 42 01 A9 0F 14 84
+               :           F8 E7 00 E0 8F 8C 27 A4 2D 5F A2 E5
+               :           6D B5 63 C0 AD 44 E9 76 91 A7 19 49
+               :           2E 46 F8 77 85 4B 3B 87 04 F0 AF D2
+               :           D8 54 26 95
+    502 02   64:         INTEGER
+               :           64 A1 0F AC 55 74 1B BD 0D 61 7B 17
+               :           03 CD B0 E6 A7 19 1D 80 AF F1 41 48
+               :           D8 1A B6 88 14 A0 2C 7A C5 76 D4 0F
+
+
+
+Hoffman, Ed.                 Informational                     [Page 10]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           0E 1F 7A 2A B2 6E 37 04 AB 39 45 73
+               :           BA 46 A8 0F 8D 82 5F 22 14 05 CF A2
+               :           A3 F3 7C 83
+    568 02   64:         INTEGER
+               :           26 1E 1D 1C A1 98 2B E4 DB 38 E8 57
+               :           6E 6B 73 19 88 61 3A FA 74 4A 36 8B
+               :           47 68 5D 50 EB 26 E3 EA 7D 9B 4E 65
+               :           A9 AF 7B AB 4B 2E 76 51 3D A8 D0 11
+               :           AB A3 D6 A8 C0 27 36 1D 54 0B AA A7
+               :           D1 6D 8D FA
+               :         }
+               :       }
+               :   }
+
+   DianePrivDSSSign =
+      0 30  331: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30  299:   SEQUENCE {
+     11 06    7:     OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :       (ANSI X9.57 algorithm)
+     20 30  286:     SEQUENCE {
+     24 02  129:       INTEGER
+               :         00 B6 49 18 3E 8A 44 C1 29 71 94 4C
+               :         01 C4 12 C1 7A 79 CB 54 4D AB 1E 81
+               :         FB C6 4C B3 0E 94 09 06 EB 01 D4 B1
+               :         C8 71 4B C7 45 C0 50 25 5D 9C FC DA
+               :         E4 6D D3 E2 86 48 84 82 7D BA 15 95
+               :         4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A
+               :         0A 8A BA 16 7B B9 50 01 48 93 8B EB
+               :         25 15 51 97 55 DC 8F 53 0E 10 A9 50
+               :         FC 70 B7 CD 30 54 FD DA DE A8 AA 22
+               :         B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9
+               :         AD E1 08 D4 6D 29 2D D6 E9
+    156 02   21:       INTEGER
+               :         00 DD C1 2F DF 53 CE 0B 34 60 77 3E
+               :         02 A4 BF 8A 5D 98 B9 10 D5
+    179 02  128:       INTEGER
+               :         0C EE 57 9B 4B BD DA B6 07 6A 74 37
+               :         4F 55 7F 9D ED BC 61 0D EB 46 59 3C
+               :         56 0B 2B 5B 0C 91 CE A5 62 52 69 CA
+               :         E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C
+               :         AD CB AE 45 E3 06 AC 8C 22 9D 9C 44
+               :         87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE
+               :         AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A
+               :         73 AA 7F 46 51 1F A9 42 16 9C 48 EB
+               :         8A 79 61 B4 D5 2F 53 22 44 63 1F 86
+               :         B8 A3 58 06 25 F8 29 C0 EF BA E0 75
+               :         F0 42 C4 63 65 52 9B 0A
+
+
+
+Hoffman, Ed.                 Informational                     [Page 11]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :       }
+               :     }
+    310 04   23:   OCTET STRING, encapsulates {
+    312 02   21:       INTEGER
+               :         00 96 95 F9 E0 C1 E0 41 2D 32 0F 8B
+               :         42 52 93 2A E6 1E 0E 21 29
+               :       }
+               :   }
+
+   DianePrivRSASignEncrypt =
+      0 30  631: SEQUENCE {
+      4 02    1:   INTEGER 0
+      7 30   13:   SEQUENCE {
+      9 06    9:     OBJECT IDENTIFIER
+               :       rsaEncryption (1 2 840 113549 1 1 1)
+               :       (PKCS #1)
+     20 05    0:     NULL
+               :     }
+     22 04  609:   OCTET STRING, encapsulates {
+     26 30  605:       SEQUENCE {
+     30 02    1:         INTEGER 0
+     33 02  129:         INTEGER
+               :           00 D6 FD B8 C0 70 C6 4C 25 EC EA CF
+               :           EA 7C BB A2 62 FA F0 E6 32 3A 53 FF
+               :           B1 92 5A 17 F4 20 E1 99 24 82 0A D0
+               :           F6 7C FB 44 CA 8B 27 06 F1 7E 26 03
+               :           A9 76 9D CF EC A0 2C 70 96 F2 83 42
+               :           F6 D4 B7 28 0A BB F8 BF 4A 4C 19 3F
+               :           07 DB A0 C1 60 1E B7 7E 67 F7 DE B1
+               :           C3 60 49 AC 45 D7 F8 C6 EF 08 37 21
+               :           93 47 EE F0 73 35 72 B0 02 C4 F3 11
+               :           C3 5E 47 E5 0A B7 83 F1 DB 74 69 64
+               :           8B 44 1D 95 5D CD 28 C0 85
+    165 02    3:         INTEGER 65537
+    170 02  128:         INTEGER
+               :           3D BD CD C2 0E 61 14 5B 4B E7 BF 60
+               :           23 04 2B C5 6B 35 A5 96 45 23 FC 69
+               :           7D 93 3C 0F D3 25 96 BA 62 52 42 E2
+               :           96 CF FE 58 80 8F EB B1 8C BD D4 0D
+               :           65 D0 3A 77 45 24 9E 0C EB 86 80 C3
+               :           AC 21 11 71 44 E3 B2 A8 A9 2E AC 17
+               :           D2 A3 84 25 63 B5 BC 2F 1E DD F6 21
+               :           FF 15 20 24 5B F1 80 2F D5 41 0E 32
+               :           24 F7 D4 4A 32 9E B9 49 D8 19 8E 3F
+               :           39 8D 62 BD 80 FC 0C 24 92 93 E4 C3
+               :           D7 05 91 53 BB 96 B6 41
+    301 02   65:         INTEGER
+               :           00 F3 B8 3F 4A D1 94 B0 91 60 13 41
+
+
+
+Hoffman, Ed.                 Informational                     [Page 12]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           92 0D 8D 44 3F 77 1D FF 96 23 44 08
+               :           D4 0B 70 C9 1A AF E9 90 94 F2 B0 D5
+               :           5F 4F 19 85 50 A1 90 91 AE BD 05 76
+               :           52 B3 22 D8 A8 7C 8E 54 7F 00 72 4F
+               :           36 75 68 73 B5
+    368 02   65:         INTEGER
+               :           00 E1 D2 E7 11 57 06 AE 72 95 22 16
+               :           AA 02 B4 5A ED 4E 9D 82 11 4F 96 3C
+               :           86 C9 10 8D 56 7B 31 75 79 69 E7 75
+               :           68 38 00 4B 2E D2 26 32 DD B1 E2 E0
+               :           2C 54 80 0A 75 BA D1 66 96 1B B0 0E
+               :           A0 7E D2 BB 91
+    435 02   65:         INTEGER
+               :           00 AF B6 BC DB 22 73 43 41 EC B4 B5
+               :           67 A9 A1 99 FC EF D2 8E FD 1D FB E5
+               :           29 8B FE 0A DF D4 C8 5E 57 25 0A 5D
+               :           2B D4 09 A0 56 5B C5 B1 62 FC 20 BE
+               :           08 2D E3 07 B5 A1 E7 B3 FF C4 C0 A5
+               :           5F AC 12 5C A9
+    502 02   65:         INTEGER
+               :           00 B9 98 41 FC 08 50 1F 73 60 8A 01
+               :           A2 7C 52 8A 20 5A EA 2C 89 D9 A5 19
+               :           DD 94 C6 1B C3 25 C0 82 51 E4 EE 2B
+               :           9A 19 DC 73 ED E9 1D 27 D4 F8 6C 03
+               :           DD AB 1D 08 7B B5 AC 7F E9 82 9B F1
+               :           89 8A 71 DB 61
+    569 02   64:         INTEGER
+               :           01 07 21 97 5F 7A 60 A8 FD 5A 5C 07
+               :           DF A8 DE F7 E2 B1 34 7D FC EB 91 BD
+               :           B0 73 74 C8 C4 BE 3F 58 45 30 06 90
+               :           B3 AC 69 CC B3 F7 3F 7C AC C7 B8 1B
+               :           65 A1 16 39 39 B0 E3 74 7D CF CD C5
+               :           AC 6C BF E5
+               :         }
+               :       }
+               :   }
+
+2.3.  Certificates
+
+   AliceDSSSignByCarlNoInherit =
+      0 30  732: SEQUENCE {
+      4 30  667:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02    2:     INTEGER 200
+     17 30    9:     SEQUENCE {
+     19 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 13]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :         (ANSI X9.57 algorithm)
+               :       }
+     28 30   18:     SEQUENCE {
+     30 31   16:       SET {
+     32 30   14:         SEQUENCE {
+     34 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     39 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     48 30   30:     SEQUENCE {
+     50 17   13:       UTCTime '990817011049Z'
+     65 17   13:       UTCTime '391231235959Z'
+               :       }
+     80 30   19:     SEQUENCE {
+     82 31   17:       SET {
+     84 30   15:         SEQUENCE {
+     86 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     91 13    8:           PrintableString 'AliceDSS'
+               :           }
+               :         }
+               :       }
+    101 30  438:     SEQUENCE {
+    105 30  299:       SEQUENCE {
+    109 06    7:         OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :           (ANSI X9.57 algorithm)
+    118 30  286:         SEQUENCE {
+    122 02  129:           INTEGER
+               :             00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :             48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :             53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :             0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :             2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :             DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :             9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :             8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :             C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :             78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :             B5 E4 09 96 5C F3 7E 5B DB
+    254 02   21:           INTEGER
+               :             00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :             B8 37 21 2B 62 8B F7 93 CD
+    277 02  128:           INTEGER
+               :             26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :             4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :             CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+
+
+
+Hoffman, Ed.                 Informational                     [Page 14]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :             7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :             3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :             E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :             01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :             95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :             1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :             D1 81 4A 60 39 BA 36 39
+               :           }
+               :         }
+    408 03  132:       BIT STRING 0 unused bits, encapsulates {
+    412 02  128:           INTEGER
+               :             5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :             3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :             16 89 28 11 23 D9 34 86 67 75 75 13
+               :             12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+               :             1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+               :             A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :             7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :             08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :             F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :             32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :             F2 A5 E2 F4 F2 83 E5 B8
+               :           }
+               :       }
+    543 A3  129:     [3] {
+    546 30  127:       SEQUENCE {
+    548 30   12:         SEQUENCE {
+    550 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    555 01    1:           BOOLEAN TRUE
+    558 04    2:           OCTET STRING, encapsulates {
+    560 30    0:               SEQUENCE {}
+               :               }
+               :           }
+    562 30   14:         SEQUENCE {
+    564 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    569 01    1:           BOOLEAN TRUE
+    572 04    4:           OCTET STRING, encapsulates {
+    574 03    2:               BIT STRING 6 unused bits
+               :                 '11'B
+               :               }
+               :           }
+    578 30   31:         SEQUENCE {
+    580 06    3:           OBJECT IDENTIFIER
+               :             authorityKeyIdentifier (2 5 29 35)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 15]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             (X.509 id-ce (2 5 29))
+    585 04   24:           OCTET STRING, encapsulates {
+    587 30   22:               SEQUENCE {
+    589 80   20:                 [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                 }
+               :               }
+               :           }
+    611 30   29:         SEQUENCE {
+    613 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    618 04   22:           OCTET STRING, encapsulates {
+    620 04   20:               OCTET STRING
+               :                 BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :                 13 01 E2 FD E3 97 FE CD
+               :               }
+               :           }
+    642 30   31:         SEQUENCE {
+    644 06    3:           OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+               :             (X.509 id-ce (2 5 29))
+    649 04   24:           OCTET STRING, encapsulates {
+    651 30   22:               SEQUENCE {
+    653 81   20:                 [1] 'AliceDSS at example.com'
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+    675 30    9:   SEQUENCE {
+    677 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :       (ANSI X9.57 algorithm)
+               :     }
+    686 03   48:   BIT STRING 0 unused bits, encapsulates {
+    689 30   45:       SEQUENCE {
+    691 02   20:         INTEGER
+               :           55 0C A4 19 1F 42 2B 89 71 22 33 8D
+               :           83 6A B5 3D 67 6B BF 45
+    713 02   21:         INTEGER
+               :           00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :           76 1D E2 10 52 5B 43 5E BD
+               :         }
+               :       }
+               :   }
+
+   AliceRSASignByCarl =
+
+
+
+Hoffman, Ed.                 Informational                     [Page 16]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+      0 30  556: SEQUENCE {
+      4 30  405:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02   16:     INTEGER
+               :       46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :       C4 10 B3 B0
+     31 30   13:     SEQUENCE {
+     33 06    9:       OBJECT IDENTIFIER
+               :         sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :         (PKCS #1)
+     44 05    0:       NULL
+               :       }
+     46 30   18:     SEQUENCE {
+     48 31   16:       SET {
+     50 30   14:         SEQUENCE {
+     52 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     57 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     66 30   30:     SEQUENCE {
+     68 17   13:       UTCTime '990919010847Z'
+     83 17   13:       UTCTime '391231235959Z'
+               :       }
+     98 30   19:     SEQUENCE {
+    100 31   17:       SET {
+    102 30   15:         SEQUENCE {
+    104 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+    109 13    8:           PrintableString 'AliceRSA'
+               :           }
+               :         }
+               :       }
+    119 30  159:     SEQUENCE {
+    122 30   13:       SEQUENCE {
+    124 06    9:         OBJECT IDENTIFIER
+               :           rsaEncryption (1 2 840 113549 1 1 1)
+               :           (PKCS #1)
+    135 05    0:         NULL
+               :         }
+    137 03  141:       BIT STRING 0 unused bits, encapsulates {
+    141 30  137:           SEQUENCE {
+    144 02  129:             INTEGER
+               :               00 E0 89 73 39 8D D8 F5 F5 E8 87 76
+               :               39 7F 4E B0 05 BB 53 83 DE 0F B7 AB
+
+
+
+Hoffman, Ed.                 Informational                     [Page 17]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               DC 7D C7 75 29 0D 05 2E 6D 12 DF A6
+               :               86 26 D4 D2 6F AA 58 29 FC 97 EC FA
+               :               82 51 0F 30 80 BE B1 50 9E 46 44 F1
+               :               2C BB D8 32 CF C6 68 6F 07 D9 B0 60
+               :               AC BE EE 34 09 6A 13 F5 F7 05 05 93
+               :               DF 5E BA 35 56 D9 61 FF 19 7F C9 81
+               :               E6 F8 6C EA 87 40 70 EF AC 6D 2C 74
+               :               9F 2D FA 55 3A B9 99 77 02 A6 48 52
+               :               8C 4E F3 57 38 57 74 57 5F
+    276 02    3:             INTEGER 65537
+               :             }
+               :           }
+               :       }
+    281 A3  129:     [3] {
+    284 30  127:       SEQUENCE {
+    286 30   12:         SEQUENCE {
+    288 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    293 01    1:           BOOLEAN TRUE
+    296 04    2:           OCTET STRING, encapsulates {
+    298 30    0:               SEQUENCE {}
+               :               }
+               :           }
+    300 30   14:         SEQUENCE {
+    302 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    307 01    1:           BOOLEAN TRUE
+    310 04    4:           OCTET STRING, encapsulates {
+    312 03    2:               BIT STRING 6 unused bits
+               :                 '11'B
+               :               }
+               :           }
+    316 30   31:         SEQUENCE {
+    318 06    3:           OBJECT IDENTIFIER
+               :             authorityKeyIdentifier (2 5 29 35)
+               :             (X.509 id-ce (2 5 29))
+    323 04   24:           OCTET STRING, encapsulates {
+    325 30   22:               SEQUENCE {
+    327 80   20:                 [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                 }
+               :               }
+               :           }
+    349 30   29:         SEQUENCE {
+    351 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 18]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             (X.509 id-ce (2 5 29))
+    356 04   22:           OCTET STRING, encapsulates {
+    358 04   20:               OCTET STRING
+               :                 77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D
+               :                 CE EC 3C A0 3A E3 FF 50
+               :               }
+               :           }
+    380 30   31:         SEQUENCE {
+    382 06    3:           OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+               :             (X.509 id-ce (2 5 29))
+    387 04   24:           OCTET STRING, encapsulates {
+    389 30   22:               SEQUENCE {
+    391 81   20:                 [1] 'AliceRSA at example.com'
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+    413 30   13:   SEQUENCE {
+    415 06    9:     OBJECT IDENTIFIER
+               :       sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :       (PKCS #1)
+    426 05    0:     NULL
+               :     }
+    428 03  129:   BIT STRING 0 unused bits
+               :     3E 70 47 A8 48 CC 13 58 8F CA 51 71
+               :     6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC
+               :     CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C
+               :     59 A9 20 AA 05 81 A8 4E 25 AD A7 70
+               :     14 75 2F F5 C7 9B D1 0E E9 63 D2 64
+               :     B7 C6 66 6E 73 21 54 DF F4 BA 25 5D
+               :     7D 49 D3 94 6B 22 36 74 73 B8 4A EC
+               :     2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A
+               :     B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA
+               :     F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A
+               :     76 AE EB 9B DB 49 B0 22
+               :   }
+
+   BobRSASignByCarl =
+      0 30  551: SEQUENCE {
+      4 30  400:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02   16:     INTEGER
+               :       46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :       CD 5D 71 D0
+
+
+
+Hoffman, Ed.                 Informational                     [Page 19]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     31 30   13:     SEQUENCE {
+     33 06    9:       OBJECT IDENTIFIER
+               :         sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :         (PKCS #1)
+     44 05    0:       NULL
+               :       }
+     46 30   18:     SEQUENCE {
+     48 31   16:       SET {
+     50 30   14:         SEQUENCE {
+     52 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     57 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     66 30   30:     SEQUENCE {
+     68 17   13:       UTCTime '990919010902Z'
+     83 17   13:       UTCTime '391231235959Z'
+               :       }
+     98 30   17:     SEQUENCE {
+    100 31   15:       SET {
+    102 30   13:         SEQUENCE {
+    104 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+    109 13    6:           PrintableString 'BobRSA'
+               :           }
+               :         }
+               :       }
+    117 30  159:     SEQUENCE {
+    120 30   13:       SEQUENCE {
+    122 06    9:         OBJECT IDENTIFIER
+               :           rsaEncryption (1 2 840 113549 1 1 1)
+               :           (PKCS #1)
+    133 05    0:         NULL
+               :         }
+    135 03  141:       BIT STRING 0 unused bits, encapsulates {
+    139 30  137:           SEQUENCE {
+    142 02  129:             INTEGER
+               :               00 A9 E1 67 98 3F 39 D5 5F F2 A0 93
+               :               41 5E A6 79 89 85 C8 35 5D 9A 91 5B
+               :               FB 1D 01 DA 19 70 26 17 0F BD A5 22
+               :               D0 35 85 6D 7A 98 66 14 41 5C CF B7
+               :               B7 08 3B 09 C9 91 B8 19 69 37 6D F9
+               :               65 1E 7B D9 A9 33 24 A3 7F 3B BB AF
+               :               46 01 86 36 34 32 CB 07 03 59 52 FC
+               :               85 8B 31 04 B8 CC 18 08 14 48 E6 4F
+               :               1C FB 5D 60 C4 E0 5C 1F 53 D3 7F 53
+               :               D8 69 01 F1 05 F8 7A 70 D1 BE 83 C6
+
+
+
+Hoffman, Ed.                 Informational                     [Page 20]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               5F 38 CF 1C 2C AA 6A A7 EB
+    274 02    3:             INTEGER 65537
+               :             }
+               :           }
+               :       }
+    279 A3  127:     [3] {
+    281 30  125:       SEQUENCE {
+    283 30   12:         SEQUENCE {
+    285 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    290 01    1:           BOOLEAN TRUE
+    293 04    2:           OCTET STRING, encapsulates {
+    295 30    0:               SEQUENCE {}
+               :               }
+               :           }
+    297 30   14:         SEQUENCE {
+    299 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    304 01    1:           BOOLEAN TRUE
+    307 04    4:           OCTET STRING, encapsulates {
+    309 03    2:               BIT STRING 5 unused bits
+               :                 '100'B (bit 2)
+               :               }
+               :           }
+    313 30   31:         SEQUENCE {
+    315 06    3:           OBJECT IDENTIFIER
+               :             authorityKeyIdentifier (2 5 29 35)
+               :             (X.509 id-ce (2 5 29))
+    320 04   24:           OCTET STRING, encapsulates {
+    322 30   22:               SEQUENCE {
+    324 80   20:                 [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                 }
+               :               }
+               :           }
+    346 30   29:         SEQUENCE {
+    348 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    353 04   22:           OCTET STRING, encapsulates {
+    355 04   20:               OCTET STRING
+               :                 E8 F4 B8 67 D8 B3 96 A4 2A F3 11 AA
+               :                 29 D3 95 5A 86 16 B4 24
+               :               }
+               :           }
+    377 30   29:         SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 21]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    379 06    3:           OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+               :             (X.509 id-ce (2 5 29))
+    384 04   22:           OCTET STRING, encapsulates {
+    386 30   20:               SEQUENCE {
+    388 81   18:                 [1] 'BobRSA at example.com'
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+    408 30   13:   SEQUENCE {
+    410 06    9:     OBJECT IDENTIFIER
+               :       sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :       (PKCS #1)
+    421 05    0:     NULL
+               :     }
+    423 03  129:   BIT STRING 0 unused bits
+               :     7B 8E 66 C5 F1 10 3F 10 20 4C 88 71
+               :     AB 7B 40 6B 21 33 FA 4A 95 DE 9D 0E
+               :     5B 6B 94 21 05 C0 F2 E1 7E 2A CD 9C
+               :     93 88 87 FB 8B B7 7E 7D 41 61 E1 E4
+               :     D6 6D F9 E2 04 55 61 45 BC 64 27 44
+               :     C0 A1 BD 59 79 D9 1D 64 3C 21 D6 45
+               :     B0 5D 68 33 92 EA AC F1 57 E5 81 7D
+               :     98 E6 35 91 A3 39 DE 77 F4 E8 1C 3B
+               :     29 DC 7F 51 07 97 F3 36 F0 50 0A DD
+               :     9B DE B6 5E 38 11 2B FB 57 EA 89 6D
+               :     AD C9 88 D8 8F CF 2B D3
+               :   }
+
+   CarlDSSSelf =
+      0 30  667: SEQUENCE {
+      4 30  602:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02    1:     INTEGER 1
+     16 30    9:     SEQUENCE {
+     18 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :         (ANSI X9.57 algorithm)
+               :       }
+     27 30   18:     SEQUENCE {
+     29 31   16:       SET {
+     31 30   14:         SEQUENCE {
+     33 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     38 13    7:           PrintableString 'CarlDSS'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 22]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           }
+               :         }
+               :       }
+     47 30   30:     SEQUENCE {
+     49 17   13:       UTCTime '990816225050Z'
+     64 17   13:       UTCTime '391231235959Z'
+               :       }
+     79 30   18:     SEQUENCE {
+     81 31   16:       SET {
+     83 30   14:         SEQUENCE {
+     85 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     90 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     99 30  439:     SEQUENCE {
+    103 30  299:       SEQUENCE {
+    107 06    7:         OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :           (ANSI X9.57 algorithm)
+    116 30  286:         SEQUENCE {
+    120 02  129:           INTEGER
+               :             00 B6 49 18 3E 8A 44 C1 29 71 94 4C
+               :             01 C4 12 C1 7A 79 CB 54 4D AB 1E 81
+               :             FB C6 4C B3 0E 94 09 06 EB 01 D4 B1
+               :             C8 71 4B C7 45 C0 50 25 5D 9C FC DA
+               :             E4 6D D3 E2 86 48 84 82 7D BA 15 95
+               :             4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A
+               :             0A 8A BA 16 7B B9 50 01 48 93 8B EB
+               :             25 15 51 97 55 DC 8F 53 0E 10 A9 50
+               :             FC 70 B7 CD 30 54 FD DA DE A8 AA 22
+               :             B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9
+               :             AD E1 08 D4 6D 29 2D D6 E9
+    252 02   21:           INTEGER
+               :             00 DD C1 2F DF 53 CE 0B 34 60 77 3E
+               :             02 A4 BF 8A 5D 98 B9 10 D5
+    275 02  128:           INTEGER
+               :             0C EE 57 9B 4B BD DA B6 07 6A 74 37
+               :             4F 55 7F 9D ED BC 61 0D EB 46 59 3C
+               :             56 0B 2B 5B 0C 91 CE A5 62 52 69 CA
+               :             E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C
+               :             AD CB AE 45 E3 06 AC 8C 22 9D 9C 44
+               :             87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE
+               :             AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A
+               :             73 AA 7F 46 51 1F A9 42 16 9C 48 EB
+               :             8A 79 61 B4 D5 2F 53 22 44 63 1F 86
+               :             B8 A3 58 06 25 F8 29 C0 EF BA E0 75
+               :             F0 42 C4 63 65 52 9B 0A
+
+
+
+Hoffman, Ed.                 Informational                     [Page 23]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           }
+               :         }
+    406 03  133:       BIT STRING 0 unused bits, encapsulates {
+    410 02  129:           INTEGER
+               :             00 99 87 74 27 03 66 A0 B1 C0 AD DC
+               :             2C 75 BB E1 6C 44 9C DA 21 6D 4D 47
+               :             6D B1 62 09 E9 D8 AE 1E F2 3A B4 94
+               :             B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25
+               :             4E B9 60 96 19 24 01 F3 62 0C FE 75
+               :             C0 FB CE D8 68 00 E3 FD D5 70 4F DF
+               :             23 96 19 06 94 F4 B1 61 8F 3A 57 B1
+               :             08 11 A4 0B 26 25 F0 52 76 81 EA 0B
+               :             62 0D 95 2A E6 86 BA 72 B2 A7 50 83
+               :             0B AA 27 CD 1B A9 4D 89 9A D7 8D 18
+               :             39 84 3F 8B C5 56 4D 80 7A
+               :           }
+               :       }
+    542 A3   66:     [3] {
+    544 30   64:       SEQUENCE {
+    546 30   15:         SEQUENCE {
+    548 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    553 01    1:           BOOLEAN TRUE
+    556 04    5:           OCTET STRING, encapsulates {
+    558 30    3:               SEQUENCE {
+    560 01    1:                 BOOLEAN TRUE
+               :                 }
+               :               }
+               :           }
+    563 30   14:         SEQUENCE {
+    565 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    570 01    1:           BOOLEAN TRUE
+    573 04    4:           OCTET STRING, encapsulates {
+    575 03    2:               BIT STRING 1 unused bits
+               :                 '1100001'B
+               :               }
+               :           }
+    579 30   29:         SEQUENCE {
+    581 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    586 04   22:           OCTET STRING, encapsulates {
+    588 04   20:               OCTET STRING
+               :                 70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                 3D 20 BC 43 2B 93 F1 1F
+               :               }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 24]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           }
+               :         }
+               :       }
+               :     }
+    610 30    9:   SEQUENCE {
+    612 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :       (ANSI X9.57 algorithm)
+               :     }
+    621 03   48:   BIT STRING 0 unused bits, encapsulates {
+    624 30   45:       SEQUENCE {
+    626 02   20:         INTEGER
+               :           6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B
+               :           C9 06 37 E9 11 17 A1 13
+    648 02   21:         INTEGER
+               :           00 8F 34 69 2A 8B B1 3C 03 79 94 32
+               :           4D 12 1F CE 89 FB 46 B2 3B
+               :         }
+               :       }
+               :   }
+
+   CarlRSASelf =
+      0 30  491: SEQUENCE {
+      4 30  340:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02   16:     INTEGER
+               :       46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :       9F F2 50 20
+     31 30   13:     SEQUENCE {
+     33 06    9:       OBJECT IDENTIFIER
+               :         sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :         (PKCS #1)
+     44 05    0:       NULL
+               :       }
+     46 30   18:     SEQUENCE {
+     48 31   16:       SET {
+     50 30   14:         SEQUENCE {
+     52 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     57 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     66 30   30:     SEQUENCE {
+     68 17   13:       UTCTime '990818070000Z'
+     83 17   13:       UTCTime '391231235959Z'
+               :       }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 25]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     98 30   18:     SEQUENCE {
+    100 31   16:       SET {
+    102 30   14:         SEQUENCE {
+    104 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+    109 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+    118 30  159:     SEQUENCE {
+    121 30   13:       SEQUENCE {
+    123 06    9:         OBJECT IDENTIFIER
+               :           rsaEncryption (1 2 840 113549 1 1 1)
+               :           (PKCS #1)
+    134 05    0:         NULL
+               :         }
+    136 03  141:       BIT STRING 0 unused bits, encapsulates {
+    140 30  137:           SEQUENCE {
+    143 02  129:             INTEGER
+               :               00 E4 4B FF 18 B8 24 57 F4 77 FF 6E
+               :               73 7B 93 71 5C BC 33 1A 92 92 72 23
+               :               D8 41 46 D0 CD 11 3A 04 B3 8E AF 82
+               :               9D BD 51 1E 17 7A F2 76 2C 2B 86 39
+               :               A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC
+               :               A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F
+               :               99 25 8F B8 4E AB B9 7D D5 96 65 DA
+               :               16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7
+               :               29 CB 82 DD AC 44 E9 AA 93 94 29 0E
+               :               F8 18 D6 C8 57 5E F2 76 C4 F2 11 60
+               :               38 B9 1B 3C 1D 97 C9 6A F1
+    275 02    3:             INTEGER 65537
+               :             }
+               :           }
+               :       }
+    280 A3   66:     [3] {
+    282 30   64:       SEQUENCE {
+    284 30   15:         SEQUENCE {
+    286 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    291 01    1:           BOOLEAN TRUE
+    294 04    5:           OCTET STRING, encapsulates {
+    296 30    3:               SEQUENCE {
+    298 01    1:                 BOOLEAN TRUE
+               :                 }
+               :               }
+               :           }
+    301 30   14:         SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 26]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    303 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    308 01    1:           BOOLEAN TRUE
+    311 04    4:           OCTET STRING, encapsulates {
+    313 03    2:               BIT STRING 1 unused bits
+               :                 '1100001'B
+               :               }
+               :           }
+    317 30   29:         SEQUENCE {
+    319 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    324 04   22:           OCTET STRING, encapsulates {
+    326 04   20:               OCTET STRING
+               :                 E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                 42 37 4E 22 AE 9E 38 BB
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+    348 30   13:   SEQUENCE {
+    350 06    9:     OBJECT IDENTIFIER
+               :       sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :       (PKCS #1)
+    361 05    0:     NULL
+               :     }
+    363 03  129:   BIT STRING 0 unused bits
+               :     B7 9E D4 04 D3 ED 29 E4 FF 89 89 15
+               :     2E 4C DB 0C F0 48 0F 32 61 EE C4 04
+               :     EC 12 5D 2D FF 0F 64 59 7E 0A C3 ED
+               :     18 FD E3 56 40 37 A7 07 B5 F0 38 12
+               :     61 50 ED EF DD 3F E3 0B B8 61 A5 A4
+               :     9B 3C E6 9E 9C 54 9A B6 95 D6 DA 6C
+               :     3B B5 2D 45 35 9D 49 01 76 FA B9 B9
+               :     31 F9 F9 6B 12 53 A0 F5 14 60 9B 7D
+               :     CA 3E F2 53 6B B0 37 6F AD E6 74 D7
+               :     DB FA 5A EA 14 41 63 5D CD BE C8 0E
+               :     C1 DA 6A 8D 53 34 18 02
+               :   }
+
+   DianeDSSSignByCarlInherit =
+      0 30  440: SEQUENCE {
+      4 30  375:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02    2:     INTEGER 210
+
+
+
+Hoffman, Ed.                 Informational                     [Page 27]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     17 30    9:     SEQUENCE {
+     19 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :         (ANSI X9.57 algorithm)
+               :       }
+     28 30   18:     SEQUENCE {
+     30 31   16:       SET {
+     32 30   14:         SEQUENCE {
+     34 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     39 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     48 30   30:     SEQUENCE {
+     50 17   13:       UTCTime '990817020810Z'
+     65 17   13:       UTCTime '391231235959Z'
+               :       }
+     80 30   19:     SEQUENCE {
+     82 31   17:       SET {
+     84 30   15:         SEQUENCE {
+     86 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     91 13    8:           PrintableString 'DianeDSS'
+               :           }
+               :         }
+               :       }
+    101 30  147:     SEQUENCE {
+    104 30    9:       SEQUENCE {
+    106 06    7:         OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :           (ANSI X9.57 algorithm)
+               :         }
+    115 03  133:       BIT STRING 0 unused bits, encapsulates {
+    119 02  129:           INTEGER
+               :             00 A0 00 17 78 2C EE 7E 81 53 2E 2E
+               :             61 08 0F A1 9B 51 52 1A DA 59 A8 73
+               :             2F 12 25 B6 08 CB CA EF 2A 44 76 8A
+               :             52 09 EA BD 05 22 D5 0F F6 FD 46 D7
+               :             AF 99 38 09 0E 13 CB 4F 2C DD 1C 34
+               :             F7 1C BF 25 FF 23 D3 3B 59 E7 82 97
+               :             37 BE 31 24 D8 18 C8 F3 49 39 5B B7
+               :             E2 E5 27 7E FC 8C 45 72 5B 7E 3E 8F
+               :             68 4D DD 46 7A 22 BE 8E FF CC DA 39
+               :             29 A3 39 E5 9F 43 E9 55 C9 D7 5B A6
+               :             81 67 CC C0 AA CD 2E C5 23
+               :           }
+               :       }
+    251 A3  129:     [3] {
+    254 30  127:       SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 28]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    256 30   12:         SEQUENCE {
+    258 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    263 01    1:           BOOLEAN TRUE
+    266 04    2:           OCTET STRING, encapsulates {
+    268 30    0:               SEQUENCE {}
+               :               }
+               :           }
+    270 30   14:         SEQUENCE {
+    272 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+    277 01    1:           BOOLEAN TRUE
+    280 04    4:           OCTET STRING, encapsulates {
+    282 03    2:               BIT STRING 6 unused bits
+               :                 '11'B
+               :               }
+               :           }
+    286 30   31:         SEQUENCE {
+    288 06    3:           OBJECT IDENTIFIER
+               :             authorityKeyIdentifier (2 5 29 35)
+               :             (X.509 id-ce (2 5 29))
+    293 04   24:           OCTET STRING, encapsulates {
+    295 30   22:               SEQUENCE {
+    297 80   20:                 [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                 }
+               :               }
+               :           }
+    319 30   29:         SEQUENCE {
+    321 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    326 04   22:           OCTET STRING, encapsulates {
+    328 04   20:               OCTET STRING
+               :                 64 30 99 7D 5C DC 45 0B 99 3A 52 2F
+               :                 16 BF 58 50 DD CE 2B 18
+               :               }
+               :           }
+    350 30   31:         SEQUENCE {
+    352 06    3:           OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+               :             (X.509 id-ce (2 5 29))
+    357 04   24:           OCTET STRING, encapsulates {
+    359 30   22:               SEQUENCE {
+    361 81   20:                 [1] 'DianeDSS at example.com'
+               :                 }
+               :               }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 29]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           }
+               :         }
+               :       }
+               :     }
+    383 30    9:   SEQUENCE {
+    385 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :       (ANSI X9.57 algorithm)
+               :     }
+    394 03   48:   BIT STRING 0 unused bits, encapsulates {
+    397 30   45:       SEQUENCE {
+    399 02   21:         INTEGER
+               :           00 A1 1A F8 17 0E 3E 5D A8 8C F4 B6
+               :           55 33 1E 4B E3 2C AC B9 5F
+    422 02   20:         INTEGER
+               :           28 4B 10 45 58 D2 1C 9D 55 35 14 18
+               :           91 B2 3F 39 DF B5 6E D3
+               :         }
+               :       }
+               :   }
+
+   DianeRSASignByCarl =
+      0 30  556: SEQUENCE {
+      4 30  405:   SEQUENCE {
+      8 A0    3:     [0] {
+     10 02    1:       INTEGER 2
+               :       }
+     13 02   16:     INTEGER
+               :       46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :       D5 9A 30 90
+     31 30   13:     SEQUENCE {
+     33 06    9:       OBJECT IDENTIFIER
+               :         sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :         (PKCS #1)
+     44 05    0:       NULL
+               :       }
+     46 30   18:     SEQUENCE {
+     48 31   16:       SET {
+     50 30   14:         SEQUENCE {
+     52 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     57 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     66 30   30:     SEQUENCE {
+     68 17   13:       UTCTime '990819070000Z'
+     83 17   13:       UTCTime '391231235959Z'
+               :       }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 30]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     98 30   19:     SEQUENCE {
+    100 31   17:       SET {
+    102 30   15:         SEQUENCE {
+    104 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+    109 13    8:           PrintableString 'DianeRSA'
+               :           }
+               :         }
+               :       }
+    119 30  159:     SEQUENCE {
+    122 30   13:       SEQUENCE {
+    124 06    9:         OBJECT IDENTIFIER
+               :           rsaEncryption (1 2 840 113549 1 1 1)
+               :           (PKCS #1)
+    135 05    0:         NULL
+               :         }
+    137 03  141:       BIT STRING 0 unused bits, encapsulates {
+    141 30  137:           SEQUENCE {
+    144 02  129:             INTEGER
+               :               00 D6 FD B8 C0 70 C6 4C 25 EC EA CF
+               :               EA 7C BB A2 62 FA F0 E6 32 3A 53 FF
+               :               B1 92 5A 17 F4 20 E1 99 24 82 0A D0
+               :               F6 7C FB 44 CA 8B 27 06 F1 7E 26 03
+               :               A9 76 9D CF EC A0 2C 70 96 F2 83 42
+               :               F6 D4 B7 28 0A BB F8 BF 4A 4C 19 3F
+               :               07 DB A0 C1 60 1E B7 7E 67 F7 DE B1
+               :               C3 60 49 AC 45 D7 F8 C6 EF 08 37 21
+               :               93 47 EE F0 73 35 72 B0 02 C4 F3 11
+               :               C3 5E 47 E5 0A B7 83 F1 DB 74 69 64
+               :               8B 44 1D 95 5D CD 28 C0 85
+    276 02    3:             INTEGER 65537
+               :             }
+               :           }
+               :       }
+    281 A3  129:     [3] {
+    284 30  127:       SEQUENCE {
+    286 30   12:         SEQUENCE {
+    288 06    3:           OBJECT IDENTIFIER
+               :             basicConstraints (2 5 29 19)
+               :             (X.509 id-ce (2 5 29))
+    293 01    1:           BOOLEAN TRUE
+    296 04    2:           OCTET STRING, encapsulates {
+    298 30    0:               SEQUENCE {}
+               :               }
+               :           }
+    300 30   14:         SEQUENCE {
+    302 06    3:           OBJECT IDENTIFIER keyUsage (2 5 29 15)
+               :             (X.509 id-ce (2 5 29))
+
+
+
+Hoffman, Ed.                 Informational                     [Page 31]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    307 01    1:           BOOLEAN TRUE
+    310 04    4:           OCTET STRING, encapsulates {
+    312 03    2:               BIT STRING 5 unused bits
+               :                 '111'B
+               :               }
+               :           }
+    316 30   31:         SEQUENCE {
+    318 06    3:           OBJECT IDENTIFIER
+               :             authorityKeyIdentifier (2 5 29 35)
+               :             (X.509 id-ce (2 5 29))
+    323 04   24:           OCTET STRING, encapsulates {
+    325 30   22:               SEQUENCE {
+    327 80   20:                 [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                 }
+               :               }
+               :           }
+    349 30   29:         SEQUENCE {
+    351 06    3:           OBJECT IDENTIFIER
+               :             subjectKeyIdentifier (2 5 29 14)
+               :             (X.509 id-ce (2 5 29))
+    356 04   22:           OCTET STRING, encapsulates {
+    358 04   20:               OCTET STRING
+               :                 8C F3 CB 75 0E 8D 31 F6 D4 29 DA 44
+               :                 92 75 B8 FE ED 4F 39 0C
+               :               }
+               :           }
+    380 30   31:         SEQUENCE {
+    382 06    3:           OBJECT IDENTIFIER subjectAltName (2 5 29 17)
+               :             (X.509 id-ce (2 5 29))
+    387 04   24:           OCTET STRING, encapsulates {
+    389 30   22:               SEQUENCE {
+    391 81   20:                 [1] 'DianeRSA at example.com'
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+    413 30   13:   SEQUENCE {
+    415 06    9:     OBJECT IDENTIFIER
+               :       sha1withRSAEncryption (1 2 840 113549 1 1 5)
+               :       (PKCS #1)
+    426 05    0:     NULL
+               :     }
+    428 03  129:   BIT STRING 0 unused bits
+               :     7D A6 2C B5 78 42 D6 79 F3 31 FE F6
+
+
+
+Hoffman, Ed.                 Informational                     [Page 32]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :     42 CA 0F 13 07 92 09 1B E0 6F B0 91
+               :     18 F6 BF 4A FB CC 63 79 FB 81 BF DD
+               :     97 C7 90 6B CB 0A 37 2B 41 6A 03 98
+               :     C5 1B 3E 32 C8 45 2B 86 01 9C 1C E2
+               :     36 EF 16 C1 1A 92 B8 BE 62 FB 53 3E
+               :     49 47 0B C4 B9 E4 2B 58 A6 06 83 F0
+               :     B2 A7 BB 85 7E D5 C6 DA CE 9C 7B 31
+               :     72 D7 A2 EA 41 AB 6A C0 DD 1F B9 14
+               :     44 18 CF 84 57 66 E8 C5 E6 B8 DC 2D
+               :     B3 1F 1B 28 43 36 75 7A
+               :   }
+
+2.4.  CRLs
+
+   CarlDSSCRLForAll =
+      0 30  216: SEQUENCE {
+      3 30  153:   SEQUENCE {
+      6 30    9:     SEQUENCE {
+      8 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :         (ANSI X9.57 algorithm)
+               :       }
+     17 30   18:     SEQUENCE {
+     19 31   16:       SET {
+     21 30   14:         SEQUENCE {
+     23 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     28 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     37 17   13:     UTCTime '990827070000Z'
+     52 30  105:     SEQUENCE {
+     54 30   19:       SEQUENCE {
+     56 02    2:         INTEGER 200
+     60 17   13:         UTCTime '990822070000Z'
+               :         }
+     75 30   19:       SEQUENCE {
+     77 02    2:         INTEGER 201
+     81 17   13:         UTCTime '990822070000Z'
+               :         }
+     96 30   19:       SEQUENCE {
+     98 02    2:         INTEGER 211
+    102 17   13:         UTCTime '990822070000Z'
+               :         }
+    117 30   19:       SEQUENCE {
+    119 02    2:         INTEGER 210
+    123 17   13:         UTCTime '990822070000Z'
+               :         }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 33]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    138 30   19:       SEQUENCE {
+    140 02    2:         INTEGER 212
+    144 17   13:         UTCTime '990824070000Z'
+               :         }
+               :       }
+               :     }
+    159 30    9:   SEQUENCE {
+    161 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :       (ANSI X9.57 algorithm)
+               :     }
+    170 03   47:   BIT STRING 0 unused bits, encapsulates {
+    173 30   44:       SEQUENCE {
+    175 02   20:         INTEGER
+               :           7E 65 52 76 33 FE 34 73 17 D1 F7 96
+               :           F9 A0 D4 D8 6D 5C 7D 3D
+    197 02   20:         INTEGER
+               :           02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E
+               :           DA 24 F3 2A 83 9C 35 A1
+               :         }
+               :       }
+               :   }
+
+   CarlDSSCRLForCarl =
+      0 30  131: SEQUENCE {
+      3 30   68:   SEQUENCE {
+      5 30    9:     SEQUENCE {
+      7 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :         (ANSI X9.57 algorithm)
+               :       }
+     16 30   18:     SEQUENCE {
+     18 31   16:       SET {
+     20 30   14:         SEQUENCE {
+     22 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     27 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     36 17   13:     UTCTime '990825070000Z'
+     51 30   20:     SEQUENCE {
+     53 30   18:       SEQUENCE {
+     55 02    1:         INTEGER 1
+     58 17   13:         UTCTime '990822070000Z'
+               :         }
+               :       }
+               :     }
+     73 30    9:   SEQUENCE {
+     75 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 34]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :       (ANSI X9.57 algorithm)
+               :     }
+     84 03   48:   BIT STRING 0 unused bits, encapsulates {
+     87 30   45:       SEQUENCE {
+     89 02   21:         INTEGER
+               :           00 B3 1F C5 4F 7A 3D EC 76 D5 60 F9
+               :           DE 79 22 EC 4F B0 90 FE 97
+    112 02   20:         INTEGER
+               :           5A 8B C3 84 BC 66 87 1B BF 79 82 5B
+               :           0A 5D 07 F6 BA A9 05 29
+               :         }
+               :       }
+               :   }
+
+   CarlDSSCRLEmpty =
+      0 30  109: SEQUENCE {
+      2 30   46:   SEQUENCE {
+      4 30    9:     SEQUENCE {
+      6 06    7:       OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :         (ANSI X9.57 algorithm)
+               :       }
+     15 30   18:     SEQUENCE {
+     17 31   16:       SET {
+     19 30   14:         SEQUENCE {
+     21 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     26 13    7:           PrintableString 'CarlDSS'
+               :           }
+               :         }
+               :       }
+     35 17   13:     UTCTime '990820070000Z'
+               :     }
+     50 30    9:   SEQUENCE {
+     52 06    7:     OBJECT IDENTIFIER dsaWithSha1 (1 2 840 10040 4 3)
+               :       (ANSI X9.57 algorithm)
+               :     }
+     61 03   48:   BIT STRING 0 unused bits, encapsulates {
+     64 30   45:       SEQUENCE {
+     66 02   20:         INTEGER
+               :           62 3F 36 17 31 58 2E 67 50 79 F5 09
+               :           4B 8C AD D4 6B F4 64 9F
+     88 02   21:         INTEGER
+               :           00 B5 3B 4E A1 4C 7B FD 0F C3 8D 9B
+               :           B6 FE C3 5D 6F DE 65 28 7D
+               :         }
+               :       }
+               :   }
+
+
+
+
+Hoffman, Ed.                 Informational                     [Page 35]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   CarlRSACRLForAll =
+      0 30  307: SEQUENCE {
+      4 30  157:   SEQUENCE {
+      7 30   13:     SEQUENCE {
+      9 06    9:       OBJECT IDENTIFIER
+               :         md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :         (PKCS #1)
+     20 05    0:       NULL
+               :       }
+     22 30   18:     SEQUENCE {
+     24 31   16:       SET {
+     26 30   14:         SEQUENCE {
+     28 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     33 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     42 17   13:     UTCTime '990827070000Z'
+     57 30  105:     SEQUENCE {
+     59 30   33:       SEQUENCE {
+     61 02   16:         INTEGER
+               :           46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :           C4 10 B3 B0
+     79 17   13:         UTCTime '990822070000Z'
+               :         }
+     94 30   33:       SEQUENCE {
+     96 02   16:         INTEGER
+               :           46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :           D5 9A 30 90
+    114 17   13:         UTCTime '990822070000Z'
+               :         }
+    129 30   33:       SEQUENCE {
+    131 02   16:         INTEGER
+               :           46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :           CD 5D 71 D0
+    149 17   13:         UTCTime '990824070000Z'
+               :         }
+               :       }
+               :     }
+    164 30   13:   SEQUENCE {
+    166 06    9:     OBJECT IDENTIFIER
+               :       md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :       (PKCS #1)
+    177 05    0:     NULL
+               :     }
+    179 03  129:   BIT STRING 0 unused bits
+               :     BF B3 97 AA 53 F0 32 21 16 2B 77 92
+
+
+
+Hoffman, Ed.                 Informational                     [Page 36]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :     7A 6B BB 97 C8 DC EA F1 FA 66 16 30
+               :     0E B5 9E 5C F0 81 D4 5E B3 6E C1 88
+               :     6B 8C D4 5E C5 4D FB 47 5E 66 F3 5D
+               :     AB E5 B4 18 36 60 A8 4D 9C 3C 89 EC
+               :     6F 27 BF 35 50 71 81 C2 B9 44 5B 62
+               :     89 19 12 31 A9 7B 9A D3 CC 66 CB 11
+               :     D9 0B 10 47 77 AD 4F 22 D9 E5 7F 30
+               :     F2 5B FC 94 51 A5 58 76 3B 1F A8 46
+               :     A6 1F F6 A1 DE 55 A1 ED 31 88 69 97
+               :     0F 08 D3 D4 0C 60 5B 1E
+               :   }
+
+   CarlRSACRLForCarl =
+      0 30  236: SEQUENCE {
+      3 30   87:   SEQUENCE {
+      5 30   13:     SEQUENCE {
+      7 06    9:       OBJECT IDENTIFIER
+               :         md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :         (PKCS #1)
+     18 05    0:       NULL
+               :       }
+     20 30   18:     SEQUENCE {
+     22 31   16:       SET {
+     24 30   14:         SEQUENCE {
+     26 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     31 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     40 17   13:     UTCTime '990825070000Z'
+     55 30   35:     SEQUENCE {
+     57 30   33:       SEQUENCE {
+     59 02   16:         INTEGER
+               :           46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :           9F F2 50 20
+     77 17   13:         UTCTime '990822070000Z'
+               :         }
+               :       }
+               :     }
+     92 30   13:   SEQUENCE {
+     94 06    9:     OBJECT IDENTIFIER
+               :       md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :       (PKCS #1)
+    105 05    0:     NULL
+               :     }
+    107 03  129:   BIT STRING 0 unused bits
+               :     21 EF 21 D4 C1 1A 85 95 49 6B CA 45
+
+
+
+Hoffman, Ed.                 Informational                     [Page 37]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :     62 DC D7 09 FF A9 51 2E 8E D9 47 18
+               :     FA F8 E5 72 DD 4F ED 74 74 E3 F3 65
+               :     32 65 28 2C 9A 1D 57 E5 D5 26 06 EA
+               :     D5 E6 23 95 84 8D 0E 89 9E EE 9B 0C
+               :     2F CE 07 F7 A3 D1 6B 85 4C 0F FF E6
+               :     DD FC DC CD 73 2C 1E 7D DC B0 71 C5
+               :     4C FC 01 6E 52 57 69 1E 39 63 DF 12
+               :     22 30 C7 13 55 94 05 6E 2A 00 A9 5B
+               :     C4 2A 66 94 62 CE 36 33 C2 2B 63 47
+               :     25 9D F3 DE 70 EE 00 56
+               :   }
+
+   CarlRSACRLEmpty =
+      0 30  199: SEQUENCE {
+      3 30   50:   SEQUENCE {
+      5 30   13:     SEQUENCE {
+      7 06    9:       OBJECT IDENTIFIER
+               :         md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :         (PKCS #1)
+     18 05    0:       NULL
+               :       }
+     20 30   18:     SEQUENCE {
+     22 31   16:       SET {
+     24 30   14:         SEQUENCE {
+     26 06    3:           OBJECT IDENTIFIER commonName (2 5 4 3)
+               :             (X.520 id-at (2 5 4))
+     31 13    7:           PrintableString 'CarlRSA'
+               :           }
+               :         }
+               :       }
+     40 17   13:     UTCTime '990820070000Z'
+               :     }
+     55 30   13:   SEQUENCE {
+     57 06    9:     OBJECT IDENTIFIER
+               :       md5withRSAEncryption (1 2 840 113549 1 1 4)
+               :       (PKCS #1)
+     68 05    0:     NULL
+               :     }
+     70 03  129:   BIT STRING 0 unused bits
+               :     A9 C5 21 B8 13 7C 74 F3 B5 11 EC 04
+               :     F3 20 45 86 1E 0B 6E 7F 83 6D 5F F4
+               :     34 76 06 59 25 0E 04 3D 88 09 88 81
+               :     37 C4 DC 20 98 FA 17 81 0B 37 94 AC
+               :     B4 8F 7B 51 89 14 A4 CB 72 73 14 07
+               :     BC 22 9C 40 A1 07 FC 44 7C 85 0F 0B
+               :     88 D1 EE E1 0E AF F6 16 74 AD A1 AF
+               :     C1 00 75 00 64 EA A5 9A F6 0B 08 A2
+               :     DB 95 19 5F A6 A7 B9 39 45 25 0A 0E
+
+
+
+Hoffman, Ed.                 Informational                     [Page 38]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :     F6 5E 84 E7 F8 B9 5A C9 18 C2 0E B8
+               :     A0 96 BE 81 3A 80 6D C9
+               :   }
+
+3.  Trivial Examples
+
+   This section covers examples of small CMS types.
+
+3.1.  ContentInfo with Data Type, BER
+
+   The object is a ContentInfo containing a Data object in BER format
+   that is ExContent.
+
+      0 30 NDEF: SEQUENCE {
+      2 06    9:   OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :     (PKCS #7)
+     13 A0 NDEF:   [0] {
+     15 24 NDEF:     OCTET STRING {
+     17 04    4:       OCTET STRING 'This'
+     23 04   24:       OCTET STRING ' is some sample content.'
+               :       }
+               :     }
+               :   }
+
+3.2.  ContentInfo with Data Type, DER
+
+   The object is a ContentInfo containing a Data object in DER format
+   that is ExContent.
+
+      0 30   43: SEQUENCE {
+      2 06    9:   OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :     (PKCS #7)
+     13 A0   30:   [0] {
+     15 04   28:     OCTET STRING 'This is some sample content.'
+               :     }
+               :   }
+
+4.  Signed-data
+
+4.1.  Basic Signed Content, DSS
+
+   A SignedData with no attribute certificates, signed by Alice using
+   DSS, just her certificate (not Carl's root cert), no CRL.  The
+   message is ExContent, and is included in the eContent.  There are no
+   signed or unsigned attributes.
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                     [Page 39]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+      0 30  919: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0  904:   [0] {
+     19 30  900:     SEQUENCE {
+     23 02    1:       INTEGER 1
+     26 31    9:       SET {
+     28 30    7:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+               :           }
+               :         }
+     37 30   43:       SEQUENCE {
+     39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     50 A0   30:         [0] {
+     52 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     82 A0  736:       [0] {
+     86 30  732:         SEQUENCE {
+     90 30  667:           SEQUENCE {
+     94 A0    3:             [0] {
+     96 02    1:               INTEGER 2
+               :               }
+     99 02    2:             INTEGER 200
+    103 30    9:             SEQUENCE {
+    105 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+    114 30   18:             SEQUENCE {
+    116 31   16:               SET {
+    118 30   14:                 SEQUENCE {
+    120 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    125 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    134 30   30:             SEQUENCE {
+    136 17   13:               UTCTime '990817011049Z'
+    151 17   13:               UTCTime '391231235959Z'
+               :               }
+    166 30   19:             SEQUENCE {
+    168 31   17:               SET {
+    170 30   15:                 SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 40]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    172 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    177 13    8:                   PrintableString 'AliceDSS'
+               :                   }
+               :                 }
+               :               }
+    187 30  438:             SEQUENCE {
+    191 30  299:               SEQUENCE {
+    195 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+    204 30  286:                 SEQUENCE {
+    208 02  129:                   INTEGER
+               :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :                   B5 E4 09 96 5C F3 7E 5B DB
+    340 02   21:                   INTEGER
+               :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :                   B8 37 21 2B 62 8B F7 93 CD
+    363 02  128:                   INTEGER
+               :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :                   D1 81 4A 60 39 BA 36 39
+               :                   }
+               :                 }
+    494 03  132:               BIT STRING 0 unused bits, encapsulates {
+    498 02  128:                   INTEGER
+               :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :                   16 89 28 11 23 D9 34 86 67 75 75 13
+               :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+
+
+
+Hoffman, Ed.                 Informational                     [Page 41]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+               :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :                   F2 A5 E2 F4 F2 83 E5 B8
+               :                   }
+               :               }
+    629 A3  129:             [3] {
+    632 30  127:               SEQUENCE {
+    634 30   12:                 SEQUENCE {
+    636 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    641 01    1:                   BOOLEAN TRUE
+    644 04    2:                   OCTET STRING, encapsulates {
+    646 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    648 30   14:                 SEQUENCE {
+    650 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    655 01    1:                   BOOLEAN TRUE
+    658 04    4:                   OCTET STRING, encapsulates {
+    660 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    664 30   31:                 SEQUENCE {
+    666 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    671 04   24:                   OCTET STRING, encapsulates {
+    673 30   22:                       SEQUENCE {
+    675 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                         }
+               :                       }
+               :                   }
+    697 30   29:                 SEQUENCE {
+    699 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    704 04   22:                   OCTET STRING, encapsulates {
+    706 04   20:                       OCTET STRING
+
+
+
+Hoffman, Ed.                 Informational                     [Page 42]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :                   13 01 E2 FD E3 97 FE CD
+               :                       }
+               :                   }
+    728 30   31:                 SEQUENCE {
+    730 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    735 04   24:                   OCTET STRING, encapsulates {
+    737 30   22:                       SEQUENCE {
+    739 81   20:                         [1] 'AliceDSS at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    761 30    9:           SEQUENCE {
+    763 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    772 03   48:           BIT STRING 0 unused bits, encapsulates {
+    775 30   45:               SEQUENCE {
+    777 02   20:                 INTEGER
+               :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+               :                   83 6A B5 3D 67 6B BF 45
+    799 02   21:                 INTEGER
+               :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :                   76 1D E2 10 52 5B 43 5E BD
+               :                 }
+               :               }
+               :           }
+               :         }
+    822 31   99:       SET {
+    824 30   97:         SEQUENCE {
+    826 02    1:           INTEGER 1
+    829 30   24:           SEQUENCE {
+    831 30   18:             SEQUENCE {
+    833 31   16:               SET {
+    835 30   14:                 SEQUENCE {
+    837 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    842 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 43]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    851 02    2:             INTEGER 200
+               :             }
+    855 30    7:           SEQUENCE {
+    857 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+    864 30    9:           SEQUENCE {
+    866 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    875 04   46:           OCTET STRING, encapsulates {
+    877 30   44:               SEQUENCE {
+    879 02   20:                 INTEGER
+               :                   09 91 FE EB D2 69 F5 18 B7 D7 CD 55
+               :                   F4 81 EA 2A 42 6A AD 03
+    901 02   20:                 INTEGER
+               :                   3A 07 CC C3 21 BE E1 1A 4B 7F 3E B5
+               :                   0D DB BA 1C EA BC CD 89
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+4.2.  Basic Signed Content, RSA
+
+   Same as 4.1, except using RSA signatures.  A SignedData with no
+   attribute certificates, signed by Alice using RSA, just her
+   certificate (not Carl's root cert), no CRL.  The message is
+   ExContent, and is included in the eContent.  There are no signed or
+   unsigned attributes.
+
+      0 30  850: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0  835:   [0] {
+     19 30  831:     SEQUENCE {
+     23 02    1:       INTEGER 1
+     26 31   11:       SET {
+     28 30    9:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+     37 05    0:           NULL
+               :           }
+               :         }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 44]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     39 30   43:       SEQUENCE {
+     41 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     52 A0   30:         [0] {
+     54 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     84 A0  560:       [0] {
+     88 30  556:         SEQUENCE {
+     92 30  405:           SEQUENCE {
+     96 A0    3:             [0] {
+     98 02    1:               INTEGER 2
+               :               }
+    101 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               C4 10 B3 B0
+    119 30   13:             SEQUENCE {
+    121 06    9:               OBJECT IDENTIFIER
+               :                 sha1withRSAEncryption
+               :                     (1 2 840 113549 1 1 5)
+               :                 (PKCS #1)
+    132 05    0:               NULL
+               :               }
+    134 30   18:             SEQUENCE {
+    136 31   16:               SET {
+    138 30   14:                 SEQUENCE {
+    140 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    145 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    154 30   30:             SEQUENCE {
+    156 17   13:               UTCTime '990919010847Z'
+    171 17   13:               UTCTime '391231235959Z'
+               :               }
+    186 30   19:             SEQUENCE {
+    188 31   17:               SET {
+    190 30   15:                 SEQUENCE {
+    192 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    197 13    8:                   PrintableString 'AliceRSA'
+               :                   }
+               :                 }
+               :               }
+    207 30  159:             SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 45]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    210 30   13:               SEQUENCE {
+    212 06    9:                 OBJECT IDENTIFIER
+               :                   rsaEncryption (1 2 840 113549 1 1 1)
+               :                   (PKCS #1)
+    223 05    0:                 NULL
+               :                 }
+    225 03  141:               BIT STRING 0 unused bits, encapsulates {
+    229 30  137:                   SEQUENCE {
+    232 02  129:                     INTEGER
+               :                   00 E0 89 73 39 8D D8 F5 F5 E8 87 76
+               :                   39 7F 4E B0 05 BB 53 83 DE 0F B7 AB
+               :                   DC 7D C7 75 29 0D 05 2E 6D 12 DF A6
+               :                   86 26 D4 D2 6F AA 58 29 FC 97 EC FA
+               :                   82 51 0F 30 80 BE B1 50 9E 46 44 F1
+               :                   2C BB D8 32 CF C6 68 6F 07 D9 B0 60
+               :                   AC BE EE 34 09 6A 13 F5 F7 05 05 93
+               :                   DF 5E BA 35 56 D9 61 FF 19 7F C9 81
+               :                   E6 F8 6C EA 87 40 70 EF AC 6D 2C 74
+               :                   9F 2D FA 55 3A B9 99 77 02 A6 48 52
+               :                   8C 4E F3 57 38 57 74 57 5F
+    364 02    3:                     INTEGER 65537
+               :                     }
+               :                   }
+               :               }
+    369 A3  129:             [3] {
+    372 30  127:               SEQUENCE {
+    374 30   12:                 SEQUENCE {
+    376 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    381 01    1:                   BOOLEAN TRUE
+    384 04    2:                   OCTET STRING, encapsulates {
+    386 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    388 30   14:                 SEQUENCE {
+    390 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    395 01    1:                   BOOLEAN TRUE
+    398 04    4:                   OCTET STRING, encapsulates {
+    400 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    404 30   31:                 SEQUENCE {
+    406 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 46]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                     (X.509 id-ce (2 5 29))
+    411 04   24:                   OCTET STRING, encapsulates {
+    413 30   22:                       SEQUENCE {
+    415 80   20:                         [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                         }
+               :                       }
+               :                   }
+    437 30   29:                 SEQUENCE {
+    439 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    444 04   22:                   OCTET STRING, encapsulates {
+    446 04   20:                       OCTET STRING
+               :                   77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D
+               :                   CE EC 3C A0 3A E3 FF 50
+               :                       }
+               :                   }
+    468 30   31:                 SEQUENCE {
+    470 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    475 04   24:                   OCTET STRING, encapsulates {
+    477 30   22:                       SEQUENCE {
+    479 81   20:                         [1] 'AliceRSA at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    501 30   13:           SEQUENCE {
+    503 06    9:             OBJECT IDENTIFIER
+               :               sha1withRSAEncryption
+               :                   (1 2 840 113549 1 1 5)
+               :               (PKCS #1)
+    514 05    0:             NULL
+               :             }
+    516 03  129:           BIT STRING 0 unused bits
+               :             3E 70 47 A8 48 CC 13 58 8F CA 51 71
+               :             6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC
+               :             CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C
+               :             59 A9 20 AA 05 81 A8 4E 25 AD A7 70
+               :             14 75 2F F5 C7 9B D1 0E E9 63 D2 64
+               :             B7 C6 66 6E 73 21 54 DF F4 BA 25 5D
+               :             7D 49 D3 94 6B 22 36 74 73 B8 4A EC
+               :             2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A
+
+
+
+Hoffman, Ed.                 Informational                     [Page 47]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA
+               :             F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A
+               :             76 AE EB 9B DB 49 B0 22
+               :           }
+               :         }
+    648 31  203:       SET {
+    651 30  200:         SEQUENCE {
+    654 02    1:           INTEGER 1
+    657 30   38:           SEQUENCE {
+    659 30   18:             SEQUENCE {
+    661 31   16:               SET {
+    663 30   14:                 SEQUENCE {
+    665 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    670 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    679 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               C4 10 B3 B0
+               :             }
+    697 30    9:           SEQUENCE {
+    699 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+    706 05    0:             NULL
+               :             }
+    708 30   13:           SEQUENCE {
+    710 06    9:             OBJECT IDENTIFIER
+               :               rsaEncryption (1 2 840 113549 1 1 1)
+               :               (PKCS #1)
+    721 05    0:             NULL
+               :             }
+    723 04  128:           OCTET STRING
+               :             2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E
+               :             9D BF 89 9A 81 E5 75 C4 91 3D D3 D0
+               :             D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84
+               :             F5 CD 60 4E 27 95 F6 CF 00 86 76 75
+               :             3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16
+               :             04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20
+               :             44 D5 9F 07 C5 53 24 FA CE 01 1D 0F
+               :             17 13 A7 2A 95 9D 2B E4 03 95 14 0B
+               :             E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6
+               :             55 13 D4 68 6F D0 07 D7 A2 B1 62 4C
+               :             E3 8F AF FD E0 D5 5D C7
+               :           }
+               :         }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 48]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :       }
+               :     }
+               :   }
+
+4.3.  Basic Signed Content, Detached Content
+
+   Same as 4.1, except with no eContent.  A SignedData with no attribute
+   certificates, signed by Alice using DSS, just her certificate (not
+   Carl's root cert), no CRL.  The message is ExContent, but the
+   eContent is not included.  There are no signed or unsigned
+   attributes.
+
+      0 30  887: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0  872:   [0] {
+     19 30  868:     SEQUENCE {
+     23 02    1:       INTEGER 1
+     26 31    9:       SET {
+     28 30    7:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+               :           }
+               :         }
+     37 30   11:       SEQUENCE {
+     39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+               :         }
+     50 A0  736:       [0] {
+     54 30  732:         SEQUENCE {
+     58 30  667:           SEQUENCE {
+     62 A0    3:             [0] {
+     64 02    1:               INTEGER 2
+               :               }
+     67 02    2:             INTEGER 200
+     71 30    9:             SEQUENCE {
+     73 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+     82 30   18:             SEQUENCE {
+     84 31   16:               SET {
+     86 30   14:                 SEQUENCE {
+     88 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+     93 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 49]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                 }
+               :               }
+    102 30   30:             SEQUENCE {
+    104 17   13:               UTCTime '990817011049Z'
+    119 17   13:               UTCTime '391231235959Z'
+               :               }
+    134 30   19:             SEQUENCE {
+    136 31   17:               SET {
+    138 30   15:                 SEQUENCE {
+    140 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    145 13    8:                   PrintableString 'AliceDSS'
+               :                   }
+               :                 }
+               :               }
+    155 30  438:             SEQUENCE {
+    159 30  299:               SEQUENCE {
+    163 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+    172 30  286:                 SEQUENCE {
+    176 02  129:                   INTEGER
+               :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :                   B5 E4 09 96 5C F3 7E 5B DB
+    308 02   21:                   INTEGER
+               :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :                   B8 37 21 2B 62 8B F7 93 CD
+    331 02  128:                   INTEGER
+               :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+
+
+
+Hoffman, Ed.                 Informational                     [Page 50]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   D1 81 4A 60 39 BA 36 39
+               :                   }
+               :                 }
+    462 03  132:               BIT STRING 0 unused bits, encapsulates {
+    466 02  128:                   INTEGER
+               :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :                   16 89 28 11 23 D9 34 86 67 75 75 13
+               :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+               :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+               :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :                   F2 A5 E2 F4 F2 83 E5 B8
+               :                   }
+               :               }
+    597 A3  129:             [3] {
+    600 30  127:               SEQUENCE {
+    602 30   12:                 SEQUENCE {
+    604 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    609 01    1:                   BOOLEAN TRUE
+    612 04    2:                   OCTET STRING, encapsulates {
+    614 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    616 30   14:                 SEQUENCE {
+    618 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    623 01    1:                   BOOLEAN TRUE
+    626 04    4:                   OCTET STRING, encapsulates {
+    628 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    632 30   31:                 SEQUENCE {
+    634 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    639 04   24:                   OCTET STRING, encapsulates {
+    641 30   22:                       SEQUENCE {
+    643 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+
+
+
+Hoffman, Ed.                 Informational                     [Page 51]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                         }
+               :                       }
+               :                   }
+    665 30   29:                 SEQUENCE {
+    667 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    672 04   22:                   OCTET STRING, encapsulates {
+    674 04   20:                       OCTET STRING
+               :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :                   13 01 E2 FD E3 97 FE CD
+               :                       }
+               :                   }
+    696 30   31:                 SEQUENCE {
+    698 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    703 04   24:                   OCTET STRING, encapsulates {
+    705 30   22:                       SEQUENCE {
+    707 81   20:                         [1] 'AliceDSS at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    729 30    9:           SEQUENCE {
+    731 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    740 03   48:           BIT STRING 0 unused bits, encapsulates {
+    743 30   45:               SEQUENCE {
+    745 02   20:                 INTEGER
+               :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+               :                   83 6A B5 3D 67 6B BF 45
+    767 02   21:                 INTEGER
+               :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :                   76 1D E2 10 52 5B 43 5E BD
+               :                 }
+               :               }
+               :           }
+               :         }
+    790 31   99:       SET {
+    792 30   97:         SEQUENCE {
+    794 02    1:           INTEGER 1
+    797 30   24:           SEQUENCE {
+    799 30   18:             SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 52]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    801 31   16:               SET {
+    803 30   14:                 SEQUENCE {
+    805 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    810 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    819 02    2:             INTEGER 200
+               :             }
+    823 30    7:           SEQUENCE {
+    825 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+    832 30    9:           SEQUENCE {
+    834 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    843 04   46:           OCTET STRING, encapsulates {
+    845 30   44:               SEQUENCE {
+    847 02   20:                 INTEGER
+               :                   06 FB C7 2A 24 D5 34 89 F7 8B B5 FD
+               :                   73 24 A5 86 C8 0F 5A 6C
+    869 02   20:                 INTEGER
+               :                   66 69 19 BC 68 58 D1 8D B1 9D 52 3F
+               :                   DA 14 88 0D FD C9 A1 B8
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+4.4.  Fancier Signed Content
+
+   Same as 4.1, but includes Carl's root cert, Carl's CRL, some signed
+   and unsigned attributes (Countersignature by Diane).  A SignedData
+   with no attribute certificates, signed by Alice using DSS, her
+   certificate and Carl's root cert, Carl's DSS CRL.  The message is
+   ExContent, and is included in the eContent.  The signed attributes
+   are Content Type, Message Digest and Signing Time; the unsigned
+   attributes are content hint and counter signature.  The message
+   includes also Alice's RSA certificate.
+
+
+
+
+
+Hoffman, Ed.                 Informational                     [Page 53]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+      0 30 2829: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0 2814:   [0] {
+     19 30 2810:     SEQUENCE {
+     23 02    1:       INTEGER 1
+     26 31    9:       SET {
+     28 30    7:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+               :           }
+               :         }
+     37 30   43:       SEQUENCE {
+     39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     50 A0   30:         [0] {
+     52 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     82 A0 1967:       [0] {
+     86 30  556:         SEQUENCE {
+     90 30  405:           SEQUENCE {
+     94 A0    3:             [0] {
+     96 02    1:               INTEGER 2
+               :               }
+     99 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               C4 10 B3 B0
+    117 30   13:             SEQUENCE {
+    119 06    9:               OBJECT IDENTIFIER
+               :                 sha1withRSAEncryption
+               :                     (1 2 840 113549 1 1 5)
+               :                 (PKCS #1)
+    130 05    0:               NULL
+               :               }
+    132 30   18:             SEQUENCE {
+    134 31   16:               SET {
+    136 30   14:                 SEQUENCE {
+    138 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    143 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    152 30   30:             SEQUENCE {
+    154 17   13:               UTCTime '990919010847Z'
+    169 17   13:               UTCTime '391231235959Z'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 54]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               }
+    184 30   19:             SEQUENCE {
+    186 31   17:               SET {
+    188 30   15:                 SEQUENCE {
+    190 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    195 13    8:                   PrintableString 'AliceRSA'
+               :                   }
+               :                 }
+               :               }
+    205 30  159:             SEQUENCE {
+    208 30   13:               SEQUENCE {
+    210 06    9:                 OBJECT IDENTIFIER
+               :                   rsaEncryption (1 2 840 113549 1 1 1)
+               :                   (PKCS #1)
+    221 05    0:                 NULL
+               :                 }
+    223 03  141:               BIT STRING 0 unused bits, encapsulates {
+    227 30  137:                   SEQUENCE {
+    230 02  129:                     INTEGER
+               :                   00 E0 89 73 39 8D D8 F5 F5 E8 87 76
+               :                   39 7F 4E B0 05 BB 53 83 DE 0F B7 AB
+               :                   DC 7D C7 75 29 0D 05 2E 6D 12 DF A6
+               :                   86 26 D4 D2 6F AA 58 29 FC 97 EC FA
+               :                   82 51 0F 30 80 BE B1 50 9E 46 44 F1
+               :                   2C BB D8 32 CF C6 68 6F 07 D9 B0 60
+               :                   AC BE EE 34 09 6A 13 F5 F7 05 05 93
+               :                   DF 5E BA 35 56 D9 61 FF 19 7F C9 81
+               :                   E6 F8 6C EA 87 40 70 EF AC 6D 2C 74
+               :                   9F 2D FA 55 3A B9 99 77 02 A6 48 52
+               :                   8C 4E F3 57 38 57 74 57 5F
+    362 02    3:                     INTEGER 65537
+               :                     }
+               :                   }
+               :               }
+    367 A3  129:             [3] {
+    370 30  127:               SEQUENCE {
+    372 30   12:                 SEQUENCE {
+    374 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    379 01    1:                   BOOLEAN TRUE
+    382 04    2:                   OCTET STRING, encapsulates {
+    384 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    386 30   14:                 SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 55]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    388 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    393 01    1:                   BOOLEAN TRUE
+    396 04    4:                   OCTET STRING, encapsulates {
+    398 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    402 30   31:                 SEQUENCE {
+    404 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    409 04   24:                   OCTET STRING, encapsulates {
+    411 30   22:                       SEQUENCE {
+    413 80   20:                         [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                         }
+               :                       }
+               :                   }
+    435 30   29:                 SEQUENCE {
+    437 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    442 04   22:                   OCTET STRING, encapsulates {
+    444 04   20:                       OCTET STRING
+               :                   77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D
+               :                   CE EC 3C A0 3A E3 FF 50
+               :                       }
+               :                   }
+    466 30   31:                 SEQUENCE {
+    468 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    473 04   24:                   OCTET STRING, encapsulates {
+    475 30   22:                       SEQUENCE {
+    477 81   20:                         [1] 'AliceRSA at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    499 30   13:           SEQUENCE {
+    501 06    9:             OBJECT IDENTIFIER
+               :               sha1withRSAEncryption
+               :                   (1 2 840 113549 1 1 5)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 56]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               (PKCS #1)
+    512 05    0:             NULL
+               :             }
+    514 03  129:           BIT STRING 0 unused bits
+               :             3E 70 47 A8 48 CC 13 58 8F CA 51 71
+               :             6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC
+               :             CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C
+               :             59 A9 20 AA 05 81 A8 4E 25 AD A7 70
+               :             14 75 2F F5 C7 9B D1 0E E9 63 D2 64
+               :             B7 C6 66 6E 73 21 54 DF F4 BA 25 5D
+               :             7D 49 D3 94 6B 22 36 74 73 B8 4A EC
+               :             2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A
+               :             B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA
+               :             F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A
+               :             76 AE EB 9B DB 49 B0 22
+               :           }
+    646 30  667:         SEQUENCE {
+    650 30  602:           SEQUENCE {
+    654 A0    3:             [0] {
+    656 02    1:               INTEGER 2
+               :               }
+    659 02    1:             INTEGER 1
+    662 30    9:             SEQUENCE {
+    664 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+    673 30   18:             SEQUENCE {
+    675 31   16:               SET {
+    677 30   14:                 SEQUENCE {
+    679 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    684 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    693 30   30:             SEQUENCE {
+    695 17   13:               UTCTime '990816225050Z'
+    710 17   13:               UTCTime '391231235959Z'
+               :               }
+    725 30   18:             SEQUENCE {
+    727 31   16:               SET {
+    729 30   14:                 SEQUENCE {
+    731 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    736 13    7:                   PrintableString 'CarlDSS'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 57]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   }
+               :                 }
+               :               }
+    745 30  439:             SEQUENCE {
+    749 30  299:               SEQUENCE {
+    753 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+    762 30  286:                 SEQUENCE {
+    766 02  129:                   INTEGER
+               :                   00 B6 49 18 3E 8A 44 C1 29 71 94 4C
+               :                   01 C4 12 C1 7A 79 CB 54 4D AB 1E 81
+               :                   FB C6 4C B3 0E 94 09 06 EB 01 D4 B1
+               :                   C8 71 4B C7 45 C0 50 25 5D 9C FC DA
+               :                   E4 6D D3 E2 86 48 84 82 7D BA 15 95
+               :                   4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A
+               :                   0A 8A BA 16 7B B9 50 01 48 93 8B EB
+               :                   25 15 51 97 55 DC 8F 53 0E 10 A9 50
+               :                   FC 70 B7 CD 30 54 FD DA DE A8 AA 22
+               :                   B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9
+               :                   AD E1 08 D4 6D 29 2D D6 E9
+    898 02   21:                   INTEGER
+               :                   00 DD C1 2F DF 53 CE 0B 34 60 77 3E
+               :                   02 A4 BF 8A 5D 98 B9 10 D5
+    921 02  128:                   INTEGER
+               :                   0C EE 57 9B 4B BD DA B6 07 6A 74 37
+               :                   4F 55 7F 9D ED BC 61 0D EB 46 59 3C
+               :                   56 0B 2B 5B 0C 91 CE A5 62 52 69 CA
+               :                   E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C
+               :                   AD CB AE 45 E3 06 AC 8C 22 9D 9C 44
+               :                   87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE
+               :                   AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A
+               :                   73 AA 7F 46 51 1F A9 42 16 9C 48 EB
+               :                   8A 79 61 B4 D5 2F 53 22 44 63 1F 86
+               :                   B8 A3 58 06 25 F8 29 C0 EF BA E0 75
+               :                   F0 42 C4 63 65 52 9B 0A
+               :                   }
+               :                 }
+   1052 03  133:               BIT STRING 0 unused bits, encapsulates {
+   1056 02  129:                   INTEGER
+               :                   00 99 87 74 27 03 66 A0 B1 C0 AD DC
+               :                   2C 75 BB E1 6C 44 9C DA 21 6D 4D 47
+               :                   6D B1 62 09 E9 D8 AE 1E F2 3A B4 94
+               :                   B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25
+               :                   4E B9 60 96 19 24 01 F3 62 0C FE 75
+               :                   C0 FB CE D8 68 00 E3 FD D5 70 4F DF
+               :                   23 96 19 06 94 F4 B1 61 8F 3A 57 B1
+               :                   08 11 A4 0B 26 25 F0 52 76 81 EA 0B
+
+
+
+Hoffman, Ed.                 Informational                     [Page 58]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   62 0D 95 2A E6 86 BA 72 B2 A7 50 83
+               :                   0B AA 27 CD 1B A9 4D 89 9A D7 8D 18
+               :                   39 84 3F 8B C5 56 4D 80 7A
+               :                   }
+               :               }
+   1188 A3   66:             [3] {
+   1190 30   64:               SEQUENCE {
+   1192 30   15:                 SEQUENCE {
+   1194 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+   1199 01    1:                   BOOLEAN TRUE
+   1202 04    5:                   OCTET STRING, encapsulates {
+   1204 30    3:                       SEQUENCE {
+   1206 01    1:                         BOOLEAN TRUE
+               :                         }
+               :                       }
+               :                   }
+   1209 30   14:                 SEQUENCE {
+   1211 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+   1216 01    1:                   BOOLEAN TRUE
+   1219 04    4:                   OCTET STRING, encapsulates {
+   1221 03    2:                       BIT STRING 1 unused bits
+               :                         '1100001'B
+               :                       }
+               :                   }
+   1225 30   29:                 SEQUENCE {
+   1227 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+   1232 04   22:                   OCTET STRING, encapsulates {
+   1234 04   20:                       OCTET STRING
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+   1256 30    9:           SEQUENCE {
+   1258 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   1267 03   48:           BIT STRING 0 unused bits, encapsulates {
+   1270 30   45:               SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 59]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   1272 02   20:                 INTEGER
+               :                   6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B
+               :                   C9 06 37 E9 11 17 A1 13
+   1294 02   21:                 INTEGER
+               :                   00 8F 34 69 2A 8B B1 3C 03 79 94 32
+               :                   4D 12 1F CE 89 FB 46 B2 3B
+               :                 }
+               :               }
+               :           }
+   1317 30  732:         SEQUENCE {
+   1321 30  667:           SEQUENCE {
+   1325 A0    3:             [0] {
+   1327 02    1:               INTEGER 2
+               :               }
+   1330 02    2:             INTEGER 200
+   1334 30    9:             SEQUENCE {
+   1336 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+   1345 30   18:             SEQUENCE {
+   1347 31   16:               SET {
+   1349 30   14:                 SEQUENCE {
+   1351 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   1356 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+   1365 30   30:             SEQUENCE {
+   1367 17   13:               UTCTime '990817011049Z'
+   1382 17   13:               UTCTime '391231235959Z'
+               :               }
+   1397 30   19:             SEQUENCE {
+   1399 31   17:               SET {
+   1401 30   15:                 SEQUENCE {
+   1403 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   1408 13    8:                   PrintableString 'AliceDSS'
+               :                   }
+               :                 }
+               :               }
+   1418 30  438:             SEQUENCE {
+   1422 30  299:               SEQUENCE {
+   1426 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 60]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   (ANSI X9.57 algorithm)
+   1435 30  286:                 SEQUENCE {
+   1439 02  129:                   INTEGER
+               :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :                   B5 E4 09 96 5C F3 7E 5B DB
+   1571 02   21:                   INTEGER
+               :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :                   B8 37 21 2B 62 8B F7 93 CD
+   1594 02  128:                   INTEGER
+               :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :                   D1 81 4A 60 39 BA 36 39
+               :                   }
+               :                 }
+   1725 03  132:               BIT STRING 0 unused bits, encapsulates {
+   1729 02  128:                   INTEGER
+               :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :                   16 89 28 11 23 D9 34 86 67 75 75 13
+               :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+               :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+               :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :                   F2 A5 E2 F4 F2 83 E5 B8
+               :                   }
+               :               }
+   1860 A3  129:             [3] {
+   1863 30  127:               SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 61]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   1865 30   12:                 SEQUENCE {
+   1867 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+   1872 01    1:                   BOOLEAN TRUE
+   1875 04    2:                   OCTET STRING, encapsulates {
+   1877 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+   1879 30   14:                 SEQUENCE {
+   1881 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+   1886 01    1:                   BOOLEAN TRUE
+   1889 04    4:                   OCTET STRING, encapsulates {
+   1891 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+   1895 30   31:                 SEQUENCE {
+   1897 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+   1902 04   24:                   OCTET STRING, encapsulates {
+   1904 30   22:                       SEQUENCE {
+   1906 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                         }
+               :                       }
+               :                   }
+   1928 30   29:                 SEQUENCE {
+   1930 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+   1935 04   22:                   OCTET STRING, encapsulates {
+   1937 04   20:                       OCTET STRING
+               :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :                   13 01 E2 FD E3 97 FE CD
+               :                       }
+               :                   }
+   1959 30   31:                 SEQUENCE {
+   1961 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+   1966 04   24:                   OCTET STRING, encapsulates {
+   1968 30   22:                       SEQUENCE {
+   1970 81   20:                         [1] 'AliceDSS at example.com'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 62]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+   1992 30    9:           SEQUENCE {
+   1994 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   2003 03   48:           BIT STRING 0 unused bits, encapsulates {
+   2006 30   45:               SEQUENCE {
+   2008 02   20:                 INTEGER
+               :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+               :                   83 6A B5 3D 67 6B BF 45
+   2030 02   21:                 INTEGER
+               :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :                   76 1D E2 10 52 5B 43 5E BD
+               :                 }
+               :               }
+               :           }
+               :         }
+   2053 A1  219:       [1] {
+   2056 30  216:         SEQUENCE {
+   2059 30  153:           SEQUENCE {
+   2062 30    9:             SEQUENCE {
+   2064 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+   2073 30   18:             SEQUENCE {
+   2075 31   16:               SET {
+   2077 30   14:                 SEQUENCE {
+   2079 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   2084 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+   2093 17   13:             UTCTime '990827070000Z'
+   2108 30  105:             SEQUENCE {
+   2110 30   19:               SEQUENCE {
+   2112 02    2:                 INTEGER 200
+   2116 17   13:                 UTCTime '990822070000Z'
+               :                 }
+   2131 30   19:               SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 63]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   2133 02    2:                 INTEGER 201
+   2137 17   13:                 UTCTime '990822070000Z'
+               :                 }
+   2152 30   19:               SEQUENCE {
+   2154 02    2:                 INTEGER 211
+   2158 17   13:                 UTCTime '990822070000Z'
+               :                 }
+   2173 30   19:               SEQUENCE {
+   2175 02    2:                 INTEGER 210
+   2179 17   13:                 UTCTime '990822070000Z'
+               :                 }
+   2194 30   19:               SEQUENCE {
+   2196 02    2:                 INTEGER 212
+   2200 17   13:                 UTCTime '990824070000Z'
+               :                 }
+               :               }
+               :             }
+   2215 30    9:           SEQUENCE {
+   2217 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   2226 03   47:           BIT STRING 0 unused bits, encapsulates {
+   2229 30   44:               SEQUENCE {
+   2231 02   20:                 INTEGER
+               :                   7E 65 52 76 33 FE 34 73 17 D1 F7 96
+               :                   F9 A0 D4 D8 6D 5C 7D 3D
+   2253 02   20:                 INTEGER
+               :                   02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E
+               :                   DA 24 F3 2A 83 9C 35 A1
+               :                 }
+               :               }
+               :           }
+               :         }
+   2275 31  554:       SET {
+   2279 30  550:         SEQUENCE {
+   2283 02    1:           INTEGER 1
+   2286 30   24:           SEQUENCE {
+   2288 30   18:             SEQUENCE {
+   2290 31   16:               SET {
+   2292 30   14:                 SEQUENCE {
+   2294 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   2299 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 64]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   2308 02    2:             INTEGER 200
+               :             }
+   2312 30    7:           SEQUENCE {
+   2314 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+   2321 A0   93:           [0] {
+   2323 30   24:             SEQUENCE {
+   2325 06    9:               OBJECT IDENTIFIER
+               :                 contentType (1 2 840 113549 1 9 3)
+               :                 (PKCS #9 (1 2 840 113549 1 9))
+   2336 31   11:               SET {
+   2338 06    9:                 OBJECT IDENTIFIER
+               :                   data (1 2 840 113549 1 7 1)
+               :                   (PKCS #7)
+               :                 }
+               :               }
+   2349 30   28:             SEQUENCE {
+   2351 06    9:               OBJECT IDENTIFIER
+               :                 signingTime (1 2 840 113549 1 9 5)
+               :                 (PKCS #9 (1 2 840 113549 1 9))
+   2362 31   15:               SET {
+   2364 17   13:                 UTCTime '030514153900Z'
+               :                 }
+               :               }
+   2379 30   35:             SEQUENCE {
+   2381 06    9:               OBJECT IDENTIFIER
+               :                 messageDigest (1 2 840 113549 1 9 4)
+               :                 (PKCS #9 (1 2 840 113549 1 9))
+   2392 31   22:               SET {
+   2394 04   20:                 OCTET STRING
+               :                   40 6A EC 08 52 79 BA 6E 16 02 2D 9E
+               :                   06 29 C0 22 96 87 DD 48
+               :                 }
+               :               }
+               :             }
+   2416 30    9:           SEQUENCE {
+   2418 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   2427 04   46:           OCTET STRING, encapsulates {
+   2429 30   44:               SEQUENCE {
+   2431 02   20:                 INTEGER
+               :                   3B A5 E0 4A DB 6D 58 E0 19 D1 00 1C
+               :                   4F 44 9A 57 7A 71 66 68
+   2453 02   20:                 INTEGER
+               :                   1A 11 98 D6 1F 1F AF 34 81 01 DE BE
+
+
+
+Hoffman, Ed.                 Informational                     [Page 65]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   8B DC B6 A8 6A 91 69 13
+               :                 }
+               :               }
+   2475 A1  354:           [1] {
+   2479 30   62:             SEQUENCE {
+   2481 06   11:               OBJECT IDENTIFIER
+               :                 id-aa-contentHint
+               :                     (1 2 840 113549 1 9 16 2 4)
+               :                 (S/MIME Authenticated Attributes
+               :                     (1 2 840 113549 1 9 16 2))
+   2494 31   47:               SET {
+   2496 30   45:                 SEQUENCE {
+   2498 0C   32:                   UTF8String
+               :                   'Content Hints Description Buffer'
+   2532 06    9:                   OBJECT IDENTIFIER
+               :                     data (1 2 840 113549 1 7 1)
+               :                     (PKCS #7)
+               :                   }
+               :                 }
+               :               }
+   2543 30  286:             SEQUENCE {
+   2547 06    9:               OBJECT IDENTIFIER
+               :                 countersignature (1 2 840 113549 1 9 6)
+               :                 (PKCS #9 (1 2 840 113549 1 9))
+   2558 31  271:               SET {
+   2562 30  267:                 SEQUENCE {
+   2566 02    1:                   INTEGER 1
+   2569 30   38:                   SEQUENCE {
+   2571 30   18:                     SEQUENCE {
+   2573 31   16:                       SET {
+   2575 30   14:                         SEQUENCE {
+   2577 06    3:                           OBJECT IDENTIFIER
+               :                             commonName (2 5 4 3)
+               :                             (X.520 id-at (2 5 4))
+   2582 13    7:                           PrintableString 'CarlRSA'
+               :                           }
+               :                         }
+               :                       }
+   2591 02   16:                     INTEGER
+               :                   46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :                   C4 10 B3 B0
+               :                     }
+   2609 30    7:                   SEQUENCE {
+   2611 06    5:                     OBJECT IDENTIFIER
+               :                       sha1 (1 3 14 3 2 26)
+               :                       (OIW)
+               :                     }
+   2618 A0   67:                   [0] {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 66]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+   2620 30   28:                     SEQUENCE {
+   2622 06    9:                       OBJECT IDENTIFIER
+               :                         signingTime
+               :                             (1 2 840 113549 1 9 5)
+               :                         (PKCS #9 (1 2 840 113549 1 9))
+   2633 31   15:                       SET {
+   2635 17   13:                         UTCTime '030514153900Z'
+               :                         }
+               :                       }
+   2650 30   35:                     SEQUENCE {
+   2652 06    9:                       OBJECT IDENTIFIER
+               :                         messageDigest
+               :                             (1 2 840 113549 1 9 4)
+               :                         (PKCS #9 (1 2 840 113549 1 9))
+   2663 31   22:                       SET {
+   2665 04   20:                         OCTET STRING
+               :                   02 5F 49 4E 39 98 50 85 B3 66 D3 8A
+               :                   1F 7B 9E 69 AA FB D8 33
+               :                         }
+               :                       }
+               :                     }
+   2687 30   13:                   SEQUENCE {
+   2689 06    9:                     OBJECT IDENTIFIER
+               :                       rsaEncryption
+               :                           (1 2 840 113549 1 1 1)
+               :                       (PKCS #1)
+   2700 05    0:                     NULL
+               :                     }
+   2702 04  128:                   OCTET STRING
+               :                   6D AA 20 24 ED 7A EE A5 5E 87 DD 75
+               :                   1F 2B 54 10 65 F4 CE 9B B1 2C 78 74
+               :                   BC 8B 1C 60 B5 DB 8B 03 9E 49 F2 2B
+               :                   7F 93 6E 3D 89 14 C9 E3 6B F4 F6 7D
+               :                   76 AE 3E 58 1F 9B BB BC 7C 30 19 4E
+               :                   10 F7 02 F1 8B 5B B4 DB 9A BB 93 B4
+               :                   18 D0 CC 2B C9 91 A9 AD D9 46 F8 65
+               :                   A9 E2 71 95 D0 D4 4E 1F CD 74 6F 82
+               :                   E8 37 6F 5A 3D CB C7 D4 5F C2 80 1B
+               :                   DA D3 84 40 68 5F 56 9A 62 F5 3B 0D
+               :                   6C 33 C3 ED 67 3F 43 BF
+               :                   }
+               :                 }
+               :               }
+               :             }
+               :           }
+               :         }
+               :       }
+               :     }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 67]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :   }
+
+4.5.  All RSA Signed Message
+
+   Same as 4.2, but includes Carl's RSA root cert (but no CRL).  A
+   SignedData with no attribute certificates, signed by Alice using RSA,
+   her certificate and Carl's root cert, no CRL.  The message is
+   ExContent, and is included in the eContent.  There are no signed or
+   unsigned attributes.
+
+      0 30 NDEF: SEQUENCE {
+      2 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     13 A0 NDEF:   [0] {
+     15 30 NDEF:     SEQUENCE {
+     17 02    1:       INTEGER 1
+     20 31   11:       SET {
+     22 30    9:         SEQUENCE {
+     24 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+     31 05    0:           NULL
+               :           }
+               :         }
+     33 30 NDEF:       SEQUENCE {
+     35 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     46 A0 NDEF:         [0] {
+     48 24 NDEF:           OCTET STRING {
+     50 04    4:             OCTET STRING 'This'
+     56 04   24:             OCTET STRING ' is some sample content.'
+               :             }
+               :           }
+               :         }
+     88 A0 NDEF:       [0] {
+     90 30  491:         SEQUENCE {
+     94 30  340:           SEQUENCE {
+     98 A0    3:             [0] {
+    100 02    1:               INTEGER 2
+               :               }
+    103 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               9F F2 50 20
+    121 30   13:             SEQUENCE {
+    123 06    9:               OBJECT IDENTIFIER
+               :                 sha1withRSAEncryption
+               :                     (1 2 840 113549 1 1 5)
+               :                 (PKCS #1)
+    134 05    0:               NULL
+
+
+
+Hoffman, Ed.                 Informational                     [Page 68]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               }
+    136 30   18:             SEQUENCE {
+    138 31   16:               SET {
+    140 30   14:                 SEQUENCE {
+    142 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    147 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    156 30   30:             SEQUENCE {
+    158 17   13:               UTCTime '990818070000Z'
+    173 17   13:               UTCTime '391231235959Z'
+               :               }
+    188 30   18:             SEQUENCE {
+    190 31   16:               SET {
+    192 30   14:                 SEQUENCE {
+    194 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    199 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    208 30  159:             SEQUENCE {
+    211 30   13:               SEQUENCE {
+    213 06    9:                 OBJECT IDENTIFIER
+               :                   rsaEncryption (1 2 840 113549 1 1 1)
+               :                   (PKCS #1)
+    224 05    0:                 NULL
+               :                 }
+    226 03  141:               BIT STRING 0 unused bits, encapsulates {
+    230 30  137:                   SEQUENCE {
+    233 02  129:                     INTEGER
+               :                   00 E4 4B FF 18 B8 24 57 F4 77 FF 6E
+               :                   73 7B 93 71 5C BC 33 1A 92 92 72 23
+               :                   D8 41 46 D0 CD 11 3A 04 B3 8E AF 82
+               :                   9D BD 51 1E 17 7A F2 76 2C 2B 86 39
+               :                   A7 BD D7 8D 1A 53 EC E4 00 D5 E8 EC
+               :                   A2 36 B1 ED E2 50 E2 32 09 8A 3F 9F
+               :                   99 25 8F B8 4E AB B9 7D D5 96 65 DA
+               :                   16 A0 C5 BE 0E AE 44 5B EF 5E F4 A7
+               :                   29 CB 82 DD AC 44 E9 AA 93 94 29 0E
+               :                   F8 18 D6 C8 57 5E F2 76 C4 F2 11 60
+               :                   38 B9 1B 3C 1D 97 C9 6A F1
+    365 02    3:                     INTEGER 65537
+               :                     }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 69]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   }
+               :               }
+    370 A3   66:             [3] {
+    372 30   64:               SEQUENCE {
+    374 30   15:                 SEQUENCE {
+    376 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    381 01    1:                   BOOLEAN TRUE
+    384 04    5:                   OCTET STRING, encapsulates {
+    386 30    3:                       SEQUENCE {
+    388 01    1:                         BOOLEAN TRUE
+               :                         }
+               :                       }
+               :                   }
+    391 30   14:                 SEQUENCE {
+    393 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    398 01    1:                   BOOLEAN TRUE
+    401 04    4:                   OCTET STRING, encapsulates {
+    403 03    2:                       BIT STRING 1 unused bits
+               :                         '1100001'B
+               :                       }
+               :                   }
+    407 30   29:                 SEQUENCE {
+    409 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    414 04   22:                   OCTET STRING, encapsulates {
+    416 04   20:                       OCTET STRING
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    438 30   13:           SEQUENCE {
+    440 06    9:             OBJECT IDENTIFIER
+               :               sha1withRSAEncryption
+               :                   (1 2 840 113549 1 1 5)
+               :               (PKCS #1)
+    451 05    0:             NULL
+               :             }
+    453 03  129:           BIT STRING 0 unused bits
+               :             B7 9E D4 04 D3 ED 29 E4 FF 89 89 15
+               :             2E 4C DB 0C F0 48 0F 32 61 EE C4 04
+
+
+
+Hoffman, Ed.                 Informational                     [Page 70]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             EC 12 5D 2D FF 0F 64 59 7E 0A C3 ED
+               :             18 FD E3 56 40 37 A7 07 B5 F0 38 12
+               :             61 50 ED EF DD 3F E3 0B B8 61 A5 A4
+               :             9B 3C E6 9E 9C 54 9A B6 95 D6 DA 6C
+               :             3B B5 2D 45 35 9D 49 01 76 FA B9 B9
+               :             31 F9 F9 6B 12 53 A0 F5 14 60 9B 7D
+               :             CA 3E F2 53 6B B0 37 6F AD E6 74 D7
+               :             DB FA 5A EA 14 41 63 5D CD BE C8 0E
+               :             C1 DA 6A 8D 53 34 18 02
+               :           }
+    585 30  556:         SEQUENCE {
+    589 30  405:           SEQUENCE {
+    593 A0    3:             [0] {
+    595 02    1:               INTEGER 2
+               :               }
+    598 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               C4 10 B3 B0
+    616 30   13:             SEQUENCE {
+    618 06    9:               OBJECT IDENTIFIER
+               :                 sha1withRSAEncryption
+               :                     (1 2 840 113549 1 1 5)
+               :                 (PKCS #1)
+    629 05    0:               NULL
+               :               }
+    631 30   18:             SEQUENCE {
+    633 31   16:               SET {
+    635 30   14:                 SEQUENCE {
+    637 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    642 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+    651 30   30:             SEQUENCE {
+    653 17   13:               UTCTime '990919010847Z'
+    668 17   13:               UTCTime '391231235959Z'
+               :               }
+    683 30   19:             SEQUENCE {
+    685 31   17:               SET {
+    687 30   15:                 SEQUENCE {
+    689 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    694 13    8:                   PrintableString 'AliceRSA'
+               :                   }
+               :                 }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 71]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :               }
+    704 30  159:             SEQUENCE {
+    707 30   13:               SEQUENCE {
+    709 06    9:                 OBJECT IDENTIFIER
+               :                   rsaEncryption (1 2 840 113549 1 1 1)
+               :                   (PKCS #1)
+    720 05    0:                 NULL
+               :                 }
+    722 03  141:               BIT STRING 0 unused bits, encapsulates {
+    726 30  137:                   SEQUENCE {
+    729 02  129:                     INTEGER
+               :                   00 E0 89 73 39 8D D8 F5 F5 E8 87 76
+               :                   39 7F 4E B0 05 BB 53 83 DE 0F B7 AB
+               :                   DC 7D C7 75 29 0D 05 2E 6D 12 DF A6
+               :                   86 26 D4 D2 6F AA 58 29 FC 97 EC FA
+               :                   82 51 0F 30 80 BE B1 50 9E 46 44 F1
+               :                   2C BB D8 32 CF C6 68 6F 07 D9 B0 60
+               :                   AC BE EE 34 09 6A 13 F5 F7 05 05 93
+               :                   DF 5E BA 35 56 D9 61 FF 19 7F C9 81
+               :                   E6 F8 6C EA 87 40 70 EF AC 6D 2C 74
+               :                   9F 2D FA 55 3A B9 99 77 02 A6 48 52
+               :                   8C 4E F3 57 38 57 74 57 5F
+    861 02    3:                     INTEGER 65537
+               :                     }
+               :                   }
+               :               }
+    866 A3  129:             [3] {
+    869 30  127:               SEQUENCE {
+    871 30   12:                 SEQUENCE {
+    873 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    878 01    1:                   BOOLEAN TRUE
+    881 04    2:                   OCTET STRING, encapsulates {
+    883 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    885 30   14:                 SEQUENCE {
+    887 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    892 01    1:                   BOOLEAN TRUE
+    895 04    4:                   OCTET STRING, encapsulates {
+    897 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    901 30   31:                 SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 72]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    903 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    908 04   24:                   OCTET STRING, encapsulates {
+    910 30   22:                       SEQUENCE {
+    912 80   20:                         [0]
+               :                   E9 E0 90 27 AC 78 20 7A 9A D3 4C F2
+               :                   42 37 4E 22 AE 9E 38 BB
+               :                         }
+               :                       }
+               :                   }
+    934 30   29:                 SEQUENCE {
+    936 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    941 04   22:                   OCTET STRING, encapsulates {
+    943 04   20:                       OCTET STRING
+               :                   77 D2 B4 D1 B7 4C 8A 8A A3 CE 45 9D
+               :                   CE EC 3C A0 3A E3 FF 50
+               :                       }
+               :                   }
+    965 30   31:                 SEQUENCE {
+    967 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    972 04   24:                   OCTET STRING, encapsulates {
+    974 30   22:                       SEQUENCE {
+    976 81   20:                         [1] 'AliceRSA at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    998 30   13:           SEQUENCE {
+   1000 06    9:             OBJECT IDENTIFIER
+               :               sha1withRSAEncryption
+               :                   (1 2 840 113549 1 1 5)
+               :               (PKCS #1)
+   1011 05    0:             NULL
+               :             }
+   1013 03  129:           BIT STRING 0 unused bits
+               :             3E 70 47 A8 48 CC 13 58 8F CA 51 71
+               :             6B 4E 36 18 5D 04 7E 80 B1 8D 4D CC
+               :             CA A3 8F CC 7D 56 C8 BC CF 6E B3 1C
+               :             59 A9 20 AA 05 81 A8 4E 25 AD A7 70
+               :             14 75 2F F5 C7 9B D1 0E E9 63 D2 64
+               :             B7 C6 66 6E 73 21 54 DF F4 BA 25 5D
+
+
+
+Hoffman, Ed.                 Informational                     [Page 73]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             7D 49 D3 94 6B 22 36 74 73 B8 4A EC
+               :             2F 64 ED D3 3D D2 A7 42 C5 E8 37 8A
+               :             B4 DB 9F 67 E4 BD 9F F9 FE 74 EF EA
+               :             F9 EE 63 6A D8 3F 4B 25 09 B5 D8 1A
+               :             76 AE EB 9B DB 49 B0 22
+               :           }
+               :         }
+   1147 31  203:       SET {
+   1150 30  200:         SEQUENCE {
+   1153 02    1:           INTEGER 1
+   1156 30   38:           SEQUENCE {
+   1158 30   18:             SEQUENCE {
+   1160 31   16:               SET {
+   1162 30   14:                 SEQUENCE {
+   1164 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   1169 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+   1178 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               C4 10 B3 B0
+               :             }
+   1196 30    9:           SEQUENCE {
+   1198 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+   1205 05    0:             NULL
+               :             }
+   1207 30   13:           SEQUENCE {
+   1209 06    9:             OBJECT IDENTIFIER
+               :               rsaEncryption (1 2 840 113549 1 1 1)
+               :               (PKCS #1)
+   1220 05    0:             NULL
+               :             }
+   1222 04  128:           OCTET STRING
+               :             2F 23 82 D2 F3 09 5F B8 0C 58 EB 4E
+               :             9D BF 89 9A 81 E5 75 C4 91 3D D3 D0
+               :             D5 7B B6 D5 FE 94 A1 8A AC E3 C4 84
+               :             F5 CD 60 4E 27 95 F6 CF 00 86 76 75
+               :             3F 2B F0 E7 D4 02 67 A7 F5 C7 8D 16
+               :             04 A5 B3 B5 E7 D9 32 F0 24 EF E7 20
+               :             44 D5 9F 07 C5 53 24 FA CE 01 1D 0F
+               :             17 13 A7 2A 95 9D 2B E4 03 95 14 0B
+               :             E9 39 0D BA CE 6E 9C 9E 0C E8 98 E6
+               :             55 13 D4 68 6F D0 07 D7 A2 B1 62 4C
+               :             E3 8F AF FD E0 D5 5D C7
+
+
+
+Hoffman, Ed.                 Informational                     [Page 74]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+4.6.  Multiple Signers
+
+   Similar to 4.1, but the message is also signed by Diane.  Two
+   signerInfos (one for Alice, one for Diane) with no attribute
+   certificates, each signed using DSS, Alice's and Diane's certificate
+   (not Carl's root cert), no CRL.  The message is ExContent, and is
+   included in the eContent.  There are no signed or unsigned
+   attributes.
+
+      0 30 1463: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0 1448:   [0] {
+     19 30 1444:     SEQUENCE {
+     23 02    1:       INTEGER 1
+     26 31    9:       SET {
+     28 30    7:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+               :           }
+               :         }
+     37 30   43:       SEQUENCE {
+     39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     50 A0   30:         [0] {
+     52 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     82 A0 1180:       [0] {
+     86 30  440:         SEQUENCE {
+     90 30  375:           SEQUENCE {
+     94 A0    3:             [0] {
+     96 02    1:               INTEGER 2
+               :               }
+     99 02    2:             INTEGER 210
+    103 30    9:             SEQUENCE {
+    105 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+    114 30   18:             SEQUENCE {
+    116 31   16:               SET {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 75]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    118 30   14:                 SEQUENCE {
+    120 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    125 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    134 30   30:             SEQUENCE {
+    136 17   13:               UTCTime '990817020810Z'
+    151 17   13:               UTCTime '391231235959Z'
+               :               }
+    166 30   19:             SEQUENCE {
+    168 31   17:               SET {
+    170 30   15:                 SEQUENCE {
+    172 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    177 13    8:                   PrintableString 'DianeDSS'
+               :                   }
+               :                 }
+               :               }
+    187 30  147:             SEQUENCE {
+    190 30    9:               SEQUENCE {
+    192 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+               :                 }
+    201 03  133:               BIT STRING 0 unused bits, encapsulates {
+    205 02  129:                   INTEGER
+               :                   00 A0 00 17 78 2C EE 7E 81 53 2E 2E
+               :                   61 08 0F A1 9B 51 52 1A DA 59 A8 73
+               :                   2F 12 25 B6 08 CB CA EF 2A 44 76 8A
+               :                   52 09 EA BD 05 22 D5 0F F6 FD 46 D7
+               :                   AF 99 38 09 0E 13 CB 4F 2C DD 1C 34
+               :                   F7 1C BF 25 FF 23 D3 3B 59 E7 82 97
+               :                   37 BE 31 24 D8 18 C8 F3 49 39 5B B7
+               :                   E2 E5 27 7E FC 8C 45 72 5B 7E 3E 8F
+               :                   68 4D DD 46 7A 22 BE 8E FF CC DA 39
+               :                   29 A3 39 E5 9F 43 E9 55 C9 D7 5B A6
+               :                   81 67 CC C0 AA CD 2E C5 23
+               :                   }
+               :               }
+    337 A3  129:             [3] {
+    340 30  127:               SEQUENCE {
+    342 30   12:                 SEQUENCE {
+    344 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+
+
+
+Hoffman, Ed.                 Informational                     [Page 76]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                     (X.509 id-ce (2 5 29))
+    349 01    1:                   BOOLEAN TRUE
+    352 04    2:                   OCTET STRING, encapsulates {
+    354 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    356 30   14:                 SEQUENCE {
+    358 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    363 01    1:                   BOOLEAN TRUE
+    366 04    4:                   OCTET STRING, encapsulates {
+    368 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    372 30   31:                 SEQUENCE {
+    374 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    379 04   24:                   OCTET STRING, encapsulates {
+    381 30   22:                       SEQUENCE {
+    383 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                         }
+               :                       }
+               :                   }
+    405 30   29:                 SEQUENCE {
+    407 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    412 04   22:                   OCTET STRING, encapsulates {
+    414 04   20:                       OCTET STRING
+               :                   64 30 99 7D 5C DC 45 0B 99 3A 52 2F
+               :                   16 BF 58 50 DD CE 2B 18
+               :                       }
+               :                   }
+    436 30   31:                 SEQUENCE {
+    438 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    443 04   24:                   OCTET STRING, encapsulates {
+    445 30   22:                       SEQUENCE {
+    447 81   20:                         [1] 'DianeDSS at example.com'
+               :                         }
+               :                       }
+               :                   }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 77]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                 }
+               :               }
+               :             }
+    469 30    9:           SEQUENCE {
+    471 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    480 03   48:           BIT STRING 0 unused bits, encapsulates {
+    483 30   45:               SEQUENCE {
+    485 02   21:                 INTEGER
+               :                   00 A1 1A F8 17 0E 3E 5D A8 8C F4 B6
+               :                   55 33 1E 4B E3 2C AC B9 5F
+    508 02   20:                 INTEGER
+               :                   28 4B 10 45 58 D2 1C 9D 55 35 14 18
+               :                   91 B2 3F 39 DF B5 6E D3
+               :                 }
+               :               }
+               :           }
+    530 30  732:         SEQUENCE {
+    534 30  667:           SEQUENCE {
+    538 A0    3:             [0] {
+    540 02    1:               INTEGER 2
+               :               }
+    543 02    2:             INTEGER 200
+    547 30    9:             SEQUENCE {
+    549 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+    558 30   18:             SEQUENCE {
+    560 31   16:               SET {
+    562 30   14:                 SEQUENCE {
+    564 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    569 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    578 30   30:             SEQUENCE {
+    580 17   13:               UTCTime '990817011049Z'
+    595 17   13:               UTCTime '391231235959Z'
+               :               }
+    610 30   19:             SEQUENCE {
+    612 31   17:               SET {
+    614 30   15:                 SEQUENCE {
+    616 06    3:                   OBJECT IDENTIFIER
+
+
+
+Hoffman, Ed.                 Informational                     [Page 78]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    621 13    8:                   PrintableString 'AliceDSS'
+               :                   }
+               :                 }
+               :               }
+    631 30  438:             SEQUENCE {
+    635 30  299:               SEQUENCE {
+    639 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+    648 30  286:                 SEQUENCE {
+    652 02  129:                   INTEGER
+               :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :                   B5 E4 09 96 5C F3 7E 5B DB
+    784 02   21:                   INTEGER
+               :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :                   B8 37 21 2B 62 8B F7 93 CD
+    807 02  128:                   INTEGER
+               :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :                   D1 81 4A 60 39 BA 36 39
+               :                   }
+               :                 }
+    938 03  132:               BIT STRING 0 unused bits, encapsulates {
+    942 02  128:                   INTEGER
+               :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :                   16 89 28 11 23 D9 34 86 67 75 75 13
+               :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+               :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+
+
+
+Hoffman, Ed.                 Informational                     [Page 79]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :                   F2 A5 E2 F4 F2 83 E5 B8
+               :                   }
+               :               }
+   1073 A3  129:             [3] {
+   1076 30  127:               SEQUENCE {
+   1078 30   12:                 SEQUENCE {
+   1080 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+   1085 01    1:                   BOOLEAN TRUE
+   1088 04    2:                   OCTET STRING, encapsulates {
+   1090 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+   1092 30   14:                 SEQUENCE {
+   1094 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+   1099 01    1:                   BOOLEAN TRUE
+   1102 04    4:                   OCTET STRING, encapsulates {
+   1104 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+   1108 30   31:                 SEQUENCE {
+   1110 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+   1115 04   24:                   OCTET STRING, encapsulates {
+   1117 30   22:                       SEQUENCE {
+   1119 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                         }
+               :                       }
+               :                   }
+   1141 30   29:                 SEQUENCE {
+   1143 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+   1148 04   22:                   OCTET STRING, encapsulates {
+   1150 04   20:                       OCTET STRING
+               :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+
+
+
+Hoffman, Ed.                 Informational                     [Page 80]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   13 01 E2 FD E3 97 FE CD
+               :                       }
+               :                   }
+   1172 30   31:                 SEQUENCE {
+   1174 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+   1179 04   24:                   OCTET STRING, encapsulates {
+   1181 30   22:                       SEQUENCE {
+   1183 81   20:                         [1] 'AliceDSS at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+   1205 30    9:           SEQUENCE {
+   1207 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   1216 03   48:           BIT STRING 0 unused bits, encapsulates {
+   1219 30   45:               SEQUENCE {
+   1221 02   20:                 INTEGER
+               :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+               :                   83 6A B5 3D 67 6B BF 45
+   1243 02   21:                 INTEGER
+               :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :                   76 1D E2 10 52 5B 43 5E BD
+               :                 }
+               :               }
+               :           }
+               :         }
+   1266 31  198:       SET {
+   1269 30   97:         SEQUENCE {
+   1271 02    1:           INTEGER 1
+   1274 30   24:           SEQUENCE {
+   1276 30   18:             SEQUENCE {
+   1278 31   16:               SET {
+   1280 30   14:                 SEQUENCE {
+   1282 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   1287 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+   1296 02    2:             INTEGER 200
+
+
+
+Hoffman, Ed.                 Informational                     [Page 81]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             }
+   1300 30    7:           SEQUENCE {
+   1302 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+   1309 30    9:           SEQUENCE {
+   1311 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   1320 04   46:           OCTET STRING, encapsulates {
+   1322 30   44:               SEQUENCE {
+   1324 02   20:                 INTEGER
+               :                   48 24 DE 8B 85 F2 16 AF EC 82 61 A9
+               :                   54 D0 2D 04 A1 CC 5A 4F
+   1346 02   20:                 INTEGER
+               :                   17 ED D5 77 02 EE 75 13 D8 10 BD 3D
+               :                   97 17 20 88 BB FD 7B 81
+               :                 }
+               :               }
+               :           }
+   1368 30   97:         SEQUENCE {
+   1370 02    1:           INTEGER 1
+   1373 30   24:           SEQUENCE {
+   1375 30   18:             SEQUENCE {
+   1377 31   16:               SET {
+   1379 30   14:                 SEQUENCE {
+   1381 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+   1386 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+   1395 02    2:             INTEGER 210
+               :             }
+   1399 30    7:           SEQUENCE {
+   1401 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+   1408 30    9:           SEQUENCE {
+   1410 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+   1419 04   46:           OCTET STRING, encapsulates {
+   1421 30   44:               SEQUENCE {
+   1423 02   20:                 INTEGER
+
+
+
+Hoffman, Ed.                 Informational                     [Page 82]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   15 FF 81 4D 8C AD 80 4E 9B 35 58 04
+               :                   37 6E 63 6E E9 5B 83 FA
+   1445 02   20:                 INTEGER
+               :                   06 7E 58 4E 2B 31 84 41 ED 49 79 38
+               :                   3E 77 D2 A6 8C 75 08 21
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+4.7.  Signing Using SKI
+
+   Same as 4.1, but the signature uses the SKI instead of the
+   issuer/serial number in the cert.  A SignedData with no attribute
+   certificates, signed by Alice using DSS, just her certificate (not
+   Carl's root cert), identified by the SKI, no CRL.  The message is
+   ExContent, and is included in the eContent.  There are no signed or
+   unsigned attributes.
+
+      0 30  915: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+               :     (PKCS #7)
+     15 A0  900:   [0] {
+     19 30  896:     SEQUENCE {
+     23 02    1:       INTEGER 3
+     26 31    9:       SET {
+     28 30    7:         SEQUENCE {
+     30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :             (OIW)
+               :           }
+               :         }
+     37 30   43:       SEQUENCE {
+     39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     50 A0   30:         [0] {
+     52 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     82 A0  736:       [0] {
+     86 30  732:         SEQUENCE {
+     90 30  667:           SEQUENCE {
+     94 A0    3:             [0] {
+     96 02    1:               INTEGER 2
+               :               }
+     99 02    2:             INTEGER 200
+
+
+
+Hoffman, Ed.                 Informational                     [Page 83]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    103 30    9:             SEQUENCE {
+    105 06    7:               OBJECT IDENTIFIER
+               :                 dsaWithSha1 (1 2 840 10040 4 3)
+               :                 (ANSI X9.57 algorithm)
+               :               }
+    114 30   18:             SEQUENCE {
+    116 31   16:               SET {
+    118 30   14:                 SEQUENCE {
+    120 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    125 13    7:                   PrintableString 'CarlDSS'
+               :                   }
+               :                 }
+               :               }
+    134 30   30:             SEQUENCE {
+    136 17   13:               UTCTime '990817011049Z'
+    151 17   13:               UTCTime '391231235959Z'
+               :               }
+    166 30   19:             SEQUENCE {
+    168 31   17:               SET {
+    170 30   15:                 SEQUENCE {
+    172 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+    177 13    8:                   PrintableString 'AliceDSS'
+               :                   }
+               :                 }
+               :               }
+    187 30  438:             SEQUENCE {
+    191 30  299:               SEQUENCE {
+    195 06    7:                 OBJECT IDENTIFIER
+               :                   dsa (1 2 840 10040 4 1)
+               :                   (ANSI X9.57 algorithm)
+    204 30  286:                 SEQUENCE {
+    208 02  129:                   INTEGER
+               :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+               :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+               :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+               :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+               :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+               :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+               :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+               :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+               :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+               :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+               :                   B5 E4 09 96 5C F3 7E 5B DB
+    340 02   21:                   INTEGER
+
+
+
+Hoffman, Ed.                 Informational                     [Page 84]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+               :                   B8 37 21 2B 62 8B F7 93 CD
+    363 02  128:                   INTEGER
+               :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+               :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+               :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+               :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+               :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+               :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+               :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+               :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+               :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+               :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+               :                   D1 81 4A 60 39 BA 36 39
+               :                   }
+               :                 }
+    494 03  132:               BIT STRING 0 unused bits, encapsulates {
+    498 02  128:                   INTEGER
+               :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+               :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+               :                   16 89 28 11 23 D9 34 86 67 75 75 13
+               :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+               :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+               :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+               :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+               :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+               :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+               :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+               :                   F2 A5 E2 F4 F2 83 E5 B8
+               :                   }
+               :               }
+    629 A3  129:             [3] {
+    632 30  127:               SEQUENCE {
+    634 30   12:                 SEQUENCE {
+    636 06    3:                   OBJECT IDENTIFIER
+               :                     basicConstraints (2 5 29 19)
+               :                     (X.509 id-ce (2 5 29))
+    641 01    1:                   BOOLEAN TRUE
+    644 04    2:                   OCTET STRING, encapsulates {
+    646 30    0:                       SEQUENCE {}
+               :                       }
+               :                   }
+    648 30   14:                 SEQUENCE {
+    650 06    3:                   OBJECT IDENTIFIER
+               :                     keyUsage (2 5 29 15)
+               :                     (X.509 id-ce (2 5 29))
+    655 01    1:                   BOOLEAN TRUE
+    658 04    4:                   OCTET STRING, encapsulates {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 85]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    660 03    2:                       BIT STRING 6 unused bits
+               :                         '11'B
+               :                       }
+               :                   }
+    664 30   31:                 SEQUENCE {
+    666 06    3:                   OBJECT IDENTIFIER
+               :                     authorityKeyIdentifier (2 5 29 35)
+               :                     (X.509 id-ce (2 5 29))
+    671 04   24:                   OCTET STRING, encapsulates {
+    673 30   22:                       SEQUENCE {
+    675 80   20:                         [0]
+               :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+               :                   3D 20 BC 43 2B 93 F1 1F
+               :                         }
+               :                       }
+               :                   }
+    697 30   29:                 SEQUENCE {
+    699 06    3:                   OBJECT IDENTIFIER
+               :                     subjectKeyIdentifier (2 5 29 14)
+               :                     (X.509 id-ce (2 5 29))
+    704 04   22:                   OCTET STRING, encapsulates {
+    706 04   20:                       OCTET STRING
+               :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :                   13 01 E2 FD E3 97 FE CD
+               :                       }
+               :                   }
+    728 30   31:                 SEQUENCE {
+    730 06    3:                   OBJECT IDENTIFIER
+               :                     subjectAltName (2 5 29 17)
+               :                     (X.509 id-ce (2 5 29))
+    735 04   24:                   OCTET STRING, encapsulates {
+    737 30   22:                       SEQUENCE {
+    739 81   20:                         [1] 'AliceDSS at example.com'
+               :                         }
+               :                       }
+               :                   }
+               :                 }
+               :               }
+               :             }
+    761 30    9:           SEQUENCE {
+    763 06    7:             OBJECT IDENTIFIER
+               :               dsaWithSha1 (1 2 840 10040 4 3)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    772 03   48:           BIT STRING 0 unused bits, encapsulates {
+    775 30   45:               SEQUENCE {
+    777 02   20:                 INTEGER
+               :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+
+
+
+Hoffman, Ed.                 Informational                     [Page 86]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :                   83 6A B5 3D 67 6B BF 45
+    799 02   21:                 INTEGER
+               :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+               :                   76 1D E2 10 52 5B 43 5E BD
+               :                 }
+               :               }
+               :           }
+               :         }
+    822 31   95:       SET {
+    824 30   93:         SEQUENCE {
+    826 02    1:           INTEGER 3
+    829 80   20:           [0]
+               :             BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+               :             13 01 E2 FD E3 97 FE CD
+    851 30    7:           SEQUENCE {
+    853 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :               (OIW)
+               :             }
+    860 30    9:           SEQUENCE {
+    862 06    7:             OBJECT IDENTIFIER dsa (1 2 840 10040 4 1)
+               :               (ANSI X9.57 algorithm)
+               :             }
+    871 04   46:           OCTET STRING, encapsulates {
+    873 30   44:               SEQUENCE {
+    875 02   20:                 INTEGER
+               :                   6D 8E 5A CD 28 A0 1F D9 86 AD 7A E9
+               :                   DF AC D7 BE EC BE 3F F8
+    897 02   20:                 INTEGER
+               :                   7C 8A 06 1E FC A4 41 35 7E F7 24 14
+               :                   FD 3D C0 56 B7 05 27 D5
+               :                 }
+               :               }
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+4.8.  S/MIME multipart/signed Message
+
+   A full S/MIME message, including MIME, that includes the body part
+   from 4.3 and the body containing the content of the message.
+
+MIME-Version: 1.0
+To: User2 at examples.com
+From: aliceDss at examples.com
+Subject: Example 4.8
+Message-Id: <020906002550300.249 at examples.com>
+
+
+
+Hoffman, Ed.                 Informational                     [Page 87]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+Date: Fri, 06 Sep 2002 00:25:21 -0300
+Content-Type: multipart/signed;
+    micalg=SHA1;
+    boundary="----=_NextBoundry____Fri,_06_Sep_2002_00:25:21";
+    protocol="application/pkcs7-signature"
+
+This is a multi-part message in MIME format.
+
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21
+
+This is some sample content.
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21
+Content-Type: application/pkcs7-signature; name=smime.p7s
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7s
+
+MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGgggL
+gMIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT
+k5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2M
+IIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lOFz
+SH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iLVPE
+/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRWa4E8
+baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1nizaoFP
+VjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8bUmJEYk2
+RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuVp1FJYLqXr
+d4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41bY8i7RaWgSu
+OF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxDKE8H5BQP1Gp
+2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwHwYDVR0j
+BBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfftQ3CkzhMB4v3
+jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM44BAMDMAAwLQ
+IUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0NevTFjMGECAQEwG
+DASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjOOAQDBC4wLAIUM/mG
+f6gkgp9Z0XtRdGimJeB/BxUCFGFFJqwYRt1WYcIOQoGiaowqGzVI
+
+------=_NextBoundry____Fri,_06_Sep_2002_00:25:21--
+
+4.9.  S/MIME application/pkcs7-mime Signed Message
+
+   A full S/MIME message, including the MIME parts.
+
+MIME-Version: 1.0
+To: User2 at examples.com
+From: aliceDss at examples.com
+Subject: Example 4.9
+Message-Id: <021031164540300.304 at examples.com>
+Date: Thu, 31 Oct 2002 16:45:14 -0300
+Content-Type: application/pkcs7-mime; smime-type=signed-data;
+    name=smime.p7m
+
+
+
+Hoffman, Ed.                 Informational                     [Page 88]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7m
+
+MIIDmQYJKoZIhvcNAQcCoIIDijCCA4YCAQExCTAHBgUrDgMCGjAtBgkqhkiG9w0BBwGgIAQ
+eDQpUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIIC4DCCAtwwggKboAMCAQICAgDIMA
+kGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUzAeFw05OTA4MTcwMTEwNDlaFw0zOTEyM
+zEyMzU5NTlaMBMxETAPBgNVBAMTCEFsaWNlRFNTMIIBtjCCASsGByqGSM44BAEwggEeAoGB
+AIGNze2D6gqeOT7CSCij5EeT3Q7XqA7sU8WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg
+23j+bv7dM3F9piuR10DcMkQiVm96nXvn89J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dh
+DEeL3/nbCElzfy5FEbteQJllzzflvbAhUA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUi
+TKqOfs+bdlLWWpMdiM5BAI1XPLLGjDDHlBd3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oI
+Xks+kPht6pzJIYo7dhTpzi5dowfNI4W4LzABfG1JiRGJNkS9+MiVSlNWteL5c+waYTYfEX/
+Cve3RUP+YdMLRgUpgObo2OQOBhAACgYBc47ladRSWC6l63eM/qeysXty9txMRNKYWiSgRI9
+k0hmd1dRMSPUNbb+VRv/qJ8qIbPiR9PQeNW2PIu0WloErjhdbOBoA/6CN+GvIkq1MauCcNH
+u8Iv2YUgFxirGX6FYvxuzTU0pY39mFHssQyhPB+QUD9RqdjTjPypeL08oPluKOBgTB/MAwG
+A1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFHBEPoIub4feStN14z0
+gvEMrk/EfMB0GA1UdDgQWBBS+bKGz48H37UNwpM4TAeL945f+zTAfBgNVHREEGDAWgRRBbG
+ljZURTU0BleGFtcGxlLmNvbTAJBgcqhkjOOAQDAzAAMC0CFFUMpBkfQiuJcSIzjYNqtT1na
+79FAhUAn2FTUlQLXLLd2ud2HeIQUltDXr0xYzBhAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERT
+UwICAMgwBwYFKw4DAhowCQYHKoZIzjgEAwQuMCwCFD1cSW6LIUFzeXle3YI5SKSBer/sAhQ
+mCq7s/CTFHOEjgASeUjbMpx5g6A==
+
+4.10.  SignedData with Attributes
+
+   A SignedData message with the following list of signedAttributes:
+
+   -unknown OID
+   -contentHints
+   -smimeCapablilties
+   -securityLabel
+   -ContentReference
+   -smimeEncryptKeyPreference
+   -mlExpansionHistory
+   -EquivalentLabel
+
+   0 30 2047: SEQUENCE {
+   4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+            :     (PKCS #7)
+  15 A0 2032:   [0] {
+  19 30 2028:     SEQUENCE {
+  23 02    1:       INTEGER 1
+  26 31    9:       SET {
+  28 30    7:         SEQUENCE {
+  30 06    5:           OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+            :             (OIW)
+            :           }
+            :         }
+  37 30   43:       SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 89]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+  39 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+            :           (PKCS #7)
+  50 A0   30:         [0] {
+  52 04   28:           OCTET STRING 'This is some sample content.'
+            :           }
+            :         }
+  82 A0  736:       [0] {
+  86 30  732:         SEQUENCE {
+  90 30  667:           SEQUENCE {
+  94 A0    3:             [0] {
+  96 02    1:               INTEGER 2
+            :               }
+  99 02    2:             INTEGER 200
+ 103 30    9:             SEQUENCE {
+ 105 06    7:               OBJECT IDENTIFIER
+            :                 dsaWithSha1 (1 2 840 10040 4 3)
+            :                 (ANSI X9.57 algorithm)
+            :               }
+ 114 30   18:             SEQUENCE {
+ 116 31   16:               SET {
+ 118 30   14:                 SEQUENCE {
+ 120 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 125 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+            :               }
+ 134 30   30:             SEQUENCE {
+ 136 17   13:               UTCTime '990817011049Z'
+ 151 17   13:               UTCTime '391231235959Z'
+            :               }
+ 166 30   19:             SEQUENCE {
+ 168 31   17:               SET {
+ 170 30   15:                 SEQUENCE {
+ 172 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 177 13    8:                   PrintableString 'AliceDSS'
+            :                   }
+            :                 }
+            :               }
+ 187 30  438:             SEQUENCE {
+ 191 30  299:               SEQUENCE {
+ 195 06    7:                 OBJECT IDENTIFIER
+            :                   dsa (1 2 840 10040 4 1)
+            :                   (ANSI X9.57 algorithm)
+ 204 30  286:                 SEQUENCE {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 90]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+ 208 02  129:                   INTEGER
+            :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+            :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+            :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+            :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+            :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+            :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+            :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+            :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+            :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+            :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+            :                   B5 E4 09 96 5C F3 7E 5B DB
+ 340 02   21:                   INTEGER
+            :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+            :                   B8 37 21 2B 62 8B F7 93 CD
+ 363 02  128:                   INTEGER
+            :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+            :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+            :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+            :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+            :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+            :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+            :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+            :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+            :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+            :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+            :                   D1 81 4A 60 39 BA 36 39
+            :                   }
+            :                 }
+ 494 03  132:               BIT STRING 0 unused bits, encapsulates {
+ 498 02  128:                   INTEGER
+            :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+            :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+            :                   16 89 28 11 23 D9 34 86 67 75 75 13
+            :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+            :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+            :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+            :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+            :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+            :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+            :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+            :                   F2 A5 E2 F4 F2 83 E5 B8
+            :                   }
+            :               }
+ 629 A3  129:             [3] {
+ 632 30  127:               SEQUENCE {
+ 634 30   12:                 SEQUENCE {
+ 636 06    3:                   OBJECT IDENTIFIER
+
+
+
+Hoffman, Ed.                 Informational                     [Page 91]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                     basicConstraints (2 5 29 19)
+            :                     (X.509 id-ce (2 5 29))
+ 641 01    1:                   BOOLEAN TRUE
+ 644 04    2:                   OCTET STRING, encapsulates {
+ 646 30    0:                       SEQUENCE {}
+            :                       }
+            :                   }
+ 648 30   14:                 SEQUENCE {
+ 650 06    3:                   OBJECT IDENTIFIER
+            :                     keyUsage (2 5 29 15)
+            :                     (X.509 id-ce (2 5 29))
+ 655 01    1:                   BOOLEAN TRUE
+ 658 04    4:                   OCTET STRING, encapsulates {
+ 660 03    2:                       BIT STRING 6 unused bits
+            :                         '11'B
+            :                       }
+            :                   }
+ 664 30   31:                 SEQUENCE {
+ 666 06    3:                   OBJECT IDENTIFIER
+            :                     authorityKeyIdentifier (2 5 29 35)
+            :                     (X.509 id-ce (2 5 29))
+ 671 04   24:                   OCTET STRING, encapsulates {
+ 673 30   22:                       SEQUENCE {
+ 675 80   20:                         [0]
+            :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+            :                   3D 20 BC 43 2B 93 F1 1F
+            :                         }
+            :                       }
+            :                   }
+ 697 30   29:                 SEQUENCE {
+ 699 06    3:                   OBJECT IDENTIFIER
+            :                     subjectKeyIdentifier (2 5 29 14)
+            :                     (X.509 id-ce (2 5 29))
+ 704 04   22:                   OCTET STRING, encapsulates {
+ 706 04   20:                       OCTET STRING
+            :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+            :                   13 01 E2 FD E3 97 FE CD
+            :                       }
+            :                   }
+ 728 30   31:                 SEQUENCE {
+ 730 06    3:                   OBJECT IDENTIFIER
+            :                     subjectAltName (2 5 29 17)
+            :                     (X.509 id-ce (2 5 29))
+ 735 04   24:                   OCTET STRING, encapsulates {
+ 737 30   22:                       SEQUENCE {
+ 739 81   20:                         [1] 'AliceDSS at example.com'
+            :                         }
+            :                       }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 92]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                   }
+            :                 }
+            :               }
+            :             }
+ 761 30    9:           SEQUENCE {
+ 763 06    7:             OBJECT IDENTIFIER
+            :               dsaWithSha1 (1 2 840 10040 4 3)
+            :               (ANSI X9.57 algorithm)
+            :             }
+ 772 03   48:           BIT STRING 0 unused bits, encapsulates {
+ 775 30   45:               SEQUENCE {
+ 777 02   20:                 INTEGER
+            :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+            :                   83 6A B5 3D 67 6B BF 45
+ 799 02   21:                 INTEGER
+            :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+            :                   76 1D E2 10 52 5B 43 5E BD
+            :                 }
+            :               }
+            :           }
+            :         }
+ 822 31 1225:       SET {
+ 826 30 1221:         SEQUENCE {
+ 830 02    1:           INTEGER 1
+ 833 30   24:           SEQUENCE {
+ 835 30   18:             SEQUENCE {
+ 837 31   16:               SET {
+ 839 30   14:                 SEQUENCE {
+ 841 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 846 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+            :               }
+ 855 02    2:             INTEGER 200
+            :             }
+ 859 30    7:           SEQUENCE {
+ 861 06    5:             OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+            :               (OIW)
+            :             }
+ 868 A0 1119:           [0] {
+ 872 30   24:             SEQUENCE {
+ 874 06    9:               OBJECT IDENTIFIER
+            :                 contentType (1 2 840 113549 1 9 3)
+            :                 (PKCS #9 (1 2 840 113549 1 9))
+ 885 31   11:               SET {
+ 887 06    9:                 OBJECT IDENTIFIER
+
+
+
+Hoffman, Ed.                 Informational                     [Page 93]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                   data (1 2 840 113549 1 7 1)
+            :                   (PKCS #7)
+            :                 }
+            :               }
+ 898 30   35:             SEQUENCE {
+ 900 06    9:               OBJECT IDENTIFIER
+            :                 messageDigest (1 2 840 113549 1 9 4)
+            :                 (PKCS #9 (1 2 840 113549 1 9))
+ 911 31   22:               SET {
+ 913 04   20:                 OCTET STRING
+            :                   40 6A EC 08 52 79 BA 6E 16 02 2D 9E
+            :                   06 29 C0 22 96 87 DD 48
+            :                 }
+            :               }
+ 935 30   56:             SEQUENCE {
+ 937 06    3:               OBJECT IDENTIFIER '1 2 5555'
+ 942 31   49:               SET {
+ 944 04   47:                 OCTET STRING
+            :                   'This is a test General ASN Attribut'
+            :                   'e, number 1.'
+            :                 }
+            :               }
+ 993 30   62:             SEQUENCE {
+ 995 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-contentHint
+            :                     (1 2 840 113549 1 9 16 2 4)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1008 31   47:               SET {
+1010 30   45:                 SEQUENCE {
+1012 0C   32:                   UTF8String
+            :                   'Content Hints Description Buffer'
+1046 06    9:                   OBJECT IDENTIFIER
+            :                     data (1 2 840 113549 1 7 1)
+            :                     (PKCS #7)
+            :                   }
+            :                 }
+            :               }
+1057 30   74:             SEQUENCE {
+1059 06    9:               OBJECT IDENTIFIER
+            :                 sMIMECapabilities
+            :                     (1 2 840 113549 1 9 15)
+            :                 (PKCS #9
+            :                     (1 2 840 113549 1 9))
+1070 31   61:               SET {
+1072 30   59:                 SEQUENCE {
+1074 30    7:                   SEQUENCE {
+1076 06    5:                     OBJECT IDENTIFIER '1 2 3 4 5 6'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 94]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                     }
+1083 30   48:                   SEQUENCE {
+1085 06    6:                     OBJECT IDENTIFIER '1 2 3 4 5 6 77'
+1093 04   38:                     OCTET STRING
+            :                   'Smime Capabilities parameters buffe'
+            :                   'r 2'
+            :                     }
+            :                   }
+            :                 }
+            :               }
+1133 30  109:             SEQUENCE {
+1135 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-securityLabel
+            :                     (1 2 840 113549 1 9 16 2 2)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1148 31   94:               SET {
+1150 31   92:                 SET {
+1152 02    1:                   INTEGER 1
+1155 06    7:                   OBJECT IDENTIFIER '1 2 3 4 5 6 7 8'
+1164 13   27:                   PrintableString
+            :                   'THIS IS A PRIVACY MARK TEST'
+1193 31   49:                   SET {
+1195 30   47:                     SEQUENCE {
+1197 80    8:                       [0]
+            :                   2A 03 04 05 06 07 86 78
+1207 A1   35:                       [1] {
+1209 13   33:                         PrintableString
+            :                         'THIS IS A TEST SECURITY-'
+            :                         'CATEGORY.'
+            :                         }
+            :                       }
+            :                     }
+            :                   }
+            :                 }
+            :               }
+1244 30  111:             SEQUENCE {
+1246 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-contentReference
+            :                     (1 2 840 113549 1 9 16 2 10)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1259 31   96:               SET {
+1261 30   94:                 SEQUENCE {
+1263 06    5:                   OBJECT IDENTIFIER '1 2 3 4 5 6'
+1270 04   43:                   OCTET STRING
+            :                   'Content Reference Content Identifie'
+            :                   'r Buffer'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 95]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+1315 04   40:                   OCTET STRING
+            :                   'Content Reference Signature Value B'
+            :                   'uffer'
+            :                   }
+            :                 }
+            :               }
+1357 30  115:             SEQUENCE {
+1359 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-encrypKeyPref
+            :                     (1 2 840 113549 1 9 16 2 11)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1372 31  100:               SET {
+1374 A0   98:                 [0] {
+1376 30   90:                   SEQUENCE {
+1378 31   11:                     SET {
+1380 30    9:                       SEQUENCE {
+1382 06    3:                         OBJECT IDENTIFIER
+            :                           countryName (2 5 4 6)
+            :                           (X.520 id-at (2 5 4))
+1387 13    2:                         PrintableString 'US'
+            :                         }
+            :                       }
+1391 31   22:                     SET {
+1393 30   20:                       SEQUENCE {
+1395 06    3:                         OBJECT IDENTIFIER
+            :                           organizationName (2 5 4 10)
+            :                           (X.520 id-at (2 5 4))
+1400 13   13:                         PrintableString 'US Government'
+            :                         }
+            :                       }
+1415 31   17:                     SET {
+1417 30   15:                       SEQUENCE {
+1419 06    3:                         OBJECT IDENTIFIER
+            :                           organizationalUnitName
+            :                               (2 5 4 11)
+            :                           (X.520 id-at (2 5 4))
+1424 13    8:                         PrintableString 'VDA Site'
+            :                         }
+            :                       }
+1434 31   12:                     SET {
+1436 30   10:                       SEQUENCE {
+1438 06    3:                         OBJECT IDENTIFIER
+            :                           organizationalUnitName
+            :                               (2 5 4 11)
+            :                           (X.520 id-at (2 5 4))
+1443 13    3:                         PrintableString 'VDA'
+            :                         }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 96]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                       }
+1448 31   18:                     SET {
+1450 30   16:                       SEQUENCE {
+1452 06    3:                         OBJECT IDENTIFIER
+            :                           commonName (2 5 4 3)
+            :                           (X.520 id-at (2 5 4))
+1457 13    9:                         PrintableString 'Daisy RSA'
+            :                         }
+            :                       }
+            :                     }
+1468 02    4:                   INTEGER 173360179
+            :                   }
+            :                 }
+            :               }
+1474 30  252:             SEQUENCE {
+1477 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-mlExpandHistory
+            :                     (1 2 840 113549 1 9 16 2 3)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1490 31  236:               SET {
+1493 30  233:                 SEQUENCE {
+1496 30  230:                   SEQUENCE {
+1499 04    7:                     OCTET STRING '5738299'
+1508 18   15:                     GeneralizedTime '19990311104433Z'
+1525 A1  201:                     [1] {
+1528 30  198:                       SEQUENCE {
+1531 A4   97:                         [4] {
+1533 30   95:                           SEQUENCE {
+1535 31   11:                             SET {
+1537 30    9:                               SEQUENCE {
+1539 06    3:                                 OBJECT IDENTIFIER
+            :                                   countryName (2 5 4 6)
+            :                                   (X.520 id-at (2 5 4))
+1544 13    2:                                 PrintableString 'US'
+            :                                 }
+            :                               }
+1548 31   22:                             SET {
+1550 30   20:                               SEQUENCE {
+1552 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationName
+            :                                       (2 5 4 10)
+            :                                   (X.520 id-at (2 5 4))
+1557 13   13:                                 PrintableString
+            :                                 'US Government'
+            :                                 }
+            :                               }
+1572 31   17:                             SET {
+
+
+
+Hoffman, Ed.                 Informational                     [Page 97]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+1574 30   15:                               SEQUENCE {
+1576 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationalUnitName
+            :                                       (2 5 4 11)
+            :                                   (X.520 id-at (2 5 4))
+1581 13    8:                                 PrintableString
+            :                                 'VDA Site'
+            :                                 }
+            :                               }
+1591 31   12:                             SET {
+1593 30   10:                               SEQUENCE {
+1595 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationalUnitName
+            :                                       (2 5 4 11)
+            :                                   (X.520 id-at (2 5 4))
+1600 13    3:                                 PrintableString 'VDA'
+            :                                 }
+            :                               }
+1605 31   23:                             SET {
+1607 30   21:                               SEQUENCE {
+1609 06    3:                                 OBJECT IDENTIFIER
+            :                                   commonName (2 5 4 3)
+            :                                   (X.520 id-at (2 5 4))
+1614 13   14:                                 PrintableString
+            :                                 'Bugs Bunny DSA'
+            :                                 }
+            :                               }
+            :                             }
+            :                           }
+1630 A4   97:                         [4] {
+1632 30   95:                           SEQUENCE {
+1634 31   11:                             SET {
+1636 30    9:                               SEQUENCE {
+1638 06    3:                                 OBJECT IDENTIFIER
+            :                                   countryName (2 5 4 6)
+            :                                   (X.520 id-at (2 5 4))
+1643 13    2:                                 PrintableString 'US'
+            :                                 }
+            :                               }
+1647 31   22:                             SET {
+1649 30   20:                               SEQUENCE {
+1651 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationName
+            :                                       (2 5 4 10)
+            :                                   (X.520 id-at (2 5 4))
+1656 13   13:                                 PrintableString
+            :                                 'US Government'
+            :                                 }
+
+
+
+Hoffman, Ed.                 Informational                     [Page 98]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                               }
+1671 31   17:                             SET {
+1673 30   15:                               SEQUENCE {
+1675 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationalUnitName
+            :                                       (2 5 4 11)
+            :                                   (X.520 id-at (2 5 4))
+1680 13    8:                                 PrintableString
+            :                                 'VDA Site'
+            :                                 }
+            :                               }
+1690 31   12:                             SET {
+1692 30   10:                               SEQUENCE {
+1694 06    3:                                 OBJECT IDENTIFIER
+            :                                   organizationalUnitName
+            :                                       (2 5 4 11)
+            :                                   (X.520 id-at (2 5 4))
+1699 13    3:                                 PrintableString 'VDA'
+            :                                 }
+            :                               }
+1704 31   23:                             SET {
+1706 30   21:                               SEQUENCE {
+1708 06    3:                                 OBJECT IDENTIFIER
+            :                                   commonName (2 5 4 3)
+            :                                   (X.520 id-at (2 5 4))
+1713 13   14:                                 PrintableString
+            :                                 'Elmer Fudd DSA'
+            :                                 }
+            :                               }
+            :                             }
+            :                           }
+            :                         }
+            :                       }
+            :                     }
+            :                   }
+            :                 }
+            :               }
+1729 30  258:             SEQUENCE {
+1733 06   11:               OBJECT IDENTIFIER
+            :                 id-aa-equivalentLabels
+            :                     (1 2 840 113549 1 9 16 2 9)
+            :                 (S/MIME Authenticated Attributes
+            :                     (1 2 840 113549 1 9 16 2))
+1746 31  242:               SET {
+1749 30  239:                 SEQUENCE {
+1752 31  114:                   SET {
+1754 02    1:                     INTEGER 1
+1757 06    7:                     OBJECT IDENTIFIER '1 2 3 4 5 6 7 9'
+
+
+
+Hoffman, Ed.                 Informational                     [Page 99]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+1766 13   38:                     PrintableString
+            :                   'EQUIVALENT THIS IS A PRIVACY MARK T'
+            :                   'EST'
+1806 31   60:                     SET {
+1808 30   58:                       SEQUENCE {
+1810 80    8:                         [0]
+            :                   2A 03 04 05 06 07 86 78
+1820 A1   46:                         [1] {
+1822 13   44:                           PrintableString
+            :                   'EQUIVALENT THIS IS A TEST SECURITY-'
+            :                   'CATEGORY.'
+            :                           }
+            :                         }
+            :                       }
+            :                     }
+1868 31  121:                   SET {
+1870 02    1:                     INTEGER 1
+1873 06    7:                     OBJECT IDENTIFIER
+            :                     '1 2 3 4 5 6 7 10'
+1882 13   45:                     PrintableString
+            :                   'EQUIVALENT THIS IS A SECOND PRIVACY'
+            :                   ' MARK TEST'
+1929 31   60:                     SET {
+1931 30   58:                       SEQUENCE {
+1933 80    8:                         [0]
+            :                   2A 03 04 05 06 07 86 78
+1943 A1   46:                         [1] {
+1945 13   44:                           PrintableString
+            :                   'EQUIVALENT THIS IS A TEST SECURITY-'
+            :                   'CATEGORY.'
+            :                           }
+            :                         }
+            :                       }
+            :                     }
+            :                   }
+            :                 }
+            :               }
+            :             }
+1991 30    9:           SEQUENCE {
+1993 06    7:             OBJECT IDENTIFIER
+            :               dsaWithSha1 (1 2 840 10040 4 3)
+            :               (ANSI X9.57 algorithm)
+            :             }
+2002 04   47:           OCTET STRING, encapsulates {
+2004 30   45:               SEQUENCE {
+2006 02   21:                 INTEGER
+            :                   00 BC 33 37 65 C4 F7 70 5C 17 49 13
+            :                   AA 4C 85 CA BB 52 91 48 59
+
+
+
+Hoffman, Ed.                 Informational                    [Page 100]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+2029 02   20:                 INTEGER
+            :                   63 96 A2 14 8B CF 57 DE B0 48 5F 6C
+            :                   64 DD 84 04 49 5F 1C CA
+            :                 }
+            :               }
+            :           }
+            :         }
+            :       }
+            :     }
+            :   }
+
+4.11.  SignedData with Certificates Only
+
+   CA SignedData message with no content or signature, containing only
+   Alices's and Carl's certificates.
+
+   0 30 1672: SEQUENCE {
+   4 06    9:   OBJECT IDENTIFIER signedData (1 2 840 113549 1 7 2)
+            :     (PKCS #7)
+  15 A0 1657:   [0] {
+  19 30 1653:     SEQUENCE {
+  23 02    1:       INTEGER 1
+  26 31    0:       SET {}
+  28 30   11:       SEQUENCE {
+  30 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+            :           (PKCS #7)
+            :         }
+  41 A0 1407:       [0] {
+  45 30  667:         SEQUENCE {
+  49 30  602:           SEQUENCE {
+  53 A0    3:             [0] {
+  55 02    1:               INTEGER 2
+            :               }
+  58 02    1:             INTEGER 1
+  61 30    9:             SEQUENCE {
+  63 06    7:               OBJECT IDENTIFIER
+            :                 dsaWithSha1 (1 2 840 10040 4 3)
+            :                 (ANSI X9.57 algorithm)
+            :               }
+  72 30   18:             SEQUENCE {
+  74 31   16:               SET {
+  76 30   14:                 SEQUENCE {
+  78 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+  83 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+
+
+
+Hoffman, Ed.                 Informational                    [Page 101]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :               }
+  92 30   30:             SEQUENCE {
+  94 17   13:               UTCTime '990816225050Z'
+ 109 17   13:               UTCTime '391231235959Z'
+            :               }
+ 124 30   18:             SEQUENCE {
+ 126 31   16:               SET {
+ 128 30   14:                 SEQUENCE {
+ 130 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 135 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+            :               }
+ 144 30  439:             SEQUENCE {
+ 148 30  299:               SEQUENCE {
+ 152 06    7:                 OBJECT IDENTIFIER
+            :                   dsa (1 2 840 10040 4 1)
+            :                   (ANSI X9.57 algorithm)
+ 161 30  286:                 SEQUENCE {
+ 165 02  129:                   INTEGER
+            :                   00 B6 49 18 3E 8A 44 C1 29 71 94 4C
+            :                   01 C4 12 C1 7A 79 CB 54 4D AB 1E 81
+            :                   FB C6 4C B3 0E 94 09 06 EB 01 D4 B1
+            :                   C8 71 4B C7 45 C0 50 25 5D 9C FC DA
+            :                   E4 6D D3 E2 86 48 84 82 7D BA 15 95
+            :                   4A 16 F6 46 ED DD F6 98 D2 BB 7E 8A
+            :                   0A 8A BA 16 7B B9 50 01 48 93 8B EB
+            :                   25 15 51 97 55 DC 8F 53 0E 10 A9 50
+            :                   FC 70 B7 CD 30 54 FD DA DE A8 AA 22
+            :                   B5 A1 AF 8B CC 02 88 E7 8B 70 5F B9
+            :                   AD E1 08 D4 6D 29 2D D6 E9
+ 297 02   21:                   INTEGER
+            :                   00 DD C1 2F DF 53 CE 0B 34 60 77 3E
+            :                   02 A4 BF 8A 5D 98 B9 10 D5
+ 320 02  128:                   INTEGER
+            :                   0C EE 57 9B 4B BD DA B6 07 6A 74 37
+            :                   4F 55 7F 9D ED BC 61 0D EB 46 59 3C
+            :                   56 0B 2B 5B 0C 91 CE A5 62 52 69 CA
+            :                   E1 6D 3E BD BF FE E1 B7 B9 2B 61 3C
+            :                   AD CB AE 45 E3 06 AC 8C 22 9D 9C 44
+            :                   87 0B C7 CD F0 1C D9 B5 4E 5D 73 DE
+            :                   AF 0E C9 1D 5A 51 F5 4F 44 79 35 5A
+            :                   73 AA 7F 46 51 1F A9 42 16 9C 48 EB
+            :                   8A 79 61 B4 D5 2F 53 22 44 63 1F 86
+            :                   B8 A3 58 06 25 F8 29 C0 EF BA E0 75
+            :                   F0 42 C4 63 65 52 9B 0A
+
+
+
+Hoffman, Ed.                 Informational                    [Page 102]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                   }
+            :                 }
+ 451 03  133:               BIT STRING 0 unused bits, encapsulates {
+ 455 02  129:                   INTEGER
+            :                   00 99 87 74 27 03 66 A0 B1 C0 AD DC
+            :                   2C 75 BB E1 6C 44 9C DA 21 6D 4D 47
+            :                   6D B1 62 09 E9 D8 AE 1E F2 3A B4 94
+            :                   B1 A3 8E 7A 9B 71 4E 00 94 C9 B4 25
+            :                   4E B9 60 96 19 24 01 F3 62 0C FE 75
+            :                   C0 FB CE D8 68 00 E3 FD D5 70 4F DF
+            :                   23 96 19 06 94 F4 B1 61 8F 3A 57 B1
+            :                   08 11 A4 0B 26 25 F0 52 76 81 EA 0B
+            :                   62 0D 95 2A E6 86 BA 72 B2 A7 50 83
+            :                   0B AA 27 CD 1B A9 4D 89 9A D7 8D 18
+            :                   39 84 3F 8B C5 56 4D 80 7A
+            :                   }
+            :               }
+ 587 A3   66:             [3] {
+ 589 30   64:               SEQUENCE {
+ 591 30   15:                 SEQUENCE {
+ 593 06    3:                   OBJECT IDENTIFIER
+            :                     basicConstraints (2 5 29 19)
+            :                     (X.509 id-ce (2 5 29))
+ 598 01    1:                   BOOLEAN TRUE
+ 601 04    5:                   OCTET STRING, encapsulates {
+ 603 30    3:                       SEQUENCE {
+ 605 01    1:                         BOOLEAN TRUE
+            :                         }
+            :                       }
+            :                   }
+ 608 30   14:                 SEQUENCE {
+ 610 06    3:                   OBJECT IDENTIFIER
+            :                     keyUsage (2 5 29 15)
+            :                     (X.509 id-ce (2 5 29))
+ 615 01    1:                   BOOLEAN TRUE
+ 618 04    4:                   OCTET STRING, encapsulates {
+ 620 03    2:                       BIT STRING 1 unused bits
+            :                         '1100001'B
+            :                       }
+            :                   }
+ 624 30   29:                 SEQUENCE {
+ 626 06    3:                   OBJECT IDENTIFIER
+            :                     subjectKeyIdentifier (2 5 29 14)
+            :                     (X.509 id-ce (2 5 29))
+ 631 04   22:                   OCTET STRING, encapsulates {
+ 633 04   20:                       OCTET STRING
+            :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+            :                   3D 20 BC 43 2B 93 F1 1F
+
+
+
+Hoffman, Ed.                 Informational                    [Page 103]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                       }
+            :                   }
+            :                 }
+            :               }
+            :             }
+ 655 30    9:           SEQUENCE {
+ 657 06    7:             OBJECT IDENTIFIER
+            :               dsaWithSha1 (1 2 840 10040 4 3)
+            :               (ANSI X9.57 algorithm)
+            :             }
+ 666 03   48:           BIT STRING 0 unused bits, encapsulates {
+ 669 30   45:               SEQUENCE {
+ 671 02   20:                 INTEGER
+            :                   6B A9 F0 4E 7A 5A 79 E3 F9 BE 3D 2B
+            :                   C9 06 37 E9 11 17 A1 13
+ 693 02   21:                 INTEGER
+            :                   00 8F 34 69 2A 8B B1 3C 03 79 94 32
+            :                   4D 12 1F CE 89 FB 46 B2 3B
+            :                 }
+            :               }
+            :           }
+ 716 30  732:         SEQUENCE {
+ 720 30  667:           SEQUENCE {
+ 724 A0    3:             [0] {
+ 726 02    1:               INTEGER 2
+            :               }
+ 729 02    2:             INTEGER 200
+ 733 30    9:             SEQUENCE {
+ 735 06    7:               OBJECT IDENTIFIER
+            :                 dsaWithSha1 (1 2 840 10040 4 3)
+            :                 (ANSI X9.57 algorithm)
+            :               }
+ 744 30   18:             SEQUENCE {
+ 746 31   16:               SET {
+ 748 30   14:                 SEQUENCE {
+ 750 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 755 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+            :               }
+ 764 30   30:             SEQUENCE {
+ 766 17   13:               UTCTime '990817011049Z'
+ 781 17   13:               UTCTime '391231235959Z'
+            :               }
+ 796 30   19:             SEQUENCE {
+ 798 31   17:               SET {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 104]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+ 800 30   15:                 SEQUENCE {
+ 802 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+            :                     (X.520 id-at (2 5 4))
+ 807 13    8:                   PrintableString 'AliceDSS'
+            :                   }
+            :                 }
+            :               }
+ 817 30  438:             SEQUENCE {
+ 821 30  299:               SEQUENCE {
+ 825 06    7:                 OBJECT IDENTIFIER
+            :                   dsa (1 2 840 10040 4 1)
+            :                   (ANSI X9.57 algorithm)
+ 834 30  286:                 SEQUENCE {
+ 838 02  129:                   INTEGER
+            :                   00 81 8D CD ED 83 EA 0A 9E 39 3E C2
+            :                   48 28 A3 E4 47 93 DD 0E D7 A8 0E EC
+            :                   53 C5 AB 84 08 4F FF 94 E1 73 48 7E
+            :                   0C D6 F3 44 48 D1 FE 9F AF A4 A1 89
+            :                   2F E1 D9 30 C8 36 DE 3F 9B BF B7 4C
+            :                   DC 5F 69 8A E4 75 D0 37 0C 91 08 95
+            :                   9B DE A7 5E F9 FC F4 9F 2F DD 43 A8
+            :                   8B 54 F1 3F B0 07 08 47 4D 5D 88 C3
+            :                   C3 B5 B3 E3 55 08 75 D5 39 76 10 C4
+            :                   78 BD FF 9D B0 84 97 37 F2 E4 51 1B
+            :                   B5 E4 09 96 5C F3 7E 5B DB
+ 970 02   21:                   INTEGER
+            :                   00 E2 47 A6 1A 45 66 B8 13 C6 DA 8F
+            :                   B8 37 21 2B 62 8B F7 93 CD
+ 993 02  128:                   INTEGER
+            :                   26 38 D0 14 89 32 AA 39 FB 3E 6D D9
+            :                   4B 59 6A 4C 76 23 39 04 02 35 5C F2
+            :                   CB 1A 30 C3 1E 50 5D DD 9B 59 E2 CD
+            :                   AA 05 3D 58 C0 7B A2 36 B8 6E 07 AF
+            :                   7D 8A 42 25 A7 F4 75 CF 4A 08 5E 4B
+            :                   3E 90 F8 6D EA 9C C9 21 8A 3B 76 14
+            :                   E9 CE 2E 5D A3 07 CD 23 85 B8 2F 30
+            :                   01 7C 6D 49 89 11 89 36 44 BD F8 C8
+            :                   95 4A 53 56 B5 E2 F9 73 EC 1A 61 36
+            :                   1F 11 7F C2 BD ED D1 50 FF 98 74 C2
+            :                   D1 81 4A 60 39 BA 36 39
+            :                   }
+            :                 }
+1124 03  132:               BIT STRING 0 unused bits, encapsulates {
+1128 02  128:                   INTEGER
+            :                   5C E3 B9 5A 75 14 96 0B A9 7A DD E3
+            :                   3F A9 EC AC 5E DC BD B7 13 11 34 A6
+            :                   16 89 28 11 23 D9 34 86 67 75 75 13
+
+
+
+Hoffman, Ed.                 Informational                    [Page 105]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                   12 3D 43 5B 6F E5 51 BF FA 89 F2 A2
+            :                   1B 3E 24 7D 3D 07 8D 5B 63 C8 BB 45
+            :                   A5 A0 4A E3 85 D6 CE 06 80 3F E8 23
+            :                   7E 1A F2 24 AB 53 1A B8 27 0D 1E EF
+            :                   08 BF 66 14 80 5C 62 AC 65 FA 15 8B
+            :                   F1 BB 34 D4 D2 96 37 F6 61 47 B2 C4
+            :                   32 84 F0 7E 41 40 FD 46 A7 63 4E 33
+            :                   F2 A5 E2 F4 F2 83 E5 B8
+            :                   }
+            :               }
+1259 A3  129:             [3] {
+1262 30  127:               SEQUENCE {
+1264 30   12:                 SEQUENCE {
+1266 06    3:                   OBJECT IDENTIFIER
+            :                     basicConstraints (2 5 29 19)
+            :                     (X.509 id-ce (2 5 29))
+1271 01    1:                   BOOLEAN TRUE
+1274 04    2:                   OCTET STRING, encapsulates {
+1276 30    0:                       SEQUENCE {}
+            :                       }
+            :                   }
+1278 30   14:                 SEQUENCE {
+1280 06    3:                   OBJECT IDENTIFIER
+            :                     keyUsage (2 5 29 15)
+            :                     (X.509 id-ce (2 5 29))
+1285 01    1:                   BOOLEAN TRUE
+1288 04    4:                   OCTET STRING, encapsulates {
+1290 03    2:                       BIT STRING 6 unused bits
+            :                         '11'B
+            :                       }
+            :                   }
+1294 30   31:                 SEQUENCE {
+1296 06    3:                   OBJECT IDENTIFIER
+            :                     authorityKeyIdentifier (2 5 29 35)
+            :                     (X.509 id-ce (2 5 29))
+1301 04   24:                   OCTET STRING, encapsulates {
+1303 30   22:                       SEQUENCE {
+1305 80   20:                         [0]
+            :                   70 44 3E 82 2E 6F 87 DE 4A D3 75 E3
+            :                   3D 20 BC 43 2B 93 F1 1F
+            :                         }
+            :                       }
+            :                   }
+1327 30   29:                 SEQUENCE {
+1329 06    3:                   OBJECT IDENTIFIER
+            :                     subjectKeyIdentifier (2 5 29 14)
+            :                     (X.509 id-ce (2 5 29))
+1334 04   22:                   OCTET STRING, encapsulates {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 106]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+1336 04   20:                       OCTET STRING
+            :                   BE 6C A1 B3 E3 C1 F7 ED 43 70 A4 CE
+            :                   13 01 E2 FD E3 97 FE CD
+            :                       }
+            :                   }
+1358 30   31:                 SEQUENCE {
+1360 06    3:                   OBJECT IDENTIFIER
+            :                     subjectAltName (2 5 29 17)
+            :                     (X.509 id-ce (2 5 29))
+1365 04   24:                   OCTET STRING, encapsulates {
+1367 30   22:                       SEQUENCE {
+1369 81   20:                         [1] 'AliceDSS at example.com'
+            :                         }
+            :                       }
+            :                   }
+            :                 }
+            :               }
+            :             }
+1391 30    9:           SEQUENCE {
+1393 06    7:             OBJECT IDENTIFIER
+            :               dsaWithSha1 (1 2 840 10040 4 3)
+            :               (ANSI X9.57 algorithm)
+            :             }
+1402 03   48:           BIT STRING 0 unused bits, encapsulates {
+1405 30   45:               SEQUENCE {
+1407 02   20:                 INTEGER
+            :                   55 0C A4 19 1F 42 2B 89 71 22 33 8D
+            :                   83 6A B5 3D 67 6B BF 45
+1429 02   21:                 INTEGER
+            :                   00 9F 61 53 52 54 0B 5C B2 DD DA E7
+            :                   76 1D E2 10 52 5B 43 5E BD
+            :                 }
+            :               }
+            :           }
+            :         }
+1452 A1  219:       [1] {
+1455 30  216:         SEQUENCE {
+1458 30  153:           SEQUENCE {
+1461 30    9:             SEQUENCE {
+1463 06    7:               OBJECT IDENTIFIER
+            :                 dsaWithSha1 (1 2 840 10040 4 3)
+            :                 (ANSI X9.57 algorithm)
+            :               }
+1472 30   18:             SEQUENCE {
+1474 31   16:               SET {
+1476 30   14:                 SEQUENCE {
+1478 06    3:                   OBJECT IDENTIFIER
+            :                     commonName (2 5 4 3)
+
+
+
+Hoffman, Ed.                 Informational                    [Page 107]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :                     (X.520 id-at (2 5 4))
+1483 13    7:                   PrintableString 'CarlDSS'
+            :                   }
+            :                 }
+            :               }
+1492 17   13:             UTCTime '990827070000Z'
+1507 30  105:             SEQUENCE {
+1509 30   19:               SEQUENCE {
+1511 02    2:                 INTEGER 200
+1515 17   13:                 UTCTime '990822070000Z'
+            :                 }
+1530 30   19:               SEQUENCE {
+1532 02    2:                 INTEGER 201
+1536 17   13:                 UTCTime '990822070000Z'
+            :                 }
+1551 30   19:               SEQUENCE {
+1553 02    2:                 INTEGER 211
+1557 17   13:                 UTCTime '990822070000Z'
+            :                 }
+1572 30   19:               SEQUENCE {
+1574 02    2:                 INTEGER 210
+1578 17   13:                 UTCTime '990822070000Z'
+            :                 }
+1593 30   19:               SEQUENCE {
+1595 02    2:                 INTEGER 212
+1599 17   13:                 UTCTime '990824070000Z'
+            :                 }
+            :               }
+            :             }
+1614 30    9:           SEQUENCE {
+1616 06    7:             OBJECT IDENTIFIER
+            :               dsaWithSha1 (1 2 840 10040 4 3)
+            :               (ANSI X9.57 algorithm)
+            :             }
+1625 03   47:           BIT STRING 0 unused bits, encapsulates {
+1628 30   44:               SEQUENCE {
+1630 02   20:                 INTEGER
+            :                   7E 65 52 76 33 FE 34 73 17 D1 F7 96
+            :                   F9 A0 D4 D8 6D 5C 7D 3D
+1652 02   20:                 INTEGER
+            :                   02 7A 5B B7 D5 5B 18 C1 CF 87 EF 7E
+            :                   DA 24 F3 2A 83 9C 35 A1
+            :                 }
+            :               }
+            :           }
+            :         }
+1674 31    0:       SET {}
+            :       }
+
+
+
+Hoffman, Ed.                 Informational                    [Page 108]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+            :     }
+            :   }
+
+5.  Enveloped-data
+
+5.1.  Basic Encrypted Content, TripleDES and RSA
+
+   An EnvelopedData from Alice to Bob of ExContent using TripleDES for
+   encrypting and RSA for key management.  Does not have an
+   OriginatorInfo.
+
+      0 30  286: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER
+               :     envelopedData (1 2 840 113549 1 7 3)
+               :     (PKCS #7)
+     15 A0  271:   [0] {
+     19 30  267:     SEQUENCE {
+     23 02    1:       INTEGER 0
+     26 31  192:       SET {
+     29 30  189:         SEQUENCE {
+     32 02    1:           INTEGER 0
+     35 30   38:           SEQUENCE {
+     37 30   18:             SEQUENCE {
+     39 31   16:               SET {
+     41 30   14:                 SEQUENCE {
+     43 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+     48 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+     57 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               CD 5D 71 D0
+               :             }
+     75 30   13:           SEQUENCE {
+     77 06    9:             OBJECT IDENTIFIER
+               :               rsaEncryption (1 2 840 113549 1 1 1)
+               :               (PKCS #1)
+     88 05    0:             NULL
+               :             }
+     90 04  128:           OCTET STRING
+               :             0B 71 0D E6 71 88 88 98 B6 96 C1 8F
+               :             70 FD A2 27 DE DA E1 EF 24 6C A4 33
+               :             DF AC E0 E9 9D A2 D3 2C 7A CD 80 B8
+               :             99 9E E6 5F B1 41 B3 72 16 83 E7 FA
+               :             2A 00 8B C7 73 35 78 26 D6 C7 CF 8C
+
+
+
+Hoffman, Ed.                 Informational                    [Page 109]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :             0C 56 DB A5 76 9D 08 38 0E F3 F9 D4
+               :             91 43 58 78 DC 49 B6 EC EE 6C 68 33
+               :             A3 21 1D F0 28 78 1F F7 5D F6 07 73
+               :             4D DF AD 69 31 20 4B 48 A9 75 22 6E
+               :             36 79 15 63 8F CC EB 9D A3 28 A1 D1
+               :             2C 57 F4 DA 1A 2C 75 1F
+               :           }
+               :         }
+    221 30   67:       SEQUENCE {
+    223 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+    234 30   20:         SEQUENCE {
+    236 06    8:           OBJECT IDENTIFIER
+               :             des-EDE3-CBC (1 2 840 113549 3 7)
+               :             (RSADSI encryptionAlgorithm
+               :                 (1 2 840 113549 3))
+    246 04    8:           OCTET STRING
+               :             2D 68 C5 E9 47 06 51 35
+               :           }
+    256 80   32:         [0]
+               :           0E C8 92 7F C6 7D 3F 8D CB AD 8E 0E
+               :           C5 49 3A EB 47 2E D6 55 DE 09 21 4E
+               :           48 EA 4E 27 B1 6E 57 25
+               :         }
+               :       }
+               :     }
+               :   }
+
+5.2.  Basic Encrypted Content, RC2/128 and RSA
+
+   Same as 5.1, except using RC2/128 for encryption and RSA for key
+   management.  An EnvelopedData from Alice to Bob of ExContent using
+   RC2/40 for encrypting and RSA for key management.  Does not have an
+   OriginatorInfo or any attributes.
+
+      0 30  291: SEQUENCE {
+      4 06    9:   OBJECT IDENTIFIER
+               :     envelopedData (1 2 840 113549 1 7 3)
+               :     (PKCS #7)
+     15 A0  276:   [0] {
+     19 30  272:     SEQUENCE {
+     23 02    1:       INTEGER 0
+     26 31  192:       SET {
+     29 30  189:         SEQUENCE {
+     32 02    1:           INTEGER 0
+     35 30   38:           SEQUENCE {
+     37 30   18:             SEQUENCE {
+     39 31   16:               SET {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 110]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     41 30   14:                 SEQUENCE {
+     43 06    3:                   OBJECT IDENTIFIER
+               :                     commonName (2 5 4 3)
+               :                     (X.520 id-at (2 5 4))
+     48 13    7:                   PrintableString 'CarlRSA'
+               :                   }
+               :                 }
+               :               }
+     57 02   16:             INTEGER
+               :               46 34 6B C7 80 00 56 BC 11 D3 6E 2E
+               :               CD 5D 71 D0
+               :             }
+     75 30   13:           SEQUENCE {
+     77 06    9:             OBJECT IDENTIFIER
+               :               rsaEncryption (1 2 840 113549 1 1 1)
+               :               (PKCS #1)
+     88 05    0:             NULL
+               :             }
+     90 04  128:           OCTET STRING
+               :             85 42 BE E3 0B 2E E5 0F 09 AA 24 CA
+               :             DE DA C1 D3 09 B8 27 2B 25 CB D5 71
+               :             FB C9 9C DB F0 B2 6E A0 8A 5F 1C 9D
+               :             4A ED 98 9D 15 39 26 01 1A 2E 6B F0
+               :             44 39 89 37 3C 6F C7 4A 61 0B 0B 27
+               :             77 AA F9 D4 97 A4 D2 21 3F C2 3F 20
+               :             D4 DC 10 E9 D6 3F 00 DB 9C 82 47 D6
+               :             7E 96 FF 12 6E 87 84 A0 BA ED 81 0F
+               :             56 6D A6 1D EB AB C3 B7 A1 B9 F8 5F
+               :             8B CC 1B 4A E5 14 36 06 61 D0 C7 64
+               :             5F 69 67 91 A9 50 EE D8
+               :           }
+               :         }
+    221 30   72:       SEQUENCE {
+    223 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+    234 30   25:         SEQUENCE {
+    236 06    8:           OBJECT IDENTIFIER rc2CBC (1 2 840 113549 3 2)
+               :             (RSADSI encryptionAlgorithm
+               :                 (1 2 840 113549 3))
+    246 30   13:           SEQUENCE {
+    248 02    1:             INTEGER 58
+    251 04    8:             OCTET STRING
+               :               E8 70 81 E2 EF C5 15 57
+               :             }
+               :           }
+    261 80   32:         [0]
+               :           06 53 0A 7B 8D 5C 16 0D CC D5 76 D6
+               :           8B 59 D6 45 8C 1A 1A 0C E6 1E F3 DE
+
+
+
+Hoffman, Ed.                 Informational                    [Page 111]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+               :           43 56 00 9B 40 8C 38 5D
+               :         }
+               :       }
+               :     }
+               :   }
+
+5.3.  S/MIME application/pkcs7-mime Encrypted Message
+
+   A full S/MIME message, including MIME, that includes the body part
+   from 5.1.
+
+MIME-Version: 1.0
+Message-Id: <00103112005203.00349 at amyemily.ig.com>
+Date: Tue, 31 Oct 2000 12:00:52 -0600 (Central Standard Time)
+From: User1
+To: User2
+Subject: Example 5.3
+Content-Type: application/pkcs7-mime;
+        name=smime.p7m;
+        smime-type=enveloped-data
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment; filename=smime.p7m
+
+MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYXJ
+sUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGPcP
+2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadC
+DgO8/nUkUNYeNxJtuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHR
+LFf02hosdR8wQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43
+LrY4OxUk660cu1lXeCSFOSOpOJ7FuVyU=
+
+6.  Digested-data
+
+   A DigestedData from Alice to Bob of ExContent using SHA-1.
+
+      0 30   94: SEQUENCE {
+      2 06    9:   OBJECT IDENTIFIER digestedData (1 2 840 113549 1 7 5)
+               :     (PKCS #7)
+     13 A0   81:   [0] {
+     15 30   79:     SEQUENCE {
+     17 02    1:       INTEGER 0
+     20 30    7:       SEQUENCE {
+     22 06    5:         OBJECT IDENTIFIER sha1 (1 3 14 3 2 26)
+               :           (OIW)
+               :         }
+     29 30   43:       SEQUENCE {
+     31 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     42 A0   30:         [0] {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 112]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+     44 04   28:           OCTET STRING 'This is some sample content.'
+               :           }
+               :         }
+     74 04   20:       OCTET STRING
+               :         40 6A EC 08 52 79 BA 6E 16 02 2D 9E
+               :         06 29 C0 22 96 87 DD 48
+               :       }
+               :     }
+               :   }
+
+7.  Encrypted-data
+
+7.1.  Simple EncryptedData
+
+   An EncryptedData from Alice to Bob of ExContent with no attributes.
+
+      0 30   87: SEQUENCE {
+      2 06    9:   OBJECT IDENTIFIER
+               :     encryptedData (1 2 840 113549 1 7 6)
+               :     (PKCS #7)
+     13 A0   74:   [0] {
+     15 30   72:     SEQUENCE {
+     17 02    1:       INTEGER 0
+     20 30   67:       SEQUENCE {
+     22 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     33 30   20:         SEQUENCE {
+     35 06    8:           OBJECT IDENTIFIER
+               :             des-EDE3-CBC (1 2 840 113549 3 7)
+               :             (RSADSI encryptionAlgorithm
+               :                 (1 2 840 113549 3))
+     45 04    8:           OCTET STRING
+               :             B3 6B 6B FB 62 31 08 4E
+               :           }
+     55 80   32:         [0]
+               :           FA FC ED DB 3F 18 17 1D 38 89 11 EA
+               :           34 D6 20 DB F4 C3 D9 58 15 EF 93 3B
+               :           9A F5 D7 04 F6 B5 70 E2
+               :         }
+               :       }
+               :     }
+               :   }
+
+   The TripleDES key is:
+
+       73 7c 79 1f 25 ea d0 e0 46 29 25 43 52 f7 dc 62
+       91 e5 cb 26 91 7a da 32
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 113]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+7.2.  EncryptedData with Unprotected Attributes
+
+   An EncryptedData from Alice to Bob of ExContent with unprotected
+   attributes.
+
+      0 30  149: SEQUENCE {
+      3 06    9:   OBJECT IDENTIFIER
+               :     encryptedData (1 2 840 113549 1 7 6)
+               :     (PKCS #7)
+     14 A0  135:   [0] {
+     17 30  132:     SEQUENCE {
+     20 02    1:       INTEGER 2
+     23 30   67:       SEQUENCE {
+     25 06    9:         OBJECT IDENTIFIER data (1 2 840 113549 1 7 1)
+               :           (PKCS #7)
+     36 30   20:         SEQUENCE {
+     38 06    8:           OBJECT IDENTIFIER
+               :             des-EDE3-CBC (1 2 840 113549 3 7)
+               :             (RSADSI encryptionAlgorithm
+               :                 (1 2 840 113549 3))
+     48 04    8:           OCTET STRING
+               :             07 27 20 85 90 9E B0 7E
+               :           }
+     58 80   32:         [0]
+               :           D2 20 8F 67 48 8A CB 41 E4 22 68 5D
+               :           BE 77 05 52 26 ED E3 01 BD 00 91 58
+               :           A7 35 6E BC 4B A2 07 33
+               :         }
+     92 A1   58:       [1] {
+     94 30   56:         SEQUENCE {
+     96 06    3:           OBJECT IDENTIFIER '1 2 5555'
+    101 31   49:           SET {
+    103 04   47:             OCTET STRING
+               :               'This is a test General ASN Attribut'
+               :               'e, number 1.'
+               :             }
+               :           }
+               :         }
+               :       }
+               :     }
+               :   }
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 114]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+8.  Security Considerations
+
+   Because this document shows examples of S/MIME and CMS messages, this
+   document also inherits all of the security considerations from
+   [SMIME-MSG] and [CMS].
+
+   The Perl script in Appendix A writes to the user's local hard drive.
+   A malicious attacker could modify the Perl script in this document.
+   Be sure to read the Perl code carefully before executing it.
+
+9.  References
+
+9.1.  Normative References
+
+   [CMS]       Housley, R., "Cryptographic Message Syntax (CMS)", RFC
+               3852, July 2004.
+
+   [PKIX]      Housley, R., Polk, W., Ford, W., and D. Solo, "Internet
+               X.509 Public Key Infrastructure Certificate and
+               Certificate Revocation List (CRL) Profile", RFC 3280,
+               April 2002.
+
+   [SMIME-MSG] Ramsdell, B., "Secure/Multipurpose Internet Mail
+               Extensions (S/MIME) Version 3.1 Message Specification",
+               RFC 3851, July 2004.
+
+9.2.  Informative References
+
+   [DVCS]      Adams, C., Sylvester, P., Zolotarev, M., and R.
+               Zuccherato, "Internet X.509 Public Key Infrastructure
+               Data Validation and Certification Server Protocols", RFC
+               3029, February 2001.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 115]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+A.  Binaries of the Examples
+
+   This section contains the binaries of the examples shown in the rest
+   of the document.  The binaries are stored in a modified Base64
+   format.  There is a Perl program that, when run over the contents of
+   this document, will extract the following binaries and write them out
+   to disk.  The program requires Perl.
+
+A.1.  How the Binaries and Extractor Works
+
+   The program in the next section looks for lines that begin with a '|'
+   character (or some whitespace followed by a '|'), ignoring all other
+   lines.  If the line begins with '|', the second character tells what
+   kind of line it is:
+
+      A line that begins with |* is a comment
+      A line that begins with |> gives the name of a new file to start
+      A line that begins with |< tells to end the file (and checks the
+            file name for sanity)
+      A line that begins with |anythingelse is a Base64 line
+
+   The program writes out a series of files, so you should run this in
+   an empty directory.  The program will overwrite files (if it can),
+   but won't delete other files already in the directory.
+
+   Run this program with this document as the standard input, such as:
+
+      ./extractsample.pl <draft-ietf-smime-examples
+
+   If you want to extract without the program, copy all the lines
+   between the "|>" and "|<" markers, remove any page breaks, and remove
+   the "|" in the first column of each line.  The result is a valid
+   Base64 blob that can be processed by any Base64 decoder.
+
+A.2.  Example Extraction Program
+
+#!/usr/bin/perl
+
+# CMS Samples extraction program. v 1.1
+
+# Get all the input as an array of lines
+ at AllIn = (); while (<STDIN>) { push(@AllIn, $_) }
+
+$Base64Chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr' .
+    'stuvwxyz0123456789+/=';
+$LineCount = 0; $CurrFile = '';
+
+foreach $Line (@AllIn) {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 116]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+    $LineCount++;  # Keep the line counter for error messages
+    $Line =~ s/^\s*//;  # Get rid of leading whitespace
+    chomp($Line);  # Get rid of CR or CRLF at the end of the line
+    if(substr($Line, 0, 1) ne '|') { next }  # Not a special line
+    elsif(substr($Line, 1, 1) eq '*') { next }  # It is a comment
+    elsif(substr($Line, 1, 1) eq '>')
+      { &StartNewFile(substr($Line, 2)) }  # Start a new file
+    elsif(substr($Line, 1, 1) eq '<')
+      { &EndCurrFile(substr($Line, 2)) }  # End the current file
+    else { &DoBase64(substr($Line, 1)) }  # It is a line of Base64
+}
+
+sub StartNewFile {
+    $TheNewFile = shift(@_);
+    if($CurrFile ne '') { die "Was about to start a new file at " .
+      "line $LineCount, but the old file, $CurrFile, was open\n" }
+    open(OUT, ">$TheNewFile") or
+      die "Could not open $TheNewFile for writing: $!\n";
+    binmode(OUT);  # This is needed for Windows, is a noop on Unix
+    $CurrFile = $TheNewFile;
+    $LeftOver = 0;  # Amount left from previous Base64 character
+    $NextPos = 0;  # Bit position to start the next Base64 character
+                   #     (bits are numbered 01234567)
+    $OutString = '';  # Holds the text going out to the file
+}
+
+sub EndCurrFile {
+    $FileToEnd = shift(@_);
+    if($CurrFile ne $FileToEnd) { die "Was about to close " .
+      "$FileToEnd at line $LineCount, but that name didn't match " .
+      "the name of the currently open file, $CurrFile\n" }
+    print OUT $OutString;
+    close(OUT);
+    $CurrFile = '';
+}
+
+sub DoBase64 {
+    $TheIn = shift(@_);
+    if($CurrFile eq '') { die "Got some Base64 at line $LineCount, " .
+      "but appear to not be writing to any particular file.\n" }
+    @Chars = split(//, $TheIn);  # Make an array of the characters
+    foreach $ThisChar (@Chars) {
+    # $ThisVal is the position in the string and the Base64 value
+      $ThisVal = index($Base64Chars, $ThisChar);
+      if($ThisVal == -1) { die "At line $LineCount, found the " .
+          "character $ThisChar, which is not a Base64 character\n" }
+      if($ThisVal == 64) { last }  # It is a "=", so we're done
+      if ($NextPos == 0 ) {
+
+
+
+Hoffman, Ed.                 Informational                    [Page 117]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+          # Don't output anything, just fill the left of $LeftOver
+          $LeftOver = $ThisVal * 4;
+          $NextPos = 6;
+      } elsif ($NextPos == 2) {
+        # Add $ThisVal to $LeftOver, output, and reset
+          $OutString .= chr($LeftOver + $ThisVal);
+          $LeftOver = 0;
+          $NextPos = 0;
+      } elsif ($NextPos == 4) {
+          # Add upper 4 bits of $ThisVal to $LeftOver and output
+          $Upper4 = ($ThisVal & 60);
+          $OutString .= chr($LeftOver + ($Upper4/4));
+          $LeftOver = (($ThisVal - $Upper4) * 64);
+          $NextPos = 2;
+      } elsif ($NextPos == 6) {
+          # Add upper 2 bits of $ThisVal to $LeftOver and output
+          $Upper2 = ($ThisVal & 48);
+          $OutString .= chr($LeftOver + ($Upper2/16));
+          $LeftOver = (($ThisVal - $Upper2) * 16);
+          $NextPos = 4;
+      } else { die "\$NextPos has an illegal value: $NextPos." }
+    }
+}
+
+B.  Examples in Order of Appearance
+
+From Section 2.1
+
+***ExContent.bin***
+
+|* Section 2.1
+|>ExContent.bin
+|VGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50Lg==
+|<ExContent.bin
+
+From Section 2.2
+
+***AlicePrivDSSSign.pri***
+
+|* Example AlicePrivDSSSign.pri
+|>AlicePrivDSSSign.pri
+|MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBAIGNze2D6gqeOT7CSCij5EeT3Q7XqA7sU8
+|WrhAhP/5Thc0h+DNbzREjR/p+vpKGJL+HZMMg23j+bv7dM3F9piuR10DcMkQiVm96nXvn8
+|9J8v3UOoi1TxP7AHCEdNXYjDw7Wz41UIddU5dhDEeL3/nbCElzfy5FEbteQJllzzflvbAh
+|UA4kemGkVmuBPG2o+4NyErYov3k80CgYAmONAUiTKqOfs+bdlLWWpMdiM5BAI1XPLLGjDD
+|HlBd3ZtZ4s2qBT1YwHuiNrhuB699ikIlp/R1z0oIXks+kPht6pzJIYo7dhTpzi5dowfNI4
+|W4LzABfG1JiRGJNkS9+MiVSlNWteL5c+waYTYfEX/Cve3RUP+YdMLRgUpgObo2OQQXAhUA
+|u0RG0aXJRgcu0P561pIH8JqFiT8=
+
+
+
+Hoffman, Ed.                 Informational                    [Page 118]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|<AlicePrivDSSSign.pri
+
+***AlicePrivRSASign.pri***
+
+|* Example AlicePrivRSASign.pri
+|>AlicePrivRSASign.pri
+|MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOCJczmN2PX16Id2OX9OsA
+|W7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvYMs/GaG8H
+|2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mXcCpkhSjE
+|7zVzhXdFdfAgMBAAECgYAApAPDJ0d2NDRspoa1eUkBSy6K0shissfXSAlqi5H3NvJ11ujN
+|FZBgJzFHNWRNlc1nY860n1asLzduHO4Ovygt9DmQbzTYbghb1WVq2EHzE9ctOV7+M8v/Ke
+|QDCz0Foo+38Y6idjeweVfTLyvehwYifQRmXskbr4saw+yRRKt/IQJBAPbW4CIhTF8KcP8n
+|/OWzUGqd5Q+1hZbGQPqoCrSbmwxVwgEd+TeCihTI8pMOks2lZiG5PNIGv7RVMcncrcqYLd
+|ECQQDo3rARJQnSAlEB3oromFD1d3dhpEWTawhVlnNd9MhbEpMic4t/03B/9aSqu3T9PCJq
+|2jiRKoZbbBTorkye+o4vAkEAl0zwh5sXf+4bgxsUtgtqkF+GJ1Hht6B/9eSI41m5+R6b0y
+|l3OCJI1yKxJZi6PVlTt/oeILLIURYjdZNR56vN8QJALPAkW/qgzYUi6tBuT/pszSHTyOTx
+|hERIZHPXKY9+RozsFd7kUbOU5yyZLVVleyTqo2IfPmxNZ0ERO+G+6YMCgwJAWIjZoVA4hG
+|qrA7y730v0nG+4tCol+/bkBS9u4oiJIW9LJZ7Qq1CTyr9AcewhJcV/+wLpIZa4M83ixpXu
+|b41fKA==
+|<AlicePrivRSASign.pri
+
+***BobPrivRSAEncrypt.pri***
+
+|* Example BobPrivRSAEncrypt.pri
+|>BobPrivRSAEncrypt.pri
+|MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf8qCTQV6meY
+|mFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmRuBlpN235ZR572akzJKN/
+|O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtdYMTgXB9T039T2GkB8QX4enDRvoPGXz
+|jPHCyqaqfrAgMBAAECgYBnzUhMmg2PmMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngw
+|y+e6alatd8brUXlweQqg9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A
+|0HPfD6bRSeTmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N
+|vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiEI2Kv8zHCue
+|UCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr84/sajB0+E0R9KfEILVH
+|IdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5qSO8bKlocSHseIVnDYDubl6nA7xhmqU
+|5iUjiEzuUJiEiUacUgFJlaV/4jbOSnI3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVf
+|JAZAcpw6iIWchw+dYhKIFmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grSta
+|vCunrnVNqcBU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8
+|Y0ZB9qANMAsGA1UdDzEEAwIAEA==
+|<BobPrivRSAEncrypt.pri
+
+***CarlPrivDSSSign.pri***
+
+|* Example CarlPrivDSSSign.pri
+|>CarlPrivDSSSign.pri
+|MIIBSgIBADCCASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8
+|ZMsw6UCQbrAdSxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5
+|UAFIk4vrJRVRl1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAh
+|UA3cEv31POCzRgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytb
+
+
+
+Hoffman, Ed.                 Informational                    [Page 119]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|DJHOpWJSacrhbT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0
+|R5NVpzqn9GUR+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgQWAhQZ
+|szilIWIxUOV/uT4IRnjRPrXlcg==
+|<CarlPrivDSSSign.pri
+
+***CarlPrivRSASign.pri***
+
+|* Example CarlPrivRSASign.pri
+|>CarlPrivRSASign.pri
+|MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAORL/xi4JFf0d/9uc3uTcV
+|y8MxqSknIj2EFG0M0ROgSzjq+Cnb1RHhd68nYsK4Y5p73XjRpT7OQA1ejsojax7eJQ4jIJ
+|ij+fmSWPuE6ruX3VlmXaFqDFvg6uRFvvXvSnKcuC3axE6aqTlCkO+BjWyFde8nbE8hFgOL
+|kbPB2XyWrxAgMBAAECgYEArnPkW19bZlrJ18bvOF9TISovYv7eKZp6hmc2531ieHU9c6C8
+|KQ7zj73Dycm2+LrWE5vDl3rKavC4hWVOD72nqPdUBkG969wgd5DfYZuab3Te6jvUnIdg7X
+|aE8WowN9XgkBb4gEfDGWvtdXe6Su05tl0CRztfG8gcq8vo9SY/pIECQQD/3wmgVgtCUp7E
+|TZOzsEm73ueBfSiZ0LFIugs54Rx7IhgztkD2v9yuHdChrQRxWmEKbjvOMNo2n2UlKbunDn
+|8LAkEA5GloGF/5V9B8ZokPumMdcssgpIF2ZInNfdHCJ6kurHpWmoUH2TADowOrf4iSUCQB
+|qhsHHyBMt8l7Vve2wn6rcwJAVzZsj4wEdmy21O4kRAD4gOKvQgGpDxSE+OcA4I+MJ6QtX6
+|LlbbVjwK1E6XaRpxlJLkb4d4VLO4cE8K/S2FQmlQJAZKEPrFV0G70NYXsXA82w5qcZHYCv
+|8UFI2Bq2iBSgLHrFdtQPDh96KrJuNwSrOUVzukaoD42CXyIUBc+io/N8gwJAJh4dHKGYK+
+|TbOOhXbmtzGYhhOvp0SjaLR2hdUOsm4+p9m05lqa97q0sudlE9qNARq6PWqMAnNh1UC6qn
+|0W2N+g==
+|<CarlPrivRSASign.pri
+
+***DianePrivDSSSign.pri***
+
+|* Example DianePrivDSSSign.pri
+|>DianePrivDSSSign.pri
+|MIIBSwIBADCCASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8
+|ZMsw6UCQbrAdSxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5
+|UAFIk4vrJRVRl1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAh
+|UA3cEv31POCzRgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytb
+|DJHOpWJSacrhbT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0
+|R5NVpzqn9GUR+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgQXAhUA
+|lpX54MHgQS0yD4tCUpMq5h4OISk=
+|<DianePrivDSSSign.pri
+
+***DianePrivRSASignEncrypt.pri***
+
+|* Example DianePrivRSASignEncrypt.pri
+|>DianePrivRSASignEncrypt.pri
+|MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANb9uMBwxkwl7OrP6ny7om
+|L68OYyOlP/sZJaF/Qg4ZkkggrQ9nz7RMqLJwbxfiYDqXadz+ygLHCW8oNC9tS3KAq7+L9K
+|TBk/B9ugwWAet35n996xw2BJrEXX+MbvCDchk0fu8HM1crACxPMRw15H5Qq3g/HbdGlki0
+|QdlV3NKMCFAgMBAAECgYA9vc3CDmEUW0vnv2AjBCvFazWllkUj/Gl9kzwP0yWWumJSQuKW
+|z/5YgI/rsYy91A1l0Dp3RSSeDOuGgMOsIRFxROOyqKkurBfSo4QlY7W8Lx7d9iH/FSAkW/
+|GAL9VBDjIk99RKMp65SdgZjj85jWK9gPwMJJKT5MPXBZFTu5a2QQJBAPO4P0rRlLCRYBNB
+|kg2NRD93Hf+WI0QI1AtwyRqv6ZCU8rDVX08ZhVChkJGuvQV2UrMi2Kh8jlR/AHJPNnVoc7
+
+
+
+Hoffman, Ed.                 Informational                    [Page 120]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|UCQQDh0ucRVwaucpUiFqoCtFrtTp2CEU+WPIbJEI1WezF1eWnndWg4AEsu0iYy3bHi4CxU
+|gAp1utFmlhuwDqB+0ruRAkEAr7a82yJzQ0HstLVnqaGZ/O/Sjv0d++Upi/4K39TIXlclCl
+|0r1AmgVlvFsWL8IL4ILeMHtaHns//EwKVfrBJcqQJBALmYQfwIUB9zYIoBonxSiiBa6iyJ
+|2aUZ3ZTGG8MlwIJR5O4rmhncc+3pHSfU+GwD3asdCHu1rH/pgpvxiYpx22ECQAEHIZdfem
+|Co/VpcB9+o3vfisTR9/OuRvbBzdMjEvj9YRTAGkLOsacyz9z98rMe4G2WhFjk5sON0fc/N
+|xaxsv+U=
+|<DianePrivRSASignEncrypt.pri
+
+From Section 2.3
+
+***AliceDSSSignByCarlNoInherit.cer***
+
+|* Example AliceDSSSignByCarlNoInherit.cer
+|>AliceDSSSignByCarlNoInherit.cer
+|MIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT
+|k5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1MwggG2
+|MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//lO
+|FzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6iL
+|VPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6YaRW
+|a4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1ni
+|zaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8bU
+|mJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuVp1
+|FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41bY8
+|i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxDKE
+|8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBs
+|AwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwfft
+|Q3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqGSM
+|44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0Ne
+|vQ==
+|<AliceDSSSignByCarlNoInherit.cer
+
+***AliceRSASignByCarl.cer***
+
+|* Example AliceRSASignByCarl.cer
+|>AliceRSASignByCarl.cer
+|MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUFADASMRAwDg
+|YDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1OVowEzERMA8G
+|A1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJczmN2PX16I
+|d2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sVCeRkTxLLvY
+|Ms/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0ny36VTq5mX
+|cCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIG
+|wDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUd9K00bdMio
+|qjzkWdzuw8oDrj/1AwHwYDVR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb20wDQYJKoZI
+|hvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzPbrMcWakgqg
+|WBqE4lradwFHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2Tt0z3Sp0LF
+|6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCI=
+|<AliceRSASignByCarl.cer
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 121]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***BobRSASignByCarl.cer***
+
+|* Example BobRSASignByCarl.cer
+|>BobRSASignByCarl.cer
+|MIICJzCCAZCgAwIBAgIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQUFADASMRAwDg
+|YDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDkwMloXDTM5MTIzMTIzNTk1OVowETEPMA0G
+|A1UEAxMGQm9iUlNBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCp4WeYPznVX/Kgk0
+|FepnmJhcg1XZqRW/sdAdoZcCYXD72lItA1hW16mGYUQVzPt7cIOwnJkbgZaTdt+WUee9mp
+|MySjfzu7r0YBhjY0MssHA1lS/IWLMQS4zBgIFEjmTxz7XWDE4FwfU9N/U9hpAfEF+Hpw0b
+|6Dxl84zxwsqmqn6wIDAQABo38wfTAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFIDAf
+|BgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQU6PS4Z9izlqQq8x
+|GqKdOVWoYWtCQwHQYDVR0RBBYwFIESQm9iUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEB
+|BQUAA4GBAHuOZsXxED8QIEyIcat7QGshM/pKld6dDltrlCEFwPLhfirNnJOIh/uLt359QW
+|Hh5NZt+eIEVWFFvGQnRMChvVl52R1kPCHWRbBdaDOS6qzxV+WBfZjmNZGjOd539OgcOync
+|f1EHl/M28FAK3Zvetl44ESv7V+qJba3JiNiPzyvT
+|<BobRSASignByCarl.cer
+
+***CarlDSSSelf.cer***
+
+|* Example CarlDSSSelf.cer
+|>CarlDSSSelf.cer
+|MIICmzCCAlqgAwIBAgIBATAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOT
+|kwODE2MjI1MDUwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdDYXJsRFNTMIIBtzCC
+|ASsGByqGSM44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8ZMsw6UCQbrAd
+|SxyHFLx0XAUCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5UAFIk4vrJRVR
+|l1Xcj1MOEKlQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAhUA3cEv31POCz
+|Rgdz4CpL+KXZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytbDJHOpWJSacrh
+|bT69v/7ht7krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0R5NVpzqn9GUR
+|+pQhacSOuKeWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgOBhQACgYEAmYd0JwNm
+|oLHArdwsdbvhbESc2iFtTUdtsWIJ6diuHvI6tJSxo456m3FOAJTJtCVOuWCWGSQB82IM/n
+|XA+87YaADj/dVwT98jlhkGlPSxYY86V7EIEaQLJiXwUnaB6gtiDZUq5oa6crKnUIMLqifN
+|G6lNiZrXjRg5hD+LxVZNgHqjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAg
+|GGMB0GA1UdDgQWBBRwRD6CLm+H3krTdeM9ILxDK5PxHzAJBgcqhkjOOAQDAzAAMC0CFGup
+|8E56Wnnj+b49K8kGN+kRF6ETAhUAjzRpKouxPAN5lDJNEh/OiftGsjs=
+|<CarlDSSSelf.cer
+
+***CarlRSASelf.cer***
+
+|* Example CarlRSASelf.cer
+|>CarlRSASelf.cer
+|MIIB6zCCAVSgAwIBAgIQRjRrx4AAVrwR024un/JQIDANBgkqhkiG9w0BAQUFADASMRAwDg
+|YDVQQDEwdDYXJsUlNBMB4XDTk5MDgxODA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEjEQMA4G
+|A1UEAxMHQ2FybFJTQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Ev/GLgkV/R3/2
+|5ze5NxXLwzGpKSciPYQUbQzRE6BLOOr4KdvVEeF3rydiwrhjmnvdeNGlPs5ADV6OyiNrHt
+|4lDiMgmKP5+ZJY+4Tqu5fdWWZdoWoMW+Dq5EW+9e9Kcpy4LdrETpqpOUKQ74GNbIV17yds
+|TyEWA4uRs8HZfJavECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+|AYYwHQYDVR0OBBYEFOngkCeseCB6mtNM8kI3TiKunji7MA0GCSqGSIb3DQEBBQUAA4GBAL
+|ee1ATT7Snk/4mJFS5M2wzwSA8yYe7EBOwSXS3/D2RZfgrD7Rj941ZAN6cHtfA4EmFQ7e/d
+
+
+
+Hoffman, Ed.                 Informational                    [Page 122]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|P+MLuGGlpJs85p6cVJq2ldbabDu1LUU1nUkBdvq5uTH5+WsSU6D1FGCbfco+8lNrsDdvre
+|Z019v6WuoUQWNdzb7IDsHaao1TNBgC
+|<CarlRSASelf.cer
+
+***DianeDSSSignByCarlInherit.cer***
+
+|* Example DianeDSSSignByCarlInherit.cer
+|>DianeDSSSignByCarlInherit.cer
+|MIIBuDCCAXegAwIBAgICANIwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4XDT
+|k5MDgxNzAyMDgxMFoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIRGlhbmVEU1MwgZMw
+|CQYHKoZIzjgEAQOBhQACgYEAoAAXeCzufoFTLi5hCA+hm1FSGtpZqHMvEiW2CMvK7ypEdo
+|pSCeq9BSLVD/b9RtevmTgJDhPLTyzdHDT3HL8l/yPTO1nngpc3vjEk2BjI80k5W7fi5Sd+
+|/IxFclt+Po9oTd1GeiK+jv/M2jkpoznln0PpVcnXW6aBZ8zAqs0uxSOjgYEwfzAMBgNVHR
+|MBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm+H3krTdeM9ILxD
+|K5PxHzAdBgNVHQ4EFgQUZDCZfVzcRQuZOlIvFr9YUN3OKxgwHwYDVR0RBBgwFoEURGlhbm
+|VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhUAoRr4Fw4+XaiM9LZVMx5L4yys
+|uV8CFChLEEVY0hydVTUUGJGyPznftW7T
+|<DianeDSSSignByCarlInherit.cer
+
+***DianeRSASignByCarl.cer***
+
+|* Example DianeRSASignByCarl.cer
+|>DianeRSASignByCarl.cer
+|MIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024u1ZowkDANBgkqhkiG9w0BAQUFADASMRAwDg
+|YDVQQDEwdDYXJsUlNBMB4XDTk5MDgxOTA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEzERMA8G
+|A1UEAxMIRGlhbmVSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANb9uMBwxkwl7O
+|rP6ny7omL68OYyOlP/sZJaF/Qg4ZkkggrQ9nz7RMqLJwbxfiYDqXadz+ygLHCW8oNC9tS3
+|KAq7+L9KTBk/B9ugwWAet35n996xw2BJrEXX+MbvCDchk0fu8HM1crACxPMRw15H5Qq3g/
+|HbdGlki0QdlV3NKMCFAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF
+|4DAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQUjPPLdQ6NMf
+|bUKdpEknW4/u1POQwwHwYDVR0RBBgwFoEURGlhbmVSU0FAZXhhbXBsZS5jb20wDQYJKoZI
+|hvcNAQEFBQADgYEAfaYstXhC1nnzMf72QsoPEweSCRvgb7CRGPa/SvvMY3n7gb/dl8eQa8
+|sKNytBagOYxRs+MshFK4YBnBziNu8WwRqSuL5i+1M+SUcLxLnkK1imBoPwsqe7hX7VxtrO
+|nHsxctei6kGrasDdH7kURBjPhFdm6MXmuNwtsx8bKEM2dXo=
+|<DianeRSASignByCarl.cer
+
+From Section 2.4
+
+***CarlDSSCRLForAll.crl***
+
+|* Example CarlDSSCRLForAll.crl
+|>CarlDSSCRLForAll.crl
+|MIHYMIGZMAkGByqGSM44BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWj
+|BpMBMCAgDIFw05OTA4MjIwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05
+|OTA4MjIwNzAwMDBaMBMCAgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMD
+|BaMAkGByqGSM44BAMDLwAwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fv
+|ftok8yqDnDWh
+|<CarlDSSCRLForAll.crl
+
+
+
+Hoffman, Ed.                 Informational                    [Page 123]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***CarlDSSCRLForCarl.crl***
+
+|* Example CarlDSSCRLForCarl.crl
+|>CarlDSSCRLForCarl.crl
+|MIGDMEQwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTFw05OTA4MjUwNzAwMDBaMB
+|QwEgIBARcNOTkwODIyMDcwMDAwWjAJBgcqhkjOOAQDAzAAMC0CFQCzH8VPej3sdtVg+d55
+|IuxPsJD+lwIUWovDhLxmhxu/eYJbCl0H9rqpBSk=
+|<CarlDSSCRLForCarl.crl
+
+***CarlDSSCRLEmpty.crl***
+
+|* Example CarlDSSCRLEmpty.crl
+|>CarlDSSCRLEmpty.crl
+|MG0wLjAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MXDTk5MDgyMDA3MDAwMFowCQ
+|YHKoZIzjgEAwMwADAtAhRiPzYXMVguZ1B59QlLjK3Ua/RknwIVALU7TqFMe/0Pw42btv7D
+|XW/eZSh9
+|<CarlDSSCRLEmpty.crl
+
+***CarlRSACRLForAll.crl***
+
+|* Example CarlRSACRLForAll.crl
+|>CarlRSACRLForAll.crl
+|MIIBMzCBnTANBgkqhkiG9w0BAQQFADASMRAwDgYDVQQDEwdDYXJsUlNBFw05OTA4MjcwNz
+|AwMDBaMGkwIQIQRjRrx4AAVrwR024uxBCzsBcNOTkwODIyMDcwMDAwWjAhAhBGNGvHgABW
+|vBHTbi7VmjCQFw05OTA4MjIwNzAwMDBaMCECEEY0a8eAAFa8EdNuLs1dcdAXDTk5MDgyND
+|A3MDAwMFowDQYJKoZIhvcNAQEEBQADgYEAv7OXqlPwMiEWK3eSemu7l8jc6vH6ZhYwDrWe
+|XPCB1F6zbsGIa4zUXsVN+0deZvNdq+W0GDZgqE2cPInsbye/NVBxgcK5RFtiiRkSMal7mt
+|PMZssR2QsQR3etTyLZ5X8w8lv8lFGlWHY7H6hGph/2od5Voe0xiGmXDwjT1AxgWx4=
+|<CarlRSACRLForAll.crl
+
+***CarlRSACRLForCarl.crl***
+
+|* Example CarlRSACRLForCarl.crl
+|>CarlRSACRLForCarl.crl
+|MIHsMFcwDQYJKoZIhvcNAQEEBQAwEjEQMA4GA1UEAxMHQ2FybFJTQRcNOTkwODI1MDcwMD
+|AwWjAjMCECEEY0a8eAAFa8EdNuLp/yUCAXDTk5MDgyMjA3MDAwMFowDQYJKoZIhvcNAQEE
+|BQADgYEAIe8h1MEahZVJa8pFYtzXCf+pUS6O2UcY+vjlct1P7XR04/NlMmUoLJodV+XVJg
+|bq1eYjlYSNDome7psML84H96PRa4VMD//m3fzczXMsHn3csHHFTPwBblJXaR45Y98SIjDH
+|E1WUBW4qAKlbxCpmlGLONjPCK2NHJZ3z3nDuAFY=
+|<CarlRSACRLForCarl.crl
+
+***CarlRSACRLEmpty.crl***
+
+|* Example CarlRSACRLEmpty.crl
+|>CarlRSACRLEmpty.crl
+|MIHHMDIwDQYJKoZIhvcNAQEEBQAwEjEQMA4GA1UEAxMHQ2FybFJTQRcNOTkwODIwMDcwMD
+|AwWjANBgkqhkiG9w0BAQQFAAOBgQCpxSG4E3x087UR7ATzIEWGHgtuf4NtX/Q0dgZZJQ4E
+|PYgJiIE3xNwgmPoXgQs3lKy0j3tRiRSky3JzFAe8IpxAoQf8RHyFDwuI0e7hDq/2FnStoa
+
+
+
+Hoffman, Ed.                 Informational                    [Page 124]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|/BAHUAZOqlmvYLCKLblRlfpqe5OUUlCg72XoTn+LlayRjCDriglr6BOoBtyQ==
+|<CarlRSACRLEmpty.crl
+
+Rest of the sections
+
+***3.1.bin***
+
+|* Example 3.1.bin
+|>3.1.bin
+|MIAGCSqGSIb3DQEHAaCAJIAEBFRoaXMEGCBpcyBzb21lIHNhbXBsZSBjb250ZW50LgAAAA
+|AAAA==
+|<3.1.bin
+
+***3.2.bin***
+
+|* Example 3.2.bin
+|>3.2.bin
+|MCsGCSqGSIb3DQEHAaAeBBxUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQu
+|<3.2.bin
+
+***4.1.bin***
+
+|* Example 4.1.bin
+|>4.1.bin
+|MIIDlwYJKoZIhvcNAQcCoIIDiDCCA4QCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg
+|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ
+|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj
+|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB
+|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T
+|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV
+|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj
+|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0
+|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm
+|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm
+|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK
+|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij
+|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm
+|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R
+|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX
+|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MWMwYQIBATAYMBIxEDAOBgNV
+|BAMTB0NhcmxEU1MCAgDIMAcGBSsOAwIaMAkGByqGSM44BAMELjAsAhQJkf7r0mn1GLfXzV
+|X0geoqQmqtAwIUOgfMwyG+4RpLfz61Ddu6HOq8zYk=
+|<4.1.bin
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 125]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***4.2.bin***
+
+|* Example 4.2.bin
+|>4.2.bin
+|MIIDUgYJKoZIhvcNAQcCoIIDQzCCAz8CAQExCzAJBgUrDgMCGgUAMCsGCSqGSIb3DQEHAa
+|AeBBxUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuoIICMDCCAiwwggGVoAMCAQICEEY0
+|a8eAAFa8EdNuLsQQs7AwDQYJKoZIhvcNAQEFBQAwEjEQMA4GA1UEAxMHQ2FybFJTQTAeFw
+|05OTA5MTkwMTA4NDdaFw0zOTEyMzEyMzU5NTlaMBMxETAPBgNVBAMTCEFsaWNlUlNBMIGf
+|MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgiXM5jdj19eiHdjl/TrAFu1OD3g+3q9x9x3
+|UpDQUubRLfpoYm1NJvqlgp/Jfs+oJRDzCAvrFQnkZE8Sy72DLPxmhvB9mwYKy+7jQJahP1
+|9wUFk99eujVW2WH/GX/Jgeb4bOqHQHDvrG0sdJ8t+lU6uZl3AqZIUoxO81c4V3RXXwIDAQ
+|ABo4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCBsAwHwYDVR0jBBgwFoAU6eCQ
+|J6x4IHqa00zyQjdOIq6eOLswHQYDVR0OBBYEFHfStNG3TIqKo85Fnc7sPKA64/9QMB8GA1
+|UdEQQYMBaBFEFsaWNlUlNBQGV4YW1wbGUuY29tMA0GCSqGSIb3DQEBBQUAA4GBAD5wR6hI
+|zBNYj8pRcWtONhhdBH6AsY1NzMqjj8x9Vsi8z26zHFmpIKoFgahOJa2ncBR1L/XHm9EO6W
+|PSZLfGZm5zIVTf9LolXX1J05RrIjZ0c7hK7C9k7dM90qdCxeg3irTbn2fkvZ/5/nTv6vnu
+|Y2rYP0slCbXYGnau65vbSbAiMYHLMIHIAgEBMCYwEjEQMA4GA1UEAxMHQ2FybFJTQQIQRj
+|Rrx4AAVrwR024uxBCzsDAJBgUrDgMCGgUAMA0GCSqGSIb3DQEBAQUABIGALyOC0vMJX7gM
+|WOtOnb+JmoHldcSRPdPQ1Xu21f6UoYqs48SE9c1gTieV9s8AhnZ1Pyvw59QCZ6f1x40WBK
+|WztefZMvAk7+cgRNWfB8VTJPrOAR0PFxOnKpWdK+QDlRQL6TkNus5unJ4M6JjmVRPUaG/Q
+|B9eisWJM44+v/eDVXcc=
+|<4.2.bin
+
+***4.3.bin***
+
+|* Example 4.3.bin
+|>4.3.bin
+|MIIDdwYJKoZIhvcNAQcCoIIDaDCCA2QCAQExCTAHBgUrDgMCGjALBgkqhkiG9w0BBwGggg
+|LgMIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNTMB4X
+|DTk5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1Mwgg
+|G2MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauECE//
+|lOFzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny/dQ6
+|iLVPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDiR6Ya
+|RWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF3dm1
+|nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgvMAF8
+|bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgFzjuV
+|p1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09B41b
+|Y8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YUeyxD
+|KE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMC
+|BsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sobPjwf
+|ftQ3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkGByqG
+|SM44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4hBSW0
+|NevTFjMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBgcqhkjO
+|OAQDBC4wLAIUBvvHKiTVNIn3i7X9cySlhsgPWmwCFGZpGbxoWNGNsZ1SP9oUiA39yaG4
+|<4.3.bin
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 126]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***4.4.bin***
+
+|* Example 4.4.bin
+|>4.4.bin
+|MIILDQYJKoZIhvcNAQcCoIIK/jCCCvoCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg
+|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCB68wggIsMIIBlaADAgECAhBGNGvH
+|gABWvBHTbi7EELOwMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNVBAMTB0NhcmxSU0EwHhcNOT
+|kwOTE5MDEwODQ3WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZVJTQTCBnzAN
+|BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4IlzOY3Y9fXoh3Y5f06wBbtTg94Pt6vcfcd1KQ
+|0FLm0S36aGJtTSb6pYKfyX7PqCUQ8wgL6xUJ5GRPEsu9gyz8ZobwfZsGCsvu40CWoT9fcF
+|BZPfXro1Vtlh/xl/yYHm+Gzqh0Bw76xtLHSfLfpVOrmZdwKmSFKMTvNXOFd0V18CAwEAAa
+|OBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgbAMB8GA1UdIwQYMBaAFOngkCes
+|eCB6mtNM8kI3TiKunji7MB0GA1UdDgQWBBR30rTRt0yKiqPORZ3O7DygOuP/UDAfBgNVHR
+|EEGDAWgRRBbGljZVJTQUBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOBgQA+cEeoSMwT
+|WI/KUXFrTjYYXQR+gLGNTczKo4/MfVbIvM9usxxZqSCqBYGoTiWtp3AUdS/1x5vRDulj0m
+|S3xmZucyFU3/S6JV19SdOUayI2dHO4SuwvZO3TPdKnQsXoN4q0259n5L2f+f507+r57mNq
+|2D9LJQm12Bp2ruub20mwIjCCApswggJaoAMCAQICAQEwCQYHKoZIzjgEAzASMRAwDgYDVQ
+|QDEwdDYXJsRFNTMB4XDTk5MDgxNjIyNTA1MFoXDTM5MTIzMTIzNTk1OVowEjEQMA4GA1UE
+|AxMHQ2FybERTUzCCAbcwggErBgcqhkjOOAQBMIIBHgKBgQC2SRg+ikTBKXGUTAHEEsF6ec
+|tUTasegfvGTLMOlAkG6wHUschxS8dFwFAlXZz82uRt0+KGSISCfboVlUoW9kbt3faY0rt+
+|igqKuhZ7uVABSJOL6yUVUZdV3I9TDhCpUPxwt80wVP3a3qiqIrWhr4vMAojni3Bfua3hCN
+|RtKS3W6QIVAN3BL99Tzgs0YHc+AqS/il2YuRDVAoGADO5Xm0u92rYHanQ3T1V/ne28YQ3r
+|Rlk8VgsrWwyRzqViUmnK4W0+vb/+4be5K2E8rcuuReMGrIwinZxEhwvHzfAc2bVOXXPerw
+|7JHVpR9U9EeTVac6p/RlEfqUIWnEjrinlhtNUvUyJEYx+GuKNYBiX4KcDvuuB18ELEY2VS
+|mwoDgYUAAoGBAJmHdCcDZqCxwK3cLHW74WxEnNohbU1HbbFiCenYrh7yOrSUsaOOeptxTg
+|CUybQlTrlglhkkAfNiDP51wPvO2GgA4/3VcE/fI5YZBpT0sWGPOlexCBGkCyYl8FJ2geoL
+|Yg2VKuaGunKyp1CDC6onzRupTYma140YOYQ/i8VWTYB6o0IwQDAPBgNVHRMBAf8EBTADAQ
+|H/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUcEQ+gi5vh95K03XjPSC8QyuT8R8wCQYH
+|KoZIzjgEAwMwADAtAhRrqfBOelp54/m+PSvJBjfpERehEwIVAI80aSqLsTwDeZQyTRIfzo
+|n7RrI7MIIC3DCCApugAwIBAgICAMgwCQYHKoZIzjgEAzASMRAwDgYDVQQDEwdDYXJsRFNT
+|MB4XDTk5MDgxNzAxMTA0OVoXDTM5MTIzMTIzNTk1OVowEzERMA8GA1UEAxMIQWxpY2VEU1
+|MwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEAgY3N7YPqCp45PsJIKKPkR5PdDteoDuxTxauE
+|CE//lOFzSH4M1vNESNH+n6+koYkv4dkwyDbeP5u/t0zcX2mK5HXQNwyRCJWb3qde+fz0ny
+|/dQ6iLVPE/sAcIR01diMPDtbPjVQh11Tl2EMR4vf+dsISXN/LkURu15AmWXPN+W9sCFQDi
+|R6YaRWa4E8baj7g3IStii/eTzQKBgCY40BSJMqo5+z5t2UtZakx2IzkEAjVc8ssaMMMeUF
+|3dm1nizaoFPVjAe6I2uG4Hr32KQiWn9HXPSgheSz6Q+G3qnMkhijt2FOnOLl2jB80jhbgv
+|MAF8bUmJEYk2RL34yJVKU1a14vlz7BphNh8Rf8K97dFQ/5h0wtGBSmA5ujY5A4GEAAKBgF
+|zjuVp1FJYLqXrd4z+p7Kxe3L23ExE0phaJKBEj2TSGZ3V1ExI9Q1tv5VG/+onyohs+JH09
+|B41bY8i7RaWgSuOF1s4GgD/oI34a8iSrUxq4Jw0e7wi/ZhSAXGKsZfoVi/G7NNTSljf2YU
+|eyxDKE8H5BQP1Gp2NOM/Kl4vTyg+W4o4GBMH8wDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8E
+|BAMCBsAwHwYDVR0jBBgwFoAUcEQ+gi5vh95K03XjPSC8QyuT8R8wHQYDVR0OBBYEFL5sob
+|PjwfftQ3CkzhMB4v3jl/7NMB8GA1UdEQQYMBaBFEFsaWNlRFNTQGV4YW1wbGUuY29tMAkG
+|ByqGSM44BAMDMAAwLQIUVQykGR9CK4lxIjONg2q1PWdrv0UCFQCfYVNSVAtcst3a53Yd4h
+|BSW0NevaGB2zCB2DCBmTAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MXDTk5MDgy
+|NzA3MDAwMFowaTATAgIAyBcNOTkwODIyMDcwMDAwWjATAgIAyRcNOTkwODIyMDcwMDAwWj
+|ATAgIA0xcNOTkwODIyMDcwMDAwWjATAgIA0hcNOTkwODIyMDcwMDAwWjATAgIA1BcNOTkw
+|ODI0MDcwMDAwWjAJBgcqhkjOOAQDAy8AMCwCFH5lUnYz/jRzF9H3lvmg1NhtXH09AhQCel
+|u31VsYwc+H737aJPMqg5w1oTGCAiowggImAgEBMBgwEjEQMA4GA1UEAxMHQ2FybERTUwIC
+
+
+
+Hoffman, Ed.                 Informational                    [Page 127]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|AMgwBwYFKw4DAhqgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBT
+|EPFw0wMzA1MTQxNTM5MDBaMCMGCSqGSIb3DQEJBDEWBBRAauwIUnm6bhYCLZ4GKcAilofd
+|SDAJBgcqhkjOOAQDBC4wLAIUO6XgStttWOAZ0QAcT0SaV3pxZmgCFBoRmNYfH680gQHevo
+|vctqhqkWkToYIBYjA+BgsqhkiG9w0BCRACBDEvMC0MIENvbnRlbnQgSGludHMgRGVzY3Jp
+|cHRpb24gQnVmZmVyBgkqhkiG9w0BBwEwggEeBgkqhkiG9w0BCQYxggEPMIIBCwIBATAmMB
+|IxEDAOBgNVBAMTB0NhcmxSU0ECEEY0a8eAAFa8EdNuLsQQs7AwBwYFKw4DAhqgQzAcBgkq
+|hkiG9w0BCQUxDxcNMDMwNTE0MTUzOTAwWjAjBgkqhkiG9w0BCQQxFgQUAl9JTjmYUIWzZt
+|OKH3ueaar72DMwDQYJKoZIhvcNAQEBBQAEgYBtqiAk7XrupV6H3XUfK1QQZfTOm7EseHS8
+|ixxgtduLA55J8it/k249iRTJ42v09n12rj5YH5u7vHwwGU4Q9wLxi1u025q7k7QY0MwryZ
+|GprdlG+GWp4nGV0NROH810b4LoN29aPcvH1F/CgBva04RAaF9WmmL1Ow1sM8PtZz9Dvw==
+|<4.4.bin
+
+***4.5.bin***
+
+|* Example 4.5.bin
+|>4.5.bin
+|MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCAJIAEBF
+|RoaXMEGCBpcyBzb21lIHNhbXBsZSBjb250ZW50LgAAAAAAAKCAMIIB6zCCAVSgAwIBAgIQ
+|RjRrx4AAVrwR024un/JQIDANBgkqhkiG9w0BAQUFADASMRAwDgYDVQQDEwdDYXJsUlNBMB
+|4XDTk5MDgxODA3MDAwMFoXDTM5MTIzMTIzNTk1OVowEjEQMA4GA1UEAxMHQ2FybFJTQTCB
+|nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Ev/GLgkV/R3/25ze5NxXLwzGpKSciPYQU
+|bQzRE6BLOOr4KdvVEeF3rydiwrhjmnvdeNGlPs5ADV6OyiNrHt4lDiMgmKP5+ZJY+4Tqu5
+|fdWWZdoWoMW+Dq5EW+9e9Kcpy4LdrETpqpOUKQ74GNbIV17ydsTyEWA4uRs8HZfJavECAw
+|EAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFOng
+|kCeseCB6mtNM8kI3TiKunji7MA0GCSqGSIb3DQEBBQUAA4GBALee1ATT7Snk/4mJFS5M2w
+|zwSA8yYe7EBOwSXS3/D2RZfgrD7Rj941ZAN6cHtfA4EmFQ7e/dP+MLuGGlpJs85p6cVJq2
+|ldbabDu1LUU1nUkBdvq5uTH5+WsSU6D1FGCbfco+8lNrsDdvreZ019v6WuoUQWNdzb7IDs
+|Haao1TNBgCMIICLDCCAZWgAwIBAgIQRjRrx4AAVrwR024uxBCzsDANBgkqhkiG9w0BAQUF
+|ADASMRAwDgYDVQQDEwdDYXJsUlNBMB4XDTk5MDkxOTAxMDg0N1oXDTM5MTIzMTIzNTk1OV
+|owEzERMA8GA1UEAxMIQWxpY2VSU0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCJ
+|czmN2PX16Id2OX9OsAW7U4PeD7er3H3HdSkNBS5tEt+mhibU0m+qWCn8l+z6glEPMIC+sV
+|CeRkTxLLvYMs/GaG8H2bBgrL7uNAlqE/X3BQWT3166NVbZYf8Zf8mB5vhs6odAcO+sbSx0
+|ny36VTq5mXcCpkhSjE7zVzhXdFdfAgMBAAGjgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDw
+|EB/wQEAwIGwDAfBgNVHSMEGDAWgBTp4JAnrHggeprTTPJCN04irp44uzAdBgNVHQ4EFgQU
+|d9K00bdMioqjzkWdzuw8oDrj/1AwHwYDVR0RBBgwFoEUQWxpY2VSU0FAZXhhbXBsZS5jb2
+|0wDQYJKoZIhvcNAQEFBQADgYEAPnBHqEjME1iPylFxa042GF0EfoCxjU3MyqOPzH1WyLzP
+|brMcWakgqgWBqE4lradwFHUv9ceb0Q7pY9Jkt8ZmbnMhVN/0uiVdfUnTlGsiNnRzuErsL2
+|Tt0z3Sp0LF6DeKtNufZ+S9n/n+dO/q+e5jatg/SyUJtdgadq7rm9tJsCIAADGByzCByAIB
+|ATAmMBIxEDAOBgNVBAMTB0NhcmxSU0ECEEY0a8eAAFa8EdNuLsQQs7AwCQYFKw4DAhoFAD
+|ANBgkqhkiG9w0BAQEFAASBgC8jgtLzCV+4DFjrTp2/iZqB5XXEkT3T0NV7ttX+lKGKrOPE
+|hPXNYE4nlfbPAIZ2dT8r8OfUAmen9ceNFgSls7Xn2TLwJO/nIETVnwfFUyT6zgEdDxcTpy
+|qVnSvkA5UUC+k5DbrObpyeDOiY5lUT1Ghv0AfXorFiTOOPr/3g1V3HAAAAAAAA
+|<4.5.bin
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 128]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***4.6.bin***
+
+|* Example 4.6.bin
+|>4.6.bin
+|MIIFtwYJKoZIhvcNAQcCoIIFqDCCBaQCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg
+|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCBJwwggG4MIIBd6ADAgECAgIA0jAJ
+|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDIwODEwWhcNMzkxMj
+|MxMjM1OTU5WjATMREwDwYDVQQDEwhEaWFuZURTUzCBkzAJBgcqhkjOOAQBA4GFAAKBgQCg
+|ABd4LO5+gVMuLmEID6GbUVIa2lmocy8SJbYIy8rvKkR2ilIJ6r0FItUP9v1G16+ZOAkOE8
+|tPLN0cNPccvyX/I9M7WeeClze+MSTYGMjzSTlbt+LlJ378jEVyW34+j2hN3UZ6Ir6O/8za
+|OSmjOeWfQ+lVyddbpoFnzMCqzS7FI6OBgTB/MAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BA
+|QDAgbAMB8GA1UdIwQYMBaAFHBEPoIub4feStN14z0gvEMrk/EfMB0GA1UdDgQWBBRkMJl9
+|XNxFC5k6Ui8Wv1hQ3c4rGDAfBgNVHREEGDAWgRREaWFuZURTU0BleGFtcGxlLmNvbTAJBg
+|cqhkjOOAQDAzAAMC0CFQChGvgXDj5dqIz0tlUzHkvjLKy5XwIUKEsQRVjSHJ1VNRQYkbI/
+|Od+1btMwggLcMIICm6ADAgECAgIAyDAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1
+|MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMjMxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURT
+|UzCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4
+|QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2TDINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSf
+|L91DqItU8T+wBwhHTV2Iw8O1s+NVCHXVOXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAO
+|JHphpFZrgTxtqPuDchK2KL95PNAoGAJjjQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5Q
+|Xd2bWeLNqgU9WMB7oja4bgevfYpCJaf0dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC
+|8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGmE2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGA
+|XOO5WnUUlgupet3jP6nsrF7cvbcTETSmFokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT
+|0HjVtjyLtFpaBK44XWzgaAP+gjfhryJKtTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/Zh
+|R7LEMoTwfkFA/UanY04z8qXi9PKD5bijgYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/w
+|QEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyh
+|s+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0RBBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQ
+|YHKoZIzjgEAwMwADAtAhRVDKQZH0IriXEiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3i
+|EFJbQ169MYHGMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGjAJBg
+|cqhkjOOAQDBC4wLAIUSCTei4XyFq/sgmGpVNAtBKHMWk8CFBft1XcC7nUT2BC9PZcXIIi7
+|/XuBMGECAQEwGDASMRAwDgYDVQQDEwdDYXJsRFNTAgIA0jAHBgUrDgMCGjAJBgcqhkjOOA
+|QDBC4wLAIUFf+BTYytgE6bNVgEN25jbulbg/oCFAZ+WE4rMYRB7Ul5OD530qaMdQgh
+|<4.6.bin
+
+***4.7.bin***
+
+|* Example 4.7.bin
+|>4.7.bin
+|MIIDlAYJKoZIhvcNAQcCoIIDhTCCA4ECAQMxCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg
+|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ
+|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj
+|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB
+|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T
+|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV
+|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj
+|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0
+|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm
+|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm
+
+
+
+Hoffman, Ed.                 Informational                    [Page 129]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK
+|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij
+|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm
+|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R
+|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX
+|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MWAwXgIBA4AUvmyhs+PB9+1D
+|cKTOEwHi/eOX/s0wBwYFKw4DAhowCQYHKoZIzjgEAwQvMC0CFQCJw2t7VvfDEgBl8Tf1xF
+|gXjRFXgwIUCw9DOqrs3nphLIyc9UGZpzwgw7c=
+|<4.7.bin
+
+***4.8.eml***
+
+|* Example 4.8.eml
+|>4.8.eml
+|TUlNRS1WZXJzaW9uOiAxLjAKVG86IFVzZXIyQGV4YW1wbGVzLmNvbQpGcm9tOiBhbGljZU
+|Rzc0BleGFtcGxlcy5jb20KU3ViamVjdDogRXhhbXBsZSA0LjgKTWVzc2FnZS1JZDogPDAy
+|MDkwNjAwMjU1MDMwMC4yNDlAZXhhbXBsZXMuY29tPgpEYXRlOiBGcmksIDA2IFNlcCAyMD
+|AyIDAwOjI1OjIxIC0wMzAwIApDb250ZW50LVR5cGU6IG11bHRpcGFydC9zaWduZWQ7CiAg
+|ICBtaWNhbGc9U0hBMTsKICAgIGJvdW5kYXJ5PSItLS0tPV9OZXh0Qm91bmRyeV9fX19Gcm
+|ksXzA2X1NlcF8yMDAyXzAwOjI1OjIxIjsKICAgIHByb3RvY29sPSJhcHBsaWNhdGlvbi9w
+|a2NzNy1zaWduYXR1cmUiCgpUaGlzIGlzIGEgbXVsdGktcGFydCBtZXNzYWdlIGluIE1JTU
+|UgZm9ybWF0LgoKLS0tLS0tPV9OZXh0Qm91bmRyeV9fX19GcmksXzA2X1NlcF8yMDAyXzAw
+|OjI1OjIxCgpUaGlzIGlzIHNvbWUgc2FtcGxlIGNvbnRlbnQuCi0tLS0tLT1fTmV4dEJvdW
+|5kcnlfX19fRnJpLF8wNl9TZXBfMjAwMl8wMDoyNToyMQpDb250ZW50LVR5cGU6IGFwcGxp
+|Y2F0aW9uL3BrY3M3LXNpZ25hdHVyZTsgbmFtZT1zbWltZS5wN3MKQ29udGVudC1UcmFuc2
+|Zlci1FbmNvZGluZzogYmFzZTY0CkNvbnRlbnQtRGlzcG9zaXRpb246IGF0dGFjaG1lbnQ7
+|IGZpbGVuYW1lPXNtaW1lLnA3cwoKTUlJRGR3WUpLb1pJaHZjTkFRY0NvSUlEYURDQ0EyUU
+|NBUUV4Q1RBSEJnVXJEZ01DR2pBTEJna3Foa2lHOXcwQkJ3R2dnZ0xnTUlJQwozRENDQXB1
+|Z0F3SUJBZ0lDQU1nd0NRWUhLb1pJempnRUF6QVNNUkF3RGdZRFZRUURFd2REWVhKc1JGTl
+|RNQjRYRFRrNU1EZ3hOekF4Ck1UQTBPVm9YRFRNNU1USXpNVEl6TlRrMU9Wb3dFekVSTUE4
+|R0ExVUVBeE1JUVd4cFkyVkVVMU13Z2dHMk1JSUJLd1lIS29aSXpqZ0UKQVRDQ0FSNENnWU
+|VBZ1kzTjdZUHFDcDQ1UHNKSUtLUGtSNVBkRHRlb0R1eFR4YXVFQ0UvL2xPRnpTSDRNMXZO
+|RVNOSCtuNitrb1lrdgo0ZGt3eURiZVA1dS90MHpjWDJtSzVIWFFOd3lSQ0pXYjNxZGUrZn
+|owbnkvZFE2aUxWUEUvc0FjSVIwMWRpTVBEdGJQalZRaDExVGwyCkVNUjR2Zitkc0lTWE4v
+|TGtVUnUxNUFtV1hQTitXOXNDRlFEaVI2WWFSV2E0RThiYWo3ZzNJU3RpaS9lVHpRS0JnQ1
+|k0MEJTSk1xbzUKK3o1dDJVdFpha3gySXprRUFqVmM4c3NhTU1NZVVGM2RtMW5pemFvRlBW
+|akFlNkkydUc0SHIzMktRaVduOUhYUFNnaGVTejZRK0czcQpuTWtoaWp0MkZPbk9MbDJqQj
+|gwamhiZ3ZNQUY4YlVtSkVZazJSTDM0eUpWS1UxYTE0dmx6N0JwaE5oOFJmOEs5N2RGUS81
+|aDB3dEdCClNtQTV1alk1QTRHRUFBS0JnRnpqdVZwMUZKWUxxWHJkNHorcDdLeGUzTDIzRX
+|hFMHBoYUpLQkVqMlRTR1ozVjFFeEk5UTF0djVWRy8KK29ueW9ocytKSDA5QjQxYlk4aTdS
+|YVdnU3VPRjFzNEdnRC9vSTM0YThpU3JVeHE0SncwZTd3aS9aaFNBWEdLc1pmb1ZpL0c3Tk
+|5UUwpsamYyWVVleXhES0U4SDVCUVAxR3AyTk9NL0tsNHZUeWcrVzRvNEdCTUg4d0RBWURW
+|UjBUQVFIL0JBSXdBREFPQmdOVkhROEJBZjhFCkJBTUNCc0F3SHdZRFZSMGpCQmd3Rm9BVW
+|NFUStnaTV2aDk1SzAzWGpQU0M4UXl1VDhSOHdIUVlEVlIwT0JCWUVGTDVzb2JQandmZnQK
+|UTNDa3poTUI0djNqbC83Tk1COEdBMVVkRVFRWU1CYUJGRUZzYVdObFJGTlRRR1Y0WVcxd2
+|JHVXVZMjl0TUFrR0J5cUdTTTQ0QkFNRApNQUF3TFFJVVZReWtHUjlDSzRseElqT05nMnEx
+|UFdkcnYwVUNGUUNmWVZOU1ZBdGNzdDNhNTNZZDRoQlNXME5ldlRGak1HRUNBUUV3CkdEQV
+|NNUkF3RGdZRFZRUURFd2REWVhKc1JGTlRBZ0lBeURBSEJnVXJEZ01DR2pBSkJnY3Foa2pP
+
+
+
+Hoffman, Ed.                 Informational                    [Page 130]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|T0FRREJDNHdMQUlVTS9tR2Y2Z2sKZ3A5WjBYdFJkR2ltSmVCL0J4VUNGR0ZGSnF3WVJ0MV
+|dZY0lPUW9HaWFvd3FHelZJCgotLS0tLS09X05leHRCb3VuZHJ5X19fX0ZyaSxfMDZfU2Vw
+|XzIwMDJfMDA6MjU6MjEtLQo=
+|<4.8.eml
+
+***4.9.eml***
+
+|* Example 4.9.eml
+|>4.9.eml
+|TUlNRS1WZXJzaW9uOiAxLjAKVG86IFVzZXIyQGV4YW1wbGVzLmNvbQpGcm9tOiBhbGljZU
+|Rzc0BleGFtcGxlcy5jb20KU3ViamVjdDogRXhhbXBsZSA0LjkKTWVzc2FnZS1JZDogPDAy
+|MTAzMTE2NDU0MDMwMC4zMDRAZXhhbXBsZXMuY29tPgpEYXRlOiBUaHUsIDMxIE9jdCAyMD
+|AyIDE2OjQ1OjE0IC0wMzAwIApDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL3BrY3M3LW1p
+|bWU7IHNtaW1lLXR5cGU9c2lnbmVkLWRhdGE7CiAgICBuYW1lPXNtaW1lLnA3bQpDb250ZW
+|50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKQ29udGVudC1EaXNwb3NpdGlvbjogYXR0
+|YWNobWVudDsgZmlsZW5hbWU9c21pbWUucDdtCgpNSUlEbVFZSktvWklodmNOQVFjQ29JSU
+|RpakNDQTRZQ0FRRXhDVEFIQmdVckRnTUNHakF0QmdrcWhraUc5dzBCQndHZ0lBUWVEUXBV
+|CmFHbHpJR2x6SUhOdmJXVWdjMkZ0Y0d4bElHTnZiblJsYm5RdW9JSUM0RENDQXR3d2dnS2
+|JvQU1DQVFJQ0FnRElNQWtHQnlxR1NNNDQKQkFNd0VqRVFNQTRHQTFVRUF4TUhRMkZ5YkVS
+|VFV6QWVGdzA1T1RBNE1UY3dNVEV3TkRsYUZ3MHpPVEV5TXpFeU16VTVOVGxhTUJNeApFVE
+|FQQmdOVkJBTVRDRUZzYVdObFJGTlRNSUlCdGpDQ0FTc0dCeXFHU000NEJBRXdnZ0VlQW9H
+|QkFJR056ZTJENmdxZU9UN0NTQ2lqCjVFZVQzUTdYcUE3c1U4V3JoQWhQLzVUaGMwaCtETm
+|J6UkVqUi9wK3ZwS0dKTCtIWk1NZzIzaitidjdkTTNGOXBpdVIxMERjTWtRaVYKbTk2blh2
+|bjg5Sjh2M1VPb2kxVHhQN0FIQ0VkTlhZakR3N1d6NDFVSWRkVTVkaERFZUwzL25iQ0Vsem
+|Z5NUZFYnRlUUpsbHp6Zmx2YgpBaFVBNGtlbUdrVm11QlBHMm8rNE55RXJZb3YzazgwQ2dZ
+|QW1PTkFVaVRLcU9mcytiZGxMV1dwTWRpTTVCQUkxWFBMTEdqRERIbEJkCjNadFo0czJxQl
+|QxWXdIdWlOcmh1QjY5OWlrSWxwL1IxejBvSVhrcytrUGh0NnB6SklZbzdkaFRwemk1ZG93
+|Zk5JNFc0THpBQmZHMUoKaVJHSk5rUzkrTWlWU2xOV3RlTDVjK3dhWVRZZkVYL0N2ZTNSVV
+|ArWWRNTFJnVXBnT2JvMk9RT0JoQUFDZ1lCYzQ3bGFkUlNXQzZsNgozZU0vcWV5c1h0eTl0
+|eE1STktZV2lTZ1JJOWswaG1kMWRSTVNQVU5iYitWUnYvcUo4cUliUGlSOVBRZU5XMlBJdT
+|BXbG9FcmpoZGJPCkJvQS82Q04rR3ZJa3ExTWF1Q2NOSHU4SXYyWVVnRnhpckdYNkZZdnh1
+|elRVMHBZMzltRkhzc1F5aFBCK1FVRDlScWRqVGpQeXBlTDAKOG9QbHVLT0JnVEIvTUF3R0
+|ExVWRFd0VCL3dRQ01BQXdEZ1lEVlIwUEFRSC9CQVFEQWdiQU1COEdBMVVkSXdRWU1CYUFG
+|SEJFUG9JdQpiNGZlU3ROMTR6MGd2RU1yay9FZk1CMEdBMVVkRGdRV0JCUytiS0d6NDhIMz
+|dVTndwTTRUQWVMOTQ1Zit6VEFmQmdOVkhSRUVHREFXCmdSUkJiR2xqWlVSVFUwQmxlR0Z0
+|Y0d4bExtTnZiVEFKQmdjcWhrak9PQVFEQXpBQU1DMENGRlVNcEJrZlFpdUpjU0l6allOcX
+|RUMW4KYTc5RkFoVUFuMkZUVWxRTFhMTGQydWQySGVJUVVsdERYcjB4WXpCaEFnRUJNQmd3
+|RWpFUU1BNEdBMVVFQXhNSFEyRnliRVJUVXdJQwpBTWd3QndZRkt3NERBaG93Q1FZSEtvWk
+|l6amdFQXdRdU1Dd0NGRDFjU1c2TElVRnplWGxlM1lJNVNLU0Jlci9zQWhRbUNxN3MvQ1RG
+|CkhPRWpnQVNlVWpiTXB4NWc2QT09Cg==
+|<4.9.eml
+
+***4.10.bin***
+
+|* Example 4.10.bin
+|>4.10.bin
+|MIIH/wYJKoZIhvcNAQcCoIIH8DCCB+wCAQExCTAHBgUrDgMCGjArBgkqhkiG9w0BBwGgHg
+|QcVGhpcyBpcyBzb21lIHNhbXBsZSBjb250ZW50LqCCAuAwggLcMIICm6ADAgECAgIAyDAJ
+
+
+
+Hoffman, Ed.                 Informational                    [Page 131]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj
+|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB
+|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T
+|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV
+|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj
+|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0
+|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm
+|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm
+|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK
+|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij
+|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm
+|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R
+|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX
+|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169MYIEyTCCBMUCAQEwGDASMRAw
+|DgYDVQQDEwdDYXJsRFNTAgIAyDAHBgUrDgMCGqCCBF8wGAYJKoZIhvcNAQkDMQsGCSqGSI
+|b3DQEHATAjBgkqhkiG9w0BCQQxFgQUQGrsCFJ5um4WAi2eBinAIpaH3UgwOAYDKqszMTEE
+|L1RoaXMgaXMgYSB0ZXN0IEdlbmVyYWwgQVNOIEF0dHJpYnV0ZSwgbnVtYmVyIDEuMD4GCy
+|qGSIb3DQEJEAIEMS8wLQwgQ29udGVudCBIaW50cyBEZXNjcmlwdGlvbiBCdWZmZXIGCSqG
+|SIb3DQEHATBKBgkqhkiG9w0BCQ8xPTA7MAcGBSoDBAUGMDAGBioDBAUGTQQmU21pbWUgQ2
+|FwYWJpbGl0aWVzIHBhcmFtZXRlcnMgYnVmZmVyIDIwbQYLKoZIhvcNAQkQAgIxXjFcAgEB
+|BgcqAwQFBgcIExtUSElTIElTIEEgUFJJVkFDWSBNQVJLIFRFU1QxMTAvgAgqAwQFBgeGeK
+|EjEyFUSElTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4wbwYLKoZIhvcNAQkQAgox
+|YDBeBgUqAwQFBgQrQ29udGVudCBSZWZlcmVuY2UgQ29udGVudCBJZGVudGlmaWVyIEJ1Zm
+|ZlcgQoQ29udGVudCBSZWZlcmVuY2UgU2lnbmF0dXJlIFZhbHVlIEJ1ZmZlcjBzBgsqhkiG
+|9w0BCRACCzFkoGIwWjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDVVTIEdvdmVybm1lbnQxET
+|APBgNVBAsTCFZEQSBTaXRlMQwwCgYDVQQLEwNWREExEjAQBgNVBAMTCURhaXN5IFJTQQIE
+|ClVEMzCB/AYLKoZIhvcNAQkQAgMxgewwgekwgeYEBzU3MzgyOTkYDzE5OTkwMzExMTA0ND
+|MzWqGByTCBxqRhMF8xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1VUyBHb3Zlcm5tZW50MREw
+|DwYDVQQLEwhWREEgU2l0ZTEMMAoGA1UECxMDVkRBMRcwFQYDVQQDEw5CdWdzIEJ1bm55IE
+|RTQaRhMF8xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1VUyBHb3Zlcm5tZW50MREwDwYDVQQL
+|EwhWREEgU2l0ZTEMMAoGA1UECxMDVkRBMRcwFQYDVQQDEw5FbG1lciBGdWRkIERTQTCCAQ
+|IGCyqGSIb3DQEJEAIJMYHyMIHvMXICAQEGByoDBAUGBwkTJkVRVUlWQUxFTlQgVEhJUyBJ
+|UyBBIFBSSVZBQ1kgTUFSSyBURVNUMTwwOoAIKgMEBQYHhnihLhMsRVFVSVZBTEVOVCBUSE
+|lTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4xeQIBAQYHKgMEBQYHChMtRVFVSVZB
+|TEVOVCBUSElTIElTIEEgU0VDT05EIFBSSVZBQ1kgTUFSSyBURVNUMTwwOoAIKgMEBQYHhn
+|ihLhMsRVFVSVZBTEVOVCBUSElTIElTIEEgVEVTVCBTRUNVUklUWS1DQVRFR09SWS4wCQYH
+|KoZIzjgEAwQvMC0CFQC8MzdlxPdwXBdJE6pMhcq7UpFIWQIUY5aiFIvPV96wSF9sZN2EBE
+|lfHMo=
+|<4.10.bin
+
+***4.11.bin***
+
+|* Example 4.11.bin
+|>4.11.bin
+|MIIGiAYJKoZIhvcNAQcCoIIGeTCCBnUCAQExADALBgkqhkiG9w0BBwGgggV/MIICmzCCAl
+|qgAwIBAgIBATAJBgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE2MjI1
+|MDUwWhcNMzkxMjMxMjM1OTU5WjASMRAwDgYDVQQDEwdDYXJsRFNTMIIBtzCCASsGByqGSM
+|44BAEwggEeAoGBALZJGD6KRMEpcZRMAcQSwXp5y1RNqx6B+8ZMsw6UCQbrAdSxyHFLx0XA
+
+
+
+Hoffman, Ed.                 Informational                    [Page 132]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+|UCVdnPza5G3T4oZIhIJ9uhWVShb2Ru3d9pjSu36KCoq6Fnu5UAFIk4vrJRVRl1Xcj1MOEK
+|lQ/HC3zTBU/dreqKoitaGvi8wCiOeLcF+5reEI1G0pLdbpAhUA3cEv31POCzRgdz4CpL+K
+|XZi5ENUCgYAM7lebS73atgdqdDdPVX+d7bxhDetGWTxWCytbDJHOpWJSacrhbT69v/7ht7
+|krYTyty65F4wasjCKdnESHC8fN8BzZtU5dc96vDskdWlH1T0R5NVpzqn9GUR+pQhacSOuK
+|eWG01S9TIkRjH4a4o1gGJfgpwO+64HXwQsRjZVKbCgOBhQACgYEAmYd0JwNmoLHArdwsdb
+|vhbESc2iFtTUdtsWIJ6diuHvI6tJSxo456m3FOAJTJtCVOuWCWGSQB82IM/nXA+87YaADj
+|/dVwT98jlhkGlPSxYY86V7EIEaQLJiXwUnaB6gtiDZUq5oa6crKnUIMLqifNG6lNiZrXjR
+|g5hD+LxVZNgHqjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1Ud
+|DgQWBBRwRD6CLm+H3krTdeM9ILxDK5PxHzAJBgcqhkjOOAQDAzAAMC0CFGup8E56Wnnj+b
+|49K8kGN+kRF6ETAhUAjzRpKouxPAN5lDJNEh/OiftGsjswggLcMIICm6ADAgECAgIAyDAJ
+|BgcqhkjOOAQDMBIxEDAOBgNVBAMTB0NhcmxEU1MwHhcNOTkwODE3MDExMDQ5WhcNMzkxMj
+|MxMjM1OTU5WjATMREwDwYDVQQDEwhBbGljZURTUzCCAbYwggErBgcqhkjOOAQBMIIBHgKB
+|gQCBjc3tg+oKnjk+wkgoo+RHk90O16gO7FPFq4QIT/+U4XNIfgzW80RI0f6fr6ShiS/h2T
+|DINt4/m7+3TNxfaYrkddA3DJEIlZvep175/PSfL91DqItU8T+wBwhHTV2Iw8O1s+NVCHXV
+|OXYQxHi9/52whJc38uRRG7XkCZZc835b2wIVAOJHphpFZrgTxtqPuDchK2KL95PNAoGAJj
+|jQFIkyqjn7Pm3ZS1lqTHYjOQQCNVzyyxowwx5QXd2bWeLNqgU9WMB7oja4bgevfYpCJaf0
+|dc9KCF5LPpD4beqcySGKO3YU6c4uXaMHzSOFuC8wAXxtSYkRiTZEvfjIlUpTVrXi+XPsGm
+|E2HxF/wr3t0VD/mHTC0YFKYDm6NjkDgYQAAoGAXOO5WnUUlgupet3jP6nsrF7cvbcTETSm
+|FokoESPZNIZndXUTEj1DW2/lUb/6ifKiGz4kfT0HjVtjyLtFpaBK44XWzgaAP+gjfhryJK
+|tTGrgnDR7vCL9mFIBcYqxl+hWL8bs01NKWN/ZhR7LEMoTwfkFA/UanY04z8qXi9PKD5bij
+|gYEwfzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIGwDAfBgNVHSMEGDAWgBRwRD6CLm
+|+H3krTdeM9ILxDK5PxHzAdBgNVHQ4EFgQUvmyhs+PB9+1DcKTOEwHi/eOX/s0wHwYDVR0R
+|BBgwFoEUQWxpY2VEU1NAZXhhbXBsZS5jb20wCQYHKoZIzjgEAwMwADAtAhRVDKQZH0IriX
+|EiM42DarU9Z2u/RQIVAJ9hU1JUC1yy3drndh3iEFJbQ169oYHbMIHYMIGZMAkGByqGSM44
+|BAMwEjEQMA4GA1UEAxMHQ2FybERTUxcNOTkwODI3MDcwMDAwWjBpMBMCAgDIFw05OTA4Mj
+|IwNzAwMDBaMBMCAgDJFw05OTA4MjIwNzAwMDBaMBMCAgDTFw05OTA4MjIwNzAwMDBaMBMC
+|AgDSFw05OTA4MjIwNzAwMDBaMBMCAgDUFw05OTA4MjQwNzAwMDBaMAkGByqGSM44BAMDLw
+|AwLAIUfmVSdjP+NHMX0feW+aDU2G1cfT0CFAJ6W7fVWxjBz4fvftok8yqDnDWhMQA=
+|<4.11.bin
+
+***5.1.bin***
+
+|* Example 5.1.bin
+|>5.1.bin
+|MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYDVQQDEwdDYX
+|JsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUABIGAC3EN5nGIiJi2lsGP
+|cP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FBs3IWg+f6KgCLx3M1eCbWx8+MDFbbpX
+|adCDgO8/nUkUNYeNxJtuzubGgzoyEd8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652j
+|KKHRLFf02hosdR8wQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8
+|Z9P43LrY4OxUk660cu1lXeCSFOSOpOJ7FuVyU=
+|<5.1.bin
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 133]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***5.2.bin***
+
+|* Example 5.2.bin
+|>5.2.bin
+|MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4GA1UEAxMHQ2
+|FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEFAASBgJQmQojGi7Z4IP+C
+|VypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQt9i3YcMwcap+aiOkyqjMalT03VUC0X
+|BOGv+HYI3HBZm/aFzxoq+YOXAWs5xlGerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg
+|+TGrnGVNQBNw47Ewoj4CAQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGH
+|cUr5MSJ/g9HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC
+|AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRRyw==
+|<5.2.bin
+
+***5.3.eml***
+
+|* Example 5.3.eml
+|>5.3.eml
+|TUlNRS1WZXJzaW9uOiAxLjAKTWVzc2FnZS1JZDogPDAwMTAzMTEyMDA1MjAzLjAwMzQ5QG
+|FteWVtaWx5LmlnLmNvbT4KRGF0ZTogVHVlLCAzMSBPY3QgMjAwMCAxMjowMDo1MiAtMDYw
+|MCAoQ2VudHJhbCBTdGFuZGFyZCBUaW1lKQpGcm9tOiBVc2VyMQpUbzogVXNlcjIKU3Viam
+|VjdDogRXhhbXBsZSA1LjMKQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9wa2NzNy1taW1l
+|OwoJbmFtZT1zbWltZS5wN207CglzbWltZS10eXBlPWVudmVsb3BlZC1kYXRhCkNvbnRlbn
+|QtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NApDb250ZW50LURpc3Bvc2l0aW9uOiBhdHRh
+|Y2htZW50OyBmaWxlbmFtZT1zbWltZS5wN20KCk1JSUJIZ1lKS29aSWh2Y05BUWNEb0lJQk
+|R6Q0NBUXNDQVFBeGdjQXdnYjBDQVFBd0pqQVNNUkF3RGdZRFZRUURFd2REWVhKc1VsTkIK
+|QWhCR05HdkhnQUJXdkJIVGJpN05YWEhRTUEwR0NTcUdTSWIzRFFFQkFRVUFCSUdBQzNFTj
+|VuR0lpSmkybHNHUGNQMmlKOTdhNGU4awpiS1F6MzZ6ZzZaMmkweXg2ellDNG1aN21YN0ZC
+|czNJV2crZjZLZ0NMeDNNMWVDYld4OCtNREZiYnBYYWRDRGdPOC9uVWtVTlllTnhKCnR1en
+|ViR2d6b3lFZDhDaDRIL2RkOWdkelRkK3RhVEVnUzBpcGRTSnVObmtWWTQvTTY1MmpLS0hS
+|TEZmMDJob3NkUjh3UXdZSktvWkkKaHZjTkFRY0JNQlFHQ0NxR1NJYjNEUU1IQkFndGFNWH
+|BSd1pSTllBZ0RzaVNmOFo5UDQzTHJZNE94VWs2NjBjdTFsWGVDU0ZPU09wTwpKN0Z1VnlV
+|PQoK
+|<5.3.eml
+
+***6.0.bin***
+
+|* Example 6.0.bin
+|>6.0.bin
+|MF4GCSqGSIb3DQEHBaBRME8CAQAwBwYFKw4DAhowKwYJKoZIhvcNAQcBoB4EHFRoaXMgaX
+|Mgc29tZSBzYW1wbGUgY29udGVudC4EFEBq7AhSebpuFgItngYpwCKWh91I
+|<6.0.bin
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 134]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+***7.1.bin***
+
+|* Example 7.1.bin
+|>7.1.bin
+|MFcGCSqGSIb3DQEHBqBKMEgCAQAwQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiza2v7Yj
+|EIToAg+vzt2z8YFx04iRHqNNYg2/TD2VgV75M7mvXXBPa1cOI=
+|<7.1.bin
+
+***7.2.bin***
+
+|* Example 7.2.bin
+|>7.2.bin
+|MIGVBgkqhkiG9w0BBwaggYcwgYQCAQIwQwYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgHJy
+|CFkJ6wfoAg0iCPZ0iKy0HkImhdvncFUibt4wG9AJFYpzVuvEuiBzOhOjA4BgMqqzMxMQQv
+|VGhpcyBpcyBhIHRlc3QgR2VuZXJhbCBBU04gQXR0cmlidXRlLCBudW1iZXIgMS4=
+|<7.2.bin
+
+C.  Acknowledgements
+
+   Blake Ramsdell, Jim Schaad, and John Pawling contributed the vast
+   majority of the examples in this document, and/or correct examples
+   during the early versions of this document.  Additional examples came
+   from many people, including Rob Colestock and Paul Hoffman.
+   Additional testing came from Holger Ebel and Russ Housley.
+
+   The examples are displayed with a modified version of Peter Gutmann's
+   "dumpasn1" program.  Peter and Jim Schaad and Blake Ramsdell have
+   been updating the program based on input from the process of writing
+   this draft.
+
+Editor's Address
+
+   Paul Hoffman
+   Internet Mail Consortium
+   127 Segre Place
+   Santa Cruz, CA  95060 USA
+
+   EMail: phoffman at imc.org
+
+
+
+
+
+
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 135]
+

+RFC 4134              Examples of S/MIME Messages              July 2005
+
+
+Full Copyright Statement
+
+   Copyright (C) The Internet Society (2005).
+
+   This document is subject to the rights, licenses and restrictions
+   contained in BCP 78, and except as set forth therein, the authors
+   retain all their rights.
+
+   This document and the information contained herein are provided on an
+   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
+   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET
+   ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED,
+   INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE
+   INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
+   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+
+Intellectual Property
+
+   The IETF takes no position regarding the validity or scope of any
+   Intellectual Property Rights or other rights that might be claimed to
+   pertain to the implementation or use of the technology described in
+   this document or the extent to which any license under such rights
+   might or might not be available; nor does it represent that it has
+   made any independent effort to identify any such rights.  Information
+   on the procedures with respect to rights in RFC documents can be
+   found in BCP 78 and BCP 79.
+
+   Copies of IPR disclosures made to the IETF Secretariat and any
+   assurances of licenses to be made available, or the result of an
+   attempt made to obtain a general license or permission for the use of
+   such proprietary rights by implementers or users of this
+   specification can be obtained from the IETF on-line IPR repository at
+   http://www.ietf.org/ipr.
+
+   The IETF invites any interested party to bring to its attention any
+   copyrights, patents or patent applications, or other proprietary
+   rights that may cover technology that may be required to implement
+   this standard.  Please address the information to the IETF at ietf-
+   ipr at ietf.org.
+
+Acknowledgement
+
+   Funding for the RFC Editor function is currently provided by the
+   Internet Society.
+
+
+
+
+
+
+
+Hoffman, Ed.                 Informational                    [Page 136]
+

diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.p12
new file mode 100644
index 0000000..79fe2f2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.pem
new file mode 100644
index 0000000..3e507ba
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-A.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAC0dXvAI0/fhu22j15YEo
+F8M3OYM8fwlvxs2/qtwELR3hVckpRIJmfGpUutb6/TBPgTS8a/fmzcrxLsL/aGSD
+jH4/TmTHrRmhlT/einuudpAXPxaS27Yz7duxRPmyXeyHy3P0ulXDEzOaZdV8kxQs
+J/v+z0knwdAh91omHRfJuNxDQtLfjp1Qtz+jrBCI6s864UblKXG/AwjWOLFQ1E0N
+A2bDo72tr3aw01gryggFkyNrB9K5/15+jJLVLFjuJfP7m3FUjPfGQB9+eZMBWpNH
+hGcSsPibqWVTDMjN0Z/mTGMzZDsEXX0Ao1K21q5vK1sfFYEahv/PCwkcW1dOeTGF
+pQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.p12
new file mode 100644
index 0000000..ef50132
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.pem
new file mode 100644
index 0000000..6c44910
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-B.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAIYpxwPMRRjPuRBsWKhB0
+ACZHEaO6RtSwu28sHO2TF1o0kHONAnqR37OhMuPR70qBynd5dVDkjpxXUfxhLDPh
+jdaxXuj2vMrbAvDJFsIsKDatlc632IsicSR4DVEnpJmUtLBQFC2VylHMxkGoo5eJ
+dsf5ZY/QqUXf+VReLWfyQXEaSGe8nI7fP61xqTsgzcN4ziqkKSKGvsEtPU/oo23Y
+xZDJpRMPdzu7TqkP3PnzRFy6HUamM2Xpyl2qeYELtGu7nuoSaF/1AX21bPtU9N9N
++wbxlGuq7NVIKdlIaoQ3FfgCVZGrVwjr7uxow7Gob+pWJJKjOS+IlSRL0MqH1t/U
+yQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.p12
new file mode 100644
index 0000000..72527d6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.pem
new file mode 100644
index 0000000..f844ee4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-C.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkWkqxLQH4vvX5e2oiydv
+VN8Et+ZznJ78yifF7Tctjm9+EfEBRupHwXHlAZd2n2CsZfhVTqk/Rnffb078X3g5
+9jx9ka0/hhkYyG6XqLybS3yXVpC/mvaeQMRu0Ubi0uSOkcf6rYiaqGjcG5DRaSAz
+SNNrDTEDYNxsuaPJoxZtQ+o1VaB3ksJ2UanzAHy45IJKXlSWS4l0Xsu6NZJxeMLB
+0iL0j5+TcaK37dkNpDi4dhFbeOi30Q8rvC5BDorFMM8GEl+GevH6Rpk0P67WlnOY
+qeDoKjzKi1w0ZDBS8XI95DLsmnHXcg2Iu8Dx1iBJMFST6mLtsMdVQAD+y2NTkbpM
+xA==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.p12
new file mode 100644
index 0000000..c2fa40b
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.pem
new file mode 100644
index 0000000..6f93f1c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-D.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkSFw/c7vnAAs4wKzS24X
+oyJrIiazcZD4A2ioqWMQD+QxFJlplJsyE5vcyVxv5Pww5Od1aPJCsSEd/C7h12eA
+576kkQcbv5KQ8LUlpj6eRjzI4E97yc9Yi9C3YibniGCv5mxLpw2bOxix9l8EBj6h
+vTfDMdoQVXkGyI2TCbYppkffJgxrL/wj82XbYeIHL27REf4+bNVRYD3LMXl7koPc
+4vUC6lyxYUELfv6UnAzppqDl+LSUkKvQEe26syIUAE3ArGvy/aYjIYBCwQQu4r9H
+WnXdIvcTdZqi3x9z/aN8Or9/IYIXpk3td6lLqI/DUwkPRS6zcthDo3x/1IFhUCB3
+KQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.p12
new file mode 100644
index 0000000..0265642
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.pem
new file mode 100644
index 0000000..0c30777
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-E.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAkFwewElSyXCGG2ygI3I4
+iYLtjAJAy002ES4JGHvr39dNhYoZ1poop18AU52mrx+SKX5vc/hAipisVa0rK9Jl
+91GF5NQdhU0KWxNCBHZAy3dUf1M63jvTC3eiG8LVV+C77Cx936i8qO5f3qWCN40z
+4W8eMwkCoVtpfzuuHk1by0VwCgU5IYuNIrwxR1bjudOctyhXNJjgr3SIsjDrqpTA
+nS4AauNFVqFfSyyaw5AX+7eA/WrMOGdJBJT1bEhHqrWxLtQzwSzKBKu7FpuF3mVX
+SHcSW4AzA6Yzq2Hcedo+SJt96IDr5xT17ncPMBzdq9pdoHlyJVq9+3O5JQOTx1WD
+6g==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.p12
new file mode 100644
index 0000000..58410dc
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.pem
new file mode 100644
index 0000000..fcc5205
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-F.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAaiR5Rnhj/vUqDgVqHaJk
+0VcMuvDzkQVmUlAZlsDa3uH3CW43yAXXM6ahacYnOgpLB96aq6cI8E74hHzO6PU6
+M50LLdp+KWu5InQv7+6fgSpShRxnHBKigCuoLy6oKFkCTTnnK002Mplr8+eHZHbi
+clm+k9rQejNalv+P9GSE5JcIEkTSXUDbfe81/ej9DCOcGbFPuL5hFQ8GNIuf+uv2
+OKXQtdpuayFZnD3hoWYE1LMT5W1lK1Jewx03phYeCMAY+MibRhzXWLDMBiwXpvW8
+cgCv777p+tRedunb5eLF+FT+/r617rskD9i9mJjqvoxQaXaYe++UX5mt9xpXZ9oM
+1g==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.p12
new file mode 100644
index 0000000..c8184a2
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.pem
new file mode 100644
index 0000000..d10c228
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-G.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAoLujmlhRD05T4G8CQa+g
+kIW/l43pazV1+iWaPnADd3/ywX7BNrVkGDaJHPci1BBq8lsiIA9nu7Gfxjl9TsZe
+wwLzZ/LxI9tTR+ikYxy0MID+x45rk1dF0nnya9S3wQAXDhP8ZKN0d8ezvbQ2N2LG
+74YPAtQZngMLMvYlG6MgoDNYOHHDkYZ6uL8PEwU9DtlZ+JPwxI7o7/E/T3XdDpvI
+UcI15axKbD5QMqGQxZwgQYFVMDvKou1upkLQ6ymHYgEzSqNNSzTYVdhVrGgTX+xl
+VZQFdJqR/gkloXbzxC/WqFTGrX1WN6kMvL+ZnVEh7DWELPmLFMfoWYCd4Q2hIjdx
+MQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.p12
new file mode 100644
index 0000000..b38c9eb
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.pem
new file mode 100644
index 0000000..0cab075
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-H.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAPaezAGexMlsmptKQBlrV
+iTDBKfTs555wM05d0CRzd6dq9GHYNk/BMPy0mPmpxLwuyQqjB3rw9+mlGre1jcLf
+Kthaz+Vna1yIGqg5dqqdu7NUX6/8x51hKQ+8B3rmlqx3wjt+bWgo2Qgl8otrHXKY
+EWrKfmTNd3z0+nklqaLFvxmQwQ33CKciw6k9A2O3DaOdf1smCfFyjF/hi4I0pJaX
+vFB/CbCAF/zVmQW+uXMNooZmd+DcKsK5ZN6LzxDXC6iqqaN0WS1kmctjYQ4pOomg
+5pdKfv+gUwUqUTbtL2/WeyuOcHY9XLluYk+nwtdFS25uQpmHZcQ4baeKB5N9IJy8
+jg==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.p12
new file mode 100644
index 0000000..7b97f68
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.pem
new file mode 100644
index 0000000..8717fd8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-I.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAJanu4ytjXr/ppQEiEsJ3
+1TqGBIoASHHWZsjd4DZmigBgERJqtXK/AsTsljFrSo1lhP3Q9TFqOeikvJ5T3y4q
+8yYY5qaEICsjUuySTIT3r7O00O5mtpdnpsRkBceqvBDDqfWefau00SVoBaqmt2P+
+Bq3x4l7MYqJNI8fPNVHqhSBlnWfxgYO/GZd4ZshhOZgrb96B98XpRlD5uYSlTpJt
+cYvSb2s+BX4RCZIGSpoQJ0dgz3uU5H5i949fbuTbyGLVka0t8gvWN0IPoSPEp3Zj
+mEw5Oz2UV0/R0qF2/yeKKNH3aFMEAzYUAmVqA5OdWiiZgLYcIm6pQvT0iAtgnT9x
+rQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.p12
new file mode 100644
index 0000000..4073ea6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.pem
new file mode 100644
index 0000000..c3fba79
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-J.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEADFGQ9QEI1TU+qRg2QFLZ
+OhYryOaAXNOaEBR+f0LCG5My9j0vI3/1BKHwq6kVPVDkfSPrrX1ZNUPOAI+PLrwI
+RGsJw6ST8dyWXeY4LEarHOPLvSTD2u+WaPcRMJSsSTFnsscKgrAeu4VfZixOTpBp
+tI3bfqTPkY9Fra8R1M9PbNsPik0WI34nPS0T9XqF+s/FhHCcL/mX/Hj5aD0qEZWd
+wCSJGDyoZRQeMc7LowMGHpu1eqcqfSLt2TCPeXebVB031AioCe1iJUddb9WxHixH
+GyNlzJl7YwztT9Z3yRqHKde6Dun128N2YThQ/7/Dn54hXcWQCK4gFCTz2deD5S9Z
+TQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.p12 b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.p12
new file mode 100644
index 0000000..50b3b76
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.p12 differ
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.pem b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.pem
new file mode 100644
index 0000000..b9805f5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/rsa3/self-testcase-L.pem
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIBADANBgkqhkiG9w0BAQQFADBsMQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDEKMAgGA1UECxMBYTESMBAGA1UEAxMJbG9jYWxob3N0MB4X
+DTA2MDkxMzE4MjYzMloXDTA3MDkxMzE4MjYzMlowbDELMAkGA1UEBhMCR0IxEjAQ
+BgNVBAgTCUJlcmtzaGlyZTEQMA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkg
+Q29tcGFueSBMdGQxCjAIBgNVBAsTAWExEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKtexL4ZP1CWMsVedm+pD2xPG+md
+VbRqkVSDQYxrHUyRVKletjluY95908bsAlJR9oK/YehXe9W7r+LnotaR+yy1P45g
+hSWa6TNl1sz3NGIZwdU9WdqdNNs9YyDgzFezxzZffrh9xFTSF0CR66Tm1VasKa20
+69RTx4fE5n4kZx+DKfBGCX3PBprvIANZp0nrfuhf21ij9lORI9OkITwqR72PrybB
+9QDZB+7og1jGLAGbRBNR61mLVfKrg2yJVhpk1dHPsUzeVr3BB5XK8i7DvflWw5di
+PeyU4S7qm7WLZ9Wdg1XOchkQWmzqEUPG71dGzG6joPhdp56LFg2Yg58myRcCAwEA
+AaOByTCBxjAdBgNVHQ4EFgQUPd6mAcGQZ8iNGajt0kffN4AeDZswgZYGA1UdIwSB
+jjCBi4AUPd6mAcGQZ8iNGajt0kffN4AeDZuhcKRuMGwxCzAJBgNVBAYTAkdCMRIw
+EAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15
+IENvbXBhbnkgTHRkMQowCAYDVQQLEwFhMRIwEAYDVQQDEwlsb2NhbGhvc3SCAQAw
+DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOCAQEAoArZH56QUnasmPqCd68C
+kcG6hw5S6p7wloY9jz+iwh9b2tF3k1SPCeE7rBV7cevr1ruv/wWttBFiGfJK/hlL
+8C/MMPj1X5JuLY3JgNmNDSK9MLr5Ejvps0AQ+kA4CCSxxpTLWeUlqNnGk/Zcfoqa
+Gyk37PDlHMQC3QWLgAX+wG/rg8WvrAP1ZjM6t25yb6hIPZgCWZbq+j8X5kS3Qxz0
+buc9HMi9oeuejeP7zWRJHhnCcDuClmpI6pk9nkjmunYtF2rMWi7f2eJ0Qjbo1wnn
+rUU5sCGLZ6i3ux/HvMgynho7RVqV+bqV+G9wZem3crNbtLhUSB2SAgYZnMqrLcW9
+jQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAq17Evhk/UJYyxV52b6kPbE8b6Z1VtGqRVINBjGsdTJFUqV62
+OW5j3n3TxuwCUlH2gr9h6Fd71buv4uei1pH7LLU/jmCFJZrpM2XWzPc0YhnB1T1Z
+2p002z1jIODMV7PHNl9+uH3EVNIXQJHrpObVVqwprbTr1FPHh8TmfiRnH4Mp8EYJ
+fc8Gmu8gA1mnSet+6F/bWKP2U5Ej06QhPCpHvY+vJsH1ANkH7uiDWMYsAZtEE1Hr
+WYtV8quDbIlWGmTV0c+xTN5WvcEHlcryLsO9+VbDl2I97JThLuqbtYtn1Z2DVc5y
+GRBabOoRQ8bvV0bMbqOg+F2nnosWDZiDnybJFwIDAQABAoIBAGA8GNn0DaUwo5RI
+htQPqVSWXENlklJ9od1G1FGJeWudFWEDietYfYbdPEcyE9+snXUxCkdSkX0mKBCR
+KdW7JsUlh2pp83t5scmmP+jcTbNlaX9ZM5Nbwun3YCp/cuExWQbEu8HZBp7nWB1v
+lFgHNPi2N7WPqvuSjLNGtHVT9gEwWGUl1zfbuZp8pNT4r1l7nwj+S9pGF3v5RXDt
+qZWSbfPF3ESPkMOpXxGk5uDLx3aoeHBQALVjeNdVlkyxjrG75Pv7ZnrmXjXzcuVv
+aVACiCPWxzaRFR9cRCx/Z34KrJorLglrfIPIrRMKJY33QO2gpYYEpFkLsLth/Ip4
+NMSJ3KkCgYEA36skUOFK0iQcdEaUXR2zcvQd3P3ctxe0JqD7dHFWnY2ndA5+VvAP
+vUjemZgw+tNt1qjLCAwxMi4cEOEICG6zSlMBRcVbqkKPS3gd3fGvD/lfQZ02EePz
+6KYVC7xz1WXIcId/HvkBNmbPEyOLqi9fIJQoYrM3LnB3AFIUqQ4K3UMCgYEAxCRT
+Z6yLGFb6Evkvvc6usqDhpAjWaaTSxlsSf9IGsKXW90OronB1IiTaWgJze1PrwWy4
+z4YOSI8oEEpF7LdwI9hztg9wFGht8lahGkfHtgR7V/QzyLMYfcU/57STI9vvsw2S
+FNqIdeP1Bd/CE8iI6o6HOAadsWlTBBUBUtnZnZ0CgYA/ecthpL5eKt9kZE9gqbgu
+rHb5K5aC45g9yjvyjOO+7N+UATT7qT9eQZrizh1AYdZvMBIGo6cmjY1rgOGNuxTo
+x+u5iEv+YstV6K3ZOeiryOKutVYN97pV0SRx4zagXjVnMhzyhkpAzSaBUPom/zCp
+B0L618+WP1aWYbT5UUHmDwKBgA3Ju+86yuBgJN42lCuUnuVBt/rvABuXEZYOCuPf
+YMcEMXNaV3No0mMfEhZnu7R8tsL3IJq+Ar0JCzjx765vSrvKWIAA39EfcjMp8dNG
+HnzmHcGWEhnWtS8KMa7ZG8rWiCgfGRjML/GRn8TU8PCxFSbf9BN1K5qwG7zauSgY
+1lplAoGAfl1Qw77H27TYGMVBgco/2g05MaKb8TZ4PKn1znlPnNcqFEBi779W0/dD
+Zgb1mjnRQkw68Jj5XA2zv/06yjvTS+nHVEDCdgIrZI2p1IrI3F4tihSoWgYtoe+8
+5OVDiHQ73d6lxVLqIRoRic8ZtWR02PbrK5SmoPsFdeTcmtzqo6c=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/rsa3/testcases.README b/BouncyCastle.AxCrypt/test/data/rsa3/testcases.README
new file mode 100644
index 0000000..6485740
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/rsa3/testcases.README differ
diff --git a/BouncyCastle.AxCrypt/test/data/scrypt/TestVectors.txt b/BouncyCastle.AxCrypt/test/data/scrypt/TestVectors.txt
new file mode 100644
index 0000000..1b54dd6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/scrypt/TestVectors.txt
@@ -0,0 +1,20 @@
+scrypt(“”, “”, 16, 1, 1, 64) =
+77 d6 57 62 38 65 7b 20 3b 19 ca 42 c1 8a 04 97
+f1 6b 48 44 e3 07 4a e8 df df fa 3f ed e2 14 42
+fc d0 06 9d ed 09 48 f8 32 6a 75 3a 0f c8 1f 17
+e8 d3 e0 fb 2e 0d 36 28 cf 35 e2 0c 38 d1 89 06
+scrypt(“password”, “NaCl”, 1024, 8, 16, 64) =
+fd ba be 1c 9d 34 72 00 78 56 e7 19 0d 01 e9 fe
+7c 6a d7 cb c8 23 78 30 e7 73 76 63 4b 37 31 62
+2e af 30 d9 2e 22 a3 88 6f f1 09 27 9d 98 30 da
+c7 27 af b9 4a 83 ee 6d 83 60 cb df a2 cc 06 40
+scrypt(“pleaseletmein”, “SodiumChloride”, 16384, 8, 1, 64) =
+70 23 bd cb 3a fd 73 48 46 1c 06 cd 81 fd 38 eb
+fd a8 fb ba 90 4f 8e 3e a9 b5 43 f6 54 5d a1 f2
+d5 43 29 55 61 3f 0f cf 62 d4 97 05 24 2a 9a f9
+e6 1e 85 dc 0d 65 1e 40 df cf 01 7b 45 57 58 87
+scrypt(“pleaseletmein”, “SodiumChloride”, 1048576, 8, 1, 64) =
+21 01 cb 9b 6a 51 1a ae ad db be 09 cf 70 f8 81
+ec 56 8d 57 4a 2f fd 4d ab e5 ee 98 20 ad aa 47
+8e 56 fd 8f 4b a5 d0 9f fa 1c 6d 92 7c 40 f4 c3
+37 30 40 49 e8 a9 52 fb cb f4 5c 6f a7 7a 41 a4
diff --git a/BouncyCastle.AxCrypt/test/data/tls/README.txt b/BouncyCastle.AxCrypt/test/data/tls/README.txt
new file mode 100644
index 0000000..2f456ed
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/README.txt
@@ -0,0 +1,8 @@
+The key and certificate .pem files here were generated using GnuTLS certtool and the accompanying template files:
+
+    certtool --generate-privkey > x509-ca-key.pem
+    certtool --generate-privkey > x509-client-key.pem
+    certtool --generate-privkey > x509-server-key.pem
+    certtool --generate-self-signed --load-privkey x509-ca-key.pem --template ca.tmpl --outfile x509-ca.pem
+    certtool --generate-certificate --load-privkey x509-client-key.pem --load-ca-certificate x509-ca.pem --load-ca-privkey x509-ca-key.pem --template client.tmpl --outfile x509-client.pem
+    certtool --generate-certificate --load-privkey x509-server-key.pem --load-ca-certificate x509-ca.pem --load-ca-privkey x509-ca-key.pem --template server.tmpl --outfile x509-server.pem
diff --git a/BouncyCastle.AxCrypt/test/data/tls/ca.tmpl b/BouncyCastle.AxCrypt/test/data/tls/ca.tmpl
new file mode 100644
index 0000000..44319d2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/ca.tmpl
@@ -0,0 +1,4 @@
+cn = BouncyCastle TLS Test CA
+ca
+cert_signing_key
+expiration_days = 7300
diff --git a/BouncyCastle.AxCrypt/test/data/tls/client.tmpl b/BouncyCastle.AxCrypt/test/data/tls/client.tmpl
new file mode 100644
index 0000000..f7f7e08
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/client.tmpl
@@ -0,0 +1,5 @@
+cn = BouncyCastle Test Client
+tls_www_client
+encryption_key
+signing_key
+expiration_days = 7300
diff --git a/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.dsa b/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.dsa
new file mode 100644
index 0000000..77c6e47
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.dsa differ
diff --git a/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.rsa b/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.rsa
new file mode 100644
index 0000000..fb48103
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/tls/keystores/client_store.rsa differ
diff --git a/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.dsa b/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.dsa
new file mode 100644
index 0000000..819cecd
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.dsa differ
diff --git a/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.rsa b/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.rsa
new file mode 100644
index 0000000..5ade0b7
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/data/tls/keystores/server_store.rsa differ
diff --git a/BouncyCastle.AxCrypt/test/data/tls/server.tmpl b/BouncyCastle.AxCrypt/test/data/tls/server.tmpl
new file mode 100644
index 0000000..e406c48
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/server.tmpl
@@ -0,0 +1,5 @@
+cn = BouncyCastle Test Server
+tls_www_server
+encryption_key
+signing_key
+expiration_days = 7300
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-ca-key.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-ca-key.pem
new file mode 100644
index 0000000..b9144d2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-ca-key.pem
@@ -0,0 +1,32 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIFegIBAAKCATEAzIc3nB+Rux7seSPAeH7Q2CkHwRKRgZRQdmL259ySG7RKZ2N7
+rSaJFhnW02OaF5/GpkkWRT/WSZQQz6wMqKf/1H7idANZ9sA4hR1HDzHNQ4Ou7h+O
+Hxom+fbZzleGtMOMRdfBVYDx/vtlcv2WP1Y0gCHzHVN5854dae+OHbBI06o+HriY
+3MvQgr6VuwNItGbl87ZJDWb3FZ7JAq77hyrIQGaD6HbSFtRuunr2UAhkCCRy8gEg
+In0BXtXPFZSfFOGec0HiXtug4zEReSK2CVpeNyBWKw3xQuMfvRJ1SnRNoPeQ/Zk5
+FgMF/P8uXlszwY+7mri3XN+gj3yXJ+kNLIRsTG5/jo9v5qxfHKvYVwXtHLkSx/Be
+5OsBsc1c8eMIszMrAiiaF2FZxMPQD97kmalzQwIDAQABAoIBMCCrbJ+R5LD+Cd8j
+wye8IgHqiTmMN2p6VWFDrOrGWcmhF81sn6G907c7CLdFY/oSuc7FQpBsglRzGT2t
+iWwbQbXLUBggkkCO3bhYP98ry6eAI54Xs5eWPCmWBkkmbqGgfAnf98V/o6gLYgi8
+fEEWX6vOlcsrvVbDp9vMZGgA85u+cs5sxXC8rEwQw1FW/0hfCKt62i+7hbY8bgCK
+AuWV3y4B8gLxMNybvTKzeUcVhG2Bs8ZzdfP9auVILEsp6CjoqlW1QPsOJ6cJSVek
+3P7k8UyY++IpajMJZ0RxD5+MgqNvrU+F9fdk0W+z8ZW/FFncmtBS/xLAxg9lCicR
+qoiRGy4y/t8vKqtbMmqgev2JxSYYbE7AXD0Pp51hTRKAFASo6VdPh2/LBdXEU3uw
+4cXszskCgZkA3rdK8gg8/wMXjznff/Z3a6K0c5KPGGd+SK/Q4KwND6C0ca9JouVv
+PZ4qbqT++Ye1a5R3S5BSwCx13pNVmVicQQ4xQTCedaaTyhcNu3sClrK5uM4F1G7g
+p5RmUFPZFWODrFpqF39wwjGaUY229+JDI++c3hUfoSNQkLqKwwu0Z4aH/0UIDMy2
+5AbX4/QMvOdosTPDDBa/9rcCgZkA6xgXtiGl4PJ7bBCAtpEZ436qFjJOnhrBoxoP
+iK9wtp5alTrGYj9a0omia2Eg+JVDR2CkSsb5/98phaR0JY9dLFrk60a02YUhQAL8
+unkD0mBBRTuKejl/I31t2OTzUZOqfm7ggL6Jwy4BUkPmQbcKJg9CRs7vjF3lGmBd
+EPGQi+Dj1FnBMBnqWQ5zP2kjMNQ0uHWaHlWTO9UCgZgBnTx60pp2krQqApZfHA8z
+hYNfTxGgcKeWqUePSU/y7AxCwq1688TBopLWKHX8owIqnHHc51fiMrBMA69cJCtF
+wW+T9GFBowpxLYeY80RKiVMVRtD+ACu6qzWuoVzybb03k5QvRWowziE7NBa+ZzJr
+YUI2zdpj1Ziw49k7nqsZEP2NWRe82AL/VhlceplZCShWGHTycnvDswKBmCNkKx2m
+DxzAJEhua5IQYf9XcC+LPz6Z9JCjObdwAd3cFPLmODtOIlQTmDnmE1qYzdoO+Gyx
+a61TYSLXUQzeej5VKKUqrcsZOZozWOyRjzu6ddkAT6Z6xWMIXOMMBH1BZ6dE9dMr
+2/1gDZ7ezekSrxpvraCPQoy1Depcm2YTl5kXL/Ul1elx3U+u1zaykzOknpMuURdD
+9rhJAoGYX90aFh+SHKIc0nLBPCZA1dvvB6Nvwvynyr6pHDYFNZvsNBAqYQpLYgdY
+QRiGIHeUJgdDfuQADaTQy0t7fWuWE1orvK9ywrdXCo9KlstMmSInZ5LlF54wtgpw
+ivt7YjT1ewzxBJz67NdDVDLrOAo32ZTJ/iKUHoqXZGcCCWAtENzv9vRvcSJLIMYt
+bUtLF3QhyUCj7/ASc+Q=
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-ca.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-ca.pem
new file mode 100644
index 0000000..1639512
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-ca.pem
@@ -0,0 +1,21 @@
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAh+gAwIBAgIEUqKcyzANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhC
+b3VuY3lDYXN0bGUgVExTIFRlc3QgQ0EwHhcNMTMxMjA3MDM1ODAzWhcNMzMxMjAy
+MDM1ODAzWjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVExTIFRlc3QgQ0EwggFS
+MA0GCSqGSIb3DQEBAQUAA4IBPwAwggE6AoIBMQDMhzecH5G7Hux5I8B4ftDYKQfB
+EpGBlFB2Yvbn3JIbtEpnY3utJokWGdbTY5oXn8amSRZFP9ZJlBDPrAyop//UfuJ0
+A1n2wDiFHUcPMc1Dg67uH44fGib59tnOV4a0w4xF18FVgPH++2Vy/ZY/VjSAIfMd
+U3nznh1p744dsEjTqj4euJjcy9CCvpW7A0i0ZuXztkkNZvcVnskCrvuHKshAZoPo
+dtIW1G66evZQCGQIJHLyASAifQFe1c8VlJ8U4Z5zQeJe26DjMRF5IrYJWl43IFYr
+DfFC4x+9EnVKdE2g95D9mTkWAwX8/y5eWzPBj7uauLdc36CPfJcn6Q0shGxMbn+O
+j2/mrF8cq9hXBe0cuRLH8F7k6wGxzVzx4wizMysCKJoXYVnEw9AP3uSZqXNDAgMB
+AAGjQzBBMA8GA1UdEwEB/wQFMAMBAf8wDwYDVR0PAQH/BAUDAwcEADAdBgNVHQ4E
+FgQU9mOvr6Pi7+4O5bKxRihqeCkyHukwDQYJKoZIhvcNAQELBQADggExAKyMiFmj
+YxzjXpQBD5dvRI7xZn79vH3lo13XRBXj/sbPXDXWIv21iLfutXn/RGGsq8piPXHG
+5UY3cpZR6gOq6QO1dJ91K0ViAJBFQdkhhtfbhqGY4jvj0vGO6zenG/WrjH26nCT7
+8S4L6ZoF6Y0EfQXluP50vEitTaZ6x/rung9h2JQ8rYKiRRVCA+tgBWK/CNhQ9LXy
+k3GU0mKLik0AkEFS17C0NWePIPEs/Kxv9iTEFacAN9wVHjZcMYnYtWaPNX0LWV8s
+2V2DMJxrmgCEcoXgJxlyEmvyqwpjB+2AiIQVIuWcwPqgBQoKHThT2zJcXV+bMhMs
+6cGvaIdvPxttduQsP349GcmUIlV6zFJq+HcMjfa8hZNIkuGBpUzdRQnu1+vYTkwz
+eVOPEIBZLzg9e2k=
+-----END CERTIFICATE-----
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-client-key.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-client-key.pem
new file mode 100644
index 0000000..386711f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-client-key.pem
@@ -0,0 +1,32 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIFewIBAAKCATEA2HMtdpNQ+bHX26BW/haQL42XQKpZb71KRCtUnYVZbYNTriRc
+t9NIs+Ifm7clUH/hLTNE3xYHoBhG/quXl1NwJT7rq4vBZ2m2iHhV3GkV8mhfbIAn
+7Uw64ehw+US/CvvNccX8gA9aCjNqRdqXEcWGwKRoW0D0kEoSXzctCqdo5h0mwcPR
++DVVMwQiFDXS+LkqhL3eF2WsebQhuFiMNi+QShO6vgWIelGvj7kjmEVttEOsRDUx
+HAVtv7kMjmsi7QAyesLmyyFt7RF6BLYZZvVbjyz+Augr+MXmY2noH/ExkKfrhaLv
+dql3qEA1xKNFxi7LLJ8BU1P9jJ1So7nYX4P8Cely6oq/Gee1bPdhLK61K+R/wf9i
+L70krkxud7hmIlmvf0Ma0dHH3HM6dvjYaZ5/JwIDAQABAoIBMCdNzuEbwhX9Tcmj
+VXihJ0CDUQZciI4KTNyRE7Xg24rP0JesIav9sVN8yamQebWi6wQ2rZhm2y6eifG/
+vfCsJY6V3NyTLaT2JL+mPk0eRe51NnKw2M81yvFvsGgLLDe13qn8viuQ3hRBHtid
+Z1ZCTIRZtltvsZkr4icpEURAfwNeIsYHpW6RXK29X+TUm0Ev+oENKzGLdGTK06Xk
+6RRV7a34BIdg+7qVWL4ROzKPHKIrHw/Jmg+775UekvkGfos8Cd2eseHJROhAIje1
+WQTvDzOfx3PiUW9RW9/CKUXNeRtWJVhUG8lfqdKejn1+8CxPzwqgNRJbpGvCFa0R
+oDQ7+3l9ELdcA+sv9Qp2OFXIhagzXlGcC4SwMQrBiz6oK5dDqb7VEjE2igOGrRUZ
+i+7G3lECgZkA2qztgn6CbUhvLEXtiUr1EwX6ZHiB1ZVWjGo8cGmS2wI4/z48Ogln
+IvxnfAF7y9PYdHuNFkwbzFVRRdToLSw0bjkZVVzRodEJexvsK8LJQu2LycKOPO0n
+TLuWmr030wuZyU8ebrfuvdM7qDSSzrUc28+BUkPGiWAQ4lybqppoXtgXFeOLrDvn
+vp4OTkJmphM4eOSn8aPQSHECgZkA/WUAmT+/l+y6q6xo8WqEbvIkVzSfrSG3oXCd
+V40oNhEPHRRDWugq19mkBOMdFWEabAKaZTl1lLfijvs0fN2RIcARVAYrg2IlJvj4
+20/muERs3yM7tX7MgFCAdApgTGBToDy2O2ANdOhgG9KCcmf1D9ZKGnum7WhQHQaD
+3RV+S9LRhVyiIbeQzJxv8ejAaQVJPe99vez+TRcCgZgkLRuVzQwSvDr4HhFv9yCY
+JxMHcBA6n1wUGrco+a474SBAybD5APk5BnywPSaXz9ItYwsyNyEaKrspTFGkt31t
+BrE0OAjONmDVJwdpLe5Rzi6kEDWryqgHv7jonIkRtweYECi+tFsguENUTm5DGB9Q
+FgIU8/VyYJwqdpuiG61Mk38uNdizg62REWDYfY+xxdg/18QY67rXYQKBmGG/UaDM
+T5tKjaPlyUG/hkDKFayyNxpxVEXpjDiW0jkxEXR1OZpazxQe97+O4Mw7fhbGVkrQ
+BISO/s2LJ+83BWJQlh6klqqC9LP4/P6U7vqMIrdc/w5/UGH7K+IXkphD3F6GrQFw
+hyBe95wj84Awi/9E+acHphgU0jqwJbPmM6cKNxrL5hs9lZToj+Jwl7CrglprBUV7
+o4mXAoGZAJZ5BBXWeXf161K/n1hQY9dFLSYHjgv4sZMkDqyNhDpdW9HqJ2XEuscG
+Gf7vaCMEV+iOHFKYBS6XMcRXg+R7VOPRvPBNwQXf1ImcQzTVlerWHwMW+y0NAubd
+IIzAXPMzjcOBBiac2wg3cvBTQE29XJ/hy4Rk6qz/oWaIinYStCelCr1FR/Vw5HzE
+/SYmOzdAkWM9bv3Mp/g2
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-client.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-client.pem
new file mode 100644
index 0000000..4f23419
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-client.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAlKgAwIBAgIEUqKc2jANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhC
+b3VuY3lDYXN0bGUgVExTIFRlc3QgQ0EwHhcNMTMxMjA3MDM1ODE4WhcNMzMxMjAy
+MDM1ODE4WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVzdCBDbGllbnQwggFS
+MA0GCSqGSIb3DQEBAQUAA4IBPwAwggE6AoIBMQDYcy12k1D5sdfboFb+FpAvjZdA
+qllvvUpEK1SdhVltg1OuJFy300iz4h+btyVQf+EtM0TfFgegGEb+q5eXU3AlPuur
+i8FnabaIeFXcaRXyaF9sgCftTDrh6HD5RL8K+81xxfyAD1oKM2pF2pcRxYbApGhb
+QPSQShJfNy0Kp2jmHSbBw9H4NVUzBCIUNdL4uSqEvd4XZax5tCG4WIw2L5BKE7q+
+BYh6Ua+PuSOYRW20Q6xENTEcBW2/uQyOayLtADJ6wubLIW3tEXoEthlm9VuPLP4C
+6Cv4xeZjaegf8TGQp+uFou92qXeoQDXEo0XGLsssnwFTU/2MnVKjudhfg/wJ6XLq
+ir8Z57Vs92EsrrUr5H/B/2IvvSSuTG53uGYiWa9/QxrR0cfcczp2+Nhpnn8nAgMB
+AAGjdjB0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDwYDVR0P
+AQH/BAUDAwegADAdBgNVHQ4EFgQU+vZUEQX5t+SGCe44YgvMmiMm8NkwHwYDVR0j
+BBgwFoAU9mOvr6Pi7+4O5bKxRihqeCkyHukwDQYJKoZIhvcNAQELBQADggExAI17
+s7teVt0hE9Zp40++AkK1k3/z7CCFsg+yS8+1VgFx5mU5XgNZMMgaASo1PCd9ZxFF
+QPXJ18MT4YjI6kWIC5RZspsTCwCq7jyg8bw36MHTNFUTYgfgMbhWPrUHRuOq0iG4
++wJVR6lXuHz/yaqMVNiy4yxBero7+zYiPZ+PKjEcvQxfcG+dIgptR6plNkFeZipT
+VCsSrit6iuStqmR7Jpj3nxPkR+g8aAfPCeiCxrSLNJFBj5J5AGSfkBzgjF5IE/z+
+tOgcmlFwtwOAIdRn/FUr7g1FFZh+Wy7AiB7qU4EcoW1HpcXJuRuKDrTzFH7L88zu
+nrv8n9XJSMDxdnP6kNwIv89HmYJWxtToO68PsATiGA6DiUUPk+FqIHqP0kgXXMSc
+ODFGSlXqh4ocvtA4APE=
+-----END CERTIFICATE-----
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-server-key.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-server-key.pem
new file mode 100644
index 0000000..894fbb9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-server-key.pem
@@ -0,0 +1,32 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIFfAIBAAKCATEAsy/PN54P7ZkH23FHjtgZuzpyGa84+YZOM3snikem660o90Ws
+TquMMtXNeAQPGAFUpu2Qxo416ogolqqtTXYJz9qsp/eDvzlNCJN7HKb5Fg28HiCc
+dMx2AR03qlGkxI3WsCPxFsX83zrz8wZSvrO7jjS1/WfJW1vYme+kktYcg90+5pJ0
+5hEAIwFU/mh9KnVRVdnINCcCqdnwpA1fAPXLwqNYdRolaczaQFI1ml8YbOgCnefz
+uxeSt9qz/7TkBITVvBf3AH5fUG6UezNxma85o7b1P4QJNiWGA7uwh7iABpIR7795
+Fk8ebOSUD9lZ9iqo0CzXBDAiwJe3uzSLBITlF0xbyveH+ILj7sKpa0CkV+5yZ1Cm
+B426lluuBlYxbi2wfAgN8arfQtnTobl/m+ClrQIDAQABAoIBMAEZ6kKNFNbIeBqT
+24dTDIUsj+DCbGPsR86wsG5FOgFRa96K0qcAS53nBAXDynKFl6igJcXs4WfLiRnN
+QGcgob+cIgM6pT8rDnlZT/291pH9mD/MwnyHDwak7C7dGXrRojWQl1TGZqjJS0f5
+enaN5lUnXwROZqsxUYohFkmtj1dpjxTqUGZ0In1JdG2mDmunMgjkJ/UqtCp0QFCp
+xtd1u5/913RBFC+n/CJl1+TnNQ4WNDRtkHZfJpVp+dOldQr028CJU3C5u1JB9ped
+JK+dywUFlqH1Tdk2v5CQV5esvbFpXX7FIlHuId+JOwFyvkR5+7NmyQ2uAz/Yeg8K
+ItdRhNQCJpYPlPH9Yb1JooEhPYrQX6oz/q2R3qiFdtc1cMZW3KCtIALZk30lW/o+
+B4EiysECgZkA1cYcdgNKy5K1O/IOyhr1eYK2us738Z3A57gC1y+m58D02dzmwacg
+HKZI9Cz98L8yEyORkdxpg86xi+NIcdU15BXXioFgMI5ZSfNVBcO4rv8G/QCxEWDr
+gnXe7FYuLlOKBbVXx7fJ0IXRUVbUlH5ZqE2HlFbSdPJmlaKtbxxyT7xhhWkf/MuI
+hRn+MFvbXvC+JqL+FS141kECgZkA1pS74hc7H5blq0J51E8EDtgU5m770VlQKhbW
+Z1D0oXVfB19DD3SX4xu22/6XlKXLlQDx4ssxVw11VIkd9WhkIrqq4U644XL5xXmf
+PMsR+fG2o+Y7MY4TNy+4qcuOK17n6R2pxR4zQoVnZs/qL4s5jPKMsC76C4Udfxfh
+yup0eFEJ+jPQdWYWQ6uX3UF0rA5x0Tb200aKbG0CgZkAkwaoeHoXLR//yfTXOyWD
+g0jliGHkoabQEA681WcOsgJB5L1LcBETwuCS+G0hUj0NoaAq9FjVsTOtZPqyzqfH
+YtGq5rXIhFzDCFt1NHvCP4ljMwsQvVUdZSLQaVd0d6Q5H2fzsYa0JNiEeB7yIhcs
+btaz0tBL+ubkqzGxeuPjsvdrUyhUObd6c6DG9FeY7xlAjq43djVKEIECgZhITde9
+SDyo2UzMV1r72iAw7EimmPELSsADXqyiJZo4qXb64fOTyqK/aQBFwtTKxs8Bh076
+L6ORhLxrXsSUg7dyKFoaD0+mz/ovu1qXvolxIix7r8F0Yj5BUzgzJp7iKFmWqGMj
+Q5jcKl18PETZ/lzHDJexajLhHNqij6aKnFPgktX80+bDGEIaTUCf0kWBEGDzsUSc
+TmGoRQKBmQDVFQ6EAOXXNp2bMLZ78qnxmS+NZPijBDeVu1cXMYdRSBoldrtSHKUM
+NFjPfesz4IRbEePK5s0vgM88QCDaspy8aLj//gh9YuqijbHOfhvMUP6MqzU/jJN7
+MDAxcGbcoFqdWTP1HB9qeX91UNRwN+2/xfO6SrLbfTvG4v/sntr8YfVYya2EuAa9
+qLk0TB3QXaoHknsz7EhRnw==
+-----END RSA PRIVATE KEY-----
diff --git a/BouncyCastle.AxCrypt/test/data/tls/x509-server.pem b/BouncyCastle.AxCrypt/test/data/tls/x509-server.pem
new file mode 100644
index 0000000..efc8069
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/data/tls/x509-server.pem
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDmjCCAlKgAwIBAgIEUqKc4DANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDExhC
+b3VuY3lDYXN0bGUgVExTIFRlc3QgQ0EwHhcNMTMxMjA3MDM1ODI0WhcNMzMxMjAy
+MDM1ODI0WjAjMSEwHwYDVQQDExhCb3VuY3lDYXN0bGUgVGVzdCBTZXJ2ZXIwggFS
+MA0GCSqGSIb3DQEBAQUAA4IBPwAwggE6AoIBMQCzL883ng/tmQfbcUeO2Bm7OnIZ
+rzj5hk4zeyeKR6brrSj3RaxOq4wy1c14BA8YAVSm7ZDGjjXqiCiWqq1NdgnP2qyn
+94O/OU0Ik3scpvkWDbweIJx0zHYBHTeqUaTEjdawI/EWxfzfOvPzBlK+s7uONLX9
+Z8lbW9iZ76SS1hyD3T7mknTmEQAjAVT+aH0qdVFV2cg0JwKp2fCkDV8A9cvCo1h1
+GiVpzNpAUjWaXxhs6AKd5/O7F5K32rP/tOQEhNW8F/cAfl9QbpR7M3GZrzmjtvU/
+hAk2JYYDu7CHuIAGkhHvv3kWTx5s5JQP2Vn2KqjQLNcEMCLAl7e7NIsEhOUXTFvK
+94f4guPuwqlrQKRX7nJnUKYHjbqWW64GVjFuLbB8CA3xqt9C2dOhuX+b4KWtAgMB
+AAGjdjB0MAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0P
+AQH/BAUDAwegADAdBgNVHQ4EFgQUlILGBt8EzhYtlNrOPrhfwi0s6bkwHwYDVR0j
+BBgwFoAU9mOvr6Pi7+4O5bKxRihqeCkyHukwDQYJKoZIhvcNAQELBQADggExAMQd
+MLOlWKWJxh6IP7sRlWKjpWZyu43eSOfvEpVljW8VaRxJC8UdhpFxsXS6Ml7wEMUC
+BkVNHGMxho/GJMXUBV7OsQSv0et1o45bmkN+KKisSVReSgcj6Drp/BRcUcybPtcJ
+aDW1txh/suHWppVmtkIkZIF/3IR2qFekDdCLoluiEOvbNn3YjUnQLm6Eo0pBxgpb
+W5MF3/19UckP1sLrs5vFk1dtDBZ/agpI9I0psv+6OsjosvrdpjIPHjwmoZ+oYtKc
+4Q30vzLCVtGGyzXWBZ+Z6AbmZpJPDQtul522XKE2vE8GA3+X/RXVAZB8a86DWtzq
+J1O6D+KOyA9zwe1CO+VJ5fMkjSNXY6WDzEXqyKEBP8tkkvSByiM546CXtNDbEwBe
+PtYQf223mpK56XTFq4k=
+-----END CERTIFICATE-----
diff --git a/BouncyCastle.AxCrypt/test/lib/nunit.core.dll b/BouncyCastle.AxCrypt/test/lib/nunit.core.dll
new file mode 100644
index 0000000..f58c07d
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/lib/nunit.core.dll differ
diff --git a/BouncyCastle.AxCrypt/test/lib/nunit.core.interfaces.dll b/BouncyCastle.AxCrypt/test/lib/nunit.core.interfaces.dll
new file mode 100644
index 0000000..cdf50b6
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/lib/nunit.core.interfaces.dll differ
diff --git a/BouncyCastle.AxCrypt/test/lib/nunit.framework.dll b/BouncyCastle.AxCrypt/test/lib/nunit.framework.dll
new file mode 100644
index 0000000..c7b1c65
Binary files /dev/null and b/BouncyCastle.AxCrypt/test/lib/nunit.framework.dll differ
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1SequenceParserTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1SequenceParserTest.cs
new file mode 100644
index 0000000..030da04
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1SequenceParserTest.cs
@@ -0,0 +1,359 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class Asn1SequenceParserTest
+    {
+        private static readonly byte[] seqData = Hex.Decode("3006020100060129");
+        private static readonly byte[] nestedSeqData = Hex.Decode("300b0201000601293003020101");
+        private static readonly byte[] expTagSeqData = Hex.Decode("a1083006020100060129");
+        private static readonly byte[] implTagSeqData = Hex.Decode("a106020100060129");
+        private static readonly byte[] nestedSeqExpTagData = Hex.Decode("300d020100060129a1053003020101");
+        private static readonly byte[] nestedSeqImpTagData = Hex.Decode("300b020100060129a103020101");
+
+		private static readonly byte[] berSeqData = Hex.Decode("30800201000601290000");
+        private static readonly byte[] berDerNestedSeqData = Hex.Decode("308002010006012930030201010000");
+        private static readonly byte[] berNestedSeqData = Hex.Decode("3080020100060129308002010100000000");
+        private static readonly byte[] berExpTagSeqData = Hex.Decode("a180308002010006012900000000");
+		private static readonly byte[] berSeqWithDERNullData = Hex.Decode("308005000201000601290000");
+
+		[Test]
+		public void TestDerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut);
+
+			seqGen.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen.AddObject(new DerObjectIdentifier("1.1"));
+
+			seqGen.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(seqData, bOut.ToArray()), "basic DER writing test failed.");
+        }
+
+		[Test]
+		public void TestNestedDerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut);
+
+			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
+
+			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream());
+
+			seqGen2.AddObject(new DerInteger(BigInteger.One));
+
+			seqGen2.Close();
+
+			seqGen1.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(nestedSeqData, bOut.ToArray()), "nested DER writing test failed.");
+        }
+
+		[Test]
+		public void TestDerExplicitTaggedSequenceWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, true);
+
+            seqGen.AddObject(new DerInteger(BigInteger.Zero));
+
+            seqGen.AddObject(new DerObjectIdentifier("1.1"));
+
+            seqGen.Close();
+
+            Assert.IsTrue(Arrays.AreEqual(expTagSeqData, bOut.ToArray()), "explicit tag writing test failed.");
+        }
+
+		[Test]
+		public void TestDerImplicitTaggedSequenceWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator seqGen = new DerSequenceGenerator(bOut, 1, false);
+
+			seqGen.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen.AddObject(new DerObjectIdentifier("1.1"));
+
+			seqGen.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(implTagSeqData, bOut.ToArray()), "implicit tag writing test failed.");
+        }
+
+		[Test]
+		public void TestNestedExplicitTagDerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator  seqGen1 = new DerSequenceGenerator(bOut);
+
+            seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+
+            seqGen1.AddObject(new DerObjectIdentifier("1.1"));
+
+            DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, true);
+
+            seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+
+            seqGen2.Close();
+
+            seqGen1.Close();
+
+            Assert.IsTrue(Arrays.AreEqual(nestedSeqExpTagData, bOut.ToArray()), "nested explicit tagged DER writing test failed.");
+        }
+
+		[Test]
+		public void TestNestedImplicitTagDerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            DerSequenceGenerator seqGen1 = new DerSequenceGenerator(bOut);
+
+			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
+
+			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream(), 1, false);
+
+			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+
+			seqGen2.Close();
+
+			seqGen1.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(nestedSeqImpTagData, bOut.ToArray()), "nested implicit tagged DER writing test failed.");
+        }
+
+		[Test]
+		public void TestBerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut);
+
+			seqGen.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen.AddObject(new DerObjectIdentifier("1.1"));
+
+			seqGen.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(berSeqData, bOut.ToArray()), "basic BER writing test failed.");
+        }
+
+		[Test]
+		public void TestNestedBerDerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut);
+
+			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
+
+			DerSequenceGenerator seqGen2 = new DerSequenceGenerator(seqGen1.GetRawOutputStream());
+
+			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+
+			seqGen2.Close();
+
+			seqGen1.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(berDerNestedSeqData, bOut.ToArray()), "nested BER/DER writing test failed.");
+        }
+
+		[Test]
+		public void TestNestedBerWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BerSequenceGenerator seqGen1 = new BerSequenceGenerator(bOut);
+
+			seqGen1.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen1.AddObject(new DerObjectIdentifier("1.1"));
+
+			BerSequenceGenerator seqGen2 = new BerSequenceGenerator(seqGen1.GetRawOutputStream());
+
+			seqGen2.AddObject(new DerInteger(BigInteger.ValueOf(1)));
+
+			seqGen2.Close();
+
+			seqGen1.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(berNestedSeqData, bOut.ToArray()), "nested BER writing test failed.");
+        }
+
+		[Test]
+		public void TestDerReading()
+        {
+            Asn1StreamParser aIn = new Asn1StreamParser(seqData);
+
+			Asn1SequenceParser seq = (Asn1SequenceParser)aIn.ReadObject();
+            int count = 0;
+
+			Assert.IsNotNull(seq, "null sequence returned");
+
+			object o;
+			while ((o = seq.ReadObject()) != null)
+            {
+                switch (count)
+                {
+                    case 0:
+                        Assert.IsTrue(o is DerInteger);
+                        break;
+                    case 1:
+                        Assert.IsTrue(o is DerObjectIdentifier);
+                        break;
+                }
+                count++;
+            }
+
+			Assert.AreEqual(2, count, "wrong number of objects in sequence");
+        }
+
+		private void doTestNestedReading(
+            byte[] data)
+        {
+            Asn1StreamParser aIn = new Asn1StreamParser(data);
+
+			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
+            object o = null;
+            int count = 0;
+
+			Assert.IsNotNull(seq, "null sequence returned");
+
+			while ((o = seq.ReadObject()) != null)
+            {
+                switch (count)
+                {
+                    case 0:
+                        Assert.IsTrue(o is DerInteger);
+                        break;
+                    case 1:
+                        Assert.IsTrue(o is DerObjectIdentifier);
+                        break;
+                    case 2:
+                        Assert.IsTrue(o is Asn1SequenceParser);
+
+						Asn1SequenceParser s = (Asn1SequenceParser)o;
+
+						// NB: Must exhaust the nested parser
+						while (s.ReadObject() != null)
+						{
+							// Ignore
+						}
+
+						break;
+                }
+                count++;
+            }
+
+			Assert.AreEqual(3, count, "wrong number of objects in sequence");
+        }
+
+		[Test]
+		public void TestNestedDerReading()
+        {
+            doTestNestedReading(nestedSeqData);
+        }
+
+		[Test]
+		public void TestBerReading()
+        {
+            Asn1StreamParser aIn = new Asn1StreamParser(berSeqData);
+
+			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
+            object o = null;
+            int count = 0;
+
+			Assert.IsNotNull(seq, "null sequence returned");
+
+			while ((o = seq.ReadObject()) != null)
+            {
+                switch (count)
+                {
+                    case 0:
+                        Assert.IsTrue(o is DerInteger);
+                        break;
+                    case 1:
+                        Assert.IsTrue(o is DerObjectIdentifier);
+                        break;
+                }
+                count++;
+            }
+
+			Assert.AreEqual(2, count, "wrong number of objects in sequence");
+        }
+
+		[Test]
+		public void TestNestedBerDerReading()
+        {
+            doTestNestedReading(berDerNestedSeqData);
+        }
+
+		[Test]
+		public void TestNestedBerReading()
+        {
+            doTestNestedReading(berNestedSeqData);
+        }
+
+		[Test]
+		public void TestBerExplicitTaggedSequenceWriting()
+        {
+            MemoryStream bOut = new MemoryStream();
+            BerSequenceGenerator seqGen = new BerSequenceGenerator(bOut, 1, true);
+
+			seqGen.AddObject(new DerInteger(BigInteger.Zero));
+
+			seqGen.AddObject(new DerObjectIdentifier("1.1"));
+
+			seqGen.Close();
+
+			Assert.IsTrue(Arrays.AreEqual(berExpTagSeqData, bOut.ToArray()), "explicit BER tag writing test failed.");
+        }
+
+		[Test]
+		public void TestSequenceWithDerNullReading()
+		{
+			doTestParseWithNull(berSeqWithDERNullData);
+		}
+
+		private void doTestParseWithNull(
+			byte[] data)
+		{
+			Asn1StreamParser aIn = new Asn1StreamParser(data);
+			Asn1SequenceParser seq = (Asn1SequenceParser) aIn.ReadObject();
+			object o;
+			int count = 0;
+
+			Assert.IsNotNull(seq, "null sequence returned");
+
+			while ((o = seq.ReadObject()) != null)
+			{
+				switch (count)
+				{
+					case 0:
+						Assert.IsTrue(o is Asn1Null);
+						break;
+					case 1:
+						Assert.IsTrue(o is DerInteger);
+						break;
+					case 2:
+						Assert.IsTrue(o is DerObjectIdentifier);
+						break;
+				}
+				count++;
+			}
+
+			Assert.AreEqual(3, count, "wrong number of objects in sequence");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1UnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1UnitTest.cs
new file mode 100644
index 0000000..88492be
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ASN1UnitTest.cs
@@ -0,0 +1,88 @@
+using System;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	public abstract class Asn1UnitTest
+		: SimpleTest
+	{
+		protected void checkMandatoryField(string name, Asn1Encodable expected, Asn1Encodable present)
+		{
+			if (!expected.Equals(present))
+			{
+				Fail(name + " field doesn't match.");
+			}
+		}
+
+		protected void checkMandatoryField(string name, string expected, string present)
+		{
+			if (!expected.Equals(present))
+			{
+				Fail(name + " field doesn't match.");
+			}
+		}
+
+		protected void checkMandatoryField(string name, byte[] expected, byte[] present)
+		{
+			if (!AreEqual(expected, present))
+			{
+				Fail(name + " field doesn't match.");
+			}
+		}
+
+		protected void checkMandatoryField(string name, int expected, int present)
+		{
+			if (expected != present)
+			{
+				Fail(name + " field doesn't match.");
+			}
+		}
+
+		protected void checkOptionalField(string name, Asn1Encodable expected, Asn1Encodable present)
+		{
+			if (expected != null)
+			{
+				if (!expected.Equals(present))
+				{
+					Fail(name + " field doesn't match.");
+				}
+			}
+			else if (present != null)
+			{
+				Fail(name + " field found when none expected.");
+			}
+		}
+
+		protected void checkOptionalField(string name, string expected, string present)
+		{
+			if (expected != null)
+			{
+				if (!expected.Equals(present))
+				{
+					Fail(name + " field doesn't match.");
+				}
+			}
+			else if (present != null)
+			{
+				Fail(name + " field found when none expected.");
+			}
+		}
+
+		protected void checkOptionalField(string name, BigInteger expected, BigInteger present)
+		{
+			if (expected != null)
+			{
+				if (!expected.Equals(present))
+				{
+					Fail(name + " field doesn't match.");
+				}
+			}
+			else if (present != null)
+			{
+				Fail(name + " field found when none expected.");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs
new file mode 100644
index 0000000..ac4ff98
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/AdditionalInformationSyntaxUnitTest.cs
@@ -0,0 +1,77 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class AdditionalInformationSyntaxUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "AdditionalInformationSyntax"; }
+		}
+
+		public override void PerformTest()
+		{
+			AdditionalInformationSyntax syntax = new AdditionalInformationSyntax("hello world");
+
+			checkConstruction(syntax, new DirectoryString("hello world"));
+
+			try
+			{
+				AdditionalInformationSyntax.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			AdditionalInformationSyntax syntax,
+			DirectoryString information)
+		{
+			checkValues(syntax, information);
+
+			syntax = AdditionalInformationSyntax.GetInstance(syntax);
+
+			checkValues(syntax, information);
+
+			Asn1InputStream aIn = new Asn1InputStream(syntax.ToAsn1Object().GetEncoded());
+
+			IAsn1String info = (IAsn1String) aIn.ReadObject();
+
+			syntax = AdditionalInformationSyntax.GetInstance(info);
+
+			checkValues(syntax, information);
+		}
+
+		private void checkValues(
+			AdditionalInformationSyntax syntax,
+			DirectoryString information)
+		{
+			checkMandatoryField("information", information, syntax.Information);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AdditionalInformationSyntaxUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionSyntaxUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionSyntaxUnitTest.cs
new file mode 100644
index 0000000..59464d2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionSyntaxUnitTest.cs
@@ -0,0 +1,99 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class AdmissionSyntaxUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "AdmissionSyntax"; }
+		}
+
+		public override void PerformTest()
+		{
+			GeneralName name = new GeneralName(new X509Name("CN=hello world"));
+			Asn1Sequence admissions = new DerSequence(
+				new Admissions(name,
+				new NamingAuthority(new DerObjectIdentifier("1.2.3"), "url", new DirectoryString("fred")),
+				new ProfessionInfo[0]));
+			AdmissionSyntax syntax = new AdmissionSyntax(name, admissions);
+
+			checkConstruction(syntax, name, admissions);
+
+			syntax = AdmissionSyntax.GetInstance(null);
+
+			if (syntax != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				AdmissionSyntax.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			AdmissionSyntax	syntax,
+			GeneralName		authority,
+			Asn1Sequence	admissions)
+		{
+			checkValues(syntax, authority, admissions);
+
+			syntax = AdmissionSyntax.GetInstance(syntax);
+
+			checkValues(syntax, authority, admissions);
+
+			Asn1InputStream aIn = new Asn1InputStream(syntax.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence info = (Asn1Sequence) aIn.ReadObject();
+
+			syntax = AdmissionSyntax.GetInstance(info);
+
+			checkValues(syntax, authority, admissions);
+		}
+
+		private void checkValues(
+			AdmissionSyntax syntax,
+			GeneralName     authority,
+			Asn1Sequence    admissions)
+		{
+			checkMandatoryField("admissionAuthority", authority, syntax.AdmissionAuthority);
+
+			Admissions[] adm = syntax.GetContentsOfAdmissions();
+
+			if (adm.Length != 1 || !adm[0].Equals(admissions[0]))
+			{
+				Fail("admissions check failed");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AdmissionSyntaxUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionsUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionsUnitTest.cs
new file mode 100644
index 0000000..edefeb8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/AdmissionsUnitTest.cs
@@ -0,0 +1,90 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class AdmissionsUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "Admissions"; }
+		}
+
+		public override void PerformTest()
+		{
+			GeneralName name = new GeneralName(new X509Name("CN=hello world"));
+			NamingAuthority auth = new NamingAuthority(new DerObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
+			Admissions admissions = new Admissions(name, auth, new ProfessionInfo[0]);
+
+			checkConstruction(admissions, name, auth);
+
+			admissions = Admissions.GetInstance(null);
+
+			if (admissions != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				Admissions.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			Admissions      admissions,
+			GeneralName     name,
+			NamingAuthority auth)
+		{
+			checkValues(admissions, name, auth);
+
+			admissions = Admissions.GetInstance(admissions);
+
+			checkValues(admissions, name, auth);
+
+			Asn1InputStream aIn = new Asn1InputStream(admissions.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence info = (Asn1Sequence)aIn.ReadObject();
+
+			admissions = Admissions.GetInstance(info);
+
+			checkValues(admissions, name, auth);
+		}
+
+		private void checkValues(
+			Admissions		admissions,
+			GeneralName		name,
+			NamingAuthority	auth)
+		{
+			checkMandatoryField("admissionAuthority", name, admissions.AdmissionAuthority);
+			checkMandatoryField("namingAuthority", auth, admissions.NamingAuthority);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AdmissionsUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/AllTests.cs
new file mode 100644
index 0000000..d219ef9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/AllTests.cs
@@ -0,0 +1,34 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    public class AllTests
+    {
+        public static void Main(string[] args)
+        {
+//            junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            suite().Run(el);
+        }
+
+		public static TestSuite suite()
+        {
+            TestSuite suite = new TestSuite("ASN.1 tests");
+
+			suite.Add(new AllTests());
+
+			// TODO Add these tests to RegressionTest list
+			suite.Add(new Asn1SequenceParserTest());
+			suite.Add(new OctetStringTest());
+			suite.Add(new ParseTest());
+			suite.Add(new TimeTest());
+
+			return suite;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/AttributeTableUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/AttributeTableUnitTest.cs
new file mode 100644
index 0000000..5dcf349
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/AttributeTableUnitTest.cs
@@ -0,0 +1,151 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Asn1Cms = Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class AttributeTableUnitTest
+        : SimpleTest
+    {
+        private static readonly DerObjectIdentifier type1 = new DerObjectIdentifier("1.1.1");
+        private static readonly DerObjectIdentifier type2 = new DerObjectIdentifier("1.1.2");
+        private static readonly DerObjectIdentifier type3 = new DerObjectIdentifier("1.1.3");
+
+		public override string Name
+		{
+			get { return "AttributeTable"; }
+		}
+
+		public override void PerformTest()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				new Asn1Cms.Attribute(type1, new DerSet(type1)),
+				new Asn1Cms.Attribute(type2, new DerSet(type2)));
+
+			Asn1Cms.AttributeTable table = new Asn1Cms.AttributeTable(v);
+
+			Asn1Cms.Attribute a = table[type1];
+            if (a == null)
+            {
+                Fail("type1 attribute not found.");
+            }
+            if (!a.AttrValues.Equals(new DerSet(type1)))
+            {
+                Fail("wrong value retrieved for type1!");
+            }
+
+			a = table[type2];
+            if (a == null)
+            {
+                Fail("type2 attribute not found.");
+            }
+            if (!a.AttrValues.Equals(new DerSet(type2)))
+            {
+                Fail("wrong value retrieved for type2!");
+            }
+
+			a = table[type3];
+            if (a != null)
+            {
+                Fail("type3 attribute found when none expected.");
+            }
+
+			Asn1EncodableVector vec = table.GetAll(type1);
+            if (vec.Count != 1)
+            {
+                Fail("wrong vector size for type1.");
+            }
+
+			vec = table.GetAll(type3);
+            if (vec.Count != 0)
+            {
+                Fail("wrong vector size for type3.");
+            }
+
+			vec = table.ToAsn1EncodableVector();
+            if (vec.Count != 2)
+            {
+                Fail("wrong vector size for single.");
+            }
+
+            IDictionary t = table.ToDictionary();
+
+			if (t.Count != 2)
+            {
+                Fail("hashtable wrong size.");
+            }
+
+            // multiple
+
+			v = new Asn1EncodableVector(
+				new Asn1Cms.Attribute(type1, new DerSet(type1)),
+				new Asn1Cms.Attribute(type1, new DerSet(type2)),
+				new Asn1Cms.Attribute(type1, new DerSet(type3)),
+				new Asn1Cms.Attribute(type2, new DerSet(type2)));
+
+			table = new Asn1Cms.AttributeTable(v);
+
+			a = table[type1];
+            if (!a.AttrValues.Equals(new DerSet(type1)))
+            {
+                Fail("wrong value retrieved for type1 multi Get!");
+            }
+
+			vec = table.GetAll(type1);
+            if (vec.Count != 3)
+            {
+                Fail("wrong vector size for multiple type1.");
+            }
+
+			a = (Asn1Cms.Attribute)vec[0];
+            if (!a.AttrValues.Equals(new DerSet(type1)))
+            {
+                Fail("wrong value retrieved for type1(0)!");
+            }
+
+            a = (Asn1Cms.Attribute)vec[1];
+            if (!a.AttrValues.Equals(new DerSet(type2)))
+            {
+                Fail("wrong value retrieved for type1(1)!");
+            }
+
+            a = (Asn1Cms.Attribute)vec[2];
+            if (!a.AttrValues.Equals(new DerSet(type3)))
+            {
+                Fail("wrong value retrieved for type1(2)!");
+            }
+
+            vec = table.GetAll(type2);
+            if (vec.Count != 1)
+            {
+                Fail("wrong vector size for multiple type2.");
+            }
+
+            vec = table.ToAsn1EncodableVector();
+            if (vec.Count != 4)
+            {
+                Fail("wrong vector size for multiple.");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new AttributeTableUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/BiometricDataUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/BiometricDataUnitTest.cs
new file mode 100644
index 0000000..a542f71
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/BiometricDataUnitTest.cs
@@ -0,0 +1,133 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class BiometricDataUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "BiometricData"; }
+        }
+
+		private byte[] GenerateHash()
+        {
+            Random rand = new Random();
+            byte[] bytes = new byte[20];
+            rand.NextBytes(bytes);
+            return bytes;
+        }
+
+		public override void PerformTest()
+        {
+            TypeOfBiometricData dataType = new TypeOfBiometricData(TypeOfBiometricData.HandwrittenSignature);
+            AlgorithmIdentifier hashAlgorithm = new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance);
+            Asn1OctetString     dataHash = new DerOctetString(GenerateHash());
+            BiometricData       bd = new BiometricData(dataType, hashAlgorithm, dataHash);
+
+            CheckConstruction(bd, dataType, hashAlgorithm, dataHash, null);
+
+            DerIA5String dataUri = new DerIA5String("http://test");
+
+            bd = new BiometricData(dataType, hashAlgorithm, dataHash, dataUri);
+
+            CheckConstruction(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+            bd = BiometricData.GetInstance(null);
+
+            if (bd != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                BiometricData.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        private void CheckConstruction(
+            BiometricData bd,
+            TypeOfBiometricData dataType,
+            AlgorithmIdentifier hashAlgorithm,
+            Asn1OctetString dataHash,
+            DerIA5String dataUri)
+        {
+            CheckValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+            bd = BiometricData.GetInstance(bd);
+
+            CheckValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(bd.ToAsn1Object().GetEncoded());
+
+			bd = BiometricData.GetInstance(seq);
+
+			CheckValues(bd, dataType, hashAlgorithm, dataHash, dataUri);
+        }
+
+        private void CheckValues(
+            BiometricData       bd,
+            TypeOfBiometricData dataType,
+            AlgorithmIdentifier algID,
+            Asn1OctetString     dataHash,
+            DerIA5String        sourceDataURI)
+        {
+            if (!bd.TypeOfBiometricData.Equals(dataType))
+            {
+                Fail("types don't match.");
+            }
+
+            if (!bd.HashAlgorithm.Equals(algID))
+            {
+                Fail("hash algorithms don't match.");
+            }
+
+            if (!bd.BiometricDataHash.Equals(dataHash))
+            {
+                Fail("hash algorithms don't match.");
+            }
+
+            if (sourceDataURI != null)
+            {
+                if (!bd.SourceDataUri.Equals(sourceDataURI))
+                {
+                    Fail("data uris don't match.");
+                }
+            }
+            else if (bd.SourceDataUri != null)
+            {
+                Fail("data uri found when none expected.");
+            }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new BiometricDataUnitTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringConstantTester.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringConstantTester.cs
new file mode 100644
index 0000000..bb966d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringConstantTester.cs
@@ -0,0 +1,25 @@
+using System;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	public class BitStringConstantTester
+	{
+		private static readonly int[] bits =
+		{
+			1 << 7, 1 << 6, 1 << 5, 1 << 4, 1 << 3, 1 << 2, 1 << 1, 1 << 0,
+			1 << 15, 1 << 14, 1 << 13, 1 << 12, 1 << 11, 1 << 10, 1 << 9, 1 << 8,
+			1 << 23, 1 << 22, 1 << 21, 1 << 20, 1 << 19, 1 << 18, 1 << 17, 1 << 16,
+			1 << 31, 1 << 30, 1 << 29, 1 << 28, 1 << 27, 1 << 26, 1 << 25, 1 << 24
+		};
+
+		public static void testFlagValueCorrect(
+			int bitNo,
+			int value)
+		{
+			if (bits[bitNo] != value)
+			{
+				throw new ArgumentException("bit value " + bitNo + " wrong");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringTest.cs
new file mode 100644
index 0000000..3a2dc31
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/BitStringTest.cs
@@ -0,0 +1,82 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class BitStringTest
+        : ITest
+    {
+        public ITestResult Perform()
+        {
+            KeyUsage k = new KeyUsage(KeyUsage.DigitalSignature);
+            if ((k.GetBytes()[0] != (byte)KeyUsage.DigitalSignature) || (k.PadBits != 7))
+            {
+                return new SimpleTestResult(false, Name + ": failed digitalSignature");
+            }
+
+            k = new KeyUsage(KeyUsage.NonRepudiation);
+            if ((k.GetBytes()[0] != (byte)KeyUsage.NonRepudiation) || (k.PadBits != 6))
+            {
+                return new SimpleTestResult(false, Name + ": failed nonRepudiation");
+            }
+
+            k = new KeyUsage(KeyUsage.KeyEncipherment);
+            if ((k.GetBytes()[0] != (byte)KeyUsage.KeyEncipherment) || (k.PadBits != 5))
+            {
+                return new SimpleTestResult(false, Name + ": failed keyEncipherment");
+            }
+
+            k = new KeyUsage(KeyUsage.CrlSign);
+            if ((k.GetBytes()[0] != (byte)KeyUsage.CrlSign)  || (k.PadBits != 1))
+            {
+                return new SimpleTestResult(false, Name + ": failed cRLSign");
+            }
+
+            k = new KeyUsage(KeyUsage.DecipherOnly);
+            if ((k.GetBytes()[1] != (byte)(KeyUsage.DecipherOnly >> 8))  || (k.PadBits != 7))
+            {
+                return new SimpleTestResult(false, Name + ": failed decipherOnly");
+            }
+
+			// test for zero length bit string
+			try
+			{
+				Asn1Object.FromByteArray(new DerBitString(new byte[0], 0).GetEncoded());
+			}
+			catch (IOException e)
+			{
+				return new SimpleTestResult(false, Name + ": " + e);
+			}
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public string Name
+        {
+			get { return "BitString"; }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new BitStringTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CMSTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CMSTest.cs
new file mode 100644
index 0000000..1afb363
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CMSTest.cs
@@ -0,0 +1,306 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class CmsTest
+		: ITest
+	{
+		//
+		// compressed data object
+		//
+		private static readonly byte[] compData = Base64.Decode(
+			"MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
+			+ "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
+			+ "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
+			+ "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
+			+ "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
+			+ "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
+			+ "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
+			+ "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
+			+ "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
+			+ "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
+			+ "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
+
+		//
+		// enveloped data
+		//
+		private static readonly byte[] envDataKeyTrns = Base64.Decode(
+			  "MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1Cb3Vu"
+			+ "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBCjANBgkqhkiG9w0BAQEFAASBgC5vdGrB"
+			+ "itQSGwifLf3KwPILjaB4WEXgT/IIO1KDzrsbItCJsMA0Smq2y0zptxT0pSRL6JRg"
+			+ "NMxLk1ySnrIrvGiEPLMR1zjxlT8yQ6VLX+kEoK43ztd1aaLw0oBfrcXcLN7BEpZ1"
+			+ "TIdjlBfXIOx1S88WY1MiYqJJFc3LMwRUaTEDMIAGCSqGSIb3DQEHATAdBglghkgB"
+			+ "ZQMEARYEEAfxLMWeaBOTTZQwUq0Y5FuggAQgwOJhL04rjSZCBCSOv5i5XpFfGsOd"
+			+ "YSHSqwntGpFqCx4AAAAAAAAAAAAA");
+
+		private static readonly byte[] envDataKEK = Base64.Decode(
+			  "MIAGCSqGSIb3DQEHA6CAMIACAQIxUqJQAgEEMAcEBQECAwQFMBAGCyqGSIb3DQEJE"
+			+ "AMHAgE6BDC7G/HyUPilIrin2Yeajqmj795VoLWETRnZAAFcAiQdoQWyz+oCh6WY/H"
+			+ "jHHi+0y+cwgAYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAiY3eDBBbF6naCABBiNdzJb"
+			+ "/v6+UZB3XXKipxFDUpz9GyjzB+gAAAAAAAAAAAAA");
+
+		private static readonly byte[] envDataNestedNDEF = Base64.Decode(
+			  "MIAGCSqGSIb3DQEHA6CAMIACAQAxge8wgewCAQAwgZUwgY8xKDAmBgNVBAoMH1RoZSBMZWdpb24g"
+			+ "b2YgdGhlIEJvdW5jeSBDYXN0bGUxLzAtBgkqhkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3Vu"
+			+ "Y3ljYXN0bGUub3JnMREwDwYDVQQIDAhWaWN0b3JpYTESMBAGA1UEBwwJTWVsYm91cm5lMQswCQYD"
+			+ "VQQGEwJBVQIBATANBgkqhkiG9w0BAQEFAARABIXMd8xiTyWDKO/LQfvdGYTPW3I9oSQWwtm4OIaN"
+			+ "VINpfY2lfwTvbmE6VXiLKeALC0dMBV8z7DEM9hE0HVmvLDCABgkqhkiG9w0BBwEwHQYJYIZIAWUD"
+			+ "BAECBBB32ko6WrVxDTqwUYEpV6IUoIAEggKgS6RowrhNlmWWI13zxD/lryxkZ5oWXPUfNiUxYX/P"
+			+ "r5iscW3s8VKJKUpJ4W5SNA7JGL4l/5LmSnJ4Qu/xzxcoH4r4vmt75EDE9p2Ob2Xi1NuSFAZubJFc"
+			+ "Zlnp4e05UHKikmoaz0PbiAi277sLQlK2FcVsntTYVT00y8+IwuuQu0ATVqkXC+VhfjV/sK6vQZnw"
+			+ "2rQKedZhLB7B4dUkmxCujb/UAq4lgSpLMXg2P6wMimTczXyQxRiZxPeI4ByCENjkafXbfcJft2eD"
+			+ "gv1DEDdYM5WrW9Z75b4lmJiOJ/xxDniHCvum7KGXzpK1d1mqTlpzPC2xoz08/MO4lRf5Mb0bYdq6"
+			+ "CjMaYqVwGsYryp/2ayX+d8H+JphEG+V9Eg8uPcDoibwhDI4KkoyGHstPw5bxcy7vVFt7LXUdNjJc"
+			+ "K1wxaUKEXDGKt9Vj93FnBTLMX0Pc9HpueV5o1ipX34dn/P3HZB9XK8ScbrE38B1VnIgylStnhVFO"
+			+ "Cj9s7qSVqI2L+xYHJRHsxaMumIRnmRuOqdXDfIo28EZAnFtQ/b9BziMGVvAW5+A8h8s2oazhSmK2"
+			+ "23ftV7uv98ScgE8fCd3PwT1kKJM83ThTYyBzokvMfPYCCvsonMV+kTWXhWcwjYTS4ukrpR452ZdW"
+			+ "l3aJqDnzobt5FK4T8OGciOj+1PxYFZyRmCuafm2Dx6o7Et2Tu/T5HYvhdY9jHyqtDl2PXH4CTnVi"
+			+ "gA1YOAArjPVmsZVwAM3Ml46uyXXhcsXwQ1X0Tv4D+PSa/id4UQ2cObOw8Cj1eW2GB8iJIZVqkZaU"
+			+ "XBexqgWYOIoxjqODSeoZKiBsTK3c+oOUBqBDueY1i55swE2o6dDt95FluX6iyr/q4w2wLt3upY1J"
+			+ "YL+TuvZxAKviuAczMS1bAAAAAAAAAAAAAA==");
+
+		//
+		// signed data
+		//
+		private static readonly byte[] signedData = Base64.Decode(
+			  "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAaCA"
+			+ "JIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEBMA0GCSqG"
+			+ "SIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
+			+ "MB4XDTA0MTAyNDA0MzA1OFoXDTA1MDIwMTA0MzA1OFowJTEWMBQGA1UEChMNQm91"
+			+ "bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ"
+			+ "AoGBAJj3OAshAOgDmPcYZ1jdNSuhOHRH9VhC/PG17FdiInVGc2ulJhEifEQga/uq"
+			+ "ZCpSd1nHsJUZKm9k1bVneWzC0941i9Znfxgb2jnXXsa5kwB2KEVESrOWsRjSRtnY"
+			+ "iLgqBG0rzpaMn5A5ntu7N0406EesBhe19cjZAageEHGZDbufAgMBAAGjTTBLMB0G"
+			+ "A1UdDgQWBBR/iHNKOo6f4ByWFFywRNZ65XSr1jAfBgNVHSMEGDAWgBR/iHNKOo6f"
+			+ "4ByWFFywRNZ65XSr1jAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFMJJ7QO"
+			+ "pHo30bnlQ4Ny3PCnK+Se+Gw3TpaYGp84+a8fGD9Dme78G6NEsgvpFGTyoLxvJ4CB"
+			+ "84Kzys+1p2HdXzoZiyXAer5S4IwptE3TxxFwKyj28cRrM6dK47DDyXUkV0qwBAMN"
+			+ "luwnk/no4K7ilzN2MZk5l7wXyNa9yJ6CHW6dMIICTTCCAbagAwIBAgIBAjANBgkq"
+			+ "hkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJB"
+			+ "VTAeFw0wNDEwMjQwNDMwNTlaFw0wNTAyMDEwNDMwNTlaMGUxGDAWBgNVBAMTD0Vy"
+			+ "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUu"
+			+ "b3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCBnzANBgkq"
+			+ "hkiG9w0BAQEFAAOBjQAwgYkCgYEAm+5CnGU6W45iUpCsaGkn5gDruZv3j/o7N6ag"
+			+ "mRZhikaLG2JF6ECaX13iioVJfmzBsPKxAACWwuTXCoSSXG8viK/qpSHwJpfQHYEh"
+			+ "tcC0CxIqlnltv3KQAGwh/PdwpSPvSNnkQBGvtFq++9gnXDBbynfP8b2L2Eis0X9U"
+			+ "2y6gFiMCAwEAAaNNMEswHQYDVR0OBBYEFEAmOksnF66FoQm6IQBVN66vJo1TMB8G"
+			+ "A1UdIwQYMBaAFH+Ic0o6jp/gHJYUXLBE1nrldKvWMAkGA1UdEwQCMAAwDQYJKoZI"
+			+ "hvcNAQEEBQADgYEAEeIjvNkKMPU/ZYCu1TqjGZPEqi+glntg2hC/CF0oGyHFpMuG"
+			+ "tMepF3puW+uzKM1s61ar3ahidp3XFhr/GEU/XxK24AolI3yFgxP8PRgUWmQizTQX"
+			+ "pWUmhlsBe1uIKVEfNAzCgtYfJQ8HJIKsUCcdWeCKVKs4jRionsek1rozkPExggEv"
+			+ "MIIBKwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFV"
+			+ "AgECMAkGBSsOAwIaBQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqG"
+			+ "SIb3DQEJBTEPFw0wNDEwMjQwNDMwNTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5U"
+			+ "BOl9XwQvlfifHCMocTANBgkqhkiG9w0BAQEFAASBgGHbe3/jcZu6b/erRhc3PEji"
+			+ "MUO8mEIRiNYBr5/vFNhkry8TrGfOpI45m7gu1MS0/vdas7ykvidl/sNZfO0GphEI"
+			+ "UaIjMRT3U6yuTWF4aLpatJbbRsIepJO/B2kdIAbV5SCbZgVDJIPOR2qnruHN2wLF"
+			+ "a+fEv4J8wQ8Xwvk0C8iMAAAAAAAA");
+
+		private static void Touch(object o)
+		{
+		}
+
+		private ITestResult CompressionTest()
+		{
+			try
+			{
+				ContentInfo info = ContentInfo.GetInstance(
+					Asn1Object.FromByteArray(compData));
+				CompressedData data = CompressedData.GetInstance(info.Content);
+
+				data = new CompressedData(data.CompressionAlgorithmIdentifier, data.EncapContentInfo);
+				info = new ContentInfo(CmsObjectIdentifiers.CompressedData, data);
+
+				if (!Arrays.AreEqual(info.GetEncoded(), compData))
+				{
+					return new SimpleTestResult(false, Name + ": CMS compression failed to re-encode");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": CMS compression failed - " + e.ToString(), e);
+			}
+		}
+
+		private ITestResult EnvelopedTest()
+		{
+			try
+			{
+				// Key trans
+				ContentInfo info = ContentInfo.GetInstance(
+					Asn1Object.FromByteArray(envDataKeyTrns));
+				EnvelopedData envData = EnvelopedData.GetInstance(info.Content);
+				Asn1Set s = envData.RecipientInfos;
+
+				if (s.Count != 1)
+				{
+					return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped, wrong number of recipients");
+				}
+
+				RecipientInfo recip = RecipientInfo.GetInstance(s[0]);
+
+				if (recip.Info is KeyTransRecipientInfo)
+				{
+					KeyTransRecipientInfo inf = KeyTransRecipientInfo.GetInstance(recip.Info);
+
+					inf = new KeyTransRecipientInfo(inf.RecipientIdentifier, inf.KeyEncryptionAlgorithm, inf.EncryptedKey);
+
+					s = new DerSet(new RecipientInfo(inf));
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped, wrong recipient type");
+				}
+
+				envData = new EnvelopedData(envData.OriginatorInfo, s, envData.EncryptedContentInfo, envData.UnprotectedAttrs);
+				info = new ContentInfo(CmsObjectIdentifiers.EnvelopedData, envData);
+
+				if (!Arrays.AreEqual(info.GetEncoded(), envDataKeyTrns))
+				{
+					return new SimpleTestResult(false, Name + ": CMS KeyTrans enveloped failed to re-encode");
+				}
+
+
+				// KEK
+				info = ContentInfo.GetInstance(
+					Asn1Object.FromByteArray(envDataKEK));
+				envData = EnvelopedData.GetInstance(info.Content);
+				s = envData.RecipientInfos;
+
+				if (s.Count != 1)
+				{
+					return new SimpleTestResult(false, Name + ": CMS KEK enveloped, wrong number of recipients");
+				}
+
+				recip = RecipientInfo.GetInstance(s[0]);
+
+				if (recip.Info is KekRecipientInfo)
+				{
+					KekRecipientInfo inf = KekRecipientInfo.GetInstance(recip.Info);
+
+					inf = new KekRecipientInfo(inf.KekID, inf.KeyEncryptionAlgorithm, inf.EncryptedKey);
+
+					s = new DerSet(new RecipientInfo(inf));
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": CMS KEK enveloped, wrong recipient type");
+				}
+
+				envData = new EnvelopedData(envData.OriginatorInfo, s, envData.EncryptedContentInfo, envData.UnprotectedAttrs);
+				info = new ContentInfo(CmsObjectIdentifiers.EnvelopedData, envData);
+
+				if (!Arrays.AreEqual(info.GetEncoded(), envDataKEK))
+				{
+					return new SimpleTestResult(false, Name + ": CMS KEK enveloped failed to re-encode");
+				}
+
+				// Nested NDEF problem
+				Asn1StreamParser asn1In = new Asn1StreamParser(new MemoryStream(envDataNestedNDEF, false));
+				ContentInfoParser ci = new ContentInfoParser((Asn1SequenceParser)asn1In.ReadObject());
+				EnvelopedDataParser ed = new EnvelopedDataParser((Asn1SequenceParser)ci
+					.GetContent(Asn1Tags.Sequence));
+				Touch(ed.Version);
+				ed.GetOriginatorInfo();
+				ed.GetRecipientInfos().ToAsn1Object();
+				EncryptedContentInfoParser eci = ed.GetEncryptedContentInfo();
+				Touch(eci.ContentType);
+				Touch(eci.ContentEncryptionAlgorithm);
+
+				Stream dataIn = ((Asn1OctetStringParser)eci.GetEncryptedContent(Asn1Tags.OctetString))
+					.GetOctetStream();
+				Streams.Drain(dataIn);
+				dataIn.Close();
+
+				// Test data doesn't have unprotected attrs, bug was being thrown by this call
+				Asn1SetParser upa = ed.GetUnprotectedAttrs();
+				if (upa != null)
+				{
+					upa.ToAsn1Object();
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": CMS enveloped failed - " + e.ToString(), e);
+			}
+		}
+
+		private ITestResult SignedTest()
+		{
+			try
+			{
+				ContentInfo info = ContentInfo.GetInstance(
+					Asn1Object.FromByteArray(signedData));
+				SignedData sData = SignedData.GetInstance(info.Content);
+
+				sData = new SignedData(sData.DigestAlgorithms, sData.EncapContentInfo, sData.Certificates, sData.CRLs, sData.SignerInfos);
+				info = new ContentInfo(CmsObjectIdentifiers.SignedData, sData);
+
+				if (!Arrays.AreEqual(info.GetEncoded(), signedData))
+				{
+					return new SimpleTestResult(false, Name + ": CMS signed failed to re-encode");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": CMS signed failed - " + e.ToString(), e);
+			}
+		}
+
+		public ITestResult Perform()
+		{
+			ITestResult res = CompressionTest();
+
+			if (!res.IsSuccessful())
+			{
+				return res;
+			}
+
+			res = EnvelopedTest();
+			if (!res.IsSuccessful())
+			{
+				return res;
+			}
+
+			return SignedTest();
+		}
+
+		public string Name
+		{
+			get { return "CMS"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new CmsTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CertHashUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CertHashUnitTest.cs
new file mode 100644
index 0000000..1e271a9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CertHashUnitTest.cs
@@ -0,0 +1,93 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.Ocsp;
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class CertHashUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "CertHash"; }
+		}
+
+		public override void PerformTest()
+		{
+			AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("1.2.2.3"));
+			byte[] digest = new byte[20];
+
+			CertHash certID = new CertHash(algId, digest);
+
+			checkConstruction(certID, algId, digest);
+
+			certID = CertHash.GetInstance(null);
+
+			if (certID != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				CertHash.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			CertHash			certHash,
+			AlgorithmIdentifier	algId,
+			byte[]				digest)
+		{
+			checkValues(certHash, algId, digest);
+
+			certHash = CertHash.GetInstance(certHash);
+
+			checkValues(certHash, algId, digest);
+
+			Asn1InputStream aIn = new Asn1InputStream(certHash.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			certHash = CertHash.GetInstance(seq);
+
+			checkValues(certHash, algId, digest);
+		}
+
+		private void checkValues(
+			CertHash certHash,
+			AlgorithmIdentifier algId,
+			byte[] digest)
+		{
+			checkMandatoryField("algorithmHash", algId, certHash.HashAlgorithm);
+
+			checkMandatoryField("certificateHash", digest, certHash.CertificateHash);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CertHashUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CertificateTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CertificateTest.cs
new file mode 100644
index 0000000..532e81a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CertificateTest.cs
@@ -0,0 +1,395 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class CertificateTest
+		: SimpleTest
+	{
+		//
+		// server.crt
+		//
+		private static readonly byte[] cert1 = Base64.Decode(
+			"MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+			+ "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+			+ "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+			+ "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+			+ "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
+			+ "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+			+ "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+			+ "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
+			+ "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
+			+ "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
+			+ "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
+			+ "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
+			+ "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
+			+ "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
+			+ "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
+			+ "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
+			+ "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
+			+ "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
+			+ "5/8=");
+
+		//
+		// ca.crt
+		//
+		private static readonly byte[] cert2 = Base64.Decode(
+			"MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+			+ "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+			+ "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+			+ "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+			+ "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2"
+			+ "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+			+ "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+			+ "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u"
+			+ "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t"
+			+ "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv"
+			+ "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s"
+			+ "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur"
+			+ "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl"
+			+ "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E"
+			+ "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG"
+			+ "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk"
+			+ "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz"
+			+ "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ"
+			+ "DhkaJ8VqOMajkQFma2r9iA==");
+
+		//
+		// testx509.pem
+		//
+		private static readonly byte[] cert3 = Base64.Decode(
+			"MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+			+ "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+			+ "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+			+ "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+			+ "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+			+ "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+			+ "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+			+ "zl9HYIMxATFyqSiD9jsx");
+
+		//
+		// v3-cert1.pem
+		//
+		private static readonly byte[] cert4 = Base64.Decode(
+			"MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx"
+			+ "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz"
+			+ "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw"
+			+ "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu"
+			+ "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2"
+			+ "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp"
+			+ "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C"
+			+ "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK"
+			+ "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x"
+			+ "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR"
+			+ "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB"
+			+ "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21"
+			+ "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3"
+			+ "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO");
+
+		//
+		// v3-cert2.pem
+		//
+		private static readonly byte[] cert5 = Base64.Decode(
+			"MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD"
+			+ "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0"
+			+ "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu"
+			+ "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1"
+			+ "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV"
+			+ "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx"
+			+ "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA"
+			+ "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT"
+			+ "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ"
+			+ "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm"
+			+ "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc"
+			+ "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz"
+			+ "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap"
+			+ "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU=");
+
+		private static readonly byte[] cert6 = Base64.Decode(
+			"MIIEDjCCAvagAwIBAgIEFAAq2jANBgkqhkiG9w0BAQUFADBLMSowKAYDVQQDEyFT"
+			+ "dW4gTWljcm9zeXN0ZW1zIEluYyBDQSAoQ2xhc3MgQikxHTAbBgNVBAoTFFN1biBN"
+			+ "aWNyb3N5c3RlbXMgSW5jMB4XDTA0MDIyOTAwNDMzNFoXDTA5MDMwMTAwNDMzNFow"
+			+ "NzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxFjAUBgNVBAMTDXN0b3Jl"
+			+ "LnN1bi5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAP9ErzFT7MPg2bVV"
+			+ "LNmHTgN4kmiRNlPpuLGWS7EDIXYBbLeSSOCp/e1ANcOGnsuf0WIq9ejd/CPyEfh4"
+			+ "sWoVvQzpOfHZ/Jyei29PEuxzWT+4kQmCx3+sLK25lAnDFsz1KiFmB6Y3GJ/JSjpp"
+			+ "L0Yy1R9YlIc82I8gSw44y5JDABW5AgMBAAGjggGQMIIBjDAOBgNVHQ8BAf8EBAMC"
+			+ "BaAwHQYDVR0OBBYEFG1WB3PApZM7OPPVWJ31UrERaoKWMEcGA1UdIARAMD4wPAYL"
+			+ "YIZIAYb3AIN9k18wLTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5zdW4uY29tL3Br"
+			+ "aS9jcHMuaHRtbDCBhQYDVR0fBH4wfDB6oCegJYYjaHR0cDovL3d3dy5zdW4uY29t"
+			+ "L3BraS9wa2lzbWljYS5jcmyiT6RNMEsxKjAoBgNVBAMTIVN1biBNaWNyb3N5c3Rl"
+			+ "bXMgSW5jIENBIChDbGFzcyBCKTEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJ"
+			+ "bmMwHwYDVR0jBBgwFoAUT7ZnqR/EEBSgG6h1wdYMI5RiiWswVAYIKwYBBQUHAQEE"
+			+ "SDBGMB0GCCsGAQUFBzABhhFodHRwOi8vdmEuc3VuLmNvbTAlBggrBgEFBQcwAYYZ"
+			+ "aHR0cDovL3ZhLmNlbnRyYWwuc3VuLmNvbTATBgNVHSUEDDAKBggrBgEFBQcDATAN"
+			+ "BgkqhkiG9w0BAQUFAAOCAQEAq3byQgyU24tBpR07iQK7agm1zQyzDQ6itdbji0ln"
+			+ "T7fOd5Pnp99iig8ovwWliNtXKAmgtJY60jWz7nEuk38AioZJhS+RPWIWX/+2PRV7"
+			+ "s2aWTzM3n43BypD+jU2qF9c9kDWP/NW9K9IcrS7SfU/2MZVmiCMD/9FEL+CWndwE"
+			+ "JJQ/oenXm44BFISI/NjV7fMckN8EayPvgtzQkD5KnEiggOD6HOrwTDFR+tmAEJ0K"
+			+ "ZttQNwOzCOcEdxXTg6qBHUbONdL7bjTT5NzV+JR/bnfiCqHzdnGwfbHzhmrnXw8j"
+			+ "QCVXcfBfL9++nmpNNRlnJMRdYGeCY6OAfh/PRo8/fXak1Q==");
+
+		private static readonly byte[] cert7 = Base64.Decode(
+			"MIIFJDCCBAygAwIBAgIKEcJZuwAAAAAABzANBgkqhkiG9w0BAQUFADAPMQ0wCwYD"
+			+ "VQQDEwRNU0NBMB4XDTA0MDUyMjE2MTM1OFoXDTA1MDUyMjE2MjM1OFowaTEbMBkG"
+			+ "CSqGSIb3DQEJCBMMMTkyLjE2OC4xLjMzMScwJQYJKoZIhvcNAQkCExhwaXhmaXJl"
+			+ "d2FsbC5jaXNjb3BpeC5jb20xITAfBgNVBAMTGHBpeGZpcmV3YWxsLmNpc2NvcGl4"
+			+ "LmNvbTB8MA0GCSqGSIb3DQEBAQUAA2sAMGgCYQCbcsY7vrjweXZiFQdhUafEjJV+"
+			+ "HRy5UKmuCy0237ffmYrN+XNLw0h90cdCSK6KPZebd2E2Bc2UmTikc/FY8meBT3/E"
+			+ "O/Osmywzi++Ur8/IrDvtuR1zd0c/xEPnV1ZRezkCAwEAAaOCAs4wggLKMAsGA1Ud"
+			+ "DwQEAwIFoDAdBgNVHQ4EFgQUzJBSxkQiN9TKvhTMQ1/Aq4gZnHswHwYDVR0jBBgw"
+			+ "FoAUMsxzXVh+5UKMNpwNHmqSfcRYfJ4wgfcGA1UdHwSB7zCB7DCB6aCB5qCB44aB"
+			+ "r2xkYXA6Ly8vQ049TVNDQSxDTj1NQVVELENOPUNEUCxDTj1QdWJsaWMlMjBLZXkl"
+			+ "MjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERDPWludCxE"
+			+ "Qz1wcmltZWtleSxEQz1zZT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/"
+			+ "b2JqZWN0Q2xhc3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnSGL2h0dHA6Ly9tYXVkLmlu"
+			+ "dC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01TQ0EuY3JsMIIBEAYIKwYBBQUHAQEE"
+			+ "ggECMIH/MIGqBggrBgEFBQcwAoaBnWxkYXA6Ly8vQ049TVNDQSxDTj1BSUEsQ049"
+			+ "UHVibGljJTIwS2V5JTIwU2VydmljZXMsQ049U2VydmljZXMsQ049Q29uZmlndXJh"
+			+ "dGlvbixEQz1pbnQsREM9cHJpbWVrZXksREM9c2U/Y0FDZXJ0aWZpY2F0ZT9iYXNl"
+			+ "P29iamVjdENsYXNzPWNlcnRpZmljYXRpb25BdXRob3JpdHkwUAYIKwYBBQUHMAKG"
+			+ "RGh0dHA6Ly9tYXVkLmludC5wcmltZWtleS5zZS9DZXJ0RW5yb2xsL01BVUQuaW50"
+			+ "LnByaW1la2V5LnNlX01TQ0EuY3J0MCwGA1UdEQEB/wQiMCCCGHBpeGZpcmV3YWxs"
+			+ "LmNpc2NvcGl4LmNvbYcEwKgBITA/BgkrBgEEAYI3FAIEMh4wAEkAUABTAEUAQwBJ"
+			+ "AG4AdABlAHIAbQBlAGQAaQBhAHQAZQBPAGYAZgBsAGkAbgBlMA0GCSqGSIb3DQEB"
+			+ "BQUAA4IBAQCa0asiPbObLJjpSz6ndJ7y4KOWMiuuBc/VQBnLr7RBCF3ZlZ6z1+e6"
+			+ "dmv8se/z11NgateKfxw69IhLCriA960HEgX9Z61MiVG+DrCFpbQyp8+hPFHoqCZN"
+			+ "b7upc8k2OtJW6KPaP9k0DW52YQDIky4Vb2rZeC4AMCorWN+KlndHhr1HFA14HxwA"
+			+ "4Mka0FM6HNWnBV2UmTjBZMDr/OrGH1jLYIceAaZK0X2R+/DWXeeqIga8jwP5empq"
+			+ "JetYnkXdtTbEh3xL0BX+mZl8vDI+/PGcwox/7YjFmyFWphRMxk9CZ3rF2/FQWMJP"
+			+ "YqQpKiQOmQg5NAhcwffLAuVjVVibPYqi");
+
+		private static readonly byte[] cert8 = Base64.Decode(
+			"MIIB0zCCATwCAQEwbqBsMGekZTBjMQswCQYDVQQGEwJERTELMAkGA1UECBMCQlkx"
+			+ "EzARBgNVBAcTClJlZ2Vuc2J1cmcxEDAOBgNVBAoTB0FDIFRlc3QxCzAJBgNVBAsT"
+			+ "AkNBMRMwEQYDVQQDEwpBQyBUZXN0IENBAgEBoHYwdKRyMHAxCzAJBgNVBAYTAkRF"
+			+ "MQswCQYDVQQIEwJCWTETMBEGA1UEBxMKUmVnZW5zYnVyZzESMBAGA1UEChMJQUMg"
+			+ "SXNzdWVyMRowGAYDVQQLExFBQyBJc3N1ZXIgc2VjdGlvbjEPMA0GA1UEAxMGQUMg"
+			+ "TWFuMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIwMDQxMTI2MTI1MjUxWhgPMjAwNDEy"
+			+ "MzEyMzAwMDBaMBkwFwYDVRhIMRAwDoEMREFVMTIzNDU2Nzg5MA0GCSqGSIb3DQEB"
+			+ "BQUAA4GBABd4Odx3yEMGL/BvItuT1RafNR2uuWuZbajg0pD6bshUsl+WCIfRiEkq"
+			+ "lHMkpI7WqAZikdnAEQ5jQsVWEuVejWxR6gjejKxc0fb9qpIui7/GoI5Eh6dmG20e"
+			+ "xbwJL3+6YYFrZwxR8cC5rPvWrblUR5XKJy+Zp/H5+t9iANnL1L8J");
+
+		private static readonly string[] subjects =
+		{
+			"C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster at connect4.com.au",
+			"C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster at connect4.com.au",
+			"C=AU,ST=QLD,CN=SSLeay/rsa test cert",
+			"C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
+			"E=cooke at issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
+			"O=Sun Microsystems Inc,CN=store.sun.com",
+			"unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com"
+		};
+
+		public override string Name
+		{
+			get { return "Certificate"; }
+		}
+
+		public void CheckCertificate(
+			int		id,
+			byte[]	cert)
+		{
+			Asn1Object seq = Asn1Object.FromByteArray(cert);
+			string dump = Asn1Dump.DumpAsString(seq);
+
+			X509CertificateStructure obj = X509CertificateStructure.GetInstance(seq);
+			TbsCertificateStructure tbsCert = obj.TbsCertificate;
+
+			if (!tbsCert.Subject.ToString().Equals(subjects[id - 1]))
+			{
+				Fail("failed subject test for certificate id " + id
+					+ " got " + tbsCert.Subject.ToString());
+			}
+
+			if (tbsCert.Version == 3)
+			{
+				X509Extensions ext = tbsCert.Extensions;
+				if (ext != null)
+				{
+					foreach (DerObjectIdentifier oid in ext.ExtensionOids)
+					{
+						X509Extension extVal = ext.GetExtension(oid);
+						Asn1Object extObj = Asn1Object.FromByteArray(extVal.Value.GetOctets());
+
+						if (oid.Equals(X509Extensions.SubjectKeyIdentifier))
+						{
+							SubjectKeyIdentifier.GetInstance(extObj);
+						}
+						else if (oid.Equals(X509Extensions.KeyUsage))
+						{
+							KeyUsage.GetInstance(extObj);
+						}
+						else if (oid.Equals(X509Extensions.ExtendedKeyUsage))
+						{
+							ExtendedKeyUsage ku = ExtendedKeyUsage.GetInstance(extObj);
+
+							Asn1Sequence sq = (Asn1Sequence)ku.ToAsn1Object();
+							for (int i = 0; i != sq.Count; i++)
+							{
+								KeyPurposeID.GetInstance(sq[i]);
+							}
+						}
+						else if (oid.Equals(X509Extensions.SubjectAlternativeName))
+						{
+							GeneralNames gn = GeneralNames.GetInstance(extObj);
+
+							Asn1Sequence sq = (Asn1Sequence)gn.ToAsn1Object();
+							for (int i = 0; i != sq.Count; i++)
+							{
+								GeneralName.GetInstance(sq[i]);
+							}
+						}
+						else if (oid.Equals(X509Extensions.IssuerAlternativeName))
+						{
+							GeneralNames gn = GeneralNames.GetInstance(extObj);
+
+							Asn1Sequence sq = (Asn1Sequence)gn.ToAsn1Object();
+							for (int i = 0; i != sq.Count; i++)
+							{
+								GeneralName.GetInstance(sq[i]);
+							}
+						}
+						else if (oid.Equals(X509Extensions.CrlDistributionPoints))
+						{
+							CrlDistPoint p = CrlDistPoint.GetInstance(extObj);
+
+							DistributionPoint[] points = p.GetDistributionPoints();
+							for (int i = 0; i != points.Length; i++)
+							{
+								// do nothing
+							}
+						}
+						else if (oid.Equals(X509Extensions.CertificatePolicies))
+						{
+							Asn1Sequence cp = (Asn1Sequence) extObj;
+
+							for (int i = 0; i != cp.Count; i++)
+							{
+								PolicyInformation.GetInstance(cp[i]);
+							}
+						}
+						else if (oid.Equals(X509Extensions.AuthorityKeyIdentifier))
+						{
+							AuthorityKeyIdentifier.GetInstance(extObj);
+						}
+						else if (oid.Equals(X509Extensions.BasicConstraints))
+						{
+							BasicConstraints.GetInstance(extObj);
+						}
+						else
+						{
+							//Console.WriteLine(oid.Id);
+						}
+					}
+				}
+			}
+		}
+
+		public void CheckAttributeCertificate(
+			int		id,
+			byte[]	cert)
+		{
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(cert);
+			string dump = Asn1Dump.DumpAsString(seq);
+
+			AttributeCertificate obj = AttributeCertificate.GetInstance(seq);
+			AttributeCertificateInfo acInfo = obj.ACInfo;
+
+			// Version
+			if (!(acInfo.Version.Equals(new DerInteger(1)))
+				&& (!(acInfo.Version.Equals(new DerInteger(2)))))
+			{
+				Fail("failed AC Version test for id " + id);
+			}
+
+			// Holder
+			Holder h = acInfo.Holder;
+			if (h == null)
+			{
+				Fail("failed AC Holder test, it's null, for id " + id);
+			}
+
+			// Issuer
+			AttCertIssuer aci = acInfo.Issuer;
+			if (aci == null)
+			{
+				Fail("failed AC Issuer test, it's null, for id " + id);
+			}
+
+			// Signature
+			AlgorithmIdentifier sig = acInfo.Signature;
+			if (sig == null)
+			{
+				Fail("failed AC Signature test for id " + id);
+			}
+
+			// Serial
+			DerInteger serial = acInfo.SerialNumber;
+
+			// Validity
+			AttCertValidityPeriod validity = acInfo.AttrCertValidityPeriod;
+			if (validity == null)
+			{
+				Fail("failed AC AttCertValidityPeriod test for id " + id);
+			}
+
+			// Attributes
+			Asn1Sequence attribSeq = acInfo.Attributes;
+			AttributeX509[] att = new AttributeX509[attribSeq.Count];
+			for (int i = 0; i < attribSeq.Count; i++)
+			{
+				att[i] = AttributeX509.GetInstance(attribSeq[i]);
+			}
+
+			// IssuerUniqueId
+			// TODO, how to best test?
+
+			// X509 Extensions
+			X509Extensions ext = acInfo.Extensions;
+			if (ext != null)
+			{
+				foreach (DerObjectIdentifier oid in ext.ExtensionOids)
+				{
+					X509Extension extVal = ext.GetExtension(oid);
+				}
+			}
+		}
+
+		public override void PerformTest()
+		{
+			CheckCertificate(1, cert1);
+			CheckCertificate(2, cert2);
+			CheckCertificate(3, cert3);
+			CheckCertificate(4, cert4);
+			CheckCertificate(5, cert5);
+			CheckCertificate(6, cert6);
+			CheckCertificate(7, cert7);
+			CheckAttributeCertificate(8, cert8);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CertificateTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs
new file mode 100644
index 0000000..20c2d18
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeIndicationUnitTest.cs
@@ -0,0 +1,107 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class CommitmentTypeIndicationUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "CommitmentTypeIndication"; }
+        }
+
+		public override void PerformTest()
+        {
+            CommitmentTypeIndication cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.ProofOfOrigin);
+
+            CheckConstruction(cti, CommitmentTypeIdentifier.ProofOfOrigin, null);
+
+            Asn1Sequence qualifier = new DerSequence(new DerObjectIdentifier("1.2"));
+
+            cti = new CommitmentTypeIndication(CommitmentTypeIdentifier.ProofOfOrigin, qualifier);
+
+            CheckConstruction(cti, CommitmentTypeIdentifier.ProofOfOrigin, qualifier);
+
+            cti = CommitmentTypeIndication.GetInstance(null);
+
+            if (cti != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                CommitmentTypeIndication.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        private void CheckConstruction(
+            CommitmentTypeIndication mv,
+            DerObjectIdentifier commitmenttTypeId,
+            Asn1Encodable qualifier)
+        {
+            CheckStatement(mv, commitmenttTypeId, qualifier);
+
+			mv = CommitmentTypeIndication.GetInstance(mv);
+
+			CheckStatement(mv, commitmenttTypeId, qualifier);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				mv.ToAsn1Object().GetEncoded());
+
+			mv = CommitmentTypeIndication.GetInstance(seq);
+
+			CheckStatement(mv, commitmenttTypeId, qualifier);
+        }
+
+		private void CheckStatement(
+            CommitmentTypeIndication cti,
+            DerObjectIdentifier     commitmentTypeId,
+            Asn1Encodable           qualifier)
+        {
+            if (!cti.CommitmentTypeID.Equals(commitmentTypeId))
+            {
+                Fail("commitmentTypeIds don't match.");
+            }
+
+            if (qualifier != null)
+            {
+                if (!cti.CommitmentTypeQualifier.Equals(qualifier))
+                {
+                    Fail("qualifiers don't match.");
+                }
+            }
+            else if (cti.CommitmentTypeQualifier != null)
+            {
+                Fail("qualifier found when none expected.");
+            }
+        }
+
+        public static void Main(
+            string[]    args)
+        {
+            RunTest(new CommitmentTypeIndicationUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs
new file mode 100644
index 0000000..192ac52
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CommitmentTypeQualifierUnitTest.cs
@@ -0,0 +1,107 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class CommitmentTypeQualifierUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "CommitmentTypeQualifier"; }
+        }
+
+		public override void PerformTest()
+        {
+            CommitmentTypeQualifier ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.ProofOfOrigin);
+
+            CheckConstruction(ctq, CommitmentTypeIdentifier.ProofOfOrigin, null);
+
+            Asn1Encodable info = new DerObjectIdentifier("1.2");
+
+            ctq = new CommitmentTypeQualifier(CommitmentTypeIdentifier.ProofOfOrigin, info);
+
+            CheckConstruction(ctq, CommitmentTypeIdentifier.ProofOfOrigin, info);
+
+            ctq = CommitmentTypeQualifier.GetInstance(null);
+
+            if (ctq != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                CommitmentTypeQualifier.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        private void CheckConstruction(
+            CommitmentTypeQualifier mv,
+            DerObjectIdentifier commitmenttTypeId,
+            Asn1Encodable qualifier)
+        {
+            CheckStatement(mv, commitmenttTypeId, qualifier);
+
+			mv = CommitmentTypeQualifier.GetInstance(mv);
+
+			CheckStatement(mv, commitmenttTypeId, qualifier);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				mv.ToAsn1Object().GetEncoded());
+
+			mv = CommitmentTypeQualifier.GetInstance(seq);
+
+			CheckStatement(mv, commitmenttTypeId, qualifier);
+        }
+
+		private void CheckStatement(
+            CommitmentTypeQualifier ctq,
+            DerObjectIdentifier     commitmentTypeId,
+            Asn1Encodable           qualifier)
+        {
+            if (!ctq.CommitmentTypeIdentifier.Equals(commitmentTypeId))
+            {
+                Fail("commitmentTypeIds don't match.");
+            }
+
+            if (qualifier != null)
+            {
+                if (!ctq.Qualifier.Equals(qualifier))
+                {
+                    Fail("qualifiers don't match.");
+                }
+            }
+            else if (ctq.Qualifier != null)
+            {
+                Fail("qualifier found when none expected.");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CommitmentTypeQualifierUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ContentHintsUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ContentHintsUnitTest.cs
new file mode 100644
index 0000000..d7453c2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ContentHintsUnitTest.cs
@@ -0,0 +1,93 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Ess;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class ContentHintsUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "ContentHints"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerUtf8String contentDescription = new DerUtf8String("Description");
+			DerObjectIdentifier contentType = new DerObjectIdentifier("1.2.2.3");
+
+			ContentHints hints = new ContentHints(contentType);
+
+			checkConstruction(hints, contentType, null);
+
+			hints = new ContentHints(contentType, contentDescription);
+
+			checkConstruction(hints, contentType, contentDescription);
+
+			hints = ContentHints.GetInstance(null);
+
+			if (hints != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				ContentHints.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			ContentHints		hints,
+			DerObjectIdentifier	contentType,
+			DerUtf8String		description)
+		{
+			checkValues(hints, contentType, description);
+
+			hints = ContentHints.GetInstance(hints);
+
+			checkValues(hints, contentType, description);
+
+			Asn1InputStream aIn = new Asn1InputStream(hints.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			hints = ContentHints.GetInstance(seq);
+
+			checkValues(hints, contentType, description);
+		}
+
+		private void checkValues(
+			ContentHints		hints,
+			DerObjectIdentifier	contentType,
+			DerUtf8String		description)
+		{
+			checkMandatoryField("contentType", contentType, hints.ContentType);
+			checkOptionalField("description", description, hints.ContentDescription);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ContentHintsUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/CscaMasterListTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/CscaMasterListTest.cs
new file mode 100644
index 0000000..814e98b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/CscaMasterListTest.cs
@@ -0,0 +1,57 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Icao;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class CscaMasterListTest
+        : SimpleTest
+    {
+		public override string Name
+		{
+			get { return "CscaMasterList"; }
+		}
+
+		public override void PerformTest() 
+		{
+			byte[] input = GetInput("masterlist-content.data");
+			CscaMasterList parsedList = CscaMasterList.GetInstance(Asn1Object.FromByteArray(input));
+
+			if (parsedList.GetCertStructs().Length != 3)
+			{
+				Fail("Cert structure parsing failed: incorrect length");
+			}
+
+			byte[] output = parsedList.GetEncoded();
+			if (!AreEqual(input, output))
+			{
+				Fail("Encoding failed after parse");
+			}
+		}
+
+		private byte[] GetInput(string name)
+		{
+			return Streams.ReadAll(SimpleTest.GetTestDataAsStream("asn1." + name));
+		}
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new CscaMasterListTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/DERApplicationSpecificTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/DERApplicationSpecificTest.cs
new file mode 100644
index 0000000..a61ae87
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/DERApplicationSpecificTest.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class DerApplicationSpecificTest
+		: SimpleTest
+	{
+		private static readonly byte[] impData = Hex.Decode("430109");
+
+		private static readonly byte[] certData = Hex.Decode(
+			  "7F218201897F4E8201495F290100420E44454356434145504153533030317F49"
+			+ "81FD060A04007F00070202020202811CD7C134AA264366862A18302575D1D787"
+			+ "B09F075797DA89F57EC8C0FF821C68A5E62CA9CE6C1C299803A6C1530B514E18"
+			+ "2AD8B0042A59CAD29F43831C2580F63CCFE44138870713B1A92369E33E2135D2"
+			+ "66DBB372386C400B8439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C"
+			+ "1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D376"
+			+ "1402CD851CD7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A793"
+			+ "9F863904393EE8E06DB6C7F528F8B4260B49AA93309824D92CDB1807E5437EE2"
+			+ "E26E29B73A7111530FA86B350037CB9415E153704394463797139E148701015F"
+			+ "200E44454356434145504153533030317F4C0E060904007F0007030102015301"
+			+ "C15F25060007000400015F24060009000400015F37384CCF25C59F3612EEE188"
+			+ "75F6C5F2E2D21F0395683B532A26E4C189B71EFE659C3F26E0EB9AEAE9986310"
+			+ "7F9B0DADA16414FFA204516AEE2B");
+
+		public override string Name
+		{
+			get { return "DerApplicationSpecific"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerInteger val = new DerInteger(9);
+
+			DerApplicationSpecific tagged = new DerApplicationSpecific(false, 3, val);
+
+			if (!AreEqual(impData, tagged.GetEncoded()))
+			{
+				Fail("implicit encoding failed");
+			}
+
+			DerInteger recVal = (DerInteger) tagged.GetObject(Asn1Tags.Integer);
+
+			if (!val.Equals(recVal))
+			{
+				Fail("implicit read back failed");
+			}
+
+			DerApplicationSpecific certObj = (DerApplicationSpecific)
+				Asn1Object.FromByteArray(certData);
+
+			if (!certObj.IsConstructed() || certObj.ApplicationTag != 33)
+			{
+				Fail("parsing of certificate data failed");
+			}
+
+			byte[] encoded = certObj.GetDerEncoded();
+
+			if (!Arrays.AreEqual(certData, encoded))
+			{
+				Console.WriteLine(Encoding.ASCII.GetString(certData, 0, certData.Length).Substring(0, 20));
+				Console.WriteLine(Encoding.ASCII.GetString(encoded, 0, encoded.Length).Substring(0, 20));
+				Fail("re-encoding of certificate data failed");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DerApplicationSpecificTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/DERUTF8StringTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/DERUTF8StringTest.cs
new file mode 100644
index 0000000..be4dace
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/DERUTF8StringTest.cs
@@ -0,0 +1,113 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class DerUtf8StringTest
+		: ITest
+	{
+		/**
+			* Unicode code point U+10400 coded as surrogate in two native Java UTF-16
+			* code units
+			*/
+		private readonly static char[] glyph1_utf16 = { (char)0xd801, (char)0xdc00 };
+
+		/**
+		 * U+10400 coded in UTF-8
+		 */
+		private readonly static byte[] glyph1_utf8 = { (byte)0xF0, (byte)0x90, (byte)0x90, (byte)0x80 };
+
+		/**
+		 * Unicode code point U+6771 in native Java UTF-16
+		 */
+		private readonly static char[] glyph2_utf16 = { (char)0x6771 };
+
+		/**
+		 * U+6771 coded in UTF-8
+		 */
+		private readonly static byte[] glyph2_utf8 = { (byte)0xE6, (byte)0x9D, (byte)0xB1 };
+
+		/**
+		 * Unicode code point U+00DF in native Java UTF-16
+		 */
+		private readonly static char[] glyph3_utf16 = { (char)0x00DF };
+
+		/**
+		 * U+00DF coded in UTF-8
+		 */
+		private readonly static byte[] glyph3_utf8 = { (byte)0xC3, (byte)0x9f };
+
+		/**
+		 * Unicode code point U+0041 in native Java UTF-16
+		 */
+		private readonly static char[] glyph4_utf16 = { (char)0x0041 };
+
+		/**
+		 * U+0041 coded in UTF-8
+		 */
+		private readonly static byte[] glyph4_utf8 = { 0x41 };
+
+		private readonly static byte[][] glyphs_utf8 = { glyph1_utf8, glyph2_utf8, glyph3_utf8, glyph4_utf8 };
+
+		private readonly static char[][] glyphs_utf16 = { glyph1_utf16, glyph2_utf16, glyph3_utf16, glyph4_utf16 };
+
+		public ITestResult Perform()
+		{
+			try
+			{
+				for (int i = 0; i < glyphs_utf16.Length; i++)
+				{
+					string s = new string(glyphs_utf16[i]);
+					byte[] b1 = new DerUtf8String(s).GetEncoded();
+					byte[] temp = new byte[b1.Length - 2];
+					Array.Copy(b1, 2, temp, 0, b1.Length - 2);
+					byte[] b2 = new DerUtf8String(new DerOctetString(temp).GetOctets()).GetEncoded();
+					if (!Arrays.AreEqual(b1, b2))
+					{
+						return new SimpleTestResult(false, Name + ": failed UTF-8 encoding and decoding");
+					}
+					if (!Arrays.AreEqual(temp, glyphs_utf8[i]))
+					{
+						return new SimpleTestResult(false, Name + ": failed UTF-8 encoding and decoding");
+					}
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed with Exception " + e.Message);
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public string Name
+		{
+			get
+			{
+				return "DERUTF8String";
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			DerUtf8StringTest test = new DerUtf8StringTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/DataGroupHashUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/DataGroupHashUnitTest.cs
new file mode 100644
index 0000000..dcebf46
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/DataGroupHashUnitTest.cs
@@ -0,0 +1,106 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Icao;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class DataGroupHashUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "DataGroupHash"; }
+        }
+
+		private byte[] GenerateHash()
+        {
+            Random rand = new Random();
+            byte[] bytes = new byte[20];
+			rand.NextBytes(bytes);
+			return bytes;
+        }
+
+		public override void PerformTest()
+        {
+            int dataGroupNumber = 1;
+            Asn1OctetString dataHash = new DerOctetString(GenerateHash());
+            DataGroupHash dg = new DataGroupHash(dataGroupNumber, dataHash);
+
+            CheckConstruction(dg, dataGroupNumber, dataHash);
+
+			try
+			{
+				DataGroupHash.GetInstance(null);
+			}
+			catch (Exception)
+			{
+				Fail("GetInstance() failed to handle null.");
+			}
+
+			try
+            {
+                DataGroupHash.GetInstance(new object());
+
+				Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckConstruction(
+            DataGroupHash dg,
+            int dataGroupNumber,
+            Asn1OctetString     dataGroupHashValue)
+        {
+            CheckValues(dg, dataGroupNumber, dataGroupHashValue);
+
+			dg = DataGroupHash.GetInstance(dg);
+
+			CheckValues(dg, dataGroupNumber, dataGroupHashValue);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				dg.ToAsn1Object().GetEncoded());
+
+			dg = DataGroupHash.GetInstance(seq);
+
+			CheckValues(dg, dataGroupNumber, dataGroupHashValue);
+        }
+
+		private void CheckValues(
+            DataGroupHash	dg,
+            int				dataGroupNumber,
+            Asn1OctetString	dataGroupHashValue)
+        {
+            if (dg.DataGroupNumber != dataGroupNumber)
+            {
+                Fail("group number don't match.");
+            }
+
+			if (!dg.DataGroupHashValue.Equals(dataGroupHashValue))
+            {
+                Fail("hash value don't match.");
+            }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new DataGroupHashUnitTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs
new file mode 100644
index 0000000..bd1fb5a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/DeclarationOfMajorityUnitTest.cs
@@ -0,0 +1,97 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class DeclarationOfMajorityUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "DeclarationOfMajority"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerGeneralizedTime dateOfBirth = new DerGeneralizedTime("20070315173729Z");
+			DeclarationOfMajority decl = new DeclarationOfMajority(dateOfBirth);
+
+			checkConstruction(decl, DeclarationOfMajority.Choice.DateOfBirth, dateOfBirth, -1);
+
+			decl = new DeclarationOfMajority(6);
+
+			checkConstruction(decl, DeclarationOfMajority.Choice.NotYoungerThan, null, 6);
+
+			decl = DeclarationOfMajority.GetInstance(null);
+
+			if (decl != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				DeclarationOfMajority.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			DeclarationOfMajority			decl,
+			DeclarationOfMajority.Choice	type,
+			DerGeneralizedTime				dateOfBirth,
+			int								notYoungerThan)
+		{
+			checkValues(decl, type, dateOfBirth, notYoungerThan);
+
+			decl = DeclarationOfMajority.GetInstance(decl);
+
+			checkValues(decl, type, dateOfBirth, notYoungerThan);
+
+			Asn1InputStream aIn = new Asn1InputStream(decl.ToAsn1Object().GetEncoded());
+
+			DerTaggedObject info = (DerTaggedObject) aIn.ReadObject();
+
+			decl = DeclarationOfMajority.GetInstance(info);
+
+			checkValues(decl, type, dateOfBirth, notYoungerThan);
+		}
+
+		private void checkValues(
+			DeclarationOfMajority			decl,
+			DeclarationOfMajority.Choice	type,
+			DerGeneralizedTime				dateOfBirth,
+			int								notYoungerThan)
+		{
+			checkMandatoryField("type", (int) type, (int) decl.Type);
+			checkOptionalField("dateOfBirth", dateOfBirth, decl.DateOfBirth);
+			if (notYoungerThan != -1 && notYoungerThan != decl.NotYoungerThan)
+			{
+				Fail("notYoungerThan mismatch");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DeclarationOfMajorityUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs
new file mode 100644
index 0000000..a84df59
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/EncryptedPrivateKeyInfoTest.cs
@@ -0,0 +1,152 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    /**
+     * Test the reading and writing of EncryptedPrivateKeyInfo objects using
+     * the test vectors provided at
+     * <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+     * RSA's Pkcs5 Page</a>.
+     * <br/>
+     * The vectors are Base 64 encoded and encrypted using the password "password"
+     * (without quotes). They should all yield the same PrivateKeyInfo object.
+     */
+    [TestFixture]
+    public class EncryptedPrivateKeyInfoTest
+        : ITest
+    {
+		static byte[] sample1 = Base64.Decode(
+			  "MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA"
+			+ "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y"
+			+ "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ"
+			+ "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo"
+			+ "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO"
+			+ "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v"
+			+ "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQgrThGfOv72bUncXEMNtc8pks"
+			+ "2jpHFjGMdKufnadAD7XuMgzkkaklEXZ4f5tU6heIIwr51g0GBEGF96gYPFnjnSQM"
+			+ "75JE02Clo+DfcfXpcybPTwwFg2jd6JTTOfkdf6OdSlA/1XNK43FA");
+
+		static byte[] sample2 = Base64.Decode(
+			  "MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA"
+			+ "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/"
+			+ "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8"
+			+ "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5"
+			+ "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi"
+			+ "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ"
+			+ "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrXE9XR3tPayE+iOB15llFSmi8"
+			+ "z0ByOXldEpkezCn92Umk++suzIVj1qfsK+bv2phZWJPbLEIWPDRHUbYf76q5ArAr"
+			+ "u4xtxT/hoK3krEs/IN3d70qjlUJ36SEw1UaZ82PWhakQbdtu39ZraMJB");
+
+		static byte[] sample3 = Base64.Decode(
+			  "MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA"
+			+ "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop"
+			+ "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f"
+			+ "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21"
+			+ "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6"
+			+ "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1"
+			+ "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8RqH2MRyblsPNSikyYhxX/cz"
+			+ "tdDxRKhilySbSBg5Kr8OfcwKp9bpinN96nmG4xr3Tch1bnVvqJzOQ5+Vva2WwVvH"
+			+ "2JkWvYm5WaANg4Q6bRxu9vz7DuhbJjQdZbxFezIAgrJdSe92B00jO/0Kny1WjiVO"
+			+ "6DA=");
+
+		public string Name
+		{
+			get { return "EncryptedPrivateKeyInfoTest"; }
+		}
+
+        private ITestResult DoTest(
+            int		id,
+            byte[]	sample)
+        {
+            EncryptedPrivateKeyInfo info;
+            try
+            {
+				info = EncryptedPrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(sample));
+            }
+            catch (Exception e)
+            {
+                return new SimpleTestResult(false, Name + ": test " + id + " failed construction - exception "
+                    + e.ToString());
+            }
+
+			byte[] bytes;
+            try
+            {
+            	bytes = info.GetDerEncoded();
+            }
+            catch (Exception e)
+            {
+                return new SimpleTestResult(false,
+                    Name + ": test " + id + " failed writing - exception " + e.ToString());
+            }
+
+            if (!Arrays.AreEqual(bytes, sample))
+            {
+                try
+                {
+                    Asn1Object obj = Asn1Object.FromByteArray(bytes);
+
+                    return new SimpleTestResult(false, Name + ": test " + id
+                        + " length mismatch - expected " + sample.Length + SimpleTest.NewLine
+                        + Asn1Dump.DumpAsString(info) + " got " + bytes.Length + SimpleTest.NewLine
+                        + Asn1Dump.DumpAsString(obj));
+                }
+                catch (Exception e)
+                {
+                    return new SimpleTestResult(false, Name + ": test " + id + " data mismatch - exception " + e.ToString());
+                }
+            }
+
+            return new SimpleTestResult(true, Name + ": test " + id + " Okay");
+        }
+
+        public ITestResult Perform()
+        {
+            ITestResult  result = DoTest(0, sample1);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            result = DoTest(1, sample2);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            result = DoTest(2, sample3);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new EncryptedPrivateKeyInfoTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/EnumeratedTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/EnumeratedTest.cs
new file mode 100644
index 0000000..29e9032
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/EnumeratedTest.cs
@@ -0,0 +1,115 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    /// <summary>
+    /// Tests used to verify correct decoding of the ENUMERATED type.
+    /// </summary>
+    [TestFixture]
+    public class EnumeratedTest
+    {
+        /// <summary>
+        /// Test vector used to test decoding of multiple items.
+        /// </summary>
+        /// <remarks>This sample uses an ENUMERATED and a BOOLEAN.</remarks>
+        private static readonly byte[] MultipleSingleByteItems = Hex.Decode("30060a01010101ff");
+
+        /// <summary>
+        /// Test vector used to test decoding of multiple items.
+        /// </summary>
+        /// <remarks>This sample uses two ENUMERATEDs.</remarks>
+        private static readonly byte[] MultipleDoubleByteItems = Hex.Decode("30080a0201010a020202");
+
+        /// <summary>
+        /// Test vector used to test decoding of multiple items.
+        /// </summary>
+        /// <remarks>This sample uses an ENUMERATED and an OBJECT IDENTIFIER.</remarks>
+        private static readonly byte[] MultipleTripleByteItems = Hex.Decode("300a0a0301010106032b0601");
+
+        /// <summary>
+        /// Makes sure multiple identically sized values are parsed correctly.
+        /// </summary>
+        [Test]
+        public void TestReadingMultipleSingleByteItems()
+        {
+            Asn1Object obj = Asn1Object.FromByteArray(MultipleSingleByteItems);
+
+            Assert.IsTrue(obj is DerSequence, "Null ASN.1 SEQUENCE");
+
+            DerSequence sequence = (DerSequence)obj;
+
+            Assert.AreEqual(2, sequence.Count, "2 items expected");
+
+            DerEnumerated enumerated = sequence[0] as DerEnumerated;
+
+            Assert.IsNotNull(enumerated, "ENUMERATED expected");
+
+            Assert.AreEqual(1, enumerated.Value.IntValue, "Unexpected ENUMERATED value");
+
+            DerBoolean boolean = sequence[1] as DerBoolean;
+
+            Assert.IsNotNull(boolean, "BOOLEAN expected");
+
+            Assert.IsTrue(boolean.IsTrue, "Unexpected BOOLEAN value");
+        }
+
+        /// <summary>
+        /// Makes sure multiple identically sized values are parsed correctly.
+        /// </summary>
+        [Test]
+        public void TestReadingMultipleDoubleByteItems()
+        {
+            Asn1Object obj = Asn1Object.FromByteArray(MultipleDoubleByteItems);
+
+            Assert.IsTrue(obj is DerSequence, "Null ASN.1 SEQUENCE");
+
+            DerSequence sequence = (DerSequence)obj;
+
+            Assert.AreEqual(2, sequence.Count, "2 items expected");
+
+            DerEnumerated enumerated1 = sequence[0] as DerEnumerated;
+
+            Assert.IsNotNull(enumerated1, "ENUMERATED expected");
+
+            Assert.AreEqual(257, enumerated1.Value.IntValue, "Unexpected ENUMERATED value");
+
+            DerEnumerated enumerated2 = sequence[1] as DerEnumerated;
+
+            Assert.IsNotNull(enumerated2, "ENUMERATED expected");
+
+            Assert.AreEqual(514, enumerated2.Value.IntValue, "Unexpected ENUMERATED value");
+        }
+
+        /// <summary>
+        /// Makes sure multiple identically sized values are parsed correctly.
+        /// </summary>
+        [Test]
+        public void TestReadingMultipleTripleByteItems()
+        {
+            Asn1Object obj = Asn1Object.FromByteArray(MultipleTripleByteItems);
+
+            Assert.IsTrue(obj is DerSequence, "Null ASN.1 SEQUENCE");
+
+            DerSequence sequence = (DerSequence)obj;
+
+            Assert.AreEqual(2, sequence.Count, "2 items expected");
+
+            DerEnumerated enumerated = sequence[0] as DerEnumerated;
+
+            Assert.IsNotNull(enumerated, "ENUMERATED expected");
+
+            Assert.AreEqual(65793, enumerated.Value.IntValue, "Unexpected ENUMERATED value");
+
+            DerObjectIdentifier objectId = sequence[1] as DerObjectIdentifier;
+
+            Assert.IsNotNull(objectId, "OBJECT IDENTIFIER expected");
+
+            Assert.AreEqual("1.3.6.1", objectId.Id, "Unexpected OBJECT IDENTIFIER value");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/EqualsAndHashCodeTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/EqualsAndHashCodeTest.cs
new file mode 100644
index 0000000..7e06953
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/EqualsAndHashCodeTest.cs
@@ -0,0 +1,93 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class EqualsAndHashCodeTest
+        : SimpleTest
+    {
+        public override void PerformTest()
+        {
+            byte[] data = { 0, 1, 0, 1, 0, 0, 1 };
+
+			Asn1Object[] values =
+			{
+                new BerOctetString(data),
+                new BerSequence(new DerPrintableString("hello world")),
+                new BerSet(new DerPrintableString("hello world")),
+                new BerTaggedObject(0, new DerPrintableString("hello world")),
+				new DerApplicationSpecific(0, data),
+                new DerBitString(data),
+                new DerBmpString("hello world"),
+                DerBoolean.True,
+                DerBoolean.False,
+                new DerEnumerated(100),
+				new DerGeneralizedTime("20070315173729Z"),
+				new DerGeneralString("hello world"),
+                new DerIA5String("hello"),
+                new DerInteger(1000),
+                DerNull.Instance,
+                new DerNumericString("123456"),
+                new DerObjectIdentifier("1.1.1.10000.1"),
+                new DerOctetString(data),
+                new DerPrintableString("hello world"),
+                new DerSequence(new DerPrintableString("hello world")),
+                new DerSet(new DerPrintableString("hello world")),
+                new DerT61String("hello world"),
+                new DerTaggedObject(0, new DerPrintableString("hello world")),
+                new DerUniversalString(data),
+                new DerUtcTime(new DateTime()),
+                new DerUtf8String("hello world"),
+                new DerVisibleString("hello world")
+            };
+
+			MemoryStream bOut = new MemoryStream();
+            Asn1OutputStream aOut = new Asn1OutputStream(bOut);
+
+            for (int i = 0; i != values.Length; i++)
+            {
+                aOut.WriteObject(values[i]);
+            }
+
+			Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray());
+
+			for (int i = 0; i != values.Length; i++)
+            {
+                Asn1Object o = aIn.ReadObject();
+                if (!o.Equals(values[i]))
+                {
+                    Fail("Failed equality test for " + o.GetType().Name);
+                }
+
+                if (o.GetHashCode() != values[i].GetHashCode())
+                {
+                    Fail("Failed hashCode test for " + o.GetType().Name);
+                }
+            }
+        }
+
+		public override string Name
+		{
+			get { return "EqualsAndHashCode"; }
+		}
+
+        public static void Main(
+            string[] args)
+        {
+			RunTest(new EqualsAndHashCodeTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/EssCertIDv2UnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/EssCertIDv2UnitTest.cs
new file mode 100644
index 0000000..9aac777
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/EssCertIDv2UnitTest.cs
@@ -0,0 +1,46 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ess;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+	public class EssCertIDv2UnitTest
+	: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "ESSCertIDv2"; }
+		}
+
+		public override void PerformTest()
+		{
+			// check GetInstance on default algorithm.
+			byte[] digest = new byte[32];
+			EssCertIDv2 essCertIdv2 = new EssCertIDv2(
+				new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256), digest);
+			Asn1Object asn1Object = essCertIdv2.ToAsn1Object();
+
+			EssCertIDv2.GetInstance(asn1Object);
+		}
+	
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new EssCertIDv2UnitTest());
+		}
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralNameTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralNameTest.cs
new file mode 100644
index 0000000..e9c3b58
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralNameTest.cs
@@ -0,0 +1,116 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class GeneralNameTest
+		: SimpleTest
+	{
+		private static readonly byte[] ipv4 = Hex.Decode("87040a090800");
+		private static readonly byte[] ipv4WithMask = Hex.Decode("87080a090800ffffff00");
+
+		private static readonly byte[] ipv6a = Hex.Decode("871020010db885a308d313198a2e03707334");
+		private static readonly byte[] ipv6b = Hex.Decode("871020010db885a3000013198a2e03707334");
+		private static readonly byte[] ipv6c = Hex.Decode("871000000000000000000000000000000001");
+		private static readonly byte[] ipv6d = Hex.Decode("871020010db885a3000000008a2e03707334");
+		private static readonly byte[] ipv6e = Hex.Decode("871020010db885a3000000008a2e0a090800");
+		private static readonly byte[] ipv6f = Hex.Decode("872020010db885a3000000008a2e0a090800ffffffffffff00000000000000000000");
+		private static readonly byte[] ipv6g = Hex.Decode("872020010db885a3000000008a2e0a090800ffffffffffffffffffffffffffffffff");
+		private static readonly byte[] ipv6h = Hex.Decode("872020010db885a300000000000000000000ffffffffffff00000000000000000000");
+	    
+		public override string Name
+		{
+			get { return "GeneralName"; }
+		}
+
+		public override void PerformTest()
+		{
+			GeneralName nm = new GeneralName(GeneralName.IPAddress, "10.9.8.0");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv4))
+			{
+				Fail("ipv4 encoding failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "10.9.8.0/255.255.255.0");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv4WithMask))
+			{
+				Fail("ipv4 with netmask 1 encoding failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "10.9.8.0/24");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv4WithMask))
+			{
+				Fail("ipv4 with netmask 2 encoding failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3:08d3:1319:8a2e:0370:7334");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6a))
+			{
+				Fail("ipv6 with netmask encoding failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::1319:8a2e:0370:7334");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6b))
+			{
+				Fail("ipv6b encoding failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "::1");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6c))
+			{
+				Fail("ipv6c failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::8a2e:0370:7334");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6d))
+			{
+				Fail("ipv6d failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::8a2e:10.9.8.0");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6e))
+			{
+				Fail("ipv6e failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/ffff:ffff:ffff::0000");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6f))
+			{
+				Fail("ipv6f failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::8a2e:10.9.8.0/128");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6g))
+			{
+				Fail("ipv6g failed");
+			}
+
+			nm = new GeneralName(GeneralName.IPAddress, "2001:0db8:85a3::/48");
+			if (!Arrays.AreEqual(nm.GetEncoded(), ipv6h))
+			{
+				Fail("ipv6h failed");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new GeneralNameTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(resultText, Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralizedTimeTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralizedTimeTest.cs
new file mode 100644
index 0000000..51995e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/GeneralizedTimeTest.cs
@@ -0,0 +1,231 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    /**
+     * X.690 test example
+     */
+    [TestFixture]
+    public class GeneralizedTimeTest
+        : SimpleTest
+    {
+        private static readonly string[] input =
+        {
+            "20020122122220",
+            "20020122122220Z",
+            "20020122122220-1000",
+            "20020122122220+00",
+            "20020122122220.1",
+            "20020122122220.1Z",
+            "20020122122220.1-1000",
+            "20020122122220.1+00",
+            "20020122122220.01",
+            "20020122122220.01Z",
+            "20020122122220.01-1000",
+            "20020122122220.01+00",
+            "20020122122220.001",
+            "20020122122220.001Z",
+            "20020122122220.001-1000",
+            "20020122122220.001+00",
+            "20020122122220.0001",
+            "20020122122220.0001Z",
+            "20020122122220.0001-1000",
+            "20020122122220.0001+00",
+            "20020122122220.0001+1000"
+        };
+
+        private static readonly string[] output =
+        {
+            "20020122122220",
+            "20020122122220GMT+00:00",
+            "20020122122220GMT-10:00",
+            "20020122122220GMT+00:00",
+            "20020122122220.1",
+            "20020122122220.1GMT+00:00",
+            "20020122122220.1GMT-10:00",
+            "20020122122220.1GMT+00:00",
+            "20020122122220.01",
+            "20020122122220.01GMT+00:00",
+            "20020122122220.01GMT-10:00",
+            "20020122122220.01GMT+00:00",
+            "20020122122220.001",
+            "20020122122220.001GMT+00:00",
+            "20020122122220.001GMT-10:00",
+            "20020122122220.001GMT+00:00",
+            "20020122122220.0001",
+            "20020122122220.0001GMT+00:00",
+            "20020122122220.0001GMT-10:00",
+            "20020122122220.0001GMT+00:00",
+            "20020122122220.0001GMT+10:00"
+        };
+
+        private static readonly string[] zOutput =
+        {
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122222220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122222220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122222220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122222220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122122220Z",
+            "20020122222220Z",
+            "20020122122220Z",
+            "20020122022220Z"
+        };
+        
+        private static readonly string[] mzOutput =
+        {
+            "20020122122220.000Z",
+            "20020122122220.000Z",
+            "20020122222220.000Z",
+            "20020122122220.000Z",
+            "20020122122220.100Z",
+            "20020122122220.100Z",
+            "20020122222220.100Z",
+            "20020122122220.100Z",
+            "20020122122220.010Z",
+            "20020122122220.010Z",
+            "20020122222220.010Z",
+            "20020122122220.010Z",
+            "20020122122220.001Z",
+            "20020122122220.001Z",
+            "20020122222220.001Z",
+            "20020122122220.001Z",
+            "20020122122220.000Z",
+            "20020122122220.000Z",
+            "20020122222220.000Z",
+            "20020122122220.000Z",
+            "20020122022220.000Z"
+        };
+
+        public override string Name
+        {
+            get { return "GeneralizedTime"; }
+        }
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i != input.Length; i++)
+            {
+                string ii = input[i], oi = output[i];
+
+                DerGeneralizedTime t = new DerGeneralizedTime(ii);
+                DateTime dt = t.ToDateTime();
+                string st = t.GetTime();
+
+                if (oi.IndexOf('G') > 0)   // don't check local time the same way
+                {
+                    if (!st.Equals(oi))
+                    {
+                        Fail("failed conversion test");
+                    }
+
+                    string dts = dt.ToString(@"yyyyMMddHHmmss\Z");
+                    string zi = zOutput[i];
+                    if (!dts.Equals(zi))
+                    {
+                        Fail("failed date conversion test");
+                    }
+                }
+                else
+                {
+                    string offset = CalculateGmtOffset(dt);
+                    if (!st.Equals(oi + offset))
+                    {
+                        Fail("failed conversion test");
+                    }
+                }
+            }
+
+            for (int i = 0; i != input.Length; i++)
+            {
+                DerGeneralizedTime t = new DerGeneralizedTime(input[i]);
+
+                if (!t.ToDateTime().ToString(@"yyyyMMddHHmmss.fff\Z").Equals(mzOutput[i]))
+                {
+                    Console.WriteLine("{0} != {1}", t.ToDateTime().ToString(@"yyyyMMddHHmmss.SSS\Z"), mzOutput[i]);
+
+                    Fail("failed long date conversion test");
+                }
+            }
+
+            /*
+             * [BMA-87]
+             */
+            {
+                DateTime t1 = new DerUtcTime("110616114855Z").ToDateTime();
+                DateTime t2 = new DerGeneralizedTime("20110616114855Z").ToDateTime();
+
+                if (t1 != t2)
+                {
+                    Fail("failed UTC equivalence test");
+                }
+
+                DateTime u1 = t1.ToUniversalTime();
+                DateTime u2 = t2.ToUniversalTime();
+
+                if (u1 != u2)
+                {
+                    Fail("failed UTC conversion test");
+                }
+            }
+        }
+
+        private string CalculateGmtOffset(
+            DateTime date)
+        {
+            char sign = '+';
+
+            // Note: GetUtcOffset incorporates Daylight Savings offset
+            TimeSpan offset =  TimeZone.CurrentTimeZone.GetUtcOffset(date);
+            if (offset.CompareTo(TimeSpan.Zero) < 0)
+            {
+                sign = '-';
+                offset = offset.Duration();
+            }
+            int hours = offset.Hours;
+            int minutes = offset.Minutes;
+
+            return "GMT" + sign + Convert(hours) + ":" + Convert(minutes);
+        }
+
+        private string Convert(int time)
+        {
+            if (time < 10)
+            {
+                return "0" + time;
+            }
+
+            return time.ToString();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new GeneralizedTimeTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/GenerationTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/GenerationTest.cs
new file mode 100644
index 0000000..534f76b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/GenerationTest.cs
@@ -0,0 +1,325 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class GenerationTest
+        :	SimpleTest
+    {
+        private static readonly byte[] v1Cert = Base64.Decode(
+			"MIGtAgEBMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYDVQQKDA1Cb"
+			+ "3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAxMlowNjELMA"
+			+ "kGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNVBAsMBlRlc3Q"
+			+ "gMTAaMA0GCSqGSIb3DQEBAQUAAwkAMAYCAQECAQI=");
+
+		private static readonly byte[] v3Cert = Base64.Decode(
+			"MIIBSKADAgECAgECMA0GCSqGSIb3DQEBBAUAMCUxCzAJBgNVBAMMAkFVMRYwFAYD"
+			+ "VQQKDA1Cb3VuY3kgQ2FzdGxlMB4XDTcwMDEwMTAwMDAwMVoXDTcwMDEwMTAwMDAw"
+			+ "MlowNjELMAkGA1UEAwwCQVUxFjAUBgNVBAoMDUJvdW5jeSBDYXN0bGUxDzANBgNV"
+			+ "BAsMBlRlc3QgMjAYMBAGBisOBwIBATAGAgEBAgECAwQAAgEDo4GVMIGSMGEGA1Ud"
+			+ "IwEB/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJB"
+			+ "VTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMCAG"
+			+ "A1UdDgEB/wQWBBQ2T3aRz8you6PBCaJJEFNrqgh0UTALBgNVHQ8EBAMCBBA=");
+
+		private static readonly byte[] v3CertNullSubject = Base64.Decode(
+			"MIHGoAMCAQICAQIwDQYJKoZIhvcNAQEEBQAwJTELMAkGA1UEAwwCQVUxFjAUBgNVB"
+			+ "AoMDUJvdW5jeSBDYXN0bGUwHhcNNzAwMTAxMDAwMDAxWhcNNzAwMTAxMDAwMDAyWj"
+			+ "AAMBgwEAYGKw4HAgEBMAYCAQECAQIDBAACAQOjSjBIMEYGA1UdEQEB/wQ8MDqkODA"
+			+ "2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwG"
+			+ "VGVzdCAy");
+
+		private static readonly byte[] v2CertList = Base64.Decode(
+			"MIIBRQIBATANBgkqhkiG9w0BAQUFADAlMQswCQYDVQQDDAJBVTEWMBQGA1UECgwN"
+			+ "Qm91bmN5IENhc3RsZRcNNzAwMTAxMDAwMDAwWhcNNzAwMTAxMDAwMDAyWjAkMCIC"
+			+ "AQEXDTcwMDEwMTAwMDAwMVowDjAMBgNVHRUEBQoDAIAAoIHFMIHCMGEGA1UdIwEB"
+			+ "/wRXMFWAFDZPdpHPzKi7o8EJokkQU2uqCHRRoTqkODA2MQswCQYDVQQDDAJBVTEW"
+			+ "MBQGA1UECgwNQm91bmN5IENhc3RsZTEPMA0GA1UECwwGVGVzdCAyggECMEMGA1Ud"
+			+ "EgQ8MDqkODA2MQswCQYDVQQDDAJBVTEWMBQGA1UECgwNQm91bmN5IENhc3RsZTEP"
+			+ "MA0GA1UECwwGVGVzdCAzMAoGA1UdFAQDAgEBMAwGA1UdHAEB/wQCMAA=");
+
+        private void TbsV1CertGenerate()
+        {
+			V1TbsCertificateGenerator gen = new V1TbsCertificateGenerator();
+            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
+            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 12, DateTimeKind.Utc);
+
+            gen.SetSerialNumber(new DerInteger(1));
+
+            gen.SetStartDate(new Time(startDate));
+            gen.SetEndDate(new Time(endDate));
+
+            gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle"));
+            gen.SetSubject(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 1"));
+
+            gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance));
+
+            SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(PkcsObjectIdentifiers.RsaEncryption, DerNull.Instance),
+                new RsaPublicKeyStructure(BigInteger.One, BigInteger.Two));
+
+            gen.SetSubjectPublicKeyInfo(info);
+
+            TbsCertificateStructure tbs = gen.GenerateTbsCertificate();
+
+			if (!Arrays.AreEqual(tbs.GetEncoded(), v1Cert))
+            {
+                Fail("failed v1 cert generation");
+            }
+
+            //
+            // read back test
+            //
+            Asn1InputStream aIn = new Asn1InputStream(v1Cert);
+            Asn1Object o = aIn.ReadObject();
+
+            if (!Arrays.AreEqual(o.GetEncoded(), v1Cert))
+            {
+                Fail("failed v1 cert read back test");
+            }
+        }
+
+		private AuthorityKeyIdentifier CreateAuthorityKeyId(
+            SubjectPublicKeyInfo	info,
+            X509Name				name,
+            int						sNumber)
+        {
+            GeneralName genName = new GeneralName(name);
+
+			return new AuthorityKeyIdentifier(
+				info,
+				GeneralNames.GetInstance(new DerSequence(genName)),
+				BigInteger.ValueOf(sNumber));
+        }
+
+		private void TbsV3CertGenerate()
+        {
+			V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator();
+            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
+            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc);
+
+			gen.SetSerialNumber(new DerInteger(2));
+
+			gen.SetStartDate(new Time(startDate));
+			gen.SetEndDate(new Time(endDate));
+
+			gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle"));
+			gen.SetSubject(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"));
+
+			gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance));
+
+			SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+				new AlgorithmIdentifier(
+					OiwObjectIdentifiers.ElGamalAlgorithm,
+					new ElGamalParameter(BigInteger.One, BigInteger.Two)),
+				new DerInteger(3));
+
+			gen.SetSubjectPublicKeyInfo(info);
+
+			//
+			// add extensions
+			//
+			IList order = new ArrayList();
+			IDictionary extensions = new Hashtable();
+
+			order.Add(X509Extensions.AuthorityKeyIdentifier);
+			order.Add(X509Extensions.SubjectKeyIdentifier);
+			order.Add(X509Extensions.KeyUsage);
+
+			extensions.Add(X509Extensions.AuthorityKeyIdentifier, new X509Extension(true, new DerOctetString(CreateAuthorityKeyId(info, new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2))));
+			extensions.Add(X509Extensions.SubjectKeyIdentifier, new X509Extension(true, new DerOctetString(new SubjectKeyIdentifier(info))));
+			extensions.Add(X509Extensions.KeyUsage, new X509Extension(false, new DerOctetString(new KeyUsage(KeyUsage.DataEncipherment))));
+
+			X509Extensions ex = new X509Extensions(order, extensions);
+
+			gen.SetExtensions(ex);
+
+			TbsCertificateStructure tbs = gen.GenerateTbsCertificate();
+
+			if (!Arrays.AreEqual(tbs.GetEncoded(), v3Cert))
+			{
+				Fail("failed v3 cert generation");
+			}
+
+			//
+			// read back test
+			//
+			Asn1Object o = Asn1Object.FromByteArray(v3Cert);
+
+			if (!Arrays.AreEqual(o.GetEncoded(), v3Cert))
+			{
+				Fail("failed v3 cert read back test");
+			}
+        }
+
+		private void TbsV3CertGenWithNullSubject()
+		{
+			V3TbsCertificateGenerator gen = new V3TbsCertificateGenerator();
+            DateTime startDate = new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc);
+            DateTime endDate = new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc);
+
+			gen.SetSerialNumber(new DerInteger(2));
+
+			gen.SetStartDate(new Time(startDate));
+			gen.SetEndDate(new Time(endDate));
+
+			gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle"));
+
+			gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5WithRsaEncryption, DerNull.Instance));
+
+			SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+				new AlgorithmIdentifier(OiwObjectIdentifiers.ElGamalAlgorithm,
+					new ElGamalParameter(BigInteger.One, BigInteger.Two)),
+				new DerInteger(3));
+
+			gen.SetSubjectPublicKeyInfo(info);
+
+			try
+			{
+				gen.GenerateTbsCertificate();
+				Fail("null subject not caught!");
+			}
+			catch (InvalidOperationException e)
+			{
+				if (!e.Message.Equals("not all mandatory fields set in V3 TBScertificate generator"))
+				{
+					Fail("unexpected exception", e);
+				}
+			}
+
+			//
+			// add extensions
+			//
+			IList order = new ArrayList();
+			IDictionary extensions = new Hashtable();
+
+			order.Add(X509Extensions.SubjectAlternativeName);
+
+			extensions.Add(
+				X509Extensions.SubjectAlternativeName,
+				new X509Extension(
+					true,
+					new DerOctetString(
+						new GeneralNames(
+							new GeneralName(
+								new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"))))));
+
+			X509Extensions ex = new X509Extensions(order, extensions);
+
+			gen.SetExtensions(ex);
+
+			TbsCertificateStructure tbs = gen.GenerateTbsCertificate();
+
+			if (!Arrays.AreEqual(tbs.GetEncoded(), v3CertNullSubject))
+			{
+				Fail("failed v3 null sub cert generation");
+			}
+
+			//
+			// read back test
+			//
+			Asn1Object o = Asn1Object.FromByteArray(v3CertNullSubject);
+
+			if (!Arrays.AreEqual(o.GetEncoded(), v3CertNullSubject))
+			{
+				Fail("failed v3 null sub cert read back test");
+			}
+		}
+
+		private void TbsV2CertListGenerate()
+        {
+            V2TbsCertListGenerator gen = new V2TbsCertListGenerator();
+
+            gen.SetIssuer(new X509Name("CN=AU,O=Bouncy Castle"));
+
+            gen.AddCrlEntry(new DerInteger(1), new Time(new DateTime(1970, 1, 1, 0, 0, 1, DateTimeKind.Utc)), ReasonFlags.AACompromise);
+
+            gen.SetNextUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 2, DateTimeKind.Utc)));
+
+            gen.SetThisUpdate(new Time(new DateTime(1970, 1, 1, 0, 0, 0, 500, DateTimeKind.Utc)));
+
+            gen.SetSignature(new AlgorithmIdentifier(PkcsObjectIdentifiers.Sha1WithRsaEncryption, DerNull.Instance));
+
+            //
+            // extensions
+            //
+            IList order = new ArrayList();
+            IDictionary extensions = new Hashtable();
+            SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(
+				new AlgorithmIdentifier(
+					OiwObjectIdentifiers.ElGamalAlgorithm,
+					new ElGamalParameter(BigInteger.One, BigInteger.Two)),
+				new DerInteger(3));
+
+			order.Add(X509Extensions.AuthorityKeyIdentifier);
+            order.Add(X509Extensions.IssuerAlternativeName);
+            order.Add(X509Extensions.CrlNumber);
+            order.Add(X509Extensions.IssuingDistributionPoint);
+
+            extensions.Add(X509Extensions.AuthorityKeyIdentifier, new X509Extension(true, new DerOctetString(CreateAuthorityKeyId(info, new X509Name("CN=AU,O=Bouncy Castle,OU=Test 2"), 2))));
+            extensions.Add(X509Extensions.IssuerAlternativeName, new X509Extension(false, new DerOctetString(GeneralNames.GetInstance(new DerSequence(new GeneralName(new X509Name("CN=AU,O=Bouncy Castle,OU=Test 3")))))));
+            extensions.Add(X509Extensions.CrlNumber, new X509Extension(false, new DerOctetString(new DerInteger(1))));
+            extensions.Add(X509Extensions.IssuingDistributionPoint, new X509Extension(true, new DerOctetString(IssuingDistributionPoint.GetInstance(DerSequence.Empty))));
+
+            X509Extensions ex = new X509Extensions(order, extensions);
+
+            gen.SetExtensions(ex);
+
+            TbsCertificateList tbs = gen.GenerateTbsCertList();
+
+            if (!Arrays.AreEqual(tbs.GetEncoded(), v2CertList))
+            {
+                Fail("failed v2 cert list generation");
+            }
+
+            //
+            // read back test
+            //
+            Asn1InputStream aIn = new Asn1InputStream(v2CertList);
+            Asn1Object o = aIn.ReadObject();
+
+            if (!Arrays.AreEqual(o.GetEncoded(), v2CertList))
+            {
+                Fail("failed v2 cert list read back test");
+            }
+        }
+
+		public override void PerformTest()
+        {
+            TbsV1CertGenerate();
+            TbsV3CertGenerate();
+			TbsV3CertGenWithNullSubject();
+            TbsV2CertListGenerate();
+        }
+
+		public override string Name
+		{
+			get { return "Generation"; }
+		}
+
+        public static void Main(
+            string[] args)
+        {
+			RunTest(new GenerationTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(resultText, Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/InputStreamTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/InputStreamTest.cs
new file mode 100644
index 0000000..1d92759
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/InputStreamTest.cs
@@ -0,0 +1,85 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class InputStreamTest
+		: SimpleTest
+	{
+		private static readonly byte[] outOfBoundsLength = new byte[] { (byte)0x30, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+		private static readonly byte[] negativeLength = new byte[] { (byte)0x30, (byte)0x84, (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+		private static readonly byte[] outsideLimitLength = new byte[] { (byte)0x30, (byte)0x83, (byte)0x0f, (byte)0xff, (byte)0xff };
+
+		public override string Name
+		{
+			get { return "InputStream"; }
+		}
+
+		public override void PerformTest()
+		{
+			Asn1InputStream aIn = new Asn1InputStream(outOfBoundsLength);
+
+			try
+			{
+				aIn.ReadObject();
+				Fail("out of bounds length not detected.");
+			}
+			catch (IOException e)
+			{
+				if (!e.Message.StartsWith("DER length more than 4 bytes"))
+				{
+					Fail("wrong exception: " + e.Message);
+				}
+			}
+
+			aIn = new Asn1InputStream(negativeLength);
+
+			try
+			{
+				aIn.ReadObject();
+				Fail("negative length not detected.");
+			}
+			catch (IOException e)
+			{
+				if (!e.Message.Equals("Corrupted stream - negative length found"))
+				{
+					Fail("wrong exception: " + e.Message);
+				}
+			}
+
+			aIn = new Asn1InputStream(outsideLimitLength);
+
+			try
+			{
+				aIn.ReadObject();
+				Fail("outside limit length not detected.");
+			}
+			catch (IOException e)
+			{
+				if (!e.Message.Equals("Corrupted stream - out of bounds length found"))
+				{
+					Fail("wrong exception: " + e.Message);
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new InputStreamTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs
new file mode 100644
index 0000000..bb6076a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/Iso4217CurrencyCodeUnitTest.cs
@@ -0,0 +1,156 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class Iso4217CurrencyCodeUnitTest
+        : SimpleTest
+    {
+        private const string AlphabeticCurrencyCode = "AUD";
+        private const int NUMERIC_CurrencyCode = 1;
+
+		public override string Name
+        {
+			get { return "Iso4217CurrencyCode"; }
+        }
+
+		public override void PerformTest()
+        {
+            //
+            // alphabetic
+            //
+            Iso4217CurrencyCode cc = new Iso4217CurrencyCode(AlphabeticCurrencyCode);
+
+            CheckNumeric(cc, AlphabeticCurrencyCode);
+
+            cc = Iso4217CurrencyCode.GetInstance(cc);
+
+            CheckNumeric(cc, AlphabeticCurrencyCode);
+
+            Asn1Object obj = cc.ToAsn1Object();
+
+            cc = Iso4217CurrencyCode.GetInstance(obj);
+
+            CheckNumeric(cc, AlphabeticCurrencyCode);
+
+            //
+            // numeric
+            //
+            cc = new Iso4217CurrencyCode(NUMERIC_CurrencyCode);
+
+            CheckNumeric(cc, NUMERIC_CurrencyCode);
+
+            cc = Iso4217CurrencyCode.GetInstance(cc);
+
+            CheckNumeric(cc, NUMERIC_CurrencyCode);
+
+            obj = cc.ToAsn1Object();
+
+            cc = Iso4217CurrencyCode.GetInstance(obj);
+
+            CheckNumeric(cc, NUMERIC_CurrencyCode);
+
+            cc = Iso4217CurrencyCode.GetInstance(null);
+
+            if (cc != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                Iso4217CurrencyCode.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new Iso4217CurrencyCode("ABCD");
+
+                Fail("constructor failed to detect out of range currencycode.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new Iso4217CurrencyCode(0);
+
+                Fail("constructor failed to detect out of range small numeric code.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new Iso4217CurrencyCode(1000);
+
+                Fail("constructor failed to detect out of range large numeric code.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        private void CheckNumeric(
+            Iso4217CurrencyCode cc,
+            string              code)
+        {
+            if (!cc.IsAlphabetic)
+            {
+                Fail("non-alphabetic code found when one expected.");
+            }
+
+            if (!cc.Alphabetic.Equals(code))
+            {
+                Fail("string codes don't match.");
+            }
+        }
+
+        private void CheckNumeric(
+            Iso4217CurrencyCode cc,
+            int                 code)
+        {
+            if (cc.IsAlphabetic)
+            {
+                Fail("alphabetic code found when one not expected.");
+            }
+
+            if (cc.Numeric != code)
+            {
+                Fail("numeric codes don't match.");
+            }
+        }
+
+        public static void Main(
+            string[]    args)
+        {
+            RunTest(new Iso4217CurrencyCodeUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/IssuingDistributionPointTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/IssuingDistributionPointTest.cs
new file mode 100644
index 0000000..b5f5c88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/IssuingDistributionPointTest.cs
@@ -0,0 +1,133 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class IssuingDistributionPointUnitTest 
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "IssuingDistributionPoint"; }
+		}
+
+		public override void PerformTest()
+		{
+			DistributionPointName name = new DistributionPointName(
+				new GeneralNames(new GeneralName(new X509Name("cn=test"))));
+			ReasonFlags reasonFlags = new ReasonFlags(ReasonFlags.CACompromise);
+
+			checkPoint(6, name, true, true, reasonFlags, true, true);
+
+			checkPoint(2, name, false, false, reasonFlags, false, false);
+
+			checkPoint(0, null, false, false, null, false, false);
+
+			try
+			{
+				IssuingDistributionPoint.GetInstance(new object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkPoint(
+			int						size,
+			DistributionPointName	distributionPoint,
+			bool					onlyContainsUserCerts,
+			bool					onlyContainsCACerts,
+			ReasonFlags				onlySomeReasons,
+			bool					indirectCRL,
+			bool					onlyContainsAttributeCerts)
+		{
+			IssuingDistributionPoint point = new IssuingDistributionPoint(distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+
+			checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+
+			Asn1Sequence seq = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(point.GetEncoded()));
+
+			if (seq.Count != size)
+			{
+				Fail("size mismatch");
+			}
+
+			point = IssuingDistributionPoint.GetInstance(seq);
+
+			checkValues(point, distributionPoint, onlyContainsUserCerts, onlyContainsCACerts, onlySomeReasons, indirectCRL, onlyContainsAttributeCerts);
+		}
+
+		private void checkValues(
+			IssuingDistributionPoint	point,
+			DistributionPointName		distributionPoint,
+			bool						onlyContainsUserCerts,
+			bool						onlyContainsCACerts,
+			ReasonFlags					onlySomeReasons,
+			bool						indirectCRL,
+			bool						onlyContainsAttributeCerts)
+		{
+			if (point.OnlyContainsUserCerts != onlyContainsUserCerts)
+			{
+				Fail("mismatch on onlyContainsUserCerts");
+			}
+
+			if (point.OnlyContainsCACerts != onlyContainsCACerts)
+			{
+				Fail("mismatch on onlyContainsCACerts");
+			}
+
+			if (point.IsIndirectCrl != indirectCRL)
+			{
+				Fail("mismatch on indirectCRL");
+			}
+
+			if (point.OnlyContainsAttributeCerts != onlyContainsAttributeCerts)
+			{
+				Fail("mismatch on onlyContainsAttributeCerts");
+			}
+
+			if (!isEquiv(onlySomeReasons, point.OnlySomeReasons))
+			{
+				Fail("mismatch on onlySomeReasons");
+			}
+
+			if (!isEquiv(distributionPoint, point.DistributionPoint))
+			{
+				Fail("mismatch on distributionPoint");
+			}
+		}
+
+		private bool isEquiv(object o1, object o2)
+		{
+			if (o1 == null)
+			{
+				return o2 == null;
+			}
+
+			return o1.Equals(o2);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new IssuingDistributionPointUnitTest());
+		}
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/KeyUsageTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/KeyUsageTest.cs
new file mode 100644
index 0000000..d7ed365
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/KeyUsageTest.cs
@@ -0,0 +1,49 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class KeyUsageTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get
+			{
+				return "KeyUsage";
+			}
+		}
+
+		public override void PerformTest()
+		{
+			BitStringConstantTester.testFlagValueCorrect(0, KeyUsage.DigitalSignature);
+			BitStringConstantTester.testFlagValueCorrect(1, KeyUsage.NonRepudiation);
+			BitStringConstantTester.testFlagValueCorrect(2, KeyUsage.KeyEncipherment);
+			BitStringConstantTester.testFlagValueCorrect(3, KeyUsage.DataEncipherment);
+			BitStringConstantTester.testFlagValueCorrect(4, KeyUsage.KeyAgreement);
+			BitStringConstantTester.testFlagValueCorrect(5, KeyUsage.KeyCertSign);
+			BitStringConstantTester.testFlagValueCorrect(6, KeyUsage.CrlSign);
+			BitStringConstantTester.testFlagValueCorrect(7, KeyUsage.EncipherOnly);
+			BitStringConstantTester.testFlagValueCorrect(8, KeyUsage.DecipherOnly);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new KeyUsageTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/LDSSecurityObjectUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/LDSSecurityObjectUnitTest.cs
new file mode 100644
index 0000000..0427816
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/LDSSecurityObjectUnitTest.cs
@@ -0,0 +1,208 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Icao;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class LDSSecurityObjectUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "LDSSecurityObject"; }
+        }
+
+		private byte[] GenerateHash()
+        {
+            Random rand = new Random();
+            byte[] bytes = new byte[20];
+            rand.NextBytes(bytes);
+            return bytes;
+        }
+
+        public override void PerformTest()
+        {
+            AlgorithmIdentifier  algoId = new AlgorithmIdentifier("1.3.14.3.2.26");
+            DataGroupHash[] datas = new DataGroupHash[2];
+
+            datas[0] = new DataGroupHash(1, new DerOctetString(GenerateHash()));
+            datas[1] = new DataGroupHash(2, new DerOctetString(GenerateHash()));
+
+            LdsSecurityObject so = new LdsSecurityObject(algoId, datas);
+
+			CheckConstruction(so, algoId, datas);
+
+			LdsVersionInfo versionInfo = new LdsVersionInfo("Hello", "world");
+
+			so = new LdsSecurityObject(algoId, datas, versionInfo);
+
+			CheckConstruction(so, algoId, datas, versionInfo);
+
+			try
+			{
+				LdsSecurityObject.GetInstance(null);
+			}
+			catch (Exception)
+			{
+				Fail("GetInstance() failed to handle null.");
+			}
+
+			try
+            {
+                LdsSecurityObject.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+			try
+            {
+				LdsSecurityObject.GetInstance(DerSequence.Empty);
+
+				Fail("constructor failed to detect empty sequence.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+			try
+            {
+                new LdsSecurityObject(algoId, new DataGroupHash[1]);
+
+				Fail("constructor failed to detect small DataGroupHash array.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+			try
+            {
+                new LdsSecurityObject(algoId, new DataGroupHash[LdsSecurityObject.UBDataGroups + 1]);
+
+				Fail("constructor failed to out of bounds DataGroupHash array.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckConstruction(
+            LdsSecurityObject	so,
+            AlgorithmIdentifier	digestAlgorithmIdentifier,
+            DataGroupHash[]		datagroupHash)
+        {
+            CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+
+			so = LdsSecurityObject.GetInstance(so);
+
+			CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				so.ToAsn1Object().GetEncoded());
+
+			so = LdsSecurityObject.GetInstance(seq);
+
+			CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, null);
+        }
+		
+		private void CheckConstruction(
+			LdsSecurityObject	so,
+			AlgorithmIdentifier	digestAlgorithmIdentifier,
+			DataGroupHash[]		datagroupHash,
+			LdsVersionInfo		versionInfo)
+		{
+			if (!so.Version.Equals(BigInteger.One))
+			{
+				Fail("version number not 1");
+			}
+
+			CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+
+			so = LdsSecurityObject.GetInstance(so);
+
+			CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				so.ToAsn1Object().GetEncoded());
+
+			so = LdsSecurityObject.GetInstance(seq);
+
+			CheckStatement(so, digestAlgorithmIdentifier, datagroupHash, versionInfo);
+		}
+
+		private void CheckStatement(
+            LdsSecurityObject	so,
+            AlgorithmIdentifier	digestAlgorithmIdentifier,
+            DataGroupHash[]		datagroupHash,
+			LdsVersionInfo		versionInfo)
+        {
+            if (digestAlgorithmIdentifier != null)
+            {
+                if (!so.DigestAlgorithmIdentifier.Equals(digestAlgorithmIdentifier))
+                {
+                    Fail("ids don't match.");
+                }
+            }
+            else if (so.DigestAlgorithmIdentifier != null)
+            {
+                Fail("digest algorithm Id found when none expected.");
+            }
+
+			if (datagroupHash != null)
+            {
+                DataGroupHash[] datas = so.GetDatagroupHash();
+
+                for (int i = 0; i != datas.Length; i++)
+                {
+                    if (!datagroupHash[i].Equals(datas[i]))
+                    {
+                        Fail("name registration authorities don't match.");
+                    }
+                }
+            }
+            else if (so.GetDatagroupHash() != null)
+            {
+                Fail("data hash groups found when none expected.");
+            }
+
+			if (versionInfo != null)
+			{
+				if (!versionInfo.Equals(so.VersionInfo))
+				{
+					Fail("versionInfo doesn't match");
+				}
+			}
+			else if (so.VersionInfo != null)
+			{
+				Fail("version info found when none expected.");
+			}
+        }
+
+		public static void Main(
+            string[]    args)
+        {
+            RunTest(new LDSSecurityObjectUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/MiscTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/MiscTest.cs
new file mode 100644
index 0000000..42f5dbd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/MiscTest.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class MiscTest
+        : ITest
+    {
+        public ITestResult Perform()
+        {
+            byte[] testIv = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+            Asn1Encodable[] values =
+            {
+                new Cast5CbcParameters(testIv, 128),
+                new NetscapeCertType(NetscapeCertType.Smime),
+                new VerisignCzagExtension(new DerIA5String("hello")),
+                new IdeaCbcPar(testIv),
+                new NetscapeRevocationUrl(new DerIA5String("http://test"))
+            };
+
+            byte[] data = Base64.Decode("MA4ECAECAwQFBgcIAgIAgAMCBSAWBWhlbGxvMAoECAECAwQFBgcIFgtodHRwOi8vdGVzdA==");
+
+            try
+            {
+                MemoryStream bOut = new MemoryStream();
+                Asn1OutputStream aOut = new Asn1OutputStream(bOut);
+
+                for (int i = 0; i != values.Length; i++)
+                {
+                    aOut.WriteObject(values[i]);
+                }
+
+                if (!Arrays.AreEqual(bOut.ToArray(), data))
+                {
+                    return new SimpleTestResult(false, Name + ": Failed data check");
+                }
+
+                Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray());
+
+                for (int i = 0; i != values.Length; i++)
+                {
+                    Asn1Object o = aIn.ReadObject();
+
+                    if (!values[i].Equals(o))
+                    {
+                        return new SimpleTestResult(false, Name + ": Failed equality test for " + o);
+                    }
+
+                    if (o.GetHashCode() != values[i].GetHashCode())
+                    {
+                        return new SimpleTestResult(false, Name + ": Failed hashCode test for " + o);
+                    }
+                }
+
+                return new SimpleTestResult(true, Name + ": Okay");
+            }
+            catch (Exception e)
+            {
+                return new SimpleTestResult(false, Name + ": Failed - exception " + e.ToString(), e);
+            }
+        }
+
+        public string Name
+        {
+            get { return "Misc"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new MiscTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryLimitUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryLimitUnitTest.cs
new file mode 100644
index 0000000..cdeb2ec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryLimitUnitTest.cs
@@ -0,0 +1,93 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class MonetaryLimitUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "MonetaryLimit"; }
+		}
+
+		public override void PerformTest()
+		{
+			string currency = "AUD";
+			int    amount = 1;
+			int    exponent = 2;
+
+			MonetaryLimit limit = new MonetaryLimit(currency, amount, exponent);
+
+			checkConstruction(limit, currency, amount, exponent);
+
+			limit = MonetaryLimit.GetInstance(null);
+
+			if (limit != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				MonetaryLimit.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			MonetaryLimit	limit,
+			string			currency,
+			int				amount,
+			int				exponent)
+		{
+			checkValues(limit, currency, amount, exponent);
+
+			limit = MonetaryLimit.GetInstance(limit);
+
+			checkValues(limit, currency, amount, exponent);
+
+			Asn1InputStream aIn = new Asn1InputStream(limit.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			limit = MonetaryLimit.GetInstance(seq);
+
+			checkValues(limit, currency, amount, exponent);
+		}
+
+		private void checkValues(
+			MonetaryLimit	limit,
+			string			currency,
+			int				amount,
+			int				exponent)
+		{
+			checkMandatoryField("currency", currency, limit.Currency);
+			checkMandatoryField("amount", amount, limit.Amount.IntValue);
+			checkMandatoryField("exponent", exponent, limit.Exponent.IntValue);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new MonetaryLimitUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryValueUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryValueUnitTest.cs
new file mode 100644
index 0000000..c75d745
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/MonetaryValueUnitTest.cs
@@ -0,0 +1,99 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class MonetaryValueUnitTest
+        : SimpleTest
+    {
+        private const int TestAmount = 100;
+        private const int ZeroExponent = 0;
+
+        private const string CurrencyCode = "AUD";
+
+        public override string Name
+        {
+			get { return "MonetaryValue"; }
+        }
+
+		public override void PerformTest()
+        {
+            MonetaryValue mv = new MonetaryValue(new Iso4217CurrencyCode(CurrencyCode), TestAmount, ZeroExponent);
+
+			CheckValues(mv, TestAmount, ZeroExponent);
+
+			mv = MonetaryValue.GetInstance(mv);
+
+			CheckValues(mv, TestAmount, ZeroExponent);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				mv.ToAsn1Object().GetEncoded());
+
+			mv = MonetaryValue.GetInstance(seq);
+
+			CheckValues(mv, TestAmount, ZeroExponent);
+
+			mv = MonetaryValue.GetInstance(null);
+
+			if (mv != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+			try
+            {
+                MonetaryValue.GetInstance(new object());
+
+				Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckValues(
+            MonetaryValue mv,
+            int           amount,
+            int           exponent)
+        {
+            if (mv.Amount.IntValue != amount)
+            {
+                Fail("amounts don't match.");
+            }
+
+            if (mv.Exponent.IntValue != exponent)
+            {
+                Fail("exponents don't match.");
+            }
+
+            Iso4217CurrencyCode cc = mv.Currency;
+
+            if (!cc.Alphabetic.Equals(CurrencyCode))
+            {
+                Fail("currency code wrong");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new MonetaryValueUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/NameOrPseudonymUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/NameOrPseudonymUnitTest.cs
new file mode 100644
index 0000000..45f6661
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/NameOrPseudonymUnitTest.cs
@@ -0,0 +1,114 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509.SigI;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class NameOrPseudonymUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "NameOrPseudonym"; }
+		}
+
+		public override void PerformTest()
+		{
+			string pseudonym = "pseudonym";
+			DirectoryString surname = new DirectoryString("surname");
+			Asn1Sequence givenName = new DerSequence(new DirectoryString("givenName"));
+
+			NameOrPseudonym id = new NameOrPseudonym(pseudonym);
+
+			checkConstruction(id, pseudonym, null, null);
+
+			id = new NameOrPseudonym(surname, givenName);
+
+			checkConstruction(id, null, surname, givenName);
+
+			id = NameOrPseudonym.GetInstance(null);
+
+			if (id != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				NameOrPseudonym.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			NameOrPseudonym	id,
+			string			pseudonym,
+			DirectoryString	surname,
+			Asn1Sequence	givenName)
+		{
+			checkValues(id, pseudonym, surname, givenName);
+
+			id = NameOrPseudonym.GetInstance(id);
+
+			checkValues(id, pseudonym, surname, givenName);
+
+			Asn1InputStream aIn = new Asn1InputStream(id.ToAsn1Object().GetEncoded());
+
+			if (surname != null)
+			{
+				Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+				id = NameOrPseudonym.GetInstance(seq);
+			}
+			else
+			{
+				IAsn1String s = (IAsn1String) aIn.ReadObject();
+
+				id = NameOrPseudonym.GetInstance(s);
+			}
+
+			checkValues(id, pseudonym, surname, givenName);
+		}
+
+		private void checkValues(
+			NameOrPseudonym	id,
+			string			pseudonym,
+			DirectoryString	surname,
+			Asn1Sequence	givenName)
+		{
+
+			if (surname != null)
+			{
+				checkMandatoryField("surname", surname, id.Surname);
+				checkMandatoryField("givenName", givenName, new DerSequence(id.GetGivenName()[0]));
+			}
+			else
+			{
+				checkOptionalField("pseudonym", new DirectoryString(pseudonym), id.Pseudonym);
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NameOrPseudonymUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/NamingAuthorityUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/NamingAuthorityUnitTest.cs
new file mode 100644
index 0000000..787b2c3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/NamingAuthorityUnitTest.cs
@@ -0,0 +1,106 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class NamingAuthorityUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "NamingAuthority"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerObjectIdentifier namingAuthorityID = new DerObjectIdentifier("1.2.3");
+			string namingAuthorityURL = "url";
+			DirectoryString namingAuthorityText = new DirectoryString("text");
+
+			NamingAuthority auth =  new NamingAuthority(namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+			checkConstruction(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+			auth =  new NamingAuthority(null, namingAuthorityURL, namingAuthorityText);
+
+			checkConstruction(auth, null, namingAuthorityURL, namingAuthorityText);
+
+			auth =  new NamingAuthority(namingAuthorityID, null, namingAuthorityText);
+
+			checkConstruction(auth, namingAuthorityID, null, namingAuthorityText);
+
+			auth =  new NamingAuthority(namingAuthorityID, namingAuthorityURL, null);
+
+			checkConstruction(auth, namingAuthorityID, namingAuthorityURL, null);
+
+			auth = NamingAuthority.GetInstance(null);
+
+			if (auth != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				NamingAuthority.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			NamingAuthority		auth,
+			DerObjectIdentifier	namingAuthorityID,
+			string				namingAuthorityURL,
+			DirectoryString		namingAuthorityText)
+		{
+			checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+			auth = NamingAuthority.GetInstance(auth);
+
+			checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+
+			Asn1InputStream aIn = new Asn1InputStream(auth.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			auth = NamingAuthority.GetInstance(seq);
+
+			checkValues(auth, namingAuthorityID, namingAuthorityURL, namingAuthorityText);
+		}
+
+		private void checkValues(
+			NamingAuthority		auth,
+			DerObjectIdentifier	namingAuthorityId,
+			string				namingAuthorityURL,
+			DirectoryString		namingAuthorityText)
+		{
+			checkOptionalField("namingAuthorityId", namingAuthorityId, auth.NamingAuthorityID);
+			checkOptionalField("namingAuthorityURL", namingAuthorityURL, auth.NamingAuthorityUrl);
+			checkOptionalField("namingAuthorityText", namingAuthorityText, auth.NamingAuthorityText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NamingAuthorityUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/NetscapeCertTypeTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/NetscapeCertTypeTest.cs
new file mode 100644
index 0000000..8db5d99
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/NetscapeCertTypeTest.cs
@@ -0,0 +1,45 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Misc;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class NetscapeCertTypeTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "NetscapeCertType"; }
+		}
+
+		public override void PerformTest()
+		{
+			BitStringConstantTester.testFlagValueCorrect(0, NetscapeCertType.SslClient);
+			BitStringConstantTester.testFlagValueCorrect(1, NetscapeCertType.SslServer);
+			BitStringConstantTester.testFlagValueCorrect(2, NetscapeCertType.Smime);
+			BitStringConstantTester.testFlagValueCorrect(3, NetscapeCertType.ObjectSigning);
+			BitStringConstantTester.testFlagValueCorrect(4, NetscapeCertType.Reserved);
+			BitStringConstantTester.testFlagValueCorrect(5, NetscapeCertType.SslCA);
+			BitStringConstantTester.testFlagValueCorrect(6, NetscapeCertType.SmimeCA);
+			BitStringConstantTester.testFlagValueCorrect(7, NetscapeCertType.ObjectSigningCA);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NetscapeCertTypeTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/OCSPTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/OCSPTest.cs
new file mode 100644
index 0000000..13f59d3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/OCSPTest.cs
@@ -0,0 +1,183 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class OcspTest
+		: ITest
+	{
+		private static byte[] unsignedReq = Base64.Decode(
+			"MEIwQDA+MDwwOjAJBgUrDgMCGgUABBRDb9GODnq7lRhSkEqw4XX24huERwQUkY4j"
+			+ "a6eKuDlkVP9hRgkEvIWqHPECAQE=");
+
+		private static byte[] signedReq = Base64.Decode(
+			"MIIC9jBAMD4wPDA6MAkGBSsOAwIaBQAEFENv0Y4OeruVGFKQSrDhdfbiG4RHBBTc"
+			+ "Mr1fP+mZAxbF2ZdehWxn6mtAngIBAaCCArAwggKsMA0GCSqGSIb3DQEBBQUAA4GB"
+			+ "AAzHBm4nL5AcRQB3Jkz7ScNeZF+GbRZ0p4kBDTnqi3IeESuso12yJhpqqyijdnj5"
+			+ "gd4/GsSAgdluLHyYZ6wgozV7G9MDXCnFnG4PBUW05HaVX81JYAp+amVyU0NOgNrG"
+			+ "90npVBsHb0o+UlkxNgMiEbSkp/TeGb6YURsYKhmwp7BgoIICFTCCAhEwggINMIIB"
+			+ "dqADAgECAgEBMA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0"
+			+ "bGUxCzAJBgNVBAYTAkFVMB4XDTA0MTAyNDEzNDc0M1oXDTA1MDIwMTEzNDc0M1ow"
+			+ "JTEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI"
+			+ "hvcNAQEBBQADgY0AMIGJAoGBAJBmLeIzthMHUeTkOeJ76iBxcMHY31o/i3a9VT12"
+			+ "y2FcS/ejJmeUCMTdtwl5alOwXY66vF4DyT1VU/nJG3mHpSoqq7qrMXOIFGcXg1Wf"
+			+ "oJRrQgTOLdQ6bod7i9ME/EjEJy70orh0nVS7NGcu0R5TjcbLde2J5zxjb/W9wqfy"
+			+ "RovJAgMBAAGjTTBLMB0GA1UdDgQWBBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAfBgNV"
+			+ "HSMEGDAWgBTcMr1fP+mZAxbF2ZdehWxn6mtAnjAJBgNVHRMEAjAAMA0GCSqGSIb3"
+			+ "DQEBBAUAA4GBAF/4EH1KkNrNxocJPIp7lThmG1KIVYESIadowMowrbok46ESofRF"
+			+ "OIPku07W+e1Y1Y1KXLIiPMG3IGwrBrn04iLsbbBUiN37BcC/VyT4xKJ2MYscGjKL"
+			+ "ua/9bU0lOyeTRAwqb8towWRd5lLYAI3RQ7dhStUTFp3Vqd803PJ/cpR6");
+
+		private static byte[] _response = Base64.Decode(
+			"MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx"
+			+ "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE"
+			+ "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG"
+			+ "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv"
+			+ "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ"
+			+ "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF"
+			+ "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1"
+			+ "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/"
+			+ "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt"
+			+ "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk"
+			+ "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI"
+			+ "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN"
+			+ "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww"
+			+ "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k"
+			+ "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz"
+			+ "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg"
+			+ "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK"
+			+ "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw"
+			+ "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI"
+			+ "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF"
+			+ "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH"
+			+ "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm"
+			+ "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E"
+			+ "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG"
+			+ "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E"
+			+ "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG"
+			+ "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4"
+			+ "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc"
+			+ "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V"
+			+ "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I"
+			+ "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq"
+			+ "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ");
+
+		private ITestResult unSignedRequest()
+		{
+			try
+			{
+				OcspRequest req = OcspRequest.GetInstance(
+					Asn1Object.FromByteArray(unsignedReq));
+
+				if (!Arrays.AreEqual(req.GetEncoded(), unsignedReq))
+				{
+					return new SimpleTestResult(false, Name + ": Ocsp unsigned request failed to re-encode");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed unsigned exception - " + e.ToString(), e);
+			}
+		}
+
+		private ITestResult SignedRequest()
+		{
+			try
+			{
+				OcspRequest req = OcspRequest.GetInstance(
+					Asn1Object.FromByteArray(signedReq));
+
+				if (!Arrays.AreEqual(req.GetEncoded(), signedReq))
+				{
+					return new SimpleTestResult(false, Name + ": Ocsp signed request failed to re-encode");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed signed exception - " + e.ToString(), e);
+			}
+		}
+
+		private ITestResult Response()
+		{
+			try
+			{
+				OcspResponse resp = OcspResponse.GetInstance(
+					Asn1Object.FromByteArray(_response));
+				ResponseBytes rBytes = ResponseBytes.GetInstance(resp.ResponseBytes);
+
+				BasicOcspResponse bResp = BasicOcspResponse.GetInstance(
+					Asn1Object.FromByteArray(rBytes.Response.GetOctets()));
+
+				resp = new OcspResponse(
+					resp.ResponseStatus,
+					new ResponseBytes(
+						rBytes.ResponseType,
+						new DerOctetString(bResp.GetEncoded())));
+
+				if (!Arrays.AreEqual(resp.GetEncoded(), _response))
+				{
+					return new SimpleTestResult(false, Name + ": Ocsp response failed to re-encode");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed response exception - " + e.ToString(), e);
+			}
+		}
+
+		public ITestResult Perform()
+		{
+			ITestResult res = unSignedRequest();
+
+			if (!res.IsSuccessful())
+			{
+				return res;
+			}
+
+			res = SignedRequest();
+			if (!res.IsSuccessful())
+			{
+				return res;
+			}
+
+			return Response();
+		}
+
+		public string Name
+		{
+			get { return "Ocsp"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new OcspTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/OIDTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/OIDTest.cs
new file mode 100644
index 0000000..b0782db
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/OIDTest.cs
@@ -0,0 +1,149 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/**
+	 * X.690 test example
+	 */
+	[TestFixture]
+	public class OidTest
+		: SimpleTest
+	{
+		byte[] req1 = Hex.Decode("0603813403");
+		byte[] req2 = Hex.Decode("06082A36FFFFFFDD6311");
+
+		public override string Name
+		{
+			get { return "OID"; }
+		}
+
+		private void recodeCheck(
+			string	oid,
+			byte[]	enc)
+		{
+			DerObjectIdentifier o = new DerObjectIdentifier(oid);
+			DerObjectIdentifier encO = (DerObjectIdentifier) Asn1Object.FromByteArray(enc);
+
+			if (!o.Equals(encO))
+			{
+				Fail("oid ID didn't match", o, encO);
+			}
+
+			byte[] bytes = o.GetDerEncoded();
+
+			if (!Arrays.AreEqual(bytes, enc))
+			{
+				Fail("failed comparison test", Hex.ToHexString(enc), Hex.ToHexString(bytes));
+			}
+		}
+
+		private void validOidCheck(
+			string oid)
+		{
+			DerObjectIdentifier o = new DerObjectIdentifier(oid);
+			o = (DerObjectIdentifier) Asn1Object.FromByteArray(o.GetEncoded());
+
+			if (!o.Id.Equals(oid))
+			{
+				Fail("failed oid check: " + oid);
+			}
+		}
+
+		private void invalidOidCheck(
+			string oid)
+		{
+			try
+			{
+				new DerObjectIdentifier(oid);
+				Fail("failed to catch bad oid: " + oid);
+			}
+			catch (FormatException)
+			{
+				// expected
+			}
+		}
+
+		private void branchCheck(string stem, string branch)
+		{
+			string expected = stem + "." + branch;
+			string actual = new DerObjectIdentifier(stem).Branch(branch).Id;
+
+			if (expected != actual)
+			{
+				Fail("failed 'branch' check for " + stem + "/" + branch);
+			}
+		}
+
+		private void onCheck(String stem, String test, bool expected)
+		{
+			if (expected != new DerObjectIdentifier(test).On(new DerObjectIdentifier(stem)))
+			{
+				Fail("failed 'on' check for " + stem + "/" + test);
+			}
+		}
+
+		public override void PerformTest()
+		{
+			recodeCheck("2.100.3", req1);
+			recodeCheck("1.2.54.34359733987.17", req2);
+
+			validOidCheck(PkcsObjectIdentifiers.Pkcs9AtContentType.Id);
+			validOidCheck("0.1");
+			validOidCheck("1.1.127.32512.8323072.2130706432.545460846592.139637976727552.35747322042253312.9151314442816847872");
+			validOidCheck("1.2.123.12345678901.1.1.1");
+			validOidCheck("2.25.196556539987194312349856245628873852187.1");
+
+			invalidOidCheck("0");
+			invalidOidCheck("1");
+			invalidOidCheck("2");
+			invalidOidCheck("3.1");
+			invalidOidCheck("..1");
+			invalidOidCheck("192.168.1.1");
+			invalidOidCheck(".123452");
+			invalidOidCheck("1.");
+			invalidOidCheck("1.345.23.34..234");
+			invalidOidCheck("1.345.23.34.234.");
+			invalidOidCheck(".12.345.77.234");
+			invalidOidCheck(".12.345.77.234.");
+			invalidOidCheck("1.2.3.4.A.5");
+			invalidOidCheck("1,2");
+
+			branchCheck("1.1", "2.2");
+
+			onCheck("1.1", "1.1", false);
+			onCheck("1.1", "1.2", false);
+			onCheck("1.1", "1.2.1", false);
+			onCheck("1.1", "2.1", false);
+			onCheck("1.1", "1.11", false);
+			onCheck("1.12", "1.1.2", false);
+			onCheck("1.1", "1.1.1", true);
+			onCheck("1.1", "1.1.2", true);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new OidTest();
+			ITestResult	result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/OctetStringTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/OctetStringTest.cs
new file mode 100644
index 0000000..8bae1b0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/OctetStringTest.cs
@@ -0,0 +1,186 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cms;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class OctetStringTest
+	{
+		[Test]
+		public void TestReadingWriting()
+		{
+			MemoryStream bOut = new MemoryStream();
+			BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut);
+
+			Stream outStream = octGen.GetOctetOutputStream();
+
+			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+			outStream.Write(new byte[4], 0, 4);
+
+			outStream.Close();
+
+			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+
+			BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject();
+
+			Stream inStream = s.GetOctetStream();
+			int count = 0;
+
+			while (inStream.ReadByte() >= 0)
+			{
+				count++;
+			}
+
+			Assert.AreEqual(8, count);
+		}
+
+		[Test]
+		public void TestReadingWritingZeroInLength()
+		{
+			MemoryStream bOut = new MemoryStream();
+			BerOctetStringGenerator octGen = new BerOctetStringGenerator(bOut);
+
+			Stream outStream = octGen.GetOctetOutputStream();
+
+			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+			outStream.Write(new byte[512], 0, 512);  // forces a zero to appear in length
+
+			outStream.Close();
+
+			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+
+			BerOctetStringParser s = (BerOctetStringParser)aIn.ReadObject();
+
+			Stream inStream = s.GetOctetStream();
+			int         count = 0;
+
+			while (inStream.ReadByte() >= 0)
+			{
+				count++;
+			}
+
+			Assert.AreEqual(516, count);
+		}
+
+		[Test]
+		public void TestReadingWritingNested()
+		{
+			MemoryStream bOut = new MemoryStream();
+			BerSequenceGenerator sGen = new BerSequenceGenerator(bOut);
+			BerOctetStringGenerator octGen = new BerOctetStringGenerator(sGen.GetRawOutputStream());
+
+			Stream outStream = octGen.GetOctetOutputStream();
+
+			BerSequenceGenerator inSGen = new BerSequenceGenerator(outStream);
+
+			BerOctetStringGenerator inOctGen = new BerOctetStringGenerator(inSGen.GetRawOutputStream());
+
+			Stream inOut = inOctGen.GetOctetOutputStream();
+
+			inOut.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+			inOut.Write(new byte[10], 0, 10);
+
+			inOut.Close();
+
+			inSGen.Close();
+
+			outStream.Close();
+
+			sGen.Close();
+
+			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+
+			BerSequenceParser sq = (BerSequenceParser)aIn.ReadObject();
+
+			BerOctetStringParser s = (BerOctetStringParser)sq.ReadObject();
+
+			Asn1StreamParser aIn2 = new Asn1StreamParser(s.GetOctetStream());
+
+			BerSequenceParser sq2 = (BerSequenceParser)aIn2.ReadObject();
+
+			BerOctetStringParser inS = (BerOctetStringParser)sq2.ReadObject();
+
+			Stream inStream = inS.GetOctetStream();
+			int         count = 0;
+
+			while (inStream.ReadByte() >= 0)
+			{
+				count++;
+			}
+
+			Assert.AreEqual(14, count);
+		}
+
+		[Test]
+		public void TestNestedStructure()
+		{
+			MemoryStream bOut = new MemoryStream();
+
+			BerSequenceGenerator sGen = new BerSequenceGenerator(bOut);
+
+			sGen.AddObject(new DerObjectIdentifier(CmsObjectIdentifiers.CompressedData.Id));
+
+			BerSequenceGenerator cGen = new BerSequenceGenerator(sGen.GetRawOutputStream(), 0, true);
+
+			cGen.AddObject(new DerInteger(0));
+
+			//
+			// AlgorithmIdentifier
+			//
+			DerSequenceGenerator algGen = new DerSequenceGenerator(cGen.GetRawOutputStream());
+
+			algGen.AddObject(new DerObjectIdentifier("1.2"));
+
+			algGen.Close();
+
+			//
+			// Encapsulated ContentInfo
+			//
+			BerSequenceGenerator eiGen = new BerSequenceGenerator(cGen.GetRawOutputStream());
+
+			eiGen.AddObject(new DerObjectIdentifier("1.1"));
+
+			BerOctetStringGenerator octGen = new BerOctetStringGenerator(eiGen.GetRawOutputStream(), 0, true);
+
+			//
+			// output containing zeroes
+			//
+			Stream outStream = octGen.GetOctetOutputStream();
+
+			outStream.Write(new byte[] { 1, 2, 3, 4 }, 0, 4);
+			outStream.Write(new byte[4], 0, 4);
+			outStream.Write(new byte[20], 0, 20);
+
+			outStream.Close();
+			eiGen.Close();
+			cGen.Close();
+			sGen.Close();
+
+			//
+			// reading back
+			//
+			Asn1StreamParser aIn = new Asn1StreamParser(bOut.ToArray());
+
+			ContentInfoParser cp = new ContentInfoParser((Asn1SequenceParser)aIn.ReadObject());
+
+			CompressedDataParser comData = new CompressedDataParser((Asn1SequenceParser)cp.GetContent(Asn1Tags.Sequence));
+			ContentInfoParser content = comData.GetEncapContentInfo();
+
+			Asn1OctetStringParser bytes = (Asn1OctetStringParser)content.GetContent(Asn1Tags.OctetString);
+
+			Stream inStream = bytes.GetOctetStream();
+			int count = 0;
+
+			while (inStream.ReadByte() >= 0)
+			{
+				count++;
+			}
+
+			Assert.AreEqual(28, count);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/OtherCertIDUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/OtherCertIDUnitTest.cs
new file mode 100644
index 0000000..a09c18e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/OtherCertIDUnitTest.cs
@@ -0,0 +1,100 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class OtherCertIDUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "OtherCertID"; }
+		}
+
+		public override void PerformTest()
+		{
+			AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("1.2.2.3"));
+			byte[] digest = new byte[20];
+			OtherHash otherHash = new OtherHash(new OtherHashAlgAndValue(algId, digest));
+			IssuerSerial issuerSerial = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new DerInteger(1));
+
+			OtherCertID certID = new OtherCertID(otherHash);
+
+			checkConstruction(certID, algId, digest, null);
+
+			certID = new OtherCertID(otherHash, issuerSerial);
+
+			checkConstruction(certID, algId, digest, issuerSerial);
+
+			certID = OtherCertID.GetInstance(null);
+
+			if (certID != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				OtherCertID.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			OtherCertID			certID,
+			AlgorithmIdentifier	algId,
+			byte[]				digest,
+			IssuerSerial		issuerSerial)
+		{
+			checkValues(certID, algId, digest, issuerSerial);
+
+			certID = OtherCertID.GetInstance(certID);
+
+			checkValues(certID, algId, digest, issuerSerial);
+
+			Asn1InputStream aIn = new Asn1InputStream(certID.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			certID = OtherCertID.GetInstance(seq);
+
+			checkValues(certID, algId, digest, issuerSerial);
+		}
+
+		private void checkValues(
+			OtherCertID			certID,
+			AlgorithmIdentifier	algId,
+			byte[]				digest,
+			IssuerSerial		issuerSerial)
+		{
+			checkMandatoryField("hashAlgorithm", algId, certID.OtherCertHash.HashAlgorithm);
+			checkMandatoryField("hashValue", digest, certID.OtherCertHash.GetHashValue());
+
+			checkOptionalField("issuerSerial", issuerSerial, certID.IssuerSerial);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new OtherCertIDUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/OtherSigningCertificateUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/OtherSigningCertificateUnitTest.cs
new file mode 100644
index 0000000..4410d8e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/OtherSigningCertificateUnitTest.cs
@@ -0,0 +1,94 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class OtherSigningCertificateUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "OtherSigningCertificate"; }
+		}
+
+		public override void PerformTest()
+		{
+			AlgorithmIdentifier algId = new AlgorithmIdentifier(new DerObjectIdentifier("1.2.2.3"));
+			byte[] digest = new byte[20];
+			OtherHash otherHash = new OtherHash(
+				new OtherHashAlgAndValue(algId, digest));
+			OtherCertID otherCertID = new OtherCertID(otherHash);
+
+			OtherSigningCertificate otherCert = new OtherSigningCertificate(otherCertID);
+
+			checkConstruction(otherCert, otherCertID);
+
+			otherCert = OtherSigningCertificate.GetInstance(null);
+
+			if (otherCert != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				OtherCertID.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			OtherSigningCertificate	otherCert,
+			OtherCertID				otherCertID)
+		{
+			checkValues(otherCert, otherCertID);
+
+			otherCert = OtherSigningCertificate.GetInstance(otherCert);
+
+			checkValues(otherCert, otherCertID);
+
+			Asn1InputStream aIn = new Asn1InputStream(otherCert.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			otherCert = OtherSigningCertificate.GetInstance(seq);
+
+			checkValues(otherCert, otherCertID);
+		}
+
+		private void checkValues(
+			OtherSigningCertificate	otherCert,
+			OtherCertID				otherCertID)
+		{
+			if (otherCert.GetCerts().Length != 1)
+			{
+				Fail("GetCerts() length wrong");
+			}
+			checkMandatoryField("GetCerts()[0]", otherCertID, otherCert.GetCerts()[0]);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new OtherSigningCertificateUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS10Test.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS10Test.cs
new file mode 100644
index 0000000..28736b8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS10Test.cs
@@ -0,0 +1,95 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class Pkcs10Test
+        : ITest
+    {
+        byte[]    req1 = Base64.Decode(
+                    "MIHoMIGTAgEAMC4xDjAMBgNVBAMTBVRlc3QyMQ8wDQYDVQQKEwZBbmFUb20xCzAJBgNVBAYTAlNF"
+                +   "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBALlEt31Tzt2MlcOljvacJgzQVhmlMoqAOgqJ9Pgd3Gux"
+                +   "Z7/WcIlgW4QCB7WZT21O1YoghwBhPDMcNGrHei9kHQkCAwEAAaAAMA0GCSqGSIb3DQEBBQUAA0EA"
+                +   "NDEI4ecNtJ3uHwGGlitNFq9WxcoZ0djbQJ5hABMotav6gtqlrwKXY2evaIrsNwkJtNdwwH18aQDU"
+                +   "KCjOuBL38Q==");
+
+        byte[]    req2 = Base64.Decode(
+                   "MIIB6TCCAVICAQAwgagxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRQwEgYDVQQH"
+                +  "EwtTYW50YSBDbGFyYTEMMAoGA1UEChMDQUJCMVEwTwYDVQQLHEhQAAAAAAAAAG8AAAAAAAAAdwAA"
+                +  "AAAAAABlAAAAAAAAAHIAAAAAAAAAIAAAAAAAAABUAAAAAAAAABxIAAAAAAAARAAAAAAAAAAxDTAL"
+                +  "BgNVBAMTBGJsdWUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANETRZ+6occCOrFxNhfKIp4C"
+                +  "mMkxwhBNb7TnnahpbM9O0r4hrBPcfYuL7u9YX/jN0YNUP+/CiT39HhSe/bikaBPDEyNsl988I8vX"
+                +  "piEdgxYq/+LTgGHbjRsRYCkPtmzwBbuBldNF8bV7pu0v4UScSsExmGqqDlX1TbPU8KkPU1iTAgMB"
+                +  "AAGgADANBgkqhkiG9w0BAQQFAAOBgQAFbrs9qUwh93CtETk7DeUD5HcdCnxauo1bck44snSV6MZV"
+                +  "OCIGaYu1501kmhEvAtVVRr6SEHwimfQDDIjnrWwYsEr/DT6tkTZAbfRd3qUu3iKjT0H0vlUZp0hJ"
+                +  "66mINtBM84uZFBfoXiWY8M3FuAnGmvy6ah/dYtJorTxLKiGkew==");
+
+        public string Name
+        {
+			get
+			{
+				return "Pkcs10";
+			}
+        }
+
+        public ITestResult BasicPkcs10Test(
+            string  testName,
+            byte[]  req)
+        {
+            try
+            {
+				CertificationRequest r = new CertificationRequest(
+					(Asn1Sequence)Asn1Object.FromByteArray(req));
+				byte[] bytes = r.GetDerEncoded();
+
+				if (!Arrays.AreEqual(bytes, req))
+				{
+					return new SimpleTestResult(false, Name + ": " + testName + " failed comparison test");
+				}
+			}
+            catch (Exception e)
+            {
+                return new SimpleTestResult(false, Name + ": Exception - " + testName + " " + e.ToString());
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public ITestResult Perform()
+        {
+            ITestResult res = BasicPkcs10Test("basic CR", req1);
+
+            if (!res.IsSuccessful())
+            {
+                return res;
+            }
+
+            return BasicPkcs10Test("Universal CR", req2);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new Pkcs10Test();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS12Test.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS12Test.cs
new file mode 100644
index 0000000..c20fa8c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/PKCS12Test.cs
@@ -0,0 +1,210 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class Pkcs12Test
+		: SimpleTest
+	{
+		private static byte[] pkcs12 = Base64.Decode(
+			  "MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCA+gwgDCABgkqhkiG9w0BBwGggCSA"
+			+ "BIIDRDCCA0AwggM8BgsqhkiG9w0BDAoBAqCCArEwggKtMCcGCiqGSIb3DQEM"
+			+ "AQMwGQQUFlnNVpQoEHc+J3UEGxARipkHu5kCAWQEggKAAH9tmy40lly6QDoc"
+			+ "1TfmY9y2qysD+lrgk+dnxP04RfoJfycTRDeaz2sPLImZtio9nsqCFqtzU/sl"
+			+ "eWigbH34BpKU1sC0Gq1cyik0GO65sW95S6YjKtGcGOBfQCPk1oQjfiqnfU3G"
+			+ "oeOaG3COQJukMFj8unv55u0xbX1hwO8SsZmr9RjPzLrVaeY6BP5+CCzOKBaj"
+			+ "GxneIDqnQW7/kBIVWK7M+JXGdgQyiKhD6NvXL/zD8oKEne0nIX7IokQuWEn6"
+			+ "8Sglv5OSclsSdvHTk57bCuV5lVzoIzczA4J/LZWdrtITeVefBLQSalBzpRde"
+			+ "rSTMj485z2x5ChizhjE627/KQ5vkKQkQVqXYYXVyeTvKZRpL7vz13C4DUCwN"
+			+ "im1XvNSCNebXS1yHJRtcONDhGJN3UsrVjHr+2kCfE5SCEeSU/dqgNLuLa1tk"
+			+ "5+jwZFNj/HjO88wlOwPCol1uuJjDpaEW7dxu5qsVSfZhEXWHs8rZAMttFMzi"
+			+ "yxsEkZe8kqngRbNJOY6KpppYedsMWDusUJGfIHo+8zymiw3gv/z+lmFOlDGt"
+			+ "CKMk9Es/MgfjpbfhbTVYHOBKS6Qyrz7LdTuBMI8XdsZMuN+Uf73690ggLmKW"
+			+ "IELUg8h1RX0ra2n6jOc/1rnebAifMhiMkL1ABQvqOobfOrG/9h9XcXoi64Qr"
+			+ "htc3T7yMAHafBX5KUcNkbcn6kssYhpvd8bPADoLBnbx3GxGh/uziB0zKQEI0"
+			+ "GnaY4SL7aR4C5xNNi41lYtsR6ohKyfPEGslhrhd4axx0cKxC2sHgVl0k+r8B"
+			+ "8Vu44XHbW8LqdspjOHN9qg2erES1Dvgj05SfHDup+V6a3ogJo2YKXOiu3DF4"
+			+ "MFEGCSqGSIb3DQEJFDFEHkIARABhAHYAaQBkACAARwAuACAASABvAG8AawAn"
+			+ "AHMAIABWAGUAcgBpAFMAaQBnAG4ALAAgAEkAbgBjAC4AIABJAEQwIwYJKoZI"
+			+ "hvcNAQkVMRYEFKEcMJ798oZLFkH0OnpbUBnrTLgWAAAAAAAAMIAGCSqGSIb3"
+			+ "DQEHBqCAMIACAQAwgAYJKoZIhvcNAQcBMCcGCiqGSIb3DQEMAQYwGQQUTErH"
+			+ "kWZ8nBXZYWO53FH4yqRZZsECAWSggASCDGCreuCr6/azcOv5w04bN3jkg4G2"
+			+ "dsvTPAjL8bichaEOQCykhuNPt1dv3FsjUsdFC550K0+Y48RyBIID6JTiN9Gj"
+			+ "K+a5aLPaXgTRdY74Toof1hYtZ4DIcVyq25LezVQHoe/++pAgEpWjqHTxVDIv"
+			+ "YFAgT2oDB+2vkeXM61XnNWOjwCY3pXpk/VGjyN4USkD7Q/Y6tPjQOywvQE7c"
+			+ "Ab1z62k9iMia7Yk/qmh+zJu4SSneo0/RLLdMZOlGZv89MResVG038TC8MTA9"
+			+ "Uf+wDRcS20d7XDbTaBAgju8TpFIw5/lbDi0feUVlk6L+jkT1ktaTc1Pwtxn7"
+			+ "psXMFW6HAWB4exOi09297R9BCOQX6vcetK/iA/3jIC6NuTdizYof0DWetdGy"
+			+ "haIkMiEnERYE3unJocH4fq585Rw6mE+BYssPVPkVWZZInF3l69bKduuxsQt+"
+			+ "pcApgBVsTjsU+1FOiUxuW2wWKi70RcQprPv5Ef1A5FRNxPFp+7IzLNlE4qCo"
+			+ "wvC6NTpeuRw3aGsXSfqHmSddrHugNPmghNgG5lv1Ef7A8MUuyp8fyjAgxCDk"
+			+ "4Hpb8PCHGj5t//Fr6Cd0MygJMIFQmv4kUd2LVHxQ9A9WFNCqTz/nBe+ZRLJL"
+			+ "NghTv6gGpjGJiBnXYv6Sod2fs+5J2GIvex4qbdh6gzZIU2YTAwpj6Aca3SjA"
+			+ "X8+m8AXt2SC3Z6T5+m8SxyiNp2P511paV/TZKtLWXQGKeEX1JXhQkaM6Q5W/"
+			+ "IhSgC8/gppk1gbIraBqrW8bEnGBnC03wi0OnMz3ohM4CVHyaW3dQquT2+u6F"
+			+ "8VeGXAYHU022NkrpPl/VlfNNEAyisU2+oJqpPZkqL6FsDWF3k6Fq2jXBLL+/"
+			+ "a0WA82jIpgjNeXze/cgoHtU023V9E9Qcu+5nPBYdCTR4sRxvHLANii0W8lPv"
+			+ "tvU5XO1UsEjHDfKL4E1bhGzGpb/OU5yg/98EN95r/xdFL5G+XVyHeR0UtkcB"
+			+ "IuvyBdhkwoprCjkcgLZe8FPIBNw84HRe7Ye6f2gDW/F5uej6rBehJS1VFvCh"
+			+ "DXzkajGmK40Gc2APS1/1vZqPu68polgw9dT84rem36PLEOq4KuU7n4QE0g7T"
+			+ "YR2G8+4FNgQTjjg/qw3lX+sj6yLn1lYt1dOVvkiM8i8tdZg/3pCKKAW1uV7a"
+			+ "astlBxVSkFfn1BrFTc2oFGkTrlUg90a+parOfGHTfDiaHX8ouEg63fk0+Xdi"
+			+ "FCarXsqHNPDbpmWLKw8TAmdeneGipyScntJJk4ajy+jROQBgGew3ofOmfkqm"
+			+ "oJFNwUvKOXN2ucViLZgsdK/7YgV1OR7oiTh8knQNPk3d5fRYSMFf9GJTjQRV"
+			+ "y2CLdICAVzvrUXf9k7miWYkjIp2/HGD7pOH018sX9MrpfJKqvdPFOssZiFd0"
+			+ "I2FUbgcEggPotvnT0XoabEiurTm8EPPpw66NKmK/H1kQL0hEtdIazPxfLmm/"
+			+ "ZUDokwa7d4bE3BwFh0weQfEvMzJu6Y5E7ir2MqD33XaGMOGys1nst1SPPyDB"
+			+ "WpOWD9w7Ng3yU1JVzqFWuVXaXDYbfnlG7AGevKF5PYNZj/RIQBBf5Xle9hTd"
+			+ "c9CtxPkrsJwA8DeAwKl2WIfbXGzAYLSnXoYUcoTkWn/O81BlUFgAXv80gLe8"
+			+ "NUrH7bhsnyGaPY953NyDk8IWUYrsn/sXvxTy5B0/7/WGMh3CSZrLX3p7TcFY"
+			+ "yBrL6SRas4q9rrcwuhBq0tUUbbgWi92nhZl4bOGmx7ehHnwuUId2HWXyVGoB"
+			+ "qToee/2E4PZFxSZwKCY6dahswFq5QGDrQKN2/qpOLZcJib6SvSGyEZl2pqr0"
+			+ "lqk7tVPzBkN/4uP0qrcbZCDbGW6IXwu3RGMRehqj/HEJcs92lZKfVrk/U07X"
+			+ "MBAiQHqV+kLw7kStECR/MGJG1c0xhqqBrf0W74+LpJiv/Q9iFNdWbXvE/cAk"
+			+ "G7+OTUABd2kI88uA43T0UoRuPOi5KnLuD3AG+7IuyGyP69Xncd4u0srMg2fn"
+			+ "DiLLZUy6vWmxwRFsSMCEfQNLtZaggukoPIihQvbX3mQS9izwLs6D89WtEcZ5"
+			+ "6DVbIlUqUinnNKsT8vW1DZo5FMJkUxB666YIPVmkQbbJOEUU89dZg5Gw0og6"
+			+ "rn4irEr4xHFdx+S7iqJXhzs9THg/9e4/k8KQ136z7LALOqDookcSdBzW6H8c"
+			+ "STjs4qKQyNimsLB90mEuIEApzhseAaLFl+kgORGJv/2a+uoukZchMsJ98MVo"
+			+ "sEPS1oBXJl2m9AshkWfON2GDeJatgcw6CyC1mSx++Gg602ZKUZZUaWxkz1Sw"
+			+ "zTj3nhiJe+SZsdfxhsojNq7zfxqgY/Rq7BwvphU3StjnxvkB4rTkbmbiGOBO"
+			+ "cvTFg4yOtQGRcifk2/XH/bgYiPqQrYSXpO3WRASV005RaSGufcpTtj3YlHGe"
+			+ "8FUgZfDtfiGezhNET9KO3/Q0i34bGEpoIb/9uOWH4ZHULIlfdSm1ynV50nE4"
+			+ "mJTXccrF6BE80KZI5GWGhqXdfPFaHTK1S20+XCw7bRJCGeiwVxvGfB+C0SZ4"
+			+ "ndtqx165dKG5JwFukcygiIZN6foh0/PhwzmFxmPtZuPQt9dtuIQ35Y7PSDsy"
+			+ "IH2Ot0Hh0YIN99lHJ6n9HomSjpwcgDXGssEuevbpz27u/MI/Uhq4Gfx0k5RF"
+			+ "0pcRYtk1dYSx44a+8WgqZLF8DUNtyjSE/H8P5iGa6tqOl7kNyeeEkfoTtKst"
+			+ "asGFwL4Qxxus4GC7repyVi7IJgSCA+iopiqKQJ2IqUHvoIEuD//sZooDx0Je"
+			+ "oFRO5VakkTO6WHd8JpOOEU2f6Zjg++HdIl0QK7xcUaRH075LzEfqgn1vyw6J"
+			+ "N6ex8D76sf/nAy01NvDPij48Z50XDwXu4kJGJvv0AJwId8BpjziBF0j3K/DI"
+			+ "YOOpd6nW4EvdivCgaCnxqlIU/u1OP4BwpO+AUjJh6RKlKviGihQpi103DFhR"
+			+ "yXNDhh55pqgCCCuNeEB+ovRt7UxzlGAVRSxJh1Zbjp/+iQun0E32RlSR4Diz"
+			+ "p5vDk8NBZpIiKRqI+8GWZc3G1igp7dvViTLw4OdWMKwhccV5+3Ll/W72aNVm"
+			+ "azYUoYOVn+OYS1NJkER0tjFOCozRGm5hfkxGlP+02wbH5uu/AQoJMqWIxT6l"
+			+ "46IWC24lmAnDCXuM+gWmwUvyXLwuBdejVK8iG1Lnfg1qztoLpYRbBROgRdpt"
+			+ "2cbPRm+9seqrth3eJbtmxCvuh3bZ3pR2e0/r5Tob/fDcOc5Kp+j4ndXWkwpa"
+			+ "OuH1yxam7zNJR+mcYp1Wiujia5qIeY1QCAEY5QgAWaSHtjlEprwUuootA2Xm"
+			+ "V7D8Vsr9BValhm9zMKj6IzsPmM+HZJWlhHcoucuAmPK6Lnys3Kv/mbkSgNOq"
+			+ "fJDY901veFfKeqiCbAm6hZjNWoQDNJKFhjXUALrcOv9VCFPA3bMW3Xul/sB4"
+			+ "Mq595e+x/1HkNOgZorBv97C6X7ENVDaAFcyZvrRU/ZeDnvFhisfxS4EJhzxl"
+			+ "cWWnQhzD+ur1FTTlkmUFzgoB/rW+i3XigiHOuRRnkcoMy1uV17rwH8eELHJu"
+			+ "Yni5vu2QUaD4jNEhliE2XCsn8Sm6bcXnfzBa7FXC39QvAcdJHzqcD6iIwjIz"
+			+ "hKLu+/XoWFMFFNsgV78AwzPAn6TRya8LLCYPoIZkEP4qBoeZtUZ8PIS/Y7M9"
+			+ "QStMwa/NI9SPswb3iScTGvor/obUEQS4QM6mVxFMpQWfwJfyU6jingX4EHRE"
+			+ "mqvZ3ehzU8ZLOdKzRKuk022YDT7hwEQ+VL0Fg0Ld9oexqT96nQpUTHZtDRMV"
+			+ "iTuJoUYTneDs2c9tsY4mWBqamZQSfTegj4sLMZagkuSUp/SpPM2zSGuD3nY6"
+			+ "u3553gIM9jYhvLBEXwjGudVCwMd3bqo/4EhnKb2PcwUzdaMkipQlNteHZjBT"
+			+ "1ici63xjJva+di0qTV+W9cyYyHwg1927X2qcMh06BhbHlcXQKbgmbL18KJEt"
+			+ "K+GGhGNkP7mtPyHHgBb6vref/z8p7oxT2CG+oBuN/z+xQoYfe9c4IC3e/kNN"
+			+ "DIoyYvPyEzAdfMS2aL8qDxzc5GH9UE9kcusJ/2dNEFTzBH2GK1CItL3IACv/"
+			+ "LwX1SkI0w7oIQTL127CSnuTrUUkvJ/+rOYScQTMD/ntZPdLdu2ffszg3SzhN"
+			+ "ELgojK8ss1OBlruWRHw/fP736Nx8MNsuOvXMnO8lruz+uyuEhF3BLv96oTcg"
+			+ "XVHdWhPmOoqNdBQdRgAAAAAAAAAAAAAAAAAAAAAAADA8MCEwCQYFKw4DAhoF"
+			+ "AAQUJMZn7MEKv4vW/+voCVyHBa6B0EMEFJOzH/BEjRtNNsZWlo/4L840aE5r"
+			+ "AgFkAAA=");
+
+		public override void PerformTest()
+		{
+			Asn1Sequence obj = (Asn1Sequence) Asn1Object.FromByteArray(pkcs12);
+
+			Pfx                 bag = new Pfx(obj);
+			ContentInfo         info = bag.AuthSafe;
+			MacData             mData = bag.MacData;
+			DigestInfo          dInfo = mData.Mac;
+			AlgorithmIdentifier algId = dInfo.AlgorithmID;
+			byte[]              salt = mData.GetSalt();
+			int                 itCount = mData.IterationCount.IntValue;
+
+			byte[] octets = ((Asn1OctetString) info.Content).GetOctets();
+			AuthenticatedSafe authSafe = new AuthenticatedSafe(
+				(Asn1Sequence) Asn1Object.FromByteArray(octets));
+			ContentInfo[] c = authSafe.GetContentInfo();
+
+			//
+			// private key section
+			//
+			if (!c[0].ContentType.Equals(PkcsObjectIdentifiers.Data))
+			{
+				Fail("Failed comparison data test");
+			}
+
+			octets = ((Asn1OctetString)c[0].Content).GetOctets();
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(octets);
+
+			SafeBag b = new SafeBag((Asn1Sequence)seq[0]);
+			if (!b.BagID.Equals(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag))
+			{
+				Fail("Failed comparison shroudedKeyBag test");
+			}
+
+			EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(b.BagValue);
+
+			encInfo = new EncryptedPrivateKeyInfo(encInfo.EncryptionAlgorithm, encInfo.GetEncryptedData());
+
+			b = new SafeBag(PkcsObjectIdentifiers.Pkcs8ShroudedKeyBag, encInfo.ToAsn1Object(), b.BagAttributes);
+
+			byte[] encodedBytes = new DerSequence(b).GetEncoded();
+
+			c[0] = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(encodedBytes));
+
+			//
+			// certificates
+			//
+			if (!c[1].ContentType.Equals(PkcsObjectIdentifiers.EncryptedData))
+			{
+				Fail("Failed comparison encryptedData test");
+			}
+
+			EncryptedData eData = EncryptedData.GetInstance(c[1].Content);
+
+			c[1] = new ContentInfo(PkcsObjectIdentifiers.EncryptedData, eData);
+
+			//
+			// create an octet stream to represent the BER encoding of authSafe
+			//
+			authSafe = new AuthenticatedSafe(c);
+
+			info = new ContentInfo(PkcsObjectIdentifiers.Data, new BerOctetString(authSafe.GetEncoded()));
+
+			mData = new MacData(new DigestInfo(algId, dInfo.GetDigest()), salt, itCount);
+
+			bag = new Pfx(info, mData);
+
+			//
+			// comparison test
+			//
+			if (!Arrays.AreEqual(bag.GetEncoded(), pkcs12))
+			{
+				Fail("Failed comparison test");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "Pkcs12"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Pkcs12Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/PKIFailureInfoTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/PKIFailureInfoTest.cs
new file mode 100644
index 0000000..734dbbc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/PKIFailureInfoTest.cs
@@ -0,0 +1,76 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/**
+	* PKIFailureInfoTest
+	*/
+	[TestFixture]
+	public class PkiFailureInfoTest
+		: SimpleTest
+	{
+		// A correct hex encoded BAD_DATA_FORMAT PkiFailureInfo
+		private static readonly byte[] CORRECT_FAILURE_INFO = Base64.Decode("AwIANQ==");
+
+		public override string Name
+		{
+			get { return "PkiFailureInfo"; }
+		}
+
+		private void doTestEncoding()
+		{
+			DerBitString bitString = (DerBitString) Asn1Object.FromByteArray(CORRECT_FAILURE_INFO);
+			PkiFailureInfo correct = new PkiFailureInfo(bitString);
+
+			PkiFailureInfo bug = new PkiFailureInfo(PkiFailureInfo.BadRequest | PkiFailureInfo.BadTime | PkiFailureInfo.BadDataFormat | PkiFailureInfo.IncorrectData);
+
+			if (!Arrays.AreEqual(correct.GetDerEncoded(), bug.GetDerEncoded()))
+			{
+				Fail("encoding doesn't match");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			BitStringConstantTester.testFlagValueCorrect(0, PkiFailureInfo.BadAlg);
+			BitStringConstantTester.testFlagValueCorrect(1, PkiFailureInfo.BadMessageCheck);
+			BitStringConstantTester.testFlagValueCorrect(2, PkiFailureInfo.BadRequest);
+			BitStringConstantTester.testFlagValueCorrect(3, PkiFailureInfo.BadTime);
+			BitStringConstantTester.testFlagValueCorrect(4, PkiFailureInfo.BadCertId);
+			BitStringConstantTester.testFlagValueCorrect(5, PkiFailureInfo.BadDataFormat);
+			BitStringConstantTester.testFlagValueCorrect(6, PkiFailureInfo.WrongAuthority);
+			BitStringConstantTester.testFlagValueCorrect(7, PkiFailureInfo.IncorrectData);
+			BitStringConstantTester.testFlagValueCorrect(8, PkiFailureInfo.MissingTimeStamp);
+			BitStringConstantTester.testFlagValueCorrect(9, PkiFailureInfo.BadPop);
+			BitStringConstantTester.testFlagValueCorrect(14, PkiFailureInfo.TimeNotAvailable);
+			BitStringConstantTester.testFlagValueCorrect(15, PkiFailureInfo.UnacceptedPolicy);
+			BitStringConstantTester.testFlagValueCorrect(16, PkiFailureInfo.UnacceptedExtension);
+			BitStringConstantTester.testFlagValueCorrect(17, PkiFailureInfo.AddInfoNotAvailable);
+			BitStringConstantTester.testFlagValueCorrect(25, PkiFailureInfo.SystemFailure);
+
+			doTestEncoding();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PkiFailureInfoTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ParseTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ParseTest.cs
new file mode 100644
index 0000000..c649fdb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ParseTest.cs
@@ -0,0 +1,303 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class ParseTest
+    {
+        private static readonly byte[] classCastTest = Base64.Decode(
+            "MIIXqAYJKoZIhvcNAQcDoIIXmTCCF5UCAQAxggG1MIIBsQIBADCBmDCBkDEL"
+            + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
+            + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
+            + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
+            + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGh04C2SyEnH9J2Va18w"
+            + "3vdp5L7immD5h5CDZFgdgHln5QBzT7hodXMVHmyGnycsWnAjYqpsil96H3xQ"
+            + "A6+9a7yB6TYSLTNv8zhL2qU3IrfdmUJyxxfsFJlWFO1MlRmu9xEAW5CeauXs"
+            + "RurQCT+C5tLc5uytbvw0Jqbz+Qp1+eaRbfvyhWFGkO/BYZ89hVL9Yl1sg/Ls"
+            + "mA5jwTj2AvHkAwis+F33ZhYlto2QDvbPsUa0cldnX8+1Pz4QzKMHmfUbFD2D"
+            + "ngaYN1tDlmezCsYFQmNx1th1SaQtTefvPr+qaqRsm8KEXlWbJQXmIfdyi0zY"
+            + "qiwztEtO81hXZYkKqc5fKMMwghXVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
+            + "CEq3cLLWVds9gIIVsAAik3al6Nn5pr7r0mSy9Ki3vEeCBcV9EzEG44BvNHNA"
+            + "WyEsqQsdSxuF7h1/DJAMuZFwCbGflaRGx/1L94zrmtpeuH501lzPMvvZCmpj"
+            + "KrOF8e1B4MVQ5TfQTdUVyRnbcDa6E4V1ZZIdAI7BgDeJttS4+L6btquXfxUg"
+            + "ttPYQkevF7MdShYNnfLkY4vUMDOp3+iVzrOlq0elM95dfSA7OdBavgDJbz/7"
+            + "mro3AFTytnWjGz8TUos+oUujTk9/kHOn4cEAIm0hHrNhPS5qoj3QnNduNrad"
+            + "rLpGtcYyNlHIsYCsvPMxwoHmIw+r9xQQRjjzmVYzidn+cNOt0FmLs6YE8ds4"
+            + "wvHRO9S69TgKPHRgk2bihgHqII9lF9qIzfG40YwJLHzGoEwVO1O0+wn8j2EP"
+            + "O9I/Q3vreCH+5VbpUD2NGTwsMwZ3YlUesurLwse/YICxmgdN5Ro4DeQJSa9M"
+            + "iJnRFYWRq+58cKgr+L11mNc9nApZBShlpPP7pdNqWOafStIEjo+dsY/J+iyS"
+            + "6WLlUvNt/12qF4NAgZMb3FvRQ9PrMe87lqSRnHcpLWHcFjuKbMKCBvcdWGWI"
+            + "R7JR8UNzUvoLGGAUI9Ck+yTq4QtfgtL5MLmdBGxSKzgs44Mmek+LnrFx+e9n"
+            + "pkrdDf2gM/m7E50FnLYqzUjctKYGLNYpXQorq9MJx6TB20CHXcqOOoQqesXa"
+            + "9jL9PIOtBQy1Ow5Bh4SP07nTFWFSMI/Wt4ZvNvWJj3ecA9KjMOA9EXWUDS/H"
+            + "k9iCb2EEMo7fe5mhoyxMxPO+EIa1sEC9A1+rDACKPQCHOLI0uPmsdo0AEECC"
+            + "QLgOQkcwQlkHexOyHiOOtBxehtGZ1eBQQZ+31DF+RRU6WvS6grg58eS4gGOQ"
+            + "bd7CS9yYebvAQkz61J8KprWdtZuG1gBGma12wKMuQuC6RuWlKsj+rPMvaQCt"
+            + "8mucGbkElPGZVhdyD8/BvpSCNbgRwb6iSiw4EECovu4P4GFJaMGUYEuCA711"
+            + "itEieYc1QqS6ULjb3LFL/RcwSw0fGdjnt6B2nHckC2VsYKU1NwU7j0R1Omb4"
+            + "y5AvSgpuWjTXWnHnE9Ey0B+KP5ERZA+jJGiwYz48ynYlvQFSbBm4I6nh/DuI"
+            + "dWB2dLNxWuhdfzafBGtEHhLHzjW3WQwwRZsKesgHLrrj9hBUObodl1uvqvZN"
+            + "AjMOj8DrqbGOhAClj1t4S1Zk1ZekuMjsuoxEL+/lgtbT+056ES0k3A/LnpRb"
+            + "uxA1ZBr26Im+GVFzEcsV0hB4vNujSwStTTZH5jX5rMyi085yJfnikcLYUn9N"
+            + "apl+srhpIZlDJPw7IHaw8tsqXKDxF7MozIXo8B45CKv5Am+BMrIemCMX/ehu"
+            + "PODICl98Ur8tNAn1L+m0nj7H3c8HW2vNuBLEI3SEHHgm2Ij3IY5pyyeVUaWC"
+            + "pumhy8Ru5dj3fZcfKgYuJBQxWMf+UqPsf4iUK3923pouJ1cQ8XU8gOXIRrtX"
+            + "e41d/yR+UAZXSig6SITLw+wLtvitSvtxvjcUSUOI9CYTovKyuz1PQKiaLsV5"
+            + "4CoJhMQ5uRlVFS3H829I2d2gLRpSp6pNWeIZO2NMBxPYf2qcSHyHqQjR7xP2"
+            + "ZTg7U3OO6dZHORfXxzAnW2ExavBIYQmZh1gLn5jSS4wXFPXyvnJAsF4s5wed"
+            + "YHsyAqM/ek0n2Oo/zAh7UcP2vcb9FOoeRK8qC9HjTciS6WbjskRN0ft4T69G"
+            + "+1RsH8/edBxo2LZeA48BSCXDXOlBZJBsOptzYJD8HSZONPnef0jn23lk0fkU"
+            + "C3BjJu2ubFChctRvJniTko4klpidkHwuJgrTnL4er8rG3RfiiEHn/d5era15"
+            + "E1cekdVYWqwQOObOd4v+0gZSJgI48TBc5Qdy8F6wIU38DR2pn/5uNthNDgXk"
+            + "NcV9a2gOE3DoLe8CEIPMihqYMPY8NuSp97eHB2YhKpjP7qX9TUMoOdE2Iat2"
+            + "klNxadJt6JTFeiBPL6R9RHAD5sVBrkrl0S+oYtgF92f9WHVwAXU7zP6IgM4x"
+            + "hhzeJT07yyIp44mKd//F+7ntbgQjZ/iLbHh0mtOlUmzkFsDR0UNSXEQoourZ"
+            + "EY4A62HXj0DMqEQbik6QwEF7FKuwZX2opdOyVKH9MzJxNfDLd5dc8wAc8bCX"
+            + "jcCx5/GzHx2S5DndWQEVhp2hOQYuoJS3r6QCYFaHtDPKnFHS2PBFyFWL+2UK"
+            + "c0WsvVaHYqYKnksmxse9I9oU75kx5O05DZCThPX6h8J8MHRuxU9tcuuleIUQ"
+            + "XY8On+JeEtLSUZgp+Z7ITLuagf6yuKQpaR396MlDii/449/dvBiXAXeduyO1"
+            + "QzSkQCh37fdasqGL3mP0ssMcxM/qpOwQsx3gMtwiHQRi1oQE1QHb8qZHDE4m"
+            + "I5afQJ9O/H/m/EVlGUSn2yYOsPlZrWuI3BBZKoRzRq1lZOQDtOh18BE3tWmX"
+            + "viGIAxajam0i2Ce3h2U7vNwtiePRNEgPmQ7RwTTv0U6X8qqkjeYskiF4Cv9G"
+            + "nrB0WreC19ih5psEWLIkCYKTr+OhQuRrtv7RcyUi9QSneh7BjcvRjlGB6joA"
+            + "F6J4Y6ENAA/nzOZJ699VkljTi59bbNJYlONpQhOeRTu8M/wExkIJz7yR9DTY"
+            + "bY4/JdbdHNFf5DSDmYAHaFLmdnnfuRy+tC9CGGJvlcLVv5LMFJQGt2Wi15p8"
+            + "lctx7sL6yNCi7OakWbEOCvGPOxY7ejnvOjVK/Krx1T+dAXNUqrsDZmvmakOP"
+            + "We+P4Di1GqcyLVOTP8wNCkuAUoN0JFoBHy336/Xnae91KlY4DciPMpEOIpPN"
+            + "oB+3h6CozV7IWX5Wh3rhfC25nyGJshIBUS6cMXAsswQI8rOylMlGaekNcSU4"
+            + "gNKNDZAK5jNkS0Z/ziIrElSvMNTfYbnx3gCkY0pV18uadmchXihVT11Bt77O"
+            + "8KCKHycR39WYFIRO09wvGv6P42CRBFTdQbWFtkSwRiH8l6x39Z7pIkDFxokT"
+            + "Dp6Htkj3ywfQXNbFgRXZUXqgD1gZVFDFx920hcJnuu65CKz6pEL6X0XUwNPg"
+            + "vtraA2nj4wjVB/y+Cxc+1FgzeELB4CAmWO1OfRVLjYe7WEe/X5DPT6p8HBkB"
+            + "5mWuv+iQ3e37e1Lrsjt2frRYQWoOSP5Lv7c8tZiNfuIp07IYnJKBWZLTqNf9"
+            + "60uiY93ssE0gr3mfYOj+fSbbjy6NgAenT7NRZmFCjFwAfmapIV0hJoqnquaN"
+            + "jj5KKOP72hp+Zr9l8cEcvIhG/BbkY3kYbx3JJ9lnujBVr69PphHQTdw67CNB"
+            + "mDkH7y3bvZ+YaDY0vdKOJif9YwW2qoALXKgVBu1T2BONbCTIUTOzrKhWEvW8"
+            + "D6x03JsWrMMqOKeoyomf1iMt4dIOjp7yGl/lQ3iserzzLsAzR699W2+PWrAT"
+            + "5vLgklJPX/Fb3Tojbsc074lBq669WZe3xzlj85hFcBmoLPPyBE91BLhEwlGC"
+            + "+lWmwFOENLFGZE0mGoRN+KYxwqfA2N6H8TWoz6m0oPUW4uQvy9sGtYTSyQO9"
+            + "6ZwVNT3ndlFrP5p2atdEFVc5aO5FsK8/Fenwez06B2wv9cE9QTVpFrnJkKtF"
+            + "SaPCZkignj64XN7cHbk7Ys6nC3WIrTCcj1UOyp5ihuMS9eL9vosYADsmrR6M"
+            + "uqqeqHsf2+6U1sO1JBkDYtLzoaILTJoqg9/eH7cTA0T0mEfxVos9kAzk5nVN"
+            + "nVOKFrCGVIbOStpYlWP6wyykIKVkssfO6D42D5Im0zmgUwgNEkB+Vxvs8bEs"
+            + "l1wPuB2YPRDCEvwM3A5d5vTKhPtKMECIcDxpdwkD5RmLt+iaYN6oSFzyeeU0"
+            + "YvXBQzq8gfpqJu/lP8cFsjEJ0qCKdDHVTAAeWE6s5XpIzXt5cEWa5JK7Us+I"
+            + "VbSmri4z0sVwSpuopXmhLqLlNWLGXRDyTjZSGGJbguczXCq5XJ2E3E4WGYd6"
+            + "mUWhnP5H7gfW7ILOUN8HLbwOWon8A6xZlMQssL/1PaP3nL8ukvOqzbIBCZQY"
+            + "nrIYGowGKDU83zhO6IOgO8RIVQBJsdjXbN0FyV/sFCs5Sf5WyPlXw/dUAXIA"
+            + "cQiVKM3GiVeAg/q8f5nfrr8+OD4TGMVtUVYujfJocDEtdjxBuyFz3aUaKj0F"
+            + "r9DM3ozAxgWcEvl2CUqJLPHH+AWn5kM7bDyQ2sTIUf5M6hdeick09hwrmXRF"
+            + "NdIoUpn7rZORh0h2VX3XytLj2ERmvv/jPVC97VKU916n1QeMJLprjIsp7GsH"
+            + "KieC1RCKEfg4i9uHoIyHo/VgnKrnTOGX/ksj2ArMhviUJ0yjDDx5jo/k5wLn"
+            + "Rew2+bhiQdghRSriUMkubFh7TN901yl1kF2BBP5PHbpgfTP6R7qfl8ZEwzzO"
+            + "elHe7t7SvI7ff5LkwDvUXSEIrHPGajYvBNZsgro+4Sx5rmaE0QSXACG228OQ"
+            + "Qaju8qWqA2UaPhcHSPHO/u7ad/r8kHceu0dYnSFNe1p5v9Tjux0Yn6y1c+xf"
+            + "V1cu3plCwzW3Byw14PH9ATmi8KJpZQaJOqTxn+zD9TvOa93blK/9b5KDY1QM"
+            + "1s70+VOq0lEMI6Ch3QhFbXaslpgMUJLgvEa5fz3GhmD6+BRHkqjjwlLdwmyR"
+            + "qbr4v6o+vnJKucoUmzvDT8ZH9nH2WCtiiEtQaLNU2vsJ4kZvEy0CEajOrqUF"
+            + "d8qgEAHgh9it5oiyGBB2X/52notXWOi6OMKgWlxxKHPTJDvEVcQ4zZUverII"
+            + "4vYrveRXdiDodggfrafziDrA/0eEKWpcZj7fDBYjUBazwjrsn5VIWfwP2AUE"
+            + "wNn+xR81/so8Nl7EDBeoRXttyH7stbZYdRnkPK025CQug9RLzfhEAgjdgQYw"
+            + "uG+z0IuyctJW1Q1E8YSOpWEFcOK5okQkLFUfB63sO1M2LS0dDHzmdZriCfIE"
+            + "F+9aPMzojaHg3OQmZD7MiIjioV6w43bzVmtMRG22weZIYH/Sh3lDRZn13AS9"
+            + "YV6L7hbFtKKYrie79SldtYazYT8FTSNml/+Qv2TvYTjVwYwHpm7t479u+MLh"
+            + "LxMRVsVeJeSxjgufHmiLk7yYJajNyS2j9Kx/fmXmJbWZNcerrfLP+q+b594Y"
+            + "1TGWr8E6ZTh9I1gU2JR7WYl/hB2/eT6sgSYHTPyGSxTEvEHP242lmjkiHY94"
+            + "CfiTMDu281gIsnAskl05aeCBkj2M5S0BWCxy7bpVAVFf5nhf74EFIBOtHaJl"
+            + "/8psz1kGVF3TzgYHkZXpUjVX/mJX8FG0R8HN7g/xK73HSvqeamr4qVz3Kmm/"
+            + "kMtYRbZre7E1D10qh/ksNYnOkYBcG4P2JyjZ5q+8CQNungz2/b0Glg5LztNz"
+            + "hUgG27xDOUraJXjkkZl/GOh0eTqhfLHXC/TfyoEAQOPcA59MKqvroFC5Js0Q"
+            + "sTgqm2lWzaLNz+PEXpJHuSifHFXaYIkLUJs+8X5711+0M03y8iP4jZeEOrjI"
+            + "l9t3ZYbazwsI3hBIke2hGprw4m3ZmSvQ22g+N6+hnitnDALMsZThesjb6aJd"
+            + "XOwhjLkWRD4nQN594o6ZRrfv4bFEPTp4ev8l6diouKlXSFFnVqz7AZw3Pe53"
+            + "BvIsoh66zHBpZhauPV/s/uLb5x6Z8sU2OK6AoJ7b8R9V/AT7zvonBi/XQNw3"
+            + "nwkwGnTS9Mh7PFnGHLJWTKKlYXrSpNviR1vPxqHMO6b+Lki10d/YMY0vHQrY"
+            + "P6oSVkA6RIKsepHWo11+rV838+2NRrdedCe91foUmOs+eoWQnwmTy2CTZmQ5"
+            + "b7/TTcau9ewimZAqI+MtDWcmWoZfgibZmnIITGcduNOJDRn+aLt9dz+zr1qA"
+            + "HxlLXCOyBPdtfx6eo4Jon+fVte37i3HmxHk+8ZGMMSS9hJbLQEkA59b4E+7L"
+            + "GI3JZjvEkhizB4n/aFeG7KT7K3x072DMbHLZ7VgsXQ1VDDmcZmizFwgyNqKy"
+            + "hKCKxU+I2O10IMtiZUpEzV1Pw7hD5Kv/eFCsJFPXOJ2j3KP6qPtX5IYki1qH"
+            + "Juo5C5uGKtqNc6OzkXsvNUfBz5sJkEYl0WfitSSo4ARyshFUNh2hGxNxUVKM"
+            + "2opOcuHSxBgwUSmVprym50C305zdHulBXv3mLzGjvRstE9qfkQ8qVJYLQEkL"
+            + "1Yn7E92ex71YsC8JhNNMy0/YZwMkiFrqyaFd/LrblWpBbGumhe4reCJ4K3mk"
+            + "lFGEsICcMoe+zU1+QuLlz/bQ+UtvClHUe8hTyIjfY04Fwo2vbdSc1U/SHho5"
+            + "thQy+lOZ/HijzCmfWK3aTqYMdwCUTCsoxri2N8vyD/K2kbMLQWUfUlBQfDOK"
+            + "VrksBoSfcluNVaO56uEUw3enPhhJghfNlJnpr5gUcrAMES53DfkjNr0dCsfM"
+            + "JOY2ZfQEwwYey1c4W1MNNMoegSTg4aXzjVc0xDgKa7RGbtRmVNbOxIhUNAVi"
+            + "thQV3Qujoz1ehDt2GyLpjGjHSpQo3WlIU4OUqJaQfF6EH+3khFqUmp1LT7Iq"
+            + "zH3ydYsoCDjvdXSSEY3hLcZVijUJqoaNWBLb/LF8OG5qTjsM2gLgy2vgO/lM"
+            + "NsqkHnWTtDimoaRRjZBlYLhdzf6QlfLi7RPmmRriiAOM0nXmylF5xBPHQLoz"
+            + "LO9lXYIfNbVJVqQsV43z52MvEQCqPNpGqjB+Au/PZalYHbosiVOQLgTB9hTI"
+            + "sGutSXXeLnf5rftCFvWyL3n5DgURzDFLibrbyVGGKAk166bK1RyVP9XZJonr"
+            + "hPYELk4KawCysJJSmC0E8sSsuXpfd6PPDru6nCV1EdXKR7DybS7NVHCktiPR"
+            + "4B4y8O/AgfJX8sb6LuxmjaINtUKEJ1+O88Gb69uy6b/Kpu2ri/SUBaNNw4Sn"
+            + "/tuaD+jxroL7RlZmt9ME/saNKn9OmLuggd6IUKAL4Ifsx9i7+JKcYuP8Cjdf"
+            + "Rx6U6H4qkEwwYGXnZYqF3jxplyOfqA2Vpvp4rnf8mST6dRLKk49IhKGTzwZr"
+            + "4za/RZhyl6lyoRAFDrVs1b+tj6RYZk0QnK3dLiN1MFYojLyz5Uvi5KlSyFw9"
+            + "trsvXyfyWdyRmJqo1fT7OUe0ImJW2RN3v/qs1k+EXizgb7DW4Rc2goDsCGrZ"
+            + "ZdMwuAdpRnyg9WNtmWwp4XXeb66u3hJHr4RwMd5oyKFB1GsmzZF7aOhSIb2B"
+            + "t3coNXo/Y+WpEj9fD7/snq7I1lS2+3Jrnna1048O7N4b5S4b5TtEcCBILP1C"
+            + "SRvaHyZhBtJpoH6UyimKfabXi08ksrcHmbs1+HRvn+3pl0bHcdeBIQS/wjk1"
+            + "TVEDtaP+K9zkJxaExtoa45QvqowxtcKtMftNoznF45LvwriXEDV9jCXvKMcO"
+            + "nxG5aQ//fbnn4j4q1wsKXxn61wuLUW5Nrg9fIhX7nTNAAooETO7bMUeOWjig"
+            + "2S1nscmtwaV+Sumyz/XUhvWynwE0AXveLrA8Gxfx");
+
+        private static readonly byte[] derExpTest = Base64.Decode(
+            "MIIS6AYJKoZIhvcNAQcDoIIS2TCCEtUCAQAxggG1MIIBsQIBADCBmDCBkDEL"
+            + "MAkGA1UEBhMCVVMxETAPBgNVBAgTCE1pY2hpZ2FuMQ0wCwYDVQQHEwRUcm95"
+            + "MQwwCgYDVQQKEwNFRFMxGTAXBgNVBAsTEEVMSVQgRW5naW5lZXJpbmcxJDAi"
+            + "BgkqhkiG9w0BCQEWFUVsaXQuU2VydmljZXNAZWRzLmNvbTEQMA4GA1UEAxMH"
+            + "RURTRUxJVAIDD6FBMA0GCSqGSIb3DQEBAQUABIIBAGsRYK/jP1YujirddAMl"
+            + "ATysfLCwd0eZhENohVqLiMleH25Dnwf+tBaH4a9hyW+7VrWw/LC6ILPVbKpo"
+            + "oLBAOical40cw6C3zulajc4gM3AlE2KEeAWtI+bgPMXhumqiWDb4byX/APYk"
+            + "53Gk7WXF6Xs4hj3tmrHSJxCUOsTdHKUJYvOqjwKGARPQDjP0EUbVJezeAwBA"
+            + "RMlJ/qBVLBj2UW28n5oJZm3oaSaU93Uc6GPVIk43IWrmEUcWVPiMfUtUCwcX"
+            + "tRNtHuQ9os++rmdNBiuB5p+vtUeA45KWnTUtkwJXvrzE6Sf9AUH/p8uOvvZJ"
+            + "3yt9LhPxcZukGIVvcQnBxLswghEVBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcE"
+            + "CGObmTycubs2gIIQ8AKUC8ciGPxa3sFJ1EPeX/nRwYGNAarlpVnG+07NITL2"
+            + "pUzqZSgsYh5JiKd8TptQBZNdebzNmCvjrVv5s9PaescGcypL7FNVPEubh0w/"
+            + "8h9rTACqUpF5yRgfcgpAGeK29F1hyZ1WaIH43avUCaDnrZcOKB7wc1ats1aQ"
+            + "TSDLImyFn4KjSo5k0Ec/xSoWnfg391vebp8eOsyHZhFMffFtKQMaayZNHJ7Q"
+            + "BzG3r/ysUbkgI5x+0bX0QfZjEIs7yuV5Wt8DxMTueCm3RQ+HkR4lNdTBkM4V"
+            + "qozCqC1SjcAF5YHB0WFkGouEPGgTlmyvLqR2xerEXVZn9YwSnT48kOde3oGt"
+            + "EAYyg0yHbNbL0sp6LDM7upRmrgWwxf0BR6lP4wyWdv/XSLatEB7twSNiPBJ4"
+            + "PJ+QagK08yQJ84UB7YpMTudKsaUs7zW76eA7KkW3TndfDYGdhbmZ5wxNl+5x"
+            + "yPZc/jcQHW7vplMfWglUVxnzibNW12th0QXSB57Mzk8v1Rvc/HLGvAOJZG/S"
+            + "N12FZOxbUrMIHGi3kXsmfWznVyq92X4P9tuDDD7sxkSGsyUAm/UJIZ3KsXhV"
+            + "QeaRHVTVDxtJtnbYxBupy1FDBO6AhVrp16Blvnip9cPn/aLfxDoFHzmsZmEg"
+            + "IcOFqpT1fW+KN6i/JxLD3mn3gKzzdL1/8F36A2GxhCbefQFp0MfIovlnMLFv"
+            + "mrINwMP8a9VnP8gIV5oW5CxmmMUPHuGkXrfg+69iVACaC2sTq6KGebhtg9OC"
+            + "8vZhmu7+Eescst694pYa3b8Sbr5bTFXV68mMMjuRnhvF2NZgF+O0jzU+sFps"
+            + "o7s1rUloCBk1clJUJ/r+j9vbhVahCeJQw62JAqjZu4R1JYAzON3S7jWU5zJ7"
+            + "pWYPSAQkLYUz3FmRRS2Yv65mXDNHqR9vqkHTIphwA9CLMKC2rIONxSVB57q1"
+            + "Npa/TFkVdXnw+cmYjyFWiWeDP7Mw0Kwy7tO008UrBY0rKQU466RI5ezDqYPc"
+            + "Lm73dUH2EjUYmKUi8zCtXpzgfTYVa/DmkbVUL9ThHMVRq1OpT2nctE7kpXZk"
+            + "OsZjEZHZX4MCrSOlc10ZW7MJIRreWMs70n7JX7MISU+8fK6JKOuaQNG8XcQp"
+            + "5IrCTIH8vmN2rVt4UT8zgm640FtO3jWUxScvxCtUJJ49hGCwK+HwDDpO6fLw"
+            + "LFuybey+6hnAbtaDyqgsgDh2KN8GSkQT9wixqwQPWsMQ4h0xQixf4IMdFOjP"
+            + "ciwp3ul8KAp/q70i0xldWGqcDjUasx6WHKc++rFjVJjoVvijKgEhlod5wJIw"
+            + "BqQVMKRsXle07NS1MOB+CRTVW6mwBEhDDERL+ym2GT2Q4uSDzoolmLq2y5vL"
+            + "+RfDHuh3W0UeC3Q5D2bJclgMsVjgfQUN19iD+lPFp2xvLTaNWi5fYDn4uuJL"
+            + "lgVDXIMmM8I+Z2hlTXTM1Pldz2/UFe3QXTbYnjP6kfd7Bo2Webhhgs/YmSR2"
+            + "XPuA42tWNAAjlK77lETWodxi3UC7XELjZ9xoGPRbxjOklXXvev9v5Vo+vcmN"
+            + "0KrLXhLdkyHRSm81SRsWoadCTSyT8ibv66P00GOt+OlIUOt0YKSUkULQfPvC"
+            + "EgMpeTm1/9l8n9bJ6td5fpJFDqLDm+FpJX6T2sWevV/Tyt6aoDPuET5iHBHW"
+            + "PoHxKl8YPRHBf+nRWoh45QMGQWNSrJRDlO8oYOhdznh4wxLn3DXEfDr0Z7Kd"
+            + "gEg6xr1XCobBn6Gi7wWXp5FDTaRF41t7fH8VxPwwDa8Yfu3vsgB6q426kjAj"
+            + "Q77wx1QFIg8gOYopTOgqze1i4h1U8ehP9btznDD6OR8+hPsVKoXYGp8Ukkc7"
+            + "JBA0o8l9O2DSGh0StsD94UhdYzn+ri7ozkXFy2SHFT2/saC34NHLoIF0v/aw"
+            + "L9G506Dtz6xXOACZ4brCG+NNnPLIcGblXIrYTy4+sm0KSdsl6BGzYh9uc8tu"
+            + "tfCh+iDuhT0n+nfnvdCmPwonONFb53Is1+dz5sisILfjB7OPRW4ngyfjgfHm"
+            + "oxxHDC/N01uoJIdmQRIisLi2nLhG+si8+Puz0SyPaB820VuV2mp77Y2osTAB"
+            + "0hTDv/sU0DQjqcuepYPUMvMs3SlkEmaEzNSiu7xOOBQYB8FoK4PeOXDIW6n2"
+            + "0hv6iS17hcZ+8GdhwC4x2Swkxt99ikRM0AxWrh1lCk5BagVN5xG79c/ZQ1M7"
+            + "a0k3WTzYF1Y4d6QPNOYeOBP9+G7/a2o3hGXDRRXnFpO7gQtlXy9A15RfvsWH"
+            + "O+UuFsOTtuiiZk1qRgWW5nkSCPCl2rP1Z7bwr3VD7o6VYhNCSdjuFfxwgNbW"
+            + "x8t35dBn6xLkc6QcBs2SZaRxvPTSAfjON++Ke0iK5w3mec0Br4QSNB1B0Aza"
+            + "w3t3AleqPyJC6IP1OQl5bi+PA+h3YZthwQmcwgXgW9bWxNDqUjUPZfsnNNDX"
+            + "MU9ANDLjITxvwr3F3ZSfJyeeDdbhr3EJUTtnzzWC6157EL9dt0jdPO35V0w4"
+            + "iUyZIW1FcYlCJp6t6Sy9n3TmxeLbq2xML4hncJBClaDMOp2QfabJ0XEYrD8F"
+            + "jq+aDM0NEUHng+Gt9WNqnjc8GzNlhxTNm3eQ6gyM/9Ip154GhH6c9hsmkMy5"
+            + "DlMjGFpFnsSTNFka2+DOzumWUiXLGbe4M3RePl1N4MLwXrkR2llguQynyoqF"
+            + "Ptat2Ky5yW2q9+IQHY49NJTlsCpunE5HFkAK9rY/4lM4/Q7hVunP6U4a0Kbu"
+            + "beFuOQMKQlBZvcplnYBefXD79uarY/q7ui6nFHlqND5mlXMknMrsQk3papfp"
+            + "OpMS4T07rCTLek0ODtb5KsHdIF76NZXevko4+d/xbv7HLCUYd8xuOuqf+y4I"
+            + "VJiT1FmYtZd9w+ubfHrOfHxY+SBtN6fs02WAccZqBXUYzZEijRbN2YUv1OnG"
+            + "rfYe4EcfOu/Sa+wLbB7msYpLfvUfEO3iseKf4LXZkgtF5P610PBZR8edeSgr"
+            + "YZW+J0K78PRAl5nEi1mvzBxi9DyNf6iQ9mWLyyCmr9p9HGE+aCMKVCn9jfZH"
+            + "WeBDAJNYDcUh5NEckqJtbEc2S1FJM7yZBWLQUt3NCQvj+nvQT45osZ3BJvFg"
+            + "IcGJ0CysoblVz4fCLybrYxby9HP89WMLHqdqsIeVX8IJ3x84SqLPuzrqf9FT"
+            + "ZVYLo0F2oBjAzjT7obt9+NJc/psOMCg+OGQkAfwj3VNvaqkkQsVxSiozgxrC"
+            + "7KaTXuAL6eKKspman96kz4QVk9P0usUPii+LFnW4XYc0RNfgJVO6BgJT7pLX"
+            + "NWwv/izMIMNAqSiWfzHHRVkhq4f1TMSF91auXOSICpJb3QQ4XFh52Mgl8+zs"
+            + "fobsb0geyb49WqFrZhUu+X+8LfQztppGmiUpFL+8EW0aPHbfaf4y9J1/Wthy"
+            + "c28Yqu62j/ljXq4Qa21uaEkoxzH1wPKCoKM9TXJtZJ39Yl9cf119Qy4M6QsB"
+            + "6oMXExlMjqIMCCWaLXLRiqbc2Y7rZHgEr08msibdoYHbSkEl8U+Kii2p6Vdx"
+            + "zyiEIz4CadrFbrAzxmrR/+3u8JuBdq0K3KNR0WWx73BU+G0rgBX56GnP7Ixy"
+            + "fuvkRb4YfJUF4PkDa50BGVhybPrIhoFteT6bSh6LQtBm9c4Kop8Svx3ZbqOT"
+            + "kgQDa0n+O0iR7x3fvNZ0Wz4YJrKGnVOPCqJSlSsnX6v2JScmaNdrSwkMTnUf"
+            + "F9450Hasd88+skC4jVAv3WAB03Gz1MtiGDhdUKFnHnU9HeHUnh38peCFEfnK"
+            + "WihakVQNfc72YoFVZHeJI5fJAW8P7xGTZ95ysyirtirxt2zkRVJa5p7semOw"
+            + "bL/lBC1bp4J6xHF/NHY8NQjvuhqkDyNlh3dRpIBVBu6Z04hRhLFW6IBxcCCv"
+            + "pjfoxJoox9yxKQKpr3J6MiZKBlndZRbSogO/wYwFeh7HhUzMNM1xIy3jWVVC"
+            + "CrzWp+Q1uxnL74SwrMP/EcZh+jZO4CYWk6guUMhTo1kbW03BZfyAqbPM+X+e"
+            + "ZqMZljydH8AWgl0MZd2IAfajDxI03/6XZSgzq24n+J7wKMYWS3WzB98OIwr+"
+            + "oKoQ7aKwaaT/KtR8ggUVYsCLs4ScFY24MnjUvMm+gQcVyeX74UlqR30Aipnf"
+            + "qzDRVcAUMMNcs0fuqePcrZ/yxPo+P135YClPDo9J8bwNpioUY8g+BQxjEQTj"
+            + "py3i2rAoX+Z5fcGjnZQVPMog0niIvLPRJ1Xl7yzPW0SevhlnMo6uDYDjWgQ2"
+            + "TLeTehRCiSd3z7ZunYR3kvJIw1Kzo4YjdO3l3WNf3RQvxPmJcSKzeqKVxWxU"
+            + "QBMIC/dIzmRDcY787qjAlKDZOdDp7qBKIqnfodWolxBA0KhvE61eYabZqUCT"
+            + "G2HJaQE1SvOdL9KM4ORFlxE3/dqv8ttBJ6N1qKk423CJjajZHYTwf1dCfj8T"
+            + "VAE/A3INTc6vg02tfkig+7ebmbeXJRH93KveEo2Wi1xQDsWNA+3DVzsMyTqV"
+            + "+AgfSjjwKouXAznhpgNc5QjmD2I6RyTf+hngftve18ZmVhtlW5+K6qi62M7o"
+            + "aM83KweH1QgCS12/p2tMEAfz//pPbod2NrFDxnmozhp2ZnD04wC+6HGz6bX/"
+            + "h8x2PDaXrpuqnZREFEYzUDKQqxdglXj5oE/chBR8+eBfYSS4JW3TBkW6RfwM"
+            + "KOBBOOv8pe3Sfq/bg7OLq5bn0jKwulqP50bysZJNlQUG/KqJagKRx60fnTqB"
+            + "7gZRebvtqgn3JQU3fRCm8ikmGz9XHruoPlrUQJitWIt4AWFxjyl3oj+suLJn"
+            + "7sK62KwsqAztLV7ztoC9dxldJF34ykok1XQ2cMT+uSrD6ghYZrmrG5QDkiKW"
+            + "tOQCUvVh/CorZNlON2rt67UvueMoW+ua25K4pLKDW316c2hGZRf/jmCpRSdb"
+            + "Xr3RDaRFIK6JpmEiFMMOEnk9yf4rChnS6MHrun7vPkf82w6Q0VxoR8NRdFyW"
+            + "3mETtm2mmG5zPFMMD8uM0BYJ/mlJ2zUcD4P3hWZ8NRiU5y1kazvrC6v7NijV"
+            + "o459AKOasZUj1rDMlXDLPloTHT2ViURHh/8GKqFHi2PDhIjPYUlLR5IrPRAl"
+            + "3m6DLZ7/tvZ1hHEu9lUMMcjrt7EJ3ujS/RRkuxhrM9BFlwzpa2VK8eckuCHm"
+            + "j89UH5Nn7TvH964K67hp3TeV5DKV6WTJmtIoZKCxSi6FFzMlky73gHZM4Vur"
+            + "eccwycFHu+8o+tQqbIAVXaJvdDstHpluUCMtb2SzVmI0bxABXp5XrkOOCg8g"
+            + "EDZz1I7rKLFcyERSifhsnXaC5E99BY0DJ/7v668ZR3bE5cU7Pmo/YmJctK3n"
+            + "m8cThrYDXJNbUi0c5vrAs36ZQECn7BY/bdDDk2NPgi36UfePI8XsbezcyrUR"
+            + "ZZwT+uQ5LOB931NjD5GOMEb96cjmECONcRjB0uD7DoTiVeS3QoWmf7Yz4g0p"
+            + "v9894YWQgOl+CvmTERO4dxd7X5wJsM3Y0acGPwneDF+HtQrIpJlslm2DivEv"
+            + "sikc6DtAQrnVRSNDr67HPPeIpgzThbxH3bm5UjvnP/zcGV1W8Nzk/OBQWi0l"
+            + "fQM9DccS6P/DW3XPSD1+fDtUK5dfH8DFf8wwgnxeVwi/1hCBq9+33XPwiVpz"
+            + "489DnjGhHqq7BdHjTIqAZvNm8UPQfXRpeexbkFZx1mJvS7so54Cs58/hHgQN"
+            + "GHJh4AUCLEt0v7Hc3CMy38ovLr3Q8eZsyNGKO5GvGNa7EffGjzOKxgqtMwT2"
+            + "yv8TOTFCWnZEUTtVA9+2CpwfmuEjD2UQ4vxoM+o=");
+
+		private static readonly byte[] longTagged = Hex.Decode("9f1f023330");
+
+		[Test]
+		public void TestClassCast()
+        {
+            ParseEnveloped(classCastTest);
+        }
+
+		[Test]
+		public void TestDerExp()
+        {
+            ParseEnveloped(derExpTest);
+        }
+
+        [Test]
+		public void TestLongTag()
+		{
+			Asn1StreamParser aIn = new Asn1StreamParser(longTagged);
+			Asn1TaggedObjectParser tagged = (Asn1TaggedObjectParser)aIn.ReadObject();
+
+			Assert.AreEqual(31, tagged.TagNo);
+		}
+
+		private void ParseEnveloped(
+			byte[] data)
+        {
+            Asn1StreamParser aIn = new Asn1StreamParser(data);
+
+			ContentInfoParser cP = new ContentInfoParser((Asn1SequenceParser)aIn.ReadObject());
+
+			EnvelopedDataParser eP = new EnvelopedDataParser((Asn1SequenceParser)cP.GetContent(Asn1Tags.Sequence));
+
+			eP.GetRecipientInfos().ToAsn1Object(); // Must drain the parser!
+
+			EncryptedContentInfoParser ecP = eP.GetEncryptedContentInfo();
+
+			Asn1OctetStringParser content = (Asn1OctetStringParser)ecP.GetEncryptedContent(Asn1Tags.OctetString);
+
+			Streams.Drain(content.GetOctetStream());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ParsingTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ParsingTest.cs
new file mode 100644
index 0000000..bb219e2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ParsingTest.cs
@@ -0,0 +1,104 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	public class ParsingTest
+		: SimpleTest
+	{
+		private static readonly string[] streams = {
+			"oRNphCO0F+jcMQKC1uMO8qFBPikDDYmtfVGeB45xvbfj1qu696YGjdW2igRnePYM/KkQtADG7gMHIhqBRcl7dBtkejNeolOklPNA3NgsACTiVN9JFUsYq0a5842+TU+U2/6Kt/D0kvz0WmwWFRPHWEWVM9PYOWabGsh28Iucc6s7eEqmr8NEzWUx/jM3dmjpFYVpSpxt2KbbT+yUO0EqFQyy8hQ7JvKRgv1AoWQfPjMsfjkKgxnA8DjenmwXaZnDaKEvQIKQl46L1Yyu3boN082SQliSJMJVgNuNNLFIt5QSUdG1ant5O6f9Yr0niAkAoqGzmqz+LZE1S7RrGHWiQ3DowE9NzviBuaAoI4WdCn1ClMwb9fdEmBMU4C7DJSgs3qaJzPUuaAT9vU3GhZqZ0wcTV5DHxSRzGLqg9JEJRi4qyeuG3Qkg3YBtathl+FiLJ7mVoO3dFIccRuuqp2MpMhfuP1DxHLNLNiUZEhLM [...]
+			"KEKVhHxtyUR9D3v5K4IJbVQLAMiVKoK9z7wFWUjzvLFNLg9C/r8zKfBa3YgZrt0Nq64+MxBePMbiNLCnfditc2qUcQZUHnvNnhwT6uGK37JmXg7MvQiKwvi31EIYt6ghqBZVs1iaqc0ep7wuQ16uwSQMlaDdXc9Qf1L0dGO/6eLyREz+p4UR4NOXK+GooQLfMxYL40zJlYcwNyR0rigvIr84WP2IMS2hZjqXtyS6HMM4yUv70hkIorjr7+JC4GtU1MyWuPuNSAGen0AZTaEEXd5sMbqXMqWg3jeM4mzRH1Kb3WdAChO5vMJZPBj9jZZKgXzmxkUh5GlIhUdYgztoNceBzQ3PIc7slCDUw9I2PjB87xsfy7jA5tFtFADs2EUyxUTMCuhilP664jSHgwbrr80k9Xc4sU+MCwCq2nQmcZYcPgKb4M31VJMlKwnZF3JUU2Jtqgg4gbErw58YoBwSkEcMJ2Juhiyx9U36MzxH [...]
+			"Ol9I/rXMwbLpxTY97v70B+HCl2+cojz2574x/cC56A7KGVF13La8RdzOOvSkl338ct9T/blEFa6QwNz3GmF+MoPdH9lncwz+tqixIqGU02Bp5swH0qjbp/Yjaeq91eR6B+9fl+KKrpglBr8S1BrI4Ey5v3AxxJdCWP8Gd+6Sp15/HMYanwlHBpCsW4+Kq8sGJoJXUXpQ/GBUJKs+WjX1zE6PsvF7/B8cByuqE3NJt7x4Oa+qZtF8qNc0CFDNj31Yhdt7JkAoD30IAd+ue9OhImQMCWwFwySRIRJXU3865K2dBR+VhLuI2aKzLh7MlgVKJk6b2P/ZIkc86ksR1sOUiHrs9EdoYuIssAgMc8QGzn4VN8lxopdzQYVG6pbXGS/VQlHkGdyLd+OHt4srz/NTUWiOquVTRxa6GgtlBFfIXikPTb+iT2pZKyKUlBvpgo0BY9vVUadsteHAI5qrFZBrL5ecK/Qtl9hf/M8qEjyj [...]
+			"o3eXWpwAGmUkxHEKm/pGkDb1ZQQctCQ06lltZjeMXDp9AkowmA0KXjPQCQwyWE/nqEvk2g/58AxNU0TWSujo5uU0h4/hdMZ7Mrj33NSskWvDpKe7lE5tUjPi74Rmc5RRS+1T/EQobpNxoic3+tTO7NBbZfJtcUYeZ3jqxL+3YQL3PrGe/Zpno9TnQW8mWbbhKhDRtKY4p3Pgk9hPSpJCM9xYo3EMAOAIiH2P6RKH6uX/gSaUY2b6DE/TT0V6v/jdSmYM4+cnYiTyJCi5txI35jfCqIlVCXJd7klirvUMg9SXBhGR25AgQ5Z8yjd7lbB8FvD8JQAXZrp6xiHxbLIW7G11fWEo7RGLFtALI6H38Ud0vKjsEN7N5AibJcxS2A/CWk9R00sTHRBHFUP8o5mz8nE7FeCiwJPs/+tCt04nGb9wxBFMsmWcPEDfIzphCaO6U/D/tQHlA846gbKoikv/6LI0ussSR/i85XBclNcv [...]
+			"PwRUnW4yU8PI7ggbI1BIO9fcTup8optkqCirodyHCiqsPOMZ4g28bJ2+kpfQRujWGlKFYQzA1ZT32s9hdci+fvXPX0KAjcUgcxsGzMABFbEm04BwDF2WLgg9s4/x71r5JrgME1S08I3mCo4N0eFHWDeLJL1b5YNNo6tfO5V2WpIE867N9zdAgvp1gijVjUNWqEB3A/NLb3reLMu2hYgqRFTCVBfcFclD46k0XEfUJqwWdQhOz92WNl/3g53bjKX1hDZgjLIzK6m+SU6+J/h4NidrS7E0gOBevZW8gRYdKMVqNWxzUfxv6kgG+kIeF9JqMcO6jdh/Zu/0tpZoHFeCweZ1jT1eEtltFu1FcTTPc1UT0pT+ZNVgefrBONoGnvn8+dBjPese6F2TmRCExJq9taKlIh/kHdkbpaa7vwrBpYRgVGfARPyM9SSCaE7pVBDuwkFeYiGU4tamm5Gq10ojRQgetJ3UOg/PGTJcxo97 [...]
+			"ZIAKizvGzbvqvqOlxOeVgHGHV9TfKNjjqyzbCj8tggv2yp7kkq1D3yRlC349tuul3zN9g4u83Ctio9Gg3HiLzMULxoOImF/hKRDhJpPLbLm0jSq1fyF+N7/YvyLeFhGoPhYEBUihDcxo1NIcWy66aBt3EuOlTyDQWrDe0Za3mrTrrl10uLHVKcQMgeD+UMgjQqmHzQJR8wdNjHPKHWVvZEdiwI031nV2giHJHXv08Jvf4vmw4dAlH2drCl6cBgg33jy7ohK8IiXz6eCw6iY9Ri8YaMzxOhgE2BOHzEz5ZC2hilL4xO/ambTER4bhb4+9VTUIehHP18FcXm8TKPQRMqyKP2fMlzWW3/uelYfPP5SHlyLAULa1KjDCkLIDunEKZDpv2ljGB6JPrTlNwFsvlZcihfOAwjbr2jW3MwP704OA8xzd/dynBU47unIZEu0LAvQ3TUz3PLga0GGO1LZGtg0Foo9zFG2wuVCdgYHm [...]
+			"uG0wQ55kMlfZtJFAqTl0bnYW/oy9NFOi0e4FqAYwsvMxGO4JtGzXgkVwEUAC0AUDItRUjxBl+TkoPTYaprgn0M/NQvKPpXJ+yzI7Ssi+F2alLR0T6eF/4rQ32AVjnANJaghXZm0ZKduckbhSxk5lilJVJRuzXKchZRtlPluvlj448bq+iThktsEQoNP8NMpi7n/EVxovp+dow4Q6t7msSRP4cGXtyYoWKbf/7e5XzBKOZZ1/f3s86uJke4dcKIaljpJfBrtuFxZC6NYXzX6PkoDoBgqQ8RBrxsX54S9cBDAPxxmkq8zviAOW3oqPMULGGmQzHBiRwE8oeDFoMnzF5aR/lkbNuTLOxhbIkosgLWlDNVEFYx9bVhdLzO7VwaAK829dimlPOo5loKB7Pd2G7ekRKXwu7wNvJBq8KRkhtLKbKoS8D6TaRWUMb9VBJ1CMy4mrw+YwTmAKURQ6Dko9J/RgzRg5Y/sUlwdMYS9H [...]
+			"sH0kIwIq1THAfTLfqUKJfG1YauCQKPc9/mk3l39yK6zgxSpCH2IjZIwhhJtGm3F+8PTneT725OuyR617nxqrgqMGkkZkyY4DA5CjsikpBo5mo8TspX1g+vtXXtxymJMTMo8JwX3nSH4gSb3vPia+gwOW2TcJmxVdp3ITPA4gJpMfqoMBqRM+eDWO6QXW5ijVL4+wnp40u5bU4fQLVzpg25+QGLqBHD6PZTQaN6F9Vy5XpsAGDlncCklVuX3Lkp3Xb9cTiNa/4ii04uwZqx0juszjwFAMPPb6u56crvN1x4FXfXzabWECHbdQLlKazowvU9bEnqG2i4H44Ae+v8Iw8HK5mbZ6ercLTD9oPgs7Ogal037l2WwLApUz/fmD5fV8SxHh+vKDpfOzv6xcQxynS82jAJw9AdUwE/4ndGzzHPIu2M81gbAgZQ02EurMMU62hYgiXeridrtyh+H5R+CiwQdEyX7/op6WVihsYj2O [...]
+			"tycxf1mOz1yLE6cT/ZlCxMeTxlEEHFeIdw0+nF/40Tsw4vLco+4kR2A6cVml611CSpN6l/RMKk2LnAkprrbJ/Uam902WBnQ+I6Vsl6GkFFq7362bdixojqMFVKYytXLCT8I78f6s8M6a3jSALQloD6Ftvn+cc+cctO3weaaaPgAlrz+f2MFs8bqpnLQYbbY/JS9IAYJFH+yVtLz7eKcedEp9JMlJ3/43szU2fDN9ZMxBoQnxEmF3WZv6GF0WRc8VhTblXRgk4mlz6Fu3IXvwW/rbn+VCYYIk/XaVLrxFAnnw6mBozAF7vmV0OrIYBlSDU8rMb+F7AvE7pwErO9TJtCE8IUvQf8TsJYRoYv21/X57pzcBedtqVeU3DnTlmESHxG6H1uJbadSFLWSxKS4svfp8T9FWqX5815yD/UplAKEIeorLTAlPIC2ASKDU6SQW260biNAfY8FYQCWa8btaTwFuY8NMwSHzyqgU0aoP [...]
+			"oDsoFvUA+sGOoMyZY6w1UhY3NBkeoozzjEkDSRN1golyXJ1dC5CtYNEjvAJYKj+sqNwg9mBlYyybYpnI3GSP125zMeBHPCoy5CoNOkJW4OH/oLyjVeQbFNic/b2Jcz6lTguYhep8hq9EM2XuFV8T1rm5+4ucI7fH1UiOqRZyuHBAJ0Cna5kv6D3efsa9rd+swybiMIUjmPWpyxzNOOihCYuf4JqRh/D5eZKm6x0Zj2uRhTAYYxI7Q3czd0R9490ufG8VbF8ASBMireMONNNAA/OZCpxJh6xnIANBqV6YDeysws3NBWY2QuNumvg5Kr3/g+VMzJHi4wGuJjraKWi9+ylMfelHF5h/h+pAQVxCotq8JU3OTnMUW4rQp2a8BR5S+mZqPSPlb87tDG9r0+yqb1uO4UIo71C7Xxwoq4M0tXjk6mSmtP/sm+Lh14qfUzKRhTHVdz91TK104mbTJNXbK+jGPD/2BJO9fiaXY8IY [...]
+			"MIDLuZTrtZnEBOB6l14iSEyokAg5Wf5JviumhfPeL7WSFTHfOodU2hrvhyvM6oAlRHY1blTj7mw+Tcf9Tmc+/FHT6PGu0NT5UAqaqChX0gS9jizgAE2Yfhd4X/DoeQySMAixKuhu8TbvDxb54jeW9+7LVkmlntJ/0SkMgsT+WQ31OfpwDmEGDczYc+Ol14aJS+EW+rnGv9d38bo/cy+EnpNh8iV2rGGoC8fDzFHKU4gqGFSZF/tnD2OfCne0Vjr/GD6kyp2MVcHig19DBg2toGRkHnuY5kLkwOanztXA80IaAmv8e6s62U8CE8ozUZeDBcvBigEkSGx79Vsyiks8+9Kq9xLHLeS5kRT6zSl8whe8U1fIfrgic34KPlozcQVahwCru1XWyQ+9uevih8x4zMftkJ3JBZhPrnlgtx9McntH/Ss9fdUEkNwWpDnq8Xby8/5gMMMwQ13XDB73vqqteDiltMq8i7LRez4iIHfS [...]
+			"MG4QbKLbQR3enPn6Z/kEUtHrzWBIqYKR7Gvs5QHLPF6417p1O58suZq38Bb8dO5udtgOqNEVAPGmOuidYygWWfWOP5ReggTUk5XlrkvRxCU0MHWbkSKkJ+T4nLjozreqTJ0io41sFVrpxuOugAvXJ6QtMmixSABUaNgU9SkkWf9pOEiJI8dfND51HxJCbXHwsMCMBp5FbaMZmlWPwirRdAox4wbLk9ZLmoWUcorUjdaWhKvT/LnjMgPmwnwwKpN/4MOnRDdAPdzXX3aWHdkzpfsQnqt3UJsTsSaJlzeUja5C5L4CXGyt99qmfcwB8OB9TL4EYTIl3maD/gUWBfckOsji8x2E2c2iuKKrcmMmcChYr4wCjtTjEeVKOAZ2m9mU2MKc2z2hDw3AuZxsY6aOtdAjnrwl5QXGRg9I5LVl5SI5RwnLwk90pJzDGuSSCtSmzh9DUZ4WpfN+1393aTGRqCMOsB4KxbXjspUbVMFJ [...]
+			"MR0BACgWKis9/AKwG9/ARgGWJn1aM3nU8YXzWG+b7aeRUkVCjl4WxeL38E3FAMLW4UcyLzxeb+CskOqhPPTglmxhK7jQcrNILsWcZvdZfApYIvk5uKqA5FKuUuL48uvD0aKGRENe/VEUFlkQru5YX4Xnp+ZThrJJlgn7ANat/qAdP6ULEcLaOQlLYcGRh5ttsJTRT4+cZQggTJjWt+9idUQ66HfC6zQ1qHcMuochy7GHiUmNXAs0AgwOF9Jwet/Qh74KGMtmppJ9gkEqiYECFQA2gVgKc1AufHJS6S6Re72FfH/UkL41L2hvlwktkD5/hZrUZ1R+RG12Eip2zKgus4g/aGl0V8B/JvkcnFUsZJ6uxs24arOBDJOuzzxky5F5B/hwVGPEdcfHunqndUcx26/KCK72hOljlqTXl8yEbXlcMqVFNByZLr7TnGzGGUlO7kuHPW/ItZUJvrHokpsLLrb3ZhEZ8pTQd75gFcf0 [...]
+			"DH2WX6XoIseX6lHIey3seUr3DAz82fyk0jL7xc5IDTrDfqS64QBhHDpqHETF/81MrPXsM3IANBfjDOl9g/gua8wWPpPNxuWZMNh0GLcAr6PJ939TCbjE3soZHF2wiA82nZEO8jIZosDVRWFUfJS6Y3nrJz63SExqB6OUdBfvSfz1Y1M/90ofBxkfeuS85deMdn+1rZdsnZJYwz2Z6lCDvYjUTfrSwfVFJBP8Y2BXr8WClUYkfGG4eNG7IPNBRuMmhrhHj5y9z+5Jor+EbbTi5F5Jvdu2/bDM7s32XsaMNLYuVtNYONrbQ+3QZ746/yKZM4hDREvxyGLgDx3Apz7pyvwKm0//iTCY3yJLxZifGLh2uc28cFBln7IH1x8oui4Xq9vF+Z2EH4Ow48Ln5pzggBKMGy4dsfW6266TNYd/Z3SZUi28sxondqhGCSGUo7ZVPAOoYDcYKvjdI/cJ688PHliyZSYBYVmR5HBxZ57s [...]
+			"AwClK6Tq9R2DYGf8RAHu9dEttLeOfUVmS4WPwX0NehsnyM7y7n2sgGnXsiva3yFqK1hKZICkVukvHF7/bpgEEm/jRwcAhQUoG+c1qVde38eHJXj58YOBGTveruc+021or9/tHBtenmYPO6+arLQtONi43NKm7+I6ugkgQlp6iBr4haa0XMDTzMX9c8Qm/O+MrVo3qESYKkVtoSSK7SGZTBaRWNF/dOM0NQxeMP+XTVOuroqE23ZNsubBTEZnd4vUilFb/iKnhyT9XnIo7gM/Yz7HLVU5yc3yIj2sFUE+DcwpvcNO5EnPhj3bHsJvf3N4r72+5my2KjoR3KAJE1Imabd54o4xZ/9UaR93qLkVuXMkLRCCU/zlZDtfbJDsRR0C5rSYd2k6IPlNcl7PgmUpsNPUyoDYqvhuRUZxgoUAfKbogzJX8FU/QpllsKVtt68ucBi0bqC5pVKu23j79nDvYQsSlYY3JwJQaM5M558J [...]
+			"KACwq8rZuOLHuNnZJA07WzI7kppCwptbcYU2B7t86QcZrnadCtxoM5QNcl9rsbMA26iWCPV3VlDAmLSWcxtMoSKWuo4edJpk8K915xkFU5U6I/901vx5hqAECQDy/Q+QDWmWTXDoVHqFV9wvIj3wCJPpJL/Ewpl0NZd+68jjOjUhjIdNebLrWNK2nhTPiIjFjkcVqEgashpOmnbHT+2MV/CHoixmUEiuRI1B0dvSf7FHGRgbXGBubisuu60g8XTens5zyRo4Qn/LTxIu2aj4LTtyLonV3sXr+y35A1zq5mCrE1f1nOINVzwYYY76iJGIaBkZuMU3366FPIbYkmXwla6RQU1FA0Y7n05qczw7Ie5TveRTByKFtUqW8OAb9vH+H2ezJ4CXE3AGbu/nTj64KClO/zL499GA+97g+X6tTN6xOJdNknlqw6ZnFNtCL8+A3hL4OyOgWD0IGC+xFvcKjDUaaJenCtQvprCJaFrv [...]
+			"rUABPQ3SEWE5rY16pM+o+7EObLNM1jEa5YCMQM/aen0PWajWNax3Pyo6TZL8aGDXZF0yWqDM3b2m6UHOr6yqsUSrD+0jXPT48QN1VdBmh+AFRK+UcaYO383a0nvtv0c9uHt4yfceXLPGWrNjW+uTnS/lKpCdpE4GfLF1SFHIUcMxT+3At7hwDHNkLXllEXqbgDP8LyQSlYwT5jQUDCOzwc8CSxAryUOj6fN+iLKAiw4haPV/WZDG+JOmDMG2azo8SoBMi3y6Z2Le2fz2dMuvn5DUvCUvazrUmWYx4NEdSzc9GfBc6cXkduMqCs+lT2Ik2GHO0WjhrEB6j5NULOaCtbrislM85P6QutN4Pj9l18pcD6vZCcDTOwMj/BznclH342jeMn7rBgpW1YSzbNGP6KC4NeNW1H2xqNtuyhcJvasx4dwhzO18A36H6HtkiQyJNnfnVHh1oviO6mi3atmnh9B/55ugXM1Wf/6Kv8kJ [...]
+			"poA1hF4zRh7HF0xVglYoLFqkUR7Pru/qYFnfMKBPuEOOGdgO3MMcAvIZ+w+Ug4THr/6+Vux0TN3wdOB+beObOboLgNE2zaD65lyMFbaulzrEnWjUgIg63CdpQJ2ESaimHGg/GmsipUCndRJ37TbUtn8W112SehsAgrsjiBcuJhw61i4bVfAZEcycq4Y/FlEDxtzoH8WzDoESNbl+r5agLcHGr37BFi81IXS8TLihC1T8b7d6tLb6lpXT+9IR4xAyZTw1IFMDZZEzVmHgYE/Et20/WhkX/oGghkWSpCxR0kynDplk+BEK2oyGKnl+rf4vymhsse2iQ/C99PhaodZjDfuGVSwPLoU0AYyAKaEwmgHPOFbDlrAmNk4iBp+IZYm9guZM2hcQ4GeA5WQyZzw4C1yMywWbdjtL9ZhpClmmPZ28nmwNORAat7tXPJoBBdXFB0gNT/wU7UYIKU5GnAiDIFJ0o8ijnuAMat3AsBki [...]
+		};
+
+		public override string Name
+		{
+			get { return "ParsingTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			inputStreamTest();
+			parserTest();
+		}
+
+		private void parserTest()
+		{
+			foreach (string stream in streams)
+			{
+				Asn1StreamParser aIn = new Asn1StreamParser(Base64.Decode(stream));
+
+				try
+				{
+					Object obj;
+					while ((obj = aIn.ReadObject()) != null)
+					{
+					}
+
+					Fail("bad stream parsed successfully!");
+				}
+				catch (IOException)
+				{
+					// ignore
+				}
+				// Note: C# may throw these instead, since no InMemoryRepresentable support
+				catch (Asn1ParsingException)
+				{
+					// ignore
+				}
+			}
+		}
+
+		private void inputStreamTest()
+		{
+			foreach (string stream in streams)
+			{
+				Asn1InputStream aIn = new Asn1InputStream(Base64.Decode(stream));
+
+				try
+				{
+					Object obj;
+					while ((obj = aIn.ReadObject()) != null)
+					{
+					}
+
+					Fail("bad stream parsed successfully!");
+				}
+				catch (IOException)
+				{
+					// ignore
+				}
+				// Note: C# may throw these instead, since no InMemoryRepresentable support
+				catch (Asn1ParsingException)
+				{
+					// ignore
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ParsingTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/PersonalDataUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/PersonalDataUnitTest.cs
new file mode 100644
index 0000000..f92e619
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/PersonalDataUnitTest.cs
@@ -0,0 +1,127 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509.SigI;
+using Org.BouncyCastle.Math;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class PersonalDataUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "PersonalData"; }
+		}
+
+		public override void PerformTest()
+		{
+			NameOrPseudonym nameOrPseudonym = new NameOrPseudonym("pseudonym");
+			BigInteger nameDistinguisher = BigInteger.ValueOf(10);
+			DerGeneralizedTime dateOfBirth= new DerGeneralizedTime("20070315173729Z");
+			DirectoryString placeOfBirth = new DirectoryString("placeOfBirth");
+			string gender = "M";
+			DirectoryString postalAddress = new DirectoryString("address");
+
+			PersonalData data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			data = new PersonalData(nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			checkConstruction(data, nameOrPseudonym, null, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			data = new PersonalData(nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
+
+			checkConstruction(data, nameOrPseudonym, nameDistinguisher, null, placeOfBirth, gender, postalAddress);
+
+			data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
+
+			checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, null, gender, postalAddress);
+
+			data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
+
+			checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, null, postalAddress);
+
+			data = new PersonalData(nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
+
+			checkConstruction(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, null);
+
+			data = PersonalData.GetInstance(null);
+
+			if (data != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				PersonalData.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			PersonalData		data,
+			NameOrPseudonym		nameOrPseudonym,
+			BigInteger			nameDistinguisher,
+			DerGeneralizedTime	dateOfBirth,
+			DirectoryString		placeOfBirth,
+			string				gender,
+			DirectoryString		postalAddress)
+		{
+			checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			data = PersonalData.GetInstance(data);
+
+			checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+
+			Asn1InputStream aIn = new Asn1InputStream(data.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			data = PersonalData.GetInstance(seq);
+
+			checkValues(data, nameOrPseudonym, nameDistinguisher, dateOfBirth, placeOfBirth, gender, postalAddress);
+		}
+
+		private void checkValues(
+			PersonalData		data,
+			NameOrPseudonym		nameOrPseudonym,
+			BigInteger			nameDistinguisher,
+			DerGeneralizedTime	dateOfBirth,
+			DirectoryString		placeOfBirth,
+			string				gender,
+			DirectoryString		postalAddress)
+		{
+			checkMandatoryField("nameOrPseudonym", nameOrPseudonym, data.NameOrPseudonym);
+			checkOptionalField("nameDistinguisher", nameDistinguisher, data.NameDistinguisher);
+			checkOptionalField("dateOfBirth", dateOfBirth, data.DateOfBirth);
+			checkOptionalField("placeOfBirth", placeOfBirth, data.PlaceOfBirth);
+			checkOptionalField("gender", gender, data.Gender);
+			checkOptionalField("postalAddress", postalAddress, data.PostalAddress);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PersonalDataUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ProcurationSyntaxUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ProcurationSyntaxUnitTest.cs
new file mode 100644
index 0000000..97d0e3e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ProcurationSyntaxUnitTest.cs
@@ -0,0 +1,111 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class ProcurationSyntaxUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "ProcurationSyntax"; }
+		}
+
+		public override void PerformTest()
+		{
+			string country = "AU";
+			DirectoryString typeOfSubstitution = new DirectoryString("substitution");
+			GeneralName thirdPerson = new GeneralName(new X509Name("CN=thirdPerson"));
+			IssuerSerial certRef = new IssuerSerial(new GeneralNames(new GeneralName(new X509Name("CN=test"))), new DerInteger(1));
+
+			ProcurationSyntax procuration = new ProcurationSyntax(country, typeOfSubstitution, thirdPerson);
+
+			checkConstruction(procuration, country, typeOfSubstitution, thirdPerson, null);
+
+			procuration = new ProcurationSyntax(country, typeOfSubstitution, certRef);
+
+			checkConstruction(procuration, country, typeOfSubstitution, null, certRef);
+
+			procuration = new ProcurationSyntax(null, typeOfSubstitution, certRef);
+
+			checkConstruction(procuration, null, typeOfSubstitution, null, certRef);
+
+			procuration = new ProcurationSyntax(country, null, certRef);
+
+			checkConstruction(procuration, country, null, null, certRef);
+
+			procuration = ProcurationSyntax.GetInstance(null);
+
+			if (procuration != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				ProcurationSyntax.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			ProcurationSyntax	procuration,
+			string				country,
+			DirectoryString		typeOfSubstitution,
+			GeneralName			thirdPerson,
+			IssuerSerial		certRef)
+		{
+			checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+
+			procuration = ProcurationSyntax.GetInstance(procuration);
+
+			checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+
+			Asn1InputStream aIn = new Asn1InputStream(procuration.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			procuration = ProcurationSyntax.GetInstance(seq);
+
+			checkValues(procuration, country, typeOfSubstitution, thirdPerson, certRef);
+		}
+
+		private void checkValues(
+			ProcurationSyntax procuration,
+			string country,
+			DirectoryString  typeOfSubstitution,
+			GeneralName thirdPerson,
+			IssuerSerial certRef)
+		{
+			checkOptionalField("country", country, procuration.Country);
+			checkOptionalField("typeOfSubstitution", typeOfSubstitution, procuration.TypeOfSubstitution);
+			checkOptionalField("thirdPerson", thirdPerson, procuration.ThirdPerson);
+			checkOptionalField("certRef", certRef, procuration.CertRef);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ProcurationSyntaxUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ProfessionInfoUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ProfessionInfoUnitTest.cs
new file mode 100644
index 0000000..6af2658
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ProfessionInfoUnitTest.cs
@@ -0,0 +1,121 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class ProfessionInfoUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "ProfessionInfo"; }
+		}
+
+		public override void PerformTest()
+		{
+			NamingAuthority auth =  new NamingAuthority(new DerObjectIdentifier("1.2.3"), "url", new DirectoryString("fred"));
+			DirectoryString[] professionItems = { new DirectoryString("substitution") };
+			DerObjectIdentifier[] professionOids = { new DerObjectIdentifier("1.2.3") };
+			string registrationNumber = "12345";
+			DerOctetString addProfInfo = new DerOctetString(new byte[20]);
+
+			ProfessionInfo info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			checkConstruction(info, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			info = new ProfessionInfo(null, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			checkConstruction(info, null, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			info = new ProfessionInfo(auth, professionItems, null, registrationNumber, addProfInfo);
+
+			checkConstruction(info, auth, professionItems, null, registrationNumber, addProfInfo);
+
+			info = new ProfessionInfo(auth, professionItems, professionOids, null, addProfInfo);
+
+			checkConstruction(info, auth, professionItems, professionOids, null, addProfInfo);
+
+			info = new ProfessionInfo(auth, professionItems, professionOids, registrationNumber, null);
+
+			checkConstruction(info, auth, professionItems, professionOids, registrationNumber, null);
+
+			info = ProfessionInfo.GetInstance(null);
+
+			if (info != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				ProcurationSyntax.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			ProfessionInfo			profInfo,
+			NamingAuthority			auth,
+			DirectoryString[]		professionItems,
+			DerObjectIdentifier[]	professionOids,
+			string					registrationNumber,
+			DerOctetString			addProfInfo)
+		{
+			checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			profInfo = ProfessionInfo.GetInstance(profInfo);
+
+			checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+
+			Asn1InputStream aIn = new Asn1InputStream(profInfo.ToAsn1Object().GetEncoded());
+
+			Asn1Sequence seq = (Asn1Sequence) aIn.ReadObject();
+
+			profInfo = ProfessionInfo.GetInstance(seq);
+
+			checkValues(profInfo, auth, professionItems, professionOids, registrationNumber, addProfInfo);
+		}
+
+		private void checkValues(
+			ProfessionInfo			profInfo,
+			NamingAuthority			auth,
+			DirectoryString[]		professionItems,
+			DerObjectIdentifier[]	professionOids,
+			string					registrationNumber,
+			DerOctetString			addProfInfo)
+		{
+			checkOptionalField("auth", auth, profInfo.NamingAuthority);
+			checkMandatoryField("professionItems", professionItems[0], profInfo.GetProfessionItems()[0]);
+			if (professionOids != null)
+			{
+				checkOptionalField("professionOids", professionOids[0], profInfo.GetProfessionOids()[0]);
+			}
+			checkOptionalField("registrationNumber", registrationNumber, profInfo.RegistrationNumber);
+			checkOptionalField("addProfessionInfo", addProfInfo, profInfo.AddProfessionInfo);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ProfessionInfoUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/QCStatementUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/QCStatementUnitTest.cs
new file mode 100644
index 0000000..8d8ec9e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/QCStatementUnitTest.cs
@@ -0,0 +1,108 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class QCStatementUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "QCStatement"; }
+        }
+
+		public override void PerformTest()
+        {
+            QCStatement mv = new QCStatement(Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1);
+
+            CheckConstruction(mv, Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, null);
+
+			Asn1Encodable info = new SemanticsInformation(new DerObjectIdentifier("1.2"));
+
+            mv = new QCStatement(Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, info);
+
+            CheckConstruction(mv, Rfc3739QCObjectIdentifiers.IdQcsPkixQCSyntaxV1, info);
+
+            mv = QCStatement.GetInstance(null);
+
+			if (mv != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+			try
+            {
+                QCStatement.GetInstance(new object());
+
+				Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckConstruction(
+            QCStatement mv,
+            DerObjectIdentifier statementId,
+            Asn1Encodable statementInfo)
+        {
+            CheckStatement(mv, statementId, statementInfo);
+
+			mv = QCStatement.GetInstance(mv);
+
+			CheckStatement(mv, statementId, statementInfo);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				mv.ToAsn1Object().GetEncoded());
+
+			mv = QCStatement.GetInstance(seq);
+
+			CheckStatement(mv, statementId, statementInfo);
+        }
+
+		private void CheckStatement(
+            QCStatement         qcs,
+            DerObjectIdentifier statementId,
+            Asn1Encodable       statementInfo)
+        {
+            if (!qcs.StatementId.Equals(statementId))
+            {
+                Fail("statementIds don't match.");
+            }
+
+			if (statementInfo != null)
+            {
+                if (!qcs.StatementInfo.Equals(statementInfo))
+                {
+                    Fail("statementInfos don't match.");
+                }
+            }
+            else if (qcs.StatementInfo != null)
+            {
+                Fail("statementInfo found when none expected.");
+            }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new QCStatementUnitTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/ReasonFlagsTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/ReasonFlagsTest.cs
new file mode 100644
index 0000000..ef404b3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/ReasonFlagsTest.cs
@@ -0,0 +1,46 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class ReasonFlagsTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "ReasonFlags"; }
+		}
+
+		public override void PerformTest()
+		{
+			BitStringConstantTester.testFlagValueCorrect(0, ReasonFlags.Unused);
+			BitStringConstantTester.testFlagValueCorrect(1, ReasonFlags.KeyCompromise);
+			BitStringConstantTester.testFlagValueCorrect(2, ReasonFlags.CACompromise);
+			BitStringConstantTester.testFlagValueCorrect(3, ReasonFlags.AffiliationChanged);
+			BitStringConstantTester.testFlagValueCorrect(4, ReasonFlags.Superseded);
+			BitStringConstantTester.testFlagValueCorrect(5, ReasonFlags.CessationOfOperation);
+			BitStringConstantTester.testFlagValueCorrect(6, ReasonFlags.CertificateHold);
+			BitStringConstantTester.testFlagValueCorrect(7, ReasonFlags.PrivilegeWithdrawn);
+			BitStringConstantTester.testFlagValueCorrect(8, ReasonFlags.AACompromise);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ReasonFlagsTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/RegressionTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/RegressionTest.cs
new file mode 100644
index 0000000..873ab43
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/RegressionTest.cs
@@ -0,0 +1,85 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    public class RegressionTest
+    {
+        public static readonly ITest[] tests =
+        {
+			new AdditionalInformationSyntaxUnitTest(),
+			new AdmissionSyntaxUnitTest(),
+			new AdmissionsUnitTest(),
+			new AttributeTableUnitTest(),
+            new BiometricDataUnitTest(),
+            new BitStringTest(),
+			new CertHashUnitTest(),
+			new CertificateTest(),
+            new CmsTest(),
+            new CommitmentTypeIndicationUnitTest(),
+            new CommitmentTypeQualifierUnitTest(),
+			new ContentHintsUnitTest(),
+			new CscaMasterListTest(),
+			new DataGroupHashUnitTest(),
+			new DeclarationOfMajorityUnitTest(),
+			new DerApplicationSpecificTest(),
+			new DerUtf8StringTest(),
+			new EncryptedPrivateKeyInfoTest(),
+            new EqualsAndHashCodeTest(),
+			new EssCertIDv2UnitTest(),
+            new GeneralizedTimeTest(),
+			new GeneralNameTest(),
+			new GenerationTest(),
+			new InputStreamTest(),
+            new Iso4217CurrencyCodeUnitTest(),
+			new IssuingDistributionPointUnitTest(),
+			new KeyUsageTest(),
+            new LDSSecurityObjectUnitTest(),
+            new MiscTest(),
+			new MonetaryLimitUnitTest(),
+			new MonetaryValueUnitTest(),
+			new NameOrPseudonymUnitTest(),
+			new NamingAuthorityUnitTest(),
+			new NetscapeCertTypeTest(),
+            new OcspTest(),
+            new OidTest(),
+			new OtherCertIDUnitTest(),
+			new OtherSigningCertificateUnitTest(),
+			new ParsingTest(),
+			new PersonalDataUnitTest(),
+			new Pkcs10Test(),
+            new Pkcs12Test(),
+			new PkiFailureInfoTest(),
+			new ProcurationSyntaxUnitTest(),
+			new ProfessionInfoUnitTest(),
+			new QCStatementUnitTest(),
+			new ReasonFlagsTest(),
+			new RequestedCertificateUnitTest(),
+			new RestrictionUnitTest(),
+			new SemanticsInformationUnitTest(),
+            new SetTest(),
+            new SignerLocationUnitTest(),
+            new SmimeTest(),
+			new StringTest(),
+			new SubjectKeyIdentifierTest(),
+			new TagTest(),
+			new TargetInformationTest(),
+			new TypeOfBiometricDataUnitTest(),
+			new UtcTimeTest(),
+			new X509ExtensionsTest(),
+			new X509NameTest(),
+            new X9Test(),
+        };
+
+        public static void Main(
+            string[] args)
+        {
+            for (int i = 0; i != tests.Length; i++)
+            {
+                ITestResult  result = tests[i].Perform();
+                Console.WriteLine(result);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/RequestedCertificateUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/RequestedCertificateUnitTest.cs
new file mode 100644
index 0000000..7675041
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/RequestedCertificateUnitTest.cs
@@ -0,0 +1,117 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class RequestedCertificateUnitTest
+		: Asn1UnitTest
+	{
+		private static readonly byte[] certBytes = Base64.Decode(
+			"MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+			+ "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+			+ "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+			+ "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+			+ "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+			+ "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+			+ "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+			+ "zl9HYIMxATFyqSiD9jsx");
+
+		public override string Name
+		{
+			get { return "RequestedCertificate"; }
+		}
+
+		public override void PerformTest()
+		{
+			RequestedCertificate.Choice type = RequestedCertificate.Choice.AttributeCertificate;
+			X509CertificateStructure cert = X509CertificateStructure.GetInstance(
+				Asn1Object.FromByteArray(certBytes));
+
+			byte[] certOctets = new byte[20];
+			RequestedCertificate requested = new RequestedCertificate(type, certOctets);
+
+			checkConstruction(requested, type, certOctets, null);
+
+			requested = new RequestedCertificate(cert);
+
+			checkConstruction(requested, RequestedCertificate.Choice.Certificate, null, cert);
+
+			requested = RequestedCertificate.GetInstance(null);
+
+			if (requested != null)
+			{
+				Fail("null GetInstance() failed.");
+			}
+
+			try
+			{
+				RequestedCertificate.GetInstance(new object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			RequestedCertificate		requested,
+			RequestedCertificate.Choice	type,
+			byte[]						certOctets,
+			X509CertificateStructure	cert)
+		{
+			checkValues(requested, type, certOctets, cert);
+
+			requested = RequestedCertificate.GetInstance(requested);
+
+			checkValues(requested, type, certOctets, cert);
+
+			Asn1InputStream aIn = new Asn1InputStream(requested.ToAsn1Object().GetEncoded());
+
+			object obj = aIn.ReadObject();
+
+			requested = RequestedCertificate.GetInstance(obj);
+
+			checkValues(requested, type, certOctets, cert);
+		}
+
+		private void checkValues(
+			RequestedCertificate		requested,
+			RequestedCertificate.Choice	type,
+			byte[]						certOctets,
+			X509CertificateStructure	cert)
+		{
+			checkMandatoryField("certType", (int) type, (int) requested.Type);
+
+			if (requested.Type == RequestedCertificate.Choice.Certificate)
+			{
+				checkMandatoryField("certificate", cert.GetEncoded(), requested.GetCertificateBytes());
+			}
+			else
+			{
+				checkMandatoryField("certificateOctets", certOctets, requested.GetCertificateBytes());
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RequestedCertificateUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/RestrictionUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/RestrictionUnitTest.cs
new file mode 100644
index 0000000..5dd6438
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/RestrictionUnitTest.cs
@@ -0,0 +1,78 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.IsisMtt.X509;
+using Org.BouncyCastle.Asn1.X500;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class RestrictionUnitTest
+		: Asn1UnitTest
+	{
+		public override string Name
+		{
+			get { return "Restriction"; }
+		}
+
+		public override void PerformTest()
+		{
+			DirectoryString res = new DirectoryString("test");
+			Restriction restriction = new Restriction(res.GetString());
+
+			checkConstruction(restriction, res);
+
+			try
+			{
+				Restriction.GetInstance(new Object());
+
+				Fail("GetInstance() failed to detect bad object.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkConstruction(
+			Restriction		restriction,
+			DirectoryString	res)
+		{
+			checkValues(restriction, res);
+
+			restriction = Restriction.GetInstance(restriction);
+
+			checkValues(restriction, res);
+
+			Asn1InputStream aIn = new Asn1InputStream(restriction.ToAsn1Object().GetEncoded());
+
+			IAsn1String str = (IAsn1String) aIn.ReadObject();
+
+			restriction = Restriction.GetInstance(str);
+
+			checkValues(restriction, res);
+		}
+
+		private void checkValues(
+			Restriction		restriction,
+			DirectoryString	res)
+		{
+			checkMandatoryField("restriction", res, restriction.RestrictionString);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RestrictionUnitTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/SMIMETest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/SMIMETest.cs
new file mode 100644
index 0000000..adb90e0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/SMIMETest.cs
@@ -0,0 +1,90 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Smime;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class SmimeTest
+		: ITest
+	{
+		private static byte[] attrBytes = Base64.Decode("MDQGCSqGSIb3DQEJDzEnMCUwCgYIKoZIhvcNAwcwDgYIKoZIhvcNAwICAgCAMAcGBSsOAwIH");
+		private static byte[] prefBytes = Base64.Decode("MCwGCyqGSIb3DQEJEAILMR2hGwQIAAAAAAAAAAAYDzIwMDcwMzE1MTczNzI5Wg==");
+
+		public ITestResult Perform()
+		{
+			SmimeCapabilityVector caps = new SmimeCapabilityVector();
+
+			caps.AddCapability(SmimeCapability.DesEde3Cbc);
+			caps.AddCapability(SmimeCapability.RC2Cbc, 128);
+			caps.AddCapability(SmimeCapability.DesCbc);
+
+			SmimeCapabilitiesAttribute attr = new SmimeCapabilitiesAttribute(caps);
+
+			SmimeEncryptionKeyPreferenceAttribute pref = new SmimeEncryptionKeyPreferenceAttribute(
+				new RecipientKeyIdentifier(new DerOctetString(new byte[8]),
+				new DerGeneralizedTime("20070315173729Z"),
+				null));
+
+			try
+			{
+				if (!Arrays.AreEqual(attr.GetEncoded(), attrBytes))
+				{
+					return new SimpleTestResult(false, Name + ": Failed attr data check");
+				}
+
+				Asn1Object o = Asn1Object.FromByteArray(attrBytes);
+				if (!attr.Equals(o))
+				{
+					return new SimpleTestResult(false, Name + ": Failed equality test for attr");
+				}
+
+				if (!Arrays.AreEqual(pref.GetEncoded(), prefBytes))
+				{
+					return new SimpleTestResult(false, Name + ": Failed attr data check");
+				}
+
+				o = Asn1Object.FromByteArray(prefBytes);
+				if (!pref.Equals(o))
+				{
+					return new SimpleTestResult(false, Name + ": Failed equality test for pref");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": Failed - exception " + e.ToString(), e);
+			}
+		}
+
+		public string Name
+		{
+			get { return "SMIME"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new SmimeTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/SemanticsInformationUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/SemanticsInformationUnitTest.cs
new file mode 100644
index 0000000..8f1f85f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/SemanticsInformationUnitTest.cs
@@ -0,0 +1,138 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class SemanticsInformationUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "SemanticsInformation"; }
+        }
+
+		public override void PerformTest()
+        {
+            DerObjectIdentifier statementId = new DerObjectIdentifier("1.1");
+            SemanticsInformation mv = new SemanticsInformation(statementId);
+
+			CheckConstruction(mv, statementId, null);
+
+            GeneralName[] names = new GeneralName[2];
+
+            names[0] = new GeneralName(GeneralName.Rfc822Name, "test at test.org");
+            names[1] = new GeneralName(new X509Name("cn=test"));
+
+            mv = new SemanticsInformation(statementId, names);
+
+			CheckConstruction(mv, statementId, names);
+
+			mv = new SemanticsInformation(names);
+
+			CheckConstruction(mv, null, names);
+
+			mv = SemanticsInformation.GetInstance(null);
+
+			if (mv != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+			try
+            {
+                SemanticsInformation.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+			try
+            {
+                new SemanticsInformation(DerSequence.Empty);
+
+				Fail("constructor failed to detect empty sequence.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckConstruction(
+            SemanticsInformation	mv,
+            DerObjectIdentifier		semanticsIdentifier,
+            GeneralName[]			names)
+        {
+            CheckStatement(mv, semanticsIdentifier, names);
+
+			mv = SemanticsInformation.GetInstance(mv);
+
+			CheckStatement(mv, semanticsIdentifier, names);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(mv.ToAsn1Object().GetEncoded());
+
+			mv = SemanticsInformation.GetInstance(seq);
+
+			CheckStatement(mv, semanticsIdentifier, names);
+        }
+
+		private void CheckStatement(
+            SemanticsInformation si,
+            DerObjectIdentifier  id,
+            GeneralName[]        names)
+        {
+            if (id != null)
+            {
+                if (!si.SemanticsIdentifier.Equals(id))
+                {
+                    Fail("ids don't match.");
+                }
+            }
+            else if (si.SemanticsIdentifier != null)
+            {
+                Fail("statementId found when none expected.");
+            }
+
+            if (names != null)
+            {
+                GeneralName[] siNames = si.GetNameRegistrationAuthorities();
+
+                for (int i = 0; i != siNames.Length; i++)
+                {
+                    if (!names[i].Equals(siNames[i]))
+                    {
+                        Fail("name registration authorities don't match.");
+                    }
+                }
+            }
+            else if (si.GetNameRegistrationAuthorities() != null)
+            {
+                Fail("name registration authorities found when none expected.");
+            }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new SemanticsInformationUnitTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/SetTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/SetTest.cs
new file mode 100644
index 0000000..57c4660
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/SetTest.cs
@@ -0,0 +1,117 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/// <remarks>Set sorting test example.</remarks>
+	[TestFixture]
+	public class SetTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "Set"; }
+		}
+
+		private void checkSortedSet(
+			int		attempt,
+			Asn1Set	s)
+		{
+			if (s[0] is DerBoolean
+				&& s[1] is DerInteger
+				&& s[2] is DerBitString
+				&& s[3] is DerOctetString)
+			{
+				return;
+			}
+
+			Fail("sorting failed on attempt: " + attempt);
+		}
+
+		public override void PerformTest()
+		{
+			Asn1EncodableVector v = new Asn1EncodableVector();
+			byte[] data = new byte[10];
+
+			v.Add(new DerOctetString(data));
+			v.Add(new DerBitString(data));
+			v.Add(new DerInteger(100));
+			v.Add(DerBoolean.True);
+
+			checkSortedSet(0, new DerSet(v));
+
+			v = new Asn1EncodableVector();
+			v.Add(new DerInteger(100));
+			v.Add(DerBoolean.True);
+			v.Add(new DerOctetString(data));
+			v.Add(new DerBitString(data));
+
+			checkSortedSet(1, new DerSet(v));
+
+			v = new Asn1EncodableVector();
+			v.Add(DerBoolean.True);
+			v.Add(new DerOctetString(data));
+			v.Add(new DerBitString(data));
+			v.Add(new DerInteger(100));
+
+
+			checkSortedSet(2, new DerSet(v));
+
+			v = new Asn1EncodableVector();
+			v.Add(new DerBitString(data));
+			v.Add(new DerOctetString(data));
+			v.Add(new DerInteger(100));
+			v.Add(DerBoolean.True);
+
+			checkSortedSet(3, new DerSet(v));
+
+			v = new Asn1EncodableVector();
+			v.Add(new DerOctetString(data));
+			v.Add(new DerBitString(data));
+			v.Add(new DerInteger(100));
+			v.Add(DerBoolean.True);
+
+			Asn1Set s = new BerSet(v);
+
+			if (!(s[0] is DerOctetString))
+			{
+				Fail("BER set sort order changed.");
+			}
+
+			// create an implicitly tagged "set" without sorting
+			Asn1TaggedObject tag = new DerTaggedObject(false, 1, new DerSequence(v));
+			s = Asn1Set.GetInstance(tag, false);
+
+			if (s[0] is DerBoolean)
+			{
+				Fail("sorted when shouldn't be.");
+			}
+
+			// equality test
+			v = new Asn1EncodableVector();
+
+			v.Add(DerBoolean.True);
+			v.Add(DerBoolean.True);
+			v.Add(DerBoolean.True);
+
+			s = new DerSet(v);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SetTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+		    string resultText = Perform().ToString();
+
+		    Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/SignerLocationUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/SignerLocationUnitTest.cs
new file mode 100644
index 0000000..bf20f1f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/SignerLocationUnitTest.cs
@@ -0,0 +1,195 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Esf;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class SignerLocationUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "SignerLocation"; }
+        }
+
+		public override void PerformTest()
+        {
+            DerUtf8String countryName = new DerUtf8String("Australia");
+
+            SignerLocation sl = new SignerLocation(countryName, null, null);
+
+            CheckConstruction(sl, countryName, null, null);
+
+            DerUtf8String localityName = new DerUtf8String("Melbourne");
+
+            sl = new SignerLocation(null, localityName, null);
+
+			CheckConstruction(sl, null, localityName, null);
+
+			sl = new SignerLocation(countryName, localityName, null);
+
+			CheckConstruction(sl, countryName, localityName, null);
+
+			Asn1Sequence postalAddress = new DerSequence(
+				new DerUtf8String("line 1"),
+				new DerUtf8String("line 2"));
+
+            sl = new SignerLocation(null, null, postalAddress);
+
+            CheckConstruction(sl, null, null, postalAddress);
+
+            sl = new SignerLocation(countryName, null, postalAddress);
+
+            CheckConstruction(sl, countryName, null, postalAddress);
+
+            sl = new SignerLocation(countryName, localityName, postalAddress);
+
+            CheckConstruction(sl, countryName, localityName, postalAddress);
+
+            sl = SignerLocation.GetInstance(null);
+
+            if (sl != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                SignerLocation.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            //
+            // out of range postal address
+            //
+			postalAddress = new DerSequence(
+				new DerUtf8String("line 1"),
+				new DerUtf8String("line 2"),
+				new DerUtf8String("line 3"),
+				new DerUtf8String("line 4"),
+				new DerUtf8String("line 5"),
+				new DerUtf8String("line 6"),
+				new DerUtf8String("line 7"));
+
+			try
+            {
+                new SignerLocation(null, null, postalAddress);
+
+                Fail("constructor failed to detect bad postalAddress.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new SignerLocation(new DerSequence(new DerTaggedObject(2, postalAddress)));
+
+                Fail("sequence constructor failed to detect bad postalAddress.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new SignerLocation(new DerSequence(new DerTaggedObject(5, postalAddress)));
+
+                Fail("sequence constructor failed to detect bad tag.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+		private void CheckConstruction(
+            SignerLocation sl,
+            DerUtf8String  countryName,
+            DerUtf8String  localityName,
+            Asn1Sequence   postalAddress)
+        {
+            CheckValues(sl, countryName, localityName, postalAddress);
+
+			sl = SignerLocation.GetInstance(sl);
+
+			CheckValues(sl, countryName, localityName, postalAddress);
+
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(
+				sl.ToAsn1Object().GetEncoded());
+
+			sl = SignerLocation.GetInstance(seq);
+
+			CheckValues(sl, countryName, localityName, postalAddress);
+        }
+
+		private void CheckValues(
+            SignerLocation sl,
+            DerUtf8String  countryName,
+            DerUtf8String  localityName,
+            Asn1Sequence   postalAddress)
+        {
+            if (countryName != null)
+            {
+                if (!countryName.Equals(sl.CountryName))
+                {
+                    Fail("countryNames don't match.");
+                }
+            }
+            else if (sl.CountryName != null)
+            {
+                Fail("countryName found when none expected.");
+            }
+
+            if (localityName != null)
+            {
+                if (!localityName.Equals(sl.LocalityName))
+                {
+                    Fail("localityNames don't match.");
+                }
+            }
+            else if (sl.LocalityName != null)
+            {
+                Fail("localityName found when none expected.");
+            }
+
+            if (postalAddress != null)
+            {
+                if (!postalAddress.Equals(sl.PostalAddress))
+                {
+                    Fail("postalAddresses don't match.");
+                }
+            }
+            else if (sl.PostalAddress != null)
+            {
+                Fail("postalAddress found when none expected.");
+            }
+        }
+
+		public static void Main(
+			string[] args)
+        {
+            RunTest(new SignerLocationUnitTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/StringTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/StringTest.cs
new file mode 100644
index 0000000..acfd380
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/StringTest.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/**
+	* X.690 test example
+	*/
+	[TestFixture]
+	public class StringTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "String"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerBitString bs = new DerBitString(
+				new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
+
+			if (!bs.GetString().Equals("#0309000123456789ABCDEF"))
+			{
+				Fail("DerBitString.GetString() result incorrect");
+			}
+
+			if (!bs.ToString().Equals("#0309000123456789ABCDEF"))
+			{
+				Fail("DerBitString.ToString() result incorrect");
+			}
+
+			bs = new DerBitString(
+				new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
+
+			if (!bs.GetString().Equals("#030900FEDCBA9876543210"))
+			{
+				Fail("DerBitString.GetString() result incorrect");
+			}
+
+			if (!bs.ToString().Equals("#030900FEDCBA9876543210"))
+			{
+				Fail("DerBitString.ToString() result incorrect");
+			}
+
+			DerUniversalString us = new DerUniversalString(
+				new byte[] { (byte)0x01,(byte)0x23,(byte)0x45,(byte)0x67,(byte)0x89,(byte)0xab,(byte)0xcd,(byte)0xef });
+
+			if (!us.GetString().Equals("#1C080123456789ABCDEF"))
+			{
+				Fail("DerUniversalString.GetString() result incorrect");
+			}
+
+			if (!us.ToString().Equals("#1C080123456789ABCDEF"))
+			{
+				Fail("DerUniversalString.ToString() result incorrect");
+			}
+
+			us = new DerUniversalString(
+				new byte[] { (byte)0xfe,(byte)0xdc,(byte)0xba,(byte)0x98,(byte)0x76,(byte)0x54,(byte)0x32,(byte)0x10 });
+
+			if (!us.GetString().Equals("#1C08FEDCBA9876543210"))
+			{
+				Fail("DerUniversalString.GetString() result incorrect");
+			}
+
+			if (!us.ToString().Equals("#1C08FEDCBA9876543210"))
+			{
+				Fail("DerUniversalString.ToString() result incorrect");
+			}
+
+			byte[] t61Bytes = new byte[] { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8 };
+			string t61String = Encoding.GetEncoding("iso-8859-1").GetString(t61Bytes, 0, t61Bytes.Length);
+			DerT61String t61 = new DerT61String(t61Bytes);
+
+			if (!t61.GetString().Equals(t61String))
+			{
+				Fail("DerT61String.GetString() result incorrect");
+			}
+
+			if (!t61.ToString().Equals(t61String))
+			{
+				Fail("DerT61String.ToString() result incorrect");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new StringTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/SubjectKeyIdentifierTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/SubjectKeyIdentifierTest.cs
new file mode 100644
index 0000000..127c47a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/SubjectKeyIdentifierTest.cs
@@ -0,0 +1,61 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class SubjectKeyIdentifierTest
+		: SimpleTest
+	{
+		private static byte[] pubKeyInfo = Base64.Decode(
+			"MFgwCwYJKoZIhvcNAQEBA0kAMEYCQQC6wMMmHYMZszT/7bNFMn+gaZoiWJLVP8ODRuu1C2jeAe" +
+			"QpxM+5Oe7PaN2GNy3nBE4EOYkB5pMJWA0y9n04FX8NAgED");
+
+		private static byte[] shaID = Hex.Decode("d8128a06d6c2feb0865994a2936e7b75b836a021");
+		private static byte[] shaTruncID = Hex.Decode("436e7b75b836a021");
+
+		public override string Name
+		{
+			get { return "SubjectKeyIdentifier"; }
+		}
+
+		public override void PerformTest()
+		{
+			SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfo.GetInstance(
+				Asn1Object.FromByteArray(pubKeyInfo));
+			SubjectKeyIdentifier ski = SubjectKeyIdentifier.CreateSha1KeyIdentifier(pubInfo);
+
+			if (!Arrays.AreEqual(shaID, ski.GetKeyIdentifier()))
+			{
+				Fail("SHA-1 ID does not match");
+			}
+
+			ski = SubjectKeyIdentifier.CreateTruncatedSha1KeyIdentifier(pubInfo);
+
+			if (!Arrays.AreEqual(shaTruncID, ski.GetKeyIdentifier()))
+			{
+				Fail("truncated SHA-1 ID does not match");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SubjectKeyIdentifierTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/TagTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/TagTest.cs
new file mode 100644
index 0000000..c5fce6d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/TagTest.cs
@@ -0,0 +1,115 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/**
+	* X.690 test example
+	*/
+	[TestFixture]
+	public class TagTest
+		: SimpleTest
+	{
+		private static readonly byte[] longTagged = Base64.Decode(
+			  "ZSRzIp8gEEZFRENCQTk4NzY1NDMyMTCfIQwyMDA2MDQwMTEyMzSUCCAFERVz"
+			+ "A4kCAHEXGBkalAggBRcYGRqUCCAFZS6QAkRFkQlURUNITklLRVKSBQECAwQF"
+			+ "kxAREhMUFRYXGBkalAggBREVcwOJAgBxFxgZGpQIIAUXGBkalAggBWUukAJE"
+			+ "RZEJVEVDSE5JS0VSkgUBAgMEBZMQERITFBUWFxgZGpQIIAURFXMDiQIAcRcY"
+			+ "GRqUCCAFFxgZGpQIIAVlLpACREWRCVRFQ0hOSUtFUpIFAQIDBAWTEBESExQV"
+			+ "FhcYGRqUCCAFERVzA4kCAHEXGBkalAggBRcYGRqUCCAFFxgZGpQIIAUXGBka"
+			+ "lAg=");
+
+		private static readonly byte[] longAppSpecificTag = Hex.Decode("5F610101");
+
+		public override string Name
+		{
+			get { return "Tag"; }
+		}
+
+		public override void PerformTest()
+		{
+			DerApplicationSpecific app = (DerApplicationSpecific)
+				Asn1Object.FromByteArray(longTagged);
+
+			app = (DerApplicationSpecific) Asn1Object.FromByteArray(app.GetContents());
+
+			Asn1InputStream aIn = new Asn1InputStream(app.GetContents());
+
+			Asn1TaggedObject tagged = (Asn1TaggedObject) aIn.ReadObject();
+
+			if (tagged.TagNo != 32)
+			{
+				Fail("unexpected tag value found - not 32");
+			}
+
+			tagged = (Asn1TaggedObject) Asn1Object.FromByteArray(tagged.GetEncoded());
+
+			if (tagged.TagNo != 32)
+			{
+				Fail("unexpected tag value found on recode - not 32");
+			}
+
+			tagged = (Asn1TaggedObject) aIn.ReadObject();
+
+			if (tagged.TagNo != 33)
+			{
+				Fail("unexpected tag value found - not 33");
+			}
+
+			tagged = (Asn1TaggedObject) Asn1Object.FromByteArray(tagged.GetEncoded());
+
+			if (tagged.TagNo != 33)
+			{
+				Fail("unexpected tag value found on recode - not 33");
+			}
+
+			aIn = new Asn1InputStream(longAppSpecificTag);
+
+			app = (DerApplicationSpecific)aIn.ReadObject();
+
+			if (app.ApplicationTag != 97)
+			{
+				Fail("incorrect tag number read");
+			}
+
+			app = (DerApplicationSpecific)Asn1Object.FromByteArray(app.GetEncoded());
+
+			if (app.ApplicationTag != 97)
+			{
+				Fail("incorrect tag number read on recode");
+			}
+
+			SecureRandom sr = new SecureRandom();
+			for (int i = 0; i < 100; ++i)
+			{
+				int testTag = (sr.NextInt() & int.MaxValue) >> sr.Next(26);
+				app = new DerApplicationSpecific(testTag, new byte[]{ 1 });
+				app = (DerApplicationSpecific)Asn1Object.FromByteArray(app.GetEncoded());
+
+				if (app.ApplicationTag != testTag)
+				{
+					Fail("incorrect tag number read on recode (random test value: " + testTag + ")");
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new TagTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/TargetInformationTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/TargetInformationTest.cs
new file mode 100644
index 0000000..7fa04cd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/TargetInformationTest.cs
@@ -0,0 +1,58 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class TargetInformationTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "TargetInformation"; }
+		}
+
+		public override void PerformTest()
+		{
+			Target[] targets = new Target[2];
+			Target targetName = new Target(Target.Choice.Name, new GeneralName(GeneralName.DnsName, "www.test.com"));
+			Target targetGroup = new Target(Target.Choice.Group, new GeneralName(GeneralName.DirectoryName, "o=Test, ou=Test"));
+			targets[0] = targetName;
+			targets[1] = targetGroup;
+			Targets targetss = new Targets(targets);
+			TargetInformation targetInformation1 = new TargetInformation(targetss);
+			// use an Target array
+			TargetInformation targetInformation2 = new TargetInformation(targets);
+			// targetInformation1 and targetInformation2 must have same
+			// encoding.
+			if (!targetInformation1.Equals(targetInformation2))
+			{
+				Fail("targetInformation1 and targetInformation2 should have the same encoding.");
+			}
+			TargetInformation targetInformation3 = TargetInformation.GetInstance(targetInformation1.ToAsn1Object());
+			TargetInformation targetInformation4 = TargetInformation.GetInstance(targetInformation2.ToAsn1Object());
+			if (!targetInformation3.Equals(targetInformation4))
+			{
+				Fail("targetInformation3 and targetInformation4 should have the same encoding.");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new TargetInformationTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/TimeTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/TimeTest.cs
new file mode 100644
index 0000000..101a879
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/TimeTest.cs
@@ -0,0 +1,28 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class TimeTest
+	{
+		[Test]
+		public void CheckCmsTimeVsX509Time()
+		{
+			DateTime now = DateTime.UtcNow;
+
+			// Time classes only have a resolution of seconds
+			now = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second, DateTimeKind.Utc);
+
+			Org.BouncyCastle.Asn1.Cms.Time cmsTime = new Org.BouncyCastle.Asn1.Cms.Time(now);
+			Org.BouncyCastle.Asn1.X509.Time x509Time = new Org.BouncyCastle.Asn1.X509.Time(now);
+
+//			Assert.AreEqual(cmsTime.Date, x509Time.ToDateTime());
+			Assert.AreEqual(now, cmsTime.Date);
+			Assert.AreEqual(now, x509Time.ToDateTime());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs
new file mode 100644
index 0000000..a59415c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/TypeOfBiometricDataUnitTest.cs
@@ -0,0 +1,152 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509.Qualified;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class TypeOfBiometricDataUnitTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "TypeOfBiometricData"; }
+        }
+
+		public override void PerformTest()
+        {
+            //
+            // predefined
+            //
+            CheckPredefinedType(TypeOfBiometricData.Picture);
+
+            CheckPredefinedType(TypeOfBiometricData.HandwrittenSignature);
+
+			//
+            // non-predefined
+            //
+            DerObjectIdentifier localType = new DerObjectIdentifier("1.1");
+
+			TypeOfBiometricData type = new TypeOfBiometricData(localType);
+
+			CheckNonPredefined(type, localType);
+
+            type = TypeOfBiometricData.GetInstance(type);
+
+            CheckNonPredefined(type, localType);
+
+            Asn1Object obj = type.ToAsn1Object();
+
+            type = TypeOfBiometricData.GetInstance(obj);
+
+            CheckNonPredefined(type, localType);
+
+            type = TypeOfBiometricData.GetInstance(null);
+
+            if (type != null)
+            {
+                Fail("null GetInstance() failed.");
+            }
+
+            try
+            {
+                TypeOfBiometricData.GetInstance(new object());
+
+                Fail("GetInstance() failed to detect bad object.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                new TypeOfBiometricData(100);
+
+                Fail("constructor failed to detect bad predefined type.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+			// Call Equals to avoid unreachable code warning
+            if (!Equals(TypeOfBiometricData.Picture, 0))
+            {
+                Fail("predefined picture should be 0");
+            }
+
+			// Call Equals to avoid unreachable code warning
+			if (!Equals(TypeOfBiometricData.HandwrittenSignature, 1))
+			{
+                Fail("predefined handwritten signature should be 1");
+            }
+        }
+
+		private void CheckPredefinedType(
+            int predefinedType)
+        {
+            TypeOfBiometricData type = new TypeOfBiometricData(predefinedType);
+
+            CheckPredefined(type, predefinedType);
+
+            type = TypeOfBiometricData.GetInstance(type);
+
+			CheckPredefined(type, predefinedType);
+
+			Asn1Object obj = Asn1Object.FromByteArray(type.ToAsn1Object().GetEncoded());
+
+			type = TypeOfBiometricData.GetInstance(obj);
+
+			CheckPredefined(type, predefinedType);
+        }
+
+		private void CheckPredefined(
+            TypeOfBiometricData	type,
+            int					val)
+        {
+            if (!type.IsPredefined)
+            {
+                Fail("predefined type expected but not found.");
+            }
+
+			if (type.PredefinedBiometricType != val)
+            {
+                Fail("predefined type does not match.");
+            }
+        }
+
+		private void CheckNonPredefined(
+            TypeOfBiometricData type,
+            DerObjectIdentifier val)
+        {
+            if (type.IsPredefined)
+            {
+                Fail("predefined type found when not expected.");
+            }
+
+			if (!type.BiometricDataOid.Equals(val))
+            {
+                Fail("data oid does not match.");
+            }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new TypeOfBiometricDataUnitTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/UTCTimeTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/UTCTimeTest.cs
new file mode 100644
index 0000000..07abbc9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/UTCTimeTest.cs
@@ -0,0 +1,122 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	/**
+	* X.690 test example
+	*/
+	[TestFixture]
+	public class UtcTimeTest
+		: SimpleTest
+	{
+		private static readonly string[] input =
+		{
+			"020122122220Z",
+			"020122122220-1000",
+			"020122122220+1000",
+			"020122122220+00",
+			"0201221222Z",
+			"0201221222-1000",
+			"0201221222+1000",
+			"0201221222+00",
+			"550122122220Z",
+			"5501221222Z"
+		};
+
+		private static readonly string[] output =
+		{
+			"20020122122220GMT+00:00",
+			"20020122122220GMT-10:00",
+			"20020122122220GMT+10:00",
+			"20020122122220GMT+00:00",
+			"20020122122200GMT+00:00",
+			"20020122122200GMT-10:00",
+			"20020122122200GMT+10:00",
+			"20020122122200GMT+00:00",
+			"19550122122220GMT+00:00",
+			"19550122122200GMT+00:00"
+		};
+
+		private static readonly string[] zOutput1 =
+		{
+			"20020122122220Z",
+			"20020122222220Z",
+			"20020122022220Z",
+			"20020122122220Z",
+			"20020122122200Z",
+			"20020122222200Z",
+			"20020122022200Z",
+			"20020122122200Z",
+			"19550122122220Z",
+			"19550122122200Z"
+		};
+
+		private static readonly string[] zOutput2 =
+		{
+			"20020122122220Z",
+			"20020122222220Z",
+			"20020122022220Z",
+			"20020122122220Z",
+			"20020122122200Z",
+			"20020122222200Z",
+			"20020122022200Z",
+			"20020122122200Z",
+			"19550122122220Z",
+			"19550122122200Z"
+		};
+
+		public override string Name
+		{
+			get { return "UTCTime"; }
+		}
+
+		public override void PerformTest()
+		{
+//			SimpleDateFormat yyyyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+//			SimpleDateFormat yyF = new SimpleDateFormat("yyyyMMddHHmmss'Z'");
+
+//			yyyyF.setTimeZone(new SimpleTimeZone(0,"Z"));
+//			yyF.setTimeZone(new SimpleTimeZone(0,"Z"));
+
+			for (int i = 0; i != input.Length; i++)
+			{
+				DerUtcTime t = new DerUtcTime(input[i]);
+
+				if (!t.AdjustedTimeString.Equals(output[i]))
+				{
+					Fail("failed conversion test " + i);
+				}
+
+//				if (!yyyyF.format(t.getAdjustedDate()).Equals(zOutput1[i]))
+				if (!t.ToAdjustedDateTime().ToString(@"yyyyMMddHHmmss\Z").Equals(zOutput1[i]))
+				{
+					Fail("failed date conversion test " + i);
+				}
+
+//				if (!yyF.format(t.getDate()).Equals(zOutput2[i]))
+				if (!t.ToDateTime().ToString(@"yyyyMMddHHmmss\Z").Equals(zOutput2[i]))
+				{
+					Fail("failed date shortened conversion test " + i);
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new UtcTimeTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/X509ExtensionsTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/X509ExtensionsTest.cs
new file mode 100644
index 0000000..f1efd3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/X509ExtensionsTest.cs
@@ -0,0 +1,117 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+	[TestFixture]
+	public class X509ExtensionsTest
+		: SimpleTest
+	{
+		private static readonly DerObjectIdentifier Oid1 = new DerObjectIdentifier("1.2.1");
+		private static readonly DerObjectIdentifier Oid2 = new DerObjectIdentifier("1.2.2");
+		private static readonly DerObjectIdentifier Oid3 = new DerObjectIdentifier("1.2.3");
+
+		public override string Name
+		{
+			get { return "X509Extensions"; }
+		}
+
+		public override void PerformTest()
+		{
+			X509ExtensionsGenerator gen = new X509ExtensionsGenerator();
+
+			gen.AddExtension(Oid1, true, new byte[20]);
+			gen.AddExtension(Oid2, true, new byte[20]);
+
+			X509Extensions ext1 = gen.Generate();
+			X509Extensions ext2 = gen.Generate();
+
+			if (!ext1.Equals(ext2))
+			{
+				Fail("Equals test failed");
+			}
+
+			gen.Reset();
+
+			gen.AddExtension(Oid2, true, new byte[20]);
+			gen.AddExtension(Oid1, true, new byte[20]);
+
+			ext2 = gen.Generate();
+
+			if (ext1.Equals(ext2))
+			{
+				Fail("inequality test failed");
+			}
+
+			if (!ext1.Equivalent(ext2))
+			{
+				Fail("equivalence true failed");
+			}
+
+			gen.Reset();
+
+			gen.AddExtension(Oid1, true, new byte[22]);
+			gen.AddExtension(Oid2, true, new byte[20]);
+
+			ext2 = gen.Generate();
+
+			if (ext1.Equals(ext2))
+			{
+				Fail("inequality 1 failed");
+			}
+
+			if (ext1.Equivalent(ext2))
+			{
+				Fail("non-equivalence 1 failed");
+			}
+
+			gen.Reset();
+
+			gen.AddExtension(Oid3, true, new byte[20]);
+			gen.AddExtension(Oid2, true, new byte[20]);
+
+			ext2 = gen.Generate();
+
+			if (ext1.Equals(ext2))
+			{
+				Fail("inequality 2 failed");
+			}
+
+			if (ext1.Equivalent(ext2))
+			{
+				Fail("non-equivalence 2 failed");
+			}
+
+			try
+			{
+				gen.AddExtension(Oid2, true, new byte[20]);
+				Fail("repeated oid");
+			}
+			catch (ArgumentException e)
+			{
+				if (!e.Message.Equals("extension 1.2.2 already added"))
+				{
+					Fail("wrong exception on repeated oid: " + e.Message);
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new X509ExtensionsTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/X509NameTest.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/X509NameTest.cs
new file mode 100644
index 0000000..9a564f7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/X509NameTest.cs
@@ -0,0 +1,674 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class X509NameTest
+        : SimpleTest
+    {
+        private static readonly string[] subjects =
+        {
+            "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Webserver Team,CN=www2.connect4.com.au,E=webmaster at connect4.com.au",
+            "C=AU,ST=Victoria,L=South Melbourne,O=Connect 4 Pty Ltd,OU=Certificate Authority,CN=Connect 4 CA,E=webmaster at connect4.com.au",
+            "C=AU,ST=QLD,CN=SSLeay/rsa test cert",
+            "C=US,O=National Aeronautics and Space Administration,SERIALNUMBER=16+CN=Steve Schoch",
+            "E=cooke at issl.atl.hp.com,C=US,OU=Hewlett Packard Company (ISSL),CN=Paul A. Cooke",
+            "O=Sun Microsystems Inc,CN=store.sun.com",
+            "unstructuredAddress=192.168.1.33,unstructuredName=pixfirewall.ciscopix.com,CN=pixfirewall.ciscopix.com"
+        };
+
+        public override string Name
+        {
+            get { return "X509Name"; }
+        }
+
+        private static X509Name FromBytes(
+            byte[] bytes)
+        {
+            return X509Name.GetInstance(Asn1Object.FromByteArray(bytes));
+        }
+
+        private IAsn1Convertible createEntryValue(
+            DerObjectIdentifier	oid,
+            string				value)
+        {
+            IDictionary attrs = new Hashtable();
+            attrs.Add(oid, value);
+
+            IList ord = new ArrayList();
+            ord.Add(oid);
+
+            X509Name name = new X509Name(ord, attrs);
+
+            Asn1Sequence seq = (Asn1Sequence)name.ToAsn1Object();
+            Asn1Set set = (Asn1Set)seq[0];
+            seq = (Asn1Sequence)set[0];
+
+            return seq[1];
+        }
+
+        private IAsn1Convertible createEntryValueFromString(
+            DerObjectIdentifier	oid,
+            string				val)
+        {
+            IDictionary attrs = new Hashtable();
+            attrs.Add(oid, val);
+
+            IList ord = new ArrayList(attrs.Keys);
+
+            X509Name name = new X509Name(new X509Name(ord, attrs).ToString());
+
+            Asn1Sequence seq = (Asn1Sequence) name.ToAsn1Object();
+            Asn1Set asn1Set = (Asn1Set) seq[0];
+            seq = (Asn1Sequence) asn1Set[0];
+
+            return seq[1];
+        }
+
+        private void doTestEncodingPrintableString(
+            DerObjectIdentifier	oid,
+            string				value)
+        {
+            IAsn1Convertible converted = createEntryValue(oid, value);
+            if (!(converted is DerPrintableString))
+            {
+                Fail("encoding for " + oid + " not printable string");
+            }
+        }
+
+        private void doTestEncodingIA5String(
+            DerObjectIdentifier oid,
+            string				value)
+        {
+            IAsn1Convertible converted = createEntryValue(oid, value);
+            if (!(converted is DerIA5String))
+            {
+                Fail("encoding for " + oid + " not IA5String");
+            }
+        }
+
+        private void doTestEncodingGeneralizedTime(
+            DerObjectIdentifier	oid,
+            string				val)
+        {
+            IAsn1Convertible converted = createEntryValue(oid, val);
+            if (!(converted is DerGeneralizedTime))
+            {
+                Fail("encoding for " + oid + " not GeneralizedTime");
+            }
+            converted = createEntryValueFromString(oid, val);
+            if (!(converted is DerGeneralizedTime))
+            {
+                Fail("encoding for " + oid + " not GeneralizedTime");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            doTestEncodingPrintableString(X509Name.C, "AU");
+            doTestEncodingPrintableString(X509Name.SerialNumber, "123456");
+            doTestEncodingPrintableString(X509Name.DnQualifier, "123456");
+            doTestEncodingIA5String(X509Name.EmailAddress, "test at test.com");
+            doTestEncodingIA5String(X509Name.DC, "test");
+            // correct encoding
+            doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "#180F32303032303132323132323232305A");
+            // compatability encoding
+            doTestEncodingGeneralizedTime(X509Name.DateOfBirth, "20020122122220Z");
+
+            //
+            // composite
+            //
+            IDictionary attrs = new Hashtable();
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.E, "feedback-crypto at bouncycastle.org");
+
+            IList order = new ArrayList();
+            order.Add(X509Name.C);
+            order.Add(X509Name.O);
+            order.Add(X509Name.L);
+            order.Add(X509Name.ST);
+            order.Add(X509Name.E);
+
+            X509Name name1 = new X509Name(order, attrs);
+
+            if (!name1.Equivalent(name1))
+            {
+                Fail("Failed same object test");
+            }
+
+            if (!name1.Equivalent(name1, true))
+            {
+                Fail("Failed same object test - in Order");
+            }
+
+            X509Name name2 = new X509Name(order, attrs);
+
+            if (!name1.Equivalent(name2))
+            {
+                Fail("Failed same name test");
+            }
+
+            if (!name1.Equivalent(name2, true))
+            {
+                Fail("Failed same name test - in Order");
+            }
+
+            if (name1.GetHashCode() != name2.GetHashCode())
+            {
+                Fail("Failed same name test - in Order");
+            }
+
+            IList ord1 = new ArrayList();
+
+            ord1.Add(X509Name.C);
+            ord1.Add(X509Name.O);
+            ord1.Add(X509Name.L);
+            ord1.Add(X509Name.ST);
+            ord1.Add(X509Name.E);
+
+            IList ord2 = new ArrayList();
+
+            ord2.Add(X509Name.E);
+            ord2.Add(X509Name.ST);
+            ord2.Add(X509Name.L);
+            ord2.Add(X509Name.O);
+            ord2.Add(X509Name.C);
+
+            name1 = new X509Name(ord1, attrs);
+            name2 = new X509Name(ord2, attrs);
+
+            if (!name1.Equivalent(name2))
+            {
+                Fail("Failed reverse name test");
+            }
+
+            // FIXME Sort out X509Name hashcode problem
+//			if (name1.GetHashCode() != name2.GetHashCode())
+//			{
+//				Fail("Failed reverse name test GetHashCode");
+//			}
+
+            if (name1.Equivalent(name2, true))
+            {
+                Fail("Failed reverse name test - in Order");
+            }
+
+            if (!name1.Equivalent(name2, false))
+            {
+                Fail("Failed reverse name test - in Order false");
+            }
+
+            IList oids = name1.GetOidList();
+            if (!CompareVectors(oids, ord1))
+            {
+                Fail("oid comparison test");
+            }
+
+            IList val1 = new ArrayList();
+
+            val1.Add("AU");
+            val1.Add("The Legion of the Bouncy Castle");
+            val1.Add("Melbourne");
+            val1.Add("Victoria");
+            val1.Add("feedback-crypto at bouncycastle.org");
+
+            name1 = new X509Name(ord1, val1);
+
+            IList values = name1.GetValueList();
+            if (!CompareVectors(values, val1))
+            {
+                Fail("value comparison test");
+            }
+
+            ord2 = new ArrayList();
+
+            ord2.Add(X509Name.ST);
+            ord2.Add(X509Name.ST);
+            ord2.Add(X509Name.L);
+            ord2.Add(X509Name.O);
+            ord2.Add(X509Name.C);
+
+            name1 = new X509Name(ord1, attrs);
+            name2 = new X509Name(ord2, attrs);
+
+            if (name1.Equivalent(name2))
+            {
+                Fail("Failed different name test");
+            }
+
+            ord2 = new ArrayList();
+
+            ord2.Add(X509Name.ST);
+            ord2.Add(X509Name.L);
+            ord2.Add(X509Name.O);
+            ord2.Add(X509Name.C);
+
+            name1 = new X509Name(ord1, attrs);
+            name2 = new X509Name(ord2, attrs);
+
+            if (name1.Equivalent(name2))
+            {
+                Fail("Failed subset name test");
+            }
+
+
+            compositeTest();
+
+
+            //
+            // getValues test
+            //
+            IList v1 = name1.GetValueList(X509Name.O);
+
+            if (v1.Count != 1 || !v1[0].Equals("The Legion of the Bouncy Castle"))
+            {
+                Fail("O test failed");
+            }
+
+            IList v2 = name1.GetValueList(X509Name.L);
+
+            if (v2.Count != 1 || !v2[0].Equals("Melbourne"))
+            {
+                Fail("L test failed");
+            }
+
+            //
+            // general subjects test
+            //
+            for (int i = 0; i != subjects.Length; i++)
+            {
+                X509Name name = new X509Name(subjects[i]);
+                byte[] encodedName = name.GetEncoded();
+                name = X509Name.GetInstance(Asn1Object.FromByteArray(encodedName));
+
+                if (!name.ToString().Equals(subjects[i]))
+                {
+                    Fail("Failed regeneration test " + i);
+                }
+            }
+
+            //
+            // sort test
+            //
+            X509Name unsorted = new X509Name("SERIALNUMBER=BBB + CN=AA");
+
+            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("CN=AA+SERIALNUMBER=BBB"))
+            {
+                Fail("Failed sort test 1");
+            }
+
+            unsorted = new X509Name("CN=AA + SERIALNUMBER=BBB");
+
+            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("CN=AA+SERIALNUMBER=BBB"))
+            {
+                Fail("Failed sort test 2");
+            }
+
+            unsorted = new X509Name("SERIALNUMBER=B + CN=AA");
+
+            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("SERIALNUMBER=B+CN=AA"))
+            {
+                Fail("Failed sort test 3");
+            }
+
+            unsorted = new X509Name("CN=AA + SERIALNUMBER=B");
+
+            if (!FromBytes(unsorted.GetEncoded()).ToString().Equals("SERIALNUMBER=B+CN=AA"))
+            {
+                Fail("Failed sort test 4");
+            }
+
+            //
+            // equality tests
+            //
+            equalityTest(new X509Name("CN=The     Legion"), new X509Name("CN=The Legion"));
+            equalityTest(new X509Name("CN=   The Legion"), new X509Name("CN=The Legion"));
+            equalityTest(new X509Name("CN=The Legion   "), new X509Name("CN=The Legion"));
+            equalityTest(new X509Name("CN=  The     Legion "), new X509Name("CN=The Legion"));
+            equalityTest(new X509Name("CN=  the     legion "), new X509Name("CN=The Legion"));
+
+            // # test
+
+            X509Name n1 = new X509Name("SERIALNUMBER=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+            X509Name n2 = new X509Name("2.5.4.5=8,O=ABC,CN=ABC Class 3 CA,C=LT");
+            X509Name n3 = new X509Name("2.5.4.5=#130138,O=ABC,CN=ABC Class 3 CA,C=LT");
+
+            equalityTest(n1, n2);
+            equalityTest(n2, n3);
+            equalityTest(n3, n1);
+
+            n1 = new X509Name(true, "2.5.4.5=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+            n2 = new X509Name(true, "SERIALNUMBER=#130138,CN=SSC Class 3 CA,O=UAB Skaitmeninio sertifikavimo centras,C=LT");
+            n3 = X509Name.GetInstance(Asn1Object.FromByteArray(Hex.Decode("3063310b3009060355040613024c54312f302d060355040a1326"
+                + "55414220536b6169746d656e696e696f20736572746966696b6176696d6f2063656e74726173311730150603550403130e53534320436c6173732033204341310a30080603550405130138")));
+
+            equalityTest(n1, n2);
+            equalityTest(n2, n3);
+            equalityTest(n3, n1);
+
+            n1 = new X509Name("SERIALNUMBER=8,O=XX,CN=ABC Class 3 CA,C=LT");
+            n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+            if (n1.Equivalent(n2))
+            {
+                Fail("empty inequality check failed");
+            }
+
+            n1 = new X509Name("SERIALNUMBER=8,O=,CN=ABC Class 3 CA,C=LT");
+            n2 = new X509Name("2.5.4.5=8,O=,CN=ABC Class 3 CA,C=LT");
+
+            equalityTest(n1, n2);
+
+            //
+            // inequality to sequences
+            //
+            name1 = new X509Name("CN=The Legion");
+
+            if (name1.Equals(DerSequence.Empty))
+            {
+                Fail("inequality test with sequence");
+            }
+
+            if (name1.Equals(new DerSequence(DerSet.Empty)))
+            {
+                Fail("inequality test with sequence and set");
+            }
+
+            Asn1EncodableVector v = new Asn1EncodableVector(
+                new DerObjectIdentifier("1.1"),
+                new DerObjectIdentifier("1.1"));
+
+            if (name1.Equals(new DerSequence(new DerSet(new DerSet(v)))))
+            {
+                Fail("inequality test with sequence and bad set");
+            }
+
+//			if (name1.Equals(new DerSequence(new DerSet(new DerSet(v))), true))
+//			{
+//				Fail("inequality test with sequence and bad set");
+//			}
+            try
+            {
+                X509Name.GetInstance(new DerSequence(new DerSet(new DerSet(v))));
+                Fail("GetInstance should reject bad sequence");
+            }
+            catch (ArgumentException)
+            {
+                //expected
+            }
+
+            if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty))))
+            {
+                Fail("inequality test with sequence and short sequence");
+            }
+
+//			if (name1.Equals(new DerSequence(new DerSet(DerSequence.Empty)), true))
+//			{
+//				Fail("inequality test with sequence and short sequence");
+//			}
+            try
+            {
+                X509Name.GetInstance(new DerSequence(new DerSet(DerSequence.Empty)));
+                Fail("GetInstance should reject short sequence");
+            }
+            catch (ArgumentException)
+            {
+                //expected
+            }
+
+            v = new Asn1EncodableVector(
+                new DerObjectIdentifier("1.1"),
+                DerSequence.Empty);
+
+            if (name1.Equals(new DerSequence(new DerSet(new DerSequence(v)))))
+            {
+                Fail("inequality test with sequence and bad sequence");
+            }
+
+            if (name1.Equivalent(null))
+            {
+                Fail("inequality test with null");
+            }
+
+            if (name1.Equivalent(null, true))
+            {
+                Fail("inequality test with null");
+            }
+
+            //
+            // this is contrived but it checks sorting of sets with equal elements
+            //
+            unsorted = new X509Name("CN=AA + CN=AA + CN=AA");
+
+            //
+            // tagging test - only works if CHOICE implemented
+            //
+            /*
+            ASN1TaggedObject tag = new DERTaggedObject(false, 1, new X509Name("CN=AA"));
+
+            if (!tag.isExplicit())
+            {
+                Fail("failed to explicitly tag CHOICE object");
+            }
+
+            X509Name name = X509Name.getInstance(tag, false);
+
+            if (!name.equals(new X509Name("CN=AA")))
+            {
+                Fail("failed to recover tagged name");
+            }
+            */
+
+            DerUtf8String testString = new DerUtf8String("The Legion of the Bouncy Castle");
+            byte[] encodedBytes = testString.GetEncoded();
+            string hexEncodedString = "#" + Hex.ToHexString(encodedBytes);
+
+            DerUtf8String converted = (DerUtf8String)
+                new X509DefaultEntryConverter().GetConvertedValue(
+                X509Name.L , hexEncodedString);
+
+            if (!converted.Equals(testString))
+            {
+                Fail("Failed X509DefaultEntryConverter test");
+            }
+
+            //
+            // try escaped.
+            //
+            converted = (DerUtf8String) new X509DefaultEntryConverter().GetConvertedValue(
+                X509Name.L , "\\" + hexEncodedString);
+
+            if (!converted.Equals(new DerUtf8String(hexEncodedString)))
+            {
+                Fail("Failed X509DefaultEntryConverter test got " + converted + " expected: " + hexEncodedString);
+            }
+
+            //
+            // try a weird value
+            //
+            X509Name n = new X509Name("CN=\\#nothex#string");
+
+            if (!n.ToString().Equals("CN=\\#nothex#string"))
+            {
+                Fail("# string not properly escaped.");
+            }
+
+            IList vls = n.GetValueList(X509Name.CN);
+            if (vls.Count != 1 || !vls[0].Equals("#nothex#string"))
+            {
+                Fail("Escaped # not reduced properly");
+            }
+
+            n = new X509Name("CN=\"a+b\"");
+
+            vls = n.GetValueList(X509Name.CN);
+            if (vls.Count != 1 || !vls[0].Equals("a+b"))
+            {
+                Fail("Escaped + not reduced properly");
+            }
+
+            n = new X509Name("CN=a\\+b");
+
+            vls = n.GetValueList(X509Name.CN);
+            if (vls.Count != 1 || !vls[0].Equals("a+b"))
+            {
+                Fail("Escaped + not reduced properly");
+            }
+
+            if (!n.ToString().Equals("CN=a\\+b"))
+            {
+                Fail("+ in string not properly escaped.");
+            }
+
+            n = new X509Name("CN=a\\=b");
+
+            vls = n.GetValueList(X509Name.CN);
+            if (vls.Count != 1 || !vls[0].Equals("a=b"))
+            {
+                Fail("Escaped = not reduced properly");
+            }
+
+            if (!n.ToString().Equals("CN=a\\=b"))
+            {
+                Fail("= in string not properly escaped.");
+            }
+
+            n = new X509Name("TELEPHONENUMBER=\"+61999999999\"");
+
+            vls = n.GetValueList(X509Name.TelephoneNumber);
+            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
+            {
+                Fail("telephonenumber escaped + not reduced properly");
+            }
+
+            n = new X509Name("TELEPHONENUMBER=\\+61999999999");
+
+            vls = n.GetValueList(X509Name.TelephoneNumber);
+            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
+            {
+                Fail("telephonenumber escaped + not reduced properly");
+            }
+
+            n = new X509Name(@"TELEPHONENUMBER=\+61999999999");
+
+            vls = n.GetValueList(X509Name.TelephoneNumber);
+            if (vls.Count != 1 || !vls[0].Equals("+61999999999"))
+            {
+                Fail("telephonenumber escaped + not reduced properly");
+            }
+        }
+
+        private void compositeTest()
+        {
+            //
+            // composite test
+            //
+            byte[] enc = Hex.Decode("305e310b300906035504061302415531283026060355040a0c1f546865204c6567696f6e206f662074686520426f756e637920436173746c653125301006035504070c094d656c626f75726e653011060355040b0c0a4173636f742056616c65");
+            X509Name n = X509Name.GetInstance(Asn1Object.FromByteArray(enc));
+
+            if (!n.ToString().Equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+            {
+                Fail("Failed composite to string test got: " + n.ToString());
+            }
+
+            IDictionary symbols = X509Name.DefaultSymbols;
+            if (!n.ToString(true, symbols).Equals("L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU"))
+            {
+                Fail("Failed composite to string test got: " + n.ToString(true, symbols));
+            }
+
+            n = new X509Name(true, "L=Melbourne+OU=Ascot Vale,O=The Legion of the Bouncy Castle,C=AU");
+            if (!n.ToString().Equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne+OU=Ascot Vale"))
+            {
+                Fail("Failed composite to string reversal test got: " + n.ToString());
+            }
+
+            n = new X509Name("C=AU, O=The Legion of the Bouncy Castle, L=Melbourne + OU=Ascot Vale");
+
+            MemoryStream bOut = new MemoryStream();
+            Asn1OutputStream aOut = new Asn1OutputStream(bOut);
+
+            aOut.WriteObject(n);
+
+            byte[] enc2 = bOut.ToArray();
+
+            if (!Arrays.AreEqual(enc, enc2))
+            {
+                Fail("Failed composite string to encoding test");
+            }
+
+            //
+            // dud name test - handle empty DN without barfing.
+            //
+            n = new X509Name("C=CH,O=,OU=dummy,CN=mail at dummy.com");
+
+            n = X509Name.GetInstance(Asn1Object.FromByteArray(n.GetEncoded()));
+        }
+
+        private void equalityTest(
+            X509Name	x509Name,
+            X509Name	x509Name1)
+        {
+            if (!x509Name.Equivalent(x509Name1))
+            {
+                Fail("equality test failed for " + x509Name + " : " + x509Name1);
+            }
+
+            // FIXME Sort out X509Name hashcode problem
+//			if (x509Name.GetHashCode() != x509Name1.GetHashCode())
+//			{
+//				Fail("GetHashCode test failed for " + x509Name + " : " + x509Name1);
+//			}
+
+            if (!x509Name.Equivalent(x509Name1, true))
+            {
+                Fail("equality test failed for " + x509Name + " : " + x509Name1);
+            }
+        }
+
+        private bool CompareVectors(
+            IList	one,
+            IList	two)
+        {
+            if (one.Count != two.Count)
+                return false;
+
+            for (int i = 0; i < one.Count; ++i)
+            {
+                if (!one[i].Equals(two[i]))
+                    return false;
+            }
+
+            return true;
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new X509NameTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/asn1/test/X9Test.cs b/BouncyCastle.AxCrypt/test/src/asn1/test/X9Test.cs
new file mode 100644
index 0000000..e310811
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/asn1/test/X9Test.cs
@@ -0,0 +1,168 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Asn1.Tests
+{
+    [TestFixture]
+    public class X9Test
+        : SimpleTest
+    {
+        private static readonly byte[] namedPub = Base64.Decode("MDcwEwYHKoZIzj0CAQYIKoZIzj0DAQEDIAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
+        private static readonly byte[] expPub = Base64.Decode(
+              "MIH8MIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4AAAA"
+            + "AAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZUsfTL"
+            + "A9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks/PAF"
+            + "yUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVECAQED"
+            + "IAADG5xRI+Iki/JrvL20hoDUa7Cggzorv5B9yyqSMjYu");
+
+        private static readonly byte[] namedPriv = Base64.Decode("MCICAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQEECDAGAgEBBAEK");
+        private static readonly byte[] expPriv = Base64.Decode(
+              "MIHnAgEAMIHXBgcqhkjOPQIBMIHLAgEBMCkGByqGSM49AQECHn///////////////3///////4"
+            + "AAAAAAAH///////zBXBB5///////////////9///////+AAAAAAAB///////wEHiVXBfoqMGZU"
+            + "sfTLA9anUKMMJQEC1JiHF9m6FattPgMVAH1zdBaP/jRxtgqFdoahlHXTv6L/BB8DZ2iujhi7ks"
+            + "/PAFyUmqLG2UhT0OZgu/hUsclQX+laAh5///////////////9///+XXetBs6YFfDxDIUZSZVEC"
+            + "AQEECDAGAgEBBAEU");
+
+        private void EncodePublicKey()
+        {
+            X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3);
+
+            if (X9IntegerConverter.GetByteLength(ecP.Curve) != 30)
+            {
+                Fail("wrong byte length reported for curve");
+            }
+
+            if (ecP.Curve.FieldSize != 239)
+            {
+                Fail("wrong field size reported for curve");
+            }
+
+            //
+            // named curve
+            //
+            X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1);
+            ECPoint point = ecP.G.Multiply(BigInteger.ValueOf(100));
+
+            DerOctetString p = new DerOctetString(point.GetEncoded(true));
+
+            SubjectPublicKeyInfo info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), p.GetOctets());
+            if (!Arrays.AreEqual(info.GetEncoded(), namedPub))
+            {
+                Fail("failed public named generation");
+            }
+
+            X9ECPoint x9P = new X9ECPoint(ecP.Curve, p);
+
+            if (!Arrays.AreEqual(p.GetOctets(), x9P.Point.GetEncoded()))
+            {
+                Fail("point encoding not preserved");
+            }
+
+            Asn1Object o = Asn1Object.FromByteArray(namedPub);
+
+            if (!info.Equals(o))
+            {
+                Fail("failed public named equality");
+            }
+
+            //
+            // explicit curve parameters
+            //
+            _params = new X962Parameters(ecP);
+
+            info = new SubjectPublicKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), p.GetOctets());
+
+            if (!Arrays.AreEqual(info.GetEncoded(), expPub))
+            {
+                Fail("failed public explicit generation");
+            }
+
+            o = Asn1Object.FromByteArray(expPub);
+
+            if (!info.Equals(o))
+            {
+                Fail("failed public explicit equality");
+            }
+        }
+
+        private void EncodePrivateKey()
+        {
+            X9ECParameters ecP = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v3);
+
+            //
+            // named curve
+            //
+            X962Parameters _params = new X962Parameters(X9ObjectIdentifiers.Prime192v1);
+
+            PrivateKeyInfo info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.Ten).ToAsn1Object());
+
+            if (!Arrays.AreEqual(info.GetEncoded(), namedPriv))
+            {
+                Fail("failed private named generation");
+            }
+
+            Asn1Object o = Asn1Object.FromByteArray(namedPriv);
+
+            if (!info.Equals(o))
+            {
+                Fail("failed private named equality");
+            }
+
+            //
+            // explicit curve parameters
+            //
+            _params = new X962Parameters(ecP);
+
+            info = new PrivateKeyInfo(new AlgorithmIdentifier(X9ObjectIdentifiers.IdECPublicKey, _params), new ECPrivateKeyStructure(BigInteger.ValueOf(20)).ToAsn1Object());
+
+            if (!Arrays.AreEqual(info.GetEncoded(), expPriv))
+            {
+                Fail("failed private explicit generation");
+            }
+
+            o = Asn1Object.FromByteArray(expPriv);
+
+            if (!info.Equals(o))
+            {
+                Fail("failed private explicit equality");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            EncodePublicKey();
+            EncodePrivateKey();
+        }
+
+        public override string Name
+        {
+            get { return "X9"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new X9Test());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/cms/test/AllTests.cs
new file mode 100644
index 0000000..1b1e694
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/AllTests.cs
@@ -0,0 +1,37 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+    public class AllTests
+    {
+        public static void Main(
+			string[] args)
+        {
+            //junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            suite().Run(el);
+        }
+
+		public static TestSuite suite()
+        {
+            TestSuite suite = new TestSuite("CMS Tests");
+
+			suite.Add(new CompressedDataTest());
+            suite.Add(new CompressedDataStreamTest());
+			suite.Add(new EnvelopedDataTest());
+			suite.Add(new EnvelopedDataStreamTest());
+			suite.Add(new Rfc4134Test());
+			suite.Add(new SignedDataTest());
+			suite.Add(new SignedDataStreamTest());
+
+			return suite;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataStreamTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataStreamTest.cs
new file mode 100644
index 0000000..89a2174
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataStreamTest.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class AuthenticatedDataStreamTest
+	{
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair signKP;
+//		private static X509Certificate signCert;
+		//signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN);
+
+//		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+
+//		private static AsymmetricCipherKeyPair origKP;
+		//origKP = CmsTestUtil.MakeKeyPair();
+//		private static X509Certificate origCert;
+		//origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN);
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair reciKP;
+		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origECKP;
+		private static AsymmetricCipherKeyPair reciECKP;
+		private static X509Certificate reciECCert;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciKP
+		{
+			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+		}
+
+		private static X509Certificate ReciCert
+		{
+			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+		}
+
+		private static AsymmetricCipherKeyPair OrigECKP
+		{
+			get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciECKP
+		{
+			get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; }
+		}
+
+		private static X509Certificate ReciECCert
+		{
+			get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; }
+		}
+
+		[Test]
+		public void TestKeyTransDESede()
+		{
+			tryKeyTrans(CmsAuthenticatedDataGenerator.DesEde3Cbc);
+		}
+
+		private void tryKeyTrans(
+			string macAlg)
+		{
+			byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna");
+
+			CmsAuthenticatedDataStreamGenerator adGen = new CmsAuthenticatedDataStreamGenerator();
+
+			adGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream bOut = new MemoryStream();
+			Stream aOut = adGen.Open(bOut, macAlg);
+			aOut.Write(data, 0, data.Length);
+			aOut.Close();
+
+			CmsAuthenticatedDataParser ad = new CmsAuthenticatedDataParser(bOut.ToArray());
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(ad.MacAlgOid, macAlg);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataTest.cs
new file mode 100644
index 0000000..0ad34a9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/AuthenticatedDataTest.cs
@@ -0,0 +1,320 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class AuthenticatedDataTest
+	{
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair signKP;
+//		private static X509Certificate signCert;
+		//signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN);
+
+//		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+
+//		private static AsymmetricCipherKeyPair origKP;
+		//origKP = CmsTestUtil.MakeKeyPair();
+//		private static X509Certificate origCert;
+		//origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN);
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair reciKP;
+		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origECKP;
+		private static AsymmetricCipherKeyPair reciECKP;
+		private static X509Certificate reciECCert;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciKP
+		{
+			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+		}
+
+		private static X509Certificate ReciCert
+		{
+			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+		}
+
+		private static AsymmetricCipherKeyPair OrigECKP
+		{
+			get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciECKP
+		{
+			get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; }
+		}
+
+		private static X509Certificate ReciECCert
+		{
+			get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; }
+		}
+		
+//		private static string          _signDN;
+//		private static KeyPair _signKP;
+//		private static X509Certificate _signCert;
+//	
+//		private static string          _origDN;
+//		private static KeyPair         _origKP;
+//		private static X509Certificate _origCert;
+//	
+//		private static string          _reciDN;
+//		private static KeyPair         _reciKP;
+//		private static X509Certificate _reciCert;
+//	
+//		private static KeyPair         _origEcKP;
+//		private static KeyPair         _reciEcKP;
+//		private static X509Certificate _reciEcCert;
+//	
+//		private static bool         _initialised = false;
+//	
+//		public bool DEBUG = true;
+//	
+//		private static void init()
+//		{
+//			if (!_initialised)
+//			{
+//			_initialised = true;
+//			
+//			_signDN   = "O=Bouncy Castle, C=AU";
+//			_signKP   = CmsTestUtil.makeKeyPair();
+//			_signCert = CmsTestUtil.makeCertificate(_signKP, _signDN, _signKP, _signDN);
+//			
+//			_origDN   = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+//			_origKP   = CmsTestUtil.makeKeyPair();
+//			_origCert = CmsTestUtil.makeCertificate(_origKP, _origDN, _signKP, _signDN);
+//			
+//			_reciDN   = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+//			_reciKP   = CmsTestUtil.makeKeyPair();
+//			_reciCert = CmsTestUtil.makeCertificate(_reciKP, _reciDN, _signKP, _signDN);
+//			
+//			_origEcKP = CmsTestUtil.makeEcDsaKeyPair();
+//			_reciEcKP = CmsTestUtil.makeEcDsaKeyPair();
+//			_reciEcCert = CmsTestUtil.makeCertificate(_reciEcKP, _reciDN, _signKP, _signDN);
+//			}
+//		}
+//	
+//		public void setUp()
+//		{
+//			init();
+//		}
+//		
+//		public AuthenticatedDataTest(string name)
+//		{
+//		super(name);
+//		}
+//		
+//		public static void main(string args[])
+//		{
+//		junit.textui.TestRunner.run(AuthenticatedDataTest.class);
+//		}
+//		
+//		public static Test suite()
+//		throws Exception
+//		{
+//		init();
+//		
+//		return new CMSTestSetup(new TestSuite(AuthenticatedDataTest.class));
+//		}
+
+		[Test]
+		public void TestKeyTransDESede()
+		{
+			tryKeyTrans(CmsAuthenticatedDataGenerator.DesEde3Cbc);
+		}
+		
+		[Test]
+		public void TestKEKDESede()
+		{
+			tryKekAlgorithm(CmsTestUtil.MakeDesEde192Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
+		}
+		
+		[Test]
+		public void TestPasswordAES256()
+		{
+			passwordTest(CmsAuthenticatedDataGenerator.Aes256Cbc);
+		}
+		
+		[Test]
+		public void TestECKeyAgree()
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator();
+
+			adGen.AddKeyAgreementRecipient(CmsAuthenticatedDataGenerator.ECDHSha1Kdf, OrigECKP.Private, OrigECKP.Public, ReciECCert, CmsAuthenticatedDataGenerator.Aes128Wrap);
+
+			CmsAuthenticatedData ad = adGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsAuthenticatedDataGenerator.DesEde3Cbc);
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(ReciECKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+		
+		[Test]
+		public void TestEncoding()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna");
+
+			CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator();
+
+			adGen.AddKeyTransRecipient(ReciCert);
+
+			CmsAuthenticatedData ad = adGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsAuthenticatedDataGenerator.DesEde3Cbc);
+
+			ad = new CmsAuthenticatedData(ad.GetEncoded());
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+
+		private void tryKeyTrans(string macAlg)
+		{
+			byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna");
+
+			CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator();
+
+			adGen.AddKeyTransRecipient(ReciCert);
+
+			CmsAuthenticatedData ad = adGen.Generate(
+				new CmsProcessableByteArray(data),
+				macAlg);
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(ad.MacAlgOid, macAlg);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+		
+		private void tryKekAlgorithm(KeyParameter kek, DerObjectIdentifier algOid)
+		{
+			byte[] data = Encoding.ASCII.GetBytes("Eric H. Echidna");
+
+			CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator();
+
+			byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
+
+			// FIXME Will this work for macs?
+			string keyAlgorithm = ParameterUtilities.GetCanonicalAlgorithmName(algOid.Id);
+
+			adGen.AddKekRecipient(keyAlgorithm, kek, kekId);
+
+			CmsAuthenticatedData ad = adGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsAuthenticatedDataGenerator.DesEde3Cbc);
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, algOid.Id);
+
+				byte[] recData = recipient.GetContent(kek);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+		
+		private void passwordTest(string algorithm)
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsAuthenticatedDataGenerator adGen = new CmsAuthenticatedDataGenerator();
+
+			adGen.AddPasswordRecipient(new Pkcs5Scheme2PbeKey("password".ToCharArray(), new byte[20], 5), algorithm);
+		
+			CmsAuthenticatedData ad = adGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsAuthenticatedDataGenerator.DesEde3Cbc);
+
+			RecipientInformationStore recipients = ad.GetRecipientInfos();
+
+			Assert.AreEqual(CmsAuthenticatedDataGenerator.DesEde3Cbc, ad.MacAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (PasswordRecipientInformation recipient in c)
+			{
+				CmsPbeKey key = new Pkcs5Scheme2PbeKey("password".ToCharArray(), recipient.KeyDerivationAlgorithm);
+
+				byte[] recData = recipient.GetContent(key);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+				Assert.IsTrue(Arrays.AreEqual(ad.GetMac(), recipient.GetMac()));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/CMSSampleMessages.cs b/BouncyCastle.AxCrypt/test/src/cms/test/CMSSampleMessages.cs
new file mode 100644
index 0000000..ae4f60f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/CMSSampleMessages.cs
@@ -0,0 +1,147 @@
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	internal class CmsSampleMessages
+	{
+		internal static readonly byte[] originatorMessage = Base64.Decode(
+			  "MIIYGgYJKoZIhvcNAQcDoIIYCzCCGAcCAQKgggRJoIIERTCCBEEwggIpAgkA"
+			+ "xS/+IvjTL8YwDQYJKoZIhvcNAQEFBQAwaTELMAkGA1UEBhMCVVMxGDAWBgNV"
+			+ "BAoTD1UuUy4gR292ZXJubWVudDESMBAGA1UECxMJSFNQRDEyTGFiMQ8wDQYD"
+			+ "VQQLEwZBZ2VudHMxGzAZBgNVBAMTEkhTUEQxMiBMYWIgQ0EgUm9vdDAeFw0w"
+			+ "NzA1MTQxNzEzMzRaFw0wODA1MTMxNzEzMzRaMFwxCzAJBgNVBAYTAlVTMRgw"
+			+ "FgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxEjAQBgNVBAsTCUhTUEQxMkxhYjEP"
+			+ "MA0GA1UECxMGQWdlbnRzMQ4wDAYDVQQDEwV1c2VyMTCCASIwDQYJKoZIhvcN"
+			+ "AQEBBQADggEPADCCAQoCggEBALC54HvfpSE3yq/EkpNCkUEV6a6Df3q4k8EM"
+			+ "dlg0nQSf2FgYh1GMiztw8SVjrF80l4+Hg5/FW2XN2kpVQBap/H5ziPYXenbi"
+			+ "VLJHCF9LVyYDOS7xGfRtQ+ZhFUcECtaCLJsR7HIiFyKZWGg0c3bFZvFkdZqT"
+			+ "8MMwjhcIVE1BptMqcGriqqMQAUKYmOguAOzMCTGAOxqBXYFmR68WtggVNMMc"
+			+ "5qU6S/4OxeCmaNSPG5p7pA1o4Cnv4aJF1mAPedVPQpAS4Lu2K9nNhRkug0yd"
+			+ "6nPaxgQudk5YxlreNOPKiAHApk9RhGVepGchJCFP2aIPu9tkIiSe3omezSZu"
+			+ "Sy/3F5UCAwEAATANBgkqhkiG9w0BAQUFAAOCAgEAGDxqVI4aR4XNfbk2MtXF"
+			+ "agNYZOswn85X84um9gG323qjYhroW0QDuy3CwtUwhH866mpnJyhJvKx3b8UE"
+			+ "7pZInoNEz1UVn+wgJVXMmaG5mfp3X6z0xDAEaKmDMJXl66wlFGG1iveGgcEi"
+			+ "oMkrxFJKvu/FXywzPvz2pXD9LQapogOQpVsvg/hed//wijDG94UBkhbHTZ53"
+			+ "6ODKuHGmooO6bgqJxKcVyLwQAq/lXGtLqODK9BDicfUzuhLWA0si7Y1daehj"
+			+ "fjgAqFGirqRtPDdk1jywoMJdDCQqocNqNGuu/+9ZoRNtY7XFbiN7h4s4KTkw"
+			+ "YqCph8g+RZYJVZJDw/+qc5ymYZiufbImA08D7x7IzqX9eeuAqKCebkxcK0Dz"
+			+ "eh/wT7Ff8csw0xqkkEbi5sTORogPexKGo9T1P4j/UbOyCHaIwFQVE67kYJqZ"
+			+ "U3BB7mGNE/dKru7jC7Aadorpj7P/EQ8sfoq5wC9r3wfFB1f5znN9ZfXd3zSU"
+			+ "Gxne2PGl3Ry4DhrhWGy/HqB+StPSkLPJL1RNtKkywtaJG1QBnrMnLNsV7T0R"
+			+ "mIDn69NkDkc59LAuB7yxwBmhYA7c7cHckdX3bE7zgN6yYdiyLyXr+ZQl+3J8"
+			+ "bBPN/IVSs5Wr1kK9RDrFX8MdP95LZxHlgMATwAqoEPe5r2tvvGBoajoIA2Tw"
+			+ "71QxggGSMIIBjgIBADB2MGkxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMu"
+			+ "IEdvdmVybm1lbnQxEjAQBgNVBAsTCUhTUEQxMkxhYjEPMA0GA1UECxMGQWdl"
+			+ "bnRzMRswGQYDVQQDExJIU1BEMTIgTGFiIENBIFJvb3QCCQDFL/4i+NMvyTAN"
+			+ "BgkqhkiG9w0BAQEFAASCAQCGpoi8DBLf6I2fwqVp9MPA5M0QNRnC34AMoc7N"
+			+ "/JGKM5dWcGNpN83yL9QmOfjgyxzwJ3L3e3hYdoXp9MNelzG5ssyyKw4NxRgM"
+			+ "C1aRPWx1R1aKee/NAgvBjN3FyDN3Pl4ACz2EMrDMmilR0zmSJkDBVbGjxNzs"
+			+ "ZPxtsBlHeLRky/K/ZrTy5jIheFcKt/0dNJiMsFh+677OlRhDihdLzYeV4RK1"
+			+ "5Iy1j18ls5rJMYh1fmZOx9T6wvlpw84IjFHzUcIxIBg8t1cUkncXbg1r+rxm"
+			+ "zIaalAKdYp58oMpjy9wV6E1mxgAM/lvE/jwiYP4/a6TsXTLDPNIxe9RZVdhA"
+			+ "GCPvMIISHQYJKoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgQBLQIaeQQMYCCEfgv"
+			+ "FBzVKLnlRNCjs2JE/G8jBI8aduv6YQTYTt0ePh9JEHTmSi7ISbCDdAf5baKN"
+			+ "mzVGQJj87Srz3YyEmUcozxscWnWgVWpUbx0GJkjz6LqyGLQ3VnqUDG80xnXo"
+			+ "nQY5q4ko6avyMIDZ+zzI2fs9ChAlBjZ41Qb0FnwDPZBH3N43q+puVWesE4wj"
+			+ "LGftt63T4k2D/qMdg7fVfHkAsXPJIxkvR4vUrGEvxTl9e24146wYgCXe+66T"
+			+ "UcAMViNCMr8UiFQFQYSmuPcSTHgQHqEaBwYys6X+fe61yE16mUazs32yVH2v"
+			+ "Cyf1mG4/GAaSmqR/BIU7y7trGd+g/KaT1Kp76e+Rys9G/oakoeIH3Hkgdhmc"
+			+ "pFBPklIlgA57EocK5n84tFRv9n9cmsbOfy0EjEa6vU4ImMPZQS4iyhLCWD1u"
+			+ "tQziu5FyHSb9COveUPuGY2iTrOWG34rHIagNndXi1OuAIGQrLjbntHmogqxb"
+			+ "zkB+yojr+WBwY1efb8X+WQ2L+us9v31qNGA0wyfg4AC5FZur90rBxBq59UPz"
+			+ "JAVRD6NP5FRPdxuvHclDoGBoiMr9NXO3Uv0tJuYADHlWMQnUGoPEL7UxzuPJ"
+			+ "VAWuHpGiywzOcWMiFEiDSIZrv4RViIVIRhEtm2bO7Ta/AGTfvJcyb6ySexc1"
+			+ "aR5TWYOjqv1NaGAVQ1vPyqazH+g17y5wnBRj2c3nSMwksn/nC60e4ax+/yaE"
+			+ "Ls9Qou9a0L2IyQgDlvhBA4CcRGcHklhlzAovGBX2gWG31CK05doZhH7bRIrj"
+			+ "8h1XOF2izffrfWb6LcDcZptw5BQWT5XeyoKD4eNZfJ4ww+dMw4+0MkXPZEn6"
+			+ "Fqg+jam9ZioqXiw5Y6bdzxawefe6gvxeca3f53KDXEm4qFaVuDgyjNZhEmyB"
+			+ "gmsWRKokQ5DDlj1PfVlO4g2Uee4zbvmr7Yx6tGnnxm6o5i/COwvvRSXp8Oj7"
+			+ "Zej0ZA+1zenNRAGXwuTKrbQ9ZZYRi4LCXluuVmy8vocGm8bnuqulMyz5hsUi"
+			+ "QMAl1knunhaT+/kQOLRwEdJUgfq8ME14XsTNiVq26W8n+9AsYHoFzJhFoCfe"
+			+ "i2wngAs1MMnw1erfnhWibkFZDlG9/5OPBZ3ZzJfgMEdT5Fs+hJxrw7UqNMkb"
+			+ "EoH+3HpzEXfcGqCL6RfdbS0hu85v1CrZv0veK8qI+rQnoqXp+xmBRiSCyWNR"
+			+ "ITepXcJsi6vWYX0nvNNbBjTsFqi78BSVRpg/zOFRvw1gX1TtTXQLcEdalKgf"
+			+ "tEo+An3f3GugB3CFw38IM4JwCB06vXTRQAoK4PM4uNYVXEgSPq4vg9UuHZ3n"
+			+ "V5l96emGLK55N5FO6FvlHFft/7elEFglbnSzSQnzVyj36Z6P7x/Q3td5SY4J"
+			+ "VAJWvR/X4Fe2G6ebIZdNSJef9UyuNPee0Fi1iJUL8L4qO61ijkjYdE3bBcGm"
+			+ "61eWj8NgxtELVgRyXq1vNgMOFlVAwkf2ZNDgNRUM49UnIFTNKnTaeAVB9pW2"
+			+ "DGrZER8LA8ABctAdElECceoMVRUG1uFdAicrEbBHcWJkTdjBPjumE4bE6HUm"
+			+ "vbpNBC4wyoPS6CSvNut/re7I4wgZwho6C6GRUuwraxJZlS+jwEvC+F4Bzlf5"
+			+ "aPygECgVaNmSGP1E/vyN2aF8CLo4NL/5o9GG8DWg9O5GdNSislr4r6ciEjCr"
+			+ "0a6rk47QDn4rDQy8iu/YkZz9u8/GJCAinWQzAvV8byhZxc81CfKj9xYTclDX"
+			+ "AB75blJvUQIP4U7gpWxLB/1sdN2V5f9jw+xTLSpoJ7r/tIeBygF6rFe402Sd"
+			+ "840SLi8ZSufAVeHUoNNDYkA/c1b6k5FaxDtN22tYQi4y3Hs7k03mGhvvLC0l"
+			+ "05fMmvtasFaW5Bupqw8E2a7wHSLmRAXrPvnrblSL/wajptKPJWDJ+oH/9d9k"
+			+ "NkC4EFBpcMEfIDky4PoCtfKQBFa5LT1WDQGfcCnrC9SDfUfhfRLBOpoFmUaT"
+			+ "O0xc0vI/jmDRsoBy9d42ebyGMg5uD6tTOIvszEirpMy5SYPPa64zhHcN+Pzs"
+			+ "db+J6fthc3aVIoob9jdv/aRUH3gDwltSnaLUIc7CWcuHSCGyM/zQPiAzkw0z"
+			+ "x6ii5fdKXsmnQn88E+YqiJTPH0fG+kkhokAGU76bQMn7fJyBeVHhF2hqSr/0"
+			+ "4zCIjgq1Zb+d9sEuRZWF+/XsGl2gwk4vgHTwM+XfU7edQssUR6kyD6wkw7EU"
+			+ "6HaRrflymAHTEvdAB+PaREQbyej7/2lY41qmA9df2I5Izb60NxmMFj9F4M4V"
+			+ "bLJOVNX5fuc8vaIhPG82hIiqe05cnBfRhtmcUUb1WDHVH3klRkti+fHrnbAW"
+			+ "TpWd5m6Wi3VssopaUozWgYVgW9M+Zr5ZUAN9H0Kb4CatxG5YFkD0MCZShGl/"
+			+ "lSc1SUxho6YakBB+5HxCI853/sQ3RMgSrMk+8ftalM2+BrT+V9wMK2O+wM5W"
+			+ "ujrAcM85sQ4OqSZfJ7MmKT8+pcIsRRocmlM/cxUf5hKXfXrmCR5mkf9jxF8B"
+			+ "J1JOwhkD8zQP7sPUcOWEcT8ctOKPygtz6tWWQDW8ciiYULYyJA6ydGrrn6T+"
+			+ "fQj8M2VsM1y4YK9dMfJUeaiP+m4BeoOjs0vqz6pBI6J3lrNz31DaNO6SApUL"
+			+ "4cOx8EZMg498TG0zmQ87yVw4mGmL3JpWBZH89HiNEY5eJ0zEIS3lMaOADRMf"
+			+ "kX8B5YHadeTuAEjXsGtFIlSf1xo45kwCxIfUcikdfu2rb+Bh251Im0oq/XTj"
+			+ "XPeviXasfas6VsMHsmTrqynFdP8THnrmHLCoeAMvgpjirXfIdR7tULJcFJtr"
+			+ "0lZLZfdZgbTsbn9GMQKwMkAAjJLfJq42usvzf4ShC7IRtvOEVAMrebaaK1YF"
+			+ "rtV5z1WNo3VRFonakKj85nXLOAdCNe6T3zESebexJKFn8e/6+shp9IDIRmWr"
+			+ "hiWut6KPFiSgAgfqpeIt9fuHiYeIK8DqISA7QUdAZrgPe8GlctvKkQLvjNW0"
+			+ "srglx9CQuDqZC6C1BLaIs3sE//yLvEd06vDFjDa0WGKWjM/Uo29af/tlL1kC"
+			+ "vDQtDPi8OPIebK8OwI2uNDZ+cnHhv3gZXCdbKkRZc1W+mrU7rUk1Fa0ViVmc"
+			+ "zhVGX22fDXbIrs9zJ+sA+3Towrx2XmMZ+PDkVBxHFE2bk+GABM62BW9YZoX4"
+			+ "R4U+n7E8Ec0sI8srcxEZYX8LWHh1XSU0yEHYjkIWDQUUSGpsbgqnjXJcnTdk"
+			+ "KK5PLk4sthLYwT4o1Gg4lRpc4dn26bIQcpGdY5PEknItDt6IBSc6bYYYoQrl"
+			+ "PIufY67haoc//d5y1LpCi5vc0wTcvbdoVepLrxVAn4MPsejbfIFJ01N0qKgv"
+			+ "fGWVxmRGtGXHe3iNLsMrvSE2FkORSc4sgjC42hfxHTEVmhTnzOplxTsN/MzE"
+			+ "S7ESv/c0rIen+zwXgtiFnTg1VPHcaT4z0DtLBMNjqYNoyDrIHUrWguFeV7/i"
+			+ "RSP7SiztMmlfKhrxlQpaNNm/XvKa1OpKbVStHMgOdpMaaCp8WaX++wb9lG6V"
+			+ "3PqBeVSCuFm1xq6KAERLUdF4XsdXNM/uUhYZX7cGIqRS3vSDJB1EfrZTpUY5"
+			+ "xGllybE/P2gufnG5EMpC2FHx4iW4pWMkYhIpzKv1Tkxe3K6ISs4wEs4n/AtL"
+			+ "hupMGZE9hDJ0LV0nRvRbY8YCRXoBaj6/qF1QED7CG4hx16yrkLAR7Th5rbH7"
+			+ "GFEzNSq1HI0IssDIimD2ZN9Cf++uH6ZpP2JZeJ/gEqGi17ovtnuklx6dtu0l"
+			+ "KL0pQjCyAoQFEFSaVJ1m4oOQJyb58lsG4gOPaPvOw1ruiJ2obt4228VR1pA8"
+			+ "Vm9A41E4pk/vA+VFJ/tSmkB5s2gmBBVcA8mU8iIyzMmliTNHeg53EYAytF5M"
+			+ "X2rA7Ct8ApqbrYSSBTUPC+MEBV7UajamWB6UaSUj575MhEnzm0xl/lFqU6ZF"
+			+ "6w0rdey/KvTiotErOS1q8RcY2dcs9Mz8Dm/8IMBcGfny0i/KLtz0OUOLFg3P"
+			+ "/VrPBt7f+YfDqLVc8AujhrxAH/hwYauJ+Q6HSVTSJI7aXB9xtdsijzMZCmnE"
+			+ "1oKRBkACSWD9BGvS3hpv/VqaHWU4B2dnv2oyrIkdkgQu2OtlFxpcOkqwexIj"
+			+ "ssxxOCmT6dpB8JNehjLDU8WXhtFJVFuR84V7KlyeG/s8TaZgCW6uLLVmpteE"
+			+ "J15bnM9jRTW/FZiHwsjy9kVbvaAT+bbIjn5u7qdGsgAQHdeKy191ONvHIttZ"
+			+ "l/qnvrygLImaTOcuMMzU/0ECNlk0QiU0YbfS/RGH2LtRzk8x3FLFVXRiNtrD"
+			+ "uJuwzlP4RufuoZfJsi0rFOuxNFQ/cZEq1q7TCzqP+saRoSLFK1iRE/Ei06pS"
+			+ "JH+cwHMxk3u7k4+HxF72uK9XHIgY6G6WfZTklH2w2VrsLLZLmJ9SO6Zpyt48"
+			+ "KcwvEcxYoZxp1gfPYDCMHeb7oi/gRj9FjnBaNf2dW3a1RqVo5y0QeSfSH4k8"
+			+ "YWX6k+Yh803ZmoIb//TEbfkbXe8XOIffbMSUuIozCQY/Rt9wAHesMWfgTuB5"
+			+ "LSoa8R+mR5lIS/P1ANHdgNrh+XRFrNFeD0dCw6bdYWUXMVaZbCE8Z8pXQ0LO"
+			+ "ItiPuI+w/izD/lXdKXWJJmN/bq2RJRo4WFEDe6sJH9G2Poe/T4xwTm4kX2uA"
+			+ "IZkYy7bZcez8a0bFJzcsJxUbBPRq93J0fXzpvQsszbVZh94VSc9nkH4FnAxT"
+			+ "Kk2bLcsXANJlw3cFO9jOygrXh6R2fyHX0E8WExb2Q7lG68wU1BJVupT8rZ0Y"
+			+ "oRY6WBYG0LuZb+4VAQuI0/Are3BznsgkqudCjf+JUhu1Yefh2hblWuMPNEWb"
+			+ "mOorerNiIzkrt5tjXyBj0g8w/pL//BIlkW5JerMtKTPMfZSroHw9wuAuqHqF"
+			+ "2sMjsW/Lbr5b8SIdIgo3vrS6EM9MGkATfSZz4z+ZWG3EB6QqcMXCZ4N2/WWl"
+			+ "EPKsIqY/509NZRzqOavcMXkOryRJ7GQpmotNbbalI6r6swRoEQ2IzK5XPCC1"
+			+ "iv52YpcRaV9BDpNNByk4l3ddOiEc4dsOkHjaLNvj6Vo1pG/C1Z8VXRRY909D"
+			+ "nH2+PfUL684WZ6kIPeLfqr7N3ZbNxZAVozVG+WXwBlLFT7L+axeGHOhHdH/g"
+			+ "SVMSmWdRX4eNuofmpsU8f3A9aCnPGDxPnB4WKnAGw34TYZrtZ9mHcjYPsq1q"
+			+ "zY6brfZD4T7tktjAlRL2PYZ15MfWVXVH1xoyjeWImTi0o4nyuy/M0HukDfwY"
+			+ "l6nW77TMRiH54wdQqIZUxa32dNNhjcNslRlpOf6td3FbELqhTiaptRSuKjs9"
+			+ "8evbDFK7rb7n6RSSzAwb3oU8pwr4dM8ArTVc0EqnvdSCs1tx46ckIK3AFgcd"
+			+ "opmNq+Qa7qhN5Zgds3cLPIQiyDThhYGPaIgyn4j/dZb1Qwa2U7urijJrBqeS"
+			+ "/kJ2rEXV9v+OX9yTYKypM05A2gOK/ESPbx24C/HmmGm/yBXBx3pABvKt41Dh"
+			+ "b0syB4hYrsq0RriovGemBrNgy4tiJB5BDI9VpWFC/7LR0quFFOrxxm7YvH2h"
+			+ "GkR0oUc/socA80WZx9TegdiBg9TVPbe0gZmoeQc6XLfscBol0QdZWSmLqFxf"
+			+ "TFN7ksaVAUPXA9phBg/k51YmrwNvx4D/A1bBQRtQmq2N4R0j3uMkynubBEfb"
+			+ "9qvQNXpdygouzKUyrN/w+7clilaq2P+R9i7rriZ1waHyjfvAdeBzQQ/pVmgh"
+			+ "o8EiL/TZpIZ71sTYv28scY+V7yYgBA5S/Y4bdmvzSSoMoK8yH/LcBFJOZLQd"
+			+ "YPt7uKWSwQN8iVDA6ZcsYoKuAUw3ziiRaf+GN58ihLB/y/sGmAmX2XwLsPSZ"
+			+ "uQIF/gT8yXjxoyWDLXl3MUgfx+pGg5vBwAtk9a2elEQR9C3a8PPsOy3N9Jh3"
+			+ "xY/A1gJ/rjuubwrb0Sd2LinzPg5uVuKR1jeMSCEebgoyBj8/t8HvknBqJkpl"
+			+ "tjZ6AxGiQ8+v5jRBzYSyiTQfPMxWzdBKqUePdJcLPITf/XitegQnikgAN6bh"
+			+ "kYMS2G9kXJH2CgDm9z3svmu/0Oz2XWEpVHlOjknghPlTaLRqgWoQbK5dkuiV"
+			+ "k9HhGwwsgiR+");
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/CMSTestUtil.cs b/BouncyCastle.AxCrypt/test/src/cms/test/CMSTestUtil.cs
new file mode 100644
index 0000000..ef7f916
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/CMSTestUtil.cs
@@ -0,0 +1,480 @@
+using System;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	public class CmsTestUtil
+	{
+		public static SecureRandom rand;
+		private static IAsymmetricCipherKeyPairGenerator kpg;
+		private static IAsymmetricCipherKeyPairGenerator gostKpg;
+		private static IAsymmetricCipherKeyPairGenerator dsaKpg;
+		private static IAsymmetricCipherKeyPairGenerator ecGostKpg;
+		private static IAsymmetricCipherKeyPairGenerator ecDsaKpg;
+		public static CipherKeyGenerator aes192kg;
+		public static CipherKeyGenerator desede128kg;
+		public static CipherKeyGenerator desede192kg;
+		public static CipherKeyGenerator rc240kg;
+		public static CipherKeyGenerator rc264kg;
+		public static CipherKeyGenerator rc2128kg;
+		public static CipherKeyGenerator aesKg;
+		public static CipherKeyGenerator seedKg;
+		public static CipherKeyGenerator camelliaKg;
+		public static BigInteger serialNumber;
+
+		private static readonly byte[] attrCert = Base64.Decode(
+			  "MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2"
+			+ "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS"
+			+ "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2"
+			+ "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0"
+			+ "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn"
+			+ "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw"
+			+ "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY"
+			+ "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs"
+			+ "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K"
+			+ "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0"
+			+ "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j"
+			+ "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw"
+			+ "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg"
+			+ "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl"
+			+ "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt"
+			+ "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0"
+			+ "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8"
+			+ "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl"
+			+ "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ"
+			+ "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct"
+			+ "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3"
+			+ "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1"
+			+ "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy"
+			+ "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6"
+			+ "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov"
+			+ "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz"
+			+ "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0"
+			+ "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46"
+			+ "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+"
+			+ "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y"
+			+ "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv"
+			+ "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0"
+			+ "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph"
+			+ "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj"
+			+ "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+"
+			+ "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA"
+			+ "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr"
+			+ "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3"
+			+ "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv");
+
+		private static IAsymmetricCipherKeyPairGenerator Kpg
+		{
+			get
+			{
+				if (kpg == null)
+				{
+					kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+					kpg.Init(new RsaKeyGenerationParameters(
+						BigInteger.ValueOf(17), rand, 1024, 25));
+				}
+
+				return kpg;
+			}
+		}
+
+		private static IAsymmetricCipherKeyPairGenerator GostKpg
+		{
+			get
+			{
+				if (gostKpg == null)
+				{
+					gostKpg = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+					gostKpg.Init(
+						new Gost3410KeyGenerationParameters(
+							rand,
+							CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
+				}
+
+				return gostKpg;
+			}
+		}
+
+		private static IAsymmetricCipherKeyPairGenerator DsaKpg
+		{
+			get
+			{
+				if (dsaKpg == null)
+				{
+					DsaParameters dsaSpec = new DsaParameters(
+						new BigInteger("7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673"),
+						new BigInteger("1138656671590261728308283492178581223478058193247"),
+						new BigInteger("4182906737723181805517018315469082619513954319976782448649747742951189003482834321192692620856488639629011570381138542789803819092529658402611668375788410"));
+					dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+					dsaKpg.Init(new DsaKeyGenerationParameters(rand, dsaSpec));
+				}
+
+				return dsaKpg;
+			}
+		}
+
+		private static IAsymmetricCipherKeyPairGenerator ECGostKpg
+		{
+			get
+			{
+				if (ecGostKpg == null)
+				{
+					ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+					ecGostKpg.Init(
+						new ECKeyGenerationParameters(
+							CryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+							new SecureRandom()));
+				}
+
+				return ecGostKpg;
+			}
+		}
+
+		private static IAsymmetricCipherKeyPairGenerator ECDsaKpg
+		{
+			get
+			{
+				if (ecDsaKpg == null)
+				{
+					ecDsaKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+					ecDsaKpg.Init(new KeyGenerationParameters(rand, 239));
+				}
+
+				return ecDsaKpg;
+			}
+		}
+
+		static CmsTestUtil()
+		{
+		    try
+		    {
+		        rand = new SecureRandom();
+
+				aes192kg = GeneratorUtilities.GetKeyGenerator("AES");
+				aes192kg.Init(new KeyGenerationParameters(rand, 192));
+
+		        desede128kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
+				desede128kg.Init(new KeyGenerationParameters(rand, 112));
+
+				desede192kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
+				desede192kg.Init(new KeyGenerationParameters(rand, 168));
+
+				rc240kg = GeneratorUtilities.GetKeyGenerator("RC2");
+				rc240kg.Init(new KeyGenerationParameters(rand, 40));
+
+				rc264kg = GeneratorUtilities.GetKeyGenerator("RC2");
+				rc264kg.Init(new KeyGenerationParameters(rand, 64));
+
+				rc2128kg = GeneratorUtilities.GetKeyGenerator("RC2");
+				rc2128kg.Init(new KeyGenerationParameters(rand, 128));
+
+				aesKg = GeneratorUtilities.GetKeyGenerator("AES");
+
+				seedKg = GeneratorUtilities.GetKeyGenerator("SEED");
+
+				camelliaKg = GeneratorUtilities.GetKeyGenerator("Camellia");
+
+				serialNumber = BigInteger.One;
+		    }
+		    catch (Exception ex)
+		    {
+		        throw new Exception(ex.ToString());
+		    }
+		}
+
+		public static string DumpBase64(
+			byte[] data)
+		{
+			StringBuilder buf = new StringBuilder();
+
+			data = Base64.Encode(data);
+
+			for (int i = 0; i < data.Length; i += 64)
+			{
+				if (i + 64 < data.Length)
+				{
+					buf.Append(Encoding.Default.GetString(data, i, 64));
+				}
+				else
+				{
+					buf.Append(Encoding.Default.GetString(data, i, data.Length - i));
+				}
+				buf.Append('\n');
+			}
+
+			return buf.ToString();
+		}
+
+		public static IX509AttributeCertificate GetAttributeCertificate()
+		{
+//			X509StreamParser parser = X509StreamParser.GetInstance("AttributeCertificate");
+//			parser.Init(CmsTestUtil.attrCert);
+//			return (X509AttributeCertificate) parser.Read();
+
+			return new X509AttrCertParser().ReadAttrCert(attrCert);
+		}
+
+		public static AsymmetricCipherKeyPair MakeKeyPair()
+		{
+			return Kpg.GenerateKeyPair();
+		}
+
+		public static AsymmetricCipherKeyPair MakeGostKeyPair()
+		{
+			return GostKpg.GenerateKeyPair();
+		}
+
+		public static AsymmetricCipherKeyPair MakeDsaKeyPair()
+		{
+			return DsaKpg.GenerateKeyPair();
+		}
+
+		public static AsymmetricCipherKeyPair MakeECGostKeyPair()
+		{
+			return ECGostKpg.GenerateKeyPair();
+		}
+
+		public static AsymmetricCipherKeyPair MakeECDsaKeyPair()
+		{
+			return ECDsaKpg.GenerateKeyPair();
+		}
+
+		public static KeyParameter MakeDesEde128Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("DESEDE", desede128kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeAes192Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("AES", aes192kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeDesEde192Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("DESEDE", desede192kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC240Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("RC2", rc240kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC264Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("RC2", rc264kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC2128Key()
+		{
+			return ParameterUtilities.CreateKeyParameter("RC2", rc2128kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeSeedKey()
+		{
+			return ParameterUtilities.CreateKeyParameter("SEED", seedKg.GenerateKey());
+		}
+
+		public static KeyParameter MakeAesKey(
+			int keySize)
+		{
+			aesKg.Init(new KeyGenerationParameters(rand, keySize));
+
+			return ParameterUtilities.CreateKeyParameter("AES", aesKg.GenerateKey());
+		}
+
+		public static KeyParameter MakeCamelliaKey(
+			int keySize)
+		{
+			camelliaKg.Init(new KeyGenerationParameters(rand, keySize));
+
+			return ParameterUtilities.CreateKeyParameter("CAMELLIA", camelliaKg.GenerateKey());
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false);
+		}
+
+		public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true);
+		}
+
+		public static X509Certificate MakeV1Certificate(AsymmetricCipherKeyPair subKP,
+			string _subDN, AsymmetricCipherKeyPair issKP, string _issDN)
+		{
+			AsymmetricKeyParameter subPub = subKP.Public;
+			AsymmetricKeyParameter issPriv = issKP.Private;
+			AsymmetricKeyParameter issPub = issKP.Public;
+
+			X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
+
+			v1CertGen.Reset();
+			v1CertGen.SetSerialNumber(AllocateSerialNumber());
+			v1CertGen.SetIssuerDN(new X509Name(_issDN));
+			v1CertGen.SetNotBefore(DateTime.UtcNow);
+			v1CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100));
+			v1CertGen.SetSubjectDN(new X509Name(_subDN));
+			v1CertGen.SetPublicKey(subPub);
+
+			if (issPub is RsaKeyParameters)
+			{
+				v1CertGen.SetSignatureAlgorithm("SHA1WithRSA");
+			}
+			else if (issPub is DsaPublicKeyParameters)
+			{
+				v1CertGen.SetSignatureAlgorithm("SHA1withDSA");
+			}
+			else if (issPub is ECPublicKeyParameters)
+			{
+				ECPublicKeyParameters ecPub = (ECPublicKeyParameters)issPub;
+				if (ecPub.AlgorithmName == "ECGOST3410")
+				{
+					v1CertGen.SetSignatureAlgorithm("GOST3411withECGOST3410");
+				}
+				else
+				{
+					v1CertGen.SetSignatureAlgorithm("SHA1withECDSA");
+				}	
+			}
+			else
+			{
+				v1CertGen.SetSignatureAlgorithm("GOST3411WithGOST3410");
+			}
+
+			X509Certificate _cert = v1CertGen.Generate(issPriv);
+
+			_cert.CheckValidity(DateTime.UtcNow);
+			_cert.Verify(issPub);
+
+			return _cert;
+		}
+
+		public static X509Certificate MakeCertificate(
+			AsymmetricCipherKeyPair subKP, string _subDN,
+			AsymmetricCipherKeyPair issKP, string _issDN, bool _ca)
+		{
+			AsymmetricKeyParameter subPub = subKP.Public;
+			AsymmetricKeyParameter issPriv = issKP.Private;
+			AsymmetricKeyParameter issPub = issKP.Public;
+
+			X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
+
+			v3CertGen.Reset();
+			v3CertGen.SetSerialNumber(AllocateSerialNumber());
+			v3CertGen.SetIssuerDN(new X509Name(_issDN));
+			v3CertGen.SetNotBefore(DateTime.UtcNow);
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100));
+			v3CertGen.SetSubjectDN(new X509Name(_subDN));
+			v3CertGen.SetPublicKey(subPub);
+
+			if (issPub is RsaKeyParameters)
+			{
+				v3CertGen.SetSignatureAlgorithm("SHA1WithRSA");
+			}
+			else if (issPub is ECPublicKeyParameters)
+			{
+				ECPublicKeyParameters ecPub = (ECPublicKeyParameters) issPub;
+				if (ecPub.AlgorithmName == "ECGOST3410")
+				{
+					v3CertGen.SetSignatureAlgorithm("GOST3411withECGOST3410");
+				}
+				else
+				{
+					v3CertGen.SetSignatureAlgorithm("SHA1withECDSA");
+				}
+			}
+			else
+			{
+				v3CertGen.SetSignatureAlgorithm("GOST3411WithGOST3410");
+			}
+
+			v3CertGen.AddExtension(
+				X509Extensions.SubjectKeyIdentifier,
+				false,
+				CreateSubjectKeyId(subPub));
+
+			v3CertGen.AddExtension(
+				X509Extensions.AuthorityKeyIdentifier,
+				false,
+				CreateAuthorityKeyId(issPub));
+
+			v3CertGen.AddExtension(
+				X509Extensions.BasicConstraints,
+				false,
+				new BasicConstraints(_ca));
+
+			X509Certificate _cert = v3CertGen.Generate(issPriv);
+
+			_cert.CheckValidity();
+			_cert.Verify(issPub);
+
+			return _cert;
+		}
+
+		public static X509Crl MakeCrl(
+			AsymmetricCipherKeyPair pair)
+		{
+			X509V2CrlGenerator crlGen = new X509V2CrlGenerator();
+			DateTime now = DateTime.UtcNow;
+
+			crlGen.SetIssuerDN(new X509Name("CN=Test CA"));
+
+			crlGen.SetThisUpdate(now);
+			crlGen.SetNextUpdate(now.AddSeconds(100));
+			crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+			crlGen.AddCrlEntry(BigInteger.One, now, CrlReason.PrivilegeWithdrawn);
+
+			crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public));
+
+			return crlGen.Generate(pair.Private);
+		}
+
+		/*
+		*
+		*  INTERNAL METHODS
+		*
+		*/
+		private static AuthorityKeyIdentifier CreateAuthorityKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
+			return new AuthorityKeyIdentifier(_info);
+		}
+
+		internal static SubjectKeyIdentifier CreateSubjectKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
+			return new SubjectKeyIdentifier(_info);
+		}
+
+		private static BigInteger AllocateSerialNumber()
+		{
+			BigInteger _tmp = serialNumber;
+			serialNumber = serialNumber.Add(BigInteger.One);
+			return _tmp;
+		}
+
+		public static byte[] StreamToByteArray(
+			Stream inStream)
+		{
+			return Streams.ReadAll(inStream);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataStreamTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataStreamTest.cs
new file mode 100644
index 0000000..48a6c56
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataStreamTest.cs
@@ -0,0 +1,116 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class CompressedDataStreamTest
+	{
+		private static readonly byte[] compData = Base64.Decode(
+			  "MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
+			+ "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
+			+ "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
+			+ "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
+			+ "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
+			+ "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
+			+ "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
+			+ "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
+			+ "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
+			+ "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
+			+ "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
+
+		private static readonly byte[] uncompData = Base64.Decode(
+			  "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl"
+			+ "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l"
+			+ "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW"
+			+ "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj"
+			+ "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA"
+			+ "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0"
+			+ "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU"
+			+ "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz"
+			+ "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI"
+			+ "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD"
+			+ "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR"
+			+ "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk"
+			+ "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA"
+			+ "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq"
+			+ "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN"
+			+ "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD"
+			+ "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio"
+			+ "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx"
+			+ "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM"
+			+ "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi"
+			+ "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ"
+			+ "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq"
+			+ "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK"
+			+ "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj"
+			+ "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF"
+			+ "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB"
+			+ "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN"
+			+ "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU"
+			+ "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0=");
+
+		[Test]
+		public void TestWorkingData()
+		{
+			CmsCompressedDataParser ed = new CmsCompressedDataParser(compData);
+
+			Assert.IsTrue(Arrays.AreEqual(uncompData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream)));
+		}
+
+		[Test]
+		public void TestEach()
+		{
+			byte[] testData = Encoding.ASCII.GetBytes("Hello world!");
+
+			CmsCompressedDataStreamGenerator gen = new CmsCompressedDataStreamGenerator();
+			MemoryStream bOut = new MemoryStream();
+
+			Stream cOut = gen.Open(bOut, CmsCompressedDataStreamGenerator.ZLib);
+
+			cOut.Write(testData, 0, testData.Length);
+
+			cOut.Close();
+
+			CmsCompressedDataParser ed = new CmsCompressedDataParser(bOut.ToArray());
+
+			Assert.IsTrue(Arrays.AreEqual(testData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream)));
+		}
+
+		[Test]
+		public void Test1000()
+		{
+			byte[] testData = new byte[10000];
+			SecureRandom rand = new SecureRandom();
+
+			rand.SetSeed(0);
+
+			for (int i = 0; i != 10; i++)
+			{
+				CmsCompressedDataStreamGenerator gen = new CmsCompressedDataStreamGenerator();
+				MemoryStream bOut = new MemoryStream();
+
+				Stream cOut = gen.Open(bOut, CmsCompressedDataStreamGenerator.ZLib);
+
+				rand.NextBytes(testData);
+
+				cOut.Write(testData, 0, testData.Length);
+
+				cOut.Close();
+
+				CmsCompressedDataParser ed = new CmsCompressedDataParser(bOut.ToArray());
+
+				Assert.IsTrue(Arrays.AreEqual(testData, CmsTestUtil.StreamToByteArray(ed.GetContent().ContentStream)));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataTest.cs
new file mode 100644
index 0000000..6df85d9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/CompressedDataTest.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class CompressedDataTest
+	{
+		private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("Hello world!");
+
+		private static readonly byte[] compData = Base64.Decode(
+			  "MIAGCyqGSIb3DQEJEAEJoIAwgAIBADANBgsqhkiG9w0BCRADCDCABgkqhkiG9w0BBwGggCSABIIC"
+			+ "Hnic7ZRdb9owFIbvK/k/5PqVYPFXGK12YYyboVFASSp1vQtZGiLRACZE49/XHoUW7S/0tXP8Efux"
+			+ "fU5ivWnasml72XFb3gb5druui7ytN803M570nii7C5r8tfwR281hy/p/KSM3+jzH5s3+pbQ90xSb"
+			+ "P3VT3QbLusnt8WPIuN5vN/vaA2+DulnXTXkXvNTr8j8ouZmkCmGI/UW+ZS/C8zP0bz2dz0zwLt+1"
+			+ "UEk2M8mlaxjRMByAhZTj0RGYg4TvogiRASROsZgjpVcJCb1KV6QzQeDJ1XkoQ5Jm+C5PbOHZZGRi"
+			+ "v+ORAcshOGeCcdFJyfgFxdtCdEcmOrbinc/+BBMzRThEYpwl+jEBpciSGWQkI0TSlREmD/eOHb2D"
+			+ "SGLuESm/iKUFt1y4XHBO2a5oq0IKJKWLS9kUZTA7vC5LSxYmgVL46SIWxIfWBQd6AdrnjLmH94UT"
+			+ "vGxVibLqRCtIpp4g2qpdtqK1LiOeolpVK5wVQ5P7+QjZAlrh0cePYTx/gNZuB9Vhndtgujl9T/tg"
+			+ "W9ogK+3rnmg3YWygnTuF5GDS+Q/jIVLnCcYZFc6Kk/+c80wKwZjwdZIqDYWRH68MuBQSXLgXYXj2"
+			+ "3CAaYOBNJMliTl0X7eV5DnoKIFSKYdj3cRpD/cK/JWTHJRe76MUXnfBW8m7Hd5zhQ4ri2NrVF/WL"
+			+ "+kV1/3AGSlJ32bFPd2BsQD8uSzIx6lObkjdz95c0AAAAAAAAAAAAAAAA");
+
+		private static readonly byte[] uncompData = Base64.Decode(
+			  "Q29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9FREktWDEyOyBuYW1lPUdyb3VwMi54MTINCkNvbnRl"
+			+ "bnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJpbmFyeQ0KQ29udGVudC1EaXNwb3NpdGlvbjogaW5saW5l"
+			+ "OyBmaWxlbmFtZT1Hcm91cDIueDEyDQoNCklTQSowMCpzc3Nzc3Nzc3NzKjAwKnJycnJycnJycnIqW"
+			+ "loqQ1lDTE9ORSAgICAgICAgKlpaKlBBUlRORVIgICAgICAgICo5NjEwMDcqMjAxMypVKjAwMjAwKj"
+			+ "AwMDAwMDAwMSowKlQqKg1HUypQTypTMVMxUzFTMVMxUzFTMVMqUjFSMVIxUjFSMVIxUjFSKjk2MTA"
+			+ "wNyoyMDEzKjAwMDAwMDAwNCpYKjAwMzA1MA1TVCo4NTAqMDAwMDQwMDAxDUJFRyowMCpCRSoyYSo0"
+			+ "MzMyNDIzNHY1NTIzKjk2MTAwNyoyM3RjNHZ5MjR2MmgzdmgzdmgqWloqSUVMKjA5KlJFKjA5DUNVU"
+			+ "ioxMSpUUk4qNTY1Nio2NSo1NjYqSU1GKjAwNio5NjEwMDcNUkVGKjZBKjQzM3IxYzNyMzRyMzRjMz"
+			+ "MxMnFjdGdjNTQqUmVmZXJlbmNlIE51bWJlcg1QRVIqQUEqSGFucyBHdXR0ZW4qQ1AqMS4zMjIuMzI"
+			+ "zLjQ0NDQqKioqKnJnZzRlZ3Y0dDQNVEFYKjR0Z3RidDR0cjR0cipHTCpnaGdoKioqKioqKioqRypD"
+			+ "DUZPQipUUCpDQSpVU0EqMDIqRE9NKkNDKlJlZ3VsYXIgTG9jYXRpb25zIHBlciBUZXJtcw1DVFAqR"
+			+ "EUqQzA0KjQ1MyoyNTAwMCpEOSpTRUwqMjMyMTQqMjM0MzI0MjM0MjMqRVMqNDIyNDM0MjMNU0FDKk"
+			+ "EqQjAwMCpBRSozNTQ1KjM0NDIzMDANQ1VSKjExKjc2Nyo3NzY3KjY1DVBPMSoxMTEtYWFhKjEwMDA"
+			+ "wMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioq"
+			+ "KioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzN"
+			+ "HE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMD"
+			+ "AwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKio"
+			+ "qKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRx"
+			+ "NmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwM"
+			+ "CpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2ZjM1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKi"
+			+ "oqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkFTKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZ"
+			+ "mMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipBMSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAq"
+			+ "QVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzNTM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqK"
+			+ "kExKnl0cmgNUE8xKjExMS1hYWEqMTAwMDAwMCpBUyo5MC4wMCpCRCpBSyoyMzQyMzV2MzUzNHE2Zj"
+			+ "M1MzR2NDM1MzQ1M3ZxM3EzMioqKioqKioqKioqQTEqeXRyaA1QTzEqMTExLWFhYSoxMDAwMDAwKkF"
+			+ "TKjkwLjAwKkJEKkFLKjIzNDIzNXYzNTM0cTZmMzUzNHY0MzUzNDUzdnEzcTMyKioqKioqKioqKipB"
+			+ "MSp5dHJoDVBPMSoxMTEtYWFhKjEwMDAwMDAqQVMqOTAuMDAqQkQqQUsqMjM0MjM1djM1MzRxNmYzN"
+			+ "TM0djQzNTM0NTN2cTNxMzIqKioqKioqKioqKkExKnl0cmgNQ1RUKjENU0UqMjIqMDAwMDQwMDAxDU"
+			+ "dFKjEqMDAwMDAwMDA0DUlFQSoxKjAwMDAwMDAwMQ0=");
+
+		[Test]
+		public void TestWorkingData()
+		{
+			CmsCompressedData ed = new CmsCompressedData(compData);
+
+			Assert.IsTrue(Arrays.AreEqual(uncompData, ed.GetContent()));
+		}
+
+		[Test]
+		public void TestEach()
+		{
+			CmsCompressedData cd = GetStdData();
+
+			Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent()));
+		}
+
+		[Test]
+		public void TestLimitUnder()
+		{
+			CmsCompressedData cd = GetStdData();
+
+			try
+			{
+				cd.GetContent(TEST_DATA.Length / 2);
+			}
+			catch (CmsException e)
+			{
+				Assert.IsTrue(e.InnerException is StreamOverflowException);
+			}
+		}
+
+		[Test]
+		public void TestLimitOver()
+		{
+			CmsCompressedData cd = GetStdData();
+
+			Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent(TEST_DATA.Length * 2)));
+		}
+
+		[Test]
+		public void TestLimitEqual()
+		{
+			CmsCompressedData cd = GetStdData();
+
+			Assert.IsTrue(Arrays.AreEqual(TEST_DATA, cd.GetContent(TEST_DATA.Length)));
+		}
+
+		private CmsCompressedData GetStdData()
+		{
+			CmsProcessableByteArray testData = new CmsProcessableByteArray(TEST_DATA);
+			CmsCompressedDataGenerator gen = new CmsCompressedDataGenerator();
+			return gen.Generate(testData, CmsCompressedDataGenerator.ZLib);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataStreamTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataStreamTest.cs
new file mode 100644
index 0000000..8512f66
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataStreamTest.cs
@@ -0,0 +1,537 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class EnvelopedDataStreamTest
+	{
+		private const int BufferSize = 4000;
+
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair signKP;
+//		private static X509Certificate signCert;
+		//signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN);
+
+//		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+//		private static AsymmetricCipherKeyPair origKP;
+		//origKP   = CmsTestUtil.MakeKeyPair();
+//		private static X509Certificate origCert;
+		//origCert = CmsTestUtil.MakeCertificate(origKP, OrigDN, _signKP, SignDN);
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair reciKP;
+		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origECKP;
+		private static AsymmetricCipherKeyPair reciECKP;
+		private static X509Certificate reciECCert;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP   = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciKP
+		{
+			get { return reciKP == null ? (reciKP   = CmsTestUtil.MakeKeyPair()) : reciKP; }
+		}
+
+		private static X509Certificate ReciCert
+		{
+			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert;}
+		}
+
+		private static AsymmetricCipherKeyPair OrigECKP
+		{
+			get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciECKP
+		{
+			get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; }
+		}
+
+		private static X509Certificate ReciECCert
+		{
+			get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert;}
+		}
+
+		[Test]
+		public void TestWorkingData()
+		{
+			byte[] keyData = Base64.Decode(
+				"MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKrAz/SQKrcQ" +
+				"nj9IxHIfKDbuXsMqUpI06s2gps6fp7RDNvtUDDMOciWGFhD45YSy8GO0mPx3" +
+				"Nkc7vKBqX4TLcqLUz7kXGOHGOwiPZoNF+9jBMPNROe/B0My0PkWg9tuq+nxN" +
+				"64oD47+JvDwrpNOS5wsYavXeAW8Anv9ZzHLU7KwZAgMBAAECgYA/fqdVt+5K" +
+				"WKGfwr1Z+oAHvSf7xtchiw/tGtosZ24DOCNP3fcTXUHQ9kVqVkNyzt9ZFCT3" +
+				"bJUAdBQ2SpfuV4DusVeQZVzcROKeA09nPkxBpTefWbSDQGhb+eZq9L8JDRSW" +
+				"HyYqs+MBoUpLw7GKtZiJkZyY6CsYkAnQ+uYVWq/TIQJBAP5zafO4HUV/w4KD" +
+				"VJi+ua+GYF1Sg1t/dYL1kXO9GP1p75YAmtm6LdnOCas7wj70/G1YlPGkOP0V" +
+				"GFzeG5KAmAUCQQCryvKU9nwWA+kypcQT9Yr1P4vGS0APYoBThnZq7jEPc5Cm" +
+				"ZI82yseSxSeea0+8KQbZ5mvh1p3qImDLEH/iNSQFAkAghS+tboKPN10NeSt+" +
+				"uiGRRWNbiggv0YJ7Uldcq3ZeLQPp7/naiekCRUsHD4Qr97OrZf7jQ1HlRqTu" +
+				"eZScjMLhAkBNUMZCQnhwFAyEzdPkQ7LpU1MdyEopYmRssuxijZao5JLqQAGw" +
+				"YCzXokGFa7hz72b09F4DQurJL/WuDlvvu4jdAkEAxwT9lylvfSfEQw4/qQgZ" +
+				"MFB26gqB6Gqs1pHIZCzdliKx5BO3VDeUGfXMI8yOkbXoWbYx5xPid/+N8R//" +
+				"+sxLBw==");
+
+			byte[] envData = Base64.Decode(
+				"MIAGCSqGSIb3DQEHA6CAMIACAQAxgcQwgcECAQAwKjAlMRYwFAYDVQQKEw1C" +
+				"b3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVQIBHjANBgkqhkiG9w0BAQEFAASB" +
+				"gDmnaDZ0vDJNlaUSYyEXsgbaUH+itNTjCOgv77QTX2ImXj+kTctM19PQF2I1" +
+				"0/NL0fjakvCgBTHKmk13a7jqB6cX3bysenHNrglHsgNGgeXQ7ggAq5fV/JQQ" +
+				"T7rSxEtuwpbuHQnoVUZahOHVKy/a0uLr9iIh1A3y+yZTZaG505ZJMIAGCSqG" +
+				"SIb3DQEHATAdBglghkgBZQMEAQIEENmkYNbDXiZxJWtq82qIRZKggAQgkOGr" +
+				"1JcTsADStez1eY4+rO4DtyBIyUYQ3pilnbirfPkAAAAAAAAAAAAA");
+
+
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(envData);
+
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+//            PKCS8EncodedKeySpec	keySpec = new PKCS8EncodedKeySpec(keyData);
+//            KeyFactory			keyFact = KeyFactory.GetInstance("RSA");
+//            Key					priKey = keyFact.generatePrivate(keySpec);
+			AsymmetricKeyParameter priKey = PrivateKeyFactory.CreateKey(keyData);
+            byte[] data = Hex.Decode("57616c6c6157616c6c6157617368696e67746f6e");
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				CmsTypedStream recData = recipient.GetContentStream(priKey);
+
+				byte[] compare = CmsTestUtil.StreamToByteArray(recData.ContentStream);
+				Assert.IsTrue(Arrays.AreEqual(data, compare));
+			}
+		}
+
+		private void VerifyData(
+			byte[]	encodedBytes,
+			string	expectedOid,
+			byte[]	expectedData)
+		{
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(encodedBytes);
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, expectedOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(expectedData, CmsTestUtil.StreamToByteArray(
+					recData.ContentStream)));
+			}
+		}
+
+		[Test]
+		public void TestKeyTransAes128BufferedStream()
+		{
+			byte[] data = new byte[2000];
+			for (int i = 0; i != 2000; i++)
+			{
+				data[i] = (byte)(i & 0xff);
+			}
+
+			//
+			// unbuffered
+			//
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				outStream.WriteByte(data[i]);
+			}
+
+			outStream.Close();
+
+			VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data);
+
+			int unbufferedLength = bOut.ToArray().Length;
+
+			//
+			// Using buffered output - should be == to unbuffered
+			//
+			edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			bOut.SetLength(0);
+
+			outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			Streams.PipeAll(new MemoryStream(data, false), outStream);
+			outStream.Close();
+
+			VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data);
+
+			Assert.AreEqual(unbufferedLength, bOut.ToArray().Length);
+		}
+
+		[Test]
+		public void TestKeyTransAes128Buffered()
+		{
+			byte[] data = new byte[2000];
+			for (int i = 0; i != 2000; i++)
+			{
+				data[i] = (byte)(i & 0xff);
+			}
+
+			//
+			// unbuffered
+			//
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream  bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				outStream.WriteByte(data[i]);
+			}
+
+			outStream.Close();
+
+			VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data);
+
+			int unbufferedLength = bOut.ToArray().Length;
+
+			//
+			// buffered - less than default of 1000
+			//
+			edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.SetBufferSize(300);
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			bOut.SetLength(0);
+
+			outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				outStream.WriteByte(data[i]);
+			}
+
+			outStream.Close();
+
+			VerifyData(bOut.ToArray(), CmsEnvelopedDataGenerator.Aes128Cbc, data);
+
+			Assert.IsTrue(unbufferedLength < bOut.ToArray().Length);
+		}
+
+		[Test]
+		public void TestKeyTransAes128Der()
+		{
+			byte[] data = new byte[2000];
+			for (int i = 0; i != 2000; i++)
+			{
+				data[i] = (byte)(i & 0xff);
+			}
+
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				outStream.WriteByte(data[i]);
+			}
+
+			outStream.Close();
+
+			// convert to DER
+			byte[] derEncodedBytes = Asn1Object.FromByteArray(bOut.ToArray()).GetDerEncoded();
+
+			VerifyData(derEncodedBytes, CmsEnvelopedDataGenerator.Aes128Cbc, data);
+		}
+
+		[Test]
+		public void TestKeyTransAes128Throughput()
+		{
+			byte[] data = new byte[40001];
+			for (int i = 0; i != data.Length; i++)
+			{
+				data[i] = (byte)(i & 0xff);
+			}
+
+			//
+			// buffered
+			//
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.SetBufferSize(BufferSize);
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			for (int i = 0; i != data.Length; i++)
+			{
+				outStream.WriteByte(data[i]);
+			}
+
+			outStream.Close();
+
+			CmsEnvelopedDataParser		ep = new CmsEnvelopedDataParser(bOut.ToArray());
+			RecipientInformationStore	recipients = ep.GetRecipientInfos();
+			ICollection					c = recipients.GetRecipients();
+
+			IEnumerator e = c.GetEnumerator();
+
+			if (e.MoveNext())
+			{
+				RecipientInformation recipient = (RecipientInformation) e.Current;
+
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);
+
+				Stream dataStream = recData.ContentStream;
+				MemoryStream dataOut = new MemoryStream();
+				int len;
+				byte[] buf = new byte[BufferSize];
+				int count = 0;
+
+				while (count != 10 && (len = dataStream.Read(buf, 0, buf.Length)) > 0)
+				{
+					Assert.AreEqual(buf.Length, len);
+
+					dataOut.Write(buf, 0, buf.Length);
+					count++;
+				}
+
+				len = dataStream.Read(buf, 0, buf.Length);
+				dataOut.Write(buf, 0, len);
+
+				Assert.IsTrue(Arrays.AreEqual(data, dataOut.ToArray()));
+			}
+			else
+			{
+				Assert.Fail("recipient not found.");
+			}
+		}
+
+		[Test]
+		public void TestKeyTransAes128()
+		{
+			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");
+
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			outStream.Write(data, 0, data.Length);
+
+			outStream.Close();
+
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());
+
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				CmsTypedStream recData = recipient.GetContentStream(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
+			}
+
+			ep.Close();
+		}
+
+		[Test]
+		public void TestAesKek()
+		{
+			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");
+			KeyParameter kek = CmsTestUtil.MakeAes192Key();
+
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
+
+			edGen.AddKekRecipient("AES192", kek, kekId);
+
+			MemoryStream  bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut,
+				CmsEnvelopedDataGenerator.DesEde3Cbc);
+			outStream.Write(data, 0, data.Length);
+
+			outStream.Close();
+
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());
+
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25");
+
+				CmsTypedStream recData = recipient.GetContentStream(kek);
+
+				Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
+			}
+
+			ep.Close();
+		}
+
+		[Test]
+		public void TestTwoAesKek()
+		{
+			byte[] data = Encoding.Default.GetBytes("WallaWallaWashington");
+			KeyParameter kek1 = CmsTestUtil.MakeAes192Key();
+			KeyParameter kek2 = CmsTestUtil.MakeAes192Key();
+
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			byte[]  kekId1 = new byte[] { 1, 2, 3, 4, 5 };
+			byte[]  kekId2 = new byte[] { 5, 4, 3, 2, 1 };
+
+			edGen.AddKekRecipient("AES192", kek1, kekId1);
+			edGen.AddKekRecipient("AES192", kek2, kekId2);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStream = edGen.Open(
+				bOut,
+				CmsEnvelopedDataGenerator.DesEde3Cbc);
+			outStream.Write(data, 0, data.Length);
+
+			outStream.Close();
+
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());
+
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			RecipientID recSel = new RecipientID();
+
+			recSel.KeyIdentifier = kekId2;
+
+			RecipientInformation recipient = recipients.GetFirstRecipient(recSel);
+
+			Assert.AreEqual(recipient.KeyEncryptionAlgOid, "2.16.840.1.101.3.4.1.25");
+
+			CmsTypedStream recData = recipient.GetContentStream(kek2);
+
+			Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
+
+			ep.Close();
+		}
+
+		[Test]
+		public void TestECKeyAgree()
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataStreamGenerator edGen = new CmsEnvelopedDataStreamGenerator();
+
+			edGen.AddKeyAgreementRecipient(
+				CmsEnvelopedDataGenerator.ECDHSha1Kdf,
+				OrigECKP.Private,
+				OrigECKP.Public,
+				ReciECCert,
+				CmsEnvelopedDataGenerator.Aes128Wrap);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream outStr = edGen.Open(bOut, CmsEnvelopedDataGenerator.Aes128Cbc);
+			outStr.Write(data, 0, data.Length);
+
+			outStr.Close();
+
+			CmsEnvelopedDataParser ep = new CmsEnvelopedDataParser(bOut.ToArray());
+
+			RecipientInformationStore recipients = ep.GetRecipientInfos();
+
+			Assert.AreEqual(ep.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientID recSel = new RecipientID();
+
+//			recSel.SetIssuer(PrincipalUtilities.GetIssuerX509Principal(ReciECCert).GetEncoded());
+			recSel.Issuer = PrincipalUtilities.GetIssuerX509Principal(ReciECCert);
+			recSel.SerialNumber = ReciECCert.SerialNumber;
+
+			RecipientInformation recipient = recipients.GetFirstRecipient(recSel);
+
+			CmsTypedStream recData = recipient.GetContentStream(ReciECKP.Private);
+
+			Assert.IsTrue(Arrays.AreEqual(data, CmsTestUtil.StreamToByteArray(recData.ContentStream)));
+
+			ep.Close();
+		}
+
+		[Test]
+		public void TestOriginatorInfo()
+		{
+			CmsEnvelopedDataParser env = new CmsEnvelopedDataParser(CmsSampleMessages.originatorMessage);
+
+			env.GetRecipientInfos();
+
+			Assert.AreEqual(CmsEnvelopedDataGenerator.DesEde3Cbc, env.EncryptionAlgOid);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataTest.cs
new file mode 100644
index 0000000..be588ef
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/EnvelopedDataTest.cs
@@ -0,0 +1,866 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class EnvelopedDataTest
+	{
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair signKP;
+//		private static X509Certificate signCert;
+		//signCert = CmsTestUtil.MakeCertificate(_signKP, SignDN, _signKP, SignDN);
+
+//		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+
+//		private static AsymmetricCipherKeyPair origKP;
+		//origKP = CmsTestUtil.MakeKeyPair();
+//		private static X509Certificate origCert;
+		//origCert = CmsTestUtil.MakeCertificate(_origKP, OrigDN, _signKP, SignDN);
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+		private const string ReciDN2 = "CN=Fred, OU=Sales, O=Bouncy Castle, C=AU";
+
+		private static AsymmetricCipherKeyPair reciKP;
+		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origECKP;
+		private static AsymmetricCipherKeyPair reciECKP;
+		private static X509Certificate reciECCert;
+		private static AsymmetricCipherKeyPair reciECKP2;
+		private static X509Certificate reciECCert2;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciKP
+		{
+			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+		}
+
+		private static X509Certificate ReciCert
+		{
+			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+		}
+
+		private static AsymmetricCipherKeyPair OrigECKP
+		{
+			get { return origECKP == null ? (origECKP = CmsTestUtil.MakeECDsaKeyPair()) : origECKP; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciECKP
+		{
+			get { return reciECKP == null ? (reciECKP = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP; }
+		}
+
+		private static X509Certificate ReciECCert
+		{
+			get { return reciECCert == null ? (reciECCert = CmsTestUtil.MakeCertificate(ReciECKP, ReciDN, SignKP, SignDN)) : reciECCert; }
+		}
+
+		private static AsymmetricCipherKeyPair ReciECKP2
+		{
+			get { return reciECKP2 == null ? (reciECKP2 = CmsTestUtil.MakeECDsaKeyPair()) : reciECKP2; }
+		}
+
+		private static X509Certificate ReciECCert2
+		{
+			get { return reciECCert2 == null ? (reciECCert2 = CmsTestUtil.MakeCertificate(ReciECKP2, ReciDN2, SignKP, SignDN)) : reciECCert2; }
+		}
+
+		private static readonly byte[] oldKEK = Base64.Decode(
+			"MIAGCSqGSIb3DQEHA6CAMIACAQIxQaI/MD0CAQQwBwQFAQIDBAUwDQYJYIZIAWUDBAEFBQAEI"
+			+ "Fi2eHTPM4bQSjP4DUeDzJZLpfemW2gF1SPq7ZPHJi1mMIAGCSqGSIb3DQEHATAUBggqhkiG9w"
+			+ "0DBwQImtdGyUdGGt6ggAQYk9X9z01YFBkU7IlS3wmsKpm/zpZClTceAAAAAAAAAAAAAA==");
+
+		private static readonly byte[] ecKeyAgreeMsgAES256 = Base64.Decode(
+			"MIAGCSqGSIb3DQEHA6CAMIACAQIxgcShgcECAQOgQ6FBMAsGByqGSM49AgEF"
+			+ "AAMyAAPdXlSTpub+qqno9hUGkUDl+S3/ABhPziIB5yGU4678tgOgU5CiKG9Z"
+			+ "kfnabIJ3nZYwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBLQUAMFswWTAtMCgx"
+			+ "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBCi/"
+			+ "rJRLbFwEVW6PcLLmojjW9lI/xGD7CfZzXrqXFw8iHaf3hTRau1gYMIAGCSqG"
+			+ "SIb3DQEHATAdBglghkgBZQMEASoEEMtCnKKPwccmyrbgeSIlA3qggAQQDLw8"
+			+ "pNJR97bPpj6baG99bQQQwhEDsoj5Xg1oOxojHVcYzAAAAAAAAAAAAAA=");
+
+		private static readonly byte[] ecKeyAgreeMsgAES128 = Base64.Decode(
+			"MIAGCSqGSIb3DQEHA6CAMIACAQIxgbShgbECAQOgQ6FBMAsGByqGSM49AgEF"
+			+ "AAMyAAL01JLEgKvKh5rbxI/hOxs/9WEezMIsAbUaZM4l5tn3CzXAN505nr5d"
+			+ "LhrcurMK+tAwGgYJK4EFEIZIPwACMA0GCWCGSAFlAwQBBQUAMEswSTAtMCgx"
+			+ "EzARBgNVBAMTCkFkbWluLU1EU0UxETAPBgNVBAoTCDRCQ1QtMklEAgEBBBhi"
+			+ "FLjc5g6aqDT3f8LomljOwl1WTrplUT8wgAYJKoZIhvcNAQcBMB0GCWCGSAFl"
+			+ "AwQBAgQQzXjms16Y69S/rB0EbHqRMaCABBAFmc/QdVW6LTKdEy97kaZzBBBa"
+			+ "fQuviUS03NycpojELx0bAAAAAAAAAAAAAA==");
+
+		private static readonly byte[] ecKeyAgreeMsgDESEDE = Base64.Decode(
+			"MIAGCSqGSIb3DQEHA6CAMIACAQIxgcahgcMCAQOgQ6FBMAsGByqGSM49AgEF"
+			+ "AAMyAALIici6Nx1WN5f0ThH2A8ht9ovm0thpC5JK54t73E1RDzCifePaoQo0"
+			+ "xd6sUqoyGaYwHAYJK4EFEIZIPwACMA8GCyqGSIb3DQEJEAMGBQAwWzBZMC0w"
+			+ "KDETMBEGA1UEAxMKQWRtaW4tTURTRTERMA8GA1UEChMINEJDVC0ySUQCAQEE"
+			+ "KJuqZQ1NB1vXrKPOnb4TCpYOsdm6GscWdwAAZlm2EHMp444j0s55J9wwgAYJ"
+			+ "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAjwnsDMsafCrKCABBjyPvqFOVMKxxut"
+			+ "VfTx4fQlNGJN8S2ATRgECMcTQ/dsmeViAAAAAAAAAAAAAA==");
+
+		private static readonly byte[] ecMqvKeyAgreeMsgAes128 = Base64.Decode(
+			  "MIAGCSqGSIb3DQEHA6CAMIACAQIxgf2hgfoCAQOgQ6FBMAsGByqGSM49AgEF"
+			+ "AAMyAAPDKU+0H58tsjpoYmYCInMr/FayvCCkupebgsnpaGEB7qS9vzcNVUj6"
+			+ "mrnmiC2grpmhRwRFMEMwQTALBgcqhkjOPQIBBQADMgACZpD13z9c7DzRWx6S"
+			+ "0xdbq3S+EJ7vWO+YcHVjTD8NcQDcZcWASW899l1PkL936zsuMBoGCSuBBRCG"
+			+ "SD8AEDANBglghkgBZQMEAQUFADBLMEkwLTAoMRMwEQYDVQQDEwpBZG1pbi1N"
+			+ "RFNFMREwDwYDVQQKEwg0QkNULTJJRAIBAQQYFq58L71nyMK/70w3nc6zkkRy"
+			+ "RL7DHmpZMIAGCSqGSIb3DQEHATAdBglghkgBZQMEAQIEEDzRUpreBsZXWHBe"
+			+ "onxOtSmggAQQ7csAZXwT1lHUqoazoy8bhAQQq+9Zjj8iGdOWgyebbfj67QAA"
+			+ "AAAAAAAAAAA=");
+
+		private static readonly byte[] ecKeyAgreeKey = Base64.Decode(
+			"MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDC8vp7xVTbKSgYVU5Wc"
+			+ "hGkWbzaj+yUFETIWP1Dt7+WSpq3ikSPdl7PpHPqnPVZfoIWhZANiAgSYHTgxf+Dd"
+			+ "Tt84dUvuSKkFy3RhjxJmjwIscK6zbEUzKhcPQG2GHzXhWK5x1kov0I74XpGhVkya"
+			+ "ElH5K6SaOXiXAzcyNGggTOk4+ZFnz5Xl0pBje3zKxPhYu0SnCw7Pcqw=");
+
+		private static readonly byte[] bobPrivRsaEncrypt = Base64.Decode(
+			"MIIChQIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKnhZ5g/OdVf"
+			+ "8qCTQV6meYmFyDVdmpFb+x0B2hlwJhcPvaUi0DWFbXqYZhRBXM+3twg7CcmR"
+			+ "uBlpN235ZR572akzJKN/O7uvRgGGNjQyywcDWVL8hYsxBLjMGAgUSOZPHPtd"
+			+ "YMTgXB9T039T2GkB8QX4enDRvoPGXzjPHCyqaqfrAgMBAAECgYBnzUhMmg2P"
+			+ "mMIbZf8ig5xt8KYGHbztpwOIlPIcaw+LNd4Ogngwy+e6alatd8brUXlweQqg"
+			+ "9P5F4Kmy9Bnah5jWMIR05PxZbMHGd9ypkdB8MKCixQheIXFD/A0HPfD6bRSe"
+			+ "TmPwF1h5HEuYHD09sBvf+iU7o8AsmAX2EAnYh9sDGQJBANDDIsbeopkYdo+N"
+			+ "vKZ11mY/1I1FUox29XLE6/BGmvE+XKpVC5va3Wtt+Pw7PAhDk7Vb/s7q/WiE"
+			+ "I2Kv8zHCueUCQQDQUfweIrdb7bWOAcjXq/JY1PeClPNTqBlFy2bKKBlf4hAr"
+			+ "84/sajB0+E0R9KfEILVHIdxJAfkKICnwJAiEYH2PAkA0umTJSChXdNdVUN5q"
+			+ "SO8bKlocSHseIVnDYDubl6nA7xhmqU5iUjiEzuUJiEiUacUgFJlaV/4jbOSn"
+			+ "I3vQgLeFAkEAni+zN5r7CwZdV+EJBqRd2ZCWBgVfJAZAcpw6iIWchw+dYhKI"
+			+ "FmioNRobQ+g4wJhprwMKSDIETukPj3d9NDAlBwJAVxhn1grStavCunrnVNqc"
+			+ "BU+B1O8BiR4yPWnLMcRSyFRVJQA7HCp8JlDV6abXd8vPFfXuC9WN7rOvTKF8"
+			+ "Y0ZB9qANMAsGA1UdDzEEAwIAEA==");
+
+		private static readonly byte[] rfc4134ex5_1 = Base64.Decode(
+			"MIIBHgYJKoZIhvcNAQcDoIIBDzCCAQsCAQAxgcAwgb0CAQAwJjASMRAwDgYD"
+			+ "VQQDEwdDYXJsUlNBAhBGNGvHgABWvBHTbi7NXXHQMA0GCSqGSIb3DQEBAQUA"
+			+ "BIGAC3EN5nGIiJi2lsGPcP2iJ97a4e8kbKQz36zg6Z2i0yx6zYC4mZ7mX7FB"
+			+ "s3IWg+f6KgCLx3M1eCbWx8+MDFbbpXadCDgO8/nUkUNYeNxJtuzubGgzoyEd"
+			+ "8Ch4H/dd9gdzTd+taTEgS0ipdSJuNnkVY4/M652jKKHRLFf02hosdR8wQwYJ"
+			+ "KoZIhvcNAQcBMBQGCCqGSIb3DQMHBAgtaMXpRwZRNYAgDsiSf8Z9P43LrY4O"
+			+ "xUk660cu1lXeCSFOSOpOJ7FuVyU=");
+
+		private static readonly byte[] rfc4134ex5_2 = Base64.Decode(
+			"MIIBZQYJKoZIhvcNAQcDoIIBVjCCAVICAQIxggEAMIG9AgEAMCYwEjEQMA4G"
+			+ "A1UEAxMHQ2FybFJTQQIQRjRrx4AAVrwR024uzV1x0DANBgkqhkiG9w0BAQEF"
+			+ "AASBgJQmQojGi7Z4IP+CVypBmNFoCDoEp87khtgyff2N4SmqD3RxPx+8hbLQ"
+			+ "t9i3YcMwcap+aiOkyqjMalT03VUC0XBOGv+HYI3HBZm/aFzxoq+YOXAWs5xl"
+			+ "GerZwTOc9j6AYlK4qXvnztR5SQ8TBjlzytm4V7zg+TGrnGVNQBNw47Ewoj4C"
+			+ "AQQwDQQLTWFpbExpc3RSQzIwEAYLKoZIhvcNAQkQAwcCAToEGHcUr5MSJ/g9"
+			+ "HnJVHsQ6X56VcwYb+OfojTBJBgkqhkiG9w0BBwEwGgYIKoZIhvcNAwIwDgIC"
+			+ "AKAECJwE0hkuKlWhgCBeKNXhojuej3org9Lt7n+wWxOhnky5V50vSpoYRfRR"
+			+ "yw==");
+
+		[Test]
+		public void TestKeyTrans()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestKeyTransRC4()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				"1.2.840.113549.3.4"); // RC4 OID
+
+			RecipientInformationStore  recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, "1.2.840.113549.3.4");
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestKeyTrans128RC4()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				"1.2.840.113549.3.4", 128);  // RC4 OID
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, "1.2.840.113549.3.4");
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestKeyTransOdes()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaBouncyCastle");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				OiwObjectIdentifiers.DesCbc.Id);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, OiwObjectIdentifiers.DesCbc.Id);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestKeyTransSmallAes()
+		{
+			byte[] data = new byte[] { 0, 1, 2, 3 };
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid,
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestKeyTransCast5()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Cast5Cbc,
+				new DerObjectIdentifier(CmsEnvelopedDataGenerator.Cast5Cbc),
+				typeof(Asn1Sequence));
+		}
+
+		[Test]
+		public void TestKeyTransAes128()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Aes128Cbc,
+				NistObjectIdentifiers.IdAes128Cbc,
+				typeof(DerOctetString));
+		}
+
+		[Test]
+		public void TestKeyTransAes192()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Aes192Cbc,
+				NistObjectIdentifiers.IdAes192Cbc,
+				typeof(DerOctetString));
+		}
+
+		[Test]
+		public void TestKeyTransAes256()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Aes256Cbc,
+				NistObjectIdentifiers.IdAes256Cbc,
+				typeof(DerOctetString));
+		}
+
+		[Test]
+		public void TestKeyTransSeed()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.SeedCbc,
+				KisaObjectIdentifiers.IdSeedCbc,
+				typeof(DerOctetString));
+		}
+
+		public void TestKeyTransCamellia128()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Camellia128Cbc,
+				NttObjectIdentifiers.IdCamellia128Cbc,
+				typeof(DerOctetString));
+		}
+
+		public void TestKeyTransCamellia192()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Camellia192Cbc,
+				NttObjectIdentifiers.IdCamellia192Cbc,
+				typeof(DerOctetString));
+		}
+
+		public void TestKeyTransCamellia256()
+		{
+			TryKeyTrans(CmsEnvelopedDataGenerator.Camellia256Cbc,
+				NttObjectIdentifiers.IdCamellia256Cbc,
+				typeof(DerOctetString));
+		}
+
+		private void TryKeyTrans(
+			string				generatorOID,
+			DerObjectIdentifier	checkOID,
+			Type				asn1Params)
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyTransRecipient(ReciCert);
+
+			CmsEnvelopedData ed = edGen.Generate(new CmsProcessableByteArray(data), generatorOID);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(checkOID.Id, ed.EncryptionAlgOid);
+
+			if (asn1Params != null)
+			{
+				Assert.IsTrue(asn1Params.IsInstanceOfType(ed.EncryptionAlgorithmID.Parameters));
+			}
+
+			ArrayList c = new ArrayList(recipients.GetRecipients());
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+				byte[] recData = recipient.GetContent(ReciKP.Private);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestErroneousKek()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington");
+			KeyParameter kek = ParameterUtilities.CreateKeyParameter(
+				"AES",
+				new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 });
+
+			CmsEnvelopedData ed = new CmsEnvelopedData(oldKEK);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(recipient.KeyEncryptionAlgOid, NistObjectIdentifiers.IdAes128Wrap.Id);
+
+				byte[] recData = recipient.GetContent(kek);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestDesKek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeDesEde192Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.6"));
+		}
+
+		[Test]
+		public void TestRC2128Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeRC2128Key(), new DerObjectIdentifier("1.2.840.113549.1.9.16.3.7"));
+		}
+
+		[Test]
+		public void TestAes128Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeAesKey(128), NistObjectIdentifiers.IdAes128Wrap);
+		}
+
+		[Test]
+		public void TestAes192Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeAesKey(192), NistObjectIdentifiers.IdAes192Wrap);
+		}
+
+		[Test]
+		public void TestAes256Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeAesKey(256), NistObjectIdentifiers.IdAes256Wrap);
+		}
+
+		[Test]
+		public void TestSeed128Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeSeedKey(), KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap);
+		}
+
+		[Test]
+		public void TestCamellia128Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(128), NttObjectIdentifiers.IdCamellia128Wrap);
+		}
+
+		[Test]
+		public void TestCamellia192Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(192), NttObjectIdentifiers.IdCamellia192Wrap);
+		}
+
+		[Test]
+		public void TestCamellia256Kek()
+		{
+			TryKekAlgorithm(CmsTestUtil.MakeCamelliaKey(256), NttObjectIdentifiers.IdCamellia256Wrap);
+		}
+
+		private void TryKekAlgorithm(
+			KeyParameter		kek,
+			DerObjectIdentifier	algOid)
+		{
+			byte[] data = Encoding.ASCII.GetBytes("WallaWallaWashington");
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			byte[] kekId = new byte[] { 1, 2, 3, 4, 5 };
+
+			string keyAlgorithm = ParameterUtilities.GetCanonicalAlgorithmName(algOid.Id);
+
+			edGen.AddKekRecipient(keyAlgorithm, kek, kekId);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			ArrayList c = new ArrayList(recipients.GetRecipients());
+
+			Assert.IsTrue(c.Count > 0);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual(algOid.Id, recipient.KeyEncryptionAlgOid);
+
+				byte[] recData = recipient.GetContent(kek);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestECKeyAgree()
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyAgreementRecipient(
+				CmsEnvelopedDataGenerator.ECDHSha1Kdf,
+				OrigECKP.Private,
+				OrigECKP.Public,
+				ReciECCert,
+				CmsEnvelopedDataGenerator.Aes128Wrap);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private);
+			ConfirmNumberRecipients(recipients, 1);
+		}
+
+		[Test]
+		public void TestECMqvKeyAgree()
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddKeyAgreementRecipient(
+				CmsEnvelopedDataGenerator.ECMqvSha1Kdf,
+				OrigECKP.Private,
+				OrigECKP.Public,
+				ReciECCert,
+				CmsEnvelopedDataGenerator.Aes128Wrap);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private);
+			ConfirmNumberRecipients(recipients, 1);
+		}
+
+		[Test]
+		public void TestECMqvKeyAgreeMultiple()
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			ArrayList recipientCerts = new ArrayList();
+			recipientCerts.Add(ReciECCert);
+			recipientCerts.Add(ReciECCert2);
+
+			edGen.AddKeyAgreementRecipients(
+				CmsEnvelopedDataGenerator.ECMqvSha1Kdf,
+				OrigECKP.Private,
+				OrigECKP.Public,
+				recipientCerts,
+				CmsEnvelopedDataGenerator.Aes128Wrap);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			ConfirmDataReceived(recipients, data, ReciECCert, ReciECKP.Private);
+			ConfirmDataReceived(recipients, data, ReciECCert2, ReciECKP2.Private);
+			ConfirmNumberRecipients(recipients, 2);
+		}
+
+		private static void ConfirmDataReceived(RecipientInformationStore recipients,
+			byte[] expectedData, X509Certificate reciCert, AsymmetricKeyParameter reciPrivKey)
+		{
+			RecipientID rid = new RecipientID();
+			rid.Issuer = PrincipalUtilities.GetIssuerX509Principal(reciCert);
+			rid.SerialNumber = reciCert.SerialNumber;
+
+			RecipientInformation recipient = recipients[rid];
+			Assert.IsNotNull(recipient);
+
+			byte[] actualData = recipient.GetContent(reciPrivKey);
+			Assert.IsTrue(Arrays.AreEqual(expectedData, actualData));
+		}
+
+		private static void ConfirmNumberRecipients(RecipientInformationStore recipients, int count)
+		{
+			Assert.AreEqual(count, recipients.GetRecipients().Count);
+		}
+
+		[Test]
+		public void TestECKeyAgreeVectors()
+		{
+			AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(ecKeyAgreeKey);
+
+			VerifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.42", ecKeyAgreeMsgAES256);
+			VerifyECKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecKeyAgreeMsgAES128);
+			VerifyECKeyAgreeVectors(privKey, "1.2.840.113549.3.7", ecKeyAgreeMsgDESEDE);
+		}
+
+		[Test]
+		public void TestECMqvKeyAgreeVectors()
+		{
+			AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(ecKeyAgreeKey);
+
+			VerifyECMqvKeyAgreeVectors(privKey, "2.16.840.1.101.3.4.1.2", ecMqvKeyAgreeMsgAes128);
+		}
+
+		[Test]
+		public void TestPasswordAes256()
+		{
+			PasswordTest(CmsEnvelopedDataGenerator.Aes256Cbc);
+			PasswordUtf8Test(CmsEnvelopedDataGenerator.Aes256Cbc);
+		}
+
+		[Test]
+		public void TestPasswordDesEde()
+		{
+			PasswordTest(CmsEnvelopedDataGenerator.DesEde3Cbc);
+			PasswordUtf8Test(CmsEnvelopedDataGenerator.DesEde3Cbc);
+		}
+
+		[Test]
+		public void TestRfc4134Ex5_1()
+		{
+			byte[] data = Hex.Decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e");
+
+//			KeyFactory kFact = KeyFactory.GetInstance("RSA");
+//			Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt));
+			AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(bobPrivRsaEncrypt);
+
+			CmsEnvelopedData ed = new CmsEnvelopedData(rfc4134ex5_1);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual("1.2.840.113549.3.7", ed.EncryptionAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				byte[] recData = recipient.GetContent(key);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		[Test]
+		public void TestRfc4134Ex5_2()
+		{
+			byte[] data = Hex.Decode("5468697320697320736f6d652073616d706c6520636f6e74656e742e");
+
+//			KeyFactory kFact = KeyFactory.GetInstance("RSA");
+//			Key key = kFact.generatePrivate(new PKCS8EncodedKeySpec(bobPrivRsaEncrypt));
+			AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(bobPrivRsaEncrypt);
+
+			CmsEnvelopedData ed = new CmsEnvelopedData(rfc4134ex5_2);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual("1.2.840.113549.3.2", ed.EncryptionAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+			IEnumerator e = c.GetEnumerator();
+
+			if (e.MoveNext())
+			{
+				do
+				{
+					RecipientInformation recipient = (RecipientInformation) e.Current;
+
+					if (recipient is KeyTransRecipientInformation)
+					{
+						byte[] recData = recipient.GetContent(key);
+
+						Assert.IsTrue(Arrays.AreEqual(data, recData));
+					}
+				}
+				while (e.MoveNext());
+			}
+			else
+			{
+				Assert.Fail("no recipient found");
+			}
+		}
+
+		[Test]
+		public void TestOriginatorInfo()
+		{
+			CmsEnvelopedData env = new CmsEnvelopedData(CmsSampleMessages.originatorMessage);
+
+			RecipientInformationStore  recipients = env.GetRecipientInfos();
+
+			Assert.AreEqual(CmsEnvelopedDataGenerator.DesEde3Cbc, env.EncryptionAlgOid);
+		}
+
+		private void PasswordTest(
+			string algorithm)
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddPasswordRecipient(new Pkcs5Scheme2PbeKey("password".ToCharArray(), new byte[20], 5), algorithm);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (PasswordRecipientInformation recipient in c)
+			{
+				CmsPbeKey key = new Pkcs5Scheme2PbeKey("password".ToCharArray(), recipient.KeyDerivationAlgorithm);
+
+				byte[] recData = recipient.GetContent(key);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		private void PasswordUtf8Test(
+			string algorithm)
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedDataGenerator edGen = new CmsEnvelopedDataGenerator();
+
+			edGen.AddPasswordRecipient(
+				new Pkcs5Scheme2Utf8PbeKey("abc\u5639\u563b".ToCharArray(), new byte[20], 5),
+				algorithm);
+
+			CmsEnvelopedData ed = edGen.Generate(
+				new CmsProcessableByteArray(data),
+				CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(ed.EncryptionAlgOid, CmsEnvelopedDataGenerator.Aes128Cbc);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (PasswordRecipientInformation recipient in c)
+			{
+				CmsPbeKey key = new Pkcs5Scheme2Utf8PbeKey(
+					"abc\u5639\u563b".ToCharArray(), recipient.KeyDerivationAlgorithm);
+
+				byte[] recData = recipient.GetContent(key);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		private void VerifyECKeyAgreeVectors(
+			AsymmetricKeyParameter	privKey,
+			string					wrapAlg,
+			byte[]					message)
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedData ed = new CmsEnvelopedData(message);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			Assert.AreEqual(wrapAlg, ed.EncryptionAlgOid);
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual("1.3.133.16.840.63.0.2", recipient.KeyEncryptionAlgOid);
+
+				byte[] recData = recipient.GetContent(privKey);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+
+		private void VerifyECMqvKeyAgreeVectors(
+			AsymmetricKeyParameter	privKey,
+			string					wrapAlg,
+			byte[]					message)
+		{
+			byte[] data = Hex.Decode("504b492d4320434d5320456e76656c6f706564446174612053616d706c65");
+
+			CmsEnvelopedData ed = new CmsEnvelopedData(message);
+
+			RecipientInformationStore recipients = ed.GetRecipientInfos();
+
+			ICollection c = recipients.GetRecipients();
+
+			Assert.AreEqual(wrapAlg, ed.EncryptionAlgOid);
+			Assert.AreEqual(1, c.Count);
+
+			foreach (RecipientInformation recipient in c)
+			{
+				Assert.AreEqual("1.3.133.16.840.63.0.16", recipient.KeyEncryptionAlgOid);
+
+				byte[] recData = recipient.GetContent(privKey);
+
+				Assert.IsTrue(Arrays.AreEqual(data, recData));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/MiscDataStreamTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/MiscDataStreamTest.cs
new file mode 100644
index 0000000..f958d05
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/MiscDataStreamTest.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class MiscDataStreamTest
+	{
+		private const string TestMessage = "Hello World!";
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair signKP;
+		private static X509Certificate signCert;
+
+		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair origKP;
+		private static X509Certificate origCert;
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+		//		private static AsymmetricCipherKeyPair reciKP;
+		//		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origDsaKP;
+		private static X509Certificate origDsaCert;
+
+		private static X509Crl signCrl;
+		private static X509Crl origCrl;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair OrigKP
+		{
+			get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; }
+		}
+
+		//		private static AsymmetricCipherKeyPair ReciKP
+		//		{
+		//			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+		//		}
+
+		private static AsymmetricCipherKeyPair OrigDsaKP
+		{
+			get { return origDsaKP == null ? (origDsaKP = CmsTestUtil.MakeDsaKeyPair()) : origDsaKP; }
+		}
+
+		private static X509Certificate SignCert
+		{
+			get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, SignKP, SignDN)) : signCert; }
+		}
+
+		private static X509Certificate OrigCert
+		{
+			get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, SignKP, SignDN)) : origCert; }
+		}
+
+		//		private static X509Certificate ReciCert
+		//		{
+		//			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+		//		}
+
+		private static X509Certificate OrigDsaCert
+		{
+			get { return origDsaCert == null ? (origDsaCert = CmsTestUtil.MakeCertificate(OrigDsaKP, OrigDN, SignKP, SignDN)) : origDsaCert; }
+		}
+
+		private static X509Crl SignCrl
+		{
+			get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; }
+		}
+
+		private static X509Crl OrigCrl
+		{
+			get { return origCrl == null ? (origCrl = CmsTestUtil.MakeCrl(OrigKP)) : origCrl; }
+		}
+
+		private void VerifySignatures(
+			CmsSignedDataParser	sp,
+			byte[]				contentDigest)
+		{
+			IX509Store certStore = sp.GetCertificates("Collection");
+			SignerInformationStore signers = sp.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = certStore.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate	cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+
+				if (contentDigest != null)
+				{
+					Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest()));
+				}
+			}
+		}
+
+		private void VerifySignatures(
+			CmsSignedDataParser sp)
+		{
+			VerifySignatures(sp, null);
+		}
+
+		private void VerifyEncodedData(
+			MemoryStream bOut)
+		{
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			sp.Close();
+		}
+
+		private void CheckSigParseable(byte[] sig)
+		{
+			CmsSignedDataParser sp = new CmsSignedDataParser(sig);
+			sp.Version.ToString();
+			CmsTypedStream sc = sp.GetSignedContent();
+			if (sc != null)
+			{
+				sc.Drain();
+			}
+			sp.GetAttributeCertificates("Collection");
+			sp.GetCertificates("Collection");
+			sp.GetCrls("Collection");
+			sp.GetSignerInfos();
+			sp.Close();
+		}
+
+		[Test]
+		public void TestSha1WithRsa()
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			crlList.Add(SignCrl);
+			crlList.Add(OrigCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			Stream sigOut = gen.Open(bOut);
+
+			CmsCompressedDataStreamGenerator cGen = new CmsCompressedDataStreamGenerator();
+
+			Stream cOut = cGen.Open(sigOut, CmsCompressedDataStreamGenerator.ZLib);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			cOut.Write(testBytes, 0, testBytes.Length);
+
+			cOut.Close();
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			// generate compressed stream
+			MemoryStream cDataOut = new MemoryStream();
+		    
+			cOut = cGen.Open(cDataOut, CmsCompressedDataStreamGenerator.ZLib);
+
+			cOut.Write(testBytes, 0, testBytes.Length);
+
+			cOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(
+				new CmsTypedStream(new MemoryStream(cDataOut.ToArray(), false)), bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			//
+			// compute expected content digest
+			//
+			IDigest md = DigestUtilities.GetDigest("SHA1");
+			byte[] cDataOutBytes = cDataOut.ToArray();
+			md.BlockUpdate(cDataOutBytes, 0, cDataOutBytes.Length);
+			byte[] hash = DigestUtilities.DoFinal(md);
+
+			VerifySignatures(sp, hash);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/Rfc4134Test.cs b/BouncyCastle.AxCrypt/test/src/cms/test/Rfc4134Test.cs
new file mode 100644
index 0000000..3bfbd13
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/Rfc4134Test.cs
@@ -0,0 +1,344 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class Rfc4134Test
+	{
+		private static readonly byte[] exContent = GetRfc4134Data("ExContent.bin");
+		private static readonly byte[] sha1 = Hex.Decode("406aec085279ba6e16022d9e0629c0229687dd48");
+
+		[Test]
+		public void Test4_1()
+		{
+			byte[] data = GetRfc4134Data("4.1.bin");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+		}
+
+		[Test]
+		public void Test4_2()
+		{
+			byte[] data = GetRfc4134Data("4.2.bin");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+		}
+
+		[Test]
+		public void Test4_3()
+		{
+			CmsProcessableByteArray unencap = new CmsProcessableByteArray(exContent);
+			byte[] data = GetRfc4134Data("4.3.bin");
+			CmsSignedData signedData = new CmsSignedData(unencap, data);
+
+			VerifySignatures(signedData, sha1);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(
+				new CmsTypedStream(unencap.GetInputStream()), data);
+
+			VerifySignatures(parser);
+		}
+
+		[Test]
+		public void Test4_4()
+		{
+			byte[] data = GetRfc4134Data("4.4.bin");
+			byte[] counterSigCert = GetRfc4134Data("AliceRSASignByCarl.cer");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData, sha1);
+
+			VerifySignerInfo4_4(GetFirstSignerInfo(signedData.GetSignerInfos()), counterSigCert);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+
+			VerifySignerInfo4_4(GetFirstSignerInfo(parser.GetSignerInfos()), counterSigCert);
+		}
+
+		[Test]
+		public void Test4_5()
+		{
+			byte[] data = GetRfc4134Data("4.5.bin");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+		}
+
+		[Test]
+		public void Test4_6()
+		{
+			byte[] data = GetRfc4134Data("4.6.bin");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+		}
+		
+		[Test]
+		public void Test4_7()
+		{
+			byte[] data = GetRfc4134Data("4.7.bin");
+			CmsSignedData signedData = new CmsSignedData(data);
+
+			VerifySignatures(signedData);
+
+			CmsSignedDataParser parser = new CmsSignedDataParser(data);
+
+			VerifySignatures(parser);
+		}
+
+		[Test]
+		public void Test5_1()
+		{
+			byte[] data = GetRfc4134Data("5.1.bin");
+			CmsEnvelopedData envelopedData = new CmsEnvelopedData(data);
+
+			VerifyEnvelopedData(envelopedData, CmsEnvelopedDataGenerator.DesEde3Cbc);
+
+			CmsEnvelopedDataParser envelopedParser = new CmsEnvelopedDataParser(data);
+
+			VerifyEnvelopedData(envelopedParser, CmsEnvelopedDataGenerator.DesEde3Cbc);
+		}
+
+		[Test]
+		public void Test5_2()
+		{
+			byte[] data = GetRfc4134Data("5.2.bin");
+			CmsEnvelopedData envelopedData = new CmsEnvelopedData(data);
+
+			VerifyEnvelopedData(envelopedData, CmsEnvelopedDataGenerator.RC2Cbc);
+
+			CmsEnvelopedDataParser envelopedParser = new CmsEnvelopedDataParser(data);
+
+			VerifyEnvelopedData(envelopedParser, CmsEnvelopedDataGenerator.RC2Cbc);
+		}
+
+		private void VerifyEnvelopedData(CmsEnvelopedData envelopedData, string symAlgorithmOID)
+		{
+			byte[] privKeyData = GetRfc4134Data("BobPrivRSAEncrypt.pri");
+			AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyData);
+			Assert.IsTrue(privKey.IsPrivate);
+			Assert.IsTrue(privKey is RsaKeyParameters);
+
+			RecipientInformationStore recipients = envelopedData.GetRecipientInfos();
+
+			Assert.AreEqual(envelopedData.EncryptionAlgOid, symAlgorithmOID);
+
+			ArrayList c = new ArrayList(recipients.GetRecipients());
+			Assert.LessOrEqual(1, c.Count);
+			Assert.GreaterOrEqual(2, c.Count);
+
+			VerifyRecipient((RecipientInformation)c[0], privKey);
+
+			if (c.Count == 2)
+			{
+				RecipientInformation recInfo = (RecipientInformation)c[1];
+
+				Assert.AreEqual(PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id, recInfo.KeyEncryptionAlgOid);
+			}
+		}
+
+		private void VerifyEnvelopedData(CmsEnvelopedDataParser envelopedParser, string symAlgorithmOID)
+		{
+			byte[] privKeyData = GetRfc4134Data("BobPrivRSAEncrypt.pri");
+			AsymmetricKeyParameter privKey = PrivateKeyFactory.CreateKey(privKeyData);
+			Assert.IsTrue(privKey.IsPrivate);
+			Assert.IsTrue(privKey is RsaKeyParameters);
+
+			RecipientInformationStore recipients = envelopedParser.GetRecipientInfos();
+
+			Assert.AreEqual(envelopedParser.EncryptionAlgOid, symAlgorithmOID);
+
+			ArrayList c = new ArrayList(recipients.GetRecipients());
+			Assert.LessOrEqual(1, c.Count);
+			Assert.GreaterOrEqual(2, c.Count);
+
+			VerifyRecipient((RecipientInformation)c[0], privKey);
+
+			if (c.Count == 2)
+			{
+				RecipientInformation recInfo = (RecipientInformation)c[1];
+
+				Assert.AreEqual(PkcsObjectIdentifiers.IdAlgCmsRC2Wrap.Id, recInfo.KeyEncryptionAlgOid);
+			}
+		}
+
+		private void VerifyRecipient(RecipientInformation recipient, AsymmetricKeyParameter privKey)
+		{
+			Assert.IsTrue(privKey.IsPrivate);
+
+			Assert.AreEqual(recipient.KeyEncryptionAlgOid, PkcsObjectIdentifiers.RsaEncryption.Id);
+
+			byte[] recData = recipient.GetContent(privKey);
+
+			Assert.IsTrue(Arrays.AreEqual(exContent, recData));
+		}
+
+		private void VerifySignerInfo4_4(SignerInformation signerInfo, byte[] counterSigCert)
+		{
+			VerifyCounterSignature(signerInfo, counterSigCert);
+
+			VerifyContentHint(signerInfo);
+		}
+
+		private SignerInformation GetFirstSignerInfo(SignerInformationStore store)
+		{
+			IEnumerator e = store.GetSigners().GetEnumerator();
+			e.MoveNext();
+			return (SignerInformation)e.Current;
+		}
+
+		private void VerifyCounterSignature(SignerInformation signInfo, byte[] certificate)
+		{
+			SignerInformation csi = GetFirstSignerInfo(signInfo.GetCounterSignatures());
+
+			X509Certificate cert = new X509CertificateParser().ReadCertificate(certificate);
+
+			Assert.IsTrue(csi.Verify(cert));
+		}
+
+		private void VerifyContentHint(SignerInformation signInfo)
+		{
+			Asn1.Cms.AttributeTable attrTable = signInfo.UnsignedAttributes;
+
+			Asn1.Cms.Attribute attr = attrTable[CmsAttributes.ContentHint];
+
+			Assert.AreEqual(1, attr.AttrValues.Count);
+		
+			Asn1EncodableVector v = new Asn1EncodableVector(
+				new DerUtf8String("Content Hints Description Buffer"),
+				CmsObjectIdentifiers.Data);
+
+			Assert.IsTrue(attr.AttrValues[0].Equals(new DerSequence(v)));
+		}
+
+		private void VerifySignatures(CmsSignedData s, byte[] contentDigest)
+		{
+			IX509Store x509Certs = s.GetCertificates("Collection");
+			IX509Store x509Crls = s.GetCrls("Collection");
+			SignerInformationStore signers = s.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				VerifySigner(signer, cert);
+
+				if (contentDigest != null)
+				{
+					Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest()));
+				}
+			}
+
+			ICollection certColl = x509Certs.GetMatches(null);
+			ICollection crlColl = x509Crls.GetMatches(null);
+
+			Assert.AreEqual(certColl.Count, s.GetCertificates("Collection").GetMatches(null).Count);
+			Assert.AreEqual(crlColl.Count, s.GetCrls("Collection").GetMatches(null).Count);
+		}
+
+		private void VerifySignatures(CmsSignedData s)
+		{
+			VerifySignatures(s, null);
+		}
+
+		private void VerifySignatures(CmsSignedDataParser sp)
+		{
+	        CmsTypedStream sc = sp.GetSignedContent();
+	        if (sc != null)
+	        {
+	            sc.Drain();
+	        }
+			
+			IX509Store x509Certs = sp.GetCertificates("Collection");
+			SignerInformationStore signers = sp.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate)certEnum.Current;
+
+				VerifySigner(signer, cert);
+			}
+		}
+
+		private void VerifySigner(SignerInformation signer, X509Certificate cert)
+		{
+			if (cert.GetPublicKey() is DsaPublicKeyParameters)
+			{
+				DsaPublicKeyParameters key = (DsaPublicKeyParameters)cert.GetPublicKey();
+
+				if (key.Parameters == null)
+				{
+					Assert.IsTrue(signer.Verify(GetInheritedKey(key)));
+				}
+				else
+				{
+					Assert.IsTrue(signer.Verify(cert));
+				}
+			}
+			else
+			{
+				Assert.IsTrue(signer.Verify(cert));
+			}
+		}
+
+		private DsaPublicKeyParameters GetInheritedKey(DsaPublicKeyParameters dsaPubKey)
+		{
+			X509Certificate cert = new X509CertificateParser().ReadCertificate(
+				GetRfc4134Data("CarlDSSSelf.cer"));
+
+			DsaParameters dsaParams = ((DsaPublicKeyParameters)cert.GetPublicKey()).Parameters;
+
+			return new DsaPublicKeyParameters(dsaPubKey.Y, dsaParams);
+		}
+
+		private static byte[] GetRfc4134Data(string name)
+		{
+			return Streams.ReadAll(SimpleTest.GetTestDataAsStream("rfc4134." + name));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataStreamTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataStreamTest.cs
new file mode 100644
index 0000000..96f3f12
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataStreamTest.cs
@@ -0,0 +1,1235 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class SignedDataStreamTest
+	{
+		private const string TestMessage = "Hello World!";
+		private const string SignDN = "O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair signKP;
+		private static X509Certificate signCert;
+
+		private const string OrigDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair origKP;
+		private static X509Certificate origCert;
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+//		private static AsymmetricCipherKeyPair reciKP;
+//		private static X509Certificate reciCert;
+
+		private static AsymmetricCipherKeyPair origDsaKP;
+		private static X509Certificate origDsaCert;
+
+		private static X509Crl signCrl;
+		private static X509Crl origCrl;
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+		private static AsymmetricCipherKeyPair OrigKP
+		{
+			get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; }
+		}
+
+//		private static AsymmetricCipherKeyPair ReciKP
+//		{
+//			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+//		}
+
+		private static AsymmetricCipherKeyPair OrigDsaKP
+		{
+			get { return origDsaKP == null ? (origDsaKP = CmsTestUtil.MakeDsaKeyPair()) : origDsaKP; }
+		}
+
+		private static X509Certificate SignCert
+		{
+			get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, SignKP, SignDN)) : signCert; }
+		}
+
+		private static X509Certificate OrigCert
+		{
+			get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, SignKP, SignDN)) : origCert; }
+		}
+
+//		private static X509Certificate ReciCert
+//		{
+//			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+//		}
+
+		private static X509Certificate OrigDsaCert
+		{
+			get { return origDsaCert == null ? (origDsaCert = CmsTestUtil.MakeCertificate(OrigDsaKP, OrigDN, SignKP, SignDN)) : origDsaCert; }
+		}
+
+		private static X509Crl SignCrl
+		{
+			get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; }
+		}
+
+		private static X509Crl OrigCrl
+		{
+			get { return origCrl == null ? (origCrl = CmsTestUtil.MakeCrl(OrigKP)) : origCrl; }
+		}
+
+		private void VerifySignatures(
+			CmsSignedDataParser	sp,
+			byte[]				contentDigest)
+		{
+			IX509Store certStore = sp.GetCertificates("Collection");
+			SignerInformationStore signers = sp.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = certStore.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate	cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+
+				if (contentDigest != null)
+				{
+					Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest()));
+				}
+			}
+		}
+
+		private void VerifySignatures(
+			CmsSignedDataParser sp)
+		{
+			VerifySignatures(sp, null);
+		}
+
+		private void VerifyEncodedData(
+			MemoryStream bOut)
+		{
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			sp.Close();
+		}
+
+	    private void CheckSigParseable(byte[] sig)
+	    {
+	        CmsSignedDataParser sp = new CmsSignedDataParser(sig);
+	        sp.Version.ToString();
+	        CmsTypedStream sc = sp.GetSignedContent();
+	        if (sc != null)
+	        {
+	            sc.Drain();
+	        }
+	        sp.GetAttributeCertificates("Collection");
+	        sp.GetCertificates("Collection");
+	        sp.GetCrls("Collection");
+	        sp.GetSignerInfos();
+	        sp.Close();
+	    }
+
+		[Test]
+		public void TestEarlyInvalidKeyException()
+		{
+			try
+			{
+				CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+				gen.AddSigner(OrigKP.Private, OrigCert,
+					"DSA", // DOESN'T MATCH KEY ALG
+					CmsSignedDataStreamGenerator.DigestSha1);
+
+				Assert.Fail("Expected InvalidKeyException in AddSigner");
+			}
+			catch (InvalidKeyException)
+			{
+				// Ignore
+			}
+		}
+
+		[Test]
+		public void TestEarlyNoSuchAlgorithmException()
+		{
+			try
+			{
+				CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+				gen.AddSigner(OrigKP.Private, OrigCert,
+					CmsSignedDataStreamGenerator.DigestSha1, // BAD OID!
+					CmsSignedDataStreamGenerator.DigestSha1);
+
+				Assert.Fail("Expected NoSuchAlgorithmException in AddSigner");
+			}
+			catch (SecurityUtilityException)
+			{
+				// Ignore
+			}
+		}
+
+		[Test]
+		public void TestSha1EncapsulatedSignature()
+		{
+			byte[]  encapSigData = Base64.Decode(
+				"MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEH"
+				+ "AaCAJIAEDEhlbGxvIFdvcmxkIQAAAAAAAKCCBGIwggINMIIBdqADAgECAgEF"
+				+ "MA0GCSqGSIb3DQEBBAUAMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJ"
+				+ "BgNVBAYTAkFVMB4XDTA1MDgwNzA2MjU1OVoXDTA1MTExNTA2MjU1OVowJTEW"
+				+ "MBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUwgZ8wDQYJKoZI"
+				+ "hvcNAQEBBQADgY0AMIGJAoGBAI1fZGgH9wgC3QiK6yluH6DlLDkXkxYYL+Qf"
+				+ "nVRszJVYl0LIxZdpb7WEbVpO8fwtEgFtoDsOdxyqh3dTBv+L7NVD/v46kdPt"
+				+ "xVkSNHRbutJVY8Xn4/TC/CDngqtbpbniMO8n0GiB6vs94gBT20M34j96O2IF"
+				+ "73feNHP+x8PkJ+dNAgMBAAGjTTBLMB0GA1UdDgQWBBQ3XUfEE6+D+t+LIJgK"
+				+ "ESSUE58eyzAfBgNVHSMEGDAWgBQ3XUfEE6+D+t+LIJgKESSUE58eyzAJBgNV"
+				+ "HRMEAjAAMA0GCSqGSIb3DQEBBAUAA4GBAFK3r1stYOeXYJOlOyNGDTWEhZ+a"
+				+ "OYdFeFaS6c+InjotHuFLAy+QsS8PslE48zYNFEqYygGfLhZDLlSnJ/LAUTqF"
+				+ "01vlp+Bgn/JYiJazwi5WiiOTf7Th6eNjHFKXS3hfSGPNPIOjvicAp3ce3ehs"
+				+ "uK0MxgLAaxievzhFfJcGSUMDMIICTTCCAbagAwIBAgIBBzANBgkqhkiG9w0B"
+				+ "AQQFADAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAe"
+				+ "Fw0wNTA4MDcwNjI1NTlaFw0wNTExMTUwNjI1NTlaMGUxGDAWBgNVBAMTD0Vy"
+				+ "aWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0"
+				+ "bGUub3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTCB"
+				+ "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAgHCJyfwV6/V3kqSu2SOU2E/K"
+				+ "I+N0XohCMUaxPLLNtNBZ3ijxwaV6JGFz7siTgZD/OGfzir/eZimkt+L1iXQn"
+				+ "OAB+ZChivKvHtX+dFFC7Vq+E4Uy0Ftqc/wrGxE6DHb5BR0hprKH8wlDS8wSP"
+				+ "zxovgk4nH0ffUZOoDSuUgjh3gG8CAwEAAaNNMEswHQYDVR0OBBYEFLfY/4EG"
+				+ "mYrvJa7Cky+K9BJ7YmERMB8GA1UdIwQYMBaAFDddR8QTr4P634sgmAoRJJQT"
+				+ "nx7LMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEEBQADgYEADIOmpMd6UHdMjkyc"
+				+ "mIE1yiwfClCsGhCK9FigTg6U1G2FmkBwJIMWBlkeH15uvepsAncsgK+Cn3Zr"
+				+ "dZMb022mwtTJDtcaOM+SNeuCnjdowZ4i71Hf68siPm6sMlZkhz49rA0Yidoo"
+				+ "WuzYOO+dggzwDsMldSsvsDo/ARyCGOulDOAxggEvMIIBKwIBATAqMCUxFjAU"
+				+ "BgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYTAkFVAgEHMAkGBSsOAwIa"
+				+ "BQCgXTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEP"
+				+ "Fw0wNTA4MDcwNjI1NTlaMCMGCSqGSIb3DQEJBDEWBBQu973mCM5UBOl9XwQv"
+				+ "lfifHCMocTANBgkqhkiG9w0BAQEFAASBgGxnBl2qozYKLgZ0ygqSFgWcRGl1"
+				+ "LgNuE587LtO+EKkgoc3aFqEdjXlAyP8K7naRsvWnFrsB6pUpnrgI9Z8ZSKv8"
+				+ "98IlpsSSJ0jBlEb4gzzavwcBpYbr2ryOtDcF+kYmKIpScglyyoLzm+KPXOoT"
+				+ "n7MsJMoKN3Kd2Vzh6s10PFgeAAAAAAAA");
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(encapSigData);
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+//		[Test]
+//		public void TestSha1WithRsaNoAttributes()
+//		{
+//			IList certList = new ArrayList();
+//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
+//
+//			certList.Add(OrigCert);
+//			certList.Add(SignCert);
+//
+//			IX509Store x509Certs = X509StoreFactory.Create(
+//				"Certificate/Collection",
+//				new X509CollectionStoreParameters(certList));
+//
+//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+//
+//			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+//
+//			gen.AddCertificates(x509Certs);
+//
+//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+//
+//			CmsSignedDataParser sp = new CmsSignedDataParser(
+//				new CmsTypedStream(new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)), s.GetEncoded());
+//
+//			sp.GetSignedContent().Drain();
+//
+//			//
+//			// compute expected content digest
+//			//
+//			IDigest md = DigestUtilities.GetDigest("SHA1");
+//
+//			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+//			md.BlockUpdate(testBytes, 0, testBytes.Length);
+//			byte[] hash = DigestUtilities.DoFinal(md);
+//
+//			VerifySignatures(sp, hash);
+//		}
+
+//		[Test]
+//		public void TestDsaNoAttributes()
+//		{
+//			IList certList = new ArrayList();
+//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes(TestMessage));
+//
+//			certList.Add(OrigDsaCert);
+//			certList.Add(SignCert);
+//
+//			IX509Store x509Certs = X509StoreFactory.Create(
+//				"Certificate/Collection",
+//				new X509CollectionStoreParameters(certList));
+//
+//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+//
+//			gen.AddSigner(OrigDsaKP.Private, OrigDsaCert, CmsSignedDataGenerator.DigestSha1);
+//
+//			gen.AddCertificates(x509Certs);
+//
+//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+//
+//			CmsSignedDataParser sp = new CmsSignedDataParser(
+//				new CmsTypedStream(
+//				new MemoryStream(Encoding.ASCII.GetBytes(TestMessage), false)),
+//				s.GetEncoded());
+//
+//			sp.GetSignedContent().Drain();
+//
+//			//
+//			// compute expected content digest
+//			//
+//			IDigest md = DigestUtilities.GetDigest("SHA1");
+//
+//			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+//			md.BlockUpdate(testBytes, 0, testBytes.Length);
+//			byte[] hash = DigestUtilities.DoFinal(md);
+//
+//			VerifySignatures(sp, hash);
+//		}
+
+		[Test]
+		public void TestSha1WithRsa()
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			crlList.Add(SignCrl);
+			crlList.Add(OrigCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			Stream sigOut = gen.Open(bOut);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(
+				new CmsTypedStream(new MemoryStream(testBytes, false)), bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			//
+			// compute expected content digest
+			//
+			IDigest md = DigestUtilities.GetDigest("SHA1");
+			md.BlockUpdate(testBytes, 0, testBytes.Length);
+			byte[] hash = DigestUtilities.DoFinal(md);
+
+			VerifySignatures(sp, hash);
+
+			//
+			// try using existing signer
+			//
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigners(sp.GetSignerInfos());
+
+			gen.AddCertificates(sp.GetCertificates("Collection"));
+			gen.AddCrls(sp.GetCrls("Collection"));
+
+			bOut.SetLength(0);
+
+			sigOut = gen.Open(bOut, true);
+
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			VerifyEncodedData(bOut);
+
+			//
+			// look for the CRLs
+			//
+			ArrayList col = new ArrayList(x509Crls.GetMatches(null));
+
+			Assert.AreEqual(2, col.Count);
+			Assert.IsTrue(col.Contains(SignCrl));
+			Assert.IsTrue(col.Contains(OrigCrl));
+		}
+
+		[Test]
+		public void TestSha1WithRsaNonData()
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			crlList.Add(SignCrl);
+			crlList.Add(OrigCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			Stream sigOut = gen.Open(bOut, "1.2.3.4", true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			CmsTypedStream stream = sp.GetSignedContent();
+
+			Assert.AreEqual("1.2.3.4", stream.ContentType);
+
+			stream.Drain();
+
+			//
+			// compute expected content digest
+			//
+			IDigest md = DigestUtilities.GetDigest("SHA1");
+			md.BlockUpdate(testBytes, 0, testBytes.Length);
+			byte[] hash = DigestUtilities.DoFinal(md);
+
+			VerifySignatures(sp, hash);
+		}
+
+		[Test]
+		public void TestSha1AndMD5WithRsa()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddDigests(CmsSignedDataStreamGenerator.DigestSha1,
+				CmsSignedDataStreamGenerator.DigestMD5);
+
+			Stream sigOut = gen.Open(bOut);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			gen.AddCertificates(x509Certs);
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestMD5);
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(
+				new CmsTypedStream(new MemoryStream(testBytes, false)), bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestSha1WithRsaEncapsulatedBufferedStream()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// find unbuffered length
+			//
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				sigOut.WriteByte((byte)(i & 0xff));
+			}
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			int unbufferedLength = bOut.ToArray().Length;
+
+			//
+			// find buffered length with buffered stream - should be equal
+			//
+			bOut.SetLength(0);
+
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			sigOut = gen.Open(bOut, true);
+
+			byte[] data = new byte[2000];
+			for (int i = 0; i != 2000; i++)
+			{
+				data[i] = (byte)(i & 0xff);
+			}
+
+			Streams.PipeAll(new MemoryStream(data, false), sigOut);
+			sigOut.Close();
+
+			VerifyEncodedData(bOut);
+
+			Assert.AreEqual(unbufferedLength, bOut.ToArray().Length);
+		}
+
+		[Test]
+		public void TestSha1WithRsaEncapsulatedBuffered()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// find unbuffered length
+			//
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				sigOut.WriteByte((byte)(i & 0xff));
+			}
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			int unbufferedLength = bOut.ToArray().Length;
+
+			//
+			// find buffered length - buffer size less than default
+			//
+			bOut.SetLength(0);
+
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.SetBufferSize(300);
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			sigOut = gen.Open(bOut, true);
+
+			for (int i = 0; i != 2000; i++)
+			{
+				sigOut.WriteByte((byte)(i & 0xff));
+			}
+
+			sigOut.Close();
+
+			VerifyEncodedData(bOut);
+
+			Assert.IsTrue(unbufferedLength < bOut.ToArray().Length);
+		}
+
+		[Test]
+		public void TestSha1WithRsaEncapsulated()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1];
+
+			ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners());
+
+			AttributeTable table = ((SignerInformation) signers[0]).SignedAttributes;
+			Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest];
+
+			Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets()));
+
+			//
+			// try using existing signer
+			//
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigners(sp.GetSignerInfos());
+
+			gen.AddCertificates(sp.GetCertificates("Collection"));
+			gen.AddCrls(sp.GetCrls("Collection"));
+
+			bOut.SetLength(0);
+
+			sigOut = gen.Open(bOut, true);
+
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedData sd = new CmsSignedData(
+				new CmsProcessableByteArray(testBytes), bOut.ToArray());
+
+			Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count);
+
+			VerifyEncodedData(bOut);
+		}
+
+		private static readonly DerObjectIdentifier dummyOid1 = new DerObjectIdentifier("1.2.3");
+		private static readonly DerObjectIdentifier dummyOid2 = new DerObjectIdentifier("1.2.3.4");
+
+		private class SignedGenAttributeTableGenerator
+			: DefaultSignedAttributeTableGenerator
+		{
+			public override AttributeTable GetAttributes(
+				IDictionary parameters)
+			{
+				IDictionary table = createStandardAttributeTable(parameters);
+
+				DerOctetString val = new DerOctetString((byte[])parameters[CmsAttributeTableParameter.Digest]);
+				Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(dummyOid1, new DerSet(val));
+
+				table[attr.AttrType] = attr;
+
+				return new AttributeTable(table);
+			}
+		};
+
+		private class UnsignedGenAttributeTableGenerator
+			: CmsAttributeTableGenerator
+		{
+			public AttributeTable GetAttributes(
+				IDictionary parameters)
+			{
+				DerOctetString val = new DerOctetString((byte[])parameters[CmsAttributeTableParameter.Signature]);
+				Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(dummyOid2, new DerSet(val));
+
+				return new AttributeTable(new DerSet(attr));
+			}
+		};
+
+		[Test]
+	    public void TestSha1WithRsaEncapsulatedSubjectKeyID()
+	    {
+	        IList certList = new ArrayList();
+	        MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+	        gen.AddSigner(OrigKP.Private,
+				CmsTestUtil.CreateSubjectKeyId(OrigCert.GetPublicKey()).GetKeyIdentifier(),
+				CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[CmsSignedGenerator.DigestSha1];
+
+			ArrayList signers = new ArrayList(sp.GetSignerInfos().GetSigners());
+
+			AttributeTable table = ((SignerInformation) signers[0]).SignedAttributes;
+			Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest];
+
+			Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets()));
+
+			//
+			// try using existing signer
+			//
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigners(sp.GetSignerInfos());
+
+//			gen.AddCertificatesAndCRLs(sp.getCertificatesAndCRLs("Collection", "BC"));
+			gen.AddCertificates(sp.GetCertificates("Collection"));
+
+			bOut.SetLength(0);
+
+			sigOut = gen.Open(bOut, true);
+
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedData sd = new CmsSignedData(new CmsProcessableByteArray(testBytes), bOut.ToArray());
+
+			Assert.AreEqual(1, sd.GetSignerInfos().GetSigners().Count);
+
+	        VerifyEncodedData(bOut);
+	    }
+
+		[Test]
+		public void TestAttributeGenerators()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			CmsAttributeTableGenerator signedGen = new SignedGenAttributeTableGenerator();
+			CmsAttributeTableGenerator unsignedGen = new UnsignedGenAttributeTableGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert,
+				CmsSignedDataStreamGenerator.DigestSha1, signedGen, unsignedGen);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+
+			//
+			// check attributes
+			//
+			SignerInformationStore signers = sp.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				checkAttribute(signer.GetContentDigest(), signer.SignedAttributes[dummyOid1]);
+				checkAttribute(signer.GetSignature(), signer.UnsignedAttributes[dummyOid2]);
+			}
+		}
+
+		private void checkAttribute(
+			byte[]				expected,
+			Asn1.Cms.Attribute	attr)
+		{
+			DerOctetString value = (DerOctetString)attr.AttrValues[0];
+
+			Assert.AreEqual(new DerOctetString(expected), value);
+		}
+
+		[Test]
+		public void TestWithAttributeCertificate()
+		{
+			IList certList = new ArrayList();
+
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
+
+			ArrayList attrCerts = new ArrayList();
+			attrCerts.Add(attrCert);
+			IX509Store store = X509StoreFactory.Create(
+				"AttributeCertificate/Collection",
+				new X509CollectionStoreParameters(attrCerts));
+
+			gen.AddAttributeCertificates(store);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			Assert.AreEqual(4, sp.Version);
+
+			store = sp.GetAttributeCertificates("Collection");
+
+			ArrayList coll = new ArrayList(store.GetMatches(null));
+
+			Assert.AreEqual(1, coll.Count);
+
+			Assert.IsTrue(coll.Contains(attrCert));
+		}
+
+		[Test]
+		public void TestSignerStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+			byte[] data = Encoding.ASCII.GetBytes(TestMessage);
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, false);
+
+			sigOut.Write(data, 0, data.Length);
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			//
+			// create new Signer
+			//
+			MemoryStream original = new MemoryStream(bOut.ToArray(), false);
+
+			bOut.SetLength(0);
+
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224);
+
+			gen.AddCertificates(x509Certs);
+
+			sigOut = gen.Open(bOut);
+
+			sigOut.Write(data, 0, data.Length);
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			CmsSignedData sd = new CmsSignedData(bOut.ToArray());
+
+			//
+			// replace signer
+			//
+			MemoryStream newOut = new MemoryStream();
+
+			CmsSignedDataParser.ReplaceSigners(original, sd.GetSignerInfos(), newOut);
+
+			sd = new CmsSignedData(new CmsProcessableByteArray(data), newOut.ToArray());
+
+			IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator();
+			signerEnum.MoveNext();
+			SignerInformation signer = (SignerInformation) signerEnum.Current;
+
+			Assert.AreEqual(signer.DigestAlgOid, CmsSignedDataStreamGenerator.DigestSha224);
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(new CmsTypedStream(
+				new MemoryStream(data, false)), newOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestEncapsulatedSignerStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			//
+			// create new Signer
+			//
+			MemoryStream  original = new MemoryStream(bOut.ToArray(), false);
+
+			bOut.SetLength(0);
+
+			gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha224);
+
+			gen.AddCertificates(x509Certs);
+
+			sigOut = gen.Open(bOut, true);
+
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedData sd = new CmsSignedData(bOut.ToArray());
+
+			//
+			// replace signer
+			//
+			MemoryStream newOut = new MemoryStream();
+
+			CmsSignedDataParser.ReplaceSigners(original, sd.GetSignerInfos(), newOut);
+
+			sd = new CmsSignedData(newOut.ToArray());
+
+			IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator();
+			signerEnum.MoveNext();
+			SignerInformation signer = (SignerInformation) signerEnum.Current;
+
+			Assert.AreEqual(signer.DigestAlgOid, CmsSignedDataStreamGenerator.DigestSha224);
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(newOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestCertStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+			byte[] data = Encoding.ASCII.GetBytes(TestMessage);
+
+			certList.Add(OrigDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut);
+
+			sigOut.Write(data, 0, data.Length);
+
+			sigOut.Close();
+
+			CheckSigParseable(bOut.ToArray());
+
+			//
+			// create new certstore with the right certificates
+			//
+			certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// replace certs
+			//
+			MemoryStream original = new MemoryStream(bOut.ToArray(), false);
+			MemoryStream newOut = new MemoryStream();
+
+			CmsSignedDataParser.ReplaceCertificatesAndCrls(original, x509Certs, null, null, newOut);
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(new CmsTypedStream(new MemoryStream(data, false)), newOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestEncapsulatedCertStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			//
+			// create new certstore with the right certificates
+			//
+			certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// replace certs
+			//
+			MemoryStream original = new MemoryStream(bOut.ToArray(), false);
+			MemoryStream newOut = new MemoryStream();
+
+			CmsSignedDataParser.ReplaceCertificatesAndCrls(original, x509Certs, null, null, newOut);
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(newOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestCertOrdering1()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+			x509Certs = sp.GetCertificates("Collection");
+			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
+
+			Assert.AreEqual(2, a.Count);
+			Assert.AreEqual(OrigCert, a[0]);
+			Assert.AreEqual(SignCert, a[1]);
+		}
+
+		[Test]
+		public void TestCertOrdering2()
+		{
+			IList certList = new ArrayList();
+			MemoryStream bOut = new MemoryStream();
+
+			certList.Add(SignCert);
+			certList.Add(OrigCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataStreamGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			Stream sigOut = gen.Open(bOut, true);
+
+			byte[] testBytes = Encoding.ASCII.GetBytes(TestMessage);
+			sigOut.Write(testBytes, 0, testBytes.Length);
+
+			sigOut.Close();
+
+			CmsSignedDataParser sp = new CmsSignedDataParser(bOut.ToArray());
+
+			sp.GetSignedContent().Drain();
+			x509Certs = sp.GetCertificates("Collection");
+			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
+
+			Assert.AreEqual(2, a.Count);
+			Assert.AreEqual(SignCert, a[0]);
+			Assert.AreEqual(OrigCert, a[1]);
+		}
+
+        [Test]
+        public void TestCertsOnly()
+        {
+            IList certList = new ArrayList();
+            certList.Add(OrigCert);
+            certList.Add(SignCert);
+
+            IX509Store x509Certs = X509StoreFactory.Create(
+                "Certificate/Collection",
+                new X509CollectionStoreParameters(certList));
+
+            MemoryStream bOut = new MemoryStream();
+
+            CmsSignedDataStreamGenerator gen = new CmsSignedDataStreamGenerator();
+            gen.AddCertificates(x509Certs);
+            gen.Open(bOut).Close();
+
+            CheckSigParseable(bOut.ToArray());
+        }
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataTest.cs b/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataTest.cs
new file mode 100644
index 0000000..96f00ea
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/cms/test/SignedDataTest.cs
@@ -0,0 +1,1480 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Cms.Tests
+{
+	[TestFixture]
+	public class SignedDataTest
+	{
+		private const string OrigDN = "O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair origKP;
+		private static X509Certificate origCert;
+
+		private const string SignDN = "CN=Bob, OU=Sales, O=Bouncy Castle, C=AU";
+		private static AsymmetricCipherKeyPair signKP;
+		private static X509Certificate signCert;
+
+		private const string ReciDN = "CN=Doug, OU=Sales, O=Bouncy Castle, C=AU";
+//		private static AsymmetricCipherKeyPair reciKP;
+//		private static X509Certificate reciCert;
+
+		private static X509Crl signCrl;
+
+		private static AsymmetricCipherKeyPair signGostKP;
+		private static X509Certificate signGostCert;
+
+		private static AsymmetricCipherKeyPair signDsaKP;
+		private static X509Certificate signDsaCert;
+
+		private static AsymmetricCipherKeyPair signECGostKP;
+		private static X509Certificate signECGostCert;
+
+		private static AsymmetricCipherKeyPair signECDsaKP;
+		private static X509Certificate signECDsaCert;
+
+		private static AsymmetricCipherKeyPair OrigKP
+		{
+			get { return origKP == null ? (origKP = CmsTestUtil.MakeKeyPair()) : origKP; }
+		}
+
+		private static AsymmetricCipherKeyPair SignKP
+		{
+			get { return signKP == null ? (signKP = CmsTestUtil.MakeKeyPair()) : signKP; }
+		}
+
+//		private static AsymmetricCipherKeyPair ReciKP
+//		{
+//			get { return reciKP == null ? (reciKP = CmsTestUtil.MakeKeyPair()) : reciKP; }
+//		}
+
+		private static AsymmetricCipherKeyPair SignGostKP
+		{
+			get { return signGostKP == null ? (signGostKP = CmsTestUtil.MakeGostKeyPair()) : signGostKP; }
+		}
+
+		private static AsymmetricCipherKeyPair SignDsaKP
+		{
+			get { return signDsaKP == null ? (signDsaKP = CmsTestUtil.MakeDsaKeyPair()) : signDsaKP; }
+		}
+
+		private static AsymmetricCipherKeyPair SignECGostKP
+		{
+			get { return signECGostKP == null ? (signECGostKP = CmsTestUtil.MakeECGostKeyPair()) : signECGostKP; }
+		}
+
+		private static AsymmetricCipherKeyPair SignECDsaKP
+		{
+			get { return signECDsaKP == null ? (signECDsaKP = CmsTestUtil.MakeECDsaKeyPair()) : signECDsaKP; }
+		}
+
+		private static X509Certificate OrigCert
+		{
+			get { return origCert == null ? (origCert = CmsTestUtil.MakeCertificate(OrigKP, OrigDN, OrigKP, OrigDN)) : origCert; }
+		}
+
+		private static X509Certificate SignCert
+		{
+			get { return signCert == null ? (signCert = CmsTestUtil.MakeCertificate(SignKP, SignDN, OrigKP, OrigDN)) : signCert; }
+		}
+
+//		private static X509Certificate ReciCert
+//		{
+//			get { return reciCert == null ? (reciCert = CmsTestUtil.MakeCertificate(ReciKP, ReciDN, SignKP, SignDN)) : reciCert; }
+//		}
+
+		private static X509Crl SignCrl
+		{
+			get { return signCrl == null ? (signCrl = CmsTestUtil.MakeCrl(SignKP)) : signCrl; }
+		}
+
+		private static X509Certificate SignGostCert
+		{
+			get { return signGostCert == null ? (signGostCert = CmsTestUtil.MakeCertificate(SignGostKP, SignDN, OrigKP, OrigDN)) : signGostCert; }
+		}
+
+		private static X509Certificate SignECGostCert
+		{
+			get { return signECGostCert == null ? (signECGostCert = CmsTestUtil.MakeCertificate(SignECGostKP, SignDN, OrigKP, OrigDN)) : signECGostCert; }
+		}
+
+		private static X509Certificate SignDsaCert
+		{
+			get { return signDsaCert == null ? (signDsaCert = CmsTestUtil.MakeCertificate(SignDsaKP, SignDN, OrigKP, OrigDN)) : signDsaCert; }
+		}
+
+		private static X509Certificate SignECDsaCert
+		{
+			get { return signECDsaCert == null ? (signECDsaCert = CmsTestUtil.MakeCertificate(SignECDsaKP, SignDN, OrigKP, OrigDN)) : signECDsaCert; }
+		}
+
+		private static readonly byte[] disorderedMessage = Base64.Decode(
+			"SU9fc3RkaW5fdXNlZABfX2xpYmNfc3RhcnRfbWFpbgBnZXRob3N0aWQAX19n"
+			+ "bW9uX3M=");
+
+		private static readonly byte[] disorderedSet = Base64.Decode(
+			"MIIYXQYJKoZIhvcNAQcCoIIYTjCCGEoCAQExCzAJBgUrDgMCGgUAMAsGCSqG"
+			+ "SIb3DQEHAaCCFqswggJUMIIBwKADAgECAgMMg6wwCgYGKyQDAwECBQAwbzEL"
+			+ "MAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbI"
+			+ "dXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwEx"
+			+ "MBEGA1UEAxQKNFItQ0EgMTpQTjAiGA8yMDAwMDMyMjA5NDM1MFoYDzIwMDQw"
+			+ "MTIxMTYwNDUzWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1"
+			+ "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh"
+			+ "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3"
+			+ "DQEBAQUAA4GPADCBiwKBgQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0I"
+			+ "fe3QMqeGMoCUnyJxwW0k2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg"
+			+ "19e9JPv061wyADOucOIaNAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKaj"
+			+ "LMAw0bu1J0FadQIFAMAAAAEwCgYGKyQDAwECBQADgYEAgFauXpoTLh3Z3pT/"
+			+ "3bhgrxO/2gKGZopWGSWSJPNwq/U3x2EuctOJurj+y2inTcJjespThflpN+7Q"
+			+ "nvsUhXU+jL2MtPlObU0GmLvWbi47cBShJ7KElcZAaxgWMBzdRGqTOdtMv+ev"
+			+ "2t4igGF/q71xf6J2c3pTLWr6P8s6tzLfOCMwggJDMIIBr6ADAgECAgQAuzyu"
+			+ "MAoGBiskAwMBAgUAMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGll"
+			+ "cnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0"
+			+ "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE4wIhgPMjAwMTA4"
+			+ "MjAwODA4MjBaGA8yMDA1MDgyMDA4MDgyMFowSzELMAkGA1UEBhMCREUxEjAQ"
+			+ "BgNVBAoUCVNpZ250cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBT"
+			+ "SUdOVFJVU1QgMTpQTjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAhV12"
+			+ "N2WhlR6f+3CXP57GrBM9la5Vnsu2b92zv5MZqQOPeEsYbZqDCFkYg1bSwsDE"
+			+ "XsGVQqXdQNAGUaapr/EUVVN+hNZ07GcmC1sPeQECgUkxDYjGi4ihbvzxlahj"
+			+ "L4nX+UTzJVBfJwXoIvJ+lMHOSpnOLIuEL3SRhBItvRECxN0CAwEAAaMSMBAw"
+			+ "DgYDVR0PAQH/BAQDAgEGMAoGBiskAwMBAgUAA4GBACDc9Pc6X8sK1cerphiV"
+			+ "LfFv4kpZb9ev4WPy/C6987Qw1SOTElhZAmxaJQBqmDHWlQ63wj1DEqswk7hG"
+			+ "LrvQk/iX6KXIn8e64uit7kx6DHGRKNvNGofPjr1WelGeGW/T2ZJKgmPDjCkf"
+			+ "sIKt2c3gwa2pDn4mmCz/DStUIqcPDbqLMIICVTCCAcGgAwIBAgIEAJ16STAK"
+			+ "BgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1"
+			+ "bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEh"
+			+ "MAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1DQSAxOlBOMCIYDzIwMDEwMjAx"
+			+ "MTM0NDI1WhgPMjAwNTAzMjIwODU1NTFaMG8xCzAJBgNVBAYTAkRFMT0wOwYD"
+			+ "VQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0"
+			+ "aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNhIDE6"
+			+ "UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvthihnl"
+			+ "tsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wdbPvg"
+			+ "JyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCAOXFw"
+			+ "VWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIFAAOB"
+			+ "gQBpSRdnDb6AcNVaXSmGo6+kVPIBhot1LzJOGaPyDNpGXxd7LV4tMBF1U7gr"
+			+ "4k1g9BO6YiMWvw9uiTZmn0CfV8+k4fWEuG/nmafRoGIuay2f+ILuT+C0rnp1"
+			+ "4FgMsEhuVNJJAmb12QV0PZII+UneyhAneZuQQzVUkTcVgYxogxdSOzCCAlUw"
+			+ "ggHBoAMCAQICBACdekowCgYGKyQDAwECBQAwbzELMAkGA1UEBhMCREUxPTA7"
+			+ "BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlr"
+			+ "YXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNlItQ2Eg"
+			+ "MTpQTjAiGA8yMDAxMDIwMTEzNDcwN1oYDzIwMDUwMzIyMDg1NTUxWjBvMQsw"
+			+ "CQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1"
+			+ "ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEw"
+			+ "EQYDVQQDFAo1Ui1DQSAxOlBOMIGhMA0GCSqGSIb3DQEBAQUAA4GPADCBiwKB"
+			+ "gQCKHkFTJx8GmoqFTxEOxpK9XkC3NZ5dBEKiUv0Ife3QMqeGMoCUnyJxwW0k"
+			+ "2/53duHxtv2yHSZpFKjrjvE/uGwdOMqBMTjMzkFg19e9JPv061wyADOucOIa"
+			+ "NAgha/zFt9XUyrHF21knKCvDNExv2MYIAagkTKajLMAw0bu1J0FadQIFAMAA"
+			+ "AAEwCgYGKyQDAwECBQADgYEAV1yTi+2gyB7sUhn4PXmi/tmBxAfe5oBjDW8m"
+			+ "gxtfudxKGZ6l/FUPNcrSc5oqBYxKWtLmf3XX87LcblYsch617jtNTkMzhx9e"
+			+ "qxiD02ufcrxz2EVt0Akdqiz8mdVeqp3oLcNU/IttpSrcA91CAnoUXtDZYwb/"
+			+ "gdQ4FI9l3+qo/0UwggJVMIIBwaADAgECAgQAxIymMAoGBiskAwMBAgUAMG8x"
+			+ "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm"
+			+ "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB"
+			+ "MTARBgNVBAMUCjZSLUNhIDE6UE4wIhgPMjAwMTEwMTUxMzMxNThaGA8yMDA1"
+			+ "MDYwMTA5NTIxN1owbzELMAkGA1UEBhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVy"
+			+ "dW5nc2JlaMhvcmRlIGbIdXIgVGVsZWtvbW11bmlrYXRpb24gdW5kIFBvc3Qx"
+			+ "ITAMBgcCggYBCgcUEwExMBEGA1UEAxQKN1ItQ0EgMTpQTjCBoTANBgkqhkiG"
+			+ "9w0BAQEFAAOBjwAwgYsCgYEAiokD/j6lEP4FexF356OpU5teUpGGfUKjIrFX"
+			+ "BHc79G0TUzgVxqMoN1PWnWktQvKo8ETaugxLkP9/zfX3aAQzDW4Zki6x6GDq"
+			+ "fy09Agk+RJvhfbbIzRkV4sBBco0n73x7TfG/9NTgVr/96U+I+z/1j30aboM6"
+			+ "9OkLEhjxAr0/GbsCBQDAAAABMAoGBiskAwMBAgUAA4GBAHWRqRixt+EuqHhR"
+			+ "K1kIxKGZL2vZuakYV0R24Gv/0ZR52FE4ECr+I49o8FP1qiGSwnXB0SwjuH2S"
+			+ "iGiSJi+iH/MeY85IHwW1P5e+bOMvEOFhZhQXQixOD7totIoFtdyaj1XGYRef"
+			+ "0f2cPOjNJorXHGV8wuBk+/j++sxbd/Net3FtMIICVTCCAcGgAwIBAgIEAMSM"
+			+ "pzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp"
+			+ "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z"
+			+ "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo3Ui1DQSAxOlBOMCIYDzIwMDEx"
+			+ "MDE1MTMzNDE0WhgPMjAwNTA2MDEwOTUyMTdaMG8xCzAJBgNVBAYTAkRFMT0w"
+			+ "OwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5p"
+			+ "a2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjZSLUNh"
+			+ "IDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGLAoGBAIOiqxUkzVyqnvth"
+			+ "ihnltsE5m1Xn5TZKeR/2MQPStc5hJ+V4yptEtIx+Fn5rOoqT5VEVWhcE35wd"
+			+ "bPvgJyQFn5msmhPQT/6XSGOlrWRoFummXN9lQzAjCj1sgTcmoLCVQ5s5WpCA"
+			+ "OXFwVWu16qndz3sPItn3jJ0F3Kh3w79NglvPAgUAwAAAATAKBgYrJAMDAQIF"
+			+ "AAOBgQBi5W96UVDoNIRkCncqr1LLG9vF9SGBIkvFpLDIIbcvp+CXhlvsdCJl"
+			+ "0pt2QEPSDl4cmpOet+CxJTdTuMeBNXxhb7Dvualog69w/+K2JbPhZYxuVFZs"
+			+ "Zh5BkPn2FnbNu3YbJhE60aIkikr72J4XZsI5DxpZCGh6xyV/YPRdKSljFjCC"
+			+ "AlQwggHAoAMCAQICAwyDqzAKBgYrJAMDAQIFADBvMQswCQYDVQQGEwJERTE9"
+			+ "MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVu"
+			+ "aWthdGlvbiB1bmQgUG9zdDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAo1Ui1D"
+			+ "QSAxOlBOMCIYDzIwMDAwMzIyMDk0MTI3WhgPMjAwNDAxMjExNjA0NTNaMG8x"
+			+ "CzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1bGllcnVuZ3NiZWjIb3JkZSBm"
+			+ "yHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0MSEwDAYHAoIGAQoHFBMB"
+			+ "MTARBgNVBAMUCjRSLUNBIDE6UE4wgaEwDQYJKoZIhvcNAQEBBQADgY8AMIGL"
+			+ "AoGBAI8x26tmrFJanlm100B7KGlRemCD1R93PwdnG7svRyf5ZxOsdGrDszNg"
+			+ "xg6ouO8ZHQMT3NC2dH8TvO65Js+8bIyTm51azF6clEg0qeWNMKiiXbBXa+ph"
+			+ "hTkGbXiLYvACZ6/MTJMJ1lcrjpRF7BXtYeYMcEF6znD4pxOqrtbf9z5hAgUA"
+			+ "wAAAATAKBgYrJAMDAQIFAAOBgQB99BjSKlGPbMLQAgXlvA9jUsDNhpnVm3a1"
+			+ "YkfxSqS/dbQlYkbOKvCxkPGA9NBxisBM8l1zFynVjJoy++aysRmcnLY/sHaz"
+			+ "23BF2iU7WERy18H3lMBfYB6sXkfYiZtvQZcWaO48m73ZBySuiV3iXpb2wgs/"
+			+ "Cs20iqroAWxwq/W/9jCCAlMwggG/oAMCAQICBDsFZ9UwCgYGKyQDAwECBQAw"
+			+ "bzELMAkGA1UEBhMCREUxITAMBgcCggYBCgcUEwExMBEGA1UEAxQKNFItQ0Eg"
+			+ "MTpQTjE9MDsGA1UEChQ0UmVndWxpZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxl"
+			+ "a29tbXVuaWthdGlvbiB1bmQgUG9zdDAiGA8xOTk5MDEyMTE3MzUzNFoYDzIw"
+			+ "MDQwMTIxMTYwMDAyWjBvMQswCQYDVQQGEwJERTE9MDsGA1UEChQ0UmVndWxp"
+			+ "ZXJ1bmdzYmVoyG9yZGUgZsh1ciBUZWxla29tbXVuaWthdGlvbiB1bmQgUG9z"
+			+ "dDEhMAwGBwKCBgEKBxQTATEwEQYDVQQDFAozUi1DQSAxOlBOMIGfMA0GCSqG"
+			+ "SIb3DQEBAQUAA4GNADCBiQKBgI4B557mbKQg/AqWBXNJhaT/6lwV93HUl4U8"
+			+ "u35udLq2+u9phns1WZkdM3gDfEpL002PeLfHr1ID/96dDYf04lAXQfombils"
+			+ "of1C1k32xOvxjlcrDOuPEMxz9/HDAQZA5MjmmYHAIulGI8Qg4Tc7ERRtg/hd"
+			+ "0QX0/zoOeXoDSEOBAgTAAAABMAoGBiskAwMBAgUAA4GBAIyzwfT3keHI/n2P"
+			+ "LrarRJv96mCohmDZNpUQdZTVjGu5VQjVJwk3hpagU0o/t/FkdzAjOdfEw8Ql"
+			+ "3WXhfIbNLv1YafMm2eWSdeYbLcbB5yJ1od+SYyf9+tm7cwfDAcr22jNRBqx8"
+			+ "wkWKtKDjWKkevaSdy99sAI8jebHtWz7jzydKMIID9TCCA16gAwIBAgICbMcw"
+			+ "DQYJKoZIhvcNAQEFBQAwSzELMAkGA1UEBhMCREUxEjAQBgNVBAoUCVNpZ250"
+			+ "cnVzdDEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFDQSBTSUdOVFJVU1QgMTpQ"
+			+ "TjAeFw0wNDA3MzAxMzAyNDZaFw0wNzA3MzAxMzAyNDZaMDwxETAPBgNVBAMM"
+			+ "CFlhY29tOlBOMQ4wDAYDVQRBDAVZYWNvbTELMAkGA1UEBhMCREUxCjAIBgNV"
+			+ "BAUTATEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAIWzLlYLQApocXIp"
+			+ "pgCCpkkOUVLgcLYKeOd6/bXAnI2dTHQqT2bv7qzfUnYvOqiNgYdF13pOYtKg"
+			+ "XwXMTNFL4ZOI6GoBdNs9TQiZ7KEWnqnr2945HYx7UpgTBclbOK/wGHuCdcwO"
+			+ "x7juZs1ZQPFG0Lv8RoiV9s6HP7POqh1sO0P/AgMBAAGjggH1MIIB8TCBnAYD"
+			+ "VR0jBIGUMIGRgBQcZzNghfnXoXRm8h1+VITC5caNRqFzpHEwbzELMAkGA1UE"
+			+ "BhMCREUxPTA7BgNVBAoUNFJlZ3VsaWVydW5nc2JlaMhvcmRlIGbIdXIgVGVs"
+			+ "ZWtvbW11bmlrYXRpb24gdW5kIFBvc3QxITAMBgcCggYBCgcUEwExMBEGA1UE"
+			+ "AxQKNVItQ0EgMTpQToIEALs8rjAdBgNVHQ4EFgQU2e5KAzkVuKaM9I5heXkz"
+			+ "bcAIuR8wDgYDVR0PAQH/BAQDAgZAMBIGA1UdIAQLMAkwBwYFKyQIAQEwfwYD"
+			+ "VR0fBHgwdjB0oCygKoYobGRhcDovL2Rpci5zaWdudHJ1c3QuZGUvbz1TaWdu"
+			+ "dHJ1c3QsYz1kZaJEpEIwQDEdMBsGA1UEAxMUQ1JMU2lnblNpZ250cnVzdDE6"
+			+ "UE4xEjAQBgNVBAoTCVNpZ250cnVzdDELMAkGA1UEBhMCREUwYgYIKwYBBQUH"
+			+ "AQEEVjBUMFIGCCsGAQUFBzABhkZodHRwOi8vZGlyLnNpZ250cnVzdC5kZS9T"
+			+ "aWdudHJ1c3QvT0NTUC9zZXJ2bGV0L2h0dHBHYXRld2F5LlBvc3RIYW5kbGVy"
+			+ "MBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYHAoIGAQoMAAQDAQH/MA0G"
+			+ "CSqGSIb3DQEBBQUAA4GBAHn1m3GcoyD5GBkKUY/OdtD6Sj38LYqYCF+qDbJR"
+			+ "6pqUBjY2wsvXepUppEler+stH8mwpDDSJXrJyuzf7xroDs4dkLl+Rs2x+2tg"
+			+ "BjU+ABkBDMsym2WpwgA8LCdymmXmjdv9tULxY+ec2pjSEzql6nEZNEfrU8nt"
+			+ "ZCSCavgqW4TtMYIBejCCAXYCAQEwUTBLMQswCQYDVQQGEwJERTESMBAGA1UE"
+			+ "ChQJU2lnbnRydXN0MSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEUNBIFNJR05U"
+			+ "UlVTVCAxOlBOAgJsxzAJBgUrDgMCGgUAoIGAMBgGCSqGSIb3DQEJAzELBgkq"
+			+ "hkiG9w0BBwEwIwYJKoZIhvcNAQkEMRYEFIYfhPoyfGzkLWWSSLjaHb4HQmaK"
+			+ "MBwGCSqGSIb3DQEJBTEPFw0wNTAzMjQwNzM4MzVaMCEGBSskCAYFMRgWFi92"
+			+ "YXIvZmlsZXMvdG1wXzEvdGVzdDEwDQYJKoZIhvcNAQEFBQAEgYA2IvA8lhVz"
+			+ "VD5e/itUxbFboKxeKnqJ5n/KuO/uBCl1N14+7Z2vtw1sfkIG+bJdp3OY2Cmn"
+			+ "mrQcwsN99Vjal4cXVj8t+DJzFG9tK9dSLvD3q9zT/GQ0kJXfimLVwCa4NaSf"
+			+ "Qsu4xtG0Rav6bCcnzabAkKuNNvKtH8amSRzk870DBg==");
+
+		private static readonly byte[] xtraCounterSig = Base64.Decode(
+			  "MIIR/AYJKoZIhvcNAQcCoIIR7TCCEekCAQExCzAJBgUrDgMCGgUAMBoGCSqG"
+			+ "SIb3DQEHAaANBAtIZWxsbyB3b3JsZKCCDnkwggTPMIIDt6ADAgECAgRDnYD3"
+			+ "MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5U"
+			+ "ZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmlj"
+			+ "YXRpb24gQXV0aG9yaXR5MB4XDTA4MDkxMjExNDMxMloXDTEwMDkxMjExNDMx"
+			+ "MlowgdgxCzAJBgNVBAYTAklUMSIwIAYDVQQKDBlJbnRlc2EgUy5wLkEuLzA1"
+			+ "MjYyODkwMDE0MSowKAYDVQQLDCFCdXNpbmVzcyBDb2xsYWJvcmF0aW9uICYg"
+			+ "U2VjdXJpdHkxHjAcBgNVBAMMFU1BU1NJTUlMSUFOTyBaSUNDQVJESTERMA8G"
+			+ "A1UEBAwIWklDQ0FSREkxFTATBgNVBCoMDE1BU1NJTUlMSUFOTzEcMBoGA1UE"
+			+ "BRMTSVQ6WkNDTVNNNzZIMTRMMjE5WTERMA8GA1UELhMIMDAwMDI1ODUwgaAw"
+			+ "DQYJKoZIhvcNAQEBBQADgY4AMIGKAoGBALeJTjmyFgx1SIP6c2AuB/kuyHo5"
+			+ "j/prKELTALsFDimre/Hxr3wOSet1TdQfFzU8Lu+EJqgfV9cV+cI1yeH1rZs7"
+			+ "lei7L3tX/VR565IywnguX5xwvteASgWZr537Fkws50bvTEMyYOj1Tf3FZvZU"
+			+ "z4n4OD39KI4mfR9i1eEVIxR3AgQAizpNo4IBoTCCAZ0wHQYDVR0RBBYwFIES"
+			+ "emljY2FyZGlAaW50ZXNhLml0MC8GCCsGAQUFBwEDBCMwITAIBgYEAI5GAQEw"
+			+ "CwYGBACORgEDAgEUMAgGBgQAjkYBBDBZBgNVHSAEUjBQME4GBgQAizABATBE"
+			+ "MEIGCCsGAQUFBwIBFjZodHRwOi8vZS10cnVzdGNvbS5pbnRlc2EuaXQvY2Ff"
+			+ "cHViYmxpY2EvQ1BTX0lOVEVTQS5odG0wDgYDVR0PAQH/BAQDAgZAMIGDBgNV"
+			+ "HSMEfDB6gBQZCQOW0bjFWBt+EORuxPagEgkQqKFcpFowWDELMAkGA1UEBhMC"
+			+ "SVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJbi5U"
+			+ "ZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHmCBDzRARMwOwYDVR0f"
+			+ "BDQwMjAwoC6gLIYqaHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L0NSTC9J"
+			+ "TlRFU0EuY3JsMB0GA1UdDgQWBBTf5ItL8KmQh541Dxt7YxcWI1254TANBgkq"
+			+ "hkiG9w0BAQUFAAOCAQEAgW+uL1CVWQepbC/wfCmR6PN37Sueb4xiKQj2mTD5"
+			+ "UZ5KQjpivy/Hbuf0NrfKNiDEhAvoHSPC31ebGiKuTMFNyZPHfPEUnyYGSxea"
+			+ "2w837aXJFr6utPNQGBRi89kH90sZDlXtOSrZI+AzJJn5QK3F9gjcayU2NZXQ"
+			+ "MJgRwYmFyn2w4jtox+CwXPQ9E5XgxiMZ4WDL03cWVXDLX00EOJwnDDMUNTRI"
+			+ "m9Zv+4SKTNlfFbi9UTBqWBySkDzAelsfB2U61oqc2h1xKmCtkGMmN9iZT+Qz"
+			+ "ZC/vaaT+hLEBFGAH2gwFrYc4/jTBKyBYeU1vsAxsibIoTs1Apgl6MH75qPDL"
+			+ "BzCCBM8wggO3oAMCAQICBEOdgPcwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE"
+			+ "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ"
+			+ "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwOTEy"
+			+ "MTE0MzEyWhcNMTAwOTEyMTE0MzEyWjCB2DELMAkGA1UEBhMCSVQxIjAgBgNV"
+			+ "BAoMGUludGVzYSBTLnAuQS4vMDUyNjI4OTAwMTQxKjAoBgNVBAsMIUJ1c2lu"
+			+ "ZXNzIENvbGxhYm9yYXRpb24gJiBTZWN1cml0eTEeMBwGA1UEAwwVTUFTU0lN"
+			+ "SUxJQU5PIFpJQ0NBUkRJMREwDwYDVQQEDAhaSUNDQVJESTEVMBMGA1UEKgwM"
+			+ "TUFTU0lNSUxJQU5PMRwwGgYDVQQFExNJVDpaQ0NNU003NkgxNEwyMTlZMREw"
+			+ "DwYDVQQuEwgwMDAwMjU4NTCBoDANBgkqhkiG9w0BAQEFAAOBjgAwgYoCgYEA"
+			+ "t4lOObIWDHVIg/pzYC4H+S7IejmP+msoQtMAuwUOKat78fGvfA5J63VN1B8X"
+			+ "NTwu74QmqB9X1xX5wjXJ4fWtmzuV6Lsve1f9VHnrkjLCeC5fnHC+14BKBZmv"
+			+ "nfsWTCznRu9MQzJg6PVN/cVm9lTPifg4Pf0ojiZ9H2LV4RUjFHcCBACLOk2j"
+			+ "ggGhMIIBnTAdBgNVHREEFjAUgRJ6aWNjYXJkaUBpbnRlc2EuaXQwLwYIKwYB"
+			+ "BQUHAQMEIzAhMAgGBgQAjkYBATALBgYEAI5GAQMCARQwCAYGBACORgEEMFkG"
+			+ "A1UdIARSMFAwTgYGBACLMAEBMEQwQgYIKwYBBQUHAgEWNmh0dHA6Ly9lLXRy"
+			+ "dXN0Y29tLmludGVzYS5pdC9jYV9wdWJibGljYS9DUFNfSU5URVNBLmh0bTAO"
+			+ "BgNVHQ8BAf8EBAMCBkAwgYMGA1UdIwR8MHqAFBkJA5bRuMVYG34Q5G7E9qAS"
+			+ "CRCooVykWjBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5BLiBT"
+			+ "LnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9uIEF1"
+			+ "dGhvcml0eYIEPNEBEzA7BgNVHR8ENDAyMDCgLqAshipodHRwOi8vZS10cnVz"
+			+ "dGNvbS5pbnRlc2EuaXQvQ1JML0lOVEVTQS5jcmwwHQYDVR0OBBYEFN/ki0vw"
+			+ "qZCHnjUPG3tjFxYjXbnhMA0GCSqGSIb3DQEBBQUAA4IBAQCBb64vUJVZB6ls"
+			+ "L/B8KZHo83ftK55vjGIpCPaZMPlRnkpCOmK/L8du5/Q2t8o2IMSEC+gdI8Lf"
+			+ "V5saIq5MwU3Jk8d88RSfJgZLF5rbDzftpckWvq6081AYFGLz2Qf3SxkOVe05"
+			+ "Ktkj4DMkmflArcX2CNxrJTY1ldAwmBHBiYXKfbDiO2jH4LBc9D0TleDGIxnh"
+			+ "YMvTdxZVcMtfTQQ4nCcMMxQ1NEib1m/7hIpM2V8VuL1RMGpYHJKQPMB6Wx8H"
+			+ "ZTrWipzaHXEqYK2QYyY32JlP5DNkL+9ppP6EsQEUYAfaDAWthzj+NMErIFh5"
+			+ "TW+wDGyJsihOzUCmCXowfvmo8MsHMIIEzzCCA7egAwIBAgIEQ52A9zANBgkq"
+			+ "hkiG9w0BAQUFADBYMQswCQYDVQQGEwJJVDEaMBgGA1UEChMRSW4uVGUuUy5B"
+			+ "LiBTLnAuQS4xLTArBgNVBAMTJEluLlRlLlMuQS4gLSBDZXJ0aWZpY2F0aW9u"
+			+ "IEF1dGhvcml0eTAeFw0wODA5MTIxMTQzMTJaFw0xMDA5MTIxMTQzMTJaMIHY"
+			+ "MQswCQYDVQQGEwJJVDEiMCAGA1UECgwZSW50ZXNhIFMucC5BLi8wNTI2Mjg5"
+			+ "MDAxNDEqMCgGA1UECwwhQnVzaW5lc3MgQ29sbGFib3JhdGlvbiAmIFNlY3Vy"
+			+ "aXR5MR4wHAYDVQQDDBVNQVNTSU1JTElBTk8gWklDQ0FSREkxETAPBgNVBAQM"
+			+ "CFpJQ0NBUkRJMRUwEwYDVQQqDAxNQVNTSU1JTElBTk8xHDAaBgNVBAUTE0lU"
+			+ "OlpDQ01TTTc2SDE0TDIxOVkxETAPBgNVBC4TCDAwMDAyNTg1MIGgMA0GCSqG"
+			+ "SIb3DQEBAQUAA4GOADCBigKBgQC3iU45shYMdUiD+nNgLgf5Lsh6OY/6ayhC"
+			+ "0wC7BQ4pq3vx8a98DknrdU3UHxc1PC7vhCaoH1fXFfnCNcnh9a2bO5Xouy97"
+			+ "V/1UeeuSMsJ4Ll+ccL7XgEoFma+d+xZMLOdG70xDMmDo9U39xWb2VM+J+Dg9"
+			+ "/SiOJn0fYtXhFSMUdwIEAIs6TaOCAaEwggGdMB0GA1UdEQQWMBSBEnppY2Nh"
+			+ "cmRpQGludGVzYS5pdDAvBggrBgEFBQcBAwQjMCEwCAYGBACORgEBMAsGBgQA"
+			+ "jkYBAwIBFDAIBgYEAI5GAQQwWQYDVR0gBFIwUDBOBgYEAIswAQEwRDBCBggr"
+			+ "BgEFBQcCARY2aHR0cDovL2UtdHJ1c3Rjb20uaW50ZXNhLml0L2NhX3B1YmJs"
+			+ "aWNhL0NQU19JTlRFU0EuaHRtMA4GA1UdDwEB/wQEAwIGQDCBgwYDVR0jBHww"
+			+ "eoAUGQkDltG4xVgbfhDkbsT2oBIJEKihXKRaMFgxCzAJBgNVBAYTAklUMRow"
+			+ "GAYDVQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5B"
+			+ "LiAtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ80QETMDsGA1UdHwQ0MDIw"
+			+ "MKAuoCyGKmh0dHA6Ly9lLXRydXN0Y29tLmludGVzYS5pdC9DUkwvSU5URVNB"
+			+ "LmNybDAdBgNVHQ4EFgQU3+SLS/CpkIeeNQ8be2MXFiNdueEwDQYJKoZIhvcN"
+			+ "AQEFBQADggEBAIFvri9QlVkHqWwv8Hwpkejzd+0rnm+MYikI9pkw+VGeSkI6"
+			+ "Yr8vx27n9Da3yjYgxIQL6B0jwt9XmxoirkzBTcmTx3zxFJ8mBksXmtsPN+2l"
+			+ "yRa+rrTzUBgUYvPZB/dLGQ5V7Tkq2SPgMySZ+UCtxfYI3GslNjWV0DCYEcGJ"
+			+ "hcp9sOI7aMfgsFz0PROV4MYjGeFgy9N3FlVwy19NBDicJwwzFDU0SJvWb/uE"
+			+ "ikzZXxW4vVEwalgckpA8wHpbHwdlOtaKnNodcSpgrZBjJjfYmU/kM2Qv72mk"
+			+ "/oSxARRgB9oMBa2HOP40wSsgWHlNb7AMbImyKE7NQKYJejB++ajwywcxggM8"
+			+ "MIIDOAIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYDVQQKExFJbi5UZS5TLkEu"
+			+ "IFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAtIENlcnRpZmljYXRpb24g"
+			+ "QXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJKoZIhvcNAQEBBQAEgYB+"
+			+ "lH2cwLqc91mP8prvgSV+RRzk13dJdZvdoVjgQoFrPhBiZCNIEoHvIhMMA/sM"
+			+ "X6euSRZk7EjD24FasCEGYyd0mJVLEy6TSPmuW+wWz/28w3a6IWXBGrbb/ild"
+			+ "/CJMkPgLPGgOVD1WDwiNKwfasiQSFtySf5DPn3jFevdLeMmEY6GCAjIwggEV"
+			+ "BgkqhkiG9w0BCQYxggEGMIIBAgIBATBgMFgxCzAJBgNVBAYTAklUMRowGAYD"
+			+ "VQQKExFJbi5UZS5TLkEuIFMucC5BLjEtMCsGA1UEAxMkSW4uVGUuUy5BLiAt"
+			+ "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5AgRDnYD3MAkGBSsOAwIaBQAwDQYJ"
+			+ "KoZIhvcNAQEBBQAEgYBHlOULfT5GDigIvxP0qZOy8VbpntmzaPF55VV4buKV"
+			+ "35J+uHp98gXKp0LrHM69V5IRKuyuQzHHFBqsXxsRI9o6KoOfgliD9Xc+BeMg"
+			+ "dKzQhBhBYoFREq8hQM0nSbqDNHYAQyNHMzUA/ZQUO5dlFuH8Dw3iDYAhNtfd"
+			+ "PrlchKJthDCCARUGCSqGSIb3DQEJBjGCAQYwggECAgEBMGAwWDELMAkGA1UE"
+			+ "BhMCSVQxGjAYBgNVBAoTEUluLlRlLlMuQS4gUy5wLkEuMS0wKwYDVQQDEyRJ"
+			+ "bi5UZS5TLkEuIC0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkCBEOdgPcwCQYF"
+			+ "Kw4DAhoFADANBgkqhkiG9w0BAQEFAASBgEeU5Qt9PkYOKAi/E/Spk7LxVume"
+			+ "2bNo8XnlVXhu4pXfkn64en3yBcqnQusczr1XkhEq7K5DMccUGqxfGxEj2joq"
+			+ "g5+CWIP1dz4F4yB0rNCEGEFigVESryFAzSdJuoM0dgBDI0czNQD9lBQ7l2UW"
+			+ "4fwPDeINgCE2190+uVyEom2E");
+
+		private void VerifySignatures(
+			CmsSignedData	s,
+			byte[]			contentDigest)
+		{
+			IX509Store x509Certs = s.GetCertificates("Collection");
+
+			SignerInformationStore signers = s.GetSignerInfos();
+			ICollection c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+
+				if (contentDigest != null)
+				{
+					Assert.IsTrue(Arrays.AreEqual(contentDigest, signer.GetContentDigest()));
+				}
+			}
+		}
+
+		private void VerifySignatures(
+			CmsSignedData s)
+		{
+			VerifySignatures(s, null);
+		}
+
+		[Test]
+		public void TestDetachedVerification()
+		{
+			byte[] data = Encoding.ASCII.GetBytes("Hello World!");
+			CmsProcessable msg = new CmsProcessableByteArray(data);
+
+			IList certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData s = gen.Generate(msg);
+
+			IDictionary hashes = new Hashtable();
+			hashes.Add(CmsSignedDataGenerator.DigestSha1, CalculateHash("SHA1", data));
+			hashes.Add(CmsSignedDataGenerator.DigestMD5, CalculateHash("MD5", data));
+
+			s = new CmsSignedData(hashes, s.GetEncoded());
+
+			VerifySignatures(s, null);
+		}
+
+		private byte[] CalculateHash(
+			string	digestName,
+			byte[]	data)
+		{
+			IDigest digest = DigestUtilities.GetDigest(digestName);
+			digest.BlockUpdate(data, 0, data.Length);
+			return DigestUtilities.DoFinal(digest);
+		}
+
+		[Test]
+		public void TestSha1AndMD5WithRsaEncapsulatedRepeated()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestMD5);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData s = gen.Generate(msg, true);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
+
+			x509Certs = s.GetCertificates("Collection");
+
+			SignerInformationStore signers = s.GetSignerInfos();
+
+			Assert.AreEqual(2, signers.Count);
+
+			SignerID sid = null;
+			ICollection c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				sid = signer.SignerID;
+
+				Assert.IsTrue(signer.Verify(cert));
+
+				//
+				// check content digest
+				//
+
+				byte[] contentDigest = (byte[])gen.GetGeneratedDigests()[signer.DigestAlgOid];
+
+				AttributeTable table = signer.SignedAttributes;
+				Asn1.Cms.Attribute hash = table[CmsAttributes.MessageDigest];
+
+				Assert.IsTrue(Arrays.AreEqual(contentDigest, ((Asn1OctetString)hash.AttrValues[0]).GetOctets()));
+			}
+
+			c = signers.GetSigners(sid);
+
+			Assert.AreEqual(2, c.Count);
+
+			//
+			// try using existing signer
+			//
+
+			gen = new CmsSignedDataGenerator();
+
+			gen.AddSigners(s.GetSignerInfos());
+
+			gen.AddCertificates(s.GetCertificates("Collection"));
+			gen.AddCrls(s.GetCrls("Collection"));
+
+			s = gen.Generate(msg, true);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
+
+			x509Certs = s.GetCertificates("Collection");
+
+			signers = s.GetSignerInfos();
+			c = signers.GetSigners();
+
+			Assert.AreEqual(2, c.Count);
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.AreEqual(true, signer.Verify(cert));
+			}
+
+			CheckSignerStoreReplacement(s, signers);
+		}
+
+		// NB: C# build doesn't support "no attributes" version of CmsSignedDataGenerator.Generate
+//		[Test]
+//		public void TestSha1WithRsaNoAttributes()
+//		{
+//			IList certList = new ArrayList();
+//			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello world!"));
+//
+//			certList.Add(OrigCert);
+//			certList.Add(SignCert);
+//
+//			IX509Store x509Certs = X509StoreFactory.Create(
+//				"Certificate/Collection",
+//				new X509CollectionStoreParameters(certList));
+//
+//			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+//
+//			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+//
+//			gen.AddCertificates(x509Certs);
+//
+//			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false, false);
+//
+//			//
+//			// compute expected content digest
+//			//
+//			IDigest md = DigestUtilities.GetDigest("SHA1");
+//
+//			byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!");
+//			md.BlockUpdate(testBytes, 0, testBytes.Length);
+//			byte[] hash = DigestUtilities.DoFinal(md);
+//
+//			VerifySignatures(s, hash);
+//		}
+
+		[Test]
+		public void TestSha1WithRsaAndAttributeTable()
+		{
+			byte[] testBytes = Encoding.ASCII.GetBytes("Hello world!");
+
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(testBytes);
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			IDigest md = DigestUtilities.GetDigest("SHA1");
+			md.BlockUpdate(testBytes, 0, testBytes.Length);
+			byte[] hash = DigestUtilities.DoFinal(md);
+
+			Asn1.Cms.Attribute attr = new Asn1.Cms.Attribute(CmsAttributes.MessageDigest,
+				new DerSet(new DerOctetString(hash)));
+
+			Asn1EncodableVector v = new Asn1EncodableVector(attr);
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1,
+				new AttributeTable(v), null);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, null, false);
+
+			//
+			// the signature is detached, so need to add msg before passing on
+			//
+			s = new CmsSignedData(msg, s.GetEncoded());
+
+			//
+			// compute expected content digest
+			//
+			VerifySignatures(s, hash);
+		}
+
+		[Test]
+		public void TestSha1WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestSha1WithRsaEncapsulatedSubjectKeyID()
+		{
+			SubjectKeyIDTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestSha1WithRsaPss()
+		{
+			rsaPssTest("SHA1", CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestSha224WithRsaPss()
+		{
+			rsaPssTest("SHA224", CmsSignedDataGenerator.DigestSha224);
+		}
+
+		[Test]
+		public void TestSha256WithRsaPss()
+		{
+			rsaPssTest("SHA256", CmsSignedDataGenerator.DigestSha256);
+		}
+
+		[Test]
+		public void TestSha384WithRsaPss()
+		{
+			rsaPssTest("SHA384", CmsSignedDataGenerator.DigestSha384);
+		}
+
+		[Test]
+		public void TestSha224WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha224);
+		}
+
+		[Test]
+		public void TestSha256WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestSha256);
+		}
+
+		[Test]
+		public void TestRipeMD128WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD128);
+		}
+
+		[Test]
+		public void TestRipeMD160WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD160);
+		}
+
+		[Test]
+		public void TestRipeMD256WithRsaEncapsulated()
+		{
+			EncapsulatedTest(SignKP, SignCert, CmsSignedDataGenerator.DigestRipeMD256);
+		}
+
+		[Test]
+		public void TestECDsaEncapsulated()
+		{
+			EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestECDsaEncapsulatedSubjectKeyID()
+		{
+			SubjectKeyIDTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestECDsaSha224Encapsulated()
+		{
+			EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha224);
+		}
+
+		[Test]
+		public void TestECDsaSha256Encapsulated()
+		{
+			EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha256);
+		}
+
+		[Test]
+		public void TestECDsaSha384Encapsulated()
+		{
+			EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha384);
+		}
+
+		[Test]
+		public void TestECDsaSha512Encapsulated()
+		{
+			EncapsulatedTest(SignECDsaKP, SignECDsaCert, CmsSignedDataGenerator.DigestSha512);
+		}
+
+		[Test]
+		public void TestECDsaSha512EncapsulatedWithKeyFactoryAsEC()
+		{
+//			X509EncodedKeySpec  pubSpec = new X509EncodedKeySpec(_signEcDsaKP.getPublic().getEncoded());
+			byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(SignECDsaKP.Public).GetDerEncoded();
+//			PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(_signEcDsaKP.Private.getEncoded());
+			byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(SignECDsaKP.Private).GetDerEncoded();
+//			KeyFactory          keyFact = KeyFactory.GetInstance("EC", "BC");
+//			KeyPair             kp = new KeyPair(keyFact.generatePublic(pubSpec), keyFact.generatePrivate(privSpec));
+			AsymmetricCipherKeyPair kp = new AsymmetricCipherKeyPair(
+                PublicKeyFactory.CreateKey(pubEnc),
+				PrivateKeyFactory.CreateKey(privEnc));
+
+			EncapsulatedTest(kp, SignECDsaCert, CmsSignedDataGenerator.DigestSha512);
+		}
+
+		[Test]
+		public void TestDsaEncapsulated()
+		{
+			EncapsulatedTest(SignDsaKP, SignDsaCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestDsaEncapsulatedSubjectKeyID()
+		{
+			SubjectKeyIDTest(SignDsaKP, SignDsaCert, CmsSignedDataGenerator.DigestSha1);
+		}
+
+		[Test]
+		public void TestGost3411WithGost3410Encapsulated()
+		{
+			EncapsulatedTest(SignGostKP, SignGostCert, CmsSignedDataGenerator.DigestGost3411);
+		}
+
+		[Test]
+		public void TestGost3411WithECGost3410Encapsulated()
+		{
+			EncapsulatedTest(SignECGostKP, SignECGostCert, CmsSignedDataGenerator.DigestGost3411);
+		}
+
+		[Test]
+		public void TestSha1WithRsaCounterSignature()
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(SignCert);
+			certList.Add(OrigCert);
+
+			crlList.Add(SignCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(SignKP.Private, SignCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			CmsSignedData s = gen.Generate(msg, true);
+			SignerInformation origSigner = (SignerInformation) new ArrayList(s.GetSignerInfos().GetSigners())[0];
+			SignerInformationStore counterSigners1 = gen.GenerateCounterSigners(origSigner);
+			SignerInformationStore counterSigners2 = gen.GenerateCounterSigners(origSigner);
+
+			SignerInformation signer1 = SignerInformation.AddCounterSigners(origSigner, counterSigners1);
+			SignerInformation signer2 = SignerInformation.AddCounterSigners(signer1, counterSigners2);
+
+			SignerInformationStore cs = signer2.GetCounterSignatures();
+			ICollection csSigners = cs.GetSigners();
+			Assert.AreEqual(2, csSigners.Count);
+
+			foreach (SignerInformation cSigner in csSigners)
+			{
+				ICollection certCollection = x509Certs.GetMatches(cSigner.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsNull(cSigner.SignedAttributes[Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtContentType]);
+				Assert.IsTrue(cSigner.Verify(cert));
+			}
+		}
+
+		private void rsaPssTest(
+			string	digestName,
+			string	digestOID)
+		{
+			IList certList = new ArrayList();
+			byte[] msgBytes = Encoding.ASCII.GetBytes("Hello World!");
+			CmsProcessable msg = new CmsProcessableByteArray(msgBytes);
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.EncryptionRsaPss, digestOID);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData s = gen.Generate(CmsSignedDataGenerator.Data, msg, false);
+
+			//
+			// compute expected content digest
+			//
+			IDigest md = DigestUtilities.GetDigest(digestName);
+			md.BlockUpdate(msgBytes, 0, msgBytes.Length);
+			byte[] expectedDigest = DigestUtilities.DoFinal(md);
+
+			VerifySignatures(s, expectedDigest);
+		}
+
+		private void SubjectKeyIDTest(
+			AsymmetricCipherKeyPair	signaturePair,
+			X509Certificate			signatureCert,
+			string					digestAlgorithm)
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(signatureCert);
+			certList.Add(OrigCert);
+
+			crlList.Add(SignCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(signaturePair.Private,
+				CmsTestUtil.CreateSubjectKeyId(signatureCert.GetPublicKey()).GetKeyIdentifier(),
+				digestAlgorithm);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			CmsSignedData s = gen.Generate(msg, true);
+
+			Assert.AreEqual(3, s.Version);
+
+			MemoryStream bIn = new MemoryStream(s.GetEncoded(), false);
+			Asn1InputStream aIn = new Asn1InputStream(bIn);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+
+			x509Certs = s.GetCertificates("Collection");
+			x509Crls = s.GetCrls("Collection");
+
+			SignerInformationStore signers = s.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+
+			//
+			// check for CRLs
+			//
+			ArrayList crls = new ArrayList(x509Crls.GetMatches(null));
+
+			Assert.AreEqual(1, crls.Count);
+
+			Assert.IsTrue(crls.Contains(SignCrl));
+
+			//
+			// try using existing signer
+			//
+
+			gen = new CmsSignedDataGenerator();
+
+			gen.AddSigners(s.GetSignerInfos());
+
+			gen.AddCertificates(s.GetCertificates("Collection"));
+			gen.AddCrls(s.GetCrls("Collection"));
+
+			s = gen.Generate(msg, true);
+
+			bIn = new MemoryStream(s.GetEncoded(), false);
+			aIn = new Asn1InputStream(bIn);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(aIn.ReadObject()));
+
+			x509Certs = s.GetCertificates("Collection");
+			x509Crls = s.GetCrls("Collection");
+
+			signers = s.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+
+			CheckSignerStoreReplacement(s, signers);
+		}
+
+		private void EncapsulatedTest(
+			AsymmetricCipherKeyPair	signaturePair,
+			X509Certificate			signatureCert,
+			string					digestAlgorithm)
+		{
+			IList certList = new ArrayList();
+			IList crlList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(signatureCert);
+			certList.Add(OrigCert);
+
+			crlList.Add(SignCrl);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+			IX509Store x509Crls = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(signaturePair.Private, signatureCert, digestAlgorithm);
+
+			gen.AddCertificates(x509Certs);
+			gen.AddCrls(x509Crls);
+
+			CmsSignedData s = gen.Generate(msg, true);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
+
+			x509Certs = s.GetCertificates("Collection");
+			x509Crls = s.GetCrls("Collection");
+
+			SignerInformationStore signers = s.GetSignerInfos();
+			ICollection c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+
+			//
+			// check for CRLs
+			//
+			ArrayList crls = new ArrayList(x509Crls.GetMatches(null));
+
+			Assert.AreEqual(1, crls.Count);
+
+			Assert.IsTrue(crls.Contains(SignCrl));
+
+			//
+			// try using existing signer
+			//
+
+			gen = new CmsSignedDataGenerator();
+
+			gen.AddSigners(s.GetSignerInfos());
+
+			gen.AddCertificates(s.GetCertificates("Collection"));
+			gen.AddCrls(s.GetCrls("Collection"));
+
+			s = gen.Generate(msg, true);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
+
+			x509Certs = s.GetCertificates("Collection");
+			x509Crls = s.GetCrls("Collection");
+
+			signers = s.GetSignerInfos();
+			c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+
+			CheckSignerStoreReplacement(s, signers);
+		}
+
+		//
+		// signerInformation store replacement test.
+		//
+		private void CheckSignerStoreReplacement(
+			CmsSignedData orig,
+			SignerInformationStore signers)
+		{
+			CmsSignedData s = CmsSignedData.ReplaceSigners(orig, signers);
+
+			IX509Store x509Certs = s.GetCertificates("Collection");
+
+			signers = s.GetSignerInfos();
+			ICollection c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+		}
+
+		[Test]
+		public void TestUnsortedAttributes()
+		{
+			CmsSignedData s = new CmsSignedData(new CmsProcessableByteArray(disorderedMessage), disorderedSet);
+
+			IX509Store x509Certs = s.GetCertificates("Collection");
+
+			SignerInformationStore	signers = s.GetSignerInfos();
+			ICollection				c = signers.GetSigners();
+
+			foreach (SignerInformation signer in c)
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate) certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+		}
+
+		[Test]
+		public void TestNullContentWithSigner()
+		{
+			IList certList = new ArrayList();
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData s = gen.Generate(null, false);
+
+			s = new CmsSignedData(ContentInfo.GetInstance(Asn1Object.FromByteArray(s.GetEncoded())));
+
+			VerifySignatures(s);
+		}
+
+		[Test]
+		public void TestWithAttributeCertificate()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(SignDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			IX509AttributeCertificate attrCert = CmsTestUtil.GetAttributeCertificate();
+
+			ArrayList attrCerts = new ArrayList();
+			attrCerts.Add(attrCert);
+
+			IX509Store store = X509StoreFactory.Create(
+				"AttributeCertificate/Collection",
+				new X509CollectionStoreParameters(attrCerts));
+
+			gen.AddAttributeCertificates(store);
+
+			CmsSignedData sd = gen.Generate(msg);
+
+			Assert.AreEqual(4, sd.Version);
+
+			store = sd.GetAttributeCertificates("Collection");
+
+			ArrayList coll = new ArrayList(store.GetMatches(null));
+
+			Assert.AreEqual(1, coll.Count);
+
+			Assert.IsTrue(coll.Contains(attrCert));
+
+			//
+			// create new certstore
+			//
+			certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// replace certs
+			//
+			sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null);
+
+			VerifySignatures(sd);
+		}
+
+		[Test]
+		public void TestCertStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(SignDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData sd = gen.Generate(msg);
+
+			//
+			// create new certstore
+			//
+			certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// replace certs
+			//
+			sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null);
+
+			VerifySignatures(sd);
+		}
+
+		[Test]
+		public void TestEncapsulatedCertStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(SignDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData sd = gen.Generate(msg, true);
+
+			//
+			// create new certstore
+			//
+			certList = new ArrayList();
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			//
+			// replace certs
+			//
+			sd = CmsSignedData.ReplaceCertificatesAndCrls(sd, x509Certs, null, null);
+
+			VerifySignatures(sd);
+		}
+
+		[Test]
+		public void TestCertOrdering1()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+			certList.Add(SignDsaCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData sd = gen.Generate(msg, true);
+
+			x509Certs = sd.GetCertificates("Collection");
+			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
+
+			Assert.AreEqual(3, a.Count);
+			Assert.AreEqual(OrigCert, a[0]);
+			Assert.AreEqual(SignCert, a[1]);
+			Assert.AreEqual(SignDsaCert, a[2]);
+		}
+
+		[Test]
+		public void TestCertOrdering2()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(SignCert);
+			certList.Add(SignDsaCert);
+			certList.Add(OrigCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+	
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData sd = gen.Generate(msg, true);
+
+			x509Certs = sd.GetCertificates("Collection");
+			ArrayList a = new ArrayList(x509Certs.GetMatches(null));
+
+			Assert.AreEqual(3, a.Count);
+			Assert.AreEqual(SignCert, a[0]);
+			Assert.AreEqual(SignDsaCert, a[1]);
+			Assert.AreEqual(OrigCert, a[2]);
+		}
+
+		[Test]
+		public void TestSignerStoreReplacement()
+		{
+			IList certList = new ArrayList();
+			CmsProcessable msg = new CmsProcessableByteArray(Encoding.ASCII.GetBytes("Hello World!"));
+
+			certList.Add(OrigCert);
+			certList.Add(SignCert);
+
+			IX509Store x509Certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			CmsSignedDataGenerator gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha1);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData original = gen.Generate(msg, true);
+
+			//
+			// create new Signer
+			//
+			gen = new CmsSignedDataGenerator();
+
+			gen.AddSigner(OrigKP.Private, OrigCert, CmsSignedDataGenerator.DigestSha224);
+
+			gen.AddCertificates(x509Certs);
+
+			CmsSignedData newSD = gen.Generate(msg, true);
+
+			//
+			// replace signer
+			//
+			CmsSignedData sd = CmsSignedData.ReplaceSigners(original, newSD.GetSignerInfos());
+
+			IEnumerator signerEnum = sd.GetSignerInfos().GetSigners().GetEnumerator();
+			signerEnum.MoveNext();
+			SignerInformation signer = (SignerInformation) signerEnum.Current;
+
+			Assert.AreEqual(CmsSignedDataGenerator.DigestSha224, signer.DigestAlgOid);
+
+			// we use a parser here as it requires the digests to be correct in the digest set, if it
+			// isn't we'll get a NullPointerException
+			CmsSignedDataParser sp = new CmsSignedDataParser(sd.GetEncoded());
+
+			sp.GetSignedContent().Drain();
+
+			VerifySignatures(sp);
+		}
+
+		[Test]
+		public void TestEncapsulatedSamples()
+		{
+			doTestSample("PSSSignDataSHA1Enc.sig");
+			doTestSample("PSSSignDataSHA256Enc.sig");
+			doTestSample("PSSSignDataSHA512Enc.sig");
+		}
+
+		[Test]
+		public void TestSamples()
+		{
+			doTestSample("PSSSignData.data", "PSSSignDataSHA1.sig");
+			doTestSample("PSSSignData.data", "PSSSignDataSHA256.sig");
+			doTestSample("PSSSignData.data", "PSSSignDataSHA512.sig");
+		}
+
+		[Test]
+		public void TestCounterSig()
+		{
+			CmsSignedData sig = new CmsSignedData(GetInput("counterSig.p7m"));
+
+			SignerInformationStore ss = sig.GetSignerInfos();
+			ArrayList signers = new ArrayList(ss.GetSigners());
+
+			SignerInformationStore cs = ((SignerInformation)signers[0]).GetCounterSignatures();
+			ArrayList csSigners = new ArrayList(cs.GetSigners());
+			Assert.AreEqual(1, csSigners.Count);
+
+			foreach (SignerInformation cSigner in csSigners)
+			{
+				ArrayList certCollection = new ArrayList(
+					sig.GetCertificates("Collection").GetMatches(cSigner.SignerID));
+
+				X509Certificate cert = (X509Certificate)certCollection[0];
+
+				Assert.IsNull(cSigner.SignedAttributes[Asn1.Pkcs.PkcsObjectIdentifiers.Pkcs9AtContentType]);
+				Assert.IsTrue(cSigner.Verify(cert));
+			}
+
+			VerifySignatures(sig);
+		}
+
+		private void doTestSample(
+			string sigName)
+		{
+			CmsSignedData sig = new CmsSignedData(GetInput(sigName));
+			VerifySignatures(sig);
+		}
+
+		private void doTestSample(
+			string	messageName,
+			string	sigName)
+		{
+			CmsSignedData sig = new CmsSignedData(
+				new CmsProcessableByteArray(GetInput(messageName)),
+				GetInput(sigName));
+
+			VerifySignatures(sig);
+		}
+
+		private byte[] GetInput(
+			string name)
+		{
+			return Streams.ReadAll(SimpleTest.GetTestDataAsStream("cms.sigs." + name));
+		}
+
+		[Test]
+		public void TestForMultipleCounterSignatures()
+		{
+			CmsSignedData sd = new CmsSignedData(xtraCounterSig);
+
+			foreach (SignerInformation sigI in sd.GetSignerInfos().GetSigners())
+			{
+				SignerInformationStore counter = sigI.GetCounterSignatures();
+				IList sigs = new ArrayList(counter.GetSigners());
+
+				Assert.AreEqual(2, sigs.Count);
+			}
+		}
+
+		private void VerifySignatures(
+			CmsSignedDataParser sp)
+		{
+			IX509Store x509Certs = sp.GetCertificates("Collection");
+			SignerInformationStore signers = sp.GetSignerInfos();
+
+			foreach (SignerInformation signer in signers.GetSigners())
+			{
+				ICollection certCollection = x509Certs.GetMatches(signer.SignerID);
+
+				IEnumerator certEnum = certCollection.GetEnumerator();
+				certEnum.MoveNext();
+				X509Certificate cert = (X509Certificate)certEnum.Current;
+
+				Assert.IsTrue(signer.Verify(cert));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/examples/DESExample.cs b/BouncyCastle.AxCrypt/test/src/crypto/examples/DESExample.cs
new file mode 100644
index 0000000..c026d31
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/examples/DESExample.cs
@@ -0,0 +1,396 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Examples
+{
+	/**
+	* DesExample is a simple DES based encryptor/decryptor.
+	* <p>
+	* The program is command line driven, with the input
+	* and output files specified on the command line.
+	* <pre>
+	* java org.bouncycastle.crypto.examples.DesExample infile outfile [keyfile]
+	* </pre>
+	* A new key is generated for each encryption, if key is not specified,
+	* then the example will assume encryption is required, and as output
+	* create deskey.dat in the current directory.  This key is a hex
+	* encoded byte-stream that is used for the decryption.  The output
+	* file is Hex encoded, 60 characters wide text file.
+	* </p>
+	* <p>
+	* When encrypting;
+	* <ul>
+	*  <li>the infile is expected to be a byte stream (text or binary)</li>
+	*  <li>there is no keyfile specified on the input line</li>
+	* </ul>
+	* </p>
+	* <p>
+	* When decrypting;
+	*  <li>the infile is expected to be the 60 character wide base64 
+	*    encoded file</li>
+	*  <li>the keyfile is expected to be a base64 encoded file</li>
+	* </p>
+	* <p>
+	* This example shows how to use the light-weight API, DES and
+	* the filesystem for message encryption and decryption.
+	* </p>
+	*/
+	public class DesExample
+	{
+		// Encrypting or decrypting ?
+		private bool encrypt = true;
+
+		// To hold the initialised DESede cipher
+		private PaddedBufferedBlockCipher cipher = null;
+
+		// The input stream of bytes to be processed for encryption
+		private Stream inStr = null;
+
+		// The output stream of bytes to be procssed
+		private Stream outStr = null;
+
+		// The key
+		private byte[] key = null;
+
+		/*
+		* start the application
+		*/
+		public static int Main(
+			string[] args)
+		{
+			bool encrypt = true;
+			string infile = null;
+			string outfile = null;
+			string keyfile = null;
+
+			if (args.Length < 2)
+			{
+//				Console.Error.WriteLine("Usage: java " + typeof(DesExample).Name + " infile outfile [keyfile]");
+				Console.Error.WriteLine("Usage: " + typeof(DesExample).Name + " infile outfile [keyfile]");
+				return 1;
+			}
+
+			keyfile = "deskey.dat";
+			infile = args[0];
+			outfile = args[1];
+
+			if (args.Length > 2)
+			{
+				encrypt = false;
+				keyfile = args[2];
+			}
+
+			try
+			{
+				DesExample de = new DesExample(infile, outfile, keyfile, encrypt);
+				de.process();
+			}
+			catch (Exception)
+			{
+				return 1;
+			}
+
+			return 0;
+		}
+
+		// Default constructor, used for the usage message
+		public DesExample()
+		{
+		}
+
+		/*
+		* Constructor, that takes the arguments appropriate for
+		* processing the command line directives.
+		*/
+		public DesExample(
+			string	infile,
+			string	outfile,
+			string	keyfile,
+			bool	encrypt)
+		{
+			/* 
+			* First, determine that infile & keyfile exist as appropriate.
+			*
+			* This will also create the BufferedInputStream as required
+			* for reading the input file.  All input files are treated
+			* as if they are binary, even if they contain text, it's the
+			* bytes that are encrypted.
+			*/
+			this.encrypt = encrypt;
+			try
+			{
+				inStr = File.OpenRead(infile);
+			}
+			catch (FileNotFoundException e)
+			{
+				Console.Error.WriteLine("Input file not found ["+infile+"]");
+				throw e;
+			}
+
+			try
+			{
+				outStr = File.Create(outfile);
+			}
+			catch (IOException e)
+			{
+				Console.Error.WriteLine("Output file not created ["+outfile+"]");
+				throw e;
+			}
+
+			if (encrypt)
+			{
+				try
+				{
+					/*
+					* The process of creating a new key requires a 
+					* number of steps.
+					*
+					* First, create the parameters for the key generator
+					* which are a secure random number generator, and
+					* the length of the key (in bits).
+					*/
+					SecureRandom sr = new SecureRandom();
+
+					KeyGenerationParameters kgp = new KeyGenerationParameters(
+						sr, 
+						DesEdeParameters.DesEdeKeyLength * 8);
+
+					/*
+					* Second, initialise the key generator with the parameters
+					*/
+					DesEdeKeyGenerator kg = new DesEdeKeyGenerator();
+					kg.Init(kgp);
+
+					/*
+					* Third, and finally, generate the key
+					*/
+					key = kg.GenerateKey();
+
+					/*
+					* We can now output the key to the file, but first
+					* hex Encode the key so that we can have a look
+					* at it with a text editor if we so desire
+					*/
+					using (Stream keystream = File.Create(keyfile))
+					{
+						Hex.Encode(key, keystream);
+					}
+				}
+				catch (IOException e)
+				{
+					Console.Error.WriteLine("Could not decryption create key file "+
+										"["+keyfile+"]");
+					throw e;
+				}
+			}
+			else
+			{
+				try
+				{
+					// TODO This block is a bit dodgy
+
+					// read the key, and Decode from hex encoding
+					Stream keystream = File.OpenRead(keyfile);
+//					int len = keystream.available();
+					int len = (int) keystream.Length;
+					byte[] keyhex = new byte[len];
+					keystream.Read(keyhex, 0, len);
+					key = Hex.Decode(keyhex);
+				}
+				catch (IOException e)
+				{
+					Console.Error.WriteLine("Decryption key file not found, "
+						+ "or not valid ["+keyfile+"]");
+					throw e;
+				}
+			}
+		}
+
+		private void process()
+		{
+			/* 
+			* Setup the DESede cipher engine, create a PaddedBufferedBlockCipher
+			* in CBC mode.
+			*/
+			cipher = new PaddedBufferedBlockCipher(
+				new CbcBlockCipher(new DesEdeEngine()));
+
+			/*
+			* The input and output streams are currently set up
+			* appropriately, and the key bytes are ready to be
+			* used.
+			*
+			*/
+
+			if (encrypt)
+			{
+				performEncrypt(key);
+			}
+			else
+			{
+				performDecrypt(key);
+			}
+
+			// after processing clean up the files
+			try
+			{
+				inStr.Close();
+				outStr.Flush();
+				outStr.Close();
+			}
+			catch (IOException)
+			{
+			}
+		}
+
+		/*
+		* This method performs all the encryption and writes
+		* the cipher text to the buffered output stream created
+		* previously.
+		*/
+		private void performEncrypt(byte[] key)
+		{
+			// initialise the cipher with the key bytes, for encryption
+			cipher.Init(true, new KeyParameter(key));
+
+			/*
+			* Create some temporary byte arrays for use in
+			* encryption, make them a reasonable size so that
+			* we don't spend forever reading small chunks from
+			* a file.
+			*
+			* There is no particular reason for using getBlockSize()
+			* to determine the size of the input chunk.  It just
+			* was a convenient number for the example.  
+			*/
+			// int inBlockSize = cipher.getBlockSize() * 5;
+			int inBlockSize = 47;
+			int outBlockSize = cipher.GetOutputSize(inBlockSize);
+
+			byte[] inblock = new byte[inBlockSize];
+			byte[] outblock = new byte[outBlockSize];
+
+			/* 
+			* now, read the file, and output the chunks
+			*/
+			try
+			{
+				int inL;
+				int outL;
+				while ((inL = inStr.Read(inblock, 0, inBlockSize)) > 0)
+				{
+					outL = cipher.ProcessBytes(inblock, 0, inL, outblock, 0);
+
+					/*
+					* Before we write anything out, we need to make sure
+					* that we've got something to write out. 
+					*/
+					if (outL > 0)
+					{
+						Hex.Encode(outblock, 0, outL, outStr);
+						outStr.WriteByte((byte)'\n');
+					}
+				}
+
+				try
+				{
+					/*
+					* Now, process the bytes that are still buffered
+					* within the cipher.
+					*/
+					outL = cipher.DoFinal(outblock, 0);
+					if (outL > 0)
+					{
+						Hex.Encode(outblock, 0, outL, outStr);
+						outStr.WriteByte((byte) '\n');
+					}
+				}
+				catch (CryptoException)
+				{
+
+				}
+			}
+			catch (IOException ioeread)
+			{
+				Console.Error.WriteLine(ioeread.StackTrace);
+			}
+		}
+
+		/*
+		* This method performs all the decryption and writes
+		* the plain text to the buffered output stream created
+		* previously.
+		*/
+		private void performDecrypt(byte[] key)
+		{    
+			// initialise the cipher for decryption
+			cipher.Init(false, new KeyParameter(key));
+
+			/* 
+			* As the decryption is from our preformatted file,
+			* and we know that it's a hex encoded format, then
+			* we wrap the InputStream with a BufferedReader
+			* so that we can read it easily.
+			*/
+//			BufferedReader br = new BufferedReader(new StreamReader(inStr));
+			StreamReader br = new StreamReader(inStr); // 'inStr' already buffered
+
+			/* 
+			* now, read the file, and output the chunks
+			*/
+			try
+			{
+				int outL;
+				byte[] inblock = null;
+				byte[] outblock = null;
+				string rv = null;
+				while ((rv = br.ReadLine()) != null)
+				{
+					inblock = Hex.Decode(rv);
+					outblock = new byte[cipher.GetOutputSize(inblock.Length)];
+
+					outL = cipher.ProcessBytes(inblock, 0, inblock.Length, outblock, 0);
+					/*
+					* Before we write anything out, we need to make sure
+					* that we've got something to write out. 
+					*/
+					if (outL > 0)
+					{
+						outStr.Write(outblock, 0, outL);
+					}
+				}
+
+				try
+				{
+					/*
+					* Now, process the bytes that are still buffered
+					* within the cipher.
+					*/
+					outL = cipher.DoFinal(outblock, 0);
+					if (outL > 0)
+					{
+						outStr.Write(outblock, 0, outL);
+					}
+				}
+				catch (CryptoException)
+				{
+
+				}
+			}
+			catch (IOException ioeread)
+			{
+				Console.Error.WriteLine(ioeread.StackTrace);
+			}
+		}
+
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/io/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/crypto/io/test/AllTests.cs
new file mode 100644
index 0000000..4d34fa6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/io/test/AllTests.cs
@@ -0,0 +1,29 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.IO.Tests
+{
+	public class AllTests
+	{
+		public static void Main(
+			string[] args)
+		{
+//            junit.textui.TestRunner.run(suite());
+			EventListener el = new NullListener();
+			suite().Run(el);
+		}
+
+		public static TestSuite suite()
+		{
+			TestSuite suite = new TestSuite("IO tests");
+
+			suite.Add(new CipherStreamTest());
+
+			return suite;
+		}
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/io/test/CipherStreamTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/io/test/CipherStreamTest.cs
new file mode 100644
index 0000000..8f03c57
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/io/test/CipherStreamTest.cs
@@ -0,0 +1,166 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.IO.Tests
+{
+	[TestFixture]
+	public class CipherStreamTest
+	{
+		private const string DATA = "This will be encrypted and then decrypted and checked for correctness";
+
+		[Test]
+		public void TestEncryptDecryptA()
+		{
+			byte[] dataBytes = Encoding.ASCII.GetBytes(DATA);
+			byte[] encryptedDataBytes = encryptOnWrite(dataBytes);
+
+			byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes);
+			string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length);
+			Assert.AreEqual(DATA, decryptedData);
+		}
+
+		[Test]
+		public void TestEncryptDecryptB()
+		{
+			byte[] dataBytes = Encoding.ASCII.GetBytes(DATA);
+			byte[] encryptedDataBytes = encryptOnRead(dataBytes);
+
+			byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes);
+			string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length);
+			Assert.AreEqual(DATA, decryptedData);
+		}
+
+		[Test]
+		public void TestEncryptDecryptC()
+		{
+			byte[] dataBytes = Encoding.ASCII.GetBytes(DATA);
+			byte[] encryptedDataBytes = encryptOnWrite(dataBytes);
+
+			byte[] decryptedDataBytes = decryptOnWrite(encryptedDataBytes);
+			string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length);
+			Assert.AreEqual(DATA, decryptedData);
+		}
+
+		[Test]
+		public void TestEncryptDecryptD()
+		{
+			byte[] dataBytes = Encoding.ASCII.GetBytes(DATA);
+			byte[] encryptedDataBytes = encryptOnRead(dataBytes);
+
+			byte[] decryptedDataBytes = decryptOnRead(encryptedDataBytes);
+			string decryptedData = Encoding.ASCII.GetString(decryptedDataBytes, 0, decryptedDataBytes.Length);
+			Assert.AreEqual(DATA, decryptedData);
+		}
+
+		private byte[] encryptOnWrite(byte[] dataBytes)
+		{
+			MemoryStream encryptedDataStream = new MemoryStream();
+			IBufferedCipher outCipher = createCipher(true);
+			CipherStream outCipherStream = new CipherStream(encryptedDataStream, null, outCipher);
+			outCipherStream.Write(dataBytes, 0, dataBytes.Length);
+			Assert.AreEqual(0L, encryptedDataStream.Position % outCipher.GetBlockSize());
+
+			outCipherStream.Close();
+			byte[] encryptedDataBytes = encryptedDataStream.ToArray();
+			Assert.AreEqual(dataBytes.Length, encryptedDataBytes.Length);
+
+			return encryptedDataBytes;
+		}
+
+		private byte[] encryptOnRead(byte[] dataBytes)
+		{
+			MemoryStream dataStream = new MemoryStream(dataBytes, false);
+			MemoryStream encryptedDataStream = new MemoryStream();
+			IBufferedCipher inCipher = createCipher(true);
+			CipherStream inCipherStream = new CipherStream(dataStream, inCipher, null);
+
+			int ch;
+			while ((ch = inCipherStream.ReadByte()) >= 0)
+			{
+				encryptedDataStream.WriteByte((byte) ch);
+			}
+
+			encryptedDataStream.Close();
+			inCipherStream.Close();
+
+			byte[] encryptedDataBytes = encryptedDataStream.ToArray();
+			Assert.AreEqual(dataBytes.Length, encryptedDataBytes.Length);
+
+			return encryptedDataBytes;
+		}
+
+		private byte[] decryptOnRead(byte[] encryptedDataBytes)
+		{
+			MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false);
+			MemoryStream dataStream = new MemoryStream();
+			IBufferedCipher inCipher = createCipher(false);
+			CipherStream inCipherStream = new CipherStream(encryptedDataStream, inCipher, null);
+
+			int ch;
+			while ((ch = inCipherStream.ReadByte()) >= 0)
+			{
+				dataStream.WriteByte((byte) ch);
+			}
+
+			inCipherStream.Close();
+			dataStream.Close();
+
+			byte[] dataBytes = dataStream.ToArray();
+			Assert.AreEqual(encryptedDataBytes.Length, dataBytes.Length);
+
+			return dataBytes;
+		}
+
+		private byte[] decryptOnWrite(byte[] encryptedDataBytes)
+		{
+			MemoryStream encryptedDataStream = new MemoryStream(encryptedDataBytes, false);
+			MemoryStream dataStream = new MemoryStream();
+			IBufferedCipher outCipher = createCipher(false);
+			CipherStream outCipherStream = new CipherStream(dataStream, null, outCipher);
+
+			int ch;
+			while ((ch = encryptedDataStream.ReadByte()) >= 0)
+			{
+				outCipherStream.WriteByte((byte) ch);
+			}
+
+			outCipherStream.Close();
+			encryptedDataStream.Close();
+
+			byte[] dataBytes = dataStream.ToArray();
+			Assert.AreEqual(encryptedDataBytes.Length, dataBytes.Length);
+
+			return dataBytes;
+		}
+
+		private IBufferedCipher createCipher(bool forEncryption)
+		{
+//			IBufferedCipher cipher = CipherUtilities.GetCipher("AES/CFB/NoPadding");
+
+			IBlockCipher blockCipher = new AesEngine();
+			int bits = 8 * blockCipher.GetBlockSize(); // TODO Is this right?
+			blockCipher = new CfbBlockCipher(blockCipher, bits);
+			IBufferedCipher cipher = new BufferedBlockCipher(blockCipher);
+
+//			SecureRandom random = new SecureRandom();
+			byte[] keyBytes = new byte[32];
+			//random.NextBytes(keyBytes);
+			KeyParameter key = new KeyParameter(keyBytes);
+
+			byte[] iv = new byte[cipher.GetBlockSize()];
+			//random.NextBytes(iv);
+
+			cipher.Init(forEncryption, new ParametersWithIV(key, iv));
+
+			return cipher;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AESFastTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AESFastTest.cs
new file mode 100644
index 0000000..5513a0e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AESFastTest.cs
@@ -0,0 +1,168 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Test vectors from the NIST standard tests and Brian Gladman's vector set
+	* <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+	* http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+	*/
+	[TestFixture]
+	public class AesFastTest
+		: CipherTest
+	{
+		static SimpleTest[]  tests =
+		{
+			new BlockCipherVectorTest(0, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(1, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(2, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(3, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(4, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(5, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(6, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(7, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+			new BlockCipherVectorTest(8, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(9, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(10, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(11, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(12, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(13, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(14, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(15, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+			new BlockCipherVectorTest(16, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(17, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(18, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(19, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(20, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(21, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(22, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(23, 10000, new AesFastEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
+		};
+
+		private IBlockCipher _engine = new AesFastEngine();
+
+		public AesFastTest()
+			: base(tests, new AesFastEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get
+			{
+				return "AESFast";
+			}
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			byte[] keyBytes = new byte[16];
+
+			_engine.Init(true, new KeyParameter(keyBytes));
+
+			//
+			// init tests
+			//
+			try
+			{
+				byte[] dudKey = new byte[6];
+
+				_engine.Init(true, new KeyParameter(dudKey));
+
+				Fail("failed key length check");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			try
+			{
+				byte[] iv = new byte[16];
+
+				_engine.Init(true, new ParametersWithIV(null, iv));
+
+				Fail("failed parameter check");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			AesFastTest test = new AesFastTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AESLightTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AESLightTest.cs
new file mode 100644
index 0000000..0b5777b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AESLightTest.cs
@@ -0,0 +1,168 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Test vectors from the NIST standard tests and Brian Gladman's vector set
+	* <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+	* http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+	*/
+	[TestFixture]
+	public class AesLightTest
+		: CipherTest
+	{
+		static SimpleTest[]  tests =
+		{
+			new BlockCipherVectorTest(0, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(1, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(2, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(3, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(4, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(5, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(6, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(7, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+			new BlockCipherVectorTest(8, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(9, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(10, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(11, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(12, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(13, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(14, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(15, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+			new BlockCipherVectorTest(16, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+					"00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+			new BlockCipherVectorTest(17, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+					"00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+			new BlockCipherMonteCarloTest(18, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+					"00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+			new BlockCipherMonteCarloTest(19, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+					"355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+			new BlockCipherVectorTest(20, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+			new BlockCipherMonteCarloTest(21, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+					"F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+			new BlockCipherVectorTest(22, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+					"80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+			new BlockCipherMonteCarloTest(23, 10000, new AesLightEngine(),
+					new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+					"C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")
+		};
+
+		private IBlockCipher _engine = new AesLightEngine();
+
+		public AesLightTest()
+			: base(tests, new AesLightEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get
+			{
+				return "AESLight";
+			}
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			byte[] keyBytes = new byte[16];
+
+			_engine.Init(true, new KeyParameter(keyBytes));
+
+			//
+			// init tests
+			//
+			try
+			{
+				byte[] dudKey = new byte[6];
+
+				_engine.Init(true, new KeyParameter(dudKey));
+
+				Fail("failed key length check");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			try
+			{
+				byte[] iv = new byte[16];
+
+				_engine.Init(true, new ParametersWithIV(null, iv));
+
+				Fail("failed parameter check");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			AesLightTest test = new AesLightTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AESTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AESTest.cs
new file mode 100644
index 0000000..7b8fc34
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AESTest.cs
@@ -0,0 +1,178 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> Test vectors from the NIST standard tests and Brian Gladman's vector set
+    /// <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+    /// http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+    /// </summary>
+    [TestFixture]
+    public class AesTest : CipherTest
+    {
+        internal static SimpleTest[] tests = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new AesEngine(), new KeyParameter(Hex.Decode("80000000000000000000000000000000")), "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+            new BlockCipherVectorTest(1, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000080")), "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+            new BlockCipherMonteCarloTest(2, 10000, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000000")), "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+            new BlockCipherMonteCarloTest(3, 10000, new AesEngine(), new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")), "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+            new BlockCipherVectorTest(4, new AesEngine(), new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+            new BlockCipherMonteCarloTest(5, 10000, new AesEngine(), new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")), "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+            new BlockCipherVectorTest(6, new AesEngine(), new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+            new BlockCipherMonteCarloTest(7, 10000, new AesEngine(), new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")), "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+            new BlockCipherVectorTest(8, new AesEngine(), new KeyParameter(Hex.Decode("80000000000000000000000000000000")), "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+            new BlockCipherVectorTest(9, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000080")), "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+            new BlockCipherMonteCarloTest(10, 10000, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000000")), "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+            new BlockCipherMonteCarloTest(11, 10000, new AesEngine(), new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")), "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+            new BlockCipherVectorTest(12, new AesEngine(), new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+            new BlockCipherMonteCarloTest(13, 10000, new AesEngine(), new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")), "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+            new BlockCipherVectorTest(14, new AesEngine(), new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+            new BlockCipherMonteCarloTest(15, 10000, new AesEngine(), new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")), "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+            new BlockCipherVectorTest(16, new AesEngine(), new KeyParameter(Hex.Decode("80000000000000000000000000000000")), "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+            new BlockCipherVectorTest(17, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000080")), "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+            new BlockCipherMonteCarloTest(18, 10000, new AesEngine(), new KeyParameter(Hex.Decode("00000000000000000000000000000000")), "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+            new BlockCipherMonteCarloTest(19, 10000, new AesEngine(), new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")), "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+            new BlockCipherVectorTest(20, new AesEngine(), new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+            new BlockCipherMonteCarloTest(21, 10000, new AesEngine(), new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")), "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+            new BlockCipherVectorTest(22, new AesEngine(), new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")), "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+            new BlockCipherMonteCarloTest(23, 10000, new AesEngine(), new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")), "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168")};
+
+        public override string Name { get { return "AES"; } }
+
+		public AesTest()
+			: base(tests, new AesEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		private ITestResult WrapTest(int id, byte[] kek, byte[] input, byte[] outBytes)
+        {
+            IWrapper wrapper = new AesWrapEngine();
+
+            wrapper.Init(true, new KeyParameter(kek));
+
+            try
+            {
+                byte[] cText = wrapper.Wrap(input, 0, input.Length);
+
+				if (!Arrays.AreEqual(cText, outBytes))
+                {
+                    return new SimpleTestResult(false, Name + ": failed wrap test " + id
+						+ " expected " + Hex.ToHexString(outBytes)
+						+ " got " + Hex.ToHexString(cText));
+                }
+            }
+            catch (System.Exception e)
+            {
+                return new SimpleTestResult(false, Name + ": failed wrap test exception " + e.ToString());
+            }
+
+            wrapper.Init(false, new KeyParameter(kek));
+
+            try
+            {
+                byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length);
+                if (!Arrays.AreEqual(pText, input))
+                {
+                    return new SimpleTestResult(false, Name + ": failed unwrap test " + id
+						+ " expected " + Hex.ToHexString(input)
+						+ " got " + Hex.ToHexString(pText));
+                }
+            }
+            catch (Exception e)
+            {
+                return new SimpleTestResult(false, Name + ": failed unwrap test exception.", e);
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public override ITestResult Perform()
+        {
+            ITestResult result = base.Perform();
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+            byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff");
+            byte[] out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
+            result = WrapTest(1, kek1, in1, out1);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek2 = Hex.Decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+            byte[] in2 = Hex.Decode("00112233445566778899aabbccddeeff");
+            byte[] out2 = Hex.Decode("96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d");
+            result = WrapTest(2, kek2, in2, out2);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek3 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+            byte[] in3 = Hex.Decode("00112233445566778899aabbccddeeff");
+            byte[] out3 = Hex.Decode("64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7");
+            result = WrapTest(3, kek3, in3, out3);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek4 = Hex.Decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+            byte[] in4 = Hex.Decode("00112233445566778899aabbccddeeff0001020304050607");
+            byte[] out4 = Hex.Decode("031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2");
+            result = WrapTest(4, kek4, in4, out4);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek5 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+            byte[] in5 = Hex.Decode("00112233445566778899aabbccddeeff0001020304050607");
+            byte[] out5 = Hex.Decode("a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1");
+            result = WrapTest(5, kek5, in5, out5);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            byte[] kek6 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+            byte[] in6 = Hex.Decode("00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f");
+            byte[] out6 = Hex.Decode("28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21");
+            result = WrapTest(6, kek6, in6, out6);
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+	        string[] args)
+        {
+            AesTest test = new AesTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AESWrapTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AESWrapTest.cs
new file mode 100644
index 0000000..11b4609
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AESWrapTest.cs
@@ -0,0 +1,214 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Wrap Test
+	*/
+	[TestFixture]
+	public class AesWrapTest
+		: ITest
+	{
+		public string Name
+		{
+			get
+			{
+				return "AESWrap";
+			}
+		}
+
+		private ITestResult wrapTest(
+			int     id,
+			byte[]  kek,
+			byte[]  inBytes,
+			byte[]  outBytes)
+		{
+			IWrapper wrapper = new AesWrapEngine();
+
+			wrapper.Init(true, new KeyParameter(kek));
+
+			try
+			{
+				byte[]  cText = wrapper.Wrap(inBytes, 0, inBytes.Length);
+				if (!Arrays.AreEqual(cText, outBytes))
+				{
+					return new SimpleTestResult(false, Name + ": failed wrap test " + id
+						+ " expected " + Hex.ToHexString(outBytes)
+						+ " got " + Hex.ToHexString(cText));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed wrap test exception " + e);
+			}
+
+			wrapper.Init(false, new KeyParameter(kek));
+
+			try
+			{
+				byte[]  pText = wrapper.Unwrap(outBytes, 0, outBytes.Length);
+				if (!Arrays.AreEqual(pText, inBytes))
+				{
+					return new SimpleTestResult(false, Name + ": failed unwrap test " + id
+						+ " expected " + Hex.ToHexString(inBytes)
+						+ " got " + Hex.ToHexString(pText));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed unwrap test exception.", e);
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public ITestResult Perform()
+		{
+			byte[]  kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+			byte[]  in1 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[]  out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
+			ITestResult result = wrapTest(1, kek1, in1, out1);
+
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			byte[]  kek2 = Hex.Decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+			byte[]  in2 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[]  out2 = Hex.Decode("96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d");
+			result = wrapTest(2, kek2, in2, out2);
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			byte[]  kek3 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+			byte[]  in3 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[]  out3 = Hex.Decode("64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7");
+			result = wrapTest(3, kek3, in3, out3);
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			byte[]  kek4 = Hex.Decode("000102030405060708090a0b0c0d0e0f1011121314151617");
+			byte[]  in4 = Hex.Decode("00112233445566778899aabbccddeeff0001020304050607");
+			byte[]  out4 = Hex.Decode("031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2");
+			result = wrapTest(4, kek4, in4, out4);
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			byte[]  kek5 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+			byte[]  in5 = Hex.Decode("00112233445566778899aabbccddeeff0001020304050607");
+			byte[]  out5 = Hex.Decode("a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1");
+			result = wrapTest(5, kek5, in5, out5);
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			byte[]  kek6 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f");
+			byte[]  in6 = Hex.Decode("00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f");
+			byte[]  out6 = Hex.Decode("28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21");
+			result = wrapTest(6, kek6, in6, out6);
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			IWrapper wrapper = new AesWrapEngine();
+			KeyParameter key = new KeyParameter(new byte[16]);
+			byte[]       buf = new byte[16];
+
+			try
+			{
+				wrapper.Init(true, key);
+
+				wrapper.Unwrap(buf, 0, buf.Length);
+
+				return new SimpleTestResult(false, Name + ": failed unwrap state test.");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+			catch (InvalidCipherTextException e)
+			{
+				return new SimpleTestResult(false, Name + ": unexpected exception: " + e, e);
+			}
+
+			try
+			{
+				wrapper.Init(false, key);
+
+				wrapper.Wrap(buf, 0, buf.Length);
+
+				return new SimpleTestResult(false, Name + ": failed unwrap state test.");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+
+			//
+			// short test
+			//
+			try
+			{
+				wrapper.Init(false, key);
+
+				wrapper.Unwrap(buf, 0, buf.Length / 2);
+
+				return new SimpleTestResult(false, Name + ": failed unwrap short test.");
+			}
+			catch (InvalidCipherTextException)
+			{
+				// expected
+			}
+
+			try
+			{
+				wrapper.Init(true, key);
+
+				wrapper.Wrap(buf, 0, 15);
+
+				return new SimpleTestResult(false, Name + ": failed wrap length test.");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			AesWrapTest test = new AesWrapTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AeadTestUtilities.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AeadTestUtilities.cs
new file mode 100644
index 0000000..40f3342
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AeadTestUtilities.cs
@@ -0,0 +1,14 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    public class AeadTestUtilities
+    {
+        internal static AeadParameters ReuseKey(AeadParameters p)
+        {
+            return new AeadParameters(null, p.MacSize, p.GetNonce(), p.GetAssociatedText());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/AllTests.cs
new file mode 100644
index 0000000..03afe69
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/AllTests.cs
@@ -0,0 +1,52 @@
+using System;
+
+#if !LIB
+using NUnit.Core;
+#endif
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class AllTests
+	{
+#if !LIB
+		[Suite]
+		public static TestSuite Suite
+		{
+			get
+			{
+				TestSuite suite = new TestSuite("Lightweight Crypto Tests");
+				suite.Add(new AllTests());
+		        suite.Add(new GcmReorderTest());
+				return suite;
+			}
+		}
+#endif
+
+		[Test]
+		public void TestCrypto()
+		{
+			foreach (Org.BouncyCastle.Utilities.Test.ITest test in RegressionTest.tests)
+			{
+				SimpleTestResult result = (SimpleTestResult)test.Perform();
+
+				if (!result.IsSuccessful())
+				{
+					Assert.Fail(result.ToString());
+				}
+			}
+		}
+#if !LIB
+        public static void Main(
+			string[] args)
+        {
+            //junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            Suite.Run(el);
+        }
+#endif
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherMonteCarloTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherMonteCarloTest.cs
new file mode 100644
index 0000000..1a46a32
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherMonteCarloTest.cs
@@ -0,0 +1,83 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* a basic test that takes a cipher, key parameter, and an input
+	* and output string. This test wraps the engine in a buffered block
+	* cipher with padding disabled.
+	*/
+	public class BlockCipherMonteCarloTest
+		: SimpleTest
+	{
+		int					id;
+		int					iterations;
+		IBlockCipher		engine;
+		ICipherParameters	param;
+		byte[]				input;
+		byte[]				output;
+
+		public BlockCipherMonteCarloTest(
+			int                 id,
+			int                 iterations,
+			IBlockCipher         engine,
+			ICipherParameters    param,
+			string              input,
+			string              output)
+		{
+			this.id = id;
+			this.iterations = iterations;
+			this.engine = engine;
+			this.param = param;
+			this.input = Hex.Decode(input);
+			this.output = Hex.Decode(output);
+		}
+
+		public override string Name
+		{
+			get { return engine.AlgorithmName + " Monte Carlo Test " + id; }
+		}
+
+		public override void PerformTest()
+		{
+			BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
+
+			cipher.Init(true, param);
+
+			byte[]  outBytes = new byte[input.Length];
+
+			Array.Copy(input, 0, outBytes, 0, outBytes.Length);
+
+			for (int i = 0; i != iterations; i++)
+			{
+				int len1 = cipher.ProcessBytes(outBytes, 0, outBytes.Length, outBytes, 0);
+
+				cipher.DoFinal(outBytes, len1);
+			}
+
+			if (!AreEqual(outBytes, output))
+			{
+				Fail("failed - " + "expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			cipher.Init(false, param);
+
+			for (int i = 0; i != iterations; i++)
+			{
+				int len1 = cipher.ProcessBytes(outBytes, 0, outBytes.Length, outBytes, 0);
+
+				cipher.DoFinal(outBytes, len1);
+			}
+
+			if (!AreEqual(input, outBytes))
+			{
+				Fail("failed reversal");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherVectorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherVectorTest.cs
new file mode 100644
index 0000000..1ce9fa4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/BlockCipherVectorTest.cs
@@ -0,0 +1,75 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* a basic test that takes a cipher, key parameter, and an input
+	* and output string. This test wraps the engine in a buffered block
+	* cipher with padding disabled.
+	*/
+	public class BlockCipherVectorTest
+		: SimpleTest
+	{
+		int                 id;
+		IBlockCipher         engine;
+		ICipherParameters    param;
+		byte[]              input;
+		byte[]              output;
+
+		public BlockCipherVectorTest(
+			int					id,
+			IBlockCipher		engine,
+			ICipherParameters	param,
+			string				input,
+			string				output)
+		{
+			this.id = id;
+			this.engine = engine;
+			this.param = param;
+			this.input = Hex.Decode(input);
+			this.output = Hex.Decode(output);
+		}
+
+		public override string Name
+		{
+			get
+			{
+				return engine.AlgorithmName + " Vector Test " + id;
+			}
+		}
+
+		public override void PerformTest()
+		{
+			BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
+
+			cipher.Init(true, param);
+
+			byte[]  outBytes = new byte[input.Length];
+
+			int len1 = cipher.ProcessBytes(input, 0, input.Length, outBytes, 0);
+
+				cipher.DoFinal(outBytes, len1);
+
+			if (!AreEqual(outBytes, output))
+			{
+				Fail("failed - " + "expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			cipher.Init(false, param);
+
+			int len2 = cipher.ProcessBytes(output, 0, output.Length, outBytes, 0);
+
+			cipher.DoFinal(outBytes, len2);
+
+			if (!AreEqual(input, outBytes))
+			{
+				Fail("failed reversal got " + Hex.ToHexString(outBytes));
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/BlowfishTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/BlowfishTest.cs
new file mode 100644
index 0000000..780dd3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/BlowfishTest.cs
@@ -0,0 +1,55 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks>Blowfish tester - vectors from http://www.counterpane.com/vectors.txt</remarks>
+    [TestFixture]
+    public class BlowfishTest
+		: CipherTest
+    {
+        public override string Name
+        {
+			get { return "Blowfish"; }
+        }
+
+        internal static SimpleTest[] tests = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new BlowfishEngine(), new KeyParameter(Hex.Decode("0000000000000000")), "0000000000000000", "4EF997456198DD78"),
+            new BlockCipherVectorTest(1, new BlowfishEngine(), new KeyParameter(Hex.Decode("FFFFFFFFFFFFFFFF")), "FFFFFFFFFFFFFFFF", "51866FD5B85ECB8A"),
+            new BlockCipherVectorTest(2, new BlowfishEngine(), new KeyParameter(Hex.Decode("3000000000000000")), "1000000000000001", "7D856F9A613063F2"),
+            new BlockCipherVectorTest(3, new BlowfishEngine(), new KeyParameter(Hex.Decode("1111111111111111")), "1111111111111111", "2466DD878B963C9D"),
+            new BlockCipherVectorTest(4, new BlowfishEngine(), new KeyParameter(Hex.Decode("0123456789ABCDEF")), "1111111111111111", "61F9C3802281B096"),
+            new BlockCipherVectorTest(5, new BlowfishEngine(), new KeyParameter(Hex.Decode("FEDCBA9876543210")), "0123456789ABCDEF", "0ACEAB0FC6A0A28D"),
+            new BlockCipherVectorTest(6, new BlowfishEngine(), new KeyParameter(Hex.Decode("7CA110454A1A6E57")), "01A1D6D039776742", "59C68245EB05282B"),
+            new BlockCipherVectorTest(7, new BlowfishEngine(), new KeyParameter(Hex.Decode("0131D9619DC1376E")), "5CD54CA83DEF57DA", "B1B8CC0B250F09A0")
+        };
+
+        public BlowfishTest()
+			: base(tests, new BlowfishEngine(), new KeyParameter(new byte[16]))
+		{
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+		public static void Main(
+			string[] args)
+        {
+            ITest test = new BlowfishTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CAST6Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CAST6Test.cs
new file mode 100644
index 0000000..7517b67
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CAST6Test.cs
@@ -0,0 +1,57 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks>Cast6 tester - vectors from http://www.ietf.org/rfc/rfc2612.txt</remarks>
+    [TestFixture]
+    public class Cast6Test : CipherTest
+    {
+        public override string Name
+        {
+			get { return "CAST6"; }
+        }
+
+		internal static SimpleTest[] tests = new SimpleTest[]
+		{
+			new BlockCipherVectorTest(0, new Cast6Engine(),
+				new KeyParameter(Hex.Decode("2342bb9efa38542c0af75647f29f615d")),
+				"00000000000000000000000000000000",
+				"c842a08972b43d20836c91d1b7530f6b"),
+			new BlockCipherVectorTest(0, new Cast6Engine(),
+				new KeyParameter(Hex.Decode("2342bb9efa38542cbed0ac83940ac298bac77a7717942863")),
+				"00000000000000000000000000000000",
+				"1b386c0210dcadcbdd0e41aa08a7a7e8"),
+			new BlockCipherVectorTest(0, new Cast6Engine(),
+				new KeyParameter(Hex.Decode("2342bb9efa38542cbed0ac83940ac2988d7c47ce264908461cc1b5137ae6b604")),
+				"00000000000000000000000000000000",
+				"4f6a2038286897b9c9870136553317fa")
+		};
+
+        public Cast6Test()
+			: base(tests, new Cast6Engine(), new KeyParameter(new byte[16]))
+        {
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new Cast6Test();
+            ITestResult result = test.Perform();
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CCMTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CCMTest.cs
new file mode 100644
index 0000000..4a54fb4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CCMTest.cs
@@ -0,0 +1,268 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* First four test vectors from
+	* NIST Special Publication 800-38C.
+	*/
+	[TestFixture]
+	public class CcmTest
+		: SimpleTest
+	{
+		private byte[] K1 = Hex.Decode("404142434445464748494a4b4c4d4e4f");
+		private byte[] N1 = Hex.Decode("10111213141516");
+		private byte[] A1 = Hex.Decode("0001020304050607");
+		private byte[] P1 = Hex.Decode("20212223");
+		private byte[] C1 = Hex.Decode("7162015b4dac255d");
+		private byte[] T1 = Hex.Decode("6084341b");
+
+		private byte[] K2 = Hex.Decode("404142434445464748494a4b4c4d4e4f");
+		private byte[] N2 = Hex.Decode("1011121314151617");
+		private byte[] A2 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+		private byte[] P2 = Hex.Decode("202122232425262728292a2b2c2d2e2f");
+		private byte[] C2 = Hex.Decode("d2a1f0e051ea5f62081a7792073d593d1fc64fbfaccd");
+		private byte[] T2 = Hex.Decode("7f479ffca464");
+
+		private byte[] K3 = Hex.Decode("404142434445464748494a4b4c4d4e4f");
+		private byte[] N3 = Hex.Decode("101112131415161718191a1b");
+		private byte[] A3 = Hex.Decode("000102030405060708090a0b0c0d0e0f10111213");
+		private byte[] P3 = Hex.Decode("202122232425262728292a2b2c2d2e2f3031323334353637");
+		private byte[] C3 = Hex.Decode("e3b201a9f5b71a7a9b1ceaeccd97e70b6176aad9a4428aa5484392fbc1b09951");
+		private byte[] T3 = Hex.Decode("67c99240c7d51048");
+
+		private byte[] K4 = Hex.Decode("404142434445464748494a4b4c4d4e4f");
+		private byte[] N4 = Hex.Decode("101112131415161718191a1b1c");
+		private byte[] A4 = Hex.Decode("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4 [...]
+		private byte[] P4 = Hex.Decode("202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f");
+		private byte[] C4 = Hex.Decode("69915dad1e84c6376a68c2967e4dab615ae0fd1faec44cc484828529463ccf72b4ac6bec93e8598e7f0dadbcea5b");
+		private byte[] T4 = Hex.Decode("f4dd5d0ee404617225ffe34fce91");
+
+		//
+		// long data vector
+		//
+		private byte[] C5 = Hex.Decode("49b17d8d3ea4e6174a48e2b65e6d8b417ac0dd3f8ee46ce4a4a2a509661cef52528c1cd9805333a5cfd482fa3f095a3c2fdd1cc47771c5e55fddd60b5c8d6d3fa5c8dd79d08b16242b6642106e7c0c28bd1064b31e6d7c9800c8397dbc3fa8071e6a38278b386c18d65d39c6ad1ef9501a5c8f68d38eb6474799f3cc898b4b9b97e87f9c95ce5c51bc9d758f17119586663a5684e0a0daf6520ec572b87473eb141d10471e4799ded9e607655402eca5176bbf792ef39dd135ac8d710da8e9e854fd3b95c681023f36b5ebe2fb213d0b62dd6e9e3cfe190b792ccb20c53423b2dca128f861 [...]
+		private byte[] T5 = Hex.Decode("5c768856796b627b13ec8641581b");
+
+		public override void PerformTest()
+		{
+			CcmBlockCipher ccm = new CcmBlockCipher(new AesEngine());
+
+			checkVectors(0, ccm, K1, 32, N1, A1, P1, T1, C1);
+			checkVectors(1, ccm, K2, 48, N2, A2, P2, T2, C2);
+			checkVectors(2, ccm, K3, 64, N3, A3, P3, T3, C3);
+
+			ivParamTest(0, ccm, K1, N1);
+
+			//
+			// 4 has a reduced associated text which needs to be replicated
+			//
+			byte[] a4 = new byte[65536]; // 524288 / 8
+
+			for (int i = 0; i < a4.Length; i += A4.Length)
+			{
+				Array.Copy(A4, 0, a4, i, A4.Length);
+			}
+
+			checkVectors(3, ccm, K4, 112, N4, a4, P4, T4, C4);
+
+			//
+			// long data test
+			//
+			checkVectors(4, ccm, K4, 112, N4, A4, A4, T5, C5);
+
+			//
+			// exception tests
+			//
+
+			try
+			{
+				ccm.Init(false, new AeadParameters(new KeyParameter(K1), 32, N2, A2));
+
+				ccm.ProcessPacket(C2, 0, C2.Length);
+
+				Fail("invalid cipher text not picked up");
+			}
+			catch (InvalidCipherTextException)
+			{
+				// expected
+			}
+
+			try
+			{
+				ccm = new CcmBlockCipher(new DesEngine());
+
+				Fail("incorrect block size not picked up");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			try
+			{
+				ccm.Init(false, new KeyParameter(K1));
+
+				Fail("illegal argument not picked up");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		private void checkVectors(
+			int count,
+			CcmBlockCipher ccm,
+			byte[] k,
+			int macSize,
+			byte[] n,
+			byte[] a,
+			byte[] p,
+			byte[] t,
+			byte[] c)
+        {
+            byte[] fa = new byte[a.Length / 2];
+            byte[] la = new byte[a.Length - (a.Length / 2)];
+            Array.Copy(a, 0, fa, 0, fa.Length);
+            Array.Copy(a, fa.Length, la, 0, la.Length);
+
+            checkVectors(count, ccm, "all initial associated data", k, macSize, n, a, null, p, t, c);
+            checkVectors(count, ccm, "subsequent associated data", k, macSize, n, null, a, p, t, c);
+            checkVectors(count, ccm, "split associated data", k, macSize, n, fa, la, p, t, c);
+    //      checkVectors(count, ccm, "reuse key", null, macSize, n, fa, la, p, t, c);
+        }
+
+        private void checkVectors(
+            int count,
+            CcmBlockCipher ccm,
+            string additionalDataType,
+            byte[] k,
+            int macSize,
+            byte[] n,
+            byte[] a,
+            byte[] sa,
+            byte[] p,
+            byte[] t,
+            byte[] c)
+        {
+            KeyParameter keyParam = (k == null) ? null : new KeyParameter(k);
+
+            ccm.Init(true, new AeadParameters(keyParam, macSize, n, a));
+
+			byte[] enc = new byte[c.Length];
+
+            if (sa != null)
+            {
+                ccm.ProcessAadBytes(sa, 0, sa.Length);
+            }
+
+			int len = ccm.ProcessBytes(p, 0, p.Length, enc, 0);
+
+			len += ccm.DoFinal(enc, len);
+
+//			ccm.Init(true, new AeadParameters(new KeyParameter(k), macSize, n, a));
+//
+//			byte[] enc = ccm.ProcessPacket(p, 0, p.Length);
+
+			if (!AreEqual(c, enc))
+			{
+                Fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
+            }
+
+//			ccm.Init(false, new AeadParameters(new KeyParameter(k), macSize, n, a));
+//
+//			byte[] dec = ccm.ProcessPacket(enc, 0, enc.Length);
+
+			ccm.Init(false, new AeadParameters(new KeyParameter(k), macSize, n, a));
+
+			byte[] tmp = new byte[enc.Length];
+
+            if (sa != null)
+            {
+                ccm.ProcessAadBytes(sa, 0, sa.Length);
+            }
+
+            len = ccm.ProcessBytes(enc, 0, enc.Length, tmp, 0);
+
+			len += ccm.DoFinal(tmp, len);
+
+			byte[] dec = new byte[len];
+
+			Array.Copy(tmp, 0, dec, 0, len);
+
+			if (!AreEqual(p, dec))
+			{
+                Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType);
+            }
+
+			if (!AreEqual(t, ccm.GetMac()))
+			{
+                Fail("MAC fails to match in test " + count + " with " + additionalDataType);
+            }
+		}
+
+		private void ivParamTest(
+			int				count,
+			CcmBlockCipher	ccm,
+			byte[]			k,
+			byte[]			n)
+		{
+			byte[] p = Encoding.ASCII.GetBytes("hello world!!");
+
+			ccm.Init(true, new ParametersWithIV(new KeyParameter(k), n));
+
+			byte[] enc = new byte[p.Length + 8];
+
+			int len = ccm.ProcessBytes(p, 0, p.Length, enc, 0);
+
+			len += ccm.DoFinal(enc, len);
+
+			ccm.Init(false, new ParametersWithIV(new KeyParameter(k), n));
+
+			byte[] tmp = new byte[enc.Length];
+
+			len = ccm.ProcessBytes(enc, 0, enc.Length, tmp, 0);
+
+			len += ccm.DoFinal(tmp, len);
+
+			byte[] dec = new byte[len];
+
+			Array.Copy(tmp, 0, dec, 0, len);
+
+			if (!AreEqual(p, dec))
+			{
+				Fail("decrypted stream fails to match in test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "CCM"; }
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CcmTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CMacTest.cs
new file mode 100644
index 0000000..d71b69f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CMacTest.cs
@@ -0,0 +1,302 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">Official Test Vectors</a>.
+     */
+    [TestFixture]
+    public class CMacTest
+        : SimpleTest
+    {
+        private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c");
+        private static readonly byte[] keyBytes192 = Hex.Decode(
+            "8e73b0f7da0e6452c810f32b809079e5"
+            + "62f8ead2522c6b7b");
+        private static readonly byte[] keyBytes256 = Hex.Decode(
+            "603deb1015ca71be2b73aef0857d7781"
+            + "1f352c073b6108d72d9810a30914dff4");
+
+        private static readonly byte[] input0 = Hex.Decode("");
+        private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a");
+        private static readonly byte[] input40 = Hex.Decode(
+            "6bc1bee22e409f96e93d7e117393172a"
+            + "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
+        private static readonly byte[] input64 = Hex.Decode(
+            "6bc1bee22e409f96e93d7e117393172a"
+            + "ae2d8a571e03ac9c9eb76fac45af8e51"
+            + "30c81c46a35ce411e5fbc1191a0a52ef"
+            + "f69f2445df4f9b17ad2b417be66c3710");
+
+        private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746");
+        private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c");
+        private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827");
+        private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe");
+
+        private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367");
+        private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184");
+        private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e");
+        private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11");
+
+        private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983");
+        private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c");
+        private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6");
+        private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410");
+
+        public CMacTest()
+        {
+        }
+
+        public override void PerformTest()
+        {
+            IBlockCipher cipher = new AesFastEngine();
+            IMac mac = new CMac(cipher, 128);
+
+            //128 bytes key
+
+            KeyParameter key = new KeyParameter(keyBytes128);
+
+            // 0 bytes message - 128 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input0, 0, input0.Length);
+
+            byte[] outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k128_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 16 bytes message - 128 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input16, 0, input16.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k128_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 40 bytes message - 128 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input40, 0, input40.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k128_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 64 bytes message - 128 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input64, 0, input64.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k128_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k128_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            //192 bytes key
+            key = new KeyParameter(keyBytes192);
+
+            // 0 bytes message - 192 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input0, 0, input0.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k192_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 16 bytes message - 192 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input16, 0, input16.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k192_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 40 bytes message - 192 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input40, 0, input40.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k192_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 64 bytes message - 192 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input64, 0, input64.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k192_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k192_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            //256 bytes key
+
+            key = new KeyParameter(keyBytes256);
+
+            // 0 bytes message - 256 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input0, 0, input0.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k256_m0))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m0) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 16 bytes message - 256 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input16, 0, input16.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k256_m16))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m16) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 40 bytes message - 256 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input40, 0, input40.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k256_m40))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m40) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // 64 bytes message - 256 bytes key
+            mac.Init(key);
+
+            mac.BlockUpdate(input64, 0, input64.Length);
+
+            outBytes = new byte[16];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output_k256_m64))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output_k256_m64) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            TestExceptions();
+        }
+
+        private void TestExceptions()
+        {
+            try 
+            {
+                CMac mac = new CMac(new AesEngine());
+                mac.Init(new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]));
+                Fail("CMac does not accept IV");
+            }
+            catch(ArgumentException)
+            {
+                // Expected
+            }
+        }
+
+        public override string Name
+        {
+            get { return "CMac"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CMacTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CTSTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CTSTest.cs
new file mode 100644
index 0000000..9d001bc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CTSTest.cs
@@ -0,0 +1,192 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> CTS tester</summary>
+    [TestFixture]
+    public class CTSTest : ITest
+    {
+        public string Name
+        {
+			get
+			{
+				return "CTS";
+			}
+        }
+
+        internal static byte[] in1;
+
+        internal static byte[] in2;
+
+        internal static byte[] out1;
+
+        internal static byte[] out2;
+
+        internal static byte[] out3;
+
+        private class CTSTester : ITest
+        {
+            private void  InitBlock(CTSTest enclosingInstance)
+            {
+                this.enclosingInstance = enclosingInstance;
+            }
+            private CTSTest enclosingInstance;
+
+            public string Name
+            {
+				get
+				{
+					return "CTS";
+				}
+            }
+
+            public CTSTest Enclosing_Instance
+            {
+                get
+                {
+                    return enclosingInstance;
+                }
+
+            }
+
+            private int id;
+            private IBlockCipher cipher;
+            private ICipherParameters parameters;
+            private byte[] input;
+            private byte[] output;
+
+            internal CTSTester(CTSTest enclosingInstance, int id, IBlockCipher cipher, ICipherParameters parameters, byte[] input, byte[] output)
+            {
+                InitBlock(enclosingInstance);
+                this.id = id;
+                this.cipher = cipher;
+                this.parameters = parameters;
+                this.input = input;
+                this.output = output;
+            }
+
+            public virtual ITestResult Perform()
+            {
+                byte[] outBytes = new byte[input.Length];
+                BufferedBlockCipher engine = new CtsBlockCipher(cipher);
+
+                engine.Init(true, parameters);
+
+                int len = engine.ProcessBytes(input, 0, input.Length, outBytes, 0);
+
+                try
+                {
+                    engine.DoFinal(outBytes, len);
+                }
+                catch (Exception e)
+                {
+                    return new SimpleTestResult(false, Name + ": encryption exception - " + e.ToString());
+                }
+
+                for (int i = 0; i != output.Length; i++)
+                {
+                    if (outBytes[i] != output[i])
+                    {
+                        return new SimpleTestResult(false, Name + ": failed encryption expected "
+							+ Hex.ToHexString(output) + " got " + Hex.ToHexString(outBytes));
+                    }
+                }
+
+                engine.Init(false, parameters);
+
+                len = engine.ProcessBytes(output, 0, output.Length, outBytes, 0);
+
+                try
+                {
+                    engine.DoFinal(outBytes, len);
+                }
+                catch (Exception e)
+                {
+                    return new SimpleTestResult(false, Name + ": decryption exception - " + e.ToString());
+                }
+
+                for (int i = 0; i != input.Length; i++)
+                {
+                    if (outBytes[i] != input[i])
+                    {
+                        return new SimpleTestResult(false, Name + ": failed encryption expected "
+							+ Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+                    }
+                }
+
+                return new SimpleTestResult(true, Name + ": Okay");
+            }
+        }
+
+        public CTSTest()
+        {
+        }
+
+        public virtual ITestResult Perform()
+        {
+            byte[] key1 = new byte[]{(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF};
+            byte[] key2 = new byte[]{(byte) 0x01, (byte) 0x23, (byte) 0x45, (byte) 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF, (byte) 0xee, (byte) 0xff };
+            byte[] iv = new byte[]{1, 2, 3, 4, 5, 6, 7, 8};
+
+            ITest test = new CTSTester(this, 1, new DesEngine(), new KeyParameter(key1), in1, out1);
+            ITestResult result = test.Perform();
+
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            test = new CTSTester(this, 2, new CbcBlockCipher(new DesEngine()), new ParametersWithIV(new KeyParameter(key1), iv), in1, out2);
+            result = test.Perform();
+
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            test = new CTSTester(this, 3, new CbcBlockCipher(new SkipjackEngine()), new ParametersWithIV(new KeyParameter(key2), iv), in2, out3);
+            result = test.Perform();
+
+            if (!result.IsSuccessful())
+            {
+                return result;
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            CTSTest test = new CTSTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        static CTSTest()
+        {
+            in1 = Hex.Decode("4e6f7720697320746865207420");
+            in2 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa");
+            out1 = Hex.Decode("9952f131588465033fa40e8a98");
+            out2 = Hex.Decode("358f84d01eb42988dc34efb994");
+            out3 = Hex.Decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaLightTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaLightTest.cs
new file mode 100644
index 0000000..2247178
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaLightTest.cs
@@ -0,0 +1,80 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
+	*/
+	[TestFixture]
+	public class CamelliaLightTest
+		: CipherTest
+	{
+		static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
+			new BlockCipherVectorTest(1, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+				"00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
+			new BlockCipherVectorTest(2, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba9876543210")),
+				"0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
+			//
+			// 192 bit
+			//
+			new BlockCipherVectorTest(3, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba98765432100011223344556677")),
+				"0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
+			new BlockCipherVectorTest(4, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+				"00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
+			new BlockCipherVectorTest(5, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("949494949494949494949494949494949494949494949494")),
+				"636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
+			//
+			// 256 bit
+			//
+			new BlockCipherVectorTest(6, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
+				"0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
+			new BlockCipherVectorTest(7, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
+				"057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
+			new BlockCipherVectorTest(8, new CamelliaLightEngine(),
+				new KeyParameter(Hex.Decode("0303030303030303030303030303030303030303030303030303030303030303")),
+				"7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
+		};
+
+		public CamelliaLightTest()
+			: base(tests, new CamelliaLightEngine(), new KeyParameter(new byte[32]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "CamelliaLight"; }
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CamelliaLightTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaTest.cs
new file mode 100644
index 0000000..a134546
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CamelliaTest.cs
@@ -0,0 +1,80 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * Camellia tester - vectors from https://www.cosic.esat.kuleuven.be/nessie/testvectors/ and RFC 3713
+	 */
+	[TestFixture]
+	public class CamelliaTest
+		: CipherTest
+	{
+		static SimpleTest[]  tests =
+		{
+			new BlockCipherVectorTest(0, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"80000000000000000000000000000000", "07923A39EB0A817D1C4D87BDB82D1F1C"),
+			new BlockCipherVectorTest(1, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+				"00000000000000000000000000000000", "6C227F749319A3AA7DA235A9BBA05A2C"),
+			new BlockCipherVectorTest(2, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba9876543210")),
+				"0123456789abcdeffedcba9876543210", "67673138549669730857065648eabe43"),
+			//
+			// 192 bit
+			//
+			new BlockCipherVectorTest(3, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba98765432100011223344556677")),
+				"0123456789abcdeffedcba9876543210", "b4993401b3e996f84ee5cee7d79b09b9"),
+			new BlockCipherVectorTest(4, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+				"00040000000000000000000000000000", "9BCA6C88B928C1B0F57F99866583A9BC"),
+			new BlockCipherVectorTest(5, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("949494949494949494949494949494949494949494949494")),
+				"636EB22D84B006381235641BCF0308D2", "94949494949494949494949494949494"),
+			//
+			// 256 bit
+			//
+			new BlockCipherVectorTest(6, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff")),
+				"0123456789abcdeffedcba9876543210", "9acc237dff16d76c20ef7c919e3a7509"),
+			new BlockCipherVectorTest(7, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A")),
+				"057764FE3A500EDBD988C5C3B56CBA9A", "4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A4A"),
+			new BlockCipherVectorTest(8, new CamelliaEngine(),
+				new KeyParameter(Hex.Decode("0303030303030303030303030303030303030303030303030303030303030303")),
+				"7968B08ABA92193F2295121EF8D75C8A", "03030303030303030303030303030303"),
+		};
+
+		public CamelliaTest()
+			: base(tests, new CamelliaEngine(), new KeyParameter(new byte[32]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Camellia"; }
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CamelliaTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Cast5Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Cast5Test.cs
new file mode 100644
index 0000000..ea2e0c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Cast5Test.cs
@@ -0,0 +1,49 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks>Cast tester - vectors from http://www.ietf.org/rfc/rfc2144.txt</remarks>
+    [TestFixture]
+    public class Cast5Test
+		: CipherTest
+    {
+        public override string Name
+        {
+			get { return "Cast5"; }
+        }
+
+		internal static SimpleTest[] testlist = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new Cast5Engine(), new KeyParameter(Hex.Decode("0123456712345678234567893456789A")), "0123456789ABCDEF", "238B4FE5847E44B2"),
+            new BlockCipherVectorTest(0, new Cast5Engine(), new KeyParameter(Hex.Decode("01234567123456782345")), "0123456789ABCDEF", "EB6A711A2C02271B"),
+            new BlockCipherVectorTest(0, new Cast5Engine(), new KeyParameter(Hex.Decode("0123456712")), "0123456789ABCDEF", "7Ac816d16E9B302E")};
+
+		public Cast5Test()
+			: base(testlist , new Cast5Engine(), new KeyParameter(new byte[16]))
+        {
+        }
+
+        public static void Main(
+			string[] args)
+        {
+            ITest test = new Cast5Test();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ChaChaTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ChaChaTest.cs
new file mode 100644
index 0000000..0b394c9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ChaChaTest.cs
@@ -0,0 +1,319 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * ChaCha Test
+     * <p>
+     * Test cases generated using ref version of ChaCha20 in estreambench-20080905.
+     * </p>
+     */
+    [TestFixture]
+    public class ChaChaTest
+        : SimpleTest
+    {
+        private static readonly byte[] zeroes = Hex.Decode(
+            "00000000000000000000000000000000"
+            + "00000000000000000000000000000000"
+            + "00000000000000000000000000000000"
+            + "00000000000000000000000000000000");
+
+        private static readonly string set1v0_0 =
+            "FBB87FBB8395E05DAA3B1D683C422046"
+            + "F913985C2AD9B23CFC06C1D8D04FF213"
+            + "D44A7A7CDB84929F915420A8A3DC58BF"
+            + "0F7ECB4B1F167BB1A5E6153FDAF4493D";
+
+        private static readonly string set1v0_192 =
+            "D9485D55B8B82D792ED1EEA8E93E9BC1"
+            + "E2834AD0D9B11F3477F6E106A2F6A5F2"
+            + "EA8244D5B925B8050EAB038F58D4DF57"
+            + "7FAFD1B89359DAE508B2B10CBD6B488E";
+
+        private static readonly string set1v0_256 =
+            "08661A35D6F02D3D9ACA8087F421F7C8"
+            + "A42579047D6955D937925BA21396DDD4"
+            + "74B1FC4ACCDCAA33025B4BCE817A4FBF"
+            + "3E5D07D151D7E6FE04934ED466BA4779";
+
+        private static readonly string set1v0_448 =
+            "A7E16DD38BA48CCB130E5BE9740CE359"
+            + "D631E91600F85C8A5D0785A612D1D987"
+            + "90780ACDDC26B69AB106CCF6D866411D"
+            + "10637483DBF08CC5591FD8B3C87A3AE0";
+
+        private static readonly string set1v9_0 =
+            "A276339F99316A913885A0A4BE870F06"
+            + "91E72B00F1B3F2239F714FE81E88E00C"
+            + "BBE52B4EBBE1EA15894E29658C4CB145"
+            + "E6F89EE4ABB045A78514482CE75AFB7C";
+
+        private static readonly string set1v9_192 =
+            "0DFB9BD4F87F68DE54FBC1C6428FDEB0"
+            + "63E997BE8490C9B7A4694025D6EBA2B1"
+            + "5FE429DB82A7CAE6AAB22918E8D00449"
+            + "6FB6291467B5AE81D4E85E81D8795EBB";
+
+        private static readonly string set1v9_256 =
+            "546F5BB315E7F71A46E56D4580F90889"
+            + "639A2BA528F757CF3B048738BA141AF3"
+            + "B31607CB21561BAD94721048930364F4"
+            + "B1227CFEB7CDECBA881FB44903550E68";
+
+        private static readonly string set1v9_448 =
+            "6F813586E76691305A0CF048C0D8586D"
+            + "C89460207D8B230CD172398AA33D19E9"
+            + "2D24883C3A9B0BB7CD8C6B2668DB142E"
+            + "37A97948A7A01498A21110297984CD20";
+
+        private static readonly string set6v0_0 =
+            "57459975BC46799394788DE80B928387"
+            + "862985A269B9E8E77801DE9D874B3F51"
+            + "AC4610B9F9BEE8CF8CACD8B5AD0BF17D"
+            + "3DDF23FD7424887EB3F81405BD498CC3";
+
+        private static readonly string set6v0_65472 =
+            "EF9AEC58ACE7DB427DF012B2B91A0C1E"
+            + "8E4759DCE9CDB00A2BD59207357BA06C"
+            + "E02D327C7719E83D6348A6104B081DB0"
+            + "3908E5186986AE41E3AE95298BB7B713";
+
+        private static readonly string set6v0_65536 =
+            "17EF5FF454D85ABBBA280F3A94F1D26E"
+            + "950C7D5B05C4BB3A78326E0DC5731F83"
+            + "84205C32DB867D1B476CE121A0D7074B"
+            + "AA7EE90525D15300F48EC0A6624BD0AF";
+
+        private static readonly string set6v1_0 =
+            "92A2508E2C4084567195F2A1005E552B"
+            + "4874EC0504A9CD5E4DAF739AB553D2E7"
+            + "83D79C5BA11E0653BEBB5C116651302E"
+            + "8D381CB728CA627B0B246E83942A2B99";
+
+        private static readonly string set6v1_65472 =
+            "E1974EC3063F7BD0CBA58B1CE34BC874"
+            + "67AAF5759B05EA46682A5D4306E5A76B"
+            + "D99A448DB8DE73AF97A73F5FBAE2C776"
+            + "35040464524CF14D7F08D4CE1220FD84";
+
+        private static readonly string set6v1_65536 =
+            "BE3436141CFD62D12FF7D852F80C1344"
+            + "81F152AD0235ECF8CA172C55CA8C031B"
+            + "2E785D773A988CA8D4BDA6FAE0E493AA"
+            + "71DCCC4C894D1F106CAC62A9FC0A9607";
+
+        // ChaCha12
+        private static readonly string chacha12_set1v0_0 =
+            "36CF0D56E9F7FBF287BC5460D95FBA94"
+            + "AA6CBF17D74E7C784DDCF7E0E882DDAE"
+            + "3B5A58243EF32B79A04575A8E2C2B73D"
+            + "C64A52AA15B9F88305A8F0CA0B5A1A25";
+
+        private static readonly string chacha12_set1v0_192 =
+            "83496792AB68FEC75ADB16D3044420A4"
+            + "A00A6E9ADC41C3A63DBBF317A8258C85"
+            + "A9BC08B4F76B413A4837324AEDF8BC2A"
+            + "67D53C9AB9E1C5BC5F379D48DF9AF730";
+
+        private static readonly string chacha12_set1v0_256 = 
+            "BAA28ED593690FD760ADA07C95E3B888"
+            + "4B4B64E488CA7A2D9BDC262243AB9251"
+            + "394C5037E255F8BCCDCD31306C508FFB"
+            + "C9E0161380F7911FCB137D46D9269250";
+
+        private static readonly string chacha12_set1v0_448 =
+            "B7ECFB6AE0B51915762FE1FD03A14D0C"
+            + "9E54DA5DC76EB16EBA5313BC535DE63D"
+            + "C72D7F9F1874E301E99C8531819F4E37"
+            + "75793F6A5D19C717FA5C78A39EB804A6";
+
+        // ChaCha8
+        private static readonly string chacha8_set1v0_0 =
+            "BEB1E81E0F747E43EE51922B3E87FB38"
+            + "D0163907B4ED49336032AB78B67C2457"
+            + "9FE28F751BD3703E51D876C017FAA435"
+            + "89E63593E03355A7D57B2366F30047C5";
+
+        private static readonly string chacha8_set1v0_192 =
+            "33B8B7CA8F8E89F0095ACE75A379C651"
+            + "FD6BDD55703C90672E44C6BAB6AACDD8"
+            + "7C976A87FD264B906E749429284134C2"
+            + "38E3B88CF74A68245B860D119A8BDF43";
+
+        private static readonly string chacha8_set1v0_256 =
+            "F7CA95BF08688BD3BE8A27724210F9DC"
+            + "16F32AF974FBFB09E9F757C577A245AB"
+            + "F35F824B70A4C02CB4A8D7191FA8A5AD"
+            + "6A84568743844703D353B7F00A8601F4";
+
+        private static readonly string chacha8_set1v0_448 =
+            "7B4117E8BFFD595CD8482270B08920FB"
+            + "C9B97794E1809E07BB271BF07C861003"
+            + "4C38DBA6ECA04E5474F399A284CBF6E2"
+            + "7F70142E604D0977797DE5B58B6B25E0";
+
+        public override string Name
+        {
+            get { return "ChaCha"; }
+        }
+
+        public override void PerformTest()
+        {
+            chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+                    set1v0_0, set1v0_192,  set1v0_256,  set1v0_448);
+            chachaTest1(20, new ParametersWithIV(new KeyParameter(Hex.Decode("00400000000000000000000000000000")), Hex.Decode("0000000000000000")),
+                    set1v9_0, set1v9_192,  set1v9_256,  set1v9_448);
+            chachaTest1(12, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+                    chacha12_set1v0_0, chacha12_set1v0_192,  chacha12_set1v0_256,  chacha12_set1v0_448);
+            chachaTest1(8, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+                    chacha8_set1v0_0, chacha8_set1v0_192,  chacha8_set1v0_256,  chacha8_set1v0_448);
+            chachaTest2(new ParametersWithIV(new KeyParameter(Hex.Decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.Decode("0D74DB42A91077DE")),
+                    set6v0_0, set6v0_65472, set6v0_65536);
+            chachaTest2(new ParametersWithIV(new KeyParameter(Hex.Decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.Decode("167DE44BB21980E7")),
+                    set6v1_0, set6v1_65472, set6v1_65536);
+            reinitBug();
+        }
+
+        private void chachaTest1(
+            int rounds,
+            ICipherParameters	parameters,
+            string				v0,
+            string				v192,
+            string				v256,
+            string				v448)
+        {
+            IStreamCipher salsa = new ChaChaEngine(rounds);
+            byte[]       buf = new byte[64];
+
+            salsa.Init(true, parameters);
+
+            for (int i = 0; i != 7; i++)
+            {
+                salsa.ProcessBytes(zeroes, 0, 64, buf, 0);
+                switch (i)
+                {
+                case 0:
+                    if (!AreEqual(buf, Hex.Decode(v0)))
+                    {
+                        mismatch("v0/" + rounds, v0, buf);
+                    }
+                    break;
+                case 3:
+                    if (!AreEqual(buf, Hex.Decode(v192)))
+                    {
+                        mismatch("v192/" + rounds, v192, buf);
+                    }
+                    break;
+                case 4:
+                    if (!AreEqual(buf, Hex.Decode(v256)))
+                    {
+                        mismatch("v256/" + rounds, v256, buf);
+                    }
+                    break;
+                default:
+                    // ignore
+                    break;
+                }
+            }
+
+            for (int i = 0; i != 64; i++)
+            {
+                buf[i] = salsa.ReturnByte(zeroes[i]);
+            }
+
+            if (!AreEqual(buf, Hex.Decode(v448)))
+            {
+                mismatch("v448", v448, buf);
+            }       
+        }
+
+        private void chachaTest2(
+            ICipherParameters	parameters,
+            string				v0,
+            string				v65472,
+            string				v65536)
+        {
+            IStreamCipher salsa = new ChaChaEngine();
+            byte[]       buf = new byte[64];
+
+            salsa.Init(true, parameters);
+
+            for (int i = 0; i != 1025; i++)
+            {
+                salsa.ProcessBytes(zeroes, 0, 64, buf, 0);
+                switch (i)
+                {
+                case 0:
+                    if (!AreEqual(buf, Hex.Decode(v0)))
+                    {
+                        mismatch("v0", v0, buf);
+                    }
+                    break;
+                case 1023:
+                    if (!AreEqual(buf, Hex.Decode(v65472)))
+                    {
+                        mismatch("v65472", v65472, buf);
+                    }
+                    break;
+                case 1024:
+                    if (!AreEqual(buf, Hex.Decode(v65536)))
+                    {
+                        mismatch("v65536", v65536, buf);
+                    }
+                    break;
+                default:
+                    // ignore
+                    break;
+                }
+            }
+        }
+
+        private void mismatch(
+            string	name,
+            string	expected,
+            byte[]	found)
+        {
+            Fail("mismatch on " + name, expected, Hex.ToHexString(found));
+        }
+
+        private void reinitBug()
+        {
+            KeyParameter key = new KeyParameter(Hex.Decode("80000000000000000000000000000000"));
+            ParametersWithIV parameters = new ParametersWithIV(key, Hex.Decode("0000000000000000"));
+
+            IStreamCipher chacha = new ChaChaEngine();
+
+            chacha.Init(true, parameters);
+
+            try
+            {
+                chacha.Init(true, key);
+                Fail("ChaCha should throw exception if no IV in Init");
+            }
+            catch (ArgumentException)
+            {
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ChaChaTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/CipherTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/CipherTest.cs
new file mode 100644
index 0000000..d9c085d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/CipherTest.cs
@@ -0,0 +1,117 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	public abstract class CipherTest
+		: SimpleTest
+	{
+		private SimpleTest[]      _tests;
+		private IBlockCipher _engine;
+		private KeyParameter _validKey;
+
+//		protected CipherTest(
+//			SimpleTest[]	tests)
+//		{
+//			_tests = tests;
+//		}
+
+		protected CipherTest(
+			SimpleTest[]	tests,
+			IBlockCipher	engine,
+			KeyParameter	validKey)
+		{
+			_tests = tests;
+			_engine = engine;
+			_validKey = validKey;
+		}
+
+		public override void PerformTest()
+		{
+			for (int i = 0; i != _tests.Length; i++)
+			{
+				_tests[i].PerformTest();
+			}
+
+			if (_engine != null)
+			{
+				//
+				// state tests
+				//
+				byte[] buf = new byte[_engine.GetBlockSize()];
+
+				try
+				{
+					_engine.ProcessBlock(buf, 0, buf, 0);
+
+					Fail("failed initialisation check");
+				}
+				catch (InvalidOperationException)
+				{
+					// expected
+				}
+
+				bufferSizeCheck((_engine));
+			}
+		}
+
+		private void bufferSizeCheck(
+			IBlockCipher engine)
+		{
+			byte[] correctBuf = new byte[engine.GetBlockSize()];
+			byte[] shortBuf = new byte[correctBuf.Length / 2];
+
+			engine.Init(true, _validKey);
+
+			try
+			{
+				engine.ProcessBlock(shortBuf, 0, correctBuf, 0);
+
+				Fail("failed short input check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			try
+			{
+				engine.ProcessBlock(correctBuf, 0, shortBuf, 0);
+
+				Fail("failed short output check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			engine.Init(false, _validKey);
+
+			try
+			{
+				engine.ProcessBlock(shortBuf, 0, correctBuf, 0);
+
+				Fail("failed short input check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			try
+			{
+				engine.ProcessBlock(correctBuf, 0, shortBuf, 0);
+
+				Fail("failed short output check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DESTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DESTest.cs
new file mode 100644
index 0000000..cf1022e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DESTest.cs
@@ -0,0 +1,214 @@
+using System;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	internal class DesParityTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "DESParityTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			byte[] k1In = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
+							   (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff };
+			byte[] k1Out = { (byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe,
+								(byte)0xfe, (byte)0xfe, (byte)0xfe, (byte)0xfe };
+
+			byte[] k2In = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
+							   (byte)0xaa, (byte)0x99, (byte)0x7f, (byte)0x63 };
+			byte[] k2Out = { (byte)0xef, (byte)0xcb, (byte)0xda, (byte)0x4f,
+								(byte)0xab, (byte)0x98, (byte)0x7f, (byte)0x62 };
+
+			DesParameters.SetOddParity(k1In);
+
+			for (int i = 0; i != k1In.Length; i++)
+			{
+				if (k1In[i] != k1Out[i])
+				{
+					Fail("Failed "
+						+ "got " + Hex.ToHexString(k1In)
+						+ " expected " + Hex.ToHexString(k1Out));
+				}
+			}
+
+			DesParameters.SetOddParity(k2In);
+
+			for (int i = 0; i != k2In.Length; i++)
+			{
+				if (k2In[i] != k2Out[i])
+				{
+					Fail("Failed "
+						+ "got " + Hex.ToHexString(k2In)
+						+ " expected " + Hex.ToHexString(k2Out));
+				}
+			}
+		}
+	}
+
+	internal class KeyGenTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "KeyGenTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			DesKeyGenerator keyGen = new DesKeyGenerator();
+
+			keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 56));
+
+			byte[] kB = keyGen.GenerateKey();
+
+			if (kB.Length != 8)
+			{
+				Fail("DES bit key wrong length.");
+			}
+		}
+	}
+
+	internal class DesParametersTest
+		: SimpleTest
+	{
+		private static readonly byte[] weakKeys =
+		{
+			(byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+			(byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+			(byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+			(byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe, (byte)0xfe,(byte)0xfe,(byte)0xfe,(byte)0xfe,
+			/* semi-weak keys */
+			(byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe, (byte)0x01,(byte)0xfe,(byte)0x01,(byte)0xfe,
+			(byte)0x1f,(byte)0xe0,(byte)0x1f,(byte)0xe0, (byte)0x0e,(byte)0xf1,(byte)0x0e,(byte)0xf1,
+			(byte)0x01,(byte)0xe0,(byte)0x01,(byte)0xe0, (byte)0x01,(byte)0xf1,(byte)0x01,(byte)0xf1,
+			(byte)0x1f,(byte)0xfe,(byte)0x1f,(byte)0xfe, (byte)0x0e,(byte)0xfe,(byte)0x0e,(byte)0xfe,
+			(byte)0x01,(byte)0x1f,(byte)0x01,(byte)0x1f, (byte)0x01,(byte)0x0e,(byte)0x01,(byte)0x0e,
+			(byte)0xe0,(byte)0xfe,(byte)0xe0,(byte)0xfe, (byte)0xf1,(byte)0xfe,(byte)0xf1,(byte)0xfe,
+			(byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01, (byte)0xfe,(byte)0x01,(byte)0xfe,(byte)0x01,
+			(byte)0xe0,(byte)0x1f,(byte)0xe0,(byte)0x1f, (byte)0xf1,(byte)0x0e,(byte)0xf1,(byte)0x0e,
+			(byte)0xe0,(byte)0x01,(byte)0xe0,(byte)0x01, (byte)0xf1,(byte)0x01,(byte)0xf1,(byte)0x01,
+			(byte)0xfe,(byte)0x1f,(byte)0xfe,(byte)0x1f, (byte)0xfe,(byte)0x0e,(byte)0xfe,(byte)0x0e,
+			(byte)0x1f,(byte)0x01,(byte)0x1f,(byte)0x01, (byte)0x0e,(byte)0x01,(byte)0x0e,(byte)0x01,
+			(byte)0xfe,(byte)0xe0,(byte)0xfe,(byte)0xe0, (byte)0xfe,(byte)0xf1,(byte)0xfe,(byte)0xf1
+		};
+
+		public override string Name
+		{
+			get { return "DesParameters"; }
+		}
+
+		public override void PerformTest()
+		{
+			try
+			{
+				DesParameters.IsWeakKey(new byte[4], 0);
+				Fail("no exception on small key");
+			}
+			catch (ArgumentException e)
+			{
+				if (!e.Message.Equals("key material too short."))
+				{
+					Fail("wrong exception");
+				}
+			}
+
+			try
+			{
+				new DesParameters(weakKeys);
+				Fail("no exception on weak key");
+			}
+			catch (ArgumentException e)
+			{
+				if (!e.Message.Equals("attempt to create weak DES key"))
+				{
+					Fail("wrong exception");
+				}
+			}
+
+			for (int i = 0; i != weakKeys.Length; i += 8)
+			{
+				if (!DesParameters.IsWeakKey(weakKeys, i))
+				{
+					Fail("weakKey test failed");
+				}
+			}
+		}
+	}
+
+	/**
+	 * DES tester - vectors from <a href="http://www.itl.nist.gov/fipspubs/fip81.htm">FIPS 81</a>
+	 */
+	[TestFixture]
+	public class DesTest
+		: CipherTest
+	{
+		static string input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
+		static string input2 = "4e6f7720697320746865";
+		static string input3 = "4e6f7720697320746865aabbcc";
+
+		static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new DesEngine(),
+				new DesParameters(Hex.Decode("0123456789abcdef")),
+				input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+			new BlockCipherVectorTest(1, new CbcBlockCipher(new DesEngine()),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input1, "e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6"),
+			new BlockCipherVectorTest(2, new CfbBlockCipher(new DesEngine(), 8),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input2, "f31fda07011462ee187f"),
+			new BlockCipherVectorTest(3, new CfbBlockCipher(new DesEngine(), 64),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input1, "f3096249c7f46e51a69e839b1a92f78403467133898ea622"),
+			new BlockCipherVectorTest(4, new OfbBlockCipher(new DesEngine(), 8),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input2, "f34a2850c9c64985d684"),
+			new BlockCipherVectorTest(5, new CfbBlockCipher(new DesEngine(), 64),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input3, "f3096249c7f46e51a69e0954bf"),
+			new BlockCipherVectorTest(6, new OfbBlockCipher(new DesEngine(), 64),
+				new ParametersWithIV(new DesParameters(Hex.Decode("0123456789abcdef")), Hex.Decode("1234567890abcdef")),
+				input3, "f3096249c7f46e5135f2c0eb8b"),
+			new DesParityTest(),
+			new DesParametersTest(),
+			new KeyGenTest()
+		};
+
+		public DesTest()
+			: base(tests, new DesEngine(), new DesParameters(new byte[8]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "DES"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DesTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DESedeTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DESedeTest.cs
new file mode 100644
index 0000000..aa61844
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DESedeTest.cs
@@ -0,0 +1,187 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+/**
+ * DESede tester
+ */
+	[TestFixture]
+	public class DesEdeTest
+		:CipherTest
+	{
+		private static readonly byte[] weakKey =     // first 8 bytes non-weak
+		{
+			(byte)0x06,(byte)0x01,(byte)0x01,(byte)0x01, (byte)0x01,(byte)0x01,(byte)0x01,(byte)0x01,
+			(byte)0x1f,(byte)0x1f,(byte)0x1f,(byte)0x1f, (byte)0x0e,(byte)0x0e,(byte)0x0e,(byte)0x0e,
+			(byte)0xe0,(byte)0xe0,(byte)0xe0,(byte)0xe0, (byte)0xf1,(byte)0xf1,(byte)0xf1,(byte)0xf1,
+		};
+
+		private const string input1 = "4e6f77206973207468652074696d6520666f7220616c6c20";
+//		private const string input2 = "4e6f7720697320746865";
+
+		private static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new DesEdeEngine(),
+				new DesEdeParameters(Hex.Decode("0123456789abcdef0123456789abcdef")),
+				input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+			new BlockCipherVectorTest(1, new DesEdeEngine(),
+				new DesEdeParameters(Hex.Decode("0123456789abcdeffedcba9876543210")),
+				input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c"),
+			new BlockCipherVectorTest(2, new DesEdeEngine(),
+				new DesEdeParameters(Hex.Decode("0123456789abcdef0123456789abcdef0123456789abcdef")),
+				input1, "3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53"),
+			new BlockCipherVectorTest(3, new DesEdeEngine(),
+				new DesEdeParameters(Hex.Decode("0123456789abcdeffedcba98765432100123456789abcdef")),
+				input1, "d80a0d8b2bae5e4e6a0094171abcfc2775d2235a706e232c")
+		};
+
+		public DesEdeTest()
+			: base(tests, new DesEdeEngine(), new DesEdeParameters(new byte[16]))
+		{
+		}
+
+		private void WrapTest(
+			int     id,
+			byte[]  kek,
+			byte[]  iv,
+			byte[]  input,
+			byte[]  output)
+		{
+			IWrapper wrapper = new DesEdeWrapEngine();
+
+			wrapper.Init(true, new ParametersWithIV(new DesEdeParameters(kek), iv));
+
+			try
+			{
+				byte[] cText = wrapper.Wrap(input, 0, input.Length);
+				if (!AreEqual(cText, output))
+				{
+					Fail(": failed wrap test " + id  + " expected " + Hex.ToHexString(output)
+						+ " got " + Hex.ToHexString(cText));
+				}
+			}
+			catch (Exception e)
+			{
+				Fail("failed wrap test exception: " + e.ToString(), e);
+			}
+
+			wrapper.Init(false, new DesEdeParameters(kek));
+
+			try
+			{
+				byte[] pText = wrapper.Unwrap(output, 0, output.Length);
+				if (!AreEqual(pText, input))
+				{
+					Fail("failed unwrap test " + id  + " expected " + Hex.ToHexString(input)
+						+ " got " + Hex.ToHexString(pText));
+				}
+			}
+			catch (Exception e)
+			{
+				Fail("failed unwrap test exception: " + e.ToString(), e);
+			}
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			byte[] kek1 = Hex.Decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
+			byte[] iv1 = Hex.Decode("5dd4cbfc96f5453b");
+			byte[] in1 = Hex.Decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
+			byte[] out1 = Hex.Decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4");
+
+			WrapTest(1, kek1, iv1, in1, out1);
+
+			//
+			// key generation
+			//
+			SecureRandom random = new SecureRandom();
+			DesEdeKeyGenerator keyGen = new DesEdeKeyGenerator();
+
+			keyGen.Init(new KeyGenerationParameters(random, 112));
+
+			byte[] kB = keyGen.GenerateKey();
+	        
+			if (kB.Length != 16)
+			{
+				Fail("112 bit key wrong length.");
+			}
+	        
+			keyGen.Init(new KeyGenerationParameters(random, 168));
+	        
+			kB = keyGen.GenerateKey();
+	        
+			if (kB.Length != 24)
+			{
+				Fail("168 bit key wrong length.");
+			}
+	        
+			try
+			{
+				keyGen.Init(new KeyGenerationParameters(random, 200));
+	            
+				Fail("invalid key length not detected.");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			try
+			{
+				DesEdeParameters.IsWeakKey(new byte[4], 0);
+				Fail("no exception on small key");
+			}
+			catch (ArgumentException e)
+			{
+				if (!e.Message.Equals("key material too short."))
+				{
+					Fail("wrong exception");
+				}
+			}
+
+			try
+			{
+				new DesEdeParameters(weakKey);
+				Fail("no exception on weak key");
+			}
+			catch (ArgumentException e)
+			{
+				if (!e.Message.Equals("attempt to create weak DESede key"))
+				{
+					Fail("wrong exception");
+				}
+			}
+		}
+
+		public override string Name
+		{
+			get { return "DESede"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DesEdeTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DHKEKGeneratorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DHKEKGeneratorTest.cs
new file mode 100644
index 0000000..eee408f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DHKEKGeneratorTest.cs
@@ -0,0 +1,79 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks>DHKEK Generator tests - from RFC 2631.</remarks>
+	[TestFixture]
+	public class DHKekGeneratorTest
+		: SimpleTest
+	{
+		private byte[] seed1 = Hex.Decode("000102030405060708090a0b0c0d0e0f10111213");
+		private DerObjectIdentifier alg1 = PkcsObjectIdentifiers.IdAlgCms3DesWrap;
+		private byte[] result1 = Hex.Decode("a09661392376f7044d9052a397883246b67f5f1ef63eb5fb");
+
+		private byte[] seed2 = Hex.Decode("000102030405060708090a0b0c0d0e0f10111213");
+		private DerObjectIdentifier alg2 = PkcsObjectIdentifiers.IdAlgCmsRC2Wrap;
+		private byte[] partyAInfo = Hex.Decode(
+				"0123456789abcdeffedcba9876543201"
+			+ "0123456789abcdeffedcba9876543201"
+			+ "0123456789abcdeffedcba9876543201"
+			+ "0123456789abcdeffedcba9876543201");
+		private byte[] result2 = Hex.Decode("48950c46e0530075403cce72889604e0");
+
+		public DHKekGeneratorTest()
+		{
+		}
+
+		public override void PerformTest()
+		{
+			CheckMask(1, new DHKekGenerator(new Sha1Digest()), new DHKdfParameters(alg1, 192, seed1), result1);
+			CheckMask(2, new DHKekGenerator(new Sha1Digest()), new DHKdfParameters(alg2, 128, seed2, partyAInfo), result2);
+		}
+
+		private void CheckMask(
+			int						count,
+			IDerivationFunction		kdf,
+			IDerivationParameters	parameters,
+			byte[]					result)
+		{
+			byte[] data = new byte[result.Length];
+
+			kdf.Init(parameters);
+
+			kdf.GenerateBytes(data, 0, data.Length);
+
+			if (!AreEqual(result, data))
+			{
+				Fail("DHKekGenerator failed generator test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "DHKekGenerator"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DHKekGeneratorTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DHTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DHTest.cs
new file mode 100644
index 0000000..b460f41
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DHTest.cs
@@ -0,0 +1,403 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class DHTest
+		: SimpleTest
+	{
+		private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+		private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+		private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+		private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+		private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+		private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+		public override string Name
+		{
+			get { return "DH"; }
+		}
+
+		private void doTestDH(
+			int         size,
+			BigInteger  g,
+			BigInteger  p)
+		{
+			DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g, p);
+
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+			//
+			// generate second pair
+			//
+			pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private;
+
+			//
+			// two way
+			//
+			DHAgreement e1 = new DHAgreement();
+			DHAgreement e2 = new DHAgreement();
+
+			e1.Init(pv1);
+			e2.Init(pv2);
+
+			BigInteger m1 = e1.CalculateMessage();
+			BigInteger m2 = e2.CalculateMessage();
+
+			BigInteger k1 = e1.CalculateAgreement(pu2, m2);
+			BigInteger k2 = e2.CalculateAgreement(pu1, m1);
+
+			if (!k1.Equals(k2))
+			{
+				Fail(size + " bit 2-way test failed");
+			}
+		}
+
+		private void doTestDHBasic(
+			int         size,
+			int         privateValueSize,
+			BigInteger  g,
+			BigInteger  p)
+		{
+			DHBasicKeyPairGenerator kpGen = getDHBasicKeyPairGenerator(g, p, privateValueSize);
+
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+
+			checkKeySize(privateValueSize, pv1);
+			//
+			// generate second pair
+			//
+			pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private;
+
+			checkKeySize(privateValueSize, pv2);
+			//
+			// two way
+			//
+			DHBasicAgreement e1 = new DHBasicAgreement();
+			DHBasicAgreement e2 = new DHBasicAgreement();
+
+			e1.Init(pv1);
+			e2.Init(pv2);
+
+			BigInteger k1 = e1.CalculateAgreement(pu2);
+			BigInteger k2 = e2.CalculateAgreement(pu1);
+
+			if (!k1.Equals(k2))
+			{
+				Fail("basic " + size + " bit 2-way test failed");
+			}
+		}
+
+		private void checkKeySize(
+			int privateValueSize,
+			DHPrivateKeyParameters priv)
+		{
+			if (privateValueSize != 0)
+			{
+				if (priv.X.BitLength != privateValueSize)
+				{
+					Fail("limited key check failed for key size " + privateValueSize);
+				}
+			}
+		}
+
+		private void doTestGPWithRandom(
+			DHKeyPairGenerator kpGen)
+		{
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+			//
+			// generate second pair
+			//
+			pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private;
+
+			//
+			// two way
+			//
+			DHAgreement e1 = new DHAgreement();
+			DHAgreement e2 = new DHAgreement();
+
+			e1.Init(new ParametersWithRandom(pv1, new SecureRandom()));
+			e2.Init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+			BigInteger m1 = e1.CalculateMessage();
+			BigInteger m2 = e2.CalculateMessage();
+
+			BigInteger k1 = e1.CalculateAgreement(pu2, m2);
+			BigInteger k2 = e2.CalculateAgreement(pu1, m1);
+
+			if (!k1.Equals(k2))
+			{
+				Fail("basic with random 2-way test failed");
+			}
+		}
+
+		private void doTestSimpleWithRandom(
+			DHBasicKeyPairGenerator kpGen)
+		{
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+			//
+			// generate second pair
+			//
+			pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private;
+
+			//
+			// two way
+			//
+			DHBasicAgreement e1 = new DHBasicAgreement();
+			DHBasicAgreement e2 = new DHBasicAgreement();
+
+			e1.Init(new ParametersWithRandom(pv1, new SecureRandom()));
+			e2.Init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+			BigInteger   k1 = e1.CalculateAgreement(pu2);
+			BigInteger   k2 = e2.CalculateAgreement(pu1);
+
+			if (!k1.Equals(k2))
+			{
+				Fail("basic with random 2-way test failed");
+			}
+		}
+
+		private DHBasicKeyPairGenerator getDHBasicKeyPairGenerator(
+			BigInteger g,
+			BigInteger p,
+			int        privateValueSize)
+		{
+			DHParameters dhParams = new DHParameters(p, g, null, privateValueSize);
+			DHKeyGenerationParameters dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+			DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
+
+			kpGen.Init(dhkgParams);
+
+			return kpGen;
+		}
+
+		private DHKeyPairGenerator getDHKeyPairGenerator(
+			BigInteger g,
+			BigInteger p)
+		{
+			DHParameters dhParams = new DHParameters(p, g);
+			DHKeyGenerationParameters dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+			DHKeyPairGenerator kpGen = new DHKeyPairGenerator();
+
+			kpGen.Init(dhkgParams);
+
+			return kpGen;
+		}
+
+		/**
+		 * this test is can take quiet a while
+		 */
+		private void doTestGeneration(
+			int size)
+		{
+			DHParametersGenerator pGen = new DHParametersGenerator();
+
+			pGen.Init(size, 10, new SecureRandom());
+
+			DHParameters dhParams = pGen.GenerateParameters();
+
+			if (dhParams.L != 0)
+			{
+				Fail("DHParametersGenerator failed to set J to 0 in generated DHParameters");
+			}
+
+			DHKeyGenerationParameters dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+
+			DHBasicKeyPairGenerator kpGen = new DHBasicKeyPairGenerator();
+
+			kpGen.Init(dhkgParams);
+
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+
+			//
+			// generate second pair
+			//
+			dhkgParams = new DHKeyGenerationParameters(new SecureRandom(), pu1.Parameters);
+
+			kpGen.Init(dhkgParams);
+
+			pair = kpGen.GenerateKeyPair();
+
+			DHPublicKeyParameters pu2 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv2 = (DHPrivateKeyParameters)pair.Private;
+
+			//
+			// two way
+			//
+			DHBasicAgreement e1 = new DHBasicAgreement();
+			DHBasicAgreement e2 = new DHBasicAgreement();
+
+			e1.Init(new ParametersWithRandom(pv1, new SecureRandom()));
+			e2.Init(new ParametersWithRandom(pv2, new SecureRandom()));
+
+			BigInteger k1 = e1.CalculateAgreement(pu2);
+			BigInteger k2 = e2.CalculateAgreement(pu1);
+
+			if (!k1.Equals(k2))
+			{
+				Fail("basic with " + size + " bit 2-way test failed");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			doTestDHBasic(512, 0, g512, p512);
+			doTestDHBasic(768, 0, g768, p768);
+			doTestDHBasic(1024, 0, g1024, p1024);
+
+			doTestDHBasic(512, 64, g512, p512);
+			doTestDHBasic(768, 128, g768, p768);
+			doTestDHBasic(1024, 256, g1024, p1024);
+
+			doTestDH(512, g512, p512);
+			doTestDH(768, g768, p768);
+			doTestDH(1024, g1024, p1024);
+
+			//
+			// generation test.
+			//
+			doTestGeneration(256);
+
+			//
+			// with random test
+			//
+			DHBasicKeyPairGenerator kpBasicGen = getDHBasicKeyPairGenerator(g512, p512, 0);
+
+			doTestSimpleWithRandom(kpBasicGen);
+
+			DHKeyPairGenerator kpGen = getDHKeyPairGenerator(g512, p512);
+
+			doTestGPWithRandom(kpGen);
+
+			//
+			// parameter tests
+			//
+			DHAgreement dh = new DHAgreement();
+			AsymmetricCipherKeyPair dhPair = kpGen.GenerateKeyPair();
+
+			try
+			{
+				dh.Init(dhPair.Public);
+				Fail("DHAgreement key check failed");
+			}
+			catch (ArgumentException)
+			{
+				// ignore
+			}
+
+			DHKeyPairGenerator kpGen768 = getDHKeyPairGenerator(g768, p768);
+
+			try
+			{
+				dh.Init(dhPair.Private);
+
+				dh.CalculateAgreement((DHPublicKeyParameters)kpGen768.GenerateKeyPair().Public, BigInteger.ValueOf(100));
+
+				Fail("DHAgreement agreement check failed");
+			}
+			catch (ArgumentException)
+			{
+				// ignore
+			}
+
+			DHBasicAgreement dhBasic = new DHBasicAgreement();
+			AsymmetricCipherKeyPair dhBasicPair = kpBasicGen.GenerateKeyPair();
+
+			try
+			{
+				dhBasic.Init(dhBasicPair.Public);
+				Fail("DHBasicAgreement key check failed");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			DHBasicKeyPairGenerator kpBasicGen768 = getDHBasicKeyPairGenerator(g768, p768, 0);
+
+			try
+			{
+				dhBasic.Init(dhPair.Private);
+
+				dhBasic.CalculateAgreement((DHPublicKeyParameters)kpBasicGen768.GenerateKeyPair().Public);
+
+				Fail("DHBasicAgreement agreement check failed");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new DHTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DSATest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DSATest.cs
new file mode 100644
index 0000000..0e63671
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DSATest.cs
@@ -0,0 +1,615 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary>Test based on FIPS 186-2, Appendix 5, an example of DSA, and FIPS 168-3 test vectors.</summary>
+    [TestFixture]
+    public class DsaTest
+        : SimpleTest
+    {
+        public override string Name
+        {
+            get { return "DSA"; }
+        }
+
+        internal BigInteger pValue = new BigInteger("8df2a494492276aa3d25759bb06869cbeac0d83afb8d0cf7cbb8324f0d7882e5d0762fc5b7210eafc2e9adac32ab7aac49693dfbf83724c2ec0736ee31c80291", 16);
+        internal BigInteger qValue = new BigInteger("c773218c737ec8ee993b4f2ded30f48edace915f", 16);
+
+        public override void PerformTest()
+        {
+            byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+            byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+
+            SecureRandom random = FixedSecureRandom.From(k1, k2);
+
+            byte[] keyData = Hex.Decode("b5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+
+            SecureRandom keyRandom = FixedSecureRandom.From(keyData, keyData);
+
+            BigInteger r = new BigInteger("68076202252361894315274692543577577550894681403");
+            BigInteger s = new BigInteger("1089214853334067536215539335472893651470583479365");
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+
+            pGen.Init(512, 80, random);
+
+            DsaParameters parameters = pGen.GenerateParameters();
+            DsaValidationParameters pValid = parameters.ValidationParameters;
+
+            if (pValid.Counter != 105)
+            {
+                Fail("Counter wrong");
+            }
+
+            if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+            {
+                Fail("p or q wrong");
+            }
+
+            DsaKeyPairGenerator dsaKeyGen = new DsaKeyPairGenerator();
+            DsaKeyGenerationParameters genParam = new DsaKeyGenerationParameters(keyRandom, parameters);
+
+            dsaKeyGen.Init(genParam);
+
+            AsymmetricCipherKeyPair pair = dsaKeyGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, keyRandom);
+
+            DsaSigner dsa = new DsaSigner();
+
+            dsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArrayUnsigned();
+            BigInteger[] sig = dsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            dsa.Init(false, pair.Public);
+
+            if (!dsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("verification fails");
+            }
+
+            Dsa2Test1();
+            Dsa2Test2();
+            Dsa2Test3();
+            Dsa2Test4();
+        }
+
+        private void Dsa2Test1()
+        {
+            byte[] seed = Hex.Decode("ED8BEE8D1CB89229D2903CBF0E51EE7377F48698");
+
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+
+            pGen.Init(new DsaParameterGenerationParameters(1024, 160, 80, new DsaTestSecureRandom(seed)));
+
+            DsaParameters parameters = pGen.GenerateParameters();
+
+            DsaValidationParameters pv = parameters.ValidationParameters;
+
+            if (pv.Counter != 5)
+            {
+                Fail("counter incorrect");
+            }
+
+            if (!AreEqual(seed, pv.GetSeed()))
+            {
+                Fail("seed incorrect");
+            }
+
+            if (!parameters.Q.Equals(new BigInteger("E950511EAB424B9A19A2AEB4E159B7844C589C4F", 16)))
+            {
+                Fail("Q incorrect");
+            }
+
+            if (!parameters.P.Equals(new BigInteger(
+                "E0A67598CD1B763B" +
+                "C98C8ABB333E5DDA0CD3AA0E5E1FB5BA8A7B4EABC10BA338" +
+                "FAE06DD4B90FDA70D7CF0CB0C638BE3341BEC0AF8A7330A3" +
+                "307DED2299A0EE606DF035177A239C34A912C202AA5F83B9" +
+                "C4A7CF0235B5316BFC6EFB9A248411258B30B839AF172440" +
+                "F32563056CB67A861158DDD90E6A894C72A5BBEF9E286C6B", 16)))
+            {
+                Fail("P incorrect");
+            }
+
+            if (!parameters.G.Equals(new BigInteger(
+                "D29D5121B0423C27" +
+                "69AB21843E5A3240FF19CACC792264E3BB6BE4F78EDD1B15" +
+                "C4DFF7F1D905431F0AB16790E1F773B5CE01C804E509066A" +
+                "9919F5195F4ABC58189FD9FF987389CB5BEDF21B4DAB4F8B" +
+                "76A055FFE2770988FE2EC2DE11AD92219F0B351869AC24DA" +
+                "3D7BA87011A701CE8EE7BFE49486ED4527B7186CA4610A75", 16)))
+            {
+                Fail("G incorrect");
+            }
+
+            DsaKeyPairGenerator kpGen = new DsaKeyPairGenerator();
+
+            kpGen.Init(new DsaKeyGenerationParameters(FixedSecureRandom.From(Hex.Decode("D0EC4E50BB290A42E9E355C73D8809345DE2E139")), parameters));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public;
+            DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private;
+
+            if (!pub.Y.Equals(new BigInteger(
+                "25282217F5730501" +
+                "DD8DBA3EDFCF349AAFFEC20921128D70FAC44110332201BB" +
+                "A3F10986140CBB97C726938060473C8EC97B4731DB004293" +
+                "B5E730363609DF9780F8D883D8C4D41DED6A2F1E1BBBDC97" +
+                "9E1B9D6D3C940301F4E978D65B19041FCF1E8B518F5C0576" +
+                "C770FE5A7A485D8329EE2914A2DE1B5DA4A6128CEAB70F79", 16)))
+            {
+                Fail("Y value incorrect");
+            }
+
+            if (!priv.X.Equals(
+                new BigInteger("D0EC4E50BB290A42E9E355C73D8809345DE2E139", 16)))
+            {
+                Fail("X value incorrect");
+            }
+
+            DsaSigner signer = new DsaSigner();
+
+            signer.Init(true, new ParametersWithRandom(kp.Private, FixedSecureRandom.From(Hex.Decode("349C55648DCF992F3F33E8026CFAC87C1D2BA075"))));
+
+            byte[] msg = Hex.Decode("A9993E364706816ABA3E25717850C26C9CD0D89D");
+
+            BigInteger[] sig = signer.GenerateSignature(msg);
+
+            if (!sig[0].Equals(new BigInteger("636155AC9A4633B4665D179F9E4117DF68601F34", 16)))
+            {
+                Fail("R value incorrect");
+            }
+
+            if (!sig[1].Equals(new BigInteger("6C540B02D9D4852F89DF8CFC99963204F4347704", 16)))
+            {
+                Fail("S value incorrect");
+            }
+
+            signer.Init(false, kp.Public);
+
+            if (!signer.VerifySignature(msg, sig[0], sig[1]))
+            {
+                Fail("signature not verified");
+            }
+
+        }
+
+        private void Dsa2Test2()
+        {
+            byte[] seed = Hex.Decode("5AFCC1EFFC079A9CCA6ECA86D6E3CC3B18642D9BE1CC6207C84002A9");
+
+            DsaParametersGenerator pGen = new DsaParametersGenerator(new Sha224Digest());
+
+            pGen.Init(new DsaParameterGenerationParameters(2048, 224, 80, new DsaTestSecureRandom(seed)));
+
+            DsaParameters parameters = pGen.GenerateParameters();
+
+            DsaValidationParameters pv = parameters.ValidationParameters;
+
+            if (pv.Counter != 21)
+            {
+                Fail("counter incorrect");
+            }
+
+            if (!AreEqual(seed, pv.GetSeed()))
+            {
+                Fail("seed incorrect");
+            }
+
+            if (!parameters.Q.Equals(new BigInteger("90EAF4D1AF0708B1B612FF35E0A2997EB9E9D263C9CE659528945C0D", 16)))
+            {
+                Fail("Q incorrect");
+            }
+
+            if (!parameters.P.Equals(new BigInteger(
+                "C196BA05AC29E1F9C3C72D56DFFC6154" +
+                "A033F1477AC88EC37F09BE6C5BB95F51C296DD20D1A28A06" +
+                "7CCC4D4316A4BD1DCA55ED1066D438C35AEBAABF57E7DAE4" +
+                "28782A95ECA1C143DB701FD48533A3C18F0FE23557EA7AE6" +
+                "19ECACC7E0B51652A8776D02A425567DED36EABD90CA33A1" +
+                "E8D988F0BBB92D02D1D20290113BB562CE1FC856EEB7CDD9" +
+                "2D33EEA6F410859B179E7E789A8F75F645FAE2E136D252BF" +
+                "FAFF89528945C1ABE705A38DBC2D364AADE99BE0D0AAD82E" +
+                "5320121496DC65B3930E38047294FF877831A16D5228418D" +
+                "E8AB275D7D75651CEFED65F78AFC3EA7FE4D79B35F62A040" +
+                "2A1117599ADAC7B269A59F353CF450E6982D3B1702D9CA83", 16)))
+            {
+                Fail("P incorrect");
+            }
+
+            if (!parameters.G.Equals(new BigInteger(
+                "A59A749A11242C58C894E9E5A91804E8"+
+                "FA0AC64B56288F8D47D51B1EDC4D65444FECA0111D78F35F"+
+                "C9FDD4CB1F1B79A3BA9CBEE83A3F811012503C8117F98E50"+
+                "48B089E387AF6949BF8784EBD9EF45876F2E6A5A495BE64B"+
+                "6E770409494B7FEE1DBB1E4B2BC2A53D4F893D418B715959"+
+                "2E4FFFDF6969E91D770DAEBD0B5CB14C00AD68EC7DC1E574"+
+                "5EA55C706C4A1C5C88964E34D09DEB753AD418C1AD0F4FDF"+
+                "D049A955E5D78491C0B7A2F1575A008CCD727AB376DB6E69"+
+                "5515B05BD412F5B8C2F4C77EE10DA48ABD53F5DD498927EE"+
+                "7B692BBBCDA2FB23A516C5B4533D73980B2A3B60E384ED20"+
+                "0AE21B40D273651AD6060C13D97FD69AA13C5611A51B9085", 16)))
+            {
+                Fail("G incorrect");
+            }
+
+            DsaKeyPairGenerator kpGen = new DsaKeyPairGenerator();
+
+            kpGen.Init(new DsaKeyGenerationParameters(
+                FixedSecureRandom.From(Hex.Decode("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17")), parameters));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public;
+            DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private;
+
+            if (!pub.Y.Equals(new BigInteger(
+                "70035C9A3B225B258F16741F3941FBF0" +
+                "6F3D056CD7BD864604CBB5EE9DD85304EE8E8E4ABD5E9032" +
+                "11DDF25CE149075510ACE166970AFDC7DF552B7244F342FA" +
+                "02F7A621405B754909D757F97290E1FE5036E904CF593446" +
+                "0C046D95659821E1597ED9F2B1F0E20863A6BBD0CE74DACB" +
+                "A5D8C68A90B29C2157CDEDB82EC12B81EE3068F9BF5F7F34" +
+                "6ECA41ED174CCCD7D154FA4F42F80FFE1BF46AE9D8125DEB" +
+                "5B4BA08A72BDD86596DBEDDC9550FDD650C58F5AE5133509" +
+                "A702F79A31ECB490F7A3C5581631F7C5BE4FF7F9E9F27FA3" +
+                "90E47347AD1183509FED6FCF198BA9A71AB3335B4F38BE8D" +
+                "15496A00B6DC2263E20A5F6B662320A3A1EC033AA61E3B68", 16)))
+            {
+                Fail("Y value incorrect");
+            }
+
+            if (!priv.X.Equals(
+                new BigInteger("00D0F09ED3E2568F6CADF9224117DA2AEC5A4300E009DE1366023E17", 16)))
+            {
+                Fail("X value incorrect");
+            }
+
+            DsaSigner signer = new DsaSigner();
+
+            signer.Init(true, new ParametersWithRandom(kp.Private,
+                FixedSecureRandom.From(Hex.Decode("735959CC4463B8B440E407EECA8A473BF6A6D1FE657546F67D401F05"))));
+
+            byte[] msg = Hex.Decode("23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
+
+            BigInteger[] sig = signer.GenerateSignature(msg);
+
+            if (!sig[0].Equals(new BigInteger("4400138D05F9639CAF54A583CAAF25D2B76D0C3EAD752CE17DBC85FE", 16)))
+            {
+                Fail("R value incorrect");
+            }
+
+            if (!sig[1].Equals(new BigInteger("874D4F12CB13B61732D398445698CFA9D92381D938AA57EE2C9327B3", 16)))
+            {
+                Fail("S value incorrect");
+            }
+
+            signer.Init(false, kp.Public);
+
+            if (!signer.VerifySignature(msg, sig[0], sig[1]))
+            {
+                Fail("signature not verified");
+            }
+        }
+
+        private void Dsa2Test3()
+        {
+            byte[] seed = Hex.Decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
+
+            DsaParametersGenerator pGen = new DsaParametersGenerator(new Sha256Digest());
+
+            pGen.Init(new DsaParameterGenerationParameters(2048, 256, 80, new DsaTestSecureRandom(seed)));
+
+            DsaParameters parameters = pGen.GenerateParameters();
+
+            DsaValidationParameters pv = parameters.ValidationParameters;
+
+            if (pv.Counter != 12)
+            {
+                Fail("counter incorrect");
+            }
+
+            if (!AreEqual(seed, pv.GetSeed()))
+            {
+                Fail("seed incorrect");
+            }
+
+            if (!parameters.Q.Equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
+            {
+                Fail("Q incorrect");
+            }
+
+            if (!parameters.P.Equals(new BigInteger(
+                "F56C2A7D366E3EBDEAA1891FD2A0D099" +
+                "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
+                "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
+                "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
+                "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
+                "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
+                "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
+                "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
+                "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
+                "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
+                "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
+            {
+                Fail("P incorrect");
+            }
+
+            if (!parameters.G.Equals(new BigInteger(
+                "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
+                "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
+                "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
+                "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
+                "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
+                "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
+                "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
+                "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
+                "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
+                "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
+                "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
+            {
+                Fail("G incorrect");
+            }
+
+            DsaKeyPairGenerator kpGen = new DsaKeyPairGenerator();
+
+            kpGen.Init(new DsaKeyGenerationParameters(
+                FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), parameters));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public;
+            DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private;
+
+            if (!pub.Y.Equals(new BigInteger(
+                "2828003D7C747199143C370FDD07A286" +
+                "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
+                "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
+                "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
+                "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
+                "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
+                "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
+                "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
+                "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
+                "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
+                "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
+            {
+                Fail("Y value incorrect");
+            }
+
+            if (!priv.X.Equals(
+                new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
+            {
+                Fail("X value incorrect");
+            }
+
+            DsaSigner signer = new DsaSigner();
+
+            signer.Init(true, new ParametersWithRandom(kp.Private,
+                FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C"))));
+
+            byte[] msg = Hex.Decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+            BigInteger[] sig = signer.GenerateSignature(msg);
+
+            if (!sig[0].Equals(new BigInteger("315C875DCD4850E948B8AC42824E9483A32D5BA5ABE0681B9B9448D444F2BE3C", 16)))
+            {
+                Fail("R value incorrect");
+            }
+
+            if (!sig[1].Equals(new BigInteger("89718D12E54A8D9ED066E4A55F7ED5A2229CD23B9A3CEE78F83ED6AA61F6BCB9", 16)))
+            {
+                Fail("S value incorrect");
+            }
+
+            signer.Init(false, kp.Public);
+
+            if (!signer.VerifySignature(msg, sig[0], sig[1]))
+            {
+                Fail("signature not verified");
+            }
+        }
+
+        private void Dsa2Test4()
+        {
+            byte[] seed = Hex.Decode("193AFCA7C1E77B3C1ECC618C81322E47B8B8B997C9C83515C59CC446C2D9BD47");
+
+            DsaParametersGenerator pGen = new DsaParametersGenerator(new Sha256Digest());
+
+            pGen.Init(new DsaParameterGenerationParameters(3072, 256, 80, new DsaTestSecureRandom(seed)));
+
+            DsaParameters parameters = pGen.GenerateParameters();
+
+            DsaValidationParameters pv = parameters.ValidationParameters;
+
+            if (pv.Counter != 20)
+            {
+                Fail("counter incorrect");
+            }
+
+            if (!AreEqual(seed, pv.GetSeed()))
+            {
+                Fail("seed incorrect");
+            }
+
+            if (!parameters.Q.Equals(new BigInteger("CFA0478A54717B08CE64805B76E5B14249A77A4838469DF7F7DC987EFCCFB11D", 16)))
+            {
+                Fail("Q incorrect");
+            }
+
+            if (!parameters.P.Equals(new BigInteger(
+                "90066455B5CFC38F9CAA4A48B4281F292C260FEEF01FD610" +
+                "37E56258A7795A1C7AD46076982CE6BB956936C6AB4DCFE0" +
+                "5E6784586940CA544B9B2140E1EB523F009D20A7E7880E4E" +
+                "5BFA690F1B9004A27811CD9904AF70420EEFD6EA11EF7DA1" +
+                "29F58835FF56B89FAA637BC9AC2EFAAB903402229F491D8D" +
+                "3485261CD068699B6BA58A1DDBBEF6DB51E8FE34E8A78E54" +
+                "2D7BA351C21EA8D8F1D29F5D5D15939487E27F4416B0CA63" +
+                "2C59EFD1B1EB66511A5A0FBF615B766C5862D0BD8A3FE7A0" +
+                "E0DA0FB2FE1FCB19E8F9996A8EA0FCCDE538175238FC8B0E" +
+                "E6F29AF7F642773EBE8CD5402415A01451A840476B2FCEB0" +
+                "E388D30D4B376C37FE401C2A2C2F941DAD179C540C1C8CE0" +
+                "30D460C4D983BE9AB0B20F69144C1AE13F9383EA1C08504F" +
+                "B0BF321503EFE43488310DD8DC77EC5B8349B8BFE97C2C56" +
+                "0EA878DE87C11E3D597F1FEA742D73EEC7F37BE43949EF1A" +
+                "0D15C3F3E3FC0A8335617055AC91328EC22B50FC15B941D3" +
+                "D1624CD88BC25F3E941FDDC6200689581BFEC416B4B2CB73", 16)))
+            {
+                Fail("P incorrect");
+            }
+
+            if (!parameters.G.Equals(new BigInteger(
+                "5E5CBA992E0A680D885EB903AEA78E4A45A469103D448EDE" +
+                "3B7ACCC54D521E37F84A4BDD5B06B0970CC2D2BBB715F7B8" +
+                "2846F9A0C393914C792E6A923E2117AB805276A975AADB52" +
+                "61D91673EA9AAFFEECBFA6183DFCB5D3B7332AA19275AFA1" +
+                "F8EC0B60FB6F66CC23AE4870791D5982AAD1AA9485FD8F4A" +
+                "60126FEB2CF05DB8A7F0F09B3397F3937F2E90B9E5B9C9B6" +
+                "EFEF642BC48351C46FB171B9BFA9EF17A961CE96C7E7A7CC" +
+                "3D3D03DFAD1078BA21DA425198F07D2481622BCE45969D9C" +
+                "4D6063D72AB7A0F08B2F49A7CC6AF335E08C4720E31476B6" +
+                "7299E231F8BD90B39AC3AE3BE0C6B6CACEF8289A2E2873D5" +
+                "8E51E029CAFBD55E6841489AB66B5B4B9BA6E2F784660896" +
+                "AFF387D92844CCB8B69475496DE19DA2E58259B090489AC8" +
+                "E62363CDF82CFD8EF2A427ABCD65750B506F56DDE3B98856" +
+                "7A88126B914D7828E2B63A6D7ED0747EC59E0E0A23CE7D8A" +
+                "74C1D2C2A7AFB6A29799620F00E11C33787F7DED3B30E1A2" +
+                "2D09F1FBDA1ABBBFBF25CAE05A13F812E34563F99410E73B", 16)))
+            {
+                Fail("G incorrect");
+            }
+
+            DsaKeyPairGenerator kpGen = new DsaKeyPairGenerator();
+
+            kpGen.Init(new DsaKeyGenerationParameters(
+                FixedSecureRandom.From(Hex.Decode("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764")), parameters));
+
+            AsymmetricCipherKeyPair kp = kpGen.GenerateKeyPair();
+
+            DsaPublicKeyParameters pub = (DsaPublicKeyParameters)kp.Public;
+            DsaPrivateKeyParameters priv = (DsaPrivateKeyParameters)kp.Private;
+
+            if (!pub.Y.Equals(new BigInteger(
+                "8B891C8692D3DE875879390F2698B26FBECCA6B075535DCE" +
+                "6B0C862577F9FA0DEF6074E7A7624121224A595896ABD4CD" +
+                "A56B2CEFB942E025D2A4282FFAA98A48CDB47E1A6FCB5CFB" +
+                "393EF35AF9DF913102BB303C2B5C36C3F8FC04ED7B8B69FE" +
+                "FE0CF3E1FC05CFA713B3435B2656E913BA8874AEA9F93600" +
+                "6AEB448BCD005D18EC3562A33D04CF25C8D3D69844343442" +
+                "FA3DB7DE618C5E2DA064573E61E6D5581BFB694A23AC87FD" +
+                "5B52D62E954E1376DB8DDB524FFC0D469DF978792EE44173" +
+                "8E5DB05A7DC43E94C11A2E7A4FBE383071FA36D2A7EC8A93" +
+                "88FE1C4F79888A99D3B6105697C2556B79BB4D7E781CEBB3" +
+                "D4866AD825A5E830846072289FDBC941FA679CA82F5F78B7" +
+                "461B2404DB883D215F4E0676CF5493950AC5591697BFEA8D" +
+                "1EE6EC016B89BA51CAFB5F9C84C989FA117375E94578F28B" +
+                "E0B34CE0545DA46266FD77F62D8F2CEE92AB77012AFEBC11" +
+                "008985A821CD2D978C7E6FE7499D1AAF8DE632C21BB48CA5" +
+                "CBF9F31098FD3FD3854C49A65D9201744AACE540354974F9", 16)))
+            {
+                Fail("Y value incorrect");
+            }
+
+            if (!priv.X.Equals(
+                new BigInteger("3ABC1587297CE7B9EA1AD6651CF2BC4D7F92ED25CABC8553F567D1B40EBB8764", 16)))
+            {
+                Fail("X value incorrect");
+            }
+
+            DsaSigner signer = new DsaSigner();
+
+            signer.Init(true, new ParametersWithRandom(kp.Private,
+                FixedSecureRandom.From(Hex.Decode("A6902C1E6E3943C5628061588A8B007BCCEA91DBF12915483F04B24AB0678BEE"))));
+
+            byte[] msg = Hex.Decode("BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD");
+
+            BigInteger[] sig = signer.GenerateSignature(msg);
+
+            if (!sig[0].Equals(new BigInteger("5F184E645A38BE8FB4A6871B6503A9D12924C7ABE04B71410066C2ECA6E3BE3E", 16)))
+            {
+                Fail("R value incorrect");
+            }
+
+            if (!sig[1].Equals(new BigInteger("91EB0C7BA3D4B9B60B825C3D9F2CADA8A2C9D7723267B033CBCDCF8803DB9C18", 16)))
+            {
+                Fail("S value incorrect");
+            }
+
+            signer.Init(false, kp.Public);
+
+            if (!signer.VerifySignature(msg, sig[0], sig[1]))
+            {
+                Fail("signature not verified");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DsaTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        private class DsaTestSecureRandom
+            : FixedSecureRandom
+        {
+            private bool first = true;
+
+            public DsaTestSecureRandom(byte[] value)
+                : base(Arrays.Clone(value))
+            {
+            }
+
+            public override void NextBytes(byte[] bytes)
+            {
+                if (first)
+                {
+                    base.NextBytes(bytes);
+                    first = false;
+                }
+                else
+                {
+                    bytes[bytes.Length - 1] = 2;
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DeterministicDSATest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DeterministicDSATest.cs
new file mode 100644
index 0000000..914a770
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DeterministicDSATest.cs
@@ -0,0 +1,511 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary>
+    /// Tests are taken from RFC 6979 - "Deterministic Usage of the Digital Signature Algorithm (DSA) and Elliptic Curve Digital Signature Algorithm (ECDSA)".
+    /// </summary>
+    [TestFixture]
+    public class DeterministicDsaTest
+        :   SimpleTest
+    {
+        public static readonly byte[] SAMPLE = Hex.Decode("73616d706c65"); // "sample"
+        public static readonly byte[] TEST = Hex.Decode("74657374"); // "test"
+
+        // test vectors from appendix in RFC 6979
+        private void TestHMacDeterministic()
+        {
+            DsaParameters dsaParameters = new DsaParameters(
+                new BigInteger("86F5CA03DCFEB225063FF830A0C769B9DD9D6153AD91D7CE27F787C43278B447" +
+                               "E6533B86B18BED6E8A48B784A14C252C5BE0DBF60B86D6385BD2F12FB763ED88" +
+                               "73ABFD3F5BA2E0A8C0A59082EAC056935E529DAF7C610467899C77ADEDFC846C" +
+                               "881870B7B19B2B58F9BE0521A17002E3BDD6B86685EE90B3D9A1B02B782B1779", 16),
+                new BigInteger("996F967F6C8E388D9E28D01E205FBA957A5698B1", 16),
+                new BigInteger("07B0F92546150B62514BB771E2A0C0CE387F03BDA6C56B505209FF25FD3C133D" +
+                               "89BBCD97E904E09114D9A7DEFDEADFC9078EA544D2E401AEECC40BB9FBBF78FD" +
+                               "87995A10A1C27CB7789B594BA7EFB5C4326A9FE59A070E136DB77175464ADCA4" +
+                               "17BE5DCE2F40D10A46A3A3943F26AB7FD9C0398FF8C76EE0A56826A8A88F1DBD", 16));
+
+            DsaPrivateKeyParameters privKey = new DsaPrivateKeyParameters(new BigInteger("411602CB19A6CCC34494D79D98EF1E7ED5AF25F7", 16), dsaParameters);
+
+            DoTestHMacDetDsaSample(new Sha1Digest(), privKey, new BigInteger("2E1A0C2562B2912CAAF89186FB0F42001585DA55", 16), new BigInteger("29EFB6B0AFF2D7A68EB70CA313022253B9A88DF5", 16));
+            DoTestHMacDetDsaSample(new Sha224Digest(), privKey, new BigInteger("4BC3B686AEA70145856814A6F1BB53346F02101E", 16), new BigInteger("410697B92295D994D21EDD2F4ADA85566F6F94C1", 16));
+            DoTestHMacDetDsaSample(new Sha256Digest(), privKey, new BigInteger("81F2F5850BE5BC123C43F71A3033E9384611C545", 16), new BigInteger("4CDD914B65EB6C66A8AAAD27299BEE6B035F5E89", 16));
+            DoTestHMacDetDsaSample(new Sha384Digest(), privKey, new BigInteger("07F2108557EE0E3921BC1774F1CA9B410B4CE65A", 16), new BigInteger("54DF70456C86FAC10FAB47C1949AB83F2C6F7595", 16));
+            DoTestHMacDetDsaSample(new Sha512Digest(), privKey, new BigInteger("16C3491F9B8C3FBBDD5E7A7B667057F0D8EE8E1B", 16), new BigInteger("02C36A127A7B89EDBB72E4FFBC71DABC7D4FC69C", 16));
+
+            DoTestHMacDetDsaTest(new Sha1Digest(), privKey, new BigInteger("42AB2052FD43E123F0607F115052A67DCD9C5C77", 16), new BigInteger("183916B0230D45B9931491D4C6B0BD2FB4AAF088", 16));
+            DoTestHMacDetDsaTest(new Sha224Digest(), privKey, new BigInteger("6868E9964E36C1689F6037F91F28D5F2C30610F2", 16), new BigInteger("49CEC3ACDC83018C5BD2674ECAAD35B8CD22940F", 16));
+            DoTestHMacDetDsaTest(new Sha256Digest(), privKey, new BigInteger("22518C127299B0F6FDC9872B282B9E70D0790812", 16), new BigInteger("6837EC18F150D55DE95B5E29BE7AF5D01E4FE160", 16));
+            DoTestHMacDetDsaTest(new Sha384Digest(), privKey, new BigInteger("854CF929B58D73C3CBFDC421E8D5430CD6DB5E66", 16), new BigInteger("91D0E0F53E22F898D158380676A871A157CDA622", 16));
+            DoTestHMacDetDsaTest(new Sha512Digest(), privKey, new BigInteger("8EA47E475BA8AC6F2D821DA3BD212D11A3DEB9A0", 16), new BigInteger("7C670C7AD72B6C050C109E1790008097125433E8", 16));
+
+            dsaParameters = new DsaParameters(
+                new BigInteger("9DB6FB5951B66BB6FE1E140F1D2CE5502374161FD6538DF1648218642F0B5C48" +
+                    "C8F7A41AADFA187324B87674FA1822B00F1ECF8136943D7C55757264E5A1A44F" +
+                    "FE012E9936E00C1D3E9310B01C7D179805D3058B2A9F4BB6F9716BFE6117C6B5" +
+                    "B3CC4D9BE341104AD4A80AD6C94E005F4B993E14F091EB51743BF33050C38DE2" +
+                    "35567E1B34C3D6A5C0CEAA1A0F368213C3D19843D0B4B09DCB9FC72D39C8DE41" +
+                    "F1BF14D4BB4563CA28371621CAD3324B6A2D392145BEBFAC748805236F5CA2FE" +
+                    "92B871CD8F9C36D3292B5509CA8CAA77A2ADFC7BFD77DDA6F71125A7456FEA15" +
+                    "3E433256A2261C6A06ED3693797E7995FAD5AABBCFBE3EDA2741E375404AE25B", 16),
+                new BigInteger("F2C3119374CE76C9356990B465374A17F23F9ED35089BD969F61C6DDE9998C1F", 16),
+                new BigInteger("5C7FF6B06F8F143FE8288433493E4769C4D988ACE5BE25A0E24809670716C613" +
+                    "D7B0CEE6932F8FAA7C44D2CB24523DA53FBE4F6EC3595892D1AA58C4328A06C4" +
+                    "6A15662E7EAA703A1DECF8BBB2D05DBE2EB956C142A338661D10461C0D135472" +
+                    "085057F3494309FFA73C611F78B32ADBB5740C361C9F35BE90997DB2014E2EF5" +
+                    "AA61782F52ABEB8BD6432C4DD097BC5423B285DAFB60DC364E8161F4A2A35ACA" +
+                    "3A10B1C4D203CC76A470A33AFDCBDD92959859ABD8B56E1725252D78EAC66E71" +
+                    "BA9AE3F1DD2487199874393CD4D832186800654760E1E34C09E4D155179F9EC0" +
+                    "DC4473F996BDCE6EED1CABED8B6F116F7AD9CF505DF0F998E34AB27514B0FFE7", 16));
+
+            privKey = new DsaPrivateKeyParameters(new BigInteger("69C7548C21D0DFEA6B9A51C9EAD4E27C33D3B3F180316E5BCAB92C933F0E4DBC", 16), dsaParameters);
+
+            DoTestHMacDetDsaSample(new Sha1Digest(), privKey, new BigInteger("3A1B2DBD7489D6ED7E608FD036C83AF396E290DBD602408E8677DAABD6E7445A", 16), new BigInteger("D26FCBA19FA3E3058FFC02CA1596CDBB6E0D20CB37B06054F7E36DED0CDBBCCF", 16));
+            DoTestHMacDetDsaSample(new Sha224Digest(), privKey, new BigInteger("DC9F4DEADA8D8FF588E98FED0AB690FFCE858DC8C79376450EB6B76C24537E2C", 16), new BigInteger("A65A9C3BC7BABE286B195D5DA68616DA8D47FA0097F36DD19F517327DC848CEC", 16));
+            DoTestHMacDetDsaSample(new Sha256Digest(), privKey, new BigInteger("EACE8BDBBE353C432A795D9EC556C6D021F7A03F42C36E9BC87E4AC7932CC809", 16), new BigInteger("7081E175455F9247B812B74583E9E94F9EA79BD640DC962533B0680793A38D53", 16));
+            DoTestHMacDetDsaSample(new Sha384Digest(), privKey, new BigInteger("B2DA945E91858834FD9BF616EBAC151EDBC4B45D27D0DD4A7F6A22739F45C00B", 16), new BigInteger("19048B63D9FD6BCA1D9BAE3664E1BCB97F7276C306130969F63F38FA8319021B", 16));
+            DoTestHMacDetDsaSample(new Sha512Digest(), privKey, new BigInteger("2016ED092DC5FB669B8EFB3D1F31A91EECB199879BE0CF78F02BA062CB4C942E", 16), new BigInteger("D0C76F84B5F091E141572A639A4FB8C230807EEA7D55C8A154A224400AFF2351", 16));
+
+            DoTestHMacDetDsaTest(new Sha1Digest(), privKey, new BigInteger("C18270A93CFC6063F57A4DFA86024F700D980E4CF4E2CB65A504397273D98EA0", 16), new BigInteger("414F22E5F31A8B6D33295C7539C1C1BA3A6160D7D68D50AC0D3A5BEAC2884FAA", 16));
+            DoTestHMacDetDsaTest(new Sha224Digest(), privKey, new BigInteger("272ABA31572F6CC55E30BF616B7A265312018DD325BE031BE0CC82AA17870EA3", 16), new BigInteger("E9CC286A52CCE201586722D36D1E917EB96A4EBDB47932F9576AC645B3A60806", 16));
+            DoTestHMacDetDsaTest(new Sha256Digest(), privKey, new BigInteger("8190012A1969F9957D56FCCAAD223186F423398D58EF5B3CEFD5A4146A4476F0", 16), new BigInteger("7452A53F7075D417B4B013B278D1BB8BBD21863F5E7B1CEE679CF2188E1AB19E", 16));
+            DoTestHMacDetDsaTest(new Sha384Digest(), privKey, new BigInteger("239E66DDBE8F8C230A3D071D601B6FFBDFB5901F94D444C6AF56F732BEB954BE", 16), new BigInteger("6BD737513D5E72FE85D1C750E0F73921FE299B945AAD1C802F15C26A43D34961", 16));
+            DoTestHMacDetDsaTest(new Sha512Digest(), privKey, new BigInteger("89EC4BB1400ECCFF8E7D9AA515CD1DE7803F2DAFF09693EE7FD1353E90A68307", 16), new BigInteger("C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1", 16));
+        }
+
+        private void DoTestHMacDetDsaSample(IDigest digest, DsaPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+        {
+            DoTestHMacDetECDsa(new DsaSigner(new HMacDsaKCalculator(digest)), digest, SAMPLE, privKey, r, s);
+        }
+
+        private void DoTestHMacDetDsaTest(IDigest digest, DsaPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+        {
+            DoTestHMacDetECDsa(new DsaSigner(new HMacDsaKCalculator(digest)), digest, TEST, privKey, r, s);
+        }
+
+        // test vectors from appendix in RFC 6979
+        private void TestECHMacDeterministic()
+        {
+            X9ECParameters x9ECParameters = NistNamedCurves.GetByName("P-192");
+            ECDomainParameters ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(new BigInteger("6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", 16), new BigInteger("57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", 16), new BigInteger("E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", 16), new BigInteger("CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", 16), new BigInteger("C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", 16), new BigInteger("3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", 16), new BigInteger("EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", 16), new BigInteger("B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", 16), new BigInteger("5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", 16), new BigInteger("7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", 16), new BigInteger("74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("P-224");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("22226F9D40A96E19C4A301CE5B74B115303C0F3A4FD30FC257FB57AC", 16), new BigInteger("66D1CDD83E3AF75605DD6E2FEFF196D30AA7ED7A2EDF7AF475403D69", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("1CDFE6662DDE1E4A1EC4CDEDF6A1F5A2FB7FBD9145C12113E6ABFD3E", 16), new BigInteger("A6694FD7718A21053F225D3F46197CA699D45006C06F871808F43EBC", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("61AA3DA010E8E8406C656BC477A7A7189895E7E840CDFE8FF42307BA", 16), new BigInteger("BC814050DAB5D23770879494F9E0A680DC1AF7161991BDE692B10101", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("0B115E5E36F0F9EC81F1325A5952878D745E19D7BB3EABFABA77E953", 16), new BigInteger("830F34CCDFE826CCFDC81EB4129772E20E122348A2BBD889A1B1AF1D", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("074BD1D979D5F32BF958DDC61E4FB4872ADCAFEB2256497CDAC30397", 16), new BigInteger("A4CECA196C3D5A1FF31027B33185DC8EE43F288B21AB342E5D8EB084", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("DEAA646EC2AF2EA8AD53ED66B2E2DDAA49A12EFD8356561451F3E21C", 16), new BigInteger("95987796F6CF2062AB8135271DE56AE55366C045F6D9593F53787BD2", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("C441CE8E261DED634E4CF84910E4C5D1D22C5CF3B732BB204DBEF019", 16), new BigInteger("902F42847A63BDC5F6046ADA114953120F99442D76510150F372A3F4", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("AD04DDE87B84747A243A631EA47A1BA6D1FAA059149AD2440DE6FBA6", 16), new BigInteger("178D49B1AE90E3D8B629BE3DB5683915F4E8C99FDF6E666CF37ADCFD", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("389B92682E399B26518A95506B52C03BC9379A9DADF3391A21FB0EA4", 16), new BigInteger("414A718ED3249FF6DBC5B50C27F71F01F070944DA22AB1F78F559AAB", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("049F050477C5ADD858CAC56208394B5A55BAEBBE887FDF765047C17C", 16), new BigInteger("077EB13E7005929CEFA3CD0403C7CDCC077ADF4E44F3C41B2F60ECFF", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("P-256");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("61340C88C3AAEBEB4F6D667F672CA9759A6CCAA9FA8811313039EE4A35471D32", 16), new BigInteger("6D7F147DAC089441BB2E2FE8F7A3FA264B9C475098FDCF6E00D7C996E1B8B7EB", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("53B2FFF5D1752B2C689DF257C04C40A587FABABB3F6FC2702F1343AF7CA9AA3F", 16), new BigInteger("B9AFB64FDC03DC1A131C7D2386D11E349F070AA432A4ACC918BEA988BF75C74C", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("EFD48B2AACB6A8FD1140DD9CD45E81D69D2C877B56AAF991C34D0EA84EAF3716", 16), new BigInteger("F7CB1C942D657C41D436C7A1B6E29F65F3E900DBB9AFF4064DC4AB2F843ACDA8", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("0EAFEA039B20E9B42309FB1D89E213057CBF973DC0CFC8F129EDDDC800EF7719", 16), new BigInteger("4861F0491E6998B9455193E34E7B0D284DDD7149A74B95B9261F13ABDE940954", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("8496A60B5E9B47C825488827E0495B0E3FA109EC4568FD3F8D1097678EB97F00", 16), new BigInteger("2362AB1ADBE2B8ADF9CB9EDAB740EA6049C028114F2460F96554F61FAE3302FE", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("0CBCC86FD6ABD1D99E703E1EC50069EE5C0B4BA4B9AC60E409E8EC5910D81A89", 16), new BigInteger("01B9D7B73DFAA60D5651EC4591A0136F87653E0FD780C3B1BC872FFDEAE479B1", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("C37EDB6F0AE79D47C3C27E962FA269BB4F441770357E114EE511F662EC34A692", 16), new BigInteger("C820053A05791E521FCAAD6042D40AEA1D6B1A540138558F47D0719800E18F2D", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("F1ABB023518351CD71D881567B1EA663ED3EFCF6C5132B354F28D3B0B7D38367", 16), new BigInteger("019F4113742A2B14BD25926B49C649155F267E60D3814B4C0CC84250E46F0083", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("83910E8B48BB0C74244EBDF7F07A1C5413D61472BD941EF3920E623FBCCEBEB6", 16), new BigInteger("8DDBEC54CF8CD5874883841D712142A56A8D0F218F5003CB0296B6B509619F2C", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("461D93F31B6540894788FD206C07CFA0CC35F46FA3C91816FFF1040AD1581A04", 16), new BigInteger("39AF9F15DE0DB8D97E72719C74820D304CE5226E32DEDAE67519E840D1194E55", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("P-384");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" +
+                                                                "96D5724E4C70A825F872C9EA60D2EDF5", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey, new BigInteger("EC748D839243D6FBEF4FC5C4859A7DFFD7F3ABDDF72014540C16D73309834FA3" +
+                                                                        "7B9BA002899F6FDA3A4A9386790D4EB2", 16),
+                                                                new BigInteger("A3BCFA947BEEF4732BF247AC17F71676CB31A847B9FF0CBC9C9ED4C1A5B3FACF" +
+                                                                        "26F49CA031D4857570CCB5CA4424A443", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("42356E76B55A6D9B4631C865445DBE54E056D3B3431766D0509244793C3F9366" +
+                                                                            "450F76EE3DE43F5A125333A6BE060122", 16),
+                                                                  new BigInteger("9DA0C81787064021E78DF658F2FBB0B042BF304665DB721F077A4298B095E483" +
+                                                                            "4C082C03D83028EFBF93A3C23940CA8D", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33" +
+                                                                            "BDE1E888E63355D92FA2B3C36D8FB2CD", 16),
+                                                                    new BigInteger("F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB" +
+                                                                            "EFDC63ECCD1AC42EC0CB8668A4FA0AB0", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("94EDBB92A5ECB8AAD4736E56C691916B3F88140666CE9FA73D64C4EA95AD133C" +
+                                                                            "81A648152E44ACF96E36DD1E80FABE46", 16),
+                                                                    new BigInteger("99EF4AEB15F178CEA1FE40DB2603138F130E740A19624526203B6351D0A3A94F" +
+                                                                            "A329C145786E679E7B82C71A38628AC8", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("ED0959D5880AB2D869AE7F6C2915C6D60F96507F9CB3E047C0046861DA4A799C" +
+                                                                            "FE30F35CC900056D7C99CD7882433709", 16),
+                                                                    new BigInteger("512C8CCEEE3890A84058CE1E22DBC2198F42323CE8ACA9135329F03C068E5112" +
+                                                                            "DC7CC3EF3446DEFCEB01A45C2667FDD5", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey, new BigInteger("4BC35D3A50EF4E30576F58CD96CE6BF638025EE624004A1F7789A8B8E43D0678" +
+                                                                        "ACD9D29876DAF46638645F7F404B11C7", 16),
+                                                                new BigInteger("D5A6326C494ED3FF614703878961C0FDE7B2C278F9A65FD8C4B7186201A29916" +
+                                                                        "95BA1C84541327E966FA7B50F7382282", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("E8C9D0B6EA72A0E7837FEA1D14A1A9557F29FAA45D3E7EE888FC5BF954B5E624" +
+                                                                        "64A9A817C47FF78B8C11066B24080E72", 16),
+                                                                new BigInteger("07041D4A7A0379AC7232FF72E6F77B6DDB8F09B16CCE0EC3286B2BD43FA8C614" +
+                                                                        "1C53EA5ABEF0D8231077A04540A96B66", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("6D6DEFAC9AB64DABAFE36C6BF510352A4CC27001263638E5B16D9BB51D451559" +
+                                                                        "F918EEDAF2293BE5B475CC8F0188636B", 16),
+                                                                new BigInteger("2D46F3BECBCC523D5F1A1256BF0C9B024D879BA9E838144C8BA6BAEB4B53B47D" +
+                                                                        "51AB373F9845C0514EEFB14024787265", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("8203B63D3C853E8D77227FB377BCF7B7B772E97892A80F36AB775D509D7A5FEB" +
+                                                                        "0542A7F0812998DA8F1DD3CA3CF023DB", 16),
+                                                                new BigInteger("DDD0760448D42D8A43AF45AF836FCE4DE8BE06B485E9B61B827C2F13173923E0" +
+                                                                        "6A739F040649A667BF3B828246BAA5A5", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("A0D5D090C9980FAF3C2CE57B7AE951D31977DD11C775D314AF55F76C676447D0" +
+                                                                        "6FB6495CD21B4B6E340FC236584FB277", 16),
+                                                                new BigInteger("976984E59B4C77B0E8E4460DCA3D9F20E07B9BB1F63BEEFAF576F6B2E8B22463" +
+                                                                        "4A2092CD3792E0159AD9CEE37659C736", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("P-521");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75C" +
+                                                                "AA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83" +
+                                                                "538", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("0343B6EC45728975EA5CBA6659BBB6062A5FF89EEA58BE3C80B619F322C87910" +
+                                                                                 "FE092F7D45BB0F8EEE01ED3F20BABEC079D202AE677B243AB40B5431D497C55D" +
+                                                                                 "75D", 16),
+                                                                  new BigInteger("0E7B0E675A9B24413D448B8CC119D2BF7B2D2DF032741C096634D6D65D0DBE3D" +
+                                                                                 "5694625FB9E8104D3B842C1B0E2D0B98BEA19341E8676AEF66AE4EBA3D5475D5" +
+                                                                                 "D16", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("1776331CFCDF927D666E032E00CF776187BC9FDD8E69D0DABB4109FFE1B5E2A3" +
+                                                                                "0715F4CC923A4A5E94D2503E9ACFED92857B7F31D7152E0F8C00C15FF3D87E2E" +
+                                                                                "D2E", 16),
+                                                                  new BigInteger("050CB5265417FE2320BBB5A122B8E1A32BD699089851128E360E620A30C7E17B" +
+                                                                                "A41A666AF126CE100E5799B153B60528D5300D08489CA9178FB610A2006C254B" +
+                                                                                "41F", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659" +
+                                                                                 "D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E" +
+                                                                                 "1A7", 16),
+                                                                  new BigInteger("04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916" +
+                                                                                  "E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E" +
+                                                                                  "CFC", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("1EA842A0E17D2DE4F92C15315C63DDF72685C18195C2BB95E572B9C5136CA4B4" +
+                                                                                "B576AD712A52BE9730627D16054BA40CC0B8D3FF035B12AE75168397F5D50C67" +
+                                                                                "451", 16),
+                                                                  new BigInteger("1F21A3CEE066E1961025FB048BD5FE2B7924D0CD797BABE0A83B66F1E35EEAF5" +
+                                                                                  "FDE143FA85DC394A7DEE766523393784484BDF3E00114A1C857CDE1AA203DB65" +
+                                                                                  "D61", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("0C328FAFCBD79DD77850370C46325D987CB525569FB63C5D3BC53950E6D4C5F1" +
+                                                                                "74E25A1EE9017B5D450606ADD152B534931D7D4E8455CC91F9B15BF05EC36E37" +
+                                                                                "7FA", 16),
+                                                                  new BigInteger("0617CCE7CF5064806C467F678D3B4080D6F1CC50AF26CA209417308281B68AF2" +
+                                                                                  "82623EAA63E5B5C0723D8B8C37FF0777B1A20F8CCB1DCCC43997F1EE0E44DA4A" +
+                                                                                  "67A", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("13BAD9F29ABE20DE37EBEB823C252CA0F63361284015A3BF430A46AAA80B87B0" +
+                                                                        "693F0694BD88AFE4E661FC33B094CD3B7963BED5A727ED8BD6A3A202ABE009D0" +
+                                                                        "367", 16),
+                                                                  new BigInteger("1E9BB81FF7944CA409AD138DBBEE228E1AFCC0C890FC78EC8604639CB0DBDC90" +
+                                                                      "F717A99EAD9D272855D00162EE9527567DD6A92CBD629805C0445282BBC91679" +
+                                                                      "7FF", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("1C7ED902E123E6815546065A2C4AF977B22AA8EADDB68B2C1110E7EA44D42086" +
+                                                                        "BFE4A34B67DDC0E17E96536E358219B23A706C6A6E16BA77B65E1C595D43CAE1" +
+                                                                        "7FB", 16),
+                                                                  new BigInteger("177336676304FCB343CE028B38E7B4FBA76C1C1B277DA18CAD2A8478B2A9A9F5" +
+                                                                      "BEC0F3BA04F35DB3E4263569EC6AADE8C92746E4C82F8299AE1B8F1739F8FD51" +
+                                                                      "9A4", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("00E871C4A14F993C6C7369501900C4BC1E9C7B0B4BA44E04868B30B41D807104" +
+                                                                        "2EB28C4C250411D0CE08CD197E4188EA4876F279F90B3D8D74A3C76E6F1E4656" +
+                                                                        "AA8", 16),
+                                                                  new BigInteger("0CD52DBAA33B063C3A6CD8058A1FB0A46A4754B034FCC644766CA14DA8CA5CA9" +
+                                                                      "FDE00E88C1AD60CCBA759025299079D7A427EC3CC5B619BFBC828E7769BCD694" +
+                                                                      "E86", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("14BEE21A18B6D8B3C93FAB08D43E739707953244FDBE924FA926D76669E7AC8C" +
+                                                                        "89DF62ED8975C2D8397A65A49DCC09F6B0AC62272741924D479354D74FF60755" +
+                                                                        "78C", 16),
+                                                                  new BigInteger("133330865C067A0EAF72362A65E2D7BC4E461E8C8995C3B6226A21BD1AA78F0E" +
+                                                                      "D94FE536A0DCA35534F0CD1510C41525D163FE9D74D134881E35141ED5E8E95B" +
+                                                                      "979", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("13E99020ABF5CEE7525D16B69B229652AB6BDF2AFFCAEF38773B4B7D08725F10" +
+                                                                        "CDB93482FDCC54EDCEE91ECA4166B2A7C6265EF0CE2BD7051B7CEF945BABD47E" +
+                                                                        "E6D", 16),
+                                                                  new BigInteger("1FBD0013C674AA79CB39849527916CE301C66EA7CE8B80682786AD60F98F7E78" +
+                                                                      "A19CA69EFF5C57400E3B3A0AD66CE0978214D13BAF4E9AC60752F7B155E2DE4D" +
+                                                                      "CE3", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("B-163");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("35318FC447D48D7E6BC93B48617DDDEDF26AA658F", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("153FEBD179A69B6122DEBF5BC61EB947B24C93526", 16), new BigInteger("37AC9C670F8CF18045049BAE7DD35553545C19E49", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("0A379E69C44F9C16EA3215EA39EB1A9B5D58CC955", 16), new BigInteger("04BAFF5308DA2A7FE2C1742769265AD3ED1D24E74", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("134E00F78FC1CB9501675D91C401DE20DDF228CDC", 16), new BigInteger("373273AEC6C36CB7BAFBB1903A5F5EA6A1D50B624", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("29430B935AF8E77519B0CA4F6903B0B82E6A21A66", 16), new BigInteger("1EA1415306E9353FA5AA54BC7C2581DFBB888440D", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("0B2F177A99F9DF2D51CCAF55F015F326E4B65E7A0", 16), new BigInteger("0DF1FB4487E9B120C5E970EFE48F55E406306C3A1", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("256D4079C6C7169B8BC92529D701776A269D56308", 16), new BigInteger("341D3FFEC9F1EB6A6ACBE88E3C86A1C8FDEB8B8E1", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("28ECC6F1272CE80EA59DCF32F7AC2D861BA803393", 16), new BigInteger("0AD4AE2C06E60183C1567D2B82F19421FE3053CE2", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("227DF377B3FA50F90C1CB3CDCBBDBA552C1D35104", 16), new BigInteger("1F7BEAD92583FE920D353F368C1960D0E88B46A56", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("11811DAFEEA441845B6118A0DFEE8A0061231337D", 16), new BigInteger("36258301865EE48C5C6F91D63F62695002AB55B57", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("3B6BB95CA823BE2ED8E3972FF516EB8972D765571", 16), new BigInteger("13DC6F420628969DF900C3FCC48220B38BE24A541", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("B-233");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("07ADC13DD5BF34D1DDEEB50B2CE23B5F5E6D18067306D60C5F6FF11E5D3", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("015CC6FD78BB06E0878E71465515EA5A21A2C18E6FC77B4B158DBEB3944", 16), new BigInteger("0822A4A6C2EB2DF213A5E90BF40377956365EE8C4B4A5A4E2EB9270CB6A", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("05D9920B53471148E10502AB49AB7A3F11084820A074FD89883CF51BC1A", 16), new BigInteger("04D3938900C0A9AAA7080D1DFEB56CFB0FADABE4214536C7ED5117ED13A", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("0A797F3B8AEFCE7456202DF1E46CCC291EA5A49DA3D4BDDA9A4B62D5E0D", 16), new BigInteger("01F6F81DA55C22DA4152134C661588F4BD6F82FDBAF0C5877096B070DC2", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("015E85A8D46225DD7E314A1C4289731FC14DECE949349FE535D11043B85", 16), new BigInteger("03F189D37F50493EFD5111A129443A662AB3C6B289129AD8C0CAC85119C", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("03B62A4BF783919098B1E42F496E65F7621F01D1D466C46940F0F132A95", 16), new BigInteger("0F4BE031C6E5239E7DAA014CBBF1ED19425E49DAEB426EC9DF4C28A2E30", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("02F1FEDC57BE203E4C8C6B8C1CEB35E13C1FCD956AB41E3BD4C8A6EFB1F", 16), new BigInteger("05738EC8A8EDEA8E435EE7266AD3EDE1EEFC2CEBE2BE1D614008D5D2951", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("0CCE175124D3586BA7486F7146894C65C2A4A5A1904658E5C7F9DF5FA5D", 16), new BigInteger("08804B456D847ACE5CA86D97BF79FD6335E5B17F6C0D964B5D0036C867E", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("035C3D6DFEEA1CFB29B93BE3FDB91A7B130951770C2690C16833A159677", 16), new BigInteger("0600F7301D12AB376B56D4459774159ADB51F97E282FF384406AFD53A02", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("061602FC8068BFD5FB86027B97455D200EC603057446CCE4D76DB8EF42C", 16), new BigInteger("03396DD0D59C067BB999B422D9883736CF9311DFD6951F91033BD03CA8D", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("07E12CB60FDD614958E8E34B3C12DDFF35D85A9C5800E31EA2CC2EF63B1", 16), new BigInteger("0E8970FD99D836F3CC1C807A2C58760DE6EDAA23705A82B9CB1CE93FECC", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("B-283");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("14510D4BC44F2D26F4553942C98073C1BD35545CEABB5CC138853C5158D2729EA408836", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("201E18D48C6DB3D5D097C4DCE1E25587E1501FC3CF47BDB5B4289D79E273D6A9" +
+                "ACB8285", 16), new BigInteger("151AE05712B024CE617358260774C8CA8B0E7A7E72EF8229BF2ACE7609560CB3" +
+                "0322C4F", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("143E878DDFD4DF40D97B8CD638B3C4706501C2201CF7108F2FB91478C11D6947" +
+                "3246925", 16), new BigInteger("0CBF1B9717FEEA3AABB09D9654110144267098E0E1E8D0289A6211BE0EEDFDD8" +
+                "6A3DB79", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("29FD82497FB3E5CEF65579272138DE59E2B666B8689466572B3B69A172CEE83B" +
+                "E145659", 16), new BigInteger("05A89D9166B40795AF0FE5958201B9C0523E500013CA12B4840EA2BC53F25F9B" +
+                "3CE87C0", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("2F00689C1BFCD2A8C7A41E0DE55AE182E6463A152828EF89FE3525139B660329" +
+                "4E69353", 16), new BigInteger("1744514FE0A37447250C8A329EAAADA81572226CABA16F39270EE5DD03F27B1F" +
+                "665EB5D", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("0DA43A9ADFAA6AD767998A054C6A8F1CF77A562924628D73C62761847AD8286E" +
+                "0D91B47", 16), new BigInteger("1D118733AE2C88357827CAFC6F68ABC25C80C640532925E95CFE66D40F8792F3" +
+                "AC44C42", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey,   new BigInteger("05A408133919F2CDCDBE5E4C14FBC706C1F71BADAFEF41F5DE4EC27272FC1CA9" +
+                "366FBB2", 16), new BigInteger("012966272872C097FEA7BCE64FAB1A81982A773E26F6E4EF7C99969846E67CA9" +
+                "CBE1692", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("08F3824E40C16FF1DDA8DC992776D26F4A5981AB5092956C4FDBB4F1AE0A711E" +
+                "EAA10E5", 16), new BigInteger("0A64B91EFADB213E11483FB61C73E3EF63D3B44EEFC56EA401B99DCC60CC28E9" +
+                "9F0F1FA", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("3597B406F5329D11A79E887847E5EC60861CCBB19EC61F252DB7BD549C699951" +
+                "C182796", 16), new BigInteger("0A6A100B997BC622D91701D9F5C6F6D3815517E577622DA69D3A0E8917C1CBE6" +
+                "3ACD345", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("1BB490926E5A1FDC7C5AA86D0835F9B994EDA315CA408002AF54A298728D422E" +
+                "BF59E4C", 16), new BigInteger("36C682CFC9E2C89A782BFD3A191609D1F0C1910D5FD6981442070393159D65FB" +
+                "CC0A8BA", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("19944AA68F9778C2E3D6E240947613E6DA60EFCE9B9B2C063FF5466D72745B5A" +
+                "0B25BA2", 16), new BigInteger("03F1567B3C5B02DF15C874F0EE22850824693D5ADC4663BAA19E384E550B1DD4" +
+                "1F31EE6", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("B-409");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("0494994CC325B08E7B4CE038BD9436F90B5E59A2C13C3140CD3AE07C04A01FC489F572CE0569A6DB7B8060393DE76330C624177", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey,   new BigInteger("0D8783188E1A540E2022D389E1D35B32F56F8C2BB5636B8ABF7718806B27A713" +
+                "EBAE37F63ECD4B61445CEF5801B62594EF3E982", 16), new BigInteger("03A6B4A80E204DB0DE12E7415C13C9EC091C52935658316B4A0C591216A38791" +
+                "54BEB1712560E346E7EF26517707435B55C3141", 16));
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("0EE4F39ACC2E03CE96C3D9FCBAFA5C22C89053662F8D4117752A9B10F09ADFDA" +
+                "59DB061E247FE5321D6B170EE758ACE1BE4D157", 16), new BigInteger("00A2B83265B456A430A8BF27DCC8A9488B3F126C10F0D6D64BF7B8A218FAAF20" +
+                "E51A295A3AE78F205E5A4A6AE224C3639F1BB34", 16));
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("02D8B1B31E33E74D7EB46C30FDE5AD2CA04EC8FE08FBA0E73BA5E568953AC5EA" +
+                "307C072942238DFC07F4A4D7C7C6A9F86436D17", 16), new BigInteger("079F7D471E6CB73234AF7F7C381D2CE15DE35BAF8BB68393B73235B3A26EC2DF" +
+                "4842CE433FB492D6E074E604D4870024D42189A", 16));
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("07BC638B7E7CE6FEE5E9C64A0F966D722D01BB4BC3F3A35F30D4CDDA92DFC5F7" +
+                "F0B4BBFE8065D9AD452FD77A1914BE3A2440C18", 16), new BigInteger("06D904429850521B28A32CBF55C7C0FDF35DC4E0BDA2552C7BF68A171E970E67" +
+                "88ACC0B9521EACB4796E057C70DD9B95FED5BFB", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("05D178DECAFD2D02A3DA0D8BA1C4C1D95EE083C760DF782193A9F7B4A8BE6FC5" +
+                "C21FD60613BCA65C063A61226E050A680B3ABD4", 16), new BigInteger("013B7581E98F6A63FBBCB3E49BCDA60F816DB230B888506D105DC229600497C3" +
+                "B46588C784BE3AA9343BEF82F7C9C80AEB63C3B", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey, new BigInteger("049F54E7C10D2732B4638473053782C6919218BBEFCEC8B51640FC193E832291" +
+                "F05FA12371E9B448417B3290193F08EE9319195", 16), new BigInteger("0499E267DEC84E02F6F108B10E82172C414F15B1B7364BE8BFD66ADC0C5DE23F" +
+                "EE3DF0D811134C25AFE0E05A6672F98889F28F1", 16));
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("0B1527FFAA7DD7C7E46B628587A5BEC0539A2D04D3CF27C54841C2544E1BBDB4" +
+                "2FDBDAAF8671A4CA86DFD619B1E3732D7BB56F2", 16), new BigInteger("0442C68C044868DF4832C807F1EDDEBF7F5052A64B826FD03451440794063F52" +
+                "B022DF304F47403D4069234CA9EB4C964B37C02", 16));
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("0BB27755B991D6D31757BCBF68CB01225A38E1CFA20F775E861055DD108ED7EA" +
+                "455E4B96B2F6F7CD6C6EC2B3C70C3EDDEB9743B", 16), new BigInteger("0C5BE90980E7F444B5F7A12C9E9AC7A04CA81412822DD5AD1BE7C45D5032555E" +
+                "A070864245CF69266871FEB8CD1B7EDC30EF6D5", 16));
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("04EFEB7098772187907C87B33E0FBBA4584226C50C11E98CA7AAC6986F8D3BE0" +
+                "44E5B52D201A410B852536527724CA5F8CE6549", 16), new BigInteger("09574102FEB3EF87E6D66B94119F5A6062950FF4F902EA1E6BD9E2037F33FF99" +
+                "1E31F5956C23AFE48FCDC557FD6F088C7C9B2B3", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("07E0249C68536AE2AEC2EC30090340DA49E6DC9E9EEC8F85E5AABFB234B6DA7D" +
+                "2E9524028CF821F21C6019770474CC40B01FAF6", 16), new BigInteger("08125B5A03FB44AE81EA46D446130C2A415ECCA265910CA69D55F2453E16CD7B" +
+                "2DFA4E28C50FA8137F9C0C6CEE4CD37ABCCF6D8", 16));
+
+            x9ECParameters = NistNamedCurves.GetByName("B-571");
+            ecDomainParameters = new ECDomainParameters(x9ECParameters.Curve, x9ECParameters.G, x9ECParameters.N);
+
+            privKey = new ECPrivateKeyParameters(new BigInteger("028A04857F24C1C082DF0D909C0E72F453F2E2340CCB071F0E389BCA2575DA19" +
+                                                                "124198C57174929AD26E348CF63F78D28021EF5A9BF2D5CBEAF6B7CCB6C4DA82" +
+                                                                "4DD5C82CFB24E11", 16), ecDomainParameters);
+
+            DoTestHMacDetECDsaSample(new Sha1Digest(), privKey, new BigInteger("147D3EB0EDA9F2152DFD014363D6A9CE816D7A1467D326A625FC4AB0C786E1B7" +
+                                                                                "4DDF7CD4D0E99541391B266C704BB6B6E8DCCD27B460802E0867143727AA4155" +
+                                                                                "55454321EFE5CB6", 16),
+                                                                  new BigInteger("17319571CAF533D90D2E78A64060B9C53169AB7FC908947B3EDADC54C79CCF0A" +
+                                                                                  "7920B4C64A4EAB6282AFE9A459677CDA37FD6DD50BEF18709590FE18B923BDF7" +
+                                                                                  "4A66B189A850819", 16));
+
+            DoTestHMacDetECDsaSample(new Sha224Digest(), privKey, new BigInteger("10F4B63E79B2E54E4F4F6A2DBC786D8F4A143ECA7B2AD97810F6472AC6AE2085" +
+                                                                                "3222854553BE1D44A7974599DB7061AE8560DF57F2675BE5F9DD94ABAF3D47F1" +
+                                                                                "582B318E459748B", 16),
+                                                                  new BigInteger("3BBEA07C6B269C2B7FE9AE4DDB118338D0C2F0022920A7F9DCFCB7489594C03B" +
+                                                                                  "536A9900C4EA6A10410007222D3DAE1A96F291C4C9275D75D98EB290DC0EEF17" +
+                                                                                  "6037B2C7A7A39A3", 16));
+
+            DoTestHMacDetECDsaSample(new Sha256Digest(), privKey, new BigInteger("213EF9F3B0CFC4BF996B8AF3A7E1F6CACD2B87C8C63820000800AC787F17EC99" +
+                                                                                "C04BCEDF29A8413CFF83142BB88A50EF8D9A086AF4EB03E97C567500C21D8657" +
+                                                                                "14D832E03C6D054", 16),
+                                                                  new BigInteger("3D32322559B094E20D8935E250B6EC139AC4AAB77920812C119AF419FB62B332" +
+                                                                                  "C8D226C6C9362AE3C1E4AABE19359B8428EA74EC8FBE83C8618C2BCCB6B43FBA" +
+                                                                                  "A0F2CCB7D303945", 16));
+
+            DoTestHMacDetECDsaSample(new Sha384Digest(), privKey, new BigInteger("375D8F49C656A0BBD21D3F54CDA287D853C4BB1849983CD891EF6CD6BB56A62B" +
+                                                                                "687807C16685C2C9BCA2663C33696ACCE344C45F3910B1DF806204FF731ECB28" +
+                                                                                "9C100EF4D1805EC", 16),
+                                                                  new BigInteger("1CDEC6F46DFEEE44BCE71D41C60550DC67CF98D6C91363625AC2553E4368D2DF" +
+                                                                                "B734A8E8C72E118A76ACDB0E58697940A0F3DF49E72894BD799450FC9E550CC0" +
+                                                                                "4B9FF9B0380021C", 16));
+            DoTestHMacDetECDsaSample(new Sha512Digest(), privKey, new BigInteger("1C26F40D940A7EAA0EB1E62991028057D91FEDA0366B606F6C434C361F04E545" +
+                                                                                "A6A51A435E26416F6838FFA260C617E798E946B57215284182BE55F29A355E60" +
+                                                                                "24FE32A47289CF0", 16),
+                                                                  new BigInteger("3691DE4369D921FE94EDDA67CB71FBBEC9A436787478063EB1CC778B3DCDC1C4" +
+                                                                                "162662752D28DEEDF6F32A269C82D1DB80C87CE4D3B662E03AC347806E3F19D1" +
+                                                                                "8D6D4DE7358DF7E", 16));
+
+            DoTestHMacDetECDsaTest(new Sha1Digest(), privKey, new BigInteger("133F5414F2A9BC41466D339B79376038A64D045E5B0F792A98E5A7AA87E0AD01" +
+                "6419E5F8D176007D5C9C10B5FD9E2E0AB8331B195797C0358BA05ECBF24ACE59" +
+                "C5F368A6C0997CC", 16),
+                new BigInteger("3D16743AE9F00F0B1A500F738719C5582550FEB64689DA241665C4CE4F328BA0" +
+                    "E34A7EF527ED13BFA5889FD2D1D214C11EB17D6BC338E05A56F41CAFF1AF7B8D" +
+                    "574DB62EF0D0F21", 16));
+
+            DoTestHMacDetECDsaTest(new Sha224Digest(), privKey, new BigInteger("3048E76506C5C43D92B2E33F62B33E3111CEEB87F6C7DF7C7C01E3CDA28FA5E8" +
+                "BE04B5B23AA03C0C70FEF8F723CBCEBFF0B7A52A3F5C8B84B741B4F6157E69A5" +
+                "FB0524B48F31828", 16),
+                new BigInteger("2C99078CCFE5C82102B8D006E3703E020C46C87C75163A2CD839C885550BA5CB" +
+                    "501AC282D29A1C26D26773B60FBE05AAB62BFA0BA32127563D42F7669C97784C" +
+                    "8897C22CFB4B8FA", 16));
+
+            DoTestHMacDetECDsaTest(new Sha256Digest(), privKey, new BigInteger("184BC808506E11A65D628B457FDA60952803C604CC7181B59BD25AEE1411A66D" +
+                                                                        "12A777F3A0DC99E1190C58D0037807A95E5080FA1B2E5CCAA37B50D401CFFC34" +
+                                                                        "17C005AEE963469", 16),
+                                                                  new BigInteger("27280D45F81B19334DBDB07B7E63FE8F39AC7E9AE14DE1D2A6884D2101850289" +
+                                                                      "D70EE400F26ACA5E7D73F534A14568478E59D00594981ABE6A1BA18554C13EB5" +
+                                                                      "E03921E4DC98333", 16));
+
+            DoTestHMacDetECDsaTest(new Sha384Digest(), privKey, new BigInteger("319EE57912E7B0FAA1FBB145B0505849A89C6DB1EC06EA20A6A7EDE072A6268A" +
+                "F6FD9C809C7E422A5F33C6C3326EAD7402467DF3272A1B2726C1C20975950F0F" +
+                "50D8324578F13EC", 16),
+                new BigInteger("2CF3EA27EADD0612DD2F96F46E89AB894B01A10DF985C5FC099CFFE0EA083EB4" +
+                    "4BE682B08BFE405DAD5F37D0A2C59015BA41027E24B99F8F75A70B6B7385BF39" +
+                    "BBEA02513EB880C", 16));
+            DoTestHMacDetECDsaTest(new Sha512Digest(), privKey, new BigInteger("2AA1888EAB05F7B00B6A784C4F7081D2C833D50794D9FEAF6E22B8BE728A2A90" +
+                "BFCABDC803162020AA629718295A1489EE7ED0ECB8AAA197B9BDFC49D18DDD78" +
+                "FC85A48F9715544", 16),
+                new BigInteger("0AA5371FE5CA671D6ED9665849C37F394FED85D51FEF72DA2B5F28EDFB2C6479" +
+                    "CA63320C19596F5E1101988E2C619E302DD05112F47E8823040CE540CD3E90DC" +
+                    "F41DBC461744EE9", 16));
+
+        }
+
+        private void DoTestHMacDetECDsaSample(IDigest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+        {
+            DoTestHMacDetECDsa(new ECDsaSigner(new HMacDsaKCalculator(digest)), digest, SAMPLE, privKey, r, s);
+        }
+
+        private void DoTestHMacDetECDsaTest(IDigest digest, ECPrivateKeyParameters privKey, BigInteger r, BigInteger s)
+        {
+            DoTestHMacDetECDsa(new ECDsaSigner(new HMacDsaKCalculator(digest)), digest, TEST, privKey, r, s);
+        }
+
+        private void DoTestHMacDetECDsa(IDsa detSigner, IDigest digest, byte[] data, ICipherParameters privKey, BigInteger r, BigInteger s)
+        {
+            byte[] m = new byte[digest.GetDigestSize()];
+
+            digest.BlockUpdate(data, 0, data.Length);
+
+            digest.DoFinal(m, 0);
+
+            detSigner.Init(true, privKey);
+
+            BigInteger[] rs = detSigner.GenerateSignature(m);
+
+            if (!r.Equals(rs[0]))
+            {
+                Fail("r value wrong");
+            }
+            if (!s.Equals(rs[1]))
+            {
+                Fail("s value wrong");
+            }
+        }
+
+        public override string Name
+        {
+            get { return "DeterministicDSA"; }
+        }
+
+        public override void PerformTest()
+        {
+            TestHMacDeterministic();
+            TestECHMacDeterministic();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DeterministicDsaTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DigestRandomNumberTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DigestRandomNumberTest.cs
new file mode 100644
index 0000000..cee2e35
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DigestRandomNumberTest.cs
@@ -0,0 +1,163 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Prng;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class DigestRandomNumberTest
+		: SimpleTest
+	{
+		private static readonly byte[] ZERO_SEED = { 0, 0, 0, 0, 0, 0, 0, 0 };
+
+		private static readonly byte[] TEST_SEED = Hex.Decode("81dcfafc885914057876");
+
+		private static readonly byte[] expected0SHA1 = Hex.Decode("95bca677b3d4ff793213c00892d2356ec729ee02");
+		private static readonly byte[] noCycle0SHA1 = Hex.Decode("d57ccd0eb12c3938d59226412bc1268037b6b846");
+		private static readonly byte[] expected0SHA256 = Hex.Decode("587e2dfd597d086e47ddcd343eac983a5c913bef8c6a1a560a5c1bc3a74b0991");
+		private static readonly byte[] noCycle0SHA256 = Hex.Decode("e5776c4483486ba7be081f4e1b9dafbab25c8fae290fd5474c1ceda2c16f9509");
+		private static readonly byte[] expected100SHA1 = Hex.Decode("b9d924092546e0876cafd4937d7364ebf9efa4be");
+		private static readonly byte[] expected100SHA256 = Hex.Decode("fbc4aa54b948b99de104c44563a552899d718bb75d1941cc62a2444b0506abaf");
+		private static readonly byte[] expectedTestSHA1 = Hex.Decode("e9ecef9f5306daf1ac51a89a211a64cb24415649");
+		private static readonly byte[] expectedTestSHA256 = Hex.Decode("bdab3ca831b472a2fa09bd1bade541ef16c96640a91fcec553679a136061de98");
+
+		private static readonly byte[] sha1Xors = Hex.Decode("7edcc1216934f3891b03ffa65821611a3e2b1f79");
+		private static readonly byte[] sha256Xors = Hex.Decode("5ec48189cc0aa71e79c707bc3c33ffd47bbba368a83d6cfebf3cd3969d7f3eed");
+
+		public override string Name
+		{
+			get { return "DigestRandomNumber"; }
+		}
+
+		private void doExpectedTest(IDigest digest, int seed, byte[] expected)
+		{
+			doExpectedTest(digest, seed, expected, null);
+		}
+	    
+		private void doExpectedTest(IDigest digest, int seed, byte[] expected, byte[] noCycle)
+		{
+			DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+			byte[] output = new byte[digest.GetDigestSize()];
+
+			rGen.AddSeedMaterial(seed);
+
+			for (int i = 0; i != 1024; i++)
+			{
+				rGen.NextBytes(output);
+			}
+
+			if (noCycle != null)
+			{
+				if (Arrays.AreEqual(noCycle, output))
+				{
+					Fail("seed not being cycled!");
+				}
+			}
+
+			if (!Arrays.AreEqual(expected, output))
+			{
+				Fail("expected output doesn't match");
+			}
+		}
+
+		private void doExpectedTest(IDigest digest, byte[] seed, byte[] expected)
+		{
+			DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+			byte[] output = new byte[digest.GetDigestSize()];
+
+			rGen.AddSeedMaterial(seed);
+
+			for (int i = 0; i != 1024; i++)
+			{
+				rGen.NextBytes(output);
+			}
+
+			if (!Arrays.AreEqual(expected, output))
+			{
+				Fail("expected output doesn't match");
+			}
+		}
+
+		private void doCountTest(IDigest digest, byte[] seed, byte[] expectedXors)
+		{
+			DigestRandomGenerator rGen = new DigestRandomGenerator(digest);
+			byte[] output = new byte[digest.GetDigestSize()];
+			int[] averages = new int[digest.GetDigestSize()];
+			byte[] ands = new byte[digest.GetDigestSize()];
+			byte[] xors = new byte[digest.GetDigestSize()];
+			byte[] ors = new byte[digest.GetDigestSize()];
+
+			rGen.AddSeedMaterial(seed);
+
+			for (int i = 0; i != 1000000; i++)
+			{
+				rGen.NextBytes(output);
+				for (int j = 0; j != output.Length; j++)
+				{
+					averages[j] += output[j] & 0xff;
+					ands[j] &= output[j];
+					xors[j] ^= output[j];
+					ors[j] |= output[j];
+				}
+			}
+
+			for (int i = 0; i != output.Length; i++)
+			{
+				if ((averages[i] / 1000000) != 127)
+				{
+					Fail("average test failed for " + digest.AlgorithmName);
+				}
+				if (ands[i] != 0)
+				{
+					Fail("and test failed for " + digest.AlgorithmName);
+				}
+				if ((ors[i] & 0xff) != 0xff)
+				{
+					Fail("or test failed for " + digest.AlgorithmName);
+				}
+				if (xors[i] != expectedXors[i])
+				{
+					Fail("xor test failed for " + digest.AlgorithmName);
+				}
+			}
+		}
+
+		public override void PerformTest()
+		{
+			doExpectedTest(new Sha1Digest(), 0, expected0SHA1, noCycle0SHA1);
+			doExpectedTest(new Sha256Digest(), 0, expected0SHA256, noCycle0SHA256);
+
+			doExpectedTest(new Sha1Digest(), 100, expected100SHA1);
+			doExpectedTest(new Sha256Digest(), 100, expected100SHA256);
+
+			doExpectedTest(new Sha1Digest(), ZERO_SEED, expected0SHA1);
+			doExpectedTest(new Sha256Digest(), ZERO_SEED, expected0SHA256);
+
+			doExpectedTest(new Sha1Digest(), TEST_SEED, expectedTestSHA1);
+			doExpectedTest(new Sha256Digest(), TEST_SEED, expectedTestSHA256);
+
+			doCountTest(new Sha1Digest(), TEST_SEED, sha1Xors);
+			doCountTest(new Sha256Digest(), TEST_SEED, sha256Xors);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new DigestRandomNumberTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/DigestTest.cs
new file mode 100644
index 0000000..9309796
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/DigestTest.cs
@@ -0,0 +1,183 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	public abstract class DigestTest
+		: SimpleTest
+	{
+		private IDigest digest;
+		private string[] input;
+		private string[] results;
+
+		protected DigestTest(
+			IDigest digest,
+			string[] input,
+			string[] results)
+		{
+			this.digest = digest;
+			this.input = input;
+			this.results = results;
+		}
+
+		public override string Name
+		{
+			get { return digest.AlgorithmName; }
+		}
+
+		public override void PerformTest()
+		{
+			byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			for (int i = 0; i < input.Length - 1; i++)
+			{
+				byte[] msg = toByteArray(input[i]);
+
+				vectorTest(digest, i, resBuf, msg, Hex.Decode(results[i]));
+			}
+
+			byte[] lastV = toByteArray(input[input.Length - 1]);
+			byte[] lastDigest = Hex.Decode(results[input.Length - 1]);
+
+			vectorTest(digest, input.Length - 1, resBuf, lastV, Hex.Decode(results[input.Length - 1]));
+
+			//
+			// clone test
+			//
+			digest.BlockUpdate(lastV, 0, lastV.Length/2);
+
+			// clone the Digest
+			IDigest d = CloneDigest(digest);
+
+			digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(lastDigest, resBuf))
+			{
+				Fail("failing clone vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+			}
+
+			d.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+			d.DoFinal(resBuf, 0);
+
+			if (!AreEqual(lastDigest, resBuf))
+			{
+				Fail("failing second clone vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+			}
+
+			//
+			// memo test
+			//
+			IMemoable m = (IMemoable)digest;
+
+			digest.BlockUpdate(lastV, 0, lastV.Length/2);
+
+			// copy the Digest
+			IMemoable copy1 = m.Copy();
+			IMemoable copy2 = copy1.Copy();
+
+			digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(lastDigest, resBuf))
+			{
+				Fail("failing memo vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+			}
+
+			m.Reset(copy1);
+
+			digest.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(lastDigest, resBuf))
+			{
+				Fail("failing memo reset vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+			}
+
+			IDigest md = (IDigest)copy2;
+
+			md.BlockUpdate(lastV, lastV.Length/2, lastV.Length - lastV.Length/2);
+			md.DoFinal(resBuf, 0);
+
+			if (!AreEqual(lastDigest, resBuf))
+			{
+				Fail("failing memo copy vector test", results[results.Length - 1], Hex.ToHexString(resBuf));
+			}
+		}
+
+		private byte[] toByteArray(
+			string input)
+		{
+			byte[] bytes = new byte[input.Length];
+
+			for (int i = 0; i != bytes.Length; i++)
+			{
+				bytes[i] = (byte)input[i];
+			}
+
+			return bytes;
+		}
+
+		private void vectorTest(
+			IDigest digest,
+			int count,
+			byte[] resBuf,
+			byte[] input,
+			byte[] expected)
+		{
+			digest.BlockUpdate(input, 0, input.Length);
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(resBuf, expected))
+			{
+				Fail("Vector " + count + " failed got " + Hex.ToHexString(resBuf));
+			}
+		}
+
+		protected abstract IDigest CloneDigest(IDigest digest);
+
+		//
+		// optional tests
+		//
+		protected void millionATest(
+			string expected)
+		{
+			byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			for (int i = 0; i < 1000000; i++)
+			{
+				digest.Update((byte)'a');
+			}
+
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(resBuf, Hex.Decode(expected)))
+			{
+				Fail("Million a's failed");
+			}
+		}
+
+		protected void sixtyFourKTest(
+			string expected)
+		{
+			byte[] resBuf = new byte[digest.GetDigestSize()];
+
+			for (int i = 0; i < 65536; i++)
+			{
+				digest.Update((byte)(i & 0xff));
+			}
+
+			digest.DoFinal(resBuf, 0);
+
+			if (!AreEqual(resBuf, Hex.Decode(expected)))
+			{
+				Fail("64k test failed");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/EAXTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/EAXTest.cs
new file mode 100644
index 0000000..c6be118
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/EAXTest.cs
@@ -0,0 +1,352 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class EaxTest
+		: SimpleTest
+	{
+		private static readonly byte[] K1 = Hex.Decode("233952DEE4D5ED5F9B9C6D6FF80FF478");
+		private static readonly byte[] N1 = Hex.Decode("62EC67F9C3A4A407FCB2A8C49031A8B3");
+		private static readonly byte[] A1 = Hex.Decode("6BFB914FD07EAE6B");
+		private static readonly byte[] P1 = Hex.Decode("");
+		private static readonly byte[] C1 = Hex.Decode("E037830E8389F27B025A2D6527E79D01");
+		private static readonly byte[] T1 = Hex.Decode("E037830E8389F27B025A2D6527E79D01");
+
+		private static readonly byte[] K2 = Hex.Decode("91945D3F4DCBEE0BF45EF52255F095A4");
+		private static readonly byte[] N2 = Hex.Decode("BECAF043B0A23D843194BA972C66DEBD");
+		private static readonly byte[] A2 = Hex.Decode("FA3BFD4806EB53FA");
+		private static readonly byte[] P2 = Hex.Decode("F7FB");
+		private static readonly byte[] C2 = Hex.Decode("19DD5C4C9331049D0BDAB0277408F67967E5");
+		private static readonly byte[] T2 = Hex.Decode("5C4C9331049D0BDAB0277408F67967E5");
+
+		private static readonly byte[] K3 = Hex.Decode("01F74AD64077F2E704C0F60ADA3DD523");
+		private static readonly byte[] N3 = Hex.Decode("70C3DB4F0D26368400A10ED05D2BFF5E");
+		private static readonly byte[] A3 = Hex.Decode("234A3463C1264AC6");
+		private static readonly byte[] P3 = Hex.Decode("1A47CB4933");
+		private static readonly byte[] C3 = Hex.Decode("D851D5BAE03A59F238A23E39199DC9266626C40F80");
+		private static readonly byte[] T3 = Hex.Decode("3A59F238A23E39199DC9266626C40F80");
+
+		private static readonly byte[] K4 = Hex.Decode("D07CF6CBB7F313BDDE66B727AFD3C5E8");
+		private static readonly byte[] N4 = Hex.Decode("8408DFFF3C1A2B1292DC199E46B7D617");
+		private static readonly byte[] A4 = Hex.Decode("33CCE2EABFF5A79D");
+		private static readonly byte[] P4 = Hex.Decode("481C9E39B1");
+		private static readonly byte[] C4 = Hex.Decode("632A9D131AD4C168A4225D8E1FF755939974A7BEDE");
+		private static readonly byte[] T4 = Hex.Decode("D4C168A4225D8E1FF755939974A7BEDE");
+
+		private static readonly byte[] K5 = Hex.Decode("35B6D0580005BBC12B0587124557D2C2");
+		private static readonly byte[] N5 = Hex.Decode("FDB6B06676EEDC5C61D74276E1F8E816");
+		private static readonly byte[] A5 = Hex.Decode("AEB96EAEBE2970E9");
+		private static readonly byte[] P5 = Hex.Decode("40D0C07DA5E4");
+		private static readonly byte[] C5 = Hex.Decode("071DFE16C675CB0677E536F73AFE6A14B74EE49844DD");
+		private static readonly byte[] T5 = Hex.Decode("CB0677E536F73AFE6A14B74EE49844DD");
+
+		private static readonly byte[] K6 = Hex.Decode("BD8E6E11475E60B268784C38C62FEB22");
+		private static readonly byte[] N6 = Hex.Decode("6EAC5C93072D8E8513F750935E46DA1B");
+		private static readonly byte[] A6 = Hex.Decode("D4482D1CA78DCE0F");
+		private static readonly byte[] P6 = Hex.Decode("4DE3B35C3FC039245BD1FB7D");
+		private static readonly byte[] C6 = Hex.Decode("835BB4F15D743E350E728414ABB8644FD6CCB86947C5E10590210A4F");
+		private static readonly byte[] T6 = Hex.Decode("ABB8644FD6CCB86947C5E10590210A4F");
+
+		private static readonly byte[] K7 = Hex.Decode("7C77D6E813BED5AC98BAA417477A2E7D");
+		private static readonly byte[] N7 = Hex.Decode("1A8C98DCD73D38393B2BF1569DEEFC19");
+		private static readonly byte[] A7 = Hex.Decode("65D2017990D62528");
+		private static readonly byte[] P7 = Hex.Decode("8B0A79306C9CE7ED99DAE4F87F8DD61636");
+		private static readonly byte[] C7 = Hex.Decode("02083E3979DA014812F59F11D52630DA30137327D10649B0AA6E1C181DB617D7F2");
+		private static readonly byte[] T7 = Hex.Decode("137327D10649B0AA6E1C181DB617D7F2");
+
+		private static readonly byte[] K8 = Hex.Decode("5FFF20CAFAB119CA2FC73549E20F5B0D");
+		private static readonly byte[] N8 = Hex.Decode("DDE59B97D722156D4D9AFF2BC7559826");
+		private static readonly byte[] A8 = Hex.Decode("54B9F04E6A09189A");
+		private static readonly byte[] P8 = Hex.Decode("1BDA122BCE8A8DBAF1877D962B8592DD2D56");
+		private static readonly byte[] C8 = Hex.Decode("2EC47B2C4954A489AFC7BA4897EDCDAE8CC33B60450599BD02C96382902AEF7F832A");
+		private static readonly byte[] T8 = Hex.Decode("3B60450599BD02C96382902AEF7F832A");
+
+		private static readonly byte[] K9 = Hex.Decode("A4A4782BCFFD3EC5E7EF6D8C34A56123");
+		private static readonly byte[] N9 = Hex.Decode("B781FCF2F75FA5A8DE97A9CA48E522EC");
+		private static readonly byte[] A9 = Hex.Decode("899A175897561D7E");
+		private static readonly byte[] P9 = Hex.Decode("6CF36720872B8513F6EAB1A8A44438D5EF11");
+		private static readonly byte[] C9 = Hex.Decode("0DE18FD0FDD91E7AF19F1D8EE8733938B1E8E7F6D2231618102FDB7FE55FF1991700");
+		private static readonly byte[] T9 = Hex.Decode("E7F6D2231618102FDB7FE55FF1991700");
+
+		private static readonly byte[] K10 = Hex.Decode("8395FCF1E95BEBD697BD010BC766AAC3");
+		private static readonly byte[] N10 = Hex.Decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
+		private static readonly byte[] A10 = Hex.Decode("126735FCC320D25A");
+		private static readonly byte[] P10 = Hex.Decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
+		private static readonly byte[] C10 = Hex.Decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC253B4652B1AF3795B124AB6E");
+		private static readonly byte[] T10 = Hex.Decode("CFC46AFC253B4652B1AF3795B124AB6E");
+
+		private static readonly byte[] K11 = Hex.Decode("8395FCF1E95BEBD697BD010BC766AAC3");
+		private static readonly byte[] N11 = Hex.Decode("22E7ADD93CFC6393C57EC0B3C17D6B44");
+		private static readonly byte[] A11 = Hex.Decode("126735FCC320D25A");
+		private static readonly byte[] P11 = Hex.Decode("CA40D7446E545FFAED3BD12A740A659FFBBB3CEAB7");
+		private static readonly byte[] C11 = Hex.Decode("CB8920F87A6C75CFF39627B56E3ED197C552D295A7CFC46AFC");
+		private static readonly byte[] T11 = Hex.Decode("CFC46AFC");
+
+		private const int NONCE_LEN = 8;
+		private const int MAC_LEN = 8;
+		private const int AUTHEN_LEN = 20;
+
+		public override string Name
+		{
+			get { return "EAX"; }
+		}
+
+		public override void PerformTest()
+		{
+			checkVectors(1, K1, 128, N1, A1, P1, T1, C1);
+			checkVectors(2, K2, 128, N2, A2, P2, T2, C2);
+			checkVectors(3, K3, 128, N3, A3, P3, T3, C3);
+			checkVectors(4, K4, 128, N4, A4, P4, T4, C4);
+			checkVectors(5, K5, 128, N5, A5, P5, T5, C5);
+			checkVectors(6, K6, 128, N6, A6, P6, T6, C6);
+			checkVectors(7, K7, 128, N7, A7, P7, T7, C7);
+			checkVectors(8, K8, 128, N8, A8, P8, T8, C8);
+			checkVectors(9, K9, 128, N9, A9, P9, T9, C9);
+			checkVectors(10, K10, 128, N10, A10, P10, T10, C10);
+			checkVectors(11, K11, 32, N11, A11, P11, T11, C11);
+
+			EaxBlockCipher eax = new EaxBlockCipher(new AesEngine());
+			ivParamTest(1, eax, K1, N1);
+
+			//
+			// exception tests
+			//
+
+			try
+			{
+				eax.Init(false, new AeadParameters(new KeyParameter(K1), 32, N2, A2));
+
+				byte[] enc = new byte[C2.Length]; 
+				int len = eax.ProcessBytes(C2, 0, C2.Length, enc, 0);
+
+				len += eax.DoFinal(enc, len);
+
+				Fail("invalid cipher text not picked up");
+			}
+			catch (InvalidCipherTextException)
+			{
+				// expected
+			}
+
+			try
+			{
+				eax.Init(false, new KeyParameter(K1));
+
+				Fail("illegal argument not picked up");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			randomTests();
+		}
+
+		private void checkVectors(
+			int				count,
+			byte[]			k,
+			int				macSize,
+			byte[]			n,
+			byte[]			a,
+			byte[]			p,
+			byte[]			t,
+			byte[]			c)
+        {
+            byte[] fa = new byte[a.Length / 2];
+            byte[] la = new byte[a.Length - (a.Length / 2)];
+            Array.Copy(a, 0, fa, 0, fa.Length);
+            Array.Copy(a, fa.Length, la, 0, la.Length);
+
+            checkVectors(count, "all initial associated data", k, macSize, n, a, null, p, t, c);
+            checkVectors(count, "subsequent associated data", k, macSize, n, null, a, p, t, c);
+            checkVectors(count, "split associated data", k, macSize, n, fa, la, p, t, c);
+        }
+
+        private void checkVectors(
+            int count,
+            string additionalDataType,
+            byte[] k,
+            int macSize,
+            byte[] n,
+            byte[] a,
+            byte[] sa,
+            byte[] p,
+            byte[] t,
+            byte[] c)
+        {
+			EaxBlockCipher encEax = new EaxBlockCipher(new AesFastEngine());
+			EaxBlockCipher decEax = new EaxBlockCipher(new AesFastEngine());
+
+			AeadParameters parameters = new AeadParameters(new KeyParameter(k), macSize, n, a);
+			encEax.Init(true, parameters);
+			decEax.Init(false, parameters);
+
+            runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+            runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+
+            // key reuse test
+            parameters = new AeadParameters(null, macSize, n, a);
+            encEax.Init(true, parameters);
+            decEax.Init(false, parameters);
+
+            runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+            runCheckVectors(count, encEax, decEax, additionalDataType, sa, p, t, c);
+        }
+
+		private void runCheckVectors(
+			int				count,
+			EaxBlockCipher	encEax,
+			EaxBlockCipher	decEax,
+            string          additionalDataType,
+            byte[]          sa,
+            byte[]          p,
+			byte[]			t,
+			byte[]			c)
+		{
+			byte[] enc = new byte[c.Length];
+
+            if (sa != null)
+            {
+                encEax.ProcessAadBytes(sa, 0, sa.Length);
+            }
+
+			int len = encEax.ProcessBytes(p, 0, p.Length, enc, 0);
+
+			len += encEax.DoFinal(enc, len);
+
+			if (!AreEqual(c, enc))
+			{
+                Fail("encrypted stream fails to match in test " + count + " with " + additionalDataType);
+            }
+
+			byte[] tmp = new byte[enc.Length];
+
+            if (sa != null)
+            {
+                decEax.ProcessAadBytes(sa, 0, sa.Length);
+            }
+
+            len = decEax.ProcessBytes(enc, 0, enc.Length, tmp, 0);
+
+			len += decEax.DoFinal(tmp, len);
+
+			byte[] dec = new byte[len];
+
+			Array.Copy(tmp, 0, dec, 0, len);
+
+			if (!AreEqual(p, dec))
+			{
+                Fail("decrypted stream fails to match in test " + count + " with " + additionalDataType);
+            }
+
+			if (!AreEqual(t, decEax.GetMac()))
+			{
+                Fail("MAC fails to match in test " + count + " with " + additionalDataType);
+            }
+		}
+
+        private void ivParamTest(
+			int					count,
+			IAeadBlockCipher	eax,
+			byte[]				k,
+			byte[]				n)
+		{
+			byte[] p = Encoding.ASCII.GetBytes("hello world!!");
+
+			eax.Init(true, new ParametersWithIV(new KeyParameter(k), n));
+
+			byte[] enc = new byte[p.Length + 8];
+
+			int len = eax.ProcessBytes(p, 0, p.Length, enc, 0);
+
+			len += eax.DoFinal(enc, len);
+
+			eax.Init(false, new ParametersWithIV(new KeyParameter(k), n));
+
+			byte[] tmp = new byte[enc.Length];
+
+			len = eax.ProcessBytes(enc, 0, enc.Length, tmp, 0);
+
+			len += eax.DoFinal(tmp, len);
+
+			byte[] dec = new byte[len];
+
+			Array.Copy(tmp, 0, dec, 0, len);
+
+			if (!AreEqual(p, dec))
+			{
+				Fail("decrypted stream fails to match in test " + count);
+			}
+		}
+
+		private void randomTests()
+		{
+			SecureRandom srng = new SecureRandom();
+			for (int i = 0; i < 10; ++i)
+			{
+				randomTest(srng);
+			}
+		}
+
+		private void randomTest(
+			SecureRandom srng)
+		{
+			int DAT_LEN = srng.Next(1024);
+			byte[] nonce = new byte[NONCE_LEN];
+			byte[] authen = new byte[AUTHEN_LEN];
+			byte[] datIn = new byte[DAT_LEN];
+			byte[] key = new byte[16];
+			srng.NextBytes(nonce);
+			srng.NextBytes(authen);
+			srng.NextBytes(datIn);
+			srng.NextBytes(key);
+
+			AesFastEngine engine = new AesFastEngine();
+			KeyParameter sessKey = new KeyParameter(key);
+			EaxBlockCipher eaxCipher = new EaxBlockCipher(engine);
+
+			AeadParameters parameters = new AeadParameters(sessKey, MAC_LEN * 8, nonce, authen);
+			eaxCipher.Init(true, parameters);
+
+			byte[] intrDat = new byte[eaxCipher.GetOutputSize(datIn.Length)];
+			int outOff = eaxCipher.ProcessBytes(datIn, 0, DAT_LEN, intrDat, 0);
+			outOff += eaxCipher.DoFinal(intrDat, outOff);
+
+			eaxCipher.Init(false, parameters);
+			byte[] datOut = new byte[eaxCipher.GetOutputSize(outOff)];
+			int resultLen = eaxCipher.ProcessBytes(intrDat, 0, outOff, datOut, 0);
+			eaxCipher.DoFinal(datOut, resultLen);
+
+			if (!AreEqual(datIn, datOut))
+			{
+				Fail("EAX roundtrip failed to match");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new EaxTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ECDHKEKGeneratorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ECDHKEKGeneratorTest.cs
new file mode 100644
index 0000000..250b2ca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ECDHKEKGeneratorTest.cs
@@ -0,0 +1,80 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Agreement.Kdf;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks>ECDHKEK Generator tests.</remarks>
+	[TestFixture]
+	public class ECDHKekGeneratorTest
+		: SimpleTest
+	{
+		private byte[] seed1 = Hex.Decode("db4a8daba1f98791d54e940175dd1a5f3a0826a1066aa9b668d4dc1e1e0790158dcad1533c03b44214d1b61fefa8b579");
+		private DerObjectIdentifier alg1 = NistObjectIdentifiers.IdAes256Wrap;
+		private byte[] result1 = Hex.Decode("8ecc6d85caf25eaba823a7d620d4ab0d33e4c645f2");
+
+		private byte[] seed2 = Hex.Decode("75d7487b5d3d2bfb3c69ce0365fe64e3bfab5d0d63731628a9f47eb8fddfa28c65decaf228a0b38f0c51c6a3356d7c56");
+		private DerObjectIdentifier alg2 = NistObjectIdentifiers.IdAes128Wrap;
+		private byte[] result2 = Hex.Decode("042be1faca3a4a8fc859241bfb87ba35");
+
+		private byte[] seed3 = Hex.Decode("fdeb6d809f997e8ac174d638734dc36d37aaf7e876e39967cd82b1cada3de772449788461ee7f856bad9305627f8e48b");
+		private DerObjectIdentifier alg3 = PkcsObjectIdentifiers.IdAlgCms3DesWrap;
+		private byte[] result3 = Hex.Decode("bcd701fc92109b1b9d6f3b6497ad5ca9627fa8a597010305");
+
+		public ECDHKekGeneratorTest()
+		{
+		}
+
+		public override void PerformTest()
+		{
+			CheckMask(1, new ECDHKekGenerator(new Sha1Digest()), new DHKdfParameters(alg1, 256, seed1), result1);
+			CheckMask(2, new ECDHKekGenerator(new Sha1Digest()), new DHKdfParameters(alg2, 128, seed2), result2);
+			CheckMask(3, new ECDHKekGenerator(new Sha1Digest()), new DHKdfParameters(alg3, 192, seed3), result3);
+		}
+
+		private void CheckMask(
+			int						count,
+			IDerivationFunction		kdf,
+			IDerivationParameters	parameters,
+			byte[]					result)
+		{
+			byte[] data = new byte[result.Length];
+
+			kdf.Init(parameters);
+
+			kdf.GenerateBytes(data, 0, data.Length);
+
+			if (!AreEqual(result, data))
+			{
+				Fail("ECDHKekGenerator failed generator test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "ECDHKekGenerator"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ECDHKekGeneratorTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ECGOST3410Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ECGOST3410Test.cs
new file mode 100644
index 0000000..37cb23e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ECGOST3410Test.cs
@@ -0,0 +1,345 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     *  ECGOST3410 tests are taken from GOST R 34.10-2001.
+     */
+    [TestFixture]
+    public class ECGost3410Test
+        : SimpleTest
+    {
+        private static readonly byte[] hashmessage = Hex.Decode("3042453136414534424341374533364339313734453431443642453241453435");
+
+        /**
+        * ECGOST3410 over the field Fp<br/>
+        */
+        BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395");
+        BigInteger s = new BigInteger("574973400270084654178925310019147038455227042649098563933718999175515839552");
+
+        byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").ToByteArray();
+
+        private readonly SecureRandom k;
+
+        public ECGost3410Test()
+        {
+            k = FixedSecureRandom.From(kData);
+        }
+
+        private void ecGOST3410_TEST()
+        {
+            BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+            BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("7"), // a
+                new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
+                mod_q, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("2"), // x
+                    new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
+                mod_q);
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECGOST3410",
+                new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d
+                parameters);
+
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ECGost3410Signer ecgost3410 = new ECGost3410Signer();
+
+            ecgost3410.Init(true, param);
+
+            byte[] mVal = new BigInteger("20798893674476452017134061561508270130637142515379653289952617252661468872421").ToByteArray();
+            byte[] message = new byte[mVal.Length];
+
+            for (int i = 0; i != mVal.Length; i++)
+            {
+                message[i] = mVal[mVal.Length - 1 - i];
+            }
+
+            BigInteger[] sig = ecgost3410.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong.", r, sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong.", s, sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECGOST3410",
+                curve.CreatePoint(
+                    new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403"), // x
+                    new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994")), // y
+                parameters);
+
+            ecgost3410.Init(false, pubKey);
+            if (!ecgost3410.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("verification fails");
+            }
+        }
+
+        /**
+         * Test Sign and Verify with test parameters
+         * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+         * gostR3410-2001-TestParamSet  P.46
+         */
+        private void ecGOST3410_TestParam()
+        {
+            SecureRandom    random = new SecureRandom();
+
+            BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+            BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("7"), // a
+                new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414"), // b
+                mod_q, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("2"), // x
+                    new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")), // y
+                mod_q);
+
+            ECKeyPairGenerator          pGen = new ECKeyPairGenerator();
+            ECKeyGenerationParameters   genParam = new ECKeyGenerationParameters(
+                parameters,
+                random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair  pair = pGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+            ECGost3410Signer ecgost3410 = new ECGost3410Signer();
+
+            ecgost3410.Init(true, param);
+
+            //get hash message using the digest GOST3411.
+            byte[] message = Encoding.ASCII.GetBytes("Message for sign");
+            Gost3411Digest gost3411 = new Gost3411Digest();
+            gost3411.BlockUpdate(message, 0, message.Length);
+            byte[] hashmessage = new byte[gost3411.GetDigestSize()];
+            gost3411.DoFinal(hashmessage, 0);
+
+            BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage);
+
+            ecgost3410.Init(false, pair.Public);
+
+            if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * Test Sign and Verify with A parameters
+         * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+         * gostR3410-2001-CryptoPro-A-ParamSet  P.47
+         */
+        public void ecGOST3410_AParam()
+        {
+            SecureRandom    random = new SecureRandom();
+
+            BigInteger mod_p = new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639319"); //p
+            BigInteger mod_q = new BigInteger("115792089237316195423570985008687907853073762908499243225378155805079068850323");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("115792089237316195423570985008687907853269984665640564039457584007913129639316"), // a
+                new BigInteger("166"), // b
+                mod_q, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("1"), // x
+                    new BigInteger("64033881142927202683649881450433473985931760268884941288852745803908878638612")), // y
+                mod_q);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410");
+            ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+                parameters,
+                random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair  pair = pGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+            ECGost3410Signer ecgost3410 = new ECGost3410Signer();
+
+            ecgost3410.Init(true, param);
+
+            BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage);
+
+            ecgost3410.Init(false, pair.Public);
+
+            if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * Test Sign and Verify with B parameters
+         * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+         * gostR3410-2001-CryptoPro-B-ParamSet  P.47-48
+         */
+        private void ecGOST3410_BParam()
+        {
+            SecureRandom random = new SecureRandom();
+
+            BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823193"); //p
+            BigInteger mod_q = new BigInteger("57896044618658097711785492504343953927102133160255826820068844496087732066703");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564823190"), // a
+                new BigInteger("28091019353058090096996979000309560759124368558014865957655842872397301267595"), // b
+                mod_q, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("1"), // x
+                    new BigInteger("28792665814854611296992347458380284135028636778229113005756334730996303888124")), // y
+                mod_q);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410");
+            ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+                parameters,
+                random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+            ECGost3410Signer ecgost3410 = new ECGost3410Signer();
+
+            ecgost3410.Init(true, param);
+
+            BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage);
+
+            ecgost3410.Init(false, pair.Public);
+
+            if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * Test Sign and Verify with C parameters
+         * see: http://www.ietf.org/internet-drafts/draft-popov-cryptopro-cpalgs-01.txt
+         * gostR3410-2001-CryptoPro-C-ParamSet  P.48
+         */
+        private void ecGOST3410_CParam()
+        {
+            SecureRandom random = new SecureRandom();
+
+            BigInteger mod_p = new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502619"); //p
+            BigInteger mod_q = new BigInteger("70390085352083305199547718019018437840920882647164081035322601458352298396601");
+
+            FpCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("70390085352083305199547718019018437841079516630045180471284346843705633502616"), // a
+                new BigInteger("32858"), // b
+                mod_q, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("0"), // x
+                    new BigInteger("29818893917731240733471273240314769927240550812383695689146495261604565990247")), // y
+                mod_q);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator("ECGOST3410");
+            ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+                parameters,
+                random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+            ECGost3410Signer ecgost3410 = new ECGost3410Signer();
+
+            ecgost3410.Init(true, param);
+
+            BigInteger[] sig = ecgost3410.GenerateSignature(hashmessage);
+
+            ecgost3410.Init(false, pair.Public);
+
+            if (!ecgost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        public override string Name
+        {
+            get { return "ECGOST3410"; }
+        }
+
+        public override void PerformTest()
+        {
+            ecGOST3410_TEST();
+            ecGOST3410_TestParam();
+            ecGOST3410_AParam();
+            ecGOST3410_BParam();
+            ecGOST3410_CParam();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ECGost3410Test test = new ECGost3410Test();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ECIESTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ECIESTest.cs
new file mode 100644
index 0000000..e8cfd6d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ECIESTest.cs
@@ -0,0 +1,252 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks>Test for ECIES - Elliptic Curve Integrated Encryption Scheme</remarks>
+    [TestFixture]
+    public class EcIesTest
+        : SimpleTest
+    {
+        public EcIesTest()
+        {
+        }
+
+        public override string Name
+        {
+            get { return "ECIES"; }
+        }
+
+        private void StaticTest()
+        {
+            BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+                    n);
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDH",
+                new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+                parameters);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDH",
+                curve.DecodePoint(Hex.Decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+                parameters);
+
+            AsymmetricCipherKeyPair p1 = new AsymmetricCipherKeyPair(pubKey, priKey);
+            AsymmetricCipherKeyPair p2 = new AsymmetricCipherKeyPair(pubKey, priKey);
+
+            //
+            // stream test
+            //
+            IesEngine i1 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()));
+            IesEngine i2 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()));
+            byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+            byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+            IesParameters p = new IesParameters(d, e, 64);
+
+            i1.Init(true, p1.Private, p2.Public, p);
+            i2.Init(false, p2.Private, p1.Public, p);
+
+            byte[] message = Hex.Decode("1234567890abcdef");
+
+            byte[] out1 = i1.ProcessBlock(message, 0, message.Length);
+
+            if (!AreEqual(out1, Hex.Decode("468d89877e8238802403ec4cb6b329faeccfa6f3a730f2cdb3c0a8e8")))
+            {
+                Fail("stream cipher test failed on enc");
+            }
+
+            byte[] out2 = i2.ProcessBlock(out1, 0, out1.Length);
+
+            if (!AreEqual(out2, message))
+            {
+                Fail("stream cipher test failed");
+            }
+
+            //
+            // twofish with CBC
+            //
+            BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
+                new CbcBlockCipher(new TwofishEngine()));
+            BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
+                new CbcBlockCipher(new TwofishEngine()));
+            i1 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()),
+                c1);
+            i2 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()),
+                c2);
+            d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+            e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+            p = new IesWithCipherParameters(d, e, 64, 128);
+
+            i1.Init(true, p1.Private, p2.Public, p);
+            i2.Init(false, p2.Private, p1.Public, p);
+
+            message = Hex.Decode("1234567890abcdef");
+
+            out1 = i1.ProcessBlock(message, 0, message.Length);
+
+            if (!AreEqual(out1, Hex.Decode("b8a06ea5c2b9df28b58a0a90a734cde8c9c02903e5c220021fe4417410d1e53a32a71696")))
+            {
+                Fail("twofish cipher test failed on enc");
+            }
+
+            out2 = i2.ProcessBlock(out1, 0, out1.Length);
+
+            if (!AreEqual(out2, message))
+            {
+                Fail("twofish cipher test failed");
+            }
+        }
+
+        private void DoTest(
+            AsymmetricCipherKeyPair	p1,
+            AsymmetricCipherKeyPair	p2)
+        {
+            //
+            // stream test
+            //
+            IesEngine i1 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()));
+            IesEngine i2 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()));
+            byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+            byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+            IesParameters  p = new IesParameters(d, e, 64);
+
+            i1.Init(true, p1.Private, p2.Public, p);
+            i2.Init(false, p2.Private, p1.Public, p);
+
+            byte[] message = Hex.Decode("1234567890abcdef");
+
+            byte[] out1 = i1.ProcessBlock(message, 0, message.Length);
+
+            byte[] out2 = i2.ProcessBlock(out1, 0, out1.Length);
+
+            if (!AreEqual(out2, message))
+            {
+                Fail("stream cipher test failed");
+            }
+
+            //
+            // twofish with CBC
+            //
+            BufferedBlockCipher c1 = new PaddedBufferedBlockCipher(
+                new CbcBlockCipher(new TwofishEngine()));
+            BufferedBlockCipher c2 = new PaddedBufferedBlockCipher(
+                new CbcBlockCipher(new TwofishEngine()));
+            i1 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()),
+                c1);
+            i2 = new IesEngine(
+                new ECDHBasicAgreement(),
+                new Kdf2BytesGenerator(new Sha1Digest()),
+                new HMac(new Sha1Digest()),
+                c2);
+            d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+            e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+            p = new IesWithCipherParameters(d, e, 64, 128);
+
+            i1.Init(true, p1.Private, p2.Public, p);
+            i2.Init(false, p2.Private, p1.Public, p);
+
+            message = Hex.Decode("1234567890abcdef");
+
+            out1 = i1.ProcessBlock(message, 0, message.Length);
+
+            out2 = i2.ProcessBlock(out1, 0, out1.Length);
+
+            if (!AreEqual(out2, message))
+            {
+                Fail("twofish cipher test failed");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            StaticTest();
+
+            BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                    curve,
+                    curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+                    n);
+
+            ECKeyPairGenerator eGen = new ECKeyPairGenerator();
+            KeyGenerationParameters gParam = new ECKeyGenerationParameters(parameters, new SecureRandom());
+
+            eGen.Init(gParam);
+
+            AsymmetricCipherKeyPair p1 = eGen.GenerateKeyPair();
+            AsymmetricCipherKeyPair p2 = eGen.GenerateKeyPair();
+
+            DoTest(p1, p2);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new EcIesTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ECNRTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ECNRTest.cs
new file mode 100644
index 0000000..5eae9f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ECNRTest.cs
@@ -0,0 +1,118 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * ECNR tests.
+     */
+    [TestFixture]
+    public class EcNrTest
+        : SimpleTest
+    {
+        /**
+            * a basic regression test with 239 bit prime
+            */
+        BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693");
+        BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143");
+
+        byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
+
+        private readonly SecureRandom k;
+
+        public EcNrTest()
+        {
+            k = FixedSecureRandom.From(kData);
+        }
+
+        private void ecNR239bitPrime()
+        {
+            BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                n);
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                parameters);
+
+            ECNRSigner ecnr = new ECNRSigner();
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ecnr.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecnr.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong.", r, sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong.", s, sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                parameters);
+
+            ecnr.Init(false, pubKey);
+            if (!ecnr.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        public override string Name
+        {
+            get
+            {
+                return "ECNR";
+            }
+        }
+
+        public override void PerformTest()
+        {
+            ecNR239bitPrime();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            EcNrTest test = new EcNrTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ECTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ECTest.cs
new file mode 100644
index 0000000..5697f41
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ECTest.cs
@@ -0,0 +1,932 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Agreement;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * ECDSA tests are taken from X9.62.
+     */
+    [TestFixture]
+    public class ECTest
+        : SimpleTest
+    {
+        /**
+        * X9.62 - 1998,<br/>
+        * J.3.1, Page 152, ECDSA over the field Fp<br/>
+        * an example with 192 bit prime
+        */
+        [Test]
+        public void TestECDsa192bitPrime()
+        {
+            BigInteger r = new BigInteger("3342403536405981729393488334694600415596881826869351677613");
+            BigInteger s = new BigInteger("5735822328888155254683894997897571951568553642892029982342");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("6140507067065001063065065565667405560006161556565665656654"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            BigInteger n = new BigInteger("6277101735386680763835789423176059013767194773182842284081");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")), // G
+                n);
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+                parameters);
+
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("0262b12d60690cdcf330babab6e69763b471f994dd702d16a5")), // Q
+                parameters);
+
+            ecdsa.Init(false, pubKey);
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("verification fails");
+            }
+        }
+
+        [Test]
+        public void TestDecode()
+        {
+            FpCurve curve = new FpCurve(
+                new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
+
+            ECPoint p = curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")).Normalize();
+
+            if (!p.AffineXCoord.ToBigInteger().Equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16)))
+            {
+                Fail("x uncompressed incorrectly");
+            }
+
+            if (!p.AffineYCoord.ToBigInteger().Equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16)))
+            {
+                Fail("y uncompressed incorrectly");
+            }
+
+            byte[] encoding = p.GetEncoded();
+
+            if (!AreEqual(encoding, Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012")))
+            {
+                Fail("point compressed incorrectly");
+            }
+        }
+
+        /**
+         * X9.62 - 1998,<br/>
+         * J.3.2, Page 155, ECDSA over the field Fp<br/>
+         * an example with 239 bit prime
+         */
+        [Test]
+        public void TestECDsa239bitPrime()
+        {
+            BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
+            BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                n);
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                parameters);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                parameters);
+
+            ecdsa.Init(false, pubKey);
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+
+        /**
+         * X9.62 - 1998,<br/>
+         * J.2.1, Page 100, ECDSA over the field F2m<br/>
+         * an example with 191 bit binary field
+         */
+        [Test]
+        public void TestECDsa191bitBinary()
+        {
+            BigInteger r = new BigInteger("87194383164871543355722284926904419997237591535066528048");
+            BigInteger s = new BigInteger("308992691965804947361541664549085895292153777025772063598");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("1542725565216523985789236956265265265235675811949404040041"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            F2mCurve curve = new F2mCurve(
+                191, // m
+                9, //k
+                new BigInteger("2866537B676752636A68F56554E12640276B649EF7526267", 16), // a
+                new BigInteger("2E45EF571F00786F67B0081B9495A3D95462F5DE0AA185EC", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("0436B3DAF8A23206F9C4F299D7B21A9C369137F2C84AE1AA0D765BE73433B3F95E332932E70EA245CA2418EA0EF98018FB")), // G
+                new BigInteger("1569275433846670190958947355803350458831205595451630533029"), // n
+                BigInteger.Two); // h
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("1275552191113212300012030439187146164646146646466749494799"), // d
+                parameters);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("045DE37E756BD55D72E3768CB396FFEB962614DEA4CE28A2E755C0E0E02F5FB132CAF416EF85B229BBB8E1352003125BA1")), // Q
+                parameters);
+
+            ecdsa.Init(false, pubKey);
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * X9.62 - 1998,<br/>
+         * J.2.1, Page 100, ECDSA over the field F2m<br/>
+         * an example with 191 bit binary field
+         */
+        [Test]
+        public void TestECDsa239bitBinary()
+        {
+            BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+            BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            F2mCurve curve = new F2mCurve(
+                239, // m
+                36, //k
+                new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); // h
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+                parameters);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                parameters);
+
+            ecdsa.Init(false, pubKey);
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        // L 4.1  X9.62 2005
+        [Test]
+        public void TestECDsaP224Sha224()
+        {
+            X9ECParameters p = NistNamedCurves.GetByName("P-224");
+            ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
+                parameters);
+            SecureRandom k = FixedSecureRandom.From(BigIntegers.AsUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
+        
+            byte[] M = Hex.Decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79");
+
+            ECDsaSigner dsa = new ECDsaSigner();
+
+            dsa.Init(true, new ParametersWithRandom(priKey, k));
+
+            BigInteger[] sig = dsa.GenerateSignature(M);
+
+            BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
+            BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
+        
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                parameters.Curve.DecodePoint(Hex.Decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
+                parameters);
+
+            dsa.Init(false, pubKey);
+            if (!dsa.VerifySignature(M, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        [Test]
+        public void TestECDsaSecP224k1Sha256()
+        {
+            X9ECParameters p = SecNamedCurves.GetByName("secp224k1");
+            ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("BE6F6E91FE96840A6518B56F3FE21689903A64FA729057AB872A9F51", 16), // d
+                parameters);
+            SecureRandom k = FixedSecureRandom.From(Hex.Decode("00c39beac93db21c3266084429eb9b846b787c094f23a4de66447efbb3"));
+       
+            byte[] M = Hex.Decode("E5D5A7ADF73C5476FAEE93A2C76CE94DC0557DB04CDC189504779117920B896D");
+
+            ECDsaSigner dsa = new ECDsaSigner();
+
+            dsa.Init(true, new ParametersWithRandom(priKey, k));
+
+            BigInteger[] sig = dsa.GenerateSignature(M);
+
+            BigInteger r = new BigInteger("8163E5941BED41DA441B33E653C632A55A110893133351E20CE7CB75", 16);
+            BigInteger s = new BigInteger("D12C3FC289DDD5F6890DCE26B65792C8C50E68BF551D617D47DF15A8", 16);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                parameters.Curve.DecodePoint(Hex.Decode("04C5C9B38D3603FCCD6994CBB9594E152B658721E483669BB42728520F484B537647EC816E58A8284D3B89DFEDB173AFDC214ECA95A836FA7C")), // Q
+                parameters);
+
+            dsa.Init(false, pubKey);
+            if (!dsa.VerifySignature(M, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        // L4.2  X9.62 2005
+        [Test]
+        public void TestECDsaP256Sha256()
+        {
+            X9ECParameters p = NistNamedCurves.GetByName("P-256");
+            ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("20186677036482506117540275567393538695075300175221296989956723148347484984008"), // d
+                parameters);
+            SecureRandom k = FixedSecureRandom.From(BigIntegers.AsUnsignedByteArray(new BigInteger("72546832179840998877302529996971396893172522460793442785601695562409154906335")));
+
+            byte[] M = Hex.Decode("1BD4ED430B0F384B4E8D458EFF1A8A553286D7AC21CB2F6806172EF5F94A06AD");
+
+            ECDsaSigner dsa = new ECDsaSigner();
+
+            dsa.Init(true, new ParametersWithRandom(priKey, k));
+
+            BigInteger[] sig = dsa.GenerateSignature(M);
+
+            BigInteger r = new BigInteger("97354732615802252173078420023658453040116611318111190383344590814578738210384");
+            BigInteger s = new BigInteger("98506158880355671805367324764306888225238061309262649376965428126566081727535");
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                parameters.Curve.DecodePoint(Hex.Decode("03596375E6CE57E0F20294FC46BDFCFD19A39F8161B58695B3EC5B3D16427C274D")), // Q
+                parameters);
+
+            dsa.Init(false, pubKey);
+            if (!dsa.VerifySignature(M, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        [Test]
+        public void TestECDsaP224OneByteOver()
+        {
+            X9ECParameters p = NistNamedCurves.GetByName("P-224");
+            ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("6081831502424510080126737029209236539191290354021104541805484120491"), // d
+                parameters);
+            SecureRandom    k = FixedSecureRandom.From(BigIntegers.AsUnsignedByteArray(new BigInteger("15456715103636396133226117016818339719732885723579037388121116732601")));
+
+            byte[] M = Hex.Decode("8797A3C693CC292441039A4E6BAB7387F3B4F2A63D00ED384B378C79FF");
+
+            ECDsaSigner dsa = new ECDsaSigner();
+
+            dsa.Init(true, new ParametersWithRandom(priKey, k));
+
+            BigInteger[] sig = dsa.GenerateSignature(M);
+
+            BigInteger r = new BigInteger("26477406756127720855365980332052585411804331993436302005017227573742");
+            BigInteger s = new BigInteger("17694958233103667059888193972742186995283044672015112738919822429978");
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                parameters.Curve.DecodePoint(Hex.Decode("03FD44EC11F9D43D9D23B1E1D1C9ED6519B40ECF0C79F48CF476CC43F1")), // Q
+                parameters);
+
+            dsa.Init(false, pubKey);
+            if (!dsa.VerifySignature(M, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        // L4.3  X9.62 2005
+        [Test]
+        public void TestECDsaP521Sha512()
+        {
+            X9ECParameters p = NistNamedCurves.GetByName("P-521");
+            ECDomainParameters parameters = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("617573726813476282316253885608633222275541026607493641741273231656161177732180358888434629562647985511298272498852936680947729040673640492310550142822667389"), // d
+                parameters);
+            SecureRandom k = FixedSecureRandom.From(BigIntegers.AsUnsignedByteArray(new BigInteger("6806532878215503520845109818432174847616958675335397773700324097584974639728725689481598054743894544060040710846048585856076812050552869216017728862957612913")));
+
+            byte[] M = Hex.Decode("6893B64BD3A9615C39C3E62DDD269C2BAAF1D85915526083183CE14C2E883B48B193607C1ED871852C9DF9C3147B574DC1526C55DE1FE263A676346A20028A66");
+
+            ECDsaSigner dsa = new ECDsaSigner();
+
+            dsa.Init(true, new ParametersWithRandom(priKey, k));
+
+            BigInteger[] sig = dsa.GenerateSignature(M);
+
+            BigInteger r = new BigInteger("1368926195812127407956140744722257403535864168182534321188553460365652865686040549247096155740756318290773648848859639978618869784291633651685766829574104630");
+            BigInteger s = new BigInteger("1624754720348883715608122151214003032398685415003935734485445999065609979304811509538477657407457976246218976767156629169821116579317401249024208611945405790");
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                parameters.Curve.DecodePoint(Hex.Decode("020145E221AB9F71C5FE740D8D2B94939A09E2816E2167A7D058125A06A80C014F553E8D6764B048FB6F2B687CEC72F39738F223D4CE6AFCBFF2E34774AA5D3C342CB3")), // Q
+                parameters);
+
+            dsa.Init(false, pubKey);
+            if (!dsa.VerifySignature(M, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * General test for long digest.
+         */
+        [Test]
+        public void TestECDsa239bitBinaryAndLargeDigest()
+        {
+            BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+            BigInteger s = new BigInteger("144940322424411242416373536877786566515839911620497068645600824084578597");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(
+                new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            F2mCurve curve = new F2mCurve(
+                239, // m
+                36, //k
+                new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(
+                    Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); // h
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+                parameters);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+            ParametersWithRandom param = new ParametersWithRandom(priKey, k);
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+
+            // Verify the signature
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(
+                    Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                parameters);
+
+            ecdsa.Init(false, pubKey);
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * key generation test
+         */
+        [Test]
+        public void TestECDsaKeyGenTest()
+        {
+            SecureRandom random = new SecureRandom();
+
+            BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                n);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+            ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(
+                parameters,
+                random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+            ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+            ECDsaSigner ecdsa = new ECDsaSigner();
+
+            ecdsa.Init(true, param);
+
+            byte[] message = new BigInteger("968236873715988614170569073515315707566766479517").ToByteArray();
+            BigInteger[] sig = ecdsa.GenerateSignature(message);
+
+            ecdsa.Init(false, pair.Public);
+
+            if (!ecdsa.VerifySignature(message, sig[0], sig[1]))
+            {
+                Fail("signature fails");
+            }
+        }
+
+        /**
+         * Basic Key Agreement Test
+         */
+        [Test]
+        public void TestECBasicAgreementTest()
+        {
+            SecureRandom random = new SecureRandom();
+
+            BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                n);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+            ECKeyGenerationParameters genParam = new ECKeyGenerationParameters(parameters, random);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair p1 = pGen.GenerateKeyPair();
+            AsymmetricCipherKeyPair p2 = pGen.GenerateKeyPair();
+
+            //
+            // two way
+            //
+            IBasicAgreement e1 = new ECDHBasicAgreement();
+            IBasicAgreement e2 = new ECDHBasicAgreement();
+
+            e1.Init(p1.Private);
+            e2.Init(p2.Private);
+
+            BigInteger   k1 = e1.CalculateAgreement(p2.Public);
+            BigInteger   k2 = e2.CalculateAgreement(p1.Public);
+
+            if (!k1.Equals(k2))
+            {
+                Fail("calculated agreement test failed");
+            }
+
+            //
+            // two way
+            //
+            e1 = new ECDHCBasicAgreement();
+            e2 = new ECDHCBasicAgreement();
+
+            e1.Init(p1.Private);
+            e2.Init(p2.Private);
+
+            k1 = e1.CalculateAgreement(p2.Public);
+            k2 = e2.CalculateAgreement(p1.Public);
+
+            if (!k1.Equals(k2))
+            {
+                Fail("calculated agreement test failed");
+            }
+        }
+
+        [Test]
+        public void TestECMqvTestVector1()
+        {
+            // Test Vector from GEC-2
+
+            X9ECParameters x9 = SecNamedCurves.GetByName("secp160r1");
+            ECDomainParameters p = new ECDomainParameters(
+                x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+
+            AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("0251B4496FECC406ED0E75A24A3C03206251419DC0")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("AA374FFC3CE144E6B073307972CB6D57B2A4E982", 16), p));
+
+            AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("03D99CE4D8BF52FA20BD21A962C6556B0F71F4CA1F")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("149EC7EA3A220A887619B3F9E5B4CA51C7D1779C", 16), p));
+
+            AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("0349B41E0E9C0369C2328739D90F63D56707C6E5BC")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("45FB58A92A17AD4B15101C66E74F277E2B460866", 16), p));
+
+            AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("02706E5D6E1F640C6E9C804E75DBC14521B1E5F3B5")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("18C13FCED9EADF884F7C595C8CB565DEFD0CB41E", 16), p));
+
+            BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+            if (x == null
+                || !x.Equals(new BigInteger("5A6955CEFDB4E43255FB7FCF718611E4DF8E05AC", 16)))
+            {
+                Fail("MQV Test Vector #1 agreement failed");
+            }
+        }
+
+        [Test]
+        public void TestECMqvTestVector2()
+        {
+            // Test Vector from GEC-2
+
+            X9ECParameters x9 = SecNamedCurves.GetByName("sect163k1");
+            ECDomainParameters p = new ECDomainParameters(
+                x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+
+            AsymmetricCipherKeyPair U1 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("03037D529FA37E42195F10111127FFB2BB38644806BC")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("03A41434AA99C2EF40C8495B2ED9739CB2155A1E0D", 16), p));
+
+            AsymmetricCipherKeyPair U2 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("02015198E74BC2F1E5C9A62B80248DF0D62B9ADF8429")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("032FC4C61A8211E6A7C4B8B0C03CF35F7CF20DBD52", 16), p));
+
+            AsymmetricCipherKeyPair V1 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("03072783FAAB9549002B4F13140B88132D1C75B3886C")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("57E8A78E842BF4ACD5C315AA0569DB1703541D96", 16), p));
+
+            AsymmetricCipherKeyPair V2 = new AsymmetricCipherKeyPair(
+                new ECPublicKeyParameters(
+                    p.Curve.DecodePoint(Hex.Decode("03067E3AEA3510D69E8EDD19CB2A703DDC6CF5E56E32")), p),
+                new ECPrivateKeyParameters(
+                    new BigInteger("02BD198B83A667A8D908EA1E6F90FD5C6D695DE94F", 16), p));
+
+            BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+            if (x == null
+                || !x.Equals(new BigInteger("038359FFD30C0D5FC1E6154F483B73D43E5CF2B503", 16)))
+            {
+                Fail("MQV Test Vector #2 agreement failed");
+            }
+        }
+
+        [Test]
+        public void TestECMqvRandom()
+        {
+            SecureRandom random = new SecureRandom();
+
+            BigInteger n = new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307");
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16), // b
+                n, BigInteger.One);
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                n);
+
+            ECKeyPairGenerator pGen = new ECKeyPairGenerator();
+
+            pGen.Init(new ECKeyGenerationParameters(parameters, random));
+
+
+            // Pre-established key pairs
+            AsymmetricCipherKeyPair U1 = pGen.GenerateKeyPair();
+            AsymmetricCipherKeyPair V1 = pGen.GenerateKeyPair();
+
+            // Ephemeral key pairs
+            AsymmetricCipherKeyPair U2 = pGen.GenerateKeyPair();
+            AsymmetricCipherKeyPair V2 = pGen.GenerateKeyPair();
+
+            BigInteger x = calculateAgreement(U1, U2, V1, V2);
+
+            if (x == null)
+            {
+                Fail("MQV Test Vector (random) agreement failed");
+            }
+        }
+
+        private static BigInteger calculateAgreement(
+            AsymmetricCipherKeyPair U1,
+            AsymmetricCipherKeyPair U2,
+            AsymmetricCipherKeyPair V1,
+            AsymmetricCipherKeyPair V2)
+        {
+            ECMqvBasicAgreement u = new ECMqvBasicAgreement();
+            u.Init(new MqvPrivateParameters(
+                (ECPrivateKeyParameters)U1.Private,
+                (ECPrivateKeyParameters)U2.Private,
+                (ECPublicKeyParameters)U2.Public));
+            BigInteger ux = u.CalculateAgreement(new MqvPublicParameters(
+                (ECPublicKeyParameters)V1.Public,
+                (ECPublicKeyParameters)V2.Public));
+
+            ECMqvBasicAgreement v = new ECMqvBasicAgreement();
+            v.Init(new MqvPrivateParameters(
+                (ECPrivateKeyParameters)V1.Private,
+                (ECPrivateKeyParameters)V2.Private,
+                (ECPublicKeyParameters)V2.Public));
+            BigInteger vx = v.CalculateAgreement(new MqvPublicParameters(
+                (ECPublicKeyParameters)U1.Public,
+                (ECPublicKeyParameters)U2.Public));
+
+            if (ux.Equals(vx))
+                return ux;
+
+            return null;
+        }
+
+        public override string Name
+        {
+            get { return "EC"; }
+        }
+
+        public override void PerformTest()
+        {
+            TestDecode();
+            TestECDsa192bitPrime();
+            TestECDsa239bitPrime();
+            TestECDsa191bitBinary();
+            TestECDsa239bitBinary();
+            TestECDsaKeyGenTest();
+            TestECBasicAgreementTest();
+
+            TestECDsaP224Sha224();
+            TestECDsaP224OneByteOver();
+            TestECDsaP256Sha256();
+            TestECDsaP521Sha512();
+            TestECDsaSecP224k1Sha256();
+            TestECDsa239bitBinaryAndLargeDigest();
+
+            TestECMqvTestVector1();
+            TestECMqvTestVector2();
+            TestECMqvRandom();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ECTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ElGamalTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ElGamalTest.cs
new file mode 100644
index 0000000..1caa703
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ElGamalTest.cs
@@ -0,0 +1,278 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class ElGamalTest
+		: SimpleTest
+	{
+		private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+		private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+		private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+		private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+		private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+		private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+		private static readonly BigInteger yPgpBogusPSamp = new BigInteger("de4688497cc05b45fe8559bc9918c45afcad69b74123a7236eba409fd9de8ea34c7869839ee9df35e3d97576145d089841aa65b5b4e061fae52c37e430354269a02496b8ed8456f2d0d7c9b0db985fbcb21ae9f78507ed6e3a29db595b201b1a4f931c7d791eede65ccf918e8a61cf146859151c78c41ad48853694623467d78", 16);
+		private static readonly BigInteger xPgpBogusPSamp = new BigInteger("cbaf780f2cfe4f987bbc5fcb0738bbd7912060ccfdf37cbfeea65c0fd857e74a8df6cc359375f28cf5725d081813c614410a78cbe4b06d677beea9ff0fa10b1dbc47a6ed8c5b8466d6a95d6574029dbdf72596392e1b6b230faf9916dc8455821c10527a375a4d1c8a54947d1fe714d321aca25ad486b4b456506999fd2fd11a", 16);
+		private static readonly BigInteger gPgpBogusPSamp = new BigInteger("153ffe9522076d1cbd6e75f0816a0fc2ebd8b0e0091406587387a1763022088a03b411eed07ff50efb82b21f1608c352d10f63ba7e7e981a2f3387cec8af2915953d00493857663ae8919f517fe90f1d2abe7af4305a344b10d1a25d75f65902cd7fd775853d3ac43d7c5253ad666e1e63ee98cdcb10af81273d4ff053ff07d51", 16);
+		private static readonly BigInteger pPgpBogusPSamp = new BigInteger("15061b26cdab4e865098a01c86f13b03220104c5443e950658b36b85245aa0c616a0c0d8d99c454bea087c172315e45b3bc9b925443948a2b6ba47608a6035b9a79a4ef34a78d7274a12ede8364f02d5030db864988643d7e92753df603bd69fbd2682ab0af64d1a866d1131a2cb13333cedb0a9e6eefddd9fff8154d34c2daab", 16);
+		private const int lPgpBogusPSamp = 0;
+
+		public override string Name
+		{
+			get { return "ElGamal"; }
+		}
+
+		private void doTestEnc(
+			int         size,
+			int         privateValueSize,
+			BigInteger  g,
+			BigInteger  p)
+		{
+			ElGamalParameters dhParams = new ElGamalParameters(p, g, privateValueSize);
+			ElGamalKeyGenerationParameters ekgParams = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams);
+			ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+			kpGen.Init(ekgParams);
+
+			//
+			// generate pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters) pair.Public;
+			ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters) pair.Private;
+
+			checkKeySize(privateValueSize, pv);
+
+			ElGamalEngine e = new ElGamalEngine();
+
+			e.Init(true, pu);
+
+			if (e.GetOutputBlockSize() != size / 4)
+			{
+				Fail(size + " GetOutputBlockSize() on encryption failed.");
+			}
+
+			byte[] message = Hex.Decode("5468697320697320612074657374");
+
+			byte[] pText = message;
+			byte[] cText = e.ProcessBlock(pText, 0, pText.Length);
+
+			e.Init(false, pv);
+
+			if (e.GetOutputBlockSize() != (size / 8) - 1)
+			{
+				Fail(size + " GetOutputBlockSize() on decryption failed.");
+			}
+
+			pText = e.ProcessBlock(cText, 0, cText.Length);
+
+			if (!Arrays.AreEqual(message, pText))
+			{
+				Fail(size + " bit test failed");
+			}
+
+
+
+			e.Init(true, pu);
+			byte[] bytes = new byte[e.GetInputBlockSize() + 2];
+
+			try
+			{
+				e.ProcessBlock(bytes, 0, bytes.Length);
+
+				Fail("out of range block not detected");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			try
+			{
+				bytes[0] = (byte)0xff;
+
+				e.ProcessBlock(bytes, 0, bytes.Length - 1);
+
+				Fail("out of range block not detected");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			try
+			{
+				bytes[0] = (byte)0x7f;
+
+				e.ProcessBlock(bytes, 0, bytes.Length - 1);
+			}
+			catch (DataLengthException)
+			{
+				Fail("in range block failed");
+			}
+		}
+
+		private void checkKeySize(
+			int							privateValueSize,
+			ElGamalPrivateKeyParameters	priv)
+		{
+			if (privateValueSize != 0)
+			{
+				if (priv.X.BitLength != privateValueSize)
+				{
+					Fail("limited key check failed for key size " + privateValueSize);
+				}
+			}
+		}
+
+		/**
+		 * this test is can take quiet a while
+		 *
+		 * @param size size of key in bits.
+		 */
+		private void doTestGeneration(
+			int size)
+		{
+			ElGamalParametersGenerator pGen = new ElGamalParametersGenerator();
+
+			pGen.Init(size, 10, new SecureRandom());
+
+			ElGamalParameters elParams = pGen.GenerateParameters();
+
+			if (elParams.L != 0)
+			{
+				Fail("ElGamalParametersGenerator failed to set L to 0 in generated ElGamalParameters");
+			}
+
+			ElGamalKeyGenerationParameters ekgParams = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
+
+			ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+			kpGen.Init(ekgParams);
+
+			//
+			// generate first pair
+			//
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+			ElGamalPublicKeyParameters pu = (ElGamalPublicKeyParameters)pair.Public;
+			ElGamalPrivateKeyParameters pv = (ElGamalPrivateKeyParameters)pair.Private;
+
+			ElGamalEngine e = new ElGamalEngine();
+
+			e.Init(true, new ParametersWithRandom(pu, new SecureRandom()));
+
+			byte[] message = Hex.Decode("5468697320697320612074657374");
+
+			byte[] pText = message;
+			byte[] cText = e.ProcessBlock(pText, 0, pText.Length);
+
+			e.Init(false, pv);
+
+			pText = e.ProcessBlock(cText, 0, cText.Length);
+
+			if (!Arrays.AreEqual(message, pText))
+			{
+				Fail("generation test failed");
+			}
+		}
+
+		[Test]
+		public void TestInvalidP()
+		{
+			ElGamalParameters dhParams = new ElGamalParameters(pPgpBogusPSamp, gPgpBogusPSamp, lPgpBogusPSamp);
+			ElGamalPublicKeyParameters pu = new ElGamalPublicKeyParameters(yPgpBogusPSamp, dhParams);
+			ElGamalPrivateKeyParameters pv = new ElGamalPrivateKeyParameters(xPgpBogusPSamp, dhParams);
+
+			ElGamalEngine e = new ElGamalEngine();
+
+			e.Init(true, pu);
+
+			byte[] message = Hex.Decode("5468697320697320612074657374");
+
+			byte[] pText = message;
+			byte[] cText = e.ProcessBlock(pText, 0, pText.Length);
+
+			e.Init(false, pv);
+
+			pText = e.ProcessBlock(cText, 0, cText.Length);
+
+			if (Arrays.AreEqual(message, pText))
+			{
+				Fail("invalid test failed");
+			}
+		}
+
+		[Test]
+		public void TestEnc512()
+		{
+			doTestEnc(512, 0, g512, p512);
+			doTestEnc(512, 64, g512, p512);
+		}
+
+		[Test]
+		public void TestEnc768()
+		{
+			doTestEnc(768, 0, g768, p768);
+			doTestEnc(768, 128, g768, p768);
+		}
+
+		[Test]
+		public void TestEnc1024()
+		{
+			doTestEnc(1024, 0, g1024, p1024);
+		}
+
+		[Test]
+		public void TestGeneration258()
+		{
+			doTestGeneration(258);
+		}
+
+		[Test]
+		public void TestInitCheck()
+		{
+			try
+			{
+				new ElGamalEngine().ProcessBlock(new byte[]{ 1 }, 0, 1);
+				Fail("failed initialisation check");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+		}
+
+		public override void PerformTest()
+		{
+			TestInvalidP();
+			TestEnc512();
+			TestEnc768();
+			TestEnc1024();
+			TestGeneration258();
+			TestInitCheck();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ElGamalTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/EqualsHashCodeTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/EqualsHashCodeTest.cs
new file mode 100644
index 0000000..05cc9ad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/EqualsHashCodeTest.cs
@@ -0,0 +1,262 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	internal class DHTestKeyParameters
+		: DHKeyParameters
+	{
+		public DHTestKeyParameters(
+			bool			isPrivate,
+			DHParameters	parameters)
+			: base(isPrivate, parameters)
+		{
+		}
+	}
+
+	internal class ElGamalTestKeyParameters
+		: ElGamalKeyParameters
+	{
+		public ElGamalTestKeyParameters(
+			bool				isPrivate,
+			ElGamalParameters	parameters)
+			: base(isPrivate, parameters)
+		{
+		}
+	}
+
+	[TestFixture]
+	public class EqualsHashCodeTest
+		: SimpleTest
+	{
+		private static object Other = new object();
+
+		public override string Name
+		{
+			get { return "EqualsHashCode"; }
+		}
+
+		private void doTest(
+			object	a,
+			object	equalsA,
+			object	notEqualsA)
+		{
+			if (a.Equals(null))
+			{
+				Fail("a equaled null");
+			}
+
+			if (!a.Equals(equalsA) || !equalsA.Equals(a))
+			{
+				Fail("equality failed");
+			}
+
+			if (a.Equals(Other))
+			{
+				Fail("other inequality failed");
+			}
+
+			if (a.Equals(notEqualsA) || notEqualsA.Equals(a))
+			{
+				Fail("inequality failed");
+			}
+
+			if (a.GetHashCode() != equalsA.GetHashCode())
+			{
+				Fail("hashCode equality failed");
+			}
+		}
+
+		[Test]
+		public void TestDH()
+		{
+			BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+			BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+			DHParameters dhParams = new DHParameters(p512, g512);
+			DHKeyGenerationParameters parameters = new DHKeyGenerationParameters(new SecureRandom(), dhParams);         DHKeyPairGenerator          kpGen = new DHKeyPairGenerator();
+
+			kpGen.Init(parameters);
+
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+			DHPublicKeyParameters pu1 = (DHPublicKeyParameters)pair.Public;
+			DHPrivateKeyParameters pv1 = (DHPrivateKeyParameters)pair.Private;
+
+			DHPublicKeyParameters pu2 = new DHPublicKeyParameters(pu1.Y, pu1.Parameters);
+			DHPrivateKeyParameters pv2 = new DHPrivateKeyParameters(pv1.X, pv1.Parameters);
+			DHPublicKeyParameters pu3 = new DHPublicKeyParameters(pv1.X, pu1.Parameters);
+			DHPrivateKeyParameters pv3 = new DHPrivateKeyParameters(pu1.Y, pu1.Parameters);
+
+			doTest(pu1, pu2, pu3);
+			doTest(pv1, pv2, pv3);
+
+			DHParameters pr1 = pu1.Parameters;
+			DHParameters pr2 = new DHParameters(
+				pr1.P, pr1.G, pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters);
+			DHParameters pr3 = new DHParameters(
+				pr1.P.Add(BigInteger.Two), pr1.G, pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters);
+
+			doTest(pr1, pr2, pr3);
+
+			pr3 = new DHParameters(
+				pr1.P, pr1.G.Add(BigInteger.One), pr1.Q, pr1.M, pr1.L, pr1.J, pr1.ValidationParameters);
+
+			doTest(pr1, pr2, pr3);
+
+			pu2 = new DHPublicKeyParameters(pu1.Y, pr2);
+			pv2 = new DHPrivateKeyParameters(pv1.X, pr2);
+
+			doTest(pu1, pu2, pu3);
+			doTest(pv1, pv2, pv3);
+
+			DHValidationParameters vp1 = new DHValidationParameters(new byte[20], 1024);
+			DHValidationParameters vp2 = new DHValidationParameters(new byte[20], 1024);
+			DHValidationParameters vp3 = new DHValidationParameters(new byte[24], 1024);
+
+			doTest(vp1, vp1, vp3);
+			doTest(vp1, vp2, vp3);
+
+			byte[] bytes = new byte[20];
+			bytes[0] = 1;
+
+			vp3 = new DHValidationParameters(bytes, 1024);
+
+			doTest(vp1, vp2, vp3);
+
+			vp3 = new DHValidationParameters(new byte[20], 2048);
+
+			doTest(vp1, vp2, vp3);
+
+			DHTestKeyParameters k1 = new DHTestKeyParameters(false, null);
+			DHTestKeyParameters k2 = new DHTestKeyParameters(false, null);
+			DHTestKeyParameters k3 = new DHTestKeyParameters(false, pu1.Parameters);
+
+			doTest(k1, k2, k3);
+		}
+
+		[Test]
+		public void TestElGamal()
+		{
+			BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+			BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+			ElGamalParameters dhParams = new ElGamalParameters(p512, g512);
+			ElGamalKeyGenerationParameters parameters = new ElGamalKeyGenerationParameters(new SecureRandom(), dhParams);         ElGamalKeyPairGenerator kpGen = new ElGamalKeyPairGenerator();
+
+			kpGen.Init(parameters);
+
+			AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+			ElGamalPublicKeyParameters pu1 = (ElGamalPublicKeyParameters)pair.Public;
+			ElGamalPrivateKeyParameters pv1 = (ElGamalPrivateKeyParameters)pair.Private;
+
+			ElGamalPublicKeyParameters pu2 = new ElGamalPublicKeyParameters(pu1.Y, pu1.Parameters);
+			ElGamalPrivateKeyParameters pv2 = new ElGamalPrivateKeyParameters(pv1.X, pv1.Parameters);
+			ElGamalPublicKeyParameters pu3 = new ElGamalPublicKeyParameters(pv1.X, pu1.Parameters);
+			ElGamalPrivateKeyParameters pv3 = new ElGamalPrivateKeyParameters(pu1.Y, pu1.Parameters);
+
+			doTest(pu1, pu2, pu3);
+			doTest(pv1, pv2, pv3);
+
+			ElGamalParameters pr1 = pu1.Parameters;
+			ElGamalParameters pr2 = new ElGamalParameters(pr1.P, pr1.G);
+			ElGamalParameters pr3 = new ElGamalParameters(pr1.G, pr1.P);
+
+			doTest(pr1, pr2, pr3);
+
+			pu2 = new ElGamalPublicKeyParameters(pu1.Y, pr2);
+			pv2 = new ElGamalPrivateKeyParameters(pv1.X, pr2);
+
+			doTest(pu1, pu2, pu3);
+			doTest(pv1, pv2, pv3);
+
+			ElGamalTestKeyParameters k1 = new ElGamalTestKeyParameters(false, null);
+			ElGamalTestKeyParameters k2 = new ElGamalTestKeyParameters(false, null);
+			ElGamalTestKeyParameters k3 = new ElGamalTestKeyParameters(false, pu1.Parameters);
+
+			doTest(k1, k2, k3);
+		}
+
+		[Test]
+		public void TestDsa()
+		{
+			BigInteger a = BigInteger.ValueOf(1), b = BigInteger.ValueOf(2), c = BigInteger.ValueOf(3);
+
+			DsaParameters dsaP1 = new DsaParameters(a, b, c);
+			DsaParameters dsaP2 = new DsaParameters(a, b, c);
+			DsaParameters dsaP3 = new DsaParameters(b, c, a);
+
+			doTest(dsaP1, dsaP2, dsaP3);
+
+			DsaValidationParameters vp1 = new DsaValidationParameters(new byte[20], 1024);
+			DsaValidationParameters vp2 = new DsaValidationParameters(new byte[20], 1024);
+			DsaValidationParameters vp3 = new DsaValidationParameters(new byte[24], 1024);
+
+			doTest(vp1, vp1, vp3);
+			doTest(vp1, vp2, vp3);
+
+			byte[] bytes = new byte[20];
+			bytes[0] = 1;
+
+			vp3 = new DsaValidationParameters(bytes, 1024);
+
+			doTest(vp1, vp2, vp3);
+
+			vp3 = new DsaValidationParameters(new byte[20], 2048);
+
+			doTest(vp1, vp2, vp3);
+		}
+
+		[Test]
+		public void TestGost3410()
+		{
+			BigInteger a = BigInteger.ValueOf(1), b = BigInteger.ValueOf(2), c = BigInteger.ValueOf(3);
+
+			Gost3410Parameters g1 = new Gost3410Parameters(a, b, c);
+			Gost3410Parameters g2 = new Gost3410Parameters(a, b, c);
+			Gost3410Parameters g3 = new Gost3410Parameters(a, c, c);
+
+			doTest(g1, g2, g3);
+
+			Gost3410ValidationParameters v1 = new Gost3410ValidationParameters(100, 1);
+			Gost3410ValidationParameters v2 = new Gost3410ValidationParameters(100, 1);
+			Gost3410ValidationParameters v3 = new Gost3410ValidationParameters(101, 1);
+
+			doTest(v1, v2, v3);
+
+			v3 = new Gost3410ValidationParameters(100, 2);
+
+			doTest(v1, v2, v3);
+
+			v1 = new Gost3410ValidationParameters(100L, 1L);
+			v2 = new Gost3410ValidationParameters(100L, 1L);
+			v3 = new Gost3410ValidationParameters(101L, 1L);
+
+			doTest(v1, v2, v3);
+
+			v3 = new Gost3410ValidationParameters(100L, 2L);
+
+			doTest(v1, v2, v3);
+		}
+
+		public override void PerformTest()
+		{
+			TestDH();
+			TestElGamal();
+			TestGost3410();
+			TestDsa();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new EqualsHashCodeTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GCMTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GCMTest.cs
new file mode 100644
index 0000000..943ffda
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GCMTest.cs
@@ -0,0 +1,711 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Modes.Gcm;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary>
+    /// Test vectors from "The Galois/Counter Mode of Operation (GCM)", McGrew/Viega, Appendix B
+    /// </summary>
+    [TestFixture]
+    public class GcmTest
+        : SimpleTest
+    {
+        private static readonly string[][] TestVectors = new string[][]
+        {
+            new string[]
+            {
+                "Test Case 1",
+                "00000000000000000000000000000000",
+                "",
+                "",
+                "000000000000000000000000",
+                "",
+                "58e2fccefa7e3061367f1d57a4e7455a",
+            },
+            new string[]
+            {
+                "Test Case 2",
+                "00000000000000000000000000000000",
+                "00000000000000000000000000000000",
+                "",
+                "000000000000000000000000",
+                "0388dace60b6a392f328c2b971b2fe78",
+                "ab6e47d42cec13bdf53a67b21257bddf",
+            },
+            new string[]
+            {
+                "Test Case 3",
+                "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b391aafd255",
+                "",
+                "cafebabefacedbaddecaf888",
+                "42831ec2217774244b7221b784d0d49c"
+                + "e3aa212f2c02a4e035c17e2329aca12e"
+                + "21d514b25466931c7d8f6a5aac84aa05"
+                + "1ba30b396a0aac973d58e091473f5985",
+                "4d5c2af327cd64a62cf35abd2ba6fab4",
+            },
+            new string[]
+            {
+                "Test Case 4",
+                "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbaddecaf888",
+                "42831ec2217774244b7221b784d0d49c"
+                + "e3aa212f2c02a4e035c17e2329aca12e"
+                + "21d514b25466931c7d8f6a5aac84aa05"
+                + "1ba30b396a0aac973d58e091",
+                "5bc94fbc3221a5db94fae95ae7121a47",
+            },
+            new string[]
+            {
+                "Test Case 5",
+                "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbad",
+                "61353b4c2806934a777ff51fa22a4755"
+                + "699b2a714fcdc6f83766e5f97b6c7423"
+                + "73806900e49f24b22b097544d4896b42"
+                + "4989b5e1ebac0f07c23f4598",
+                "3612d2e79e3b0785561be14aaca2fccb",
+            },
+            new string[]
+            {
+                "Test Case 6",
+                "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "9313225df88406e555909c5aff5269aa"
+                + "6a7a9538534f7da1e4c303d2a318a728"
+                + "c3c0c95156809539fcf0e2429a6b5254"
+                + "16aedbf5a0de6a57a637b39b",
+                "8ce24998625615b603a033aca13fb894"
+                + "be9112a5c3a211a8ba262a3cca7e2ca7"
+                + "01e4a9a4fba43c90ccdcb281d48c7c6f"
+                + "d62875d2aca417034c34aee5",
+                "619cc5aefffe0bfa462af43c1699d050",
+            },
+            new string[]
+            {
+                "Test Case 7",
+                "00000000000000000000000000000000"
+                + "0000000000000000",
+                "",
+                "",
+                "000000000000000000000000",
+                "",
+                "cd33b28ac773f74ba00ed1f312572435",
+            },
+            new string[]
+            {
+                "Test Case 8",
+                "00000000000000000000000000000000"
+                + "0000000000000000",
+                "00000000000000000000000000000000",
+                "",
+                "000000000000000000000000",
+                "98e7247c07f0fe411c267e4384b0f600",
+                "2ff58d80033927ab8ef4d4587514f0fb",
+            },
+            new string[]
+            {
+                "Test Case 9",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b391aafd255",
+                "",
+                "cafebabefacedbaddecaf888",
+                "3980ca0b3c00e841eb06fac4872a2757"
+                + "859e1ceaa6efd984628593b40ca1e19c"
+                + "7d773d00c144c525ac619d18c84a3f47"
+                + "18e2448b2fe324d9ccda2710acade256",
+                "9924a7c8587336bfb118024db8674a14",
+            },
+            new string[]
+            {
+                "Test Case 10",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbaddecaf888",
+                "3980ca0b3c00e841eb06fac4872a2757"
+                + "859e1ceaa6efd984628593b40ca1e19c"
+                + "7d773d00c144c525ac619d18c84a3f47"
+                + "18e2448b2fe324d9ccda2710",
+                "2519498e80f1478f37ba55bd6d27618c",
+            },
+            new string[]
+            {
+                "Test Case 11",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbad",
+                "0f10f599ae14a154ed24b36e25324db8"
+                + "c566632ef2bbb34f8347280fc4507057"
+                + "fddc29df9a471f75c66541d4d4dad1c9"
+                + "e93a19a58e8b473fa0f062f7",
+                "65dcc57fcf623a24094fcca40d3533f8",
+            },
+            new string[]
+            {
+                "Test Case 12",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "9313225df88406e555909c5aff5269aa"
+                + "6a7a9538534f7da1e4c303d2a318a728"
+                + "c3c0c95156809539fcf0e2429a6b5254"
+                + "16aedbf5a0de6a57a637b39b",
+                "d27e88681ce3243c4830165a8fdcf9ff"
+                + "1de9a1d8e6b447ef6ef7b79828666e45"
+                + "81e79012af34ddd9e2f037589b292db3"
+                + "e67c036745fa22e7e9b7373b",
+                "dcf566ff291c25bbb8568fc3d376a6d9",
+            },
+            new string[]
+            {
+                "Test Case 13",
+                "00000000000000000000000000000000"
+                + "00000000000000000000000000000000",
+                "",
+                "",
+                "000000000000000000000000",
+                "",
+                "530f8afbc74536b9a963b4f1c4cb738b",
+            },
+            new string[]
+            {
+                "Test Case 14",
+                "00000000000000000000000000000000"
+                + "00000000000000000000000000000000",
+                "00000000000000000000000000000000",
+                "",
+                "000000000000000000000000",
+                "cea7403d4d606b6e074ec5d3baf39d18",
+                "d0d1c8a799996bf0265b98b5d48ab919",
+            },
+            new string[]
+            {
+                "Test Case 15",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b391aafd255",
+                "",
+                "cafebabefacedbaddecaf888",
+                "522dc1f099567d07f47f37a32a84427d"
+                + "643a8cdcbfe5c0c97598a2bd2555d1aa"
+                + "8cb08e48590dbb3da7b08b1056828838"
+                + "c5f61e6393ba7a0abcc9f662898015ad",
+                "b094dac5d93471bdec1a502270e3cc6c",
+            },
+            new string[]
+            {
+                "Test Case 16",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbaddecaf888",
+                "522dc1f099567d07f47f37a32a84427d"
+                + "643a8cdcbfe5c0c97598a2bd2555d1aa"
+                + "8cb08e48590dbb3da7b08b1056828838"
+                + "c5f61e6393ba7a0abcc9f662",
+                "76fc6ece0f4e1768cddf8853bb2d551b",
+            },
+            new string[]
+            {
+                "Test Case 17",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "cafebabefacedbad",
+                "c3762df1ca787d32ae47c13bf19844cb"
+                + "af1ae14d0b976afac52ff7d79bba9de0"
+                + "feb582d33934a4f0954cc2363bc73f78"
+                + "62ac430e64abe499f47c9b1f",
+                "3a337dbf46a792c45e454913fe2ea8f2",
+            },
+            new string[]
+            {
+                "Test Case 18",
+                "feffe9928665731c6d6a8f9467308308"
+                + "feffe9928665731c6d6a8f9467308308",
+                "d9313225f88406e5a55909c5aff5269a"
+                + "86a7a9531534f7da2e4c303d8a318a72"
+                + "1c3c0c95956809532fcf0e2449a6b525"
+                + "b16aedf5aa0de657ba637b39",
+                "feedfacedeadbeeffeedfacedeadbeef"
+                + "abaddad2",
+                "9313225df88406e555909c5aff5269aa"
+                + "6a7a9538534f7da1e4c303d2a318a728"
+                + "c3c0c95156809539fcf0e2429a6b5254"
+                + "16aedbf5a0de6a57a637b39b",
+                "5a8def2f0c9e53f1f75d7853659e2a20"
+                + "eeb2b22aafde6419a058ab4f6f746bf4"
+                + "0fc0c3b780f244452da3ebf1c5d82cde"
+                + "a2418997200ef82e44ae7e3f",
+                "a44a8266ee1c8eb0c8b5d4cf5ae9f19a",
+            },
+        };
+
+        public override string Name
+        {
+            get { return "GCM"; }
+        }
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i < TestVectors.Length; ++i)
+            {
+                RunTestCase(TestVectors[i]);
+            }
+
+            RandomTests();
+            OutputSizeTests();
+            DoTestExceptions();
+        }
+
+        protected IBlockCipher CreateAesEngine()
+        {
+            return new AesFastEngine();
+        }
+
+        private void DoTestExceptions()
+        {
+            GcmBlockCipher gcm = new GcmBlockCipher(CreateAesEngine());
+
+            try
+            {
+                gcm = new GcmBlockCipher(new DesEngine());
+
+                Fail("incorrect block size not picked up");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                gcm.Init(false, new KeyParameter(new byte[16]));
+
+                Fail("illegal argument not picked up");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // TODO
+            //AEADTestUtil.testReset(this, new GCMBlockCipher(createAESEngine()), new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
+            //AEADTestUtil.testTampering(this, gcm, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[16]));
+            //AEADTestUtil.testOutputSizes(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(new KeyParameter(
+            //        new byte[16]), 128, new byte[16]));
+            //AEADTestUtil.testBufferSizeChecks(this, new GCMBlockCipher(createAESEngine()), new AEADParameters(
+            //        new KeyParameter(new byte[16]), 128, new byte[16]));
+        }
+
+        private void RunTestCase(string[] testVector)
+        {
+            for (int macLength = 12; macLength <= 16; ++macLength)
+            {
+                RunTestCase(testVector, macLength);
+            }
+        }
+
+        private void RunTestCase(string[] testVector, int macLength)
+        {
+            int pos = 0;
+            string testName = testVector[pos++];
+            byte[] K = Hex.Decode(testVector[pos++]);
+            byte[] P = Hex.Decode(testVector[pos++]);
+            byte[] A = Hex.Decode(testVector[pos++]);
+            byte[] IV = Hex.Decode(testVector[pos++]);
+            byte[] C = Hex.Decode(testVector[pos++]);
+
+            // For short MAC, take leading bytes
+            byte[] t = Hex.Decode(testVector[pos++]);
+            byte[] T = new byte[macLength];
+            Array.Copy(t, T, T.Length);
+
+            // Default multiplier
+            RunTestCase(null, null, testName, K, IV, A, P, C, T);
+
+            RunTestCase(new BasicGcmMultiplier(), new BasicGcmMultiplier(), testName, K, IV, A, P, C, T);
+            RunTestCase(new Tables8kGcmMultiplier(), new Tables8kGcmMultiplier(), testName, K, IV, A, P, C, T);
+            RunTestCase(new Tables64kGcmMultiplier(), new Tables64kGcmMultiplier(), testName, K, IV, A, P, C, T);
+        }
+
+        private void RunTestCase(
+            IGcmMultiplier	encM,
+            IGcmMultiplier	decM,
+            string			testName,
+            byte[]          K,
+            byte[]          IV,
+            byte[]          A,
+            byte[]          P,
+            byte[]			C,
+            byte[]			T)
+        {
+            byte[] fa = new byte[A.Length / 2];
+            byte[] la = new byte[A.Length - (A.Length / 2)];
+            Array.Copy(A, 0, fa, 0, fa.Length);
+            Array.Copy(A, fa.Length, la, 0, la.Length);
+
+            RunTestCase(encM, decM, testName + " all initial associated data", K, IV, A, null, P, C, T);
+            RunTestCase(encM, decM, testName + " all subsequent associated data", K, IV, null, A, P, C, T);
+            RunTestCase(encM, decM, testName + " split associated data", K, IV, fa, la, P, C, T);
+        }
+
+        private void RunTestCase(
+            IGcmMultiplier  encM,
+            IGcmMultiplier  decM,
+            string          testName,
+            byte[]          K,
+            byte[]          IV,
+            byte[]          A,
+            byte[]          SA,
+            byte[]          P,
+            byte[]          C,
+            byte[]          T)
+        {
+            AeadParameters parameters = new AeadParameters(new KeyParameter(K), T.Length * 8, IV, A);
+            GcmBlockCipher encCipher = InitCipher(encM, true, parameters);
+            GcmBlockCipher decCipher = InitCipher(decM, false, parameters);
+            CheckTestCase(encCipher, decCipher, testName, SA, P, C, T);
+            CheckTestCase(encCipher, decCipher, testName + " (reused)", SA, P, C, T);
+
+            // Key reuse
+            AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters);
+            encCipher.Init(true, keyReuseParams);
+            decCipher.Init(false, keyReuseParams);
+            CheckTestCase(encCipher, decCipher, testName + " (key reuse)", SA, P, C, T);
+        }
+
+        private GcmBlockCipher InitCipher(
+            IGcmMultiplier	m,
+            bool			forEncryption,
+            AeadParameters	parameters)
+        {
+            GcmBlockCipher c = new GcmBlockCipher(CreateAesEngine(), m);
+            c.Init(forEncryption, parameters);
+            return c;
+        }
+
+        private void CheckTestCase(
+            GcmBlockCipher	encCipher,
+            GcmBlockCipher	decCipher,
+            string			testName,
+            byte[]          SA,
+            byte[]          P,
+            byte[]			C,
+            byte[]			T)
+        {
+            byte[] enc = new byte[encCipher.GetOutputSize(P.Length)];
+            if (SA != null)
+            {
+                encCipher.ProcessAadBytes(SA, 0, SA.Length);
+            }
+            int len = encCipher.ProcessBytes(P, 0, P.Length, enc, 0);
+            len += encCipher.DoFinal(enc, len);
+
+            if (enc.Length != len)
+            {
+//				Console.WriteLine("" + enc.Length + "/" + len);
+                Fail("encryption reported incorrect length: " + testName);
+            }
+
+            byte[] mac = encCipher.GetMac();
+
+            byte[] data = new byte[P.Length];
+            Array.Copy(enc, data, data.Length);
+            byte[] tail = new byte[enc.Length - P.Length];
+            Array.Copy(enc, P.Length, tail, 0, tail.Length);
+
+            if (!AreEqual(C, data))
+            {
+                Fail("incorrect encrypt in: " + testName);
+            }
+
+            if (!AreEqual(T, mac))
+            {
+                Fail("GetMac() returned wrong mac in: " + testName);
+            }
+
+            if (!AreEqual(T, tail))
+            {
+                Fail("stream contained wrong mac in: " + testName);
+            }
+
+            byte[] dec = new byte[decCipher.GetOutputSize(enc.Length)];
+            if (SA != null)
+            {
+                decCipher.ProcessAadBytes(SA, 0, SA.Length);
+            }
+            len = decCipher.ProcessBytes(enc, 0, enc.Length, dec, 0);
+            len += decCipher.DoFinal(dec, len);
+            mac = decCipher.GetMac();
+
+            data = new byte[C.Length];
+            Array.Copy(dec, data, data.Length);
+
+            if (!AreEqual(P, data))
+            {
+                Fail("incorrect decrypt in: " + testName);
+            }
+        }
+
+        private void RandomTests()
+        {
+            SecureRandom srng = new SecureRandom();
+            srng.SetSeed(DateTimeUtilities.CurrentUnixMs());
+            RandomTests(srng, null);
+            RandomTests(srng, new BasicGcmMultiplier());
+            RandomTests(srng, new Tables8kGcmMultiplier());
+            RandomTests(srng, new Tables64kGcmMultiplier());
+        }
+
+        private void RandomTests(SecureRandom srng, IGcmMultiplier m)
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                RandomTest(srng, m);
+            }
+        }
+
+        private void RandomTest(SecureRandom srng, IGcmMultiplier m)
+        {
+            int kLength = 16 + 8 * srng.Next(3);
+            byte[] K = new byte[kLength];
+            srng.NextBytes(K);
+
+            int pLength = srng.Next(65536);
+            byte[] P = new byte[pLength];
+            srng.NextBytes(P);
+
+            int aLength = srng.Next(256);
+            byte[] A = new byte[aLength];
+            srng.NextBytes(A);
+
+            int saLength = srng.Next(256);
+            byte[] SA = new byte[saLength];
+            srng.NextBytes(SA);
+
+            int ivLength = 1 + srng.Next(256);
+            byte[] IV = new byte[ivLength];
+            srng.NextBytes(IV);
+
+            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
+            GcmBlockCipher cipher = InitCipher(m, true, parameters);
+            byte[] C = new byte[cipher.GetOutputSize(P.Length)];
+            int predicted = cipher.GetUpdateOutputSize(P.Length);
+
+            int split = srng.Next(SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            int len = cipher.ProcessBytes(P, 0, P.Length, C, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            if (predicted != len)
+            {
+                Fail("encryption reported incorrect update length in randomised test");
+            }
+
+            len += cipher.DoFinal(C, len);
+
+            if (C.Length != len)
+            {
+                Fail("encryption reported incorrect length in randomised test");
+            }
+
+            byte[] encT = cipher.GetMac();
+            byte[] tail = new byte[C.Length - P.Length];
+            Array.Copy(C, P.Length, tail, 0, tail.Length);
+
+            if (!AreEqual(encT, tail))
+            {
+                Fail("stream contained wrong mac in randomised test");
+            }
+
+            cipher.Init(false, parameters);
+            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
+            predicted = cipher.GetUpdateOutputSize(C.Length);
+
+            split = srng.Next(SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            if (predicted != len)
+            {
+                Fail("decryption reported incorrect update length in randomised test");
+            }
+
+            len += cipher.DoFinal(decP, len);
+
+            if (!AreEqual(P, decP))
+            {
+                Fail("incorrect decrypt in randomised test");
+            }
+
+            byte[] decT = cipher.GetMac();
+            if (!AreEqual(encT, decT))
+            {
+                Fail("decryption produced different mac from encryption");
+            }
+
+            //
+            // key reuse test
+            //
+            cipher.Init(false, AeadTestUtilities.ReuseKey(parameters));
+            decP = new byte[cipher.GetOutputSize(C.Length)];
+
+            split = NextInt(srng, SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            len += cipher.DoFinal(decP, len);
+
+            if (!AreEqual(P, decP))
+            {
+                Fail("incorrect decrypt in randomised test");
+            }
+
+            decT = cipher.GetMac();
+            if (!AreEqual(encT, decT))
+            {
+                Fail("decryption produced different mac from encryption");
+            }
+        }
+
+        private void OutputSizeTests()
+        {
+            byte[] K = new byte[16];
+            byte[] A = null;
+            byte[] IV = new byte[16];
+
+            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
+            GcmBlockCipher cipher = InitCipher(null, true, parameters);
+
+            if (cipher.GetUpdateOutputSize(0) != 0)
+            {
+                Fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
+            }
+
+            if (cipher.GetOutputSize(0) != 16)
+            {
+                Fail("incorrect getOutputSize for initial 0 bytes encryption");
+            }
+
+            cipher.Init(false, parameters);
+
+            if (cipher.GetUpdateOutputSize(0) != 0)
+            {
+                Fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
+            }
+
+            // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
+            if (cipher.GetOutputSize(0) != 0)
+            {
+                Fail("fragile getOutputSize for initial 0 bytes decryption");
+            }
+
+            if (cipher.GetOutputSize(16) != 0)
+            {
+                Fail("incorrect getOutputSize for initial MAC-size bytes decryption");
+            }
+        }
+
+        private static int NextInt(SecureRandom rand, int n)
+        {
+            if ((n & -n) == n)  // i.e., n is a power of 2
+            {
+                return (int)(((uint)n * (ulong)((uint)rand.NextInt() >> 1)) >> 31);
+            }
+
+            int bits, value;
+            do
+            {
+                bits = (int)((uint)rand.NextInt() >> 1);
+                value = bits % n;
+            }
+            while (bits - value + (n - 1) < 0);
+
+            return value;
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new GcmTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GMacTest.cs
new file mode 100644
index 0000000..383ff96
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GMacTest.cs
@@ -0,0 +1,187 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * Test vectors for AES-GMAC, extracted from <a
+     * href="http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip">NIST CAVP GCM test
+     * vectors</a>.
+     * 
+     */
+    [TestFixture]
+    public class GMacTest 
+        : SimpleTest
+    {
+        private class TestCase
+        {
+            private byte[] key;
+            private byte[] iv;
+            private byte[] ad;
+            private byte[] tag;
+            private string name;
+
+            internal TestCase(string name, string key, string iv, string ad, string tag)
+            {
+                this.name = name;
+                this.key = Hex.Decode(key);
+                this.iv = Hex.Decode(iv);
+                this.ad = Hex.Decode(ad);
+                this.tag = Hex.Decode(tag);
+            }
+
+            public string getName()
+            {
+                return name;
+            }
+
+            public byte[] getKey()
+            {
+                return key;
+            }
+
+            public byte[] getIv()
+            {
+                return iv;
+            }
+
+            public byte[] getAd()
+            {
+                return ad;
+            }
+
+            public byte[] getTag()
+            {
+                return tag;
+            }
+        }
+
+        private TestCase[] TEST_VECTORS = new TestCase[] {
+            // Count = 0, from each of the PTlen = 0 test vector sequences
+            new TestCase("128/96/0/128", "11754cd72aec309bf52f7687212e8957", "3c819d9a9bed087615030b65", "",
+                         "250327c674aaf477aef2675748cf6971"),
+            new TestCase("128/96/0/120", "272f16edb81a7abbea887357a58c1917", "794ec588176c703d3d2a7a07", "",
+                         "b6e6f197168f5049aeda32dafbdaeb"),
+            new TestCase("128/96/0/112", "81b6844aab6a568c4556a2eb7eae752f", "ce600f59618315a6829bef4d", "",
+                         "89b43e9dbc1b4f597dbbc7655bb5"),
+            new TestCase("128/96/0/104", "cde2f9a9b1a004165ef9dc981f18651b", "29512c29566c7322e1e33e8e", "",
+                         "2e58ce7dabd107c82759c66a75"),
+            new TestCase("128/96/0/96", "b01e45cc3088aaba9fa43d81d481823f", "5a2c4a66468713456a4bd5e1", "",
+                         "014280f944f53c681164b2ff"),
+
+            new TestCase("128/96/128/128", "77be63708971c4e240d1cb79e8d77feb", "e0e00f19fed7ba0136a797f3",
+                         "7a43ec1d9c0a5a78a0b16533a6213cab", "209fcc8d3675ed938e9c7166709dd946"),
+            new TestCase("128/96/128/96", "bea48ae4980d27f357611014d4486625", "32bddb5c3aa998a08556454c",
+                         "8a50b0b8c7654bced884f7f3afda2ead", "8e0f6d8bf05ffebe6f500eb1"),
+
+            new TestCase("128/96/384/128", "99e3e8793e686e571d8285c564f75e2b", "c2dd0ab868da6aa8ad9c0d23",
+                         "b668e42d4e444ca8b23cfdd95a9fedd5178aa521144890b093733cf5cf22526c5917ee476541809ac6867a8c399309fc",
+                         "3f4fba100eaf1f34b0baadaae9995d85"),
+            new TestCase("128/96/384/96", "c77acd1b0918e87053cb3e51651e7013", "39ff857a81745d10f718ac00",
+                         "407992f82ea23b56875d9a3cb843ceb83fd27cb954f7c5534d58539fe96fb534502a1b38ea4fac134db0a42de4be1137",
+                         "2a5dc173285375dc82835876"),
+
+            new TestCase(
+                "128/1024/0/128",
+                "d0f1f4defa1e8c08b4b26d576392027c",
+                "42b4f01eb9f5a1ea5b1eb73b0fb0baed54f387ecaa0393c7d7dffc6af50146ecc021abf7eb9038d4303d91f8d741a11743166c0860208bcc02c6258fd9511a2fa626f96d60b72fcff773af4e88e7a923506e4916ecbd814651e9f445adef4ad6a6b6c7290cc13b956130eef5b837c939fcac0cbbcc9656cd75b13823ee5acdac",
+                "", "7ab49b57ddf5f62c427950111c5c4f0d"),
+            new TestCase(
+                "128/1024/384/96",
+                "3cce72d37933394a8cac8a82deada8f0",
+                "aa2f0d676d705d9733c434e481972d4888129cf7ea55c66511b9c0d25a92a174b1e28aa072f27d4de82302828955aadcb817c4907361869bd657b45ff4a6f323871987fcf9413b0702d46667380cd493ed24331a28b9ce5bbfa82d3a6e7679fcce81254ba64abcad14fd18b22c560a9d2c1cd1d3c42dac44c683edf92aced894",
+                "5686b458e9c176f4de8428d9ebd8e12f569d1c7595cf49a4b0654ab194409f86c0dd3fdb8eb18033bb4338c70f0b97d1",
+                "a3a9444b21f330c3df64c8b6"), };
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i < TEST_VECTORS.Length; i++)
+            {
+                TestCase testCase = TEST_VECTORS[i];
+
+                IMac mac = new GMac(new GcmBlockCipher(new AesFastEngine()), testCase.getTag().Length * 8);
+                ICipherParameters key = new KeyParameter(testCase.getKey());
+                mac.Init(new ParametersWithIV(key, testCase.getIv()));
+
+                testSingleByte(mac, testCase);
+                testMultibyte(mac, testCase);
+            }
+
+            // Invalid mac size
+            testInvalidMacSize(97);
+            testInvalidMacSize(136);
+            testInvalidMacSize(24);
+        }
+
+        private void testInvalidMacSize(int size)
+        {
+            try
+            {
+                GMac mac = new GMac(new GcmBlockCipher(new AesFastEngine()), size);
+                mac.Init(new ParametersWithIV(null, new byte[16]));
+                Fail("Expected failure for illegal mac size " + size);
+            }
+            catch (ArgumentException e)
+            {
+                if (!e.Message.StartsWith("Invalid value for MAC size"))
+                {
+                    Fail("Illegal mac size failed with unexpected message");
+                }
+            }
+        }
+
+        private void testMultibyte(IMac mac, TestCase testCase)
+        {
+            mac.BlockUpdate(testCase.getAd(), 0, testCase.getAd().Length);
+            checkMac(mac, testCase);
+        }
+
+        private void testSingleByte(IMac mac, TestCase testCase)
+        {
+            byte[] ad = testCase.getAd();
+            for (int i = 0; i < ad.Length; i++)
+            {
+                mac.Update(ad[i]);
+            }
+            checkMac(mac, testCase);
+        }
+
+        private void checkMac(IMac mac, TestCase testCase)
+        {
+            byte[] generatedMac = new byte[mac.GetMacSize()];
+            mac.DoFinal(generatedMac, 0);
+            if (!AreEqual(testCase.getTag(), generatedMac))
+            {
+                Fail("Failed " + testCase.getName() + " - expected " + Hex.ToHexString(testCase.getTag()) + " got "
+                     + Hex.ToHexString(generatedMac));
+            }
+        }
+
+        public override string Name
+        {
+            get { return "GMac"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new GMacTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147MacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147MacTest.cs
new file mode 100644
index 0000000..5f3188f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147MacTest.cs
@@ -0,0 +1,105 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * GOST 28147 MAC tester
+	 */
+	[TestFixture]
+	public class Gost28147MacTest
+		:	ITest
+	{
+		//
+		// these GOSTMac for testing.
+		//
+		static byte[]   gkeyBytes1 = Hex.Decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
+		static byte[]   gkeyBytes2 = Hex.Decode("6d145dc993f4019e104280df6fcd8cd8e01e101e4c113d7ec4f469ce6dcd9e49");
+
+		static byte[]   input3 = Hex.Decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
+		static byte[]   input4 = Hex.Decode("7768617420646f2079612077616e7420666f72206e6f7468696e673f");
+
+		static byte[]   output7 = Hex.Decode("93468a46");
+		static byte[]   output8 = Hex.Decode("93468a46");
+
+		public Gost28147MacTest()
+		{
+		}
+
+		public ITestResult Perform()
+		{
+			// test1
+			IMac mac = new Gost28147Mac();
+			KeyParameter key = new KeyParameter(gkeyBytes1);
+
+			mac.Init(key);
+
+			mac.BlockUpdate(input3, 0, input3.Length);
+
+			byte[] outBytes = new byte[4];
+
+			mac.DoFinal(outBytes, 0);
+
+			if (!Arrays.AreEqual(outBytes, output7))
+			{
+				return new SimpleTestResult(false, Name + ": Failed test 1 - expected "
+					+ Hex.ToHexString(output7)
+					+ " got " + Hex.ToHexString(outBytes));
+			}
+
+			// test2
+			key = new KeyParameter(gkeyBytes2);
+
+			ParametersWithSBox gparam = new ParametersWithSBox(key, Gost28147Engine.GetSBox("E-A"));
+
+			mac.Init(gparam);
+
+			mac.BlockUpdate(input4, 0, input4.Length);
+
+			outBytes = new byte[4];
+
+			mac.DoFinal(outBytes, 0);
+
+			if (!Arrays.AreEqual(outBytes, output8))
+			{
+				return new SimpleTestResult(false, Name + ": Failed test 2 - expected "
+					+ Hex.ToHexString(output8)
+					+ " got " + Hex.ToHexString(outBytes));
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public string Name
+		{
+			get { return "Gost28147Mac"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new Gost28147MacTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147Test.cs
new file mode 100644
index 0000000..5b67535
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST28147Test.cs
@@ -0,0 +1,334 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class Gost28147Test
+		: CipherTest
+	{
+		static string input1 =  "0000000000000000";
+		static string output1 = "1b0bbc32cebcab42";
+		static string input2 =  "bc350e71aac5f5c2";
+		static string output2 = "d35ab653493b49f5";
+		static string input3 =  "bc350e71aa11345709acde";
+		static string output3 = "8824c124c4fd14301fb1e8";
+		static string input4 =  "000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f";
+		static string output4 = "29b7083e0a6d955ca0ec5b04fdb4ea41949f1dd2efdf17baffc1780b031f3934";
+
+		static byte[] TestSBox = {
+				0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+				0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+				0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+				0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+				0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+				0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0,
+				0x0,0x1,0x2,0x3,0x4,0x5,0x6,0x7,0x8,0x9,0xA,0xB,0xC,0xD,0xE,0xF,
+				0xF,0xE,0xD,0xC,0xB,0xA,0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x2,0x1,0x0
+		};
+
+		static SimpleTest[] tests =
+		{   new BlockCipherVectorTest(1, new Gost28147Engine(),
+				new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),
+					input1, output1),
+			new BlockCipherVectorTest(2, new CbcBlockCipher(new Gost28147Engine()),
+				new ParametersWithIV(new KeyParameter(Hex.Decode("00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF")),
+				Hex.Decode("1234567890abcdef")), input2, output2),
+			new BlockCipherVectorTest(3, new GOfbBlockCipher(new Gost28147Engine()),
+				new ParametersWithIV(new KeyParameter(Hex.Decode("0011223344556677889900112233445566778899001122334455667788990011")),
+				Hex.Decode("1234567890abcdef")), //IV
+				input3, output3),
+			new BlockCipherVectorTest(4, new CfbBlockCipher(new Gost28147Engine(), 64),
+				new ParametersWithIV(new KeyParameter(Hex.Decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5")),
+				Hex.Decode("aafd12f659cae634")), input4, output4),
+
+			//tests with parameters, set S-box.
+			new BlockCipherVectorTest(5, new Gost28147Engine(),
+				new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")),//key , default parameter S-box set to D-Test
+				input1, output1),
+			new BlockCipherVectorTest(6, new CfbBlockCipher(new Gost28147Engine(), 64),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("D-Test")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"b587f7a0814c911d"), //encrypt message
+			new BlockCipherVectorTest(7, new CfbBlockCipher(new Gost28147Engine(), 64),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("E-Test")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"e8287f53f991d52b"), //encrypt message
+			new BlockCipherVectorTest(8, new CfbBlockCipher(new Gost28147Engine(), 64),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("E-A")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"c41009dba22ebe35"), //encrypt message
+			new BlockCipherVectorTest(9, new CfbBlockCipher(new Gost28147Engine(), 8),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("E-B")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"80d8723fcd3aba28"), //encrypt message
+			new BlockCipherVectorTest(10, new CfbBlockCipher(new Gost28147Engine(), 8),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("E-C")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"739f6f95068499b5"), //encrypt message
+			new BlockCipherVectorTest(11, new CfbBlockCipher(new Gost28147Engine(), 8),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("E-D")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"4663f720f4340f57"), //encrypt message
+			new BlockCipherVectorTest(12, new CfbBlockCipher(new Gost28147Engine(), 8),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						Gost28147Engine.GetSBox("D-A")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"5bb0a31d218ed564"), //encrypt message
+			new BlockCipherVectorTest(13, new CfbBlockCipher(new Gost28147Engine(), 8),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+						new KeyParameter(Hex.Decode("546d203368656c326973652073736e62206167796967747473656865202c3d73")), //key
+						TestSBox), //set own S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"0000000000000000", //input message
+					"c3af96ef788667c5"), //encrypt message
+			new BlockCipherVectorTest(14, new GOfbBlockCipher(new Gost28147Engine()),
+				new ParametersWithIV(
+					new ParametersWithSBox(
+							new KeyParameter(Hex.Decode("4ef72b778f0b0bebeef4f077551cb74a927b470ad7d7f2513454569a247e989d")), //key
+							Gost28147Engine.GetSBox("E-A")), //type S-box
+					Hex.Decode("1234567890abcdef")), //IV
+					"bc350e71aa11345709acde",  //input message
+					"1bcc2282707c676fb656dc"), //encrypt message
+
+		};
+
+		private const int Gost28147_KEY_LENGTH = 32;
+
+		private byte[] generateKey(byte[] startkey)
+		{
+			byte[] newKey = new byte[Gost28147_KEY_LENGTH];
+
+			Gost3411Digest digest = new Gost3411Digest();
+
+			digest.BlockUpdate(startkey, 0, startkey.Length);
+			digest.DoFinal(newKey, 0);
+
+			return newKey;
+		}
+
+		public Gost28147Test()
+			: base(tests, new Gost28147Engine(), new KeyParameter(new byte[32]))
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			//advanced tests with Gost28147KeyGenerator:
+			//encrypt on hesh message; ECB mode:
+			byte[] inBytes = Hex.Decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+			byte[] output = Hex.Decode("8ad3c8f56b27ff1fbd46409359bdc796bc350e71aac5f5c0");
+			byte[] outBytes = new byte[inBytes.Length];
+
+			byte[] key = generateKey(Hex.Decode("0123456789abcdef"));  //!!! heshing start_key - get 256 bits !!!
+	//        System.out.println(new string(Hex.Encode(key)));
+			ICipherParameters  param = new ParametersWithSBox(new KeyParameter(key), Gost28147Engine.GetSBox("E-A"));
+			//CipherParameters  param = new Gost28147Parameters(key,"D-Test");
+			BufferedBlockCipher cipher = new BufferedBlockCipher(new Gost28147Engine());
+
+			cipher.Init(true, param);
+			int len1 = cipher.ProcessBytes(inBytes, 0, inBytes.Length, outBytes, 0);
+			try
+			{
+				cipher.DoFinal(outBytes, len1);
+			}
+			catch (CryptoException e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (outBytes.Length != output.Length)
+			{
+				Fail("failed - "
+					+ "expected " + Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			for (int i = 0; i != outBytes.Length; i++)
+			{
+				if (outBytes[i] != output[i])
+				{
+					Fail("failed - "
+						+ "expected " + Hex.ToHexString(output)
+						+ " got " + Hex.ToHexString(outBytes));
+				}
+			}
+
+
+			//encrypt on hesh message; CFB mode:
+			inBytes = Hex.Decode("bc350e71aac5f5c2");
+			output = Hex.Decode("0ebbbafcf38f14a5");
+			outBytes = new byte[inBytes.Length];
+
+			key = generateKey(Hex.Decode("0123456789abcdef"));  //!!! heshing start_key - get 256 bits !!!
+			param = new ParametersWithIV(
+				new ParametersWithSBox(
+					new KeyParameter(key), //key
+					Gost28147Engine.GetSBox("E-A")), //type S-box
+				Hex.Decode("1234567890abcdef")); //IV
+
+			cipher = new BufferedBlockCipher(new CfbBlockCipher(new Gost28147Engine(), 64));
+
+			cipher.Init(true, param);
+			len1 = cipher.ProcessBytes(inBytes, 0, inBytes.Length, outBytes, 0);
+			try
+			{
+				cipher.DoFinal(outBytes, len1);
+			}
+			catch (CryptoException e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+			if (outBytes.Length != output.Length)
+			{
+				Fail("failed - "
+					+ "expected " + Hex.ToHexString(output)
+					+ " got " + Hex.ToHexString(outBytes));
+			}
+			for (int i = 0; i != outBytes.Length; i++)
+			{
+				if (outBytes[i] != output[i])
+				{
+					Fail("failed - "
+						+ "expected " + Hex.ToHexString(output)
+						+ " got " + Hex.ToHexString(outBytes));
+				}
+			}
+
+
+			//encrypt on hesh message; CFB mode:
+			inBytes = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
+			output = Hex.Decode("64988982819f0a1655e226e19ecad79d10cc73bac95c5d7da034786c12294225");
+			outBytes = new byte[inBytes.Length];
+
+			key = generateKey(Hex.Decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f659cae63489b479e5"));  //!!! heshing start_key - get 256 bits !!!
+			param = new ParametersWithIV(
+				new ParametersWithSBox(
+					new KeyParameter(key), //key
+					Gost28147Engine.GetSBox("E-A")), //type S-box
+				Hex.Decode("aafd12f659cae634")); //IV
+
+			cipher = new BufferedBlockCipher(new CfbBlockCipher(new Gost28147Engine(), 64));
+
+			cipher.Init(true, param);
+			len1 = cipher.ProcessBytes(inBytes, 0, inBytes.Length, outBytes, 0);
+
+			cipher.DoFinal(outBytes, len1);
+
+			if (outBytes.Length != output.Length)
+			{
+				Fail("failed - "
+					+ "expected " + Hex.ToHexString(output)
+					+ " got " + Hex.ToHexString(outBytes));
+			}
+
+			for (int i = 0; i != outBytes.Length; i++)
+			{
+				if (outBytes[i] != output[i])
+				{
+					Fail("failed - "
+						+ "expected " + Hex.ToHexString(output)
+						+ " got " + Hex.ToHexString(outBytes));
+				}
+			}
+
+			//encrypt on hesh message; OFB mode:
+			inBytes = Hex.Decode("bc350e71aa11345709acde");
+			output = Hex.Decode("1bcc2282707c676fb656dc");
+			outBytes = new byte[inBytes.Length];
+
+			key = generateKey(Hex.Decode("0123456789abcdef"));  //!!! heshing start_key - get 256 bits !!!
+			param = new ParametersWithIV(
+				new ParametersWithSBox(
+					new KeyParameter(key), //key
+					Gost28147Engine.GetSBox("E-A")), //type S-box
+				Hex.Decode("1234567890abcdef")); //IV
+
+			cipher = new BufferedBlockCipher(new GOfbBlockCipher(new Gost28147Engine()));
+
+			cipher.Init(true, param);
+			len1 = cipher.ProcessBytes(inBytes, 0, inBytes.Length, outBytes, 0);
+
+			cipher.DoFinal(outBytes, len1);
+
+			if (outBytes.Length != output.Length)
+			{
+				Fail("failed - "
+					+ "expected " + Hex.ToHexString(output)
+					+ " got " + Hex.ToHexString(outBytes));
+			}
+
+			for (int i = 0; i != outBytes.Length; i++)
+			{
+				if (outBytes[i] != output[i])
+				{
+					Fail("failed - "
+						+ "expected " + Hex.ToHexString(output)
+						+ " got " + Hex.ToHexString(outBytes));
+				}
+			}
+		}
+
+		public override string Name
+		{
+			get { return "Gost28147"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new Gost28147Test();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3410Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3410Test.cs
new file mode 100644
index 0000000..f546627
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3410Test.cs
@@ -0,0 +1,1604 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class Gost3410Test
+		: ITest
+	{
+		private static readonly byte[] hashmessage = Hex.Decode("3042453136414534424341374533364339313734453431443642453241453435");
+
+		private static byte[] zeroTwo(int length)
+		{
+			byte[] data = new byte[length];
+			data[data.Length - 1] = 0x02;
+			return data;
+		}
+
+		private class Gost3410_TEST1_512
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-TEST1-512"; }
+			}
+
+			FixedSecureRandom init_random = FixedSecureRandom.From(Hex.Decode("00005EC900007341"), zeroTwo(64));
+			FixedSecureRandom random = FixedSecureRandom.From(Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
+			FixedSecureRandom keyRandom = FixedSecureRandom.From(Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"));
+
+			BigInteger pValue = new BigInteger("EE8172AE8996608FB69359B89EB82A69854510E2977A4D63BC97322CE5DC3386EA0A12B343E9190F23177539845839786BB0C345D165976EF2195EC9B1C379E3", 16);
+			BigInteger qValue = new BigInteger("98915E7EC8265EDFCDA31E88F24809DDB064BDC7285DD50D7289F0AC6F49DD2D", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("3e5f895e276d81d2d52c0763270a458157b784c57abdbd807bc44fd43a32ac06",16);
+				BigInteger s = new BigInteger("3f0dd5d4400d47c08e4ce505ff7434b6dbf729592e37c74856dab85115a60955",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(512, 1, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (parameters.ValidationParameters == null)
+				{
+					return new SimpleTestResult(false, Name + "validation parameters wrong");
+				}
+
+				if (parameters.ValidationParameters.C != 29505
+					||  parameters.ValidationParameters.X0 != 24265)
+				{
+					return new SimpleTestResult(false, Name + "validation parameters values wrong");
+				}
+
+				if (!init_random.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'init_random'.");
+				}
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator         Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters  genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair  pair = Gost3410KeyGen.GenerateKeyPair();
+
+				if (!keyRandom.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'keyRandom'.");
+				}
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer gost3410 = new Gost3410Signer();
+
+				gost3410.Init(true, param);
+
+				BigInteger[] sig = gost3410.GenerateSignature(hashmessage);
+
+				if (!random.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'random'.");
+				}
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				gost3410.Init(false, pair.Public);
+
+				if (gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_TEST2_512
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-TEST2-512"; }
+			}
+
+			FixedSecureRandom init_random = FixedSecureRandom.From(Hex.Decode("000000003DFC46F1000000000000000D"), zeroTwo(64));
+			FixedSecureRandom random = FixedSecureRandom.From(Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A"));
+			FixedSecureRandom keyRandom = FixedSecureRandom.From(Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046"));
+
+			BigInteger pValue = new BigInteger("8b08eb135af966aab39df294538580c7da26765d6d38d30cf1c06aae0d1228c3316a0e29198460fad2b19dc381c15c888c6dfd0fc2c565abb0bf1faff9518f85", 16);
+			BigInteger qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("7c07c8cf035c2a1cb2b7fae5807ac7cd623dfca7a1a68f6d858317822f1ea00d",16);
+				BigInteger s = new BigInteger("7e9e036a6ff87dbf9b004818252b1f6fc310bdd4d17cb8c37d9c36c7884de60c",16);
+				Gost3410ParametersGenerator  pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(512, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!init_random.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'init_random'.");
+				}
+
+				if (parameters.ValidationParameters == null)
+				{
+					return new SimpleTestResult(false, Name + ": validation parameters wrong");
+				}
+
+				if (parameters.ValidationParameters.CL != 13
+					||  parameters.ValidationParameters.X0L != 1039943409)
+				{
+					return new SimpleTestResult(false, Name + ": validation parameters values wrong");
+				}
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				if (!keyRandom.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'keyRandom'.");
+				}
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!random.IsExhausted)
+				{
+					return new SimpleTestResult(false, Name
+						+ ": unexpected number of bytes used from 'random'.");
+				}
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (!Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+		}
+
+		private class Gost3410_TEST1_1024
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-TEST1-1024"; }
+			}
+
+			private class SecureRandomImpl1 : SecureRandom
+			{
+				bool firstInt = true;
+
+				public override int NextInt()
+				{
+					string x0 = "0xA565";
+					string c =  "0x538B";
+
+					if (firstInt)
+					{
+						firstInt = false;
+						return NumberParsing.DecodeIntFromHex(x0);
+					}
+					return NumberParsing.DecodeIntFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+
+					byte[] d = Hex.Decode("02");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl1();
+
+			private class SecureRandomImpl2 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl2();
+
+			private class SecureRandomImpl3 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl3();
+
+			BigInteger  pValue = new BigInteger("ab8f37938356529e871514c1f48c5cbce77b2f4fc9a2673ac2c1653da8984090c0ac73775159a26bef59909d4c9846631270e16653a6234668f2a52a01a39b921490e694c0f104b58d2e14970fccb478f98d01e975a1028b9536d912de5236d2dd2fc396b77153594d4178780e5f16f718471e2111c8ce64a7d7e196fa57142d", 16);
+			BigInteger  qValue = new BigInteger("bcc02ca0ce4f0753ec16105ee5d530aa00d39f3171842ab2c334a26b5f576e0f", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("a8790aabbd5a998ff524bad048ac69cd1faff2dab048265c8d60d1471c44a9ee",16);
+				BigInteger s = new BigInteger("30df5ba32ac77170b9632559bef7d37620017756dff3fea1088b4267db0944b8",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 1, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_TEST2_1024
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-TEST2-1024"; }
+			}
+
+			private class SecureRandomImpl4 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x3DFC46F1";
+					string c =  "0xD";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+
+					byte[] d = Hex.Decode("02");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl4();
+
+			private class SecureRandomImpl5 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl5();
+
+			private class SecureRandomImpl6 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl6();
+
+			BigInteger  pValue = new BigInteger("e2c4191c4b5f222f9ac2732562f6d9b4f18e7fb67a290ea1e03d750f0b9806755fc730d975bf3faa606d05c218b35a6c3706919aab92e0c58b1de4531c8fa8e7af43c2bff016251e21b2870897f6a27ac4450bca235a5b748ad386e4a0e4dfcb09152435abcfe48bd0b126a8122c7382f285a9864615c66decddf6afd355dfb7", 16);
+			BigInteger  qValue = new BigInteger("931a58fb6f0dcdf2fe7549bc3f19f4724b56898f7f921a076601edb18c93dc75", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger              r = new BigInteger("81d69a192e9c7ac21fc07da41bd07e230ba6a94eb9f3c1fd104c7bd976733ca5",16);
+				BigInteger              s = new BigInteger("315c879c8414f35feb4deb15e7cc0278c48e6ca1596325d6959338d860b0c47a",16);
+				Gost3410ParametersGenerator  pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters           parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator         Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters  genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair  pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_AParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-AParam"; }
+			}
+
+			private class SecureRandomImpl7 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x520874F5";
+					string c =  "0xEE39ADB3";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+
+					byte[] d = Hex.Decode("02");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl7();
+
+			private class SecureRandomImpl8 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl8();
+
+			private class SecureRandomImpl9 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl9();
+
+			BigInteger  pValue = new BigInteger("b4e25efb018e3c8b87505e2a67553c5edc56c2914b7e4f89d23f03f03377e70a2903489dd60e78418d3d851edb5317c4871e40b04228c3b7902963c4b7d85d52b9aa88f2afdbeb28da8869d6df846a1d98924e925561bd69300b9ddd05d247b5922d967cbb02671881c57d10e5ef72d3e6dad4223dc82aa1f7d0294651a480df", 16);
+			BigInteger  qValue = new BigInteger("972432a437178b30bd96195b773789ab2fff15594b176dd175b63256ee5af2cf", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("64a8856628e5669d85f62cd763dd4a99bc56d33dc0e1859122855d141e9e4774",16);
+				BigInteger s = new BigInteger("319ebac97092b288d469a4b988248794f60c865bc97858d9a3135c6d1a1bf2dd",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_BParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-BParam"; }
+			}
+
+			private class SecureRandomImpl10 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x5B977CDB";
+					string c =  "0x6E9692DD";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] d = Hex.Decode("bc3cbbdb7e6f848286e19ad9a27a8e297e5b71c53dd974cdf60f937356df69cbc97a300ccc71685c553046147f11568c4fddf363d9d886438345a62c3b75963d6546adfabf31b31290d12cae65ecb8309ef66782");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl10();
+
+			private class SecureRandomImpl11 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl11();
+
+			private class SecureRandomImpl12 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl12();
+
+			BigInteger  pValue = new BigInteger("c6971fc57524b30c9018c5e621de15499736854f56a6f8aee65a7a404632b3540f09020f67f04dc2e6783b141dceffd21a703035b7d0187c6e12cb4229922bafdb2225b73e6b23a0de36e20047065aea000c1a374283d0ad8dc1981e3995f0bb8c72526041fcb98ae6163e1e71a669d8364e9c4c3188f673c5f8ee6fadb41abf", 16);
+			BigInteger  qValue = new BigInteger("b09d634c10899cd7d4c3a7657403e05810b07c61a688bab2c37f475e308b0607", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("860d82c60e9502cd00c0e9e1f6563feafec304801974d745c5e02079946f729e",16);
+				BigInteger s = new BigInteger("7ef49264ef022801aaa03033cd97915235fbab4c823ed936b0f360c22114688a",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_CParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-CParam"; }
+			}
+
+			private class SecureRandomImpl13 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x43848744";
+					string c =  "0xB50A826D";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] d = Hex.Decode("7F575E8194BC5BDF");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl13();
+
+			private class SecureRandomImpl14 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl14();
+
+			private class SecureRandomImpl15 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl15();
+
+			BigInteger  pValue = new BigInteger("9d88e6d7fe3313bd2e745c7cdd2ab9ee4af3c8899e847de74a33783ea68bc30588ba1f738c6aaf8ab350531f1854c3837cc3c860ffd7e2e106c3f63b3d8a4c034ce73942a6c3d585b599cf695ed7a3c4a93b2b947b7157bb1a1c043ab41ec8566c6145e938a611906de0d32e562494569d7e999a0dda5c879bdd91fe124df1e9", 16);
+			BigInteger  qValue = new BigInteger("fadd197abd19a1b4653eecf7eca4d6a22b1f7f893b641f901641fbb555354faf", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("4deb95a0b35e7ed7edebe9bef5a0f93739e16b7ff27fe794d989d0c13159cfbc",16);
+				BigInteger s = new BigInteger("e1d0d30345c24cfeb33efde3deee5fbbda78ddc822b719d860cd0ba1fb6bd43b",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_DParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-DParam"; }
+			}
+
+			private class SecureRandomImpl16 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x13DA8B9D";
+					string c =  "0xA0E9DE4B";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+
+					byte[] d = Hex.Decode("41ab97857f42614355d32db0b1069f109a4da283676c7c53a68185b4");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl16();
+
+			private class SecureRandomImpl17 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl17();
+
+			private class SecureRandomImpl18 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl18();
+
+			BigInteger  pValue = new BigInteger("80f102d32b0fd167d069c27a307adad2c466091904dbaa55d5b8cc7026f2f7a1919b890cb652c40e054e1e9306735b43d7b279eddf9102001cd9e1a831fe8a163eed89ab07cf2abe8242ac9dedddbf98d62cddd1ea4f5f15d3a42a6677bdd293b24260c0f27c0f1d15948614d567b66fa902baa11a69ae3bceadbb83e399c9b5", 16);
+			BigInteger  qValue = new BigInteger("f0f544c418aac234f683f033511b65c21651a6078bda2d69bb9f732867502149", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger              r = new BigInteger("712592d285b792e33b8a9a11e8e6c4f512ddf0042972bbfd1abb0a93e8fc6f54",16);
+				BigInteger              s = new BigInteger("2cf26758321258b130d5612111339f09ceb8668241f3482e38baa56529963f07",16);
+				Gost3410ParametersGenerator  pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_AExParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-AExParam"; }
+			}
+
+			private class SecureRandomImpl19 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0xD05E9F14";
+					string c =  "0x46304C5F";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] d = Hex.Decode("35ab875399cda33c146ca629660e5a5e5c07714ca326db032dd6751995cdb90a612b9228932d8302704ec24a5def7739c5813d83");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl19();
+
+			private class SecureRandomImpl20 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl20();
+
+			private class SecureRandomImpl21 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl21();
+
+			BigInteger  pValue = new BigInteger("ca3b3f2eee9fd46317d49595a9e7518e6c63d8f4eb4d22d10d28af0b8839f079f8289e603b03530784b9bb5a1e76859e4850c670c7b71c0df84ca3e0d6c177fe9f78a9d8433230a883cd82a2b2b5c7a3306980278570cdb79bf01074a69c9623348824b0c53791d53c6a78cab69e1cfb28368611a397f50f541e16db348dbe5f", 16);
+			BigInteger  qValue = new BigInteger("cae4d85f80c147704b0ca48e85fb00a9057aa4acc44668e17f1996d7152690d9", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("90892707282f433398488f19d31ac48523a8e2ded68944e0da91c6895ee7045e",16);
+				BigInteger s = new BigInteger("3be4620ee88f1ee8f9dd63c7d145b7e554839feeca125049118262ea4651e9de",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_BExParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-BExParam"; }
+			}
+
+			private class SecureRandomImpl22 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x7A007804";
+					string c =  "0xD31A4FF7";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] d = Hex.Decode("7ec123d161477762838c2bea9dbdf33074af6d41d108a066a1e7a07ab3048de2");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl22();
+
+			private class SecureRandomImpl23 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl23();
+
+			private class SecureRandomImpl24 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl24();
+
+			BigInteger  pValue = new BigInteger("9286dbda91eccfc3060aa5598318e2a639f5ba90a4ca656157b2673fb191cd0589ee05f4cef1bd13508408271458c30851ce7a4ef534742bfb11f4743c8f787b11193ba304c0e6bca25701bf88af1cb9b8fd4711d89f88e32b37d95316541bf1e5dbb4989b3df13659b88c0f97a3c1087b9f2d5317d557dcd4afc6d0a754e279", 16);
+			BigInteger  qValue = new BigInteger("c966e9b3b8b7cdd82ff0f83af87036c38f42238ec50a876cd390e43d67b6013f", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("8f79a582513df84dc247bcb624340cc0e5a34c4324a20ce7fe3ab8ff38a9db71",16);
+				BigInteger s = new BigInteger("7508d22fd6cbb45efd438cb875e43f137247088d0f54b29a7c91f68a65b5fa85",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		private class Gost3410_CExParam
+			: ITest
+		{
+			public string Name
+			{
+				get { return "Gost3410-CExParam"; }
+			}
+
+			private class SecureRandomImpl25 : SecureRandom
+			{
+				bool firstLong = true;
+
+				public override long NextLong()
+				{
+					string x0 = "0x162AB910";
+					string c =  "0x93F828D3";
+
+					if (firstLong)
+					{
+						firstLong = false;
+						return NumberParsing.DecodeLongFromHex(x0);
+					}
+					return NumberParsing.DecodeLongFromHex(c);
+				}
+
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] d = Hex.Decode("ca82cce78a738bc46f103d53b9bf809745ec845e4f6da462606c51f60ecf302e31204b81");
+
+					Array.Copy(d, 0, bytes, bytes.Length-d.Length, d.Length);
+				}
+			};
+			SecureRandom init_random = new SecureRandomImpl25();
+
+			private class SecureRandomImpl26 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] k = Hex.Decode("90F3A564439242F5186EBB224C8E223811B7105C64E4F5390807E6362DF4C72A");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - k.Length); i += k.Length)
+					{
+						Array.Copy(k, 0, bytes, i, k.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(k, 0, bytes, i - k.Length, bytes.Length - (i - k.Length));
+					}
+					else
+					{
+						Array.Copy(k, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom random = new SecureRandomImpl26();
+
+			private class SecureRandomImpl27 : SecureRandom
+			{
+				public override void NextBytes(byte[] bytes)
+				{
+					byte[] x = Hex.Decode("3036314538303830343630454235324435324234314132373832433138443046");
+
+					int i;
+
+					for (i = 0; i < (bytes.Length - x.Length); i += x.Length)
+					{
+						Array.Copy(x, 0, bytes, i, x.Length);
+					}
+
+					if (i > bytes.Length)
+					{
+						Array.Copy(x, 0, bytes, i - x.Length, bytes.Length - (i - x.Length));
+					}
+					else
+					{
+						Array.Copy(x, 0, bytes, i, bytes.Length - i);
+					}
+				}
+			};
+			SecureRandom keyRandom = new SecureRandomImpl27();
+
+			BigInteger  pValue = new BigInteger("b194036ace14139d36d64295ae6c50fc4b7d65d8b340711366ca93f383653908ee637be428051d86612670ad7b402c09b820fa77d9da29c8111a8496da6c261a53ed252e4d8a69a20376e6addb3bdcd331749a491a184b8fda6d84c31cf05f9119b5ed35246ea4562d85928ba1136a8d0e5a7e5c764ba8902029a1336c631a1d", 16);
+			BigInteger  qValue = new BigInteger("96120477df0f3896628e6f4a88d83c93204c210ff262bccb7dae450355125259", 16);
+
+			public ITestResult Perform()
+			{
+				BigInteger r = new BigInteger("169fdb2dc09f690b71332432bfec806042e258fa9a21dafe73c6abfbc71407d9",16);
+				BigInteger s = new BigInteger("9002551808ae40d19f6f31fb67e4563101243cf07cffd5f2f8ff4c537b0c9866",16);
+				Gost3410ParametersGenerator pGen = new Gost3410ParametersGenerator();
+
+				pGen.Init(1024, 2, init_random);
+
+				Gost3410Parameters parameters = pGen.GenerateParameters();
+
+				if (!pValue.Equals(parameters.P) || !qValue.Equals(parameters.Q))
+				{
+					return new SimpleTestResult(false, Name + ": p or q wrong");
+				}
+
+				Gost3410KeyPairGenerator Gost3410KeyGen = new Gost3410KeyPairGenerator();
+				Gost3410KeyGenerationParameters genParam = new Gost3410KeyGenerationParameters(keyRandom, parameters);
+
+				Gost3410KeyGen.Init(genParam);
+
+				AsymmetricCipherKeyPair pair = Gost3410KeyGen.GenerateKeyPair();
+
+				ParametersWithRandom param = new ParametersWithRandom(pair.Private, random);
+
+				Gost3410Signer Gost3410 = new Gost3410Signer();
+
+				Gost3410.Init(true, param);
+
+				BigInteger[] sig = Gost3410.GenerateSignature(hashmessage);
+
+				if (!r.Equals(sig[0]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": r component wrong." + SimpleTest.NewLine
+						+ " expecting: " + r.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[0].ToString(16));
+				}
+
+				if (!s.Equals(sig[1]))
+				{
+					return new SimpleTestResult(false, Name
+						+ ": s component wrong." + SimpleTest.NewLine
+						+ " expecting: " + s.ToString(16) + SimpleTest.NewLine
+						+ " got      : " + sig[1].ToString(16));
+				}
+
+				Gost3410.Init(false, pair.Public);
+
+				if (Gost3410.VerifySignature(hashmessage, sig[0], sig[1]))
+				{
+					return new SimpleTestResult(true, Name + ": Okay");
+				}
+				else
+				{
+					return new SimpleTestResult(false, Name + ": verification fails");
+				}
+			}
+		}
+
+		ITest[] tests =
+		{
+			new Gost3410_TEST1_512(),
+			new Gost3410_TEST2_512(),
+//	        new Gost3410_TEST1_1024(),
+//	        new Gost3410_TEST2_1024(),
+//	        new Gost3410_AParam(),
+//	        new Gost3410_BParam(),
+//	        new Gost3410_CParam(),
+//	        new Gost3410_DParam(),
+//	        new Gost3410_AExParam(),
+//	        new Gost3410_BExParam(),
+//	        new Gost3410_CExParam()
+		};
+
+		public string Name
+		{
+			get { return "Gost3410"; }
+		}
+
+		public ITestResult Perform()
+		{
+			for (int i = 0; i != tests.Length; i++)
+			{
+				ITestResult result = tests[i].Perform();
+
+				if (!result.IsSuccessful())
+				{
+					return result;
+				}
+			}
+
+			return new SimpleTestResult(true, "Gost3410: Okay");
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new Gost3410Test();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3411DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3411DigestTest.cs
new file mode 100644
index 0000000..1826b28
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GOST3411DigestTest.cs
@@ -0,0 +1,79 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class Gost3411DigestTest
+		: DigestTest
+	{
+		private static readonly string[] messages =
+		{
+			"",
+			"This is message, length=32 bytes",
+			"Suppose the original message has length = 50 bytes",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+		};
+
+		//  If S-box = D-A (see: digest/Gost3411Digest.java; function: E(byte[] in, byte[] key); string: CipherParameters  param = new Gost28147Parameters(key,"D-A");)
+		private static readonly string[] digests =
+		{
+			"981e5f3ca30c841487830f84fb433e13ac1101569b9c13584ac483234cd656c0",
+			"2cefc2f7b7bdc514e18ea57fa74ff357e7fa17d652c75f69cb1be7893ede48eb",
+			"c3730c5cbccacf915ac292676f21e8bd4ef75331d9405e5f1a61dc3130a65011",
+			"73b70a39497de53a6e08c67b6d4db853540f03e9389299d9b0156ef7e85d0f61"
+		};
+
+		//  If S-box = D-Test (see: digest/GOST3411Digest.cs; function:E(byte[] in, byte[] key); string: ICipherParameters p = new Gost28147Parameters(key, "D-Test");)
+//		private static readonly string[] digests =
+//		{
+//			"ce85b99cc46752fffee35cab9a7b0278abb4c2d2055cff685af4912c49490f8d",
+//			"b1c466d37519b82e8319819ff32595e047a28cb6f83eff1c6916a815a637fffa",
+//			"471aba57a60a770d3a76130635c1fbea4ef14de51f78b4ae57dd893b62f55208",
+//			"95c1af627c356496d80274330b2cff6a10c67b5f597087202f94d06d2338cf8e"
+//		};
+
+		// 1 million 'a'
+		static private string  million_a_digest = "8693287aa62f9478f7cb312ec0866b6c4e4a0f11160441e8f4ffcd2715dd554f";
+
+		public Gost3411DigestTest()
+			: base(new Gost3411Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new Gost3411Digest((Gost3411Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new Gost3411DigestTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/GcmReorderTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/GcmReorderTest.cs
new file mode 100644
index 0000000..54d17f4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/GcmReorderTest.cs
@@ -0,0 +1,362 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Modes.Gcm;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class GcmReorderTest
+	{
+		private static readonly byte[] H;
+		private static readonly SecureRandom random = new SecureRandom(); 
+		private static readonly IGcmMultiplier mul = new Tables64kGcmMultiplier();
+		private static readonly IGcmExponentiator exp = new Tables1kGcmExponentiator();
+		private static readonly byte[] Empty = new byte[0];
+
+		static GcmReorderTest()
+		{
+			H = new byte[16];
+			random.NextBytes(H);
+			mul.Init(Arrays.Clone(H));
+			exp.Init(Arrays.Clone(H));
+		}
+
+		[Test]
+		public void TestCombine()
+		{
+			for (int count = 0; count < 10; ++count)
+			{
+				byte[] A = randomBytes(1000);
+				byte[] C = randomBytes(1000);
+
+				byte[] ghashA_ = GHASH(A, Empty);
+				byte[] ghash_C = GHASH(Empty, C);
+				byte[] ghashAC = GHASH(A, C);
+
+				byte[] ghashCombine = combine_GHASH(ghashA_, (long)A.Length * 8, ghash_C, (long)C.Length * 8);
+
+				Assert.IsTrue(Arrays.AreEqual(ghashAC, ghashCombine));
+			}
+		}
+
+		[Test]
+		public void TestConcatAuth()
+		{
+			for (int count = 0; count < 10; ++count)
+			{
+				byte[] P = randomBlocks(100);
+				byte[] A = randomBytes(1000);
+				byte[] PA = concatArrays(P, A);
+
+				byte[] ghashP_ = GHASH(P, Empty);
+				byte[] ghashA_ = GHASH(A, Empty);
+				byte[] ghashPA_val = GHASH(PA, Empty);
+				byte[] ghashConcat = concatAuth_GHASH(ghashP_, (long)P.Length * 8, ghashA_, (long)A.Length * 8);
+
+				Assert.IsTrue(Arrays.AreEqual(ghashPA_val, ghashConcat));
+			}
+		}
+
+		[Test]
+		public void TestConcatCrypt()
+		{
+			for (int count = 0; count < 10; ++count)
+			{
+				byte[] P = randomBlocks(100);
+				byte[] A = randomBytes(1000);
+				byte[] PA = concatArrays(P, A);
+
+				byte[] ghash_P = GHASH(Empty, P);
+				byte[] ghash_A = GHASH(Empty, A);
+				byte[] ghash_PA = GHASH(Empty, PA);
+				byte[] ghashConcat = concatCrypt_GHASH(ghash_P, (long)P.Length * 8, ghash_A, (long)A.Length * 8);
+
+				Assert.IsTrue(Arrays.AreEqual(ghash_PA, ghashConcat));
+			}
+		}
+
+		[Test]
+		public void TestExp()
+		{
+			{
+				byte[] buf1 = new byte[16];
+				buf1[0] = 0x80;
+
+				byte[] buf2 = new byte[16];
+
+				for (int pow = 0; pow != 100; ++pow)
+				{
+					exp.ExponentiateX(pow, buf2);
+
+					Assert.IsTrue(Arrays.AreEqual(buf1, buf2));
+
+					mul.MultiplyH(buf1);
+				}
+			}
+
+			long[] testPow = new long[]{ 10, 1, 8, 17, 24, 13, 2, 13, 2, 3 };
+			byte[][] testData = new byte[][]{
+				Hex.Decode("9185848a877bd87ba071e281f476e8e7"),
+				Hex.Decode("697ce3052137d80745d524474fb6b290"),
+				Hex.Decode("2696fc47198bb23b11296e4f88720a17"),
+				Hex.Decode("01f2f0ead011a4ae0cf3572f1b76dd8e"),
+				Hex.Decode("a53060694a044e4b7fa1e661c5a7bb6b"),
+				Hex.Decode("39c0392e8b6b0e04a7565c85394c2c4c"),
+				Hex.Decode("519c362d502e07f2d8b7597a359a5214"),
+				Hex.Decode("5a527a393675705e19b2117f67695af4"),
+				Hex.Decode("27fc0901d1d332a53ba4d4386c2109d2"),
+				Hex.Decode("93ca9b57174aabedf8220e83366d7df6"),
+			};
+
+			for (int i = 0; i != 10; ++i)
+			{
+				long pow = testPow[i];
+				byte[] data = Arrays.Clone(testData[i]);
+
+				byte[] expected = Arrays.Clone(data);
+				for (int j = 0; j < pow; ++j)
+				{
+					mul.MultiplyH(expected);
+				}
+
+				byte[] H_a = new byte[16];
+				exp.ExponentiateX(pow, H_a);
+				byte[] actual = multiply(data, H_a);
+
+				Assert.IsTrue(Arrays.AreEqual(expected, actual));
+			}
+		}
+
+		[Test]
+		public void TestMultiply()
+		{
+			byte[] expected = Arrays.Clone(H);
+			mul.MultiplyH(expected);
+
+			Assert.IsTrue(Arrays.AreEqual(expected, multiply(H, H)));
+
+			for (int count = 0; count < 10; ++count)
+			{
+				byte[] a = new byte[16];
+				random.NextBytes(a);
+
+				byte[] b = new byte[16];
+				random.NextBytes(b);
+
+				expected = Arrays.Clone(a);
+				mul.MultiplyH(expected);
+				Assert.IsTrue(Arrays.AreEqual(expected, multiply(a, H)));
+				Assert.IsTrue(Arrays.AreEqual(expected, multiply(H, a)));
+				
+				expected = Arrays.Clone(b);
+				mul.MultiplyH(expected);
+				Assert.IsTrue(Arrays.AreEqual(expected, multiply(b, H)));
+				Assert.IsTrue(Arrays.AreEqual(expected, multiply(H, b)));
+				
+				Assert.IsTrue(Arrays.AreEqual(multiply(a, b), multiply(b, a)));
+			}
+		}
+
+		private byte[] randomBlocks(int upper)
+		{
+			byte[] bs = new byte[16 * random.Next(upper)];
+			random.NextBytes(bs);
+			return bs;
+		}
+
+		private byte[] randomBytes(int upper)
+		{
+			byte[] bs = new byte[random.Next(upper)];
+			random.NextBytes(bs);
+			return bs;
+		}
+
+		private byte[] concatArrays(byte[] a, byte[] b)
+		{
+			byte[] ab = new byte[a.Length + b.Length];
+			Array.Copy(a, 0, ab, 0, a.Length);
+			Array.Copy(b, 0, ab, a.Length, b.Length);
+			return ab;
+		}
+
+		private byte[] combine_GHASH(byte[] ghashA_, long bitlenA, byte[] ghash_C, long bitlenC)
+		{
+			// Note: bitlenA must be aligned to the block size
+
+			long c = (bitlenC + 127) >> 7;
+
+			byte[] H_c = new byte[16];
+			exp.ExponentiateX(c, H_c);
+
+			byte[] tmp1 = lengthBlock(bitlenA, 0);
+			mul.MultiplyH(tmp1);
+
+			byte[] ghashAC = Arrays.Clone(ghashA_);
+			xor(ghashAC, tmp1);
+			ghashAC = multiply(ghashAC, H_c);
+			// No need to touch the len(C) part (second 8 bytes)
+			xor(ghashAC, tmp1);
+			xor(ghashAC, ghash_C);
+
+			return ghashAC;
+		}
+
+		private byte[] concatAuth_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
+		{
+			// Note: bitlenP must be aligned to the block size
+
+			long a = (bitlenA + 127) >> 7;
+
+			byte[] tmp1 = lengthBlock(bitlenP, 0);
+			mul.MultiplyH(tmp1);
+
+			byte[] tmp2 = lengthBlock(bitlenA ^ (bitlenP + bitlenA), 0);
+			mul.MultiplyH(tmp2);
+
+			byte[] H_a = new byte[16];
+			exp.ExponentiateX(a, H_a);
+
+			byte[] ghashC = Arrays.Clone(ghashP);
+			xor(ghashC, tmp1);
+			ghashC = multiply(ghashC, H_a);
+			xor(ghashC, tmp2);
+			xor(ghashC, ghashA);
+			return ghashC;
+		}
+
+		private byte[] concatCrypt_GHASH(byte[] ghashP, long bitlenP, byte[] ghashA, long bitlenA)
+		{
+			// Note: bitlenP must be aligned to the block size
+			
+			long a = (bitlenA + 127) >> 7;
+
+			byte[] tmp1 = lengthBlock(0, bitlenP);
+			mul.MultiplyH(tmp1);
+
+			byte[] tmp2 = lengthBlock(0, bitlenA ^ (bitlenP + bitlenA));
+			mul.MultiplyH(tmp2);
+
+			byte[] H_a = new byte[16];
+			exp.ExponentiateX(a, H_a);
+
+			byte[] ghashC = Arrays.Clone(ghashP);
+			xor(ghashC, tmp1);
+			ghashC = multiply(ghashC, H_a);
+			xor(ghashC, tmp2);
+			xor(ghashC, ghashA);
+			return ghashC;
+		}
+
+		private byte[] GHASH(byte[] A, byte[] C)
+		{
+			byte[] X = new byte[16];
+
+			{
+				for (int pos = 0; pos < A.Length; pos += 16)
+				{
+					byte[] tmp = new byte[16];
+					int num = System.Math.Min(A.Length - pos, 16);
+					Array.Copy(A, pos, tmp, 0, num);
+					xor(X, tmp);
+					mul.MultiplyH(X);
+				}
+			}
+
+			{
+				for (int pos = 0; pos < C.Length; pos += 16)
+				{
+					byte[] tmp = new byte[16];
+					int num = System.Math.Min(C.Length - pos, 16);
+					Array.Copy(C, pos, tmp, 0, num);
+					xor(X, tmp);
+					mul.MultiplyH(X);
+				}
+			}
+
+			{
+				xor(X, lengthBlock((long)A.Length * 8, (long)C.Length * 8));
+				mul.MultiplyH(X);
+			}
+
+			return X;
+		}
+
+		private static byte[] lengthBlock(long bitlenA, long bitlenC)
+		{
+			byte[] tmp = new byte[16];
+			UInt64_To_BE((ulong)bitlenA, tmp, 0);
+			UInt64_To_BE((ulong)bitlenC, tmp, 8);
+			return tmp;
+		}
+
+		private static void xor(byte[] block, byte[] val)
+		{
+			for (int i = 15; i >= 0; --i)
+			{
+				block[i] ^= val[i];
+			}
+		}
+
+		private static void UInt64_To_BE(ulong n, byte[] bs, int off)
+		{
+			UInt32_To_BE((uint)(n >> 32), bs, off);
+			UInt32_To_BE((uint)(n), bs, off + 4);
+		}
+
+		private static void UInt32_To_BE(uint n, byte[] bs, int off)
+		{
+			bs[  off] = (byte)(n >> 24);
+			bs[++off] = (byte)(n >> 16);
+			bs[++off] = (byte)(n >>  8);
+			bs[++off] = (byte)(n      );
+		}
+
+		private static byte[] multiply(byte[] a, byte[] b)
+		{
+			byte[] c = new byte[16];
+			byte[] tmp = Arrays.Clone(b);
+
+			for (int i = 0; i < 16; ++i)
+			{
+				byte bits = a[i];
+				for (int j = 7; j >= 0; --j)
+				{
+					if ((bits & (1 << j)) != 0)
+					{
+						xor(c, tmp);
+					}
+
+					bool lsb = (tmp[15] & 1) != 0;
+					shiftRight(tmp);
+					if (lsb)
+					{
+						// R = new byte[]{ 0xe1, ... };
+						//GcmUtilities.Xor(tmp, R);
+						tmp[0] ^= (byte)0xe1;
+					}
+				}
+			}
+
+			return c;
+		}
+
+		private static void shiftRight(byte[] block)
+		{
+			int i = 0;
+			byte bit = 0;
+			for (;;)
+			{
+				byte b = block[i];
+				block[i] = (byte)((b >> 1) | bit);
+				if (++i == 16) break;
+				bit = (byte)(b << 7);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyTest.cs
new file mode 100644
index 0000000..0904bc9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyTest.cs
@@ -0,0 +1,192 @@
+using System;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * HC-128 and HC-256 Tests. Based on the test vectors in the official reference
+	 * papers, respectively:
+	 * <pre>
+	 * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+	 * http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+	 * </pre>
+	 * See HCFamilyVecTest for a more exhaustive test based on the ecrypt vectors.
+	 */
+	public class HCFamilyTest
+		: SimpleTest
+	{
+		private static readonly byte[] MSG = new byte[64];
+
+		private static readonly string[][] HC128_VerifiedTest = new string[][]
+		{
+			new string[]{
+				"Set 2, vector#  0",
+				"00000000000000000000000000000000",
+				"00000000000000000000000000000000",
+				"82001573A003FD3B7FD72FFB0EAF63AA" +
+				"C62F12DEB629DCA72785A66268EC758B" +
+				"1EDB36900560898178E0AD009ABF1F49" +
+				"1330DC1C246E3D6CB264F6900271D59C"
+			},
+			new string[]{
+				"Set 6, vector#  0",
+				"0053A6F94C9FF24598EB3E91E4378ADD",
+				"0D74DB42A91077DE45AC137AE148AF16",
+				"2E1ED12A8551C05AF41FF39D8F9DF933" +
+				"122B5235D48FC2A6F20037E69BDBBCE8" +
+				"05782EFC16C455A4B3FF06142317535E" +
+				"F876104C32445138CB26EBC2F88A684C"
+			},
+			new string[]{
+				"Set 6, vector#  1",
+				"0558ABFE51A4F74A9DF04396E93C8FE2",
+				"167DE44BB21980E74EB51C83EA51B81F",
+				"4F864BF3C96D0363B1903F0739189138" +
+				"F6ED2BC0AF583FEEA0CEA66BA7E06E63" +
+				"FB28BF8B3CA0031D24ABB511C57DD17B" +
+				"FC2861C32400072CB680DF2E58A5CECC"
+			},
+			new string[]{
+				"Set 6, vector#  2",
+				"0A5DB00356A9FC4FA2F5489BEE4194E7",
+				"1F86ED54BB2289F057BE258CF35AC128",
+				"82168AB0023B79AAF1E6B4D823855E14" +
+				"A7084378036A951B1CFEF35173875ED8" +
+				"6CB66AB8410491A08582BE40080C3102" +
+				"193BA567F9E95D096C3CC60927DD7901"
+			},
+			new string[]{
+				"Set 6, vector#  3",
+				"0F62B5085BAE0154A7FA4DA0F34699EC",
+				"288FF65DC42B92F960C72E95FC63CA31",
+				"1CD8AEDDFE52E217E835D0B7E84E2922" +
+				"D04B1ADBCA53C4522B1AA604C42856A9" +
+				"0AF83E2614BCE65C0AECABDD8975B557" +
+				"00D6A26D52FFF0888DA38F1DE20B77B7"
+			}
+		};
+
+		private static readonly string[][] HC256_VerifiedTest = new string[][]
+		{
+			new string[]{
+				"Set 2, vector#  0",
+				"00000000000000000000000000000000",
+				"00000000000000000000000000000000",
+				"5B078985D8F6F30D42C5C02FA6B67951" +
+				"53F06534801F89F24E74248B720B4818" +
+				"CD9227ECEBCF4DBF8DBF6977E4AE14FA" +
+				"E8504C7BC8A9F3EA6C0106F5327E6981"
+			},
+			new string[]{
+				"Set 2, vector#  9",
+				"09090909090909090909090909090909",
+				"00000000000000000000000000000000",
+				"F5C2926651AEED9AF1A9C2F04C03D081" +
+				"2145B56AEA46EB283A25A4C9E3D8BEB4" +
+				"821B418F06F2B9DCDF1A85AB8C02CD14" +
+				"62E1BBCAEC9AB0E99AA6AFF918BA627C"
+			},
+			new string[]{
+				"Set 2, vector#135",
+				"87878787878787878787878787878787",
+				"00000000000000000000000000000000",
+				"CEC0C3852E3B98233EBCB975C10B1191" +
+				"3C69F2275EB97A1402EDF16C6FBE19BE" +
+				"79D65360445BCB63676E6553B609A065" +
+				"0155C3B22DD1975AC0F3F65063A2E16E"
+			},
+			new string[]{
+				"Set 6, vector#  0",
+				"0053A6F94C9FF24598EB3E91E4378ADD" +
+				"3083D6297CCF2275C81B6EC11467BA0D",
+				"0D74DB42A91077DE45AC137AE148AF16" +
+				"7DE44BB21980E74EB51C83EA51B81F86",
+				"23D9E70A45EB0127884D66D9F6F23C01" +
+				"D1F88AFD629270127247256C1FFF91E9" +
+				"1A797BD98ADD23AE15BEE6EEA3CEFDBF" +
+				"A3ED6D22D9C4F459DB10C40CDF4F4DFF"
+			},
+			new string[]{
+				"Set 6, vector#  1",
+				"0558ABFE51A4F74A9DF04396E93C8FE2" +
+				"3588DB2E81D4277ACD2073C6196CBF12",
+				"167DE44BB21980E74EB51C83EA51B81F" +
+				"86ED54BB2289F057BE258CF35AC1288F",
+				"C44B5262F2EAD9C018213127686DB742" +
+				"A72D3F2D61D18F0F4E7DE5B4F7ADABE0" +
+				"7E0C82033B139F02BAACB4E2F2D0BE30" +
+				"110C3A8A2B621523756692877C905DD0"
+			},
+			new string[]{
+				"Set 6, vector#  2",
+				"0A5DB00356A9FC4FA2F5489BEE4194E7" +
+				"3A8DE03386D92C7FD22578CB1E71C417",
+				"1F86ED54BB2289F057BE258CF35AC128" +
+				"8FF65DC42B92F960C72E95FC63CA3198",
+				"9D13AA06122F4F03AE60D507701F1ED0" +
+				"63D7530FF35EE76CAEDCBFB01D8A239E" +
+				"FA4A44B272DE9B4092E2AD56E87C3A60" +
+				"89F5A074D1F6E5B8FC6FABEE0C936F06"
+			},
+			new string[]{
+				"Set 6, vector#  3",
+				"0F62B5085BAE0154A7FA4DA0F34699EC" +
+				"3F92E5388BDE3184D72A7DD02376C91C",
+				"288FF65DC42B92F960C72E95FC63CA31" +
+				"98FF66CD349B0269D0379E056CD33AA1",
+				"C8632038DA61679C4685288B37D3E232" +
+				"7BC2D28C266B041FE0CA0D3CFEED8FD5" +
+				"753259BAB757168F85EA96ADABD823CA" +
+				"4684E918423E091565713FEDDE2CCFE0"
+			}
+		};
+
+		public override string Name
+		{
+			get { return "HC-128 and HC-256"; }
+		}
+
+		public override void PerformTest()
+		{
+			IStreamCipher hc = new HC256Engine();
+
+			for (int i = 0; i != HC256_VerifiedTest.Length; i++)
+			{
+				string[] test = HC256_VerifiedTest[i];
+				HCTest(hc, "HC-256 - " + test[0], Hex.Decode(test[1]), Hex.Decode(test[2]), Hex.Decode(test[3]));
+			}
+
+			hc = new HC128Engine();
+
+			for (int i = 0; i != HC128_VerifiedTest.Length; i++)
+			{
+				string[] test = HC128_VerifiedTest[i];
+				HCTest(hc, "HC-128 - " + test[0], Hex.Decode(test[1]), Hex.Decode(test[2]), Hex.Decode(test[3]));
+			}
+		}
+
+		private void HCTest(IStreamCipher hc, string test, byte[] key, byte[] IV, byte[] expected)
+		{
+			KeyParameter kp = new KeyParameter(key);
+			ParametersWithIV ivp = new ParametersWithIV(kp, IV);
+
+			hc.Init(true, ivp);
+			for (int i = 0; i < 64; i++)
+			{
+				if (hc.ReturnByte(MSG[i]) != expected[i])
+				{
+					Fail(test + " failure at byte " + i);
+				}
+			}
+		}
+
+		public static void Main(string[] args)
+		{
+			RunTest(new HCFamilyTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyVecTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyVecTest.cs
new file mode 100644
index 0000000..00b0ee7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/HCFamilyVecTest.cs
@@ -0,0 +1,184 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* HC-128 and HC-256 Tests. Based on the test vectors in the official reference
+	* papers, respectively:
+	* 
+	* http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc128_p3.pdf
+	* http://www.ecrypt.eu.org/stream/p3ciphers/hc/hc256_p3.pdf
+	*/
+	[TestFixture]
+	public class HCFamilyVecTest
+		: SimpleTest
+	{
+		private class PeekableLineReader
+			: StreamReader
+		{
+			public PeekableLineReader(Stream s)
+				: base(s)
+			{
+				peek = base.ReadLine();
+			}
+
+			public string PeekLine()
+			{
+				return peek;
+			}
+
+			public override string ReadLine()
+			{
+				string tmp = peek;
+				peek = base.ReadLine();
+				return tmp;
+			}
+
+			private string peek; 
+	    }
+
+		public override string Name
+		{
+			get { return "HC-128 and HC-256"; }
+		}
+
+		public override void PerformTest()
+		{
+			RunTests(new HC128Engine(), "hc128/ecrypt_HC-128.txt");
+			RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_128K_128IV.txt");
+			RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_256K_128IV.txt");
+			RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_128K_256IV.txt");
+			RunTests(new HC256Engine(), "hc256/ecrypt_HC-256_256K_256IV.txt");
+		}
+
+		private void RunTests(IStreamCipher hc, string fileName)
+		{
+			Stream resource = SimpleTest.GetTestDataAsStream(
+				"hc256." + fileName.Replace('/', '.'));
+			PeekableLineReader r = new PeekableLineReader(resource);
+			RunAllVectors(hc, fileName, r);
+		}
+
+		private void RunAllVectors(IStreamCipher hc, string fileName, PeekableLineReader r)
+		{
+			for (;;)
+			{
+				string line = r.ReadLine();
+				if (line == null)
+					break;
+
+				line = line.Trim();
+
+				if (line.StartsWith("Set "))
+				{
+					RunVector(hc, fileName, r, line.Replace(":", ""));
+				}
+			}
+		}
+
+		private void RunVector(IStreamCipher hc, string fileName, PeekableLineReader r, string vectorName)
+		{
+//			Console.WriteLine(fileName + " => " + vectorName);
+			string hexKey = ReadBlock(r);
+			string hexIV = ReadBlock(r);
+
+			ICipherParameters cp = new KeyParameter(Hex.Decode(hexKey));
+			cp = new ParametersWithIV(cp, Hex.Decode(hexIV));
+			hc.Init(true, cp);
+
+			byte[] input = new byte[64];
+			byte[] output = new byte[64];
+			byte[] digest = new byte[64];
+			int pos = 0;
+
+			for (;;)
+			{
+				string line1 = r.PeekLine().Trim();
+				int equalsPos = line1.IndexOf('=');
+				string lead = line1.Substring(0, equalsPos - 1);
+
+				string hexData = ReadBlock(r);
+				byte[] data = Hex.Decode(hexData);
+
+				if (lead.Equals("xor-digest"))
+				{
+					if (!Arrays.AreEqual(data, digest))
+					{
+						Fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
+//						Console.WriteLine(fileName + " => " + vectorName + " failed at " + lead); return;
+					}
+					break;
+				}
+
+				int posA = lead.IndexOf('[');
+				int posB = lead.IndexOf("..");
+				int posC = lead.IndexOf(']');
+				int start = Int32.Parse(lead.Substring(posA + 1, posB - (posA + 1)));
+				int end = Int32.Parse(lead.Substring(posB + 2, posC - (posB + 2)));
+
+				if (start % 64 != 0 || (end - start != 63))
+					throw new InvalidOperationException(vectorName + ": " + lead + " not on 64 byte boundaries");
+
+				while (pos < end)
+				{
+					hc.ProcessBytes(input, 0, input.Length, output, 0);
+					xor(digest, output);
+					pos += 64;
+				}
+
+				if (!Arrays.AreEqual(data, output))
+				{
+					Fail("Failed in " + fileName + " for test vector: " + vectorName + " at " + lead);
+//					Console.WriteLine(fileName + " => " + vectorName + " failed at " + lead); return;
+				}
+			}
+		}
+
+		private static string ReadBlock(PeekableLineReader r)
+		{
+			string first = r.ReadLine().Trim();
+			string result = first.Substring(first.LastIndexOf(' ') + 1);
+
+			for (;;)
+			{
+				string peek = r.PeekLine().Trim();
+				if (peek.Length < 1 || peek.IndexOf('=') >= 0)
+					break;
+				result += r.ReadLine().Trim();
+			}
+
+			return result;
+		}
+
+		private static void xor(byte[] digest, byte[] block)
+		{
+			for (int i = 0; i < digest.Length; ++i)
+			{
+				digest[i] ^= block[i];
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new HCFamilyVecTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/IDEATest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/IDEATest.cs
new file mode 100644
index 0000000..fbbd1ae
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/IDEATest.cs
@@ -0,0 +1,53 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class IdeaTest
+        : CipherTest
+    {
+        public override string Name
+        {
+            get { return "IDEA"; }
+        }
+
+        internal static SimpleTest[] tests = new SimpleTest[]
+        {
+            new BlockCipherVectorTest(0, new IdeaEngine(),
+                new KeyParameter(Hex.Decode("00112233445566778899AABBCCDDEEFF")),
+                "000102030405060708090a0b0c0d0e0f",
+                "ed732271a7b39f475b4b2b6719f194bf"),
+            new BlockCipherVectorTest(0, new IdeaEngine(),
+                new KeyParameter(Hex.Decode("00112233445566778899AABBCCDDEEFF")),
+                "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+                "b8bc6ed5c899265d2bcfad1fc6d4287d")
+        };
+
+        public IdeaTest()
+            : base(tests, new IdeaEngine(), new KeyParameter(new byte[32]))
+        {
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new IdeaTest();
+            ITestResult result = test.Perform();
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ISAACTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ISAACTest.cs
new file mode 100644
index 0000000..1782bbc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ISAACTest.cs
@@ -0,0 +1,196 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* ISAAC Test - see http://www.burtleburtle.net/bob/rand/isaacafa.html
+	*/
+	[TestFixture]
+	public class IsaacTest
+		: SimpleTest
+	{
+		byte[] outBase = Hex.Decode(
+			"f650e4c8e448e96d98db2fb4f5fad54f433f1afbedec154ad837048746ca4f9a" +
+			"5de3743e88381097f1d444eb823cedb66a83e1e04a5f6355c744243325890e2e" +
+			"7452e31957161df638a824f3002ed71329f5544951c08d83d78cb99ea0cc74f3" +
+			"8f651659cbc8b7c2f5f71c6912ad6419e5792e1b860536b809b3ce98d45d6d81" +
+			"f3b2612917e38f8529cf72ce349947b0c998f9ffb5e13dae32ae2a2bf7cf814c" +
+			"8ebfa303cf22e0640b923200eca4d58aef53cec4d0f7b37d9c411a2affdf8a80" +
+			"b40e27bcb4d2f97644b89b08f37c71d51a70e7e90bdb9c3060dc5207b3c3f24b" +
+			"d7386806229749b54e232cd091dabc65a70e11018b87437e5781414fcdbc62e2" +
+			"8107c9ff69d2e4ae3b18e752b143b6886f4e077295138769943c3c74afc17a97" +
+			"0fd439636a529b0bd8c58a6aa8bcc22d2db35dfea7a2f4026cb167db538e1f4e" +
+			"7275e2771d3b8e97ecc5dc9115e3a5b90369661430ab93ecac9fe69d7bc76811" +
+			"60eda8da28833522d5295ebc5adb60e7f7e1cdd097166d14b67ec13a210f3925" +
+			"64af0fef0d0286843aea3decb058bafbb8b0ccfcf2b5cc05e3a662d9814bc24c" +
+			"2364a1aa37c0ed052b36505c451e7ec85d2a542fe43d0fbb91c8d92560d4d5f8" +
+			"12a0594b9e8a51dacd49ebdb1b0dcdc1cd57c7f7e63444517ded386f2f36fa86" +
+			"a6d1210133bc405db388d96cdb6dbe96fe29661c13edc0cbcb0eee4a70cc94ae" +
+			"de11ed340606cf9f3a6ce38923d74f4ea37f63ff917bdec2d73f72d40e7e0e67" +
+			"3d77d9a213add9228891b3db01a9bd7056a001e3d51f093dcc033ce35ad0d3b0" +
+			"34105a8c6a123f57bd2e50247364944be89b1a3b21835c4d9f39e2d9d405ded8" +
+			"294d37e5bccaaeed35a124b56708a2bcb00960ba2a98121a4d8fae820bb3263f" +
+			"12595a196a1075890809e49421c171ec884d682514c8009bb0b84e7b03fb88f4" +
+			"28e7cb789388b13bdd2dc1d5848f520a07c28cd168a3935872c9137d127dd430" +
+			"c613f1578c2f0d55f7d3f39f309bfb788406b13746c0a6f53718d59708607f04" +
+			"76904b6d04db4e13cd7411a7b510ce0ebfc7f7ccb83f957afdfef62dc35e4580" +
+			"3ff1e5244112d96c02c9b944d5990dfbe7e265810d9c7e7e826dfa8966f1e0ab" +
+			"30bcc764eadebeaced35e5ee0c571a7de4f3a26af7f58f7badf6bc235d023e65" +
+			"1ed3ff4eec46b0b6d2a93b51e75b41c97e315aeb61119a5a53245b7933f6d7b1" +
+			"cae8deba50fc8194afa92a6dc87c80064188bfcd8bace62e78ffa5685597ec0f" +
+			"b4415f7d08294766ad56764309c36f903dde9f394a0a283c18080c8e080c79ec" +
+			"79ae4c10cb9e15637cdd662f62d31911a4ca0cf15cf824cd3b708f991e16614c" +
+			"b6b9d7665de87abb7229ea81d5b2d75056e6cd21fe1e42d596da2655c2b9aa36" +
+			"b8f6fd4a6a158d1001913fd3af7d1fb80b5e435f90c107576554abda7a68710f" +
+			"82ac484fd7e1c7be95c85eaa94a302f44d3cfbda786b29081010b27582d53d12" +
+			"21e2a51c3d1e9150b059261dd0638e1a31860f0581f2864dff4cfc350451516d" +
+			"bd086f26bc5654c165dfa427a82427f5582e3014b8d2486dc79a17499a1d7745" +
+			"8766bb541e04a7f73d3dff8ad5ec6bf4dbef7d9f36ec0ea31feb2e4f15cfcc5c" +
+			"d8c423fbd0ef3cc9eb244925ba5590c8a5f48ac433c5321c613b67b2479c3a22" +
+			"e21339cc10d210aa931dd7e2ef05ee06b82f2703a385cb2c5d67133c877eb7b4" +
+			"1e3437f75afb43ae53c078f394d904811d96458908063a85e13222281956b1e5" +
+			"31860f132e7b022f21182ca396f703ac46819e2e0d28fe523724d4dca0eabe6b" +
+			"c66699fdc6112fdd19c1e69c04d3658a4b55dd9931907d62f854b5224d678f26" +
+			"22ae0582eafed133e4a51d2184bd6dd6c1a513753f28ee63fb737b1a70a1660e" +
+			"8a8dfaa31be79937f7476978513c1764531ac6bf12c06908001cdb951a4b6a53" +
+			"d067fce512b2cfb69ddb477f740e006639ddf25acc8bfa2df1b20eaf64f2632c" +
+			"9783cdee63bfd4d80084cfe575f4e9e219b48fd06c48ddd87a36af9371865c4c" +
+			"9ce0199d867027d72cb7b77f84ef01da72f5972f040f7074df9afa29c921f94e" +
+			"75c08a3618c1ef9ad649a428c5b719378a30738ad97cd348858129a6239e3b0a" +
+			"bbb8abc480fac4c2ecfcf20bd9d711f9e2a4ef71b5fe87c0be8b06b2aafef5a7" +
+			"9c15db3b0aeb81654389a84a253b1d7a19047c797cdc78a2d20adf0356f55a71" +
+			"3e730fa8fd8650d8959e234eb7546681dad1b22a142a6e858ef4bce668235b9d" +
+			"85a13f8574096ae7a949bea229322d0dd568385882846526403dae086dd1943a" +
+			"e1279bff9e7e4f041c3a4524484525e481d4cc5fe24124c0037464c0bf1bd691" +
+			"26ceb003275ead3ac5bde90826414ff3a30519add7b43abe2ce5d3d588412761" +
+			"97ca2070e5fbb9c7276df0b4308f751f37a97df6c9cd808cfe4cb3803d469303" +
+			"aee19096c0d5d42a4e823ad3f5f9cc3b4286619c9ca45e1c66c97340891aec49" +
+			"45bae606c798f04752649d6cce86fdfc80c6e402d6ec2f2b27c822821fe26ce0" +
+			"92f57ea7de462f4d07497cae5a48755c721502dd6cbe7935836d80039ead7f70" +
+			"9ab3a42f4c8652d632e39273e8fa38601da4f25a0cd6ef8102503f7d8854a0a1" +
+			"9a30c4e88815715305efe29457c4c9252887d96fc1a71e3ce9f841632d0985de" +
+			"d21e796c6fb5ce5602614abfc3c7be2cb54fed6fa617a083c3142d8f6079e4ce" +
+			"ceffc1471d0cb81bdc153e5fe36ef5bbd531161a165b10157aa114ed3f7579b3" +
+			"f7f395f1bc6172c7a86f875e0e6c51b3cdfec2af73c0e762824c2009c5a87748" +
+			"94d401258aba3ffbd32be0608c17eff021e2547e07cffad905340e15f3310c92" +
+			"9d8d190886ba527ff943f672ef73fbf046d95ca5c54cd95b9d855e894bb5af29");
+
+		byte[] outFFFFFFFF = Hex.Decode(
+			"de3b3f3c19e0629c1fc8b7836695d523e7804edd86ff7ce9b106f52caebae9d9" +
+			"72f845d49ce17d7da44e49bae954aac0d0b1284b98a88eec1524fb6bc91a16b5" +
+			"1192ac5334131446ac2442de9ff3d5867b9b9148881ee30a6e87dd88e5d1f7cd" +
+			"98db31ff36f70d9850cfefaef42abb00ecc39ed308bf4b8030cdc2b6b7e42f0e" +
+			"908030dd282f96edacc888b3a986e109c129998f89baa1b5da8970b07a6ab012" +
+			"f10264f23c315c9c8e0c164955c68517b6a4f982b2626db70787f869ac6d551b" +
+			"e34931627c7058e965c502e18d2cd370e6db3b70d947d61aa9717cf8394f48c6" +
+			"3c796f3a154950846badb28b70d982f29bc670254e3e5e0f8e36b0a5f6da0a04" +
+			"6b235ed6a42988c012bde74d879fa8eb5d59f5f40ed5e76601c9847b3edb2690");
+
+		byte[] outFFFF0000 = Hex.Decode(
+			"26c54b1f8c4e3fc582e9e8180f7aba5380463dcf58b03cbeda0ecc8ba90ccff8" +
+			"5bd50896313d7efed44015faeac6964b241a7fb8a2e37127a7cbea0fd7c020f2" +
+			"406371b87ef5185089504751e5e44352eff63e00e5c28f5dff0616a9a3a00f1f" +
+			"4a1350e3a17be9abddfc2c94571450a0dc4c3c0c7c7f98e80c95f607d50c676a" +
+			"9a3006f9d279a79a4d66b2ab0c52930c9ee84bc09895e70fa041b1a3a2966f11" +
+			"6a47fd09705124b1f5c7ae055e54536e66584b1608f3612d81b72f109a385831" +
+			"121945b207b90ac72437a248f27a121c2801f4153a8699fb047e193f7ba69e1b" +
+			"b117869675d4c963e6070c2ca3d332ce830cb5e3d9ed2eee7faf0acc20fbe154" +
+			"188ae789e95bd5c1f459dbd150aab6eb833170257084bc5d44e9df09f5624f9d" +
+			"afecd0c9340ac8587f8625d343f7efd1cc8abcf7a6f90eabd4e8e2d906278d6e" +
+			"431fcade165c8c467887fbf5c26d341557b064b98c60dd40ab262dc046d69647" +
+			"56f3ddc1a07ae5f87be878b9334fcde40add68d2ca1dc05fb1670f998c7c4607" +
+			"9a6e48bdb330ad8d30b61b5cc8dc156f5733905931949783f89ac396b65aa4b8" +
+			"51f746b53ed8ea66130e1d75e8eab136e60450e3e600226bc8e17d03744ce94c" +
+			"0eec9234fea5f18eef65d81f2f10cfbc0b112b8cde17c32eb33ed81d7356eac3" +
+			"eb1cb9cefa6604c2d707949b6e5a83e60705bf6aae76dcc7d35d68ff149c1ac5" +
+			"424bb4a39e2f496f886637fce3db4ba4ad12c1a32d25e1606f6635ff636486f6" +
+			"714997b45477f38813c02afce4bebf196b813332f0decd567c745f441e736364");
+
+		byte[] out0000FFFF = Hex.Decode(
+			"bc31712f2a2f467a5abc737c57ce0f8d49d2f775eb850fc8f856daf19310fee2"+
+			"5bab40e78403c9ef4ccd971418992faf4e85ca643fa6b482f30c4659066158a6"+
+			"5bc3e620ba7ea5c34dd0eac5aabb2cf078d915fd1f8c437ed00423076c10f701"+
+			"eefa7fc7c461aca5db8a87be29d925c4212d4adcfa71ff5b06af15c048aa0dfd"+
+			"f0e645bc09fea200c430a88eb38c466ff358b836f1159656a078f6fc752f6db1"+
+			"6680bb30fc771a6a785bbb2298e947d7b3500e557775962248bedf4e82c16e66"+
+			"f39283ccb95e5399061056a11c4a280f00f7487888199487905273c7aa13012b"+
+			"4849eca626cbf071c782e084f9fded57de92313e5f61a6e81117fb1115eff275"+
+			"66fd5c755bb3b01bba69aeb8f1b1b1cc9709734be31b35bc707d372ba6fe70d1"+
+			"e2c3b0e5e74a7058faff6b11d3a168f19fecc9fcb36b3e6a5f828c01c22ac0c2"+
+			"5da2a3a9eec7e0ebbbf51472e430ed4cf1c7ab57ef9aea511e40250846d260b6"+
+			"17a3fdeba16cf4afaf700144d3296b58b22a3c79ed96f3e2fc8d9e3c660ae153"+
+			"8e0c285ccdc48b59117e80413bd0ad24c6a8d4f133fe1496f14351bb89904fa5"+
+			"e10c4b8d50e0604578389c336a9ab3d292beb90ce640fc028e697cf54e021e2f"+
+			"c0ca3fe0471fde5e5462f221739a74f5a13ae0621fe2a82e752bc294f63de48d"+
+			"e85430af71307a30441b861ab5380e6a6dbe1251c9baa567da14e38e5a0ccddf"+
+			"0127205c38fc3b77065e98101d219246103438d223ec7f8f533d4bb3a3d3407a"+
+			"944910f11e8e5492e86de7a0471250eca32f0838b3db02fffe71898712af3261");
+
+		public override string Name
+		{
+			get { return "ISAAC"; }
+		}
+
+		public override void PerformTest()
+		{
+			IsaacEngine engine = new IsaacEngine();
+
+			doTest(engine, Hex.Decode("00000000"), outBase);
+			doTest(engine, Hex.Decode("ffffffff"), outFFFFFFFF);
+
+			byte[] k = new byte[256 * 4];
+			for (int i = 0; i != k.Length; i++)
+			{
+				k[i] = (byte)((i % 4 == 0 || i % 4 == 1) ? 0xff : 0x00);
+			}
+			doTest(engine, k, outFFFF0000);
+			k = new byte[256 * 4];
+			for (int i = 0; i != k.Length; i++)
+			{
+				k[i] = (byte)((i % 4 == 2 || i % 4 == 3) ? 0xff : 0x00);
+			}
+			doTest(engine, k, out0000FFFF);
+		}
+
+		private void doTest(
+			IsaacEngine	engine,
+			byte[]		key,
+			byte[]		output)
+		{
+			byte[] input = new byte[output.Length];
+			byte[] enc = new byte[output.Length];
+			engine.Init(true, new KeyParameter(key));
+			engine.ProcessBytes(input, 0, input.Length, enc, 0);
+			if (!AreEqual(enc, output))
+			{
+				Fail("ciphertext mismatch");
+			}
+			engine.Init(false, new KeyParameter(key));
+			engine.ProcessBytes(enc, 0, enc.Length, enc, 0);
+			if (!AreEqual(enc, input))
+			{
+				Fail("plaintext mismatch");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new IsaacTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9796Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9796Test.cs
new file mode 100644
index 0000000..562238b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9796Test.cs
@@ -0,0 +1,961 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> test vectors from ISO 9796-1 and ISO 9796-2 edition 1.</summary>
+    [TestFixture]
+    public class ISO9796Test
+        : SimpleTest
+    {
+        static BigInteger mod1 = new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16);
+
+        static BigInteger pub1 = new BigInteger("03", 16);
+
+        static BigInteger pri1 = new BigInteger("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7", 16);
+
+        static BigInteger mod2 = new BigInteger("ffffff7fa27087c35ebead78412d2bdffe0301edd494df13458974ea89b364708f7d0f5a00a50779ddf9f7d4cb80b8891324da251a860c4ec9ef288104b3858d", 16);
+
+        static BigInteger pub2 = new BigInteger("03", 16);
+
+        static BigInteger pri2 = new BigInteger("2aaaaa9545bd6bf5e51fc7940adcdca5550080524e18cfd88b96e8d1c19de6121b13fac0eb0495d47928e047724d91d1740f6968457ce53ec8e24c9362ce84b5", 16);
+
+        static byte[] msg1 = Hex.Decode("0cbbaa99887766554433221100");
+
+        //
+        // you'll need to see the ISO 9796 to make sense of this
+        //
+        static byte[] sig1 = mod1.Subtract(new BigInteger("309f873d8ded8379490f6097eaafdabc137d3ebfd8f25ab5f138d56a719cdc526bdd022ea65dabab920a81013a85d092e04d3e421caab717c90d89ea45a8d23a", 16)).ToByteArray();
+
+        static byte[] msg2 = Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+
+        static byte[] sig2 = new BigInteger("319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c", 16).ToByteArray();
+
+        static byte[] msg3 = Hex.Decode("0112233445566778899aabbccd");
+
+        static byte[] sig3 = mod2.Subtract(new BigInteger("58e59ffb4b1fb1bcdbf8d1fe9afa3730c78a318a1134f5791b7313d480ff07ac319b068edf8f212945cb09cf33df30ace54f4a063fcca0b732f4b662dc4e2454", 16)).ToByteArray();
+
+        //
+        // ISO 9796-2
+        //
+        static BigInteger mod3 = new BigInteger("ffffffff78f6c55506c59785e871211ee120b0b5dd644aa796d82413a47b24573f1be5745b5cd9950f6b389b52350d4e01e90009669a8720bf265a2865994190a661dea3c7828e2e7ca1b19651adc2d5", 16);
+
+        static BigInteger pub3 = new BigInteger("03", 16);
+
+        static BigInteger pri3 = new BigInteger("2aaaaaaa942920e38120ee965168302fd0301d73a4e60c7143ceb0adf0bf30b9352f50e8b9e4ceedd65343b2179005b2f099915e4b0c37e41314bb0821ad8330d23cba7f589e0f129b04c46b67dfce9d", 16);
+
+        static BigInteger mod4 = new BigInteger("FFFFFFFF45f1903ebb83d4d363f70dc647b839f2a84e119b8830b2dec424a1ce0c9fd667966b81407e89278283f27ca8857d40979407fc6da4cc8a20ecb4b8913b5813332409bc1f391a94c9c328dfe46695daf922259174544e2bfbe45cc5cd", 16);
+        static BigInteger pub4 = new BigInteger("02", 16);
+        static BigInteger pri4 = new BigInteger("1fffffffe8be3207d7707a9a6c7ee1b8c8f7073e5509c2337106165bd8849439c193faccf2cd70280fd124f0507e4f94cb66447680c6b87b6599d1b61c8f3600854a618262e9c1cb1438e485e47437be036d94b906087a61ee74ab0d9a1accd8", 16);
+
+        static byte[] msg4 = Hex.Decode("6162636462636465636465666465666765666768666768696768696a68696a6b696a6b6c6a6b6c6d6b6c6d6e6c6d6e6f6d6e6f706e6f7071");
+        static byte[] sig4 = Hex.Decode("374695b7ee8b273925b4656cc2e008d41463996534aa5aa5afe72a52ffd84e118085f8558f36631471d043ad342de268b94b080bee18a068c10965f581e7f32899ad378835477064abed8ef3bd530fce");
+
+        static byte[] msg5 = Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+        static byte[] sig5 = Hex.Decode("5cf9a01854dbacaec83aae8efc563d74538192e95466babacd361d7c86000fe42dcb4581e48e4feb862d04698da9203b1803b262105104d510b365ee9c660857ba1c001aa57abfd1c8de92e47c275cae");
+
+        //
+        // scheme 2 data
+        //
+        static BigInteger mod6 = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+        static BigInteger pub6 = new BigInteger("11", 16);
+        static BigInteger pri6 = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+
+        //		static byte[] sig6 = new BigInteger("0073FEAF13EB12914A43FE635022BB4AB8188A8F3ABD8D8A9E4AD6C355EE920359C7F237AE36B1212FE947F676C68FE362247D27D1F298CA9302EB21F4A64C26CE44471EF8C0DFE1A54606F0BA8E63E87CDACA993BFA62973B567473B4D38FAE73AB228600934A9CC1D3263E632E21FD52D2B95C5F7023DA63DE9509C01F6C7BBC", 16).ModPow(pri6, mod6).ToByteArray();
+        static byte[] sig6 = new BigInteger("0073FEAF13EB12914A43FE635022BB4AB8188A8F3ABD8D8A9E4AD6C355EE920359C7F237AE36B1212FE947F676C68FE362247D27D1F298CA9302EB21F4A64C26CE44471EF8C0DFE1A54606F0BA8E63E87CDACA993BFA62973B567473B4D38FAE73AB228600934A9CC1D3263E632E21FD52D2B95C5F7023DA63DE9509C01F6C7BBC", 16).ModPow(pri6, mod6).ToByteArray();
+
+        static byte[] msg7 = Hex.Decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F70717270717273");
+        static byte[] sig7 = new BigInteger("296B06224010E1EC230D4560A5F88F03550AAFCE31C805CE81E811E5E53E5F71AE64FC2A2A486B193E87972D90C54B807A862F21A21919A43ECF067240A8C8C641DE8DCDF1942CF790D136728FFC0D98FB906E7939C1EC0E64C0E067F0A7443D6170E411DF91F797D1FFD74009C4638462E69D5923E7433AEC028B9A90E633CC", 16).ModPow(pri6, mod6).ToByteArray();
+
+        static byte[] msg8 = Hex.Decode("FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA98");
+        static byte[] sig8 = new BigInteger("01402B29ABA104079677CE7FC3D5A84DB24494D6F9508B4596484F5B3CC7E8AFCC4DDE7081F21CAE9D4F94D6D2CCCB43FCEDA0988FFD4EF2EAE72CFDEB4A2638F0A34A0C49664CD9DB723315759D758836C8BA26AC4348B66958AC94AE0B5A75195B57ABFB9971E21337A4B517F2E820B81F26BCE7C66F48A2DB12A8F3D731CC", 16).ModPow(pri6, mod6).ToByteArray();
+
+        static byte[] msg9 = Hex.Decode("6162636462636465636465666465666765666768666768696768696A68696A6B696A6B6C6A6B6C6D6B6C6D6E6C6D6E6F6D6E6F706E6F70716F707172707172737172737472737475737475767475767775767778767778797778797A78797A61797A61627A6162636162636462636465");
+        static byte[] sig9 = new BigInteger("6F2BB97571FE2EF205B66000E9DD06656655C1977F374E8666D636556A5FEEEEAF645555B25F45567C4EE5341F96FED86508C90A9E3F11B26E8D496139ED3E55ECE42860A6FB3A0817DAFBF13019D93E1D382DA07264FE99D9797D2F0B7779357CA7E74EE440D8855B7DDF15F000AC58EE3FFF144845E771907C0C83324A6FBC", 16).ModPow(pri6, mod6).ToByteArray();
+
+        public override string Name
+        {
+            get { return "ISO9796"; }
+        }
+
+        private bool IsSameAs(
+            byte[]	a,
+            int		off,
+            byte[]	b)
+        {
+            if ((a.Length - off) != b.Length)
+            {
+                return false;
+            }
+
+            for (int i = 0; i != b.Length; i++)
+            {
+                if (a[i + off] != b[i])
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+        private bool StartsWith(
+            byte[]	a,
+            byte[]	b)
+        {
+            if (a.Length < b.Length)
+                return false;
+
+            for (int i = 0; i != b.Length; i++)
+            {
+                if (a[i] != b[i])
+                    return false;
+            }
+
+            return true;
+        }
+
+        [Test]
+        public virtual void DoTest1()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod1, pub1);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod1, pri1);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-1 - public encrypt, private decrypt
+            //
+            ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+            eng.Init(true, privParameters);
+
+            eng.SetPadBits(4);
+
+            data = eng.ProcessBlock(msg1, 0, msg1.Length);
+
+            eng.Init(false, pubParameters);
+
+            if (!AreEqual(sig1, data))
+            {
+                Fail("failed ISO9796-1 generation Test 1");
+            }
+
+            data = eng.ProcessBlock(data, 0, data.Length);
+
+            if (!AreEqual(msg1, data))
+            {
+                Fail("failed ISO9796-1 retrieve Test 1");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest2()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod1, pub1);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod1, pri1);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-1 - public encrypt, private decrypt
+            //
+            ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+            eng.Init(true, privParameters);
+
+            data = eng.ProcessBlock(msg2, 0, msg2.Length);
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(data, 1, sig2))
+            {
+                Fail("failed ISO9796-1 generation Test 2");
+            }
+
+            data = eng.ProcessBlock(data, 0, data.Length);
+
+            if (!AreEqual(msg2, data))
+            {
+                Fail("failed ISO9796-1 retrieve Test 2");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest3()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod2, pub2);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod2, pri2);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-1 - public encrypt, private decrypt
+            //
+            ISO9796d1Encoding eng = new ISO9796d1Encoding(rsa);
+
+            eng.Init(true, privParameters);
+
+            eng.SetPadBits(4);
+
+            data = eng.ProcessBlock(msg3, 0, msg3.Length);
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig3, 1, data))
+            {
+                Fail("failed ISO9796-1 generation Test 3");
+            }
+
+            data = eng.ProcessBlock(data, 0, data.Length);
+
+            if (!IsSameAs(msg3, 0, data))
+            {
+                Fail("failed ISO9796-1 retrieve Test 3");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest4()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod3, pub3);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod3, pri3);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - Signing
+            //
+            Iso9796d2Signer eng = new Iso9796d2Signer(rsa, new RipeMD128Digest());
+
+            eng.Init(true, privParameters);
+
+            eng.Update(msg4[0]);
+            eng.BlockUpdate(msg4, 1, msg4.Length - 1);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig4, 0, data))
+            {
+                Fail("failed ISO9796-2 generation Test 4");
+            }
+
+            eng.Update(msg4[0]);
+            eng.BlockUpdate(msg4, 1, msg4.Length - 1);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 4");
+            }
+
+            if (eng.HasFullMessage())
+            {
+                eng = new Iso9796d2Signer(rsa, new RipeMD128Digest());
+
+                eng.Init(false, pubParameters);
+
+                if (!eng.VerifySignature(sig4))
+                {
+                    Fail("failed ISO9796-2 verify and recover Test 4");
+                }
+
+                if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4))
+                {
+                    Fail("failed ISO9796-2 recovered message Test 4");
+                }
+
+                // try update with recovered
+                eng.UpdateWithRecoveredMessage(sig4);
+
+                if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4))
+                {
+                    Fail("failed ISO9796-2 updateWithRecovered recovered message Test 4");
+                }
+                
+                if (!eng.VerifySignature(sig4))
+                {
+                    Fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
+                }
+                
+                if(!IsSameAs(eng.GetRecoveredMessage(), 0, msg4))
+                {
+                    Fail("failed ISO9796-2 updateWithRecovered recovered verify message Test 4");
+                }
+                
+                // should fail
+                eng.UpdateWithRecoveredMessage(sig4);
+                
+                eng.BlockUpdate(msg4, 0, msg4.Length);
+                
+                if (eng.VerifySignature(sig4))
+                {
+                    Fail("failed ISO9796-2 updateWithRecovered verify and recover Test 4");
+                }
+            }
+            else
+            {
+                Fail("full message flag false - Test 4");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest5()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod3, pub3);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod3, pri3);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - Signing
+            //
+            Iso9796d2Signer eng = new Iso9796d2Signer(rsa, new RipeMD160Digest(), true);
+
+            eng.Init(true, privParameters);
+
+            eng.Update(msg5[0]);
+            eng.BlockUpdate(msg5, 1, msg5.Length - 1);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig5, 0, data))
+            {
+                Fail("failed ISO9796-2 generation Test 5");
+            }
+
+            eng.Update(msg5[0]);
+            eng.BlockUpdate(msg5, 1, msg5.Length - 1);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 5");
+            }
+
+            if (eng.HasFullMessage())
+            {
+                Fail("fullMessage true - Test 5");
+            }
+
+            if (!StartsWith(msg5, eng.GetRecoveredMessage()))
+            {
+                Fail("failed ISO9796-2 partial recovered message Test 5");
+            }
+
+            int length = eng.GetRecoveredMessage().Length;
+
+            if (length >= msg5.Length)
+            {
+                Fail("Test 5 recovered message too long");
+            }
+
+            eng = new Iso9796d2Signer(rsa, new RipeMD160Digest(), true);
+
+            eng.Init(false, pubParameters);
+
+            eng.UpdateWithRecoveredMessage(sig5);
+
+            if (!StartsWith(msg5, eng.GetRecoveredMessage()))
+            {
+                Fail("failed ISO9796-2 updateWithRecovered partial recovered message Test 5");
+            }
+
+            if (eng.HasFullMessage())
+            {
+                Fail("fullMessage updateWithRecovered true - Test 5");
+            }
+
+            for (int i = length ; i != msg5.Length; i++)
+            {
+                eng.Update(msg5[i]);
+            }
+
+            if (!eng.VerifySignature(sig5))
+            {
+                Fail("failed ISO9796-2 verify Test 5");
+            }
+
+            if (eng.HasFullMessage())
+            {
+                Fail("fullMessage updateWithRecovered true - Test 5");
+            }
+
+            // should fail
+            eng.UpdateWithRecoveredMessage(sig5);
+
+            eng.BlockUpdate(msg5, 0, msg5.Length);
+
+            if (eng.VerifySignature(sig5))
+            {
+                Fail("failed ISO9796-2 updateWithRecovered verify fail Test 5");
+            }
+        }
+
+        //
+        // against a zero length string
+        //
+        [Test]
+        public virtual void DoTest6()
+        {
+            byte[] salt = Hex.Decode("61DF870C4890FE85D6E3DD87C3DCE3723F91DB49");
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod6, pub6);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod6, pri6);
+            ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            Iso9796d2PssSigner eng = new Iso9796d2PssSigner(rsa, new RipeMD160Digest(), 20, true);
+
+            eng.Init(true, sigParameters);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig6, 1, data))
+            {
+                Fail("failed ISO9796-2 generation Test 6");
+            }
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 6");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest7()
+        {
+            byte[] salt = new byte[0];
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod6, pub6);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod6, pri6);
+            ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            Iso9796d2PssSigner eng = new Iso9796d2PssSigner(rsa, new Sha1Digest(), 0, false);
+
+            eng.Init(true, sigParameters);
+
+            eng.Update(msg7[0]);
+            eng.BlockUpdate(msg7, 1, msg7.Length - 1);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig7, 0, data))
+            {
+                Fail("failed ISO9796-2 generation Test 7");
+            }
+
+            eng.Update(msg7[0]);
+            eng.BlockUpdate(msg7, 1, msg7.Length - 1);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 7");
+            }
+
+            if (!IsSameAs(msg7, 0, eng.GetRecoveredMessage()))
+            {
+                Fail("failed ISO9796-2 recovery Test 7");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest8()
+        {
+            byte[] salt = Hex.Decode("78E293203CBA1B7F92F05F4D171FF8CA3E738FF8");
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod6, pub6);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod6, pri6);
+            ParametersWithSalt sigParameters = new ParametersWithSalt(privParameters, salt);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            Iso9796d2PssSigner eng = new Iso9796d2PssSigner(rsa, new RipeMD160Digest(), 20, false);
+
+            eng.Init(true, sigParameters);
+
+            eng.Update(msg8[0]);
+            eng.BlockUpdate(msg8, 1, msg8.Length - 1);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig8, 0, data))
+            {
+                Fail("failed ISO9796-2 generation Test 8");
+            }
+
+            eng.Update(msg8[0]);
+            eng.BlockUpdate(msg8, 1, msg8.Length - 1);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 8");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest9()
+        {
+            RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod6, pub6);
+            RsaKeyParameters privParameters = new RsaKeyParameters(true, mod6, pri6);
+            RsaEngine rsa = new RsaEngine();
+            byte[] data;
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            Iso9796d2PssSigner eng = new Iso9796d2PssSigner(rsa, new RipeMD160Digest(), 0, true);
+
+            eng.Init(true, privParameters);
+
+            eng.Update(msg9[0]);
+            eng.BlockUpdate(msg9, 1, msg9.Length - 1);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            if (!IsSameAs(sig9, 0, data))
+            {
+                Fail("failed ISO9796-2 generation Test 9");
+            }
+
+            eng.Update(msg9[0]);
+            eng.BlockUpdate(msg9, 1, msg9.Length - 1);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 9");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest10()
+        {
+            BigInteger          mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+            BigInteger          pubExp = new BigInteger("65537", 10);
+            BigInteger          priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+            RsaKeyParameters    pubParameters = new RsaKeyParameters(false, mod, pubExp);
+            RsaKeyParameters    privParameters = new RsaKeyParameters(true, mod, priExp);
+            RsaEngine           rsa = new RsaEngine();
+            byte[]              data;
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            IDigest              dig = new Sha1Digest();
+            Iso9796d2PssSigner  eng = new Iso9796d2PssSigner(rsa, dig, dig.GetDigestSize());
+
+            //
+            // as the padding is random this test needs to repeat a few times to
+            // make sure
+            //
+            for (int i = 0; i != 500; i++)
+            {
+                eng.Init(true, privParameters);
+
+                eng.Update(msg9[0]);
+                eng.BlockUpdate(msg9, 1, msg9.Length - 1);
+
+                data = eng.GenerateSignature();
+
+                eng.Init(false, pubParameters);
+
+                eng.Update(msg9[0]);
+                eng.BlockUpdate(msg9, 1, msg9.Length - 1);
+
+                if (!eng.VerifySignature(data))
+                {
+                    Fail("failed ISO9796-2 verify Test 10");
+                }
+            }
+        }
+
+        [Test]
+        public virtual void DoTest11()
+        {
+            BigInteger          mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+            BigInteger          pubExp = new BigInteger("65537", 10);
+            BigInteger          priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+            RsaKeyParameters    pubParameters = new RsaKeyParameters(false, mod, pubExp);
+            RsaKeyParameters    privParameters = new RsaKeyParameters(true, mod, priExp);
+            RsaEngine           rsa = new RsaEngine();
+            byte[]              data;
+            byte[]              m1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+            byte[]              m2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+            byte[]              m3 = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+            //
+            // ISO 9796-2 - PSS Signing
+            //
+            IDigest              dig = new Sha1Digest();
+            Iso9796d2PssSigner  eng = new Iso9796d2PssSigner(rsa, dig, dig.GetDigestSize());
+
+            //
+            // check message bounds
+            //
+            eng.Init(true, privParameters);
+
+            eng.BlockUpdate(m1, 0, m1.Length);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m2, 0, m2.Length);
+
+            if (eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 m2 verify Test 11");
+            }
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m3, 0, m3.Length);
+
+            if (eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 m3 verify Test 11");
+            }
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m1, 0, m1.Length);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 11");
+            }
+        }
+
+        [Test]
+        public virtual void DoTest12()
+        {
+            BigInteger          mod = new BigInteger("B3ABE6D91A4020920F8B3847764ECB34C4EB64151A96FDE7B614DC986C810FF2FD73575BDF8532C06004C8B4C8B64F700A50AEC68C0701ED10E8D211A4EA554D", 16);
+            BigInteger          pubExp = new BigInteger("65537", 10);
+            BigInteger          priExp = new BigInteger("AEE76AE4716F77C5782838F328327012C097BD67E5E892E75C1356E372CCF8EE1AA2D2CBDFB4DA19F703743F7C0BA42B2D69202BA7338C294D1F8B6A5771FF41", 16);
+            RsaKeyParameters    pubParameters = new RsaKeyParameters(false, mod, pubExp);
+            RsaKeyParameters    privParameters = new RsaKeyParameters(true, mod, priExp);
+            RsaEngine           rsa = new RsaEngine();
+            byte[]              data;
+            byte[]              m1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+            byte[]              m2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+            byte[]              m3 = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+            //
+            // ISO 9796-2 - Regular Signing
+            //
+            IDigest           dig = new Sha1Digest();
+            Iso9796d2Signer  eng = new Iso9796d2Signer(rsa, dig);
+
+            //
+            // check message bounds
+            //
+            eng.Init(true, privParameters);
+
+            eng.BlockUpdate(m1, 0, m1.Length);
+
+            data = eng.GenerateSignature();
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m2, 0, m2.Length);
+
+            if (eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 m2 verify Test 12");
+            }
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m3, 0, m3.Length);
+
+            if (eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 m3 verify Test 12");
+            }
+
+            eng.Init(false, pubParameters);
+
+            eng.BlockUpdate(m1, 0, m1.Length);
+
+            if (!eng.VerifySignature(data))
+            {
+                Fail("failed ISO9796-2 verify Test 12");
+            }
+        }
+
+        [Test]
+        public void DoTest13()
+        {
+            BigInteger modulus = new BigInteger(1, Hex.Decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
+            BigInteger pubExp = new BigInteger(1, Hex.Decode("010001"));
+            BigInteger privExp = new BigInteger(1, Hex.Decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
+
+            RsaKeyParameters pubParams = new RsaKeyParameters(false, modulus, pubExp);
+            RsaKeyParameters privParams = new RsaKeyParameters(true, modulus, privExp);
+
+            IAsymmetricBlockCipher rsaEngine = new RsaBlindedEngine();
+            IDigest digest = new Sha256Digest();
+
+            // set challenge to all zero's for verification
+            byte[] challenge = new byte[8];
+
+            // DOES NOT USE FINAL BOOLEAN TO INDICATE RECOVERY
+            Iso9796d2Signer signer = new Iso9796d2Signer(rsaEngine, digest, false);
+
+            // sign
+            signer.Init(true, privParams);
+            signer.BlockUpdate(challenge, 0, challenge.Length);
+
+            byte[]  sig = signer.GenerateSignature();
+
+            // verify
+            signer.Init(false, pubParams);
+            signer.BlockUpdate(challenge, 0, challenge.Length);
+
+            if (!signer.VerifySignature(sig))
+            {
+                Fail("basic verification failed");
+            }
+
+            // === LETS ACTUALLY DO SOME RECOVERY, USING INPUT FROM INTERNAL AUTHENTICATE ===
+
+            signer.Reset();
+
+            string args0 = "482E20D1EDDED34359C38F5E7C01203F9D6B2641CDCA5C404D49ADAEDE034C7481D781D043722587761C90468DE69C6585A1E8B9C322F90E1B580EEDAB3F6007D0C366CF92B4DB8B41C8314929DCE2BE889C0129123484D2FD3D12763D2EBFD12AC8E51D7061AFCA1A53DEDEC7B9A617472A78C952CCC72467AE008E5F132994";
+
+            digest = new Sha1Digest();
+
+            signer = new Iso9796d2Signer(rsaEngine, digest, true);
+
+
+            signer.Init(false, pubParams);
+            byte[] signature = Hex.Decode(args0);
+            signer.UpdateWithRecoveredMessage(signature);
+            signer.BlockUpdate(challenge, 0, challenge.Length);
+
+            if (!signer.VerifySignature(signature))
+            {
+                Fail("recovered + challenge signature failed");
+            }
+
+            // === FINALLY, USING SHA-256 ===
+
+            signer.Reset();
+
+            digest = new Sha256Digest();
+
+            // NOTE setting implicit to false does not actually do anything for verification !!!
+            signer = new Iso9796d2Signer(rsaEngine, digest, false);
+
+
+            signer.Init(true, privParams);
+            // generate NONCE of correct length using some inner knowledge
+            int nonceLength = modulus.BitLength / 8 - 1 - digest.GetDigestSize() - 2;
+            byte[] nonce = new byte[nonceLength];
+            SecureRandom rnd = new SecureRandom();
+
+            rnd.NextBytes(nonce);
+
+            signer.BlockUpdate(nonce, 0, nonce.Length);
+            signer.BlockUpdate(challenge, 0, challenge.Length);
+            byte[] sig3 = signer.GenerateSignature();
+
+            signer.Init(false, pubParams);
+            signer.UpdateWithRecoveredMessage(sig3);
+            signer.BlockUpdate(challenge, 0, challenge.Length);
+            if (signer.VerifySignature(sig3))
+            {
+                if (signer.HasFullMessage())
+                {
+                    Fail("signer indicates full message");
+                }
+                byte[] recoverableMessage = signer.GetRecoveredMessage();
+
+                // sanity check, normally the nonce is ignored in eMRTD specs (PKI Technical Report)
+                if (!Arrays.AreEqual(nonce, recoverableMessage))
+                {
+                    Fail("Nonce compare with recoverable part of message failed");
+                }
+            }
+            else
+            {
+                Fail("recoverable + nonce failed.");
+            }
+        }
+
+        private static readonly byte[] longMessage = Base64.Decode(
+            "VVNIKzErU0U2ODAxNTMyOTcxOSsyKzErNisyKzErMTo6OTk5OTk5OTk5OTk5"
+          + "OTo6OSsyOjo3Nzc3Nzc3Nzc3Nzc3Ojo5Kys1OjIwMTMwNDA1OjExMzUyMCdV"
+          + "U0ErMTo6OjE2OjEnVVNDKzRmYjk3YzFhNDI5ZGIyZDYnVVNBKzY6MTY6MTox"
+          + "MDoxKzE0OjIwNDgrMTI6/vn3S0h96eNhfmPN6OZUxXhd815h0tP871Hl+V1r"
+          + "fHHUXvrPXmjHV0vdb8fYY1zxwvnQUcFBWXT43PFi7Xbow0/9e9l6/mhs1UJq"
+          + "VPvp+ELbeXfn4Nj02ttk0e3H5Hfa69NYRuHv1WBO6lfizNnM9m9XYmh9TOrg"
+          + "f9rDRtd+ZNbf4lz9fPTt9OXyxOJWRPr/0FLzxUVsddplfHxM3ndETFD7ffjI"
+          + "/mhRYuL8WXZ733LeWFRCeOzKzmDz/HvT3GZx/XJMbFpqyOZjedzh6vZr1vrD"
+          + "615TQfN7wtJJ29bN2Hvzb2f1xGHaXl7af0/w9dpR2dr7/HzuZEJKYc7JSkv4"
+          + "/k37yERIbcrfbVTeVtR+dcVoeeRT41fmzMfzf8RnWOX4YMNifl0rMTM68EFA"
+          + "QSdCR00rMzgwKzk5OTk5OTk5J0RUTSsxMzc6MjAxMzA0MDU6MTAyJ0ZUWCtB"
+          + "QUkrKytJTlZPSUNFIFRFU1QnUkZGK09OOjEyMzQ1NidSRkYrRFE6MjIyMjIy"
+          + "MjIyJ0RUTSsxNzE6MjAxMzA0MDE6MTAyJ05BRCtTVSs5OTk5OTk5OTk5OTk5"
+          + "Ojo5KytURVNUIFNVUFBMSUVSOjpUcmFzZSByZWdpc3RlciBYWFhYWFhYK1Rl"
+          + "c3QgYWRkcmVzcyBzdXBwbGllcitDaXR5KysxMjM0NStERSdSRkYrVkE6QTEy"
+          + "MzQ1Njc4J05BRCtTQ08rOTk5OTk5OTk5OTk5OTo6OSsrVEVTVCBTVVBQTElF"
+          + "Ujo6VHJhc2UgcmVnaXN0ZXIgWFhYWFhYWCtUZXN0IGFkZHJlc3Mgc3VwcGxp"
+          + "ZXIrQ2l0eSsrMTIzNDUrREUnUkZGK1ZBOkExMjM0NTY3OCdOQUQrQlkrODg4"
+          + "ODg4ODg4ODg4ODo6OSdOQUQrSVYrNzc3Nzc3Nzc3Nzc3Nzo6OSsrVEVTVCBC"
+          + "VVlFUitUZXN0IGFkZHJlc3MgYnV5ZXIrQ2l0eTIrKzU0MzIxK0RFJ1JGRitW"
+          + "QTpKODc2NTQzMjEnTkFEK0JDTys3Nzc3Nzc3Nzc3Nzc3Ojo5KytURVNUIEJV"
+          + "WUVSK1Rlc3QgYWRkcmVzcyBidXllcitDaXR5MisrNTQzMjErREUnUkZGK1ZB"
+          + "Oko4NzY1NDMyMSdOQUQrRFArODg4ODg4ODg4ODg4ODo6OSdOQUQrUFIrNzc3"
+          + "Nzc3Nzc3Nzc3Nzo6OSdDVVgrMjpFVVI6NCdQQVQrMzUnRFRNKzEzOjIwMTMw"
+          + "NjI0OjEwMidMSU4rMSsrMTExMTExMTExMTExMTpFTidQSUErMStBQUFBQUFB"
+          + "OlNBJ0lNRCtGK00rOjo6UFJPRFVDVCBURVNUIDEnUVRZKzQ3OjEwLjAwMCdN"
+          + "T0ErNjY6Ny4wMCdQUkkrQUFCOjEuMDAnUFJJK0FBQTowLjcwJ1JGRitPTjox"
+          + "MjM0NTYnUkZGK0RROjIyMjIyMjIyMidUQVgrNytWQVQrKys6OjoyMS4wMDAn"
+          + "QUxDK0ErKysxK1REJ1BDRCsxOjMwLjAwMCdNT0ErMjA0OjMuMDAnTElOKzIr"
+          + "KzIyMjIyMjIyMjIyMjI6RU4nUElBKzErQkJCQkJCQjpTQSdJTUQrRitNKzo6"
+          + "OlBST0RVQ1QgVEVTVCAyJ1FUWSs0NzoyMC4wMDAnTU9BKzY2OjgwLjAwJ1BS"
+          + "SStBQUI6NS4wMCdQUkkrQUFBOjQuMDAnUkZGK09OOjEyMzQ1NidSRkYrRFE6"
+          + "MjIyMjIyMjIyJ1RBWCs3K1ZBVCsrKzo6OjIxLjAwMCdBTEMrQSsrKzErVEQn"
+          + "UENEKzE6MjAuMDAwJ01PQSsyMDQ6MjAuMDAnVU5TK1MnQ05UKzI6MidNT0Er"
+          + "Nzk6ODcuMDAnTU9BKzEzOToxMDUuMjcnTU9BKzEyNTo4Ny4wMCdNT0ErMjYw"
+          + "OjAuMDAnTU9BKzI1OTowLjAwJ01PQSsxNzY6MTguMjcnVEFYKzcrVkFUKysr"
+          + "Ojo6MjEuMDAwJ01PQSsxNzY6MTguMjcnTU9BKzEyNTo4Ny4wMCc=");
+
+        private static readonly byte[] shortPartialSig = Base64.Decode(
+            "sb8yyKk6HM1cJhICScMx7QRQunRyrZ1fbI42+T+TBGNjOknvzKuvG7aftGX7"
+          + "O/RXuYgk6LTxpXv7+O5noUhMBsR2PKaHveuylU1WSPmDxDCui3kp4frqVH0w"
+          + "8Vjpl5CsKqBsmKkbGCKE+smM0xFXhYxV8QUTB2XsWNCQiFiHPgwbpfWzZUNY"
+          + "QPWd0A99P64EuUIYz1tkkDnLFmwQ19/PJu1a8orIQInmkVYWSsBsZ/7Ks6lx"
+          + "nDHpAvgiRe+OXmJ/yuQy1O3FJYdyoqvjYRPBu3qYeBK9+9L3lExLilImH5aD"
+          + "nJznaXcO8QFOxVPbrF2s4GdPIMDonEyAHdrnzoghlg==");
+
+        [Test]
+        public void DoShortPartialTest()
+        {
+            byte[]     recovered = Hex.Decode("5553482b312b534536383031353332393731392b322b312b362b322b312b313a3a393939393939393939393939393a3a392b323a3a373737373737373737373737373a3a392b2b353a32303133303430353a313133");
+            BigInteger exp = new BigInteger("10001", 16);
+            BigInteger mod = new BigInteger("b9b70b083da9e37e23cde8e654855db31e21d2d3fc11a5f91d2b3c311efa8f5e28c757dd6fc798631cb1b9d051c14119749cb122ad76e8c3fd7bd93abe282c026a14fba9f8023977a7a0d8b49a24d1ad87e4379a931846a1ef9520ea57e28c998cf65722683d0caaa0da8306973e2496a25cbd3cb4adb4b284e25604fabf12f385456c75da7c3c4cde37440cfb7db8c8fe6851e2bc59767b9f7218540238ac8acef3bc7bd3dc6671320c2c1a2ac8a6799ce1eaf62b9683ab1e1341b37b9249dbd6cd987b2f27b5c4619a1eda7f0fb0b59a519afbbc3cee640261cec90a4bb8f [...]
+
+            AsymmetricKeyParameter pubKey = new RsaKeyParameters(false, mod, exp);
+
+            Iso9796d2PssSigner pssSign = new Iso9796d2PssSigner(new RsaEngine(), new Sha1Digest(), 20);
+
+            pssSign.Init(false, pubKey);
+
+            pssSign.UpdateWithRecoveredMessage(shortPartialSig);
+
+            byte[] recoveredMessage = pssSign.GetRecoveredMessage();
+            pssSign.BlockUpdate(longMessage, recoveredMessage.Length, longMessage.Length - recoveredMessage.Length);
+
+            if (!pssSign.VerifySignature(shortPartialSig))
+            {
+                Fail("short partial PSS sig verification failed.");
+            }
+
+            byte[] mm = pssSign.GetRecoveredMessage();
+
+            if (!Arrays.AreEqual(recovered, mm))
+            {
+                Fail("short partial PSS recovery failed");
+            }
+        }
+
+        [Test]
+        public void DoFullMessageTest()
+        {
+            BigInteger modulus = new BigInteger(1, Hex.Decode("CDCBDABBF93BE8E8294E32B055256BBD0397735189BF75816341BB0D488D05D627991221DF7D59835C76A4BB4808ADEEB779E7794504E956ADC2A661B46904CDC71337DD29DDDD454124EF79CFDD7BC2C21952573CEFBA485CC38C6BD2428809B5A31A898A6B5648CAA4ED678D9743B589134B7187478996300EDBA16271A861"));
+            BigInteger pubExp = new BigInteger(1, Hex.Decode("010001"));
+            BigInteger privExp = new BigInteger(1, Hex.Decode("4BA6432AD42C74AA5AFCB6DF60FD57846CBC909489994ABD9C59FE439CC6D23D6DE2F3EA65B8335E796FD7904CA37C248367997257AFBD82B26F1A30525C447A236C65E6ADE43ECAAF7283584B2570FA07B340D9C9380D88EAACFFAEEFE7F472DBC9735C3FF3A3211E8A6BBFD94456B6A33C17A2C4EC18CE6335150548ED126D"));
+            RsaKeyParameters pubParams = new RsaKeyParameters(false, modulus, pubExp);
+            RsaKeyParameters privParams = new RsaKeyParameters(true, modulus, privExp);
+
+            IAsymmetricBlockCipher rsaEngine = new RsaBlindedEngine();
+
+            // set challenge to all zero's for verification
+            byte[] challenge = new byte[8];
+
+            Iso9796d2PssSigner pssSign = new Iso9796d2PssSigner(new RsaEngine(), new Sha256Digest(), 20, true);
+
+            pssSign.Init(true, privParams);
+
+            pssSign.BlockUpdate(challenge, 0, challenge.Length);
+
+            byte[] sig = pssSign.GenerateSignature();
+
+            pssSign.Init(false, pubParams);
+
+            pssSign.UpdateWithRecoveredMessage(sig);
+
+            if (!pssSign.VerifySignature(sig))
+            {
+                Fail("challenge PSS sig verification failed.");
+            }
+
+            byte[] mm = pssSign.GetRecoveredMessage();
+
+            if (!Arrays.AreEqual(challenge, mm))
+            {
+                Fail("challenge partial PSS recovery failed");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            DoTest1();
+            DoTest2();
+            DoTest3();
+            DoTest4();
+            DoTest5();
+            DoTest6();
+            DoTest7();
+            DoTest8();
+            DoTest9();
+            DoTest10();
+            DoTest11();
+            DoTest12();
+            DoTest13();
+            DoShortPartialTest();
+            DoFullMessageTest();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ISO9796Test());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9797Alg3MacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9797Alg3MacTest.cs
new file mode 100644
index 0000000..9d5d8b6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ISO9797Alg3MacTest.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class ISO9797Alg3MacTest
+		: SimpleTest
+	{
+		static byte[] keyBytes = Hex.Decode("7CA110454A1A6E570131D9619DC1376E");
+		static byte[] ivBytes = Hex.Decode("0000000000000000");
+
+		static byte[] input1 = Encoding.ASCII.GetBytes("Hello World !!!!");
+
+		static byte[] output1 = Hex.Decode("F09B856213BAB83B");
+
+		public ISO9797Alg3MacTest()
+		{
+		}
+
+		public override void PerformTest()
+		{
+			KeyParameter key = new KeyParameter(keyBytes);
+			IBlockCipher cipher = new DesEngine();
+			IMac mac = new ISO9797Alg3Mac(cipher);
+
+			//
+			// standard DAC - zero IV
+			//
+			mac.Init(key);
+
+			mac.BlockUpdate(input1, 0, input1.Length);
+
+			byte[] outBytes = new byte[8];
+
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output1))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			//  reset
+			//
+			mac.Reset();
+
+			mac.Init(key);
+
+			for (int i = 0; i != input1.Length / 2; i++)
+			{
+				mac.Update(input1[i]);
+			}
+
+			mac.BlockUpdate(input1, input1.Length / 2, input1.Length - (input1.Length / 2));
+
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output1))
+			{
+				Fail("Reset failed - expected " + Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes));
+			}
+		}
+
+		public override string Name
+		{
+			get
+			{
+				return "ISO9797Alg3Mac";
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ISO9797Alg3MacTest test = new ISO9797Alg3MacTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/KDF1GeneratorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/KDF1GeneratorTest.cs
new file mode 100644
index 0000000..89c8d54
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/KDF1GeneratorTest.cs
@@ -0,0 +1,103 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * KDF1 tests - vectors from ISO 18033.
+	 */
+	[TestFixture]
+	public class Kdf1GeneratorTest
+		: SimpleTest
+	{
+		private byte[] seed1 = Hex.Decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+		private byte[] mask1 = Hex.Decode(
+			"0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
+			+ "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
+			+ "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
+			+ "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
+
+		private byte[] seed2 = Hex.Decode(
+			"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+			+ "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+		private byte[] mask2 = Hex.Decode(
+			"5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
+			+ "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
+			+ "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
+			+ "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
+
+		private byte[] seed3;
+		private byte[] mask3= Hex.Decode(
+			"09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
+			+ "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
+			+ "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
+			+ "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
+
+		public Kdf1GeneratorTest()
+		{
+			seed3 = seed2;
+		}
+
+		public override void PerformTest()
+		{
+			checkMask(1, new Kdf1BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed1, mask1);
+			checkMask(2, new Kdf1BytesGenerator(new Sha1Digest()), seed2, mask2);
+			checkMask(3, new Kdf1BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed3, mask3);
+
+			try
+			{
+				new Kdf1BytesGenerator(new Sha1Digest()).GenerateBytes(new byte[10], 0, 20);
+
+				Fail("short input array not caught");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+		}
+
+		private void checkMask(
+			int					count,
+			IDerivationFunction	kdf,
+			byte[]				seed,
+			byte[]				result)
+		{
+			byte[] data = new byte[result.Length];
+
+			kdf.Init(new Iso18033KdfParameters(seed));
+
+			kdf.GenerateBytes(data, 0, data.Length);
+
+			if (!AreEqual(result, data))
+			{
+				Fail("KDF1 failed generator test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "KDF1"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Kdf1GeneratorTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/KDF2GeneratorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/KDF2GeneratorTest.cs
new file mode 100644
index 0000000..e184e0b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/KDF2GeneratorTest.cs
@@ -0,0 +1,115 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* KDF2 tests - vectors from ISO 18033.
+	*/
+	[TestFixture]
+	public class Kdf2GeneratorTest
+		: SimpleTest
+	{
+		private static readonly byte[] seed1 = Hex.Decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+		private static readonly byte[] mask1 = Hex.Decode(
+			"df79665bc31dc5a62f70535e52c53015b9d37d412ff3c119343959"
+			+ "9e1b628774c50d9ccb78d82c425e4521ee47b8c36a4bcffe8b8112a8"
+			+ "9312fc04420a39de99223890e74ce10378bc515a212b97b8a6447ba6"
+			+ "a8870278f0262727ca041fa1aa9f7b5d1cf7f308232fe861");
+
+		private static readonly byte[] seed2 = Hex.Decode(
+			"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+			+ "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+		private static readonly byte[] mask2 = Hex.Decode(
+			"10a2403db42a8743cb989de86e668d168cbe604611ac179f819a3d18412e9eb456"
+			+ "68f2923c087c12fee0c5a0d2a8aa70185401fbbd99379ec76c663e875a60b4aacb13"
+			+ "19fa11c3365a8b79a44669f26fb555c80391847b05eca1cb5cf8c2d531448d33fbac"
+			+ "a19f6410ee1fcb260892670e0814c348664f6a7248aaf998a3acc6");
+		private static readonly byte[] adjustedMask2 = Hex.Decode(
+			"10a2403db42a8743cb989de86e668d168cbe6046e23ff26f741e87949a3bba1311ac1"
+			+ "79f819a3d18412e9eb45668f2923c087c1299005f8d5fd42ca257bc93e8fee0c5a0d2"
+			+ "a8aa70185401fbbd99379ec76c663e9a29d0b70f3fe261a59cdc24875a60b4aacb131"
+			+ "9fa11c3365a8b79a44669f26fba933d012db213d7e3b16349");
+
+		private static readonly byte[] sha1Mask = Hex.Decode(
+			"0e6a26eb7b956ccb8b3bdc1ca975bc57c3989e8fbad31a224655d800c46954840ff32"
+			+ "052cdf0d640562bdfadfa263cfccf3c52b29f2af4a1869959bc77f854cf15bd7a2519"
+			+ "2985a842dbff8e13efee5b7e7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837ee"
+			+ "a4e0a2f04b53ca8f50fb31225c1be2d0126c8c7a4753b0807");
+
+		private static readonly byte[] seed3 = Hex.Decode("CA7C0F8C3FFA87A96E1B74AC8E6AF594347BB40A");
+		private static readonly byte[] mask3 = Hex.Decode("744AB703F5BC082E59185F6D049D2D367DB245C2");
+
+		private static readonly byte[] seed4 = Hex.Decode("0499B502FC8B5BAFB0F4047E731D1F9FD8CD0D8881");
+		private static readonly byte[] mask4 = Hex.Decode("03C62280C894E103C680B13CD4B4AE740A5EF0C72547292F82DC6B1777F47D63BA9D1EA732DBF386");
+
+		public Kdf2GeneratorTest()
+		{
+		}
+
+		public override void PerformTest()
+		{
+			checkMask(1, new Kdf2BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed1, mask1);
+			checkMask(2, new Kdf2BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed2, mask2);
+			checkMask(3, new Kdf2BytesGenerator(new Sha256Digest()), seed2, adjustedMask2);
+			checkMask(4, new Kdf2BytesGenerator(new Sha1Digest()), seed2, sha1Mask);
+			checkMask(5, new Kdf2BytesGenerator(new Sha1Digest()), seed3, mask3);
+			checkMask(6, new Kdf2BytesGenerator(new Sha1Digest()), seed4, mask4);
+
+			try
+			{
+				new Kdf2BytesGenerator(new Sha1Digest()).GenerateBytes(new byte[10], 0, 20);
+
+				Fail("short input array not caught");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+		}
+
+		private void checkMask(
+			int					count,
+			IDerivationFunction	kdf,
+			byte[]				seed,
+			byte[]				result)
+		{
+			byte[] data = new byte[result.Length];
+
+			kdf.Init(new KdfParameters(seed, new byte[0]));
+
+			kdf.GenerateBytes(data, 0, data.Length);
+
+			if (!AreEqual(result, data))
+			{
+				Fail("KDF2 failed generator test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "KDF2"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Kdf2GeneratorTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MD2DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MD2DigestTest.cs
new file mode 100644
index 0000000..4f4da51
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MD2DigestTest.cs
@@ -0,0 +1,67 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for MD2
+     * from RFC1319 by B.Kaliski of RSA Laboratories April 1992
+     *
+     */
+    [TestFixture]
+    public class MD2DigestTest
+        : DigestTest
+    {
+        static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "message digest",
+            "abcdefghijklmnopqrstuvwxyz",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+            "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+        };
+
+        static string[] digests =
+        { 
+            "8350e5a3e24c153df2275c9f80692773",
+            "32ec01ec4a6dac72c0ab96fb34c0b5d1",
+            "da853b0d3f88d99b30283a69e6ded6bb",
+            "ab4f496bfb2a530b219ff33031fe06b0",
+            "4e8ddff3650292ab5a4108c3aa47940b",
+            "da33def2a42df13975352846c30338cd",
+            "d5976f79d83d3a0dc9806c3c66f3efd8" 
+        };
+
+        public MD2DigestTest()
+            : base(new MD2Digest(), messages, digests)
+        {
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new MD2Digest((MD2Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new MD2DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MD4DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MD4DigestTest.cs
new file mode 100644
index 0000000..4fd4e09
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MD4DigestTest.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for MD4 from RFC 1320.
+     */
+    [TestFixture]
+    public class MD4DigestTest
+        : DigestTest
+    {
+        static private string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+        };
+
+        static private string[] digests =
+        {
+            "31d6cfe0d16ae931b73c59d7e0c089c0",
+            "bde52cb31de33e46245e05fbdbd6fb24",
+            "a448017aaf21d8525fc10ae87aa6729d",
+            "e33b4ddc9c38f2199c3e7b164fcc0536"
+        };
+
+        public MD4DigestTest()
+            : base(new MD4Digest(), messages, digests)
+        {
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new MD4Digest((MD4Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new MD4DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MD5DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MD5DigestTest.cs
new file mode 100644
index 0000000..cc91416
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MD5DigestTest.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for MD5 from "Handbook of Applied Cryptography", page 345.
+     */
+    [TestFixture]
+    public class MD5DigestTest
+        : DigestTest
+    {
+        static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "abcdefghijklmnopqrstuvwxyz"
+        };
+
+        static string[] digests =
+        {
+            "d41d8cd98f00b204e9800998ecf8427e",
+            "0cc175b9c0f1b6a831c399e269772661",
+            "900150983cd24fb0d6963f7d28e17f72",
+            "c3fcd3d76192e4007dfb496cca67e13b"
+        };
+
+        public MD5DigestTest()
+            : base(new MD5Digest(), messages, digests)
+        {
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new MD5Digest((MD5Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new MD5DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MD5HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MD5HMacTest.cs
new file mode 100644
index 0000000..101b8be
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MD5HMacTest.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks> MD5 HMac Test, test vectors from RFC 2202</remarks>
+    [TestFixture]
+    public class MD5HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "MD5HMac"; }
+        }
+
+		internal static readonly string[] keys = new string[]{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "0102030405060708090a0b0c0d0e0f10111213141516171819", "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [...]
+        internal static readonly string[] digests = new string[]{"9294727a3638bb1c13f48ef8158bfc9d", "750c783e6ab0b503eaa86e310a5db738", "56be34521d144c88dbb8c733f0e8b3f6", "697eaf0aca3a3aea3a75164746ffaa79", "56461ef2342edc00f9bab995690efd4c", "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd", "6f630fad67cda0ee1fb1f562db3aa53e"};
+        internal static readonly string[] messages = new string[]{"Hi There", "what do ya want for nothing?", "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "Test With Truncation", "Test Using Larger Than Block-Size Key - Hash Key First", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"};
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new MD5Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+			for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + "Vector " + i + " failed");
+                }
+            }
+
+			// test reset
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+			if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+			return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new MD5HMacTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MGF1GeneratorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MGF1GeneratorTest.cs
new file mode 100644
index 0000000..ee67ffa
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MGF1GeneratorTest.cs
@@ -0,0 +1,103 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * MGF1 tests - vectors from ISO 18033 for KDF1 (equivalent).
+	 */
+	[TestFixture]
+	public class Mgf1GeneratorTest
+		: SimpleTest
+	{
+		private byte[] seed1 = Hex.Decode("d6e168c5f256a2dcff7ef12facd390f393c7a88d");
+		private byte[] mask1 = Hex.Decode(
+			"0742ba966813af75536bb6149cc44fc256fd6406df79665bc31dc5"
+			+ "a62f70535e52c53015b9d37d412ff3c1193439599e1b628774c50d9c"
+			+ "cb78d82c425e4521ee47b8c36a4bcffe8b8112a89312fc04420a39de"
+			+ "99223890e74ce10378bc515a212b97b8a6447ba6a8870278");
+
+		private byte[] seed2 = Hex.Decode(
+			"032e45326fa859a72ec235acff929b15d1372e30b207255f0611b8f785d7643741"
+			+ "52e0ac009e509e7ba30cd2f1778e113b64e135cf4e2292c75efe5288edfda4");
+		private byte[] mask2 = Hex.Decode(
+			"5f8de105b5e96b2e490ddecbd147dd1def7e3b8e0e6a26eb7b956ccb8b3bdc1ca9"
+			+ "75bc57c3989e8fbad31a224655d800c46954840ff32052cdf0d640562bdfadfa263c"
+			+ "fccf3c52b29f2af4a1869959bc77f854cf15bd7a25192985a842dbff8e13efee5b7e"
+			+ "7e55bbe4d389647c686a9a9ab3fb889b2d7767d3837eea4e0a2f04");
+
+		private byte[] seed3;
+		private byte[] mask3= Hex.Decode(
+			"09e2decf2a6e1666c2f6071ff4298305e2643fd510a2403db42a8743cb989de86e"
+			+ "668d168cbe604611ac179f819a3d18412e9eb45668f2923c087c12fee0c5a0d2a8aa"
+			+ "70185401fbbd99379ec76c663e875a60b4aacb1319fa11c3365a8b79a44669f26fb5"
+			+ "55c80391847b05eca1cb5cf8c2d531448d33fbaca19f6410ee1fcb");
+
+		public Mgf1GeneratorTest()
+		{
+			seed3 = seed2;
+		}
+
+		public override void PerformTest()
+		{
+			checkMask(1, new Mgf1BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed1, mask1);
+			checkMask(2, new Mgf1BytesGenerator(new Sha1Digest()), seed2, mask2);
+			checkMask(3, new Mgf1BytesGenerator(new ShortenedDigest(new Sha256Digest(), 20)), seed3, mask3);
+
+			try
+			{
+				new Mgf1BytesGenerator(new Sha1Digest()).GenerateBytes(new byte[10], 0, 20);
+
+				Fail("short input array not caught");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+		}
+
+		private void checkMask(
+			int                count,
+			IDerivationFunction kdf,
+			byte[]             seed,
+			byte[]             result)
+		{
+			byte[]             data = new byte[result.Length];
+
+			kdf.Init(new MgfParameters(seed));
+
+			kdf.GenerateBytes(data, 0, data.Length);
+
+			if (!AreEqual(result, data))
+			{
+				Fail("MGF1 failed generator test " + count);
+			}
+		}
+
+		public override string Name
+		{
+			get { return "MGF1"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Mgf1GeneratorTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/MacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/MacTest.cs
new file mode 100644
index 0000000..9a58f8a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/MacTest.cs
@@ -0,0 +1,214 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks> MAC tester - vectors from
+    /// <a href="http://www.itl.nist.gov/fipspubs/fip81.htm">FIP 81</a> and
+    /// <a href="http://www.itl.nist.gov/fipspubs/fip113.htm">FIP 113</a>.
+    /// </remarks>
+    [TestFixture]
+    public class MacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "IMac"; }
+        }
+
+		internal static byte[] keyBytes;
+        internal static byte[] ivBytes;
+        internal static byte[] input1;
+        internal static byte[] output1;
+        internal static byte[] output2;
+        internal static byte[] output3;
+
+        //
+        // these aren't NIST vectors, just for regression testing.
+        //
+        internal static byte[] input2;
+        internal static byte[] output4;
+        internal static byte[] output5;
+        internal static byte[] output6;
+
+        public MacTest()
+        {
+        }
+
+        public virtual ITestResult Perform()
+        {
+            KeyParameter key = new KeyParameter(keyBytes);
+            IBlockCipher cipher = new DesEngine();
+            IMac mac = new CbcBlockCipherMac(cipher);
+
+            //
+            // standard DAC - zero IV
+            //
+            mac.Init(key);
+
+            mac.BlockUpdate(input1, 0, input1.Length);
+
+            byte[] outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output1))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output1) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // mac with IV.
+            //
+            ParametersWithIV param = new ParametersWithIV(key, ivBytes);
+
+            mac.Init(param);
+
+            mac.BlockUpdate(input1, 0, input1.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output2))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output2) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // CFB mac with IV - 8 bit CFB mode
+            //
+            param = new ParametersWithIV(key, ivBytes);
+
+            mac = new CfbBlockCipherMac(cipher);
+
+            mac.Init(param);
+
+            mac.BlockUpdate(input1, 0, input1.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output3))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output3) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // word aligned data - zero IV
+            //
+            mac.Init(key);
+
+            mac.BlockUpdate(input2, 0, input2.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output4))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output4) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // word aligned data - zero IV - CBC padding
+            //
+            mac = new CbcBlockCipherMac(cipher, new Pkcs7Padding());
+
+            mac.Init(key);
+
+            mac.BlockUpdate(input2, 0, input2.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output5))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output5) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // non-word aligned data - zero IV - CBC padding
+            //
+            mac.Reset();
+
+            mac.BlockUpdate(input1, 0, input1.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output6))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output6) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            //
+            // non-word aligned data - zero IV - CBC padding
+            //
+            mac.Init(key);
+
+            mac.BlockUpdate(input1, 0, input1.Length);
+
+            outBytes = new byte[4];
+
+            mac.DoFinal(outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output6))
+            {
+                return new SimpleTestResult(false, Name + ": Failed - expected "
+					+ Hex.ToHexString(output6) + " got " + Hex.ToHexString(outBytes));
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            MacTest test = new MacTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        static MacTest()
+        {
+            keyBytes = Hex.Decode("0123456789abcdef");
+            ivBytes = Hex.Decode("1234567890abcdef");
+            input1 = Hex.Decode("37363534333231204e6f77206973207468652074696d6520666f7220");
+            output1 = Hex.Decode("f1d30f68");
+            output2 = Hex.Decode("58d2e77e");
+            output3 = Hex.Decode("cd647403");
+            input2 = Hex.Decode("3736353433323120");
+            output4 = Hex.Decode("3af549c9");
+            output5 = Hex.Decode("188fbdd5");
+            output6 = Hex.Decode("7045eecd");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ModeTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ModeTest.cs
new file mode 100644
index 0000000..c67dce0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ModeTest.cs
@@ -0,0 +1,108 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks> CFB/OFB Mode test of IV padding.</remarks>
+	[TestFixture]
+	public class ModeTest
+		: ITest
+	{
+		public string Name
+		{
+			get { return "ModeTest"; }
+		}
+
+		public ModeTest()
+		{
+		}
+
+		public virtual ITestResult Perform()
+		{
+			KeyParameter key = new KeyParameter(Hex.Decode("0011223344556677"));
+			byte[] input = Hex.Decode("4e6f7720");
+			byte[] out1 = new byte[4];
+			byte[] out2 = new byte[4];
+
+
+			IBlockCipher ofb = new OfbBlockCipher(new DesEngine(), 32);
+
+			ofb.Init(true, new ParametersWithIV(key, Hex.Decode("1122334455667788")));
+
+			ofb.ProcessBlock(input, 0, out1, 0);
+
+			ofb.Init(false, new ParametersWithIV(key, Hex.Decode("1122334455667788")));
+			ofb.ProcessBlock(out1, 0, out2, 0);
+
+			if (!Arrays.AreEqual(out2, input))
+			{
+				return new SimpleTestResult(false, Name + ": test 1 - in != out");
+			}
+
+			ofb.Init(true, new ParametersWithIV(key, Hex.Decode("11223344")));
+
+			ofb.ProcessBlock(input, 0, out1, 0);
+
+			ofb.Init(false, new ParametersWithIV(key, Hex.Decode("0000000011223344")));
+			ofb.ProcessBlock(out1, 0, out2, 0);
+
+			if (!Arrays.AreEqual(out2, input))
+			{
+				return new SimpleTestResult(false, Name + ": test 2 - in != out");
+			}
+
+			IBlockCipher cfb = new CfbBlockCipher(new DesEngine(), 32);
+
+			cfb.Init(true, new ParametersWithIV(key, Hex.Decode("1122334455667788")));
+
+			cfb.ProcessBlock(input, 0, out1, 0);
+
+			cfb.Init(false, new ParametersWithIV(key, Hex.Decode("1122334455667788")));
+			cfb.ProcessBlock(out1, 0, out2, 0);
+
+			if (!Arrays.AreEqual(out2, input))
+			{
+				return new SimpleTestResult(false, Name + ": test 3 - in != out");
+			}
+
+			cfb.Init(true, new ParametersWithIV(key, Hex.Decode("11223344")));
+
+			cfb.ProcessBlock(input, 0, out1, 0);
+
+			cfb.Init(false, new ParametersWithIV(key, Hex.Decode("0000000011223344")));
+			cfb.ProcessBlock(out1, 0, out2, 0);
+
+			if (!Arrays.AreEqual(out2, input))
+			{
+				return new SimpleTestResult(false, Name + ": test 4 - in != out");
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new ModeTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/NaccacheSternTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/NaccacheSternTest.cs
new file mode 100644
index 0000000..faa8450
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/NaccacheSternTest.cs
@@ -0,0 +1,354 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * Test case for NaccacheStern cipher. For details on this cipher, please see
+	 *
+	 * http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf
+	 *
+	 * Performs the following tests:
+	 *  <ul>
+	 *  <li> Toy example from the NaccacheSternPaper </li>
+	 *  <li> 768 bit test with text "Now is the time for all good men." (ripped from RSA test) and
+	 *     the same test with the first byte replaced by 0xFF </li>
+	 *  <li> 1024 bit test analog to 768 bit test </li>
+	 *  </ul>
+	 */
+	[TestFixture, Explicit]
+	public class NaccacheSternTest
+		: SimpleTest
+	{
+		static bool debug = false;
+
+		static readonly NaccacheSternEngine cryptEng = new NaccacheSternEngine();
+		static readonly NaccacheSternEngine decryptEng = new NaccacheSternEngine();
+
+		static NaccacheSternTest()
+		{
+			cryptEng.Debug = debug;
+			decryptEng.Debug = debug;
+		}
+
+		// Values from NaccacheStern paper
+		static readonly BigInteger a = BigInteger.ValueOf(101);
+		static readonly BigInteger u1 = BigInteger.ValueOf(3);
+		static readonly BigInteger u2 = BigInteger.ValueOf(5);
+		static readonly BigInteger u3 = BigInteger.ValueOf(7);
+		static readonly BigInteger b = BigInteger.ValueOf(191);
+		static readonly BigInteger v1 = BigInteger.ValueOf(11);
+		static readonly BigInteger v2 = BigInteger.ValueOf(13);
+		static readonly BigInteger v3 = BigInteger.ValueOf(17);
+
+		static readonly BigInteger sigma
+			= u1.Multiply(u2).Multiply(u3).Multiply(v1).Multiply(v2).Multiply(v3);
+
+		static readonly BigInteger p
+			= BigInteger.Two.Multiply(a).Multiply(u1).Multiply(u2).Multiply(u3).Add(BigInteger.One);
+
+		static readonly BigInteger q
+			= BigInteger.Two.Multiply(b).Multiply(v1).Multiply(v2).Multiply(v3).Add(BigInteger.One);
+
+		static readonly BigInteger n = p.Multiply(q);
+
+		static readonly BigInteger phi_n
+			= p.Subtract(BigInteger.One).Multiply(q.Subtract(BigInteger.One));
+
+		static readonly BigInteger g = BigInteger.ValueOf(131);
+
+		static readonly IList smallPrimes = new ArrayList();
+
+		// static final BigInteger paperTest = BigInteger.ValueOf(202);
+
+		static readonly string input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		static readonly BigInteger paperTest = BigInteger.ValueOf(202);
+
+		//
+		// to check that we handling byte extension by big number correctly.
+		//
+		static readonly string edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		public override string Name
+		{
+			get { return "NaccacheStern"; }
+		}
+
+		public override void PerformTest()
+		{
+			// Test with given key from NaccacheSternPaper (totally insecure)
+
+			// First the Parameters from the NaccacheStern Paper
+			// (see http://www.gemplus.com/smart/rd/publications/pdf/NS98pkcs.pdf )
+
+			smallPrimes.Add(u1);
+			smallPrimes.Add(u2);
+			smallPrimes.Add(u3);
+			smallPrimes.Add(v1);
+			smallPrimes.Add(v2);
+			smallPrimes.Add(v3);
+
+			NaccacheSternKeyParameters pubParameters = new NaccacheSternKeyParameters(false, g, n, sigma.BitLength);
+
+			NaccacheSternPrivateKeyParameters privParameters = new NaccacheSternPrivateKeyParameters(g, n, sigma
+				.BitLength, smallPrimes, phi_n);
+
+			AsymmetricCipherKeyPair pair = new AsymmetricCipherKeyPair(pubParameters, privParameters);
+
+			// Initialize Engines with KeyPair
+
+			if (debug)
+			{
+				Console.WriteLine("initializing encryption engine");
+			}
+			cryptEng.Init(true, pair.Public);
+
+			if (debug)
+			{
+				Console.WriteLine("initializing decryption engine");
+			}
+			decryptEng.Init(false, pair.Private);
+
+			byte[] data = paperTest.ToByteArray();
+
+			if (!new BigInteger(data).Equals(new BigInteger(enDeCrypt(data))))
+			{
+				Fail("failed NaccacheStern paper test");
+			}
+
+			//
+			// key generation test
+			//
+
+			//
+			// 768 Bit test
+			//
+
+			if (debug)
+			{
+				Console.WriteLine();
+				Console.WriteLine("768 Bit TEST");
+			}
+
+			// specify key generation parameters
+			NaccacheSternKeyGenerationParameters genParam
+				= new NaccacheSternKeyGenerationParameters(new SecureRandom(), 768, 8, 30, debug);
+
+			// Initialize Key generator and generate key pair
+			NaccacheSternKeyPairGenerator pGen = new NaccacheSternKeyPairGenerator();
+			pGen.Init(genParam);
+
+			pair = pGen.GenerateKeyPair();
+
+			if (((NaccacheSternKeyParameters)pair.Public).Modulus.BitLength < 768)
+			{
+				Console.WriteLine("FAILED: key size is <786 bit, exactly "
+						   + ((NaccacheSternKeyParameters)pair.Public).Modulus.BitLength + " bit");
+				Fail("failed key generation (768) length test");
+			}
+
+			// Initialize Engines with KeyPair
+
+			if (debug)
+			{
+				Console.WriteLine("initializing " + genParam.Strength + " bit encryption engine");
+			}
+			cryptEng.Init(true, pair.Public);
+
+			if (debug)
+			{
+				Console.WriteLine("initializing " + genParam.Strength + " bit decryption engine");
+			}
+			decryptEng.Init(false, pair.Private);
+
+			// Basic data input
+			data = Hex.Decode(input);
+
+			if (!new BigInteger(1, data).Equals(new BigInteger(1, enDeCrypt(data))))
+			{
+				Fail("failed encryption decryption (" + genParam.Strength + ") basic test");
+			}
+
+			// Data starting with FF byte (would be interpreted as negative
+			// BigInteger)
+
+			data = Hex.Decode(edgeInput);
+
+			if (!new BigInteger(1, data).Equals(new BigInteger(1, enDeCrypt(data))))
+			{
+				Fail("failed encryption decryption (" + genParam.Strength + ") edgeInput test");
+			}
+
+			//
+			// 1024 Bit Test
+			//
+			/*
+					if (debug)
+					{
+						Console.WriteLine();
+						Console.WriteLine("1024 Bit TEST");
+					}
+
+					// specify key generation parameters
+					genParam = new NaccacheSternKeyGenerationParameters(new SecureRandom(), 1024, 8, 40, debug);
+
+					pGen.Init(genParam);
+					pair = pGen.generateKeyPair();
+
+					if (((NaccacheSternKeyParameters)pair.Public).getModulus().bitLength() < 1024)
+					{
+						if (debug)
+						{
+							Console.WriteLine("FAILED: key size is <1024 bit, exactly "
+											+ ((NaccacheSternKeyParameters)pair.Public).getModulus().bitLength() + " bit");
+						}
+						Fail("failed key generation (1024) length test");
+					}
+
+					// Initialize Engines with KeyPair
+
+					if (debug)
+					{
+						Console.WriteLine("initializing " + genParam.getStrength() + " bit encryption engine");
+					}
+					cryptEng.Init(true, pair.Public);
+
+					if (debug)
+					{
+						Console.WriteLine("initializing " + genParam.getStrength() + " bit decryption engine");
+					}
+					decryptEng.Init(false, pair.Private);
+
+					if (debug)
+					{
+						Console.WriteLine("Data is           " + new BigInteger(1, data));
+					}
+
+					// Basic data input
+					data = Hex.Decode(input);
+
+					if (!new BigInteger(1, data).Equals(new BigInteger(1, enDeCrypt(data))))
+					{
+						Fail("failed encryption decryption (" + genParam.getStrength() + ") basic test");
+					}
+
+					// Data starting with FF byte (would be interpreted as negative
+					// BigInteger)
+
+					data = Hex.Decode(edgeInput);
+
+					if (!new BigInteger(1, data).Equals(new BigInteger(1, enDeCrypt(data))))
+					{
+						Fail("failed encryption decryption (" + genParam.getStrength() + ") edgeInput test");
+					}
+			*/
+			// END OF TEST CASE
+
+			try
+			{
+				new NaccacheSternEngine().ProcessBlock(new byte[]{ 1 }, 0, 1);
+				Fail("failed initialisation check");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+
+			if (debug)
+			{
+				Console.WriteLine("All tests successful");
+			}
+		}
+
+		private byte[] enDeCrypt(
+			byte[] input)
+		{
+			// create work array
+			byte[] data = new byte[input.Length];
+			Array.Copy(input, 0, data, 0, data.Length);
+
+			// Perform encryption like in the paper from Naccache-Stern
+			if (debug)
+			{
+				Console.WriteLine("encrypting data. Data representation\n"
+					//                    + "As string:.... " + new string(data) + "\n"
+					+ "As BigInteger: " + new BigInteger(1, data));
+				Console.WriteLine("data length is " + data.Length);
+			}
+
+			try
+			{
+				data = cryptEng.ProcessData(data);
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (debug)
+				{
+					Console.WriteLine("failed - exception " + e + "\n" + e.Message);
+				}
+				Fail("failed - exception " + e + "\n" + e.Message);
+			}
+
+			if (debug)
+			{
+				Console.WriteLine("enrypted data representation\n"
+						   //                    + "As string:.... " + new string(data) + "\n"
+						   + "As BigInteger: " + new BigInteger(1, data));
+				Console.WriteLine("data length is " + data.Length);
+			}
+
+			try
+			{
+				data = decryptEng.ProcessData(data);
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (debug)
+				{
+					Console.WriteLine("failed - exception " + e + "\n" + e.Message);
+				}
+				Fail("failed - exception " + e + "\n" + e.Message);
+			}
+
+			if (debug)
+			{
+				Console.WriteLine("decrypted data representation\n"
+					//                    + "As string:.... " + new string(data) + "\n"
+					+ "As BigInteger: " + new BigInteger(1, data));
+				Console.WriteLine("data length is " + data.Length);
+			}
+
+			return data;
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new NaccacheSternTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/NoekeonTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/NoekeonTest.cs
new file mode 100644
index 0000000..b6fff70
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/NoekeonTest.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Noekeon tester
+	*/
+	[TestFixture]
+	public class NoekeonTest
+		: CipherTest
+	{
+		private static readonly SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new NoekeonEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"00000000000000000000000000000000",
+				"b1656851699e29fa24b70148503d2dfc"),
+			new BlockCipherVectorTest(1, new NoekeonEngine(),
+				new KeyParameter(Hex.Decode("ffffffffffffffffffffffffffffffff")),
+				"ffffffffffffffffffffffffffffffff",
+				"2a78421b87c7d0924f26113f1d1349b2"),
+			new BlockCipherVectorTest(2, new NoekeonEngine(),
+				new KeyParameter(Hex.Decode("b1656851699e29fa24b70148503d2dfc")),
+				"2a78421b87c7d0924f26113f1d1349b2",
+				"e2f687e07b75660ffc372233bc47532c")
+		};
+
+		public NoekeonTest()
+			: base(tests, new NoekeonEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Noekeon"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NoekeonTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/NullTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/NullTest.cs
new file mode 100644
index 0000000..16a5180
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/NullTest.cs
@@ -0,0 +1,88 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class NullTest
+		: CipherTest
+	{
+		static SimpleTest[]  tests =
+		{
+			new BlockCipherVectorTest(0, new NullEngine(),
+					new KeyParameter(Hex.Decode("00")), "00", "00")
+		};
+
+		public NullTest()
+			: base(tests, new NullEngine(), new KeyParameter(new byte[2]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Null"; }
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			IBlockCipher engine = new NullEngine();
+
+			engine.Init(true, null);
+
+			byte[] buf = new byte[1];
+
+			engine.ProcessBlock(buf, 0, buf, 0);
+
+			if (buf[0] != 0)
+			{
+				Fail("NullCipher changed data!");
+			}
+
+			byte[] shortBuf = new byte[0];
+
+			try
+			{
+				engine.ProcessBlock(shortBuf, 0, buf, 0);
+
+				Fail("failed short input check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+
+			try
+			{
+				engine.ProcessBlock(buf, 0, shortBuf, 0);
+
+				Fail("failed short output check");
+			}
+			catch (DataLengthException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NullTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/OAEPTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/OAEPTest.cs
new file mode 100644
index 0000000..b4c375e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/OAEPTest.cs
@@ -0,0 +1,798 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class OaepTest
+        : SimpleTest
+    {
+        private static readonly byte[] pubKeyEnc1 =
+        {
+            (byte)0x30, (byte)0x5a, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
+            (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
+            (byte)0x00, (byte)0x03, (byte)0x49, (byte)0x00, (byte)0x30, (byte)0x46, (byte)0x02, (byte)0x41,
+            (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce, (byte)0x88, (byte)0xac, (byte)0xfd,
+            (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f, (byte)0xc4, (byte)0x52, (byte)0x3f,
+            (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3, (byte)0x77, (byte)0x4a, (byte)0x25,
+            (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5, (byte)0xd9, (byte)0x9c, (byte)0xb5,
+            (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28, (byte)0x5e, (byte)0x53, (byte)0x01,
+            (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb, (byte)0x68, (byte)0x76, (byte)0x93,
+            (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62, (byte)0x4a, (byte)0x11, (byte)0xe0,
+            (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc, (byte)0xac, (byte)0xa0, (byte)0xa1,
+            (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11
+        };
+
+        private static readonly byte[] privKeyEnc1 =
+        {
+            (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x52, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+            (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+            (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
+            (byte)0x01, (byte)0x3c, (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x38, (byte)0x02, (byte)0x01,
+            (byte)0x00, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xaa, (byte)0x36, (byte)0xab, (byte)0xce,
+            (byte)0x88, (byte)0xac, (byte)0xfd, (byte)0xff, (byte)0x55, (byte)0x52, (byte)0x3c, (byte)0x7f,
+            (byte)0xc4, (byte)0x52, (byte)0x3f, (byte)0x90, (byte)0xef, (byte)0xa0, (byte)0x0d, (byte)0xf3,
+            (byte)0x77, (byte)0x4a, (byte)0x25, (byte)0x9f, (byte)0x2e, (byte)0x62, (byte)0xb4, (byte)0xc5,
+            (byte)0xd9, (byte)0x9c, (byte)0xb5, (byte)0xad, (byte)0xb3, (byte)0x00, (byte)0xa0, (byte)0x28,
+            (byte)0x5e, (byte)0x53, (byte)0x01, (byte)0x93, (byte)0x0e, (byte)0x0c, (byte)0x70, (byte)0xfb,
+            (byte)0x68, (byte)0x76, (byte)0x93, (byte)0x9c, (byte)0xe6, (byte)0x16, (byte)0xce, (byte)0x62,
+            (byte)0x4a, (byte)0x11, (byte)0xe0, (byte)0x08, (byte)0x6d, (byte)0x34, (byte)0x1e, (byte)0xbc,
+            (byte)0xac, (byte)0xa0, (byte)0xa1, (byte)0xf5, (byte)0x02, (byte)0x01, (byte)0x11, (byte)0x02,
+            (byte)0x40, (byte)0x0a, (byte)0x03, (byte)0x37, (byte)0x48, (byte)0x62, (byte)0x64, (byte)0x87,
+            (byte)0x69, (byte)0x5f, (byte)0x5f, (byte)0x30, (byte)0xbc, (byte)0x38, (byte)0xb9, (byte)0x8b,
+            (byte)0x44, (byte)0xc2, (byte)0xcd, (byte)0x2d, (byte)0xff, (byte)0x43, (byte)0x40, (byte)0x98,
+            (byte)0xcd, (byte)0x20, (byte)0xd8, (byte)0xa1, (byte)0x38, (byte)0xd0, (byte)0x90, (byte)0xbf,
+            (byte)0x64, (byte)0x79, (byte)0x7c, (byte)0x3f, (byte)0xa7, (byte)0xa2, (byte)0xcd, (byte)0xcb,
+            (byte)0x3c, (byte)0xd1, (byte)0xe0, (byte)0xbd, (byte)0xba, (byte)0x26, (byte)0x54, (byte)0xb4,
+            (byte)0xf9, (byte)0xdf, (byte)0x8e, (byte)0x8a, (byte)0xe5, (byte)0x9d, (byte)0x73, (byte)0x3d,
+            (byte)0x9f, (byte)0x33, (byte)0xb3, (byte)0x01, (byte)0x62, (byte)0x4a, (byte)0xfd, (byte)0x1d,
+            (byte)0x51, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xd8, (byte)0x40, (byte)0xb4, (byte)0x16,
+            (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4,
+            (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52,
+            (byte)0x4d, (byte)0x04, (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00,
+            (byte)0xaf, (byte)0x46, (byte)0x12, (byte)0x0d, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0xc9,
+            (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4, (byte)0x53, (byte)0xf6, (byte)0x34,
+            (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1, (byte)0xd9, (byte)0x35, (byte)0x3f,
+            (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66, (byte)0xb1, (byte)0xd0, (byte)0x5a,
+            (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x89, (byte)0x02,
+            (byte)0x20, (byte)0x59, (byte)0x0b, (byte)0x95, (byte)0x72, (byte)0xa2, (byte)0xc2, (byte)0xa9,
+            (byte)0xc4, (byte)0x06, (byte)0x05, (byte)0x9d, (byte)0xc2, (byte)0xab, (byte)0x2f, (byte)0x1d,
+            (byte)0xaf, (byte)0xeb, (byte)0x7e, (byte)0x8b, (byte)0x4f, (byte)0x10, (byte)0xa7, (byte)0x54,
+            (byte)0x9e, (byte)0x8e, (byte)0xed, (byte)0xf5, (byte)0xb4, (byte)0xfc, (byte)0xe0, (byte)0x9e,
+            (byte)0x05, (byte)0x02, (byte)0x21, (byte)0x00, (byte)0x8e, (byte)0x3c, (byte)0x05, (byte)0x21,
+            (byte)0xfe, (byte)0x15, (byte)0xe0, (byte)0xea, (byte)0x06, (byte)0xa3, (byte)0x6f, (byte)0xf0,
+            (byte)0xf1, (byte)0x0c, (byte)0x99, (byte)0x52, (byte)0xc3, (byte)0x5b, (byte)0x7a, (byte)0x75,
+            (byte)0x14, (byte)0xfd, (byte)0x32, (byte)0x38, (byte)0xb8, (byte)0x0a, (byte)0xad, (byte)0x52,
+            (byte)0x98, (byte)0x62, (byte)0x8d, (byte)0x51, (byte)0x02, (byte)0x20, (byte)0x36, (byte)0x3f,
+            (byte)0xf7, (byte)0x18, (byte)0x9d, (byte)0xa8, (byte)0xe9, (byte)0x0b, (byte)0x1d, (byte)0x34,
+            (byte)0x1f, (byte)0x71, (byte)0xd0, (byte)0x9b, (byte)0x76, (byte)0xa8, (byte)0xa9, (byte)0x43,
+            (byte)0xe1, (byte)0x1d, (byte)0x10, (byte)0xb2, (byte)0x4d, (byte)0x24, (byte)0x9f, (byte)0x2d,
+            (byte)0xea, (byte)0xfe, (byte)0xf8, (byte)0x0c, (byte)0x18, (byte)0x26
+        };
+
+        private static readonly byte[] output1 = 
+        { 
+            (byte)0x1b, (byte)0x8f, (byte)0x05, (byte)0xf9, (byte)0xca, (byte)0x1a, (byte)0x79, (byte)0x52,
+            (byte)0x6e, (byte)0x53, (byte)0xf3, (byte)0xcc, (byte)0x51, (byte)0x4f, (byte)0xdb, (byte)0x89,
+            (byte)0x2b, (byte)0xfb, (byte)0x91, (byte)0x93, (byte)0x23, (byte)0x1e, (byte)0x78, (byte)0xb9,
+            (byte)0x92, (byte)0xe6, (byte)0x8d, (byte)0x50, (byte)0xa4, (byte)0x80, (byte)0xcb, (byte)0x52,
+            (byte)0x33, (byte)0x89, (byte)0x5c, (byte)0x74, (byte)0x95, (byte)0x8d, (byte)0x5d, (byte)0x02,
+            (byte)0xab, (byte)0x8c, (byte)0x0f, (byte)0xd0, (byte)0x40, (byte)0xeb, (byte)0x58, (byte)0x44,
+            (byte)0xb0, (byte)0x05, (byte)0xc3, (byte)0x9e, (byte)0xd8, (byte)0x27, (byte)0x4a, (byte)0x9d,
+            (byte)0xbf, (byte)0xa8, (byte)0x06, (byte)0x71, (byte)0x40, (byte)0x94, (byte)0x39, (byte)0xd2
+        };
+
+        private static readonly byte[] pubKeyEnc2 =
+        {
+            (byte)0x30, (byte)0x4c, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86,
+            (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05,
+            (byte)0x00, (byte)0x03, (byte)0x3b, (byte)0x00, (byte)0x30, (byte)0x38, (byte)0x02, (byte)0x33,
+            (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d, (byte)0xfd,
+            (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78, (byte)0xb8,
+            (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c, (byte)0x98,
+            (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b, (byte)0x26,
+            (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b, (byte)0x69,
+            (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b, (byte)0xe8,
+            (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03
+        };
+
+        private static readonly byte[] privKeyEnc2 =
+        {
+            (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x13, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+            (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+            (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x81,
+            (byte)0xfe, (byte)0x30, (byte)0x81, (byte)0xfb, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x02,
+            (byte)0x33, (byte)0x00, (byte)0xa3, (byte)0x07, (byte)0x9a, (byte)0x90, (byte)0xdf, (byte)0x0d,
+            (byte)0xfd, (byte)0x72, (byte)0xac, (byte)0x09, (byte)0x0c, (byte)0xcc, (byte)0x2a, (byte)0x78,
+            (byte)0xb8, (byte)0x74, (byte)0x13, (byte)0x13, (byte)0x3e, (byte)0x40, (byte)0x75, (byte)0x9c,
+            (byte)0x98, (byte)0xfa, (byte)0xf8, (byte)0x20, (byte)0x4f, (byte)0x35, (byte)0x8a, (byte)0x0b,
+            (byte)0x26, (byte)0x3c, (byte)0x67, (byte)0x70, (byte)0xe7, (byte)0x83, (byte)0xa9, (byte)0x3b,
+            (byte)0x69, (byte)0x71, (byte)0xb7, (byte)0x37, (byte)0x79, (byte)0xd2, (byte)0x71, (byte)0x7b,
+            (byte)0xe8, (byte)0x34, (byte)0x77, (byte)0xcf, (byte)0x02, (byte)0x01, (byte)0x03, (byte)0x02,
+            (byte)0x32, (byte)0x6c, (byte)0xaf, (byte)0xbc, (byte)0x60, (byte)0x94, (byte)0xb3, (byte)0xfe,
+            (byte)0x4c, (byte)0x72, (byte)0xb0, (byte)0xb3, (byte)0x32, (byte)0xc6, (byte)0xfb, (byte)0x25,
+            (byte)0xa2, (byte)0xb7, (byte)0x62, (byte)0x29, (byte)0x80, (byte)0x4e, (byte)0x68, (byte)0x65,
+            (byte)0xfc, (byte)0xa4, (byte)0x5a, (byte)0x74, (byte)0xdf, (byte)0x0f, (byte)0x8f, (byte)0xb8,
+            (byte)0x41, (byte)0x3b, (byte)0x52, (byte)0xc0, (byte)0xd0, (byte)0xe5, (byte)0x3d, (byte)0x9b,
+            (byte)0x59, (byte)0x0f, (byte)0xf1, (byte)0x9b, (byte)0xe7, (byte)0x9f, (byte)0x49, (byte)0xdd,
+            (byte)0x21, (byte)0xe5, (byte)0xeb, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0xcf, (byte)0x20,
+            (byte)0x35, (byte)0x02, (byte)0x8b, (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4,
+            (byte)0x16, (byte)0x66, (byte)0xb4, (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3,
+            (byte)0xb4, (byte)0x32, (byte)0x04, (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x91, (byte)0x02,
+            (byte)0x1a, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
+            (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
+            (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
+            (byte)0xb1, (byte)0xd0, (byte)0x5f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x8a, (byte)0x15,
+            (byte)0x78, (byte)0xac, (byte)0x5d, (byte)0x13, (byte)0xaf, (byte)0x10, (byte)0x2b, (byte)0x22,
+            (byte)0xb9, (byte)0x99, (byte)0xcd, (byte)0x74, (byte)0x61, (byte)0xf1, (byte)0x5e, (byte)0x6d,
+            (byte)0x22, (byte)0xcc, (byte)0x03, (byte)0x23, (byte)0xdf, (byte)0xdf, (byte)0x0b, (byte)0x02,
+            (byte)0x1a, (byte)0x00, (byte)0x86, (byte)0x55, (byte)0x21, (byte)0x4a, (byte)0xc5, (byte)0x4d,
+            (byte)0x8d, (byte)0x4e, (byte)0xcd, (byte)0x61, (byte)0x77, (byte)0xf1, (byte)0xc7, (byte)0x36,
+            (byte)0x90, (byte)0xce, (byte)0x2a, (byte)0x48, (byte)0x2c, (byte)0x8b, (byte)0x05, (byte)0x99,
+            (byte)0xcb, (byte)0xe0, (byte)0x3f, (byte)0x02, (byte)0x1a, (byte)0x00, (byte)0x83, (byte)0xef,
+            (byte)0xef, (byte)0xb8, (byte)0xa9, (byte)0xa4, (byte)0x0d, (byte)0x1d, (byte)0xb6, (byte)0xed,
+            (byte)0x98, (byte)0xad, (byte)0x84, (byte)0xed, (byte)0x13, (byte)0x35, (byte)0xdc, (byte)0xc1,
+            (byte)0x08, (byte)0xf3, (byte)0x22, (byte)0xd0, (byte)0x57, (byte)0xcf, (byte)0x8d
+        };
+
+        private static readonly byte[] output2 =
+        {
+            (byte)0x14, (byte)0xbd, (byte)0xdd, (byte)0x28, (byte)0xc9, (byte)0x83, (byte)0x35, (byte)0x19,
+            (byte)0x23, (byte)0x80, (byte)0xe8, (byte)0xe5, (byte)0x49, (byte)0xb1, (byte)0x58, (byte)0x2a,
+            (byte)0x8b, (byte)0x40, (byte)0xb4, (byte)0x48, (byte)0x6d, (byte)0x03, (byte)0xa6, (byte)0xa5,
+            (byte)0x31, (byte)0x1f, (byte)0x1f, (byte)0xd5, (byte)0xf0, (byte)0xa1, (byte)0x80, (byte)0xe4,
+            (byte)0x17, (byte)0x53, (byte)0x03, (byte)0x29, (byte)0xa9, (byte)0x34, (byte)0x90, (byte)0x74,
+            (byte)0xb1, (byte)0x52, (byte)0x13, (byte)0x54, (byte)0x29, (byte)0x08, (byte)0x24, (byte)0x52,
+            (byte)0x62, (byte)0x51
+        };
+
+        private static readonly byte[] pubKeyEnc3 =
+        {
+            (byte)0x30, (byte)0x81, (byte)0x9d, (byte)0x30, (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a,
+            (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7, (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01,
+            (byte)0x05, (byte)0x00, (byte)0x03, (byte)0x81, (byte)0x8b, (byte)0x00, (byte)0x30, (byte)0x81,
+            (byte)0x87, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
+            (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
+            (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
+            (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
+            (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
+            (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
+            (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
+            (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
+            (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
+            (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
+            (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
+            (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
+            (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
+            (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
+            (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
+            (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
+            (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11
+        };
+
+        private static readonly byte[] privKeyEnc3 =
+        {
+            (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x75, (byte)0x02, (byte)0x01, (byte)0x00, (byte)0x30,
+            (byte)0x0d, (byte)0x06, (byte)0x09, (byte)0x2a, (byte)0x86, (byte)0x48, (byte)0x86, (byte)0xf7,
+            (byte)0x0d, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x05, (byte)0x00, (byte)0x04, (byte)0x82,
+            (byte)0x02, (byte)0x5f, (byte)0x30, (byte)0x82, (byte)0x02, (byte)0x5b, (byte)0x02, (byte)0x01,
+            (byte)0x00, (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xbb, (byte)0xf8, (byte)0x2f,
+            (byte)0x09, (byte)0x06, (byte)0x82, (byte)0xce, (byte)0x9c, (byte)0x23, (byte)0x38, (byte)0xac,
+            (byte)0x2b, (byte)0x9d, (byte)0xa8, (byte)0x71, (byte)0xf7, (byte)0x36, (byte)0x8d, (byte)0x07,
+            (byte)0xee, (byte)0xd4, (byte)0x10, (byte)0x43, (byte)0xa4, (byte)0x40, (byte)0xd6, (byte)0xb6,
+            (byte)0xf0, (byte)0x74, (byte)0x54, (byte)0xf5, (byte)0x1f, (byte)0xb8, (byte)0xdf, (byte)0xba,
+            (byte)0xaf, (byte)0x03, (byte)0x5c, (byte)0x02, (byte)0xab, (byte)0x61, (byte)0xea, (byte)0x48,
+            (byte)0xce, (byte)0xeb, (byte)0x6f, (byte)0xcd, (byte)0x48, (byte)0x76, (byte)0xed, (byte)0x52,
+            (byte)0x0d, (byte)0x60, (byte)0xe1, (byte)0xec, (byte)0x46, (byte)0x19, (byte)0x71, (byte)0x9d,
+            (byte)0x8a, (byte)0x5b, (byte)0x8b, (byte)0x80, (byte)0x7f, (byte)0xaf, (byte)0xb8, (byte)0xe0,
+            (byte)0xa3, (byte)0xdf, (byte)0xc7, (byte)0x37, (byte)0x72, (byte)0x3e, (byte)0xe6, (byte)0xb4,
+            (byte)0xb7, (byte)0xd9, (byte)0x3a, (byte)0x25, (byte)0x84, (byte)0xee, (byte)0x6a, (byte)0x64,
+            (byte)0x9d, (byte)0x06, (byte)0x09, (byte)0x53, (byte)0x74, (byte)0x88, (byte)0x34, (byte)0xb2,
+            (byte)0x45, (byte)0x45, (byte)0x98, (byte)0x39, (byte)0x4e, (byte)0xe0, (byte)0xaa, (byte)0xb1,
+            (byte)0x2d, (byte)0x7b, (byte)0x61, (byte)0xa5, (byte)0x1f, (byte)0x52, (byte)0x7a, (byte)0x9a,
+            (byte)0x41, (byte)0xf6, (byte)0xc1, (byte)0x68, (byte)0x7f, (byte)0xe2, (byte)0x53, (byte)0x72,
+            (byte)0x98, (byte)0xca, (byte)0x2a, (byte)0x8f, (byte)0x59, (byte)0x46, (byte)0xf8, (byte)0xe5,
+            (byte)0xfd, (byte)0x09, (byte)0x1d, (byte)0xbd, (byte)0xcb, (byte)0x02, (byte)0x01, (byte)0x11,
+            (byte)0x02, (byte)0x81, (byte)0x81, (byte)0x00, (byte)0xa5, (byte)0xda, (byte)0xfc, (byte)0x53,
+            (byte)0x41, (byte)0xfa, (byte)0xf2, (byte)0x89, (byte)0xc4, (byte)0xb9, (byte)0x88, (byte)0xdb,
+            (byte)0x30, (byte)0xc1, (byte)0xcd, (byte)0xf8, (byte)0x3f, (byte)0x31, (byte)0x25, (byte)0x1e,
+            (byte)0x06, (byte)0x68, (byte)0xb4, (byte)0x27, (byte)0x84, (byte)0x81, (byte)0x38, (byte)0x01,
+            (byte)0x57, (byte)0x96, (byte)0x41, (byte)0xb2, (byte)0x94, (byte)0x10, (byte)0xb3, (byte)0xc7,
+            (byte)0x99, (byte)0x8d, (byte)0x6b, (byte)0xc4, (byte)0x65, (byte)0x74, (byte)0x5e, (byte)0x5c,
+            (byte)0x39, (byte)0x26, (byte)0x69, (byte)0xd6, (byte)0x87, (byte)0x0d, (byte)0xa2, (byte)0xc0,
+            (byte)0x82, (byte)0xa9, (byte)0x39, (byte)0xe3, (byte)0x7f, (byte)0xdc, (byte)0xb8, (byte)0x2e,
+            (byte)0xc9, (byte)0x3e, (byte)0xda, (byte)0xc9, (byte)0x7f, (byte)0xf3, (byte)0xad, (byte)0x59,
+            (byte)0x50, (byte)0xac, (byte)0xcf, (byte)0xbc, (byte)0x11, (byte)0x1c, (byte)0x76, (byte)0xf1,
+            (byte)0xa9, (byte)0x52, (byte)0x94, (byte)0x44, (byte)0xe5, (byte)0x6a, (byte)0xaf, (byte)0x68,
+            (byte)0xc5, (byte)0x6c, (byte)0x09, (byte)0x2c, (byte)0xd3, (byte)0x8d, (byte)0xc3, (byte)0xbe,
+            (byte)0xf5, (byte)0xd2, (byte)0x0a, (byte)0x93, (byte)0x99, (byte)0x26, (byte)0xed, (byte)0x4f,
+            (byte)0x74, (byte)0xa1, (byte)0x3e, (byte)0xdd, (byte)0xfb, (byte)0xe1, (byte)0xa1, (byte)0xce,
+            (byte)0xcc, (byte)0x48, (byte)0x94, (byte)0xaf, (byte)0x94, (byte)0x28, (byte)0xc2, (byte)0xb7,
+            (byte)0xb8, (byte)0x88, (byte)0x3f, (byte)0xe4, (byte)0x46, (byte)0x3a, (byte)0x4b, (byte)0xc8,
+            (byte)0x5b, (byte)0x1c, (byte)0xb3, (byte)0xc1, (byte)0x02, (byte)0x41, (byte)0x00, (byte)0xee,
+            (byte)0xcf, (byte)0xae, (byte)0x81, (byte)0xb1, (byte)0xb9, (byte)0xb3, (byte)0xc9, (byte)0x08,
+            (byte)0x81, (byte)0x0b, (byte)0x10, (byte)0xa1, (byte)0xb5, (byte)0x60, (byte)0x01, (byte)0x99,
+            (byte)0xeb, (byte)0x9f, (byte)0x44, (byte)0xae, (byte)0xf4, (byte)0xfd, (byte)0xa4, (byte)0x93,
+            (byte)0xb8, (byte)0x1a, (byte)0x9e, (byte)0x3d, (byte)0x84, (byte)0xf6, (byte)0x32, (byte)0x12,
+            (byte)0x4e, (byte)0xf0, (byte)0x23, (byte)0x6e, (byte)0x5d, (byte)0x1e, (byte)0x3b, (byte)0x7e,
+            (byte)0x28, (byte)0xfa, (byte)0xe7, (byte)0xaa, (byte)0x04, (byte)0x0a, (byte)0x2d, (byte)0x5b,
+            (byte)0x25, (byte)0x21, (byte)0x76, (byte)0x45, (byte)0x9d, (byte)0x1f, (byte)0x39, (byte)0x75,
+            (byte)0x41, (byte)0xba, (byte)0x2a, (byte)0x58, (byte)0xfb, (byte)0x65, (byte)0x99, (byte)0x02,
+            (byte)0x41, (byte)0x00, (byte)0xc9, (byte)0x7f, (byte)0xb1, (byte)0xf0, (byte)0x27, (byte)0xf4,
+            (byte)0x53, (byte)0xf6, (byte)0x34, (byte)0x12, (byte)0x33, (byte)0xea, (byte)0xaa, (byte)0xd1,
+            (byte)0xd9, (byte)0x35, (byte)0x3f, (byte)0x6c, (byte)0x42, (byte)0xd0, (byte)0x88, (byte)0x66,
+            (byte)0xb1, (byte)0xd0, (byte)0x5a, (byte)0x0f, (byte)0x20, (byte)0x35, (byte)0x02, (byte)0x8b,
+            (byte)0x9d, (byte)0x86, (byte)0x98, (byte)0x40, (byte)0xb4, (byte)0x16, (byte)0x66, (byte)0xb4,
+            (byte)0x2e, (byte)0x92, (byte)0xea, (byte)0x0d, (byte)0xa3, (byte)0xb4, (byte)0x32, (byte)0x04,
+            (byte)0xb5, (byte)0xcf, (byte)0xce, (byte)0x33, (byte)0x52, (byte)0x52, (byte)0x4d, (byte)0x04,
+            (byte)0x16, (byte)0xa5, (byte)0xa4, (byte)0x41, (byte)0xe7, (byte)0x00, (byte)0xaf, (byte)0x46,
+            (byte)0x15, (byte)0x03, (byte)0x02, (byte)0x40, (byte)0x54, (byte)0x49, (byte)0x4c, (byte)0xa6,
+            (byte)0x3e, (byte)0xba, (byte)0x03, (byte)0x37, (byte)0xe4, (byte)0xe2, (byte)0x40, (byte)0x23,
+            (byte)0xfc, (byte)0xd6, (byte)0x9a, (byte)0x5a, (byte)0xeb, (byte)0x07, (byte)0xdd, (byte)0xdc,
+            (byte)0x01, (byte)0x83, (byte)0xa4, (byte)0xd0, (byte)0xac, (byte)0x9b, (byte)0x54, (byte)0xb0,
+            (byte)0x51, (byte)0xf2, (byte)0xb1, (byte)0x3e, (byte)0xd9, (byte)0x49, (byte)0x09, (byte)0x75,
+            (byte)0xea, (byte)0xb7, (byte)0x74, (byte)0x14, (byte)0xff, (byte)0x59, (byte)0xc1, (byte)0xf7,
+            (byte)0x69, (byte)0x2e, (byte)0x9a, (byte)0x2e, (byte)0x20, (byte)0x2b, (byte)0x38, (byte)0xfc,
+            (byte)0x91, (byte)0x0a, (byte)0x47, (byte)0x41, (byte)0x74, (byte)0xad, (byte)0xc9, (byte)0x3c,
+            (byte)0x1f, (byte)0x67, (byte)0xc9, (byte)0x81, (byte)0x02, (byte)0x40, (byte)0x47, (byte)0x1e,
+            (byte)0x02, (byte)0x90, (byte)0xff, (byte)0x0a, (byte)0xf0, (byte)0x75, (byte)0x03, (byte)0x51,
+            (byte)0xb7, (byte)0xf8, (byte)0x78, (byte)0x86, (byte)0x4c, (byte)0xa9, (byte)0x61, (byte)0xad,
+            (byte)0xbd, (byte)0x3a, (byte)0x8a, (byte)0x7e, (byte)0x99, (byte)0x1c, (byte)0x5c, (byte)0x05,
+            (byte)0x56, (byte)0xa9, (byte)0x4c, (byte)0x31, (byte)0x46, (byte)0xa7, (byte)0xf9, (byte)0x80,
+            (byte)0x3f, (byte)0x8f, (byte)0x6f, (byte)0x8a, (byte)0xe3, (byte)0x42, (byte)0xe9, (byte)0x31,
+            (byte)0xfd, (byte)0x8a, (byte)0xe4, (byte)0x7a, (byte)0x22, (byte)0x0d, (byte)0x1b, (byte)0x99,
+            (byte)0xa4, (byte)0x95, (byte)0x84, (byte)0x98, (byte)0x07, (byte)0xfe, (byte)0x39, (byte)0xf9,
+            (byte)0x24, (byte)0x5a, (byte)0x98, (byte)0x36, (byte)0xda, (byte)0x3d, (byte)0x02, (byte)0x41,
+            (byte)0x00, (byte)0xb0, (byte)0x6c, (byte)0x4f, (byte)0xda, (byte)0xbb, (byte)0x63, (byte)0x01,
+            (byte)0x19, (byte)0x8d, (byte)0x26, (byte)0x5b, (byte)0xdb, (byte)0xae, (byte)0x94, (byte)0x23,
+            (byte)0xb3, (byte)0x80, (byte)0xf2, (byte)0x71, (byte)0xf7, (byte)0x34, (byte)0x53, (byte)0x88,
+            (byte)0x50, (byte)0x93, (byte)0x07, (byte)0x7f, (byte)0xcd, (byte)0x39, (byte)0xe2, (byte)0x11,
+            (byte)0x9f, (byte)0xc9, (byte)0x86, (byte)0x32, (byte)0x15, (byte)0x4f, (byte)0x58, (byte)0x83,
+            (byte)0xb1, (byte)0x67, (byte)0xa9, (byte)0x67, (byte)0xbf, (byte)0x40, (byte)0x2b, (byte)0x4e,
+            (byte)0x9e, (byte)0x2e, (byte)0x0f, (byte)0x96, (byte)0x56, (byte)0xe6, (byte)0x98, (byte)0xea,
+            (byte)0x36, (byte)0x66, (byte)0xed, (byte)0xfb, (byte)0x25, (byte)0x79, (byte)0x80, (byte)0x39,
+            (byte)0xf7
+        };
+
+        private static readonly byte[] output3 = Hex.Decode(
+              "b8246b56a6ed5881aeb585d9a25b2ad790c417e080681bf1ac2bc3deb69d8bce"
+            + "f0c4366fec400af052a72e9b0effb5b3f2f192dbeaca03c12740057113bf1f06"
+            + "69ac22e9f3a7852e3c15d913cab0b8863a95c99294ce8674214954610346f4d4"
+            + "74b26f7c48b42ee68e1f572a1fc4026ac456b4f59f7b621ea1b9d88f64202fb1");
+
+        private static readonly byte[] seed = {
+            (byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+            (byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+            (byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+            (byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+        };
+
+        private class VecRand
+            : SecureRandom
+        {
+            private readonly byte[] seed;
+
+            internal VecRand(byte[] seed)
+            {
+                this.seed = seed;
+            }
+
+            public override void NextBytes(
+                byte[] bytes)
+            {
+                Array.Copy(seed, 0, bytes, 0, bytes.Length);
+            }
+        }
+
+        private void BaseOaepTest(
+            int		id,
+            byte[]	pubKeyEnc,
+            byte[]	privKeyEnc,
+            byte[]	output)
+        {
+            //
+            // extract the public key info.
+            //
+            Asn1Object pubKeyObj = Asn1Object.FromByteArray(pubKeyEnc);
+            RsaPublicKeyStructure pubStruct = RsaPublicKeyStructure.GetInstance(
+                SubjectPublicKeyInfo.GetInstance(pubKeyObj).GetPublicKey());
+
+            //
+            // extract the private key info.
+            //
+            Asn1Object privKeyObj = Asn1Object.FromByteArray(privKeyEnc);
+            RsaPrivateKeyStructure privStruct = new RsaPrivateKeyStructure(
+                (Asn1Sequence)PrivateKeyInfo.GetInstance(privKeyObj).ParsePrivateKey());
+
+            RsaKeyParameters pubParameters = new RsaKeyParameters(
+                false,
+                pubStruct.Modulus,
+                pubStruct.PublicExponent);
+
+            RsaKeyParameters privParameters = new RsaPrivateCrtKeyParameters(
+                privStruct.Modulus,
+                privStruct.PublicExponent,
+                privStruct.PrivateExponent,
+                privStruct.Prime1,
+                privStruct.Prime2,
+                privStruct.Exponent1,
+                privStruct.Exponent2,
+                privStruct.Coefficient);
+
+            byte[] input = new byte[] {
+                (byte)0x54, (byte)0x85, (byte)0x9b, (byte)0x34,
+                (byte)0x2c, (byte)0x49, (byte)0xea, (byte)0x2a
+            };
+
+            EncDec("id(" + id + ")", pubParameters, privParameters, seed, input, output);
+        }
+
+        private void EncDec(
+            string				label,
+            RsaKeyParameters	pubParameters,
+            RsaKeyParameters	privParameters,
+            byte[]				seed,
+            byte[]				input,
+            byte[]				output)
+        {
+            IAsymmetricBlockCipher cipher = new OaepEncoding(new RsaEngine());
+
+            cipher.Init(true, new ParametersWithRandom(pubParameters, new VecRand(seed)));
+
+            byte[] outBytes = cipher.ProcessBlock(input, 0, input.Length);
+
+            for (int i = 0; i != output.Length; i++)
+            {
+                if (outBytes[i] != output[i])
+                {
+                    Fail(label + " failed encryption");
+                }
+            }
+
+            cipher.Init(false, privParameters);
+
+            outBytes = cipher.ProcessBlock(output, 0, output.Length);
+
+            for (int i = 0; i != input.Length; i++)
+            {
+                if (outBytes[i] != input[i])
+                {
+                    Fail(label + " failed decoding");
+                }
+            }
+        }
+
+        /*
+        * RSA vector tests from PKCS#1 page
+        */
+        private static readonly byte[] modulus_1024 = Hex.Decode(
+              "a8b3b284af8eb50b387034a860f146c4"
+            + "919f318763cd6c5598c8ae4811a1e0ab"
+            + "c4c7e0b082d693a5e7fced675cf46685"
+            + "12772c0cbc64a742c6c630f533c8cc72"
+            + "f62ae833c40bf25842e984bb78bdbf97"
+            + "c0107d55bdb662f5c4e0fab9845cb514"
+            + "8ef7392dd3aaff93ae1e6b667bb3d424"
+            + "7616d4f5ba10d4cfd226de88d39f16fb");
+
+        private static readonly byte[] pubExp_1024 = Hex.Decode("010001");
+
+        private static readonly byte[] privExp_1024 = Hex.Decode(
+              "53339cfdb79fc8466a655c7316aca85c"
+            + "55fd8f6dd898fdaf119517ef4f52e8fd"
+            + "8e258df93fee180fa0e4ab29693cd83b"
+            + "152a553d4ac4d1812b8b9fa5af0e7f55"
+            + "fe7304df41570926f3311f15c4d65a73"
+            + "2c483116ee3d3d2d0af3549ad9bf7cbf"
+            + "b78ad884f84d5beb04724dc7369b31de"
+            + "f37d0cf539e9cfcdd3de653729ead5d1");
+
+        private static readonly byte[] prime1_1024 = Hex.Decode(
+              "d32737e7267ffe1341b2d5c0d150a81b"
+            + "586fb3132bed2f8d5262864a9cb9f30a"
+            + "f38be448598d413a172efb802c21acf1"
+            + "c11c520c2f26a471dcad212eac7ca39d");
+
+        private static readonly byte[] prime2_1024 = Hex.Decode(
+              "cc8853d1d54da630fac004f471f281c7"
+            + "b8982d8224a490edbeb33d3e3d5cc93c"
+            + "4765703d1dd791642f1f116a0dd852be"
+            + "2419b2af72bfe9a030e860b0288b5d77");
+
+        private static readonly byte[] primeExp1_1024 = Hex.Decode(
+              "0e12bf1718e9cef5599ba1c3882fe804"
+            + "6a90874eefce8f2ccc20e4f2741fb0a3"
+            + "3a3848aec9c9305fbecbd2d76819967d"
+            + "4671acc6431e4037968db37878e695c1");
+
+        private static readonly byte[] primeExp2_1024 = Hex.Decode(
+              "95297b0f95a2fa67d00707d609dfd4fc"
+            + "05c89dafc2ef6d6ea55bec771ea33373"
+            + "4d9251e79082ecda866efef13c459e1a"
+            + "631386b7e354c899f5f112ca85d71583");
+
+        private static readonly byte[] crtCoef_1024 = Hex.Decode(
+              "4f456c502493bdc0ed2ab756a3a6ed4d"
+            + "67352a697d4216e93212b127a63d5411"
+            + "ce6fa98d5dbefd73263e372814274381"
+            + "8166ed7dd63687dd2a8ca1d2f4fbd8e1");
+
+        private static readonly byte[] input_1024_1 = Hex.Decode(
+              "6628194e12073db03ba94cda9ef95323"
+            + "97d50dba79b987004afefe34");
+
+        private static readonly byte[] seed_1024_1 = Hex.Decode(
+              "18b776ea21069d69776a33e96bad48e1"
+            + "dda0a5ef");
+
+        private static readonly byte[] output_1024_1 = Hex.Decode(
+              "354fe67b4a126d5d35fe36c777791a3f"
+            + "7ba13def484e2d3908aff722fad468fb"
+            + "21696de95d0be911c2d3174f8afcc201"
+            + "035f7b6d8e69402de5451618c21a535f"
+            + "a9d7bfc5b8dd9fc243f8cf927db31322"
+            + "d6e881eaa91a996170e657a05a266426"
+            + "d98c88003f8477c1227094a0d9fa1e8c"
+            + "4024309ce1ecccb5210035d47ac72e8a");
+
+        private static readonly byte[] input_1024_2 = Hex.Decode(
+              "750c4047f547e8e41411856523298ac9"
+            + "bae245efaf1397fbe56f9dd5");
+
+        private static readonly byte[] seed_1024_2 = Hex.Decode(
+              "0cc742ce4a9b7f32f951bcb251efd925"
+            + "fe4fe35f");
+
+        private static readonly byte[] output_1024_2 = Hex.Decode(
+              "640db1acc58e0568fe5407e5f9b701df"
+            + "f8c3c91e716c536fc7fcec6cb5b71c11"
+            + "65988d4a279e1577d730fc7a29932e3f"
+            + "00c81515236d8d8e31017a7a09df4352"
+            + "d904cdeb79aa583adcc31ea698a4c052"
+            + "83daba9089be5491f67c1a4ee48dc74b"
+            + "bbe6643aef846679b4cb395a352d5ed1"
+            + "15912df696ffe0702932946d71492b44");
+
+        private static readonly byte[] input_1024_3 = Hex.Decode(
+              "d94ae0832e6445ce42331cb06d531a82"
+            + "b1db4baad30f746dc916df24d4e3c245"
+            + "1fff59a6423eb0e1d02d4fe646cf699d"
+            + "fd818c6e97b051");
+
+        private static readonly byte[] seed_1024_3 = Hex.Decode(
+              "2514df4695755a67b288eaf4905c36ee"
+            + "c66fd2fd");
+
+        private static readonly byte[] output_1024_3 = Hex.Decode(
+              "423736ed035f6026af276c35c0b3741b"
+            + "365e5f76ca091b4e8c29e2f0befee603"
+            + "595aa8322d602d2e625e95eb81b2f1c9"
+            + "724e822eca76db8618cf09c5343503a4"
+            + "360835b5903bc637e3879fb05e0ef326"
+            + "85d5aec5067cd7cc96fe4b2670b6eac3"
+            + "066b1fcf5686b68589aafb7d629b02d8"
+            + "f8625ca3833624d4800fb081b1cf94eb");
+
+        private static readonly byte[] input_1024_4 = Hex.Decode(
+              "52e650d98e7f2a048b4f86852153b97e"
+            + "01dd316f346a19f67a85");
+
+        private static readonly byte[] seed_1024_4 = Hex.Decode(
+              "c4435a3e1a18a68b6820436290a37cef"
+            + "b85db3fb");
+
+        private static readonly byte[] output_1024_4 = Hex.Decode(
+              "45ead4ca551e662c9800f1aca8283b05"
+            + "25e6abae30be4b4aba762fa40fd3d38e"
+            + "22abefc69794f6ebbbc05ddbb1121624"
+            + "7d2f412fd0fba87c6e3acd888813646f"
+            + "d0e48e785204f9c3f73d6d8239562722"
+            + "dddd8771fec48b83a31ee6f592c4cfd4"
+            + "bc88174f3b13a112aae3b9f7b80e0fc6"
+            + "f7255ba880dc7d8021e22ad6a85f0755");
+
+        private static readonly byte[] input_1024_5 = Hex.Decode(
+              "8da89fd9e5f974a29feffb462b49180f"
+            + "6cf9e802");
+
+        private static readonly byte[] seed_1024_5 = Hex.Decode(
+              "b318c42df3be0f83fea823f5a7b47ed5"
+            + "e425a3b5");
+
+        private static readonly byte[] output_1024_5 = Hex.Decode(
+              "36f6e34d94a8d34daacba33a2139d00a"
+            + "d85a9345a86051e73071620056b920e2"
+            + "19005855a213a0f23897cdcd731b4525"
+            + "7c777fe908202befdd0b58386b1244ea"
+            + "0cf539a05d5d10329da44e13030fd760"
+            + "dcd644cfef2094d1910d3f433e1c7c6d"
+            + "d18bc1f2df7f643d662fb9dd37ead905"
+            + "9190f4fa66ca39e869c4eb449cbdc439");
+
+        private static readonly byte[] input_1024_6 = Hex.Decode("26521050844271");
+
+        private static readonly byte[] seed_1024_6 = Hex.Decode(
+              "e4ec0982c2336f3a677f6a356174eb0c"
+            + "e887abc2");
+
+        private static readonly byte[] output_1024_6 = Hex.Decode(
+              "42cee2617b1ecea4db3f4829386fbd61"
+            + "dafbf038e180d837c96366df24c097b4"
+            + "ab0fac6bdf590d821c9f10642e681ad0"
+            + "5b8d78b378c0f46ce2fad63f74e0ad3d"
+            + "f06b075d7eb5f5636f8d403b9059ca76"
+            + "1b5c62bb52aa45002ea70baace08ded2"
+            + "43b9d8cbd62a68ade265832b56564e43"
+            + "a6fa42ed199a099769742df1539e8255");
+
+        private static readonly byte[] modulus_1027 = Hex.Decode(
+              "051240b6cc0004fa48d0134671c078c7"
+            + "c8dec3b3e2f25bc2564467339db38853"
+            + "d06b85eea5b2de353bff42ac2e46bc97"
+            + "fae6ac9618da9537a5c8f553c1e35762"
+            + "5991d6108dcd7885fb3a25413f53efca"
+            + "d948cb35cd9b9ae9c1c67626d113d57d"
+            + "de4c5bea76bb5bb7de96c00d07372e96"
+            + "85a6d75cf9d239fa148d70931b5f3fb0"
+            + "39");
+
+        private static readonly byte[] pubExp_1027 = Hex.Decode("010001");
+
+        private static readonly byte[] privExp_1027 = Hex.Decode(
+              "0411ffca3b7ca5e9e9be7fe38a85105e"
+            + "353896db05c5796aecd2a725161eb365"
+            + "1c8629a9b862b904d7b0c7b37f8cb5a1"
+            + "c2b54001018a00a1eb2cafe4ee4e9492"
+            + "c348bc2bedab4b9ebbf064e8eff322b9"
+            + "009f8eec653905f40df88a3cdc49d456"
+            + "7f75627d41aca624129b46a0b7c698e5"
+            + "e65f2b7ba102c749a10135b6540d0401");
+
+        private static readonly byte[] prime1_1027 = Hex.Decode(
+              "027458c19ec1636919e736c9af25d609"
+            + "a51b8f561d19c6bf6943dd1ee1ab8a4a"
+            + "3f232100bd40b88decc6ba235548b6ef"
+            + "792a11c9de823d0a7922c7095b6eba57"
+            + "01");
+
+        private static readonly byte[] prime2_1027 = Hex.Decode(
+              "0210ee9b33ab61716e27d251bd465f4b"
+            + "35a1a232e2da00901c294bf22350ce49"
+            + "0d099f642b5375612db63ba1f2038649"
+            + "2bf04d34b3c22bceb909d13441b53b51"
+            + "39");
+
+        private static readonly byte[] primeExp1_1027 = Hex.Decode(
+              "39fa028b826e88c1121b750a8b242fa9"
+            + "a35c5b66bdfd1fa637d3cc48a84a4f45"
+            + "7a194e7727e49f7bcc6e5a5a412657fc"
+            + "470c7322ebc37416ef458c307a8c0901");
+
+        private static readonly byte[] primeExp2_1027 = Hex.Decode(
+              "015d99a84195943979fa9e1be2c3c1b6"
+            + "9f432f46fd03e47d5befbbbfd6b1d137"
+            + "1d83efb330a3e020942b2fed115e5d02"
+            + "be24fd92c9019d1cecd6dd4cf1e54cc8"
+            + "99");
+
+        private static readonly byte[] crtCoef_1027 = Hex.Decode(
+              "01f0b7015170b3f5e42223ba30301c41"
+            + "a6d87cbb70e30cb7d3c67d25473db1f6"
+            + "cbf03e3f9126e3e97968279a865b2c2b"
+            + "426524cfc52a683d31ed30eb984be412"
+            + "ba");
+
+        private static readonly byte[] input_1027_1 = Hex.Decode(
+              "4a86609534ee434a6cbca3f7e962e76d"
+            + "455e3264c19f605f6e5ff6137c65c56d"
+            + "7fb344cd52bc93374f3d166c9f0c6f9c"
+            + "506bad19330972d2");
+
+        private static readonly byte[] seed_1027_1 = Hex.Decode(
+              "1cac19ce993def55f98203f6852896c9"
+            + "5ccca1f3");
+
+        private static readonly byte[] output_1027_1 = Hex.Decode(
+              "04cce19614845e094152a3fe18e54e33"
+            + "30c44e5efbc64ae16886cb1869014cc5"
+            + "781b1f8f9e045384d0112a135ca0d12e"
+            + "9c88a8e4063416deaae3844f60d6e96f"
+            + "e155145f4525b9a34431ca3766180f70"
+            + "e15a5e5d8e8b1a516ff870609f13f896"
+            + "935ced188279a58ed13d07114277d75c"
+            + "6568607e0ab092fd803a223e4a8ee0b1"
+            + "a8");
+
+        private static readonly byte[] input_1027_2 = Hex.Decode(
+              "b0adc4f3fe11da59ce992773d9059943"
+            + "c03046497ee9d9f9a06df1166db46d98"
+            + "f58d27ec074c02eee6cbe2449c8b9fc5"
+            + "080c5c3f4433092512ec46aa793743c8");
+
+        private static readonly byte[] seed_1027_2 = Hex.Decode(
+              "f545d5897585e3db71aa0cb8da76c51d"
+            + "032ae963");
+
+        private static readonly byte[] output_1027_2 = Hex.Decode(
+              "0097b698c6165645b303486fbf5a2a44"
+            + "79c0ee85889b541a6f0b858d6b6597b1"
+            + "3b854eb4f839af03399a80d79bda6578"
+            + "c841f90d645715b280d37143992dd186"
+            + "c80b949b775cae97370e4ec97443136c"
+            + "6da484e970ffdb1323a20847821d3b18"
+            + "381de13bb49aaea66530c4a4b8271f3e"
+            + "ae172cd366e07e6636f1019d2a28aed1"
+            + "5e");
+
+        private static readonly byte[] input_1027_3 = Hex.Decode(
+              "bf6d42e701707b1d0206b0c8b45a1c72"
+            + "641ff12889219a82bdea965b5e79a96b"
+            + "0d0163ed9d578ec9ada20f2fbcf1ea3c"
+            + "4089d83419ba81b0c60f3606da99");
+
+        private static readonly byte[] seed_1027_3 = Hex.Decode(
+              "ad997feef730d6ea7be60d0dc52e72ea"
+            + "cbfdd275");
+
+        private static readonly byte[] output_1027_3 = Hex.Decode(
+              "0301f935e9c47abcb48acbbe09895d9f"
+            + "5971af14839da4ff95417ee453d1fd77"
+            + "319072bb7297e1b55d7561cd9d1bb24c"
+            + "1a9a37c619864308242804879d86ebd0"
+            + "01dce5183975e1506989b70e5a834341"
+            + "54d5cbfd6a24787e60eb0c658d2ac193"
+            + "302d1192c6e622d4a12ad4b53923bca2"
+            + "46df31c6395e37702c6a78ae081fb9d0"
+            + "65");
+
+        private static readonly byte[] input_1027_4 = Hex.Decode(
+              "fb2ef112f5e766eb94019297934794f7"
+            + "be2f6fc1c58e");
+
+        private static readonly byte[] seed_1027_4 = Hex.Decode(
+              "136454df5730f73c807a7e40d8c1a312"
+            + "ac5b9dd3");
+
+        private static readonly byte[] output_1027_4 = Hex.Decode(
+              "02d110ad30afb727beb691dd0cf17d0a"
+            + "f1a1e7fa0cc040ec1a4ba26a42c59d0a"
+            + "796a2e22c8f357ccc98b6519aceb682e"
+            + "945e62cb734614a529407cd452bee3e4"
+            + "4fece8423cc19e55548b8b994b849c7e"
+            + "cde4933e76037e1d0ce44275b08710c6"
+            + "8e430130b929730ed77e09b015642c55"
+            + "93f04e4ffb9410798102a8e96ffdfe11"
+            + "e4");
+
+        private static readonly byte[] input_1027_5 = Hex.Decode(
+              "28ccd447bb9e85166dabb9e5b7d1adad"
+            + "c4b9d39f204e96d5e440ce9ad928bc1c"
+            + "2284");
+
+        private static readonly byte[] seed_1027_5 = Hex.Decode(
+              "bca8057f824b2ea257f2861407eef63d"
+            + "33208681");
+
+        private static readonly byte[] output_1027_5 = Hex.Decode(
+              "00dbb8a7439d90efd919a377c54fae8f"
+            + "e11ec58c3b858362e23ad1b8a4431079"
+            + "9066b99347aa525691d2adc58d9b06e3"
+            + "4f288c170390c5f0e11c0aa3645959f1"
+            + "8ee79e8f2be8d7ac5c23d061f18dd74b"
+            + "8c5f2a58fcb5eb0c54f99f01a8324756"
+            + "8292536583340948d7a8c97c4acd1e98"
+            + "d1e29dc320e97a260532a8aa7a758a1e"
+            + "c2");
+
+        private static readonly byte[] input_1027_6 = Hex.Decode("f22242751ec6b1");
+
+        private static readonly byte[] seed_1027_6 = Hex.Decode(
+              "2e7e1e17f647b5ddd033e15472f90f68"
+            + "12f3ac4e");
+
+        private static readonly byte[] output_1027_6 = Hex.Decode(
+              "00a5ffa4768c8bbecaee2db77e8f2eec"
+            + "99595933545520835e5ba7db9493d3e1"
+            + "7cddefe6a5f567624471908db4e2d83a"
+            + "0fbee60608fc84049503b2234a07dc83"
+            + "b27b22847ad8920ff42f674ef79b7628"
+            + "0b00233d2b51b8cb2703a9d42bfbc825"
+            + "0c96ec32c051e57f1b4ba528db89c37e"
+            + "4c54e27e6e64ac69635ae887d9541619"
+            + "a9");
+
+        private void OaepVecTest(
+            int					keySize,
+            int					no,
+            RsaKeyParameters	pubParam,
+            RsaKeyParameters	privParam,
+            byte[]				seed,
+            byte[]				input,
+            byte[]				output)
+        {
+            EncDec(keySize + " " + no, pubParam, privParam, seed, input, output);
+        }
+
+        public override string Name
+        {
+            get { return "OAEP"; }
+        }
+
+        public override void PerformTest()
+        {
+            BaseOaepTest(1, pubKeyEnc1, privKeyEnc1, output1);
+            BaseOaepTest(2, pubKeyEnc2, privKeyEnc2, output2);
+            BaseOaepTest(3, pubKeyEnc3, privKeyEnc3, output3);
+
+            RsaKeyParameters pubParam = new RsaKeyParameters(
+                false,
+                new BigInteger(1, modulus_1024),
+                new BigInteger(1, pubExp_1024));
+            RsaKeyParameters privParam = new RsaPrivateCrtKeyParameters(
+                pubParam.Modulus,
+                pubParam.Exponent,
+                new BigInteger(1, privExp_1024),
+                new BigInteger(1, prime1_1024),
+                new BigInteger(1, prime2_1024),
+                new BigInteger(1, primeExp1_1024),
+                new BigInteger(1, primeExp2_1024),
+                new BigInteger(1, crtCoef_1024));
+
+            OaepVecTest(1024, 1, pubParam, privParam, seed_1024_1, input_1024_1, output_1024_1);
+            OaepVecTest(1024, 2, pubParam, privParam, seed_1024_2, input_1024_2, output_1024_2);
+            OaepVecTest(1024, 3, pubParam, privParam, seed_1024_3, input_1024_3, output_1024_3);
+            OaepVecTest(1024, 4, pubParam, privParam, seed_1024_4, input_1024_4, output_1024_4);
+            OaepVecTest(1024, 5, pubParam, privParam, seed_1024_5, input_1024_5, output_1024_5);
+            OaepVecTest(1024, 6, pubParam, privParam, seed_1024_6, input_1024_6, output_1024_6);
+
+            pubParam = new RsaKeyParameters(
+                false,
+                new BigInteger(1, modulus_1027),
+                new BigInteger(1, pubExp_1027));
+            privParam = new RsaPrivateCrtKeyParameters(
+                pubParam.Modulus,
+                pubParam.Exponent,
+                new BigInteger(1, privExp_1027),
+                new BigInteger(1, prime1_1027),
+                new BigInteger(1, prime2_1027),
+                new BigInteger(1, primeExp1_1027),
+                new BigInteger(1, primeExp2_1027),
+                new BigInteger(1, crtCoef_1027));
+
+            OaepVecTest(1027, 1, pubParam, privParam, seed_1027_1, input_1027_1, output_1027_1);
+            OaepVecTest(1027, 2, pubParam, privParam, seed_1027_2, input_1027_2, output_1027_2);
+            OaepVecTest(1027, 3, pubParam, privParam, seed_1027_3, input_1027_3, output_1027_3);
+            OaepVecTest(1027, 4, pubParam, privParam, seed_1027_4, input_1027_4, output_1027_4);
+            OaepVecTest(1027, 5, pubParam, privParam, seed_1027_5, input_1027_5, output_1027_5);
+            OaepVecTest(1027, 6, pubParam, privParam, seed_1027_6, input_1027_6, output_1027_6);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new OaepTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/OCBTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/OCBTest.cs
new file mode 100644
index 0000000..9f898fb
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/OCBTest.cs
@@ -0,0 +1,515 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * Test vectors from <a href="http://tools.ietf.org/html/rfc7253">RFC 7253 on The OCB
+     * Authenticated-Encryption Algorithm</a>
+     */
+    public class OcbTest
+        : SimpleTest
+    {
+        private const string KEY_128 = "000102030405060708090A0B0C0D0E0F";
+        private const string KEY_96 = "0F0E0D0C0B0A09080706050403020100";
+
+        /*
+         * Test vectors from Appendix A of the specification, containing the strings N, A, P, C in order
+         */
+
+        private static readonly string[][] TEST_VECTORS_128 = new string[][]{
+            new string[]{ "BBAA99887766554433221100",
+              "",
+              "",
+              "785407BFFFC8AD9EDCC5520AC9111EE6" },
+            new string[]{ "BBAA99887766554433221101",
+              "0001020304050607",
+              "0001020304050607",
+              "6820B3657B6F615A5725BDA0D3B4EB3A257C9AF1F8F03009" },
+            new string[]{ "BBAA99887766554433221102",
+              "0001020304050607",
+              "",
+              "81017F8203F081277152FADE694A0A00" },
+            new string[]{ "BBAA99887766554433221103",
+              "",
+              "0001020304050607",
+              "45DD69F8F5AAE72414054CD1F35D82760B2CD00D2F99BFA9" },
+            new string[]{ "BBAA99887766554433221104",
+              "000102030405060708090A0B0C0D0E0F",
+              "000102030405060708090A0B0C0D0E0F",
+              "571D535B60B277188BE5147170A9A22C3AD7A4FF3835B8C5701C1CCEC8FC3358" },
+            new string[]{ "BBAA99887766554433221105",
+              "000102030405060708090A0B0C0D0E0F",
+              "",
+              "8CF761B6902EF764462AD86498CA6B97" },
+            new string[]{ "BBAA99887766554433221106",
+              "",
+              "000102030405060708090A0B0C0D0E0F",
+              "5CE88EC2E0692706A915C00AEB8B2396F40E1C743F52436BDF06D8FA1ECA343D" },
+            new string[]{ "BBAA99887766554433221107",
+              "000102030405060708090A0B0C0D0E0F1011121314151617",
+              "000102030405060708090A0B0C0D0E0F1011121314151617",
+              "1CA2207308C87C010756104D8840CE1952F09673A448A122C92C62241051F57356D7F3C90BB0E07F" },
+            new string[]{ "BBAA99887766554433221108",
+              "000102030405060708090A0B0C0D0E0F1011121314151617",
+              "",
+              "6DC225A071FC1B9F7C69F93B0F1E10DE" },
+            new string[]{ "BBAA99887766554433221109",
+              "",
+              "000102030405060708090A0B0C0D0E0F1011121314151617",
+              "221BD0DE7FA6FE993ECCD769460A0AF2D6CDED0C395B1C3CE725F32494B9F914D85C0B1EB38357FF" },
+            new string[]{ "BBAA9988776655443322110A",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+              "BD6F6C496201C69296C11EFD138A467ABD3C707924B964DEAFFC40319AF5A48540FBBA186C5553C68AD9F592A79A4240" },
+            new string[]{ "BBAA9988776655443322110B",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+              "",
+              "FE80690BEE8A485D11F32965BC9D2A32" },
+            new string[]{ "BBAA9988776655443322110C",
+              "",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F",
+              "2942BFC773BDA23CABC6ACFD9BFD5835BD300F0973792EF46040C53F1432BCDFB5E1DDE3BC18A5F840B52E653444D5DF" },
+            new string[]{ "BBAA9988776655443322110D",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "D5CA91748410C1751FF8A2F618255B68A0A12E093FF454606E59F9C1D0DDC54B65E8628E568BAD7AED07BA06A4A69483A7035490C5769E60" },
+            new string[]{ "BBAA9988776655443322110E",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "",
+              "C5CD9D1850C141E358649994EE701B68" },
+            new string[]{ "BBAA9988776655443322110F",
+              "",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "4412923493C57D5DE0D700F753CCE0D1D2D95060122E9F15A5DDBFC5787E50B5CC55EE507BCB084E479AD363AC366B95A98CA5F3000B1479" },
+        };
+
+        private static readonly string[][] TEST_VECTORS_96 = new string[][]{
+            new string[]{ "BBAA9988776655443322110D",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222324252627",
+              "1792A4E31E0755FB03E31B22116E6C2DDF9EFD6E33D536F1A0124B0A55BAE884ED93481529C76B6AD0C515F4D1CDD4FDAC4F02AA" },
+        };
+
+        public override string Name
+        {
+            get { return "OCB"; }
+        }
+
+        public override void PerformTest()
+        {
+            byte[] K128 = Hex.Decode(KEY_128);
+            for (int i = 0; i < TEST_VECTORS_128.Length; ++i)
+            {
+                RunTestCase("Test Case " + i, TEST_VECTORS_128[i], 128, K128);
+            }
+
+            byte[] K96 = Hex.Decode(KEY_96);
+            for (int i = 0; i < TEST_VECTORS_96.Length; ++i)
+            {
+                RunTestCase("Test Case " + i, TEST_VECTORS_96[i], 96, K96);
+            }
+
+            RunLongerTestCase(128, 128, "67E944D23256C5E0B6C61FA22FDF1EA2");
+            RunLongerTestCase(192, 128, "F673F2C3E7174AAE7BAE986CA9F29E17");
+            RunLongerTestCase(256, 128, "D90EB8E9C977C88B79DD793D7FFA161C");
+            RunLongerTestCase(128, 96, "77A3D8E73589158D25D01209");
+            RunLongerTestCase(192, 96, "05D56EAD2752C86BE6932C5E");
+            RunLongerTestCase(256, 96, "5458359AC23B0CBA9E6330DD");
+            RunLongerTestCase(128, 64, "192C9B7BD90BA06A");
+            RunLongerTestCase(192, 64, "0066BC6E0EF34E24");
+            RunLongerTestCase(256, 64, "7D4EA5D445501CBE");
+
+            RandomTests();
+            OutputSizeTests();
+            DoTestExceptions();
+        }
+
+        private void DoTestExceptions()
+        {
+            IAeadBlockCipher ocb = CreateOcbCipher();
+
+            try
+            {
+                ocb = new OcbBlockCipher(new DesEngine(), new DesEngine());
+                Fail("incorrect block size not picked up");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            try
+            {
+                ocb.Init(false, new KeyParameter(new byte[16]));
+                Fail("illegal argument not picked up");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+
+            // TODO
+            //AEADTestUtil.testReset(this, createOCBCipher(), createOCBCipher(), new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
+            //AEADTestUtil.testTampering(this, ocb, new AEADParameters(new KeyParameter(new byte[16]), 128, new byte[15]));
+        }
+
+        private void RunTestCase(string testName, string[] testVector, int macLengthBits, byte[] K)
+        {
+            int pos = 0;
+            byte[] N = Hex.Decode(testVector[pos++]);
+            byte[] A = Hex.Decode(testVector[pos++]);
+            byte[] P = Hex.Decode(testVector[pos++]);
+            byte[] C = Hex.Decode(testVector[pos++]);
+
+            int macLengthBytes = macLengthBits / 8;
+
+            KeyParameter keyParameter = new KeyParameter(K);
+            AeadParameters parameters = new AeadParameters(keyParameter, macLengthBits, N, A);
+
+            IAeadBlockCipher encCipher = InitOcbCipher(true, parameters);
+            IAeadBlockCipher decCipher = InitOcbCipher(false, parameters);
+
+            CheckTestCase(encCipher, decCipher, testName, macLengthBytes, P, C);
+            CheckTestCase(encCipher, decCipher, testName + " (reused)", macLengthBytes, P, C);
+
+            // Key reuse
+            AeadParameters keyReuseParams = AeadTestUtilities.ReuseKey(parameters);
+            encCipher.Init(true, keyReuseParams);
+            decCipher.Init(false, keyReuseParams);
+            CheckTestCase(encCipher, decCipher, testName + " (key reuse)", macLengthBytes, P, C);
+        }
+
+        private IBlockCipher CreateUnderlyingCipher()
+        {
+            return new AesEngine();
+        }
+
+        private IAeadBlockCipher CreateOcbCipher()
+        {
+            return new OcbBlockCipher(CreateUnderlyingCipher(), CreateUnderlyingCipher());
+        }
+
+        private IAeadBlockCipher InitOcbCipher(bool forEncryption, AeadParameters parameters)
+        {
+            IAeadBlockCipher c = CreateOcbCipher();
+            c.Init(forEncryption, parameters);
+            return c;
+        }
+
+        private void CheckTestCase(IAeadBlockCipher encCipher, IAeadBlockCipher decCipher, string testName,
+            int macLengthBytes, byte[] P, byte[] C)
+        {
+            byte[] tag = Arrays.CopyOfRange(C, C.Length - macLengthBytes, C.Length);
+
+            {
+                byte[] enc = new byte[encCipher.GetOutputSize(P.Length)];
+                int len = encCipher.ProcessBytes(P, 0, P.Length, enc, 0);
+                len += encCipher.DoFinal(enc, len);
+
+                if (enc.Length != len)
+                {
+                    Fail("encryption reported incorrect length: " + testName);
+                }
+
+                if (!AreEqual(C, enc))
+                {
+                    Fail("incorrect encrypt in: " + testName);
+                }
+
+                if (!AreEqual(tag, encCipher.GetMac()))
+                {
+                    Fail("getMac() not the same as the appended tag: " + testName);
+                }
+            }
+
+            {
+                byte[] dec = new byte[decCipher.GetOutputSize(C.Length)];
+                int len = decCipher.ProcessBytes(C, 0, C.Length, dec, 0);
+                len += decCipher.DoFinal(dec, len);
+
+                if (dec.Length != len)
+                {
+                    Fail("decryption reported incorrect length: " + testName);
+                }
+
+                if (!AreEqual(P, dec))
+                {
+                    Fail("incorrect decrypt in: " + testName);
+                }
+
+                if (!AreEqual(tag, decCipher.GetMac()))
+                {
+                    Fail("getMac() not the same as the appended tag: " + testName);
+                }
+            }
+        }
+
+        private void RunLongerTestCase(int keyLen, int tagLen, string expectedOutputHex)
+        {
+            byte[] expectedOutput = Hex.Decode(expectedOutputHex);
+            byte[] keyBytes = new byte[keyLen / 8];
+            keyBytes[keyBytes.Length - 1] = (byte)tagLen;
+            KeyParameter key = new KeyParameter(keyBytes);
+
+            IAeadBlockCipher c1 = InitOcbCipher(true, new AeadParameters(key, tagLen, CreateNonce(385)));
+            IAeadBlockCipher c2 = CreateOcbCipher();
+
+            long total = 0;
+
+            byte[] S = new byte[128];
+
+            uint n = 0;
+            for (int i = 0; i < 128; ++i)
+            {
+                c2.Init(true, new AeadParameters(key, tagLen, CreateNonce(++n)));
+                total += UpdateCiphers(c1, c2, S, i, true, true);
+                c2.Init(true, new AeadParameters(key, tagLen, CreateNonce(++n)));
+                total += UpdateCiphers(c1, c2, S, i, false, true);
+                c2.Init(true, new AeadParameters(key, tagLen, CreateNonce(++n)));
+                total += UpdateCiphers(c1, c2, S, i, true, false);
+            }
+
+            long expectedTotal = 16256 + (48 * tagLen);
+
+            if (total != expectedTotal)
+            {
+                Fail("test generated the wrong amount of input: " + total);
+            }
+
+            byte[] output = new byte[c1.GetOutputSize(0)];
+            c1.DoFinal(output, 0);
+
+            if (!AreEqual(expectedOutput, output))
+            {
+                Fail("incorrect encrypt in long-form test");
+            }
+        }
+
+        private byte[] CreateNonce(uint n)
+        {
+            return new byte[]{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)(n >> 8), (byte)n };
+        }
+
+        private int UpdateCiphers(IAeadBlockCipher c1, IAeadBlockCipher c2, byte[] S, int i,
+            bool includeAAD, bool includePlaintext)
+        {
+            int inputLen = includePlaintext ? i : 0;
+            int outputLen = c2.GetOutputSize(inputLen);
+
+            byte[] output = new byte[outputLen];
+
+            int len = 0;
+
+            if (includeAAD) {
+                c2.ProcessAadBytes(S, 0, i);
+            }
+
+            if (includePlaintext) {
+                len += c2.ProcessBytes(S, 0, i, output, len);
+            }
+
+            len += c2.DoFinal(output, len);
+
+            c1.ProcessAadBytes(output, 0, len);
+
+            return len;
+        }
+
+        private void RandomTests()
+        {
+            SecureRandom srng = new SecureRandom();
+            srng.SetSeed(DateTimeUtilities.CurrentUnixMs());
+            for (int i = 0; i < 10; ++i)
+            {
+                RandomTest(srng);
+            }
+        }
+
+        private void RandomTest(SecureRandom srng)
+        {
+            int kLength = 16 + 8 * (System.Math.Abs(srng.NextInt()) % 3);
+            byte[] K = new byte[kLength];
+            srng.NextBytes(K);
+
+            int pLength = (int)((uint)srng.NextInt() >> 16);
+            byte[] P = new byte[pLength];
+            srng.NextBytes(P);
+
+            int aLength = (int)((uint)srng.NextInt() >> 24);
+            byte[] A = new byte[aLength];
+            srng.NextBytes(A);
+
+            int saLength = (int)((uint)srng.NextInt() >> 24);
+            byte[] SA = new byte[saLength];
+            srng.NextBytes(SA);
+
+            int ivLength = 1 + NextInt(srng, 15);
+            byte[] IV = new byte[ivLength];
+            srng.NextBytes(IV);
+
+            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
+            IAeadBlockCipher cipher = InitOcbCipher(true, parameters);
+            byte[] C = new byte[cipher.GetOutputSize(P.Length)];
+            int predicted = cipher.GetUpdateOutputSize(P.Length);
+
+            int split = NextInt(srng, SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            int len = cipher.ProcessBytes(P, 0, P.Length, C, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            if (predicted != len)
+            {
+                Fail("encryption reported incorrect update length in randomised test");
+            }
+
+            len += cipher.DoFinal(C, len);
+
+            if (C.Length != len)
+            {
+                Fail("encryption reported incorrect length in randomised test");
+            }
+
+            byte[] encT = cipher.GetMac();
+            byte[] tail = new byte[C.Length - P.Length];
+            Array.Copy(C, P.Length, tail, 0, tail.Length);
+
+            if (!AreEqual(encT, tail))
+            {
+                Fail("stream contained wrong mac in randomised test");
+            }
+
+            cipher.Init(false, parameters);
+            byte[] decP = new byte[cipher.GetOutputSize(C.Length)];
+            predicted = cipher.GetUpdateOutputSize(C.Length);
+
+            split = NextInt(srng, SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            if (predicted != len)
+            {
+                Fail("decryption reported incorrect update length in randomised test");
+            }
+
+            len += cipher.DoFinal(decP, len);
+
+            if (!AreEqual(P, decP))
+            {
+                Fail("incorrect decrypt in randomised test");
+            }
+
+            byte[] decT = cipher.GetMac();
+            if (!AreEqual(encT, decT))
+            {
+                Fail("decryption produced different mac from encryption");
+            }
+
+            //
+            // key reuse test
+            //
+            cipher.Init(false, AeadTestUtilities.ReuseKey(parameters));
+            decP = new byte[cipher.GetOutputSize(C.Length)];
+
+            split = NextInt(srng, SA.Length + 1);
+            cipher.ProcessAadBytes(SA, 0, split);
+            len = cipher.ProcessBytes(C, 0, C.Length, decP, 0);
+            cipher.ProcessAadBytes(SA, split, SA.Length - split);
+
+            len += cipher.DoFinal(decP, len);
+
+            if (!AreEqual(P, decP))
+            {
+                Fail("incorrect decrypt in randomised test");
+            }
+
+            decT = cipher.GetMac();
+            if (!AreEqual(encT, decT))
+            {
+                Fail("decryption produced different mac from encryption");
+            }
+        }
+
+        private void OutputSizeTests()
+        {
+            byte[] K = new byte[16];
+            byte[] A = null;
+            byte[] IV = new byte[15];
+
+            AeadParameters parameters = new AeadParameters(new KeyParameter(K), 16 * 8, IV, A);
+            IAeadBlockCipher cipher = InitOcbCipher(true, parameters);
+
+            if (cipher.GetUpdateOutputSize(0) != 0)
+            {
+                Fail("incorrect getUpdateOutputSize for initial 0 bytes encryption");
+            }
+
+            if (cipher.GetOutputSize(0) != 16)
+            {
+                Fail("incorrect getOutputSize for initial 0 bytes encryption");
+            }
+
+            cipher.Init(false, parameters);
+
+            if (cipher.GetUpdateOutputSize(0) != 0)
+            {
+                Fail("incorrect getUpdateOutputSize for initial 0 bytes decryption");
+            }
+
+            // NOTE: 0 bytes would be truncated data, but we want it to fail in the doFinal, not here
+            if (cipher.GetOutputSize(0) != 0)
+            {
+                Fail("fragile getOutputSize for initial 0 bytes decryption");
+            }
+
+            if (cipher.GetOutputSize(16) != 0)
+            {
+                Fail("incorrect getOutputSize for initial MAC-size bytes decryption");
+            }
+        }
+
+        private static int NextInt(SecureRandom rand, int n)
+        {
+            if ((n & -n) == n)  // i.e., n is a power of 2
+            {
+                return (int)(((uint)n * (ulong)((uint)rand.NextInt() >> 1)) >> 31);
+            }
+
+            int bits, value;
+            do
+            {
+                bits = (int)((uint)rand.NextInt() >> 1);
+                value = bits % n;
+            }
+            while (bits - value + (n - 1) < 0);
+
+            return value;
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new OcbTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/PSSBlindTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/PSSBlindTest.cs
new file mode 100644
index 0000000..d887a8f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/PSSBlindTest.cs
@@ -0,0 +1,399 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/*
+	* RSA PSS test vectors for PKCS#1 V2.1 with blinding
+	*/
+	[TestFixture]
+	public class PssBlindTest
+		: SimpleTest
+	{
+		private readonly int DATA_LENGTH = 1000;
+		private readonly int NUM_TESTS = 50;
+		private readonly int NUM_TESTS_WITH_KEY_GENERATION = 10;
+
+		private class FixedRandom
+			: SecureRandom
+		{
+			private readonly byte[] vals;
+
+			public FixedRandom(
+				byte[] vals)
+			{
+				this.vals = vals;
+			}
+
+			public override void NextBytes(
+				byte[] bytes)
+			{
+				Array.Copy(vals, 0, bytes, 0, vals.Length);
+			}
+		}
+
+		//
+		// Example 1: A 1024-bit RSA keypair
+		//
+		private RsaKeyParameters pub1 = new RsaKeyParameters(false,
+					new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+					new BigInteger("010001",16));
+
+		private RsaKeyParameters prv1 = new RsaPrivateCrtKeyParameters(
+					new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+					new BigInteger("010001",16),
+					new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+					new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+					new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+					new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+					new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+					new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+		// PSSExample1.1
+
+		private byte[] msg1a = Hex.Decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
+
+		private byte[] slt1a = Hex.Decode("dee959c7e06411361420ff80185ed57f3e6776af");
+
+		private byte[] sig1a = Hex.Decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
+
+		// PSSExample1.2
+
+		private byte[] msg1b = Hex.Decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
+
+		private byte[] slt1b = Hex.Decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
+
+		private byte[] sig1b = Hex.Decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
+
+		//
+		// Example 2: A 1025-bit RSA keypair
+		//
+
+		private RsaKeyParameters pub2 = new RsaKeyParameters(false,
+					new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+					new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv2 = new RsaPrivateCrtKeyParameters(
+					new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+					new BigInteger("010001", 16),
+					new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
+					new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
+					new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
+					new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
+					new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
+					new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
+
+		// PSS Example 2.1
+
+		private byte[] msg2a = Hex.Decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
+		private byte[] slt2a = Hex.Decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
+		private byte[] sig2a = Hex.Decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
+
+		// PSS Example 2.2
+
+		private byte[] msg2b = Hex.Decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de18 [...]
+		private byte[] slt2b = Hex.Decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
+		private byte[] sig2b = Hex.Decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
+
+		//
+		//  Example 4: A 1027-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub4 = new RsaKeyParameters(false,
+					new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+					new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv4 = new RsaPrivateCrtKeyParameters(
+					new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+					new BigInteger("010001", 16),
+					new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
+					new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
+					new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
+					new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
+					new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
+					new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
+
+		// PSS Example 4.1
+
+		private byte[] msg4a = Hex.Decode("9fb03b827c8217d9");
+
+		private byte[] slt4a = Hex.Decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
+
+		private byte[] sig4a = Hex.Decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
+
+		// PSS Example 4.2
+
+		private byte[] msg4b = Hex.Decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
+
+		private byte[] slt4b = Hex.Decode("22d71d54363a4217aa55113f059b3384e3e57e44");
+
+		private byte[] sig4b = Hex.Decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
+
+
+		//
+		// Example 8: A 1031-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub8 = new RsaKeyParameters(false,
+					new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+					new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv8 = new RsaPrivateCrtKeyParameters(
+					new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+					new BigInteger("010001", 16),
+					new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
+					new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
+					new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
+					new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
+					new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
+					new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
+
+		// PSS Example 8.1
+
+		private byte[] msg8a = Hex.Decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
+
+		private byte[] slt8a = Hex.Decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
+
+		private byte[] sig8a = Hex.Decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
+
+		// PSS Example 8.2
+
+		private byte[] msg8b = Hex.Decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
+
+		private byte[] slt8b = Hex.Decode("435c098aa9909eb2377f1248b091b68987ff1838");
+
+		private byte[] sig8b = Hex.Decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
+
+		//
+		// Example 9: A 1536-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub9 = new RsaKeyParameters(false,
+					new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+					new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv9 = new RsaPrivateCrtKeyParameters(
+					new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+					new BigInteger("010001", 16),
+					new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
+					new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
+					new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
+					new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
+					new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
+					new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
+
+		// PSS Example 9.1
+
+		private byte[] msg9a = Hex.Decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
+
+		private byte[] slt9a = Hex.Decode("c0a425313df8d7564bd2434d311523d5257eed80");
+
+		private byte[] sig9a = Hex.Decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
+
+		// PSS Example 9.2
+
+		private byte[] msg9b = Hex.Decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
+
+		private byte[] slt9b = Hex.Decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
+
+		private byte[] sig9b = Hex.Decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
+
+
+		public override string Name
+		{
+			get { return "PssBlindTest"; }
+		}
+
+		private void testSig(
+			int                 id,
+			RsaKeyParameters    pub,
+			RsaKeyParameters    prv,
+			byte[]              slt,
+			byte[]              msg,
+			byte[]              sig)
+		{
+			RsaBlindingFactorGenerator blindFactorGen = new RsaBlindingFactorGenerator();
+			RsaBlindingEngine blindingEngine = new RsaBlindingEngine();
+			PssSigner blindSigner = new PssSigner(blindingEngine, new Sha1Digest(), 20);
+			PssSigner signer = new PssSigner(new RsaEngine(), new Sha1Digest(), 20);
+
+			blindFactorGen.Init(pub);
+
+			BigInteger blindFactor = blindFactorGen.GenerateBlindingFactor();
+			RsaBlindingParameters parameters = new RsaBlindingParameters(pub, blindFactor);
+
+			// generate a blind signature
+			blindSigner.Init(true, new ParametersWithRandom(parameters, new FixedRandom(slt)));
+
+			blindSigner.BlockUpdate(msg, 0, msg.Length);
+
+			byte[] blindedData = blindSigner.GenerateSignature();
+
+			RsaEngine signerEngine = new RsaEngine();
+
+			signerEngine.Init(true, prv);
+
+			byte[] blindedSig = signerEngine.ProcessBlock(blindedData, 0, blindedData.Length);
+
+			// unblind the signature
+			blindingEngine.Init(false, parameters);
+
+			byte[] s = blindingEngine.ProcessBlock(blindedSig, 0, blindedSig.Length);
+
+			//signature verification
+			if (!AreEqual(s, sig))
+			{
+				Fail("test " + id + " failed generation");
+			}
+	        
+			//verify signature with PssSigner
+			signer.Init(false, pub);
+			signer.BlockUpdate(msg, 0, msg.Length);
+
+			if (!signer.VerifySignature(s))
+			{
+        		Fail("test " + id + " failed PssSigner verification");
+			}
+		}
+
+		private bool isProcessingOkay(
+			RsaKeyParameters    pub,
+			RsaKeyParameters    prv,
+			byte[]              data,
+			SecureRandom        random)
+		{
+			RsaBlindingFactorGenerator blindFactorGen = new RsaBlindingFactorGenerator();
+			RsaBlindingEngine blindingEngine = new RsaBlindingEngine();
+			PssSigner blindSigner = new PssSigner(blindingEngine, new Sha1Digest(), 20);
+			PssSigner pssEng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20);
+
+			random.NextBytes(data);
+
+			blindFactorGen.Init(pub);
+
+			BigInteger blindFactor = blindFactorGen.GenerateBlindingFactor();
+			RsaBlindingParameters parameters = new RsaBlindingParameters(pub, blindFactor);
+
+			// generate a blind signature
+			blindSigner.Init(true, new ParametersWithRandom(parameters, random));
+
+			blindSigner.BlockUpdate(data, 0, data.Length);
+
+			byte[] blindedData = blindSigner.GenerateSignature();
+
+			RsaEngine signerEngine = new RsaEngine();
+
+			signerEngine.Init(true, prv);
+
+			byte[] blindedSig = signerEngine.ProcessBlock(blindedData, 0, blindedData.Length);
+
+			// unblind the signature
+			blindingEngine.Init(false, parameters);
+
+			byte[] s = blindingEngine.ProcessBlock(blindedSig, 0, blindedSig.Length);
+
+			//verify signature with PssSigner
+			pssEng.Init(false, pub);
+			pssEng.BlockUpdate(data, 0, data.Length);
+
+			return pssEng.VerifySignature(s);
+		}
+
+		public override void PerformTest()
+		{
+			testSig(1, pub1, prv1, slt1a, msg1a, sig1a);
+			testSig(2, pub1, prv1, slt1b, msg1b, sig1b);
+			testSig(3, pub2, prv2, slt2a, msg2a, sig2a);
+			testSig(4, pub2, prv2, slt2b, msg2b, sig2b);
+			testSig(5, pub4, prv4, slt4a, msg4a, sig4a);
+			testSig(6, pub4, prv4, slt4b, msg4b, sig4b);
+			testSig(7, pub8, prv8, slt8a, msg8a, sig8a);
+			testSig(8, pub8, prv8, slt8b, msg8b, sig8b);
+			testSig(9, pub9, prv9, slt9a, msg9a, sig9a);
+			testSig(10, pub9, prv9, slt9b, msg9b, sig9b);
+	        
+			//
+			// loop test
+			//
+			int failed = 0;
+			byte[] data = new byte[DATA_LENGTH];
+
+			SecureRandom    random = new SecureRandom();
+
+
+			RsaKeyParameters[] kprv ={prv1, prv2, prv4, prv8, prv9};
+			RsaKeyParameters[] kpub ={pub1, pub2, pub4, pub8, pub9};
+
+			for (int j = 0, i = 0; j < NUM_TESTS; j++, i++)
+			{
+        		if (i == kprv.Length)
+				{
+					i = 0;
+				}
+
+				if (!isProcessingOkay(kpub[i], kprv[i], data, random))
+				{
+            		failed++;
+				}
+			}
+
+			if (failed != 0)
+			{
+				Fail("loop test failed - failures: " + failed);
+			}
+
+			//
+			// key generation test
+			//
+			RsaKeyPairGenerator pGen = new RsaKeyPairGenerator();
+			RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x11), new SecureRandom(), 1024, 25);
+
+			pGen.Init(genParam);
+			failed = 0;
+
+			for (int k = 0; k < NUM_TESTS_WITH_KEY_GENERATION; k++)
+			{
+        		AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+				for (int j = 0; j < NUM_TESTS; j++)
+				{
+					if (!isProcessingOkay((RsaKeyParameters)pair.Public, (RsaKeyParameters)pair.Private, data, random))
+					{
+						failed++;
+					}
+				}
+			}
+
+			if (failed != 0)
+			{
+				Fail("loop test with key generation failed - failures: " + failed);
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PssBlindTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/PSSTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/PSSTest.cs
new file mode 100644
index 0000000..91d8d3a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/PSSTest.cs
@@ -0,0 +1,338 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks>RSA PSS test vectors for PKCS#1 V2.1</remarks>
+	[TestFixture]
+	public class PssTest
+		: SimpleTest
+	{
+		private const int DataLength = 1000;
+		private const int NumTests = 500;
+
+		private class FixedRandom
+			: SecureRandom
+		{
+			private readonly byte[] vals;
+
+			public FixedRandom(
+				byte[] vals)
+			{
+				this.vals = vals;
+			}
+
+			public override void NextBytes(
+				byte[] bytes)
+			{
+				Array.Copy(vals, 0, bytes, 0, vals.Length);
+			}
+		}
+
+		//
+		// Example 1: A 1024-bit RSA keypair
+		//
+		private RsaKeyParameters pub1 = new RsaKeyParameters(false,
+			new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+			new BigInteger("010001",16));
+
+		private RsaKeyParameters prv1 = new RsaPrivateCrtKeyParameters(
+			new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+			new BigInteger("010001",16),
+			new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+			new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+			new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+			new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+			new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+			new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+		// PSSExample1.1
+
+		private byte[] msg1a = Hex.Decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
+
+		private byte[] slt1a = Hex.Decode("dee959c7e06411361420ff80185ed57f3e6776af");
+
+		private byte[] sig1a = Hex.Decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
+
+		// PSSExample1.2
+
+		private byte[] msg1b = Hex.Decode("851384cdfe819c22ed6c4ccb30daeb5cf059bc8e1166b7e3530c4c233e2b5f8f71a1cca582d43ecc72b1bca16dfc7013226b9e");
+
+		private byte[] slt1b = Hex.Decode("ef2869fa40c346cb183dab3d7bffc98fd56df42d");
+
+		private byte[] sig1b = Hex.Decode("3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843");
+
+		//
+		// Example 2: A 1025-bit RSA keypair
+		//
+
+		private RsaKeyParameters pub2 = new RsaKeyParameters(false,
+			new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+			new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv2 = new RsaPrivateCrtKeyParameters(
+			new BigInteger("01d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c9", 16),
+			new BigInteger("010001", 16),
+			new BigInteger("027d147e4673057377fd1ea201565772176a7dc38358d376045685a2e787c23c15576bc16b9f444402d6bfc5d98a3e88ea13ef67c353eca0c0ddba9255bd7b8bb50a644afdfd1dd51695b252d22e7318d1b6687a1c10ff75545f3db0fe602d5f2b7f294e3601eab7b9d1cecd767f64692e3e536ca2846cb0c2dd486a39fa75b1", 16),
+			new BigInteger("016601e926a0f8c9e26ecab769ea65a5e7c52cc9e080ef519457c644da6891c5a104d3ea7955929a22e7c68a7af9fcad777c3ccc2b9e3d3650bce404399b7e59d1", 16),
+			new BigInteger("014eafa1d4d0184da7e31f877d1281ddda625664869e8379e67ad3b75eae74a580e9827abd6eb7a002cb5411f5266797768fb8e95ae40e3e8a01f35ff89e56c079", 16),
+			new BigInteger("e247cce504939b8f0a36090de200938755e2444b29539a7da7a902f6056835c0db7b52559497cfe2c61a8086d0213c472c78851800b171f6401de2e9c2756f31", 16),
+			new BigInteger("b12fba757855e586e46f64c38a70c68b3f548d93d787b399999d4c8f0bbd2581c21e19ed0018a6d5d3df86424b3abcad40199d31495b61309f27c1bf55d487c1", 16),
+			new BigInteger("564b1e1fa003bda91e89090425aac05b91da9ee25061e7628d5f51304a84992fdc33762bd378a59f030a334d532bd0dae8f298ea9ed844636ad5fb8cbdc03cad", 16));
+
+		// PSS Example 2.1
+
+		private byte[] msg2a = Hex.Decode("daba032066263faedb659848115278a52c44faa3a76f37515ed336321072c40a9d9b53bc05014078adf520875146aae70ff060226dcb7b1f1fc27e9360");
+		private byte[] slt2a = Hex.Decode("57bf160bcb02bb1dc7280cf0458530b7d2832ff7");
+		private byte[] sig2a = Hex.Decode("014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3");
+
+		// PSS Example 2.2
+
+		private byte[] msg2b = Hex.Decode("e4f8601a8a6da1be34447c0959c058570c3668cfd51dd5f9ccd6ad4411fe8213486d78a6c49f93efc2ca2288cebc2b9b60bd04b1e220d86e3d4848d709d032d1e8c6a070c6af9a499fcf95354b14ba6127c739de1bb0fd16431e46938aec0cf8ad9eb72e832a7035de9b7807bdc0ed8b68eb0f5ac2216be40ce920c0db0eddd3860ed788efaccaca502d8f2bd6d1a7c1f41ff46f1681c8f1f818e9c4f6d91a0c7803ccc63d76a6544d843e084e363b8acc55aa531733edb5dee5b5196e9f03e8b731b3776428d9e457fe3fbcb3db7274442d785890e9cb0854b6444dace791d7273de18 [...]
+		private byte[] slt2b = Hex.Decode("7f6dd359e604e60870e898e47b19bf2e5a7b2a90");
+		private byte[] sig2b = Hex.Decode("010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea");
+
+		//
+		//  Example 4: A 1027-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub4 = new RsaKeyParameters(false,
+			new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+			new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv4 = new RsaPrivateCrtKeyParameters(
+			new BigInteger("054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c3705", 16),
+			new BigInteger("010001", 16),
+			new BigInteger("fa041f8cd9697ceed38ec8caa275523b4dd72b09a301d3541d72f5d31c05cbce2d6983b36183af10690bd46c46131e35789431a556771dd0049b57461bf060c1f68472e8a67c25f357e5b6b4738fa541a730346b4a07649a2dfa806a69c975b6aba64678acc7f5913e89c622f2d8abb1e3e32554e39df94ba60c002e387d9011", 16),
+			new BigInteger("029232336d2838945dba9dd7723f4e624a05f7375b927a87abe6a893a1658fd49f47f6c7b0fa596c65fa68a23f0ab432962d18d4343bd6fd671a5ea8d148413995", 16),
+			new BigInteger("020ef5efe7c5394aed2272f7e81a74f4c02d145894cb1b3cab23a9a0710a2afc7e3329acbb743d01f680c4d02afb4c8fde7e20930811bb2b995788b5e872c20bb1", 16),
+			new BigInteger("026e7e28010ecf2412d9523ad704647fb4fe9b66b1a681581b0e15553a89b1542828898f27243ebab45ff5e1acb9d4df1b051fbc62824dbc6f6c93261a78b9a759", 16),
+			new BigInteger("012ddcc86ef655998c39ddae11718669e5e46cf1495b07e13b1014cd69b3af68304ad2a6b64321e78bf3bbca9bb494e91d451717e2d97564c6549465d0205cf421", 16),
+			new BigInteger("010600c4c21847459fe576703e2ebecae8a5094ee63f536bf4ac68d3c13e5e4f12ac5cc10ab6a2d05a199214d1824747d551909636b774c22cac0b837599abcc75", 16));
+
+		// PSS Example 4.1
+
+		private byte[] msg4a = Hex.Decode("9fb03b827c8217d9");
+
+		private byte[] slt4a = Hex.Decode("ed7c98c95f30974fbe4fbddcf0f28d6021c0e91d");
+
+		private byte[] sig4a = Hex.Decode("0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948");
+
+		// PSS Example 4.2
+
+		private byte[] msg4b = Hex.Decode("0ca2ad77797ece86de5bf768750ddb5ed6a3116ad99bbd17edf7f782f0db1cd05b0f677468c5ea420dc116b10e80d110de2b0461ea14a38be68620392e7e893cb4ea9393fb886c20ff790642305bf302003892e54df9f667509dc53920df583f50a3dd61abb6fab75d600377e383e6aca6710eeea27156e06752c94ce25ae99fcbf8592dbe2d7e27453cb44de07100ebb1a2a19811a478adbeab270f94e8fe369d90b3ca612f9f");
+
+		private byte[] slt4b = Hex.Decode("22d71d54363a4217aa55113f059b3384e3e57e44");
+
+		private byte[] sig4b = Hex.Decode("049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598");
+
+
+		//
+		// Example 8: A 1031-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub8 = new RsaKeyParameters(false,
+			new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+			new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv8 = new RsaPrivateCrtKeyParameters(
+			new BigInteger("495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f", 16),
+			new BigInteger("010001", 16),
+			new BigInteger("6c66ffe98980c38fcdeab5159898836165f4b4b817c4f6a8d486ee4ea9130fe9b9092bd136d184f95f504a607eac565846d2fdd6597a8967c7396ef95a6eeebb4578a643966dca4d8ee3de842de63279c618159c1ab54a89437b6a6120e4930afb52a4ba6ced8a4947ac64b30a3497cbe701c2d6266d517219ad0ec6d347dbe9", 16),
+			new BigInteger("08dad7f11363faa623d5d6d5e8a319328d82190d7127d2846c439b0ab72619b0a43a95320e4ec34fc3a9cea876422305bd76c5ba7be9e2f410c8060645a1d29edb", 16),
+			new BigInteger("0847e732376fc7900f898ea82eb2b0fc418565fdae62f7d9ec4ce2217b97990dd272db157f99f63c0dcbb9fbacdbd4c4dadb6df67756358ca4174825b48f49706d", 16),
+			new BigInteger("05c2a83c124b3621a2aa57ea2c3efe035eff4560f33ddebb7adab81fce69a0c8c2edc16520dda83d59a23be867963ac65f2cc710bbcfb96ee103deb771d105fd85", 16),
+			new BigInteger("04cae8aa0d9faa165c87b682ec140b8ed3b50b24594b7a3b2c220b3669bb819f984f55310a1ae7823651d4a02e99447972595139363434e5e30a7e7d241551e1b9", 16),
+			new BigInteger("07d3e47bf686600b11ac283ce88dbb3f6051e8efd04680e44c171ef531b80b2b7c39fc766320e2cf15d8d99820e96ff30dc69691839c4b40d7b06e45307dc91f3f", 16));
+
+		// PSS Example 8.1
+
+		private byte[] msg8a = Hex.Decode("81332f4be62948415ea1d899792eeacf6c6e1db1da8be13b5cea41db2fed467092e1ff398914c714259775f595f8547f735692a575e6923af78f22c6997ddb90fb6f72d7bb0dd5744a31decd3dc3685849836ed34aec596304ad11843c4f88489f209735f5fb7fdaf7cec8addc5818168f880acbf490d51005b7a8e84e43e54287977571dd99eea4b161eb2df1f5108f12a4142a83322edb05a75487a3435c9a78ce53ed93bc550857d7a9fb");
+
+		private byte[] slt8a = Hex.Decode("1d65491d79c864b373009be6f6f2467bac4c78fa");
+
+		private byte[] sig8a = Hex.Decode("0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5");
+
+		// PSS Example 8.2
+
+		private byte[] msg8b = Hex.Decode("e2f96eaf0e05e7ba326ecca0ba7fd2f7c02356f3cede9d0faabf4fcc8e60a973e5595fd9ea08");
+
+		private byte[] slt8b = Hex.Decode("435c098aa9909eb2377f1248b091b68987ff1838");
+
+		private byte[] sig8b = Hex.Decode("2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e");
+
+		//
+		// Example 9: A 1536-bit RSA key pair
+		//
+
+		private RsaKeyParameters pub9 = new RsaKeyParameters(false,
+			new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+			new BigInteger("010001", 16));
+
+		private RsaKeyParameters prv9 = new RsaPrivateCrtKeyParameters(
+			new BigInteger("e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b", 16),
+			new BigInteger("010001", 16),
+			new BigInteger("6a7fd84fb85fad073b34406db74f8d61a6abc12196a961dd79565e9da6e5187bce2d980250f7359575359270d91590bb0e427c71460b55d51410b191bcf309fea131a92c8e702738fa719f1e0041f52e40e91f229f4d96a1e6f172e15596b4510a6daec26105f2bebc53316b87bdf21311666070e8dfee69d52c71a976caae79c72b68d28580dc686d9f5129d225f82b3d615513a882b3db91416b48ce08888213e37eeb9af800d81cab328ce420689903c00c7b5fd31b75503a6d419684d629", 16),
+			new BigInteger("f8eb97e98df12664eefdb761596a69ddcd0e76daece6ed4bf5a1b50ac086f7928a4d2f8726a77e515b74da41988f220b1cc87aa1fc810ce99a82f2d1ce821edced794c6941f42c7a1a0b8c4d28c75ec60b652279f6154a762aed165d47dee367", 16),
+			new BigInteger("ed4d71d0a6e24b93c2e5f6b4bbe05f5fb0afa042d204fe3378d365c2f288b6a8dad7efe45d153eef40cacc7b81ff934002d108994b94a5e4728cd9c963375ae49965bda55cbf0efed8d6553b4027f2d86208a6e6b489c176128092d629e49d3d", 16),
+			new BigInteger("2bb68bddfb0c4f56c8558bffaf892d8043037841e7fa81cfa61a38c5e39b901c8ee71122a5da2227bd6cdeeb481452c12ad3d61d5e4f776a0ab556591befe3e59e5a7fddb8345e1f2f35b9f4cee57c32414c086aec993e9353e480d9eec6289f", 16),
+			new BigInteger("4ff897709fad079746494578e70fd8546130eeab5627c49b080f05ee4ad9f3e4b7cba9d6a5dff113a41c3409336833f190816d8a6bc42e9bec56b7567d0f3c9c696db619b245d901dd856db7c8092e77e9a1cccd56ee4dba42c5fdb61aec2669", 16),
+			new BigInteger("77b9d1137b50404a982729316efafc7dfe66d34e5a182600d5f30a0a8512051c560d081d4d0a1835ec3d25a60f4e4d6aa948b2bf3dbb5b124cbbc3489255a3a948372f6978496745f943e1db4f18382ceaa505dfc65757bb3f857a58dce52156", 16));
+
+		// PSS Example 9.1
+
+		private byte[] msg9a = Hex.Decode("a88e265855e9d7ca36c68795f0b31b591cd6587c71d060a0b3f7f3eaef43795922028bc2b6ad467cfc2d7f659c5385aa70ba3672cdde4cfe4970cc7904601b278872bf51321c4a972f3c95570f3445d4f57980e0f20df54846e6a52c668f1288c03f95006ea32f562d40d52af9feb32f0fa06db65b588a237b34e592d55cf979f903a642ef64d2ed542aa8c77dc1dd762f45a59303ed75e541ca271e2b60ca709e44fa0661131e8d5d4163fd8d398566ce26de8730e72f9cca737641c244159420637028df0a18079d6208ea8b4711a2c750f5");
+
+		private byte[] slt9a = Hex.Decode("c0a425313df8d7564bd2434d311523d5257eed80");
+
+		private byte[] sig9a = Hex.Decode("586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e");
+
+		// PSS Example 9.2
+
+		private byte[] msg9b = Hex.Decode("c8c9c6af04acda414d227ef23e0820c3732c500dc87275e95b0d095413993c2658bc1d988581ba879c2d201f14cb88ced153a01969a7bf0a7be79c84c1486bc12b3fa6c59871b6827c8ce253ca5fefa8a8c690bf326e8e37cdb96d90a82ebab69f86350e1822e8bd536a2e");
+
+		private byte[] slt9b = Hex.Decode("b307c43b4850a8dac2f15f32e37839ef8c5c0e91");
+
+		private byte[] sig9b = Hex.Decode("80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958");
+
+
+		public override string Name
+		{
+			get { return "PSSTest"; }
+		}
+
+		private void doTestSig(
+			int					id,
+			RsaKeyParameters	pub,
+			RsaKeyParameters	prv,
+			byte[]				slt,
+			byte[]				msg,
+			byte[]				sig)
+		{
+			PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20);
+
+			eng.Init(true, new ParametersWithRandom(prv, new FixedRandom(slt)));
+
+			eng.BlockUpdate(msg, 0, msg.Length);
+
+			byte[] s = eng.GenerateSignature();
+
+			if (!AreEqual(s, sig))
+			{
+				Fail("test " + id + " failed generation");
+			}
+
+			eng.Init(false, pub);
+
+			eng.BlockUpdate(msg, 0, msg.Length);
+
+			if (!eng.VerifySignature(s))
+			{
+				Fail("test " + id + " failed verification");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			doTestSig(1, pub1, prv1, slt1a, msg1a, sig1a);
+			doTestSig(2, pub1, prv1, slt1b, msg1b, sig1b);
+			doTestSig(3, pub2, prv2, slt2a, msg2a, sig2a);
+			doTestSig(4, pub2, prv2, slt2b, msg2b, sig2b);
+			doTestSig(5, pub4, prv4, slt4a, msg4a, sig4a);
+			doTestSig(6, pub4, prv4, slt4b, msg4b, sig4b);
+			doTestSig(7, pub8, prv8, slt8a, msg8a, sig8a);
+			doTestSig(8, pub8, prv8, slt8b, msg8b, sig8b);
+			doTestSig(9, pub9, prv9, slt9a, msg9a, sig9a);
+			doTestSig(10, pub9, prv9, slt9b, msg9b, sig9b);
+
+			//
+			// loop test - sha-1 only
+			//
+			PssSigner eng = new PssSigner(new RsaEngine(), new Sha1Digest(), 20);
+			int failed = 0;
+			byte[] data = new byte[DataLength];
+
+			SecureRandom random = new SecureRandom();
+			random.NextBytes(data);
+
+			for (int j = 0; j < NumTests; j++)
+			{
+				eng.Init(true, new ParametersWithRandom(prv8, random));
+
+				eng.BlockUpdate(data, 0, data.Length);
+
+				byte[] s = eng.GenerateSignature();
+
+				eng.Init(false, pub8);
+
+				eng.BlockUpdate(data, 0, data.Length);
+
+				if (!eng.VerifySignature(s))
+				{
+					failed++;
+				}
+			}
+
+			if (failed != 0)
+			{
+				Fail("loop test failed - failures: " + failed);
+			}
+
+			//
+			// loop test - sha-256 and sha-1
+			//
+			eng = new PssSigner(new RsaEngine(), new Sha256Digest(), new Sha1Digest(), 20);
+			failed = 0;
+			data = new byte[DataLength];
+
+			random.NextBytes(data);
+
+			for (int j = 0; j < NumTests; j++)
+			{
+				eng.Init(true, new ParametersWithRandom(prv8, random));
+
+				eng.BlockUpdate(data, 0, data.Length);
+
+				byte[] s = eng.GenerateSignature();
+
+				eng.Init(false, pub8);
+
+				eng.BlockUpdate(data, 0, data.Length);
+
+				if (!eng.VerifySignature(s))
+				{
+					failed++;
+				}
+			}
+
+			if (failed != 0)
+			{
+				Fail("loop test failed - failures: " + failed);
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PssTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/PaddingTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/PaddingTest.cs
new file mode 100644
index 0000000..6f41d75
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/PaddingTest.cs
@@ -0,0 +1,171 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* General Padding tests.
+	*/
+	[TestFixture]
+	public class PaddingTest : SimpleTest
+	{
+		public PaddingTest()
+		{
+		}
+
+		private void blockCheck(
+			PaddedBufferedBlockCipher   cipher,
+			IBlockCipherPadding          padding,
+			KeyParameter                key,
+			byte[]                      data)
+		{
+			byte[]  outBytes = new byte[data.Length + 8];
+			byte[]  dec = new byte[data.Length];
+
+			try
+			{
+				cipher.Init(true, key);
+
+				int    len = cipher.ProcessBytes(data, 0, data.Length, outBytes, 0);
+
+				len += cipher.DoFinal(outBytes, len);
+
+				cipher.Init(false, key);
+
+				int    decLen = cipher.ProcessBytes(outBytes, 0, len, dec, 0);
+
+				decLen += cipher.DoFinal(dec, decLen);
+
+				if (!AreEqual(data, dec))
+				{
+					Fail("failed to decrypt - i = " + data.Length + ", padding = " + padding.PaddingName);
+				}
+			}
+			catch (Exception e)
+			{
+				Fail("Exception - " + e.ToString(), e);
+			}
+		}
+
+		public void doTestPadding(
+			IBlockCipherPadding  padding,
+			SecureRandom        rand,
+			byte[]              ffVector,
+			byte[]              ZeroVector)
+		{
+			PaddedBufferedBlockCipher    cipher = new PaddedBufferedBlockCipher(new DesEngine(), padding);
+			KeyParameter                 key = new KeyParameter(Hex.Decode("0011223344556677"));
+
+			//
+			// ff test
+			//
+			byte[]    data = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 };
+
+			if (ffVector != null)
+			{
+				padding.AddPadding(data, 3);
+
+				if (!AreEqual(data, ffVector))
+				{
+					Fail("failed ff test for " + padding.PaddingName);
+				}
+			}
+
+			//
+			// zero test
+			//
+			if (ZeroVector != null)
+			{
+				data = new byte[8];
+				padding.AddPadding(data, 4);
+
+				if (!AreEqual(data, ZeroVector))
+				{
+					Fail("failed zero test for " + padding.PaddingName);
+				}
+			}
+
+			for (int i = 1; i != 200; i++)
+			{
+				data = new byte[i];
+
+				rand.NextBytes(data);
+
+				blockCheck(cipher, padding, key, data);
+			}
+		}
+
+		public override void PerformTest()
+		{
+			SecureRandom    rand = new SecureRandom(new byte[20]);
+
+			rand.SetSeed(DateTime.Now.Ticks);
+
+			doTestPadding(new Pkcs7Padding(), rand,
+				Hex.Decode("ffffff0505050505"),
+				Hex.Decode("0000000004040404"));
+
+			Pkcs7Padding padder = new Pkcs7Padding();
+			try
+			{
+				padder.PadCount(new byte[8]);
+
+				Fail("invalid padding not detected");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!"pad block corrupted".Equals(e.Message))
+				{
+					Fail("wrong exception for corrupt padding: " + e);
+				}
+			} 
+
+			doTestPadding(new ISO10126d2Padding(), rand,
+				null,
+				null);
+
+			doTestPadding(new X923Padding(), rand,
+				null,
+				null);
+
+			doTestPadding(new TbcPadding(), rand,
+				Hex.Decode("ffffff0000000000"),
+				Hex.Decode("00000000ffffffff"));
+
+			doTestPadding(new ZeroBytePadding(), rand,
+				Hex.Decode("ffffff0000000000"),
+				null);
+
+			doTestPadding(new ISO7816d4Padding(), rand,
+				Hex.Decode("ffffff8000000000"),
+				Hex.Decode("0000000080000000"));
+		}
+
+		public override string Name
+		{
+			get { return "PaddingTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PaddingTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs12Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs12Test.cs
new file mode 100644
index 0000000..29d5a39
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs12Test.cs
@@ -0,0 +1,101 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks> test for Pkcs12 key generation - vectors from
+	/// <a href="http://www.drh-consultancy.demon.co.uk/test.txt">
+	///	http://www.drh-consultancy.demon.co.uk/test.txt</a>
+	/// </remarks>
+	[TestFixture]
+	public class Pkcs12Test
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "Pkcs12Test"; }
+		}
+
+		internal char[] password1 = new char[]{'s', 'm', 'e', 'g'};
+		internal char[] password2 = new char[]{'q', 'u', 'e', 'e', 'g'};
+
+		private void Run1(int id, char[] password, byte[] salt, int iCount, byte[] result)
+		{
+			PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha1Digest());
+
+			generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password), salt, iCount);
+
+			ICipherParameters key = generator.GenerateDerivedParameters("DESEDE", 24 * 8);
+
+			if (!Arrays.AreEqual(result, ((KeyParameter) key).GetKey()))
+			{
+				Fail("id " + id + " Failed");
+			}
+		}
+
+		private void Run2(int id, char[] password, byte[] salt, int iCount, byte[] result)
+		{
+			PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha1Digest());
+
+			generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password), salt, iCount);
+
+			ParametersWithIV parameters = (ParametersWithIV)
+				generator.GenerateDerivedParameters("DES", 64, 64);
+
+			if (!Arrays.AreEqual(result, parameters.GetIV()))
+			{
+				Fail("id " + id + " Failed");
+			}
+		}
+
+		private void Run3(int id, char[] password, byte[] salt, int iCount, byte[] result)
+		{
+			PbeParametersGenerator generator = new Pkcs12ParametersGenerator(new Sha1Digest());
+
+			generator.Init(PbeParametersGenerator.Pkcs12PasswordToBytes(password), salt, iCount);
+
+			ICipherParameters key = generator.GenerateDerivedMacParameters(160);
+
+			if (!Arrays.AreEqual(result, ((KeyParameter) key).GetKey()))
+			{
+				Fail("id " + id + " Failed");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			Run1(1, password1, Hex.Decode("0A58CF64530D823F"), 1, Hex.Decode("8AAAE6297B6CB04642AB5B077851284EB7128F1A2A7FBCA3"));
+			Run2(2, password1, Hex.Decode("0A58CF64530D823F"), 1, Hex.Decode("79993DFE048D3B76"));
+			Run1(3, password1, Hex.Decode("642B99AB44FB4B1F"), 1, Hex.Decode("F3A95FEC48D7711E985CFE67908C5AB79FA3D7C5CAA5D966"));
+			Run2(4, password1, Hex.Decode("642B99AB44FB4B1F"), 1, Hex.Decode("C0A38D64A79BEA1D"));
+			Run3(5, password1, Hex.Decode("3D83C0E4546AC140"), 1, Hex.Decode("8D967D88F6CAA9D714800AB3D48051D63F73A312"));
+			Run1(6, password2, Hex.Decode("05DEC959ACFF72F7"), 1000, Hex.Decode("ED2034E36328830FF09DF1E1A07DD357185DAC0D4F9EB3D4"));
+			Run2(7, password2, Hex.Decode("05DEC959ACFF72F7"), 1000, Hex.Decode("11DEDAD7758D4860"));
+			Run1(8, password2, Hex.Decode("1682C0FC5B3F7EC5"), 1000, Hex.Decode("483DD6E919D7DE2E8E648BA8F862F3FBFBDC2BCB2C02957F"));
+			Run2(9, password2, Hex.Decode("1682C0FC5B3F7EC5"), 1000, Hex.Decode("9D461D1B00355C50"));
+			Run3(10, password2, Hex.Decode("263216FCC2FAB31C"), 1000, Hex.Decode("5EC4C7A80DF652294C3925B6489A7AB857C83476"));
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Pkcs12Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs5Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs5Test.cs
new file mode 100644
index 0000000..8066e8e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Pkcs5Test.cs
@@ -0,0 +1,243 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+    /// <summary> A test class for Pkcs5 PbeS2 with PBKDF2 (Pkcs5 v2.0) using
+    /// test vectors provider at
+    /// <a href="http://www.rsasecurity.com/rsalabs/pkcs/pkcs-5/index.html">
+    /// RSA's Pkcs5 Page</a>
+    /// <br/>
+    /// The vectors are Base 64 encoded and encrypted using the password "password"
+    /// (without quotes). They should all yield the same PrivateKeyInfo object.
+    /// </summary>
+    [TestFixture]
+    public class Pkcs5Test
+        : SimpleTest
+    {
+        public override string Name
+        {
+            get { return "Pkcs5Test"; }
+        }
+
+        /// <summary> encrypted using des-cbc.</summary>
+        internal static byte[] sample1;
+
+        /// <summary> encrypted using des-ede3-cbc.</summary>
+        internal static byte[] sample2;
+
+        /// <summary> encrypted using rc2-cbc.</summary>
+        internal static byte[] sample3;
+
+        internal static byte[] result;
+
+        private class PbeTest
+            : SimpleTest
+        {
+            private Pkcs5Test enclosingInstance;
+
+            private void InitBlock(
+                Pkcs5Test enclosingInstance)
+            {
+                this.enclosingInstance = enclosingInstance;
+            }
+
+            public override string Name
+            {
+                get { return cipher.AlgorithmName + " Pkcs5S2 Test " + id; }
+            }
+
+            public Pkcs5Test Enclosing_Instance
+            {
+                get { return enclosingInstance; }
+            }
+
+            internal int id;
+            internal BufferedBlockCipher cipher;
+            internal byte[] sample;
+            internal int keySize;
+
+            internal PbeTest(
+                Pkcs5Test			enclosingInstance,
+                int					id,
+                BufferedBlockCipher	cipher,
+                byte[]				sample,
+                int					keySize)
+            {
+                InitBlock(enclosingInstance);
+
+                this.id = id;
+                this.cipher = cipher;
+                this.sample = sample;
+                this.keySize = keySize;
+            }
+
+            public override void PerformTest()
+            {
+                char[] password = "password".ToCharArray();
+                PbeParametersGenerator generator = new Pkcs5S2ParametersGenerator();
+
+                EncryptedPrivateKeyInfo info = null;
+                try
+                {
+                    info = EncryptedPrivateKeyInfo.GetInstance(Asn1Object.FromByteArray(sample));
+                }
+                catch (System.Exception e)
+                {
+                    Fail("failed construction - exception " + e.ToString(), e);
+                }
+
+                PbeS2Parameters alg = PbeS2Parameters.GetInstance(info.EncryptionAlgorithm.Parameters);
+                Pbkdf2Params func = Pbkdf2Params.GetInstance(alg.KeyDerivationFunc.Parameters);
+                EncryptionScheme scheme = alg.EncryptionScheme;
+
+                if (func.KeyLength != null)
+                {
+                    keySize = func.KeyLength.IntValue * 8;
+                }
+
+                int iterationCount = func.IterationCount.IntValue;
+                byte[] salt = func.GetSalt();
+
+                generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt, iterationCount);
+
+                DerObjectIdentifier algOid = scheme.ObjectID;
+
+                byte[] iv;
+                if (algOid.Equals(PkcsObjectIdentifiers.RC2Cbc))
+                {
+                    RC2CbcParameter rc2Params = RC2CbcParameter.GetInstance(scheme.Asn1Object);
+                    iv = rc2Params.GetIV();
+                }
+                else
+                {
+                    iv = ((Asn1OctetString) scheme.Asn1Object).GetOctets();
+                }
+
+                ICipherParameters param = new ParametersWithIV(
+                    generator.GenerateDerivedParameters(algOid.Id, keySize), iv);
+
+                cipher.Init(false, param);
+
+                byte[] data = info.GetEncryptedData();
+                byte[] outBytes = new byte[cipher.GetOutputSize(data.Length)];
+                int len = cipher.ProcessBytes(data, 0, data.Length, outBytes, 0);
+
+                try
+                {
+                    len += cipher.DoFinal(outBytes, len);
+                }
+                catch (Exception e)
+                {
+                    Fail("failed DoFinal - exception " + e.ToString());
+                }
+
+                if (result.Length != len)
+                {
+                    Fail("failed length");
+                }
+
+                for (int i = 0; i != len; i++)
+                {
+                    if (outBytes[i] != result[i])
+                    {
+                        Fail("failed comparison");
+                    }
+                }
+            }
+        }
+
+        public override void PerformTest()
+        {
+            BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEngine()));
+            SimpleTest test = new PbeTest(this, 0, cipher, sample1, 64);
+
+            test.PerformTest();
+
+            cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEdeEngine()));
+            test = new PbeTest(this, 1, cipher, sample2, 192);
+
+            test.PerformTest();
+
+            cipher = new PaddedBufferedBlockCipher(new CbcBlockCipher(new RC2Engine()));
+            test = new PbeTest(this, 2, cipher, sample3, 0);
+
+            test.PerformTest();
+
+            //
+            // RFC 3211 tests
+            //
+            char[] password = "password".ToCharArray();
+            PbeParametersGenerator generator = new Pkcs5S2ParametersGenerator();
+
+            byte[] salt = Hex.Decode("1234567878563412");
+
+            generator.Init(
+                PbeParametersGenerator.Pkcs5PasswordToBytes(password),
+                salt,
+                5);
+
+            if (!AreEqual(((KeyParameter)generator.GenerateDerivedParameters("DES", 64)).GetKey(),
+                Hex.Decode("d1daa78615f287e6")))
+            {
+                Fail("64 test failed");
+            }
+
+            password = "All n-entities must communicate with other n-entities via n-1 entiteeheehees".ToCharArray();
+
+            generator.Init(
+                PbeParametersGenerator.Pkcs5PasswordToBytes(password),
+                salt,
+                500);
+
+            if (!AreEqual(((KeyParameter)generator.GenerateDerivedParameters("DESEDE", 192)).GetKey(),
+                Hex.Decode("6a8970bf68c92caea84a8df28510858607126380cc47ab2d")))
+            {
+                Fail("192 test failed");
+            }
+
+            generator.Init(PbeParametersGenerator.Pkcs5PasswordToBytes(password), salt, 60000);
+            if (!AreEqual(((KeyParameter)generator.GenerateDerivedParameters("DESEDE", 192)).GetKey(),
+                Hex.Decode("29aaef810c12ecd2236bbcfb55407f9852b5573dc1c095bb")))
+            {
+                Fail("192 (60000) test failed");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Pkcs5Test());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        static Pkcs5Test()
+        {
+            sample1 = Base64.Decode("MIIBozA9BgkqhkiG9w0BBQ0wMDAbBgkqhkiG9w0BBQwwDgQIfWBDXwLp4K4CAggA" + "MBEGBSsOAwIHBAiaCF/AvOgQ6QSCAWDWX4BdAzCRNSQSANSuNsT5X8mWYO27mr3Y" + "9c9LoBVXGNmYWKA77MI4967f7SmjNcgXj3xNE/jmnVz6hhsjS8E5VPT3kfyVkpdZ" + "0lr5e9Yk2m3JWpPU7++v5zBkZmC4V/MwV/XuIs6U+vykgzMgpxQg0oZKS9zgmiZo" + "f/4dOCL0UtCDnyOSvqT7mCVIcMDIEKu8QbVlgZYBop08l60EuEU3gARUo8WsYQmO" + "Dz/ldx0Z+znIT0SXVuOwc+RVItC5T/Qx+aijmmpt+9l14nmaGBrEkmuhmtdvU/4v" + "aptewGRgmjOfD6cqK+zs0O5NrrJ3P/6ZSxXj91CQg [...]
+            sample2 = Base64.Decode("MIIBpjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIeFeOWl1jywYCAggA" + "MBQGCCqGSIb3DQMHBAjUJ5eGBhQGtQSCAWBrHrRgqO8UUMLcWzZEtpk1l3mjxiF/" + "koCMkHsFwowgyWhEbgIkTgbSViK54LVK8PskekcGNLph+rB6bGZ7pPbL5pbXASJ8" + "+MkQcG3FZdlS4Ek9tTJDApj3O1UubZGFG4uvTlJJFbF1BOJ3MkY3XQ9Gl1qwv7j5" + "6e103Da7Cq9+oIDKmznza78XXQYrUsPo8mJGjUxPskEYlzwvHjKubRnYm/K6RKhi" + "5f4zX4BQ/Dt3H812ZjRXrsjAJP0KrD/jyD/jCT7zNBVPH1izBds+RwizyQAHwfNJ" + "BFR78TH4cgzB619X47FDVOnT0LqQNVd0O3cSwnPrX [...]
+            sample3 = Base64.Decode("MIIBrjBIBgkqhkiG9w0BBQ0wOzAeBgkqhkiG9w0BBQwwEQQIrHyQPBZqWLUCAggA" + "AgEQMBkGCCqGSIb3DQMCMA0CAToECEhbh7YZKiPSBIIBYCT1zp6o5jpFlIkgwPop" + "7bW1+8ACr4exqzkeb3WflQ8cWJ4cURxzVdvxUnXeW1VJdaQZtjS/QHs5GhPTG/0f" + "wtvnaPfwrIJ3FeGaZfcg2CrYhalOFmEb4xrE4KyoEQmUN8tb/Cg94uzd16BOPw21" + "RDnE8bnPdIGY7TyL95kbkqH23mK53pi7h+xWIgduW+atIqDyyt55f7WMZcvDvlj6" + "VpN/V0h+qxBHL274WA4dj6GYgeyUFpi60HdGCK7By2TBy8h1ZvKGjmB9h8jZvkx1" + "MkbRumXxyFsowTZawyYvO8Um6lbfEDP9zIEUq0IV8 [...]
+            result = Hex.Decode("30820155020100300d06092a864886f70d01010105000482013f3082013b020100024100" + "debbfc2c09d61bada2a9462f24224e54cc6b3cc0755f15ce318ef57e79df17026b6a85cc" + "a12428027245045df2052a329a2f9ad3d17b78a10572ad9b22bf343b020301000102402d" + "90a96adcec472743527bc023153d8f0d6e96b40c8ed228276d467d843306429f8670559b" + "f376dd41857f6397c2fc8d95e0e53ed62de420b855430ee4a1b8a1022100ffcaf0838239" + "31e073ff534f06a5d415b3d414bc614a4544a3dff7ed271817eb022100deea30242117db"  [...]
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Poly1305Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Poly1305Test.cs
new file mode 100644
index 0000000..a151316
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Poly1305Test.cs
@@ -0,0 +1,395 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/*
+	 */
+	public class Poly1305Test
+		: SimpleTest
+	{
+		private const int MAXLEN = 1000;
+
+		private class KeyEngine
+			: IBlockCipher
+		{
+
+			private byte[] key;
+			private int blockSize;
+
+			public KeyEngine(int blockSize)
+			{
+				this.blockSize = blockSize;
+			}
+
+			public void Init(bool forEncryption, ICipherParameters parameters)
+			{
+				if (parameters is KeyParameter)
+				{
+					this.key = ((KeyParameter)parameters).GetKey();
+				}
+			}
+
+			public bool IsPartialBlockOkay 
+			{ 
+				get { return false; } 
+			}
+
+			public string AlgorithmName
+			{
+				get { return "Key"; }
+			}
+
+			public int GetBlockSize()
+			{
+				return blockSize;
+			}
+
+			public int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
+			{
+				Array.Copy(key, 0, output, outOff, key.Length);
+				return key.Length;
+			}
+
+			public void Reset()
+			{
+			}
+
+		}
+
+		private class TestCase
+		{
+			internal byte[] key;
+			internal byte[] nonce;
+			internal byte[] message;
+			internal byte[] expectedMac;
+
+			public TestCase(string key, string nonce, string message, string expectedMac)
+			{
+				this.key = Hex.Decode(key);
+				// nacl test case keys are not pre-Clamped
+				Poly1305KeyGenerator.Clamp(this.key);
+				this.nonce = (nonce == null) ? null : Hex.Decode(nonce);
+				this.message = Hex.Decode(message);
+				this.expectedMac = Hex.Decode(expectedMac);
+			}
+		}
+
+		private static TestCase[] CASES = {
+			// Raw Poly1305
+			// onetimeauth.c from nacl-20110221
+			new TestCase("2539121d8e234e652d651fa4c8cff880eea6a7251c1e72916d11c2cb214d3c25", null,
+			             "8e993b9f48681273c29650ba32fc76ce48332ea7164d96a4476fb8c531a1186a"
+			             + "c0dfc17c98dce87b4da7f011ec48c97271d2c20f9b928fe2270d6fb863d51738"
+			             + "b48eeee314a7cc8ab932164548e526ae90224368517acfeabd6bb3732bc0e9da"
+			             + "99832b61ca01b6de56244a9e88d5f9b37973f622a43d14a6599b1f654cb45a74e355a5",
+			             "f3ffc7703f9400e52a7dfb4b3d3305d9"),
+
+			// Poly1305-AES
+			// Loop 1 of test-poly1305aes from poly1305aes-20050218
+			new TestCase("0000000000000000000000000000000000000000000000000000000000000000",
+			             "00000000000000000000000000000000", "", "66e94bd4ef8a2c3b884cfa59ca342b2e"),
+			new TestCase("f795bd4a52e29ed713d313fa20e98dbcf795bd0a50e29e0710d3130a20e98d0c",
+			             "917cf69ebd68b2ec9b9fe9a3eadda692", "66f7", "5ca585c75e8f8f025e710cabc9a1508b"),
+			new TestCase("e69dae0aab9f91c03a325dcc9436fa903ef49901c8e11c000430d90ad45e7603",
+			             "166450152e2394835606a9d1dd2cdc8b", "66f75c0e0c7a406586", "2924f51b9c2eff5df09db61dd03a9ca1"),
+			new TestCase("85a4ea91a7de0b0d96eed0d4bf6ecf1cda4afc035087d90e503f8f0ea08c3e0d",
+			             "0b6ef7a0b8f8c738b0f8d5995415271f",
+			             "66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea",
+			             "3c5a13adb18d31c64cc29972030c917d"),
+			new TestCase(
+				"25eb69bac5cdf7d6bfcee4d9d5507b82ca3c6a0da0a864024ca3090628c28e0d",
+				"046772a4f0a8de92e4f0d628cdb04484",
+				"66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de",
+				"fc5fb58dc65daf19b14d1d05da1064e8"),
+
+			// Specific test cases generated from test-poly1305aes from poly1305aes-20050218 that
+			// expose Java unsigned integer problems
+			new TestCase(
+				"95cc0e44d0b79a8856afcae1bec4fe3c" + "01bcb20bfc8b6e03609ddd09f44b060f",
+				null,
+				"66f75c0e0c7a40658629e3392f7f8e3349a02191ffd49f39879a8d9d1d0e23ea3caa4d240bd2ab8a8c4a6bb8d3288d9de4b793f05e97646dd4d98055de"
+				+ "fc3e0677d956b4c62664bac15962ab15d93ccbbc03aafdbde779162ed93b55361f0f8acaa41d50ef5175927fe79ea316186516eef15001cd04d3524a55"
+				+ "e4fa3c5ca479d3aaa8a897c21807f721b6270ffc68b6889d81a116799f6aaa35d8e04c7a7dd5e6da2519e8759f54e906696f5772fee093283bcef7b930"
+				+ "aed50323bcbc8c820c67422c1e16bdc022a9c0277c9d95fef0ea4ee11e2b27276da811523c5acb80154989f8a67ee9e3fa30b73b0c1c34bf46e3464d97"
+				+ "7cd7fcd0ac3b82721080bb0d9b982ee2c77feee983d7ba35da88ce86955002940652ab63bc56fb16f994da2b01d74356509d7d1b6d7956b0e5a557757b"
+				+ "d1ced2eef8650bc5b6d426108c1518abcbd0befb6a0d5fd57a3e2dbf31458eab63df66613653d4beae73f5c40eb438fbcfdcf4a4ba46320184b9ca0da4"
+				+ "dfae77de7ccc910356caea3243f33a3c81b064b3b7cedc7435c223f664227215715980e6e0bb570d459ba80d7512dbe458c8f0f3f52d659b6e8eef19ee"
+				+ "71aea2ced85c7a42ffca6522a62db49a2a46eff72bd7f7e0883acd087183f0627f3537a4d558754ed63358e8182bee196735b361dc9bd64d5e34e1074a"
+				+ "855655d2974cc6fa1653754cf40f561d8c7dc526aab2908ec2d2b977cde1a1fb1071e32f40e049ea20f30368ba1592b4fe57fb51595d23acbdace324cd"
+				+ "d78060a17187c662368854e915402d9b52fb21e984663e41c26a109437e162cfaf071b53f77e50000a5388ff183b82ce7a1af476c416d7d204157b3633"
+				+ "b2f4ec077b699b032816997e37bceded8d4a04976fd7d0c0b029f290794c3be504c5242287ea2f831f11ed5690d92775cd6e863d7731fd4da687ebfb13"
+				+ "df4c41dc0fb8", "ae345d555eb04d6947bb95c0965237e2"),
+			new TestCase(
+				"76fb3635a2dc92a1f768163ab12f2187" + "cd07fd0ef8c0be0afcbdb30af4af0009",
+				null,
+				"f05204a74f0f88a7fa1a95b84ec3d8ffb36fcdc7723ea65dfe7cd464e86e0abf6b9d51db3220cfd8496ad6e6d36ebee8d990f9ce0d3bb7f72b7ab5b3ab0a73240d11efe772c857021ae859db4933cdde4387b471d2ce700fef4b81087f8f47c307881fd83017afcd15b8d21edf9b704677f46df97b07e5b83f87c8abd90af9b1d0f9e2710e8ebd0d4d1c6a055abea861f42368bed94d9373e909c1d3715b221c16bc524c55c31ec3eab204850bb2474a84f9917038eff9d921130951391b5c54f09b5e1de833ea2cd7d3b306740abb7096d1e173da83427da2adddd3631eda30b54dbf487f2b082e8646f07d6e0a87e97522ca3 [...]
+				"045be28cc52009f506bdbfabedacf0b4"),
+
+		};
+
+		public override string Name
+		{
+			get { return "Poly1305"; }
+		}
+
+		public override void PerformTest()
+		{
+			testKeyGenerator();
+			testInit();
+			for (int i = 0; i < CASES.Length; i++)
+			{
+				testCase(i);
+			}
+			testSequential();
+			testReset();
+		}
+
+		private void testCase(int i)
+		{
+			byte[] output = new byte[16];
+			TestCase tc = CASES[i];
+
+			IMac mac;
+			if (tc.nonce == null)
+			{
+				// Raw Poly1305 test - don't do any transform on AES key part
+				mac = new Poly1305(new KeyEngine(16));
+				mac.Init(new ParametersWithIV(new KeyParameter(tc.key), new byte[16]));
+			}
+			else
+			{
+				mac = new Poly1305(new AesFastEngine());
+				mac.Init(new ParametersWithIV(new KeyParameter(tc.key), tc.nonce));
+			}
+			mac.BlockUpdate(tc.message, 0, tc.message.Length);
+			mac.DoFinal(output, 0);
+
+			if (!Arrays.AreEqual(output, tc.expectedMac))
+			{
+				Fail("Mismatched output " + i, Hex.ToHexString(tc.expectedMac), Hex.ToHexString(output));
+			}
+		}
+
+		private void testSequential()
+		{
+			// Sequential test, adapted from test-poly1305aes
+			int len;
+			byte[] kr = new byte[32];
+			byte[] m = new byte[MAXLEN];
+			byte[] n = new byte[16];
+			byte[] output = new byte[16];
+
+			int c = 0;
+			IMac mac = new Poly1305(new AesFastEngine());
+			for (int loop = 0; loop < 13; loop++)
+			{
+				len = 0;
+				for (;;)
+				{
+					c++;
+					mac.Init(new ParametersWithIV(new KeyParameter(kr), n));
+					mac.BlockUpdate(m, 0, len);
+					mac.DoFinal(output, 0);
+
+					// if (c == 678)
+					// {
+					// TestCase tc = CASES[0];
+					//
+					// if (!Arrays.AreEqual(tc.key, kr))
+					// {
+					// System.err.println("Key bad");
+					// System.err.println(Hex.ToHexString(tc.key)));
+					// System.err.println(Hex.ToHexString(kr)));
+					// System.exit(1);
+					// }
+					// if (!Arrays.AreEqual(tc.nonce, n))
+					// {
+					// System.err.println("Nonce bad");
+					// System.exit(1);
+					// }
+					// System.out.printf("[%d] m: %s\n", c, Hex.ToHexString(m, 0, len)));
+					// System.out.printf("[%d] K: %s\n", c, new string(Hex.encodje(kr)));
+					// System.out.printf("[%d] N: %s\n", c, Hex.ToHexString(n)));
+					// System.out.printf("[%d] M: ", c);
+					// }
+					// System.out.printf("%d/%s\n", c, Hex.ToHexString(out)));
+
+					if (len >= MAXLEN)
+						break;
+					n[0] = (byte)(n[0] ^ loop);
+					for (int i = 0; i < 16; ++i)
+						n[i] ^= output[i];
+					if (len % 2 != 0)
+						for (int i = 0; i < 16; ++i)
+							kr[i] ^= output[i];
+					if (len % 3 != 0)
+						for (int i = 0; i < 16; ++i)
+							kr[i + 16] ^= output[i];
+					Poly1305KeyGenerator.Clamp(kr);
+					m[len++] ^= output[0];
+				}
+			}
+			// Output after 13 loops as generated by poly1305 ref
+			if (c != 13013 || !Arrays.AreEqual(output, Hex.Decode("c96f60a23701a5b0fd2016f58cbe4f7e")))
+			{
+				Fail("Sequential Poly1305 " + c, "c96f60a23701a5b0fd2016f58cbe4f7e", Hex.ToHexString(output));
+			}
+		}
+
+		private void testReset()
+		{
+			CipherKeyGenerator gen = new Poly1305KeyGenerator();
+			gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
+			byte[] k = gen.GenerateKey();
+
+			byte[] m = new byte[10000];
+			byte[] check = new byte[16];
+			byte[] output = new byte[16];
+
+			// Generate baseline
+			IMac poly = new Poly1305(new AesFastEngine());
+			poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+
+			poly.BlockUpdate(m, 0, m.Length);
+			poly.DoFinal(check, 0);
+
+			// Check reset after doFinal
+			poly.BlockUpdate(m, 0, m.Length);
+			poly.DoFinal(output, 0);
+
+			if (!Arrays.AreEqual(check, output))
+			{
+				Fail("Mac not reset after doFinal");
+			}
+
+			// Check reset
+			poly.Update((byte)1);
+			poly.Update((byte)2);
+			poly.Reset();
+			poly.BlockUpdate(m, 0, m.Length);
+			poly.DoFinal(output, 0);
+
+			if (!Arrays.AreEqual(check, output))
+			{
+				Fail("Mac not reset after doFinal");
+			}
+
+			// Check init resets
+			poly.Update((byte)1);
+			poly.Update((byte)2);
+			poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+			poly.BlockUpdate(m, 0, m.Length);
+			poly.DoFinal(output, 0);
+
+			if (!Arrays.AreEqual(check, output))
+			{
+				Fail("Mac not reset after doFinal");
+			}
+		}
+
+		private void testInit()
+		{
+			CipherKeyGenerator gen = new Poly1305KeyGenerator();
+			gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
+			byte[] k = gen.GenerateKey();
+
+			IMac poly = new Poly1305(new AesFastEngine());
+			poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+
+			try
+			{
+				poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[15]));
+				Fail("16 byte nonce required");
+			} catch (ArgumentException)
+			{
+				// Expected
+			}
+
+			try
+			{
+				byte[] k2 = new byte[k.Length - 1];
+				Array.Copy(k, 0, k2, 0, k2.Length);
+				poly.Init(new ParametersWithIV(new KeyParameter(k2), new byte[16]));
+				Fail("32 byte key required");
+			} catch (ArgumentException)
+			{
+				// Expected
+			}
+
+			try
+			{
+				k[19] = (byte)0xFF;
+				poly.Init(new ParametersWithIV(new KeyParameter(k), new byte[16]));
+				Fail("UnClamped key should not be accepted.");
+			} catch (ArgumentException)
+			{
+				// Expected
+			}
+
+		}
+
+		private void testKeyGenerator()
+		{
+			CipherKeyGenerator gen = new Poly1305KeyGenerator();
+			gen.Init(new KeyGenerationParameters(new SecureRandom(), 256));
+			byte[] k = gen.GenerateKey();
+
+			if (k.Length != 32)
+			{
+				Fail("Poly1305 key should be 256 bits.");
+			}
+
+			try
+			{
+				Poly1305KeyGenerator.CheckKey(k);
+			} catch (ArgumentException)
+			{
+				Fail("Poly1305 key should be Clamped on generation.");
+			}
+
+			byte[] k2 = new byte[k.Length];
+			Array.Copy(k, 0, k2, 0, k2.Length);
+			Poly1305KeyGenerator.Clamp(k);
+			if (!Arrays.AreEqual(k, k2))
+			{
+				Fail("Poly1305 key should be Clamped on generation.");
+			}
+
+			try
+			{
+				k2[19] = (byte)0xff;
+				Poly1305KeyGenerator.CheckKey(k2);
+				Fail("UnClamped key should fail check.");
+			} catch (ArgumentException)
+			{
+				// Expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Poly1305Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RC2Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RC2Test.cs
new file mode 100644
index 0000000..177c181
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RC2Test.cs
@@ -0,0 +1,58 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+    /// <summary> RC2 tester - vectors from  ftp://ftp.isi.edu/in-notes/rfc2268.txt
+    ///
+    /// RFC 2268 "A Description of the RC2(r) Encryption Algorithm"
+    /// </summary>
+
+    [TestFixture]
+    public class RC2Test:CipherTest
+    {
+        public override string Name
+        {
+			get { return "RC2"; }
+        }
+
+		internal static BlockCipherVectorTest[] tests = new BlockCipherVectorTest[]{
+            new BlockCipherVectorTest(0, new RC2Engine(), new RC2Parameters(Hex.Decode("0000000000000000"), 63), "0000000000000000", "ebb773f993278eff"),
+            new BlockCipherVectorTest(1, new RC2Engine(), new RC2Parameters(Hex.Decode("ffffffffffffffff"), 64), "ffffffffffffffff", "278b27e42e2f0d49"),
+            new BlockCipherVectorTest(2, new RC2Engine(), new RC2Parameters(Hex.Decode("3000000000000000"), 64), "1000000000000001", "30649edf9be7d2c2"),
+            new BlockCipherVectorTest(3, new RC2Engine(), new RC2Parameters(Hex.Decode("88"), 64), "0000000000000000", "61a8a244adacccf0"),
+            new BlockCipherVectorTest(4, new RC2Engine(), new RC2Parameters(Hex.Decode("88bca90e90875a"), 64), "0000000000000000", "6ccf4308974c267f"),
+            new BlockCipherVectorTest(5, new RC2Engine(), new RC2Parameters(Hex.Decode("88bca90e90875a7f0f79c384627bafb2"), 64), "0000000000000000", "1a807d272bbe5db1"),
+            new BlockCipherVectorTest(6, new RC2Engine(), new RC2Parameters(Hex.Decode("88bca90e90875a7f0f79c384627bafb2"), 128), "0000000000000000", "2269552ab0f85ca6"),
+            new BlockCipherVectorTest(7, new RC2Engine(), new RC2Parameters(Hex.Decode("88bca90e90875a7f0f79c384627bafb216f80a6f85920584c42fceb0be255daf1e"), 129), "0000000000000000", "5b78d3a43dfff1f1")};
+
+		public RC2Test()
+			:base(tests, new RC2Engine(), new RC2Parameters(new byte[16]))
+        {
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new RC2Test();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RC2WrapTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RC2WrapTest.cs
new file mode 100644
index 0000000..fc27acd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RC2WrapTest.cs
@@ -0,0 +1,123 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* RC2 wrap tester
+	*/
+	[TestFixture]
+	public class RC2WrapTest
+		: ITest
+	{
+		private class RFCRandom
+			: SecureRandom
+		{
+			public override void NextBytes(
+				byte[] nextBytes)
+			{
+				Array.Copy(Hex.Decode("4845cce7fd1250"), 0, nextBytes, 0, nextBytes.Length);
+			}
+		}
+
+		private ITestResult wrapTest(
+			int     id,
+			ICipherParameters paramsWrap,
+			ICipherParameters paramsUnwrap,
+			byte[]  inBytes,
+			byte[]  outBytes)
+		{
+			IWrapper wrapper = new RC2WrapEngine();
+
+			wrapper.Init(true, paramsWrap);
+
+			try
+			{
+				byte[]  cText = wrapper.Wrap(inBytes, 0, inBytes.Length);
+				if (!Arrays.AreEqual(cText, outBytes))
+				{
+					return new SimpleTestResult(false, Name + ": failed wrap test " + id
+						+ " expected " + Hex.ToHexString(outBytes)
+						+ " got " + Hex.ToHexString(cText));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed wrap test exception " + e, e);
+			}
+
+			wrapper.Init(false, paramsUnwrap);
+
+			try
+			{
+				byte[]  pText = wrapper.Unwrap(outBytes, 0, outBytes.Length);
+				if (!Arrays.AreEqual(pText, inBytes))
+				{
+					return new SimpleTestResult(false, Name + ": failed unwrap test " + id
+						+ " expected " + Hex.ToHexString(inBytes)
+						+ " got " + Hex.ToHexString(pText));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": failed unwrap test exception " + e, e);
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public ITestResult Perform()
+		{
+			byte[]  kek1 = Hex.Decode("fd04fd08060707fb0003fefffd02fe05");
+			byte[]  iv1 = Hex.Decode("c7d90059b29e97f7");
+			byte[]  in1 = Hex.Decode("b70a25fbc9d86a86050ce0d711ead4d9");
+			byte[]  out1 = Hex.Decode("70e699fb5701f7833330fb71e87c85a420bdc99af05d22af5a0e48d35f3138986cbaafb4b28d4f35");
+			//
+			// note the RFC 3217 test specifies a key to be used with an effective key size of
+			// 40 bits which is why it is done here - in practice nothing less than 128 bits should be used.
+			//
+			ICipherParameters paramWrap = new ParametersWithRandom(new ParametersWithIV(new RC2Parameters(kek1, 40), iv1), new RFCRandom());
+			ICipherParameters paramUnwrap = new RC2Parameters(kek1, 40);
+
+			ITestResult result = wrapTest(1, paramWrap, paramUnwrap, in1, out1);
+
+			if (!result.IsSuccessful())
+			{
+				return result;
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public string Name
+		{
+			get { return "RC2Wrap"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new RC2WrapTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RC4Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RC4Test.cs
new file mode 100644
index 0000000..7c1ac91
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RC4Test.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> RC4 Test</summary>
+    [TestFixture]
+    public class RC4Test
+		: ITest
+    {
+        public string Name
+        {
+			get { return "RC4"; }
+        }
+
+		internal StreamCipherVectorTest[] tests = new StreamCipherVectorTest[]{
+            new StreamCipherVectorTest(0, new RC4Engine(), new KeyParameter(Hex.Decode("0123456789ABCDEF")), "4e6f772069732074", "3afbb5c77938280d"),
+            new StreamCipherVectorTest(0, new RC4Engine(), new KeyParameter(Hex.Decode("0123456789ABCDEF")), "68652074696d6520", "1cf1e29379266d59"),
+            new StreamCipherVectorTest(0, new RC4Engine(), new KeyParameter(Hex.Decode("0123456789ABCDEF")), "666f7220616c6c20", "12fbb0c771276459")};
+
+        public virtual ITestResult Perform()
+        {
+            for (int i = 0; i != tests.Length; i++)
+            {
+                ITestResult res = tests[i].Perform();
+
+                if (!res.IsSuccessful())
+                {
+                    return res;
+                }
+            }
+
+			return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new RC4Test();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RC5Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RC5Test.cs
new file mode 100644
index 0000000..e50878a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RC5Test.cs
@@ -0,0 +1,201 @@
+using System;
+
+using NUnit.Framework;
+
+using System.Text;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+    /**
+    * RC5 tester - vectors from ftp://ftp.nordu.net/rfc/rfc2040.txt
+    *
+    * RFC 2040 "The RC5, RC5-CBC, RC5-CBC-Pad, and RC5-CTS Algorithms"
+    */
+    [TestFixture]
+    public class RC5Test: ITest
+    {
+        BlockCipherVectorTest[] tests =
+        {
+            new BlockCipherVectorTest(0, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000000", "7a7bba4d79111d1e"),
+            new BlockCipherVectorTest(1, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "797bba4d78111d1e"),
+            new BlockCipherVectorTest(2, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("0000000000000001")),
+                    "0000000000000000", "7a7bba4d79111d1f"),
+            new BlockCipherVectorTest(3, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000001", "7a7bba4d79111d1f"),
+            new BlockCipherVectorTest(4, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "8b9ded91ce7794a6"),
+            new BlockCipherVectorTest(5, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("11"), 1),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000000", "2f759fe7ad86a378"),
+            new BlockCipherVectorTest(6, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 2),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000000", "dca2694bf40e0788"),
+            new BlockCipherVectorTest(7, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00000000"), 2),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000000", "dca2694bf40e0788"),
+            new BlockCipherVectorTest(8, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00000000"), 8),
+                        Hex.Decode("0000000000000000")),
+                    "0000000000000000", "dcfe098577eca5ff"),
+            new BlockCipherVectorTest(9, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 8),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "9646fb77638f9ca8"),
+            new BlockCipherVectorTest(10, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 12),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "b2b3209db6594da4"),
+            new BlockCipherVectorTest(11, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 16),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "545f7f32a5fc3836"),
+            new BlockCipherVectorTest(12, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304"), 8),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "8285e7c1b5bc7402"),
+            new BlockCipherVectorTest(13, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304"), 12),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "fc586f92f7080934"),
+            new BlockCipherVectorTest(14, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304"), 16),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "cf270ef9717ff7c4"),
+            new BlockCipherVectorTest(15, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405060708"), 12),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "e493f1c1bb4d6e8c"),
+            new BlockCipherVectorTest(16, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405060708"), 8),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "5c4c041e0f217ac3"),
+            new BlockCipherVectorTest(17, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405060708"), 12),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "921f12485373b4f7"),
+            new BlockCipherVectorTest(18, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405060708"), 16),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "5ba0ca6bbe7f5fad"),
+            new BlockCipherVectorTest(19, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304050607081020304050607080"), 8),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "c533771cd0110e63"),
+            new BlockCipherVectorTest(20, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304050607081020304050607080"), 12),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "294ddb46b3278d60"),
+            new BlockCipherVectorTest(21, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("01020304050607081020304050607080"), 16),
+                        Hex.Decode("0102030405060708")),
+                    "1020304050607080", "dad6bda9dfe8f7e8"),
+            new BlockCipherVectorTest(22, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405"), 12),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "97e0787837ed317f"),
+            new BlockCipherVectorTest(23, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405"), 8),
+                        Hex.Decode("0000000000000000")),
+                    "ffffffffffffffff", "7875dbf6738c6478"),
+            new BlockCipherVectorTest(23, new CbcBlockCipher(new RC532Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("0102030405"), 8),
+                        Hex.Decode("7875dbf6738c6478")),
+                    "0808080808080808", "8f34c3c681c99695"),
+            new BlockCipherVectorTest(640, new CbcBlockCipher(new RC564Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("00000000000000000000000000000000")),
+                    "00000000000000000000000000000000", "9f09b98d3f6062d9d4d59973d00e0e63"),
+            new BlockCipherVectorTest(641, new CbcBlockCipher(new RC564Engine()),
+                    new ParametersWithIV(
+                        new RC5Parameters(Hex.Decode("00"), 0),
+                        Hex.Decode("00000000000000000000000000000000")),
+                    "ffffffffffffffffffffffffffffffff", "9e09b98d3f6062d9d3d59973d00e0e63")
+        };
+
+		public string Name
+        {
+			get { return "RC5"; }
+        }
+
+		public ITestResult Perform()
+        {
+            for (int i = 0; i != tests.Length; i++)
+            {
+                ITestResult  res = tests[i].Perform();
+
+                if (!res.IsSuccessful())
+                {
+                    return res;
+                }
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RC5Test test = new RC5Test();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RC6Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RC6Test.cs
new file mode 100644
index 0000000..4f59ec4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RC6Test.cs
@@ -0,0 +1,54 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <remarks> RC6 Test - test vectors from AES Submitted RSA Reference implementation.
+    /// ftp://ftp.funet.fi/pub/crypt/cryptography/symmetric/aes/rc6-unix-refc.tar
+    /// </remarks>
+	[TestFixture]
+    public class RC6Test
+		: CipherTest
+    {
+        public override string Name
+        {
+			get { return "RC6"; }
+        }
+
+		internal static SimpleTest[] tests = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new RC6Engine(), new KeyParameter(Hex.Decode("00000000000000000000000000000000")), "80000000000000000000000000000000", "f71f65e7b80c0c6966fee607984b5cdf"),
+            new BlockCipherVectorTest(1, new RC6Engine(), new KeyParameter(Hex.Decode("000000000000000000000000000000008000000000000000")), "00000000000000000000000000000000", "dd04c176440bbc6686c90aee775bd368"),
+            new BlockCipherVectorTest(2, new RC6Engine(), new KeyParameter(Hex.Decode("000000000000000000000000000000000000001000000000")), "00000000000000000000000000000000", "937fe02d20fcb72f0f57201012b88ba4"),
+            new BlockCipherVectorTest(3, new RC6Engine(), new KeyParameter(Hex.Decode("00000001000000000000000000000000")), "00000000000000000000000000000000", "8a380594d7396453771a1dfbe2914c8e"),
+            new BlockCipherVectorTest(4, new RC6Engine(), new KeyParameter(Hex.Decode("1000000000000000000000000000000000000000000000000000000000000000")), "00000000000000000000000000000000", "11395d4bfe4c8258979ee2bf2d24dff4"),
+            new BlockCipherVectorTest(5, new RC6Engine(), new KeyParameter(Hex.Decode("0000000000000000000000000000000000080000000000000000000000000000")), "00000000000000000000000000000000", "3d6f7e99f6512553bb983e8f75672b97")};
+
+        public RC6Test()
+			: base(tests, new RC6Engine(), new KeyParameter(new byte[32]))
+        {
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new RC6Test();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RFC3211WrapTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RFC3211WrapTest.cs
new file mode 100644
index 0000000..bdef7c9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RFC3211WrapTest.cs
@@ -0,0 +1,216 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Wrap Test based on RFC3211 test vectors
+	*/
+	[TestFixture]
+	public class Rfc3211WrapTest
+		: SimpleTest
+	{
+		// Note: These test data assume the Rfc3211WrapEngine will call SecureRandom.NextBytes
+
+		SecureRandom r1 = FixedSecureRandom.From(
+			new byte[]{ 0xC4, 0x36, 0xF5, 0x41 });
+
+		SecureRandom r2 = FixedSecureRandom.From(
+			new byte[]{ 0xFA, 0x06, 0x0A, 0x45 });
+
+		public override string Name
+		{
+			get { return "RFC3211Wrap"; }
+		}
+
+		private void doWrapTest(
+			int				id,
+			IBlockCipher	engine,
+			byte[]			kek,
+			byte[]			iv,
+			SecureRandom	rand,
+			byte[]			inBytes,
+			byte[]			outBytes)
+		{
+			IWrapper wrapper = new Rfc3211WrapEngine(engine);
+
+			wrapper.Init(true, new ParametersWithRandom(
+				new ParametersWithIV(new KeyParameter(kek), iv), rand));
+
+			byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length);
+			if (!AreEqual(cText, outBytes))
+			{
+				Fail("failed Wrap test " + id  + " expected "
+					+ Hex.ToHexString(outBytes) + " got " + Hex.ToHexString(cText));
+			}
+
+			wrapper.Init(false, new ParametersWithIV(new KeyParameter(kek), iv));
+
+			byte[] pText = wrapper.Unwrap(outBytes, 0, outBytes.Length);
+			if (!AreEqual(pText, inBytes))
+			{
+				Fail("rfailed Unwrap test " + id  + " expected "
+					+ Hex.ToHexString(inBytes) + " got " + Hex.ToHexString(pText));
+			}
+		}
+
+		private void doTestCorruption()
+		{
+			byte[] kek = Hex.Decode("D1DAA78615F287E6");
+			byte[] iv = Hex.Decode("EFE598EF21B33D6D");
+
+			IWrapper wrapper = new Rfc3211WrapEngine(new DesEngine());
+
+			wrapper.Init(false, new ParametersWithIV(new KeyParameter(kek), iv));
+
+			byte[] block = Hex.Decode("ff739D838C627C897323A2F8C436F541");
+			encryptBlock(kek, iv, block);
+
+			try
+			{
+				wrapper.Unwrap(block, 0, block.Length);
+
+				Fail("bad length not detected");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals("wrapped key corrupted"))
+				{
+					Fail("wrong exception on length");
+				}
+			}
+
+			block = Hex.Decode("08639D838C627C897323A2F8C436F541");
+			doTestChecksum(kek, iv, block, wrapper);
+
+			block = Hex.Decode("08736D838C627C897323A2F8C436F541");
+			doTestChecksum(kek, iv, block, wrapper);
+	        
+			block = Hex.Decode("08739D638C627C897323A2F8C436F541");
+			doTestChecksum(kek, iv, block, wrapper);
+		}
+
+		private void doTestChecksum(
+			byte[]		kek,
+			byte[]		iv,
+			byte[]		block,
+			IWrapper	wrapper)
+		{
+			encryptBlock(kek, iv, block);
+
+			try
+			{
+				wrapper.Unwrap(block, 0, block.Length);
+
+				Fail("bad checksum not detected");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals("wrapped key fails checksum"))
+				{
+					Fail("wrong exception");
+				}
+			}
+		}
+
+		private void encryptBlock(byte[] key, byte[] iv, byte[] cekBlock)
+		{
+			IBlockCipher engine = new CbcBlockCipher(new DesEngine());
+
+			engine.Init(true, new ParametersWithIV(new KeyParameter(key), iv));
+
+			for (int i = 0; i < cekBlock.Length; i += 8)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);
+			}
+
+			for (int i = 0; i < cekBlock.Length; i += 8)
+			{
+				engine.ProcessBlock(cekBlock, i, cekBlock, i);
+			}
+		}
+
+		public override void PerformTest()
+		{
+			doWrapTest(1, new DesEngine(), Hex.Decode("D1DAA78615F287E6"), Hex.Decode("EFE598EF21B33D6D"), r1, Hex.Decode("8C627C897323A2F8"), Hex.Decode("B81B2565EE373CA6DEDCA26A178B0C10"));
+			doWrapTest(2, new DesEdeEngine(), Hex.Decode("6A8970BF68C92CAEA84A8DF28510858607126380CC47AB2D"), Hex.Decode("BAF1CA7931213C4E"), r2,
+				Hex.Decode("8C637D887223A2F965B566EB014B0FA5D52300A3F7EA40FFFC577203C71BAF3B"),
+				Hex.Decode("C03C514ABDB9E2C5AAC038572B5E24553876B377AAFB82ECA5A9D73F8AB143D9EC74E6CAD7DB260C"));
+
+			doTestCorruption();
+	        
+			IWrapper wrapper = new Rfc3211WrapEngine(new DesEngine());
+			ParametersWithIV parameters = new ParametersWithIV(new KeyParameter(new byte[16]), new byte[16]);
+			byte[] buf = new byte[16];
+
+			try
+			{
+				wrapper.Init(true, parameters);
+
+				wrapper.Unwrap(buf, 0, buf.Length);
+
+				Fail("failed Unwrap state test.");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+			catch (InvalidCipherTextException e)
+			{
+				Fail("unexpected exception: " + e, e);
+			}
+
+			try
+			{
+				wrapper.Init(false, parameters);
+
+				wrapper.Wrap(buf, 0, buf.Length);
+
+				Fail("failed Unwrap state test.");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+
+			//
+			// short test
+			//
+			try
+			{
+				wrapper.Init(false, parameters);
+
+				wrapper.Unwrap(buf, 0, buf.Length / 2);
+
+				Fail("failed Unwrap short test.");
+			}
+			catch (InvalidCipherTextException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Rfc3211WrapTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RSABlindedTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RSABlindedTest.cs
new file mode 100644
index 0000000..80d6e8e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RSABlindedTest.cs
@@ -0,0 +1,449 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class RsaBlindedTest
+		: SimpleTest
+	{
+		static BigInteger mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+		static BigInteger  pubExp = new BigInteger("11", 16);
+		static BigInteger  privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+		static BigInteger  p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
+		static BigInteger  q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
+		static BigInteger  pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
+		static BigInteger  qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
+		static BigInteger  crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
+
+		static string input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		//
+		// to check that we handling byte extension by big number correctly.
+		//
+		static string edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		static byte[] oversizedSig = Hex.Decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] dudBlock = Hex.Decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] truncatedDataBlock = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] incorrectPadding = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] missingDataBlock = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+
+		public override string Name
+		{
+			get { return "RSABlinded"; }
+		}
+
+		private void doTestStrictPkcs1Length(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			IAsymmetricBlockCipher eng = new RsaBlindedEngine();
+
+			eng.Init(true, privParameters);
+
+			byte[] data = null;
+
+			try
+			{
+				data = eng.ProcessBlock(oversizedSig, 0, oversizedSig.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+
+				Fail("oversized signature block not recognised");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals("block incorrect size"))
+				{
+					Fail("RSA: failed - exception " + e.ToString(), e);
+				}
+			}
+
+
+			// Create the encoding with StrictLengthEnabled=false (done thru environment in Java version)
+			Pkcs1Encoding.StrictLengthEnabled = false;
+
+			eng = new Pkcs1Encoding(new RsaBlindedEngine());
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (InvalidCipherTextException e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			Pkcs1Encoding.StrictLengthEnabled = true;
+		}
+
+		private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+		}
+
+		private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+		}
+
+		private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+		}
+
+		private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+		}
+
+		private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage)
+		{
+			IAsymmetricBlockCipher eng = new RsaBlindedEngine();
+
+			eng.Init(true, privParameters);
+
+			byte[] data = null;
+
+			try
+			{
+				data = eng.ProcessBlock(inputData, 0, inputData.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+
+				Fail("missing data block not recognised");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals(expectedMessage))
+				{
+					Fail("RSA: failed - exception " + e.ToString(), e);
+				}
+			}
+		}
+
+		private void doTestOaep(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			//
+			// OAEP - public encrypt, private decrypt
+			//
+			IAsymmetricBlockCipher eng = new OaepEncoding(new RsaBlindedEngine());
+			byte[] data = Hex.Decode(input);
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed OAEP Test");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod, pubExp);
+			RsaKeyParameters privParameters = new RsaPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+			byte[] data = Hex.Decode(edgeInput);
+
+			//
+			// RAW
+			//
+			IAsymmetricBlockCipher eng = new RsaBlindedEngine();
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!edgeInput.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed RAW edge Test");
+			}
+
+			data = Hex.Decode(input);
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed RAW Test");
+			}
+
+			//
+			// PKCS1 - public encrypt, private decrypt
+			//
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(true, pubParameters);
+
+			if (eng.GetOutputBlockSize() != ((Pkcs1Encoding)eng).GetUnderlyingCipher().GetOutputBlockSize())
+			{
+				Fail("PKCS1 output block size incorrect");
+			}
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed PKCS1 public/private Test");
+			}
+
+			//
+			// PKCS1 - private encrypt, public decrypt
+			//
+			eng = new Pkcs1Encoding(((Pkcs1Encoding)eng).GetUnderlyingCipher());
+
+			eng.Init(true, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed PKCS1 private/public Test");
+			}
+
+			//
+			// key generation test
+			//
+			RsaKeyPairGenerator pGen = new RsaKeyPairGenerator();
+			RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x11), new SecureRandom(), 768, 25);
+
+			pGen.Init(genParam);
+
+			AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+			eng = new RsaBlindedEngine();
+
+			if (((RsaKeyParameters)pair.Public).Modulus.BitLength < 768)
+			{
+				Fail("failed key generation (768) length test");
+			}
+
+			eng.Init(true, pair.Public);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, pair.Private);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed key generation (768) Test");
+			}
+
+			genParam = new RsaKeyGenerationParameters(BigInteger.ValueOf(0x11), new SecureRandom(), 1024, 25);
+
+			pGen.Init(genParam);
+			pair = pGen.GenerateKeyPair();
+
+			eng.Init(true, pair.Public);
+
+			if (((RsaKeyParameters)pair.Public).Modulus.BitLength < 1024)
+			{
+				Fail("failed key generation (1024) length test");
+			}
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, pair.Private);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed key generation (1024) test");
+			}
+
+			doTestOaep(pubParameters, privParameters);
+			doTestStrictPkcs1Length(pubParameters, privParameters);
+			doTestDudPkcs1Block(pubParameters, privParameters);
+			doTestMissingDataPkcs1Block(pubParameters, privParameters);
+			doTestTruncatedPkcs1Block(pubParameters, privParameters);
+			doTestWrongPaddingPkcs1Block(pubParameters, privParameters);
+
+			try
+			{
+				new RsaBlindedEngine().ProcessBlock(new byte[]{ 1 }, 0, 1);
+				Fail("failed initialisation check");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new RsaBlindedTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RegressionTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RegressionTest.cs
new file mode 100644
index 0000000..27d6bb0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RegressionTest.cs
@@ -0,0 +1,135 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    public class RegressionTest
+    {
+        public static ITest[] tests = new ITest[]
+        {
+            new AesTest(),
+            new AesLightTest(),
+            new AesFastTest(),
+            new AesWrapTest(),
+            new DesTest(),
+            new DesEdeTest(),
+            new ModeTest(),
+            new PaddingTest(),
+            new DHTest(),
+            new ElGamalTest(),
+            new DsaTest(),
+            new ECTest(),
+            new DeterministicDsaTest(),
+            new Gost3410Test(),
+            new ECGost3410Test(),
+            new EcIesTest(),
+            new EcNrTest(),
+            new MacTest(),
+            new Gost28147MacTest(),
+            new RC2Test(),
+            new RC2WrapTest(),
+            new RC4Test(),
+            new RC5Test(),
+            new RC6Test(),
+            new RijndaelTest(),
+            new SerpentTest(),
+            new CamelliaTest(),
+            new CamelliaLightTest(),
+            new DigestRandomNumberTest(),
+            new SkipjackTest(),
+            new BlowfishTest(),
+            new TwofishTest(),
+            new Threefish256Test(),
+            new Threefish512Test(),
+            new Threefish1024Test(),
+            new SkeinDigestTest(),
+            new SkeinMacTest(),
+            new Cast5Test(),
+            new Cast6Test(),
+            new Gost28147Test(),
+            new IdeaTest(),
+            new RsaBlindedTest(),
+            new RsaTest(),
+            new ISO9796Test(),
+            new ISO9797Alg3MacTest(),
+            new MD2DigestTest(),
+            new MD4DigestTest(),
+            new MD5DigestTest(),
+            new PssBlindTest(),
+            new Sha1DigestTest(),
+            new Sha224DigestTest(),
+            new Sha256DigestTest(),
+            new Sha384DigestTest(),
+            new Sha512DigestTest(),
+            new Sha512t224DigestTest(),
+            new Sha512t256DigestTest(),
+            new Sha3DigestTest(),
+            new RipeMD128DigestTest(),
+            new RipeMD160DigestTest(),
+            new RipeMD256DigestTest(),
+            new RipeMD320DigestTest(),
+            new TigerDigestTest(),
+            new Gost3411DigestTest(),
+            new WhirlpoolDigestTest(),
+            new MD5HMacTest(),
+            new Sha1HMacTest(),
+            new Sha224HMacTest(),
+            new Sha256HMacTest(),
+            new Sha384HMacTest(),
+            new Sha512HMacTest(),
+            new RipeMD128HMacTest(),
+            new RipeMD160HMacTest(),
+            new OaepTest(),
+            new PssTest(),
+            new CTSTest(),
+            new CcmTest(),
+            new Pkcs5Test(),
+            new Pkcs12Test(),
+            new Kdf1GeneratorTest(),
+            new Kdf2GeneratorTest(),
+            new Mgf1GeneratorTest(),
+            new DHKekGeneratorTest(),
+            new ECDHKekGeneratorTest(),
+            new ShortenedDigestTest(),
+            new EqualsHashCodeTest(),
+            new TeaTest(),
+            new XteaTest(),
+            new Rfc3211WrapTest(),
+            new SeedTest(),
+            new NaccacheSternTest(),
+            new Salsa20Test(),
+            new XSalsa20Test(),
+            new ChaChaTest(),
+            new CMacTest(),
+            new EaxTest(),
+            new GcmTest(),
+            new GMacTest(),
+            new HCFamilyTest(),
+            new HCFamilyVecTest(),
+            new IsaacTest(),
+            new NoekeonTest(),
+            new VmpcKsa3Test(),
+            new VmpcMacTest(),
+            new VmpcTest(),
+            new Srp6Test(),
+            new SCryptTest(),
+            new NullTest(),
+            new SipHashTest(),
+            new Poly1305Test(),
+            new OcbTest(),
+            new SM3DigestTest()
+        };
+
+        public static void Main(
+            string[] args)
+        {
+            for (int i = 0; i != tests.Length; i++)
+            {
+                ITestResult result = tests[i].Perform();
+
+                Console.WriteLine(result);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RijndaelTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RijndaelTest.cs
new file mode 100644
index 0000000..f714c83
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RijndaelTest.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+    * Test vectors from the NIST standard tests and Brian Gladman's vector set
+    * <a href="http://fp.gladman.plus.com/cryptography_technology/rijndael/">
+    * http://fp.gladman.plus.com/cryptography_technology/rijndael/</a>
+    */
+    [TestFixture]
+    public class RijndaelTest
+		: CipherTest
+    {
+        static SimpleTest[] tests =
+        {
+            new BlockCipherVectorTest(0, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+                    "00000000000000000000000000000000", "0EDD33D3C621E546455BD8BA1418BEC8"),
+            new BlockCipherVectorTest(1, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("00000000000000000000000000000080")),
+                    "00000000000000000000000000000000", "172AEAB3D507678ECAF455C12587ADB7"),
+            new BlockCipherMonteCarloTest(2, 10000, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+                    "00000000000000000000000000000000", "C34C052CC0DA8D73451AFE5F03BE297F"),
+            new BlockCipherMonteCarloTest(3, 10000, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("5F060D3716B345C253F6749ABAC10917")),
+                    "355F697E8B868B65B25A04E18D782AFA", "ACC863637868E3E068D2FD6E3508454A"),
+            new BlockCipherVectorTest(4, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+                    "80000000000000000000000000000000", "6CD02513E8D4DC986B4AFE087A60BD0C"),
+            new BlockCipherMonteCarloTest(5, 10000, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("AAFE47EE82411A2BF3F6752AE8D7831138F041560631B114")),
+                    "F3F6752AE8D7831138F041560631B114", "77BA00ED5412DFF27C8ED91F3C376172"),
+            new BlockCipherVectorTest(6, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+                    "80000000000000000000000000000000", "DDC6BF790C15760D8D9AEB6F9A75FD4E"),
+            new BlockCipherMonteCarloTest(7, 10000, new RijndaelEngine(128),
+                    new KeyParameter(Hex.Decode("28E79E2AFC5F7745FCCABE2F6257C2EF4C4EDFB37324814ED4137C288711A386")),
+                    "C737317FE0846F132B23C8C2A672CE22", "E58B82BFBA53C0040DC610C642121168"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(160),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c")),
+                    "3243f6a8885a308d313198a2e03707344a409382", "16e73aec921314c29df905432bc8968ab64b1f51"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(160),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+                    "3243f6a8885a308d313198a2e03707344a409382", "0553eb691670dd8a5a5b5addf1aa7450f7a0e587"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(160),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+                    "3243f6a8885a308d313198a2e03707344a409382", "73cd6f3423036790463aa9e19cfcde894ea16623"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(160),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+                    "3243f6a8885a308d313198a2e03707344a409382", "601b5dcd1cf4ece954c740445340bf0afdc048df"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(160),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+                    "3243f6a8885a308d313198a2e03707344a409382", "579e930b36c1529aa3e86628bacfe146942882cf"),
+            new BlockCipherVectorTest(8, new RijndaelEngine(192),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d", "b24d275489e82bb8f7375e0d5fcdb1f481757c538b65148a"),
+            new BlockCipherVectorTest(9, new RijndaelEngine(192),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d", "725ae43b5f3161de806a7c93e0bca93c967ec1ae1b71e1cf"),
+            new BlockCipherVectorTest(10, new RijndaelEngine(192),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d", "bbfc14180afbf6a36382a061843f0b63e769acdc98769130"),
+            new BlockCipherVectorTest(11, new RijndaelEngine(192),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d", "0ebacf199e3315c2e34b24fcc7c46ef4388aa475d66c194c"),
+            new BlockCipherVectorTest(12, new RijndaelEngine(224),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "b0a8f78f6b3c66213f792ffd2a61631f79331407a5e5c8d3793aceb1"),
+            new BlockCipherVectorTest(13, new RijndaelEngine(224),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "08b99944edfce33a2acb131183ab0168446b2d15e958480010f545e3"),
+            new BlockCipherVectorTest(14, new RijndaelEngine(224),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "be4c597d8f7efe22a2f7e5b1938e2564d452a5bfe72399c7af1101e2"),
+            new BlockCipherVectorTest(15, new RijndaelEngine(224),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "ef529598ecbce297811b49bbed2c33bbe1241d6e1a833dbe119569e8"),
+            new BlockCipherVectorTest(16, new RijndaelEngine(224),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa9", "02fafc200176ed05deb8edb82a3555b0b10d47a388dfd59cab2f6c11"),
+            new BlockCipherVectorTest(17, new RijndaelEngine(256),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "7d15479076b69a46ffb3b3beae97ad8313f622f67fedb487de9f06b9ed9c8f19"),
+            new BlockCipherVectorTest(18, new RijndaelEngine(256),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "514f93fb296b5ad16aa7df8b577abcbd484decacccc7fb1f18dc567309ceeffd"),
+            new BlockCipherVectorTest(19, new RijndaelEngine(256),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da5")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "5d7101727bb25781bf6715b0e6955282b9610e23a43c2eb062699f0ebf5887b2"),
+            new BlockCipherVectorTest(20, new RijndaelEngine(256),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d90")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "d56c5a63627432579e1dd308b2c8f157b40a4bfb56fea1377b25d3ed3d6dbf80"),
+            new BlockCipherVectorTest(21, new RijndaelEngine(256),
+                    new KeyParameter(Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c762e7160f38b4da56a784d9045190cfe")),
+                    "3243f6a8885a308d313198a2e03707344a4093822299f31d0082efa98ec4e6c8", "a49406115dfb30a40418aafa4869b7c6a886ff31602a7dd19c889dc64f7e4e7a")
+        };
+
+		public RijndaelTest()
+			: base(tests, new RijndaelEngine(128), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+        {
+			get { return "Rijndael"; }
+        }
+
+        public static void Main(
+			string[] args)
+        {
+            ITest test = new RijndaelTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128DigestTest.cs
new file mode 100644
index 0000000..ead4f06
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * RIPEMD128 Digest Test
+	 */
+	[TestFixture]
+	public class RipeMD128DigestTest
+		: DigestTest
+	{
+		readonly static string[] messages = {
+			"",
+			"a",
+			"abc",
+			"message digest",
+			"abcdefghijklmnopqrstuvwxyz",
+			"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+			"12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+		};
+
+		readonly static string[] digests = {
+			"cdf26213a150dc3ecb610f18f6b38b46",
+			"86be7afa339d0fc7cfc785e72f578d33",
+			"c14a12199c66e4ba84636b0f69144c77",
+			"9e327b3d6e523062afc1132d7df9d1b8",
+			"fd2aa607f71dc8f510714922b371834e",
+			"a1aa0689d0fafa2ddc22e88b49133a06",
+			"d1e959eb179c911faea4624c60c5c702",
+			"3f45ef194732c2dbb2c4a2c769795fa3"
+		};
+
+		readonly static String million_a_digest = "4a7f5723f954eba1216c9d8f6320431f";
+
+		public RipeMD128DigestTest()
+			: base(new RipeMD128Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new RipeMD128Digest((RipeMD128Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RipeMD128DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128HMacTest.cs
new file mode 100644
index 0000000..2f6a2d9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD128HMacTest.cs
@@ -0,0 +1,100 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * RipeMD128 HMac Test, test vectors from RFC 2286
+     */
+    [TestFixture]
+    public class RipeMD128HMacTest: ITest
+    {
+        readonly static string[] keys =
+        {
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+        readonly static string[] digests = {
+            "fbf61f9492aa4bbf81c172e84e0734db",
+            "875f828862b6b334b427c55f9f7ff09b",
+            "09f0b2846d2f543da363cbec8d62a38d",
+            "bdbbd7cf03e44b5aa60af815be4d2294",
+            "e79808f24b25fd031c155f0d551d9a3a",
+            "dc732928de98104a1f59d373c150acbb",
+            "5c6bec96793e16d40690c237635f30c5"
+        };
+
+        readonly static string[] messages = {
+            "Hi There",
+            "what do ya want for nothing?",
+            "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "Test With Truncation",
+            "Test Using Larger Than Block-Size Key - Hash Key First",
+            "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+        };
+
+		public string Name
+        {
+			get { return "RipeMD128HMac"; }
+        }
+
+		public ITestResult Perform()
+        {
+            HMac hmac = new HMac(new RipeMD128Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new RipeMD128HMacTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160DigestTest.cs
new file mode 100644
index 0000000..15e53f2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * RIPEMD160 Digest Test
+	 */
+	[TestFixture]
+	public class RipeMD160DigestTest
+		: DigestTest
+	{
+		readonly static string[] messages = {
+			"",
+			"a",
+			"abc",
+			"message digest",
+			"abcdefghijklmnopqrstuvwxyz",
+			"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+			"12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+		};
+
+		readonly static string[] digests = {
+			"9c1185a5c5e9fc54612808977ee8f548b2258d31",
+			"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe",
+			"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc",
+			"5d0689ef49d2fae572b881b123a85ffa21595f36",
+			"f71c27109c692c1b56bbdceb5b9d2865b3708dbc",
+			"12a053384a9c0c88e405a06c27dcf49ada62eb2b",
+			"b0e20b6e3116640286ed3a87a5713079b21f5189",
+			"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+		};
+
+		readonly static string million_a_digest = "52783243c1697bdbe16d37f97f68f08325dc1528";
+
+		public RipeMD160DigestTest()
+			: base(new RipeMD160Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new RipeMD160Digest((RipeMD160Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RipeMD160DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160HMacTest.cs
new file mode 100644
index 0000000..cc87a53
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD160HMacTest.cs
@@ -0,0 +1,102 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * RipeMD160 HMac Test, test vectors from RFC 2286
+     */
+    [TestFixture]
+    public class RipeMD160HMacTest
+		: ITest
+    {
+        readonly static string[] keys =
+        {
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+        readonly static string[] digests = {
+            "24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668",
+            "dda6c0213a485a9e24f4742064a7f033b43c4069",
+            "b0b105360de759960ab4f35298e116e295d8e7c1",
+            "d5ca862f4d21d5e610e18b4cf1beb97a4365ecf4",
+            "7619693978f91d90539ae786500ff3d8e0518e39",
+            "6466ca07ac5eac29e1bd523e5ada7605b791fd8b",
+            "69ea60798d71616cce5fd0871e23754cd75d5a0a"
+        };
+
+        readonly static string[] messages = {
+            "Hi There",
+            "what do ya want for nothing?",
+            "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "Test With Truncation",
+            "Test Using Larger Than Block-Size Key - Hash Key First",
+            "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"
+        };
+
+        public string Name
+        {
+			get { return "RipeMD160HMac"; }
+        }
+
+		public ITestResult Perform()
+        {
+            HMac hmac = new HMac(new RipeMD160Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new RipeMD160HMacTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD256DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD256DigestTest.cs
new file mode 100644
index 0000000..5b3e6b1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD256DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * RIPEMD256 Digest Test
+	 */
+	[TestFixture]
+	public class RipeMD256DigestTest
+		: DigestTest
+	{
+		readonly static string[] messages = {
+			"",
+			"a",
+			"abc",
+			"message digest",
+			"abcdefghijklmnopqrstuvwxyz",
+			"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+			"12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+		};
+
+		readonly static string[] digests = {
+			"02ba4c4e5f8ecd1877fc52d64d30e37a2d9774fb1e5d026380ae0168e3c5522d",
+			"f9333e45d857f5d90a91bab70a1eba0cfb1be4b0783c9acfcd883a9134692925",
+			"afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65",
+			"87e971759a1ce47a514d5c914c392c9018c7c46bc14465554afcdf54a5070c0e",
+			"649d3034751ea216776bf9a18acc81bc7896118a5197968782dd1fd97d8d5133",
+			"3843045583aac6c8c8d9128573e7a9809afb2a0f34ccc36ea9e72f16f6368e3f",
+			"5740a408ac16b720b84424ae931cbb1fe363d1d0bf4017f1a89f7ea6de77a0b8",
+			"06fdcc7a409548aaf91368c06a6275b553e3f099bf0ea4edfd6778df89a890dd"
+		};
+
+		readonly static string million_a_digest = "ac953744e10e31514c150d4d8d7b677342e33399788296e43ae4850ce4f97978";
+
+		public RipeMD256DigestTest()
+			: base(new RipeMD256Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new RipeMD256Digest((RipeMD256Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RipeMD256DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD320DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD320DigestTest.cs
new file mode 100644
index 0000000..047d68a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RipeMD320DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * RIPEMD320 Digest Test
+	 */
+	[TestFixture]
+	public class RipeMD320DigestTest
+		: DigestTest
+	{
+		readonly static string[] messages = {
+			"",
+			"a",
+			"abc",
+			"message digest",
+			"abcdefghijklmnopqrstuvwxyz",
+			"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+			"12345678901234567890123456789012345678901234567890123456789012345678901234567890"
+		};
+
+		readonly static string[] digests = {
+			"22d65d5661536cdc75c1fdf5c6de7b41b9f27325ebc61e8557177d705a0ec880151c3a32a00899b8",
+			"ce78850638f92658a5a585097579926dda667a5716562cfcf6fbe77f63542f99b04705d6970dff5d",
+			"de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d",
+			"3a8e28502ed45d422f68844f9dd316e7b98533fa3f2a91d29f84d425c88d6b4eff727df66a7c0197",
+			"cabdb1810b92470a2093aa6bce05952c28348cf43ff60841975166bb40ed234004b8824463e6b009",
+			"d034a7950cf722021ba4b84df769a5de2060e259df4c9bb4a4268c0e935bbc7470a969c9d072a1ac",
+			"ed544940c86d67f250d232c30b7b3e5770e0c60c8cb9a4cafe3b11388af9920e1b99230b843c86a4",
+			"557888af5f6d8ed62ab66945c6d2a0a47ecd5341e915eb8fea1d0524955f825dc717e4a008ab2d42"
+		};
+
+		readonly static string million_a_digest = "bdee37f4371e20646b8b0d862dda16292ae36f40965e8c8509e63d1dbddecc503e2b63eb9245bb66";
+
+		public RipeMD320DigestTest()
+			: base(new RipeMD320Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new RipeMD320Digest((RipeMD320Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new RipeMD320DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/RsaTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/RsaTest.cs
new file mode 100644
index 0000000..c343f0b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/RsaTest.cs
@@ -0,0 +1,596 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class RsaTest
+		: SimpleTest
+	{
+		static BigInteger  mod = new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16);
+		static BigInteger  pubExp = new BigInteger("11", 16);
+		static BigInteger  privExp = new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16);
+		static BigInteger  p = new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16);
+		static BigInteger  q = new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16);
+		static BigInteger  pExp = new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16);
+		static BigInteger  qExp = new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16);
+		static BigInteger  crtCoef = new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16);
+
+		static string input = "4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		//
+		// to check that we handling byte extension by big number correctly.
+		//
+		static string edgeInput = "ff6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e";
+
+		static byte[] oversizedSig = Hex.Decode("01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] dudBlock = Hex.Decode("000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] truncatedDataBlock = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff004e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] incorrectPadding = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4e6f77206973207468652074696d6520666f7220616c6c20676f6f64206d656e");
+		static byte[] missingDataBlock = Hex.Decode("0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
+
+		public override string Name
+		{
+			get { return "RSA"; }
+		}
+
+		private void doTestStrictPkcs1Length(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			IAsymmetricBlockCipher   eng = new RsaEngine();
+
+			eng.Init(true, privParameters);
+
+			byte[] data = null;
+
+			try
+			{
+				data = eng.ProcessBlock(oversizedSig, 0, oversizedSig.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+
+				Fail("oversized signature block not recognised");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals("block incorrect size"))
+				{
+					Fail("RSA: failed - exception " + e.ToString(), e);
+				}
+			}
+
+
+			// Create the encoding with StrictLengthEnabled=false (done thru environment in Java version)
+			Pkcs1Encoding.StrictLengthEnabled = false;
+
+			eng = new Pkcs1Encoding(new RsaEngine());
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (InvalidCipherTextException e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			Pkcs1Encoding.StrictLengthEnabled = true;
+		}
+
+		private void doTestTruncatedPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, truncatedDataBlock, "block truncated");
+		}
+
+		private void doTestDudPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, dudBlock, "unknown block type");
+		}
+
+		private void doTestWrongPaddingPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, incorrectPadding, "block padding incorrect");
+		}
+
+		private void doTestMissingDataPkcs1Block(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			checkForPkcs1Exception(pubParameters, privParameters, missingDataBlock, "no data in block");
+		}
+
+		private void checkForPkcs1Exception(RsaKeyParameters pubParameters, RsaKeyParameters privParameters, byte[] inputData, string expectedMessage)
+		{
+			IAsymmetricBlockCipher   eng = new RsaEngine();
+
+			eng.Init(true, privParameters);
+
+			byte[] data = null;
+
+			try
+			{
+				data = eng.ProcessBlock(inputData, 0, inputData.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString(), e);
+			}
+
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+
+				Fail("missing data block not recognised");
+			}
+			catch (InvalidCipherTextException e)
+			{
+				if (!e.Message.Equals(expectedMessage))
+				{
+					Fail("RSA: failed - exception " + e.ToString(), e);
+				}
+			}
+		}
+
+		private void doTestOaep(RsaKeyParameters pubParameters, RsaKeyParameters privParameters)
+		{
+			//
+			// OAEP - public encrypt, private decrypt
+			//
+			IAsymmetricBlockCipher eng = new OaepEncoding(new RsaEngine());
+			byte[] data = Hex.Decode(input);
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed OAEP Test");
+			}
+		}
+
+		// TODO Move this when other JCE tests are ported from Java
+		/**
+		 * signature with a "forged signature" (sig block not at end of plain text)
+		 */
+		private void doTestBadSig()//PrivateKey priv, PublicKey pub)
+		{
+//			Signature           sig = Signature.getInstance("SHA1WithRSAEncryption", "BC");
+			ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption");
+//			KeyPairGenerator    fact;
+//			KeyPair             keyPair;
+//			byte[]              data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+//			fact = KeyPairGenerator.getInstance("RSA", "BC");
+			RsaKeyPairGenerator fact = new RsaKeyPairGenerator();
+
+//			fact.initialize(768, new SecureRandom());
+			RsaKeyGenerationParameters factParams = new RsaKeyGenerationParameters(
+//				BigInteger.ValueOf(0x11), new SecureRandom(), 768, 25);
+				BigInteger.ValueOf(3), new SecureRandom(), 768, 25);
+			fact.Init(factParams);
+
+//			keyPair = fact.generateKeyPair();
+//
+//			PrivateKey  signingKey = keyPair.getPrivate();
+//			PublicKey   verifyKey = keyPair.getPublic();
+			AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair();
+
+			AsymmetricKeyParameter priv = keyPair.Private;
+			AsymmetricKeyParameter pub = keyPair.Public;
+
+//			testBadSig(signingKey, verifyKey);
+
+
+
+
+
+//			MessageDigest sha1 = MessageDigest.getInstance("SHA1", "BC");
+			IDigest sha1 = DigestUtilities.GetDigest("SHA1");
+
+//			Cipher signer = Cipher.getInstance("RSA/ECB/PKCS1Padding", "BC");
+//			IBufferedCipher signer = CipherUtilities.GetCipher("RSA/ECB/PKCS1Padding");
+			IAsymmetricBlockCipher signer = new Pkcs1Encoding(new RsaEngine());
+
+//			signer.init(Cipher.ENCRYPT_MODE, priv);
+			signer.Init(true, priv);
+
+//			byte[] block = new byte[signer.getBlockSize()];
+//			byte[] block = new byte[signer.GetBlockSize()];
+			byte[] block = new byte[signer.GetInputBlockSize()];
+
+//			sha1.update((byte)0);
+			sha1.Update(0);
+
+//			byte[] sigHeader = Hex.decode("3021300906052b0e03021a05000414");
+			byte[] sigHeader = Hex.Decode("3021300906052b0e03021a05000414");
+//			System.arraycopy(sigHeader, 0, block, 0, sigHeader.length);
+			Array.Copy(sigHeader, 0, block, 0, sigHeader.Length);
+
+//			sha1.digest(block, sigHeader.length, sha1.getDigestLength());
+			sha1.DoFinal(block, sigHeader.Length);
+
+//			System.arraycopy(sigHeader, 0, block,
+//				sigHeader.length + sha1.getDigestLength(), sigHeader.length);
+			Array.Copy(sigHeader, 0, block,
+				sigHeader.Length + sha1.GetDigestSize(), sigHeader.Length);
+
+//			byte[] sigBytes = signer.doFinal(block);
+			byte[] sigBytes = signer.ProcessBlock(block, 0, block.Length);
+
+//			Signature verifier = Signature.getInstance("SHA1WithRSA", "BC");
+			ISigner verifier = SignerUtilities.GetSigner("SHA1WithRSA");
+
+//			verifier.initVerify(pub);
+			verifier.Init(false, pub);
+
+//			verifier.update((byte)0);
+			verifier.Update(0);
+
+//			if (verifier.verify(sig))
+			if (verifier.VerifySignature(sigBytes))
+			{
+//				fail("bad signature passed");
+				Fail("bad signature passed");
+			}
+		}
+
+		private void testZeroBlock(ICipherParameters encParameters, ICipherParameters decParameters)
+		{
+			IAsymmetricBlockCipher eng = new Pkcs1Encoding(new RsaEngine());
+		
+			eng.Init(true, encParameters);
+
+			if (eng.GetOutputBlockSize() != ((Pkcs1Encoding)eng).GetUnderlyingCipher().GetOutputBlockSize())
+			{
+				Fail("PKCS1 output block size incorrect");
+			}
+
+			byte[] zero = new byte[0];
+			byte[] data = null;
+
+			try
+			{
+				data = eng.ProcessBlock(zero, 0, zero.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			eng.Init(false, decParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString(), e);
+			}
+
+			if (!Arrays.AreEqual(zero, data))
+			{
+				Fail("failed PKCS1 zero Test");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			RsaKeyParameters pubParameters = new RsaKeyParameters(false, mod, pubExp);
+			RsaKeyParameters privParameters = new RsaPrivateCrtKeyParameters(mod, pubExp, privExp, p, q, pExp, qExp, crtCoef);
+			byte[] data = Hex.Decode(edgeInput);
+
+			//
+			// RAW
+			//
+			IAsymmetricBlockCipher   eng = new RsaEngine();
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("RSA: failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!edgeInput.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed RAW edge Test");
+			}
+
+			data = Hex.Decode(input);
+
+			eng.Init(true, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed RAW Test");
+			}
+
+			//
+			// PKCS1 - public encrypt, private decrypt
+			//
+			eng = new Pkcs1Encoding(eng);
+
+			eng.Init(true, pubParameters);
+
+			if (eng.GetOutputBlockSize() != ((Pkcs1Encoding)eng).GetUnderlyingCipher().GetOutputBlockSize())
+			{
+				Fail("PKCS1 output block size incorrect");
+			}
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed PKCS1 public/private Test");
+			}
+
+			//
+			// PKCS1 - private encrypt, public decrypt
+			//
+			eng = new Pkcs1Encoding(((Pkcs1Encoding)eng).GetUnderlyingCipher());
+
+			eng.Init(true, privParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, pubParameters);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed PKCS1 private/public Test");
+			}
+
+			testZeroBlock(pubParameters, privParameters);
+			testZeroBlock(privParameters, pubParameters);
+
+			//
+			// key generation test
+			//
+			RsaKeyPairGenerator  pGen = new RsaKeyPairGenerator();
+			RsaKeyGenerationParameters  genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x11), new SecureRandom(), 768, 25);
+
+			pGen.Init(genParam);
+
+			AsymmetricCipherKeyPair  pair = pGen.GenerateKeyPair();
+
+			eng = new RsaEngine();
+
+			if (((RsaKeyParameters)pair.Public).Modulus.BitLength < 768)
+			{
+				Fail("failed key generation (768) length test");
+			}
+
+			eng.Init(true, pair.Public);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, pair.Private);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed key generation (768) Test");
+			}
+
+			genParam = new RsaKeyGenerationParameters(BigInteger.ValueOf(0x11), new SecureRandom(), 1024, 25);
+
+			pGen.Init(genParam);
+			pair = pGen.GenerateKeyPair();
+
+			eng.Init(true, pair.Public);
+
+			if (((RsaKeyParameters)pair.Public).Modulus.BitLength < 1024)
+			{
+				Fail("failed key generation (1024) length test");
+			}
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			eng.Init(false, pair.Private);
+
+			try
+			{
+				data = eng.ProcessBlock(data, 0, data.Length);
+			}
+			catch (Exception e)
+			{
+				Fail("failed - exception " + e.ToString());
+			}
+
+			if (!input.Equals(Hex.ToHexString(data)))
+			{
+				Fail("failed key generation (1024) test");
+			}
+
+			genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x11), new SecureRandom(), 16, 25);
+			pGen.Init(genParam);
+
+			for (int i = 0; i < 100; ++i)
+			{
+				pair = pGen.GenerateKeyPair();
+				RsaPrivateCrtKeyParameters privKey = (RsaPrivateCrtKeyParameters) pair.Private;
+				BigInteger pqDiff = privKey.P.Subtract(privKey.Q).Abs();
+
+				if (pqDiff.BitLength < 5)
+				{
+					Fail("P and Q too close in RSA key pair");
+				}
+			}
+
+			doTestBadSig();
+			doTestOaep(pubParameters, privParameters);
+			doTestStrictPkcs1Length(pubParameters, privParameters);
+			doTestDudPkcs1Block(pubParameters, privParameters);
+			doTestMissingDataPkcs1Block(pubParameters, privParameters);
+			doTestTruncatedPkcs1Block(pubParameters, privParameters);
+			doTestWrongPaddingPkcs1Block(pubParameters, privParameters);
+
+			try
+			{
+				new RsaEngine().ProcessBlock(new byte[]{ 1 }, 0, 1);
+				Fail("failed initialisation check");
+			}
+			catch (InvalidOperationException)
+			{
+				// expected
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new RsaTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SCryptTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SCryptTest.cs
new file mode 100644
index 0000000..c055ab7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SCryptTest.cs
@@ -0,0 +1,103 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <summary>
+	/// scrypt test vectors from "Stronger Key Derivation Via Sequential Memory-hard Functions" Appendix B.
+	/// (http://www.tarsnap.com/scrypt/scrypt.pdf)
+	/// </summary>
+	[TestFixture]
+	public class SCryptTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "SCrypt"; }
+		}
+
+		public override void PerformTest()
+		{
+			using (StreamReader sr = new StreamReader(SimpleTest.GetTestDataAsStream("scrypt.TestVectors.txt")))
+			{
+				int count = 0;
+				string line = sr.ReadLine();
+
+				while (line != null)
+				{
+					++count;
+					string header = line;
+					StringBuilder data = new StringBuilder();
+
+					while (!IsEndData(line = sr.ReadLine()))
+					{
+						data.Append(line.Replace(" ", ""));
+					}
+
+					int start = header.IndexOf('(') + 1;
+					int limit = header.LastIndexOf(')');
+					string argStr = header.Substring(start, limit - start);
+					string[] args = argStr.Split(',');
+
+					byte[] P = ExtractQuotedString(args[0]);
+					byte[] S = ExtractQuotedString(args[1]);
+					int N = ExtractInteger(args[2]);
+					int r = ExtractInteger(args[3]);
+					int p = ExtractInteger(args[4]);
+					int dkLen = ExtractInteger(args[5]);
+					byte[] expected = Hex.Decode(data.ToString());
+
+					// This skips very expensive test case(s), remove check to re-enable
+					if (N <= 16384)
+					{
+						byte[] result = SCrypt.Generate(P, S, N, r, p, dkLen);
+
+						if (!AreEqual(expected, result))
+						{
+							Fail("Result does not match expected value in test case " + count);
+						}
+					}
+				}
+			}
+		}
+
+		private static bool IsEndData(string line)
+		{
+			return line == null || line.StartsWith("scrypt");
+		}
+
+		private static byte[] ExtractQuotedString(string arg)
+		{
+			arg = arg.Trim();
+			arg = arg.Substring(1, arg.Length - 2);
+			return Encoding.ASCII.GetBytes(arg);
+		}
+
+		private static int ExtractInteger(string arg)
+		{
+			return int.Parse(arg.Trim());
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SCryptTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SEEDTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SEEDTest.cs
new file mode 100644
index 0000000..2fcb242
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SEEDTest.cs
@@ -0,0 +1,65 @@
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* SEED tester - vectors http://www.ietf.org/rfc/rfc4009.txt
+	*/
+	[TestFixture]
+	public class SeedTest
+		: CipherTest
+	{
+		static SimpleTest[]  tests =
+		{
+			new BlockCipherVectorTest(0, new SeedEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"000102030405060708090a0b0c0d0e0f",
+				"5EBAC6E0054E166819AFF1CC6D346CDB"),
+			new BlockCipherVectorTest(0, new SeedEngine(),
+				new KeyParameter(Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+				"00000000000000000000000000000000",
+				"c11f22f20140505084483597e4370f43"),
+			new BlockCipherVectorTest(0, new SeedEngine(),
+				new KeyParameter(Hex.Decode("4706480851E61BE85D74BFB3FD956185")),
+				"83A2F8A288641FB9A4E9A5CC2F131C7D",
+				"EE54D13EBCAE706D226BC3142CD40D4A"),
+			new BlockCipherVectorTest(0, new SeedEngine(),
+				new KeyParameter(Hex.Decode("28DBC3BC49FFD87DCFA509B11D422BE7")),
+				"B41E6BE2EBA84A148E2EED84593C5EC7",
+				"9B9B7BFCD1813CB95D0B3618F40F5122"),
+			new BlockCipherVectorTest(0, new SeedEngine(),
+				new KeyParameter(Hex.Decode("0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E")),
+				"0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E",
+				"8296F2F1B007AB9D533FDEE35A9AD850"),
+		};
+
+		public SeedTest()
+			: base(tests, new SeedEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "SEED"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SeedTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1DigestTest.cs
new file mode 100644
index 0000000..318035b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1DigestTest.cs
@@ -0,0 +1,57 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <remarks>Standard vector test for SHA-1 from "Handbook of Applied Cryptography", page 345.</remarks>
+	[TestFixture]
+	public class Sha1DigestTest
+		: DigestTest
+	{
+		private static string[] messages =
+		{
+			"",
+			"a",
+			"abc",
+			"abcdefghijklmnopqrstuvwxyz"
+		};
+
+		private static string[] digests =
+		{
+			"da39a3ee5e6b4b0d3255bfef95601890afd80709",
+			"86f7e437faa5a7fce15d1ddcb9eaeaea377667b8",
+			"a9993e364706816aba3e25717850c26c9cd0d89d",
+			"32d10c7b8cf96570ca04ce37f2a19d84240d3a89"
+		};
+
+		public Sha1DigestTest()
+			: base(new Sha1Digest(), messages, digests)
+		{
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new Sha1Digest((Sha1Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Sha1DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1HMacTest.cs
new file mode 100644
index 0000000..865f5b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA1HMacTest.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> SHA1 HMac Test, test vectors from RFC 2202</summary>
+    [TestFixture]
+    public class Sha1HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "SHA1HMac"; }
+        }
+
+		public static readonly string[] keys = new string[]{"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b", "4a656665", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "0102030405060708090a0b0c0d0e0f10111213141516171819", "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [...]
+        public static readonly string[] digests = new string[]{"b617318655057264e28bc0b6fb378c8ef146be00", "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79", "125d7342b9ac11cd91a39af48aa17b4f63f175d3", "4c9007f4026250c6bc8414f9bf50c86c2d7235da", "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", "aa4ae5e15272d00e95705637ce8a3b55ed402112", "e8e99d0f45237d786d6bbaa7965c7808bbff1a91", "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04", "aa4ae5e15272d00e95705637ce8a3b55ed402112", "e8e99d0f45237d786d6bbaa7965c7808 [...]
+        public static readonly string[] messages = new string[]{"Hi There", "what do ya want for nothing?", "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd", "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd", "Test With Truncation", "Test Using Larger Than Block-Size Key - Hash Key First", "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data"};
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new Sha1Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            //
+            // test reset
+            //
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+            if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new Sha1HMacTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224DigestTest.cs
new file mode 100644
index 0000000..9469b65
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224DigestTest.cs
@@ -0,0 +1,70 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * standard vector test for SHA-224 from RFC 3874 - only the last three are in
+	 * the RFC.
+	 */
+	[TestFixture]
+	public class Sha224DigestTest
+		: DigestTest
+	{
+		private static string[] messages =
+		{
+			"",
+			"a",
+			"abc",
+			"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+		};
+
+		private static string[] digests =
+		{
+			"d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f",
+			"abd37534c7d9a2efb9465de931cd7055ffdb8879563ae98078d6d6d5",
+			"23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+			"75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525"
+		};
+
+		// 1 million 'a'
+		private static string million_a_digest = "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67";
+
+		public Sha224DigestTest()
+			: base(new Sha224Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new Sha224Digest((Sha224Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Sha224DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224HMacTest.cs
new file mode 100644
index 0000000..06c6ea1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA224HMacTest.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> SHA224 HMac Test, test vectors from RFC</summary>
+    [TestFixture]
+    public class Sha224HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "SHA224HMac"; }
+        }
+
+		public static readonly string[] keys =
+		{
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+		public static readonly string[] digests =
+		{
+            "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
+            "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
+            "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
+            "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
+            "0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c",
+            "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
+            "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
+        };
+
+		public static readonly string[] messages =
+		{
+            "Hi There",
+            "what do ya want for nothing?",
+            "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "Test With Truncation",
+            "Test Using Larger Than Block-Size Key - Hash Key First",
+            "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+        };
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new Sha224Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            //
+            // test reset
+            //
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+            if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new Sha224HMacTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256DigestTest.cs
new file mode 100644
index 0000000..d2ae89e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256DigestTest.cs
@@ -0,0 +1,71 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for SHA-256 from FIPS Draft 180-2.
+     *
+     * Note, the first two vectors are _not_ from the draft, the last three are.
+     */
+    [TestFixture]
+    public class Sha256DigestTest
+        : DigestTest
+    {
+        private static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+        };
+
+        private static string[] digests =
+        {
+            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+            "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb",
+            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+            "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"
+        };
+
+        // 1 million 'a'
+        static private string  million_a_digest = "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0";
+
+        public Sha256DigestTest()
+            : base(new Sha256Digest(), messages, digests)
+        {
+        }
+
+        public override void PerformTest()
+        {
+            base.PerformTest();
+
+            millionATest(million_a_digest);
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new Sha256Digest((Sha256Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Sha256DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256HMacTest.cs
new file mode 100644
index 0000000..a9016af
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA256HMacTest.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> SHA256 HMac Test, test vectors from RFC</summary>
+    [TestFixture]
+    public class Sha256HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "SHA256HMac"; }
+        }
+
+		public static readonly string[] keys =
+		{
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+		public static readonly string[] digests =
+		{
+            "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+            "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+            "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+            "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+            "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5",
+            "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+            "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
+        };
+
+		public static readonly string[] messages =
+		{
+            "Hi There",
+            "what do ya want for nothing?",
+            "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "Test With Truncation",
+            "Test Using Larger Than Block-Size Key - Hash Key First",
+            "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+        };
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new Sha256Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            //
+            // test reset
+            //
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+            if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new Sha256HMacTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384DigestTest.cs
new file mode 100644
index 0000000..99363ac
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384DigestTest.cs
@@ -0,0 +1,70 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for SHA-384 from FIPS Draft 180-2.
+     *
+     * Note, the first two vectors are _not_ from the draft, the last three are.
+     */
+    [TestFixture]
+    public class Sha384DigestTest
+        : DigestTest
+    {
+        private static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+        };
+
+        private static string[] digests =
+        {
+            "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b",
+            "54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31",
+            "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7",
+            "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712fcc7c71a557e2db966c3e9fa91746039"
+        };
+
+        static private string  million_a_digest = "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b07b8b3dc38ecc4ebae97ddd87f3d8985";
+
+        public Sha384DigestTest()
+            : base(new Sha384Digest(), messages, digests)
+        {
+        }
+
+        public override void PerformTest()
+        {
+            base.PerformTest();
+
+            millionATest(million_a_digest);
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new Sha384Digest((Sha384Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Sha384DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384HMacTest.cs
new file mode 100644
index 0000000..0caba12
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA384HMacTest.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary> SHA384 HMac Test, test vectors from RFC</summary>
+    [TestFixture]
+    public class Sha384HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "SHA384HMac"; }
+        }
+
+		public static readonly string[] keys =
+		{
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+		public static readonly string[] digests =
+		{
+            "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
+            "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649",
+            "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b2a5ab39dc13814b94e3ab6e101a34f27",
+            "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e6801dd23c4a7d679ccf8a386c674cffb",
+            "3abf34c3503b2a23a46efc619baef897f4c8e42c934ce55ccbae9740fcbc1af4ca62269e2a37cd88ba926341efe4aeea",
+            "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c60c2ef6ab4030fe8296248df163f44952",
+            "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5a678cc31e799176d3860e6110c46523e"
+        };
+
+		public static readonly string[] messages =
+		{
+            "Hi There",
+            "what do ya want for nothing?",
+            "0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+            "0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "Test With Truncation",
+            "Test Using Larger Than Block-Size Key - Hash Key First",
+            "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+        };
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new Sha384Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            //
+            // test reset
+            //
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+            if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new Sha384HMacTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA3DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA3DigestTest.cs
new file mode 100644
index 0000000..2b8ae4a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA3DigestTest.cs
@@ -0,0 +1,374 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * SHA3 Digest Test
+     */
+    [TestFixture]
+    public class Sha3DigestTest
+        : SimpleTest
+    {
+        readonly static string[] messages = {
+            "",
+            "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f67",
+            "54686520717569636b2062726f776e20666f78206a756d7073206f76657220746865206c617a7920646f672e"
+        };
+
+        readonly static string[] digests288 = { // the default settings
+            "6753e3380c09e385d0339eb6b050a68f66cfd60a73476e6fd6adeb72f5edd7c6f04a5d01",  // message[0]    
+            "0bbe6afae0d7e89054085c1cc47b1689772c89a41796891e197d1ca1b76f288154933ded",  // message[1]
+            "82558a209b960ddeb531e6dcb281885b2400ca160472462486e79f071e88a3330a8a303d",  // message[2]
+            "94049e1ad7ef5d5b0df2b880489e7ab09ec937c3bfc1b04470e503e1ac7b1133c18f86da",  // 64k a-test
+            "a9cb5a75b5b81b7528301e72553ed6770214fa963956e790528afe420de33c074e6f4220",  // random alphabet test
+            "eadaf5ba2ad6a2f6f338fce0e1efdad2a61bb38f6be6068b01093977acf99e97a5d5827c"   // extremely long data test
+        };
+
+        readonly static string[] digests224 = {
+            "f71837502ba8e10837bdd8d365adb85591895602fc552b48b7390abd",
+            "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe",
+            "c59d4eaeac728671c635ff645014e2afa935bebffdb5fbd207ffdeab",
+            "f621e11c142fbf35fa8c22841c3a812ba1e0151be4f38d80b9f1ff53",
+            "68b5fc8c87193155bba68a2485377e809ee4f81a85ef023b9e64add0",
+            "c42e4aee858e1a8ad2976896b9d23dd187f64436ee15969afdbc68c5"
+        };
+
+        readonly static string[] digests256 = {
+            "c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470",
+            "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15",
+            "578951e24efd62a3d63a86f7cd19aaa53c898fe287d2552133220370240b572d",
+            "0047a916daa1f92130d870b542e22d3108444f5a7e4429f05762fb647e6ed9ed",
+            "db368762253ede6d4f1db87e0b799b96e554eae005747a2ea687456ca8bcbd03",
+            "5f313c39963dcf792b5470d4ade9f3a356a3e4021748690a958372e2b06f82a4"
+        };
+
+        readonly static string[] digests384 = {
+            "2c23146a63a29acf99e73b88f8c24eaa7dc60aa771780ccc006afbfa8fe2479b2dd2b21362337441ac12b515911957ff",
+            "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3",
+            "9ad8e17325408eddb6edee6147f13856ad819bb7532668b605a24a2d958f88bd5c169e56dc4b2f89ffd325f6006d820b",
+            "c704cfe7a1a53208ca9526cd24251e0acdc252ecd978eee05acd16425cfb404ea81f5a9e2e5e97784d63ee6a0618a398",
+            "d4fe8586fd8f858dd2e4dee0bafc19b4c12b4e2a856054abc4b14927354931675cdcaf942267f204ea706c19f7beefc4",
+            "9b7168b4494a80a86408e6b9dc4e5a1837c85dd8ff452ed410f2832959c08c8c0d040a892eb9a755776372d4a8732315"
+        };
+
+        readonly static string[] digests512 = {
+            "0eab42de4c3ceb9235fc91acffe746b29c29a8c366b7c60e4e67c466f36a4304c00fa9caf9d87976ba469bcbe06713b435f091ef2769fb160cdab33d3670680e",
+            "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609",
+            "ab7192d2b11f51c7dd744e7b3441febf397ca07bf812cceae122ca4ded6387889064f8db9230f173f6d1ab6e24b6e50f065b039f799f5592360a6558eb52d760",
+            "34341ead153aa1d1fdcf6cf624c2b4f6894b6fd16dc38bd4ec971ac0385ad54fafcb2e0ed86a1e509456f4246fdcb02c3172824cd649d9ad54c51f7fb49ea67c",
+            "dc44d4f4d36b07ab5fc04016cbe53548e5a7778671c58a43cb379fd00c06719b8073141fc22191ffc3db5f8b8983ae8341fa37f18c1c969664393aa5ceade64e",
+            "3e122edaf37398231cfaca4c7c216c9d66d5b899ec1d7ac617c40c7261906a45fc01617a021e5da3bd8d4182695b5cb785a28237cbb167590e34718e56d8aab8"
+        };
+
+        // test vectors from  http://www.di-mgt.com.au/hmac_sha3_testvectors.html
+        readonly static byte[][] macKeys =
+        {
+            Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"),
+            Hex.Decode("4a656665"),
+            Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
+            Hex.Decode("0102030405060708090a0b0c0d0e0f10111213141516171819"),
+            Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaa"),
+            Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaa"),
+            Hex.Decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +
+                       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+        };
+
+        readonly static string[] macData =
+        {
+            "4869205468657265",
+            "7768617420646f2079612077616e7420666f72206e6f7468696e673f",
+            "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" +
+                "dddddddddddddddddddddddddddddddddddd",
+            "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd" +
+                "cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+            "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a" +
+                "65204b6579202d2048617368204b6579204669727374",
+            "5468697320697320612074657374207573696e672061206c6172676572207468" +
+                "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
+                "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
+                "647320746f20626520686173686564206265666f7265206265696e6720757365" +
+                "642062792074686520484d414320616c676f726974686d2e",
+            "5468697320697320612074657374207573696e672061206c6172676572207468" +
+                "616e20626c6f636b2d73697a65206b657920616e642061206c61726765722074" +
+                "68616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565" +
+                "647320746f20626520686173686564206265666f7265206265696e6720757365\n" +
+                "642062792074686520484d414320616c676f726974686d2e"
+        };
+
+        readonly static string[] mac224 =
+        {
+            "b73d595a2ba9af815e9f2b4e53e78581ebd34a80b3bbaac4e702c4cc",
+            "e824fec96c074f22f99235bb942da1982664ab692ca8501053cbd414",
+            "770df38c99d6e2bacd68056dcfe07d4c89ae20b2686a6185e1faa449",
+            "305a8f2dfb94bad28861a03cbc4d590febe775c58cb4961c28428a0b",
+            "e7a52dfa45f95a217c100066b239aa8ad519be9b35d667268b1b57ff",
+            "ba13009405a929f398b348885caa5419191bb948ada32194afc84104",
+            "92649468be236c3c72c189909c063b13f994be05749dc91310db639e"
+        };
+
+        readonly static string[] mac256 =
+        {
+            "9663d10c73ee294054dc9faf95647cb99731d12210ff7075fb3d3395abfb9821",
+            "aa9aed448c7abc8b5e326ffa6a01cdedf7b4b831881468c044ba8dd4566369a1",
+            "95f43e50f8df80a21977d51a8db3ba572dcd71db24687e6f86f47c1139b26260",
+            "6331ba9b4af5804a68725b3663eb74814494b63c6093e35fb320a85d507936fd",
+            "b4d0cdee7ec2ba81a88b86918958312300a15622377929a054a9ce3ae1fac2b6",
+            "1fdc8cb4e27d07c10d897dec39c217792a6e64fa9c63a77ce42ad106ef284e02",
+            "fdaa10a0299aecff9bb411cf2d7748a4022e4a26be3fb5b11b33d8c2b7ef5484"
+        };
+
+        readonly static string[] mac384 =
+        {
+            "892dfdf5d51e4679bf320cd16d4c9dc6f749744608e003add7fba894acff87361efa4e5799be06b6461f43b60ae97048",
+            "5af5c9a77a23a6a93d80649e562ab77f4f3552e3c5caffd93bdf8b3cfc6920e3023fc26775d9df1f3c94613146ad2c9d",
+            "4243c29f2201992ff96441e3b91ff81d8c601d706fbc83252684a4bc51101ca9b2c06ddd03677303c502ac5331752a3c",
+            "b730724d3d4090cda1be799f63acbbe389fef7792fc18676fa5453aab398664650ed029c3498bbe8056f06c658e1e693",
+            "d62482ef601d7847439b55236e9679388ffcd53c62cd126f39be6ea63de762e26cd5974cb9a8de401b786b5555040f6f",
+            "4860ea191ac34994cf88957afe5a836ef36e4cc1a66d75bf77defb7576122d75f60660e4cf731c6effac06402787e2b9",
+            "fe9357e3cfa538eb0373a2ce8f1e26ad6590afdaf266f1300522e8896d27e73f654d0631c8fa598d4bb82af6b744f4f5"
+        };
+
+        readonly static string[] mac512 =
+        {
+            "8852c63be8cfc21541a4ee5e5a9a852fc2f7a9adec2ff3a13718ab4ed81aaea0b87b7eb397323548e261a64e7fc75198f6663a11b22cd957f7c8ec858a1c7755",
+            "c2962e5bbe1238007852f79d814dbbecd4682e6f097d37a363587c03bfa2eb0859d8d9c701e04cececfd3dd7bfd438f20b8b648e01bf8c11d26824b96cebbdcb",
+            "eb0ed9580e0ec11fc66cbb646b1be904eaff6da4556d9334f65ee4b2c85739157bae9027c51505e49d1bb81cfa55e6822db55262d5a252c088a29a5e95b84a66",
+            "b46193bb59f4f696bf702597616da91e2a4558a593f4b015e69141ba81e1e50ea580834c2b87f87baa25a3a03bfc9bb389847f2dc820beae69d30c4bb75369cb",
+            "d05888a6ebf8460423ea7bc85ea4ffda847b32df32291d2ce115fd187707325c7ce4f71880d91008084ce24a38795d20e6a28328a0f0712dc38253370da3ebb5",
+            "2c6b9748d35c4c8db0b4407dd2ed2381f133bdbd1dfaa69e30051eb6badfcca64299b88ae05fdbd3dd3dd7fe627e42e39e48b0fe8c7f1e85f2dbd52c2d753572",
+            "6adc502f14e27812402fc81a807b28bf8a53c87bea7a1df6256bf66f5de1a4cb741407ad15ab8abc136846057f881969fbb159c321c904bfb557b77afb7778c8"
+        };
+
+        readonly static KeyParameter truncKey = new KeyParameter(Hex.Decode("0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c"));
+        readonly static byte[] truncData = Hex.Decode("546573742057697468205472756e636174696f6e");
+
+        readonly static byte[] trunc224 = Hex.Decode("f52bbcfd654264e7133085c5e69b72c3");
+        readonly static byte[] trunc256 = Hex.Decode("745e7e687f8335280d54202ef13cecc6");
+        readonly static byte[] trunc384 = Hex.Decode("fa9aea2bc1e181e47cbb8c3df243814d");
+        readonly static byte[] trunc512 = Hex.Decode("04c929fead434bba190dacfa554ce3f5");
+
+        readonly static byte[] xtremeData = Hex.Decode("61626364656667686263646566676869636465666768696a6465666768696a6b65666768696a6b6c666768696a6b6c6d6768696a6b6c6d6e68696a6b6c6d6e6f");
+
+        public override string Name
+        {
+            get { return "SHA3"; }
+        }
+
+        private void TestDigest(IDigest digest, string[] expected)
+        {
+            byte[] hash = new byte[digest.GetDigestSize()];
+
+            for (int i = 0; i != messages.Length; i++)
+            {
+                if (messages.Length != 0)
+                {
+                    byte[] data = Hex.Decode(messages[i]);
+
+                    digest.BlockUpdate(data, 0, data.Length);
+                }
+
+                digest.DoFinal(hash, 0);
+
+                if (!Arrays.AreEqual(Hex.Decode(expected[i]), hash))
+                {
+                    Fail("sha3 mismatch on " + digest.AlgorithmName + " index " + i);
+                }
+            }
+
+            byte[] k64 = new byte[1024 * 64];
+
+            for (int i = 0; i != k64.Length; i++)
+            {
+                k64[i] = (byte)'a';
+            }
+
+            digest.BlockUpdate(k64, 0, k64.Length);
+
+            digest.DoFinal(hash, 0);
+
+            if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash))
+            {
+                Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k a");
+            }
+
+            for (int i = 0; i != k64.Length; i++)
+            {
+                digest.Update((byte)'a');
+            }
+
+            digest.DoFinal(hash, 0);
+
+            if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length]), hash))
+            {
+                Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k a single");
+            }
+
+
+            for (int i = 0; i != k64.Length; i++)
+            {
+                k64[i] = (byte)('a' + (i % 26));
+            }
+
+            digest.BlockUpdate(k64, 0, k64.Length);
+
+            digest.DoFinal(hash, 0);
+
+            if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash))
+            {
+                Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k alpha");
+            }
+
+            for (int i = 0; i != 64; i++)
+            {
+                digest.Update(k64[i * 1024]);
+                digest.BlockUpdate(k64, i * 1024 + 1, 1023);
+            }
+
+            digest.DoFinal(hash, 0);
+
+            if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 1]), hash))
+            {
+                Fail("sha3 mismatch on " + digest.AlgorithmName + " 64k chunked alpha");
+            }
+
+            TestDigestDoFinal(digest);
+
+            //
+            // extremely long data test
+            //
+            //Console.WriteLine("Starting very long");
+            //for (int i = 0; i != 16384; i++)
+            //{
+            //    for (int j = 0; j != 1024; j++)
+            //    {
+            //        digest.BlockUpdate(xtremeData, 0, xtremeData.Length);
+            //    }
+            //}
+    
+            //digest.DoFinal(hash, 0);
+    
+            //if (!Arrays.AreEqual(Hex.Decode(expected[messages.Length + 2]), hash))
+            //{
+            //    Fail("sha3 mismatch on " + digest.AlgorithmName + " extreme data test");
+            //}
+            //Console.WriteLine("Done");
+        }
+
+        private void TestDigestDoFinal(IDigest digest)
+        {
+            byte[] hash = new byte[digest.GetDigestSize()];
+            digest.DoFinal(hash, 0);
+
+            for (int i = 0; i <= digest.GetDigestSize(); ++i)
+            {
+                byte[] cmp = new byte[2 * digest.GetDigestSize()];
+                Array.Copy(hash, 0, cmp, i, hash.Length);
+
+                byte[] buf = new byte[2 * digest.GetDigestSize()];
+                digest.DoFinal(buf, i);
+
+                if (!Arrays.AreEqual(cmp, buf))
+                {
+                    Fail("sha3 offset DoFinal on " + digest.AlgorithmName);
+                }
+            }
+        }
+
+        private void TestMac(IDigest digest, byte[][] keys, String[] data, String[] expected, byte[] truncExpected)
+        {
+            IMac mac = new HMac(digest);
+
+            for (int i = 0; i != keys.Length; i++)
+            {
+                mac.Init(new KeyParameter(keys[i]));
+
+                byte[] mData = Hex.Decode(data[i]);
+
+                mac.BlockUpdate(mData, 0, mData.Length);
+
+                byte[] macV = new byte[mac.GetMacSize()];
+
+                mac.DoFinal(macV, 0);
+
+                if (!Arrays.AreEqual(Hex.Decode(expected[i]), macV))
+                {
+                    Fail("sha3 HMAC mismatch on " + digest.AlgorithmName);
+                }
+            }
+
+            {
+                mac = new HMac(digest);
+
+                mac.Init(truncKey);
+
+                mac.BlockUpdate(truncData, 0, truncData.Length);
+
+                byte[] macV = new byte[mac.GetMacSize()];
+
+                mac.DoFinal(macV, 0);
+
+                for (int i = 0; i != truncExpected.Length; i++)
+                {
+                    if (macV[i] != truncExpected[i])
+                    {
+                        Fail("mismatch on truncated HMAC for " + digest.AlgorithmName);
+                    }
+                }
+            }
+        }
+
+        public override void PerformTest()
+        {
+            TestDigest(new Sha3Digest(), digests288);
+            TestDigest(new Sha3Digest(224), digests224);
+            TestDigest(new Sha3Digest(256), digests256);
+            TestDigest(new Sha3Digest(384), digests384);
+            TestDigest(new Sha3Digest(512), digests512);
+
+            TestMac(new Sha3Digest(224), macKeys, macData, mac224, trunc224);
+            TestMac(new Sha3Digest(256), macKeys, macData, mac256, trunc256);
+            TestMac(new Sha3Digest(384), macKeys, macData, mac384, trunc384);
+            TestMac(new Sha3Digest(512), macKeys, macData, mac512, trunc512);
+        }
+
+        protected virtual IDigest CloneDigest(IDigest digest)
+        {
+            return new Sha3Digest((Sha3Digest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Sha3DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512DigestTest.cs
new file mode 100644
index 0000000..d4f56e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512DigestTest.cs
@@ -0,0 +1,70 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/// <summary>
+	/// Standard vector test for SHA-512 from FIPS Draft 180-2.
+	/// Note, the first two vectors are _not_ from the draft, the last three are.
+	/// </summary>
+	[TestFixture]
+	public class Sha512DigestTest
+		: DigestTest
+	{
+		private static string[] messages =
+		{
+			"",
+			"a",
+			"abc",
+			"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+		};
+
+		private static string[] digests =
+		{
+			"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e",
+			"1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75",
+			"ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+			"8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909"   
+		};
+
+		// 1 million 'a'
+		static private string  million_a_digest = "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b";
+
+		public Sha512DigestTest()
+			: base(new Sha512Digest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			millionATest(million_a_digest);
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new Sha512Digest((Sha512Digest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Sha512DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512HMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512HMacTest.cs
new file mode 100644
index 0000000..c091a72
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512HMacTest.cs
@@ -0,0 +1,123 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+    /// <summary> SHA512 HMac Test, test vectors from RFC</summary>
+    [TestFixture]
+    public class Sha512HMacTest
+		: ITest
+    {
+        public string Name
+        {
+			get { return "SHA512HMac"; }
+        }
+
+		public static readonly string[] keys =
+		{
+            "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
+            "4a656665",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "0102030405060708090a0b0c0d0e0f10111213141516171819",
+            "0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+            "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+        };
+
+		public static readonly string[] digests =
+		{
+            "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
+            "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
+            "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
+            "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
+            "415fad6271580a531d4179bc891d87a650188707922a4fbb36663a1eb16da008711c5b50ddd0fc235084eb9d3364a1454fb2ef67cd1d29fe6773068ea266e96b",
+            "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
+            "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
+        };
+
+		public static readonly string[] messages =
+		{
+			"Hi There",
+			"what do ya want for nothing?",
+			"0xdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
+			"0xcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd",
+			"Test With Truncation",
+			"Test Using Larger Than Block-Size Key - Hash Key First",
+			"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."
+		};
+
+		public virtual ITestResult Perform()
+        {
+            HMac hmac = new HMac(new Sha512Digest());
+            byte[] resBuf = new byte[hmac.GetMacSize()];
+
+            for (int i = 0; i < messages.Length; i++)
+            {
+                byte[] m = Encoding.ASCII.GetBytes(messages[i]);
+                if (messages[i].StartsWith("0x"))
+                {
+                    m = Hex.Decode(messages[i].Substring(2));
+                }
+                hmac.Init(new KeyParameter(Hex.Decode(keys[i])));
+                hmac.BlockUpdate(m, 0, m.Length);
+                hmac.DoFinal(resBuf, 0);
+
+                if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[i])))
+                {
+                    return new SimpleTestResult(false, Name + ": Vector " + i + " failed");
+                }
+            }
+
+            //
+            // test reset
+            //
+            int vector = 0; // vector used for test
+            byte[] m2 = Encoding.ASCII.GetBytes(messages[vector]);
+            if (messages[vector].StartsWith("0x"))
+            {
+                m2 = Hex.Decode(messages[vector].Substring(2));
+            }
+            hmac.Init(new KeyParameter(Hex.Decode(keys[vector])));
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+            hmac.Reset();
+            hmac.BlockUpdate(m2, 0, m2.Length);
+            hmac.DoFinal(resBuf, 0);
+
+            if (!Arrays.AreEqual(resBuf, Hex.Decode(digests[vector])))
+            {
+                return new SimpleTestResult(false, Name + "Reset with vector " + vector + " failed");
+            }
+
+            return new SimpleTestResult(true, Name + ": Okay");
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new Sha512HMacTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t224DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t224DigestTest.cs
new file mode 100644
index 0000000..a3d68e1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t224DigestTest.cs
@@ -0,0 +1,62 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for SHA-512/224 from FIPS 180-4.
+     *
+     * Note, only the last 2 message entries are FIPS originated..
+     */
+    public class Sha512t224DigestTest
+        : DigestTest
+    {
+        private static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+        };
+
+        private static string[] digests =
+        {
+            "6ed0dd02806fa89e25de060c19d3ac86cabb87d6a0ddd05c333b84f4",
+            "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327",
+            "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA",
+            "23FEC5BB94D60B23308192640B0C453335D664734FE40E7268674AF9"
+        };
+
+        // 1 million 'a'
+        private const string million_a_digest = "37ab331d76f0d36de422bd0edeb22a28accd487b7a8453ae965dd287";
+
+        internal Sha512t224DigestTest()
+            : base(new Sha512tDigest(224), messages, digests)
+        {
+        }
+
+        public override void PerformTest()
+        {
+            base.PerformTest();
+
+            millionATest(million_a_digest);
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new Sha512tDigest((Sha512tDigest)digest);
+        }
+
+        public static void Main(
+            string[]    args)
+        {
+            RunTest(new Sha512t224DigestTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t256DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t256DigestTest.cs
new file mode 100644
index 0000000..c957aa6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SHA512t256DigestTest.cs
@@ -0,0 +1,62 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * standard vector test for SHA-512/256 from FIPS 180-4.
+     *
+     * Note, only the last 2 message entries are FIPS originated..
+     */
+    public class Sha512t256DigestTest
+        : DigestTest
+    {
+        private static string[] messages =
+        {
+            "",
+            "a",
+            "abc",
+            "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
+        };
+
+        private static string[] digests =
+        {
+            "c672b8d1ef56ed28ab87c3622c5114069bdd3ad7b8f9737498d0c01ecef0967a",
+            "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8",
+            "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23",
+            "3928E184FB8690F840DA3988121D31BE65CB9D3EF83EE6146FEAC861E19B563A"
+        };
+
+        // 1 million 'a'
+        private const string million_a_digest = "9a59a052930187a97038cae692f30708aa6491923ef5194394dc68d56c74fb21";
+
+        internal Sha512t256DigestTest()
+            : base(new Sha512tDigest(256), messages, digests)
+        {
+        }
+
+        public override void PerformTest()
+        {
+            base.PerformTest();
+
+            millionATest(million_a_digest);
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new Sha512tDigest((Sha512tDigest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Sha512t256DigestTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SM3DigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SM3DigestTest.cs
new file mode 100644
index 0000000..1137898
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SM3DigestTest.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	 * standard vector test for SM3 digest from chinese specification
+	 */
+	[TestFixture]
+	public class SM3DigestTest
+	    : DigestTest
+	{
+	    private static string[] messages = {
+	        // Standard test vectors
+	        "abc",
+	        "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd",
+	        // Non-standard test vectors
+	        "",
+	        "a",
+	        "abcdefghijklmnopqrstuvwxyz",
+	    };
+
+	    private static string[] digests = {
+	        // Standard test vectors
+	        "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
+	        "debe9ff92275b8a138604889c18e5a4d6fdb70e5387e5765293dcba39c0c5732",
+	        // Non-standard test vectors
+	        "1ab21d8355cfa17f8e61194831e81a8f22bec8c728fefb747ed035eb5082aa2b",
+	        "623476ac18f65a2909e43c7fec61b49c7e764a91a18ccb82f1917a29c86c5e88",
+	        "b80fe97a4da24afc277564f66a359ef440462ad28dcc6d63adb24d5c20a61595",
+	    };
+
+	    private static string sixtyFourKdigest = "97049bdc8f0736bc7300eafa9980aeb9cf00f24f7ec3a8f1f8884954d7655c1d";
+	    private static string million_a_digest = "c8aaf89429554029e231941a2acc0ad61ff2a5acd8fadd25847a3a732b3b02c3";
+
+	    public SM3DigestTest()
+			: base(new SM3Digest(), messages, digests)
+	    {
+	    }
+
+	    public override void PerformTest()
+	    {
+	        base.PerformTest();
+
+	        sixtyFourKTest(sixtyFourKdigest);
+	        millionATest(million_a_digest);
+	    }
+
+	    protected override IDigest CloneDigest(IDigest digest)
+	    {
+	        return new SM3Digest((SM3Digest)digest);
+	    }
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SM3DigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SRP6Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SRP6Test.cs
new file mode 100644
index 0000000..3b80e2c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SRP6Test.cs
@@ -0,0 +1,300 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Agreement.Srp;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class Srp6Test
+		: SimpleTest
+	{
+	    private static BigInteger FromHex(string hex)
+	    {
+	        return new BigInteger(1, Hex.Decode(hex));
+	    }
+
+		// 1024 bit example prime from RFC5054 and corresponding generator
+		private static readonly BigInteger N_1024 = FromHex("EEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C"
+	            + "9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE4"
+	            + "8E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B29"
+	            + "7BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9A"
+	            + "FD5138FE8376435B9FC61D2FC0EB06E3");
+		private static readonly BigInteger g_1024 = BigInteger.Two;
+
+		private readonly SecureRandom random = new SecureRandom();
+
+	    public override string Name
+	    {
+	        get { return "SRP6"; }
+	    }
+
+	    public override void PerformTest()
+	    {
+	    	rfc5054AppendixBTestVectors();
+
+	        testMutualVerification(N_1024, g_1024);
+	        testClientCatchesBadB(N_1024, g_1024);
+	        testServerCatchesBadA(N_1024, g_1024);
+
+			testWithRandomParams(256);
+			testWithRandomParams(384);
+			testWithRandomParams(512);
+	    }
+
+	    private void rfc5054AppendixBTestVectors()
+	    {
+	    	byte[] I = Encoding.UTF8.GetBytes("alice");
+	    	byte[] P = Encoding.UTF8.GetBytes("password123");
+	    	byte[] s = Hex.Decode("BEB25379D1A8581EB5A727673A2441EE");
+	    	BigInteger N = N_1024;
+	    	BigInteger g = g_1024;
+	    	BigInteger a = FromHex("60975527035CF2AD1989806F0407210BC81EDC04E2762A56AFD529DDDA2D4393");
+	    	BigInteger b = FromHex("E487CB59D31AC550471E81F00F6928E01DDA08E974A004F49E61F5D105284D20");
+
+	    	BigInteger expect_k = FromHex("7556AA045AEF2CDD07ABAF0F665C3E818913186F");
+	    	BigInteger expect_x = FromHex("94B7555AABE9127CC58CCF4993DB6CF84D16C124");
+	    	BigInteger expect_v = FromHex("7E273DE8696FFC4F4E337D05B4B375BEB0DDE1569E8FA00A9886D812"
+	            + "9BADA1F1822223CA1A605B530E379BA4729FDC59F105B4787E5186F5"
+	            + "C671085A1447B52A48CF1970B4FB6F8400BBF4CEBFBB168152E08AB5"
+	            + "EA53D15C1AFF87B2B9DA6E04E058AD51CC72BFC9033B564E26480D78"
+	            + "E955A5E29E7AB245DB2BE315E2099AFB");
+	    	BigInteger expect_A = FromHex("61D5E490F6F1B79547B0704C436F523DD0E560F0C64115BB72557EC4"
+	            + "4352E8903211C04692272D8B2D1A5358A2CF1B6E0BFCF99F921530EC"
+	            + "8E39356179EAE45E42BA92AEACED825171E1E8B9AF6D9C03E1327F44"
+	            + "BE087EF06530E69F66615261EEF54073CA11CF5858F0EDFDFE15EFEA"
+	            + "B349EF5D76988A3672FAC47B0769447B");
+	    	BigInteger expect_B = FromHex("BD0C61512C692C0CB6D041FA01BB152D4916A1E77AF46AE105393011"
+	            + "BAF38964DC46A0670DD125B95A981652236F99D9B681CBF87837EC99"
+	            + "6C6DA04453728610D0C6DDB58B318885D7D82C7F8DEB75CE7BD4FBAA"
+	            + "37089E6F9C6059F388838E7A00030B331EB76840910440B1B27AAEAE"
+	            + "EB4012B7D7665238A8E3FB004B117B58");
+	    	BigInteger expect_u = FromHex("CE38B9593487DA98554ED47D70A7AE5F462EF019");
+	    	BigInteger expect_S = FromHex("B0DC82BABCF30674AE450C0287745E7990A3381F63B387AAF271A10D"
+	            + "233861E359B48220F7C4693C9AE12B0A6F67809F0876E2D013800D6C"
+	            + "41BB59B6D5979B5C00A172B4A2A5903A0BDCAF8A709585EB2AFAFA8F"
+	            + "3499B200210DCC1F10EB33943CD67FC88A2F39A4BE5BEC4EC0A3212D"
+	            + "C346D7E474B29EDE8A469FFECA686E5A");
+
+	    	BigInteger k = Srp6Utilities.CalculateK(new Sha1Digest(), N, g);
+	    	if (!k.Equals(expect_k))
+	    	{
+	    		Fail("wrong value of 'k'");
+	    	}
+
+	    	BigInteger x = Srp6Utilities.CalculateX(new Sha1Digest(), N, s, I, P);
+	    	if (!x.Equals(expect_x))
+	    	{
+	    		Fail("wrong value of 'x'");
+	    	}
+
+	    	Srp6VerifierGenerator gen = new Srp6VerifierGenerator();
+	    	gen.Init(N, g, new Sha1Digest());
+	    	BigInteger v = gen.GenerateVerifier(s, I, P);
+	    	if (!v.Equals(expect_v))
+	    	{
+	    		Fail("wrong value of 'v'");
+	    	}
+
+	        Srp6Client client = new MySrp6Client(a);
+	        client.Init(N, g, new Sha1Digest(), random);
+
+	    	BigInteger A = client.GenerateClientCredentials(s, I, P);
+	    	if (!A.Equals(expect_A))
+	    	{
+	    		Fail("wrong value of 'A'");
+	    	}
+
+	    	Srp6Server server = new MySrp6Server(b);
+	        server.Init(N, g, v, new Sha1Digest(), random);
+
+	    	BigInteger B = server.GenerateServerCredentials();
+	    	if (!B.Equals(expect_B))
+	    	{
+	    		Fail("wrong value of 'B'");
+	    	}
+
+	        BigInteger u = Srp6Utilities.CalculateU(new Sha1Digest(), N, A, B);
+	    	if (!u.Equals(expect_u))
+	    	{
+	    		Fail("wrong value of 'u'");
+	    	}
+
+	        BigInteger clientS = client.CalculateSecret(B);
+	        if (!clientS.Equals(expect_S))
+	    	{
+	    		Fail("wrong value of 'S' (client)");
+	    	}
+
+	        BigInteger serverS = server.CalculateSecret(A);
+	        if (!serverS.Equals(expect_S))
+	    	{
+	    		Fail("wrong value of 'S' (server)");
+	    	}
+	    }
+
+		private void testWithRandomParams(int bits)
+		{
+	        DHParametersGenerator paramGen = new DHParametersGenerator();
+	        paramGen.Init(bits, 25, random);
+	        DHParameters parameters = paramGen.GenerateParameters();
+
+	        BigInteger g = parameters.G;
+	        BigInteger p = parameters.P;
+
+	        testMutualVerification(p, g);
+		}
+
+	    private void testMutualVerification(BigInteger N, BigInteger g)
+	    {
+	        byte[] I = Encoding.UTF8.GetBytes("username");
+	        byte[] P = Encoding.UTF8.GetBytes("password");
+	        byte[] s = new byte[16];
+	        random.NextBytes(s);
+
+	        Srp6VerifierGenerator gen = new Srp6VerifierGenerator();
+	        gen.Init(N, g, new Sha256Digest());
+	        BigInteger v = gen.GenerateVerifier(s, I, P);
+
+	        Srp6Client client = new Srp6Client();
+	        client.Init(N, g, new Sha256Digest(), random);
+
+	        Srp6Server server = new Srp6Server();
+	        server.Init(N, g, v, new Sha256Digest(), random);
+
+	        BigInteger A = client.GenerateClientCredentials(s, I, P);
+	        BigInteger B = server.GenerateServerCredentials();
+
+	        BigInteger clientS = client.CalculateSecret(B);
+	        BigInteger serverS = server.CalculateSecret(A);
+
+	        if (!clientS.Equals(serverS))
+	        {
+	            Fail("SRP agreement failed - client/server calculated different secrets");
+	        }
+	    }
+
+	    private void testClientCatchesBadB(BigInteger N, BigInteger g)
+	    {
+	        byte[] I = Encoding.UTF8.GetBytes("username");
+	        byte[] P = Encoding.UTF8.GetBytes("password");
+	        byte[] s = new byte[16];
+	        random.NextBytes(s);
+
+	        Srp6Client client = new Srp6Client();
+	        client.Init(N, g, new Sha256Digest(), random);
+
+	        client.GenerateClientCredentials(s, I, P);
+
+	        try
+	        {
+	        	client.CalculateSecret(BigInteger.Zero);
+	        	Fail("Client failed to detect invalid value for 'B'");
+	        }
+	        catch (CryptoException)
+	        {
+	        	// Expected
+	        }
+
+	        try
+	        {
+	        	client.CalculateSecret(N);
+	        	Fail("Client failed to detect invalid value for 'B'");
+	        }
+	        catch (CryptoException)
+	        {
+	        	// Expected
+	        }
+	    }
+
+	    private void testServerCatchesBadA(BigInteger N, BigInteger g)
+	    {
+	        byte[] I = Encoding.UTF8.GetBytes("username");
+	        byte[] P = Encoding.UTF8.GetBytes("password");
+	        byte[] s = new byte[16];
+	        random.NextBytes(s);
+
+	        Srp6VerifierGenerator gen = new Srp6VerifierGenerator();
+	        gen.Init(N, g, new Sha256Digest());
+	        BigInteger v = gen.GenerateVerifier(s, I, P);
+
+	        Srp6Server server = new Srp6Server();
+	        server.Init(N, g, v, new Sha256Digest(), random);
+
+	        server.GenerateServerCredentials();
+
+	        try
+	        {
+	        	server.CalculateSecret(BigInteger.Zero);
+	        	Fail("Client failed to detect invalid value for 'A'");
+	        }
+	        catch (CryptoException)
+	        {
+	        	// Expected
+	        }
+
+	        try
+	        {
+	        	server.CalculateSecret(N);
+	        	Fail("Client failed to detect invalid value for 'A'");
+	        }
+	        catch (CryptoException)
+	        {
+	        	// Expected
+	        }
+	    }
+
+	    public static void Main(string[] args)
+	    {
+	        RunTest(new Srp6Test());
+	    }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+		private class MySrp6Client
+			: Srp6Client
+		{
+			private readonly BigInteger nonRandomPrivA;
+
+			internal MySrp6Client(BigInteger nonRandomPrivA)
+			{
+				this.nonRandomPrivA = nonRandomPrivA;
+			}
+
+            protected override BigInteger SelectPrivateValue()
+            {
+                return nonRandomPrivA;
+            }
+		}
+
+		private class MySrp6Server
+			: Srp6Server
+		{
+			private readonly BigInteger nonRandomPrivB;
+
+			internal MySrp6Server(BigInteger nonRandomPrivB)
+			{
+				this.nonRandomPrivB = nonRandomPrivB;
+			}
+
+            protected override BigInteger SelectPrivateValue()
+            {
+                return nonRandomPrivB;
+            }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Salsa20Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Salsa20Test.cs
new file mode 100644
index 0000000..b4dc1ef
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Salsa20Test.cs
@@ -0,0 +1,318 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* Salsa20 Test
+	*/
+	[TestFixture]
+	public class Salsa20Test
+		: SimpleTest
+	{
+		private static readonly byte[] zeroes = Hex.Decode(
+			  "00000000000000000000000000000000"
+			+ "00000000000000000000000000000000"
+			+ "00000000000000000000000000000000"
+			+ "00000000000000000000000000000000");
+
+		private static readonly string set1v0_0 =
+			  "4DFA5E481DA23EA09A31022050859936"
+			+ "DA52FCEE218005164F267CB65F5CFD7F"
+			+ "2B4F97E0FF16924A52DF269515110A07"
+			+ "F9E460BC65EF95DA58F740B7D1DBB0AA";
+
+		private static readonly string set1v0_192 =
+			  "DA9C1581F429E0A00F7D67E23B730676"
+			+ "783B262E8EB43A25F55FB90B3E753AEF"
+			+ "8C6713EC66C51881111593CCB3E8CB8F"
+			+ "8DE124080501EEEB389C4BCB6977CF95";
+
+		private static readonly string set1v0_256 =
+			  "7D5789631EB4554400E1E025935DFA7B"
+			+ "3E9039D61BDC58A8697D36815BF1985C"
+			+ "EFDF7AE112E5BB81E37ECF0616CE7147"
+			+ "FC08A93A367E08631F23C03B00A8DA2F";
+
+		private static readonly string set1v0_448 =
+			  "B375703739DACED4DD4059FD71C3C47F"
+			+ "C2F9939670FAD4A46066ADCC6A564578"
+			+ "3308B90FFB72BE04A6B147CBE38CC0C3"
+			+ "B9267C296A92A7C69873F9F263BE9703";
+
+		private static readonly string set1v9_0 =
+			  "0471076057830FB99202291177FBFE5D"
+			+ "38C888944DF8917CAB82788B91B53D1C"
+			+ "FB06D07A304B18BB763F888A61BB6B75"
+			+ "5CD58BEC9C4CFB7569CB91862E79C459";
+
+		private static readonly string set1v9_192 =
+			  "D1D7E97556426E6CFC21312AE3811425"
+			+ "9E5A6FB10DACBD88E4354B0472556935"
+			+ "2B6DA5ACAFACD5E266F9575C2ED8E6F2"
+			+ "EFE4B4D36114C3A623DD49F4794F865B";
+
+		private static readonly string set1v9_256 =
+			  "AF06FAA82C73291231E1BD916A773DE1"
+			+ "52FD2126C40A10C3A6EB40F22834B8CC"
+			+ "68BD5C6DBD7FC1EC8F34165C517C0B63"
+			+ "9DB0C60506D3606906B8463AA0D0EC2F";
+
+		private static readonly string set1v9_448 =
+			  "AB3216F1216379EFD5EC589510B8FD35"
+			+ "014D0AA0B613040BAE63ECAB90A9AF79"
+			+ "661F8DA2F853A5204B0F8E72E9D9EB4D"
+			+ "BA5A4690E73A4D25F61EE7295215140C";
+
+		private static readonly string set6v0_0 =
+			  "F5FAD53F79F9DF58C4AEA0D0ED9A9601"
+			+ "F278112CA7180D565B420A48019670EA"
+			+ "F24CE493A86263F677B46ACE1924773D"
+			+ "2BB25571E1AA8593758FC382B1280B71";
+
+		private static readonly string set6v0_65472 =
+			  "B70C50139C63332EF6E77AC54338A407"
+			+ "9B82BEC9F9A403DFEA821B83F7860791"
+			+ "650EF1B2489D0590B1DE772EEDA4E3BC"
+			+ "D60FA7CE9CD623D9D2FD5758B8653E70";
+
+		private static readonly string set6v0_65536 =
+			  "81582C65D7562B80AEC2F1A673A9D01C"
+			+ "9F892A23D4919F6AB47B9154E08E699B"
+			+ "4117D7C666477B60F8391481682F5D95"
+			+ "D96623DBC489D88DAA6956B9F0646B6E";
+
+		private static readonly string set6v1_0 =
+			  "3944F6DC9F85B128083879FDF190F7DE"
+			+ "E4053A07BC09896D51D0690BD4DA4AC1"
+			+ "062F1E47D3D0716F80A9B4D85E6D6085"
+			+ "EE06947601C85F1A27A2F76E45A6AA87";
+
+		private static readonly string set6v1_65472 =
+			  "36E03B4B54B0B2E04D069E690082C8C5"
+			+ "92DF56E633F5D8C7682A02A65ECD1371"
+			+ "8CA4352AACCB0DA20ED6BBBA62E177F2"
+			+ "10E3560E63BB822C4158CAA806A88C82";
+
+		private static readonly string set6v1_65536 =
+			  "1B779E7A917C8C26039FFB23CF0EF8E0"
+			+ "8A1A13B43ACDD9402CF5DF38501098DF"
+			+ "C945A6CC69A6A17367BC03431A86B3ED"
+			+ "04B0245B56379BF997E25800AD837D7D";
+
+		// Salsa20/12
+
+		private static readonly string salsa12_set1v0_0 = 
+			"FC207DBFC76C5E1774961E7A5AAD0906"
+			+ "9B2225AC1CE0FE7A0CE77003E7E5BDF8"
+			+ "B31AF821000813E6C56B8C1771D6EE70"
+			+ "39B2FBD0A68E8AD70A3944B677937897";
+
+		private static readonly string salsa12_set1v0_192 = 
+			"4B62A4881FA1AF9560586510D5527ED4"
+			+ "8A51ECAFA4DECEEBBDDC10E9918D44AB"
+			+ "26B10C0A31ED242F146C72940C6E9C37"
+			+ "53F641DA84E9F68B4F9E76B6C48CA5AC";
+
+		private static readonly string salsa12_set1v0_256 = 
+			"F52383D9DEFB20810325F7AEC9EADE34"
+			+ "D9D883FEE37E05F74BF40875B2D0BE79"
+			+ "ED8886E5BFF556CEA8D1D9E86B1F68A9"
+			+ "64598C34F177F8163E271B8D2FEB5996";
+
+		private static readonly string salsa12_set1v0_448 =
+			"A52ED8C37014B10EC0AA8E05B5CEEE12"
+			+ "3A1017557FB3B15C53E6C5EA8300BF74"
+			+ "264A73B5315DC821AD2CAB0F3BB2F152"
+			+ "BDAEA3AEE97BA04B8E72A7B40DCC6BA4";
+
+		// Salsa20/8
+
+		private static readonly string salsa8_set1v0_0 =
+			"A9C9F888AB552A2D1BBFF9F36BEBEB33"
+			+ "7A8B4B107C75B63BAE26CB9A235BBA9D"
+			+ "784F38BEFC3ADF4CD3E266687EA7B9F0"
+			+ "9BA650AE81EAC6063AE31FF12218DDC5";
+
+		private static readonly string salsa8_set1v0_192 =
+			"BB5B6BB2CC8B8A0222DCCC1753ED4AEB"
+			+ "23377ACCBD5D4C0B69A8A03BB115EF71"
+			+ "871BC10559080ACA7C68F0DEF32A80DD"
+			+ "BAF497259BB76A3853A7183B51CC4B9F";
+
+		private static readonly string salsa8_set1v0_256 =
+			"4436CDC0BE39559F5E5A6B79FBDB2CAE"
+			+ "4782910F27FFC2391E05CFC78D601AD8"
+			+ "CD7D87B074169361D997D1BED9729C0D"
+			+ "EB23418E0646B7997C06AA84E7640CE3";
+
+		private static readonly string salsa8_set1v0_448 =
+			"BEE85903BEA506B05FC04795836FAAAC"
+			+ "7F93F785D473EB762576D96B4A65FFE4"
+			+ "63B34AAE696777FC6351B67C3753B89B"
+			+ "A6B197BD655D1D9CA86E067F4D770220";
+
+		public override string Name
+		{
+			get { return "Salsa20"; }
+		}
+
+		public override void PerformTest()
+		{
+			salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+					set1v0_0, set1v0_192,  set1v0_256,  set1v0_448);
+			salsa20Test1(20, new ParametersWithIV(new KeyParameter(Hex.Decode("00400000000000000000000000000000")), Hex.Decode("0000000000000000")),
+					set1v9_0, set1v9_192,  set1v9_256,  set1v9_448);
+			salsa20Test1(12, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+		             salsa12_set1v0_0, salsa12_set1v0_192,  salsa12_set1v0_256,  salsa12_set1v0_448);
+			salsa20Test1(8, new ParametersWithIV(new KeyParameter(Hex.Decode("80000000000000000000000000000000")), Hex.Decode("0000000000000000")),
+		             salsa8_set1v0_0, salsa8_set1v0_192,  salsa8_set1v0_256,  salsa8_set1v0_448);
+			salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.Decode("0053A6F94C9FF24598EB3E91E4378ADD3083D6297CCF2275C81B6EC11467BA0D")), Hex.Decode("0D74DB42A91077DE")),
+					set6v0_0, set6v0_65472, set6v0_65536);
+			salsa20Test2(new ParametersWithIV(new KeyParameter(Hex.Decode("0558ABFE51A4F74A9DF04396E93C8FE23588DB2E81D4277ACD2073C6196CBF12")), Hex.Decode("167DE44BB21980E7")),
+					set6v1_0, set6v1_65472, set6v1_65536);
+			reinitBug();
+		}
+
+		private void salsa20Test1(
+			int rounds,
+			ICipherParameters	parameters,
+			string				v0,
+			string				v192,
+			string				v256,
+			string				v448)
+		{
+			IStreamCipher salsa = new Salsa20Engine(rounds);
+			byte[]       buf = new byte[64];
+
+			salsa.Init(true, parameters);
+
+			for (int i = 0; i != 7; i++)
+			{
+				salsa.ProcessBytes(zeroes, 0, 64, buf, 0);
+				switch (i)
+				{
+				case 0:
+					if (!AreEqual(buf, Hex.Decode(v0)))
+					{
+						mismatch("v0/" + rounds, v0, buf);
+					}
+					break;
+				case 3:
+					if (!AreEqual(buf, Hex.Decode(v192)))
+					{
+						mismatch("v192/" + rounds, v192, buf);
+					}
+					break;
+				case 4:
+					if (!AreEqual(buf, Hex.Decode(v256)))
+					{
+						mismatch("v256/" + rounds, v256, buf);
+					}
+					break;
+				default:
+					// ignore
+					break;
+				}
+			}
+
+			for (int i = 0; i != 64; i++)
+			{
+				buf[i] = salsa.ReturnByte(zeroes[i]);
+			}
+
+			if (!AreEqual(buf, Hex.Decode(v448)))
+			{
+				mismatch("v448", v448, buf);
+			}       
+		}
+
+		private void salsa20Test2(
+			ICipherParameters	parameters,
+			string				v0,
+			string				v65472,
+			string				v65536)
+		{
+			IStreamCipher salsa = new Salsa20Engine();
+			byte[]       buf = new byte[64];
+
+			salsa.Init(true, parameters);
+
+			for (int i = 0; i != 1025; i++)
+			{
+				salsa.ProcessBytes(zeroes, 0, 64, buf, 0);
+				switch (i)
+				{
+				case 0:
+					if (!AreEqual(buf, Hex.Decode(v0)))
+					{
+						mismatch("v0", v0, buf);
+					}
+					break;
+				case 1023:
+					if (!AreEqual(buf, Hex.Decode(v65472)))
+					{
+						mismatch("v65472", v65472, buf);
+					}
+					break;
+				case 1024:
+					if (!AreEqual(buf, Hex.Decode(v65536)))
+					{
+						mismatch("v65536", v65536, buf);
+					}
+					break;
+				default:
+					// ignore
+					break;
+				}
+			}
+		}
+
+		private void mismatch(
+			string	name,
+			string	expected,
+			byte[]	found)
+		{
+			Fail("mismatch on " + name, expected, Hex.ToHexString(found));
+		}
+
+		private void reinitBug()
+		{
+			KeyParameter key = new KeyParameter(Hex.Decode("80000000000000000000000000000000"));
+			ParametersWithIV parameters = new ParametersWithIV(key, Hex.Decode("0000000000000000"));
+
+			IStreamCipher salsa = new Salsa20Engine();
+
+			salsa.Init(true, parameters);
+
+			try
+			{
+				salsa.Init(true, key);
+				Fail("Salsa20 should throw exception if no IV in Init");
+			}
+			catch (ArgumentException)
+			{
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Salsa20Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SerpentTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SerpentTest.cs
new file mode 100644
index 0000000..2467797
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SerpentTest.cs
@@ -0,0 +1,119 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class SerpentTest: CipherTest
+    {
+        static SimpleTest[]  tests =
+        {
+            new BlockCipherVectorTest(0, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+                "00000000000000000000000000000000", "8910494504181950f98dd998a82b6749"),
+            new BlockCipherVectorTest(1, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+                "80000000000000000000000000000000", "10b5ffb720b8cb9002a1142b0ba2e94a"),
+            new BlockCipherVectorTest(2, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+                "00000000008000000000000000000000", "4f057a42d8d5bd9746e434680ddcd5e5"),
+            new BlockCipherVectorTest(3, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+                "00000000000000000000400000000000", "99407bf8582ef12550886ef5b6f169b9"),
+            new BlockCipherVectorTest(4, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+                "40000000000000000000000000000000", "d522a3b8d6d89d4d2a124fdd88f36896"),
+            new BlockCipherVectorTest(5, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+                "00000000000200000000000000000000", "189b8ec3470085b3da97e82ca8964e32"),
+            new BlockCipherVectorTest(6, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("000000000000000000000000000000000000000000000000")),
+                "00000000000000000000008000000000", "f77d868cf760b9143a89809510ccb099"),
+            new BlockCipherVectorTest(7, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+                "08000000000000000000000000000000", "d43b7b981b829342fce0e3ec6f5f4c82"),
+            new BlockCipherVectorTest(8, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+                "00000000000000000100000000000000", "0bf30e1a0c33ccf6d5293177886912a7"),
+            new BlockCipherVectorTest(9, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000000000000")),
+                "00000000000000000000000000000001", "6a7f3b805d2ddcba49b89770ade5e507"),
+            new BlockCipherVectorTest(10, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("80000000000000000000000000000000")),
+                "00000000000000000000000000000000", "49afbfad9d5a34052cd8ffa5986bd2dd"),
+            new BlockCipherVectorTest(11, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("000000000000000000000000004000000000000000000000")),
+                "00000000000000000000000000000000", "ba8829b1de058c4b48615d851fc74f17"),
+            new BlockCipherVectorTest(12, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("0000000000000000000000000000000000000000000000000000000100000000")),
+                "00000000000000000000000000000000", "89f64377bf1e8a46c8247044e8056a98"),
+/*
+            new BlockCipherMonteCarloTest(13, 10000, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")),
+                "7a4f7db38c52a8b711b778a38d203b6b", "003380e19f10065740394f48e2fe80b7"),
+*/
+            new BlockCipherMonteCarloTest(13, 100, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("47f5f881daab9b67b43bd1342e339c19")),
+                "7a4f7db38c52a8b711b778a38d203b6b", "4db75303d815c2f7cc6ca935d1c5a046"),
+/*
+            new BlockCipherMonteCarloTest(14, 10000, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")),
+                "70a05e12f74589009692a337f53ff614", "afb5425426906db26b70bdf842ac5400"),
+*/
+            new BlockCipherMonteCarloTest(14, 100, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("31fba879ebc5e80df35e6fa33eaf92d6")),
+                "70a05e12f74589009692a337f53ff614", "fc53a50f4d3bc9836001893d2f41742d"),
+/*
+            new BlockCipherMonteCarloTest(15, 10000, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
+                "9cc523d034a93740a0aa4e2054bb34d8", "1949d506ada7de1f1344986e8ea049b2"),
+*/
+            new BlockCipherMonteCarloTest(15, 100, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("bde6dd392307984695aee80e574f9977caae9aa78eda53e8")),
+                "9cc523d034a93740a0aa4e2054bb34d8", "77117e6a9e80f40b2a36b7d755573c2d"),
+/*
+            new BlockCipherMonteCarloTest(16, 10000, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
+                "ee1a61106fae2d381d686cbf854bab65", "e57f45559027cb1f2ed9603d814e1c34"),
+*/
+            new BlockCipherMonteCarloTest(16, 100, new SerpentEngine(),
+                new KeyParameter(Hex.Decode("60f6f8ad4290699dc50921a1bbcca92da914e7d9cf01a9317c79c0af8f2487a1")),
+                "ee1a61106fae2d381d686cbf854bab65", "dcd7f13ea0dcdfd0139d1a42e2ffb84b")
+        };
+
+		public SerpentTest()
+			: base(tests, new SerpentEngine(), new KeyParameter(new byte[32]))
+		{
+		}
+
+		public override string Name
+        {
+			get { return "Serpent"; }
+        }
+
+		public static void Main(
+	        string[] args)
+        {
+            ITest test = new SerpentTest();
+            ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/ShortenedDigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/ShortenedDigestTest.cs
new file mode 100644
index 0000000..4956b5b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/ShortenedDigestTest.cs
@@ -0,0 +1,98 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Paddings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class ShortenedDigestTest : SimpleTest
+	{
+		public override void PerformTest()
+		{
+			IDigest  d = new Sha1Digest();
+			ShortenedDigest sd = new ShortenedDigest(new Sha1Digest(), 10);
+
+			if (sd.GetDigestSize() != 10)
+			{
+				Fail("size check wrong for SHA-1");
+			}
+
+			if (sd.GetByteLength() != d.GetByteLength())
+			{
+				Fail("byte length check wrong for SHA-1");
+			}
+
+			//
+			// check output fits
+			//
+			sd.DoFinal(new byte[10], 0);
+
+			d = new Sha512Digest();
+			sd = new ShortenedDigest(new Sha512Digest(), 20);
+
+			if (sd.GetDigestSize() != 20)
+			{
+				Fail("size check wrong for SHA-512");
+			}
+
+			if (sd.GetByteLength() != d.GetByteLength())
+			{
+				Fail("byte length check wrong for SHA-512");
+			}
+
+			//
+			// check output fits
+			//
+			sd.DoFinal(new byte[20], 0);
+
+			try
+			{
+				new ShortenedDigest(null, 20);
+
+				Fail("null parameter not caught");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+
+			try
+			{
+				new ShortenedDigest(new Sha1Digest(), 50);
+
+				Fail("short digest not caught");
+			}
+			catch (ArgumentException)
+			{
+				// expected
+			}
+		}
+
+		public override string Name
+		{
+			get { return "ShortenedDigest"; }
+		}
+
+		public static void Main(
+			string[]    args)
+		{
+			RunTest(new ShortenedDigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SipHashTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SipHashTest.cs
new file mode 100644
index 0000000..82dfce8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SipHashTest.cs
@@ -0,0 +1,156 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Utilities;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /// <summary>
+    /// SipHash test values from "SipHash: a fast short-input PRF", by Jean-Philippe
+    /// Aumasson and Daniel J. Bernstein (https://131002.net/siphash/siphash.pdf), Appendix A.
+    /// </summary>
+    [TestFixture]
+    public class SipHashTest
+        : SimpleTest
+    {
+        private const int UPDATE_BYTES = 0;
+        private const int UPDATE_FULL = 1;
+        private const int UPDATE_MIX = 2;
+
+        public override string Name
+        {
+            get { return "SipHash"; }
+        }
+
+        public override void PerformTest()
+        {
+            byte[] key = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+            byte[] input = Hex.Decode("000102030405060708090a0b0c0d0e");
+
+            RunMac(key, input, UPDATE_BYTES);
+            RunMac(key, input, UPDATE_FULL);
+            RunMac(key, input, UPDATE_MIX);
+
+            SecureRandom random = new SecureRandom();
+            for (int i = 0; i < 100; ++i)
+            {
+                RandomTest(random);
+            }
+        }
+
+        private void RunMac(byte[] key, byte[] input, int updateType)
+        {
+            long expected = unchecked((long)0xa129ca6149be45e5);
+
+            SipHash mac = new SipHash();
+            mac.Init(new KeyParameter(key));
+
+            UpdateMac(mac, input, updateType);
+
+            long result = mac.DoFinal();
+            if (expected != result)
+            {
+                Fail("Result does not match expected value for DoFinal()");
+            }
+
+            // NOTE: Little-endian representation of 0xa129ca6149be45e5
+            byte[] expectedBytes = Hex.Decode("e545be4961ca29a1");
+
+            UpdateMac(mac, input, updateType);
+
+            byte[] output = new byte[mac.GetMacSize()];
+            int len = mac.DoFinal(output, 0);
+            if (len != output.Length)
+            {
+                Fail("Result length does not equal GetMacSize() for DoFinal(byte[],int)");
+            }
+            if (!AreEqual(expectedBytes, output))
+            {
+                Fail("Result does not match expected value for DoFinal(byte[],int)");
+            }
+        }
+
+        private void RandomTest(SecureRandom random)
+        {
+            byte[] key = new byte[16];
+            random.NextBytes(key);
+
+            int length = 1 + random.Next(1024);
+            byte[] input = new byte[length];
+            random.NextBytes(input);
+
+            SipHash mac = new SipHash();
+            mac.Init(new KeyParameter(key));
+
+            UpdateMac(mac, input, UPDATE_BYTES);
+            long result1 = mac.DoFinal();
+
+            UpdateMac(mac, input, UPDATE_FULL);
+            long result2 = mac.DoFinal();
+
+            UpdateMac(mac, input, UPDATE_MIX);
+            long result3 = mac.DoFinal();
+
+            if (result1 != result2 || result1 != result3)
+            {
+                Fail("Inconsistent results in random test");
+            }
+        }
+
+        private void UpdateMac(SipHash mac, byte[] input, int updateType)
+        {
+            switch (updateType)
+            {
+            case UPDATE_BYTES:
+            {
+                for (int i = 0; i < input.Length; ++i)
+                {
+                    mac.Update(input[i]);
+                }
+                break;
+            }
+            case UPDATE_FULL:
+            {
+                mac.BlockUpdate(input, 0, input.Length);
+                break;
+            }
+            case UPDATE_MIX:
+            {
+                int step = System.Math.Max(1, input.Length / 3);
+                int pos = 0;
+                while (pos < input.Length)
+                {
+                    mac.Update(input[pos++]);
+                    int len = System.Math.Min(input.Length - pos, step);
+                    mac.BlockUpdate(input, pos, len);
+                    pos += len;
+                }
+                break;
+            }
+            default:
+                throw new InvalidOperationException();
+            }
+        }
+
+        public static void Main(string[] args)
+        {
+            RunTest(new SipHashTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinDigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinDigestTest.cs
new file mode 100644
index 0000000..b6f1c54
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinDigestTest.cs
@@ -0,0 +1,303 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	[TestFixture]
+	public class SkeinDigestTest
+		: SimpleTest
+	{
+		private class Case
+		{
+			private byte[] message;
+			private byte[] digest;
+			private int blockSize;
+			private int outputSize;
+
+			public Case(int blockSize, int outputSize, string message, string digest)
+			{
+				this.blockSize = blockSize;
+				this.outputSize = outputSize;
+				this.message = Hex.Decode(message);
+				this.digest = Hex.Decode(digest);
+			}
+
+			public int getOutputSize()
+			{
+				return outputSize;
+			}
+
+			public int getBlockSize()
+			{
+				return blockSize;
+			}
+
+			public byte[] getMessage()
+			{
+				return message;
+			}
+
+			public byte[] getDigest()
+			{
+				return digest;
+			}
+
+		}
+
+		// Test cases from skein_golden_kat.txt and skein_golden_kat_short.txt in Skein 1.3 NIST CD
+		private static readonly Case[] TEST_CASES = {
+			new Case(256, 256, "", "c8877087da56e072870daa843f176e9453115929094c3a40c463a196c29bf7ba"),
+			new Case(256, 256, "fb", "088eb23cc2bccfb8171aa64e966d4af937325167dfcd170700ffd21f8a4cbdac"),
+			new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+			         "5c3002ff57a627089ea2f97a5000d5678416389019e80e45a3bbcab118315d26"),
+			new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a129233",
+			         "640c894a4bba6574c83e920ddf7dd2982fc634881bbbcb9d774eae0a285e89ce"),
+			new Case(256, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "0cd491b7715704c3a15a45a1ca8d93f8f646d3a1"),
+			new Case(256, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "afd1e2d0f5b6cd4e1f8b3935fa2497d27ee97e72060adac099543487"),
+			new Case(256, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "4de6fe2bfdaa3717a4261030ef0e044ced9225d066354610842a24a3eafd1dcf"),
+			new Case(256, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "954620fb31e8b782a2794c6542827026fe069d715df04261629fcbe81d7d529b"
+			         + "95ba021fa4239fb00afaa75f5fd8e78b"),
+			new Case(256, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "51347e27c7eabba514959f899a6715ef6ad5cf01c23170590e6a8af399470bf9"
+			         + "0ea7409960a708c1dbaa90e86389df254abc763639bb8cdf7fb663b29d9557c3"),
+			new Case(256, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "6c9b6facbaf116b538aa655e0be0168084aa9f1be445f7e06714585e5999a6c9"
+			         + "84fffa9d41a316028692d4aad18f573fbf27cf78e84de26da1928382b023987d"
+			         + "cfe002b6201ea33713c54a8a5d9eb346f0365e04330d2faaf7bc8aba92a5d7fb"
+			         + "6345c6fb26750bce65ab2045c233627679ac6e9acb33602e26fe3526063ecc8b"),
+
+			new Case(512, 512, "", "bc5b4c50925519c290cc634277ae3d6257212395cba733bbad37a4af0fa06af4"
+			         + "1fca7903d06564fea7a2d3730dbdb80c1f85562dfcc070334ea4d1d9e72cba7a"),
+			new Case(512, 512, "fb", "c49e03d50b4b2cc46bd3b7ef7014c8a45b016399fd1714467b7596c86de98240"
+			         + "e35bf7f9772b7d65465cd4cffab14e6bc154c54fc67b8bc340abf08eff572b9e"),
+			new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+			         "abefb179d52f68f86941acbbe014cc67ec66ad78b7ba9508eb1400ee2cbdb06f"
+			         + "9fe7c2a260a0272d0d80e8ef5e8737c0c6a5f1c02ceb00fb2746f664b85fcef5"),
+			new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a129233",
+			         "5c5b7956f9d973c0989aa40a71aa9c48a65af2757590e9a758343c7e23ea2df4"
+			         + "057ce0b49f9514987feff97f648e1dd065926e2c371a0211ca977c213f14149f"),
+			new Case(512, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "ef03079d61b57c6047e15fa2b35b46fa24279539"),
+			new Case(512, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "d9e3219b214e15246a2038f76a573e018ef69b385b3bd0576b558231"),
+			new Case(512, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "809dd3f763a11af90912bbb92bc0d94361cbadab10142992000c88b4ceb88648"),
+			new Case(512, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "825f5cbd5da8807a7b4d3e7bd9cd089ca3a256bcc064cd73a9355bf3ae67f2bf"
+			         + "93ac7074b3b19907a0665ba3a878b262"),
+			new Case(512, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "1a0d5abf4432e7c612d658f8dcfa35b0d1ab68b8d6bd4dd115c23cc57b5c5bcd"
+			         + "de9bff0ece4208596e499f211bc07594d0cb6f3c12b0e110174b2a9b4b2cb6a9"),
+
+			new Case(1024, 1024, "", "0fff9563bb3279289227ac77d319b6fff8d7e9f09da1247b72a0a265cd6d2a62"
+			         + "645ad547ed8193db48cff847c06494a03f55666d3b47eb4c20456c9373c86297"
+			         + "d630d5578ebd34cb40991578f9f52b18003efa35d3da6553ff35db91b81ab890"
+			         + "bec1b189b7f52cb2a783ebb7d823d725b0b4a71f6824e88f68f982eefc6d19c6"),
+			new Case(1024, 1024, "fb", "6426bdc57b2771a6ef1b0dd39f8096a9a07554565743ac3de851d28258fcff22"
+			         + "9993e11c4e6bebc8b6ecb0ad1b140276081aa390ec3875960336119427827473"
+			         + "4770671b79f076771e2cfdaaf5adc9b10cbae43d8e6cd2b1c1f5d6c82dc96618"
+			         + "00ddc476f25865b8748253173187d81da971c027d91d32fb390301c2110d2db2"),
+			new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8",
+			         "140e93726ab0b0467c0b8a834ad8cda4d1769d273661902b70db0dcb5ee692ac"
+			         + "b3f852d03b11f857850f2428432811309c1dcbe5724f00267ea3667e89fadb4e"
+			         + "4911da6b0ba8a7eddf87c1c67152ef0f07b7fead3557318478bdef5ad1e5926d"
+			         + "7071fdd4bfa5076d4b3253f8de479ebdf5357676f1641b2f097e9b785e9e528e"),
+			new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a129233",
+			         "31105e1ef042c30b95b16e0f6e6a1a19172bb7d54a0597dd0c711194888efe1d"
+			         + "bce82d47416df9577ca387219f06e45cd10964ff36f6711edbbea0e9595b0f66"
+			         + "f72b755d70a46857e0aec98561a743d49370d8e572e212811273125f66cc30bf"
+			         + "117d3221894c48012bf6e2219de91e064b01523517420a1e00f71c4cc04bab62"),
+			new Case(1024, 160, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "2e6a4cbf2ef05ea9c24b93e8d1de732ddf2739eb"),
+			new Case(1024, 224, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "1d6de19f37f7a3c265440eecb4b9fbd3300bb5ac60895cfc0d4d3c72"),
+			new Case(1024, 256, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "986a4d472b123e8148731a8eac9db23325f0058c4ccbc44a5bb6fe3a8db672d7"),
+			new Case(1024, 384, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "9c3d0648c11f31c18395d5e6c8ebd73f43d189843fc45235e2c35e345e12d62b"
+			         + "c21a41f65896ddc6a04969654c2e2ce9"),
+			new Case(1024, 512, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "5d0416f49c2d08dfd40a1446169dc6a1d516e23b8b853be4933513051de8d5c2"
+			         + "6baccffb08d3b16516ba3c6ccf3e9a6c78fff6ef955f2dbc56e1459a7cdba9a5"),
+			new Case(1024, 1024, "fbd17c26b61a82e12e125f0d459b96c91ab4837dff22b39b78439430cdfc5dc8"
+			         + "78bb393a1a5f79bef30995a85a12923339ba8ab7d8fc6dc5fec6f4ed22c122bb"
+			         + "e7eb61981892966de5cef576f71fc7a80d14dab2d0c03940b95b9fb3a727c66a"
+			         + "6e1ff0dc311b9aa21a3054484802154c1826c2a27a0914152aeb76f1168d4410",
+			         "96ca81f586c825d0360aef5acaec49ad55289e1797072eee198b64f349ce65b6"
+			         + "e6ed804fe38f05135fe769cc56240ddda5098f620865ce4a4278c77fa2ec6bc3"
+			         + "1c0f354ca78c7ca81665bfcc5dc54258c3b8310ed421d9157f36c093814d9b25"
+			         + "103d83e0ddd89c52d0050e13a64c6140e6388431961685734b1f138fe2243086"),
+
+		};
+
+		public override string Name
+		{
+			get { return "SkeinDigest"; }
+		}
+
+		public override void PerformTest()
+		{
+			for (int i = 0; i < TEST_CASES.Length; i++)
+			{
+				Case test = TEST_CASES[i];
+				runTest(test);
+			}
+		}
+
+		private void runTest(Case dc)
+		{
+			SkeinDigest digest = new SkeinDigest(dc.getBlockSize(), dc.getOutputSize());
+
+			byte[] message = dc.getMessage();
+			digest.BlockUpdate(message, 0, message.Length);
+
+			byte[] output = new byte[digest.GetDigestSize()];
+			digest.DoFinal(output, 0);
+
+			if (!AreEqual(output, dc.getDigest()))
+			{
+				Fail(digest.AlgorithmName + " message mismatch.\n Message " + Hex.ToHexString(dc.getMessage()),
+				     Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			}
+
+			// Clone test
+			digest.BlockUpdate(message, 0, message.Length / 2);
+
+			// clone the Digest
+			IDigest d = new SkeinDigest(digest);
+
+			digest.BlockUpdate(message, message.Length / 2, message.Length - message.Length / 2);
+			digest.DoFinal(output, 0);
+
+			if (!AreEqual(dc.getDigest(), output))
+			{
+				Fail("failing clone vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			}
+
+			d.BlockUpdate(message, message.Length / 2, message.Length - message.Length / 2);
+			d.DoFinal(output, 0);
+
+			if (!AreEqual(dc.getDigest(), output))
+			{
+				Fail("failing second clone vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			}
+
+			//	        //
+			//	        // memo test
+			//	        //
+			//	        Memoable m = (Memoable)digest;
+			//
+			//	        digest.Update(message, 0, message.Length / 2);
+			//
+			//	        // copy the Digest
+			//	        Memoable copy1 = m.copy();
+			//	        Memoable copy2 = copy1.copy();
+			//
+			//	        digest.Update(message, message.Length / 2, message.Length - message.Length / 2);
+			//	        digest.DoFinal(output, 0);
+			//
+			//	        if (!AreEqual(dc.getDigest(), output))
+			//	        {
+			//				Fail("failing memo vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			//	        }
+			//
+			//	        m.reset(copy1);
+			//
+			//	        digest.Update(message, message.Length / 2, message.Length - message.Length / 2);
+			//	        digest.DoFinal(output, 0);
+			//
+			//	        if (!AreEqual(dc.getDigest(), output))
+			//	        {
+			//				fail("failing memo reset vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			//	        }
+			//
+			//	        IDigest md = (IDigest)copy2;
+			//
+			//	        md.Update(message, message.Length / 2, message.Length - message.Length / 2);
+			//	        md.DoFinal(output, 0);
+			//
+			//	        if (!AreEqual(dc.getDigest(), output))
+			//	        {
+			//				Fail("failing memo copy vector test", Hex.ToHexString(dc.getDigest()), Hex.ToHexString(output));
+			//	        }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SkeinDigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinMacTest.cs
new file mode 100644
index 0000000..852c3b2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SkeinMacTest.cs
@@ -0,0 +1,174 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	[TestFixture]
+	public class SkeinMacTest
+		: SimpleTest
+	{
+		private class Case
+		{
+			private byte[] message;
+			private byte[] digest;
+			private byte[] key;
+			private int blockSize;
+			private int outputSize;
+
+			public Case(int blockSize, int outputSize, String message, String key, String digest)
+			{
+				this.blockSize = blockSize;
+				this.outputSize = outputSize;
+				this.message = Hex.Decode(message);
+				this.key = Hex.Decode(key);
+				this.digest = Hex.Decode(digest);
+			}
+
+			public int getOutputSize()
+			{
+				return outputSize;
+			}
+
+			public int getBlockSize()
+			{
+				return blockSize;
+			}
+
+			public byte[] getMessage()
+			{
+				return message;
+			}
+
+			public byte[] getKey()
+			{
+				return key;
+			}
+
+			public byte[] getDigest()
+			{
+				return digest;
+			}
+
+			public override string ToString()
+			{
+				return String.Format("new Case({0}, {1}, \"{2}\", \"{3}\", \"{4}\"),", blockSize, outputSize,
+				                     Hex.ToHexString(message), Hex.ToHexString(key), Hex.ToHexString(digest));
+			}
+
+		}
+
+		// Test cases from skein_golden_kat.txt in Skein 1.3 NIST CD
+		// Excludes empty '(none)' key 'random+MAC' tests, which are in effect digest 
+		private static readonly Case[] TEST_CASES = {
+			new Case(256, 256, "", "cb41f1706cde09651203c2d0efbaddf8", "886e4efefc15f06aa298963971d7a25398fffe5681c84db39bd00851f64ae29d"),
+			new Case(256, 256, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "979422a94e3afaa46664124d4e5e8b9422b1d8baf11c6ae6725992ac72a112ca"),
+			new Case(256, 256, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "1d658372cbea2f9928493cc47599d6f4ad8ce33536bedfa20b739f07516519d5"),
+			new Case(256, 256, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "41ef6b0f0fad81c040284f3b1a91e9c44e4c26a6d7207f3aac4362856ef12aca"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "ca8208119b9e4e4057631ab31015cfd256f6763a0a34381633d97f640899b84f"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "9e9980fcc16ee082cf164a5147d0e0692aeffe3dcb8d620e2bb542091162e2e9"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "c353a316558ec34f8245dd2f9c2c4961fbc7decc3b69053c103e4b8aaaf20394"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf8", "b1b8c18188e69a6ecae0b6018e6b638c6a91e6de6881e32a60858468c17b520d"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "1dfd2515a412e78852cd81a7f2167711b4ca19b2891c2ea36ba94f8451944793"),
+			new Case(256, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "a097340709b443ed2c0a921f5dcefef3ead65c4f0bcd5f13da54d7ed"),
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "ac1b4fab6561c92d0c487e082daec53e0db4f505e08bf51cae4fd5375e37fc04"),
+			new Case(256, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "96e6cebb23573d0a70ce36a67aa05d2403148093f25c695e1254887cc97f9771d2518413af4286bf2a06b61a53f7fcec"),
+			new Case(256, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "0e95e597e71d6350f20b99c4179f54f43a4722705c06ba765a82cb0a314fe2fe87ef8090063 [...]
+			new Case(256, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf8", "064abd4896f460b1953f5a357e7f7c5256e29cdb62b8740d0b52295cfa2ef4c7a2"),
+			new Case(256, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "edf220e43e048603bd16197d59b673b9974de5b8bcf7cb1558a4799f6fd3743eb5fb400cd6129afc0c60e7b741b7e5806f0e0b93eb8429fbc7efa222175a9c80fd"),
+			new Case(256, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e92", "f3f59fb07399c7b73aae02a8590883cb2fdfde75c55654e71846522301bde48d267169adcc559e038e8c2f28faa552b550d51874055384adea93c036c71a1f0af0c7bcc3bc [...]
+			new Case(256, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "80eb80d9b8836b32fa576fc84ba08edfbdfd6979123d61914e610a70a372b37f560a109094 [...]
+			new Case(256, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa613 [...]
+			new Case(512, 512, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "9bd43d2a2fcfa92becb9f69faab3936978f1b865b7e44338fc9c8f16aba949ba340291082834a1fc5aa81649e13d50cd98641a1d0883062bfe2c16d1faa7e3aa"),
+			new Case(512, 512, "d3", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "f0c0a10f031c8fc69cfabcd54154c318b5d6cd95d06b12cf20264402492211ee010d5cecc2dc37fd772afac0596b2bf71e6020ef2dee7c860628b6e643ed9ff6"),
+			new Case(512, 512, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "0c1f1921253dd8e5c2d4c5f4099f851042d91147892705829161f5fc64d89785226eb6e187068493ee4c78a4b7c0f55a8cbbb1a5982c2daf638fc6a74b16b0d7"),
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "478d7b6c0cc6e35d9ebbdedf39128e5a36585db6222891692d1747d401de34ce3db6fcbab6c968b7f2620f4a844a2903b547775579993736d2493a75ff6752a1"),
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "13c170bac1de35e5fb843f65fabecf214a54a6e0458a4ff6ea5df91915468f4efcd371effa8965a9e82c5388d84730490dcf3976af157b8baf550655a5a6ab78"),
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc235", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "a947812529a72fd3b8967ec391b298bee891babc8487a1ec4ea3d88f6b2b5be09ac6a780f30f8e8c3bbb4f18bc302a28f3e87d170ba0f858a8fefe3487478cca"),
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "7690ba61f10e0bba312980b0212e6a9a51b0e9aadfde7ca535754a706e042335b29172aae29 [...]
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "d10e3ba81855ac087fbf5a3bc1f99b27d05f98ba22441138026225d34a418b93fd9e8dfaf5120757451adabe050d0eb59d271b0fe1bbf04badbcf9ba25a8791b"),
+			new Case(512, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "5670b226156570dff3efe16661ab86eb24982cdf"),
+			new Case(512, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a [...]
+			new Case(512, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "dfbf5c1319a1d9d70efb2f1600fbcf694f935907f31d24a16d6cd2fb2d7855a769681766c0a29da778eed346cd1d740f"),
+			new Case(512, 512, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "04d8cddb0ad931d54d195899a094684344e902286037272890bce98a41813edc37a3cee190a69 [...]
+			new Case(512, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c193", "08fca368b3b14ac406676adf37ac9be2dbb8704e694055a0c6331184d4f0070098f23f0963 [...]
+			new Case(512, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a [...]
+			new Case(512, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e", "acc2e03f07f33e9820a6038421089429adcd6a7a83f733beec048c05bf37531a170a5537fcb565c348a70a83217f8be768ff6f95fd2b3d89cb7d8a3dc849505e3710eb4e65a8 [...]
+			new Case(512, 2056, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "9f3e082223c43090a4a3ffbdcd469cbabfe0c1399d1edf45a5dfc18f4db5428928a76e979b8d [...]
+			new Case(1024, 1024, "", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "bcf37b3459c88959d6b6b58b2bfe142cef60c6f4ec56b0702480d7893a2b0595aa354e87102a788b61996b9cbc1eade7dafbf6581135572c09666d844c90f066b800fc4f5fd1737644894ef7d588afc5c38f5d920bdbd3b738aea3a3267d161ed65284d1f57 [...]
+			new Case(1024, 1024, "d3090c72", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "df0596e5808835a3e304aa27923db05f61dac57c0696a1d19abf188e70aa9dbcc659e9510f7c9a37fbc025bd4e5ea293e78ed7838dd0b08864e8ad40ddb3a88031ebefc21572a89960d1916107a7da7ac0c067e34ec46a86a29ca63fa250bd398 [...]
+			new Case(1024, 1024, "d3090c72167517f7", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c015a4767032c0bb28f076b66485f51531c12e948f47dbc2cb904a4b75d1e8a6d931dab4a07e0a54d1bb5b55e602141746bd09fb15e8f01a8d74e9e63959cb37336bc1b896ec78da734c15e362db04368fbba280f20a043e0 [...]
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e59", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "0a1b960099fc9d653b0fd1f5b6b972fb366907b772cbce5a59b6171d7935506f70c212bd169d68c5cfd8618343611b7eb2e686ff1dc7c03a57e1a55ed10726848161eea903d53b58459be42d95df989c66c2eea4e51cde272c2d8be67bf3bca2aee633777eb8486781eaa060d0f538abd6c93dbd2d1bf66e6f50bfdcac3725a4"),
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c", "3e0cd7938d71c39ffbb08a6ba7995ade3ad140e2c0c45cdbafb099247e08e4c20b61c1f885ced5ed2f816680925034918236e5807f0eecf3f27e9cfca36675eb75873efa1 [...]
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdf", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc81463134", "7266752f7e9aa04bd7d8a1b16030677de6021301f6a62473c76bae2b98bbf8aad73bd00a4b5 [...]
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69a1626c6206b7252736f24253c9ee9b85eb852dfc814631346c042eb4187aa1c [...]
+			new Case(1024, 160, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "17c3c533b27d666da556ae586e641b7a3a0bcc45"),
+			new Case(1024, 224, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69 [...]
+			new Case(1024, 256, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69 [...]
+			new Case(1024, 384, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69 [...]
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1", "211ac479e9961141da3aac19d320a1dbbbfad55d2dce87e6a345fcd58e36827597378432b48 [...]
+			new Case(1024, 264, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69 [...]
+			new Case(1024, 520, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac69 [...]
+			new Case(1024, 1032, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed", "cb41f1706cde09651203c2d0efbaddf847a0d315cb2e53ff8bac41da0002672e920244c66e02d5f0dad3e94c42bb65f0d14157decf4105ef5609d5b0984457c1935df3061ff06e9f204192ba11e5bb2cac0430c1c370cb3d113fea5ec1021eb875e5946d7a96ac6 [...]
+			new Case(1024, 1024, "d3090c72167517f7c7ad82a70c2fd3f6443f608301591e598eadb195e8357135ba26fede2ee187417f816048d00fc23512737a2113709a77e4170c49a94b7fdff45ff579a72287743102e7766c35ca5abc5dfe2f63a1e726ce5fbd2926db03a2dd18b03fc1508a9aac45eb362440203a323e09edee6324ee2e37b4432c1867ed696e6c9db1e6abea026288954a9c2d5758d7c5db7c9e48aa3d21cae3d977a7c3926066aa393dbd538dd0c30da8916c8757f24c18488014668a2627163a37b261833dc2f8c3c56b1b2e0be21fd3fbdb507b2950b77a6cc02efb393e57419383a920767bca2c972107aa6 [...]
+
+		};
+
+		public override string Name
+		{
+			get { return "SkeinMac"; }
+		}
+
+		public override void PerformTest()
+		{
+			for (int i = 0; i < TEST_CASES.Length; i++)
+			{
+				Case test = TEST_CASES[i];
+				runTest(test);
+			}
+		}
+
+		private void runTest(Case dc)
+		{
+			IMac digest = new SkeinMac(dc.getBlockSize(), dc.getOutputSize());
+			digest.Init(new KeyParameter(dc.getKey()));
+
+			byte[] message = dc.getMessage();
+			digest.BlockUpdate(message, 0, message.Length);
+
+			byte[] output = new byte[digest.GetMacSize()];
+			digest.DoFinal(output, 0);
+
+			if (!AreEqual(output, dc.getDigest()))
+			{
+				Fail(digest.AlgorithmName + " message " + (dc.getMessage().Length * 8) + " mismatch.\n Message  " + Hex.ToHexString(dc.getMessage())
+				     + "\n Key      " + Hex.ToHexString(dc.getKey()) + "\n Expected "
+				     + Hex.ToHexString(dc.getDigest()) + "\n Actual   " + Hex.ToHexString(output));
+			}
+
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SkeinMacTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/SkipjackTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/SkipjackTest.cs
new file mode 100644
index 0000000..d9fe6e4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/SkipjackTest.cs
@@ -0,0 +1,46 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class SkipjackTest
+		: CipherTest
+    {
+        public override string Name
+        {
+			get { return "SKIPJACK"; }
+        }
+
+        internal static SimpleTest[] tests = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new SkipjackEngine(), new KeyParameter(Hex.Decode("00998877665544332211")), "33221100ddccbbaa", "2587cae27a12d300")};
+
+		public SkipjackTest()
+			: base(tests, new SkipjackEngine(), new KeyParameter(new byte[16]))
+		{
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            ITest test = new SkipjackTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/StreamCipherVectorTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/StreamCipherVectorTest.cs
new file mode 100644
index 0000000..ead2f16
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/StreamCipherVectorTest.cs
@@ -0,0 +1,68 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    /**
+     * a basic test that takes a stream cipher, key parameter, and an input
+     * and output string.
+     */
+    public class StreamCipherVectorTest: ITest
+    {
+        int                 id;
+        IStreamCipher       cipher;
+        ICipherParameters    param;
+        byte[]              input;
+        byte[]              output;
+
+        public StreamCipherVectorTest(
+            int                 id,
+            IStreamCipher       cipher,
+            ICipherParameters    param,
+            string              input,
+            string              output)
+        {
+            this.id = id;
+            this.cipher = cipher;
+            this.param = param;
+            this.input = Hex.Decode(input);
+            this.output = Hex.Decode(output);
+        }
+
+		public string Name
+		{
+			get { return cipher.AlgorithmName + " Vector Test " + id; }
+		}
+
+		public ITestResult Perform()
+        {
+            cipher.Init(true, param);
+
+            byte[] outBytes = new byte[input.Length];
+
+            cipher.ProcessBytes(input, 0, input.Length, outBytes, 0);
+
+            if (!Arrays.AreEqual(outBytes, output))
+            {
+                return new SimpleTestResult(false, Name + ": failed - "
+					+ "expected " + Hex.ToHexString(output)
+					+ " got " + Hex.ToHexString(outBytes));
+            }
+
+            cipher.Init(false, param);
+
+            cipher.ProcessBytes(output, 0, output.Length, outBytes, 0);
+
+            if (!Arrays.AreEqual(input, outBytes))
+            {
+                return new SimpleTestResult(false, Name + ": failed reversal");
+            }
+
+            return new SimpleTestResult(true, Name + ": OKAY");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/TEATest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/TEATest.cs
new file mode 100644
index 0000000..525941d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/TEATest.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
+	*/
+	[TestFixture]
+	public class TeaTest
+		: CipherTest
+	{
+		private static readonly SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new TeaEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"0000000000000000","41ea3a0a94baa940"),
+			new BlockCipherVectorTest(1, new TeaEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"0102030405060708", "6a2f9cf3fccf3c55"),
+			new BlockCipherVectorTest(2, new TeaEngine(),
+				new KeyParameter(Hex.Decode("0123456712345678234567893456789A")),
+				"0000000000000000", "34e943b0900f5dcb"),
+			new BlockCipherVectorTest(3, new TeaEngine(),
+				new KeyParameter(Hex.Decode("0123456712345678234567893456789A")),
+				"0102030405060708", "773dc179878a81c0"),
+		};
+
+		public TeaTest()
+			: base(tests, new TeaEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "TEA"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new TeaTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish1024Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish1024Test.cs
new file mode 100644
index 0000000..64f9aa2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish1024Test.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	[TestFixture]
+	public class Threefish1024Test
+		: CipherTest
+	{
+		// Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+		static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(new byte[128]),
+				new byte[16]),
+			                          "0000000000000000000000000000000000000000000000000000000000000000" +
+			                          "0000000000000000000000000000000000000000000000000000000000000000" +
+			                          "0000000000000000000000000000000000000000000000000000000000000000" +
+			                          "0000000000000000000000000000000000000000000000000000000000000000",
+			                          "f05c3d0a3d05b304f785ddc7d1e036015c8aa76e2f217b06c6e1544c0bc1a90d" +
+			                          "f0accb9473c24e0fd54fea68057f43329cb454761d6df5cf7b2e9b3614fbd5a2" +
+			                          "0b2e4760b40603540d82eabc5482c171c832afbe68406bc39500367a592943fa" +
+			                          "9a5b4a43286ca3c4cf46104b443143d560a4b230488311df4feef7e1dfe8391e"),
+			new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(Hex.Decode(
+				"101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+				"303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f" +
+				"505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f" +
+				"707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f")),
+				Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+			                          "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+			                          "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0" +
+			                          "bfbebdbcbbbab9b8b7b6b5b4b3b2b1b0afaeadacabaaa9a8a7a6a5a4a3a2a1a0" +
+			                          "9f9e9d9c9b9a999897969594939291908f8e8d8c8b8a89888786858483828180",
+			                          "a6654ddbd73cc3b05dd777105aa849bce49372eaaffc5568d254771bab85531c" +
+			                          "94f780e7ffaae430d5d8af8c70eebbe1760f3b42b737a89cb363490d670314bd" +
+			                          "8aa41ee63c2e1f45fbd477922f8360b388d6125ea6c7af0ad7056d01796e90c8" +
+			                          "3313f4150a5716b30ed5f569288ae974ce2b4347926fce57de44512177dd7cde")
+		};
+
+		public Threefish1024Test()
+			: base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_1024), new KeyParameter(new byte[128]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Threefish-1024"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Threefish1024Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish256Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish256Test.cs
new file mode 100644
index 0000000..e44299a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish256Test.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	[TestFixture]
+	public class Threefish256Test
+		: CipherTest
+	{
+		// Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+		static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(new byte[32]),
+				new byte[16]),
+			                          "0000000000000000000000000000000000000000000000000000000000000000",
+			                          "84da2a1f8beaee947066ae3e3103f1ad536db1f4a1192495116b9f3ce6133fd8"),
+			new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(Hex.Decode(
+				"101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f")),
+				Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+			                          "FFFEFDFCFBFAF9F8F7F6F5F4F3F2F1F0EFEEEDECEBEAE9E8E7E6E5E4E3E2E1E0",
+			                          "e0d091ff0eea8fdfc98192e62ed80ad59d865d08588df476657056b5955e97df")
+		};
+
+		public Threefish256Test()
+			: base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_256), new KeyParameter(new byte[32]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Threefish-256"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Threefish256Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish512Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish512Test.cs
new file mode 100644
index 0000000..8f4ec63
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/Threefish512Test.cs
@@ -0,0 +1,64 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	[TestFixture]
+	public class Threefish512Test
+		: CipherTest
+	{
+		// Test cases from skein_golden_kat_internals.txt in Skein 1.3 NIST CD
+		static SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(new byte[64]),
+				new byte[16]),
+			                          "0000000000000000000000000000000000000000000000000000000000000000" +
+			                          "0000000000000000000000000000000000000000000000000000000000000000",
+			                          "b1a2bbc6ef6025bc40eb3822161f36e375d1bb0aee3186fbd19e47c5d479947b" +
+			                          "7bc2f8586e35f0cff7e7f03084b0b7b1f1ab3961a580a3e97eb41ea14a6d7bbe"),
+			new BlockCipherVectorTest(1, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512),
+			                          new TweakableBlockCipherParameters(
+				new KeyParameter(Hex.Decode(
+				"101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f" +
+				"303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f")),
+				Hex.Decode("000102030405060708090a0b0c0d0e0f")),
+			                          "fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e0" +
+			                          "dfdedddcdbdad9d8d7d6d5d4d3d2d1d0cfcecdcccbcac9c8c7c6c5c4c3c2c1c0",
+			                          "e304439626d45a2cb401cad8d636249a6338330eb06d45dd8b36b90e97254779" +
+			                          "272a0a8d99463504784420ea18c9a725af11dffea10162348927673d5c1caf3d")
+		};
+
+		public Threefish512Test()
+			: base(tests, new ThreefishEngine(ThreefishEngine.BLOCKSIZE_512), new KeyParameter(new byte[64]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "Threefish-512"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Threefish512Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/TigerDigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/TigerDigestTest.cs
new file mode 100644
index 0000000..b351c4b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/TigerDigestTest.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+    /**
+     * Tiger Digest Test
+     */
+    [TestFixture]
+    public class TigerDigestTest
+        : DigestTest
+    {
+        readonly static string[] messages =
+        {
+            "",
+            "abc",
+            "Tiger",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvw",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ=abcdefghijklmnopqrstuvwxyz+0123456789",
+            "Tiger - A Fast New Hash Function, by Ross Anderson and Eli Biham, proceedings of Fast Software Encryption 3, Cambridge, 1996.",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-"
+        };
+
+        readonly static string[] digests = {
+            "3293AC630C13F0245F92BBB1766E16167A4E58492DDE73F3",
+            "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93",
+            "DD00230799F5009FEC6DEBC838BB6A27DF2B9D6F110C7937",
+            "F71C8583902AFB879EDFE610F82C0D4786A3A534504486B5",
+            "38F41D9D9A710A10C3727AC0DEEAA270727D9F926EC10139",
+            "48CEEB6308B87D46E95D656112CDF18D97915F9765658957",
+            "631ABDD103EB9A3D245B6DFD4D77B257FC7439501D1568DD",
+            "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25",
+            "C54034E5B43EB8005848A7E0AE6AAC76E4FF590AE715FD25"
+        };
+
+        readonly static string hash64k = "FDF4F5B35139F48E710E421BE5AF411DE1A8AAC333F26204";
+
+        public TigerDigestTest()
+            : base(new TigerDigest(), messages, digests)
+        {
+        }
+
+        public override void PerformTest()
+        {
+            base.PerformTest();
+
+            sixtyFourKTest(hash64k);
+        }
+
+        protected override IDigest CloneDigest(IDigest digest)
+        {
+            return new TigerDigest((TigerDigest)digest);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new TigerDigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/TwofishTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/TwofishTest.cs
new file mode 100644
index 0000000..9425d2e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/TwofishTest.cs
@@ -0,0 +1,54 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+    [TestFixture]
+    public class TwofishTest
+		: CipherTest
+    {
+        public override string Name
+        {
+			get { return "Twofish"; }
+        }
+
+        internal static string key1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
+        internal static string key2 = "000102030405060708090a0b0c0d0e0f1011121314151617";
+        internal static string key3 = "000102030405060708090a0b0c0d0e0f";
+
+        internal static string input = "000102030405060708090A0B0C0D0E0F";
+
+        internal static SimpleTest[] tests = new SimpleTest[]{
+            new BlockCipherVectorTest(0, new TwofishEngine(), new KeyParameter(Hex.Decode(key1)), input, "8ef0272c42db838bcf7b07af0ec30f38"),
+            new BlockCipherVectorTest(1, new TwofishEngine(), new KeyParameter(Hex.Decode(key2)), input, "95accc625366547617f8be4373d10cd7"),
+            new BlockCipherVectorTest(2, new TwofishEngine(), new KeyParameter(Hex.Decode(key3)), input, "9fb63337151be9c71306d159ea7afaa4")};
+
+        public TwofishTest()
+			: base(tests, new TwofishEngine(), new KeyParameter(new byte[32]))
+		{
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            ITest test = new TwofishTest();
+            ITestResult result = test.Perform();
+
+            Console.WriteLine(result);
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCKSA3Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCKSA3Test.cs
new file mode 100644
index 0000000..a25105b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCKSA3Test.cs
@@ -0,0 +1,112 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* VMPC Test
+	*/
+	[TestFixture]
+	public class VmpcKsa3Test
+		: SimpleTest
+	{
+		private static readonly byte[] input = new byte[1000000];
+
+		public override string Name
+		{
+			get { return "VMPC-KSA3"; }
+		}
+
+		private void checkByte(byte[] array, int position, byte b)
+		{
+			if (array[position] != b)
+			{
+				Fail("Fail on position " + position,
+					Hex.ToHexString(new byte[] { b }),
+					Hex.ToHexString(new byte[] { array[position] }));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			byte[] key = Hex.Decode("9661410AB797D8A9EB767C21172DF6C7");
+			byte[] iv = Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155");
+			ICipherParameters kp = new KeyParameter(key);
+			ICipherParameters kpwiv = new ParametersWithIV(kp, iv);
+
+			VmpcKsa3Engine engine = new VmpcKsa3Engine();
+
+			try
+			{
+				engine.Init(true, kp);
+				Fail("Init failed to throw expected exception");
+			}
+			catch (ArgumentException)
+			{
+				// Expected
+			}
+
+			engine.Init(true, kpwiv);
+			checkEngine(engine);
+
+			engine.Reset();
+			byte[] output = checkEngine(engine);
+
+			engine.Init(false, kpwiv);
+			byte[] recovered = new byte[output.Length];
+			engine.ProcessBytes(output, 0, output.Length, recovered, 0);
+
+			if (!Arrays.AreEqual(input, recovered))
+			{
+				Fail("decrypted bytes differ from original bytes");
+			}
+		}
+
+		private byte[] checkEngine(VmpcKsa3Engine engine)
+		{
+			byte[] output = new byte[input.Length];
+			engine.ProcessBytes(input, 0, output.Length, output, 0);
+
+			checkByte(output, 0, (byte) 0xB6);
+			checkByte(output, 1, (byte) 0xEB);
+			checkByte(output, 2, (byte) 0xAE);
+			checkByte(output, 3, (byte) 0xFE);
+			checkByte(output, 252, (byte) 0x48);
+			checkByte(output, 253, (byte) 0x17);
+			checkByte(output, 254, (byte) 0x24);
+			checkByte(output, 255, (byte) 0x73);
+			checkByte(output, 1020, (byte) 0x1D);
+			checkByte(output, 1021, (byte) 0xAE);
+			checkByte(output, 1022, (byte) 0xC3);
+			checkByte(output, 1023, (byte) 0x5A);
+			checkByte(output, 102396, (byte) 0x1D);
+			checkByte(output, 102397, (byte) 0xA7);
+			checkByte(output, 102398, (byte) 0xE1);
+			checkByte(output, 102399, (byte) 0xDC);
+
+			return output;
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new VmpcKsa3Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCMacTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCMacTest.cs
new file mode 100644
index 0000000..0ddb550
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCMacTest.cs
@@ -0,0 +1,68 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Macs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	[TestFixture]
+	public class VmpcMacTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "VMPC-MAC"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new VmpcMacTest());
+		}
+
+		private static byte[] output1 = Hex.Decode("9BDA16E2AD0E284774A3ACBC8835A8326C11FAAD");
+
+		public override void PerformTest()
+		{
+			ICipherParameters kp = new KeyParameter(
+				Hex.Decode("9661410AB797D8A9EB767C21172DF6C7"));
+			ICipherParameters kpwiv = new ParametersWithIV(kp,
+				Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155"));
+
+			byte[] m = new byte[256];
+			for (int i = 0; i < 256; i++)
+			{
+				m[i] = (byte) i;
+			}
+
+			VmpcMac mac = new VmpcMac();
+			mac.Init(kpwiv);
+
+			mac.BlockUpdate(m, 0, m.Length);
+
+			byte[] output = new byte[20];
+			mac.DoFinal(output, 0);
+
+			if (!Arrays.AreEqual(output, output1))
+			{
+				Fail("Fail",
+					Hex.ToHexString(output1),
+					Hex.ToHexString(output));
+			}
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCTest.cs
new file mode 100644
index 0000000..6186c47
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/VMPCTest.cs
@@ -0,0 +1,112 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* VMPC Test
+	*/
+	[TestFixture]
+	public class VmpcTest
+		: SimpleTest
+	{
+		private static readonly byte[] input = new byte[1000000];
+
+		public override string Name
+		{
+			get { return "VMPC"; }
+		}
+
+		private void checkByte(byte[] array, int position, byte b)
+		{
+			if (array[position] != b)
+			{
+				Fail("Fail on position " + position,
+					Hex.ToHexString(new byte[] { b }),
+					Hex.ToHexString(new byte[] { array[position] }));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			byte[] key = Hex.Decode("9661410AB797D8A9EB767C21172DF6C7");
+			byte[] iv = Hex.Decode("4B5C2F003E67F39557A8D26F3DA2B155");
+			ICipherParameters kp = new KeyParameter(key);
+			ICipherParameters kpwiv = new ParametersWithIV(kp, iv);
+
+			VmpcEngine engine = new VmpcEngine();
+
+			try
+			{
+				engine.Init(true, kp);
+				Fail("Init failed to throw expected exception");
+			}
+			catch (ArgumentException)
+			{
+				// Expected
+			}
+
+			engine.Init(true, kpwiv);
+			checkEngine(engine);
+
+			engine.Reset();
+			byte[] output = checkEngine(engine);
+
+			engine.Init(false, kpwiv);
+			byte[] recovered = new byte[output.Length];
+			engine.ProcessBytes(output, 0, output.Length, recovered, 0);
+
+			if (!Arrays.AreEqual(input, recovered))
+			{
+				Fail("decrypted bytes differ from original bytes");
+			}
+		}
+
+		private byte[] checkEngine(VmpcEngine engine)
+		{
+			byte[] output = new byte[input.Length];
+			engine.ProcessBytes(input, 0, output.Length, output, 0);
+
+			checkByte(output, 0, (byte) 0xA8);
+			checkByte(output, 1, (byte) 0x24);
+			checkByte(output, 2, (byte) 0x79);
+			checkByte(output, 3, (byte) 0xF5);
+			checkByte(output, 252, (byte) 0xB8);
+			checkByte(output, 253, (byte) 0xFC);
+			checkByte(output, 254, (byte) 0x66);
+			checkByte(output, 255, (byte) 0xA4);
+			checkByte(output, 1020, (byte) 0xE0);
+			checkByte(output, 1021, (byte) 0x56);
+			checkByte(output, 1022, (byte) 0x40);
+			checkByte(output, 1023, (byte) 0xA5);
+			checkByte(output, 102396, (byte) 0x81);
+			checkByte(output, 102397, (byte) 0xCA);
+			checkByte(output, 102398, (byte) 0x49);
+			checkByte(output, 102399, (byte) 0x9A);
+
+			return output;
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new VmpcTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/WhirlpoolDigestTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/WhirlpoolDigestTest.cs
new file mode 100644
index 0000000..1445b89
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/WhirlpoolDigestTest.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Encodings;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+
+	/**
+	 * ISO vector test for Whirlpool
+	 *  
+	 */
+	[TestFixture]
+	public class WhirlpoolDigestTest
+		: DigestTest
+	{
+		private static string[] messages =
+		{
+			"",
+			"a",
+			"abc",
+			"message digest",
+			"abcdefghijklmnopqrstuvwxyz",
+			"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+			"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+			"abcdbcdecdefdefgefghfghighijhijk"
+		};
+
+		private static string[] digests =
+		{
+			"19FA61D75522A4669B44E39C1D2E1726C530232130D407F89AFEE0964997F7A73E83BE698B288FEBCF88E3E03C4F0757EA8964E59B63D93708B138CC42A66EB3",
+			"8ACA2602792AEC6F11A67206531FB7D7F0DFF59413145E6973C45001D0087B42D11BC645413AEFF63A42391A39145A591A92200D560195E53B478584FDAE231A",
+			"4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5",
+			"378C84A4126E2DC6E56DCC7458377AAC838D00032230F53CE1F5700C0FFB4D3B8421557659EF55C106B4B52AC5A4AAA692ED920052838F3362E86DBD37A8903E",
+			"F1D754662636FFE92C82EBB9212A484A8D38631EAD4238F5442EE13B8054E41B08BF2A9251C30B6A0B8AAE86177AB4A6F68F673E7207865D5D9819A3DBA4EB3B",
+			"DC37E008CF9EE69BF11F00ED9ABA26901DD7C28CDEC066CC6AF42E40F82F3A1E08EBA26629129D8FB7CB57211B9281A65517CC879D7B962142C65F5A7AF01467",
+			"466EF18BABB0154D25B9D38A6414F5C08784372BCCB204D6549C4AFADB6014294D5BD8DF2A6C44E538CD047B2681A51A2C60481E88C5A20B2C2A80CF3A9A083B",
+			"2A987EA40F917061F5D6F0A0E4644F488A7A5A52DEEE656207C562F988E95C6916BDC8031BC5BE1B7B947639FE050B56939BAAA0ADFF9AE6745B7B181C3BE3FD"
+		};
+
+		private static string _millionAResultVector = "0C99005BEB57EFF50A7CF005560DDF5D29057FD86B20BFD62DECA0F1CCEA4AF51FC15490EDDC47AF32BB2B66C34FF9AD8C6008AD677F77126953B226E4ED8B01";
+
+		private static string _thirtyOneZeros = "3E3F188F8FEBBEB17A933FEAF7FE53A4858D80C915AD6A1418F0318E68D49B4E459223CD414E0FBC8A57578FD755D86E827ABEF4070FC1503E25D99E382F72BA";
+
+		public WhirlpoolDigestTest()
+			: base(new WhirlpoolDigest(), messages, digests)
+		{
+		}
+
+		public override void PerformTest()
+		{
+			base.PerformTest();
+
+			byte[] thirtyOneZeros = new byte[31];
+			performStandardVectorTest("31 zeroes test", 
+			                          thirtyOneZeros, _thirtyOneZeros);
+
+			byte[] millionAInByteArray = new byte[1000000];
+			Arrays.Fill(millionAInByteArray, (byte)'a');
+
+			performStandardVectorTest("Million 'a' test", 
+			                          millionAInByteArray, _millionAResultVector);
+		}
+
+		private void performStandardVectorTest(string testTitle, byte[] inputBytes,
+		                                       string resultsAsHex)
+		{
+			doPerformTest(testTitle, inputBytes, resultsAsHex);        
+		}
+
+		private void doPerformTest(string testTitle, byte[] inputBytes, string resultsAsHex)
+		{
+			string resStr = createHexOutputFromDigest(inputBytes);
+			if (!resultsAsHex.Equals(resStr.ToUpper()))
+			{
+				Fail(testTitle, resultsAsHex, resStr);
+			}
+		}
+
+		private string createHexOutputFromDigest(byte[] digestBytes)
+		{
+			string resStr;
+			IDigest digest = new WhirlpoolDigest();
+			byte[] resBuf = new byte[digest.GetDigestSize()];
+			digest.BlockUpdate(digestBytes, 0, digestBytes.Length);
+			digest.DoFinal(resBuf, 0);
+			resStr = Hex.ToHexString(resBuf);
+			return resStr;
+		}
+
+		protected override IDigest CloneDigest(IDigest digest)
+		{
+			return new WhirlpoolDigest((WhirlpoolDigest)digest);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new WhirlpoolDigestTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/XSalsa20Test.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/XSalsa20Test.cs
new file mode 100644
index 0000000..74ed04e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/XSalsa20Test.cs
@@ -0,0 +1,183 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* XSalsa20 Test
+	*/
+	[TestFixture]
+	public class XSalsa20Test 
+		: SimpleTest
+	{
+		private class TestCase
+		{
+
+			private byte[] key;
+			private byte[] iv;
+			private byte[] plaintext;
+			private byte[] ciphertext;
+
+			public TestCase(String key, string iv, string plaintext, string ciphertext)
+			{
+				this.key = Hex.Decode(key);
+				this.iv = Hex.Decode(iv);
+				this.plaintext = Hex.Decode(plaintext);
+				this.ciphertext = Hex.Decode(ciphertext);
+			}
+
+			public byte[] Key
+			{
+				get { return key; }
+			}
+
+			public byte[] Iv
+			{
+				get { return iv; }
+			}
+
+			public byte[] Plaintext
+			{
+				get { return plaintext; }
+			}
+
+			public byte[] Ciphertext
+			{
+				get { return ciphertext; }
+			}
+		}
+
+		// Test cases generated by naclcrypto-20090308, as used by cryptopp
+		private static readonly TestCase[] TEST_CASES = new TestCase[] {
+			new TestCase(
+				"a6a7251c1e72916d11c2cb214d3c252539121d8e234e652d651fa4c8cff88030",
+				"9e645a74e9e0a60d8243acd9177ab51a1beb8d5a2f5d700c",
+				"093c5e5585579625337bd3ab619d615760d8c5b224a85b1d0efe0eb8a7ee163abb0376529fcc09bab506c618e13ce777d82c3ae9d1a6f972d4160287cbfe60bf2130fc0a6ff6049d0a5c8a82f429231f008082e845d7e189d37f9ed2b464e6b919e6523a8c1210bd52a02a4c3fe406d3085f5068d1909eeeca6369abc981a42e87fe665583f0ab85ae71f6f84f528e6b397af86f6917d9754b7320dbdc2fea81496f2732f532ac78c4e9c6cfb18f8e9bdf74622eb126141416776971a84f94d156beaf67aecbf2ad412e76e66e8fad7633f5b6d7f3d64b5c6c69ce29003c6024465ae3b89be78e915d88b4b5621d",
+				"b2af688e7d8fc4b508c05cc39dd583d6714322c64d7f3e63147aede2d9534934b04ff6f337b031815cd094bdbc6d7a92077dce709412286822ef0737ee47f6b7ffa22f9d53f11dd2b0a3bb9fc01d9a88f9d53c26e9365c2c3c063bc4840bfc812e4b80463e69d179530b25c158f543191cff993106511aa036043bbc75866ab7e34afc57e2cce4934a5faae6eabe4f221770183dd060467827c27a354159a081275a291f69d946d6fe28ed0b9ce08206cf484925a51b9498dbde178ddd3ae91a8581b91682d860f840782f6eea49dbb9bd721501d2c67122dea3b7283848c5f13e0c0de876bd227a856e4de593a3"),
+			new TestCase(
+				"9e1da239d155f52ad37f75c7368a536668b051952923ad44f57e75ab588e475a",
+				"af06f17859dffa799891c4288f6635b5c5a45eee9017fd72",
+				"feac9d54fc8c115ae247d9a7e919dd76cfcbc72d32cae4944860817cbdfb8c04e6b1df76a16517cd33ccf1acda9206389e9e318f5966c093cfb3ec2d9ee2de856437ed581f552f26ac2907609df8c613b9e33d44bfc21ff79153e9ef81a9d66cc317857f752cc175fd8891fefebb7d041e6517c3162d197e2112837d3bc4104312ad35b75ea686e7c70d4ec04746b52ff09c421451459fb59f",
+				"2c261a2f4e61a62e1b27689916bf03453fcbc97bb2af6f329391ef063b5a219bf984d07d70f602d85f6db61474e9d9f5a2deecb4fcd90184d16f3b5b5e168ee03ea8c93f3933a22bc3d1a5ae8c2d8b02757c87c073409052a2a8a41e7f487e041f9a49a0997b540e18621cad3a24f0a56d9b19227929057ab3ba950f6274b121f193e32e06e5388781a1cb57317c0ba6305e910961d01002f0"),
+			new TestCase("d5c7f6797b7e7e9c1d7fd2610b2abf2bc5a7885fb3ff78092fb3abe8986d35e2",
+	             "744e17312b27969d826444640e9c4a378ae334f185369c95",
+	             "7758298c628eb3a4b6963c5445ef66971222be5d1a4ad839715d1188071739b77cc6e05d5410f963a64167629757",
+	             "27b8cfe81416a76301fd1eec6a4d99675069b2da2776c360db1bdfea7c0aa613913e10f7a60fec04d11e65f2d64e"),
+			new TestCase(
+				"737d7811ce96472efed12258b78122f11deaec8759ccbd71eac6bbefa627785c",
+				"6fb2ee3dda6dbd12f1274f126701ec75c35c86607adb3edd",
+				"501325fb2645264864df11faa17bbd58312b77cad3d94ac8fb8542f0eb653ad73d7fce932bb874cb89ac39fc47f8267cf0f0c209f204b2d8578a3bdf461cb6a271a468bebaccd9685014ccbc9a73618c6a5e778a21cc8416c60ad24ddc417a130d53eda6dfbfe47d09170a7be1a708b7b5f3ad464310be36d9a2a95dc39e83d38667e842eb6411e8a23712297b165f690c2d7ca1b1346e3c1fccf5cafd4f8be0",
+				"6724c372d2e9074da5e27a6c54b2d703dc1d4c9b1f8d90f00c122e692ace7700eadca942544507f1375b6581d5a8fb39981c1c0e6e1ff2140b082e9ec016fce141d5199647d43b0b68bfd0fea5e00f468962c7384dd6129aea6a3fdfe75abb210ed5607cef8fa0e152833d5ac37d52e557b91098a322e76a45bbbcf4899e790618aa3f4c2e5e0fc3de93269a577d77a5502e8ea02f717b1dd2df1ec69d8b61ca"),
+			new TestCase(
+				"760158da09f89bbab2c99e6997f9523a95fcef10239bcca2573b7105f6898d34",
+				"43636b2cc346fc8b7c85a19bf507bdc3dafe953b88c69dba",
+				"d30a6d42dff49f0ed039a306bae9dec8d9e88366cc19e8c3642fd58fa0794ebf8029d949730339b0823a51f0f49f0d2c71f1051c1e0e2c86941f172789cdb1b0107413e70f982ff9761877bb526ef1c3eb1106a948d60ef21bd35d32cfd64f89b79ed63ecc5cca56246af736766f285d8e6b0da9cb1cd21020223ffacc5a32",
+				"c815b6b79b64f9369aec8dce8c753df8a50f2bc97c70ce2f014db33a65ac5816bac9e30ac08bdded308c65cb87e28e2e71b677dc25c5a6499c1553555daf1f55270a56959dffa0c66f24e0af00951ec4bb59ccc3a6c5f52e0981647e53e439313a52c40fa7004c855b6e6eb25b212a138e843a9ba46edb2a039ee82a263abe"),
+			new TestCase(
+				"27ba7e81e7edd4e71be53c07ce8e633138f287e155c7fa9e84c4ad804b7fa1b9",
+				"ea05f4ebcd2fb6b000da0612861ba54ff5c176fb601391aa",
+				"e09ff5d2cb050d69b2d42494bde5825238c756d6991d99d7a20d1ef0b83c371c89872690b2fc11d5369f4fc4971b6d3d6c078aef9b0f05c0e61ab89c025168054defeb03fef633858700c58b1262ce011300012673e893e44901dc18eee3105699c44c805897bdaf776af1833162a21a",
+				"a23e7ef93c5d0667c96d9e404dcbe6be62026fa98f7a3ff9ba5d458643a16a1cef7272dc6097a9b52f35983557c77a11b314b4f7d5dc2cca15ee47616f861873cbfed1d32372171a61e38e447f3cf362b3abbb2ed4170d89dcb28187b7bfd206a3e026f084a7e0ed63d319de6bc9afc0"),
+			new TestCase("6799d76e5ffb5b4920bc2768bafd3f8c16554e65efcf9a16f4683a7a06927c11",
+	             "61ab951921e54ff06d9b77f313a4e49df7a057d5fd627989", "472766", "8fd7df"),
+			new TestCase(
+				"f68238c08365bb293d26980a606488d09c2f109edafa0bbae9937b5cc219a49c",
+				"5190b51e9b708624820b5abdf4e40fad1fb950ad1adc2d26",
+				"47ec6b1f73c4b7ff5274a0bfd7f45f864812c85a12fbcb3c2cf8a3e90cf66ccf2eacb521e748363c77f52eb426ae57a0c6c78f75af71284569e79d1a92f949a9d69c4efc0b69902f1e36d7562765543e2d3942d9f6ff5948d8a312cff72c1afd9ea3088aff7640bfd265f7a9946e606abc77bcedae6bddc75a0dba0bd917d73e3bd1268f727e0096345da1ed25cf553ea7a98fea6b6f285732de37431561ee1b3064887fbcbd71935e02",
+				"36160e88d3500529ba4edba17bc24d8cfaca9a0680b3b1fc97cf03f3675b7ac301c883a68c071bc54acdd3b63af4a2d72f985e51f9d60a4c7fd481af10b2fc75e252fdee7ea6b6453190617dcc6e2fe1cd56585fc2f0b0e97c5c3f8ad7eb4f31bc4890c03882aac24cc53acc1982296526690a220271c2f6e326750d3fbda5d5b63512c831f67830f59ac49aae330b3e0e02c9ea0091d19841f1b0e13d69c9fbfe8a12d6f30bb734d9d2"),
+			new TestCase(
+				"45b2bd0de4ed9293ec3e26c4840faaf64b7d619d51e9d7a2c7e36c83d584c3df",
+				"546c8c5d6be8f90952cab3f36d7c1957baaa7a59abe3d7e5",
+				"5007c8cd5b3c40e17d7fe423a87ae0ced86bec1c39dc07a25772f3e96dabd56cd3fd7319f6c9654925f2d87087a700e1b130da796895d1c9b9acd62b266144067d373ed51e787498b03c52faad16bb3826fa511b0ed2a19a8663f5ba2d6ea7c38e7212e9697d91486c49d8a000b9a1935d6a7ff7ef23e720a45855481440463b4ac8c4f6e7062adc1f1e1e25d3d65a31812f58a71160",
+				"8eacfba568898b10c0957a7d44100685e8763a71a69a8d16bc7b3f88085bb9a2f09642e4d09a9f0ad09d0aad66b22610c8bd02ff6679bb92c2c026a216bf425c6be35fb8dae7ff0c72b0efd6a18037c70eed0ca90062a49a3c97fdc90a8f9c2ea536bfdc41918a7582c9927fae47efaa3dc87967b7887dee1bf071734c7665901d9105dae2fdf66b4918e51d8f4a48c60d19fbfbbcba"),
+			new TestCase(
+				"fe559c9a282beb40814d016d6bfcb2c0c0d8bf077b1110b8703a3ce39d70e0e1",
+				"b076200cc7011259805e18b304092754002723ebec5d6200",
+				"6db65b9ec8b114a944137c821fd606be75478d928366d5284096cdef782fcff7e8f59cb8ffcda979757902c5ffa6bc477ceaa4cb5d5ea76f94d91e833f823a6bc78f1055dfa6a97bea8965c1cde67a668e001257334a585727d9e0f7c1a06e88d3d25a4e6d9096c968bf138e116a3ebeffd4bb4808adb1fd698164ba0a35c709a47f16f1f4435a2345a9194a00b95abd51851d505809a6077da9baca5831afff31578c487ee68f2767974a98a7e803aac788da98319c4ea8eaa3d394855651f484cef543f537e35158ee29",
+				"4dce9c8f97a028051b0727f34e1b9ef21f06f0760f36e71713204027902090ba2bb6b13436ee778d9f50530efbd7a32b0d41443f58ccaee781c7b716d3a96fdec0e3764ed7959f34c3941278591ea033b5cbadc0f1916032e9bebbd1a8395b83fb63b1454bd775bd20b3a2a96f951246ac14daf68166ba62f6cbff8bd121ac9498ff8852fd2be975df52b5daef3829d18eda42e715022dcbf930d0a789ee6a146c2c7088c35773c63c06b4af4559856ac199ced86863e4294707825337c5857970eb7fddeb263781309011"),
+			new TestCase(
+				"0ae10012d7e56614b03dcc89b14bae9242ffe630f3d7e35ce8bbb97bbc2c92c3",
+				"f96b025d6cf46a8a12ac2af1e2aef1fb83590adadaa5c5ea",
+				"ea0f354e96f12bc72bbaa3d12b4a8ed879b042f0689878f46b651cc4116d6f78409b11430b3aaa30b2076891e8e1fa528f2fd169ed93dc9f84e24409eec2101daf4d057be2492d11de640cbd7b355ad29fb70400fffd7cd6d425abeeb732a0eaa4330af4c656252c4173deab653eb85c58462d7ab0f35fd12b613d29d473d330310dc323d3c66348bbdbb68a326324657cae7b77a9e34358f2cec50c85609e73056856796e3be8d62b6e2fe9f953",
+				"e8abd48924b54e5b80866be7d4ebe5cf4274cafff08b39cb2d40a8f0b472398aedc776e0793812fbf1f60078635d2ed86b15efcdba60411ee23b07233592a44ec31b1013ce8964236675f8f183aef885e864f2a72edf4215b5338fa2b54653dfa1a8c55ce5d95cc605b9b311527f2e3463ffbec78a9d1d65dabad2f338769c9f43f133a791a11c7eca9af0b771a4ac32963dc8f631a2c11217ac6e1b9430c1aae1ceebe22703f429998a8fb8c641"),
+			new TestCase(
+				"082c539bc5b20f97d767cd3f229eda80b2adc4fe49c86329b5cd6250a9877450",
+				"845543502e8b64912d8f2c8d9fffb3c69365686587c08d0c",
+				"a96bb7e910281a6dfad7c8a9c370674f0ceec1ad8d4f0de32f9ae4a23ed329e3d6bc708f876640a229153ac0e7281a8188dd77695138f01cda5f41d5215fd5c6bdd46d982cb73b1efe2997970a9fdbdb1e768d7e5db712068d8ba1af6067b5753495e23e6e1963af012f9c7ce450bf2de619d3d59542fb55f3",
+				"835da74fc6de08cbda277a7966a07c8dcd627e7b17adde6d930b6581e3124b8baad096f693991fedb1572930601fc7709541839b8e3ffd5f033d2060d999c6c6e3048276613e648000acb5212cc632a916afce290e20ebdf612d08a6aa4c79a74b070d3f872a861f8dc6bb07614db515d363349d3a8e3336a3"),
+			new TestCase("3d02bff3375d403027356b94f514203737ee9a85d2052db3e4e5a217c259d18a",
+	             "74216c95031895f48c1dba651555ebfa3ca326a755237025",
+	             "0d4b0f54fd09ae39baa5fa4baccf2e6682e61b257e01f42b8f",
+	             "16c4006c28365190411eb1593814cf15e74c22238f210afc3d"),
+			new TestCase(
+				"ad1a5c47688874e6663a0f3fa16fa7efb7ecadc175c468e5432914bdb480ffc6",
+				"e489eed440f1aae1fac8fb7a9825635454f8f8f1f52e2fcc",
+				"aa6c1e53580f03a9abb73bfdadedfecada4c6b0ebe020ef10db745e54ba861caf65f0e40dfc520203bb54d29e0a8f78f16b3f1aa525d6bfa33c54726e59988cfbec78056",
+				"02fe84ce81e178e7aabdd3ba925a766c3c24756eefae33942af75e8b464556b5997e616f3f2dfc7fce91848afd79912d9fb55201b5813a5a074d2c0d4292c1fd441807c5"),
+			new TestCase(
+				"053a02bedd6368c1fb8afc7a1b199f7f7ea2220c9a4b642a6850091c9d20ab9c",
+				"c713eea5c26dad75ad3f52451e003a9cb0d649f917c89dde",
+				"8f0a8a164760426567e388840276de3f95cb5e3fadc6ed3f3e4fe8bc169d9388804dcb94b6587dbb66cb0bd5f87b8e98b52af37ba290629b858e0e2aa7378047a26602",
+				"516710e59843e6fbd4f25d0d8ca0ec0d47d39d125e9dad987e0518d49107014cb0ae405e30c2eb3794750bca142ce95e290cf95abe15e822823e2e7d3ab21bc8fbd445"),
+			new TestCase(
+				"5b14ab0fbed4c58952548a6cb1e0000cf4481421f41288ea0aa84add9f7deb96",
+				"54bf52b911231b952ba1a6af8e45b1c5a29d97e2abad7c83",
+				"37fb44a675978b560ff9a4a87011d6f3ad2d37a2c3815b45a3c0e6d1b1d8b1784cd468927c2ee39e1dccd4765e1c3d676a335be1ccd6900a45f5d41a317648315d8a8c24adc64eb285f6aeba05b9029586353d303f17a807658b9ff790474e1737bd5fdc604aeff8dfcaf1427dcc3aacbb0256badcd183ed75a2dc52452f87d3c1ed2aa583472b0ab91cda20614e9b6fdbda3b49b098c95823cc72d8e5b717f2314b0324e9ce",
+				"ae6deb5d6ce43d4b09d0e6b1c0e9f46157bcd8ab50eaa3197ff9fa2bf7af649eb52c68544fd3adfe6b1eb316f1f23538d470c30dbfec7e57b60cbcd096c782e7736b669199c8253e70214cf2a098fda8eac5da79a9496a3aae754d03b17c6d70d1027f42bf7f95ce3d1d9c338854e158fcc803e4d6262fb639521e47116ef78a7a437ca9427ba645cd646832feab822a208278e45e93e118d780b988d65397eddfd7a819526e"),
+			new TestCase(
+				"d74636e3413a88d85f322ca80fb0bd650bd0bf0134e2329160b69609cd58a4b0",
+				"efb606aa1d9d9f0f465eaa7f8165f1ac09f5cb46fecf2a57",
+				"f85471b75f6ec81abac2799ec09e98e280b2ffd64ca285e5a0109cfb31ffab2d617b2c2952a2a8a788fc0da2af7f530758f74f1ab56391ab5ff2adbcc5be2d6c7f49fbe8118104c6ff9a23c6dfe52f57954e6a69dcee5db06f514f4a0a572a9a8525d961dae72269b987189d465df6107119c7fa790853e063cba0fab7800ca932e258880fd74c33c784675bedad0e7c09e9cc4d63dd5e9713d5d4a0196e6b562226ac31b4f57c04f90a181973737ddc7e80f364112a9fbb435ebdbcabf7d490ce52",
+				"b2b795fe6c1d4c83c1327e015a67d4465fd8e32813575cbab263e20ef05864d2dc17e0e4eb81436adfe9f638dcc1c8d78f6b0306baf938e5d2ab0b3e05e735cc6fff2d6e02e3d60484bea7c7a8e13e23197fea7b04d47d48f4a4e5944174539492800d3ef51e2ee5e4c8a0bdf050c2dd3dd74fce5e7e5c37364f7547a11480a3063b9a0a157b15b10a5a954de2731ced055aa2e2767f0891d4329c426f3808ee867bed0dc75b5922b7cfb895700fda016105a4c7b7f0bb90f029f6bbcb04ac36ac16") };
+
+		public override string Name
+		{
+			get { return "XSalsa20"; }
+		}
+
+		public override void PerformTest()
+		{
+			for (int i = 0; i < TEST_CASES.Length; i++)
+			{
+				performTest(i, TEST_CASES[i]);
+			}
+		}
+
+		private void performTest(int number, TestCase testCase)
+		{
+			byte[] plaintext = testCase.Plaintext;
+			byte[] output = new byte[plaintext.Length];
+
+			XSalsa20Engine engine = new XSalsa20Engine();
+			engine.Init(false, new ParametersWithIV(new KeyParameter(testCase.Key), testCase.Iv));
+
+			engine.ProcessBytes(testCase.Plaintext, 0, testCase.Plaintext.Length, output, 0);
+
+			if (!Arrays.AreEqual(testCase.Ciphertext, output))
+			{
+				Fail("mismatch on " + number, Hex.ToHexString(testCase.Ciphertext), Hex.ToHexString(output));
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new XSalsa20Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/test/XTEATest.cs b/BouncyCastle.AxCrypt/test/src/crypto/test/XTEATest.cs
new file mode 100644
index 0000000..a1ea652
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/test/XTEATest.cs
@@ -0,0 +1,59 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tests
+{
+	/**
+	* TEA tester - based on C implementation results from http://www.simonshepherd.supanet.com/tea.htm
+	*/
+	[TestFixture]
+	public class XteaTest
+		: CipherTest
+	{
+		private static readonly SimpleTest[] tests =
+		{
+			new BlockCipherVectorTest(0, new XteaEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"0000000000000000", "dee9d4d8f7131ed9"),
+			new BlockCipherVectorTest(1, new XteaEngine(),
+				new KeyParameter(Hex.Decode("00000000000000000000000000000000")),
+				"0102030405060708", "065c1b8975c6a816"),
+			new BlockCipherVectorTest(2, new XteaEngine(),
+				new KeyParameter(Hex.Decode("0123456712345678234567893456789A")),
+				"0000000000000000", "1ff9a0261ac64264"),
+			new BlockCipherVectorTest(3, new XteaEngine(),
+				new KeyParameter(Hex.Decode("0123456712345678234567893456789A")),
+				"0102030405060708", "8c67155b2ef91ead"),
+		};
+
+		public XteaTest()
+			: base(tests, new XteaEngine(), new KeyParameter(new byte[16]))
+		{
+		}
+
+		public override string Name
+		{
+			get { return "XTEA"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new XteaTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsClient.cs b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsClient.cs
new file mode 100644
index 0000000..61521ad
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsClient.cs
@@ -0,0 +1,158 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockTlsClient
+        :   DefaultTlsClient
+    {
+        internal TlsSession mSession;
+
+        internal MockTlsClient(TlsSession session)
+        {
+            this.mSession = session;
+        }
+
+        public override TlsSession GetSessionToResume()
+        {
+            return this.mSession;
+        }
+
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+                + ")");
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
+                + alertDescription + ")");
+        }
+
+        public override int[] GetCipherSuites()
+        {
+            return Arrays.Concatenate(base.GetCipherSuites(),
+                new int[]
+                {
+                    CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+                });
+        }
+
+        public override IDictionary GetClientExtensions()
+        {
+            IDictionary clientExtensions = TlsExtensionsUtilities.EnsureExtensionsInitialised(base.GetClientExtensions());
+            TlsExtensionsUtilities.AddEncryptThenMacExtension(clientExtensions);
+            TlsExtensionsUtilities.AddMaxFragmentLengthExtension(clientExtensions, MaxFragmentLength.pow2_9);
+            TlsExtensionsUtilities.AddTruncatedHMacExtension(clientExtensions);
+            return clientExtensions;
+        }
+
+        public override void NotifyServerVersion(ProtocolVersion serverVersion)
+        {
+            base.NotifyServerVersion(serverVersion);
+
+            Console.WriteLine("TLS client negotiated " + serverVersion);
+        }
+
+        public override TlsAuthentication GetAuthentication()
+        {
+            return new MyTlsAuthentication(mContext);
+        }
+
+        public override void NotifyHandshakeComplete()
+        {
+            base.NotifyHandshakeComplete();
+
+            TlsSession newSession = mContext.ResumableSession;
+            if (newSession != null)
+            {
+                byte[] newSessionID = newSession.SessionID;
+                string hex = Hex.ToHexString(newSessionID);
+
+                if (this.mSession != null && Arrays.AreEqual(this.mSession.SessionID, newSessionID))
+                {
+                    Console.WriteLine("Resumed session: " + hex);
+                }
+                else
+                {
+                    Console.WriteLine("Established session: " + hex);
+                }
+
+                this.mSession = newSession;
+            }
+        }
+
+        internal class MyTlsAuthentication
+            :   TlsAuthentication
+        {
+            private readonly TlsContext mContext;
+
+            internal MyTlsAuthentication(TlsContext context)
+            {
+                this.mContext = context;
+            }
+
+            public virtual void NotifyServerCertificate(Certificate serverCertificate)
+            {
+                X509CertificateStructure[] chain = serverCertificate.GetCertificateList();
+                Console.WriteLine("TLS client received server certificate chain of length " + chain.Length);
+                for (int i = 0; i != chain.Length; i++)
+                {
+                    X509CertificateStructure entry = chain[i];
+                    // TODO Create Fingerprint based on certificate signature algorithm digest
+                    Console.WriteLine("    Fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                        + entry.Subject + ")");
+                }
+            }
+
+            public virtual TlsCredentials GetClientCredentials(CertificateRequest certificateRequest)
+            {
+                byte[] certificateTypes = certificateRequest.CertificateTypes;
+                if (certificateTypes == null || !Arrays.Contains(certificateTypes, ClientCertificateType.rsa_sign))
+                    return null;
+
+                SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+                IList sigAlgs = certificateRequest.SupportedSignatureAlgorithms;
+                if (sigAlgs != null)
+                {
+                    foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs)
+                    {
+                        if (sigAlg.Signature == SignatureAlgorithm.rsa)
+                        {
+                            signatureAndHashAlgorithm = sigAlg;
+                            break;
+                        }
+                    }
+
+                    if (signatureAndHashAlgorithm == null)
+                    {
+                        return null;
+                    }
+                }
+
+                return TlsTestUtilities.LoadSignerCredentials(mContext, new string[] { "x509-client.pem", "x509-ca.pem" },
+                    "x509-client-key.pem", signatureAndHashAlgorithm);
+            }
+        };
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsServer.cs b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsServer.cs
new file mode 100644
index 0000000..54a645d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/MockTlsServer.cs
@@ -0,0 +1,137 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    internal class MockTlsServer
+        :   DefaultTlsServer
+    {
+        public override void NotifyAlertRaised(byte alertLevel, byte alertDescription, string message, Exception cause)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS client raised alert (AlertLevel." + alertLevel + ", AlertDescription." + alertDescription
+                + ")");
+            if (message != null)
+            {
+                output.WriteLine("> " + message);
+            }
+            if (cause != null)
+            {
+                output.WriteLine(cause);
+            }
+        }
+
+        public override void NotifyAlertReceived(byte alertLevel, byte alertDescription)
+        {
+            TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out;
+            output.WriteLine("TLS client received alert (AlertLevel." + alertLevel + ", AlertDescription."
+                + alertDescription + ")");
+        }
+
+        protected override int[] GetCipherSuites()
+        {
+            return Arrays.Concatenate(base.GetCipherSuites(),
+                new int[]
+                {
+                    CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_ECDHE_RSA_WITH_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_ESTREAM_SALSA20_SHA1,
+                    CipherSuite.TLS_RSA_WITH_SALSA20_SHA1,
+                });
+        }
+
+        protected override ProtocolVersion MaximumVersion
+        {
+            get { return ProtocolVersion.TLSv12; }
+        }
+
+        public override ProtocolVersion GetServerVersion()
+        {
+            ProtocolVersion serverVersion = base.GetServerVersion();
+
+            Console.WriteLine("TLS server negotiated " + serverVersion);
+
+            return serverVersion;
+        }
+
+        public override CertificateRequest GetCertificateRequest()
+        {
+            IList serverSigAlgs = null;
+
+            if (TlsUtilities.IsSignatureAlgorithmsExtensionAllowed(mServerVersion))
+            {
+                byte[] hashAlgorithms = new byte[]{ HashAlgorithm.sha512, HashAlgorithm.sha384, HashAlgorithm.sha256,
+                    HashAlgorithm.sha224, HashAlgorithm.sha1 };
+                byte[] signatureAlgorithms = new byte[]{ SignatureAlgorithm.rsa };
+
+                serverSigAlgs = new ArrayList();
+                for (int i = 0; i < hashAlgorithms.Length; ++i)
+                {
+                    for (int j = 0; j < signatureAlgorithms.Length; ++j)
+                    {
+                        serverSigAlgs.Add(new SignatureAndHashAlgorithm(hashAlgorithms[i],
+                            signatureAlgorithms[j]));
+                    }
+                }
+            }
+
+            IList certificateAuthorities = new ArrayList();
+            certificateAuthorities.Add(TlsTestUtilities.LoadCertificateResource("x509-ca.pem").Subject);
+
+            return new CertificateRequest(new byte[]{ ClientCertificateType.rsa_sign }, serverSigAlgs, certificateAuthorities);
+        }
+
+        public override void NotifyClientCertificate(Certificate clientCertificate)
+        {
+            X509CertificateStructure[] chain = clientCertificate.GetCertificateList();
+            Console.WriteLine("TLS server received client certificate chain of length " + chain.Length);
+            for (int i = 0; i != chain.Length; i++)
+            {
+                X509CertificateStructure entry = chain[i];
+                // TODO Create fingerprint based on certificate signature algorithm digest
+                Console.WriteLine("    fingerprint:SHA-256 " + TlsTestUtilities.Fingerprint(entry) + " ("
+                    + entry.Subject + ")");
+            }
+        }
+
+        protected override TlsEncryptionCredentials GetRsaEncryptionCredentials()
+        {
+            return TlsTestUtilities.LoadEncryptionCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"},
+                "x509-server-key.pem");
+        }
+
+        protected override TlsSignerCredentials GetRsaSignerCredentials()
+        {
+            /*
+             * TODO Note that this code fails to provide default value for the client supported
+             * algorithms if it wasn't sent.
+             */
+            SignatureAndHashAlgorithm signatureAndHashAlgorithm = null;
+            IList sigAlgs = mSupportedSignatureAlgorithms;
+            if (sigAlgs != null)
+            {
+                foreach (SignatureAndHashAlgorithm sigAlg in sigAlgs)
+                {
+                    if (sigAlg.Signature == SignatureAlgorithm.rsa)
+                    {
+                        signatureAndHashAlgorithm = sigAlg;
+                        break;
+                    }
+                }
+
+                if (signatureAndHashAlgorithm == null)
+                {
+                    return null;
+                }
+            }
+
+            return TlsTestUtilities.LoadSignerCredentials(mContext, new string[]{"x509-server.pem", "x509-ca.pem"},
+                "x509-server-key.pem", signatureAndHashAlgorithm);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsClientTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsClientTest.cs
new file mode 100644
index 0000000..c9a5ef9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsClientTest.cs
@@ -0,0 +1,66 @@
+using System;
+using System.IO;
+using System.Net.Sockets;
+using System.Text;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    /**
+     * A simple test designed to conduct a TLS handshake with an external TLS server.
+     * <p/>
+     * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in
+     * this package (under 'src/test/resources') for help configuring an external TLS server.
+     */
+    public class TlsClientTest
+    {
+        private static readonly SecureRandom secureRandom = new SecureRandom();
+
+        public static void Main(string[] args)
+        {
+            string hostname = "localhost";
+            int port = 5556;
+
+            long time1 = DateTime.UtcNow.Ticks;
+
+            MockTlsClient client = new MockTlsClient(null);
+            TlsClientProtocol protocol = OpenTlsConnection(hostname, port, client);
+            protocol.Close();
+
+            long time2 = DateTime.UtcNow.Ticks;
+            Console.WriteLine("Elapsed 1: " + (time2 - time1)/TimeSpan.TicksPerMillisecond + "ms");
+
+            client = new MockTlsClient(client.GetSessionToResume());
+            protocol = OpenTlsConnection(hostname, port, client);
+
+            long time3 = DateTime.UtcNow.Ticks;
+            Console.WriteLine("Elapsed 2: " + (time3 - time2)/TimeSpan.TicksPerMillisecond + "ms");
+
+            byte[] req = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\n\r\n");
+
+            Stream tlsStream = protocol.Stream;
+            tlsStream.Write(req, 0, req.Length);
+            tlsStream.Flush();
+
+            StreamReader reader = new StreamReader(tlsStream);
+
+            String line;
+            while ((line = reader.ReadLine()) != null)
+            {
+                Console.WriteLine(">>> " + line);
+            }
+
+            protocol.Close();
+        }
+
+        internal static TlsClientProtocol OpenTlsConnection(string hostname, int port, TlsClient client)
+        {
+            TcpClient tcp = new TcpClient(hostname, port);
+
+            TlsClientProtocol protocol = new TlsClientProtocol(tcp.GetStream(), secureRandom);
+            protocol.Connect(client);
+            return protocol;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsServerTest.cs b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsServerTest.cs
new file mode 100644
index 0000000..77adf22
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsServerTest.cs
@@ -0,0 +1,78 @@
+using System;
+using System.IO;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    /**
+     * A simple test designed to conduct a TLS handshake with an external TLS client.
+     * <p/>
+     * Please refer to GnuTLSSetup.html or OpenSSLSetup.html (under 'docs'), and x509-*.pem files in
+     * this package (under 'src/test/resources') for help configuring an external TLS client.
+     */
+    public class TlsServerTest
+    {
+        private static readonly SecureRandom secureRandom = new SecureRandom();
+
+        public static void Main(string[] args)
+        {
+            int port = 5556;
+
+            TcpListener ss = new TcpListener(IPAddress.Any, port);
+            ss.Start();
+            Stream stdout = Console.OpenStandardOutput();
+            while (true)
+            {
+                TcpClient s = ss.AcceptTcpClient();
+                Console.WriteLine("--------------------------------------------------------------------------------");
+                Console.WriteLine("Accepted " + s);
+                ServerThread st = new ServerThread(s, stdout);
+                Thread t = new Thread(new ThreadStart(st.Run));
+                t.Start();
+            }
+        }
+
+        internal class ServerThread
+        {
+            private readonly TcpClient s;
+            private readonly Stream stdout;
+
+            internal ServerThread(TcpClient s, Stream stdout)
+            {
+                this.s = s;
+                this.stdout = stdout;
+            }
+
+            public void Run()
+            {
+                try
+                {
+                    MockTlsServer server = new MockTlsServer();
+                    TlsServerProtocol serverProtocol = new TlsServerProtocol(s.GetStream(), secureRandom);
+                    serverProtocol.Accept(server);
+                    Stream log = new TeeOutputStream(serverProtocol.Stream, stdout);
+                    Streams.PipeAll(serverProtocol.Stream, log);
+                    serverProtocol.Close();
+                }
+                finally
+                {
+                    try
+                    {
+                        s.Close();
+                    }
+                    catch (IOException)
+                    {
+                    }
+                    finally
+                    {
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsTestUtilities.cs b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsTestUtilities.cs
new file mode 100644
index 0000000..272dfd4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/crypto/tls/test/TlsTestUtilities.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO.Pem;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Crypto.Tls.Tests
+{
+    public abstract class TlsTestUtilities
+    {
+        internal static readonly byte[] RsaCertData = Base64
+            .Decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
+                + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
+                + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA2MDIwNVoXDTEzMDIyNT"
+                + "A2MDM0NVowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
+                + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
+                + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
+                + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCBSAwEgYDVR"
+                + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAHU55Ncz"
+                + "eglREcTg54YLUlGWu2WOYWhit/iM1eeq8Kivro7q98eW52jTuMI3CI5ulqd0hYzshQKQaZ5GDzErMyM=");
+
+        internal static readonly byte[] DudRsaCertData = Base64
+            .Decode("MIICUzCCAf2gAwIBAgIBATANBgkqhkiG9w0BAQQFADCBjzELMAkGA1UEBhMCQVUxKDAmBgNVBAoMH1RoZSBMZWdpb2"
+                + "4gb2YgdGhlIEJvdW5jeSBDYXN0bGUxEjAQBgNVBAcMCU1lbGJvdXJuZTERMA8GA1UECAwIVmljdG9yaWExLzAtBgkq"
+                + "hkiG9w0BCQEWIGZlZWRiYWNrLWNyeXB0b0Bib3VuY3ljYXN0bGUub3JnMB4XDTEzMDIyNTA1NDcyOFoXDTEzMDIyNT"
+                + "A1NDkwOFowgY8xCzAJBgNVBAYTAkFVMSgwJgYDVQQKDB9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIw"
+                + "EAYDVQQHDAlNZWxib3VybmUxETAPBgNVBAgMCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWVkYmFjay1jcnlwdG"
+                + "9AYm91bmN5Y2FzdGxlLm9yZzBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr5YtqKmKXmEGb4Shy"
+                + "pL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERo0QwQjAOBgNVHQ8BAf8EBAMCAAEwEgYDVR"
+                + "0lAQH/BAgwBgYEVR0lADAcBgNVHREBAf8EEjAQgQ50ZXN0QHRlc3QudGVzdDANBgkqhkiG9w0BAQQFAANBAJg55PBS"
+                + "weg6obRUKF4FF6fCrWFi6oCYSQ99LWcAeupc5BofW5MstFMhCOaEucuGVqunwT5G7/DweazzCIrSzB0=");
+
+        internal static string Fingerprint(X509CertificateStructure c)
+        {
+            byte[] der = c.GetEncoded();
+            byte[] sha1 = Sha256DigestOf(der);
+            byte[] hexBytes = Hex.Encode(sha1);
+            string hex = Encoding.ASCII.GetString(hexBytes).ToUpper(CultureInfo.InvariantCulture);
+
+            StringBuilder fp = new StringBuilder();
+            int i = 0;
+            fp.Append(hex.Substring(i, 2));
+            while ((i += 2) < hex.Length)
+            {
+                fp.Append(':');
+                fp.Append(hex.Substring(i, 2));
+            }
+            return fp.ToString();
+        }
+
+        internal static byte[] Sha256DigestOf(byte[] input)
+        {
+            return DigestUtilities.CalculateDigest("SHA256", input);
+        }
+
+        internal static TlsAgreementCredentials LoadAgreementCredentials(TlsContext context,
+            string[] certResources, string keyResource)
+        {
+            Certificate certificate = LoadCertificateChain(certResources);
+            AsymmetricKeyParameter privateKey = LoadPrivateKeyResource(keyResource);
+
+            return new DefaultTlsAgreementCredentials(certificate, privateKey);
+        }
+
+        internal static TlsEncryptionCredentials LoadEncryptionCredentials(TlsContext context,
+            string[] certResources, string keyResource)
+        {
+            Certificate certificate = LoadCertificateChain(certResources);
+            AsymmetricKeyParameter privateKey = LoadPrivateKeyResource(keyResource);
+
+            return new DefaultTlsEncryptionCredentials(context, certificate, privateKey);
+        }
+
+        internal static TlsSignerCredentials LoadSignerCredentials(TlsContext context, string[] certResources,
+            string keyResource, SignatureAndHashAlgorithm signatureAndHashAlgorithm)
+        {
+            Certificate certificate = LoadCertificateChain(certResources);
+            AsymmetricKeyParameter privateKey = LoadPrivateKeyResource(keyResource);
+
+            return new DefaultTlsSignerCredentials(context, certificate, privateKey, signatureAndHashAlgorithm);
+        }
+
+        internal static Certificate LoadCertificateChain(string[] resources)
+        {
+            X509CertificateStructure[] chain = new X509CertificateStructure[resources.Length];
+            for (int i = 0; i < resources.Length; ++i)
+            {
+                chain[i] = LoadCertificateResource(resources[i]);
+            }
+            return new Certificate(chain);
+        }
+
+        internal static X509CertificateStructure LoadCertificateResource(string resource)
+        {
+            PemObject pem = LoadPemResource(resource);
+            if (pem.Type.EndsWith("CERTIFICATE"))
+            {
+                return X509CertificateStructure.GetInstance(pem.Content);
+            }
+            throw new ArgumentException("doesn't specify a valid certificate", "resource");
+        }
+
+        internal static AsymmetricKeyParameter LoadPrivateKeyResource(string resource)
+        {
+            PemObject pem = LoadPemResource(resource);
+            if (pem.Type.EndsWith("RSA PRIVATE KEY"))
+            {
+                RsaPrivateKeyStructure rsa = RsaPrivateKeyStructure.GetInstance(pem.Content);
+                return new RsaPrivateCrtKeyParameters(rsa.Modulus, rsa.PublicExponent,
+                    rsa.PrivateExponent, rsa.Prime1, rsa.Prime2, rsa.Exponent1,
+                    rsa.Exponent2, rsa.Coefficient);
+            }
+            if (pem.Type.EndsWith("PRIVATE KEY"))
+            {
+                return PrivateKeyFactory.CreateKey(pem.Content);
+            }
+            throw new ArgumentException("doesn't specify a valid private key", "resource");
+        }
+
+        internal static PemObject LoadPemResource(string resource)
+        {
+            Stream s = SimpleTest.GetTestDataAsStream("tls." + resource);
+            PemReader p = new PemReader(new StreamReader(s));
+            PemObject o = p.ReadPemObject();
+            p.Reader.Close();
+            return o;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/AllTests.cs
new file mode 100644
index 0000000..54ccd8f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/AllTests.cs
@@ -0,0 +1,30 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Math.EC.Tests
+{
+    public class AllTests
+    {
+        public static void Main(
+            string[] args)
+        {
+//            junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            suite().Run(el);
+        }
+
+        public static TestSuite suite()
+        {
+            TestSuite suite = new TestSuite("EC Math tests");
+
+            suite.Add(new ECAlgorithmsTest());
+            suite.Add(new ECPointTest());
+
+            return suite;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/ECAlgorithmsTest.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECAlgorithmsTest.cs
new file mode 100644
index 0000000..e98f331
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECAlgorithmsTest.cs
@@ -0,0 +1,153 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Math.EC.Tests
+{
+    [TestFixture]
+    public class ECAlgorithmsTest
+    {
+        private const int SCALE = 4;
+        private static readonly SecureRandom RND = new SecureRandom();
+
+        [Test]
+        [Ignore("SLOW! 44 sec")]
+        public void TestSumOfMultiplies()
+        {
+            foreach (X9ECParameters x9 in GetTestCurves())
+            {
+                ECPoint[] points = new ECPoint[SCALE];
+                BigInteger[] scalars = new BigInteger[SCALE];
+                for (int i = 0; i < SCALE; ++i)
+                {
+                    points[i] = GetRandomPoint(x9);
+                    scalars[i] = GetRandomScalar(x9);
+                }
+
+                ECPoint u = x9.Curve.Infinity;
+                for (int i = 0; i < SCALE; ++i)
+                {
+                    u = u.Add(points[i].Multiply(scalars[i]));
+
+                    ECPoint v = ECAlgorithms.SumOfMultiplies(CopyPoints(points, i + 1), CopyScalars(scalars, i + 1));
+
+                    ECPoint[] results = new ECPoint[] { u, v };
+                    x9.Curve.NormalizeAll(results);
+
+                    AssertPointsEqual("ECAlgorithms.SumOfMultiplies is incorrect", results[0], results[1]);
+                }
+            }
+        }
+
+        [Test]
+        [Ignore("SLOW! 1 min")]
+        public void TestSumOfTwoMultiplies()
+        {
+            foreach (X9ECParameters x9 in GetTestCurves())
+            {
+                ECPoint p = GetRandomPoint(x9);
+                BigInteger a = GetRandomScalar(x9);
+
+                for (int i = 0; i < SCALE; ++i)
+                {
+                    ECPoint q = GetRandomPoint(x9);
+                    BigInteger b = GetRandomScalar(x9);
+
+                    ECPoint u = p.Multiply(a).Add(q.Multiply(b));
+                    ECPoint v = ECAlgorithms.ShamirsTrick(p, a, q, b);
+                    ECPoint w = ECAlgorithms.SumOfTwoMultiplies(p, a, q, b);
+
+                    ECPoint[] results = new ECPoint[] { u, v, w };
+                    x9.Curve.NormalizeAll(results);
+
+                    AssertPointsEqual("ECAlgorithms.ShamirsTrick is incorrect", results[0], results[1]);
+                    AssertPointsEqual("ECAlgorithms.SumOfTwoMultiplies is incorrect", results[0], results[2]);
+
+                    p = q;
+                    a = b;
+                }
+            }
+        }
+
+        private void AssertPointsEqual(string message, ECPoint a, ECPoint b)
+        {
+            Assert.AreEqual(a, b, message);
+        }
+
+        private ECPoint[] CopyPoints(ECPoint[] ps, int len)
+        {
+            ECPoint[] result = new ECPoint[len];
+            Array.Copy(ps, 0, result, 0, len);
+            return result;
+        }
+
+        private BigInteger[] CopyScalars(BigInteger[] ks, int len)
+        {
+            BigInteger[] result = new BigInteger[len];
+            Array.Copy(ks, 0, result, 0, len);
+            return result;
+        }
+
+        private ECPoint GetRandomPoint(X9ECParameters x9)
+        {
+            return x9.G.Multiply(GetRandomScalar(x9));
+        }
+
+        private BigInteger GetRandomScalar(X9ECParameters x9)
+        {
+            return new BigInteger(x9.N.BitLength, RND);
+        }
+
+        private IList GetTestCurves()
+        {
+            ArrayList x9s = new ArrayList();
+            ArrayList names = new ArrayList();
+            CollectionUtilities.AddRange(names, ECNamedCurveTable.Names);
+            CollectionUtilities.AddRange(names, CustomNamedCurves.Names);
+            foreach (string name in names)
+            {
+                X9ECParameters x9 = ECNamedCurveTable.GetByName(name);
+                if (x9 != null)
+                {
+                    AddTestCurves(x9s, x9);
+                }
+
+                x9 = CustomNamedCurves.GetByName(name);
+                if (x9 != null)
+                {
+                    AddTestCurves(x9s, x9);
+                }
+            }
+            return x9s;
+        }
+
+        private void AddTestCurves(IList x9s, X9ECParameters x9)
+        {
+            ECCurve curve = x9.Curve;
+
+            int[] coords = ECCurve.GetAllCoordinateSystems();
+            for (int i = 0; i < coords.Length; ++i)
+            {
+                int coord = coords[i];
+                if (curve.CoordinateSystem == coord)
+                {
+                    x9s.Add(x9);
+                }
+                else if (curve.SupportsCoordinateSystem(coord))
+                {
+                    ECCurve c = curve.Configure().SetCoordinateSystem(coord).Create();
+                    x9s.Add(new X9ECParameters(c, c.ImportPoint(x9.G), x9.N, x9.H));
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointPerformanceTest.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointPerformanceTest.cs
new file mode 100644
index 0000000..5edbd90
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointPerformanceTest.cs
@@ -0,0 +1,210 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Math.EC.Tests
+{
+    /**
+    * Compares the performance of the the window NAF point multiplication against
+    * conventional point multiplication.
+    */
+    [TestFixture, Explicit]
+    public class ECPointPerformanceTest
+    {
+        internal const int MILLIS_PER_ROUND = 200;
+        internal const int MILLIS_WARMUP = 1000;
+
+        internal const int MULTS_PER_CHECK = 16;
+        internal const int NUM_ROUNDS = 10;
+
+        private static string[] COORD_NAMES = new string[]{ "AFFINE", "HOMOGENEOUS", "JACOBIAN", "JACOBIAN-CHUDNOVSKY",
+            "JACOBIAN-MODIFIED", "LAMBDA-AFFINE", "LAMBDA-PROJECTIVE", "SKEWED" };
+
+        private void RandMult(string curveName)
+        {
+            X9ECParameters spec = ECNamedCurveTable.GetByName(curveName);
+            if (spec != null)
+            {
+                RandMult(curveName, spec);
+            }
+
+            spec = CustomNamedCurves.GetByName(curveName);
+            if (spec != null)
+            {
+                RandMult(curveName + " (custom)", spec);
+            }
+        }
+
+        private void RandMult(string label, X9ECParameters spec)
+        {
+            ECCurve C = spec.Curve;
+            ECPoint G = (ECPoint)spec.G;
+            BigInteger n = spec.N;
+
+            SecureRandom random = new SecureRandom();
+            random.SetSeed(DateTimeUtilities.CurrentUnixMs());
+
+            Console.WriteLine(label);
+
+            int[] coords = ECCurve.GetAllCoordinateSystems();
+            for (int i = 0; i < coords.Length; ++i)
+            {
+                int coord = coords[i];
+                if (C.SupportsCoordinateSystem(coord))
+                {
+                    ECCurve c = C;
+                    ECPoint g = G;
+
+                    bool defaultCoord = (c.CoordinateSystem == coord);
+                    if (!defaultCoord)
+                    {
+                        c = C.Configure().SetCoordinateSystem(coord).Create();
+                        g = c.ImportPoint(G);
+                    }
+
+                    double avgRate = RandMult(random, g, n);
+                    string coordName = COORD_NAMES[coord];
+                    StringBuilder sb = new StringBuilder();
+                    sb.Append("   ");
+                    sb.Append(defaultCoord ? '*' : ' ');
+                    sb.Append(coordName);
+                    for (int j = sb.Length; j < 30; ++j)
+                    {
+                        sb.Append(' ');
+                    }
+                    sb.Append(": ");
+                    sb.Append(avgRate);
+                    sb.Append(" mults/sec");
+                    for (int j = sb.Length; j < 64; ++j)
+                    {
+                        sb.Append(' ');
+                    }
+                    sb.Append('(');
+                    sb.Append(1000.0 / avgRate);
+                    sb.Append(" millis/mult)");
+                    Console.WriteLine(sb.ToString());
+                }
+            }
+        }
+
+        private double RandMult(SecureRandom random, ECPoint g, BigInteger n)
+        {
+            BigInteger[] ks = new BigInteger[128];
+            for (int i = 0; i < ks.Length; ++i)
+            {
+                ks[i] = new BigInteger(n.BitLength - 1, random);
+            }
+
+            int ki = 0;
+            ECPoint p = g;
+
+            {
+                long startTime = DateTimeUtilities.CurrentUnixMs();
+                long goalTime = startTime + MILLIS_WARMUP;
+
+                do
+                {
+                    BigInteger k = ks[ki];
+                    p = g.Multiply(k);
+                    if ((ki & 1) != 0)
+                    {
+                        g = p;
+                    }
+                    if (++ki == ks.Length)
+                    {
+                        ki = 0;
+                    }
+                }
+                while (DateTimeUtilities.CurrentUnixMs() < goalTime);
+            }
+
+            double minRate = Double.MaxValue, maxRate = Double.MinValue, totalRate = 0.0;
+
+            for (int i = 1; i <= NUM_ROUNDS; i++)
+            {
+                long startTime = DateTimeUtilities.CurrentUnixMs();
+                long goalTime = startTime + MILLIS_PER_ROUND;
+                long count = 0, endTime;
+
+                do
+                {
+                    ++count;
+
+                    for (int j = 0; j < MULTS_PER_CHECK; ++j)
+                    {
+                        BigInteger k = ks[ki];
+                        p = g.Multiply(k);
+                        if ((ki & 1) != 0)
+                        {
+                            g = p;
+                        }
+                        if (++ki == ks.Length)
+                        {
+                            ki = 0;
+                        }
+                    }
+
+                    endTime = DateTimeUtilities.CurrentUnixMs();
+                }
+                while (endTime < goalTime);
+
+                double roundElapsed = (double)(endTime - startTime);
+                double roundRate = count * MULTS_PER_CHECK * 1000L / roundElapsed;
+
+                minRate = System.Math.Min(minRate, roundRate);
+                maxRate = System.Math.Max(maxRate, roundRate);
+                totalRate += roundRate;
+            }
+
+            return (totalRate - minRate - maxRate) / (NUM_ROUNDS - 2);
+        }
+
+        [Test]
+        [Ignore("SLOW! 15 min")]
+        public void TestMultiply()
+        {
+            ArrayList nameList = new ArrayList();
+            CollectionUtilities.AddRange(nameList, ECNamedCurveTable.Names);
+            CollectionUtilities.AddRange(nameList, CustomNamedCurves.Names);
+
+            string[] names = (string[])nameList.ToArray(typeof(string));
+            Array.Sort(names);
+            ISet oids = new HashSet();
+            foreach (string name in names)
+            {
+                DerObjectIdentifier oid = ECNamedCurveTable.GetOid(name);
+                if (oid == null)
+                {
+                    oid = CustomNamedCurves.GetOid(name);
+                }
+                if (oid != null)
+                {
+                    if (oids.Contains(oid))
+                        continue;
+
+                    oids.Add(oid);
+                }
+
+                RandMult(name);
+            }
+        }
+
+        public static void Main(string[] args)
+        {
+            new ECPointPerformanceTest().TestMultiply();
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointTest.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointTest.cs
new file mode 100644
index 0000000..8430f43
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/ECPointTest.cs
@@ -0,0 +1,507 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto.EC;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Math.EC.Tests
+{
+    /**
+     * Test class for {@link org.bouncycastle.math.ec.ECPoint ECPoint}. All
+     * literature values are taken from "Guide to elliptic curve cryptography",
+     * Darrel Hankerson, Alfred J. Menezes, Scott Vanstone, 2004, Springer-Verlag
+     * New York, Inc.
+     */
+    [TestFixture]
+    public class ECPointTest
+    {
+        /**
+         * Random source used to generate random points
+         */
+        private SecureRandom secRand = new SecureRandom();
+
+//		private ECPointTest.Fp fp = null;
+
+//		private ECPointTest.F2m f2m = null;
+
+        /**
+         * Nested class containing sample literature values for <code>Fp</code>.
+         */
+        public class Fp
+        {
+            internal static readonly BigInteger q = new BigInteger("29");
+
+            internal static readonly BigInteger a = new BigInteger("4");
+
+            internal static readonly BigInteger b = new BigInteger("20");
+
+            internal static readonly BigInteger n = new BigInteger("38");
+
+            internal static readonly BigInteger h = new BigInteger("1");
+
+            internal static readonly ECCurve curve = new FpCurve(q, a, b, n, h);
+
+            internal static readonly ECPoint infinity = curve.Infinity;
+
+            internal static readonly int[] pointSource = { 5, 22, 16, 27, 13, 6, 14, 6 };
+
+            internal static ECPoint[] p = new ECPoint[pointSource.Length / 2];
+
+            /**
+             * Creates the points on the curve with literature values.
+             */
+            internal static void CreatePoints()
+            {
+                for (int i = 0; i < pointSource.Length / 2; i++)
+                {
+                    p[i] = curve.CreatePoint(
+                        new BigInteger(pointSource[2 * i].ToString()),
+                        new BigInteger(pointSource[2 * i + 1].ToString()));
+                }
+            }
+        }
+
+        /**
+         * Nested class containing sample literature values for <code>F2m</code>.
+         */
+        public class F2m
+        {
+            // Irreducible polynomial for TPB z^4 + z + 1
+            internal const int m = 4;
+
+            internal const int k1 = 1;
+
+            // a = z^3
+            internal static readonly BigInteger aTpb = new BigInteger("1000", 2);
+
+            // b = z^3 + 1
+            internal static readonly BigInteger bTpb = new BigInteger("1001", 2);
+
+            internal static readonly BigInteger n = new BigInteger("23");
+
+            internal static readonly BigInteger h = new BigInteger("1");
+
+            internal static readonly ECCurve curve = new F2mCurve(m, k1, aTpb, bTpb, n, h);
+
+            internal static readonly ECPoint infinity = curve.Infinity;
+
+            internal static readonly String[] pointSource = { "0010", "1111", "1100", "1100",
+                    "0001", "0001", "1011", "0010" };
+
+            internal static readonly ECPoint[] p = new ECPoint[pointSource.Length / 2];
+
+            /**
+             * Creates the points on the curve with literature values.
+             */
+            internal static void CreatePoints()
+            {
+                for (int i = 0; i < pointSource.Length / 2; i++)
+                {
+                    p[i] = curve.CreatePoint(
+                        new BigInteger(pointSource[2 * i], 2),
+                        new BigInteger(pointSource[2 * i + 1], 2));
+                }
+            }
+        }
+
+        [SetUp]
+        public void setUp()
+        {
+//			fp = new ECPointTest.Fp();
+            Fp.CreatePoints();
+
+//			f2m = new ECPointTest.F2m();
+            F2m.CreatePoints();
+        }
+
+        /**
+         * Tests, if inconsistent points can be created, i.e. points with exactly
+         * one null coordinate (not permitted).
+         */
+        [Test]
+        public void TestPointCreationConsistency()
+        {
+            try
+            {
+                ECPoint bad = Fp.curve.CreatePoint(BigInteger.ValueOf(12), null);
+                Assert.Fail();
+            }
+            catch (ArgumentException)
+            {
+                // Expected
+            }
+
+            try
+            {
+                ECPoint bad = Fp.curve.CreatePoint(null, BigInteger.ValueOf(12));
+                Assert.Fail();
+            }
+            catch (ArgumentException)
+            {
+                // Expected
+            }
+
+            try
+            {
+                ECPoint bad = F2m.curve.CreatePoint(new BigInteger("1011"), null);
+                Assert.Fail();
+            }
+            catch (ArgumentException)
+            {
+                // Expected
+            }
+
+            try
+            {
+                ECPoint bad = F2m.curve.CreatePoint(null, new BigInteger("1011"));
+                Assert.Fail();
+            }
+            catch (ArgumentException)
+            {
+                // Expected
+            }
+        }
+
+        /**
+         * Tests <code>ECPoint.add()</code> against literature values.
+         *
+         * @param p
+         *            The array of literature values.
+         * @param infinity
+         *            The point at infinity on the respective curve.
+         */
+        private void ImplTestAdd(ECPoint[] p, ECPoint infinity)
+        {
+            AssertPointsEqual("p0 plus p1 does not equal p2", p[2], p[0].Add(p[1]));
+            AssertPointsEqual("p1 plus p0 does not equal p2", p[2], p[1].Add(p[0]));
+            for (int i = 0; i < p.Length; i++)
+            {
+                AssertPointsEqual("Adding infinity failed", p[i], p[i].Add(infinity));
+                AssertPointsEqual("Adding to infinity failed", p[i], infinity.Add(p[i]));
+            }
+        }
+
+        /**
+         * Calls <code>implTestAdd()</code> for <code>Fp</code> and
+         * <code>F2m</code>.
+         */
+        [Test]
+        public void TestAdd()
+        {
+            ImplTestAdd(Fp.p, Fp.infinity);
+            ImplTestAdd(F2m.p, F2m.infinity);
+        }
+
+        /**
+         * Tests <code>ECPoint.twice()</code> against literature values.
+         *
+         * @param p
+         *            The array of literature values.
+         */
+        private void ImplTestTwice(ECPoint[] p)
+        {
+            AssertPointsEqual("Twice incorrect", p[3], p[0].Twice());
+            AssertPointsEqual("Add same point incorrect", p[3], p[0].Add(p[0]));
+        }
+
+        /**
+         * Calls <code>implTestTwice()</code> for <code>Fp</code> and
+         * <code>F2m</code>.
+         */
+        [Test]
+        public void TestTwice()
+        {
+            ImplTestTwice(Fp.p);
+            ImplTestTwice(F2m.p);
+        }
+
+        private void ImplTestThreeTimes(ECPoint[] p)
+        {
+            ECPoint P = p[0];
+            ECPoint _3P = P.Add(P).Add(P);
+            AssertPointsEqual("ThreeTimes incorrect", _3P, P.ThreeTimes());
+            AssertPointsEqual("TwicePlus incorrect", _3P, P.TwicePlus(P));
+        }
+
+        /**
+         * Calls <code>implTestThreeTimes()</code> for <code>Fp</code> and
+         * <code>F2m</code>.
+         */
+        [Test]
+        public void TestThreeTimes()
+        {
+            ImplTestThreeTimes(Fp.p);
+            ImplTestThreeTimes(F2m.p);
+        }
+
+        /**
+         * Goes through all points on an elliptic curve and checks, if adding a
+         * point <code>k</code>-times is the same as multiplying the point by
+         * <code>k</code>, for all <code>k</code>. Should be called for points
+         * on very small elliptic curves only.
+         *
+         * @param p
+         *            The base point on the elliptic curve.
+         * @param infinity
+         *            The point at infinity on the elliptic curve.
+         */
+        private void ImplTestAllPoints(ECPoint p, ECPoint infinity)
+        {
+            ECPoint adder = infinity;
+            ECPoint multiplier = infinity;
+
+            BigInteger i = BigInteger.One;
+            do
+            {
+                adder = adder.Add(p);
+                multiplier = p.Multiply(i);
+                AssertPointsEqual("Results of Add() and Multiply() are inconsistent " + i, adder, multiplier);
+                i = i.Add(BigInteger.One);
+            }
+            while (!(adder.Equals(infinity)));
+        }
+
+        /**
+         * Calls <code>implTestAllPoints()</code> for the small literature curves,
+         * both for <code>Fp</code> and <code>F2m</code>.
+         */
+        [Test]
+        public void TestAllPoints()
+        {
+            for (int i = 0; i < Fp.p.Length; i++)
+            {
+                ImplTestAllPoints(Fp.p[0], Fp.infinity);
+            }
+
+            for (int i = 0; i < F2m.p.Length; i++)
+            {
+                ImplTestAllPoints(F2m.p[0], F2m.infinity);
+            }
+        }
+
+        /**
+         * Checks, if the point multiplication algorithm of the given point yields
+         * the same result as point multiplication done by the reference
+         * implementation given in <code>multiply()</code>. This method chooses a
+         * random number by which the given point <code>p</code> is multiplied.
+         *
+         * @param p
+         *            The point to be multiplied.
+         * @param numBits
+         *            The bitlength of the random number by which <code>p</code>
+         *            is multiplied.
+         */
+        private void ImplTestMultiply(ECPoint p, int numBits)
+        {
+            BigInteger k = new BigInteger(numBits, secRand);
+            ECPoint reff = ECAlgorithms.ReferenceMultiply(p, k);
+            ECPoint q = p.Multiply(k);
+            AssertPointsEqual("ECPoint.Multiply is incorrect", reff, q);
+        }
+
+        /**
+         * Checks, if the point multiplication algorithm of the given point yields
+         * the same result as point multiplication done by the reference
+         * implementation given in <code>multiply()</code>. This method tests
+         * multiplication of <code>p</code> by every number of bitlength
+         * <code>numBits</code> or less.
+         *
+         * @param p
+         *            The point to be multiplied.
+         * @param numBits
+         *            Try every multiplier up to this bitlength
+         */
+        private void ImplTestMultiplyAll(ECPoint p, int numBits)
+        {
+            BigInteger bound = BigInteger.One.ShiftLeft(numBits);
+            BigInteger k = BigInteger.Zero;
+
+            do
+            {
+                ECPoint reff = ECAlgorithms.ReferenceMultiply(p, k);
+                ECPoint q = p.Multiply(k);
+                AssertPointsEqual("ECPoint.Multiply is incorrect", reff, q);
+                k = k.Add(BigInteger.One);
+            }
+            while (k.CompareTo(bound) < 0);
+        }
+
+        /**
+         * Tests <code>ECPoint.add()</code> and <code>ECPoint.subtract()</code>
+         * for the given point and the given point at infinity.
+         *
+         * @param p
+         *            The point on which the tests are performed.
+         * @param infinity
+         *            The point at infinity on the same curve as <code>p</code>.
+         */
+        private void ImplTestAddSubtract(ECPoint p, ECPoint infinity)
+        {
+            AssertPointsEqual("Twice and Add inconsistent", p.Twice(), p.Add(p));
+            AssertPointsEqual("Twice p - p is not p", p, p.Twice().Subtract(p));
+            AssertPointsEqual("TwicePlus(p, -p) is not p", p, p.TwicePlus(p.Negate()));
+            AssertPointsEqual("p - p is not infinity", infinity, p.Subtract(p));
+            AssertPointsEqual("p plus infinity is not p", p, p.Add(infinity));
+            AssertPointsEqual("infinity plus p is not p", p, infinity.Add(p));
+            AssertPointsEqual("infinity plus infinity is not infinity ", infinity, infinity.Add(infinity));
+            AssertPointsEqual("Twice infinity is not infinity ", infinity, infinity.Twice());
+        }
+
+        /**
+         * Calls <code>implTestAddSubtract()</code> for literature values, both
+         * for <code>Fp</code> and <code>F2m</code>.
+         */
+        [Test]
+        public void TestAddSubtractMultiplySimple()
+        {
+            int fpBits = Fp.curve.Order.BitLength;
+            for (int iFp = 0; iFp < Fp.pointSource.Length / 2; iFp++)
+            {
+                ImplTestAddSubtract(Fp.p[iFp], Fp.infinity);
+
+                ImplTestMultiplyAll(Fp.p[iFp], fpBits);
+                ImplTestMultiplyAll(Fp.infinity, fpBits);
+            }
+
+            int f2mBits = F2m.curve.Order.BitLength;
+            for (int iF2m = 0; iF2m < F2m.pointSource.Length / 2; iF2m++)
+            {
+                ImplTestAddSubtract(F2m.p[iF2m], F2m.infinity);
+
+                ImplTestMultiplyAll(F2m.p[iF2m], f2mBits);
+                ImplTestMultiplyAll(F2m.infinity, f2mBits);
+            }
+        }
+
+        /**
+         * Test encoding with and without point compression.
+         *
+         * @param p
+         *            The point to be encoded and decoded.
+         */
+        private void ImplTestEncoding(ECPoint p)
+        {
+            // Not Point Compression
+            byte[] unCompBarr = p.GetEncoded(false);
+            ECPoint decUnComp = p.Curve.DecodePoint(unCompBarr);
+            AssertPointsEqual("Error decoding uncompressed point", p, decUnComp);
+
+            // Point compression
+            byte[] compBarr = p.GetEncoded(true);
+            ECPoint decComp = p.Curve.DecodePoint(compBarr);
+            AssertPointsEqual("Error decoding compressed point", p, decComp);
+        }
+
+        private void ImplAddSubtractMultiplyTwiceEncodingTest(ECCurve curve, ECPoint q, BigInteger n)
+        {
+            // Get point at infinity on the curve
+            ECPoint infinity = curve.Infinity;
+
+            ImplTestAddSubtract(q, infinity);
+            ImplTestMultiply(q, n.BitLength);
+            ImplTestMultiply(infinity, n.BitLength);
+
+            ECPoint p = q;
+            for (int i = 0; i < 10; ++i)
+            {
+                ImplTestEncoding(p);
+                p = p.Twice();
+            }
+        }
+
+        private void ImplSqrtTest(ECCurve c)
+        {
+            if (ECAlgorithms.IsFpCurve(c))
+            {
+                BigInteger p = c.Field.Characteristic;
+                BigInteger pMinusOne = p.Subtract(BigInteger.One);
+                BigInteger legendreExponent = p.ShiftRight(1);
+
+                int count = 0;
+                while (count < 10)
+                {
+                    BigInteger nonSquare = BigIntegers.CreateRandomInRange(BigInteger.Two, pMinusOne, secRand);
+                    if (!nonSquare.ModPow(legendreExponent, p).Equals(BigInteger.One))
+                    {
+                        ECFieldElement root = c.FromBigInteger(nonSquare).Sqrt();
+                        Assert.IsNull(root);
+                        ++count;
+                    }
+                }
+            }
+        }
+
+        private void ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(X9ECParameters x9ECParameters)
+        {
+            BigInteger n = x9ECParameters.N;
+            ECPoint G = x9ECParameters.G;
+            ECCurve C = x9ECParameters.Curve;
+
+            int[] coords = ECCurve.GetAllCoordinateSystems();
+            for (int i = 0; i < coords.Length; ++i)
+            {
+                int coord = coords[i];
+                if (C.SupportsCoordinateSystem(coord))
+                {
+                    ECCurve c = C;
+                    ECPoint g = G;
+
+                    if (c.CoordinateSystem != coord)
+                    {
+                        c = C.Configure().SetCoordinateSystem(coord).Create();
+                        g = c.ImportPoint(G);
+                    }
+
+                    // The generator is multiplied by random b to get random q
+                    BigInteger b = new BigInteger(n.BitLength, secRand);
+                    ECPoint q = g.Multiply(b).Normalize();
+
+                    ImplAddSubtractMultiplyTwiceEncodingTest(c, q, n);
+
+                    ImplSqrtTest(c);
+                }
+            }
+        }
+
+        /**
+         * Calls <code>implTestAddSubtract()</code>,
+         * <code>implTestMultiply</code> and <code>implTestEncoding</code> for
+         * the standard elliptic curves as given in <code>SecNamedCurves</code>.
+         */
+        [Test]
+        public void TestAddSubtractMultiplyTwiceEncoding()
+        {
+            ArrayList names = new ArrayList();
+            CollectionUtilities.AddRange(names, ECNamedCurveTable.Names);
+            CollectionUtilities.AddRange(names, CustomNamedCurves.Names);
+
+            foreach (string name in names)
+            {
+                X9ECParameters x9ECParameters = ECNamedCurveTable.GetByName(name);
+                if (x9ECParameters != null)
+                {
+                    ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
+                }
+
+                x9ECParameters = CustomNamedCurves.GetByName(name);
+                if (x9ECParameters != null)
+                {
+                    ImplAddSubtractMultiplyTwiceEncodingTestAllCoords(x9ECParameters);
+                }
+            }
+        }
+
+        private void AssertPointsEqual(string message, ECPoint a, ECPoint b)
+        {
+            Assert.AreEqual(a, b, message);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/F2mProofer.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/F2mProofer.cs
new file mode 100644
index 0000000..727d32c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/F2mProofer.cs
@@ -0,0 +1,201 @@
+// TODO Need a replacement for the Java properties class to finish this class
+
+//using System;
+//using System.IO;
+//using System.Text;
+//
+//using Org.BouncyCastle.Asn1.Sec;
+//using Org.BouncyCastle.Asn1.X9;
+//using Org.BouncyCastle.Math.EC;
+//using Org.BouncyCastle.Security;
+//
+//namespace Org.BouncyCastle.Math.EC.Tests
+//{
+//	public class F2mProofer
+//	{
+//		private const int NUM_SAMPLES = 1000;
+//
+//		private static readonly string PATH = "crypto/test/src/org/bouncycastle/math/ec/test/samples/";
+//
+//		private static readonly string INPUT_FILE_NAME_PREFIX = "Input_";
+//
+//		private static readonly string RESULT_FILE_NAME_PREFIX = "Output_";
+//
+//		/**
+//		* The standard curves on which the tests are done
+//		*/
+//		public static readonly string[] Curves = { "sect163r2", "sect233r1",
+//			"sect283r1", "sect409r1", "sect571r1" };
+//
+//		private string pointToString(F2mPoint p)
+//		{
+//			F2mFieldElement x = (F2mFieldElement) p.X;
+//			F2mFieldElement y = (F2mFieldElement) p.Y;
+//
+//			int m = x.M;
+//			int len = m / 2 + 5;
+//
+//			StringBuilder sb = new StringBuilder(len);
+//			sb.Append('(');
+//			sb.Append(x.ToBigInteger().ToString(16));
+//			sb.Append(", ");
+//			sb.Append(y.ToBigInteger().ToString(16));
+//			sb.Append(')');
+//
+//			return sb.ToString();
+//		}
+//
+//		private void generateRandomInput(X9ECParameters x9ECParameters)
+//		{
+//			F2mPoint g = (F2mPoint) x9ECParameters.G;
+//			int m = ((F2mFieldElement) g.X).M;
+//
+//			SecureRandom secRand = new SecureRandom(); //SecureRandom.GetInstance("SHA1PRNG");
+//			Properties inputProps = new Properties();
+//			for (int i = 0; i < NUM_SAMPLES; i++)
+//			{
+//				BigInteger rand = new BigInteger(m, secRand);
+//				inputProps.put(i.ToString(), rand.ToString(16));
+//			}
+//			string bits = m.ToString();
+//			FileStream fos = File.Create(PATH
+//				+ INPUT_FILE_NAME_PREFIX + bits + ".properties");
+//			inputProps.store(fos, "Input Samples of length" + bits);
+//			fos.Close();
+//		}
+//
+//		private void multiplyPoints(X9ECParameters x9ECParameters,
+//			string classPrefix)
+//		{
+//			F2mPoint g = (F2mPoint) x9ECParameters.G;
+//			int m = ((F2mFieldElement) g.X).M;
+//
+//			string inputFileName = PATH + INPUT_FILE_NAME_PREFIX + m
+//				+ ".properties";
+//			Properties inputProps = new Properties();
+//			FileStream fis = File.OpenRead(inputFileName); 
+//			inputProps.load(fis);
+//			fis.Close();
+//
+//			Properties outputProps = new Properties();
+//
+//			for (int i = 0; i < NUM_SAMPLES; i++)
+//			{
+//				BigInteger rand = new BigInteger(inputProps.getProperty(Integer
+//					.ToString(i)), 16);
+//				F2mPoint result = (F2mPoint) g.Multiply(rand).normalize();
+//				string resultStr = pointToString(result);
+//				outputProps.setProperty(i.ToString(), resultStr);
+//			}
+//
+//			string outputFileName = PATH + RESULT_FILE_NAME_PREFIX + classPrefix
+//				+ "_" + m + ".properties";
+//			FileStream fos = File.Create(outputFileName);
+//			outputProps.store(fos, "Output Samples of length" + m);
+//			fos.Close();
+//		}
+//
+//		private Properties loadResults(string classPrefix, int m)
+//		{
+//			FileStream fis = File.OpenRead(PATH
+//				+ RESULT_FILE_NAME_PREFIX + classPrefix + "_" + m + ".properties");
+//			Properties res = new Properties();
+//			res.load(fis);
+//			fis.Close();
+//			return res;
+//		}
+//
+//		private void compareResult(X9ECParameters x9ECParameters,
+//			string classPrefix1, string classPrefix2)
+//		{
+//			F2mPoint g = (F2mPoint) x9ECParameters.G;
+//			int m = ((F2mFieldElement) g.X).M;
+//
+//			Properties res1 = loadResults(classPrefix1, m);
+//			Properties res2 = loadResults(classPrefix2, m);
+//
+//			Set keys = res1.keySet();
+//			Iterator iter = keys.iterator();
+//			while (iter.hasNext())
+//			{
+//				string key = (string) iter.next();
+//				string result1 = res1.getProperty(key);
+//				string result2 = res2.getProperty(key);
+//				if (!(result1.Equals(result2)))
+//				{
+//					Console.Error.WriteLine("Difference found: m = " + m + ", "
+//						+ result1 + " does not equal " + result2);
+//				}
+//			}
+//
+//		}
+//
+//		private static void usage()
+//		{
+//			Console.Error.WriteLine("Usage: F2mProofer [-init | -Multiply <className> "
+//				+ "| -compare <className1> <className2>]");
+//		}
+//
+//		public static void Main(string[] args)
+//		{
+//			if (args.Length == 0)
+//			{
+//				usage();
+//				return;
+//			}
+//			F2mProofer proofer = new F2mProofer();
+//			if (args[0].Equals("-init"))
+//			{
+//				Console.WriteLine("Generating random input...");
+//				for (int i = 0; i < Curves.Length; i++)
+//				{
+//					X9ECParameters x9ECParameters = SecNamedCurves
+//						.GetByName(Curves[i]);
+//					proofer.generateRandomInput(x9ECParameters);
+//				}
+//				Console.WriteLine("Successfully generated random input in " + PATH);
+//			}
+//			else if (args[0].Equals("-compare"))
+//			{
+//				if (args.Length < 3)
+//				{
+//					usage();
+//					return;
+//				}
+//				string classPrefix1 = args[1];
+//				string classPrefix2 = args[2];
+//				Console.WriteLine("Comparing results...");
+//				for (int i = 0; i < Curves.Length; i++)
+//				{
+//					X9ECParameters x9ECParameters = SecNamedCurves
+//						.GetByName(Curves[i]);
+//					proofer.compareResult(x9ECParameters, classPrefix1,
+//						classPrefix2);
+//				}
+//				Console.WriteLine("Successfully compared results in " + PATH);
+//			}
+//			else if (args[0].Equals("-Multiply"))
+//			{
+//				if (args.Length < 2)
+//				{
+//					usage();
+//					return;
+//				}
+//				string classPrefix = args[1];
+//				Console.WriteLine("Multiplying points...");
+//				for (int i = 0; i < Curves.Length; i++)
+//				{
+//					X9ECParameters x9ECParameters = SecNamedCurves
+//						.GetByName(Curves[i]);
+//					proofer.multiplyPoints(x9ECParameters, classPrefix);
+//				}
+//				Console.WriteLine("Successfully generated multiplied points in "
+//					+ PATH);
+//			}
+//			else
+//			{
+//				usage();
+//			}
+//		}
+//	}
+//}
diff --git a/BouncyCastle.AxCrypt/test/src/math/ec/test/TnafTest.cs b/BouncyCastle.AxCrypt/test/src/math/ec/test/TnafTest.cs
new file mode 100644
index 0000000..c04ae00
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/ec/test/TnafTest.cs
@@ -0,0 +1,158 @@
+//using System;
+//using System.Text;
+//
+//using NUnit.Framework;
+//
+//using Org.BouncyCastle.Asn1.Sec;
+//using Org.BouncyCastle.Asn1.X9;
+//using Org.BouncyCastle.Math.EC.Multiplier;
+//using Org.BouncyCastle.Utilities.Date;
+//
+//namespace Org.BouncyCastle.Math.EC.Tests
+//{
+//	[TestFixture, Explicit]
+//	public class TnafTest
+//	{
+//		private Random m_rand = new Random();
+//
+//		private string ecPointToString(
+//			ECPoint p) 
+//		{
+//			StringBuilder sb = new StringBuilder("x = ");
+//			sb.Append(p.X.ToBigInteger().ToString());
+//			sb.Append("; y = ");
+//			sb.Append(p.Y.ToBigInteger().ToString());
+//			return sb.ToString();
+//		}
+//
+//		private ECPoint repeatedMultiply(ECPoint p, BigInteger k)
+//		{
+//			ECPoint result = p.Multiply(k);
+//			for (int i = 1; i < 10; ++i)
+//			{
+//				ECPoint check = p.Multiply(k);
+//				Assert.AreEqual(result, check);
+//			}
+//			return result;
+//		}
+//
+//		private void ImplTestMultiplyTnaf(string curveName) 
+//		{
+//			X9ECParameters x9ECParameters = SecNamedCurves.GetByName(curveName);
+//
+//			F2mCurve curve = (F2mCurve)x9ECParameters.Curve;
+//			BigInteger n = curve.N;
+//
+//			// The generator is multiplied by random b to get random q
+//			BigInteger b = new BigInteger(n.BitLength, m_rand);
+//			ECPoint g = x9ECParameters.G;
+//			F2mPoint p = (F2mPoint) g.Multiply(b);
+//
+//			BigInteger k = new BigInteger(n.BitLength, m_rand);
+//			long now1 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new WTauNafMultiplier());
+//			ECPoint refRWTnaf = repeatedMultiply(p, k);
+//			long now2 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new WNafMultiplier());
+//			ECPoint refWnaf = repeatedMultiply(p, k);
+//			long now3 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new FpNafMultiplier());
+//			ECPoint refFpNaf = repeatedMultiply(p, k);
+//			long now4 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new ReferenceMultiplier());
+//			ECPoint reference = repeatedMultiply(p, k);
+//			long now5 = DateTimeUtilities.CurrentUnixMs();
+//
+//			Assert.AreEqual(reference, refRWTnaf, "WTNAF multiplication is incorrect");
+//			Assert.AreEqual(reference, refFpNaf, "FPNAF multiplication is incorrect");
+//			Assert.AreEqual(reference, refWnaf, "WNAF multiplication is incorrect");
+//
+//			Console.WriteLine(curveName + ": Multiply WTNAF took millis:  " + (now2 - now1));
+//			Console.WriteLine(curveName + ": Multiply WNAF took millis:   " + (now3 - now2));
+//			Console.WriteLine(curveName + ": Multiply FPNAF took millis:  " + (now4 - now3));
+//			Console.WriteLine(curveName + ": Multiply REFE took millis:   " + (now5 - now4));
+//
+////			Console.WriteLine(curveName + ": refRWTnaf  = " + ecPointToString(refRWTnaf));
+////			Console.WriteLine(curveName + ": refWnaf    = " + ecPointToString(refWnaf));
+////			Console.WriteLine(curveName + ": refFpNaf   = " + ecPointToString(refFpNaf));
+////			Console.WriteLine(curveName + ": reference  = " + ecPointToString(reference) + "\n");
+//			Console.WriteLine();
+//		}
+//
+//		[Test]
+//		public void TestMultiplyTnaf() 
+//		{
+//			Console.WriteLine("\n\n\n*****  Start test multiplications on F2m (Koblitz) *****");
+//			ImplTestMultiplyTnaf("sect163k1");
+//			ImplTestMultiplyTnaf("sect233k1");
+//			ImplTestMultiplyTnaf("sect239k1");
+//			ImplTestMultiplyTnaf("sect283k1");
+//			ImplTestMultiplyTnaf("sect409k1");
+//			ImplTestMultiplyTnaf("sect571k1");
+//		}
+//
+//		private void ImplTestMultiplyWnaf(String curveName) 
+//		{
+//			X9ECParameters x9ECParameters = SecNamedCurves.GetByName(curveName);
+//
+//			BigInteger r = x9ECParameters.N;
+//
+//			// The generator is multiplied by random b to get random q
+//			BigInteger b = new BigInteger(r.BitLength, m_rand);
+//			ECPoint g = x9ECParameters.G;
+//			ECPoint p = g.Multiply(b);
+//
+//			BigInteger k = new BigInteger(r.BitLength, m_rand);
+//			long now1 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new WNafMultiplier());
+//			ECPoint refWnaf = repeatedMultiply(p, k);
+//			long now2 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new FpNafMultiplier());
+//			ECPoint refFpNaf = repeatedMultiply(p, k);
+//			long now3 = DateTimeUtilities.CurrentUnixMs();
+//			p.SetECMultiplier(new ReferenceMultiplier());
+//			ECPoint reference = repeatedMultiply(p, k);
+//			long now4 = DateTimeUtilities.CurrentUnixMs();
+//
+//			Assert.AreEqual(reference, refWnaf, "WNAF multiplication is incorrect");
+//			Assert.AreEqual(reference, refFpNaf, "FPNAF multiplication is incorrect");
+//
+//			Console.WriteLine(curveName + ": Multiply WNAF took millis:   " + (now2 - now1));
+//			Console.WriteLine(curveName + ": Multiply FPNAF took millis:  " + (now3 - now2));
+//			Console.WriteLine(curveName + ": Multiply REFE took millis:   " + (now4 - now3));
+//
+////			Console.WriteLine(curveName + ": refWnaf    = " + ecPointToString(refWnaf));
+////			Console.WriteLine(curveName + ": refFpNaf   = " + ecPointToString(refFpNaf));
+////			Console.WriteLine(curveName + ": reference  = " + ecPointToString(reference));
+//			Console.WriteLine();
+//		}
+//
+//		[Test]
+//		public void TestMultiplyWnaf() 
+//		{
+//			Console.WriteLine("\n\n\n*****  Start test multiplications on F2m *****");
+//			ImplTestMultiplyWnaf("sect113r1");
+//			ImplTestMultiplyWnaf("sect113r2");
+//			ImplTestMultiplyWnaf("sect131r1");
+//			ImplTestMultiplyWnaf("sect131r2");
+//			ImplTestMultiplyWnaf("sect163r1");
+//			ImplTestMultiplyWnaf("sect163r2");
+//			ImplTestMultiplyWnaf("sect193r1");
+//			ImplTestMultiplyWnaf("sect193r2");
+//			ImplTestMultiplyWnaf("sect233r1");
+//			ImplTestMultiplyWnaf("sect283r1");
+//			ImplTestMultiplyWnaf("sect409r1");
+//			ImplTestMultiplyWnaf("sect571r1");
+//
+//			Console.WriteLine("\n\n\n*****  Start test multiplications on Fp  *****");
+//			ImplTestMultiplyWnaf("secp112r1");
+//			ImplTestMultiplyWnaf("secp128r1");
+//			ImplTestMultiplyWnaf("secp160r1");
+//			ImplTestMultiplyWnaf("secp192r1");
+//			ImplTestMultiplyWnaf("secp224r1");
+//			ImplTestMultiplyWnaf("secp256r1");
+//			ImplTestMultiplyWnaf("secp384r1");
+//			ImplTestMultiplyWnaf("secp521r1");
+//		}
+//	}
+//}
diff --git a/BouncyCastle.AxCrypt/test/src/math/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/math/test/AllTests.cs
new file mode 100644
index 0000000..4af8952
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/test/AllTests.cs
@@ -0,0 +1,29 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Math.Tests
+{
+    public class AllTests
+    {
+        public static void Main(
+			string[] args)
+        {
+//            junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            suite().Run(el);
+        }
+
+        public static TestSuite suite()
+        {
+			TestSuite suite = new TestSuite("Math tests");
+
+			suite.Add(new BigIntegerTest());
+
+			return suite;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/math/test/BigIntegerTest.cs b/BouncyCastle.AxCrypt/test/src/math/test/BigIntegerTest.cs
new file mode 100644
index 0000000..8196cc6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/math/test/BigIntegerTest.cs
@@ -0,0 +1,1048 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Math.Tests
+{
+    [TestFixture]
+    public class BigIntegerTest
+    {
+        private static Random random = new Random();
+
+        [Test]
+        public void MonoBug81857()
+        {
+            BigInteger b = new BigInteger("18446744073709551616");
+            BigInteger exp = BigInteger.Two;
+            BigInteger mod = new BigInteger("48112959837082048697");
+            BigInteger expected = new BigInteger("4970597831480284165");
+
+            BigInteger manual = b.Multiply(b).Mod(mod);
+            Assert.AreEqual(expected, manual, "b * b % mod");
+        }
+
+        [Test]
+        public void TestAbs()
+        {
+            Assert.AreEqual(zero, zero.Abs());
+
+            Assert.AreEqual(one, one.Abs());
+            Assert.AreEqual(one, minusOne.Abs());
+
+            Assert.AreEqual(two, two.Abs());
+            Assert.AreEqual(two, minusTwo.Abs());
+        }
+
+        [Test]
+        public void TestAdd()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i + j),
+                        val(i).Add(val(j)),
+                        "Problem: " + i + ".Add(" + j + ") should be " + (i + j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestAnd()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i & j),
+                        val(i).And(val(j)),
+                        "Problem: " + i + " AND " + j + " should be " + (i & j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestAndNot()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i & ~j),
+                        val(i).AndNot(val(j)),
+                        "Problem: " + i + " AND NOT " + j + " should be " + (i & ~j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestBitCount()
+        {
+            Assert.AreEqual(0, zero.BitCount);
+            Assert.AreEqual(1, one.BitCount);
+            Assert.AreEqual(0, minusOne.BitCount);
+            Assert.AreEqual(1, two.BitCount);
+            Assert.AreEqual(1, minusTwo.BitCount);
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger pow2 = one.ShiftLeft(i);
+
+                Assert.AreEqual(1, pow2.BitCount);
+                Assert.AreEqual(i, pow2.Negate().BitCount);
+            }
+
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger test = new BigInteger(128, 0, random);
+                int bitCount = 0;
+
+                for (int bit = 0; bit < test.BitLength; ++bit)
+                {
+                    if (test.TestBit(bit))
+                    {
+                        ++bitCount;
+                    }
+                }
+
+                Assert.AreEqual(bitCount, test.BitCount);
+            }
+        }
+
+        [Test]
+        public void TestBitLength()
+        {
+            Assert.AreEqual(0, zero.BitLength);
+            Assert.AreEqual(1, one.BitLength);
+            Assert.AreEqual(0, minusOne.BitLength);
+            Assert.AreEqual(2, two.BitLength);
+            Assert.AreEqual(1, minusTwo.BitLength);
+
+            for (int i = 0; i < 100; ++i)
+            {
+                int bit = i + random.Next(64);
+                BigInteger odd = new BigInteger(bit, random).SetBit(bit + 1).SetBit(0);
+                BigInteger pow2 = one.ShiftLeft(bit);
+
+                Assert.AreEqual(bit + 2, odd.BitLength);
+                Assert.AreEqual(bit + 2, odd.Negate().BitLength);
+                Assert.AreEqual(bit + 1, pow2.BitLength);
+                Assert.AreEqual(bit, pow2.Negate().BitLength);
+            }
+        }
+
+        [Test]
+        public void TestClearBit()
+        {
+            Assert.AreEqual(zero, zero.ClearBit(0));
+            Assert.AreEqual(zero, one.ClearBit(0));
+            Assert.AreEqual(two, two.ClearBit(0));
+
+            Assert.AreEqual(zero, zero.ClearBit(1));
+            Assert.AreEqual(one, one.ClearBit(1));
+            Assert.AreEqual(zero, two.ClearBit(1));
+
+            // TODO Tests for clearing bits in negative numbers
+
+            // TODO Tests for clearing extended bits
+
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger n = new BigInteger(128, random);
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    int pos = random.Next(128);
+                    BigInteger m = n.ClearBit(pos);
+                    bool test = m.ShiftRight(pos).Remainder(two).Equals(one);
+
+                    Assert.IsFalse(test);
+                }
+            }
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger pow2 = one.ShiftLeft(i);
+                BigInteger minusPow2 = pow2.Negate();
+
+                Assert.AreEqual(zero, pow2.ClearBit(i));
+                Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.ClearBit(i));
+
+                BigInteger bigI = BigInteger.ValueOf(i);
+                BigInteger negI = bigI.Negate();
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    string data = "i=" + i + ", j=" + j;
+                    Assert.AreEqual(bigI.AndNot(one.ShiftLeft(j)), bigI.ClearBit(j), data);
+                    Assert.AreEqual(negI.AndNot(one.ShiftLeft(j)), negI.ClearBit(j), data);
+                }
+            }
+        }
+
+        [Test]
+        public void TestCompareTo()
+        {
+            Assert.AreEqual(0, minusTwo.CompareTo(minusTwo));
+            Assert.AreEqual(-1, minusTwo.CompareTo(minusOne));
+            Assert.AreEqual(-1, minusTwo.CompareTo(zero));
+            Assert.AreEqual(-1, minusTwo.CompareTo(one));
+            Assert.AreEqual(-1, minusTwo.CompareTo(two));
+
+            Assert.AreEqual(1, minusOne.CompareTo(minusTwo));
+            Assert.AreEqual(0, minusOne.CompareTo(minusOne));
+            Assert.AreEqual(-1, minusOne.CompareTo(zero));
+            Assert.AreEqual(-1, minusOne.CompareTo(one));
+            Assert.AreEqual(-1, minusOne.CompareTo(two));
+
+            Assert.AreEqual(1, zero.CompareTo(minusTwo));
+            Assert.AreEqual(1, zero.CompareTo(minusOne));
+            Assert.AreEqual(0, zero.CompareTo(zero));
+            Assert.AreEqual(-1, zero.CompareTo(one));
+            Assert.AreEqual(-1, zero.CompareTo(two));
+
+            Assert.AreEqual(1, one.CompareTo(minusTwo));
+            Assert.AreEqual(1, one.CompareTo(minusOne));
+            Assert.AreEqual(1, one.CompareTo(zero));
+            Assert.AreEqual(0, one.CompareTo(one));
+            Assert.AreEqual(-1, one.CompareTo(two));
+
+            Assert.AreEqual(1, two.CompareTo(minusTwo));
+            Assert.AreEqual(1, two.CompareTo(minusOne));
+            Assert.AreEqual(1, two.CompareTo(zero));
+            Assert.AreEqual(1, two.CompareTo(one));
+            Assert.AreEqual(0, two.CompareTo(two));
+        }
+
+        [Test]
+        public void TestConstructors()
+        {
+            Assert.AreEqual(BigInteger.Zero, new BigInteger(new byte[]{ 0 }));
+            Assert.AreEqual(BigInteger.Zero, new BigInteger(new byte[]{ 0, 0 }));
+
+            for (int i = 0; i < 10; ++i)
+            {
+                Assert.IsTrue(new BigInteger(i + 3, 0, random).TestBit(0));
+            }
+
+            // TODO Other constructors
+        }
+
+        [Test]
+        public void TestDivide()
+        {
+            for (int i = -5; i <= 5; ++i)
+            {
+                try
+                {
+                    val(i).Divide(zero);
+                    Assert.Fail("expected ArithmeticException");
+                }
+                catch (ArithmeticException) {}
+            }
+
+            int product = 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9;
+            int productPlus = product + 1;
+
+            BigInteger bigProduct = val(product);
+            BigInteger bigProductPlus = val(productPlus);
+
+            for (int divisor = 1; divisor < 10; ++divisor)
+            {
+                // Exact division
+                BigInteger expected = val(product / divisor);
+
+                Assert.AreEqual(expected, bigProduct.Divide(val(divisor)));
+                Assert.AreEqual(expected.Negate(), bigProduct.Negate().Divide(val(divisor)));
+                Assert.AreEqual(expected.Negate(), bigProduct.Divide(val(divisor).Negate()));
+                Assert.AreEqual(expected, bigProduct.Negate().Divide(val(divisor).Negate()));
+
+                expected = val((product + 1)/divisor);
+
+                Assert.AreEqual(expected, bigProductPlus.Divide(val(divisor)));
+                Assert.AreEqual(expected.Negate(), bigProductPlus.Negate().Divide(val(divisor)));
+                Assert.AreEqual(expected.Negate(), bigProductPlus.Divide(val(divisor).Negate()));
+                Assert.AreEqual(expected, bigProductPlus.Negate().Divide(val(divisor).Negate()));
+            }
+
+            for (int rep = 0; rep < 10; ++rep)
+            {
+                BigInteger a = new BigInteger(100 - rep, 0, random);
+                BigInteger b = new BigInteger(100 + rep, 0, random);
+                BigInteger c = new BigInteger(10 + rep, 0, random);
+                BigInteger d = a.Multiply(b).Add(c);
+                BigInteger e = d.Divide(a);
+
+                Assert.AreEqual(b, e);
+            }
+
+            // Special tests for power of two since uses different code path internally
+            for (int i = 0; i < 100; ++i)
+            {
+                int shift = random.Next(64);
+                BigInteger a = one.ShiftLeft(shift);
+                BigInteger b = new BigInteger(64 + random.Next(64), random);
+                BigInteger bShift = b.ShiftRight(shift);
+
+                string data = "shift=" + shift +", b=" + b.ToString(16);
+
+                Assert.AreEqual(bShift, b.Divide(a), data);
+                Assert.AreEqual(bShift.Negate(), b.Divide(a.Negate()), data);
+                Assert.AreEqual(bShift.Negate(), b.Negate().Divide(a), data);
+                Assert.AreEqual(bShift, b.Negate().Divide(a.Negate()), data);
+            }
+
+            // Regression
+            {
+                int shift = 63;
+                BigInteger a = one.ShiftLeft(shift);
+                BigInteger b = new BigInteger(1, Hex.Decode("2504b470dc188499"));
+                BigInteger bShift = b.ShiftRight(shift);
+
+                string data = "shift=" + shift +", b=" + b.ToString(16);
+
+                Assert.AreEqual(bShift, b.Divide(a), data);
+                Assert.AreEqual(bShift.Negate(), b.Divide(a.Negate()), data);
+//				Assert.AreEqual(bShift.Negate(), b.Negate().Divide(a), data);
+                Assert.AreEqual(bShift, b.Negate().Divide(a.Negate()), data);
+            }
+        }
+
+        [Test]
+        public void TestDivideAndRemainder()
+        {
+            // TODO More basic tests
+
+            BigInteger n = new BigInteger(48, random);
+            BigInteger[] qr = n.DivideAndRemainder(n);
+            Assert.AreEqual(one, qr[0]);
+            Assert.AreEqual(zero, qr[1]);
+            qr = n.DivideAndRemainder(one);
+            Assert.AreEqual(n, qr[0]);
+            Assert.AreEqual(zero, qr[1]);
+
+            for (int rep = 0; rep < 10; ++rep)
+            {
+                BigInteger a = new BigInteger(100 - rep, 0, random);
+                BigInteger b = new BigInteger(100 + rep, 0, random);
+                BigInteger c = new BigInteger(10 + rep, 0, random);
+                BigInteger d = a.Multiply(b).Add(c);
+                BigInteger[] es = d.DivideAndRemainder(a);
+
+                Assert.AreEqual(b, es[0]);
+                Assert.AreEqual(c, es[1]);
+            }
+
+            // Special tests for power of two since uses different code path internally
+            for (int i = 0; i < 100; ++i)
+            {
+                int shift = random.Next(64);
+                BigInteger a = one.ShiftLeft(shift);
+                BigInteger b = new BigInteger(64 + random.Next(64), random);
+                BigInteger bShift = b.ShiftRight(shift);
+                BigInteger bMod = b.And(a.Subtract(one));
+
+                string data = "shift=" + shift +", b=" + b.ToString(16);
+
+                qr = b.DivideAndRemainder(a);
+                Assert.AreEqual(bShift, qr[0], data);
+                Assert.AreEqual(bMod, qr[1], data);
+
+                qr = b.DivideAndRemainder(a.Negate());
+                Assert.AreEqual(bShift.Negate(), qr[0], data);
+                Assert.AreEqual(bMod, qr[1], data);
+
+                qr = b.Negate().DivideAndRemainder(a);
+                Assert.AreEqual(bShift.Negate(), qr[0], data);
+                Assert.AreEqual(bMod.Negate(), qr[1], data);
+
+                qr = b.Negate().DivideAndRemainder(a.Negate());
+                Assert.AreEqual(bShift, qr[0], data);
+                Assert.AreEqual(bMod.Negate(), qr[1], data);
+            }
+        }
+
+        [Test]
+        public void TestFlipBit()
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger a = new BigInteger(128, 0, random);
+                BigInteger b = a;
+
+                for (int x = 0; x < 100; ++x)
+                {
+                    // Note: Intentionally greater than initial size
+                    int pos = random.Next(256);
+
+                    a = a.FlipBit(pos);
+                    b = b.TestBit(pos) ? b.ClearBit(pos) : b.SetBit(pos);
+                }
+
+                Assert.AreEqual(a, b);
+            }
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger pow2 = one.ShiftLeft(i);
+                BigInteger minusPow2 = pow2.Negate();
+
+                Assert.AreEqual(zero, pow2.FlipBit(i));
+                Assert.AreEqual(minusPow2.ShiftLeft(1), minusPow2.FlipBit(i));
+
+                BigInteger bigI = BigInteger.ValueOf(i);
+                BigInteger negI = bigI.Negate();
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    string data = "i=" + i + ", j=" + j;
+                    Assert.AreEqual(bigI.Xor(one.ShiftLeft(j)), bigI.FlipBit(j), data);
+                    Assert.AreEqual(negI.Xor(one.ShiftLeft(j)), negI.FlipBit(j), data);
+                }
+            }
+        }
+
+        [Test]
+        public void TestGcd()
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger fac = new BigInteger(32, random).Add(two);
+                BigInteger p1 = BigInteger.ProbablePrime(63, random);
+                BigInteger p2 = BigInteger.ProbablePrime(64, random);
+
+                BigInteger gcd = fac.Multiply(p1).Gcd(fac.Multiply(p2));
+
+                Assert.AreEqual(fac, gcd);
+            }
+        }
+
+        [Test]
+        public void TestGetLowestSetBit()
+        {
+            for (int i = 1; i <= 100; ++i)
+            {
+                BigInteger test = new BigInteger(i + 1, 0, random).Add(one);
+                int bit1 = test.GetLowestSetBit();
+                Assert.AreEqual(test, test.ShiftRight(bit1).ShiftLeft(bit1));
+                int bit2 = test.ShiftLeft(i + 1).GetLowestSetBit();
+                Assert.AreEqual(i + 1, bit2 - bit1);
+                int bit3 = test.ShiftLeft(3 * i).GetLowestSetBit();
+                Assert.AreEqual(3 * i, bit3 - bit1);
+            }
+        }
+
+        [Test]
+        public void TestIntValue()
+        {
+            int[] tests = new int[]{ int.MinValue, -1234, -10, -1, 0, ~0, 1, 10, 5678, int.MaxValue };
+
+            foreach (int test in tests)
+            {
+                Assert.AreEqual(test, val(test).IntValue);
+            }
+
+            // TODO Tests for large numbers
+        }
+
+        [Test]
+        public void TestIsProbablePrime()
+        {
+            Assert.IsFalse(zero.IsProbablePrime(100));
+            Assert.IsFalse(zero.IsProbablePrime(100));
+            Assert.IsTrue(zero.IsProbablePrime(0));
+            Assert.IsTrue(zero.IsProbablePrime(-10));
+            Assert.IsFalse(minusOne.IsProbablePrime(100));
+            Assert.IsTrue(minusTwo.IsProbablePrime(100));
+            Assert.IsTrue(val(-17).IsProbablePrime(100));
+            Assert.IsTrue(val(67).IsProbablePrime(100));
+            Assert.IsTrue(val(773).IsProbablePrime(100));
+
+            foreach (int p in firstPrimes)
+            {
+                Assert.IsTrue(val(p).IsProbablePrime(100));
+                Assert.IsTrue(val(-p).IsProbablePrime(100));
+            }
+
+            foreach (int c in nonPrimes)
+            {
+                Assert.IsFalse(val(c).IsProbablePrime(100));
+                Assert.IsFalse(val(-c).IsProbablePrime(100));
+            }
+
+            foreach (int e in mersennePrimeExponents)
+            {
+                Assert.IsTrue(mersenne(e).IsProbablePrime(100));
+                Assert.IsTrue(mersenne(e).Negate().IsProbablePrime(100));
+            }
+
+            foreach (int e in nonPrimeExponents)
+            {
+                Assert.IsFalse(mersenne(e).IsProbablePrime(100));
+                Assert.IsFalse(mersenne(e).Negate().IsProbablePrime(100));
+            }
+
+            // TODO Other examples of 'tricky' values?
+        }
+
+        [Test]
+        public void TestLongValue()
+        {
+            long[] tests = new long[]{ long.MinValue, -1234, -10, -1, 0L, ~0L, 1, 10, 5678, long.MaxValue };
+
+            foreach (long test in tests)
+            {
+                Assert.AreEqual(test, val(test).LongValue);
+            }
+
+            // TODO Tests for large numbers
+        }
+
+        [Test]
+        public void TestMax()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(val(System.Math.Max(i, j)), val(i).Max(val(j)));
+                }
+            }
+        }
+
+        [Test]
+        public void TestMin()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(val(System.Math.Min(i, j)), val(i).Min(val(j)));
+                }
+            }
+        }
+
+        [Test]
+        public void TestMod()
+        {
+            // TODO Basic tests
+
+            for (int rep = 0; rep < 100; ++rep)
+            {
+                int diff = random.Next(25);
+                BigInteger a = new BigInteger(100 - diff, 0, random);
+                BigInteger b = new BigInteger(100 + diff, 0, random);
+                BigInteger c = new BigInteger(10 + diff, 0, random);
+
+                BigInteger d = a.Multiply(b).Add(c);
+                BigInteger e = d.Mod(a);
+                Assert.AreEqual(c, e);
+
+                BigInteger pow2 = one.ShiftLeft(random.Next(128));
+                Assert.AreEqual(b.And(pow2.Subtract(one)), b.Mod(pow2));
+            }
+        }
+
+        [Test]
+        public void TestModInverse()
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger p = BigInteger.ProbablePrime(64, random);
+                BigInteger q = new BigInteger(63, random).Add(one);
+                BigInteger inv = q.ModInverse(p);
+                BigInteger inv2 = inv.ModInverse(p);
+
+                Assert.AreEqual(q, inv2);
+                Assert.AreEqual(one, q.Multiply(inv).Mod(p));
+            }
+
+            // ModInverse a power of 2 for a range of powers
+            for (int i = 1; i <= 128; ++i)
+            {
+                BigInteger m = one.ShiftLeft(i);
+                BigInteger d = new BigInteger(i, random).SetBit(0);
+                BigInteger x = d.ModInverse(m);
+                BigInteger check = x.Multiply(d).Mod(m);
+
+                Assert.AreEqual(one, check);
+            }
+        }
+
+        [Test]
+        public void TestModPow()
+        {
+            try
+            {
+                two.ModPow(one, zero);
+                Assert.Fail("expected ArithmeticException");
+            }
+            catch (ArithmeticException) {}
+
+            Assert.AreEqual(zero, zero.ModPow(zero, one));
+            Assert.AreEqual(one, zero.ModPow(zero, two));
+            Assert.AreEqual(zero, two.ModPow(one, one));
+            Assert.AreEqual(one, two.ModPow(zero, two));
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger m = BigInteger.ProbablePrime(10 + i, random);
+                BigInteger x = new BigInteger(m.BitLength - 1, random);
+
+                Assert.AreEqual(x, x.ModPow(m, m));
+                if (x.SignValue != 0)
+                {
+                    Assert.AreEqual(zero, zero.ModPow(x, m));
+                    Assert.AreEqual(one, x.ModPow(m.Subtract(one), m));
+                }
+
+                BigInteger y = new BigInteger(m.BitLength - 1, random);
+                BigInteger n = new BigInteger(m.BitLength - 1, random);
+                BigInteger n3 = n.ModPow(three, m);
+
+                BigInteger resX = n.ModPow(x, m);
+                BigInteger resY = n.ModPow(y, m);
+                BigInteger res = resX.Multiply(resY).Mod(m);
+                BigInteger res3 = res.ModPow(three, m);
+
+                Assert.AreEqual(res3, n3.ModPow(x.Add(y), m));
+
+                BigInteger a = x.Add(one); // Make sure it's not zero
+                BigInteger b = y.Add(one); // Make sure it's not zero
+
+                Assert.AreEqual(a.ModPow(b, m).ModInverse(m), a.ModPow(b.Negate(), m));
+            }
+        }
+
+        [Test]
+        public void TestMultiply()
+        {
+            BigInteger one = BigInteger.One;
+
+            Assert.AreEqual(one, one.Negate().Multiply(one.Negate()));
+
+            for (int i = 0; i < 100; ++i)
+            {
+                int aLen = 64 + random.Next(64);
+                int bLen = 64 + random.Next(64);
+
+                BigInteger a = new BigInteger(aLen, random).SetBit(aLen);
+                BigInteger b = new BigInteger(bLen, random).SetBit(bLen);
+                BigInteger c = new BigInteger(32, random);
+
+                BigInteger ab = a.Multiply(b);
+                BigInteger bc = b.Multiply(c);
+
+                Assert.AreEqual(ab.Add(bc), a.Add(c).Multiply(b));
+                Assert.AreEqual(ab.Subtract(bc), a.Subtract(c).Multiply(b));
+            }
+
+            // Special tests for power of two since uses different code path internally
+            for (int i = 0; i < 100; ++i)
+            {
+                int shift = random.Next(64);
+                BigInteger a = one.ShiftLeft(shift);
+                BigInteger b = new BigInteger(64 + random.Next(64), random);
+                BigInteger bShift = b.ShiftLeft(shift);
+
+                Assert.AreEqual(bShift, a.Multiply(b));
+                Assert.AreEqual(bShift.Negate(), a.Multiply(b.Negate()));
+                Assert.AreEqual(bShift.Negate(), a.Negate().Multiply(b));
+                Assert.AreEqual(bShift, a.Negate().Multiply(b.Negate()));
+
+                Assert.AreEqual(bShift, b.Multiply(a));
+                Assert.AreEqual(bShift.Negate(), b.Multiply(a.Negate()));
+                Assert.AreEqual(bShift.Negate(), b.Negate().Multiply(a));
+                Assert.AreEqual(bShift, b.Negate().Multiply(a.Negate()));
+            }
+        }
+
+        [Test]
+        public void TestNegate()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                Assert.AreEqual(val(-i), val(i).Negate());
+            }
+        }
+
+        [Test]
+        public void TestNextProbablePrime()
+        {
+            BigInteger firstPrime = BigInteger.ProbablePrime(32, random);
+            BigInteger nextPrime = firstPrime.NextProbablePrime();
+
+            Assert.IsTrue(firstPrime.IsProbablePrime(10));
+            Assert.IsTrue(nextPrime.IsProbablePrime(10));
+
+            BigInteger check = firstPrime.Add(one);
+
+            while (check.CompareTo(nextPrime) < 0)
+            {
+                Assert.IsFalse(check.IsProbablePrime(10));
+                check = check.Add(one);
+            }
+        }
+
+        [Test]
+        public void TestNot()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                Assert.AreEqual(
+                    val(~i),
+                    val(i).Not(),
+                    "Problem: ~" + i + " should be " + ~i);
+            }
+        }
+
+        [Test]
+        public void TestOr()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i | j),
+                        val(i).Or(val(j)),
+                        "Problem: " + i + " OR " + j + " should be " + (i | j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestPow()
+        {
+            Assert.AreEqual(one, zero.Pow(0));
+            Assert.AreEqual(zero, zero.Pow(123));
+            Assert.AreEqual(one, one.Pow(0));
+            Assert.AreEqual(one, one.Pow(123));
+
+            Assert.AreEqual(two.Pow(147), one.ShiftLeft(147));
+            Assert.AreEqual(one.ShiftLeft(7).Pow(11), one.ShiftLeft(77));
+
+            BigInteger n = new BigInteger("1234567890987654321");
+            BigInteger result = one;
+
+            for (int i = 0; i < 10; ++i)
+            {
+                try
+                {
+                    val(i).Pow(-1);
+                    Assert.Fail("expected ArithmeticException");
+                }
+                catch (ArithmeticException) {}
+
+                Assert.AreEqual(result, n.Pow(i));
+
+                result = result.Multiply(n);
+            }
+        }
+
+        [Test]
+        public void TestRemainder()
+        {
+            // TODO Basic tests
+
+            for (int rep = 0; rep < 10; ++rep)
+            {
+                BigInteger a = new BigInteger(100 - rep, 0, random);
+                BigInteger b = new BigInteger(100 + rep, 0, random);
+                BigInteger c = new BigInteger(10 + rep, 0, random);
+                BigInteger d = a.Multiply(b).Add(c);
+                BigInteger e = d.Remainder(a);
+
+                Assert.AreEqual(c, e);
+            }
+        }
+
+        [Test]
+        public void TestSetBit()
+        {
+            Assert.AreEqual(one, zero.SetBit(0));
+            Assert.AreEqual(one, one.SetBit(0));
+            Assert.AreEqual(three, two.SetBit(0));
+
+            Assert.AreEqual(two, zero.SetBit(1));
+            Assert.AreEqual(three, one.SetBit(1));
+            Assert.AreEqual(two, two.SetBit(1));
+
+            // TODO Tests for setting bits in negative numbers
+
+            // TODO Tests for setting extended bits
+
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger n = new BigInteger(128, random);
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    int pos = random.Next(128);
+                    BigInteger m = n.SetBit(pos);
+                    bool test = m.ShiftRight(pos).Remainder(two).Equals(one);
+
+                    Assert.IsTrue(test);
+                }
+            }
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger pow2 = one.ShiftLeft(i);
+                BigInteger minusPow2 = pow2.Negate();
+
+                Assert.AreEqual(pow2, pow2.SetBit(i));
+                Assert.AreEqual(minusPow2, minusPow2.SetBit(i));
+
+                BigInteger bigI = BigInteger.ValueOf(i);
+                BigInteger negI = bigI.Negate();
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    string data = "i=" + i + ", j=" + j;
+                    Assert.AreEqual(bigI.Or(one.ShiftLeft(j)), bigI.SetBit(j), data);
+                    Assert.AreEqual(negI.Or(one.ShiftLeft(j)), negI.SetBit(j), data);
+                }
+            }
+        }
+
+        [Test]
+        public void TestShiftLeft()
+        {
+            for (int i = 0; i < 100; ++i)
+            {
+                int shift = random.Next(128);
+
+                BigInteger a = new BigInteger(128 + i, random).Add(one);
+                int bits = a.BitCount; // Make sure nBits is set
+
+                BigInteger negA = a.Negate();
+                bits = negA.BitCount; // Make sure nBits is set
+
+                BigInteger b = a.ShiftLeft(shift);
+                BigInteger c = negA.ShiftLeft(shift);
+
+                Assert.AreEqual(a.BitCount, b.BitCount);
+                Assert.AreEqual(negA.BitCount + shift, c.BitCount);
+                Assert.AreEqual(a.BitLength + shift, b.BitLength);
+                Assert.AreEqual(negA.BitLength + shift, c.BitLength);
+
+                int j = 0;
+                for (; j < shift; ++j)
+                {
+                    Assert.IsFalse(b.TestBit(j));
+                }
+
+                for (; j < b.BitLength; ++j)
+                {
+                    Assert.AreEqual(a.TestBit(j - shift), b.TestBit(j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestShiftRight()
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                int shift = random.Next(128);
+                BigInteger a = new BigInteger(256 + i, random).SetBit(256 + i);
+                BigInteger b = a.ShiftRight(shift);
+
+                Assert.AreEqual(a.BitLength - shift, b.BitLength);
+
+                for (int j = 0; j < b.BitLength; ++j)
+                {
+                    Assert.AreEqual(a.TestBit(j + shift), b.TestBit(j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestSignValue()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                Assert.AreEqual(i < 0 ? -1 : i > 0 ? 1 : 0, val(i).SignValue);
+            }
+        }
+
+        [Test]
+        public void TestSubtract()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i - j),
+                        val(i).Subtract(val(j)),
+                        "Problem: " + i + ".Subtract(" + j + ") should be " + (i - j));
+                }
+            }
+        }
+
+        [Test]
+        public void TestTestBit()
+        {
+            for (int i = 0; i < 10; ++i)
+            {
+                BigInteger n = new BigInteger(128, random);
+
+                Assert.IsFalse(n.TestBit(128));
+                Assert.IsTrue(n.Negate().TestBit(128));
+
+                for (int j = 0; j < 10; ++j)
+                {
+                    int pos = random.Next(128);
+                    bool test = n.ShiftRight(pos).Remainder(two).Equals(one);
+
+                    Assert.AreEqual(test, n.TestBit(pos));
+                }
+            }
+        }
+
+        [Test]
+        public void TestToByteArray()
+        {
+            byte[] z = BigInteger.Zero.ToByteArray();
+            Assert.IsTrue(Arrays.AreEqual(new byte[1], z));
+
+            for (int i = 16; i <= 48; ++i)
+            {
+                BigInteger x = BigInteger.ProbablePrime(i, random);
+                byte[] b = x.ToByteArray();
+                Assert.AreEqual((i / 8 + 1), b.Length);
+                BigInteger y = new BigInteger(b);
+                Assert.AreEqual(x, y);
+
+                x = x.Negate();
+                b = x.ToByteArray();
+                Assert.AreEqual((i / 8 + 1), b.Length);
+                y = new BigInteger(b);
+                Assert.AreEqual(x, y);
+            }
+        }
+
+        [Test]
+        public void TestToByteArrayUnsigned()
+        {
+            byte[] z = BigInteger.Zero.ToByteArrayUnsigned();
+            Assert.IsTrue(Arrays.AreEqual(new byte[0], z));
+
+            for (int i = 16; i <= 48; ++i)
+            {
+                BigInteger x = BigInteger.ProbablePrime(i, random);
+                byte[] b = x.ToByteArrayUnsigned();
+                Assert.AreEqual((i + 7) / 8, b.Length);
+                BigInteger y = new BigInteger(1, b);
+                Assert.AreEqual(x, y);
+
+                x = x.Negate();
+                b = x.ToByteArrayUnsigned();
+                Assert.AreEqual(i / 8 + 1, b.Length);
+                y = new BigInteger(b);
+                Assert.AreEqual(x, y);
+            }
+        }
+
+        [Test]
+        public void TestToString()
+        {
+            string s = "12345667890987654321";
+
+            Assert.AreEqual(s, new BigInteger(s).ToString());
+            Assert.AreEqual(s, new BigInteger(s, 10).ToString(10));
+            Assert.AreEqual(s, new BigInteger(s, 16).ToString(16));
+
+            for (int i = 0; i < 100; ++i)
+            {
+                BigInteger n = new BigInteger(i, random);
+
+                Assert.AreEqual(n, new BigInteger(n.ToString(2), 2));
+                Assert.AreEqual(n, new BigInteger(n.ToString(10), 10));
+                Assert.AreEqual(n, new BigInteger(n.ToString(16), 16));
+            }
+
+            // Radix version
+            int[] radices = new int[] { 2, 8, 10, 16 };
+            int trials = 256;
+
+            BigInteger[] tests = new BigInteger[trials];
+            for (int i = 0; i < trials; ++i)
+            {
+                int len = random.Next(i + 1);
+                tests[i] = new BigInteger(len, random);
+            }
+
+            foreach (int radix in radices)
+            {
+                for (int i = 0; i < trials; ++i)
+                {
+                    BigInteger n1 = tests[i];
+                    string str = n1.ToString(radix);
+                    BigInteger n2 = new BigInteger(str, radix);
+                    Assert.AreEqual(n1, n2);
+                }
+            }
+        }
+
+        [Test]
+        public void TestValueOf()
+        {
+            Assert.AreEqual(-1, BigInteger.ValueOf(-1).SignValue);
+            Assert.AreEqual(0, BigInteger.ValueOf(0).SignValue);
+            Assert.AreEqual(1, BigInteger.ValueOf(1).SignValue);
+
+            for (long i = -5; i < 5; ++i)
+            {
+                Assert.AreEqual(i, BigInteger.ValueOf(i).IntValue);
+            }
+        }
+
+        [Test]
+        public void TestXor()
+        {
+            for (int i = -10; i <= 10; ++i)
+            {
+                for (int j = -10; j <= 10; ++j)
+                {
+                    Assert.AreEqual(
+                        val(i ^ j),
+                        val(i).Xor(val(j)),
+                        "Problem: " + i + " XOR " + j + " should be " + (i ^ j));
+                }
+            }
+        }
+
+        private static BigInteger val(long n)
+        {
+            return BigInteger.ValueOf(n);
+        }
+
+        private static BigInteger mersenne(int e)
+        {
+            return two.Pow(e).Subtract(one);
+        }
+
+        private static readonly BigInteger minusTwo = BigInteger.Two.Negate();
+        private static readonly BigInteger minusOne = BigInteger.One.Negate();
+        private static readonly BigInteger zero = BigInteger.Zero;
+        private static readonly BigInteger one = BigInteger.One;
+        private static readonly BigInteger two = BigInteger.Two;
+        private static readonly BigInteger three = BigInteger.Three;
+
+        private static int[] firstPrimes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 };
+        private static int[] nonPrimes = { 0, 1, 4, 10, 20, 21, 22, 25, 26, 27 };
+
+        private static int[] mersennePrimeExponents = { 2, 3, 5, 7, 13, 17, 19, 31, 61, 89 };
+        private static int[] nonPrimeExponents = { 1, 4, 6, 9, 11, 15, 23, 29, 37, 41 };
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/ocsp/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/ocsp/test/AllTests.cs
new file mode 100644
index 0000000..d7393c2
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/ocsp/test/AllTests.cs
@@ -0,0 +1,31 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Ocsp.Tests
+{
+	public class AllTests
+	{
+		public static void Main(
+			string[] args)
+		{
+			//junit.textui.TestRunner.run(suite());
+			EventListener el = new NullListener();
+			suite().Run(el);
+		}
+
+		public static TestSuite suite()
+		{
+			TestSuite suite = new TestSuite("OCSP Tests");
+
+			suite.Add(new OcspTest());
+
+			return suite;
+		}
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTest.cs b/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTest.cs
new file mode 100644
index 0000000..823de90
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTest.cs
@@ -0,0 +1,852 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Ocsp;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Ocsp.Tests
+{
+	[TestFixture]
+	public class OcspTest
+		: SimpleTest
+	{
+		private static readonly byte[] testResp1 = Base64.Decode(
+			  "MIIFnAoBAKCCBZUwggWRBgkrBgEFBQcwAQEEggWCMIIFfjCCARehgZ8wgZwx"
+			+ "CzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEgcHJhZGVzaDESMBAGA1UE"
+			+ "BxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAKBgNVBAsTA0FUQzEeMBwG"
+			+ "A1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQwIgYJKoZIhvcNAQkBFhVv"
+			+ "Y3NwQHRjcy1jYS50Y3MuY28uaW4YDzIwMDMwNDAyMTIzNDU4WjBiMGAwOjAJ"
+			+ "BgUrDgMCGgUABBRs07IuoCWNmcEl1oHwIak1BPnX8QQUtGyl/iL9WJ1VxjxF"
+			+ "j0hAwJ/s1AcCAQKhERgPMjAwMjA4MjkwNzA5MjZaGA8yMDAzMDQwMjEyMzQ1"
+			+ "OFowDQYJKoZIhvcNAQEFBQADgYEAfbN0TCRFKdhsmvOdUoiJ+qvygGBzDxD/"
+			+ "VWhXYA+16AphHLIWNABR3CgHB3zWtdy2j7DJmQ/R7qKj7dUhWLSqclAiPgFt"
+			+ "QQ1YvSJAYfEIdyHkxv4NP0LSogxrumANcDyC9yt/W9yHjD2ICPBIqCsZLuLk"
+			+ "OHYi5DlwWe9Zm9VFwCGgggPMMIIDyDCCA8QwggKsoAMCAQICAQYwDQYJKoZI"
+			+ "hvcNAQEFBQAwgZQxFDASBgNVBAMTC1RDUy1DQSBPQ1NQMSYwJAYJKoZIhvcN"
+			+ "AQkBFhd0Y3MtY2FAdGNzLWNhLnRjcy5jby5pbjEMMAoGA1UEChMDVENTMQww"
+			+ "CgYDVQQLEwNBVEMxEjAQBgNVBAcTCUh5ZGVyYWJhZDEXMBUGA1UECBMOQW5k"
+			+ "aHJhIHByYWRlc2gxCzAJBgNVBAYTAklOMB4XDTAyMDgyOTA3MTE0M1oXDTAz"
+			+ "MDgyOTA3MTE0M1owgZwxCzAJBgNVBAYTAklOMRcwFQYDVQQIEw5BbmRocmEg"
+			+ "cHJhZGVzaDESMBAGA1UEBxMJSHlkZXJhYmFkMQwwCgYDVQQKEwNUQ1MxDDAK"
+			+ "BgNVBAsTA0FUQzEeMBwGA1UEAxMVVENTLUNBIE9DU1AgUmVzcG9uZGVyMSQw"
+			+ "IgYJKoZIhvcNAQkBFhVvY3NwQHRjcy1jYS50Y3MuY28uaW4wgZ8wDQYJKoZI"
+			+ "hvcNAQEBBQADgY0AMIGJAoGBAM+XWW4caMRv46D7L6Bv8iwtKgmQu0SAybmF"
+			+ "RJiz12qXzdvTLt8C75OdgmUomxp0+gW/4XlTPUqOMQWv463aZRv9Ust4f8MH"
+			+ "EJh4ekP/NS9+d8vEO3P40ntQkmSMcFmtA9E1koUtQ3MSJlcs441JjbgUaVnm"
+			+ "jDmmniQnZY4bU3tVAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADALBgNVHQ8E"
+			+ "BAMCB4AwEwYDVR0lBAwwCgYIKwYBBQUHAwkwNgYIKwYBBQUHAQEEKjAoMCYG"
+			+ "CCsGAQUFBzABhhpodHRwOi8vMTcyLjE5LjQwLjExMDo3NzAwLzAtBgNVHR8E"
+			+ "JjAkMCKgIKAehhxodHRwOi8vMTcyLjE5LjQwLjExMC9jcmwuY3JsMA0GCSqG"
+			+ "SIb3DQEBBQUAA4IBAQB6FovM3B4VDDZ15o12gnADZsIk9fTAczLlcrmXLNN4"
+			+ "PgmqgnwF0Ymj3bD5SavDOXxbA65AZJ7rBNAguLUo+xVkgxmoBH7R2sBxjTCc"
+			+ "r07NEadxM3HQkt0aX5XYEl8eRoifwqYAI9h0ziZfTNes8elNfb3DoPPjqq6V"
+			+ "mMg0f0iMS4W8LjNPorjRB+kIosa1deAGPhq0eJ8yr0/s2QR2/WFD5P4aXc8I"
+			+ "KWleklnIImS3zqiPrq6tl2Bm8DZj7vXlTOwmraSQxUwzCKwYob1yGvNOUQTq"
+			+ "pG6jxn7jgDawHU1+WjWQe4Q34/pWeGLysxTraMa+Ug9kPe+jy/qRX2xwvKBZ"
+//			+ "====");
+			+ "");
+
+		private static readonly byte[] testResp2 = Base64.Decode(
+			  "MIII1QoBAKCCCM4wggjKBgkrBgEFBQcwAQEEggi7MIIItzCBjqADAgEAoSMw"
+			+ "ITEfMB0GA1UEAxMWT0NTUCBjZXJ0LVFBLUNMSUVOVC04NxgPMjAwMzA1MTky"
+			+ "MDI2MzBaMFEwTzA6MAkGBSsOAwIaBQAEFJniwiUuyrhKIEF2TjVdVdCAOw0z"
+			+ "BBR2olPKrPOJUVyGZ7BXOC4L2BmAqgIBL4AAGA8yMDAzMDUxOTIwMjYzMFow"
+			+ "DQYJKoZIhvcNAQEEBQADggEBALImFU3kUtpNVf4tIFKg/1sDHvGpk5Pk0uhH"
+			+ "TiNp6vdPfWjOgPkVXskx9nOTabVOBE8RusgwEcK1xeBXSHODb6mnjt9pkfv3"
+			+ "ZdbFLFvH/PYjOb6zQOgdIOXhquCs5XbcaSFCX63hqnSaEqvc9w9ctmQwds5X"
+			+ "tCuyCB1fWu/ie8xfuXR5XZKTBf5c6dO82qFE65gTYbGOxJBYiRieIPW1XutZ"
+			+ "A76qla4m+WdxubV6SPG8PVbzmAseqjsJRn4jkSKOGenqSOqbPbZn9oBsU0Ku"
+			+ "hul3pwsNJvcBvw2qxnWybqSzV+n4OvYXk+xFmtTjw8H9ChV3FYYDs8NuUAKf"
+			+ "jw1IjWegggcOMIIHCjCCAzMwggIboAMCAQICAQIwDQYJKoZIhvcNAQEEBQAw"
+			+ "bzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMRAwDgYDVQQHEwdXYWx0aGFt"
+			+ "MRYwFAYDVQQKEw1Gb3J1bSBTeXN0ZW1zMQswCQYDVQQLEwJRQTEcMBoGA1UE"
+			+ "AxMTQ2VydGlmaWNhdGUgTWFuYWdlcjAeFw0wMzAzMjEwNTAwMDBaFw0yNTAz"
+			+ "MjEwNTAwMDBaMCExHzAdBgNVBAMTFk9DU1AgY2VydC1RQS1DTElFTlQtODcw"
+			+ "ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVuxRCZgJAYAftYuRy"
+			+ "9axdtsHrkIJyVVRorLCTWOoLmx2tlrGqKbHOGKmvqEPEpeCDYQk+0WIlWMuM"
+			+ "2pgiYAolwqSFBwCjkjQN3fCIHXiby0JBgCCLoe7wa0pZffE+8XZH0JdSjoT3"
+			+ "2OYD19wWZeY2VB0JWJFWYAnIL+R5Eg7LwJ5QZSdvghnOWKTv60m/O1rC0see"
+			+ "9lbPO+3jRuaDyCUKYy/YIKBYC9rtC4hS47jg70dTfmE2nccjn7rFCPBrVr4M"
+			+ "5szqdRzwu3riL9W+IE99LTKXOH/24JX0S4woeGXMS6me7SyZE6x7P2tYkNXM"
+			+ "OfXk28b3SJF75K7vX6T6ecWjAgMBAAGjKDAmMBMGA1UdJQQMMAoGCCsGAQUF"
+			+ "BwMJMA8GCSsGAQUFBzABBQQCBQAwDQYJKoZIhvcNAQEEBQADggEBAKNSn7pp"
+			+ "UEC1VTN/Iqk8Sc2cAYM7KSmeB++tuyes1iXY4xSQaEgOxRa5AvPAKnXKSzfY"
+			+ "vqi9WLdzdkpTo4AzlHl5nqU/NCUv3yOKI9lECVMgMxLAvZgMALS5YXNZsqrs"
+			+ "hP3ASPQU99+5CiBGGYa0PzWLstXLa6SvQYoHG2M8Bb2lHwgYKsyrUawcfc/s"
+			+ "jE3jFJeyCyNwzH0eDJUVvW1/I3AhLNWcPaT9/VfyIWu5qqZU+ukV/yQXrKiB"
+			+ "glY8v4QDRD4aWQlOuiV2r9sDRldOPJe2QSFDBe4NtBbynQ+MRvF2oQs/ocu+"
+			+ "OAHX7uiskg9GU+9cdCWPwJf9cP/Zem6MemgwggPPMIICt6ADAgECAgEBMA0G"
+			+ "CSqGSIb3DQEBBQUAMG8xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJNQTEQMA4G"
+			+ "A1UEBxMHV2FsdGhhbTEWMBQGA1UEChMNRm9ydW0gU3lzdGVtczELMAkGA1UE"
+			+ "CxMCUUExHDAaBgNVBAMTE0NlcnRpZmljYXRlIE1hbmFnZXIwHhcNMDMwMzIx"
+			+ "MDUwMDAwWhcNMjUwMzIxMDUwMDAwWjBvMQswCQYDVQQGEwJVUzELMAkGA1UE"
+			+ "CBMCTUExEDAOBgNVBAcTB1dhbHRoYW0xFjAUBgNVBAoTDUZvcnVtIFN5c3Rl"
+			+ "bXMxCzAJBgNVBAsTAlFBMRwwGgYDVQQDExNDZXJ0aWZpY2F0ZSBNYW5hZ2Vy"
+			+ "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4VeU+48VBjI0mGRt"
+			+ "9qlD+WAhx3vv4KCOD5f3HWLj8D2DcoszVTVDqtRK+HS1eSpO/xWumyXhjV55"
+			+ "FhG2eYi4e0clv0WyswWkGLqo7IxYn3ZhVmw04ohdTjdhVv8oS+96MUqPmvVW"
+			+ "+MkVRyqm75HdgWhKRr/lEpDNm+RJe85xMCipkyesJG58p5tRmAZAAyRs3jYw"
+			+ "5YIFwDOnt6PCme7ui4xdas2zolqOlynMuq0ctDrUPKGLlR4mVBzgAVPeatcu"
+			+ "ivEQdB3rR6UN4+nv2jx9kmQNNb95R1M3J9xHfOWX176UWFOZHJwVq8eBGF9N"
+			+ "pav4ZGBAyqagW7HMlo7Hw0FzUwIDAQABo3YwdDARBglghkgBhvhCAQEEBAMC"
+			+ "AJcwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU64zBxl1yKES8tjU3/rBA"
+			+ "NaeBpjkwHwYDVR0jBBgwFoAU64zBxl1yKES8tjU3/rBANaeBpjkwDgYDVR0P"
+			+ "AQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQAzHnf+Z+UgxDVOpCu0DHF+"
+			+ "qYZf8IaUQxLhUD7wjwnt3lJ0QV1z4oyc6Vs9J5xa8Mvf7u1WMmOxvN8r8Kb0"
+			+ "k8DlFszLd0Qwr+NVu5NQO4Vn01UAzCtH4oX2bgrVzotqDnzZ4TcIr11EX3Nb"
+			+ "tO8yWWl+xWIuxKoAO8a0Rh97TyYfAj4++GIm43b2zIvRXEWAytjz7rXUMwRC"
+			+ "1ipRQwSA9gyw2y0s8emV/VwJQXsTe9xtDqlEC67b90V/BgL/jxck5E8yrY9Z"
+			+ "gNxlOgcqscObisAkB5I6GV+dfa+BmZrhSJ/bvFMUrnFzjLFvZp/9qiK11r5K"
+			+ "A5oyOoNv0w+8bbtMNEc1"
+//			+ "====");
+			+ "");
+
+		/**
+		 * extra version number encoding.
+		 */
+		private static readonly byte[] irregReq = Base64.Decode(
+			  "MIIQpTBUoAMCAQAwTTBLMEkwCQYFKw4DAhoFAAQUIcFvFFVjPem15pKox4cfcnzF"
+			+ "Kf4EFJf8OQzmVmyJ/hc4EhitQbXcqAzDAhB9ePsP19SuP6CsAgFwQuEAoIIQSzCC"
+			+ "EEcwDQYJKoZIhvcNAQEFBQADgYEAlq/Tjl8OtFM8Tib1JYTiaPy9vFDr8UZhqXJI"
+			+ "FyrdgtUyyDt0EcrgnBGacAeRZzF5sokIC6DjXweU7EItGqrpw/RaCUPUWFpPxR6y"
+			+ "HjuzrLmICocTI9MH7dRUXm0qpxoY987sx1PtWB4pSR99ixBtq3OPNdsI0uJ+Qkei"
+			+ "LbEZyvWggg+wMIIPrDCCA5owggKCoAMCAQICEEAxXx/eFe7gm/NX7AkcS68wDQYJ"
+			+ "KoZIhvcNAQEFBQAwgZoxCzAJBgNVBAYTAlNFMTMwMQYDVQQKDCpMw6Ruc2bDtnJz"
+			+ "w6RrcmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkxFTATBgNVBAUTDDExMTEx"
+			+ "MTExMTExMTE/MD0GA1UEAww2TMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIFB1cmNo"
+			+ "YXNlciBDQTEgZm9yIEJhbmtJRCBURVNUMB4XDTA4MTAwNjIyMDAwMFoXDTEwMTAx"
+			+ "MDIxNTk1OVowgZExCzAJBgNVBAYTAlNFMTMwMQYDVQQKDCpMw6Ruc2bDtnJzw6Rr"
+			+ "cmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkxFTATBgNVBAUTDDExMTExMTEx"
+			+ "MTExMTE2MDQGA1UEAwwtTMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIE9DU1AgZm9y"
+			+ "IEJhbmtJRCBURVNUMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5e/h6aL2m"
+			+ "DVpWeu5e5p1Ps9kbvuuGeAp9zJDYLbZz7uzT67X+s59HaViroD2+2my/gg7rX7tK"
+			+ "H9VXpJad1W9O19SjfNyxgeAMwVMkrbb4IlrQwu0v/Ub8JPxSWwZZXYiODq5abeXA"
+			+ "abMYIHxSaSkhrsUj1dpSAohHLJRlq707swIDAQABo2cwZTAfBgNVHSMEGDAWgBTR"
+			+ "vcp2QyNdNGZ+q7TjKSrrHZqxmDATBgNVHSAEDDAKMAgGBiqFcDwBBjAOBgNVHQ8B"
+			+ "Af8EBAMCBkAwHQYDVR0OBBYEFF/3557FEvkA8iiPv2XcBclxKnTdMA0GCSqGSIb3"
+			+ "DQEBBQUAA4IBAQAOxRvHO89XJ0v83BZdPFzEBA4B2Tqc1oABUn13S6fAkcGWvOmG"
+			+ "eY61MK16aMnLPNDadZrAqJc6PEtVY57uaywE9acwv9XpHO0bcS94tLwvZZJ2KBt0"
+			+ "Oq96gaI6gnJViUjyWjm+qBZvod0QPOLGv6wUPoiNcCpSid/COTjKpLYpCJj3ZWUV"
+			+ "nsTRWSRVXsdY/xI0gs/A8/c5P1PuTxoi99RTmcruoFxvV4MmhWyX7IGqG4OAtLdo"
+			+ "yefz/90FPGOrmqY9OgEb+gNuTM26YDvSs1dfarPl89d8jjwxHgNbZjh2VHFqKolJ"
+			+ "8TB8ZS5aNvhHPumOOE47y95rTBxrxSmGvKb8MIIENDCCAxygAwIBAgIRAJAFaeOw"
+			+ "7XbxH/DN/Vvhjx8wDQYJKoZIhvcNAQEFBQAwgZUxCzAJBgNVBAYTAlNFMTMwMQYD"
+			+ "VQQKDCpMw6Ruc2bDtnJzw6RrcmluZ2FyIEJhbmsgQWt0aWVib2xhZyAocHVibCkx"
+			+ "FTATBgNVBAUTDDExMTExMTExMTExMTE6MDgGA1UEAwwxTMOkbnNmw7Zyc8Oka3Jp"
+			+ "bmdhciBCYW5rIFJvb3QgQ0ExIGZvciBCYW5rSUQgVEVTVDAeFw0wNzEwMDExMjAw"
+			+ "MzdaFw0yOTA3MDExMjAwMzdaMIGaMQswCQYDVQQGEwJTRTEzMDEGA1UECgwqTMOk"
+			+ "bnNmw7Zyc8Oka3JpbmdhciBCYW5rIEFrdGllYm9sYWcgKHB1YmwpMRUwEwYDVQQF"
+			+ "EwwxMTExMTExMTExMTExPzA9BgNVBAMMNkzDpG5zZsO2cnPDpGtyaW5nYXIgQmFu"
+			+ "ayBQdXJjaGFzZXIgQ0ExIGZvciBCYW5rSUQgVEVTVDCCASIwDQYJKoZIhvcNAQEB"
+			+ "BQADggEPADCCAQoCggEBAMK5WbYojYRX1ZKrbxJBgbd4x503LfMWgr67sVD5L0NY"
+			+ "1RPhZVFJRKJWvawE5/eXJ4oNQwc831h2jiOgINXuKyGXqdAVGBcpFwIxTfzxwT4l"
+			+ "fvztr8pE6wk7mLLwKUvIjbM3EF1IL3zUI3UU/U5ioyGmcb/o4GGN71kMmvV/vrkU"
+			+ "02/s7xicXNxYej4ExLiCkS5+j/+3sR47Uq5cL9e8Yg7t5/6FyLGQjKoS8HU/abYN"
+			+ "4kpx/oyrxzrXMhnMVDiI8QX9NYGJwI8KZ/LU6GDq/NnZ3gG5v4l4UU1GhgUbrk4I"
+			+ "AZPDu99zvwCtkdj9lJN0eDv8jdyEPZ6g1qPBE0pCNqcCAwEAAaN4MHYwDwYDVR0T"
+			+ "AQH/BAUwAwEB/zATBgNVHSAEDDAKMAgGBiqFcDwBBjAOBgNVHQ8BAf8EBAMCAQYw"
+			+ "HwYDVR0jBBgwFoAUnkjp1bkQUOrkRiLgxpxwAe2GQFYwHQYDVR0OBBYEFNG9ynZD"
+			+ "I100Zn6rtOMpKusdmrGYMA0GCSqGSIb3DQEBBQUAA4IBAQAPVSC4HEd+yCtSgL0j"
+			+ "NI19U2hJeP28lAD7OA37bcLP7eNrvfU/2tuqY7rEn1m44fUbifewdgR8x2DzhM0m"
+			+ "fJcA5Z12PYUb85L9z8ewGQdyHLNlMpKSTP+0lebSc/obFbteC4jjuvux60y5KVOp"
+			+ "osXbGw2qyrS6uhZJrTDP1B+bYg/XBttG+i7Qzx0S5Tq//VU9OfAQZWpvejadKAk9"
+			+ "WCcXq6zALiJcxsUwOHZRvvHDxkHuf5eZpPvm1gaqa+G9CtV+oysZMU1eTRasBHsB"
+			+ "NRWYfOSXggsyqRHfIAVieB4VSsB8WhZYm8UgYoLhAQfSJ5Xq5cwBOHkVj33MxAyP"
+			+ "c7Y5MIID/zCCAuegAwIBAgIRAOXEoBcV4gV3Z92gk5AuRgwwDQYJKoZIhvcNAQEF"
+			+ "BQAwZjEkMCIGA1UECgwbRmluYW5zaWVsbCBJRC1UZWtuaWsgQklEIEFCMR8wHQYD"
+			+ "VQQLDBZCYW5rSUQgTWVtYmVyIEJhbmtzIENBMR0wGwYDVQQDDBRCYW5rSUQgUm9v"
+			+ "dCBDQSBURVNUMjAeFw0wNzEwMDExMTQ1NDlaFw0yOTA4MDExMTU4MjVaMIGVMQsw"
+			+ "CQYDVQQGEwJTRTEzMDEGA1UECgwqTMOkbnNmw7Zyc8Oka3JpbmdhciBCYW5rIEFr"
+			+ "dGllYm9sYWcgKHB1YmwpMRUwEwYDVQQFEwwxMTExMTExMTExMTExOjA4BgNVBAMM"
+			+ "MUzDpG5zZsO2cnPDpGtyaW5nYXIgQmFuayBSb290IENBMSBmb3IgQmFua0lEIFRF"
+			+ "U1QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDBzn7IXIpyOGCCTuzL"
+			+ "DKE/T+pFRTgFh3QgKtifZ4zxdvB2Sd5+90vUEGcGExUhzpgb9gOUrT1eE0XhdiUR"
+			+ "YuYYpJI/nzPQWTsRtEaql7NHBPKnEauoA9oAhCT4pE5gLlqpTfkB8nAsRTI2XqpI"
+			+ "hQ7vTvnTRx20xog21NIbz1GztV8H1kBH2eDvRX7cXGiugp6CXV/le9cB+/4TBNUN"
+			+ "Xqupt79dM49KCoDuYr72W7Hv4BSWw3IInEN2m8T2X6UBpBGkCiGwLQy/+KOmYRK7"
+			+ "1PSFC0rXDwOJ0HJ/8fHwx6vLMxHAQ6s/9vOW10MjgjSQlbVqH/4Pa+TlpWumSV4E"
+			+ "l0z9AgMBAAGjeDB2MA8GA1UdEwEB/wQFMAMBAf8wEwYDVR0gBAwwCjAIBgYqhXA8"
+			+ "AQYwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQYMBaAFJuTMPljHcYdrRO9sEi1amb4"
+			+ "tE3VMB0GA1UdDgQWBBSeSOnVuRBQ6uRGIuDGnHAB7YZAVjANBgkqhkiG9w0BAQUF"
+			+ "AAOCAQEArnW/9n+G+84JOgv1Wn4tsBBS7QgJp1rdCoiNrZPx2du/7Wz3wQVNKBjL"
+			+ "eMCyLjg0OVHuq4hpCv9MZpUqdcUW8gpp4dLDAAd1uE7xqVuG8g4Ir5qocxbZHQew"
+			+ "fnqSJJDlEZgDeZIzod92OO+htv0MWqKWbr3Mo2Hqhn+t0+UVWsW4k44e7rUw3xQq"
+			+ "r2VdMJv/C68BXUgqh3pplUDjWyXfreiACTT0q3HT6v6WaihKCa2WY9Kd1IkDcLHb"
+			+ "TZk8FqMmGn72SgJw3H5Dvu7AiZijjNAUulMnMpxBEKyFTU2xRBlZZVcp50VJ2F7+"
+			+ "siisxbcYOAX4GztLMlcyq921Ov/ipDCCA88wggK3oAMCAQICEQCmaX+5+m5bF5us"
+			+ "CtyMq41SMA0GCSqGSIb3DQEBBQUAMGYxJDAiBgNVBAoMG0ZpbmFuc2llbGwgSUQt"
+			+ "VGVrbmlrIEJJRCBBQjEfMB0GA1UECwwWQmFua0lEIE1lbWJlciBCYW5rcyBDQTEd"
+			+ "MBsGA1UEAwwUQmFua0lEIFJvb3QgQ0EgVEVTVDIwHhcNMDQwODEzMDcyMDEwWhcN"
+			+ "MjkwODEyMTIwMjQ2WjBmMSQwIgYDVQQKDBtGaW5hbnNpZWxsIElELVRla25payBC"
+			+ "SUQgQUIxHzAdBgNVBAsMFkJhbmtJRCBNZW1iZXIgQmFua3MgQ0ExHTAbBgNVBAMM"
+			+ "FEJhbmtJRCBSb290IENBIFRFU1QyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB"
+			+ "CgKCAQEA25D0f1gipbACk4Bg3t6ODUlCWOU0TWeTkzAHR7IRB5T++yvsVosedMMW"
+			+ "6KYYTbPONeJSt5kydX+wZi9nVNdlhkNULLbDKWfRY7x+B9MR1Q0Kq/e4VR0uRsak"
+			+ "Bv5iwEYZ7cSR63HfBaPTqQsGobq+wtGH5JeTBrmCt4A3kN1UWgX32Dv/I3m7v8bK"
+			+ "iwh4cnvAD9PIOtq6pOmAkSvLvp8jCy3qFLe9KAxm8M/ZAmnxYaRV8DVEg57FGoG6"
+			+ "oiG3Ixx8PSVVdzpFY4kuUFLi4ueMPwjnXFiBhhWJJeOtFG3Lc2aW3zvcDbD/MsDm"
+			+ "rSZNTmtbOOou8xuMKjlNY9PU5MHIaQIDAQABo3gwdjAPBgNVHRMBAf8EBTADAQH/"
+			+ "MBMGA1UdIAQMMAowCAYGKoVwPAEGMA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAW"
+			+ "gBSbkzD5Yx3GHa0TvbBItWpm+LRN1TAdBgNVHQ4EFgQUm5Mw+WMdxh2tE72wSLVq"
+			+ "Zvi0TdUwDQYJKoZIhvcNAQEFBQADggEBAIQ4ZBHWssA38pfNzH5A+H3SXpAlI8Jc"
+			+ "LuoMVOIwwbfd1Up0xopCs+Ay41v8FZtcTMFqCVTih2nzVusTgnFBPMPJ2cnTlRue"
+			+ "kAtVRNsiWn2/Ool/OXoYf5YnpgYu8t9jLCBCoDS5YJg714r9V9hCwfey8TCWBU80"
+			+ "vL7EIfjK13nUxf8d49GzZlFMNqGDMjfMp1FYrHBGLZBr8br/G/7em1Cprw7iR8cw"
+			+ "pddz+QXXFIrIz5Y9D/x1RrwoLibPw0kMrSwI2G4aCvoBySfbD6cpnJf6YHRctdSb"
+			+ "755zhdBW7XWTl6ReUVuEt0hTFms4F60kFAi5hIbDRSN1Slv5yP2b0EA=");
+
+		public override string Name
+		{
+			get { return "OCSP"; }
+		}
+
+		private void doTestECDsa()
+		{
+			string signDN = "O=Bouncy Castle, C=AU";
+			AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeECKeyPair();
+			X509Certificate testCert = OcspTestUtil.MakeECDsaCertificate(signKP, signDN, signKP, signDN);
+
+			string origDN = "CN=Eric H. Echidna, E=eric at bouncycastle.org, O=Bouncy Castle, C=AU";
+			GeneralName origName = new GeneralName(new X509Name(origDN));
+
+			//
+			// general id value for our test issuer cert and a serial number.
+			//
+			CertificateID id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One);
+
+			//
+			// basic request generation
+			//
+			OcspReqGenerator gen = new OcspReqGenerator();
+
+			gen.AddRequest(id);
+
+			OcspReq req = gen.Generate();
+
+			if (req.IsSigned)
+			{
+				Fail("signed but shouldn't be");
+			}
+
+			X509Certificate[] certs = req.GetCerts();
+
+			if (certs != null)
+			{
+				Fail("null certs expected, but not found");
+			}
+
+			Req[] requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// request generation with signing
+			//
+			X509Certificate[] chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			gen.AddRequest(new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withECDSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			certs = req.GetCerts();
+
+			if (certs == null)
+			{
+				Fail("null certs found");
+			}
+
+			if (certs.Length != 1 || !certs[0].Equals(testCert))
+			{
+				Fail("incorrect certs found in request");
+			}
+
+			//
+			// encoding test
+			//
+			byte[] reqEnc = req.GetEncoded();
+
+			OcspReq newReq = new OcspReq(reqEnc);
+
+			if (!newReq.Verify(signKP.Public))
+			{
+				Fail("newReq signature failed to Verify");
+			}
+
+			//
+			// request generation with signing and nonce
+			//
+			chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			IList oids = new ArrayList();
+			IList values = new ArrayList();
+			byte[] sampleNonce = new byte[16];
+			Random rand = new Random();
+
+			rand.NextBytes(sampleNonce);
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			oids.Add(OcspObjectIdentifiers.PkixOcspNonce);
+			values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce))));
+
+			gen.SetRequestExtensions(new X509Extensions(oids, values));
+
+			gen.AddRequest(new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withECDSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			//
+			// extension check.
+			//
+			ISet extOids = req.GetCriticalExtensionOids();
+
+			if (extOids.Count != 0)
+			{
+				Fail("wrong number of critical extensions in OCSP request.");
+			}
+
+			extOids = req.GetNonCriticalExtensionOids();
+
+			if (extOids.Count != 1)
+			{
+				Fail("wrong number of non-critical extensions in OCSP request.");
+			}
+
+			Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce);
+
+			Asn1Encodable extObj = X509ExtensionUtilities.FromExtensionValue(extValue);
+
+			if (!(extObj is Asn1OctetString))
+			{
+				Fail("wrong extension type found.");
+			}
+
+			if (!AreEqual(((Asn1OctetString)extObj).GetOctets(), sampleNonce))
+			{
+				Fail("wrong extension value found.");
+			}
+
+			//
+			// request list check
+			//
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// response generation
+			//
+			BasicOcspRespGenerator respGen = new BasicOcspRespGenerator(signKP.Public);
+
+			respGen.AddResponse(id, CertificateStatus.Good);
+
+			respGen.Generate("SHA1withECDSA", signKP.Private, chain, DateTime.UtcNow);
+		}
+
+		private void doTestRsa()
+		{
+			string signDN = "O=Bouncy Castle, C=AU";
+			AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeKeyPair();
+			X509Certificate testCert = OcspTestUtil.MakeCertificate(signKP, signDN, signKP, signDN);
+
+			string origDN = "CN=Eric H. Echidna, E=eric at bouncycastle.org, O=Bouncy Castle, C=AU";
+			GeneralName origName = new GeneralName(new X509Name(origDN));
+
+			//
+			// general id value for our test issuer cert and a serial number.
+			//
+			CertificateID id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One);
+
+			//
+			// basic request generation
+			//
+			OcspReqGenerator gen = new OcspReqGenerator();
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			OcspReq req = gen.Generate();
+
+			if (req.IsSigned)
+			{
+				Fail("signed but shouldn't be");
+			}
+
+			X509Certificate[] certs = req.GetCerts();
+
+			if (certs != null)
+			{
+				Fail("null certs expected, but not found");
+			}
+
+			Req[] requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// request generation with signing
+			//
+			X509Certificate[] chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withRSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			certs = req.GetCerts();
+
+			if (certs == null)
+			{
+				Fail("null certs found");
+			}
+
+			if (certs.Length != 1 || !certs[0].Equals(testCert))
+			{
+				Fail("incorrect certs found in request");
+			}
+
+			//
+			// encoding test
+			//
+			byte[] reqEnc = req.GetEncoded();
+
+			OcspReq newReq = new OcspReq(reqEnc);
+
+			if (!newReq.Verify(signKP.Public))
+			{
+				Fail("newReq signature failed to Verify");
+			}
+
+			//
+			// request generation with signing and nonce
+			//
+			chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			IList oids = new ArrayList();
+			IList values = new ArrayList();
+			byte[] sampleNonce = new byte[16];
+			Random rand = new Random();
+
+			rand.NextBytes(sampleNonce);
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			oids.Add(OcspObjectIdentifiers.PkixOcspNonce);
+			values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce))));
+
+			gen.SetRequestExtensions(new X509Extensions(oids, values));
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withRSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			//
+			// extension check.
+			//
+			ISet extOids = req.GetCriticalExtensionOids();
+
+			if (extOids.Count != 0)
+			{
+				Fail("wrong number of critical extensions in OCSP request.");
+			}
+
+			extOids = req.GetNonCriticalExtensionOids();
+
+			if (extOids.Count != 1)
+			{
+				Fail("wrong number of non-critical extensions in OCSP request.");
+			}
+
+			Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce);
+
+			Asn1Object extObj = X509ExtensionUtilities.FromExtensionValue(extValue);
+
+			if (!(extObj is Asn1OctetString))
+			{
+				Fail("wrong extension type found.");
+			}
+
+			if (!AreEqual(((Asn1OctetString)extObj).GetOctets(), sampleNonce))
+			{
+				Fail("wrong extension value found.");
+			}
+
+			//
+			// request list check
+			//
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// response generation
+			//
+			BasicOcspRespGenerator respGen = new BasicOcspRespGenerator(signKP.Public);
+
+			respGen.AddResponse(id, CertificateStatus.Good);
+
+			BasicOcspResp resp = respGen.Generate("SHA1withRSA", signKP.Private, chain, DateTime.UtcNow);
+			OCSPRespGenerator rGen = new OCSPRespGenerator();
+
+			byte[] enc = rGen.Generate(OCSPRespGenerator.Successful, resp).GetEncoded();
+		}
+
+		private void doTestIrregularVersionReq()
+		{
+			OcspReq ocspRequest = new OcspReq(irregReq);
+			X509Certificate cert = ocspRequest.GetCerts()[0];
+			if (!ocspRequest.Verify(cert.GetPublicKey()))
+			{
+				Fail("extra version encoding test failed");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			string signDN = "O=Bouncy Castle, C=AU";
+			AsymmetricCipherKeyPair signKP = OcspTestUtil.MakeKeyPair();
+			X509Certificate testCert = OcspTestUtil.MakeCertificate(signKP, signDN, signKP, signDN);
+
+			string origDN = "CN=Eric H. Echidna, E=eric at bouncycastle.org, O=Bouncy Castle, C=AU";
+			GeneralName origName = new GeneralName(new X509Name(origDN));
+
+			//
+			// general id value for our test issuer cert and a serial number.
+			//
+			CertificateID   id = new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One);
+
+			//
+			// basic request generation
+			//
+			OcspReqGenerator gen = new OcspReqGenerator();
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			OcspReq req = gen.Generate();
+
+			if (req.IsSigned)
+			{
+				Fail("signed but shouldn't be");
+			}
+
+			X509Certificate[] certs = req.GetCerts();
+
+			if (certs != null)
+			{
+				Fail("null certs expected, but not found");
+			}
+
+			Req[] requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// request generation with signing
+			//
+			X509Certificate[] chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withRSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			certs = req.GetCerts();
+
+			if (certs == null)
+			{
+				Fail("null certs found");
+			}
+
+			if (certs.Length != 1 || !testCert.Equals(certs[0]))
+			{
+				Fail("incorrect certs found in request");
+			}
+
+			//
+			// encoding test
+			//
+			byte[] reqEnc = req.GetEncoded();
+
+			OcspReq newReq = new OcspReq(reqEnc);
+
+			if (!newReq.Verify(signKP.Public))
+			{
+				Fail("newReq signature failed to Verify");
+			}
+
+			//
+			// request generation with signing and nonce
+			//
+			chain = new X509Certificate[1];
+
+			gen = new OcspReqGenerator();
+
+			IList oids = new ArrayList();
+			IList values = new ArrayList();
+			byte[] sampleNonce = new byte[16];
+			Random rand = new Random();
+
+			rand.NextBytes(sampleNonce);
+
+			gen.SetRequestorName(new GeneralName(GeneralName.DirectoryName, new X509Name("CN=fred")));
+
+			oids.Add(OcspObjectIdentifiers.PkixOcspNonce);
+			values.Add(new X509Extension(false, new DerOctetString(new DerOctetString(sampleNonce))));
+
+			gen.SetRequestExtensions(new X509Extensions(oids, values));
+
+			gen.AddRequest(
+				new CertificateID(CertificateID.HashSha1, testCert, BigInteger.One));
+
+			chain[0] = testCert;
+
+			req = gen.Generate("SHA1withRSA", signKP.Private, chain);
+
+			if (!req.IsSigned)
+			{
+				Fail("not signed but should be");
+			}
+
+			if (!req.Verify(signKP.Public))
+			{
+				Fail("signature failed to Verify");
+			}
+
+			//
+			// extension check.
+			//
+			ISet extOids = req.GetCriticalExtensionOids();
+
+			if (extOids.Count != 0)
+			{
+				Fail("wrong number of critical extensions in OCSP request.");
+			}
+
+			extOids = req.GetNonCriticalExtensionOids();
+
+			if (extOids.Count != 1)
+			{
+				Fail("wrong number of non-critical extensions in OCSP request.");
+			}
+
+			Asn1OctetString extValue = req.GetExtensionValue(OcspObjectIdentifiers.PkixOcspNonce);
+			Asn1Object extObj = X509ExtensionUtilities.FromExtensionValue(extValue);
+
+			if (!(extObj is Asn1OctetString))
+			{
+				Fail("wrong extension type found.");
+			}
+
+			byte[] compareNonce = ((Asn1OctetString) extObj).GetOctets();
+
+			if (!AreEqual(compareNonce, sampleNonce))
+			{
+				Fail("wrong extension value found.");
+			}
+
+			//
+			// request list check
+			//
+			requests = req.GetRequestList();
+
+			if (!requests[0].GetCertID().Equals(id))
+			{
+				Fail("Failed isFor test");
+			}
+
+			//
+			// response parsing - test 1
+			//
+			OcspResp response = new OcspResp(testResp1);
+
+			if (response.Status != 0)
+			{
+				Fail("response status not zero.");
+			}
+
+			BasicOcspResp brep = (BasicOcspResp) response.GetResponseObject();
+			chain = brep.GetCerts();
+
+			if (!brep.Verify(chain[0].GetPublicKey()))
+			{
+				Fail("response 1 failed to Verify.");
+			}
+
+			//
+			// test 2
+			//
+			SingleResp[] singleResp = brep.Responses;
+
+			response = new OcspResp(testResp2);
+
+			if (response.Status != 0)
+			{
+				Fail("response status not zero.");
+			}
+
+			brep = (BasicOcspResp)response.GetResponseObject();
+			chain = brep.GetCerts();
+
+			if (!brep.Verify(chain[0].GetPublicKey()))
+			{
+				Fail("response 2 failed to Verify.");
+			}
+
+			singleResp = brep.Responses;
+
+			//
+			// simple response generation
+			//
+			OCSPRespGenerator respGen = new OCSPRespGenerator();
+			OcspResp resp = respGen.Generate(OCSPRespGenerator.Successful, response.GetResponseObject());
+
+			if (!resp.GetResponseObject().Equals(response.GetResponseObject()))
+			{
+				Fail("response fails to match");
+			}
+
+			doTestECDsa();
+			doTestRsa();
+			doTestIrregularVersionReq();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new OcspTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTestUtil.cs b/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTestUtil.cs
new file mode 100644
index 0000000..53b8f5b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/ocsp/test/OCSPTestUtil.cs
@@ -0,0 +1,147 @@
+using System;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Ocsp.Tests
+{
+	public class OcspTestUtil
+	{
+		public static SecureRandom rand;
+		public static IAsymmetricCipherKeyPairGenerator kpg, ecKpg;
+		public static CipherKeyGenerator desede128kg;
+		public static CipherKeyGenerator desede192kg;
+		public static CipherKeyGenerator rc240kg;
+		public static CipherKeyGenerator rc264kg;
+		public static CipherKeyGenerator rc2128kg;
+		public static BigInteger serialNumber;
+
+		public static readonly bool Debug = true;
+
+		static OcspTestUtil()
+		{
+			rand = new SecureRandom();
+
+//			kpg  = KeyPairGenerator.GetInstance("RSA");
+//			kpg.initialize(1024, rand);
+			kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			kpg.Init(new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), rand, 1024, 25));
+
+			serialNumber = BigInteger.One;
+
+			ecKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+			ecKpg.Init(new KeyGenerationParameters(rand, 192));
+		}
+
+		public static AsymmetricCipherKeyPair MakeKeyPair()
+		{
+			return kpg.GenerateKeyPair();
+		}
+
+		public static AsymmetricCipherKeyPair MakeECKeyPair()
+		{
+			return ecKpg.GenerateKeyPair();
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false);
+		}
+
+		public static X509Certificate MakeECDsaCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeECDsaCertificate(_subKP, _subDN, _issKP, _issDN, false);
+		}
+
+		public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true);
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca)
+		{
+			return MakeCertificate(_subKP,_subDN, _issKP, _issDN, "MD5withRSA", _ca);
+		}
+
+		public static X509Certificate MakeECDsaCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca)
+		{
+			return MakeCertificate(_subKP,_subDN, _issKP, _issDN, "SHA1WithECDSA", _ca);
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, string algorithm, bool _ca)
+		{
+			AsymmetricKeyParameter _subPub = _subKP.Public;
+			AsymmetricKeyParameter _issPriv = _issKP.Private;
+			AsymmetricKeyParameter _issPub = _issKP.Public;
+
+			X509V3CertificateGenerator _v3CertGen = new X509V3CertificateGenerator();
+
+			_v3CertGen.Reset();
+			_v3CertGen.SetSerialNumber(allocateSerialNumber());
+			_v3CertGen.SetIssuerDN(new X509Name(_issDN));
+			_v3CertGen.SetNotBefore(DateTime.UtcNow);
+			_v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100));
+			_v3CertGen.SetSubjectDN(new X509Name(_subDN));
+			_v3CertGen.SetPublicKey(_subPub);
+			_v3CertGen.SetSignatureAlgorithm(algorithm);
+
+			_v3CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false,
+				createSubjectKeyId(_subPub));
+
+			_v3CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false,
+				createAuthorityKeyId(_issPub));
+
+			_v3CertGen.AddExtension(X509Extensions.BasicConstraints, false,
+				new BasicConstraints(_ca));
+
+			X509Certificate _cert = _v3CertGen.Generate(_issPriv);
+
+			_cert.CheckValidity(DateTime.UtcNow);
+			_cert.Verify(_issPub);
+
+			return _cert;
+		}
+
+		/*
+		 *
+		 * INTERNAL METHODS
+		 *
+		 */
+
+		private static AuthorityKeyIdentifier createAuthorityKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
+			return new AuthorityKeyIdentifier(_info);
+		}
+
+		private static SubjectKeyIdentifier createSubjectKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
+			return new SubjectKeyIdentifier(_info);
+		}
+
+		private static BigInteger allocateSerialNumber()
+		{
+			BigInteger _tmp = serialNumber;
+			serialNumber = serialNumber.Add(BigInteger.One);
+			return _tmp;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/ByteArrayHandler.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/ByteArrayHandler.cs
new file mode 100644
index 0000000..676db87
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/ByteArrayHandler.cs
@@ -0,0 +1,195 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * Simple routine to encrypt and decrypt using a passphrase.
+    * This service routine provides the basic PGP services between
+    * byte arrays.
+    *
+    * Note: this code plays no attention to -Console in the file name
+    * the specification of "_CONSOLE" in the filename.
+    * It also expects that a single pass phrase will have been used.
+    *
+    */
+    public sealed class ByteArrayHandler
+    {
+        private ByteArrayHandler()
+        {
+        }
+
+        /**
+        * decrypt the passed in message stream
+        *
+        * @param encrypted  The message to be decrypted.
+        * @param passPhrase Pass phrase (key)
+        *
+        * @return Clear text as a byte array.  I18N considerations are
+        *         not handled by this routine
+        * @exception IOException
+        * @exception PgpException
+        */
+        public static byte[] Decrypt(
+            byte[] encrypted,
+            char[] passPhrase)
+        {
+            Stream inputStream = new MemoryStream(encrypted);
+
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+            PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);
+            PgpEncryptedDataList enc = null;
+            PgpObject o = pgpF.NextPgpObject();
+
+			//
+            // the first object might be a PGP marker packet.
+            //
+            if (o is PgpEncryptedDataList)
+            {
+                enc = (PgpEncryptedDataList) o;
+            }
+            else
+            {
+                enc = (PgpEncryptedDataList) pgpF.NextPgpObject();
+            }
+
+            PgpPbeEncryptedData pbe = (PgpPbeEncryptedData)enc[0];
+
+            Stream clear = pbe.GetDataStream(passPhrase);
+
+            PgpObjectFactory pgpFact = new PgpObjectFactory(clear);
+
+            PgpCompressedData cData = (PgpCompressedData) pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(cData.GetDataStream());
+
+            PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject();
+
+            Stream unc = ld.GetInputStream();
+
+			return Streams.ReadAll(unc);
+        }
+
+        /**
+        * Simple PGP encryptor between byte[].
+        *
+        * @param clearData  The test to be encrypted
+        * @param passPhrase The pass phrase (key).  This method assumes that the
+        *                   key is a simple pass phrase, and does not yet support
+        *                   RSA or more sophisiticated keying.
+        * @param fileName   File name. This is used in the Literal Data Packet (tag 11)
+        *                   which is really inly important if the data is to be
+        *                   related to a file to be recovered later.  Because this
+        *                   routine does not know the source of the information, the
+        *                   caller can set something here for file name use that
+        *                   will be carried.  If this routine is being used to
+        *                   encrypt SOAP MIME bodies, for example, use the file name from the
+        *                   MIME type, if applicable. Or anything else appropriate.
+        *
+        * @param armor
+        *
+        * @return encrypted data.
+        * @exception IOException
+        * @exception PgpException
+        */
+        public static byte[] Encrypt(
+            byte[]						clearData,
+            char[]						passPhrase,
+            string						fileName,
+            SymmetricKeyAlgorithmTag	algorithm,
+            bool						armor)
+        {
+            if (fileName == null)
+            {
+                fileName = PgpLiteralData.Console;
+            }
+
+			byte[] compressedData = Compress(clearData, fileName, CompressionAlgorithmTag.Zip);
+
+			MemoryStream bOut = new MemoryStream();
+
+			Stream output = bOut;
+			if (armor)
+			{
+				output = new ArmoredOutputStream(output);
+			}
+
+			PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(algorithm, new SecureRandom());
+            encGen.AddMethod(passPhrase);
+
+			Stream encOut = encGen.Open(output, compressedData.Length);
+
+			encOut.Write(compressedData, 0, compressedData.Length);
+			encOut.Close();
+			
+			if (armor)
+			{
+				output.Close();
+			}
+
+			return bOut.ToArray();
+        }
+
+		private static byte[] Compress(byte[] clearData, string fileName, CompressionAlgorithmTag algorithm)
+		{
+            MemoryStream bOut = new MemoryStream();
+
+            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm);
+            Stream cos = comData.Open(bOut); // open it with the final destination
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+
+            // we want to Generate compressed data. This might be a user option later,
+            // in which case we would pass in bOut.
+            Stream pOut = lData.Open(
+				cos,					// the compressed output stream
+                PgpLiteralData.Binary,
+                fileName,				// "filename" to store
+                clearData.Length,		// length of clear data
+                DateTime.UtcNow			// current time
+            );
+
+			pOut.Write(clearData, 0, clearData.Length);
+			pOut.Close();
+
+			comData.Close();
+
+			return bOut.ToArray();
+		}
+
+		private static string GetAsciiString(byte[] bs)
+		{
+			return Encoding.ASCII.GetString(bs, 0, bs.Length);
+		}
+
+        public static void Main(
+			string[] args)
+        {
+            string passPhrase = "Dick Beck";
+            char[] passArray = passPhrase.ToCharArray();
+
+            byte[] original = Encoding.ASCII.GetBytes("Hello world");
+            Console.WriteLine("Starting PGP test");
+            byte[] encrypted = Encrypt(original, passArray, "iway", SymmetricKeyAlgorithmTag.Cast5, true);
+
+            Console.WriteLine("\nencrypted data = '"+Hex.ToHexString(encrypted)+"'");
+            byte[] decrypted= Decrypt(encrypted,passArray);
+
+            Console.WriteLine("\ndecrypted data = '"+GetAsciiString(decrypted)+"'");
+
+            encrypted = Encrypt(original, passArray, "iway", SymmetricKeyAlgorithmTag.Aes256, false);
+
+            Console.WriteLine("\nencrypted data = '"+Hex.ToHexString(encrypted)+"'");
+            decrypted= Decrypt(encrypted, passArray);
+
+            Console.WriteLine("\ndecrypted data = '"+GetAsciiString(decrypted)+"'");
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/ClearSignedFileProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/ClearSignedFileProcessor.cs
new file mode 100644
index 0000000..14fa372
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/ClearSignedFileProcessor.cs
@@ -0,0 +1,375 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that creates clear signed files and verifies them.
+    * <p>
+    * To sign a file: ClearSignedFileProcessor -s fileName secretKey passPhrase.
+	* </p>
+    * <p>
+    * To decrypt: ClearSignedFileProcessor -v fileName signatureFile publicKeyFile.
+	* </p>
+    */
+    public sealed class ClearSignedFileProcessor
+    {
+        private ClearSignedFileProcessor()
+        {
+        }
+
+		private static int ReadInputLine(
+			MemoryStream	bOut,
+			Stream			fIn)
+		{
+			bOut.SetLength(0);
+
+			int lookAhead = -1;
+			int ch;
+
+			while ((ch = fIn.ReadByte()) >= 0)
+			{
+				bOut.WriteByte((byte) ch);
+				if (ch == '\r' || ch == '\n')
+				{
+					lookAhead = ReadPassedEol(bOut, ch, fIn);
+					break;
+				}
+			}
+
+			return lookAhead;
+		}
+
+		private static int ReadInputLine(
+			MemoryStream	bOut,
+			int				lookAhead,
+			Stream			fIn)
+		{
+			bOut.SetLength(0);
+
+			int ch = lookAhead;
+
+			do
+			{
+				bOut.WriteByte((byte) ch);
+				if (ch == '\r' || ch == '\n')
+				{
+					lookAhead = ReadPassedEol(bOut, ch, fIn);
+					break;
+				}
+			}
+			while ((ch = fIn.ReadByte()) >= 0);
+
+			if (ch < 0)
+			{
+				lookAhead = -1;
+			}
+
+			return lookAhead;
+		}
+
+		private static int ReadPassedEol(
+			MemoryStream	bOut,
+			int				lastCh,
+			Stream			fIn)
+		{
+			int lookAhead = fIn.ReadByte();
+
+			if (lastCh == '\r' && lookAhead == '\n')
+			{
+				bOut.WriteByte((byte) lookAhead);
+				lookAhead = fIn.ReadByte();
+			}
+
+			return lookAhead;
+		}
+
+		/*
+		* verify a clear text signed file
+		*/
+        private static void VerifyFile(
+            Stream	inputStream,
+            Stream	keyIn,
+			string	resultName)
+        {
+			ArmoredInputStream aIn = new ArmoredInputStream(inputStream);
+			Stream outStr = File.Create(resultName);
+
+			//
+			// write out signed section using the local line separator.
+			// note: trailing white space needs to be removed from the end of
+			// each line RFC 4880 Section 7.1
+			//
+			MemoryStream lineOut = new MemoryStream();
+			int lookAhead = ReadInputLine(lineOut, aIn);
+			byte[] lineSep = LineSeparator;
+
+			if (lookAhead != -1 && aIn.IsClearText())
+			{
+				byte[] line = lineOut.ToArray();
+				outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
+				outStr.Write(lineSep, 0, lineSep.Length);
+
+				while (lookAhead != -1 && aIn.IsClearText())
+				{
+					lookAhead = ReadInputLine(lineOut, lookAhead, aIn);
+                
+					line = lineOut.ToArray();
+					outStr.Write(line, 0, GetLengthWithoutSeparatorOrTrailingWhitespace(line));
+					outStr.Write(lineSep, 0, lineSep.Length);
+				}
+			}
+
+			outStr.Close();
+
+			PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(keyIn);
+
+			PgpObjectFactory pgpFact = new PgpObjectFactory(aIn);
+			PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject();
+			PgpSignature sig = p3[0];
+
+			sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId));
+
+			//
+			// read the input, making sure we ignore the last newline.
+			//
+			Stream sigIn = File.OpenRead(resultName);
+
+			lookAhead = ReadInputLine(lineOut, sigIn);
+
+			ProcessLine(sig, lineOut.ToArray());
+
+			if (lookAhead != -1)
+			{
+				do
+				{
+					lookAhead = ReadInputLine(lineOut, lookAhead, sigIn);
+
+					sig.Update((byte) '\r');
+					sig.Update((byte) '\n');
+
+					ProcessLine(sig, lineOut.ToArray());
+				}
+				while (lookAhead != -1);
+			}
+
+			sigIn.Close();
+
+			if (sig.Verify())
+            {
+                Console.WriteLine("signature verified.");
+            }
+            else
+            {
+                Console.WriteLine("signature verification failed.");
+            }
+        }
+
+		private static byte[] LineSeparator
+		{
+			get { return Encoding.ASCII.GetBytes(SimpleTest.NewLine); }
+		}
+
+        /*
+        * create a clear text signed file.
+        */
+        private static void SignFile(
+            string	fileName,
+            Stream	keyIn,
+            Stream	outputStream,
+            char[]	pass,
+			string	digestName)
+        {
+			HashAlgorithmTag digest;
+
+			if (digestName.Equals("SHA256"))
+			{
+				digest = HashAlgorithmTag.Sha256;
+			}
+			else if (digestName.Equals("SHA384"))
+			{
+				digest = HashAlgorithmTag.Sha384;
+			}
+			else if (digestName.Equals("SHA512"))
+			{
+				digest = HashAlgorithmTag.Sha512;
+			}
+			else if (digestName.Equals("MD5"))
+			{
+				digest = HashAlgorithmTag.MD5;
+			}
+			else if (digestName.Equals("RIPEMD160"))
+			{
+				digest = HashAlgorithmTag.RipeMD160;
+			}
+			else
+			{
+				digest = HashAlgorithmTag.Sha1;
+			}
+
+			PgpSecretKey                    pgpSecKey = PgpExampleUtilities.ReadSecretKey(keyIn);
+            PgpPrivateKey                   pgpPrivKey = pgpSecKey.ExtractPrivateKey(pass);
+            PgpSignatureGenerator           sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, digest);
+            PgpSignatureSubpacketGenerator  spGen = new PgpSignatureSubpacketGenerator();
+
+			sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);
+
+			IEnumerator enumerator = pgpSecKey.PublicKey.GetUserIds().GetEnumerator();
+            if (enumerator.MoveNext())
+            {
+                spGen.SetSignerUserId(false, (string) enumerator.Current);
+                sGen.SetHashedSubpackets(spGen.Generate());
+            }
+
+            Stream fIn = File.OpenRead(fileName);
+			ArmoredOutputStream aOut = new ArmoredOutputStream(outputStream);
+
+			aOut.BeginClearText(digest);
+
+			//
+			// note the last \n/\r/\r\n in the file is ignored
+			//
+			MemoryStream lineOut = new MemoryStream();
+			int lookAhead = ReadInputLine(lineOut, fIn);
+
+			ProcessLine(aOut, sGen, lineOut.ToArray());
+
+			if (lookAhead != -1)
+			{
+				do
+				{
+					lookAhead = ReadInputLine(lineOut, lookAhead, fIn);
+
+					sGen.Update((byte) '\r');
+					sGen.Update((byte) '\n');
+
+					ProcessLine(aOut, sGen, lineOut.ToArray());
+				}
+				while (lookAhead != -1);
+			}
+
+			fIn.Close();
+
+			aOut.EndClearText();
+
+			BcpgOutputStream bOut = new BcpgOutputStream(aOut);
+
+            sGen.Generate().Encode(bOut);
+
+            aOut.Close();
+        }
+
+		private static void ProcessLine(
+			PgpSignature	sig,
+			byte[]			line)
+		{
+			// note: trailing white space needs to be removed from the end of
+			// each line for signature calculation RFC 4880 Section 7.1
+			int length = GetLengthWithoutWhiteSpace(line);
+			if (length > 0)
+			{
+				sig.Update(line, 0, length);
+			}
+		}
+
+		private static void ProcessLine(
+			Stream					aOut,
+			PgpSignatureGenerator	sGen,
+			byte[]					line)
+		{
+			int length = GetLengthWithoutWhiteSpace(line);
+			if (length > 0)
+			{
+				sGen.Update(line, 0, length);
+			}
+
+			aOut.Write(line, 0, line.Length);
+		}
+
+		private static int GetLengthWithoutSeparatorOrTrailingWhitespace(byte[] line)
+		{
+			int end = line.Length - 1;
+
+			while (end >= 0 && IsWhiteSpace(line[end]))
+			{
+				end--;
+			}
+
+			return end + 1;
+		}
+
+		private static bool IsLineEnding(
+			byte b)
+		{
+			return b == '\r' || b == '\n';
+		}
+
+		private static int GetLengthWithoutWhiteSpace(
+			byte[] line)
+		{
+			int end = line.Length - 1;
+
+			while (end >= 0 && IsWhiteSpace(line[end]))
+			{
+				end--;
+			}
+
+			return end + 1;
+		}
+
+		private static bool IsWhiteSpace(
+			byte b)
+		{
+			return IsLineEnding(b) || b == '\t' || b == ' ';
+		}
+
+		public static int Main(
+            string[] args)
+        {
+            if (args[0].Equals("-s"))
+            {
+				Stream fis = File.OpenRead(args[2]);
+				Stream fos = File.Create(args[1] + ".asc");
+
+				Stream keyIn = PgpUtilities.GetDecoderStream(fis);
+
+				string digestName = (args.Length == 4)
+					?	"SHA1"
+					:	args[4];
+
+				SignFile(args[1], keyIn, fos, args[3].ToCharArray(), digestName);
+
+				fis.Close();
+				fos.Close();
+            }
+            else if (args[0].Equals("-v"))
+            {
+				if (args[1].IndexOf(".asc") < 0)
+				{
+					Console.Error.WriteLine("file needs to end in \".asc\"");
+					return 1;
+				}
+
+				Stream fin = File.OpenRead(args[1]);
+				Stream fis = File.OpenRead(args[2]);
+
+				Stream keyIn = PgpUtilities.GetDecoderStream(fis);
+
+				VerifyFile(fin, keyIn, args[1].Substring(0, args[1].Length - 4));
+
+				fin.Close();
+				fis.Close();
+            }
+            else
+            {
+                Console.Error.WriteLine("usage: ClearSignedFileProcessor [-s file keyfile passPhrase]|[-v sigFile keyFile]");
+            }
+			return 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/DetachedSignatureProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DetachedSignatureProcessor.cs
new file mode 100644
index 0000000..c495984
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DetachedSignatureProcessor.cs
@@ -0,0 +1,167 @@
+using System;
+using System.Collections;
+using System.IO;
+
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that creates seperate signatures for files and verifies them.
+    * <p>
+    * To sign a file: DetachedSignatureProcessor -s [-a] fileName secretKey passPhrase.<br/>
+    * If -a is specified the output file will be "ascii-armored".</p>
+    * <p>
+    * To decrypt: DetachedSignatureProcessor -v  fileName signatureFile publicKeyFile.</p>
+    * <p>
+    * Note: this example will silently overwrite files.
+    * It also expects that a single pass phrase
+    * will have been used.</p>
+    */
+    public sealed class DetachedSignatureProcessor
+    {
+        private DetachedSignatureProcessor()
+        {
+        }
+
+		private static void VerifySignature(
+			string	fileName,
+			string	inputFileName,
+			string	keyFileName)
+		{
+			using (Stream input = File.OpenRead(inputFileName),
+				keyIn = File.OpenRead(keyFileName))
+			{
+				VerifySignature(fileName, input, keyIn);
+			}
+		}
+
+		/**
+        * verify the signature in in against the file fileName.
+        */
+        private static void VerifySignature(
+            string	fileName,
+            Stream	inputStream,
+            Stream	keyIn)
+        {
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+            PgpObjectFactory pgpFact = new PgpObjectFactory(inputStream);
+            PgpSignatureList p3 = null;
+            PgpObject o = pgpFact.NextPgpObject();
+            if (o is PgpCompressedData)
+            {
+                PgpCompressedData c1 = (PgpCompressedData)o;
+                pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+                p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+            }
+            else
+            {
+                p3 = (PgpSignatureList)o;
+            }
+
+            PgpPublicKeyRingBundle pgpPubRingCollection = new PgpPublicKeyRingBundle(
+				PgpUtilities.GetDecoderStream(keyIn));
+            Stream dIn = File.OpenRead(fileName);
+            PgpSignature sig = p3[0];
+            PgpPublicKey key = pgpPubRingCollection.GetPublicKey(sig.KeyId);
+            sig.InitVerify(key);
+
+			int ch;
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                sig.Update((byte)ch);
+            }
+
+			dIn.Close();
+
+			if (sig.Verify())
+            {
+                Console.WriteLine("signature verified.");
+            }
+            else
+            {
+                Console.WriteLine("signature verification failed.");
+            }
+        }
+
+		private static void CreateSignature(
+			string	inputFileName,
+			string	keyFileName,
+			string	outputFileName,
+			char[]	pass,
+			bool	armor)
+		{
+			using (Stream keyIn = File.OpenRead(keyFileName),
+				output = File.OpenRead(outputFileName))
+			{
+				CreateSignature(inputFileName, keyIn, output, pass, armor);
+			}
+		}
+
+		private static void CreateSignature(
+			string	fileName,
+			Stream	keyIn,
+			Stream	outputStream,
+			char[]	pass,
+			bool	armor)
+        {
+            if (armor)
+            {
+                outputStream = new ArmoredOutputStream(outputStream);
+            }
+
+            PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn);
+            PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass);
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+				pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+
+			sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+
+			BcpgOutputStream bOut = new BcpgOutputStream(outputStream);
+
+			Stream fIn = File.OpenRead(fileName);
+
+            int ch;
+            while ((ch = fIn.ReadByte()) >= 0)
+            {
+                sGen.Update((byte)ch);
+            }
+
+			fIn.Close();
+
+			sGen.Generate().Encode(bOut);
+
+			if (armor)
+			{
+				outputStream.Close();
+			}
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            if (args[0].Equals("-s"))
+            {
+                if (args[1].Equals("-a"))
+                {
+					CreateSignature(args[2], args[3], args[2] + ".asc", args[4].ToCharArray(), true);
+                }
+                else
+                {
+					CreateSignature(args[1], args[2], args[1] + ".bpg", args[3].ToCharArray(), false);
+                }
+            }
+            else if (args[0].Equals("-v"))
+            {
+				VerifySignature(args[1], args[2], args[3]);
+			}
+            else
+            {
+                Console.Error.WriteLine("usage: DetachedSignatureProcessor [-s [-a] file keyfile passPhrase]|[-v file sigFile keyFile]");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/DirectKeySignature.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DirectKeySignature.cs
new file mode 100644
index 0000000..a6bf8e7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DirectKeySignature.cs
@@ -0,0 +1,140 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg;
+using Org.BouncyCastle.Bcpg.Sig;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+	/**
+	* A simple utility class that directly signs a public key and writes the signed key to "SignedKey.asc" in 
+	* the current working directory.
+	* <p>
+	* To sign a key: DirectKeySignature secretKeyFile secretKeyPass publicKeyFile(key to be signed) NotationName NotationValue.<br/>
+	* </p><p>
+	* To display a NotationData packet from a publicKey previously signed: DirectKeySignature signedPublicKeyFile.<br/>
+	* </p><p>
+	* <b>Note</b>: this example will silently overwrite files, nor does it pay any attention to
+	* the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
+	* will have been used.
+	* </p>
+	*/
+	public class DirectKeySignature
+	{
+		public static void Main(
+			string[] args)
+		{
+			if (args.Length == 1)
+			{
+				Stream fis = File.OpenRead(args[0]);
+
+				PgpPublicKeyRing ring = new PgpPublicKeyRing(
+					PgpUtilities.GetDecoderStream(fis));
+				PgpPublicKey key = ring.GetPublicKey();
+
+				// iterate through all direct key signautures and look for NotationData subpackets
+				foreach (PgpSignature sig in key.GetSignaturesOfType(PgpSignature.DirectKey))
+				{
+					Console.WriteLine("Signature date is: "
+						+ sig.GetHashedSubPackets().GetSignatureCreationTime());
+
+					NotationData[] data = sig.GetHashedSubPackets().GetNotationDataOccurences();
+
+					for (int i = 0; i < data.Length; i++)
+					{
+						Console.WriteLine("Found Notaion named '" + data[i].GetNotationName()
+							+"' with content '" + data[i].GetNotationValue() + "'.");
+					}
+				}
+
+				fis.Close();
+			}
+			else if (args.Length == 5)
+			{
+				Stream secFis = File.OpenRead(args[0]);
+				Stream pubFis = File.OpenRead(args[2]);
+
+				// gather command line arguments
+				PgpSecretKeyRing secRing = new PgpSecretKeyRing(
+					PgpUtilities.GetDecoderStream(secFis));
+				String secretKeyPass = args[1];
+				PgpPublicKeyRing ring = new PgpPublicKeyRing(
+					PgpUtilities.GetDecoderStream(pubFis));
+				String notationName = args[3];
+				String notationValue = args[4];
+
+				// create the signed keyRing
+				PgpPublicKeyRing sRing = null;
+				sRing = new PgpPublicKeyRing(
+					new MemoryStream(
+						SignPublicKey(secRing.GetSecretKey(), secretKeyPass,
+							ring.GetPublicKey(), notationName, notationValue, true),
+						false));
+				ring = sRing;
+
+				secFis.Close();
+				pubFis.Close();
+
+				Stream fos = File.Create("SignedKey.asc");
+
+				// write the created keyRing to file
+				ArmoredOutputStream aOut = new ArmoredOutputStream(fos);
+				sRing.Encode(aOut);
+				aOut.Close();
+
+				// Note: ArmoredOutputStream.Close() leaves underlying stream open
+				fos.Close();
+			}
+			else
+			{
+				Console.Error.WriteLine("usage: DirectKeySignature secretKeyFile secretKeyPass publicKeyFile(key to be signed) NotationName NotationValue");
+				Console.Error.WriteLine("or: DirectKeySignature signedPublicKeyFile");
+			}
+		}
+
+		private static byte[] SignPublicKey(
+			PgpSecretKey	secretKey,
+			string			secretKeyPass,
+			PgpPublicKey	keyToBeSigned,
+			string			notationName,
+			string			notationValue,
+			bool			armor)
+		{
+			Stream os = new MemoryStream();
+			if (armor)
+			{
+				os = new ArmoredOutputStream(os);
+			}
+
+			PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(
+				secretKeyPass.ToCharArray());
+
+			PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+				secretKey.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+
+			sGen.InitSign(PgpSignature.DirectKey, pgpPrivKey);
+
+			BcpgOutputStream bOut = new BcpgOutputStream(os);
+
+			sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+			PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
+
+			bool isHumanReadable = true;
+
+			spGen.SetNotationData(true, isHumanReadable, notationName, notationValue);
+
+			PgpSignatureSubpacketVector packetVector = spGen.Generate();
+			sGen.SetHashedSubpackets(packetVector);
+
+			bOut.Flush();
+
+			if (armor)
+			{
+				os.Close();
+			}
+
+			return PgpPublicKey.AddCertification(keyToBeSigned, sGen.Generate()).GetEncoded();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs
new file mode 100644
index 0000000..6040351
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/DsaElGamalKeyRingGenerator.cs
@@ -0,0 +1,134 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that Generates a public/secret keyring containing a DSA signing
+    * key and an El Gamal key for encryption.
+    * <p>
+    * usage: DSAElGamalKeyRingGenerator [-a] identity passPhrase</p>
+    * <p>
+    * Where identity is the name to be associated with the public key. The keys are placed
+    * in the files pub.[asc|bpg] and secret.[asc|bpg].</p>
+    * <p>
+    * <b>Note</b>: this example encrypts the secret key using AES_256, many PGP products still
+    * do not support this, if you are having problems importing keys try changing the algorithm
+    * id to PgpEncryptedData.Cast5. CAST5 is more widelysupported.</p>
+    */
+    public sealed class DsaElGamalKeyRingGenerator
+    {
+        private DsaElGamalKeyRingGenerator()
+        {
+        }
+
+		private static void ExportKeyPair(
+            Stream					secretOut,
+            Stream					publicOut,
+            AsymmetricCipherKeyPair	dsaKp,
+            AsymmetricCipherKeyPair	elgKp,
+            string					identity,
+            char[]					passPhrase,
+            bool					armor)
+        {
+            if (armor)
+            {
+                secretOut = new ArmoredOutputStream(secretOut);
+            }
+
+			PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow);
+            PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);
+
+			PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
+				identity, SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, new SecureRandom());
+
+			keyRingGen.AddSubKey(elgKeyPair);
+
+			keyRingGen.GenerateSecretKeyRing().Encode(secretOut);
+
+			if (armor)
+            {
+				secretOut.Close();
+				publicOut = new ArmoredOutputStream(publicOut);
+            }
+
+			keyRingGen.GeneratePublicKeyRing().Encode(publicOut);
+
+			if (armor)
+			{
+				publicOut.Close();
+			}
+        }
+
+		public static int Main(
+            string[] args)
+        {
+            if (args.Length < 2)
+            {
+                Console.WriteLine("DsaElGamalKeyRingGenerator [-a] identity passPhrase");
+                return 0;
+            }
+
+			IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(1024, 80, new SecureRandom());
+            DsaParameters dsaParams = pGen.GenerateParameters();
+            DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);
+            dsaKpg.Init(kgp);
+
+
+			//
+            // this takes a while as the key generator has to Generate some DSA parameters
+            // before it Generates the key.
+            //
+            AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair();
+
+
+			IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
+
+			BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+            BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+			ElGamalParameters elParams = new ElGamalParameters(p, g);
+            ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
+            elgKpg.Init(elKgp);
+
+			//
+            // this is quicker because we are using preGenerated parameters.
+            //
+            AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair();
+
+			Stream out1, out2;
+			if (args[0].Equals("-a"))
+            {
+                if (args.Length < 3)
+                {
+                    Console.WriteLine("DSAElGamalKeyRingGenerator [-a] identity passPhrase");
+                    return 0;
+                }
+
+				out1 = File.Create("secret.asc");
+                out2 = File.Create("pub.asc");
+
+				ExportKeyPair(out1, out2, dsaKp, elgKp, args[1], args[2].ToCharArray(), true);
+            }
+            else
+            {
+                out1 = File.Create("secret.bpg");
+                out2 = File.Create("pub.bpg");
+
+				ExportKeyPair(out1, out2, dsaKp, elgKp, args[0], args[1].ToCharArray(), false);
+            }
+			out1.Close();
+			out2.Close();
+			return 0;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedFileProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedFileProcessor.cs
new file mode 100644
index 0000000..c77408b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedFileProcessor.cs
@@ -0,0 +1,259 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that encrypts/decrypts public key based
+    * encryption files.
+    * <p>
+    * To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.<br/>
+    * If -a is specified the output file will be "ascii-armored".
+    * If -i is specified the output file will be have integrity checking added.</p>
+    * <p>
+    * To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.</p>
+    * <p>
+	* Note 1: this example will silently overwrite files, nor does it pay any attention to
+	* the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
+	* will have been used.</p>
+	* <p>
+	* Note 2: if an empty file name has been specified in the literal data object contained in the
+	* encrypted packet a file with the name filename.out will be generated in the current working directory.</p>
+    */
+    public sealed class KeyBasedFileProcessor
+    {
+        private KeyBasedFileProcessor()
+        {
+        }
+
+		private static void DecryptFile(
+			string	inputFileName,
+			string	keyFileName,
+			char[]	passwd,
+			string	defaultFileName)
+		{
+			using (Stream input = File.OpenRead(inputFileName),
+			       keyIn = File.OpenRead(keyFileName))
+			{
+				DecryptFile(input, keyIn, passwd, defaultFileName);
+			}
+		}
+
+		/**
+		 * decrypt the passed in message stream
+		 */
+		private static void DecryptFile(
+			Stream	inputStream,
+			Stream	keyIn,
+			char[]	passwd,
+			string	defaultFileName)
+		{
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+            try
+            {
+                PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);
+                PgpEncryptedDataList enc;
+
+                PgpObject o = pgpF.NextPgpObject();
+                //
+                // the first object might be a PGP marker packet.
+                //
+                if (o is PgpEncryptedDataList)
+                {
+                    enc = (PgpEncryptedDataList)o;
+                }
+                else
+                {
+                    enc = (PgpEncryptedDataList)pgpF.NextPgpObject();
+                }
+
+                //
+                // find the secret key
+                //
+                PgpPrivateKey sKey = null;
+                PgpPublicKeyEncryptedData pbe = null;
+				PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(
+					PgpUtilities.GetDecoderStream(keyIn));
+
+				foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
+                {
+                    sKey = PgpExampleUtilities.FindSecretKey(pgpSec, pked.KeyId, passwd);
+
+                    if (sKey != null)
+                    {
+                        pbe = pked;
+                        break;
+                    }
+                }
+
+				if (sKey == null)
+                {
+                    throw new ArgumentException("secret key for message not found.");
+                }
+
+                Stream clear = pbe.GetDataStream(sKey);
+
+                PgpObjectFactory plainFact = new PgpObjectFactory(clear);
+
+                PgpObject message = plainFact.NextPgpObject();
+
+                if (message is PgpCompressedData)
+                {
+                    PgpCompressedData cData = (PgpCompressedData)message;
+                    PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());
+
+                    message = pgpFact.NextPgpObject();
+                }
+
+                if (message is PgpLiteralData)
+                {
+                    PgpLiteralData ld = (PgpLiteralData)message;
+
+					string outFileName = ld.FileName;
+					if (outFileName.Length == 0)
+					{
+						outFileName = defaultFileName;
+					}
+
+					Stream fOut = File.Create(outFileName);
+					Stream unc = ld.GetInputStream();
+					Streams.PipeAll(unc, fOut);
+					fOut.Close();
+                }
+                else if (message is PgpOnePassSignatureList)
+                {
+                    throw new PgpException("encrypted message contains a signed message - not literal data.");
+                }
+                else
+                {
+                    throw new PgpException("message is not a simple encrypted file - type unknown.");
+                }
+
+                if (pbe.IsIntegrityProtected())
+                {
+                    if (!pbe.Verify())
+                    {
+                        Console.Error.WriteLine("message failed integrity check");
+                    }
+                    else
+                    {
+                        Console.Error.WriteLine("message integrity check passed");
+                    }
+                }
+                else
+                {
+                    Console.Error.WriteLine("no message integrity check");
+                }
+            }
+            catch (PgpException e)
+            {
+                Console.Error.WriteLine(e);
+
+                Exception underlyingException = e.InnerException;
+                if (underlyingException != null)
+                {
+                    Console.Error.WriteLine(underlyingException.Message);
+                    Console.Error.WriteLine(underlyingException.StackTrace);
+                }
+            }
+        }
+		
+		private static void EncryptFile(
+			string	outputFileName,
+			string	inputFileName,
+			string	encKeyFileName,
+			bool	armor,
+			bool	withIntegrityCheck)
+		{
+			PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName);
+
+			using (Stream output = File.Create(outputFileName))
+			{
+				EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck);
+			}
+		}
+
+        private static void EncryptFile(
+            Stream			outputStream,
+            string			fileName,
+            PgpPublicKey	encKey,
+            bool			armor,
+            bool			withIntegrityCheck)
+        {
+            if (armor)
+            {
+                outputStream = new ArmoredOutputStream(outputStream);
+            }
+
+            try
+            {
+            	byte[] bytes = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip);
+
+				PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(
+					SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
+				encGen.AddMethod(encKey);
+
+				Stream cOut = encGen.Open(outputStream, bytes.Length);
+
+				cOut.Write(bytes, 0, bytes.Length);
+				cOut.Close();
+
+				if (armor)
+				{
+					outputStream.Close();
+				}
+            }
+            catch (PgpException e)
+            {
+                Console.Error.WriteLine(e);
+
+                Exception underlyingException = e.InnerException;
+                if (underlyingException != null)
+                {
+                    Console.Error.WriteLine(underlyingException.Message);
+                    Console.Error.WriteLine(underlyingException.StackTrace);
+                }
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            if (args.Length == 0)
+            {
+                Console.Error.WriteLine("usage: KeyBasedFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
+                return;
+            }
+
+            if (args[0].Equals("-e"))
+            {
+                if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia"))
+                {
+					EncryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].IndexOf('i') > 0));
+                }
+                else if (args[1].Equals("-i"))
+                {
+					EncryptFile(args[2] + ".bpg", args[2], args[3], false, true);
+                }
+                else
+                {
+					EncryptFile(args[1] + ".bpg", args[1], args[2], false, false);
+                }
+            }
+            else if (args[0].Equals("-d"))
+            {
+				DecryptFile(args[1], args[2], args[3].ToCharArray(), new FileInfo(args[1]).Name + ".out");
+            }
+            else
+            {
+                Console.Error.WriteLine("usage: KeyBasedFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs
new file mode 100644
index 0000000..7fb00a3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/KeyBasedLargeFileProcessor.cs
@@ -0,0 +1,267 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that encrypts/decrypts public key based
+    * encryption large files.
+    * <p>
+    * To encrypt a file: KeyBasedLargeFileProcessor -e [-a|-ai] fileName publicKeyFile.<br/>
+    * If -a is specified the output file will be "ascii-armored".
+    * If -i is specified the output file will be have integrity checking added.</p>
+    * <p>
+    * To decrypt: KeyBasedLargeFileProcessor -d fileName secretKeyFile passPhrase.</p>
+    * <p>
+    * Note 1: this example will silently overwrite files, nor does it pay any attention to
+    * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
+    * will have been used.</p>
+    * <p>
+    * Note 2: this example Generates partial packets to encode the file, the output it Generates
+    * will not be readable by older PGP products or products that don't support partial packet
+    * encoding.</p>
+	* <p>
+	* Note 3: if an empty file name has been specified in the literal data object contained in the
+	* encrypted packet a file with the name filename.out will be generated in the current working directory.</p>
+    */
+    public sealed class KeyBasedLargeFileProcessor
+    {
+        private KeyBasedLargeFileProcessor()
+        {
+        }
+
+		private static void DecryptFile(
+			string	inputFileName,
+			string	keyFileName,
+			char[]	passwd,
+			string	defaultFileName)
+		{
+			using (Stream input = File.OpenRead(inputFileName),
+			       keyIn = File.OpenRead(keyFileName))
+			{
+				DecryptFile(input, keyIn, passwd, defaultFileName);
+			}
+		}
+
+		/**
+        * decrypt the passed in message stream
+        */
+        private static void DecryptFile(
+            Stream	inputStream,
+            Stream	keyIn,
+			char[]	passwd,
+			string	defaultFileName)
+		{
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+            try
+            {
+                PgpObjectFactory        pgpF = new PgpObjectFactory(inputStream);
+                PgpEncryptedDataList    enc;
+
+                PgpObject o = pgpF.NextPgpObject();
+                //
+                // the first object might be a PGP marker packet.
+                //
+                if (o is PgpEncryptedDataList)
+                {
+                    enc = (PgpEncryptedDataList)o;
+                }
+                else
+                {
+                    enc = (PgpEncryptedDataList)pgpF.NextPgpObject();
+                }
+
+                //
+                // find the secret key
+                //
+                PgpPrivateKey sKey = null;
+                PgpPublicKeyEncryptedData pbe = null;
+				PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(
+					PgpUtilities.GetDecoderStream(keyIn));
+
+				foreach (PgpPublicKeyEncryptedData pked in enc.GetEncryptedDataObjects())
+                {
+                    sKey = PgpExampleUtilities.FindSecretKey(pgpSec, pked.KeyId, passwd);
+
+                    if (sKey != null)
+                    {
+                        pbe = pked;
+                        break;
+                    }
+                }
+
+                if (sKey == null)
+                {
+                    throw new ArgumentException("secret key for message not found.");
+                }
+
+                Stream clear = pbe.GetDataStream(sKey);
+
+                PgpObjectFactory plainFact = new PgpObjectFactory(clear);
+
+                PgpCompressedData cData = (PgpCompressedData) plainFact.NextPgpObject();
+
+                PgpObjectFactory pgpFact = new PgpObjectFactory(cData.GetDataStream());
+
+                PgpObject message = pgpFact.NextPgpObject();
+
+                if (message is PgpLiteralData)
+                {
+                    PgpLiteralData ld = (PgpLiteralData)message;
+
+					string outFileName = ld.FileName;
+					if (outFileName.Length == 0)
+					{
+						outFileName = defaultFileName;
+					}
+
+					Stream fOut = File.Create(outFileName);
+                    Stream unc = ld.GetInputStream();
+					Streams.PipeAll(unc, fOut);
+					fOut.Close();
+                }
+                else if (message is PgpOnePassSignatureList)
+                {
+                    throw new PgpException("encrypted message contains a signed message - not literal data.");
+                }
+                else
+                {
+                    throw new PgpException("message is not a simple encrypted file - type unknown.");
+                }
+
+                if (pbe.IsIntegrityProtected())
+                {
+                    if (!pbe.Verify())
+                    {
+                        Console.Error.WriteLine("message failed integrity check");
+                    }
+                    else
+                    {
+                        Console.Error.WriteLine("message integrity check passed");
+                    }
+                }
+                else
+                {
+                    Console.Error.WriteLine("no message integrity check");
+                }
+            }
+            catch (PgpException e)
+            {
+                Console.Error.WriteLine(e);
+
+                Exception underlyingException = e.InnerException;
+                if (underlyingException != null)
+                {
+                    Console.Error.WriteLine(underlyingException.Message);
+                    Console.Error.WriteLine(underlyingException.StackTrace);
+                }
+            }
+        }
+
+		private static void EncryptFile(
+			string	outputFileName,
+			string	inputFileName,
+			string	encKeyFileName,
+			bool	armor,
+			bool	withIntegrityCheck)
+		{
+			PgpPublicKey encKey = PgpExampleUtilities.ReadPublicKey(encKeyFileName);
+
+			using (Stream output = File.Create(outputFileName))
+			{
+				EncryptFile(output, inputFileName, encKey, armor, withIntegrityCheck);
+			}
+		}
+
+        private static void EncryptFile(
+            Stream			outputStream,
+            string			fileName,
+            PgpPublicKey	encKey,
+            bool			armor,
+            bool			withIntegrityCheck)
+        {
+            if (armor)
+            {
+                outputStream = new ArmoredOutputStream(outputStream);
+            }
+
+            try
+            {
+                PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
+
+                cPk.AddMethod(encKey);
+
+                Stream cOut = cPk.Open(outputStream, new byte[1 << 16]);
+
+                PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(
+					CompressionAlgorithmTag.Zip);
+
+				PgpUtilities.WriteFileToLiteralData(
+					comData.Open(cOut),
+					PgpLiteralData.Binary,
+					new FileInfo(fileName),
+					new byte[1 << 16]);
+
+				comData.Close();
+
+				cOut.Close();
+
+				if (armor)
+				{
+					outputStream.Close();
+				}
+            }
+            catch (PgpException e)
+            {
+                Console.Error.WriteLine(e);
+
+                Exception underlyingException = e.InnerException;
+                if (underlyingException != null)
+                {
+                    Console.Error.WriteLine(underlyingException.Message);
+                    Console.Error.WriteLine(underlyingException.StackTrace);
+                }
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            if (args.Length == 0)
+            {
+                Console.Error.WriteLine("usage: KeyBasedLargeFileProcessor -e|-d [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
+                return;
+            }
+
+            if (args[0].Equals("-e"))
+            {
+                if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia"))
+                {
+					EncryptFile(args[2] + ".asc", args[2], args[3], true, (args[1].IndexOf('i') > 0));
+                }
+                else if (args[1].Equals("-i"))
+                {
+					EncryptFile(args[2] + ".bpg", args[2], args[3], false, true);
+                }
+                else
+                {
+					EncryptFile(args[1] + ".bpg", args[1], args[2], false, false);
+                }
+            }
+            else if (args[0].Equals("-d"))
+            {
+				DecryptFile(args[1], args[2], args[3].ToCharArray(), new FileInfo(args[1]).Name + ".out");
+            }
+            else
+            {
+                Console.Error.WriteLine("usage: KeyBasedLargeFileProcessor -d|-e [-a|ai] file [secretKeyFile passPhrase|pubKeyFile]");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/PbeFileProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PbeFileProcessor.cs
new file mode 100644
index 0000000..66b1cc4
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PbeFileProcessor.cs
@@ -0,0 +1,183 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that encrypts/decrypts password based
+    * encryption files.
+    * <p>
+    * To encrypt a file: PBEFileProcessor -e [-ai] fileName passPhrase.<br/>
+    * If -a is specified the output file will be "ascii-armored".<br/>
+    * If -i is specified the output file will be "integrity protected".</p>
+    * <p>
+    * To decrypt: PBEFileProcessor -d fileName passPhrase.</p>
+    * <p>
+    * Note: this example will silently overwrite files, nor does it pay any attention to
+    * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
+    * will have been used.</p>
+    */
+    public sealed class PbeFileProcessor
+    {
+        private PbeFileProcessor() {}
+
+		private static void DecryptFile(string inputFileName, char[] passPhrase)
+		{
+			using (Stream input = File.OpenRead(inputFileName))
+			{
+				DecryptFile(input, passPhrase);
+			}
+		}
+
+        /**
+        * decrypt the passed in message stream
+        */
+        private static void DecryptFile(
+            Stream	inputStream,
+            char[]	passPhrase)
+        {
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+			PgpObjectFactory pgpF = new PgpObjectFactory(inputStream);
+            PgpObject o = pgpF.NextPgpObject();
+
+            //
+            // the first object might be a PGP marker packet.
+            //
+			PgpEncryptedDataList enc = o as PgpEncryptedDataList;
+            if (enc == null)
+            {
+                enc = (PgpEncryptedDataList)pgpF.NextPgpObject();
+            }
+
+            PgpPbeEncryptedData pbe = (PgpPbeEncryptedData)enc[0];
+
+            Stream clear = pbe.GetDataStream(passPhrase);
+
+            PgpObjectFactory pgpFact = new PgpObjectFactory(clear);
+
+			//
+			// if we're trying to read a file generated by someone other than us
+			// the data might not be compressed, so we check the return type from
+			// the factory and behave accordingly.
+			//
+			o = pgpFact.NextPgpObject();
+			if (o is PgpCompressedData)
+			{
+				PgpCompressedData cData = (PgpCompressedData) o;
+				pgpFact = new PgpObjectFactory(cData.GetDataStream());
+				o = pgpFact.NextPgpObject();
+			}
+
+			PgpLiteralData ld = (PgpLiteralData) o;
+			Stream unc = ld.GetInputStream();
+            Stream fOut = File.Create(ld.FileName);
+			Streams.PipeAll(unc, fOut);
+			fOut.Close();
+
+			if (pbe.IsIntegrityProtected())
+            {
+                if (!pbe.Verify())
+                {
+                    Console.Error.WriteLine("message failed integrity check");
+                }
+                else
+                {
+                    Console.Error.WriteLine("message integrity check passed");
+                }
+            }
+            else
+            {
+                Console.Error.WriteLine("no message integrity check");
+            }
+        }
+
+		private static void EncryptFile(
+			string	outputFileName,
+			string	inputFileName,
+			char[]	passPhrase,
+			bool	armor,
+			bool	withIntegrityCheck)
+		{
+			using (Stream output = File.Create(outputFileName))
+			{
+				EncryptFile(output, inputFileName, passPhrase, armor, withIntegrityCheck);
+			}
+		}
+
+        private static void EncryptFile(
+            Stream	outputStream,
+            string	fileName,
+            char[]	passPhrase,
+            bool	armor,
+            bool	withIntegrityCheck)
+        {
+            if (armor)
+            {
+                outputStream = new ArmoredOutputStream(outputStream);
+            }
+
+			try
+            {
+				byte[] compressedData = PgpExampleUtilities.CompressFile(fileName, CompressionAlgorithmTag.Zip);
+
+				PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(
+					SymmetricKeyAlgorithmTag.Cast5, withIntegrityCheck, new SecureRandom());
+				encGen.AddMethod(passPhrase);
+
+				Stream encOut = encGen.Open(outputStream, compressedData.Length);
+
+	            encOut.Write(compressedData, 0, compressedData.Length);
+				encOut.Close();
+
+				if (armor)
+				{
+					outputStream.Close();
+				}
+            }
+            catch (PgpException e)
+            {
+                Console.Error.WriteLine(e);
+
+                Exception underlyingException = e.InnerException;
+                if (underlyingException != null)
+                {
+                    Console.Error.WriteLine(underlyingException.Message);
+                    Console.Error.WriteLine(underlyingException.StackTrace);
+                }
+            }
+        }
+
+		public static void Main(
+			string[] args)
+        {
+            if (args[0].Equals("-e"))
+            {
+                if (args[1].Equals("-a") || args[1].Equals("-ai") || args[1].Equals("-ia"))
+                {
+					EncryptFile(args[2] + ".asc", args[2], args[3].ToCharArray(), true, (args[1].IndexOf('i') > 0));
+                }
+                else if (args[1].Equals("-i"))
+                {
+					EncryptFile(args[2] + ".bpg", args[2], args[3].ToCharArray(), false, true);
+                }
+                else
+                {
+					EncryptFile(args[1] + ".bpg", args[1], args[2].ToCharArray(), false, false);
+                }
+            }
+            else if (args[0].Equals("-d"))
+            {
+				DecryptFile(args[1], args[2].ToCharArray());
+            }
+            else
+            {
+                Console.Error.WriteLine("usage: PbeFileProcessor -e [-ai]|-d file passPhrase");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/PgpExampleUtilities.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PgpExampleUtilities.cs
new file mode 100644
index 0000000..fd371d7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PgpExampleUtilities.cs
@@ -0,0 +1,123 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+	internal class PgpExampleUtilities
+	{
+		internal static byte[] CompressFile(string fileName, CompressionAlgorithmTag algorithm)
+		{
+			MemoryStream bOut = new MemoryStream();
+			PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(algorithm);
+			PgpUtilities.WriteFileToLiteralData(comData.Open(bOut), PgpLiteralData.Binary,
+				new FileInfo(fileName));
+			comData.Close();
+			return bOut.ToArray();
+		}
+
+		/**
+		 * Search a secret key ring collection for a secret key corresponding to keyID if it
+		 * exists.
+		 * 
+		 * @param pgpSec a secret key ring collection.
+		 * @param keyID keyID we want.
+		 * @param pass passphrase to decrypt secret key with.
+		 * @return
+		 * @throws PGPException
+		 * @throws NoSuchProviderException
+		 */
+		internal static PgpPrivateKey FindSecretKey(PgpSecretKeyRingBundle pgpSec, long keyID, char[] pass)
+		{
+			PgpSecretKey pgpSecKey = pgpSec.GetSecretKey(keyID);
+
+			if (pgpSecKey == null)
+			{
+				return null;
+			}
+
+			return pgpSecKey.ExtractPrivateKey(pass);
+		}
+
+		internal static PgpPublicKey ReadPublicKey(string fileName)
+		{
+			using (Stream keyIn = File.OpenRead(fileName))
+			{
+				return ReadPublicKey(keyIn);
+			}
+		}
+
+		/**
+		 * A simple routine that opens a key ring file and loads the first available key
+		 * suitable for encryption.
+		 * 
+		 * @param input
+		 * @return
+		 * @throws IOException
+		 * @throws PGPException
+		 */
+		internal static PgpPublicKey ReadPublicKey(Stream input)
+		{
+			PgpPublicKeyRingBundle pgpPub = new PgpPublicKeyRingBundle(
+				PgpUtilities.GetDecoderStream(input));
+
+			//
+			// we just loop through the collection till we find a key suitable for encryption, in the real
+			// world you would probably want to be a bit smarter about this.
+			//
+
+			foreach (PgpPublicKeyRing keyRing in pgpPub.GetKeyRings())
+			{
+				foreach (PgpPublicKey key in keyRing.GetPublicKeys())
+				{
+					if (key.IsEncryptionKey)
+					{
+						return key;
+					}
+				}
+			}
+
+			throw new ArgumentException("Can't find encryption key in key ring.");
+		}
+
+		internal static PgpSecretKey ReadSecretKey(string fileName)
+		{
+			using (Stream keyIn = File.OpenRead(fileName))
+			{
+				return ReadSecretKey(keyIn);
+			}
+		}
+
+		/**
+		 * A simple routine that opens a key ring file and loads the first available key
+		 * suitable for signature generation.
+		 * 
+		 * @param input stream to read the secret key ring collection from.
+		 * @return a secret key.
+		 * @throws IOException on a problem with using the input stream.
+		 * @throws PGPException if there is an issue parsing the input stream.
+		 */
+		internal static PgpSecretKey ReadSecretKey(Stream input)
+		{
+			PgpSecretKeyRingBundle pgpSec = new PgpSecretKeyRingBundle(
+				PgpUtilities.GetDecoderStream(input));
+
+			//
+			// we just loop through the collection till we find a key suitable for encryption, in the real
+			// world you would probably want to be a bit smarter about this.
+			//
+
+			foreach (PgpSecretKeyRing keyRing in pgpSec.GetKeyRings())
+			{
+				foreach (PgpSecretKey key in keyRing.GetSecretKeys())
+				{
+					if (key.IsSigningKey)
+					{
+						return key;
+					}
+				}
+			}
+
+			throw new ArgumentException("Can't find signing key in key ring.");
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/PublicKeyRingDump.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PublicKeyRingDump.cs
new file mode 100644
index 0000000..bb6108f
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/PublicKeyRingDump.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * Basic class which just lists the contents of the public key file passed
+    * as an argument. If the file contains more than one "key ring" they are
+    * listed in the order found.
+    */
+    public sealed class PublicKeyRingDump
+    {
+        private PublicKeyRingDump()
+        {
+        }
+
+        public static string GetAlgorithm(
+            PublicKeyAlgorithmTag algId)
+        {
+            switch (algId)
+            {
+                case PublicKeyAlgorithmTag.RsaGeneral:
+                    return "RsaGeneral";
+                case PublicKeyAlgorithmTag.RsaEncrypt:
+                    return "RsaEncrypt";
+                case PublicKeyAlgorithmTag.RsaSign:
+                    return "RsaSign";
+                case PublicKeyAlgorithmTag.ElGamalEncrypt:
+                    return "ElGamalEncrypt";
+                case PublicKeyAlgorithmTag.Dsa:
+                    return "DSA";
+                case PublicKeyAlgorithmTag.EC:
+                    return "EC";
+                case PublicKeyAlgorithmTag.ECDsa:
+                    return "ECDSA";
+                case PublicKeyAlgorithmTag.ElGamalGeneral:
+                    return "ElGamalGeneral";
+                case PublicKeyAlgorithmTag.DiffieHellman:
+                    return "DiffieHellman";
+            }
+
+            return "unknown";
+        }
+
+		public static void Main(
+			string[] args)
+        {
+			Stream fs = File.OpenRead(args[0]);
+
+			//
+            // Read the public key rings
+            //
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(
+                PgpUtilities.GetDecoderStream(fs));
+
+			fs.Close();
+
+			foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
+            {
+                try
+                {
+					//PgpPublicKey pubKey =
+					pgpPub.GetPublicKey();
+                }
+                catch (Exception e)
+                {
+                    Console.Error.WriteLine(e.Message);
+                    Console.Error.WriteLine(e.StackTrace);
+                    continue;
+                }
+
+				bool first = true;
+
+				foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
+                {
+                    if (first)
+                    {
+                        Console.WriteLine("Key ID: " +  pgpKey.KeyId.ToString("X"));
+                        first = false;
+                    }
+                    else
+                    {
+                        Console.WriteLine("Key ID: " + pgpKey.KeyId.ToString("X") + " (subkey)");
+                    }
+
+					Console.WriteLine("            Algorithm: " + GetAlgorithm(pgpKey.Algorithm));
+                    Console.WriteLine("            Fingerprint: " + Hex.ToHexString(pgpKey.GetFingerprint()));
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/RsaKeyRingGenerator.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/RsaKeyRingGenerator.cs
new file mode 100644
index 0000000..284118b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/RsaKeyRingGenerator.cs
@@ -0,0 +1,115 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Bcpg.OpenPgp;
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that Generates a RSA PgpPublicKey/PgpSecretKey pair.
+    * <p>
+    * usage: RsaKeyRingGenerator [-a] identity passPhrase</p>
+    * <p>
+    * Where identity is the name to be associated with the public key. The keys are placed
+    * in the files pub.[asc|bpg] and secret.[asc|bpg].</p>
+    */
+    public sealed class RsaKeyRingGenerator
+    {
+        private RsaKeyRingGenerator()
+        {
+        }
+
+		private static void ExportKeyPair(
+            Stream                   secretOut,
+            Stream                   publicOut,
+            AsymmetricKeyParameter   publicKey,
+            AsymmetricKeyParameter   privateKey,
+            string                   identity,
+            char[]                   passPhrase,
+            bool                     armor)
+        {
+			if (armor)
+			{
+				secretOut = new ArmoredOutputStream(secretOut);
+			}
+
+			PgpSecretKey secretKey = new PgpSecretKey(
+                PgpSignature.DefaultCertification,
+                PublicKeyAlgorithmTag.RsaGeneral,
+                publicKey,
+                privateKey,
+                DateTime.UtcNow,
+                identity,
+                SymmetricKeyAlgorithmTag.Cast5,
+                passPhrase,
+                null,
+                null,
+                new SecureRandom()
+                );
+
+            secretKey.Encode(secretOut);
+
+			if (armor)
+            {
+				secretOut.Close();
+				publicOut = new ArmoredOutputStream(publicOut);
+            }
+
+            PgpPublicKey key = secretKey.PublicKey;
+
+            key.Encode(publicOut);
+
+			if (armor)
+			{
+				publicOut.Close();
+			}
+        }
+
+		public static int Main(
+			string[] args)
+        {
+            IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+
+            kpg.Init(new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), new SecureRandom(), 1024, 25));
+
+            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();
+
+            if (args.Length < 2)
+            {
+                Console.WriteLine("RsaKeyPairGenerator [-a] identity passPhrase");
+                return 0;
+            }
+
+			Stream out1, out2;
+            if (args[0].Equals("-a"))
+            {
+                if (args.Length < 3)
+                {
+                    Console.WriteLine("RsaKeyPairGenerator [-a] identity passPhrase");
+					return 0;
+				}
+
+				out1 = File.Create("secret.asc");
+                out2 = File.Create("pub.asc");
+
+                ExportKeyPair(out1, out2, kp.Public, kp.Private, args[1], args[2].ToCharArray(), true);
+            }
+            else
+            {
+                out1 = File.Create("secret.bpg");
+                out2 = File.Create("pub.bpg");
+
+                ExportKeyPair(out1, out2, kp.Public, kp.Private, args[0], args[1].ToCharArray(), false);
+            }
+			out1.Close();
+			out2.Close();
+			return 0;
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/SignedFileProcessor.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/SignedFileProcessor.cs
new file mode 100644
index 0000000..1ad0d10
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/SignedFileProcessor.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections;
+using System.IO;
+
+
+using Org.BouncyCastle.Bcpg.OpenPgp;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples
+{
+    /**
+    * A simple utility class that signs and verifies files.
+    * <p>
+    * To sign a file: SignedFileProcessor -s [-a] fileName secretKey passPhrase.<br/>
+    * If -a is specified the output file will be "ascii-armored".</p>
+    * <p>
+    * To decrypt: SignedFileProcessor -v fileName publicKeyFile.</p>
+    * <p>
+    * <b>Note</b>: this example will silently overwrite files, nor does it pay any attention to
+    * the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
+    * will have been used.</p>
+    * <p>
+    * <b>Note</b>: the example also makes use of PGP compression. If you are having difficulty Getting it
+    * to interoperate with other PGP programs try removing the use of compression first.</p>
+    */
+    public sealed class SignedFileProcessor
+    {
+        private SignedFileProcessor() {}
+
+		/**
+        * verify the passed in file as being correctly signed.
+        */
+        private static void VerifyFile(
+            Stream	inputStream,
+            Stream	keyIn)
+        {
+            inputStream = PgpUtilities.GetDecoderStream(inputStream);
+
+            PgpObjectFactory			pgpFact = new PgpObjectFactory(inputStream);
+            PgpCompressedData			c1 = (PgpCompressedData) pgpFact.NextPgpObject();
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            PgpOnePassSignatureList		p1 = (PgpOnePassSignatureList) pgpFact.NextPgpObject();
+            PgpOnePassSignature			ops = p1[0];
+
+            PgpLiteralData				p2 = (PgpLiteralData) pgpFact.NextPgpObject();
+            Stream						dIn = p2.GetInputStream();
+            PgpPublicKeyRingBundle		pgpRing = new PgpPublicKeyRingBundle(PgpUtilities.GetDecoderStream(keyIn));
+            PgpPublicKey				key = pgpRing.GetPublicKey(ops.KeyId);
+            Stream						fos = File.Create(p2.FileName);
+
+			ops.InitVerify(key);
+
+			int ch;
+			while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+                fos.WriteByte((byte) ch);
+            }
+            fos.Close();
+
+            PgpSignatureList	p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+			PgpSignature		firstSig = p3[0];
+            if (ops.Verify(firstSig))
+            {
+                Console.Out.WriteLine("signature verified.");
+            }
+            else
+            {
+                Console.Out.WriteLine("signature verification failed.");
+            }
+        }
+
+        /**
+        * Generate an encapsulated signed file.
+        *
+        * @param fileName
+        * @param keyIn
+        * @param outputStream
+        * @param pass
+        * @param armor
+        */
+        private static void SignFile(
+            string	fileName,
+            Stream	keyIn,
+            Stream	outputStream,
+            char[]	pass,
+            bool	armor,
+			bool	compress)
+        {
+            if (armor)
+            {
+                outputStream = new ArmoredOutputStream(outputStream);
+            }
+
+            PgpSecretKey pgpSec = PgpExampleUtilities.ReadSecretKey(keyIn);
+            PgpPrivateKey pgpPrivKey = pgpSec.ExtractPrivateKey(pass);
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(pgpSec.PublicKey.Algorithm, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+            foreach (string userId in pgpSec.PublicKey.GetUserIds())
+            {
+                PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
+                spGen.SetSignerUserId(false, userId);
+                sGen.SetHashedSubpackets(spGen.Generate());
+                // Just the first one!
+                break;
+            }
+
+            Stream cOut = outputStream;
+			PgpCompressedDataGenerator cGen = null;
+			if (compress)
+			{
+				cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.ZLib);
+
+				cOut = cGen.Open(cOut);
+			}
+
+			BcpgOutputStream bOut = new BcpgOutputStream(cOut);
+
+            sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+            FileInfo					file = new FileInfo(fileName);
+            PgpLiteralDataGenerator     lGen = new PgpLiteralDataGenerator();
+            Stream						lOut = lGen.Open(bOut, PgpLiteralData.Binary, file);
+            FileStream					fIn = file.OpenRead();
+            int                         ch = 0;
+
+			while ((ch = fIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte) ch);
+                sGen.Update((byte)ch);
+            }
+
+			fIn.Close();
+			lGen.Close();
+
+			sGen.Generate().Encode(bOut);
+
+			if (cGen != null)
+			{
+				cGen.Close();
+			}
+
+			if (armor)
+			{
+				outputStream.Close();
+			}
+        }
+
+		public static void Main(
+            string[] args)
+        {
+			// TODO provide command-line option to determine whether to use compression in SignFile
+            if (args[0].Equals("-s"))
+            {
+				Stream keyIn, fos;
+                if (args[1].Equals("-a"))
+                {
+                    keyIn = File.OpenRead(args[3]);
+                    fos = File.Create(args[2] + ".asc");
+
+					SignFile(args[2], keyIn, fos, args[4].ToCharArray(), true, true);
+                }
+                else
+                {
+                    keyIn = File.OpenRead(args[2]);
+                    fos = File.Create(args[1] + ".bpg");
+
+					SignFile(args[1], keyIn, fos, args[3].ToCharArray(), false, true);
+                }
+				keyIn.Close();
+				fos.Close();
+            }
+            else if (args[0].Equals("-v"))
+            {
+				using (Stream fis = File.OpenRead(args[1]),
+                	keyIn = File.OpenRead(args[2]))
+				{
+					VerifyFile(fis, keyIn);
+				}
+			}
+            else
+            {
+                Console.Error.WriteLine("usage: SignedFileProcessor -v|-s [-a] file keyfile [passPhrase]");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/examples/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/openpgp/examples/test/AllTests.cs
new file mode 100644
index 0000000..a066ff3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/examples/test/AllTests.cs
@@ -0,0 +1,405 @@
+#if !LIB
+using System;
+using System.IO;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Examples.Tests
+{
+	[TestFixture]
+	public class AllTests
+	{
+		private static readonly byte[] clearSignedPublicKey = Base64.Decode(
+			  "mQELBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+"
+			+ "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1"
+			+ "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO"
+			+ "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7"
+			+ "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4"
+			+ "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp"
+			+ "tBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2BBMBAgAgBQJEIdvsAhsDBgsJCAcD"
+			+ "AgQVAggDBBYCAwECHgECF4AACgkQ4M/Ier3f9xagdAf/fbKWBjLQM8xR7JkR"
+			+ "P4ri8YKOQPhK+VrddGUD59/wzVnvaGyl9MZE7TXFUeniQq5iXKnm22EQbYch"
+			+ "v2Jcxyt2H9yptpzyh4tP6tEHl1C887p2J4qe7F2ATua9CzVGwXQSUbKtj2fg"
+			+ "UZP5SsNp25guhPiZdtkf2sHMeiotmykFErzqGMrvOAUThrO63GiYsRk4hF6r"
+			+ "cQ01d+EUVpY/sBcCxgNyOiB7a84sDtrxnX5BTEZDTEj8LvuEyEV3TMUuAjx1"
+			+ "7Eyd+9JtKzwV4v3hlTaWOvGro9nPS7YaPuG+RtufzXCUJPbPfTjTvtGOqvEz"
+			+ "oztls8tuWA0OGHba9XfX9rfgorACAAM=");
+
+		private static readonly string crOnlyMessage =
+			"\r"
+			+ " hello world!\r"
+			+ "\r"
+			+ "- dash\r";
+
+		private static readonly string nlOnlyMessage =
+			"\n"
+			+ " hello world!\n"
+			+ "\n"
+			+ "- dash\n";
+
+		private static readonly string crNlMessage =
+			"\r\n"
+			+ " hello world!\r\n"
+			+ "\r\n"
+			+ "- dash\r\n";
+
+		private static readonly string crNlMessageTrailingWhiteSpace =
+			"\r\n"
+			+ " hello world! \t\r\n"
+			+ "\r\n"
+			+ "\r\n";
+
+		private static readonly string crOnlySignedMessage =
+			"-----BEGIN PGP SIGNED MESSAGE-----\r"
+			+ "Hash: SHA256\r"
+			+ "\r"
+			+ "\r"
+			+ " hello world!\r"
+			+ "\r"
+			+ "- - dash\r"
+			+ "-----BEGIN PGP SIGNATURE-----\r"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r"
+			+ "\r"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r";
+
+		private static readonly string nlOnlySignedMessage =
+			"-----BEGIN PGP SIGNED MESSAGE-----\n"
+			+ "Hash: SHA256\n"
+			+ "\n"
+			+ "\n"
+			+ " hello world!\n"
+			+ "\n"
+			+ "- - dash\n"
+			+ "-----BEGIN PGP SIGNATURE-----\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\n"
+			+ "\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\n"
+			+ "=84Nd\n"
+			+ "-----END PGP SIGNATURE-----\n";
+
+		private static readonly string crNlSignedMessage =
+			"-----BEGIN PGP SIGNED MESSAGE-----\r\n"
+			+ "Hash: SHA256\r\n"
+			+ "\r\n"
+			+ "\r\n"
+			+ " hello world!\r\n"
+			+ "\r\n"
+			+ "- - dash\r\n"
+			+ "-----BEGIN PGP SIGNATURE-----\r\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n"
+			+ "\r\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r\n";
+
+		private static readonly string crNlSignedMessageTrailingWhiteSpace =
+			"-----BEGIN PGP SIGNED MESSAGE-----\r\n"
+			+ "Hash: SHA256\r\n"
+			+ "\r\n"
+			+ "\r\n"
+			+ " hello world! \t\r\n"
+			+ "\r\n"
+			+ "- - dash\r\n"
+			+ "-----BEGIN PGP SIGNATURE-----\r\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n"
+			+ "\r\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r\n";
+
+		private TextWriter _oldOut;
+		private TextWriter _oldErr;
+
+		private MemoryStream _currentOut;
+		private MemoryStream _currentErr;
+
+		[SetUp]
+		public void SetUp()
+		{
+			_oldOut = Console.Out;
+			_oldErr = Console.Error;
+			_currentOut = new MemoryStream();
+			_currentErr = new MemoryStream();
+
+			Console.SetOut(new StreamWriter(_currentOut));
+			Console.SetError(new StreamWriter(_currentErr));
+		}
+
+		[TearDown]
+		public void TearDown()
+		{
+			Console.SetOut(_oldOut);
+			Console.SetError(_oldErr);
+		}
+
+		[Test]
+		public void TestRsaKeyGeneration() 
+		{
+			RsaKeyRingGenerator.Main(new string[] { "test", "password" });
+
+			CreateSmallTestInput();
+			CreateLargeTestInput();
+
+			CheckSigning("bpg");
+			CheckKeyBasedEncryption("bpg");
+			CheckLargeKeyBasedEncryption("bpg");
+
+			RsaKeyRingGenerator.Main(new string[] { "-a", "test", "password" });
+
+			CheckSigning("asc");
+			CheckKeyBasedEncryption("asc");
+			CheckLargeKeyBasedEncryption("asc");
+		}
+
+		[Test]
+		public void TestDsaElGamalKeyGeneration() 
+		{
+			DsaElGamalKeyRingGenerator.Main(new string[] { "test", "password" });
+
+			CreateSmallTestInput();
+			CreateLargeTestInput();
+
+			CheckSigning("bpg");
+			CheckKeyBasedEncryption("bpg");
+			CheckLargeKeyBasedEncryption("bpg");
+
+			DsaElGamalKeyRingGenerator.Main(new string[] { "-a", "test", "password" });
+
+			CheckSigning("asc");
+			CheckKeyBasedEncryption("asc");
+			CheckLargeKeyBasedEncryption("asc");
+		}
+
+		[Test]
+		public void TestPbeEncryption() 
+		{
+			Console.Error.Flush();
+			_currentErr.SetLength(0);
+
+			PbeFileProcessor.Main(new string[] { "-e", "test.txt", "password" });
+
+			PbeFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("no message integrity check", GetLine(_currentErr));
+
+			PbeFileProcessor.Main(new string[] { "-e", "-i", "test.txt", "password" });
+
+			PbeFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+
+			PbeFileProcessor.Main(new string[] { "-e", "-ai", "test.txt", "password" });
+
+			PbeFileProcessor.Main(new string[] { "-d", "test.txt.asc", "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+		}
+
+		[Test]
+		public void TestClearSigned()
+		{
+			CreateTestFile(clearSignedPublicKey, "pub.bpg");
+
+			CheckClearSignedVerify(nlOnlySignedMessage);
+			CheckClearSignedVerify(crOnlySignedMessage);
+			CheckClearSignedVerify(crNlSignedMessage);
+			CheckClearSignedVerify(crNlSignedMessageTrailingWhiteSpace);
+
+			ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" });
+
+			RsaKeyRingGenerator.Main(new string[] { "test", "password" });
+
+			CheckClearSigned(crOnlyMessage);
+			CheckClearSigned(nlOnlyMessage);
+			CheckClearSigned(crNlMessage);
+			CheckClearSigned(crNlMessageTrailingWhiteSpace);
+		}
+
+		[Test]
+		public void TestClearSignedBogusInput()
+		{
+			CreateTestFile(clearSignedPublicKey, "test.txt");
+
+			ClearSignedFileProcessor.Main(new String[] { "-s", "test.txt", "secret.bpg", "password" });
+		}
+
+		private void CheckClearSignedVerify(
+			string message)
+		{
+			CreateTestData(message, "test.txt.asc");
+
+			ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" });
+		}
+
+		private void CheckClearSigned(
+			string message)
+		{
+			CreateTestData(message, "test.txt");
+
+			ClearSignedFileProcessor.Main(new string[] { "-s", "test.txt", "secret.bpg", "password" });
+			ClearSignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub.bpg" });
+		}
+
+		private void CheckSigning(
+			string type) 
+		{
+			Console.Out.Flush();
+			_currentOut.SetLength(0);
+
+			SignedFileProcessor.Main(new string[] { "-s", "test.txt", "secret." + type, "password" });
+			SignedFileProcessor.Main(new string[] { "-v", "test.txt.bpg", "pub." + type });
+
+			Console.Out.Flush();
+			Assert.AreEqual("signature verified.", GetLine(_currentOut));
+
+			SignedFileProcessor.Main(new string[] { "-s", "-a", "test.txt", "secret." + type, "password" });
+			SignedFileProcessor.Main(new string[] { "-v", "test.txt.asc", "pub." + type });
+
+			Console.Out.Flush();
+			Assert.AreEqual("signature verified.", GetLine(_currentOut));
+		}
+
+		private void CheckKeyBasedEncryption(
+			string type) 
+		{
+			Console.Error.Flush();
+			_currentErr.SetLength(0);
+
+			KeyBasedFileProcessor.Main(new string[] { "-e", "test.txt", "pub." + type });
+			KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("no message integrity check", GetLine(_currentErr));
+
+			KeyBasedFileProcessor.Main(new string[] { "-e", "-i", "test.txt", "pub." + type });
+			KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.bpg", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+
+			KeyBasedFileProcessor.Main(new string[] { "-e", "-ai", "test.txt", "pub." + type });
+			KeyBasedFileProcessor.Main(new string[] { "-d", "test.txt.asc", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+		}
+
+		private void CheckLargeKeyBasedEncryption(
+			string type) 
+		{
+			Console.Error.Flush();
+			_currentErr.SetLength(0);
+
+			KeyBasedLargeFileProcessor.Main(new string[] { "-e", "large.txt", "pub." + type });
+			KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.bpg", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("no message integrity check", GetLine(_currentErr));
+
+			KeyBasedLargeFileProcessor.Main(new string[] { "-e", "-i", "large.txt", "pub." + type });
+			KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.bpg", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+
+			KeyBasedLargeFileProcessor.Main(new string[] { "-e", "-ai", "large.txt", "pub." + type });
+			KeyBasedLargeFileProcessor.Main(new string[] { "-d", "large.txt.asc", "secret." + type, "password" });
+
+			Console.Error.Flush();
+			Assert.AreEqual("message integrity check passed", GetLine(_currentErr));
+		}
+
+		private void CreateSmallTestInput() 
+		{
+			TextWriter bfOut = new StreamWriter(File.Create("test.txt"));
+			bfOut.WriteLine("hello world!");
+			bfOut.Close();
+		}
+
+		private void CreateLargeTestInput() 
+		{
+			TextWriter bfOut = new StreamWriter(File.Create("large.txt"));
+
+			for (int i = 1; i <= 2000; i++)
+			{
+				bfOut.WriteLine("hello to planet " + i + "!");
+			}
+
+			bfOut.Close();
+		}
+
+		private void CreateTestData(
+			string	testData,
+			string	name)
+		{
+			TextWriter bfOut = new StreamWriter(File.Create(name));
+			bfOut.Write(testData);
+			bfOut.Close();
+		}
+
+		private void CreateTestFile(
+			byte[]	keyData,
+			string	name)
+		{
+			FileStream fOut = File.Create(name);
+			fOut.Write(keyData, 0, keyData.Length);
+			fOut.Close();
+		}
+
+		private string GetLine(
+			MemoryStream outStr) 
+		{
+			byte[] b = outStr.ToArray();
+			TextReader bRd = new StreamReader(new MemoryStream(b, false));
+			outStr.SetLength(0);
+			return bRd.ReadLine();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			//junit.textui.TestRunner.run(suite());
+			EventListener el = new NullListener();
+			suite().Run(el);
+		}
+
+		public static TestSuite suite()
+		{
+			TestSuite suite = new TestSuite("OpenPGP Example Tests");
+
+			suite.Add(new AllTests());
+
+			return suite;
+		}
+
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/DSA2Test.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/DSA2Test.cs
new file mode 100644
index 0000000..883ae31
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/DSA2Test.cs
@@ -0,0 +1,237 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	/**
+	* GPG compatability test vectors
+	*/
+	[TestFixture]
+	public class Dsa2Test
+		//extends TestCase
+	{
+		[Test]
+		public void TestK1024H160()
+		{
+			doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-160-sign.gpg");
+		}
+
+		[Test]
+		public void TestK1024H224()
+		{
+			doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-224-sign.gpg");
+		}
+
+		[Test]
+		public void TestK1024H256()
+		{
+			doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-256-sign.gpg");
+		}
+
+		[Test]
+		public void TestK1024H384()
+		{
+			doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-384-sign.gpg");
+		}
+
+		[Test]
+		public void TestK1024H512()
+		{
+			doSigVerifyTest("DSA-1024-160.pub", "dsa-1024-512-sign.gpg");
+		}
+
+		[Test]
+		public void TestK2048H224()
+		{
+			doSigVerifyTest("DSA-2048-224.pub", "dsa-2048-224-sign.gpg");
+		}
+
+		[Test]
+		public void TestK3072H256()
+		{
+			doSigVerifyTest("DSA-3072-256.pub", "dsa-3072-256-sign.gpg");
+		}
+
+		[Test]
+		public void TestK7680H384()
+		{
+			doSigVerifyTest("DSA-7680-384.pub", "dsa-7680-384-sign.gpg");
+		}
+
+		[Test]
+		public void TestK15360H512()
+		{
+			doSigVerifyTest("DSA-15360-512.pub", "dsa-15360-512-sign.gpg");
+		}
+
+		[Test]
+		public void TestGenerateK1024H224()
+		{
+			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha224);
+		}
+
+		[Test]
+		public void TestGenerateK1024H256()
+		{
+			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha256);
+		}
+
+		[Test]
+		public void TestGenerateK1024H384()
+		{
+			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha384);
+		}
+
+		[Test]
+		public void TestGenerateK1024H512()
+		{
+			doSigGenerateTest("DSA-1024-160.sec", "DSA-1024-160.pub", HashAlgorithmTag.Sha512);
+		}
+
+		[Test]
+		public void TestGenerateK2048H256()
+		{
+			doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha256);
+		}
+
+		[Test]
+		public void TestGenerateK2048H512()
+		{
+			doSigGenerateTest("DSA-2048-224.sec", "DSA-2048-224.pub", HashAlgorithmTag.Sha512);
+		}
+
+		private void doSigGenerateTest(
+			string				privateKeyFile,
+			string				publicKeyFile,
+			HashAlgorithmTag	digest)
+		{
+			PgpSecretKeyRing		secRing = loadSecretKey(privateKeyFile);
+			PgpPublicKeyRing		pubRing = loadPublicKey(publicKeyFile);
+			string					data = "hello world!";
+			byte[]					dataBytes = Encoding.ASCII.GetBytes(data);
+			MemoryStream			bOut = new MemoryStream();
+			MemoryStream			testIn = new MemoryStream(dataBytes, false);
+			PgpSignatureGenerator	sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, digest);
+
+			sGen.InitSign(PgpSignature.BinaryDocument, secRing.GetSecretKey().ExtractPrivateKey("test".ToCharArray()));
+
+			BcpgOutputStream bcOut = new BcpgOutputStream(bOut);
+
+			sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+			PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+
+//			Date testDate = new Date((System.currentTimeMillis() / 1000) * 1000);
+			DateTime testDate = new DateTime(
+				(DateTime.UtcNow.Ticks / TimeSpan.TicksPerSecond) * TimeSpan.TicksPerSecond);
+
+			Stream lOut = lGen.Open(
+				new UncloseableStream(bcOut),
+				PgpLiteralData.Binary,
+				"_CONSOLE",
+				dataBytes.Length,
+				testDate);
+
+			int ch;
+			while ((ch = testIn.ReadByte()) >= 0)
+			{
+				lOut.WriteByte((byte)ch);
+				sGen.Update((byte)ch);
+			}
+
+			lGen.Close();
+
+			sGen.Generate().Encode(bcOut);
+
+			PgpObjectFactory        pgpFact = new PgpObjectFactory(bOut.ToArray());
+			PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+			PgpOnePassSignature     ops = p1[0];
+
+			Assert.AreEqual(digest, ops.HashAlgorithm);
+			Assert.AreEqual(PublicKeyAlgorithmTag.Dsa, ops.KeyAlgorithm);
+
+			PgpLiteralData          p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+			if (!p2.ModificationTime.Equals(testDate))
+			{
+				Assert.Fail("Modification time not preserved");
+			}
+
+			Stream dIn = p2.GetInputStream();
+
+			ops.InitVerify(pubRing.GetPublicKey());
+
+			while ((ch = dIn.ReadByte()) >= 0)
+			{
+				ops.Update((byte)ch);
+			}
+
+			PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+			PgpSignature sig = p3[0];
+
+			Assert.AreEqual(digest, sig.HashAlgorithm);
+			Assert.AreEqual(PublicKeyAlgorithmTag.Dsa, sig.KeyAlgorithm);
+
+			Assert.IsTrue(ops.Verify(sig));
+		}
+
+		private void doSigVerifyTest(
+			string	publicKeyFile,
+			string	sigFile)
+		{
+			PgpPublicKeyRing publicKey = loadPublicKey(publicKeyFile);
+			PgpObjectFactory pgpFact = loadSig(sigFile);
+
+			PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+			pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+			PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+			PgpOnePassSignature ops = p1[0];
+
+			PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+
+			Stream dIn = p2.GetInputStream();
+
+			ops.InitVerify(publicKey.GetPublicKey());
+
+			int ch;
+			while ((ch = dIn.ReadByte()) >= 0)
+			{
+				ops.Update((byte)ch);
+			}
+
+			PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+			Assert.IsTrue(ops.Verify(p3[0]));
+		}
+
+		private PgpObjectFactory loadSig(
+			string sigName)
+		{
+			Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.sigs." + sigName);
+
+			return new PgpObjectFactory(fIn);
+		}
+
+		private PgpPublicKeyRing loadPublicKey(
+			string keyName)
+		{
+			Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.keys." + keyName);
+
+			return new PgpPublicKeyRing(fIn);
+		}
+
+		private PgpSecretKeyRing loadSecretKey(
+			string keyName)
+		{
+			Stream fIn = SimpleTest.GetTestDataAsStream("openpgp.dsa.keys." + keyName);
+
+			return new PgpSecretKeyRing(fIn);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPArmoredTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPArmoredTest.cs
new file mode 100644
index 0000000..aa13477
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPArmoredTest.cs
@@ -0,0 +1,265 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	[TestFixture]
+	public class PgpArmoredTest
+		: SimpleTest
+	{
+		private static readonly byte[] sample = Base64.Decode(
+				"mQGiBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn"
+			+ "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg"
+			+ "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf"
+			+ "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ"
+			+ "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G"
+			+ "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ"
+			+ "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG"
+			+ "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP"
+			+ "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif"
+			+ "IIeLOTI5Dc4XKeV32a+bWrQidGVzdCAoVGVzdCBrZXkpIDx0ZXN0QHViaWNh"
+			+ "bGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB4TOABgsJCAcDAgMVAgMDFgIB"
+			+ "Ah4BAheAAAoJEJh8Njfhe8KmGDcAoJWr8xgPr75y/Cp1kKn12oCCOb8zAJ4p"
+			+ "xSvk4K6tB2jYbdeSrmoWBZLdMLACAAC5AQ0EQDzfARAEAJeUAPvUzJJbKcc5"
+			+ "5Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj47UPAD/tQxwz8VAwJySx82ggN"
+			+ "LxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j2BVqZAaX3q79a3eMiql1T0oE"
+			+ "AGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOHAAQNBACD0mVMlAUgd7REYy/1"
+			+ "mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWaHz6CN1XptdwpDeSYEOFZ0PSu"
+			+ "qH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85efMBA9jUv/DeBOzRWMFG6sC6y"
+			+ "k8NGG7Swea7EHKeQI40G3jgO/+xANtMyTIhPBBgRAgAPBQJAPN8BAhsMBQkB"
+			+ "4TOAAAoJEJh8Njfhe8KmG7kAn00mTPGJCWqmskmzgdzeky5fWd7rAKCNCp3u"
+			+ "ZJhfg0htdgAfIy8ppm05vLACAAA=");
+
+		private static readonly byte[] marker = Hex.Decode("2d2d2d2d2d454e4420504750205055424c4943204b455920424c4f434b2d2d2d2d2d");
+
+		// Contains "Hello World!" as an armored message
+		// The 'blank line' after the headers contains (legal) whitespace - see RFC2440 6.2
+		private static readonly string blankLineData =
+			  "-----BEGIN PGP MESSAGE-----\n"
+			+ "Version: BCPG v1.32\n"
+			+ "Comment: A dummy message\n"
+			+ " \t \t\n"
+			+ "SGVsbG8gV29ybGQh\n"
+			+ "=d9Xi\n"
+			+ "-----END PGP MESSAGE-----\n";
+
+		private int markerCount(
+			byte[] data)
+		{
+			int ind = 0;
+			int matches = 0;
+
+			while (ind < data.Length)
+			{
+				if (data[ind] == 0x2d)
+				{
+					int count = 0;
+					while (count < marker.Length)
+					{
+						if (data[ind + count] != marker[count])
+						{
+							break;
+						}
+						count++;
+					}
+
+					if (count == marker.Length)
+					{
+						matches++;
+					}
+
+					// TODO Is this correct?
+					ind += count;
+				}
+				else
+				{
+					ind++;
+				}
+			}
+
+			return matches;
+		}
+
+		private void blankLineTest()
+		{
+			byte[] blankLineBytes = Encoding.ASCII.GetBytes(blankLineData);
+			MemoryStream bIn = new MemoryStream(blankLineBytes, false);
+			ArmoredInputStream aIn = new ArmoredInputStream(bIn, true);
+
+			MemoryStream bOut = new MemoryStream();
+			int c;
+			while ((c = aIn.ReadByte()) >= 0)
+			{
+				bOut.WriteByte((byte)c);
+			}
+
+			byte[] expected = Encoding.ASCII.GetBytes("Hello World!");
+
+			if (!Arrays.AreEqual(expected, bOut.ToArray()))
+			{
+				Fail("Incorrect message retrieved in blank line test.");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			//
+			// test immediate close
+			//
+			MemoryStream bOut = new MemoryStream();
+			ArmoredOutputStream aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Close();
+
+			byte[] data = bOut.ToArray();
+
+			if (data.Length != 0)
+			{
+				Fail("No data should have been written");
+			}
+
+			//
+			// multiple close
+			//
+			bOut = new MemoryStream();
+			aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Write(sample, 0, sample.Length);
+
+			aOut.Close();
+			aOut.Close();
+
+			int mc = markerCount(bOut.ToArray());
+
+			if (mc < 1)
+			{
+				Fail("No end marker found");
+			}
+
+			if (mc > 1)
+			{
+				Fail("More than one end marker found");
+			}
+
+			//
+			// writing and reading single objects
+			//
+			bOut = new MemoryStream();
+			aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Write(sample, 0, sample.Length);
+
+			aOut.Close();
+
+			ArmoredInputStream aIn = new ArmoredInputStream(
+				new MemoryStream(bOut.ToArray(), false));
+
+			PgpObjectFactory fact = new PgpObjectFactory(aIn);
+			int count = 0;
+
+			while (fact.NextPgpObject() != null)
+			{
+				count++;
+			}
+
+			if (count != 1)
+			{
+				Fail("wrong number of objects found: " + count);
+			}
+
+			//
+			// writing and reading multiple objects  - in single block
+			//
+			bOut = new MemoryStream();
+			aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Write(sample, 0, sample.Length);
+			aOut.Write(sample, 0, sample.Length);
+
+			aOut.Close();
+
+			aIn = new ArmoredInputStream(
+				new MemoryStream(bOut.ToArray(), false));
+
+			fact = new PgpObjectFactory(aIn);
+			count = 0;
+
+			while (fact.NextPgpObject() != null)
+			{
+				count++;
+			}
+
+			if (count != 2)
+			{
+				Fail("wrong number of objects found: " + count);
+			}
+
+			//
+			// writing and reading multiple objects  - in single block
+			//
+			bOut = new MemoryStream();
+			aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Write(sample, 0, sample.Length);
+
+			aOut.Close();     // does not close underlying stream
+
+			aOut = new ArmoredOutputStream(bOut);
+
+			aOut.Write(sample, 0, sample.Length);
+
+			aOut.Close();
+
+			aIn = new ArmoredInputStream(
+				new MemoryStream(bOut.ToArray(), false));
+
+			count = 0;
+			bool atLeastOne;
+			do
+			{
+				atLeastOne = false;
+				fact = new PgpObjectFactory(aIn);
+
+				while (fact.NextPgpObject() != null)
+				{
+					atLeastOne = true;
+					count++;
+				}
+			}
+			while (atLeastOne);
+
+			if (count != 2)
+			{
+				Fail("wrong number of objects found: " + count);
+			}
+
+			blankLineTest();
+		}
+
+		public override string Name
+		{
+			get { return "PGPArmoredTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PgpArmoredTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPClearSignedSignatureTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPClearSignedSignatureTest.cs
new file mode 100644
index 0000000..668f8cc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPClearSignedSignatureTest.cs
@@ -0,0 +1,445 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	[TestFixture]
+	public class PgpClearSignedSignatureTest
+		: SimpleTest
+	{
+		private static readonly byte[] publicKey = Base64.Decode(
+			  "mQELBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+"
+			+ "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1"
+			+ "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO"
+			+ "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7"
+			+ "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4"
+			+ "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp"
+			+ "tBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2BBMBAgAgBQJEIdvsAhsDBgsJCAcD"
+			+ "AgQVAggDBBYCAwECHgECF4AACgkQ4M/Ier3f9xagdAf/fbKWBjLQM8xR7JkR"
+			+ "P4ri8YKOQPhK+VrddGUD59/wzVnvaGyl9MZE7TXFUeniQq5iXKnm22EQbYch"
+			+ "v2Jcxyt2H9yptpzyh4tP6tEHl1C887p2J4qe7F2ATua9CzVGwXQSUbKtj2fg"
+			+ "UZP5SsNp25guhPiZdtkf2sHMeiotmykFErzqGMrvOAUThrO63GiYsRk4hF6r"
+			+ "cQ01d+EUVpY/sBcCxgNyOiB7a84sDtrxnX5BTEZDTEj8LvuEyEV3TMUuAjx1"
+			+ "7Eyd+9JtKzwV4v3hlTaWOvGro9nPS7YaPuG+RtufzXCUJPbPfTjTvtGOqvEz"
+			+ "oztls8tuWA0OGHba9XfX9rfgorACAAM=");
+
+		private static readonly byte[] secretKey = Base64.Decode(
+			  "lQOWBEQh2+wBCAD26kte0hO6flr7Y2aetpPYutHY4qsmDPy+GwmmqVeCDkX+"
+			+ "r1g7DuFbMhVeu0NkKDnVl7GsJ9VarYsFYyqu0NzLa9XS2qlTIkmJV+2/xKa1"
+			+ "tzjn18fT/cnAWL88ZLCOWUr241aPVhLuIc6vpHnySpEMkCh4rvMaimnTrKwO"
+			+ "42kgeDGd5cXfs4J4ovRcTbc4hmU2BRVsRjiYMZWWx0kkyL2zDVyaJSs4yVX7"
+			+ "Jm4/LSR1uC/wDT0IJJuZT/gQPCMJNMEsVCziRgYkAxQK3OWojPSuv4rXpyd4"
+			+ "Gvo6IbvyTgIskfpSkCnQtORNLIudQSuK7pW+LkL62N+ohuKdMvdxauOnAAYp"
+			+ "AAf+JCJJeAXEcrTVHotsrRR5idzmg6RK/1MSQUijwPmP7ZGy1BmpAmYUfbxn"
+			+ "B56GvXyFV3Pbj9PgyJZGS7cY+l0BF4ZqN9USiQtC9OEpCVT5LVMCFXC/lahC"
+			+ "/O3EkjQy0CYK+GwyIXa+Flxcr460L/Hvw2ZEXJZ6/aPdiR+DU1l5h99Zw8V1"
+			+ "Y625MpfwN6ufJfqE0HLoqIjlqCfi1iwcKAK2oVx2SwnT1W0NwUUXjagGhD2s"
+			+ "VzJVpLqhlwmS0A+RE9Niqrf80/zwE7QNDF2DtHxmMHJ3RY/pfu5u1rrFg9YE"
+			+ "lmS60mzOe31CaD8Li0k5YCJBPnmvM9mN3/DWWprSZZKtmQQA96C2/VJF5EWm"
+			+ "+/Yxi5J06dG6Bkz311Ui4p2zHm9/4GvTPCIKNpGx9Zn47YFD3tIg3fIBVPOE"
+			+ "ktG38pEPx++dSSFF9Ep5UgmYFNOKNUVq3yGpatBtCQBXb1LQLAMBJCJ5TQmk"
+			+ "68hMOEaqjMHSOa18cS63INgA6okb/ueAKIHxYQcEAP9DaXu5n9dZQw7pshbN"
+			+ "Nu/T5IP0/D/wqM+W5r+j4P1N7PgiAnfKA4JjKrUgl8PGnI2qM/Qu+g3qK++c"
+			+ "F1ESHasnJPjvNvY+cfti06xnJVtCB/EBOA2UZkAr//Tqa76xEwYAWRBnO2Y+"
+			+ "KIVOT+nMiBFkjPTrNAD6fSr1O4aOueBhBAC6aA35IfjC2h5MYk8+Z+S4io2o"
+			+ "mRxUZ/dUuS+kITvWph2e4DT28Xpycpl2n1Pa5dCDO1lRqe/5JnaDYDKqxfmF"
+			+ "5tTG8GR4d4nVawwLlifXH5Ll7t5NcukGNMCsGuQAHMy0QHuAaOvMdLs5kGHn"
+			+ "8VxfKEVKhVrXsvJSwyXXSBtMtUcRtBNnZ2dnZ2dnZyA8Z2dnQGdnZ2c+iQE2"
+			+ "BBMBAgAgBQJEIdvsAhsDBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ4M/I"
+			+ "er3f9xagdAf/fbKWBjLQM8xR7JkRP4ri8YKOQPhK+VrddGUD59/wzVnvaGyl"
+			+ "9MZE7TXFUeniQq5iXKnm22EQbYchv2Jcxyt2H9yptpzyh4tP6tEHl1C887p2"
+			+ "J4qe7F2ATua9CzVGwXQSUbKtj2fgUZP5SsNp25guhPiZdtkf2sHMeiotmykF"
+			+ "ErzqGMrvOAUThrO63GiYsRk4hF6rcQ01d+EUVpY/sBcCxgNyOiB7a84sDtrx"
+			+ "nX5BTEZDTEj8LvuEyEV3TMUuAjx17Eyd+9JtKzwV4v3hlTaWOvGro9nPS7Ya"
+			+ "PuG+RtufzXCUJPbPfTjTvtGOqvEzoztls8tuWA0OGHba9XfX9rfgorACAAA=");
+
+		private static readonly string crOnlyMessage =
+				"\r"
+			+ " hello world!\r"
+			+ "\r"
+			+ "- dash\r";
+
+		private static readonly string nlOnlyMessage =
+			"\n"
+			+ " hello world!\n"
+			+ "\n"
+			+ "- dash\n";
+
+		private static readonly string crNlMessage =
+			"\r\n"
+			+ " hello world!\r\n"
+			+ "\r\n"
+			+ "- dash\r\n";
+
+		private static readonly string crOnlySignedMessage =
+				"-----BEGIN PGP SIGNED MESSAGE-----\r"
+			+ "Hash: SHA256\r"
+			+ "\r"
+			+ "\r"
+			+ " hello world!\r"
+			+ "\r"
+			+ "- - dash\r"
+			+ "-----BEGIN PGP SIGNATURE-----\r"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r"
+			+ "\r"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r";
+
+		private static readonly string nlOnlySignedMessage =
+			"-----BEGIN PGP SIGNED MESSAGE-----\n"
+			+ "Hash: SHA256\n"
+			+ "\n"
+			+ "\n"
+			+ " hello world!\n"
+			+ "\n"
+			+ "- - dash\n"
+			+ "-----BEGIN PGP SIGNATURE-----\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\n"
+			+ "\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\n"
+			+ "=84Nd\n"
+			+ "-----END PGP SIGNATURE-----\n";
+
+		private static readonly string crNlSignedMessage =
+				"-----BEGIN PGP SIGNED MESSAGE-----\r\n"
+			+ "Hash: SHA256\r\n"
+			+ "\r\n"
+			+ "\r\n"
+			+ " hello world!\r\n"
+			+ "\r\n"
+			+ "- - dash\r\n"
+			+ "-----BEGIN PGP SIGNATURE-----\r\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n"
+			+ "\r\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r\n";
+
+		private static readonly string crNlSignedMessageTrailingWhiteSpace =
+			"-----BEGIN PGP SIGNED MESSAGE-----\r\n"
+			+ "Hash: SHA256\r\n"
+			+ "\r\n"
+			+ "\r\n"
+			+ " hello world! \t\r\n"
+			+ "\r\n"
+			+ "- - dash\r\n"
+			+ "-----BEGIN PGP SIGNATURE-----\r\n"
+			+ "Version: GnuPG v1.4.2.1 (GNU/Linux)\r\n"
+			+ "\r\n"
+			+ "iQEVAwUBRCNS8+DPyHq93/cWAQi6SwgAj3ItmSLr/sd/ixAQLW7/12jzEjfNmFDt\r\n"
+			+ "WOZpJFmXj0fnMzTrOILVnbxHv2Ru+U8Y1K6nhzFSR7d28n31/XGgFtdohDEaFJpx\r\n"
+			+ "Fl+KvASKIonnpEDjFJsPIvT1/G/eCPalwO9IuxaIthmKj0z44SO1VQtmNKxdLAfK\r\n"
+			+ "+xTnXGawXS1WUE4CQGPM45mIGSqXcYrLtJkAg3jtRa8YRUn2d7b2BtmWH+jVaVuC\r\n"
+			+ "hNrXYv7iHFOu25yRWhUQJisvdC13D/gKIPRvARXPgPhAC2kovIy6VS8tDoyG6Hm5\r\n"
+			+ "dMgLEGhmqsgaetVq1ZIuBZj5S4j2apBJCDpF6GBfpBOfwIZs0Tpmlw==\r\n"
+			+ "=84Nd\r"
+			+ "-----END PGP SIGNATURE-----\r\n";
+
+		public override string Name
+		{
+			get { return "PGPClearSignedSignature"; }
+		}
+
+		private void messageTest(
+			string message,
+			string type)
+		{
+			ArmoredInputStream aIn = new ArmoredInputStream(
+				new MemoryStream(Encoding.ASCII.GetBytes(message)));
+
+			string[] headers = aIn.GetArmorHeaders();
+
+			if (headers == null || headers.Length != 1)
+			{
+				Fail("wrong number of headers found");
+			}
+
+			if (!"Hash: SHA256".Equals(headers[0]))
+			{
+				Fail("header value wrong: " + headers[0]);
+			}
+
+			//
+			// read the input, making sure we ingore the last newline.
+			//
+			MemoryStream bOut = new MemoryStream();
+			int ch;
+
+			while ((ch = aIn.ReadByte()) >= 0 && aIn.IsClearText())
+			{
+				bOut.WriteByte((byte)ch);
+			}
+
+			PgpPublicKeyRingBundle pgpRings = new PgpPublicKeyRingBundle(publicKey);
+
+			PgpObjectFactory	pgpFact = new PgpObjectFactory(aIn);
+			PgpSignatureList	p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+			PgpSignature		sig = p3[0];
+
+			sig.InitVerify(pgpRings.GetPublicKey(sig.KeyId));
+
+			MemoryStream lineOut = new MemoryStream();
+			Stream sigIn = new MemoryStream(bOut.ToArray(), false);
+			int lookAhead = ReadInputLine(lineOut, sigIn);
+
+			ProcessLine(sig, lineOut.ToArray());
+
+			if (lookAhead != -1)
+			{
+				do
+				{
+					lookAhead = ReadInputLine(lineOut, lookAhead, sigIn);
+
+					sig.Update((byte) '\r');
+					sig.Update((byte) '\n');
+
+					ProcessLine(sig, lineOut.ToArray());
+				}
+				while (lookAhead != -1);
+			}
+
+			if (!sig.Verify())
+			{
+				Fail("signature failed to verify m_in " + type);
+			}
+		}
+
+		private PgpSecretKey ReadSecretKey(
+			Stream    inputStream)
+		{
+			PgpSecretKeyRingBundle        pgpSec = new PgpSecretKeyRingBundle(inputStream);
+
+			//
+			// we just loop through the collection till we find a key suitable for encryption, in the real
+			// world you would probably want to be a bit smarter about this.
+			//
+			//
+			// iterate through the key rings.
+			//
+			foreach (PgpSecretKeyRing kRing in pgpSec.GetKeyRings())
+			{
+				foreach (PgpSecretKey k in kRing.GetSecretKeys())
+				{
+					if (k.IsSigningKey)
+					{
+						return k;
+					}
+				}
+			}
+
+			throw new ArgumentException("Can't find signing key in key ring.");
+		}
+
+		private void generateTest(
+			string message,
+			string type)
+		{
+			PgpSecretKey                    pgpSecKey = ReadSecretKey(new MemoryStream(secretKey));
+			PgpPrivateKey                   pgpPrivKey = pgpSecKey.ExtractPrivateKey("".ToCharArray());
+			PgpSignatureGenerator           sGen = new PgpSignatureGenerator(pgpSecKey.PublicKey.Algorithm, HashAlgorithmTag.Sha256);
+			PgpSignatureSubpacketGenerator  spGen = new PgpSignatureSubpacketGenerator();
+
+			sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);
+
+			IEnumerator    it = pgpSecKey.PublicKey.GetUserIds().GetEnumerator();
+			if (it.MoveNext())
+			{
+				spGen.SetSignerUserId(false, (string)it.Current);
+				sGen.SetHashedSubpackets(spGen.Generate());
+			}
+
+			MemoryStream bOut = new MemoryStream();
+			ArmoredOutputStream aOut = new ArmoredOutputStream(bOut);
+			MemoryStream bIn = new MemoryStream(Encoding.ASCII.GetBytes(message), false);
+
+			aOut.BeginClearText(HashAlgorithmTag.Sha256);
+
+			//
+			// note the last \n m_in the file is ignored
+			//
+			MemoryStream lineOut = new MemoryStream();
+			int lookAhead = ReadInputLine(lineOut, bIn);
+
+			ProcessLine(aOut, sGen, lineOut.ToArray());
+
+			if (lookAhead != -1)
+			{
+				do
+				{
+					lookAhead = ReadInputLine(lineOut, lookAhead, bIn);
+
+					sGen.Update((byte) '\r');
+					sGen.Update((byte) '\n');
+
+					ProcessLine(aOut, sGen, lineOut.ToArray());
+				}
+				while (lookAhead != -1);
+			}
+
+			aOut.EndClearText();
+
+			BcpgOutputStream bcpgOut = new BcpgOutputStream(aOut);
+
+			sGen.Generate().Encode(bcpgOut);
+
+			aOut.Close();
+
+			byte[] bs = bOut.ToArray();
+			messageTest(Encoding.ASCII.GetString(bs, 0, bs.Length), type);
+		}
+
+		private static int ReadInputLine(
+			MemoryStream	bOut,
+			Stream			fIn)
+		{
+			bOut.SetLength(0);
+
+			int lookAhead = -1;
+			int ch;
+
+			while ((ch = fIn.ReadByte()) >= 0)
+			{
+				bOut.WriteByte((byte) ch);
+				if (ch == '\r' || ch == '\n')
+				{
+					lookAhead = ReadPassedEol(bOut, ch, fIn);
+					break;
+				}
+			}
+
+			return lookAhead;
+		}
+
+		private static int ReadInputLine(
+			MemoryStream	bOut,
+			int				lookAhead,
+			Stream			fIn)
+		{
+			bOut.SetLength(0);
+
+			int ch = lookAhead;
+
+			do
+			{
+				bOut.WriteByte((byte) ch);
+				if (ch == '\r' || ch == '\n')
+				{
+					lookAhead = ReadPassedEol(bOut, ch, fIn);
+					break;
+				}
+			}
+			while ((ch = fIn.ReadByte()) >= 0);
+
+			return lookAhead;
+		}
+
+		private static int ReadPassedEol(
+			MemoryStream	bOut,
+			int				lastCh,
+			Stream			fIn)
+		{
+			int lookAhead = fIn.ReadByte();
+
+			if (lastCh == '\r' && lookAhead == '\n')
+			{
+				bOut.WriteByte((byte) lookAhead);
+				lookAhead = fIn.ReadByte();
+			}
+
+			return lookAhead;
+		}
+
+		private static void ProcessLine(
+			PgpSignature	sig,
+			byte[]			line)
+		{
+			int length = GetLengthWithoutWhiteSpace(line);
+			if (length > 0)
+			{
+				sig.Update(line, 0, length);
+			}
+		}
+
+		private static void ProcessLine(
+			Stream					aOut,
+			PgpSignatureGenerator	sGen,
+			byte[]					line)
+		{
+			int length = GetLengthWithoutWhiteSpace(line);
+			if (length > 0)
+			{
+				sGen.Update(line, 0, length);
+			}
+
+			aOut.Write(line, 0, line.Length);
+		}
+
+		private static int GetLengthWithoutWhiteSpace(
+			byte[] line)
+		{
+			int end = line.Length - 1;
+
+			while (end >= 0 && IsWhiteSpace(line[end]))
+			{
+				end--;
+			}
+
+			return end + 1;
+		}
+
+		private static bool IsWhiteSpace(
+			byte b)
+		{
+			return b == '\r' || b == '\n' || b == '\t' || b == ' ';
+		}
+
+		public override void PerformTest()
+		{
+			messageTest(crOnlySignedMessage, "\\r");
+			messageTest(nlOnlySignedMessage, "\\n");
+			messageTest(crNlSignedMessage, "\\r\\n");
+			messageTest(crNlSignedMessageTrailingWhiteSpace, "\\r\\n");
+
+			generateTest(nlOnlyMessage, "\\r");
+			generateTest(crOnlyMessage, "\\n");
+			generateTest(crNlMessage, "\\r\\n");
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PgpClearSignedSignatureTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPCompressionTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPCompressionTest.cs
new file mode 100644
index 0000000..fdcf722
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPCompressionTest.cs
@@ -0,0 +1,117 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Utilities;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	[TestFixture]
+	public class PgpCompressionTest
+		: SimpleTest
+	{
+		private static readonly byte[] Data = Encoding.ASCII.GetBytes("hello world! !dlrow olleh");
+
+		[Test]
+		public void TestUncompressed()
+		{
+			doTestCompression(CompressionAlgorithmTag.Uncompressed);
+		}
+
+		[Test]
+		public void TestZip()
+		{
+			doTestCompression(CompressionAlgorithmTag.Zip);
+		}
+
+		[Test]
+		public void TestZLib()
+		{
+			doTestCompression(CompressionAlgorithmTag.ZLib);
+		}
+
+		[Test]
+		public void TestBZip2()
+		{
+			doTestCompression(CompressionAlgorithmTag.BZip2);
+		}
+
+		public override void PerformTest()
+		{
+			doTestCompression(CompressionAlgorithmTag.Uncompressed);
+			doTestCompression(CompressionAlgorithmTag.Zip);
+			doTestCompression(CompressionAlgorithmTag.ZLib);
+			doTestCompression(CompressionAlgorithmTag.BZip2);
+		}
+
+		private void doTestCompression(
+			CompressionAlgorithmTag type)
+		{
+			doTestCompression(type, true);
+			doTestCompression(type, false);
+		}
+
+		private void doTestCompression(
+			CompressionAlgorithmTag	type,
+			bool					streamClose)
+		{
+			MemoryStream bOut = new MemoryStream();
+			PgpCompressedDataGenerator cPacket = new PgpCompressedDataGenerator(type);
+			Stream os = cPacket.Open(new UncloseableStream(bOut), new byte[Data.Length - 1]);
+			os.Write(Data, 0, Data.Length);
+
+			if (streamClose)
+			{
+				os.Close();
+			}
+			else
+			{
+				cPacket.Close();
+			}
+
+			ValidateData(bOut.ToArray());
+
+			try
+			{
+				os.Close();
+				cPacket.Close();
+			}
+			catch (Exception)
+			{
+				Fail("Redundant Close() should be ignored");
+			}
+		}
+
+		private void ValidateData(
+			byte[] compressed)
+		{
+			PgpObjectFactory pgpFact = new PgpObjectFactory(compressed);
+			PgpCompressedData c1 = (PgpCompressedData) pgpFact.NextPgpObject();
+
+			Stream pIn = c1.GetDataStream();
+			byte[] bytes = Streams.ReadAll(pIn);
+			pIn.Close();
+
+			if (!AreEqual(bytes, Data))
+			{
+				Fail("compression test failed");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "PGPCompressionTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PgpCompressionTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSAElGamalTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSAElGamalTest.cs
new file mode 100644
index 0000000..b863249
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSAElGamalTest.cs
@@ -0,0 +1,492 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	[TestFixture]
+	public class PgpDsaElGamalTest
+		: SimpleTest
+	{
+		private static readonly byte[] testPubKeyRing = Base64.Decode(
+			  "mQGiBEAR8jYRBADNifuSopd20JOQ5x30ljIaY0M6927+vo09NeNxS3KqItba"
+			+ "nz9o5e2aqdT0W1xgdHYZmdElOHTTsugZxdXTEhghyxoo3KhVcNnTABQyrrvX"
+			+ "qouvmP2fEDEw0Vpyk+90BpyY9YlgeX/dEA8OfooRLCJde/iDTl7r9FT+mts8"
+			+ "g3azjwCgx+pOLD9LPBF5E4FhUOdXISJ0f4EEAKXSOi9nZzajpdhe8W2ZL9gc"
+			+ "BpzZi6AcrRZBHOEMqd69gtUxA4eD8xycUQ42yH89imEcwLz8XdJ98uHUxGJi"
+			+ "qp6hq4oakmw8GQfiL7yQIFgaM0dOAI9Afe3m84cEYZsoAFYpB4/s9pVMpPRH"
+			+ "NsVspU0qd3NHnSZ0QXs8L8DXGO1uBACjDUj+8GsfDCIP2QF3JC+nPUNa0Y5t"
+			+ "wKPKl+T8hX/0FBD7fnNeC6c9j5Ir/Fp/QtdaDAOoBKiyNLh1JaB1NY6US5zc"
+			+ "qFks2seZPjXEiE6OIDXYra494mjNKGUobA4hqT2peKWXt/uBcuL1mjKOy8Qf"
+			+ "JxgEd0MOcGJO+1PFFZWGzLQ3RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSBv"
+			+ "bmx5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPohZBBMRAgAZBQJAEfI2BAsH"
+			+ "AwIDFQIDAxYCAQIeAQIXgAAKCRAOtk6iUOgnkDdnAKC/CfLWikSBdbngY6OK"
+			+ "5UN3+o7q1ACcDRqjT3yjBU3WmRUNlxBg3tSuljmwAgAAuQENBEAR8jgQBAC2"
+			+ "kr57iuOaV7Ga1xcU14MNbKcA0PVembRCjcVjei/3yVfT/fuCVtGHOmYLEBqH"
+			+ "bn5aaJ0P/6vMbLCHKuN61NZlts+LEctfwoya43RtcubqMc7eKw4k0JnnoYgB"
+			+ "ocLXOtloCb7jfubOsnfORvrUkK0+Ne6anRhFBYfaBmGU75cQgwADBQP/XxR2"
+			+ "qGHiwn+0YiMioRDRiIAxp6UiC/JQIri2AKSqAi0zeAMdrRsBN7kyzYVVpWwN"
+			+ "5u13gPdQ2HnJ7d4wLWAuizUdKIQxBG8VoCxkbipnwh2RR4xCXFDhJrJFQUm+"
+			+ "4nKx9JvAmZTBIlI5Wsi5qxst/9p5MgP3flXsNi1tRbTmRhqIRgQYEQIABgUC"
+			+ "QBHyOAAKCRAOtk6iUOgnkBStAJoCZBVM61B1LG2xip294MZecMtCwQCbBbsk"
+			+ "JVCXP0/Szm05GB+WN+MOCT2wAgAA");
+
+		private static readonly byte[] testPrivKeyRing = Base64.Decode(
+			  "lQHhBEAR8jYRBADNifuSopd20JOQ5x30ljIaY0M6927+vo09NeNxS3KqItba"
+			+ "nz9o5e2aqdT0W1xgdHYZmdElOHTTsugZxdXTEhghyxoo3KhVcNnTABQyrrvX"
+			+ "qouvmP2fEDEw0Vpyk+90BpyY9YlgeX/dEA8OfooRLCJde/iDTl7r9FT+mts8"
+			+ "g3azjwCgx+pOLD9LPBF5E4FhUOdXISJ0f4EEAKXSOi9nZzajpdhe8W2ZL9gc"
+			+ "BpzZi6AcrRZBHOEMqd69gtUxA4eD8xycUQ42yH89imEcwLz8XdJ98uHUxGJi"
+			+ "qp6hq4oakmw8GQfiL7yQIFgaM0dOAI9Afe3m84cEYZsoAFYpB4/s9pVMpPRH"
+			+ "NsVspU0qd3NHnSZ0QXs8L8DXGO1uBACjDUj+8GsfDCIP2QF3JC+nPUNa0Y5t"
+			+ "wKPKl+T8hX/0FBD7fnNeC6c9j5Ir/Fp/QtdaDAOoBKiyNLh1JaB1NY6US5zc"
+			+ "qFks2seZPjXEiE6OIDXYra494mjNKGUobA4hqT2peKWXt/uBcuL1mjKOy8Qf"
+			+ "JxgEd0MOcGJO+1PFFZWGzP4DAwLeUcsVxIC2s2Bb9ab2XD860TQ2BI2rMD/r"
+			+ "7/psx9WQ+Vz/aFAT3rXkEJ97nFeqEACgKmUCAEk9939EwLQ3RXJpYyBILiBF"
+			+ "Y2hpZG5hICh0ZXN0IGtleSBvbmx5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3Jn"
+			+ "PohZBBMRAgAZBQJAEfI2BAsHAwIDFQIDAxYCAQIeAQIXgAAKCRAOtk6iUOgn"
+			+ "kDdnAJ9Ala3OcwEV1DbK906CheYWo4zIQwCfUqUOLMp/zj6QAk02bbJAhV1r"
+			+ "sAewAgAAnQFYBEAR8jgQBAC2kr57iuOaV7Ga1xcU14MNbKcA0PVembRCjcVj"
+			+ "ei/3yVfT/fuCVtGHOmYLEBqHbn5aaJ0P/6vMbLCHKuN61NZlts+LEctfwoya"
+			+ "43RtcubqMc7eKw4k0JnnoYgBocLXOtloCb7jfubOsnfORvrUkK0+Ne6anRhF"
+			+ "BYfaBmGU75cQgwADBQP/XxR2qGHiwn+0YiMioRDRiIAxp6UiC/JQIri2AKSq"
+			+ "Ai0zeAMdrRsBN7kyzYVVpWwN5u13gPdQ2HnJ7d4wLWAuizUdKIQxBG8VoCxk"
+			+ "bipnwh2RR4xCXFDhJrJFQUm+4nKx9JvAmZTBIlI5Wsi5qxst/9p5MgP3flXs"
+			+ "Ni1tRbTmRhr+AwMC3lHLFcSAtrNg/EiWFLAnKNXH27zjwuhje8u2r+9iMTYs"
+			+ "GjbRxaxRY0GKRhttCwqe2BC0lHhzifdlEcc9yjIjuKfepG2fnnSIRgQYEQIA"
+			+ "BgUCQBHyOAAKCRAOtk6iUOgnkBStAJ9HFejVtVJ/A9LM/mDPe0ExhEXt/QCg"
+			+ "m/KM7hJ/JrfnLQl7IaZsdg1F6vCwAgAA");
+
+		private static readonly byte[] encMessage = Base64.Decode(
+			  "hQEOAynbo4lhNjcHEAP/dgCkMtPB6mIgjFvNiotjaoh4sAXf4vFNkSeehQ2c"
+			+ "r+IMt9CgIYodJI3FoJXxOuTcwesqTp5hRzgUBJS0adLDJwcNubFMy0M2tp5o"
+			+ "KTWpXulIiqyO6f5jI/oEDHPzFoYgBmR4x72l/YpMy8UoYGtNxNvR7LVOfqJv"
+			+ "uDY/71KMtPQEAIadOWpf1P5Td+61Zqn2VH2UV7H8eI6hGa6Lsy4sb9iZNE7f"
+			+ "c+spGJlgkiOt8TrQoq3iOK9UN9nHZLiCSIEGCzsEn3uNuorD++Qs065ij+Oy"
+			+ "36TKeuJ+38CfT7u47dEshHCPqWhBKEYrxZWHUJU/izw2Q1Yxd2XRxN+nafTL"
+			+ "X1fQ0lABQUASa18s0BkkEERIdcKQXVLEswWcGqWNv1ZghC7xO2VDBX4HrPjp"
+			+ "drjL63p2UHzJ7/4gPWGGtnqq1Xita/1mrImn7pzLThDWiT55vjw6Hw==");
+
+		private static readonly byte[] signedAndEncMessage = Base64.Decode(
+			  "hQEOAynbo4lhNjcHEAP+K20MVhzdX57hf/cU8TH0prP0VePr9mmeBedzqqMn"
+			+ "fp2p8Zb68zmcMlI/WiL5XMNLYRmCgEcXyWbKdP/XV9m9LDBe1CMAGrkCeGBy"
+			+ "je69IQQ5LS9vDPyEMF4iAAv/EqACjqHkizdY/a/FRx/t2ioXYdEC2jA6kS9C"
+			+ "McpsNz16DE8EAIk3uKn4bGo/+15TXkyFYzW5Cf71SfRoHNmU2zAI93zhjN+T"
+			+ "B7mGJwWXzsMkIO6FkMU5TCSrwZS3DBWCIaJ6SYoaawE/C/2j9D7bX1Jv8kum"
+			+ "4cq+eZM7z6JYs6xend+WAwittpUxbEiyC2AJb3fBSXPAbLqWd6J6xbZZ7GDK"
+			+ "r2Ca0pwBxwGhbMDyi2zpHLzw95H7Ah2wMcGU6kMLB+hzBSZ6mSTGFehqFQE3"
+			+ "2BnAj7MtnbghiefogacJ891jj8Y2ggJeKDuRz8j2iICaTOy+Y2rXnnJwfYzm"
+			+ "BMWcd2h1C5+UeBJ9CrrLniCCI8s5u8z36Rno3sfhBnXdRmWSxExXtocbg1Ht"
+			+ "dyiThf6TK3W29Yy/T6x45Ws5zOasaJdsFKM=");
+
+		private static readonly char[] pass = "hello world".ToCharArray();
+
+		private static readonly SecureRandom random = new SecureRandom();
+
+		public override void PerformTest()
+		{
+			PgpPublicKey pubKey = null;
+
+			//
+			// Read the public key
+			//
+			PgpObjectFactory pgpFact = new PgpObjectFactory(testPubKeyRing);
+			PgpPublicKeyRing pgpPub = (PgpPublicKeyRing)pgpFact.NextPgpObject();
+
+			pubKey = pgpPub.GetPublicKey();
+
+			if (pubKey.BitStrength != 1024)
+			{
+				Fail("failed - key strength reported incorrectly.");
+			}
+
+			//
+			// Read the private key
+			//
+			PgpSecretKeyRing	sKey = new PgpSecretKeyRing(testPrivKeyRing);
+			PgpSecretKey		secretKey = sKey.GetSecretKey();
+			PgpPrivateKey		pgpPrivKey = secretKey.ExtractPrivateKey(pass);
+
+			//
+			// signature generation
+			//
+			const string data = "hello world!";
+			byte[] dataBytes = Encoding.ASCII.GetBytes(data);
+			MemoryStream bOut = new MemoryStream();
+			MemoryStream testIn = new MemoryStream(dataBytes, false);
+			PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa,
+				HashAlgorithmTag.Sha1);
+
+			sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+
+			PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(
+				CompressionAlgorithmTag.Zip);
+
+			BcpgOutputStream bcOut = new BcpgOutputStream(
+				cGen.Open(new UncloseableStream(bOut)));
+
+			sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+			PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+
+			DateTime testDateTime = new DateTime(1973, 7, 27);
+			Stream lOut = lGen.Open(
+				new UncloseableStream(bcOut),
+				PgpLiteralData.Binary,
+				"_CONSOLE",
+				dataBytes.Length,
+				testDateTime);
+
+			int ch;
+			while ((ch = testIn.ReadByte()) >= 0)
+			{
+				lOut.WriteByte((byte) ch);
+				sGen.Update((byte) ch);
+			}
+
+			lGen.Close();
+
+			sGen.Generate().Encode(bcOut);
+
+			cGen.Close();
+
+			//
+			// verify Generated signature
+			//
+			pgpFact = new PgpObjectFactory(bOut.ToArray());
+
+			PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+			pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+			PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+			PgpOnePassSignature ops = p1[0];
+
+			PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+			if (!p2.ModificationTime.Equals(testDateTime))
+			{
+				Fail("Modification time not preserved");
+			}
+
+			Stream    dIn = p2.GetInputStream();
+
+			ops.InitVerify(pubKey);
+
+			while ((ch = dIn.ReadByte()) >= 0)
+			{
+				ops.Update((byte)ch);
+			}
+
+			PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+			if (!ops.Verify(p3[0]))
+			{
+				Fail("Failed Generated signature check");
+			}
+
+			//
+			// test encryption
+			//
+
+			//
+			// find a key sutiable for encryption
+			//
+			long pgpKeyID = 0;
+			AsymmetricKeyParameter pKey = null;
+
+			foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
+			{
+				if (pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalEncrypt
+					|| pgpKey.Algorithm == PublicKeyAlgorithmTag.ElGamalGeneral)
+				{
+					pKey = pgpKey.GetKey();
+					pgpKeyID = pgpKey.KeyId;
+					if (pgpKey.BitStrength != 1024)
+					{
+						Fail("failed - key strength reported incorrectly.");
+					}
+
+					//
+					// verify the key
+					//
+
+				}
+			}
+
+			IBufferedCipher c = CipherUtilities.GetCipher("ElGamal/None/PKCS1Padding");
+
+			c.Init(true, pKey);
+
+			byte[] inBytes = Encoding.ASCII.GetBytes("hello world");
+			byte[] outBytes = c.DoFinal(inBytes);
+
+			pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass);
+
+			c.Init(false, pgpPrivKey.Key);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!Arrays.AreEqual(inBytes, outBytes))
+			{
+				Fail("decryption failed.");
+			}
+
+			//
+			// encrypted message
+			//
+			byte[] text = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o',
+								(byte)' ', (byte)'w', (byte)'o', (byte)'r', (byte)'l', (byte)'d', (byte)'!', (byte)'\n' };
+
+			PgpObjectFactory pgpF = new PgpObjectFactory(encMessage);
+
+			PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+			PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];
+
+			Stream clear = encP.GetDataStream(pgpPrivKey);
+
+			pgpFact = new PgpObjectFactory(clear);
+
+			c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+			pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+			PgpLiteralData ld = (PgpLiteralData)pgpFact.NextPgpObject();
+
+			if (!ld.FileName.Equals("test.txt"))
+			{
+				throw new Exception("wrong filename in packet");
+			}
+
+			Stream inLd = ld.GetDataStream();
+			byte[] bytes = Streams.ReadAll(inLd);
+
+			if (!Arrays.AreEqual(bytes, text))
+			{
+				Fail("wrong plain text in decrypted packet");
+			}
+
+			//
+			// signed and encrypted message
+			//
+			pgpF = new PgpObjectFactory(signedAndEncMessage);
+
+			encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+			encP = (PgpPublicKeyEncryptedData)encList[0];
+
+			clear = encP.GetDataStream(pgpPrivKey);
+
+			pgpFact = new PgpObjectFactory(clear);
+
+			c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+			pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+			p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+			ops = p1[0];
+
+			ld = (PgpLiteralData)pgpFact.NextPgpObject();
+
+			bOut = new MemoryStream();
+
+			if (!ld.FileName.Equals("test.txt"))
+			{
+				throw new Exception("wrong filename in packet");
+			}
+
+			inLd = ld.GetDataStream();
+
+			//
+			// note: we use the DSA public key here.
+			//
+			ops.InitVerify(pgpPub.GetPublicKey());
+
+			while ((ch = inLd.ReadByte()) >= 0)
+			{
+				ops.Update((byte) ch);
+				bOut.WriteByte((byte) ch);
+			}
+
+			p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+			if (!ops.Verify(p3[0]))
+			{
+				Fail("Failed signature check");
+			}
+
+			if (!Arrays.AreEqual(bOut.ToArray(), text))
+			{
+				Fail("wrong plain text in decrypted packet");
+			}
+
+			//
+			// encrypt
+			//
+			MemoryStream cbOut = new MemoryStream();
+			PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(
+				SymmetricKeyAlgorithmTag.TripleDes, random);
+			PgpPublicKey puK = sKey.GetSecretKey(pgpKeyID).PublicKey;
+
+			cPk.AddMethod(puK);
+
+			Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOut.ToArray().Length);
+
+			cOut.Write(text, 0, text.Length);
+
+			cOut.Close();
+
+			pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+			encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+			encP = (PgpPublicKeyEncryptedData)encList[0];
+
+			pgpPrivKey = sKey.GetSecretKey(pgpKeyID).ExtractPrivateKey(pass);
+
+			clear = encP.GetDataStream(pgpPrivKey);
+			outBytes = Streams.ReadAll(clear);
+
+			if (!Arrays.AreEqual(outBytes, text))
+			{
+				Fail("wrong plain text in Generated packet");
+			}
+
+			//
+			// use of PgpKeyPair
+			//
+			BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+			BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+			ElGamalParameters elParams = new ElGamalParameters(p, g);
+
+			IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
+			kpg.Init(new ElGamalKeyGenerationParameters(random, elParams));
+
+			AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();
+
+			PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalGeneral ,
+				kp.Public, kp.Private, DateTime.UtcNow);
+
+			PgpPublicKey k1 = pgpKp.PublicKey;
+			PgpPrivateKey k2 = pgpKp.PrivateKey;
+
+
+
+
+
+			// Test bug with ElGamal P size != 0 mod 8 (don't use these sizes at home!)
+			for (int pSize = 257; pSize < 264; ++pSize)
+			{
+				// Generate some parameters of the given size
+				ElGamalParametersGenerator epg = new ElGamalParametersGenerator();
+				epg.Init(pSize, 2, random);
+
+				elParams = epg.GenerateParameters();
+
+				kpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
+				kpg.Init(new ElGamalKeyGenerationParameters(random, elParams));
+
+
+				// Run a short encrypt/decrypt test with random key for the given parameters
+				kp = kpg.GenerateKeyPair();
+
+				PgpKeyPair elGamalKeyPair = new PgpKeyPair(
+					PublicKeyAlgorithmTag.ElGamalGeneral, kp, DateTime.UtcNow);
+
+				cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, random);
+
+				puK = elGamalKeyPair.PublicKey;
+
+				cPk.AddMethod(puK);
+
+				cbOut = new MemoryStream();
+
+				cOut = cPk.Open(new UncloseableStream(cbOut), text.Length);
+
+				cOut.Write(text, 0, text.Length);
+
+				cOut.Close();
+
+				pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+				encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+				encP = (PgpPublicKeyEncryptedData)encList[0];
+
+				pgpPrivKey = elGamalKeyPair.PrivateKey;
+
+				// Note: This is where an exception would be expected if the P size causes problems
+				clear = encP.GetDataStream(pgpPrivKey);
+				byte[] decText = Streams.ReadAll(clear);
+
+				if (!Arrays.AreEqual(text, decText))
+				{
+					Fail("decrypted message incorrect");
+				}
+			}
+
+
+			// check sub key encoding
+
+			foreach (PgpPublicKey pgpKey in pgpPub.GetPublicKeys())
+			{
+				if (!pgpKey.IsMasterKey)
+				{
+					byte[] kEnc = pgpKey.GetEncoded();
+
+					PgpObjectFactory objF = new PgpObjectFactory(kEnc);
+
+					// TODO Make PgpPublicKey a PgpObject or return a PgpPublicKeyRing
+//					PgpPublicKey k = (PgpPublicKey)objF.NextPgpObject();
+//
+//					pKey = k.GetKey();
+//					pgpKeyID = k.KeyId;
+//					if (k.BitStrength != 1024)
+//					{
+//						Fail("failed - key strength reported incorrectly.");
+//					}
+//
+//					if (objF.NextPgpObject() != null)
+//					{
+//						Fail("failed - stream not fully parsed.");
+//					}
+                }
+            }
+		}
+
+		public override string Name
+		{
+			get { return "PGPDSAElGamalTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PgpDsaElGamalTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSATest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSATest.cs
new file mode 100644
index 0000000..7808ed6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPDSATest.cs
@@ -0,0 +1,597 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+	[TestFixture]
+    public class PgpDsaTest
+		: SimpleTest
+    {
+		private static readonly byte[] testPubKey = Base64.Decode(
+              "mQGiBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
+            + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
+            + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
+            + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
+            + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
+            + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
+            + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
+            + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
+            + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbLQzRXJpYyBFY2hp"
+            + "ZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNhc3RsZS5vcmc+iFkEExEC"
+            + "ABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j9enEyjRDAlwAn2rrom0s"
+            + "MhufWK5vIRwg7gj5qsLEAJ4vnT5dPBVblofsG+pDoCVeJXGGng==");
+
+		private static readonly byte[] testPrivKey = Base64.Decode(
+			  "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
+            + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
+            + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
+            + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
+            + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
+            + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
+            + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
+            + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
+            + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC"
+            + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu"
+            + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh"
+            + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j"
+            + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD"
+            + "4nXkHg==");
+
+		private static readonly byte[] testPrivKey2 = Base64.Decode(
+              "lQHhBEAnoewRBADRvKgDhbV6pMzqYfUgBsLxSHzmycpuxGbjMrpyKHDOEemj"
+            + "iQb6TyyBKUoR28/pfshFP9R5urtKIT7wjVrDuOkxYkgRhNm+xmPXW2Lw3D++"
+            + "MQrC5VWe8ywBltz6T9msmChsaKo2hDhIiRI/mg9Q6rH9pJKtVGi4R7CgGxM2"
+            + "STQ5fwCgub38qGS1W2O4hUsa+3gva5gaNZUEAItegda4/H4t88XdWxW3D8pv"
+            + "RnFz26/ADdImVaQlBoumD15VmcgYoT1Djizey7X8vfV+pntudESzLbn3GHlI"
+            + "6C09seH4e8eYP63t7KU/qbUCDomlSswd1OgQ/RxfN86q765K2t3K1i3wDSxe"
+            + "EgSRyGKee0VNvOBFOFhuWt+patXaBADE1riNkUxg2P4lBNWwu8tEZRmsl/Ys"
+            + "DBIzXBshoMzZCvS5PnNXMW4G3SAaC9OC9jvKSx9IEWhKjfjs3QcWzXR28mcm"
+            + "5na0bTxeOMlaPPhBdkTCmFl0IITWlH/pFlR2ah9WYoWYhZEL2tqB82wByzxH"
+            + "SkSeD9V5oeSCdCcqiqkEmv4DAwLeNsQ2XGJVRmA4lld+CR5vRxpT/+/2xklp"
+            + "lxVf/nx0+thrHDpro3u/nINIIObk0gh59+zaEEe3APlHqbQVYWFhIGJiYiA8"
+            + "Y2NjQGRkZC5lZWU+iFoEExECABoFAkAnoewFCwcDAgEDFQIDAxYCAQIeAQIX"
+            + "gAAKCRA5nBpCS63az85BAKCbPfU8ATrFvkXhzGNGlc1BJo6DWQCgnK125xVK"
+            + "lWLpt6ZJJ7TXcx3nkm6wAgAAnQFXBEAnoe0QBACsQxPvaeBcv2TkbgU/5Wc/"
+            + "tO222dPE1mxFbXjGTKfb+6ge96iyD8kTRLrKCkEEeVBa8AZqMSoXUVN6tV8j"
+            + "/zD8Bc76o5iJ6wgpg3Mmy2GxInVfsfZN6/G3Y2ukmouz+CDNvQdUw8cTguIb"
+            + "QoV3XhQ03MLbfVmNcHsku9F4CuKNWwADBQP0DSSe8v5PXF9CSCXOIxBDcQ5x"
+            + "RKjyYOveqoH/4lbOV0YNUbIDZq4RaUdotpADuPREFmWf0zTB6KV/WIiag8XU"
+            + "WU9zdDvLKR483Bo6Do5pDBcN+NqfQ+ntGY9WJ7BSFnhQ3+07i1K+NsfFTRfv"
+            + "hf9X3MP75rCf7MxAIWHTabEmUf4DAwLeNsQ2XGJVRmA8DssBUCghogG9n8T3"
+            + "qfBeKsplGyCcF+JjPeQXkKQaoYGJ0aJz36qFP9d8DuWtT9soQcqIxVf6mTa8"
+            + "kN1594hGBBgRAgAGBQJAJ6HtAAoJEDmcGkJLrdrPpMkAnRyjQSKugz0YJqOB"
+            + "yGasMLQLxd2OAKCEIlhtCarlufVQNGZsuWxHVbU8crACAAA=");
+
+		private static readonly byte[] sig1 = Base64.Decode(
+              "owGbwMvMwCR4VvnryyOnTJwZ10gncZSkFpfolVSU2Ltz78hIzcnJVyjPL8pJUeTq"
+            + "sGdmZQCJwpQLMq3ayTA/0Fj3xf4jbwPfK/H3zj55Z9L1n2k/GOapKJrvMZ4tLiCW"
+            + "GtP/XeDqX4fORDUA");
+
+		private static readonly byte[] sig1crc = Base64.Decode("OZa/");
+
+		private static readonly byte[] testPubWithUserAttr = Base64.Decode(
+              "mQGiBD2Rqv0RBADqKCkhVEtB/lEEr/9CubuHEy2oN/yU5j+2GXSdcNdVnRI/rwFy"
+            + "fHEQIk3uU7zHSUKFrC59yDm0sODYyjEdE3BVb0xvEJ5LE/OdndcIMXT1DungZ1vB"
+            + "zIK/3lr33W/PHixYxv9jduH3WrTehBpiKkgMZp8XloSFj2Cnw9LDyfqB7QCg/8K1"
+            + "o2k75NkOd9ZjnA9ye7Ri3bEEAKyr61Mo7viPWBK1joWAEsxG0OBWM+iSlG7kwh31"
+            + "8efgC/7Os6x4Y0jzs8mpcbBjeZtZjS9lRbfp7RinhF269xL0TZ3JxIdtaAV/6yDQ"
+            + "9NXfZY9dskN++HIR/5GCEEgq/qTJZt6ti5k7aV19ZFfO6wiK3NUy08wOrVsdOkVE"
+            + "w9IcBADaplhpcel3201uU3OCboogJtw81R5MJMZ4Y9cKL/ca2jGISn0nA7KrAw9v"
+            + "ShheSixGO4BV9JECkLEbtg7i+W/j/De6S+x2GLNcphuTP3UmgtKbhs0ItRqzW561"
+            + "s6gLkqi6aWmgaFLd8E1pMJcd9DSY95P13EYB9VJIUxFNUopzo7QcUmFsZiBIYXVz"
+            + "ZXIgPGhhdXNlckBhY20ub3JnPokAWAQQEQIAGAUCPZGq/QgLAwkIBwIBCgIZAQUb"
+            + "AwAAAAAKCRAqIBiOh4JvOKg4AJ9j14yygOqqzqiLKeaasIzqT8LCIgCggx14WuLO"
+            + "wOUTUswTaVKMFnU7tseJAJwEEAECAAYFAj2Rqx8ACgkQ9aWTKMpUDFV+9QP/RiWT"
+            + "5FAF5Rgb7beaApsgXsME+Pw7HEYFtqGa6VcXEpbcUXO6rjaXsgMgY90klWlWCF1T"
+            + "HOyKITvj2FdhE+0j8NQn4vaGpiTwORW/zMf/BZ0abdSWQybp10Yjs8gXw30UheO+"
+            + "F1E524MC+s2AeUi2hwHMiS+AVYd4WhxWHmWuBpTRypP/AAALTgEQAAEBAAAAAQAA"
+            + "AAABAAAA/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQ"
+            + "Dg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/"
+            + "2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7"
+            + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozv/wAARCABqAF0DASIAAhEBAxEB/8QAHwAAAQUB"
+            + "AQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQID"
+            + "AAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0"
+            + "NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKT"
+            + "lJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl"
+            + "5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL"
+            + "/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHB"
+            + "CSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpj"
+            + "ZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3"
+            + "uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIR"
+            + "AxEAPwD2aiiq9xcxWsRllcKqjOT06E/0oAsVm6jrmm6VGXvLuOPGflz8x+grzXxV"
+            + "8U51u5LXRgBGowZHXknnkc9OQcV51caneXdw9xPOXlckl2AJHY4J6cD1oA9J1z4p"
+            + "TRkrYQhRyQ0hIY5/2QRx7k9ulczN8SvEEshdZkX0UorDrznI759a5Mksckkknqec"
+            + "mkoA7WD4oavEoEttbTepYEZ+mCMVv6H8SLTULhbe/gFozAYkD5Unp3Ax/kV5XRQB"
+            + "9EAhgCDkHkEcgilryTwd4zn0m4WzvpTJZSMBuY5MfbueletKyugZWDKwyCOc/j3o"
+            + "AduyWLDeWB5Ynj8jSUUUAdFXn/xU15dO0RbGGYC5uWwUB6L1Jx+n413F1cJa2stz"
+            + "J92JC5+gGa+bdfvp9S1q4urmRneQg5Yk4HGAPYZoAzySxySSSep5yaSvQvAPhOHU"
+            + "rB7u5iLGUlIwQRx7HPr/AJ9LGsfC+dJGngc+X12gc8nvx1/rQB5rRXS3Xg28t9ye"
+            + "VLvA7Ddj8MDt6Vnx6JKJCsocnBwqqQSOxPH+fWgDKorTl0SaLGXxkZ+ZcZ4z1yfb"
+            + "P1qg0MqLueN1A6kqRigCOvVPh74mF9YjS7tgLi3GIm6b17c+oOfrXlda3haeW38R"
+            + "WjxfeMgBOCcD/PHpzQB7nRRRQBqarZjUNLubPJXz4yhI64PFfO3iDRrnRtdm0+cq"
+            + "0ocEbehzyOv1xX0vXnHxU8Kf2hYf23aRk3VsMTAZO6MZ5x7UAbfga1W00WzjRSF8"
+            + "kbsg5z744HT/ADmuoysikdQSVP8AI1yPgq6il0axk27V8sDcTg5x7V1qSxOcJIrH"
+            + "/ZOaAKV5p8JgJSPJGMr97PNcxqOiRXLiRI8nONoIGO55z/8AqyeldhPcQxwyOzoQ"
+            + "owRkflXH6t4q0nTLjy57mNXfJCA5x+Qx0NAGXd6LD5iiaPYwTAAx07+vXvXOXmiR"
+            + "Qu6u5VTk/MQQV7cdvxPT866KbxTpt7HGR8p7SMw5HuOP8/Ws/ULlb2No0bKMOGBJ"
+            + "BHrjHHXn6D8QDzWZQk8iAYVWIA9K6LwDZNeeJ4sEqsaF2YHBHpz2/wA/WsG+V0vZ"
+            + "kkGGVsEZz9OcntXffC62iiS7vJTsklKxRFuAw6nBP+eKAPRKKKKAOiqOSNJYzHIo"
+            + "ZGGCD0NSUUAeRajIunwzQG4e3tYZTHGsPzOxJ6ADuQcH8Pw5v+19Q0rVJVgl1JG3"
+            + "cxykEj13cnHT1r1C38OQ3l063cIkkhmkZDKSeCfx9R/kVLeeGIRKs7hVVDn5OCx9"
+            + "yeTjqMf0oAo3k1xP4biuJFeKV4w7gDaQcen1/wAjt5gbK81HW41kIiJBZppULe47"
+            + "eoxx+YzivW9Vh/0FAE+XPIJGCOR0rnbPT7eG+LyxlkAG1wQSPXrjvg9MfjQBycNj"
+            + "4hMRZgJkUjETQqAy/UAY6DoO/wCNbVlYTNbSNJbmBlBwoUfM30B7j2/lz20VhbKA"
+            + "wHmZOQWbOfyrO1G3jil8tBhWToOcdu+c/wAvagDzbUdGlu9aRxFiB/vsuBggZOfq"
+            + "cfWujSIR2dnNZTEeXKgMcb4BUHjofbjNKmI5juiabaGGxVJLcdh/nFWtI0oxagsD"
+            + "DIkkWXYp4VQDnOemSfyHbigDtgSQMjBI6HqKKKKAOiopoPXjGKdQBnXLiDUI5SMK"
+            + "VwxHGf8APFUtW1A+YkMKmbnc23njuf6D/ObWquoaNSQCM/rwP1rMYxxTGWR1UsoU"
+            + "biAcdep+o/KgDG1LxdpracIirCVRjaykHr6cHGQe1cv/AGjNcXBW3sntyT/rHcjj"
+            + "Hp6Z+nQdAK6PXIdIvcE3Fv5rEfNgP9eRn8c8d/rgzX2i2sqo1y8745CD5WPseOnH"
+            + "f8aANiz1O9gjiR5FMUhAV1wcH0Ix6jHHSrMsskz7pGy2MZNc8PEEM7xxWsM/lr8r"
+            + "b4jtI9CcHt7nr7Vqi4JuEjB2qse9y2Ace47dRn/OQDMuRMl8RHw7SgDBPGT6jpwf"
+            + "yzXa2NmbYF3IMrDB2kkAe3HP5Vwk99u1hdg3ANuOOOB0z6ZwPz6c8eiAhgCDkHkE"
+            + "cgigBaKKKAOiqJiMEb9mBknjim3LFIGcOU285ArNa8mKIN3QclScn6+/FADL9xOc"
+            + "K2Tj7xAxnAwQPqOmawdSNpeSJBfQyGNXwQpIAPvjqOPyPT12nYsxYnJIGSeMnHP+"
+            + "e9UL7TUumEqOYp1GNw6N/vDv/wDXoA5+70vSbFGlhtopUxkBl3EZ45z7/kKwTdpN"
+            + "cIsOmeSCduUiCnB9cdeg/M/j0v8AbFtY5hu0gjmGSRICT19cdMDt3+lULzxPZGZv"
+            + "LXcBnCrwB6Y4PX+ZoAptMRbiMDAGSSMksf8A9Q6DuKzJtVYs+BvcPgMTkEdOTnrx"
+            + "/KoLzVmvZZQjjaT82DyPbqcdx+GKitLf7TNsLYAGWPfH+TQBcsYJDE0rOyu4wjHk"
+            + "gfQ+p/zzWjpnja5sdSOm6yyK0Z2pMCQjZ+6SM9CCMdhnp3E1hYy393FaW0eXfjAx"
+            + "gAdT26D+X4Vg/EuFLbxOsCYBitkQkEdsgcADsB+lAHplvqUbsu5vlYA5PIB7468e"
+            + "nPf8lfUlDkRRrIvqZNn6EV41o3iO/wBFcCJ/MhBP7pjwD6g9ua7G08b6TcRl7h5L"
+            + "eTPKvGz5+hUH9cUAeo3uFDrt+Y4O7HOOB69Pr/8AXqhUlx/r2/z2qOgBCQoJJwBy"
+            + "SeABXHeIfHVvbXcemaW4luHlVJJlIKxjODgg8nqKq/Em6uItOhWOeVAx5CuRnrXn"
+            + "+jf8hyw/6+Y//QhQB6xrmlxzXc0NyuHVyQcdjnBz379D1BGeK5u88LMJGlt2RlX7"
+            + "qkEsPXn6/pXo/ilVzbttG7DDOOeornqAONbRpI4v3pKOQcAqQD+Y/P6j052NK0p5"
+            + "HWHy3IBPyqrfN6gZz+P4/hpXoGzOOiP/ACNdH4XRftsp2jIBxx70AX9E0pdMtvMm"
+            + "VRNt5xyEGOgPf3NeDeLdVOs+J768zlGkKx+yjgfy/WvoPXeNEvMcfujXzJQAUUUU"
+            + "Af/ZiQBGBBARAgAGBQI9katEAAoJECogGI6Hgm84xz8AoNGz1fJrVPxqkBrUDmWA"
+            + "GsP6qVGYAJ0ZOftw/GfQHzdGR8pOK85DLUPEErQkUmFsZiBIYXVzZXIgPGhhdXNl"
+            + "ckBwcml2YXNwaGVyZS5jb20+iQBGBBARAgAGBQI9katmAAoJECogGI6Hgm84m0oA"
+            + "oJS3CTrgpqRZfhgPtHGtUVjRCJbbAJ9stJgPcbqA2xXEg9yl2TQToWdWxbQkUmFs"
+            + "ZiBIYXVzZXIgPGhhdXNlckBwcml2YXNwaGVyZS5vcmc+iQBGBBARAgAGBQI9kauJ"
+            + "AAoJECogGI6Hgm84GfAAnRswktLMzDfIjv6ni76Qp5B850byAJ90I0LEHOLhda7r"
+            + "kqTwZ8rguNssUrQkUmFsZiBIYXVzZXIgPGhhdXNlckBwcml2YXNwaGVyZS5uZXQ+"
+            + "iQBGBBARAgAGBQI9kaubAAoJECogGI6Hgm84zi0An16C4s/B9Z0/AtfoN4ealMh3"
+            + "i3/7AJ9Jg4GOUqGCGRRKUA9Gs5pk8yM8GbQmUmFsZiBDLiBIYXVzZXIgPHJhbGZo"
+            + "YXVzZXJAYmx1ZXdpbi5jaD6JAEYEEBECAAYFAj2Rq8oACgkQKiAYjoeCbzhPOACg"
+            + "iiTohKuIa66FNiI24mQ+XR9nTisAoLmh3lJf16/06qLPsRd9shTkLfmHtB9SYWxm"
+            + "IEhhdXNlciA8cmFsZmhhdXNlckBnbXguY2g+iQBGBBARAgAGBQI9kavvAAoJECog"
+            + "GI6Hgm84ZE8An0RlgL8mPBa/P08S5e/lD35MlDdgAJ99pjCeY46S9+nVyx7ACyKO"
+            + "SZ4OcLQmUmFsZiBIYXVzZXIgPGhhdXNlci5yYWxmQG15c3VucmlzZS5jaD6JAEYE"
+            + "EBECAAYFAj2RrEEACgkQKiAYjoeCbzjz0wCg+q801XrXk+Rf+koSI50MW5OaaKYA"
+            + "oKOVA8SLxE29qSR/bJeuW0ryzRLqtCVSYWxmIEhhdXNlciA8aGF1c2VyLnJhbGZA"
+            + "ZnJlZXN1cmYuY2g+iQBGBBARAgAGBQI9kaxXAAoJECogGI6Hgm848zoAnRBtWH6e"
+            + "fTb3is63s8J2zTfpsyS0AKDxTjl+ZZV0COHLrSCaNLZVcpImFrkEDQQ9kar+EBAA"
+            + "+RigfloGYXpDkJXcBWyHhuxh7M1FHw7Y4KN5xsncegus5D/jRpS2MEpT13wCFkiA"
+            + "tRXlKZmpnwd00//jocWWIE6YZbjYDe4QXau2FxxR2FDKIldDKb6V6FYrOHhcC9v4"
+            + "TE3V46pGzPvOF+gqnRRh44SpT9GDhKh5tu+Pp0NGCMbMHXdXJDhK4sTw6I4TZ5dO"
+            + "khNh9tvrJQ4X/faY98h8ebByHTh1+/bBc8SDESYrQ2DD4+jWCv2hKCYLrqmus2UP"
+            + "ogBTAaB81qujEh76DyrOH3SET8rzF/OkQOnX0ne2Qi0CNsEmy2henXyYCQqNfi3t"
+            + "5F159dSST5sYjvwqp0t8MvZCV7cIfwgXcqK61qlC8wXo+VMROU+28W65Szgg2gGn"
+            + "VqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09jdvOmeFX"
+            + "klnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2gpXI61Brwv0YAWCvl"
+            + "9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPAQ/ClWxiNjrtVjLhd"
+            + "ONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrKlQzZlp+r"
+            + "0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVes91hcAAgIQAKD9MGkS8SUD2irI"
+            + "AiwVHU0WXLBnk2CvvueSmT9YtC34UKkIkDPZ7VoeuXDfqTOlbiE6T16zPvArZfbl"
+            + "JGdrU7HhsTdu+ADxRt1dPur0G0ICJ3pBD3ydGWpdLI/94x1BvTY4rsR5mS4YWmpf"
+            + "e2kWc7ZqezhP7Xt9q7m4EK456ddeUZWtkwGU+PKyRAZ+CK82Uhouw+4aW0NjiqmX"
+            + "hfH9/BUhI1P/8R9VkTfAFGPmZzqoHr4AuO5tLRLD2RFSmQCP8nZTiP9nP+wBBvn7"
+            + "vuqKRQsj9PwwPD4V5SM+kpW+rUIWr9TZYl3UqSnlXlpEZFd2Bfl6NloeH0cfU69E"
+            + "gtjcWGvGxYKPS0cg5yhVb4okka6RqIPQiYl6eJgv4tRTKoPRX29o0aUVdqVvDr5u"
+            + "tnFzcINq7jTo8GiO8Ia3cIFWfo0LyQBd1cf1U+eEOz+DleEFqyljaz9VCbDPE4GP"
+            + "o+ALESBlOwn5daUSaah9iU8aVPaSjn45hoQqxOKPwJxnCKKQ01iy0Gir+CDU8JJB"
+            + "7bmbvQN4bke30EGAeED3oi+3VaBHrhjYLv7SHIxP5jtCJKWMJuLRV709HsWJi3kn"
+            + "fGHwH+yCDF8+PDeROAzpXBaD2EFhKgeUTjP5Rgn6ltRf8TQnfbW4qlwyiXMhPOfC"
+            + "x6qNmwaFPKQJpIkVq5VGfRXAERfkiQBMBBgRAgAMBQI9kar+BRsMAAAAAAoJECog"
+            + "GI6Hgm84CDMAoNrNeP4c8XqFJnsLLPcjk5YGLaVIAKCrL5KFuLQVIp7d0Fkscx3/"
+            + "7DGrzw==");
+
+		private static readonly byte[] aesSecretKey = Base64.Decode(
+              "lQHpBEBSdIYRBADpd7MeIxRk4RsvyMnJNIYe4FiVv6i7I7+LPRvnIjDct0bN"
+            + "1gCV48QFej7g/PsvXRjYSowV3VIvchWX8OERd/5i10cLbcs7X52EP1vwYaLj"
+            + "uRfNUBg8Q51RQsKR+/rBmnVsi68rjU4yTH6wpo6FOO4pz4wFV+tWwGOwOitA"
+            + "K31L4wCgqh59eFFBrOlRFAbDvaL7emoCIR8EAOLxDKiLQJYQrKZfXdZnifeo"
+            + "dhEP0uuV4O5TG6nrqkhWffzC9cSoFD0BhMl979d8IB2Uft4FNvQc2u8hbJL5"
+            + "7OCGDCUAidlB9jSdu0/J+kfRaTGhYDjBgw7AA42576BBSMNouJg/aOOQENEN"
+            + "Nn4n7NxR3viBzIsL/OIeU8HSkBgaA/41PsvcgZ3kwpdltJ/FVRWhmMmv/q/X"
+            + "qp1YOnF8xPU9bv2ofELrxJfRsbS4GW1etzD+nXs/woW4Vfixs01x+cutR4iF"
+            + "3hw+eU+yLToMPmmo8D2LUvX1SRODJpx5yBBeRIYv6nz9H3sQRDx3kaLASxDV"
+            + "jTxKmrLYnZz5w5qyVpvRyv4JAwKyWlhdblPudWBFXNkW5ydKn0AV2f51wEtj"
+            + "Zy0aLIeutVMSJf1ytLqjFqrnFe6pdJrHO3G00TE8OuFhftWosLGLbEGytDtF"
+            + "cmljIEguIEVjaGlkbmEgKHRlc3Qga2V5IC0gQUVTMjU2KSA8ZXJpY0Bib3Vu"
+            + "Y3ljYXN0bGUub3JnPohZBBMRAgAZBQJAUnSGBAsHAwIDFQIDAxYCAQIeAQIX"
+            + "gAAKCRBYt1NnUiCgeFKaAKCiqtOO+NQES1gJW6XuOGmSkXt8bQCfcuW7SXZH"
+            + "zxK1FfdcG2HEDs3YEVawAgAA");
+
+		private static readonly byte[] aesPublicKey = Base64.Decode(
+              "mQGiBEBSdIYRBADpd7MeIxRk4RsvyMnJNIYe4FiVv6i7I7+LPRvnIjDct0bN"
+            + "1gCV48QFej7g/PsvXRjYSowV3VIvchWX8OERd/5i10cLbcs7X52EP1vwYaLj"
+            + "uRfNUBg8Q51RQsKR+/rBmnVsi68rjU4yTH6wpo6FOO4pz4wFV+tWwGOwOitA"
+            + "K31L4wCgqh59eFFBrOlRFAbDvaL7emoCIR8EAOLxDKiLQJYQrKZfXdZnifeo"
+            + "dhEP0uuV4O5TG6nrqkhWffzC9cSoFD0BhMl979d8IB2Uft4FNvQc2u8hbJL5"
+            + "7OCGDCUAidlB9jSdu0/J+kfRaTGhYDjBgw7AA42576BBSMNouJg/aOOQENEN"
+            + "Nn4n7NxR3viBzIsL/OIeU8HSkBgaA/41PsvcgZ3kwpdltJ/FVRWhmMmv/q/X"
+            + "qp1YOnF8xPU9bv2ofELrxJfRsbS4GW1etzD+nXs/woW4Vfixs01x+cutR4iF"
+            + "3hw+eU+yLToMPmmo8D2LUvX1SRODJpx5yBBeRIYv6nz9H3sQRDx3kaLASxDV"
+            + "jTxKmrLYnZz5w5qyVpvRyrQ7RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSAt"
+            + "IEFFUzI1NikgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IWQQTEQIAGQUCQFJ0"
+            + "hgQLBwMCAxUCAwMWAgECHgECF4AACgkQWLdTZ1IgoHhSmgCfU83BLBF2nCua"
+            + "zk2dXB9zO1l6XS8AnA07U4cq5W0GrKM6/kP9HWtPhgOFsAIAAA==");
+
+		private static readonly byte[] twofishSecretKey = Base64.Decode(
+              "lQHpBEBSdtIRBACf7WfrqTl8F051+EbaljPf/8/ajFpAfMq/7p3Hri8OCsuc"
+            + "fJJIufEEOV1/Lt/wkN67MmSyrU0fUCsRbEckRiB4EJ0zGHVFfAnku2lzdgc8"
+            + "AVounqcHOmqA/gliFDEnhYOx3bOIAOav+yiOqfKVBhWRCpFdOTE+w/XoDM+p"
+            + "p8bH5wCgmP2FuWpzfSut7GVKp51xNEBRNuED/3t2Q+Mq834FVynmLKEmeXB/"
+            + "qtIz5reHEQR8eMogsOoJS3bXs6v3Oblj4in1gLyTVfcID5tku6kLP20xMRM2"
+            + "zx2oRbz7TyOCrs15IpRXyqqJxUWD8ipgJPkPXE7hK8dh4YSTUi4i5a1ug8xG"
+            + "314twlPzrchpWZiutDvZ+ks1rzOtBACHrEFG2frUu+qVkL43tySE0cV2bnuK"
+            + "LVhXbpzF3Qdkfxou2nuzsCbl6m87OWocJX8uYcQGlHLKv8Q2cfxZyieLFg6v"
+            + "06LSFdE9drGBWz7mbrT4OJjxPyvnkffPfLOOqae3PMYIIuscvswuhm4X5aoj"
+            + "KJs01YT3L6f0iIj03hCeV/4KAwLcGrxT3X0qR2CZyZYSVBdjXeNYKXuGBtOf"
+            + "ood26WOtwLw4+l9sHVoiXNv0LomkO58ndJRPGCeZWZEDMVrfkS7rcOlktDxF"
+            + "cmljIEguIEVjaGlkbmEgKHRlc3Qga2V5IC0gdHdvZmlzaCkgPGVyaWNAYm91"
+            + "bmN5Y2FzdGxlLm9yZz6IWQQTEQIAGQUCQFJ20gQLBwMCAxUCAwMWAgECHgEC"
+            + "F4AACgkQaCCMaHh9zR2+RQCghcQwlt4B4YmNxp2b3v6rP3E8M0kAn2Gspi4u"
+            + "A/ynoqnC1O8HNlbjPdlVsAIAAA==");
+
+		private static readonly byte[] twofishPublicKey = Base64.Decode(
+              "mQGiBEBSdtIRBACf7WfrqTl8F051+EbaljPf/8/ajFpAfMq/7p3Hri8OCsuc"
+            + "fJJIufEEOV1/Lt/wkN67MmSyrU0fUCsRbEckRiB4EJ0zGHVFfAnku2lzdgc8"
+            + "AVounqcHOmqA/gliFDEnhYOx3bOIAOav+yiOqfKVBhWRCpFdOTE+w/XoDM+p"
+            + "p8bH5wCgmP2FuWpzfSut7GVKp51xNEBRNuED/3t2Q+Mq834FVynmLKEmeXB/"
+            + "qtIz5reHEQR8eMogsOoJS3bXs6v3Oblj4in1gLyTVfcID5tku6kLP20xMRM2"
+            + "zx2oRbz7TyOCrs15IpRXyqqJxUWD8ipgJPkPXE7hK8dh4YSTUi4i5a1ug8xG"
+            + "314twlPzrchpWZiutDvZ+ks1rzOtBACHrEFG2frUu+qVkL43tySE0cV2bnuK"
+            + "LVhXbpzF3Qdkfxou2nuzsCbl6m87OWocJX8uYcQGlHLKv8Q2cfxZyieLFg6v"
+            + "06LSFdE9drGBWz7mbrT4OJjxPyvnkffPfLOOqae3PMYIIuscvswuhm4X5aoj"
+            + "KJs01YT3L6f0iIj03hCeV7Q8RXJpYyBILiBFY2hpZG5hICh0ZXN0IGtleSAt"
+            + "IHR3b2Zpc2gpIDxlcmljQGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkFAkBS"
+            + "dtIECwcDAgMVAgMDFgIBAh4BAheAAAoJEGggjGh4fc0dvkUAn2QGdNk8Wrrd"
+            + "+DvKECrO5+yoPRx3AJ91DhCMme6uMrQorKSDYxHlgc7iT7ACAAA=");
+
+		private static readonly char[] pass = "hello world".ToCharArray();
+
+		/**
+        * Generated signature test
+        *
+        * @param sKey
+        * @param pgpPrivKey
+        * @return test result
+        */
+        public void GenerateTest(
+            PgpSecretKeyRing sKey,
+            PgpPublicKey     pgpPubKey,
+            PgpPrivateKey    pgpPrivKey)
+        {
+            string data = "hello world!";
+            MemoryStream bOut = new MemoryStream();
+
+            byte[] dataBytes = Encoding.ASCII.GetBytes(data);
+            MemoryStream testIn = new MemoryStream(dataBytes, false);
+
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+
+            PgpSignatureSubpacketGenerator spGen = new PgpSignatureSubpacketGenerator();
+
+            IEnumerator enumerator = sKey.GetSecretKey().PublicKey.GetUserIds().GetEnumerator();
+            enumerator.MoveNext();
+            string primaryUserId = (string) enumerator.Current;
+
+            spGen.SetSignerUserId(true, primaryUserId);
+
+            sGen.SetHashedSubpackets(spGen.Generate());
+
+            PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(
+                CompressionAlgorithmTag.Zip);
+
+            BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));
+
+            sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+
+			DateTime testDateTime = new DateTime(1973, 7, 27);
+			Stream lOut = lGen.Open(
+				new UncloseableStream(bcOut),
+				PgpLiteralData.Binary,
+				"_CONSOLE",
+				dataBytes.Length,
+				testDateTime);
+
+			int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte) ch);
+                sGen.Update((byte)ch);
+            }
+
+            lGen.Close();
+
+            sGen.Generate().Encode(bcOut);
+
+            cGen.Close();
+
+            PgpObjectFactory pgpFact = new PgpObjectFactory(bOut.ToArray());
+            PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+			PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+            PgpOnePassSignature ops = p1[0];
+
+            PgpLiteralData p2 = (PgpLiteralData) pgpFact.NextPgpObject();
+			if (!p2.ModificationTime.Equals(testDateTime))
+			{
+				Fail("Modification time not preserved");
+			}
+
+			Stream dIn = p2.GetInputStream();
+
+            ops.InitVerify(pgpPubKey);
+
+			while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte) ch);
+            }
+
+			PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject();
+
+			if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed generated signature check");
+            }
+        }
+
+		public override void PerformTest()
+        {
+            PgpPublicKey pubKey = null;
+
+			//
+            // Read the public key
+            //
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey);
+
+			pubKey = pgpPub.GetPublicKey();
+
+            //
+            // Read the private key
+            //
+            PgpSecretKeyRing sKey = new PgpSecretKeyRing(testPrivKey);
+            PgpSecretKey secretKey = sKey.GetSecretKey();
+            PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(pass);
+
+            //
+            // test signature message
+            //
+            PgpObjectFactory pgpFact = new PgpObjectFactory(sig1);
+            PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+			pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+            PgpOnePassSignature ops = p1[0];
+
+            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+
+            Stream dIn = p2.GetInputStream();
+
+            ops.InitVerify(pubKey);
+
+			int ch;
+			while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte) ch);
+            }
+
+            PgpSignatureList p3 = (PgpSignatureList) pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed signature check");
+            }
+
+            //
+            // signature generation
+            //
+            GenerateTest(sKey, pubKey, pgpPrivKey);
+
+            //
+            // signature generation - canonical text
+            //
+            const string data = "hello world!";
+            byte[] dataBytes = Encoding.ASCII.GetBytes(data);
+            MemoryStream bOut = new MemoryStream();
+            MemoryStream testIn = new MemoryStream(dataBytes, false);
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+                PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+			sGen.InitSign(PgpSignature.CanonicalTextDocument, pgpPrivKey);
+
+            PgpCompressedDataGenerator  cGen = new PgpCompressedDataGenerator(
+                CompressionAlgorithmTag.Zip);
+
+            BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));
+
+            sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+			DateTime testDateTime = new DateTime(1973, 7, 27);
+			Stream lOut = lGen.Open(
+				new UncloseableStream(bcOut),
+				PgpLiteralData.Text,
+				"_CONSOLE",
+				dataBytes.Length,
+				testDateTime);
+
+			while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte) ch);
+                sGen.Update((byte)ch);
+            }
+
+			lGen.Close();
+
+			sGen.Generate().Encode(bcOut);
+
+            cGen.Close();
+
+            //
+            // verify Generated signature - canconical text
+            //
+            pgpFact = new PgpObjectFactory(bOut.ToArray());
+
+            c1 = (PgpCompressedData) pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            p1 = (PgpOnePassSignatureList) pgpFact.NextPgpObject();
+
+            ops = p1[0];
+
+            p2 = (PgpLiteralData) pgpFact.NextPgpObject();
+			if (!p2.ModificationTime.Equals(testDateTime))
+			{
+				Fail("Modification time not preserved");
+			}
+
+            dIn = p2.GetInputStream();
+
+            ops.InitVerify(pubKey);
+
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            p3 = (PgpSignatureList) pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed generated signature check");
+            }
+
+            //
+            // Read the public key with user attributes
+            //
+            pgpPub = new PgpPublicKeyRing(testPubWithUserAttr);
+
+            pubKey = pgpPub.GetPublicKey();
+
+            int count = 0;
+            foreach (PgpUserAttributeSubpacketVector attributes in pubKey.GetUserAttributes())
+            {
+                int sigCount = 0;
+                foreach (object sigs in pubKey.GetSignaturesForUserAttribute(attributes))
+                {
+					if (sigs == null)
+						Fail("null signature found");
+
+					sigCount++;
+                }
+
+                if (sigCount != 1)
+                {
+                    Fail("Failed user attributes signature check");
+                }
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("Failed user attributes check");
+            }
+
+            byte[]  pgpPubBytes = pgpPub.GetEncoded();
+            pgpPub = new PgpPublicKeyRing(pgpPubBytes);
+            pubKey = pgpPub.GetPublicKey();
+            count = 0;
+
+			foreach (object ua in pubKey.GetUserAttributes())
+            {
+				if (ua == null)
+					Fail("null user attribute found");
+
+				count++;
+            }
+
+			if (count != 1)
+            {
+                Fail("Failed user attributes reread");
+            }
+
+            //
+            // reading test extra data - key with edge condition for DSA key password.
+            //
+            char[] passPhrase = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
+
+			sKey = new PgpSecretKeyRing(testPrivKey2);
+            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(passPhrase);
+
+			//
+            // reading test - aes256 encrypted passphrase.
+            //
+            sKey = new PgpSecretKeyRing(aesSecretKey);
+            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass);
+
+            //
+            // reading test - twofish encrypted passphrase.
+            //
+            sKey = new PgpSecretKeyRing(twofishSecretKey);
+            pgpPrivKey = sKey.GetSecretKey().ExtractPrivateKey(pass);
+
+			//
+            // use of PgpKeyPair
+            //
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(512, 80, new SecureRandom()); // TODO Is the certainty okay?
+            DsaParameters dsaParams = pGen.GenerateParameters();
+            DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);
+			IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+			kpg.Init(kgp);
+
+
+			AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();
+
+            PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa,
+                kp.Public, kp.Private, DateTime.UtcNow);
+
+			PgpPublicKey k1 = pgpKp.PublicKey;
+            PgpPrivateKey k2 = pgpKp.PrivateKey;
+        }
+
+		public override string Name
+        {
+			get { return "PGPDSATest"; }
+        }
+
+		public static void Main(
+			string[] args)
+        {
+			RunTest(new PgpDsaTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPNoPrivateKeyTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPNoPrivateKeyTest.cs
new file mode 100644
index 0000000..edb96b1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPNoPrivateKeyTest.cs
@@ -0,0 +1,169 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PGPNoPrivateKeyTest
+        : SimpleTest
+    {
+        private static string pgpOldPass = "test";
+        private static string pgpNewPass = "newtest";
+
+        private static readonly byte[] pgpPrivateEmpty = Base64.Decode(
+              "lQCVBFGSNGwBBACwABZRIEW/4vDQajcO0FW39yNDcsHBDwPkGT95D7jiVTTRoSs6"
+            + "ACWRAAwGlz4V62U0+nEgasxpifHnu6jati5zxwS16qNvBcxcqZrdZWdvolzCWWsr"
+            + "pFd0juhwesrvvUb5dN/xCJKyLPkp6A+uwv35/cxVSOHFvbW7nnronwinYQARAQAB"
+            + "/gJlAkdOVQG0HlRlc3QgVGVzdGVyc29uIDx0ZXN0QHRlc3QubmV0Poi4BBMBAgAi"
+            + "BQJRkjRsAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDSr6Hh9tuk5NfI"
+            + "A/4iMPF9k2/7KanWksNrBqhKemsyI7hLTxAwv+AA9B0rOO2QoJYe9OjuKn199fNO"
+            + "JPsAgwy7okvDe3QAUz3WA9GlghM5STYvonFJtl7o4kyjcZ4HO2ZI5Bdc5O9i63QA"
+            + "rNv40qVp++A3Mf+13z7cftKufj0vOfw6YeayLVXcV4h95J0B/gRRkjSNAQQA2l3d"
+            + "ZnFFYXYDoNHz1cOX4787CbKdBIfiALFfdbyQ6TzYkCTJTnVCZlQs2aeyrcdTSZUx"
+            + "N4y9bih4nfJ8uRKyQvLm6O0u6bG16kUDDnnwlsGn3uvTXfUwnSPq8pFY2acde6ZG"
+            + "N25vezNK1R6C7kU3+puNHqBIRANfHTsBElaD2V0AEQEAAf4CAwIUI0+QlwBVFdNa"
+            + "S/ppOwSht7Gr19AK4SHe92VWDKnCBPN2W3vhM4NcZSQCV2oiEMI0akLZ26jqCiRl"
+            + "AvTjLSVDho1rUWbaSxFfKlDQNbxCJKlMQeVfbsWXJMeDkn1AhPru3PBLl6Y1jocd"
+            + "vIVM7aQugNQlwEuFWgtZeODxcgBfX2lQeEMIv0AtWTAMt6MVT8AgnFqiqC4+14t0"
+            + "j2CHP2hqCDr5zw9gerAYQ0F03OS34vDm4Y5DmQFjyB05QO2cIN4DZ9gJg8NAQT+P"
+            + "+bwWR3/i9pTq3InNkoi2uT41OnHsYWgKoEQn62BDxjbvO359crUiq9VvS52v2UXh"
+            + "b6Z+fF3PoXXsobS1QQwTPXAeA/mlAflTp+HrkckatY7DgWbON1SSn4Z1XcWPKBSY"
+            + "epS5+90Tj3byZvN7Laj61ZlXVBvU3x7z6MaBZDf4479fklcUnJ13v+P6uGnTI4YE"
+            + "Q5pPjHn1dDqD2Nl8ZW9ufK9pPYkBPQQYAQIACQUCUZI0jQIbAgCoCRDSr6Hh9tuk"
+            + "5J0gBBkBAgAGBQJRkjSNAAoJEPIU7wJ5Ws2K0F0D/jHx4jrZq7SCv69/4hictjgz"
+            + "nNNFSOm20/brHXMBdp6p9mBqt28WU8fgRkxS0mz+1i7VNTv6ZwUXawfTyOVCPR5B"
+            + "QEC+FA+LvdX0UcJBJpa9tT4koz1JBxmppxxLYdS2A5sslPD5If8QHUaOMEX9O1I+"
+            + "So3rEh3+DuhQj88FUuG8uJAD/3Xtpf/5nEpghLOZdQ/7QkLCoRZk7fwjChQNFSJU"
+            + "5xiZbZ/GsSvU1IqAP/NZBmBO0qDm5m7ahXy71O1bMFtaiUaw2Mb7dwqqDvppbjIB"
+            + "OHdIhSnAorRLcnjm8z51QVMzHmgvKt5/e1q1fzsVzza6DWtYr2X/1VsuouSC1uz1"
+            + "nPdgnQH+BFGSNJ4BBAC3KliQlchs0rctsXbhA/GEfiO0s9tAgVsfJL1PWUkC+26M"
+            + "yBbqkVg5RV+J6dyTSeT6cDI8PMu8XFPO6H2WWdovfs7X9K1lxfnNWxQB2L6t2xre"
+            + "XyFqvTsYEFuGvYmbNyUYvA+daHD0xqX8UrC0J6TYg5ie5I685X8gFKVEtGYG/wAR"
+            + "AQAB/gIDAuMt34hcdJPX03uBj9LtjcnrMNLyF7PVJv4wBXEt7T9Kp8cYZ80Sxpd2"
+            + "11LHzjgiPg1kkkImJ9Ie1qbPZjc9tyiGf47m0TIORnKtwNb2YN+sKLpqZ+ienfTs"
+            + "vc0uyuVGW+8PCt409M9R++0q66sxvb3oKBp2zsr3BbGaISs4OVxY2L8uU3t5j9pi"
+            + "qKdV2XTiV9OZJ+2f1au1tMwhNPzjVJ4GH53TxewSkshRJTZtw2ouUJkdA/bizfNO"
+            + "9XYYvV8sW1/ASe1dnOs+ANDGzumzSA00dWPSveURroG+ZtVXVgkakJJtDwdAYutP"
+            + "kSm28cnsl1OmrBKPonB5N3uDjTlq56vji1d2F5ugAXTTD5PptiML1wEB/TqsRJRX"
+            + "uY7DLy+8iukOVOyoVw63UMX27YUz61JJZYcB7U28gNeRyBsnTEbjmvteoFsYnaGg"
+            + "Owgc+1Zx4rQdZEqxZRmfwmiUgHGyI9OpvoVaTIuDIqDd2ZRWiJ8EGAECAAkFAlGS"
+            + "NJ4CGwwACgkQ0q+h4fbbpOScsgQAmMymSfAmltnHQzKr5k2GvlAqIzl9MqKVm9wA"
+            + "0Cx3grwzPaiqmfspPIueQ8Phexiy6dwfPrwNoKnJOEjM6/sOcWEmLiIoYi+/oQjU"
+            + "12zwogOfzT/1hPpG5zs+GBGX4sorCK663PuovwCEoNrWm+7nItfTwdnFavNuj7s4"
+            + "+b3JLdM=");
+
+        private static readonly byte[] pgpPrivateFull = Base64.Decode(
+              "lQH+BFGSNGwBBACwABZRIEW/4vDQajcO0FW39yNDcsHBDwPkGT95D7jiVTTRoSs6"
+            + "ACWRAAwGlz4V62U0+nEgasxpifHnu6jati5zxwS16qNvBcxcqZrdZWdvolzCWWsr"
+            + "pFd0juhwesrvvUb5dN/xCJKyLPkp6A+uwv35/cxVSOHFvbW7nnronwinYQARAQAB"
+            + "/gIDAuqTuDp/Chfq0TKnSxmm2ZpDuiHD+NFVnCyNuJpvCQk0PnVwmGMH4xvsAZB2"
+            + "TOrfh2XHf/n9J4vjxB6p6Zs1kGBgg9hcHoWf+oEf1Tz/PE/c1tUXG2Hz9wlAgstU"
+            + "my2NpDTYUjQs45p+LaM+WFtLNXzBeqELKlMevs8Xb7n+VHwiTuM3KfXETLCoLz0Q"
+            + "3GmmpOuNnvXBdza7RsDwke0r66HzwX4Le8cMH9Pe7kSMakx9S1UR/uIsxsZYZOKb"
+            + "BieGEumxiAnew0Ri5/8wTd5yYC7BWbYvBUgdMQ1gzkzmJcVky8NVfoZKQ0GkdvMo"
+            + "fMThIVXN1U6+aqzAuUMFCPYQ7fEpfoNLhCnzQPv3RE7Wo2vFMjWBod2J4MSLhBuq"
+            + "Ut+FYLqYqU21Qe4PEyPmGnkVu7Wd8FGjBF+IKZg+ycPi++h/twloD/h7LEaq907C"
+            + "4R3rdOzjZnefDfxVWjLLhqKSSuXxtjSSKwMNdbjYVVJ/tB5UZXN0IFRlc3RlcnNv"
+            + "biA8dGVzdEB0ZXN0Lm5ldD6IuAQTAQIAIgUCUZI0bAIbAwYLCQgHAwIGFQgCCQoL"
+            + "BBYCAwECHgECF4AACgkQ0q+h4fbbpOTXyAP+IjDxfZNv+ymp1pLDawaoSnprMiO4"
+            + "S08QML/gAPQdKzjtkKCWHvTo7ip9ffXzTiT7AIMMu6JLw3t0AFM91gPRpYITOUk2"
+            + "L6JxSbZe6OJMo3GeBztmSOQXXOTvYut0AKzb+NKlafvgNzH/td8+3H7Srn49Lzn8"
+            + "OmHmsi1V3FeIfeSdAf4EUZI0jQEEANpd3WZxRWF2A6DR89XDl+O/OwmynQSH4gCx"
+            + "X3W8kOk82JAkyU51QmZULNmnsq3HU0mVMTeMvW4oeJ3yfLkSskLy5ujtLumxtepF"
+            + "Aw558JbBp97r0131MJ0j6vKRWNmnHXumRjdub3szStUegu5FN/qbjR6gSEQDXx07"
+            + "ARJWg9ldABEBAAH+AgMCFCNPkJcAVRXTWkv6aTsEobexq9fQCuEh3vdlVgypwgTz"
+            + "dlt74TODXGUkAldqIhDCNGpC2duo6gokZQL04y0lQ4aNa1Fm2ksRXypQ0DW8QiSp"
+            + "TEHlX27FlyTHg5J9QIT67tzwS5emNY6HHbyFTO2kLoDUJcBLhVoLWXjg8XIAX19p"
+            + "UHhDCL9ALVkwDLejFU/AIJxaoqguPteLdI9ghz9oagg6+c8PYHqwGENBdNzkt+Lw"
+            + "5uGOQ5kBY8gdOUDtnCDeA2fYCYPDQEE/j/m8Fkd/4vaU6tyJzZKItrk+NTpx7GFo"
+            + "CqBEJ+tgQ8Y27zt+fXK1IqvVb0udr9lF4W+mfnxdz6F17KG0tUEMEz1wHgP5pQH5"
+            + "U6fh65HJGrWOw4FmzjdUkp+GdV3FjygUmHqUufvdE4928mbzey2o+tWZV1Qb1N8e"
+            + "8+jGgWQ3+OO/X5JXFJydd7/j+rhp0yOGBEOaT4x59XQ6g9jZfGVvbnyvaT2JAT0E"
+            + "GAECAAkFAlGSNI0CGwIAqAkQ0q+h4fbbpOSdIAQZAQIABgUCUZI0jQAKCRDyFO8C"
+            + "eVrNitBdA/4x8eI62au0gr+vf+IYnLY4M5zTRUjpttP26x1zAXaeqfZgardvFlPH"
+            + "4EZMUtJs/tYu1TU7+mcFF2sH08jlQj0eQUBAvhQPi73V9FHCQSaWvbU+JKM9SQcZ"
+            + "qaccS2HUtgObLJTw+SH/EB1GjjBF/TtSPkqN6xId/g7oUI/PBVLhvLiQA/917aX/"
+            + "+ZxKYISzmXUP+0JCwqEWZO38IwoUDRUiVOcYmW2fxrEr1NSKgD/zWQZgTtKg5uZu"
+            + "2oV8u9TtWzBbWolGsNjG+3cKqg76aW4yATh3SIUpwKK0S3J45vM+dUFTMx5oLyre"
+            + "f3tatX87Fc82ug1rWK9l/9VbLqLkgtbs9Zz3YJ0B/gRRkjSeAQQAtypYkJXIbNK3"
+            + "LbF24QPxhH4jtLPbQIFbHyS9T1lJAvtujMgW6pFYOUVfienck0nk+nAyPDzLvFxT"
+            + "zuh9llnaL37O1/StZcX5zVsUAdi+rdsa3l8har07GBBbhr2JmzclGLwPnWhw9Mal"
+            + "/FKwtCek2IOYnuSOvOV/IBSlRLRmBv8AEQEAAf4CAwLjLd+IXHST19N7gY/S7Y3J"
+            + "6zDS8hez1Sb+MAVxLe0/SqfHGGfNEsaXdtdSx844Ij4NZJJCJifSHtamz2Y3Pbco"
+            + "hn+O5tEyDkZyrcDW9mDfrCi6amfonp307L3NLsrlRlvvDwreNPTPUfvtKuurMb29"
+            + "6Cgads7K9wWxmiErODlcWNi/LlN7eY/aYqinVdl04lfTmSftn9WrtbTMITT841Se"
+            + "Bh+d08XsEpLIUSU2bcNqLlCZHQP24s3zTvV2GL1fLFtfwEntXZzrPgDQxs7ps0gN"
+            + "NHVj0r3lEa6BvmbVV1YJGpCSbQ8HQGLrT5EptvHJ7JdTpqwSj6JweTd7g405auer"
+            + "44tXdheboAF00w+T6bYjC9cBAf06rESUV7mOwy8vvIrpDlTsqFcOt1DF9u2FM+tS"
+            + "SWWHAe1NvIDXkcgbJ0xG45r7XqBbGJ2hoDsIHPtWceK0HWRKsWUZn8JolIBxsiPT"
+            + "qb6FWkyLgyKg3dmUVoifBBgBAgAJBQJRkjSeAhsMAAoJENKvoeH226TknLIEAJjM"
+            + "pknwJpbZx0Myq+ZNhr5QKiM5fTKilZvcANAsd4K8Mz2oqpn7KTyLnkPD4XsYsunc"
+            + "Hz68DaCpyThIzOv7DnFhJi4iKGIvv6EI1Nds8KIDn80/9YT6Ruc7PhgRl+LKKwiu"
+            + "utz7qL8AhKDa1pvu5yLX08HZxWrzbo+7OPm9yS3T");
+
+        public override void PerformTest()
+        {
+            PgpSecretKeyRing pgpSecRing = new PgpSecretKeyRing(pgpPrivateFull);
+            PgpSecretKey pgpSecKey = pgpSecRing.GetSecretKey();
+            bool isFullEmpty = pgpSecKey.IsPrivateKeyEmpty;
+
+            pgpSecRing = new PgpSecretKeyRing(pgpPrivateEmpty);
+            pgpSecKey = pgpSecRing.GetSecretKey();
+            bool isEmptyEmpty = pgpSecKey.IsPrivateKeyEmpty;
+
+            //
+            // Check isPrivateKeyEmpty() is public
+            //
+
+            if (isFullEmpty || !isEmptyEmpty)
+            {
+                Fail("Empty private keys not detected correctly.");
+            }
+
+            //
+            // Check copyWithNewPassword doesn't throw an exception for secret
+            // keys without private keys (PGPException: unknown S2K type: 101).
+            //
+
+            SecureRandom rand = new SecureRandom();
+
+            try
+            {
+                PgpSecretKey pgpChangedKey = PgpSecretKey.CopyWithNewPassword(pgpSecKey,
+                    pgpOldPass.ToCharArray(), pgpNewPass.ToCharArray(), pgpSecKey.KeyEncryptionAlgorithm, rand);
+            }
+            catch (PgpException e)
+            {
+                if (!e.Message.Equals("no private key in this SecretKey - public key present only."))
+                {
+                    Fail("wrong exception.");
+                }
+            }
+        }
+
+        public override string Name
+        {
+            get { return "PGPNoPrivateKeyTest"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new PGPNoPrivateKeyTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPBETest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPBETest.cs
new file mode 100644
index 0000000..621cef6
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPBETest.cs
@@ -0,0 +1,384 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpPbeTest
+		: SimpleTest
+    {
+		private static readonly DateTime TestDateTime = new DateTime(2003, 8, 29, 23, 35, 11, 0);
+
+		private static readonly byte[] enc1 = Base64.Decode(
+            "jA0EAwMC5M5wWBP2HBZgySvUwWFAmMRLn7dWiZN6AkQMvpE3b6qwN3SSun7zInw2"
+            + "hxxdgFzVGfbjuB8w");
+//        private static readonly byte[] enc1crc = Base64.Decode("H66L");
+		private static readonly char[] pass = "hello world".ToCharArray();
+
+		/**
+		 * Message with both PBE and symmetric
+		 */
+		private static readonly byte[] testPBEAsym = Base64.Decode(
+			"hQIOA/ZlQEFWB5vuEAf/covEUaBve7NlWWdiO5NZubdtTHGElEXzG9hyBycp9At8" +
+			"nZGi27xOZtEGFQo7pfz4JySRc3O0s6w7PpjJSonFJyNSxuze2LuqRwFWBYYcbS8/" +
+			"7YcjB6PqutrT939OWsozfNqivI9/QyZCjBvFU89pp7dtUngiZ6MVv81ds2I+vcvk" +
+			"GlIFcxcE1XoCIB3EvbqWNaoOotgEPT60unnB2BeDV1KD3lDRouMIYHfZ3SzBwOOI" +
+			"6aK39sWnY5sAK7JjFvnDAMBdueOiI0Fy+gxbFD/zFDt4cWAVSAGTC4w371iqppmT" +
+			"25TM7zAtCgpiq5IsELPlUZZnXKmnYQ7OCeysF0eeVwf+OFB9fyvCEv/zVQocJCg8" +
+			"fWxfCBlIVFNeNQpeGygn/ZmRaILvB7IXDWP0oOw7/F2Ym66IdYYIp2HeEZv+jFwa" +
+			"l41w5W4BH/gtbwGjFQ6CvF/m+lfUv6ZZdzsMIeEOwhP5g7rXBxrbcnGBaU+PXbho" +
+			"gjDqaYzAWGlrmAd6aPSj51AGeYXkb2T1T/yoJ++M3GvhH4C4hvitamDkksh/qRnM" +
+			"M/s8Nku6z1+RXO3M6p5QC1nlAVqieU8esT43945eSoC77K8WyujDNbysDyUCUTzt" +
+			"p/aoQwe/HgkeOTJNelKR9y2W3xinZLFzep0SqpNI/e468yB/2/LGsykIyQa7JX6r" +
+			"BYwuBAIDAkOKfv5rK8v0YDfnN+eFqwhTcrfBj5rDH7hER6nW3lNWcMataUiHEaMg" +
+			"o6Q0OO1vptIGxW8jClTD4N1sCNwNu9vKny8dKYDDHbCjE06DNTv7XYVW3+JqTL5E" +
+			"BnidvGgOmA==");
+
+		/**
+        * decrypt the passed in message stream
+        */
+        private byte[] DecryptMessage(
+            byte[] message)
+        {
+            PgpObjectFactory		pgpF = new PgpObjectFactory(message);
+            PgpEncryptedDataList	enc = (PgpEncryptedDataList) pgpF.NextPgpObject();
+            PgpPbeEncryptedData		pbe = (PgpPbeEncryptedData) enc[0];
+            Stream					clear = pbe.GetDataStream(pass);
+
+			PgpObjectFactory		pgpFact = new PgpObjectFactory(clear);
+            PgpCompressedData		cData = (PgpCompressedData) pgpFact.NextPgpObject();
+            pgpFact = new PgpObjectFactory(cData.GetDataStream());
+
+			PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject();
+
+            if (!ld.FileName.Equals("test.txt")
+                && !ld.FileName.Equals("_CONSOLE"))
+            {
+                Fail("wrong filename in packet");
+            }
+
+			if (!ld.ModificationTime.Equals(TestDateTime))
+			{
+				Fail("wrong modification time in packet: " + ld.ModificationTime + " vs " + TestDateTime);
+			}
+
+			Stream unc = ld.GetInputStream();
+			byte[] bytes = Streams.ReadAll(unc);
+
+			if (pbe.IsIntegrityProtected() && !pbe.Verify())
+			{
+				Fail("integrity check failed");
+			}
+
+			return bytes;
+        }
+
+		private byte[] DecryptMessageBuffered(
+			byte[] message)
+		{
+			PgpObjectFactory		pgpF = new PgpObjectFactory(message);
+			PgpEncryptedDataList	enc = (PgpEncryptedDataList) pgpF.NextPgpObject();
+			PgpPbeEncryptedData		pbe = (PgpPbeEncryptedData) enc[0];
+
+			Stream clear = pbe.GetDataStream(pass);
+
+			PgpObjectFactory	pgpFact = new PgpObjectFactory(clear);
+			PgpCompressedData	cData = (PgpCompressedData) pgpFact.NextPgpObject();
+
+			pgpFact = new PgpObjectFactory(cData.GetDataStream());
+
+			PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject();
+
+			MemoryStream bOut = new MemoryStream();
+			if (!ld.FileName.Equals("test.txt")
+				&& !ld.FileName.Equals("_CONSOLE"))
+			{
+				Fail("wrong filename in packet");
+			}
+			if (!ld.ModificationTime.Equals(TestDateTime))
+			{
+				Fail("wrong modification time in packet: " + ld.ModificationTime.Ticks + " " + TestDateTime.Ticks);
+			}
+
+			Stream unc = ld.GetInputStream();
+			byte[] buf = new byte[1024];
+
+			int len;
+			while ((len = unc.Read(buf, 0, buf.Length)) > 0)
+			{
+				bOut.Write(buf, 0, len);
+			}
+
+			if (pbe.IsIntegrityProtected() && !pbe.Verify())
+			{
+				Fail("integrity check failed");
+			}
+
+			return bOut.ToArray();
+		}
+
+		public override void PerformTest()
+        {
+            byte[] data = DecryptMessage(enc1);
+            if (data[0] != 'h' || data[1] != 'e' || data[2] != 'l')
+            {
+                Fail("wrong plain text in packet");
+            }
+
+			//
+            // create a PBE encrypted message and read it back.
+            //
+			byte[] text = Encoding.ASCII.GetBytes("hello world!\n");
+
+			//
+            // encryption step - convert to literal data, compress, encode.
+            //
+            MemoryStream bOut = new UncloseableMemoryStream();
+
+            PgpCompressedDataGenerator comData = new PgpCompressedDataGenerator(
+                CompressionAlgorithmTag.Zip);
+
+            PgpLiteralDataGenerator lData = new PgpLiteralDataGenerator();
+			Stream comOut = comData.Open(new UncloseableStream(bOut));
+            Stream ldOut = lData.Open(
+				new UncloseableStream(comOut),
+                PgpLiteralData.Binary,
+                PgpLiteralData.Console,
+                text.Length,
+                TestDateTime);
+
+			ldOut.Write(text, 0, text.Length);
+			ldOut.Close();
+
+			comOut.Close();
+
+			//
+            // encrypt - with stream close
+            //
+            MemoryStream cbOut = new UncloseableMemoryStream();
+            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(
+				SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
+
+            cPk.AddMethod(pass);
+
+			byte[] bOutData = bOut.ToArray();
+			Stream cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length);
+            cOut.Write(bOutData, 0, bOutData.Length);
+            cOut.Close();
+
+			data = DecryptMessage(cbOut.ToArray());
+            if (!Arrays.AreEqual(data, text))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+
+			//
+			// encrypt - with generator close
+			//
+			cbOut = new UncloseableMemoryStream();
+			cPk = new PgpEncryptedDataGenerator(
+				SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
+
+			cPk.AddMethod(pass);
+
+			bOutData = bOut.ToArray();
+			cOut = cPk.Open(new UncloseableStream(cbOut), bOutData.Length);
+			cOut.Write(bOutData, 0, bOutData.Length);
+
+			cPk.Close();
+
+			data = DecryptMessage(cbOut.ToArray());
+
+			if (!AreEqual(data, text))
+			{
+				Fail("wrong plain text in generated packet");
+			}
+
+			//
+            // encrypt - partial packet style.
+            //
+            SecureRandom rand = new SecureRandom();
+            byte[] test = new byte[1233];
+
+            rand.NextBytes(test);
+
+			bOut = new UncloseableMemoryStream();
+
+			comData = new PgpCompressedDataGenerator(
+				CompressionAlgorithmTag.Zip);
+			comOut = comData.Open(new UncloseableStream(bOut));
+
+			lData = new PgpLiteralDataGenerator();
+            ldOut = lData.Open(
+				new UncloseableStream(comOut),
+                PgpLiteralData.Binary,
+                PgpLiteralData.Console,
+                TestDateTime,
+                new byte[16]);
+
+            ldOut.Write(test, 0, test.Length);
+            lData.Close();
+
+			comData.Close();
+            cbOut = new UncloseableMemoryStream();
+            cPk = new PgpEncryptedDataGenerator(
+				SymmetricKeyAlgorithmTag.Cast5, rand);
+
+            cPk.AddMethod(pass);
+
+			cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
+            {
+                byte[] tmp = bOut.ToArray();
+                cOut.Write(tmp, 0, tmp.Length);
+            }
+
+			cPk.Close();
+
+			data = DecryptMessage(cbOut.ToArray());
+            if (!Arrays.AreEqual(data, test))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+
+            //
+            // with integrity packet
+            //
+            cbOut = new UncloseableMemoryStream();
+            cPk = new PgpEncryptedDataGenerator(
+				SymmetricKeyAlgorithmTag.Cast5, true, rand);
+
+            cPk.AddMethod(pass);
+
+            cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
+            bOutData = bOut.ToArray();
+            cOut.Write(bOutData, 0, bOutData.Length);
+            cPk.Close();
+
+			data = DecryptMessage(cbOut.ToArray());
+            if (!Arrays.AreEqual(data, test))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+
+			//
+			// decrypt with buffering
+			//
+			data = DecryptMessageBuffered(cbOut.ToArray());
+			if (!AreEqual(data, test))
+			{
+				Fail("wrong plain text in buffer generated packet");
+			}
+
+			//
+			// sample message
+			//
+			PgpObjectFactory pgpFact = new PgpObjectFactory(testPBEAsym);
+
+			PgpEncryptedDataList enc = (PgpEncryptedDataList)pgpFact.NextPgpObject();
+
+			PgpPbeEncryptedData pbe = (PgpPbeEncryptedData) enc[1];
+
+			Stream clear = pbe.GetDataStream("password".ToCharArray());
+
+			pgpFact = new PgpObjectFactory(clear);
+
+			PgpLiteralData ld = (PgpLiteralData) pgpFact.NextPgpObject();
+
+			Stream unc = ld.GetInputStream();
+			byte[] bytes = Streams.ReadAll(unc);
+
+			if (!AreEqual(bytes, Hex.Decode("5361742031302e30322e30370d0a")))
+			{
+				Fail("data mismatch on combined PBE");
+			}
+
+			//
+			// with integrity packet - one byte message
+			//
+			byte[] msg = new byte[1];
+			bOut = new MemoryStream();
+
+			comData = new PgpCompressedDataGenerator(
+				CompressionAlgorithmTag.Zip);
+
+			lData = new PgpLiteralDataGenerator();
+			comOut = comData.Open(new UncloseableStream(bOut));
+			ldOut = lData.Open(
+				new UncloseableStream(comOut),
+				PgpLiteralData.Binary,
+				PgpLiteralData.Console,
+				msg.Length,
+				TestDateTime);
+
+			ldOut.Write(msg, 0, msg.Length);
+
+			ldOut.Close();
+
+			comOut.Close();
+        
+			cbOut = new MemoryStream();
+			cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, true, rand);
+
+			cPk.AddMethod(pass);
+
+			cOut = cPk.Open(new UncloseableStream(cbOut), new byte[16]);
+
+			data = bOut.ToArray();
+			cOut.Write(data, 0, data.Length);
+
+			cOut.Close();
+
+			data = DecryptMessage(cbOut.ToArray());
+			if (!AreEqual(data, msg))
+			{
+				Fail("wrong plain text in generated packet");
+			}
+
+			//
+			// decrypt with buffering
+			//
+			data = DecryptMessageBuffered(cbOut.ToArray());
+			if (!AreEqual(data, msg))
+			{
+				Fail("wrong plain text in buffer generated packet");
+			}
+		}
+
+		private class UncloseableMemoryStream
+			: MemoryStream
+		{
+			public override void Close()
+			{
+				throw new Exception("Close() called on underlying stream");
+			}
+		}
+
+		public override string Name
+        {
+			get { return "PGPPBETest"; }
+        }
+
+		public static void Main(
+			string[] args)
+        {
+			RunTest(new PgpPbeTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPacketTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPacketTest.cs
new file mode 100644
index 0000000..b82f852
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPPacketTest.cs
@@ -0,0 +1,80 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpPacketTest
+        : SimpleTest
+    {
+        private static int MAX = 32000;
+
+        private void ReadBackTest(
+            PgpLiteralDataGenerator generator)
+        {
+            Random rand = new Random();
+            byte[] buf = new byte[MAX];
+
+            rand.NextBytes(buf);
+
+            for (int i = 1; i != MAX; i++)
+            {
+                MemoryStream bOut = new MemoryStream();
+
+                Stream outputStream = generator.Open(
+					new UncloseableStream(bOut),
+					PgpLiteralData.Binary,
+					PgpLiteralData.Console,
+					i,
+					DateTime.UtcNow);
+
+				outputStream.Write(buf, 0, i);
+
+                generator.Close();
+
+                PgpObjectFactory fact = new PgpObjectFactory(bOut.ToArray());
+
+                PgpLiteralData data = (PgpLiteralData)fact.NextPgpObject();
+
+                Stream inputStream = data.GetInputStream();
+
+                for (int count = 0; count != i; count++)
+                {
+                    if (inputStream.ReadByte() != (buf[count] & 0xff))
+                    {
+                        Fail("failed readback test - length = " + i);
+                    }
+                }
+            }
+        }
+
+        public override void PerformTest()
+        {
+            ReadBackTest(new PgpLiteralDataGenerator(true));
+			ReadBackTest(new PgpLiteralDataGenerator(false));
+        }
+
+		public override string Name
+        {
+			get { return "PGPPacketTest"; }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+			RunTest(new PgpPacketTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPRSATest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPRSATest.cs
new file mode 100644
index 0000000..c14f365
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPRSATest.cs
@@ -0,0 +1,1233 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Bcpg.Attr;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpRsaTest
+        : SimpleTest
+    {
+        private static readonly byte[] testPubKey = Base64.Decode(
+              "mIsEPz2nJAEEAOTVqWMvqYE693qTgzKv/TJpIj3hI8LlYPC6m1dk0z3bDLwVVk9F"
+            + "FAB+CWS8RdFOWt/FG3tEv2nzcoNdRvjv9WALyIGNawtae4Ml6oAT06/511yUzXHO"
+            + "k+9xK3wkXN5jdzUhf4cA2oGpLSV/pZlocsIDL+jCUQtumUPwFodmSHhzAAYptC9F"
+            + "cmljIEVjaGlkbmEgKHRlc3Qga2V5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPoi4"
+            + "BBMBAgAiBQI/PackAhsDBQkAg9YABAsHAwIDFQIDAxYCAQIeAQIXgAAKCRA1WGFG"
+            + "/fPzc8WMA/9BbjuB8E48QAlxoiVf9U8SfNelrz/ONJA/bMvWr/JnOGA9PPmFD5Uc"
+            + "+kV/q+i94dEMjsC5CQ1moUHWSP2xlQhbOzBP2+oPXw3z2fBs9XJgnTH6QWMAAvLs"
+            + "3ug9po0loNHLobT/D/XdXvcrb3wvwvPT2FptZqrtonH/OdzT9JdfrA==");
+
+        private static readonly byte[] testPrivKey = Base64.Decode(
+              "lQH8BD89pyQBBADk1aljL6mBOvd6k4Myr/0yaSI94SPC5WDwuptXZNM92wy8FVZP"
+            + "RRQAfglkvEXRTlrfxRt7RL9p83KDXUb47/VgC8iBjWsLWnuDJeqAE9Ov+ddclM1x"
+            + "zpPvcSt8JFzeY3c1IX+HANqBqS0lf6WZaHLCAy/owlELbplD8BaHZkh4cwAGKf4D"
+            + "AwKbLeIOVYTEdWD5v/YgW8ERs0pDsSIfBTvsJp2qA798KeFuED6jGsHUzdi1M990"
+            + "6PRtplQgnoYmYQrzEc6DXAiAtBR4Kuxi4XHx0ZR2wpVlVxm2Ypgz7pbBNWcWqzvw"
+            + "33inl7tR4IDsRdJOY8cFlN+1tSCf16sDidtKXUVjRjZNYJytH18VfSPlGXMeYgtw"
+            + "3cSGNTERwKaq5E/SozT2MKTiORO0g0Mtyz+9MEB6XVXFavMun/mXURqbZN/k9BFb"
+            + "z+TadpkihrLD1xw3Hp+tpe4CwPQ2GdWKI9KNo5gEnbkJgLrSMGgWalPhknlNHRyY"
+            + "bSq6lbIMJEE3LoOwvYWwweR1+GrV9farJESdunl1mDr5/d6rKru+FFDwZM3na1IF"
+            + "4Ei4FpqhivZ4zG6pN5XqLy+AK85EiW4XH0yAKX1O4YlbmDU4BjxhiwTdwuVMCjLO"
+            + "5++jkz5BBQWdFX8CCMA4FJl36G70IbGzuFfOj07ly7QvRXJpYyBFY2hpZG5hICh0"
+            + "ZXN0IGtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IuAQTAQIAIgUCPz2nJAIb"
+            + "AwUJAIPWAAQLBwMCAxUCAwMWAgECHgECF4AACgkQNVhhRv3z83PFjAP/QW47gfBO"
+            + "PEAJcaIlX/VPEnzXpa8/zjSQP2zL1q/yZzhgPTz5hQ+VHPpFf6voveHRDI7AuQkN"
+            + "ZqFB1kj9sZUIWzswT9vqD18N89nwbPVyYJ0x+kFjAALy7N7oPaaNJaDRy6G0/w/1"
+            + "3V73K298L8Lz09habWaq7aJx/znc0/SXX6w=");
+
+        private static readonly byte[] testPubKeyV3 = Base64.Decode(
+              "mQCNAz+zvlEAAAEEAMS22jgXbOZ/D3xWgM2kauSdzrwlU7Ms5hDW05ObqQyO"
+            + "FfQoKKMhfupyoa7J3x04VVBKu6Eomvr1es+VImH0esoeWFFahNOYq/I+jRRB"
+            + "woOhAGZ5UB2/hRd7rFmxqp6sCXi8wmLO2tAorlTzAiNNvl7xF4cQZpc0z56F"
+            + "wdi2fBUJAAURtApGSVhDSVRZX1FBiQCVAwUQP7O+UZ6Fwdi2fBUJAQFMwwQA"
+            + "qRnFsdg4xQnB8Y5d4cOpXkIn9AZgYS3cxtuSJB84vG2CgC39nfv4c+nlLkWP"
+            + "4puG+mZuJNgVoE84cuAF4I//1anKjlU7q1M6rFQnt5S4uxPyG3dFXmgyU1b4"
+            + "PBOnA0tIxjPzlIhJAMsPCGGA5+5M2JP0ad6RnzqzE3EENMX+GqY=");
+
+        private static readonly byte[] testPrivKeyV3 = Base64.Decode(
+              "lQHfAz+zvlEAAAEEAMS22jgXbOZ/D3xWgM2kauSdzrwlU7Ms5hDW05ObqQyO"
+            + "FfQoKKMhfupyoa7J3x04VVBKu6Eomvr1es+VImH0esoeWFFahNOYq/I+jRRB"
+            + "woOhAGZ5UB2/hRd7rFmxqp6sCXi8wmLO2tAorlTzAiNNvl7xF4cQZpc0z56F"
+            + "wdi2fBUJAAURAXWwRBZQHNikA/f0ScLLjrXi4s0hgQecg+dkpDow94eu5+AR"
+            + "0DzZnfurpgfUJCNiDi5W/5c3Zj/xyrfMAgkbCgJ1m6FZqAQh7Mq73l7Kfu4/"
+            + "XIkyDF3tDgRuZNezB+JuElX10tV03xumHepp6M6CfhXqNJ15F33F99TA5hXY"
+            + "CPYD7SiSOpIhQkCOAgDAA63imxbpuKE2W7Y4I1BUHB7WQi8ZdkZd04njNTv+"
+            + "rFUuOPapQVfbWG0Vq8ld3YmJB4QWsa2mmqn+qToXbwufAgBpXkjvqK5yPiHF"
+            + "Px2QbFc1VqoCJB6PO5JRIqEiUZBFGdDlLxt3VSyqz7IZ/zEnxZq+tPCGGGSm"
+            + "/sAGiMvENcHVAfy0kTXU42TxEAYJyyNyqjXOobDJpEV1mKhFskRXt7tbMfOS"
+            + "Yf91oX8f6xw6O2Nal+hU8dS0Bmfmk5/enHmvRLHQocO0CkZJWENJVFlfUUE=");
+
+        private static readonly byte[] sig1 = Base64.Decode(
+              "owGbwMvMwMRoGpHo9vfz52LGNTJJnBmpOTn5eiUVJfb23JvAHIXy/KKcFEWuToap"
+            + "zKwMIGG4Bqav0SwMy3yParsEKi2LMGI9xhh65sBxb05n5++ZLcWNJ/eLFKdWbm95"
+            + "tHbDV7GMwj/tUctUpFUXWPYFCLdNsDiVNuXbQvZtdXV/5xzY+9w1nCnijH9JoNiJ"
+            + "22n2jo0zo30/TZLo+jDl2vTzIvPeLEsPM3ZUE/1Ytqs4SG2TxIQbH7xf3uzcYXq2"
+            + "5Fw9AA==");
+
+//		private static readonly byte[] sig1crc = Base64.Decode("+3i0");
+
+        private static readonly byte[] subKey = Base64.Decode(
+              "lQH8BD89pyQBBADk1aljL6mBOvd6k4Myr/0yaSI94SPC5WDwuptXZNM92wy8FVZP"
+            + "RRQAfglkvEXRTlrfxRt7RL9p83KDXUb47/VgC8iBjWsLWnuDJeqAE9Ov+ddclM1x"
+            + "zpPvcSt8JFzeY3c1IX+HANqBqS0lf6WZaHLCAy/owlELbplD8BaHZkh4cwAGKf4D"
+            + "AwKt6ZC7iqsQHGDNn2ZAuhS+ZwiFC+BToW9Vq6rwggWjgM/SThv55rfDk7keiXUT"
+            + "MyUcZVeYBe4Jttb4fAAm83hNztFu6Jvm9ITcm7YvnasBtVQjppaB+oYZgsTtwK99"
+            + "LGC3mdexnriCLxPN6tDFkGhzdOcYZfK6py4Ska8Dmq9nOZU9Qtv7Pm3qa5tuBvYw"
+            + "myTxeaJYifZTu/sky3Gj+REb8WonbgAJX/sLNBPUt+vYko+lxU8uqZpVEMU//hGG"
+            + "Rns2gIHdbSbIe1vGgIRUEd7Z0b7jfVQLUwqHDyfh5DGvAUhvtJogjUyFIXZzpU+E"
+            + "9ES9t7LZKdwNZSIdNUjM2eaf4g8BpuQobBVkj/GUcotKyeBjwvKxHlRefL4CCw28"
+            + "DO3SnLRKxd7uBSqeOGUKxqasgdekM/xIFOrJ85k7p89n6ncLQLHCPGVkzmVeRZro"
+            + "/T7zE91J57qBGZOUAP1vllcYLty1cs9PCc5oWnj3XbQvRXJpYyBFY2hpZG5hICh0"
+            + "ZXN0IGtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IuAQTAQIAIgUCPz2nJAIb"
+            + "AwUJAIPWAAQLBwMCAxUCAwMWAgECHgECF4AACgkQNVhhRv3z83PFjAP/QW47gfBO"
+            + "PEAJcaIlX/VPEnzXpa8/zjSQP2zL1q/yZzhgPTz5hQ+VHPpFf6voveHRDI7AuQkN"
+            + "ZqFB1kj9sZUIWzswT9vqD18N89nwbPVyYJ0x+kFjAALy7N7oPaaNJaDRy6G0/w/1"
+            + "3V73K298L8Lz09habWaq7aJx/znc0/SXX6y0JEVyaWMgRWNoaWRuYSA8ZXJpY0Bi"
+            + "b3VuY3ljYXN0bGUub3JnPoi4BBMBAgAiBQI/RxQNAhsDBQkAg9YABAsHAwIDFQID"
+            + "AxYCAQIeAQIXgAAKCRA1WGFG/fPzc3O6A/49tXFCiiP8vg77OXvnmbnzPBA1G6jC"
+            + "RZNP1yIXusOjpHqyLN5K9hw6lq/o4pNiCuiq32osqGRX3lv/nDduJU1kn2Ow+I2V"
+            + "ci+ojMXdCGdEqPwZfv47jHLwRrIUJ22OOoWsORtgvSeRUd4Izg8jruaFM7ufr5hr"
+            + "jEl1cuLW1Hr8Lp0B/AQ/RxxQAQQA0J2BIdqb8JtDGKjvYxrju0urJVVzyI1CnCjA"
+            + "p7CtLoHQJUQU7PajnV4Jd12ukfcoK7MRraYydQEjxh2MqPpuQgJS3dgQVrxOParD"
+            + "QYBFrZNd2tZxOjYakhErvUmRo6yWFaxChwqMgl8XWugBNg1Dva+/YcoGQ+ly+Jg4"
+            + "RWZoH88ABin+AwMCldD/2v8TyT1ghK70IuFs4MZBhdm6VgyGR8DQ/Ago6IAjA4BY"
+            + "Sol3lJb7+IIGsZaXwEuMRUvn6dWfa3r2I0p1t75vZb1Ng1YK32RZ5DNzl4Xb3L8V"
+            + "D+1Fiz9mHO8wiplAwDudB+RmQMlth3DNi/UsjeCTdEJAT+TTC7D40DiHDb1bR86Y"
+            + "2O5Y7MQ3SZs3/x0D/Ob6PStjfQ1kiqbruAMROKoavG0zVgxvspkoKN7h7BapnwJM"
+            + "6yf4qN/aByhAx9sFvADxu6z3SVcxiFw3IgAmabyWYb85LP8AsTYAG/HBoC6yob47"
+            + "Mt+GEDeyPifzzGXBWYIH4heZbSQivvA0eRwY5VZsMsBkbY5VR0FLVWgplbuO21bS"
+            + "rPS1T0crC+Zfj7FQBAkTfsg8RZQ8MPaHng01+gnFd243DDFvTAHygvm6a2X2fiRw"
+            + "5epAST4wWfY/BZNOxmfSKH6QS0oQMRscw79He6vGTB7vunLrKQYD4veInwQYAQIA"
+            + "CQUCP0ccUAIbDAAKCRA1WGFG/fPzczmFA/wMg5HhN5NkqmjnHUFfeXNXdHzmekyw"
+            + "38RnuCMKmfc43AiDs+FtJ62gpQ6PEsZF4o9S5fxcjVk3VSg00XMDtQ/0BsKBc5Gx"
+            + "hJTq7G+/SoeM433WG19uoS0+5Lf/31wNoTnpv6npOaYpcTQ7L9LCnzwAF4H0hJPE"
+            + "6bhmW2CMcsE/IZUB4QQ/Rwc1EQQAs5MUQlRiYOfi3fQ1OF6Z3eCwioDKu2DmOxot"
+            + "BICvdoG2muvs0KEBas9bbd0FJqc92FZJv8yxEgQbQtQAiFxoIFHRTFK+SPO/tQm+"
+            + "r83nwLRrfDeVVdRfzF79YCc+Abuh8sS/53H3u9Y7DYWr9IuMgI39nrVhY+d8yukf"
+            + "jo4OR+sAoKS/f7V1Xxj/Eqhb8qzf+N+zJRUlBACDd1eo/zFJZcq2YJa7a9vkViME"
+            + "axvwApqxeoU7oDpeHEMWg2DXJ7V24ZU5SbPTMY0x98cc8pcoqwsqux8xicWc0reh"
+            + "U3odQxWM4Se0LmEdca0nQOmNJlL9IsQ+QOJzx47qUOUAqhxnkXxQ/6B8w+M6gZya"
+            + "fwSdy70OumxESZipeQP+Lo9x6FcaW9L78hDX0aijJhgSEsnGODKB+bln29txX37E"
+            + "/a/Si+pyeLMi82kUdIL3G3I5HPWd3qSO4K94062+HfFj8bA20/1tbb/WxvxB2sKJ"
+            + "i3IobblFOvFHo+v8GaLdVyartp0JZLue/jP1dl9ctulSrIqaJT342uLsgTjsr2z+"
+            + "AwMCAyAU8Vo5AhhgFkDto8vQk7yxyRKEzu5qB66dRcTlaUPIiR8kamcy5ZTtujs4"
+            + "KIW4j2M/LvagrpWfV5+0M0VyaWMgRWNoaWRuYSAoRFNBIFRlc3QgS2V5KSA8ZXJp"
+            + "Y0Bib3VuY3ljYXN0bGUub3JnPohZBBMRAgAZBQI/Rwc1BAsHAwIDFQIDAxYCAQIe"
+            + "AQIXgAAKCRDNI/XpxMo0QwJcAJ40447eezSiIMspuzkwsMyFN8YBaQCdFTuZuT30"
+            + "CphiUYWnsC0mQ+J15B4=");
+
+        private static readonly byte[] enc1 = Base64.Decode(
+              "hIwDKwfQexPJboABA/4/7prhYYMORTiQ5avQKx0XYpCLujzGefYjnyuWZnx3Iev8"
+            + "Pmsguumm+OLLvtXhhkXQmkJRXbIg6Otj2ubPYWflRPgpJSgOrNOreOl5jeABOrtw"
+            + "bV6TJb9OTtZuB7cTQSCq2gmYiSZkluIiDjNs3R3mEanILbYzOQ3zKSggKpzlv9JQ"
+            + "AZUqTyDyJ6/OUbJF5fI5uiv76DCsw1zyMWotUIu5/X01q+AVP5Ly3STzI7xkWg/J"
+            + "APz4zUHism7kSYz2viAQaJx9/bNnH3AM6qm1Fuyikl4=");
+
+//		private static readonly byte[] enc1crc = Base64.Decode("lv4o");
+
+//        private static readonly byte[] enc2 = Base64.Decode(
+//			  "hIwDKwfQexPJboABBAC62jcJH8xKnKb1neDVmiovYON04+7VQ2v4BmeHwJrdag1g"
+//			+ "Ya++6PeBlQ2Q9lSGBwLobVuJmQ7cOnPUJP727JeSGWlMyFtMbBSHekOaTenT5lj7"
+//			+ "Zk7oRHxMp/hByzlMacIDzOn8LPSh515RHM57eDLCOwqnAxGQwk67GRl8f5dFH9JQ"
+//			+ "Aa7xx8rjCqPbiIQW6t5LqCNvPZOiSCmftll6+se1XJhFEuq8WS4nXtPfTiJ3vib4"
+//			+ "3soJdHzGB6AOs+BQ6aKmmNTVAxa5owhtSt1Z/6dfSSk=");
+
+        private static readonly byte[] subPubKey = Base64.Decode(
+              "mIsEPz2nJAEEAOTVqWMvqYE693qTgzKv/TJpIj3hI8LlYPC6m1dk0z3bDLwVVk9F"
+            + "FAB+CWS8RdFOWt/FG3tEv2nzcoNdRvjv9WALyIGNawtae4Ml6oAT06/511yUzXHO"
+            + "k+9xK3wkXN5jdzUhf4cA2oGpLSV/pZlocsIDL+jCUQtumUPwFodmSHhzAAYptC9F"
+            + "cmljIEVjaGlkbmEgKHRlc3Qga2V5KSA8ZXJpY0Bib3VuY3ljYXN0bGUub3JnPoi4"
+            + "BBMBAgAiBQI/PackAhsDBQkAg9YABAsHAwIDFQIDAxYCAQIeAQIXgAAKCRA1WGFG"
+            + "/fPzc8WMA/9BbjuB8E48QAlxoiVf9U8SfNelrz/ONJA/bMvWr/JnOGA9PPmFD5Uc"
+            + "+kV/q+i94dEMjsC5CQ1moUHWSP2xlQhbOzBP2+oPXw3z2fBs9XJgnTH6QWMAAvLs"
+            + "3ug9po0loNHLobT/D/XdXvcrb3wvwvPT2FptZqrtonH/OdzT9JdfrIhMBBARAgAM"
+            + "BQI/RxooBYMAemL8AAoJEM0j9enEyjRDiBgAn3RcLK+gq90PvnQFTw2DNqdq7KA0"
+            + "AKCS0EEIXCzbV1tfTdCUJ3hVh3btF7QkRXJpYyBFY2hpZG5hIDxlcmljQGJvdW5j"
+            + "eWNhc3RsZS5vcmc+iLgEEwECACIFAj9HFA0CGwMFCQCD1gAECwcDAgMVAgMDFgIB"
+            + "Ah4BAheAAAoJEDVYYUb98/Nzc7oD/j21cUKKI/y+Dvs5e+eZufM8EDUbqMJFk0/X"
+            + "Ihe6w6OkerIs3kr2HDqWr+jik2IK6KrfaiyoZFfeW/+cN24lTWSfY7D4jZVyL6iM"
+            + "xd0IZ0So/Bl+/juMcvBGshQnbY46haw5G2C9J5FR3gjODyOu5oUzu5+vmGuMSXVy"
+            + "4tbUevwuiEwEEBECAAwFAj9HGigFgwB6YvwACgkQzSP16cTKNEPwBQCdHm0Amwza"
+            + "NmVmDHm3rmqI7rp2oQ0An2YbiP/H/kmBNnmTeH55kd253QOhuIsEP0ccUAEEANCd"
+            + "gSHam/CbQxio72Ma47tLqyVVc8iNQpwowKewrS6B0CVEFOz2o51eCXddrpH3KCuz"
+            + "Ea2mMnUBI8YdjKj6bkICUt3YEFa8Tj2qw0GARa2TXdrWcTo2GpIRK71JkaOslhWs"
+            + "QocKjIJfF1roATYNQ72vv2HKBkPpcviYOEVmaB/PAAYpiJ8EGAECAAkFAj9HHFAC"
+            + "GwwACgkQNVhhRv3z83M5hQP8DIOR4TeTZKpo5x1BX3lzV3R85npMsN/EZ7gjCpn3"
+            + "ONwIg7PhbSetoKUOjxLGReKPUuX8XI1ZN1UoNNFzA7UP9AbCgXORsYSU6uxvv0qH"
+            + "jON91htfbqEtPuS3/99cDaE56b+p6TmmKXE0Oy/Swp88ABeB9ISTxOm4ZltgjHLB"
+            + "PyGZAaIEP0cHNREEALOTFEJUYmDn4t30NThemd3gsIqAyrtg5jsaLQSAr3aBtprr"
+            + "7NChAWrPW23dBSanPdhWSb/MsRIEG0LUAIhcaCBR0UxSvkjzv7UJvq/N58C0a3w3"
+            + "lVXUX8xe/WAnPgG7ofLEv+dx97vWOw2Fq/SLjICN/Z61YWPnfMrpH46ODkfrAKCk"
+            + "v3+1dV8Y/xKoW/Ks3/jfsyUVJQQAg3dXqP8xSWXKtmCWu2vb5FYjBGsb8AKasXqF"
+            + "O6A6XhxDFoNg1ye1duGVOUmz0zGNMffHHPKXKKsLKrsfMYnFnNK3oVN6HUMVjOEn"
+            + "tC5hHXGtJ0DpjSZS/SLEPkDic8eO6lDlAKocZ5F8UP+gfMPjOoGcmn8Encu9Drps"
+            + "REmYqXkD/i6PcehXGlvS+/IQ19GooyYYEhLJxjgygfm5Z9vbcV9+xP2v0ovqcniz"
+            + "IvNpFHSC9xtyORz1nd6kjuCveNOtvh3xY/GwNtP9bW2/1sb8QdrCiYtyKG25RTrx"
+            + "R6Pr/Bmi3Vcmq7adCWS7nv4z9XZfXLbpUqyKmiU9+Nri7IE47K9stDNFcmljIEVj"
+            + "aGlkbmEgKERTQSBUZXN0IEtleSkgPGVyaWNAYm91bmN5Y2FzdGxlLm9yZz6IWQQT"
+            + "EQIAGQUCP0cHNQQLBwMCAxUCAwMWAgECHgECF4AACgkQzSP16cTKNEMCXACfauui"
+            + "bSwyG59Yrm8hHCDuCPmqwsQAni+dPl08FVuWh+wb6kOgJV4lcYae");
+
+//		private static readonly byte[] subPubCrc = Base64.Decode("rikt");
+
+        private static readonly byte[] pgp8Key = Base64.Decode(
+              "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF"
+            + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd"
+            + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy"
+            + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y"
+            + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7"
+            + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO"
+            + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP"
+            + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY"
+            + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb"
+            + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4"
+            + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj"
+            + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I"
+            + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH"
+            + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt"
+            + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j"
+            + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw"
+            + "AgAA");
+
+        private static readonly char[] pgp8Pass = "2002 Buffalo Sabres".ToCharArray();
+
+        private static readonly char[] pass = "hello world".ToCharArray();
+
+        private static readonly byte[] fingerprintKey = Base64.Decode(
+              "mQEPA0CiJdUAAAEIAMI+znDlPd2kQoEcnxqxLcRz56Z7ttFKHpnYp0UkljZdquVc"
+            + "By1jMfXGVV64xN1IvMcyenLXUE0IUeUBCQs6tHunFRAPSeCxJ3FdFe1B5MpqQG8A"
+            + "BnEpAds/hAUfRDZD5y/lolk1hjvFMrRh6WXckaA/QQ2t00NmTrJ1pYUpkw9tnVQb"
+            + "LUjWJhfZDBBcN0ADtATzgkugxMtcDxR6I5x8Ndn+IilqIm23kxGIcmMd/BHOec4c"
+            + "jRwJXXDb7u8tl+2knAf9cwhPHp3+Zy4uGSQPdzQnXOhBlA+4WDa0RROOevWgq8uq"
+            + "8/9Xp/OlTVL+OoIzjsI6mJP1Joa4qmqAnaHAmXcAEQEAAbQoQk9BM1JTS1kgPEJP"
+            + "QSBNb25pdG9yaW5nIEAgODg4LTI2OS01MjY2PokBFQMFEECiJdWqaoCdocCZdwEB"
+            + "0RsH/3HPxoUZ3G3K7T3jgOnJUckTSHWU3XspHzMVgqOxjTrcexi5IsAM5M+BulfW"
+            + "T2aO+Kqf5w8cKTKgW02DNpHUiPjHx0nzDE+Do95zbIErGeK+Twkc4O/aVsvU9GGO"
+            + "81VFI6WMvDQ4CUAUnAdk03MRrzI2nAuhn4NJ5LQS+uJrnqUJ4HmFAz6CQZQKd/kS"
+            + "Xgq+A6i7aI1LG80YxWa9ooQgaCrb9dwY/kPQ+yC22zQ3FExtv+Fv3VtAKTilO3vn"
+            + "BA4Y9uTHuObHfI+1yxUS2PrlRUX0m48ZjpIX+cEN3QblGBJudI/A1QSd6P0LZeBr"
+            + "7F1Z1aF7ZDo0KzgiAIBvgXkeTpw=");
+
+//		private static readonly byte[] fingerprintCheck = Base64.Decode("CTv2");
+
+        private static readonly byte[] jpegImage = Base64.Decode(
+              "/9j/4AAQSkZJRgABAQEASABIAAD/4QAWRXhpZgAATU0AKgAAAAgAAAAAAAD/2wBDAAUDBAQEAwUE"
+            + "BAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/"
+            + "wAALCAA6AFABASIA/8QAHAAAAgMAAwEAAAAAAAAAAAAABQcABAYBAggD/8QAMRAAAgEDBAEDAwME"
+            + "AQUAAAAAAQIDBAURAAYSITEHIkETFFEjYXEVMkKRCCUzQ4Gh/9oACAEBAAA/APX1TdKCmlaOoqoo"
+            + "WXzzbiP9nWaS71lXuA2tqrgopBOxpyGyWLAEEd4GAf3+fOjLPXoVaOcNzYAhl8HskADwAPz37f3z"
+            + "opSvI9Mjypwcr7l/B1XuFwSmoTVooljB9xDYAH51Vor191F9dKGb6Py3yo4huwcHwf8AYP7ZLIyu"
+            + "gZSGBGQQejrnU1NKn1EqVi3sZJOBCwxxIp9xzksfb5PR+Mdga+ljqIKje1TNBBNToYYgU4477HwQ"
+            + "Bn9z8/nW6mqxLR0NzpJkMLx8lJUkOGAIx4I/0f41lJ93UkkrRxVKvNKVjZfpSe6RyqhCp7wCSD89"
+            + "EEDRWppEkgqKdYohGcoZAjAlSMMcZ+PHH/3odsG6VLW2qaoqV+nTyFZpHOFQL0Sc9ADGTnHWtZap"
+            + "EpoamJm/TgYkfgJ5H/zGuKieVJIGkqCgmfCJFFy64s3Z+Oh58fHyNfGavipIJ2BrZcKXA+mzEd9Y"
+            + "OCcHI/gDV62SzvBGKhQHaNWzj8jvP750oN/xM3qkshLPEstOhj7IVyvkY+f7Nd7hf9vbc9QbVb7n"
+            + "dadLldqc00FMCwlmZnCrgL2v/cAySPBPwSD+/wC+3HbWx3rLbaqW81CVHOWnetMZjRm9h7VvClcj"
+            + "oDB7PymPTvem+a6roxvC10sd3ScmlucdEyUtRADxdice9wY3PQGRgj4OnHU3u5RW+op6imo4q+KA"
+            + "1UKGQ/bzrnt0biWxkgFOJK9ZyCCVX6f3T1Rh9RawbltdQNv18CGe2wxBDQyvGrowIJd15HEnHvP+"
+            + "OBjXoGzS0tNTpQipFTIw48Xn5SSBVUMw5e5wMgZ/j86yVNvvZ9TeDR1c9XSV0bl443dmYZXiCSCR"
+            + "jvxkjR1L1b46iWpStpIRLOWkCqyniP8AJjxPIniBjr+etFdu11DVu321WZiFHRjZcA/gsO+seNYf"
+            + "fVpq6n1Eo5KNATIYmb5Bx7csP4z/AKz8aX1N6Q7W3FuWWrS1TRzi+tXSutUESQhCGiVAvJVRgfcc"
+            + "HkeidM6tSmTbps9RHIH4KoqC8j/VC8R0+CSScZLdknPZGgNfYpUUUzfewxxcWpopWbhL715KgBIQ"
+            + "MCQc4A84+dD963X7ywQ0NIVW60qqzkzIfoszAMGUNyUHORkDrHxo3sSaOhtX2hnp3uNRF9b7hqtO"
+            + "DxM3Rcj3dMCPHXLGfOkLuPddp9R/ViOa62KppqK3Vctvsz0UylKtWfgXy3+L8WIZFBGRhs407rTT"
+            + "bcuFDRWmtsNGIZ1MMEU9GPqRorKPcJEzhich8Anz350Wk2zs2OsT7D7RZJpChMEk0MoypJZWVwM9"
+            + "ZzjWw2lbKaioFjQy/U9shLyu7Esi5JLEnsgnQlaSqhqayWSRZ5JaiSSNPoBCiq54jPuJyA2W+QfA"
+            + "+FrSXq4bdulZHRpWRzpArPK0SSNUExh14qB4c5X9ipz41Zud0juVouVooHN6rrZKVaoek/VhYgqE"
+            + "4v7cZPTfPHwT7tZX0e2NVUV5rK2ku9TeY6aFZJ6GuLALKzNnizE4CsqHIyBxJCk4AYFNt2wSUExm"
+            + "pP1lqgq1zkfXUtIgkiOFHQCsCM/kfOtZU7GsNZU1FFc1lrqCSNSlFOQ8SJk8kC4/tJx1rMwbWt0V"
+            + "CW21VW+krVoFTCRrPC0bf+NF8ocqMcT/AIg6EVF5/p9U6zPXLVFGpoKlSpMiEkniSCcqVY+eQIPW"
+            + "NULf/UNxJNS0dhklu8SK9Lco6pUcEr0JOu1HQ7z+R5OndaI5leWV0VQ54kA5KlWIx/Gqd2t6vcqe"
+            + "FIXNJMs71SoCMsQuG5jsN8AAjyTnrGlt6mVlqswtS0SG71NTXpSiCQFpogckll6Y4wvyD/OToVd7"
+            + "3tLedda4Nr3iRK2mqJhW1K0qxSSGJf1OTOAwwVADLkA9fPV2W77msVfPTClNRUyJCla0SqS5dR5J"
+            + "b2kluKlQc5BbHnWu2xTS0G4qmjvSq6RwrPHJUMHkkYDhzJHXIhmBAHnxpaL6j3il3D6g1VLuSz1k"
+            + "1ht//S6SZQ4KoTI6MyMOb9hR85HedM/0wqn3RsC0bhgq/pQV9J9WELEFaNWGARg+04xkd95xjQTe"
+            + "df6c7U+ysl3mtMFJe5JYGkkmAVKgKZCZGzlVbBySemA/OgvpZUQxvaqitgoqSsiX6XKh5RwVCBP0"
+            + "8KCTIoU8VJyDjIA8Bs2e5CprDTR8VXi8pRgyyZMh8qQMDHz850ZOlVv30RsW5blcL5S3a626+1cq"
+            + "TirFQ0qJIgAQCNjgIMeFKn9wQCMA3o2vprca/ctp29Jv6/3aoZ4IRRx08dC5D8nWQv7FJYHByeuv"
+            + "zo5SWn1Z2ttahutFZqbcG6JK5ZLu1TNEzzUq5ASNyVw6pxUMc5Oc5znR6KyXffldUVW4rBcbAqos"
+            + "EUq1qrUzUkwy8bFB+m4ZI2IBbAJAbOdau0+nmybJYqe027atvNHTRlYomhVz+Tln8knyScn50j/+"
+            + "SOyd3VO2oDtmPcNPYqJgDt23xKtOIiTy6gYO/Z5YOcAHGsJ/x39NgbzuDc+0bNt6/wAySmltbXGv"
+            + "flaT8ST07xBjIR30RjsL+dex9uwT/wBKo6i5UtPFdHp4/u/pgECTiOQDYBIByB+w0RVEVmZUUM39"
+            + "xA7P867ampqampqaq09BQwV9RWwUVNFU1AUTTJEoeQLnHJgMnGTjP51a1Nf/2Q==");
+
+        private static readonly byte[] embeddedJPEGKey = Base64.Decode(
+              "mI0ER0JXuwEEAKNqsXwLU6gu6P2Q/HJqEJVt3A7Kp1yucn8HWVeJF9JLAKVjVU8jrvz9Bw4NwaRJ"
+            + "NGYEAgdRq8Hx3WP9FXFCIVfCdi+oQrphcHWzzBFul8sykUGT+LmcBdqQGU9WaWSJyCOmUht4j7t0"
+            + "zk/IXX0YxGmkqR+no5rTj9LMDG8AQQrFABEBAAG0P0VyaWMgSCBFY2hpZG5hIChpbWFnZSB0ZXN0"
+            + "IGtleSkgPGVyaWMuZWNoaWRuYUBib3VuY3ljYXN0bGUub3JnPoi2BBMBAgAgBQJHQle7AhsDBgsJ"
+            + "CAcDAgQVAggDBBYCAwECHgECF4AACgkQ1+RWqFFpjMTKtgP+Okqkn0gVpQyNYXM/hWX6f3UQcyXk"
+            + "2Sd/fWW0XG+LBjhhBo+lXRWK0uYF8OMdZwsSl9HimpgYD5/kNs0Seh417DioP1diOgxkgezyQgMa"
+            + "+ODZfNnIvVaBr1pHLPLeqIBxBVMWBfa4wDXnLLGu8018uvI2yBhz5vByB1ntxwgKMXCwAgAD0cf3"
+            + "x/UBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQEBAEgASAAA/+EAFkV4aWYAAE1NACoAAAAI"
+            + "AAAAAAAA/9sAQwAFAwQEBAMFBAQEBQUFBgcMCAcHBwcPCwsJDBEPEhIRDxERExYcFxMUGhURERgh"
+            + "GBodHR8fHxMXIiQiHiQcHh8e/8AACwgAOgBQAQEiAP/EABwAAAIDAAMBAAAAAAAAAAAAAAUHAAQG"
+            + "AQIIA//EADEQAAIBAwQBAwMDBAEFAAAAAAECAwQFEQAGEiExByJBExRRI2FxFTJCkQglM0OBof/a"
+            + "AAgBAQAAPwD19U3SgppWjqKqKFl8824j/Z1mku9ZV7gNraq4KKQTsachsliwBBHeBgH9/nzoyz16"
+            + "FWjnDc2AIZfB7JAA8AD89+3986KUryPTI8qcHK+5fwdV7hcEpqE1aKJYwfcQ2AB+dVaK9fdRfXSh"
+            + "m+j8t8qOIbsHB8H/AGD+2SyMroGUhgRkEHo651NTSp9RKlYt7GSTgQsMcSKfcc5LH2+T0fjHYGvp"
+            + "Y6iCo3tUzQQTU6GGIFOOO+x8EAZ/c/P51upqsS0dDc6SZDC8fJSVJDhgCMeCP9H+NZSfd1JJK0cV"
+            + "SrzSlY2X6UnukcqoQqe8Akg/PRBA0VqaRJIKinWKIRnKGQIwJUjDHGfjxx/96HbBulS1tqmqKlfp"
+            + "08hWaRzhUC9EnPQAxk5x1rWWqRKaGpiZv04GJH4CeR/8xrionlSSBpKgoJnwiRRcuuLN2fjoefHx"
+            + "8jXxmr4qSCdga2XClwPpsxHfWDgnByP4A1etks7wRioUB2jVs4/I7z++dKDf8TN6pLISzxLLToY+"
+            + "yFcr5GPn+zXe4X/b23PUG1W+53WnS5XanNNBTAsJZmZwq4C9r/3AMkjwT8Eg/v8Avtx21sd6y22q"
+            + "lvNQlRzlp3rTGY0ZvYe1bwpXI6Awez8pj073pvmuq6MbwtdLHd0nJpbnHRMlLUQA8XYnHvcGNz0B"
+            + "kYI+Dpx1N7uUVvqKeopqOKvigNVChkP28657dG4lsZIBTiSvWcgglV+n909UYfUWsG5bXUDb9fAh"
+            + "ntsMQQ0Mrxq6MCCXdeRxJx7z/jgY16Bs0tLTU6UIqRUyMOPF5+UkgVVDMOXucDIGf4/OslTb72fU"
+            + "3g0dXPV0ldG5eON3ZmGV4gkgkY78ZI0dS9W+OolqUraSESzlpAqsp4j/ACY8TyJ4gY6/nrRXbtdQ"
+            + "1bt9tVmYhR0Y2XAP4LDvrHjWH31aaup9RKOSjQEyGJm+Qce3LD+M/wCs/Gl9TekO1txbllq0tU0c"
+            + "4vrV0rrVBEkIQholQLyVUYH3HB5HonTOrUpk26bPURyB+CqKgvI/1QvEdPgkknGS3ZJz2RoDX2KV"
+            + "FFM33sMcXFqaKVm4S+9eSoASEDAkHOAPOPnQ/et1+8sENDSFVutKqs5MyH6LMwDBlDclBzkZA6x8"
+            + "aN7EmjobV9oZ6d7jURfW+4arTg8TN0XI93TAjx1yxnzpC7j3XafUf1Yjmutiqaait1XLb7M9FMpS"
+            + "rVn4F8t/i/FiGRQRkYbONO60023LhQ0VprbDRiGdTDBFPRj6kaKyj3CRM4YnIfAJ89+dFpNs7Njr"
+            + "E+w+0WSaQoTBJNDKMqSWVlcDPWc41sNpWymoqBY0Mv1PbIS8ruxLIuSSxJ7IJ0JWkqoamslkkWeS"
+            + "WokkjT6AQoqueIz7icgNlvkHwPha0l6uG3bpWR0aVkc6QKzytEkjVBMYdeKgeHOV/Yqc+NWbndI7"
+            + "laLlaKBzeq62SlWqHpP1YWIKhOL+3GT03zx8E+7WV9HtjVVFeaytpLvU3mOmhWSehriwCyszZ4sx"
+            + "OArKhyMgcSQpOAGBTbdsElBMZqT9ZaoKtc5H11LSIJIjhR0ArAjP5HzrWVOxrDWVNRRXNZa6gkjU"
+            + "pRTkPEiZPJAuP7ScdazMG1rdFQlttVVvpK1aBUwkazwtG3/jRfKHKjHE/wCIOhFRef6fVOsz1y1R"
+            + "RqaCpUqTIhJJ4kgnKlWPnkCD1jVC3/1DcSTUtHYZJbvEivS3KOqVHBK9CTrtR0O8/keTp3WiOZXl"
+            + "ldFUOeJAOSpViMfxqndrer3KnhSFzSTLO9UqAjLELhuY7DfAAI8k56xpbeplZarMLUtEhu9TU16U"
+            + "ogkBaaIHJJZemOML8g/zk6FXe97S3nXWuDa94kStpqiYVtStKsUkhiX9TkzgMMFQAy5APXz1dlu+"
+            + "5rFXz0wpTUVMiQpWtEqkuXUeSW9pJbipUHOQWx51rtsU0tBuKpo70qukcKzxyVDB5JGA4cyR1yIZ"
+            + "gQB58aWi+o94pdw+oNVS7ks9ZNYbf/0ukmUOCqEyOjMjDm/YUfOR3nTP9MKp90bAtG4YKv6UFfSf"
+            + "VhCxBWjVhgEYPtOMZHfecY0E3nX+nO1PsrJd5rTBSXuSWBpJJgFSoCmQmRs5VWwcknpgPzoL6WVE"
+            + "Mb2qorYKKkrIl+lyoeUcFQgT9PCgkyKFPFScg4yAPAbNnuQqaw00fFV4vKUYMsmTIfKkDAx8/OdG"
+            + "TpVb99EbFuW5XC+Ut2utuvtXKk4qxUNKiSIAEAjY4CDHhSp/cEAjAN6Nr6a3Gv3LadvSb+v92qGe"
+            + "CEUcdPHQuQ/J1kL+xSWBwcnrr86OUlp9WdrbWobrRWam3BuiSuWS7tUzRM81KuQEjclcOqcVDHOT"
+            + "nOc50eisl335XVFVuKwXGwKqLBFKtaq1M1JMMvGxQfpuGSNiAWwCQGznWrtPp5smyWKntNu2rbzR"
+            + "00ZWKJoVc/k5Z/JJ8knJ+dI//kjsnd1TtqA7Zj3DT2KiYA7dt8SrTiIk8uoGDv2eWDnABxrCf8d/"
+            + "TYG87g3PtGzbev8AMkppbW1xr35Wk/Ek9O8QYyEd9EY7C/nXsfbsE/8ASqOouVLTxXR6eP7v6YBA"
+            + "k4jkA2ASAcgfsNEVRFZmVFDN/cQOz/Ou2pqampqamqtPQUMFfUVsFFTRVNQFE0yRKHkC5xyYDJxk"
+            + "4z+dWtTX/9mItgQTAQIAIAUCR0JYkAIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJENfkVqhR"
+            + "aYzEAPYD/iHdLOAE8r8HHF3F4z28vtIT8iiRB9aPC/YH0xqV1qeEKG8+VosBaQAOCEquONtRWsww"
+            + "gO3XB0d6VAq2kMOKc2YiB4ZtZcFvvmP9KdmVIZxVjpa9ozjP5j9zFso1HOpFcsn/VDBEqy5TvsNx"
+            + "Qvmtc8X7lqK/zLRVkSSBItik2IIhsAIAAw==");
+
+        private void FingerPrintTest()
+        {
+            //
+            // version 3
+            //
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(fingerprintKey);
+
+            PgpPublicKey pubKey = pgpPub.GetPublicKey();
+
+            if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("4FFB9F0884266C715D1CEAC804A3BBFA")))
+            {
+                Fail("version 3 fingerprint test failed");
+            }
+
+            //
+            // version 4
+            //
+            pgpPub = new PgpPublicKeyRing(testPubKey);
+
+            pubKey = pgpPub.GetPublicKey();
+
+            if (!Arrays.AreEqual(pubKey.GetFingerprint(), Hex.Decode("3062363c1046a01a751946bb35586146fdf3f373")))
+            {
+               Fail("version 4 fingerprint test failed");
+            }
+        }
+
+        private void MixedTest(
+            PgpPrivateKey	pgpPrivKey,
+            PgpPublicKey	pgpPubKey)
+        {
+            byte[] text = Encoding.ASCII.GetBytes("hello world!\n");
+
+            //
+            // literal data
+            //
+            MemoryStream bOut = new MemoryStream();
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            Stream lOut = lGen.Open(
+                bOut,
+                PgpLiteralData.Binary,
+                PgpLiteralData.Console,
+                text.Length,
+                DateTime.UtcNow);
+
+            lOut.Write(text, 0, text.Length);
+
+            lGen.Close();
+
+            byte[] bytes = bOut.ToArray();
+
+            PgpObjectFactory f = new PgpObjectFactory(bytes);
+            CheckLiteralData((PgpLiteralData)f.NextPgpObject(), text);
+
+            MemoryStream bcOut = new MemoryStream();
+
+            PgpEncryptedDataGenerator encGen = new PgpEncryptedDataGenerator(
+                SymmetricKeyAlgorithmTag.Aes128,
+                true,
+                new SecureRandom());
+
+            encGen.AddMethod(pgpPubKey);
+
+            encGen.AddMethod("password".ToCharArray());
+
+            Stream cOut = encGen.Open(bcOut, bytes.Length);
+
+            cOut.Write(bytes, 0, bytes.Length);
+
+            cOut.Close();
+
+            byte[] encData = bcOut.ToArray();
+
+            //
+            // asymmetric
+            //
+            PgpObjectFactory pgpF = new PgpObjectFactory(encData);
+
+            PgpEncryptedDataList encList = (PgpEncryptedDataList) pgpF.NextPgpObject();
+
+            PgpPublicKeyEncryptedData  encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            Stream clear = encP.GetDataStream(pgpPrivKey);
+
+            PgpObjectFactory pgpFact = new PgpObjectFactory(clear);
+
+            CheckLiteralData((PgpLiteralData)pgpFact.NextPgpObject(), text);
+
+            //
+            // PBE
+            //
+            pgpF = new PgpObjectFactory(encData);
+
+            encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            PgpPbeEncryptedData encPbe = (PgpPbeEncryptedData) encList[1];
+
+            clear = encPbe.GetDataStream("password".ToCharArray());
+
+            pgpF = new PgpObjectFactory(clear);
+
+            CheckLiteralData((PgpLiteralData) pgpF.NextPgpObject(), text);
+        }
+
+        private void CheckLiteralData(
+            PgpLiteralData	ld,
+            byte[]			data)
+        {
+            if (!ld.FileName.Equals(PgpLiteralData.Console))
+                throw new Exception("wrong filename in packet");
+
+            Stream inLd = ld.GetDataStream();
+            byte[] bytes = Streams.ReadAll(inLd);
+
+            if (!AreEqual(bytes, data))
+            {
+                Fail("wrong plain text in decrypted packet");
+            }
+        }
+
+        private void ExistingEmbeddedJpegTest()
+        {
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(embeddedJPEGKey);
+
+            PgpPublicKey pubKey = pgpPub.GetPublicKey();
+
+            int count = 0;
+            foreach (PgpUserAttributeSubpacketVector attributes in pubKey.GetUserAttributes())
+            {
+                int sigCount = 0;
+                foreach (PgpSignature sig in pubKey.GetSignaturesForUserAttribute(attributes))
+                {
+                    sig.InitVerify(pubKey);
+
+                    if (!sig.VerifyCertification(attributes, pubKey))
+                    {
+                        Fail("signature failed verification");
+                    }
+
+                    sigCount++;
+                }
+
+                if (sigCount != 1)
+                {
+                    Fail("Failed user attributes signature check");
+                }
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("didn't find user attributes");
+            }
+        }
+
+        private void EmbeddedJpegTest()
+        {
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey);
+            PgpSecretKeyRing pgpSec = new PgpSecretKeyRing(testPrivKey);
+
+            PgpPublicKey pubKey = pgpPub.GetPublicKey();
+
+            PgpUserAttributeSubpacketVectorGenerator vGen = new PgpUserAttributeSubpacketVectorGenerator();
+
+            vGen.SetImageAttribute(ImageAttrib.Format.Jpeg, jpegImage);
+
+            PgpUserAttributeSubpacketVector uVec = vGen.Generate();
+
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(
+                PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.PositiveCertification, pgpSec.GetSecretKey().ExtractPrivateKey(pass));
+
+            PgpSignature sig = sGen.GenerateCertification(uVec, pubKey);
+
+            PgpPublicKey nKey = PgpPublicKey.AddCertification(pubKey, uVec, sig);
+
+            int count = 0;
+            foreach (PgpUserAttributeSubpacketVector attributes in nKey.GetUserAttributes())
+            {
+                int sigCount = 0;
+                foreach (PgpSignature s in nKey.GetSignaturesForUserAttribute(attributes))
+                {
+                    s.InitVerify(pubKey);
+
+                    if (!s.VerifyCertification(attributes, pubKey))
+                    {
+                        Fail("added signature failed verification");
+                    }
+
+                    sigCount++;
+                }
+
+                if (sigCount != 1)
+                {
+                    Fail("Failed added user attributes signature check");
+                }
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("didn't find added user attributes");
+            }
+
+            nKey = PgpPublicKey.RemoveCertification(nKey, uVec);
+
+            if (nKey.GetUserAttributes().GetEnumerator().MoveNext())
+            {
+                Fail("found attributes where none expected");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            //
+            // Read the public key
+            //
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(testPubKey);
+
+            AsymmetricKeyParameter pubKey = pgpPub.GetPublicKey().GetKey();
+
+            IEnumerator enumerator = pgpPub.GetPublicKey().GetUserIds().GetEnumerator();
+            enumerator.MoveNext();
+            string uid = (string) enumerator.Current;
+
+
+            enumerator = pgpPub.GetPublicKey().GetSignaturesForId(uid).GetEnumerator();
+            enumerator.MoveNext();
+            PgpSignature sig = (PgpSignature) enumerator.Current;
+
+            sig.InitVerify(pgpPub.GetPublicKey());
+
+            if (!sig.VerifyCertification(uid, pgpPub.GetPublicKey()))
+            {
+                Fail("failed to verify certification");
+            }
+
+            //
+            // write a public key
+            //
+            MemoryStream bOut = new UncloseableMemoryStream();
+            BcpgOutputStream pOut = new BcpgOutputStream(bOut);
+
+            pgpPub.Encode(pOut);
+
+            if (!Arrays.AreEqual(bOut.ToArray(), testPubKey))
+            {
+                Fail("public key rewrite failed");
+            }
+
+            //
+            // Read the public key
+            //
+            PgpPublicKeyRing pgpPubV3 = new PgpPublicKeyRing(testPubKeyV3);
+            AsymmetricKeyParameter pubKeyV3 = pgpPub.GetPublicKey().GetKey();
+
+            //
+            // write a V3 public key
+            //
+            bOut = new UncloseableMemoryStream();
+            pOut = new BcpgOutputStream(bOut);
+
+            pgpPubV3.Encode(pOut);
+
+            //
+            // Read a v3 private key
+            //
+            char[] passP = "FIXCITY_QA".ToCharArray();
+
+            {
+                PgpSecretKeyRing pgpPriv2 = new PgpSecretKeyRing(testPrivKeyV3);
+                PgpSecretKey pgpPrivSecretKey = pgpPriv2.GetSecretKey();
+                PgpPrivateKey pgpPrivKey2 = pgpPrivSecretKey.ExtractPrivateKey(passP);
+
+                //
+                // write a v3 private key
+                //
+                bOut = new UncloseableMemoryStream();
+                pOut = new BcpgOutputStream(bOut);
+
+                pgpPriv2.Encode(pOut);
+
+                byte[] result = bOut.ToArray();
+                if (!Arrays.AreEqual(result, testPrivKeyV3))
+                {
+                    Fail("private key V3 rewrite failed");
+                }
+            }
+
+            //
+            // Read the private key
+            //
+            PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(testPrivKey);
+            PgpPrivateKey pgpPrivKey = pgpPriv.GetSecretKey().ExtractPrivateKey(pass);
+
+            //
+            // write a private key
+            //
+            bOut = new UncloseableMemoryStream();
+            pOut = new BcpgOutputStream(bOut);
+
+            pgpPriv.Encode(pOut);
+
+            if (!Arrays.AreEqual(bOut.ToArray(), testPrivKey))
+            {
+                Fail("private key rewrite failed");
+            }
+
+            //
+            // test encryption
+            //
+            IBufferedCipher c = CipherUtilities.GetCipher("RSA");
+
+//                c.Init(Cipher.ENCRYPT_MODE, pubKey);
+            c.Init(true, pubKey);
+
+            byte[] inBytes = Encoding.ASCII.GetBytes("hello world");
+            byte[] outBytes = c.DoFinal(inBytes);
+
+//                c.Init(Cipher.DECRYPT_MODE, pgpPrivKey.GetKey());
+            c.Init(false, pgpPrivKey.Key);
+
+            outBytes = c.DoFinal(outBytes);
+
+            if (!Arrays.AreEqual(inBytes, outBytes))
+            {
+                Fail("decryption failed.");
+            }
+
+            //
+            // test signature message
+            //
+            PgpObjectFactory pgpFact = new PgpObjectFactory(sig1);
+
+            PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+            PgpOnePassSignature ops = p1[0];
+
+            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+
+            Stream dIn = p2.GetInputStream();
+
+            ops.InitVerify(pgpPub.GetPublicKey(ops.KeyId));
+
+            int ch;
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed signature check");
+            }
+
+            //
+            // encrypted message - read subkey
+            //
+            pgpPriv = new PgpSecretKeyRing(subKey);
+
+            //
+            // encrypted message
+            //
+            byte[] text = Encoding.ASCII.GetBytes("hello world!\n");
+
+            PgpObjectFactory pgpF = new PgpObjectFactory(enc1);
+
+            PgpEncryptedDataList encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            PgpPublicKeyEncryptedData encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass);
+
+            Stream clear = encP.GetDataStream(pgpPrivKey);
+
+            pgpFact = new PgpObjectFactory(clear);
+
+            c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            PgpLiteralData ld = (PgpLiteralData)pgpFact.NextPgpObject();
+
+            if (!ld.FileName.Equals("test.txt"))
+            {
+                throw new Exception("wrong filename in packet");
+            }
+
+            Stream inLd = ld.GetDataStream();
+            byte[] bytes = Streams.ReadAll(inLd);
+
+            if (!Arrays.AreEqual(bytes, text))
+            {
+                Fail("wrong plain text in decrypted packet");
+            }
+
+            //
+            // encrypt - short message
+            //
+            byte[] shortText = { (byte)'h', (byte)'e', (byte)'l', (byte)'l', (byte)'o' };
+
+            MemoryStream cbOut = new UncloseableMemoryStream();
+            PgpEncryptedDataGenerator cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
+            PgpPublicKey puK = pgpPriv.GetSecretKey(encP.KeyId).PublicKey;
+
+            cPk.AddMethod(puK);
+
+            Stream cOut = cPk.Open(new UncloseableStream(cbOut), shortText.Length);
+
+            cOut.Write(shortText, 0, shortText.Length);
+
+            cOut.Close();
+
+            pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+            encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass);
+
+            if (encP.GetSymmetricAlgorithm(pgpPrivKey) != SymmetricKeyAlgorithmTag.Cast5)
+            {
+                Fail("symmetric algorithm mismatch");
+            }
+
+            clear = encP.GetDataStream(pgpPrivKey);
+            outBytes = Streams.ReadAll(clear);
+
+            if (!Arrays.AreEqual(outBytes, shortText))
+            {
+                Fail("wrong plain text in generated short text packet");
+            }
+
+            //
+            // encrypt
+            //
+            cbOut = new UncloseableMemoryStream();
+            cPk = new PgpEncryptedDataGenerator(SymmetricKeyAlgorithmTag.Cast5, new SecureRandom());
+            puK = pgpPriv.GetSecretKey(encP.KeyId).PublicKey;
+
+            cPk.AddMethod(puK);
+
+            cOut = cPk.Open(new UncloseableStream(cbOut), text.Length);
+
+            cOut.Write(text, 0, text.Length);
+
+            cOut.Close();
+
+            pgpF = new PgpObjectFactory(cbOut.ToArray());
+
+            encList = (PgpEncryptedDataList)pgpF.NextPgpObject();
+
+            encP = (PgpPublicKeyEncryptedData)encList[0];
+
+            pgpPrivKey = pgpPriv.GetSecretKey(encP.KeyId).ExtractPrivateKey(pass);
+
+            clear = encP.GetDataStream(pgpPrivKey);
+            outBytes = Streams.ReadAll(clear);
+
+            if (!Arrays.AreEqual(outBytes, text))
+            {
+                Fail("wrong plain text in generated packet");
+            }
+
+            //
+            // read public key with sub key.
+            //
+            pgpF = new PgpObjectFactory(subPubKey);
+            object o;
+            while ((o = pgpFact.NextPgpObject()) != null)
+            {
+                // TODO Should something be tested here?
+                // Console.WriteLine(o);
+            }
+
+            //
+            // key pair generation - CAST5 encryption
+            //
+            char[] passPhrase = "hello".ToCharArray();
+            IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters(
+                BigInteger.ValueOf(0x10001), new SecureRandom(), 1024, 25);
+
+            kpg.Init(genParam);
+
+
+            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();
+
+            PgpSecretKey secretKey = new PgpSecretKey(
+                PgpSignature.DefaultCertification,
+                PublicKeyAlgorithmTag.RsaGeneral,
+                kp.Public,
+                kp.Private,
+                DateTime.UtcNow,
+                "fred",
+                SymmetricKeyAlgorithmTag.Cast5,
+                passPhrase,
+                null,
+                null,
+                new SecureRandom()
+                );
+
+            PgpPublicKey key = secretKey.PublicKey;
+
+
+            enumerator = key.GetUserIds().GetEnumerator();
+            enumerator.MoveNext();
+            uid = (string) enumerator.Current;
+
+
+            enumerator = key.GetSignaturesForId(uid).GetEnumerator();
+            enumerator.MoveNext();
+            sig = (PgpSignature) enumerator.Current;
+
+            sig.InitVerify(key);
+
+            if (!sig.VerifyCertification(uid, key))
+            {
+                Fail("failed to verify certification");
+            }
+
+            pgpPrivKey = secretKey.ExtractPrivateKey(passPhrase);
+
+            key = PgpPublicKey.RemoveCertification(key, uid, sig);
+
+            if (key == null)
+            {
+                Fail("failed certification removal");
+            }
+
+            byte[] keyEnc = key.GetEncoded();
+
+            key = PgpPublicKey.AddCertification(key, uid, sig);
+
+            keyEnc = key.GetEncoded();
+
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.KeyRevocation, secretKey.ExtractPrivateKey(passPhrase));
+
+            sig = sGen.GenerateCertification(key);
+
+            key = PgpPublicKey.AddCertification(key, sig);
+
+            keyEnc = key.GetEncoded();
+
+            PgpPublicKeyRing tmpRing = new PgpPublicKeyRing(keyEnc);
+
+            key = tmpRing.GetPublicKey();
+
+            IEnumerator sgEnum = key.GetSignaturesOfType(PgpSignature.KeyRevocation).GetEnumerator();
+            sgEnum.MoveNext();
+            sig = (PgpSignature) sgEnum.Current;
+
+            sig.InitVerify(key);
+
+            if (!sig.VerifyCertification(key))
+            {
+                Fail("failed to verify revocation certification");
+            }
+
+            //
+            // use of PgpKeyPair
+            //
+            PgpKeyPair pgpKp = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral,
+                kp.Public, kp.Private, DateTime.UtcNow);
+
+            PgpPublicKey k1 = pgpKp.PublicKey;
+            PgpPrivateKey k2 = pgpKp.PrivateKey;
+
+            k1.GetEncoded();
+
+            MixedTest(k2, k1);
+
+            //
+            // key pair generation - AES_256 encryption.
+            //
+            kp = kpg.GenerateKeyPair();
+
+            secretKey = new PgpSecretKey(PgpSignature.DefaultCertification, PublicKeyAlgorithmTag.RsaGeneral, kp.Public, kp.Private, DateTime.UtcNow, "fred", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, new SecureRandom());
+
+            secretKey.ExtractPrivateKey(passPhrase);
+
+            secretKey.Encode(new UncloseableMemoryStream());
+
+            //
+            // secret key password changing.
+            //
+            const string newPass = "newPass";
+
+            secretKey = PgpSecretKey.CopyWithNewPassword(secretKey, passPhrase, newPass.ToCharArray(), secretKey.KeyEncryptionAlgorithm, new SecureRandom());
+
+            secretKey.ExtractPrivateKey(newPass.ToCharArray());
+
+            secretKey.Encode(new UncloseableMemoryStream());
+
+            key = secretKey.PublicKey;
+
+            key.Encode(new UncloseableMemoryStream());
+
+
+            enumerator = key.GetUserIds().GetEnumerator();
+            enumerator.MoveNext();
+            uid = (string) enumerator.Current;
+
+
+            enumerator = key.GetSignaturesForId(uid).GetEnumerator();
+            enumerator.MoveNext();
+            sig = (PgpSignature) enumerator.Current;
+
+            sig.InitVerify(key);
+
+            if (!sig.VerifyCertification(uid, key))
+            {
+                Fail("failed to verify certification");
+            }
+
+            pgpPrivKey = secretKey.ExtractPrivateKey(newPass.ToCharArray());
+
+            //
+            // signature generation
+            //
+            const string data = "hello world!";
+            byte[] dataBytes = Encoding.ASCII.GetBytes(data);
+
+            bOut = new UncloseableMemoryStream();
+
+            MemoryStream testIn = new MemoryStream(dataBytes, false);
+
+            sGen = new PgpSignatureGenerator(
+                PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+
+            PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(
+                CompressionAlgorithmTag.Zip);
+
+            BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));
+
+            sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+
+            DateTime testDateTime = new DateTime(1973, 7, 27);
+            Stream lOut = lGen.Open(new UncloseableStream(bcOut), PgpLiteralData.Binary, "_CONSOLE",
+                dataBytes.Length, testDateTime);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Close();
+
+            sGen.Generate().Encode(bcOut);
+
+            bcOut.Dispose();
+
+            //
+            // verify generated signature
+            //
+            pgpFact = new PgpObjectFactory(bOut.ToArray());
+
+            c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+            ops = p1[0];
+
+            p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+            if (!p2.ModificationTime.Equals(testDateTime))
+            {
+                Fail("Modification time not preserved");
+            }
+
+            dIn = p2.GetInputStream();
+
+            ops.InitVerify(secretKey.PublicKey);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed generated signature check");
+            }
+
+            //
+            // signature generation - version 3
+            //
+            bOut = new UncloseableMemoryStream();
+
+            testIn = new MemoryStream(dataBytes);
+            PgpV3SignatureGenerator sGenV3 = new PgpV3SignatureGenerator(
+                PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, pgpPrivKey);
+
+            cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
+
+            bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));
+
+            sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+            lGen = new PgpLiteralDataGenerator();
+            lOut = lGen.Open(
+                new UncloseableStream(bcOut),
+                PgpLiteralData.Binary,
+                "_CONSOLE",
+                dataBytes.Length,
+                testDateTime);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte) ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Close();
+
+            sGen.Generate().Encode(bcOut);
+
+            bcOut.Close();
+
+            //
+            // verify generated signature
+            //
+            pgpFact = new PgpObjectFactory(bOut.ToArray());
+
+            c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+            ops = p1[0];
+
+            p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+            if (!p2.ModificationTime.Equals(testDateTime))
+            {
+                Fail("Modification time not preserved");
+            }
+
+            dIn = p2.GetInputStream();
+
+            ops.InitVerify(secretKey.PublicKey);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed v3 generated signature check");
+            }
+
+            //
+            // extract PGP 8 private key
+            //
+            pgpPriv = new PgpSecretKeyRing(pgp8Key);
+
+            secretKey = pgpPriv.GetSecretKey();
+
+            pgpPrivKey = secretKey.ExtractPrivateKey(pgp8Pass);
+
+            //
+            // other sig tests
+            //
+            PerformTestSig(HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey);
+            PerformTestSig(HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey);
+            PerformTestSig(HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey);
+            FingerPrintTest();
+            ExistingEmbeddedJpegTest();
+            EmbeddedJpegTest();
+        }
+
+        private void PerformTestSig(
+            HashAlgorithmTag	hashAlgorithm,
+            PgpPublicKey		pubKey,
+            PgpPrivateKey		privKey)
+        {
+            const string data = "hello world!";
+            byte[] dataBytes = Encoding.ASCII.GetBytes(data);
+
+            MemoryStream bOut = new UncloseableMemoryStream();
+            MemoryStream testIn = new MemoryStream(dataBytes, false);
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, hashAlgorithm);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, privKey);
+
+            PgpCompressedDataGenerator cGen = new PgpCompressedDataGenerator(CompressionAlgorithmTag.Zip);
+
+            BcpgOutputStream bcOut = new BcpgOutputStream(cGen.Open(new UncloseableStream(bOut)));
+
+            sGen.GenerateOnePassVersion(false).Encode(bcOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            DateTime testDateTime = new DateTime(1973, 7, 27);
+            Stream lOut = lGen.Open(
+                new UncloseableStream(bcOut),
+                PgpLiteralData.Binary,
+                "_CONSOLE",
+                dataBytes.Length,
+                testDateTime);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Close();
+
+            sGen.Generate().Encode(bcOut);
+
+            bcOut.Close();
+
+            //
+            // verify generated signature
+            //
+            PgpObjectFactory pgpFact = new PgpObjectFactory(bOut.ToArray());
+
+            PgpCompressedData c1 = (PgpCompressedData)pgpFact.NextPgpObject();
+
+            pgpFact = new PgpObjectFactory(c1.GetDataStream());
+
+            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+
+            PgpOnePassSignature ops = p1[0];
+
+            PgpLiteralData p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+            if (!p2.ModificationTime.Equals(testDateTime))
+            {
+                Fail("Modification time not preserved");
+            }
+
+            Stream dIn = p2.GetInputStream();
+
+            ops.InitVerify(pubKey);
+
+            // TODO Need a stream object to automatically call Update?
+            // (via ISigner implementation of PgpSignatureGenerator)
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+
+            if (!ops.Verify(p3[0]))
+            {
+                Fail("Failed generated signature check - " + hashAlgorithm);
+            }
+        }
+
+        private class UncloseableMemoryStream
+            : MemoryStream
+        {
+            public override void Close()
+            {
+                throw new Exception("Close() called on underlying stream");
+            }
+        }
+
+        public override string Name
+        {
+            get { return "PGPRSATest"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new PgpRsaTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPSignatureTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPSignatureTest.cs
new file mode 100644
index 0000000..0d82353
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PGPSignatureTest.cs
@@ -0,0 +1,1045 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Bcpg.Sig;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpSignatureTest
+        : SimpleTest
+    {
+        private const int[] NO_PREFERENCES = null;
+        private static readonly int[] PREFERRED_SYMMETRIC_ALGORITHMS
+            = new int[] { (int)SymmetricKeyAlgorithmTag.Aes128, (int)SymmetricKeyAlgorithmTag.TripleDes };
+        private static readonly int[] PREFERRED_HASH_ALGORITHMS
+            = new int[] { (int)HashAlgorithmTag.Sha1, (int)HashAlgorithmTag.Sha256 };
+        private static readonly int[] PREFERRED_COMPRESSION_ALGORITHMS
+            = new int[] { (int)CompressionAlgorithmTag.ZLib };
+
+        private const int TEST_EXPIRATION_TIME = 10000;
+        private const string TEST_USER_ID = "test user id";
+        private static readonly byte[] TEST_DATA = Encoding.ASCII.GetBytes("hello world!\nhello world!\n");
+        private static readonly byte[] TEST_DATA_WITH_CRLF = Encoding.ASCII.GetBytes("hello world!\r\nhello world!\r\n");
+
+        private static readonly byte[] dsaKeyRing = Base64.Decode(
+            "lQHhBD9HBzURBACzkxRCVGJg5+Ld9DU4Xpnd4LCKgMq7YOY7Gi0EgK92gbaa6+zQ"
+            + "oQFqz1tt3QUmpz3YVkm/zLESBBtC1ACIXGggUdFMUr5I87+1Cb6vzefAtGt8N5VV"
+            + "1F/MXv1gJz4Bu6HyxL/ncfe71jsNhav0i4yAjf2etWFj53zK6R+Ojg5H6wCgpL9/"
+            + "tXVfGP8SqFvyrN/437MlFSUEAIN3V6j/MUllyrZglrtr2+RWIwRrG/ACmrF6hTug"
+            + "Ol4cQxaDYNcntXbhlTlJs9MxjTH3xxzylyirCyq7HzGJxZzSt6FTeh1DFYzhJ7Qu"
+            + "YR1xrSdA6Y0mUv0ixD5A4nPHjupQ5QCqHGeRfFD/oHzD4zqBnJp/BJ3LvQ66bERJ"
+            + "mKl5A/4uj3HoVxpb0vvyENfRqKMmGBISycY4MoH5uWfb23FffsT9r9KL6nJ4syLz"
+            + "aRR0gvcbcjkc9Z3epI7gr3jTrb4d8WPxsDbT/W1tv9bG/EHawomLcihtuUU68Uej"
+            + "6/wZot1XJqu2nQlku57+M/V2X1y26VKsipolPfja4uyBOOyvbP4DAwIDIBTxWjkC"
+            + "GGAWQO2jy9CTvLHJEoTO7moHrp1FxOVpQ8iJHyRqZzLllO26OzgohbiPYz8u9qCu"
+            + "lZ9Xn7QzRXJpYyBFY2hpZG5hIChEU0EgVGVzdCBLZXkpIDxlcmljQGJvdW5jeWNh"
+            + "c3RsZS5vcmc+iFkEExECABkFAj9HBzUECwcDAgMVAgMDFgIBAh4BAheAAAoJEM0j"
+            + "9enEyjRDAlwAnjTjjt57NKIgyym7OTCwzIU3xgFpAJ0VO5m5PfQKmGJRhaewLSZD"
+            + "4nXkHg==");
+
+        private static readonly char[] dsaPass = "hello world".ToCharArray();
+
+        private static readonly byte[] rsaKeyRing = Base64.Decode(
+              "lQIEBEBXUNMBBADScQczBibewnbCzCswc/9ut8R0fwlltBRxMW0NMdKJY2LF"
+            + "7k2COeLOCIU95loJGV6ulbpDCXEO2Jyq8/qGw1qD3SCZNXxKs3GS8Iyh9Uwd"
+            + "VL07nMMYl5NiQRsFB7wOb86+94tYWgvikVA5BRP5y3+O3GItnXnpWSJyREUy"
+            + "6WI2QQAGKf4JAwIVmnRs4jtTX2DD05zy2mepEQ8bsqVAKIx7lEwvMVNcvg4Y"
+            + "8vFLh9Mf/uNciwL4Se/ehfKQ/AT0JmBZduYMqRU2zhiBmxj4cXUQ0s36ysj7"
+            + "fyDngGocDnM3cwPxaTF1ZRBQHSLewP7dqE7M73usFSz8vwD/0xNOHFRLKbsO"
+            + "RqDlLA1Cg2Yd0wWPS0o7+qqk9ndqrjjSwMM8ftnzFGjShAdg4Ca7fFkcNePP"
+            + "/rrwIH472FuRb7RbWzwXA4+4ZBdl8D4An0dwtfvAO+jCZSrLjmSpxEOveJxY"
+            + "GduyR4IA4lemvAG51YHTHd4NXheuEqsIkn1yarwaaj47lFPnxNOElOREMdZb"
+            + "nkWQb1jfgqO24imEZgrLMkK9bJfoDnlF4k6r6hZOp5FSFvc5kJB4cVo1QJl4"
+            + "pwCSdoU6luwCggrlZhDnkGCSuQUUW45NE7Br22NGqn4/gHs0KCsWbAezApGj"
+            + "qYUCfX1bcpPzUMzUlBaD5rz2vPeO58CDtBJ0ZXN0ZXIgPHRlc3RAdGVzdD6I"
+            + "sgQTAQIAHAUCQFdQ0wIbAwQLBwMCAxUCAwMWAgECHgECF4AACgkQs8JyyQfH"
+            + "97I1QgP8Cd+35maM2cbWV9iVRO+c5456KDi3oIUSNdPf1NQrCAtJqEUhmMSt"
+            + "QbdiaFEkPrORISI/2htXruYn0aIpkCfbUheHOu0sef7s6pHmI2kOQPzR+C/j"
+            + "8D9QvWsPOOso81KU2axUY8zIer64Uzqc4szMIlLw06c8vea27RfgjBpSCryw"
+            + "AgAA");
+
+        private static readonly char[] rsaPass = "2002 Buffalo Sabres".ToCharArray();
+
+        private static readonly byte[] nullPacketsSubKeyBinding = Base64.Decode(
+            "iDYEGBECAAAAACp9AJ9PlJCrFpi+INwG7z61eku2Wg1HaQCgl33X5Egj+Kf7F9CXIWj2iFCvQDo=");
+
+        private static readonly byte[] okAttr = Base64.Decode(
+                "mQENBFOkuoMBCAC+8WcWLBZovlR5pLW4tbOoH3APia+poMEeTNkXKe8yAH0f"
+              + "ZmTQgeXFBIizd4Ka1QETbayv+C6Axt6Ipdwf+3N/lqcOqg6PEwuIX4MBrv5R"
+              + "ILMH5QyM3a3RlyXa7xES3I9t2VHiZvl15OrTZe67YNGtxlXyeawt6v/9d/a3"
+              + "M1EaUzjN4H2EfI3P/VWpMUvQkn70996UKInOyaSB0hef/QS10jshG9DdgmLM"
+              + "1/mJFRp8ynZOV4yGLnAdoEoPGG/HJZEzWfqOiwmWZOIrZIwedY1eKuMIhUGv"
+              + "LTC9u+9X0h+Y0st5eb1pf8OLvrpRpEyHMrxXfj/V3rxom4d160ifGihPABEB"
+              + "AAG0GndpdGggYXR0dHIgPGF0dHJAYXR0ci5uZXQ+iQE4BBMBAgAiBQJTpLqD"
+              + "AhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRBCjbg0bKVgCXJiB/wO"
+              + "6ksdrAy+zVxygFhk6Ju2vpMAOGnLl1nqBVT1mA5XiJu3rSiJmROLF2l21K0M"
+              + "BICZfz+mjIwN56RZNzZnEmXk/E2+PgADV5VTRRsjqlyoeN/NrLWuTm9FyngJ"
+              + "f96jVPysN6FzYRUB5Fuys57P+nu0RMoLGkHmQhp4L5hgNJTBy1SRnXukoIgJ"
+              + "2Ra3EBQ7dBrzuWW1ycwU5acfOoxfcVqgXkiXaxgvujFChZGWT6djbnbbzlMm"
+              + "sMKr6POKChEPWo1HJXXz1OaPsd75JA8bImgnrHhB3dHhD2wIqzQrtTxvraqz"
+              + "ZWWR2xYZPltzBSlaAdn8Hf0GGBoMhutb3tJLzbAX0cybzJkBEAABAQAAAAAA"
+              + "AAAAAAAAAP/Y/+AAEEpGSUYAAQEAAAEAAQAA/9sAQwAKBwcIBwYKCAgICwoK"
+              + "Cw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYpNCkhIjBBMTQ5Oz4+PiUuRElD"
+              + "PEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7"
+              + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7/8AAEQgAkAB4AwEiAAIR"
+              + "AQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIB"
+              + "AwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHw"
+              + "JDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVm"
+              + "Z2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4"
+              + "ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5+v/EAB8B"
+              + "AAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQE"
+              + "AAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDTh"
+              + "JfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2"
+              + "d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXG"
+              + "x8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5+v/aAAwDAQACEQMRAD8A"
+              + "9moqtf30Gm2cl3cvtijGSa4a++LNlGStlZvKR0ZuBWkKU6nwomU4x3PQqK8g"
+              + "uPinrEzYhhihX86ns/Ffia/XzElJUHOV4/rW/wBUqJXlZEe2i9j1iivMP+Ex"
+              + "1q3+/KCw6gip4PiXdREC5tUkHcrwaTwlVbK4e1iekUVzmheNdO1ycWyK8U5G"
+              + "drf410QOa55RcXaSNE09ULRRRUjCiiigAooooAKKKKAOY+IblfCN1g9cA/rX"
+              + "h1fQPiXT4dU0o2dwXEcrclCARgE8ZB9K4J/AGkKeJr38ZU/+Ir0MLiIUoNSO"
+              + "erTlJ3R54v3hXpfg3UdNGmrHPMsToOc9+KrQeBdAd2SS7vkYdPnX/wCIqy3g"
+              + "fRoThb+9GP8AaQ/+yVdavRqxs2yYU5wdzH164t57+V7XHlZOCOh5rn5n5Ndr"
+              + "J4U0xBt/tC8x16p/8RTP+EK0uRQ32q9IPfzE/wDiKuGKpRSSYnSm3c5/wjP5"
+              + "XiKFywUDqScelevR6/pCR4k1S0DDqPOXI/WvPLjwdplpbtPG9zI6so2yspU5"
+              + "YDoFHrW7pOmRWpEiqVyuPlHH41xYmPgpPmibU4uKszqY9f0aZtseq2bN6eeu"
+              + "f51fVldQyMGU9CDkGueMCOpxtYe3NYWoabJJOZrWV7V1yFe1cxnH1HX8a57G"
+              + "lz0CiuFg8U6rpjql2PtkXTMgCv8Agw4/MfjXU6VrthrCH7NKRIoy8LjDr+Hp"
+              + "7jIosFzRooopDCiiigClqXKRD1c/+gtWPLFitnUfuRH/AG//AGUiqDKGFAzA"
+              + "mFzG7rGhAJJyB604XtzGGjeAuD3GR2x260t1fTJf3EChAsLKo+XOcorZP/fV"
+              + "Qm8lPXZ/3yKLCJDPIBsjUjIHUewFWoYWS2jDDBArPN1IQR8o/wCAirdvcERw"
+              + "u33ZYkdgOgLKCcfnRYBL0f8AEvmz6x/+jUqxbzyCLCKoC92NRaiMWLkHhmj/"
+              + "AB+dTWlarutdoIXI64oQETXJ25MbA9DsolCEY4zjpVswL5QXgMB1xWZMRDIy"
+              + "woJn6HnAWmIzb+GZyyIisD0Vl4Nc5I0ulXSO8zQtnMTrkGM/71dVNpufnMkm"
+              + "7Odwfmqd5CGi8tuQB0b5v51SEzf8M+Kl1QixvdqXoHysOFmA7j0PqPxHoOlr"
+              + "xm5DROrRkxvGQVZOCpHQivSPCfiEa9px80gXlvhZ1Hf0Yex/mDRKNtQTN6ii"
+              + "ioKKmoD9zGfSVf1OP61QrUuovOgZM4PBB9CDkH865PxJrVx4d057yS0inAcI"
+              + "qq5TJJ+hoAqXg/4m9/8A9dU/9FR1CRUGlan/AG7Fcal9n+z+dNjy9+/btRV6"
+              + "4GemelWiKoRHVuIf6Ha/9e0X/oC1VIrIt/FtxNGsFtoxk+zoITI1zhWKjbn7"
+              + "vt0zSYzfvJSLAIennIB+p/pWtZy4hXmuQa71fUzGhtre1jR920MXLHGMk+2T"
+              + "6da1oZb22ULM6FDwGCkHNFhGzNqCbjAmXkPGF7VJFAkEQHBNQWkMUcQIwc85"
+              + "9fepJJeOtNIVyK4bg1jXjda0LiTg1k3b9atEsxr3qai0LWDoOvQXpYiEny5x"
+              + "6oep/Dg/hT7s9ayLoZVs1VriPeQcjIorC8F37ah4Vs3kbdLCvkyexXjn3xg/"
+              + "jRWBqb1ee/FqYLpun24P+snLMPoOK9Crzb4uKQumSfwl2H44qo7iexB4JQHR"
+              + "wCMj7Q39K2roRRXTkqPLU8iuB8NFl8S6ftdgrSHIycH5T2rvb8b2uap6MS1R"
+              + "DJcWsq7YUCt65J4rA0FUCHKjh2/9CNYfjDUSkS2lskrlHDTSR/8ALPjocUaH"
+              + "4msUtVjCM0qLyqkAH8TyKSBnoELoOgFJf3VoITFcTBNy546gevtzXM6Rqd3f"
+              + "akWadyigsYw3y+gAH410O/PDZHHcU7E3LWnXED2SC2nE0ajG4HJ/GpJJeOtY"
+              + "lxYpJdxXMcssLxkE+SwXdj14qrf6jrP22SK0t4RFkFZZMYx/n8aANieXg1mX"
+              + "MnWla5lKRCSMFmB8xoz8qHHvzg1TnlzVIRTuW61l3MyQRSTuNwjXdt9T2FXZ"
+              + "3zWfcRpPG8Mn3JBtJ9PQ/nVCO7+Dl49z4f1BJG3Mt6XJ/wB5V/woqD4LwvDp"
+              + "urK45W5VT9QtFYPc1Wx6VXDfFi0M3hmG6A5trhSfoRj/AAruaz9d01dY0O80"
+              + "9v8AlvEVX2bt+uKFowZ4z4Zbd4h04/8ATRv/AEBq7+T53ufrXnXhffF4ls4J"
+              + "QVkildWB7EKwNehwnfLcD/aFXLcUThGs5bDUpYrgFWZ2dGHR1J6ip57C0voR"
+              + "HcQq6htwI+Ug4xkEVo+MJ0jksrYA+ZuMhPouMfzP6VnQyEqKqOqJejMmfSr/"
+              + "AE8NNbzC6hjG7aQVlA/kcVueFtR+12Mrpceagk4Abdt4/rUiMeOeaqS6UhuV"
+              + "ubSaWymxtdrbC+YvoR6+9FhHRPcCNGaRgiqNzFjgAVmya/pYkZftSnH8QQlT"
+              + "9D3rmdbefT4o7KO6ne3ky+yV9xBB9euO+Kw2mfruNAj0OW8t/K837TB5eM7/"
+              + "ADBjFVp3IAOQQwyCDkEexrz95W9vrirula1LYyiOQu9s2Q0YPT3GehpgdJK2"
+              + "apzt8hottQgv1k8pZEeMZIYg5GcZyKjuFkkKQxKXklYKijqSeAKdwPUvhdbe"
+              + "X4ZmutpH2y7eUZ9AAv8ANTRXSaJpqaPotnpyYP2eIKxHdv4j+JyaKwe5qi/R"
+              + "RRSGeaeJ/Dx03x7Yavbr/o967eZj+GQI38xz+dXdPffczD1cVu+Lzi0tT6Tj"
+              + "/wBBNc3oz7r5x6uKroIwPFt5BeazFbQKGa1BWSQdycfL+GP1qCCPgU3+yprC"
+              + "/ltrpcSqxOezAnhge9aMNv04rRaIh7jEiNSSFLeF55c7I1LNjrgVcjt/alu9"
+              + "O+12U1uSUEqFNyjlcjrRcVjzzVL6bU5xJIioqjCIo4Uf1NUDEfStiXTLizuH"
+              + "tboL5qc7l6OvZhTTZ+1K4WMZoSe1NFuSelbP2M9xT47As2FXJp3FYqaUptJ2"
+              + "fZu3IVwSR1r0L4f6FHqmsf2w8bC3sjhA2CGlx29duc/UisHQ/DlzreoiwtPl"
+              + "24NxPjKwL/Vj2H9K9m07T7bStPhsbOPy4IV2qO/uT6knkmoky4otUUUVBYUU"
+              + "UUAc54yP+hWv/XwB+hrntOTyNbSP+84rs9Z04ajaqu7a8bh0OMjI9a5O6gvo"
+              + "b3zjZAuDwyOMfryKaegEHjZTYva6qV8yFf3MqKMsueQw9uDmq+nPZahGJLSd"
+              + "Hz2zyKsXEOpagyC4IWOM5WNOmfUnuaxtT8NOJPtFoGt5uu6PjP4U0xNHSx2b"
+              + "jtmrC2p/u1xEOr+J9MO1sXCj++OavxeO9Tj4m0vJ9jTuI09c8NrqUavGfKuI"
+              + "/wDVyhc49iO4rnToV/A/lXCI5xkPGCFI/HvWhL491BhiLSufc1l6hrXiTVZQ"
+              + "IALaPGOFyfc0gHzadBZxGW9nSFBydxp+nafPrEii0RrOyP3rmRfncf7Cn+Z/"
+              + "Wo9K8NXEl0Lm+L3EgOQZTux9K7W0s5BgYNFwsbOg2tlpVilnYxCOMHJ7s7Hq"
+              + "xPc1sqcjNZNnbsuM1qoMLUlD6KKKACiiigBCM1E9tG55UVNRQBWNlF2UVC+m"
+              + "xP8Aw1fooAx5NDgfqg/KoG8N2p/5ZL+Vb9FAHPjw1ag/6pfyqZNBt06IPyra"
+              + "ooAzU0qJOiirCWcadBVqigBixhegp1LRQAUUUUAf/9mJATgEEwECACIFAlOk"
+              + "xL4CGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEEKNuDRspWAJhi8I"
+              + "AKhIemGlaKtuZxBA4bQcJOy/ZdGJriJuu3OQl2m6CAwxaGMncpxHFVTT6GqI"
+              + "Vu4/b4SSwYP1pI24MqAkdEudjFSi15ByogPFpUoDJC44zrO64b/mv3L5iq1C"
+              + "PY+VvgLMAdvA3Tsoj/rNYlD0fieBa9EF8BtoAkaA4X6pihNPGsVe0AxlJhQw"
+              + "eMgLXwTjllJm1iWa/fEQvv5Uk01gzayH1TIwkNAJ0E8s6Ontu2szUHjFGRNA"
+              + "llR5OJzt/loo9p53zWddFfxlCfn2w+smHyB4i+FfpQfFSMLnwew7wncHs6XE"
+              + "PevLPcW66T3w2/oMd0fC7GwhnCiebDYjl8ymF+4b0N65AQ0EU6S6gwEIAOAC"
+              + "NRzXH0dc5wwkucFdTMs1nxr16y+Kk3zF3R21OkHLHazXVC7ZP2HurTFGd5VP"
+              + "Yd+vv0CrYHCjjMu0lIeMfTlpJswvJRBxVw8vIVLpOSqxtJS+zysE8/LpKw6i"
+              + "ti51ydalhm6VYGPm+OAoAAO1pLriwR132caoye5vqxGKEUCmkaNLl8LCljyH"
+              + "kMgL5nQr+7cerTcGd2MaC8Y5vQuZBpVVBZcVt004iP3bCJu2l2RKskIoSysC"
+              + "68bqV4XLMnoVeM97VPdwdb0Y7tGXCW8YodN8ni43YOaQxfr7fHx8nyzQ5S8w"
+              + "a701GKWcQqCb0DR1ngCRAgWLzj8HDlZoofPL8d0AEQEAAYkBHwQYAQIACQUC"
+              + "U6S6gwIbDAAKCRBCjbg0bKVgCWPSB/wN9Z5ayWiox5xxouAQv4W2JZGPiqk8"
+              + "nFF5fzSgQxV4Xo63IaC1bD8411pgRlj1aWtt8pvWjEW9WWxvyPnkz0xldErb"
+              + "NRZ9482TknY0dsrbmg6jwLOlNvLhLVhWUWt+DkH20daVCADV/0p2/2OPodn+"
+              + "MYnueL5ljoJxzTO84WMz1u7qumMdX4EcLAFblelmPsGiNsnGabc148+TgYZI"
+              + "1fBucn5Xrk4fxVCuqa8QjOa37aHHT5Li/xGIDCbtCqPPIi7M7O1yq8gXLWP9"
+              + "TV7nsu99t4EiZT4zov9rCS+tgvBiFrRqsHL37PGrS27s+gMw3GR7F6BiDiqa"
+              + "0GvLdt0Lx24c"
+            );
+
+        private static readonly byte[] attrLongLength = Base64.Decode(
+                "mQENBEGz0vIBCADLb2Sb5QbOhRIzfOg3u9F338gK1XZWJG8JwXP8DSGbQEof"
+              + "0+YoT/7bA+3h1ljh3LG0m8JUEdolrxLz/8Mguu2TA2UQiMwRaRChSVvBgkCR"
+              + "Ykr97+kClNgmi+PLuUN1z4tspqdE761nRVvUl2x4XvLTJ21hU5eXGGsC+qFP"
+              + "4Efe8B5kH+FexAfnFPPzou3GjbDbYv4CYi0pyhTxmauxyJyQrQ/MQUt0RFRk"
+              + "L8qCzWCR2BmH3jM3M0Wt0oKn8C8+fWItUh5U9fzv/K9GeO/SV8+zdL4MrdqD"
+              + "stgqXNs27H+WeIgbXlUGIs0mONE6TtKZ5PXG5zFM1bz1vDdAYbY4eUWDABEB"
+              + "AAGJAhwEHwEIAAYFAlLd55oACgkQ5ppjUk3RnxANSBAAqzYF/9hu7x7wtmi7"
+              + "ScmIal6bXP14ZJaRVibMnAPEPIHAULPVa8x9QX/fGW8px5tK9YU41wigLXe6"
+              + "3eC5MOLc+wkouELsBeeA3zap51/5HhsuHq5AYtL2tigce9epYUVNV9LaZd2U"
+              + "vQOQ6RqyTMhSADN9mD0kR+Nu1+ns7Ur7qAq6UI39hFIGKPoZQ61pTrVsi8N7"
+              + "GxHoNwa1FAxm0Dm4XvyiJHPOYs0K4OnNWLKLCcSVOx453Zj3JnllRrCFLpIt"
+              + "H27jAxcbGStxWpJvlVMSylcP/x0ATjGfp+kSv2TpU2wK0W5iUtrn30W+WZp4"
+              + "+BIXL0NSi4XPksoUoM9dOTsOCPh/ntiWJBlzIdhQuxgcwymoYnaAG0ermI+R"
+              + "djB0gCj0AfMDZEOW+thFKg1kEkYrUnAISNDt+VZNUtk26tJ7PDitC9EY6IA6"
+              + "vbKeh47LmqpyK3gqQiIA/XuWhdUOr1Wv3H8qxumFjxQQh9sr72IbWFJ+tSNl"
+              + "UtrohK7N6CoJQidkj2qFsuGLcFKypAdS7Y0s0t9uOYJLwj1c+2KG0mrA2PvW"
+              + "1vng9mMN6AHIx9oRSwQc1+OV29ws2hfNB3JQnpdzBYAy8C5haUWG7E7WFg+j"
+              + "pNpeREVX0S+1ibmWDVs+trSQI8hd58j91Kc2YvwE13YigC9nlU2R853Gsox4"
+              + "oazn75iJAhwEHwEIAAYFAlMkBMIACgkQcssEwQwvQ5L2yxAAmND9w3OZsJpF"
+              + "tTAJFpfg8Bacy0Xs/+LipA1hB8vG+mvaiedcqc5KTpuFQ4bffH1swMRjXAM7"
+              + "ZP/u/6qX2LL9kjxCtwDUjDT8YcphTnRxSu5Jv3w4Rf0zWIRWHhnbswiBuGwE"
+              + "zQN8V20AYxfZ+ffkR0wymm/y8qLQ1oNynweijXHSlaG/sVmvDxkuc77n4hLi"
+              + "4UVQiSAP7dRIkcOh6QCBW4TxoZkDfxIhASFQWl1paCagO1rwyo7YY42O4c16"
+              + "+UZBMZtWTvRO2rThz1g9SxAyx8FZ7SxMv140C7VGQmdag97dA1WgBOCuLzLi"
+              + "cYT+o/bL9vpFXSI7LVflQEqauzL4fs2X8ggckoI4lkjcDe8DhiDmCoju5Lat"
+              + "Q/7DqV8T6z/Gv0sK2hqKr4ULC3By4N11WDCg6wXa72tMQoFBT1vOC+UzLHOj"
+              + "vgWBJKE7q3E7kFfq22D0ZX0BPTYy2mcrghMzvvOe74Dx495zlUJhtBfr8MC2"
+              + "uPnjsv6PjCYAaomQcvvI0o/5k8JIFi1P0pwLM5VjfujdAuCpAwQuy9AeGlz2"
+              + "TEuZZlWBZuyBqZ7JyHx5xz1aVXbY7kofqO+njyyZ+MakZRLYpBI+B/8KomQP"
+              + "pqWVARw4uPAXVTd1fjW2CTQtt7Ia6BRWMSblxTv3VWosTSgPnCXmzYEpGvCL"
+              + "bIauL8UEhzS0JVBHUCBHbG9iYWwgRGlyZWN0b3J5IFZlcmlmaWNhdGlvbiBL"
+              + "ZXmJAV4EEAECAEAFAkJRtHAHCwkIBwMCCgIZARkYbGRhcDovL2tleXNlcnZl"
+              + "ci5wZ3AuY29tBRsDAAAAAxYCAQUeAQAAAAQVCAIKABIJEJcQuJvKV618B2VH"
+              + "UEcAAQH35ggAnVHdAh2KqrvwSnPos73YdlVbeF9Lcbxs4oYPDCk6AHiDpjr2"
+              + "nxu48i1BiLea7aTEEwwAkcIa/3lCLP02NjGXq5gRnWpW/d0xtsaDDj8yYWus"
+              + "WGhEJsUlrq5Cz2KjwxNQHXRhHXEDR8vq9uzw5EjCB0u69vlwNmo8+fa17YMN"
+              + "VdXaXsmXJlJciVHazdvGoscTzZOuKDHdaJmY8nJcCydk4qsFOiGOcFm5UOKP"
+              + "nzdBh31NKglqw/xh+1nTA2z5orsY4jVFIB6sWqutIcVQYt/J78diAKFemkEO"
+              + "Qe0kU5JZrY34E8pp4BmS6mfPyr8NtHFfMOAE4m8acFeaZK1X6+uW57QpRE5S"
+              + "IEtTMSA8ZG8tbm90LXJlcGx5QGtleXNlcnZlcjEucGdwLmNvbT6JAVMEEAEC"
+              + "AD0FAkmgVoIHCwkIBwMCChkYbGRhcDovL2tleXNlcnZlci5wZ3AuY29tBRsD"
+              + "AAAAAxYCAQUeAQAAAAQVCAIKAAoJEJcQuJvKV618t6wH/1RFTp9Z7QUZFR5h"
+              + "r8eHFWhPoeTCMXF3Vikgw2mZsjN43ZyzpxrIdUwwHROQXn1BzAvOS0rGNiDs"
+              + "fOOmQFulz+Oc14xxGox2TZbdnDnXEb8ReZnimQCWYERfpRtY6GSY7uWzNjG2"
+              + "dLB1y3XfsOBG+QqTULSJSZqRYD+2IpwPlAdl6qncqRvFzGcPXPIp0RS6nvoP"
+              + "Jfe0u2sETDRAUDwivr7ZU/xCA12txELhcsvMQP0fy0CRNgN+pQ2b6iBL2x1l"
+              + "jHgSG1r3g3gQjHEk3UCTEKHq9+mFhd/Gi0RXz6i1AmrvW4pKhbtN76WrXeF+"
+              + "FXTsB09f1xKnWi4c303Ms1tIJQC0KUROUi1LUzIgPGRvLW5vdC1yZXBseUBr"
+              + "ZXlzZXJ2ZXIyLnBncC5jb20+iQFTBBABAgA9BQJJoFabBwsJCAcDAgoZGGxk"
+              + "YXA6Ly9rZXlzZXJ2ZXIucGdwLmNvbQUbAwAAAAMWAgEFHgEAAAAEFQgCCgAK"
+              + "CRCXELibyletfBwzB/41/OkBDVLgEYnGJ78rKHLtgMdRfrL8gmZn9KhMi44H"
+              + "nlFl1NAgi1yuWA2wC8DziVKIiu8YCaCVP0FFXuBK1BF8uZDRp8lZuT3Isf0/"
+              + "4DX4yuvZwY5nmtDu3qXrjZ7bZi1W2A8c9Hgc+5A30R9PtiYy5Lz2m8xZl4P6"
+              + "wDrYCQA2RLfzGC887bIPBK/tvXTRUFZfj2X1o/q4pr8z4NJTaFUl/XrseGcJ"
+              + "R2PP3S2/fU5LErqLJhlj690xofRkf9oYrUiyyb1/UbWmNJsOHSHyy8FEc9lv"
+              + "lSJIa39niSQKK6I0Mh1LheXNL7aG152KkXiH0mi6bH4EOzaTR7dfLey3o9Ph"
+              + "0cye/wAADVkBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQEAAAEAAQAA"
+              + "/9sAQwAKBwcIBwYKCAgICwoKCw4YEA4NDQ4dFRYRGCMfJSQiHyIhJis3LyYp"
+              + "NCkhIjBBMTQ5Oz4+PiUuRElDPEg3PT47/9sAQwEKCwsODQ4cEBAcOygiKDs7"
+              + "Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7"
+              + "Ozs7/8AAEQgAkAB4AwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAAB"
+              + "AgMEBQYHCAkKC//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNR"
+              + "YQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNE"
+              + "RUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeY"
+              + "mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn"
+              + "6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkK"
+              + "C//EALURAAIBAgQEAwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRC"
+              + "kaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpDREVGR0hJSlNU"
+              + "VVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWm"
+              + "p6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX2"
+              + "9/j5+v/aAAwDAQACEQMRAD8A9moqtf30Gm2cl3cvtijGSa4a++LNlGStlZvK"
+              + "R0ZuBWkKU6nwomU4x3PQqK8guPinrEzYhhihX86ns/Ffia/XzElJUHOV4/rW"
+              + "/wBUqJXlZEe2i9j1iivMP+Ex1q3+/KCw6gip4PiXdREC5tUkHcrwaTwlVbK4"
+              + "e1iekUVzmheNdO1ycWyK8U5Gdrf410QOa55RcXaSNE09ULRRRUjCiiigAooo"
+              + "oAKKKKAOY+IblfCN1g9cA/rXh1fQPiXT4dU0o2dwXEcrclCARgE8ZB9K4J/A"
+              + "GkKeJr38ZU/+Ir0MLiIUoNSOerTlJ3R54v3hXpfg3UdNGmrHPMsToOc9+KrQ"
+              + "eBdAd2SS7vkYdPnX/wCIqy3gfRoThb+9GP8AaQ/+yVdavRqxs2yYU5wdzH16"
+              + "4t57+V7XHlZOCOh5rn5n5NdrJ4U0xBt/tC8x16p/8RTP+EK0uRQ32q9IPfzE"
+              + "/wDiKuGKpRSSYnSm3c5/wjP5XiKFywUDqScelevR6/pCR4k1S0DDqPOXI/Wv"
+              + "PLjwdplpbtPG9zI6so2yspU5YDoFHrW7pOmRWpEiqVyuPlHH41xYmPgpPmib"
+              + "U4uKszqY9f0aZtseq2bN6eeuf51fVldQyMGU9CDkGueMCOpxtYe3NYWoabJJ"
+              + "OZrWV7V1yFe1cxnH1HX8a57Glz0CiuFg8U6rpjql2PtkXTMgCv8Agw4/MfjX"
+              + "U6VrthrCH7NKRIoy8LjDr+Hp7jIosFzRooopDCiiigClqXKRD1c/+gtWPLFi"
+              + "tnUfuRH/AG//AGUiqDKGFAzAmFzG7rGhAJJyB604XtzGGjeAuD3GR2x260t1"
+              + "fTJf3EChAsLKo+XOcorZP/fVQm8lPXZ/3yKLCJDPIBsjUjIHUewFWoYWS2jD"
+              + "DBArPN1IQR8o/wCAirdvcERwu33ZYkdgOgLKCcfnRYBL0f8AEvmz6x/+jUqx"
+              + "bzyCLCKoC92NRaiMWLkHhmj/AB+dTWlarutdoIXI64oQETXJ25MbA9DsolCE"
+              + "Y4zjpVswL5QXgMB1xWZMRDIywoJn6HnAWmIzb+GZyyIisD0Vl4Nc5I0ulXSO"
+              + "8zQtnMTrkGM/71dVNpufnMkm7Odwfmqd5CGi8tuQB0b5v51SEzf8M+Kl1Qix"
+              + "vdqXoHysOFmA7j0PqPxHoOlrxm5DROrRkxvGQVZOCpHQivSPCfiEa9px80gX"
+              + "lvhZ1Hf0Yex/mDRKNtQTN6iiioKKmoD9zGfSVf1OP61QrUuovOgZM4PBB9CD"
+              + "kH865PxJrVx4d057yS0inAcIqq5TJJ+hoAqXg/4m9/8A9dU/9FR1CRUGlan/"
+              + "AG7Fcal9n+z+dNjy9+/btRV64GemelWiKoRHVuIf6Ha/9e0X/oC1VIrIt/Ft"
+              + "xNGsFtoxk+zoITI1zhWKjbn7vt0zSYzfvJSLAIennIB+p/pWtZy4hXmuQa71"
+              + "fUzGhtre1jR920MXLHGMk+2T6da1oZb22ULM6FDwGCkHNFhGzNqCbjAmXkPG"
+              + "F7VJFAkEQHBNQWkMUcQIwc859fepJJeOtNIVyK4bg1jXjda0LiTg1k3b9atE"
+              + "sxr3qai0LWDoOvQXpYiEny5x6oep/Dg/hT7s9ayLoZVs1VriPeQcjIorC8F3"
+              + "7ah4Vs3kbdLCvkyexXjn3xg/jRWBqb1ee/FqYLpun24P+snLMPoOK9Crzb4u"
+              + "KQumSfwl2H44qo7iexB4JQHRwCMj7Q39K2roRRXTkqPLU8iuB8NFl8S6ftdg"
+              + "rSHIycH5T2rvb8b2uap6MS1RDJcWsq7YUCt65J4rA0FUCHKjh2/9CNYfjDUS"
+              + "kS2lskrlHDTSR/8ALPjocUaH4msUtVjCM0qLyqkAH8TyKSBnoELoOgFJf3Vo"
+              + "ITFcTBNy546gevtzXM6Rqd3fakWadyigsYw3y+gAH410O/PDZHHcU7E3LWnX"
+              + "ED2SC2nE0ajG4HJ/GpJJeOtYlxYpJdxXMcssLxkE+SwXdj14qrf6jrP22SK0"
+              + "t4RFkFZZMYx/n8aANieXg1mXMnWla5lKRCSMFmB8xoz8qHHvzg1TnlzVIRTu"
+              + "W61l3MyQRSTuNwjXdt9T2FXZ3zWfcRpPG8Mn3JBtJ9PQ/nVCO7+Dl49z4f1B"
+              + "JG3Mt6XJ/wB5V/woqD4LwvDpurK45W5VT9QtFYPc1Wx6VXDfFi0M3hmG6A5t"
+              + "rhSfoRj/AAruaz9d01dY0O809v8AlvEVX2bt+uKFowZ4z4Zbd4h04/8ATRv/"
+              + "AEBq7+T53ufrXnXhffF4ls4JQVkildWB7EKwNehwnfLcD/aFXLcUThGs5bDU"
+              + "pYrgFWZ2dGHR1J6ip57C0voRHcQq6htwI+Ug4xkEVo+MJ0jksrYA+ZuMhPou"
+              + "MfzP6VnQyEqKqOqJejMmfSr/AE8NNbzC6hjG7aQVlA/kcVueFtR+12Mrpcea"
+              + "gk4Abdt4/rUiMeOeaqS6UhuVubSaWymxtdrbC+YvoR6+9FhHRPcCNGaRgiqN"
+              + "zFjgAVmya/pYkZftSnH8QQlT9D3rmdbefT4o7KO6ne3ky+yV9xBB9euO+Kw2"
+              + "mfruNAj0OW8t/K837TB5eM7/ADBjFVp3IAOQQwyCDkEexrz95W9vrirula1L"
+              + "YyiOQu9s2Q0YPT3GehpgdJK2apzt8hottQgv1k8pZEeMZIYg5GcZyKjuFkkK"
+              + "QxKXklYKijqSeAKdwPUvhdbeX4ZmutpH2y7eUZ9AAv8ANTRXSaJpqaPotnpy"
+              + "YP2eIKxHdv4j+JyaKwe5qi/RRRSGeaeJ/Dx03x7Yavbr/o967eZj+GQI38xz"
+              + "+dXdPffczD1cVu+Lzi0tT6Tj/wBBNc3oz7r5x6uKroIwPFt5BeazFbQKGa1B"
+              + "WSQdycfL+GP1qCCPgU3+yprC/ltrpcSqxOezAnhge9aMNv04rRaIh7jEiNSS"
+              + "FLeF55c7I1LNjrgVcjt/alu9O+12U1uSUEqFNyjlcjrRcVjzzVL6bU5xJIio"
+              + "qjCIo4Uf1NUDEfStiXTLizuHtboL5qc7l6OvZhTTZ+1K4WMZoSe1NFuSelbP"
+              + "2M9xT47As2FXJp3FYqaUptJ2fZu3IVwSR1r0L4f6FHqmsf2w8bC3sjhA2CGl"
+              + "x29duc/UisHQ/DlzreoiwtPl24NxPjKwL/Vj2H9K9m07T7bStPhsbOPy4IV2"
+              + "qO/uT6knkmoky4otUUUVBYUUUUAc54yP+hWv/XwB+hrntOTyNbSP+84rs9Z0"
+              + "4ajaqu7a8bh0OMjI9a5O6gvob3zjZAuDwyOMfryKaegEHjZTYva6qV8yFf3M"
+              + "qKMsueQw9uDmq+nPZahGJLSdHz2zyKsXEOpagyC4IWOM5WNOmfUnuaxtT8NO"
+              + "JPtFoGt5uu6PjP4U0xNHSx2bjtmrC2p/u1xEOr+J9MO1sXCj++OavxeO9Tj4"
+              + "m0vJ9jTuI09c8NrqUavGfKuI/wDVyhc49iO4rnToV/A/lXCI5xkPGCFI/HvW"
+              + "hL491BhiLSufc1l6hrXiTVZQIALaPGOFyfc0gHzadBZxGW9nSFBydxp+nafP"
+              + "rEii0RrOyP3rmRfncf7Cn+Z/Wo9K8NXEl0Lm+L3EgOQZTux9K7W0s5BgYNFw"
+              + "sbOg2tlpVilnYxCOMHJ7s7HqxPc1sqcjNZNnbsuM1qoMLUlD6KKKACiiigBC"
+              + "M1E9tG55UVNRQBWNlF2UVC+mxP8Aw1fooAx5NDgfqg/KoG8N2p/5ZL+Vb9FA"
+              + "HPjw1ag/6pfyqZNBt06IPyraooAzU0qJOiirCWcadBVqigBixhegp1LRQAUU"
+              + "UUAf/9mJAVYEEAECADgFAkJRtHAHCwkIBwMCChkYbGRhcDovL2tleXNlcnZl"
+              + "ci5wZ3AuY29tBRsDAAAAAxYCAQUeAQAAAAASCRCXELibyletfAdlR1BHAAEB"
+              + "SBIH/j+RGcMuHmVoZq4+XbmCunnbft4T0Ta4o6mxNkc6wk5P9PpcE9ixztjV"
+              + "ysMmv2i4Y746dCY9B1tfhQW10S39HzrYHh3I4a2wb9zQniZCf1XnbCe1eRss"
+              + "NhTpLVXXnXKEsc9EwD5MtiPICluZIXB08Zx2uJSZ+/i9TqSM5EUuJk+lXqgX"
+              + "GUiTaSXN63I/4BnbFzCw8SaST7d7nok45UC9I/+gcKVO+oYETgrsU7AL6uk1"
+              + "6YD9JpfYZHEFmpYoS+qQ3tLfPCG3gaS/djBZWWkNt5z7e6sbRko49XEj3EUh"
+              + "33HgjrOlL8uJNbhlZ5NeILcxHqGTHji+5wMEDBjfNT/C6m0=");
+
+        public override void PerformTest()
+        {
+            //
+            // RSA tests
+            //
+            PgpSecretKeyRing pgpPriv = new PgpSecretKeyRing(rsaKeyRing);
+            PgpSecretKey secretKey = pgpPriv.GetSecretKey();
+            PgpPrivateKey pgpPrivKey = secretKey.ExtractPrivateKey(rsaPass);
+
+            try
+            {
+                doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+                Fail("RSA wrong key test failed.");
+            }
+            catch (PgpException)
+            {
+                // expected
+            }
+
+            try
+            {
+                doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+                Fail("RSA V3 wrong key test failed.");
+            }
+            catch (PgpException)
+            {
+                // expected
+            }
+
+            //
+            // certifications
+            //
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.KeyRevocation, pgpPrivKey);
+
+            PgpSignature sig = sGen.GenerateCertification(secretKey.PublicKey);
+
+            sig.InitVerify(secretKey.PublicKey);
+
+            if (!sig.VerifyCertification(secretKey.PublicKey))
+            {
+                Fail("revocation verification failed.");
+            }
+
+            PgpSecretKeyRing pgpDSAPriv = new PgpSecretKeyRing(dsaKeyRing);
+            PgpSecretKey secretDSAKey = pgpDSAPriv.GetSecretKey();
+            PgpPrivateKey pgpPrivDSAKey = secretDSAKey.ExtractPrivateKey(dsaPass);
+
+            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+
+            PgpSignatureSubpacketGenerator    unhashedGen = new PgpSignatureSubpacketGenerator();
+            PgpSignatureSubpacketGenerator    hashedGen = new PgpSignatureSubpacketGenerator();
+
+            hashedGen.SetSignatureExpirationTime(false, TEST_EXPIRATION_TIME);
+            hashedGen.SetSignerUserId(true, TEST_USER_ID);
+            hashedGen.SetPreferredCompressionAlgorithms(false, PREFERRED_COMPRESSION_ALGORITHMS);
+            hashedGen.SetPreferredHashAlgorithms(false, PREFERRED_HASH_ALGORITHMS);
+            hashedGen.SetPreferredSymmetricAlgorithms(false, PREFERRED_SYMMETRIC_ALGORITHMS);
+
+            sGen.SetHashedSubpackets(hashedGen.Generate());
+            sGen.SetUnhashedSubpackets(unhashedGen.Generate());
+
+            sig = sGen.GenerateCertification(secretDSAKey.PublicKey, secretKey.PublicKey);
+
+            byte[] sigBytes = sig.GetEncoded();
+
+            PgpObjectFactory f = new PgpObjectFactory(sigBytes);
+
+            sig = ((PgpSignatureList) f.NextPgpObject())[0];
+
+            sig.InitVerify(secretDSAKey.PublicKey);
+
+            if (!sig.VerifyCertification(secretDSAKey.PublicKey, secretKey.PublicKey))
+            {
+                Fail("subkey binding verification failed.");
+            }
+
+            PgpSignatureSubpacketVector hashedPcks = sig.GetHashedSubPackets();
+            PgpSignatureSubpacketVector unhashedPcks = sig.GetUnhashedSubPackets();
+
+            if (hashedPcks.Count != 6)
+            {
+                Fail("wrong number of hashed packets found.");
+            }
+
+            if (unhashedPcks.Count != 1)
+            {
+                Fail("wrong number of unhashed packets found.");
+            }
+
+            if (!hashedPcks.GetSignerUserId().Equals(TEST_USER_ID))
+            {
+                Fail("test userid not matching");
+            }
+
+            if (hashedPcks.GetSignatureExpirationTime() != TEST_EXPIRATION_TIME)
+            {
+                Fail("test signature expiration time not matching");
+            }
+
+            if (unhashedPcks.GetIssuerKeyId() != secretDSAKey.KeyId)
+            {
+                Fail("wrong issuer key ID found in certification");
+            }
+
+            int[] prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
+            preferredAlgorithmCheck("compression", PREFERRED_COMPRESSION_ALGORITHMS, prefAlgs);
+
+            prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
+            preferredAlgorithmCheck("hash", PREFERRED_HASH_ALGORITHMS, prefAlgs);
+
+            prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
+            preferredAlgorithmCheck("symmetric", PREFERRED_SYMMETRIC_ALGORITHMS, prefAlgs);
+
+            SignatureSubpacketTag[] criticalHashed = hashedPcks.GetCriticalTags();
+
+            if (criticalHashed.Length != 1)
+            {
+                Fail("wrong number of critical packets found.");
+            }
+
+            if (criticalHashed[0] != SignatureSubpacketTag.SignerUserId)
+            {
+                Fail("wrong critical packet found in tag list.");
+            }
+
+            //
+            // no packets passed
+            //
+            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+
+            sGen.SetHashedSubpackets(null);
+            sGen.SetUnhashedSubpackets(null);
+
+            sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
+
+            sig.InitVerify(secretDSAKey.PublicKey);
+
+            if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
+            {
+                Fail("subkey binding verification failed.");
+            }
+
+            hashedPcks = sig.GetHashedSubPackets();
+
+            if (hashedPcks.Count != 1)
+            {
+                Fail("found wrong number of hashed packets");
+            }
+
+            unhashedPcks = sig.GetUnhashedSubPackets();
+
+            if (unhashedPcks.Count != 1)
+            {
+                Fail("found wrong number of unhashed packets");
+            }
+
+            try
+            {
+                sig.VerifyCertification(secretKey.PublicKey);
+
+                Fail("failed to detect non-key signature.");
+            }
+            catch (InvalidOperationException)
+            {
+                // expected
+            }
+
+            //
+            // override hash packets
+            //
+            sGen = new PgpSignatureGenerator(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1);
+
+            sGen.InitSign(PgpSignature.SubkeyBinding, pgpPrivDSAKey);
+
+            hashedGen = new PgpSignatureSubpacketGenerator();
+
+            DateTime creationTime = new DateTime(1973, 7, 27);
+            hashedGen.SetSignatureCreationTime(false, creationTime);
+
+            sGen.SetHashedSubpackets(hashedGen.Generate());
+
+            sGen.SetUnhashedSubpackets(null);
+
+            sig = sGen.GenerateCertification(TEST_USER_ID, secretKey.PublicKey);
+
+            sig.InitVerify(secretDSAKey.PublicKey);
+
+            if (!sig.VerifyCertification(TEST_USER_ID, secretKey.PublicKey))
+            {
+                Fail("subkey binding verification failed.");
+            }
+
+            hashedPcks = sig.GetHashedSubPackets();
+
+            if (hashedPcks.Count != 1)
+            {
+                Fail("found wrong number of hashed packets in override test");
+            }
+
+            if (!hashedPcks.HasSubpacket(SignatureSubpacketTag.CreationTime))
+            {
+                Fail("hasSubpacket test for creation time failed");
+            }
+
+            DateTime sigCreationTime = hashedPcks.GetSignatureCreationTime();
+            if (!sigCreationTime.Equals(creationTime))
+            {
+                Fail("creation of overridden date failed.");
+            }
+
+            prefAlgs = hashedPcks.GetPreferredCompressionAlgorithms();
+            preferredAlgorithmCheck("compression", NO_PREFERENCES, prefAlgs);
+
+            prefAlgs = hashedPcks.GetPreferredHashAlgorithms();
+            preferredAlgorithmCheck("hash", NO_PREFERENCES, prefAlgs);
+
+            prefAlgs = hashedPcks.GetPreferredSymmetricAlgorithms();
+            preferredAlgorithmCheck("symmetric", NO_PREFERENCES, prefAlgs);
+
+            if (hashedPcks.GetKeyExpirationTime() != 0)
+            {
+                Fail("unexpected key expiration time found");
+            }
+
+            if (hashedPcks.GetSignatureExpirationTime() != 0)
+            {
+                Fail("unexpected signature expiration time found");
+            }
+
+            if (hashedPcks.GetSignerUserId() != null)
+            {
+                Fail("unexpected signer user ID found");
+            }
+
+            criticalHashed = hashedPcks.GetCriticalTags();
+
+            if (criticalHashed.Length != 0)
+            {
+                Fail("critical packets found when none expected");
+            }
+
+            unhashedPcks = sig.GetUnhashedSubPackets();
+
+            if (unhashedPcks.Count != 1)
+            {
+                Fail("found wrong number of unhashed packets in override test");
+            }
+
+            //
+            // general signatures
+            //
+            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha256, secretKey.PublicKey, pgpPrivKey);
+            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha384, secretKey.PublicKey, pgpPrivKey);
+            doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha512, secretKey.PublicKey, pgpPrivKey);
+            doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+            doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+            doTestTextSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+            doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+            doTestTextSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+
+            //
+            // DSA Tests
+            //
+            pgpPriv = new PgpSecretKeyRing(dsaKeyRing);
+            secretKey = pgpPriv.GetSecretKey();
+            pgpPrivKey = secretKey.ExtractPrivateKey(dsaPass);
+
+            try
+            {
+                doTestSig(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+                Fail("DSA wrong key test failed.");
+            }
+            catch (PgpException)
+            {
+                // expected
+            }
+
+            try
+            {
+                doTestSigV3(PublicKeyAlgorithmTag.RsaGeneral, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+
+                Fail("DSA V3 wrong key test failed.");
+            }
+            catch (PgpException)
+            {
+                // expected
+            }
+
+            doTestSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+            doTestSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey);
+            doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+            doTestTextSig(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+            doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA_WITH_CRLF, TEST_DATA_WITH_CRLF);
+            doTestTextSigV3(PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1, secretKey.PublicKey, pgpPrivKey, TEST_DATA, TEST_DATA_WITH_CRLF);
+
+            // special cases
+            //
+            doTestMissingSubpackets(nullPacketsSubKeyBinding);
+
+            doTestMissingSubpackets(generateV3BinarySig(pgpPrivKey, PublicKeyAlgorithmTag.Dsa, HashAlgorithmTag.Sha1));
+
+            // keyflags
+            doTestKeyFlagsValues();
+
+            // TODO Seems to depend on some other functionality that's yet to be ported
+            //doTestUserAttributeEncoding();
+        }
+
+        //private void doTestUserAttributeEncoding()
+        //{
+        //    PgpPublicKeyRing pkr = new PgpPublicKeyRing(okAttr);
+
+        //    CheckUserAttribute("normal", pkr, pkr.GetPublicKey());
+
+        //    pkr = new PgpPublicKeyRing(attrLongLength);
+
+        //    CheckUserAttribute("long", pkr, pkr.GetPublicKey());
+        //}
+
+        //private void CheckUserAttribute(String type, PgpPublicKeyRing pkr, PgpPublicKey masterPk)
+        //{
+        //    foreach (PgpUserAttributeSubpacketVector attr in pkr.GetPublicKey().GetUserAttributes())
+        //    {
+        //        foreach (PgpSignature sig in masterPk.GetSignaturesForUserAttribute(attr))
+        //        {
+        //            sig.InitVerify(masterPk);
+        //            if (!sig.VerifyCertification(attr, masterPk))
+        //            {
+        //                Fail("user attribute sig failed to verify on " + type);
+        //            }
+        //        }
+        //    }
+        //}
+
+        private void doTestKeyFlagsValues()
+        {
+            checkValue(KeyFlags.CertifyOther, 0x01);
+            checkValue(KeyFlags.SignData, 0x02);
+            checkValue(KeyFlags.EncryptComms, 0x04);
+            checkValue(KeyFlags.EncryptStorage, 0x08);
+            checkValue(KeyFlags.Split, 0x10);
+            checkValue(KeyFlags.Authentication, 0x20);
+            checkValue(KeyFlags.Shared, 0x80);
+
+            // yes this actually happens
+            checkValue(new byte[] { 4, 0, 0, 0 }, 0x04);
+            checkValue(new byte[] { 4, 0, 0 }, 0x04);
+            checkValue(new byte[] { 4, 0 }, 0x04);
+            checkValue(new byte[] { 4 }, 0x04);
+        }
+
+        private void checkValue(int flag, int val)
+        {
+            KeyFlags f = new KeyFlags(true, flag);
+
+            if (f.Flags != val)
+            {
+                Fail("flag value mismatch");
+            }
+        }
+
+        private void checkValue(byte[] flag, int val)
+        {
+            KeyFlags f = new KeyFlags(true, flag);
+
+            if (f.Flags != val)
+            {
+                Fail("flag value mismatch");
+            }
+        }
+
+        private void doTestMissingSubpackets(byte[] signature)
+        {
+            PgpObjectFactory f = new PgpObjectFactory(signature);
+            object obj = f.NextPgpObject();
+
+            while (!(obj is PgpSignatureList))
+            {
+                obj = f.NextPgpObject();
+                if (obj is PgpLiteralData)
+                {
+                    Stream input = ((PgpLiteralData)obj).GetDataStream();
+                    Streams.Drain(input);
+                }
+            }
+
+            PgpSignature sig = ((PgpSignatureList)obj)[0];
+
+            if (sig.Version > 3)
+            {
+                PgpSignatureSubpacketVector v = sig.GetHashedSubPackets();
+
+                if (v.GetKeyExpirationTime() != 0)
+                {
+                    Fail("key expiration time not zero for missing subpackets");
+                }
+
+                if (!sig.HasSubpackets)
+                {
+                    Fail("HasSubpackets property was false with packets");
+                }
+            }
+            else
+            {
+                if (sig.GetHashedSubPackets() != null)
+                {
+                    Fail("hashed sub packets found when none expected");
+                }
+
+                if (sig.GetUnhashedSubPackets() != null)
+                {
+                    Fail("unhashed sub packets found when none expected");
+                }
+
+                if (sig.HasSubpackets)
+                {
+                    Fail("HasSubpackets property was true with no packets");
+                }
+            }
+        }
+
+        private void preferredAlgorithmCheck(
+            string	type,
+            int[]	expected,
+            int[]	prefAlgs)
+        {
+            if (expected == null)
+            {
+                if (prefAlgs != null)
+                {
+                    Fail("preferences for " + type + " found when none expected");
+                }
+            }
+            else
+            {
+                if (prefAlgs.Length != expected.Length)
+                {
+                    Fail("wrong number of preferred " + type + " algorithms found");
+                }
+
+                for (int i = 0; i != expected.Length; i++)
+                {
+                    if (expected[i] != prefAlgs[i])
+                    {
+                        Fail("wrong algorithm found for " + type + ": expected " + expected[i] + " got " + prefAlgs);
+                    }
+                }
+            }
+        }
+
+        private void doTestSig(
+            PublicKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            PgpPublicKey			pubKey,
+            PgpPrivateKey			privKey)
+        {
+            MemoryStream bOut = new MemoryStream();
+            MemoryStream testIn = new MemoryStream(TEST_DATA, false);
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, hashAlgorithm);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, privKey);
+            sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            Stream lOut = lGen.Open(
+                new UncloseableStream(bOut),
+                PgpLiteralData.Binary,
+                "_CONSOLE",
+                TEST_DATA.Length * 2,
+                DateTime.UtcNow);
+
+            int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
+            sGen.Update(TEST_DATA);
+
+            lGen.Close();
+
+            sGen.Generate().Encode(bOut);
+
+            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, TEST_DATA);
+        }
+
+        private void doTestTextSig(
+            PublicKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            PgpPublicKey			pubKey,
+            PgpPrivateKey			privKey,
+            byte[]					data,
+            byte[]					canonicalData)
+        {
+            PgpSignatureGenerator sGen = new PgpSignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
+            MemoryStream bOut = new MemoryStream();
+            MemoryStream testIn = new MemoryStream(data, false);
+            DateTime creationTime = DateTime.UtcNow;
+
+            sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
+            sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            Stream lOut = lGen.Open(
+                new UncloseableStream(bOut),
+                PgpLiteralData.Text,
+                "_CONSOLE",
+                data.Length * 2,
+                creationTime);
+
+            int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Write(data, 0, data.Length);
+            sGen.Update(data);
+
+            lGen.Close();
+
+            PgpSignature sig = sGen.Generate();
+
+            if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
+            {
+                Fail("creation time not set in v4 signature");
+            }
+
+            sig.Encode(bOut);
+
+            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
+        }
+
+        private void doTestSigV3(
+            PublicKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            PgpPublicKey			pubKey,
+            PgpPrivateKey			privKey)
+        {
+            byte[] bytes = generateV3BinarySig(privKey, encAlgorithm, hashAlgorithm);
+
+            verifySignature(bytes, hashAlgorithm, pubKey, TEST_DATA);
+        }
+
+        private byte[] generateV3BinarySig(
+            PgpPrivateKey			privKey,
+            PublicKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag		hashAlgorithm)
+        {
+            MemoryStream bOut = new MemoryStream();
+            MemoryStream testIn = new MemoryStream(TEST_DATA, false);
+            PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, hashAlgorithm);
+
+            sGen.InitSign(PgpSignature.BinaryDocument, privKey);
+            sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            Stream lOut = lGen.Open(
+                new UncloseableStream(bOut),
+                PgpLiteralData.Binary,
+                "_CONSOLE",
+                TEST_DATA.Length * 2,
+                DateTime.UtcNow);
+
+            int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Write(TEST_DATA, 0, TEST_DATA.Length);
+            sGen.Update(TEST_DATA);
+
+            lGen.Close();
+
+            sGen.Generate().Encode(bOut);
+
+            return bOut.ToArray();
+        }
+
+        private void doTestTextSigV3(
+            PublicKeyAlgorithmTag	encAlgorithm,
+            HashAlgorithmTag		hashAlgorithm,
+            PgpPublicKey			pubKey,
+            PgpPrivateKey			privKey,
+            byte[]					data,
+            byte[]					canonicalData)
+        {
+            PgpV3SignatureGenerator sGen = new PgpV3SignatureGenerator(encAlgorithm, HashAlgorithmTag.Sha1);
+            MemoryStream bOut = new MemoryStream();
+            MemoryStream testIn = new MemoryStream(data, false);
+
+            sGen.InitSign(PgpSignature.CanonicalTextDocument, privKey);
+            sGen.GenerateOnePassVersion(false).Encode(bOut);
+
+            PgpLiteralDataGenerator lGen = new PgpLiteralDataGenerator();
+            Stream lOut = lGen.Open(
+                new UncloseableStream(bOut),
+                PgpLiteralData.Text,
+                "_CONSOLE",
+                data.Length * 2,
+                DateTime.UtcNow);
+
+            int ch;
+            while ((ch = testIn.ReadByte()) >= 0)
+            {
+                lOut.WriteByte((byte)ch);
+                sGen.Update((byte)ch);
+            }
+
+            lOut.Write(data, 0, data.Length);
+            sGen.Update(data);
+
+            lGen.Close();
+
+            PgpSignature sig = sGen.Generate();
+
+            if (sig.CreationTime == DateTimeUtilities.UnixMsToDateTime(0))
+            {
+                Fail("creation time not set in v3 signature");
+            }
+
+            sig.Encode(bOut);
+
+            verifySignature(bOut.ToArray(), hashAlgorithm, pubKey, canonicalData);
+        }
+
+        private void verifySignature(
+            byte[] encodedSig,
+            HashAlgorithmTag hashAlgorithm,
+            PgpPublicKey pubKey,
+            byte[] original)
+        {
+            PgpObjectFactory        pgpFact = new PgpObjectFactory(encodedSig);
+            PgpOnePassSignatureList p1 = (PgpOnePassSignatureList)pgpFact.NextPgpObject();
+            PgpOnePassSignature     ops = p1[0];
+            PgpLiteralData          p2 = (PgpLiteralData)pgpFact.NextPgpObject();
+            Stream					dIn = p2.GetInputStream();
+
+            ops.InitVerify(pubKey);
+
+            int ch;
+            while ((ch = dIn.ReadByte()) >= 0)
+            {
+                ops.Update((byte)ch);
+            }
+
+            PgpSignatureList p3 = (PgpSignatureList)pgpFact.NextPgpObject();
+            PgpSignature sig = p3[0];
+
+            DateTime creationTime = sig.CreationTime;
+
+            // Check creationTime is recent
+            if (creationTime.CompareTo(DateTime.UtcNow) > 0
+                || creationTime.CompareTo(DateTime.UtcNow.AddMinutes(-10)) < 0)
+            {
+                Fail("bad creation time in signature: " + creationTime);
+            }
+
+            if (sig.KeyId != pubKey.KeyId)
+            {
+                Fail("key id mismatch in signature");
+            }
+
+            if (!ops.Verify(sig))
+            {
+                Fail("Failed generated signature check - " + hashAlgorithm);
+            }
+
+            sig.InitVerify(pubKey);
+
+            for (int i = 0; i != original.Length; i++)
+            {
+                sig.Update(original[i]);
+            }
+
+            sig.Update(original);
+
+            if (!sig.Verify())
+            {
+                Fail("Failed generated signature check against original data");
+            }
+        }
+
+        public override string Name
+        {
+            get { return "PGPSignatureTest"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new PgpSignatureTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpKeyRingTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpKeyRingTest.cs
new file mode 100644
index 0000000..2ac2f0c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpKeyRingTest.cs
@@ -0,0 +1,2161 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpKeyRingTest
+        : SimpleTest
+    {
+        private static readonly byte[] pub1 = Base64.Decode(
+            "mQGiBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn"
+            + "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg"
+            + "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf"
+            + "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ"
+            + "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G"
+            + "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ"
+            + "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG"
+            + "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP"
+            + "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif"
+            + "IIeLOTI5Dc4XKeV32a+bWrQidGVzdCAoVGVzdCBrZXkpIDx0ZXN0QHViaWNh"
+            + "bGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB4TOABgsJCAcDAgMVAgMDFgIB"
+            + "Ah4BAheAAAoJEJh8Njfhe8KmGDcAoJWr8xgPr75y/Cp1kKn12oCCOb8zAJ4p"
+            + "xSvk4K6tB2jYbdeSrmoWBZLdMLACAAC5AQ0EQDzfARAEAJeUAPvUzJJbKcc5"
+            + "5Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj47UPAD/tQxwz8VAwJySx82ggN"
+            + "LxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j2BVqZAaX3q79a3eMiql1T0oE"
+            + "AGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOHAAQNBACD0mVMlAUgd7REYy/1"
+            + "mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWaHz6CN1XptdwpDeSYEOFZ0PSu"
+            + "qH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85efMBA9jUv/DeBOzRWMFG6sC6y"
+            + "k8NGG7Swea7EHKeQI40G3jgO/+xANtMyTIhPBBgRAgAPBQJAPN8BAhsMBQkB"
+            + "4TOAAAoJEJh8Njfhe8KmG7kAn00mTPGJCWqmskmzgdzeky5fWd7rAKCNCp3u"
+            + "ZJhfg0htdgAfIy8ppm05vLACAAA=");
+
+        private static readonly byte[] sec1 = Base64.Decode(
+            "lQHhBEA83v0RBADzKVLVCnpWQxX0LCsevw/3OLs0H7MOcLBQ4wMO9sYmzGYn"
+            + "xpVj+4e4PiCP7QBayWyy4lugL6Lnw7tESvq3A4v3fefcxaCTkJrryiKn4+Cg"
+            + "y5rIBbrSKNtCEhVi7xjtdnDjP5kFKgHYjVOeIKn4Cz/yzPG3qz75kDknldLf"
+            + "yHxp2wCgwW1vAE5EnZU4/UmY7l8kTNkMltMEAJP4/uY4zcRwLI9Q2raPqAOJ"
+            + "TYLd7h+3k/BxI0gIw96niQ3KmUZDlobbWBI+VHM6H99vcttKU3BgevNf8M9G"
+            + "x/AbtW3SS4De64wNSU3189XDG8vXf0vuyW/K6Pcrb8exJWY0E1zZQ1WXT0gZ"
+            + "W0kH3g5ro//Tusuil9q2lVLF2ovJA/0W+57bPzi318dWeNs0tTq6Njbc/GTG"
+            + "FUAVJ8Ss5v2u6h7gyJ1DB334ExF/UdqZGldp0ugkEXaSwBa2R7d3HBgaYcoP"
+            + "Ck1TrovZzEY8gm7JNVy7GW6mdOZuDOHTxyADEEP2JPxh6eRcZbzhGuJuYIif"
+            + "IIeLOTI5Dc4XKeV32a+bWv4CAwJ5KgazImo+sGBfMhDiBcBTqyDGhKHNgHic"
+            + "0Pky9FeRvfXTc2AO+jGmFPjcs8BnTWuDD0/jkQnRZpp1TrQidGVzdCAoVGVz"
+            + "dCBrZXkpIDx0ZXN0QHViaWNhbGwuY29tPohkBBMRAgAkBQJAPN79AhsDBQkB"
+            + "4TOABgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEJh8Njfhe8KmGDcAn3XeXDMg"
+            + "BZgrZzFWU2IKtA/5LG2TAJ0Vf/jjyq0jZNZfGfoqGTvD2MAl0rACAACdAVgE"
+            + "QDzfARAEAJeUAPvUzJJbKcc55Iyb13+Gfb8xBWE3HinQzhGr1v6A1aIZbRj4"
+            + "7UPAD/tQxwz8VAwJySx82ggNLxCk4jW9YtTL3uZqfczsJngV25GoIN10f4/j"
+            + "2BVqZAaX3q79a3eMiql1T0oEAGmD7tO1LkTvWfm3VvA0+t8/6ZeRLEiIqAOH"
+            + "AAQNBACD0mVMlAUgd7REYy/1mL99Zlu9XU0uKyUex99sJNrcx1aj8rIiZtWa"
+            + "Hz6CN1XptdwpDeSYEOFZ0PSuqH9ByM3OfjU/ya0//xdvhwYXupn6P1Kep85e"
+            + "fMBA9jUv/DeBOzRWMFG6sC6yk8NGG7Swea7EHKeQI40G3jgO/+xANtMyTP4C"
+            + "AwJ5KgazImo+sGBl2C7CFuI+5KM4ZhbtVie7l+OiTpr5JW2z5VgnV3EX9p04"
+            + "LcGKfQvD65+ELwli6yh8B2zGcipqTaYk3QoYNIhPBBgRAgAPBQJAPN8BAhsM"
+            + "BQkB4TOAAAoJEJh8Njfhe8KmG7kAniuRkaFFv1pdCBN8JJXpcorHmyouAJ9L"
+            + "xxmusffR6OI7WgD3XZ0AL8zUC7ACAAA=");
+
+//		private static readonly char[] pass1 = "qwertzuiop".ToCharArray();
+
+        private static readonly byte[] pub2 = Base64.Decode(
+            "mQGiBEBtfW8RBADfWjTxFedIbGBNVgh064D/OCf6ul7x4PGsCl+BkAyheYkr"
+            + "mVUsChmBKoeXaY+Fb85wwusXzyM/6JFK58Rg+vEb3Z19pue8Ixxq7cRtCtOA"
+            + "tOP1eKXLNtTRWJutvLkQmeOa19UZ6ziIq23aWuWKSq+KKMWek2GUnGycnx5M"
+            + "W0pn1QCg/39r9RKhY9cdKYqRcqsr9b2B/AsD/Ru24Q15Jmrsl9zZ6EC47J49"
+            + "iNW5sLQx1qf/mgfVWQTmU2j6gq4ND1OuK7+0OP/1yMOUpkjjcqxFgTnDAAoM"
+            + "hHDTzCv/aZzIzmMvgLsYU3aIMfbz+ojpuASMCMh+te01cEMjiPWwDtdWWOdS"
+            + "OSyX9ylzhO3PiNDks8R83onsacYpA/9WhTcg4bvkjaj66I7wGZkm3BmTxNSb"
+            + "pE4b5HZDh31rRYhY9tmrryCfFnU4BS2Enjj5KQe9zFv7pUBCBW2oFo8i8Osn"
+            + "O6fa1wVN4fBHC6wqWmmpnkFerNPkiC9V75KUFIfeWHmT3r2DVSO3dfdHDERA"
+            + "jFIAioMLjhaX6DnODF5KQrABh7QmU2FpIFB1bGxhYmhvdGxhIDxwc2FpQG15"
+            + "amF2YXdvcmxkLmNvbT6wAwP//4kAVwQQEQIAFwUCQG19bwcLCQgHAwIKAhkB"
+            + "BRsDAAAAAAoJEKXQf/RT99uYmfAAoMKxV5g2owIfmy2w7vSLvOQUpvvOAJ4n"
+            + "jB6xJot523rPAQW9itPoGGekirABZ7kCDQRAbX1vEAgA9kJXtwh/CBdyorrW"
+            + "qULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9"
+            + "ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/"
+            + "Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4"
+            + "DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEs"
+            + "tSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1B"
+            + "n5x8vYlLIhkmuquiXsNV6TILOwACAgf9F7/nJHDayJ3pBVTTVSq2g5WKUXMg"
+            + "xxGKTvOahiVRcbO03w0pKAkH85COakVfe56sMYpWRl36adjNoKOxaciow74D"
+            + "1R5snY/hv/kBXPBkzo4UMkbANIVaZ0IcnLp+rkkXcDVbRCibZf8FfCY1zXbq"
+            + "d680UtEgRbv1D8wFBqfMt7kLsuf9FnIw6vK4DU06z5ZDg25RHGmswaDyY6Mw"
+            + "NGCrKGbHf9I/T7MMuhGF/in8UU8hv8uREOjseOqklG3/nsI1hD/MdUC7fzXi"
+            + "MRO4RvahLoeXOuaDkMYALdJk5nmNuCL1YPpbFGttI3XsK7UrP/Fhd8ND6Nro"
+            + "wCqrN6keduK+uLABh4kATAQYEQIADAUCQG19bwUbDAAAAAAKCRCl0H/0U/fb"
+            + "mC/0AJ4r1yvyu4qfOXlDgmVuCsvHFWo63gCfRIrCB2Jv/N1cgpmq0L8LGHM7"
+            + "G/KwAWeZAQ0EQG19owEIAMnavLYqR7ffaDPbbq+lQZvLCK/3uA0QlyngNyTa"
+            + "sDW0WC1/ryy2dx7ypOOCicjnPYfg3LP5TkYAGoMjxH5+xzM6xfOR+8/EwK1z"
+            + "N3A5+X/PSBDlYjQ9dEVKrvvc7iMOp+1K1VMf4Ug8Yah22Ot4eLGP0HRCXiv5"
+            + "vgdBNsAl/uXnBJuDYQmLrEniqq/6UxJHKHxZoS/5p13Cq7NfKB1CJCuJXaCE"
+            + "TW2do+cDpN6r0ltkF/r+ES+2L7jxyoHcvQ4YorJoDMlAN6xpIZQ8dNaTYP/n"
+            + "Mx/pDS3shUzbU+UYPQrreJLMF1pD+YWP5MTKaZTo+U/qPjDFGcadInhPxvh3"
+            + "1ssAEQEAAbABh7QuU2FuZGh5YSBQdWxsYWJob3RsYSA8cHNhbmRoeWFAbXlq"
+            + "YXZhd29ybGQuY29tPrADA///iQEtBBABAgAXBQJAbX2jBwsJCAcDAgoCGQEF"
+            + "GwMAAAAACgkQx87DL9gOvoeVUwgAkQXYiF0CxhKbDnuabAssnOEwJrutgCRO"
+            + "CJRQvIwTe3fe6hQaWn2Yowt8OQtNFiR8GfAY6EYxyFLKzZbAI/qtq5fHmN3e"
+            + "RSyNWe6d6e17hqZZL7kf2sVkyGTChHj7Jiuo7vWkdqT2MJN6BW5tS9CRH7Me"
+            + "D839STv+4mAAO9auGvSvicP6UEQikAyCy/ihoJxLQlspfbSNpi0vrUjCPT7N"
+            + "tWwfP0qF64i9LYkjzLqihnu+UareqOPhXcWnyFKrjmg4ezQkweNU2pdvCLbc"
+            + "W24FhT92ivHgpLyWTswXcqjhFjVlRr0+2sIz7v1k0budCsJ7PjzOoH0hJxCv"
+            + "sJQMlZR/e7ABZ7kBDQRAbX2kAQgAm5j+/LO2M4pKm/VUPkYuj3eefHkzjM6n"
+            + "KbvRZX1Oqyf+6CJTxQskUWKAtkzzKafPdS5Wg0CMqeXov+EFod4bPEYccszn"
+            + "cKd1U8NRwacbEpCvvvB84Yl2YwdWpDpkryyyLI4PbCHkeuwx9Dc2z7t4XDB6"
+            + "FyAJTMAkia7nzYa/kbeUO3c2snDb/dU7uyCsyKtTZyTyhTgtl/f9L03Bgh95"
+            + "y3mOUz0PimJ0Sg4ANczF4d04BpWkjLNVJi489ifWodPlHm1hag5drYekYpWJ"
+            + "+3g0uxs5AwayV9BcOkPKb1uU3EoYQw+nn0Kn314Nvx2M1tKYunuVNLEm0PhA"
+            + "/+B8PTq8BQARAQABsAGHiQEiBBgBAgAMBQJAbX2kBRsMAAAAAAoJEMfOwy/Y"
+            + "Dr6HkLoH/RBY8lvUv1r8IdTs5/fN8e/MnGeThLl+JrlYF/4t3tjXYIf5xUj/"
+            + "c9NdjreKYgHfMtrbVM08LlxUVQlkjuF3DIk5bVH9Blq8aXmyiwiM5GrCry+z"
+            + "WiqkpZze1G577C38mMJbHDwbqNCLALMzo+W2q04Avl5sniNnDNGbGz9EjhRg"
+            + "o7oS16KkkD6Ls4RnHTEZ0vyZOXodDHu+sk/2kzj8K07kKaM8rvR7aDKiI7HH"
+            + "1GxJz70fn1gkKuV2iAIIiU25bty+S3wr+5h030YBsUZF1qeKCdGOmpK7e9Of"
+            + "yv9U7rf6Z5l8q+akjqLZvej9RnxeH2Um7W+tGg2me482J+z6WOawAWc=");
+
+        private static readonly byte[] sec2 = Base64.Decode(
+            "lQHpBEBtfW8RBADfWjTxFedIbGBNVgh064D/OCf6ul7x4PGsCl+BkAyheYkr"
+            + "mVUsChmBKoeXaY+Fb85wwusXzyM/6JFK58Rg+vEb3Z19pue8Ixxq7cRtCtOA"
+            + "tOP1eKXLNtTRWJutvLkQmeOa19UZ6ziIq23aWuWKSq+KKMWek2GUnGycnx5M"
+            + "W0pn1QCg/39r9RKhY9cdKYqRcqsr9b2B/AsD/Ru24Q15Jmrsl9zZ6EC47J49"
+            + "iNW5sLQx1qf/mgfVWQTmU2j6gq4ND1OuK7+0OP/1yMOUpkjjcqxFgTnDAAoM"
+            + "hHDTzCv/aZzIzmMvgLsYU3aIMfbz+ojpuASMCMh+te01cEMjiPWwDtdWWOdS"
+            + "OSyX9ylzhO3PiNDks8R83onsacYpA/9WhTcg4bvkjaj66I7wGZkm3BmTxNSb"
+            + "pE4b5HZDh31rRYhY9tmrryCfFnU4BS2Enjj5KQe9zFv7pUBCBW2oFo8i8Osn"
+            + "O6fa1wVN4fBHC6wqWmmpnkFerNPkiC9V75KUFIfeWHmT3r2DVSO3dfdHDERA"
+            + "jFIAioMLjhaX6DnODF5KQv4JAwIJH6A/rzqmMGAG4e+b8Whdvp8jaTGVT4CG"
+            + "M1b65rbiDyAuf5KTFymQBOIi9towgFzG9NXAZC07nEYSukN56tUTUDNVsAGH"
+            + "tCZTYWkgUHVsbGFiaG90bGEgPHBzYWlAbXlqYXZhd29ybGQuY29tPrADA///"
+            + "iQBXBBARAgAXBQJAbX1vBwsJCAcDAgoCGQEFGwMAAAAACgkQpdB/9FP325iZ"
+            + "8ACgwrFXmDajAh+bLbDu9Iu85BSm+84AnieMHrEmi3nbes8BBb2K0+gYZ6SK"
+            + "sAFnnQJqBEBtfW8QCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoB"
+            + "p1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3b"
+            + "zpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa"
+            + "8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPw"
+            + "pVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obE"
+            + "AxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7"
+            + "AAICB/0Xv+ckcNrInekFVNNVKraDlYpRcyDHEYpO85qGJVFxs7TfDSkoCQfz"
+            + "kI5qRV97nqwxilZGXfpp2M2go7FpyKjDvgPVHmydj+G/+QFc8GTOjhQyRsA0"
+            + "hVpnQhycun6uSRdwNVtEKJtl/wV8JjXNdup3rzRS0SBFu/UPzAUGp8y3uQuy"
+            + "5/0WcjDq8rgNTTrPlkODblEcaazBoPJjozA0YKsoZsd/0j9Pswy6EYX+KfxR"
+            + "TyG/y5EQ6Ox46qSUbf+ewjWEP8x1QLt/NeIxE7hG9qEuh5c65oOQxgAt0mTm"
+            + "eY24IvVg+lsUa20jdewrtSs/8WF3w0Po2ujAKqs3qR524r64/gkDAmmp39NN"
+            + "U2pqYHokufIOab2VpD7iQo8UjHZNwR6dpjyky9dVfIe4MA0H+t0ju8UDdWoe"
+            + "IkRu8guWsI83mjGPbIq8lmsZOXPCA8hPuBmL0iaj8TnuotmsBjIBsAGHiQBM"
+            + "BBgRAgAMBQJAbX1vBRsMAAAAAAoJEKXQf/RT99uYL/QAnivXK/K7ip85eUOC"
+            + "ZW4Ky8cVajreAJ9EisIHYm/83VyCmarQvwsYczsb8rABZ5UDqARAbX2jAQgA"
+            + "ydq8tipHt99oM9tur6VBm8sIr/e4DRCXKeA3JNqwNbRYLX+vLLZ3HvKk44KJ"
+            + "yOc9h+Dcs/lORgAagyPEfn7HMzrF85H7z8TArXM3cDn5f89IEOViND10RUqu"
+            + "+9zuIw6n7UrVUx/hSDxhqHbY63h4sY/QdEJeK/m+B0E2wCX+5ecEm4NhCYus"
+            + "SeKqr/pTEkcofFmhL/mnXcKrs18oHUIkK4ldoIRNbZ2j5wOk3qvSW2QX+v4R"
+            + "L7YvuPHKgdy9DhiismgMyUA3rGkhlDx01pNg/+czH+kNLeyFTNtT5Rg9Cut4"
+            + "kswXWkP5hY/kxMpplOj5T+o+MMUZxp0ieE/G+HfWywARAQABCWEWL2cKQKcm"
+            + "XFTNsWgRoOcOkKyJ/osERh2PzNWvOF6/ir1BMRsg0qhd+hEcoWHaT+7Vt12i"
+            + "5Y2Ogm2HFrVrS5/DlV/rw0mkALp/3cR6jLOPyhmq7QGwhG27Iy++pLIksXQa"
+            + "RTboa7ZasEWw8zTqa4w17M5Ebm8dtB9Mwl/kqU9cnIYnFXj38BWeia3iFBNG"
+            + "PD00hqwhPUCTUAcH9qQPSqKqnFJVPe0KQWpq78zhCh1zPUIa27CE86xRBf45"
+            + "XbJwN+LmjCuQEnSNlloXJSPTRjEpla+gWAZz90fb0uVIR1dMMRFxsuaO6aCF"
+            + "QMN2Mu1wR/xzTzNCiQf8cVzq7YkkJD8ChJvu/4BtWp3BlU9dehAz43mbMhaw"
+            + "Qx3NmhKR/2dv1cJy/5VmRuljuzC+MRtuIjJ+ChoTa9ubNjsT6BF5McRAnVzf"
+            + "raZK+KVWCGA8VEZwe/K6ouYLsBr6+ekCKIkGZdM29927m9HjdFwEFjnzQlWO"
+            + "NZCeYgDcK22v7CzobKjdo2wdC7XIOUVCzMWMl+ch1guO/Y4KVuslfeQG5X1i"
+            + "PJqV+bwJriCx5/j3eE/aezK/vtZU6cchifmvefKvaNL34tY0Myz2bOx44tl8"
+            + "qNcGZbkYF7xrNCutzI63xa2ruN1p3hNxicZV1FJSOje6+ITXkU5Jmufto7IJ"
+            + "t/4Q2dQefBQ1x/d0EdX31yK6+1z9dF/k3HpcSMb5cAWa2u2g4duAmREHc3Jz"
+            + "lHCsNgyzt5mkb6kS43B6og8Mm2SOx78dBIOA8ANzi5B6Sqk3/uN5eQFLY+sQ"
+            + "qGxXzimyfbMjyq9DdqXThx4vlp3h/GC39KxL5MPeB0oe6P3fSP3C2ZGjsn3+"
+            + "XcYk0Ti1cBwBOFOZ59WYuc61B0wlkiU/WGeaebABh7QuU2FuZGh5YSBQdWxs"
+            + "YWJob3RsYSA8cHNhbmRoeWFAbXlqYXZhd29ybGQuY29tPrADA///iQEtBBAB"
+            + "AgAXBQJAbX2jBwsJCAcDAgoCGQEFGwMAAAAACgkQx87DL9gOvoeVUwgAkQXY"
+            + "iF0CxhKbDnuabAssnOEwJrutgCROCJRQvIwTe3fe6hQaWn2Yowt8OQtNFiR8"
+            + "GfAY6EYxyFLKzZbAI/qtq5fHmN3eRSyNWe6d6e17hqZZL7kf2sVkyGTChHj7"
+            + "Jiuo7vWkdqT2MJN6BW5tS9CRH7MeD839STv+4mAAO9auGvSvicP6UEQikAyC"
+            + "y/ihoJxLQlspfbSNpi0vrUjCPT7NtWwfP0qF64i9LYkjzLqihnu+UareqOPh"
+            + "XcWnyFKrjmg4ezQkweNU2pdvCLbcW24FhT92ivHgpLyWTswXcqjhFjVlRr0+"
+            + "2sIz7v1k0budCsJ7PjzOoH0hJxCvsJQMlZR/e7ABZ50DqARAbX2kAQgAm5j+"
+            + "/LO2M4pKm/VUPkYuj3eefHkzjM6nKbvRZX1Oqyf+6CJTxQskUWKAtkzzKafP"
+            + "dS5Wg0CMqeXov+EFod4bPEYccszncKd1U8NRwacbEpCvvvB84Yl2YwdWpDpk"
+            + "ryyyLI4PbCHkeuwx9Dc2z7t4XDB6FyAJTMAkia7nzYa/kbeUO3c2snDb/dU7"
+            + "uyCsyKtTZyTyhTgtl/f9L03Bgh95y3mOUz0PimJ0Sg4ANczF4d04BpWkjLNV"
+            + "Ji489ifWodPlHm1hag5drYekYpWJ+3g0uxs5AwayV9BcOkPKb1uU3EoYQw+n"
+            + "n0Kn314Nvx2M1tKYunuVNLEm0PhA/+B8PTq8BQARAQABCXo6bD6qi3s4U8Pp"
+            + "Uf9l3DyGuwiVPGuyb2P+sEmRFysi2AvxMe9CkF+CLCVYfZ32H3Fcr6XQ8+K8"
+            + "ZGH6bJwijtV4QRnWDZIuhUQDS7dsbGqTh4Aw81Fm0Bz9fpufViM9RPVEysxs"
+            + "CZRID+9jDrACthVsbq/xKomkKdBfNTK7XzGeZ/CBr9F4EPlnBWClURi9txc0"
+            + "pz9YP5ZRy4XTFgx+jCbHgKWUIz4yNaWQqpSgkHEDrGZwstXeRaaPftcfQN+s"
+            + "EO7OGl/Hd9XepGLez4vKSbT35CnqTwMzCK1IwUDUzyB4BYEFZ+p9TI18HQDW"
+            + "hA0Wmf6E8pjS16m/SDXoiRY43u1jUVZFNFzz25uLFWitfRNHCLl+VfgnetZQ"
+            + "jMFr36HGVQ65fogs3avkgvpgPwDc0z+VMj6ujTyXXgnCP/FdhzgkRFJqgmdJ"
+            + "yOlC+wFmZJEs0MX7L/VXEXdpR27XIGYm24CC7BTFKSdlmR1qqenXHmCCg4Wp"
+            + "00fV8+aAsnesgwPvxhCbZQVp4v4jqhVuB/rvsQu9t0rZnKdDnWeom/F3StYo"
+            + "A025l1rrt0wRP8YS4XlslwzZBqgdhN4urnzLH0/F3X/MfjP79Efj7Zk07vOH"
+            + "o/TPjz8lXroPTscOyXWHwtQqcMhnVsj9jvrzhZZSdUuvnT30DR7b8xcHyvAo"
+            + "WG2cnF/pNSQX11RlyyAOlw9TOEiDJ4aLbFdkUt+qZdRKeC8mEC2xsQ87HqFR"
+            + "pWKWABWaoUO0nxBEmvNOy97PkIeGVFNHDLlIeL++Ry03+JvuNNg4qAnwacbJ"
+            + "TwQzWP4vJqre7Gl/9D0tVlD4Yy6Xz3qyosxdoFpeMSKHhgKVt1bk0SQP7eXA"
+            + "C1c+eDc4gN/ZWpl+QLqdk2T9vr4wRAaK5LABh4kBIgQYAQIADAUCQG19pAUb"
+            + "DAAAAAAKCRDHzsMv2A6+h5C6B/0QWPJb1L9a/CHU7Of3zfHvzJxnk4S5fia5"
+            + "WBf+Ld7Y12CH+cVI/3PTXY63imIB3zLa21TNPC5cVFUJZI7hdwyJOW1R/QZa"
+            + "vGl5sosIjORqwq8vs1oqpKWc3tRue+wt/JjCWxw8G6jQiwCzM6PltqtOAL5e"
+            + "bJ4jZwzRmxs/RI4UYKO6EteipJA+i7OEZx0xGdL8mTl6HQx7vrJP9pM4/CtO"
+            + "5CmjPK70e2gyoiOxx9RsSc+9H59YJCrldogCCIlNuW7cvkt8K/uYdN9GAbFG"
+            + "RdanignRjpqSu3vTn8r/VO63+meZfKvmpI6i2b3o/UZ8Xh9lJu1vrRoNpnuP"
+            + "Nifs+ljmsAFn");
+
+        private static readonly char[] sec2pass1 = "sandhya".ToCharArray();
+        private static readonly char[] sec2pass2 = "psai".ToCharArray();
+
+        private static readonly byte[] pub3 = Base64.Decode(
+            "mQGiBEB9BH0RBACtYQtE7tna6hgGyGLpq+ds3r2cLC0ISn5dNw7tm9vwiNVF"
+            + "JA2N37RRrifw4PvgelRSvLaX3M3ZBqC9s1Metg3v4FSlIRtSLWCNpHSvNw7i"
+            + "X8C2Xy9Hdlbh6Y/50o+iscojLRE14upfR1bIkcCZQGSyvGV52V2wBImUUZjV"
+            + "s2ZngwCg7mu852vK7+euz4WaL7ERVYtq9CMEAJ5swrljerDpz/RQ4Lhp6KER"
+            + "KyuI0PUttO57xINGshEINgYlZdGaZHRueHe7uKfI19mb0T4N3NJWaZ0wF+Cn"
+            + "rixsq0VrTUfiwfZeGluNG73aTCeY45fVXMGTTSYXzS8T0LW100Xn/0g9HRyA"
+            + "xUpuWo8IazxkMqHJis2uwriYKpAfA/9anvj5BS9p5pfPjp9dGM7GTMIYl5f2"
+            + "fcP57f+AW1TVR6IZiMJAvAdeWuLtwLnJiFpGlnFz273pfl+sAuqm1yNceImR"
+            + "2SDDP4+vtyycWy8nZhgEuhZx3W3cWMQz5WyNJSY1JJHh9TCQkCoN8E7XpVP4"
+            + "zEPboB2GzD93mfD8JLHP+7QtVGVzdCBLZXkgKG5vIGNvbW1lbnQpIDx0ZXN0"
+            + "QGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkFAkB9BH0ECwcDAgMVAgMDFgIB"
+            + "Ah4BAheAAAoJEKnMV8vjZQOpSRQAnidAQswYkrXQAFcLBzhxQTknI9QMAKDR"
+            + "ryV3l6xuCCgHST8JlxpbjcXhlLACAAPRwXPBcQEQAAEBAAAAAAAAAAAAAAAA"
+            + "/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q"
+            + "/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAi"
+            + "LCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEcITIy"
+            + "MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy"
+            + "MjIy/8AAEQgAFAAUAwEiAAIRAQMRAf/EABoAAQACAwEAAAAAAAAAAAAAAAAE"
+            + "BQIDBgf/xAAoEAABAgUDBAEFAAAAAAAAAAABAgMABBEhMQUSQQYTIiNhFFGB"
+            + "kcH/xAAXAQEAAwAAAAAAAAAAAAAAAAAEAgMF/8QAJBEAAQQAAwkAAAAAAAAA"
+            + "AAAAAQACERIEIfATMTJBUZGx0fH/2gAMAwEAAhEDEQA/APMuotJlJVxstqaP"
+            + "o22NlAUp+YsNO0qSUtBcMu6n6EtOHcfPAHHFI16++oajQtTA3DapK02HFR8U"
+            + "pE9pTbQWtKm2WG2rlxVyQTcfGbn7Qm0OIjL77Wrs2NNm9lzTmmSxQ0PX4opS"
+            + "prk5tmESF6syggzGwOLG6gXgHFbZhBixk8XlIDcOQLRKt+rX+3qC5ZLTQblp"
+            + "Qlvwvxn9CMpZturVGkJHapQJphRH8hCLXbzrqpYsCx1zC5rtpJNuYQhASc0U"
+            + "AQv/2YhcBBMRAgAcBQJAfQV+AhsDBAsHAwIDFQIDAxYCAQIeAQIXgAAKCRCp"
+            + "zFfL42UDqfa2AJ9hjtEeDTbTEAuuSbzhYFxN/qc0FACgsmzysdbBpuN65yK0"
+            + "1tbEaeIMtqCwAgADuM0EQH0EfhADAKpG5Y6vGbm//xZYG08RRmdi67dZjF59"
+            + "Eqfo43mRrliangB8qkqoqqf3za2OUbXcZUQ/ajDXUvjJAoY2b5XJURqmbtKk"
+            + "wPRIeD2+wnKABat8wmcFhZKATX1bqjdyRRGxawADBgMAoMJKJLELdnn885oJ"
+            + "6HDmIez++ZWTlafzfUtJkQTCRKiE0NsgSvKJr/20VdK3XUA/iy0m1nQwfzv/"
+            + "okFuIhEPgldzH7N/NyEvtN5zOv/TpAymFKewAQ26luEu6l+lH4FsiEYEGBEC"
+            + "AAYFAkB9BH4ACgkQqcxXy+NlA6mtMgCgtQMFBaKymktM+DQmCgy2qjW7WY0A"
+            + "n3FaE6UZE9GMDmCIAjhI+0X9aH6CsAIAAw==");
+
+        private static readonly byte[] sec3 = Base64.Decode(
+            "lQHhBEB9BH0RBACtYQtE7tna6hgGyGLpq+ds3r2cLC0ISn5dNw7tm9vwiNVF"
+            + "JA2N37RRrifw4PvgelRSvLaX3M3ZBqC9s1Metg3v4FSlIRtSLWCNpHSvNw7i"
+            + "X8C2Xy9Hdlbh6Y/50o+iscojLRE14upfR1bIkcCZQGSyvGV52V2wBImUUZjV"
+            + "s2ZngwCg7mu852vK7+euz4WaL7ERVYtq9CMEAJ5swrljerDpz/RQ4Lhp6KER"
+            + "KyuI0PUttO57xINGshEINgYlZdGaZHRueHe7uKfI19mb0T4N3NJWaZ0wF+Cn"
+            + "rixsq0VrTUfiwfZeGluNG73aTCeY45fVXMGTTSYXzS8T0LW100Xn/0g9HRyA"
+            + "xUpuWo8IazxkMqHJis2uwriYKpAfA/9anvj5BS9p5pfPjp9dGM7GTMIYl5f2"
+            + "fcP57f+AW1TVR6IZiMJAvAdeWuLtwLnJiFpGlnFz273pfl+sAuqm1yNceImR"
+            + "2SDDP4+vtyycWy8nZhgEuhZx3W3cWMQz5WyNJSY1JJHh9TCQkCoN8E7XpVP4"
+            + "zEPboB2GzD93mfD8JLHP+/4DAwIvYrn+YqRaaGAu19XUj895g/GROyP8WEaU"
+            + "Bd/JNqWc4kE/0guetGnPzq7G3bLVwiKfFd4X7BrgHAo3mrQtVGVzdCBLZXkg"
+            + "KG5vIGNvbW1lbnQpIDx0ZXN0QGJvdW5jeWNhc3RsZS5vcmc+iFkEExECABkF"
+            + "AkB9BH0ECwcDAgMVAgMDFgIBAh4BAheAAAoJEKnMV8vjZQOpSRQAoKZy6YS1"
+            + "irF5/Q3JlWiwbkN6dEuLAJ9lldRLOlXsuQ5JW1+SLEc6K9ho4rACAADRwXPB"
+            + "cQEQAAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD//gAXQ3Jl"
+            + "YXRlZCB3aXRoIFRoZSBHSU1Q/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZ"
+            + "EhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sA"
+            + "QwEJCQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy"
+            + "MjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgAFAAUAwEiAAIRAQMRAf/EABoA"
+            + "AQACAwEAAAAAAAAAAAAAAAAEBQIDBgf/xAAoEAABAgUDBAEFAAAAAAAAAAAB"
+            + "AgMABBEhMQUSQQYTIiNhFFGBkcH/xAAXAQEAAwAAAAAAAAAAAAAAAAAEAgMF"
+            + "/8QAJBEAAQQAAwkAAAAAAAAAAAAAAQACERIEIfATMTJBUZGx0fH/2gAMAwEA"
+            + "AhEDEQA/APMuotJlJVxstqaPo22NlAUp+YsNO0qSUtBcMu6n6EtOHcfPAHHF"
+            + "I16++oajQtTA3DapK02HFR8UpE9pTbQWtKm2WG2rlxVyQTcfGbn7Qm0OIjL7"
+            + "7Wrs2NNm9lzTmmSxQ0PX4opSprk5tmESF6syggzGwOLG6gXgHFbZhBixk8Xl"
+            + "IDcOQLRKt+rX+3qC5ZLTQblpQlvwvxn9CMpZturVGkJHapQJphRH8hCLXbzr"
+            + "qpYsCx1zC5rtpJNuYQhASc0UAQv/2YhcBBMRAgAcBQJAfQV+AhsDBAsHAwID"
+            + "FQIDAxYCAQIeAQIXgAAKCRCpzFfL42UDqfa2AJ9hjtEeDTbTEAuuSbzhYFxN"
+            + "/qc0FACgsmzysdbBpuN65yK01tbEaeIMtqCwAgAAnQEUBEB9BH4QAwCqRuWO"
+            + "rxm5v/8WWBtPEUZnYuu3WYxefRKn6ON5ka5Ymp4AfKpKqKqn982tjlG13GVE"
+            + "P2ow11L4yQKGNm+VyVEapm7SpMD0SHg9vsJygAWrfMJnBYWSgE19W6o3ckUR"
+            + "sWsAAwYDAKDCSiSxC3Z5/POaCehw5iHs/vmVk5Wn831LSZEEwkSohNDbIEry"
+            + "ia/9tFXSt11AP4stJtZ0MH87/6JBbiIRD4JXcx+zfzchL7Teczr/06QMphSn"
+            + "sAENupbhLupfpR+BbP4DAwIvYrn+YqRaaGBjvFK1fbxCt7ZM4I2W/3BC0lCX"
+            + "m/NypKNspGflec8u96uUlA0fNCnxm6f9nbB0jpvoKi0g4iqAf+P2iEYEGBEC"
+            + "AAYFAkB9BH4ACgkQqcxXy+NlA6mtMgCgvccZA/Sg7BXVpxli47SYhxSHoM4A"
+            + "oNCOMplSnYTuh5ikKeBWtz36gC1psAIAAA==");
+
+        private static readonly char[] sec3pass1 = "123456".ToCharArray();
+
+        //
+        // GPG comment packets.
+        //
+        private static readonly byte[] sec4 = Base64.Decode(
+            "lQG7BD0PbK8RBAC0cW4Y2MZXmAmqYp5Txyw0kSQsFvwZKHNMFRv996IsN57URVF5"
+            + "BGMVPRBi9dNucWbjiSYpiYN13wE9IuLZsvVaQojV4XWGRDc+Rxz9ElsXnsYQ3mZU"
+            + "7H1bNQEofstChk4z+dlvPBN4GFahrIzn/CeVUn6Ut7dVdYbiTqviANqNXwCglfVA"
+            + "2OEePvqFnGxs1jhJyPSOnTED/RwRvsLH/k43mk6UEvOyN1RIpBXN+Ieqs7h1gFrQ"
+            + "kB+WMgeP5ZUsotTffVDSUS9UMxRQggVUW1Xml0geGwQsNfkr/ztWMs/T4xp1v5j+"
+            + "QyJx6OqNlkGdqOsoqkzJx0SQ1zBxdinFyyC4H95SDAb/RQOu5LQmxFG7quexztMs"
+            + "infEA/9cVc9+qCo92yRAaXRqKNVVQIQuPxeUsGMyVeJQvJBD4An8KTMCdjpF10Cp"
+            + "qA3t+n1S0zKr5WRUtvS6y60MOONO+EJWVWBNkx8HJDaIMNkfoqQoz3Krn7w6FE/v"
+            + "/5uwMd6jY3N3yJZn5nDZT9Yzv9Nx3j+BrY+henRlSU0c6xDc9QAAnjJYg0Z83VJG"
+            + "6HrBcgc4+4K6lHulCqH9JiM6RFNBX2ZhY3RvcjoAAK9hV206agp99GI6x5qE9+pU"
+            + "vs6O+Ich/SYjOkRTQV9mYWN0b3I6AACvYAfGn2FGrpBYbjnpTuFOHJMS/T5xg/0m"
+            + "IzpEU0FfZmFjdG9yOgAAr0dAQz6XxMwxWIn8xIZR/v2iN2L9C6O0EkZvbyBCYXIg"
+            + "PGJhekBxdXV4PohXBBMRAgAXBQI9D2yvBQsHCgMEAxUDAgMWAgECF4AACgkQUGLI"
+            + "YCIktfoGogCfZiXMJUKrScqozv5tMwzTTk2AaT8AniM5iRr0Du/Y08SL/NMhtF6H"
+            + "hJ89nO4EPQ9ssRADAI6Ggxj6ZBfoavuXd/ye99osW8HsNlbqhXObu5mCMNySX2wa"
+            + "HoWyRUEaUkI9eQw+MlHzIwzA32E7y2mU3OQBKdgLcBg4jxtcWVEg8ESKF9MpFXxl"
+            + "pExxWrr4DFBfCRcsTwAFEQL9G3OvwJuEZXgx2JSS41D3pG4/qiHYICVa0u3p/14i"
+            + "cq0kXajIk5ZJ6frCIAHIzuQ3n7jjzr05yR8s/qCrNbBA+nlkVNa/samk+jCzxxxa"
+            + "cR/Dbh2wkvTFuDFFETwQYLuZAADcDck4YGQAmHivVT2NNDCf/aTz0+CJWl+xRc2l"
+            + "Qw7D/SQjOkVMR19mYWN0b3I6AACbBnv9m5/bb/pjYAm2PtDp0CysQ9X9JCM6RUxH"
+            + "X2ZhY3RvcjoAAJsFyHnSmaWguTFf6lJ/j39LtUNtmf0kIzpFTEdfZmFjdG9yOgAA"
+            + "mwfwMD3LxmWtuCWBE9BptWMNH07Z/SQjOkVMR19mYWN0b3I6AACbBdhBrbSiM4UN"
+            + "y7khDW2Sk0e4v9mIRgQYEQIABgUCPQ9ssQAKCRBQYshgIiS1+jCMAJ9txwHnb1Kl"
+            + "6i/fSoDs8SkdM7w48wCdFvPEV0sSxE73073YhBgPZtMWbBo=");
+
+        //
+        // PGP freeware version 7
+        //
+        private static readonly byte[] pub5 = Base64.Decode(
+            "mQENBEBrBE4BCACjXVcNIFDQSofaIyZnALb2CRg+WY9uUqgHEEAOlPe03Cs5STM5"
+            + "HDlNmrh4TdFceJ46rxk1mQOjULES1YfHay8lCIzrD7FX4oj0r4DC14Fs1vXaSar2"
+            + "1szIpttOw3obL4A1e0p6N4jjsoG7N/pA0fEL0lSw92SoBrMbAheXRg4qNTZvdjOR"
+            + "grcuOuwgJRvPLtRXlhyLBoyhkd5mmrIDGv8QHJ/UjpeIcRXY9kn9oGXnEYcRbMaU"
+            + "VwXB4pLzWqz3ZejFI3lOxRWjm760puPOnGYlzSVBxlt2LgzUgSj1Mn+lIpWmAzsa"
+            + "xEiU4xUwEomQns72yYRZ6D3euNCibcte4SeXABEBAAG0KXBhbGFzaCBrYXNvZGhh"
+            + "biA8cGthc29kaGFuQHRpYWEtY3JlZi5vcmc+iQEuBBABAgAYBQJAawROCAsBAwkI"
+            + "BwIKAhkBBRsDAAAAAAoJEOfelumuiOrYqPEH+wYrdP5Tq5j+E5yN1pyCg1rwbSOt"
+            + "Dka0y0p7Oq/VIGLk692IWPItLEunnBXQtGBcWqklrvogvlhxtf16FgoyScfLJx1e"
+            + "1cJa+QQnVuH+VOESN6iS9Gp9lUfVOHv74mEMXw0l2Djfy/lnrkAMBatggyGnF9xF"
+            + "VXOLk1J2WVFm9KUE23o6qdB7RGkf31pN2eA7SWmkdJSkUH7o/QSFBI+UTRZ/IY5P"
+            + "ZIJpsdiIOqd9YMG/4RoSZuPqNRR6x7BSs8nQVR9bYs4PPlp4GfdRnOcRonoTeJCZ"
+            + "83RnsraWJnJTg34gRLBcqumhTuFKc8nuCNK98D6zkQESdcHLLTquCOaF5L+5AQ0E"
+            + "QGsETwEIAOVwNCTaDZvW4dowPbET1bI5UeYY8rAGLYsWSUfgaFv2srMiApyBVltf"
+            + "i6OLcPjcUCHDBjCv4pwx/C4qcHWb8av4xQIpqQXOpO9NxYE1eZnel/QB7DtH12ZO"
+            + "nrDNmHtaXlulcKNGe1i1utlFhgzfFx6rWkRL0ENmkTkaQmPY4gTGymJTUhBbsSRq"
+            + "2ivWqQA1TPwBuda73UgslIAHRd/SUaxjXoLpMbGOTeqzcKGjr5XMPTs7/YgBpWPP"
+            + "UxMlEQIiU3ia1bxpEhx05k97ceK6TSH2oCPQA7gumjxOSjKT+jEm+8jACVzymEmc"
+            + "XRy4D5Ztqkw/Z16pvNcu1DI5m6xHwr8AEQEAAYkBIgQYAQIADAUCQGsETwUbDAAA"
+            + "AAAKCRDn3pbprojq2EynB/4/cEOtKbI5UisUd3vkTzvWOcqWUqGqi5wjjioNtIM5"
+            + "pur2nFvhQE7SZ+PbAa87HRJU/4WcWMcoLkHD48JrQwHCHOLHSV5muYowb78X4Yh9"
+            + "epYtSJ0uUahcn4Gp48p4BkhgsPYXkxEImSYzAOWStv21/7WEMqItMYl89BV6Upm8"
+            + "HyTJx5MPTDbMR7X51hRg3OeQs6po3WTCWRzFIMyGm1rd/VK1L5ZDFPqO3S6YUJ0z"
+            + "cxecYruvfK0Wp7q834wE8Zkl/PQ3NhfEPL1ZiLr/L00Ty+77/FZqt8SHRCICzOfP"
+            + "OawcVGI+xHVXW6lijMpB5VaVIH8i2KdBMHXHtduIkPr9");
+
+        private static readonly byte[] sec5 = Base64.Decode(
+            "lQOgBEBrBE4BCACjXVcNIFDQSofaIyZnALb2CRg+WY9uUqgHEEAOlPe03Cs5STM5"
+            + "HDlNmrh4TdFceJ46rxk1mQOjULES1YfHay8lCIzrD7FX4oj0r4DC14Fs1vXaSar2"
+            + "1szIpttOw3obL4A1e0p6N4jjsoG7N/pA0fEL0lSw92SoBrMbAheXRg4qNTZvdjOR"
+            + "grcuOuwgJRvPLtRXlhyLBoyhkd5mmrIDGv8QHJ/UjpeIcRXY9kn9oGXnEYcRbMaU"
+            + "VwXB4pLzWqz3ZejFI3lOxRWjm760puPOnGYlzSVBxlt2LgzUgSj1Mn+lIpWmAzsa"
+            + "xEiU4xUwEomQns72yYRZ6D3euNCibcte4SeXABEBAAEB8wqP7JkKN6oMNi1xJNqU"
+            + "vvt0OV4CCnrIFiOPCjebjH/NC4T/9pJ6BYSjYdo3VEPNhPhRS9U3071Kqbdt35J5"
+            + "kmzMq1yNStC1jkxHRCNTMsb1yIEY1v+fv8/Cy+tBpvAYiJKaox8jW3ppi9vTHZjW"
+            + "tYYq0kwAVojMovz1O3wW/pEF69UPBmPYsze+AHA1UucYYqdWO8U2tsdFJET/hYpe"
+            + "o7ppHJJCdqWzeiE1vDUrih9pP3MPpzcRS/gU7HRDb5HbfP7ghSLzByEa+2mvg5eK"
+            + "eLwNAx2OUtrVg9rJswXX7DOLa1nKPhdGrSV/qwuK4rBdaqJ/OvszVJ0Vln0T/aus"
+            + "it1PAuVROLUPqTVVN8/zkMenFbf5vtryC3GQYXvvZq+l3a4EXwrR/1pqrTfnfOuD"
+            + "GwlFhRJAqPfthxZS68/xC8qAmTtkl7j4nscNM9kSoZ3BFwSyD9B/vYHPWGlqnpGF"
+            + "k/hBXuIgl07KIeNIyEC3f1eRyaiMFqEz5yXbbTfEKirSVpHM/mpeKxG8w96aK3Je"
+            + "AV0X6ZkC4oLTp6HCG2TITUIeNxCh2rX3fhr9HvBDXBbMHgYlIcLwzNkwDX74cz/7"
+            + "nIclcubaWjEkDHP20XFicuChFc9zx6kBYuYy170snltTBgTWSuRH15W4NQqrLo37"
+            + "zyzZQubX7CObgQJu4ahquiOg4SWl6uEI7+36U0SED7sZzw8ns1LxrwOWbXuHie1i"
+            + "xCvsJ4RpJJ03iEdNdUIb77qf6AriqE92tXzcVXToBv5S2K5LdFYNJ1rWdwaKJRkt"
+            + "kmjCL67KM9WT/IagsUyU+57ao3COtqw9VWZi6ev+ubM6fIV0ZK46NEggOLph1hi2"
+            + "gZ9ew9uVuruYg7lG2Ku82N0fjrQpcGFsYXNoIGthc29kaGFuIDxwa2Fzb2RoYW5A"
+            + "dGlhYS1jcmVmLm9yZz6dA6AEQGsETwEIAOVwNCTaDZvW4dowPbET1bI5UeYY8rAG"
+            + "LYsWSUfgaFv2srMiApyBVltfi6OLcPjcUCHDBjCv4pwx/C4qcHWb8av4xQIpqQXO"
+            + "pO9NxYE1eZnel/QB7DtH12ZOnrDNmHtaXlulcKNGe1i1utlFhgzfFx6rWkRL0ENm"
+            + "kTkaQmPY4gTGymJTUhBbsSRq2ivWqQA1TPwBuda73UgslIAHRd/SUaxjXoLpMbGO"
+            + "TeqzcKGjr5XMPTs7/YgBpWPPUxMlEQIiU3ia1bxpEhx05k97ceK6TSH2oCPQA7gu"
+            + "mjxOSjKT+jEm+8jACVzymEmcXRy4D5Ztqkw/Z16pvNcu1DI5m6xHwr8AEQEAAQF7"
+            + "osMrvQieBAJFYY+x9jKPVclm+pVaMaIcHKwCTv6yUZMqbHNRTfwdCVKTdAzdlh5d"
+            + "zJNXXRu8eNwOcfnG3WrWAy59cYE389hA0pQPOh7iL2V1nITf1qdLru1HJqqLC+dy"
+            + "E5GtkNcgvQYbv7ACjQacscvnyBioYC6TATtPnHipMO0S1sXEnmUugNlW88pDln4y"
+            + "VxCtQXMBjuqMt0bURqmb+RoYhHhoCibo6sexxSnbEAPHBaW1b1Rm7l4UBSW6S5U0"
+            + "MXURE60IHfP1TBe1l/xOIxOi8qdBQCyaFW2up00EhRBy/WOO6KAYXQrRRpOs9TBq"
+            + "ic2wquwZePmErTbIttnnBcAKmpodrM/JBkn/we5fVg+FDTP8sM/Ubv0ZuM70aWmF"
+            + "v0/ZKbkCkh2YORLWl5+HR/RKShdkmmFgZZ5uzbOGxxEGKhw+Q3+QFUF7PmYOnOtv"
+            + "s9PZE3dV7ovRDoXIjfniD1+8sLUWwW5d+3NHAQnCHJrLnPx4sTHx6C0yWMcyZk6V"
+            + "fNHpLK4xDTbgoTmxJa/4l+wa0iD69h9K/Nxw/6+X/GEM5w3d/vjlK1Da6urN9myc"
+            + "GMsfiIll5DNIWdLLxCBPFmhJy653CICQLY5xkycWB7JOZUBTOEVrYr0AbBZSTkuB"
+            + "fq5p9MfH4N51M5TWnwlJnqEiGnpaK+VDeP8GniwCidTYyiocNPvghvWIzG8QGWMY"
+            + "PFncRpjFxmcY4XScYYpyRme4qyPbJhbZcgGpfeLvFKBPmNxVKJ2nXTdx6O6EbHDj"
+            + "XctWqNd1EQas7rUN728u7bk8G7m37MGqQuKCpNvOScH4TnPROBY8get0G3bC4mWz"
+            + "6emPeENnuyElfWQiHEtCZr1InjnNbb/C97O+vWu9PfsE");
+
+        private static readonly char[] sec5pass1 = "12345678".ToCharArray();
+
+        //
+        // Werner Koch "odd keys"
+        //
+        private static readonly byte[] pub6 = Base64.Decode(
+            "mQGiBDWiHh4RBAD+l0rg5p9rW4M3sKvmeyzhs2mDxhRKDTVVUnTwpMIR2kIA9pT4"
+            + "3No/coPajDvhZTaDM/vSz25IZDZWJ7gEu86RpoEdtr/eK8GuDcgsWvFs5+YpCDwW"
+            + "G2dx39ME7DN+SRvEE1xUm4E9G2Nnd2UNtLgg82wgi/ZK4Ih9CYDyo0a9awCgisn3"
+            + "RvZ/MREJmQq1+SjJgDx+c2sEAOEnxGYisqIKcOTdPOTTie7o7x+nem2uac7uOW68"
+            + "N+wRWxhGPIxsOdueMIa7U94Wg/Ydn4f2WngJpBvKNaHYmW8j1Q5zvZXXpIWRXSvy"
+            + "TR641BceGHNdYiR/PiDBJsGQ3ac7n7pwhV4qex3IViRDJWz5Dzr88x+Oju63KtxY"
+            + "urUIBACi7d1rUlHr4ok7iBRlWHYXU2hpUIQ8C+UOE1XXT+HB7mZLSRONQnWMyXnq"
+            + "bAAW+EUUX2xpb54CevAg4eOilt0es8GZMmU6c0wdUsnMWWqOKHBFFlDIvyI27aZ9"
+            + "quf0yvby63kFCanQKc0QnqGXQKzuXbFqBYW2UQrYgjXji8rd8bQnV2VybmVyIEtv"
+            + "Y2ggKGdudXBnIHNpZykgPGRkOWpuQGdudS5vcmc+iGUEExECAB0FAjZVoKYFCQht"
+            + "DIgDCwQDBRUDAgYBAxYCAQIXgAASCRBot6uJV1SNzQdlR1BHAAEBLj4AoId15gcy"
+            + "YpBX2YLtEQTlXPp3mtEGAJ9UxzJE/t3EHCHK2bAIOkBwIW8ItIkBXwMFEDWiHkMD"
+            + "bxG4/z6qCxADYzIFHR6I9Si9gzPQNRcFs2znrTp5pV5Mk6f1aqRgZxL3E4qUZ3xe"
+            + "PQhwAo3fSy3kCwLmFGqvzautSMHn8K5V1u+T5CSHqLFYKqj5FGtuB/xwoKDXH6UO"
+            + "P0+l5IP8H1RTjme3Fhqahec+zPG3NT57vc2Ru2t6PmuAwry2BMuSFMBs7wzXkyC3"
+            + "DbI54MV+IKPjHMORivK8uI8jmna9hdNVyBifCk1GcxkHBSCFvU8xJePsA/Q//zCe"
+            + "lvrnrIiMfY4CQTmKzke9MSzbAZQIRddgrGAsiX1tE8Z3YMd8lDpuujHLVEdWZo6s"
+            + "54OJuynHrtFFObdapu0uIrT+dEXSASMUbEuNCLL3aCnrEtGJCwxB2TPQvCCvR2BK"
+            + "zol6MGWxA+nmddeQib2r+GXoKXLdnHcpsAjA7lkXk3IFyJ7MLFK6uDrjGbGJs2FK"
+            + "SduUjS/Ib4hGBBARAgAGBQI1oic8AAoJEGx+4bhiHMATftYAn1fOaKDUOt+dS38r"
+            + "B+CJ2Q+iElWJAKDRPpp8q5GylbM8DPlMpClWN3TYqYhGBBARAgAGBQI27U5sAAoJ"
+            + "EF3iSZZbA1iiarYAn35qU3ZOlVECELE/3V6q98Q30eAaAKCtO+lacH0Qq1E6v4BP"
+            + "/9y6MoLIhohiBBMRAgAiAhsDBAsHAwIDFQIDAxYCAQIeAQIXgAUCP+mCaQUJDDMj"
+            + "ywAKCRBot6uJV1SNzaLvAJwLsPV1yfc2D+yT+2W11H/ftNMDvwCbBweORhCb/O/E"
+            + "Okg2UTXJBR4ekoCIXQQTEQIAHQMLBAMFFQMCBgEDFgIBAheABQI/6YJzBQkMMyPL"
+            + "AAoJEGi3q4lXVI3NgroAn2Z+4KgVo2nzW72TgCJwkAP0cOc2AJ0ZMilsOWmxmEG6"
+            + "B4sHMLkB4ir4GIhdBBMRAgAdAwsEAwUVAwIGAQMWAgECF4AFAj/pgnMFCQwzI8sA"
+            + "CgkQaLeriVdUjc2CugCfRrOIfllp3mSmGpHgIxvg5V8vtMcAn0BvKVehOn+12Yvn"
+            + "9BCHfg34jUZbiF0EExECAB0DCwQDBRUDAgYBAxYCAQIXgAUCP+mCcwUJDDMjywAK"
+            + "CRBot6uJV1SNzYK6AJ9x7R+daNIjkieNW6lJeVUIoj1UHgCeLZm025uULML/5DFs"
+            + "4tUvXs8n9XiZAaIENaIg8xEEALYPe0XNsPjx+inTQ+Izz527ZJnoc6BhWik/4a2b"
+            + "ZYENSOQXAMKTDQMv2lLeI0i6ceB967MNubhHeVdNeOWYHFSM1UGRfhmZERISho3b"
+            + "p+wVZvVG8GBVwpw34PJjgYU/0tDwnJaJ8BzX6j0ecTSTjQPnaUEtdJ/u/gmG9j02"
+            + "18TzAKDihdNoKJEU9IKUiSjdGomSuem/VwQArHfaucSiDmY8+zyZbVLLnK6UJMqt"
+            + "sIv1LvAg20xwXoUk2bY8H3tXL4UZ8YcoSXYozwALq3cIo5UZJ0q9Of71mI8WLK2i"
+            + "FSYVplpTX0WMClAdkGt3HgVb7xtOhGt1mEKeRQjNZ2LteUQrRDD9MTQ+XxcvEN0I"
+            + "pAj4kBJe9bR6HzAD/iecCmGwSlHUZZrgqWzv78o79XxDdcuLdl4i2fL7kwEOf9js"
+            + "De7hGs27yrdJEmAG9QF9TOF9LJFmE1CqkgW+EpKxsY01Wjm0BFJB1R7iPUaUtFRZ"
+            + "xYqfgXarmPjql2iBi+cVjLzGu+4BSojVAPgP/hhcnIowf4M4edPiICMP1GVjtCFX"
+            + "ZXJuZXIgS29jaCA8d2VybmVyLmtvY2hAZ3V1Zy5kZT6IYwQTEQIAGwUCNs8JNwUJ"
+            + "CCCxRAMLCgMDFQMCAxYCAQIXgAASCRBsfuG4YhzAEwdlR1BHAAEBaSAAn3YkpT5h"
+            + "xgehGFfnX7izd+c8jI0SAJ9qJZ6jJvXnGB07p60aIPYxgJbLmYkAdQMFEDWjdxQd"
+            + "GfTBDJhXpQEBPfMC/0cxo+4xYVAplFO0nIYyjQgP7D8O0ufzPsIwF3kvb7b5FNNj"
+            + "fp+DAhN6G0HOIgkL3GsWtCfH5UHali+mtNFIKDpTtr+F/lPpZP3OPzzsLZS4hYTq"
+            + "mMs1O/ACq8axKgAilYkBXwMFEDWiJw4DbxG4/z6qCxADB9wFH0i6mmn6rWYKFepJ"
+            + "hXyhE4wWqRPJAnvfoiWUntDp4aIQys6lORigVXIWo4k4SK/FH59YnzF7578qrTZW"
+            + "/RcA0bIqJqzqaqsOdTYEFa49cCjvLnBW4OebJlLTUs/nnmU0FWKW8OwwL+pCu8d7"
+            + "fLSSnggBsrUQwbepuw0cJoctFPAz5T1nQJieQKVsHaCNwL2du0XefOgF5ujB1jK1"
+            + "q3p4UysF9hEcBR9ltE3THr+iv4jtZXmC1P4at9W5LFWsYuwr0U3yJcaKSKp0v/wG"
+            + "EWe2J/gFQZ0hB1+35RrCZPgiWsEv87CHaG6XtQ+3HhirBCJsYhmOikVKoEan6PhU"
+            + "VR1qlXEytpAt389TBnvyceAX8hcHOE3diuGvILEgYes3gw3s5ZmM7bUX3jm2BrX8"
+            + "WchexUFUQIuKW2cL379MFXR8TbxpVxrsRYE/4jHZBYhGBBARAgAGBQI27U4LAAoJ"
+            + "EF3iSZZbA1iifJoAoLEsGy16hV/CfmDku6D1CBUIxXvpAJ9GBApdC/3OXig7sBrV"
+            + "CWOb3MQzcLkBjQQ2zwcIEAYA9zWEKm5eZpMMBRsipL0IUeSKEyeKUjABX4vYNurl"
+            + "44+2h6Y8rHn7rG1l/PNj39UJXBkLFj1jk8Q32v+3BQDjvwv8U5e/kTgGlf7hH3WS"
+            + "W38RkZw18OXYCvnoWkYneIuDj6/HH2bVNXmTac05RkBUPUv4yhqlaFpkVcswKGuE"
+            + "NRxujv/UWvVF+/2P8uSQgkmGp/cbwfMTkC8JBVLLBRrJhl1uap2JjZuSVklUUBez"
+            + "Vf3NJMagVzx47HPqLVl4yr4bAAMGBf9PujlH5I5OUnvZpz+DXbV/WQVfV1tGRCra"
+            + "kIj3mpN6GnUDF1LAbe6vayUUJ+LxkM1SqQVcmuy/maHXJ+qrvNLlPqUZPmU5cINl"
+            + "sA7bCo1ljVUp54J1y8PZUx6HxfEl/LzLVkr+ITWnyqeiRikDecUf4kix2teTlx6I"
+            + "3ecqT5oNqZSRXWwnN4SbkXtAd7rSgEptUYhQXgSEarp1pXJ4J4rgqFa49jKISDJq"
+            + "rn/ElltHe5Fx1bpfkCIYlYk45Cga9bOIVAQYEQIADAUCNs8HCAUJBvPJAAASCRBs"
+            + "fuG4YhzAEwdlR1BHAAEBeRUAoIGpCDmMy195TatlloHAJEjZu5KaAJwOvW989hOb"
+            + "8cg924YIFVA1+4/Ia7kBjQQ1oiE8FAYAkQmAlOXixb8wra83rE1i7LCENLzlvBZW"
+            + "KBXN4ONelZAnnkOm7IqRjMhtKRJN75zqVyKUaUwDKjpf9J5K2t75mSxBtnbNRqL3"
+            + "XodjHK93OcAUkz3ci7iuC/b24JI2q4XeQG/v4YR1VodM0zEQ1IC0JCq4Pl39QZyX"
+            + "JdZCrUFvMcXq5ruNSldztBqTFFUiFbkw1Fug/ZyXJve2FVcbsRXFrB7EEuy+iiU/"
+            + "kZ/NViKk0L4T6KRHVsEiriNlCiibW19fAAMFBf9Tbv67KFMDrLqQan/0oSSodjDQ"
+            + "KDGqtoh7KQYIKPXqfqT8ced9yd5MLFwPKf3t7AWG1ucW2x118ANYkPSU122UTndP"
+            + "sax0cY4XkaHxaNwpNFCotGQ0URShxKNpcqbdfvy+1d8ppEavgOyxnV1JOkLjZJLw"
+            + "K8bgxFdbPWcsJJnjuuH3Pwz87CzTgOSYQxMPnIwQcx5buZIV5NeELJtcbbd3RVua"
+            + "K/GQht8QJpuXSji8Nl1FihYDjACR8TaRlAh50GmIRgQoEQIABgUCOCv7gwAKCRBs"
+            + "fuG4YhzAE9hTAJ9cRHu+7q2hkxpFfnok4mRisofCTgCgzoPjNIuYiiV6+wLB5o11"
+            + "7MNWPZCIVAQYEQIADAUCNaIhPAUJB4TOAAASCRBsfuG4YhzAEwdlR1BHAAEBDfUA"
+            + "oLstR8cg5QtHwSQ3nFCOKEREUFIwAKDID3K3hM+b6jW1o+tNX9dnjb+YMZkAbQIw"
+            + "bYOUAAABAwC7ltmO5vdKssohwzXEZeYvDW2ll3CYD2I+ruiNq0ybxkfFBopq9cxt"
+            + "a0OvVML4LK/TH+60f/Fqx9wg2yk9APXyaomdLrXfWyfZ91YtNCfj3ElC4XB4qqm0"
+            + "HRn0wQyYV6UABRG0IVdlcm5lciBLb2NoIDx3ZXJuZXIua29jaEBndXVnLmRlPokA"
+            + "lQMFEDRfoOmOB31Gi6BmjQEBzwgD/2fHcdDXuRRY+SHvIVESweijstB+2/sVRp+F"
+            + "CDjR74Kg576sJHfTJCxtSSmzpaVpelb5z4URGJ/Byi5L9AU7hC75S1ZnJ+MjBT6V"
+            + "ePyk/r0uBrMkU/lMG7lk/y2By3Hll+edjzJsdwn6aoNPiyen4Ch4UGTEguxYsLq0"
+            + "HES/UvojiQEVAwUTNECE2gnp+QqKck5FAQH+1Af/QMlYPlLG+5E19qP6AilKQUzN"
+            + "kd1TWMenXTS66hGIVwkLVQDi6RCimhnLMq/F7ENA8bSbyyMuncaBz5dH4kjfiDp1"
+            + "o64LULcTmN1LW9ctpTAIeLLJZnwxoJLkUbLUYKADKqIBXHMt2B0zRmhFOqEjRN+P"
+            + "hI7XCcHeHWHiDeUB58QKMyeoJ/QG/7zLwnNgDN2PVqq2E72C3ye5FOkYLcHfWKyB"
+            + "Rrn6BdUphAB0LxZujSGk8ohZFbia+zxpWdE8xSBhZbjVGlwLurmS2UTjjxByBNih"
+            + "eUD6IC3u5P6psld0OfqnpriZofP0CBP2oTk65r529f/1lsy2kfWrVPYIFJXEnIkA"
+            + "lQMFEDQyneGkWMS9SnJfMQEBMBMD/1ADuhhuY9kyN7Oj6DPrDt5SpPQDGS0Jtw3y"
+            + "uIPoed+xyzlrEuL2HeaOj1O9urpn8XLN7V21ajkzlqsxnGkOuifbE9UT67o2b2vC"
+            + "ldCcY4nV5n+U1snMDwNv+RkcEgNa8ANiWkm03UItd7/FpHDQP0FIgbPEPwRoBN87"
+            + "I4gaebfRiQCVAwUQNDUSwxRNm5Suj3z1AQGMTAP/UaXXMhPzcjjLxBW0AccTdHUt"
+            + "Li+K+rS5PNxxef2nnasEhCdK4GkM9nwJgsP0EZxCG3ZSAIlWIgQ3MK3ZAV1Au5pL"
+            + "KolRjFyEZF420wAtiE7V+4lw3FCqNoXDJEFC3BW431kx1wAhDk9VaIHHadYcof4d"
+            + "dmMLQOW2cJ7LDEEBW/WJAJUDBRA0M/VQImbGhU33abUBARcoA/9eerDBZGPCuGyE"
+            + "mQBcr24KPJHWv/EZIKl5DM/Ynz1YZZbzLcvEFww34mvY0jCfoVcCKIeFFBMKiSKr"
+            + "OMtoVC6cQMKpmhE9hYRStw4E0bcf0BD/stepdVtpwRnG8SDP2ZbmtgyjYT/7T4Yt"
+            + "6/0f6N/0NC7E9qfq4ZlpU3uCGGu/44kAlQMFEDQz8kp2sPVxuCQEdQEBc5YD/Rix"
+            + "vFcLTO1HznbblrO0WMzQc+R4qQ50CmCpWcFMwvVeQHo/bxoxGggNMmuVT0bqf7Mo"
+            + "lZDSJNS96IAN32uf25tYHgERnQaMhmi1aSHvRDh4jxFu8gGVgL6lWit/vBDW/BiF"
+            + "BCH6sZJJrGSuSdpecTtaWC8OJGDoKTO9PqAA/HQRiQB1AwUQNDJSx011eFs7VOAZ"
+            + "AQGdKQL/ea3qD2OP3wVTzXvfjQL1CosX4wyKusBBhdt9u2vOT+KWkiRk1o35nIOG"
+            + "uZLHtSFQDY8CVDOkqg6g4sVbOcTl8QUwHA+A4AVDInwTm1m4Bk4oeCIwk4Bp6mDd"
+            + "W11g28k/iQEVAgUSNDIWPm/Y4wPDeaMxAQGvBQgAqGhzA/21K7oL/L5S5Xz//eO7"
+            + "J8hgvqqGXWd13drNy3bHbKPn7TxilkA3ca24st+6YPZDdSUHLMCqg16YOMyQF8gE"
+            + "kX7ZHWPacVoUpCmSz1uQ3p6W3+u5UCkRpgQN8wBbJx5ZpBBqeq5q/31okaoNjzA2"
+            + "ghEWyR5Ll+U0C87MY7pc7PlNHGCr0ZNOhhtf1jU+H9ag5UyT6exIYim3QqWYruiC"
+            + "LSUcim0l3wK7LMW1w/7Q6cWfAFQvl3rGjt3rg6OWg9J4H2h5ukf5JNiRybkupmat"
+            + "UM+OVMRkf93jzU62kbyZpJBHiQZuxxJaLkhpv2RgWib9pbkftwEy/ZnmjkxlIIkA"
+            + "lQMFEDQvWjh4313xYR8/NQEB37QEAIi9vR9h9ennz8Vi7RNU413h1ZoZjxfEbOpk"
+            + "QAjE/LrZ/L5WiWdoStSiyqCLPoyPpQafiU8nTOr1KmY4RgceJNgxIW4OiSMoSvrh"
+            + "c2kqP+skb8A2B4+47Aqjr5fSAVfVfrDMqDGireOguhQ/hf9BOYsM0gs+ROdtyLWP"
+            + "tMjRnFlviD8DBRAz8qQSj6lRT5YOKXIRAntSAJ9StSEMBoFvk8iRWpXb6+LDNLUW"
+            + "zACfT8iY3IxwvMF6jjCHrbuxQkL7chSJARUDBRA0MMO7569NIyeqD3EBATIAB/4t"
+            + "CPZ1sLWO07g2ZCpiP1HlYpf5PENaXtaasFvhWch7eUe3DksuMEPzB5GnauoQZAku"
+            + "hEGkoEfrfL3AXtXH+WMm2t7dIcTBD4p3XkeZ+PgJpKiASXDyul9rumXXvMxSL4KV"
+            + "7ar+F1ZJ0ycCx2r2au0prPao70hDAzLTy16hrWgvdHSK7+wwaYO5TPCL5JDmcB+d"
+            + "HKW72qNUOD0pxbe0uCkkb+gDxeVX28pZEkIIOMMV/eAs5bs/smV+eJqWT/EyfVBD"
+            + "o7heF2aeyJj5ecxNOODr88xKF7qEpqazCQ4xhvFY+Yn6+vNCcYfkoZbOn0XQAvqf"
+            + "a2Vab9woVIVSaDji/mlPiQB1AwUQNDC233FfeD4HYGBJAQFh6QL/XCgm5O3q9kWp"
+            + "gts1MHKoHoh7vxSSQGSP2k7flNP1UB2nv4sKvyGM8eJKApuROIodcTkccM4qXaBu"
+            + "XunMr5kJlvDJPm+NLzKyhtQP2fWI7xGYwiCiB29gm1GFMjdur4amiQEVAwUQNDBR"
+            + "9fjDdqGixRdJAQE+mAf+JyqJZEVFwNwZ2hSIMewekC1r7N97p924nqfZKnzn6weF"
+            + "pE80KIJSWtEVzI0XvHlVCOnS+WRxn7zxwrOTbrcEOy0goVbNgUsP5ypZa2/EM546"
+            + "uyyJTvgD0nwA45Q4bP5sGhjh0G63r9Vwov7itFe4RDBGM8ibGnZTr9hHo469jpom"
+            + "HSNeavcaUYyEqcr4GbpQmdpJTnn/H0A+fMl7ZHRoaclNx9ZksxihuCRrkQvUOb3u"
+            + "RD9lFIhCvNwEardN62dKOKJXmn1TOtyanZvnmWigU5AmGuk6FpsClm3p5vvlid64"
+            + "i49fZt9vW5krs2XfUevR4oL0IyUl+qW2HN0DIlDiAYkAlQMFEDQvbv2wcgJwUPMh"
+            + "JQEBVBID/iOtS8CQfMxtG0EmrfaeVUU8R/pegBmVWDBULAp8CLTtdfxjVzs/6DXw"
+            + "0RogXMRRl2aFfu1Yp0xhBYjII6Kque/FzAFXY9VNF1peqnPt7ADdeptYMppZa8sG"
+            + "n9BBRu9Fsw69z6JkyqvMiVxGcKy3XEpVGr0JHx8Xt6BYdrULiKr2iQB1AwUQNC68"
+            + "n6jZR/ntlUftAQFaYgL+NUYEj/sX9M5xq1ORX0SsVPMpNamHO3JBSmZSIzjiox5M"
+            + "AqoFOCigAkonuzk5aBy/bRHy1cmDBOxf4mNhzrH8N6IkGvPE70cimDnbFvr+hoZS"
+            + "jIqxtELNZsLuLVavLPAXiQCVAwUQNC6vWocCuHlnLQXBAQHb1gQAugp62aVzDCuz"
+            + "4ntfXsmlGbLY7o5oZXYIKdPP4riOj4imcJh6cSgYFL6OMzeIp9VW/PHo2mk8kkdk"
+            + "z5uif5LqOkEuIxgra7p1Yq/LL4YVhWGQeD8hwpmu+ulYoPOw40dVYS36PwrHIH9a"
+            + "fNhl8Or5O2VIHIWnoQ++9r6gwngFQOyJAJUDBRAzHnkh1sNKtX1rroUBAWphBACd"
+            + "huqm7GHoiXptQ/Y5F6BivCjxr9ch+gPSjaLMhq0kBHVO+TbXyVefVVGVgCYvFPjo"
+            + "zM8PEVykQAtY//eJ475aGXjF+BOAhl2z0IMkQKCJMExoEDHbcj0jIIMZ2/+ptgtb"
+            + "FSyJ2DQ3vvCdbw/1kyPHTPfP+L2u40GWMIYVBbyouokAlQMFEDMe7+UZsymln7HG"
+            + "2QEBzMED/3L0DyPK/u6PyAd1AdpjUODTkWTZjZ6XA2ubc6IXXsZWpmCgB/24v8js"
+            + "J3DIsvUD3Ke55kTr6xV+au+mAkwOQqWUTUWfQCkSrSDlbUJ1VPBzhyTpuzjBopte"
+            + "7o3R6XXfcLiC5jY6eCX0QtLGhKpLjTr5uRhf1fYODGsAGXmCByDviQB1AgUQMy6U"
+            + "MB0Z9MEMmFelAQHV4AMAjdFUIyFtpTr5jkyZSd3y//0JGO0z9U9hLVxeBBCwvdEQ"
+            + "xsrpeTtVdqpeKZxHN1GhPCYvgLFZAQlcPh/Gc8u9uO7wVSgJc3zYKFThKpQevdF/"
+            + "rzjTCHfgigf5Iui0qiqBiQCVAwUQMx22bAtzgG/ED06dAQFi0gQAkosqTMWy+1eU"
+            + "Xbi2azFK3RX5ERf9wlN7mqh7TvwcPXvVWzUARnwRv+4kk3uOWI18q5UPis7KH3KY"
+            + "OVeRrPd8bbp6SjhBh82ourTEQUXLBDQiI1V1cZZmwwEdlnAnhFnkXgMBNM2q7oBe"
+            + "fRHADfYDfGo90wXyrVVL+GihDNpzUwOJAJUDBRAzHUFnOWvfULwOR3EBAbOYA/90"
+            + "JIrKmxhwP6quaheFOjjPoxDGEZpGJEOwejEByYj+AgONCRmQS3BydtubA+nm/32D"
+            + "FeG8pe/dnFvGc+QgNW560hK21C2KJj72mhjRlg/na7jz4/MmBAv5k61Q7roWi0rw"
+            + "x+R9NSHxpshC8A92zmvo8w/XzVSogC8pJ04jcnY6YokAlQMFEDMdPtta9LwlvuSC"
+            + "3QEBvPMD/3TJGroHhHYjHhiEpDZZVszeRQ0cvVI/uLLi5yq3W4F6Jy47DF8VckA7"
+            + "mw0bXrOMNACN7Je7uyaU85qvJC2wgoQpFGdFlkjmkAwDAjR+koEysiE8FomiOHhv"
+            + "EpEY/SjSS4jj4IPmgV8Vq66XjPw+i7Z0RsPLOIf67yZHxypNiBiYiQCVAwUQMxxw"
+            + "pKrq6G7/78D5AQHo2QQAjnp6KxOl6Vvv5rLQ/4rj3OemvF7IUUq34xb25i/BSvGB"
+            + "UpDQVUmhv/qIfWvDqWGZedyM+AlNSfUWPWnP41S8OH+lcERH2g2dGKGl7kH1F2Bx"
+            + "ByZlqREHm2q624wPPA35RLXtXIx06yYjLtJ7b+FCAX6PUgZktZYk5gwjdoAGrC2J"
+            + "AJUDBRAzGvcCKC6c7f53PGUBAUozA/9l/qKmcqbi8RtLsKQSh3vHds9d22zcbkuJ"
+            + "PBSoOv2D7i2VLshaQFjq+62uYZGE6nU1WP5sZcBDuWjoX4t4NrffnOG/1R9D0t1t"
+            + "9F47D77HJzjvo+J52SN520YHcbT8VoHdPRoEOXPN4tzhvn2GapVVdaAlWM0MLloh"
+            + "NH3I9jap9okAdQMFEDMZlUAnyXglSykrxQEBnuwC/jXbFL+jzs2HQCuo4gyVrPlU"
+            + "ksQCLYZjNnZtw1ca697GV3NhBhSXR9WHLQH+ZWnpTzg2iL3WYSdi9tbPs78iY1FS"
+            + "d4EG8H9V700oQG8dlICF5W2VjzR7fByNosKM70WSXYkBFQMFEDMWBsGCy1t9eckW"
+            + "HQEBHzMH/jmrsHwSPrA5R055VCTuDzdS0AJ+tuWkqIyqQQpqbost89Hxper3MmjL"
+            + "Jas/VJv8EheuU3vQ9a8sG2SnlWKLtzFqpk7TCkyq/H3blub0agREbNnYhHHTGQFC"
+            + "YJb4lWjWvMjfP+N5jvlLcnDqQPloXfAOgy7W90POoqFrsvhxdpnXgoLrzyNNja1O"
+            + "1NRj+Cdv/GmJYNi6sQe43zmXWeA7syLKMw6058joDqEJFKndgSp3Zy/yXmObOZ/H"
+            + "C2OJwA3gzEaAu8Pqd1svwGIGznqtTNCn9k1+rMvJPaxglg7PXIJS282hmBl9AcJl"
+            + "wmh2GUCswl9/sj+REWTb8SgJUbkFcp6JAJUDBRAwdboVMPfsgxioXMEBAQ/LA/9B"
+            + "FTZ9T95P/TtsxeC7lm9imk2mpNQCBEvXk286FQnGFtDodGfBfcH5SeKHaUNxFaXr"
+            + "39rDGUtoTE98iAX3qgCElf4V2rzgoHLpuQzCg3U35dfs1rIxlpcSDk5ivaHpPV3S"
+            + "v+mlqWL049y+3bGaZeAnwM6kvGMP2uccS9U6cbhpw4hGBBARAgAGBQI3GtRfAAoJ"
+            + "EF3iSZZbA1iikWUAoIpSuXzuN/CI63dZtT7RL7c/KtWUAJ929SAtTr9SlpSgxMC8"
+            + "Vk1T1i5/SYkBFQMFEzccnFnSJilEzmrGwQEBJxwH/2oauG+JlUC3zBUsoWhRQwqo"
+            + "7DdqaPl7sH5oCGDKS4x4CRA23U15NicDI7ox6EizkwCjk0dRr1EeRK+RqL1b/2T4"
+            + "2B6nynOLhRG2A0BPHRRJLcoL4nKfoPSo/6dIC+3iVliGEl90KZZD5bnONrVJQkRj"
+            + "ZL8Ao+9IpmoYh8XjS5xMLEF9oAQqAkA93nVBm56lKmaL1kl+M3dJFtNKtVB8de1Z"
+            + "XifDs8HykD42qYVtcseCKxZXhC3UTG5YLNhPvgZKH8WBCr3zcR13hFDxuecUmu0M"
+            + "VhvEzoKyBYYt0rrqnyWrxwbv4gSTUWH5ZbgsTjc1SYKZxz6hrPQnfYWzNkznlFWJ"
+            + "ARUDBRM0xL43CdxwOTnzf10BATOCB/0Q6WrpzwPMofjHj54MiGLKVP++Yfwzdvns"
+            + "HxVpTZLZ5Ux8ErDsnLmvUGphnLVELZwEkEGRjln7a19h9oL8UYZaV+IcR6tQ06Fb"
+            + "1ldR+q+3nXtBYzGhleXdgJQSKLJkzPF72tvY0DHUB//GUV9IBLQMvfG8If/AFsih"
+            + "4iXi96DOtUAbeuIhnMlWwLJFeGjLLsX1u6HSX33xy4bGX6v/UcHbTSSYaxzb92GR"
+            + "/xpP2Xt332hOFRkDZL52g27HS0UrEJWdAVZbh25KbZEl7C6zX/82OZ5nTEziHo20"
+            + "eOS6Nrt2+gLSeA9X5h/+qUx30kTPz2LUPBQyIqLCJkHM8+0q5j9ciQCiAwUTNMS+"
+            + "HZFeTizbCJMJAQFrGgRlEAkG1FYU4ufTxsaxhFZy7xv18527Yxpls6mSCi1HL55n"
+            + "Joce6TI+Z34MrLOaiZljeQP3EUgzA+cs1sFRago4qz2wS8McmQ9w0FNQQMz4vVg9"
+            + "CVi1JUVd4EWYvJpA8swDd5b9+AodYFEsfxt9Z3aP+AcWFb10RlVVsNw9EhObc6IM"
+            + "nwAOHCEI9vp5FzzFiQCVAwUQNxyr6UyjTSyISdw9AQHf+wP+K+q6hIQ09tkgaYaD"
+            + "LlWKLbuxePXqM4oO72qi70Gkg0PV5nU4l368R6W5xgR8ZkxlQlg85sJ0bL6wW/Sj"
+            + "Mz7pP9hkhNwk0x3IFkGMTYG8i6Gt8Nm7x70dzJoiC+A496PryYC0rvGVf+Om8j5u"
+            + "TexBBjb/jpJhAQ/SGqeDeCHheOC0Lldlcm5lciBLb2NoIChtZWluIGFsdGVyIGtl"
+            + "eSkgPHdrQGNvbXB1dGVyLm9yZz6JAHUDBRM2G2MyHRn0wQyYV6UBASKKAv4wzmK7"
+            + "a9Z+g0KH+6W8ffIhzrQo8wDAU9X1WJKzJjS205tx4mmdnAt58yReBc/+5HXTI8IK"
+            + "R8IgF+LVXKWAGv5P5AqGhnPMeQSCs1JYdf9MPvbe34jD8wA1LTWFXn9e/cWIRgQQ"
+            + "EQIABgUCNxrUaQAKCRBd4kmWWwNYovRiAJ9dJBVfjx9lGARoFXmAieYrMGDrmwCZ"
+            + "AQyO4Wo0ntQ+iq4do9M3/FTFjiCZAaIENu1I6REEAJRGEqcYgXJch5frUYBj2EkD"
+            + "kWAbhRqVXnmiF3PjCEGAPMMYsTddiU7wcKfiCAqKWWXow7BjTJl6Do8RT1jdKpPO"
+            + "lBJXqqPYzsyBxLzE6mLps0K7SLJlSKTQqSVRcx0jx78JWYGlAlP0Kh9sPV2w/rPh"
+            + "0LrPeOKXT7lZt/DrIhfPAKDL/sVqCrmY3QfvrT8kSKJcgtLWfQP/cfbqVNrGjW8a"
+            + "m631N3UVA3tWfpgM/T9OjmKmw44NE5XfPJTAXlCV5j7zNMUkDeoPkrFF8DvbpYQs"
+            + "4XWYHozDjhR2Q+eI6gZ0wfmhLHqqc2eVVkEG7dT57Wp9DAtCMe7RZfhnarTQMqlY"
+            + "tOEa/suiHk0qLo59NsyF8eh68IDNCeYD/Apzonwaq2EQ1OEpfFlp6LcSnS34+UGZ"
+            + "tTO4BgJdmEjr/QrIPp6bJDstgho+/2oR8yQwuHGJwbS/8ADA4IFEpLduSpzrABho"
+            + "7RuNQcm96bceRY+7Hza3zf7pg/JGdWOb+bC3S4TIpK+3sx3YNWs7eURwpGREeJi5"
+            + "/Seic+GXlGzltBpXZXJuZXIgS29jaCA8d2tAZ251cGcub3JnPohjBBMRAgAbBQI3"
+            + "Gs+QBQkMyXyAAwsKAwMVAwIDFgIBAheAABIJEF3iSZZbA1iiB2VHUEcAAQFdwgCe"
+            + "O/s43kCLDMIsHCb2H3LC59clC5UAn1EyrqWk+qcOXLpQIrP6Qa3QSmXIiEYEEBEC"
+            + "AAYFAjca0T0ACgkQbH7huGIcwBOF9ACeNwO8G2G0ei03z0g/n3QZIpjbzvEAnRaE"
+            + "qX2PuBbClWoIP6h9yrRlAEbUiQB1AwUQNxrRYx0Z9MEMmFelAQHRrgL/QDNKPV5J"
+            + "gWziyzbHvEKfTIw/Ewv6El2MadVvQI8kbPN4qkPr2mZWwPzuc9rneCPQ1eL8AOdC"
+            + "8+ZyxWzx2vsrk/FcU5donMObva2ct4kqJN6xl8xjsxDTJhBSFRaiBJjxiEYEEBEC"
+            + "AAYFAjca0aMACgkQaLeriVdUjc0t+ACghK37H2vTYeXXieNJ8aZkiPJSte4An0WH"
+            + "FOotQdTW4NmZJK+Uqk5wbWlgiEYEEBECAAYFAjdPH10ACgkQ9u7fIBhLxNktvgCe"
+            + "LnQ5eOxAJz+Cvkb7FnL/Ko6qc5YAnjhWWW5c1o3onvKEH2Je2wQa8T6iiEYEEBEC"
+            + "AAYFAjenJv4ACgkQmDRl2yFDlCJ+yQCfSy1zLftEfLuIHZsUHis9U0MlqLMAn2EI"
+            + "f7TI1M5OKysQcuFLRC58CfcfiEUEEBECAAYFAjfhQTMACgkQNmdg8X0u14h55wCf"
+            + "d5OZCV3L8Ahi4QW/JoXUU+ZB0M0AmPe2uw7WYDLOzv48H76tm6cy956IRgQQEQIA"
+            + "BgUCOCpiDwAKCRDj8lhUEo8OeRsdAJ9FHupRibBPG2t/4XDqF+xiMLL/8ACfV5F2"
+            + "SR0ITE4k/C+scS1nJ1KZUDW0C1dlcm5lciBLb2NoiGMEExECABsFAjbtSOoFCQzJ"
+            + "fIADCwoDAxUDAgMWAgECF4AAEgkQXeJJllsDWKIHZUdQRwABAbXWAJ9SCW0ieOpL"
+            + "7AY6vF+OIaMmw2ZW1gCgkto0eWfgpjAuVg6jXqR1wHt2pQOJAh4EEBQDAAYFAjcv"
+            + "WdQACgkQbEwxpbHVFWcNxQf/bg14WGJ0GWMNSuuOOR0WYzUaNtzYpiLSVyLrreXt"
+            + "o8LBNwzbgzj2ramW7Ri+tYJAHLhtua8ZgSeibmgBuZasF8db1m5NN1ZcHBXGTysA"
+            + "jp+KnicTZ9Orj75D9o3oSmMyRcisEhr+gkj0tVhGfOAOC6eKbufVuyYFDVIyOyUB"
+            + "GlW7ApemzAzYemfs3DdjHn87lkjHMVESO4fM5rtLuSc7cBfL/e6ljaWQc5W8S0gI"
+            + "Dv0VtL39pMW4BlpKa25r14oJywuUpvWCZusvDm7ZJnqZ/WmgOHQUsyYudTROpGIb"
+            + "lsNg8iqC6huWpGSBRdu3oRQRhkqpfVdszz6BB/nAx01q2wf/Q+U9XId1jyzxUL1S"
+            + "GgaYMf6QdyjHQ1oxuFLNxzM6C/M069twbNgXJ71RsDDXVxFZfSTjSiH100AP9+9h"
+            + "b5mycaXLUOXYDvOSFzHBd/LsjFNVrrFbDs5Xw+cLGVHOIgR5IWAfgu5d1PAZU9uQ"
+            + "VgdGnQfmZg383RSPxvR3fnZz1rHNUGmS6w7x6FVbxa1QU2t38gNacIwHATAPcBpy"
+            + "JLfXoznbpg3ADbgCGyDjBwnuPQEQkYwRakbczRrge8IaPZbt2HYPoUsduXMZyJI8"
+            + "z5tvu7pUDws51nV1EX15BcN3++aY5pUyA1ItaaDymQVmoFbQC0BNMzMO53dMnFko"
+            + "4i42kohGBBARAgAGBQI3OvmjAAoJEHUPZJXInZM+hosAnRntCkj/70shGTPxgpUF"
+            + "74zA+EbzAKCcMkyHXIz2W0Isw3gDt27Z9ggsE4hGBBARAgAGBQI3NyPFAAoJEPbu"
+            + "3yAYS8TZh2UAoJVmzw85yHJzsXQ1vpO2IAPfv59NAJ9WY0oiYqb3q1MSxBRwG0gV"
+            + "iNCJ7YkBFQMFEDdD3tNSgFdEdlNAHQEByHEH/2JMfg71GgiyGJTKxCAymdyf2j2y"
+            + "fH6wI782JK4BWV4c0E/V38q+jpIYslihV9t8s8w1XK5niMaLwlCOyBWOkDP3ech6"
+            + "+GPPtfB3cmlL2hS896PWZ1adQHgCeQpB837n56yj0aTs4L1xarbSVT22lUwMiU6P"
+            + "wYdH2Rh8nh8FvN0IZsbln2nOj73qANQzNflmseUKF1Xh4ck8yLrRd4r6amhxAVAf"
+            + "cYFRJN4zdLL3cmhgkt0ADZlzAwXnEjwdHHy7SvAJk1ecNOA9pFsOJbvnzufd1afs"
+            + "/CbG78I+0JDhg75Z2Nwq8eKjsKqiO0zz/vG5yWSndZvWkTWz3D3b1xr1Id2IRgQQ"
+            + "EQIABgUCOCpiHgAKCRDj8lhUEo8OeQ+QAKCbOTscyUnWHSrDo4fIy0MThEjhOgCe"
+            + "L4Kb7TWkd/OHQScVBO8sTUz0+2g=");
+
+//		private static readonly byte[] pub6check = Base64.Decode("62O9");
+
+        //
+        // revoked sub key
+        //
+        private static readonly byte[] pub7 = Base64.Decode(
+            "mQGiBEFOsIwRBADcjRx7nAs4RaWsQU6p8/ECLZD9sSeYc6CN6UDI96RKj0/hCzMs"
+            + "qlA0+9fzGZ7ZEJ34nuvDKlhKGC7co5eOiE0a9EijxgcrZU/LClZWa4YfyNg/ri6I"
+            + "yTyfOfrPQ33GNQt2iImDf3FKp7XKuY9nIxicGQEaW0kkuAmbV3oh0+9q8QCg/+fS"
+            + "epDEqEE/+nKONULGizKUjMED/RtL6RThRftZ9DOSdBytGYd48z35pca/qZ6HA36K"
+            + "PVQwi7V77VKQyKFLTOXPLnVyO85hyYB/Nv4DFHN+vcC7/49lfoyYMZlN+LarckHi"
+            + "NL154wmmzygB/KKysvWBLgkErEBCD0xBDd89iTQNlDtVQAWGORVffl6WWjOAkliG"
+            + "3dL6A/9A288HfFRnywqi3xddriV6wCPmStC3dkCS4vHk2ofS8uw4ZNoRlp1iEPna"
+            + "ai2Xa9DX1tkhaGk2k96MqqbBdGpbW8sMA9otJ9xdMjWEm/CgJUFUFQf3zaVy3mkM"
+            + "S2Lvb6P4Wc2l/diEEIyK8+PqJItSh0OVU3K9oM7ngHwVcalKILQVUkV2b2tlZCA8"
+            + "UmV2b2tlZEB0ZWQ+iQBOBBARAgAOBQJBTrCMBAsDAgECGQEACgkQvglkcFA/c63+"
+            + "QgCguh8rsJbPTtbhZcrqBi5Mo1bntLEAoPZQ0Kjmu2knRUpHBeUemHDB6zQeuQIN"
+            + "BEFOsIwQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz"
+            + "0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRP"
+            + "xfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvN"
+            + "ILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dD"
+            + "ox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMI"
+            + "PWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/93zriSvSHqsi1FeEmUBo431Jkh"
+            + "VerIzb6Plb1j6FIq+s3vyvx9K+dMvjotZqylWZj4GXpH+2xLJTjWkrGSfUZVI2Nk"
+            + "nyOFxUCKLLqaqVBFAQIjULfvQfGEWiGQKk9aRLkdG+D+8Y2N9zYoBXoQ9arvvS/t"
+            + "4mlOsiuaTe+BZ4x+BXTpF4b9sKZl7V8QP/TkoJWUdydkvxciHdWp7ssqyiKOFRhG"
+            + "818knDfFQ3cn2w/RnOb+7AF9wDncXDPYLfpPv9b2qZoLrXcyvlLffGDUdWs553ut"
+            + "1F5AprMURs8BGmY9BnjggfVubHdhTUoA4gVvrdaf+D9NwZAl0xK/5Y/oPuMZiQBG"
+            + "BBgRAgAGBQJBTrCMAAoJEL4JZHBQP3Ot09gAoMmLKloVDP+WhDXnsM5VikxysZ4+"
+            + "AKCrJAUO+lYAyPYwEwgK+bKmUGeKrIkARgQoEQIABgUCQU6wpQAKCRC+CWRwUD9z"
+            + "rQK4AJ98kKFxGU6yhHPr6jYBJPWemTNOXgCfeGB3ox4PXeS4DJDuLy9yllytOjo=");
+
+//		private static readonly byte[] pub7check = Base64.Decode("f/YQ");
+
+        private static readonly byte[] pub8 = Base64.Decode(
+            "mQGiBEEcraYRBADFYj+uFOhHz5SdECvJ3Z03P47gzmWLQ5HH8fPYC9rrv7AgqFFX"
+            + "aWlJJVMLua9e6xoCiDWJs/n4BbZ/weL/11ELg6XqUnzFhYyz0H2KFsPgQ/b9lWLY"
+            + "MtcPMFy5jE33hv/ixHgYLFqoNaAIbg0lzYEW/otQ9IhRl16fO1Q/CQZZrQCg/9M2"
+            + "V2BTmm9RYog86CXJtjawRBcD/RIqU0zulxZ2Zt4javKVxrGIwW3iBU935ebmJEIK"
+            + "Y5EVkGKBOCvsApZ+RGzpYeR2uMsTnQi8RJgiAnjaoVPCdsVJE7uQ0h8XuJ5n5mJ2"
+            + "kLCFlF2hj5ViicZzse+crC12CGtgRe8z23ubLRcd6IUGhVutK8/b5knZ22vE14JD"
+            + "ykKdA/96ObzJQdiuuPsEWN799nUUCaYWPAoLAmiXuICSP4GEnxLbYHWo8zhMrVMT"
+            + "9Q5x3h8cszUz7Acu2BXjP1m96msUNoxPOZtt88NlaFz1Q/JSbQTsVOMd9b/IRN6S"
+            + "A/uU0BiKEMHXuT8HUHVPK49oCKhZrGFP3RT8HZxDKLmR/qrgZ7ABh7QhSmlhIFlp"
+            + "eXUgPHl5amlhQG5vd21lZGlhdGVjaC5jb20+sAMD//+JAF0EEBECAB0FAkEcraYH"
+            + "CwkIBwMCCgIZAQUbAwAAAAUeAQAAAAAKCRD0/lb4K/9iFJlhAKCRMifQewiX5o8F"
+            + "U099FG3QnLVUZgCfWpMOsHulGHfNrxdBSkE5Urqh1ymwAWe5Ag0EQRytphAIAPZC"
+            + "V7cIfwgXcqK61qlC8wXo+VMROU+28W65Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdM"
+            + "ZIZJ+AyDvWXpF9Sh01D49Vlf3HZSTz09jdvOmeFXklnN/biudE/F/Ha8g8VHMGHO"
+            + "fMlm/xX5u/2RXscBqtNbno2gpXI61Brwv0YAWCvl9Ij9WE5J280gtJ3kkQc2azNs"
+            + "OA1FHQ98iLMcfFstjvbzySPAQ/ClWxiNjrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq"
+            + "/zzhsSlAGBGNfISnCnLWhsQDGcgHKXrKlQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2J"
+            + "SyIZJrqrol7DVekyCzsAAgIH/3K2wKRSzkIpDfZR25+tnQ8brv3TYoDZo3/wN3F/"
+            + "r6PGjx0150Q8g8EAC0bqm4rXWzOqdSxYxvIPOAGm5P4y+884yS6j3vKcXitT7vj+"
+            + "ODc2pVwGDLDjrMRrosSK89ycPCK6R/5pD7Rv4l9DWi2fgLvXqJHS2/ujUf2uda9q"
+            + "i9xNMnBXIietR82Sih4undFUOwh6Mws/o3eed9DIdaqv2Y2Aw43z/rJ6cjSGV3C7"
+            + "Rkf9x85AajYA3LwpS8d99tgFig2u6V/A16oi6/M51oT0aR/ZAk50qUc4WBk9uRUX"
+            + "L3Y+P6v6FCBE/06fgVltwcQHO1oKYKhH532tDL+9mW5/dYGwAYeJAEwEGBECAAwF"
+            + "AkEcraYFGwwAAAAACgkQ9P5W+Cv/YhShrgCg+JW8m5nF3R/oZGuG87bXQBszkjMA"
+            + "oLhGPncuGKowJXMRVc70/8qwXQJLsAFnmQGiBD2K5rYRBADD6kznWZA9nH/pMlk0"
+            + "bsG4nI3ELgyI7KpgRSS+Dr17+CCNExxCetT+fRFpiEvUcSxeW4pOe55h0bQWSqLo"
+            + "MNErXVJEXrm1VPkC08W8D/gZuPIsdtKJu4nowvdoA+WrI473pbeONGjaEDbuIJak"
+            + "yeKM1VMSGhsImdKtxqhndq2/6QCg/xARUIzPRvKr2TJ52K393895X1kEAMCdjSs+"
+            + "vABnhaeNNR5+NNkkIOCCjCS8qZRZ4ZnIayvn9ueG3KrhZeBIHoajUHrlTXBVj7XO"
+            + "wXVfGpW17jCDiqhU8Pu6VwEwX1iFbuUwqBffiRLXKg0zfcN+MyFKToi+VsJi4jiZ"
+            + "zcwUFMb8jE8tvR/muXti7zKPRPCbNBExoCt4A/0TgkzAosG/W4dUkkbc6XoHrjob"
+            + "iYuy6Xbs/JYlV0vf2CyuKCZC6UoznO5x2GkvOyVtAgyG4HSh1WybdrutZ8k0ysks"
+            + "mOthE7n7iczdj9Uwg2h+TfgDUnxcCAwxnOsX5UaBqGdkX1PjCWs+O3ZhUDg6UsZc"
+            + "7O5a3kstf16lHpf4q7ABAIkAYQQfEQIAIQUCPYrmtgIHABcMgBHRi/xlIgI+Q6LT"
+            + "kNJ7zKvTd87NHAAKCRDJM3gHb/sRj7bxAJ9f6mdlXQH7gMaYiY5tBe/FRtPr1gCf"
+            + "UhDJQG0ARvORFWHjwhhBMLxW7j2wAWC0KkRlc21vbmQgS2VlIDxkZXNtb25kLmtl"
+            + "ZUBub3dtZWRpYXRlY2guY29tPrADAQD9iQBYBBARAgAYBQI9iua2CAsDCQgHAgEK"
+            + "AhkBBRsDAAAAAAoJEMkzeAdv+xGP7v4An19iqadBCCgDIe2DTpspOMidwQYPAJ4/"
+            + "5QXbcn4ClhOKTO3ZEZefQvvL27ABYLkCDQQ9iua2EAgA9kJXtwh/CBdyorrWqULz"
+            + "Bej5UxE5T7bxbrlLOCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHT"
+            + "UPj1WV/cdlJPPT2N286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq"
+            + "01uejaClcjrUGvC/RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O"
+            + "9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcK"
+            + "ctaGxAMZyAcpesqVDNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TIL"
+            + "OwACAgf/SO+bbg+owbFKVN5HgOjOElQZVnCsegwCLqTeQzPPzsWmkGX2qZJPDIRN"
+            + "RZfJzti6+oLJwaRA/3krjviUty4VKhZ3lKg8fd9U0jEdnw+ePA7yJ6gZmBHL15U5"
+            + "OKH4Zo+OVgDhO0c+oetFpend+eKcvtoUcRoQoi8VqzYUNG0b/nmZGDlxQe1/ZNbP"
+            + "HpNf1BAtJXivCEKMD6PVzsLPg2L4tFIvD9faeeuKYQ4jcWtTkBLuIaZba3i3a4wG"
+            + "xTN20j9HpISVuLW/EfZAK1ef4DNjLmHEU9dMzDqfi+hPmMbGlFqcKr+VjcYIDuje"
+            + "o+92xm/EWAmlti88r2hZ3MySamHDrLABAIkATAQYEQIADAUCPYrmtgUbDAAAAAAK"
+            + "CRDJM3gHb/sRjzVTAKDVS+OJLMeS9VLAmT8atVCB42MwIQCgoh1j3ccWnhc/h6B7"
+            + "9Uqz3fUvGoewAWA=");
+
+        private static readonly byte[] sec8 = Base64.Decode(
+            "lQHpBEEcraYRBADFYj+uFOhHz5SdECvJ3Z03P47gzmWLQ5HH8fPYC9rrv7AgqFFX"
+            + "aWlJJVMLua9e6xoCiDWJs/n4BbZ/weL/11ELg6XqUnzFhYyz0H2KFsPgQ/b9lWLY"
+            + "MtcPMFy5jE33hv/ixHgYLFqoNaAIbg0lzYEW/otQ9IhRl16fO1Q/CQZZrQCg/9M2"
+            + "V2BTmm9RYog86CXJtjawRBcD/RIqU0zulxZ2Zt4javKVxrGIwW3iBU935ebmJEIK"
+            + "Y5EVkGKBOCvsApZ+RGzpYeR2uMsTnQi8RJgiAnjaoVPCdsVJE7uQ0h8XuJ5n5mJ2"
+            + "kLCFlF2hj5ViicZzse+crC12CGtgRe8z23ubLRcd6IUGhVutK8/b5knZ22vE14JD"
+            + "ykKdA/96ObzJQdiuuPsEWN799nUUCaYWPAoLAmiXuICSP4GEnxLbYHWo8zhMrVMT"
+            + "9Q5x3h8cszUz7Acu2BXjP1m96msUNoxPOZtt88NlaFz1Q/JSbQTsVOMd9b/IRN6S"
+            + "A/uU0BiKEMHXuT8HUHVPK49oCKhZrGFP3RT8HZxDKLmR/qrgZ/4JAwLXyWhb4pf4"
+            + "nmCmD0lDwoYvatLiR7UQVM2MamxClIiT0lCPN9C2AYIFgRWAJNS215Tjx7P/dh7e"
+            + "8sYfh5XEHErT3dMbsAGHtCFKaWEgWWl5dSA8eXlqaWFAbm93bWVkaWF0ZWNoLmNv"
+            + "bT6wAwP//4kAXQQQEQIAHQUCQRytpgcLCQgHAwIKAhkBBRsDAAAABR4BAAAAAAoJ"
+            + "EPT+Vvgr/2IUmWEAoJEyJ9B7CJfmjwVTT30UbdCctVRmAJ9akw6we6UYd82vF0FK"
+            + "QTlSuqHXKbABZ50CawRBHK2mEAgA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlL"
+            + "OCDaAadWoxTpj0BV89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N"
+            + "286Z4VeSWc39uK50T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/"
+            + "RgBYK+X0iP1YTknbzSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2O"
+            + "u1WMuF040zT9fBdXQ6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqV"
+            + "DNmWn6vQClCbAkbTCD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwACAgf/crbApFLO"
+            + "QikN9lHbn62dDxuu/dNigNmjf/A3cX+vo8aPHTXnRDyDwQALRuqbitdbM6p1LFjG"
+            + "8g84Aabk/jL7zzjJLqPe8pxeK1Pu+P44NzalXAYMsOOsxGuixIrz3Jw8IrpH/mkP"
+            + "tG/iX0NaLZ+Au9eokdLb+6NR/a51r2qL3E0ycFciJ61HzZKKHi6d0VQ7CHozCz+j"
+            + "d5530Mh1qq/ZjYDDjfP+snpyNIZXcLtGR/3HzkBqNgDcvClLx3322AWKDa7pX8DX"
+            + "qiLr8znWhPRpH9kCTnSpRzhYGT25FRcvdj4/q/oUIET/Tp+BWW3BxAc7WgpgqEfn"
+            + "fa0Mv72Zbn91gf4JAwITijME9IlFBGAwH6YmBtWIlnDiRbsq/Pxozuhbnes831il"
+            + "KmdpUKXkiIfHY0MqrEWl3Dfn6PMJGTnhgqXMrDxx3uHrq0Jl2swRnAWIIO8gID7j"
+            + "uPetUqEviPiwAYeJAEwEGBECAAwFAkEcraYFGwwAAAAACgkQ9P5W+Cv/YhShrgCg"
+            + "+JW8m5nF3R/oZGuG87bXQBszkjMAoLhGPncuGKowJXMRVc70/8qwXQJLsAFn");
+
+        private static readonly char[] sec8pass = "qwertyui".ToCharArray();
+
+        private static readonly byte[] sec9 = Base64.Decode(
+            "lQGqBEHCokERBAC9rh5SzC1sX1y1zoFuBB/v0SGhoKMEvLYf8Qv/j4deAMrc"
+            + "w5dxasYoD9oxivIUfTbZKo8cqr+dKLgu8tycigTM5b/T2ms69SUAxSBtj2uR"
+            + "LZrh4vjC/93kF+vzYJ4fNaBs9DGfCnsTouKjXqmfN3SlPMKNcGutO7FaUC3d"
+            + "zcpYfwCg7qyONHvXPhS0Iw4QL3mJ/6wMl0UD/0PaonqW0lfGeSjJSM9Jx5Bt"
+            + "fTSlwl6GmvYmI8HKvOBXAUSTZSbEkMsMVcIgf577iupzgWCgNF6WsNqQpKaq"
+            + "QIq1Kjdd0Y00xU1AKflOkhl6eufTigjviM+RdDlRYsOO5rzgwDTRTu9giErs"
+            + "XIyJAIZIdu2iaBHX1zHTfJ1r7nlAA/9H4T8JIhppUk/fLGsoPNZzypzVip8O"
+            + "mFb9PgvLn5GmuIC2maiocT7ibbPa7XuXTO6+k+323v7PoOUaKD3uD93zHViY"
+            + "Ma4Q5pL5Ajc7isnLXJgJb/hvvB1oo+wSDo9vJX8OCSq1eUPUERs4jm90/oqy"
+            + "3UG2QVqs5gcKKR4o48jTiv4DZQJHTlUBtB1mb28ga2V5IDxmb28ua2V5QGlu"
+            + "dmFsaWQuY29tPoheBBMRAgAeBQJBwqJCAhsDBgsJCAcDAgMVAgMDFgIBAh4B"
+            + "AheAAAoJEOKcXvehtw4ajJMAoK9nLfsrRY6peq56l/KzmjzuaLacAKCXnmiU"
+            + "waI7+uITZ0dihJ3puJgUz50BWARBwqJDEAQA0DPcNIn1BQ4CDEzIiQkegNPY"
+            + "mkYyYWDQjb6QFUXkuk1WEB73TzMoemsA0UKXwNuwrUgVhdpkB1+K0OR/e5ik"
+            + "GhlFdrDCqyT+mw6dRWbJ2i4AmFXZaRKO8AozZeWojsfP1/AMxQoIiBEteMFv"
+            + "iuXnZ3pGxSfZYm2+33IuPAV8KKMAAwUD/0C2xZQXgVWTiVz70HUviOmeTQ+f"
+            + "b1Hj0U9NMXWB383oQRBZCvQDM12cqGsvPZuZZ0fkGehGAIoyXtIjJ9lejzZN"
+            + "1TE9fnXZ9okXI4yCl7XLSE26OAbNsis4EtKTNScNaU9Dk3CS5XD/pkRjrkPN"
+            + "2hdUFtshuGmYkqhb9BIlrwE7/gMDAglbVSwecr9mYJcDYCH62U9TScWDTzsQ"
+            + "NFEfhMez3hGnNHNfHe+7yN3+Q9/LIhbba3IJEN5LsE5BFvudLbArp56EusIn"
+            + "JCxgiEkEGBECAAkFAkHCokMCGwwACgkQ4pxe96G3Dho2UQCeN3VPwx3dROZ+"
+            + "4Od8Qj+cLrBndGEAn0vaQdy6eIGeDw2I9u3Quwy6JnROnQHhBEHCozMRBADH"
+            + "ZBlB6xsAnqFYtYQOHr4pX6Q8TrqXCiHHc/q56G2iGbI9IlbfykQzaPHgWqZw"
+            + "9P0QGgF/QZh8TitiED+imLlGDqj3nhzpazqDh5S6sg6LYkQPqhwG/wT5sZQQ"
+            + "fzdeupxupjI5YN8RdIqkWF+ILOjk0+awZ4z0TSY/f6OSWpOXlwCgjIquR3KR"
+            + "tlCLk+fBlPnOXaOjX+kEAJw7umykNIHNaoY/2sxNhQhjqHVxKyN44y6FCSv9"
+            + "jRyW8Q/Qc8YhqBIHdmlcXoNWkDtlvErjdYMvOKFqKB1e2bGpjvhtIhNVQWdk"
+            + "oHap9ZuM1nV0+fD/7g/NM6D9rOOVCahBG2fEEeIwxa2CQ7zHZYfg9Umn3vbh"
+            + "TYi68R3AmgLOA/wKIVkfFKioI7iX4crQviQHJK3/A90SkrjdMQwLoiUjdgtk"
+            + "s7hJsTP1OPb2RggS1wCsh4sv9nOyDULj0T0ySGv7cpyv5Nq0FY8gw2oogHs5"
+            + "fjUnG4VeYW0zcIzI8KCaJT4UhR9An0A1jF6COrYCcjuzkflFbQLtQb9uNj8a"
+            + "hCpU4/4DAwIUxXlRMYE8uWCranzPo83FnBPRnGJ2aC9SqZWJYVUKIn4Vf2nu"
+            + "pVvCGFja0usl1WfV72hqlNKEONq7lohJBBgRAgAJBQJBwqMzAhsCAAoJEOKc"
+            + "Xvehtw4afisAoME/t8xz/rj/N7QRN9p8Ji8VPGSqAJ9K8eFJ+V0mxR+octJr"
+            + "6neEEX/i1Q==");
+
+        public char[] sec9pass = "foo".ToCharArray();
+
+        // version 4 keys with expiry dates
+        private static readonly byte[] pub10 = Base64.Decode(
+            "mQGiBEKqia0RBACc3hkufmscRSC4UvPZqMDsHm4+d/GXIr+3iNMSSEySJu8yk+k0"
+            + "Xs11C/K+n+v1rnn2jGGknv+1lDY6w75TIcTE6o6HGKeIDxsAm8P3MhoGU1GNPamA"
+            + "eTDeNybtrN/g6C65fCY9uI11hsUboYgQZ8ND22PB0VtvdOgq9D85qNUzxwCg1BbJ"
+            + "ycAKd4VqEvQ2Zglp3dCSrFMD/Ambq1kZqYa69sp3b9BPKuAgUgUPoytOArEej3Bk"
+            + "easAgAxNhWJy4GxigES3vk50rVi7w8XBuqbD1mQCzldF0HX0/A7PxLBv6od5uqqF"
+            + "HFxIyxg/KBZLd9ZOrsSaoUWH58jZq98X/sFtJtRi5VuJagMxCIJD4mLgtMv7Unlb"
+            + "/GrsA/9DEnObA/fNTgK70T+ZmPIS5tSt+bio30Aw4YGpPCGqpnm1u73b5kqX3U3B"
+            + "P+vGDvFuqZYpqQA8byAueH0MbaDHI4CFugvShXvgysJxN7ov7/8qsZZUMfK1t2Nr"
+            + "SAsPuKRbcY4gNKXIElKeXbyaET7vX7uAEKuxEwdYGFp/lNTkHLQgdGVzdCBrZXkg"
+            + "KHRlc3QpIDx0ZXN0QHRlc3QudGVzdD6IZAQTEQIAJAUCQqqJrQIbAwUJACTqAAYL"
+            + "CQgHAwIDFQIDAxYCAQIeAQIXgAAKCRDjDROQZRqIzDzLAJ42AeCRIBBjv8r8qw9y"
+            + "laNj2GZ1sACgiWYHVXMA6B1H9I1kS3YsCd3Oq7qwAgAAuM0EQqqJrhADAKWkix8l"
+            + "pJN7MMTXob4xFF1TvGll0UD1bDGOMMbes6aeXSbT9QXee/fH3GnijLY7wB+qTPv9"
+            + "ohubrSpnv3yen3CEBW6Q2YK+NlCskma42Py8YMV2idmYjtJi1ckvHFWt5wADBQL/"
+            + "fkB5Q5xSGgspMaTZmtmX3zG7ZDeZ0avP8e8mRL8UszCTpqs6vMZrXwyQLZPbtMYv"
+            + "PQpuRGEeKj0ysimwYRA5rrLQjnRER3nyuuEUUgc4j+aeRxPf9WVsJ/a1FCHtaAP1"
+            + "iE8EGBECAA8FAkKqia4CGwwFCQAk6gAACgkQ4w0TkGUaiMzdqgCfd66H7DL7kFGd"
+            + "IoS+NIp8JO+noxAAn25si4QAF7og8+4T5YQUuhIhx/NesAIAAA==");
+
+        private static readonly byte[] sec10 = Base64.Decode(
+            "lQHhBEKqia0RBACc3hkufmscRSC4UvPZqMDsHm4+d/GXIr+3iNMSSEySJu8yk+k0"
+            + "Xs11C/K+n+v1rnn2jGGknv+1lDY6w75TIcTE6o6HGKeIDxsAm8P3MhoGU1GNPamA"
+            + "eTDeNybtrN/g6C65fCY9uI11hsUboYgQZ8ND22PB0VtvdOgq9D85qNUzxwCg1BbJ"
+            + "ycAKd4VqEvQ2Zglp3dCSrFMD/Ambq1kZqYa69sp3b9BPKuAgUgUPoytOArEej3Bk"
+            + "easAgAxNhWJy4GxigES3vk50rVi7w8XBuqbD1mQCzldF0HX0/A7PxLBv6od5uqqF"
+            + "HFxIyxg/KBZLd9ZOrsSaoUWH58jZq98X/sFtJtRi5VuJagMxCIJD4mLgtMv7Unlb"
+            + "/GrsA/9DEnObA/fNTgK70T+ZmPIS5tSt+bio30Aw4YGpPCGqpnm1u73b5kqX3U3B"
+            + "P+vGDvFuqZYpqQA8byAueH0MbaDHI4CFugvShXvgysJxN7ov7/8qsZZUMfK1t2Nr"
+            + "SAsPuKRbcY4gNKXIElKeXbyaET7vX7uAEKuxEwdYGFp/lNTkHP4DAwLssmOjVC+d"
+            + "mWB783Lpzjb9evKzsxisTdx8/jHpUSS+r//6/Guyx3aA/zUw5bbftItW57mhuNNb"
+            + "JTu7WrQgdGVzdCBrZXkgKHRlc3QpIDx0ZXN0QHRlc3QudGVzdD6IZAQTEQIAJAUC"
+            + "QqqJrQIbAwUJACTqAAYLCQgHAwIDFQIDAxYCAQIeAQIXgAAKCRDjDROQZRqIzDzL"
+            + "AJ0cYPwKeoSReY14LqJtAjnkX7URHACgsRZWfpbalrSyDnq3TtZeGPUqGX+wAgAA"
+            + "nQEUBEKqia4QAwClpIsfJaSTezDE16G+MRRdU7xpZdFA9WwxjjDG3rOmnl0m0/UF"
+            + "3nv3x9xp4oy2O8Afqkz7/aIbm60qZ798np9whAVukNmCvjZQrJJmuNj8vGDFdonZ"
+            + "mI7SYtXJLxxVrecAAwUC/35AeUOcUhoLKTGk2ZrZl98xu2Q3mdGrz/HvJkS/FLMw"
+            + "k6arOrzGa18MkC2T27TGLz0KbkRhHio9MrIpsGEQOa6y0I50REd58rrhFFIHOI/m"
+            + "nkcT3/VlbCf2tRQh7WgD9f4DAwLssmOjVC+dmWDXVLRopzxbBGOvodp/LZoSDb56"
+            + "gNJjDMJ1aXqWW9qTAg1CFjBq73J3oFpVzInXZ8+Q8inxv7bnWiHbiE8EGBECAA8F"
+            + "AkKqia4CGwwFCQAk6gAACgkQ4w0TkGUaiMzdqgCgl2jw5hfk/JsyjulQqe1Nps1q"
+            + "Lx0AoMdnFMZmTMLHn8scUW2j9XO312tmsAIAAA==");
+
+//		private static readonly char[] sec10pass = "test".ToCharArray();
+
+        private static readonly byte[] subKeyBindingKey = Base64.Decode(
+            "mQGiBDWagYwRBAD7UcH4TAIp7tmUoHBNxVxCVz2ZrNo79M6fV63riOiH2uDxfIpr"
+            + "IrL0cM4ehEKoqlhngjDhX60eJrOw1nC5BpYZRnDnyDYT4wTWRguxObzGq9pqA1dM"
+            + "oPTJhkFZVIBgFY99/ULRqaUYIhFGgBtnwS70J8/L/PGVc3DmWRLMkTDjSQCg/5Nh"
+            + "MCjMK++MdYMcMl/ziaKRT6EEAOtw6PnU9afdohbpx9CK4UvCCEagfbnUtkSCQKSk"
+            + "6cUp6VsqyzY0pai/BwJ3h4apFMMMpVrtBAtchVgqo4xTr0Sve2j0k+ase6FSImiB"
+            + "g+AR7hvTUTcBjwtIExBc8TuCTqmn4GG8F7UMdl5Z0AZYj/FfAQYaRVZYP/pRVFNx"
+            + "Lw65BAC/Fi3qgiGCJFvXnHIckTfcAmZnKSEXWY9NJ4YQb4+/nH7Vsw0wR/ZObUHR"
+            + "bWgTc9Vw1uZIMe0XVj6Yk1dhGRehUnrm3mE7UJxu7pgkBCbFECFSlSSqP4MEJwZV"
+            + "09YP/msu50kjoxyoTpt+16uX/8B4at24GF1aTHBxwDLd8X0QWrQsTWVycmlsbCBM"
+            + "eW5jaCBDTEVBUiBzeXN0ZW0gREggPGNsZWFyQG1sLmNvbT6JAEsEEBECAAsFAjWa"
+            + "gYwECwMBAgAKCRDyAGjiP47/XanfAKCs6BPURWVQlGh635VgL+pdkUVNUwCdFcNa"
+            + "1isw+eAcopXPMj6ACOapepu5Ag0ENZqBlBAIAPZCV7cIfwgXcqK61qlC8wXo+VMR"
+            + "OU+28W65Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf"
+            + "3HZSTz09jdvOmeFXklnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2g"
+            + "pXI61Brwv0YAWCvl9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPA"
+            + "Q/ClWxiNjrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQD"
+            + "GcgHKXrKlQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVekyCzsAAgIH"
+            + "/RYtVo+HROZ6jrNjrATEwQm1fUQrk6n5+2dniN881lF0CNkB4NkHw1Xxz4Ejnu/0"
+            + "iLg8fkOAsmanOsKpOkRtqUnVpsVL5mLJpFEyCY5jbcfj+KY9/25bs0ga7kLHNZia"
+            + "zbCxJdF+W179z3nudQxRaXG/0XISIH7ziZbSVni69sKc1osk1+OoOMbSuZ86z535"
+            + "Pln4fXclkFE927HxfbWoO+60hkOLKh7x+8fC82b3x9vCETujEaxrscO2xS7/MYXP"
+            + "8t1ffriTDmhuIuQS2q4fLgeWdqrODrMhrD8Dq7e558gzp30ZCqpiS7EmKGczL7B8"
+            + "gXxbBCVSTxYMJheXt2xMXsuJAD8DBRg1moGU8gBo4j+O/10RAgWdAKCPhaFIXuC8"
+            + "/cdiNMxTDw9ug3De5QCfYXmDzRSFUu/nrCi8yz/l09wsnxo=");
+
+//		private static readonly byte[] subKeyBindingCheckSum = Base64.Decode("3HU+");
+
+        //
+        // PGP8 with SHA1 checksum.
+        //
+        private static readonly byte[] rewrapKey = Base64.Decode(
+            "lQOWBEUPOQgBCADdjPTtl8oOwqJFA5WU8p7oDK5KRWfmXeXUZr+ZJipemY5RSvAM"
+            + "rxqsM47LKYbmXOJznXCQ8+PPa+VxXAsI1CXFHIFqrXSwvB/DUmb4Ec9EuvNd18Zl"
+            + "hJAybzmV2KMkaUp9oG/DUvxZJqkpUddNfwqZu0KKKZWF5gwW5Oy05VCpaJxQVXFS"
+            + "whdbRfwEENJiNx4RB3OlWhIjY2p+TgZfgQjiGB9i15R+37sV7TqzBUZF4WWcnIRQ"
+            + "DnpUfxHgxQ0wO/h/aooyRHSpIx5i4oNpMYq9FNIyakEx/Bomdbs5hW9dFxhrE8Es"
+            + "UViAYITgTsyROxmgGatGG09dcmVDJVYF4i7JAAYpAAf/VnVyUDs8HrxYTOIt4rYY"
+            + "jIHToBsV0IiLpA8fEA7k078L1MwSwERVVe6oHVTjeR4A9OxE52Vroh2eOLnF3ftf"
+            + "6QThVVZr+gr5qeG3yvQ36N7PXNEVOlkyBzGmFQNe4oCA+NR2iqnAIspnekVmwJV6"
+            + "xVvPCjWw/A7ZArDARpfthspwNcJAp4SWfoa2eKzvUTznTyqFu2PSS5fwQZUgOB0P"
+            + "Y2FNaKeqV8vEZu4SUWwLOqXBQIZXiaLvdKNgwFvUe3kSHdCNsrVzW7SYxFwaEog2"
+            + "o6YLKPVPqjlGX1cMOponGp+7n9nDYkQjtEsGSSMQkQRDAcBdSVJmLO07kFOQSOhL"
+            + "WQQA49BcgTZyhyH6TnDBMBHsGCYj43FnBigypGT9FrQHoWybfX47yZaZFROAaaMa"
+            + "U6man50YcYZPwzDzXHrK2MoGALY+DzB3mGeXVB45D/KYtlMHPLgntV9T5b14Scbc"
+            + "w1ES2OUtsSIUs0zelkoXqjLuKnSIYK3mMb67Au7AEp6LXM8EAPj2NypvC86VEnn+"
+            + "FH0QHvUwBpmDw0EZe25xQs0brvAG00uIbiZnTH66qsIfRhXV/gbKK9J5DTGIqQ15"
+            + "DuPpz7lcxg/n2+SmjQLNfXCnG8hmtBjhTe+udXAUrmIcfafXyu68SAtebgm1ga56"
+            + "zUfqsgN3FFuMUffLl3myjyGsg5DnA/oCFWL4WCNClOgL6A5VkNIUait8QtSdCACT"
+            + "Y7jdSOguSNXfln0QT5lTv+q1AjU7zjRl/LsFNmIJ5g2qdDyK937FOXM44FEEjZty"
+            + "/4P2dzYpThUI4QUohIj8Qi9f2pZQueC5ztH6rpqANv9geZKcciAeAbZ8Md0K2TEU"
+            + "RD3Lh+RSBzILtBtUZXN0IEtleSA8dGVzdEBleGFtcGxlLmNvbT6JATYEEwECACAF"
+            + "AkUPOQgCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRDYpknHeQaskD9NB/9W"
+            + "EbFuLaqZAl3yjLU5+vb75BdvcfL1lUs44LZVwobNp3/0XbZdY76xVPNZURtU4u3L"
+            + "sJfGlaF+EqZDE0Mqc+vs5SIb0OnCzNJ00KaUFraUtkByRV32T5ECHK0gMBjCs5RT"
+            + "I0vVv+Qmzl4+X1Y2bJ2mlpBejHIrOzrBD5NTJimTAzyfnNfipmbqL8p/cxXKKzS+"
+            + "OM++ZFNACj6lRM1W9GioXnivBRC88gFSQ4/GXc8yjcrMlKA27JxV+SZ9kRWwKH2f"
+            + "6o6mojUQxnHr+ZFKUpo6ocvTgBDlC57d8IpwJeZ2TvqD6EdA8rZ0YriVjxGMDrX1"
+            + "8esfw+iLchfEwXtBIRwS");
+
+        private static readonly char[] rewrapPass = "voltage123".ToCharArray();
+
+        private static readonly byte[] pubWithX509 = Base64.Decode(
+              "mQENBERabjABCACtmfyo6Nph9MQjv4nmCWjZrRYnhXbivomAdIwYkLZUj1bjqE+j"
+            + "uaLzjZV8xSI59odZvrmOiqlzOc4txitQ1OX7nRgbOJ7qku0dvwjtIn46+HQ+cAFn"
+            + "2mTi81RyXEpO2uiZXfsNTxUtMi+ZuFLufiMc2kdk27GZYWEuasdAPOaPJnA+wW6i"
+            + "ZHlt0NfXIGNz864gRwhD07fmBIr1dMFfATWxCbgMd/rH7Z/j4rvceHD2n9yrhPze"
+            + "YN7W4Nuhsr2w/Ft5Cm9xO7vXT/cpto45uxn8f7jERep6bnUwNOhH8G+6xLQgTLD0"
+            + "qFBGVSIneK3lobs6+xn6VaGN8W0tH3UOaxA1ABEBAAG0D0NOPXFhLWRlZXBzaWdo"
+            + "dIkFDgQQZAIFAQUCRFpuMAUDCWdU0gMF/3gCGwPELGQBAQQwggTkMIIDzKADAgEC"
+            + "AhBVUMV/M6rIiE+IzmnPheQWMA0GCSqGSIb3DQEBBQUAMG4xEzARBgoJkiaJk/Is"
+            + "ZAEZFgNjb20xEjAQBgoJkiaJk/IsZAEZFgJxYTEVMBMGCgmSJomT8ixkARkWBXRt"
+            + "czAxMRUwEwYKCZImiZPyLGQBGRYFV2ViZmUxFTATBgNVBAMTDHFhLWRlZXBzaWdo"
+            + "dDAeFw0wNjA1MDQyMTEyMTZaFw0xMTA1MDQyMTIwMDJaMG4xEzARBgoJkiaJk/Is"
+            + "ZAEZFgNjb20xEjAQBgoJkiaJk/IsZAEZFgJxYTEVMBMGCgmSJomT8ixkARkWBXRt"
+            + "czAxMRUwEwYKCZImiZPyLGQBGRYFV2ViZmUxFTATBgNVBAMTDHFhLWRlZXBzaWdo"
+            + "dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK2Z/Kjo2mH0xCO/ieYJ"
+            + "aNmtFieFduK+iYB0jBiQtlSPVuOoT6O5ovONlXzFIjn2h1m+uY6KqXM5zi3GK1DU"
+            + "5fudGBs4nuqS7R2/CO0ifjr4dD5wAWfaZOLzVHJcSk7a6Jld+w1PFS0yL5m4Uu5+"
+            + "IxzaR2TbsZlhYS5qx0A85o8mcD7BbqJkeW3Q19cgY3PzriBHCEPTt+YEivV0wV8B"
+            + "NbEJuAx3+sftn+Piu9x4cPaf3KuE/N5g3tbg26GyvbD8W3kKb3E7u9dP9ym2jjm7"
+            + "Gfx/uMRF6npudTA06Efwb7rEtCBMsPSoUEZVIid4reWhuzr7GfpVoY3xbS0fdQ5r"
+            + "EDUCAwEAAaOCAXwwggF4MAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0G"
+            + "A1UdDgQWBBSmFTRv5y65DHtTYae48zl0ExNWZzCCASUGA1UdHwSCARwwggEYMIIB"
+            + "FKCCARCgggEMhoHFbGRhcDovLy9DTj1xYS1kZWVwc2lnaHQsQ049cWEtd3VtYW4x"
+            + "LWRjLENOPUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNl"
+            + "cyxDTj1Db25maWd1cmF0aW9uLERDPVdlYmZlLERDPXRtczAxLERDPXFhLERDPWNv"
+            + "bT9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xhc3M9Y1JM"
+            + "RGlzdHJpYnV0aW9uUG9pbnSGQmh0dHA6Ly9xYS13dW1hbjEtZGMud2ViZmUudG1z"
+            + "MDEucWEuY29tL0NlcnRFbnJvbGwvcWEtZGVlcHNpZ2h0LmNybDAQBgkrBgEEAYI3"
+            + "FQEEAwIBADANBgkqhkiG9w0BAQUFAAOCAQEAfuZCW3XlB7Eok35zQbvYt9rhAndT"
+            + "DNw3wPNI4ZzD1nXoYWnwhNNvWRpsOt4ExOSNdaHErfgDXAMyyg66Sro0TkAx8eAj"
+            + "fPQsyRAh0nm0glzFmJN6TdOZbj7hqGZjc4opQ6nZo8h/ULnaEwMIUW4gcSkZt0ww"
+            + "CuErl5NUrN3DpkREeCG/fVvQZ8ays3ibQ5ZCZnYBkLYq/i0r3NLW34WfYhjDY48J"
+            + "oQWtvFSAxvRfz2NGmqnrCHPQZxqlfdta97kDa4VQ0zSeBaC70gZkLmD1GJMxWoXW"
+            + "6tmEcgPY5SghInUf+L2u52V55MjyAFzVp7kTK2KY+p7qw35vzckrWkwu8AAAAAAA"
+            + "AQE=");
+
+        private static readonly byte[] secWithPersonalCertificate = Base64.Decode(
+            "lQOYBEjGLGsBCACp1I1dZKsK4N/I0/4g02hDVNLdQkDZfefduJgyJUyBGo/I"
+            + "/ZBpc4vT1YwVIdic4ADjtGB4+7WohN4v8siGzwRSeXardSdZVIw2va0JDsQC"
+            + "yeoTnwVkUgn+w/MDgpL0BBhTpr9o3QYoo28/qKMni3eA8JevloZqlAbQ/sYq"
+            + "rToMAqn0EIdeVVh6n2lRQhUJaNkH/kA5qWBpI+eI8ot/Gm9kAy3i4e0Xqr3J"
+            + "Ff1lkGlZuV5H5p/ItZui9BDIRn4IDaeR511NQnKlxFalM/gP9R9yDVI1aXfy"
+            + "STcp3ZcsTOTGNzACtpvMvl6LZyL42DyhlOKlJQJS81wp4dg0LNrhMFOtABEB"
+            + "AAEAB/0QIH5UEg0pTqAG4r/3v1uKmUbKJVJ3KhJB5xeSG3dKWIqy3AaXR5ZN"
+            + "mrJfXK7EfC5ZcSAqx5br1mzVl3PHVBKQVQxvIlmG4r/LKvPVhQYZUFyJWckZ"
+            + "9QMR+EA0Dcran9Ds5fa4hH84jgcwalkj64XWRAKDdVh098g17HDw+IYnQanl"
+            + "7IXbYvh+1Lr2HyPo//vHX8DxXIJBv+E4skvqGoNfCIfwcMeLsrI5EKo+D2pu"
+            + "kAuBYI0VBiZkrJHFXWmQLW71Mc/Bj7wTG8Q1pCpu7YQ7acFSv+/IOCsB9l9S"
+            + "vdB7pNhB3lEjYFGoTgr03VfeixA7/x8uDuSXjnBdTZqmGqkZBADNwCqlzdaQ"
+            + "X6CjS5jc3vzwDSPgM7ovieypEL6NU3QDEUhuP6fVvD2NYOgVnAEbJzgOleZS"
+            + "W2AFXKAf5NDxfqHnBmo/jlYb5yZV5Y+8/poLLj/m8t7sAfAmcZqGXfYMbSbe"
+            + "tr6TGTUXcXgbRyU5oH1e4iq691LOwZ39QjL8lNQQywQA006XYEr/PS9uJkyM"
+            + "Cg+M+nmm40goW4hU/HboFh9Ru6ataHj+CLF42O9sfMAV02UcD3Agj6w4kb5L"
+            + "VswuwfmY+17IryT81d+dSmDLhpo6ufKoAp4qrdP+bzdlbfIim4Rdrw5vF/Yk"
+            + "rC/Nfm3CLJxTimHJhqFx4MG7yEC89lxgdmcD/iJ3m41fwS+bPN2rrCAf7j1u"
+            + "JNr/V/8GAnoXR8VV9150BcOneijftIIYKKyKkV5TGwcTfjaxRKp87LTeC3MV"
+            + "szFDw04MhlIKRA6nBdU0Ay8Yu+EjXHK2VSpLG/Ny+KGuNiFzhqgBxM8KJwYA"
+            + "ISa1UEqWjXoLU3qu1aD7cCvANPVCOASwAYe0GlBHUCBEZXNrdG9wIDxpbmZv"
+            + "QHBncC5jb20+sAMD//+JAW4EEAECAFgFAkjGLGswFIAAAAAAIAAHcHJlZmVy"
+            + "cmVkLWVtYWlsLWVuY29kaW5nQHBncC5jb21wZ3BtaW1lBwsJCAcDAgoCGQEF"
+            + "GwMAAAADFgECBR4BAAAABRUCCAkKAAoJEHHHqp2m1tlWsx8H/icpHl1Nw17A"
+            + "D6MJN6zJm+aGja+5BOFxOsntW+IV6JI+l5WwiIVE8xTDhoXW4zdH3IZTqoyY"
+            + "frtkqLGpvsPtAQmV6eiPgE3+25ahL+MmjXKsceyhbZeCPDtM2M382VCHYCZK"
+            + "DZ4vrHVgK/BpyTeP/mqoWra9+F5xErhody71/cLyIdImLqXgoAny6YywjuAD"
+            + "2TrFnzPEBmZrkISHVEso+V9sge/8HsuDqSI03BAVWnxcg6aipHtxm907sdVo"
+            + "jzl2yFbxCCCaDIKR7XVbmdX7VZgCYDvNSxX3WEOgFq9CYl4ZlXhyik6Vr4XP"
+            + "7EgqadtfwfMcf4XrYoImSQs0gPOd4QqwAWedA5gESMYsawEIALiazFREqBfi"
+            + "WouTjIdLuY09Ks7PCkn0eo/i40/8lEj1R6JKFQ5RlHNnabh+TLvjvb3nOSU0"
+            + "sDg+IKK/JUc8/Fo7TBdZvARX6BmltEGakqToDC3eaF9EQgHLEhyE/4xXiE4H"
+            + "EeIQeCHdC7k0pggEuWUn5lt6oeeiPUWhqdlUOvzjG+jqMPJL0bk9STbImHUR"
+            + "EiugCPTekC0X0Zn0yrwyqlJQMWnh7wbSl/uo4q45K7qOhxcijo+hNNrkRAMi"
+            + "fdNqD4s5qDERqqHdAAgpWqydo7zV5tx0YSz5fjh59Z7FxkUXpcu1WltT6uVn"
+            + "hubiMTWpXzXOQI8wZL2fb12JmRY47BEAEQEAAQAH+wZBeanj4zne+fBHrWAS"
+            + "2vx8LYiRV9EKg8I/PzKBVdGUnUs0vTqtXU1dXGXsAsPtu2r1bFh0TQH06gR1"
+            + "24iq2obgwkr6x54yj+sZlE6SU0SbF/mQc0NCNAXtSKV2hNXvy+7P+sVJR1bn"
+            + "b5ukuvkj1tgEln/0W4r20qJ60F+M5QxXg6kGh8GAlo2tetKEv1NunAyWY6iv"
+            + "FTnSaIJ/YaKQNcudNvOJjeIakkIzfzBL+trUiI5n1LTBB6+u3CF/BdZBTxOy"
+            + "QwjAh6epZr+GnQqeaomFxBc3mU00sjrsB1Loso84UIs6OKfjMkPoZWkQrQQW"
+            + "+xvQ78D33YwqNfXk/5zQAxkEANZxJGNKaAeDpN2GST/tFZg0R5GPC7uWYC7T"
+            + "pG100mir9ugRpdeIFvfAa7IX2jujxo9AJWo/b8hq0q0koUBdNAX3xxUaWy+q"
+            + "KVCRxBifpYVBfEViD3lsbMy+vLYUrXde9087YD0c0/XUrj+oowWJavblmZtS"
+            + "V9OjkQW9zoCigpf5BADcYV+6bkmJtstxJopJG4kD/lr1o35vOEgLkNsMLayc"
+            + "NuzES084qP+8yXPehkzSsDB83kc7rKfQCQMZ54V7KCCz+Rr4wVG7FCrFAw4e"
+            + "4YghfGVU/5whvbJohl/sXXCYGtVljvY/BSQrojRdP+/iZxFbeD4IKiTjV+XL"
+            + "WKSS56Fq2QQAzeoKBJFUq8nqc8/OCmc52WHSOLnB4AuHL5tNfdE9tjqfzZAE"
+            + "tx3QB7YGGP57tPQxPFDFJVRJDqw0YxI2tG9Pum8iriKGjHg+oEfFhxvCmPxf"
+            + "zDKaGibkLeD7I6ATpXq9If+Nqb5QjzPjFbXBIz/q2nGjamZmp4pujKt/aZxF"
+            + "+YRCebABh4kCQQQYAQIBKwUCSMYsbAUbDAAAAMBdIAQZAQgABgUCSMYsawAK"
+            + "CRCrkqZshpdZSNAiB/9+5nAny2O9/lp2K2z5KVXqlNAHUmd4S/dpqtsZCbAo"
+            + "8Lcr/VYayrNojga1U7cyhsvFky3N9wczzPHq3r9Z+R4WnRM1gpRWl+9+xxtd"
+            + "ZxGfGzMRlxX1n5rCqltKKk6IKuBAr2DtTnxThaQiISO2hEw+P1MT2HnSzMXt"
+            + "zse5CZ5OiOd/bm/rdvTRD/JmLqhXmOFaIwzdVP0dR9Ld4Dug2onOlIelIntC"
+            + "cywY6AmnL0DThaTy5J8MiMSPamSmATl4Bicm8YRbHHz58gCYxI5UMLwtwR1+"
+            + "rSEmrB6GwVHZt0/BzOpuGpvFZI5ZmC5yO/waR1hV+VYj025cIz+SNuDPyjy4"
+            + "AAoJEHHHqp2m1tlW/w0H/3w38SkB5n9D9JL3chp+8fex03t7CQowVMdsBYNY"
+            + "qI4QoVQkakkxzCz5eF7rijXt5eC3NE/quWhlMigT8LARiwBROBWgDRFW4WuX"
+            + "6MwYtjKKUkZSkBKxP3lmaqZrJpF6jfhPEN76zr/NxWPC/nHRNldUdqkzSu/r"
+            + "PeJyePMofJevzMkUzw7EVtbtWhZavCz+EZXRTZXub9M4mDMj64BG6JHMbVZI"
+            + "1iDF2yka5RmhXz9tOhYgq80m7UQUb1ttNn86v1zVbe5lmB8NG4Ndv+JaaSuq"
+            + "SBZOYQ0ZxtMAB3vVVLZCWxma1P5HdXloegh+hosqeu/bl0Wh90z5Bspt6eI4"
+            + "imqwAWeVAdgESMYtmwEEAM9ZeMFxor7oSoXnhQAXD9lXLLfBky6IcIWISY4F"
+            + "JWc8sK8+XiVzpOrefKro0QvmEGSYcDFQMHdScBLOTsiVJiqenA7fg1bkBr/M"
+            + "bnD7vTKMJe0DARlU27tE5hsWCDYTluxIFjGcAcecY2UqHkqpctYKY0WY9EIm"
+            + "dBA5TYaw3c0PABEBAAEAA/0Zg6318nC57cWLIp5dZiO/dRhTPZD0hI+BWZrg"
+            + "zJtPT8rXVY+qK3Jwquig8z29/r+nppEE+xQWVWDlv4M28BDJAbGE+qWKAZqT"
+            + "67lyKgc0c50W/lfbGvvs+F7ldCcNpFvlk79GODKxcEeTGDQKb9R6FnHFee/K"
+            + "cZum71O3Ku3vUQIA3B3PNM+tKocIUNDHnInuLyqLORwQBNGfjU/pLMM0MkpP"
+            + "lWeIfgUmn2zL/e0JrRoO0LQqX1LN/TlfcurDM0SEtwIA8Sba9OpDq99Yz360"
+            + "FiePJiGNNlbj9EZsuGJyMVXL1mTLA6WHnz5XZOfYqJXHlmKvaKDbARW4+0U7"
+            + "0/vPdYWSaQIAwYeo2Ce+b7M5ifbGMDWYBisEvGISg5xfvbe6qApmHS4QVQzE"
+            + "Ym81rdJJ8OfvgSbHcgn37S3OBXIQvNdejF4BWqM9sAGHtCBIeW5lay1JbnRy"
+            + "YW5ldCA8aHluZWtAYWxzb2Z0LmN6PrADA///iQDrBBABAgBVBQJIxi2bBQkB"
+            + "mgKAMBSAAAAAACAAB3ByZWZlcnJlZC1lbWFpbC1lbmNvZGluZ0BwZ3AuY29t"
+            + "cGdwbWltZQULBwgJAgIZAQUbAQAAAAUeAQAAAAIVAgAKCRDlTa3BE84gWVKW"
+            + "BACcoCFKvph9r9QiHT1Z3N4wZH36Uxqu/059EFALnBkEdVudX/p6S9mynGRk"
+            + "EfhmWFC1O6dMpnt+ZBEed/4XyFWVSLPwirML+6dxfXogdUsdFF1NCRHc3QGc"
+            + "txnNUT/zcZ9IRIQjUhp6RkIvJPHcyfTXKSbLviI+PxzHU2Padq8pV7ABZ7kA"
+            + "jQRIfg8tAQQAutJR/aRnfZYwlVv+KlUDYjG8YQUfHpTxpnmVu7W6N0tNg/Xr"
+            + "5dg50wq3I4HOamRxUwHpdPkXyNF1szpDSRZmlM+VmiIvJDBnyH5YVlxT6+zO"
+            + "8LUJ2VTbfPxoLFp539SQ0oJOm7IGMAGO7c0n/QV0N3hKUfWgCyJ+sENDa0Ft"
+            + "JycAEQEAAbABj4kEzQQYAQIENwUCSMYtnAUJAeEzgMLFFAAAAAAAFwNleDUw"
+            + "OWNlcnRpZmljYXRlQHBncC5jb20wggNhMIICyqADAgECAgkA1AoCoRKJCgsw"
+            + "DQYJKoZIhvcNAQEFBQAwgakxCzAJBgNVBAYTAkNaMRcwFQYDVQQIEw5DemVj"
+            + "aCBSZXB1YmxpYzESMBAGA1UEChQJQSYmTCBzb2Z0MSAwHgYDVQQLExdJbnRl"
+            + "cm5hbCBEZXZlbG9wbWVudCBDQTEqMCgGA1UEAxQhQSYmTCBzb2Z0IEludGVy"
+            + "bmFsIERldmVsb3BtZW50IENBMR8wHQYJKoZIhvcNAQkBFhBrYWRsZWNAYWxz"
+            + "b2Z0LmN6MB4XDTA4MDcxNjE1MDkzM1oXDTA5MDcxNjE1MDkzM1owaTELMAkG"
+            + "A1UEBhMCQ1oxFzAVBgNVBAgTDkN6ZWNoIFJlcHVibGljMRIwEAYDVQQKFAlB"
+            + "JiZMIHNvZnQxFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5IeW5l"
+            + "ay1JbnRyYW5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAutJR/aRn"
+            + "fZYwlVv+KlUDYjG8YQUfHpTxpnmVu7W6N0tNg/Xr5dg50wq3I4HOamRxUwHp"
+            + "dPkXyNF1szpDSRZmlM+VmiIvJDBnyH5YVlxT6+zO8LUJ2VTbfPxoLFp539SQ"
+            + "0oJOm7IGMAGO7c0n/QV0N3hKUfWgCyJ+sENDa0FtJycCAwEAAaOBzzCBzDAJ"
+            + "BgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBD"
+            + "ZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUNaw7A6r10PtYZzAvr9CrSKeRYJgwHwYD"
+            + "VR0jBBgwFoAUmqSRM8rN3+T1+tkGiqef8S5suYgwGgYDVR0RBBMwEYEPaHlu"
+            + "ZWtAYWxzb2Z0LmN6MCgGA1UdHwQhMB8wHaAboBmGF2h0dHA6Ly9wZXRyazIv"
+            + "Y2EvY2EuY3JsMAsGA1UdDwQEAwIF4DANBgkqhkiG9w0BAQUFAAOBgQCUdOWd"
+            + "7mBLWj1/GSiYgfwgdTrgk/VZOJvMKBiiFyy1iFEzldz6Xx+mAexnFJKfZXZb"
+            + "EMEGWHfWPmgJzAtuTT0Jz6tUwDmeLH3MP4m8uOZtmyUJ2aq41kciV3rGxF0G"
+            + "BVlZ/bWTaOzHdm6cjylt6xxLt6MJzpPBA/9ZfybSBh1DaAUbDgAAAJ0gBBkB"
+            + "AgAGBQJIxi2bAAoJEAdYkEWLb2R2fJED/RK+JErZ98uGo3Z81cHkdP3rk8is"
+            + "DUL/PR3odBPFH2SIA5wrzklteLK/ZXmBUzcvxqHEgI1F7goXbsBgeTuGgZdx"
+            + "pINErxkNpcMl9FTldWKGiapKrhkZ+G8knDizF/Y7Lg6uGd2nKVxzutLXdHJZ"
+            + "pU89Q5nzq6aJFAZo5TBIcchQAAoJEOVNrcETziBZXvQD/1mvFqBfWqwXxoj3"
+            + "8fHUuFrE2pcp32y3ciO2i+uNVEkNDoaVVNw5eHQaXXWpllI/Pe6LnBl4vkyc"
+            + "n3pjONa4PKrePkEsCUhRbIySqXIHuNwZumDOlKzZHDpCUw72LaC6S6zwuoEf"
+            + "ucOcxTeGIUViANWXyTIKkHfo7HfigixJIL8nsAFn");
+
+        [Test]
+        public void PerformTest1()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub1);
+
+            int count = 0;
+
+            foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+                byte[] bytes = pgpPub1.GetEncoded();
+
+                PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes);
+
+                foreach (PgpPublicKey pubKey in pgpPub2.GetPublicKeys())
+                {
+                    keyCount++;
+
+                    foreach (PgpSignature sig in pubKey.GetSignatures())
+                    {
+                        if (sig == null)
+                            Fail("null signature found");
+                    }
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of public keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings");
+            }
+
+            //
+            // exact match
+            //
+            count = 0;
+            foreach (PgpPublicKeyRing pgpPub3 in pubRings.GetKeyRings("test (Test key) <test at ubicall.com>"))
+            {
+                if (pgpPub3 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings on exact match");
+            }
+
+            //
+            // partial match 1 expected
+            //
+            count = 0;
+            foreach (PgpPublicKeyRing pgpPub4 in pubRings.GetKeyRings("test", true))
+            {
+                if (pgpPub4 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings on partial match 1");
+            }
+
+            //
+            // partial match 0 expected
+            //
+            count = 0;
+            foreach (PgpPublicKeyRing pgpPub5 in pubRings.GetKeyRings("XXX", true))
+            {
+                if (pgpPub5 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 0)
+            {
+                Fail("wrong number of public keyrings on partial match 0");
+            }
+
+            //
+            // case-insensitive partial match
+            //
+            count = 0;
+            foreach (PgpPublicKeyRing pgpPub6 in pubRings.GetKeyRings("TEST at ubicall.com", true, true))
+            {
+                if (pgpPub6 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings on case-insensitive partial match");
+            }
+
+            PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(sec1);
+            count = 0;
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    PgpPublicKey pk = k.PublicKey;
+
+                    pk.GetSignatures();
+
+                    byte[] pkBytes = pk.GetEncoded();
+
+                    PgpPublicKeyRing pkR = new PgpPublicKeyRing(pkBytes);
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+
+            //
+            // exact match
+            //
+            count = 0;
+            foreach (PgpSecretKeyRing o1 in secretRings.GetKeyRings("test (Test key) <test at ubicall.com>"))
+            {
+                if (o1 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings on exact match");
+            }
+
+            //
+            // partial match 1 expected
+            //
+            count = 0;
+            foreach (PgpSecretKeyRing o2 in secretRings.GetKeyRings("test", true))
+            {
+                if (o2 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings on partial match 1");
+            }
+
+            //
+            // exact match 0 expected
+            //
+            count = 0;
+            foreach (PgpSecretKeyRing o3 in secretRings.GetKeyRings("test", false))
+            {
+                if (o3 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 0)
+            {
+                Fail("wrong number of secret keyrings on partial match 0");
+            }
+
+            //
+            // case-insensitive partial match
+            //
+            count = 0;
+            foreach (PgpSecretKeyRing o4 in secretRings.GetKeyRings("TEST at ubicall.com", true, true))
+            {
+                if (o4 == null)
+                    Fail("null keyring found");
+
+                count++;
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings on case-insensitive partial match");
+            }
+        }
+
+        [Test]
+        public void PerformTest2()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub2);
+
+            int count = 0;
+
+            byte[] encRing = pubRings.GetEncoded();
+
+            pubRings = new PgpPublicKeyRingBundle(encRing);
+
+            foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpPub1.GetEncoded();
+
+                PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes);
+
+                foreach (PgpPublicKey pk in pgpPub2.GetPublicKeys())
+                {
+                    byte[] pkBytes = pk.GetEncoded();
+
+                    PgpPublicKeyRing pkR = new PgpPublicKeyRing(pkBytes);
+
+                    keyCount++;
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of public keys");
+                }
+            }
+
+            if (count != 2)
+            {
+                Fail("wrong number of public keyrings");
+            }
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(sec2);
+
+            count = 0;
+
+
+            encRing = secretRings2.GetEncoded();
+            PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings2.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    PgpPublicKey pk = k.PublicKey;
+
+                    if (pk.KeyId == -1413891222336124627L)
+                    {
+                        int sCount = 0;
+
+                        foreach (PgpSignature pgpSignature in pk.GetSignaturesOfType(PgpSignature.SubkeyBinding))
+                        {
+                            int type = pgpSignature.SignatureType;
+                            if (type != PgpSignature.SubkeyBinding)
+                            {
+                                Fail("failed to return correct signature type");
+                            }
+                            sCount++;
+                        }
+
+                        if (sCount != 1)
+                        {
+                            Fail("failed to find binding signature");
+                        }
+                    }
+
+                    pk.GetSignatures();
+
+                    if (k.KeyId == -4049084404703773049L
+                        || k.KeyId == -1413891222336124627L)
+                    {
+                        k.ExtractPrivateKey(sec2pass1);
+                    }
+                    else if (k.KeyId == -6498553574938125416L
+                        || k.KeyId == 59034765524361024L)
+                    {
+                        k.ExtractPrivateKey(sec2pass2);
+                    }
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 2)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest3()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub3);
+
+            int count = 0;
+
+            byte[] encRing = pubRings.GetEncoded();
+
+            pubRings = new PgpPublicKeyRingBundle(encRing);
+
+            foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpPub1.GetEncoded();
+
+                PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes);
+
+                foreach (PgpPublicKey pubK in pgpPub2.GetPublicKeys())
+                {
+                    keyCount++;
+                    pubK.GetSignatures();
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of public keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings");
+            }
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(sec3);
+
+            count = 0;
+
+            encRing = secretRings2.GetEncoded();
+
+            PgpSecretKeyRingBundle secretRings = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings2.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    k.ExtractPrivateKey(sec3pass1);
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest4()
+        {
+            PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec4);
+            int count = 0;
+
+
+            byte[] encRing = secretRings1.GetEncoded();
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    k.ExtractPrivateKey(sec3pass1);
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest5()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub5);
+
+            int count = 0;
+
+            byte[] encRing = pubRings.GetEncoded();
+
+            pubRings = new PgpPublicKeyRingBundle(encRing);
+
+            foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpPub1.GetEncoded();
+
+                PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes);
+
+                foreach (PgpPublicKey o in pgpPub2.GetPublicKeys())
+                {
+                    if (o == null)
+                        Fail("null keyring found");
+
+                    keyCount++;
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of public keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of public keyrings");
+            }
+
+            PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec5);
+
+            count = 0;
+
+            encRing = secretRings1.GetEncoded();
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    k.ExtractPrivateKey(sec5pass1);
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest6()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub6);
+
+            foreach (PgpPublicKeyRing pgpPub in pubRings.GetKeyRings())
+            {
+                foreach (PgpPublicKey k in pgpPub.GetPublicKeys())
+                {
+                    if (k.KeyId == 0x5ce086b5b5a18ff4L)
+                    {
+                        int count = 0;
+
+                        foreach (PgpSignature sig in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation))
+                        {
+                            if (sig == null)
+                                Fail("null signature found");
+
+                            count++;
+                        }
+
+                        if (count != 1)
+                        {
+                            Fail("wrong number of revocations in test6.");
+                        }
+                    }
+                }
+            }
+
+            byte[] encRing = pubRings.GetEncoded();
+        }
+
+        [Test, Explicit]
+        public void PerformTest7()
+        {
+            PgpPublicKeyRing pgpPub = new PgpPublicKeyRing(pub7);
+            PgpPublicKey masterKey = null;
+
+            foreach (PgpPublicKey k in pgpPub.GetPublicKeys())
+            {
+                if (k.IsMasterKey)
+                {
+                    masterKey = k;
+                    continue;
+                }
+
+                int count = 0;
+                PgpSignature sig = null;
+
+                foreach (PgpSignature sigTemp in k.GetSignaturesOfType(PgpSignature.SubkeyRevocation))
+                {
+                    sig = sigTemp;
+                    count++;
+                }
+
+                if (count != 1)
+                {
+                    Fail("wrong number of revocations in test7.");
+                }
+
+                sig.InitVerify(masterKey);
+
+                if (!sig.VerifyCertification(k))
+                {
+                    Fail("failed to verify revocation certification");
+                }
+            }
+        }
+
+        [Test]
+        public void PerformTest8()
+        {
+            PgpPublicKeyRingBundle pubRings = new PgpPublicKeyRingBundle(pub8);
+
+            int count = 0;
+
+            byte[] encRing = pubRings.GetEncoded();
+
+            pubRings = new PgpPublicKeyRingBundle(encRing);
+
+            foreach (PgpPublicKeyRing pgpPub1 in pubRings.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpPub1.GetEncoded();
+
+                PgpPublicKeyRing pgpPub2 = new PgpPublicKeyRing(bytes);
+
+                foreach (PgpPublicKey o in pgpPub2.GetPublicKeys())
+                {
+                    if (o == null)
+                        Fail("null key found");
+
+                    keyCount++;
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of public keys");
+                }
+            }
+
+            if (count != 2)
+            {
+                Fail("wrong number of public keyrings");
+            }
+
+            PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec8);
+
+            count = 0;
+
+            encRing = secretRings1.GetEncoded();
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+                    k.ExtractPrivateKey(sec8pass);
+                }
+
+                if (keyCount != 2)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest9()
+        {
+            PgpSecretKeyRingBundle secretRings1 = new PgpSecretKeyRingBundle(sec9);
+
+            int count = 0;
+
+            byte[] encRing = secretRings1.GetEncoded();
+
+            PgpSecretKeyRingBundle secretRings2 = new PgpSecretKeyRingBundle(encRing);
+
+            foreach (PgpSecretKeyRing pgpSec1 in secretRings1.GetKeyRings())
+            {
+                count++;
+
+                int keyCount = 0;
+
+                byte[] bytes = pgpSec1.GetEncoded();
+
+                PgpSecretKeyRing pgpSec2 = new PgpSecretKeyRing(bytes);
+
+                foreach (PgpSecretKey k in pgpSec2.GetSecretKeys())
+                {
+                    keyCount++;
+
+                    PgpPrivateKey pKey = k.ExtractPrivateKey(sec9pass);
+                    if (keyCount == 1 && pKey != null)
+                    {
+                        Fail("primary secret key found, null expected");
+                    }
+                }
+
+                if (keyCount != 3)
+                {
+                    Fail("wrong number of secret keys");
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("wrong number of secret keyrings");
+            }
+        }
+
+        [Test]
+        public void PerformTest10()
+        {
+            PgpSecretKeyRing secretRing = new PgpSecretKeyRing(sec10);
+
+            foreach (PgpSecretKey secretKey in secretRing.GetSecretKeys())
+            {
+                PgpPublicKey pubKey = secretKey.PublicKey;
+
+                if (pubKey.ValidDays != 28)
+                {
+                    Fail("days wrong on secret key ring");
+                }
+
+                if (pubKey.GetValidSeconds() != 28 * 24 * 60 * 60)
+                {
+                    Fail("seconds wrong on secret key ring");
+                }
+            }
+
+            PgpPublicKeyRing publicRing = new PgpPublicKeyRing(pub10);
+
+            foreach (PgpPublicKey pubKey in publicRing.GetPublicKeys())
+            {
+                if (pubKey.ValidDays != 28)
+                {
+                    Fail("days wrong on public key ring");
+                }
+
+                if (pubKey.GetValidSeconds() != 28 * 24 * 60 * 60)
+                {
+                    Fail("seconds wrong on public key ring");
+                }
+            }
+        }
+
+        [Test]
+        public void PerformTest11()
+        {
+            PgpPublicKeyRing pubRing = new PgpPublicKeyRing(subKeyBindingKey);
+
+            foreach (PgpPublicKey key in pubRing.GetPublicKeys())
+            {
+                if (key.GetValidSeconds() != 0)
+                {
+                    Fail("expiration time non-zero");
+                }
+            }
+        }
+
+        [Test]
+        public void GenerateTest()
+        {
+            char[] passPhrase = "hello".ToCharArray();
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(512, 80, new SecureRandom());
+            DsaParameters dsaParams = pGen.GenerateParameters();
+            DsaKeyGenerationParameters dsaKgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);
+            IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            dsaKpg.Init(dsaKgp);
+
+
+            //
+            // this takes a while as the key generator has to Generate some DSA parameters
+            // before it Generates the key.
+            //
+            AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair();
+            IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
+
+            BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+            BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+            ElGamalParameters elParams = new ElGamalParameters(p, g);
+            ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
+            elgKpg.Init(elKgp);
+
+            //
+            // this is quicker because we are using preGenerated parameters.
+            //
+            AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair();
+            PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow);
+            PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);
+
+            PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
+                "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, new SecureRandom());
+
+            keyRingGen.AddSubKey(elgKeyPair);
+
+            PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing();
+
+            keyRing.GetSecretKey().ExtractPrivateKey(passPhrase);
+
+            PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing();
+
+            PgpPublicKey vKey = null;
+            PgpPublicKey sKey = null;
+
+            foreach (PgpPublicKey pk in pubRing.GetPublicKeys())
+            {
+                if (pk.IsMasterKey)
+                {
+                    vKey = pk;
+                }
+                else
+                {
+                    sKey = pk;
+                }
+            }
+
+            foreach (PgpSignature sig in sKey.GetSignatures())
+            {
+                if (sig.KeyId == vKey.KeyId
+                    && sig.SignatureType == PgpSignature.SubkeyBinding)
+                {
+                    sig.InitVerify(vKey);
+
+                    if (!sig.VerifyCertification(vKey, sKey))
+                    {
+                        Fail("failed to verify sub-key signature.");
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public void InsertMasterTest()
+        {
+            SecureRandom random = new SecureRandom();
+
+            char[] passPhrase = "hello".ToCharArray();
+            IAsymmetricCipherKeyPairGenerator rsaKpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+
+            rsaKpg.Init(new KeyGenerationParameters(random, 512));
+
+            //
+            // this is quicker because we are using pregenerated parameters.
+            //
+            AsymmetricCipherKeyPair rsaKp = rsaKpg.GenerateKeyPair();
+            PgpKeyPair rsaKeyPair1 = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, rsaKp, DateTime.UtcNow);
+
+            rsaKp = rsaKpg.GenerateKeyPair();
+            PgpKeyPair rsaKeyPair2 = new PgpKeyPair(PublicKeyAlgorithmTag.RsaGeneral, rsaKp, DateTime.UtcNow);
+
+            PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification,
+                rsaKeyPair1, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random);
+            PgpSecretKeyRing secRing1 = keyRingGen.GenerateSecretKeyRing();
+            PgpPublicKeyRing pubRing1 = keyRingGen.GeneratePublicKeyRing();
+
+            keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification,
+                rsaKeyPair2, "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, null, null, random);
+            PgpSecretKeyRing secRing2 = keyRingGen.GenerateSecretKeyRing();
+            PgpPublicKeyRing pubRing2 = keyRingGen.GeneratePublicKeyRing();
+
+            try
+            {
+                PgpPublicKeyRing.InsertPublicKey(pubRing1, pubRing2.GetPublicKey());
+                Fail("adding second master key (public) should throw an ArgumentException");
+            }
+            catch (ArgumentException e)
+            {
+                if (!e.Message.Equals("cannot add a master key to a ring that already has one"))
+                {
+                    Fail("wrong message in public test");
+                }
+            }
+
+            try
+            {
+                PgpSecretKeyRing.InsertSecretKey(secRing1, secRing2.GetSecretKey());
+                Fail("adding second master key (secret) should throw an ArgumentException");
+            }
+            catch (ArgumentException e)
+            {
+                if (!e.Message.Equals("cannot add a master key to a ring that already has one"))
+                {
+                    Fail("wrong message in secret test");
+                }
+            }
+        }
+
+        [Test]
+        public void GenerateSha1Test()
+        {
+            char[] passPhrase = "hello".ToCharArray();
+
+            IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(512, 80, new SecureRandom());
+            DsaParameters dsaParams = pGen.GenerateParameters();
+            DsaKeyGenerationParameters kgp = new DsaKeyGenerationParameters(new SecureRandom(), dsaParams);
+            dsaKpg.Init(kgp);
+
+            //
+            // this takes a while as the key generator has to generate some DSA params
+            // before it generates the key.
+            //
+            AsymmetricCipherKeyPair dsaKp = dsaKpg.GenerateKeyPair();
+
+
+            IAsymmetricCipherKeyPairGenerator elgKpg = GeneratorUtilities.GetKeyPairGenerator("ELGAMAL");
+
+            BigInteger g = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+            BigInteger p = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+            ElGamalParameters elParams = new ElGamalParameters(p, g);
+            ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(new SecureRandom(), elParams);
+            elgKpg.Init(elKgp);
+
+            //
+            // this is quicker because we are using preGenerated parameters.
+            //
+            AsymmetricCipherKeyPair elgKp = elgKpg.GenerateKeyPair();
+
+
+            PgpKeyPair dsaKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.Dsa, dsaKp, DateTime.UtcNow);
+            PgpKeyPair elgKeyPair = new PgpKeyPair(PublicKeyAlgorithmTag.ElGamalEncrypt, elgKp, DateTime.UtcNow);
+
+            PgpKeyRingGenerator keyRingGen = new PgpKeyRingGenerator(PgpSignature.PositiveCertification, dsaKeyPair,
+                "test", SymmetricKeyAlgorithmTag.Aes256, passPhrase, true, null, null, new SecureRandom());
+
+            keyRingGen.AddSubKey(elgKeyPair);
+
+            PgpSecretKeyRing keyRing = keyRingGen.GenerateSecretKeyRing();
+
+            keyRing.GetSecretKey().ExtractPrivateKey(passPhrase);
+
+            PgpPublicKeyRing pubRing = keyRingGen.GeneratePublicKeyRing();
+
+            PgpPublicKey vKey = null;
+            PgpPublicKey sKey = null;
+
+            foreach (PgpPublicKey pk in pubRing.GetPublicKeys())
+            {
+                if (pk.IsMasterKey)
+                {
+                    vKey = pk;
+                }
+                else
+                {
+                    sKey = pk;
+                }
+            }
+
+            foreach (PgpSignature sig in sKey.GetSignatures())
+            {
+                if (sig.KeyId == vKey.KeyId
+                    && sig.SignatureType == PgpSignature.SubkeyBinding)
+                {
+                    sig.InitVerify(vKey);
+
+                    if (!sig.VerifyCertification(vKey, sKey))
+                    {
+                        Fail("failed to verify sub-key signature.");
+                    }
+                }
+            }
+        }
+
+        [Test]
+        public void RewrapTest()
+        {
+            SecureRandom rand = new SecureRandom();
+
+            // Read the secret key rings
+            PgpSecretKeyRingBundle privRings = new PgpSecretKeyRingBundle(
+                new MemoryStream(rewrapKey, false));
+
+            foreach (PgpSecretKeyRing pgpPrivEnum in privRings.GetKeyRings())
+            {
+                foreach (PgpSecretKey pgpKeyEnum in pgpPrivEnum.GetSecretKeys())
+                {
+                    // re-encrypt the key with an empty password
+                    PgpSecretKeyRing pgpPriv = PgpSecretKeyRing.RemoveSecretKey(pgpPrivEnum, pgpKeyEnum);
+                    PgpSecretKey pgpKey = PgpSecretKey.CopyWithNewPassword(
+                        pgpKeyEnum,
+                        rewrapPass,
+                        null,
+                        SymmetricKeyAlgorithmTag.Null,
+                        rand);
+                    pgpPriv = PgpSecretKeyRing.InsertSecretKey(pgpPriv, pgpKey);
+
+                    // this should succeed
+                    PgpPrivateKey privTmp = pgpKey.ExtractPrivateKey(null);
+                }
+            }
+        }
+
+        [Test]
+        public void PublicKeyRingWithX509Test()
+        {
+            checkPublicKeyRingWithX509(pubWithX509);
+
+            PgpPublicKeyRing pubRing = new PgpPublicKeyRing(pubWithX509);
+
+            checkPublicKeyRingWithX509(pubRing.GetEncoded());
+        }
+
+        [Test]
+        public void SecretKeyRingWithPersonalCertificateTest()
+        {
+            checkSecretKeyRingWithPersonalCertificate(secWithPersonalCertificate);
+            PgpSecretKeyRingBundle secRing = new PgpSecretKeyRingBundle(secWithPersonalCertificate);
+            checkSecretKeyRingWithPersonalCertificate(secRing.GetEncoded());
+        }
+
+        private void checkSecretKeyRingWithPersonalCertificate(
+            byte[] keyRing)
+        {
+            PgpSecretKeyRingBundle secCol = new PgpSecretKeyRingBundle(keyRing);
+
+            int count = 0;
+
+            foreach (PgpSecretKeyRing ring in secCol.GetKeyRings())
+            {
+                IEnumerator e = ring.GetExtraPublicKeys().GetEnumerator();
+                while (e.MoveNext())
+                {
+                    ++count;
+                }
+            }
+
+            if (count != 1)
+            {
+                Fail("personal certificate data subkey not found - count = " + count);
+            }
+        }
+
+        private void checkPublicKeyRingWithX509(
+            byte[] keyRing)
+        {
+            PgpPublicKeyRing pubRing = new PgpPublicKeyRing(keyRing);
+            IEnumerator en = pubRing.GetPublicKeys().GetEnumerator();
+
+            if (en.MoveNext())
+            {
+                PgpPublicKey key = (PgpPublicKey) en.Current;
+
+                IEnumerator sEn = key.GetSignatures().GetEnumerator();
+
+                if (sEn.MoveNext())
+                {
+                    PgpSignature sig = (PgpSignature) sEn.Current;
+                    if (sig.KeyAlgorithm != PublicKeyAlgorithmTag.Experimental_1)
+                    {
+                        Fail("experimental signature not found");
+                    }
+                    if (!AreEqual(sig.GetSignature(), Hex.Decode("000101")))
+                    {
+                        Fail("experimental encoding check failed");
+                    }
+                }
+                else
+                {
+                    Fail("no signature found");
+                }
+            }
+            else
+            {
+                Fail("no key found");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            PerformTest1();
+            PerformTest2();
+            PerformTest3();
+            PerformTest4();
+            PerformTest5();
+            PerformTest6();
+
+            // NB: This was commented out in the original Java source
+            //PerformTest7();
+
+            PerformTest8();
+            PerformTest9();
+            PerformTest10();
+            PerformTest11();
+
+            GenerateTest();
+            GenerateSha1Test();
+            RewrapTest();
+            PublicKeyRingWithX509Test();
+            SecretKeyRingWithPersonalCertificateTest();
+            InsertMasterTest();
+        }
+
+        public override string Name
+        {
+            get { return "PgpKeyRingTest"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new PgpKeyRingTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpMarkerTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpMarkerTest.cs
new file mode 100644
index 0000000..89be7cd
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/PgpMarkerTest.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    [TestFixture]
+    public class PgpMarkerTest
+        : SimpleTest
+    {
+        private static readonly byte[] message1 = Base64.Decode(
+            "qANQR1DBwU4DdrlXatQSHgoQCADWlhY3bWWaOTm4t2espRWPFQmETeinnieHce64"
+            + "lmEIFzaryEWeSdQc8XGfDzcb7sxq7b5b9Hm6OrACcCbSp2KGEJNG5kJmo2A16UPq"
+            + "JdK4xNelpJRh3KcJPv+N/9VJrMdj4C+DRnGNFg1hTQf3RKsX+ms2V0OBC5vGlOZY"
+            + "zX+XZz/7hl1PXVLN23u4npZI/1xETI2VtRoM76S6oykGXxMtT3+sGU1fAVEKVS45"
+            + "pyQHWbBqApkWrURq0xBqpVfDwOgGw09dJxt2igW9hjvNAd9tJiMGrMF5o2OLlub7"
+            + "c7FiK+dWLLcw+nx7Hl6FQmo9E8qyW8x1Cb78HjR/JXMgH/ngB/4gba6xX+s5TJkW"
+            + "H2Wpp5ePTw39EqHosUMrm05R+C0ha3EyyaJIvKj2WWmImKu5PWo1t37Pi6KHFNC3"
+            + "wsYJMRKnnNtd34luMTOgLpDcdgClzfp2p6EqHMoB7Uj3etlLmbN+vpGgz9qkLBRV"
+            + "7MpR1yE9qrZNeGgbkry6N31w5E7HoAHu5JNcwxgzbJoj2lI8uvs6Gf7fEoQOuAPE"
+            + "W/SGlfR2BdBPiJ1yErMElc2O8LVS0wTwwifHpEsMV+1ntl1EC5d052lo+6q7zNqD"
+            + "uYt1/2if6h9W9fe+S9mzr0ZAtxIN2ZGOFJJRnqzjDQ4siB9nnwr6YgvUVRSr/lQB"
+            + "hDTd0bmjyWacCt0PPMJWchO6A5tzqKUpTWSYibpdks80kLQogQHsJTZd/kpS0I6f"
+            + "gD0HYYlMssZwhg2J2TWwXDpDTgQ6mzFKbGSdOSk/deTJj2+EubzxaZcxZEocCJA8"
+            + "bppCj4kLBnCj1LjYx7A=");
+
+        private static readonly byte[] message2 = Base64.Decode(
+            "qANQR1DBwU4DZlTzKj+E4aMQCADruFAojUIlHGcnswLIekvhbVnaHnbCt6Kp"
+            + "IL2zppmEIYJ9n1xCO1k+3Y5j9vNATbqCVWs1HD0aAL3PRI1eZ1l8GkIBCd2z"
+            + "tcZpSI/uyI/JCzVW2stCH0gpP2V7zcjk8HaIuBz4ZsyU9m7v6LwCDPB4CTrb"
+            + "Z5nn5Jm3eowonQsRL/3TpJtG+IjTaw29NbCBNNX8quM5LwfIsfWovqNv28r1"
+            + "aX8FsqoTRsWEfQ7dMV/swVGqv0PgKxqErdnZVJ2yOJqjLk+lBJT6zhqPijGV"
+            + "10pc68hdZxxLU1KZq25DAjS12xcAgagjRkOmYE/H1oEjGZlXfS4y/xQ7skHa"
+            + "HI+b04vECACTpQPwCXhxYiNWnf4XhJPONIGyrsXVtsTNwzOShFPmeUvpipP4"
+            + "HknakBkBuUY49xcffQogW/NlGCZnQOulDLE6fCH/krkSmI8WVP5Vhf6bM1Qm"
+            + "92dHZFoTrrcQ9NVGaCNHHWf7KXkNfKdTkE23LdggoVrVAzO4WcdqVc6s/or7"
+            + "jQYP9zXLeu8+GGFMxe/9FCtoIWbujGQHsdDEkCK4h+D44EVDPzbvWj39ZB4w"
+            + "hHoab8RLHd7njcrPeoCPdYkFVCKOSuLdxxYZDbbmgpISaafrafwefkkESeGu"
+            + "JzbNhmyS8zfOiejWzndaLYWUSE/sqISK9Pg+xKundnFPk04+AhIRyYEoUjG3"
+            + "LgGVyM49mrM8E7QwAGU0m/VCJLoOu+N74Z1rp1wFdA5yCllFlONNM4Czhd1D"
+            + "ZMyLFqGXiKlyVCPlUTN2uVisYQGr6iNGYSPxpKjwiAzdeeQBPOETG0vd3nTO"
+            + "MN4BMKcG+kRJd5FU72SRfmbGwPPjd1gts9xFvtj4Tvpkam8=");
+
+		public override void PerformTest()
+        {
+            //
+            // test encrypted message
+            //
+            PgpObjectFactory pgpFact = new PgpObjectFactory(message1);
+
+            if (pgpFact.NextPgpObject() is PgpMarker)
+            {
+                if (pgpFact.NextPgpObject() is PgpEncryptedDataList)
+                {
+                    return;
+                }
+                else
+                {
+                    Fail("error processing after marker.");
+                }
+            }
+
+			// TODO Does this even get called?
+			pgpFact = new PgpObjectFactory(message2);
+
+            if (pgpFact.NextPgpObject() is PgpMarker)
+            {
+                if (!(pgpFact.NextPgpObject() is PgpEncryptedDataList))
+                {
+                    return;
+                }
+                else
+                {
+                    Fail("error processing after marker.");
+                }
+            }
+        }
+
+		public override string Name
+        {
+			get { return "PgpMarkerTest"; }
+        }
+
+		public static void Main(
+            string[] args)
+        {
+            RunTest(new PgpMarkerTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openpgp/test/RegressionTest.cs b/BouncyCastle.AxCrypt/test/src/openpgp/test/RegressionTest.cs
new file mode 100644
index 0000000..e8a3685
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openpgp/test/RegressionTest.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Bcpg.OpenPgp.Tests
+{
+    public class RegressionTest
+    {
+        public static ITest[] tests =
+        {
+            new PgpKeyRingTest(),
+            new PgpRsaTest(),
+            new PgpDsaTest(),
+            new PgpDsaElGamalTest(),
+            new PgpPbeTest(),
+            new PgpMarkerTest(),
+            new PgpPacketTest(),
+            new PgpArmoredTest(),
+            new PgpSignatureTest(),
+            new PgpClearSignedSignatureTest(),
+            new PgpCompressionTest(),
+            new PGPNoPrivateKeyTest(),
+        };
+
+        public static void Main(
+            string[] args)
+        {
+            foreach (ITest test in tests)
+            {
+                ITestResult result = test.Perform();
+                Console.WriteLine(result);
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openssl/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/openssl/test/AllTests.cs
new file mode 100644
index 0000000..954fcb3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openssl/test/AllTests.cs
@@ -0,0 +1,135 @@
+#if !LIB
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.OpenSsl.Tests
+{
+	[TestFixture]
+	public class AllTests
+	{
+		private class Password
+			: IPasswordFinder
+		{
+			private readonly char[] password;
+
+			public Password(
+				char[] word)
+			{
+				this.password = (char[]) word.Clone();
+			}
+
+			public char[] GetPassword()
+			{
+				return (char[]) password.Clone();
+			}
+		}
+		
+		[Suite]
+		public static TestSuite Suite
+		{
+			get
+			{
+				TestSuite suite = new TestSuite("OpenSSL Tests");
+				suite.Add(new AllTests());
+				return suite;
+			}
+		}
+
+		[Test]
+		public void TestOpenSsl()
+		{
+			Org.BouncyCastle.Utilities.Test.ITest[] tests = new Org.BouncyCastle.Utilities.Test.ITest[]{
+				new ReaderTest(),
+				new WriterTest()
+			};
+
+			foreach (Org.BouncyCastle.Utilities.Test.ITest test in tests)
+			{
+				SimpleTestResult result = (SimpleTestResult)test.Perform();
+
+				if (!result.IsSuccessful())
+				{
+					Assert.Fail(result.ToString());
+				}
+			}
+		}
+
+		[Test]
+		public void TestPkcs8Encrypted()
+		{
+			IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
+
+			AsymmetricKeyParameter privKey = kpGen.GenerateKeyPair().Private;
+
+			// FIXME see PbeUtilities and Pkcs8Generator
+//			EncryptedTest(privKey, Pkcs8Generator.Aes256Cbc);
+//			EncryptedTest(privKey, Pkcs8Generator.Des3Cbc);
+			EncryptedTest(privKey, Pkcs8Generator.PbeSha1_3DES);
+		}
+
+		private void EncryptedTest(AsymmetricKeyParameter privKey, string algorithm)
+		{
+			StringWriter sw = new StringWriter();
+			PemWriter pWrt = new PemWriter(sw);
+			Pkcs8Generator pkcs8 = new Pkcs8Generator(privKey, algorithm);
+			pkcs8.Password = "hello".ToCharArray();
+
+			pWrt.WriteObject(pkcs8);
+			pWrt.Writer.Close();
+
+			String result = sw.ToString();
+
+			PemReader pRd = new PemReader(new StringReader(result), new Password("hello".ToCharArray()));
+
+			AsymmetricKeyParameter rdKey = (AsymmetricKeyParameter)pRd.ReadObject();
+			pRd.Reader.Close();
+
+			Assert.AreEqual(privKey, rdKey);
+		}
+
+		[Test]
+		public void TestPkcs8Plain()
+		{
+			IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
+
+			AsymmetricKeyParameter privKey = kpGen.GenerateKeyPair().Private;
+
+			StringWriter sw = new StringWriter();
+			PemWriter pWrt = new PemWriter(sw);
+
+			Pkcs8Generator pkcs8 = new Pkcs8Generator(privKey);
+			pWrt.WriteObject(pkcs8);
+			pWrt.Writer.Close();
+
+			string result = sw.ToString();
+
+			PemReader pRd = new PemReader(new StringReader(result), new Password("hello".ToCharArray()));
+
+			AsymmetricKeyParameter rdKey = (AsymmetricKeyParameter)pRd.ReadObject();
+			pRd.Reader.Close();
+
+			Assert.AreEqual(privKey, rdKey);
+		}
+
+        public static void Main(
+			string[] args)
+        {
+            //junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            Suite.Run(el);
+        }
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/openssl/test/ReaderTest.cs b/BouncyCastle.AxCrypt/test/src/openssl/test/ReaderTest.cs
new file mode 100644
index 0000000..e3990b5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openssl/test/ReaderTest.cs
@@ -0,0 +1,379 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.OpenSsl.Tests
+{
+    /**
+    * basic class for reading test.pem - the password is "secret"
+    */
+    [TestFixture]
+    public class ReaderTest
+        : SimpleTest
+    {
+        private class Password
+            : IPasswordFinder
+        {
+            private readonly char[] password;
+
+            public Password(
+                char[] word)
+            {
+                this.password = (char[]) word.Clone();
+            }
+
+            public char[] GetPassword()
+            {
+                return (char[]) password.Clone();
+            }
+        }
+
+        public override string Name
+        {
+            get { return "PEMReaderTest"; }
+        }
+
+        public override void PerformTest()
+        {
+            IPasswordFinder pGet = new Password("secret".ToCharArray());
+            PemReader pemRd = OpenPemResource("test.pem", pGet);
+            AsymmetricCipherKeyPair pair;
+
+            object o;
+            while ((o = pemRd.ReadObject()) != null)
+            {
+//				if (o is AsymmetricCipherKeyPair)
+//				{
+//					ackp = (AsymmetricCipherKeyPair)o;
+//
+//					Console.WriteLine(ackp.Public);
+//					Console.WriteLine(ackp.Private);
+//				}
+//				else
+//				{
+//					Console.WriteLine(o.ToString());
+//				}
+            }
+
+            //
+            // pkcs 7 data
+            //
+            pemRd = OpenPemResource("pkcs7.pem", null);
+
+            ContentInfo d = (ContentInfo)pemRd.ReadObject();    
+    
+            if (!d.ContentType.Equals(CmsObjectIdentifiers.EnvelopedData))
+            {
+                Fail("failed envelopedData check");
+            }
+
+            /*
+            {
+                //
+                // ECKey
+                //
+                pemRd = OpenPemResource("eckey.pem", null);
+    
+                // TODO Resolve return type issue with EC keys and fix PemReader to return parameters
+//				ECNamedCurveParameterSpec spec = (ECNamedCurveParameterSpec)pemRd.ReadObject();
+    
+                pair = (AsymmetricCipherKeyPair)pemRd.ReadObject();
+                ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+    
+                sgr.Init(true, pair.Private);
+    
+                byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+    
+                sgr.BlockUpdate(message, 0, message.Length);
+    
+                byte[] sigBytes = sgr.GenerateSignature();
+    
+                sgr.Init(false, pair.Public);
+    
+                sgr.BlockUpdate(message, 0, message.Length);
+    
+                if (!sgr.VerifySignature(sigBytes))
+                {
+                    Fail("EC verification failed");
+                }
+
+                // TODO Resolve this issue with the algorithm name, study Java version
+//				if (!((ECPublicKeyParameters) pair.Public).AlgorithmName.Equals("ECDSA"))
+//				{
+//					Fail("wrong algorithm name on public got: " + ((ECPublicKeyParameters) pair.Public).AlgorithmName);
+//				}
+//	
+//				if (!((ECPrivateKeyParameters) pair.Private).AlgorithmName.Equals("ECDSA"))
+//				{
+//					Fail("wrong algorithm name on private got: " + ((ECPrivateKeyParameters) pair.Private).AlgorithmName);
+//				}
+            }
+            */
+
+            //
+            // writer/parser test
+            //
+            IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            kpGen.Init(
+                new RsaKeyGenerationParameters(
+                BigInteger.ValueOf(0x10001),
+                new SecureRandom(),
+                768,
+                25));
+
+            pair = kpGen.GenerateKeyPair();
+
+            keyPairTest("RSA", pair);
+
+//			kpGen = KeyPairGenerator.getInstance("DSA");
+//			kpGen.initialize(512, new SecureRandom());
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(512, 80, new SecureRandom());
+
+            kpGen = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            kpGen.Init(
+                new DsaKeyGenerationParameters(
+                    new SecureRandom(),
+                    pGen.GenerateParameters()));
+
+            pair = kpGen.GenerateKeyPair();
+
+            keyPairTest("DSA", pair);
+
+            //
+            // PKCS7
+            //
+            MemoryStream bOut = new MemoryStream();
+            PemWriter pWrt = new PemWriter(new StreamWriter(bOut));
+
+            pWrt.WriteObject(d);
+            pWrt.Writer.Close();
+
+            pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false)));
+            d = (ContentInfo)pemRd.ReadObject();    
+
+            if (!d.ContentType.Equals(CmsObjectIdentifiers.EnvelopedData))
+            {
+                Fail("failed envelopedData recode check");
+            }
+
+
+            // OpenSSL test cases (as embedded resources)
+            doOpenSslDsaTest("unencrypted");
+            doOpenSslRsaTest("unencrypted");
+
+            doOpenSslTests("aes128");
+            doOpenSslTests("aes192");
+            doOpenSslTests("aes256");
+            doOpenSslTests("blowfish");
+            doOpenSslTests("des1");
+            doOpenSslTests("des2");
+            doOpenSslTests("des3");
+            doOpenSslTests("rc2_128");
+
+            doOpenSslDsaTest("rc2_40_cbc");
+            doOpenSslRsaTest("rc2_40_cbc");
+            doOpenSslDsaTest("rc2_64_cbc");
+            doOpenSslRsaTest("rc2_64_cbc");
+
+            doDudPasswordTest("7fd98", 0, "Corrupted stream - out of bounds length found");
+            doDudPasswordTest("ef677", 1, "Corrupted stream - out of bounds length found");
+            doDudPasswordTest("800ce", 2, "unknown tag 26 encountered");
+            doDudPasswordTest("b6cd8", 3, "DEF length 81 object truncated by 56");
+            doDudPasswordTest("28ce09", 4, "DEF length 110 object truncated by 28");
+            doDudPasswordTest("2ac3b9", 5, "DER length more than 4 bytes: 11");
+            doDudPasswordTest("2cba96", 6, "DEF length 100 object truncated by 35");
+            doDudPasswordTest("2e3354", 7, "DEF length 42 object truncated by 9");
+            doDudPasswordTest("2f4142", 8, "DER length more than 4 bytes: 14");
+            doDudPasswordTest("2fe9bb", 9, "DER length more than 4 bytes: 65");
+            doDudPasswordTest("3ee7a8", 10, "DER length more than 4 bytes: 57");
+            doDudPasswordTest("41af75", 11, "unknown tag 16 encountered");
+            doDudPasswordTest("1704a5", 12, "corrupted stream detected");
+            doDudPasswordTest("1c5822", 13, "Unknown object in GetInstance: Org.BouncyCastle.Asn1.DerUtf8String");
+            doDudPasswordTest("5a3d16", 14, "corrupted stream detected");
+            doDudPasswordTest("8d0c97", 15, "corrupted stream detected");
+            doDudPasswordTest("bc0daf", 16, "corrupted stream detected");
+            doDudPasswordTest("aaf9c4d",17, "Corrupted stream - out of bounds length found");
+
+            // encrypted private key test
+            pGet = new Password("password".ToCharArray());
+            pemRd = OpenPemResource("enckey.pem", pGet);
+
+            RsaPrivateCrtKeyParameters privKey = (RsaPrivateCrtKeyParameters)pemRd.ReadObject();
+
+            if (!privKey.PublicExponent.Equals(new BigInteger("10001", 16)))
+            {
+                Fail("decryption of private key data check failed");
+            }
+
+            // general PKCS8 test
+            pGet = new Password("password".ToCharArray());
+            pemRd = OpenPemResource("pkcs8test.pem", pGet);
+
+            while ((privKey = (RsaPrivateCrtKeyParameters)pemRd.ReadObject()) != null)
+            {
+                if (!privKey.PublicExponent.Equals(new BigInteger("10001", 16)))
+                {
+                    Fail("decryption of private key data check failed");
+                }
+            }
+        }
+
+        private void keyPairTest(
+            string					name,
+            AsymmetricCipherKeyPair	pair) 
+        {
+            MemoryStream bOut = new MemoryStream();
+            PemWriter pWrt = new PemWriter(new StreamWriter(bOut));
+
+            pWrt.WriteObject(pair.Public);
+            pWrt.Writer.Close();
+
+            PemReader pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false)));
+
+            AsymmetricKeyParameter pubK = (AsymmetricKeyParameter) pemRd.ReadObject();
+            if (!pubK.Equals(pair.Public))
+            {
+                Fail("Failed public key read: " + name);
+            }
+
+            bOut = new MemoryStream();
+            pWrt = new PemWriter(new StreamWriter(bOut));
+
+            pWrt.WriteObject(pair.Private);
+            pWrt.Writer.Close();
+
+            pemRd = new PemReader(new StreamReader(new MemoryStream(bOut.ToArray(), false)));
+
+            AsymmetricCipherKeyPair kPair = (AsymmetricCipherKeyPair) pemRd.ReadObject();
+            if (!kPair.Private.Equals(pair.Private))
+            {
+                Fail("Failed private key read: " + name);
+            }
+            
+            if (!kPair.Public.Equals(pair.Public))
+            {
+                Fail("Failed private key public read: " + name);
+            }
+        }
+
+        private void doOpenSslTests(
+            string baseName)
+        {
+            doOpenSslDsaModesTest(baseName);
+            doOpenSslRsaModesTest(baseName);
+        }
+
+        private void doOpenSslDsaModesTest(
+            string baseName)
+        {
+            doOpenSslDsaTest(baseName + "_cbc");
+            doOpenSslDsaTest(baseName + "_cfb");
+            doOpenSslDsaTest(baseName + "_ecb");
+            doOpenSslDsaTest(baseName + "_ofb");
+        }
+
+        private void doOpenSslRsaModesTest(
+            string baseName)
+        {
+            doOpenSslRsaTest(baseName + "_cbc");
+            doOpenSslRsaTest(baseName + "_cfb");
+            doOpenSslRsaTest(baseName + "_ecb");
+            doOpenSslRsaTest(baseName + "_ofb");
+        }
+
+        private void doOpenSslDsaTest(
+            string name)
+        {
+            string fileName = "dsa.openssl_dsa_" + name + ".pem";
+
+            doOpenSslTestFile(fileName, typeof(DsaPrivateKeyParameters));
+        }
+
+        private void doOpenSslRsaTest(
+            string name)
+        {
+            string fileName = "rsa.openssl_rsa_" + name + ".pem";
+
+            doOpenSslTestFile(fileName, typeof(RsaPrivateCrtKeyParameters));
+        }
+
+        private void doOpenSslTestFile(
+            string	fileName,
+            Type	expectedPrivKeyType)
+        {
+            PemReader pr = OpenPemResource(fileName, new Password("changeit".ToCharArray()));
+            AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair;
+            pr.Reader.Close();
+
+            if (kp == null)
+            {
+                Fail("Didn't find OpenSSL key");
+            }
+
+            if (!expectedPrivKeyType.IsInstanceOfType(kp.Private))
+            {
+                Fail("Returned key not of correct type");
+            }
+        }
+
+        private void doDudPasswordTest(string password, int index, string message)
+        {
+            // illegal state exception check - in this case the wrong password will
+            // cause an underlying class cast exception.
+            try
+            {
+                IPasswordFinder pGet = new Password(password.ToCharArray());
+                PemReader pemRd = OpenPemResource("test.pem", pGet);
+
+                Object o;
+                while ((o = pemRd.ReadObject()) != null)
+                {
+                }
+
+                Fail("issue not detected: " + index);
+            }
+            catch (IOException e)
+            {
+                if (e.Message.IndexOf(message) < 0)
+                {
+                    Console.Error.WriteLine(message);
+                    Console.Error.WriteLine(e.Message);
+                    Fail("issue " + index + " exception thrown, but wrong message");
+                }
+            }
+        }
+
+        private static PemReader OpenPemResource(
+            string			fileName,
+            IPasswordFinder	pGet)
+        {
+            Stream data = GetTestDataAsStream("openssl." + fileName);
+            TextReader tr = new StreamReader(data);
+            return new PemReader(tr, pGet);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ReaderTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/openssl/test/WriterTest.cs b/BouncyCastle.AxCrypt/test/src/openssl/test/WriterTest.cs
new file mode 100644
index 0000000..41f3717
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/openssl/test/WriterTest.cs
@@ -0,0 +1,185 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.IO.Pem;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.OpenSsl.Tests
+{
+	[TestFixture]
+	public class WriterTest
+		: SimpleTest
+	{
+		private static readonly SecureRandom random = new SecureRandom();
+
+		// TODO Replace with a randomly generated key each test run?
+		private static readonly RsaPrivateCrtKeyParameters testRsaKey = new RsaPrivateCrtKeyParameters(
+			new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+			new BigInteger("11", 16),
+			new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+			new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+			new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+			new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+			new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+			new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+		private static readonly DsaParameters testDsaParams = new DsaParameters(
+			new BigInteger("7434410770759874867539421675728577177024889699586189000788950934679315164676852047058354758883833299702695428196962057871264685291775577130504050839126673"),
+			new BigInteger("1138656671590261728308283492178581223478058193247"),
+			new BigInteger("4182906737723181805517018315469082619513954319976782448649747742951189003482834321192692620856488639629011570381138542789803819092529658402611668375788410"));
+
+//		private static readonly PKCS8EncodedKeySpec testEcDsaKeySpec = new PKCS8EncodedKeySpec(
+//			Base64.Decode("MIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMr" +
+//				"jAwPp9R+KMUEhB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus+w2sY8OIPQQWGb5i5LdAyi" +
+//				"/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2dno1GMols5497in5gL5+zn0yMsRtyv5o=")
+//		);
+		private static readonly byte[] testEcDsaKeyBytes = Base64.Decode(
+			  "MIG/AgEAMBAGByqGSM49AgEGBSuBBAAiBIGnMIGkAgEBBDCSBU3vo7ieeKs0ABQamy/ynxlde7Ylr8HmyfLaNnMr"
+			+ "jAwPp9R+KMUEhB7zxSAXv9KgBwYFK4EEACKhZANiAQQyyolMpg+TyB4o9kPWqafHIOe8o9K1glus+w2sY8OIPQQWGb5i5LdAyi"
+			+ "/SscwU24rZM0yiL3BHodp9ccwyhLrFYgXJUOQcCN2dno1GMols5497in5gL5+zn0yMsRtyv5o=");
+
+		private static readonly char[] testPassword = "bouncy".ToCharArray();
+
+		private static readonly string[] algorithms = new string[]
+		{
+			"AES-128-CBC", "AES-128-CFB", "AES-128-ECB", "AES-128-OFB",
+			"AES-192-CBC", "AES-192-CFB", "AES-192-ECB", "AES-192-OFB",
+			"AES-256-CBC", "AES-256-CFB", "AES-256-ECB", "AES-256-OFB",
+			"BF-CBC", "BF-CFB", "BF-ECB", "BF-OFB",
+			"DES-CBC", "DES-CFB", "DES-ECB", "DES-OFB",
+			"DES-EDE", "DES-EDE-CBC", "DES-EDE-CFB", "DES-EDE-ECB", "DES-EDE-OFB",
+			"DES-EDE3", "DES-EDE3-CBC", "DES-EDE3-CFB", "DES-EDE3-ECB", "DES-EDE3-OFB",
+			"RC2-CBC", "RC2-CFB", "RC2-ECB", "RC2-OFB",
+			"RC2-40-CBC",
+			"RC2-64-CBC",
+		};
+
+		private class Password
+			: IPasswordFinder
+		{
+			private readonly char[] password;
+
+			public Password(
+				char[] word)
+			{
+				this.password = (char[]) word.Clone();
+			}
+
+			public char[] GetPassword()
+			{
+				return (char[]) password.Clone();
+			}
+		}
+
+		public override string Name
+		{
+			get { return "PEMWriterTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			IAsymmetricCipherKeyPairGenerator dsaKpg = GeneratorUtilities.GetKeyPairGenerator("DSA");
+			dsaKpg.Init(new DsaKeyGenerationParameters(random, testDsaParams));
+			AsymmetricCipherKeyPair testDsaKp = dsaKpg.GenerateKeyPair();
+			AsymmetricKeyParameter testDsaKey = testDsaKp.Private;
+
+			doWriteReadTest(testDsaKey);
+			doWriteReadTests(testDsaKey, algorithms);
+
+			doWriteReadTest(testRsaKey);
+			doWriteReadTests(testRsaKey, algorithms);
+
+			AsymmetricKeyParameter ecPriv = PrivateKeyFactory.CreateKey(testEcDsaKeyBytes);
+			doWriteReadTest(ecPriv);
+			doWriteReadTests(ecPriv, algorithms);
+
+			IAsymmetricCipherKeyPairGenerator ecKpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+			ecKpg.Init(new KeyGenerationParameters(random, 239));
+			ecPriv = ecKpg.GenerateKeyPair().Private;
+			doWriteReadTest(ecPriv);
+			doWriteReadTests(ecPriv, algorithms);
+
+			// override test
+			PemWriter pWrt = new PemWriter(new StringWriter());
+
+			object o = new PemObject("FRED", new byte[100]);
+			pWrt.WriteObject(o);
+
+			pWrt.Writer.Close();
+		}
+
+		private void doWriteReadTests(
+			AsymmetricKeyParameter	akp,
+			string[]				algorithms)
+		{
+			foreach (string algorithm in algorithms)
+			{
+				doWriteReadTest(akp, algorithm);
+			}
+		}
+
+		private void doWriteReadTest(
+			AsymmetricKeyParameter	akp)
+		{
+			StringWriter sw = new StringWriter();
+			PemWriter pw = new PemWriter(sw);
+
+			pw.WriteObject(akp);
+			pw.Writer.Close();
+
+			string data = sw.ToString();
+
+			PemReader pr = new PemReader(new StringReader(data));
+
+			AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair;
+
+			if (kp == null || !kp.Private.Equals(akp))
+			{
+				Fail("Failed to read back test key");
+			}
+		}
+
+		private void doWriteReadTest(
+			AsymmetricKeyParameter	akp,
+			string					algorithm)
+		{
+			StringWriter sw = new StringWriter();
+			PemWriter pw = new PemWriter(sw);
+
+			pw.WriteObject(akp, algorithm, testPassword, random);
+			pw.Writer.Close();
+
+			string data = sw.ToString();
+
+			PemReader pr = new PemReader(new StringReader(data), new Password(testPassword));
+
+			AsymmetricCipherKeyPair kp = pr.ReadObject() as AsymmetricCipherKeyPair;
+
+			if (kp == null || !kp.Private.Equals(akp))
+			{
+				Fail("Failed to read back test key encoded with: " + algorithm);
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new WriterTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/pkcs/examples/PKCS12Example.cs b/BouncyCastle.AxCrypt/test/src/pkcs/examples/PKCS12Example.cs
new file mode 100644
index 0000000..002e14c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/pkcs/examples/PKCS12Example.cs
@@ -0,0 +1,386 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Pkcs.Examples
+{
+	/**
+	* Example of how to set up a certificate chain and a PKCS 12 store for
+	* a private individual - obviously you'll need to generate your own keys,
+	* and you may need to add a NetscapeCertType extension or add a key
+	* usage extension depending on your application, but you should get the
+	* idea! As always this is just an example...
+	*/
+	public class Pkcs12Example
+	{
+		private static readonly char[] passwd = "hello world".ToCharArray();
+
+		private static readonly X509V1CertificateGenerator v1CertGen = new X509V1CertificateGenerator();
+		private static readonly X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
+
+		/**
+		* we generate the CA's certificate
+		*/
+		public static X509CertificateEntry CreateMasterCert(
+			AsymmetricKeyParameter	pubKey,
+			AsymmetricKeyParameter	privKey)
+		{
+			//
+			// signers name
+			//
+			string issuer = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
+
+			//
+			// subjects name - the same as we are self signed.
+			//
+			string subject = "C=AU, O=The Legion of the Bouncy Castle, OU=Bouncy Primary Certificate";
+
+			//
+			// create the certificate - version 1
+			//
+
+			v1CertGen.SetSerialNumber(BigInteger.One);
+			v1CertGen.SetIssuerDN(new X509Name(issuer));
+			v1CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1));
+			v1CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1));
+			v1CertGen.SetSubjectDN(new X509Name(subject));
+			v1CertGen.SetPublicKey(pubKey);
+			v1CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			X509Certificate cert = v1CertGen.Generate(privKey);
+
+			cert.CheckValidity(DateTime.UtcNow);
+
+			cert.Verify(pubKey);
+
+//			PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)cert;
+			IDictionary bagAttr = new Hashtable();
+
+			//
+			// this is actually optional - but if you want to have control
+			// over setting the friendly name this is the way to do it...
+			//
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
+//				new DERBMPString("Bouncy Primary Certificate"));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id,
+				new DerBmpString("Bouncy Primary Certificate"));
+
+			return new X509CertificateEntry(cert, bagAttr);
+		}
+
+		/**
+		* we generate an intermediate certificate signed by our CA
+		*/
+		public static X509CertificateEntry CreateIntermediateCert(
+			AsymmetricKeyParameter	pubKey,
+			AsymmetricKeyParameter	caPrivKey,
+			X509Certificate			caCert)
+		{
+			//
+			// subject name table.
+			//
+			IDictionary attrs = new Hashtable();
+			IList order = new ArrayList();
+
+			attrs.Add(X509Name.C, "AU");
+			attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+			attrs.Add(X509Name.OU, "Bouncy Intermediate Certificate");
+			attrs.Add(X509Name.EmailAddress, "feedback-crypto at bouncycastle.org");
+
+			order.Add(X509Name.C);
+			order.Add(X509Name.O);
+			order.Add(X509Name.OU);
+			order.Add(X509Name.EmailAddress);
+
+			//
+			// create the certificate - version 3
+			//
+			v3CertGen.Reset();
+
+			v3CertGen.SetSerialNumber(BigInteger.Two);
+			v3CertGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert));
+			v3CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1));
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1));
+			v3CertGen.SetSubjectDN(new X509Name(order, attrs));
+			v3CertGen.SetPublicKey(pubKey);
+			v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			//
+			// extensions
+			//
+			v3CertGen.AddExtension(
+				X509Extensions.SubjectKeyIdentifier,
+				false,
+				new SubjectKeyIdentifierStructure(pubKey));
+
+			v3CertGen.AddExtension(
+				X509Extensions.AuthorityKeyIdentifier,
+				false,
+				new AuthorityKeyIdentifierStructure(caCert));
+
+			v3CertGen.AddExtension(
+				X509Extensions.BasicConstraints,
+				true,
+				new BasicConstraints(0));
+
+			X509Certificate cert = v3CertGen.Generate(caPrivKey);
+
+			cert.CheckValidity(DateTime.UtcNow);
+
+			cert.Verify(caCert.GetPublicKey());
+
+//			PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)cert;
+			IDictionary bagAttr = new Hashtable();
+
+			//
+			// this is actually optional - but if you want to have control
+			// over setting the friendly name this is the way to do it...
+			//
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
+//				new DERBMPString("Bouncy Intermediate Certificate"));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id,
+				new DerBmpString("Bouncy Intermediate Certificate"));
+
+			return new X509CertificateEntry(cert, bagAttr);
+		}
+
+		/**
+		* we generate a certificate signed by our CA's intermediate certficate
+		*/
+		public static X509CertificateEntry CreateCert(
+			AsymmetricKeyParameter	pubKey,
+			AsymmetricKeyParameter	caPrivKey,
+			AsymmetricKeyParameter	caPubKey)
+		{
+			//
+			// signers name table.
+			//
+			IDictionary sAttrs = new Hashtable();
+			IList sOrder = new ArrayList();
+
+			sAttrs.Add(X509Name.C, "AU");
+			sAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+			sAttrs.Add(X509Name.OU, "Bouncy Intermediate Certificate");
+			sAttrs.Add(X509Name.EmailAddress, "feedback-crypto at bouncycastle.org");
+
+			sOrder.Add(X509Name.C);
+			sOrder.Add(X509Name.O);
+			sOrder.Add(X509Name.OU);
+			sOrder.Add(X509Name.EmailAddress);
+
+			//
+			// subjects name table.
+			//
+			IDictionary attrs = new Hashtable();
+			IList order = new ArrayList();
+
+			attrs.Add(X509Name.C, "AU");
+			attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+			attrs.Add(X509Name.L, "Melbourne");
+			attrs.Add(X509Name.CN, "Eric H. Echidna");
+			attrs.Add(X509Name.EmailAddress, "feedback-crypto at bouncycastle.org");
+
+			order.Add(X509Name.C);
+			order.Add(X509Name.O);
+			order.Add(X509Name.L);
+			order.Add(X509Name.CN);
+			order.Add(X509Name.EmailAddress);
+
+			//
+			// create the certificate - version 3
+			//
+			v3CertGen.Reset();
+
+			v3CertGen.SetSerialNumber(BigInteger.Three);
+			v3CertGen.SetIssuerDN(new X509Name(sOrder, sAttrs));
+			v3CertGen.SetNotBefore(DateTime.UtcNow.AddMonths(-1));
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddMonths(1));
+			v3CertGen.SetSubjectDN(new X509Name(order, attrs));
+			v3CertGen.SetPublicKey(pubKey);
+			v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			//
+			// add the extensions
+			//
+			v3CertGen.AddExtension(
+				X509Extensions.SubjectKeyIdentifier,
+				false,
+				new SubjectKeyIdentifierStructure(pubKey));
+
+			v3CertGen.AddExtension(
+				X509Extensions.AuthorityKeyIdentifier,
+				false,
+				new AuthorityKeyIdentifierStructure(caPubKey));
+
+			X509Certificate cert = v3CertGen.Generate(caPrivKey);
+
+			cert.CheckValidity(DateTime.UtcNow);
+
+			cert.Verify(caPubKey);
+
+//			PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)cert;
+			IDictionary bagAttr = new Hashtable();
+
+			//
+			// this is also optional - in the sense that if you leave this
+			// out the keystore will add it automatically, note though that
+			// for the browser to recognise the associated private key this
+			// you should at least use the pkcs_9_localKeyId OID and set it
+			// to the same as you do for the private key's localKeyId.
+			//
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
+//				new DERBMPString("Eric's Key"));
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
+//				new SubjectKeyIdentifierStructure(pubKey));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id,
+				new DerBmpString("Eric's Key"));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id,
+				new SubjectKeyIdentifierStructure(pubKey));
+
+			return new X509CertificateEntry(cert, bagAttr);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+//			Security.addProvider(new BouncyCastleProvider());
+
+			//
+			// personal keys
+			//
+//			RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
+			RsaKeyParameters pubKey = new RsaKeyParameters(false,
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+//			RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
+			RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16),
+				new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+				new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+				new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+				new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+				new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+				new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+			//
+			// intermediate keys.
+			//
+//			RSAPublicKeySpec intPubKeySpec = new RSAPublicKeySpec(
+			RsaKeyParameters intPubKey = new RsaKeyParameters(false,
+				new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16),
+				new BigInteger("ffff", 16));
+
+
+//			RSAPrivateCrtKeySpec intPrivKeySpec = new RSAPrivateCrtKeySpec(
+			RsaPrivateCrtKeyParameters intPrivKey = new RsaPrivateCrtKeyParameters(
+				new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16),
+				new BigInteger("ffff", 16),
+				new BigInteger("7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff", 16),
+				new BigInteger("ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649", 16),
+				new BigInteger("97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721", 16),
+				new BigInteger("6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f", 16),
+				new BigInteger("70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f", 16),
+				new BigInteger("e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d", 16));
+
+			//
+			// ca keys
+			//
+//			RSAPublicKeySpec caPubKeySpec = new RSAPublicKeySpec(
+			RsaKeyParameters caPubKey = new RsaKeyParameters(false,
+				new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16),
+				new BigInteger("11", 16));
+
+//			RSAPrivateCrtKeySpec   caPrivKeySpec = new RSAPrivateCrtKeySpec(
+			RsaPrivateCrtKeyParameters caPrivKey = new RsaPrivateCrtKeyParameters(
+				new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16),
+				new BigInteger("11", 16),
+				new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16),
+				new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16),
+				new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16),
+				new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16),
+				new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16),
+				new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16));
+
+
+
+			//
+			// set up the keys
+			//
+//			KeyFactory          fact = KeyFactory.getInstance("RSA", "BC");
+//			PrivateKey          caPrivKey = fact.generatePrivate(caPrivKeySpec);
+//			PublicKey           caPubKey = fact.generatePublic(caPubKeySpec);
+//			PrivateKey          intPrivKey = fact.generatePrivate(intPrivKeySpec);
+//			PublicKey           intPubKey = fact.generatePublic(intPubKeySpec);
+//			PrivateKey          privKey = fact.generatePrivate(privKeySpec);
+//			PublicKey           pubKey = fact.generatePublic(pubKeySpec);
+
+			X509CertificateEntry[] chain = new X509CertificateEntry[3];
+
+			chain[2] = CreateMasterCert(caPubKey, caPrivKey);
+			chain[1] = CreateIntermediateCert(intPubKey, caPrivKey, chain[2].Certificate);
+			chain[0] = CreateCert(pubKey, intPrivKey, intPubKey);
+
+			//
+			// add the friendly name for the private key
+			//
+//			PKCS12BagAttributeCarrier   bagAttr = (PKCS12BagAttributeCarrier)privKey;
+			IDictionary bagAttr = new Hashtable();
+
+			//
+			// this is also optional - in the sense that if you leave this
+			// out the keystore will add it automatically, note though that
+			// for the browser to recognise which certificate the private key
+			// is associated with you should at least use the pkcs_9_localKeyId
+			// OID and set it to the same as you do for the private key's
+			// corresponding certificate.
+			//
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_friendlyName,
+//				new DERBMPString("Eric's Key"));
+//			bagAttr.setBagAttribute(
+//				PKCSObjectIdentifiers.pkcs_9_at_localKeyId,
+//				new SubjectKeyIdentifierStructure(pubKey));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtFriendlyName.Id,
+				new DerBmpString("Eric's Key"));
+			bagAttr.Add(PkcsObjectIdentifiers.Pkcs9AtLocalKeyID.Id,
+				new SubjectKeyIdentifierStructure(pubKey));
+
+			//
+			// store the key and the certificate chain
+			//
+//			KeyStore store = KeyStore.getInstance("PKCS12", "BC");
+//			store.load(null, null);
+			Pkcs12Store store = new Pkcs12StoreBuilder().Build();
+
+			//
+			// if you haven't set the friendly name and local key id above
+			// the name below will be the name of the key
+			//
+			store.SetKeyEntry("Eric's Key", new AsymmetricKeyEntry(privKey, bagAttr), chain);
+
+//			FileOutputStream fOut = new FileOutputStream("id.p12");
+//
+//			store.store(fOut, passwd);
+			FileStream fOut = File.Create("id.p12");
+			store.Save(fOut, passwd, new SecureRandom());
+			fOut.Close();
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs b/BouncyCastle.AxCrypt/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs
new file mode 100644
index 0000000..a41c992
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/pkcs/test/EncryptedPrivateKeyInfoTest.cs
@@ -0,0 +1,92 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Pkcs.Tests
+{
+    [TestFixture]
+    public class EncryptedPrivateKeyInfoTest
+        : SimpleTest
+    {
+        private readonly string alg = PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc.Id; // 3 key triple DES with SHA-1
+
+		public override string Name
+        {
+			get { return "EncryptedPrivateKeyInfoTest"; }
+        }
+
+		public override void PerformTest()
+        {
+            IAsymmetricCipherKeyPairGenerator pGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25);
+
+			pGen.Init(genParam);
+
+			AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+            //
+            // set up the parameters
+            //
+            byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+            int iterationCount = 100;
+
+			//
+            // set up the key
+            //
+            char[] password1 = { 'h', 'e', 'l', 'l', 'o' };
+
+            EncryptedPrivateKeyInfo  encInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(alg, password1, salt, iterationCount, PrivateKeyInfoFactory.CreatePrivateKeyInfo(pair.Private));
+
+            PrivateKeyInfo info = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password1, encInfo);
+
+            AsymmetricKeyParameter key = PrivateKeyFactory.CreateKey(info);
+
+            if (!key.Equals(pair.Private))
+            {
+                Fail("Key corrupted");
+            }
+
+			doOpensslTestKeys();
+		}
+
+		private void doOpensslTestKeys()
+		{
+			string[] names = GetTestDataEntries("keys");
+			foreach (string name in names)
+			{
+//				Console.Write(name + " => ");
+				Stream data = GetTestDataAsStream(name);
+				AsymmetricKeyParameter key = PrivateKeyFactory.DecryptKey("12345678a".ToCharArray(), data);
+//				Console.WriteLine(key.GetType().Name);
+				if (!(key is RsaPrivateCrtKeyParameters))
+				{
+					Fail("Sample key could not be decrypted: " + name);
+				}
+			}
+		}
+
+		public static void Main(
+            string[] args)
+        {
+			RunTest(new EncryptedPrivateKeyInfoTest());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS10Test.cs b/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS10Test.cs
new file mode 100644
index 0000000..d0227b9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS10Test.cs
@@ -0,0 +1,88 @@
+#region Using directives
+
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.Security;
+
+#endregion
+
+namespace Org.BouncyCastle.Pkcs.Tests
+{
+    [TestFixture]
+    public class Pkcs10Test
+        : SimpleTest
+    {
+        public override string Name
+        {
+			get { return "Pkcs10"; }
+        }
+
+		public override void PerformTest()
+        {
+            IAsymmetricCipherKeyPairGenerator pGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            RsaKeyGenerationParameters genParam = new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25);
+
+            pGen.Init(genParam);
+
+            AsymmetricCipherKeyPair pair = pGen.GenerateKeyPair();
+
+            IDictionary attrs = new Hashtable();
+
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.EmailAddress, "feedback-crypto at bouncycastle.org");
+
+            X509Name subject = new X509Name(new ArrayList(attrs.Keys), attrs);
+
+            Pkcs10CertificationRequest req1 = new Pkcs10CertificationRequest(
+				"SHA1withRSA",
+				subject,
+				pair.Public,
+				null,
+				pair.Private);
+
+			byte[] bytes = req1.GetEncoded();
+
+			Pkcs10CertificationRequest req2 = new Pkcs10CertificationRequest(bytes);
+
+			if (!req2.Verify())
+            {
+                Fail("Failed verify check.");
+            }
+
+            if (!req2.GetPublicKey().Equals(req1.GetPublicKey()))
+            {
+                Fail("Failed public key check.");
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+			RunTest(new Pkcs10Test());
+        }
+
+		[Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS12StoreTest.cs b/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS12StoreTest.cs
new file mode 100644
index 0000000..c6b3913
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/pkcs/test/PKCS12StoreTest.cs
@@ -0,0 +1,921 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Pkcs.Tests
+{
+	/**
+	* Exercise the various key stores, making sure we at least get back what we put in!
+	* <p>This tests both the PKCS12 key store.</p>
+	*/
+	[TestFixture]
+	public class Pkcs12StoreTest
+		: SimpleTest
+	{
+		private static readonly char[] passwd = "hello world".ToCharArray();
+
+		//
+		// pkcs-12 pfx-pdu
+		//
+		private static readonly byte[] pkcs12 = Base64.Decode(
+			"MIACAQMwgAYJKoZIhvcNAQcBoIAkgAQBMAQBgAQBMAQBgAQBBgQBCQQJKoZI"
+			+ "hvcNAQcBBAGgBAGABAEkBAGABAEEBAEBBAEwBAEEBAEDBAOCAzQEAQQEAQEE"
+			+ "ATAEAQQEAQMEA4IDMAQBBAQBAQQBBgQBBAQBAQQBCwQBBAQBCwQLKoZIhvcN"
+			+ "AQwKAQIEAQQEAQEEAaAEAQQEAQMEA4ICpQQBBAQBAQQBMAQBBAQBAwQDggKh"
+			+ "BAEEBAEBBAEwBAEEBAEBBAEbBAEEBAEBBAEGBAEEBAEBBAEKBAEEBAEKBAoq"
+			+ "hkiG9w0BDAEDBAEEBAEPBA8wDQQIoagiwNZPJR4CAQEEAQQEAQEEAQQEAQQE"
+			+ "AQMEA4ICgAQBBAQDggKABIICgEPG0XlhMFyrs4ZWDrvEzl51ICfXd6K2ql2l"
+			+ "nnxhszUbigtSj6x49VEx4PfOB9fQFeidc5L5An+nKp646NBMIY0UwXGs8BLQ"
+			+ "au59jtOs987+l7QYIvl6fdGUIuLPhVSnZZDyqD+HQjU/0/ccKFHRif4tlEQq"
+			+ "aErvZbFeH0pg4ijf1HfgX6gBJGRKdO+msa4qKGnZdHCSLZehyyxvxAmURetg"
+			+ "yhtEl7RmedTB+4TDs7atekqxkNlD9tfwDUX6sb0IH6qbEA6P/DlVMdaD54Cl"
+			+ "QDxRzOfIIjklZhv5OMFWtPK0aYPcqyxzLpw1qRAyoTVXpidkj/hpIpgCVBP/"
+			+ "k5s2+WdGbLgA/4/zSrF6feRCE5llzM2IGxiHVq4oPzzngl3R+Fi5VCPDMcuW"
+			+ "NRuIOzJA+RNV2NPOE/P3knThDnwiImq+rfxmvZ1u6T06s20RmWK6cxp7fTEw"
+			+ "lQ9BOsv+mmyV8dr6cYJq4IlRzHdFOyEUBDwfHThyribNKKobO50xh2f93xYj"
+			+ "Rn5UMOQBJIe3b7OKZt5HOIMrJSZO02IZgvImi9yQWi96PnWa419D1cAsLWvM"
+			+ "xiN0HqZMbDFfxVM2BZmsxiexLhkHWKwLqfQDzRjJfmVww8fnXpWZhFXKyut9"
+			+ "gMGEyCNoba4RU3QI/wHKWYaK74qtJpsucuLWBH6UcsHsCry6VZkwRxWwC0lb"
+			+ "/F3Bm5UKHax5n9JHJ2amQm9zW3WJ0S5stpPObfmg5ArhbPY+pVOsTqBRlop1"
+			+ "bYJLD/X8Qbs468Bwzej0FhoEU59ZxFrbjLSBsMUYrVrwD83JE9kEazMLVchc"
+			+ "uCB9WT1g0hxYb7VA0BhOrWhL8F5ZH72RMCYLPI0EAQQEAQEEATEEAQQEAQEE"
+			+ "AXgEAQQEAQEEATAEAQQEAQEEAVEEAQQEAQEEAQYEAQQEAQEEAQkEAQQEAQkE"
+			+ "CSqGSIb3DQEJFAQBBAQBAQQBMQQBBAQBAQQBRAQBBAQBAQQBHgQBBAQBAQQB"
+			+ "QgQBBAQBQgRCAEQAYQB2AGkAZAAgAEcALgAgAEgAbwBvAGsAJwBzACAAVgBl"
+			+ "AHIAaQBTAGkAZwBuACwAIABJAG4AYwAuACAASQBEBAEEBAEBBAEwBAEEBAEB"
+			+ "BAEjBAEEBAEBBAEGBAEEBAEBBAEJBAEEBAEJBAkqhkiG9w0BCRUEAQQEAQEE"
+			+ "ATEEAQQEAQEEARYEAQQEAQEEAQQEAQQEAQEEARQEAQQEARQEFKEcMJ798oZL"
+			+ "FkH0OnpbUBnrTLgWBAIAAAQCAAAEAgAABAEwBAGABAEGBAEJBAkqhkiG9w0B"
+			+ "BwYEAaAEAYAEATAEAYAEAQIEAQEEAQAEATAEAYAEAQYEAQkECSqGSIb3DQEH"
+			+ "AQQBMAQBGwQBBgQBCgQKKoZIhvcNAQwBBgQPMA0ECEE7euvmxxwYAgEBBAGg"
+			+ "BAGABAEEBAEIBAgQIWDGlBWxnwQBBAQBCAQI2WsMhavhSCcEAQQEAQgECPol"
+			+ "uHJy9bm/BAEEBAEQBBCiRxtllKXkJS2anKD2q3FHBAEEBAEIBAjKy6BRFysf"
+			+ "7gQBBAQDggMwBIIDMJWRGu2ZLZild3oz7UBdpBDUVMOA6eSoWiRIfVTo4++l"
+			+ "RUBm8TpmmGrVkV32PEoLkoV+reqlyWCvqqSjRzi3epQiVwPQ6PV+ccLqxDhV"
+			+ "pGWDRQ5UttDBC2+u4fUQVZi2Z1i1g2tsk6SzB3MKUCrjoWKvaDUUwXo5k9Vz"
+			+ "qSLWCLTZCjs3RaY+jg3NbLZYtfMDdYovhCU2jMYV9adJ8MxxmJRz+zPWAJph"
+			+ "LH8hhfkKG+wJOSszqk9BqGZUa/mnZyzeQSMTEFga1ZB/kt2e8SZFWrTZEBgJ"
+			+ "oszsL5MObbwMDowNurnZsnS+Mf7xi01LeG0VT1fjd6rn9BzVwuMwhoqyoCNo"
+			+ "ziUqSUyLEwnGTYYpvXLxzhNiYzW8546KdoEKDkEjhfYsc4XqSjm9NYy/BW/M"
+			+ "qR+aL92j8hqnkrWkrWyvocUe3mWaiqt7/oOzNZiMTcV2dgjjh9HfnjSHjFGe"
+			+ "CVhnEWzV7dQIVyc/qvNzOuND8X5IyJ28xb6a/i1vScwGuo/UDgPAaMjGw28f"
+			+ "siOZBShzde0Kj82y8NilfYLHHeIGRW+N/grUFWhW25mAcBReXDd5JwOqM/eF"
+			+ "y+4+zBzlO84ws88T1pkSifwtMldglN0APwr4hvUH0swfiqQOWtwyeM4t+bHd"
+			+ "5buAlXOkSeF5rrLzZ2/Lx+JJmI2pJ/CQx3ej3bxPlx/BmarUGAxaI4le5go4"
+			+ "KNfs4GV8U+dbEHQz+yDYL+ksYNs1eb+DjI2khbl28jhoeAFKBtu2gGOL5M9M"
+			+ "CIP/JDOCHimu1YZRuOTAf6WISnG/0Ri3pYZsgQ0i4cXj+WfYwYVjhKX5AcDj"
+			+ "UKnc4/Cxp+TbbgZqEKRcYVb2q0kOAxkeaNo3WCm+qvUYrwAmKp4nVB+/24rK"
+			+ "khHiyYJQsETxtOEyvJkVxAS01djY4amuJ4jL0sYnXIhW3Ag93eavbzksGT7W"
+			+ "Fg1ywpr1x1xpXWIIuVt1k4e+g9fy7Yx7rx0IK1qCSjNwU3QPWbaef1rp0Q/X"
+			+ "P9IVXYkqo1g/T3SyXqrbZLO+sDjiG4IT3z3fJJqt81sRSVT0QN1ND8l93BG4"
+			+ "QKzghYw8sZ4FwKPtLky1dDcVTgQBBAQBCAQIK/85VMKWDWYEAQQEAQgECGsO"
+			+ "Q85CcFwPBAEEBAEIBAhaup6ot9XnQAQBBAQCgaAEgaCeCMadSm5fkLfhErYQ"
+			+ "DgePZl/rrjP9FQ3VJZ13XrjTSjTRknAbXi0DEu2tvAbmCf0sdoVNuZIZ92W0"
+			+ "iyaa2/A3RHA2RLPNQz5meTi1RE2N361yR0q181dC3ztkkJ8PLyd74nCtgPUX"
+			+ "0JlsvLRrdSjPBpBQ14GiM8VjqeIY7EVFy3vte6IbPzodxaviuSc70iXM4Yko"
+			+ "fQq6oaSjNBFRqkHrBAEEBAEIBAjlIvOf8SnfugQBBAQBCAQIutCF3Jovvl0E"
+			+ "AQQEAQgECO7jxbucdp/3BAEEBAEIBAidxK3XDLj+BwQBBAQBCAQI3m/HMbd3"
+			+ "TwwEAQQEA4ICOASCAjgtoCiMfTkjpCRuMhF5gNLRBiNv+xjg6GvZftR12qiJ"
+			+ "dLeCERI5bvXbh9GD6U+DjTUfhEab/37TbiI7VOFzsI/R137sYy9Tbnu7qkSx"
+			+ "u0bTvyXSSmio6sMRiWIcakmDbv+TDWR/xgtj7+7C6p+1jfUGXn/RjB3vlyjL"
+			+ "Q9lFe5F84qkZjnADo66p9gor2a48fgGm/nkABIUeyzFWCiTp9v6FEzuBfeuP"
+			+ "T9qoKSnCitaXRCru5qekF6L5LJHLNXLtIMSrbO0bS3hZK58FZAUVMaqawesJ"
+			+ "e/sVfQip9x/aFQ6U3KlSpJkmZK4TAqp9jIfxBC8CclbuwmoXPMomiCH57ykr"
+			+ "vkFHOGcxRcCxax5HySCwSyPDr8I4+6Kocty61i/1Xr4xJjb+3oyFStIpB24x"
+			+ "+ALb0Mz6mUa1ls76o+iQv0VM2YFwnx+TC8KC1+O4cNOE/gKeh0ircenVX83h"
+			+ "GNez8C5Ltg81g6p9HqZPc2pkwsneX2sJ4jMsjDhewV7TyyS3x3Uy3vTpZPek"
+			+ "VdjYeVIcgAz8VLJOpsIjyHMB57AyT7Yj87hVVy//VODnE1T88tRXZb+D+fCg"
+			+ "lj2weQ/bZtFzDX0ReiEQP6+yklGah59omeklIy9wctGV1o9GNZnGBSLvQ5NI"
+			+ "61e9zmQTJD2iDjihvQA/6+edKswCjGRX6rMjRWXT5Jv436l75DVoUj09tgR9"
+			+ "ytXSathCjQUL9MNXzUMtr7mgEUPETjM/kYBR7CNrsc+gWTWHYaSWuqKVBAEE"
+			+ "BAEIBAh6slfZ6iqkqwQBBAQBCAQI9McJKl5a+UwEAQQEATgEOBelrmiYMay3"
+			+ "q0OW2x2a8QQodYqdUs1TCUU4JhfFGFRy+g3yU1cP/9ZSI8gcI4skdPc31cFG"
+			+ "grP7BAEEBAEIBAhzv/wSV+RBJQQBBAQBCAQI837ImVqqlr4EAQQEAQgECGeU"
+			+ "gjULLnylBAEEBAEIBAjD3P4hlSBCvQQBBAQBCAQISP/qivIzf50EAQQEAQgE"
+			+ "CKIDMX9PKxICBAEEBAOCBOgEggTocP5VVT1vWvpAV6koZupKN1btJ3C01dR6"
+			+ "16g1zJ5FK5xL1PTdA0r6iAwVtgYdxQYnU8tht3bkNXdPJC1BdsC9oTkBg9Nr"
+			+ "dqlF5cCzXWIezcR3ObjGLpXu49SAHvChH4emT5rytv81MYxZ7bGmlQfp8BNa"
+			+ "0cMZz05A56LXw//WWDEzZcbKSk4tCsfMXBdGk/ngs7aILZ4FGM620PBPtD92"
+			+ "pz2Ui/tUZqtQ0WKdLzwga1E/rl02a/x78/OdlVRNeaIYWJWLmLavX98w0PhY"
+			+ "ha3Tbj/fqq+H3ua6Vv2Ff4VeXazkXpp4tTiqUxhc6aAGiRYckwZaP7OPSbos"
+			+ "RKFlRLVofSGu1IVSKO+7faxV4IrVaAAzqRwLGkpJZLV7NkzkU1BwgvsAZAI4"
+			+ "WClPDF228ygbhLwrSN2NK0s+5bKhTCNAR/LCUf3k7uip3ZSe18IwEkUMWiaZ"
+			+ "ayktcTYn2ZjmfIfV7wIxHgWPkP1DeB+RMS7VZe9zEgJKOA16L+9SNBwJSSs9"
+			+ "5Sb1+nmhquZmnAltsXMgwOrR12JLIgdfyyqGcNq997U0/KuHybqBVDVu0Fyr"
+			+ "6O+q5oRmQZq6rju7h+Hb/ZUqRxRoTTSPjGD4Cu9vUqkoNVgwYOT+88FIMYun"
+			+ "g9eChhio2kwPYwU/9BNGGzh+hAvAKcUpO016mGLImYin+FpQxodJXfpNCFpG"
+			+ "4v4HhIwKh71OOfL6ocM/518dYwuU4Ds2/JrDhYYFsn+KprLftjrnTBnSsfYS"
+			+ "t68b+Xr16qv9r6sseEkXbsaNbrGiZAhfHEVBOxQ4lchHrMp4zpduxG4crmpc"
+			+ "+Jy4SadvS0uaJvADgI03DpsDYffUdriECUqAfOg/Hr7HHyr6Q9XMo1GfIarz"
+			+ "eUHBgi1Ny0nDTWkdb7I3bIajG+Unr3KfK6dZz5Lb3g5NeclU5zintB1045Jr"
+			+ "j9fvGGk0/2lG0n17QViBiOzGs2poTlhn7YxmiskwlkRKVafxPZNPxKILpN9s"
+			+ "YaWGz93qER/pGMJarGJxu8sFi3+yt6FZ4pVPkvKE8JZMEPBBrmH41batS3sw"
+			+ "sfnJ5CicAkwd8bluQpoc6qQd81HdNpS6u7djaRSDwPtYnZWu/8Hhj4DXisje"
+			+ "FJBAjQdn2nK4MV7WKVwr+mNcVgOdc5IuOZbRLOfc3Sff6kYVuQFfcCGgAFpd"
+			+ "nbprF/FnYXR/rghWE7fT1gfzSMNv+z5UjZ5Rtg1S/IQfUM/P7t0UqQ01/w58"
+			+ "bTlMGihTxHiJ4Qf3o5GUzNmAyryLvID+nOFqxpr5es6kqSN4GPRHsmUIpB9t"
+			+ "f9Nw952vhsXI9uVkhQap3JvmdAKJaIyDz6Qi7JBZvhxpghVIDh73BQTaAFP9"
+			+ "5GUcPbYOYJzKaU5MeYEsorGoanSqPDeKDeZxjxJD4xFsqJCoutyssqIxnXUN"
+			+ "Y3Uojbz26IJOhqIBLaUn6QVFX79buWYjJ5ZkDS7D8kq6DZeqZclt5711AO5U"
+			+ "uz/eDSrx3d4iVHR+kSeopxFKsrK+KCH3CbBUMIFGX/GE9WPhDWCtjjNKEe8W"
+			+ "PinQtxvv8MlqGXtv3v7ObJ2BmfIfLD0rh3EB5WuRNKL7Ssxaq14KZGEBvc7G"
+			+ "Fx7jXLOW6ZV3SH+C3deJGlKM2kVhDdIVjjODvQzD8qw8a/ZKqDO5hGGKUTGD"
+			+ "Psdd7O/k/Wfn+XdE+YuKIhcEAQQEAQgECJJCZNJdIshRBAEEBAEIBAiGGrlG"
+			+ "HlKwrAQBBAQBCAQIkdvKinJYjJcEAQQEAUAEQBGiIgN/s1bvPQr+p1aQNh/X"
+			+ "UQFmay6Vm5HIvPhoNrX86gmMjr6/sg28/WCRtSfyuYjwQkK91n7MwFLOBaU3"
+			+ "RrsEAQQEAQgECLRqESFR50+zBAEEBAEIBAguqbAEWMTiPwQBBAQBGAQYKzUv"
+			+ "EetQEAe3cXEGlSsY4a/MNTbzu1WbBAEEBAEIBAiVpOv1dOWZ1AQCAAAEAgAA"
+			+ "BAIAAAQCAAAEAgAABAIAAAAAAAAAADA1MCEwCQYFKw4DAhoFAAQUvMkeVqe6"
+			+ "D4UmMHGEQwcb8O7ZwhgEEGiX9DeqtRwQnVi+iY/6Re8AAA==");
+
+		private static readonly byte[] certUTF = Base64.Decode(
+			"MIIGVQIBAzCCBg8GCSqGSIb3DQEHAaCCBgAEggX8MIIF+DCCAsUGCSqGSIb3"
+			+ "DQEHAaCCArYEggKyMIICrjCCAqoGCyqGSIb3DQEMCgEDoIIChTCCAoEGCiqG"
+			+ "SIb3DQEJFgGgggJxBIICbTCCAmkwggHSoAMCAQICAQcwDQYJKoZIhvcNAQEF"
+			+ "BQAwOTEPMA0GA1UEBxMGTGV1dmVuMRkwFwYDVQQKExBVdGltYWNvIFN1YiBD"
+			+ "QSAyMQswCQYDVQQGEwJCRTAeFw05OTEyMzEyMzAwMDBaFw0xOTEyMzEyMzAw"
+			+ "MDBaMFcxCzAJBgNVBAYTAkJFMQ8wDQYDVQQHEwZIYWFjaHQxEDAOBgNVBAoT"
+			+ "B1V0aW1hY28xDDAKBgNVBAsMA1ImRDEXMBUGA1UEAxMOR2VlcnQgRGUgUHJp"
+			+ "bnMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYGIyhTn/p0IA41ElLD"
+			+ "fZ44PS88AAcDCiOd2DIMLck56ea+5nhI0JLyz1XgPHecc8SLFdl7vSIBA0eb"
+			+ "tm/A7WIqIp0lcvgoyQ0qsak/dvzs+xw6r2xLCVogku4+/To6UebtfRsukXNI"
+			+ "ckP5lWV/Ui4l+XvGdmENlEE9/BvOZIvLAgMBAAGjYzBhMBEGA1UdIwQKMAiA"
+			+ "BlN1YkNBMjAQBgNVHQ4ECQQHVXNlcklEMjAOBgNVHQ8BAf8EBAMCBLAwGQYD"
+			+ "VR0RBBIwEIEOVXNlcklEMkB1dGkuYmUwDwYDVR0TAQH/BAUwAwEBADANBgkq"
+			+ "hkiG9w0BAQUFAAOBgQACS7iLLgMV4O5gFdriI7dqX55l7Qn6HiRNxlSH2kCX"
+			+ "41X82gae4MHFc41qqsC4qm6KZWi1yvTN9XgSBCXTaw1SXGTK7SuNdoYh6ufC"
+			+ "KuAwy5lsaetyARDksRiOIrNV9j+MRIjJMjPNg+S+ysIHTWZo2NTUuVuZ01D2"
+			+ "jDtYPhcDFDESMBAGCSqGSIb3DQEJFTEDBAE3MIIDKwYJKoZIhvcNAQcGoIID"
+			+ "HDCCAxgCAQAwggMRBgkqhkiG9w0BBwEwKAYKKoZIhvcNAQwBAzAaBBS5KxQC"
+			+ "BMuZ1To+yed2j/TT45td6gICCACAggLYxQS+fu7W2sLQTkslI0EoNxLoH/WO"
+			+ "L8NgiIgZ5temV3mgC2q0MxjVVq+SCvG89ZSTfptxOaSmYV772irFdzlrtotZ"
+			+ "wmYk1axuFDYQ1gH0M6i9FWuhOnbk7qHclmOroXqrrbP6g3IsjwztH0+iwBCg"
+			+ "39f63V0rr8DHiu7zZ2hBkU4/RHEsXLjaCBVNTUSssWhVLisLh2sqBJccPC2E"
+			+ "1lw4c4WrshGQ+syLGG38ttFgXT1c+xYNpUKqJiJTLVouOH9kK3nH1hPRHKMN"
+			+ "9CucBdUzibvkcRk1L53F3MfvjhCSNeWEmd9PKN+FtUtzRWQG3L84VGTM37Ws"
+			+ "YcxaDwDFGcw3u1W8WFsCCkjpZecKN8P2Kp/ai/iugcXY77bYwAwpETDvQFvD"
+			+ "nnL9oGi03HYdfeiXglC7x7dlojvnpkXDbE0nJiFwhe8Mxpx8GVlGHtP+siXg"
+			+ "tklubg1eTCSoG9m1rsBJM717ZHXUGf32HNun2dn4vOWGocgBmokZ46KKMb9v"
+			+ "reT39JTxi8Jlp+2cYb6Qr/oBzudR+D4iAiiVhhhEbJKPNHa61YyxF810fNI2"
+			+ "GWlNIyN3KcI8XU6WJutm/0H3X8Y+iCSWrJ2exUktj8GiqNQ6Yx0YgEk9HI7W"
+			+ "t9UVTIsPCgCqrV4SWCOPf6so1JqnpvlPvvNyNxSsAJ7DaJx1+oD2QQfhowk/"
+			+ "bygkKnRo5Y15ThrTsIyQKsJHTIVy+6K5uFZnlT1DGV3DcNpuk3AY26hrAzWO"
+			+ "TuWXsULZe7M6h6U2hTT/eplZ/mwHlXdF1VErIuusaCdkSI0doY4/Q223H40L"
+			+ "BNU3pTezl41PLceSll00WGVr2MunlNeXKnXDJW06lnfs9BmnpV2+Lkfmf30W"
+			+ "Pn4RKJQc+3D3SV4fCoQLIGrKiZLFfEdGJcMlySr+dJYcEtoZPuo6i/hb5xot"
+			+ "le63h65ihNtXlEDrNpYSQqnfhjOzk5/+ZvYEcOtDObEwPTAhMAkGBSsOAwIa"
+			+ "BQAEFMIeDI9l2Da24mtA1fbQIPc6+4dUBBQ8a4lD7j1CA1vRLhdEgPM+5hpD"
+			+ "RgICCAA=");
+
+		private static readonly byte[] pkcs12noFriendly = Base64.Decode(
+			"MIACAQMwgAYJKoZIhvcNAQcBoIAkgASCBAAwgDCABgkqhkiG9w0BBwGggCSA"
+			+ "BIICvjCCArowggK2BgsqhkiG9w0BDAoBAqCCAqUwggKhMBsGCiqGSIb3DQEM"
+			+ "AQMwDQQIyJDupEHvySECAQEEggKAupvM7RuZL3G4qNeJM3afElt03TVfynRT"
+			+ "xUxAZOfx+zekHJTlnEuHJ+a16cOV6dQUgYfyMw1xcq4E+l59rVeMX9V3Zr0K"
+			+ "tsMN9VYB/9zn62Kw6LQnY0rMlWYf4bt9Ut5ysq0hE5t9FL+NZ5FbFdWBOKsj"
+			+ "/3oC6eNXOkOFyrY2haPJtD1hVHUosrlC0ffecV0YxPDsReeyx0R4CiYZpAUy"
+			+ "ZD7rkxL+mSX7zTsShRiga2Q/NEhC1KZpbhO/qbyOgvH0r7CRumSMvijzDgaV"
+			+ "IGqtrIZ2E2k5kscjcuFTW0x3OZTLAW/UnAh4JXJzC6isbdiWuswbAEBHifUC"
+			+ "rk2f+bDJKe2gkH67J2K0yDQ3YSSibpjDX/bVfbtfmOoggK9MKQwqEeE0nbYE"
+			+ "jzInH2OK5jPtmwppjmVA7i3Uk25w2+z7b/suUbft9hPCNjxFvzdbyCcXK4Vv"
+			+ "xAgEbVWnIkvOQNbyaQi+DEF/4P26GwgJgXuJpMBn0zzsSZSIDLNl8eJHoKp2"
+			+ "ZXknTi0SZkLaYlBxZlNhFoyXLfvQd6TI2aR5aCVqg1aZMBXyOWfz5t0JTVX8"
+			+ "HTIcdXKis91iEsLB7vjcxIOASTAjKARr5tRp6OvaVterAyDOn2awYQJLLic5"
+			+ "pQfditRAlsLkTxlDdu0/QBMXSPptO8g3R+dS7ntvCjXgZZyxpOeKkssS2l5v"
+			+ "/B2EsfKmYA9hU4aBdW1S9o/PcF1wpVqABd8664TGJ77tCAkbdHe0VJ3Bop2X"
+			+ "lNxlWeEeD0v0QUZLqkJoMEwi5SUE6HAWjbqGhRuHyey9E+UsdCVnQ8AxXQzL"
+			+ "2UKOmIrXc6R25GsLPCysXuXPRFBB2Tul0V3re3hPcAAAAAAAADCABgkqhkiG"
+			+ "9w0BBwaggDCAAgEAMIAGCSqGSIb3DQEHATAbBgoqhkiG9w0BDAEGMA0ECDXn"
+			+ "UZu6xckzAgEBoIAEggTYQMbzAoGnRVJMbCaJJUYgaARJ4zMfxt2e12H4pX/e"
+			+ "vnZrR1eKAMck5c2vJoEasr0i2VUcAcK12AntVIEnBwuRBcA2WrZnC28WR+O7"
+			+ "rLdu9ymG2V3zmk66aTizaB6rcHAzs2lD74n+/zJhZNaDMBfu9LzAdWb/u6Rb"
+			+ "AThmbw764Zyv9802pET6xrB8ureffgyvQAdlcGHM+yxaOV3ZEtS0cp7i+pb/"
+			+ "NTiET4jAFoO1tbBrWGJSRrMKvx4ZREppMhG3e/pYglfMFl+1ejbDsOvEUKSt"
+			+ "H+MVrgDgAv4NsUtNmBu+BIIEAIOCjrBSK3brtV0NZOWsa6hZSSGBhflbEY8s"
+			+ "U1bDsgZIW4ZaJJvSYEXLmiWSBOgq9VxojMfjowY+zj6ePJJMyI3E7AcFa+on"
+			+ "zZjeKxkKypER+TtpBeraqUfgf01b6olH8L2i4+1yotCQ0PS+15qRYPK6D+d3"
+			+ "S+R4veOA6wEsNRijVcB3oQsBCi0FVdf+6MVDvjNzBCZXj0heVi+x0EE106Sz"
+			+ "B3HaDbB/KNHMPZvvs3J3z2lWLj5w7YZ9eVmrVJKsgG2HRKxtt2IQquRj4BkS"
+			+ "upFnMTBVgWxXgwXycauC9bgYZurs+DbijqhHfWpUrttDfavsP8aX6+i3gabK"
+			+ "DH4LQRL7xrTcKkcUHxOTcPHLgDPhi+RevkV+BX9tdajbk4tqw1d+0wOkf1pW"
+			+ "aTG8fUp0lUpra7EJ0lGy8t/MB3NEk/5tLk9qA2nsKKdNoEdZWiEBE0fMrH1o"
+			+ "tWJDew3VhspT+Lkor2dLN5ydjcr3wkb76OETPeMxS91onNj5mrAMUBt66vb6"
+			+ "Gx4CL8FTRNZ/l8Kzngzdv9PmmKPTIXbhYbn3XRGg3od2tC/oVfsqYlGAMgFO"
+			+ "STt+BZ1BR9Phyi4jsiy8R0seCEDRWYQLbwgwVj0V8Rx9VptqRoCnB4XhGJoJ"
+			+ "TdAz/MT7KOSxIh2F2FymTJpyImcV6X4Kcj9iY0AZQ4zj712g4yMR6xKGzRu6"
+			+ "oIBDkFW2bdA3Lb9ePpo5GFtNyA7IbggIko6VOeeOKxaq9nALS2gsZc1yaYtp"
+			+ "aKL8kB+dVTCXiLgQniO6eMzgonsuwFnG+42XM1vhEpAvFzeJRC0CYzebEK9n"
+			+ "nGXKCPoqPFuw3gcPMn57NCZJ8MjT/p0wANIEm6AsgqrdFKwTRVJ1ytB/X9Ri"
+			+ "ysmjMBs9zbFKjU9jVDg1vGBNtb7YnYg9IrYHa3e4yTu2wUJKGP2XWHVgjDR7"
+			+ "6RtzlO4ljw0kkSMMEDle2ZbGZ6lVXbFwV0wPNPmGA6+XGJRxcddTnrM6R/41"
+			+ "zqksFLgoNL2BdofMXwv7SzxGyvFhHdRRdBZ5dKj2K9OfXakEcm/asZGu87u8"
+			+ "y9m7Cckw8ilSNPMdvYiFRoThICx9NiwYl1IIKGcWlb9p6RAx6XNSkY6ZZ6pE"
+			+ "Vla1E26rbd7is1ssSeqxLXXV9anuG5HDwMIt+CIbD8fZmNTcWMzZRiaFajvR"
+			+ "gXdyTu/UhVdhiQPF+lrxp4odgF0cXrpcGaKvOtPq04F4ad3O5EkSGucI210Q"
+			+ "pR/jQs07Yp5xDPzsXAb8naHb84FvK1iONAEjWbfhDxqtH7KGrBbW4KEzJrv3"
+			+ "B8GLDp+wOAFjGEdGDPkOx3y2L2HuI1XiS9LwL+psCily/A96OiUyRU8yEz4A"
+			+ "AAAAAAAAAAAEAwAAAAAAAAAAADAtMCEwCQYFKw4DAhoFAAQU1NQjgVRH6Vg3"
+			+ "tTy3wnQisALy9aYECKiM2gZrLi+fAAA=");
+
+		private static readonly char[] noFriendlyPassword = "sschette12".ToCharArray();
+
+		private static readonly byte[] pkcs12StorageIssue = Base64.Decode(
+			"MIIO8QIBAzCCDrEGCSqGSIb3DQEHAaCCDqIEgg6eMIIOmjCCBBMGCSqGSIb3"
+			+ "DQEHAaCCBAQEggQAMIID/DCCA/gGCyqGSIb3DQEMCgECoIICtjCCArIwHAYK"
+			+ "KoZIhvcNAQwBAzAOBAgURJ+/5hA2pgICB9AEggKQYZ4POE8clgH9Bjd1XO8m"
+			+ "sr6NiRBiA08CllHSOn2RzyAgHTa+cKaWrEVVJ9mCd9XveSUCoBF9E1C3jSl0"
+			+ "XIqLNgYd6mWK9BpeMRImM/5crjy///K4ab9kymzkc5qc0pIpdCQCZ04YmtFP"
+			+ "B80VCgyaoh2xoxqgjBCIgdSg5XdepdA5nXkG9EsQ1oVUyCykv20lKgKKRseG"
+			+ "Jo23AX8YUYR7ANqP2gz9lvlX6RBczuoZ62ujopUexiQgt5SZx97sgo3o/b/C"
+			+ "px17A2L4wLdeAYCMCsZhC2UeaqnZCHSsvnPZfRGiuSEGbV5gHLmXszLDaEdQ"
+			+ "Bo873GTpKTTzBfRFzNCtYtZRqh2AUsInWZWQUcCeX6Ogwa0wTonkp18/tqsh"
+			+ "Fj1fVpnsRmjJTTXFxkPtUw5GPJnDAM0t1xqV7kOjN76XnZrMyk2azQ1Mf3Hn"
+			+ "sGpF+VRGH6JtxbM0Jm5zD9uHcmkSfNR3tP/+vHOB1mkIR9tD2cHvBg7pAlPD"
+			+ "RfDVWynhS+UBNlQ0SEM/pgR7PytRSUoKc/hhe3N8VerF7VL3BwWfBLlZFYZH"
+			+ "FvPQg4coxF7+We7nrSQfXvdVBP9Zf0PTdf3pbZelGCPVjOzbzY/o/cB23IwC"
+			+ "ONxlY8SC1nJDXrPZ5sY51cg/qUqor056YqipRlI6I+FoTMmMDKPAiV1V5ibo"
+			+ "DNQJkyv/CAbTX4+oFlxgddTwYcPZgd/GoGjiP9yBHHdRISatHwMcM06CzXJS"
+			+ "s3MhzXWD4aNxvvSpXAngDLdlB7cm4ja2klmMzL7IuxzLXFQFFvYf7IF5I1pC"
+			+ "YZOmTlJgp0efL9bHjuHFnh0S0lPtlGDOjJ/4YpWvSKDplcPiXhaFVjsUtclE"
+			+ "oxCC5xppRm8QWS8xggEtMA0GCSsGAQQBgjcRAjEAMBMGCSqGSIb3DQEJFTEG"
+			+ "BAQBAAAAMGkGCSsGAQQBgjcRATFcHloATQBpAGMAcgBvAHMAbwBmAHQAIABS"
+			+ "AFMAQQAgAFMAQwBoAGEAbgBuAGUAbAAgAEMAcgB5AHAAdABvAGcAcgBhAHAA"
+			+ "aABpAGMAIABQAHIAbwB2AGkAZABlAHIwgZsGCSqGSIb3DQEJFDGBjR6BigA3"
+			+ "AGQAZQBmADUAYgA0ADMANgBjAGEAYgBkADAAMAAyAGQAZAAyADkAMAAzAGIA"
+			+ "MQA2ADgANgBjADcAOQA0ADgAXwA0ADYAZgAyADYAZgBkADQALQA4ADEAMgBk"
+			+ "AC0ANABlAGYAYgAtADgAMAA4ADgALQA0ADUAYQBiADkAMQA5ADEAMAA3AGMA"
+			+ "YzCCCn8GCSqGSIb3DQEHBqCCCnAwggpsAgEAMIIKZQYJKoZIhvcNAQcBMBwG"
+			+ "CiqGSIb3DQEMAQYwDgQIbr2xdnQ9inMCAgfQgIIKOHg9VKz+jlM+3abi3cp6"
+			+ "/XMathxDSEJLrxJs6j5DAVX17S4sw1Q/1pptjdMdd8QtTfUB6JpfgJ5Kpn+h"
+			+ "gZMf6M8wWue0U/RZN0D9w7o+2n+X3ItdEXu80eJVDOm7I2p8qiXtijbMbXRL"
+			+ "Cup1lgfPM5uv2D63/hmWRXLeG8eySrJnKENngpM559V8TI2JcTUBy1ZP3kcH"
+			+ "KbcJ/tVPnIIe4qguxfsTmDtAQviGvWUohbt+RGFmtqfgntK7o6b+S8uRSwEs"
+			+ "fOU/pnVE9M1ugtNJZI/xeGJq6umZWXA/OrAcK7feWUwqRvfivDGQJEoggByd"
+			+ "4/g92PhK1JGkwlCb1HdfhOOKKChowQ4zVvSOm+uBxARGhk2i5uW9I20I0vSJ"
+			+ "px42O2VFVJweOchfp+wBtSHBKYP1ZXyXWMvOtULClosSeesbYMAwvyBfpYEz"
+			+ "3rQt/1iZkqDmEisXk8X1aEKG1KSWaSPyb/+6glWikDm+YdQw3Khu7IZt1l/H"
+			+ "qWGecccel+R9mT4YjRzHlahUYk4U+RNVasVpH1Kxz2j3CZqL+b3jQOwSAPd/"
+			+ "hKI+S/pjIpBPfiC4WxORAzGZzY2j+a79B70h1DO1D9jGur3vJDbdmGBNgs6d"
+			+ "nonE1B527SICcGeXY1MtnZCLOPvySih0AvOekbN9x2CJg+Hp9e7A3Fxni53/"
+			+ "oMLr9wGRRDki72eXCXW98mU8VJofoWYS1/VBLXGf/f+tJ9J02PpzxleqPH9T"
+			+ "4mE+YHnZId6cqjCXmwvMr2cMw2clDVfvkbAJRE3eZHzL7IWSO8+giXzzrTsl"
+			+ "VbMuXVkT4oniTN7TSRsBCT3zVVmCy1QL2hPBD6KsVc+bvLgAHRov84FPrI3f"
+			+ "kY/oJufT36VE34Eu+QjzULlvVsLE3lhjutOerVIGSP//FM4LE99hp214P0JF"
+			+ "DgBK+3J+ihmFdW8hUXOt6BU8/MBeiroiJMWo1/f/XcduekG2ZsdGv+GNPzXI"
+			+ "PyHRpCgAgmck1+qoUPXxHRJuNqv223OZ5MN14X7iLl5OZ+f8IWfxUnZeZ9gj"
+			+ "HNeceElwZ+YOup1CAi3haD9jxRWhZG4NDfB4IYi4Bc/TAkXE3jCPkYEvIbj9"
+			+ "ExaU1Ts0+lqOOcwRmBoYjVrz0xbtfR/OWlopyrDHbeL5iQcQCW/loYRapWCZ"
+			+ "E4ekHknpX9yoAwT355vtTkl0VKXeSZHE8jREhN95aY9zCoLYwbTQDTw7qUR5"
+			+ "UamabLew0oS0XALtuOrfX4OUOZZUstUsGBle/Pw1TE3Bhe1clhrikp0F+Xgb"
+			+ "Xx90KqxZX/36RMnCMAD7/q+57rV7WXp2Y5tT0AUgyUMjy1F1X/b1olUfqO1u"
+			+ "rlWIUTl2znmQ3D9uO3W4ytfgGd5DpKcl2w84MBAT9qGwKuQg/UYKbP4K/+4L"
+			+ "Y1DWCy3utmohQ28IJtlIUkPL1G7lHX1tfq/VA+bRNTJIhMrNn06ZJpuEJHDs"
+			+ "/ferdlMFt/d6MrwVivmPVYkb8mSbHSiI8jZOFE44sA974depsDyXafFaSsl0"
+			+ "bVzqOAu0C/n9dIednU0xxxgDF/djdZ/QhbaDIg2VJf11wx0nw9n76B0+eeyu"
+			+ "QLaapzxCpQNDVOAM9doBb5F1I5pXQHFQqzTNtLmqDC4x0g8IH7asyk5LCglT"
+			+ "b1pwMqPJOL2vGWKRLhPzT+9OfSpCmYGKytf593hmGmwIgEO13hQrw31F5TYt"
+			+ "btkbDr+Q5XilOKEczhEM+Ug7YHU7bxkckOAbxu0YeRp/57GdGLokeLJ0dRlQ"
+			+ "+V2CfQvWJoVC6PS4PUQtjwgK2p/LU10QsEFwM/S621fGq9zGrv7+FPBATRDb"
+			+ "k4E9D/WaRylnW11ZTrOlTchQkoHcOh0xztlFxU8jzuIuDrPQQWkoqdl6B+yf"
+			+ "lykRNJKKxwzFiPl40nLC3nEdIzCEvR4r/9QHiWQxAVSc/wQX+an5vakUmSXS"
+			+ "oLFjgVdY1jmvdsx2r5BQPuOR8ONGmw/muvVSMaHV85brA4uk0lxn00HD9/a0"
+			+ "A1LCeFkabNLn9wJT8RaJeOSNmFFllLR70OHaoPSb3GyzHpvd1e6aeaimdyVH"
+			+ "BQWJ6Ufx+HjbOGuOiN46WyE6Q27dnWxx8qF89dKB4T/J0mEXqueiUjAUnnnR"
+			+ "Cs4zPaX53hmNBdrZGaLs+xNG8xy+iyBUJIWWfQAQjCjfHYlT9nygiUWIbVQq"
+			+ "RHkGkAN62jsSNLgHvWVzQPNNsYq0U8TPhyyci/vc8MJytujjptcz8FPqUjg2"
+			+ "TPv34ef9buErsm4vsdEv/8Z+9aDaNex+O3Lo3N0Aw7M5NcntFBHjFY/nBFNZ"
+			+ "whH5YA4gQ8PLZ5qshlGvb0DFXHV/9zxnsdPkLwH47ERm5IlEAuoaWtZFxg27"
+			+ "BjLfwU1Opk+ybDSb5WZVZrs7ljsU85p3Vaf3a//yoyr9ITYj15tTXxSPoct0"
+			+ "fDUy1I6LjJH/+eZXKA1WSda9mDQlRocvJ0IIIlI4weJpTdm8aHIJ8OngCqOF"
+			+ "TufcSLDM41+nxEK1LqXeAScVy74kVvvqngj6mIrbylrINZOHheEgTXrUWEc0"
+			+ "uXS8l1YqY6K6Ru5km2jVyWi/ujrDGb6QGShC09oiDYUuUGy4gwJ3XLVX/dR3"
+			+ "pmMExohTGiVefFP400wVZaxB9g1BQmjSEZxIaW1U1K6fk8Yni8yWB3/L/PuD"
+			+ "0+OV+98i1sQGaPe35crIpEc7R2XJdngL0Ol1ZuvCIBfy5DQwGIawTtBnjPdi"
+			+ "hy//QTt/isdu7C5pGaJDkZFMrfxMibr6c3xXr7wwR75sTzPNmS8mquEdLsmG"
+			+ "h8gTUnB8/K6V11JtUExMqTimTbUw+j8PggpeBelG36breWJIz1O+dmCTGuLM"
+			+ "x/sK/i8eiUeRvWjqYpq5DYt4URWg2WlcpcKiUxQp07/NMx0svDC+mlQGwMnJ"
+			+ "8KOJMW1qr3TGEJ/VVKKVn6sXn/RxA+VPofYzhwZByRX87XmNdPeQKC2DHQsW"
+			+ "6v83dua5gcnv0cv/smXt7Yr/c12i0fbIaQvj3qjtUCDucjARoBey3eCyG5H6"
+			+ "5VHSsFnPZ2HCTum+jRSw/ENsu/77XU4BIM2fjAfswp7iIr2Xi4OZWKIj6o6q"
+			+ "+fNgnOJjemDYHAFK+hWxClrG8b+9Eaf21o4zcHkhCfBlYv4d+xcZOIDsDPwI"
+			+ "sf+4V+CfoBLALsa2K0pXlPplGom/a8h7CjlyaICbWpEDItqwu7NQwdMRCa7i"
+			+ "yAyM1sVjXUdcZByS1bjOFSeBe7ygAvEl78vApLxqt8Cw11XSsOtmwssecUN/"
+			+ "pb7iHE4OMyOgsYx9u7rZ2hMyl42n3c29IwDYMumiNqk9cwCBpQTJAQEv4VzO"
+			+ "QE5xYDBY9SEozni+4f7B7e2Wj/LOGb3vfNVYGNpDczBFxvr2FXTQla0lNYD/"
+			+ "aePuC++QW4KvwiGL1Zx4Jo0eoDKWYlYj0qiNlQbWfVw+raaaFnlrq+je0W6P"
+			+ "+BrKZCncho145y+CFKRLZrN5yl/cDxwsePMVhAIMr1DzVhgBXzA3MB8wBwYF"
+			+ "Kw4DAhoEFN4Cwj9AtArnRbOIAsRhaaoZlTNJBBTIVPqCrloqLns145CWXjb0"
+			+ "g141BQ==");
+
+		private static readonly char[] storagePassword = "pass".ToCharArray();
+
+		private static readonly byte[] pkcs12nopass = Base64.Decode(
+			"MIIMvgIBAzCCDIQGCSqGSIb3DQEHAaCCDHUEggxxMIIMbTCCCS8GCSqGSIb3"
+			+ "DQEHBqCCCSAwggkcAgEAMIIJFQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYw"
+			+ "DgQIfnlhuZRR6/YCAggAgIII6DYgeRwq5n9kzvohZ3JuK+fB+9jZ7Or6EGBA"
+			+ "GDxtBfHmSNUBWJEV/I8wV1zrKKoW/CaoZfA61pyrVZRd/roaqBx/koTFoh/g"
+			+ "woyyWTRV9gYTXSVqPQgCH+e2dISAa6UGO+/YOWOOwG2X3t8tS+3FduFQFLt5"
+			+ "cvUP98zENdm57Aef5pKpBSZDLIAoTASfmqwszWABRh2p/wKOHcCQ9Aj2e2vs"
+			+ "pls/ntIv81MqPuxHttwX8e+3dKWGFrJRztLpCD2aua8VkSsHFsPxEHkezX4O"
+			+ "6/VCjMCRFGophTS4dgKKtQIhZ9i/ESlr6sGKgIpyG99ALFpNEhtTKe+T3boE"
+			+ "sEkhGDquSpu4PGz2m0W5sej1DyFkKX4zIbeMDAb1y3O7aP0F+Llo9QSeGsOA"
+			+ "aCwND3NUAKBMOHzwdyNQcuCGCqY8j5rrSt99A5FMs3UVW3XU6hRCx7JlzO05"
+			+ "PNCkcPRSnKSNzBhIR5W0qj4PAZnQTfX+wbtUaDLIqsObX4Muh2l3gl+JmdpO"
+			+ "53U7ILqN8PAPly1eT+fIrUmlMmFhvo6LbTB7B2K728wsA/5wROlud/mOQz4s"
+			+ "quS288YsnVc9ExSZKodWa3Pqcdb/cgKNJYDxrR6/eBHOj+0RLK/1yTK9ghj7"
+			+ "IPYHoEqQbw768WK92RjM+RFGlXASkQhR9y4weWj/388uAWMIbQ+R2Zi4nb31"
+			+ "knjqRPFThysG1bsRL04/9PgysaasfS9KYOeAlLqp+Ar4gJrof5fytBuY+6wm"
+			+ "/J8eEdNw7VPV1cz/4rhrd2sfJQwDEN/iZoy8rTwe7wozpwZI0lwH11BBbav+"
+			+ "1AMfI79jjxhqOeo7uxE2NzUmSd05JYI7a94tcRzGQyGEKpGxYCRamzFW23qb"
+			+ "vG5Hcqi7Tdd7eTxw4c60l/vQLSo38g6ST5yZrK3URLiAtpioPyjrq2jnVfie"
+			+ "QLsiAHhpHF01+t+OcKv3UjwdEyBmQ34h9klwiG7iwBFXZaPXFCF2Np1TqFVG"
+			+ "jjBzmB+hRddEiYwN+XGCKB2Cvgc5ZMQ8LG9jQmEKLmOjuumz1ciAVY2qtl1s"
+			+ "HYSvfNsIAV/gGzHshOVF19JmGtcQt3pMtupoRh+sh8jY2/x5eIKrj2Jx6HPd"
+			+ "p/6IPUr54j0xSd6j7gWuXMj/eKp/utMNuBzAhkydnhXYedvTDYIj7SyPPIHa"
+			+ "qtam8rxTDWn2AOxp7OXTgPmo1GU2zW1OLL1D3MFlS+oaRMfhgNrhW+QP5ay6"
+			+ "ge4QLijpnSM+p0CbFAOClwzgdJV56bBVV09sDqSBXnG9MeEv5nDaH3I+GpPA"
+			+ "UgDkaI4zT61kaGgk0uNMf3czy2ycoQzTx0iHDTXSdSqvUC1yFza8UG4AYaKz"
+			+ "14gtSL7StvZtK0Y8oI084BINI1LgrWyrOLj7vkds4WrKhXm21BtM1GbN/pFh"
+			+ "XI41h+XoD8KnEPqJ36rAgBo1uHqTNJCC7YikDE/dEvq6MkOx+Nug1YZRHEyi"
+			+ "3AHry5u1HJHtxT34HXBwRXvnstuFhvU6cjc1WY1dJhu1p82TGnx7OBo/QbcM"
+			+ "8MRrWmWuU5eW4jWbriGNGYfvZy+tHnGwy0bIeqrsHOG6/JwvfmYYXe64sryH"
+			+ "5Qo96SZtcTJZaNFwuBY+bFUuOWm8YrT1L7Gl2Muf3pEVtNHLeYARBo1jEAym"
+			+ "Cb4jw0oodZqbPKdyyzUZu69fdTJiQkMUcKDfHJEGK0Li9SvtdqJLiiJs57Tb"
+			+ "YfOvn+TIuC40ssJFtmtlGCVH/0vtKLWYeW1NYAMzgI/nlhQ7W6Aroh8sZnqv"
+			+ "SwxeQmRJaVLxiV6YveTKuVlCbqNVLeEtKYAujgnJtPemGCPbwZpwlBw6V+Dz"
+			+ "oXveOBcUqATztWJeNv7RbU0Mk7k057+DNxXBIU+eHRGquyHQSBXxBbA+OFuu"
+			+ "4SPfEAyoYed0HEaoKN9lIsBW1xTROI30MZvaJXvPdLsa8izXGPLnTGmoI+fv"
+			+ "tJ644HtBCCCr3Reu82ZsTSDMxspZ9aa4ro9Oza+R5eULXDhVXedbhJBYiPPo"
+			+ "J37El5lRqOgu2SEilhhVQq3ZCugsinCaY9P/RtWG4CFnH1IcIT5+/mivB48I"
+			+ "2XfH6Xq6ziJdj2/r86mhEnz9sKunNvYPBDGlOvI7xucEf9AiEQoTR1xyFDbW"
+			+ "ljL4BsJqgsHN02LyUzLwqMstwv+/JH1wUuXSK40Kik/N7+jEFW2C+/N8tN7l"
+			+ "RPKSLaTjxVuTfdv/BH1dkV4iGFgpQrdWkWgkb+VZP9xE2mLz715eIAg13x6+"
+			+ "n97tc9Hh375xZJqwr3QyYTXWpsK/vx04RThv8p0qMdqKvf3jVQWwnCnoeBv2"
+			+ "L4h/uisOLY18qka/Y48ttympG+6DpmzXTwD1LycoG2SOWckCMmJhZK40+zr3"
+			+ "NVmWf6iJtbLGMxI/kzTqbTaOfXc2MroertyM1rILRSpgnJFxJfai5Enspr9b"
+			+ "SCwlP718jG2lQsnYlw8CuxoZAiaNy4MmC5Y3qNl3hlcggcHeLodyGkSyRsBg"
+			+ "cEiKSL7JNvqr0X/nUeW28zVxkmQsWlp3KmST8agf+r+sQvw52fXNLdYznGZV"
+			+ "rJrwgNOoRj0Z70MwTns3s/tCqDEsy5Sv/5dZW2uQEe7/wvmsP2WLu73Rwplg"
+			+ "1dwi/Uo9lO9dkEzmoIK5wMPCDINxL1K+0Y79q0tIAEMDgaIxmtRpEh8/TEsA"
+			+ "UwyEErkDsQqgGviH+ePmawJ/yehYHTRfYUgdUflwApJxRx65pDeSYkiYboMU"
+			+ "8WSAQY2nh/p9hLlS4zbz9dCK2tzVyRkJgqNy/c4IpiHEx2l1iipW9vENglqx"
+			+ "dYP4uqD8e3OOLjDQKizWx2t1u7GRwoEVQ3d3QzzOvsRcv7h+6vNsmYqE6phe"
+			+ "wKFZLctpSn21zkyut444ij4sSr1OG68dEXLY0t0mATfTmXXy5GJBsdK/lLfk"
+			+ "YTIPYYeDMle9aEicDqaKqkZUuYPnVchGp8UFMJ3M0n48OMDdDvpzBLTxxZeW"
+			+ "cK5v/m3OEo3jgxy9wXfZdz//J3zXXqvX8LpMy1K9X0uCBTz6ERlawviMQhg1"
+			+ "1okD5zCCAzYGCSqGSIb3DQEHAaCCAycEggMjMIIDHzCCAxsGCyqGSIb3DQEM"
+			+ "CgECoIICpjCCAqIwHAYKKoZIhvcNAQwBAzAOBAj3QoojTSbZqgICCAAEggKA"
+			+ "YOSp5XGdnG1pdm9CfvlAaUSHRCOyNLndoUTqteTZjHTEM9bGwNXAx4/R5H2Q"
+			+ "PnPm5HB/ynVSXX0uKdW6YlbqUyAdV3eqE4X3Nl+K7ZoXmgAFnMr0tveBhT1b"
+			+ "7rTi0TN4twjJzBTkKcxT8XKjvpVizUxGo+Ss5Wk8FrWLHAiC5dZvgRemtGcM"
+			+ "w5S09Pwj+qXpjUhX1pB5/63qWPrjVf+Bfmlz4bWcqogGk0i7eg+OdTeWMrW0"
+			+ "KR9nD1+/uNEyc4FdGtdIPnM+ax0E+vcco0ExQpTXe0xoX4JW7O71d550Wp89"
+			+ "hAVPNrJA5eUbSWNsuz+38gjUJ+4XaAEhcA7HZIp6ZyxtzSJUoh7oqpRktoxu"
+			+ "3cSVqVxIqAEqlNn6j0vbKfW91Od5DI5L+BIxY4xqXS7fdwipj9r6qWA8t9QU"
+			+ "C2r1A+xXpZ4jEh6inHW9qlfACBBrYf8pSDakSR6yTbaA07LExw0IXz5oiQYt"
+			+ "s7yx231CZlOH88bBmruLOIZsJjeg/lf63zI7Gg4F85QG3RqEJnY2pinLUTP7"
+			+ "R62VErFZPc2a85r2dbFH1mSQIj/rT1IKe32zIW8xoHC4VwrPkT3bcLFAu2TH"
+			+ "5k5zSI/gZUKjPDxb2dwLM4pvsj3gJ9vcFZp6BCuLkZc5rd7CyD8HK9PrBLKd"
+			+ "H3Yngy4A08W4U3XUtIux95WE+5O/UEmSF7fr2vT//DwZArGUpBPq4Bikb8cv"
+			+ "0wpOwUv8r0DXveeaPsxdipXlt29Ayywcs6KIidLtCaCX6/0u/XtMsGNFS+ah"
+			+ "OlumTGBFpbLnagvIf0GKNhbg2lTjflACnxIj8d+QWsnrIU1uC1JRRKCnhpi2"
+			+ "veeWd1m8GUb3aTFiMCMGCSqGSIb3DQEJFTEWBBS9g+Xmq/8B462FWFfaLWd/"
+			+ "rlFxOTA7BgkqhkiG9w0BCRQxLh4sAEMAZQByAHQAeQBmAGkAawBhAHQAIAB1"
+			+ "AHoAeQB0AGsAbwB3AG4AaQBrAGEwMTAhMAkGBSsOAwIaBQAEFKJpUOIj0OtI"
+			+ "j2CPp38YIFBEqvjsBAi8G+yhJe3A/wICCAA=");
+
+		/**
+		* we generate a self signed certificate for the sake of testing - RSA
+		*/
+		public X509CertificateEntry CreateCert(
+			AsymmetricKeyParameter	pubKey,
+			AsymmetricKeyParameter	privKey,
+			string					issuerEmail,
+			string					subjectEmail)
+		{
+			//
+			// distinguished name table.
+			//
+            IDictionary issuerAttrs = new Hashtable();
+			issuerAttrs.Add(X509Name.C, "AU");
+			issuerAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+			issuerAttrs.Add(X509Name.L, "Melbourne");
+			issuerAttrs.Add(X509Name.ST, "Victoria");
+			issuerAttrs.Add(X509Name.EmailAddress, issuerEmail);
+
+			IDictionary subjectAttrs = new Hashtable();
+			subjectAttrs.Add(X509Name.C, "AU");
+			subjectAttrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+			subjectAttrs.Add(X509Name.L, "Melbourne");
+			subjectAttrs.Add(X509Name.ST, "Victoria");
+			subjectAttrs.Add(X509Name.EmailAddress, subjectEmail);
+
+			IList order = new ArrayList();
+			order.Add(X509Name.C);
+			order.Add(X509Name.O);
+			order.Add(X509Name.L);
+			order.Add(X509Name.ST);
+			order.Add(X509Name.EmailAddress);
+
+			//
+			// extensions
+			//
+
+			//
+			// create the certificate - version 3
+			//
+			X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+			certGen.SetIssuerDN(new X509Name(order, issuerAttrs));
+			certGen.SetNotBefore(DateTime.UtcNow.AddDays(-30));
+			certGen.SetNotAfter(DateTime.UtcNow.AddDays(30));
+			certGen.SetSubjectDN(new X509Name(order, subjectAttrs));
+			certGen.SetPublicKey(pubKey);
+			certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+
+			return new X509CertificateEntry(certGen.Generate(privKey));
+		}
+
+		public void doTestPkcs12Store()
+		{
+			BigInteger mod = new BigInteger("bb1be8074e4787a8d77967f1575ef72dd7582f9b3347724413c021beafad8f32dba5168e280cbf284df722283dad2fd4abc750e3d6487c2942064e2d8d80641aa5866d1f6f1f83eec26b9b46fecb3b1c9856a303148a5cc899c642fb16f3d9d72f52526c751dc81622c420c82e2cfda70fe8d13f16cc7d6a613a5b2a2b5894d1", 16);
+
+			MemoryStream stream = new MemoryStream(pkcs12, false);
+			Pkcs12Store store = new Pkcs12StoreBuilder().Build();
+			store.Load(stream, passwd);
+
+			string pName = null;
+			foreach (string n in store.Aliases)
+			{
+				if (store.IsKeyEntry(n))
+				{
+					pName = n;
+					//break;
+				}
+			}
+
+			AsymmetricKeyEntry key = store.GetKey(pName);
+
+			if (!((RsaKeyParameters) key.Key).Modulus.Equals(mod))
+			{
+				Fail("Modulus doesn't match.");
+			}
+
+			X509CertificateEntry[] ch = store.GetCertificateChain(pName);
+
+			if (ch.Length != 3)
+			{
+				Fail("chain was wrong length");
+			}
+
+			if (!ch[0].Certificate.SerialNumber.Equals(new BigInteger("96153094170511488342715101755496684211")))
+			{
+				Fail("chain[0] wrong certificate.");
+			}
+
+			if (!ch[1].Certificate.SerialNumber.Equals(new BigInteger("279751514312356623147411505294772931957")))
+			{
+				Fail("chain[1] wrong certificate.");
+			}
+
+			if (!ch[2].Certificate.SerialNumber.Equals(new BigInteger("11341398017")))
+			{
+				Fail("chain[2] wrong certificate.");
+			}
+
+			//
+			// save test
+			//
+			MemoryStream bOut = new MemoryStream();
+			store.Save(bOut, passwd, new SecureRandom());
+
+			stream = new MemoryStream(bOut.ToArray(), false);
+			store.Load(stream, passwd);
+
+			key = store.GetKey(pName);
+
+			if (!((RsaKeyParameters)key.Key).Modulus.Equals(mod))
+			{
+				Fail("Modulus doesn't match.");
+			}
+
+			store.DeleteEntry(pName);
+
+			if (store.GetKey(pName) != null)
+			{
+				Fail("Failed deletion test.");
+			}
+
+			//
+			// cert chain test
+			//
+			store.SetCertificateEntry("testCert", ch[2]);
+
+			if (store.GetCertificateChain("testCert") != null)
+			{
+				Fail("Failed null chain test.");
+			}
+
+			//
+			// UTF 8 single cert test
+			//
+			stream = new MemoryStream(certUTF, false);
+			store.Load(stream, "user".ToCharArray());
+
+			if (store.GetCertificate("37") == null)
+			{
+				Fail("Failed to find UTF cert.");
+			}
+
+			//
+			// try for a self generated certificate
+			//
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+			RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16),
+				new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+				new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+				new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+				new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+				new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+				new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+			X509CertificateEntry[] chain = new X509CertificateEntry[] {
+				CreateCert(pubKey, privKey, "issuer at bouncycastle.org", "subject at bouncycastle.org")
+			};
+
+			store = new Pkcs12StoreBuilder().Build();
+
+			store.SetKeyEntry("privateKey", new AsymmetricKeyEntry(privKey), chain);
+
+			if (!store.ContainsAlias("privateKey") || !store.ContainsAlias("PRIVATEKEY"))
+			{
+				Fail("couldn't find alias privateKey");
+			}
+
+			if (store.IsCertificateEntry("privateKey"))
+			{
+				Fail("key identified as certificate entry");
+			}
+
+			if (!store.IsKeyEntry("privateKey") || !store.IsKeyEntry("PRIVATEKEY"))
+			{
+				Fail("key not identified as key entry");
+			}
+
+			if (!"privateKey".Equals(store.GetCertificateAlias(chain[0].Certificate)))
+			{
+				Fail("Did not return alias for key certificate privateKey");
+			}
+
+			MemoryStream store1Stream = new MemoryStream();
+			store.Save(store1Stream, passwd, new SecureRandom());
+			testNoExtraLocalKeyID(store1Stream.ToArray());
+
+			//
+			// no friendly name test
+			//
+			stream = new MemoryStream(pkcs12noFriendly, false);
+			store.Load(stream, noFriendlyPassword);
+
+			pName = null;
+
+			foreach (string n in store.Aliases)
+			{
+				if (store.IsKeyEntry(n))
+				{
+					pName = n;
+					//break;
+				}
+			}
+
+			ch = store.GetCertificateChain(pName);
+
+			//for (int i = 0; i != ch.Length; i++)
+			//{
+			//	Console.WriteLine(ch[i]);
+			//}
+
+			if (ch.Length != 1)
+			{
+				Fail("no cert found in pkcs12noFriendly");
+			}
+
+			//
+			// failure tests
+			//
+			ch = store.GetCertificateChain("dummy");
+
+			store.GetCertificateChain("DUMMY");
+
+			store.GetCertificate("dummy");
+
+			store.GetCertificate("DUMMY");
+
+			//
+			// storage test
+			//
+			stream = new MemoryStream(pkcs12StorageIssue, false);
+			store.Load(stream, storagePassword);
+
+			pName = null;
+
+			foreach (string n in store.Aliases)
+			{
+				if (store.IsKeyEntry(n))
+				{
+					pName = n;
+					//break;
+				}
+			}
+
+			ch = store.GetCertificateChain(pName);
+			if (ch.Length != 2)
+			{
+				Fail("Certificate chain wrong length");
+			}
+
+			store.Save(new MemoryStream(), storagePassword, new SecureRandom());
+
+			//
+			// basic certificate check
+			//
+			store.SetCertificateEntry("cert", ch[1]);
+
+			if (!store.ContainsAlias("cert") || !store.ContainsAlias("CERT"))
+			{
+				Fail("couldn't find alias cert");
+			}
+
+			if (!store.IsCertificateEntry("cert") || !store.IsCertificateEntry("CERT"))
+			{
+				Fail("cert not identified as certificate entry");
+			}
+
+			if (store.IsKeyEntry("cert") || store.IsKeyEntry("CERT"))
+			{
+				Fail("cert identified as key entry");
+			}
+
+			if (!store.IsEntryOfType("cert", typeof(X509CertificateEntry)))
+			{
+				Fail("cert not identified as X509CertificateEntry");
+			}
+
+			if (!store.IsEntryOfType("CERT", typeof(X509CertificateEntry)))
+			{
+				Fail("CERT not identified as X509CertificateEntry");
+			}
+
+			if (store.IsEntryOfType("cert", typeof(AsymmetricKeyEntry)))
+			{
+				Fail("cert identified as key entry via AsymmetricKeyEntry");
+			}
+
+			if (!"cert".Equals(store.GetCertificateAlias(ch[1].Certificate)))
+			{
+				Fail("Did not return alias for certificate entry");
+			}
+
+			//
+			// test restoring of a certificate with private key originally as a ca certificate
+			//
+			store = new Pkcs12StoreBuilder().Build();
+
+			store.SetCertificateEntry("cert", ch[0]);
+
+			if (!store.ContainsAlias("cert") || !store.ContainsAlias("CERT"))
+			{
+				Fail("restore: couldn't find alias cert");
+			}
+
+			if (!store.IsCertificateEntry("cert") || !store.IsCertificateEntry("CERT"))
+			{
+				Fail("restore: cert not identified as certificate entry");
+			}
+
+			if (store.IsKeyEntry("cert") || store.IsKeyEntry("CERT"))
+			{
+				Fail("restore: cert identified as key entry");
+			}
+
+			if (store.IsEntryOfType("cert", typeof(AsymmetricKeyEntry)))
+			{
+				Fail("restore: cert identified as key entry via AsymmetricKeyEntry");
+			}
+
+			if (store.IsEntryOfType("CERT", typeof(AsymmetricKeyEntry)))
+			{
+				Fail("restore: cert identified as key entry via AsymmetricKeyEntry");
+			}
+
+			if (!store.IsEntryOfType("cert", typeof(X509CertificateEntry)))
+			{
+				Fail("restore: cert not identified as X509CertificateEntry");
+			}
+
+			//
+			// test of reading incorrect zero-length encoding
+			//
+			stream = new MemoryStream(pkcs12nopass, false);
+			store.Load(stream, "".ToCharArray());
+		}
+
+		private void testSupportedTypes(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain)
+		{
+			basicStoreTest(privKey, chain,
+				PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc,
+				PkcsObjectIdentifiers.PbewithShaAnd40BitRC2Cbc );
+			basicStoreTest(privKey, chain,
+				PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc,
+				PkcsObjectIdentifiers.PbeWithShaAnd3KeyTripleDesCbc );
+		}
+
+		private void basicStoreTest(AsymmetricKeyEntry privKey, X509CertificateEntry[] chain,
+			DerObjectIdentifier keyAlgorithm, DerObjectIdentifier certAlgorithm)
+		{
+			Pkcs12Store store = new Pkcs12StoreBuilder()
+				.SetKeyAlgorithm(keyAlgorithm)
+				.SetCertAlgorithm(certAlgorithm)
+				.Build();
+
+			store.SetKeyEntry("key", privKey, chain);
+
+			MemoryStream bOut = new MemoryStream();
+
+			store.Save(bOut, passwd, new SecureRandom());
+
+			store.Load(new MemoryStream(bOut.ToArray(), false), passwd);
+
+			AsymmetricKeyEntry k = store.GetKey("key");
+
+			if (!k.Equals(privKey))
+			{
+				Fail("private key didn't match");
+			}
+
+			X509CertificateEntry[] c = store.GetCertificateChain("key");
+
+			if (c.Length != chain.Length || !c[0].Equals(chain[0]))
+			{
+				Fail("certificates didn't match");
+			}
+
+			// check attributes
+			Pkcs12Entry b1 = k;
+			Pkcs12Entry b2 = chain[0];
+
+			if (b1[PkcsObjectIdentifiers.Pkcs9AtFriendlyName] != null)
+			{
+				DerBmpString name = (DerBmpString)b1[PkcsObjectIdentifiers.Pkcs9AtFriendlyName];
+
+				if (!name.Equals(new DerBmpString("key")))
+				{
+					Fail("friendly name wrong");
+				}
+			}
+			else
+			{
+				Fail("no friendly name found on key");
+			}
+
+			if (b1[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] != null)
+			{
+				Asn1OctetString id = (Asn1OctetString)b1[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID];
+
+				if (!id.Equals(b2[PkcsObjectIdentifiers.Pkcs9AtLocalKeyID]))
+				{
+					Fail("local key id mismatch");
+				}
+			}
+			else
+			{
+				Fail("no local key id found");
+			}
+
+			//
+			// check algorithm types.
+			//
+			Asn1InputStream aIn = new Asn1InputStream(bOut.ToArray());
+
+			Pfx pfx = new Pfx((Asn1Sequence)aIn.ReadObject());
+
+			ContentInfo cInfo = pfx.AuthSafe;
+
+			Asn1OctetString auth = (Asn1OctetString)cInfo.Content;
+
+			aIn = new Asn1InputStream(auth.GetOctets());
+			Asn1Sequence s1 = (Asn1Sequence)aIn.ReadObject();
+
+			ContentInfo c1 = ContentInfo.GetInstance(s1[0]);
+			ContentInfo c2 = ContentInfo.GetInstance(s1[1]);
+
+			aIn = new Asn1InputStream(((Asn1OctetString)c1.Content).GetOctets());
+
+			SafeBag sb = new SafeBag((Asn1Sequence)(((Asn1Sequence)aIn.ReadObject())[0]));
+
+			EncryptedPrivateKeyInfo encInfo = EncryptedPrivateKeyInfo.GetInstance(sb.BagValue);
+
+			// check the key encryption
+			if (!encInfo.EncryptionAlgorithm.ObjectID.Equals(keyAlgorithm))
+			{
+				Fail("key encryption algorithm wrong");
+			}
+
+			// check the certificate encryption
+			EncryptedData cb = EncryptedData.GetInstance(c2.Content);
+
+			if (!cb.EncryptionAlgorithm.ObjectID.Equals(certAlgorithm))
+			{
+				Fail("cert encryption algorithm wrong");
+			}
+		}
+
+		private void testNoExtraLocalKeyID(byte[] store1data)
+		{
+			IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			kpg.Init(new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), new SecureRandom(), 512, 25));
+
+			AsymmetricCipherKeyPair newPair =  kpg.GenerateKeyPair();
+
+			Pkcs12Store store1 = new Pkcs12StoreBuilder().Build();
+			store1.Load(new MemoryStream(store1data, false), passwd);
+
+			Pkcs12Store store2 = new Pkcs12StoreBuilder().Build();
+
+			AsymmetricKeyEntry k1 = store1.GetKey("privatekey");
+			X509CertificateEntry[] chain1 = store1.GetCertificateChain("privatekey");
+
+			X509CertificateEntry[] chain2 = new X509CertificateEntry[chain1.Length + 1];
+
+			Array.Copy(chain1, 0, chain2, 1, chain1.Length);
+
+			chain2[0] = CreateCert(newPair.Public, k1.Key, "subject at bouncycastle.org", "extra at bouncycaste.org");
+
+			if (chain1[0][PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] == null)
+			{
+				Fail("localKeyID not found initially");
+			}
+
+			store2.SetKeyEntry("new", new AsymmetricKeyEntry(newPair.Private), chain2);
+
+			MemoryStream bOut = new MemoryStream();
+
+			store2.Save(bOut, passwd, new SecureRandom());
+
+			store2.Load(new MemoryStream(bOut.ToArray(), false), passwd);
+
+			chain2 = store2.GetCertificateChain("new");
+
+			if (chain2[1][PkcsObjectIdentifiers.Pkcs9AtLocalKeyID] != null)
+			{
+				Fail("localKeyID found after save");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "PKCS12Store"; }
+		}
+
+		public override void PerformTest()
+		{
+			doTestPkcs12Store();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Pkcs12StoreTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/SecureRandomTest.cs b/BouncyCastle.AxCrypt/test/src/security/test/SecureRandomTest.cs
new file mode 100644
index 0000000..0a7ac88
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/SecureRandomTest.cs
@@ -0,0 +1,150 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto.Prng;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+	[TestFixture]
+	public class SecureRandomTest
+	{
+#if !NETCF_1_0 && !PCL
+		[Test]
+		public void TestCryptoApi()
+		{
+			SecureRandom random = new SecureRandom(
+				new CryptoApiRandomGenerator());
+
+			checkSecureRandom(random);
+		}
+#endif
+
+		[Test]
+		public void TestDefault()
+		{
+			SecureRandom random = new SecureRandom();
+
+			checkSecureRandom(random);
+		}
+
+		[Test]
+		public void TestSha1Prng()
+		{
+			SecureRandom random = SecureRandom.GetInstance("SHA1PRNG");
+			random.SetSeed(SecureRandom.GetSeed(20));
+
+			checkSecureRandom(random);
+		}
+
+		[Test]
+		public void TestSha256Prng()
+		{
+			SecureRandom random = SecureRandom.GetInstance("SHA256PRNG");
+			random.SetSeed(SecureRandom.GetSeed(32));
+
+			checkSecureRandom(random);
+		}
+
+		[Test]
+		public void TestThreadedSeed()
+		{
+			SecureRandom random = new SecureRandom(
+				new ThreadedSeedGenerator().GenerateSeed(20, false));
+
+			checkSecureRandom(random);
+		}
+
+		[Test]
+		public void TestVmpcPrng()
+		{
+			SecureRandom random = new SecureRandom(new VmpcRandomGenerator());
+			random.SetSeed(SecureRandom.GetSeed(32));
+
+			checkSecureRandom(random);
+		}
+
+
+		private static void checkSecureRandom(
+			SecureRandom random)
+		{
+			// Note: This will periodically (< 1e-6 probability) give a false alarm.
+			// That's randomness for you!
+			Assert.IsTrue(runChiSquaredTests(random), "Chi2 test detected possible non-randomness");
+		}
+
+		private static bool runChiSquaredTests(
+			SecureRandom random)
+		{
+			int passes = 0;
+
+			for (int tries = 0; tries < 100; ++tries)
+			{
+				double chi2 = measureChiSquared(random, 1000);
+				if (chi2 < 285.0) // 255 degrees of freedom in test => Q ~ 10.0% for 285
+					++passes;
+			}
+
+			return passes > 75;
+		}
+
+		private static double measureChiSquared(
+			SecureRandom	random,
+			int				rounds)
+		{
+			int[] counts = new int[256];
+
+			byte[] bs = new byte[256];
+			for (int i = 0; i < rounds; ++i)
+			{
+				random.NextBytes(bs);
+
+				for (int b = 0; b < 256; ++b)
+				{
+					++counts[bs[b]];
+				}
+			}
+
+			byte mask = SecureRandom.GetSeed(1)[0];
+			for (int i = 0; i < rounds; ++i)
+			{
+				random.NextBytes(bs);
+
+				for (int b = 0; b < 256; ++b)
+				{
+					++counts[bs[b] ^ mask];
+				}
+
+				++mask;
+			}
+
+			byte shift = SecureRandom.GetSeed(1)[0];
+			for (int i = 0; i < rounds; ++i)
+			{
+				random.NextBytes(bs);
+
+				for (int b = 0; b < 256; ++b)
+				{
+					++counts[(byte)(bs[b] + shift)];
+				}
+
+				++shift;
+			}
+
+			int total = 3 * rounds;
+
+			double chi2 = 0;
+			for (int k = 0; k < counts.Length; ++k)
+			{
+				double diff = ((double) counts[k]) - total;
+				double diff2 = diff * diff;
+
+				chi2 += diff2;
+			}
+
+			chi2 /= total;
+
+			return chi2;
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/TestDigestUtil.cs b/BouncyCastle.AxCrypt/test/src/security/test/TestDigestUtil.cs
new file mode 100644
index 0000000..0f169f9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/TestDigestUtil.cs
@@ -0,0 +1,63 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+    [TestFixture]
+    public class TestDigestUtilities
+    {
+		private static readonly byte[] TestBytes = new byte[100];
+
+		static TestDigestUtilities()
+		{
+			new SecureRandom().NextBytes(TestBytes);
+		}
+
+		[Test]
+        public void TestAlgorithms()
+        {
+			CheckAlgorithm("GOST3411", new Gost3411Digest());
+			CheckAlgorithm("MD2", new MD2Digest());
+            CheckAlgorithm("MD4", new MD4Digest());
+            CheckAlgorithm("MD5", new MD5Digest());
+			CheckAlgorithm("RipeMD128", new RipeMD128Digest());
+			CheckAlgorithm("RipeMD160", new RipeMD160Digest());
+			CheckAlgorithm("RipeMD256", new RipeMD256Digest());
+			CheckAlgorithm("RipeMD320", new RipeMD320Digest());
+			CheckAlgorithm("SHA-1", new Sha1Digest());
+            CheckAlgorithm("SHA-224", new Sha224Digest());
+            CheckAlgorithm("SHA-256", new Sha256Digest());
+            CheckAlgorithm("SHA-384", new Sha384Digest());
+            CheckAlgorithm("SHA-512", new Sha512Digest());
+			CheckAlgorithm("Tiger", new TigerDigest());
+			CheckAlgorithm("Whirlpool", new WhirlpoolDigest());
+		}
+
+		private void CheckAlgorithm(
+            string	name,
+            IDigest	digest)
+        {
+            byte[] hash1 = MakeTestHash(digest);
+			byte[] hash2 = MakeTestHash(DigestUtilities.GetDigest(name));
+
+			Assert.AreEqual(hash1, hash2, name);
+        }
+
+		private byte[] MakeTestHash(
+			IDigest digest)
+		{
+			for (int i = 0; i < digest.GetDigestSize(); ++i)
+			{
+				digest.Update((byte) i);
+			}
+
+			digest.BlockUpdate(TestBytes, 0, TestBytes.Length);
+
+			return DigestUtilities.DoFinal(digest);
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/TestDotNetUtil.cs b/BouncyCastle.AxCrypt/test/src/security/test/TestDotNetUtil.cs
new file mode 100644
index 0000000..f880b38
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/TestDotNetUtil.cs
@@ -0,0 +1,88 @@
+#if !(NETCF_1_0 || SILVERLIGHT)
+
+using System;
+using System.Security.Cryptography;
+using SystemX509 = System.Security.Cryptography.X509Certificates;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+	[TestFixture]
+	public class TestDotNetUtilities
+	{
+		[Test]
+		public void TestRsaInterop()
+		{
+			for (int i = 0; i < 100; ++i)
+			{
+				RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(512);
+				RSAParameters rp = rsa.ExportParameters(true);
+				AsymmetricCipherKeyPair kp = DotNetUtilities.GetRsaKeyPair(rp);
+
+				DotNetUtilities.ToRSA((RsaKeyParameters)kp.Public);
+				// TODO This method appears to not work for private keys (when no CRT info)
+				//DotNetUtilities.ToRSA((RsaKeyParameters)kp.Private);
+				DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)kp.Private);
+			}
+		}
+
+		[Test]
+		public void TestX509CertificateConversion()
+		{
+			BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM="));
+			BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs="));
+			BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx"));
+			BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw=="));
+			BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A="));
+
+			DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG);
+			DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para);
+			DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para);
+
+			IDictionary attrs = new Hashtable();
+			attrs[X509Name.C] = "AU";
+			attrs[X509Name.O] = "The Legion of the Bouncy Castle";
+			attrs[X509Name.L] = "Melbourne";
+			attrs[X509Name.ST] = "Victoria";
+			attrs[X509Name.E] = "feedback-crypto at bouncycastle.org";
+
+			IList ord = new ArrayList(attrs.Keys);
+
+			X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+
+			certGen.SetIssuerDN(new X509Name(ord, attrs));
+			certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));
+			certGen.SetNotAfter(DateTime.UtcNow.AddDays(1));
+			certGen.SetSubjectDN(new X509Name(ord, attrs));
+			certGen.SetPublicKey(dsaPub);
+			certGen.SetSignatureAlgorithm("SHA1WITHDSA");
+
+			X509Certificate cert = certGen.Generate(dsaPriv);
+
+			cert.CheckValidity();
+			cert.Verify(dsaPub);
+
+			SystemX509.X509Certificate dotNetCert = DotNetUtilities.ToX509Certificate(cert);
+
+			X509Certificate certCopy = DotNetUtilities.FromX509Certificate(dotNetCert);
+
+			Assert.AreEqual(cert, certCopy);
+
+			certCopy.CheckValidity();
+			certCopy.Verify(dsaPub);
+		}
+	}
+}
+
+#endif
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/TestEncodings.cs b/BouncyCastle.AxCrypt/test/src/security/test/TestEncodings.cs
new file mode 100644
index 0000000..557d2dc
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/TestEncodings.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+    [TestFixture]
+    public class TestEncodings
+    {
+		[Test]
+		public void TestEC()
+		{
+			BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv"));
+			BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R"));
+			BigInteger ECParraH = new BigInteger(Base64.Decode("AQ=="));
+			BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L"));
+			BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l"));
+			BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx"));
+			BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo"));
+
+			FpCurve curve = new FpCurve(
+				new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+			ECDomainParameters ecDomain =
+				new ECDomainParameters(
+					curve,
+					new FpPoint(curve,
+						curve.FromBigInteger(ECParraGX),
+						curve.FromBigInteger(ECParraGY)),
+				ECParraN);
+
+			ECPublicKeyParameters ecPub = new ECPublicKeyParameters(
+				new FpPoint(
+					curve,
+					curve.FromBigInteger(ECPubQX),
+					curve.FromBigInteger(ECPubQY)),
+				ecDomain);
+
+			ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters(ECPrivD, ecDomain);
+
+			SubjectPublicKeyInfo subinfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(ecPub);
+			PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(ecPriv);
+
+			ECPublicKeyParameters tecPub = (ECPublicKeyParameters)PublicKeyFactory.CreateKey(subinfo);
+			ECPrivateKeyParameters tecPriv = (ECPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo);
+
+			Assert.IsTrue(tecPub.Equals(ecPub), "EC: public key to info back to public key");
+			Assert.IsTrue(tecPriv.Equals(ecPriv), "EC: private key to info back to private key");
+		}
+
+        [Test]
+        public void TestDH()
+        {
+            BigInteger DHParraP = new BigInteger(Base64.Decode("ALJCm1CUL6mOnyVqWTSV6Z2+DVSGOvgboOhmbyyxCrym59uVnXMmPjIgQTrmniFg7PvdcN7NNFwFmcZleULso1s="));
+            BigInteger DHParraQ = new BigInteger(Base64.Decode("WSFNqEoX1MdPkrUsmkr0zt8GqkMdfA3QdDM3lliFXlNz7crOuZMfGRAgnXNPELB2fe64b2aaLgLM4zK8oXZRrQ=="));
+            BigInteger DHPubY = new BigInteger(Base64.Decode("AIki+8/zggCS2e488AsTNULI4LujdUeQQsZI949Dc9lKXZRmrPIC1h8NRoneHQEhpAe4Rhe0nhUOGZJekT5++SA="));
+            BigInteger DHPrivX = new BigInteger(Base64.Decode("Apo67noMRO5eDWo/TtpRiBmKGw7ywh25shIu0Rs03krQmWKRbDPvdygWdJ5IpW6ZbKlCTAMhSxpz03YSeSEDmw=="));
+
+
+            DHParameters dhPara = new DHParameters(DHParraP, DHParraQ);
+            DHPublicKeyParameters dhPublic = new DHPublicKeyParameters(DHPubY, dhPara);
+            DHPrivateKeyParameters dhPrivate = new DHPrivateKeyParameters(DHPrivX, dhPara);
+
+            SubjectPublicKeyInfo pubInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(dhPublic);
+            PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dhPrivate);
+
+            DHPublicKeyParameters testPubKey = (DHPublicKeyParameters) PublicKeyFactory.CreateKey(pubInfo);
+            DHPrivateKeyParameters testPrivKey = (DHPrivateKeyParameters) PrivateKeyFactory.CreateKey(privInfo);
+
+            Assert.IsFalse(!testPrivKey.Equals(dhPrivate), "DH: Private key to info back to key");
+            Assert.IsFalse(!testPubKey.Equals(dhPublic), "DH: Public key to info back to key");
+
+            Assert.IsTrue(true, "Diffe Helman Test worked.");
+
+        }
+
+        [Test]
+        public void TestElGamal()
+        {
+
+                BigInteger ELGamalParaG = new BigInteger(Base64.Decode("QAZPRcsH8kHVKS5065R1Xy6QtsPvDkmDZtPuq18EJkvLrCIZivE/m5puQp3/VKJrG7dKgz4NBGpONp3HT+Cn/g=="));
+                BigInteger ELGamalParaP = new BigInteger(Base64.Decode("AKXmAwgkudDLI/Yxk6wk3APn+mSjX5QSyDwpchmegSIi1ZNC0Jb+IbxjroKNhRTBKjtv4/JTXtJS6IqaZv9uKes="));
+                BigInteger ELGamalPubY = new BigInteger(Base64.Decode("AJ/gXuZuCA2X044otNkzs8FI36XuFu1L/YHg5cEmDvICTigycRN2E1DnhP+CTqxEqgEqX8rBe5tuGDlkTLwgNqM="));
+                BigInteger ELGamalPriv = new BigInteger(Base64.Decode("CqVr+K0TpuJKQnc76MjKhxrJzGr93jnuE3mTpth486Meymt8uWEVAQj1tGc9DTt14F9aV9WIT2oYYbvLJRcwow=="));
+
+
+
+                ElGamalParameters elPara = new ElGamalParameters(ELGamalParaP, ELGamalParaG);
+
+                ElGamalPrivateKeyParameters elPriv = new ElGamalPrivateKeyParameters(ELGamalPriv, elPara);
+                ElGamalPublicKeyParameters elPub = new ElGamalPublicKeyParameters(ELGamalPubY, elPara);
+
+                SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(elPub);
+                PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(elPriv);
+
+                ElGamalPrivateKeyParameters telPriv = (ElGamalPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo);
+                ElGamalPublicKeyParameters telPub = (ElGamalPublicKeyParameters)PublicKeyFactory.CreateKey(subInfo);
+
+
+                             // Console.WriteLine(telPriv.Equals(elPriv));
+
+
+
+                Assert.IsTrue(telPriv.Equals(elPriv), "ELGamal Private key to into back to private key.");
+                Assert.IsTrue(telPub.Equals(elPub), "ELGamal Public key to into back to private key.");
+
+                Assert.IsTrue(true, "ELGamal Test worked.");
+
+            }
+
+        [Test]
+        public void TestRsa()
+        {
+
+            BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
+            BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+            BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+            BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+            BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+            BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+            BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
+			RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+			SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rsaPublic);
+            RsaKeyParameters testResult = (RsaKeyParameters)PublicKeyFactory.CreateKey(subInfo);
+
+			// check RSA public key.
+
+            Assert.IsFalse(!testResult.Equals(rsaPublic), "RSA: test failed on public key to info and back to public key.");
+
+            PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(rsaPrivate);
+            testResult = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(privInfo);
+
+            Assert.IsFalse(!testResult.Equals(rsaPrivate), "RSA: private key to info back to private key.");
+
+            Assert.IsTrue(true, "RSATest worked.");
+
+        }
+
+        [Test]
+        public void TestDSA()
+        {
+            BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM="));
+            BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs="));
+            BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx"));
+            BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw=="));
+            BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A="));
+
+            DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG);
+            DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para);
+            DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para);
+
+            SubjectPublicKeyInfo subInfo = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(dsaPub);
+            DsaKeyParameters testResult = (DsaKeyParameters)PublicKeyFactory.CreateKey(subInfo);
+
+            // check RSA public key.
+
+            Assert.IsFalse(!testResult.Equals(dsaPub), "DSA: test failed on public key to info and back to public key.");
+
+            PrivateKeyInfo privInfo = PrivateKeyInfoFactory.CreatePrivateKeyInfo(dsaPriv);
+            testResult = (DsaPrivateKeyParameters)PrivateKeyFactory.CreateKey(privInfo);
+
+            Assert.IsFalse(!testResult.Equals(dsaPriv), "DSA: private key to info back to private key.");
+
+            Assert.IsTrue(true, "DSATest worked.");
+
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/TestParameterUtil.cs b/BouncyCastle.AxCrypt/test/src/security/test/TestParameterUtil.cs
new file mode 100644
index 0000000..fe49421
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/TestParameterUtil.cs
@@ -0,0 +1,74 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+	[TestFixture]
+	public class TestParameterUtilities
+	{
+		[Test]
+		public void TestCreateKeyParameter()
+		{
+			SecureRandom random = new SecureRandom();
+
+			doTestCreateKeyParameter("AES", NistObjectIdentifiers.IdAes128Cbc,
+				128, typeof(KeyParameter), random);
+			doTestCreateKeyParameter("DES", OiwObjectIdentifiers.DesCbc,
+				64, typeof(DesParameters), random);
+			doTestCreateKeyParameter("DESEDE", PkcsObjectIdentifiers.DesEde3Cbc,
+				192, typeof(DesEdeParameters), random);
+			doTestCreateKeyParameter("RC2", PkcsObjectIdentifiers.RC2Cbc,
+				128, typeof(RC2Parameters), random);
+		}
+
+		private void doTestCreateKeyParameter(
+			string				algorithm,
+			DerObjectIdentifier	oid,
+			int					keyBits,
+			Type				expectedType,
+			SecureRandom		random)
+		{
+			int keyLength = keyBits / 8;
+			byte[] bytes = new byte[keyLength];
+			random.NextBytes(bytes);
+
+			KeyParameter key;
+
+			key = ParameterUtilities.CreateKeyParameter(algorithm, bytes);
+			checkKeyParameter(key, expectedType, bytes);
+
+			key = ParameterUtilities.CreateKeyParameter(oid, bytes);
+			checkKeyParameter(key, expectedType, bytes);
+
+			bytes = new byte[keyLength * 2];
+			random.NextBytes(bytes);
+
+			int offset = random.Next(1, keyLength);
+			byte[] expected = new byte[keyLength];
+			Array.Copy(bytes, offset, expected, 0, keyLength);
+
+			key = ParameterUtilities.CreateKeyParameter(algorithm, bytes, offset, keyLength);
+			checkKeyParameter(key, expectedType, expected);
+
+			key = ParameterUtilities.CreateKeyParameter(oid, bytes, offset, keyLength);
+			checkKeyParameter(key, expectedType, expected);
+		}
+
+		private void checkKeyParameter(
+			KeyParameter	key,
+			Type			expectedType,
+			byte[]			expectedBytes)
+		{
+			Assert.IsTrue(expectedType.IsInstanceOfType(key));
+			Assert.IsTrue(Arrays.AreEqual(expectedBytes, key.GetKey()));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/security/test/TestSignerUtil.cs b/BouncyCastle.AxCrypt/test/src/security/test/TestSignerUtil.cs
new file mode 100644
index 0000000..18b856e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/security/test/TestSignerUtil.cs
@@ -0,0 +1,181 @@
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Security.Tests
+{
+    [TestFixture]
+    public class TestSignerUtilities
+    {
+        [Test]
+        public void TestAlgorithms()
+        {
+            //
+            // RSA parameters
+            //
+            BigInteger rsaMod = new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a [...]
+            BigInteger rsaPubExp = new BigInteger("10001", 16);
+
+            BigInteger rsaPrivExp = new BigInteger("65dad56ac7df7abb434e4cb5eeadb16093aa6da7f0033aad3815289b04757d32bfee6ade7749c8e4a323b5050a2fb9e2a99e23469e1ed4ba5bab54336af20a5bfccb8b3424cc6923db2ffca5787ed87aa87aa614cd04cedaebc8f623a2d2063017910f436dff18bb06f01758610787f8b258f0a8efd8bd7de30007c47b2a1031696c7d6523bc191d4d918927a7e0b09584ed205bd2ff4fc4382678df82353f7532b3bbb81d69e3f39070aed3fb64fce032a089e8e64955afa5213a6eb241231bd98d702fba725a9b205952fda186412d9e0d9344d2998c455ad8c2ba [...]
+            BigInteger rsaPrivP = new BigInteger("d4fd9ac3474fb83aaf832470643609659e511b322632b239b688f3cd2aad87527d6cf652fb9c9ca67940e84789444f2e99b0cb0cfabbd4de95396106c865f38e2fb7b82b231260a94df0e01756bf73ce0386868d9c41645560a81af2f53c18e4f7cdf3d51d80267372e6e0216afbf67f655c9450769cca494e4f6631b239ce1b", 16);
+            BigInteger rsaPrivQ = new BigInteger("c8eaa0e2a1b3a4412a702bccda93f4d150da60d736c99c7c566fdea4dd1b401cbc0d8c063daaf0b579953d36343aa18b33dbf8b9eae94452490cc905245f8f7b9e29b1a288bc66731a29e1dd1a45c9fd7f8238ff727adc49fff73991d0dc096206b9d3a08f61e7462e2b804d78cb8c5eccdb9b7fbd2ad6a8fea46c1053e1be75", 16);
+            BigInteger rsaPrivDP = new BigInteger("10edcb544421c0f9e123624d1099feeb35c72a8b34e008ac6fa6b90210a7543f293af4e5299c8c12eb464e70092805c7256e18e5823455ba0f504d36f5ccacac1b7cd5c58ff710f9c3f92646949d88fdd1e7ea5fed1081820bb9b0d2a8cd4b093fecfdb96dabd6e28c3a6f8c186dc86cddc89afd3e403e0fcf8a9e0bcb27af0b", 16);
+            BigInteger rsaPrivDQ = new BigInteger("97fc25484b5a415eaa63c03e6efa8dafe9a1c8b004d9ee6e80548fefd6f2ce44ee5cb117e77e70285798f57d137566ce8ea4503b13e0f1b5ed5ca6942537c4aa96b2a395782a4cb5b58d0936e0b0fa63b1192954d39ced176d71ef32c6f42c84e2e19f9d4dd999c2151b032b97bd22aa73fd8c5bcd15a2dca4046d5acc997021", 16);
+            BigInteger rsaPrivQinv = new BigInteger("4bb8064e1eff7e9efc3c4578fcedb59ca4aef0993a8312dfdcb1b3decf458aa6650d3d0866f143cbf0d3825e9381181170a0a1651eefcd7def786b8eb356555d9fa07c85b5f5cbdd74382f1129b5e36b4166b6cc9157923699708648212c484958351fdc9cf14f218dbe7fbf7cbd93a209a4681fe23ceb44bab67d66f45d1c9d", 16);
+
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaMod, rsaPubExp);
+            RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(
+                rsaMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+            //
+            // ECDSA parameters
+            //
+            BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv"));
+            BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R"));
+            BigInteger ECParraH = new BigInteger(Base64.Decode("AQ=="));
+            BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L"));
+            BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l"));
+            BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx"));
+            BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo"));
+
+            FpCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters ecDomain = new ECDomainParameters(curve,
+                new FpPoint(curve,
+                    curve.FromBigInteger(ECParraGX),
+                    curve.FromBigInteger(ECParraGY)),
+                ECParraN);
+
+            ECPublicKeyParameters ecPub = new ECPublicKeyParameters(
+                new FpPoint(curve,
+                    curve.FromBigInteger(ECPubQX),
+                    curve.FromBigInteger(ECPubQY)),
+                ecDomain);
+
+            ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters(ECPrivD, ecDomain);
+
+            //
+            // DSA parameters
+            //
+            BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM="));
+            BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs="));
+            BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx"));
+            BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw=="));
+            BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A="));
+
+            DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG);
+            DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para);
+            DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para);
+
+            //
+            // ECGOST3410 parameters
+            //
+            IAsymmetricCipherKeyPairGenerator ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+            ecGostKpg.Init(
+                new ECKeyGenerationParameters(
+                    CryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+                    new SecureRandom()));
+
+            AsymmetricCipherKeyPair ecGostPair = ecGostKpg.GenerateKeyPair();
+
+            //
+            // GOST3410 parameters
+            //
+            IAsymmetricCipherKeyPairGenerator gostKpg = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+            gostKpg.Init(
+                new Gost3410KeyGenerationParameters(
+                    new SecureRandom(),
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
+
+            AsymmetricCipherKeyPair gostPair = gostKpg.GenerateKeyPair();
+
+
+
+            //
+            // signer loop
+            //
+            byte[] shortMsg = new byte[] { 1, 4, 5, 6, 8, 8, 4, 2, 1, 3 };
+            byte[] longMsg = new byte[100];
+            new SecureRandom().NextBytes(longMsg);
+
+            foreach (string algorithm in SignerUtilities.Algorithms)
+            {
+                ISigner signer = SignerUtilities.GetSigner(algorithm);
+
+                string upper = algorithm.ToUpper(CultureInfo.InvariantCulture);
+                int withPos = upper.LastIndexOf("WITH");
+
+                string cipherName = withPos < 0
+                    ?	upper
+                    :	upper.Substring(withPos + "WITH".Length);
+
+                ICipherParameters signParams = null, verifyParams = null;
+
+                if (cipherName == "RSA" || cipherName == "RSAANDMGF1")
+                {
+                    signParams = rsaPrivate;
+                    verifyParams = rsaPublic;
+                }
+                else if (cipherName == "ECDSA")
+                {
+                    signParams = ecPriv;
+                    verifyParams = ecPub;
+                }
+                else if (cipherName == "DSA")
+                {
+                    signParams = dsaPriv;
+                    verifyParams = dsaPub;
+                }
+                else if (cipherName == "ECGOST3410")
+                {
+                    signParams = ecGostPair.Private;
+                    verifyParams = ecGostPair.Public;
+                }
+                else if (cipherName == "GOST3410")
+                {
+                    signParams = gostPair.Private;
+                    verifyParams = gostPair.Public;
+                }
+                else
+                {
+                    Assert.Fail("Unknown algorithm encountered: " + cipherName);
+                }
+
+                signer.Init(true, signParams);
+                foreach (byte b in shortMsg)
+                {
+                    signer.Update(b);
+                }
+                signer.BlockUpdate(longMsg, 0, longMsg.Length);
+                byte[] sig = signer.GenerateSignature();
+
+                signer.Init(false, verifyParams);
+                foreach (byte b in shortMsg)
+                {
+                    signer.Update(b);
+                }
+                signer.BlockUpdate(longMsg, 0, longMsg.Length);
+
+                Assert.IsTrue(signer.VerifySignature(sig), cipherName + " signer " + algorithm + " failed.");
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/AESSICTest.cs b/BouncyCastle.AxCrypt/test/src/test/AESSICTest.cs
new file mode 100644
index 0000000..f8de35e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/AESSICTest.cs
@@ -0,0 +1,147 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>
+	/// Test vectors based on NIST Special Publication 800-38A,
+	/// "Recommendation for Block Cipher Modes of Operation"
+	/// </remarks>
+	[TestFixture]
+	public class AesSicTest
+		: SimpleTest
+	{
+		private static readonly byte[][] keys =
+		{
+			Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c"),
+			Hex.Decode("8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b"),
+			Hex.Decode("603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4")
+		};
+
+		private static readonly byte[][] plain =
+		{
+			Hex.Decode("6bc1bee22e409f96e93d7e117393172a"),
+			Hex.Decode("ae2d8a571e03ac9c9eb76fac45af8e51"),
+			Hex.Decode("30c81c46a35ce411e5fbc1191a0a52ef"),
+			Hex.Decode("f69f2445df4f9b17ad2b417be66c3710")
+		};
+
+		private static readonly byte[,][] cipher =
+		{
+			{
+				Hex.Decode("874d6191b620e3261bef6864990db6ce"),
+				Hex.Decode("9806f66b7970fdff8617187bb9fffdff"),
+				Hex.Decode("5ae4df3edbd5d35e5b4f09020db03eab"),
+				Hex.Decode("1e031dda2fbe03d1792170a0f3009cee")
+			},
+			{
+				Hex.Decode("1abc932417521ca24f2b0459fe7e6e0b"),
+				Hex.Decode("090339ec0aa6faefd5ccc2c6f4ce8e94"),
+				Hex.Decode("1e36b26bd1ebc670d1bd1d665620abf7"),
+				Hex.Decode("4f78a7f6d29809585a97daec58c6b050")
+			},
+			{
+				Hex.Decode("601ec313775789a5b7a7f504bbf3d228"),
+				Hex.Decode("f443e3ca4d62b59aca84e990cacaf5c5"),
+				Hex.Decode("2b0930daa23de94ce87017ba2d84988d"),
+				Hex.Decode("dfc9c58db67aada613c2dd08457941a6")
+			}
+		};
+
+		public override string Name
+		{
+			get { return "AESSIC"; }
+		}
+
+		public override void PerformTest()
+		{
+			IBufferedCipher c = CipherUtilities.GetCipher("AES/SIC/NoPadding");
+
+			//
+			// NIST vectors
+			//
+			for (int i = 0; i != keys.Length; i++)
+			{
+				KeyParameter skey = ParameterUtilities.CreateKeyParameter("AES", keys[i]);
+				c.Init(true, new ParametersWithIV(skey, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF")));
+
+				for (int j = 0; j != plain.Length; j++)
+				{
+					byte[] enc = c.ProcessBytes(plain[j]);
+					if (!AreEqual(enc, cipher[i, j]))
+					{
+						Fail("AESSIC encrypt failed: key " + i + " block " + j);
+					}
+				}
+
+				c.Init(false, new ParametersWithIV(skey, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF")));
+
+				for (int j = 0; j != plain.Length; j++)
+				{
+					byte[] enc = c.ProcessBytes(cipher[i, j]);
+					if (!AreEqual(enc, plain[j]))
+					{
+						Fail("AESSIC decrypt failed: key " + i + " block " + j);
+					}
+				}
+			}
+
+			//
+			// check CTR also recognised.
+			//
+			c = CipherUtilities.GetCipher("AES/CTR/NoPadding");
+
+			KeyParameter sk = ParameterUtilities.CreateKeyParameter("AES", Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C"));
+
+			c.Init(true, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001")));
+
+			byte[] crypt = c.DoFinal(Hex.Decode("00000000000000000000000000000000"));
+
+			if (!AreEqual(crypt, Hex.Decode("D23513162B02D0F72A43A2FE4A5F97AB")))
+			{
+				Fail("AESSIC failed test 2");
+			}
+
+			//
+			// check partial block processing
+			//
+			c = CipherUtilities.GetCipher("AES/CTR/NoPadding");
+
+			sk = ParameterUtilities.CreateKeyParameter("AES", Hex.Decode("2B7E151628AED2A6ABF7158809CF4F3C"));
+
+			c.Init(true, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001")));
+
+			crypt = c.DoFinal(Hex.Decode("12345678"));
+
+			c.Init(false, new ParametersWithIV(sk, Hex.Decode("F0F1F2F3F4F5F6F7F8F9FAFBFCFD0001")));
+
+			crypt = c.DoFinal(crypt);
+
+			if (!AreEqual(crypt, Hex.Decode("12345678")))
+			{
+				Fail("AESSIC failed partial test");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AesSicTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/AESTest.cs b/BouncyCastle.AxCrypt/test/src/test/AESTest.cs
new file mode 100644
index 0000000..5a1ce80
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/AESTest.cs
@@ -0,0 +1,363 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>Basic test class for the AES cipher vectors from FIPS-197</remarks>
+	[TestFixture]
+	public class AesTest
+		: BaseBlockCipherTest
+	{
+		internal static readonly string[] cipherTests =
+		{
+			"128",
+			"000102030405060708090a0b0c0d0e0f",
+			"00112233445566778899aabbccddeeff",
+			"69c4e0d86a7b0430d8cdb78070b4c55a",
+			"192",
+			"000102030405060708090a0b0c0d0e0f1011121314151617",
+			"00112233445566778899aabbccddeeff",
+			"dda97ca4864cdfe06eaf70a0ec0d7191",
+			"256",
+			"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f",
+			"00112233445566778899aabbccddeeff",
+			"8ea2b7ca516745bfeafc49904b496089",
+		};
+
+		public AesTest()
+			: base("AES")
+		{
+		}
+
+		[Test]
+		public void TestCiphers()
+		{
+			for (int i = 0; i != cipherTests.Length; i += 4)
+			{
+				doCipherTest(int.Parse(cipherTests[i]),
+					Hex.Decode(cipherTests[i + 1]),
+					Hex.Decode(cipherTests[i + 2]),
+					Hex.Decode(cipherTests[i + 3]));
+			}
+		}
+
+		[Test]
+		public void TestOids()
+		{
+			string[] oids = {
+				NistObjectIdentifiers.IdAes128Ecb.Id,
+				NistObjectIdentifiers.IdAes128Cbc.Id,
+				NistObjectIdentifiers.IdAes128Ofb.Id,
+				NistObjectIdentifiers.IdAes128Cfb.Id,
+				NistObjectIdentifiers.IdAes192Ecb.Id,
+				NistObjectIdentifiers.IdAes192Cbc.Id,
+				NistObjectIdentifiers.IdAes192Ofb.Id,
+				NistObjectIdentifiers.IdAes192Cfb.Id,
+				NistObjectIdentifiers.IdAes256Ecb.Id,
+				NistObjectIdentifiers.IdAes256Cbc.Id,
+				NistObjectIdentifiers.IdAes256Ofb.Id,
+				NistObjectIdentifiers.IdAes256Cfb.Id
+			};
+
+			string[] names = {
+				"AES/ECB/PKCS7Padding",
+				"AES/CBC/PKCS7Padding",
+				"AES/OFB/NoPadding",
+				"AES/CFB/NoPadding",
+				"AES/ECB/PKCS7Padding",
+				"AES/CBC/PKCS7Padding",
+				"AES/OFB/NoPadding",
+				"AES/CFB/NoPadding",
+				"AES/ECB/PKCS7Padding",
+				"AES/CBC/PKCS7Padding",
+				"AES/OFB/NoPadding",
+				"AES/CFB/NoPadding"
+			};
+
+			oidTest(oids, names, 4);
+		}
+
+		[Test]
+		public void TestWrap()
+		{
+			byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+			byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[] out1 = Hex.Decode("1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5");
+
+			wrapTest(1, "AESWrap", kek1, in1, out1);
+		}
+
+		[Test]
+		public void TestWrapOids()
+		{
+			string[] wrapOids =
+			{
+				NistObjectIdentifiers.IdAes128Wrap.Id,
+				NistObjectIdentifiers.IdAes192Wrap.Id,
+				NistObjectIdentifiers.IdAes256Wrap.Id
+			};
+
+			wrapOidTest(wrapOids, "AESWrap");
+		}
+
+		private void doCipherTest(
+			int		strength,
+			byte[]	keyBytes,
+			byte[]	input,
+			byte[]	output)
+		{
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", keyBytes);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/ECB/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/ECB/NoPadding");
+
+			try
+			{
+				outCipher.Init(true, key);
+			}
+			catch (Exception e)
+			{
+				Fail("AES failed initialisation - " + e, e);
+			}
+
+			try
+			{
+				inCipher.Init(false, key);
+			}
+			catch (Exception e)
+			{
+				Fail("AES failed initialisation - " + e, e);
+			}
+
+			//
+			// encryption pass
+			//
+			MemoryStream bOut = new MemoryStream();
+
+			CipherStream cOut = new CipherStream(bOut, null, outCipher);
+
+			try
+			{
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					cOut.WriteByte(input[i]);
+				}
+				cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+				cOut.Close();
+			}
+			catch (IOException e)
+			{
+				Fail("AES failed encryption - " + e, e);
+			}
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("AES failed encryption - expected "
+					+ Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			MemoryStream bIn = new MemoryStream(bytes, false);
+
+			CipherStream cIn = new CipherStream(bIn, inCipher, null);
+
+			try
+			{
+//				DataInputStream dIn = new DataInputStream(cIn);
+				BinaryReader dIn = new BinaryReader(cIn);
+
+				bytes = new byte[input.Length];
+
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+//					bytes[i] = (byte)dIn.read();
+					bytes[i] = dIn.ReadByte();
+				}
+
+				int remaining = bytes.Length - input.Length / 2;
+//				dIn.readFully(bytes, input.Length / 2, remaining);
+				byte[] extra = dIn.ReadBytes(remaining);
+				if (extra.Length < remaining)
+					throw new EndOfStreamException();
+				extra.CopyTo(bytes, input.Length / 2);
+			}
+			catch (Exception e)
+			{
+				Fail("AES failed encryption - " + e, e);
+			}
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("AES failed decryption - expected "
+					+ Hex.ToHexString(input) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+		}
+
+		[Test]
+		public void TestEax()
+		{
+			byte[] K = Hex.Decode("233952DEE4D5ED5F9B9C6D6FF80FF478");
+			byte[] N = Hex.Decode("62EC67F9C3A4A407FCB2A8C49031A8B3");
+			byte[] P = Hex.Decode("68656c6c6f20776f726c642121");
+			byte[] C = Hex.Decode("2f9f76cb7659c70e4be11670a3e193ae1bc6b5762a");
+
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/EAX/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/EAX/NoPadding");
+
+			inCipher.Init(true, new ParametersWithIV(key, N));
+
+			byte[] enc = inCipher.DoFinal(P);
+			if (!AreEqual(enc, C))
+			{
+				Fail("ciphertext doesn't match in EAX");
+			}
+
+			outCipher.Init(false, new ParametersWithIV(key, N));
+
+			byte[] dec = outCipher.DoFinal(C);
+			if (!AreEqual(dec, P))
+			{
+				Fail("plaintext doesn't match in EAX");
+			}
+
+			try
+			{
+				inCipher = CipherUtilities.GetCipher("AES/EAX/PKCS5Padding");
+
+				Fail("bad padding missed in EAX");
+			}
+			catch (SecurityUtilityException)
+			{
+				// expected
+			}
+		}
+
+		[Test]
+		public void TestCcm()
+		{
+			byte[] K = Hex.Decode("404142434445464748494a4b4c4d4e4f");
+			byte[] N = Hex.Decode("10111213141516");
+			byte[] P = Hex.Decode("68656c6c6f20776f726c642121");
+			byte[] C = Hex.Decode("39264f148b54c456035de0a531c8344f46db12b388");
+
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/CCM/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/CCM/NoPadding");
+
+			inCipher.Init(true, new ParametersWithIV(key, N));
+
+			byte[] enc = inCipher.DoFinal(P);
+			if (!AreEqual(enc, C))
+			{
+				Fail("ciphertext doesn't match in CCM");
+			}
+
+			outCipher.Init(false, new ParametersWithIV(key, N));
+
+			byte[] dec = outCipher.DoFinal(C);
+			if (!AreEqual(dec, P))
+			{
+				Fail("plaintext doesn't match in CCM");
+			}
+
+			try
+			{
+				inCipher = CipherUtilities.GetCipher("AES/CCM/PKCS5Padding");
+
+				Fail("bad padding missed in CCM");
+			}
+			catch (SecurityUtilityException)
+			{
+				// expected
+			}
+		}
+
+		[Test]
+		public void TestGcm()
+		{
+			// Test Case 15 from McGrew/Viega
+			byte[] K = Hex.Decode(
+				  "feffe9928665731c6d6a8f9467308308"
+				+ "feffe9928665731c6d6a8f9467308308");
+			byte[] P = Hex.Decode(
+				  "d9313225f88406e5a55909c5aff5269a"
+				+ "86a7a9531534f7da2e4c303d8a318a72"
+				+ "1c3c0c95956809532fcf0e2449a6b525"
+				+ "b16aedf5aa0de657ba637b391aafd255");
+			byte[] N = Hex.Decode("cafebabefacedbaddecaf888");
+			string T = "b094dac5d93471bdec1a502270e3cc6c";
+			byte[] C = Hex.Decode(
+				  "522dc1f099567d07f47f37a32a84427d"
+				+ "643a8cdcbfe5c0c97598a2bd2555d1aa"
+				+ "8cb08e48590dbb3da7b08b1056828838"
+				+ "c5f61e6393ba7a0abcc9f662898015ad"
+				+ T);
+
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("AES", K);
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("AES/GCM/NoPadding");
+
+			inCipher.Init(true, new ParametersWithIV(key, N));
+
+			byte[] enc = inCipher.DoFinal(P);
+			if (!AreEqual(enc, C))
+			{
+				Fail("ciphertext doesn't match in GCM");
+			}
+
+			outCipher.Init(false, new ParametersWithIV(key, N));
+
+			byte[] dec = outCipher.DoFinal(C);
+			if (!AreEqual(dec, P))
+			{
+				Fail("plaintext doesn't match in GCM");
+			}
+
+			try
+			{
+				inCipher = CipherUtilities.GetCipher("AES/GCM/PKCS5Padding");
+
+				Fail("bad padding missed in GCM");
+			}
+			catch (SecurityUtilityException)
+			{
+				// expected
+			}
+		}
+
+		public override void PerformTest()
+		{
+			TestCiphers();
+			TestWrap();
+			TestOids();
+			TestWrapOids();
+			TestEax();
+			TestCcm();
+			TestGcm();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AesTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/AttrCertSelectorTest.cs b/BouncyCastle.AxCrypt/test/src/test/AttrCertSelectorTest.cs
new file mode 100644
index 0000000..37c1e66
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/AttrCertSelectorTest.cs
@@ -0,0 +1,214 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class AttrCertSelectorTest
+		: SimpleTest
+	{
+		private static readonly RsaPrivateCrtKeyParameters RsaPrivateKeySpec = new RsaPrivateCrtKeyParameters(
+			new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+			new BigInteger("11", 16),
+			new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+			new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+			new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+			new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+			new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+			new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+		private static readonly byte[] holderCert = Base64.Decode(
+			  "MIIGjTCCBXWgAwIBAgICAPswDQYJKoZIhvcNAQEEBQAwaTEdMBsGCSqGSIb3DQEJ"
+			+ "ARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZpcmdpbmlhIFRlY2ggQ2VydGlm"
+			+ "aWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0MQswCQYDVQQGEwJVUzAeFw0w"
+			+ "MzAxMzExMzUyMTRaFw0wNDAxMzExMzUyMTRaMIGDMRswGQYJKoZIhvcNAQkBFgxz"
+			+ "c2hhaEB2dC5lZHUxGzAZBgNVBAMTElN1bWl0IFNoYWggKHNzaGFoKTEbMBkGA1UE"
+			+ "CxMSVmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAxMQswCQYDVQQK"
+			+ "EwJ2dDELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPDc"
+			+ "scgSKmsEp0VegFkuitD5j5PUkDuzLjlfaYONt2SN8WeqU4j2qtlCnsipa128cyKS"
+			+ "JzYe9duUdNxquh5BPIkMkHBw4jHoQA33tk0J/sydWdN74/AHPpPieK5GHwhU7GTG"
+			+ "rCCS1PJRxjXqse79ExAlul+gjQwHeldAC+d4A6oZAgMBAAGjggOmMIIDojAMBgNV"
+			+ "HRMBAf8EAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCA/gwHQYD"
+			+ "VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMB0GA1UdDgQWBBRUIoWAzlXbzBYE"
+			+ "yVTjQFWyMMKo1jCBkwYDVR0jBIGLMIGIgBTgc3Fm+TGqKDhen+oKfbl+xVbj2KFt"
+			+ "pGswaTEdMBsGCSqGSIb3DQEJARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZp"
+			+ "cmdpbmlhIFRlY2ggQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0"
+			+ "MQswCQYDVQQGEwJVU4IBADCBiwYJYIZIAYb4QgENBH4WfFZpcmdpbmlhIFRlY2gg"
+			+ "Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgZGlnaXRhbCBjZXJ0aWZpY2F0ZXMgYXJl"
+			+ "IHN1YmplY3QgdG8gcG9saWNpZXMgbG9jYXRlZCBhdCBodHRwOi8vd3d3LnBraS52"
+			+ "dC5lZHUvY2EvY3BzLy4wFwYDVR0RBBAwDoEMc3NoYWhAdnQuZWR1MBkGA1UdEgQS"
+			+ "MBCBDmlybWhlbHBAdnQuZWR1MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYn"
+			+ "aHR0cDovL2JveDE3Ny5jYy52dC5lZHUvY2EvaXNzdWVycy5odG1sMEQGA1UdHwQ9"
+			+ "MDswOaA3oDWGM2h0dHA6Ly9ib3gxNzcuY2MudnQuZWR1L2h0ZG9jcy1wdWJsaWMv"
+			+ "Y3JsL2NhY3JsLmNybDBUBgNVHSAETTBLMA0GCysGAQQBtGgFAQEBMDoGCysGAQQB"
+			+ "tGgFAQEBMCswKQYIKwYBBQUHAgEWHWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9jYS9j"
+			+ "cHMvMD8GCWCGSAGG+EIBBAQyFjBodHRwOi8vYm94MTc3LmNjLnZ0LmVkdS9jZ2kt"
+			+ "cHVibGljL2NoZWNrX3Jldl9jYT8wPAYJYIZIAYb4QgEDBC8WLWh0dHA6Ly9ib3gx"
+			+ "NzcuY2MudnQuZWR1L2NnaS1wdWJsaWMvY2hlY2tfcmV2PzBLBglghkgBhvhCAQcE"
+			+ "PhY8aHR0cHM6Ly9ib3gxNzcuY2MudnQuZWR1L35PcGVuQ0E4LjAxMDYzMC9jZ2kt"
+			+ "cHVibGljL3JlbmV3YWw/MCwGCWCGSAGG+EIBCAQfFh1odHRwOi8vd3d3LnBraS52"
+			+ "dC5lZHUvY2EvY3BzLzANBgkqhkiG9w0BAQQFAAOCAQEAHJ2ls9yjpZVcu5DqiE67"
+			+ "r7BfkdMnm7IOj2v8cd4EAlPp6OPBmjwDMwvKRBb/P733kLBqFNWXWKTpT008R0KB"
+			+ "8kehbx4h0UPz9vp31zhGv169+5iReQUUQSIwTGNWGLzrT8kPdvxiSAvdAJxcbRBm"
+			+ "KzDic5I8PoGe48kSCkPpT1oNmnivmcu5j1SMvlx0IS2BkFMksr0OHiAW1elSnE/N"
+			+ "RuX2k73b3FucwVxB3NRo3vgoHPCTnh9r4qItAHdxFlF+pPtbw2oHESKRfMRfOIHz"
+			+ "CLQWSIa6Tvg4NIV3RRJ0sbCObesyg08lymalQMdkXwtRn5eGE00SHWwEUjSXP2gR"
+			+ "3g==");
+
+		public override string Name
+		{
+			get { return "AttrCertSelector"; }
+		}
+
+		private IX509AttributeCertificate CreateAttrCert()
+		{
+//			CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC");
+//			X509Certificate iCert = (X509Certificate) fact
+//				.generateCertificate(new ByteArrayInputStream(holderCert));
+			X509Certificate iCert = new X509CertificateParser().ReadCertificate(holderCert);
+
+			//
+			// a sample key pair.
+			//
+			// RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
+			// new BigInteger(
+			// "b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7",
+			// 16), new BigInteger("11", 16));
+
+			//
+			// set up the keys
+			//
+//			KeyFactory kFact = KeyFactory.getInstance("RSA", "BC");
+//			PrivateKey privKey = kFact.generatePrivate(RsaPrivateKeySpec);
+			AsymmetricKeyParameter privKey = RsaPrivateKeySpec;
+
+			X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator();
+
+			// the actual attributes
+			GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789 at test.com");
+			Asn1EncodableVector roleSyntax = new Asn1EncodableVector(roleName);
+
+			// roleSyntax OID: 2.5.24.72
+			X509Attribute attributes = new X509Attribute("2.5.24.72",
+				new DerSequence(roleSyntax));
+
+			gen.AddAttribute(attributes);
+			gen.SetHolder(new AttributeCertificateHolder(PrincipalUtilities.GetSubjectX509Principal(iCert)));
+			gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test")));
+			gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			gen.SetSerialNumber(BigInteger.One);
+			gen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			Target targetName = new Target(
+				Target.Choice.Name,
+				new GeneralName(GeneralName.DnsName, "www.test.com"));
+
+			Target targetGroup = new Target(
+				Target.Choice.Group,
+				new GeneralName(GeneralName.DirectoryName, "o=Test, ou=Test"));
+
+			Target[] targets = new Target[]{ targetName, targetGroup };
+
+			TargetInformation targetInformation = new TargetInformation(targets);
+			gen.AddExtension(X509Extensions.TargetInformation.Id, true, targetInformation);
+
+			return gen.Generate(privKey);
+		}
+
+		[Test]
+		public void TestSelector()
+		{
+			IX509AttributeCertificate aCert = CreateAttrCert();
+			X509AttrCertStoreSelector sel = new X509AttrCertStoreSelector();
+			sel.AttributeCert = aCert;
+			bool match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate.");
+			}
+			sel.AttributeCert = null;
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate.");
+			}
+			sel.Holder = aCert.Holder;
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate holder.");
+			}
+			sel.Holder = null;
+			sel.Issuer = aCert.Issuer;
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate issuer.");
+			}
+			sel.Issuer = null;
+
+//			CertificateFactory fact = CertificateFactory.getInstance("X.509", "BC");
+//			X509Certificate iCert = (X509Certificate) fact.generateCertificate(
+//				new ByteArrayInputStream(holderCert));
+			X509Certificate iCert = new X509CertificateParser().ReadCertificate(holderCert);
+			match = aCert.Holder.Match(iCert);
+			if (!match)
+			{
+				Fail("Issuer holder does not match signing certificate of attribute certificate.");
+			}
+
+			sel.SerialNumber = aCert.SerialNumber;
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate serial number.");
+			}
+
+			sel.AttributeCertificateValid = new DateTimeObject(DateTime.UtcNow);
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate time.");
+			}
+
+			sel.AddTargetName(new GeneralName(2, "www.test.com"));
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate target name.");
+			}
+			sel.SetTargetNames(null);
+			sel.AddTargetGroup(new GeneralName(4, "o=Test, ou=Test"));
+			match = sel.Match(aCert);
+			if (!match)
+			{
+				Fail("Selector does not match attribute certificate target group.");
+			}
+			sel.SetTargetGroups(null);
+		}
+
+		public override void PerformTest()
+		{
+			TestSelector();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AttrCertSelectorTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/AttrCertTest.cs b/BouncyCastle.AxCrypt/test/src/test/AttrCertTest.cs
new file mode 100644
index 0000000..d701d00
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/AttrCertTest.cs
@@ -0,0 +1,621 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class AttrCertTest
+		: SimpleTest
+	{
+		private static readonly RsaPrivateCrtKeyParameters RSA_PRIVATE_KEY_SPEC = new RsaPrivateCrtKeyParameters(
+			new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+			new BigInteger("11", 16),
+			new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+			new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+			new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+			new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+			new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+			new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+		internal static readonly byte[] attrCert = Base64.Decode(
+			"MIIHQDCCBqkCAQEwgZChgY2kgYowgYcxHDAaBgkqhkiG9w0BCQEWDW1sb3JjaEB2"
+			+ "dC5lZHUxHjAcBgNVBAMTFU1hcmt1cyBMb3JjaCAobWxvcmNoKTEbMBkGA1UECxMS"
+			+ "VmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAyMQswCQYDVQQKEwJ2"
+			+ "dDELMAkGA1UEBhMCVVMwgYmkgYYwgYMxGzAZBgkqhkiG9w0BCQEWDHNzaGFoQHZ0"
+			+ "LmVkdTEbMBkGA1UEAxMSU3VtaXQgU2hhaCAoc3NoYWgpMRswGQYDVQQLExJWaXJn"
+			+ "aW5pYSBUZWNoIFVzZXIxEDAOBgNVBAsTB0NsYXNzIDExCzAJBgNVBAoTAnZ0MQsw"
+			+ "CQYDVQQGEwJVUzANBgkqhkiG9w0BAQQFAAIBBTAiGA8yMDAzMDcxODE2MDgwMloY"
+			+ "DzIwMDMwNzI1MTYwODAyWjCCBU0wggVJBgorBgEEAbRoCAEBMYIFORaCBTU8UnVs"
+			+ "ZSBSdWxlSWQ9IkZpbGUtUHJpdmlsZWdlLVJ1bGUiIEVmZmVjdD0iUGVybWl0Ij4K"
+			+ "IDxUYXJnZXQ+CiAgPFN1YmplY3RzPgogICA8U3ViamVjdD4KICAgIDxTdWJqZWN0"
+			+ "TWF0Y2ggTWF0Y2hJZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5j"
+			+ "dGlvbjpzdHJpbmctZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlw"
+			+ "ZT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjc3RyaW5nIj4KICAg"
+			+ "ICAgIENOPU1hcmt1cyBMb3JjaDwvQXR0cmlidXRlVmFsdWU+CiAgICAgPFN1Ympl"
+			+ "Y3RBdHRyaWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFt"
+			+ "ZXM6dGM6eGFjbWw6MS4wOnN1YmplY3Q6c3ViamVjdC1pZCIgRGF0YVR5cGU9Imh0"
+			+ "dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hI3N0cmluZyIgLz4gCiAgICA8"
+			+ "L1N1YmplY3RNYXRjaD4KICAgPC9TdWJqZWN0PgogIDwvU3ViamVjdHM+CiAgPFJl"
+			+ "c291cmNlcz4KICAgPFJlc291cmNlPgogICAgPFJlc291cmNlTWF0Y2ggTWF0Y2hJ"
+			+ "ZD0idXJuOm9hc2lzOm5hbWVzOnRjOnhhY21sOjEuMDpmdW5jdGlvbjpzdHJpbmct"
+			+ "ZXF1YWwiPgogICAgIDxBdHRyaWJ1dGVWYWx1ZSBEYXRhVHlwZT0iaHR0cDovL3d3"
+			+ "dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIj4KICAgICAgaHR0cDovL3p1"
+			+ "bmkuY3MudnQuZWR1PC9BdHRyaWJ1dGVWYWx1ZT4KICAgICA8UmVzb3VyY2VBdHRy"
+			+ "aWJ1dGVEZXNpZ25hdG9yIEF0dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6"
+			+ "eGFjbWw6MS4wOnJlc291cmNlOnJlc291cmNlLWlkIiBEYXRhVHlwZT0iaHR0cDov"
+			+ "L3d3dy53My5vcmcvMjAwMS9YTUxTY2hlbWEjYW55VVJJIiAvPiAKICAgIDwvUmVz"
+			+ "b3VyY2VNYXRjaD4KICAgPC9SZXNvdXJjZT4KICA8L1Jlc291cmNlcz4KICA8QWN0"
+			+ "aW9ucz4KICAgPEFjdGlvbj4KICAgIDxBY3Rpb25NYXRjaCBNYXRjaElkPSJ1cm46"
+			+ "b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmZ1bmN0aW9uOnN0cmluZy1lcXVhbCI+"
+			+ "CiAgICAgPEF0dHJpYnV0ZVZhbHVlIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9y"
+			+ "Zy8yMDAxL1hNTFNjaGVtYSNzdHJpbmciPgpEZWxlZ2F0ZSBBY2Nlc3MgICAgIDwv"
+			+ "QXR0cmlidXRlVmFsdWU+CgkgIDxBY3Rpb25BdHRyaWJ1dGVEZXNpZ25hdG9yIEF0"
+			+ "dHJpYnV0ZUlkPSJ1cm46b2FzaXM6bmFtZXM6dGM6eGFjbWw6MS4wOmFjdGlvbjph"
+			+ "Y3Rpb24taWQiIERhdGFUeXBlPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNj"
+			+ "aGVtYSNzdHJpbmciIC8+IAogICAgPC9BY3Rpb25NYXRjaD4KICAgPC9BY3Rpb24+"
+			+ "CiAgPC9BY3Rpb25zPgogPC9UYXJnZXQ+CjwvUnVsZT4KMA0GCSqGSIb3DQEBBAUA"
+			+ "A4GBAGiJSM48XsY90HlYxGmGVSmNR6ZW2As+bot3KAfiCIkUIOAqhcphBS23egTr"
+			+ "6asYwy151HshbPNYz+Cgeqs45KkVzh7bL/0e1r8sDVIaaGIkjHK3CqBABnfSayr3"
+			+ "Rd1yBoDdEv8Qb+3eEPH6ab9021AsLEnJ6LWTmybbOpMNZ3tv");
+
+		internal static readonly byte[] signCert = Base64.Decode(
+			"MIIGjTCCBXWgAwIBAgICAPswDQYJKoZIhvcNAQEEBQAwaTEdMBsGCSqGSIb3DQEJ"
+			+ "ARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZpcmdpbmlhIFRlY2ggQ2VydGlm"
+			+ "aWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0MQswCQYDVQQGEwJVUzAeFw0w"
+			+ "MzAxMzExMzUyMTRaFw0wNDAxMzExMzUyMTRaMIGDMRswGQYJKoZIhvcNAQkBFgxz"
+			+ "c2hhaEB2dC5lZHUxGzAZBgNVBAMTElN1bWl0IFNoYWggKHNzaGFoKTEbMBkGA1UE"
+			+ "CxMSVmlyZ2luaWEgVGVjaCBVc2VyMRAwDgYDVQQLEwdDbGFzcyAxMQswCQYDVQQK"
+			+ "EwJ2dDELMAkGA1UEBhMCVVMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPDc"
+			+ "scgSKmsEp0VegFkuitD5j5PUkDuzLjlfaYONt2SN8WeqU4j2qtlCnsipa128cyKS"
+			+ "JzYe9duUdNxquh5BPIkMkHBw4jHoQA33tk0J/sydWdN74/AHPpPieK5GHwhU7GTG"
+			+ "rCCS1PJRxjXqse79ExAlul+gjQwHeldAC+d4A6oZAgMBAAGjggOmMIIDojAMBgNV"
+			+ "HRMBAf8EAjAAMBEGCWCGSAGG+EIBAQQEAwIFoDAOBgNVHQ8BAf8EBAMCA/gwHQYD"
+			+ "VR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMEMB0GA1UdDgQWBBRUIoWAzlXbzBYE"
+			+ "yVTjQFWyMMKo1jCBkwYDVR0jBIGLMIGIgBTgc3Fm+TGqKDhen+oKfbl+xVbj2KFt"
+			+ "pGswaTEdMBsGCSqGSIb3DQEJARYOaXJtaGVscEB2dC5lZHUxLjAsBgNVBAMTJVZp"
+			+ "cmdpbmlhIFRlY2ggQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxCzAJBgNVBAoTAnZ0"
+			+ "MQswCQYDVQQGEwJVU4IBADCBiwYJYIZIAYb4QgENBH4WfFZpcmdpbmlhIFRlY2gg"
+			+ "Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgZGlnaXRhbCBjZXJ0aWZpY2F0ZXMgYXJl"
+			+ "IHN1YmplY3QgdG8gcG9saWNpZXMgbG9jYXRlZCBhdCBodHRwOi8vd3d3LnBraS52"
+			+ "dC5lZHUvY2EvY3BzLy4wFwYDVR0RBBAwDoEMc3NoYWhAdnQuZWR1MBkGA1UdEgQS"
+			+ "MBCBDmlybWhlbHBAdnQuZWR1MEMGCCsGAQUFBwEBBDcwNTAzBggrBgEFBQcwAoYn"
+			+ "aHR0cDovL2JveDE3Ny5jYy52dC5lZHUvY2EvaXNzdWVycy5odG1sMEQGA1UdHwQ9"
+			+ "MDswOaA3oDWGM2h0dHA6Ly9ib3gxNzcuY2MudnQuZWR1L2h0ZG9jcy1wdWJsaWMv"
+			+ "Y3JsL2NhY3JsLmNybDBUBgNVHSAETTBLMA0GCysGAQQBtGgFAQEBMDoGCysGAQQB"
+			+ "tGgFAQEBMCswKQYIKwYBBQUHAgEWHWh0dHA6Ly93d3cucGtpLnZ0LmVkdS9jYS9j"
+			+ "cHMvMD8GCWCGSAGG+EIBBAQyFjBodHRwOi8vYm94MTc3LmNjLnZ0LmVkdS9jZ2kt"
+			+ "cHVibGljL2NoZWNrX3Jldl9jYT8wPAYJYIZIAYb4QgEDBC8WLWh0dHA6Ly9ib3gx"
+			+ "NzcuY2MudnQuZWR1L2NnaS1wdWJsaWMvY2hlY2tfcmV2PzBLBglghkgBhvhCAQcE"
+			+ "PhY8aHR0cHM6Ly9ib3gxNzcuY2MudnQuZWR1L35PcGVuQ0E4LjAxMDYzMC9jZ2kt"
+			+ "cHVibGljL3JlbmV3YWw/MCwGCWCGSAGG+EIBCAQfFh1odHRwOi8vd3d3LnBraS52"
+			+ "dC5lZHUvY2EvY3BzLzANBgkqhkiG9w0BAQQFAAOCAQEAHJ2ls9yjpZVcu5DqiE67"
+			+ "r7BfkdMnm7IOj2v8cd4EAlPp6OPBmjwDMwvKRBb/P733kLBqFNWXWKTpT008R0KB"
+			+ "8kehbx4h0UPz9vp31zhGv169+5iReQUUQSIwTGNWGLzrT8kPdvxiSAvdAJxcbRBm"
+			+ "KzDic5I8PoGe48kSCkPpT1oNmnivmcu5j1SMvlx0IS2BkFMksr0OHiAW1elSnE/N"
+			+ "RuX2k73b3FucwVxB3NRo3vgoHPCTnh9r4qItAHdxFlF+pPtbw2oHESKRfMRfOIHz"
+			+ "CLQWSIa6Tvg4NIV3RRJ0sbCObesyg08lymalQMdkXwtRn5eGE00SHWwEUjSXP2gR"
+			+ "3g==");
+
+		internal static readonly byte[] certWithBaseCertificateID = Base64.Decode(
+			"MIIBqzCCARQCAQEwSKBGMD6kPDA6MQswCQYDVQQGEwJJVDEOMAwGA1UEChMFVU5JVE4xDDAKBgNV"
+			+ "BAsTA0RJVDENMAsGA1UEAxMEcm9vdAIEAVMVjqB6MHikdjB0MQswCQYDVQQGEwJBVTEoMCYGA1UE"
+			+ "ChMfVGhlIExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFByaW1h"
+			+ "cnkgQ2VydGlmaWNhdGUxFjAUBgNVBAMTDUJvdW5jeSBDYXN0bGUwDQYJKoZIhvcNAQEFBQACBQKW"
+			+ "RhnHMCIYDzIwMDUxMjEyMTIwMDQyWhgPMjAwNTEyMTkxMjAxMzJaMA8wDQYDVRhIMQaBBGVWSVAw"
+			+ "DQYJKoZIhvcNAQEFBQADgYEAUAVin9StDaA+InxtXq/av6rUQLI9p1X6louBcj4kYJnxRvTrHpsr"
+			+ "N3+i9Uq/uk5lRdAqmPFvcmSbuE3TRAsjrXON5uFiBBKZ1AouLqcr8nHbwcdwjJ9TyUNO9I4hfpSH"
+			+ "UHHXMtBKgp4MOkhhX8xTGyWg3hp23d3GaUeg/IYlXBI=");
+
+		internal static readonly byte[] holderCertWithBaseCertificateID = Base64.Decode(
+			"MIIBwDCCASmgAwIBAgIEAVMVjjANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJJVDEOMAwGA1UE"
+			+ "ChMFVU5JVE4xDDAKBgNVBAsTA0RJVDENMAsGA1UEAxMEcm9vdDAeFw0wNTExMTExMjAxMzJaFw0w"
+			+ "NjA2MTYxMjAxMzJaMD4xCzAJBgNVBAYTAklUMQ4wDAYDVQQKEwVVTklUTjEMMAoGA1UECxMDRElU"
+			+ "MREwDwYDVQQDEwhMdWNhQm9yejBaMA0GCSqGSIb3DQEBAQUAA0kAMEYCQQC0p+RhcFdPFqlwgrIr"
+			+ "5YtqKmKXmEGb4ShypL26Ymz66ZAPdqv7EhOdzl3lZWT6srZUMWWgQMYGiHQg4z2R7X7XAgERoxUw"
+			+ "EzARBglghkgBhvhCAQEEBAMCBDAwDQYJKoZIhvcNAQEFBQADgYEAsX50VPQQCWmHvPq9y9DeCpmS"
+			+ "4szcpFAhpZyn6gYRwY9CRZVtmZKH8713XhkGDWcIEMcG0u3oTz3tdKgPU5uyIPrDEWr6w8ClUj4x"
+			+ "5aVz5c2223+dVY7KES//JSB2bE/KCIchN3kAioQ4K8O3e0OL6oDVjsqKGw5bfahgKuSIk/Q=");
+
+
+		public override string Name
+		{
+			get { return "AttrCertTest"; }
+		}
+
+		private void doTestCertWithBaseCertificateID()
+		{
+			IX509AttributeCertificate attrCert = new X509V2AttributeCertificate(certWithBaseCertificateID);
+			X509CertificateParser fact = new X509CertificateParser();
+			X509Certificate cert = fact.ReadCertificate(holderCertWithBaseCertificateID);
+
+			AttributeCertificateHolder holder = attrCert.Holder;
+
+			if (holder.GetEntityNames() != null)
+			{
+				Fail("entity names set when none expected");
+			}
+
+			if (!holder.SerialNumber.Equals(cert.SerialNumber))
+			{
+				Fail("holder serial number doesn't Match");
+			}
+
+			if (!holder.GetIssuer()[0].Equivalent(cert.IssuerDN))
+			{
+				Fail("holder issuer doesn't Match");
+			}
+
+			if (!holder.Match(cert))
+			{
+				Fail("holder not matching holder certificate");
+			}
+
+			if (!holder.Equals(holder.Clone()))
+			{
+				Fail("holder clone test failed");
+			}
+
+			if (!attrCert.Issuer.Equals(attrCert.Issuer.Clone()))
+			{
+				Fail("issuer clone test failed");
+			}
+
+			equalityAndHashCodeTest(attrCert, certWithBaseCertificateID);
+		}
+
+		private void equalityAndHashCodeTest(
+			IX509AttributeCertificate	attrCert,
+			byte[]						encoding)
+		{
+			if (!attrCert.Equals(attrCert))
+			{
+				Fail("same certificate not equal");
+			}
+
+			if (!attrCert.Holder.Equals(attrCert.Holder))
+			{
+				Fail("same holder not equal");
+			}
+
+			if (!attrCert.Issuer.Equals(attrCert.Issuer))
+			{
+				Fail("same issuer not equal");
+			}
+
+			if (attrCert.Holder.Equals(attrCert.Issuer))
+			{
+				Fail("wrong holder equal");
+			}
+
+			if (attrCert.Issuer.Equals(attrCert.Holder))
+			{
+				Fail("wrong issuer equal");
+			}
+
+			IX509AttributeCertificate attrCert2 = new X509V2AttributeCertificate(encoding);
+
+			if (attrCert2.Holder.GetHashCode() != attrCert.Holder.GetHashCode())
+			{
+				Fail("holder hashCode test failed");
+			}
+
+			if (!attrCert2.Holder.Equals(attrCert.Holder))
+			{
+				Fail("holder Equals test failed");
+			}
+
+			if (attrCert2.Issuer.GetHashCode() != attrCert.Issuer.GetHashCode())
+			{
+				Fail("issuer hashCode test failed");
+			}
+
+			if (!attrCert2.Issuer.Equals(attrCert.Issuer))
+			{
+				Fail("issuer Equals test failed");
+			}
+		}
+
+		private void doTestGenerateWithCert()
+		{
+			X509CertificateParser fact = new X509CertificateParser();
+			X509Certificate iCert = fact.ReadCertificate(signCert);
+
+			//
+			// a sample key pair.
+			//
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+			//
+			// set up the keys
+			//
+//			PrivateKey privKey;
+//			PublicKey pubKey;
+//
+//			KeyFactory  kFact = KeyFactory.getInstance("RSA");
+//
+//			privKey = kFact.generatePrivate(RSA_PRIVATE_KEY_SPEC);
+//			pubKey = kFact.generatePublic(pubKeySpec);
+			AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC;
+
+			X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator();
+
+			// the actual attributes
+			GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789");
+
+			// roleSyntax OID: 2.5.24.72
+			X509Attribute attributes = new X509Attribute("2.5.24.72",
+				new DerSequence(roleName));
+
+			gen.AddAttribute(attributes);
+			gen.SetHolder(new AttributeCertificateHolder(iCert));
+			gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test")));
+			gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			gen.SetSerialNumber(BigInteger.One);
+			gen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			IX509AttributeCertificate aCert = gen.Generate(privKey);
+
+			aCert.CheckValidity();
+
+			aCert.Verify(pubKey);
+
+			AttributeCertificateHolder holder = aCert.Holder;
+
+			if (holder.GetEntityNames() != null)
+			{
+				Fail("entity names set when none expected");
+			}
+
+			if (!holder.SerialNumber.Equals(iCert.SerialNumber))
+			{
+				Fail("holder serial number doesn't Match");
+			}
+
+			if (!holder.GetIssuer()[0].Equivalent(iCert.IssuerDN))
+			{
+				Fail("holder issuer doesn't Match");
+			}
+
+			if (!holder.Match(iCert))
+			{
+				Fail("generated holder not matching holder certificate");
+			}
+
+			X509Attribute[] attrs = aCert.GetAttributes("2.5.24.72");
+
+			if (attrs == null)
+			{
+				Fail("attributes related to 2.5.24.72 not found");
+			}
+
+			X509Attribute attr = attrs[0];
+
+			if (!attr.Oid.Equals("2.5.24.72"))
+			{
+				Fail("attribute oid mismatch");
+			}
+
+			Asn1Encodable[] values = attr.GetValues();
+
+			GeneralName role = GeneralNames.GetInstance(values[0]).GetNames()[0];
+
+			if (role.TagNo != GeneralName.Rfc822Name)
+			{
+				Fail("wrong general name type found in role");
+			}
+
+			if (!((IAsn1String)role.Name).GetString().Equals("DAU123456789"))
+			{
+				Fail("wrong general name value found in role");
+			}
+
+			X509Certificate sCert = fact.ReadCertificate(holderCertWithBaseCertificateID);
+
+			if (holder.Match(sCert))
+			{
+				Fail("generated holder matching wrong certificate");
+			}
+
+			equalityAndHashCodeTest(aCert, aCert.GetEncoded());
+		}
+
+		private void doTestGenerateWithPrincipal()
+		{
+			X509CertificateParser fact = new X509CertificateParser();
+			X509Certificate iCert = fact.ReadCertificate(signCert);
+
+			//
+			// a sample key pair.
+			//
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+			//
+			// set up the keys
+			//
+//			PrivateKey          privKey;
+//			PublicKey           pubKey;
+//
+//			KeyFactory  kFact = KeyFactory.getInstance("RSA");
+//
+//			privKey = kFact.generatePrivate(RSA_PRIVATE_KEY_SPEC);
+//			pubKey = kFact.generatePublic(pubKeySpec);
+			AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC;
+
+			X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator();
+
+			// the actual attributes
+			GeneralName roleName = new GeneralName(GeneralName.Rfc822Name, "DAU123456789");
+
+			// roleSyntax OID: 2.5.24.72
+			X509Attribute attributes = new X509Attribute("2.5.24.72",
+				new DerSequence(roleName));
+
+			gen.AddAttribute(attributes);
+			gen.SetHolder(new AttributeCertificateHolder(iCert.SubjectDN));
+			gen.SetIssuer(new AttributeCertificateIssuer(new X509Name("cn=test")));
+			gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			gen.SetSerialNumber(BigInteger.One);
+			gen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			IX509AttributeCertificate aCert = gen.Generate(privKey);
+
+			aCert.CheckValidity();
+
+			aCert.Verify(pubKey);
+
+			AttributeCertificateHolder holder = aCert.Holder;
+
+			if (holder.GetEntityNames() == null)
+			{
+				Fail("entity names not set when expected");
+			}
+
+			if (holder.SerialNumber != null)
+			{
+				Fail("holder serial number found when none expected");
+			}
+
+			if (holder.GetIssuer() != null)
+			{
+				Fail("holder issuer found when none expected");
+			}
+
+			if (!holder.Match(iCert))
+			{
+				Fail("generated holder not matching holder certificate");
+			}
+
+			X509Certificate sCert = fact.ReadCertificate(holderCertWithBaseCertificateID);
+
+			if (holder.Match(sCert))
+			{
+				Fail("principal generated holder matching wrong certificate");
+			}
+
+			equalityAndHashCodeTest(aCert, aCert.GetEncoded());
+		}
+
+		public override void PerformTest()
+		{
+			IX509AttributeCertificate aCert = new X509V2AttributeCertificate(attrCert);
+			X509CertificateParser fact = new X509CertificateParser();
+			X509Certificate sCert = fact.ReadCertificate(signCert);
+
+			aCert.Verify(sCert.GetPublicKey());
+
+			//
+			// search test
+			//
+			IList list = new ArrayList();
+
+			list.Add(sCert);
+
+//			CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list);
+//			CertStore store = CertStore.getInstance("Collection", ccsp);
+			IX509Store store = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(list));
+
+			ArrayList certs = new ArrayList(
+//				store.getCertificates(aCert.getIssuer()));
+				store.GetMatches(aCert.Issuer));
+
+			if (certs.Count != 1 || !certs.Contains(sCert))
+			{
+				Fail("sCert not found by issuer");
+			}
+
+			X509Attribute[] attrs = aCert.GetAttributes("1.3.6.1.4.1.6760.8.1.1");
+			if (attrs == null || attrs.Length != 1)
+			{
+				Fail("attribute not found");
+			}
+
+			//
+			// reencode test
+			//
+			aCert = new X509V2AttributeCertificate(aCert.GetEncoded());
+
+			aCert.Verify(sCert.GetPublicKey());
+
+			IX509AttributeCertificate saCert = new X509V2AttributeCertificate(aCert.GetEncoded());
+
+			if (!aCert.NotAfter.Equals(saCert.NotAfter))
+			{
+				Fail("failed date comparison");
+			}
+
+			// base generator test
+
+			//
+			// a sample key pair.
+			//
+			RsaKeyParameters pubKey = new RsaKeyParameters(
+				false,
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+			AsymmetricKeyParameter privKey = RSA_PRIVATE_KEY_SPEC;
+
+			//
+			// set up the keys
+			//
+//			PrivateKey          privKey;
+//			PublicKey           pubKey;
+//
+//			KeyFactory  kFact = KeyFactory.getInstance("RSA");
+//
+//			privKey = kFact.generatePrivate(privKeySpec);
+//			pubKey = kFact.generatePublic(pubKeySpec);
+
+			X509V2AttributeCertificateGenerator gen = new X509V2AttributeCertificateGenerator();
+
+			gen.AddAttribute(attrs[0]);
+			gen.SetHolder(aCert.Holder);
+			gen.SetIssuer(aCert.Issuer);
+			gen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			gen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			gen.SetSerialNumber(aCert.SerialNumber);
+			gen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+
+			aCert = gen.Generate(privKey);
+
+			aCert.CheckValidity();
+
+			aCert.Verify(pubKey);
+
+			// as the issuer is the same this should still work (even though it is not
+			// technically correct
+
+			certs = new ArrayList(
+//				store.getCertificates(aCert.Issuer));
+				store.GetMatches(aCert.Issuer));
+
+			if (certs.Count != 1 || !certs.Contains(sCert))
+			{
+				Fail("sCert not found by issuer");
+			}
+
+			attrs = aCert.GetAttributes("1.3.6.1.4.1.6760.8.1.1");
+			if (attrs == null || attrs.Length != 1)
+			{
+				Fail("attribute not found");
+			}
+
+			//
+			// reencode test
+			//
+			aCert = new X509V2AttributeCertificate(aCert.GetEncoded());
+
+			aCert.Verify(pubKey);
+
+			AttributeCertificateIssuer issuer = aCert.Issuer;
+
+			X509Name[] principals = issuer.GetPrincipals();
+
+			//
+			// test holder
+			//
+			AttributeCertificateHolder holder = aCert.Holder;
+
+			if (holder.GetEntityNames() == null)
+			{
+				Fail("entity names not set");
+			}
+
+			if (holder.SerialNumber != null)
+			{
+				Fail("holder serial number set when none expected");
+			}
+
+			if (holder.GetIssuer() != null)
+			{
+				Fail("holder issuer set when none expected");
+			}
+
+			principals = holder.GetEntityNames();
+
+			string ps = principals[0].ToString();
+
+			// TODO Check that this is a good enough test
+//			if (!ps.Equals("C=US, O=vt, OU=Class 2, OU=Virginia Tech User, CN=Markus Lorch (mlorch), EMAILADDRESS=mlorch at vt.edu"))
+			if (!principals[0].Equivalent(new X509Name("C=US, O=vt, OU=Class 2, OU=Virginia Tech User, CN=Markus Lorch (mlorch), EMAILADDRESS=mlorch at vt.edu")))
+			{
+				Fail("principal[0] for entity names don't Match");
+			}
+
+			//
+			// extension test
+			//
+
+			gen.AddExtension("1.1", true, new DerOctetString(new byte[10]));
+
+			gen.AddExtension("2.2", false, new DerOctetString(new byte[20]));
+
+			aCert = gen.Generate(privKey);
+
+			ISet exts = aCert.GetCriticalExtensionOids();
+
+			if (exts.Count != 1 || !exts.Contains("1.1"))
+			{
+				Fail("critical extension test failed");
+			}
+
+			exts = aCert.GetNonCriticalExtensionOids();
+
+			if (exts.Count != 1 || !exts.Contains("2.2"))
+			{
+				Fail("non-critical extension test failed");
+			}
+
+			Asn1OctetString extString = aCert.GetExtensionValue(new DerObjectIdentifier("1.1"));
+			Asn1Encodable extValue = X509ExtensionUtilities.FromExtensionValue(extString);
+
+			if (!extValue.Equals(new DerOctetString(new byte[10])))
+			{
+				Fail("wrong extension value found for 1.1");
+			}
+
+			doTestCertWithBaseCertificateID();
+			doTestGenerateWithCert();
+			doTestGenerateWithPrincipal();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new AttrCertTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/BaseBlockCipherTest.cs b/BouncyCastle.AxCrypt/test/src/test/BaseBlockCipherTest.cs
new file mode 100644
index 0000000..87fb010
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/BaseBlockCipherTest.cs
@@ -0,0 +1,146 @@
+using System;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	public abstract class BaseBlockCipherTest
+		: SimpleTest
+	{
+		string algorithm;
+
+		internal BaseBlockCipherTest(
+			string algorithm)
+		{
+			this.algorithm = algorithm;
+		}
+
+		public override string Name
+		{
+			get { return algorithm; }
+		}
+
+		protected void oidTest(
+			string[]	oids,
+			string[]	names,
+			int			groupSize)
+		{
+			byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+			for (int i = 0; i != oids.Length; i++)
+			{
+				IBufferedCipher c1 = CipherUtilities.GetCipher(oids[i]);
+				IBufferedCipher c2 = CipherUtilities.GetCipher(names[i]);
+				CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]);
+
+				KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey());
+
+				ICipherParameters cp = k;
+				if (names[i].IndexOf("/ECB/") < 0)
+				{
+					cp = new ParametersWithIV(cp, new byte[16]);
+				}
+
+				c1.Init(true, cp);
+				c2.Init(false, cp);
+
+				byte[] result = c2.DoFinal(c1.DoFinal(data));
+
+				if (!AreEqual(data, result))
+				{
+					Fail("failed OID test");
+				}
+
+				if (k.GetKey().Length != (16 + ((i / groupSize) * 8)))
+				{
+					Fail("failed key length test");
+				}
+			}
+		}
+
+		protected void wrapOidTest(
+			string[]	oids,
+			string		name)
+		{
+			byte[] data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+
+			for (int i = 0; i != oids.Length; i++)
+			{
+				IWrapper c1 = WrapperUtilities.GetWrapper(oids[i]);
+				IWrapper c2 = WrapperUtilities.GetWrapper(name);
+				CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]);
+
+				KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey());
+
+				c1.Init(true, k);
+				c2.Init(false, k);
+
+				byte[] wrapped = c1.Wrap(data, 0, data.Length);
+				byte[] wKeyBytes = c2.Unwrap(wrapped, 0, wrapped.Length);
+
+				if (!AreEqual(data, wKeyBytes))
+				{
+					Fail("failed wrap OID test");
+				}
+
+				if (k.GetKey().Length != (16 + (i * 8)))
+				{
+					Fail("failed key length test");
+				}
+			}
+		}
+
+		protected void wrapTest(
+			int		id,
+			string	wrappingAlgorithm,
+			byte[]	kek,
+			byte[]	inBytes,
+			byte[]	outBytes)
+		{
+			IWrapper wrapper = WrapperUtilities.GetWrapper(wrappingAlgorithm);
+
+			wrapper.Init(true, ParameterUtilities.CreateKeyParameter(algorithm, kek));
+
+			try
+			{
+				byte[] cText = wrapper.Wrap(inBytes, 0, inBytes.Length);
+				if (!AreEqual(cText, outBytes))
+				{
+					Fail("failed wrap test " + id  + " expected "
+						+ Hex.ToHexString(outBytes) + " got "
+						+ Hex.ToHexString(cText));
+				}
+			}
+			catch (TestFailedException e)
+			{
+				throw e;
+			}
+			catch (Exception e)
+			{
+				Fail("failed wrap test exception " + e.ToString(), e);
+			}
+
+			wrapper.Init(false, ParameterUtilities.CreateKeyParameter(algorithm, kek));
+
+			try
+			{
+				byte[] pTextBytes = wrapper.Unwrap(outBytes, 0, outBytes.Length);
+
+				if (!AreEqual(pTextBytes, inBytes))
+				{
+					Fail("failed unwrap test " + id  + " expected "
+						+ Hex.ToHexString(inBytes) + " got "
+						+ Hex.ToHexString(pTextBytes));
+				}
+			}
+			catch (Exception e)
+			{
+				Fail("failed unwrap test exception " + e.ToString(), e);
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/BlockCipherTest.cs b/BouncyCastle.AxCrypt/test/src/test/BlockCipherTest.cs
new file mode 100644
index 0000000..2e8e8b0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/BlockCipherTest.cs
@@ -0,0 +1,972 @@
+using System;
+using System.Globalization;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    /**
+    * basic test class for a block cipher, basically this just exercises the provider, and makes sure we
+    * are behaving sensibly, correctness of the implementation is shown in the lightweight test classes.
+    */
+    [TestFixture]
+    public class BlockCipherTest
+        : SimpleTest
+    {
+        private static readonly ISet validModes = CollectionUtilities.ReadOnly(
+            new HashSet(new string[]{ "CBC", "CCM", "CFB", "CTR", "CTS", "EAX", "ECB", "GCM", "OCB", "OFB" }));
+
+        private static readonly string[] cipherTests1 =
+        {
+            "DES",
+            "466da00648ef0e1f9617b1f002e225251a3248d09172f46b9617b1f002e225250112ecb3da61bc99",
+            "DESede",
+            "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394",
+            "SKIPJACK",
+            "d4de46d52274dbb029f33b076043f8c40089f906751623de29f33b076043f8c4ac99b90f9396cb04",
+            "Blowfish",
+            "7870ebe7f6a52803eb9396ba6c5198216ce81d76d8d4c74beb9396ba6c5198211212473b05214e9f",
+            "Twofish",
+            "70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c0839e31468661bcfc57a14899ceeb0253",
+            "RC2",
+            "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b994a5b859e765797",
+            "RC5",
+            "220053543e3eca3bc9503a091ca67b08372560d8a4fdbee8c9503a091ca67b08a796d53bb8a4b7e0",
+            "RC5-64",
+            "e0b4a526ba3bc5f09199c3b1fe3737fe6d248cde70e565b0feea59ebfda375ae1946c386a48d8d8a74d7b1947ff6a788",
+            "RC6",
+            "44c97b67ca8486067f8b6c5b97632f3049e5e52c1d61fdd527dc3da39616540f19a3db39aac1ffd713795cd886cce0c0",
+            "IDEA",
+            "8c9fd56823ffdc523f6ccf7f614aa6173553e594fc7a21b53f6ccf7f614aa61740c54f7a66e95108",
+            "TEA",
+            "fcf45062104fda7c35712368b56dd4216a6ca998dc297b5435712368b56dd421208027ed2923cd0c",
+            "XTEA",
+            "4b427893d3d6aaded2afafabe25f7b233fb5589faa2b6389d2afafabe25f7b239d12979ac67e1c07",
+            "Camellia",
+            "3a68b4ad145bc2c76010669d68f2826359887afce763a78d9994143266adfaec8ba7ee562a1688ef9dfd7f897e5c44dc",
+            "SEED",
+            "d53d4ce1f48b9879420949467bfcbfbe2c6a7d4a8770bee0c71211def898d7c5024ce2007dd85accb3f69d906ae2164d",
+            "Noekeon",
+            "7e68ceb33aad9db04af6b878a16dd6c6b4f880d6c89027ba581884c10690bb6b3dbfd6ed5513e2c4f5670c3528023121",
+            "DES/CBC/NoPadding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a",
+            "DESede/CBC/NoPadding",
+            "4d3d7931875cf25593dc402298add8b914761e4936c9585ae22b2c1441169231",
+            "SKIPJACK/CBC/NoPadding",
+            "ceebcc2e5e2b847f9ed797b4930b95f115b9e6cf49c457fc2ea0df79ad5c8334",
+            "Blowfish/CBC/NoPadding",
+            "80823abbabc109733e7ebf3ce3344d67fc387c306b782086b452f7fbe8e844ce",
+            "Twofish/CBC/NoPadding",
+            "f819694251a00bdd403928745cd1d8a094de61f49ddf8e7692e9d81a83812943",
+            "RC2/CBC/NoPadding",
+            "a51facdb3933c9676795cd38cc3146fd4694722b468b1a979a399c77606abf99",
+            "RC5/CBC/NoPadding",
+            "9ee7517eab0280445f3a7c60c90c0f75029d65bca8b1af83ace5399d388c83c3",
+            "RC6/CBC/NoPadding",
+            "c44695633c07010f3a0d8f7ea046a642d4a96bf4e44f89fd91b46830bc95b130",
+            "IDEA/CBC/NoPadding",
+            "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9",
+            "DES/CBC/PKCS5Padding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122afdc70484fb9c0232",
+            "DES/CBC/ISO10126Padding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8",
+            "DES/CBC/ISO7816-4Padding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a1f80b9b0f1be49ac",
+            "DES/CBC/X9.23Padding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122a980639850a2cc3e8",
+            "DESede/CBC/PKCS7Padding",
+            "4d3d7931875cf25593dc402298add8b914761e4936c9585ae22b2c1441169231a41e40695f1cff84",
+            "SKIPJACK/CBC/PKCS7Padding",
+            "ceebcc2e5e2b847f9ed797b4930b95f115b9e6cf49c457fc2ea0df79ad5c8334df7042de5db89c96",
+            "Blowfish/CBC/PKCS7Padding",
+            "80823abbabc109733e7ebf3ce3344d67fc387c306b782086b452f7fbe8e844cef986562ab1a675e8",
+            "Twofish/CBC/PKCS7Padding",
+            "f819694251a00bdd403928745cd1d8a094de61f49ddf8e7692e9d81a838129433e5f1343d6cdb0b41838619da1541f04",
+            "RC2/CBC/PKCS7Padding",
+            "a51facdb3933c9676795cd38cc3146fd4694722b468b1a979a399c77606abf9958435525f770f137",
+            "RC5/CBC/PKCS7Padding",
+            "9ee7517eab0280445f3a7c60c90c0f75029d65bca8b1af83ace5399d388c83c3edd95ff49be76651",
+            "RC5-64/CBC/PKCS7Padding",
+            "e479fd11f89dab22d2f3dd062b1d2abd5b5962553421a5c562dc7214c3b23b8e21949fda87f2f820e5f032c552c6ec78",
+            "RC6/CBC/PKCS7Padding",
+            "c44695633c07010f3a0d8f7ea046a642d4a96bf4e44f89fd91b46830bc95b130824b972c9019a69d2dd05ef2d36b37ac",
+            "IDEA/CBC/PKCS7Padding",
+            "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9e584751325ef7c32",
+            "IDEA/CBC/ISO10126Padding",
+            "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b",
+            "IDEA/CBC/X9.23Padding",
+            "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d978b3fd73135f033b",
+            "AES/CBC/PKCS7Padding",
+            "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7",
+            "AES/CBC/ISO7816-4Padding",
+            "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08306d84876508a33efec701118d8eeaf6d",
+            "Rijndael/CBC/PKCS7Padding",
+            "cf87f4d8bb9d1abb36cdd9f44ead7d046db2f802d99e1ef0a5940f306079e08389a44c4a8cc1a47cbaee1128da55bbb7",
+            "Serpent/CBC/PKCS7Padding",
+            "f8940ca31aba8ce1e0693b1ae0b1e08daef6de03c80f019774280052f824ac44540bb8dd74dfad47f83f9c7ec268ca68",
+            "CAST5/CBC/PKCS7Padding",
+            "87b6dc0c5a1d23d42fa740b0548be0b298112000544610d889d6361994cf8e670a19d6af72d7289f",
+            "CAST6/CBC/PKCS7Padding",
+            "943445569cfdda174118e433828f84e137faee38cac5c827d87a3c9a5a46a07dd64e7ad8accd921f248eea627cd6826f",
+            "IDEA/CBC/PKCS7Padding",
+            "30cd990ebdae80fe12b6c6e4fcd1c064a27d985c276b3d7097351c8684e4c4d9e584751325ef7c32",
+            "DES/CBC/ZeroBytePadding",
+            "60fa2f8fae5aa2a38e9ac77d0246726beb7511e4515feb12cf99f75cc6e0122ad3b3f002c927f1fd",
+            "DES/CTS/NoPadding", // official style
+            "60fa2f8fae5aa2a38e9ac77d0246726bcf99f75cc6e0122aeb7511e4515feb12",
+            "DESede/CTS/NoPadding",
+            "4d3d7931875cf25593dc402298add8b9e22b2c144116923114761e4936c9585a",
+            "SKIPJACK/CTS/NoPadding",
+            "ceebcc2e5e2b847f9ed797b4930b95f12ea0df79ad5c833415b9e6cf49c457fc",
+            "Blowfish/CTS/NoPadding",
+            "80823abbabc109733e7ebf3ce3344d67b452f7fbe8e844cefc387c306b782086",
+            "Twofish/CTS/NoPadding",
+            "94de61f49ddf8e7692e9d81a83812943f819694251a00bdd403928745cd1d8a0",
+            "AES/CTS/NoPadding",
+            "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04",
+            "Rijndael/CTS/NoPadding",
+            "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04",
+            "Serpent/CTS/NoPadding",
+            "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d",
+            "CAST5/CTS/NoPadding",
+            "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8",
+            "CAST6/CTS/NoPadding",
+            "37faee38cac5c827d87a3c9a5a46a07d943445569cfdda174118e433828f84e1",
+            "RC2/CTS/NoPadding",
+            "a51facdb3933c9676795cd38cc3146fd9a399c77606abf994694722b468b1a97",
+            "RC5/CTS/NoPadding",
+            "9ee7517eab0280445f3a7c60c90c0f75ace5399d388c83c3029d65bca8b1af83",
+            "RC6/CTS/NoPadding",
+            "d4a96bf4e44f89fd91b46830bc95b130c44695633c07010f3a0d8f7ea046a642",
+            "IDEA/CTS/NoPadding",
+            "30cd990ebdae80fe12b6c6e4fcd1c06497351c8684e4c4d9a27d985c276b3d70",
+            "DES/CBC/WithCTS",                  // older style
+            "60fa2f8fae5aa2a38e9ac77d0246726bcf99f75cc6e0122aeb7511e4515feb12",
+            "DESede/CBC/WithCTS",
+            "4d3d7931875cf25593dc402298add8b9e22b2c144116923114761e4936c9585a",
+            "SKIPJACK/CBC/WithCTS",
+            "ceebcc2e5e2b847f9ed797b4930b95f12ea0df79ad5c833415b9e6cf49c457fc",
+            "Blowfish/CBC/WithCTS",
+            "80823abbabc109733e7ebf3ce3344d67b452f7fbe8e844cefc387c306b782086",
+            "Twofish/CBC/WithCTS",
+            "94de61f49ddf8e7692e9d81a83812943f819694251a00bdd403928745cd1d8a0",
+            "AES/CBC/WithCTS",
+            "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04",
+            "Rijndael/CBC/WithCTS",
+            "6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04",
+            "Serpent/CBC/WithCTS",
+            "aef6de03c80f019774280052f824ac44f8940ca31aba8ce1e0693b1ae0b1e08d",
+            "CAST5/CBC/WithCTS",
+            "87b6dc0c5a1d23d42fa740b0548be0b289d6361994cf8e6798112000544610d8",
+            "CAST6/CBC/WithCTS",
+            "37faee38cac5c827d87a3c9a5a46a07d943445569cfdda174118e433828f84e1",
+            "RC2/CBC/WithCTS",
+            "a51facdb3933c9676795cd38cc3146fd9a399c77606abf994694722b468b1a97",
+            "RC5/CBC/WithCTS",
+            "9ee7517eab0280445f3a7c60c90c0f75ace5399d388c83c3029d65bca8b1af83",
+            "RC6/CBC/WithCTS",
+            "d4a96bf4e44f89fd91b46830bc95b130c44695633c07010f3a0d8f7ea046a642",
+            "IDEA/CBC/WithCTS",
+            "30cd990ebdae80fe12b6c6e4fcd1c06497351c8684e4c4d9a27d985c276b3d70",
+            "DES/OFB/NoPadding",
+            "537572e480c1714f5c9a4f3b874df824dc6681b1fd6c11982debcad91e3f78b7",
+            "DESede/OFB/NoPadding",
+            "481e9872acea7fcf8e29a453242da774e5f6a28f15f7723659a73e4ff4939f80",
+            "SKIPJACK/OFB/NoPadding",
+            "71143a124e3a0cde753b60fe9b200e559018b6a0fe0682659f7c13feb9df995c",
+            "Blowfish/OFB/NoPadding",
+            "6cd6f7c5d2c655556d7a9e98a1696d1875e9f1b2fc991e28a2d55b56861e80bd",
+            "Twofish/OFB/NoPadding",
+            "821c54b1b54ae113cf74595eefe10c83b61c9682fc81f92c52f39a3a693f88b8",
+            "RC2/OFB/NoPadding",
+            "0a07cb78537cb04c0c74e28a7b86b80f80acadf87d6ef32792f1a8cf74b39f74",
+            "RC5/OFB/NoPadding",
+            "c62b233df296283b918a2b4cc53a54fbf061850e781b97332ed1bd78b88d9670",
+            "IDEA/OFB/NoPadding",
+            "dd447da3cbdcf81f4053fb446596261cb00a3c49a66085485af5f7c10ba20dad",
+            "DES/OFB8/NoPadding",
+            "53cb5010d189f94cf584e5ff1c4a9d86443c45ddb6fa3c2d1a5dadfcdf01db8a",
+            "DESede/OFB8/NoPadding",
+            "482c0c1ccd0e6d218e1cffb0a295352c2357ffaa673f2257ef5c77b6c04f03b5",
+            "SKIPJACK/OFB8/NoPadding",
+            "719ea1b432b3d2c8011e5aa873f95978420022b5e2c9c1a1c1082cd1f4999da2",
+            "Blowfish/OFB8/NoPadding",
+            "6ca6078755b263f09787d830b6fda7b7748494634bdc73ab68540cf9f6b7eccf",
+            "Twofish/OFB8/NoPadding",
+            "825dcec234ad52253d6e064b0d769bc04b1142435933f4a510ffc20d70095a88",
+            "RC2/OFB8/NoPadding",
+            "0aa26c6f6a820fe7d38da97085995ad62e2e293323a76300fcd4eb572810f7c6",
+            "RC5/OFB8/NoPadding",
+            "c601a9074dbd874f4d3293f6a32d93d9f0a4f5685d8597f0102fcc96d444f976",
+            "IDEA/OFB8/NoPadding",
+            "dd7897b6ced43d060a518bb38d570308b83b4de577eb208130daabf619e9b1fb",
+            "DES/CFB/NoPadding",
+            "537572e480c1714fec3c7424f88d4202219244c5ca8f5e4361d64f08fe747bb2",
+            "DESede/CFB/NoPadding",
+            "481e9872acea7fcfb75bb58670fe64c59123265139e357d161cd4ddb5eba042a",
+            "SKIPJACK/CFB/NoPadding",
+            "71143a124e3a0cde70a69ede4ceb14376b1e6a80bafde0a6330508dfa86a7c41",
+            "Blowfish/CFB/NoPadding",
+            "6cd6f7c5d2c6555561167fe9b10665102206869339122f1ed89efa4a985397f6",
+            "Twofish/CFB/NoPadding",
+            "821c54b1b54ae113cf74595eefe10c8308b7a438277de4f40948ac2d172d53d2",
+            "RC2/CFB/NoPadding",
+            "0a07cb78537cb04ca1401450d5cd411c7da7fa5b6baaa17bb2137bd95c9f26a5",
+            "RC5/CFB/NoPadding",
+            "c62b233df296283b989352bbebf616a19e11503ac737f9e0eaf19049cde05d34",
+            "IDEA/CFB/NoPadding",
+            "dd447da3cbdcf81fcbe4661dcbed88aed899f87585118384bd0565067fa6c13a",
+            "DES/CFB8/NoPadding",
+            "53cb0cdff712a825eb283b23c31e7323aa12495e7e751428b5c4eb89b28a25d4",
+            "DESede/CFB8/NoPadding",
+            "482cd5bf87ca4cee0b573d66a077231bfea93843ce2d1f948550a1d208e18279",
+            "SKIPJACK/CFB8/NoPadding",
+            "719eef3906bef23f7b63599285437d8e34183b165acf3e855b4e160d4f036508",
+            "Blowfish/CFB8/NoPadding",
+            "6ca63aaada9188d2410c07513cc0736b9888770768c25a5befc776beea5bdc4c",
+            "Twofish/CFB8/NoPadding",
+            "825d12af040721cf5ed4a4798647837ac5eb14d752aace28728aeb37b2010abd",
+            "RC2/CFB8/NoPadding",
+            "0aa227f94be3a32ff927c5d25647ea41d7c2a1e94012fc7f2ad6767b9664bce5",
+            "RC5/CFB8/NoPadding",
+            "c601cf88725411f119965b9cd38d6c313b91128ed7c98c7604cc62d9b210be79",
+            "IDEA/CFB8/NoPadding",
+            "dd7839d2525420d10f95eec23dbaf3463302c445972a28c563c2635191bc19af",
+            // TODO Check that PGPCFB modes are obsolete for C# build
+//			"IDEA/PGPCFB/NoPadding",
+//			"dd447da3cbdcf81fcbe4661dcbed88aed899f87585118384bd0565067fa6c13a",
+//			"IDEA/PGPCFBwithIv/NoPadding",
+//			"ed5adbac0e730cc0f00df7e4f6fef672ab042673106435faf3ecf3996a72a0e127b440ba9e5313501de3",
+            "Twofish/ECB/TBCPadding",
+            "70336d9c9718a8a2ced1b19deed973a3c58af7ea71a69e7efc4df082dca581c019d7daa58d02b89aab6e8c0d17202439",
+            "RC2/ECB/TBCPadding",
+            "eb5b889bbcced12eb6b1a3da6a3d965bba66a5edfdd4c8a6b6b1a3da6a3d965b6b5359ba5e69b179"
+        };
+
+        private static readonly string[] cipherTests2 =
+        {
+            "DES/OFB64/NoPadding",
+            "537572e480c1714f5c9a4f3b874df824dc6681b1fd6c11982debcad91e",
+            "DES/CFB64/NoPadding",
+            "537572e480c1714fec3c7424f88d4202219244c5ca8f5e4361d64f08fe",
+            "DES/CTR/NoPadding",
+            "537572e480c1714fb47081d35eb18eaca9e0a5aee982f105438a0db6ce",
+            "DES/CTS/NoPadding",
+            "60fa2f8fae5aa2a38e9ac77d0246726b32df660db51a710ceb7511e451"
+        };
+
+        private static readonly byte[] input1 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
+        private static readonly byte[] input2 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c");
+
+//		static RC2ParameterSpec rc2Spec = new RC2ParameterSpec(128, Hex.decode("0123456789abcdef"));
+        private static readonly byte[] rc2IV = Hex.Decode("0123456789abcdef");
+
+//		static RC5ParameterSpec rc5Spec = new RC5ParameterSpec(16, 16, 32, Hex.decode("0123456789abcdef"));
+//		static RC5ParameterSpec rc564Spec = new RC5ParameterSpec(16, 16, 64, Hex.decode("0123456789abcdef0123456789abcdef"));
+        private static readonly byte[] rc5IV = Hex.Decode("0123456789abcdef");
+        private static readonly byte[] rc564IV = Hex.Decode("0123456789abcdef0123456789abcdef");
+        private const int rc5Rounds = 16;
+
+        /**
+        * a fake random number generator - we just want to make sure the random numbers
+        * aren't random so that we get the same output, while still getting to test the
+        * key generation facilities.
+        */
+        private class FixedSecureRandom
+            : SecureRandom
+        {
+            byte[] seed = {
+                    (byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+                    (byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+                    (byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+                    (byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+            };
+
+            public override void NextBytes(
+                byte[] bytes)
+            {
+                int offset = 0;
+
+                while ((offset + seed.Length) < bytes.Length)
+                {
+                    Array.Copy(seed, 0, bytes, offset, seed.Length);
+                    offset += seed.Length;
+                }
+
+                Array.Copy(seed, 0, bytes, offset, bytes.Length- offset);
+            }
+        }
+
+        public override string Name
+        {
+            get { return "BlockCipher"; }
+        }
+
+        private int GetIVLength(
+            string algorithm)
+        {
+            string[] parts = algorithm.Split('/');
+
+            if (parts.Length < 2)
+                return 0;
+
+            string mode = parts[1];
+
+            int pos = mode.IndexOfAny(new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' });
+            string baseMode = pos < 0 ? mode : mode.Substring(0, pos);
+
+            if (!validModes.Contains(baseMode))
+                throw new Exception("Unhandled mode: " + mode);
+
+            if (baseMode == "ECB")
+                return 0;
+
+            string baseAlgorithm = parts[0];
+            IBufferedCipher baseCipher = CipherUtilities.GetCipher(baseAlgorithm);
+            return baseCipher.GetBlockSize();
+        }
+
+        private void doTest(
+            string	algorithm,
+            byte[]	input,
+            byte[]	output)
+        {
+            KeyParameter key = null;
+            CipherKeyGenerator keyGen;
+            SecureRandom rand;
+            IBufferedCipher inCipher = null, outCipher = null;
+            byte[] iv = null;
+            CipherStream cIn, cOut;
+            MemoryStream bIn, bOut;
+
+            rand = new FixedSecureRandom();
+
+            string[] parts = algorithm.ToUpper(CultureInfo.InvariantCulture).Split('/');
+            string baseAlgorithm = parts[0];
+            string mode = parts.Length > 1 ? parts[1] : null;
+
+            try
+            {
+                keyGen = GeneratorUtilities.GetKeyGenerator(baseAlgorithm);
+
+                // TODO Add Algorithm property to CipherKeyGenerator?
+//				if (!keyGen.getAlgorithm().Equals(baseAlgorithm))
+//				{
+//					Fail("wrong key generator returned!");
+//				}
+
+                // TODO Add new Init method to CipherKeyGenerator?
+//				keyGen.Init(rand);
+                keyGen.Init(new KeyGenerationParameters(rand, keyGen.DefaultStrength));
+
+                byte[] keyBytes = keyGen.GenerateKey();
+
+                if (algorithm.StartsWith("RC5"))
+                {
+                    key = new RC5Parameters(keyBytes, rc5Rounds);
+                }
+                else
+                {
+                    key = ParameterUtilities.CreateKeyParameter(baseAlgorithm, keyBytes);
+                }
+
+                inCipher = CipherUtilities.GetCipher(algorithm);
+                outCipher = CipherUtilities.GetCipher(algorithm);
+
+                if (!inCipher.AlgorithmName.ToUpper(CultureInfo.InvariantCulture).StartsWith(baseAlgorithm))
+                {
+                    Fail("wrong cipher returned!");
+                }
+
+                ICipherParameters parameters = key;
+
+                int ivLength = GetIVLength(algorithm);
+
+                if (ivLength > 0)
+                {
+                    if (baseAlgorithm == "RC2")
+                    {
+                        iv = rc2IV;
+                    }
+                    else if (baseAlgorithm == "RC5")
+                    {
+                        iv = rc5IV;
+                    }
+                    else if (baseAlgorithm == "RC5-64")
+                    {
+                        iv = rc564IV;
+                    }
+                    else
+                    {
+                        // NB: rand always generates same values each test run
+                        iv = rand.GenerateSeed(ivLength);
+                    }
+
+                    parameters = new ParametersWithIV(key, iv);
+                }
+
+                // NB: 'rand' still needed e.g. for some paddings
+                parameters = new ParametersWithRandom(parameters, rand);
+
+                outCipher.Init(true, parameters);
+            }
+            catch (Exception e)
+            {
+                Fail("" + algorithm + " failed initialisation - " + e.ToString(), e);
+            }
+
+            //
+            // grab the iv if there is one
+            //
+            try
+            {
+                // The Java version set this implicitly, but we set it explicity
+                //byte[] iv = outCipher.getIV();
+
+                if (iv != null)
+                {
+                    // TODO Examine short IV handling for these FIPS-compliant modes in Java build
+                    if (mode.StartsWith("CFB")
+                        || mode.StartsWith("GOFB")
+                        || mode.StartsWith("OFB")
+                        || mode.StartsWith("OPENPGPCFB"))
+                    {
+                        // These modes automatically pad out the IV if it is short
+                    }
+                    else
+                    {
+                        try
+                        {
+                            byte[] nIv = new byte[iv.Length- 1];
+                            inCipher.Init(false, new ParametersWithIV(key, nIv));
+                            Fail("failed to pick up short IV");
+                        }
+                        //catch (InvalidAlgorithmParameterException e)
+                        catch (ArgumentException)
+                        {
+                            // ignore - this is what we want...
+                        }
+                    }
+
+                    //IvParameterSpec spec = new IvParameterSpec(iv);
+                    inCipher.Init(false, new ParametersWithIV(key, iv));
+                }
+                else
+                {
+                    inCipher.Init(false, key);
+                }
+            }
+            catch (Exception e)
+            {
+                Fail("" + algorithm + " failed initialisation - " + e.ToString());
+            }
+
+            //
+            // encryption pass
+            //
+            bOut = new MemoryStream();
+            cOut = new CipherStream(bOut, null, outCipher);
+
+            try
+            {
+                for (int i = 0; i != input.Length/ 2; i++)
+                {
+                    cOut.WriteByte(input[i]);
+                }
+                cOut.Write(input, input.Length/ 2, input.Length- input.Length/ 2);
+                cOut.Close();
+            }
+            catch (IOException e)
+            {
+                Fail("" + algorithm + " failed encryption - " + e.ToString());
+            }
+
+            byte[] bytes = bOut.ToArray();
+
+            if (!AreEqual(bytes, output))
+            {
+                Fail("" + algorithm + " failed encryption - expected "
+                    + Hex.ToHexString(output) + " got "
+                    + Hex.ToHexString(bytes));
+            }
+
+            //
+            // decryption pass
+            //
+            bIn = new MemoryStream(bytes, false);
+            cIn = new CipherStream(bIn, inCipher, null);
+
+            try
+            {
+                BinaryReader dIn = new BinaryReader(cIn);
+
+                bytes = new byte[input.Length];
+
+                for (int i = 0; i != input.Length/ 2; i++)
+                {
+                    bytes[i] = dIn.ReadByte();
+                }
+
+                int remaining = bytes.Length - input.Length / 2;
+                byte[] extra = dIn.ReadBytes(remaining);
+                if (extra.Length < remaining)
+                    throw new EndOfStreamException();
+                extra.CopyTo(bytes, input.Length / 2);
+            }
+            catch (Exception e)
+            {
+                Fail("" + algorithm + " failed decryption - " + e.ToString());
+            }
+
+            if (!AreEqual(bytes, input))
+            {
+                Fail("" + algorithm + " failed decryption - expected "
+                    + Hex.ToHexString(input) + " got "
+                    + Hex.ToHexString(bytes));
+            }
+        }
+
+        // TODO Make private again and call from PerformTest
+        public void doTestExceptions()
+        {
+            // TODO Put back in
+//			SecretKeyFactory skF = null;
+//	        
+//			try
+//			{
+//				skF = SecretKeyFactory.getInstance("DESede");
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+//	        
+//			KeySpec ks = null;
+//			SecretKey secKey = null;
+//			byte[] bb = new byte[24];
+//
+//			try
+//			{
+//				skF.getKeySpec(null, null);
+//	            
+//				Fail("failed exception test - no exception thrown");
+//			}
+//			catch (InvalidKeySpecException e)
+//			{
+//				// ignore okay
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("failed exception test.", e);
+//			}
+//			try
+//			{
+//				ks = (KeySpec)new DESedeKeySpec(bb);
+//				skF.getKeySpec(null, ks.getClass());
+//	            
+//				Fail("failed exception test - no exception thrown");
+//			}
+//			catch (InvalidKeySpecException e)
+//			{
+//				// ignore okay;
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("failed exception test.", e);
+//			}
+//			try
+//			{
+//				skF.getKeySpec(secKey, null);
+//			}
+//			catch (InvalidKeySpecException e)
+//			{
+//				// ignore okay
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("failed exception test.", e);
+//			}
+            
+            try
+            {
+                CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator("DESede");
+
+                try
+                {
+                    kg.Init(new KeyGenerationParameters(new SecureRandom(), int.MinValue));
+
+                    Fail("failed exception test - no exception thrown");
+                }
+//				catch (InvalidParameterException)
+                catch (ArgumentException)
+                {
+                    // ignore okay
+                }
+                catch (Exception e)
+                {
+                    Fail("failed exception test.", e);
+                }
+            }
+            catch (Exception e)
+            {
+                Fail("unexpected exception.", e);
+            }
+
+            // TODO Put back in
+//			try
+//			{
+//				skF = SecretKeyFactory.getInstance("DESede");
+//
+//				try
+//				{
+//					skF.translateKey(null);
+//	                
+//					Fail("failed exception test - no exception thrown");
+//				}
+//				catch (InvalidKeyException)
+//				{
+//					// ignore okay
+//				}
+//				catch (Exception e)
+//				{
+//					Fail("failed exception test.", e);
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+            
+//			try
+//			{
+//				byte[] rawDESKey = { (byte)128, (byte)131, (byte)133, (byte)134,
+//						(byte)137, (byte)138, (byte)140, (byte)143 };
+//
+////				SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES");
+//				KeyParameter cipherKey = new DesParameters(rawDESKey);
+//
+//				IBufferedCipher cipher = CipherUtilities.GetCipher("DES/CBC/NoPadding");
+//
+//				try
+//				{
+//					// According specification engineInit(int opmode, Key key,
+//					// SecureRandom random) throws InvalidKeyException if this
+//					// cipher is being
+//					// initialized for decryption and requires algorithm parameters
+//					// that cannot be determined from the given key
+////					cipher.Init(false, cipherKey, (SecureRandom)null);
+//					cipher.Init(false, new ParametersWithRandom(cipherKey, new SecureRandom()));
+//
+//					Fail("failed exception test - no InvalidKeyException thrown");
+//				}
+//				catch (InvalidKeyException)
+//				{
+//					// ignore
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+
+            try
+            {
+//				byte[] rawDESKey = { -128, -125, -123, -122, -119, -118 };
+                byte[] rawDESKey = { 128, 131, 133, 134, 137, 138 };
+
+//				SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES");
+
+//				IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/NoPadding");
+                try
+                {
+                    KeyParameter cipherKey = new DesParameters(rawDESKey);
+
+                    // According specification engineInit(int opmode, Key key,
+                    // SecureRandom random) throws InvalidKeyException if the given
+                    // key is inappropriate for initializing this cipher
+//					cipher.Init(true, cipherKey);
+
+//					Fail("failed exception test - no InvalidKeyException thrown");
+                    Fail("failed exception test - no ArgumentException thrown");
+                }
+//				catch (InvalidKeyException)
+                catch (ArgumentException)
+                {
+                    // ignore
+                }
+            }
+            catch (Exception e)
+            {
+                Fail("unexpected exception.", e);
+            }
+
+//			try
+//			{
+////				byte[] rawDESKey = { -128, -125, -123, -122, -119, -118, -117, -115, -114 };
+//				byte[] rawDESKey = { 128, 131, 133, 134, 137, 138, 139, 141, 142 };
+//
+////				SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES");
+//				KeyParameter cipherKey = new DesParameters(rawDESKey);
+//
+//				IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/NoPadding");
+//				try
+//				{
+//					// According specification engineInit(int opmode, Key key,
+//					// SecureRandom random) throws InvalidKeyException if the given
+//					// key is inappropriate for initializing this cipher
+//					cipher.Init(true, cipherKey);
+//	                
+//					Fail("failed exception test - no InvalidKeyException thrown");
+//				}
+//				catch (InvalidKeyException)
+//				{
+//					// ignore
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+
+
+            try
+            {
+                byte[] rawDESKey = { (byte)128, (byte)131, (byte)133, (byte)134,
+                    (byte)137, (byte)138, (byte)140, (byte)143 };
+
+//				SecretKeySpec cipherKey = new SecretKeySpec(rawDESKey, "DES");
+                KeyParameter cipherKey = new DesParameters(rawDESKey);
+
+                IBufferedCipher ecipher = CipherUtilities.GetCipher("DES/ECB/PKCS5Padding");
+                ecipher.Init(true, cipherKey);
+
+                byte[] cipherText = new byte[0];
+                try
+                {
+                    // According specification Method engineUpdate(byte[] input,
+                    // int inputOffset, int inputLen, byte[] output, int
+                    // outputOffset)
+                    // throws ShortBufferException - if the given output buffer is
+                    // too
+                    // small to hold the result
+//					ecipher.update(new byte[20], 0, 20, cipherText);
+                    ecipher.ProcessBytes(new byte[20], 0, 20, cipherText, 0);
+
+//					Fail("failed exception test - no ShortBufferException thrown");
+                    Fail("failed exception test - no DataLengthException thrown");
+                }
+//				catch (ShortBufferException)
+                catch (DataLengthException)
+                {
+                    // ignore
+                }
+            }
+            catch (Exception e)
+            {
+                Fail("unexpected exception.", e);
+            }
+
+            // TODO Put back in
+//			try
+//			{
+//				KeyGenerator keyGen = KeyGenerator.getInstance("DES");
+//
+//				keyGen.init((SecureRandom)null);
+//
+//				// According specification engineGenerateKey() doesn't throw any exceptions.
+//
+//				SecretKey key = keyGen.generateKey();
+//				if (key == null)
+//				{
+//					Fail("key is null!");
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+//
+//			try
+//			{
+//				AlgorithmParameters algParams = AlgorithmParameters.getInstance("DES");
+//	            
+//				algParams.init(new IvParameterSpec(new byte[8]));
+//
+//				// According specification engineGetEncoded() returns
+//				// the parameters in their primary encoding format. The primary
+//				// encoding
+//				// format for parameters is ASN.1, if an ASN.1 specification for
+//				// this type
+//				// of parameters exists.
+//				byte[] iv = algParams.getEncoded();
+//	            
+//				if (iv.Length!= 10)
+//				{
+//					Fail("parameters encoding wrong length - "  + iv.Length);
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("unexpected exception.", e);
+//			}
+
+            try
+            {
+                try
+                {
+//					AlgorithmParameters algParams = AlgorithmParameters.getInstance("DES");
+
+                    byte[] encoding = new byte[10];
+                    encoding[0] = 3;
+                    encoding[1] = 8;
+
+//					algParams.init(encoding, "ASN.1");
+                    ParameterUtilities.GetCipherParameters(
+                        "AES",
+                        ParameterUtilities.CreateKeyParameter("AES", new byte[16]),
+                        Asn1Object.FromByteArray(encoding));
+
+//					Fail("failed exception test - no IOException thrown");
+                    Fail("failed exception test - no Exception thrown");
+                }
+//				catch (IOException)
+                catch (ArgumentException)
+                {
+                    // okay
+                }
+
+//				try
+//				{
+//					IBufferedCipher c = CipherUtilities.GetCipher("DES");
+//
+//					Key k = new PublicKey()
+//					{
+//
+//						public string getAlgorithm()
+//						{
+//							return "STUB";
+//						}
+//
+//						public string getFormat()
+//						{
+//							return null;
+//						}
+//
+//						public byte[] getEncoded()
+//						{
+//							return null;
+//						}
+//	                    
+//					};
+//	    
+//					c.Init(true, k);
+//	    
+//					Fail("failed exception test - no InvalidKeyException thrown for public key");
+//				}
+//				catch (InvalidKeyException e)
+//				{
+//					// okay
+//				}
+//	            
+//				try
+//				{
+//					IBufferedCipher c = CipherUtilities.GetCipher("DES");
+//	    
+//					Key k = new PrivateKey()
+//					{
+//
+//						public string getAlgorithm()
+//						{
+//							return "STUB";
+//						}
+//
+//						public string getFormat()
+//						{
+//							return null;
+//						}
+//
+//						public byte[] getEncoded()
+//						{
+//							return null;
+//						}
+//	                    
+//					};
+//	    
+//					c.Init(false, k);
+//	    
+//					Fail("failed exception test - no InvalidKeyException thrown for private key");
+//				}
+//				catch (InvalidKeyException e)
+//				{
+//					// okay
+//				}
+            }
+            catch (Exception e)
+            {
+                Fail("unexpected exception.", e);
+            }
+        }
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i != cipherTests1.Length; i += 2)
+            {
+                doTest(cipherTests1[i], input1, Hex.Decode(cipherTests1[i + 1]));
+            }
+
+            for (int i = 0; i != cipherTests2.Length; i += 2)
+            {
+                doTest(cipherTests2[i], input2, Hex.Decode(cipherTests2[i + 1]));
+            }
+
+            //
+            // check for less than a block
+            //
+            try
+            {
+                IBufferedCipher c = CipherUtilities.GetCipher("AES/CTS/NoPadding");
+
+                c.Init(true, ParameterUtilities.CreateKeyParameter("AES", new byte[16]));
+
+                c.DoFinal(new byte[4]);
+
+                Fail("CTS failed to throw exception");
+            }
+            catch (Exception e)
+            {
+//				if (!(e is IllegalBlockSizeException))
+                if (!(e is DataLengthException))
+                {
+                    Fail("CTS exception test - " + e, e);
+                }
+            }
+
+            doTestExceptions();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new BlockCipherTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CMacTest.cs b/BouncyCastle.AxCrypt/test/src/test/CMacTest.cs
new file mode 100644
index 0000000..f80caca
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CMacTest.cs
@@ -0,0 +1,276 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/**
+	 * CMAC tester - <a href="http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/tv/omac1-tv.txt">AES Official Test Vectors</a>.
+	 */
+	[TestFixture]
+	public class CMacTest
+		:	SimpleTest
+	{
+		private static readonly byte[] keyBytes128 = Hex.Decode("2b7e151628aed2a6abf7158809cf4f3c");
+		private static readonly byte[] keyBytes192 = Hex.Decode(
+			  "8e73b0f7da0e6452c810f32b809079e5"
+			+ "62f8ead2522c6b7b");
+		private static readonly byte[] keyBytes256 = Hex.Decode(
+			  "603deb1015ca71be2b73aef0857d7781"
+			+ "1f352c073b6108d72d9810a30914dff4");
+		
+		private static readonly byte[] input0 = Hex.Decode("");
+		private static readonly byte[] input16 = Hex.Decode("6bc1bee22e409f96e93d7e117393172a");
+		private static readonly byte[] input40 = Hex.Decode(
+			  "6bc1bee22e409f96e93d7e117393172a"
+			+ "ae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411");
+		private static readonly byte[] input64 = Hex.Decode(
+			  "6bc1bee22e409f96e93d7e117393172a"
+			+ "ae2d8a571e03ac9c9eb76fac45af8e51"
+			+ "30c81c46a35ce411e5fbc1191a0a52ef"
+			+ "f69f2445df4f9b17ad2b417be66c3710");
+
+		private static readonly byte[] output_k128_m0 = Hex.Decode("bb1d6929e95937287fa37d129b756746");
+		private static readonly byte[] output_k128_m16 = Hex.Decode("070a16b46b4d4144f79bdd9dd04a287c");
+		private static readonly byte[] output_k128_m40 = Hex.Decode("dfa66747de9ae63030ca32611497c827");
+		private static readonly byte[] output_k128_m64 = Hex.Decode("51f0bebf7e3b9d92fc49741779363cfe");
+
+		private static readonly byte[] output_k192_m0 = Hex.Decode("d17ddf46adaacde531cac483de7a9367");
+		private static readonly byte[] output_k192_m16 = Hex.Decode("9e99a7bf31e710900662f65e617c5184");
+		private static readonly byte[] output_k192_m40 = Hex.Decode("8a1de5be2eb31aad089a82e6ee908b0e");
+		private static readonly byte[] output_k192_m64 = Hex.Decode("a1d5df0eed790f794d77589659f39a11");
+
+		private static readonly byte[] output_k256_m0 = Hex.Decode("028962f61b7bf89efc6b551f4667d983");
+		private static readonly byte[] output_k256_m16 = Hex.Decode("28a7023f452e8f82bd4bf28d8c37c35c");
+		private static readonly byte[] output_k256_m40 = Hex.Decode("aaf3d8f1de5640c232f5b169b9c911e6");
+		private static readonly byte[] output_k256_m64 = Hex.Decode("e1992190549f6ed5696a2c056c315410");
+
+		private static readonly byte[] output_des_ede = Hex.Decode("1ca670dea381d37c");
+
+		public CMacTest()
+		{
+		}
+		
+		public override void PerformTest()
+		{
+//			Mac mac = Mac.getInstance("AESCMAC", "BC");
+			IMac mac = MacUtilities.GetMac("AESCMAC");
+
+			//128 bytes key
+
+//			SecretKeySpec key = new SecretKeySpec(keyBytes128, "AES");
+			KeyParameter key = new KeyParameter(keyBytes128);
+
+			// 0 bytes message - 128 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input0, 0, input0.Length);
+
+			byte[] output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k128_m0))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k128_m0)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 16 bytes message - 128 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input16, 0, input16.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k128_m16))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k128_m16)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 40 bytes message - 128 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input40, 0, input40.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k128_m40))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k128_m40)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 64 bytes message - 128 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input64, 0, input64.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k128_m64))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k128_m64)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			//192 bytes key
+
+//			key = new SecretKeySpec(keyBytes192, "AES");
+			key = new KeyParameter(keyBytes192);
+
+			// 0 bytes message - 192 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input0, 0, input0.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k192_m0))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k192_m0)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 16 bytes message - 192 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input16, 0, input16.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k192_m16))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k192_m16)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 40 bytes message - 192 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input40, 0, input40.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k192_m40))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k192_m40)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 64 bytes message - 192 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input64, 0, input64.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k192_m64))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k192_m64)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			//256 bytes key
+
+//			key = new SecretKeySpec(keyBytes256, "AES");
+			key = new KeyParameter(keyBytes256);
+
+			// 0 bytes message - 256 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input0, 0, input0.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k256_m0))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k256_m0)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 16 bytes message - 256 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input16, 0, input16.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k256_m16))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k256_m16)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 40 bytes message - 256 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input40, 0, input40.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k256_m40))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k256_m40)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+			// 64 bytes message - 256 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input64, 0, input64.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_k256_m64))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_k256_m64)
+					+ " got " + Hex.ToHexString(output));
+			}
+
+//			mac = Mac.getInstance("DESedeCMAC", "BC");
+			mac = MacUtilities.GetMac("DESedeCMAC");
+
+			//DESede
+			
+//			key = new SecretKeySpec(keyBytes128, "DESede");
+			key = new KeyParameter(keyBytes128);
+
+			// 0 bytes message - 128 bytes key
+			mac.Init(key);
+
+			mac.BlockUpdate(input0, 0, input0.Length);
+
+			output = MacUtilities.DoFinal(mac);
+
+			if (!AreEqual(output, output_des_ede))
+			{
+				Fail("Failed - expected " + Hex.ToHexString(output_des_ede)
+					+ " got " + Hex.ToHexString(output));
+			}
+		}
+
+		public override string Name
+		{
+			get { return "CMac"; }
+		}
+
+		public static void Main(string[] args)
+		{
+			RunTest(new CMacTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CRL5Test.cs b/BouncyCastle.AxCrypt/test/src/test/CRL5Test.cs
new file mode 100644
index 0000000..ebd74af
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CRL5Test.cs
@@ -0,0 +1,257 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class Crl5Test
+		: SimpleTest
+	{
+		private static readonly byte[] indirectCrl = Base64.Decode(
+			"MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV"
+			+"BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0"
+			+"MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO"
+			+"Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3"
+			+"MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0"
+			+"MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/jFw0wMzAx"
+			+"MTMxMTI2NTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+QXDTAzMDExMzExMjY1NlowZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/4hcNMDQwNzEzMDc1ODM4WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/eFw0wMzAy"
+			+"MTcwNjMzMjVaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP98XDTAzMDIxNzA2MzMyNVowZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/0xcNMDMwMjE3MDYzMzI1WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/dFw0wMzAx"
+			+"MTMxMTI4MTRaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9cXDTAzMDExMzExMjcwN1owZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/2BcNMDMwMTEzMTEyNzA3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/VFw0wMzA0"
+			+"MzAxMjI3NTNaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+			+"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+			+"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9YXDTAzMDQzMDEyMjc1M1owZzBlBgNV"
+			+"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+			+"UE4wfgIEL64/xhcNMDMwMjEyMTM0NTQwWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+			+"BgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQTjCBkAIEL64/xRcNMDMw"
+			+"MjEyMTM0NTQwWjB5MHcGA1UdHQEB/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoG"
+			+"A1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwG"
+			+"BwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNTpQTjB+AgQvrj/CFw0w"
+			+"MzAyMTIxMzA5MTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRww"
+			+"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNV"
+			+"BAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj/BFw0wMzAyMTIxMzA4NDBaMHkw"
+			+"dwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No"
+			+"ZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAY"
+			+"BgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uP74XDTAzMDIxNzA2MzcyNVow"
+			+"ZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz"
+			+"Y2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3Qg"
+			+"Q0EgMTE6UE4wgZACBC+uP70XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0BAf8EbTBr"
+			+"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx"
+			+"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU"
+			+"ZXN0IENBIDU6UE4wgZACBC+uP7AXDTAzMDIxMjEzMDg1OVoweTB3BgNVHR0BAf8E"
+			+"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+			+"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln"
+			+"RyBUZXN0IENBIDU6UE4wgZACBC+uP68XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0B"
+			+"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr"
+			+"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR"
+			+"U2lnRyBUZXN0IENBIDU6UE4wfgIEL64/kxcNMDMwNDEwMDUyNjI4WjBnMGUGA1Ud"
+			+"HQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVs"
+			+"ZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQ"
+			+"TjCBkAIEL64/khcNMDMwNDEwMDUyNjI4WjB5MHcGA1UdHQEB/wRtMGukaTBnMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UE"
+			+"CxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0Eg"
+			+"NTpQTjB+AgQvrj8/Fw0wMzAyMjYxMTA0NDRaMGcwZQYDVR0dAQH/BFswWaRXMFUx"
+			+"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYH"
+			+"AoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj8+Fw0w"
+			+"MzAyMjYxMTA0NDRaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRww"
+			+"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgw"
+			+"DAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uPs0X"
+			+"DTAzMDUyMDA1MjczNlowZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUx"
+			+"HDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgG"
+			+"A1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZACBC+uPswXDTAzMDUyMDA1MjczNlow"
+			+"eTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz"
+			+"Y2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwEx"
+			+"MBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4wfgIEL64+PBcNMDMwNjE3MTAzNDE2"
+			+"WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1"
+			+"dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVz"
+			+"dCBDQSAxMTpQTjCBkAIEL64+OxcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB/wRt"
+			+"MGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBB"
+			+"RzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdH"
+			+"IFRlc3QgQ0EgNjpQTjCBkAIEL64+OhcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB"
+			+"/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtv"
+			+"bSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFT"
+			+"aWdHIFRlc3QgQ0EgNjpQTjB+AgQvrj45Fw0wMzA2MTcxMzAxMDBaMGcwZQYDVR0d"
+			+"AQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxl"
+			+"a29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBO"
+			+"MIGQAgQvrj44Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJ"
+			+"BgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQL"
+			+"FAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA2"
+			+"OlBOMIGQAgQvrj43Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcx"
+			+"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYD"
+			+"VQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBD"
+			+"QSA2OlBOMIGQAgQvrj42Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6Rp"
+			+"MGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAw"
+			+"DgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVz"
+			+"dCBDQSA2OlBOMIGQAgQvrj4zFw0wMzA2MTcxMDM3NDlaMHkwdwYDVR0dAQH/BG0w"
+			+"a6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH"
+			+"MRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cg"
+			+"VGVzdCBDQSA2OlBOMH4CBC+uPjEXDTAzMDYxNzEwNDI1OFowZzBlBgNVHR0BAf8E"
+			+"WzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+			+"QUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZAC"
+			+"BC+uPjAXDTAzMDYxNzEwNDI1OFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UE"
+			+"BhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1Rl"
+			+"bGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4w"
+			+"gZACBC+uPakXDTAzMTAyMjExMzIyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkG"
+			+"A1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsU"
+			+"B1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6"
+			+"UE4wgZACBC+uPLIXDTA1MDMxMTA2NDQyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzEL"
+			+"MAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNV"
+			+"BAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENB"
+			+"IDY6UE4wgZACBC+uPKsXDTA0MDQwMjA3NTQ1M1oweTB3BgNVHR0BAf8EbTBrpGkw"
+			+"ZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAO"
+			+"BgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0"
+			+"IENBIDY6UE4wgZACBC+uOugXDTA1MDEyNzEyMDMyNFoweTB3BgNVHR0BAf8EbTBr"
+			+"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx"
+			+"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU"
+			+"ZXN0IENBIDY6UE4wgZACBC+uOr4XDTA1MDIxNjA3NTcxNloweTB3BgNVHR0BAf8E"
+			+"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+			+"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln"
+			+"RyBUZXN0IENBIDY6UE4wgZACBC+uOqcXDTA1MDMxMDA1NTkzNVoweTB3BgNVHR0B"
+			+"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr"
+			+"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR"
+			+"U2lnRyBUZXN0IENBIDY6UE4wgZACBC+uOjwXDTA1MDUxMTEwNDk0NloweTB3BgNV"
+			+"HR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+			+"bGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UE"
+			+"AxQRU2lnRyBUZXN0IENBIDY6UE4wgaoCBC+sbdUXDTA1MTExMTEwMDMyMVowgZIw"
+			+"gY8GA1UdHQEB/wSBhDCBgaR/MH0xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0"
+			+"c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj"
+			+"MS8wDAYHAoIGAQoHFBMBMTAfBgNVBAMUGFRlbGVTZWMgUEtTIFNpZ0cgQ0EgMTpQ"
+			+"TjCBlQIEL64uaBcNMDYwMTIzMTAyNTU1WjB+MHwGA1UdHQEB/wRyMHCkbjBsMQsw"
+			+"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEWMBQGA1UE"
+			+"CxQNWmVudHJhbGUgQm9ubjEnMAwGBwKCBgEKBxQTATEwFwYDVQQDFBBUVEMgVGVz"
+			+"dCBDQSA5OlBOMIGVAgQvribHFw0wNjA4MDEwOTQ4NDRaMH4wfAYDVR0dAQH/BHIw"
+			+"cKRuMGwxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH"
+			+"MRYwFAYDVQQLFA1aZW50cmFsZSBCb25uMScwDAYHAoIGAQoHFBMBMTAXBgNVBAMU"
+			+"EFRUQyBUZXN0IENBIDk6UE6ggZswgZgwCwYDVR0UBAQCAhEMMB8GA1UdIwQYMBaA"
+			+"FANbyNumDI9545HwlCF26NuOJC45MA8GA1UdHAEB/wQFMAOEAf8wVwYDVR0SBFAw"
+			+"ToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1ULVRlbGVTZWMgVGVzdCBESVIg"
+			+"ODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1kZTANBgkqhkiG9w0BAQUFAAOB"
+			+"gQBewL5gLFHpeOWO07Vk3Gg7pRDuAlvaovBH4coCyCWpk5jEhUfFSYEDuaQB7do4"
+			+"IlJmeTHvkI0PIZWJ7bwQ2PVdipPWDx0NVwS/Cz5jUKiS3BbAmZQZOueiKLFpQq3A"
+			+"b8aOHA7WHU4078/1lM+bgeu33Ln1CGykEbmSjA/oKPi/JA==");
+
+		private static readonly byte[] directCrl = Base64.Decode(
+			"MIIGXTCCBckCAQEwCgYGKyQDAwECBQAwdDELMAkGA1UEBhMCREUxHDAaBgNVBAoU"
+			+"E0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0MS4w"
+			+"DAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBOFw0w"
+			+"NjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIElTAVAgQvrj/pFw0wMzA3MjIw"
+			+"NTQxMjhaMBUCBC+uP+oXDTAzMDcyMjA1NDEyOFowFQIEL64/5xcNMDQwNDA1MTMx"
+			+"ODE3WjAVAgQvrj/oFw0wNDA0MDUxMzE4MTdaMBUCBC+uP+UXDTAzMDExMzExMTgx"
+			+"MVowFQIEL64/5hcNMDMwMTEzMTExODExWjAVAgQvrj/jFw0wMzAxMTMxMTI2NTZa"
+			+"MBUCBC+uP+QXDTAzMDExMzExMjY1NlowFQIEL64/4hcNMDQwNzEzMDc1ODM4WjAV"
+			+"AgQvrj/eFw0wMzAyMTcwNjMzMjVaMBUCBC+uP98XDTAzMDIxNzA2MzMyNVowFQIE"
+			+"L64/0xcNMDMwMjE3MDYzMzI1WjAVAgQvrj/dFw0wMzAxMTMxMTI4MTRaMBUCBC+u"
+			+"P9cXDTAzMDExMzExMjcwN1owFQIEL64/2BcNMDMwMTEzMTEyNzA3WjAVAgQvrj/V"
+			+"Fw0wMzA0MzAxMjI3NTNaMBUCBC+uP9YXDTAzMDQzMDEyMjc1M1owFQIEL64/xhcN"
+			+"MDMwMjEyMTM0NTQwWjAVAgQvrj/FFw0wMzAyMTIxMzQ1NDBaMBUCBC+uP8IXDTAz"
+			+"MDIxMjEzMDkxNlowFQIEL64/wRcNMDMwMjEyMTMwODQwWjAVAgQvrj++Fw0wMzAy"
+			+"MTcwNjM3MjVaMBUCBC+uP70XDTAzMDIxNzA2MzcyNVowFQIEL64/sBcNMDMwMjEy"
+			+"MTMwODU5WjAVAgQvrj+vFw0wMzAyMTcwNjM3MjVaMBUCBC+uP5MXDTAzMDQxMDA1"
+			+"MjYyOFowFQIEL64/khcNMDMwNDEwMDUyNjI4WjAVAgQvrj8/Fw0wMzAyMjYxMTA0"
+			+"NDRaMBUCBC+uPz4XDTAzMDIyNjExMDQ0NFowFQIEL64+zRcNMDMwNTIwMDUyNzM2"
+			+"WjAVAgQvrj7MFw0wMzA1MjAwNTI3MzZaMBUCBC+uPjwXDTAzMDYxNzEwMzQxNlow"
+			+"FQIEL64+OxcNMDMwNjE3MTAzNDE2WjAVAgQvrj46Fw0wMzA2MTcxMDM0MTZaMBUC"
+			+"BC+uPjkXDTAzMDYxNzEzMDEwMFowFQIEL64+OBcNMDMwNjE3MTMwMTAwWjAVAgQv"
+			+"rj43Fw0wMzA2MTcxMzAxMDBaMBUCBC+uPjYXDTAzMDYxNzEzMDEwMFowFQIEL64+"
+			+"MxcNMDMwNjE3MTAzNzQ5WjAVAgQvrj4xFw0wMzA2MTcxMDQyNThaMBUCBC+uPjAX"
+			+"DTAzMDYxNzEwNDI1OFowFQIEL649qRcNMDMxMDIyMTEzMjI0WjAVAgQvrjyyFw0w"
+			+"NTAzMTEwNjQ0MjRaMBUCBC+uPKsXDTA0MDQwMjA3NTQ1M1owFQIEL6466BcNMDUw"
+			+"MTI3MTIwMzI0WjAVAgQvrjq+Fw0wNTAyMTYwNzU3MTZaMBUCBC+uOqcXDTA1MDMx"
+			+"MDA1NTkzNVowFQIEL646PBcNMDUwNTExMTA0OTQ2WjAVAgQvrG3VFw0wNTExMTEx"
+			+"MDAzMjFaMBUCBC+uLmgXDTA2MDEyMzEwMjU1NVowFQIEL64mxxcNMDYwODAxMDk0"
+			+"ODQ0WqCBijCBhzALBgNVHRQEBAICEQwwHwYDVR0jBBgwFoAUA1vI26YMj3njkfCU"
+			+"IXbo244kLjkwVwYDVR0SBFAwToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1U"
+			+"LVRlbGVTZWMgVGVzdCBESVIgODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1k"
+			+"ZTAKBgYrJAMDAQIFAAOBgQArj4eMlbAwuA2aS5O4UUUHQMKKdK/dtZi60+LJMiMY"
+			+"ojrMIf4+ZCkgm1Ca0Cd5T15MJxVHhh167Ehn/Hd48pdnAP6Dfz/6LeqkIHGWMHR+"
+			+"z6TXpwWB+P4BdUec1ztz04LypsznrHcLRa91ixg9TZCb1MrOG+InNhleRs1ImXk8"
+			+"MQ==");
+
+		public override string Name
+		{
+			get { return "CRL5"; }
+		}
+
+		[Test]
+		public void TestIndirectCrl()
+		{
+			X509Crl crl = new X509CrlParser().ReadCrl(indirectCrl);
+
+			foreach (X509CrlEntry crlEntry in crl.GetRevokedCertificates())
+			{
+				if (crlEntry.GetCertificateIssuer() == null)
+				{
+					Fail("certificate issuer CRL entry extension is null");
+				}
+			}
+		}
+
+		[Test]
+		public void TestDirectCrl()
+		{
+			X509Crl crl = new X509CrlParser().ReadCrl(directCrl);
+
+			foreach (X509CrlEntry crlEntry in crl.GetRevokedCertificates())
+			{
+				if (crlEntry.GetCertificateIssuer() != null)
+				{
+					Fail("certificate issuer CRL entry extension is not null");
+				}
+			}
+		}
+
+		public override void PerformTest()
+		{
+			TestIndirectCrl();
+			TestDirectCrl();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Crl5Test());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CamelliaTest.cs b/BouncyCastle.AxCrypt/test/src/test/CamelliaTest.cs
new file mode 100644
index 0000000..f8e3520
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CamelliaTest.cs
@@ -0,0 +1,204 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Ntt;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <summary>Basic test class for Camellia</summary>
+	[TestFixture]
+	public class CamelliaTest
+		: BaseBlockCipherTest
+	{
+		internal static readonly string[] cipherTests =
+		{
+			"128",
+			"0123456789abcdeffedcba9876543210",
+			"0123456789abcdeffedcba9876543210",
+			"67673138549669730857065648eabe43",
+			"192",
+			"0123456789abcdeffedcba98765432100011223344556677",
+			"0123456789abcdeffedcba9876543210",
+			"b4993401b3e996f84ee5cee7d79b09b9",
+			"256",
+			"0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff",
+			"0123456789abcdeffedcba9876543210",
+			"9acc237dff16d76c20ef7c919e3a7509",
+		};
+
+		public CamelliaTest()
+			: base("Camellia")
+		{
+		}
+
+		[Test]
+		public void TestCiphers()
+		{
+			for (int i = 0; i != cipherTests.Length; i += 4)
+			{
+				doCipherTest(int.Parse(cipherTests[i]),
+					Hex.Decode(cipherTests[i + 1]),
+					Hex.Decode(cipherTests[i + 2]),
+					Hex.Decode(cipherTests[i + 3]));
+			}
+		}
+
+		[Test]
+		public void TestWrap()
+		{
+			byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+			byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[] out1 = Hex.Decode("635d6ac46eedebd3a7f4a06421a4cbd1746b24795ba2f708");
+
+			wrapTest(1, "CamelliaWrap", kek1, in1, out1);
+		}
+
+		[Test]
+		public void TestOids()
+		{
+			string[] oids = {
+				NttObjectIdentifiers.IdCamellia128Cbc.Id,
+				NttObjectIdentifiers.IdCamellia192Cbc.Id,
+				NttObjectIdentifiers.IdCamellia256Cbc.Id
+			};
+
+			string[] names = {
+				"Camellia/CBC/PKCS7Padding",
+				"Camellia/CBC/PKCS7Padding",
+				"Camellia/CBC/PKCS7Padding"
+			};
+
+			oidTest(oids, names, 1);
+		}
+
+		[Test]
+		public void TestWrapOids()
+		{
+			string[] wrapOids = {
+				NttObjectIdentifiers.IdCamellia128Wrap.Id,
+				NttObjectIdentifiers.IdCamellia192Wrap.Id,
+				NttObjectIdentifiers.IdCamellia256Wrap.Id
+			};
+
+			wrapOidTest(wrapOids, "CamelliaWrap");
+		}
+
+		public void doCipherTest(
+			int		strength,
+			byte[]	keyBytes,
+			byte[]	input,
+			byte[]	output)
+		{
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("Camellia", keyBytes);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("Camellia/ECB/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("Camellia/ECB/NoPadding");
+
+			try
+			{
+				outCipher.Init(true, key);
+			}
+			catch (Exception e)
+			{
+				Fail("Camellia failed initialisation - " + e.ToString(), e);
+			}
+
+			try
+			{
+				inCipher.Init(false, key);
+			}
+			catch (Exception e)
+			{
+				Fail("Camellia failed initialisation - " + e.ToString(), e);
+			}
+
+			//
+			// encryption pass
+			//
+			MemoryStream bOut = new MemoryStream();
+			CipherStream cOut = new CipherStream(bOut, null, outCipher);
+
+			try
+			{
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					cOut.WriteByte(input[i]);
+				}
+				cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+				cOut.Close();
+			}
+			catch (IOException e)
+			{
+				Fail("Camellia failed encryption - " + e.ToString(), e);
+			}
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("Camellia failed encryption - expected "
+					+ Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			MemoryStream bIn = new MemoryStream(bytes, false);
+			CipherStream cIn = new CipherStream(bIn, inCipher, null);
+
+			try
+			{
+//				DataInputStream dIn = new DataInputStream(cIn);
+				BinaryReader dIn = new BinaryReader(cIn);
+
+				bytes = new byte[input.Length];
+
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+//					bytes[i] = (byte)dIn.read();
+					bytes[i] = dIn.ReadByte();
+				}
+
+				int remaining = bytes.Length - input.Length / 2;
+//				dIn.readFully(bytes, input.Length / 2, remaining);
+				byte[] extra = dIn.ReadBytes(remaining);
+				if (extra.Length < remaining)
+					throw new EndOfStreamException();
+				extra.CopyTo(bytes, input.Length / 2);
+			}
+			catch (Exception e)
+			{
+				Fail("Camellia failed encryption - " + e.ToString(), e);
+			}
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("Camellia failed decryption - expected "
+					+ Hex.ToHexString(input) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			TestCiphers();
+			TestWrap();
+			TestOids();
+			TestWrapOids();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CamelliaTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CertPathBuilderTest.cs b/BouncyCastle.AxCrypt/test/src/test/CertPathBuilderTest.cs
new file mode 100644
index 0000000..e31bde8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CertPathBuilderTest.cs
@@ -0,0 +1,163 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class CertPathBuilderTest
+        : SimpleTest
+    {
+        private void baseTest()
+        {
+//			CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
+            X509CertificateParser certParser = new X509CertificateParser();
+            X509CrlParser crlParser = new X509CrlParser();
+
+            // initialise CertStore
+            X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin);
+            X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin);
+            X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin);
+            X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin);
+            X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin);
+
+            IList certList = new ArrayList();
+            certList.Add(rootCert);
+            certList.Add(interCert);
+            certList.Add(finalCert);
+
+            IList crlList = new ArrayList();
+            crlList.Add(rootCrl);
+            crlList.Add(interCrl);
+
+//			CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list);
+//			CertStore store = CertStore.getInstance("Collection", ccsp, "BC");
+            IX509Store x509CertStore = X509StoreFactory.Create(
+                "Certificate/Collection",
+                new X509CollectionStoreParameters(certList));
+            IX509Store x509CrlStore = X509StoreFactory.Create(
+                "CRL/Collection",
+                new X509CollectionStoreParameters(crlList));
+
+            // NB: Month is 1-based in .NET
+            //DateTime validDate = new DateTime(2008, 9, 4, 14, 49, 10).ToUniversalTime();
+            DateTime validDate = new DateTime(2008, 9, 4, 5, 49, 10);
+
+            //Searching for rootCert by subjectDN without CRL
+            ISet trust = new HashSet();
+            trust.Add(new TrustAnchor(rootCert, null));
+
+//			CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX","BC");
+            PkixCertPathBuilder cpb = new PkixCertPathBuilder();
+            X509CertStoreSelector targetConstraints = new X509CertStoreSelector();
+            targetConstraints.Subject = finalCert.SubjectDN;
+            PkixBuilderParameters parameters = new PkixBuilderParameters(trust, targetConstraints);
+//			parameters.addCertStore(store);
+            parameters.AddStore(x509CertStore);
+            parameters.AddStore(x509CrlStore);
+            parameters.Date = new DateTimeObject(validDate);
+            PkixCertPathBuilderResult result = cpb.Build(parameters);
+            PkixCertPath path = result.CertPath;
+
+            if (path.Certificates.Count != 2)
+            {
+                Fail("wrong number of certs in baseTest path");
+            }
+        }
+
+        private void v0Test()
+        {
+            // create certificates and CRLs
+            AsymmetricCipherKeyPair rootPair = TestUtilities.GenerateRsaKeyPair();
+            AsymmetricCipherKeyPair interPair = TestUtilities.GenerateRsaKeyPair();
+            AsymmetricCipherKeyPair endPair = TestUtilities.GenerateRsaKeyPair();
+
+            X509Certificate rootCert = TestUtilities.GenerateRootCert(rootPair);
+            X509Certificate interCert = TestUtilities.GenerateIntermediateCert(interPair.Public, rootPair.Private, rootCert);
+            X509Certificate endCert = TestUtilities.GenerateEndEntityCert(endPair.Public, interPair.Private, interCert);
+
+            BigInteger revokedSerialNumber = BigInteger.Two;
+            X509Crl rootCRL = TestUtilities.CreateCrl(rootCert, rootPair.Private, revokedSerialNumber);
+            X509Crl interCRL = TestUtilities.CreateCrl(interCert, interPair.Private, revokedSerialNumber);
+
+            // create CertStore to support path building
+            IList certList = new ArrayList();
+            certList.Add(rootCert);
+            certList.Add(interCert);
+            certList.Add(endCert);
+
+            IList crlList = new ArrayList();
+            crlList.Add(rootCRL);
+            crlList.Add(interCRL);
+
+//			CollectionCertStoreParameters parameters = new CollectionCertStoreParameters(list);
+//			CertStore                     store = CertStore.getInstance("Collection", parameters);
+            IX509Store x509CertStore = X509StoreFactory.Create(
+                "Certificate/Collection",
+                new X509CollectionStoreParameters(certList));
+            IX509Store x509CrlStore = X509StoreFactory.Create(
+                "CRL/Collection",
+                new X509CollectionStoreParameters(crlList));
+
+            ISet trust = new HashSet();
+            trust.Add(new TrustAnchor(rootCert, null));
+
+            // build the path
+//			CertPathBuilder  builder = CertPathBuilder.getInstance("PKIX", "BC");
+            PkixCertPathBuilder builder = new PkixCertPathBuilder();
+            X509CertStoreSelector pathConstraints = new X509CertStoreSelector();
+
+            pathConstraints.Subject = endCert.SubjectDN;
+
+            PkixBuilderParameters buildParams = new PkixBuilderParameters(trust, pathConstraints);
+//			buildParams.addCertStore(store);
+            buildParams.AddStore(x509CertStore);
+            buildParams.AddStore(x509CrlStore);
+
+            buildParams.Date = new DateTimeObject(DateTime.UtcNow);
+
+            PkixCertPathBuilderResult result = builder.Build(buildParams);
+            PkixCertPath path = result.CertPath;
+
+            if (path.Certificates.Count != 2)
+            {
+                Fail("wrong number of certs in v0Test path");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            baseTest();
+            v0Test();
+        }
+        
+        public override string Name
+        {
+            get { return "CertPathBuilder"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CertPathBuilderTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CertPathTest.cs b/BouncyCastle.AxCrypt/test/src/test/CertPathTest.cs
new file mode 100644
index 0000000..f1a7c94
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CertPathTest.cs
@@ -0,0 +1,359 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class CertPathTest
+		: SimpleTest
+	{
+		internal static readonly byte[] rootCertBin = Base64.Decode(
+			"MIIBqzCCARQCAQEwDQYJKoZIhvcNAQEFBQAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMRLUjhPe4YUdLo6EcjKcWUOG7CydFTH53Pr1lWjOkbmszYDpkhCTT9LOsI+disk18nkBxSl8DAHTqV+VxtuTPt64iyi10YxyDeep+DwZG/f8cVQv97U3hA9cLurZ2CofkMLGr6JpSGCMZ9FcstcTdHB4lbErIJ54YqfF4pNOs4/AgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAgyrTEFY7ALpeY59jL6xFOLpuPqoBOWrUWv6O+zy5BCU0qiX71r3BpigtxRj+DYcfLIM9FNERDoHu3TthD3nw [...]
+		internal static readonly byte[] interCertBin = Base64.Decode(
+			"MIICSzCCAbSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlMB4XDTA4MDkwNDA0NDUwOFoXDTA4MDkxMTA0NDUwOFowKDEmMCQGA1UEAxMdVGVzdCBJbnRlcm1lZGlhdGUgQ2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAISS9OOZ2wxzdWny9aVvk4Joq+dwSJ+oqvHUxX3PflZyuiLiCBUOUE4q59dGKdtNX5fIfwyK3cpV0e73Y/0fwfM3m9rOWFrCKOhfeswNTes0w/2PqPVVDDsF/nj7NApuqXwioeQlgTL251RDF4sVoxXqAU7lRkcqwZt3mwqS4KTJAgMBAAGjgY4wgYswRgYDVR0jBD8wPYAUhv8BOT27EB9JaCccJD4YASPP5XWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2Vy [...]
+		internal static readonly byte[] finalCertBin = Base64.Decode(
+			"MIICRjCCAa+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZTAeFw0wODA5MDQwNDQ1MDhaFw0wODA5MTEwNDQ1MDhaMB8xHTAbBgNVBAMTFFRlc3QgRW5kIENlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQChpUeo0tPYywWKiLlbWKNJBcCpSaLSlaZ+4+yer1AxI5yJIVHP6SAlBghlbD5Qne5ImnN/15cz1xwYAiul6vGKJkVPlFEe2Mr+g/J/WJPQQPsjbZ1G+vxbAwXEDA4KaQrnpjRZFq+CdKHwOjuPLYS/MYQNgdIvDVEQcTbPQ8GaiQIDAQABo4GIMIGFMEYGA1UdIwQ/MD2AFL/IwAGOkHzaQyPZegy79CwM5oTFoSKkIDAeMRwwGgYDVQQDExNUZXN0IENBIENl [...]
+		internal static readonly byte[] rootCrlBin = Base64.Decode(
+			"MIIBYjCBzAIBATANBgkqhkiG9w0BAQsFADAeMRwwGgYDVQQDExNUZXN0IENBIENlcnRpZmljYXRlFw0wODA5MDQwNDQ1MDhaFw0wODA5MDQwNzMxNDhaMCIwIAIBAhcNMDgwOTA0MDQ0NTA4WjAMMAoGA1UdFQQDCgEJoFYwVDBGBgNVHSMEPzA9gBSG/wE5PbsQH0loJxwkPhgBI8/ldaEipCAwHjEcMBoGA1UEAxMTVGVzdCBDQSBDZXJ0aWZpY2F0ZYIBATAKBgNVHRQEAwIBATANBgkqhkiG9w0BAQsFAAOBgQCAbaFCo0BNG4AktVf6jjBLeawP1u0ELYkOCEGvYZE0mBpQ+OvFg7subZ6r3lRIj030nUli28sPFtu5ZQMBNcpE4nS1ziF44RfT3Lp5UgHx9x17Krz781iEyV+7zU8YxYMY9wULD+DCuK294kGKIssVNbmTYXZatBNoXQN5CLIocA==");
+		internal static readonly byte[] interCrlBin = Base64.Decode(
+			"MIIBbDCB1gIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDEx1UZXN0IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZRcNMDgwOTA0MDQ0NTA4WhcNMDgwOTA0MDczMTQ4WjAiMCACAQIXDTA4MDkwNDA0NDUwOFowDDAKBgNVHRUEAwoBCaBWMFQwRgYDVR0jBD8wPYAUv8jAAY6QfNpDI9l6DLv0LAzmhMWhIqQgMB4xHDAaBgNVBAMTE1Rlc3QgQ0EgQ2VydGlmaWNhdGWCAQEwCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQELBQADgYEAEVCr5TKs5yguGgLH+dBzmSPoeSIWJFLsgWwJEit/iUDJH3dgYmaczOcGxIDtbYYHLWIHM+P2YRyQz3MEkCXEgm/cx4y7leAmux5l+xQWgmxFPz+197vaphPeCZo+B7V1CWtm518gcq4mrs9ovfgNqgyFj7KGjcBpWdJE32KMt50=");
+
+		/*
+		 * certpath with a circular reference
+		 */
+		internal static readonly byte[] certA = Base64.Decode(
+			"MIIC6jCCAlOgAwIBAgIBBTANBgkqhkiG9w0BAQUFADCBjTEPMA0GA1UEAxMGSW50"
+			+ "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+			+ "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+			+ "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2NTda"
+			+ "Fw0xNzAzMzAwODQ0MDBaMIGlMScwJQYDVQQDHh4AQQByAG0AaQBuACAASADkAGIA"
+			+ "ZQByAGwAaQBuAGcxCzAJBgNVBAYTAkNIMQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNV"
+			+ "BAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNwaGVyZSBBRzEQMA4GA1UECxMHVGVzdGlu"
+			+ "ZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5AcHJpdmFzcGhlcmUuY29tMIGfMA0GCSqG"
+			+ "SIb3DQEBAQUAA4GNADCBiQKBgQCfHfyVs5dbxG35H/Thd29qR4NZU88taCu/OWA1"
+			+ "GdACI02lXWYpmLWiDgnU0ULP+GG8OnVp1IES9fz2zcrXKQ19xZzsen/To3h5sNte"
+			+ "cJpS00XMM24q/jDwy5NvkBP9YIfFKQ1E/0hFHXcqwlw+b/y/v6YGsZCU2h6QDzc4"
+			+ "5m0+BwIDAQABo0AwPjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIE8DAeBglg"
+			+ "hkgBhvhCAQ0EERYPeGNhIGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAJEu"
+			+ "KiSfIwsY7SfobMLrv2v/BtLhGLi4RnmjiwzBhuv5rn4rRfBpq1ppmqQMJ2pmA67v"
+			+ "UWCY+mNwuyjHyivpCCyJGsZ9d5H09g2vqxzkDBMz7X9VNMZYFH8j/R3/Cfvqks31"
+			+ "z0OFslJkeKLa1I0P/dfVHsRKNkLRT3Ws5LKksErQ");
+
+		internal static readonly byte[] certB = Base64.Decode(
+			"MIICtTCCAh6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+			+ "ZXIyMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+			+ "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+			+ "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ2Mzha"
+			+ "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjMxCzAJBgNVBAYTAkNI"
+			+ "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+			+ "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+			+ "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxCXIB"
+			+ "QRnmVvl2h7Q+0SsRxDLnyM1dJG9jMa+UCCmHy0k/ZHs5VirSbjEJSjkQ9BGeh9SC"
+			+ "7JwbMpXO7UE+gcVc2RnWUY+MA+fWIeTV4KtkYA8WPu8wVGCXbN8wwh/StOocszxb"
+			+ "g+iLvGeh8CYSRqg6QN3S/02etH3o8H4e7Z0PZwIDAQABoyMwITAPBgNVHRMBAf8E"
+			+ "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCtWdirSsmt"
+			+ "+CBBCNn6ZnbU3QqQfiiQIomjenNEHESJgaS/+PvPE5i3xWFXsunTHLW321/Km16I"
+			+ "7+ZvT8Su1cqHg79NAT8QB0yke1saKSy2C0Pic4HwrNqVBWFNSxMU0hQzpx/ZXDbZ"
+			+ "DqIXAp5EfyRYBy2ul+jm6Rot6aFgzuopKg==");
+
+		internal static readonly byte[] certC = Base64.Decode(
+			"MIICtTCCAh6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+			+ "ZXIxMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+			+ "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+			+ "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ0Mzla"
+			+ "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjIxCzAJBgNVBAYTAkNI"
+			+ "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+			+ "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+			+ "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD0rLr6"
+			+ "f2/ONeJzTb0q9M/NNX+MnAFMSqiQGVBkT76u5nOH4KLkpHXkzI82JI7GuQMzoT3a"
+			+ "+RP1hO6FneO92ms2soC6xiOFb4EC69Dfhh87Nww5O35JxVF0bzmbmIAWd6P/7zGh"
+			+ "nd2S4tKkaZcubps+C0j9Fgi0hipVicAOUVVoDQIDAQABoyMwITAPBgNVHRMBAf8E"
+			+ "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCLPvc1IMA4"
+			+ "YP+PmnEldyUoRWRnvPWjBGeu0WheBP7fdcnGBf93Nmc5j68ZN+eTZ5VMuZ99YdvH"
+			+ "CXGNX6oodONLU//LlFKdLl5xjLAS5X9p1RbOEGytnalqeiEpjk4+C/7rIBG1kllO"
+			+ "dItmI6LlEMV09Hkpg6ZRAUmRkb8KrM4X7A==");
+
+		internal static readonly byte[] certD = Base64.Decode(
+			"MIICtTCCAh6gAwIBAgIBBjANBgkqhkiG9w0BAQQFADCBjTEPMA0GA1UEAxMGSW50"
+			+ "ZXIzMQswCQYDVQQGEwJDSDEPMA0GA1UEBxMGWnVyaWNoMQswCQYDVQQIEwJaSDEX"
+			+ "MBUGA1UEChMOUHJpdmFzcGhlcmUgQUcxEDAOBgNVBAsTB1Rlc3RpbmcxJDAiBgkq"
+			+ "hkiG9w0BCQEWFWFybWluQHByaXZhc3BoZXJlLmNvbTAeFw0wNzA0MDIwODQ5NTNa"
+			+ "Fw0xNzAzMzAwODQ0MDBaMIGNMQ8wDQYDVQQDEwZJbnRlcjExCzAJBgNVBAYTAkNI"
+			+ "MQ8wDQYDVQQHEwZadXJpY2gxCzAJBgNVBAgTAlpIMRcwFQYDVQQKEw5Qcml2YXNw"
+			+ "aGVyZSBBRzEQMA4GA1UECxMHVGVzdGluZzEkMCIGCSqGSIb3DQEJARYVYXJtaW5A"
+			+ "cHJpdmFzcGhlcmUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCae3TP"
+			+ "jIVKeASqvNabaiUHAMGUgFxB7L0yUsIj39azLcLtUj4S7XkDf7SMGtYV0JY1XNaQ"
+			+ "sHJAsnJivDZc50oiYvqDYfgFZx5+AsN5l5X5rjRzs/OX+Jo+k1OgsIyu6+mf9Kfb"
+			+ "5IdWOVB2EcOg4f9tPjLM8CIj9Pp7RbKLyqUUgwIDAQABoyMwITAPBgNVHRMBAf8E"
+			+ "BTADAQH/MA4GA1UdDwEB/wQEAwIB9jANBgkqhkiG9w0BAQQFAAOBgQCgr9kUdWUT"
+			+ "Lt9UcztSzR3pnHRsyvS0E/z850OKQKS5/VxLEalpFvhj+3EcZ7Y6mFxaaS2B7vXg"
+			+ "2YWyqV1PRb6iF7/u9EXkpSTKGrJahwANirCa3V/HTUuPdCE2GITlnWI8h3eVA+xQ"
+			+ "D4LF0PXHOkXbwmhXRSb10lW1bSGkUxE9jg==");
+
+		private void doTestExceptions()
+		{
+			byte[] enc = { (byte)0, (byte)2, (byte)3, (byte)4, (byte)5 };
+//			MyCertPath mc = new MyCertPath(enc);
+			MemoryStream os = new MemoryStream();
+			MemoryStream ins;
+			byte[] arr;
+
+			// TODO Support serialization of cert paths?
+//			ObjectOutputStream oos = new ObjectOutputStream(os);
+//			oos.WriteObject(mc);
+//			oos.Flush();
+//			oos.Close();
+
+			try
+			{
+//				CertificateFactory cFac = CertificateFactory.GetInstance("X.509");
+				arr = os.ToArray();
+				ins = new MemoryStream(arr, false);
+//				cFac.generateCertPath(ins);
+				new PkixCertPath(ins);
+			}
+			catch (CertificateException)
+			{
+				// ignore okay
+			}
+
+//			CertificateFactory cf = CertificateFactory.GetInstance("X.509");
+			X509CertificateParser cf = new X509CertificateParser();
+			IList certCol = new ArrayList();
+
+			certCol.Add(cf.ReadCertificate(certA));
+			certCol.Add(cf.ReadCertificate(certB));
+			certCol.Add(cf.ReadCertificate(certC));
+			certCol.Add(cf.ReadCertificate(certD));
+
+//			CertPathBuilder pathBuilder = CertPathBuilder.GetInstance("PKIX");
+			PkixCertPathBuilder pathBuilder = new PkixCertPathBuilder();
+			X509CertStoreSelector select = new X509CertStoreSelector();
+			select.Subject = ((X509Certificate)certCol[0]).SubjectDN;
+
+			ISet trustanchors = new HashSet();
+			trustanchors.Add(new TrustAnchor(cf.ReadCertificate(rootCertBin), null));
+
+//			CertStore certStore = CertStore.getInstance("Collection", new CollectionCertStoreParameters(certCol));
+			IX509Store x509CertStore = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certCol));
+
+			PkixBuilderParameters parameters = new PkixBuilderParameters(trustanchors, select);
+			parameters.AddStore(x509CertStore);
+
+			try
+			{
+				PkixCertPathBuilderResult result = pathBuilder.Build(parameters);
+				PkixCertPath path = result.CertPath;
+				Fail("found cert path in circular set");
+			}
+			catch (PkixCertPathBuilderException)
+			{
+				// expected
+			}
+		}
+
+		public override void PerformTest()
+		{
+			X509CertificateParser cf = new X509CertificateParser();
+
+			X509Certificate rootCert = cf.ReadCertificate(rootCertBin);
+			X509Certificate interCert = cf.ReadCertificate(interCertBin);
+			X509Certificate finalCert = cf.ReadCertificate(finalCertBin);
+
+			//Testing CertPath generation from List
+			IList list = new ArrayList();
+			list.Add(interCert);
+//			CertPath certPath1 = cf.generateCertPath(list);
+			PkixCertPath certPath1 = new PkixCertPath(list);
+
+			//Testing CertPath encoding as PkiPath
+			byte[] encoded = certPath1.GetEncoded("PkiPath");
+
+			//Testing CertPath generation from InputStream
+			MemoryStream inStream = new MemoryStream(encoded, false);
+//			CertPath certPath2 = cf.generateCertPath(inStream, "PkiPath");
+			PkixCertPath certPath2 = new PkixCertPath(inStream, "PkiPath");
+
+			//Comparing both CertPathes
+			if (!certPath2.Equals(certPath1))
+			{
+				Fail("CertPath differ after encoding and decoding.");
+			}
+
+			encoded = certPath1.GetEncoded("PKCS7");
+
+			//Testing CertPath generation from InputStream
+			inStream = new MemoryStream(encoded, false);
+//			certPath2 = cf.generateCertPath(inStream, "PKCS7");
+			certPath2 = new PkixCertPath(inStream, "PKCS7");
+
+			//Comparing both CertPathes
+			if (!certPath2.Equals(certPath1))
+			{
+				Fail("CertPath differ after encoding and decoding.");
+			}
+
+			encoded = certPath1.GetEncoded("PEM");
+
+			//Testing CertPath generation from InputStream
+			inStream = new MemoryStream(encoded, false);
+//			certPath2 = cf.generateCertPath(inStream, "PEM");
+			certPath2 = new PkixCertPath(inStream, "PEM");
+
+			//Comparing both CertPathes
+			if (!certPath2.Equals(certPath1))
+			{
+				Fail("CertPath differ after encoding and decoding.");
+			}
+
+			//
+			// empty list test
+			//
+			list = new ArrayList();
+
+//			CertPath certPath = CertificateFactory.GetInstance("X.509","BC").generateCertPath(list);
+			PkixCertPath certPath = new PkixCertPath(list);
+			if (certPath.Certificates.Count != 0)
+			{
+				Fail("list wrong size.");
+			}
+
+			//
+			// exception tests
+			//
+			doTestExceptions();
+		}
+
+		public override string Name
+		{
+			get { return "CertPath"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CertPathTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+
+//		private class MyCertificate : X509Certificate
+//		{
+//			private readonly string type;
+//			private readonly byte[] encoding;
+//
+//			public MyCertificate(string type, byte[] encoding)
+////				: base(type)
+//			{
+//				this.type = type;
+//
+//				// don't copy to allow null parameter in test
+//				this.encoding = encoding;
+//			}
+//
+//			public override byte[] GetEncoded()
+//			{
+//				// do copy to force NPE in test
+//				return (byte[])encoding.Clone();
+//			}
+//
+//			public override void Verify(AsymmetricKeyParameter publicKey)
+//			{
+//			}
+//
+//			public override string ToString()
+//			{
+//				return "[My test Certificate, type: " + type + "]";
+//			}
+//
+//			public override AsymmetricKeyParameter GetPublicKey()
+//			{
+//				throw new NotImplementedException();
+//
+////            return new PublicKey()
+////            {
+////                public string getAlgorithm()
+////                {
+////                    return "TEST";
+////                }
+////
+////                public byte[] getEncoded()
+////                {
+////                    return new byte[] { (byte)1, (byte)2, (byte)3 };
+////                }
+////
+////                public string getFormat()
+////                {
+////                    return "TEST_FORMAT";
+////                }
+////            };
+//			}
+//		}
+
+//		private class MyCertPath : PkixCertPath
+//		{
+//			private readonly ArrayList certificates;
+//
+//			private readonly ArrayList encodingNames;
+//
+//			private readonly byte[] encoding;
+//
+//			public MyCertPath(byte[] encoding)
+//				: base("MyEncoding")
+//			{
+//				this.encoding = encoding;
+//				certificates = new ArrayList();
+//				certificates.Add(new MyCertificate("MyEncoding", encoding));
+//				encodingNames = new ArrayList();
+//				encodingNames.Add("MyEncoding");
+//			}
+//
+//			public override IList Certificates
+//			{
+//				get { return CollectionUtilities.ReadOnly(certificates); }
+//			}
+//
+//			public override byte[] GetEncoded()
+//			{
+//				return (byte[])encoding.Clone();
+//			}
+//
+//			public override byte[] GetEncoded(
+//				string encoding)
+//			{
+//				if (Type.Equals(encoding))
+//				{
+//					return (byte[])this.encoding.Clone();
+//				}
+//				throw new CertificateEncodingException("Encoding not supported: "
+//					+ encoding);
+//			}
+//
+//			public override IEnumerable Encodings
+//			{
+//				get { return new EnumerableProxy(encodingNames); }
+//			}
+//		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CertPathValidatorTest.cs b/BouncyCastle.AxCrypt/test/src/test/CertPathValidatorTest.cs
new file mode 100644
index 0000000..a92bb9b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CertPathValidatorTest.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class CertPathValidatorTest
+        : SimpleTest
+    {
+        private byte[] AC_PR = Base64.Decode(
+            "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFU1RDQ0F6R2dBd0lC"
+            + "QWdJQkJUQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR"
+            + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU"
+            + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs"
+            + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5"
+            + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW"
+            + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy"
+            + "bHNaV2x5WVRBZUZ3MHdNakEwTURReE9UTTVNREJhRncwd05UQTBNRFF5DQpN"
+            + "elU1TURCYU1HRXhDekFKQmdOVkJBWVRBa0pTTVJNd0VRWURWUVFLRXdwSlEx"
+            + "QXRRbkpoYzJsc01UMHdPd1lEDQpWUVFERXpSQmRYUnZjbWxrWVdSbElFTmxj"
+            + "blJwWm1sallXUnZjbUVnWkdFZ1VISmxjMmxrWlc1amFXRWdaR0VnDQpVbVZ3"
+            + "ZFdKc2FXTmhNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJD"
+            + "Z0tDQVFFQXMwc0t5NGsrDQp6b016aldyMTQxeTVYQ045UGJMZERFQXN2cjZ4"
+            + "Z0NCN1l5bEhIQ1NBYmpGR3dOQ0R5NlVxN1h0VjZ6UHdIMXpGDQpFWENlS3Jm"
+            + "UUl5YXBXSEZ4V1VKajBMblFrY1RZM1FOR1huK0JuVk9EVTZDV3M1c3NoZktH"
+            + "RXZyVlQ1Z214V1NmDQp4OFlsdDgzY1dwUE1QZzg3VDlCaHVIbHQzazh2M2Ev"
+            + "NmRPbmF2dytOYTAyZExBaDBlNzZqcCtQUS9LK0pHZlBuDQphQjVVWURrZkd0"
+            + "em5uTTNBV01tY3VJK0o0ek5OMDZaa3ZnbDFsdEo2UU1qcnZEUFlSak9ndDlT"
+            + "cklpY1NmbEo4DQptVDdHWGRRaXJnQUNXc3g1QURBSklRK253TU1vNHlyTUtx"
+            + "SlFhNFFDMHhhT0QvdkdVcG9SaDQzT0FTZFp3c3YvDQpPWFlybmVJeVAwVCs4"
+            + "UUlEQVFBQm80RzNNSUcwTUQwR0ExVWRId1EyTURRd01xQXdvQzZHTEdoMGRI"
+            + "QTZMeTloDQpZM0poYVhvdWFXTndZbkpoYzJsc0xtZHZkaTVpY2k5TVExSmhZ"
+            + "M0poYVhvdVkzSnNNQklHQTFVZElBUUxNQWt3DQpCd1lGWUV3QkFRRXdIUVlE"
+            + "VlIwT0JCWUVGREpUVFlKNE9TWVB5T09KZkVMZXhDaHppK2hiTUI4R0ExVWRJ"
+            + "d1FZDQpNQmFBRklyNjhWZUVFUk0xa0VMNlYwbFVhUTJreFBBM01BNEdBMVVk"
+            + "RHdFQi93UUVBd0lCQmpBUEJnTlZIUk1CDQpBZjhFQlRBREFRSC9NQTBHQ1Nx"
+            + "R1NJYjNEUUVCQlFVQUE0SUJBUUJRUFNoZ1lidnFjaWV2SDVVb3ZMeXhkbkYr"
+            + "DQpFcjlOeXF1SWNkMnZ3Y0N1SnpKMkQ3WDBUcWhHQ0JmUEpVVkdBVWorS0NP"
+            + "SDFCVkgva1l1OUhsVHB1MGtKWFBwDQpBQlZkb2hJUERqRHhkbjhXcFFSL0Yr"
+            + "ejFDaWtVcldIMDR4eTd1N1p6UUpLSlBuR0loY1FpOElyRm1PYkllMEc3DQpY"
+            + "WTZPTjdPRUZxY21KTFFHWWdtRzFXMklXcytQd1JwWTdENGhLVEFoVjFSNkVv"
+            + "amE1L3BPcmVDL09kZXlQWmVxDQo1SUZTOUZZZk02U0Npd2hrK3l2Q1FHbVo0"
+            + "YzE5SjM0ZjVFYkRrK1NQR2tEK25EQ0E3L3VMUWNUMlJURE14SzBaDQpuZlo2"
+            + "Nm1Sc0ZjcXRGaWdScjVFcmtKZDdoUVV6eHNOV0VrNzJEVUFIcVgvNlNjeWtt"
+            + "SkR2V0plSUpqZlcNCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0NCg==");
+
+        private byte[] AC_RAIZ_ICPBRASIL = Base64.Decode(
+            "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlFdURDQ0E2Q2dBd0lC"
+            + "QWdJQkJEQU5CZ2txaGtpRzl3MEJBUVVGQURDQnRERUxNQWtHQTFVRUJoTUNR"
+            + "bEl4DQpFekFSQmdOVkJBb1RDa2xEVUMxQ2NtRnphV3d4UFRBN0JnTlZCQXNU"
+            + "TkVsdWMzUnBkSFYwYnlCT1lXTnBiMjVoDQpiQ0JrWlNCVVpXTnViMnh2WjJs"
+            + "aElHUmhJRWx1Wm05eWJXRmpZVzhnTFNCSlZFa3hFVEFQQmdOVkJBY1RDRUp5"
+            + "DQpZWE5wYkdsaE1Rc3dDUVlEVlFRSUV3SkVSakV4TUM4R0ExVUVBeE1vUVhW"
+            + "MGIzSnBaR0ZrWlNCRFpYSjBhV1pwDQpZMkZrYjNKaElGSmhhWG9nUW5KaGMy"
+            + "bHNaV2x5WVRBZUZ3MHdNVEV4TXpBeE1qVTRNREJhRncweE1URXhNekF5DQpN"
+            + "elU1TURCYU1JRzBNUXN3Q1FZRFZRUUdFd0pDVWpFVE1CRUdBMVVFQ2hNS1NV"
+            + "TlFMVUp5WVhOcGJERTlNRHNHDQpBMVVFQ3hNMFNXNXpkR2wwZFhSdklFNWhZ"
+            + "Mmx2Ym1Gc0lHUmxJRlJsWTI1dmJHOW5hV0VnWkdFZ1NXNW1iM0p0DQpZV05o"
+            + "YnlBdElFbFVTVEVSTUE4R0ExVUVCeE1JUW5KaGMybHNhV0V4Q3pBSkJnTlZC"
+            + "QWdUQWtSR01URXdMd1lEDQpWUVFERXloQmRYUnZjbWxrWVdSbElFTmxjblJw"
+            + "Wm1sallXUnZjbUVnVW1GcGVpQkNjbUZ6YVd4bGFYSmhNSUlCDQpJakFOQmdr"
+            + "cWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBd1BNdWR3WC9odm0r"
+            + "VWgyYi9sUUFjSFZBDQppc2FtYUxrV2Rrd1A5L1MvdE9LSWdSckw2T3krWklH"
+            + "bE9VZGQ2dVl0azlNYS8zcFVwZ2NmTkFqMHZZbTVnc3lqDQpRbzllbXNjK3g2"
+            + "bTRWV3drOWlxTVpTQ0s1RVFrQXEvVXQ0bjdLdUxFMStnZGZ0d2RJZ3hmVXNQ"
+            + "dDRDeU5yWTUwDQpRVjU3S00yVVQ4eDVycm16RWpyN1RJQ0dwU1VBbDJnVnFl"
+            + "NnhhaWkrYm1ZUjFRcm1XYUJTQUc1OUxya3Jqcll0DQpiUmhGYm9VRGUxREsr"
+            + "NlQ4czVMNms4Yzhva3BiSHBhOXZlTXp0RFZDOXNQSjYwTVdYaDZhblZLbzFV"
+            + "Y0xjYlVSDQp5RWVOdlpuZVZSS0FBVTZvdXdkakR2d2xzYUt5ZEZLd2VkMFRv"
+            + "UTQ3Ym1VS2djbSt3VjNlVFJrMzZVT25Ud0lEDQpBUUFCbzRIU01JSFBNRTRH"
+            + "QTFVZElBUkhNRVV3UXdZRllFd0JBUUF3T2pBNEJnZ3JCZ0VGQlFjQ0FSWXNh"
+            + "SFIwDQpjRG92TDJGamNtRnBlaTVwWTNCaWNtRnphV3d1WjI5MkxtSnlMMFJR"
+            + "UTJGamNtRnBlaTV3WkdZd1BRWURWUjBmDQpCRFl3TkRBeW9EQ2dMb1lzYUhS"
+            + "MGNEb3ZMMkZqY21GcGVpNXBZM0JpY21GemFXd3VaMjkyTG1KeUwweERVbUZq"
+            + "DQpjbUZwZWk1amNtd3dIUVlEVlIwT0JCWUVGSXI2OFZlRUVSTTFrRUw2VjBs"
+            + "VWFRMmt4UEEzTUE4R0ExVWRFd0VCDQovd1FGTUFNQkFmOHdEZ1lEVlIwUEFR"
+            + "SC9CQVFEQWdFR01BMEdDU3FHU0liM0RRRUJCUVVBQTRJQkFRQVpBNWMxDQpV"
+            + "L2hnSWg2T2NnTEFmaUpnRldwdm1EWldxbFYzMC9iSEZwajhpQm9iSlNtNXVE"
+            + "cHQ3VGlyWWgxVXhlM2ZRYUdsDQpZakplKzl6ZCtpelBSYkJxWFBWUUEzNEVY"
+            + "Y3drNHFwV3VmMWhIcmlXZmRyeDhBY3FTcXI2Q3VRRndTcjc1Rm9zDQpTemx3"
+            + "REFEYTcwbVQ3d1pqQW1RaG5aeDJ4SjZ3ZldsVDlWUWZTLy9KWWVJYzdGdWUy"
+            + "Sk5MZDAwVU9TTU1haUsvDQp0NzllbktOSEVBMmZ1cEgzdkVpZ2Y1RWg0YlZB"
+            + "TjVWb2hyVG02TVk1M3g3WFFaWnIxTUU3YTU1bEZFblNlVDB1DQptbE9BalIy"
+            + "bUFidlNNNVg1b1NaTnJtZXRkenlUajJmbENNOENDN01MYWIwa2tkbmdSSWxV"
+            + "QkdIRjEvUzVubVBiDQpLKzlBNDZzZDMzb3FLOG44DQotLS0tLUVORCBDRVJU"
+            + "SUZJQ0FURS0tLS0tDQo=");
+
+        private byte[] schefer = Base64.Decode(
+            "MIIEnDCCBAWgAwIBAgICIPAwDQYJKoZIhvcNAQEEBQAwgcAxCzAJBgNVBAYT"
+            + "AkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1MDA4IFdpZXNiYWRl"
+            + "bjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAYBgNVBAsTEVNDSFVG"
+            + "QSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBCZW51dHplciBTZXJ2"
+            + "aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu"
+            + "ZGUwHhcNMDQwMzMwMTEwODAzWhcNMDUwMzMwMTEwODAzWjCBnTELMAkGA1UE"
+            + "BhMCREUxCjAIBgNVBAcTASAxIzAhBgNVBAoTGlNIUyBJbmZvcm1hdGlvbnNz"
+            + "eXN0ZW1lIEFHMRwwGgYDVQQLExM2MDAvMDU5NDktNjAwLzA1OTQ5MRgwFgYD"
+            + "VQQDEw9TY2hldHRlciBTdGVmYW4xJTAjBgkqhkiG9w0BCQEWFlN0ZWZhbi5T"
+            + "Y2hldHRlckBzaHMuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJD0"
+            + "95Bi76fkAMjJNTGPDiLPHmZXNsmakngDeS0juzKMeJA+TjXFouhYh6QyE4Bl"
+            + "Nf18fT4mInlgLefwf4t6meIWbiseeTo7VQdM+YrbXERMx2uHsRcgZMsiMYHM"
+            + "kVfYMK3SMJ4nhCmZxrBkoTRed4gXzVA1AA8YjjTqMyyjvt4TAgMBAAGjggHE"
+            + "MIIBwDAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIEsDALBgNVHQ8EBAMC"
+            + "BNAwOQYJYIZIAYb4QgENBCwWKlplcnRpZmlrYXQgbnVyIGZ1ZXIgU0NIVUZB"
+            + "LU9ubGluZSBndWVsdGlnLjAdBgNVHQ4EFgQUXReirhBfg0Yhf6MsBWoo/nPa"
+            + "hGwwge0GA1UdIwSB5TCB4oAUf2UyCaBV9JUeG9lS1Yo6OFBUdEKhgcakgcMw"
+            + "gcAxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIEwZIRVNTRU4xGDAWBgNVBAcTDzY1"
+            + "MDA4IFdpZXNiYWRlbjEaMBgGA1UEChMRU0NIVUZBIEhPTERJTkcgQUcxGjAY"
+            + "BgNVBAsTEVNDSFVGQSBIT0xESU5HIEFHMSIwIAYDVQQDExlJbnRlcm5ldCBC"
+            + "ZW51dHplciBTZXJ2aWNlMSowKAYJKoZIhvcNAQkBFht6ZXJ0aWZpa2F0QHNj"
+            + "aHVmYS1vbmxpbmUuZGWCAQAwIQYDVR0RBBowGIEWU3RlZmFuLlNjaGV0dGVy"
+            + "QHNocy5kZTAmBgNVHRIEHzAdgRt6ZXJ0aWZpa2F0QHNjaHVmYS1vbmxpbmUu"
+            + "ZGUwDQYJKoZIhvcNAQEEBQADgYEAWzZtN9XQ9uyrFXqSy3hViYwV751+XZr0"
+            + "YH5IFhIS+9ixNAu8orP3bxqTaMhpwoU7T/oSsyGGSkb3fhzclgUADbA2lrOI"
+            + "GkeB/m+FArTwRbwpqhCNTwZywOp0eDosgPjCX1t53BB/m/2EYkRiYdDGsot0"
+            + "kQPOVGSjQSQ4+/D+TM8=");
+
+        public override void PerformTest()
+        {
+            X509CertificateParser certParser = new X509CertificateParser();
+            X509CrlParser crlParser = new X509CrlParser();
+
+            // initialise CertStore
+            X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin);
+            X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin);
+            X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin);
+            X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin);
+            X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin);
+
+            IList x509Certs = new ArrayList();
+            x509Certs.Add(rootCert);
+            x509Certs.Add(interCert);
+            x509Certs.Add(finalCert);
+
+            IList x509Crls = new ArrayList();
+            x509Crls.Add(rootCrl);
+            x509Crls.Add(interCrl);
+
+//			CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(list);
+//			CertStore store = CertStore.GetInstance("Collection", ccsp);
+//			X509CollectionStoreParameters ccsp = new X509CollectionStoreParameters(list);
+            IX509Store x509CertStore = X509StoreFactory.Create(
+                "Certificate/Collection",
+                new X509CollectionStoreParameters(x509Certs));
+            IX509Store x509CrlStore = X509StoreFactory.Create(
+                "CRL/Collection",
+                new X509CollectionStoreParameters(x509Crls));
+
+            // NB: Month is 1-based in .NET
+            //DateTime validDate = new DateTime(2008,9,4,14,49,10).ToUniversalTime();
+            DateTime validDate = new DateTime(2008, 9, 4, 5, 49, 10);
+
+            //validating path
+            IList certchain = new ArrayList();
+            certchain.Add(finalCert);
+            certchain.Add(interCert);
+//			CertPath cp = CertificateFactory.GetInstance("X.509").GenerateCertPath(certchain);
+            PkixCertPath cp = new PkixCertPath(certchain);
+            ISet trust = new HashSet();
+            trust.Add(new TrustAnchor(rootCert, null));
+
+//			CertPathValidator cpv = CertPathValidator.GetInstance("PKIX");
+            PkixCertPathValidator cpv = new PkixCertPathValidator();
+            PkixParameters param = new PkixParameters(trust);
+            param.AddStore(x509CertStore);
+            param.AddStore(x509CrlStore);
+            param.Date = new DateTimeObject(validDate);
+            MyChecker checker = new MyChecker();
+            param.AddCertPathChecker(checker);
+
+            PkixCertPathValidatorResult result = (PkixCertPathValidatorResult) cpv.Validate(cp, param);
+            PkixPolicyNode policyTree = result.PolicyTree;
+            AsymmetricKeyParameter subjectPublicKey = result.SubjectPublicKey;
+
+            if (checker.GetCount() != 2)
+            {
+                Fail("checker not evaluated for each certificate");
+            }
+            
+            if (!subjectPublicKey.Equals(finalCert.GetPublicKey()))
+            {
+                Fail("wrong public key returned");
+            }
+
+            //
+            // invalid path containing a valid one test
+            //
+            try
+            {
+                // initialise CertStore
+                rootCert = certParser.ReadCertificate(AC_RAIZ_ICPBRASIL);
+                interCert = certParser.ReadCertificate(AC_PR);
+                finalCert = certParser.ReadCertificate(schefer);
+
+                x509Certs = new ArrayList();
+                x509Certs.Add(rootCert);
+                x509Certs.Add(interCert);
+                x509Certs.Add(finalCert);
+
+//				ccsp = new CollectionCertStoreParameters(list);
+//				store = CertStore.GetInstance("Collection", ccsp);
+//				ccsp = new X509CollectionStoreParameters(list);
+                x509CertStore = X509StoreFactory.Create(
+                    "Certificate/Collection",
+                    new X509CollectionStoreParameters(x509Certs));
+
+                // NB: Month is 1-based in .NET
+                //validDate = new DateTime(2004,3,21,2,21,10).ToUniversalTime();
+                validDate = new DateTime(2004, 3, 20, 19, 21, 10);
+
+                //validating path
+                certchain = new ArrayList();
+                certchain.Add(finalCert);
+                certchain.Add(interCert);
+//				cp = CertificateFactory.GetInstance("X.509").GenerateCertPath(certchain);
+                cp = new PkixCertPath(certchain);
+                trust = new HashSet();
+                trust.Add(new TrustAnchor(rootCert, null));
+
+//				cpv = CertPathValidator.GetInstance("PKIX");
+                cpv = new PkixCertPathValidator();
+                param = new PkixParameters(trust);
+                param.AddStore(x509CertStore);
+                param.IsRevocationEnabled = false;
+                param.Date = new DateTimeObject(validDate);
+
+                result =(PkixCertPathValidatorResult) cpv.Validate(cp, param);
+                policyTree = result.PolicyTree;
+                subjectPublicKey = result.SubjectPublicKey;
+
+                Fail("Invalid path validated");
+            }
+            catch (Exception e)
+            {
+                if (e is PkixCertPathValidatorException 
+                    && e.Message.StartsWith("Could not validate certificate signature."))
+                {
+                    return;
+                }
+                Fail("unexpected exception", e);
+            }
+        }
+
+        public override string Name
+        {
+            get { return "CertPathValidator"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CertPathValidatorTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+
+        private class MyChecker
+            : PkixCertPathChecker
+        {
+            private static int count;
+
+            public override void Init(bool forward)
+            {
+            }
+
+            public override bool IsForwardCheckingSupported()
+            {
+                return true;
+            }
+
+            public override ISet GetSupportedExtensions()
+            {
+                return null;
+            }
+
+            public override void Check(X509Certificate cert, ICollection unresolvedCritExts)
+            {
+                count++;
+            }
+
+            public int GetCount()
+            {
+                return count;
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CertTest.cs b/BouncyCastle.AxCrypt/test/src/test/CertTest.cs
new file mode 100644
index 0000000..9bb4df7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CertTest.cs
@@ -0,0 +1,2544 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class CertTest
+        : SimpleTest
+    {
+        //
+        // server.crt
+        //
+        private static readonly byte[] cert1 = Base64.Decode(
+            "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+            + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+            + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+            + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+            + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
+            + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+            + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+            + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
+            + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
+            + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
+            + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
+            + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
+            + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
+            + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
+            + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
+            + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
+            + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
+            + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
+            + "5/8=");
+
+        //
+        // ca.crt
+        //
+        private static readonly byte[] cert2 = Base64.Decode(
+            "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+            + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+            + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+            + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+            + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2"
+            + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+            + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+            + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u"
+            + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t"
+            + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv"
+            + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s"
+            + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur"
+            + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl"
+            + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E"
+            + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG"
+            + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk"
+            + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz"
+            + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ"
+            + "DhkaJ8VqOMajkQFma2r9iA==");
+
+        //
+        // testx509.pem
+        //
+        private static readonly byte[] cert3 = Base64.Decode(
+            "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+            + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+            + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+            + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+            + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+            + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+            + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+            + "zl9HYIMxATFyqSiD9jsx");
+
+        //
+        // v3-cert1.pem
+        //
+        private static readonly byte[] cert4 = Base64.Decode(
+            "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx"
+            + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz"
+            + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw"
+            + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu"
+            + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2"
+            + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp"
+            + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C"
+            + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK"
+            + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x"
+            + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR"
+            + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB"
+            + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21"
+            + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3"
+            + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO");
+
+        //
+        // v3-cert2.pem
+        //
+        private static readonly byte[] cert5 = Base64.Decode(
+            "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD"
+            + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0"
+            + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu"
+            + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1"
+            + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV"
+            + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx"
+            + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA"
+            + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT"
+            + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ"
+            + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm"
+            + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc"
+            + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz"
+            + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap"
+            + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU=");
+
+        //
+        // pem encoded pkcs7
+        //
+        private static readonly byte[] cert6 = Base64.Decode(
+            "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w"
+            + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG"
+            + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy"
+            + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw"
+            + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi"
+            + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A"
+            + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH"
+            + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF"
+            + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d"
+            + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix"
+            + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR"
+            + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD"
+            + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj"
+            + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy"
+            + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy"
+            + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j"
+            + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg"
+            + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B"
+            + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB"
+            + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc"
+            + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG"
+            + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv"
+            + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B"
+            + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0"
+            + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg"
+            + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ"
+            + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln"
+            + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB"
+            + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx"
+            + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy"
+            + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD"
+            + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl"
+            + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz"
+            + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m"
+            + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv"
+            + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb"
+            + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK"
+            + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB"
+            + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0"
+            + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo"
+            + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB"
+            + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R"
+            + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y"
+            + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j"
+            + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu"
+            + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE"
+            + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg"
+            + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG"
+            + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU"
+            + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG"
+            + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w"
+            + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O"
+            + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy"
+            + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA==");
+
+        //
+        // dsaWithSHA1 cert
+        //
+        private static readonly byte[] cert7 = Base64.Decode(
+            "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG"
+            + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7"
+            + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh"
+            + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj"
+            + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z"
+            + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa"
+            + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw"
+            + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj"
+            + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE"
+            + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3"
+            + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn"
+            + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc"
+            + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg"
+            + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q"
+            + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH"
+            + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC"
+            + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC"
+            + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY"
+            + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1"
+            + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ"
+            + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T"
+            + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU"
+            + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji"
+            + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID"
+            + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh"
+            + "cg==");
+
+        //
+        // testcrl.pem
+        //
+        private static readonly byte[] crl1 = Base64.Decode(
+            "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT"
+            + "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy"
+            + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw"
+            + "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw"
+            + "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw"
+            + "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw"
+            + "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw"
+            + "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw"
+            + "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw"
+            + "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw"
+            + "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF"
+            + "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ"
+            + "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt"
+            + "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v");
+
+        //
+        // ecdsa cert with extra octet string.
+        //
+//		private static readonly byte[] oldEcdsa = Base64.Decode(
+//			"MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ"
+//			+ "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw"
+//			+ "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV"
+//			+ "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w"
+//			+ "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb"
+//			+ "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ"
+//			+ "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5"
+//			+ "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///"
+//			+ "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////"
+//			+ "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/"
+//			+ "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq"
+//			+ "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw"
+//			+ "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G"
+//			+ "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR");
+
+        private static readonly byte[] uncompressedPtEC = Base64.Decode(
+            "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ"
+            + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD"
+            + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw"
+            + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK"
+            + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G"
+            + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0"
+            + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ"
+            + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT"
+            + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2"
+            + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7"
+            + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA"
+            + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD"
+            + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn"
+            + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH"
+            + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB"
+            + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI"
+            + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt"
+            + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD"
+            + "z+fauEg=");
+
+        private static readonly byte[] keyUsage = Base64.Decode(
+            "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE"
+            + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50"
+            + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs"
+            + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp"
+            + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0"
+            + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa"
+            + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV"
+            + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw"
+            + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50"
+            + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50"
+            + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL"
+            + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv"
+            + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV"
+            + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173"
+            + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw"
+            + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50"
+            + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff"
+            + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE"
+            + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50"
+            + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD"
+            + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D"
+            + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx"
+            + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW"
+            + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG"
+            + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI"
+            + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ"
+            + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU"
+            + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE"
+            + "PHayXOw=");
+
+        private static readonly byte[] nameCert = Base64.Decode(
+            "MIIEFjCCA3+gAwIBAgIEdS8BozANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJE"+
+            "RTERMA8GA1UEChQIREFURVYgZUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRQ0Eg"+
+            "REFURVYgRDAzIDE6UE4wIhgPMjAwMTA1MTAxMDIyNDhaGA8yMDA0MDUwOTEwMjI0"+
+            "OFowgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIFAZCYXllcm4xEjAQBgNVBAcUCU7I"+
+            "dXJuYmVyZzERMA8GA1UEChQIREFURVYgZUcxHTAbBgNVBAUTFDAwMDAwMDAwMDA4"+
+            "OTU3NDM2MDAxMR4wHAYDVQQDFBVEaWV0bWFyIFNlbmdlbmxlaXRuZXIwgaEwDQYJ"+
+            "KoZIhvcNAQEBBQADgY8AMIGLAoGBAJLI/LJLKaHoMk8fBECW/od8u5erZi6jI8Ug"+
+            "C0a/LZyQUO/R20vWJs6GrClQtXB+AtfiBSnyZOSYzOdfDI8yEKPEv8qSuUPpOHps"+
+            "uNCFdLZF1vavVYGEEWs2+y+uuPmg8q1oPRyRmUZ+x9HrDvCXJraaDfTEd9olmB/Z"+
+            "AuC/PqpjAgUAwAAAAaOCAcYwggHCMAwGA1UdEwEB/wQCMAAwDwYDVR0PAQH/BAUD"+
+            "AwdAADAxBgNVHSAEKjAoMCYGBSskCAEBMB0wGwYIKwYBBQUHAgEWD3d3dy56cy5k"+
+            "YXRldi5kZTApBgNVHREEIjAggR5kaWV0bWFyLnNlbmdlbmxlaXRuZXJAZGF0ZXYu"+
+            "ZGUwgYQGA1UdIwR9MHuhc6RxMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1"+
+            "bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0"+
+            "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE6CBACm8LkwDgYHAoIG"+
+            "AQoMAAQDAQEAMEcGA1UdHwRAMD4wPKAUoBKGEHd3dy5jcmwuZGF0ZXYuZGWiJKQi"+
+            "MCAxCzAJBgNVBAYTAkRFMREwDwYDVQQKFAhEQVRFViBlRzAWBgUrJAgDBAQNMAsT"+
+            "A0VVUgIBBQIBATAdBgNVHQ4EFgQUfv6xFP0xk7027folhy+ziZvBJiwwLAYIKwYB"+
+            "BQUHAQEEIDAeMBwGCCsGAQUFBzABhhB3d3cuZGlyLmRhdGV2LmRlMA0GCSqGSIb3"+
+            "DQEBBQUAA4GBAEOVX6uQxbgtKzdgbTi6YLffMftFr2mmNwch7qzpM5gxcynzgVkg"+
+            "pnQcDNlm5AIbS6pO8jTCLfCd5TZ5biQksBErqmesIl3QD+VqtB+RNghxectZ3VEs"+
+            "nCUtcE7tJ8O14qwCb3TxS9dvIUFiVi4DjbxX46TdcTbTaK8/qr6AIf+l");
+
+        private static readonly byte[] probSelfSignedCert = Base64.Decode(
+            "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF"
+            + "MScwJQYDVQQKEx4gRElSRUNUSU9OIEdFTkVSQUxFIERFUyBJTVBPVFMxGjAYBgNV"
+            + "BAMTESBBQyBNSU5FRkkgQiBURVNUMB4XDTA0MDUwNzEyMDAwMFoXDTE0MDUwNzEy"
+            + "MDAwMFowRTEnMCUGA1UEChMeIERJUkVDVElPTiBHRU5FUkFMRSBERVMgSU1QT1RT"
+            + "MRowGAYDVQQDExEgQUMgTUlORUZJIEIgVEVTVDCBnzANBgkqhkiG9w0BAQEFAAOB"
+            + "jQAwgYkCgYEAveoCUOAukZdcFCs2qJk76vSqEX0ZFzHqQ6faBPZWjwkgUNwZ6m6m"
+            + "qWvvyq1cuxhoDvpfC6NXILETawYc6MNwwxsOtVVIjuXlcF17NMejljJafbPximEt"
+            + "DQ4LcQeSp4K7FyFlIAMLyt3BQ77emGzU5fjFTvHSUNb3jblx0sV28c0CAwEAAaOB"
+            + "tTCBsjAfBgNVHSMEGDAWgBSEJ4bLbvEQY8cYMAFKPFD1/fFXlzAdBgNVHQ4EFgQU"
+            + "hCeGy27xEGPHGDABSjxQ9f3xV5cwDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIB"
+            + "AQQEAwIBBjA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vYWRvbmlzLnBrNy5jZXJ0"
+            + "cGx1cy5uZXQvZGdpLXRlc3QuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN"
+            + "AQEFBQADgYEAmToHJWjd3+4zknfsP09H6uMbolHNGG0zTS2lrLKpzcmkQfjhQpT9"
+            + "LUTBvfs1jdjo9fGmQLvOG+Sm51Rbjglb8bcikVI5gLbclOlvqLkm77otjl4U4Z2/"
+            + "Y0vP14Aov3Sn3k+17EfReYUZI4liuB95ncobC4e8ZM++LjQcIM0s+Vs=");
+
+
+        private static readonly byte[] gost34102001base = Base64.Decode(
+            "MIIB1DCCAYECEEjpVKXP6Wn1yVz3VeeDQa8wCgYGKoUDAgIDBQAwbTEfMB0G"
+            + "A1UEAwwWR29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRv"
+            + "UHJvMQswCQYDVQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIw"
+            + "MDFAZXhhbXBsZS5jb20wHhcNMDUwMjAzMTUxNjQ2WhcNMTUwMjAzMTUxNjQ2"
+            + "WjBtMR8wHQYDVQQDDBZHb3N0UjM0MTAtMjAwMSBleGFtcGxlMRIwEAYDVQQK"
+            + "DAlDcnlwdG9Qcm8xCzAJBgNVBAYTAlJVMSkwJwYJKoZIhvcNAQkBFhpHb3N0"
+            + "UjM0MTAtMjAwMUBleGFtcGxlLmNvbTBjMBwGBiqFAwICEzASBgcqhQMCAiQA"
+            + "BgcqhQMCAh4BA0MABECElWh1YAIaQHUIzROMMYks/eUFA3pDXPRtKw/nTzJ+"
+            + "V4/rzBa5lYgD0Jp8ha4P5I3qprt+VsfLsN8PZrzK6hpgMAoGBiqFAwICAwUA"
+            + "A0EAHw5dw/aw/OiNvHyOE65kvyo4Hp0sfz3csM6UUkp10VO247ofNJK3tsLb"
+            + "HOLjUaqzefrlGb11WpHYrvWFg+FcLA==");
+
+        private static readonly byte[] gost341094base = Base64.Decode(
+            "MIICDzCCAbwCEBcxKsIb0ghYvAQeUjfQdFAwCgYGKoUDAgIEBQAwaTEdMBsG"
+            + "A1UEAwwUR29zdFIzNDEwLTk0IGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1By"
+            + "bzELMAkGA1UEBhMCUlUxJzAlBgkqhkiG9w0BCQEWGEdvc3RSMzQxMC05NEBl"
+            + "eGFtcGxlLmNvbTAeFw0wNTAyMDMxNTE2NTFaFw0xNTAyMDMxNTE2NTFaMGkx"
+            + "HTAbBgNVBAMMFEdvc3RSMzQxMC05NCBleGFtcGxlMRIwEAYDVQQKDAlDcnlw"
+            + "dG9Qcm8xCzAJBgNVBAYTAlJVMScwJQYJKoZIhvcNAQkBFhhHb3N0UjM0MTAt"
+            + "OTRAZXhhbXBsZS5jb20wgaUwHAYGKoUDAgIUMBIGByqFAwICIAIGByqFAwIC"
+            + "HgEDgYQABIGAu4Rm4XmeWzTYLIB/E6gZZnFX/oxUJSFHbzALJ3dGmMb7R1W+"
+            + "t7Lzk2w5tUI3JoTiDRCKJA4fDEJNKzsRK6i/ZjkyXJSLwaj+G2MS9gklh8x1"
+            + "G/TliYoJgmjTXHemD7aQEBON4z58nJHWrA0ILD54wbXCtrcaqCqLRYGTMjJ2"
+            + "+nswCgYGKoUDAgIEBQADQQBxKNhOmjgz/i5CEgLOyKyz9pFGkDcaymsWYQWV"
+            + "v7CZ0pTM8IzMzkUBW3GHsUjCFpanFZDfg2zuN+3kT+694n9B");
+
+        private static readonly byte[] gost341094A = Base64.Decode(
+            "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOZGVmYXVsdDM0MTAtOTQx"
+            + "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1vbGExDDAKBgNVBAgT"
+            + "A01FTDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx"
+            + "MzExNTdaFw0wNjAzMjkxMzExNTdaMIGBMRcwFQYDVQQDEw5kZWZhdWx0MzQxMC05NDENMAsGA1UE"
+            + "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLW9sYTEMMAoGA1UECBMDTUVMMQsw"
+            + "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq"
+            + "hQMCAiACBgcqhQMCAh4BA4GEAASBgIQACDLEuxSdRDGgdZxHmy30g/DUYkRxO9Mi/uSHX5NjvZ31"
+            + "b7JMEMFqBtyhql1HC5xZfUwZ0aT3UnEFDfFjLP+Bf54gA+LPkQXw4SNNGOj+klnqgKlPvoqMGlwa"
+            + "+hLPKbS561WpvB2XSTgbV+pqqXR3j6j30STmybelEV3RdS2Now8wDTALBgNVHQ8EBAMCB4AwCgYG"
+            + "KoUDAgIEBQADQQBCFy7xWRXtNVXflKvDs0pBdBuPzjCMeZAXVxK8vUxsxxKu76d9CsvhgIFknFRi"
+            + "wWTPiZenvNoJ4R1uzeX+vREm");
+
+        private static readonly byte[] gost341094B = Base64.Decode(
+            "MIICSDCCAfWgAwIBAgIBATAKBgYqhQMCAgQFADCBgTEXMBUGA1UEAxMOcGFyYW0xLTM0MTAtOTQx"
+            +  "DTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNVBAgT"
+            +  "A01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAzMjkx"
+            +  "MzEzNTZaFw0wNjAzMjkxMzEzNTZaMIGBMRcwFQYDVQQDEw5wYXJhbTEtMzQxMC05NDENMAsGA1UE"
+            +  "ChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMDTWVsMQsw"
+            +  "CQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MIGlMBwGBiqFAwICFDASBgcq"
+            +  "hQMCAiADBgcqhQMCAh4BA4GEAASBgEa+AAcZmijWs1M9x5Pn9efE8D9ztG1NMoIt0/hNZNqln3+j"
+            +  "lMZjyqPt+kTLIjtmvz9BRDmIDk6FZz+4LhG2OTL7yGpWfrMxMRr56nxomTN9aLWRqbyWmn3brz9Y"
+            +  "AUD3ifnwjjIuW7UM84JNlDTOdxx0XRUfLQIPMCXe9cO02Xskow8wDTALBgNVHQ8EBAMCB4AwCgYG"
+            +  "KoUDAgIEBQADQQBzFcnuYc/639OTW+L5Ecjw9KxGr+dwex7lsS9S1BUgKa3m1d5c+cqI0B2XUFi5"
+            +  "4iaHHJG0dCyjtQYLJr0OZjRw");
+
+        private static readonly byte[] gost34102001A = Base64.Decode(
+            "MIICCzCCAbigAwIBAgIBATAKBgYqhQMCAgMFADCBhDEaMBgGA1UEAxMRZGVmYXVsdC0zNDEwLTIw"
+            + "MDExDTALBgNVBAoTBERpZ3QxDzANBgNVBAsTBkNyeXB0bzEOMAwGA1UEBxMFWS1PbGExDDAKBgNV"
+            + "BAgTA01lbDELMAkGA1UEBhMCcnUxGzAZBgkqhkiG9w0BCQEWDHRlc3RAdGVzdC5ydTAeFw0wNTAz"
+            + "MjkxMzE4MzFaFw0wNjAzMjkxMzE4MzFaMIGEMRowGAYDVQQDExFkZWZhdWx0LTM0MTAtMjAwMTEN"
+            + "MAsGA1UEChMERGlndDEPMA0GA1UECxMGQ3J5cHRvMQ4wDAYDVQQHEwVZLU9sYTEMMAoGA1UECBMD"
+            + "TWVsMQswCQYDVQQGEwJydTEbMBkGCSqGSIb3DQEJARYMdGVzdEB0ZXN0LnJ1MGMwHAYGKoUDAgIT"
+            + "MBIGByqFAwICIwEGByqFAwICHgEDQwAEQG/4c+ZWb10IpeHfmR+vKcbpmSOClJioYmCVgnojw0Xn"
+            + "ned0KTg7TJreRUc+VX7vca4hLQaZ1o/TxVtfEApK/O6jDzANMAsGA1UdDwQEAwIHgDAKBgYqhQMC"
+            + "AgMFAANBAN8y2b6HuIdkD3aWujpfQbS1VIA/7hro4vLgDhjgVmev/PLzFB8oTh3gKhExpDo82IEs"
+            + "ZftGNsbbyp1NFg7zda0=");
+
+        private static readonly byte[] gostCA1 = Base64.Decode(
+            "MIIDNDCCAuGgAwIBAgIQZLcKDcWcQopF+jp4p9jylDAKBgYqhQMCAgQFADBm"
+            + "MQswCQYDVQQGEwJSVTEPMA0GA1UEBxMGTW9zY293MRcwFQYDVQQKEw5PT08g"
+            + "Q3J5cHRvLVBybzEUMBIGA1UECxMLRGV2ZWxvcG1lbnQxFzAVBgNVBAMTDkNQ"
+            + "IENTUCBUZXN0IENBMB4XDTAyMDYwOTE1NTIyM1oXDTA5MDYwOTE1NTkyOVow"
+            + "ZjELMAkGA1UEBhMCUlUxDzANBgNVBAcTBk1vc2NvdzEXMBUGA1UEChMOT09P"
+            + "IENyeXB0by1Qcm8xFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5D"
+            + "UCBDU1AgVGVzdCBDQTCBpTAcBgYqhQMCAhQwEgYHKoUDAgIgAgYHKoUDAgIe"
+            + "AQOBhAAEgYAYglywKuz1nMc9UiBYOaulKy53jXnrqxZKbCCBSVaJ+aCKbsQm"
+            + "glhRFrw6Mwu8Cdeabo/ojmea7UDMZd0U2xhZFRti5EQ7OP6YpqD0alllo7za"
+            + "4dZNXdX+/ag6fOORSLFdMpVx5ganU0wHMPk67j+audnCPUj/plbeyccgcdcd"
+            + "WaOCASIwggEeMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud"
+            + "DgQWBBTe840gTo4zt2twHilw3PD9wJaX0TCBygYDVR0fBIHCMIG/MDygOqA4"
+            + "hjYtaHR0cDovL2ZpZXdhbGwvQ2VydEVucm9sbC9DUCUyMENTUCUyMFRlc3Ql"
+            + "MjBDQSgzKS5jcmwwRKBCoECGPmh0dHA6Ly93d3cuY3J5cHRvcHJvLnJ1L0Nl"
+            + "cnRFbnJvbGwvQ1AlMjBDU1AlMjBUZXN0JTIwQ0EoMykuY3JsMDmgN6A1hjMt"
+            + "ZmlsZTovL1xcZmlld2FsbFxDZXJ0RW5yb2xsXENQIENTUCBUZXN0IENBKDMp"
+            + "LmNybC8wEgYJKwYBBAGCNxUBBAUCAwMAAzAKBgYqhQMCAgQFAANBAIJi7ni7"
+            + "9rwMR5rRGTFftt2k70GbqyUEfkZYOzrgdOoKiB4IIsIstyBX0/ne6GsL9Xan"
+            + "G2IN96RB7KrowEHeW+k=");
+
+        private static readonly byte[] gostCA2 = Base64.Decode(
+            "MIIC2DCCAoWgAwIBAgIQe9ZCugm42pRKNcHD8466zTAKBgYqhQMCAgMFADB+"
+            + "MRowGAYJKoZIhvcNAQkBFgtzYmFAZGlndC5ydTELMAkGA1UEBhMCUlUxDDAK"
+            + "BgNVBAgTA01FTDEUMBIGA1UEBxMLWW9zaGthci1PbGExDTALBgNVBAoTBERp"
+            + "Z3QxDzANBgNVBAsTBkNyeXB0bzEPMA0GA1UEAxMGc2JhLUNBMB4XDTA0MDgw"
+            + "MzEzMzE1OVoXDTE0MDgwMzEzNDAxMVowfjEaMBgGCSqGSIb3DQEJARYLc2Jh"
+            + "QGRpZ3QucnUxCzAJBgNVBAYTAlJVMQwwCgYDVQQIEwNNRUwxFDASBgNVBAcT"
+            + "C1lvc2hrYXItT2xhMQ0wCwYDVQQKEwREaWd0MQ8wDQYDVQQLEwZDcnlwdG8x"
+            + "DzANBgNVBAMTBnNiYS1DQTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMC"
+            + "Ah4BA0MABEDMSy10CuOH+i8QKG2UWA4XmCt6+BFrNTZQtS6bOalyDY8Lz+G7"
+            + "HybyipE3PqdTB4OIKAAPsEEeZOCZd2UXGQm5o4HaMIHXMBMGCSsGAQQBgjcU"
+            + "AgQGHgQAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud"
+            + "DgQWBBRJJl3LcNMxkZI818STfoi3ng1xoDBxBgNVHR8EajBoMDGgL6Athito"
+            + "dHRwOi8vc2JhLmRpZ3QubG9jYWwvQ2VydEVucm9sbC9zYmEtQ0EuY3JsMDOg"
+            + "MaAvhi1maWxlOi8vXFxzYmEuZGlndC5sb2NhbFxDZXJ0RW5yb2xsXHNiYS1D"
+            + "QS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwCgYGKoUDAgIDBQADQQA+BRJHbc/p"
+            + "q8EYl6iJqXCuR+ozRmH7hPAP3c4KqYSC38TClCgBloLapx/3/WdatctFJW/L"
+            + "mcTovpq088927shE");
+
+        private static readonly byte[] inDirectCrl = Base64.Decode(
+            "MIIdXjCCHMcCAQEwDQYJKoZIhvcNAQEFBQAwdDELMAkGA1UEBhMCREUxHDAaBgNV"
+            +"BAoUE0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0"
+            +"MS4wDAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBO"
+            +"Fw0wNjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIbfzB+AgQvrj/pFw0wMzA3"
+            +"MjIwNTQxMjhaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+oXDTAzMDcyMjA1NDEyOFowZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/5xcNMDQwNDA1MTMxODE3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/oFw0wNDA0"
+            +"MDUxMzE4MTdaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+UXDTAzMDExMzExMTgxMVowZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/5hcNMDMwMTEzMTExODExWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/jFw0wMzAx"
+            +"MTMxMTI2NTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP+QXDTAzMDExMzExMjY1NlowZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/4hcNMDQwNzEzMDc1ODM4WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/eFw0wMzAy"
+            +"MTcwNjMzMjVaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP98XDTAzMDIxNzA2MzMyNVowZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/0xcNMDMwMjE3MDYzMzI1WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/dFw0wMzAx"
+            +"MTMxMTI4MTRaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9cXDTAzMDExMzExMjcwN1owZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/2BcNMDMwMTEzMTEyNzA3WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNDpQTjB+AgQvrj/VFw0wMzA0"
+            +"MzAxMjI3NTNaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYD"
+            +"VQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMU"
+            +"EVNpZ0cgVGVzdCBDQSA0OlBOMH4CBC+uP9YXDTAzMDQzMDEyMjc1M1owZzBlBgNV"
+            +"HR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDQ6"
+            +"UE4wfgIEL64/xhcNMDMwMjEyMTM0NTQwWjBnMGUGA1UdHQEB/wRbMFmkVzBVMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKC"
+            +"BgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQTjCBkAIEL64/xRcNMDMw"
+            +"MjEyMTM0NTQwWjB5MHcGA1UdHQEB/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoG"
+            +"A1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwG"
+            +"BwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0EgNTpQTjB+AgQvrj/CFw0w"
+            +"MzAyMTIxMzA5MTZaMGcwZQYDVR0dAQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRww"
+            +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNV"
+            +"BAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj/BFw0wMzAyMTIxMzA4NDBaMHkw"
+            +"dwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2No"
+            +"ZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAY"
+            +"BgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uP74XDTAzMDIxNzA2MzcyNVow"
+            +"ZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz"
+            +"Y2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3Qg"
+            +"Q0EgMTE6UE4wgZACBC+uP70XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0BAf8EbTBr"
+            +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx"
+            +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU"
+            +"ZXN0IENBIDU6UE4wgZACBC+uP7AXDTAzMDIxMjEzMDg1OVoweTB3BgNVHR0BAf8E"
+            +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+            +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln"
+            +"RyBUZXN0IENBIDU6UE4wgZACBC+uP68XDTAzMDIxNzA2MzcyNVoweTB3BgNVHR0B"
+            +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr"
+            +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR"
+            +"U2lnRyBUZXN0IENBIDU6UE4wfgIEL64/kxcNMDMwNDEwMDUyNjI4WjBnMGUGA1Ud"
+            +"HQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVs"
+            +"ZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVzdCBDQSAxMTpQ"
+            +"TjCBkAIEL64/khcNMDMwNDEwMDUyNjI4WjB5MHcGA1UdHQEB/wRtMGukaTBnMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEQMA4GA1UE"
+            +"CxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdHIFRlc3QgQ0Eg"
+            +"NTpQTjB+AgQvrj8/Fw0wMzAyMjYxMTA0NDRaMGcwZQYDVR0dAQH/BFswWaRXMFUx"
+            +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMSgwDAYH"
+            +"AoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBOMIGQAgQvrj8+Fw0w"
+            +"MzAyMjYxMTA0NDRaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJBgNVBAYTAkRFMRww"
+            +"GgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQLFAdUZWxlU2VjMSgw"
+            +"DAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA1OlBOMH4CBC+uPs0X"
+            +"DTAzMDUyMDA1MjczNlowZzBlBgNVHR0BAf8EWzBZpFcwVTELMAkGA1UEBhMCREUx"
+            +"HDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxKDAMBgcCggYBCgcUEwExMBgG"
+            +"A1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZACBC+uPswXDTAzMDUyMDA1MjczNlow"
+            +"eTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRz"
+            +"Y2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwEx"
+            +"MBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4wfgIEL64+PBcNMDMwNjE3MTAzNDE2"
+            +"WjBnMGUGA1UdHQEB/wRbMFmkVzBVMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1"
+            +"dHNjaGUgVGVsZWtvbSBBRzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFUVEMgVGVz"
+            +"dCBDQSAxMTpQTjCBkAIEL64+OxcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB/wRt"
+            +"MGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBB"
+            +"RzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFTaWdH"
+            +"IFRlc3QgQ0EgNjpQTjCBkAIEL64+OhcNMDMwNjE3MTAzNDE2WjB5MHcGA1UdHQEB"
+            +"/wRtMGukaTBnMQswCQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtv"
+            +"bSBBRzEQMA4GA1UECxQHVGVsZVNlYzEoMAwGBwKCBgEKBxQTATEwGAYDVQQDFBFT"
+            +"aWdHIFRlc3QgQ0EgNjpQTjB+AgQvrj45Fw0wMzA2MTcxMzAxMDBaMGcwZQYDVR0d"
+            +"AQH/BFswWaRXMFUxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxl"
+            +"a29tIEFHMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVRUQyBUZXN0IENBIDExOlBO"
+            +"MIGQAgQvrj44Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcxCzAJ"
+            +"BgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYDVQQL"
+            +"FAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBDQSA2"
+            +"OlBOMIGQAgQvrj43Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6RpMGcx"
+            +"CzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAwDgYD"
+            +"VQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVzdCBD"
+            +"QSA2OlBOMIGQAgQvrj42Fw0wMzA2MTcxMzAxMDBaMHkwdwYDVR0dAQH/BG0wa6Rp"
+            +"MGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFHMRAw"
+            +"DgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cgVGVz"
+            +"dCBDQSA2OlBOMIGQAgQvrj4zFw0wMzA2MTcxMDM3NDlaMHkwdwYDVR0dAQH/BG0w"
+            +"a6RpMGcxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH"
+            +"MRAwDgYDVQQLFAdUZWxlU2VjMSgwDAYHAoIGAQoHFBMBMTAYBgNVBAMUEVNpZ0cg"
+            +"VGVzdCBDQSA2OlBOMH4CBC+uPjEXDTAzMDYxNzEwNDI1OFowZzBlBgNVHR0BAf8E"
+            +"WzBZpFcwVTELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+            +"QUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRVFRDIFRlc3QgQ0EgMTE6UE4wgZAC"
+            +"BC+uPjAXDTAzMDYxNzEwNDI1OFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkGA1UE"
+            +"BhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsUB1Rl"
+            +"bGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6UE4w"
+            +"gZACBC+uPakXDTAzMTAyMjExMzIyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzELMAkG"
+            +"A1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNVBAsU"
+            +"B1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENBIDY6"
+            +"UE4wgZACBC+uPLIXDTA1MDMxMTA2NDQyNFoweTB3BgNVHR0BAf8EbTBrpGkwZzEL"
+            +"MAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAOBgNV"
+            +"BAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0IENB"
+            +"IDY6UE4wgZACBC+uPKsXDTA0MDQwMjA3NTQ1M1oweTB3BgNVHR0BAf8EbTBrpGkw"
+            +"ZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcxEDAO"
+            +"BgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBUZXN0"
+            +"IENBIDY6UE4wgZACBC+uOugXDTA1MDEyNzEyMDMyNFoweTB3BgNVHR0BAf8EbTBr"
+            +"pGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20gQUcx"
+            +"EDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2lnRyBU"
+            +"ZXN0IENBIDY6UE4wgZACBC+uOr4XDTA1MDIxNjA3NTcxNloweTB3BgNVHR0BAf8E"
+            +"bTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVrb20g"
+            +"QUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRU2ln"
+            +"RyBUZXN0IENBIDY6UE4wgZACBC+uOqcXDTA1MDMxMDA1NTkzNVoweTB3BgNVHR0B"
+            +"Af8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRlbGVr"
+            +"b20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQR"
+            +"U2lnRyBUZXN0IENBIDY6UE4wgZACBC+uOjwXDTA1MDUxMTEwNDk0NloweTB3BgNV"
+            +"HR0BAf8EbTBrpGkwZzELMAkGA1UEBhMCREUxHDAaBgNVBAoUE0RldXRzY2hlIFRl"
+            +"bGVrb20gQUcxEDAOBgNVBAsUB1RlbGVTZWMxKDAMBgcCggYBCgcUEwExMBgGA1UE"
+            +"AxQRU2lnRyBUZXN0IENBIDY6UE4wgaoCBC+sbdUXDTA1MTExMTEwMDMyMVowgZIw"
+            +"gY8GA1UdHQEB/wSBhDCBgaR/MH0xCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0"
+            +"c2NoZSBUZWxla29tIEFHMR8wHQYDVQQLFBZQcm9kdWt0emVudHJ1bSBUZWxlU2Vj"
+            +"MS8wDAYHAoIGAQoHFBMBMTAfBgNVBAMUGFRlbGVTZWMgUEtTIFNpZ0cgQ0EgMTpQ"
+            +"TjCBlQIEL64uaBcNMDYwMTIzMTAyNTU1WjB+MHwGA1UdHQEB/wRyMHCkbjBsMQsw"
+            +"CQYDVQQGEwJERTEcMBoGA1UEChQTRGV1dHNjaGUgVGVsZWtvbSBBRzEWMBQGA1UE"
+            +"CxQNWmVudHJhbGUgQm9ubjEnMAwGBwKCBgEKBxQTATEwFwYDVQQDFBBUVEMgVGVz"
+            +"dCBDQSA5OlBOMIGVAgQvribHFw0wNjA4MDEwOTQ4NDRaMH4wfAYDVR0dAQH/BHIw"
+            +"cKRuMGwxCzAJBgNVBAYTAkRFMRwwGgYDVQQKFBNEZXV0c2NoZSBUZWxla29tIEFH"
+            +"MRYwFAYDVQQLFA1aZW50cmFsZSBCb25uMScwDAYHAoIGAQoHFBMBMTAXBgNVBAMU"
+            +"EFRUQyBUZXN0IENBIDk6UE6ggZswgZgwCwYDVR0UBAQCAhEMMB8GA1UdIwQYMBaA"
+            +"FANbyNumDI9545HwlCF26NuOJC45MA8GA1UdHAEB/wQFMAOEAf8wVwYDVR0SBFAw"
+            +"ToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1ULVRlbGVTZWMgVGVzdCBESVIg"
+            +"ODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1kZTANBgkqhkiG9w0BAQUFAAOB"
+            +"gQBewL5gLFHpeOWO07Vk3Gg7pRDuAlvaovBH4coCyCWpk5jEhUfFSYEDuaQB7do4"
+            +"IlJmeTHvkI0PIZWJ7bwQ2PVdipPWDx0NVwS/Cz5jUKiS3BbAmZQZOueiKLFpQq3A"
+            +"b8aOHA7WHU4078/1lM+bgeu33Ln1CGykEbmSjA/oKPi/JA==");
+
+        private static readonly byte[] directCRL = Base64.Decode(
+            "MIIGXTCCBckCAQEwCgYGKyQDAwECBQAwdDELMAkGA1UEBhMCREUxHDAaBgNVBAoU"
+            +"E0RldXRzY2hlIFRlbGVrb20gQUcxFzAVBgNVBAsUDlQtVGVsZVNlYyBUZXN0MS4w"
+            +"DAYHAoIGAQoHFBMBMTAeBgNVBAMUF1QtVGVsZVNlYyBUZXN0IERJUiA4OlBOFw0w"
+            +"NjA4MDQwODQ1MTRaFw0wNjA4MDQxNDQ1MTRaMIIElTAVAgQvrj/pFw0wMzA3MjIw"
+            +"NTQxMjhaMBUCBC+uP+oXDTAzMDcyMjA1NDEyOFowFQIEL64/5xcNMDQwNDA1MTMx"
+            +"ODE3WjAVAgQvrj/oFw0wNDA0MDUxMzE4MTdaMBUCBC+uP+UXDTAzMDExMzExMTgx"
+            +"MVowFQIEL64/5hcNMDMwMTEzMTExODExWjAVAgQvrj/jFw0wMzAxMTMxMTI2NTZa"
+            +"MBUCBC+uP+QXDTAzMDExMzExMjY1NlowFQIEL64/4hcNMDQwNzEzMDc1ODM4WjAV"
+            +"AgQvrj/eFw0wMzAyMTcwNjMzMjVaMBUCBC+uP98XDTAzMDIxNzA2MzMyNVowFQIE"
+            +"L64/0xcNMDMwMjE3MDYzMzI1WjAVAgQvrj/dFw0wMzAxMTMxMTI4MTRaMBUCBC+u"
+            +"P9cXDTAzMDExMzExMjcwN1owFQIEL64/2BcNMDMwMTEzMTEyNzA3WjAVAgQvrj/V"
+            +"Fw0wMzA0MzAxMjI3NTNaMBUCBC+uP9YXDTAzMDQzMDEyMjc1M1owFQIEL64/xhcN"
+            +"MDMwMjEyMTM0NTQwWjAVAgQvrj/FFw0wMzAyMTIxMzQ1NDBaMBUCBC+uP8IXDTAz"
+            +"MDIxMjEzMDkxNlowFQIEL64/wRcNMDMwMjEyMTMwODQwWjAVAgQvrj++Fw0wMzAy"
+            +"MTcwNjM3MjVaMBUCBC+uP70XDTAzMDIxNzA2MzcyNVowFQIEL64/sBcNMDMwMjEy"
+            +"MTMwODU5WjAVAgQvrj+vFw0wMzAyMTcwNjM3MjVaMBUCBC+uP5MXDTAzMDQxMDA1"
+            +"MjYyOFowFQIEL64/khcNMDMwNDEwMDUyNjI4WjAVAgQvrj8/Fw0wMzAyMjYxMTA0"
+            +"NDRaMBUCBC+uPz4XDTAzMDIyNjExMDQ0NFowFQIEL64+zRcNMDMwNTIwMDUyNzM2"
+            +"WjAVAgQvrj7MFw0wMzA1MjAwNTI3MzZaMBUCBC+uPjwXDTAzMDYxNzEwMzQxNlow"
+            +"FQIEL64+OxcNMDMwNjE3MTAzNDE2WjAVAgQvrj46Fw0wMzA2MTcxMDM0MTZaMBUC"
+            +"BC+uPjkXDTAzMDYxNzEzMDEwMFowFQIEL64+OBcNMDMwNjE3MTMwMTAwWjAVAgQv"
+            +"rj43Fw0wMzA2MTcxMzAxMDBaMBUCBC+uPjYXDTAzMDYxNzEzMDEwMFowFQIEL64+"
+            +"MxcNMDMwNjE3MTAzNzQ5WjAVAgQvrj4xFw0wMzA2MTcxMDQyNThaMBUCBC+uPjAX"
+            +"DTAzMDYxNzEwNDI1OFowFQIEL649qRcNMDMxMDIyMTEzMjI0WjAVAgQvrjyyFw0w"
+            +"NTAzMTEwNjQ0MjRaMBUCBC+uPKsXDTA0MDQwMjA3NTQ1M1owFQIEL6466BcNMDUw"
+            +"MTI3MTIwMzI0WjAVAgQvrjq+Fw0wNTAyMTYwNzU3MTZaMBUCBC+uOqcXDTA1MDMx"
+            +"MDA1NTkzNVowFQIEL646PBcNMDUwNTExMTA0OTQ2WjAVAgQvrG3VFw0wNTExMTEx"
+            +"MDAzMjFaMBUCBC+uLmgXDTA2MDEyMzEwMjU1NVowFQIEL64mxxcNMDYwODAxMDk0"
+            +"ODQ0WqCBijCBhzALBgNVHRQEBAICEQwwHwYDVR0jBBgwFoAUA1vI26YMj3njkfCU"
+            +"IXbo244kLjkwVwYDVR0SBFAwToZMbGRhcDovL3Brc2xkYXAudHR0Yy5kZS9vdT1U"
+            +"LVRlbGVTZWMgVGVzdCBESVIgODpQTixvPURldXRzY2hlIFRlbGVrb20gQUcsYz1k"
+            +"ZTAKBgYrJAMDAQIFAAOBgQArj4eMlbAwuA2aS5O4UUUHQMKKdK/dtZi60+LJMiMY"
+            +"ojrMIf4+ZCkgm1Ca0Cd5T15MJxVHhh167Ehn/Hd48pdnAP6Dfz/6LeqkIHGWMHR+"
+            +"z6TXpwWB+P4BdUec1ztz04LypsznrHcLRa91ixg9TZCb1MrOG+InNhleRs1ImXk8"
+            +"MQ==");
+
+        private static readonly byte[] pkcs7CrlProblem = Base64.Decode(
+              "MIIwSAYJKoZIhvcNAQcCoIIwOTCCMDUCAQExCzAJBgUrDgMCGgUAMAsGCSqG"
+            + "SIb3DQEHAaCCEsAwggP4MIIC4KADAgECAgF1MA0GCSqGSIb3DQEBBQUAMEUx"
+            + "CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR4wHAYDVQQD"
+            + "ExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUwHhcNMDQxMjAyMjEyNTM5WhcNMDYx"
+            + "MjMwMjEyNTM5WjBMMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMR2VvVHJ1c3Qg"
+            + "SW5jMSYwJAYDVQQDEx1HZW9UcnVzdCBBZG9iZSBPQ1NQIFJlc3BvbmRlcjCB"
+            + "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4gnNYhtw7U6QeVXZODnGhHMj"
+            + "+OgZ0DB393rEk6a2q9kq129IA2e03yKBTfJfQR9aWKc2Qj90dsSqPjvTDHFG"
+            + "Qsagm2FQuhnA3fb1UWhPzeEIdm6bxDsnQ8nWqKqxnWZzELZbdp3I9bBLizIq"
+            + "obZovzt60LNMghn/unvvuhpeVSsCAwEAAaOCAW4wggFqMA4GA1UdDwEB/wQE"
+            + "AwIE8DCB5QYDVR0gAQH/BIHaMIHXMIHUBgkqhkiG9y8BAgEwgcYwgZAGCCsG"
+            + "AQUFBwICMIGDGoGAVGhpcyBjZXJ0aWZpY2F0ZSBoYXMgYmVlbiBpc3N1ZWQg"
+            + "aW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBBY3JvYmF0IENyZWRlbnRpYWxzIENQ"
+            + "UyBsb2NhdGVkIGF0IGh0dHA6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jlc291cmNl"
+            + "cy9jcHMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2VvdHJ1c3QuY29tL3Jl"
+            + "c291cmNlcy9jcHMwEwYDVR0lBAwwCgYIKwYBBQUHAwkwOgYDVR0fBDMwMTAv"
+            + "oC2gK4YpaHR0cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9hZG9iZWNhMS5j"
+            + "cmwwHwYDVR0jBBgwFoAUq4BZw2WDbR19E70Zw+wajw1HaqMwDQYJKoZIhvcN"
+            + "AQEFBQADggEBAENJf1BD7PX5ivuaawt90q1OGzXpIQL/ClzEeFVmOIxqPc1E"
+            + "TFRq92YuxG5b6+R+k+tGkmCwPLcY8ipg6ZcbJ/AirQhohzjlFuT6YAXsTfEj"
+            + "CqEZfWM2sS7crK2EYxCMmKE3xDfPclYtrAoz7qZvxfQj0TuxHSstHZv39wu2"
+            + "ZiG1BWiEcyDQyTgqTOXBoZmfJtshuAcXmTpgkrYSrS37zNlPTGh+pMYQ0yWD"
+            + "c8OQRJR4OY5ZXfdna01mjtJTOmj6/6XPoLPYTq2gQrc2BCeNJ4bEhLb7sFVB"
+            + "PbwPrpzTE/HRbQHDrzj0YimDxeOUV/UXctgvYwHNtEkcBLsOm/uytMYwggSh"
+            + "MIIDiaADAgECAgQ+HL0oMA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNVBAYTAlVT"
+            + "MSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UE"
+            + "CxMUQWRvYmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3Qg"
+            + "Q0EwHhcNMDMwMTA4MjMzNzIzWhcNMjMwMTA5MDAwNzIzWjBpMQswCQYDVQQG"
+            + "EwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxHTAb"
+            + "BgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYwFAYDVQQDEw1BZG9iZSBS"
+            + "b290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzE9UhPen"
+            + "ouczU38/nBKIayyZR2d+Dx65rRSI+cMQ2B3w8NWfaQovWTWwzGypTJwVoJ/O"
+            + "IL+gz1Ti4CBmRT85hjh+nMSOByLGJPYBErA131XqaZCw24U3HuJOB7JCoWoT"
+            + "aaBm6oCREVkqmwh5WiBELcm9cziLPC/gQxtdswvwrzUaKf7vppLdgUydPVmO"
+            + "rTE8QH6bkTYG/OJcjdGNJtVcRc+vZT+xqtJilvSoOOq6YEL09BxKNRXO+E4i"
+            + "Vg+VGMX4lp+f+7C3eCXpgGu91grwxnSUnfMPUNuad85LcIMjjaDKeCBEXDxU"
+            + "ZPHqojAZn+pMBk0GeEtekt8i0slns3rSAQIDAQABo4IBTzCCAUswEQYJYIZI"
+            + "AYb4QgEBBAQDAgAHMIGOBgNVHR8EgYYwgYMwgYCgfqB8pHoweDELMAkGA1UE"
+            + "BhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMR0w"
+            + "GwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEWMBQGA1UEAxMNQWRvYmUg"
+            + "Um9vdCBDQTENMAsGA1UEAxMEQ1JMMTArBgNVHRAEJDAigA8yMDAzMDEwODIz"
+            + "MzcyM1qBDzIwMjMwMTA5MDAwNzIzWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgw"
+            + "FoAUgrc4SpOqmxDvgLvZVOLxD/uAnN4wHQYDVR0OBBYEFIK3OEqTqpsQ74C7"
+            + "2VTi8Q/7gJzeMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjYu"
+            + "MDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQAy2p9DdcH6b8lv26sdNjc+"
+            + "vGEZNrcCPB0jWZhsnu5NhedUyCAfp9S74r8Ad30ka3AvXME6dkm10+AjhCpx"
+            + "aiLzwScpmBX2NZDkBEzDjbyfYRzn/SSM0URDjBa6m02l1DUvvBHOvfdRN42f"
+            + "kOQU8Rg/vulZEjX5M5LznuDVa5pxm5lLyHHD4bFhCcTl+pHwQjo3fTT5cujN"
+            + "qmIcIenV9IIQ43sFti1oVgt+fpIsb01yggztVnSynbmrLSsdEF/bJ3Vwj/0d"
+            + "1+ICoHnlHOX/r2RAUS2em0fbQqV8H8KmSLDXvpJpTaT2KVfFeBEY3IdRyhOy"
+            + "Yp1PKzK9MaXB+lKrBYjIMIIEyzCCA7OgAwIBAgIEPhy9tTANBgkqhkiG9w0B"
+            + "AQUFADBpMQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJ"
+            + "bmNvcnBvcmF0ZWQxHTAbBgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYw"
+            + "FAYDVQQDEw1BZG9iZSBSb290IENBMB4XDTA0MDExNzAwMDMzOVoXDTE1MDEx"
+            + "NTA4MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu"
+            + "Yy4xHjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTCCASIwDQYJKoZI"
+            + "hvcNAQEBBQADggEPADCCAQoCggEBAKfld+BkeFrnOYW8r9L1WygTDlTdSfrO"
+            + "YvWS/Z6Ye5/l+HrBbOHqQCXBcSeCpz7kB2WdKMh1FOE4e9JlmICsHerBLdWk"
+            + "emU+/PDb69zh8E0cLoDfxukF6oVPXj6WSThdSG7H9aXFzRr6S3XGCuvgl+Qw"
+            + "DTLiLYW+ONF6DXwt3TQQtKReJjOJZk46ZZ0BvMStKyBaeB6DKZsmiIo89qso"
+            + "13VDZINH2w1KvXg0ygDizoNtbvgAPFymwnsINS1klfQlcvn0x0RJm9bYQXK3"
+            + "5GNZAgL3M7Lqrld0jMfIUaWvuHCLyivytRuzq1dJ7E8rmidjDEk/G+27pf13"
+            + "fNZ7vR7M+IkCAwEAAaOCAZ0wggGZMBIGA1UdEwEB/wQIMAYBAf8CAQEwUAYD"
+            + "VR0gBEkwRzBFBgkqhkiG9y8BAgEwODA2BggrBgEFBQcCARYqaHR0cHM6Ly93"
+            + "d3cuYWRvYmUuY29tL21pc2MvcGtpL2Nkc19jcC5odG1sMBQGA1UdJQQNMAsG"
+            + "CSqGSIb3LwEBBTCBsgYDVR0fBIGqMIGnMCKgIKAehhxodHRwOi8vY3JsLmFk"
+            + "b2JlLmNvbS9jZHMuY3JsMIGAoH6gfKR6MHgxCzAJBgNVBAYTAlVTMSMwIQYD"
+            + "VQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRv"
+            + "YmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0ExDTAL"
+            + "BgNVBAMTBENSTDEwCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFIK3OEqTqpsQ"
+            + "74C72VTi8Q/7gJzeMB0GA1UdDgQWBBSrgFnDZYNtHX0TvRnD7BqPDUdqozAZ"
+            + "BgkqhkiG9n0HQQAEDDAKGwRWNi4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA"
+            + "PzlZLqIAjrFeEWEs0uC29YyJhkXOE9mf3YSaFGsITF+Gl1j0pajTjyH4R35Q"
+            + "r3floW2q3HfNzTeZ90Jnr1DhVERD6zEMgJpCtJqVuk0sixuXJHghS/KicKf4"
+            + "YXJJPx9epuIRF1siBRnznnF90svmOJMXApc0jGnYn3nQfk4kaShSnDaYaeYR"
+            + "DJKcsiWhl6S5zfwS7Gg8hDeyckhMQKKWnlG1CQrwlSFisKCduoodwRtWgft8"
+            + "kx13iyKK3sbalm6vnVc+5nufS4vI+TwMXoV63NqYaSroafBWk0nL53zGXPEy"
+            + "+A69QhzEViJKn2Wgqt5gt++jMMNImbRObIqgfgF1VjCCBUwwggQ0oAMCAQIC"
+            + "AgGDMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1H"
+            + "ZW9UcnVzdCBJbmMuMR4wHAYDVQQDExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUw"
+            + "HhcNMDYwMzI0MTU0MjI5WhcNMDkwNDA2MTQ0MjI5WjBzMQswCQYDVQQGEwJV"
+            + "UzELMAkGA1UECBMCTUExETAPBgNVBAoTCEdlb1RydXN0MR0wGwYDVQQDExRN"
+            + "YXJrZXRpbmcgRGVwYXJ0bWVudDElMCMGCSqGSIb3DQEJARYWbWFya2V0aW5n"
+            + "QGdlb3RydXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB"
+            + "ANmvajTO4XJvAU2nVcLmXeCnAQX7RZt+7+ML3InmqQ3LCGo1weop09zV069/"
+            + "1x/Nmieol7laEzeXxd2ghjGzwfXafqQEqHn6+vBCvqdNPoSi63fSWhnuDVWp"
+            + "KVDOYgxOonrXl+Cc43lu4zRSq+Pi5phhrjDWcH74a3/rdljUt4c4GFezFXfa"
+            + "w2oTzWkxj2cTSn0Szhpr17+p66UNt8uknlhmu4q44Speqql2HwmCEnpLYJrK"
+            + "W3fOq5D4qdsvsLR2EABLhrBezamLI3iGV8cRHOUTsbTMhWhv/lKfHAyf4XjA"
+            + "z9orzvPN5jthhIfICOFq/nStTgakyL4Ln+nFAB/SMPkCAwEAAaOCAhYwggIS"
+            + "MA4GA1UdDwEB/wQEAwIF4DCB5QYDVR0gAQH/BIHaMIHXMIHUBgkqhkiG9y8B"
+            + "AgEwgcYwgZAGCCsGAQUFBwICMIGDGoGAVGhpcyBjZXJ0aWZpY2F0ZSBoYXMg"
+            + "YmVlbiBpc3N1ZWQgaW4gYWNjb3JkYW5jZSB3aXRoIHRoZSBBY3JvYmF0IENy"
+            + "ZWRlbnRpYWxzIENQUyBsb2NhdGVkIGF0IGh0dHA6Ly93d3cuZ2VvdHJ1c3Qu"
+            + "Y29tL3Jlc291cmNlcy9jcHMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuZ2Vv"
+            + "dHJ1c3QuY29tL3Jlc291cmNlcy9jcHMwOgYDVR0fBDMwMTAvoC2gK4YpaHR0"
+            + "cDovL2NybC5nZW90cnVzdC5jb20vY3Jscy9hZG9iZWNhMS5jcmwwHwYDVR0j"
+            + "BBgwFoAUq4BZw2WDbR19E70Zw+wajw1HaqMwRAYIKwYBBQUHAQEEODA2MDQG"
+            + "CCsGAQUFBzABhihodHRwOi8vYWRvYmUtb2NzcC5nZW90cnVzdC5jb20vcmVz"
+            + "cG9uZGVyMBQGA1UdJQQNMAsGCSqGSIb3LwEBBTA8BgoqhkiG9y8BAQkBBC4w"
+            + "LAIBAYYnaHR0cDovL2Fkb2JlLXRpbWVzdGFtcC5nZW90cnVzdC5jb20vdHNh"
+            + "MBMGCiqGSIb3LwEBCQIEBTADAgEBMAwGA1UdEwQFMAMCAQAwDQYJKoZIhvcN"
+            + "AQEFBQADggEBAAOhy6QxOo+i3h877fvDvTa0plGD2bIqK7wMdNqbMDoSWied"
+            + "FIcgcBOIm2wLxOjZBAVj/3lDq59q2rnVeNnfXM0/N0MHI9TumHRjU7WNk9e4"
+            + "+JfJ4M+c3anrWOG3NE5cICDVgles+UHjXetHWql/LlP04+K2ZOLb6LE2xGnI"
+            + "YyLW9REzCYNAVF+/WkYdmyceHtaBZdbyVAJq0NAJPsfgY1pWcBo31Mr1fpX9"
+            + "WrXNTYDCqMyxMImJTmN3iI68tkXlNrhweQoArKFqBysiBkXzG/sGKYY6tWKU"
+            + "pzjLc3vIp/LrXC5zilROes8BSvwu1w9qQrJNcGwo7O4uijoNtyYil1Exgh1Q"
+            + "MIIdTAIBATBLMEUxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJ"
+            + "bmMuMR4wHAYDVQQDExVHZW9UcnVzdCBDQSBmb3IgQWRvYmUCAgGDMAkGBSsO"
+            + "AwIaBQCgggxMMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwIwYJKoZIhvcN"
+            + "AQkEMRYEFP4R6qIdpQJzWyzrqO8X1ZfJOgChMIIMCQYJKoZIhvcvAQEIMYIL"
+            + "+jCCC/agggZ5MIIGdTCCA6gwggKQMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV"
+            + "BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMR4wHAYDVQQDExVHZW9U"
+            + "cnVzdCBDQSBmb3IgQWRvYmUXDTA2MDQwNDE3NDAxMFoXDTA2MDQwNTE3NDAx"
+            + "MFowggIYMBMCAgC5Fw0wNTEwMTEyMDM2MzJaMBICAVsXDTA0MTEwNDE1MDk0"
+            + "MVowEwICALgXDTA1MTIxMjIyMzgzOFowEgIBWhcNMDQxMTA0MTUwOTMzWjAT"
+            + "AgIA5hcNMDUwODI3MDQwOTM4WjATAgIAtxcNMDYwMTE2MTc1NTEzWjATAgIA"
+            + "hhcNMDUxMjEyMjIzODU1WjATAgIAtRcNMDUwNzA2MTgzODQwWjATAgIA4BcN"
+            + "MDYwMzIwMDc0ODM0WjATAgIAgRcNMDUwODAyMjIzMTE1WjATAgIA3xcNMDUx"
+            + "MjEyMjIzNjUwWjASAgFKFw0wNDExMDQxNTA5MTZaMBICAUQXDTA0MTEwNDE1"
+            + "MDg1M1owEgIBQxcNMDQxMDAzMDEwMDQwWjASAgFsFw0wNDEyMDYxOTQ0MzFa"
+            + "MBMCAgEoFw0wNjAzMDkxMjA3MTJaMBMCAgEkFw0wNjAxMTYxNzU1MzRaMBIC"
+            + "AWcXDTA1MDMxODE3NTYxNFowEwICAVEXDTA2MDEzMTExMjcxMVowEgIBZBcN"
+            + "MDQxMTExMjI0ODQxWjATAgIA8RcNMDUwOTE2MTg0ODAxWjATAgIBThcNMDYw"
+            + "MjIxMjAxMDM2WjATAgIAwRcNMDUxMjEyMjIzODE2WjASAgFiFw0wNTAxMTAx"
+            + "NjE5MzRaMBICAWAXDTA1MDExMDE5MDAwNFowEwICAL4XDTA1MDUxNzE0NTYx"
+            + "MFowDQYJKoZIhvcNAQEFBQADggEBAEKhRMS3wVho1U3EvEQJZC8+JlUngmZQ"
+            + "A78KQbHPWNZWFlNvPuf/b0s7Lu16GfNHXh1QAW6Y5Hi1YtYZ3YOPyMd4Xugt"
+            + "gCdumbB6xtKsDyN5RvTht6ByXj+CYlYqsL7RX0izJZ6mJn4fjMkqzPKNOjb8"
+            + "kSn5T6rn93BjlATtCE8tPVOM8dnqGccRE0OV59+nDBXc90UMt5LdEbwaUOap"
+            + "snVB0oLcNm8d/HnlVH6RY5LnDjrT4vwfe/FApZtTecEWsllVUXDjSpwfcfD/"
+            + "476/lpGySB2otALqzImlA9R8Ok3hJ8dnF6hhQ5Oe6OJMnGYgdhkKbxsKkdib"
+            + "tTVl3qmH5QAwggLFMIIBrQIBATANBgkqhkiG9w0BAQUFADBpMQswCQYDVQQG"
+            + "EwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxHTAb"
+            + "BgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMRYwFAYDVQQDEw1BZG9iZSBS"
+            + "b290IENBFw0wNjAxMjcxODMzMzFaFw0wNzAxMjcwMDAwMDBaMIHeMCMCBD4c"
+            + "vUAXDTAzMDEyMTIzNDY1NlowDDAKBgNVHRUEAwoBBDAjAgQ+HL1BFw0wMzAx"
+            + "MjEyMzQ3MjJaMAwwCgYDVR0VBAMKAQQwIwIEPhy9YhcNMDMwMTIxMjM0NzQy"
+            + "WjAMMAoGA1UdFQQDCgEEMCMCBD4cvWEXDTA0MDExNzAxMDg0OFowDDAKBgNV"
+            + "HRUEAwoBBDAjAgQ+HL2qFw0wNDAxMTcwMTA5MDVaMAwwCgYDVR0VBAMKAQQw"
+            + "IwIEPhy9qBcNMDQwMTE3MDEzOTI5WjAMMAoGA1UdFQQDCgEEoC8wLTAKBgNV"
+            + "HRQEAwIBDzAfBgNVHSMEGDAWgBSCtzhKk6qbEO+Au9lU4vEP+4Cc3jANBgkq"
+            + "hkiG9w0BAQUFAAOCAQEAwtXF9042wG39icUlsotn5tpE3oCusLb/hBpEONhx"
+            + "OdfEQOq0w5hf/vqaxkcf71etA+KpbEUeSVaHMHRPhx/CmPrO9odE139dJdbt"
+            + "9iqbrC9iZokFK3h/es5kg73xujLKd7C/u5ngJ4mwBtvhMLjFjF2vJhPKHL4C"
+            + "IgMwdaUAhrcNzy16v+mw/VGJy3Fvc6oCESW1K9tvFW58qZSNXrMlsuidgunM"
+            + "hPKG+z0SXVyCqL7pnqKiaGddcgujYGOSY4S938oVcfZeZQEODtSYGlzldojX"
+            + "C1U1hCK5+tHAH0Ox/WqRBIol5VCZQwJftf44oG8oviYq52aaqSejXwmfT6zb"
+            + "76GCBXUwggVxMIIFbQoBAKCCBWYwggViBgkrBgEFBQcwAQEEggVTMIIFTzCB"
+            + "taIWBBS+8EpykfXdl4h3z7m/NZfdkAQQERgPMjAwNjA0MDQyMDIwMTVaMGUw"
+            + "YzA7MAkGBSsOAwIaBQAEFEb4BuZYkbjBjOjT6VeA/00fBvQaBBT3fTSQniOp"
+            + "BbHBSkz4xridlX0bsAICAYOAABgPMjAwNjA0MDQyMDIwMTVaoBEYDzIwMDYw"
+            + "NDA1MDgyMDE1WqEjMCEwHwYJKwYBBQUHMAECBBIEEFqooq/R2WltD7TposkT"
+            + "BhMwDQYJKoZIhvcNAQEFBQADgYEAMig6lty4b0JDsT/oanfQG5x6jVKPACpp"
+            + "1UA9SJ0apJJa7LeIdDFmu5C2S/CYiKZm4A4P9cAu0YzgLHxE4r6Op+HfVlAG"
+            + "6bzUe1P/hi1KCJ8r8wxOZAktQFPSzs85RAZwkHMfB0lP2e/h666Oye+Zf8VH"
+            + "RaE+/xZ7aswE89HXoumgggQAMIID/DCCA/gwggLgoAMCAQICAXUwDQYJKoZI"
+            + "hvcNAQEFBQAwRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu"
+            + "Yy4xHjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTAeFw0wNDEyMDIy"
+            + "MTI1MzlaFw0wNjEyMzAyMTI1MzlaMEwxCzAJBgNVBAYTAlVTMRUwEwYDVQQK"
+            + "EwxHZW9UcnVzdCBJbmMxJjAkBgNVBAMTHUdlb1RydXN0IEFkb2JlIE9DU1Ag"
+            + "UmVzcG9uZGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDiCc1iG3Dt"
+            + "TpB5Vdk4OcaEcyP46BnQMHf3esSTprar2SrXb0gDZ7TfIoFN8l9BH1pYpzZC"
+            + "P3R2xKo+O9MMcUZCxqCbYVC6GcDd9vVRaE/N4Qh2bpvEOydDydaoqrGdZnMQ"
+            + "tlt2ncj1sEuLMiqhtmi/O3rQs0yCGf+6e++6Gl5VKwIDAQABo4IBbjCCAWow"
+            + "DgYDVR0PAQH/BAQDAgTwMIHlBgNVHSABAf8EgdowgdcwgdQGCSqGSIb3LwEC"
+            + "ATCBxjCBkAYIKwYBBQUHAgIwgYMagYBUaGlzIGNlcnRpZmljYXRlIGhhcyBi"
+            + "ZWVuIGlzc3VlZCBpbiBhY2NvcmRhbmNlIHdpdGggdGhlIEFjcm9iYXQgQ3Jl"
+            + "ZGVudGlhbHMgQ1BTIGxvY2F0ZWQgYXQgaHR0cDovL3d3dy5nZW90cnVzdC5j"
+            + "b20vcmVzb3VyY2VzL2NwczAxBggrBgEFBQcCARYlaHR0cDovL3d3dy5nZW90"
+            + "cnVzdC5jb20vcmVzb3VyY2VzL2NwczATBgNVHSUEDDAKBggrBgEFBQcDCTA6"
+            + "BgNVHR8EMzAxMC+gLaArhilodHRwOi8vY3JsLmdlb3RydXN0LmNvbS9jcmxz"
+            + "L2Fkb2JlY2ExLmNybDAfBgNVHSMEGDAWgBSrgFnDZYNtHX0TvRnD7BqPDUdq"
+            + "ozANBgkqhkiG9w0BAQUFAAOCAQEAQ0l/UEPs9fmK+5prC33SrU4bNekhAv8K"
+            + "XMR4VWY4jGo9zURMVGr3Zi7Eblvr5H6T60aSYLA8txjyKmDplxsn8CKtCGiH"
+            + "OOUW5PpgBexN8SMKoRl9YzaxLtysrYRjEIyYoTfEN89yVi2sCjPupm/F9CPR"
+            + "O7EdKy0dm/f3C7ZmIbUFaIRzINDJOCpM5cGhmZ8m2yG4BxeZOmCSthKtLfvM"
+            + "2U9MaH6kxhDTJYNzw5BElHg5jlld92drTWaO0lM6aPr/pc+gs9hOraBCtzYE"
+            + "J40nhsSEtvuwVUE9vA+unNMT8dFtAcOvOPRiKYPF45RX9Rdy2C9jAc20SRwE"
+            + "uw6b+7K0xjANBgkqhkiG9w0BAQEFAASCAQC7a4yICFGCEMPlJbydK5qLG3rV"
+            + "sip7Ojjz9TB4nLhC2DgsIHds8jjdq2zguInluH2nLaBCVS+qxDVlTjgbI2cB"
+            + "TaWS8nglC7nNjzkKAsa8vThA8FZUVXTW0pb74jNJJU2AA27bb4g+4WgunCrj"
+            + "fpYp+QjDyMmdrJVqRmt5eQN+dpVxMS9oq+NrhOSEhyIb4/rejgNg9wnVK1ms"
+            + "l5PxQ4x7kpm7+Ua41//owkJVWykRo4T1jo4eHEz1DolPykAaKie2VKH/sMqR"
+            + "Spjh4E5biKJLOV9fKivZWKAXByXfwUbbMsJvz4v/2yVHFy9xP+tqB5ZbRoDK"
+            + "k8PzUyCprozn+/22oYIPijCCD4YGCyqGSIb3DQEJEAIOMYIPdTCCD3EGCSqG"
+            + "SIb3DQEHAqCCD2Iwgg9eAgEDMQswCQYFKw4DAhoFADCB+gYLKoZIhvcNAQkQ"
+            + "AQSggeoEgecwgeQCAQEGAikCMCEwCQYFKw4DAhoFAAQUoT97qeCv3FXYaEcS"
+            + "gY8patCaCA8CAiMHGA8yMDA2MDQwNDIwMjA1N1owAwIBPAEB/wIIO0yRre3L"
+            + "8/6ggZCkgY0wgYoxCzAJBgNVBAYTAlVTMRYwFAYDVQQIEw1NYXNzYWNodXNl"
+            + "dHRzMRAwDgYDVQQHEwdOZWVkaGFtMRUwEwYDVQQKEwxHZW9UcnVzdCBJbmMx"
+            + "EzARBgNVBAsTClByb2R1Y3Rpb24xJTAjBgNVBAMTHGFkb2JlLXRpbWVzdGFt"
+            + "cC5nZW90cnVzdC5jb22gggzJMIIDUTCCAjmgAwIBAgICAI8wDQYJKoZIhvcN"
+            + "AQEFBQAwRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4x"
+            + "HjAcBgNVBAMTFUdlb1RydXN0IENBIGZvciBBZG9iZTAeFw0wNTAxMTAwMTI5"
+            + "MTBaFw0xNTAxMTUwODAwMDBaMIGKMQswCQYDVQQGEwJVUzEWMBQGA1UECBMN"
+            + "TWFzc2FjaHVzZXR0czEQMA4GA1UEBxMHTmVlZGhhbTEVMBMGA1UEChMMR2Vv"
+            + "VHJ1c3QgSW5jMRMwEQYDVQQLEwpQcm9kdWN0aW9uMSUwIwYDVQQDExxhZG9i"
+            + "ZS10aW1lc3RhbXAuZ2VvdHJ1c3QuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GN"
+            + "ADCBiQKBgQDRbxJotLFPWQuuEDhKtOMaBUJepGxIvWxeahMbq1DVmqnk88+j"
+            + "w/5lfPICPzQZ1oHrcTLSAFM7Mrz3pyyQKQKMqUyiemzuG/77ESUNfBNSUfAF"
+            + "PdtHuDMU8Is8ABVnFk63L+wdlvvDIlKkE08+VTKCRdjmuBVltMpQ6QcLFQzm"
+            + "AQIDAQABo4GIMIGFMDoGA1UdHwQzMDEwL6AtoCuGKWh0dHA6Ly9jcmwuZ2Vv"
+            + "dHJ1c3QuY29tL2NybHMvYWRvYmVjYTEuY3JsMB8GA1UdIwQYMBaAFKuAWcNl"
+            + "g20dfRO9GcPsGo8NR2qjMA4GA1UdDwEB/wQEAwIGwDAWBgNVHSUBAf8EDDAK"
+            + "BggrBgEFBQcDCDANBgkqhkiG9w0BAQUFAAOCAQEAmnyXjdtX+F79Nf0KggTd"
+            + "6YC2MQD9s09IeXTd8TP3rBmizfM+7f3icggeCGakNfPRmIUMLoa0VM5Kt37T"
+            + "2X0TqzBWusfbKx7HnX4v1t/G8NJJlT4SShSHv+8bjjU4lUoCmW2oEcC5vXwP"
+            + "R5JfjCyois16npgcO05ZBT+LLDXyeBijE6qWmwLDfEpLyILzVRmyU4IE7jvm"
+            + "rgb3GXwDUvd3yQXGRRHbPCh3nj9hBGbuzyt7GnlqnEie3wzIyMG2ET/wvTX5"
+            + "4BFXKNe7lDLvZj/MXvd3V7gMTSVW0kAszKao56LfrVTgp1VX3UBQYwmQqaoA"
+            + "UwFezih+jEvjW6cYJo/ErDCCBKEwggOJoAMCAQICBD4cvSgwDQYJKoZIhvcN"
+            + "AQEFBQAwaTELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMg"
+            + "SW5jb3Jwb3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEW"
+            + "MBQGA1UEAxMNQWRvYmUgUm9vdCBDQTAeFw0wMzAxMDgyMzM3MjNaFw0yMzAx"
+            + "MDkwMDA3MjNaMGkxCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0"
+            + "ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRvYmUgVHJ1c3QgU2Vydmlj"
+            + "ZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUA"
+            + "A4IBDwAwggEKAoIBAQDMT1SE96ei5zNTfz+cEohrLJlHZ34PHrmtFIj5wxDY"
+            + "HfDw1Z9pCi9ZNbDMbKlMnBWgn84gv6DPVOLgIGZFPzmGOH6cxI4HIsYk9gES"
+            + "sDXfVeppkLDbhTce4k4HskKhahNpoGbqgJERWSqbCHlaIEQtyb1zOIs8L+BD"
+            + "G12zC/CvNRop/u+mkt2BTJ09WY6tMTxAfpuRNgb84lyN0Y0m1VxFz69lP7Gq"
+            + "0mKW9Kg46rpgQvT0HEo1Fc74TiJWD5UYxfiWn5/7sLd4JemAa73WCvDGdJSd"
+            + "8w9Q25p3zktwgyONoMp4IERcPFRk8eqiMBmf6kwGTQZ4S16S3yLSyWezetIB"
+            + "AgMBAAGjggFPMIIBSzARBglghkgBhvhCAQEEBAMCAAcwgY4GA1UdHwSBhjCB"
+            + "gzCBgKB+oHykejB4MQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lz"
+            + "dGVtcyBJbmNvcnBvcmF0ZWQxHTAbBgNVBAsTFEFkb2JlIFRydXN0IFNlcnZp"
+            + "Y2VzMRYwFAYDVQQDEw1BZG9iZSBSb290IENBMQ0wCwYDVQQDEwRDUkwxMCsG"
+            + "A1UdEAQkMCKADzIwMDMwMTA4MjMzNzIzWoEPMjAyMzAxMDkwMDA3MjNaMAsG"
+            + "A1UdDwQEAwIBBjAfBgNVHSMEGDAWgBSCtzhKk6qbEO+Au9lU4vEP+4Cc3jAd"
+            + "BgNVHQ4EFgQUgrc4SpOqmxDvgLvZVOLxD/uAnN4wDAYDVR0TBAUwAwEB/zAd"
+            + "BgkqhkiG9n0HQQAEEDAOGwhWNi4wOjQuMAMCBJAwDQYJKoZIhvcNAQEFBQAD"
+            + "ggEBADLan0N1wfpvyW/bqx02Nz68YRk2twI8HSNZmGye7k2F51TIIB+n1Lvi"
+            + "vwB3fSRrcC9cwTp2SbXT4COEKnFqIvPBJymYFfY1kOQETMONvJ9hHOf9JIzR"
+            + "REOMFrqbTaXUNS+8Ec6991E3jZ+Q5BTxGD++6VkSNfkzkvOe4NVrmnGbmUvI"
+            + "ccPhsWEJxOX6kfBCOjd9NPly6M2qYhwh6dX0ghDjewW2LWhWC35+kixvTXKC"
+            + "DO1WdLKduastKx0QX9sndXCP/R3X4gKgeeUc5f+vZEBRLZ6bR9tCpXwfwqZI"
+            + "sNe+kmlNpPYpV8V4ERjch1HKE7JinU8rMr0xpcH6UqsFiMgwggTLMIIDs6AD"
+            + "AgECAgQ+HL21MA0GCSqGSIb3DQEBBQUAMGkxCzAJBgNVBAYTAlVTMSMwIQYD"
+            + "VQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRv"
+            + "YmUgVHJ1c3QgU2VydmljZXMxFjAUBgNVBAMTDUFkb2JlIFJvb3QgQ0EwHhcN"
+            + "MDQwMTE3MDAwMzM5WhcNMTUwMTE1MDgwMDAwWjBFMQswCQYDVQQGEwJVUzEW"
+            + "MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgQ0Eg"
+            + "Zm9yIEFkb2JlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp+V3"
+            + "4GR4Wuc5hbyv0vVbKBMOVN1J+s5i9ZL9nph7n+X4esFs4epAJcFxJ4KnPuQH"
+            + "ZZ0oyHUU4Th70mWYgKwd6sEt1aR6ZT788Nvr3OHwTRwugN/G6QXqhU9ePpZJ"
+            + "OF1Ibsf1pcXNGvpLdcYK6+CX5DANMuIthb440XoNfC3dNBC0pF4mM4lmTjpl"
+            + "nQG8xK0rIFp4HoMpmyaIijz2qyjXdUNkg0fbDUq9eDTKAOLOg21u+AA8XKbC"
+            + "ewg1LWSV9CVy+fTHREmb1thBcrfkY1kCAvczsuquV3SMx8hRpa+4cIvKK/K1"
+            + "G7OrV0nsTyuaJ2MMST8b7bul/Xd81nu9Hsz4iQIDAQABo4IBnTCCAZkwEgYD"
+            + "VR0TAQH/BAgwBgEB/wIBATBQBgNVHSAESTBHMEUGCSqGSIb3LwECATA4MDYG"
+            + "CCsGAQUFBwIBFipodHRwczovL3d3dy5hZG9iZS5jb20vbWlzYy9wa2kvY2Rz"
+            + "X2NwLmh0bWwwFAYDVR0lBA0wCwYJKoZIhvcvAQEFMIGyBgNVHR8Egaowgacw"
+            + "IqAgoB6GHGh0dHA6Ly9jcmwuYWRvYmUuY29tL2Nkcy5jcmwwgYCgfqB8pHow"
+            + "eDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jw"
+            + "b3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEWMBQGA1UE"
+            + "AxMNQWRvYmUgUm9vdCBDQTENMAsGA1UEAxMEQ1JMMTALBgNVHQ8EBAMCAQYw"
+            + "HwYDVR0jBBgwFoAUgrc4SpOqmxDvgLvZVOLxD/uAnN4wHQYDVR0OBBYEFKuA"
+            + "WcNlg20dfRO9GcPsGo8NR2qjMBkGCSqGSIb2fQdBAAQMMAobBFY2LjADAgSQ"
+            + "MA0GCSqGSIb3DQEBBQUAA4IBAQA/OVkuogCOsV4RYSzS4Lb1jImGRc4T2Z/d"
+            + "hJoUawhMX4aXWPSlqNOPIfhHflCvd+Whbarcd83NN5n3QmevUOFUREPrMQyA"
+            + "mkK0mpW6TSyLG5ckeCFL8qJwp/hhckk/H16m4hEXWyIFGfOecX3Sy+Y4kxcC"
+            + "lzSMadifedB+TiRpKFKcNphp5hEMkpyyJaGXpLnN/BLsaDyEN7JySExAopae"
+            + "UbUJCvCVIWKwoJ26ih3BG1aB+3yTHXeLIorextqWbq+dVz7me59Li8j5PAxe"
+            + "hXrc2phpKuhp8FaTScvnfMZc8TL4Dr1CHMRWIkqfZaCq3mC376Mww0iZtE5s"
+            + "iqB+AXVWMYIBgDCCAXwCAQEwSzBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN"
+            + "R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgQ0EgZm9yIEFkb2Jl"
+            + "AgIAjzAJBgUrDgMCGgUAoIGMMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0BCRAB"
+            + "BDAcBgkqhkiG9w0BCQUxDxcNMDYwNDA0MjAyMDU3WjAjBgkqhkiG9w0BCQQx"
+            + "FgQUp7AnXBqoNcarvO7fMJut1og2U5AwKwYLKoZIhvcNAQkQAgwxHDAaMBgw"
+            + "FgQU1dH4eZTNhgxdiSABrat6zsPdth0wDQYJKoZIhvcNAQEBBQAEgYCinr/F"
+            + "rMiQz/MRm9ZD5YGcC0Qo2dRTPd0Aop8mZ4g1xAhKFLnp7lLsjCbkSDpVLDBh"
+            + "cnCk7CV+3FT5hlvt8OqZlR0CnkSnCswLFhrppiWle6cpxlwGqyAteC8uKtQu"
+            + "wjE5GtBKLcCOAzQYyyuNZZeB6oCZ+3mPhZ62FxrvvEGJCgAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+            + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==");
+
+        private static readonly byte[] emptyDNCert = Base64.Decode(
+              "MIICfTCCAeagAwIBAgIBajANBgkqhkiG9w0BAQQFADB8MQswCQYDVQQGEwJVUzEMMAoGA1UEChMD"
+            + "Q0RXMQkwBwYDVQQLEwAxCTAHBgNVBAcTADEJMAcGA1UECBMAMRowGAYDVQQDExFUZW1wbGFyIFRl"
+            + "c3QgMTAyNDEiMCAGCSqGSIb3DQEJARYTdGVtcGxhcnRlc3RAY2R3LmNvbTAeFw0wNjA1MjIwNTAw"
+            + "MDBaFw0xMDA1MjIwNTAwMDBaMHwxCzAJBgNVBAYTAlVTMQwwCgYDVQQKEwNDRFcxCTAHBgNVBAsT"
+            + "ADEJMAcGA1UEBxMAMQkwBwYDVQQIEwAxGjAYBgNVBAMTEVRlbXBsYXIgVGVzdCAxMDI0MSIwIAYJ"
+            + "KoZIhvcNAQkBFhN0ZW1wbGFydGVzdEBjZHcuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB"
+            + "gQDH3aJpJBfM+A3d84j5YcU6zEQaQ76u5xO9NSBmHjZykKS2kCcUqPpvVOPDA5WgV22dtKPh+lYV"
+            + "iUp7wyCVwAKibq8HIbihHceFqMKzjwC639rMoDJ7bi/yzQWz1Zg+075a4FGPlUKn7Yfu89wKkjdW"
+            + "wDpRPXc/agqBnrx5pJTXzQIDAQABow8wDTALBgNVHQ8EBAMCALEwDQYJKoZIhvcNAQEEBQADgYEA"
+            + "RRsRsjse3i2/KClFVd6YLZ+7K1BE0WxFyY2bbytkwQJSxvv3vLSuweFUbhNxutb68wl/yW4GLy4b"
+            + "1QdyswNxrNDXTuu5ILKhRDDuWeocz83aG2KGtr3JlFyr3biWGEyn5WUOE6tbONoQDJ0oPYgI6CAc"
+            + "EHdUp0lioOCt6UOw7Cs=");
+
+        private static readonly byte[] gostRFC4491_94 = Base64.Decode(
+            "MIICCzCCAboCECMO42BGlSTOxwvklBgufuswCAYGKoUDAgIEMGkxHTAbBgNVBAMM" +
+            "FEdvc3RSMzQxMC05NCBleGFtcGxlMRIwEAYDVQQKDAlDcnlwdG9Qcm8xCzAJBgNV" +
+            "BAYTAlJVMScwJQYJKoZIhvcNAQkBFhhHb3N0UjM0MTAtOTRAZXhhbXBsZS5jb20w" +
+            "HhcNMDUwODE2MTIzMjUwWhcNMTUwODE2MTIzMjUwWjBpMR0wGwYDVQQDDBRHb3N0" +
+            "UjM0MTAtOTQgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYDVQQGEwJS" +
+            "VTEnMCUGCSqGSIb3DQEJARYYR29zdFIzNDEwLTk0QGV4YW1wbGUuY29tMIGlMBwG" +
+            "BiqFAwICFDASBgcqhQMCAiACBgcqhQMCAh4BA4GEAASBgLuEZuF5nls02CyAfxOo" +
+            "GWZxV/6MVCUhR28wCyd3RpjG+0dVvrey85NsObVCNyaE4g0QiiQOHwxCTSs7ESuo" +
+            "v2Y5MlyUi8Go/htjEvYJJYfMdRv05YmKCYJo01x3pg+2kBATjeM+fJyR1qwNCCw+" +
+            "eMG1wra3Gqgqi0WBkzIydvp7MAgGBiqFAwICBANBABHHCH4S3ALxAiMpR3aPRyqB" +
+            "g1DjB8zy5DEjiULIc+HeIveF81W9lOxGkZxnrFjXBSqnjLeFKgF1hffXOAP7zUM=");
+
+        private static readonly byte[] gostRFC4491_2001 = Base64.Decode(
+            "MIIB0DCCAX8CECv1xh7CEb0Xx9zUYma0LiEwCAYGKoUDAgIDMG0xHzAdBgNVBAMM" +
+            "Fkdvc3RSMzQxMC0yMDAxIGV4YW1wbGUxEjAQBgNVBAoMCUNyeXB0b1BybzELMAkG" +
+            "A1UEBhMCUlUxKTAnBgkqhkiG9w0BCQEWGkdvc3RSMzQxMC0yMDAxQGV4YW1wbGUu" +
+            "Y29tMB4XDTA1MDgxNjE0MTgyMFoXDTE1MDgxNjE0MTgyMFowbTEfMB0GA1UEAwwW" +
+            "R29zdFIzNDEwLTIwMDEgZXhhbXBsZTESMBAGA1UECgwJQ3J5cHRvUHJvMQswCQYD" +
+            "VQQGEwJSVTEpMCcGCSqGSIb3DQEJARYaR29zdFIzNDEwLTIwMDFAZXhhbXBsZS5j" +
+            "b20wYzAcBgYqhQMCAhMwEgYHKoUDAgIkAAYHKoUDAgIeAQNDAARAhJVodWACGkB1" +
+            "CM0TjDGJLP3lBQN6Q1z0bSsP508yfleP68wWuZWIA9CafIWuD+SN6qa7flbHy7Df" +
+            "D2a8yuoaYDAIBgYqhQMCAgMDQQA8L8kJRLcnqeyn1en7U23Sw6pkfEQu3u0xFkVP" +
+            "vFQ/3cHeF26NG+xxtZPz3TaTVXdoiYkXYiD02rEx1bUcM97i");
+
+        private class DudPublicKey
+            : AsymmetricKeyParameter
+        {
+            public DudPublicKey()
+                : base(false)
+            {
+            }
+
+            public string Algorithm
+            {
+                get { return null; }
+            }
+
+            public string Format
+            {
+                get { return null; }
+            }
+
+            public byte[] GetEncoded()
+            {
+                return null;
+            }
+        }
+
+        private AsymmetricKeyParameter dudPublicKey = new DudPublicKey();
+
+        public override string Name
+        {
+            get { return "CertTest"; }
+        }
+
+        internal void checkCertificate(
+            int		id,
+            byte[]	bytes)
+        {
+            string dump = "";
+
+            try
+            {
+                X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes);
+
+                AsymmetricKeyParameter k = cert.GetPublicKey();
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e);
+            }
+        }
+
+        internal void checkNameCertificate(
+            int     id,
+            byte[]  bytes)
+        {
+            string dump = "";
+
+            try
+            {
+                X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes);
+
+                AsymmetricKeyParameter k = cert.GetPublicKey();
+                if (!cert.IssuerDN.ToString().Equals("C=DE,O=DATEV eG,0.2.262.1.10.7.20=1+CN=CA DATEV D03 1:PN"))
+                {
+                    Fail(id + " failed - name test.");
+                }
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e);
+            }
+
+        }
+
+        internal void checkKeyUsage(
+            int		id,
+            byte[]	bytes)
+        {
+            string dump = "";
+
+            try
+            {
+                X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes);
+
+                AsymmetricKeyParameter k = cert.GetPublicKey();
+
+                if (cert.GetKeyUsage()[7])
+                {
+                    Fail("error generating cert - key usage wrong.");
+                }
+
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e);
+            }
+
+        }
+
+        internal void checkSelfSignedCertificate(
+            int     id,
+            byte[]  bytes)
+        {
+            string dump = "";
+
+            try
+            {
+                X509Certificate cert = new X509CertificateParser().ReadCertificate(bytes);
+
+                AsymmetricKeyParameter k = cert.GetPublicKey();
+
+                cert.Verify(k);
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e);
+            }
+        }
+
+        /**
+         * we Generate a self signed certificate for the sake of testing - RSA
+         */
+        internal void checkCreation1()
+        {
+            //
+            // a sample key pair.
+            //
+            RsaKeyParameters pubKey = new RsaKeyParameters(
+                false,
+                new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+                new BigInteger("11", 16));
+
+            RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+                new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+                new BigInteger("11", 16),
+                new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+                new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+                new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+                new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+                new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+                new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+            //
+            // set up the keys
+            //
+//			AsymmetricKeyParameter privKey;
+//			AsymmetricKeyParameter pubKey;
+
+//			KeyFactory  fact = KeyFactory.GetInstance("RSA");
+//
+//			privKey = fact.generatePrivate(privKeySpec);
+//			pubKey = fact.generatePublic(pubKeySpec);
+
+            //
+            // distinguished name table.
+            //
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+            IList values = new ArrayList();
+            values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            //
+            // extensions
+            //
+
+            //
+            // create the certificate - version 3 - without extensions
+            //
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+            X509Certificate cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            ISet dummySet = cert.GetNonCriticalExtensionOids();
+            if (dummySet != null)
+            {
+                Fail("non-critical oid set should be null");
+            }
+            dummySet = cert.GetCriticalExtensionOids();
+            if (dummySet != null)
+            {
+                Fail("critical oid set should be null");
+            }
+
+            //
+            // create the certificate - version 3 - with extensions
+            //
+            certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+            certGen.AddExtension("2.5.29.15", true,
+                new X509KeyUsage(X509KeyUsage.EncipherOnly));
+            certGen.AddExtension("2.5.29.37", true,
+                new DerSequence(KeyPurposeID.AnyExtendedKeyUsage));
+            certGen.AddExtension("2.5.29.17", true,
+                new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test at test.test")));
+
+            cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded());
+
+            if (!cert.GetKeyUsage()[7])
+            {
+                Fail("error generating cert - key usage wrong.");
+            }
+
+            IList l = cert.GetExtendedKeyUsage();
+            if (!l[0].Equals(KeyPurposeID.AnyExtendedKeyUsage.Id))
+            {
+                Fail("failed extended key usage test");
+            }
+
+            foreach (IList gn in cert.GetSubjectAlternativeNames())
+            {
+                if (!gn[1].Equals("test at test.test"))
+                {
+                    Fail("failed subject alternative names test");
+                }
+            }
+
+            // Console.WriteLine(cert);
+
+            //
+            // create the certificate - version 1
+            //
+            X509V1CertificateGenerator certGen1 = new X509V1CertificateGenerator();
+
+            certGen1.SetSerialNumber(BigInteger.One);
+            certGen1.SetIssuerDN(new X509Name(ord, values));
+            certGen1.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen1.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen1.SetSubjectDN(new X509Name(ord, values));
+            certGen1.SetPublicKey(pubKey);
+            certGen1.SetSignatureAlgorithm("MD5WithRSAEncryption");
+
+            cert = certGen1.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded());
+
+            // Console.WriteLine(cert);
+            if (!cert.IssuerDN.Equivalent(cert.SubjectDN))
+            {
+                Fail("name comparison fails");
+            }
+        }
+
+        /**
+         * we Generate a self signed certificate for the sake of testing - DSA
+         */
+        internal void checkCreation2()
+        {
+            //
+            // set up the keys
+            //
+            AsymmetricKeyParameter privKey;
+            AsymmetricKeyParameter pubKey;
+
+            try
+            {
+//				KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA", "SUN");
+//				g.initialize(512, new SecureRandom());
+//				KeyPair p = g.generateKeyPair();
+                IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+                DsaParametersGenerator dpg = new DsaParametersGenerator();
+                dpg.Init(512, 25, new SecureRandom());
+                g.Init(new DsaKeyGenerationParameters(new SecureRandom(), dpg.GenerateParameters()));
+                AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+                privKey = p.Private;
+                pubKey = p.Public;
+            }
+            catch (Exception e)
+            {
+                Fail("error setting up keys - " + e.ToString());
+                return;
+            }
+
+            //
+            // distinguished name table.
+            //
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+            IList values = new ArrayList();
+            values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            //
+            // extensions
+            //
+
+            //
+            // create the certificate - version 3
+            //
+            X509V3CertificateGenerator  certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("SHA1withDSA");
+
+            try
+            {
+                X509Certificate cert = certGen.Generate(privKey);
+
+                cert.CheckValidity(DateTime.UtcNow);
+
+                cert.Verify(pubKey);
+
+                cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded());
+
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail("error setting generating cert - " + e.ToString());
+            }
+
+            //
+            // create the certificate - version 1
+            //
+            X509V1CertificateGenerator certGen1 = new X509V1CertificateGenerator();
+
+            certGen1.SetSerialNumber(BigInteger.One);
+            certGen1.SetIssuerDN(new X509Name(ord, values));
+            certGen1.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen1.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen1.SetSubjectDN(new X509Name(ord, values));
+            certGen1.SetPublicKey(pubKey);
+            certGen1.SetSignatureAlgorithm("SHA1withDSA");
+
+            try
+            {
+                X509Certificate cert = certGen1.Generate(privKey);
+
+                cert.CheckValidity(DateTime.UtcNow);
+
+                cert.Verify(pubKey);
+
+                cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded());
+
+                //Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail("error setting generating cert - " + e.ToString());
+            }
+
+            //
+            // exception test
+            //
+            try
+            {
+                certGen.SetPublicKey(dudPublicKey);
+
+                Fail("key without encoding not detected in v1");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        /**
+         * we Generate a self signed certificate for the sake of testing - ECDSA
+         */
+        internal void checkCreation3()
+        {
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
+
+            ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                spec);
+
+            //
+            // set up the keys
+            //
+//			AsymmetricKeyParameter privKey;
+//			AsymmetricKeyParameter pubKey;
+//
+//			try
+//			{
+//				KeyFactory fact = KeyFactory.GetInstance("ECDSA");
+//
+//				privKey = fact.generatePrivate(privKeySpec);
+//				pubKey = fact.generatePublic(pubKeySpec);
+//			}
+//			catch (Exception e)
+//			{
+//				Fail("error setting up keys - " + e.ToString());
+//				return;
+//			}
+
+            //
+            // distinguished name table.
+            //
+            IDictionary attrs = new Hashtable();
+            IList order = new ArrayList();
+
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.E, "feedback-crypto at bouncycastle.org");
+
+            order.Add(X509Name.C);
+            order.Add(X509Name.O);
+            order.Add(X509Name.L);
+            order.Add(X509Name.ST);
+            order.Add(X509Name.E);
+
+
+            //
+            // ToString test
+            //
+            X509Name p = new X509Name(order, attrs);
+            string s = p.ToString();
+
+            if (!s.Equals("C=AU,O=The Legion of the Bouncy Castle,L=Melbourne,ST=Victoria,E=feedback-crypto at bouncycastle.org"))
+            {
+                Fail("ordered X509Principal test failed - s = " + s + ".");
+            }
+
+            //
+            // create the certificate - version 3
+            //
+            X509V3CertificateGenerator  certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(order, attrs));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(order, attrs));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("SHA1withECDSA");
+
+            try
+            {
+                X509Certificate cert = certGen.Generate(privKey);
+
+                cert.CheckValidity(DateTime.UtcNow);
+
+                cert.Verify(pubKey);
+
+                X509CertificateParser fact = new X509CertificateParser();
+                cert = fact.ReadCertificate(cert.GetEncoded());
+
+                //
+                // try with point compression turned off
+                //
+//				((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED");
+                ECPoint q = pubKey.Q.Normalize();
+                pubKey = new ECPublicKeyParameters(
+                    pubKey.AlgorithmName,
+                    q.Curve.CreatePoint(q.XCoord.ToBigInteger(), q.YCoord.ToBigInteger()),
+                    pubKey.Parameters);
+
+                certGen.SetPublicKey(pubKey);
+
+                cert = certGen.Generate(privKey);
+
+                cert.CheckValidity(DateTime.UtcNow);
+
+                cert.Verify(pubKey);
+
+                cert = fact.ReadCertificate(cert.GetEncoded());
+
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail("error setting generating cert - " + e.ToString());
+            }
+
+            X509Name pr = new X509Name("O=\"The Bouncy Castle, The Legion of\",E=feedback-crypto at bouncycastle.org,ST=Victoria,L=Melbourne,C=AU");
+
+            if (!pr.ToString().Equals("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto at bouncycastle.org,ST=Victoria,L=Melbourne,C=AU"))
+            {
+                Fail("string based X509Principal test failed.");
+            }
+
+            pr = new X509Name("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto at bouncycastle.org,ST=Victoria,L=Melbourne,C=AU");
+
+            if (!pr.ToString().Equals("O=The Bouncy Castle\\, The Legion of,E=feedback-crypto at bouncycastle.org,ST=Victoria,L=Melbourne,C=AU"))
+            {
+                Fail("string based X509Principal test failed.");
+            }
+        }
+
+        /**
+         * we Generate a self signed certificate for the sake of testing - SHA224withECDSA
+         */
+        private void createECCert(
+            string				algorithm,
+            DerObjectIdentifier	algOid)
+        {
+            FpCurve curve = new FpCurve(
+                new BigInteger("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"), // q (or p)
+                new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16),   // a
+                new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16));  // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+//				curve.DecodePoint(Hex.Decode("02C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G
+                curve.DecodePoint(Hex.Decode("0200C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G
+                new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16)); // n
+
+            ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+//				curve.DecodePoint(Hex.Decode("026BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q
+                curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q
+                spec);
+
+//			//
+//			// set up the keys
+//			//
+//			AsymmetricKeyParameter privKey;
+//			AsymmetricKeyParameter pubKey;
+//
+//			KeyFactory fact = KeyFactory.GetInstance("ECDSA");
+//
+//			privKey = fact.generatePrivate(privKeySpec);
+//			pubKey = fact.generatePublic(pubKeySpec);
+
+
+            //
+            // distinguished name table.
+            //
+            IDictionary attrs = new Hashtable();
+            IList order = new ArrayList();
+
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.E, "feedback-crypto at bouncycastle.org");
+
+            order.Add(X509Name.C);
+            order.Add(X509Name.O);
+            order.Add(X509Name.L);
+            order.Add(X509Name.ST);
+            order.Add(X509Name.E);
+
+            //
+            // create the certificate - version 3
+            //
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(order, attrs));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(order, attrs));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm(algorithm);
+
+
+            X509Certificate cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            X509CertificateParser fact = new X509CertificateParser();
+            cert = fact.ReadCertificate(cert.GetEncoded());
+
+            //
+            // try with point compression turned off
+            //
+//			((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED");
+            ECPoint q = pubKey.Q.Normalize();
+            pubKey = new ECPublicKeyParameters(
+                pubKey.AlgorithmName,
+                q.Curve.CreatePoint(q.XCoord.ToBigInteger(), q.YCoord.ToBigInteger()),
+                pubKey.Parameters);
+
+            certGen.SetPublicKey(pubKey);
+
+            cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            cert = fact.ReadCertificate(cert.GetEncoded());
+
+            if (!cert.SigAlgOid.Equals(algOid.ToString()))
+            {
+                Fail("ECDSA oid incorrect.");
+            }
+
+            if (cert.GetSigAlgParams() != null)
+            {
+                Fail("sig parameters present");
+            }
+
+            ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+            sig.Init(false, pubKey);
+
+            byte[] b = cert.GetTbsCertificate();
+            sig.BlockUpdate(b, 0, b.Length);
+
+            if (!sig.VerifySignature(cert.GetSignature()))
+            {
+                Fail("EC certificate signature not mapped correctly.");
+            }
+            // Console.WriteLine(cert);
+        }
+
+        private void checkCrl(
+            int     id,
+            byte[]  bytes)
+        {
+            string dump = "";
+
+            try
+            {
+                X509Crl cert = new X509CrlParser().ReadCrl(bytes);
+
+                // Console.WriteLine(cert);
+            }
+            catch (Exception e)
+            {
+                Fail(dump + SimpleTest.NewLine + Name + ": "+ id + " failed - exception " + e.Message, e);
+            }
+
+        }
+
+        private void checkCrlCreation1()
+        {
+            IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            kpGen.Init(
+                new RsaKeyGenerationParameters(
+                    BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25));
+
+            X509V2CrlGenerator crlGen = new X509V2CrlGenerator();
+            DateTime now = DateTime.UtcNow;
+            AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+            crlGen.SetIssuerDN(new X509Name("CN=Test CA"));
+
+            crlGen.SetThisUpdate(now);
+            crlGen.SetNextUpdate(now.AddSeconds(100));
+            crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+            crlGen.AddCrlEntry(BigInteger.One, now, CrlReason.PrivilegeWithdrawn);
+
+            crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false,
+                new AuthorityKeyIdentifierStructure(pair.Public));
+
+            X509Crl crl = crlGen.Generate(pair.Private);
+
+            if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true))
+            {
+                Fail("failed CRL issuer test");
+            }
+
+            Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
+
+            if (authExt == null)
+            {
+                Fail("failed to find CRL extension");
+            }
+
+            AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt);
+
+            X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One);
+
+            if (entry == null)
+            {
+                Fail("failed to find CRL entry");
+            }
+
+            if (!entry.SerialNumber.Equals(BigInteger.One))
+            {
+                Fail("CRL cert serial number does not match");
+            }
+
+            if (!entry.HasExtensions)
+            {
+                Fail("CRL entry extension not found");
+            }
+
+            Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode);
+
+            if (ext != null)
+            {
+                DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext);
+
+                if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn)
+                {
+                    Fail("CRL entry reasonCode wrong");
+                }
+            }
+            else
+            {
+                Fail("CRL entry reasonCode not found");
+            }
+        }
+
+        private void checkCrlCreation2()
+        {
+            IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            kpGen.Init(
+                new RsaKeyGenerationParameters(
+                    BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25));
+
+            X509V2CrlGenerator crlGen = new X509V2CrlGenerator();
+            DateTime now = DateTime.UtcNow;
+            AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+            crlGen.SetIssuerDN(new X509Name("CN=Test CA"));
+
+            crlGen.SetThisUpdate(now);
+            crlGen.SetNextUpdate(now.AddSeconds(100));
+            crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+            IList extOids = new ArrayList();
+            IList extValues = new ArrayList();
+
+            CrlReason crlReason = new CrlReason(CrlReason.PrivilegeWithdrawn);
+
+            try
+            {
+                extOids.Add(X509Extensions.ReasonCode);
+                extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded())));
+            }
+            catch (IOException e)
+            {
+                throw new ArgumentException("error encoding reason: " + e);
+            }
+
+            X509Extensions entryExtensions = new X509Extensions(extOids, extValues);
+
+            crlGen.AddCrlEntry(BigInteger.One, now, entryExtensions);
+
+            crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public));
+
+            X509Crl crl = crlGen.Generate(pair.Private);
+
+            if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true))
+            {
+                Fail("failed CRL issuer test");
+            }
+
+            Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
+
+            if (authExt == null)
+            {
+                Fail("failed to find CRL extension");
+            }
+
+            AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt);
+
+            X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One);
+
+            if (entry == null)
+            {
+                Fail("failed to find CRL entry");
+            }
+
+            if (!entry.SerialNumber.Equals(BigInteger.One))
+            {
+                Fail("CRL cert serial number does not match");
+            }
+
+            if (!entry.HasExtensions)
+            {
+                Fail("CRL entry extension not found");
+            }
+
+            Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode);
+
+            if (ext != null)
+            {
+                DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext);
+
+                if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn)
+                {
+                    Fail("CRL entry reasonCode wrong");
+                }
+            }
+            else
+            {
+                Fail("CRL entry reasonCode not found");
+            }
+        }
+
+        private void checkCrlCreation3()
+        {
+            IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            kpGen.Init(
+                new RsaKeyGenerationParameters(
+                    BigInteger.ValueOf(0x10001), new SecureRandom(), 768, 25));
+
+            X509V2CrlGenerator crlGen = new X509V2CrlGenerator();
+            DateTime now = DateTime.UtcNow;
+            AsymmetricCipherKeyPair pair = kpGen.GenerateKeyPair();
+
+            crlGen.SetIssuerDN(new X509Name("CN=Test CA"));
+
+            crlGen.SetThisUpdate(now);
+            crlGen.SetNextUpdate(now.AddSeconds(100));
+            crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+            IList extOids = new ArrayList();
+            IList extValues = new ArrayList();
+
+            CrlReason crlReason = new CrlReason(CrlReason.PrivilegeWithdrawn);
+
+            try
+            {
+                extOids.Add(X509Extensions.ReasonCode);
+                extValues.Add(new X509Extension(false, new DerOctetString(crlReason.GetEncoded())));
+            }
+            catch (IOException e)
+            {
+                throw new ArgumentException("error encoding reason: " + e);
+            }
+
+            X509Extensions entryExtensions = new X509Extensions(extOids, extValues);
+
+            crlGen.AddCrlEntry(BigInteger.One, now, entryExtensions);
+
+            crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public));
+
+            X509Crl crl = crlGen.Generate(pair.Private);
+
+            if (!crl.IssuerDN.Equivalent(new X509Name("CN=Test CA"), true))
+            {
+                Fail("failed CRL issuer test");
+            }
+
+            Asn1OctetString authExt = crl.GetExtensionValue(X509Extensions.AuthorityKeyIdentifier);
+
+            if (authExt == null)
+            {
+                Fail("failed to find CRL extension");
+            }
+
+            AuthorityKeyIdentifier authId = new AuthorityKeyIdentifierStructure(authExt);
+
+            X509CrlEntry entry = crl.GetRevokedCertificate(BigInteger.One);
+
+            if (entry == null)
+            {
+                Fail("failed to find CRL entry");
+            }
+
+            if (!entry.SerialNumber.Equals(BigInteger.One))
+            {
+                Fail("CRL cert serial number does not match");
+            }
+
+            if (!entry.HasExtensions)
+            {
+                Fail("CRL entry extension not found");
+            }
+
+            Asn1OctetString ext = entry.GetExtensionValue(X509Extensions.ReasonCode);
+
+            if (ext != null)
+            {
+                DerEnumerated reasonCode = (DerEnumerated)X509ExtensionUtilities.FromExtensionValue(ext);
+
+                if (reasonCode.Value.IntValue != CrlReason.PrivilegeWithdrawn)
+                {
+                    Fail("CRL entry reasonCode wrong");
+                }
+            }
+            else
+            {
+                Fail("CRL entry reasonCode not found");
+            }
+
+            //
+            // check loading of existing CRL
+            //
+            crlGen = new X509V2CrlGenerator();
+            now = DateTime.UtcNow;
+
+            crlGen.SetIssuerDN(new X509Name("CN=Test CA"));
+
+            crlGen.SetThisUpdate(now);
+            crlGen.SetNextUpdate(now.AddSeconds(100));
+            crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+            crlGen.AddCrl(crl);
+
+            crlGen.AddCrlEntry(BigInteger.Two, now, entryExtensions);
+
+            crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(pair.Public));
+
+            X509Crl newCrl = crlGen.Generate(pair.Private);
+
+            int count = 0;
+            bool oneFound = false;
+            bool twoFound = false;
+
+            foreach (X509CrlEntry crlEnt in newCrl.GetRevokedCertificates())
+            {
+                if (crlEnt.SerialNumber.IntValue == 1)
+                {
+                    oneFound = true;
+                }
+                else if (crlEnt.SerialNumber.IntValue == 2)
+                {
+                    twoFound = true;
+                }
+
+                count++;
+            }
+
+            if (count != 2)
+            {
+                Fail("wrong number of CRLs found");
+            }
+
+            if (!oneFound || !twoFound)
+            {
+                Fail("wrong CRLs found in copied list");
+            }
+
+            //
+            // check factory read back
+            //
+            X509Crl readCrl = new X509CrlParser().ReadCrl(newCrl.GetEncoded());
+
+            if (readCrl == null)
+            {
+                Fail("crl not returned!");
+            }
+
+//			ICollection col = cFact.generateCRLs(new ByteArrayInputStream(newCrl.getEncoded()));
+            ICollection col = new X509CrlParser().ReadCrls(newCrl.GetEncoded());
+
+            if (col.Count != 1)
+            {
+                Fail("wrong number of CRLs found in collection");
+            }
+        }
+
+        /**
+         * we Generate a self signed certificate for the sake of testing - GOST3410
+         */
+        internal void checkCreation4()
+        {
+            //
+            // set up the keys
+            //
+            AsymmetricKeyParameter privKey;
+            AsymmetricKeyParameter pubKey;
+
+//			GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec("GostR3410-94-CryptoPro-A");
+//			g.initialize(gost3410P, new SecureRandom());
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+            g.Init(
+                new Gost3410KeyGenerationParameters(
+                    new SecureRandom(),
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
+
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            privKey = p.Private;
+            pubKey = p.Public;
+
+            //
+            // distinguished name table.
+            //
+            IDictionary attrs = new Hashtable();
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.E, "feedback-crypto at bouncycastle.org");
+
+            IList order = new ArrayList();
+            order.Add(X509Name.C);
+            order.Add(X509Name.O);
+            order.Add(X509Name.L);
+            order.Add(X509Name.ST);
+            order.Add(X509Name.E);
+
+            //
+            // extensions
+            //
+
+            //
+            // create the certificate - version 3
+            //
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(order, attrs));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(order, attrs));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("GOST3411withGOST3410");
+
+            X509Certificate cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            //
+            // check verifies in general
+            //
+            cert.Verify(pubKey);
+
+            //
+            // check verifies with contained key
+            //
+            cert.Verify(cert.GetPublicKey());
+
+            cert = new X509CertificateParser().ReadCertificate(cert.GetEncoded());
+
+            //Console.WriteLine(cert);
+
+            //check getEncoded()
+            byte[] bytesch = cert.GetEncoded();
+        }
+
+        internal void checkCreation5()
+        {
+            //
+            // a sample key pair.
+            //
+            RsaKeyParameters pubKey = new RsaKeyParameters(
+                false,
+                new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+                new BigInteger("11", 16));
+
+            RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+                new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+                new BigInteger("11", 16),
+                new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+                new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+                new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+                new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+                new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+                new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+            //
+            // set up the keys
+            //
+            SecureRandom rand = new SecureRandom();
+//			AsymmetricKeyParameter privKey;
+//			AsymmetricKeyParameter pubKey;
+//
+//			KeyFactory  fact = KeyFactory.GetInstance("RSA");
+//
+//			privKey = fact.generatePrivate(privKeySpec);
+//			pubKey = fact.generatePublic(pubKeySpec);
+
+            //
+            // distinguished name table.
+            //
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+            IList values = new ArrayList();
+            values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            //
+            // create base certificate - version 3
+            //
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+            certGen.AddExtension("2.5.29.15", true,
+                new X509KeyUsage(X509KeyUsage.EncipherOnly));
+            certGen.AddExtension("2.5.29.37", true,
+                new DerSequence(KeyPurposeID.AnyExtendedKeyUsage));
+            certGen.AddExtension("2.5.29.17", true,
+                new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test at test.test")));
+
+            X509Certificate baseCert = certGen.Generate(privKey);
+
+            //
+            // copy certificate
+            //
+            certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+
+            certGen.CopyAndAddExtension(new DerObjectIdentifier("2.5.29.15"), true, baseCert);
+            certGen.CopyAndAddExtension("2.5.29.37", false, baseCert);
+
+            X509Certificate cert = certGen.Generate(privKey);
+
+            cert.CheckValidity(DateTime.UtcNow);
+
+            cert.Verify(pubKey);
+
+            DerObjectIdentifier oid1 = new DerObjectIdentifier("2.5.29.15");
+            if (!baseCert.GetExtensionValue(oid1).Equals(cert.GetExtensionValue(oid1)))
+            {
+                Fail("2.5.29.15 differs");
+            }
+
+            DerObjectIdentifier oid2 = new DerObjectIdentifier("2.5.29.37");
+            if (!baseCert.GetExtensionValue(oid2).Equals(cert.GetExtensionValue(oid2)))
+            {
+                Fail("2.5.29.37 differs");
+            }
+
+            //
+            // exception test
+            //
+            try
+            {
+                certGen.CopyAndAddExtension("2.5.99.99", true, baseCert);
+
+                Fail("exception not thrown on dud extension copy");
+            }
+            catch (CertificateParsingException)
+            {
+                // expected
+            }
+
+            try
+            {
+                certGen.SetPublicKey(dudPublicKey);
+
+                certGen.Generate(privKey);
+
+                Fail("key without encoding not detected in v3");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        private void doTestForgedSignature()
+        {
+            string cert = "MIIBsDCCAVoCAQYwDQYJKoZIhvcNAQEFBQAwYzELMAkGA1UEBhMCQVUxEzARBgNV"
+                + "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMSMwIQYD"
+                + "VQQDExpTZXJ2ZXIgdGVzdCBjZXJ0ICg1MTIgYml0KTAeFw0wNjA5MTEyMzU4NTVa"
+                + "Fw0wNjEwMTEyMzU4NTVaMGMxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpRdWVlbnNs"
+                + "YW5kMRowGAYDVQQKExFDcnlwdFNvZnQgUHR5IEx0ZDEjMCEGA1UEAxMaU2VydmVy"
+                + "IHRlc3QgY2VydCAoNTEyIGJpdCkwXDANBgkqhkiG9w0BAQEFAANLADBIAkEAn7PD"
+                + "hCeV/xIxUg8V70YRxK2A5jZbD92A12GN4PxyRQk0/lVmRUNMaJdq/qigpd9feP/u"
+                + "12S4PwTLb/8q/v657QIDAQABMA0GCSqGSIb3DQEBBQUAA0EAbynCRIlUQgaqyNgU"
+                + "DF6P14yRKUtX8akOP2TwStaSiVf/akYqfLFm3UGka5XbPj4rifrZ0/sOoZEEBvHQ"
+                + "e20sRA==";
+
+            X509Certificate x509 = new X509CertificateParser().ReadCertificate(Base64.Decode(cert));
+
+            try
+            {
+                x509.Verify(x509.GetPublicKey());
+
+                Fail("forged RSA signature passed");
+            }
+            catch (Exception)
+            {
+                // expected
+            }
+        }
+
+        private void pemTest()
+        {
+            X509Certificate cert = readPemCert(PemData.CERTIFICATE_1);
+            if (cert == null)
+            {
+                Fail("PEM cert not read");
+            }
+            cert = readPemCert("-----BEGIN CERTIFICATE-----" + PemData.CERTIFICATE_2);
+            if (cert == null)
+            {
+                Fail("PEM cert with extraneous header not read");
+            }
+            X509Crl crl = new X509CrlParser().ReadCrl(Encoding.ASCII.GetBytes(PemData.CRL_1));
+            if (crl == null)
+            {
+                Fail("PEM crl not read");
+            }
+            ArrayList col = new ArrayList(
+                new X509CertificateParser().ReadCertificates(Encoding.ASCII.GetBytes(PemData.CERTIFICATE_2)));
+            if (col.Count != 1 || !col.Contains(cert))
+            {
+                Fail("PEM cert collection not right");
+            }
+            col = new ArrayList(
+                new X509CrlParser().ReadCrls(Encoding.ASCII.GetBytes(PemData.CRL_2)));
+            if (col.Count != 1 || !col.Contains(crl))
+            {
+                Fail("PEM crl collection not right");
+            }
+        }
+
+        private static X509Certificate readPemCert(
+            string pemData)
+        {
+            return new X509CertificateParser().ReadCertificate(Encoding.ASCII.GetBytes(pemData));
+        }
+
+        private void pkcs7Test()
+        {
+            Asn1Encodable rootCert = Asn1Object.FromByteArray(CertPathTest.rootCertBin);
+            Asn1Encodable rootCrl = Asn1Object.FromByteArray(CertPathTest.rootCrlBin);
+
+            X509CertificateParser certParser = new X509CertificateParser();
+            X509CrlParser crlParser = new X509CrlParser();
+
+            SignedData sigData = new SignedData(
+                DerSet.Empty,
+                new ContentInfo(CmsObjectIdentifiers.Data, null),
+                new DerSet(
+                    rootCert,
+                    new DerTaggedObject(false, 2, Asn1Object.FromByteArray(AttrCertTest.attrCert))),
+                new DerSet(rootCrl),
+                DerSet.Empty);
+
+            ContentInfo info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData);
+
+            X509Certificate cert = certParser.ReadCertificate(info.GetEncoded());
+            if (cert == null || !AreEqual(cert.GetEncoded(), rootCert.ToAsn1Object().GetEncoded()))
+            {
+                Fail("PKCS7 cert not read");
+            }
+            X509Crl crl = crlParser.ReadCrl(info.GetEncoded());
+            if (crl == null || !AreEqual(crl.GetEncoded(), rootCrl.ToAsn1Object().GetEncoded()))
+            {
+                Fail("PKCS7 crl not read");
+            }
+            ArrayList col = new ArrayList(certParser.ReadCertificates(info.GetEncoded()));
+            if (col.Count != 1 || !col.Contains(cert))
+            {
+                Fail("PKCS7 cert collection not right");
+            }
+            col = new ArrayList(crlParser.ReadCrls(info.GetEncoded()));
+            if (col.Count != 1 || !col.Contains(crl))
+            {
+                Fail("PKCS7 crl collection not right");
+            }
+
+            // data with no certificates or CRLs
+
+            sigData = new SignedData(DerSet.Empty, new ContentInfo(CmsObjectIdentifiers.Data, null), DerSet.Empty, DerSet.Empty, DerSet.Empty);
+
+            info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData);
+
+            cert = certParser.ReadCertificate(info.GetEncoded());
+            if (cert != null)
+            {
+                Fail("PKCS7 cert present");
+            }
+            crl = crlParser.ReadCrl(info.GetEncoded());
+            if (crl != null)
+            {
+                Fail("PKCS7 crl present");
+            }
+
+            // data with absent certificates and CRLS
+
+            sigData = new SignedData(DerSet.Empty, new ContentInfo(CmsObjectIdentifiers.Data, null), null, null, DerSet.Empty);
+
+            info = new ContentInfo(CmsObjectIdentifiers.SignedData, sigData);
+
+            cert = certParser.ReadCertificate(info.GetEncoded());
+            if (cert != null)
+            {
+                Fail("PKCS7 cert present");
+            }
+            crl = crlParser.ReadCrl(info.GetEncoded());
+            if (crl != null)
+            {
+                Fail("PKCS7 crl present");
+            }
+
+            //
+            // sample message
+            //
+            ICollection certCol = certParser.ReadCertificates(pkcs7CrlProblem);
+            ICollection crlCol = crlParser.ReadCrls(pkcs7CrlProblem);
+
+            if (crlCol.Count != 0)
+            {
+                Fail("wrong number of CRLs: " + crlCol.Count);
+            }
+
+            if (certCol.Count != 4)
+            {
+                Fail("wrong number of Certs: " + certCol.Count);
+            }
+        }
+
+        private void createPssCert(
+            string algorithm)
+        {
+            AsymmetricCipherKeyPair keyPair = GenerateLongFixedKeys();
+
+            AsymmetricKeyParameter privKey = keyPair.Private;
+            AsymmetricKeyParameter pubKey = keyPair.Public;
+
+            //
+            // distinguished name table.
+            //
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+            IList values = new ArrayList();
+            values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            //
+            // create base certificate - version 3
+            //
+            X509V3CertificateGenerator  certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name(ord, values));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name(ord, values));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm(algorithm);
+            certGen.AddExtension("2.5.29.15", true,
+            new X509KeyUsage(X509KeyUsage.EncipherOnly));
+            certGen.AddExtension("2.5.29.37", true,
+            new DerSequence(KeyPurposeID.AnyExtendedKeyUsage));
+            certGen.AddExtension("2.5.29.17", true,
+            new GeneralNames(new GeneralName(GeneralName.Rfc822Name, "test at test.test")));
+
+            X509Certificate baseCert = certGen.Generate(privKey);
+
+            baseCert.Verify(pubKey);
+        }
+
+        private static AsymmetricCipherKeyPair GenerateLongFixedKeys()
+        {
+//			RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
+            RsaKeyParameters pubKey = new RsaKeyParameters(false,
+                new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+                new BigInteger("010001",16));
+
+//			RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
+            RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+                new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+                new BigInteger("010001",16),
+                new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+                new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+                new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+                new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+                new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+                new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+//			KeyFactory  fact = KeyFactory.getInstance("RSA", "BC");
+//
+//			PrivateKey privKey = fact.generatePrivate(privKeySpec);
+//			PublicKey pubKey = fact.generatePublic(pubKeySpec);
+
+            return new AsymmetricCipherKeyPair(pubKey, privKey);
+        }
+
+        private void doTestNullDerNullCert()
+        {
+            AsymmetricCipherKeyPair keyPair = GenerateLongFixedKeys();
+
+            AsymmetricKeyParameter pubKey = keyPair.Public;
+            AsymmetricKeyParameter privKey = keyPair.Private;
+
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name("CN=Test"));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name("CN=Test"));
+            certGen.SetPublicKey(pubKey);
+            certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+            X509Certificate cert = certGen.Generate(privKey);
+
+            X509CertificateStructure certStruct = X509CertificateStructure.GetInstance(
+                Asn1Object.FromByteArray(cert.GetEncoded()));
+
+            Asn1Encodable tbsCertificate = certStruct.TbsCertificate;
+            AlgorithmIdentifier sig = certStruct.SignatureAlgorithm;
+
+            DerSequence seq = new DerSequence(
+                tbsCertificate,
+                new AlgorithmIdentifier(sig.ObjectID),
+                certStruct.Signature);
+
+            try
+            {
+                // verify
+                byte[] encoded = seq.GetEncoded();
+                X509CertificateParser fact = new X509CertificateParser();
+                cert = fact.ReadCertificate(encoded);
+                cert.Verify(cert.GetPublicKey());
+            }
+            catch (Exception e)
+            {
+                Fail("doTestNullDerNull failed - exception " + e.ToString(), e);
+            }
+        }
+
+        public override void PerformTest()
+        {
+            checkCertificate(1, cert1);
+            checkCertificate(2, cert2);
+            checkCertificate(3, cert3);
+            checkCertificate(4, cert4);
+            checkCertificate(5, cert5);
+            // This cert uses an incorrect encoding (compressed wrapped in extra octet string)
+            // which the Java build supports backwards, but we choose not to for C# build
+//			checkCertificate(6, oldEcdsa);
+            checkCertificate(7, cert7);
+
+            checkKeyUsage(8, keyUsage);
+            checkSelfSignedCertificate(9, uncompressedPtEC);
+            checkNameCertificate(10, nameCert);
+
+            checkSelfSignedCertificate(11, probSelfSignedCert);
+            checkSelfSignedCertificate(12, gostCA1);
+            checkSelfSignedCertificate(13, gostCA2);
+            checkSelfSignedCertificate(14, gost341094base);
+            checkSelfSignedCertificate(15, gost34102001base);
+            checkSelfSignedCertificate(16, gost341094A);
+            checkSelfSignedCertificate(17, gost341094B);
+            checkSelfSignedCertificate(17, gost34102001A);
+
+            checkCrl(1, crl1);
+
+            checkCreation1();
+            checkCreation2();
+            checkCreation3();
+            checkCreation4();
+            checkCreation5();
+
+            createECCert("SHA1withECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+            createECCert("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+            createECCert("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+            createECCert("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+            createECCert("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+
+            createPssCert("SHA1withRSAandMGF1");
+            createPssCert("SHA224withRSAandMGF1");
+            createPssCert("SHA256withRSAandMGF1");
+            createPssCert("SHA384withRSAandMGF1");
+
+            checkCrlCreation1();
+            checkCrlCreation2();
+            checkCrlCreation3();
+
+            pemTest();
+            pkcs7Test();
+
+            doTestForgedSignature();
+
+            doTestNullDerNullCert();
+
+            checkCertificate(18, emptyDNCert);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new CertTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/CipherStreamTest.cs b/BouncyCastle.AxCrypt/test/src/test/CipherStreamTest.cs
new file mode 100644
index 0000000..0809dfe
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/CipherStreamTest.cs
@@ -0,0 +1,449 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>Check that cipher input/output streams are working correctly</remarks>
+	[TestFixture]
+	public class CipherStreamTest
+		: SimpleTest
+	{
+		private static readonly byte[] RK = Hex.Decode("0123456789ABCDEF");
+		private static readonly byte[] RIN = Hex.Decode("4e6f772069732074");
+		private static readonly byte[] ROUT = Hex.Decode("3afbb5c77938280d");
+
+		private static byte[] SIN = Hex.Decode(
+			"00000000000000000000000000000000"
+			+ "00000000000000000000000000000000"
+			+ "00000000000000000000000000000000"
+			+ "00000000000000000000000000000000");
+		private static readonly byte[] SK = Hex.Decode("80000000000000000000000000000000");
+		private static readonly byte[] SIV = Hex.Decode("0000000000000000");
+		private static readonly byte[] SOUT = Hex.Decode(
+			  "4DFA5E481DA23EA09A31022050859936"
+			+ "DA52FCEE218005164F267CB65F5CFD7F"
+			+ "2B4F97E0FF16924A52DF269515110A07"
+			+ "F9E460BC65EF95DA58F740B7D1DBB0AA");
+
+		private static readonly byte[] HCIN = new byte[64];
+		private static readonly byte[] HCIV = new byte[32];
+
+		private static readonly byte[] HCK256A = new byte[32];
+		private static readonly byte[] HC256A = Hex.Decode(
+			  "5B078985D8F6F30D42C5C02FA6B67951"
+			+ "53F06534801F89F24E74248B720B4818"
+			+ "CD9227ECEBCF4DBF8DBF6977E4AE14FA"
+			+ "E8504C7BC8A9F3EA6C0106F5327E6981");
+
+		private static readonly byte[] HCK128A = new byte[16];
+		private static readonly byte[] HC128A = Hex.Decode(
+			  "82001573A003FD3B7FD72FFB0EAF63AA"
+			+ "C62F12DEB629DCA72785A66268EC758B"
+			+ "1EDB36900560898178E0AD009ABF1F49"
+			+ "1330DC1C246E3D6CB264F6900271D59C");
+
+		private void doRunTest(
+			string	name,
+			int		ivLength)
+		{
+			string lCode = "ABCDEFGHIJKLMNOPQRSTUVWXY0123456789";
+
+			string baseName = name;
+			if (name.IndexOf('/') >= 0)
+			{
+				baseName = name.Substring(0, name.IndexOf('/'));
+			}
+
+			CipherKeyGenerator kGen = GeneratorUtilities.GetKeyGenerator(baseName);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher(name);
+			IBufferedCipher outCipher = CipherUtilities.GetCipher(name);
+			KeyParameter key = ParameterUtilities.CreateKeyParameter(baseName, kGen.GenerateKey());
+			MemoryStream bIn = new MemoryStream(Encoding.ASCII.GetBytes(lCode), false);
+			MemoryStream bOut = new MemoryStream();
+
+			// In the Java build, this IV would be implicitly created and then retrieved with getIV()
+			ICipherParameters cipherParams = key;
+			if (ivLength > 0)
+			{
+				cipherParams = new ParametersWithIV(cipherParams, new byte[ivLength]);
+			}
+
+			inCipher.Init(true, cipherParams);
+
+			// TODO Should we provide GetIV() method on IBufferedCipher?
+			//if (inCipher.getIV() != null)
+			//{
+			//	outCipher.Init(false, new ParametersWithIV(key, inCipher.getIV()));
+			//}
+			//else
+			//{
+			//	outCipher.Init(false, key);
+			//}
+			outCipher.Init(false, cipherParams);
+
+			CipherStream cIn = new CipherStream(bIn, inCipher, null);
+			CipherStream cOut = new CipherStream(bOut, null, outCipher);
+
+			int c;
+
+			while ((c = cIn.ReadByte()) >= 0)
+			{
+				cOut.WriteByte((byte)c);
+			}
+
+			cIn.Close();
+
+			cOut.Flush();
+			cOut.Close();
+
+			byte[] bs = bOut.ToArray();
+			string res = Encoding.ASCII.GetString(bs, 0, bs.Length);
+
+			if (!res.Equals(lCode))
+			{
+				Fail("Failed - decrypted data doesn't match.");
+			}
+		}
+
+		private void doTestAlgorithm(
+			string	name,
+			byte[]	keyBytes,
+			byte[]	iv,
+			byte[]	plainText,
+			byte[]	cipherText)
+		{
+			KeyParameter key = ParameterUtilities.CreateKeyParameter(name, keyBytes);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher(name);
+			IBufferedCipher outCipher = CipherUtilities.GetCipher(name);
+
+			if (iv != null)
+			{
+				inCipher.Init(true, new ParametersWithIV(key, iv));
+				outCipher.Init(false, new ParametersWithIV(key, iv));
+			}
+			else
+			{
+				inCipher.Init(true, key);
+				outCipher.Init(false, key);
+			}
+
+			byte[] enc = inCipher.DoFinal(plainText);
+			if (!AreEqual(enc, cipherText))
+			{
+				Fail(name + ": cipher text doesn't match");
+			}
+
+			byte[] dec = outCipher.DoFinal(enc);
+
+			if (!AreEqual(dec, plainText))
+			{
+				Fail(name + ": plain text doesn't match");
+			}
+		}
+
+		private void doTestException(
+			string	name,
+			int		ivLength)
+		{
+			try
+			{
+				byte[] key128 = {
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143,
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143
+				};
+
+				byte[] key256 = {
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143,
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143,
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143,
+					(byte)128, (byte)131, (byte)133, (byte)134,
+					(byte)137, (byte)138, (byte)140, (byte)143 };
+
+				byte[] keyBytes;
+				if (name.Equals("HC256"))
+				{
+					keyBytes = key256;
+				}
+				else
+				{
+					keyBytes = key128;
+				}
+
+				KeyParameter cipherKey = ParameterUtilities.CreateKeyParameter(name, keyBytes);
+
+				ICipherParameters cipherParams = cipherKey;
+				if (ivLength > 0)
+				{
+					cipherParams = new ParametersWithIV(cipherParams, new byte[ivLength]);
+				}
+
+				IBufferedCipher ecipher = CipherUtilities.GetCipher(name);
+				ecipher.Init(true, cipherParams);
+
+				byte[] cipherText = new byte[0];
+				try
+				{
+					// According specification Method engineUpdate(byte[] input,
+					// int inputOffset, int inputLen, byte[] output, int
+					// outputOffset)
+					// throws ShortBufferException - if the given output buffer is
+					// too
+					// small to hold the result
+					ecipher.ProcessBytes(new byte[20], 0, 20, cipherText, 0);
+
+//					Fail("failed exception test - no ShortBufferException thrown");
+					Fail("failed exception test - no DataLengthException thrown");
+				}
+//				catch (ShortBufferException e)
+				catch (DataLengthException)
+				{
+					// ignore
+				}
+
+				// NB: The lightweight engine doesn't take public/private keys
+//				try
+//				{
+//					IBufferedCipher c = CipherUtilities.GetCipher(name);
+//
+//					//                Key k = new PublicKey()
+//					//                {
+//					//
+//					//                    public string getAlgorithm()
+//					//                    {
+//					//                        return "STUB";
+//					//                    }
+//					//
+//					//                    public string getFormat()
+//					//                    {
+//					//                        return null;
+//					//                    }
+//					//
+//					//                    public byte[] getEncoded()
+//					//                    {
+//					//                        return null;
+//					//                    }
+//					//
+//					//                };
+//					AsymmetricKeyParameter k = new AsymmetricKeyParameter(false);
+//					c.Init(true, k);
+//
+//					Fail("failed exception test - no InvalidKeyException thrown for public key");
+//				}
+//				catch (InvalidKeyException)
+//				{
+//					// okay
+//				}
+//
+//				try
+//				{
+//					IBufferedCipher c = CipherUtilities.GetCipher(name);
+//
+//					//				Key k = new PrivateKey()
+//					//                {
+//					//
+//					//                    public string getAlgorithm()
+//					//                    {
+//					//                        return "STUB";
+//					//                    }
+//					//
+//					//                    public string getFormat()
+//					//                    {
+//					//                        return null;
+//					//                    }
+//					//
+//					//                    public byte[] getEncoded()
+//					//                    {
+//					//                        return null;
+//					//                    }
+//					//
+//					//                };
+//
+//					AsymmetricKeyParameter k = new AsymmetricKeyParameter(true);
+//					c.Init(false, k);
+//
+//					Fail("failed exception test - no InvalidKeyException thrown for private key");
+//				}
+//				catch (InvalidKeyException)
+//				{
+//					// okay
+//				}
+			}
+			catch (Exception e)
+			{
+				Fail("unexpected exception.", e);
+			}
+		}
+
+		[Test]
+		public void TestRC4()
+		{
+			doRunTest("RC4", 0);
+		}
+
+		[Test]
+		public void TestRC4Exception()
+		{
+			doTestException("RC4", 0);
+		}
+
+		[Test]
+		public void TestRC4Algorithm()
+		{
+			doTestAlgorithm("RC4", RK, null, RIN, ROUT);
+		}
+
+		[Test]
+		public void TestSalsa20()
+		{
+			doRunTest("Salsa20", 8);
+		}
+
+		[Test]
+		public void TestSalsa20Exception()
+		{
+			doTestException("Salsa20", 8);
+		}
+
+		[Test]
+		public void TestSalsa20Algorithm()
+		{
+			doTestAlgorithm("Salsa20", SK, SIV, SIN, SOUT);
+		}
+
+		[Test]
+		public void TestHC128()
+		{
+			doRunTest("HC128", 16);
+		}
+
+		[Test]
+		public void TestHC128Exception()
+		{
+			doTestException("HC128", 16);
+		}
+
+		[Test]
+		public void TestHC128Algorithm()
+		{
+			doTestAlgorithm("HC128", HCK128A, HCIV, HCIN, HC128A);
+		}
+
+		[Test]
+		public void TestHC256()
+		{
+			doRunTest("HC256", 32);
+		}
+
+		[Test]
+		public void TestHC256Exception()
+		{
+			doTestException("HC256", 32);
+		}
+
+		[Test]
+		public void TestHC256Algorithm()
+		{
+			doTestAlgorithm("HC256", HCK256A, HCIV, HCIN, HC256A);
+		}
+
+		[Test]
+		public void TestVmpc()
+		{
+			doRunTest("VMPC", 16);
+		}
+
+		[Test]
+		public void TestVmpcException()
+		{
+			doTestException("VMPC", 16);
+		}
+
+//		[Test]
+//		public void TestVmpcAlgorithm()
+//		{
+//			doTestAlgorithm("VMPC", a, iv, in, a);
+//		}
+
+		[Test]
+		public void TestVmpcKsa3()
+		{
+			doRunTest("VMPC-KSA3", 16);
+		}
+
+		[Test]
+		public void TestVmpcKsa3Exception()
+		{
+			doTestException("VMPC-KSA3", 16);
+		}
+
+//		[Test]
+//		public void TestVmpcKsa3Algorithm()
+//		{
+//			doTestAlgorithm("VMPC-KSA3", a, iv, in, a);
+//		}
+
+		[Test]
+		public void TestDesEcbPkcs7()
+		{
+			doRunTest("DES/ECB/PKCS7Padding", 0);
+		}
+
+		[Test]
+		public void TestDesCfbNoPadding()
+		{
+			doRunTest("DES/CFB8/NoPadding", 0);
+		}
+
+		public override void PerformTest()
+		{
+			TestRC4();
+			TestRC4Exception();
+			TestRC4Algorithm();
+			TestSalsa20();
+			TestSalsa20Exception();
+			TestSalsa20Algorithm();
+			TestHC128();
+			TestHC128Exception();
+			TestHC128Algorithm();
+			TestHC256();
+			TestHC256Exception();
+			TestHC256Algorithm();
+			TestVmpc();
+			TestVmpcException();
+//			TestVmpcAlgorithm();
+			TestVmpcKsa3();
+			TestVmpcKsa3Exception();
+//			TestVmpcKsa3Algorithm();
+			TestDesEcbPkcs7();
+			TestDesCfbNoPadding();
+		}
+
+		public override string Name
+		{
+			get { return "CipherStreamTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new CipherStreamTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/DESedeTest.cs b/BouncyCastle.AxCrypt/test/src/test/DESedeTest.cs
new file mode 100644
index 0000000..d84b994
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/DESedeTest.cs
@@ -0,0 +1,298 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    /// <remarks>
+    /// Basic test class for key generation for a DES-EDE block cipher, basically
+    /// this just exercises the provider, and makes sure we are behaving sensibly,
+    /// correctness of the implementation is shown in the lightweight test classes.
+    /// </remarks>
+    [TestFixture]
+    public class DesEdeTest
+        : SimpleTest
+    {
+        private static string[] cipherTests1 =
+    {
+        "112",
+        "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394",
+        "128",
+        "2f4bc6b30c893fa549d82c560d61cf3eb088aed020603de249d82c560d61cf3e529e95ecd8e05394",
+        "168",
+        "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89",
+        "192",
+        "50ddb583a25c21e6c9233f8e57a86d40bb034af421c03096c9233f8e57a86d402fce91e8eb639f89",
+        };
+
+        private static byte[] input1 = Hex.Decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
+
+        /**
+         * a fake random number generator - we just want to make sure the random numbers
+         * aren't random so that we get the same output, while still getting to test the
+         * key generation facilities.
+         */
+        private class FixedSecureRandom
+            : SecureRandom
+        {
+            private byte[] seed =
+        {
+            (byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+            (byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+            (byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+            (byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+        };
+
+            public override void NextBytes(
+                byte[] bytes)
+            {
+                int offset = 0;
+
+                while ((offset + seed.Length) < bytes.Length)
+                {
+                    Array.Copy(seed, 0, bytes, offset, seed.Length);
+                    offset += seed.Length;
+                }
+
+                Array.Copy(seed, 0, bytes, offset, bytes.Length - offset);
+            }
+        }
+
+        public override string Name
+        {
+            get { return "DESEDE"; }
+        }
+
+        private void wrapTest(
+            string  alg,
+            int     id,
+            byte[]  kek,
+            byte[]  iv,
+            byte[]  input,
+            byte[]  output)
+        {
+            try
+            {
+                IWrapper wrapper = WrapperUtilities.GetWrapper(alg + "Wrap");
+
+                KeyParameter desEdeKey = new DesEdeParameters(kek);
+                wrapper.Init(true, new ParametersWithIV(desEdeKey, iv));
+
+                try
+                {
+//					byte[] cText = wrapper.Wrap(new SecretKeySpec(input, alg));
+                    byte[] cText = wrapper.Wrap(input, 0, input.Length);
+
+                    if (!Arrays.AreEqual(cText, output))
+                    {
+                        Fail("failed wrap test " + id  + " expected "
+                            + Hex.ToHexString(output) + " got " + Hex.ToHexString(cText));
+                    }
+                }
+                catch (Exception e)
+                {
+                    Fail("failed wrap test exception " + e.ToString());
+                }
+
+                wrapper.Init(false, desEdeKey);
+
+                try
+                {
+//					Key pText = wrapper.unwrap(output, alg, IBufferedCipher.SECRET_KEY);
+                    byte[] pText = wrapper.Unwrap(output, 0, output.Length);
+//					if (!Arrays.AreEqual(pText.getEncoded(), input))
+                    if (!Arrays.AreEqual(pText, input))
+                    {
+                        Fail("failed unwrap test " + id  + " expected "
+                            + Hex.ToHexString(input) + " got "
+                            + Hex.ToHexString(pText));
+                    }
+                }
+                catch (Exception e)
+                {
+                    Fail("failed unwrap test exception " + e.ToString());
+                }
+            }
+            catch (Exception ex)
+            {
+                Fail("failed exception " + ex.ToString());
+            }
+        }
+
+        private void doTest(
+            string  alg,
+            int     strength,
+            byte[]  input,
+            byte[]  output)
+        {
+            KeyParameter		key = null;
+            CipherKeyGenerator	keyGen;
+            SecureRandom		rand;
+            IBufferedCipher		inCipher = null;
+            IBufferedCipher		outCipher = null;
+            CipherStream		cIn;
+            CipherStream		cOut;
+            MemoryStream		bIn;
+            MemoryStream		bOut;
+
+            rand = new FixedSecureRandom();
+
+            try
+            {
+                keyGen = GeneratorUtilities.GetKeyGenerator(alg);
+                keyGen.Init(new KeyGenerationParameters(rand, strength));
+
+                key = new DesEdeParameters(keyGen.GenerateKey());
+
+                inCipher = CipherUtilities.GetCipher(alg + "/ECB/PKCS7Padding");
+                outCipher = CipherUtilities.GetCipher(alg + "/ECB/PKCS7Padding");
+
+                outCipher.Init(true, new ParametersWithRandom(key, rand));
+            }
+            catch (Exception e)
+            {
+                Fail(alg + " failed initialisation - " + e.ToString());
+            }
+
+            try
+            {
+                inCipher.Init(false, key);
+            }
+            catch (Exception e)
+            {
+                Fail(alg + " failed initialisation - " + e.ToString());
+            }
+
+            //
+            // encryption pass
+            //
+            bOut = new MemoryStream();
+
+            cOut = new CipherStream(bOut, null, outCipher);
+
+            try
+            {
+                for (int i = 0; i != input.Length / 2; i++)
+                {
+                    cOut.WriteByte(input[i]);
+                }
+                cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+                cOut.Close();
+            }
+            catch (IOException e)
+            {
+                Fail(alg + " failed encryption - " + e.ToString());
+            }
+
+            byte[] bytes = bOut.ToArray();
+
+            if (!Arrays.AreEqual(bytes, output))
+            {
+                Fail(alg + " failed encryption - expected "
+                    + Hex.ToHexString(output) + " got "
+                    + Hex.ToHexString(bytes));
+            }
+
+            //
+            // decryption pass
+            //
+            bIn = new MemoryStream(bytes, false);
+
+            cIn = new CipherStream(bIn, inCipher, null);
+
+            try
+            {
+//				DataInputStream dIn = new DataInputStream(cIn);
+                BinaryReader dIn = new BinaryReader(cIn);
+
+                bytes = new byte[input.Length];
+
+                for (int i = 0; i != input.Length / 2; i++)
+                {
+                    bytes[i] = (byte)dIn.ReadByte();
+                }
+//				dIn.readFully(bytes, input.Length / 2, bytes.Length - input.Length / 2);
+                int remaining = bytes.Length - input.Length / 2;
+                byte[] rest = dIn.ReadBytes(remaining);
+                if (rest.Length != remaining)
+                    throw new Exception("IO problem with BinaryReader");
+                rest.CopyTo(bytes, input.Length / 2);
+            }
+            catch (Exception e)
+            {
+                Fail(alg + " failed encryption - " + e.ToString());
+            }
+
+            if (!Arrays.AreEqual(bytes, input))
+            {
+                Fail(alg + " failed decryption - expected "
+                    + Hex.ToHexString(input) + " got "
+                    + Hex.ToHexString(bytes));
+            }
+
+            // TODO Put back in
+//			//
+//			// keyspec test
+//			//
+//			try
+//			{
+//				SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(alg);
+//				DESedeKeySpec keySpec = (DESedeKeySpec)keyFactory.getKeySpec((SecretKey)key, DESedeKeySpec.class);
+//
+//				if (!equalArray(key.getEncoded(), keySpec.getKey(), 16))
+//				{
+//					Fail(alg + " KeySpec does not match key.");
+//				}
+//			}
+//			catch (Exception e)
+//			{
+//				Fail(alg + " failed keyspec - " + e.ToString());
+//			}
+        }
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i != cipherTests1.Length; i += 2)
+            {
+                doTest("DESEDE", int.Parse(cipherTests1[i]), input1, Hex.Decode(cipherTests1[i + 1]));
+            }
+
+            for (int i = 0; i != cipherTests1.Length; i += 2)
+            {
+                doTest("TDEA", int.Parse(cipherTests1[i]), input1, Hex.Decode(cipherTests1[i + 1]));
+            }
+
+            byte[] kek1 = Hex.Decode("255e0d1c07b646dfb3134cc843ba8aa71f025b7c0838251f");
+            byte[] iv1 = Hex.Decode("5dd4cbfc96f5453b");
+            byte[] in1 = Hex.Decode("2923bf85e06dd6ae529149f1f1bae9eab3a7da3d860d3e98");
+            byte[] out1 = Hex.Decode("690107618ef092b3b48ca1796b234ae9fa33ebb4159604037db5d6a84eb3aac2768c632775a467d4");
+
+            wrapTest("DESEDE", 1, kek1, iv1, in1, out1);
+            wrapTest("TDEA", 1, kek1, iv1, in1, out1);
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DesEdeTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/DHTest.cs b/BouncyCastle.AxCrypt/test/src/test/DHTest.cs
new file mode 100644
index 0000000..18a0d84
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/DHTest.cs
@@ -0,0 +1,651 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class DHTest
+        : SimpleTest
+    {
+        private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+        private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+        private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+        private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+        private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+        private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+        // public key with mismatched oid/parameters
+        private byte[] oldPubEnc = Base64.Decode(
+            "MIIBnzCCARQGByqGSM4+AgEwggEHAoGBAPxSrN417g43VAM9sZRf1dt6AocAf7D6" +
+            "WVCtqEDcBJrMzt63+g+BNJzhXVtbZ9kp9vw8L/0PHgzv0Ot/kOLX7Khn+JalOECW" +
+            "YlkyBhmOVbjR79TY5u2GAlvG6pqpizieQNBCEMlUuYuK1Iwseil6VoRuA13Zm7uw" +
+            "WO1eZmaJtY7LAoGAQaPRCFKM5rEdkMrV9FNzeSsYRs8m3DqPnnJHpuySpyO9wUcX" +
+            "OOJcJY5qvHbDO5SxHXu/+bMgXmVT6dXI5o0UeYqJR7fj6pR4E6T0FwG55RFr5Ok4" +
+            "3C4cpXmaOu176SyWuoDqGs1RDGmYQjwbZUi23DjaaTFUly9LCYXMliKrQfEDgYQA" +
+            "AoGAQUGCBN4TaBw1BpdBXdTvTfCU69XDB3eyU2FOBE3UWhpx9D8XJlx4f5DpA4Y6" +
+            "6sQMuCbhfmjEph8W7/sbMurM/awR+PSR8tTY7jeQV0OkmAYdGK2nzh0ZSifMO1oE" +
+            "NNhN2O62TLs67msxT28S4/S89+LMtc98mevQ2SX+JF3wEVU=");
+
+        // bogus key with full PKCS parameter set
+        private byte[] oldFullParams = Base64.Decode(
+            "MIIBIzCCARgGByqGSM4+AgEwggELAoGBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9E" +
+            "AMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f" +
+            "6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv" +
+            "8iIDGZ3RSAHHAoGBAPfhoIXWmz3ey7yrXDa4V7l5lK+7+jrqgvlXTAs9B4JnUVlX" +
+            "jrrUWU/mcQcQgYC0SRZxI+hMKBYTt88JMozIpuE8FnqLVHyNKOCjrh4rs6Z1kW6j" +
+            "fwv6ITVi8ftiegEkO8yk8b6oUZCJqIPf4VrlnwaSi2ZegHtVJWQBTDv+z0kqAgFk" +
+            "AwUAAgIH0A==");
+
+        private byte[] samplePubEnc = Base64.Decode(
+            "MIIBpjCCARsGCSqGSIb3DQEDATCCAQwCgYEA/X9TgR11EilS30qcLuzk5/YRt1I8" +
+            "70QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZUKWk" +
+            "n5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOuK2HX" +
+            "Ku/yIgMZndFIAccCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdR" +
+            "WVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWR" +
+            "bqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoC" +
+            "AgIAA4GEAAKBgEIiqxoUW6E6GChoOgcfNbVFclW91ITf5MFSUGQwt2R0RHoOhxvO" +
+            "lZhNs++d0VPATLAyXovjfgENT9SGCbuZttYcqqLdKTbMXBWPek+rfnAl9E4iEMED" +
+            "IDd83FJTKs9hQcPAm7zmp0Xm1bGF9CbUFjP5G02265z7eBmHDaT0SNlB");
+
+        private byte[] samplePrivEnc = Base64.Decode(
+            "MIIBZgIBADCCARsGCSqGSIb3DQEDATCCAQwCgYEA/X9TgR11EilS30qcLuzk5/YR" +
+            "t1I870QAwx4/gLZRJmlFXUAiUftZPY1Y+r/F9bow9subVWzXgTuAHTRv8mZgt2uZ" +
+            "UKWkn5/oBHsQIsJPu6nX/rfGG/g7V+fGqKYVDwT7g/bTxR7DAjVUE1oWkTL2dfOu" +
+            "K2HXKu/yIgMZndFIAccCgYEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0H" +
+            "gmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuz" +
+            "pnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7P" +
+            "SSoCAgIABEICQAZYXnBHazxXUUdFP4NIf2Ipu7du0suJPZQKKff81wymi2zfCfHh" +
+            "uhe9gQ9xdm4GpzeNtrQ8/MzpTy+ZVrtd29Q=");
+
+        public override string Name
+        {
+            get { return "DH"; }
+        }
+
+        private void doTestGP(
+            string		algName,
+            int         size,
+            int         privateValueSize,
+            BigInteger  g,
+            BigInteger  p)
+        {
+            IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator(algName);
+
+            DHParameters dhParams = new DHParameters(p, g, null, privateValueSize);
+            KeyGenerationParameters kgp = new DHKeyGenerationParameters(new SecureRandom(), dhParams);
+
+            keyGen.Init(kgp);
+
+            //
+            // a side
+            //
+            AsymmetricCipherKeyPair aKeyPair = keyGen.GenerateKeyPair();
+
+            IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algName);
+
+            checkKeySize(privateValueSize, aKeyPair);
+
+            aKeyAgreeBasic.Init(aKeyPair.Private);
+
+            //
+            // b side
+            //
+            AsymmetricCipherKeyPair bKeyPair = keyGen.GenerateKeyPair();
+
+            IBasicAgreement bKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algName);
+
+            checkKeySize(privateValueSize, bKeyPair);
+
+            bKeyAgreeBasic.Init(bKeyPair.Private);
+
+            //
+            // agreement
+            //
+//			aKeyAgreeBasic.doPhase(bKeyPair.Public, true);
+//			bKeyAgreeBasic.doPhase(aKeyPair.Public, true);
+//
+//			BigInteger  k1 = new BigInteger(aKeyAgreeBasic.generateSecret());
+//			BigInteger  k2 = new BigInteger(bKeyAgreeBasic.generateSecret());
+            BigInteger k1 = aKeyAgreeBasic.CalculateAgreement(bKeyPair.Public);
+            BigInteger k2 = bKeyAgreeBasic.CalculateAgreement(aKeyPair.Public);
+
+            if (!k1.Equals(k2))
+            {
+                Fail(size + " bit 2-way test failed");
+            }
+
+            //
+            // public key encoding test
+            //
+//			byte[]              pubEnc = aKeyPair.Public.GetEncoded();
+            byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded();
+
+//			KeyFactory          keyFac = KeyFactory.getInstance(algName);
+//			X509EncodedKeySpec  pubX509 = new X509EncodedKeySpec(pubEnc);
+//			DHPublicKey         pubKey = (DHPublicKey)keyFac.generatePublic(pubX509);
+            DHPublicKeyParameters pubKey = (DHPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
+//			DHParameterSpec     spec = pubKey.Parameters;
+            DHParameters spec = pubKey.Parameters;
+
+            if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P))
+            {
+                Fail(size + " bit public key encoding/decoding test failed on parameters");
+            }
+
+            if (!((DHPublicKeyParameters)aKeyPair.Public).Y.Equals(pubKey.Y))
+            {
+                Fail(size + " bit public key encoding/decoding test failed on y value");
+            }
+
+            //
+            // public key serialisation test
+            //
+            // TODO Put back in
+//			MemoryStream bOut = new MemoryStream();
+//			ObjectOutputStream oOut = new ObjectOutputStream(bOut);
+//
+//			oOut.WriteObject(aKeyPair.Public);
+//
+//			MemoryStream bIn = new MemoryStream(bOut.ToArray(), false);
+//			ObjectInputStream oIn = new ObjectInputStream(bIn);
+//
+//			pubKey = (DHPublicKeyParameters)oIn.ReadObject();
+            spec = pubKey.Parameters;
+
+            if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P))
+            {
+                Fail(size + " bit public key serialisation test failed on parameters");
+            }
+
+            if (!((DHPublicKeyParameters)aKeyPair.Public).Y.Equals(pubKey.Y))
+            {
+                Fail(size + " bit public key serialisation test failed on y value");
+            }
+
+            //
+            // private key encoding test
+            //
+//			byte[] privEnc = aKeyPair.Private.GetEncoded();
+            byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded();
+//			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+//			DHPrivateKeyParameters privKey = (DHPrivateKey)keyFac.generatePrivate(privPKCS8);
+            DHPrivateKeyParameters privKey = (DHPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc);
+
+            spec = privKey.Parameters;
+
+            if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P))
+            {
+                Fail(size + " bit private key encoding/decoding test failed on parameters");
+            }
+
+            if (!((DHPrivateKeyParameters)aKeyPair.Private).X.Equals(privKey.X))
+            {
+                Fail(size + " bit private key encoding/decoding test failed on y value");
+            }
+
+            //
+            // private key serialisation test
+            //
+            // TODO Put back in
+//			bOut = new MemoryStream();
+//			oOut = new ObjectOutputStream(bOut);
+//
+//			oOut.WriteObject(aKeyPair.Private);
+//
+//			bIn = new MemoryStream(bOut.ToArray(), false);
+//			oIn = new ObjectInputStream(bIn);
+//
+//			privKey = (DHPrivateKeyParameters)oIn.ReadObject();
+            spec = privKey.Parameters;
+
+            if (!spec.G.Equals(dhParams.G) || !spec.P.Equals(dhParams.P))
+            {
+                Fail(size + " bit private key serialisation test failed on parameters");
+            }
+
+            if (!((DHPrivateKeyParameters)aKeyPair.Private).X.Equals(privKey.X))
+            {
+                Fail(size + " bit private key serialisation test failed on y value");
+            }
+
+            //
+            // three party test
+            //
+            IAsymmetricCipherKeyPairGenerator aPairGen = GeneratorUtilities.GetKeyPairGenerator(algName);
+            aPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec));
+            AsymmetricCipherKeyPair aPair = aPairGen.GenerateKeyPair();
+
+            IAsymmetricCipherKeyPairGenerator bPairGen = GeneratorUtilities.GetKeyPairGenerator(algName);
+            bPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec));
+            AsymmetricCipherKeyPair bPair = bPairGen.GenerateKeyPair();
+
+            IAsymmetricCipherKeyPairGenerator cPairGen = GeneratorUtilities.GetKeyPairGenerator(algName);
+            cPairGen.Init(new DHKeyGenerationParameters(new SecureRandom(), spec));
+            AsymmetricCipherKeyPair cPair = cPairGen.GenerateKeyPair();
+
+
+            IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement(algName);
+            aKeyAgree.Init(aPair.Private);
+
+            IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement(algName);
+            bKeyAgree.Init(bPair.Private);
+
+            IBasicAgreement cKeyAgree = AgreementUtilities.GetBasicAgreement(algName);
+            cKeyAgree.Init(cPair.Private);
+
+//			Key ac = aKeyAgree.doPhase(cPair.Public, false);
+//			Key ba = bKeyAgree.doPhase(aPair.Public, false);
+//			Key cb = cKeyAgree.doPhase(bPair.Public, false);
+//
+//			aKeyAgree.doPhase(cb, true);
+//			bKeyAgree.doPhase(ac, true);
+//			cKeyAgree.doPhase(ba, true);
+//
+//			BigInteger aShared = new BigInteger(aKeyAgree.generateSecret());
+//			BigInteger bShared = new BigInteger(bKeyAgree.generateSecret());
+//			BigInteger cShared = new BigInteger(cKeyAgree.generateSecret());
+
+            DHPublicKeyParameters ac = new DHPublicKeyParameters(aKeyAgree.CalculateAgreement(cPair.Public), spec);
+            DHPublicKeyParameters ba = new DHPublicKeyParameters(bKeyAgree.CalculateAgreement(aPair.Public), spec);
+            DHPublicKeyParameters cb = new DHPublicKeyParameters(cKeyAgree.CalculateAgreement(bPair.Public), spec);
+
+            BigInteger aShared = aKeyAgree.CalculateAgreement(cb);
+            BigInteger bShared = bKeyAgree.CalculateAgreement(ac);
+            BigInteger cShared = cKeyAgree.CalculateAgreement(ba);
+
+            if (!aShared.Equals(bShared))
+            {
+                Fail(size + " bit 3-way test failed (a and b differ)");
+            }
+
+            if (!cShared.Equals(bShared))
+            {
+                Fail(size + " bit 3-way test failed (c and b differ)");
+            }
+        }
+
+        private void doTestExplicitWrapping(
+            int			size,
+            int			privateValueSize,
+            BigInteger	g,
+            BigInteger	p)
+        {
+            DHParameters dhParams = new DHParameters(p, g, null, privateValueSize);
+
+            IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
+
+            keyGen.Init(new DHKeyGenerationParameters(new SecureRandom(), dhParams));
+
+            //
+            // a side
+            //
+            AsymmetricCipherKeyPair aKeyPair = keyGen.GenerateKeyPair();
+
+            IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
+
+            checkKeySize(privateValueSize, aKeyPair);
+
+            aKeyAgree.Init(aKeyPair.Private);
+
+            //
+            // b side
+            //
+            AsymmetricCipherKeyPair bKeyPair = keyGen.GenerateKeyPair();
+
+            IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement("DH");
+
+            checkKeySize(privateValueSize, bKeyPair);
+
+            bKeyAgree.Init(bKeyPair.Private);
+
+            //
+            // agreement
+            //
+//			aKeyAgree.doPhase(bKeyPair.Public, true);
+//			bKeyAgree.doPhase(aKeyPair.Public, true);
+//
+//			SecretKey k1 = aKeyAgree.generateSecret(PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id);
+//			SecretKey k2 = bKeyAgree.generateSecret(PkcsObjectIdentifiers.IdAlgCms3DesWrap.Id);
+
+            // TODO Does this really test the same thing as the above code?
+            BigInteger b1 = aKeyAgree.CalculateAgreement(bKeyPair.Public);
+            BigInteger b2 = bKeyAgree.CalculateAgreement(aKeyPair.Public);
+
+            if (!b1.Equals(b2))
+            {
+                Fail("Explicit wrapping test failed");
+            }
+        }
+
+        private void checkKeySize(
+            int						privateValueSize,
+            AsymmetricCipherKeyPair	aKeyPair)
+        {
+            if (privateValueSize != 0)
+            {
+                DHPrivateKeyParameters key = (DHPrivateKeyParameters)aKeyPair.Private;
+
+                if (key.X.BitLength != privateValueSize)
+                {
+                    Fail("limited key check failed for key size " + privateValueSize);
+                }
+            }
+        }
+
+// TODO Put back in
+//    private void doTestRandom(
+//        int         size)
+//    {
+//        AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DH");
+//        a.init(size, new SecureRandom());
+//        AlgorithmParameters parameters = a.generateParameters();
+//
+//        byte[] encodeParams = parameters.GetEncoded();
+//
+//        AlgorithmParameters a2 = AlgorithmParameters.getInstance("DH");
+//        a2.init(encodeParams);
+//
+//        // a and a2 should be equivalent!
+//        byte[] encodeParams_2 = a2.GetEncoded();
+//
+//        if (!areEqual(encodeParams, encodeParams_2))
+//        {
+//            Fail("encode/Decode parameters failed");
+//        }
+//
+//        DHParameterSpec dhP = (DHParameterSpec)parameters.getParameterSpec(DHParameterSpec.class);
+//
+//        doTestGP("DH", size, 0, dhP.G, dhP.P);
+//    }
+
+        [Test]
+        public void TestECDH()
+        {
+            doTestECDH("ECDH");
+        }
+
+        [Test]
+        public void TestECDHC()
+        {
+            doTestECDH("ECDHC");
+        }
+
+        private void doTestECDH(
+            string algorithm)
+        {
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator(algorithm);
+
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q
+//				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+//				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters ecSpec = new ECDomainParameters(
+                curve,
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
+                BigInteger.One); //1); // h
+
+//			g.initialize(ecSpec, new SecureRandom());
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
+
+            //
+            // a side
+            //
+            AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
+
+            IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algorithm);
+
+            aKeyAgreeBasic.Init(aKeyPair.Private);
+
+            //
+            // b side
+            //
+            AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair();
+
+            IBasicAgreement bKeyAgreeBasic = AgreementUtilities.GetBasicAgreement(algorithm);
+
+            bKeyAgreeBasic.Init(bKeyPair.Private);
+
+            //
+            // agreement
+            //
+//			aKeyAgreeBasic.doPhase(bKeyPair.Public, true);
+//			bKeyAgreeBasic.doPhase(aKeyPair.Public, true);
+//
+//			BigInteger k1 = new BigInteger(aKeyAgreeBasic.generateSecret());
+//			BigInteger k2 = new BigInteger(bKeyAgreeBasic.generateSecret());
+            BigInteger k1 = aKeyAgreeBasic.CalculateAgreement(bKeyPair.Public);
+            BigInteger k2 = bKeyAgreeBasic.CalculateAgreement(aKeyPair.Public);
+
+            if (!k1.Equals(k2))
+            {
+                Fail(algorithm + " 2-way test failed");
+            }
+
+            //
+            // public key encoding test
+            //
+//			byte[] pubEnc = aKeyPair.Public.GetEncoded();
+            byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded();
+
+//			KeyFactory keyFac = KeyFactory.getInstance(algorithm);
+//			X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc);
+//			ECPublicKey pubKey = (ECPublicKey)keyFac.generatePublic(pubX509);
+            ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
+
+            ECDomainParameters ecDP = pubKey.Parameters;
+
+//			if (!pubKey.getW().Equals(((ECPublicKeyParameters)aKeyPair.Public).getW()))
+            ECPoint pq1 = pubKey.Q.Normalize(), pq2 = ((ECPublicKeyParameters)aKeyPair.Public).Q.Normalize();
+            if (!pq1.Equals(pq2))
+            {
+//				Console.WriteLine(" expected " + pubKey.getW().getAffineX() + " got " + ((ECPublicKey)aKeyPair.Public).getW().getAffineX());
+//				Console.WriteLine(" expected " + pubKey.getW().getAffineY() + " got " + ((ECPublicKey)aKeyPair.Public).getW().getAffineY());
+//				Fail(algorithm + " public key encoding (W test) failed");
+                Console.WriteLine(" expected " + pq1.AffineXCoord.ToBigInteger()
+                    + " got " + pq2.AffineXCoord.ToBigInteger());
+                Console.WriteLine(" expected " + pq1.AffineYCoord.ToBigInteger()
+                    + " got " + pq2.AffineYCoord.ToBigInteger());
+                Fail(algorithm + " public key encoding (Q test) failed");
+            }
+
+//			if (!pubKey.Parameters.getGenerator().Equals(((ECPublicKeyParameters)aKeyPair.Public).Parameters.getGenerator()))
+            if (!pubKey.Parameters.G.Equals(((ECPublicKeyParameters)aKeyPair.Public).Parameters.G))
+            {
+                Fail(algorithm + " public key encoding (G test) failed");
+            }
+
+            //
+            // private key encoding test
+            //
+//			byte[] privEnc = aKeyPair.Private.GetEncoded();
+            byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded();
+
+//			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+//			ECPrivateKey        privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8);
+            ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc);
+
+//			if (!privKey.getS().Equals(((ECPrivateKey)aKeyPair.Private).getS()))
+            if (!privKey.D.Equals(((ECPrivateKeyParameters)aKeyPair.Private).D))
+            {
+//				Fail(algorithm + " private key encoding (S test) failed");
+                Fail(algorithm + " private key encoding (D test) failed");
+            }
+
+//			if (!privKey.Parameters.getGenerator().Equals(((ECPrivateKey)aKeyPair.Private).Parameters.getGenerator()))
+            if (!privKey.Parameters.G.Equals(((ECPrivateKeyParameters)aKeyPair.Private).Parameters.G))
+            {
+                Fail(algorithm + " private key encoding (G test) failed");
+            }
+        }
+
+        [Test]
+        public void TestExceptions()
+        {
+            DHParameters dhParams = new DHParameters(p512, g512);
+
+            try
+            {
+                IBasicAgreement aKeyAgreeBasic = AgreementUtilities.GetBasicAgreement("DH");
+
+//				aKeyAgreeBasic.generateSecret("DES");
+                aKeyAgreeBasic.CalculateAgreement(null);
+            }
+            catch (InvalidOperationException)
+            {
+                // okay
+            }
+            catch (Exception e)
+            {
+                Fail("Unexpected exception: " + e, e);
+            }
+        }
+
+        private void doTestDesAndDesEde(
+            BigInteger	g,
+            BigInteger	p)
+        {
+            DHParameters dhParams = new DHParameters(p, g, null, 256);
+
+            IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("DH");
+
+            keyGen.Init(new DHKeyGenerationParameters(new SecureRandom(), dhParams));
+
+            AsymmetricCipherKeyPair kp = keyGen.GenerateKeyPair();
+
+            IBasicAgreement keyAgreement = AgreementUtilities.GetBasicAgreement("DH");
+
+            keyAgreement.Init(kp.Private);
+            BigInteger agreed = keyAgreement.CalculateAgreement(kp.Public);
+            byte[] agreedBytes = agreed.ToByteArrayUnsigned();
+
+            // TODO Figure out where the magic happens of choosing the right
+            // bytes from 'agreedBytes' for each key type - need C# equivalent?
+            // (see JCEDHKeyAgreement.engineGenerateSecret)
+
+//			SecretKey key = keyAgreement.generateSecret("DES");
+//
+//			if (key.getEncoded().length != 8)
+//			{
+//				Fail("DES length wrong");
+//			}
+//
+//			if (!DESKeySpec.isParityAdjusted(key.getEncoded(), 0))
+//			{
+//				Fail("DES parity wrong");
+//			}
+//
+//			key = keyAgreement.generateSecret("DESEDE");
+//
+//			if (key.getEncoded().length != 24)
+//			{
+//				Fail("DESEDE length wrong");
+//			}
+//
+//			if (!DESedeKeySpec.isParityAdjusted(key.getEncoded(), 0))
+//			{
+//				Fail("DESEDE parity wrong");
+//			}
+//
+//			key = keyAgreement.generateSecret("Blowfish");
+//
+//			if (key.getEncoded().length != 16)
+//			{
+//				Fail("Blowfish length wrong");
+//			}
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            doTestGP("DH", 512, 0, g512, p512);
+            doTestGP("DiffieHellman", 768, 0, g768, p768);
+            doTestGP("DIFFIEHELLMAN", 1024, 0, g1024, p1024);
+            doTestGP("DH", 512, 64, g512, p512);
+            doTestGP("DiffieHellman", 768, 128, g768, p768);
+            doTestGP("DIFFIEHELLMAN", 1024, 256, g1024, p1024);
+            doTestExplicitWrapping(512, 0, g512, p512);
+            doTestDesAndDesEde(g768, p768);
+
+            // TODO Put back in
+            //doTestRandom(256);
+        }
+
+        [Test]
+        public void TestEnc()
+        {
+//			KeyFactory kFact = KeyFactory.getInstance("DH", "BC");
+//			
+//			Key k = kFact.generatePrivate(new PKCS8EncodedKeySpec(samplePrivEnc));
+            AsymmetricKeyParameter k = PrivateKeyFactory.CreateKey(samplePrivEnc);
+            byte[] encoded = PrivateKeyInfoFactory.CreatePrivateKeyInfo(k).GetEncoded();
+
+            if (!Arrays.AreEqual(samplePrivEnc, encoded))
+            {
+                Fail("private key re-encode failed");
+            }
+
+//			k = kFact.generatePublic(new X509EncodedKeySpec(samplePubEnc));
+            k = PublicKeyFactory.CreateKey(samplePubEnc);
+            encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded();
+
+            if (!Arrays.AreEqual(samplePubEnc, encoded))
+            {
+                Fail("public key re-encode failed");
+            }
+
+//			k = kFact.generatePublic(new X509EncodedKeySpec(oldPubEnc));
+            k = PublicKeyFactory.CreateKey(oldPubEnc);
+            encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded();
+
+            if (!Arrays.AreEqual(oldPubEnc, encoded))
+            {
+                Fail("old public key re-encode failed");
+            }
+
+//			k = kFact.generatePublic(new X509EncodedKeySpec(oldFullParams));
+            k = PublicKeyFactory.CreateKey(oldFullParams);
+            encoded = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(k).GetEncoded();
+
+            if (!Arrays.AreEqual(oldFullParams, encoded))
+            {
+                Fail("old full public key re-encode failed");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            TestEnc();
+            TestFunction();
+            TestECDH();
+            TestECDHC();
+            TestExceptions();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DHTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/DSATest.cs b/BouncyCastle.AxCrypt/test/src/test/DSATest.cs
new file mode 100644
index 0000000..a8b8bec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/DSATest.cs
@@ -0,0 +1,888 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class DsaTest
+        : SimpleTest
+    {
+        private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+        private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+
+        private static readonly SecureRandom random = FixedSecureRandom.From(k1, k2);
+
+        // TODO How shall we satisfy this compatibility test?
+//		[Test]
+//		public void TestCompat()
+//		{
+//			if (Security.getProvider("SUN") == null)
+//				return;
+//			ISigner s = SignerUtilities.GetSigner("DSA", "SUN");
+//			KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA", "SUN");
+//			byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+//
+//			g.initialize(512, new SecureRandom());
+//
+//			KeyPair p = g.generateKeyPair();
+//
+//			PrivateKey sKey = p.Private;
+//			PublicKey vKey = p.Public;
+//
+//			//
+//			// sign SUN - verify with BC
+//			//
+//			s.Init(true, sKey);
+//
+//			s.update(data);
+//
+//			byte[] sigBytes = s.GenerateSignature();
+//
+//			s = SignerUtilities.GetSigner("DSA");
+//
+//			s.Init(false, vKey);
+//
+//			s.update(data);
+//
+//			if (!s.VerifySignature(sigBytes))
+//			{
+//				Fail("SUN -> BC verification failed");
+//			}
+//
+//			//
+//			// sign BC - verify with SUN
+//			//
+//
+//			s.Init(true, sKey);
+//
+//			s.update(data);
+//
+//			sigBytes = s.GenerateSignature();
+//
+//			s = SignerUtilities.GetSigner("DSA", "SUN");
+//
+//			s.Init(false, vKey);
+//
+//			s.update(data);
+//
+//			if (!s.VerifySignature(sigBytes))
+//			{
+//				Fail("BC -> SUN verification failed");
+//			}
+//
+//			//
+//			// key encoding test - BC decoding Sun keys
+//			//
+//			KeyFactory f = KeyFactory.GetInstance("DSA");
+//			X509EncodedKeySpec x509s = new X509EncodedKeySpec(vKey.GetEncoded());
+//			DSAPublicKey k1 = (DSAPublicKey)f.generatePublic(x509s);
+//
+//			if (!k1.Y.Equals(((DSAPublicKey)vKey).Y))
+//			{
+//				Fail("public number not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.G.Equals(((DSAPublicKey)vKey).Parameters.G))
+//			{
+//				Fail("public generator not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.P.Equals(((DSAPublicKey)vKey).Parameters.P))
+//			{
+//				Fail("public p value not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.Q.Equals(((DSAPublicKey)vKey).Parameters.Q))
+//			{
+//				Fail("public q value not decoded properly");
+//			}
+//
+//			PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(sKey.GetEncoded());
+//			DSAPrivateKey k2 = (DSAPrivateKey)f.generatePrivate(pkcs8);
+//
+//			if (!k2.X.Equals(((DSAPrivateKey)sKey).X))
+//			{
+//				Fail("private number not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.G.Equals(((DSAPrivateKey)sKey).Parameters.G))
+//			{
+//				Fail("private generator not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.P.Equals(((DSAPrivateKey)sKey).Parameters.P))
+//			{
+//				Fail("private p value not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.Q.Equals(((DSAPrivateKey)sKey).Parameters.Q))
+//			{
+//				Fail("private q value not decoded properly");
+//			}
+//
+//			//
+//			// key decoding test - SUN decoding BC keys
+//			//
+//			f = KeyFactory.GetInstance("DSA", "SUN");
+//			x509s = new X509EncodedKeySpec(k1.GetEncoded());
+//
+//			vKey = (DSAPublicKey)f.generatePublic(x509s);
+//
+//			if (!k1.Y.Equals(((DSAPublicKey)vKey).Y))
+//			{
+//				Fail("public number not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.G.Equals(((DSAPublicKey)vKey).Parameters.G))
+//			{
+//				Fail("public generator not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.P.Equals(((DSAPublicKey)vKey).Parameters.P))
+//			{
+//				Fail("public p value not decoded properly");
+//			}
+//
+//			if (!k1.Parameters.Q.Equals(((DSAPublicKey)vKey).Parameters.Q))
+//			{
+//				Fail("public q value not decoded properly");
+//			}
+//
+//			pkcs8 = new PKCS8EncodedKeySpec(k2.GetEncoded());
+//			sKey = (DSAPrivateKey)f.generatePrivate(pkcs8);
+//
+//			if (!k2.X.Equals(((DSAPrivateKey)sKey).X))
+//			{
+//				Fail("private number not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.G.Equals(((DSAPrivateKey)sKey).Parameters.G))
+//			{
+//				Fail("private generator not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.P.Equals(((DSAPrivateKey)sKey).Parameters.P))
+//			{
+//				Fail("private p value not decoded properly");
+//			}
+//
+//			if (!k2.Parameters.Q.Equals(((DSAPrivateKey)sKey).Parameters.Q))
+//			{
+//				Fail("private q value not decoded properly");
+//			}
+//		}
+
+        [Test]
+        public void TestNONEwithDSA()
+        {
+            byte[] dummySha1 = Hex.Decode("01020304050607080910111213141516");
+
+            SecureRandom rand = new SecureRandom();
+
+            DsaParametersGenerator pGen = new DsaParametersGenerator();
+            pGen.Init(512, 80, rand);
+
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters()));
+
+            AsymmetricCipherKeyPair kp = g.GenerateKeyPair();
+
+            ISigner sig = SignerUtilities.GetSigner("NONEwithDSA");
+            sig.Init(true, kp.Private);
+            sig.BlockUpdate(dummySha1, 0, dummySha1.Length);
+            byte[] sigBytes = sig.GenerateSignature();
+
+            sig.Init(false, kp.Public);
+            sig.BlockUpdate(dummySha1, 0, dummySha1.Length);
+            sig.VerifySignature(sigBytes);
+
+            // reset test
+
+            sig.BlockUpdate(dummySha1, 0, dummySha1.Length);
+
+            if (!sig.VerifySignature(sigBytes))
+            {
+                Fail("NONEwithDSA failed to reset");
+            }
+
+            // lightweight test
+            DsaSigner signer = new DsaSigner();
+            Asn1Sequence derSig = Asn1Sequence.GetInstance(Asn1Object.FromByteArray(sigBytes));
+
+            signer.Init(false, kp.Public);
+
+            if (!signer.VerifySignature(dummySha1,
+                DerInteger.GetInstance(derSig[0]).Value, DerInteger.GetInstance(derSig[1]).Value))
+            {
+                Fail("NONEwithDSA not really NONE!");
+            }
+        }
+
+        /**
+        * X9.62 - 1998,<br/>
+        * J.3.2, Page 155, ECDSA over the field Fp<br/>
+        * an example with 239 bit prime
+        */
+        [Test]
+        public void TestECDsa239BitPrime()
+        {
+            BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
+            BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(
+                new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+
+//			KeyFactory f = KeyFactory.GetInstance("ECDSA");
+//			PrivateKey sKey = f.generatePrivate(priKey);
+//			PublicKey vKey = f.generatePublic(pubKey);
+            AsymmetricKeyParameter sKey = priKey;
+            AsymmetricKeyParameter vKey = pubKey;
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            byte[] message = Encoding.ASCII.GetBytes("abc");
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("239 Bit EC verification failed");
+            }
+
+            BigInteger[] sig = DerDecode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                        + " expecting: " + r + SimpleTest.NewLine
+                        + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                        + " expecting: " + s + SimpleTest.NewLine
+                        + " got      : " + sig[1]);
+            }
+        }
+
+        /**
+        * X9.62 - 1998,<br/>
+        * J.2.1, Page 100, ECDSA over the field F2m<br/>
+        * an example with 191 bit binary field
+        */
+        [Test]
+        public void TestECDsa239BitBinary()
+        {
+            BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+            BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(
+                new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            ECCurve curve = new F2mCurve(
+                239, // m
+                36, // k
+                new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); // h
+
+            ECPrivateKeyParameters sKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+                parameters);
+
+            ECPublicKeyParameters vKey = new ECPublicKeyParameters(
+                "ECDSA",
+                curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                parameters);
+
+            ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+            byte[] message = Encoding.ASCII.GetBytes("abc");
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("239 Bit EC verification failed");
+            }
+
+            BigInteger[] sig = DerDecode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+        }
+
+        [Test]
+        public void TestECDsa239BitBinaryRipeMD160()
+        {
+            DoTestECDsa239BitBinary("RIPEMD160withECDSA", TeleTrusTObjectIdentifiers.ECSignWithRipeMD160);
+        }
+
+        [Test]
+        public void TestECDsa239BitBinarySha1()
+        {
+            DoTestECDsa239BitBinary("SHA1withECDSA", TeleTrusTObjectIdentifiers.ECSignWithSha1);
+        }
+
+        [Test]
+        public void TestECDsa239BitBinarySha224()
+        {
+            DoTestECDsa239BitBinary("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+        }
+
+        [Test]
+        public void TestECDsa239BitBinarySha256()
+        {
+            DoTestECDsa239BitBinary("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+        }
+
+        [Test]
+        public void TestECDsa239BitBinarySha384()
+        {
+            DoTestECDsa239BitBinary("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+        }
+
+        [Test]
+        public void TestECDsa239BitBinarySha512()
+        {
+            DoTestECDsa239BitBinary("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+        }
+
+        private void DoTestECDsa239BitBinary(
+            string				algorithm,
+            DerObjectIdentifier	oid)
+        {
+            BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+            BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
+
+            byte[] kData = BigIntegers.AsUnsignedByteArray(
+                new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363"));
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            ECCurve curve = new F2mCurve(
+                239, // m
+                36, // k
+                new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); // h
+
+            ECPrivateKeyParameters sKey = new ECPrivateKeyParameters(
+                new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+                parameters);
+
+            ECPublicKeyParameters vKey = new ECPublicKeyParameters(
+                curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                parameters);
+
+            ISigner sgr = SignerUtilities.GetSigner(algorithm);
+            byte[] message = Encoding.ASCII.GetBytes("abc");
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr = SignerUtilities.GetSigner(oid.Id);
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("239 Bit EC RIPEMD160 verification failed");
+            }
+        }
+
+        private void doTestBadStrength(
+            int strength)
+        {
+//			IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+
+            // test exception
+            //
+            try
+            {
+                SecureRandom rand = new SecureRandom();
+
+                DsaParametersGenerator pGen = new DsaParametersGenerator();
+                pGen.Init(strength, 80, rand);
+
+//				g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters()));
+
+                Fail("illegal parameter " + strength + " check failed.");
+            }
+            catch (ArgumentException)
+            {
+                // expected
+            }
+        }
+
+        [Test]
+        public void TestGeneration()
+        {
+            ISigner s = SignerUtilities.GetSigner("DSA");
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+            SecureRandom rand = new SecureRandom();
+
+            // KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA");
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+
+            // test exception
+            //
+
+            doTestBadStrength(513);
+            doTestBadStrength(510);
+            doTestBadStrength(1025);
+
+            //g.initialize(512, rand);
+            {
+                DsaParametersGenerator pGen = new DsaParametersGenerator();
+                pGen.Init(512, 80, rand);
+
+                g.Init(new DsaKeyGenerationParameters(rand, pGen.GenerateParameters()));
+            }
+
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            AsymmetricKeyParameter sKey = p.Private;
+            AsymmetricKeyParameter vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("DSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("DSA verification failed");
+            }
+
+
+
+            //
+            // ECDSA Fp generation test
+            //
+            s = SignerUtilities.GetSigner("ECDSA");
+
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters ecSpec = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
+
+            g = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+            g.Init(new ECKeyGenerationParameters(ecSpec, rand));
+
+            p = g.GenerateKeyPair();
+
+            sKey = p.Private;
+            vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("ECDSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("ECDSA verification failed");
+            }
+
+            //
+            // ECDSA F2m generation test
+            //
+            s = SignerUtilities.GetSigner("ECDSA");
+
+            curve = new F2mCurve(
+                    239, // m
+                    36, // k
+                    new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                    new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ecSpec = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); // h
+
+            g = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+            g.Init(new ECKeyGenerationParameters(ecSpec, rand));
+
+            p = g.GenerateKeyPair();
+
+            sKey = p.Private;
+            vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("ECDSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("ECDSA verification failed");
+            }
+        }
+
+        [Test]
+        public void TestParameters()
+        {
+//			AlgorithmParameterGenerator a = AlgorithmParameterGenerator.GetInstance("DSA");
+//			a.init(512, random);
+            DsaParametersGenerator a = new DsaParametersGenerator();
+            a.Init(512, 20, random);
+
+//			AlgorithmParameters parameters = a.generateParameters();
+            DsaParameters p = a.GenerateParameters();
+
+//			byte[] encodeParams = parameters.GetEncoded();
+            byte[] encodeParams = new DsaParameter(p.P, p.Q, p.G).GetDerEncoded();
+
+//			AlgorithmParameters a2 = AlgorithmParameters.GetInstance("DSA");
+//			a2.init(encodeParams);
+            DsaParameter dsaP = DsaParameter.GetInstance(Asn1Object.FromByteArray(encodeParams));
+            DsaParameters p2 = new DsaParameters(dsaP.P, dsaP.Q, dsaP.G);
+
+            // a and a2 should be equivalent!
+//			byte[] encodeParams_2 = a2.GetEncoded();
+            byte[] encodeParams_2 = new DsaParameter(p2.P, p2.Q, p2.G).GetDerEncoded();
+
+            if (!AreEqual(encodeParams, encodeParams_2))
+            {
+                Fail("encode/Decode parameters failed");
+            }
+
+//			DSAParameterSpec dsaP = (DSAParameterSpec)parameters.getParameterSpec(typeof(DSAParameterSpec));
+
+//			KeyPairGenerator g = KeyPairGenerator.GetInstance("DSA");
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+//			g.initialize(dsaP, new SecureRandom());
+            g.Init(new DsaKeyGenerationParameters(new SecureRandom(), p));
+//			KeyPair p = g.generateKeyPair();
+            AsymmetricCipherKeyPair pair = g.GenerateKeyPair();
+
+//			PrivateKey sKey = p.Private;
+//			PublicKey vKey = p.Public;
+            AsymmetricKeyParameter sKey = pair.Private;
+            AsymmetricKeyParameter vKey = pair.Public;
+
+            ISigner s = SignerUtilities.GetSigner("DSA");
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("DSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("DSA verification failed");
+            }
+        }
+
+        [Test]
+        public void TestDsa2Parameters()
+        {
+            byte[] seed = Hex.Decode("4783081972865EA95D43318AB2EAF9C61A2FC7BBF1B772A09017BDF5A58F4FF0");
+
+            //AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("DSA", "BC");
+            //a.init(2048, new DSATestSecureRandom(seed));
+            DsaParametersGenerator a = new DsaParametersGenerator(new Sha256Digest());
+            a.Init(new DsaParameterGenerationParameters(2048, 256, 80, new DsaTestSecureRandom(seed)));
+
+            //AlgorithmParameters parameters = a.generateParameters();
+
+            //DSAParameterSpec dsaP = (DSAParameterSpec)parameters.getParameterSpec(DSAParameterSpec.class);
+            DsaParameters dsaP = a.GenerateParameters();
+
+            if (!dsaP.Q.Equals(new BigInteger("C24ED361870B61E0D367F008F99F8A1F75525889C89DB1B673C45AF5867CB467", 16)))
+            {
+                Fail("Q incorrect");
+            }
+
+            if (!dsaP.P.Equals(new BigInteger(
+                "F56C2A7D366E3EBDEAA1891FD2A0D099" +
+                "436438A673FED4D75F594959CFFEBCA7BE0FC72E4FE67D91" +
+                "D801CBA0693AC4ED9E411B41D19E2FD1699C4390AD27D94C" +
+                "69C0B143F1DC88932CFE2310C886412047BD9B1C7A67F8A2" +
+                "5909132627F51A0C866877E672E555342BDF9355347DBD43" +
+                "B47156B2C20BAD9D2B071BC2FDCF9757F75C168C5D9FC431" +
+                "31BE162A0756D1BDEC2CA0EB0E3B018A8B38D3EF2487782A" +
+                "EB9FBF99D8B30499C55E4F61E5C7DCEE2A2BB55BD7F75FCD" +
+                "F00E48F2E8356BDB59D86114028F67B8E07B127744778AFF" +
+                "1CF1399A4D679D92FDE7D941C5C85C5D7BFF91BA69F9489D" +
+                "531D1EBFA727CFDA651390F8021719FA9F7216CEB177BD75", 16)))
+            {
+                Fail("P incorrect");
+            }
+
+            if (!dsaP.G.Equals(new BigInteger(
+                "8DC6CC814CAE4A1C05A3E186A6FE27EA" +
+                "BA8CDB133FDCE14A963A92E809790CBA096EAA26140550C1" +
+                "29FA2B98C16E84236AA33BF919CD6F587E048C52666576DB" +
+                "6E925C6CBE9B9EC5C16020F9A44C9F1C8F7A8E611C1F6EC2" +
+                "513EA6AA0B8D0F72FED73CA37DF240DB57BBB27431D61869" +
+                "7B9E771B0B301D5DF05955425061A30DC6D33BB6D2A32BD0" +
+                "A75A0A71D2184F506372ABF84A56AEEEA8EB693BF29A6403" +
+                "45FA1298A16E85421B2208D00068A5A42915F82CF0B858C8" +
+                "FA39D43D704B6927E0B2F916304E86FB6A1B487F07D8139E" +
+                "428BB096C6D67A76EC0B8D4EF274B8A2CF556D279AD267CC" +
+                "EF5AF477AFED029F485B5597739F5D0240F67C2D948A6279", 16)))
+            {
+                Fail("G incorrect");
+            }
+
+            //KeyPairGenerator    g = KeyPairGenerator.getInstance("DSA", "BC");
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("DSA");
+            //g.initialize(dsaP, FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")));
+            g.Init(new DsaKeyGenerationParameters(FixedSecureRandom.From(Hex.Decode("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C")), dsaP));
+            //KeyPair p = g.generateKeyPair();
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            //DSAPrivateKey  sKey = (DSAPrivateKey)p.getPrivate();
+            //DSAPublicKey   vKey = (DSAPublicKey)p.getPublic();
+            DsaPrivateKeyParameters sKey = (DsaPrivateKeyParameters)p.Private;
+            DsaPublicKeyParameters vKey = (DsaPublicKeyParameters)p.Public;
+
+            if (!vKey.Y.Equals(new BigInteger(
+                "2828003D7C747199143C370FDD07A286" +
+                "1524514ACC57F63F80C38C2087C6B795B62DE1C224BF8D1D" +
+                "1424E60CE3F5AE3F76C754A2464AF292286D873A7A30B7EA" +
+                "CBBC75AAFDE7191D9157598CDB0B60E0C5AA3F6EBE425500" +
+                "C611957DBF5ED35490714A42811FDCDEB19AF2AB30BEADFF" +
+                "2907931CEE7F3B55532CFFAEB371F84F01347630EB227A41" +
+                "9B1F3F558BC8A509D64A765D8987D493B007C4412C297CAF" +
+                "41566E26FAEE475137EC781A0DC088A26C8804A98C23140E" +
+                "7C936281864B99571EE95C416AA38CEEBB41FDBFF1EB1D1D" +
+                "C97B63CE1355257627C8B0FD840DDB20ED35BE92F08C49AE" +
+                "A5613957D7E5C7A6D5A5834B4CB069E0831753ECF65BA02B", 16)))
+            {
+                Fail("Y value incorrect");
+            }
+
+            if (!sKey.X.Equals(
+                new BigInteger("0CAF2EF547EC49C4F3A6FE6DF4223A174D01F2C115D49A6F73437C29A2A8458C", 16)))
+            {
+                Fail("X value incorrect");
+            }
+
+            //byte[] encodeParams = parameters.getEncoded();
+            byte[] encodeParams = new DsaParameter(dsaP.P, dsaP.Q, dsaP.G).GetDerEncoded();
+
+            //AlgorithmParameters a2 = AlgorithmParameters.getInstance("DSA", "BC");
+            //a2.init(encodeParams);
+            DsaParameter dsaP2 = DsaParameter.GetInstance(Asn1Object.FromByteArray(encodeParams));
+            DsaParameters p2 = new DsaParameters(dsaP.P, dsaP.Q, dsaP.G);
+
+            // a and a2 should be equivalent!
+            //byte[] encodeParams_2 = a2.GetEncoded();
+            byte[] encodeParams_2 = new DsaParameter(p2.P, p2.Q, p2.G).GetDerEncoded();
+
+            if (!AreEqual(encodeParams, encodeParams_2))
+            {
+                Fail("encode/decode parameters failed");
+            }
+
+            ISigner s = SignerUtilities.GetSigner("DSA");
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("DSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("DSA verification failed");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            // TODO
+//			TestCompat();
+            TestNONEwithDSA();
+            TestECDsa239BitPrime();
+            TestECDsa239BitBinary();
+            TestECDsa239BitBinaryRipeMD160();
+            TestECDsa239BitBinarySha1();
+            TestECDsa239BitBinarySha224();
+            TestECDsa239BitBinarySha256();
+            TestECDsa239BitBinarySha384();
+            TestECDsa239BitBinarySha512();
+
+            TestGeneration();
+            TestParameters();
+            TestDsa2Parameters();
+        }
+
+        protected BigInteger[] DerDecode(
+            byte[] encoding)
+        {
+            Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+            return new BigInteger[]
+            {
+                ((DerInteger)s[0]).Value,
+                ((DerInteger)s[1]).Value
+            };
+        }
+
+        public override string Name
+        {
+            get { return "DSA/ECDSA"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DsaTest());
+        }
+
+        private class DsaTestSecureRandom
+            : FixedSecureRandom
+        {
+            private bool first = true;
+
+            public DsaTestSecureRandom(byte[] value)
+                : base(Arrays.Clone(value))
+            {
+            }
+
+            public override void NextBytes(byte[] bytes)
+            {
+                if (first)
+                {
+                    base.NextBytes(bytes);
+                    first = false;
+                }
+                else
+                {
+                    bytes[bytes.Length - 1] = 2;
+                }
+            }
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/DigestTest.cs b/BouncyCastle.AxCrypt/test/src/test/DigestTest.cs
new file mode 100644
index 0000000..5d840ee
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/DigestTest.cs
@@ -0,0 +1,175 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class DigestTest
+        : SimpleTest
+    {
+        private static string[,] abcVectors =
+        {
+            { "MD2", "da853b0d3f88d99b30283a69e6ded6bb" },
+            { "MD4", "a448017aaf21d8525fc10ae87aa6729d" },
+            { "MD5", "900150983cd24fb0d6963f7d28e17f72"},
+            { "SHA-1", "a9993e364706816aba3e25717850c26c9cd0d89d" },
+            { "SHA-224", "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7" },
+            { "SHA-256", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" },
+            { "SHA-384", "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7" },
+            { "SHA-512", "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f" },
+            { "SHA-512/224", "4634270F707B6A54DAAE7530460842E20E37ED265CEEE9A43E8924AA" },
+            { "SHA-512/256", "53048E2681941EF99B2E29B76B4C7DABE4C2D0C634FC6D46E0E2F13107E7AF23" },
+            { "RIPEMD128", "c14a12199c66e4ba84636b0f69144c77" },
+            { "RIPEMD160", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc" },
+            { "RIPEMD256", "afbd6e228b9d8cbbcef5ca2d03e6dba10ac0bc7dcbe4680e1e42d2e975459b65" },
+            { "RIPEMD320", "de4c01b3054f8930a79d09ae738e92301e5a17085beffdc1b8d116713e74f82fa942d64cdbc4682d" },
+            { "Tiger", "2AAB1484E8C158F2BFB8C5FF41B57A525129131C957B5F93" },
+            { "GOST3411", "b285056dbf18d7392d7677369524dd14747459ed8143997e163b2986f92fd42c" },
+            { "WHIRLPOOL", "4E2448A4C6F486BB16B6562C73B4020BF3043E3A731BCE721AE1B303D97E6D4C7181EEBDB6C57E277D0E34957114CBD6C797FC9D95D8B582D225292076D4EEF5" }
+        };
+
+        public override string Name
+        {
+            get { return "Digest"; }
+        }
+
+        void doTest(
+            string algorithm)
+        {
+            byte[] message = Encoding.ASCII.GetBytes("hello world");
+
+            IDigest digest = DigestUtilities.GetDigest(algorithm);
+
+//			byte[] result = digest.digest(message);
+            digest.BlockUpdate(message, 0, message.Length);
+            byte[] result = DigestUtilities.DoFinal(digest);
+
+//			byte[] result2 = digest.digest(message);
+            digest.BlockUpdate(message, 0, message.Length);
+            byte[] result2 = DigestUtilities.DoFinal(digest);
+
+            // test one digest the same message with the same instance
+            if (!AreEqual(result, result2))
+            {
+                Fail("Result object 1 not equal");
+            }
+
+            // test two, single byte updates
+            for (int i = 0; i < message.Length; i++)
+            {
+                digest.Update(message[i]);
+            }
+//			result2 = digest.digest();
+            result2 = DigestUtilities.DoFinal(digest);
+
+            if (!AreEqual(result, result2))
+            {
+                Fail("Result object 2 not equal");
+            }
+
+            // test three, two half updates
+            digest.BlockUpdate(message, 0, message.Length/2);
+            digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2);
+//			result2 = digest.digest();
+            result2 = DigestUtilities.DoFinal(digest);
+
+            if (!AreEqual(result, result2))
+            {
+                Fail("Result object 3 not equal");
+            }
+
+            // TODO Should we support Clone'ing of digests?
+//			// test four, clone test
+//			digest.BlockUpdate(message, 0, message.Length/2);
+//			IDigest d = (IDigest)digest.Clone();
+//			digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2);
+////			result2 = digest.digest();
+//			result2 = new byte[digest.GetDigestSize()];
+//			digest.DoFinal(result2, 0);
+//
+//			if (!AreEqual(result, result2))
+//			{
+//				Fail("Result object 4(a) not equal");
+//			}
+//
+//			d.BlockUpdate(message, message.Length/2, message.Length-message.Length/2);
+////			result2 = d.digest();
+//			result2 = new byte[d.GetDigestSize()];
+//			d.DoFinal(result2, 0);
+//
+//			if (!AreEqual(result, result2))
+//			{
+//				Fail("Result object 4(b) not equal");
+//			}
+
+            // test five, check reset() method
+            digest.BlockUpdate(message, 0, message.Length/2);
+            digest.Reset();
+            digest.BlockUpdate(message, 0, message.Length/2);
+            digest.BlockUpdate(message, message.Length/2, message.Length-message.Length/2);
+//			result2 = digest.digest();
+            result2 = DigestUtilities.DoFinal(digest);
+
+            if (!AreEqual(result, result2))
+            {
+                Fail("Result object 5 not equal");
+            }
+        }
+
+        /**
+         * Test the hash against a standard value for the string "abc"
+         *
+         * @param algorithm algorithm to test
+         * @param hash expected value
+         * @return the test result.
+         */
+        void doAbcTest(
+            string algorithm,
+            string hash)
+        {
+            byte[] abc = { (byte)0x61, (byte)0x62, (byte)0x63 };
+
+            IDigest digest = DigestUtilities.GetDigest(algorithm);
+
+//			byte[] result = digest.digest(abc);
+            digest.BlockUpdate(abc, 0, abc.Length);
+            byte[] result = DigestUtilities.DoFinal(digest);
+
+            if (!AreEqual(result, Hex.Decode(hash)))
+            {
+                Fail("abc result not equal for " + algorithm);
+            }
+        }
+
+        public override void PerformTest()
+        {
+            for (int i = 0; i != abcVectors.GetLength(0); i++)
+            {
+                doTest(abcVectors[i, 0]);
+
+                doAbcTest(abcVectors[i, 0], abcVectors[i, 1]);
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new DigestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/ECDSA5Test.cs b/BouncyCastle.AxCrypt/test/src/test/ECDSA5Test.cs
new file mode 100644
index 0000000..3bf746e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/ECDSA5Test.cs
@@ -0,0 +1,300 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class ECDsa5Test
+        : SimpleTest
+    {
+//		private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+//		private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+//
+//		private SecureRandom random = FixedSecureRandom.From(k1, k2);
+
+        [Test]
+        public void DecodeTest()
+        {
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldFp(new BigInteger("6277101735386680763835789423207666416083908700390324961279")), // q
+//				new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+//				new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
+            ECCurve curve = new FpCurve(
+                new BigInteger("6277101735386680763835789423207666416083908700390324961279"), // q
+                new BigInteger("fffffffffffffffffffffffffffffffefffffffffffffffc", 16), // a
+                new BigInteger("64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", 16)); // b
+
+//			ECPoint p = ECPointUtil.DecodePoint(curve, Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"));
+            ECPoint p = curve.DecodePoint(Hex.Decode("03188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"));
+
+            BigInteger x = p.XCoord.ToBigInteger(); //p.getAffineX();
+
+            if (!x.Equals(new BigInteger("188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", 16)))
+            {
+                Fail("x uncompressed incorrectly");
+            }
+
+            BigInteger y = p.YCoord.ToBigInteger(); //p.getAffineX();
+            if (!y.Equals(new BigInteger("7192b95ffc8da78631011ed6b24cdd573f977a11e794811", 16)))
+            {
+                Fail("y uncompressed incorrectly");
+            }
+        }
+
+        /**
+        * X9.62 - 1998,<br/>
+        * J.3.2, Page 155, ECDSA over the field Fp<br/>
+        * an example with 239 bit prime
+        */
+        [Test]
+        public void TestECDsa239BitPrime()
+        {
+            BigInteger r = new BigInteger("308636143175167811492622547300668018854959378758531778147462058306432176");
+            BigInteger s = new BigInteger("323813553209797357708078776831250505931891051755007842781978505179448783");
+
+            byte[] kData = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q
+//				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+//				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
+                BigInteger.One); //1); // h
+
+            ECPrivateKeyParameters sKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                spec);
+
+            ECPublicKeyParameters vKey = new ECPublicKeyParameters(
+                "ECDSA",
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+//			KeyFactory f = KeyFactory.getInstance("ECDSA");
+//			AsymmetricKeyParameter sKey = f.generatePrivate(priKey);
+//			AsymmetricKeyParameter vKey = f.generatePublic(pubKey);
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("239 Bit EC verification failed");
+            }
+
+            BigInteger[] sig = derDecode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+        }
+
+        /**
+        * X9.62 - 1998,<br/>
+        * J.2.1, Page 100, ECDSA over the field F2m<br/>
+        * an example with 191 bit binary field
+        */
+        [Test]
+        public void TestECDsa239BitBinary()
+        {
+            BigInteger r = new BigInteger("21596333210419611985018340039034612628818151486841789642455876922391552");
+            BigInteger s = new BigInteger("197030374000731686738334997654997227052849804072198819102649413465737174");
+        
+            byte[] kData = new BigInteger("171278725565216523967285789236956265265265235675811949404040041670216363").ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldF2m(239, // m
+//							new int[] { 36 }), // k
+//				new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+//				new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+            ECCurve curve = new F2mCurve(
+                239, // m
+                36, // k
+                new BigInteger("32010857077C5431123A46B808906756F543423E8D27877578125778AC76", 16), // a
+                new BigInteger("790408F2EEDAF392B012EDEFB3392F30F4327C0CA3F31FC383C422AA8C16", 16)); // b
+
+            ECDomainParameters parameters = new ECDomainParameters(
+                curve,
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                curve.DecodePoint(Hex.Decode("0457927098FA932E7C0A96D3FD5B706EF7E5F5C156E16B7E7C86038552E91D61D8EE5077C33FECF6F1A16B268DE469C3C7744EA9A971649FC7A9616305")), // G
+                new BigInteger("220855883097298041197912187592864814557886993776713230936715041207411783"), // n
+                BigInteger.ValueOf(4)); //4); // h
+
+            ECPrivateKeyParameters sKey = new ECPrivateKeyParameters(
+                "ECDSA",
+                new BigInteger("145642755521911534651321230007534120304391871461646461466464667494947990"), // d
+                parameters);
+
+            ECPublicKeyParameters vKey = new ECPublicKeyParameters(
+                "ECDSA",
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                curve.DecodePoint(Hex.Decode("045894609CCECF9A92533F630DE713A958E96C97CCB8F5ABB5A688A238DEED6DC2D9D0C94EBFB7D526BA6A61764175B99CB6011E2047F9F067293F57F5")), // Q
+                parameters);
+
+            ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+//			KeyFactory f = KeyFactory.getInstance("ECDSA");
+//			AsymmetricKeyParameter sKey = f.generatePrivate(priKeySpec);
+//			AsymmetricKeyParameter vKey = f.generatePublic(pubKeySpec);
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("239 Bit EC verification failed");
+            }
+
+            BigInteger[] sig = derDecode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail("r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail("s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+        }
+
+        [Test]
+        public void TestGeneration()
+        {
+            //
+            // ECDSA generation test
+            //
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+            ISigner s = SignerUtilities.GetSigner("ECDSA");
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q
+//				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+//				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters ecSpec = new ECDomainParameters(
+                curve,
+//				ECPointUtil.DecodePoint(curve,
+                curve.DecodePoint(
+                    Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
+                BigInteger.One); //1); // h
+
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
+
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            AsymmetricKeyParameter sKey = p.Private;
+            AsymmetricKeyParameter vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("ECDSA");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("ECDSA verification failed");
+            }
+        }
+
+        protected BigInteger[] derDecode(
+            byte[] encoding)
+        {
+            Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+            return new BigInteger[]
+            {
+                ((DerInteger)s[0]).Value,
+                ((DerInteger)s[1]).Value
+            };
+        }
+
+        public override string Name
+        {
+            get { return "ECDSA5"; }
+        }
+
+        public override void PerformTest()
+        {
+            DecodeTest();
+            TestECDsa239BitPrime();
+            TestECDsa239BitBinary();
+            TestGeneration();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ECDsa5Test());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/ECEncodingTest.cs b/BouncyCastle.AxCrypt/test/src/test/ECEncodingTest.cs
new file mode 100644
index 0000000..f1a4d5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/ECEncodingTest.cs
@@ -0,0 +1,243 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class ECEncodingTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "ECEncodingTest"; }
+		}
+
+		/** J.4.7 An Example with m = 304 */
+		private int m = 304;
+
+		/** f = 010000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000807 */
+		private int k1 = 1;
+		private int k2 = 2;
+		private int k3 = 11;
+		private static readonly byte[] hexa = {(byte)0xFD, 0x0D, 0x69, 0x31, 0x49, (byte)0xA1, 0x18, (byte)0xF6, 0x51
+			, (byte)0xE6, (byte)0xDC, (byte)0xE6, (byte)0x80, 0x20, (byte)0x85, 0x37, 0x7E, 0x5F, (byte)0x88, 0x2D, 0x1B, 0x51
+			, 0x0B, 0x44, 0x16, 0x00, 0x74, (byte)0xC1, 0x28, (byte)0x80, 0x78, 0x36, 0x5A, 0x03
+			, (byte)0x96, (byte)0xC8, (byte)0xE6, (byte)0x81};
+		private static readonly byte[] hexb = {(byte)0xBD, (byte)0xDB, (byte)0x97, (byte)0xE5, (byte)0x55
+			, (byte)0xA5, (byte)0x0A, (byte)0x90, (byte)0x8E, (byte)0x43, (byte)0xB0
+			, (byte)0x1C, (byte)0x79, (byte)0x8E, (byte)0xA5, (byte)0xDA, (byte)0xA6
+			, (byte)0x78, (byte)0x8F, (byte)0x1E, (byte)0xA2, (byte)0x79
+			, (byte)0x4E, (byte)0xFC, (byte)0xF5, (byte)0x71, (byte)0x66, (byte)0xB8
+			, (byte)0xC1, (byte)0x40, (byte)0x39, (byte)0x60, (byte)0x1E
+			, (byte)0x55, (byte)0x82, (byte)0x73, (byte)0x40, (byte)0xBE};
+		private static readonly BigInteger a = new BigInteger(1, hexa);
+		private static readonly BigInteger b = new BigInteger(1, hexb);
+
+		/** Base point G (with point compression) */
+		private byte[] enc = {0x02, 0x19, 0x7B, 0x07, (byte)0x84, 0x5E, (byte)0x9B, (byte)0xE2, (byte)0xD9, 0x6A, (byte)0xDB, 0x0F
+				, 0x5F, 0x3C, 0x7F, 0x2C, (byte)0xFF, (byte)0xBD, 0x7A, 0x3E, (byte)0xB8, (byte)0xB6, (byte)0xFE, 
+				(byte)0xC3, 0x5C, 0x7F, (byte)0xD6, 0x7F, 0x26, (byte)0xDD, (byte)0xF6
+				, 0x28, 0x5A, 0x64, 0x4F, 0x74, 0x0A, 0x26, 0x14};
+
+		private void doTestPointCompression() 
+		{
+			ECCurve curve = new F2mCurve(m, k1, k2, k3, a, b);
+			curve.DecodePoint(enc);
+
+			int[] ks = new int[3];
+			ks[0] = k3;
+			ks[1] = k2;
+			ks[2] = k1;
+		}
+	    
+		public override void PerformTest()
+		{
+			byte[] ecParams = Hex.Decode("3081C8020101302806072A8648CE3D0101021D00D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF303C041C68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43041C2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B0439040D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD021D00D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F020101");
+			doTestParams(ecParams, true);
+
+			doTestParams(ecParams, false);
+
+			ecParams = Hex.Decode("3081C8020101302806072A8648CE3D0101021D00D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF303C041C56E6C7E4F11A7B4B961A4DCB5BD282EB22E42E9BCBE3E7B361F18012041C4BE3E7B361F18012F2353D22975E02D8D05D2C6F3342DD8F57D4C76F0439048D127A0C27E0DE207ED3B7FB98F83C8BD5A2A57C827F4B97874DEB2C1BAEB0C006958CE61BB1FC81F5389E288CB3E86E2ED91FB47B08FCCA021D00D7C134AA264366862A18302575D11A5F7AABFBA3D897FF5CA727AF53020101");
+			doTestParams(ecParams, true);
+
+			doTestParams(ecParams, false);
+
+			ecParams = Hex.Decode("30820142020101303c06072a8648ce3d0101023100fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000ffffffff3066043100fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffc043100b3312fa7e23ee7e4988e056be3f82d19181d9c6efe8141120314088f5013875ac656398d8a2ed19d2a85c8edd3ec2aef046104aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d [...]
+			doTestParams(ecParams, true);
+
+			doTestParams(ecParams, false);
+
+			doTestPointCompression();
+		}
+
+		private void doTestParams(
+			byte[]	ecParameterEncoded,
+			bool	compress)
+		{
+//			string keyStorePass = "myPass";
+			Asn1Sequence seq = (Asn1Sequence) Asn1Object.FromByteArray(ecParameterEncoded);
+			X9ECParameters x9 = new X9ECParameters(seq);
+			AsymmetricCipherKeyPair kp = null;
+			bool success = false;
+			while (!success)
+			{
+				IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+//				kpg.Init(new ECParameterSpec(x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed()));
+				ECDomainParameters ecParams = new ECDomainParameters(
+					x9.Curve, x9.G, x9.N, x9.H, x9.GetSeed());
+				kpg.Init(new ECKeyGenerationParameters(ecParams, new SecureRandom()));
+				kp = kpg.GenerateKeyPair();
+				// The very old Problem... we need a certificate chain to
+				// save a private key...
+				ECPublicKeyParameters pubKey = (ECPublicKeyParameters) kp.Public;
+
+				if (!compress)
+				{
+					//pubKey.setPointFormat("UNCOMPRESSED");
+					pubKey = SetPublicUncompressed(pubKey, false);
+				}
+
+				byte[] x = pubKey.Q.AffineXCoord.ToBigInteger().ToByteArrayUnsigned();
+				byte[] y = pubKey.Q.AffineYCoord.ToBigInteger().ToByteArrayUnsigned();
+				if (x.Length == y.Length)
+				{
+					success = true;
+				}
+			}
+
+			// The very old Problem... we need a certificate chain to
+			// save a private key...
+
+			X509CertificateEntry[] chain = new X509CertificateEntry[] {
+				new X509CertificateEntry(GenerateSelfSignedSoftECCert(kp, compress))
+			};
+
+//			KeyStore keyStore = KeyStore.getInstance("BKS");
+//			keyStore.load(null, keyStorePass.ToCharArray());
+			Pkcs12Store keyStore = new Pkcs12StoreBuilder().Build();
+
+			keyStore.SetCertificateEntry("ECCert", chain[0]);
+
+			ECPrivateKeyParameters privateECKey = (ECPrivateKeyParameters) kp.Private;
+			keyStore.SetKeyEntry("ECPrivKey", new AsymmetricKeyEntry(privateECKey), chain);
+
+			// Test ec sign / verify
+			ECPublicKeyParameters pub = (ECPublicKeyParameters) kp.Public;
+//			string oldPrivateKey = new string(Hex.encode(privateECKey.getEncoded()));
+			byte[] oldPrivateKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(privateECKey).GetDerEncoded();
+			string oldPrivateKey = Hex.ToHexString(oldPrivateKeyBytes);
+//			string oldPublicKey = new string(Hex.encode(pub.getEncoded()));
+			byte[] oldPublicKeyBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(pub).GetDerEncoded();
+			string oldPublicKey = Hex.ToHexString(oldPublicKeyBytes);
+			ECPrivateKeyParameters newKey = (ECPrivateKeyParameters)
+				keyStore.GetKey("ECPrivKey").Key;
+			ECPublicKeyParameters newPubKey = (ECPublicKeyParameters)
+				keyStore.GetCertificate("ECCert").Certificate.GetPublicKey();
+
+			if (!compress)
+			{
+				// TODO Private key compression?
+				//newKey.setPointFormat("UNCOMPRESSED");
+				//newPubKey.setPointFormat("UNCOMPRESSED");
+				newPubKey = SetPublicUncompressed(newPubKey, false);
+			}
+
+//			string newPrivateKey = new string(Hex.encode(newKey.getEncoded()));
+			byte[] newPrivateKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(newKey).GetDerEncoded();
+			string newPrivateKey = Hex.ToHexString(newPrivateKeyBytes);
+//			string newPublicKey = new string(Hex.encode(newPubKey.getEncoded()));
+			byte[] newPublicKeyBytes = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(newPubKey).GetDerEncoded();
+			string newPublicKey = Hex.ToHexString(newPublicKeyBytes);
+
+			if (!oldPrivateKey.Equals(newPrivateKey))
+//			if (!privateECKey.Equals(newKey))
+			{
+				Fail("failed private key comparison");
+			}
+
+			if (!oldPublicKey.Equals(newPublicKey))
+//			if (!pub.Equals(newPubKey))
+			{
+				Fail("failed public key comparison");
+			}
+		}
+
+		/**
+		* Create a self signed cert for our software emulation
+		* 
+		* @param kp
+		*            is the keypair for our certificate
+		* @return a self signed cert for our software emulation
+		* @throws InvalidKeyException
+		*             on error
+		* @throws SignatureException
+		*             on error
+		*/
+		private X509Certificate GenerateSelfSignedSoftECCert(
+			AsymmetricCipherKeyPair	kp,
+			bool					compress)
+		{
+			X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+			ECPrivateKeyParameters privECKey = (ECPrivateKeyParameters) kp.Private;
+			ECPublicKeyParameters pubECKey = (ECPublicKeyParameters) kp.Public;
+
+			if (!compress)
+			{
+				// TODO Private key compression?
+				//privECKey.setPointFormat("UNCOMPRESSED");
+				//pubECKey.setPointFormat("UNCOMPRESSED");
+				pubECKey = SetPublicUncompressed(pubECKey, false);
+			}
+
+			certGen.SetSignatureAlgorithm("ECDSAwithSHA1");
+			certGen.SetSerialNumber(BigInteger.One);
+			certGen.SetIssuerDN(new X509Name("CN=Software emul (EC Cert)"));
+			certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50000));
+			certGen.SetSubjectDN(new X509Name("CN=Software emul (EC Cert)"));
+			certGen.SetPublicKey(pubECKey);
+
+			return certGen.Generate(privECKey);
+		}
+
+		private ECPublicKeyParameters SetPublicUncompressed(
+			ECPublicKeyParameters	key,
+			bool					withCompression)
+		{
+			ECPoint p = key.Q.Normalize();
+			return new ECPublicKeyParameters(
+				key.AlgorithmName,
+				p.Curve.CreatePoint(p.XCoord.ToBigInteger(), p.YCoord.ToBigInteger(), withCompression),
+				key.Parameters);
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ECEncodingTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/ECNRTest.cs b/BouncyCastle.AxCrypt/test/src/test/ECNRTest.cs
new file mode 100644
index 0000000..8a24443
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/ECNRTest.cs
@@ -0,0 +1,204 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class ECNRTest
+        : SimpleTest
+    {
+        private static readonly byte[] k1 = Hex.Decode("d5014e4b60ef2ba8b6211b4062ba3224e0427dd3");
+        private static readonly byte[] k2 = Hex.Decode("345e8d05c075c3a508df729a1685690e68fcfb8c8117847e89063bca1f85d968fd281540b6e13bd1af989a1fbf17e06462bf511f9d0b140fb48ac1b1baa5bded");
+
+        private readonly SecureRandom random = FixedSecureRandom.From(k1, k2);
+
+        /**
+         * X9.62 - 1998,<br/>
+         * J.3.2, Page 155, ECDSA over the field Fp<br/>
+         * an example with 239 bit prime
+         */
+        [Test]
+        public void TestECNR239bitPrime()
+        {
+            BigInteger r = new BigInteger("308636143175167811492623515537541734843573549327605293463169625072911693");
+            BigInteger s = new BigInteger("852401710738814635664888632022555967400445256405412579597015412971797143");
+
+            byte[] kData = new BigInteger("700000017569056646655505781757157107570501575775705779575555657156756655").ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            X9ECParameters p = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime239v1);
+            ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECCurve curve = spec.Curve;
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("876300101507107567501066130761671078357010671067781776716671676178726717"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                curve.DecodePoint(Hex.Decode("025b6dc53bc61a2548ffb0f671472de6c9521a9d2d2534e65abfcbd5fe0c70")), // Q
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR");
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            checkSignature(239, priKey, pubKey, sgr, k, message, r, s);
+        }
+
+        // -------------------------------------------------------------------------
+
+        /**
+         * X9.62 - 1998,<br/>
+         * Page 104-105, ECDSA over the field Fp<br/>
+         * an example with 192 bit prime
+         */
+        [Test]
+        public void TestECNR192bitPrime()
+        {
+            BigInteger r  = new BigInteger("2474388605162950674935076940284692598330235697454145648371");
+            BigInteger s  = new BigInteger("2997192822503471356158280167065034437828486078932532073836");
+
+            byte[] kData = new BigInteger("dcc5d1f1020906df2782360d36b2de7a17ece37d503784af", 16).ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            X9ECParameters p = X962NamedCurves.GetByOid(X9ObjectIdentifiers.Prime192v1);
+            ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECCurve curve = spec.Curve;
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("651056770906015076056810763456358567190100156695615665659"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                curve.DecodePoint(Hex.Decode("0262B12D60690CDCF330BABAB6E69763B471F994DD702D16A5")), // Q
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("SHA1withECNR");
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            checkSignature(192, priKey, pubKey, sgr, k, message, r, s);
+        }
+
+        // -------------------------------------------------------------------------
+
+        /**
+         * SEC 2: Recommended Elliptic Curve Domain Parameters - September 2000,<br/>
+         * Page 17-19, Recommended 521-bit Elliptic Curve Domain Parameters over Fp<br/>
+         * an ECC example with a 521 bit prime and a 512 bit hash
+         */
+        [Test]
+        public void TestECNR521bitPrime()
+        {
+            BigInteger r  = new BigInteger("1820641608112320695747745915744708800944302281118541146383656165330049339564439316345159057453301092391897040509935100825960342573871340486684575368150970954");
+            BigInteger s  = new BigInteger("6358277176448326821136601602749690343031826490505780896013143436153111780706227024847359990383467115737705919410755190867632280059161174165591324242446800763");
+
+            byte[] kData = new BigInteger("cdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", 16).ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            X9ECParameters p = SecNamedCurves.GetByOid(SecObjectIdentifiers.SecP521r1);
+            ECDomainParameters spec = new ECDomainParameters(p.Curve, p.G, p.N, p.H);
+            ECCurve curve = spec.Curve;
+
+            ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(
+                new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+                curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("SHA512withECNR");
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            checkSignature(521, priKey, pubKey, sgr, k, message, r, s);
+        }
+
+        private void checkSignature(
+            int						size,
+            ECPrivateKeyParameters	sKey,
+            ECPublicKeyParameters	vKey,
+            ISigner					sgr,
+            SecureRandom			k,
+            byte[]					message,
+            BigInteger				r,
+            BigInteger				s)
+        {
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail(size + " bit EC verification failed");
+            }
+
+            BigInteger[] sig = derDecode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail(size + "bit"
+                    + ": r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail(size + "bit"
+                    + ": s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+        }
+
+        protected BigInteger[] derDecode(
+            byte[] encoding)
+        {
+            Asn1Sequence s = (Asn1Sequence) Asn1Object.FromByteArray(encoding);
+
+            return new BigInteger[]
+            {
+                ((DerInteger)s[0]).Value,
+                ((DerInteger)s[1]).Value
+            };
+        }
+
+        public override string Name
+        {
+            get { return "ECNR"; }
+        }
+
+        public override void PerformTest()
+        {
+            TestECNR192bitPrime();
+            TestECNR239bitPrime();
+            TestECNR521bitPrime();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new ECNRTest());
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/ElGamalTest.cs b/BouncyCastle.AxCrypt/test/src/test/ElGamalTest.cs
new file mode 100644
index 0000000..9a87ea9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/ElGamalTest.cs
@@ -0,0 +1,334 @@
+using System;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class ElGamalTest
+		: SimpleTest
+	{
+		private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+		private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+		private static readonly BigInteger g768 = new BigInteger("7c240073c1316c621df461b71ebb0cdcc90a6e5527e5e126633d131f87461c4dc4afc60c2cb0f053b6758871489a69613e2a8b4c8acde23954c08c81cbd36132cfd64d69e4ed9f8e51ed6e516297206672d5c0a69135df0a5dcf010d289a9ca1", 16);
+		private static readonly BigInteger p768 = new BigInteger("8c9dd223debed1b80103b8b309715be009d48860ed5ae9b9d5d8159508efd802e3ad4501a7f7e1cfec78844489148cd72da24b21eddd01aa624291c48393e277cfc529e37075eccef957f3616f962d15b44aeab4039d01b817fde9eaa12fd73f", 16);
+
+		private static readonly BigInteger g1024 = new BigInteger("1db17639cdf96bc4eabba19454f0b7e5bd4e14862889a725c96eb61048dcd676ceb303d586e30f060dbafd8a571a39c4d823982117da5cc4e0f89c77388b7a08896362429b94a18a327604eb7ff227bffbc83459ade299e57b5f77b50fb045250934938efa145511166e3197373e1b5b1e52de713eb49792bedde722c6717abf", 16);
+		private static readonly BigInteger p1024 = new BigInteger("a00e283b3c624e5b2b4d9fbc2653b5185d99499b00fd1bf244c6f0bb817b4d1c451b2958d62a0f8a38caef059fb5ecd25d75ed9af403f5b5bdab97a642902f824e3c13789fed95fa106ddfe0ff4a707c85e2eb77d49e68f2808bcea18ce128b178cd287c6bc00efa9a1ad2a673fe0dceace53166f75b81d6709d5f8af7c66bb7", 16);
+
+		public override string Name
+		{
+			get { return "ElGamal"; }
+		}
+
+		[Test]
+		public void TestGP512()
+		{
+			doTestGP(512, 0, g512, p512);
+			doTestGP(512, 64, g512, p512);
+		}
+
+		[Test]
+		public void TestGP768()
+		{
+			doTestGP(768, 0, g768, p768);
+			doTestGP(768, 128, g768, p768);
+		}
+
+		[Test]
+		public void TestGP1024()
+		{
+			doTestGP(1024, 0, g1024, p1024);
+			doTestGP(1024, 256, g1024, p1024);
+		}
+
+		[Test]
+		public void TestRandom256()
+		{
+			doTestRandom(256);
+		}
+
+		private void doTestGP(
+			int			size,
+			int         privateValueSize,
+			BigInteger	g,
+			BigInteger	p)
+		{
+			IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("ElGamal");
+
+//			DHParameterSpec elParams = new DHParameterSpec(p, g);
+//			keyGen.initialize(elParams);
+			ElGamalParameters elParams = new ElGamalParameters(p, g, privateValueSize);
+			ElGamalKeyGenerationParameters elKgp = new ElGamalKeyGenerationParameters(
+				new SecureRandom(), elParams);
+			keyGen.Init(elKgp);
+
+			AsymmetricCipherKeyPair keyPair = keyGen.GenerateKeyPair();
+			SecureRandom rand = new SecureRandom();
+
+			checkKeySize(privateValueSize, keyPair);
+
+			IBufferedCipher cipher = CipherUtilities.GetCipher("ElGamal");
+
+			cipher.Init(true, new ParametersWithRandom(keyPair.Public, rand));
+
+			byte[] inBytes = Encoding.ASCII.GetBytes("This is a test");
+
+			if (cipher.GetOutputSize(inBytes.Length) != (size / 8) * 2)
+			{
+				Fail("getOutputSize wrong on encryption");
+			}
+
+			byte[] outBytes = cipher.DoFinal(inBytes);
+
+			cipher.Init(false, keyPair.Private);
+
+			if (cipher.GetOutputSize(outBytes.Length) != (size / 8) - 1)
+			{
+				Fail("GetOutputSize wrong on decryption");
+			}
+
+
+			//
+			// No Padding - maximum length
+			//
+			byte[] modBytes = ((ElGamalPublicKeyParameters)keyPair.Public).Parameters.P.ToByteArray();
+			byte[] maxInput = new byte[modBytes.Length - 1];
+
+			maxInput[0] |= 0x7f;
+
+			cipher.Init(true, new ParametersWithRandom(keyPair.Public, rand));
+
+			outBytes = cipher.DoFinal(maxInput);
+
+			cipher.Init(false, keyPair.Private);
+
+			outBytes = cipher.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, maxInput))
+			{
+				Fail("NoPadding test failed on decrypt expected "
+					+ Hex.ToHexString(maxInput) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+
+			//
+			// encrypt/decrypt
+			//
+			IBufferedCipher c1 = CipherUtilities.GetCipher("ElGamal");
+			IBufferedCipher c2 = CipherUtilities.GetCipher("ElGamal");
+
+			c1.Init(true, new ParametersWithRandom(keyPair.Public, rand));
+
+			byte[] out1 = c1.DoFinal(inBytes);
+
+			c2.Init(false, keyPair.Private);
+
+			byte[] out2 = c2.DoFinal(out1);
+
+			if (!AreEqual(inBytes, out2))
+			{
+				Fail(size + " encrypt test failed");
+			}
+
+
+			//
+			// encrypt/decrypt with update
+			//
+			int outLen = c1.ProcessBytes(inBytes, 0, 2, out1, 0);
+
+			outLen += c1.DoFinal(inBytes, 2, inBytes.Length - 2, out1, outLen);
+
+			outLen = c2.ProcessBytes(out1, 0, 2, out2, 0);
+
+			outLen += c2.DoFinal(out1, 2, out1.Length - 2, out2, outLen);
+
+			if (!AreEqual(inBytes, out2))
+			{
+				Fail(size + " encrypt with update test failed");
+			}
+
+
+
+			//
+			// public key encoding test
+			//
+//			byte[] pubEnc = keyPair.Public.GetEncoded();
+			byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(keyPair.Public).GetDerEncoded();
+
+//			KeyFactory keyFac = KeyFactory.GetInstance("ElGamal");
+//			X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(pubEnc);
+//			DHPublicKeyParameters pubKey = (DHPublicKeyParameters)keyFac.generatePublic(pubX509);
+			ElGamalPublicKeyParameters pubKey = (ElGamalPublicKeyParameters)
+				PublicKeyFactory.CreateKey(pubEnc);
+			ElGamalParameters spec = pubKey.Parameters;
+
+			if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P))
+			{
+				Fail(size + " bit public key encoding/decoding test failed on parameters");
+			}
+
+			if (!((ElGamalPublicKeyParameters)keyPair.Public).Y.Equals(pubKey.Y))
+			{
+				Fail(size + " bit public key encoding/decoding test failed on y value");
+			}
+
+/*
+			//
+			// public key serialisation test
+			//
+			// TODO Is there some standard this serialization must conform to?
+			BinaryFormatter formatter = new BinaryFormatter();
+
+			MemoryStream bOut = new MemoryStream();
+//			ObjectOutputStream oOut = new ObjectOutputStream(bOut);
+//			oOut.writeObject(keyPair.Public);
+			formatter.Serialize(bOut, keyPair.Public);
+
+			MemoryStream bIn = new MemoryStream(bOut.ToArray(), false);
+//			ObjectInputStream oIn = new ObjectInputStream(bIn);
+//			pubKey = (DHPublicKeyParameters)oIn.readObject();
+			pubKey = (ElGamalPublicKeyParameters) formatter.Deserialize(bIn);
+			spec = pubKey.Parameters;
+
+			if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P))
+			{
+				Fail(size + " bit public key serialisation test failed on parameters");
+			}
+
+			if (!((ElGamalPublicKeyParameters )keyPair.Public).Y.Equals(pubKey.Y))
+			{
+				Fail(size + " bit public key serialisation test failed on y value");
+			}
+*/
+
+			//
+			// private key encoding test
+			//
+			// TODO Keys don't support GetEncoded
+//			byte[] privEnc = keyPair.Private.GetEncoded();
+			byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(keyPair.Private).GetDerEncoded();
+
+//			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+//			DHPrivateKeyParameters privKey = (DHPrivateKeyParameters)keyFac.generatePrivate(privPKCS8);
+			ElGamalPrivateKeyParameters privKey = (ElGamalPrivateKeyParameters)
+				PrivateKeyFactory.CreateKey(privEnc);
+
+			spec = privKey.Parameters;
+
+			if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P))
+			{
+				Fail(size + " bit private key encoding/decoding test failed on parameters");
+			}
+
+			if (!((ElGamalPrivateKeyParameters)keyPair.Private).X.Equals(privKey.X))
+			{
+				Fail(size + " bit private key encoding/decoding test failed on y value");
+			}
+
+/*
+			//
+			// private key serialisation test
+			//
+			bOut = new MemoryStream();
+//			oOut = new ObjectOutputStream(bOut);
+//			oOut.writeObject(keyPair.Private);
+			formatter.Serialize(bOut, keyPair.Private);
+
+			bIn = new MemoryStream(bOut.ToArray(), false);
+//			oIn = new ObjectInputStream(bIn);
+//			privKey = (DHPrivateKeyParameters)oIn.readObject();
+			privKey = (ElGamalPrivateKeyParameters) formatter.Deserialize(bIn);
+			spec = privKey.Parameters;
+
+			if (!spec.G.Equals(elParams.G) || !spec.P.Equals(elParams.P))
+			{
+				Fail(size + " bit private key serialisation test failed on parameters");
+			}
+
+			if (!((ElGamalPrivateKeyParameters) keyPair.Private).X.Equals(privKey.X))
+			{
+				Fail(size + " bit private key serialisation test failed on y value");
+			}
+*/
+		}
+
+		private void checkKeySize(int privateValueSize, AsymmetricCipherKeyPair aKeyPair)
+		{
+			if (privateValueSize != 0)
+			{
+//				DHPrivateKey key = (DHPrivateKey)aKeyPair.getPrivate();
+				ElGamalPrivateKeyParameters key = (ElGamalPrivateKeyParameters) aKeyPair.Private;
+
+				if (key.X.BitLength != privateValueSize)
+				{
+					Fail("limited key check failed for key size " + privateValueSize);
+				}
+			}
+		}
+
+		private void doTestRandom(
+			int size)
+		{
+//			AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("ElGamal");
+//			a.init(size, new SecureRandom());
+			ElGamalParametersGenerator a = new ElGamalParametersGenerator();
+			a.Init(size, 20, new SecureRandom());
+
+//			AlgorithmParameters parameters = a.generateParameters();
+			ElGamalParameters p = a.GenerateParameters();
+
+//			byte[] encodeParams = parameters.GetEncoded();
+			byte[] encodeParams = new ElGamalParameter(p.P, p.G).GetDerEncoded(); 
+
+//			AlgorithmParameters a2 = AlgorithmParameters.getInstance("ElGamal");
+//			a2.init(encodeParams);
+			ElGamalParameter elP = new ElGamalParameter((Asn1Sequence) Asn1Object.FromByteArray(encodeParams));
+			ElGamalParameters p2 = new ElGamalParameters(elP.P, elP.G);
+
+			// a and a2 should be equivalent!
+//			byte[] encodeParams_2 = a2.GetEncoded();
+			byte[] encodeParams_2 = new ElGamalParameter(p2.P, p2.G).GetDerEncoded(); 
+
+			if (!AreEqual(encodeParams, encodeParams_2))
+			{
+				Fail(this.Name + ": encode/decode parameters failed");
+			}
+
+//			DHParameters elP = (DHParameters)parameters.getParameterSpec(typeof(DHParameters));
+
+			doTestGP(size, 0, elP.G, elP.P);
+		}
+
+		public override void PerformTest()
+		{
+			TestGP512();
+			TestGP768();
+			TestGP1024();
+			TestRandom256();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new ElGamalTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/EncryptedPrivateKeyInfoTest.cs b/BouncyCastle.AxCrypt/test/src/test/EncryptedPrivateKeyInfoTest.cs
new file mode 100644
index 0000000..baac5ff
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/EncryptedPrivateKeyInfoTest.cs
@@ -0,0 +1,154 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class EncryptedPrivateKeyInfoTest
+		: SimpleTest
+	{
+		private const string alg = "1.2.840.113549.1.12.1.3"; // 3 key triple DES with SHA-1
+
+		public override void PerformTest()
+		{
+			IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			fact.Init(new KeyGenerationParameters(new SecureRandom(), 512));
+
+			AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair();
+
+			AsymmetricKeyParameter priKey = keyPair.Private;
+			AsymmetricKeyParameter pubKey = keyPair.Public;
+
+			//
+			// set up the parameters
+			//
+			byte[] salt = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+			int iterationCount = 100;
+			Asn1Encodable defParams = PbeUtilities.GenerateAlgorithmParameters(alg, salt, iterationCount);
+			char[] password1 = { 'h', 'e', 'l', 'l', 'o' };
+
+//				AlgorithmParameters parameters = AlgorithmParameters.getInstance(alg);
+//
+//				parameters.init(defParams);
+
+			//
+			// set up the key
+			//
+//				PBEKeySpec pbeSpec = new PBEKeySpec(password1);
+//				SecretKeyFactory keyFact = SecretKeyFactory.getInstance(alg);
+
+//				IBufferedCipher cipher = CipherUtilities.GetCipher(alg);
+			IWrapper wrapper = WrapperUtilities.GetWrapper(alg);
+
+			ICipherParameters parameters = PbeUtilities.GenerateCipherParameters(
+				alg, password1, defParams);
+
+//				cipher.Init(IBufferedCipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), parameters);
+			wrapper.Init(true, parameters);
+
+//				byte[] wrappedKey = cipher.Wrap(priKey);
+			byte[] pkb = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey).GetDerEncoded();
+			byte[] wrappedKey = wrapper.Wrap(pkb, 0, pkb.Length);
+
+			//
+			// create encrypted object
+			//
+
+			// TODO Figure out what this was supposed to do
+//				EncryptedPrivateKeyInfo pInfo = new EncryptedPrivateKeyInfo(parameters, wrappedKey);
+			PrivateKeyInfo plain = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey);
+			EncryptedPrivateKeyInfo pInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+				alg, password1, salt, iterationCount,  plain);
+
+
+			//
+			// decryption step
+			//
+			char[] password2 = { 'h', 'e', 'l', 'l', 'o' };
+
+//				pbeSpec = new PBEKeySpec(password2);
+//
+//				cipher = CipherUtilities.GetCipher(pInfo.EncryptionAlgorithm);
+//
+//				cipher.Init(false, keyFact.generateSecret(pbeSpec), pInfo.getAlgParameters());
+//
+//				PKCS8EncodedKeySpec keySpec = pInfo.getKeySpec(cipher);
+			PrivateKeyInfo decrypted = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password2, pInfo);
+
+//				if (!MessageDigest.isEqual(priKey.GetEncoded(), keySpec.GetEncoded()))
+			if (!decrypted.Equals(plain))
+			{
+				Fail("Private key does not match");
+			}
+
+			//
+			// using ICipherParameters test
+			//
+//			pbeSpec = new PBEKeySpec(password1);
+//			keyFact = SecretKeyFactory.getInstance(alg);
+//			cipher = CipherUtilities.GetCipher(alg);
+			wrapper = WrapperUtilities.GetWrapper(alg);
+
+//			cipher.init(IBufferedCipher.WRAP_MODE, keyFact.generateSecret(pbeSpec), parameters);
+			wrapper.Init(true, parameters);
+
+//			wrappedKey = cipher.wrap(priKey);
+			wrappedKey = wrapper.Wrap(pkb, 0, pkb.Length);
+
+			//
+			// create encrypted object
+			//
+
+			// TODO Figure out what this was supposed to do
+//			pInfo = new EncryptedPrivateKeyInfo(cipher.getParameters(), wrappedKey);
+			plain = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey);
+			pInfo = EncryptedPrivateKeyInfoFactory.CreateEncryptedPrivateKeyInfo(
+				alg, password1, salt, iterationCount,  plain);
+
+			//
+			// decryption step
+			//
+//			pbeSpec = new PBEKeySpec(password2);
+//
+//			cipher = CipherUtilities.GetCipher(pInfo.getAlgName());
+//
+//			cipher.init(IBufferedCipher.DECRYPT_MODE, keyFact.generateSecret(pbeSpec), pInfo.getAlgParameters());
+//
+//			keySpec = pInfo.getKeySpec(cipher);
+			decrypted = PrivateKeyInfoFactory.CreatePrivateKeyInfo(password2, pInfo);
+
+//			if (!MessageDigest.isEqual(priKey.GetEncoded(), keySpec.GetEncoded()))
+			if (!decrypted.Equals(plain))
+			{
+				Fail("Private key does not match");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "EncryptedPrivateKeyInfoTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new EncryptedPrivateKeyInfoTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/FIPSDESTest.cs b/BouncyCastle.AxCrypt/test/src/test/FIPSDESTest.cs
new file mode 100644
index 0000000..1f40e15
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/FIPSDESTest.cs
@@ -0,0 +1,205 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>
+	/// Basic FIPS test class for a block cipher, just to make sure ECB/CBC/OFB/CFB are behaving
+	/// correctly. Tests from <a href="http://www.itl.nist.gov/fipspubs/fip81.htm">FIPS 81</a>.
+	/// </remarks>
+	[TestFixture]
+	public class FipsDesTest
+		: ITest
+	{
+		private static readonly string[] fips1Tests =
+		{
+			"DES/ECB/NoPadding",
+			"3fa40e8a984d48156a271787ab8883f9893d51ec4b563b53",
+			"DES/CBC/NoPadding",
+			"e5c7cdde872bf27c43e934008c389c0f683788499a7c05f6",
+			"DES/CFB/NoPadding",
+			"f3096249c7f46e51a69e839b1a92f78403467133898ea622"
+		};
+
+		private static readonly string[] fips2Tests =
+		{
+			"DES/CFB8/NoPadding",
+			"f31fda07011462ee187f",
+			"DES/OFB8/NoPadding",
+			"f34a2850c9c64985d684"
+		};
+
+		private static readonly byte[] input1 = Hex.Decode("4e6f77206973207468652074696d6520666f7220616c6c20");
+		private static readonly byte[] input2 = Hex.Decode("4e6f7720697320746865");
+
+		public string Name
+		{
+			get { return "FIPSDES"; }
+		}
+
+		public ITestResult doTest(
+			string	algorithm,
+			byte[]	input,
+			byte[]	output)
+		{
+			KeyParameter key;
+			IBufferedCipher inCipher, outCipher;
+			CipherStream cIn, cOut;
+			MemoryStream bIn, bOut;
+
+//			IvParameterSpec spec = new IvParameterSpec();
+			byte[] spec = Hex.Decode("1234567890abcdef");
+
+			try
+			{
+				key = new DesParameters(Hex.Decode("0123456789abcdef"));
+
+				inCipher = CipherUtilities.GetCipher(algorithm);
+				outCipher = CipherUtilities.GetCipher(algorithm);
+
+				if (algorithm.StartsWith("DES/ECB"))
+				{
+					outCipher.Init(true, key);
+				}
+				else
+				{
+					outCipher.Init(true, new ParametersWithIV(key, spec));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed initialisation - " + e.ToString(), e);
+			}
+
+			try
+			{
+				if (algorithm.StartsWith("DES/ECB"))
+				{
+					inCipher.Init(false, key);
+				}
+				else
+				{
+					inCipher.Init(false, new ParametersWithIV(key, spec));
+				}
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed initialisation - " + e.ToString(), e);
+			}
+
+			//
+			// encryption pass
+			//
+			bOut = new MemoryStream();
+			cOut = new CipherStream(bOut, null, outCipher);
+
+			try
+			{
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					cOut.WriteByte(input[i]);
+				}
+				cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+				cOut.Close();
+			}
+			catch (IOException e)
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - " + e.ToString());
+			}
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!Arrays.AreEqual(bytes, output))
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - expected "
+					+ Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			bIn = new MemoryStream(bytes, false);
+			cIn = new CipherStream(bIn, inCipher, null);
+
+			try
+			{
+				BinaryReader dIn = new BinaryReader(cIn);
+
+				bytes = new byte[input.Length];
+
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					bytes[i] = dIn.ReadByte();
+				}
+
+				int remaining = bytes.Length - input.Length / 2;
+				byte[] extra = dIn.ReadBytes(remaining);
+				if (extra.Length < remaining)
+					throw new EndOfStreamException();
+				extra.CopyTo(bytes, input.Length / 2);
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed encryption - " + e.ToString());
+			}
+
+			if (!Arrays.AreEqual(bytes, input))
+			{
+				return new SimpleTestResult(false, Name + ": " + algorithm + " failed decryption - expected "
+					+ Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes));
+			}
+
+			return new SimpleTestResult(true, Name + ": " + algorithm + " Okay");
+		}
+
+		public ITestResult Perform()
+		{
+			for (int i = 0; i != fips1Tests.Length; i += 2)
+			{
+				ITestResult result = doTest(fips1Tests[i], input1, Hex.Decode(fips1Tests[i + 1]));
+				if (!result.IsSuccessful())
+				{
+					return result;
+				}
+			}
+
+			for (int i = 0; i != fips2Tests.Length; i += 2)
+			{
+				ITestResult result = doTest(fips2Tests[i], input2, Hex.Decode(fips2Tests[i + 1]));
+				if (!result.IsSuccessful())
+				{
+					return result;
+				}
+			}
+
+			return new SimpleTestResult(true, Name + ": Okay");
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new FipsDesTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/GOST28147Test.cs b/BouncyCastle.AxCrypt/test/src/test/GOST28147Test.cs
new file mode 100644
index 0000000..0adfad3
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/GOST28147Test.cs
@@ -0,0 +1,245 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>Basic test class for the GOST28147 cipher</remarks>
+	[TestFixture]
+	public class Gost28147Test
+		: SimpleTest
+	{
+		private static string[] cipherTests =
+		{
+			"256",
+			"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+			"4e6f77206973207468652074696d6520666f7220616c6c20",
+			"281630d0d5770030068c252d841e84149ccc1912052dbc02",
+
+			"256",
+			"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
+			"4e6f77206973207468652074696d65208a920c6ed1a804f5",
+			"88e543dfc04dc4f764fa7b624741cec07de49b007bf36065"
+		};
+
+		public override string Name
+		{
+			get { return "GOST28147"; }
+		}
+
+		private void doTestEcb(
+			int		strength,
+			byte[]	keyBytes,
+			byte[]	input,
+			byte[]	output)
+		{
+			IBufferedCipher inCipher, outCipher;
+			CipherStream cIn, cOut;
+			MemoryStream bIn, bOut;
+
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("GOST28147", keyBytes);
+
+			inCipher = CipherUtilities.GetCipher("GOST28147/ECB/NoPadding");
+			outCipher = CipherUtilities.GetCipher("GOST28147/ECB/NoPadding");
+			outCipher.Init(true, key);
+			inCipher.Init(false, key);
+
+			//
+			// encryption pass
+			//
+			bOut = new MemoryStream();
+			cOut = new CipherStream(bOut, null, outCipher);
+
+			for (int i = 0; i != input.Length / 2; i++)
+			{
+				cOut.WriteByte(input[i]);
+			}
+			cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+			cOut.Close();
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("GOST28147 failed encryption - expected "
+					+ Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			bIn = new MemoryStream(bytes, false);
+			cIn = new CipherStream(bIn, inCipher, null);
+
+			BinaryReader dIn = new BinaryReader(cIn);
+
+			bytes = new byte[input.Length];
+
+			for (int i = 0; i != input.Length / 2; i++)
+			{
+				bytes[i] = dIn.ReadByte();
+			}
+
+			int remaining = bytes.Length - input.Length / 2;
+			byte[] extra = dIn.ReadBytes(remaining);
+			if (extra.Length < remaining)
+				throw new EndOfStreamException();
+			extra.CopyTo(bytes, input.Length / 2);
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("GOST28147 failed decryption - expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes));
+			}
+		}
+
+		private void doTestCfb(
+			int         strength,
+			byte[]      keyBytes,
+			byte[]      input,
+			byte[]      output)
+		{
+			IBufferedCipher inCipher, outCipher;
+			CipherStream cIn, cOut;
+			MemoryStream bIn, bOut;
+
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("GOST28147", keyBytes);
+
+			inCipher = CipherUtilities.GetCipher("GOST28147/CFB8/NoPadding");
+			outCipher = CipherUtilities.GetCipher("GOST28147/CFB8/NoPadding");
+			byte[] iv = {1,2,3,4,5,6,7,8};
+
+			outCipher.Init(true, new ParametersWithIV(key, iv));
+			inCipher.Init(false, new ParametersWithIV(key, iv));
+
+			//
+			// encryption pass
+			//
+			bOut = new MemoryStream();
+			cOut = new CipherStream(bOut, null, outCipher);
+
+			for (int i = 0; i != input.Length / 2; i++)
+			{
+				cOut.WriteByte(input[i]);
+			}
+			cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+			cOut.Close();
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("GOST28147 failed encryption - expected " + Hex.ToHexString(output) + " got " + Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			bIn = new MemoryStream(bytes, false);
+			cIn = new CipherStream(bIn, inCipher, null);
+
+			BinaryReader dIn = new BinaryReader(cIn);
+
+			bytes = new byte[input.Length];
+
+			for (int i = 0; i != input.Length / 2; i++)
+			{
+				bytes[i] = dIn.ReadByte();
+			}
+
+			int remaining = bytes.Length - input.Length / 2;
+			byte[] extra = dIn.ReadBytes(remaining);
+			if (extra.Length < remaining)
+				throw new EndOfStreamException();
+			extra.CopyTo(bytes, input.Length / 2);
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("GOST28147 failed decryption - expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(bytes));
+			}
+		}
+
+		private void doOidTest()
+		{
+			string[] oids = {
+					CryptoProObjectIdentifiers.GostR28147Cbc.Id,
+			};
+
+			string[] names = {
+				"GOST28147/CBC/PKCS7Padding"
+			};
+
+			try
+			{
+				byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+//				IvParameterSpec ivSpec = new IvParameterSpec(new byte[8]);
+				byte[] iv = new byte[8];
+			    
+				for (int i = 0; i != oids.Length; i++)
+				{
+					IBufferedCipher c1 = CipherUtilities.GetCipher(oids[i]);
+					IBufferedCipher c2 = CipherUtilities.GetCipher(names[i]);
+
+//					KeyGenerator kg = KeyGenerator.getInstance(oids[i]);
+//					SecretKey k = kg.generateKey();
+					CipherKeyGenerator kg = GeneratorUtilities.GetKeyGenerator(oids[i]);
+					KeyParameter k = ParameterUtilities.CreateKeyParameter(oids[i], kg.GenerateKey());
+
+					c1.Init(true, new ParametersWithIV(k, iv));
+					c2.Init(false, new ParametersWithIV(k, iv));
+
+					byte[] result = c2.DoFinal(c1.DoFinal(data));
+
+					if (!AreEqual(data, result))
+					{
+						Fail("failed OID test");
+					}
+				}
+			}
+			catch (Exception ex)
+			{
+				Fail("failed exception " + ex.ToString(), ex);
+			}
+		}
+
+		public override void PerformTest() 
+		{
+			for (int i = 0; i != cipherTests.Length; i += 8)
+			{
+				doTestEcb(int.Parse(cipherTests[i]),
+					Hex.Decode(cipherTests[i + 1]),
+					Hex.Decode(cipherTests[i + 2]),
+					Hex.Decode(cipherTests[i + 3]));
+
+				doTestCfb(int.Parse(cipherTests[i + 4]),
+					Hex.Decode(cipherTests[i + 4 + 1]),
+					Hex.Decode(cipherTests[i + 4 + 2]),
+					Hex.Decode(cipherTests[i + 4 + 3]));
+
+				doOidTest();
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new Gost28147Test());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/test/GOST3410Test.cs b/BouncyCastle.AxCrypt/test/src/test/GOST3410Test.cs
new file mode 100644
index 0000000..db232c5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/GOST3410Test.cs
@@ -0,0 +1,380 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class Gost3410Test
+        : SimpleTest
+    {
+        private void ecGOST3410Test()
+        {
+            BigInteger r = new BigInteger("29700980915817952874371204983938256990422752107994319651632687982059210933395");
+            BigInteger s = new BigInteger("46959264877825372965922731380059061821746083849389763294914877353246631700866");
+
+            byte[] kData = new BigInteger("53854137677348463731403841147996619241504003434302020712960838528893196233395").ToByteArrayUnsigned();
+
+            SecureRandom k = FixedSecureRandom.From(kData);
+
+            BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+
+            ECCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("7"), // a
+                new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("2"),
+                    new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")),
+                new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q
+
+            ECPrivateKeyParameters sKey = new ECPrivateKeyParameters(
+                "ECGOST3410",
+                new BigInteger("55441196065363246126355624130324183196576709222340016572108097750006097525544"), // d
+                spec);
+
+            ECPublicKeyParameters vKey = new ECPublicKeyParameters(
+                "ECGOST3410",
+                curve.CreatePoint(
+                    new BigInteger("57520216126176808443631405023338071176630104906313632182896741342206604859403"),
+                    new BigInteger("17614944419213781543809391949654080031942662045363639260709847859438286763994")),
+                spec);
+
+            ISigner sgr = SignerUtilities.GetSigner("ECGOST3410");
+
+            sgr.Init(true, new ParametersWithRandom(sKey, k));
+
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail("ECGOST3410 verification failed");
+            }
+
+            BigInteger[] sig = decode(sigBytes);
+
+            if (!r.Equals(sig[0]))
+            {
+                Fail(
+                    ": r component wrong." + SimpleTest.NewLine
+                    + " expecting: " + r + SimpleTest.NewLine
+                    + " got      : " + sig[0]);
+            }
+
+            if (!s.Equals(sig[1]))
+            {
+                Fail(
+                    ": s component wrong." + SimpleTest.NewLine
+                    + " expecting: " + s + SimpleTest.NewLine
+                    + " got      : " + sig[1]);
+            }
+        }
+
+        private void generationTest()
+        {
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+            ISigner s = SignerUtilities.GetSigner("GOST3410");
+
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+            g.Init(
+                new Gost3410KeyGenerationParameters(
+                    new SecureRandom(),
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
+
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            AsymmetricKeyParameter sKey = p.Private;
+            AsymmetricKeyParameter vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("GOST3410");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("GOST3410 verification failed");
+            }
+
+            //
+            // default initialisation test
+            //
+            s = SignerUtilities.GetSigner("GOST3410");
+            g = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+
+            // TODO This is supposed to be a 'default initialisation' test, but don't have a factory
+            // These values are defaults from JCE provider
+            g.Init(
+                new Gost3410KeyGenerationParameters(
+                    new SecureRandom(),
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProA));
+
+            p = g.GenerateKeyPair();
+
+            sKey = p.Private;
+            vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("GOST3410");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("GOST3410 verification failed");
+            }
+
+            //
+            // encoded test
+            //
+            //KeyFactory f = KeyFactory.getInstance("GOST3410");
+            //X509EncodedKeySpec  x509s = new X509EncodedKeySpec(vKey.GetEncoded());
+            //Gost3410PublicKeyParameters k1 = (Gost3410PublicKeyParameters)f.generatePublic(x509s);
+            byte[] vKeyEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded();
+            Gost3410PublicKeyParameters k1 = (Gost3410PublicKeyParameters)
+                PublicKeyFactory.CreateKey(vKeyEnc);
+
+            if (!k1.Y.Equals(((Gost3410PublicKeyParameters)vKey).Y))
+            {
+                Fail("public number not decoded properly");
+            }
+
+            //PKCS8EncodedKeySpec  pkcs8 = new PKCS8EncodedKeySpec(sKey.GetEncoded());
+            //Gost3410PrivateKeyParameters k2 = (Gost3410PrivateKeyParameters)f.generatePrivate(pkcs8);
+            byte[] sKeyEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded();
+            Gost3410PrivateKeyParameters k2 = (Gost3410PrivateKeyParameters)
+                PrivateKeyFactory.CreateKey(sKeyEnc);
+
+            if (!k2.X.Equals(((Gost3410PrivateKeyParameters)sKey).X))
+            {
+                Fail("private number not decoded properly");
+            }
+
+            //
+            // ECGOST3410 generation test
+            //
+            s = SignerUtilities.GetSigner("ECGOST3410");
+            g = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+
+            BigInteger mod_p = new BigInteger("57896044618658097711785492504343953926634992332820282019728792003956564821041"); //p
+
+            ECCurve curve = new FpCurve(
+                mod_p, // p
+                new BigInteger("7"), // a
+                new BigInteger("43308876546767276905765904595650931995942111794451039583252968842033849580414")); // b
+
+            ECDomainParameters ecSpec = new ECDomainParameters(
+                curve,
+                curve.CreatePoint(
+                    new BigInteger("2"),
+                    new BigInteger("4018974056539037503335449422937059775635739389905545080690979365213431566280")),
+                new BigInteger("57896044618658097711785492504343953927082934583725450622380973592137631069619")); // q
+
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
+
+            p = g.GenerateKeyPair();
+
+            sKey = p.Private;
+            vKey = p.Public;
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("ECGOST3410");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("ECGOST3410 verification failed");
+            }
+        }
+
+        private void keyStoreTest(
+            AsymmetricKeyParameter	sKey,
+            AsymmetricKeyParameter	vKey)
+//	        throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, NoSuchProviderException, SignatureException, InvalidKeyException, UnrecoverableKeyException
+        {
+            //
+            // keystore test
+            //
+//			KeyStore ks = KeyStore.GetInstance("JKS");
+//			ks.Load(null, null);
+            Pkcs12StoreBuilder ksBuilder = new Pkcs12StoreBuilder();
+            Pkcs12Store ks = ksBuilder.Build();
+    
+            //
+            // create the certificate - version 3
+            //
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+    
+            certGen.SetSerialNumber(BigInteger.One);
+            certGen.SetIssuerDN(new X509Name("CN=Test"));
+            certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+            certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+            certGen.SetSubjectDN(new X509Name("CN=Test"));
+            certGen.SetPublicKey(vKey);
+            certGen.SetSignatureAlgorithm("GOST3411withGOST3410");
+    
+            X509Certificate cert = certGen.Generate(sKey);
+            X509CertificateEntry certEntry = new X509CertificateEntry(cert);
+
+//	        ks.SetKeyEntry("gost", sKey, "gost".ToCharArray(), new X509Certificate[] { cert });
+            ks.SetKeyEntry("gost", new AsymmetricKeyEntry(sKey), new X509CertificateEntry[] { certEntry });
+    
+            MemoryStream bOut = new MemoryStream();
+    
+            ks.Save(bOut, "gost".ToCharArray(), new SecureRandom());
+    
+//	        ks = KeyStore.getInstance("JKS");
+            ks = ksBuilder.Build();
+
+            ks.Load(new MemoryStream(bOut.ToArray(), false), "gost".ToCharArray());
+
+//	        AsymmetricKeyParameter gKey = (AsymmetricKeyParameter)ks.GetKey("gost", "gost".ToCharArray());
+//	        AsymmetricKeyEntry gKeyEntry = (AsymmetricKeyEntry)
+                ks.GetKey("gost");
+        }
+        
+        private void parametersTest()
+        {
+//	        AlgorithmParameterGenerator a = AlgorithmParameterGenerator.getInstance("GOST3410");
+//	        a.init(512, random);
+//	        AlgorithmParameters params = a.generateParameters();
+//
+//	        byte[] encodeParams = params.getEncoded();
+//
+//	        AlgorithmParameters a2 = AlgorithmParameters.getInstance("GOST3410");
+//	        a2.init(encodeParams);
+//
+//	        // a and a2 should be equivalent!
+//	        byte[] encodeParams_2 = a2.getEncoded();
+//
+//	        if (!arrayEquals(encodeParams, encodeParams_2))
+//	        {
+//	            Fail("encode/decode parameters failed");
+//	        }
+
+//			GOST3410ParameterSpec gost3410P = new GOST3410ParameterSpec(
+//				CryptoProObjectIdentifiers.gostR3410_94_CryptoPro_B.getId());
+//			g.initialize(gost3410P, new SecureRandom());
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("GOST3410");
+            g.Init(
+                new Gost3410KeyGenerationParameters(
+                    new SecureRandom(),
+                    CryptoProObjectIdentifiers.GostR3410x94CryptoProB));
+
+            AsymmetricCipherKeyPair p = g.GenerateKeyPair();
+
+            AsymmetricKeyParameter sKey = p.Private;
+            AsymmetricKeyParameter vKey = p.Public;
+
+            ISigner s = SignerUtilities.GetSigner("GOST3410");
+            byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+            s.Init(true, sKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            byte[] sigBytes = s.GenerateSignature();
+
+            s = SignerUtilities.GetSigner("GOST3410");
+
+            s.Init(false, vKey);
+
+            s.BlockUpdate(data, 0, data.Length);
+
+            if (!s.VerifySignature(sigBytes))
+            {
+                Fail("GOST3410 verification failed");
+            }
+
+            keyStoreTest(sKey, vKey);
+        }
+
+        private BigInteger[] decode(
+            byte[]  encoding)
+        {
+            byte[] r = new byte[32];
+            byte[] s = new byte[32];
+
+            Array.Copy(encoding, 0, s, 0, 32);
+            Array.Copy(encoding, 32, r, 0, 32);
+
+            BigInteger[] sig = new BigInteger[2];
+
+            sig[0] = new BigInteger(1, r);
+            sig[1] = new BigInteger(1, s);
+
+            return sig;
+        }
+
+        public override string Name
+        {
+            get { return "GOST3410/ECGOST3410"; }
+        }
+
+        public override void PerformTest()
+        {
+            ecGOST3410Test();
+            generationTest();
+            parametersTest();
+        }
+
+        public static void Main(
+            string[]	args)
+        {
+            RunTest(new Gost3410Test());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/HMacTest.cs b/BouncyCastle.AxCrypt/test/src/test/HMacTest.cs
new file mode 100644
index 0000000..e4f5cb9
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/HMacTest.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Iana;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    /// <remarks>HMAC tester</remarks>
+    [TestFixture]
+    public class HMacTest
+        : SimpleTest
+    {
+        private static byte[] keyBytes = Hex.Decode("0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
+        private static byte[] message = Encoding.ASCII.GetBytes("Hi There");
+        private static byte[] output1 = Hex.Decode("b617318655057264e28bc0b6fb378c8ef146be00");
+        private static byte[] outputMD5 = Hex.Decode("5ccec34ea9656392457fa1ac27f08fbc");
+        private static byte[] outputMD2 = Hex.Decode("dc1923ef5f161d35bef839ca8c807808");
+        private static byte[] outputMD4 = Hex.Decode("5570ce964ba8c11756cdc3970278ff5a");
+        private static byte[] output224 = Hex.Decode("896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22");
+        private static byte[] output256 = Hex.Decode("b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7");
+        private static byte[] output384 = Hex.Decode("afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6");
+        private static byte[] output512 = Hex.Decode("87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854");
+        private static byte[] output512_224 = Hex.Decode("b244ba01307c0e7a8ccaad13b1067a4cf6b961fe0c6a20bda3d92039");
+        private static byte[] output512_256 = Hex.Decode("9f9126c3d9c3c330d760425ca8a217e31feae31bfe70196ff81642b868402eab");
+        private static byte[] outputRipeMD128 = Hex.Decode("fda5717fb7e20cf05d30bb286a44b05d");
+        private static byte[] outputRipeMD160 = Hex.Decode("24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668");
+        private static byte[] outputTiger = Hex.Decode("1d7a658c75f8f004916e7b07e2a2e10aec7de2ae124d3647");
+        private static byte[] outputOld384 = Hex.Decode("0a046aaa0255e432912228f8ccda437c8a8363fb160afb0570ab5b1fd5ddc20eb1888b9ed4e5b6cb5bc034cd9ef70e40");
+        private static byte[] outputOld512 = Hex.Decode("9656975ee5de55e75f2976ecce9a04501060b9dc22a6eda2eaef638966280182477fe09f080b2bf564649cad42af8607a2bd8d02979df3a980f15e2326a0a22a");
+
+        public void doTestHMac(
+            string  hmacName,
+            byte[]  output)
+        {
+            KeyParameter key = new KeyParameter(keyBytes); //, hmacName);
+
+            IMac mac = MacUtilities.GetMac(hmacName);
+
+            mac.Init(key);
+
+            mac.Reset();
+
+            mac.BlockUpdate(message, 0, message.Length);
+
+//			byte[] outBytes = mac.DoFinal();
+            byte[] outBytes = new byte[mac.GetMacSize()];
+            mac.DoFinal(outBytes, 0);
+
+            if (!AreEqual(outBytes, output))
+            {
+                Fail("Failed - expected "
+                    + Hex.ToHexString(output) + " got "
+                    + Hex.ToHexString(outBytes));
+            }
+
+            // no key generator for the old algorithms
+            if (hmacName.StartsWith("Old"))
+            {
+                return;
+            }
+
+            CipherKeyGenerator kGen = GeneratorUtilities.GetKeyGenerator(hmacName);
+
+            mac.Init(new KeyParameter(kGen.GenerateKey())); // hmacName
+
+            mac.BlockUpdate(message, 0, message.Length);
+
+//			outBytes = mac.DoFinal();
+            outBytes = new byte[mac.GetMacSize()];
+            mac.DoFinal(outBytes, 0);
+        }
+
+        private void doTestExceptions()
+        {
+            IMac mac = MacUtilities.GetMac("HmacSHA1");
+
+            byte [] b = {(byte)1, (byte)2, (byte)3, (byte)4, (byte)5};
+//			KeyParameter sks = new KeyParameter(b); //, "HmacSHA1");
+//			RC5ParameterSpec algPS = new RC5ParameterSpec(100, 100, 100);
+            RC5Parameters rc5Parameters = new RC5Parameters(b, 100);
+
+            try
+            {
+//				mac.Init(sks, algPS);
+                mac.Init(rc5Parameters);
+            }
+//			catch (InvalidAlgorithmParameterException e)
+            catch (Exception)
+            {
+                // ignore okay
+            }
+
+            try
+            {
+                mac.Init(null); //, null);
+            }
+//			catch (InvalidKeyException)
+//			{
+//				// ignore okay
+//			}
+//			catch (InvalidAlgorithmParameterException e)
+            catch (Exception)
+            {
+                // ignore okay
+            }
+
+//			try
+//			{
+//				mac.Init(null);
+//			}
+//			catch (InvalidKeyException)
+//			{
+//				// ignore okay
+//			}
+        }
+
+        public override void PerformTest()
+        {
+            doTestHMac("HMac-SHA1", output1);
+            doTestHMac("HMac-MD5", outputMD5);
+            doTestHMac("HMac-MD4", outputMD4);
+            doTestHMac("HMac-MD2", outputMD2);
+            doTestHMac("HMac-SHA224", output224);
+            doTestHMac("HMac-SHA256", output256);
+            doTestHMac("HMac-SHA384", output384);
+            doTestHMac("HMac-SHA512", output512);
+            doTestHMac("HMac-SHA512/224", output512_224);
+            doTestHMac("HMac-SHA512/256", output512_256);
+            doTestHMac("HMac-RIPEMD128", outputRipeMD128);
+            doTestHMac("HMac-RIPEMD160", outputRipeMD160);
+            doTestHMac("HMac-TIGER", outputTiger);
+
+            doTestHMac("HMac/SHA1", output1);
+            doTestHMac("HMac/MD5", outputMD5);
+            doTestHMac("HMac/MD4", outputMD4);
+            doTestHMac("HMac/MD2", outputMD2);
+            doTestHMac("HMac/SHA224", output224);
+            doTestHMac("HMac/SHA256", output256);
+            doTestHMac("HMac/SHA384", output384);
+            doTestHMac("HMac/SHA512", output512);
+            doTestHMac("HMac/RIPEMD128", outputRipeMD128);
+            doTestHMac("HMac/RIPEMD160", outputRipeMD160);
+            doTestHMac("HMac/TIGER", outputTiger);
+
+            doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha1.Id, output1);
+            doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha224.Id, output224);
+            doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha256.Id, output256);
+            doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha384.Id, output384);
+            doTestHMac(PkcsObjectIdentifiers.IdHmacWithSha512.Id, output512);
+            doTestHMac(IanaObjectIdentifiers.HmacSha1.Id, output1);
+            doTestHMac(IanaObjectIdentifiers.HmacMD5.Id, outputMD5);
+            doTestHMac(IanaObjectIdentifiers.HmacRipeMD160.Id, outputRipeMD160);
+            doTestHMac(IanaObjectIdentifiers.HmacTiger.Id, outputTiger);
+
+//			// test for compatibility with broken HMac.
+//			doTestHMac("OldHMacSHA384", outputOld384);
+//			doTestHMac("OldHMacSHA512", outputOld512);
+
+            doTestExceptions();
+        }
+
+        public override string Name
+        {
+            get { return "HMac"; }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new HMacTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/IESTest.cs b/BouncyCastle.AxCrypt/test/src/test/IESTest.cs
new file mode 100644
index 0000000..193fe1a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/IESTest.cs
@@ -0,0 +1,245 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/**
+	 * test for ECIES - Elliptic Curve Integrated Encryption Scheme
+	 */
+	[TestFixture]
+	public class IesTest
+		: SimpleTest
+	{
+		private static readonly BigInteger g512 = new BigInteger("153d5d6172adb43045b68ae8e1de1070b6137005686d29d3d73a7749199681ee5b212c9b96bfdcfa5b20cd5e3fd2044895d609cf9b410b7a0f12ca1cb9a428cc", 16);
+		private static readonly BigInteger p512 = new BigInteger("9494fec095f3b85ee286542b3836fc81a5dd0a0349b4c239dd38744d488cf8e31db8bcb7d33b41abb9e5a33cca9144b1cef332c94bf0573bf047a3aca98cdf3b", 16);
+
+		public override string Name
+		{
+			get { return "IES"; }
+		}
+
+		public override void PerformTest()
+		{
+			IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECIES");
+
+			ECCurve curve = new FpCurve(
+				new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+			ECDomainParameters ecSpec = new ECDomainParameters(
+				curve,
+				curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+				new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
+
+			g.Init(
+				new ECKeyGenerationParameters(
+					ecSpec,
+					new SecureRandom()));
+
+			IBufferedCipher c1 = CipherUtilities.GetCipher("ECIES");
+			IBufferedCipher c2 = CipherUtilities.GetCipher("ECIES");
+
+			doTest(g, c1, c2);
+
+			g = GeneratorUtilities.GetKeyPairGenerator("ECIES");
+
+			g.Init(new KeyGenerationParameters(new SecureRandom(), 192));
+
+			doTest(g, c1, c2);
+
+			g = GeneratorUtilities.GetKeyPairGenerator("ECIES");
+
+			g.Init(new KeyGenerationParameters(new SecureRandom(), 239));
+
+			doTest(g, c1, c2);
+
+			g = GeneratorUtilities.GetKeyPairGenerator("ECIES");
+
+			g.Init(new KeyGenerationParameters(new SecureRandom(), 256));
+
+			doTest(g, c1, c2);
+
+			doDefTest(g, c1, c2);
+
+			c1 = CipherUtilities.GetCipher("IES");
+			c2 = CipherUtilities.GetCipher("IES");
+
+			g = GeneratorUtilities.GetKeyPairGenerator("DH");
+
+//			DHParameterSpec dhParams = new DHParameterSpec(p512, g512);
+//			g.initialize(dhParams);
+			g.Init(
+				new DHKeyGenerationParameters(
+					new SecureRandom(),
+					new DHParameters(p512, g512)));
+
+			doTest(g, c1, c2);
+
+			doDefTest(g, c1, c2);
+		}
+
+		public void doTest(
+			IAsymmetricCipherKeyPairGenerator	g,
+			IBufferedCipher						c1,
+			IBufferedCipher						c2)
+		{
+			//
+			// a side
+			//
+			AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
+			AsymmetricKeyParameter aPub = aKeyPair.Public;
+			AsymmetricKeyParameter  aPriv = aKeyPair.Private;
+
+			//
+			// b side
+			//
+			AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair();
+			AsymmetricKeyParameter bPub = bKeyPair.Public;
+			AsymmetricKeyParameter bPriv = bKeyPair.Private;
+
+			// TODO Put back in
+//			//
+//			// stream test
+//			//
+//			IEKeySpec c1Key = new IEKeySpec(aPriv, bPub);
+//			IEKeySpec c2Key = new IEKeySpec(bPriv, aPub);
+//
+//			byte[] d = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
+//			byte[] e = new byte[] { 8, 7, 6, 5, 4, 3, 2, 1 };
+//
+//			IESParameterSpec param = new IESParameterSpec(d, e, 128);
+//
+//			c1.Init(true, c1Key, param);
+//
+//			c2.Init(false, c2Key, param);
+//
+//			byte[] message = Hex.Decode("1234567890abcdef");
+//
+//			byte[] out1 = c1.DoFinal(message, 0, message.Length);
+//
+//			byte[] out2 = c2.DoFinal(out1, 0, out1.Length);
+//
+//			if (!AreEqual(out2, message))
+//			{
+//				Fail("stream cipher test failed");
+//			}
+		}
+
+		public void doDefTest(
+			IAsymmetricCipherKeyPairGenerator	g,
+			IBufferedCipher						c1,
+			IBufferedCipher						c2)
+		{
+			//
+			// a side
+			//
+			AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
+			AsymmetricKeyParameter aPub = aKeyPair.Public;
+			AsymmetricKeyParameter aPriv = aKeyPair.Private;
+
+			//
+			// b side
+			//
+			AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair();
+			AsymmetricKeyParameter bPub = bKeyPair.Public;
+			AsymmetricKeyParameter bPriv = bKeyPair.Private;
+
+			// TODO Put back in
+//			//
+//			// stream test
+//			//
+//			IEKeySpec c1Key = new IEKeySpec(aPriv, bPub);
+//			IEKeySpec c2Key = new IEKeySpec(bPriv, aPub);
+//
+//			c1.Init(true, c1Key);
+//
+//			AlgorithmParameters param = c1.getParameters();
+//
+//			c2.Init(false, c2Key, param);
+//
+//			byte[] message = Hex.Decode("1234567890abcdef");
+//
+//			byte[] out1 = c1.DoFinal(message, 0, message.Length);
+//
+//			byte[] out2 = c2.DoFinal(out1, 0, out1.Length);
+//
+//			if (!AreEqual(out2, message))
+//			{
+//				Fail("stream cipher test failed");
+//			}
+//
+//			//
+//			// int DoFinal
+//			//
+//			int len1 = c1.DoFinal(message, 0, message.Length, out1, 0);
+//
+//			if (len1 != out1.Length)
+//			{
+//				Fail("encryption length wrong");
+//			}
+//
+//			int len2 = c2.DoFinal(out1, 0, out1.Length, out2, 0);
+//
+//			if (len2 != out2.Length)
+//			{
+//				Fail("decryption length wrong");
+//			}
+//        
+//			if (!AreEqual(out2, message))
+//			{
+//				Fail("stream cipher test failed");
+//			}
+//        
+//			//
+//			// int DoFinal with update
+//			//
+//			len1 = c1.ProcessBytes(message, 0, 2, out1, 0);
+//
+//			len1 += c1.DoFinal(message, 2, message.Length - 2, out1, len1);
+//
+//			if (len1 != out1.Length)
+//			{
+//				Fail("update encryption length wrong");
+//			}
+//
+//			len2 = c2.ProcessBytes(out1, 0, 2, out2, 0);
+//
+//			len2 += c2.DoFinal(out1, 2, out1.Length - 2, out2, len2);
+//
+//			if (len2 != out2.Length)
+//			{
+//				Fail("update decryption length wrong");
+//			}
+//
+//			if (!AreEqual(out2, message))
+//			{
+//				Fail("update stream cipher test failed");
+//			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new IesTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/MacTest.cs b/BouncyCastle.AxCrypt/test/src/test/MacTest.cs
new file mode 100644
index 0000000..d4b3188
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/MacTest.cs
@@ -0,0 +1,216 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <remarks>
+	/// MAC tester - vectors from
+	/// <a href="http://www.itl.nist.gov/fipspubs/fip81.htm">FIP 81</a> and
+	/// <a href="http://www.itl.nist.gov/fipspubs/fip113.htm">FIP 113</a>.
+	/// </remarks>
+	[TestFixture]
+	public class MacTest
+		: SimpleTest
+	{
+		private static readonly byte[] keyBytes = Hex.Decode("0123456789abcdef");
+		private static readonly byte[] ivBytes = Hex.Decode("1234567890abcdef");
+
+		private static readonly byte[] input = Hex.Decode("37363534333231204e6f77206973207468652074696d6520666f7220");
+
+		private static readonly byte[] output1 = Hex.Decode("f1d30f68");
+		private static readonly byte[] output2 = Hex.Decode("58d2e77e");
+		private static readonly byte[] output3 = Hex.Decode("cd647403");
+
+		private static readonly byte[] keyBytesISO9797 = Hex.Decode("7CA110454A1A6E570131D9619DC1376E");
+
+		private static readonly byte[] inputISO9797 = Encoding.ASCII.GetBytes("Hello World !!!!");
+
+		private static readonly byte[] outputISO9797 = Hex.Decode("F09B856213BAB83B");
+
+		private static readonly byte[] inputDesEDE64 = Encoding.ASCII.GetBytes("Hello World !!!!");
+
+		private static readonly byte[] outputDesEDE64 = Hex.Decode("862304d33af01096");
+
+		private void aliasTest(
+			KeyParameter	key,
+			string			primary,
+			params string[]	aliases)
+		{
+			IMac mac = MacUtilities.GetMac(primary);
+
+			//
+			// standard DAC - zero IV
+			//
+			mac.Init(key);
+
+			mac.BlockUpdate(input, 0, input.Length);
+
+			byte[] refBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(refBytes, 0);
+
+			for (int i = 0; i != aliases.Length; i++)
+			{
+				mac = MacUtilities.GetMac(aliases[i]);
+
+				mac.Init(key);
+
+				mac.BlockUpdate(input, 0, input.Length);
+
+				byte[] outBytes = new byte[mac.GetMacSize()];
+				mac.DoFinal(outBytes, 0);
+
+				if (!AreEqual(outBytes, refBytes))
+				{
+					Fail("Failed - expected "
+						+ Hex.ToHexString(refBytes) + " got "
+						+ Hex.ToHexString(outBytes));
+				}
+			}
+		}
+
+		public override void PerformTest()
+		{
+			KeyParameter key = new DesParameters(keyBytes);
+			IMac mac = MacUtilities.GetMac("DESMac");
+
+			//
+			// standard DAC - zero IV
+			//
+			mac.Init(key);
+
+			mac.BlockUpdate(input, 0, input.Length);
+
+			//byte[] outBytes = mac.DoFinal();
+			byte[] outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output1))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(output1) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			//
+			// mac with IV.
+			//
+			mac.Init(new ParametersWithIV(key, ivBytes));
+
+			mac.BlockUpdate(input, 0, input.Length);
+
+			//outBytes = mac.DoFinal();
+			outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output2))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(output2) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			//
+			// CFB mac with IV - 8 bit CFB mode
+			//
+			mac = MacUtilities.GetMac("DESMac/CFB8");
+
+			mac.Init(new ParametersWithIV(key, ivBytes));
+
+			mac.BlockUpdate(input, 0, input.Length);
+
+			//outBytes = mac.DoFinal();
+			outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output3))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(output3) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			//
+			// ISO9797 algorithm 3 using DESEDE
+			//
+			key = new DesEdeParameters(keyBytesISO9797);
+
+			mac = MacUtilities.GetMac("ISO9797ALG3");
+
+			mac.Init(key);
+
+			mac.BlockUpdate(inputISO9797, 0, inputISO9797.Length);
+
+			//outBytes = mac.DoFinal();
+			outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, outputISO9797))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(outputISO9797) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			//
+			// 64bit DESede Mac
+			//
+			key = new DesEdeParameters(keyBytesISO9797);
+
+			mac = MacUtilities.GetMac("DESEDE64");
+
+			mac.Init(key);
+
+			mac.BlockUpdate(inputDesEDE64, 0, inputDesEDE64.Length);
+
+			//outBytes = mac.DoFinal();
+			outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, outputDesEDE64))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(outputDesEDE64) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			aliasTest(
+				ParameterUtilities.CreateKeyParameter("DESede", keyBytesISO9797),
+				"DESedeMac64withISO7816-4Padding",
+				"DESEDE64WITHISO7816-4PADDING",
+				"DESEDEISO9797ALG1MACWITHISO7816-4PADDING",
+				"DESEDEISO9797ALG1WITHISO7816-4PADDING");
+
+			aliasTest(
+				ParameterUtilities.CreateKeyParameter("DESede", keyBytesISO9797),
+				"ISO9797ALG3WITHISO7816-4PADDING",
+				"ISO9797ALG3MACWITHISO7816-4PADDING");
+		}
+
+		public override string Name
+		{
+			get { return "Mac"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new MacTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/MqvTest.cs b/BouncyCastle.AxCrypt/test/src/test/MqvTest.cs
new file mode 100644
index 0000000..ef36e1a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/MqvTest.cs
@@ -0,0 +1,99 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class MqvTest
+		: SimpleTest
+	{
+		public override string Name
+		{
+			get { return "MQV"; }
+		}
+
+		public override void PerformTest()
+		{
+			TestECMqv();
+		}
+
+		[Test]
+		public void TestECMqv()
+		{
+			IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECMQV");
+
+//			EllipticCurve curve = new EllipticCurve(
+//				new ECFieldFp(new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839")), // q
+//				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+//				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+			ECCurve curve = new FpCurve(
+				new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+				new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+				new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+			ECDomainParameters ecSpec = new ECDomainParameters(
+				curve,
+//				ECPointUtil.DecodePoint(curve, Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+				curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+				new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307"), // n
+				BigInteger.One); //1); // h
+
+//			g.initialize(ecSpec, new SecureRandom());
+			g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
+			
+			//
+			// U side
+			//
+			AsymmetricCipherKeyPair U1 = g.GenerateKeyPair();
+			AsymmetricCipherKeyPair U2 = g.GenerateKeyPair();
+			
+			IBasicAgreement uAgree = AgreementUtilities.GetBasicAgreement("ECMQV");
+			uAgree.Init(new MqvPrivateParameters(
+				(ECPrivateKeyParameters)U1.Private,
+				(ECPrivateKeyParameters)U2.Private,
+				(ECPublicKeyParameters)U2.Public));
+			
+			//
+			// V side
+			//
+			AsymmetricCipherKeyPair V1 = g.GenerateKeyPair();
+			AsymmetricCipherKeyPair V2 = g.GenerateKeyPair();
+
+			IBasicAgreement vAgree = AgreementUtilities.GetBasicAgreement("ECMQV");
+			vAgree.Init(new MqvPrivateParameters(
+				(ECPrivateKeyParameters)V1.Private,
+				(ECPrivateKeyParameters)V2.Private,
+				(ECPublicKeyParameters)V2.Public));
+			
+			//
+			// agreement
+			//
+			BigInteger ux = uAgree.CalculateAgreement(new MqvPublicParameters(
+				(ECPublicKeyParameters)V1.Public,
+				(ECPublicKeyParameters)V2.Public));
+			BigInteger vx = vAgree.CalculateAgreement(new MqvPublicParameters(
+				(ECPublicKeyParameters)U1.Public,
+				(ECPublicKeyParameters)U2.Public));
+
+			if (!ux.Equals(vx))
+			{
+				Fail("Agreement failed");
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new MqvTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/NamedCurveTest.cs b/BouncyCastle.AxCrypt/test/src/test/NamedCurveTest.cs
new file mode 100644
index 0000000..bc8684a
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/NamedCurveTest.cs
@@ -0,0 +1,381 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Sec;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class NamedCurveTest
+        : SimpleTest
+    {
+//		private static readonly Hashtable CurveNames = new Hashtable();
+//		private static readonly Hashtable CurveAliases = new Hashtable();
+//
+//		static NamedCurveTest()
+//		{
+//			CurveNames.Add("prime192v1", "prime192v1"); // X9.62
+//			CurveNames.Add("sect571r1", "sect571r1"); // sec
+//			CurveNames.Add("secp224r1", "secp224r1");
+//			CurveNames.Add("B-409", SecNamedCurves.GetName(NistNamedCurves.GetOid("B-409")));   // nist
+//			CurveNames.Add("P-521", SecNamedCurves.GetName(NistNamedCurves.GetOid("P-521")));
+//			CurveNames.Add("brainpoolp160r1", "brainpoolp160r1");         // TeleTrusT
+//
+//			CurveAliases.Add("secp192r1", "prime192v1");
+//			CurveAliases.Add("secp256r1", "prime256v1");
+//		}
+
+        private static ECDomainParameters GetCurveParameters(
+            string name)
+        {
+            ECDomainParameters ecdp = ECGost3410NamedCurves.GetByName(name);
+
+            if (ecdp != null)
+                return ecdp;
+
+            X9ECParameters ecP = ECNamedCurveTable.GetByName(name);
+
+            if (ecP == null)
+                throw new Exception("unknown curve name: " + name);
+
+            return new ECDomainParameters(ecP.Curve, ecP.G, ecP.N, ecP.H, ecP.GetSeed());
+        }
+
+        public void doTestCurve(
+            string name)
+        {
+//			ECGenParameterSpec ecSpec = new ECGenParameterSpec(name);
+            ECDomainParameters ecSpec = GetCurveParameters(name);
+
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDH");
+
+//			g.initialize(ecSpec, new SecureRandom());
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); 
+
+            //
+            // a side
+            //
+            AsymmetricCipherKeyPair aKeyPair = g.GenerateKeyPair();
+
+//			KeyAgreement aKeyAgree = KeyAgreement.getInstance("ECDHC");
+            IBasicAgreement aKeyAgree = AgreementUtilities.GetBasicAgreement("ECDHC");
+
+            aKeyAgree.Init(aKeyPair.Private);
+
+            //
+            // b side
+            //
+            AsymmetricCipherKeyPair bKeyPair = g.GenerateKeyPair();
+
+//			KeyAgreement bKeyAgree = KeyAgreement.getInstance("ECDHC");
+            IBasicAgreement bKeyAgree = AgreementUtilities.GetBasicAgreement("ECDHC");
+
+            bKeyAgree.Init(bKeyPair.Private);
+
+            //
+            // agreement
+            //
+//			aKeyAgree.doPhase(bKeyPair.Public, true);
+//			bKeyAgree.doPhase(aKeyPair.Public, true);
+//
+//			BigInteger k1 = new BigInteger(aKeyAgree.generateSecret());
+//			BigInteger k2 = new BigInteger(bKeyAgree.generateSecret());
+            BigInteger k1 = aKeyAgree.CalculateAgreement(bKeyPair.Public);
+            BigInteger k2 = bKeyAgree.CalculateAgreement(aKeyPair.Public);
+
+            if (!k1.Equals(k2))
+            {
+                Fail("2-way test failed");
+            }
+
+            //
+            // public key encoding test
+            //
+//			byte[]              pubEnc = aKeyPair.Public.getEncoded();
+            byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(aKeyPair.Public).GetDerEncoded();
+
+//			KeyFactory          keyFac = KeyFactory.getInstance("ECDH");
+//			X509EncodedKeySpec  pubX509 = new X509EncodedKeySpec(pubEnc);
+//			ECPublicKey         pubKey = (ECPublicKey)keyFac.generatePublic(pubX509);
+            ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
+
+//			if (!pubKey.getW().Equals(((ECPublicKey)aKeyPair.Public).getW()))
+            if (!pubKey.Q.Equals(((ECPublicKeyParameters)aKeyPair.Public).Q))
+            {
+                Fail("public key encoding (Q test) failed");
+            }
+
+            // TODO Put back in?
+//			if (!(pubKey.getParams() is ECNamedCurveSpec))
+//			{
+//				Fail("public key encoding not named curve");
+//			}
+
+            //
+            // private key encoding test
+            //
+//			byte[]              privEnc = aKeyPair.Private.getEncoded();
+            byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(aKeyPair.Private).GetDerEncoded();
+
+//			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+//			ECPrivateKey        privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8);
+            ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc);
+
+//			if (!privKey.getS().Equals(((ECPrivateKey)aKeyPair.Private).getS()))
+            if (!privKey.D.Equals(((ECPrivateKeyParameters)aKeyPair.Private).D))
+            {
+                Fail("private key encoding (S test) failed");
+            }
+
+            // TODO Put back in?
+//			if (!(privKey.getParams() is ECNamedCurveSpec))
+//			{
+//				Fail("private key encoding not named curve");
+//			}
+//
+//			ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams();
+//			if (!(privSpec.GetName().Equals(name) || privSpec.GetName().Equals(CurveNames.get(name))))
+//			{
+//				Fail("private key encoding wrong named curve. Expected: "
+//					+ CurveNames[name] + " got " + privSpec.GetName());
+//			}
+        }
+
+        public void doTestECDsa(
+            string name)
+        {
+//			ECGenParameterSpec ecSpec = new ECGenParameterSpec(name);
+            ECDomainParameters ecSpec = GetCurveParameters(name);
+
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+
+//			g.initialize(ecSpec, new SecureRandom());
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); 
+
+            ISigner sgr = SignerUtilities.GetSigner("ECDSA");
+            AsymmetricCipherKeyPair pair = g.GenerateKeyPair();
+            AsymmetricKeyParameter sKey = pair.Private;
+            AsymmetricKeyParameter vKey = pair.Public;
+
+            sgr.Init(true, sKey);
+
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail(name + " verification failed");
+            }
+
+            //
+            // public key encoding test
+            //
+//			byte[]              pubEnc = vKey.getEncoded();
+            byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded();
+
+//			KeyFactory          keyFac = KeyFactory.getInstance("ECDH");
+//			X509EncodedKeySpec  pubX509 = new X509EncodedKeySpec(pubEnc);
+//			ECPublicKey         pubKey = (ECPublicKey)keyFac.generatePublic(pubX509);
+            ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
+
+//			if (!pubKey.getW().Equals(((ECPublicKey)vKey).getW()))
+            if (!pubKey.Q.Equals(((ECPublicKeyParameters)vKey).Q))
+            {
+                Fail("public key encoding (Q test) failed");
+            }
+
+            // TODO Put back in?
+//			if (!(pubKey.Parameters is ECNamedCurveSpec))
+//			{
+//				Fail("public key encoding not named curve");
+//			}
+
+            //
+            // private key encoding test
+            //
+//			byte[]              privEnc = sKey.getEncoded();
+            byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded();
+
+//			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+//			ECPrivateKey        privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8);
+            ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc);
+
+//			if (!privKey.getS().Equals(((ECPrivateKey)sKey).getS()))
+            if (!privKey.D.Equals(((ECPrivateKeyParameters)sKey).D))
+            {
+                Fail("private key encoding (D test) failed");
+            }
+
+            // TODO Put back in?
+//			if (!(privKey.Parameters is ECNamedCurveSpec))
+//			{
+//				Fail("private key encoding not named curve");
+//			}
+//
+//			ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams();
+//			if (!privSpec.GetName().EqualsIgnoreCase(name)
+//				&& !privSpec.GetName().EqualsIgnoreCase((string) CurveAliases[name]))
+//			{
+//				Fail("private key encoding wrong named curve. Expected: " + name + " got " + privSpec.GetName());
+//			}
+        }
+
+        public void doTestECGost(
+            string name)
+        {
+//			ECGenParameterSpec ecSpec = new ECGenParameterSpec(name);
+            ECDomainParameters ecSpec = GetCurveParameters(name);
+
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+
+//			g.initialize(ecSpec, new SecureRandom());
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom())); 
+
+            ISigner sgr = SignerUtilities.GetSigner("ECGOST3410");
+            AsymmetricCipherKeyPair pair = g.GenerateKeyPair();
+            AsymmetricKeyParameter sKey = pair.Private;
+            AsymmetricKeyParameter vKey = pair.Public;
+
+            sgr.Init(true, sKey);
+
+            byte[] message = new byte[] { (byte)'a', (byte)'b', (byte)'c' };
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            byte[] sigBytes = sgr.GenerateSignature();
+
+            sgr.Init(false, vKey);
+
+            sgr.BlockUpdate(message, 0, message.Length);
+
+            if (!sgr.VerifySignature(sigBytes))
+            {
+                Fail(name + " verification failed");
+            }
+
+            // TODO Get this working?
+//			//
+//			// public key encoding test
+//			//
+////			byte[]              pubEnc = vKey.getEncoded();
+//			byte[] pubEnc = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(vKey).GetDerEncoded();
+//
+////			KeyFactory          keyFac = KeyFactory.getInstance("ECGOST3410");
+////			X509EncodedKeySpec  pubX509 = new X509EncodedKeySpec(pubEnc);
+////			ECPublicKey         pubKey = (ECPublicKey)keyFac.generatePublic(pubX509);
+//			ECPublicKeyParameters pubKey = (ECPublicKeyParameters) PublicKeyFactory.CreateKey(pubEnc);
+//
+////			if (!pubKey.getW().equals(((ECPublicKey)vKey).getW()))
+//			if (!pubKey.Q.Equals(((ECPublicKeyParameters)vKey).Q))
+//			{
+//				Fail("public key encoding (Q test) failed");
+//			}
+
+            // TODO Put back in?
+//			if (!(pubKey.Parameters is ECNamedCurveSpec))
+//			{
+//				Fail("public key encoding not named curve");
+//			}
+
+            // TODO Get this working?
+//			//
+//			// private key encoding test
+//			//
+////			byte[]              privEnc = sKey.getEncoded();
+//			byte[] privEnc = PrivateKeyInfoFactory.CreatePrivateKeyInfo(sKey).GetDerEncoded();
+//
+////			PKCS8EncodedKeySpec privPKCS8 = new PKCS8EncodedKeySpec(privEnc);
+////			ECPrivateKey        privKey = (ECPrivateKey)keyFac.generatePrivate(privPKCS8);
+//			ECPrivateKeyParameters privKey = (ECPrivateKeyParameters) PrivateKeyFactory.CreateKey(privEnc);
+//
+////			if (!privKey.getS().Equals(((ECPrivateKey)sKey).getS()))
+//			if (!privKey.D.Equals(((ECPrivateKeyParameters)sKey).D))
+//			{
+//				Fail("GOST private key encoding (D test) failed");
+//			}
+
+            // TODO Put back in?
+//			if (!(privKey.Parameters is ECNamedCurveSpec))
+//			{
+//				Fail("GOST private key encoding not named curve");
+//			}
+//
+//			ECNamedCurveSpec privSpec = (ECNamedCurveSpec)privKey.getParams();
+//			if (!privSpec.getName().equalsIgnoreCase(name)
+//				&& !privSpec.getName().equalsIgnoreCase((String)CURVE_ALIASES[name]))
+//			{
+//				Fail("GOST private key encoding wrong named curve. Expected: " + name + " got " + privSpec.getName());
+//			}
+        }
+
+        public override string Name
+        {
+            get { return "NamedCurve"; }
+        }
+        
+        public override void PerformTest()
+        {
+            doTestCurve("prime192v1"); // X9.62
+            doTestCurve("sect571r1"); // sec
+            doTestCurve("secp224r1");
+            doTestCurve("B-409");   // nist
+            doTestCurve("P-521");
+            doTestCurve("brainpoolp160r1");    // TeleTrusT
+
+            foreach (string name in X962NamedCurves.Names)
+            {
+                doTestECDsa(name);
+            }
+
+            foreach (string name in SecNamedCurves.Names)
+            {
+                doTestECDsa(name);
+            }
+
+            foreach (string name in TeleTrusTNamedCurves.Names)
+            {
+                doTestECDsa(name);
+            }
+
+            foreach (string name in ECGost3410NamedCurves.Names)
+            {
+                doTestECGost(name);
+            }
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new NamedCurveTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/NistCertPathTest.cs b/BouncyCastle.AxCrypt/test/src/test/NistCertPathTest.cs
new file mode 100644
index 0000000..0f42e24
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/NistCertPathTest.cs
@@ -0,0 +1,5192 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class NistCertPathTest
+		: SimpleTest
+	{
+		/*
+		* These tests are taken from the NIST X.509 Validation Test Suite
+		* available at: http://csrc.nist.gov/pki/testing/x509paths.html
+		*
+		* Only the relevant certificate and crl data has been kept, in order
+		* to keep the class size to a minimum.
+		*
+		*/
+		private const string TEST_POLICY_1 = "2.16.840.1.101.3.1.48.1";
+		private const string TEST_POLICY_2 = "2.16.840.1.101.3.1.48.2";
+		private const string TEST_POLICY_3 = "2.16.840.1.101.3.1.48.3";
+		private const string TEST_POLICY_4 = "2.16.840.1.101.3.1.48.4";
+		private const string TEST_POLICY_5 = "2.16.840.1.101.3.1.48.5";
+
+		private static ISet ANY;
+		private static ISet TP1;
+		private static ISet TP2;
+		private static ISet TP3;
+		private static ISet TP4;
+		private static ISet TP1_TP2;
+
+		static NistCertPathTest()
+		{
+			ANY = new HashSet();
+
+			TP1 = new HashSet();
+			TP1.Add(TEST_POLICY_1);
+
+			TP2 = new HashSet();
+			TP2.Add(TEST_POLICY_2);
+
+			TP3 = new HashSet();
+			TP3.Add(TEST_POLICY_3);
+
+			TP4 = new HashSet();
+			TP4.Add(TEST_POLICY_4);
+
+			TP1_TP2 = new HashSet();
+			TP1_TP2.Add(TEST_POLICY_1);
+			TP1_TP2.Add(TEST_POLICY_2);
+		}
+
+		/*
+		 *  FIELDS
+		 */
+		private X509CertificateParser certParser = new X509CertificateParser();
+		private X509CrlParser crlParser = new X509CrlParser();
+
+		private X509Certificate trustedCert;
+		private X509Crl trustedCRL;
+		private ISet trustedSet;
+		private int testCount;
+		private IList testFail;
+		private StringBuilder resultBuf;
+
+		public override string Name
+		{
+			get { return "NistCertPathTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			Init();
+
+			Test(" 1", TEST_1_DATA, true, false);
+			Test(" 2", TEST_2_DATA, false, false);
+			Test(" 3", TEST_3_DATA, false, false);
+			Test(" 4", TEST_4_DATA, true, false);
+			Test(" 5", TEST_5_DATA, false, false);
+			Test(" 6", TEST_6_DATA, false, false);
+			Test(" 7", TEST_7_DATA, true, false);
+			Test(" 8", TEST_8_DATA, false, false);
+			Test(" 9", TEST_9_DATA, false, false);
+
+			Test("10", TEST_10_DATA, false, false);
+			Test("11", TEST_11_DATA, false, false);
+			Test("12", TEST_12_DATA, true, false);
+			Test("13", TEST_13_DATA, false, false);
+			Test("14", TEST_14_DATA, false, false);
+			Test("15", TEST_15_DATA, true, false);
+			Test("16", TEST_16_DATA, true, false);
+			Test("17", TEST_17_DATA, true, false);
+			Test("18", TEST_18_DATA, true, false);
+			Test("19", TEST_19_DATA, false, false);
+
+			Test("20", TEST_20_DATA, false, false);
+			Test("21", TEST_21_DATA, false, false);
+			Test("22", TEST_22_DATA, false, false);
+			Test("23", TEST_23_DATA, false, false);
+			Test("24", TEST_24_DATA, true, false);
+			Test("25", TEST_25_DATA, false, false);
+			Test("26", TEST_26_DATA, true, false);
+			Test("27", TEST_27_DATA, true, false);
+			Test("28", TEST_28_DATA, false, false);
+			Test("29", TEST_29_DATA, false, false);
+
+			Test("30", TEST_30_DATA, true, false);
+			Test("31", TEST_31_DATA, false, false);
+			Test("32", TEST_32_DATA, false, false);
+			Test("33", TEST_33_DATA, true, false);
+
+			Test("34a", TEST_34_DATA, ANY, true, true, false);
+			Test("34b", TEST_34_DATA, ANY, false, true, false);
+			Test("34c", TEST_34_DATA, TP1, true, true, false);
+			Test("34d", TEST_34_DATA, TP1, false, true, false);
+			Test("34e", TEST_34_DATA, TP2, true, false, false);
+			Test("34f", TEST_34_DATA, TP2, false, true, false);
+
+			Test("35a", TEST_35_DATA, false, true, false);
+			Test("35b", TEST_35_DATA, true, false, false);
+
+			Test("36a", TEST_36_DATA, false, true, false);
+			Test("36b", TEST_36_DATA, true, false, false);
+
+			Test("37a", TEST_37_DATA, false, true, false);
+			Test("37b", TEST_37_DATA, true, false, false);
+
+			Test("38a", TEST_38_DATA, false, true, false);
+			Test("38b", TEST_38_DATA, true, false, false);
+
+			Test("39a", TEST_39_DATA, ANY, true, true, false);
+			Test("39b", TEST_39_DATA, ANY, false, true, false);
+			Test("39c", TEST_39_DATA, TP1, true, true, false);
+			Test("39d", TEST_39_DATA, TP1, false, true, false);
+			Test("39e", TEST_39_DATA, TP2, true, false, false);
+			Test("39f", TEST_39_DATA, TP2, false, true, false);
+
+			Test("40a", TEST_40_DATA, false, true, false);
+			Test("40b", TEST_40_DATA, true, false, false);
+
+			Test("41a", TEST_41_DATA, false, true, false);
+			Test("41b", TEST_41_DATA, true, false, false);
+
+			Test("42a", TEST_42_DATA, false, true, false);
+			Test("42b", TEST_42_DATA, true, false, false);
+
+			Test("43a", TEST_43_DATA, false, true, false);
+			Test("43b", TEST_43_DATA, true, false, false);
+
+			Test("44a", TEST_44_DATA, false, true, false);
+			Test("44b", TEST_44_DATA, true, false, false);
+
+			Test("45a", TEST_45_DATA, false, false, false);
+			Test("45b", TEST_45_DATA, true, false, false);
+
+			Test("46a", TEST_46_DATA, ANY, false, true, false);
+			Test("46b", TEST_46_DATA, ANY, true, true, false);
+			Test("46c", TEST_46_DATA, TP1, true, true, false);
+			Test("46d", TEST_46_DATA, TP1, false, true, false);
+			Test("46e", TEST_46_DATA, TP2, true, false, false);
+			Test("46f", TEST_46_DATA, TP2, false, false, false);
+
+			Test("47a", TEST_47_DATA, false, false, false);
+			Test("47b", TEST_47_DATA, true, false, false);
+
+			Test("48a", TEST_48_DATA, TP1, false, true, false);
+			Test("48b", TEST_48_DATA, TP1, true, true, false);
+			Test("48c", TEST_48_DATA, ANY, false, true, false);
+			Test("48d", TEST_48_DATA, ANY, true, true, false);
+			Test("48e", TEST_48_DATA, TP2, false, true, false);
+			Test("48f", TEST_48_DATA, TP2, true, false, false);
+
+			Test("49a", TEST_49_DATA, TP1, false, true, false);
+			Test("49b", TEST_49_DATA, TP1, true, true, false);
+			Test("49c", TEST_49_DATA, TP3, false, true, false);
+			Test("49d", TEST_49_DATA, TP3, true, false, false);
+			Test("49e", TEST_49_DATA, ANY, false, true, false);
+			Test("49f", TEST_49_DATA, ANY, true, true, false);
+
+			Test("50a", TEST_50_DATA, TP1, false, true, false);
+			Test("50b", TEST_50_DATA, TP1, true, true, false);
+			Test("50c", TEST_50_DATA, TP1_TP2, false, true, false);
+			Test("50d", TEST_50_DATA, TP1_TP2, true, true, false);
+			Test("50e", TEST_50_DATA, ANY, false, true, false);
+			Test("50f", TEST_50_DATA, ANY, true, true, false);
+
+			Test("51a", TEST_51_DATA, false, true, false);
+			Test("51b", TEST_51_DATA, true, false, false);
+
+			Test("52a", TEST_52_DATA, TP1, false, true, false);
+			Test("52b", TEST_52_DATA, TP1, true, false, false);
+			Test("52c", TEST_52_DATA, TP1_TP2, false, true, false);
+			Test("52d", TEST_52_DATA, TP1_TP2, true, false, false);
+			Test("52e", TEST_52_DATA, ANY, false, true, false);
+			Test("52f", TEST_52_DATA, ANY, true, true, false);
+
+			Test("53a", TEST_53_DATA, TP1, false, true, false);
+			Test("53b", TEST_53_DATA, TP1, true, true, false);
+			Test("53c", TEST_53_DATA, TP1_TP2, false, true, false);
+			Test("53d", TEST_53_DATA, TP1_TP2, true, true, false);
+			Test("53e", TEST_53_DATA, TP4, false, true, false);
+			Test("53f", TEST_53_DATA, TP4, true, false, false);
+			Test("53g", TEST_53_DATA, ANY, false, true, false);
+			Test("53h", TEST_53_DATA, ANY, true, true, false);
+
+			Test("54", TEST_54_DATA, false, false);
+			Test("55", TEST_55_DATA, false, false);
+			Test("56", TEST_56_DATA, true, false);
+			Test("57", TEST_57_DATA, true, false);
+			Test("58", TEST_58_DATA, false, false);
+			Test("59", TEST_59_DATA, false, false);
+
+			Test("60", TEST_60_DATA, false, false);
+			Test("61", TEST_61_DATA, false, false);
+			Test("62", TEST_62_DATA, true, false);
+			Test("63", TEST_63_DATA, true, false);
+			Test("64", TEST_64_DATA, false, false);
+			Test("65", TEST_65_DATA, false, false);
+			Test("66", TEST_66_DATA, false, false);
+			Test("67", TEST_67_DATA, true, false);
+			Test("68", TEST_68_DATA, false, false);
+			Test("69", TEST_69_DATA, false, false);
+
+			Test("70", TEST_70_DATA, false, false);
+			Test("71", TEST_71_DATA, false, false);
+			Test("72", TEST_72_DATA, false, false);
+			Test("73", TEST_73_DATA, false, false);
+			Test("74", TEST_74_DATA, true, false);
+			Test("75", TEST_75_DATA, false, false);
+			Test("76", TEST_76_DATA, false, false);
+
+			resultBuf.Append("NISTCertPathTest -- Failed: ");
+			resultBuf.Append(testFail.Count).Append('/').Append(testCount).Append("\n");
+
+			if (testFail.Count != 0)
+			{
+				resultBuf.Append("\n");
+				Fail(resultBuf.ToString());
+			}
+		}
+
+		private void Init()
+		{
+			try
+			{
+				trustedCert = certParser.ReadCertificate(Base64.Decode(Trust_Anchor_CP_01_01_crt));
+				trustedCRL = crlParser.ReadCrl(Base64.Decode(Trust_Anchor_CRL_CP_01_01_crl));
+				trustedSet = new HashSet();
+
+				byte[] _ncBytes = null;
+				Asn1OctetString _oct = trustedCert.GetExtensionValue(X509Extensions.NameConstraints);
+				if (_oct != null)
+				{
+					_ncBytes = _oct.GetOctets();
+				}
+
+				trustedSet.Add(new TrustAnchor(trustedCert, _ncBytes));
+				testCount = 0;
+				testFail = new ArrayList();
+				resultBuf = new StringBuilder("\n");
+			}
+			catch (Exception ex)
+			{
+				throw new Exception(ex.Message);
+			}
+		}
+
+		private X509Certificate DecodeCertificate(string _str)
+		{
+			return certParser.ReadCertificate(Base64.Decode(_str));
+		}
+
+		private X509Crl DecodeCRL(string _str)
+		{
+			return crlParser.ReadCrl(Base64.Decode(_str));
+		}
+
+		private void MakeCertStore(string[] _strs, out IX509Store certStore, out IX509Store crlStore)
+		{
+			ArrayList certs = new ArrayList();
+			ArrayList crls = new ArrayList();
+			crls.Add(trustedCRL);
+
+			for (int i = 0; i < _strs.Length; i++)
+			{
+				if (_strs[i].StartsWith("MIIC"))
+				{
+					certs.Add(certParser.ReadCertificate(Base64.Decode(_strs[i])));
+				}
+				else if (_strs[i].StartsWith("MIIB"))
+				{
+					crls.Add(crlParser.ReadCrl(Base64.Decode(_strs[i])));
+				}
+				else
+				{
+					throw new ArgumentException("Invalid certificate or crl");
+				}
+			}
+
+			// Insert elements backwards to muck up forward ordering dependency
+//            IList _vec2 = new ArrayList();
+//            for (int i = _vec.Count - 1; i >= 0; i--)
+//            {
+//                _vec2.Add(_vec[i]);
+//            }
+			certs.Reverse();
+			crls.Reverse();
+
+			certStore = X509StoreFactory.Create("Certificate/Collection",
+				new X509CollectionStoreParameters(certs));
+			crlStore = X509StoreFactory.Create("CRL/Collection",
+				new X509CollectionStoreParameters(crls));
+		}
+
+		private void Test(string _name, string[] _data, bool _accept,
+			bool _debug)
+		{
+			Test(_name, _data, null, false, _accept, _debug);
+		}
+
+		private void Test(string _name, string[] _data, bool _explicit,
+			bool _accept, bool _debug)
+		{
+			Test(_name, _data, null, _explicit, _accept, _debug);
+		}
+
+		private void Test(string _name, string[] _data, ISet _ipolset,
+			bool _explicit, bool _accept, bool _debug)
+		{
+			testCount++;
+			bool _pass = true;
+
+			try
+			{
+//				CertPathBuilder _cpb = CertPathBuilder.GetInstance("PKIX");
+				PkixCertPathBuilder _cpb = new PkixCertPathBuilder();
+
+				X509Certificate _ee = DecodeCertificate(_data[_data.Length - 1]);
+				X509CertStoreSelector _select = new X509CertStoreSelector();
+				_select.Subject = _ee.SubjectDN;
+
+				IX509Store certStore, crlStore;
+				MakeCertStore(_data, out certStore, out crlStore);
+
+				PkixBuilderParameters _param = new PkixBuilderParameters(
+					trustedSet, _select);
+				_param.IsExplicitPolicyRequired = _explicit;
+				_param.AddStore(certStore);
+				_param.AddStore(crlStore);
+				_param.IsRevocationEnabled = true;
+
+				if (_ipolset != null)
+				{
+					_param.SetInitialPolicies(_ipolset);
+				}
+
+				PkixCertPathBuilderResult _result = _cpb.Build(_param);
+
+				if (!_accept)
+				{
+					_pass = false;
+					testFail.Add(_name);
+				}
+			}
+			catch (Exception)
+			{
+				if (_accept)
+				{
+					_pass = false;
+					testFail.Add(_name);
+				}
+			}
+
+			resultBuf.Append("NISTCertPathTest -- ").Append(_name).Append(": ")
+				.Append(_pass ? "\n" : "Failed.\n");
+		}
+
+		/*
+		 *  Trust Anchor
+		 *
+		 */
+		public const string Trust_Anchor_CP_01_01_crt =
+			"MIICbDCCAdWgAwIBAgIDAYafMA0GCSqGSIb3DQEBBQUAMF4xCzAJBgNVBAYTAlVTMRgwFg" +
+			"YDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsTA0RvRDEQMA4GA1UECxMHVGVzdGlu" +
+			"ZzEVMBMGA1UEAxMMVHJ1c3QgQW5jaG9yMB4XDTk5MDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" +
+			"EwMFowXjELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" +
+			"CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANPzucEztz+nJ/ZBHVyceZ2q0pUQt4TO2qPlWAw+" +
+			"TotWvz6qIS1QE/7zGS56yxHP89O4X1efnZeArx2VVxLfNNS9865N53ymINQETtpjYT49Ko" +
+			"03z8U8yfn68DlIBHi9sN31JEYzoUafF58Eu883lAwTQ6qQrJF4HbrzGIQqgitHAgMBAAGj" +
+			"ODA2MBEGA1UdDgQKBAirmuv5wudUjzAMBgNVHRMEBTADAQH/MBMGA1UdIwQMMAqACKua6/" +
+			"nC51SPMA0GCSqGSIb3DQEBBQUAA4GBABZWD2Gsh4tP62QSG8OFWUpo4TulIcFZLpGsaP4T" +
+			"/2Nt7lXUoIJMN7wWjqkmYf5/Rvo4HxNcimq3EkeYcrm1VoDueJUYGvRjcCY5mxkghI27Yl" +
+			"/fLKE9/BvQOrvYzBs2EqKrrT7m4VK0dRMR7CeVpmPP08z0Tti6uK2tzBplp1pF";
+		public const string Trust_Anchor_CRL_CP_01_01_crl =
+			"MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDFRydXN0IEFuY2hvchcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAiMCACAS" +
+			"cXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEwCgYDVR0UBAMCAQEwEwYDVR0j" +
+			"BAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAC7lqZwejJRW7QvzH11/7cYcL3r" +
+			"acgMxH3PSU/ufvyLk7ahR++RtHary/WeCvRdyznLiIOA8ZBiguWtVPqsNysNn7WLofQIVa" +
+			"+/TD3T+lece4e1NwGQvj5Q+e2wRtGXg+gCuTjTKUFfKRnWz7O7RyiJKKim0jtAF4RkCpLe" +
+			"bNChY=";
+
+
+		/*
+		 *  test1
+		 *
+		 */
+
+		public const string End_Certificate_CP_01_01_crt =
+			"MIIChjCCAe+gAwIBAgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMY07G8M4FkOvF+6LpO7BKcDuXCKudfl1+bKSowj" +
+			"2GCza8uIiMfYSH5k+fYb43lGQeRh9yVHcfNQlE7yfGo3tgxGv5yWpeKvDMqL8Iy6Q0oIjm" +
+			"qH80ZOz21dUkermcckzTEOfe/R2fNpJPv8M24pq29SdYAqu+CpLDHFtws9O+q1AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIrNv88bwFLtIwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAK4hP" +
+			"goWtZbHf6qWfRfmrPrz9hDH1644NrJop2Y7MXzuTtpo1zp4NCG4+ii0CSOfvhugc8yOmq3" +
+			"I6olgE0V16VtC5br2892UHYZ55Q4oQ9BWouVVlOyY9rogOB160BnsqBELFhT0Wf6mnbsdD" +
+			"G+BB5fFyeK61aYDWV84kS7cSX5w=";
+		public readonly string[] TEST_1_DATA = new string[]
+		{
+			End_Certificate_CP_01_01_crt,
+		};
+
+		/*
+		 *  test2
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_01_02_crt =
+			"MIIClTCCAf6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAxLjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDWOZ4hk+K6NX/l+OiHC4pfKCWFt+XM2n/TxwkqY+mt" +
+			"j9Co77rPPPtVA7mDKU4OiYT74mIWH52HQBZr+PRmOFh0Z9S1oTpLbxNLCDc6OmQKBo6iex" +
+			"SIt/jOatFFmzmTZ78Kq9s3nfrOVA83ggmPDTPkuG5GwcxPgFq0vRmAJ0CESQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI5o5Am09NlOYwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEA3C7Ye5/Te14LIwo/LK2fnpobbQA3dhOn5UgqZ8lKbQ/HV1D8/eU9dK" +
+			"2v5gW43XvFq4whK0WKLBvBFchKtp9T1QX3CI2WCqdJRyqla6TkQsS36T17/ww2nzy1853Y" +
+			"hfDYNsge5XW8YZNfNjjVxcR3RnyFxPax1YIlISiGdI0dnag=";
+		public const string Intermediate_CRL_CP_01_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI5o5Am09NlOYwDQYJKoZIhvcNAQEFBQADgYEAl26W" +
+			"g1Gqq3R93XPjghABVocfeIi8zcSJ0YAKqbifh5V3JCC8Piy19GzZdL244GqBDls44IAhKj" +
+			"YuXN2mSohdqwULbye4agAgfl37XhhwsBDTYwaJiv3njFQ6Ml7KJ3STmoIpmlLvrXibDuHX" +
+			"ocuNGo72ckhOdBpXd+PhgGuoTis=";
+		public const string End_Certificate_CP_01_02_crt =
+			"MIIChjCCAe+gAwIBAgIBAzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALwJrZT6bJXQnZzc3socZ/mNsEag4BTdym99ZCP2" +
+			"3PGsTCfV2z7+p4DehIFrn/N/a1d1nvyqRqpQGPU86tl1CWgFtXS+zCctDR71P76bjd6yef" +
+			"5vxxdO/SBIRHfQTjM8F3BTLkrC+PVl5wbaLcEXRORXrFvBvsj0oqwZ4C8ZObh/AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIf5mSjuNhs/gwEwYDVR0jBAwwCoAI5o5Am09NlOYwDQYJKoZIhvcNAQEFBQADgYEAK7wd" +
+			"MyLlIZ/Qsqj3/A3Gat0d5BORtFTZH0VdlVVOWN1JCZxrnjeIFB92NNzUROemxgBxzneuWN" +
+			"SlYlcpTk25pAbs6RMdbT8dovKQkQkF2TXeQ+4qktFaLQntVT8UsEzHR4Diw0/gH8tseGqF" +
+			"F7FyiW8ni6zInSO+embUKiibj9I=";
+		public readonly string[] TEST_2_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_01_02_crt,
+			Intermediate_CRL_CP_01_02_crl,
+			End_Certificate_CP_01_02_crt
+		};
+
+		/*
+		 *  test3
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_01_03_crt =
+			"MIIClTCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAxLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC4RZ0R82sA+BfyynFeoIDG7c5IlZ8HorEv+O4Ij3Oy" +
+			"7FR1MB4no8hDEBPBf5fCrAR/8PVxCZjVj2HOwnSAqUQgxo6WPcmkabux12k8kK6yeKq3b7" +
+			"u5fL6tb7eKElQzsz8Je4z4rCDkI10vV+X0VZ5Ip/Es428dw2KoN8eyGmw3+QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIz08WhMpG2JswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAQ+iqlFvbvDejO/m+RCHh2UuUau1FuABObkPOu2Tv9yTWvTSWDRygdO" +
+			"LQRiOLsjgrdXPdbDutVGjllBoTN8cdz3SWjCpampg5TBikArxmNEYMDQvL6n2lkUcetRJR" +
+			"gQ7TYLvFj9+SycKXfM5CUXAyCfcU/QwDghhZgc99AuDZtJc=";
+		public const string Intermediate_CRL_CP_01_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIz08WhMpG2JswDQYJKoZIhvcNAQEFBQADgYEAoyO/" +
+			"xcpJ0Obj4rTXhHFd7XMzslt79njkEgdwnon9BaYB3xSmkEXCMwLMurrjVYKaB6SWAiPeUv" +
+			"G7ScDHJE6UFVJwIt4vP/M7gTOJ7uak33aWi9e5DeIuLqE6pFqTGu+uoBkkd82SHg2GhJhZ" +
+			"VXDtJ3UcO/3JQPbslc02s9HiRBg=";
+		public const string End_Certificate_CP_01_03_crt =
+			"MIIChjCCAe+gAwIBAgIBBTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDEuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANAD1vQj//4BGEXW1Q7HX/AUyFJFyHoYcvg5y4u/" +
+			"8Sj6okriXj3knnBKDiJLpKfcsO5p5MQS5QzAc+lxErXD+duiw8lm61hj0StsRzhDFsaC1g" +
+			"akjzU70R2Tmz/djUnqO3aa2wICc4NVAXnIMMsH/b6XXFZpC0/C32TPTv9aa9mrAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIPw2wltiRqz4wEwYDVR0jBAwwCoAIz08WhMpG2JswDQYJKoZIhvcNAQEFBQADgYEAln42" +
+			"iR3eHyazF8CRjS9Jnas/26MaBtjUyDtcSjTVDWFlccwrQ7TgtzjkNm9fCmgSyvryDnUYGM" +
+			"DoEjwYNLIgtCAkVIEBTmJvlqiPHH+tV5oJvIav+Fn8okHpuuK44umDcdKiFWlOyxrShxzV" +
+			"3Bez/eHklaPTw/VsVhyh+Uru5zM=";
+		public readonly string[] TEST_3_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_01_03_crt,
+			Intermediate_CRL_CP_01_03_crl,
+			End_Certificate_CP_01_03_crt
+		};
+
+		/*
+		 *  test4
+		 *
+		 */
+		public const string Intermediate_Certificate_1_CP_02_01_crt =
+			"MIIClTCCAf6gAwIBAgIBBjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC/lQLtWKzklgYuzhjMiK2CzFmzODsEY/JIVNdn9T8M" +
+			"W4ufpGwnfIV62EUHCFeMYydKBm8Hyjbjrz1otINJmrGL5WSAX1/UPtHy1chgXOsFYD6nAH" +
+			"jZAJJGw74nUbKw5+L1wUHU8qXABaaTrRpS1UdKSq4TCZ18NCjC4Oxcf/yDdQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQINsJcxaBqdugwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAOQP3iUX7FtJlL9nvu4F+8o/N5vr+OB28OsbYtW+Q1FzEfjkUGtT9Ri" +
+			"teradpN/xUnS/oj3BfqFtNANkYKrBeqRtm2VeOC3kdCVFnWFME2aoRAQZbWvOwCFc3yLA7" +
+			"JBdENtDNI54yYHMHPA4/2CuNQq1Iu1ektAS95DIe7ddxL18=";
+		public const string Intermediate_Certificate_2_CP_02_01_crt =
+			"MIIClTCCAf6gAwIBAgIBBzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMi4wMTAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLUNQLjAyLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCx/mIo1Ma/IN8OR7KOjclvIwsv0JFXD/T258DruDZU" +
+			"uGoYiEbAc/ZN7R8OHI7dnv9pBfsvyEl7m2DVoLZnP0eXJTHjdZxb1TwPHoSIysi9u3xWlP" +
+			"Rg+v+GGfKLB9pL0m8SZh97SngerZI14w7vQy0kkXziGatSpBoXtWNmsHJNuQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIoI0mSmDmzZUwEwYDVR0jBAwwCoAINsJcxaBqdugwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAcfs1pH12Qwdhv4NOJO2xxgMZZo8+A9Zl9c7RxsvuoZOOyCxoE9wT/l" +
+			"PdUpGoGxtIPoWQs1qXEXnAlXJCXjLCJUHIG1/E6gQUXW0Ty6Ztpc5Dz06pPTN2gt+41B3J" +
+			"sL/Klqc4iyCaWr8sYgEPQ8nColWRmIwk9gAasPNkNhyxA3Y=";
+		public const string Intermediate_CRL_1_CP_02_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAINsJcxaBqdugwDQYJKoZIhvcNAQEFBQADgYEAlBaV" +
+			"VfrZqvyRhGXNYFik169nBHiNfKpw8k1YgFAQeNYdmfScq1KHmKzDhsx9kQteczBL7ltviK" +
+			"TN3CKlZW82c16mfd4yYx0l5tkU80lwKCHSUzx92+qrvYjSMup+bqSsi8JhqByBf6b0JbKf" +
+			"yx53Vpw1OCzjxrVHcfHPx8Q/vR4=";
+		public const string Intermediate_CRL_2_CP_02_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1DUC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoI0mSmDmzZUwDQYJKoZIhvcNAQEFBQADgYEAhAHP" +
+			"QxpcrTTN0GXeOwoMXuQUoHMvezEpM0BYOVLzI3KbRXWa9iWZINr99cRQvonMtOGkhIH3iS" +
+			"wSNbsjmF9HX5UvNzrofOWataVP+macpCuNlK0NS3xxJjKRWOB9C1Ib7tiSSrQqIPcchlF6" +
+			"vofy2ALEL6Usa1UTVYMhzGYnVZU=";
+		public const string End_Certificate_CP_02_01_crt =
+			"MIIChjCCAe+gAwIBAgIBCDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1DUC4wMi4wMTAeFw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOzYq2murB5ZjQd4wReI51Lc1F5VwK90OMGRfi71" +
+			"YvwdRjgCudeDXZGW5ayid82y+eTDKFSzo1Li/BPTUXMpeqHHMCmLeefqxAWmz3aDoilF8I" +
+			"Q53PlejnXJdntsal44w6WdP6ssiXlwzcZDnobAfuDTPgsnWWfzAkr1/LqEw/QZAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIP5tVdEyxotcwEwYDVR0jBAwwCoAIoI0mSmDmzZUwDQYJKoZIhvcNAQEFBQADgYEAkVx9" +
+			"S/20Hir8qMnfMpMGTgMKoVeWoljxim83IkNs1Xqe1oLGHdyDUA66uF8wPkoTqGrfDYvgBa" +
+			"5Mi0iJREnMWoiWvCe467+L1b2gtvRBMl9bcRj40bvelk0Wn4lBl3VuKXarP5M0PKT5OWvN" +
+			"2cPLNeXHvV6ZIrC4rmK2ISpIXX4=";
+		public readonly string[] TEST_4_DATA = new string[]
+		{
+			Intermediate_Certificate_1_CP_02_01_crt,
+			Intermediate_Certificate_2_CP_02_01_crt,
+			Intermediate_CRL_1_CP_02_01_crl,
+			Intermediate_CRL_2_CP_02_01_crl,
+			End_Certificate_CP_02_01_crt
+		};
+
+		/*
+		 *  test5
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_02_02_crt =
+			"MIIClTCCAf6gAwIBAgIBCTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw00NzAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDHJmlRKb+mjc61iiqGe9gx/VUMLNmGrXGRYKMmYSxO" +
+			"Q5sGLoztd2XtEgtZEPwvzd9KLKGP3XmgTrc4BGohqoFoG9Qb+w2ZGFwVC22GpeSoXc+J2u" +
+			"2t3uRKYgboHpB0Jk42XLy+2wSEtS+/er7cFu2ufdPsvT4J1AqiuZSco96vtQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIBvoP1E6PGiMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAmOyFq2vZrUNDVWRcyzYvZhs1uQ4zgXtfqnPE0V19RgaYffCrSCI86z" +
+			"5kyDUyZwbGABMxBaVxEw536MesyDTdZdEVw6lN5RRtxr8/WEiSH6oI6t0xNxuNOkSNpz4d" +
+			"28HA4UfUvtXK8RK2YZnPAd6UXsRUPBPXKEpzy4v/9RyihSg=";
+		public const string Intermediate_CRL_CP_02_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIBvoP1E6PGiMwDQYJKoZIhvcNAQEFBQADgYEAALlA" +
+			"f3IDWexcdkMQHWTdGeFe+bG5dBvVPL5ZyQUw9DWbLwrjw/Jm4v9t+HLjETLSymsFT4bW21" +
+			"OwnEiAAdaKT96k5t+sTyU5QQ6HL/jRXLHLGdCQgMFCglm5iNqaCLIFoMAVCaFkYtFUE3m/" +
+			"iVt+319JOh5UyshMuWrAEW0IGGQ=";
+		public const string End_Certificate_CP_02_02_crt =
+			"MIIChjCCAe+gAwIBAgIBCjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL/Src6e8qXwL+KJs5+v+JsakZdSDqMAFJUMfA2O" +
+			"OO2TIqcvDFHzqesX+G+28MUwy6++ux07CD3FCaapgzBN4zO4RfKcamxFReKMKcEvNVVCOO" +
+			"wO4Lvku1Sad14oYyGLOMzZwZFjRp8paaz5g87k70EOPBLeDlFMcch36czw53sLAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIPoHc2Sfk6XUwEwYDVR0jBAwwCoAIBvoP1E6PGiMwDQYJKoZIhvcNAQEFBQADgYEAFHhm" +
+			"o6QRFdO1x1wp7Jb1QQAlChFfP8MrGVNK04Ur8f+wfkwIypTDifJ0AoFpjcM3Ohu9Ixvb9q" +
+			"3kCSIWKDnWtDWw1/dN8mPL5If5gGqPA0+wRbUKVKvduOg7hKr4mWjKw7oYiaJuIIoN9RRZ" +
+			"ejzltd0NEaODNPW/JaKeQUVgZbY=";
+		public readonly string[] TEST_5_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_02_02_crt,
+			Intermediate_CRL_CP_02_02_crl,
+			End_Certificate_CP_02_02_crt
+		};
+
+		/*
+		 *  test6
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_02_03_crt =
+			"MIIClTCCAf6gAwIBAgIBCzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCaJ7NcOvb22F6HjMF1R/AORa4+pKFfFfd9teXPpVWC" +
+			"9InTq+alY11QaSj27Qg0znOIItmf2W/8Dub9sjnbg+SgAkoV5+CAkplodRNC8AbD4x8rh/" +
+			"fioQ8lb0Qb4Dn9I0n2wjOgitmMRdE2uW4uwVpH52vsMyenbDVxVI7jA4NS/wIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIC2T+/BkG93AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEApr6kDXVY5jYt23wC9n3LmhoxDoWh8cBQxcWmr1wpVxIrCbaP0/y00a" +
+			"29wbewKfucUoh/W2OfjNcohjpKRrnVmOpi5vN7SmbZIHaxbKLzyQ7JwF17aznyCSZVrGpF" +
+			"A/S49T5rlCm8KDBcc2ym7gRJzwUApbC0Wws4Pg46czrpQlg=";
+		public const string Intermediate_CRL_CP_02_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIC2T+/BkG93AwDQYJKoZIhvcNAQEFBQADgYEAlBFY" +
+			"vPxhFYsjFOIfQkd7MwKIi7vgPgoWTP5f+QlI0ison5n4N3rYJv31hTZRRRP99JZce1hY6J" +
+			"Qiv1OtkpG7VfQIhr0FAGxTNaJD6F6rLbGjG8cap4+VibFQf5gZv0XQcyW4akYiRqSXImYn" +
+			"NVlNyaxiJja+5GA9XVqvWOjjz4o=";
+		public const string End_Certificate_CP_02_03_crt =
+			"MIIChjCCAe+gAwIBAgIBDDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMi4wMzAeFw00NzAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMlW6FOLwhRsKZM6p0ww4QEWjQzjpjYhKnz3BnLw" +
+			"SdGZqMe4wzZnDWc/0eyDOMCSYXIWQhlDMqQn2zCVPbDKzMRkdEeRSvE6ghhYP/hn3ipjSw" +
+			"D8QwaqofCp0sFkbDPke+xD2tMhLdUyNKynPjpSQmYtfoA98PD7so3cSAtrYuSDAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIc/X6kp7teCQwEwYDVR0jBAwwCoAIC2T+/BkG93AwDQYJKoZIhvcNAQEFBQADgYEAStub" +
+			"g3DzhJgzYO+ZmRc0acldZGwZFm6F1Ckc1JzQDgVHU0bnCANgBcJj49UV2MwbNKPQdVzdwo" +
+			"c91rfwrSY/PrvVQ9tUonZ28y/esFRBAdJTLf4u++p/gI3vfCvEXa5xVTIz1Hc+iKzAGKrI" +
+			"cveDHy3ZZluQ3J6tbHs2BhnQFXM=";
+		public readonly string[] TEST_6_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_02_03_crt,
+			Intermediate_CRL_CP_02_03_crl,
+			End_Certificate_CP_02_03_crt
+		};
+
+		/*
+		 *  test7
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_02_04_crt =
+			"MIIClTCCAf6gAwIBAgIBDTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDgZy2Xs5pIoJrT7GuagmKLrn8F9rj8p8w2wELorGhM" +
+			"1HJMVOurH+o+y6RXd0oMGJkKNrhjEnbHKm3PBYiLgpCjVEcFNhQF1OOxJ7RdahvA9ifsuw" +
+			"jV1TxTGq35jeaJYASRXb2TiNfzuPWSVm0MWr5zz+YB6NNuvjxwEBgZvNiV8QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIWAOnkHkwSVkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAMiHozz92EOhSXU/krwQVs0GNEWoAUH3LHt70Zr01dFzEF6QhA/wUa4" +
+			"+V4XwbMob+q4zGnTHj+tL9ChGWi3NDGELQ4cN64OMPsToGKkepLy+sDwdm9LaUP1bDvPxd" +
+			"v2hjlskJ7TEu4+6ltXSG/k36Jk8C0/I/ayNGbYcEcLyes3s=";
+		public const string Intermediate_CRL_CP_02_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIWAOnkHkwSVkwDQYJKoZIhvcNAQEFBQADgYEAVtCi" +
+			"IocktnWOwWiaOc7tTUJvvH5+IYVyB/XhmMhF7cDbL292gyrnuh1+3+lHwZQBPoF9kzF0vt" +
+			"WaweG7mDvYKxENQODdph/VcnypgUiFTWRTIPB1ZXfCTMWYf2QSalpHRDR4vVsqF748QbcG" +
+			"E9mbzvLUz6NDA+Vf8wEwZehqSDM=";
+		public const string End_Certificate_CP_02_04_crt =
+			"MIIChjCCAe+gAwIBAgIBDjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMi4wNDAeFw01MDAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDIuMDQwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALBX5GIQtvwswWwMDDPnphIk1rJSbcq7iClXLM2E" +
+			"kgvBu+hbOzb0v9mtl0KJB71TWJCfwceVQiXc3Gk+YduujAbZRVTkROf9UOWD9bfrI7g+52" +
+			"g4ms2n7evCO33b+kGEf4I014xl8dJDWtHK9Bhr+569RW9TzO06IeVeTD7whxMXAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIuKXv5WkUTWAwEwYDVR0jBAwwCoAIWAOnkHkwSVkwDQYJKoZIhvcNAQEFBQADgYEAiu0B" +
+			"yR5Ru8qVsgRqkOpCvrJnkqBAImbbR6+BUYH0juRxxKzKnbFOjU6a9WvkKpEBB8Q2xLynPN" +
+			"68ecLpnOynx3xj2sWWSVbsRKPy0iOesQblKrq3yHAm4lhzoWA8t1Xz29Ko1WxylDhyxGpR" +
+			"QAWsyGVCfJFlsZE0ibw3erlWTnA=";
+		public readonly string[] TEST_7_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_02_04_crt,
+			Intermediate_CRL_CP_02_04_crl,
+			End_Certificate_CP_02_04_crt
+		};
+
+		/*
+		 *  test8
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_02_05_crt =
+			"MIIClTCCAf6gAwIBAgIBDzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAyLjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC2d80bD1RounqjKizkZJYPFUuVWZQ8W2nZDkEp8qR9" +
+			"fRWCAGOZGs84tgHj5gasmxy1mxJc9ogyQ2mcZhJRitRm5LVNuGevO6JmfqYtJxbW54aZGE" +
+			"5AWSRXqjJKJEih4VmPjA3vjQaSZSZJnu0DSnO82qWfu1ZUDlvIG6dfKJWRQQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI3uNhI+QuI4owEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAG/+Rpk8dYrSFdaEO8Ch5tuvvKTOMi7W/DRA4B4xR7WyRJmosPB+37c" +
+			"teGKVzqFND22Xc8xQH/b/nxYW08sCSLAfN0cRusoSWwWSRtPO2f9fyC/BqCy2B2kQLFNPM" +
+			"Bk22jNFwLqPUeZn1UHN05RFAqVx325kpl2m1V7tw/mrXATI=";
+		public const string Intermediate_CRL_CP_02_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI3uNhI+QuI4owDQYJKoZIhvcNAQEFBQADgYEAWZUI" +
+			"2VGY4pak0kICONP/CKvamYFs5txJfR69AC5tEJ+Fy3PmSeHkLUZf/oc9d8EEyr0MsIjRHj" +
+			"N4X4MquMlk4FflZcc8GblQK8LdXBK4Dy1SiXHA5GB3U1AmgzAzEQGwGRZnzWP5+rJ65upX" +
+			"vksAYyPQmruRM0O5sElctPn6B+Y=";
+		public const string End_Certificate_CP_02_05_crt =
+			"MIICiDCCAfGgAwIBAgIBEDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMi4wNTAgGA8yMDUwMDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" +
+			"EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" +
+			"CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wMi4wNTCBnz" +
+			"ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAviLKpW4iblWNLQfmBJJ+ruMgygmjRWfoFGya" +
+			"Ndv2ma0Ugqm5xXq8c0orbnezwSp+tnzZZhG5KDNZr5+z3krCkqOGGzuUvVLqeJxPOLu7Js" +
+			"y472nAA7+FhwfZrXUI+Vg9F4qF+Ye81ivDrYVAEmalCpCyHOAKdvwkwQjRucifu90CAwEA" +
+			"AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" +
+			"QKBAjgph7BA5L7dzATBgNVHSMEDDAKgAje42Ej5C4jijANBgkqhkiG9w0BAQUFAAOBgQBr" +
+			"MDMv9NWCTIQ3blMEqPiEyjiBhSJl88Cu797P4lIn+gc6E+0vZp61X7B2k5CHgsnxyVLK5e" +
+			"bwl0bYAPKwRI9yzHLrj71RNw8HA7PCRPn1GNrtBBbIpLE0/sqLo51UPu/377+CnzYhIycL" +
+			"tvS0KDLUTDSY/OowDcplF6Xwnt8cUQ==";
+		public readonly string[] TEST_8_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_02_05_crt,
+			Intermediate_CRL_CP_02_05_crl,
+			End_Certificate_CP_02_05_crt
+		};
+
+		/*
+		 *  test9
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_03_01_crt =
+			"MIIClTCCAf6gAwIBAgIBETANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw0wMDAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCuF8mub5cgUYZytrRjJ5Rhc2fgazGxWIj6EIKzeSpo" +
+			"FwScItRX9KxnTIXEBTguBk7eQUsbN8yu49/Mlq45EAnemyZRBWzLFLYLPCco7pyTsWm7Ps" +
+			"2FAGJ3vE9pC9xaZC+KrwF3Ho+DZNDwhj5InXTP8pChAIPfB8/7V/2mk0lN0wIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI4mI6Ojs0onswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAMVGzU6f4YOHpHla+YuGCjHOUZYrA9J25G3UFFoPr2JZEG+Fb5hRQUh" +
+			"4S1qUQKXn6dpVua+qTJDk3Tg2N8OdIHG/gy0hvYHsxhLCSDQBsfPN7p3FClM7r/VHOqgAN" +
+			"vzT+KYvxx6gwn6O+n7ERkrBIfkyrGFhnmjx3+VOCc9P4SDE=";
+		public const string Intermediate_CRL_CP_03_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMy4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI4mI6Ojs0onswDQYJKoZIhvcNAQEFBQADgYEAfwYf" +
+			"4kAG4srB2VxWimJs1HwXTaPDooellQclZ5hP/EluT7oe03+ReFef6uXbHt/xRdeaoQhJGy" +
+			"SP8dWf6UIbL82oaSYqChIvAZD6zTMavEgSET0PlUsK1aEMTpMEtKPvedFSOTNBaMNvMzSW" +
+			"t5xwurn63qyXTOxHf4m2L4w8+i0=";
+		public const string End_Certificate_CP_03_01_crt =
+			"MIIChjCCAe+gAwIBAgIBEjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMy4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJ/ALaZ+MdNxKDH49+7jUm+17DII5QQEfjk8IaEU" +
+			"syApOhsByOG06HPItiBEnnfDDxU5kjsZDtw/9LlouBocNXAJt+ZmL3QYyOgeH4SQ4f21rw" +
+			"7j8fw57gUkP5oWhEc0loXr/hB92hoKbsBoRpv8F1zPZcPNLUnyUzqLH5+CeIibAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QI822isg/wPCowEwYDVR0jBAwwCoAI4mI6Ojs0onswDQYJKoZIhvcNAQEFBQADgYEAilIn" +
+			"OD0iQrLrHRkO4zr9S9VXAJXJV3l9wfbLBweXM3q/zt4HGKBw4Wq1Yn+AfDxXrBtJA5hP5e" +
+			"d7CDd4eM93yeKozdZCLNZfUM8sJ2/MRh07tvwJ19e2STklED8b/ndmr5my8H8jjJDaaYww" +
+			"qTSnXqpcqsUsj+kV4Mk0DvVWT3w=";
+		public readonly string[] TEST_9_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_03_01_crt,
+			Intermediate_CRL_CP_03_01_crl,
+			End_Certificate_CP_03_01_crt
+		};
+
+		/*
+		 *  test10
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_03_02_crt =
+			"MIIClTCCAf6gAwIBAgIBEzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC4AbP8gDUUcIa8w4pEsGgbYH2sz08QMUXd4xwx691i" +
+			"9QCcyWSovQO4Jozeb9JwtyN2+f3T+JqZL/gwUHuLO2IEXpzE2C8FzQg6Ma+TiSrlvGJfec" +
+			"TlSooFmEtD3Xh6I6N5PM1fpyyY2sOOhARN5S6qR9BOuxkBAqrAT0fgqD2TswIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI97nJCqq6+kIwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAWwpfh9oOOvj9xHS0zcczaUIHTkpjgk09I+pERlu0Z0+rHvpZGge4Ov" +
+			"NDFtMc4TgthGcydbIwiKogjtGBM2/sNHIO2jcpNeOtNKLxrzD4Y0Ve164kXBu9Mmsxx4sG" +
+			"7XUXZWgiOPfu/HmyPVdzbIReJdQO515SNx7JdgVyUkyhBxM=";
+		public const string Intermediate_CRL_CP_03_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMy4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI97nJCqq6+kIwDQYJKoZIhvcNAQEFBQADgYEAC9Hv" +
+			"NevV6/Oz3wcgEbDgZYRKJRdr4OW4Es7R4ahjz3sH6GXZ1HiEjx2+frmp8LMshQ4D+hpjRk" +
+			"drSPko1M4a/fQCYxbonZ0xjpYw067dwLmr56+GPJAxkzcSmFKXx+ejyQpG+9+qCR+zm98V" +
+			"lop6besAaGUjZKnYShIQOfNzDZk=";
+		public const string End_Certificate_CP_03_02_crt =
+			"MIIChjCCAe+gAwIBAgIBFDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMy4wMjAeFw05ODAxMDExMjAxMDBaFw0wMDAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMJMiW+G4bgoRaYz2OUu/+PQ/yp4JgFOB3Vegf5/" +
+			"vIrF4gsnoQxOCCsO5JTLrbS5fi3COjvM5w9/SZpNHtSfyWb9afmx4DdrT1bNjma7I6PCid" +
+			"yxMzX4iTLeaMRnqBk4A+/0Wf2+4VzCqr8aViIiQ7u2JfZiTQ4dZxDoUW6G8lrbAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIEjny2GzFXGQwEwYDVR0jBAwwCoAI97nJCqq6+kIwDQYJKoZIhvcNAQEFBQADgYEAJw3T" +
+			"3aL3pYbZhswgshOvJ9Y1qv65R6rClSxB5lqBw6+Qki4ZpW57NK8LwaGS03XzDUPaDi4/9R" +
+			"hGCHpP24fIskS4n4jNZgKpGtt6VEVorUH7cOLNCw2cuwMlKbkyZnNdx2JqTMMlHzNJ3cmy" +
+			"aX3F70IY0OZbwCKdUo/uMVC6hss=";
+		public readonly string[] TEST_10_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_03_02_crt,
+			Intermediate_CRL_CP_03_02_crl,
+			End_Certificate_CP_03_02_crt
+		};
+
+		/*
+		 *  test11
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_03_03_crt =
+			"MIIClTCCAf6gAwIBAgIBFTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCjLYKGKEMJgC/r0NH7vubQZ5qPEFEEN6QdLUWWqf/O" +
+			"Yqo9hboQq6S8dFHp3DVR5x/4NOdNRjsTABbXsnz8U+L7+4CorhDhXj29weGMYIIfJ3XSIb" +
+			"T7sE/GOPmXeGhrTv2zucI1j80sN5nTEoiGFm10LQqAgoyV46BxDltf3/D7wwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIhCIOyzfScpAwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAA18kQijoJebmTQS7n/q/fQx2iblOJaJAWQLHeGCCGqKxCjUpOxuD+y" +
+			"xMspmTKdQqEkqQ5vpHdFYQ5MYuecqAdp6woWUNQGVd4HHPmHsAW3Oppwb0yLggYs8IVHjm" +
+			"dNO1pYb+YYciCKBtX8D1OnedIRcrQmDMJUjbfmAEv/4b0EM=";
+		public const string Intermediate_CRL_CP_03_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMy4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhCIOyzfScpAwDQYJKoZIhvcNAQEFBQADgYEAk34j" +
+			"SxMr8p1h1qJWlfoh4er9pu1AkkHujovan6Ctx89VwFdOS5Kw82OCvD+nmJAHrFuncNlClf" +
+			"51G8FCEAFLhMNwic4WAxrBX15hcUTaWk8Wj00dfUFwjG8/Kv3QUCDBN8f3KC8/oBeORRX9" +
+			"dHW5ei2IUKuD1ITCeIoyRDBxQIg=";
+		public const string End_Certificate_CP_03_03_crt =
+			"MIIChjCCAe+gAwIBAgIBFjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMy4wMzAeFw05ODAxMDExMjAxMDBaFw01MDA3MDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDMuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALSw1Ey7kzFzzjMS4oTSrZH/95NMHLxtUSaVGMCy" +
+			"0q2iLfGZ79eTS9megQUranYlIuK411yvFtskbFKf0idMKBtM8nX3Rxubm5EnbnpgvNrBEg" +
+			"0FbOPqpSaR+8pxZ6lweB45tkzLU3OZeAZSpGOY1UvT/htn6Ae8JQAVajSvYyfNAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIF014kOHikvcwEwYDVR0jBAwwCoAIhCIOyzfScpAwDQYJKoZIhvcNAQEFBQADgYEAdLMM" +
+			"zGPPvBLgPbhn2tba/7HiaZaayHIxTXmpW0KAhP+8hwapOitrtLGPwqVtxQ3GoSMZJPMDCV" +
+			"WsrT3OZm27G6ytqqNZ2ZO49UC7WwQ49TVlN79Ui9RZIBnRzlMIDNKsyuohfSRhFZTkWdoH" +
+			"/y8ulY8k4xBThV8e8IRgtYj3nhc=";
+		public readonly string[] TEST_11_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_03_03_crt,
+			Intermediate_CRL_CP_03_03_crl,
+			End_Certificate_CP_03_03_crt
+		};
+
+		/*
+		 *  test12
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_03_04_crt =
+			"MIIClTCCAf6gAwIBAgIBFzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjAzLjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDbUii3czeUQ2zNlxvrhnJ0LcBGxCDHFr3xx+plDg3f" +
+			"uasDKCY/VjCLEfQ5a2oqcovvGKsd2CPXbCFJtimW1R7Dvt+a0y95fppsdseorYDikiBlOj" +
+			"ja6LR3Cz3bslYc133C+W/MKHMJ0tdvtTk+SJrq7lqs+iv/b/xHC3k/gDjIswIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIFNw3o1kc4XkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAn/pr7/noYyjXSKEe/eLk3l4Rb6PEhNAnzySmxGkjIjWKAgh5IVYSGV" +
+			"KFO/FaNOiYkRFHwXZFNj71q7gbM+HwALurN0Mr/MUA1TSpPy7YhFL0SWq3C3XsC/dVJ50b" +
+			"HmTW+dGcxboX0h9HeKFxp3VyOY/dUut2oc+s/TnmqQII1CU=";
+		public const string Intermediate_CRL_CP_03_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wMy4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIFNw3o1kc4XkwDQYJKoZIhvcNAQEFBQADgYEAMoJ5" +
+			"jGE1AxxfluixG8Sk7H4W2rqSEkQyNHfnlKSMbh9KZA3evI8HGKGGfkbBNoe4/HauZ4NVFw" +
+			"FXgllCp+TI8Qd+HafFoDv6ff1K7T86p6r7tE3AEM1XmbnfohP3/ivpIzustv/f2rqjxILK" +
+			"Ldvrth2/OlNygwY+D54lcWH1DX8=";
+		public const string End_Certificate_CP_03_04_crt =
+			"MIICiDCCAfGgAwIBAgIBGDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wMy4wNDAgFw05ODAxMDExMjAxMDBaGA8yMDUwMDEwMTEyMD" +
+			"EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" +
+			"CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wMy4wNDCBnz" +
+			"ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuSL9tB1JW6JPUO2Xw6TMYkPX41lru3EPyYko" +
+			"YgXy4giy6LGoqbgtskHehD22v3rfWjqOd9iV2PBio/vYE4zEz0H0n84dpnBvog6A1AlE19" +
+			"PkQ1txjzIA52FQIRwRfZ38LaulQEfJ0a+fiRHQiM960O3YvHXV+GEbNcw4jo8b0sUCAwEA" +
+			"AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" +
+			"QKBAh9/WgM+UT6bTATBgNVHSMEDDAKgAgU3DejWRzheTANBgkqhkiG9w0BAQUFAAOBgQDR" +
+			"I6PKUGg876/fSljtqxXCR4CoGAAurNFOcM4EWeoc6ZvuDOi3P7rNYiYAXXlmp7epOAgvZP" +
+			"EV4vS16ODaJO6qIMR1YsaGEPo0ecT2pEStvP37X6pb5TdyjyKYF3586IN6TJdFMFsW/Lqg" +
+			"tucl9bGlWmfTVwxTexq6+D8diK48KQ==";
+		public readonly string[] TEST_12_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_03_04_crt,
+			Intermediate_CRL_CP_03_04_crl,
+			End_Certificate_CP_03_04_crt
+		};
+
+		/*
+		 *  test13
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_01_crt =
+			"MIIClTCCAf6gAwIBAgIBGTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC5UJ+KMj8tAmzr3OGYL2gSFcNTf8ik+ZVxlaPVGHyS" +
+			"KjYQBAEbefhfg5Ps2aIuqBwYkbtFXuHif5GEhgObA4InCyESeRjYLGcVMqwSZzAOFAR0dP" +
+			"1LzgzQs3ZgG9JX5MO5wEZ8IMnVN4Otu4XIlWSgIpUNS2vyet8Zi7t9fX+JewIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIOZvfph4Uu9YwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAXMyscmGpKSLG3hQltMQLegy0+g5wzgOrbFOWxZmiVNR+zSsHDD3UAH" +
+			"H4SyTozlooC0jAY4yAhZ5RX6SSJKx9fHsOZD9ldCmst14qLk3pkI+M0QiPBZkVTx5/7dR2" +
+			"wGkuNKSVWH6woOq7BbEzpO7xMlrUr6tgHt4Dc6Evt1pVZls=";
+		public const string Intermediate_CRL_CP_04_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wNC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIOZvfph4Uu9YwDQYJKoZIhvcNAQEFBQADgYEAe79z" +
+			"iEUgP/mvouJ9ufit1y4SjnHQWik75W65eGn/XGArRrBqJ8jZVJE4/rpDBbzm2V0hQoWU8z" +
+			"zchZFlesUyqQZ9KUlT0YGR0YPcNw/V+58RonWWfmU3M2DvWDrXgCOXPm61+AYq4+kTowsG" +
+			"0stmeML6NxjDzWpfAgI/MpXqe80=";
+		public const string End_Certificate_CP_04_01_crt =
+			"MIIChjCCAe+gAwIBAgIBGjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC45OS45OTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPiAZKXPjK8jvaNj34VynyKPK7dQtFysBPKFW5Y1" +
+			"Bc+OMsyd2pPpQoJYcQTMMomlAqoBvSXUJCMNly/BxVuvn7l6I9crtx6PjBBUlEzdcsscaa" +
+			"EaHuCCVl+Msnr66cSV3GqVGAhujun81+lyurcTEog3ftsohwbQnfA76qNU/N3/AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIJZPDbf2xNv8wEwYDVR0jBAwwCoAIOZvfph4Uu9YwDQYJKoZIhvcNAQEFBQADgYEAZf4L" +
+			"1RDHDXwwA2CgcIhM4CAfZ72CR2zOan0at38VVFB3u9vs4VLwFcrOQCIjDbdLijc0XWLima" +
+			"4vCD1qrsv6Hk5+6113HfFNmD8mp6X5jAwoNPa/I4kmFOA8iIm4TTk7M75vQyCQTPG0VzbU" +
+			"Nu3uwTbXKm5ME9C5MFMf7z347CM=";
+		public readonly string[] TEST_13_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_01_crt,
+			Intermediate_CRL_CP_04_01_crl,
+			End_Certificate_CP_04_01_crt
+		};
+
+		/*
+		 *  test14
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_02_crt =
+			"MIIClTCCAf6gAwIBAgIBGzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCteErspc5ekSOel/wmjn/XQ0HUy4XzxB5Zj0nGn9FD" +
+			"PbjF2LERCHOn5aBnIMHYhyr7PDynwbvSx2egzGC6wGe9Zrri1MteirQ9Ppw7062IIleloy" +
+			"UAiuwvD+s0npKsvboarQsCMfOB1hOB1tGG1bjXP6B5B187SZXuR3KawggyJwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIUjnGp96itUMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAR6fmN+9p5AWy/asEAiVBnbY9q7EQXyB8WuZK9FtFmupe3hlfcTq84E" +
+			"A+TGvXOlNr05/1iLRv82GsWXDif7DlGVPN8CS1+0kb5Ve8Pmv2ziiWVREqWx916ioPjDRp" +
+			"wvdGcCNC26+fyvv5TrP8uzojurl1ZlVRRqi2sIbopVX5r8w=";
+		public const string Intermediate_CRL_CP_04_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wNC4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUjnGp96itUMwDQYJKoZIhvcNAQEFBQADgYEAZkXJ" +
+			"aJG4QDE02wFURwaxWuv2VyD7m+N/2B0/9KR+6UKVpsMd2XHq+G3SlFOa6dA/fHUdhtUs2D" +
+			"gpx3SfQYbcgKFrryZHqJDK230eP3F41S9g5XJTRaNR5iZvxvh4bmSf4l6a5MXsKEoBoJoT" +
+			"j8cU4qg6j7Xk4NpIR1JbWiSIYQc=";
+		public const string End_Certificate_CP_04_02_crt =
+			"MIIChjCCAe+gAwIBAgIBHDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MRAwDgYDVQQLEwdUZXN0aW5nMQwwCgYDVQQLEwNEb0Qx" +
+			"FTATBgNVBAMTDENBMS1DUC4wNC4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALM7mfq+hpLfvQdqZUJfIx/2gFcgHS2AsgZn0An+" +
+			"Yn61WtG8K2+lt/a8aypa/q+J93RVkRYKWKFQcJHiRgx7DMlXElVnfQbSFuLX46ng4hqmQL" +
+			"sSOKmXDld2BlyMZ41B3rfdhJT8P12RMR6uAwvc9CH3b0UTcsc498Kj+JeaRbzxAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIo7S64S6t5nswEwYDVR0jBAwwCoAIUjnGp96itUMwDQYJKoZIhvcNAQEFBQADgYEApNT5" +
+			"Y+9Jc28m5Qwjm+/8SKk83iCPnIW3BsAvQUB9Wmd1+kMZvqLySQjm1tBBbcGYuSERMJ2Et5" +
+			"eoTdL9B6EG2CZYnPqu1vk0TVugRxs7IJm4h5z4MCInf2g1KTt0AMEasQW6ZTj7DIkkU48Z" +
+			"EKLPoBGXfD9t9Y9cmdj1e1RQbog=";
+		public readonly string[] TEST_14_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_02_crt,
+			Intermediate_CRL_CP_04_02_crl,
+			End_Certificate_CP_04_02_crt
+		};
+
+		/*
+		 *  test15
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_03_crt =
+			"MIICmzCCAgSgAwIBAgIBHTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGQxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEbMBkGA1UEAxMSICBDQTEgLSAgIENQLjA0LjAzMI" +
+			"GfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD11QBcw4P2rTUfPmbVNYqdo0AMmcB3Yxsx" +
+			"Iz5me/S1I2PJLtRh9KP7lUV20SMEFsFKtE1C+9O7ODtOUCJA/6ECeXbyj20SbG1E2oQrZe" +
+			"gkcn7IQDUgnuedzdFj4kTevok6ao9hycg+qeZrL6oeBD2XQCd9nqMmzhihNu/QOSnp5wID" +
+			"AQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMA" +
+			"sGCWCGSAFlAwEwATARBgNVHQ4ECgQInx+ELo31rJMwEwYDVR0jBAwwCoAIq5rr+cLnVI8w" +
+			"DQYJKoZIhvcNAQEFBQADgYEAriYMoRDpSPI4HWrxN1rjqWIzggz8p1wpbEFgK5o/Fi2KT3" +
+			"jCd6bfCcIFDpoXNqlsc+dvzc4XB1Eg/Qbcror8HP8LSxrbFw/y7VhC+wCaDCmhcqQn3rp/" +
+			"WaOWnR7/H7HlKM9m1u7MBtwlxHINnLKwPHIA1XwmAnItAXIL2yHRJhU=";
+		public const string Intermediate_CRL_CP_04_03_crl =
+			"MIIBUTCBuwIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxGzAZBgNV" +
+			"BAMTEiAgQ0ExIC0gICBDUC4wNC4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWq" +
+			"AjMCEwCgYDVR0UBAMCAQEwEwYDVR0jBAwwCoAInx+ELo31rJMwDQYJKoZIhvcNAQEFBQAD" +
+			"gYEAvJgOX6tewnRbC9Ch+Fe4KjkB9IAhe5anQKGfnDHuLfga6JEjOzyfhonWZeppJwvYpl" +
+			"1rZbsKICNphMDkd/eaWnn8Q9w02ah4kzIb0LuzrNBrxpFv9AAidfGU2VeF0gRi02jtAZsh" +
+			"gUNbrdC+ovA8mAsBigy+HMzCi61+wrumwvo=";
+		public const string End_Certificate_CP_04_03_crt =
+			"MIICijCCAfOgAwIBAgIBHjANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"GTAXBgNVBAMTEGNhMSAtIENQLjA0LjAzICAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMT" +
+			"IwMTAwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYD" +
+			"VQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLUNQLjA0LjAzMI" +
+			"GfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2Rd0VKnTIrME7hzpnpIPGXGXZCjpf5lSO" +
+			"19zvB3WdZumLGdwUBXpIQTrl5teYgL62PpOwNC93URZDEUt+rqoqvs8E7MpF3IulStp2+H" +
+			"/xa6Ihf4OmkgKjpHNTWOIFXeRJ4sVgWuH6cqQ+6GL+0fa1sed1crsEgTTAGYNhFi6ebwID" +
+			"AQABo1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR" +
+			"0OBAoECBNwCFdDgPCqMBMGA1UdIwQMMAqACJ8fhC6N9ayTMA0GCSqGSIb3DQEBBQUAA4GB" +
+			"ABAjSPg794yiVz9RqdNxic8TGnApNrZui/vwr1U8ZkETZfx8W1fWgQ0z7KjryML5IOmvps" +
+			"zycM7by6jb2kMmxI1SQCwjiNQ1fb1osrNAj2bRfpp2YgjjbHx1XkddommtVc0V8kvyQBcb" +
+			"7NdxfbwKr8AtpiWTWIajc2uqUlELsLzr";
+		public readonly string[] TEST_15_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_03_crt,
+			Intermediate_CRL_CP_04_03_crl,
+			End_Certificate_CP_04_03_crt
+		};
+
+		/*
+		 *  test16
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_04_crt =
+			"MIIClzCCAgCgAwIBAgIBHzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOQ0ExIC0gQ1AuMDQuMDQwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOFf5hr4R8IqTp53qQSiBEjOFQ3Q3ICcafl+FLzm" +
+			"K3xIFqERjyXARsTM4gDQ9yntFeNp2TiIi98xBrz7D8TlrbTAmxO/PUfAQ68tXpz9Id/XrU" +
+			"WeAKxMZULPL9nPFcGQoh0qq3JKpFRSb3Iobryfysblm7cCDDCJOI7uK14XZtTFAgMBAAGj" +
+			"YzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBYGA1UdIAQPMA0wCwYJYI" +
+			"ZIAWUDATABMBEGA1UdDgQKBAjior7qCuLBljATBgNVHSMEDDAKgAirmuv5wudUjzANBgkq" +
+			"hkiG9w0BAQUFAAOBgQBhh55gTy5htqjxW1Ch2hRrRikhBH7LJz1PmDuzwiIOtnWL+EiQOY" +
+			"T6h3NV1j8Kn5S4KhUOrhnvrPXRi22HdqRzEPl7y/wXm6G0XcgYlyy2ofZKdYVWCVStKAMW" +
+			"5SwV2wC5RPK2KphdhnlEqss6QVRUsliDDjnf9Saiey9nzJAfNw==";
+		public const string Intermediate_CRL_CP_04_04_crl =
+			"MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNV" +
+			"BAMTDkNBMSAtIENQLjA0LjA0Fw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMDBaoCMwIT" +
+			"AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAjior7qCuLBljANBgkqhkiG9w0BAQUFAAOBgQBI" +
+			"VlXD5FnIiO8tavLJ8qo/qRhbBNgUbFBdAgAY6yVnFNP6YN4qPineYPN6NV1XdqNDrZh2Nz" +
+			"GHzX3YDo1Uv9yABVR0NvXCaMIW5/raqZp/on6bPuQLgJe9UisOPKunzehTm/NmO1RW9dwU" +
+			"37UzC0XnVHyVipDVh07DrTKBUtQJQw==";
+		public const string End_Certificate_CP_04_04_crt =
+			"MIICjTCCAfagAwIBAgIBIDANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJVUzEZMBcGA1" +
+			"UEChMQVS5TLiAgR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRswGQYDVQQDExJDQTEgICAgLSAgQ1AuMDQuMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMT" +
+			"AxMTIwMTAwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQww" +
+			"CgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLUNQLjA0Lj" +
+			"A0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCegy6qOnM14CS7+enBElgh2DLtF5bn" +
+			"ah0yfA18/hbqnmUaWOWJQllyXa8QFawnvdXOOEXJm1ErIm3rDYihkbUTP+ybOBH9dprWtl" +
+			"1cSGL9CkoxwzkJRLQTu5xG72EhET3S3kwqZsmYbgy4MduGKv9VGFbv75Wr17Vo9K4Lz6QK" +
+			"vQIDAQABo1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQ" +
+			"YDVR0OBAoECEc4b3BP059HMBMGA1UdIwQMMAqACOKivuoK4sGWMA0GCSqGSIb3DQEBBQUA" +
+			"A4GBADj73jXpPLev5crwZIoXCJd/nXXp1fJzEEbByWggsR9cFHN4wnp7N6gpIxQbLQwjmo" +
+			"cLPC1pHQ3A5VHVrCbxAk6nifmSvnKFWHTBftZGpfTGkrXbURFF64T/CB4O+JXr1eBUGheN" +
+			"Q0T8L17UNgi3oBENKjASWnpjxvD2QrOnH0rb";
+		public readonly string[] TEST_16_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_04_crt,
+			Intermediate_CRL_CP_04_04_crl,
+			End_Certificate_CP_04_04_crt
+		};
+
+		/*
+		 *  test17
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_05_crt =
+			"MIIClzCCAgCgAwIBAgIBITANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOICBDQTEtQ1AuMDQuMDUwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMBsWmrcKH0J9bkI3zHthZ0S3904f3fMUSasY5qp" +
+			"7CSQ0sbXTwP947sfAPK4Dso6Bpwl0WExRCdFHd6qfY9wR+NtfuI/DkFEY8WveoqM4Vskpi" +
+			"cutWghCx14PiPY5YGFn8VvXu7wbuHp4TnHtUCMEUt3EfYO5oqm+/I8y0eTKMNHAgMBAAGj" +
+			"YzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMBYGA1UdIAQPMA0wCwYJYI" +
+			"ZIAWUDATABMBEGA1UdDgQKBAjOoKlp+BfGqTATBgNVHSMEDDAKgAirmuv5wudUjzANBgkq" +
+			"hkiG9w0BAQUFAAOBgQDLhQ/RJFqMDNRonAHZ30DYyphf8do4q6ARikhhXSSa6G2G/PzbpS" +
+			"x3T+3G8ot+NnFhtf9ZWo7KfwmFEbUA/B/X2vJaJbNImkMDT1aTY5sPXtA69B3QKQVz7HST" +
+			"f5XH6DjuoV0/m1M153A4vf1Z783dOPw1MzOq19t+6tYFeELEHQ==";
+		public const string Intermediate_CRL_CP_04_05_crl =
+			"MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNV" +
+			"BAMTDiAgQ0ExLUNQLjA0LjA1Fw05OTAxMDExMjAxMDBaFw00ODAxMDExMjAxMDBaoCMwIT" +
+			"AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAjOoKlp+BfGqTANBgkqhkiG9w0BAQUFAAOBgQAp" +
+			"6gLCdPQw7Hisnr1i3QbD7GybqfD6b1s10GQ3c/j59RYDe1Fk47Srs9ol/baleasWjcdt8M" +
+			"SlTc66KvK9YPFAqIdYoOW4FidpJBF/1cvSc2hGYwVsxLnXKr9CJ5Py5vBCCjovIRiLdzoL" +
+			"ZoteOKFIEHkV7V8V2OTFawxpW9hkiA==";
+		public const string End_Certificate_CP_04_05_crt =
+			"MIICiDCCAfGgAwIBAgIBIjANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FzAVBgNVBAMTDkNBMS1DUC4wNC4wNSAgMB4XDTk4MDEwMTEyMDEwMFoXDTQ4MDEwMTEyMD" +
+			"EwMFowYDELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UE" +
+			"CxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5nMRcwFQYDVQQDEw5Vc2VyMS1DUC4wNC4wNTCBnz" +
+			"ANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwZsiUhXiFHN9dfJb0Yyy+rYtV8gx+d0+8WkW" +
+			"5C68nQgSqqk2uSTpvZbx0bpHF+s+LKppj2M2tt/AfZgVQHTsp5rO0IftZE2iLwqejj0rYU" +
+			"Poprq1PE3vVhs818ZlDS0PTUP97YxLysQjq2jS/d/9lF5pS3sMlP4Usp24gXX0vG0CAwEA" +
+			"AaNSMFAwDgYDVR0PAQH/BAQDAgXgMBYGA1UdIAQPMA0wCwYJYIZIAWUDATABMBEGA1UdDg" +
+			"QKBAjpC0ZvCXrvBTATBgNVHSMEDDAKgAjOoKlp+BfGqTANBgkqhkiG9w0BAQUFAAOBgQB7" +
+			"YwJWcx+PU1sUZUOVleoB5amHFu0GT+Hy7cRa82UJMHFkz0bmnyEV8CBNcnn0xa5iVfwe2y" +
+			"5ZKwy61DLR3MPTar9eKITL67uZag9w+1tnIf594XRbEiUzn20uxuDFX3oPoZCemtWdVanj" +
+			"2T+9TVQKfrp15+qzOCObNNRHZw29EA==";
+		public readonly string[] TEST_17_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_05_crt,
+			Intermediate_CRL_CP_04_05_crl,
+			End_Certificate_CP_04_05_crt
+		};
+
+		/*
+		 *  test18
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_04_06_crt =
+			"MIIClTCCAf6gAwIBAgIBIzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA0LjA2MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQD0t0dfe82Su58bJdn4dh7E3OCam1AUPTzPnt7DwT2w" +
+			"1XwD76OCUYP7SBBjsLYDDfUCb2ek96pSK4jpzyE6/4IOtfObe7OW+iBT9YAB5WeW+SmvEO" +
+			"TIX+xo13sbz6rG6j9svcOxtth98yv7mxzV/ZwTNBSO72CcfDXIIq20TVunlwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI0AufZEn1f9AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAbfhxuNBYizxfMZNcyiN61j+7LXZZo3SmMU21UmOhPBTmdTbIkuVCI+" +
+			"F1jSWdu3eGShVNJ3jmkidDvojMm+E8ZZ1YGHYfgeG16dDQudaGUjGmOfYzzlkFmsaf0paG" +
+			"4y4sBerPsZCmhN7BanGh3qYPFvadSmp3OapGfEmDtS+BbVQ=";
+		public const string Intermediate_CRL_CP_04_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wNC4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI0AufZEn1f9AwDQYJKoZIhvcNAQEFBQADgYEAIAI7" +
+			"W6K69twJZnHx6CoIMs5+P9DrJ2yKHptmntlOCTSJirC/xdj0Zv2k5FW84VrTtdCSZDT1Ce" +
+			"4Dh69fT2sUUexJb/4IcDtzloiuASSJzKWCeVIj9A8e6+coNUJVKtRKRX8bHJ5Un7xpFrY6" +
+			"t1hdxt8gUecAAdXEFGuZ3QEHHN0=";
+		public const string End_Certificate_CP_04_06_crt =
+			"MIIChjCCAe+gAwIBAgIBJDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPdS5zLiBHT1ZFUk5NRU5UMQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1RFU1RJTkcx" +
+			"FTATBgNVBAMTDGNhMS1DUC4wNC4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDQuMDYwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKq8rAPXsu1RVm3vT7od7CDLn8k/C3x3wvfzoWrm" +
+			"W0cmlhp9xRy5a3HWiJATD8yCKY1psBgnrOpv37sdtUX4P2kf668HrYOaGo365fKPeT5Wjm" +
+			"gp0pL3sXKNNsCuJPd3wKAXGHAi1R9arZFYPsKJlfQl1774dwAvzxSOMr5+pbnzAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QI33MEYdo5YX4wEwYDVR0jBAwwCoAI0AufZEn1f9AwDQYJKoZIhvcNAQEFBQADgYEAo8Ge" +
+			"ADBoJFEIRzdO37uasuyIBhClTUgyFhEKemMBN6aelYeiJMX6FZIL3DgZOce4dg7Zg3Ak/w" +
+			"B5m8XlGQLW9xIbpEzY/Iq9kr+qK6k9YmvtcOiHFbnudCFNZngTQZpxjiDaj4eA48uqKIxs" +
+			"51taC5gOv9LYWPnugN8TsUUFZ1s=";
+		public readonly string[] TEST_18_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_04_06_crt,
+			Intermediate_CRL_CP_04_06_crl,
+			End_Certificate_CP_04_06_crt
+		};
+
+		/*
+		 *  test19
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_05_01_crt =
+			"MIIClTCCAf6gAwIBAgIBJTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA1LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCshocJtyGsxeEd2ouVTVKp+HuhDjnDk9eXtaLQIKaB" +
+			"7aTODHYbq1mC+1LO5DmRV5PBVd8NuuCA+1DmzFrfYl+nMCjjgOkC0//Gf9O85Hi/n21q0T" +
+			"F+oVa1j9fc7nAgLIziexaXrflYSbaeNWkwHHftGUninKPuNGM2re0krEeurQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIaUi/P20o4LcwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAWBLeJl4qlAPKxmBM5QZ2JYsbCV3VBeYGAKQ+4L7ehS63VQMCwIjBCI" +
+			"LaHGIFfCqecDNd6cpYIArdx4tY7X2/Zxm3j5ocngpI1Tv8zydQcFeraILglsHf2UZUuK/N" +
+			"6jKGjwL68C8YwmA+u6ZhcQFD2Xg4wSMC/xxzAs9zEAQGBPo=";
+		public const string End_Certificate_CP_05_01_crt =
+			"MIIChjCCAe+gAwIBAgIBJjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wNS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDUuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO9ODA12Fky/Md5AELkaOvOwB31UlfZq3SHAOvs0" +
+			"Y4NYoA7Q5KDIwW8RNzMSKD30z51VlgOAaBVR6HLo6rkcWB4wGiV7EPelewdSOdk72IrnYR" +
+			"npJEm2KEuLkHB+gejgk+paw8CejxMsrvT6loN8Pz0btBKxWaCfknTIyXVyQsolAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QI5LtSKs/inGMwEwYDVR0jBAwwCoAIaUi/P20o4LcwDQYJKoZIhvcNAQEFBQADgYEAOMrC" +
+			"38uzHckKMkiawXhPUHtDQfyR7bLweS2qro7GyndfxPpeMJwjzVxqvQBtMuHON+al8jyXpy" +
+			"BsEryV6qvdFC1vczLzJHAJZmLe5np27zQIXOObsyYcOG+aPq727/pKoD90DAlBvrxNW0ox" +
+			"x7citflEYpmOEv9Do5xiO3MuCFw=";
+		public readonly string[] TEST_19_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_05_01_crt,
+			End_Certificate_CP_05_01_crt
+		};
+
+		/*
+		 *  test20
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_06_01_crt =
+			"MIIClTCCAf6gAwIBAgIBJzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDI4MXZB08BfUHxo//4Re7Ax0qWkHgy6nb+/XaLQ2Fw" +
+			"Pbvpb5mkhLhqDZBSX3KQL0YiJ8p81tmdvRQH/LbFzX/3OKBTUfV5imYy979A2NEb4otFp6" +
+			"EDSskZhttY3d2IzUICoCWUXhObnmkHJ2jEc81bggFkK5Lir1m/tKq2IOPFJQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQICIAmlz6+Cc0wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEA0ZvIG2cnk32p6uxqGw8Bu40NrfHu9gNkJL5MhDHJXA6OxU5BX5bWZp" +
+			"LnKXLoHiqSdtEdmy5cLZw3kggxndxjsnRFMyCawaYupJBhlgquFbuvBtA8rMtkc5H4zudP" +
+			"ZcOcvXu7Xw58K+1caSGURL+A6uXFPnMUBd1+k+ejbtO8Pto=";
+		public const string Intermediate_CRL_CP_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJKoZIhvcNAQEFBQADgYEAbkJe" +
+			"jfc1rztCbtC6xJZ3iZEDDMW2CxFvOvSwhmCjPqVY3lrCPNSQzdjmqepioCnu7ongP+HAA7" +
+			"hM7bm+SoN7KzXKufQ7C2ONoAwvoPZgnoidg7RVECxUByD6AJu04yd2wCLYRpCfS2tDtXLh" +
+			"HEDpe+ELwv35pbkCMlCO2u7J+Tc=";
+		public const string End_Certificate_CP_06_01_crt =
+			"MIIChjCCAe+gAwIBAgIBKDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDYuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOh7lUwMRet7t/ABI6mo27CsnRzQ64Xx7f1dqxrJ" +
+			"NuuSRslVShaWnwiGHjc+5/TS7Urfj9VO0dseBCzPsyYFoIX1q7Q5zlArwy24qpXTGMmlpE" +
+			"GByzi7jkXO8w5+wqh3+8RFrQQzr71zLtAVV/qPUyleuF8M8jzkwfPvawunmwdLAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIayC0PPU9zyswEwYDVR0jBAwwCoAICIAmlz6+Cc0wDQYJKoZIhvcNAQEFBQADgYEAPz7b" +
+			"UvaEV7Myjhe8LJO/soj84X71rvVPtBPrhYjWTJ6p69GCfJRyho3vAUIt8RFal1GFb72c45" +
+			"DQGkcVzLLJw8cDP3ajtWac5HZ9dNPJkW+Kh12l9gqjn061XAjQ4XnbbwQDYCuXhguPE9v3" +
+			"kzDbimwVwIEOB/4SARX37y7TUWk=";
+		public readonly string[] TEST_20_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_06_01_crt,
+			Intermediate_CRL_CP_06_01_crl,
+			End_Certificate_CP_06_01_crt
+		};
+
+		/*
+		 *  test21
+		 *
+		 */
+		public const string Intermediate_Certificate_CP_06_02_crt =
+			"MIIClTCCAf6gAwIBAgIBKTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUNQLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC/IejV3DmeaLW8OwMfAGyr5+8NOxM1C+UBYslbOfWj" +
+			"KUGdhlX6TxFc5AOJVJBpS/QjeA+RWoUCxnxKb9QSlOrBmADrcnGz8zV0/c0JDLaU3oSgsV" +
+			"EWZE0SexBVWrKcl1j7wN0RuxMeAp342/YoyvBwea3VeqJkmSCc7Y2TjruWEQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIaHxWOdHsLbUwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAuzeq/lqp0qs62krK6EA81Silhy42l/KmynE3mVu9GPBgQS0BUDi7+r" +
+			"QQ+m0UxYElzj2SNO4J5aBYeC98lVJFCHX7QE8yVOoPBQd5rA+rrz4HD9QoP7glxTqLU6Tc" +
+			"9VFd+iaFpqsVtSh2bxH2BtUB2ARgebTklaNl5VPbu0+yc2I=";
+		public const string Intermediate_CRL_CP_06_02_crl =
+			"MIIBbzCB2QIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1DUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAiMCACAS" +
+			"oXDTk5MDEwMTEyMDAwMFowDDAKBgNVHRUEAwoBAaAjMCEwCgYDVR0UBAMCAQEwEwYDVR0j" +
+			"BAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQADgYEAYGaAzVoUdlSZ3uGKiRPfHAFIoK" +
+			"T79hNOvtOxaGA0aIek9OypDrDqYAh/s2jsXSheL0pr/v9WRIHvtCt7ytXDxVyn4Nxjpfv7" +
+			"BkAMMiccdUx1OH1VElTRkmmtMe7ROzUeHUGzXJNPex1Bc9BvSChH18bWYckyOZdYJBjctC" +
+			"KJFgw=";
+		public const string End_Certificate_CP_06_02_crt =
+			"MIIChjCCAe+gAwIBAgIBKjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1DUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtQ1AuMDYuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAK4D9H8JxeIrFuOmx0cSkIYNS0p7cDSBlcc57Na3" +
+			"+1k7lJD7mE9ZP6/47YsDVK2bwe4aTKCTXtPk/kGQ6bsLswJXbyW4k4+f5LeAYoXgbmZXjA" +
+			"WF+BKIl8uKetsqC3HkCeqhBaY1AGUqef4oOAkakEP+1jYFumNYtMaB+9x/0ncBAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIC9MiJNI71RMwEwYDVR0jBAwwCoAIaHxWOdHsLbUwDQYJKoZIhvcNAQEFBQADgYEAo/ib" +
+			"mIxteityjZlszjCc/s7yM/0snL78pYpMOZ3P2TPKkYh2Th4+Bw8JqX10+M/zwFBj5Bw7Im" +
+			"zCIRfS3GFuKmcVcyHB4OZLMcQZtXWA8GOZ94YvWq5TBINlVtThQtusQj15KBq2TJNNFUyD" +
+			"pBdvyo05AnEsRY0HbIQu6ZhNQ40=";
+		public readonly string[] TEST_21_DATA = new string[]
+		{
+			Intermediate_Certificate_CP_06_02_crt,
+			Intermediate_CRL_CP_06_02_crl,
+			End_Certificate_CP_06_02_crt
+		};
+
+		/*
+		 *  test22
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_01_01_crt =
+			"MIIChDCCAe2gAwIBAgIBKzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAxLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDDOu1J/VIzbB4VcS2Dwf2fsHOmIj3iatM8y61V7CrN" +
+			"RCxCWTJ1Os8e/mFWOi/zN+0afizA0UzJDTe8L++/RlP68IFg5Ju2OhXqQC3HbUZmQ7ve9g" +
+			"QdWTfur3oEJV6/XoVE4WG0Ic7D1p7BENb3LUT+8MJdSboTvAggA1CiOI6zRQIDAQABo1Iw" +
+			"UDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBAoECP" +
+			"RyRiSV+4XrMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBAJlmJ9EW" +
+			"9ujUosqHZyZkniu2vX8VOL52OnxtLxw3LqxLyuxivjyYCaMAaJNr7/xfm3C2ozh9mQyZTQ" +
+			"6TpBapLFUH8QsEKUhy57MDUgIvZsyOvvjJh3AXfSkXDaMZ3ncLg6x0wwjN/Hxu9i+IhX1W" +
+			"1E7/5foGx7AEVfwY7Fo9S82d";
+		public const string Intermediate_CRL_IC_01_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9HJGJJX7heswDQYJKoZIhvcNAQEFBQADgYEAV4DM" +
+			"F5gU8MZ6E/mnjAWS+dIRKUBJV1GZJ+hOysdbmK1hD0mj5Pd5qTzlcvLjuatIoIsB5DCpYd" +
+			"AcNRLVvF5EJFhVjqsPzRlfUZth0Xqa+U/DeHjVxHxYsLEOSt+v2bLkbGh88SmOAk6F8xj1" +
+			"l7YIfPX5cIkUBTVZlsUt51slMXc=";
+		public const string End_Certificate_IC_01_01_crt =
+			"MIIChjCCAe+gAwIBAgIBLDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wMS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDEuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPrk1fosBu0hemIKgTDCeV/RoFbbsm02X4LfZonX" +
+			"KeGRGYZXz4tpWgbNpjKBq1e/2bOO1DCn9I8I2kjvZdOkabk4MLeuRDo/sqlNndu4Ar5502" +
+			"pAo4A2V0QLR4IDHAJoDpxtSFrqELOiiyCx9O9V19ywe5pcBFrxVEWDqTnBUeDJAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIbI6BhABrmQ8wEwYDVR0jBAwwCoAI9HJGJJX7heswDQYJKoZIhvcNAQEFBQADgYEAYzYy" +
+			"M0wbzNhZftAWz7TfFi64uA9WmTmd4MeK9vga4ChswT4H1zlaV1Sr+3hqpGmOoP5AUd9XIq" +
+			"O/ui+/gFaeuOLI+ATmK+V2KHGAneMwzcw9qbXRc+xZqGGjbXMb3Bowe3qrj3mhyowfa1n7" +
+			"x5xB7XEOqO6sfWxLdDjLVo4sn88=";
+		public readonly string[] TEST_22_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_01_01_crt,
+			Intermediate_CRL_IC_01_01_crl,
+			End_Certificate_IC_01_01_crt
+		};
+
+		/*
+		 *  test23
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_02_01_crt =
+			"MIICkjCCAfugAwIBAgIBLTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDemJgZnOzXOwNGqRA3Xq9aMrAWQU4oFuhSELsEYfLZ" +
+			"GO3ntBjJLqCn+rs3FjR9N94cu63TduOAgqlXqrNbvyO1+SF9m35JXreqn/OS6KrK6c8W2I" +
+			"pDAWJcr89nGyyCXMoJeaOOtj8m2NjZblmCZvtAl5UMOew73GE7Z5fE+jtA2wIDAQABo2Aw" +
+			"XjAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQIhT9GjaaHj68wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEAWhKJUujLapxpz/DoD/w48HMzkL6UQCxQPOAjwwHicX8wFcKmcrWLVBdVC3" +
+			"0+ywrzMraWhaq+QCOqsgtxCwTZrfUxbCNqhKS0lZijCMgNN4Jht+PAZ22tzEsw7nCwiMM2" +
+			"n1jeKF/3btoDEUvZn9SuzhkIyxy7Q8l2tbNOsANqpxE=";
+		public const string Intermediate_CRL_IC_02_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhT9GjaaHj68wDQYJKoZIhvcNAQEFBQADgYEAJsjf" +
+			"oS3F1KMpcVBOC1Z6P5N20TYLCCHG6KETlBA3Rjf8ehNxJKJW0lGd7qHpVHp4BGvkSfaOAa" +
+			"OrC0G59wjDEY+Ci4QS46OYzBcHXMFX5HF2xMq+y5SfQnyV6MQUVVkxJRjgsTLrYwP2JaYm" +
+			"BK/zExhqQgPfgcR+56swBPXqogo=";
+		public const string End_Certificate_IC_02_01_crt =
+			"MIIChjCCAe+gAwIBAgIBLjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wMi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANbTVeAxOibAO3KGqxxY3VqKXDr9tKJN+igpKb4w" +
+			"goR0ZnWGDusSVm4pvneZ9qfmi8A0sM0E91+B2hAwsU6Y9RoA7nPsTkFYi5F+hHGIF46Op6" +
+			"8blGrZraGf9bsWXCZFoLoxcgltwjGPQqyZ5mnnm8cxUbtaWmgo28MK1yBH/sS5AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QI3gkBNo/SISMwEwYDVR0jBAwwCoAIhT9GjaaHj68wDQYJKoZIhvcNAQEFBQADgYEAQGl1" +
+			"7uT2xxYDks6HolrQIpesIoPqEiZ8TkizEBuLG3sUKsC7klHwy2iyVvA6nRUDwf/XzDLpGW" +
+			"/Gn0KTW6ZYIX6snOC1+7HX5OJglQx8tDpDvcAgyocK8PvCrHfu9o33J49aSeLAVpoCHwne" +
+			"tTtJxVfTMmjYWKeDbHHHi8a2YTI=";
+		public readonly string[] TEST_23_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_02_01_crt,
+			Intermediate_CRL_IC_02_01_crl,
+			End_Certificate_IC_02_01_crt
+		};
+
+		/*
+		 *  test24
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_02_02_crt =
+			"MIIClTCCAf6gAwIBAgIBLzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDoeA32BPwgq8pLJoR/tbOSjHtAz6fmzvzJrhJMvl64" +
+			"ccVuIzGxzOneYsO/ZYWy3ZGtlCoMZJRnS83tw0ikU9vQUwBw7DEcfRlLKYkY68rp25N1V5" +
+			"JEjnlHw+RvubdGkonWzUNJFbY1GA24J3no2GZHiLPgWmGb1jsA8Ag32MUrCQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIKx4Ybzu2PaYwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAotGeNFzmktvcxpCRcpuARHkv1lW+LegvbDBnSPvGnr1+Cn9rZcuLup" +
+			"u8ex6VJ7KWtgWBtzdOelerO6ytfWQ67uNpTOuc0SDdk/f3tCagdx44LBVQywuq/Kj57ZuN" +
+			"jpe4J8UPZSBFFK+P3gTX3S/lIKsDi6xjRnqFLSQYGX2XiIE=";
+		public const string Intermediate_CRL_IC_02_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wMi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIKx4Ybzu2PaYwDQYJKoZIhvcNAQEFBQADgYEAOfuX" +
+			"wRv4skbPZAbOH/LVXdc/cA7vCSTAnWecN3ZKm/eCsxbyRxqn7fcDyHmqg5H3Ac5UOlMHR4" +
+			"FMe0Dp+Yu4Xg8xg3zRvE/3M/5jyRILGGi7olh4ikkOMD+UlreysvYvUX2MVP1iM9qAkXh8" +
+			"E8n/LZIlABN2GGkFEMRMJA6KTXg=";
+		public const string End_Certificate_IC_02_02_crt =
+			"MIIChjCCAe+gAwIBAgIBMDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wMi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKogqWGx9EpJ/0G7ORopyIQ4IZXYKKTE48WqOJbu" +
+			"nLD3txGjMUb5Xefl/QyTfd6J758ddGzPiKs1zWO6riffJLIBoOFDmt8tchPBJuIM3gKgXe" +
+			"VcZMyF5mebm5/GZekMOjbs8P/zbLdrlu1D9CZWZMXONYitdluSg2moMGbewS2NAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIP8N7OmNGshEwEwYDVR0jBAwwCoAIKx4Ybzu2PaYwDQYJKoZIhvcNAQEFBQADgYEAwkpF" +
+			"j6Kv+OcKrUtOgnH9QddB0Ej0oU6B5/5Hhhf3liAPKtllDHnhUj6nqfh4APNq/iqYFOkKMR" +
+			"RUZoaj6kakJNSOlgvRIiQfuFIgv3CqLZnhr85YFRnKgoluZE1pq3TvunoiKyJbCjbmyCos" +
+			"Rd32gVcJq024xvY2eVBTl6tfn5A=";
+		public readonly string[] TEST_24_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_02_02_crt,
+			Intermediate_CRL_IC_02_02_crl,
+			End_Certificate_IC_02_02_crt
+		};
+
+		/*
+		 *  test25
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_02_03_crt =
+			"MIICjzCCAfigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC7LFt+yGItQFqSEPi03ICIr5ydWnFPQHZdEMNu2tRU" +
+			"3XiOpfam1wl0xgAPGBkQK768OfidpP/i1hgYOU/isOB5dyALscvIQ9XJG1OWQXBBLgKuCb" +
+			"MS5fuDhBNa4KiFuGMbJ3/UjluRsD9qaXwGUavc436JwbRHvW8FomaBYYY1hQIDAQABo10w" +
+			"WzAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAT" +
+			"ARBgNVHQ4ECgQIPsBg9tMABhAwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEF" +
+			"BQADgYEANZcayTTX+FGhtRUJ+XuYA7jR14CJL6qTHPvdSMgHNw9mGXI/7sO5I4v1vayOCI" +
+			"YQ9luBvrTYlMPmuej8+bhM8YTYpiiOjVFANwvSKArI9U2CAGBcoBMXydykkm8qYw4gtYQT" +
+			"neiOz7VqI9plLWA111IRMgayD3CAt4Ntpzd1VSE=";
+		public const string Intermediate_CRL_IC_02_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wMi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIPsBg9tMABhAwDQYJKoZIhvcNAQEFBQADgYEAVeQi" +
+			"tT1FRUaJlhfpkfjZr6VHmvGnqYapdo4DRT/pm8tsp1LbZZXpYW638ztwgZNgeBRPFlcb+x" +
+			"8naQjEkoaYzLbCYfdY+PPVDv7ym15PE48Kve8ImvANY0YnTGS8pcKdK1dpNKBnYYMOG9JN" +
+			"+H5K/4cSm/WMCKIuKdsiAWFYauE=";
+		public const string End_Certificate_IC_02_03_crt =
+			"MIIChjCCAe+gAwIBAgIBMjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wMi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALGbo9yEujZ9RFU+Vmxb5+Rx1VdIG/3E/5hXV/xI" +
+			"OFu4mEfYh2tBhP2qIMH2KbrR1tiW5t4DvTCBM3NKKqp75wpiuu7E3q6imt1pLbGW13NVL+" +
+			"81gYWXnCnzHpxYjMTIqqCkPIAeOG+SBJ1MgERbL+NBl+AK3WG4TeQ8vw7r2CGrAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIS/HbII+ki/kwEwYDVR0jBAwwCoAIPsBg9tMABhAwDQYJKoZIhvcNAQEFBQADgYEAWHy4" +
+			"sHrTkqY1XjDBY5XpNEyhP6htcnjYD9bos4wjxPlJUyxdIWACWrLDE+R5iRCOYsh/nDAJEt" +
+			"CUcVASukvP6VLJaFjyxUOaCp6JCVV+txk7Fh0S/Ur3Zyysfp5LllP1plOA3N/k1Hliljp0" +
+			"+bnSiDhA1+3hJh0gDMjWUdRq9yM=";
+		public readonly string[] TEST_25_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_02_03_crt,
+			Intermediate_CRL_IC_02_03_crl,
+			End_Certificate_IC_02_03_crt
+		};
+
+		/*
+		 *  test26
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_02_04_crt =
+			"MIICkjCCAfugAwIBAgIBMzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjAyLjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDf5u5ouGQlQmdNfc4ell3RXKWmtq+ar9VKMme3kp8D" +
+			"cbDbUaVwlvhWTkOKxb9I208wfGG2nQiArezIwutlASf7sWo16EPapmGdCF+rp1dpjAPBUu" +
+			"fruEyCZ8nu2ITD52wuPY9OAcKHQE2/bBpCJWkw97fYX6Q9PPW5uobWoUJtOwIDAQABo2Aw" +
+			"XjAMBgNVHRMEBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQIjDm8K5YcGakwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEAEQIJeZj/HE3HvjjJV7PdU+2Ze8OeCYeeWDocxrA647xpeOksVXBXKmq2OV" +
+			"NqoFk7YNtlSUqiS2TlqjGqLtKYetk7a17qS/8EIQct+H5KWdvkLkYMkfIAAMJvJZHPGxEv" +
+			"j+oVPAi9FITRbFdN8Jvdo9MAuU2q8d2x8MF236RmEds=";
+		public const string Intermediate_CRL_IC_02_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wMi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIjDm8K5YcGakwDQYJKoZIhvcNAQEFBQADgYEAV5bX" +
+			"7WsT8sWeA0iQ7V/+ZQESDzvyHA7Ziju0iRsvTL7qOVF/Nl5v+zND+ZNPhdJDKEM/Q0lEaA" +
+			"ybe0E73NMmM1qRX1daAwE++jHukF9TMeNl750HJaS667H6jcjeRrHUJDD0+AgqrZY52dL6" +
+			"CPM3V4QSvdfc1/xtKmNIZWSSoqY=";
+		public const string End_Certificate_IC_02_04_crt =
+			"MIIChjCCAe+gAwIBAgIBNDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wMi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDIuMDQwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMW45d5dPrzUJbuRIDeQ5gIJRYxi80PxPvxSmJe8" +
+			"ScG1A+l75SAtgLGWAxBqxPSzL+teBBUsnmf2Xsc8/qQHHev74uat0lxq9YrZ3npLW2YNo2" +
+			"CfxLK0M7F1/bhkHK2f9ttIvOrrKI67BeEjfACULdJEhl431uWINWV0pY+fHq+pAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QII61NnUvgvjYwEwYDVR0jBAwwCoAIjDm8K5YcGakwDQYJKoZIhvcNAQEFBQADgYEAjwgL" +
+			"6qMnnqUvNspsDaYpPQzTCqXkqshZhsy5G/nLk621H/YbNGlnZ6asHGljYVYMzjmcny16y6" +
+			"ntiv9QPB7YorAx27WT7pQPFla96s+nM/rfwWHPWI6QGDsquPriwJm/MwQC+1oDXEFKvdIL" +
+			"0urejfd5hgiXYbRRwMI7km97iHg=";
+		public readonly string[] TEST_26_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_02_04_crt,
+			Intermediate_CRL_IC_02_04_crl,
+			End_Certificate_IC_02_04_crt
+		};
+
+		/*
+		 *  test27
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_04_01_crt =
+			"MIICjzCCAfigAwIBAgIBNTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA0LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDBtNwpr9LZBF2LRtAp9Tb1FZnfM3b/Jv2sdO5zc/Bk" +
+			"sO4ByUgY+Mux9dEvFrkVWBK110TvXn+dj+85TuboILv4MDKlu+tI/rtuadXGwwDIg8TQnz" +
+			"uyC7LWhxM5JZs1/Is+sPKUY4PTCHs3+EHPBWf2tFiP3l6ZftkySEiL6+2LSQIDAQABo10w" +
+			"WzAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAT" +
+			"ARBgNVHQ4ECgQIbMuZ73onuZswEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEF" +
+			"BQADgYEAhaTSc2xafdP/QceMm9YJ/rZJ5gTgBR/SlmKQwd2BclHabG+Fozdg4delDjtRXS" +
+			"FKY3sFWBFZHVeprh4T93Oj6IVA5X4DIuUeBpprtS+psCnWZxdtcUWmbyYQwZNCifG5C5D0" +
+			"lRwxlMlv40xT2oCM1zPZpfmqemBDUPJ2OhkCjvo=";
+		public const string Intermediate_CRL_IC_04_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIbMuZ73onuZswDQYJKoZIhvcNAQEFBQADgYEAMk6D" +
+			"Rztz1AyFnFr1KAlbjLLwxtQplf2eIc//zUkDFVUHtX5TrEC/ijUaItjdkOoPGQfpnL0w8x" +
+			"wyqWndMh593QPCqIJTtv/iACoiJNZ90ZJS0adcdZ+AEmQpa0Zv0e1JOqRrPoAfTq4HrOfR" +
+			"vhBwhvKQNtTExupW/EBudznKC6Q=";
+		public const string End_Certificate_IC_04_01_crt =
+			"MIIChjCCAe+gAwIBAgIBNjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNC4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDQuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2dGkraKGdIi6EXxAu6/ekMqDloX5YSVBGh4Hp2" +
+			"faujr1u4j8Lp8afqjngRxFUpTqGbqH0ETgm4cVPXmc9rUvUzYTMdxTUmIZ+iW+ULZEvzNB" +
+			"712kxRPCD2kDFN2fH2ai8miXr434w+weLm8VQN4jJGo4nswhSs2w1gsUmWyn/ZAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QITsLx/sO1edwwEwYDVR0jBAwwCoAIbMuZ73onuZswDQYJKoZIhvcNAQEFBQADgYEAeKft" +
+			"0RM8/b3zQodaKrTdWiFyLg5fzoOsTecSfdFPXoqz9J5ejLVkvJevSmfXJrIUhKXySzsQi+" +
+			"GazuTh/hvWjwUTIvmupi+EiFudnMpXCro8bgi48+NkepNjXvjsSmOfzlrK3SxtpH5dqonL" +
+			"6LHjGyg+Xp0Nor1m5g1rLHyrcEk=";
+		public readonly string[] TEST_27_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_04_01_crt,
+			Intermediate_CRL_IC_04_01_crl,
+			End_Certificate_IC_04_01_crt
+		};
+
+		/*
+		 *  test28
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_05_01_crt =
+			"MIIClTCCAf6gAwIBAgIBNzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDM3aWmgX3OzAaBg6lnWjpFQ9ufeTOia3+lIUqn+Ypf" +
+			"5OH/s9dLRqg1ZynV3YIUyzaJPP/YlUEmrhheJn3Bjw25bHeIKdge73pfEbuBAugbUMS75D" +
+			"csBV7Ze9D+sVw8w/LtT3ZPcvM3Vju4d+c14Ip/8pC15jlgQPhwVQSf0x3V2QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBAjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIJ2DFtxoQnXkwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEASvdcfBOh2d1dC10pGLZLI3T+oSPCup/U9riynIR3RxZsIaS/+Q2s81" +
+			"oeg++WQV6pyYvCLneZIp0efvqh5DThNV9lhBcJjlYwm/T8Hi2IaRGsSMwIvzrFN7zxA/zu" +
+			"tW98wigAKM2myk/nlYxmholgbQkQ7ZxYM3lD1TDRl69N66Q=";
+		public const string Intermediate_CRL_IC_05_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJ2DFtxoQnXkwDQYJKoZIhvcNAQEFBQADgYEAK7Ym" +
+			"Y9PjX5CpVewe2E9PNxj3dLYElghaQyapYoVtNq3jDqLMWspdmHdNdeaQoXsjlSJe0Zy8xH" +
+			"ZvpimwifnFZ5hq4yByzHjzNMpcA2yFtg2MtPWGEia+BmaZYZi3X0lR+OShKpNLFc4CfVM/" +
+			"aWG6W2BulHjIAThZhTg3uRekDzs=";
+		public const string End_Certificate_IC_05_01_crt =
+			"MIIChjCCAe+gAwIBAgIBODANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALlcUtceuxDznvI3pVM7YddPcBOrNvrOtpuLOa1L" +
+			"Lj9LeNH6+8CzRZnMsUtt+bRGqCKMEJLUIIstWwGg4SskXWk2m+nDKm5Ai6Kyx4nldpgtgQ" +
+			"xZSEwNcwRhpy7TtmLkxDVM9DoTbIbK0dZ7aWw4bXVHPK/lnOMtOaJbFDq0sLfxAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIiXgrRBVcDf0wEwYDVR0jBAwwCoAIJ2DFtxoQnXkwDQYJKoZIhvcNAQEFBQADgYEAhyO6" +
+			"SP6brWDDKZwdQGULno4Om5+DuilJKamyEcvSqE666z1KhvOCdLicqwVa6tQiAL6akrt5Kv" +
+			"R+TT0xqHR4JGosGLGolvK4DLrMeD+PRK7m1a+nJl44luo5Mn48HrKI7jn7n8Lp9bNdCHvr" +
+			"NHaQksCIR/Q8xoucPa+8sCTVSj4=";
+		public readonly string[] TEST_28_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_05_01_crt,
+			Intermediate_CRL_IC_05_01_crl,
+			End_Certificate_IC_05_01_crt
+		};
+
+		/*
+		 *  test29
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_05_02_crt =
+			"MIICkjCCAfugAwIBAgIBOTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCrtIYqo2Is8Cd6Ld+fyWC755oA6hQiiruooaR/6O4z" +
+			"ikyhOUztnHkOGMF5H4CKWafwwVrfFtqe7iop3N6AToEIpNlJLVy3cj14A/IASVYSSNFeHd" +
+			"O44Id1NWhPiKx3paPTWslMEdKQV9BlXb7gu8pQpvqTa/38hNQ9vdil/4QZbQIDAQABo2Aw" +
+			"XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBAjAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQI9P78RavuWW8wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEA0sAEmWBYSazUav6RtuNFtZgNrlQ2i5i138VzRHoF/kq/CxeR/lINQqgJhC" +
+			"ZlUnlslUuM86g8OQGlR8SS0Wsi0MdCQCtPCKA2hStlTx9MMux2IZAGoyHy6P95UE9qINHE" +
+			"fYZUYjO9rh96fzNyJ5Oy2kJdJWdhFXtSh3BSOe0ZD+Y=";
+		public const string Intermediate_CRL_IC_05_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9P78RavuWW8wDQYJKoZIhvcNAQEFBQADgYEAlPLh" +
+			"+CMqRcbLgUKEAL2UlSY5tjsF8At0hf000kec93TnBf7f1NKYVJ5eyeoh/WK4s+k4paAA5E" +
+			"/P2C8JMlGXNTrqKZXMy2zIlufE1ymXAZCKLOLC5ezXRSpwIsBWxko2nfw8Bz/mZO/bCSCT" +
+			"nDwkH8BJIbFV51vJFlyyOmZnCz4=";
+		public const string End_Certificate_IC_05_02_crt =
+			"MIIChjCCAe+gAwIBAgIBOjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMPsWBfT8HqaiLnoUCPAFniq502odL4uVqzOOxkx" +
+			"evZtjh7NaFlRjuYjTofdkj/IAgg7lkkBEW3auK47Td3TvqnHO401PqvOFNTlbhr5wDLmXS" +
+			"WWcR6XrvgYL3Z3wx15/z6eojcSgu07kdvKqzuLzcDs+noG8lbcruokX0A186pVAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QImgomUTkzwbEwEwYDVR0jBAwwCoAI9P78RavuWW8wDQYJKoZIhvcNAQEFBQADgYEATAEq" +
+			"YVV0iYdYomPqxbTapSCJFAMQO/WZhN9brCXP88+jRfk6cAHzTodQOYTOAVe8YXa904505e" +
+			"RA11NNTViP3s/AseGWuqbWjsom9mbR+tVkvufGqPQtm1JhfLgR/68e29AI7tj7zIJyFVYD" +
+			"nLRXGwMGnosqSHDle+WYyfok6a8=";
+		public readonly string[] TEST_29_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_05_02_crt,
+			Intermediate_CRL_IC_05_02_crl,
+			End_Certificate_IC_05_02_crt
+		};
+
+		/*
+		 *  test30
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_05_03_crt =
+			"MIICkjCCAfugAwIBAgIBOzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA1LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCajRjoRNL9HFTytLLx7C8WYouW0uONGsrtGS5tKMiW" +
+			"oLlQUkohqB2a2PhA1InNGQqnbDtNdqKbR1k6EzD6MyegvXK1sXs0ZE8gt0LZYio7Xp3k+Q" +
+			"7i4Rk5iTruAUrV8bFMYmeIXHXL/9rl5LQV8YRp/Ut3Bg3VECzfhQG4EavMlwIDAQABo2Aw" +
+			"XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQI9041oiwvHsgwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEAYwGYwLsA/kxYZG/RM+kvoH+mUebrBVZRBxjovYsYzNznD26fssjBFfiTmg" +
+			"zwZJfG7MZRsgDSRsS+bxuTlXMVeGRKH8fVj7PNq05sS18QZQOF0CCKzg9DLkCzkzkEWBxc" +
+			"5ersciPrL90UarOIPIJWUxQ/5sdMS/wZtYTU34rNNWE=";
+		public const string Intermediate_CRL_IC_05_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI9041oiwvHsgwDQYJKoZIhvcNAQEFBQADgYEAJHTp" +
+			"k+RRsD0dUv59J1GQMWjQTjVz39Xaonx2sk38WHcrHBB78L0W6Skjvt082PwZg32sb7FQBt" +
+			"boAQ3PIKpXMnFnkjnkyaFihrnMdfa0abCPtQhFl3yra+w+1a2RDjQBZOOdq3xlFcLi9unT" +
+			"YYome7eS93wchIvNWFpgwF5A5XY=";
+		public const string End_Certificate_IC_05_03_crt =
+			"MIIChjCCAe+gAwIBAgIBPDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDUuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYxdSZq7qRBdPOz6H+l0GGAtymAWTshfZZCubHK" +
+			"lQjbVq98qudORfhCOZgOy83j/mo2KAecBhxaxB9YA5ggWNAgaKtFvknvjFemtBCZwt6cVK" +
+			"8LCyUGKzStwAV1+HSDlHxdWo7pRwP0beXFvFECrX418osGt6E/v7Cz++ZtvaDhAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIgTuCLfTVa+QwEwYDVR0jBAwwCoAI9041oiwvHsgwDQYJKoZIhvcNAQEFBQADgYEAQRuC" +
+			"rAx9zzu9QwOq9weNit9PNgFHBpo3Gh9jPVYGJjOQxeSqqou503xi82H3W30FT/3ESCO7IF" +
+			"hfpr/uQZVEmUQnvDsVwbKvED1QF9qkTp6ILk38ITJJgfb+sdSL3bsUeNqVXd0C9wzVoErc" +
+			"OuoCulwkZzfoIOlO2YAjAnR1nUc=";
+		public readonly string[] TEST_30_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_05_03_crt,
+			Intermediate_CRL_IC_05_03_crl,
+			End_Certificate_IC_05_03_crt
+		};
+
+		/*
+		 *  test31
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_06_01_crt =
+			"MIIClTCCAf6gAwIBAgIBPTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDmutL9PY/BLXvXMEDQLQnWE7dCOsrLNvJiuSjDdznF" +
+			"vBz6WS/RqUr9zsDFknpOWB3Epo2syV4ZFto+v4VWNo61uaClIEsw5x1y0saG19px34KVpQ" +
+			"wkpvLeRZySdCydKdE1rptYR/JbHvPo5TU4mxOo6L7JeEwAvjSI4tK4rwJ4MwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI1BB9j6Jyny4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAajWMbY8zL8jS2VUjCPBMuIjUvBfy55+92EXg5pZnyNNwN1diZfJFiB" +
+			"rrPWEg3Fa4NMLgaDKWZsYkOcDDo8I+Qb9FsU9LphCzQ1ubIEuxu6KPX9X29BscFOxUnZCz" +
+			"yuzVfadACxi5Y7Bz5pN5LfC/jEb2iXjkdN5Rm8AqT81syIo=";
+		public const string Intermediate_CRL_IC_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI1BB9j6Jyny4wDQYJKoZIhvcNAQEFBQADgYEAxH4/" +
+			"mgACT847PyufmF1nob9TSqBj+cM5ye2bgv83gTVd3B1Gopr75Tnu4iP10d0PpSXjySWCjB" +
+			"0HPJ7BdxzkKxSrcM5vcb/jLdk9PqMUS30ohexsx1xK+E38pDJdLX4kbJ3E62AgyXm9WQlD" +
+			"9xsDk7TMXwuxHT4fX070HL6lWGI=";
+		public const string End_Certificate_IC_06_01_crt =
+			"MIIChjCCAe+gAwIBAgIBPjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAO1VOl25MTf068LOgzmQOmyh8MXunBrQ4t6UYuEj" +
+			"H7v+owR9JTDXpfzLPcYfkR+BH2jjISSHIJsUDesKVhpmhABNXcOI5tiRNkeDlV2zKCBXKC" +
+			"wFi5qkhrE8FUCP0hL8YzbybOrYZYSVEP8GgIgMSQcTvhN/Tor0o1jdJvRLmevXAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIFJA9XGd9UZUwEwYDVR0jBAwwCoAI1BB9j6Jyny4wDQYJKoZIhvcNAQEFBQADgYEApRQC" +
+			"OTU9cp16BHM2n0TdZThgj9kSAQ4wHk/dKNOjYNEWu6n/GQ0alxy1dyRzpsr058FOvft23Z" +
+			"Kp0YhdKG/7F1hkcoNvC2yN+Re44n7S+F/jcEPTWnOX6h1Nkw8OS7Uz2fZ8t61iHjqjX4sv" +
+			"M/cKP+AkC8g7p2tfdkP1fQ6ww5E=";
+		public readonly string[] TEST_31_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_06_01_crt,
+			Intermediate_CRL_IC_06_01_crl,
+			End_Certificate_IC_06_01_crt
+		};
+
+		/*
+		 *  test32
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_06_02_crt =
+			"MIICkjCCAfugAwIBAgIBPzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC0JoTnPaI/HT2eAqCW1204nRNjcA8EQSp87tvHLpWy" +
+			"5aafmxeJxvk5V9Ba7Ye8eY8yX9losbNUpHJFNdE46fD5qp/oS7Cn3NXA0dwIDQEn1X9vaz" +
+			"nqtZtMjt1S/yGv2xDOb2LKT9zRrqSvxGszCHFUBcJ4HDFJMAdhXPUZiLyXVQIDAQABo2Aw" +
+			"XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwICBDAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQI7j2LO1CcsE4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEAfXIh0oYlM2pagAWzTuYqTl0NavtfqibPgolvhgIG/XmmjswHOg/JVCLb7O" +
+			"jIYtEG2MAD0xQXwu0mc9Deufed2embP/wc0qVG7rj7lxUq6p0aMQJNndBw4m9KlSnjdzyG" +
+			"lwE9pNd2BgEeD516J2k7dspCZHDw3qLer4i2JYoCo2Y=";
+		public const string Intermediate_CRL_IC_06_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI7j2LO1CcsE4wDQYJKoZIhvcNAQEFBQADgYEAJej7" +
+			"23qVtwkcvCTPb6afTosYMnVppPXWbtvqn0N5mAFHQfE27x1YPOXOQHBrpQuTyiUdUmPXiH" +
+			"xMKbuR5o2lfdQgew9hbYVk6GegSu+DBC1JKv2YSTgzgRAlJfyByDZ7mbJwZWHVHys08oGk" +
+			"adG6zstavg5EkEeRuAp47T+7cZc=";
+		public const string End_Certificate_IC_06_02_crt =
+			"MIIChjCCAe+gAwIBAgIBQDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMkIzl9+NRTZf/xaA8noiHRt65Zo6Zp57YvCKUe+" +
+			"YfoC8koMq12MBgrc0IyIfJoqEDEMfD1WbitZdGZMQZ7D9BP2Bk09NXLEAAuj+waFhYk0bW" +
+			"vHBH90O7HpMGmxwHmzOjDV3JHYsU8hq77/5gRFDNRkSCJe2A1Maj8Gcqi6tYf5AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIYDfThEjNL28wEwYDVR0jBAwwCoAI7j2LO1CcsE4wDQYJKoZIhvcNAQEFBQADgYEAJiHT" +
+			"CjLGZK5Lyw+7ICDHs3eS1OGJH/wfsLcBP5sLER41qJfrXGTl2XdKvBMIpriUmJYzjkjof4" +
+			"bvS/VPDNlhI9AJadicW8LM4L3qpy7/YV4Dd/C/BJphJ6cZcT+hjaRKeC7gQVjMeC/npu/p" +
+			"jLgIgzf7HC4WYnaS3h9oYl0cMJk=";
+		public readonly string[] TEST_32_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_06_02_crt,
+			Intermediate_CRL_IC_06_02_crl,
+			End_Certificate_IC_06_02_crt
+		};
+
+		/*
+		 *  test33
+		 *
+		 */
+		public const string Intermediate_Certificate_IC_06_03_crt =
+			"MIICkjCCAfugAwIBAgIBQTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLUlDLjA2LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCuUtIYFbVjg8VLLUqIEQ6r7hjTaqYVs8DJnJPHUWPA" +
+			"JW9HEIV+d6hj/so76Bff4KJRX7MgoXbvq4ivmn8656N7YSGk9GPuJ25SXK7RJyoqzG/x2R" +
+			"AVUCx/wG99VXVDZhd5ZAVBG2JCkHImsWAei6/Tz8UgXmmLBM8rZNJ/hNtTBwIDAQABo2Aw" +
+			"XjAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSAFlAw" +
+			"EwATARBgNVHQ4ECgQIpwUlwG1W+sMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcN" +
+			"AQEFBQADgYEAqJhUfgar10fl5qG+oH34s/JS3ku0dRm4cTQvqUNOWA9ALnBhSkmOpoMMzH" +
+			"sE9FXXcZ072a8/ecpviP04X5mt5QSLreh3hPVvgWv1LiZ9YkS4Z2kcr+3Gx7zj4gQgT5vG" +
+			"QPpbIBAtBRH5xNHIYQsk6kOe2+t7b0Q82Wnj8UoznmQ=";
+		public const string Intermediate_CRL_IC_06_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1JQy4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIpwUlwG1W+sMwDQYJKoZIhvcNAQEFBQADgYEAKCp7" +
+			"ViY1cajXpbjCIqe8yo/98SQRIxoTNgp7EUaaV17FeHZ59nJhRtsF1XnLP4cK0lPBkKFhHK" +
+			"2XyDEWx2hK3X7Z3lSAtn12WFJHOP5T5i0DmYfMJYAFbuPD0JQEWCM3aYsgbXKbbFH1BURh" +
+			"L/uy3arVBP4FaJB8gH678K4J1p4=";
+		public const string End_Certificate_IC_06_03_crt =
+			"MIIChjCCAe+gAwIBAgIBQjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1JQy4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtSUMuMDYuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALZw+GpvdleGlmdqZ/zEO2DUGhwgrsselBUNnEzR" +
+			"bcuzr5O1WwiG6aLjrPxIXeL1wLS1/u9AD9p3CQU0XFhi+bEI9+LLnt2y3707O+AQxy1PnQ" +
+			"6qmYE4jMwqDGHn8WVanN2joFT3isLH5wJD0Jh74eoG0tqCHUyOiXaZNo78qgB3AgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIJOeyCnvfJtAwEwYDVR0jBAwwCoAIpwUlwG1W+sMwDQYJKoZIhvcNAQEFBQADgYEAJbz1" +
+			"RipbW6uu7B+f2Ol1iq4AVOUuET2S9vi9ojReyAIka3q1XUceZCm5Et0KqpOoOLiu8IRuNB" +
+			"bvKwRcZ4hcVEXv5bRMqaPEK2B0VrRAV/Llj5A+RGn6yc1ZdkJeBRhoSsaHn5whfICaiJX6" +
+			"j3lMpo/CiMRViL+gZLU3SdKqvdY=";
+		public readonly string[] TEST_33_DATA = new string[]
+		{
+			Intermediate_Certificate_IC_06_03_crt,
+			Intermediate_CRL_IC_06_03_crl,
+			End_Certificate_IC_06_03_crt
+		};
+
+		/*
+		 *  test34
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_01_01_crt =
+			"MIIClTCCAf6gAwIBAgIBQzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDRkBhJJVgOXHjydAHAnokd/XfEiW+bnWd2ZPJrMBmP" +
+			"7TlvVpxOGqLd6lGdbelbSyAzut1i8lyYn9NSDR0PcyehCSS+MsKS2uNKsTEuH3mlMK/7C5" +
+			"B1qggKqE8f7opyl9+U+Qyi1WQj01gY6XYXaCxksCB0Oqx2737d7QWMvl15dQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIO1U69B4DBHQwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAcHWV4Q4z7C+IC4bWgIf1+BzkszCN+LSb4JquR7GgICESbwF2JzR+xL" +
+			"7yoKvB/NBcCqtMY4Hi1DHACbIGJwRe68vVHzz4CmYEK50UUCbAtiAiy9Od6wwrTyFyacBd" +
+			"CBjiO6mkFEp6jOsoIgXRfxK4kDNcMkGUUwMbSR/wZKFuImc=";
+		public const string Intermediate_CRL_PP_01_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIO1U69B4DBHQwDQYJKoZIhvcNAQEFBQADgYEAHtbX" +
+			"MUofQlCnbJhgLQw96jsBRu0Kdx/Rk4LWxEbZQOWNaD7aukASjEv63d1qZIDgpefuUNTz5s" +
+			"3eascdtI6iyWFtBO3r6tihtkkSbxocN2Rz7OlR4rW9VwuUirxP0145nMd5CEL03/CNABP5" +
+			"zUo1bNgswHW3z/RaH6h0j0yTkbo=";
+		public const string End_Certificate_PP_01_01_crt =
+			"MIIChjCCAe+gAwIBAgIBRDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALQaTS1wvv551g3BP9JYBMM+KXXLzxtOwPlO5NR4" +
+			"LwuJJB2WuO4vmbn8AG35in/0JqwjZeroLQvbCPxZseXsyA0+7cMO0qcjRJ5l5WdFsahT6g" +
+			"z1YW8pYYY5i2eDUkIRsM7roHMiNjt3zpkuUGX0xZQfAxhuWnRIvlGg5J4r7UOdAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIeyLSANVaTpQwEwYDVR0jBAwwCoAIO1U69B4DBHQwDQYJKoZIhvcNAQEFBQADgYEAvZ4a" +
+			"SQMNl+Q++D9yVaGr+37XJyxs4yow5e5YM9LXn1qBASQ+GNfqPWoe2cPCPYKj32yulxyFEu" +
+			"RHrbhpEQe+nrKWJgO9W1bmfwgQDin29ne/JCQPlznhd3EPFvCkmPLnTyJmSLR6B2VxvndM" +
+			"GO8JEbj3KCf51uf3VnC/Qj11mX8=";
+		public readonly string[] TEST_34_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_01_01_crt,
+			Intermediate_CRL_PP_01_01_crl,
+			End_Certificate_PP_01_01_crt
+		};
+
+		/*
+		 *  test35
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_01_02_crt =
+			"MIICfTCCAeagAwIBAgIBRTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCkQQXRO+dnU2v7EbaqQNmfPD8v0s5Wa50hl9M1Gfr5" +
+			"5nuVUZs/RI//1VksTNrW10MVh11nsxpA/XRPntEIbHiH1OoECd4dnZBiA/2xEueM02fTjj" +
+			"fb/t7g+pr9dSU/TzCVZDVWFBcPn4VNz7BBqIrTAOXaJkyBZ8hh7vyiE1Y2VQIDAQABo0sw" +
+			"STAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHQ4ECgQIoTKVlZ8YCR" +
+			"AwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEADhtnd6ifr6kyfC5D" +
+			"UWuAXLtoccMj8Jaur/1YT1DgnH1XbBsEeZwm9Jkzr1a3cXPIHgaHYgXvBeGUtZ3XhbCSGp" +
+			"8U6clJz3lm3qKPKkb5rdDrpdTaPnEJJjS3C4ZK1L7UZtQga2Enlelm5vIkhjsF3Sexe1kY" +
+			"mzqiLZZ8yLxJ/Tg=";
+		public const string Intermediate_CRL_PP_01_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoTKVlZ8YCRAwDQYJKoZIhvcNAQEFBQADgYEAn94u" +
+			"sT8ZYNzfHIdnx0+fV0jglL0Kn1duz+ehKHow+RGqH+J9opMYuXVD+rVQnLdZl5LbFBcv+5" +
+			"TSP9WR9QtyoXar4/jmY2FFdBjfgO9w7p7OHD4WxblJmfPVOvrzFm/slZE39Oe5Qn4KlS03" +
+			"9tttEFTKDH3qREQbT6g4k4ExxYM=";
+		public const string End_Certificate_PP_01_02_crt =
+			"MIICbjCCAdegAwIBAgIBRjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANBwkwTWdZ977UAx6CCpXc9T4MX9T3/Tt6LbtY9I" +
+			"eXxI9W15eXm/aqrKiXhULB+oF9/qNeUi2fAtrURZ7hgHbTaswr8CZ3Uwc6Rbkyj2GGiM6Z" +
+			"8sKFztYZfFyGBiNEwfTT0yaUUQ6etIFqPuL/6qLvqXmvNPxFb9gjTH/azs/MdNAgMBAAGj" +
+			"OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIW1/BRCbe3c0wEwYDVR0jBAwwCoAIoT" +
+			"KVlZ8YCRAwDQYJKoZIhvcNAQEFBQADgYEAPJg24q7wCU8CVlxFLchoe7txhkzApkVMIJ9G" +
+			"+QTnraHDn0CZS6undCsJw8mrTNBQPHFn2Ixa5lrPfJvwW4Med1bcJKbwR4TveL1WeYYq6+" +
+			"9k1kS/7KmqyKAKC/s504jAc7qgMd4b08oLxbGVfFVjWG/ZMbO770FrsyRHHs2rTOU=";
+		public readonly string[] TEST_35_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_01_02_crt,
+			Intermediate_CRL_PP_01_02_crl,
+			End_Certificate_PP_01_02_crt
+		};
+
+		/*
+		 *  test36
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_03_crt =
+			"MIIClTCCAf6gAwIBAgIBRzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDL/XgMvoeszcAzZqMYnv1At5u83Gb/CEX3fv6O1jL4" +
+			"W3XbdvBNIZpuTwQhTH4Iofk9rIuQdkR7xOmbk4AqZINuas3Y1CPdzss7teraK0CNralNl1" +
+			"jPYK+ClDBHt32Iw3bAl7RqWX73hl3YH6/7cvG4XCo1HqeeFFHUGa7HXGXq9QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQITMu5Qbn1Cm4wEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAuCnzXbHg87PIYYRbCCiXKDKA3MOcEKuxpNaSbtm12DQWpnvzmaK5nB" +
+			"D/Ebko97CS7u9Tpwa7TmTyi39bYzY0dmVaotCDzfSTpzw6qHZl/w8riS+cKr0mimnjW1cq" +
+			"kGPyHf0zBBqh0liGbd7EOLIBln0ASrn8V+G4Tj0Q6aQVcko=";
+		public const string Intermediate_Certificate_2_PP_01_03_crt =
+			"MIIClTCCAf6gAwIBAgIBSDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCu1Fq+gBJsBf5EjKKtNIxgdtgPMObby7tKH7fTJxYE" +
+			"5LPyPi/IiWQ5Mi/8BCG3zmQhu9ZdBbpal350qCGVTbaMlnpi98D4WwXSw7e8oHIJIK689p" +
+			"Q6Z5cf8hgwPnwDpYLeEaqxwhd4bu0x1lG1fUISA0ZZIQaEeNSJfdh15IkAswIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQILRhQwULcyPYwEwYDVR0jBAwwCoAITMu5Qbn1Cm4wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAlEVOqXcdeTU7wT0l+/BJhlG5iaAcanAsOaJFZsXPjLMSjhldQe11/z" +
+			"BsrrqjcpdctcmBarKO4MnwqVU9DN2RZ/v5Gps6OcPxj3T8wlrCGe4l6s9d1FncBMJ0RAUe" +
+			"QEn2JLkQW5JWRBQ00+RXJYFuIM6Ger2MipWj1oOciv9MMoc=";
+		public const string Intermediate_CRL_1_PP_01_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAITMu5Qbn1Cm4wDQYJKoZIhvcNAQEFBQADgYEAycux" +
+			"rzvy2IiYfFkTw7QgGuBhxIQPbSIbfudqyUumuviHJkIMZpPwYj2wltjyiRaozrDAWq8mlc" +
+			"PsFYNr2lUYN5Cj4BhNQCNZlyBw7LLdzRgza55zVjmYkHWedyZm3kPWe7Y0w8xc/XIvi3iC" +
+			"qlwV+X85cgHNJarx3GEYdb7Yos4=";
+		public const string Intermediate_CRL_2_PP_01_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAILRhQwULcyPYwDQYJKoZIhvcNAQEFBQADgYEAbcjU" +
+			"+8l6pSik8PcuIzWndAg/w8uRfAgR5W9hPSXZChlx7uM+48wK98DGEXuTkJcbeclZia+Mpi" +
+			"J5u3qG1zhoL1aHr+RqyJrjiWKC4/rDBuiUk/ftU54mrYn0qev3aSjf/GLtpcC8kC3gpqD+" +
+			"20bvxLjBG3Vc9ZrxDvzfj8cD9K4=";
+		public const string End_Certificate_PP_01_03_crt =
+			"MIIChjCCAe+gAwIBAgIBSTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMO0l0+X6jfT8cY4DumtseTryyIJ7h+nraogXmYo" +
+			"uhFGvMUWEAZVGD4x9QTTVEL/UCqNfzpI//Pp/uZpDudSgOX0ZdAbykObqCAEO85msK+eie" +
+			"8baS1cW1XGjCuWDqNZko3Uo3c5lLPlRMbZ3hjvA1zmYh3prYnOh032GZAArVcVAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIMh2aWvtm0mgwEwYDVR0jBAwwCoAILRhQwULcyPYwDQYJKoZIhvcNAQEFBQADgYEAigVE" +
+			"FlCgbgKLR9FWIiwnz1bZ0MKsfhytllCI+jGx0Q3o3CxCGXs9PvL6BPDdMOxNIT/oU2uG64" +
+			"EhZEjcZCnUknGx9OkkSSVq44P/pGuUx1g4Kx4i8gsJ/UPrPpYv/3heuMcKWCr92l33cxPT" +
+			"IU+kmAtqy0MBvBKL4p635+MSIVA=";
+		public readonly string[] TEST_36_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_03_crt,
+			Intermediate_Certificate_2_PP_01_03_crt,
+			Intermediate_CRL_1_PP_01_03_crl,
+			Intermediate_CRL_2_PP_01_03_crl,
+			End_Certificate_PP_01_03_crt
+		};
+
+		/*
+		 *  test37
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_04_crt =
+			"MIIClTCCAf6gAwIBAgIBSjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC9gxMP8j4L+ISffY9wkislQ/V5sO9LzZOncYK93lZf" +
+			"HXJG1MPSQzFPNzDLSc2zsilA03v6q+zr4NRrRWwWGmB34NGM4aqkoxox/7ngTn0MIq5gZ2" +
+			"eOx0FbjA9W9DHEceVDS6kgs9lFcN2W+muCG2/fGqQUED9Fzl9JSM/tE8XAKwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIgdUt9H4i6kwwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAxPe0vM0BvormJLF5HxkyFcTtoombfDGANoLoyj+PTWRD6z1/AcAx5K" +
+			"rn/0J1sZo13M2ezaZUABbbpNH9X0OS225IJF4mXNpfkYhsz/+jNPGjRpN2p0K+DhMSawUw" +
+			"QfGv2x6f31k6WCdy/769i1mwKP6Rpph2nkRyYW8MwO0N5HU=";
+		public const string Intermediate_Certificate_2_PP_01_04_crt =
+			"MIIClTCCAf6gAwIBAgIBSzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC7YCtN67S/ItOzaSGqTvfEE483HoQGiQZ0ob3+0beK" +
+			"kmbSGADBQVBKe/sLJEKddyV2Gl8S4x+cKaKBWUI8lMZViJwWqVnyAFd8ZiAB/BpXaKKgP5" +
+			"pFsg10Yo/EtsxGlLSTLurst0azNnFv7ca5Hb8te3T91eaI6y59IjbsRgilSQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIGazrt+QRNCkwEwYDVR0jBAwwCoAIgdUt9H4i6kwwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAUIz/MSc6K5eaIAg8skaAgm6rSPvcU/711b9G0qsIs6YqvEz4zhGi5X" +
+			"nalYYXfaSQzomuRuABNvuR1Ydaw/B9OdPMro0DhX8VpY6NzCL5Qj60/I4is5a+Hzgk82ck" +
+			"eAC3okPHbVMd7R9kdFsWNE3Capnv7rriqXO3vwFw8b9vXD4=";
+		public const string Intermediate_CRL_1_PP_01_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIgdUt9H4i6kwwDQYJKoZIhvcNAQEFBQADgYEAkR24" +
+			"ebKfvEhDA0C7sawukQbv/q8mjSS3CrhA/oqeb8bML1IlW8rjHSXuRU/n3oeyAZuxLCAQMU" +
+			"TPG6Vq4dOu8XC1RY74xIm8ps4mE0xB8/nI5kadHUSDPtUZhNzc8tv+z7fUGRaVGL7CBEpq" +
+			"ICyQKYytCwxyf4xu2Ip71Uy2tuo=";
+		public const string Intermediate_CRL_2_PP_01_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIGazrt+QRNCkwDQYJKoZIhvcNAQEFBQADgYEAjpUo" +
+			"XSj0HX7Wm4w1FiRBBazInGOhSQX9VP2GcGb5lfr3GKt75Y+C+C9qd5X25DVkA4M1gPBK+u" +
+			"XjSMQoHAmFJychQG23rcGcuDJlzRMyfvPCF9dOGLFdmkuHSo5hQUyYsxnXV8cWLIkR1AUz" +
+			"PtUbTJL9g98R/OJFsCBiPi+By6w=";
+		public const string End_Certificate_PP_01_04_crt =
+			"MIIChjCCAe+gAwIBAgIBTDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDQwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOtf65MaydWM3bmMT8tAGCX8gZkx1JlgQyBlJT67" +
+			"2APIkfmKRFK/dBtSwwCVGHZG4JYBrrwMpzUPrkGKYI6ZVIvvPnPfadZns9i5SM5LZFS+a5" +
+			"JfbRnSJd8dXhZsKHxqkxIWwG6+VgnRKXE/Uc4m8TePQJZEOra5ezna5yhvqUwPAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwAjARBgNVHQ4ECg" +
+			"QI4iNoMjKiXMkwEwYDVR0jBAwwCoAIGazrt+QRNCkwDQYJKoZIhvcNAQEFBQADgYEAmOjp" +
+			"2EupE1AmgjGfiGK1fk9kf39yQXK1EDsyO6KLdWL/bmWeYi/G7ZE57/+yVVADJuHI8xVIDZ" +
+			"LAC0u5p35OLgbcmmA5bs52KWJJfa0nbgGpVaUSMg9SkEGS997OsgExWMvYhdFIKXlq4Rwc" +
+			"ca89Hg1GlXdrpfD2OCDNBvcWB5Y=";
+		public readonly string[] TEST_37_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_04_crt,
+			Intermediate_Certificate_2_PP_01_04_crt,
+			Intermediate_CRL_1_PP_01_04_crl,
+			Intermediate_CRL_2_PP_01_04_crl,
+			End_Certificate_PP_01_04_crt
+		};
+
+		/*
+		 *  test38
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_05_crt =
+			"MIIClTCCAf6gAwIBAgIBTTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDFzEEzV/yUEORIOufyqpZzKpYz5aPyBbcDf8AMMCM5" +
+			"tEz7j39cf1f227cbrTcAaUfYFwkrb07RU4bTS2X+U2Ak7Q5OROz5rrZBbsfwF3yHhwHxCg" +
+			"KLjbwz7D+OJdNfv7x2HRckwfMUkmP4cEuJIIPwj1ieBbsnUi9dkWZePwl80QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIjsCjmszYCHMwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAWMUBdOdHMB/SV5kPUk+zut9g/1v/GyxyB60mq9jGqjrIsk4a9JRqa5" +
+			"MWju+6kVfSLelAOCR24EQsXnZM/5Qqg3Wb/SFJXWDcBnfWQWgh8UmJfmPhD7jViG5QVIxn" +
+			"iALNCYtz373L+IDECLMO6S3wcTPsHdYv14jl6BKtabwIpE4=";
+		public const string Intermediate_Certificate_2_PP_01_05_crt =
+			"MIIClTCCAf6gAwIBAgIBTjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCZzdj+ixWCuxJGMjcoHUwSNqI9Wt9gYwXUTl+dWg/E" +
+			"lg2SPJP7lrBOibAhSmaTorhunUSEf2adhdxhuGrd5Ucp6G0oZAa6ZDWaID4rKYWsI7d5kv" +
+			"mrUhDEEdzk2s4PCoPiQm4dKwRg2rIvA5Dv+W1ldqSVSG376zVrQ5xdjDUX5QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQIUASviIKBmJgwEwYDVR0jBAwwCoAIjsCjmszYCHMwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAa3c+0Drcq7iWP7K+gE6Mz/0ATQoiG87irXWfWBUGWtYnsh6K+1THMl" +
+			"ibmZjYhsztK1P5rm6qL6HAyw0PhrRE9imqZ16cgiMomh65BWQImOeiXx9YWIPvjXWsE6iV" +
+			"E31XShr9b9OZBA2+Zpydc3ID/SQzy9PiTAfL5yJiW/JZvFw=";
+		public const string Intermediate_CRL_1_PP_01_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIjsCjmszYCHMwDQYJKoZIhvcNAQEFBQADgYEAZIzN" +
+			"pXT89MplQgcXcA/K7YKlf62QCbw3rE+bUQiumJMlNGiVdaNJ8T66ObyoOWE+s+KN/Oetlu" +
+			"HglQ7r6RG68gHYtZZiO6kmxq+wor65dFGQyRggpD+D47yioEgR12wUUksL/8oBW1pfGW2B" +
+			"dR4sNWjzV5k5EWbLYu7wxj2/ubo=";
+		public const string Intermediate_CRL_2_PP_01_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUASviIKBmJgwDQYJKoZIhvcNAQEFBQADgYEAlZ06" +
+			"h2L/89GvCtU1K1VtbHPMN/LAUYJrWFID1Eo+Cf/5wKEGBr8hxRtvshTK436zqVQRQN/XTq" +
+			"7u0SLxvIixNRErlmUlGByi5vumN2OA77SxOyqYLCnBXTd5tWbFGz/udjaNk1MxOK0MQxPV" +
+			"9R+HHUUVojRnAIQvlcqx/sMzU5o=";
+		public const string End_Certificate_PP_01_05_crt =
+			"MIIChjCCAe+gAwIBAgIBTzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDUwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALyBn2GKvoKNHcu3AEJRCbWOyUpCc/onvRoQgWRr" +
+			"wE7vMI7vjqnoR8mXdWDW5u9DFu9V5pb/yHBWn1zpgFGNnLrqn8irwR9i6Q+qlu4lXL5WSr" +
+			"DqBqEKxrOBDPgkVz8Ldjt/Hy57qEukBarvpAwTc4XEJPAmxNrboMeGCEn2UShbAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIaV3Cd/83r08wEwYDVR0jBAwwCoAIUASviIKBmJgwDQYJKoZIhvcNAQEFBQADgYEAVJXz" +
+			"gooT1qd6rdehnLxJMf1HZ6JuqpyoQjzWF1jA3SkJmBDMXvAkMmIcQ7r5CZHaVF0iMQl5JW" +
+			"fxPtM9Bws6jZhVL0TkwJHmbnSvbzUkJYeXPCP7ags4bu5I32co1nFVF6wf3aQDZeLFj/TU" +
+			"1GCQ4rh80T5oknuazD4xXAYx9sE=";
+		public readonly string[] TEST_38_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_05_crt,
+			Intermediate_Certificate_2_PP_01_05_crt,
+			Intermediate_CRL_1_PP_01_05_crl,
+			Intermediate_CRL_2_PP_01_05_crl,
+			End_Certificate_PP_01_05_crt
+		};
+
+		/*
+		 *  test39
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_06_crt =
+			"MIICvjCCAiegAwIBAgIBUDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA2MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCjeJAwaZ0cw6O76hu15XadwJiTsIJcXZxGAETq8H9p" +
+			"VJs7kJh57oLpO/lG8zG89QS9g1ozxaaGDWsSyXsDzv1eqDVZg3ISQu6XcKdDu8EwgQDY3S" +
+			"EGkJ2AidFue3l0kEwR9+rtsuVKd/P+ULF1hWcoyLB/sQD5z8GvIiDKyRBiFwIDAQABo4GL" +
+			"MIGIMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMD0GA1UdIAQ2MDQwCwYJYI" +
+			"ZIAWUDATABMAsGCWCGSAFlAwEwAjALBglghkgBZQMBMAMwCwYJYIZIAWUDATAEMBEGA1Ud" +
+			"DgQKBAh9i6tKUsPTgTATBgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQ" +
+			"B/Gxsb5lxSTN21CrjBp2aE+U1oTP2MpIFWUD1q8KWhZZF1iCQ7orcDVITqJPdPxDu1YwKk" +
+			"zOegc4YBSJzHZqF/W4Kw4wisMfnWLTsUAeP/Ucz4vXk5rsf7IRssFG6PLxVmtRZizoxl9a" +
+			"DO9abTM/jV8Mgi1IB6LdWgmtosBGBzbQ==";
+		public const string Intermediate_Certificate_2_PP_01_06_crt =
+			"MIICrzCCAhigAwIBAgIBUTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA2MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC8DbqYUf437toWlRkOQA5PloqYQjWYpiR67yGSjQHp" +
+			"j/HlduTYFS4qfUbLCjH4qsNUH8yQDvogImQw5M1IQOsUAqO6mYFxjqUWccuOaHT6XfUaOs" +
+			"DDHr/tQUvhz3LJryaILiPlNcQF8QiYpujM1utVRyFpmUrMAlOvWUB93c/xUQIDAQABo30w" +
+			"ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAgQxGVMTJml1TAT" +
+			"BgNVHSMEDDAKgAh9i6tKUsPTgTANBgkqhkiG9w0BAQUFAAOBgQALJtPqY5uROJ+2QYTekn" +
+			"fSUc0gC7j3/cngIvxGT385xDLTrd6TjYSi+12+vU7RNd3MIZoz1o7RpWQV6C751WtOFuZi" +
+			"iXeQ758aLqfhjYSVW/NHkO8vjrAMUzUbgjqb03k7q5JgtT6udB+9ySmou2/RxYW5p/IT17" +
+			"euMVGmQb/RFg==";
+		public const string Intermediate_Certificate_3_PP_01_06_crt =
+			"MIICojCCAgugAwIBAgIBUjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA2MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCsQqIx0ayxpIE8NduclvK1ubbNkXyvr0RDqnGOoyTj" +
+			"yMtnfnwRbclkFCNBdalZYofuTWP0reqvqGqsBj+RS3uazvDBqVmn0J0AGRiLILummgEFRJ" +
+			"ow8IB1hduDYJpDMrHRpfXpbG2H3fzN1XeX/B0hUZgdQ86GyK2qrmyIcyqZXwIDAQABo3Aw" +
+			"bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECNKJMmEWCA+jMBMGA1UdIwQMMAqACBDE" +
+			"ZUxMmaXVMA0GCSqGSIb3DQEBBQUAA4GBAKv9F3+Y4N8RX4bRZ4fFTKri2rrB4BsVrBFpOr" +
+			"SLzKnuyO1O5gg45d70pSHUAVBn3pz0f/6WwWLECq9tB7/Fphi0TyqeFmkRnysygZGlvLgs" +
+			"L19bpIgVPkjFFziMGuzdAFIGy8vnV19yJ2euMygEHr20yiGBUaHHnKyuOGbDg4i7";
+		public const string Intermediate_CRL_1_PP_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIfYurSlLD04EwDQYJKoZIhvcNAQEFBQADgYEARL4u" +
+			"DZvfcQDYanTfwU/hWAJDdDO7m7oQZLy3o0PTqXkk2Jd2v3+M2U8UN2PcuqZXT1lwS/piiW" +
+			"Sc1x1YndD0qUtV4bOZ9SESPhCeOc1lQTk5mMf/zqFxQqYv8rfDB5O3QY4bjS7QQzSsvmal" +
+			"TGCnoHmUJ4skmZJrQAzYnXyD9G4=";
+		public const string Intermediate_CRL_2_PP_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIEMRlTEyZpdUwDQYJKoZIhvcNAQEFBQADgYEAcEyr" +
+			"sgLhVq0L6N5fww/U6TW4lqaVAEtjqxluWRyZnL3AJLEHfwh1lllCG5dNM5fahGDOW/53fV" +
+			"+gW5l92bsi2D/lAkDfNUdQdi5ZpQG9y2zhTArUlx9z1+KXklCi2Gg1X22gi+cYbK2hfzk6" +
+			"kNGP1v42bjrkF/ECczpy3e41rEg=";
+		public const string Intermediate_CRL_3_PP_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI0okyYRYID6MwDQYJKoZIhvcNAQEFBQADgYEAp3uQ" +
+			"Tn2HC65TFmSjzvjuStIJwJcVahNcTWiGdtfTalZrMtuC9vUgQq0K1QIa7QNC9C3hQlzb5e" +
+			"bO7JhJDs+5GZnnsqHN3pvdKEoueRfWBjUGpPnSGFD61ysf9aDFY2j9Amf3zcBFsXZs4+DM" +
+			"dIENndbjkwqCV4zRTajAqCsIy20=";
+		public const string End_Certificate_PP_01_06_crt =
+			"MIIClTCCAf6gAwIBAgIBUzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wMS4wNjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA2MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC+IxiNJMOQG2gx1xd9ELNuzs9LrVJVRLvgP0lpWrx2" +
+			"2HTEXPDB6YmrEg/YgyptmQ5Z4K6CEgJz3EdDOarCSGcL7DmcSEwEw46MV3piS5DrHwQ4GH" +
+			"a2/ENSh3lF+6dliBwbQR2necmQ5g8ekqkWNb65pLl6RCNGkntJpdu8w5GWbwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIMf/eRyakKwgwEwYDVR0jBAwwCoAI0okyYRYID6MwDQYJKoZI" +
+			"hvcNAQEFBQADgYEADgpHRDgyPuK4dc+m2p0IELHUAK3qsdTZzBXsaA0rkkk1aRjI6DQ2qg" +
+			"b4crRU3spQgYwBC7KQYd/hp8Lk17iX6fdV/9wol0DxTGhamOJA0uRl768awRArf4cEUElF" +
+			"uWPN8D3wJEfL6BWgReUJWg8V9HEtdvXZZgzFN/CgHRkQ2RM=";
+		public readonly string[] TEST_39_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_06_crt,
+			Intermediate_Certificate_2_PP_01_06_crt,
+			Intermediate_Certificate_3_PP_01_06_crt,
+			Intermediate_CRL_1_PP_01_06_crl,
+			Intermediate_CRL_2_PP_01_06_crl,
+			Intermediate_CRL_3_PP_01_06_crl,
+			End_Certificate_PP_01_06_crt
+		};
+
+		/*
+		 *  test40
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_07_crt =
+			"MIICrzCCAhigAwIBAgIBVDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA3MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDs3Z/FfgJOyKp+Ds8xiQBM053cWylYbD+g+zuWDz3d" +
+			"nD0eF77TLPITL7hwI058Pn3tXHlveuKMFqbvzWUgFXaBoHmmRohIj1eqfJQhlmKLjlSYyC" +
+			"N4xhLVi7vg71ZjFdRk1k8ME1HDfpb2WXqXh9LyRYY8b/aqL+NHe1PUDbT6FQIDAQABo30w" +
+			"ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAgvehPxsTfSBDAT" +
+			"BgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQBpdMBEONGcpFitMN1ihf" +
+			"W441E4HVTQwtF+h56aagVFndUF1gQsVEdDNmvvN/jdlzXotcfdEj1lOahmcwWbPOlNx3PB" +
+			"LUPAcaNM9SCrXWi1gKJK3gXC2OAxj0mT5XhfPlAdfhZXTBZLqMqebmk6kVwa+VyPPZFHGy" +
+			"BW0fV2ClJ69Q==";
+		public const string Intermediate_Certificate_2_PP_01_07_crt =
+			"MIICojCCAgugAwIBAgIBVTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA3MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCrO/98w96Bg5YTTmtdc9sL8AOABGcYx5J8E1Y7/GhU" +
+			"2sInc/j0dtBbE0Tj4KFIKpVLD0m2mTyHVCUA0/QGiS1Tq6DzmZW/V36Clya3CoX9rDTJyU" +
+			"cKHpgntV19fFAK58aksyKCdP9jjLpbSspzOlIc+mVW+hkjgw3NcuY6fAOQvQIDAQABo3Aw" +
+			"bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECEmeATXRkM5EMBMGA1UdIwQMMAqACC96" +
+			"E/GxN9IEMA0GCSqGSIb3DQEBBQUAA4GBAG/Qv60jyImedUXtCYl0QpQ1Ne2ZLxvUHRLms8" +
+			"B1nXC/Rze7zfz5cwiyQn+6XN2rhuYFdTMDEFZDIjeeCLNllfan4GUAdRGtoJnfoLOGLlQf" +
+			"RW1ONc80cxd1NTxHqxOtqpWdoJQEn8070WLqQPACEs88XYKBZ00sF9ZdSg5vhHUu";
+		public const string Intermediate_Certificate_3_PP_01_07_crt =
+			"MIIClTCCAf6gAwIBAgIBVjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA3MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC+5b7o4iWl80ntDMKGcnquLQDTGlf6Gy/8y34Vw08/" +
+			"8ij+nuHMiKpo6UCF0OpDcnkJ2ovvMsY5dAb5ErhH64UbnMlKbghnGv0sVidtipoC8u7ey1" +
+			"YUIzDCdmbNvTfho6IXKzH8ev//K+FJd3qBuKHl9u2Kk5+igsyb+bPSid7d/QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIUDKu7h5EQ70wEwYDVR0jBAwwCoAISZ4BNdGQzkQwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAnKhR3OvdgtVtmio7ikCvjxlSoKVbUleazxONOxHUAKdXEv0/mSOTwp" +
+			"hPPIoE2xAqPOOHvXPmzmJpPADjrfhU6afJ7ThDRFTMk4ZLOkT1SvRlymK7uWhj5bhUgi6S" +
+			"UQ2LUmrY2hIN4cTrrzZvDw2Q/6UIuqpmySXEOHDL5T5MXEo=";
+		public const string Intermediate_CRL_1_PP_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIL3oT8bE30gQwDQYJKoZIhvcNAQEFBQADgYEA4gZR" +
+			"71wRXNdxWe7kaQPAw44UUw+cN1bDBU0RV7nwYAFDYxDIaDGOfjhUVTMBq4rb51S7uqIqYS" +
+			"F6j7BdLXl9WVRJobfkRH0t0cBnuSeQRz3ckrZrCuvyxb3PEL3pbf0UH1i/BfoG+EHJAY7R" +
+			"OVOL/dyoXeX6ehH6ImGhucDixS0=";
+		public const string Intermediate_CRL_2_PP_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAISZ4BNdGQzkQwDQYJKoZIhvcNAQEFBQADgYEAfzKw" +
+			"NHrl10PJDHa3olBYXYzXi94zxDsEQSIb+W4pPXUfDZijPqL1NzapLqc/uL1Sl28GmLDrbm" +
+			"nCrlMn1Kt/gI6XndOnSyC9Sg6WDxAI3HTHxlG5MHLBn9Lb36CHobnwep1BMo8zl2clh0Kz" +
+			"PIxQSGXM1BDpHkwF5eoFAolDih4=";
+		public const string Intermediate_CRL_3_PP_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUDKu7h5EQ70wDQYJKoZIhvcNAQEFBQADgYEAj7+M" +
+			"EeIe1GmJpbRUFqbNrDvT5tHjKQMNdbe5Y8F920U5t0ig1Up60kc7hs7LH57i6R/quPOpym" +
+			"a9Eo9Bql+P2Bg9FELih5/a4B021TZBmmdSI5fwQZ6Q5PjgG58Zl2cJitNYvGi7tVUBojA5" +
+			"CSN7KBMyipia9ivxm9a/llJPrQY=";
+		public const string End_Certificate_PP_01_07_crt =
+			"MIIClTCCAf6gAwIBAgIBVzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wMS4wNzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA3MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC/RmUcYHxgQRHCUh5cMug/J2o8DzYbT+2pIehJkNCr" +
+			"zfqemV3qshLdMct5GV73oEkG5b6n7tj3/hI1TLh/A3LQpKROAGZybdo9fk4Pa0+6V6ql/U" +
+			"NnSpcAKct/f3IvchGo9nBGdi9aE+j+xKhMM6E8xj1+Jc7Z0xz7zE4+qRbeZQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQI/y572lfRyH4wEwYDVR0jBAwwCoAIUDKu7h5EQ70wDQYJKoZI" +
+			"hvcNAQEFBQADgYEANl9zdMKbaq14OP45PeK9D4ftOSuliW2di1qAX38FQoWPYLLoaDU0Q1" +
+			"9I54PDY/UYRR9jKDl1WPhV6cD+65eadtiOZVr/h1CaW/HxTloouzN4z1zCXMC7AxZKo+EI" +
+			"XLN8f4w7hKLFYgf6gP9+iVi+T2gKfH5Ch2zjRhlmGFRgsBQ=";
+		public readonly string[] TEST_40_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_07_crt,
+			Intermediate_Certificate_2_PP_01_07_crt,
+			Intermediate_Certificate_3_PP_01_07_crt,
+			Intermediate_CRL_1_PP_01_07_crl,
+			Intermediate_CRL_2_PP_01_07_crl,
+			Intermediate_CRL_3_PP_01_07_crl,
+			End_Certificate_PP_01_07_crt
+		};
+
+		/*
+		 *  test41
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_08_crt =
+			"MIICojCCAgugAwIBAgIBWDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA4MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDDe20HLq7R8b0fWTsEiNV3Z5IbQseZ8QCW+1cb6yM+" +
+			"ArKLJDnXx8zmTHSHQCpw3G7xhGsxA1btm0cSC5P/1bw/kFWsSLRe2NFF6oKU+7c+cgIUMB" +
+			"kzyXk+kpWAQRb7hcb50iKdKFtO8gMNGMAxlHRI05/1tThyAs9suI4TrxTS9QIDAQABo3Aw" +
+			"bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECFxr9vgF31fKMBMGA1UdIwQMMAqACKua" +
+			"6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBABaX7TYfmSyVmzGCVbTFweUuPilo4wzy7z/w0x" +
+			"y4uSaM/YMtixUdDPpTHOJNYDdeV85v+w9oezdL2ZYAaGn7tldC6k8ouq/6hOGGST+ziHJS" +
+			"gTOD8UVBQPRPvWEwgmDIprnzrVRz8rG6uqslXNiBDnO9BMGpRo4dy8YpOmV6BPCD";
+		public const string Intermediate_Certificate_2_PP_01_08_crt =
+			"MIIClTCCAf6gAwIBAgIBWTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA4MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC8nLZcMLHYKxVqbhwJiqQbAYhf7S6ck2O9AhNor935" +
+			"Bfm7/8qVZbBAotQy1PoCjSW0UYdknDolWvi8aAtO0f9XVrAv6BZVVW9j3osIGN/XUThaN+" +
+			"9dZ83kGpyjeoitpGK4wbFNDteuBFYp+8gFNupnX7JQwUK3aGwBUucbe7puRQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIL0xyFYBk4OcwEwYDVR0jBAwwCoAIXGv2+AXfV8owDQYJKoZI" +
+			"hvcNAQEFBQADgYEAPk+Lys0Ueoyhp544EH9Hqy9+gY+l/+N99v7KvBlZWKuhkwZDE+qAYT" +
+			"P/SOPsWe8ADZE2iQ4pOlpK8jSqtJSdK69RgGL9omLnR04L9c/zKLArBE+VmoV7mohcQp8x" +
+			"aB4q/g3QnAqwfFYDjIWW3H6gRAeQ5MOtKdz/4042fJxc5L8=";
+		public const string Intermediate_Certificate_3_PP_01_08_crt =
+			"MIIClTCCAf6gAwIBAgIBWjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA4MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCvy6bNOyVaP8JTwiySFa3Sj+rdSqzkalK5gA7DLk4q" +
+			"AyvnAK64HgbCsb8dpnSi94WBDsocrQ4C1Ltoahc/AZyRVLA/REsAh1r3/0FALZgYiIxvSF" +
+			"m3ihKb3P9URBbotzhl1ahRZPSrcxKwNXEmxB0gjixGW7GZTARq3Il5ressRwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQIwFtfZBe/KqUwEwYDVR0jBAwwCoAIL0xyFYBk4OcwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAeZhpIDEYyV/LkOtUf1TryemJExQ1jdfirJ3AUtoFIoWz1p9aqnV6Po" +
+			"GAMozjtdyotfSA2O8c065DwD+CvUXPmdD+2vWpX/2hJPj+x++UvvntAokD2UE9HCeEvBHK" +
+			"rr59hvKKd6GChyhAjLris202eTLIiMEoyZy9X/Wt1nXF8/g=";
+		public const string Intermediate_CRL_1_PP_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIXGv2+AXfV8owDQYJKoZIhvcNAQEFBQADgYEAhkwT" +
+			"E/EGAe32J883qVrh1wG5xQzO/GGfp/zuDYGL2k1zZ2zq7MajKfzBoXXQ3WPh5dTK1sy5o5" +
+			"boPHG0pge0B4/2JvuDVS539+9HAPansUNsrMXzOblg1acjdKtuk4oS8PIYkM/lbA6yJl6F" +
+			"QMbdIthWqa2gjaWKll3R8fVUjxI=";
+		public const string Intermediate_CRL_2_PP_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIL0xyFYBk4OcwDQYJKoZIhvcNAQEFBQADgYEAN6BQ" +
+			"sEQT5YCvs9vlUSdG4gjTgNkyQTCdmSIcufpK4MG/AoW/Fn5zJXxiMyHmvT/dkk/UOf82/s" +
+			"41YI/Inz4qRmGF4IL7jo+l7V+OI1n+Vf4ClgZU6ocb9d1dFoBkJu3xI9dcWK6ExpzaBUXw" +
+			"rPJilV4M5luGbszdDCs9cLjmiRA=";
+		public const string Intermediate_CRL_3_PP_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIwFtfZBe/KqUwDQYJKoZIhvcNAQEFBQADgYEAkmDx" +
+			"t+r59llppKmm9mSTof9/BX2rNyG9LfIH7wweoDi9be2vYOLy0NU1kJ8f3/muEw2v7hWDri" +
+			"k9ROLDFnb/S8MYVT0l4rymRhpshPF1uMTOZmfJUCfTX9jIaShztSScqcGSP0a3EUfDD14R" +
+			"1yMu2pdlMM35llE0lV3uf/eUNr0=";
+		public const string End_Certificate_PP_01_08_crt =
+			"MIIClTCCAf6gAwIBAgIBWzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wMS4wODAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA4MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDTWNp6Oz39wwU8AFDzYVs3UfVvXg+t6j/qFavnvllI" +
+			"NO6aU1o4Hnk1wfmTPZPErc00/MfizMSumTYYRl21hEZWhjNO5uQIHrF9V/4OToo2iOfsPd" +
+			"gxwpSokwxcl7CJyadwUxhRDYCLhSORXoCK1CPQZjwb+uQz799O5ozb0WVNYQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQIO1TNJtWwaiIwEwYDVR0jBAwwCoAIwFtfZBe/KqUwDQYJKoZI" +
+			"hvcNAQEFBQADgYEANmP9hyFnYvi8gdtRe8ERoEG90NwoyPTsB8sXd40f+Sm1QxKqMPzKPL" +
+			"7bOtY12JGwZ55a6HFVgpw4PnU+0iOcCMHS5OQQLtyirxX2HfioiXEmcmRJT6FvLHrGIHGv" +
+			"KNcfc3rUiksdOb6+j2k8x4IwQ6pBEHQwY8U4Y4DgqALlqM0=";
+		public readonly string[] TEST_41_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_08_crt,
+			Intermediate_Certificate_2_PP_01_08_crt,
+			Intermediate_Certificate_3_PP_01_08_crt,
+			Intermediate_CRL_1_PP_01_08_crl,
+			Intermediate_CRL_2_PP_01_08_crl,
+			Intermediate_CRL_3_PP_01_08_crl,
+			End_Certificate_PP_01_08_crt
+		};
+
+		/*
+		 *  test42
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_01_09_crt =
+			"MIICrzCCAhigAwIBAgIBXDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjAxLjA5MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDJqSSqGjgI3JUJfA/XkloAOg2QtZeAGp2nCq1Oiply" +
+			"MTjJpMpEOSRYrEIgKMGnBPq33seP7X/obCT2jgexmbFT2TmPirM+h1aqbGQ7QAqsx80BdE" +
+			"ofdcfiNosLbbzli9qFrbarO7fJfBhzraBFGDJj3N8nLi2YtP9IieFYJ/MhKwIDAQABo30w" +
+			"ezAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAwBgNVHSAEKTAnMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwCwYJYIZIAWUDATADMBEGA1UdDgQKBAiVRMrZuHQ7VjAT" +
+			"BgNVHSMEDDAKgAirmuv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQCetZy9JMzUVveSPE2fQY" +
+			"4fRVChyvIc9nCE4wbzhnRl3zduBGmAwTFr7dRWSFTnEq1c2b6B5nJtCzmt4Ovapf69sIlM" +
+			"s3iV16eBB1WTNCY8YlAsnmZ7q/AR0t0vX+hh6QV6zN5xqulOM4Y8csZEx3RWJzV/LjE5w7" +
+			"mKvofBEUoqQA==";
+		public const string Intermediate_Certificate_2_PP_01_09_crt =
+			"MIICojCCAgugAwIBAgIBXTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjAxLjA5MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDWUTlTieoi7aLGUYOAgqUC2J/6JarOWfv4vobpwjAA" +
+			"DjvQGqg/GCZP7FgD/72Z4YefZKJEFZTDnYfmy2qh6iBYxcvLsJ+PJGzPCObNSmyq8gpeXy" +
+			"KKEeCZtEev1tSywTT6E5Dhee4dX0QHE4ydZEliMMXGRW/8ffT6x54CPwVylQIDAQABo3Aw" +
+			"bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECAMhmGN8+qXoMBMGA1UdIwQMMAqACJVE" +
+			"ytm4dDtWMA0GCSqGSIb3DQEBBQUAA4GBALNjokGrTnWsPn5KrlO+g3R8tAGM90JQDjfrap" +
+			"xWM+nN+dUVVdGU6w2pAOAq2UhfySiP42qiFChnPK9oOqPF2Or7/kcmXZzBfZkE/FnJGNUA" +
+			"gs9je1nZvTPQYsF094OqE7QdJi2k3seA1tqejA1kihMHpwQNmIp8bFpqn4dPO6ys";
+		public const string Intermediate_Certificate_3_PP_01_09_crt =
+			"MIIClTCCAf6gAwIBAgIBXjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjAxLjA5MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDHUpHhF4ANNLOywnvpqyDgzLMtatW3ZxgLBBRYk6TE" +
+			"jMgTVKmRasVRTA9uatGG4b2f70YWs9cOd4ylQDqPEDdKNZ47bqZdX6RAU3j1dO9LBwWDbp" +
+			"NvZ3zuDBRDoCZClIcBESDYweaZ9nUgKl/WxTeCnMwqkfSJGYBBcHIonRPnGwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwAjARBgNVHQ4ECgQIyppef22OmjEwEwYDVR0jBAwwCoAIAyGYY3z6pegwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAOySUCY+PZxomhWgTRSKRodOIe/QSfCMSC+0iw24a2TuJzFLjN9pSm9" +
+			"0C2PqWbfwD1uDjrteO1NK+1yhtIDySiptR9GmR/fhL7NJ+z7M4fEJBjjeeI9/aEIuHuBFT" +
+			"TVHfwsJxnZtjujtOdl56B825LsKW8Otumd2A43N9wIgSyBg=";
+		public const string Intermediate_Certificate_4_PP_01_09_crt =
+			"MIIClTCCAf6gAwIBAgIBXzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjAxLjA5MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDR8/c35YqAswoRMgQswlTbKB9oYEzrFSC0G4dt8ydP" +
+			"O4PyQs+J8wUVrRVMiVDTLO9rUnzR1T3iA0dqM+SvWMIA8pMWKyNV58f73ZPJIejhxMmOZa" +
+			"sSLHceMmmMRy1zyk38i3ZJP3YhvxffTjWyTZ9k2xSDX+6KNnkiKkJSKpl6nwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIpcWcVIIu63kwEwYDVR0jBAwwCoAIyppef22OmjEwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAckgV11ND/D1vfPEMUbDGUvtmsziHiSuEoDLJqSAhOmcX+evKWOfoVo" +
+			"f7og+0ajuul7yuB+7YX1AakOw+33k++Rsgg4o+ImZq3+VScpgnIQ037OOhgH3umwFRC0r3" +
+			"NpWqhmQuz+mHnKiK3X+IDsQOFkhnpNs06CQSZzmrzbYlQU0=";
+		public const string Intermediate_CRL_1_PP_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIlUTK2bh0O1YwDQYJKoZIhvcNAQEFBQADgYEAkEc6" +
+			"qHGOWZXYTQ5fsWyJgEtuJyl8uJ+gMcikcMut5SIJTTtOz+q3wclYDevT8z1MM25kNdgwyg" +
+			"b1bwHNAG8I72eIDtGfLrChFwU3qpvVMTG9gPYJb05Q8On56nsBu/PnnzJervzxjViaeOuv" +
+			"kjwwfmWqGkyiK433WxzgPqE48eA=";
+		public const string Intermediate_CRL_2_PP_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIAyGYY3z6pegwDQYJKoZIhvcNAQEFBQADgYEAV9Md" +
+			"8PaNoIlT7WIwnelqrbwsR66vAaT8w3gu8XDYXu+MOYThfyERUvtH6AUrHWfiRvWEzKljHH" +
+			"3BQB0Zsa9Zz3U5cLzJcqtqDc1lH53aIA8MflrfMVrYSF684s28FikcukmA5Fw3+7S3TJ18" +
+			"Hq7plHwTCidVD6yG35hsPwcjTrE=";
+		public const string Intermediate_CRL_3_PP_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyppef22OmjEwDQYJKoZIhvcNAQEFBQADgYEAjBaP" +
+			"V/TFQtDLxQFIBCbfqhlgpOfvJBatjNuvB0TuD2rsGS1eaLNfTfyVKlOLpxoKwKYMu36kIO" +
+			"l/+KEPDq+ofy7uDZ6GLK3KZ/WiJyriqBQjFCvlhNTW1cjA7Ejk2lOM/A46mrUS9xC+aITh" +
+			"d+/UYGt6O/e256cOwQCUaF2z328=";
+		public const string Intermediate_CRL_4_PP_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIpcWcVIIu63kwDQYJKoZIhvcNAQEFBQADgYEApZ1l" +
+			"w5SJoU8zeKwX5jpVWiFFFomDgKsNlkkX5mF88l0B6MiYbGqJIowJRfeIlxvPOf20imN7Z8" +
+			"l38DRXFacDQP4y5kxM420dp+ljQL5q9RsrC1+OS7I7TGgGwPoZTO4mHVk8nx9MyT+kW1OU" +
+			"x9qRYWN0CLmP22kutYBndny222Y=";
+		public const string End_Certificate_PP_01_09_crt =
+			"MIIChjCCAe+gAwIBAgIBYDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wMS4wOTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDEuMDkwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALiOjwwwUk1HNwf2rdzPL2okKTgL+lMdzhC7cbq3" +
+			"6A409EY7iipPCcsDsheo9EaTNOHV9xjWDqOhqjA38h4hGNkRUVOlTW2r8SoHISn3gDXfrh" +
+			"aHbU3owscAmt1nuA7rzo7L1eBPsisIIxAY16uAmVN5RdiAAaP8VUdshcNI4/1jAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIGZIY3nffEXowEwYDVR0jBAwwCoAIpcWcVIIu63kwDQYJKoZIhvcNAQEFBQADgYEA0Svm" +
+			"aqjaeQx/lnF223xlCTsU7XzOxbHetRWfeCTw0QrWQaTrKjWTS/TNyzLhGuPBFg+NTTvWML" +
+			"gzteo/WWdF8+d2rOis9FVRCe/Euok6ZCL/xgzaE86ZSQg0jj6458TpuC2cszSaifRSlhL5" +
+			"ogy4ADWgJxdVcBrgADo6QZXkXXw=";
+		public readonly string[] TEST_42_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_01_09_crt,
+			Intermediate_Certificate_2_PP_01_09_crt,
+			Intermediate_Certificate_3_PP_01_09_crt,
+			Intermediate_Certificate_4_PP_01_09_crt,
+			Intermediate_CRL_1_PP_01_09_crl,
+			Intermediate_CRL_2_PP_01_09_crl,
+			Intermediate_CRL_3_PP_01_09_crl,
+			Intermediate_CRL_4_PP_01_09_crl,
+			End_Certificate_PP_01_09_crt
+		};
+
+		/*
+		 *  test43
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_06_01_crt =
+			"MIICozCCAgygAwIBAgIBYTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC4mu1oBHB9BeorCFJIuSw5tszmmYBD4bjTklsAfjrz" +
+			"OknQsYxEoHfifpdgivh1fMUk+mK5YWUz0G8/edquKbJhPBTTWp8opsGzTATsTLSEzkKbVM" +
+			"DQ84ttxrhJWlrVRlouZTnD5HoLUvujY4EdydmKsjj6UBt/tGL5EKodymcEtwIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEKMBEGA1UdDgQKBAiGRi8YRte8PzATBgNVHSMEDDAKgAir" +
+			"muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQDHOaIki9TogVJn54FRPl+7FyzBJ2DnR4RTM/" +
+			"q1K3COWRdtvmGqtBBtAccxWziQJ5TnAQn1XA0cFPoCgymGPRcUz+0+C+3VhJ/m9LggVP3/" +
+			"pjJEG0fsmJtUYPyphUlXeUzf4qSj34SlJws3DIHTR8ozAR75HZmlMRnxyZBLl+jAng==";
+		public const string Intermediate_Certificate_2_PP_06_01_crt =
+			"MIIClTCCAf6gAwIBAgIBYjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC2rptuREzhGfEJ3U8ILPBq+z0s+aafMvBRHpqkipDq" +
+			"bC7v9zpwg1K18F4MYiATpPAEfdEeprKs0mWfdusF93BoMBVm1y0zRgDRUNdyB5GFO8g8+2" +
+			"yNEO6L37c1PwrMLnvJakaqwbbnwlcMcKtLHoX19fyveQQg5DNj8WcKZj397wIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIJPt6qKdFeYEwEwYDVR0jBAwwCoAIhkYvGEbXvD8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAkFJGNze9/6YX7Rv8FR9obFGACIJ7Om4YQQRW9WM9pEDgKls7g9b9El" +
+			"dJxLKOlWoRoYZIrbEam19traE2O3dxqRevPoYvfAqkR089BkxH/cFYyfqw64IpjDG84dsY" +
+			"XieajI/Ov/HjgF0VQKF3+Y1ZiDjb2OHNgMkqs9VmUHaE+94=";
+		public const string Intermediate_Certificate_3_PP_06_01_crt =
+			"MIIClTCCAf6gAwIBAgIBYzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCzxfyi52gw/5tt6/9aNAXdY3wZYH1GifzGoN4cg8Mt" +
+			"++5xmTdrc2A9/5biaTUVC0x/Ml6mm940NA9mM/EoEu4SdnP2crNCIFHWNlYz3cJtYJ68rE" +
+			"rEU+S0gnYaYRiwNGhVpAjV+FPDr0Ghgp5rYQ61evAhmRuNAFwYocUw80G6JQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIZ9yMlboxCIEwEwYDVR0jBAwwCoAIJPt6qKdFeYEwDQYJKoZI" +
+			"hvcNAQEFBQADgYEATNnRMQmvTxRcSMUL4pa5bejuX2Ixy/OfZIAlJWt9AfLW2tHmdAaGpD" +
+			"GhTHKfyQQ+HrIMQ+lXau8Yu6nzWXAY8pKpKD1Hbd355VE4dYZ7aPvcAulZHeV0F2EFn09x" +
+			"qQ1frHDRoCOc11B5qV5hnwgDE/ByZh1+OWUcR4tBQKyEF4g=";
+		public const string Intermediate_Certificate_4_PP_06_01_crt =
+			"MIIClTCCAf6gAwIBAgIBZDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDB66hLZx1WGcCqmOxHK/rotXOpccJQOB2L3kpWP1M2" +
+			"ZiWufUguLw45XShdqu31OgmGw0/w9ugwy96aRL+Tiluj4xjIAxJCav5cXF8Dt2Ex7hjIHm" +
+			"XV0rHbJUiduHEh3fQphgtzlR4QxG6i/i4SbcsoJzsws8x3qOqRPaWDtyWs0QIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIyZsLNvyyIZEwEwYDVR0jBAwwCoAIZ9yMlboxCIEwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAc7G4BAUsQeqNp/Kv8TKJckfxWygz54PrkBICNw/eGuGamVJMRkYCP3" +
+			"yJ8NW4jY/rfxzKKyjVB09XuNBLDwYdR5Z5UHSg6Ijes3j8tehZ+9DwEQrR+WQf/adHIsxn" +
+			"/347MHrSQF7CJzE9tAu6AOu53lKxLeH6C/5YI611or2Ql1I=";
+		public const string Intermediate_CRL_1_PP_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhkYvGEbXvD8wDQYJKoZIhvcNAQEFBQADgYEAC7ev" +
+			"Pqe0veUX+zF51d/NiG6VwgEwOP1HlzD/saDn/FYXStTQDwoIyFjmZ9z0yLGIaVI1O9BWVD" +
+			"CTU3bCU1dBg61Blo3rI3TlNqmGrYRUSJ857QM9c/G+/+V0XJ/HgId39Pufd9Tob150XNMs" +
+			"9h0PvqjhYjG1bARMRa8JB4KTBU4=";
+		public const string Intermediate_CRL_2_PP_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJPt6qKdFeYEwDQYJKoZIhvcNAQEFBQADgYEAiUbi" +
+			"qQ3X/hTgjhpQGDZi/7EnZcqSgiAFMreV30/mav2NtXDITE9DqZzCS9x1vHBp4BBsQwYVvp" +
+			"XvLVSgns4pFwR+0Whc+tPo2j9ScePq3sICsqleWTN1DvuoP9rBe8w7pDN4guA59Kbeku75" +
+			"5CMA5YjiTUomK4UaqI3htwkBlWo=";
+		public const string Intermediate_CRL_3_PP_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZ9yMlboxCIEwDQYJKoZIhvcNAQEFBQADgYEANowv" +
+			"f/scWT6FFT393XEpWcTnA18hBT5Nkddw6mHjKBq7ndtBQkydMO8Wym1IeQ2qYbAqu3ifNZ" +
+			"SKF3PfgJjYPBKImzJdHTKfcclMC5H8Y9JDN0voeyONr9NiXcoj+p24YNYjb+PFI6avRYo7" +
+			"Xyrqvwnvng/IY9zLtc7SYYUIODk=";
+		public const string Intermediate_CRL_4_PP_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyZsLNvyyIZEwDQYJKoZIhvcNAQEFBQADgYEAsnA9" +
+			"ERwsi2mK540oPL45mLdOjGnet7+HhNk14q0hvALTYGB1vEjijc+Yvf6mHJGRbiG207BpJ1" +
+			"DWeWBY8TLe4YJXlSrWwx1jD46rCt7gdqXAdLpMo+i35yfQ19ZqeWcRLkspmczoUJLJaJza" +
+			"eLRrnjv62GLJ09KVKpZBGhV3SUM=";
+		public const string End_Certificate_PP_06_01_crt =
+			"MIICbjCCAdegAwIBAgIBZTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wNi4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKrLB7XA0PKY0qtSC5lMBvvIvbyjBM8XmANrN9Wx" +
+			"66QxEuloRAz0D5uAu7TnJBv6qNuIPGFl74yusKCSkjEkBMdVpBCfDvpG1/Tz3sALSlxmnz" +
+			"xbK2ytOncbYuYrzvXttx6wkhLrBLlnfuwpZwGZOr/Pt6WwQJWjXxgTNJ6dcgXbAgMBAAGj" +
+			"OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIv0gg7LxDM+swEwYDVR0jBAwwCoAIyZ" +
+			"sLNvyyIZEwDQYJKoZIhvcNAQEFBQADgYEAgzlxBGGOBvHw20eOzSswMqrHopNMcvwuEO+Z" +
+			"Mr0h8U2/HIiRqKWQaxMyM8A0oULGJny3B/0WtkfVQ2EIibZGiKIjC1RPAB3QmL0vgSyUmF" +
+			"s/LZbzugpJW6jvfov7N4O+u0J5rYniRxa4bgrXa89TY9kwDMbr6/z4oiI8bq3gEsw=";
+		public readonly string[] TEST_43_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_06_01_crt,
+			Intermediate_Certificate_2_PP_06_01_crt,
+			Intermediate_Certificate_3_PP_06_01_crt,
+			Intermediate_Certificate_4_PP_06_01_crt,
+			Intermediate_CRL_1_PP_06_01_crl,
+			Intermediate_CRL_2_PP_06_01_crl,
+			Intermediate_CRL_3_PP_06_01_crl,
+			Intermediate_CRL_4_PP_06_01_crl,
+			End_Certificate_PP_06_01_crt
+		};
+
+		/*
+		 *  test44
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_06_02_crt =
+			"MIICozCCAgygAwIBAgIBZjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDjg5+XWZwW1gLAOldsRshbCXmUCmt1Vs+oZsvyH+6d" +
+			"2PwKs8ydrz+oD0/D8V7cRXucj7q7cJSLhEY1wJoTTgrWeRg1hQioAXzPW3ZkaZuzhpi+cC" +
+			"qeZzN5nPvqK18GWvpffNbUUVfOuaHzzHmhmhgQyZaNG7JHwpWM10UMzMawOwIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEFMBEGA1UdDgQKBAh5am+tkndt5zATBgNVHSMEDDAKgAir" +
+			"muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQAF0h1iaxxZUp43AjP5gSvbW6JfFRW/ugH9SU" +
+			"n3e1B29LMH3F/ML0joVhPx5CIVpX4nfaYzdeje9+E2/bHMBGSCFeHz9S/KoBLLiI0GNhzh" +
+			"I6MytvPMPRx7hkuROouQ69TnslJiGCcoo+MD0fA2YwO1bCtyLdeVHYhJZWQ2Sg8PHQ==";
+		public const string Intermediate_Certificate_2_PP_06_02_crt =
+			"MIIClTCCAf6gAwIBAgIBZzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDF4KSKxo8HvQ59E77LcuLpZ7ujNDjb30KB+EbIuRmy" +
+			"khXAkhq2Rp2Iqd3OhC0AXmhSF+enJq3h0dqyxNWP08SIuK5ia3OIeatl1UgEyukuAnrLuI" +
+			"A7PFUQAGZmDG4OuHv28zza4n/SwfCaKfi8qatIwpwF/29ycB8wYBrHThQD0wIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIKFZV4vjfOOQwEwYDVR0jBAwwCoAIeWpvrZJ3becwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAuj8P5ga8Xv9eFjk4AdRMx/Fj/doRAOLZfs+OnrduRXPLe7CFKDxhFx" +
+			"xYOma8In08cgXVVnRR+2nZ54h5qjCYpskGNx+yZRY8+HW3XXE3KpS7QgTnc/1XshUy9VGm" +
+			"2qX0k661f2d3KnSKiKVKtM/y/j/nNyxPugDz1Yy50NtzQOE=";
+		public const string Intermediate_Certificate_3_PP_06_02_crt =
+			"MIIClTCCAf6gAwIBAgIBaDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCitrzXkbO4hAQpBRQE880MFBPq84umX9pyKbV3iMqK" +
+			"Z7HBYwZOvEwGQxG+TX1PIj0Jz27oyvoqpLeMkbn9L3K0BuS0AZKlWIOGPPHWpYTDoQCCs9" +
+			"Mba1evVT/1CMxESsv2kgf49YHMs/6TtxQX0qj5TQzXrkM6CMBc5zyPBDWORQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIxLES0WIVZQYwEwYDVR0jBAwwCoAIKFZV4vjfOOQwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAdQeDAOFys//2xUFwBilhqr32/jh4gT/ijxRjG0msKTYXmWcCQv9Tms" +
+			"smtIMtiwwnByhjTdQAtOmEyDm/CFW0/NBnxlRvqZKt+PRtscpExVy7xnnm2MBITTa+9xkC" +
+			"A361jSDPnRPEOZoKdMRRzNnW4f59m0huibeFNRYJ7y8BnHs=";
+		public const string Intermediate_Certificate_4_PP_06_02_crt =
+			"MIIClTCCAf6gAwIBAgIBaTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCg0yQG7oewLD2eFfPuj2DPBgT47iEri2IVeS/r5hUD" +
+			"nZhxzT2/+UsQfiS+ufdC2Xq+QAcXFcAifPbvRs9xo2q0uLz26mwSq1TH8ilHLKatKwJ/Yf" +
+			"hcRAfEWDwhLJGRhZ7YrKu8xczZgyxwaeu5m38lEaLIRyaVfVSrw8WhN4z4ewIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQI/dKmuI1u6I0wEwYDVR0jBAwwCoAIxLES0WIVZQYwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAOEcMpdSAVKUzQ1A7LJnWOh5Tul6yXw6qMsdZNGOZ3vYBXH3vHnSHvp" +
+			"MqJQ1JIX/4XSiKF8En5dVI/ooNabgyORpPnLGDvrshvO/09iaDlQXxWRsoGAFhcIe7Ibp+" +
+			"3g6hnBO5U+0pbInioKVYf/1VyZSUK1QQMutshMIye/8gyZw=";
+		public const string Intermediate_CRL_1_PP_06_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIeWpvrZJ3becwDQYJKoZIhvcNAQEFBQADgYEAEJ28" +
+			"g5iyw3ZOqs5ly7O2X0YWtgKK3BnPztxygCUWO1xVy/QbMM5ybAU/UPbJC2pUnkOZMX+h30" +
+			"RYp/kV9w2o15V1hxj2M0tR8fQ0WXudwi20pZO56uHb+WSaETOmPVoNH5efeXsTvtbHQR5w" +
+			"95L2vNeEzJEy1l7S/sasUUoQvqY=";
+		public const string Intermediate_CRL_2_PP_06_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIKFZV4vjfOOQwDQYJKoZIhvcNAQEFBQADgYEApLIK" +
+			"X/YJYhSfn7yLTAlKjnhpH1QDlFeaE6/+uj6j7ZgpK6HBjHOvfwbrjurl+L3ZTLrY1FCL4/" +
+			"SUgXrJxbAyMANlg4Z8u6o73F9cur2gi3sgv5d6FjJ8VwuKYWY2dwZNeXwlWE/W0h01Vd9H" +
+			"QVuctFxzQaJQdQBadw/XqzvLlyw=";
+		public const string Intermediate_CRL_3_PP_06_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIxLES0WIVZQYwDQYJKoZIhvcNAQEFBQADgYEAE5J9" +
+			"wJKAb3veF4GhHeoIgy6JvMsrjv7d7dhT+ZIKq+wPNk1909X/Zo1GXxJSjMaMgkLlXa0QN6" +
+			"LtSJxbyMRCKSJfqTKOezFXirZ7MEQ04FT0z6Hp0m+E2Q7dGs52ZOV3YZBhQUlH+aQ8WNu2" +
+			"6clf4VqBiUYgGhkE95PhN5AAnOU=";
+		public const string Intermediate_CRL_4_PP_06_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI/dKmuI1u6I0wDQYJKoZIhvcNAQEFBQADgYEAKgk1" +
+			"HJ7OW203z9H7jNGxoLCN9bGDKOFcWlWuruzXWOAn+AomjSZpqZkZU1qyKrFaKM320sfn8C" +
+			"ZJPnVWaVMLBLNddDRWUjJrUHtNdnnZEuYPYlRVb0MmwaxHHR0ZBUIaniqoLuvtQIB9N++T" +
+			"bu4cjx33mN6MX0oWr4Bbq7ovPnE=";
+		public const string End_Certificate_PP_06_02_crt =
+			"MIICbjCCAdegAwIBAgIBajANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wNi4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANAr4hFku3Y6jI+vD6JTRFc7ZLL9tIxT7Mq+QcDd" +
+			"rRHgSEXhPL3MM//3ZFXca3w4rXOUVQyANQncywNM3uwl7T9jC0MD2kJ9PsNGQL2bQcSajX" +
+			"jrxT403PVFsa6ZrLMU0hwomSO4nJBLCJj3i1rlX9esYbRNCqzep2OMWgAWRUsrAgMBAAGj" +
+			"OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIMBvQP4Q8w2UwEwYDVR0jBAwwCoAI/d" +
+			"KmuI1u6I0wDQYJKoZIhvcNAQEFBQADgYEAnmNf+3jJp4mo4YDznASTMnrBBdXuskhnRXSQ" +
+			"Gj5dNq6PxEXM+CmBhaNlnFYcr7UCtcD8XwampfyO52tvAZW5kWQKsxyowVtsxtwkAtj6/f" +
+			"trIeulIM0B1xjyXJshmVST5u6gZ3OegsAyuqyAbo9B1IvkNFOldt624aEG43jq7ho=";
+		public readonly string[] TEST_44_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_06_02_crt,
+			Intermediate_Certificate_2_PP_06_02_crt,
+			Intermediate_Certificate_3_PP_06_02_crt,
+			Intermediate_Certificate_4_PP_06_02_crt,
+			Intermediate_CRL_1_PP_06_02_crl,
+			Intermediate_CRL_2_PP_06_02_crl,
+			Intermediate_CRL_3_PP_06_02_crl,
+			Intermediate_CRL_4_PP_06_02_crl,
+			End_Certificate_PP_06_02_crt
+		};
+
+		/*
+		 *  test45
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_06_03_crt =
+			"MIICozCCAgygAwIBAgIBazANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCrUMqMxZ4sSrH6sKv2y6nYKagLvUHaforCnf4z/5O1" +
+			"PeldaW4ANtNPA8SkVBES/zoKgvrLJUmqRi4b+BGhCVqLU77PvWyiPOS40tpJfw7m9pPK53" +
+			"aeaLC9M6rarjdOvF8MkdtytCMU/Ef1NsuJULwEP+XB90k4lHr9EzbgKhXvoQIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEEMBEGA1UdDgQKBAhF0iXZmlIKsTATBgNVHSMEDDAKgAir" +
+			"muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQCmab7noekyx5TzxAqWoQiC9S/aZJtvLkuH1p" +
+			"KiZnclMpRvIL1CVOukkzLTZXY0EcCHnXuVGjw+9vmiQWGGw8t6TGCXo/CtCo934HGBxOfQ" +
+			"MVysEjst7L7TDQsqxk4j9O8cU/TFWsghW9Ihu7SVIn8RJmknKMB2xkIhcDe8S8dmxw==";
+		public const string Intermediate_Certificate_2_PP_06_03_crt =
+			"MIIClTCCAf6gAwIBAgIBbDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCmT7wL9WwWBr1oY9bHIq4IrJOkbOARK3zOeyZSbBBB" +
+			"zxcky5kjC9pamMpyZjga+q0CGd2rq9eUjQ2FXZsBSgf/X9B0/g9trNMebYgGnYmHHX2JK+" +
+			"doyAX+h3afDbZzZ696S0Hw7yRx00+teQe/Gx4h4qKPwbJIW5Bep9SBysikJQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQInXHgY/+onu4wEwYDVR0jBAwwCoAIRdIl2ZpSCrEwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAhlboR5gzYWluWIaFM5R1Ko0/rprrv5BHONRiXjLfAPkzZmd7FLDE2j" +
+			"BlU7s7IenICeST4c7HG5zqBigK1814GG75nq5htCGUnM6pn8/gvc58+ckKeWgbJxC5I/0u" +
+			"olCCs8ORbWIEGWmghGg1USxeI1RQwXGgE8XwtabVibJOVBk=";
+		public const string Intermediate_Certificate_3_PP_06_03_crt =
+			"MIIClTCCAf6gAwIBAgIBbTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDEouRlqTFQiJQSwc+yhjpvA0dUIbRrNwLF+EPfUWq0" +
+			"FV1UV0a5lb5BGPW4RGUEbFwsgGCHsfLiY7WmUpC1e6332PZPnrnoJbf28paeiZ8KqcAKZE" +
+			"pGPWKCmFBwBW23q1w/v/CxcXJoBx5OC1yxG3fGH7CZSzc+4Z/+PxLk9yoASwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIc24GzUM6/LswEwYDVR0jBAwwCoAInXHgY/+onu4wDQYJKoZI" +
+			"hvcNAQEFBQADgYEANLxcLvJqjyu94HN+X6tTxGcN1s43kQh8yRGotW2ptuA2jmGlAhI8QQ" +
+			"sXHO0o0bFLBC/Uv0L0YlEJhK1w0ct7Awwn4UYgqupxug2f84yamcvFa1es3osIMJoi0GPz" +
+			"1WDBM711efRtbzvK6t/4fJ01nG2BlMeEbctVqrehuAip4p4=";
+		public const string Intermediate_Certificate_4_PP_06_03_crt =
+			"MIIClTCCAf6gAwIBAgIBbjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDNuzSN3BiT84M3Dy6KeTQkMqWNuYGTENWPP8WvQ0Ot" +
+			"ggue/lemC+IqYBtIEYtk3A30eKKnF28WIbPlB3oSykrPVV5dMhYGF9ysOtp4wyETHtzdv0" +
+			"7HyqlMHOCPiFplbwjUSo0uEIRVgS3luBJi9onTpcn97/i0S7VsM2nooooaowIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIDjpr8w0dRq0wEwYDVR0jBAwwCoAIc24GzUM6/LswDQYJKoZI" +
+			"hvcNAQEFBQADgYEArE6qUMnjXiB5eKiAFc9Elw1dYsQArtnDQAfFGtShDulxYKq9+pxory" +
+			"4kTMUZZCJc7awEC11tdJp7xJGcpjCJl4I2wBcHiCcVcnwQijqM719PqoQKydXB9MSrXqmU" +
+			"2CyakSzBpb82VooVNx0IZ3h0nXQSE3V0qSXXCaImJcOIGMo=";
+		public const string Intermediate_CRL_1_PP_06_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIRdIl2ZpSCrEwDQYJKoZIhvcNAQEFBQADgYEAQrHK" +
+			"VV2MJPJLNdPoEuqFXRTEclSmYhUWC5lthK0JnKUbCUj2cMAku2UdN5sRgVG0475dXV2nvn" +
+			"huxy+IQVt5OJ+PNZ9MYZlC2CfYsBiW9DEYMA603XhVvX/bxx80MwxNby18oyo/V9ycSyJw" +
+			"XzUmzYRUtohHk39r3eUSAt5H7zM=";
+		public const string Intermediate_CRL_2_PP_06_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAInXHgY/+onu4wDQYJKoZIhvcNAQEFBQADgYEADOEh" +
+			"jV8V8y17mFstkVwigOAKURbi7sD24RkLd1QG0Bn21JiwpkGY8Z4vetQps+VX586xKzz6v6" +
+			"Sj+TJk3jfHCiEAk6a7PLxRcVCCi6y70mzEBCwn6fS5NDfxzxYYLgq+dlUiVwqXsHksEvUz" +
+			"2Z5dpuLhbUGxHiqazNE9iq9pEEE=";
+		public const string Intermediate_CRL_3_PP_06_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIc24GzUM6/LswDQYJKoZIhvcNAQEFBQADgYEAK/zi" +
+			"r7ASgtWA0xGQVrqhHsXH9bdaj+FceW6ivoXo3z6xCFLvzu2uenEu5g849+YI0KMomHsDAY" +
+			"tX8qO3XEaLGchbhIfywgRVDlSF8ytMKhJTS05R/vZSZAl+eoT3mC92Grihsd3wublyNZ7a" +
+			"d925Py/oFp3J+geUkKJQK+RVu4M=";
+		public const string Intermediate_CRL_4_PP_06_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wNi4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIDjpr8w0dRq0wDQYJKoZIhvcNAQEFBQADgYEAcBag" +
+			"81RFYMBAf8aRP5VXPcfu0OxgJvVE25ZHGLCkLD4TPKAXMjZMHWrf34+5FW7aigDO1YhGA+" +
+			"2zVtVj8k71DichiCCGXQvH50AqFgeNXNQwn9WcpQ8rRkfmyhlccfeM+MzHI1giRw/RjvCN" +
+			"0dfJL9g3c7peW+VCKn85REZ1ne4=";
+		public const string End_Certificate_PP_06_03_crt =
+			"MIICbjCCAdegAwIBAgIBbzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wNi4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKBSOacrUg5H5yuISkqmJuQcK2ao+Ib0FmIKCuek" +
+			"8mm2HEiux+K5/yIAYsQnz9eDKzKWaS73exPniKOXABHaL6dxsptbdBqWB6II2kIl0BFz9P" +
+			"82qjz6DMwpUhj5Pwfy5q0Bz8grTe31ZYP19y8AHgcWna+eiY4fNVXVkIEJOJ6tAgMBAAGj" +
+			"OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQIaZQ3Q55so58wEwYDVR0jBAwwCoAIDj" +
+			"pr8w0dRq0wDQYJKoZIhvcNAQEFBQADgYEAnNYKc2pSFZ9PtR4gQyVI3j+gQ97tcWu6Alxm" +
+			"4T48fSb2KtFGuozJyCv0aYjtuZ9ava9r4v04lyFPoAjWYbALHC9F+vz7JLNr4VstuMdy5O" +
+			"ax+PvJjKGACSXD7QjXJ48qvm+v8OnMbkzf8+rY3LoTJ2KhXo9Ey4+UmU/YuZ0PXuY=";
+		public readonly string[] TEST_45_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_06_03_crt,
+			Intermediate_Certificate_2_PP_06_03_crt,
+			Intermediate_Certificate_3_PP_06_03_crt,
+			Intermediate_Certificate_4_PP_06_03_crt,
+			Intermediate_CRL_1_PP_06_03_crl,
+			Intermediate_CRL_2_PP_06_03_crl,
+			Intermediate_CRL_3_PP_06_03_crl,
+			Intermediate_CRL_4_PP_06_03_crl,
+			End_Certificate_PP_06_03_crt
+		};
+
+		/*
+		 *  test46
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_06_04_crt =
+			"MIICozCCAgygAwIBAgIBcDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDFoR/YTJlGYenu2IRsTiT6jwIA7yOnFbM9JXcqYIP5" +
+			"jSgtn/wVztPHgVWP+582foXJ+oEcThQVZ+RBXYt6VU5o7eVCsGJjqMd0DbRzTO+poelVoY" +
+			"1UEJMrKG0xSEex0T6XLQ+jPU9o5tlXoLYsXvpvbIrCJ0o8kuk4MWTzenDKJwIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEAMBEGA1UdDgQKBAgVwXynYDSYEDATBgNVHSMEDDAKgAir" +
+			"muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQC6MnYM9cY3CNb7/KKZvoaSwF/Se5iZYnbdPn" +
+			"WCnKydnN1AhlDN3kEw0gjTmZo/MkvPqku2aPzg5EiZ0eyeJaR6a4aiICU9z/Hiet19mBF6" +
+			"BtAUdt0fJ7aL5WPAc4BKXUbONd6vkQNv8uLcBmsqZ4wXDj7ZVBMGKcuDq7uClb0xYw==";
+		public const string Intermediate_Certificate_2_PP_06_04_crt =
+			"MIIClTCCAf6gAwIBAgIBcTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDHqX/4IZpOCsHWgdJ6mICN94nXz/KqsXPNymadVdZA" +
+			"nVU0fHdMcxehAvsBKju5d791Psly1Xyyda8KQ0BKPgGed6jNKb89JzuEtPBov0VMzskqwR" +
+			"irjaDCwYKtibiDe+T/kEN9Sq5pbexHcaTbAIeQrAIoSUmGdQ/Up6PYplb0jwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQISKcQDqdBecUwEwYDVR0jBAwwCoAIFcF8p2A0mBAwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAkAQaOoZYAZOCk881Ro+SIclAj2lp+arAkWPP/gwN4/0lpH62eWqlmY" +
+			"okWRBjk6+iwCgRxQ56uUjJhE08p5juZ5V32ie3RW+S1ZBPtL/T/+Tqp9HNQQ3GjW1yc/yI" +
+			"sWQxrd7QKzTER37HBiOr5WjEjn+dzuWlJtClcQetqMLtMgM=";
+		public const string Intermediate_Certificate_3_PP_06_04_crt =
+			"MIIClTCCAf6gAwIBAgIBcjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC2tnVj8KHGCm8XBPvDYWZMp3yOKQxuORze6a764qIC" +
+			"hkdO7hQbgJ9YiuAF/y62W17FnbhKPX6ninaZG0N77bznKvivSC3+T1jIVhw+kpxRh9MRya" +
+			"L2p+zHJEyO/9JaKWzJZiVi4kebW+hwNgSZc7FSYsAbW7lr4ujDei/yn/AJEwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIaAEiWf4JpfQwEwYDVR0jBAwwCoAISKcQDqdBecUwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAHNsZDCWtOqt741IJNA9OwpymTA4ES1BRJquEvGj5+4RH2pxi67bYd1" +
+			"kWTPF1qFC2R1sugSNhbU0wOBMdKUJtKWNacPsK0HbD7CPqt4THOcMXFO36b/2gqHqy9rc/" +
+			"slWuIwbtT/tEC+Mk67GEATWNPifoPT7TjWHM3RhsDnagZXw=";
+		public const string Intermediate_Certificate_4_PP_06_04_crt =
+			"MIIClTCCAf6gAwIBAgIBczANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjA0MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDgdk/smDJ5yZYJDH4SG7pIDCzGNZeLO9RI3ybOx4/B" +
+			"M3YQu3DDFSOv8kq6PgL8ThC8Dk6t1jSbT8QVzaGgx0KMV3p6pIMdaVNkOjVjUb+L0nXVfr" +
+			"XYpFLON6tZLgh8oIbiz4KznKmsxo6VdYwyUeHmkpGcL5y+8qLspCNdRJnDGwIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIgSY376EamQowEwYDVR0jBAwwCoAIaAEiWf4JpfQwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAEztvmGSVnDGGeNlIoR+wfRM8ndJogvUxLBZm4N96mDZ9Y+Nr99Dqvw" +
+			"+mMI3BU0miA5kDO9aFrKIgow3cpruoedhnBUsxTfhrNaFEwp+ORUb3tWn7sSxLfnTim4Vq" +
+			"y6j/EfUK2CS4ZAy7J5BADWSqDezPnrb5UaY1JFKMuLyGRac=";
+		public const string Intermediate_CRL_1_PP_06_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIFcF8p2A0mBAwDQYJKoZIhvcNAQEFBQADgYEAPlIW" +
+			"SxwW2LE8qxeD+M+HypNwai7j9XxUA2MhBbGVnsrhH+DKX5VeyP/nyZn2hBoGWhs05IpG2P" +
+			"S0odnyhbgGSXSj+IOfkZkVT0BmuEJmqv75R15LBzeyONks+eSEhoOIGAaIN4WgJ5mzjSrI" +
+			"ddDu3c4s6QO/OFVrNF1F6e4laSU=";
+		public const string Intermediate_CRL_2_PP_06_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAISKcQDqdBecUwDQYJKoZIhvcNAQEFBQADgYEAE5wt" +
+			"y3+jVnr8de/Yi0LV70v3JDHimwG2pQcuDRhR1NLPr4oC+2uxMqwxVzdHITDb3yI2ZT9pVh" +
+			"PV3UvX85avMdA0/JyaMWSKNpbSah1eNfMwMBY2vzh1Q7f5n+7HYYM+I2kz7HARPvwsLP9d" +
+			"j4mY7Kq7uiOFdnQzJ6LWjm8qEMs=";
+		public const string Intermediate_CRL_3_PP_06_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIaAEiWf4JpfQwDQYJKoZIhvcNAQEFBQADgYEAOm2f" +
+			"m3IdcDnIS915tEZzDmIbTFPBkIn0wjUreZKb9uNxE2a8Jixq+UP2uiyYWiWmXnRdVB1Gsb" +
+			"ofc5f8ctNgSPVTSYB0U5apIauXjV0y7WMUrLNrDFa5m9lxLRhF9kvXVL8zPhVfMpujnXre" +
+			"A8WS4UjDMuveyQL6yASGoZvB+Ps=";
+		public const string Intermediate_CRL_4_PP_06_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wNi4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIgSY376EamQowDQYJKoZIhvcNAQEFBQADgYEAznK9" +
+			"ekskl4uWU+2Xqp3Pj14wvXuzfPAqFlHR0jl5By7T82JRiRa6LGX6T953vcwwJBsYG1hMqH" +
+			"pgbnUGB8APQ6YNXN+7ZkudaG6fMVX6bCr8zT+nVSj7PHIK2VFsC1Jpm5SoQMHH6DFit/oH" +
+			"tm4tdV8+nupMBQn1ZtxQHgUUF14=";
+		public const string End_Certificate_PP_06_04_crt =
+			"MIIChjCCAe+gAwIBAgIBdDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wNi4wNDAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDQwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOCVJmtrW8Z2WGGRNjEgyp2NJn1xaIVDwlxL4C0n" +
+			"UAPpo1WM/rarQTYejT2Yo8H39TdRfiAlggF0Qsce0W//atey8WewGsFlUem6a4OFwg1X2h" +
+			"CN/COL0eC4a6lwkdOKmqgxSyWNWeKxXRTM8+EYQIem78uY7A8XuzVUmOpzYWoLAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QION6UOZ2Eky4wEwYDVR0jBAwwCoAIgSY376EamQowDQYJKoZIhvcNAQEFBQADgYEAXota" +
+			"1N1UrMxj2a/vdII92Wi8uEetcHo9vmiJVYxwPFkp+qo1q93Ww8Qnfp7xzaZwLgVoUOAF8U" +
+			"TRUVnzqoSwmRrfyEMfrgej3eiBjcU+zS9mNlx9mUUSLmlY+xMeejyVDCntRn6YJWWLesVq" +
+			"eFOjyNux97/XnGT3T1w0J+wShu4=";
+		public readonly string[] TEST_46_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_06_04_crt,
+			Intermediate_Certificate_2_PP_06_04_crt,
+			Intermediate_Certificate_3_PP_06_04_crt,
+			Intermediate_Certificate_4_PP_06_04_crt,
+			Intermediate_CRL_1_PP_06_04_crl,
+			Intermediate_CRL_2_PP_06_04_crl,
+			Intermediate_CRL_3_PP_06_04_crl,
+			Intermediate_CRL_4_PP_06_04_crl,
+			End_Certificate_PP_06_04_crt
+		};
+
+		/*
+		 *  test47
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PP_06_05_crt =
+			"MIICozCCAgygAwIBAgIBdTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA2LjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDMIUtQ/CgudxHAwAAn8jUsdAY8u7WDslOC4nNbWn5C" +
+			"tILgZ2hGIZhEnhzP+VCV8ke8zLo1DX0hCRYAgzk5XTGAimExHFv/yDdhpJWEnqMRljkCHx" +
+			"Hg3XE1439qutBdmWvGUlRF0hQrd9Q/Ubr+PjEzP3a0EUmXo7LYuQKMcFsC4wIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEHMBEGA1UdDgQKBAgha8GqGbO1nDATBgNVHSMEDDAKgAir" +
+			"muv5wudUjzANBgkqhkiG9w0BAQUFAAOBgQAEG5C3P1A/MYpNJ0qvi26v04GGUWDQWRW1q9" +
+			"1392XpAxDdv7kODf1FUMpfBpcUblagxrX7Npthv6/6W8poBTjvJuq5BfnnOMQrCwnsNfRy" +
+			"Y7b1mAZIvcOBhWe+bFVqRLUqZ+JseWkw0YgZIGtX41Znwl0VcFQKJ4lNkuaBgXXdGw==";
+		public const string Intermediate_Certificate_2_PP_06_05_crt =
+			"MIICozCCAgygAwIBAgIBdjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EyLVBQLjA2LjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQC36j0YkXZZSw3qQaxD0g2BfrKYperkGjVAfLwOtOxB" +
+			"0A3Ufx2ECl/MqNOvi/QWlTkKwnrqw0aEnD25iS1DFM4jMZBmdfJg80oa+y6TJoZcIb+3bv" +
+			"SK5o3ArCFWkhTHHggIIY3H9dQOgAeYQF57Vb0iu59GPfnYJO8y8ZpxGIYcjQIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAECMBEGA1UdDgQKBAhUpoGZzfV7EjATBgNVHSMEDDAKgAgh" +
+			"a8GqGbO1nDANBgkqhkiG9w0BAQUFAAOBgQAjrFHzC1FLvssJTfV5YsGfw7Luj4EqLDQd6b" +
+			"MgtBSwPnXqMTUAZpDETyeYvcgM+L2tasB26MSy6IttSKsaJpHPCP+BIs0jji5xosuCX6Cs" +
+			"wI2gE/LjF85rjZnldrlDShw01DlcmWlWwudit/ieO71Xc8i0F4EhSaTUJX12po5Xkg==";
+		public const string Intermediate_Certificate_3_PP_06_05_crt =
+			"MIICozCCAgygAwIBAgIBdzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMi1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0EzLVBQLjA2LjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDFWhChPQNFYQpLBmVmXSGF2py1wcfhZgZurv0E5AgE" +
+			"BZwBo2bxSeC36lBQyR3OABGI4nQoEegSQWwuS2Pk3+emG2MZ8R5QINAkMlAKTp5Gj7KTlm" +
+			"3VVJRx7/VduoFx8sZPjkpvF1bSL+KOH4UZny1xqqTj4bJ+oGu58INeSNVa+wIDAQABo3Ew" +
+			"bzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATAMBgNVHSQEBTADgAEEMBEGA1UdDgQKBAjN4PvsHY9+YzATBgNVHSMEDDAKgAhU" +
+			"poGZzfV7EjANBgkqhkiG9w0BAQUFAAOBgQA8KmWbAQOnM59zry9TNtLbA2P5y8R/sO771S" +
+			"yQYcu6undt9t7UEiOepDp/z3CGsITm9RdtXAobZ5ZqhW+3Ll+UnML1itiCytOPbfC7iiUO" +
+			"S5jviQnpgJncZD2Lp65yNAB7lMmMleFO15Bsk8VNmzMDMsFtzo508Bs6T33ZW69/vg==";
+		public const string Intermediate_Certificate_4_PP_06_05_crt =
+			"MIIClTCCAf6gAwIBAgIBeDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMy1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0E0LVBQLjA2LjA1MIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDxx57R4j64xdbjpTl7reLby/T2ym4rESC90aBkC2/E" +
+			"/YUSjsuGG9GiHEVgoGzoQGQNQV0v9ZMIvuoI6q7Fd6VZhIVGE0MGzTFNA9QEEDGPc10ZxC" +
+			"Gyh9mZYp77PMuhQ12Iv3aDW9KNTr09+HyhK7d3Se7toXLwjE5pKt+A4ZvBFQIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIwmq0fugIX0kwEwYDVR0jBAwwCoAIzeD77B2PfmMwDQYJKoZI" +
+			"hvcNAQEFBQADgYEAbAbRorTyh6zfAmdg0lfeZyCyW9k4NWfhUs46iSOl6lkZH8c1eoAF5/" +
+			"q0pOF+CtI3F9VMhfUXChEbVj7QENctU7kDiFe8300OWD5h1VUi+WTK4CG7B36/BjkrVOuG" +
+			"Os76P9l1WaC+/WRZdcqgFMfPjpn3R179dImBDwZiCMMbVqc=";
+		public const string Intermediate_CRL_1_PP_06_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIIWvBqhmztZwwDQYJKoZIhvcNAQEFBQADgYEADX3u" +
+			"wxpN+p8N2HqmhFw8w9LCeoR3Xa/uaqgqh4i/VkDuAC4Bi7VbIO6rcxDO2uAdZgNhb/hnRq" +
+			"cvKLcy0vrovCa2EPHcFo7dJl7si2q09EeuHT4+lZt/Ek/VOkwHhvh2o6yEvKOGXCnF9hZr" +
+			"8YbOIknboEz+tRfxoJArRBwpJkE=";
+		public const string Intermediate_CRL_2_PP_06_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIVKaBmc31exIwDQYJKoZIhvcNAQEFBQADgYEAQz7u" +
+			"dfU4yAHFLH5BgeZkYh0l2lZ95af+E/67MSCjQSF7RWWWTffbDMc4HmiRlZLvQdltyGCKmi" +
+			"kuzcPP8vyYOBQmoIKQ6c2LItBjXVavLdpe91yCOhCWXVVlnMFq5ztrvBEpfO0GVUOnPWfG" +
+			"1Ugit3SEd4DbhYFTBYHbbOKRWsU=";
+		public const string Intermediate_CRL_3_PP_06_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIzeD77B2PfmMwDQYJKoZIhvcNAQEFBQADgYEAkiW6" +
+			"h9a8v+IITd+p0jxukj2FYfmED59ZXAlYhQdQAGlPE71rOXn6ZPURYoGf7qlmBwQffpksOb" +
+			"Byb+PX+CBTUNXzhgTzD7ifM9xOhCEKVKai9acQfvokU56OHwfq5AnkRykLZ7IdvdYCP57k" +
+			"ynrNNV35dsMZXg23/PpreumlOkE=";
+		public const string Intermediate_CRL_4_PP_06_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QUC4wNi4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIwmq0fugIX0kwDQYJKoZIhvcNAQEFBQADgYEAnTbS" +
+			"MBWyoPaslaLpAMmJ+D6kmmKAdRYurA0okU/QP+0W+YNPV4DducAQUDy8Cg3RkpRK2ze0ad" +
+			"l6TUW8g83hj9TXSBp+XZuVvzerMCjOeBqhskZN4Ly8101ZZmMmdYdSc3PEhqkme6iZzjwB" +
+			"ZooAN2dIYjuBj1c1/t5qH80CMAI=";
+		public const string End_Certificate_PP_06_05_crt =
+			"MIICbjCCAdegAwIBAgIBeTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBNC1QUC4wNi4wNTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDYuMDUwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALyVMklPv3uwTPzLG70sXIwKSEt65yiU71ibHyhH" +
+			"wJ/6dXy3HK2UETkRBK7UVSOYq005EbO9s/3oR3zt7QTFifvRTsIjl1L4TCLC2a8ApBr3BH" +
+			"xmBWcJDf427Pk1fm5qDdEmZnpyIlpKaKIiBcdtwZfjr0lROL8RNcvgtJPdu/ndAgMBAAGj" +
+			"OjA4MA4GA1UdDwEB/wQEAwIF4DARBgNVHQ4ECgQISjAUfyAwSA0wEwYDVR0jBAwwCoAIwm" +
+			"q0fugIX0kwDQYJKoZIhvcNAQEFBQADgYEAC6Af3cJUh/IQgWdbC2Vmk96sYjDlAsbA2keY" +
+			"J0bgBcNaIVoJ/W0B3rSawqSU+Vv64p7kcuAl6cbvIXPB++19V23jj6HUs1JxtPJZ9IWkS/" +
+			"FRakv6lD7+j1OdzJvDR8AMZWmPFHJdQnJwQ+I1YOU/O/ShawOnGCmihpIULUINFhk=";
+		public readonly string[] TEST_47_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PP_06_05_crt,
+			Intermediate_Certificate_2_PP_06_05_crt,
+			Intermediate_Certificate_3_PP_06_05_crt,
+			Intermediate_Certificate_4_PP_06_05_crt,
+			Intermediate_CRL_1_PP_06_05_crl,
+			Intermediate_CRL_2_PP_06_05_crl,
+			Intermediate_CRL_3_PP_06_05_crl,
+			Intermediate_CRL_4_PP_06_05_crl,
+			End_Certificate_PP_06_05_crt
+		};
+
+		/*
+		 *  test48
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_01_crt =
+			"MIIClTCCAf6gAwIBAgIBejANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAxMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCp2vHVX08nyKe+S8NPkNJOZ9Xng22TbYXhUHtXw9yv" +
+			"ZmPkRhwDrZfBLXZcdZFixidkky3kCzv8Q3aPyPByM2ozH+AHJzEMbwifhyvUbANcS+Jts3" +
+			"lsZHarN7VyiXO+8J2OtYqX9qzmrAOHGleB2cJopEcmAMdrzgt1JIo98SUs4wIDAQABo2Mw" +
+			"YTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAWBgNVHSAEDzANMAsGCWCGSA" +
+			"FlAwEwATARBgNVHQ4ECgQIoRYqHNcbLacwEwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZI" +
+			"hvcNAQEFBQADgYEAXchRFC94Pl25d3Kl4wBcueQLyWPRuH9zS0ZPLAqKLcWVdcg3fYMuJ5" +
+			"SypMMpxLaVjN7xq0KjML1gLiPQPk18iA2TOAUMblvjUl1uFzDdD6SqQidEZh2h3wxFtbLP" +
+			"U7qBBki7i1+Xn072Bpn2paw/vlh4K+ut0tFQ2BAhqVnQGJ8=";
+		public const string Intermediate_CRL_PP_08_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIoRYqHNcbLacwDQYJKoZIhvcNAQEFBQADgYEARyX9" +
+			"2+LoXD2fIAACBMPDgds6m3Equ+Aawlr0kuppPO4ydCU4kiEgtVGK+kY5GzP6fUpAKjC8mh" +
+			"BrozojhAbkJekDoN0BIJ42Iab70VmdWXRQhPsUDhQwEt+9eSgy+HfiFfpcL1VJx8uY4XMh" +
+			"VB3hmapIe99P/T2QkZ+Pl8j0MgY=";
+		public const string End_Certificate_PP_08_01_crt =
+			"MIIChjCCAe+gAwIBAgIBezANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wOC4wMTAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDEwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYtrtpgxNl+9jF3TN1B9bSEGQci+cQOKpFsmrtF" +
+			"AyiGBxKONgGSgSFFuFIhyBKZF5ROaKX1P8lsQkrpnuybUi+Z9ADdyoaLUDD/z/kp5sebAZ" +
+			"ujmF8HVlqHYj5Ls2smS9EdSN1zgPTXIOTeZd/lv1iFppRZv6cBqlaoapQJsb1JAgMBAAGj" +
+			"UjBQMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSAEDzANMAsGCWCGSAFlAwEwATARBgNVHQ4ECg" +
+			"QIZjcOdw0ZTCYwEwYDVR0jBAwwCoAIoRYqHNcbLacwDQYJKoZIhvcNAQEFBQADgYEAarsn" +
+			"13/g0vOKxy0okOp2JXEsPdsP7aWnCfR8N4+7gFD6dVnkgCIyc5Kbs7MbhB9gtIxYhHOV9W" +
+			"MaW9QAcBH+eXciFDfQBfaMBkL34ssE/TsZ92r/bhBwKRcH54f96G0QWUnoNMt4U/1j2mKn" +
+			"faFirltqEPUu9mv4FiQ0pNT9yH0=";
+		public readonly string[] TEST_48_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_01_crt,
+			Intermediate_CRL_PP_08_01_crl,
+			End_Certificate_PP_08_01_crt
+		};
+
+		/*
+		 *  test49
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_02_crt =
+			"MIICojCCAgugAwIBAgIBfDANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAyMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQCmAgNA68ABUEppM9Oo3guiGvguvtrWQzsQIJfMBrE4" +
+			"/Scwc4SPK4PiJD+kVwtXinXpVclBMQge10uZ48lSJTihfZscJw3RSHt70H4CpPQm44QS7P" +
+			"7fQqpcZKZvMWmY6A8jju3Phbuq2WgJCIxxVw886GNIAXW8C4ZFmXCjwiGGHwIDAQABo3Aw" +
+			"bjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAjBgNVHSAEHDAaMAsGCWCGSA" +
+			"FlAwEwATALBglghkgBZQMBMAIwEQYDVR0OBAoECOhZ4RAlqGGcMBMGA1UdIwQMMAqACKua" +
+			"6/nC51SPMA0GCSqGSIb3DQEBBQUAA4GBAGEVSOcNaUu50f6AgGBtz1MDdRiHe08W/nzCNn" +
+			"0K1/UqrIXVJ7IYgbOLkL3cdHy4PdngCyEblzl5Cwp9chh2zL0PTUbV1uJIBW32ks1HuAVQ" +
+			"FTZqx0iuopY5AqRCJVDJt4HB5PKObwnmLPNWicI4Juap13j/Tcnw1EP7E7n6OejC";
+		public const string Intermediate_CRL_PP_08_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI6FnhECWoYZwwDQYJKoZIhvcNAQEFBQADgYEACLHw" +
+			"iDARFoF4GauIHnoZlfj6nlOHAFfNSXq06Vvl713bsoAiOSV+2goZjRG62uxhampE+gCdXx" +
+			"1nwhKQ5R5jOGGOxgLtBFNZwKmD0KiDOSvfIVJ0kYCcaB4mSm0a/7pcCPrrE5ofvkmTW6Wx" +
+			"k/YIuBZdDoqZC91v4tnu0fSch9Q=";
+		public const string End_Certificate_PP_08_02_crt =
+			"MIICkzCCAfygAwIBAgIBfTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wOC4wMjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDIwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJsz8ys71e8UB+VDTBAocVQvADiqh0LjdML3pET" +
+			"B6VvikiHgbB1PJufxDses+v0WD74ChZEa/octNcMFqMgBlhVBEfvbyGTjiN97LzdZ7SPyd" +
+			"DsDulqwBG9sACryUGHqwHYnUbjOqsThOXFB8Sg/CGGawpZAosm2AuH2gqNvNuJAgMBAAGj" +
+			"XzBdMA4GA1UdDwEB/wQEAwIF4DAjBgNVHSAEHDAaMAsGCWCGSAFlAwEwATALBglghkgBZQ" +
+			"MBMAIwEQYDVR0OBAoECOiMLE2l5u16MBMGA1UdIwQMMAqACOhZ4RAlqGGcMA0GCSqGSIb3" +
+			"DQEBBQUAA4GBAFf4BCbNtduwn5InkfdtFbQOqhPLAn/5eIhxhVhUu7TekWT7ktdaVQFzGF" +
+			"G2h1+gXgFP+YKjJy7kGzEVQjlWtuC0l74EwybNHnYAoDg4itKe+0OSNNXdyOmn+i0tE0nx" +
+			"sWN19VvhLGFC8p38gd0oDr1ziYdg0z2Mx4IlMDxl7QhT";
+		public readonly string[] TEST_49_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_02_crt,
+			Intermediate_CRL_PP_08_02_crl,
+			End_Certificate_PP_08_02_crt
+		};
+
+		/*
+		 *  test50
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_03_crt =
+			"MIICkDCCAfmgAwIBAgIBfjANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb0QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDFRydXN0IEFuY2hvcjAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMF4xCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvZDEQMA4GA1UECxMHVGVzdGluZzEVMBMGA1UEAxMMQ0ExLVBQLjA4LjAzMIGfMA0GCS" +
+			"qGSIb3DQEBAQUAA4GNADCBiQKBgQDKZDgBum5Ud5i8HWlCKInJ1x9goZ7TQJ+LdfA9iGU1" +
+			"47xJL5eFcERWy4dr5wM5GNRW/DHXlnA/qsRVE29EuRh6qAVgcPGAfmJxz7s5yhmErfmiQ3" +
+			"0rh6+pma/EhcjntXqwIqnk1qt6mEk7x9UKO3ksFCVsDEA67/dvownjcZB59wIDAQABo14w" +
+			"XDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjARBgNVHSAECjAIMAYGBFUdIA" +
+			"AwEQYDVR0OBAoECGtTrZIwYYHbMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqGSIb3DQEB" +
+			"BQUAA4GBAM3t13xJJraRiJDAwZFxhTNR570wMdSRiF3yWSRtOjEv8NTVFj/T1oJJ8h9Gqh" +
+			"hMpTTHU7uGCyVB9S1HCelmS+1zteKr0B+WVzBl9yuhvku3farz6zgIVK3v5hQ6xC4H4Lac" +
+			"NDhTTKBkRfDf9KskFoxJ/AGxPdZtIEC92DFSblQB";
+		public const string Intermediate_CRL_PP_08_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIa1OtkjBhgdswDQYJKoZIhvcNAQEFBQADgYEAcUHo" +
+			"D00X/pd3D5KGa5C6dY18RsnUovkjUkegGTpbhQfmYZIdBatj7Kv75FeUJ9UpqCUjxHgdiE" +
+			"EVy60NLVGP2VRuJ1m8vfDz8hu5PaiVjneQoRw2M9ieBnz3PjSETDdBGJLWHyCBZbp/W2+0" +
+			"iqcZK7Fm9O5EL4PUO6QIwuH76q0=";
+		public const string End_Certificate_PP_08_03_crt =
+			"MIICgTCCAeqgAwIBAgIBfzANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1" +
+			"UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3Rpbmcx" +
+			"FTATBgNVBAMTDENBMS1QUC4wOC4wMzAeFw05ODAxMDExMjAxMDBaFw00ODAxMDExMjAxMD" +
+			"BaMGAxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9VLlMuIEdvdmVybm1lbnQxDDAKBgNVBAsT" +
+			"A0RvRDEQMA4GA1UECxMHVGVzdGluZzEXMBUGA1UEAxMOVXNlcjEtUFAuMDguMDMwgZ8wDQ" +
+			"YJKoZIhvcNAQEBBQADgY0AMIGJAoGBALsXEPrCg91CObTl5OrHIB5GshIDXgqBmjzxfWPK" +
+			"ih4STWeBe2eIFO9pONXcM5lstEu2XLBPP6QBMUMWOrphJejrJ3eDQHs404bBnt95O/x17i" +
+			"665CZtg1jUqoO1kOBOComx2AJGZ46RdBExbfd0tTtdHWtRhMsnQchI+WtEyotdAgMBAAGj" +
+			"TTBLMA4GA1UdDwEB/wQEAwIF4DARBgNVHSAECjAIMAYGBFUdIAAwEQYDVR0OBAoECEWZkJ" +
+			"TYQ3z5MBMGA1UdIwQMMAqACGtTrZIwYYHbMA0GCSqGSIb3DQEBBQUAA4GBAHki/TrpHiKW" +
+			"gvERhguQ/uOqHHZNXsog+fgGVFFMOWwJ9bq4aHKd1fDZpyZF4vBxW7llbhuSt+ob2TNlkR" +
+			"wkqzfGL+3xOTKNRgzDwJcil8akC1N5uBftrQk+eL7rM1PezWRM7fIbpmv5ZieIVswtTPF5" +
+			"1Rl3G+JXUBy9E95espls";
+		public readonly string[] TEST_50_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_03_crt,
+			Intermediate_CRL_PP_08_03_crl,
+			End_Certificate_PP_08_03_crt
+		};
+
+		/*
+		 *  test51
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_04_crt =
+			"MIICljCCAf+gAwIBAgICAIAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsrM3A06j1zDz6VuZh+O2UrAPcKtwSA6KxTShUpgr" +
+			"t9UB5iIAEvxcDTwDlubEv/cJjDcFj9N57otzW4ppnuT2ztE4ROmkNb0xL6u00deS1yGjXB" +
+			"wy1G9g8bYDdAXOJlv0tjHOBqXlyKoMny82BOBL2vsCstiqxl14Q3/wBD1w29MCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAMwEQYDVR0OBAoECJiAkexK6/c7MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAL4xwcpXZQPTTPYIQ8CMoVla/5P1x6BPmPqSkvh1D/o4ds9Ll9kHBz" +
+			"//X1ZM8SzYcEO+1r75JUzoHsvDw9yYAk2oclLsCORAPqD8Owhv3jv0QQtYSmf0Sxt5FLx0" +
+			"MRP9keY/DURRf9KitO4glOawtRtYMq2BeeJk1xusY0KqEnQr";
+		public const string Intermediate_CRL_PP_08_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAImICR7Err9zswDQYJKoZIhvcNAQEFBQADgYEAcN3a" +
+			"jIEcXsQatb0fvVcFnO7d7lzNtgbqL3MtaqJ/PjkRJ/rO7JAXQRwdajUZF4ECHylZKE2HUG" +
+			"Dk+vidV98T8mNmb0TEuuLV+J1G0q8ezMXRJtDt/2m3y1VBireXlEMd1DdgpsDdCQ4va+XJ" +
+			"qv0TvVhfxWry+LrVb6Bf5ItexXg=";
+		public const string End_Certificate_PP_08_04_crt =
+			"MIIChzCCAfCgAwIBAgICAIEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUFAuMDguMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA0MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPJWa/cB7WW7tkGxFhcwxqE+BycXe3Ru2qGbun" +
+			"NPQZ/j44UT2C6rl1wZwugCY0sR6mXR/P/NR7czZvg4Tt6lwcNtc8PeafFMUeu0u0Kg9uWn" +
+			"fzQQKeIgRVcEzGTGMPGWXS0ed6X/1+Dj8A+T/tqXKUtM3Jpe0pCmm9CIrYCXLPRQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAQwEQYDVR0OBA" +
+			"oECKm9IOyOM1h+MBMGA1UdIwQMMAqACJiAkexK6/c7MA0GCSqGSIb3DQEBBQUAA4GBAEXy" +
+			"dlTkkZaYK6sUJCiPeCPxfj5cdo/G4RGBImMJbTeDyVTvXSH9G2yWUMqBGnYLrwdJJeXjF3" +
+			"89miJgnJ+1r/r3r2/NeAUuJDsOHRMFh0KXFmgubyw/kGsZBe3279hDnND8ZjfQBmKQD17f" +
+			"PycWTTAC5p6GM8tGERiDSnMc5rmm";
+		public readonly string[] TEST_51_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_04_crt,
+			Intermediate_CRL_PP_08_04_crl,
+			End_Certificate_PP_08_04_crt
+		};
+
+		/*
+		 *  test52
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_05_crt =
+			"MIICljCCAf+gAwIBAgICAIIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwH2d+D0pH8y4QJAPpE0s2oWucV1jlE4pBMGNNPJ5" +
+			"FIRmyRCt90IpzmK/EuqT6iSZYd9hIB9wa180ByN67PK1z4loLFMUL2RmbWeAFlGy5eEFOy" +
+			"4d479qfy6JCOzt0TKhYzhukLUqGLa4DDTzvnnUx0o86aLvGq0K5s6DRlNyc08CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAMwEQYDVR0OBAoECDSeuxr4EVgaMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAKoGi6qlODB8Lc86PtGXfBhW769jB8xzgmENE59sqNBEvYa/oK9Xxm" +
+			"1JX1OGEQMq/mqwZXg6hSczpexCIO4tUH8QKTU68yvqcZoZCDV8FLM8aEUPtUoPIpluhAtN" +
+			"scGfb3uXoV9fg7q1Pi5YlKMnNrDIq1tH1CAGKMDRrjW63Q8C";
+		public const string Intermediate_CRL_PP_08_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAINJ67GvgRWBowDQYJKoZIhvcNAQEFBQADgYEAv5Hs" +
+			"nYPZO1fGC/Z2lIbbUKjIv0+BrR9HbG+b76wXeJTVxfXMlZe0cpOR/KD29DyxI3G4IedHRy" +
+			"zL8iCDWYbA86arJzl5GZJ1MC2A586vNn/6wiiT6nP3iMj2z/nyvan8L30KNBm9IDXQExOu" +
+			"PNE/wOWYBxxCjg551fpXfJKqDIo=";
+		public const string End_Certificate_PP_08_05_crt =
+			"MIIChzCCAfCgAwIBAgICAIMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUFAuMDguMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA1MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4BZFTwOqI+71v8CdiYbe7x0qYveN524h6+iLh" +
+			"oEqvzuVKVqvQgVSaSLPcMhoCGDv3nqyP57Znl/3I09vLU6F4HKLtjO9E0PZu8EXOKLjeWP" +
+			"XmJQkdHfODj/TrrWSsrdorl7s7gdWEUFlbiWvUVUtkqLNbGLJZ5Q1xZvBRLS7loQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAMwEQYDVR0OBA" +
+			"oECBDaTXbN11BBMBMGA1UdIwQMMAqACDSeuxr4EVgaMA0GCSqGSIb3DQEBBQUAA4GBAGVa" +
+			"QNtd4LgoVZQ+Uy1lSr6sog4fsGaoQJCZcvrMJwGpMF0FJsGtOb0R2mfwHi1YXqPF5qZY2I" +
+			"7cVbwVtRQzbXunk1z12k0iIesMtYUncxb/SBstC7VNS8HNZm9ese+YM6Ac8mGT+IUZsPcP" +
+			"gI9fQ1L/2u+/3L4fweca1R45xm5M";
+		public readonly string[] TEST_52_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_05_crt,
+			Intermediate_CRL_PP_08_05_crl,
+			End_Certificate_PP_08_05_crt
+		};
+
+		/*
+		 *  test53
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PP_08_06_crt =
+			"MIICsDCCAhmgAwIBAgICAIQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QUC4wOC4wNjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAlSIH/+6DEL1P9tkgbsI2PcW0w9dmqMTLP3jKYPsr" +
+			"sSWI5bcv55sk6RItVr3hGgkaskZoHeamUBAiGPksVyrqmRwSCJzQDLnLdMnjjudvPjp1ZZ" +
+			"9UCufTtMPFvnEuVBx5e8A13AQ4OyHqaJgWRVoRJd6vwTa5jzfYCCMJZHHKpcUCAwEAAaN9" +
+			"MHswDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwMAYDVR0gBCkwJzALBglghk" +
+			"gBZQMBMAEwCwYJYIZIAWUDATACMAsGCWCGSAFlAwEwAzARBgNVHQ4ECgQI8837JGF7vMAw" +
+			"EwYDVR0jBAwwCoAIq5rr+cLnVI8wDQYJKoZIhvcNAQEFBQADgYEAKmgbxzWI6V2twYDp65" +
+			"Gu8zn883CnI08s2FEVupvrKduxYmg+ZDkTBE3ZJFxcOuxJf58MRfDWy8C4jJhLnT3JSSSg" +
+			"sY3n93jzc0s2h5y2wd1bUTDLqhqWCshisDG/88rpv938O8luiUEwltolzKTa+ScA6nXSQt" +
+			"LT4I6O3vbTx2g=";
+		public const string Intermediate_CRL_PP_08_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QUC4wOC4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8837JGF7vMAwDQYJKoZIhvcNAQEFBQADgYEAHua+" +
+			"lC3wP4G6796jjr6wuu7xEQqY1azsLVsGtL7YL8fm42rl7hgU40SuFIc7Kc+A7oEEkKgvmu" +
+			"SLMIv7q5O8J26fQOuduGWQAncPYB8w7sNWjCZbdjVbjp1XIApcAL3djCbLZ8/NYsCoOuwx" +
+			"hRQKX1hIn+rNDi1DMD4H99QdDGE=";
+		public const string End_Certificate_PP_08_06_crt =
+			"MIICoTCCAgqgAwIBAgICAIUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUFAuMDguMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBQLjA4LjA2MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDnaYU/lu+u+LmLQwyACSsRyxQEEvgriE7ApmHj" +
+			"sNBcd3lovFQMfw9MyOOMsInOgQZU8p/invnhx11/pwi77ViQQ780unhHt5H/tteaYwcsDR" +
+			"cUxR/8jK0DBnbVWvm8S/NGb8BxfbRmDHBTWGZ70hDSCJypWRfHQj0I/SAqAW/VuwIDAQAB" +
+			"o2wwajAOBgNVHQ8BAf8EBAMCBeAwMAYDVR0gBCkwJzALBglghkgBZQMBMAEwCwYJYIZIAW" +
+			"UDATACMAsGCWCGSAFlAwEwAzARBgNVHQ4ECgQIhh/KikcKA7EwEwYDVR0jBAwwCoAI8837" +
+			"JGF7vMAwDQYJKoZIhvcNAQEFBQADgYEAbHK3lkqbGy61lu9d22uO2H3hzwvjmlccZo8pro" +
+			"ord45d2nRIxw2ag4dS1YRFrefVdxZtKeR9+5o+tQtvmTcDOer4u6NZ/sVVElTb1d6axtL0" +
+			"i4cmqv6bGWYECEwtwmPGqAavp9pPZjNRbkBGy9qhVNTXfDQYpA8yzXWO/xUrwNU=";
+		public readonly string[] TEST_53_DATA = new string[]
+		{
+			Intermediate_Certificate_PP_08_06_crt,
+			Intermediate_CRL_PP_08_06_crl,
+			End_Certificate_PP_08_06_crt
+		};
+
+		/*
+		 *  test54
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_01_crt =
+			"MIICmTCCAgKgAwIBAgICAIYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxDV2d7qXbpCvOzBimskBLsgexpEYaHv0s7gOaqhC" +
+			"4A3K8sxdjyW6QdGZhKX8tCMqnlPp9CNbpY4tQQ5oTSk5pj6HwAsTfGcDwXJnjKWx1FJ7rD" +
+			"meZZ8c2K7a8voBl6FoPGn8CMhO0WmM9Eyb/vDUPdCZzScb+z/BxTcV1BPFdq0CAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECBpj0+Gcq32oMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAB/9veHrkLeu8jkwXggJtwqPTmkrIBcX+pz85BTSETYeLOzF46" +
+			"onk+qt+IHptlrm3D7ny2Y5M0dQQ6tPzhGZxCEg9RoDibZGtsx+qeAh1ZjeEpEcQyp/idWY" +
+			"asH+EIuEIOZA9c1ySxI/3v3ZfzaSGS8jsgSDkLB4JumrE9ZkLNd1";
+		public const string Intermediate_Certificate_2_PL_01_01_crt =
+			"MIICljCCAf+gAwIBAgICAIcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3B3UKG3tEL6FQz6dL6iqSvzgGsm1Fg5uzK8npkEq" +
+			"g2caUM7huYFfXeur1mu6iKiROcGX8ZYxrPi9Orh39YVrSu2EUWvqQui4QScf4dIlzAOunv" +
+			"0gAa/lIVTHgZhIomKND6/tZLU251dJiFhoV6bXx2tor83vWFVPx2oVd5LL5S0CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECJmK3jFTIl6lMBMGA1UdIwQMMAqACBpj0+Gcq32oMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBADkYLTg4RncTpAFmpUy7WGOMvoFV15nDoi91OMxhxVkbGSE0DJFxi3" +
+			"hPKcfUNvzy0bEUUTaqOXdbIkoLTG77NTckJxurSRyam0jA0+6SUYZ6F9fVotwMul2EiVl9" +
+			"XP5oCt7LkgqVgMASuwfzMnQozB6Oi/YP2OdSPXLipI6rl2dx";
+		public const string Intermediate_CRL_1_PL_01_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIGmPT4ZyrfagwDQYJKoZIhvcNAQEFBQADgYEAd8YZ" +
+			"8jibr8yjcGYSDicJuyUvHBZntTVQ1sP5XVmtCZcYcQCVjbC0auYTEP5snXbGPW5qeEaaXB" +
+			"MhekMr776hP4Kl3g4AjguFl3XQGcURlgNd8LsTpMMdNWC7XwooOF2FzFjD1ru0BSEWabzW" +
+			"NNaVeuMMbu2N0lc6NDJvRC8LkhA=";
+		public const string Intermediate_CRL_2_PL_01_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAImYreMVMiXqUwDQYJKoZIhvcNAQEFBQADgYEAZFec" +
+			"GtjOfp8pT0n1dMF/x9n8y5tM+G3LLnZvDJspLc/sqP3E3B/sHBiis81caEkQQAOTBU5goJ" +
+			"0KOFAUOfEq+IX5uvNhuPuinx0OsSak+2Annvi12zodMQKPNm1uMVt2bMHHHZVEVTqcv36g" +
+			"xgdbp0YKTmuvSy6s8NtGFpkNmnU=";
+		public const string End_Certificate_PL_01_01_crt =
+			"MIIChzCCAfCgAwIBAgICAIgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCAUPp5j4V5XTA44Ra1EWkp9HgS4w3uXJ7/Vhi" +
+			"K5bARFrDOOxjV8nmr5hoUYr4jwdi2Rl+60TQK/F08gdcGxdyc9p/yiU5HyAP6i+4iqmvaW" +
+			"9b2egNyZ5tOmpl/Q9FSFWa9d/PYBKM5Sj/r73RtA+/chc4uq3uyLekSRQGh1MieQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECAiL3A4CkaFyMBMGA1UdIwQMMAqACJmK3jFTIl6lMA0GCSqGSIb3DQEBBQUAA4GBAJtH" +
+			"mNNvCt/0uFbHdvUvCuBeZ9cggfpTyUS4X8zgcLDPFbw6VvX65umOZpceZI6hwcre+LZahi" +
+			"gUEPvXppncEObkeVTcYdOTSDoxh5tZyee1P4sbD9H+suGWeewqUDvFs2ymHtxlkpOttitR" +
+			"xQc2U6VlCuZ4XU8SwucyhW0z51e4";
+		public readonly string[] TEST_54_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_01_crt,
+			Intermediate_Certificate_2_PL_01_01_crt,
+			Intermediate_CRL_1_PL_01_01_crl,
+			Intermediate_CRL_2_PL_01_01_crl,
+			End_Certificate_PL_01_01_crt
+		};
+
+		/*
+		 *  test55
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_02_crt =
+			"MIICmTCCAgKgAwIBAgICAIkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4QmGXEeVKCn1aQx27r+EBuQqfi8fP7gyV5JLkaSu" +
+			"DOUrqXg8dQxHsBNCf3XilGIvjNFZjVUPdS8FNqC+if9D164VyGQlv/JUor/GlvwVfyotUO" +
+			"U1PqSzFrAALYTmfm/ZqhMvGYloStSDxlzjDmyKadskzOxZZDNSe5s8dvUpYn0CAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECGk7qDbbBgRbMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAD+eI+jg4jmeC3pJRGEF/hbPPYvL6aocjqqbZyNKN5FWItccQo" +
+			"PWg/GK1GpusDZadesZBDo6fLIUJzL+OumrIYJLB3HxQsmyOXB1gRg1hcva71RWFJYzx01U" +
+			"eB8lCbk8Zu24HzLzqjfVuwKOFFELWDEq7bd6Re/aKSHtNnDbsgSE";
+		public const string Intermediate_Certificate_2_PL_01_02_crt =
+			"MIICljCCAf+gAwIBAgICAIowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAl/HiHoos7eHaDIFhMmvIPk63UT33Z+0iiCIuKLW7" +
+			"tgkT8ia1Yg++np1pC3oqYVeKkXqMcjgonPGQhcek12vLt3/+2PYyYirOTVZaiO9pKQ5An8" +
+			"ZMWXIJmCEAMHabPO1RnetvRv5JZFxZY9jIUnD2fUADzzUh/eHN6Pur0DDrI6sCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECPk0C10KQLZuMBMGA1UdIwQMMAqACGk7qDbbBgRbMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAMJ4+BZQxpxWhNbo8bpGkbbcKT3kfKYrHjHsZADC+/gAJSVL854b1W" +
+			"VKsGr1YcCX10V1Gcqb6Jgziy+AzRLhcJngszcz0A7LxrMH+FIyWEPgZnOyQCa8B/9bnsh9" +
+			"bC1gEmXGOVtWboIFOEdGghEbm/ENnQyj+HbIk3jhF3QYbXhw";
+		public const string Intermediate_CRL_1_PL_01_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIaTuoNtsGBFswDQYJKoZIhvcNAQEFBQADgYEAZEt+" +
+			"FjRuXgnOZg70geqS4hVsF1VWWawlAVGmjPsbRH7rADXPUE2bYL54wLdwt/6QYwHqy2KwCf" +
+			"d4OkWkwn9xwGS4j+XBCw9Y4nbWI+wrsZ9W7vgbeIaVUUUZu6hoin1GxrGDcfbM+bhYzQAA" +
+			"gNmKIWdlJ4tKD2KNgg0KmZPoj/k=";
+		public const string Intermediate_CRL_2_PL_01_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI+TQLXQpAtm4wDQYJKoZIhvcNAQEFBQADgYEAXwZO" +
+			"wr9mrO6yUOoopNjcIcDssCUksYco1PFgWx9O/hGq9ktdoGoGcECGhdkHTLe2ab3WFl9jzW" +
+			"1/lkysD9Jl3VjbnbRB3dPQlrSfiv7cYBLnfKvyF/CxQg/wCtWo46GJJQgOx/WHzi9aF08m" +
+			"tQuJEtl7RgoByUSvLtmvKjQWEnc=";
+		public const string End_Certificate_PL_01_02_crt =
+			"MIICljCCAf+gAwIBAgICAIswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0/rXOZwUebRaHcPPFeKTB2OWIzIAgavqb5HerPAe" +
+			"c3sJCdNOSLc0OX0dFblso97WR8uueF9I7QeGg3ayQjzDVqm5Tu77ZaCuyb6UU8+fY2eqwD" +
+			"5lCVuLfJr9U2JD5b2TcdvAD9RqfhefclVjDj9rObLjvzLg3AefO3drsfBtAIMCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECDBWCFTOp3evMBMGA1UdIwQMMAqACPk0C10KQLZuMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAI/JpU3gHo8Izsbjlx6bkQo/e/hD634N5lSMtVHIGnoVLu99dvroRu" +
+			"2DO8Fhnv6VZpMvYoAc5oEgUqx9hw3bfS/XN9GXaeMssjwN/qM6lzCsvMG7DA9sf59xjf4Y" +
+			"2+u4KTye4PdpmWaseDDJ1wAihTHEaofnQdaoUffxQgw5UcAf";
+		public readonly string[] TEST_55_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_02_crt,
+			Intermediate_Certificate_2_PL_01_02_crt,
+			Intermediate_CRL_1_PL_01_02_crl,
+			Intermediate_CRL_2_PL_01_02_crl,
+			End_Certificate_PL_01_02_crt
+		};
+
+		/*
+		 *  test56
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PL_01_03_crt =
+			"MIICmTCCAgKgAwIBAgICAIwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wMzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA60y6V2WkNCB34dcGfu+Jo3YHQZXzgp76+HgnyFmP" +
+			"DLj9DjZHqifD3gW8Zk7L+yK4PfLDSHjbrXM9GY1ser6XwhaJQDPUBBYW5X3XTOmDWmV63J" +
+			"YeRF5r7cfF2h3eEZ460GRLK5tt0Zr8V+hA9oOvwqynrIhDYC/tCzE28ciqA+sCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECPE2FCetVerZMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBABUOUWwyfyrRIw7dRIVfLlWyp5R1I+Kmq5e8st0AEMVpPAmLoy" +
+			"0s+46Xf+THXZy5em1P3bSVTSUhTs+XD6tbFFUcTrX0mQJlshR7yD/A0siMDUNzzt9LJQvP" +
+			"dwNjQSA2keOrV9q/2CAGce4daL4Wz54jfh33YVqJ8sHT4E8CxQb7";
+		public const string Intermediate_CRL_PL_01_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8TYUJ61V6tkwDQYJKoZIhvcNAQEFBQADgYEA6FnB" +
+			"LXWt4B/3oP0PXERYh7ZV39yu/tm9DHBQGcGDF8JIspU7F+mH/+37U/lT6BQxpKOpgOgGeP" +
+			"nTQeQzN9sRsXxFO22SkHbdPCao84qvv485epgzqFcVsCRBwBBLcnNLMg891q0EYsTW9vSw" +
+			"Dx7V4CawyYAYGz1MqYuY6SSs6Q0=";
+		public const string End_Certificate_PL_01_03_crt =
+			"MIIChzCCAfCgAwIBAgICAI0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjAzMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwt6B9gpDz/x/vnowXf1MdkAPeaCWZ3pYikgxE" +
+			"ZLrMuulFaI1UDnAzgSuSvoHE80VKGKjSkrzIX9OFfeilW5rNZAXoZrjtkaJd1Q8l5AtjFn" +
+			"0tlLytDzIMYo5Tiq/n3IiTdbEzGYzEOCcSyVaQdB7K1WgYI/z/UAaWV/GbqCX1zQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECMQHLiufEm0IMBMGA1UdIwQMMAqACPE2FCetVerZMA0GCSqGSIb3DQEBBQUAA4GBAD5/" +
+			"vGn/rpoHvny/mfh6n2zVNNQLTEBiddfAdCWpeBFcwxS5lpxfm4dAWgHhprZTMirF9yS+wO" +
+			"wWQ4G9/wiqfAtoaNN1qkHMlUMOAPsOSff6ClgP+1uzKVqQa9NTd5HAeMdYfYjMa/fcF/37" +
+			"plCs5ZsJjb9lhEjNd/tq4/aALQmt";
+		public readonly string[] TEST_56_DATA = new string[]
+		{
+			Intermediate_Certificate_PL_01_03_crt,
+			Intermediate_CRL_PL_01_03_crl,
+			End_Certificate_PL_01_03_crt
+		};
+
+		/*
+		 *  test57
+		 *
+		 */
+
+		public const string Intermediate_Certificate_PL_01_04_crt =
+			"MIICmTCCAgKgAwIBAgICAI4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA06yd2NQEAgpv0kQQEOzhHHU4YqHgtvJgkdLYxb2W" +
+			"Zordrm4b/43UDnLmsI0790V76y9Aa+Y8SIMBBRBJgnlppFJrFsPaOMO98M3/mXkQotVbY1" +
+			"59P/AjWMxpzP9h8Bs8KuoPqnl5jN0UZAF4kRoNXHzyS445VBp4DtWz/jcCPm8CAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECHxLORDZ1KKNMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBACHmDOaoC0Hr2cmfuQvdyGDF7/RlvTUJ7cvGypCa724SwAZGZk" +
+			"Tf5GwxgjVcLHY5RlX2kDm9vjneDzP88U3587qA2ZRwxhheK0RGp1kudNQ5y2gAGKZ7YSc0" +
+			"SENMDxUAa6HUkn9Rfo4rf5ULuGNJZXQZ3DtP+lZSwzkUeCVjKhyQ";
+		public const string Intermediate_CRL_PL_01_04_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wNBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIfEs5ENnUoo0wDQYJKoZIhvcNAQEFBQADgYEAb8lX" +
+			"19SlVNRkc9SKNpRLZQom67djZfMSIPIDkBALfMepdevbquzgO7AufTuiDn5Zqe6J6odTv6" +
+			"RrQReo64XB4+Lx2pXOe8bZEbzZk0HvzLl9DjN7zxyNglNK+Hd2xS4yT4ps4fBdvXvWAXEx" +
+			"6DfvWHbGFDoH2auomCKJtCVXxCI=";
+		public const string End_Certificate_PL_01_04_crt =
+			"MIICljCCAf+gAwIBAgICAI8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDQwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA14bXc39XiWvb4r1jzbADzrpfbg2Y9sGBkefSQHsM" +
+			"QZ1SRLR7uexWD7MuDYh4ZYBL+WPhaJJr3a1jnAIp54h68m8mwS13DgrxBF2/hrVKEm9IRG" +
+			"s13hoM4Mjjogn/Lvc1xLvB5lctHjZrNRZjyrt+PqDDmqZqgCOmcD61PhrfAoECAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECB9hXgJfzBvTMBMGA1UdIwQMMAqACHxLORDZ1KKNMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAB0HgiURRd/REVfc5DenIPhMu8riVcwVgTUwatsCWragUhXpCtvJmf" +
+			"z4vGo1rKYai2dltVX6am+NDvN5tROcM0bvC8lOCc/iPfI5eWTy9SJ2nxvs1+q809Rj0rno" +
+			"zS77TIE8rD7Q8ZUd3qNUiBwdjBoc9misgyN7zUulg4Ueebvv";
+		public readonly string[] TEST_57_DATA = new string[]
+		{
+			Intermediate_Certificate_PL_01_04_crt,
+			Intermediate_CRL_PL_01_04_crl,
+			End_Certificate_PL_01_04_crt
+		};
+
+		/*
+		 *  test58
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_05_crt =
+			"MIICmTCCAgKgAwIBAgICAJAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA/rVBEGZ4jibDhREeRGV3jPnv05esRL8/En1Bu35y" +
+			"QrAHi32+kBu42vwwDbeuiTZd/B90bn5srJZoW83rxXxNnpxqbnjN3GgIcRiUVyaVRTp9/U" +
+			"IT8B9h09b9yT8gpQ5qR0+JDcOHCfJwpogAsyJJa6AM5p/q3TeF39ugfVOWt/cCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECJ7/mkuLuEIGMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBADC0A2KMMSSmGI9p85WG7XZVMBX/xdDYOHO0e3ORTRFS3kj9rK" +
+			"a0yUjc1X+p22AA8kUyOLpYIulfDjPrLKN2E/hWSf3+XWMiC7JfX01F+BBl/avEZoymaZB4" +
+			"dkH1Hym4IMJoSaEOgf5HFKBnFEA6aUcr+oDYGUP+Sc1dmJMjBW72";
+		public const string Intermediate_Certificate_2_PL_01_05_crt =
+			"MIICmTCCAgKgAwIBAgICAJEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEArir4GaS6r0Tv9PMbaOXYdPKADNpVbJe79G5t/F6x" +
+			"7Tz1rwUR+m10E+Jq9RsV+fU/nUzzjJXHbPLZnfodUVVmrXgzvQ8+B2N4jJtdNLG66j2PZG" +
+			"+P8GQzVK9drDh54VHXdvxAYCXs7GaIprWmCQsxZOKjhFU3YDiRRK8qJGpBG/cCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECMmrFr30fUzZMBMGA1UdIwQMMAqACJ7/mkuLuEIGMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAI4qJF6STCi+elUbpZIP7YmcaQsS0PE4G3+LJoMg1LT3rSeobK" +
+			"Aj/yUetmA7y0B5i0svKjRChLOpfClNPVPCx/+mc75+LG+dh1eVG/qk2UH/lrqLN0XLl8tA" +
+			"IwZeoPaegBQAIp9oEjhDN1fWtKIkOe6A6wYdH2VPvsqC8g02VcwD";
+		public const string Intermediate_Certificate_3_PL_01_05_crt =
+			"MIICmTCCAgKgAwIBAgICAJIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtRC2/PDG3kx8LpzfWC0yJph5h3LXZJZW0W2voss1" +
+			"HYPP1/MBoQY067dfbALilVRh9asCNL4F45uu0lT24qS9vjW8SzBOLA18GsVYRmWO7EP+Cd" +
+			"9f3mgPIMJ5n+UjW+yhBwh0Z2pzVElkX9CxECrs1Mt2ulyuwWA1lR8nRMaTUeMCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECAlV3mzXYPyuMBMGA1UdIwQMMAqACMmrFr30fUzZMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAG28iHdlA+nTs/b9pi+m9eMy7niELjIWL9fMgn1r4iXQ0TsPYi" +
+			"tgpoip+BB4G/jz7MPx/N4nwyAPV+C9wN8cAHALf/ka2MxAORYFVFI+5PDgXzm78ILqj91f" +
+			"vOFN4jemizTES4/dHxfmdctnsTRpU9ALQgfJLhxEQISOPwuemKB0";
+		public const string Intermediate_CRL_1_PL_01_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAInv+aS4u4QgYwDQYJKoZIhvcNAQEFBQADgYEA5i45" +
+			"gETFAw6l9Awex9IAVIqYTA1dnbDyrUYDRdzd0x6OxSPODvNfQCwqwlTJXrHidCPO8jRhMS" +
+			"Zcdn/MTlIeHa6OERFcjOiwOpeTgtchvpTdDchs5ve8Ik+myue+cfgpEVKOE+ZQ2T2tcyz/" +
+			"+DbeMptECfJ0lVfCKIY7ZOzBPaQ=";
+		public const string Intermediate_CRL_2_PL_01_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIyasWvfR9TNkwDQYJKoZIhvcNAQEFBQADgYEAdsNe" +
+			"ugM8sd8bmIDkYXce2WmS5Zx6QUQ0yT6Ij4OR5/F4CG4Vl+k3JkNPuAiNSs2Z9HeML+F/W8" +
+			"3yEPe/mdLV4nLw4B/b1/8DmgZN4r1ojaWuHAg+KrA3Zz3Rc/hwQfvBy49mf4NGtY4ArbeB" +
+			"DYKz5sVlrwR+gOCR5jm4IC7WEDs=";
+		public const string Intermediate_CRL_3_PL_01_05_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4wNRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAICVXebNdg/K4wDQYJKoZIhvcNAQEFBQADgYEAqYex" +
+			"FaIykZo17O2URpofe8x04L/VsfA9jV28zUgNFruAGld/kUh4rYvgwrdbNZ8NmEFDp9J9aL" +
+			"93af3bzoNvWCik2VrQLd5nccCFiC04B+LUH9Y2p+7vV2ojrtBks5SMW0q4HaNyPSQu8Fst" +
+			"4mYVf+QIYZC3iVAF4rsKnaxwzIU=";
+		public const string End_Certificate_PL_01_05_crt =
+			"MIIChzCCAfCgAwIBAgICAJMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDUwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA1MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCXJjzKGcLyONTyOa6sQHvIKZIAh0pWdteUiXf" +
+			"b7yjCn6Z52SCHxB9GZERHwR7fbJpoE3oDcYUY+8pH65bIVm1p3zr5deo4v85DEZQ50cU9a" +
+			"WEUAO/5X57P7pYb9/47abu0cdsLIWeE+O94HpZS8vz8mxRQKLj27gPY1KzzTbrZQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECG8ILlM9oqZwMBMGA1UdIwQMMAqACAlV3mzXYPyuMA0GCSqGSIb3DQEBBQUAA4GBAF6S" +
+			"x3aunfgnDmo42aPOzDh536WSkTTbX9bmUNyg3IQHl/3xhVqjS76bMqreYhx5nh4VNx/Z3N" +
+			"LD0W75XmASCk0wtW9S1MoxzJMFIozRruaE3oykrbyMMOt0Br5CV12ofUd0WybDkXfNAIze" +
+			"IRgps3nORHWjV1GwXe8uNoUn6/z7";
+		public readonly string[] TEST_58_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_05_crt,
+			Intermediate_Certificate_2_PL_01_05_crt,
+			Intermediate_Certificate_3_PL_01_05_crt,
+			Intermediate_CRL_1_PL_01_05_crl,
+			Intermediate_CRL_2_PL_01_05_crl,
+			Intermediate_CRL_3_PL_01_05_crl,
+			End_Certificate_PL_01_05_crt
+		};
+
+		/*
+		 *  test59
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_06_crt =
+			"MIICmTCCAgKgAwIBAgICAJQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAweCAiEGMLycmodjrUMIWEEFshkvhX2r90wGl+/pU" +
+			"Ia9NSdT23zYzE4Uo8Is1ywyV+YfvgR22j/RXF6j8OK+XZ8jlgfjVTAhjCnTWY9LDR7qAyk" +
+			"8zuuITxJrYpiPoxqZs9BXLfGkDbye5VpVJXvQdbJNxgKO0hkBBDfe+T9+qw6ECAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECG1DiuoAwV6aMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAMFvtFiMDMP6n3CrqQLSzhpK5Qu0uxa56ARXIKSIqi0OUZAu9v" +
+			"sCXxMvaG/R5bElwi7ybYZ5KUSN+PnDmlUxWWL5Ib5RZdXgj7L83oyLTQmbDMvka6rSWHgw" +
+			"Jq8qHVslhh+l+YNOb4fzs8x9ctCrs/BgjX8wkORpQbigU0BUJ9sX";
+		public const string Intermediate_Certificate_2_PL_01_06_crt =
+			"MIICmTCCAgKgAwIBAgICAJUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwf6Nf0+r7JvE6BO4MbDbS1T1SCzn78haBAmqGZLS" +
+			"Ac4xQTydvmzr9PwiWlU0xjFfKItqRMt7rfzTTPfvvnwxsAfQNPtxKzi30yCNq/VotMA7j5" +
+			"iQYaVe2OWVHu13agbXLEZ0pL/ZkmQ3Gvo6UhF4dRmCnjFbd5cMTxQVHUrwgyECAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECE3tS4AYmwZDMBMGA1UdIwQMMAqACG1DiuoAwV6aMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBADcBTKbhx8PCunjRVJkcLBCcVGHs9HfkChDafwBO51fe5uhHE2" +
+			"QBpW3J8ZsevuFQiEZvuy2RVFktE6ZoKD8wxwBFhs+OIxe2mergQPy6jHuxoSUiPzr3CVXZ" +
+			"UsNxe7j3IcJLqbJ15UqGFH5yph7Sa4Ym6x747miF6W9knNkjcx3K";
+		public const string Intermediate_Certificate_3_PL_01_06_crt =
+			"MIICmTCCAgKgAwIBAgICAJYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwq2YlDLHX4KktKnzLCYjnk079IDgXENrkRBuZHTB" +
+			"IQyZoiBH4ZWHreZKs3LvznP8uSd8eEL8keNw4PwZ6aT1LF/Jr/UlrFQNnpLzQVXwGGAuzh" +
+			"tFJYRlOfI5cCZYAcpjnyUV4GW+MuwBdoqDycMjmqIv/8A8vupjahffcmBAassCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECB+qYFJjEkJ5MBMGA1UdIwQMMAqACE3tS4AYmwZDMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBADiXredACtRQTV2TKgu5SDdPlczj7cZZUARJiJKiRfjmxHCc1q" +
+			"m/Oh7sHkqRvlHqjoX8qp4iSchoZWdOAE5O/q4Ef6rViejDFVyN2ZmlhP6KIiRxznrvYfF1" +
+			"n08K7CHgHWvDaumm4pNmWeF03nuasHrY0W9h1uk5poVuzaWDpx3A";
+		public const string Intermediate_CRL_1_PL_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIbUOK6gDBXpowDQYJKoZIhvcNAQEFBQADgYEAiHM1" +
+			"xFuYt6tDscqzwj0mLHPHULnR44/vNyPUg0KnV03Dd4XbFHz0FtwDKgVTBZ8x7ybp83ubJH" +
+			"tE/p8nPW5kN25WQOlYkZoAcMpEXjTzlo9evU0W3nyzJjmlT8YEI7vnmWFz/ahzy6WFwPue" +
+			"h862EKh2zVO4hoqZYEuDQI33fOc=";
+		public const string Intermediate_CRL_2_PL_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAITe1LgBibBkMwDQYJKoZIhvcNAQEFBQADgYEAuDSF" +
+			"W1KOc4x41HGvdRaw/NtipD2y6zSh3mtRoo7Q6J2BvJvunymZNEziozBOiUgT8zMgbdbm4a" +
+			"PEwlHRaoJP8+yxJIlKaHa9Hc7Yz4SOwSrLicf7EnBSct3Mze0b48UYqbn1q+lf/zKaUGrP" +
+			"M6oqtE8Fam06T+WUfutU53zTtSs=";
+		public const string Intermediate_CRL_3_PL_01_06_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4wNhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIH6pgUmMSQnkwDQYJKoZIhvcNAQEFBQADgYEAcPfO" +
+			"+Rj2KmO1CxjuKLEiOUAIq5YmR4U06IcCBGMxlrdHVXHM3vepBKUlMDaT4UGcleABMPX9Iz" +
+			"/31ofyXlZ/fQJOoTZt0CI7SOPQE5ZkUsR3BDuUqf1+sWwBYyBHkrC95JhJkM4LfGS5K19p" +
+			"fp0j0bguzNCXSBRTfjSZhy80tcs=";
+		public const string End_Certificate_PL_01_06_crt =
+			"MIICljCCAf+gAwIBAgICAJcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDYwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wNjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3asAqJcjXngEuyM/W3+TAE+Qr4JtNUdwBtmrpGlo" +
+			"fAvJdmXHARyiN/Zn6Si8bGI8Wz8J4Y+Ll7zLdaMU4MCZo6hwZiaQwkh9a+ZecCpLpjs4mz" +
+			"MSf5zHSwTYiXKMazlmnGEITVyKLmAiLSyGeeJvOJVqVo/NZXRGVlmnPxZFfgsCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECLZuS770NcDsMBMGA1UdIwQMMAqACB+qYFJjEkJ5MA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAGM18aR2i8vSywsWhcLrRN1Xckl/HiBPNphobfKoER4NG29cFjUPQX" +
+			"zukjQcJl2clAXNCVtcsKCoYRP3YUyAB6At+yskuuJXtES7FIzM3rt/UpDS5ktVC3gh+jgE" +
+			"pPhMILYIXFzYY1hifkpagfO+mkcr7RqHU3tHAr6LCWjqrB9g";
+		public readonly string[] TEST_59_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_06_crt,
+			Intermediate_Certificate_2_PL_01_06_crt,
+			Intermediate_Certificate_3_PL_01_06_crt,
+			Intermediate_CRL_1_PL_01_06_crl,
+			Intermediate_CRL_2_PL_01_06_crl,
+			Intermediate_CRL_3_PL_01_06_crl,
+			End_Certificate_PL_01_06_crt
+		};
+
+		/*
+		 *  test60
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_07_crt =
+			"MIICmTCCAgKgAwIBAgICAJgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wNzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5HkS45NLuqq9ZwF79+pTGtQnGWO7DFdetYeQTbeD" +
+			"sisjZMsK0sCCR5xAKYQsJSS4v/8LQUdxlQR30LMV0SQUKFMJyFsMiSsO8subb6sVINWn8A" +
+			"tL4zcQK0WiASUZOEkybAFJtP31PahzI5wfD1cikE1M4BlDij5WeaIjt/RTHKUCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECLSUEn5d8YywMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBANLO+kEiswkGzEh4ZcF5LtfnPZlnG4gTPSNugeWJc+Xedqmttp" +
+			"jZ35fr1hiRe2Q1UcyTd4ThkPknawwZednbsZVPqw8u1mo7kuAeL9KrCk199vL4bV8Ag/kj" +
+			"HJ8TAy40UDB6hMm7l4j8mEKwV03THVrz1Vvz59CQXj+iseH6yUNO";
+		public const string Intermediate_Certificate_2_PL_01_07_crt =
+			"MIICmTCCAgKgAwIBAgICAJkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wNzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu78gmT5HwmBHEe+K8fLLgGaPpcv13ZjrgL4twTBS" +
+			"OkZn5LL9GcfkPuA5WIAZkVYfCWSDPqcAGoOWUIDADfBfdcyLteUH+xI01rHKiLDVexMvU9" +
+			"vqCmcBKhxK3S6wraW5YhOO0bx4oPrZXVIjyG8fh4e5WTEykzvUWJ8ZbzSJ9JsCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECCT+fDEaN7GaMBMGA1UdIwQMMAqACLSUEn5d8YywMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBANpKr98PiXAdcXlbgSgif0213H+tg3WwUNKZTw8MpqPyrN2/DZ" +
+			"HBi6e2KWXLTxttV9AZBRvcKwsveS6oc31eulMe8nHxRNRfadvF6dL3Tsig6HAQkartcJMI" +
+			"yfW4V3EhXbCdziQkre7XcR9WK5bpQoX04HWeew6YTxjG/cL9MIJR";
+		public const string Intermediate_Certificate_3_PL_01_07_crt =
+			"MIICmTCCAgKgAwIBAgICAJowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wNzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr7YezMXvnkSuNCdXch2HRAEVuCqfzpVRCj6laJI9" +
+			"Q+NxgXwzaOwnImvwER3Hblh1l0MAt5/I/9hhqCN+918ueME50MkoM1wPbcmrRIlwWLGSVZ" +
+			"yBKeyPHrLbdPqVIexUlQk7PasLm/Qx4SvRGVe9IMLrEzPV3MFJtrJoWaMobQkCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECKw8JlHMvVfuMBMGA1UdIwQMMAqACCT+fDEaN7GaMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAA5JEDEDyqfZzTGzOoMV+8RVke+a4qgOo7rnOEdletgGFEwz8A" +
+			"tiMHBxR+UMxuHS82Hz3+F8XlyYIwlrG9wWVcB/tOyzgVyA28Yux9Q/meU7T6dco/AnmOdr" +
+			"2XL6Xm5iLnARG+PkUPHOsxuweyB/sSUSA8ZJPowNRWTik57ul/bO";
+		public const string Intermediate_Certificate_4_PL_01_07_crt =
+			"MIICljCCAf+gAwIBAgICAJswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wNzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA7mNS8dGz0gkXDbBRzP2ypdNMahJbM3cSMHO0hYpn" +
+			"uRsiXGUhIB0K4WVbnz6tr7Hch3yltK4H1Y12Lf8cXEETR2sE9lCY2A3r8/VM5OUbou5Y8k" +
+			"wIf03VhP7cGKonaFtlj/WD77fidDePVp1Nk28gV0T2F/l4pM5TEJrq5C9PSUcCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECJBEcZsMRq6CMBMGA1UdIwQMMAqACKw8JlHMvVfuMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBACfbHKpuRJnZ5UU0sih8RuywhUo6Getwl/p6fsi87wYI61pvYru+hm" +
+			"4R4eAMZvg7MrAarS3Iu3zKBU1HKeq1i+hpwTIXrngR8eL2fU/X6GPzdte3+3tjhah38bqF" +
+			"zDon+N6ap4MKWRk033SsFYo1K88Mena2tGuFForJlV9DOF1l";
+		public const string Intermediate_CRL_1_PL_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAItJQSfl3xjLAwDQYJKoZIhvcNAQEFBQADgYEAJtaE" +
+			"I1+PCNL1/bgEVKWUIwvh58ugnWhxzbFW6hNJwNEz9/yt+FLZfNrT/Ezort4VVQFLQg7+Gj" +
+			"KrkIujqfRJG4LXrXAV8ZsvSPuwyQ+hM1GdHGDPhj9x6DkjFusxJYUEs5BzlX7ovpnaIPSW" +
+			"RPsatheSzu48pMOCmyTKE3MpuZg=";
+		public const string Intermediate_CRL_2_PL_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIJP58MRo3sZowDQYJKoZIhvcNAQEFBQADgYEALiV+" +
+			"BFpXhgTjiMZBYLVuc/fqhHcXeXOGOmJZoKUnIXjETH3rzkkt5k4tMN00ycZVgpRwn3ZyQs" +
+			"cFLcW8taau1J7iQOmGY/7qIT0eFx2OlgNmxqirmwx4OM5VSH5mEpnp9NOr1rfut1GDRzw0" +
+			"tZ+nhD/PGDXYPu+QPX6jii0vdHo=";
+		public const string Intermediate_CRL_3_PL_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIrDwmUcy9V+4wDQYJKoZIhvcNAQEFBQADgYEASY47" +
+			"p94jEh9FZ1TrPS82nWC3Z6ZKdaD9pUbaJpRnAId59QdBaD2Cxq+SfM3HTlz8grCAPKwulv" +
+			"jDDhXhp4H/m63Q/pJbyl3bbMxnphMOoDwB9wwKIUQPM5wagMovF/UYtC8MoC++m2kuZ1eb" +
+			"fR/OIJuQr+k/kD5Axhw/xolKPdE=";
+		public const string Intermediate_CRL_4_PL_01_07_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QTC4wMS4wNxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIkERxmwxGroIwDQYJKoZIhvcNAQEFBQADgYEAMhIQ" +
+			"lE+BdCO6NBz+YgcH+tjP0n4OCdQ+7uxUxUYmPtPbsLwbDDEEZUjykgwiA6P47Cqh5fXB6G" +
+			"tfInh1cmQi3y2IEHK+bRSx321qczOh34Yx2hw5vp+JFttbQAEl/BHixklrFBrXjN0UsWGC" +
+			"ibXcZy0YjerWTp/yceoABz9p94U=";
+		public const string End_Certificate_PL_01_07_crt =
+			"MIIChzCCAfCgAwIBAgICAJwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDcwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA3MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCdH60mBM1eInACvOB83zLrtiebq9B5UBlAAVS8" +
+			"9ucDwGx1HOJwhwk2AmvhN7pYuDc+BFzuNtgHojqZSDpRMA3rVsGlgOkZ3sOQzvxB73w+/X" +
+			"XmCYpwcEGLpK4egl8r1aOYm0Zm4OxqWhNu9+Do7nrJczDLi8k/qh8/+Rfdtvt4kwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECEmVurZ+7UXFMBMGA1UdIwQMMAqACJBEcZsMRq6CMA0GCSqGSIb3DQEBBQUAA4GBAANe" +
+			"AbvpAHwBu9+FlI4DOb65Z+h5f2Ok59FVbVqAj3zkMRkawppngK3CMY/1BQlGXOlHvE+CGz" +
+			"x/7DsiV0O3rxOUjutt00PNxCyIM2pcOZeGUaAu5DJWn0SRwzTMJa4M5K+7wh/4sSPWyxKi" +
+			"ueDq2VXvIgAfEVC8Lv44sxcOduSZ";
+		public readonly string[] TEST_60_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_07_crt,
+			Intermediate_Certificate_2_PL_01_07_crt,
+			Intermediate_Certificate_3_PL_01_07_crt,
+			Intermediate_Certificate_4_PL_01_07_crt,
+			Intermediate_CRL_1_PL_01_07_crl,
+			Intermediate_CRL_2_PL_01_07_crl,
+			Intermediate_CRL_3_PL_01_07_crl,
+			Intermediate_CRL_4_PL_01_07_crl,
+			End_Certificate_PL_01_07_crt
+		};
+
+		/*
+		 *  test61
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_08_crt =
+			"MIICmTCCAgKgAwIBAgICAJ0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wODCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsr+i9HxgO6LnOa6xOHfe9BeLVTo4iZd8rp6UTc02" +
+			"C0MmsSjvIgn3UiayU7aoHcTH8tAXSV5bn0CIH4B46qLym//oE69hUFImy6d1kKgNoaUKWB" +
+			"HztKVtswSSPjIUf7pbyp0wasYMN6fIKYyLpLXUxzA2DrD0kP2Y8ElQJKl2HocCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECPMW3WMPtaowMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAH2N6S9ggfmRJkzhs82uOPXaHF62YEg1pbNxaCyJJbSt2iIIyy" +
+			"NPSlE1OufPPH3pO7p5xcYi90LCI//0tlUL8y7aULFNygbshFY3B8MSgCz3KPA3UKdtIZYe" +
+			"7lqP9/ob5wmkjtLpx6oZ4/38jxqe37pH1IwVjaUnoeElSo3EkCI5";
+		public const string Intermediate_Certificate_2_PL_01_08_crt =
+			"MIICmTCCAgKgAwIBAgICAJ4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wODCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqZZolrig33i1rEwdP1pin8a5PgzSk7fT+qhrJRCg" +
+			"UTOW5WyPtakrLTUipDcR07t8tIe0NsjRoph7+fAwbjWBfbJdydndHHGx5BqWg8Xi4zFhFd" +
+			"6Mc5O6KO7Yqxs8lmthv/RAdL4Eiir9d9hqskKOtQKbLWz+Bz3+9NwfLGzwzPcCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECFjxM3RkbbhNMBMGA1UdIwQMMAqACPMW3WMPtaowMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAJOJKBubTS/kLnfXN5YbQfggxbO2c7DTxx2LhrnPiyVDEow+Xf" +
+			"lMv4YK5olH6UUm02D8cv6Wxg4NeTtBBnwKQG/GV4Ssgc/rrpEzM7jFRQcUzPu0jfya2fX8" +
+			"ZNBnSDjovlN6vmZHtiksjh66h3a0aVusEuOQXD29ogMR8qAGYQaZ";
+		public const string Intermediate_Certificate_3_PL_01_08_crt =
+			"MIICmTCCAgKgAwIBAgICAJ8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wODCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAogLtEcWxzzkkIYe+KrwKhaQjjGQqy2KDsW00U5lx" +
+			"+XJoT8eKd5pxFdCa0SPn/jkNILVeh07mIHec1WF8SOeveVT4Ewd3nG/6ZGoVVq6l0j+3RM" +
+			"jpJbp26BPR69nFn6rmFUMoSNq0VG8Zl+UBqnjq83G3umJCJMMRekUTULSFEGUCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECGAFYeJIhrRzMBMGA1UdIwQMMAqACFjxM3RkbbhNMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBABHamiW7sPLQ83nXt3LZemcAp4QaDB8X94EuJGBwshEcKLoOHb" +
+			"/3cZkPRbOiRQUh/YdpfyApndGFSi0DtwM2Z7yup+MzdrR0wzQoNS95A51nHE7XdCuVFemc" +
+			"LTJ5rdd2BLK3OB5lQagVLzAY9Bs1vaeXKT2Cy+gSUkTIekWcsH3K";
+		public const string Intermediate_Certificate_4_PL_01_08_crt =
+			"MIICljCCAf+gAwIBAgICAKAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wODCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxVjjKlLlZzeZhamPO2NDnRtWM1oWZ3/kdwdBRn50" +
+			"o1NRXb60Ir2HjniK1dRdbijAvR5uItLe9tmj4nusBiaPUGM0HNlEdQWSzble8rvUsP0apw" +
+			"uJusV7zLvzwwbgLbMYT+8lMhxWXM34xszP+dgjWASQOVao1Uqs/MLLibOuueUCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECFMFrvh2hQ18MBMGA1UdIwQMMAqACGAFYeJIhrRzMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAFsCOJ4DzuMOKti5PvF71ZKOtcTHSv123ZNdPIbK6OatT9YhVuUOYB" +
+			"AjMavggywrb+QOXOFfJMctQlS3y/JE9YyoNNt/4UTdx1jQ3I2ablonmzjt8eN5GJ9jUXth" +
+			"fHjxnmGUeWlAvwMjEdzdigkyuWCi9LJfjyHtTjSf9n7w2rU+";
+		public const string Intermediate_CRL_1_PL_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8xbdYw+1qjAwDQYJKoZIhvcNAQEFBQADgYEAG2Aq" +
+			"R1oelnrTgh56m6Mm+Lsm0Sf+Ot1W7LzZmMDwoZgmGLcTduVktx+XrtiDDWsf58hmneT1q0" +
+			"5wl4yNH8y/VCAA3SM/gOq4ddOEiS8GbuEYo5P/julH/U3g6M0vfPUZ5y+7V0s35jIbTkjX" +
+			"76n3Rhf88nvTscYvMdqrYyUhAmg=";
+		public const string Intermediate_CRL_2_PL_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIWPEzdGRtuE0wDQYJKoZIhvcNAQEFBQADgYEAX/+I" +
+			"DkAx7PLTi2x6aYbLacPRaUSjMne84MDaEkYiA64Vo3eL6FbKe14z2mBsM2W7x8xDnxjZ0N" +
+			"RbhcFZ2E6A1ct6HMunuKxjoROIsdWhrYMqJfKKMTWMviz1UjtupsGUWS0dVQCquAr6DJmr" +
+			"W88P8wgiVH2VZsc+edDmCGDunrI=";
+		public const string Intermediate_CRL_3_PL_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIYAVh4kiGtHMwDQYJKoZIhvcNAQEFBQADgYEASw1+" +
+			"6rGDKgpUtXcCziQCjy8mHFD2zV6x/Ppxm2Gj0U+5eFnIbMPmr4TUYwfSOROUycsiJX/Wa8" +
+			"HEuqWJhIdcsHMA7TYf0iSXK597Bljjg4F/1Rgz0wqLjgMuA59eFbKjJ6zP1E6Sv2Ck0Ea9" +
+			"HJsv5zFA1ljVnNWoQwoHsuLk/wk=";
+		public const string Intermediate_CRL_4_PL_01_08_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QTC4wMS4wOBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIUwWu+HaFDXwwDQYJKoZIhvcNAQEFBQADgYEAHHKd" +
+			"U1SccTsK99BUDrvF930ejNRAvHQM9xv80wcUAy18x+TLwBH8vDTmP210/C5Zk9pQs+rLDd" +
+			"doQQbWJrQkznyB1OSK0T41KZ9L0UE+YmFGJjz0PEzYHV0Kc57j5uc7Fsi8Xu20Y8JeTaJs" +
+			"FUXVsvnCuoSxYmwY1futFWHJG7Q=";
+		public const string End_Certificate_PL_01_08_crt =
+			"MIICljCCAf+gAwIBAgICAKEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDgwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNS1QTC4wMS4wODCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwgNkhQrcqmjhkES6DNAW3uQLKILcFlrFvOlWfDPo" +
+			"ngXzCKeed85npqL+Enxo4sLarEiywuDLrDgPf0gKnZXQWBmzWViZhvTsiAemH7iNsNS68s" +
+			"hhb0vnLzlPpDUJDv7KVKW8VbM7nvplKptlEE6g5kmj3iEmM4l2u8Z/pmQoTsMCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECLfApJ09y/ZNMBMGA1UdIwQMMAqACFMFrvh2hQ18MA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAG2ANLc/ib9ayz0B0L6/XQf/xuwETEq8kb5vWml/PbcFD1b/uwRHI8" +
+			"vTvM559nZgtzkhS5ZAvNBTh1CB9Ox/nugHc4srbH6/Wcd94pMQx/sfCB/C6zZ5Tbm7Y4jp" +
+			"hkjnxwGUYTvgNzxmaAPLyCfqY7KwhCSzns2M+yuncEKqlzuT";
+		public readonly string[] TEST_61_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_08_crt,
+			Intermediate_Certificate_2_PL_01_08_crt,
+			Intermediate_Certificate_3_PL_01_08_crt,
+			Intermediate_Certificate_4_PL_01_08_crt,
+			Intermediate_CRL_1_PL_01_08_crl,
+			Intermediate_CRL_2_PL_01_08_crl,
+			Intermediate_CRL_3_PL_01_08_crl,
+			Intermediate_CRL_4_PL_01_08_crl,
+			End_Certificate_PL_01_08_crt
+		};
+
+		/*
+		 *  test62
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_09_crt =
+			"MIICmTCCAgKgAwIBAgICAKIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4wOTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4slldx8rhfz5l2i0rwib2McrCyQkadTjJRoEGQCV" +
+			"xT0dmw7GhDa6wJg2ozXLLk5y7ZCwlmBOTEoNbigHvcKSnJT8R/S+F4KqBz5d5dbRMNEKYz" +
+			"jdbD7Sm7id+eyfq1s5cpmta2lBJ5gTaC9YPSOY2mucGcJ1muYzdOc6h+PCCNMCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECO7tq4dJC8OgMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAHbth0HjAygIoWVrz59ZBPntOn5nzgUGpH60aSDOS6i9ZOKSoC" +
+			"7wCOEt6IpKO7M7SNznxaX2uhFTYotneyq3qENvqZVXKhE6wQRsdK4kG10cxSB5AXPHJRgk" +
+			"W9+p+Nb0iYVKwHdDCW8KHYIroGhSkKxuflwxhK6DcwQuA7y5q7r7";
+		public const string Intermediate_Certificate_2_PL_01_09_crt =
+			"MIICmTCCAgKgAwIBAgICAKMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4wOTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA70v7BFxmToZHF5M29JK6N0Ha6n729cv1U912mH9O" +
+			"NTz9tafa+jv4W7njScv21CJbNlUO5rlAFcTlXY0U9vbqHEufhtwRQqi7+pkfa+Ig8bwl26" +
+			"4U8L5rgmSvZJpEiiKfkmF2Rz9+zPPhHjk58ZcKoAcyhOdZ60KqmaaU/TVtEq8CAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECKOwR13+P/BlMBMGA1UdIwQMMAqACO7tq4dJC8OgMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAN71oLHr0+uf6zCOC5L7oeCOGMUwvZyROu8eTztZrPYGjaamSm" +
+			"Z0ZmUPOJP3g5nO6tHf34Tb9CTkwPdPicEaXuxflkSbJBV3mUFQ1BUDlyYTuaL8uT2N61dg" +
+			"xt5RgYTIGsW3/2XrRvXsH91gSiEkccoUyjKnQcX3oZmEeITb6H8m";
+		public const string Intermediate_Certificate_3_PL_01_09_crt =
+			"MIICmTCCAgKgAwIBAgICAKQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4wOTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwMLmDs63ai7i4xC/1ufMFWeigJAlbKWMti/PeEKi" +
+			"7LBfNJDRaO+1kde6QIo1vhkhKtokNu9ue3Rfo1+xGuZVohjRbHnmamEm5G3jihegPQgGCR" +
+			"fDZoJDI9HMbwBa0RWw1Nes5igIVjdSHQKO/XTul1yyF2Dt03K2qeLwes+2FyECAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECPEAjG80q0FoMBMGA1UdIwQMMAqACKOwR13+P/BlMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAN9eiZXma2n0XgzdvYrlV/IEqBIhpcZ7gycjDumVBVITZJD2sJ" +
+			"bkBi+N8dg7uovgxGxWGsyxqgAboLhMgbpbFzGh+HyIhQu/CeAx93PWYc5rP2l2Y8d7KJvk" +
+			"p1GZEcG/nTakpjxTQ5MQYFsOHVsnDDOyaZYvqPuMrwGYsfoUa1wq";
+		public const string Intermediate_Certificate_4_PL_01_09_crt =
+			"MIICljCCAf+gAwIBAgICAKUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4wOTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo4L9QEqzq2VXzkZI3cvUWR5v6vreKKQPfJPfEwNH" +
+			"nMS0cgDjC4Fnw9ySI7Eb4A/OJGLIyg84mzTl6JX3kGoYr9/bJ8jOD7pN6CljXuHpwwmd7L" +
+			"6Nf5Hy0ltjAIr5s67e33OWdPi4gApS4FN6nPSDkZotY73d1xqJYQQZWuNEsGUCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECLfU7BuxzXeCMBMGA1UdIwQMMAqACPEAjG80q0FoMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBABmQZOvwRpVsTD8uazfQpLJUZkuTap4OOPHie5xJsvOhGend2k+LiP" +
+			"7btGoFrqmkyVV/+dNA8+45SRsnoOtgctiF2ubeqIvd7xf/J5C9Cmo+T89Mt7WEBEuDmEZm" +
+			"JPXvOvyh6lRcYVSBnvVW5ZSstNAQKa/8xuyN0OrE1hJWbucn";
+		public const string Intermediate_CRL_1_PL_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI7u2rh0kLw6AwDQYJKoZIhvcNAQEFBQADgYEAbXc1" +
+			"QgR2TAvOPqJmRFFrDQkPVIVyEEDTwZy5aNnoAKK+AmJ5FZkBtbPJ8qt9UeYRh8lbX8+EIk" +
+			"tyrAKw/1Kc3h7RDqAQ/p8t8kFwVQh2l4KTIukV8hYcj5sMKlt5f49ZwzWPyoOaLDomiUfI" +
+			"OY/jaDMw293AjQXxGCDtnaTvh0o=";
+		public const string Intermediate_CRL_2_PL_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIo7BHXf4/8GUwDQYJKoZIhvcNAQEFBQADgYEAq6en" +
+			"XtvIdh/DifGzWn11hqJIZxLQDGJZPoMmwSOLyB6OzsPrIg1xkOWZYEOELTR8+qP6emmx+D" +
+			"CaEbUDLj60rso0gRQCBwTgHgjeMRpv8fGnV8MJgMv5BdzsGAGQbLSSY9FxtqeCPfZ6olHC" +
+			"iUIopdZJZP8ZvGKQ6QGaMnLpJ78=";
+		public const string Intermediate_CRL_3_PL_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAI8QCMbzSrQWgwDQYJKoZIhvcNAQEFBQADgYEAraCx" +
+			"ruxopFbKvxOx/CIF4niG27ABB2ZwU6n4NBGYHo1Y9NjuytjjMZvQjMHyoayqpnF5TA1vXL" +
+			"jXjI3VgQcK7A4ah/0FNLFGtczyY8kXXrpbmdg8+xdNJEG3/e5rDW5VSf7OY1XqU85ySUJQ" +
+			"ZR5uiy8LxlDdaIT4WT7X5ezs3wk=";
+		public const string Intermediate_CRL_4_PL_01_09_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QTC4wMS4wORcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIt9TsG7HNd4IwDQYJKoZIhvcNAQEFBQADgYEATtjA" +
+			"BdSZYnIbv1bCL+aSiioJg9S9yWGD1mjsA/CDzvkzSffeSpvqaSy+Zwwf+NDMMG6Cs+SgU+" +
+			"sxQdJALAbb4sYGEyXj/Exh9BYHvgoVahH4NWuhm6LIN8RTcMDAtGoGYFNGXGuT8XRBUJZ/" +
+			"tH9re3gpWaE1rjWeB/2ZBR5ONcM=";
+		public const string End_Certificate_PL_01_09_crt =
+			"MIIChzCCAfCgAwIBAgICAKYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTQtUEwuMDEuMDkwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVBMLjAxLjA5MIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC+g1Puqjn+/Of35mqVVUricIV5x+bpZRCAgBDh" +
+			"VYcmZFXLB/XnRd/mYTu0RR4ISEerC1km5tjGeCN2k3NGdZwz/wEh9kEL8WikSqpxUSUD/N" +
+			"vQbliz4f3YECLcpNXKzkCvszeB5ZGHa0sLYDg3r62wy+1y2rtcrHzFEoMFgnnruwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECANGcL2klYf7MBMGA1UdIwQMMAqACLfU7BuxzXeCMA0GCSqGSIb3DQEBBQUAA4GBAHm+" +
+			"/vQ7VxDry3VqiqKnNoOhAHTTIUphNWF4jddRqVc32IsjVaeTbcGwCIRflRm/lUplRvXXxb" +
+			"JEbW9mP3nfTCREUdm49hjmo/szsPjgosFoEmuEKXThC81/y2vQkb4/jqRoOHEknU++38EU" +
+			"Juv6Y6psZNa37x8Yn3i7S+b3TM2q";
+		public readonly string[] TEST_62_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_09_crt,
+			Intermediate_Certificate_2_PL_01_09_crt,
+			Intermediate_Certificate_3_PL_01_09_crt,
+			Intermediate_Certificate_4_PL_01_09_crt,
+			Intermediate_CRL_1_PL_01_09_crl,
+			Intermediate_CRL_2_PL_01_09_crl,
+			Intermediate_CRL_3_PL_01_09_crl,
+			Intermediate_CRL_4_PL_01_09_crl,
+			End_Certificate_PL_01_09_crt
+		};
+
+		/*
+		 *  test63
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_PL_01_10_crt =
+			"MIICmTCCAgKgAwIBAgICAKcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1QTC4wMS4xMDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAr4LmuvhSms70CnuAHIHwz45csKvBPVtcDjA1tWNb" +
+			"NIvvNHBzyt6G8U4CTVKmsFAZOzrWJem3b/ZywM1WlDarGJAAa/SRIYZ/jQwaOIoPW4OUfK" +
+			"ZQI6MO7uAPcIQ4ugtPth10viVqZYLZn/6O26Q905YsFltuPFl64KrJVJJBlLECAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBjAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECGRn9ckrcsEdMBMGA1UdIwQMMAqACKua6/nC51SPMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBANK+1qalm7Nl+PJHT9nQLVJ3ruQNAoMlH9fN52Q9BZCr30iWCd" +
+			"+GhQIPRjxZ4GWojMnqbWzYQsxIR2PLdFc6SwjQrq+i2ES/LePDtaLQddS44/+GP/+qDpM9" +
+			"Mqp3/Nbe1MfOKRBT57qgrxa8eUVieysoKeYX6yQpa8bab3qDwOTH";
+		public const string Intermediate_Certificate_2_PL_01_10_crt =
+			"MIICmTCCAgKgAwIBAgICAKgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1QTC4wMS4xMDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAx5tMLJ3LRxi9jAzCSNkj8zyrSO0cImNGf6ZCIzEU" +
+			"V8LrmXjgiZboPTh9LWQ3msWDLpzaxVxDLBXG3eMO8ys46TfJKciyeoiB8wfuNGMKAccm8u" +
+			"43XjWs1KAdNikWEZupYPgdmA92oRlVcHshG9PqP4+xA6sydpu3V18Nyfa0n3MCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECDE3dDXkS7TxMBMGA1UdIwQMMAqACGRn9ckrcsEdMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAE+8cyOUQ7y4atc4BlZNZvGNRZ63dbGDCM2AItTEAf4ETM9v7j" +
+			"biUWTirJyoWsGxm2eIUk1V+EKxcuO3FotFUe7lS6thmVd6OYOSW+02RXMNklmptzK9I3AK" +
+			"DZNh82ugLNyrrd06BSiED+0MoGVVI4gi3wdFtRiai+MgQVeWIB4i";
+		public const string Intermediate_Certificate_3_PL_01_10_crt =
+			"MIICmTCCAgKgAwIBAgICAKkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMy1QTC4wMS4xMDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsmSUL/UZBYMdqU0PecjCd+9U+1Ld3mKkH303Fido" +
+			"K6k5S4ZObxVHKhYDJyp3CcVT2+nENjzIfQQQaA11UK7Uf/jmVs0IC8e2scWzq0W2BeOLef" +
+			"jVgNgXGsXyfLi9T4KJPPyGsKlIU2R2xKxgHmAOt/tw6OYX/OaEfM1jiQza5lkCAwEAAaNm" +
+			"MGQwEgYDVR0TAQH/BAgwBgEB/wIBATAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBg" +
+			"lghkgBZQMBMAEwEQYDVR0OBAoECHYI07i4owpIMBMGA1UdIwQMMAqACDE3dDXkS7TxMA0G" +
+			"CSqGSIb3DQEBBQUAA4GBAK23Kx99Y9HtFBVnHWW/NfvNro7I5Wx/ZCko6ulHm84FPAjhnL" +
+			"tvc4jmfAZd0wYPKQKWwUKUDWNEwIU1qkxyJYACckue35GLzj8aLY/z+h037vGonFmNutMM" +
+			"rcRdiV7gVD17dYLVTt0RgxsDVDtut+twqHgIaKtKyJnl9dSgFFv1";
+		public const string Intermediate_Certificate_4_PL_01_10_crt =
+			"MIICljCCAf+gAwIBAgICAKowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTMtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNC1QTC4wMS4xMDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEArgBnLCnqI6Sa7gXkZOvIKH4EL5i3CoG6eGG2R8aA" +
+			"kjBs78IKGYj9gY7rRajAKSpf19zvfcW8+2gBDDj5AoCy6uDnBICmqdu+hkdokVi8dJHiTU" +
+			"9LdS2TeuvFv47eiXoEBjMEAquCuSyHvW3lNrA+ESTnK3s7V4lBoO+o5mZD6dsCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECLTgYziQC9zmMBMGA1UdIwQMMAqACHYI07i4owpIMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAEx8wgBjBglU98rocddKAEKXkt4MNzrpUMq75C9HtnuOtFgM2oY/OC" +
+			"x67aZSTEph9ag6Hc+MyxWB5rzGD9j0y7OLsasE9AX8vjplUq50wq1xAFkGi1GnqRK/Oe7D" +
+			"S6R66+UFHW/3KAeNe96aaJuMcx0TRbfkGbW1ASSi/ixMd9Gi";
+		public const string Intermediate_CRL_1_PL_01_10_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZGf1yStywR0wDQYJKoZIhvcNAQEFBQADgYEAjkY5" +
+			"nXjLst8CMz0fyEM7Ft2d9TOOJXV4TMAfSAP9QCnit8qzrdVdJ6TJIsJNZYBz9Ryr5K/iSw" +
+			"KbYk0g6y/pskcMoHG3vJwNAxBbkf+fV7Eyve+90Z6oWDXHKLGCQQpdZ0a0wAqYeiScok8+" +
+			"YHypEVLfbjWARR9fsci2Ps3tdvA=";
+		public const string Intermediate_CRL_2_PL_01_10_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIMTd0NeRLtPEwDQYJKoZIhvcNAQEFBQADgYEAdpTU" +
+			"xcywBjX2rD8Gu6zkDqlDmZfRXHDPtnf2RB4bHDx77kDEib6nH6DGoJdx8WnRTZsTjly3MG" +
+			"62LfVmjp/bJyKHUQqBDrilv21EWsaI9JOr673Nk5iTZa/645GdgyLzSmxvcVDN40BAH0py" +
+			"/2gvBQTPNzp2W1IR2mebuLdHwTI=";
+		public const string Intermediate_CRL_3_PL_01_10_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMy1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIdgjTuLijCkgwDQYJKoZIhvcNAQEFBQADgYEATVf2" +
+			"cEEGphsIe0AsqNJ5rENLe8DeDAV8R4XCKdeP5qmHmLMm9Z4pX8bIfU7bCoXiNIwGvIU6ag" +
+			"FmHPNHEj70cQFVqCX/ZESc02hit+Os9g7pcl7s9QgwVUCMZdCiF/+pSEp3eCL5tFoKmAZe" +
+			"nxkL0KOSuKmBzuqRtZufbhDvmbw=";
+		public const string Intermediate_CRL_4_PL_01_10_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBNC1QTC4wMS4xMBcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAItOBjOJAL3OYwDQYJKoZIhvcNAQEFBQADgYEAbG2B" +
+			"BhvRQ1pY/8VFeiCRFD8mBzq5iW5hWv2P7Zdp9zEbQo0fI4Kbis3OGemEttCxvAc/UPfogr" +
+			"UudImf3s8sLV9BS59xQUGQlxZ5XBNlripY8EjHNWrwgy7/x4hzlZ9yYBbqoNOqnHLy/gbM" +
+			"XZWoCbIK0co70lh1soOQ6eqLDKM=";
+		public const string End_Certificate_PL_01_10_crt =
+			"MIICljCCAf+gAwIBAgICAKswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTQtUEwuMDEuMTAwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBNS1QTC4wMS4xMDCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3bx0qx8s4Zse6Ri6NqkLEKUPLIOhTFj/9Dh7sxvE" +
+			"HpemBlTjbp2in08WTxEb9n8iAIWuGs3Vqm82ttBQmayjIaWD5oE/BE0oV/e91NAv/aRLsl" +
+			"f7VtOb6vi8Ef6muOAjI2dUaUD6QONkqkJhnZ353uR3LZnsAEAW+InePGFNEGkCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAeYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECIokB8m8Vi4QMBMGA1UdIwQMMAqACLTgYziQC9zmMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAKBGQwZQLQFXb+/kjP5xAtq+1rRtrblytjpv3ujJrKH1v2VB2+9boB" +
+			"0YYYGJTy2Wuj0ZBEMeTzMO8Hol4Mq9pnYv5DCmfnZN3FuDidgnRsCjM3ZL7NcXXG9YwlKF" +
+			"G2SXj0YfkSwN9gnyN11W8i+F/OSjlm+TDKHB3ePMcY8EnnXy";
+		public readonly string[] TEST_63_DATA = new string[]
+		{
+			Intermediate_Certificate_1_PL_01_10_crt,
+			Intermediate_Certificate_2_PL_01_10_crt,
+			Intermediate_Certificate_3_PL_01_10_crt,
+			Intermediate_Certificate_4_PL_01_10_crt,
+			Intermediate_CRL_1_PL_01_10_crl,
+			Intermediate_CRL_2_PL_01_10_crl,
+			Intermediate_CRL_3_PL_01_10_crl,
+			Intermediate_CRL_4_PL_01_10_crl,
+			End_Certificate_PL_01_10_crt
+		};
+
+		/*
+		 *  test64
+		 *
+		 */
+
+		public const string Intermediate_Certificate_RL_02_01_crt =
+			"MIICljCCAf+gAwIBAgICAKwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMi4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3AN+Y3Hl/9V0nKXHQotb/cA2VfZc5vrRu+ZjwKgK" +
+			"6KasGegAorKSTybYX/fTbnaPwykDPfSscAnzAW5WdF9+wTLmvYc+6pkcx1ryKkGmofFMXi" +
+			"bZ5LUO/oK0iuNjBKfLdWoi+hpciKyPb9Bs8SO/svKSNqTEbn9ts3q6tpbngoECAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECGXQ07qiAqv2MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBADKtN3OOaRdte0X4xLC6nTGaK/u7IEKQ0DjduDHwJR5w27zefrx48Z" +
+			"dlq8t5lAfQJqWmfk7iCIW1QJPLcZOouWDP2S9Cb0YooGQRIEkMjpBn3Xufx0XUphtCDs3W" +
+			"9LAMVXqfuce1tpZ6Dvrh6/H2X8rJMU29Czsz949bh6tcsHJi";
+		public const string Intermediate_CRL_RL_02_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIZdDTuqICq/YwDQYJKoZIhvcNAQEFBQADgYEAxrDH" +
+			"zKno1mkJqPTub0c9To6jC3CGTilV1E12oD0kFjkXqL40+W251qQ2wMC+G7ZrzBIc5dRuJ9" +
+			"3feHZ7cc03/s3TziXDvSyfNOYpHzkPwT48HuSgBYgJ3uswwk+tDiA64NzbOJqssxxhFRok" +
+			"9OpwC8eQkzgpA3a6816v2I3XL9s=";
+		public const string End_Certificate_RL_02_01_crt =
+			"MIIChzCCAfCgAwIBAgICAK0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDIuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAyLjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCykRGcIKuxia47yRmJT8XpNNi2LTTbUUTteIBp" +
+			"DZBfz2ExeWLruO9Rn1/oB/EP+4apx4r9rQ2tGsvr/7qQYeQK8W7eJzZgvxFadY57IMfUNq" +
+			"1nEnj0ZvuWrOSf+K9v6FWX5Y2uyZS5Uvb1VVQv0Ev890+yXTtthPTjepk3JkkouwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECFIkVrx7NRAdMBMGA1UdIwQMMAqACGXQ07qiAqv2MA0GCSqGSIb3DQEBBQUAA4GBAI+B" +
+			"T6bFZruoeFHXsYVjkQ42jSdYB9JuQkG7JLKte5gGlhyR+jMlJBzxBgNIfvlmYSnbRFPbE8" +
+			"eqsGm90hJJoUuVMkm0i03H13uddlS494O6HhTGpaKcYwp3hbLhVcaY3wFTqTCuZk1T7Oxq" +
+			"ggTrCDYvNH+/ZpQuy6nB/FH3SAHS";
+		public readonly string[] TEST_64_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_02_01_crt,
+			Intermediate_CRL_RL_02_01_crl,
+			End_Certificate_RL_02_01_crt
+		};
+
+		/*
+		 *  test65
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_RL_03_01_crt =
+			"MIICljCCAf+gAwIBAgICAK4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsZG8wsV3Kuo+jtnKxLYGBuAqQwUh6Cs7ioDTNUFI" +
+			"UDDJ0lOP1HVTMBA7DEcyTCGvnQ02dEVVuCddBTQvG5RvW7G7cCEW37cS56/3yPsU1bD/cp" +
+			"3C1pPJpoun04va91Sxtgcmx7jnz69QPVrucu6aI1sZyeOlvzb8K7DceaAfR98CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECMNzJ3SpyOLxMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBABo7oKmQilgji3w1tGz1cMrWxZxqGJqOAKcHywli+oxFo2oxSfEuFS" +
+			"tN2aEd2Ja5HU5a0ySztvByXF1TTNurGez7ARxmcS2kpoQtQXTloywza4A5N7iQwk0yyo/E" +
+			"J4lrXUfVRwZHr7FwA7qMODtFb0+Zivv9JLaq19GhnRhzZyWp";
+		public const string Intermediate_Certificate_2_RL_03_01_crt =
+			"MIICljCCAf+gAwIBAgICAK8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wMy4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAt7yNq1QZsV3p7OR8rgPuY7x7Bvs+nPhcLR7zFOgR" +
+			"+plQUwpWQ2PhuzReVV4jNasKtNK9MIWoeV+eV3pEiso5obb9+Byvha1F6gkYNZMPs9Iv86" +
+			"cJSMtownNJVGVAL9FEpof1QKLp7kfn08EjkoGmGy85xy9uFytd2S8n5TlrBqcCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECAVwoCPFqMtqMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAL9GufFieduzBJaMtsXtKHMf64O/KAGLSh1YDXS+a7Ku+EFw+WteKU" +
+			"Ob6+c1m7VH9P711eATQoACotCdKusPECqeYDEmT9keqA4f7cP4VcvGwhvSVQJsPuB3LL3S" +
+			"LIILE4zhT+O9G+5v+mkG/pEDirRYk6ZkdM91bsUuzsX40uyn";
+		public const string Intermediate_CRL_RL_03_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1STC4wMy4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIBXCgI8Woy2owDQYJKoZIhvcNAQEFBQADgYEAkwyA" +
+			"I1rrz6tOmEpBHDzuJfqY2nbXCIXFN6dVuaKNZWHJ4ZNIc4/t29Wa5GgXYrVXyXRcXP/u5k" +
+			"NEhOX2/NwCm6vL8+tclYP5qPLrh/Dk4v3nvcTFLKCvclAbf4Il0zfMQx+RRnO5PPqPDu5i" +
+			"1tHHwOtA8Q+oO71lZEwPE+pX1Sc=";
+		public const string End_Certificate_RL_03_01_crt =
+			"MIIChzCCAfCgAwIBAgICALAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDPGLfi8/T5p63cbGE98mqO5VzkeI1r2/2TLgvY" +
+			"RpL1h8i+CVYKoX37yYwNXf+HkHhj1OXJSNrm7853ctmDf2h1fv3f1+qJLg4VRVzlEgErNq" +
+			"74OR7XLXV77kGOmhip2g5BF5VKeqAdj0pCo1E5ZFHpRPFq/0DDmSda6GKJ6Dl8hwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECOHM3uWxFmcrMBMGA1UdIwQMMAqACMNzJ3SpyOLxMA0GCSqGSIb3DQEBBQUAA4GBAFBu" +
+			"doX0TZK/yoUcrSkP8AtFiv5c7QvyEtigFZTT+lbW/g4RX/oJGNZCu78yAxCczl+Z6ft+0V" +
+			"wInwahjyyAgw4QXxtw3b9CfqvT7HH7hcQ6r9ZA/NA9XpzNtxKfmXjzCZWdfmLJrd8KCnU/" +
+			"utKRAObRBKiaTGa178SEWvtkoIXd";
+		public readonly string[] TEST_65_DATA = new string[]
+		{
+			Intermediate_Certificate_1_RL_03_01_crt,
+			Intermediate_Certificate_2_RL_03_01_crt,
+			Intermediate_CRL_RL_03_01_crl,
+			End_Certificate_RL_03_01_crt
+		};
+
+		/*
+		 *  test66
+		 *
+		 */
+
+		public const string Intermediate_Certificate_RL_03_02_crt =
+			"MIICljCCAf+gAwIBAgICALEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvoTuc2LYBOhziBe02f6F8l9MwX74O1lknBcJjGvq" +
+			"JcirQx/6hQgBQT4hz4RRXNy7DSBr3swEw4eDNSeyd6kvG0h9oI3+SVmVyPPVi5eKDL1roI" +
+			"OBzmfx1+Nn/CnwOf8VroKDutBBQ0gJ24IEjwp6er/8hEAVN/yIjIi/MTFeoRkCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECKtCUOlmMPu6MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAI9x8O/JgJuZV/s4OBUy3AvcW9QP3HWWBQSdxUdjSosT2schjn7wrR" +
+			"gttL7vWjT1djsbATAHa5C3inG+VjGIq/NqWaPoHAucRNMs4oZX2ACZFuBLOb/qhywsKh5+" +
+			"bjv4QgtqkUedzEratY6yQiJSiMSJVJSMzHosTVMX7oOp+cll";
+		public const string Intermediate_CRL_RL_03_02_crl =
+			"MIIBcDCB2gIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" +
+			"CyFw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgIzAhMAoGA1UdFAQDAgEBMBMGA1Ud" +
+			"IwQMMAqACKtCUOlmMPu6MA0GCSqGSIb3DQEBBQUAA4GBAAEZ0Hg6sKiVXIeK6zbQrKtMMz" +
+			"Vz2K68+SqN1LAjlNW6u+HSTlAvhRIFO1Hv5Zj7qbO226rLxas/X2XWXpMlm84NHN8T4dZU" +
+			"4Yo5rhhpCHckRxNYn3AFcfcV4ra1rrTtdx8e7e7/m0Ghog9Ny52ZuQThasL9caF0JxUx6d" +
+			"zbBHPm";
+		public const string End_Certificate_RL_03_02_crt =
+			"MIIChzCCAfCgAwIBAgICALIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAyMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNb6HGPRDulLMCCyCq6w2X8rHPtm1gN68JXFkX" +
+			"j/BZsHhu29Z9hXj76hO//7O775EPVMSLyRy8t15yzYpXfZRHFaGB5bs8U2R5ClvsD2FR0H" +
+			"t0JVfU6Ggn1lhO+jOiguJtXVRjofsfvHuiOe75ctaJ9lBpgwiV8tk4VRKz2e5xVwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECI3Gy0TgXMrwMBMGA1UdIwQMMAqACKtCUOlmMPu6MA0GCSqGSIb3DQEBBQUAA4GBAISQ" +
+			"Qh9+7D6nk3FL5YQOzyZ0BSHQYjpbIVykJ+Lr4jBPKyGgCqW6jqWNg7X4waB77J2z/OkavY" +
+			"A6qtpsk8r2wmG9thi8JyZZNhYMxAszHzFbBmSoxGRMvI0XarxgIu8Ky6V7jKVDLz12C3o9" +
+			"H0yd+nZXilCD+p9BTjjg5bGUogJS";
+		public readonly string[] TEST_66_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_03_02_crt,
+			Intermediate_CRL_RL_03_02_crl,
+			End_Certificate_RL_03_02_crt
+		};
+
+		/*
+		 *  test67
+		 *
+		 */
+
+		public const string Intermediate_Certificate_RL_03_03_crt =
+			"MIICljCCAf+gAwIBAgICALMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wMy4wMzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu/o0uxgTrAvNDrMNuG2eTla+AmkLVCIXBbsIo0gs" +
+			"tLm29tLwfBh/8l5OC0y6Xeh5lx+NLdelsiZGRNaaWmWHj9Ji5V6rclr8sXRDUjxe12zLeh" +
+			"0G+a0TfpL380cx9RItqQyA1ZRiUNymmJHnm13hwrf7LPirR9BMrtyTT2EI3cMCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECHYt39LYdEn0MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAIoSGa7MxnOuHoWM/BoJKsCeBmBHYCYDKmQ19JfsDHW8z8oAFiikFb" +
+			"Gtw1Qpc0GFfJgN0cppaXfe5lDS6BWL2dPorhu3URfXKu84ATLwGmNhqLDY7zh/zPvLtG2m" +
+			"izaMLC6ZwZL5KELpYpcP15EHPDquyP1xpV3fT17GjpG9IH8k";
+		public const string Intermediate_CRL_1_RL_03_03_crl =
+			"MIIBcDCB2gIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wMi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" +
+			"C0Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgIzAhMAoGA1UdFAQDAgEBMBMGA1Ud" +
+			"IwQMMAqACHYt39LYdEn0MA0GCSqGSIb3DQEBBQUAA4GBAI3HsXanos/N6uO3QVUaBZzmCt" +
+			"w1HCHMrLVG614YlUQiEedQ/oEc7dwCeD1rUbGNVkFPIRvMkmUQo1klhKAlEUmrtW+aH+If" +
+			"6oqumifqxvaycWidacbgNLIAMQtlQmniPF6Pq0dv8sNeKq4CE0gjRHOPJ2zIqy3kJ3tZYB" +
+			"pTguwO";
+		public const string Intermediate_CRL_2_RL_03_03_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wMy4wMxcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIdi3f0th0SfQwDQYJKoZIhvcNAQEFBQADgYEAXZSZ" +
+			"ySsD7U6ETy9ZRmiKUCJMUV9CIhCY0mEihHjW0DhFTyV1Hr01yN5zUr/IFVuP/Xcx36IX4l" +
+			"dVv6/MgR1GeM/BUGZhm4z6YwfAosZ1N3zayIy/pP3fa1rVRl8cgCxc/8qxg9nH9p6yPpxM" +
+			"AOOu6TLYquk/dA7wJPEW7MPixXY=";
+		public const string End_Certificate_RL_03_03_crt =
+			"MIIChzCCAfCgAwIBAgICALQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDMuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjAzLjAzMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC5LNxAB+lm514Hk2ykrFUb7fCX0ryIEMg0mgeT" +
+			"/z8Iw7xisht57koK4PTXY863aunfNNh+8oFTHZnoLB5dbkROj1nFRgcWPezzv1wNkZEpxn" +
+			"NINtTPBogW22NPznoZ/rSk9JRFe0sCOVazkW9tZbY2ARqyJsYU1ez5tQIkDS47kQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECMWddsi+qmxKMBMGA1UdIwQMMAqACHYt39LYdEn0MA0GCSqGSIb3DQEBBQUAA4GBAAv8" +
+			"nrJaqEycAyIKdPBYTUqaxjkv4SmonDDJG9OqvD78/o9hUKKteoMkNUp8eexTkWk0L72L4N" +
+			"/eXB30+m65E841V+Dy8L4bXh15n4qz4cyMt8Kvm7nbCqcgpiyBJmBxzfaXDLSthlmhcJ4X" +
+			"zDFnav1LEw5fZklt7cnMl4YvLD8d";
+		public readonly string[] TEST_67_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_03_03_crt,
+			Intermediate_CRL_1_RL_03_03_crl,
+			Intermediate_CRL_2_RL_03_03_crl,
+			End_Certificate_RL_03_03_crt
+		};
+
+		/*
+		 *  test68
+		 *
+		 */
+
+		public const string Intermediate_Certificate_1_RL_05_01_crt =
+			"MIICljCCAf+gAwIBAgICALUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNS4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA59vHTe5A9AcT237mW7HdSfh8Pu4P2wJNLT7RXczN" +
+			"7DD/P6mAkugSgPTXwwlE1oSB/hCxAtEPhwONYZFYlRClFJidHDdVApalB7UbosTghsUzAg" +
+			"Lqw7NL+w9i3Un2G7JM2oWwugozQn/1hzr2Cii2TIB6K0RWKoPBJvaWUURS/G8CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECP55Cc4eBca8MBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBALX594y5uF4Rt7CoRHeKZ5h8QiG7mc+kQDMjaSU4KJwNVVL0mJatQG" +
+			"w90yFfhvprlgDt9UIAvpF6z5gysbrjHXJaEhVlXeg9D5mcxsL4THEc8f6oU1GjfT/SOD9l" +
+			"QrT/keX3D9lcFEaTOgi0HIZ7aFIJgoWjXF/9kNNMEAs8sJNI";
+		public const string Intermediate_Certificate_2_RL_05_01_crt =
+			"MIICljCCAf+gAwIBAgICALYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDUuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wNS4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAtl4hX6HlF0M+lSBTG8jHiB06hOy87LL81yAE2JQt" +
+			"/6F+LZjuOBTCIc2yO2bVM3XzUnjyYDBYGnBFp/7XpRoiADuPJSfmkzmezpyJc+hm96UR1g" +
+			"Bpo+pPKbRTWuM+FYy+vPtaDk5wKOrmyNx440PwbzxTN3JeWz17xeYE98bXMc0CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECJOjtwEYV9VSMBMGA1UdIwQMMAqACP55Cc4eBca8MA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAFbkOffoIjWSfxEuKszoK7Fj27Hf5jlV92xqXtBLURjNGi9jCLUIUd" +
+			"QLnONZLJYo70Z6XaGjpAK1EtZKVWsz11JDq5egE1zNES//9Tz8xDtJ7Lcq0mwneVFxmBuL" +
+			"gxkw4GKbBFKz10FoSP7VJWaeW080WwKnp96Me5GtZRe260N1";
+		public const string Intermediate_CRL_1_RL_05_01_crl =
+			"MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjA4MDYCAg" +
+			"C2Fw05OTAxMDExMjAwMDBaMCEwCgYDVR0VBAMKAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQCg" +
+			"IzAhMAoGA1UdFAQDAgEBMBMGA1UdIwQMMAqACP55Cc4eBca8MA0GCSqGSIb3DQEBBQUAA4" +
+			"GBAIdOaBfpAEKWLrSvepVjk3UTfEfsSP6y+kFMl33YXy18xUvVpLarGu6YjQIpXiL+ulkP" +
+			"eF8TAc9AarUjvDf0kcslIOt3NhdMxR4/F614Ds/rPEXs4c7n4kCkvAlFg/19iIFeCaynx3" +
+			"X0s/v1SwzgAUHi3P+OwAGDApDTyKbnmzvt";
+		public const string Intermediate_CRL_2_RL_05_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1STC4wNS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIk6O3ARhX1VIwDQYJKoZIhvcNAQEFBQADgYEAfOOd" +
+			"JiLUCFSurAafQEBfxE9KVrgFC+W9m64cmERicO1QL9aDVIDGJAIY1pdvWVdhLBIKwSugwB" +
+			"ZH3ToptY+VizvFN1gkKGL2OuvDsXPHn1+QgmqvxYFPmvwDcwuxZ/3zD1VeHgEIKo9ugRnW" +
+			"F8G2Ph6SWUxJCjJQpB7WIbydowI=";
+		public const string End_Certificate_RL_05_01_crt =
+			"MIIChzCCAfCgAwIBAgICALcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUkwuMDUuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA1LjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9NWkW/mia20c5gM3DpcTsBWTNC/d/Cob+OVrS" +
+			"lYytMjK4htO3MavavMZNTLAYFCXWhZ+Uo/uiAF0ddE4HaFI418eKJMSSbQyed0TG5Udw/t" +
+			"3dhYeLzLEmVc0r00q5v+CLINsCNQAKaPV71UvoHrE092zZjmtacuAetBS1Q2ufpwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECGNPOXdCLpZ3MBMGA1UdIwQMMAqACJOjtwEYV9VSMA0GCSqGSIb3DQEBBQUAA4GBALTo" +
+			"hfBEPdzZ6A9QNStakOhmhHYox70xOPuWqzSbIugZv4chKXNQGiUAoOGImTw1mcun/uPNtd" +
+			"0bT+O+a9yX5gzW55CSmR/teHkTkND1mJhOMuYOmaCaBHnqgIIe1iEhMZQgag70+/tSmmQm" +
+			"UpWGpxeK2c02tBK6gEmnqk75bKRT";
+		public readonly string[] TEST_68_DATA = new string[]
+		{
+			Intermediate_Certificate_1_RL_05_01_crt,
+			Intermediate_Certificate_2_RL_05_01_crt,
+			Intermediate_CRL_1_RL_05_01_crl,
+			Intermediate_CRL_2_RL_05_01_crl,
+			End_Certificate_RL_05_01_crt
+		};
+
+		/*
+		 *  test69
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_05_02_crt =
+			"MIICljCCAf+gAwIBAgICALgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNS4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAouNcO1wHvKHPR15L7Fohr/QbTkPWGr9QYp2MXEDy" +
+			"BRGHt63Ob+yNvsP/C74GJA+PzvcRELSnJxmBVbdRN5y/u4S6Zt4yTTcrvp4vl//luoGLOX" +
+			"NHhCXbrGavyoP/iKpbfP7fy948AN34i95HuZENoGPjG5stX0uk12P087S2tPcCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECFi86MGPmMsXMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAFVZVMZEsaVuL0qX5Ls94+x8gBklxPfxgfG5LeBR2/YcqW+7BhsVA1" +
+			"GQhjBtwqCU9SOL16oTrqgw2+YeWBjaYuNYVlxfdifd0pQydpE1iDQWxmoKLzSDmtWgRYhz" +
+			"v0TB6j8q+0x5Q0OOrHX0jdIiBnHrLmReCK8dY1x6fb6I0tTH";
+		public const string Intermediate_CRL_RL_05_02_crl =
+			"MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNS4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjA4MDYCAg" +
+			"C5Fw05OTAxMDExMjAwMDBaMCEwCgYDVR0VBAMKAQEwEwYJYIZIAWUCAQwCAQH/BAMCAQCg" +
+			"IzAhMAoGA1UdFAQDAgEBMBMGA1UdIwQMMAqACFi86MGPmMsXMA0GCSqGSIb3DQEBBQUAA4" +
+			"GBAFMN6PWjz2bA1RRySYNXde2rKiYkZYghbtT4ig2yDJBKOiPnjdx+jriFJxGYpt7BvcNx" +
+			"cDfijmDZ1clzprIvz0lFO6IwsQiWtLxOz4Doj6K2AD+7IxuGLceaXmubvi4e6VVC3xXGsu" +
+			"OYsNgFzsdUXIazi74+eOcj4dqrHAepbhXT";
+		public const string End_Certificate_RL_05_02_crt =
+			"MIIChzCCAfCgAwIBAgICALkwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDUuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA1LjAyMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuWE1aFx3Zjk6gM0Wy6ijcUegbiGvhjBgqIGwv" +
+			"YissT0v3KGAKoh5wGeKC+rePQNbZ91j4XDLvUNUdNw8HVNdNG/igIwsuaJ9teKSbqrAw9X" +
+			"aD2YjJz/I6X6WXFd/eQ+g9lY3eidOXJkglYSwWMxUV62RUZbGyqjR1so+XpmYxCQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECLLbuNyVkkK9MBMGA1UdIwQMMAqACFi86MGPmMsXMA0GCSqGSIb3DQEBBQUAA4GBACKt" +
+			"GgxIRXYHZGZgwYHjNzquM1pUJTbxxm3qYA4U6r44oAo1UzQTDpHOalflreGFvG05l1BCnQ" +
+			"olQ8rcXU25v/CDfyww7cl8l7IxjYz7PNht7R97vjfMVqqButbn+BmU6D5kR9YXDCDPzaQ5" +
+			"DrKNk+3tIjJNj6YhxhqC2tPG9RIN";
+		public readonly string[] TEST_69_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_05_02_crt,
+			Intermediate_CRL_RL_05_02_crl,
+			End_Certificate_RL_05_02_crt
+		};
+
+		/*
+		 *  test70
+		 *
+		 */
+		public const string Intermediate_Certificate_1_RL_06_01_crt =
+			"MIICljCCAf+gAwIBAgICALowDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNi4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAmhxr4ckU5C3E57odZjgcxl46ZF2QVy+K86YoLOGT" +
+			"mq34NSHTFxP93mrNqMYdFKFedUTNI68HkecFVvVKoXsDNBnhyyCTQ3xXhBcMUXFByB+55k" +
+			"W5LeQ8l1G2ugsyZ7Z+P8uylrpeGJt4RjOTilhcI2mnfZ7S+arFGe4KYgnsaFUCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECOS4X3XqhyJYMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBALCPtNwXGxVSUNGErkBHSYCHyqlA55jKQQvZ4P0PznWEQ/gBJx34hq" +
+			"LxiBO2G+iDomzHszeM77TXkQBpNxCUw26Jxv2HuvyBXuSprgjw5F1tvLqwsBAnD5vsb0uD" +
+			"NrkKIzJSIBFQ1SRhuCObaXnamfPJHBmkP25t4QqEvoXMtVHB";
+		public const string Intermediate_Certificate_2_RL_06_01_crt =
+			"MIICljCCAf+gAwIBAgICALswDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDYuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMi1STC4wNi4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA2IKrW6HDZJVFw3e4cC7v/jPGXAexI4B88707NhAc" +
+			"qxSVfGTPJBdfWo5pkptZKN5/L5n6+rixLItHnei/uwBCHvhwzeEIGo1yVCgz6R2MoNB966" +
+			"Q5CHWfT43BUjp0rZLJkK4hVKNyXB78NVv2Fly+XWBDEnzQvgVPWbGOvzE3zh0CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECK/1z9Xbu2jGMBMGA1UdIwQMMAqACOS4X3XqhyJYMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAAa/MVC+8ozm9py40a4o/kHbkkmFNQr4s9yi3KXXuVxsNvquFMXm4a" +
+			"gC8GPoNjvV+RPRmU8wOM6I2/PPl2JEQRb7NDM8LkY/m/Au4GHVeln6FKlldiRm0A+YIr19" +
+			"ip2RHOldikAjUUYv7JT3SP34sjtq2e8bsXfWEPG5BA/wxtm7";
+		public const string Intermediate_CRL_1_RL_06_01_crl =
+			"MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" +
+			"C7Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgODA2MAoGA1UdFAQDAgEBMBMGCWCG" +
+			"SAFlAgEMAgEB/wQDAgEAMBMGA1UdIwQMMAqACOS4X3XqhyJYMA0GCSqGSIb3DQEBBQUAA4" +
+			"GBAJSexboWDaqLVY6iiWt8ZX5GwuNwDBN1R2TgM95H7JqjMgoWML887dKk24p4eKACFMWI" +
+			"Ji9nwsqdZ/h1FtPhYpSoJ8l8vo4imMKr+tTnMngDNpMMZPQyRY1AK1jSrLhEtUdjiEtrTY" +
+			"rG56RNt4YyUtNxxfkEymvwJxmO/4YcAz/l";
+		public const string Intermediate_CRL_2_RL_06_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMi1STC4wNi4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIr/XP1du7aMYwDQYJKoZIhvcNAQEFBQADgYEAImRg" +
+			"n9A7px9exOJL4Se9jsSHzZ3sAd3y16LdAb+HLtYLl1swNB4KPE+OebtzEoYiSzVVwezdlm" +
+			"5WseZjfbd0q01srZI4FeACZe99iBSpKymdKxw2gRvfYZ8ZMwFpK2mQq9cmygFn53iOwP7j" +
+			"3KE+lllielu7sYyEnkliF9wsaG0=";
+		public const string End_Certificate_RL_06_01_crt =
+			"MIIChzCCAfCgAwIBAgICALwwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTItUkwuMDYuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA2LjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDZVBNzD7LZW6mC2GSbVPjpcJ7sWISYsL2eHqXb" +
+			"/PuxtbOneOjYqx0GeL9pxDGSSNl2NrlG0G1HTU2MaEOVA6h96W9e5ADV/pzGPMr97z+3BV" +
+			"unxLX+ciM3T7rUQm/LueQTEC2Ww19T6QOg2i8rEadYT0OoW6OcvyuomemspxgClQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECK5pHDrhL7xjMBMGA1UdIwQMMAqACK/1z9Xbu2jGMA0GCSqGSIb3DQEBBQUAA4GBAF3J" +
+			"Kskjs4jp+BBoei9YWYtmOupn9w3oGyhknNh2jz7api5Gtgk2SyKfYFvN6EhWZJEab0hPFe" +
+			"WuYwO7zNCLGHw0cFXT/R48ogd6JkH6xDwj4afZDkWVTu8oaVD4h1rTYS6WPRzizAozOzhi" +
+			"tmIo+MV/lCG8+jdVtFgeKycI8aX7";
+		public readonly string[] TEST_70_DATA = new string[]
+		{
+			Intermediate_Certificate_1_RL_06_01_crt,
+			Intermediate_Certificate_2_RL_06_01_crt,
+			Intermediate_CRL_1_RL_06_01_crl,
+			Intermediate_CRL_2_RL_06_01_crl,
+			End_Certificate_RL_06_01_crt
+		};
+
+		/*
+		 *  test71
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_06_02_crt =
+			"MIICljCCAf+gAwIBAgICAL0wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNi4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxMlJ0vbkMRGzuEDTDGuPmwDzU1xn3dFDZ1Tx6ONP" +
+			"fwNN5gk6r9kYl5TZ8f5TbkQSnOzyhDSqX8dGumCSgukETXtYBU2+KiIAtliu5NJRbXe3La" +
+			"vn102HxaHDLGsR0FFLiFM9GVhOOXryJoXoGZqUwvqbWyaQQEzrV4RWmuOv7xMCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECFNaMo88Vb5MMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAJsjJG4/U1OWCJPB1u7UD3TPKRgOR9hT5l3LzFw5s0CEGt2Beg25LP" +
+			"GEGcr0sEdosVQI5m5CuPolpmlQv0FkZv5M1W+uXX+F/6edtMDEquDpdR97ihQSLZjFFqjE" +
+			"ytuaD4gqtL/BKBbz3e93mOmR9Wi+kWlXOYl0j8wpU9ePSjDV";
+		public const string Intermediate_CRL_RL_06_02_crl =
+			"MIIBhTCB7wIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNi4wMhcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWjAjMCECAg" +
+			"C+Fw05OTAxMDExMjAwMDBaMAwwCgYDVR0VBAMKAQGgODA2MAoGA1UdFAQDAgEBMBMGCWCG" +
+			"SAFlAgEMAgEB/wQDAgEAMBMGA1UdIwQMMAqACFNaMo88Vb5MMA0GCSqGSIb3DQEBBQUAA4" +
+			"GBAAKNj5xmtE7wzO1p5igiAmCDV6KuYsiPAQPHPEBlmo85vzvWv2hpEtmk4nDhehogl0QX" +
+			"rhvRRqR+cPE5vBLB8mAStW+ZR6FXQPnmU5qGHqCQ4Wh6TWZesd7oyftoS7bJD5Xdf5ErA9" +
+			"qijWoz8FgxZHVnAFmjA0rUINkdQ5JfE5oj";
+		public const string End_Certificate_RL_06_02_crt =
+			"MIIChzCCAfCgAwIBAgICAL4wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDYuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA2LjAyMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD3UzwrnwKRlP00Pn49iI35S0wLn7c1I3rsmzdm" +
+			"YFicetxHNeOKXLg1CN1bqkbAJ+N39fKjrkusqb2T+R3zhAV5LeLT4fzbHYdU7f4r6xgW2/" +
+			"b2WLv+QVR+ldTsVxgPp/ZUgYi4/vAow4Q/6IT+zWtlawMBob/nLjVl+jQ9N4coFwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECPhq75noL+9WMBMGA1UdIwQMMAqACFNaMo88Vb5MMA0GCSqGSIb3DQEBBQUAA4GBAIU2" +
+			"5bLX/NyDC8dKUxRwVn8oc3YPQjK0zXGdUr15Ib+cLdRyFVCuAyxVdpTf/csuga6tDhGuTL" +
+			"B18mTE/fAjhUOiKiOLD6m4P77Nj67l2NTi86RimsI/Z6r5+bU31ahrls/7kr788+f4oEIY" +
+			"TyOJecojsJUOG3qzK9J50iszclxg";
+		public readonly string[] TEST_71_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_06_02_crt,
+			Intermediate_CRL_RL_06_02_crl,
+			End_Certificate_RL_06_02_crt
+		};
+
+		/*
+		 *  test72
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_07_01_crt =
+			"MIICljCCAf+gAwIBAgICAL8wDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAxjHxSRwJjEkLG9Al5uSQ22QI8N/hJ8hhkhh9qlaJ" +
+			"mHusM8sWpAp2vnuumlThTA2zZbptXZ8Krb7i/Kpym4wo3ZkEThwi/ijsM5QCunQJmESRGD" +
+			"yPZJjfhWjoC+lCjbmzsOGLMETpgSEMy+EyoXkRCnKmXcmCMS8HjLrqdnwiWBUCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECHPEkeIs8GuwMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBABCmgEnb8dfnG9lWQKT5BmQm459WqRQAiqdfqf9w0qRMuVrdfLMwqx" +
+			"oq4uh10A3d+auHohgT2fT9RzNaWnRoNaH9K6qLQsdCUZdqjbEGdyiIFzvWP9MkV9nhDlo2" +
+			"GgiU68HfnpKO/WA9EaRHyEzwT9o4SA7hAbz+3L12hB2WLSOg";
+		public const string Intermediate_CRL_RL_07_01_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNy4wMRcNOTgwMTAxMDYwMTAwWhcNOTgwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIc8SR4izwa7AwDQYJKoZIhvcNAQEFBQADgYEAOyZr" +
+			"f1tRnuzoq7dgQo+eOYhb5JyRyrNaSwNnRy82wOP+/G3NH8V3NGonDFOOcd9SoLTbeW4o71" +
+			"vdOrKZgom5H2MZK5M4wTdfPAfXB1wBxOMzW5jXzsRtaha4l6EPI+GVL0eXN+aW3k/pscdA" +
+			"ToI+OxTmRRnCYS6yW3qL9RoTIXQ=";
+		public const string End_Certificate_RL_07_01_crt =
+			"MIIChzCCAfCgAwIBAgICAMAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrm/Zem9Tt2UJFUKdAhTNwvhLo03uOax74ZgbV" +
+			"YNTCpKeEWkV5d5d7DRC4mCTX1yjIlg6K4l7T+sRGI4XAcDRgYLuoyG1X958XCXSdIPTdbK" +
+			"Hxs/tFv4mrCwi1kU+zjyzDoqgjT6kUxgM39rfcvDMH6qSzHQKgTFp7Tj/DHiELqwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECGFR8c6rRbhcMBMGA1UdIwQMMAqACHPEkeIs8GuwMA0GCSqGSIb3DQEBBQUAA4GBAANZ" +
+			"TVR288mKpDDzm9XZMZ9+K1kPZ+eQYX+vUul11luVw27AIJGR8Fb4PIGl4+ALvqU3NQP/6v" +
+			"d+zvS7IfiR6q7aLS3w111BUCgDhTJAp3oSo12qfcp+2DB1M9QfjrM9nKgmh5bBJigdJwJM" +
+			"W8HHKStUMLdxg+qkZJgZpnyowCFM";
+		public readonly string[] TEST_72_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_07_01_crt,
+			Intermediate_CRL_RL_07_01_crl,
+			End_Certificate_RL_07_01_crt
+		};
+
+		/*
+		 *  test73
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_07_02_crt =
+			"MIICljCCAf+gAwIBAgICAMEwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNNTAwMTAxMDYwMDMwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMjCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0CvEneaAPtxZOTqlh/TXBM6V0bQgKbO58yEyURcO" +
+			"Zi7jzYsmNtN9Tsr0wAlD41/ZONsW4MMzZ13UCc0aGa+eE8XRULBe5cgaGxJKwVnEqz3W8z" +
+			"v1MjOk7Anb8TkxMSlWlptC6V3eRA85p5Id9gXbIrP3E3NuSfyx6246oLjNnbECAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECIb5Ia6wKcHtMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAAYEHQY+Z4qv4bYLmd+sz4aNGwZF7FT6ZIQ43OSeb+t+ibL7rZ0X0y" +
+			"4SCTMs1mAB44IA6RFurmeCFk0ladRCn3A1xaVI1HlHen13ovzDA9ogL4CWbYXvCUv/znQY" +
+			"yVSQCTKwT8iVam8xS1MsNCe408iVjhRfR6u9Hi31M+Pf+AUe";
+		public const string Intermediate_CRL_RL_07_02_crl =
+			"MIIBSzCBtQIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNy4wMhcNNTAwMTAxMDYwMTAwWhcNNTAwMTAxMTIwMTAwWqAjMCEwCg" +
+			"YDVR0UBAMCAQEwEwYDVR0jBAwwCoAIhvkhrrApwe0wDQYJKoZIhvcNAQEFBQADgYEALVUq" +
+			"3Wq/Opvp9ifmQ4VXz4dgLNR+5Nz3muJ4RZt5R5b4R3RYllhgXNYw2EbEVCFjnfm97z73Ke" +
+			"wzVV+fo/u5GbqJHN2cAVEHarOpasLxySktNA1Cwq5OTzUF0dYISqYbyBvVcaOQBvU/Lwj7" +
+			"MQJJVVq96iDKnAJYBX03EHKbBeg=";
+		public const string End_Certificate_RL_07_02_crt =
+			"MIIChzCCAfCgAwIBAgICAMIwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDIwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAyMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD6YgsbjW9IL7/SBORKssFUZBUxmluOpxJK/7d7" +
+			"JA2pxbg7L96xHFPWN36CYDJzTscNpbGrD3G2MPkg4GqoTo0rU28NYVzj4SwqYoSLIbXB+r" +
+			"SVgWcxNgbJ+4x9bK3YccNLR1PWEFxz1NckhCLBmb5pI4E34MCxQ6PvFO02I19FwQIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECIutV9ItCIbZMBMGA1UdIwQMMAqACIb5Ia6wKcHtMA0GCSqGSIb3DQEBBQUAA4GBALQE" +
+			"cBr31h3jKUHcuf3yztr9NWUkGMDM0NCXHOpQl7JbV3P5BjvaiRYWlUrN7+92G8EaUFORto" +
+			"zp8GG+d/MvFooVQOvpOzyhautYWyqq3AWpZLppnxNk1mRAdjUAvJaONtv37eLsma0bhtLM" +
+			"j62sQQ6CdoKbMtIEGuJgpwWqHYwY";
+		public readonly string[] TEST_73_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_07_02_crt,
+			Intermediate_CRL_RL_07_02_crl,
+			End_Certificate_RL_07_02_crt
+		};
+
+		/*
+		 *  test74
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_07_03_crt =
+			"MIICljCCAf+gAwIBAgICAMMwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wNy4wMzCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEA8QzGjV0NVTNrOgkeqTkQFCOvl7M0qmjmYJjuw4R3" +
+			"YfQIXDN0m9HR2JKp5WKTSUedmWviGS7NbGSzLR7+6OkLwSoxN9PkA/fMko7O0KWBfduhvn" +
+			"jymlDMb2GPb1hBjScbq8fVJHwzqUm+BtEO2MXwXKYY2hZr+OEyEGhSEThp90MCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECFwl2XphEZRSMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAAb5GERgYVGuOb62gVZAAnhuk5K7CCkWZucOv6iI7pAgI6S7pvool/" +
+			"dXHC0tzgQ+/MkuWcr+22k/ya7f+iSfiYokjnQkgoYFYk3PkjyOXA3mzs5qhF0nOP6Gvmz4" +
+			"asONA+qZSqa4pjxF9Kn8L64f9yeyEXnckmbzdmbjAFCveQIP";
+		public const string Intermediate_CRL_RL_07_03_crl =
+			"MIIBTTCBtwIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wNy4wMxcNOTkwMTAxMDYwMTAwWhgPMjA1MDAxMDExMjAxMDBaoCMwIT" +
+			"AKBgNVHRQEAwIBATATBgNVHSMEDDAKgAhcJdl6YRGUUjANBgkqhkiG9w0BAQUFAAOBgQAz" +
+			"DMl8P16hylNkUEw4z9//PJFObNPZCYdmzBfp0K3tNRrOAouUVegyX0gDHi8O+bmmJNgcnC" +
+			"tMRXx+D4qP7bx5fDS2MVQhSsncf6u4UZ8pxbRc0JmwR5oGZLPQabrctgmEmg8ZKGApKtsf" +
+			"pGyvvTwaAzM+GaWXD68bBEN3VfVdeQ==";
+		public const string End_Certificate_RL_07_03_crt =
+			"MIIChzCCAfCgAwIBAgICAMQwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDcuMDMwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA3LjAzMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDU6mec24uBaVip7fFWHas+o/lpZBOfj/IPHXQ9" +
+			"QaRZwmJZBB81AX3BJ60DD12o/+RXdHl7B2Eh9kYv/QEXOKmyhJFSPa0Lv7MQ/hCIcL4m1U" +
+			"FDGtJ3SUixZMqVBP0xjwXoNS88zzaCBL+co2TxhBrYMzeNQOX1eEkXMT4pvULmAwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECBBgFdYLuvk9MBMGA1UdIwQMMAqACFwl2XphEZRSMA0GCSqGSIb3DQEBBQUAA4GBAAof" +
+			"dPOGa4ZxRPcLw6zWM/NLzF3XYDqXAsZBsC75r0GRrogqEYn07tVUDNaQczDtjRLBRNmxWE" +
+			"+qCkJwc+wOBJqOFUxcuhK9oag6OE94+UIHdh3Td9i2ELZXj9RSNchnjyFohj5gk1dJSO41" +
+			"86Ls3mCT9JcssR0dSxxkF0ENfZCG";
+		public readonly string[] TEST_74_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_07_03_crt,
+			Intermediate_CRL_RL_07_03_crl,
+			End_Certificate_RL_07_03_crt
+		};
+
+		/*
+		 *  test75
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_08_01_crt =
+			"MIICljCCAf+gAwIBAgICAMUwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wOC4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAs2YRTEl3C1TmmneJ6K110nSACn+KXxSOTGAGN5xv" +
+			"XW751StpE2iEQIbRVPQdMzmcQX0bcg/WpdrewPQld9NRjFj7it+9YNQh7vMKhZwoAPoDmv" +
+			"TnTdTEuV0c1FLVDVhiaAD9KMBa4fBLRfTKVzgzAr+oNqLhm3YBd2JWRHg+fA8CAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECB4we8+hIrkKMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBABTQI82uCMwQ4bgUWr9lawSI5DyWg3KY13F45rAlmKyckgne9SHbCH" +
+			"+Lvm3XkkIqKmeHfJ3QTf7bpz6eErn3CxRrGm5JWblcYbVT+smjboJ9A0BXifqINYLy3qGc" +
+			"AnNRkPq8OUREj2sU1qWKagUIgA/Vk2WyZhcUiApJPHI4fwv9";
+		public const string Intermediate_CRL_RL_08_01_crl =
+			"MIIBWjCBxAIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wOC4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqAyMDAwCg" +
+			"YDVR0UBAMCAQEwDQYDVR0bAQH/BAMCAQEwEwYDVR0jBAwwCoAIHjB7z6EiuQowDQYJKoZI" +
+			"hvcNAQEFBQADgYEAkjF0oERt5XW2i70gyspkEYIHyGCHnqngky5yuwQSRrlW7t0vGdKV7W" +
+			"50evTeSVV41uhi1MBcccpx1MdRcB5vsatFSSKcKx4NF3PuHXxXCm2HkfXQy4K5zftE3jOZ" +
+			"5s+yTHiw3s/QSErtHRca+TQcEZwamI+p402TEa6e82l6xHI=";
+		public const string End_Certificate_RL_08_01_crt =
+			"MIIChzCCAfCgAwIBAgICAMYwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDguMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA4LjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfEMqWMqk3Rre5m4ILtQIz45JImvU379Al/S6t" +
+			"2y/TzimJc4nhIKQp80VaZA/gwu/DcvMgJPM+FFz5U5rRkDaYASsc34tZUESF5LC6ZbtGqf" +
+			"J96IKdajvkGLsHyI7dseuwaQ0FlOwcmKMSR898MGNNbKxaQNLEXsIFypRDsN6JhwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECMT22ARjB1ABMBMGA1UdIwQMMAqACB4we8+hIrkKMA0GCSqGSIb3DQEBBQUAA4GBAIaP" +
+			"EqI7oHl/+h3MszG4VB1Va9NTN0kaysTyjQSVBi9jhOlPkzuXc2wI1bymBhatHEn6OrgP13" +
+			"vsOiH2BiyudYcYjKpwI4FUiyKLIc0CXzM0VYFoMzb91QtsK1EnvAPDKNYVVFXrL7ABVIK4" +
+			"hU6HfMMUbnpKWBxT5274iHScX8tL";
+		public readonly string[] TEST_75_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_08_01_crt,
+			Intermediate_CRL_RL_08_01_crl,
+			End_Certificate_RL_08_01_crt
+		};
+
+		/*
+		 *  test76
+		 *
+		 */
+		public const string Intermediate_Certificate_RL_09_01_crt =
+			"MIICljCCAf+gAwIBAgICAMcwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9EMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxUcnVzdCBBbmNob3IwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNVBAMTDENBMS1STC4wOS4wMTCBnzANBg" +
+			"kqhkiG9w0BAQEFAAOBjQAwgYkCgYEAsvkvLv5fMFYvohaXO8a7GgU4rDHe9iL7LP1VeNUg" +
+			"GIdJGqPEnuggQ/guhrBHafGh1NtmlEbmPJ4WQ99dBbPHHeO8sfCgkmWC0SqPODoI+t3qJE" +
+			"kf2z9dWoAij15RXPliywZz+S6bTtcEQAREyBQ6M8/HJ83wRXp/uCpdPOSxVPkCAwEAAaNj" +
+			"MGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwFgYDVR0gBA8wDTALBglghk" +
+			"gBZQMBMAEwEQYDVR0OBAoECISY4bvGMEBTMBMGA1UdIwQMMAqACKua6/nC51SPMA0GCSqG" +
+			"SIb3DQEBBQUAA4GBAAd7g+dWso4V/Vr+QIoNLueCBAYWdOF+Yz3VeomcsDAs2V8E+xcZaq" +
+			"jo2LrMygYCeMxVfXx/ZdhLPOaZ+ahNAbk+nWRwj35JdTNAAbMMWFdZUgR6N+uzx1v7i86p" +
+			"AWUpRJ9IYPgUoQ5pmjdf3Ru1nrLfRt4yp+kNHWp6IL/+MwcM";
+		public const string Intermediate_CRL_RL_09_01_crl =
+			"MIIBXDCBxgIBATANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS" +
+			"5TLiBHb3Zlcm5tZW50MQwwCgYDVQQLEwNEb2QxEDAOBgNVBAsTB1Rlc3RpbmcxFTATBgNV" +
+			"BAMTDENBMS1STC4wOS4wMRcNOTkwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMTAwWqA0MDIwCg" +
+			"YDVR0UBAMCAQEwDwYDVR0cAQH/BAUwA4IB/zATBgNVHSMEDDAKgAiEmOG7xjBAUzANBgkq" +
+			"hkiG9w0BAQUFAAOBgQAKTXYgqlP+upFIwOSpdaVKDT8aqFzY9nSIsxHg5Wdl43U7p44LvQ" +
+			"lW8XKhw74oQl1ExU5s7mDaEqB0JIozGzmoNyKsErgWKNW+lpKSxR5+1EHOB6Oo2KijpTsv" +
+			"GFrHFCnF09f9JaTaMRIXOljx3rMO1UZsftKy/L9z3aUz8hQRnQ==";
+		public const string End_Certificate_RL_09_01_crt =
+			"MIIChzCCAfCgAwIBAgICAMgwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxGDAWBg" +
+			"NVBAoTD1UuUy4gR292ZXJubWVudDEMMAoGA1UECxMDRG9kMRAwDgYDVQQLEwdUZXN0aW5n" +
+			"MRUwEwYDVQQDEwxDQTEtUkwuMDkuMDEwHhcNOTgwMTAxMTIwMTAwWhcNNDgwMTAxMTIwMT" +
+			"AwWjBgMQswCQYDVQQGEwJVUzEYMBYGA1UEChMPVS5TLiBHb3Zlcm5tZW50MQwwCgYDVQQL" +
+			"EwNEb0QxEDAOBgNVBAsTB1Rlc3RpbmcxFzAVBgNVBAMTDlVzZXIxLVJMLjA5LjAxMIGfMA" +
+			"0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDpz09VCXzAhH4/ifMk0RAzaBqJCXaHHqAdO/TW" +
+			"6uvOVtl+fGvWXhXmSSCUfzg5xBqdUXrqcyxOME3vdgF1uOFZ4q2K6+Zuxmm+GCOCIpe+Gl" +
+			"Jzqz4WKXG0iaXXQOYa56itNc/6Z6D/aAjNJavI19w0lmb9l6U2WBfn3LywxHp4dwIDAQAB" +
+			"o1IwUDAOBgNVHQ8BAf8EBAMCBeAwFgYDVR0gBA8wDTALBglghkgBZQMBMAEwEQYDVR0OBA" +
+			"oECOri1JgnJfLjMBMGA1UdIwQMMAqACISY4bvGMEBTMA0GCSqGSIb3DQEBBQUAA4GBADmV" +
+			"Ee0xy25Z0HtmWwprKPjJDr/p7TgzbmNC58pUPkgtxnJFP4yrzNB9FQBWSfnjZpzQkLSU7i" +
+			"7O6cf5HkqjQqoPErDnJLWgGzjbF80v2IIyZk7rEpAAM4MwjIk7hFvJK8QkTht9F4N1zj2X" +
+			"0TQkmlbo9Z4SFj/3fsbl9h2GdKuU";
+
+		public readonly string[] TEST_76_DATA = new string[]
+		{
+			Intermediate_Certificate_RL_09_01_crt,
+			Intermediate_CRL_RL_09_01_crl,
+			End_Certificate_RL_09_01_crt
+		};
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NistCertPathTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/NoekeonTest.cs b/BouncyCastle.AxCrypt/test/src/test/NoekeonTest.cs
new file mode 100644
index 0000000..c3745da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/NoekeonTest.cs
@@ -0,0 +1,157 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Tests
+{
+	/**
+	* basic test class for SEED
+	*/
+	[TestFixture]
+	public class NoekeonTest
+		: BaseBlockCipherTest
+	{
+		private static readonly string[] cipherTests =
+		{
+			"128",
+			"b1656851699e29fa24b70148503d2dfc",
+			"2a78421b87c7d0924f26113f1d1349b2",
+			"e2f687e07b75660ffc372233bc47532c"
+		};
+
+		public NoekeonTest()
+			: base("Noekeon")
+		{
+		}
+
+		public void DoTest(
+			int		strength,
+			byte[]	keyBytes,
+			byte[]	input,
+			byte[]	output)
+		{
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("Noekeon", keyBytes);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("Noekeon/ECB/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("Noekeon/ECB/NoPadding");
+
+			try
+			{
+				outCipher.Init(true, key);
+			}
+			catch (Exception e)
+			{
+				Fail("Noekeon failed initialisation - " + e.Message, e);
+			}
+
+			try
+			{
+				inCipher.Init(false, key);
+			}
+			catch (Exception e)
+			{
+				Fail("Noekeoen failed initialisation - " + e.Message, e);
+			}
+
+			//
+			// encryption pass
+			//
+			MemoryStream bOut = new MemoryStream();
+
+			CipherStream cOut = new CipherStream(bOut, null, outCipher);
+
+			try
+			{
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					cOut.WriteByte(input[i]);
+				}
+				cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+				cOut.Close();
+			}
+			catch (IOException e)
+			{
+				Fail("Noekeon failed encryption - " + e.Message, e);
+			}
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("Noekeon failed encryption - expected "
+					+ Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			MemoryStream bIn = new MemoryStream(bytes, false);
+
+			CipherStream cIn = new CipherStream(bIn, inCipher, null);
+
+			try
+			{
+//				DataInputStream dIn = new DataInputStream(cIn);
+				BinaryReader dIn = new BinaryReader(cIn);
+
+				bytes = new byte[input.Length];
+
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+//					bytes[i] = (byte)dIn.read();
+					bytes[i] = dIn.ReadByte();
+				}
+				int remaining = bytes.Length - input.Length / 2;
+//				dIn.readFully(bytes, input.Length / 2, remaining);
+				byte[] extra = dIn.ReadBytes(remaining);
+				if (extra.Length < remaining)
+					throw new EndOfStreamException();
+				extra.CopyTo(bytes, input.Length / 2);
+			}
+			catch (Exception e)
+			{
+				Fail("Noekeon failed encryption - " + e.Message, e);
+			}
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("Noekeon failed decryption - expected "
+					+ Hex.ToHexString(input) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			for (int i = 0; i != cipherTests.Length; i += 4)
+			{
+				DoTest(int.Parse(cipherTests[i]),
+					Hex.Decode(cipherTests[i + 1]),
+					Hex.Decode(cipherTests[i + 2]),
+					Hex.Decode(cipherTests[i + 3]));
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new NoekeonTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PBETest.cs b/BouncyCastle.AxCrypt/test/src/test/PBETest.cs
new file mode 100644
index 0000000..ee61a02
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PBETest.cs
@@ -0,0 +1,527 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/**
+	* test out the various PBE modes, making sure the JCE implementations
+	* are compatible woth the light weight ones.
+	*/
+	[TestFixture]
+	public class PbeTest
+		: SimpleTest
+	{
+		private class OpenSslTest
+			: SimpleTest
+		{
+			private char[] password;
+			private string baseAlgorithm;
+			private string algorithm;
+			private int keySize;
+			private int ivSize;
+
+			public OpenSslTest(
+				string	baseAlgorithm,
+				string	algorithm,
+				int		keySize,
+				int		ivSize)
+			{
+				this.password = algorithm.ToCharArray();
+				this.baseAlgorithm = baseAlgorithm;
+				this.algorithm = algorithm;
+				this.keySize = keySize;
+				this.ivSize = ivSize;
+			}
+
+			public override string Name
+			{
+				get { return "OpenSSLPBE"; }
+			}
+
+			public override void PerformTest()
+			{
+				byte[] salt = new byte[16];
+				int iCount = 100;
+
+				for (int i = 0; i != salt.Length; i++)
+				{
+					salt[i] = (byte)i;
+				}
+
+				PbeParametersGenerator pGen = new OpenSslPbeParametersGenerator();
+
+				pGen.Init(
+					PbeParametersGenerator.Pkcs5PasswordToBytes(password),
+					salt,
+					iCount);
+
+				ParametersWithIV parameters = (ParametersWithIV)
+					pGen.GenerateDerivedParameters(baseAlgorithm, keySize, ivSize);
+
+				KeyParameter encKey = (KeyParameter) parameters.Parameters;
+
+				IBufferedCipher c;
+				if (baseAlgorithm.Equals("RC4"))
+				{
+					c = CipherUtilities.GetCipher(baseAlgorithm);
+
+					c.Init(true, encKey);
+				}
+				else
+				{
+					c = CipherUtilities.GetCipher(baseAlgorithm + "/CBC/PKCS7Padding");
+
+					c.Init(true, parameters);
+				}
+
+				byte[] enc = c.DoFinal(salt);
+
+				c = CipherUtilities.GetCipher(algorithm);
+
+//					PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount);
+//					SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm);
+//
+//					c.Init(false, fact.generateSecret(keySpec));
+
+				Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(
+					algorithm, salt, iCount);
+				ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+					algorithm, password, algParams);
+				c.Init(false, cipherParams);
+
+				byte[] dec = c.DoFinal(enc);
+
+				if (!AreEqual(salt, dec))
+				{
+					Fail("" + algorithm + "failed encryption/decryption test");
+				}
+			}
+		}
+
+		private class Pkcs12Test
+			: SimpleTest
+		{
+			private char[] password;
+			private string baseAlgorithm;
+			private string algorithm;
+			private IDigest digest;
+			private int keySize;
+			private int ivSize;
+
+			public Pkcs12Test(
+				string		baseAlgorithm,
+				string		algorithm,
+				IDigest		digest,
+				int			keySize,
+				int			ivSize)
+			{
+				this.password = algorithm.ToCharArray();
+				this.baseAlgorithm = baseAlgorithm;
+				this.algorithm = algorithm;
+				this.digest = digest;
+				this.keySize = keySize;
+				this.ivSize = ivSize;
+			}
+
+			public override string Name
+			{
+				get { return "PKCS12PBE"; }
+			}
+
+			public override void PerformTest()
+			{
+				int iCount = 100;
+				byte[] salt = DigestUtilities.DoFinal(digest);
+
+				PbeParametersGenerator pGen = new Pkcs12ParametersGenerator(digest);
+
+				pGen.Init(
+					PbeParametersGenerator.Pkcs12PasswordToBytes(password),
+					salt,
+					iCount);
+
+				ParametersWithIV parameters = (ParametersWithIV)
+					pGen.GenerateDerivedParameters(baseAlgorithm, keySize, ivSize);
+
+				KeyParameter encKey = (KeyParameter) parameters.Parameters;
+
+				IBufferedCipher c;
+				if (baseAlgorithm.Equals("RC4"))
+				{
+					c = CipherUtilities.GetCipher(baseAlgorithm);
+	                
+					c.Init(true, encKey);
+				}
+				else
+				{
+					c = CipherUtilities.GetCipher(baseAlgorithm + "/CBC/PKCS7Padding");
+	                
+					c.Init(true, parameters);
+				}
+
+				byte[] enc = c.DoFinal(salt);
+
+				c = CipherUtilities.GetCipher(algorithm);
+
+//					PBEKeySpec keySpec = new PBEKeySpec(password, salt, iCount);
+//					SecretKeyFactory fact = SecretKeyFactory.getInstance(algorithm);
+//
+//					c.Init(false, fact.generateSecret(keySpec));
+
+				Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(
+					algorithm, salt, iCount);
+				ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+					algorithm, password, algParams);
+				c.Init(false, cipherParams);
+
+				byte[] dec = c.DoFinal(enc);
+
+				if (!AreEqual(salt, dec))
+				{
+					Fail("" + algorithm + "failed encryption/decryption test");
+				}
+
+				// NB: We don't support retrieving parameters from cipher
+//				//
+//				// get the parameters
+//				//
+//				AlgorithmParameters param = c.getParameters();
+//				PBEParameterSpec spec = (PBEParameterSpec)param.getParameterSpec(PBEParameterSpec.class);
+//
+//				if (!AreEqual(salt, spec.getSalt()))
+//				{
+//					Fail("" + algorithm + "failed salt test");
+//				}
+//	            
+//				if (iCount != spec.getIterationCount())
+//				{
+//					Fail("" + algorithm + "failed count test");
+//				}
+
+	            // NB: This section just repeats earlier test passing 'param' separately
+//				//
+//				// try using parameters
+//				//
+//				keySpec = new PBEKeySpec(password);
+//	            
+//				c.Init(false, fact.generateSecret(keySpec), param);
+//	            
+//				dec = c.DoFinal(enc);
+//	            
+//				if (!AreEqual(salt, dec))
+//				{
+//					Fail("" + algorithm + "failed encryption/decryption test");
+//				}
+			}
+		}
+
+		private Pkcs12Test[] pkcs12Tests = {
+			new Pkcs12Test("DESede", "PBEWITHSHAAND3-KEYTRIPLEDES-CBC",  new Sha1Digest(),   192,  64),
+			new Pkcs12Test("DESede", "PBEWITHSHAAND2-KEYTRIPLEDES-CBC",  new Sha1Digest(),   128,  64),
+			new Pkcs12Test("RC4",    "PBEWITHSHAAND128BITRC4",           new Sha1Digest(),   128,   0),
+			new Pkcs12Test("RC4",    "PBEWITHSHAAND40BITRC4",            new Sha1Digest(),    40,   0),
+			new Pkcs12Test("RC2",    "PBEWITHSHAAND128BITRC2-CBC",       new Sha1Digest(),   128,  64),
+			new Pkcs12Test("RC2",    "PBEWITHSHAAND40BITRC2-CBC",        new Sha1Digest(),    40,  64),
+			new Pkcs12Test("AES",    "PBEWithSHA1And128BitAES-CBC-BC",   new Sha1Digest(),   128, 128),
+			new Pkcs12Test("AES",    "PBEWithSHA1And192BitAES-CBC-BC",   new Sha1Digest(),   192, 128),
+			new Pkcs12Test("AES",    "PBEWithSHA1And256BitAES-CBC-BC",   new Sha1Digest(),   256, 128),
+			new Pkcs12Test("AES",    "PBEWithSHA256And128BitAES-CBC-BC", new Sha256Digest(), 128, 128),
+			new Pkcs12Test("AES",    "PBEWithSHA256And192BitAES-CBC-BC", new Sha256Digest(), 192, 128),   
+			new Pkcs12Test("AES",    "PBEWithSHA256And256BitAES-CBC-BC", new Sha256Digest(), 256, 128)
+		};
+
+		private OpenSslTest[] openSSLTests = {
+			new OpenSslTest("AES", "PBEWITHMD5AND128BITAES-CBC-OPENSSL", 128, 128),
+			new OpenSslTest("AES", "PBEWITHMD5AND192BITAES-CBC-OPENSSL", 192, 128),
+			new OpenSslTest("AES", "PBEWITHMD5AND256BITAES-CBC-OPENSSL", 256, 128)
+		};
+
+		static byte[] message = Hex.Decode("4869205468657265");
+
+		private byte[] hMac1 = Hex.Decode("bcc42174ccb04f425d9a5c8c4a95d6fd7c372911");
+		private byte[] hMac2 = Hex.Decode("cb1d8bdb6aca9e3fa8980d6eb41ab28a7eb2cfd6");
+
+		// NB: These two makePbeCipher... methods are same in .NET
+		private IBufferedCipher makePbeCipherUsingParam(
+			string  algorithm,
+			bool	forEncryption,
+			char[]  password,
+			byte[]  salt,
+			int     iterationCount)
+		{
+//			PBEKeySpec pbeSpec = new PBEKeySpec(password);
+//			SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm);
+//			PBEParameterSpec defParams = new PBEParameterSpec(salt, iterationCount);
+
+			Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(
+				algorithm, salt, iterationCount);
+			ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+				algorithm, password, algParams);
+			
+			IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
+
+//			cipher.Init(forEncryption, keyFact.generateSecret(pbeSpec), defParams);
+			cipher.Init(forEncryption, cipherParams);
+
+			return cipher;
+		}
+
+		// NB: These two makePbeCipher... methods are same in .NET
+		private IBufferedCipher makePbeCipherWithoutParam(
+			string  algorithm,
+			bool	forEncryption,
+			char[]  password,
+			byte[]  salt,
+			int     iterationCount)
+		{
+//			PBEKeySpec pbeSpec = new PBEKeySpec(password, salt, iterationCount);
+//			SecretKeyFactory keyFact = SecretKeyFactory.getInstance(algorithm);
+
+			Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(
+				algorithm, salt, iterationCount);
+			ICipherParameters cipherParams = PbeUtilities.GenerateCipherParameters(
+				algorithm, password, algParams);
+			
+			IBufferedCipher cipher = CipherUtilities.GetCipher(algorithm);
+
+//			cipher.Init(forEncryption, keyFact.generateSecret(pbeSpec));
+			cipher.Init(forEncryption, cipherParams);
+
+			return cipher;
+		}
+
+		private void doTestPbeHMac(
+			string	hmacName,
+			byte[]	output)
+		{
+			ICipherParameters key = null;
+			byte[] outBytes;
+			IMac mac = null;
+
+			try
+			{
+//				SecretKeyFactory fact = SecretKeyFactory.getInstance(hmacName);
+//
+//				key = fact.generateSecret(new PBEKeySpec("hello".ToCharArray()));
+
+				Asn1Encodable algParams = PbeUtilities.GenerateAlgorithmParameters(
+					hmacName, new byte[20], 100);
+				key = PbeUtilities.GenerateCipherParameters(
+					hmacName, "hello".ToCharArray(), algParams);
+				mac = MacUtilities.GetMac(hmacName);
+			}
+			catch (Exception e)
+			{
+				Fail("Failed - exception " + e.ToString(), e);
+			}
+
+			try
+			{
+//				mac.Init(key, new PBEParameterSpec(new byte[20], 100));
+				mac.Init(key);
+			}
+			catch (Exception e)
+			{
+				Fail("Failed - exception " + e.ToString(), e);
+			}
+
+			mac.Reset();
+
+			mac.BlockUpdate(message, 0, message.Length);
+
+//			outBytes = mac.DoFinal();
+			outBytes = new byte[mac.GetMacSize()];
+			mac.DoFinal(outBytes, 0);
+
+			if (!AreEqual(outBytes, output))
+			{
+				Fail("Failed - expected "
+					+ Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			byte[] input = Hex.Decode("1234567890abcdefabcdef1234567890fedbca098765");
+
+			//
+			// DES
+			//
+			IBufferedCipher cEnc = CipherUtilities.GetCipher("DES/CBC/PKCS7Padding");
+
+			cEnc.Init(
+				true,
+				new ParametersWithIV(
+					new DesParameters(Hex.Decode("30e69252758e5346")),
+					Hex.Decode("7c1c1ab9c454a688")));
+
+			byte[] outBytes = cEnc.DoFinal(input);
+			char[] password = "password".ToCharArray();
+
+			IBufferedCipher cDec = makePbeCipherUsingParam(
+				"PBEWithSHA1AndDES",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			byte[] inBytes = cDec.DoFinal(outBytes);
+
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("DES failed");
+			}
+
+			cDec = makePbeCipherWithoutParam(
+				"PBEWithSHA1AndDES",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			inBytes = cDec.DoFinal(outBytes);
+
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("DES failed without param");
+			}
+
+			//
+			// DESede
+			//
+			cEnc = CipherUtilities.GetCipher("DESede/CBC/PKCS7Padding");
+
+			cEnc.Init(
+				true,
+				new ParametersWithIV(
+					new DesParameters(Hex.Decode("732f2d33c801732b7206756cbd44f9c1c103ddd97c7cbe8e")),
+					Hex.Decode("b07bf522c8d608b8")));
+
+			outBytes = cEnc.DoFinal(input);
+
+			cDec = makePbeCipherUsingParam(
+				"PBEWithSHAAnd3-KeyTripleDES-CBC",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			inBytes = cDec.DoFinal(outBytes);
+
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("DESede failed");
+			}
+
+			//
+			// 40Bit RC2
+			//
+			cEnc = CipherUtilities.GetCipher("RC2/CBC/PKCS7Padding");
+
+			cEnc.Init(
+				true,
+				new ParametersWithIV(
+					new RC2Parameters(Hex.Decode("732f2d33c8")),
+					Hex.Decode("b07bf522c8d608b8")));
+
+			outBytes = cEnc.DoFinal(input);
+
+			cDec = makePbeCipherUsingParam(
+				"PBEWithSHAAnd40BitRC2-CBC",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			inBytes = cDec.DoFinal(outBytes);
+
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("RC2 failed");
+			}
+
+			//
+			// 128bit RC4
+			//
+			cEnc = CipherUtilities.GetCipher("RC4");
+
+			cEnc.Init(
+				true,
+				ParameterUtilities.CreateKeyParameter("RC4", Hex.Decode("732f2d33c801732b7206756cbd44f9c1")));
+
+			outBytes = cEnc.DoFinal(input);
+
+			cDec = makePbeCipherUsingParam(
+				"PBEWithSHAAnd128BitRC4",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			inBytes = cDec.DoFinal(outBytes);
+
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("RC4 failed");
+			}
+
+			cDec = makePbeCipherWithoutParam(
+				"PBEWithSHAAnd128BitRC4",
+				false,
+				password,
+				Hex.Decode("7d60435f02e9e0ae"),
+				2048);
+
+			inBytes = cDec.DoFinal(outBytes);
+	        
+			if (!AreEqual(input, inBytes))
+			{
+				Fail("RC4 failed without param");
+			}
+
+			for (int i = 0; i != pkcs12Tests.Length; i++)
+			{
+				pkcs12Tests[i].PerformTest();
+			}
+
+			for (int i = 0; i != openSSLTests.Length; i++)
+			{
+				openSSLTests[i].PerformTest();
+			}
+
+			doTestPbeHMac("PBEWithHMacSHA1", hMac1);
+			doTestPbeHMac("PBEWithHMacRIPEMD160", hMac2);
+		}
+
+		public override string Name
+		{
+			get { return "PbeTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PbeTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PEMData.cs b/BouncyCastle.AxCrypt/test/src/test/PEMData.cs
new file mode 100644
index 0000000..ea783c8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PEMData.cs
@@ -0,0 +1,117 @@
+using System;
+
+namespace Org.BouncyCastle.Tests
+{
+	class PemData
+	{
+		internal static readonly string CERTIFICATE_1 =
+			"-----BEGIN X509 CERTIFICATE-----\r"
+			+ "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx\r"
+			+ "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY\r"
+			+ "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB\r"
+			+ "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ\r"
+			+ "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2\r"
+			+ "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW\r"
+			+ "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM\r"
+			+ "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l\r"
+			+ "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv\r"
+			+ "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re\r"
+			+ "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO\r"
+			+ "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE\r"
+			+ "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy\r"
+			+ "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0\r"
+			+ "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw\r"
+			+ "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL\r"
+			+ "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4\r"
+			+ "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF\r"
+			+ "5/8=\r"
+			+ "-----END X509 CERTIFICATE-----\r";
+
+		internal static readonly string CERTIFICATE_2 =
+			"-----BEGIN CERTIFICATE-----\n"
+			+ "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx\n"
+			+ "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY\n"
+			+ "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB\n"
+			+ "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ\n"
+			+ "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2\n"
+			+ "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW\n"
+			+ "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM\n"
+			+ "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l\n"
+			+ "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv\n"
+			+ "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re\n"
+			+ "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO\n"
+			+ "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE\n"
+			+ "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy\n"
+			+ "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0\n"
+			+ "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw\n"
+			+ "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL\n"
+			+ "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4\n"
+			+ "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF\n"
+			+ "5/8=\n"
+			+ "-----END CERTIFICATE-----\n";
+
+		internal static readonly string CRL_1 =
+			"-----BEGIN X509 CRL-----\r\n"
+			+ "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT\r\n"
+			+ "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy\r\n"
+			+ "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw\r\n"
+			+ "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw\r\n"
+			+ "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw\r\n"
+			+ "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw\r\n"
+			+ "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw\r\n"
+			+ "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw\r\n"
+			+ "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw\r\n"
+			+ "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw\r\n"
+			+ "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF\r\n"
+			+ "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ\r\n"
+			+ "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt\r\n"
+			+ "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v\r\n"
+			+ "-----END X509 CRL-----\r\n";
+
+		internal static readonly string CRL_2 =
+			"-----BEGIN CRL-----\r\n"
+			+ "MIICjTCCAfowDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMxIDAeBgNVBAoT\r\n"
+			+ "F1JTQSBEYXRhIFNlY3VyaXR5LCBJbmMuMS4wLAYDVQQLEyVTZWN1cmUgU2VydmVy\r\n"
+			+ "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5Fw05NTA1MDIwMjEyMjZaFw05NTA2MDEw\r\n"
+			+ "MDAxNDlaMIIBaDAWAgUCQQAABBcNOTUwMjAxMTcyNDI2WjAWAgUCQQAACRcNOTUw\r\n"
+			+ "MjEwMDIxNjM5WjAWAgUCQQAADxcNOTUwMjI0MDAxMjQ5WjAWAgUCQQAADBcNOTUw\r\n"
+			+ "MjI1MDA0NjQ0WjAWAgUCQQAAGxcNOTUwMzEzMTg0MDQ5WjAWAgUCQQAAFhcNOTUw\r\n"
+			+ "MzE1MTkxNjU0WjAWAgUCQQAAGhcNOTUwMzE1MTk0MDQxWjAWAgUCQQAAHxcNOTUw\r\n"
+			+ "MzI0MTk0NDMzWjAWAgUCcgAABRcNOTUwMzI5MjAwNzExWjAWAgUCcgAAERcNOTUw\r\n"
+			+ "MzMwMDIzNDI2WjAWAgUCQQAAIBcNOTUwNDA3MDExMzIxWjAWAgUCcgAAHhcNOTUw\r\n"
+			+ "NDA4MDAwMjU5WjAWAgUCcgAAQRcNOTUwNDI4MTcxNzI0WjAWAgUCcgAAOBcNOTUw\r\n"
+			+ "NDI4MTcyNzIxWjAWAgUCcgAATBcNOTUwNTAyMDIxMjI2WjANBgkqhkiG9w0BAQIF\r\n"
+			+ "AAN+AHqOEJXSDejYy0UwxxrH/9+N2z5xu/if0J6qQmK92W0hW158wpJg+ovV3+wQ\r\n"
+			+ "wvIEPRL2rocL0tKfAsVq1IawSJzSNgxG0lrcla3MrJBnZ4GaZDu4FutZh72MR3Gt\r\n"
+			+ "JaAL3iTJHJD55kK2D/VoyY1djlsPuNh6AEgdVwFAyp0v\r\n"
+			+ "-----END CRL-----\r\n";
+
+		internal static readonly string ATTRIBUTE_CERTIFICATE_1 =
+			"-----BEGIN X509 ATTRIBUTE CERTIFICATE-----\r\n"
+			+ "MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl\r\n"
+			+ "IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy\r\n"
+			+ "aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV\r\n"
+			+ "BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv\r\n"
+			+ "dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw\r\n"
+			+ "MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV\r\n"
+			+ "MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI\r\n"
+			+ "NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7\r\n"
+			+ "eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G\r\n"
+			+ "odUBlSsJwPPQjZSU\r\n"
+			+ "-----END X509 ATTRIBUTE CERTIFICATE-----\r\n";
+
+		internal static readonly string ATTRIBUTE_CERTIFICATE_2 =
+			"-----BEGIN ATTRIBUTE CERTIFICATE-----\r\n"
+			+ "MIIBuDCCASECAQEwZ6BlMGCkXjBcMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhl\r\n"
+			+ "IExlZ2lvbiBvZiB0aGUgQm91bmN5IENhc3RsZTEjMCEGA1UECxMaQm91bmN5IFBy\r\n"
+			+ "aW1hcnkgQ2VydGlmaWNhdGUCARSgYjBgpF4wXDELMAkGA1UEBhMCQVUxKDAmBgNV\r\n"
+			+ "BAoTH1RoZSBMZWdpb24gb2YgdGhlIEJvdW5jeSBDYXN0bGUxIzAhBgNVBAsTGkJv\r\n"
+			+ "dW5jeSBQcmltYXJ5IENlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAAgEBMCIYDzIw\r\n"
+			+ "MDUwNjEwMDI0MTMzWhgPMjAwNTA2MTAwMjQzMTNaMBkwFwYDVRhIMRAwDoEMREFV\r\n"
+			+ "MTIzNDU2Nzg5MA0GCSqGSIb3DQEBBQUAA4GBALAYXT9zdxSR5zdPLAon1xIPehgI\r\n"
+			+ "NZhjM7w0uu3OdzSV5sC31X1Kx9vi5RIWiM9VimRTwbQIod9POttD5QMXCwQb/fm7\r\n"
+			+ "eiJqL2YBIXOeClB19VrQe8xQtMFbyuFpDiM7QdvIam9ShZZMEMGjv9QHI64M4b0G\r\n"
+			+ "odUBlSsJwPPQjZSU\r\n"
+			+ "-----END ATTRIBUTE CERTIFICATE-----\r\n";
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PKCS10CertRequestTest.cs b/BouncyCastle.AxCrypt/test/src/test/PKCS10CertRequestTest.cs
new file mode 100644
index 0000000..819439c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PKCS10CertRequestTest.cs
@@ -0,0 +1,470 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.CryptoPro;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Asn1.X9;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Tests
+{
+    [TestFixture]
+    public class Pkcs10CertRequestTest
+        : SimpleTest
+    {
+        private static readonly byte[] gost3410EC_A = Base64.Decode(
+              "MIIBOzCB6wIBADB/MQ0wCwYDVQQDEwR0ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBMdGQxHjAcBgNV"
+            +"BAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYDVQQGEwJydTEZ"
+            +"MBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiMBBgcqhQMCAh4B"
+            +"A0MABEBYx0P2D7YuuZo5HgdIAUKAXcLBDZ+4LYFgbKjrfStVfH59lc40BQ2FZ7M703hLpXK8GiBQ"
+            +"GEYpKaAuQZnMIpByoAAwCAYGKoUDAgIDA0EAgXMcTrhdOY2Er2tHOSAgnMezqrYxocZTWhxmW5Rl"
+            +"JY6lbXH5rndCn4swFzXU+YhgAsJv1wQBaoZEWRl5WV4/nA==");
+
+        private static readonly byte[] gost3410EC_B = Base64.Decode(
+              "MIIBPTCB7QIBADCBgDENMAsGA1UEAxMEdGVzdDEWMBQGA1UEChMNRGVtb3MgQ28gTHRkLjEeMBwG"
+            +"A1UECxMVQ3J5cHRvZ3JhcGh5IGRpdmlzaW9uMQ8wDQYDVQQHEwZNb3Njb3cxCzAJBgNVBAYTAnJ1"
+            +"MRkwFwYJKoZIhvcNAQkBFgpzZGJAZG9sLnJ1MGMwHAYGKoUDAgITMBIGByqFAwICIwIGByqFAwIC"
+            +"HgEDQwAEQI5SLoWT7dZVilbV9j5B/fyIDuDs6x4pjqNC2TtFYbpRHrk/Wc5g/mcHvD80tsm5o1C7"
+            +"7cizNzkvAVUM4VT4Dz6gADAIBgYqhQMCAgMDQQAoT5TwJ8o+bSrxckymyo3diwG7ZbSytX4sRiKy"
+            +"wXPWRS9LlBvPO2NqwpS2HUnxSU8rzfL9fJcybATf7Yt1OEVq");
+
+        private static readonly byte[] gost3410EC_C = Base64.Decode(
+              "MIIBRDCB9AIBADCBhzEVMBMGA1UEAxMMdGVzdCByZXF1ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBM"
+            +"dGQxHjAcBgNVBAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYD"
+            +"VQQGEwJydTEZMBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiMD"
+            +"BgcqhQMCAh4BA0MABEBcmGh7OmR4iqqj+ycYo1S1fS7r5PhisSQU2Ezuz8wmmmR2zeTZkdMYCOBa"
+            +"UTMNms0msW3wuYDho7nTDNscHTB5oAAwCAYGKoUDAgIDA0EAVoOMbfyo1Un4Ss7WQrUjHJoiaYW8"
+            +"Ime5LeGGU2iW3ieAv6es/FdMrwTKkqn5dhd3aL/itFg5oQbhyfXw5yw/QQ==");
+
+        private static readonly byte[] gost3410EC_ExA = Base64.Decode(
+              "MIIBOzCB6wIBADB/MQ0wCwYDVQQDEwR0ZXN0MRUwEwYDVQQKEwxEZW1vcyBDbyBMdGQxHjAcBgNV"
+            + "BAsTFUNyeXB0b2dyYXBoeSBkaXZpc2lvbjEPMA0GA1UEBxMGTW9zY293MQswCQYDVQQGEwJydTEZ"
+            + "MBcGCSqGSIb3DQEJARYKc2RiQGRvbC5ydTBjMBwGBiqFAwICEzASBgcqhQMCAiQABgcqhQMCAh4B"
+            + "A0MABEDkqNT/3f8NHj6EUiWnK4JbVZBh31bEpkwq9z3jf0u8ZndG56Vt+K1ZB6EpFxLT7hSIos0w"
+            + "weZ2YuTZ4w43OgodoAAwCAYGKoUDAgIDA0EASk/IUXWxoi6NtcUGVF23VRV1L3undB4sRZLp4Vho"
+            + "gQ7m3CMbZFfJ2cPu6QyarseXGYHmazoirH5lGjEo535c1g==");
+
+        private static readonly byte[] gost3410EC_ExB = Base64.Decode(
+              "MIIBPTCB7QIBADCBgDENMAsGA1UEAxMEdGVzdDEWMBQGA1UEChMNRGVtb3MgQ28gTHRkLjEeMBwG"
+            + "A1UECxMVQ3J5cHRvZ3JhcGh5IGRpdmlzaW9uMQ8wDQYDVQQHEwZNb3Njb3cxCzAJBgNVBAYTAnJ1"
+            + "MRkwFwYJKoZIhvcNAQkBFgpzZGJAZG9sLnJ1MGMwHAYGKoUDAgITMBIGByqFAwICJAEGByqFAwIC"
+            + "HgEDQwAEQMBWYUKPy/1Kxad9ChAmgoSWSYOQxRnXo7KEGLU5RNSXA4qMUvArWzvhav+EYUfTbWLh"
+            + "09nELDyHt2XQcvgQHnSgADAIBgYqhQMCAgMDQQAdaNhgH/ElHp64mbMaEo1tPCg9Q22McxpH8rCz"
+            + "E0QBpF4H5mSSQVGI5OAXHToetnNuh7gHHSynyCupYDEHTbkZ");
+
+        public override string Name
+        {
+            get { return "PKCS10CertRequest"; }
+        }
+
+        private void generationTest(
+            int		keySize,
+            string	keyName,
+            string	sigName)
+        {
+            IAsymmetricCipherKeyPairGenerator kpg = GeneratorUtilities.GetKeyPairGenerator(keyName);
+
+//			kpg.initialize(keySize);
+            kpg.Init(new KeyGenerationParameters(new SecureRandom(), keySize));
+
+            AsymmetricCipherKeyPair kp = kpg.GenerateKeyPair();
+
+            IDictionary attrs = new Hashtable();
+            attrs.Add(X509Name.C, "AU");
+            attrs.Add(X509Name.O, "The Legion of the Bouncy Castle");
+            attrs.Add(X509Name.L, "Melbourne");
+            attrs.Add(X509Name.ST, "Victoria");
+            attrs.Add(X509Name.EmailAddress, "feedback-crypto at bouncycastle.org");
+
+            IList order = new ArrayList();
+            order.Add(X509Name.C);
+            order.Add(X509Name.O);
+            order.Add(X509Name.L);
+            order.Add(X509Name.ST);
+            order.Add(X509Name.EmailAddress);
+
+            X509Name subject = new X509Name(order, attrs);
+
+            Pkcs10CertificationRequest req1 = new Pkcs10CertificationRequest(
+                sigName,
+                subject,
+                kp.Public,
+                null,
+                kp.Private);
+
+            byte[] bytes = req1.GetEncoded();
+
+            Pkcs10CertificationRequest req2 = new Pkcs10CertificationRequest(bytes);
+
+            if (!req2.Verify())
+            {
+                Fail(sigName + ": Failed Verify check.");
+            }
+
+            if (!req2.GetPublicKey().Equals(req1.GetPublicKey()))
+            {
+                Fail(keyName + ": Failed public key check.");
+            }
+        }
+
+        /*
+         * we generate a self signed certificate for the sake of testing - SHA224withECDSA
+         */
+        private void createECRequest(
+            string				algorithm,
+            DerObjectIdentifier	algOid)
+        {
+            FpCurve curve = new FpCurve(
+                new BigInteger("6864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151"), // q (or p)
+                new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", 16),   // a
+                new BigInteger("0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", 16));  // b
+
+            ECDomainParameters spec = new ECDomainParameters(
+                curve,
+//				curve.DecodePoint(Hex.Decode("02C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G
+                curve.DecodePoint(Hex.Decode("0200C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66")), // G
+                new BigInteger("01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", 16)); // n
+
+            ECPrivateKeyParameters privKey = new ECPrivateKeyParameters(
+                new BigInteger("5769183828869504557786041598510887460263120754767955773309066354712783118202294874205844512909370791582896372147797293913785865682804434049019366394746072023"), // d
+                spec);
+
+            ECPublicKeyParameters pubKey = new ECPublicKeyParameters(
+//				curve.DecodePoint(Hex.Decode("026BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q
+                curve.DecodePoint(Hex.Decode("02006BFDD2C9278B63C92D6624F151C9D7A822CC75BD983B17D25D74C26740380022D3D8FAF304781E416175EADF4ED6E2B47142D2454A7AC7801DD803CF44A4D1F0AC")), // Q
+                spec);
+
+//			//
+//			// set up the keys
+//			//
+//			AsymmetricKeyParameter privKey;
+//			AsymmetricKeyParameter pubKey;
+//
+//			KeyFactory fact = KeyFactory.getInstance("ECDSA");
+//
+//			privKey = fact.generatePrivate(privKeySpec);
+//			pubKey = fact.generatePublic(pubKeySpec);
+
+            Pkcs10CertificationRequest req = new Pkcs10CertificationRequest(
+                algorithm, new X509Name("CN=XXX"), pubKey, null, privKey);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC.");
+            }
+
+            req = new Pkcs10CertificationRequest(req.GetEncoded());
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC encoded.");
+            }
+
+            //
+            // try with point compression turned off
+            //
+//			((ECPointEncoder)pubKey).setPointFormat("UNCOMPRESSED");
+            ECPoint q = pubKey.Q.Normalize();
+            pubKey = new ECPublicKeyParameters(
+                pubKey.AlgorithmName,
+                q.Curve.CreatePoint(q.XCoord.ToBigInteger(), q.YCoord.ToBigInteger()),
+                pubKey.Parameters);
+
+            req = new Pkcs10CertificationRequest(
+                algorithm, new X509Name("CN=XXX"), pubKey, null, privKey);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC uncompressed.");
+            }
+
+            req = new Pkcs10CertificationRequest(req.GetEncoded());
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC uncompressed encoded.");
+            }
+
+            if (!req.SignatureAlgorithm.ObjectID.Equals(algOid))
+            {
+                Fail("ECDSA oid incorrect.");
+            }
+
+            if (req.SignatureAlgorithm.Parameters != null)
+            {
+                Fail("ECDSA parameters incorrect.");
+            }
+
+            ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+            sig.Init(false, pubKey);
+
+            byte[] b = req.GetCertificationRequestInfo().GetEncoded();
+            sig.BlockUpdate(b, 0, b.Length);
+
+            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            {
+                Fail("signature not mapped correctly.");
+            }
+        }
+
+        private void createECGostRequest()
+        {
+            string algorithm = "GOST3411withECGOST3410";
+            IAsymmetricCipherKeyPairGenerator ecGostKpg = GeneratorUtilities.GetKeyPairGenerator("ECGOST3410");
+
+            ecGostKpg.Init(
+                new ECKeyGenerationParameters(
+                    CryptoProObjectIdentifiers.GostR3410x2001CryptoProA,
+                    new SecureRandom()));
+
+            //
+            // set up the keys
+            //
+            AsymmetricCipherKeyPair pair = ecGostKpg.GenerateKeyPair();
+            AsymmetricKeyParameter privKey = pair.Private;
+            AsymmetricKeyParameter pubKey = pair.Public;
+
+            Pkcs10CertificationRequest req = new Pkcs10CertificationRequest(
+                algorithm, new X509Name("CN=XXX"), pubKey, null, privKey);
+
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC.");
+            }
+
+            req = new Pkcs10CertificationRequest(req.GetEncoded());
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC encoded.");
+            }
+
+            if (!req.SignatureAlgorithm.ObjectID.Equals(CryptoProObjectIdentifiers.GostR3411x94WithGostR3410x2001))
+            {
+                Fail("ECGOST oid incorrect.");
+            }
+
+            if (req.SignatureAlgorithm.Parameters != null)
+            {
+                Fail("ECGOST parameters incorrect.");
+            }
+
+            ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+            sig.Init(false, pubKey);
+
+            byte[] b = req.GetCertificationRequestInfo().GetEncoded();
+            sig.BlockUpdate(b, 0, b.Length);
+
+            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            {
+                Fail("signature not mapped correctly.");
+            }
+        }
+
+        private void createPssTest(
+            string algorithm)
+        {
+//			RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(
+            RsaKeyParameters pubKey = new RsaKeyParameters(false,
+                new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+                new BigInteger("010001",16));
+
+//			RSAPrivateCrtKeySpec privKeySpec = new RSAPrivateCrtKeySpec(
+            RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+                new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+                new BigInteger("010001",16),
+                new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+                new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+                new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+                new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+                new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+                new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+//			KeyFactory  fact = KeyFactory.getInstance("RSA", "BC");
+//
+//			PrivateKey privKey = fact.generatePrivate(privKeySpec);
+//			PublicKey pubKey = fact.generatePublic(pubKeySpec);
+
+            Pkcs10CertificationRequest req = new Pkcs10CertificationRequest(
+                algorithm, new X509Name("CN=XXX"), pubKey, null, privKey);
+
+            if (!req.Verify())
+            {
+                Fail("Failed verify check PSS.");
+            }
+
+            req = new Pkcs10CertificationRequest(req.GetEncoded());
+            if (!req.Verify())
+            {
+                Fail("Failed verify check PSS encoded.");
+            }
+
+            if (!req.SignatureAlgorithm.ObjectID.Equals(PkcsObjectIdentifiers.IdRsassaPss))
+            {
+                Fail("PSS oid incorrect.");
+            }
+
+            if (req.SignatureAlgorithm.Parameters == null)
+            {
+                Fail("PSS parameters incorrect.");
+            }
+
+            ISigner sig = SignerUtilities.GetSigner(algorithm);
+
+            sig.Init(false, pubKey);
+
+            byte[] encoded = req.GetCertificationRequestInfo().GetEncoded();
+            sig.BlockUpdate(encoded, 0, encoded.Length);
+
+            if (!sig.VerifySignature(req.Signature.GetBytes()))
+            {
+                Fail("signature not mapped correctly.");
+            }
+        }
+
+        // previous code found to cause a NullPointerException
+        private void nullPointerTest()
+        {
+            IAsymmetricCipherKeyPairGenerator keyGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+            keyGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
+
+            AsymmetricCipherKeyPair pair = keyGen.GenerateKeyPair();
+
+            IList oids = new ArrayList();
+            IList values = new ArrayList();
+            oids.Add(X509Extensions.BasicConstraints);
+            values.Add(new X509Extension(true, new DerOctetString(new BasicConstraints(true))));
+            oids.Add(X509Extensions.KeyUsage);
+            values.Add(new X509Extension(true, new DerOctetString(
+                new KeyUsage(KeyUsage.KeyCertSign | KeyUsage.CrlSign))));
+            SubjectKeyIdentifier subjectKeyIdentifier = new SubjectKeyIdentifierStructure(pair.Public);
+            X509Extension ski = new X509Extension(false, new DerOctetString(subjectKeyIdentifier));
+            oids.Add(X509Extensions.SubjectKeyIdentifier);
+            values.Add(ski);
+
+            AttributePkcs attribute = new AttributePkcs(PkcsObjectIdentifiers.Pkcs9AtExtensionRequest,
+                new DerSet(new X509Extensions(oids, values)));
+
+            Pkcs10CertificationRequest p1 = new Pkcs10CertificationRequest(
+                "SHA1WithRSA", new X509Name("cn=csr"), pair.Public, new DerSet(attribute), pair.Private);
+            Pkcs10CertificationRequest p2 = new Pkcs10CertificationRequest(
+                "SHA1WithRSA", new X509Name("cn=csr"), pair.Public, new DerSet(attribute), pair.Private);
+
+            if (!p1.Equals(p2))
+            {
+                Fail("cert request comparison failed");
+            }
+        }
+
+        public override void PerformTest()
+        {
+            generationTest(512, "RSA", "SHA1withRSA");
+            generationTest(512, "GOST3410", "GOST3411withGOST3410");
+
+            //		if (Security.getProvider("SunRsaSign") != null)
+            //        {
+            //            generationTest(512, "RSA", "SHA1withRSA", "SunRsaSign");
+            //        }
+
+            // elliptic curve GOST A parameter set
+            Pkcs10CertificationRequest req = new Pkcs10CertificationRequest(gost3410EC_A);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check gost3410EC_A.");
+            }
+
+            // elliptic curve GOST B parameter set
+            req = new Pkcs10CertificationRequest(gost3410EC_B);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check gost3410EC_B.");
+            }
+
+            // elliptic curve GOST C parameter set
+            req = new Pkcs10CertificationRequest(gost3410EC_C);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check gost3410EC_C.");
+            }
+
+            // elliptic curve GOST ExA parameter set
+            req = new Pkcs10CertificationRequest(gost3410EC_ExA);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check gost3410EC_ExA.");
+            }
+
+            // elliptic curve GOST ExB parameter set
+            req = new Pkcs10CertificationRequest(gost3410EC_ExB);
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check gost3410EC_ExA.");
+            }
+
+            // elliptic curve openSSL
+            IAsymmetricCipherKeyPairGenerator g = GeneratorUtilities.GetKeyPairGenerator("ECDSA");
+
+            ECCurve curve = new FpCurve(
+                new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+
+            ECDomainParameters ecSpec = new ECDomainParameters(
+                curve,
+                curve.DecodePoint(Hex.Decode("020ffa963cdca8816ccc33b8642bedf905c3d358573d3f27fbbd3b3cb9aaaf")), // G
+                new BigInteger("883423532389192164791648750360308884807550341691627752275345424702807307")); // n
+
+//			g.initialize(ecSpec, new SecureRandom());
+            g.Init(new ECKeyGenerationParameters(ecSpec, new SecureRandom()));
+
+            AsymmetricCipherKeyPair kp = g.GenerateKeyPair();
+
+            req = new Pkcs10CertificationRequest(
+                "ECDSAWITHSHA1", new X509Name("CN=XXX"), kp.Public, null, kp.Private);
+
+            if (!req.Verify())
+            {
+                Fail("Failed Verify check EC.");
+            }
+
+            createECRequest("SHA1withECDSA", X9ObjectIdentifiers.ECDsaWithSha1);
+            createECRequest("SHA224withECDSA", X9ObjectIdentifiers.ECDsaWithSha224);
+            createECRequest("SHA256withECDSA", X9ObjectIdentifiers.ECDsaWithSha256);
+            createECRequest("SHA384withECDSA", X9ObjectIdentifiers.ECDsaWithSha384);
+            createECRequest("SHA512withECDSA", X9ObjectIdentifiers.ECDsaWithSha512);
+
+            createECGostRequest();
+
+            // TODO The setting of parameters for MGF algorithms is not implemented
+//			createPssTest("SHA1withRSAandMGF1");
+//			createPssTest("SHA224withRSAandMGF1");
+//			createPssTest("SHA256withRSAandMGF1");
+//			createPssTest("SHA384withRSAandMGF1");
+
+            nullPointerTest();
+        }
+
+        public static void Main(
+            string[] args)
+        {
+            RunTest(new Pkcs10CertRequestTest());
+        }
+
+        [Test]
+        public void TestFunction()
+        {
+            string resultText = Perform().ToString();
+
+            Assert.AreEqual(Name + ": Okay", resultText);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PSSTest.cs b/BouncyCastle.AxCrypt/test/src/test/PSSTest.cs
new file mode 100644
index 0000000..677289e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PSSTest.cs
@@ -0,0 +1,253 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class PssTest
+		: SimpleTest
+	{
+		private class FixedRandom
+			: SecureRandom
+		{
+			private readonly byte[] vals;
+
+			public FixedRandom(
+				byte[] vals)
+			{
+				this.vals = vals;
+			}
+
+			public override void NextBytes(
+				byte[] bytes)
+			{
+				vals.CopyTo(bytes, 0);
+			}
+		}
+
+		private RsaKeyParameters pubKey = new RsaKeyParameters(false,
+			new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+			new BigInteger("010001",16));
+
+		private RsaPrivateCrtKeyParameters privKey = new RsaPrivateCrtKeyParameters(
+			new BigInteger("a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a2137",16),
+			new BigInteger("010001",16),
+			new BigInteger("33a5042a90b27d4f5451ca9bbbd0b44771a101af884340aef9885f2a4bbe92e894a724ac3c568c8f97853ad07c0266c8c6a3ca0929f1e8f11231884429fc4d9ae55fee896a10ce707c3ed7e734e44727a39574501a532683109c2abacaba283c31b4bd2f53c3ee37e352cee34f9e503bd80c0622ad79c6dcee883547c6a3b325",16),
+			new BigInteger("e7e8942720a877517273a356053ea2a1bc0c94aa72d55c6e86296b2dfc967948c0a72cbccca7eacb35706e09a1df55a1535bd9b3cc34160b3b6dcd3eda8e6443",16),
+			new BigInteger("b69dca1cf7d4d7ec81e75b90fcca874abcde123fd2700180aa90479b6e48de8d67ed24f9f19d85ba275874f542cd20dc723e6963364a1f9425452b269a6799fd",16),
+			new BigInteger("28fa13938655be1f8a159cbaca5a72ea190c30089e19cd274a556f36c4f6e19f554b34c077790427bbdd8dd3ede2448328f385d81b30e8e43b2fffa027861979",16),
+			new BigInteger("1a8b38f398fa712049898d7fb79ee0a77668791299cdfa09efc0e507acb21ed74301ef5bfd48be455eaeb6e1678255827580a8e4e8e14151d1510a82a3f2e729",16),
+			new BigInteger("27156aba4126d24a81f3a528cbfb27f56886f840a9f6e86e17a44b94fe9319584b8e22fdde1e5a2e3bd8aa5ba8d8584194eb2190acf832b847f13a3d24a79f4d",16));
+
+		// PSSExample1.1
+
+		private static readonly byte[] msg1a = Hex.Decode("cdc87da223d786df3b45e0bbbc721326d1ee2af806cc315475cc6f0d9c66e1b62371d45ce2392e1ac92844c310102f156a0d8d52c1f4c40ba3aa65095786cb769757a6563ba958fed0bcc984e8b517a3d5f515b23b8a41e74aa867693f90dfb061a6e86dfaaee64472c00e5f20945729cbebe77f06ce78e08f4098fba41f9d6193c0317e8b60d4b6084acb42d29e3808a3bc372d85e331170fcbf7cc72d0b71c296648b3a4d10f416295d0807aa625cab2744fd9ea8fd223c42537029828bd16be02546f130fd2e33b936d2676e08aed1b73318b750a0167d0");
+
+		private static readonly byte[] slt1a = Hex.Decode("dee959c7e06411361420ff80185ed57f3e6776af");
+
+		private static readonly byte[] sig1a = Hex.Decode("9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c");
+
+		private static readonly byte[] sig1b = Hex.Decode("96ea348db4db2947aee807bd687411a880913706f21b383a1002b97e43656e5450a9d1812efbedd1ed159f8307986adf48bada66a8efd14bd9e2f6f6f458e73b50c8ce6e3079011c5b4bd1600a2601a66198a1582574a43f13e0966c6c2337e6ca0886cd9e1b1037aeadef1382117d22b35e7e4403f90531c8cfccdf223f98e4");
+
+		private static readonly byte[] sig1c = Hex.Decode("9e64cc1062c537b142480bc5af407b55904ead970e20e0f8f6664279c96c6da6b03522160f224a85cc413dfe6bd00621485b665abac6d90ff38c9af06f4ddd6c7c81540439e5795601a1343d9feb465712ff8a5f5150391522fb5a9b8e2225a555f4efaa5e5c0ed7a19b27074c2d9f6dbbd0c893ba02c4a35b115d337bccd7a2");
+
+		public override void PerformTest()
+		{
+			ISigner s = SignerUtilities.GetSigner("SHA1withRSA/PSS");
+
+			s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a)));
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			byte[] sig = s.GenerateSignature();
+
+			if (!Arrays.AreEqual(sig1a, sig))
+			{
+				Fail("PSS Sign test expected "
+					+ Hex.ToHexString(sig1a) + " got "
+					+ Hex.ToHexString(sig));
+			}
+
+			s = SignerUtilities.GetSigner("SHA1withRSAandMGF1");
+
+			s.Init(false, pubKey);
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			if (!s.VerifySignature(sig1a))
+			{
+				Fail("SHA1 signature verification failed");
+			}
+
+			s = SignerUtilities.GetSigner("SHA1withRSAandMGF1");
+
+			s.Init(false, pubKey);
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			if (!s.VerifySignature(sig1a))
+			{
+				Fail("SHA1 signature verification with default parameters failed");
+			}
+
+//				AlgorithmParameters pss = s.getParameters();
+			// TODO Can we do some equivalent check?
+//				if (!Arrays.AreEqual(pss.getEncoded(), new byte[] { 0x30, 0x00 }))
+//				{
+//					Fail("failed default encoding test.");
+//				}
+
+			s = SignerUtilities.GetSigner("SHA256withRSA/PSS");
+
+			s.Init(true, new ParametersWithRandom(privKey, new FixedRandom(slt1a)));
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			sig = s.GenerateSignature();
+
+			if (!Arrays.AreEqual(sig1b, sig))
+			{
+				Fail("PSS Sign test expected "
+					+ Hex.ToHexString(sig1b) + " got "
+					+ Hex.ToHexString(sig));
+			}
+
+			s = SignerUtilities.GetSigner("SHA256withRSAandMGF1");
+
+			s.Init(false, pubKey);
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			if (!s.VerifySignature(sig1b))
+			{
+				Fail("SHA256 signature verification failed");
+			}
+
+			//
+			// 512 test -with zero salt length
+			//
+			//s = SignerUtilities.GetSigner("SHA512withRSAandMGF1");
+//				s.setParameter(
+//					new PSSParameterSpec("SHA-512", "MGF1", new MGF1ParameterSpec("SHA-512"), 0, 1));
+
+			// TODO How to do this via SignerUtilities/Init
+			// trailerField=1 above means use default/implicit trailer?)
+			s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit);
+			s.Init(true, privKey);
+
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			sig = s.GenerateSignature();
+
+//				pss = s.getParameters();
+
+			if (!Arrays.AreEqual(sig1c, sig))
+			{
+				Fail("PSS Sign test expected "
+					+ Hex.ToHexString(sig1c) + " got "
+					+ Hex.ToHexString(sig));
+			}
+
+
+
+//				s = SignerUtilities.GetSigner("SHA512withRSAandMGF1");
+
+			// TODO How to do this via SignerUtilities/Init
+			// trailerField=1 above means use default/implicit trailer?)
+			s = new PssSigner(new RsaEngine(), new Sha512Digest(), 0, PssSigner.TrailerImplicit);
+			s.Init(false, pubKey);
+
+			s.BlockUpdate(msg1a, 0, msg1a.Length);
+			if (!s.VerifySignature(sig1c))
+			{
+				Fail("SHA512 signature verification failed");
+			}
+
+			SecureRandom random = new SecureRandom();
+
+			// Note: PSS minimum key size determined by hash/salt lengths
+//			PrivateKey priv2048Key = fact.generatePrivate(RSATest.priv2048KeySpec);
+//			PublicKey pub2048Key = fact.generatePublic(RSATest.pub2048KeySpec);
+			AsymmetricKeyParameter priv2048Key = RsaTest.priv2048KeySpec;
+			AsymmetricKeyParameter pub2048Key = RsaTest.pub2048KeySpec;
+
+			rawModeTest("SHA1withRSA/PSS", X509ObjectIdentifiers.IdSha1, priv2048Key, pub2048Key, random);
+			// FIXME
+//			rawModeTest("SHA224withRSA/PSS", NistObjectIdentifiers.IdSha224, priv2048Key, pub2048Key, random);
+//			rawModeTest("SHA256withRSA/PSS", NistObjectIdentifiers.IdSha256, priv2048Key, pub2048Key, random);
+//			rawModeTest("SHA384withRSA/PSS", NistObjectIdentifiers.IdSha384, priv2048Key, pub2048Key, random);
+//			rawModeTest("SHA512withRSA/PSS", NistObjectIdentifiers.IdSha512, priv2048Key, pub2048Key, random);
+		}
+
+		private void rawModeTest(string sigName, DerObjectIdentifier digestOID,
+			AsymmetricKeyParameter privKey, AsymmetricKeyParameter pubKey, SecureRandom random)
+		{
+			byte[] sampleMessage = new byte[1000 + random.Next() % 100];
+			random.NextBytes(sampleMessage);
+
+			ISigner normalSig = SignerUtilities.GetSigner(sigName);
+
+			// FIXME
+//			PSSParameterSpec spec = (PSSParameterSpec)normalSig.getParameters().getParameterSpec(PSSParameterSpec.class);
+
+			// Make sure we generate the same 'random' salt for both normal and raw signers
+			// FIXME
+//			int saltLen = spec.getSaltLength();
+//			byte[] fixedRandomBytes = new byte[saltLen];
+			byte[] fixedRandomBytes = new byte[128];
+			random.NextBytes(fixedRandomBytes);
+
+			normalSig.Init(true, new ParametersWithRandom(privKey, FixedSecureRandom.From(fixedRandomBytes)));
+			normalSig.BlockUpdate(sampleMessage, 0, sampleMessage.Length);
+			byte[] normalResult = normalSig.GenerateSignature();
+
+			byte[] hash = DigestUtilities.CalculateDigest(digestOID.Id, sampleMessage);
+		
+			ISigner rawSig = SignerUtilities.GetSigner("RAWRSASSA-PSS");
+
+			// Need to init the params explicitly to avoid having a 'raw' variety of every PSS algorithm
+			// FIXME
+//			rawSig.setParameter(spec);
+
+			rawSig.Init(true, new ParametersWithRandom(privKey, FixedSecureRandom.From(fixedRandomBytes)));
+			rawSig.BlockUpdate(hash, 0, hash.Length);
+			byte[] rawResult = rawSig.GenerateSignature();
+
+			if (!Arrays.AreEqual(normalResult, rawResult))
+			{
+				Fail("raw mode signature differs from normal one");
+			}
+
+			rawSig.Init(false, pubKey);
+			rawSig.BlockUpdate(hash, 0, hash.Length);
+
+			if (!rawSig.VerifySignature(rawResult))
+			{
+				Fail("raw mode signature verification failed");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "PSS"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PssTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PkixNameConstraintsTest.cs b/BouncyCastle.AxCrypt/test/src/test/PkixNameConstraintsTest.cs
new file mode 100644
index 0000000..a20fc33
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PkixNameConstraintsTest.cs
@@ -0,0 +1,433 @@
+using System;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <summary>
+	/// Test class for {@link PkixNameConstraintValidator}.
+	/// The field testXYZ is the name to test.
+	/// The field testXYZIsConstraint must be tested if it is permitted and excluded.
+	/// The field testXYZIsNotConstraint must be tested if it is not permitted and
+	/// not excluded.
+	/// Furthermore there are tests for the intersection and union of test names.
+	/// </summary>
+	[TestFixture]
+	public class PkixNameConstraintsTest
+		: SimpleTest
+	{
+		private readonly string testEmail = "test at abc.test.com";
+
+		private readonly string[] testEmailIsConstraint = { "test at abc.test.com", "abc.test.com", ".test.com" };
+
+		private readonly string[] testEmailIsNotConstraint = { ".abc.test.com", "www.test.com", "test1 at abc.test.com", "bc.test.com" };
+
+		private readonly string[] email1 = {
+			"test at test.com", "test at test.com", "test at test.com", "test at abc.test.com",
+			"test at test.com", "test at test.com", ".test.com", ".test.com",
+			".test.com", ".test.com", "test.com", "abc.test.com",
+			"abc.test1.com", "test.com", "test.com", ".test.com" };
+
+		private readonly string[] email2 = {
+			"test at test.abc.com", "test at test.com", ".test.com", ".test.com",
+			"test.com", "test1.com", "test at test.com", ".test.com",
+			".test1.com", "test.com", "test.com", ".test.com", ".test.com",
+			"test1.com", ".test.com", "abc.test.com" };
+
+		private readonly string[] emailintersect = {
+			null, "test at test.com", null, "test at abc.test.com", "test at test.com", null,
+			null, ".test.com", null, null, "test.com", "abc.test.com", null,
+			null, null, "abc.test.com" };
+
+		private readonly string[][] emailunion = new string[16][] {
+			new string[] { "test at test.com", "test at test.abc.com" },
+			new string[] { "test at test.com" },
+			new string[] { "test at test.com", ".test.com" },
+			new string[] { ".test.com" },
+			new string[] { "test.com" },
+			new string[] { "test at test.com", "test1.com" },
+			new string[] { ".test.com", "test at test.com" },
+			new string[] { ".test.com" },
+			new string[] { ".test.com", ".test1.com" },
+			new string[] { ".test.com", "test.com" },
+			new string[] { "test.com" },
+			new string[] { ".test.com" },
+			new string[] { ".test.com", "abc.test1.com" },
+			new string[] { "test1.com", "test.com" },
+			new string[] { ".test.com", "test.com" },
+			new string[] { ".test.com" } };
+
+		private readonly string[] dn1 = { "O=test org, OU=test org unit, CN=John Doe" };
+
+		private readonly string[] dn2 = { "O=test org, OU=test org unit" };
+
+		private readonly string[][] dnUnion = new string[1][] {
+			new string[] { "O=test org, OU=test org unit" } };
+
+		private readonly string[] dnIntersection = { "O=test org, OU=test org unit, CN=John Doe" };
+
+		private readonly string testDN = "O=test org, OU=test org unit, CN=John Doe";
+
+		private readonly string[] testDNIsConstraint = {
+			"O=test org, OU=test org unit",
+			"O=test org, OU=test org unit, CN=John Doe" };
+
+		private readonly string[] testDNIsNotConstraint = {
+			"O=test org, OU=test org unit, CN=John Doe2",
+			"O=test org, OU=test org unit2",
+			"OU=test org unit, O=test org, CN=John Doe",
+			"O=test org, OU=test org unit, CN=John Doe, L=USA" };
+
+		private readonly string testDNS = "abc.test.com";
+
+		private readonly string[] testDNSIsConstraint = { "test.com", "abc.test.com", "test.com" };
+
+		private readonly string[] testDNSIsNotConstraint = { "wwww.test.com", "ww.test.com", "www.test.com" };
+
+		private readonly string[] dns1 = { "www.test.de", "www.test1.de", "www.test.de" };
+
+		private readonly string[] dns2 = { "test.de", "www.test.de", "www.test.de" };
+
+		private readonly string[] dnsintersect = { "www.test.de", null, null };
+
+		private readonly string[][] dnsunion = new string[3][] {
+			new string[] { "test.de" },
+			new string[] { "www.test1.de", "www.test.de" },
+			new string[] { "www.test.de" } };
+
+		private readonly string testURI = "http://karsten:password@abc.test.com:8080";
+
+		private readonly string[] testURIIsConstraint = { "abc.test.com", ".test.com" };
+
+		private readonly string[] testURIIsNotConstraint = { "xyz.test.com", ".abc.test.com" };
+
+		private readonly string[] uri1 = { "www.test.de", ".test.de", "test1.de", ".test.de" };
+
+		private readonly string[] uri2 = { "test.de", "www.test.de", "test1.de", ".test.de" };
+
+		private readonly string[] uriintersect = { null, "www.test.de", "test1.de", ".test.de" };
+
+		private readonly string[][] uriunion = new string[4][] {
+			new string[] { "www.test.de", "test.de" },
+			new string[] { ".test.de" },
+			new string[] { "test1.de" },
+			new string[] { ".test.de" } };
+
+		private readonly byte[] testIP = { (byte)192, (byte)168, 1, 2 };
+
+		private readonly byte[][] testIPIsConstraint = new byte[2][] {
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 0 },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 4 } };
+
+		private readonly byte[][] testIPIsNotConstraint = new byte[2][] {
+			new byte[] { (byte) 192, (byte) 168, 3, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 2 },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, 3 } };
+
+		private readonly byte[][] ip1 = new byte[3][] {
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFE, (byte) 0xFF },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFF, (byte) 0xFF },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFF, (byte) 0x00 } };
+
+		private readonly byte[][] ip2 = new byte[3][] {
+			new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFC, 3 },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFF, (byte) 0xFF },
+			new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFF, (byte) 0x00 } };
+
+		private readonly byte[][] ipintersect = new byte[3][] {
+			new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFE, (byte) 0xFF },
+			new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+						(byte) 0xFF, (byte) 0xFF }, null };
+
+		private readonly byte[][][] ipunion = new byte[3][][] {
+			new byte[2][] {
+							new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+											(byte) 0xFE, (byte) 0xFF },
+							new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF,
+											(byte) 0xFC, 3 } },
+			new byte[1][] {
+							new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+											(byte) 0xFF, (byte) 0xFF } },
+			new byte[2][] {
+							new byte[] { (byte) 192, (byte) 168, 1, 1, (byte) 0xFF, (byte) 0xFF,
+											(byte) 0xFF, (byte) 0x00 },
+							new byte[] { (byte) 192, (byte) 168, 0, 1, (byte) 0xFF, (byte) 0xFF,
+											(byte) 0xFF, (byte) 0x00 } } };
+
+		public override string Name
+		{
+			get { return "PkixNameConstraintsTest"; }
+		}
+
+		public override void PerformTest()
+		{
+			TestConstraints(GeneralName.Rfc822Name, testEmail,
+				testEmailIsConstraint, testEmailIsNotConstraint, email1, email2,
+				emailunion, emailintersect);
+			TestConstraints(GeneralName.DnsName, testDNS, testDNSIsConstraint,
+				testDNSIsNotConstraint, dns1, dns2, dnsunion, dnsintersect);
+			TestConstraints(GeneralName.DirectoryName, testDN, testDNIsConstraint,
+				testDNIsNotConstraint, dn1, dn2, dnUnion, dnIntersection);
+			TestConstraints(GeneralName.UniformResourceIdentifier, testURI,
+				testURIIsConstraint, testURIIsNotConstraint, uri1, uri2, uriunion,
+				uriintersect);
+			TestConstraints(GeneralName.IPAddress, testIP, testIPIsConstraint,
+				testIPIsNotConstraint, ip1, ip2, ipunion, ipintersect);
+		}
+
+		/**
+		 * Tests string based GeneralNames for inclusion or exclusion.
+		 * 
+		 * @param nameType The {@link GeneralName} type to test.
+		 * @param testName The name to test.
+		 * @param testNameIsConstraint The names where <code>testName</code> must
+		 *            be included and excluded.
+		 * @param testNameIsNotConstraint The names where <code>testName</code>
+		 *            must not be excluded and included.
+		 * @param testNames1 Operand 1 of test names to use for union and
+		 *            intersection testing.
+		 * @param testNames2 Operand 2 of test names to use for union and
+		 *            intersection testing.
+		 * @param testUnion The union results.
+		 * @param testInterSection The intersection results.
+		 * @throws Exception If an unexpected exception occurs.
+		 */
+		private void TestConstraints(
+			int			nameType,
+			string		testName,
+			string[]	testNameIsConstraint,
+			string[]	testNameIsNotConstraint,
+			string[]	testNames1,
+			string[]	testNames2,
+			string[][]	testUnion,
+			string[]	testInterSection)
+		{
+			for (int i = 0; i < testNameIsConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, testNameIsConstraint[i]))));
+				constraintValidator.checkPermitted(new GeneralName(nameType, testName));
+			}
+			for (int i = 0; i < testNameIsNotConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, testNameIsNotConstraint[i]))));
+				try
+				{
+					constraintValidator.checkPermitted(new GeneralName(nameType, testName));
+					Fail("not permitted name allowed: " + nameType);
+				}
+				catch (PkixNameConstraintValidatorException)
+				{
+					// expected
+				}
+			}
+			for (int i = 0; i < testNameIsConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, testNameIsConstraint[i])));
+				try
+				{
+					constraintValidator.checkExcluded(new GeneralName(nameType, testName));
+					Fail("excluded name missed: " + nameType);
+				}
+				catch (PkixNameConstraintValidatorException)
+				{
+					// expected
+				}
+			}
+			for (int i = 0; i < testNameIsNotConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, testNameIsNotConstraint[i])));
+				constraintValidator.checkExcluded(new GeneralName(nameType, testName));
+			}
+			for (int i = 0; i < testNames1.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, testNames1[i])));
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, testNames2[i])));
+				PkixNameConstraintValidator constraints2 = new PkixNameConstraintValidator();
+				for (int j = 0; j < testUnion[i].Length; j++)
+				{
+					constraints2.AddExcludedSubtree(new GeneralSubtree(
+						new GeneralName(nameType, testUnion[i][j])));
+				}
+				if (!constraints2.Equals(constraintValidator))
+				{
+					Fail("union wrong: " + nameType);
+				}
+				constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, testNames1[i]))));
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, testNames2[i]))));
+				constraints2 = new PkixNameConstraintValidator();
+				if (testInterSection[i] != null)
+				{
+					constraints2.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+						new GeneralName(nameType, testInterSection[i]))));
+				}
+				else
+				{
+					constraints2.IntersectEmptyPermittedSubtree(nameType);
+				}
+				if (!constraints2.Equals(constraintValidator))
+				{
+					Fail("intersection wrong: " + nameType);
+				}
+			}
+		}
+
+		/**
+		 * Tests byte array based GeneralNames for inclusion or exclusion.
+		 * 
+		 * @param nameType The {@link GeneralName} type to test.
+		 * @param testName The name to test.
+		 * @param testNameIsConstraint The names where <code>testName</code> must
+		 *            be included and excluded.
+		 * @param testNameIsNotConstraint The names where <code>testName</code>
+		 *            must not be excluded and included.
+		 * @param testNames1 Operand 1 of test names to use for union and
+		 *            intersection testing.
+		 * @param testNames2 Operand 2 of test names to use for union and
+		 *            intersection testing.
+		 * @param testUnion The union results.
+		 * @param testInterSection The intersection results.
+		 * @throws Exception If an unexpected exception occurs.
+		 */
+		private void TestConstraints(
+			int nameType,
+			byte[] testName,
+			byte[][] testNameIsConstraint,
+			byte[][] testNameIsNotConstraint,
+			byte[][] testNames1,
+			byte[][] testNames2,
+			byte[][][] testUnion,
+			byte[][] testInterSection)
+		{
+			for (int i = 0; i < testNameIsConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, new DerOctetString(
+					testNameIsConstraint[i])))));
+				constraintValidator.checkPermitted(new GeneralName(nameType,
+					new DerOctetString(testName)));
+			}
+			for (int i = 0; i < testNameIsNotConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, new DerOctetString(
+					testNameIsNotConstraint[i])))));
+				try
+				{
+					constraintValidator.checkPermitted(new GeneralName(nameType,
+						new DerOctetString(testName)));
+					Fail("not permitted name allowed: " + nameType);
+				}
+				catch (PkixNameConstraintValidatorException)
+				{
+					// expected
+				}
+			}
+			for (int i = 0; i < testNameIsConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, new DerOctetString(testNameIsConstraint[i]))));
+				try
+				{
+					constraintValidator.checkExcluded(new GeneralName(nameType,
+						new DerOctetString(testName)));
+					Fail("excluded name missed: " + nameType);
+				}
+				catch (PkixNameConstraintValidatorException)
+				{
+					// expected
+				}
+			}
+			for (int i = 0; i < testNameIsNotConstraint.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, new DerOctetString(testNameIsNotConstraint[i]))));
+				constraintValidator.checkExcluded(new GeneralName(nameType,
+					new DerOctetString(testName)));
+			}
+			for (int i = 0; i < testNames1.Length; i++)
+			{
+				PkixNameConstraintValidator constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, new DerOctetString(testNames1[i]))));
+				constraintValidator.AddExcludedSubtree(new GeneralSubtree(new GeneralName(
+					nameType, new DerOctetString(testNames2[i]))));
+				PkixNameConstraintValidator constraints2 = new PkixNameConstraintValidator();
+				for (int j = 0; j < testUnion[i].Length; j++)
+				{
+					constraints2.AddExcludedSubtree(new GeneralSubtree(
+						new GeneralName(nameType, new DerOctetString(
+						testUnion[i][j]))));
+				}
+				if (!constraints2.Equals(constraintValidator))
+				{
+					Fail("union wrong: " + nameType);
+				}
+				constraintValidator = new PkixNameConstraintValidator();
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, new DerOctetString(testNames1[i])))));
+				constraintValidator.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+					new GeneralName(nameType, new DerOctetString(testNames2[i])))));
+				constraints2 = new PkixNameConstraintValidator();
+				if (testInterSection[i] != null)
+				{
+					constraints2.IntersectPermittedSubtree(new DerSequence(new GeneralSubtree(
+						new GeneralName(nameType, new DerOctetString(
+						testInterSection[i])))));
+				}
+				else
+				{
+					constraints2.IntersectEmptyPermittedSubtree(nameType);
+				}
+
+				if (!constraints2.Equals(constraintValidator))
+				{
+					Fail("intersection wrong: " + nameType);
+				}
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PkixNameConstraintsTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PkixPolicyMappingTest.cs b/BouncyCastle.AxCrypt/test/src/test/PkixPolicyMappingTest.cs
new file mode 100644
index 0000000..47e2c31
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PkixPolicyMappingTest.cs
@@ -0,0 +1,419 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class PkixPolicyMappingTest : SimpleTest
+	{
+		static X509V3CertificateGenerator v3CertGen = new X509V3CertificateGenerator();
+
+		public override string Name
+		{
+			get { return "PkixPolicyMapping"; }
+		}
+
+		/**
+		 * TrustAnchor's Cert
+		 */
+		private X509Certificate CreateTrustCert(
+			AsymmetricKeyParameter pubKey,
+			AsymmetricKeyParameter privKey)
+		{
+			string issuer = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor";
+			string subject = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor";
+			v3CertGen.SetSerialNumber(BigInteger.ValueOf(10));
+			v3CertGen.SetIssuerDN(new X509Name(issuer));
+			v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30));
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30));
+			v3CertGen.SetSubjectDN(new X509Name(subject));
+			v3CertGen.SetPublicKey(pubKey);
+			v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+			X509Certificate cert = v3CertGen.Generate(privKey);
+			return cert;
+		}
+
+		/**
+		 * intermediate cert
+		 */
+		private X509Certificate CreateIntmedCert(
+			AsymmetricKeyParameter pubKey,
+			AsymmetricKeyParameter caPrivKey,
+			AsymmetricKeyParameter caPubKey,
+			Asn1EncodableVector policies,
+			Hashtable policyMap)
+		{
+			string issuer = "C=JP, O=policyMappingAdditionalTest, OU=trustAnchor";
+			string subject = "C=JP, O=policyMappingAdditionalTest, OU=intmedCA";
+			v3CertGen.Reset();
+			v3CertGen.SetSerialNumber(BigInteger.ValueOf(20));
+			v3CertGen.SetIssuerDN(new X509Name(issuer));
+			v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30));
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30));
+			v3CertGen.SetSubjectDN(new X509Name(subject));
+			v3CertGen.SetPublicKey(pubKey);
+			v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+			v3CertGen.AddExtension(X509Extensions.CertificatePolicies, true, new DerSequence(policies));
+			v3CertGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
+			v3CertGen.AddExtension(X509Extensions.PolicyMappings, true, new PolicyMappings(policyMap));
+			X509Certificate cert = v3CertGen.Generate(caPrivKey);
+			return cert;
+		}
+
+		/**
+		 * endEntity cert
+		 */
+		private X509Certificate CreateEndEntityCert(
+			AsymmetricKeyParameter pubKey,
+			AsymmetricKeyParameter caPrivKey,
+			AsymmetricKeyParameter caPubKey,
+			Asn1EncodableVector policies)
+		{
+			string issuer = "C=JP, O=policyMappingAdditionalTest, OU=intMedCA";
+			string subject = "C=JP, O=policyMappingAdditionalTest, OU=endEntity";
+			v3CertGen.Reset();
+			v3CertGen.SetSerialNumber(BigInteger.ValueOf(20));
+			v3CertGen.SetIssuerDN(new X509Name(issuer));
+			v3CertGen.SetNotBefore(DateTime.UtcNow.AddDays(-30));
+			v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(30));
+			v3CertGen.SetSubjectDN(new X509Name(subject));
+			v3CertGen.SetPublicKey(pubKey);
+			v3CertGen.SetSignatureAlgorithm("SHA1WithRSAEncryption");
+			v3CertGen.AddExtension(X509Extensions.CertificatePolicies, true, new DerSequence(policies));
+			X509Certificate cert = v3CertGen.Generate(caPrivKey);
+			return cert;
+		}
+
+		private string TestPolicies(
+			int index,
+			X509Certificate trustCert,
+			X509Certificate intCert,
+			X509Certificate endCert,
+			ISet requirePolicies,
+			bool okay)
+		{
+			ISet trust = new HashSet();
+			trust.Add(new TrustAnchor(trustCert, null));
+			X509CertStoreSelector targetConstraints = new X509CertStoreSelector();
+			targetConstraints.Subject = endCert.SubjectDN;
+			PkixBuilderParameters pbParams = new PkixBuilderParameters(trust, targetConstraints);
+
+			ISet certs = new HashSet();
+			certs.Add(intCert);
+			certs.Add(endCert);
+
+			IX509Store store = X509StoreFactory.Create(
+				"CERTIFICATE/COLLECTION",
+				new X509CollectionStoreParameters(certs));
+			pbParams.AddStore(store);
+
+			pbParams.IsRevocationEnabled = false;
+			if (requirePolicies != null)
+			{
+				pbParams.IsExplicitPolicyRequired = true;
+				pbParams.SetInitialPolicies(requirePolicies);
+			}
+
+//			CertPathBuilder cpb = CertPathBuilder.GetInstance("PKIX");
+			PkixCertPathBuilder cpb = new PkixCertPathBuilder();
+			PkixCertPathBuilderResult result = null;
+
+			try
+			{
+				result = (PkixCertPathBuilderResult)cpb.Build(pbParams);
+
+				if (!okay)
+				{
+					Fail(index + ": path validated when failure expected.");
+				}
+
+//				if (result.getPolicyTree() != null)
+//				{
+//					Console.WriteLine("OK");
+//					Console.WriteLine("policy: " + result.getPolicyTree());
+//				}
+//				else
+//				{
+//					Console.WriteLine("OK: policy tree = null");
+//				}
+
+				return "";
+			}
+			catch (TestFailedException e)
+			{
+				throw e;
+			}
+			catch (Exception e)
+			{
+				if (okay)
+				{
+					Fail(index + ": path failed to validate when success expected.");
+				}
+
+				Exception ee = e.InnerException;
+				if (ee != null)
+				{
+					return ee.Message;
+				}
+
+				return e.Message;
+			}
+		}
+
+		public override void PerformTest()
+		{
+			//
+			// personal keys
+			//
+			RsaPublicKeyStructure pubKeySpec = new RsaPublicKeyStructure(
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16));
+
+			RsaPrivateCrtKeyParameters privKeySpec = new RsaPrivateCrtKeyParameters(
+				new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+				new BigInteger("11", 16),
+				new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+				new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+				new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+				new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+				new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+				new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+			//
+			// intermediate keys.
+			//
+			RsaPublicKeyStructure intPubKeySpec = new RsaPublicKeyStructure(
+				new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16),
+				new BigInteger("ffff", 16));
+
+
+			RsaPrivateCrtKeyParameters intPrivKeySpec = new RsaPrivateCrtKeyParameters(
+				new BigInteger("8de0d113c5e736969c8d2b047a243f8fe18edad64cde9e842d3669230ca486f7cfdde1f8eec54d1905fff04acc85e61093e180cadc6cea407f193d44bb0e9449b8dbb49784cd9e36260c39e06a947299978c6ed8300724e887198cfede20f3fbde658fa2bd078be946a392bd349f2b49c486e20c405588e306706c9017308e69", 16),
+				new BigInteger("ffff", 16),
+				new BigInteger("7deb1b194a85bcfd29cf871411468adbc987650903e3bacc8338c449ca7b32efd39ffc33bc84412fcd7df18d23ce9d7c25ea910b1ae9985373e0273b4dca7f2e0db3b7314056ac67fd277f8f89cf2fd73c34c6ca69f9ba477143d2b0e2445548aa0b4a8473095182631da46844c356f5e5c7522eb54b5a33f11d730ead9c0cff", 16),
+				new BigInteger("ef4cede573cea47f83699b814de4302edb60eefe426c52e17bd7870ec7c6b7a24fe55282ebb73775f369157726fcfb988def2b40350bdca9e5b418340288f649", 16),
+				new BigInteger("97c7737d1b9a0088c3c7b528539247fd2a1593e7e01cef18848755be82f4a45aa093276cb0cbf118cb41117540a78f3fc471ba5d69f0042274defc9161265721", 16),
+				new BigInteger("6c641094e24d172728b8da3c2777e69adfd0839085be7e38c7c4a2dd00b1ae969f2ec9d23e7e37090fcd449a40af0ed463fe1c612d6810d6b4f58b7bfa31eb5f", 16),
+				new BigInteger("70b7123e8e69dfa76feb1236d0a686144b00e9232ed52b73847e74ef3af71fb45ccb24261f40d27f98101e230cf27b977a5d5f1f15f6cf48d5cb1da2a3a3b87f", 16),
+				new BigInteger("e38f5750d97e270996a286df2e653fd26c242106436f5bab0f4c7a9e654ce02665d5a281f2c412456f2d1fa26586ef04a9adac9004ca7f913162cb28e13bf40d", 16));
+
+			//
+			// ca keys
+			//
+			RsaPublicKeyStructure caPubKeySpec = new RsaPublicKeyStructure(
+				new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16),
+				new BigInteger("11", 16));
+
+			RsaPrivateCrtKeyParameters caPrivKeySpec = new RsaPrivateCrtKeyParameters(
+				new BigInteger("b259d2d6e627a768c94be36164c2d9fc79d97aab9253140e5bf17751197731d6f7540d2509e7b9ffee0a70a6e26d56e92d2edd7f85aba85600b69089f35f6bdbf3c298e05842535d9f064e6b0391cb7d306e0a2d20c4dfb4e7b49a9640bdea26c10ad69c3f05007ce2513cee44cfe01998e62b6c3637d3fc0391079b26ee36d5", 16),
+				new BigInteger("11", 16),
+				new BigInteger("92e08f83cc9920746989ca5034dcb384a094fb9c5a6288fcc4304424ab8f56388f72652d8fafc65a4b9020896f2cde297080f2a540e7b7ce5af0b3446e1258d1dd7f245cf54124b4c6e17da21b90a0ebd22605e6f45c9f136d7a13eaac1c0f7487de8bd6d924972408ebb58af71e76fd7b012a8d0e165f3ae2e5077a8648e619", 16),
+				new BigInteger("f75e80839b9b9379f1cf1128f321639757dba514642c206bbbd99f9a4846208b3e93fbbe5e0527cc59b1d4b929d9555853004c7c8b30ee6a213c3d1bb7415d03", 16),
+				new BigInteger("b892d9ebdbfc37e397256dd8a5d3123534d1f03726284743ddc6be3a709edb696fc40c7d902ed804c6eee730eee3d5b20bf6bd8d87a296813c87d3b3cc9d7947", 16),
+				new BigInteger("1d1a2d3ca8e52068b3094d501c9a842fec37f54db16e9a67070a8b3f53cc03d4257ad252a1a640eadd603724d7bf3737914b544ae332eedf4f34436cac25ceb5", 16),
+				new BigInteger("6c929e4e81672fef49d9c825163fec97c4b7ba7acb26c0824638ac22605d7201c94625770984f78a56e6e25904fe7db407099cad9b14588841b94f5ab498dded", 16),
+				new BigInteger("dae7651ee69ad1d081ec5e7188ae126f6004ff39556bde90e0b870962fa7b926d070686d8244fe5a9aa709a95686a104614834b0ada4b10f53197a5cb4c97339", 16));
+
+			//
+			// set up the keys
+			//
+			AsymmetricKeyParameter caPrivKey = caPrivKeySpec;
+			RsaKeyParameters caPubKey = new RsaKeyParameters(false, caPubKeySpec.Modulus, caPubKeySpec.PublicExponent);
+			AsymmetricKeyParameter intPrivKey = intPrivKeySpec;
+			RsaKeyParameters intPubKey = new RsaKeyParameters(false, intPubKeySpec.Modulus, intPubKeySpec.PublicExponent);
+			AsymmetricKeyParameter privKey = privKeySpec;
+			RsaKeyParameters pubKey = new RsaKeyParameters(false, pubKeySpec.Modulus, intPubKeySpec.PublicExponent);
+
+			X509Certificate trustCert = CreateTrustCert(caPubKey, caPrivKeySpec);
+			Asn1EncodableVector intPolicies = null;
+			Hashtable map = null;
+			Asn1EncodableVector policies = null;
+			ISet requirePolicies = null;
+			X509Certificate intCert = null;
+			X509Certificate endCert = null;
+
+			// valid test_00
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = null;
+			string msg = TestPolicies(0, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(0, msg, "");
+
+			// test_01
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.1");
+			msg = TestPolicies(1, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(1, msg, "");
+
+			// test_02
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.5.29.32.0");
+			msg = TestPolicies(2, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(2, msg, "");
+
+			// test_03
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3")));
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.1");
+			msg = TestPolicies(3, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(3, msg, "");
+
+			// test_04
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3")));
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.3");
+			msg = TestPolicies(4, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(4, msg, "");
+
+			// test_05
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.2");
+			msg = TestPolicies(5, trustCert, intCert, endCert, requirePolicies, false);
+			CheckMessage(5, msg, "Path processing failed on policy.");
+
+			// test_06
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.1")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.1");
+			msg = TestPolicies(6, trustCert, intCert, endCert, requirePolicies, true);
+			CheckMessage(6, msg, "");
+
+			// test_07
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.2")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.3");
+			msg = TestPolicies(7, trustCert, intCert, endCert, requirePolicies, false);
+			CheckMessage(7, msg, "Path processing failed on policy.");
+
+			// test_08
+			intPolicies = new Asn1EncodableVector();
+			intPolicies.Add(new PolicyInformation(new DerObjectIdentifier("2.5.29.32.0")));
+			map = new Hashtable();
+			map["2.16.840.1.101.3.2.1.48.1"] = "2.16.840.1.101.3.2.1.48.2";
+			intCert = CreateIntmedCert(intPubKey, caPrivKey, caPubKey, intPolicies, map);
+
+			policies = new Asn1EncodableVector();
+			policies.Add(new PolicyInformation(new DerObjectIdentifier("2.16.840.1.101.3.2.1.48.3")));
+			endCert = CreateEndEntityCert(pubKey, intPrivKey, intPubKey, policies);
+
+			requirePolicies = new HashSet();
+			requirePolicies.Add("2.16.840.1.101.3.2.1.48.1");
+			msg = TestPolicies(8, trustCert, intCert, endCert, requirePolicies, false);
+			CheckMessage(8, msg, "Path processing failed on policy.");
+		}
+
+		private void CheckMessage(
+			int		index,
+			string	msg,
+			string	expected)
+		{
+			if (!msg.Equals(expected))
+			{
+				Fail("test " + index + " failed got: " + msg + " expected: " + expected);
+			}
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PkixPolicyMappingTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/PkixTest.cs b/BouncyCastle.AxCrypt/test/src/test/PkixTest.cs
new file mode 100644
index 0000000..8823196
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/PkixTest.cs
@@ -0,0 +1,248 @@
+using System;
+using System.IO;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+    public class PkixTest
+		: SimpleTest
+    {
+        /*
+         * The following certs and crls are described in:
+         * http://www.ietf.org/internet-drafts/draft-ietf-pkix-new-part1-08.txt
+         *
+         *   This section contains four examples: three certificates and a CRL.
+         *   The first two certificates and the CRL comprise a minimal
+         *   certification path.
+         *
+         *   Section C.1 contains an annotated hex dump of a "self-signed"
+         *   certificate issued by a CA whose distinguished name is
+         *   cn=us,o=gov,ou=nist.  The certificate contains a DSA public key with
+         *   parameters, and is signed by the corresponding DSA private key.
+         *
+         *   Section C.2 contains an annotated hex dump of an end entity
+         *   certificate.  The end entity certificate contains a DSA public key,
+         *   and is signed by the private key corresponding to the "self-signed"
+         *   certificate in section C.1.
+         *
+         *   Section C.3 contains a dump of an end entity certificate which
+         *   contains an RSA public key and is signed with RSA and MD5.  This
+         *   certificate is not part of the minimal certification path.
+         *
+         *   Section C.4 contains an annotated hex dump of a CRL.  The CRL is
+         *   issued by the CA whose distinguished name is cn=us,o=gov,ou=nist and
+         *   the list of revoked certificates includes the end entity certificate
+         *   presented in C.2.
+         */
+
+        /**
+         * C.1  Certificate
+         * 
+            * This section contains an annotated hex dump of a 699 byte version 3
+            * certificate.  The certificate contains the following information:
+            * (a)  the serial number is 23 (17 hex);
+            * (b)  the certificate is signed with DSA and the SHA-1 hash algorithm;
+            * (c)  the issuer's distinguished name is OU=NIST; O=gov; C=US
+            * (d)  and the subject's distinguished name is OU=NIST; O=gov; C=US
+            * (e)  the certificate was issued on June 30, 1997 and will expire on
+            * December 31, 1997;
+            * (f)  the certificate contains a 1024 bit DSA public key with
+            * parameters;
+            * (g)  the certificate contains a subject key identifier extension
+            * generated using method (1) of section 4.2.1.2; and
+            * (h)  the certificate is a CA certificate (as indicated through the
+            * basic constraints extension.)
+         */
+        static byte[] rootCertBin = Hex.Decode(
+            "308202bb3082027ba003020102020111300906072a8648ce380403302a310b30"
+            + "09060355040613025553310c300a060355040a1303676f76310d300b06035504"
+            + "0b13044e495354301e170d3937303633303030303030305a170d393731323331"
+            + "3030303030305a302a310b3009060355040613025553310c300a060355040a13"
+            + "03676f76310d300b060355040b13044e495354308201b83082012c06072a8648"
+            + "ce3804013082011f02818100b68b0f942b9acea525c6f2edfcfb9532ac011233"
+            + "b9e01cad909bbc48549ef394773c2c713555e6fe4f22cbd5d83e8993334dfcbd"
+            + "4f41643ea29870ec31b450deebf198280ac93e44b3fd22979683d018a3e3bd35"
+            + "5bffeea321726a7b96dab93f1e5a90af24d620f00d21a7d402b91afcac21fb9e"
+            + "949e4b42459e6ab24863fe43021500b20db0b101df0c6624fc1392ba55f77d57"
+            + "7481e5028181009abf46b1f53f443dc9a565fb91c08e47f10ac30147c2444236"
+            + "a99281de57c5e0688658007b1ff99b77a1c510a580917851513cf6fcfccc46c6"
+            + "817892843df4933d0c387e1a5b994eab1464f60c21224e28089c92b9669f40e8"
+            + "95f6d5312aef39a262c7b26d9e58c43aa81181846daff8b419b4c211aed0223b"
+            + "aa207fee1e57180381850002818100b59e1f490447d1dbf53addca0475e8dd75"
+            + "f69b8ab197d6596982d3034dfd3b365f4af2d14ec107f5d12ad378776356ea96"
+            + "614d420b7a1dfbab91a4cedeef77c8e5ef20aea62848afbe69c36aa530f2c2b9"
+            + "d9822b7dd9c4841fde0de854d71b992eb3d088f6d6639ba7e20e82d43b8a681b"
+            + "065631590b49eb99a5d581417bc955a3323030301d0603551d0e0416041486ca"
+            + "a5228162efad0a89bcad72412c2949f48656300f0603551d130101ff04053003"
+            + "0101ff300906072a8648ce380403032f00302c0214431bcf292545c04e52e77d"
+            + "d6fcb1664c83cf2d7702140b5b9a241198e8f3869004f608a9e18da5cc3ad4");
+
+
+        /**
+         * C.2  Certificate
+         * 
+            * This section contains an annotated hex dump of a 730 byte version 3
+            * certificate.  The certificate contains the following information:
+            * (a the serial number is 18 (12 hex);
+            * (b)  the certificate is signed with DSA and the SHA-1 hash algorithm;
+            * (c)  the issuer's distinguished name is OU=nist; O=gov; C=US
+            * (d)  and the subject's distinguished name is CN=Tim Polk; OU=nist;
+            * O=gov; C=US
+            * (e)  the certificate was valid from July 30, 1997 through December 1,
+            * 1997;
+            * (f)  the certificate contains a 1024 bit DSA public key;
+            * (g)  the certificate is an end entity certificate, as the basic
+            * constraints extension is not present;
+            * (h)  the certificate contains an authority key identifier extension
+            * matching the subject key identifier of the certificate in Appendix
+            * C.1; and
+            * (i)  the certificate includes one alternative name - an RFC 822
+            * address of "wpolk at nist.gov".
+         */
+        static byte[] userCert1Bin = Hex.Decode(
+            "308202da30820299a003020102020112300906072a8648ce380403302a310b30"
+            + "09060355040613025553310c300a060355040a1303676f76310d300b06035504"
+            + "0b13044e495354301e170d3937303733303030303030305a170d393731323031"
+            + "3030303030305a303d310b3009060355040613025553310c300a060355040a13"
+            + "03676f76310d300b060355040b13044e4953543111300f060355040313085469"
+            + "6d20506f6c6b308201b73082012c06072a8648ce3804013082011f02818100b6"
+            + "8b0f942b9acea525c6f2edfcfb9532ac011233b9e01cad909bbc48549ef39477"
+            + "3c2c713555e6fe4f22cbd5d83e8993334dfcbd4f41643ea29870ec31b450deeb"
+            + "f198280ac93e44b3fd22979683d018a3e3bd355bffeea321726a7b96dab93f1e"
+            + "5a90af24d620f00d21a7d402b91afcac21fb9e949e4b42459e6ab24863fe4302"
+            + "1500b20db0b101df0c6624fc1392ba55f77d577481e5028181009abf46b1f53f"
+            + "443dc9a565fb91c08e47f10ac30147c2444236a99281de57c5e0688658007b1f"
+            + "f99b77a1c510a580917851513cf6fcfccc46c6817892843df4933d0c387e1a5b"
+            + "994eab1464f60c21224e28089c92b9669f40e895f6d5312aef39a262c7b26d9e"
+            + "58c43aa81181846daff8b419b4c211aed0223baa207fee1e5718038184000281"
+            + "8030b675f77c2031ae38bb7e0d2baba09c4bdf20d524133ccd98e55f6cb7c1ba"
+            + "4abaa9958053f00d72dc3337f4010bf5041f9d2e1f62d8843a9b25095a2dc846"
+            + "8e2bd4f50d3bc72dc66cb998c1253a444e8eca9561357cce15315c23131ea205"
+            + "d17a241ccbd3720990ff9b9d28c0a10aec469f0db8d0dcd018a62b5ef98fb595"
+            + "bea33e303c30190603551d1104123010810e77706f6c6b406e6973742e676f76"
+            + "301f0603551d2304183016801486caa5228162efad0a89bcad72412c2949f486"
+            + "56300906072a8648ce380403033000302d02143697cbe3b42ce1bb61a9d3cc24"
+            + "cc22929ff4f587021500abc979afd2161ca9e368a91410b4a02eff225a73");
+
+		/**
+		* C.3  End Entity Certificate Using RSA
+		* 
+		* This section contains an annotated hex dump of a 654 byte version 3
+		* certificate.  The certificate contains the following information:
+		* (a)  the serial number is 256;
+		* (b)  the certificate is signed with RSA and the SHA-1 hash algorithm;
+		* (c)  the issuer's distinguished name is OU=NIST; O=gov; C=US
+		* (d)  and the subject's distinguished name is CN=Tim Polk; OU=NIST;
+		* O=gov; C=US
+		* (e)  the certificate was issued on May 21, 1996 at 09:58:26 and
+		* expired on May 21, 1997 at 09:58:26;
+		* (f)  the certificate contains a 1024 bit RSA public key;
+		* (g)  the certificate is an end entity certificate (not a CA
+		* certificate);
+		* (h)  the certificate includes an alternative subject name of
+		*    "<http://www.itl.nist.gov/div893/staff/polk/index.html>" and an
+		* alternative issuer name of "<http://www.nist.gov/>" - both are URLs;
+		* (i)  the certificate include an authority key identifier extension
+		* and a certificate policies extension psecifying the policy OID
+		* 2.16.840.1.101.3.2.1.48.9; and
+		* (j)  the certificate includes a critical key usage extension
+		* specifying that the public key is intended for verification of
+		* digital signatures.
+		*/
+        static byte[] userCert2Bin = Hex.Decode(
+            "3082028e308201f7a00302010202020100300d06092a864886f70d0101050500"
+            + "302a310b3009060355040613025553310c300a060355040b1303676f76310d30"
+            + "0b060355040a13044e495354301e170d3936303532313039353832365a170d39"
+            + "37303532313039353832365a303d310b3009060355040613025553310c300a06"
+            + "0355040b1303676f76310d300b060355040a13044e4953543111300f06035504"
+            + "03130854696d20506f6c6b30819f300d06092a864886f70d010101050003818d"
+            + "0030818902818100e16ae4033097023cf410f3b51e4d7f147bf6f5d078e9a48a"
+            + "f0a375ecedb656967f8899859af23e687787eb9ed19fc0b417dcab8923a41d7e"
+            + "16234c4fa84df531b87caae31a4909f44b26db2767308212014ae91ab6c10c53"
+            + "8b6cfc2f7a43ec33367e32b27bd5aacf0114c612ec13f22d147a8b215814134c"
+            + "46a39af21695ff230203010001a381af3081ac303f0603551d11043830368634"
+            + "687474703a2f2f7777772e69746c2e6e6973742e676f762f6469763839332f73"
+            + "746166662f706f6c6b2f696e6465782e68746d6c301f0603551d120418301686"
+            + "14687474703a2f2f7777772e6e6973742e676f762f301f0603551d2304183016"
+            + "80140868af8533c8394a7af882938e706a4a20842c3230170603551d20041030"
+            + "0e300c060a60864801650302013009300e0603551d0f0101ff04040302078030"
+            + "0d06092a864886f70d0101050500038181008e8e3656788bbfa13975172ee310"
+            + "dc832b6834521cf66c1d525e5420105e4ca940f94b729e82b961dceb32a5bdb1"
+            + "b148f99b01bbebaf9b83f6528cb06d7cd09a39543e6d206fcdd0debe275f204f"
+            + "b6ab0df5b7e1bab4dfdf3dd4f6ed01fb6ecb9859ac41fb489c1ff65b46e029e2"
+            + "76ecc43a0afc92c5c0d2a9c9d32952876533");
+
+        /**
+         * This section contains an annotated hex dump of a version 2 CRL with
+         * one extension (cRLNumber). The CRL was issued by OU=NIST; O=gov; C=US
+         * on August 7, 1997; the next scheduled issuance was September 7, 1997.
+         * The CRL includes one revoked certificates: serial number 18 (12 hex),
+         * which was revoked on July 31, 1997 due to keyCompromise.  The CRL
+         * itself is number 18, and it was signed with DSA and SHA-1.
+         */
+        static byte[] crlBin = Hex.Decode(
+            "3081cb30818c020101300906072a8648ce380403302a310b3009060355040613025553310c300a060355040a1303676f76310d300b060355040b13044e495354170d3937303830373030303030305a170d3937303930373030303030305a30223020020112170d3937303733313030303030305a300c300a0603551d1504030a0101a00e300c300a0603551d14040302010c300906072a8648ce380403032f00302c0214224e9f43ba950634f2bb5e65dba68005c03a29470214591a57c982d7022114c3d40b321b9616b11f465a");
+
+        public override void PerformTest()
+        {
+            try
+            {
+                X509CertificateParser certParser = new X509CertificateParser();
+                X509CrlParser crlParser = new X509CrlParser();
+
+                X509Certificate rootCert = certParser.ReadCertificate(rootCertBin);
+                X509Certificate userCert1 = certParser.ReadCertificate(userCert1Bin);
+                X509Certificate userCert2 = certParser.ReadCertificate(userCert2Bin);
+
+                X509Crl crl = crlParser.ReadCrl(crlBin);
+
+                rootCert.Verify(rootCert.GetPublicKey());
+                userCert1.Verify(rootCert.GetPublicKey());
+
+                crl.Verify(rootCert.GetPublicKey());
+
+                if (!crl.IsRevoked(userCert1))
+                {
+                    Fail(this.Name + ": usercert1 not revoked.");
+                }
+
+                if (crl.IsRevoked(userCert2))
+                {
+                    Fail(this.Name + ": usercert2 revoked.");
+                }
+
+            }
+            catch (Exception e)
+            {
+                Fail(this.Name + ": exception - " + e.ToString());
+            }
+        }
+
+		public override String Name
+		{
+			get { return "PkixTest"; }
+        }
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new PkixTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/RSATest.cs b/BouncyCastle.AxCrypt/test/src/test/RSATest.cs
new file mode 100644
index 0000000..a765ff1
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/RSATest.cs
@@ -0,0 +1,685 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Nist;
+using Org.BouncyCastle.Asn1.Oiw;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Asn1.TeleTrust;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class RsaTest
+		: SimpleTest
+	{
+		/**
+		* a fake random number generator - we just want to make sure the random numbers
+		* aren't random so that we get the same output, while still getting to test the
+		* key generation facilities.
+		*/
+		// TODO Use FixedSecureRandom instead?
+		private class MyFixedSecureRandom
+			: SecureRandom
+		{
+			byte[] seed =
+			{
+				(byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+				(byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+				(byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+				(byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+			};
+
+			public override void NextBytes(
+				byte[] bytes)
+			{
+				int offset = 0;
+
+				while ((offset + seed.Length) < bytes.Length)
+				{
+					seed.CopyTo(bytes, offset);
+					offset += seed.Length;
+				}
+
+				Array.Copy(seed, 0, bytes, offset, bytes.Length - offset);
+			}
+		}
+
+		private static readonly byte[] seed =
+		{
+			(byte)0xaa, (byte)0xfd, (byte)0x12, (byte)0xf6, (byte)0x59,
+			(byte)0xca, (byte)0xe6, (byte)0x34, (byte)0x89, (byte)0xb4,
+			(byte)0x79, (byte)0xe5, (byte)0x07, (byte)0x6d, (byte)0xde,
+			(byte)0xc2, (byte)0xf0, (byte)0x6c, (byte)0xb5, (byte)0x8f
+		};
+
+		private RsaKeyParameters pubKeySpec = new RsaKeyParameters(
+			false,
+			new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+			new BigInteger("11", 16));
+
+		private RsaPrivateCrtKeyParameters privKeySpec = new RsaPrivateCrtKeyParameters(
+			new BigInteger("b4a7e46170574f16a97082b22be58b6a2a629798419be12872a4bdba626cfae9900f76abfb12139dce5de56564fab2b6543165a040c606887420e33d91ed7ed7", 16),
+			new BigInteger("11", 16),
+			new BigInteger("9f66f6b05410cd503b2709e88115d55daced94d1a34d4e32bf824d0dde6028ae79c5f07b580f5dce240d7111f7ddb130a7945cd7d957d1920994da389f490c89", 16),
+			new BigInteger("c0a0758cdf14256f78d4708c86becdead1b50ad4ad6c5c703e2168fbf37884cb", 16),
+			new BigInteger("f01734d7960ea60070f1b06f2bb81bfac48ff192ae18451d5e56c734a5aab8a5", 16),
+			new BigInteger("b54bb9edff22051d9ee60f9351a48591b6500a319429c069a3e335a1d6171391", 16),
+			new BigInteger("d3d83daf2a0cecd3367ae6f8ae1aeb82e9ac2f816c6fc483533d8297dd7884cd", 16),
+			new BigInteger("b8f52fc6f38593dabb661d3f50f8897f8106eee68b1bce78a95b132b4e5b5d19", 16));
+
+		private RsaKeyParameters isoPubKeySpec = new RsaKeyParameters(
+			false,
+			new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16),
+			new BigInteger("03", 16));
+
+		private RsaKeyParameters isoPrivKeySpec = new RsaKeyParameters(
+			true,
+			new BigInteger("0100000000000000000000000000000000bba2d15dbb303c8a21c5ebbcbae52b7125087920dd7cdf358ea119fd66fb064012ec8ce692f0a0b8e8321b041acd40b7", 16),
+			new BigInteger("2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaac9f0783a49dd5f6c5af651f4c9d0dc9281c96a3f16a85f9572d7cc3f2d0f25a9dbf1149e4cdc32273faadd3fda5dcda7", 16));
+
+		internal static RsaKeyParameters pub2048KeySpec = new RsaKeyParameters(
+			false,
+			new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af6 [...]
+			new BigInteger("10001", 16));
+
+		internal static RsaPrivateCrtKeyParameters priv2048KeySpec = new RsaPrivateCrtKeyParameters(
+			new BigInteger("a7295693155b1813bb84877fb45343556e0568043de5910872a3a518cc11e23e2db74eaf4545068c4e3d258a2718fbacdcc3eafa457695b957e88fbf110aed049a992d9c430232d02f3529c67a3419935ea9b569f85b1bcd37de6b899cd62697e843130ff0529d09c97d813cb15f293751ff56f943fbdabb63971cc7f4f6d5bff1594416b1f5907bde5a84a44f9802ef29b43bda1960f948f8afb8766c1ab80d32eec88ed66d0b65aebe44a6d0b3c5e0ab051aaa1b912fbcc17b8e751ddecc5365b6db6dab0020c3057db4013a51213a5798a3aab67985b0f4d88627a54a0f3f0285fbcb4afdfeb65cb153af6 [...]
+			new BigInteger("10001", 16),
+			new BigInteger("65dad56ac7df7abb434e4cb5eeadb16093aa6da7f0033aad3815289b04757d32bfee6ade7749c8e4a323b5050a2fb9e2a99e23469e1ed4ba5bab54336af20a5bfccb8b3424cc6923db2ffca5787ed87aa87aa614cd04cedaebc8f623a2d2063017910f436dff18bb06f01758610787f8b258f0a8efd8bd7de30007c47b2a1031696c7d6523bc191d4d918927a7e0b09584ed205bd2ff4fc4382678df82353f7532b3bbb81d69e3f39070aed3fb64fce032a089e8e64955afa5213a6eb241231bd98d702fba725a9b205952fda186412d9e0d9344d2998c455ad8c2bae85ee672751466d5288304032b5b7e02f [...]
+			new BigInteger("d4fd9ac3474fb83aaf832470643609659e511b322632b239b688f3cd2aad87527d6cf652fb9c9ca67940e84789444f2e99b0cb0cfabbd4de95396106c865f38e2fb7b82b231260a94df0e01756bf73ce0386868d9c41645560a81af2f53c18e4f7cdf3d51d80267372e6e0216afbf67f655c9450769cca494e4f6631b239ce1b", 16),
+			new BigInteger("c8eaa0e2a1b3a4412a702bccda93f4d150da60d736c99c7c566fdea4dd1b401cbc0d8c063daaf0b579953d36343aa18b33dbf8b9eae94452490cc905245f8f7b9e29b1a288bc66731a29e1dd1a45c9fd7f8238ff727adc49fff73991d0dc096206b9d3a08f61e7462e2b804d78cb8c5eccdb9b7fbd2ad6a8fea46c1053e1be75", 16),
+			new BigInteger("10edcb544421c0f9e123624d1099feeb35c72a8b34e008ac6fa6b90210a7543f293af4e5299c8c12eb464e70092805c7256e18e5823455ba0f504d36f5ccacac1b7cd5c58ff710f9c3f92646949d88fdd1e7ea5fed1081820bb9b0d2a8cd4b093fecfdb96dabd6e28c3a6f8c186dc86cddc89afd3e403e0fcf8a9e0bcb27af0b", 16),
+			new BigInteger("97fc25484b5a415eaa63c03e6efa8dafe9a1c8b004d9ee6e80548fefd6f2ce44ee5cb117e77e70285798f57d137566ce8ea4503b13e0f1b5ed5ca6942537c4aa96b2a395782a4cb5b58d0936e0b0fa63b1192954d39ced176d71ef32c6f42c84e2e19f9d4dd999c2151b032b97bd22aa73fd8c5bcd15a2dca4046d5acc997021", 16),
+			new BigInteger("4bb8064e1eff7e9efc3c4578fcedb59ca4aef0993a8312dfdcb1b3decf458aa6650d3d0866f143cbf0d3825e9381181170a0a1651eefcd7def786b8eb356555d9fa07c85b5f5cbdd74382f1129b5e36b4166b6cc9157923699708648212c484958351fdc9cf14f218dbe7fbf7cbd93a209a4681fe23ceb44bab67d66f45d1c9d", 16));
+
+		public override void PerformTest()
+		{
+			byte[] input = new byte[]
+			{ (byte)0x54, (byte)0x85, (byte)0x9b, (byte)0x34, (byte)0x2c, (byte)0x49, (byte)0xea, (byte)0x2a };
+			byte[][] output = new byte[][]
+			{
+				Hex.Decode("8b427f781a2e59dd9def386f1956b996ee07f48c96880e65a368055ed8c0a8831669ef7250b40918b2b1d488547e72c84540e42bd07b03f14e226f04fbc2d929"),
+				Hex.Decode("2ec6e1a1711b6c7b8cd3f6a25db21ab8bb0a5f1d6df2ef375fa708a43997730ffc7c98856dbbe36edddcdd1b2d2a53867d8355af94fea3aeec128da908e08f4c"),
+				Hex.Decode("0850ac4e5a8118323200c8ed1e5aaa3d5e635172553ccac66a8e4153d35c79305c4440f11034ab147fccce21f18a50cf1c0099c08a577eb68237a91042278965"),
+				Hex.Decode("1c9649bdccb51056751fe43837f4eb43bada472accf26f65231666d5de7d11950d8379b3596dfdf75c6234274896fa8d18ad0865d3be2ac4d6687151abdf01e93941dcef18fa63186c9351d1506c89d09733c5ff4304208c812bdd21a50f56fde115e629e0e973721c9fcc87e89295a79853dee613962a0b2f2fc57163fd99057a3c776f13c20c26407eb8863998d7e53b543ba8d0a295a9a68d1a149833078c9809ad6a6dad7fc22a95ad615a73138c54c018f40d99bf8eeecd45f5be526f2d6b01aeb56381991c1ab31a2e756f15e052b9cd5638b2eff799795c5bae493307d5eb9f8c21d438de131fe505a4e7 [...]
+				Hex.Decode("4c4afc0c24dddaedd4f9a3b23be30d35d8e005ffd36b3defc5d18acc830c3ed388ce20f43a00e614fd087c814197bc9fc2eff9ad4cc474a7a2ef3ed9c0f0a55eb23371e41ee8f2e2ed93ea3a06ca482589ab87e0d61dcffda5eea1241408e43ea1108726cdb87cc3aa5e9eaaa9f72507ca1352ac54a53920c94dccc768147933d8c50aefd9d1da10522a40133cd33dbc0524669e70f771a88d65c4716d471cd22b08b9f01f24e4e9fc7ffbcfa0e0a7aed47b345826399b26a73be112eb9c5e06fc6742fc3d0ef53d43896403c5105109cfc12e6deeaf4a48ba308e039774b9bdb31a9b9e133c81c321630cf0b4b2 [...]
+				Hex.Decode("06b5b26bd13515f799e5e37ca43cace15cd82fd4bf36b25d285a6f0998d97c8cb0755a28f0ae66618b1cd03e27ac95eaaa4882bc6dc0078cd457d4f7de4154173a9c7a838cfc2ac2f74875df462aae0cfd341645dc51d9a01da9bdb01507f140fa8a016534379d838cc3b2a53ac33150af1b242fc88013cb8d914e66c8182864ee6de88ce2879d4c05dd125409620a96797c55c832fb2fb31d4310c190b8ed2c95fdfda2ed87f785002faaec3f35ec05cf70a3774ce185e4882df35719d582dd55ac31257344a9cba95189dcbea16e8c6cb7a235a0384bc83b6183ca8547e670fe33b1b91725ae0c250c9eca7b5b [...]
+				Hex.Decode("135f1be3d045526235bf9d5e43499d4ee1bfdf93370769ae56e85dbc339bc5b7ea3bee49717497ee8ac3f7cd6adb6fc0f17812390dcd65ac7b87fef7970d9ff9"),
+				Hex.Decode("03c05add1e030178c352face07cafc9447c8f369b8f95125c0d311c16b6da48ca2067104cce6cd21ae7b163cd18ffc13001aecebdc2eb02b9e92681f84033a98"),
+				Hex.Decode("00319bb9becb49f3ed1bca26d0fcf09b0b0a508e4d0bd43b350f959b72cd25b3af47d608fdcd248eada74fbe19990dbeb9bf0da4b4e1200243a14e5cab3f7e610c")
+			};
+			SecureRandom rand = new MyFixedSecureRandom();
+
+//			KeyFactory fact = KeyFactory.GetInstance("RSA");
+//
+//			PrivateKey  privKey = fact.generatePrivate(privKeySpec);
+//			PublicKey   pubKey = fact.generatePublic(pubKeySpec);
+			AsymmetricKeyParameter privKey = privKeySpec;
+			AsymmetricKeyParameter pubKey = pubKeySpec;
+
+//			PrivateKey  priv2048Key = fact.generatePrivate(priv2048KeySpec);
+//			PublicKey   pub2048Key = fact.generatePublic(pub2048KeySpec);
+			AsymmetricKeyParameter priv2048Key = priv2048KeySpec;
+			AsymmetricKeyParameter pub2048Key = pub2048KeySpec;
+
+			//
+			// No Padding
+			//
+//			Cipher c = Cipher.GetInstance("RSA");
+			IBufferedCipher c = CipherUtilities.GetCipher("RSA");
+
+//			c.init(Cipher.ENCRYPT_MODE, pubKey, rand);
+			c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand));
+
+			byte[] outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[0]))
+			{
+				Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			c.init(Cipher.DECRYPT_MODE, privKey);
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			// No Padding - incremental
+			//
+//			c = Cipher.GetInstance("RSA");
+			c = CipherUtilities.GetCipher("RSA");
+
+//			c.init(Cipher.ENCRYPT_MODE, pubKey, rand);
+			c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand));
+
+			c.ProcessBytes(input);
+
+			outBytes = c.DoFinal();
+
+			if (!AreEqual(outBytes, output[0]))
+			{
+				Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			c.init(Cipher.DECRYPT_MODE, privKey);
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			// No Padding - incremental - explicit use of NONE in mode.
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/NoPadding");
+
+//			c.init(Cipher.ENCRYPT_MODE, pubKey, rand);
+			c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand));
+			
+			c.ProcessBytes(input);
+
+			outBytes = c.DoFinal();
+
+			if (!AreEqual(outBytes, output[0]))
+			{
+				Fail("NoPadding test failed on encrypt expected " + Hex.ToHexString(output[0]) + " got " + Hex.ToHexString(outBytes));
+			}
+			
+//			c.init(Cipher.DECRYPT_MODE, privKey);
+			c.Init(false, privKey);
+			
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("NoPadding test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			// No Padding - maximum.Length
+			//
+			c = CipherUtilities.GetCipher("RSA");
+
+			byte[] modBytes = ((RsaKeyParameters) pubKey).Modulus.ToByteArray();
+
+			byte[] maxInput = new byte[modBytes.Length - 1];
+
+			maxInput[0] |= 0x7f;
+
+			c.Init(true, pubKey);// new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(maxInput);
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, maxInput))
+			{
+				Fail("NoPadding test failed on decrypt expected "
+					+ Hex.ToHexString(maxInput) + " got "
+					+ Hex.ToHexString(outBytes));
+			}
+
+			//
+			// PKCS1 V 1.5
+			//
+			c = CipherUtilities.GetCipher("RSA//PKCS1Padding");
+
+			c.Init(true, new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[1]))
+			{
+				Fail("PKCS1 test failed on encrypt expected " + Hex.ToHexString(output[1]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("PKCS1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			// PKCS1 V 1.5 - NONE
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/PKCS1Padding");
+
+			c.Init(true, new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[1]))
+			{
+				Fail("PKCS1 test failed on encrypt expected " + Hex.ToHexString(output[1]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("PKCS1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+			
+			//
+			// OAEP - SHA1
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding");
+
+			c.Init(true, new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[2]))
+			{
+				Fail("OAEP test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding");
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("OAEP test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+	        // TODO
+//			AlgorithmParameters oaepP = c.getParameters();
+	        byte[] rop = new RsaesOaepParameters(
+					new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance),
+					new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance)),
+					new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded(), rop.getEncoded()))
+//			{
+//				Fail("OAEP test failed default sha-1 parameters");
+//			}
+
+			//
+			// OAEP - SHA224
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA224AndMGF1Padding");
+
+			c.Init(true, new ParametersWithRandom(pub2048Key, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[3]))
+			{
+				Fail("OAEP SHA-224 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, priv2048Key);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("OAEP SHA-224 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			oaepP = c.getParameters();
+			rop = new RsaesOaepParameters(
+				new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha224, DerNull.Instance)),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded(), rop.getEncoded())
+//			{
+//				Fail("OAEP test failed default sha-224 parameters");
+//			}
+
+			//
+			// OAEP - SHA 256
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA256AndMGF1Padding");
+
+			c.Init(true, new ParametersWithRandom(pub2048Key, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[4]))
+			{
+				Fail("OAEP SHA-256 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, priv2048Key);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("OAEP SHA-256 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			oaepP = c.getParameters();
+			rop = new RsaesOaepParameters(
+				new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha256, DerNull.Instance)),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded(), rop.getEncoded())
+//			{
+//				Fail("OAEP test failed default sha-256 parameters");
+//			}
+
+			//
+			// OAEP - SHA 384
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA384AndMGF1Padding");
+
+			c.Init(true, new ParametersWithRandom(pub2048Key, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[5]))
+			{
+				Fail("OAEP SHA-384 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, priv2048Key);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("OAEP SHA-384 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			oaepP = c.getParameters();
+			rop = new RsaesOaepParameters(
+				new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(NistObjectIdentifiers.IdSha384, DerNull.Instance)),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded(), rop.getEncoded())
+//			{
+//				Fail("OAEP test failed default sha-384 parameters");
+//			}
+
+			//
+			// OAEP - MD5
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithMD5AndMGF1Padding");
+
+			c.Init(true, new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(input);
+
+			if (!AreEqual(outBytes, output[6]))
+			{
+				Fail("OAEP MD5 test failed on encrypt expected " + Hex.ToHexString(output[2]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("OAEP MD5 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+//			oaepP = c.getParameters();
+			rop = new RsaesOaepParameters(
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5, DerNull.Instance),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(PkcsObjectIdentifiers.MD5, DerNull.Instance)),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[0]))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded(), rop.getEncoded())
+//			{
+//				Fail("OAEP test failed default md5 parameters");
+//			}
+
+			//
+			// OAEP - SHA1 with default parameters
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding");
+
+			// TODO
+//			c.init(Cipher.ENCRYPT_MODE, pubKey, OAEPParameterSpec.DEFAULT, rand);
+//
+//			outBytes = c.DoFinal(input);
+//
+//			if (!AreEqual(outBytes, output[2]))
+//			{
+//				Fail("OAEP test failed on encrypt expected " + Encoding.ASCII.GetString(Hex.Encode(output[2])) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes)));
+//			}
+//
+//			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding");
+//
+//			c.Init(false, privKey);
+//
+//			outBytes = c.DoFinal(outBytes);
+//
+//			if (!AreEqual(outBytes, input))
+//			{
+//				Fail("OAEP test failed on decrypt expected " + Encoding.ASCII.GetString(Hex.Encode(input)) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes)));
+//			}
+//
+//			oaepP = c.getParameters();
+//
+//			if (!AreEqual(oaepP.getEncoded(), new byte[] { 0x30, 0x00 }))
+//			{
+//				Fail("OAEP test failed default parameters");
+//			}
+
+			//
+			// OAEP - SHA1 with specified string
+			//
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPPadding");
+
+			// TODO
+//			c.init(Cipher.ENCRYPT_MODE, pubKey, new OAEPParameterSpec("SHA1", "MGF1", new MGF1ParameterSpec("SHA1"), new PSource.PSpecified(new byte[] { 1, 2, 3, 4, 5 })), rand);
+//
+//			outBytes = c.DoFinal(input);
+//
+//			oaepP = c.getParameters();
+			rop = new RsaesOaepParameters(
+				new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdMgf1, new AlgorithmIdentifier(OiwObjectIdentifiers.IdSha1, DerNull.Instance)),
+				new AlgorithmIdentifier(PkcsObjectIdentifiers.IdPSpecified, new DerOctetString(new byte[] { 1, 2, 3, 4, 5 }))).GetEncoded();
+
+//			if (!AreEqual(oaepP.getEncoded())
+//			{
+//				Fail("OAEP test failed changed sha-1 parameters");
+//			}
+//
+//			if (!AreEqual(outBytes, output[7]))
+//			{
+//				Fail("OAEP test failed on encrypt expected " + Encoding.ASCII.GetString(Hex.Encode(output[2])) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes)));
+//			}
+
+			c = CipherUtilities.GetCipher("RSA/NONE/OAEPWithSHA1AndMGF1Padding");
+
+	        // TODO
+//			c.init(Cipher.DECRYPT_MODE, privKey, oaepP);
+//
+//			outBytes = c.DoFinal(outBytes);
+//
+//			if (!AreEqual(outBytes, input))
+//			{
+//				Fail("OAEP test failed on decrypt expected " + Encoding.ASCII.GetString(Hex.Encode(input)) + " got " + Encoding.ASCII.GetString(Hex.Encode(outBytes)));
+//			}
+
+			//
+			// iso9796-1
+			//
+			byte[] isoInput =  Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+//			PrivateKey  isoPrivKey = fact.generatePrivate(isoPrivKeySpec);
+//			PublicKey   isoPubKey = fact.generatePublic(isoPubKeySpec);
+			AsymmetricKeyParameter isoPrivKey = isoPrivKeySpec;
+			AsymmetricKeyParameter isoPubKey = isoPubKeySpec;
+
+			c = CipherUtilities.GetCipher("RSA/NONE/ISO9796-1Padding");
+
+			c.Init(true, isoPrivKey);
+
+			outBytes = c.DoFinal(isoInput);
+
+			if (!AreEqual(outBytes, output[8]))
+			{
+				Fail("ISO9796-1 test failed on encrypt expected " + Hex.ToHexString(output[3]) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			c.Init(false, isoPubKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, isoInput))
+			{
+				Fail("ISO9796-1 test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			//
+			// generation with parameters test.
+			//
+			IAsymmetricCipherKeyPairGenerator keyPairGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+
+			//
+			// 768 bit RSA with e = 2^16-1
+			//
+			keyPairGen.Init(
+				new RsaKeyGenerationParameters(
+					BigInteger.ValueOf(0x10001),
+					new SecureRandom(),
+					768,
+					25));
+
+			AsymmetricCipherKeyPair kp = keyPairGen.GenerateKeyPair();
+
+			pubKey = kp.Public;
+			privKey = kp.Private;
+
+			c.Init(true, new ParametersWithRandom(pubKey, rand));
+
+			outBytes = c.DoFinal(input);
+
+			c.Init(false, privKey);
+
+			outBytes = c.DoFinal(outBytes);
+
+			if (!AreEqual(outBytes, input))
+			{
+				Fail("key generation test failed on decrypt expected " + Hex.ToHexString(input) + " got " + Hex.ToHexString(outBytes));
+			}
+
+			//
+			// comparison check
+			//
+//			KeyFactory keyFact = KeyFactory.GetInstance("RSA");
+//
+//			RSAPrivateCrtKey crtKey = (RSAPrivateCrtKey)keyFact.translateKey(privKey);
+			RsaPrivateCrtKeyParameters crtKey = (RsaPrivateCrtKeyParameters) privKey;
+
+			if (!privKey.Equals(crtKey))
+			{
+				Fail("private key equality check failed");
+			}
+
+//			RSAPublicKey copyKey = (RSAPublicKey)keyFact.translateKey(pubKey);
+			RsaKeyParameters copyKey = (RsaKeyParameters) pubKey;
+
+			if (!pubKey.Equals(copyKey))
+			{
+				Fail("public key equality check failed");
+			}
+
+			SecureRandom random = new SecureRandom();
+			rawModeTest("SHA1withRSA", X509ObjectIdentifiers.IdSha1, priv2048Key, pub2048Key, random);
+			rawModeTest("MD5withRSA", PkcsObjectIdentifiers.MD5, priv2048Key, pub2048Key, random);
+			rawModeTest("RIPEMD128withRSA", TeleTrusTObjectIdentifiers.RipeMD128, priv2048Key, pub2048Key, random);
+		}
+		
+		private void rawModeTest(string sigName, DerObjectIdentifier digestOID,
+			AsymmetricKeyParameter privKey, AsymmetricKeyParameter pubKey, SecureRandom random)
+		{
+			byte[] sampleMessage = new byte[1000 + random.Next() % 100];
+			random.NextBytes(sampleMessage);
+
+			ISigner normalSig = SignerUtilities.GetSigner(sigName);
+			normalSig.Init(true, privKey);
+			normalSig.BlockUpdate(sampleMessage, 0, sampleMessage.Length);
+			byte[] normalResult = normalSig.GenerateSignature();
+			
+			byte[] hash = DigestUtilities.CalculateDigest(digestOID.Id, sampleMessage);
+			byte[] digInfo = derEncode(digestOID, hash);
+			
+			ISigner rawSig = SignerUtilities.GetSigner("RSA");
+			rawSig.Init(true, privKey);
+			rawSig.BlockUpdate(digInfo, 0, digInfo.Length);
+			byte[] rawResult = rawSig.GenerateSignature();
+			
+			if (!Arrays.AreEqual(normalResult, rawResult))
+			{
+				Fail("raw mode signature differs from normal one");
+			}
+
+			rawSig.Init(false, pubKey);
+			rawSig.BlockUpdate(digInfo, 0, digInfo.Length);
+
+			if (!rawSig.VerifySignature(rawResult))
+			{
+				Fail("raw mode signature verification failed");
+			}
+		}
+
+		private byte[] derEncode(DerObjectIdentifier oid, byte[] hash)
+		{
+			AlgorithmIdentifier algId = new AlgorithmIdentifier(oid, DerNull.Instance);
+			DigestInfo dInfo = new DigestInfo(algId, hash);
+
+			return dInfo.GetEncoded(Asn1Encodable.Der);
+		}
+		
+		public override string Name
+		{
+			get { return "RSATest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new RsaTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/RegressionTest.cs b/BouncyCastle.AxCrypt/test/src/test/RegressionTest.cs
new file mode 100644
index 0000000..0ffde72
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/RegressionTest.cs
@@ -0,0 +1,80 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+    public class RegressionTest
+    {
+		// These tests were ported from org.bouncycastle.jce.provider.test in Java build
+        public static ITest[] tests = new ITest[]
+		{
+			new FipsDesTest(),
+			new DesEdeTest(),
+			new AesTest(),
+			new CamelliaTest(),
+			new SeedTest(),
+			new AesSicTest(),
+			new Gost28147Test(),
+			new PbeTest(),
+			new BlockCipherTest(),
+			new MacTest(),
+			new HMacTest(),
+//			new SealedTest(),
+			new RsaTest(),
+			new DHTest(),
+			new DsaTest(),
+//			new ImplicitlyCaTest(),
+			new ECNRTest(),
+			new ECDsa5Test(),
+			new Gost3410Test(),
+			new ElGamalTest(),
+			new IesTest(),
+			new SigTest(),
+			new AttrCertTest(),
+			new CertTest(),
+			new Pkcs10CertRequestTest(),
+			new EncryptedPrivateKeyInfoTest(),  // Also in Org.BouncyCastle.Pkcs.Tests
+//			new KeyStoreTest(),
+//			new Pkcs12StoreTest(), // Already in Org.BouncyCastle.Pkcs.Tests
+			new DigestTest(),
+			new PssTest(),
+			new WrapTest(),
+//			new DoFinalTest(),
+			new CipherStreamTest(),
+			new NamedCurveTest(),
+			new PkixTest(),
+//			new NetscapeCertRequestTest(),
+			new X509StoreTest(),
+//			new X509StreamParserTest(),
+			new X509CertificatePairTest(),
+			new CertPathTest(),
+//			new CertStoreTest(),
+			new CertPathValidatorTest(),
+			new CertPathBuilderTest(),
+			new ECEncodingTest(),
+//			new AlgorithmParametersTest(),
+			new NistCertPathTest(),
+			new PkixPolicyMappingTest(),
+//			new SlotTwoTest(),
+			new PkixNameConstraintsTest(),
+			new NoekeonTest(),
+			new AttrCertSelectorTest(),
+//			new SerialisationTest(),
+			new MqvTest(),
+			new CMacTest(),
+			new Crl5Test(),
+		};
+
+		public static void Main(
+            string[] args)
+        {
+            for (int i = 0; i != tests.Length; i++)
+            {
+                ITestResult result = tests[i].Perform();
+
+				Console.WriteLine(result);
+            }
+		}
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/SEEDTest.cs b/BouncyCastle.AxCrypt/test/src/test/SEEDTest.cs
new file mode 100644
index 0000000..2b380d5
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/SEEDTest.cs
@@ -0,0 +1,190 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Kisa;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.IO;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Tests
+{
+	/// <summary>Basic test class for SEED</summary>
+	[TestFixture]
+	public class SeedTest
+		: BaseBlockCipherTest
+	{
+		internal static readonly string[] cipherTests =
+		{
+			"128",
+			"28DBC3BC49FFD87DCFA509B11D422BE7",
+			"B41E6BE2EBA84A148E2EED84593C5EC7",
+			"9B9B7BFCD1813CB95D0B3618F40F5122"
+		};
+
+		public SeedTest()
+			: base("SEED")
+		{
+		}
+
+		[Test]
+		public void TestCiphers()
+		{
+			for (int i = 0; i != cipherTests.Length; i += 4)
+			{
+				doCipherTest(int.Parse(cipherTests[i]),
+					Hex.Decode(cipherTests[i + 1]),
+					Hex.Decode(cipherTests[i + 2]),
+					Hex.Decode(cipherTests[i + 3]));
+			}
+		}
+
+		[Test]
+		public void TestWrap()
+		{
+			byte[] kek1 = Hex.Decode("000102030405060708090a0b0c0d0e0f");
+			byte[] in1 = Hex.Decode("00112233445566778899aabbccddeeff");
+			byte[] out1 = Hex.Decode("bf71f77138b5afea05232a8dad54024e812dc8dd7d132559");
+
+			wrapTest(1, "SEEDWrap", kek1, in1, out1);
+		}
+
+		[Test]
+		public void TestOids()
+		{
+			string[] oids = {
+				KisaObjectIdentifiers.IdSeedCbc.Id
+			};
+
+			string[] names = {
+				"SEED/CBC/PKCS7Padding"
+			};
+
+			oidTest(oids, names, 1);
+		}
+
+		[Test]
+		public void TestWrapOids()
+		{
+			string[] wrapOids = {
+				KisaObjectIdentifiers.IdNpkiAppCmsSeedWrap.Id
+			};
+
+			wrapOidTest(wrapOids, "SEEDWrap");
+		}
+
+		public void doCipherTest(
+			int		strength,
+			byte[]	keyBytes,
+			byte[]	input,
+			byte[]	output)
+		{
+			KeyParameter key = ParameterUtilities.CreateKeyParameter("SEED", keyBytes);
+
+			IBufferedCipher inCipher = CipherUtilities.GetCipher("SEED/ECB/NoPadding");
+			IBufferedCipher outCipher = CipherUtilities.GetCipher("SEED/ECB/NoPadding");
+
+			try
+			{
+				outCipher.Init(true, key);
+			}
+			catch (Exception e)
+			{
+				Fail("SEED failed initialisation - " + e.ToString(), e);
+			}
+
+			try
+			{
+				inCipher.Init(false, key);
+			}
+			catch (Exception e)
+			{
+				Fail("SEED failed initialisation - " + e.ToString(), e);
+			}
+
+			//
+			// encryption pass
+			//
+			MemoryStream bOut = new MemoryStream();
+			CipherStream cOut = new CipherStream(bOut, null, outCipher);
+
+			try
+			{
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+					cOut.WriteByte(input[i]);
+				}
+				cOut.Write(input, input.Length / 2, input.Length - input.Length / 2);
+				cOut.Close();
+			}
+			catch (IOException e)
+			{
+				Fail("SEED failed encryption - " + e.ToString(), e);
+			}
+
+			byte[] bytes = bOut.ToArray();
+
+			if (!AreEqual(bytes, output))
+			{
+				Fail("SEED failed encryption - expected "
+					+ Hex.ToHexString(output) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+
+			//
+			// decryption pass
+			//
+			MemoryStream bIn = new MemoryStream(bytes, false);
+			CipherStream cIn = new CipherStream(bIn, inCipher, null);
+
+			try
+			{
+//				DataInputStream dIn = new DataInputStream(cIn);
+				BinaryReader dIn = new BinaryReader(cIn);
+
+				bytes = new byte[input.Length];
+
+				for (int i = 0; i != input.Length / 2; i++)
+				{
+//					bytes[i] = (byte)dIn.read();
+					bytes[i] = dIn.ReadByte();
+				}
+
+				int remaining = bytes.Length - input.Length / 2;
+//				dIn.readFully(bytes, input.Length / 2, remaining);
+				byte[] extra = dIn.ReadBytes(remaining);
+				if (extra.Length < remaining)
+					throw new EndOfStreamException();
+				extra.CopyTo(bytes, input.Length / 2);
+			}
+			catch (Exception e)
+			{
+				Fail("SEED failed encryption - " + e.ToString(), e);
+			}
+
+			if (!AreEqual(bytes, input))
+			{
+				Fail("SEED failed decryption - expected "
+					+ Hex.ToHexString(input) + " got "
+					+ Hex.ToHexString(bytes));
+			}
+		}
+
+		public override void PerformTest()
+		{
+			TestCiphers();
+			TestWrap();
+			TestOids();
+			TestWrapOids();
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SeedTest());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/SigTest.cs b/BouncyCastle.AxCrypt/test/src/test/SigTest.cs
new file mode 100644
index 0000000..803a244
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/SigTest.cs
@@ -0,0 +1,378 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class SigTest
+		: SimpleTest
+	{
+		/**
+		 * signature with a "forged signature" (sig block not at end of plain text)
+		 */
+		private void doTestBadSig(
+			AsymmetricKeyParameter	priv,
+			AsymmetricKeyParameter	pub)
+		{
+			IDigest sha1 = DigestUtilities.GetDigest("SHA1");
+			IBufferedCipher signer = CipherUtilities.GetCipher("RSA//PKCS1Padding");
+
+			signer.Init(true, priv);
+
+			byte[] block = new byte[signer.GetBlockSize()];
+
+			sha1.Update((byte)0);
+
+			byte[] sigHeader = Hex.Decode("3021300906052b0e03021a05000414");
+			Array.Copy(sigHeader, 0, block, 0, sigHeader.Length);
+
+//			byte[] dig = sha1.digest();
+			byte[] dig = DigestUtilities.DoFinal(sha1);
+
+			Array.Copy(dig, 0, block, sigHeader.Length, dig.Length);
+
+			Array.Copy(sigHeader, 0, block,
+				sigHeader.Length + dig.Length, sigHeader.Length);
+
+			byte[] sig = signer.DoFinal(block);
+
+			ISigner verifier = SignerUtilities.GetSigner("SHA1WithRSA");
+
+			verifier.Init(false, pub);
+
+			verifier.Update((byte)0);
+
+			if (verifier.VerifySignature(sig))
+			{
+				Fail("bad signature passed");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			ISigner sig = SignerUtilities.GetSigner("SHA1WithRSAEncryption");
+
+			byte[] data = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
+
+			IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			fact.Init(
+				new RsaKeyGenerationParameters(
+					BigInteger.ValueOf(0x10001),
+					new SecureRandom(),
+					768,
+					25));
+
+			AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair();
+
+			AsymmetricKeyParameter signingKey = keyPair.Private;
+			AsymmetricKeyParameter verifyKey = keyPair.Public;
+
+			doTestBadSig(signingKey, verifyKey);
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			byte[] sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA1 verification failed");
+			}
+
+			sig = SignerUtilities.GetSigner("MD2WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("MD2 verification failed");
+			}
+
+			sig = SignerUtilities.GetSigner("MD5WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("MD5 verification failed");
+			}
+
+			sig = SignerUtilities.GetSigner("RIPEMD160WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("RIPEMD160 verification failed");
+			}
+
+			//
+			// RIPEMD-128
+			//
+			sig = SignerUtilities.GetSigner("RIPEMD128WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("RIPEMD128 verification failed");
+			}
+
+			//
+			// RIPEMD256
+			//
+			sig = SignerUtilities.GetSigner("RIPEMD256WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("RIPEMD256 verification failed");
+			}
+
+			//
+			// SHA-224
+			//
+			sig = SignerUtilities.GetSigner("SHA224WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA224 verification failed");
+			}
+
+			//
+			// SHA-256
+			//
+			sig = SignerUtilities.GetSigner("SHA256WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA256 verification failed");
+			}
+
+			//
+			// SHA-384
+			//
+			sig = SignerUtilities.GetSigner("SHA384WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA384 verification failed");
+			}
+
+			//
+			// SHA-512
+			//
+			sig = SignerUtilities.GetSigner("SHA512WithRSAEncryption");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA512 verification failed");
+			}
+
+			//
+			// ISO Sigs.
+			//
+			sig = SignerUtilities.GetSigner("MD5WithRSA/ISO9796-2");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("MD5/ISO verification failed");
+			}
+
+			sig = SignerUtilities.GetSigner("SHA1WithRSA/ISO9796-2");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("SHA1/ISO verification failed");
+			}
+
+			sig = SignerUtilities.GetSigner("RIPEMD160WithRSA/ISO9796-2");
+
+			sig.Init(true, signingKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			sig.Init(false, verifyKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("RIPEMD160/ISO verification failed");
+			}
+
+			//
+			// standard vector test - B.1.3 RIPEMD160, implicit.
+			//
+			BigInteger  mod = new BigInteger("ffffffff78f6c55506c59785e871211ee120b0b5dd644aa796d82413a47b24573f1be5745b5cd9950f6b389b52350d4e01e90009669a8720bf265a2865994190a661dea3c7828e2e7ca1b19651adc2d5", 16);
+			BigInteger  pub = new BigInteger("03", 16);
+			BigInteger  pri = new BigInteger("2aaaaaaa942920e38120ee965168302fd0301d73a4e60c7143ceb0adf0bf30b9352f50e8b9e4ceedd65343b2179005b2f099915e4b0c37e41314bb0821ad8330d23cba7f589e0f129b04c46b67dfce9d", 16);
+
+//			KeyFactory  f = KeyFactory.getInstance("RSA");
+//			AsymmetricKeyParameter privKey = f.generatePrivate(new RSAPrivateKeySpec(mod, pri));
+//			AsymmetricKeyParameter pubKey = f.generatePublic(new RSAPublicKeySpec(mod, pub));
+			AsymmetricKeyParameter privKey = new RsaKeyParameters(true, mod, pri);
+			AsymmetricKeyParameter pubKey = new RsaKeyParameters(false, mod, pub);
+			byte[] testSig = Hex.Decode("5cf9a01854dbacaec83aae8efc563d74538192e95466babacd361d7c86000fe42dcb4581e48e4feb862d04698da9203b1803b262105104d510b365ee9c660857ba1c001aa57abfd1c8de92e47c275cae");
+
+			data = Hex.Decode("fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210");
+
+			sig = SignerUtilities.GetSigner("RIPEMD160WithRSA/ISO9796-2");
+
+			sig.Init(true, privKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			sigBytes = sig.GenerateSignature();
+
+			if (!AreEqual(testSig, sigBytes))
+			{
+				Fail("SigTest: failed ISO9796-2 generation Test");
+			}
+
+			sig.Init(false, pubKey);
+
+			sig.BlockUpdate(data, 0, data.Length);
+
+			if (!sig.VerifySignature(sigBytes))
+			{
+				Fail("RIPEMD160/ISO verification failed");
+			}
+		}
+
+		public override string Name
+		{
+			get { return "SigTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new SigTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/TestUtilities.cs b/BouncyCastle.AxCrypt/test/src/test/TestUtilities.cs
new file mode 100644
index 0000000..a794212
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/TestUtilities.cs
@@ -0,0 +1,264 @@
+using System;
+using System.Diagnostics;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+
+namespace Org.BouncyCastle.Tests
+{
+	/**
+	 * Test Utils
+	 */
+	internal class TestUtilities
+	{
+		/**
+		 * Create a random 1024 bit RSA key pair
+		 */
+		public static AsymmetricCipherKeyPair GenerateRsaKeyPair()
+		{
+			IAsymmetricCipherKeyPairGenerator kpGen = GeneratorUtilities.GetKeyPairGenerator("RSA");
+
+			kpGen.Init(new KeyGenerationParameters(new SecureRandom(), 1024));
+
+			return kpGen.GenerateKeyPair();
+		}
+
+		public static X509Certificate GenerateRootCert(
+			AsymmetricCipherKeyPair pair)
+		{
+			X509V1CertificateGenerator  certGen = new X509V1CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+			certGen.SetIssuerDN(new X509Name("CN=Test CA Certificate"));
+			certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			certGen.SetSubjectDN(new X509Name("CN=Test CA Certificate"));
+			certGen.SetPublicKey(pair.Public);
+			certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+			return certGen.Generate(pair.Private);
+		}
+
+		public static X509Certificate GenerateIntermediateCert(
+			AsymmetricKeyParameter	intKey,
+			AsymmetricKeyParameter	caKey,
+			X509Certificate			caCert)
+		{
+			X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+			certGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert));
+			certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			certGen.SetSubjectDN(new X509Name("CN=Test Intermediate Certificate"));
+			certGen.SetPublicKey(intKey);
+			certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+			certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
+			certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(intKey));
+			certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(0));
+			certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyCertSign | KeyUsage.CrlSign));
+
+			return certGen.Generate(caKey);
+		}
+
+		public static X509Certificate GenerateEndEntityCert(
+			AsymmetricKeyParameter entityKey,
+			AsymmetricKeyParameter caKey,
+			X509Certificate caCert)
+		{
+			X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+			certGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert));
+			certGen.SetNotBefore(DateTime.UtcNow.AddSeconds(-50));
+			certGen.SetNotAfter(DateTime.UtcNow.AddSeconds(50));
+			certGen.SetSubjectDN(new X509Name("CN=Test End Certificate"));
+			certGen.SetPublicKey(entityKey);
+			certGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+			certGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
+			certGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(entityKey));
+			certGen.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(false));
+			certGen.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.DigitalSignature | KeyUsage.KeyEncipherment));
+
+			return certGen.Generate(caKey);
+		}
+
+		public static X509Crl CreateCrl(
+			X509Certificate			caCert, 
+			AsymmetricKeyParameter	caKey, 
+			BigInteger				serialNumber)
+		{
+			X509V2CrlGenerator	crlGen = new X509V2CrlGenerator();
+			DateTime			now = DateTime.UtcNow;
+//			BigInteger			revokedSerialNumber = BigInteger.Two;
+
+			crlGen.SetIssuerDN(PrincipalUtilities.GetSubjectX509Principal(caCert));
+
+			crlGen.SetThisUpdate(now);
+			crlGen.SetNextUpdate(now.AddSeconds(100));
+			crlGen.SetSignatureAlgorithm("SHA256WithRSAEncryption");
+
+			crlGen.AddCrlEntry(serialNumber, now, CrlReason.PrivilegeWithdrawn);
+
+			crlGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, new AuthorityKeyIdentifierStructure(caCert));
+			crlGen.AddExtension(X509Extensions.CrlNumber, false, new CrlNumber(BigInteger.One));
+
+			return crlGen.Generate(caKey);
+		}
+
+		public static X509Certificate CreateExceptionCertificate(
+			bool exceptionOnEncode)
+		{
+			return new ExceptionCertificate(exceptionOnEncode);
+		}
+
+		private class ExceptionCertificate
+			: X509Certificate
+		{
+			private bool _exceptionOnEncode;
+
+			public ExceptionCertificate(
+				bool exceptionOnEncode)
+			{
+				_exceptionOnEncode = exceptionOnEncode;
+			}
+
+			public override void CheckValidity()
+			{
+				throw new CertificateNotYetValidException();
+			}
+
+			public override void CheckValidity(
+				DateTime date)
+			{
+				throw new CertificateExpiredException();
+			}
+
+			public override int Version
+			{
+				get { return 0; }
+			}
+
+			public override BigInteger SerialNumber
+			{
+				get { return null; }
+			}
+
+			public override X509Name IssuerDN
+			{
+				get { return null; }
+			}
+
+			public override X509Name SubjectDN
+			{
+				get { return null; }
+			}
+
+			public override DateTime NotBefore
+			{
+				get { return DateTime.MaxValue; }
+			}
+
+			public override DateTime NotAfter
+			{
+				get { return DateTime.MinValue; }
+			}
+
+			public override byte[] GetTbsCertificate()
+			{
+				throw new CertificateEncodingException();
+			}
+
+			public override byte[] GetSignature()
+			{
+				return new byte[0];
+			}
+
+			public override string SigAlgName
+			{
+				get { return null; }
+			}
+
+			public override string SigAlgOid
+			{
+				get { return null; }
+			}
+
+			public override byte[] GetSigAlgParams()
+			{
+				return new byte[0];
+			}
+
+			public override DerBitString IssuerUniqueID
+			{
+				get { return null; }
+			}
+
+			public override DerBitString SubjectUniqueID
+			{
+				get { return null; }
+			}
+
+			public override bool[] GetKeyUsage()
+			{
+				return new bool[0];
+			}
+
+			public override int GetBasicConstraints()
+			{
+				return 0;
+			}
+
+			public override byte[] GetEncoded()
+			{
+				if (_exceptionOnEncode)
+				{
+					throw new CertificateEncodingException();
+				}
+
+				return new byte[0];
+			}
+
+			public override void Verify(
+				AsymmetricKeyParameter key)
+			{
+				throw new CertificateException();
+			}
+
+			public override string ToString()
+			{
+				return null;
+			}
+
+			public override AsymmetricKeyParameter GetPublicKey()
+			{
+				return null;
+			}
+
+			public override ISet GetCriticalExtensionOids()
+			{
+				return null;
+			}
+
+			public override ISet GetNonCriticalExtensionOids()
+			{
+				return null;
+			}
+
+			public override Asn1OctetString GetExtensionValue(
+				DerObjectIdentifier oid)
+			{
+				return null;
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/WrapTest.cs b/BouncyCastle.AxCrypt/test/src/test/WrapTest.cs
new file mode 100644
index 0000000..bb49446
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/WrapTest.cs
@@ -0,0 +1,94 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Pkcs;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class WrapTest
+		: ITest
+	{
+		public ITestResult Perform()
+		{
+			try
+			{
+//				IBufferedCipher cipher = CipherUtilities.GetCipher("DES/ECB/PKCS5Padding");
+				IWrapper cipher = WrapperUtilities.GetWrapper("DES/ECB/PKCS5Padding");
+
+				IAsymmetricCipherKeyPairGenerator fact = GeneratorUtilities.GetKeyPairGenerator("RSA");
+				fact.Init(
+					new RsaKeyGenerationParameters(
+						BigInteger.ValueOf(0x10001),
+						new SecureRandom(),
+						512,
+						25));
+
+				AsymmetricCipherKeyPair keyPair = fact.GenerateKeyPair();
+
+				AsymmetricKeyParameter priKey = keyPair.Private;
+				AsymmetricKeyParameter pubKey = keyPair.Public;
+
+				byte[] priKeyBytes = PrivateKeyInfoFactory.CreatePrivateKeyInfo(priKey).GetDerEncoded();
+
+				CipherKeyGenerator keyGen = GeneratorUtilities.GetKeyGenerator("DES");
+
+//				Key wrapKey = keyGen.generateKey();
+				byte[] wrapKeyBytes = keyGen.GenerateKey();
+				KeyParameter wrapKey = new DesParameters(wrapKeyBytes);
+
+//				cipher.Init(IBufferedCipher.WRAP_MODE, wrapKey);
+				cipher.Init(true, wrapKey);
+//				byte[] wrappedKey = cipher.Wrap(priKey);
+				byte[] wrappedKey = cipher.Wrap(priKeyBytes, 0, priKeyBytes.Length);
+
+//				cipher.Init(IBufferedCipher.UNWRAP_MODE, wrapKey);
+				cipher.Init(false, wrapKey);
+
+//				Key key = cipher.unwrap(wrappedKey, "RSA", IBufferedCipher.PRIVATE_KEY);
+				byte[] unwrapped = cipher.Unwrap(wrappedKey, 0, wrappedKey.Length);
+
+				//if (!Arrays.AreEqual(priKey.getEncoded(), key.getEncoded()))
+				if (!Arrays.AreEqual(priKeyBytes, unwrapped))
+				{
+					return new SimpleTestResult(false, "Unwrapped key does not match");
+				}
+
+				return new SimpleTestResult(true, Name + ": Okay");
+			}
+			catch (Exception e)
+			{
+				return new SimpleTestResult(false, Name + ": exception - " + e.ToString());
+			}
+		}
+
+		public string Name
+		{
+			get { return "WrapTest"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			ITest test = new WrapTest();
+			ITestResult result = test.Perform();
+
+			Console.WriteLine(result);
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/X509CertificatePairTest.cs b/BouncyCastle.AxCrypt/test/src/test/X509CertificatePairTest.cs
new file mode 100644
index 0000000..a83de4c
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/X509CertificatePairTest.cs
@@ -0,0 +1,149 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Security.Certificates;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class X509CertificatePairTest
+		: SimpleTest
+	{
+		public override void PerformTest()
+		{
+			//CertificateFactory cf = CertificateFactory.getInstance("X.509");
+			X509CertificateParser cf = new X509CertificateParser();
+
+			X509Certificate rootCert = (X509Certificate) cf.ReadCertificate(CertPathTest.rootCertBin);
+			X509Certificate interCert = (X509Certificate) cf.ReadCertificate(CertPathTest.interCertBin);
+			X509Certificate finalCert = (X509Certificate) cf.ReadCertificate(CertPathTest.finalCertBin);
+
+			X509CertificatePair pair1 = new X509CertificatePair(rootCert, interCert);
+			X509CertificatePair pair2 = new X509CertificatePair(rootCert, interCert);
+			X509CertificatePair pair3 = new X509CertificatePair(interCert, finalCert);
+			X509CertificatePair pair4 = new X509CertificatePair(rootCert, finalCert);
+			X509CertificatePair pair5 = new X509CertificatePair(rootCert, null);
+			X509CertificatePair pair6 = new X509CertificatePair(rootCert, null);
+			X509CertificatePair pair7 = new X509CertificatePair(null, rootCert);
+			X509CertificatePair pair8 = new X509CertificatePair(null, rootCert);
+
+			if (!pair1.Equals(pair2))
+			{
+				Fail("pair1 pair2 equality test");
+			}
+
+			if (!pair5.Equals(pair6))
+			{
+				Fail("pair1 pair2 equality test");
+			}
+
+			if (!pair7.Equals(pair8))
+			{
+				Fail("pair1 pair2 equality test");
+			}
+
+			if (pair1.Equals(null))
+			{
+				Fail("pair1 null equality test");
+			}
+
+			if (pair1.GetHashCode() != pair2.GetHashCode())
+			{
+				Fail("pair1 pair2 hashCode equality test");
+			}
+
+			if (pair1.Equals(pair3))
+			{
+				Fail("pair1 pair3 inequality test");
+			}
+
+			if (pair1.Equals(pair4))
+			{
+				Fail("pair1 pair4 inequality test");
+			}
+
+			if (pair1.Equals(pair5))
+			{
+				Fail("pair1 pair5 inequality test");
+			}
+
+			if (pair1.Equals(pair7))
+			{
+				Fail("pair1 pair7 inequality test");
+			}
+
+			if (pair5.Equals(pair1))
+			{
+				Fail("pair5 pair1 inequality test");
+			}
+
+			if (pair7.Equals(pair1))
+			{
+				Fail("pair7 pair1 inequality test");
+			}
+
+			if (pair1.Forward != rootCert)
+			{
+				Fail("pair1 forward test");
+			}
+
+			if (pair1.Reverse != interCert)
+			{
+				Fail("pair1 reverse test");
+			}
+
+			if (!AreEqual(pair1.GetEncoded(), pair2.GetEncoded()))
+			{
+				Fail("encoding check");
+			}
+
+			pair4 = new X509CertificatePair(rootCert, TestUtilities.CreateExceptionCertificate(false));
+
+			try
+			{
+				pair4.GetEncoded();
+
+				Fail("no exception on bad GetEncoded()");
+			}
+			catch (CertificateEncodingException)
+			{
+				// expected
+			}
+
+			pair4 = new X509CertificatePair(rootCert, TestUtilities.CreateExceptionCertificate(true));
+
+			try
+			{
+				pair4.GetEncoded();
+
+				Fail("no exception on exception GetEncoded()");
+			}
+			catch (CertificateEncodingException)
+			{
+				// expected
+			}
+		}
+
+		public override string Name
+		{
+			get { return "X509CertificatePair"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new X509CertificatePairTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/X509StoreTest.cs b/BouncyCastle.AxCrypt/test/src/test/X509StoreTest.cs
new file mode 100644
index 0000000..37673b8
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/X509StoreTest.cs
@@ -0,0 +1,335 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests
+{
+	[TestFixture]
+	public class X509StoreTest
+		: SimpleTest
+	{
+		private void certPairTest()
+		{
+			X509CertificateParser certParser = new X509CertificateParser();
+
+			X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin);
+			X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin);
+			X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin);
+
+			// Testing CollectionCertStore generation from List
+			X509CertificatePair pair1 = new X509CertificatePair(rootCert, interCert);
+
+			IList certList = new ArrayList();
+			certList.Add(pair1);
+			certList.Add(new X509CertificatePair(interCert, finalCert));
+
+			IX509Store certStore = X509StoreFactory.Create(
+				"CertificatePair/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			X509CertPairStoreSelector selector = new X509CertPairStoreSelector();
+			X509CertStoreSelector fwSelector = new X509CertStoreSelector();
+
+			fwSelector.SerialNumber = rootCert.SerialNumber;
+			fwSelector.Subject = rootCert.IssuerDN;
+
+			selector.ForwardSelector = fwSelector;
+
+			IList col = new ArrayList(certStore.GetMatches(selector));
+
+			if (col.Count != 1 || !col.Contains(pair1))
+			{
+				Fail("failed pair1 test");
+			}
+
+			col = new ArrayList(certStore.GetMatches(null));
+
+			if (col.Count != 2)
+			{
+				Fail("failed null test");
+			}
+		}
+
+		public override void PerformTest()
+		{
+			X509CertificateParser certParser = new X509CertificateParser();
+			X509CrlParser crlParser = new X509CrlParser();
+
+			X509Certificate rootCert = certParser.ReadCertificate(CertPathTest.rootCertBin);
+			X509Certificate interCert = certParser.ReadCertificate(CertPathTest.interCertBin);
+			X509Certificate finalCert = certParser.ReadCertificate(CertPathTest.finalCertBin);
+			X509Crl rootCrl = crlParser.ReadCrl(CertPathTest.rootCrlBin);
+			X509Crl interCrl = crlParser.ReadCrl(CertPathTest.interCrlBin);
+
+			// Testing CollectionCertStore generation from List
+			IList certList = new ArrayList();
+			certList.Add(rootCert);
+			certList.Add(interCert);
+			certList.Add(finalCert);
+
+			IX509Store certStore = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+
+			// set default to be the same as for SUN X500 name
+			X509Name.DefaultReverse = true;
+
+			// Searching for rootCert by subjectDN
+
+			X509CertStoreSelector targetConstraints = new X509CertStoreSelector();
+			targetConstraints.Subject = PrincipalUtilities.GetSubjectX509Principal(rootCert);
+			IList certs = new ArrayList(certStore.GetMatches(targetConstraints));
+			if (certs.Count != 1 || !certs.Contains(rootCert))
+			{
+				Fail("rootCert not found by subjectDN");
+			}
+
+			// Searching for rootCert by subjectDN encoded as byte
+			targetConstraints = new X509CertStoreSelector();
+			targetConstraints.Subject = PrincipalUtilities.GetSubjectX509Principal(rootCert);
+			certs = new ArrayList(certStore.GetMatches(targetConstraints));
+			if (certs.Count != 1 || !certs.Contains(rootCert))
+			{
+				Fail("rootCert not found by encoded subjectDN");
+			}
+
+			X509Name.DefaultReverse = false;
+
+			// Searching for rootCert by public key encoded as byte
+			targetConstraints = new X509CertStoreSelector();
+			targetConstraints.SubjectPublicKey =
+				SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(rootCert.GetPublicKey());
+			certs = new ArrayList(certStore.GetMatches(targetConstraints));
+			if (certs.Count != 1 || !certs.Contains(rootCert))
+			{
+				Fail("rootCert not found by encoded public key");
+			}
+
+			// Searching for interCert by issuerDN
+			targetConstraints = new X509CertStoreSelector();
+			targetConstraints.Issuer = PrincipalUtilities.GetSubjectX509Principal(rootCert);
+			certs = new ArrayList(certStore.GetMatches(targetConstraints));
+			if (certs.Count != 2)
+			{
+				Fail("did not found 2 certs");
+			}
+			if (!certs.Contains(rootCert))
+			{
+				Fail("rootCert not found");
+			}
+			if (!certs.Contains(interCert))
+			{
+				Fail("interCert not found");
+			}
+
+			// Searching for rootCrl by issuerDN
+			IList crlList = new ArrayList();
+			crlList.Add(rootCrl);
+			crlList.Add(interCrl);
+			IX509Store store = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(crlList));
+
+			X509CrlStoreSelector targetConstraintsCRL = new X509CrlStoreSelector();
+
+			ArrayList issuers = new ArrayList();
+			issuers.Add(rootCrl.IssuerDN);
+			targetConstraintsCRL.Issuers = issuers;
+
+			IList crls = new ArrayList(store.GetMatches(targetConstraintsCRL));
+			if (crls.Count != 1 || !crls.Contains(rootCrl))
+			{
+				Fail("rootCrl not found");
+			}
+
+			crls = new ArrayList(certStore.GetMatches(targetConstraintsCRL));
+			if (crls.Count != 0)
+			{
+				Fail("error using wrong selector (CRL)");
+			}
+			certs = new ArrayList(store.GetMatches(targetConstraints));
+			if (certs.Count != 0)
+			{
+				Fail("error using wrong selector (certs)");
+			}
+			// Searching for attribute certificates
+			X509V2AttributeCertificate attrCert = new X509V2AttributeCertificate(AttrCertTest.attrCert);
+			IX509AttributeCertificate attrCert2 = new X509V2AttributeCertificate(AttrCertTest.certWithBaseCertificateID);
+
+			IList attrList = new ArrayList();
+			attrList.Add(attrCert);
+			attrList.Add(attrCert2);
+			store = X509StoreFactory.Create(
+				"AttributeCertificate/Collection",
+				new X509CollectionStoreParameters(attrList));
+
+			X509AttrCertStoreSelector attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.Holder = attrCert.Holder;
+			if (!attrSelector.Holder.Equals(attrCert.Holder))
+			{
+				Fail("holder get not correct");
+			}
+			IList attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on holder");
+			}
+			attrSelector.Holder = attrCert2.Holder;
+			if (attrSelector.Holder.Equals(attrCert.Holder))
+			{
+				Fail("holder get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert2))
+			{
+				Fail("attrCert2 not found on holder");
+			}
+			attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.Issuer = attrCert.Issuer;
+			if (!attrSelector.Issuer.Equals(attrCert.Issuer))
+			{
+				Fail("issuer get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on issuer");
+			}
+			attrSelector.Issuer = attrCert2.Issuer;
+			if (attrSelector.Issuer.Equals(attrCert.Issuer))
+			{
+				Fail("issuer get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert2))
+			{
+				Fail("attrCert2 not found on issuer");
+			}
+			attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.AttributeCert = attrCert;
+			if (!attrSelector.AttributeCert.Equals(attrCert))
+			{
+				Fail("attrCert get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on attrCert");
+			}
+			attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.SerialNumber = attrCert.SerialNumber;
+			if (!attrSelector.SerialNumber.Equals(attrCert.SerialNumber))
+			{
+				Fail("serial number get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on serial number");
+			}
+			attrSelector = (X509AttrCertStoreSelector)attrSelector.Clone();
+			if (!attrSelector.SerialNumber.Equals(attrCert.SerialNumber))
+			{
+				Fail("serial number get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on serial number");
+			}
+
+			attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotBefore);
+			if (attrSelector.AttributeCertificateValid.Value != attrCert.NotBefore)
+			{
+				Fail("valid get not correct");
+			}
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 1 || !attrs.Contains(attrCert))
+			{
+				Fail("attrCert not found on valid");
+			}
+			attrSelector = new X509AttrCertStoreSelector();
+			attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotBefore.AddMilliseconds(-100));
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 0)
+			{
+				Fail("attrCert found on before");
+			}
+			attrSelector.AttributeCertificateValid = new DateTimeObject(attrCert.NotAfter.AddMilliseconds(100));
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 0)
+			{
+				Fail("attrCert found on after");
+			}
+			attrSelector.SerialNumber = BigInteger.ValueOf(10000);
+			attrs = new ArrayList(store.GetMatches(attrSelector));
+			if (attrs.Count != 0)
+			{
+				Fail("attrCert found on wrong serial number");
+			}
+
+			attrSelector.AttributeCert = null;
+			attrSelector.AttributeCertificateValid = null;
+			attrSelector.Holder = null;
+			attrSelector.Issuer = null;
+			attrSelector.SerialNumber = null;
+			if (attrSelector.AttributeCert != null)
+			{
+				Fail("null attrCert");
+			}
+			if (attrSelector.AttributeCertificateValid != null)
+			{
+				Fail("null attrCertValid");
+			}
+			if (attrSelector.Holder != null)
+			{
+				Fail("null attrCert holder");
+			}
+			if (attrSelector.Issuer != null)
+			{
+				Fail("null attrCert issuer");
+			}
+			if (attrSelector.SerialNumber != null)
+			{
+				Fail("null attrCert serial");
+			}
+
+			attrs = new ArrayList(certStore.GetMatches(attrSelector));
+			if (attrs.Count != 0)
+			{
+				Fail("error using wrong selector (attrs)");
+			}
+
+			certPairTest();
+		}
+
+		public override string Name
+		{
+			get { return "IX509Store"; }
+		}
+
+		public static void Main(
+			string[] args)
+		{
+			RunTest(new X509StoreTest());
+		}
+
+		[Test]
+		public void TestFunction()
+		{
+			string resultText = Perform().ToString();
+
+			Assert.AreEqual(Name + ": Okay", resultText);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/nist/NistCertPathTest.cs b/BouncyCastle.AxCrypt/test/src/test/nist/NistCertPathTest.cs
new file mode 100644
index 0000000..fed98a7
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/nist/NistCertPathTest.cs
@@ -0,0 +1,847 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Pkix;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Extension;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tests.Nist
+{
+	[TestFixture]
+	public class NistCertPathTest
+	{
+		private static readonly string GOOD_CA_CERT = "GoodCACert";
+
+		private static readonly string GOOD_CA_CRL = "GoodCACRL";
+
+		private static readonly string TRUST_ANCHOR_ROOT_CRL = "TrustAnchorRootCRL";
+
+		private static readonly string TRUST_ANCHOR_ROOT_CERTIFICATE = "TrustAnchorRootCertificate";
+
+		private static readonly char[] PKCS12_PASSWORD = "password".ToCharArray();
+
+		private static readonly string ANY_POLICY = "2.5.29.32.0";
+		private static readonly string NIST_TEST_POLICY_1 = "2.16.840.1.101.3.2.1.48.1";
+		private static readonly string NIST_TEST_POLICY_2 = "2.16.840.1.101.3.2.1.48.2";
+		private static readonly string NIST_TEST_POLICY_3 = "2.16.840.1.101.3.2.1.48.3";
+
+		private static IDictionary certs = new Hashtable();
+		private static IDictionary crls = new Hashtable();
+
+		private static ISet noPolicies = new HashSet();
+		private static ISet anyPolicy = new HashSet();
+		private static ISet nistTestPolicy1 = new HashSet();
+		private static ISet nistTestPolicy2 = new HashSet();
+		private static ISet nistTestPolicy3 = new HashSet();
+		private static ISet nistTestPolicy1And2 = new HashSet();
+
+		static NistCertPathTest()
+		{
+			anyPolicy.Add(ANY_POLICY);
+
+			nistTestPolicy1.Add(NIST_TEST_POLICY_1);
+			nistTestPolicy2.Add(NIST_TEST_POLICY_2);
+			nistTestPolicy3.Add(NIST_TEST_POLICY_3);
+			nistTestPolicy1And2.Add(NIST_TEST_POLICY_1);
+			nistTestPolicy1And2.Add(NIST_TEST_POLICY_2);
+
+		}
+
+		[Test]
+		public void TestValidSignaturesTest1()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "ValidCertificatePathTest1EE", GOOD_CA_CERT },
+				new string[] { GOOD_CA_CRL, TRUST_ANCHOR_ROOT_CRL });
+		}
+
+		[Test]
+		public void TestInvalidCASignatureTest2()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "ValidCertificatePathTest1EE", "BadSignedCACert" },
+				new string[] { "BadSignedCACRL", TRUST_ANCHOR_ROOT_CRL },
+				1,
+				"TrustAnchor found but certificate validation failed.");
+		}
+
+		[Test]
+		public void TestInvalidEESignatureTest3()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "InvalidEESignatureTest3EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL },
+				0,
+				"Could not validate certificate signature.");
+		}
+        
+		[Test]
+		public void TestValidDSASignaturesTest4()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "DSACACert", "ValidDSASignaturesTest4EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL" });
+		}
+
+		[Test]
+		// 4.1.5
+		public void TestValidDSAParameterInheritanceTest5()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "DSACACert", "DSAParametersInheritedCACert", "ValidDSAParameterInheritanceTest5EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL", "DSAParametersInheritedCACRL" });
+		}
+
+		[Test]
+		public void TestInvalidDSASignaturesTest6()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "DSACACert", "InvalidDSASignatureTest6EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "DSACACRL" },
+				0,
+				"Could not validate certificate signature.");
+		}
+
+		[Test]
+		public void TestCANotBeforeDateTest1()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "BadnotBeforeDateCACert", "InvalidCAnotBeforeDateTest1EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "BadnotBeforeDateCACRL" },
+				1,
+				"Could not validate certificate: certificate not valid until 20470101120100GMT+00:00");
+		}
+        
+		[Test]
+		public void TestInvalidEENotBeforeDateTest2()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "InvalidEEnotBeforeDateTest2EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL },
+				0,
+				"Could not validate certificate: certificate not valid until 20470101120100GMT+00:00");
+		}
+
+		[Test]
+		public void TestValidPre2000UTCNotBeforeDateTest3()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "Validpre2000UTCnotBeforeDateTest3EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL });
+		}
+
+		[Test]
+		public void TestValidGeneralizedTimeNotBeforeDateTest4()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "ValidGeneralizedTimenotBeforeDateTest4EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL });
+		}
+
+		[Test]
+		public void TestInvalidCANotAfterDateTest5()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "BadnotAfterDateCACert", "InvalidCAnotAfterDateTest5EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "BadnotAfterDateCACRL" },
+				1,
+				"Could not validate certificate: certificate expired on 20020101120100GMT+00:00");
+		}
+
+		[Test]
+		public void TestInvalidEENotAfterDateTest6()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "InvalidEEnotAfterDateTest6EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL },
+				0,
+				"Could not validate certificate: certificate expired on 20020101120100GMT+00:00");
+		}
+
+		[Test]
+		public void TestInvalidValidPre2000UTCNotAfterDateTest7()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "Invalidpre2000UTCEEnotAfterDateTest7EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL },
+				0,
+				"Could not validate certificate: certificate expired on 19990101120100GMT+00:00");
+		}
+
+		[Test]
+		public void TestInvalidNegativeSerialNumberTest15()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "NegativeSerialNumberCACert", "InvalidNegativeSerialNumberTest15EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "NegativeSerialNumberCACRL" },
+				0,
+				"Certificate revocation after Thu Apr 19 14:57:20",
+				"reason: keyCompromise");
+		}
+
+		//
+		// 4.8 Certificate Policies
+		//
+		[Test]
+		public void TestAllCertificatesSamePolicyTest1()
+		{
+			string[] certList = new string[] { GOOD_CA_CERT, "ValidCertificatePathTest1EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				certList,
+				crlList,
+				noPolicies);
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				certList,
+				crlList,
+				nistTestPolicy1);
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				certList,
+				crlList,
+				nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				certList,
+				crlList,
+				nistTestPolicy1And2);
+		}
+
+		[Test]
+		public void TestAllCertificatesNoPoliciesTest2()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "NoPoliciesCACert", "AllCertificatesNoPoliciesTest2EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "NoPoliciesCACRL" });
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { "NoPoliciesCACert", "AllCertificatesNoPoliciesTest2EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, "NoPoliciesCACRL" },
+				noPolicies,
+				1,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest3()
+		{
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" });
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" },
+				noPolicies,
+				1,
+				"No valid policy tree found when one expected.");
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "PoliciesP2subCACert", "DifferentPoliciesTest3EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCACRL" },
+				nistTestPolicy1And2,
+				1,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest4()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "GoodsubCACert", "DifferentPoliciesTest4EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "GoodsubCACRL" },
+				0,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest5()
+		{
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE,
+				new string[] { GOOD_CA_CERT, "PoliciesP2subCA2Cert", "DifferentPoliciesTest5EE" },
+				new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL, "PoliciesP2subCA2CRL" },
+				0,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestOverlappingPoliciesTest6()
+		{
+			string[] certList = new string[] { "PoliciesP1234CACert", "PoliciesP1234subCAP123Cert", "PoliciesP1234subsubCAP123P12Cert", "OverlappingPoliciesTest6EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP1234CACRL", "PoliciesP1234subCAP123CRL", "PoliciesP1234subsubCAP123P12CRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest7()
+		{
+			string[] certList = new string[] { "PoliciesP123CACert", "PoliciesP123subCAP12Cert", "PoliciesP123subsubCAP12P1Cert", "DifferentPoliciesTest7EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL", "PoliciesP123subCAP12CRL", "PoliciesP123subsubCAP12P1CRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList,
+				0,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest8()
+		{
+			string[] certList = new string[] { "PoliciesP12CACert", "PoliciesP12subCAP1Cert", "PoliciesP12subsubCAP1P2Cert", "DifferentPoliciesTest8EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL", "PoliciesP12subCAP1CRL", "PoliciesP12subsubCAP1P2CRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList,
+				1,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest9()
+		{
+			string[] certList = new string[] { "PoliciesP123CACert", "PoliciesP123subCAP12Cert", "PoliciesP123subsubCAP12P2Cert", "PoliciesP123subsubsubCAP12P2P1Cert", "DifferentPoliciesTest9EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL", "PoliciesP123subCAP12CRL", "PoliciesP123subsubCAP2P2CRL", "PoliciesP123subsubsubCAP12P2P1CRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList,
+				1,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestAllCertificatesSamePoliciesTest10()
+		{
+			string[] certList = new string[] { "PoliciesP12CACert", "AllCertificatesSamePoliciesTest10EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2);
+		}
+
+		[Test]
+		public void TestAllCertificatesAnyPolicyTest11()
+		{
+			string[] certList = new string[] { "anyPolicyCACert", "AllCertificatesanyPolicyTest11EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "anyPolicyCACRL" };
+
+			PkixCertPathValidatorResult result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+
+			result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+		}
+
+		[Test]
+		public void TestDifferentPoliciesTest12()
+		{
+			string[] certList = new string[] { "PoliciesP3CACert", "DifferentPoliciesTest12EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP3CACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList,
+				0,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestAllCertificatesSamePoliciesTest13()
+		{
+			string[] certList = new string[] { "PoliciesP123CACert", "AllCertificatesSamePoliciesTest13EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP123CACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy3);
+		}
+
+		[Test]
+		public void TestAnyPolicyTest14()
+		{
+			string[] certList = new string[] { "anyPolicyCACert", "AnyPolicyTest14EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "anyPolicyCACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test]
+		public void TestUserNoticeQualifierTest15()
+		{
+			string[] certList = new string[] { "UserNoticeQualifierTest15EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test]
+		public void TestUserNoticeQualifierTest16()
+		{
+			string[] certList = new string[] { GOOD_CA_CERT, "UserNoticeQualifierTest16EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL };
+
+			PkixCertPathValidatorResult result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+
+			result = DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test] 
+		public void TestUserNoticeQualifierTest17()
+		{
+			string[] certList = new string[] { GOOD_CA_CERT, "UserNoticeQualifierTest17EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, GOOD_CA_CRL };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test]
+		public void TestUserNoticeQualifierTest18()
+		{
+			string[] certList = new string[] { "PoliciesP12CACert", "UserNoticeQualifierTest18EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "PoliciesP12CACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2);
+		}
+
+		[Test]
+		public void TestUserNoticeQualifierTest19()
+		{
+			string[] certList = new string[] { "UserNoticeQualifierTest19EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy2,
+				-1,
+				"Path processing failed on policy.");
+		}
+
+		[Test]
+		public void TestInvalidInhibitPolicyMappingTest1()
+		{
+			string[] certList = new string[] { "inhibitPolicyMapping0CACert", "inhibitPolicyMapping0subCACert", "InvalidinhibitPolicyMappingTest1EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitPolicyMapping0CACRL", "inhibitPolicyMapping0subCACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"No valid policy tree found when one expected.");
+		}
+
+		[Test]
+		public void TestValidInhibitPolicyMappingTest2()
+		{
+			string[] certList = new string[] { "inhibitPolicyMapping1P12CACert", "inhibitPolicyMapping1P12subCACert", "ValidinhibitPolicyMappingTest2EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitPolicyMapping1P12CACRL", "inhibitPolicyMapping1P12subCACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, nistTestPolicy1);
+		}
+
+		// 4.12.7
+		[Test]
+		public void TestValidSelfIssuedInhibitAnyPolicyTest7()
+		{
+			string[] certList = new string[] { "inhibitAnyPolicy1CACert", "inhibitAnyPolicy1SelfIssuedCACert", "inhibitAnyPolicy1subCA2Cert", "ValidSelfIssuedinhibitAnyPolicyTest7EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "inhibitAnyPolicy1CACRL", "inhibitAnyPolicy1subCA2CRL" };
+
+			doBuilderTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, false, false);
+		}
+
+		// 4.4.19
+		[Test]
+		public void TestValidSeparateCertificateandCRLKeysTest19()
+		{
+			string[] certList = new string[] { "SeparateCertificateandCRLKeysCertificateSigningCACert", "SeparateCertificateandCRLKeysCRLSigningCert", "ValidSeparateCertificateandCRLKeysTest19EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "SeparateCertificateandCRLKeysCRL" };
+
+			doBuilderTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null, false, false);
+		}
+
+		[Test]
+		public void TestValidpathLenConstraintTest13()
+		{
+			string[] certList = new string[] { "pathLenConstraint6CACert", "pathLenConstraint6subCA4Cert", "pathLenConstraint6subsubCA41Cert", "pathLenConstraint6subsubsubCA41XCert", "ValidpathLenConstraintTest13EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "pathLenConstraint6CACRL", "pathLenConstraint6subCA4CRL", "pathLenConstraint6subsubCA41CRL", "pathLenConstraint6subsubsubCA41XCRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null);
+		}
+
+		// 4.4.10
+		[Test]
+		public void TestInvalidUnknownCRLExtensionTest10()
+		{
+			string[] certList = new string[] { "UnknownCRLExtensionCACert", "InvalidUnknownCRLExtensionTest10EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "UnknownCRLExtensionCACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"CRL contains unsupported critical extensions.");
+		}
+
+		// 4.14.3
+		[Test]
+		public void TestInvaliddistributionPointTest3()
+		{
+			string[] certList = new string[] { "distributionPoint1CACert", "InvaliddistributionPointTest3EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint1CACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
+		}
+
+		// 4.14.5
+		[Test]
+		public void TestValiddistributionPointTest5()
+		{
+			string[] certList = new string[] { "distributionPoint2CACert", "ValiddistributionPointTest5EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" };
+
+			DoTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null);
+		}
+
+		// 4.14.8
+		[Test]
+		public void TestInvaliddistributionPointTest8()
+		{
+			string[] certList = new string[] { "distributionPoint2CACert", "InvaliddistributionPointTest8EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
+		}
+
+		// 4.14.9
+		[Test]
+		public void TestInvaliddistributionPointTest9()
+		{
+			string[] certList = new string[] { "distributionPoint2CACert", "InvaliddistributionPointTest9EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "distributionPoint2CACRL" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"No match for certificate CRL issuing distribution point name to cRLIssuer CRL distribution point.");
+		}
+
+		// 4.14.17
+		[Test]
+		public void TestInvalidonlySomeReasonsTest17()
+		{
+			string[] certList = new string[] { "onlySomeReasonsCA2Cert", "InvalidonlySomeReasonsTest17EE" };
+			string[] crlList = new string[] { TRUST_ANCHOR_ROOT_CRL, "onlySomeReasonsCA2CRL1", "onlySomeReasonsCA2CRL2" };
+
+			DoExceptionTest(TRUST_ANCHOR_ROOT_CERTIFICATE, certList, crlList, null,
+				0,
+				"Certificate status could not be determined.");
+		}
+
+		// section 4.14: tests 17, 24, 25, 30, 31, 32, 33, 35
+
+		// section 4.15: tests 5, 7
+		private void DoExceptionTest(
+			string		trustAnchor,
+			string[]	certs,
+			string[]	crls,
+			int			index,
+			string		message)
+		{
+			try
+			{
+				DoTest(trustAnchor, certs, crls);
+
+				Assert.Fail("path accepted when should be rejected");
+			}
+			catch (PkixCertPathValidatorException e)
+			{
+				Assert.AreEqual(index, e.Index);
+				Assert.AreEqual(message, e.Message);
+			}
+		}
+
+		private void DoExceptionTest(
+			string		trustAnchor,
+			string[]	certs,
+			string[]	crls,
+			ISet		policies,
+			int			index,
+			string		message)
+		{
+			try
+			{
+				DoTest(trustAnchor, certs, crls, policies);
+				Assert.Fail("path accepted when should be rejected");
+			}
+			catch (PkixCertPathValidatorException e)
+			{
+				Assert.AreEqual(index, e.Index);
+				Assert.AreEqual(message, e.Message);
+			}
+		}
+
+		private void DoExceptionTest(
+			string		trustAnchor,
+			string[]	certs,
+			string[]	crls,
+			int			index,
+			string		mesStart,
+			string		mesEnd)
+		{
+			try
+			{
+				DoTest(trustAnchor, certs, crls);
+
+				Assert.Fail("path accepted when should be rejected");
+			}
+			catch (PkixCertPathValidatorException e)
+			{
+				Assert.AreEqual(index, e.Index);
+				Assert.IsTrue(e.Message.StartsWith(mesStart));
+				Assert.IsTrue(e.Message.EndsWith(mesEnd));
+			}
+		}
+
+		private PkixCertPathValidatorResult DoTest(
+			string trustAnchor,
+			string[] certs,
+			string[] crls)
+		{
+			return DoTest(trustAnchor, certs, crls, null);
+		}
+
+		private PkixCertPathValidatorResult DoTest(
+			string trustAnchor,
+			string[] certs,
+			string[] crls,
+			ISet policies)
+		{
+			ISet trustedSet = new HashSet();
+			trustedSet.Add(GetTrustAnchor(trustAnchor));
+
+			IList x509Certs = new ArrayList();
+			IList x509Crls = new ArrayList();
+			X509Certificate endCert = LoadCert(certs[certs.Length - 1]);
+
+			for (int i = 0; i != certs.Length - 1; i++)
+			{
+				x509Certs.Add(LoadCert(certs[i]));
+			}
+
+			x509Certs.Add(endCert);
+
+			PkixCertPath certPath = new PkixCertPath(x509Certs);
+
+			for (int i = 0; i != crls.Length; i++)
+			{
+				x509Crls.Add(LoadCrl(crls[i]));
+			}
+
+			IX509Store x509CertStore = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(x509Certs));
+			IX509Store x509CrlStore = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(x509Crls));
+
+//			CertPathValidator validator = CertPathValidator.GetInstance("PKIX");
+			PkixCertPathValidator validator = new PkixCertPathValidator();
+			PkixParameters parameters = new PkixParameters(trustedSet);
+
+			parameters.AddStore(x509CertStore);
+			parameters.AddStore(x509CrlStore);
+			parameters.IsRevocationEnabled = true;
+
+			if (policies != null)
+			{
+				parameters.IsExplicitPolicyRequired = true;
+				parameters.SetInitialPolicies(policies);
+			}
+
+			// Perform validation as of this date since test certs expired
+			parameters.Date = new DateTimeObject(DateTime.Parse("1/1/2011"));
+
+			return validator.Validate(certPath, parameters);
+		}
+
+		private PkixCertPathBuilderResult doBuilderTest(
+			string		trustAnchor,
+			string[]	certs,
+			string[]	crls,
+			ISet		initialPolicies,
+			bool		policyMappingInhibited,
+			bool		anyPolicyInhibited)
+		{
+			ISet trustedSet = new HashSet();
+			trustedSet.Add(GetTrustAnchor(trustAnchor));
+
+			IList x509Certs = new ArrayList();
+			IList x509Crls = new ArrayList();
+			X509Certificate endCert = LoadCert(certs[certs.Length - 1]);
+
+			for (int i = 0; i != certs.Length - 1; i++)
+			{
+				x509Certs.Add(LoadCert(certs[i]));
+			}
+
+			x509Certs.Add(endCert);
+
+			for (int i = 0; i != crls.Length; i++)
+			{
+				x509Crls.Add(LoadCrl(crls[i]));
+			}
+
+			IX509Store x509CertStore = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(x509Certs));
+			IX509Store x509CrlStore = X509StoreFactory.Create(
+				"CRL/Collection",
+				new X509CollectionStoreParameters(x509Crls));
+
+//			CertPathBuilder builder = CertPathBuilder.GetInstance("PKIX");   
+			PkixCertPathBuilder builder = new PkixCertPathBuilder();
+
+			X509CertStoreSelector endSelector = new X509CertStoreSelector();
+
+			endSelector.Certificate = endCert;
+
+			PkixBuilderParameters builderParams = new PkixBuilderParameters(trustedSet, endSelector);
+
+			if (initialPolicies != null)
+			{
+				builderParams.SetInitialPolicies(initialPolicies);
+				builderParams.IsExplicitPolicyRequired = true;
+			}
+			if (policyMappingInhibited)
+			{
+				builderParams.IsPolicyMappingInhibited = policyMappingInhibited;
+			}
+			if (anyPolicyInhibited)
+			{
+				builderParams.IsAnyPolicyInhibited = anyPolicyInhibited;
+			}
+
+			builderParams.AddStore(x509CertStore);
+			builderParams.AddStore(x509CrlStore);
+
+			// Perform validation as of this date since test certs expired
+			builderParams.Date = new DateTimeObject(DateTime.Parse("1/1/2011"));
+
+			try
+			{
+				return (PkixCertPathBuilderResult) builder.Build(builderParams);
+			}
+			catch (PkixCertPathBuilderException e)
+			{               
+				throw e.InnerException;
+			}
+		}
+
+		private X509Certificate LoadCert(
+			string certName)
+		{
+			X509Certificate cert = (X509Certificate)certs[certName];
+
+			if (cert != null)
+			{
+				return cert;
+			}
+
+			Stream fs = null;
+
+			try
+			{
+				fs = SimpleTest.GetTestDataAsStream("PKITS.certs." + certName + ".crt");
+
+				cert = new X509CertificateParser().ReadCertificate(fs);
+
+				certs[certName] = cert;
+
+				return cert;
+			}
+			catch (Exception e)
+			{
+				throw new InvalidOperationException("exception loading certificate " + certName + ": " + e);
+			}
+			finally
+			{
+				fs.Close();
+			}
+		}
+
+		private X509Crl LoadCrl(
+			string crlName)
+			//throws Exception
+		{
+			X509Crl crl = (X509Crl)certs[crlName];
+        
+			if (crl != null)
+			{
+				return crl;
+			}
+
+			Stream fs = null;
+
+			try
+			{
+				fs = SimpleTest.GetTestDataAsStream("PKITS.crls." + crlName + ".crl");
+
+				crl = new X509CrlParser().ReadCrl(fs);
+
+				crls[crlName] = crl;
+
+				return crl;
+			}
+			catch (Exception)
+			{
+				throw new InvalidOperationException("exception loading CRL: " + crlName);
+			}
+			finally
+			{
+				fs.Close();
+			}
+		}
+
+		private TrustAnchor GetTrustAnchor(string trustAnchorName)
+		{
+			X509Certificate cert = LoadCert(trustAnchorName);
+			Asn1OctetString extBytes = cert.GetExtensionValue(X509Extensions.NameConstraints);
+
+			if (extBytes != null)
+			{
+				Asn1Encodable extValue = X509ExtensionUtilities.FromExtensionValue(extBytes);
+
+				return new TrustAnchor(cert, extValue.GetDerEncoded());
+			}
+
+			return new TrustAnchor(cert, null);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/test/rsa3/RSA3CertTest.cs b/BouncyCastle.AxCrypt/test/src/test/rsa3/RSA3CertTest.cs
new file mode 100644
index 0000000..913f4f0
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/test/rsa3/RSA3CertTest.cs
@@ -0,0 +1,127 @@
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.OpenSsl;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Test;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tests.Rsa3
+{
+	/**
+	* Marius Schilder's Bleichenbacher's Forgery Attack Tests
+	*/
+	[TestFixture]
+	public class RSA3CertTest
+		//extends TestCase
+	{
+		[Test]
+		public void TestA()
+		{
+			doTest("self-testcase-A.pem");
+		}
+
+		[Test]
+		public void TestB()
+		{
+			doTest("self-testcase-B.pem");
+		}
+
+		[Test]
+		public void TestC()
+		{
+			doTest("self-testcase-C.pem");
+		}
+
+		[Test]
+		public void TestD()
+		{
+			doTest("self-testcase-D.pem");
+		}
+
+		[Test]
+		public void TestE()
+		{
+			doTest("self-testcase-E.pem");
+		}
+
+		[Test]
+		public void TestF()
+		{
+			doTest("self-testcase-F.pem");
+		}
+
+		[Test]
+		public void TestG()
+		{
+			doTest("self-testcase-G.pem");
+		}
+
+		[Test]
+		public void TestH()
+		{
+			doTest("self-testcase-H.pem");
+		}
+
+		[Test]
+		public void TestI()
+		{
+			doTest("self-testcase-I.pem");
+		}
+
+		[Test]
+		public void TestJ()
+		{
+			doTest("self-testcase-J.pem");
+		}
+
+		[Test]
+		public void TestL()
+		{
+			doTest("self-testcase-L.pem");
+		}
+
+		private void doTest(
+			string certName)
+		{
+			X509Certificate cert = loadCert(certName);
+			byte[] tbs = cert.GetTbsCertificate();
+			ISigner sig = SignerUtilities.GetSigner(cert.SigAlgName);
+
+			sig.Init(false, cert.GetPublicKey());
+
+			sig.BlockUpdate(tbs, 0, tbs.Length);
+
+			Assert.IsFalse(sig.VerifySignature(cert.GetSignature()));
+		}
+
+		private X509Certificate loadCert(
+			string certName)
+		{
+			Stream s = SimpleTest.GetTestDataAsStream("rsa3." + certName);
+			TextReader tr = new StreamReader(s);
+			PemReader rd = new PemReader(tr);
+
+			return (X509Certificate) rd.ReadObject();
+		}
+
+//		public static void main (string[] args) 
+//			throws Exception
+//		{
+//			junit.textui.TestRunner.run(suite());
+//		}
+//	    
+//		public static Test suite() 
+//			throws Exception
+//		{   
+//			TestSuite suite = new TestSuite("Bleichenbacher's Forgery Attack Tests");
+//	        
+//			suite.addTestSuite(RSA3CertTest.class);
+//	        
+//			return suite;
+//		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/AllTests.cs
new file mode 100644
index 0000000..c58ff22
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/AllTests.cs
@@ -0,0 +1,34 @@
+#if !LIB
+using System;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+    public class AllTests
+    {
+        public static void Main(
+			string[] args)
+        {
+            //junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            suite().Run(el);
+        }
+
+		public static TestSuite suite()
+        {
+            TestSuite suite = new TestSuite("TSP Tests");
+
+			suite.Add(new GenTimeAccuracyUnitTest());
+			suite.Add(new ParseTest());
+			suite.Add(new TimeStampTokenInfoUnitTest());
+			suite.Add(new TspTest());
+
+			return suite;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/GenTimeAccuracyTest.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/GenTimeAccuracyTest.cs
new file mode 100644
index 0000000..01cc83d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/GenTimeAccuracyTest.cs
@@ -0,0 +1,116 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Tsp;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+	[TestFixture]
+	public class GenTimeAccuracyUnitTest
+	{
+		private static readonly DerInteger ZERO_VALUE = new DerInteger(0);
+		private static readonly DerInteger ONE_VALUE = new DerInteger(1);
+		private static readonly DerInteger TWO_VALUE = new DerInteger(2);
+		private static readonly DerInteger THREE_VALUE = new DerInteger(3);
+
+		[Test]
+		public void TestOneTwoThree()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ONE_VALUE, TWO_VALUE, THREE_VALUE));
+
+			checkValues(accuracy, ONE_VALUE, TWO_VALUE, THREE_VALUE);
+
+			checkTostring(accuracy, "1.002003");
+		}
+
+		[Test]
+		public void TestThreeTwoOne()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(THREE_VALUE, TWO_VALUE, ONE_VALUE));
+
+			checkValues(accuracy, THREE_VALUE, TWO_VALUE, ONE_VALUE);
+
+			checkTostring(accuracy, "3.002001");
+		}
+
+		[Test]
+		public void TestTwoThreeTwo()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(TWO_VALUE, THREE_VALUE, TWO_VALUE));
+
+			checkValues(accuracy, TWO_VALUE, THREE_VALUE, TWO_VALUE);
+
+			checkTostring(accuracy, "2.003002");
+		}
+
+		[Test]
+		public void TestZeroTwoThree()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ZERO_VALUE, TWO_VALUE, THREE_VALUE));
+
+			checkValues(accuracy, ZERO_VALUE, TWO_VALUE, THREE_VALUE);
+
+			checkTostring(accuracy, "0.002003");
+		}
+
+		[Test]
+		public void TestThreeTwoNull()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(THREE_VALUE, TWO_VALUE, null));
+
+			checkValues(accuracy, THREE_VALUE, TWO_VALUE, ZERO_VALUE);
+
+			checkTostring(accuracy, "3.002000");
+		}
+
+		[Test]
+		public void TestOneNullOne()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ONE_VALUE, null, ONE_VALUE));
+
+			checkValues(accuracy, ONE_VALUE, ZERO_VALUE, ONE_VALUE);
+
+			checkTostring(accuracy, "1.000001");
+		}
+
+		[Test]
+		public void TestZeroNullNull()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(ZERO_VALUE, null, null));
+
+			checkValues(accuracy, ZERO_VALUE, ZERO_VALUE, ZERO_VALUE);
+
+			checkTostring(accuracy, "0.000000");
+		}
+
+		[Test]
+		public void TestNullNullNull()
+		{
+			GenTimeAccuracy accuracy = new GenTimeAccuracy(new Accuracy(null, null, null));
+
+			checkValues(accuracy, ZERO_VALUE, ZERO_VALUE, ZERO_VALUE);
+
+			checkTostring(accuracy, "0.000000");
+		}
+
+		private void checkValues(
+			GenTimeAccuracy accuracy,
+			DerInteger      secs,
+			DerInteger      millis,
+			DerInteger      micros)
+		{
+			Assert.AreEqual(secs.Value.IntValue, accuracy.Seconds);
+			Assert.AreEqual(millis.Value.IntValue, accuracy.Millis);
+			Assert.AreEqual(micros.Value.IntValue, accuracy.Micros);
+		}
+
+		private void checkTostring(
+			GenTimeAccuracy	accuracy,
+			string			expected)
+		{
+			Assert.AreEqual(expected, accuracy.ToString());
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/ParseTest.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/ParseTest.cs
new file mode 100644
index 0000000..ec9ba72
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/ParseTest.cs
@@ -0,0 +1,396 @@
+using System;
+using System.Collections;
+using System.IO;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+	[TestFixture]
+	public class ParseTest
+	{
+		private static readonly byte[] sha1Request = Base64.Decode("MDACAQEwITAJBgUrDgMCGgUABBT5UbEBmJssO3RxcQtOePxNvfoMpgIIC+GvYW2mtZQ=");
+		private static readonly byte[] sha1noNonse = Base64.Decode("MCYCAQEwITAJBgUrDgMCGgUABBT5UbEBmJssO3RxcQtOePxNvfoMpg==");
+		private static readonly byte[] md5Request = Base64.Decode("MDoCAQEwIDAMBggqhkiG9w0CBQUABBDIl9FBCvjyx0+6EbHbUR6eBgkrBgEEAakHBQECCDQluayIxIzn");
+		private static readonly byte[] ripemd160Request = Base64.Decode("MD8CAQEwITAJBgUrJAMCAQUABBSq03a/mk50Yd9lMF+BSqOp/RHGQQYJKwYBBAGpBwUBAgkA4SZs9NfqISMBAf8=");
+
+		private static readonly byte[] sha1Response = Base64.Decode(
+			  "MIICbDADAgEAMIICYwYJKoZIhvcNAQcCoIICVDCCAlACAQMxCzAJBgUrDgMC"
+			+ "GgUAMIHaBgsqhkiG9w0BCRABBKCBygSBxzCBxAIBAQYEKgMEATAhMAkGBSsO"
+			+ "AwIaBQAEFPlRsQGYmyw7dHFxC054/E29+gymAgEEGA8yMDA0MTIwOTA3NTIw"
+			+ "NVowCgIBAYACAfSBAWQBAf8CCAvhr2FtprWUoGmkZzBlMRgwFgYDVQQDEw9F"
+			+ "cmljIEguIEVjaGlkbmExJDAiBgkqhkiG9w0BCQEWFWVyaWNAYm91bmN5Y2Fz"
+			+ "dGxlLm9yZzEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUx"
+			+ "ggFfMIIBWwIBATAqMCUxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNV"
+			+ "BAYTAkFVAgECMAkGBSsOAwIaBQCggYwwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3"
+			+ "DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0wNDEyMDkwNzUyMDVaMCMGCSqGSIb3"
+			+ "DQEJBDEWBBTGR1cbm94tWbcpDWrH+bD8UYePsTArBgsqhkiG9w0BCRACDDEc"
+			+ "MBowGDAWBBS37aLzFcheqeJ5cla0gjNWHGKbRzANBgkqhkiG9w0BAQEFAASB"
+			+ "gBrc9CJ3xlcTQuWQXJUqPEn6f6vfJAINKsn22z8LIfS/2p/CTFU6+W/bz8j8"
+			+ "j+8uWEJe8okTsI0FflljIsspqOPTB/RrnXteajbkuk/rLmz1B2g/qWBGAzPI"
+			+ "D214raBc1a7Bpd76PkvSSdjqrEaaskd+7JJiPr9l9yeSoh1AIt0N");
+
+		private static readonly byte[] sha1noNonseResponse = Base64.Decode(
+			  "MIICYjADAgEAMIICWQYJKoZIhvcNAQcCoIICSjCCAkYCAQMxCzAJBgUrDgMC"
+			+ "GgUAMIHQBgsqhkiG9w0BCRABBKCBwASBvTCBugIBAQYEKgMEATAhMAkGBSsO"
+			+ "AwIaBQAEFPlRsQGYmyw7dHFxC054/E29+gymAgECGA8yMDA0MTIwOTA3MzQx"
+			+ "MlowCgIBAYACAfSBAWQBAf+gaaRnMGUxGDAWBgNVBAMTD0VyaWMgSC4gRWNo"
+			+ "aWRuYTEkMCIGCSqGSIb3DQEJARYVZXJpY0Bib3VuY3ljYXN0bGUub3JnMRYw"
+			+ "FAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQswCQYDVQQGEwJBVTGCAV8wggFbAgEB"
+			+ "MCowJTEWMBQGA1UEChMNQm91bmN5IENhc3RsZTELMAkGA1UEBhMCQVUCAQIw"
+			+ "CQYFKw4DAhoFAKCBjDAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJ"
+			+ "KoZIhvcNAQkFMQ8XDTA0MTIwOTA3MzQxMlowIwYJKoZIhvcNAQkEMRYEFMNA"
+			+ "xlscHYiByHL9DIEh3FewIhgSMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFLft"
+			+ "ovMVyF6p4nlyVrSCM1YcYptHMA0GCSqGSIb3DQEBAQUABIGAaj46Tarrg7V7"
+			+ "z13bbetrGv+xy159eE8kmIW9nPegru3DuK/GmbMx9W3l0ydx0zdXRwYi6NZc"
+			+ "nNqbEZQZ2L1biJVTflgWq4Nxu4gPGjH/BGHKdH/LyW4eDcXZR39AkNBMnDAK"
+			+ "EmhhJo1/Tc+S/WkV9lnHJCPIn+TAijBUO6EiTik=");
+
+		private static readonly byte[] md5Response = Base64.Decode(
+			  "MIICcDADAgEAMIICZwYJKoZIhvcNAQcCoIICWDCCAlQCAQMxCzAJBgUrDgMC"
+			+ "GgUAMIHeBgsqhkiG9w0BCRABBKCBzgSByzCByAIBAQYJKwYBBAGpBwUBMCAw"
+			+ "DAYIKoZIhvcNAgUFAAQQyJfRQQr48sdPuhGx21EengIBAxgPMjAwNDEyMDkw"
+			+ "NzQ2MTZaMAoCAQGAAgH0gQFkAQH/Agg0JbmsiMSM56BppGcwZTEYMBYGA1UE"
+			+ "AxMPRXJpYyBILiBFY2hpZG5hMSQwIgYJKoZIhvcNAQkBFhVlcmljQGJvdW5j"
+			+ "eWNhc3RsZS5vcmcxFjAUBgNVBAoTDUJvdW5jeSBDYXN0bGUxCzAJBgNVBAYT"
+			+ "AkFVMYIBXzCCAVsCAQEwKjAlMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxlMQsw"
+			+ "CQYDVQQGEwJBVQIBAjAJBgUrDgMCGgUAoIGMMBoGCSqGSIb3DQEJAzENBgsq"
+			+ "hkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMDQxMjA5MDc0NjE2WjAjBgkq"
+			+ "hkiG9w0BCQQxFgQUFpRpaiRUUjiY7EbefbWLKDIY0XMwKwYLKoZIhvcNAQkQ"
+			+ "AgwxHDAaMBgwFgQUt+2i8xXIXqnieXJWtIIzVhxim0cwDQYJKoZIhvcNAQEB"
+			+ "BQAEgYBTwKsLLrQm+bvKV7Jwto/cMQh0KsVB5RoEeGn5CI9XyF2Bm+JRcvQL"
+			+ "Nm7SgSOBVt4A90TqujxirNeyQnXRiSnFvXd09Wet9WIQNpwpiGlE7lCrAhuq"
+			+ "/TAUe79VIpoQZDtyhbh0Vzxl24yRoechabC0zuPpOWOzrA4YC3Hv1J2tAA==");
+
+		private static readonly byte[] signingCert = Base64.Decode(
+			  "MIICWjCCAcOgAwIBAgIBAjANBgkqhkiG9w0BAQQFADAlMRYwFAYDVQQKEw1Cb3Vu"
+			+ "Y3kgQ2FzdGxlMQswCQYDVQQGEwJBVTAeFw0wNDEyMDkwNzEzMTRaFw0wNTAzMTkw"
+			+ "NzEzMTRaMGUxGDAWBgNVBAMTD0VyaWMgSC4gRWNoaWRuYTEkMCIGCSqGSIb3DQEJ"
+			+ "ARYVZXJpY0Bib3VuY3ljYXN0bGUub3JnMRYwFAYDVQQKEw1Cb3VuY3kgQ2FzdGxl"
+			+ "MQswCQYDVQQGEwJBVTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqGAFO3dK"
+			+ "jB7Ca7u5Z3CabsbGr2Exg+3sztSPiRCIba03es4295EhtDF5bXQvrW2R1Bg72vED"
+			+ "5tWaQjVDetvDfCzVC3ErHLTVk3OgpLIP1gf2T0LcOH2pTh2LP9c5Ceta+uggK8zK"
+			+ "9sYUUnzGPSAZxrqHIIAlPIgqk0BMV+KApyECAwEAAaNaMFgwHQYDVR0OBBYEFO4F"
+			+ "YoqogtB9MjD0NB5x5HN3TrGUMB8GA1UdIwQYMBaAFPXAecuwLqNkCxYVLE/ngFQR"
+			+ "7RLIMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMA0GCSqGSIb3DQEBBAUAA4GBADGi"
+			+ "D5/qmGvcBgswEM/z2dF4lOxbTNKUW31ZHiU8CXlN0IkFtNbBLBTbJOQIAUnNEabL"
+			+ "T7aYgj813OZKUbJTx4MuGChhot/TEP7hKo/xz9OnXLsqYDKbqbo8iLOode+SI7II"
+			+ "+yYghOtqvx32cL2Qmffi1LaMbhJP+8NbsIxowdRC");
+
+		private static readonly byte[] unacceptablePolicy = Base64.Decode(
+			"MDAwLgIBAjAkDCJSZXF1ZXN0ZWQgcG9saWN5IGlzIG5vdCBzdXBwb3J0ZWQuAwMAAAE=");
+
+		private static readonly byte[] generalizedTime = Base64.Decode(
+			  "MIIKPTADAgEAMIIKNAYJKoZIhvcNAQcCoIIKJTCCCiECAQMxCzAJBgUrDgMC"
+			+ "GgUAMIIBGwYLKoZIhvcNAQkQAQSgggEKBIIBBjCCAQICAQEGCisGAQQBhFkK"
+			+ "AwEwITAJBgUrDgMCGgUABBQAAAAAAAAAAAAAAAAAAAAAAAAAAAICUC8YEzIw"
+			+ "MDUwMzEwMTA1ODQzLjkzM1owBIACAfQBAf8CAWSggaikgaUwgaIxCzAJBgNV"
+			+ "BAYTAkdCMRcwFQYDVQQIEw5DYW1icmlkZ2VzaGlyZTESMBAGA1UEBxMJQ2Ft"
+			+ "YnJpZGdlMSQwIgYDVQQKExtuQ2lwaGVyIENvcnBvcmF0aW9uIExpbWl0ZWQx"
+			+ "JzAlBgNVBAsTHm5DaXBoZXIgRFNFIEVTTjozMjJBLUI1REQtNzI1QjEXMBUG"
+			+ "A1UEAxMOZGVtby1kc2UyMDAtMDGgggaFMIID2TCCA0KgAwIBAgICAIswDQYJ"
+			+ "KoZIhvcNAQEFBQAwgYwxCzAJBgNVBAYTAkdCMRcwFQYDVQQIEw5DYW1icmlk"
+			+ "Z2VzaGlyZTESMBAGA1UEBxMJQ2FtYnJpZGdlMSQwIgYDVQQKExtuQ2lwaGVy"
+			+ "IENvcnBvcmF0aW9uIExpbWl0ZWQxGDAWBgNVBAsTD1Byb2R1Y3Rpb24gVEVT"
+			+ "VDEQMA4GA1UEAxMHVEVTVCBDQTAeFw0wNDA2MTQxNDIzNTlaFw0wNTA2MTQx"
+			+ "NDIzNTlaMIGiMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hp"
+			+ "cmUxEjAQBgNVBAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jw"
+			+ "b3JhdGlvbiBMaW1pdGVkMScwJQYDVQQLEx5uQ2lwaGVyIERTRSBFU046MzIy"
+			+ "QS1CNURELTcyNUIxFzAVBgNVBAMTDmRlbW8tZHNlMjAwLTAxMIGfMA0GCSqG"
+			+ "SIb3DQEBAQUAA4GNADCBiQKBgQC7zUamCeLIApddx1etW5YEFrL1WXnlCd7j"
+			+ "mMFI6RpSq056LBkF1z5LgucLY+e/c3u2Nw+XJuS3a2fKuBD7I1s/6IkVtIb/"
+			+ "KLDjjafOnottKhprH8K41siJUeuK3PRzfZ5kF0vwB3rNvWPCBJmp7kHtUQw3"
+			+ "RhIsJTYs7Wy8oVFHVwIDAQABo4IBMDCCASwwCQYDVR0TBAIwADAWBgNVHSUB"
+			+ "Af8EDDAKBggrBgEFBQcDCDAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l"
+			+ "cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFDlEe9Pd0WwQrtnEmFRI2Vmt"
+			+ "b+lCMIG5BgNVHSMEgbEwga6AFNy1VPweOQLC65bs6/0RcUYB19vJoYGSpIGP"
+			+ "MIGMMQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hpcmUxEjAQ"
+			+ "BgNVBAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlv"
+			+ "biBMaW1pdGVkMRgwFgYDVQQLEw9Qcm9kdWN0aW9uIFRFU1QxEDAOBgNVBAMT"
+			+ "B1RFU1QgQ0GCAQAwDQYJKoZIhvcNAQEFBQADgYEASEMlrpRE1RYZPxP3530e"
+			+ "hOYUDjgQbw0dwpPjQtLWkeJrePMzDBAbuWwpRI8dOzKP3Rnrm5rxJ7oLY2S0"
+			+ "A9ZfV+iwFKagEHFytfnPm2Y9AeNR7a3ladKd7NFMw+5Tbk7Asbetbb+NJfCl"
+			+ "9YzHwxLGiQbpKxgc+zYOjq74eGLKtcKhggKkMIICDQIBATCB0qGBqKSBpTCB"
+			+ "ojELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDkNhbWJyaWRnZXNoaXJlMRIwEAYD"
+			+ "VQQHEwlDYW1icmlkZ2UxJDAiBgNVBAoTG25DaXBoZXIgQ29ycG9yYXRpb24g"
+			+ "TGltaXRlZDEnMCUGA1UECxMebkNpcGhlciBEU0UgRVNOOjMyMkEtQjVERC03"
+			+ "MjVCMRcwFQYDVQQDEw5kZW1vLWRzZTIwMC0wMaIlCgEBMAkGBSsOAwIaBQAD"
+			+ "FQDaLe88TQvM+iMKmIXMmDSyPCZ/+KBmMGSkYjBgMQswCQYDVQQGEwJVUzEk"
+			+ "MCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlvbiBMaW1pdGVkMRgwFgYDVQQL"
+			+ "Ew9Qcm9kdWN0aW9uIFRlc3QxETAPBgNVBAMTCFRlc3QgVE1DMA0GCSqGSIb3"
+			+ "DQEBBQUAAgjF2jVbAAAAADAiGA8yMDA1MDMxMDAyNTQxOVoYDzIwMDUwMzEz"
+			+ "MDI1NDE5WjCBjTBLBgorBgEEAYRZCgQBMT0wOzAMAgTF2jVbAgQAAAAAMA8C"
+			+ "BAAAAAACBAAAaLkCAf8wDAIEAAAAAAIEAAKV/DAMAgTF3inbAgQAAAAAMD4G"
+			+ "CisGAQQBhFkKBAIxMDAuMAwGCisGAQQBhFkKAwGgDjAMAgQAAAAAAgQAB6Eg"
+			+ "oQ4wDAIEAAAAAAIEAAPQkDANBgkqhkiG9w0BAQUFAAOBgQB1q4d3GNWk7oAT"
+			+ "WkpYmZaTFvapMhTwAmAtSGgFmNOZhs21iHWl/X990/HEBsduwxohfrd8Pz64"
+			+ "hV/a76rpeJCVUfUNmbRIrsurFx6uKwe2HUHKW8grZWeCD1L8Y1pKQdrD41gu"
+			+ "v0msfOXzLWW+xe5BcJguKclN8HmT7s2odtgiMTGCAmUwggJhAgEBMIGTMIGM"
+			+ "MQswCQYDVQQGEwJHQjEXMBUGA1UECBMOQ2FtYnJpZGdlc2hpcmUxEjAQBgNV"
+			+ "BAcTCUNhbWJyaWRnZTEkMCIGA1UEChMbbkNpcGhlciBDb3Jwb3JhdGlvbiBM"
+			+ "aW1pdGVkMRgwFgYDVQQLEw9Qcm9kdWN0aW9uIFRFU1QxEDAOBgNVBAMTB1RF"
+			+ "U1QgQ0ECAgCLMAkGBSsOAwIaBQCgggEnMBoGCSqGSIb3DQEJAzENBgsqhkiG"
+			+ "9w0BCRABBDAjBgkqhkiG9w0BCQQxFgQUi1iYx5H3ACnvngWZTPfdxGswkSkw"
+			+ "geMGCyqGSIb3DQEJEAIMMYHTMIHQMIHNMIGyBBTaLe88TQvM+iMKmIXMmDSy"
+			+ "PCZ/+DCBmTCBkqSBjzCBjDELMAkGA1UEBhMCR0IxFzAVBgNVBAgTDkNhbWJy"
+			+ "aWRnZXNoaXJlMRIwEAYDVQQHEwlDYW1icmlkZ2UxJDAiBgNVBAoTG25DaXBo"
+			+ "ZXIgQ29ycG9yYXRpb24gTGltaXRlZDEYMBYGA1UECxMPUHJvZHVjdGlvbiBU"
+			+ "RVNUMRAwDgYDVQQDEwdURVNUIENBAgIAizAWBBSpS/lH6bN/wf3E2z2X29vF"
+			+ "2U7YHTANBgkqhkiG9w0BAQUFAASBgGvDVsgsG5I5WKjEDVHvdRwUx+8Cp10l"
+			+ "zGF8o1h7aK5O3zQ4jLayYHea54E5+df35gG7Z3eoOy8E350J7BvHiwDLTqe8"
+			+ "SoRlGs9VhL6LMmCcERfGSlSn61Aa15iXZ8eHMSc5JTeJl+kqy4I3FPP4m2ai"
+			+ "8wy2fQhn7hUM8Ntg7Y2s");
+
+		private static readonly byte[] v2SigningCertResponse = Base64.Decode(
+			  "MIIPPTADAgEAMIIPNAYJKoZIhvcNAQcCoIIPJTCCDyECAQMxDzANBglghkgBZQMEAgEFADCB6QYL"
+			+ "KoZIhvcNAQkQAQSggdkEgdYwgdMCAQEGBgQAj2cBATAxMA0GCWCGSAFlAwQCAQUABCBcU0GN08TA"
+			+ "LUFi7AAwQwVkSXqGu9tAzvJ7EXW7SMXHHQIRAM7Fa7g6tMvZI3dgllwMfpcYDzIwMDcxMjExMTAy"
+			+ "MTU5WjADAgEBAgYBFsi5OlmgYqRgMF4xCzAJBgNVBAYTAkRFMSQwIgYDVQQKDBtEZXV0c2NoZSBS"
+			+ "ZW50ZW52ZXJzaWNoZXJ1bmcxEzARBgNVBAsMClFDIFJvb3QgQ0ExFDASBgNVBAMMC1FDIFJvb3Qg"
+			+ "VFNQoIILQjCCBwkwggXxoAMCAQICAwN1pjANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJERTEk"
+			+ "MCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2ljaGVydW5nMRMwEQYDVQQLDApRQyBSb290IENB"
+			+ "MB4XDTA3MTEyMDE2MDcyMFoXDTEyMDcyNzIwMjExMVowXjELMAkGA1UEBhMCREUxJDAiBgNVBAoM"
+			+ "G0RldXRzY2hlIFJlbnRlbnZlcnNpY2hlcnVuZzETMBEGA1UECwwKUUMgUm9vdCBDQTEUMBIGA1UE"
+			+ "AwwLUUMgUm9vdCBUU1AwggEkMA0GCSqGSIb3DQEBAQUAA4IBEQAwggEMAoIBAQCv1vO+EtGnJNs0"
+			+ "atv76BAJXs4bmO8yzVwe3RUtgeu5z9iefh8P46i1g3EL2CD15NcTfoHksr5KudNY30olfjHG7lIu"
+			+ "MO3R5sAcrGDPP7riZJnaI6VD/e6kVR569VBid5z105fJAB7mID7+Bn7pdRwDW3Fy2CzfofXGuvrO"
+			+ "GPNEWq8x8kqqf75DB5nAs5QP8H41obkdkap2ttHkkPZCiMghTs8iHfpJ0STn47MKq+QrUmuATMZi"
+			+ "XrdEfb7f3TBMjO0UVJF64Mh+kC9GtUEHlcm0Tq2Pk5XIUxWEyL94rZ4UWcVdSVE7IjggV2MifMNx"
+			+ "geZO3SwsDZk71AhDBy30CSzBAgUAx3HB5aOCA+IwggPeMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMI"
+			+ "MBMGA1UdIwQMMAqACECefuBmflfeMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwUAYIKwYBBQUH"
+			+ "AQEERDBCMEAGCCsGAQUFBzABhjRodHRwOi8vb2NzcC1yb290cWMudGMuZGV1dHNjaGUtcmVudGVu"
+			+ "dmVyc2ljaGVydW5nLmRlMHcGA1UdIARwMG4wbAYNKwYBBAGBrTwBCAEBAzBbMFkGCCsGAQUFBwIB"
+			+ "Fk1odHRwOi8vd3d3LmRldXRzY2hlLXJlbnRlbnZlcnNpY2hlcnVuZy1idW5kLmRlL3N0YXRpYy90"
+			+ "cnVzdGNlbnRlci9wb2xpY3kuaHRtbDCCATwGA1UdHwSCATMwggEvMHygeqB4hnZsZGFwOi8vZGly"
+			+ "LnRjLmRldXRzY2hlLXJlbnRlbnZlcnNpY2hlcnVuZy5kZS9vdT1RQyUyMFJvb3QlMjBDQSxjbj1Q"
+			+ "dWJsaWMsbz1EUlYsYz1ERT9hdHRybmFtZT1jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0MIGuoIGr"
+			+ "oIGohoGlaHR0cDovL2Rpci50Yy5kZXV0c2NoZS1yZW50ZW52ZXJzaWNoZXJ1bmcuZGU6ODA4OS9z"
+			+ "ZXJ2bGV0L0Rpclh3ZWIvQ2EveC5jcmw/ZG49b3UlM0RRQyUyMFJvb3QlMjBDQSUyQ2NuJTNEUHVi"
+			+ "bGljJTJDbyUzRERSViUyQ2MlM0RERSZhdHRybmFtZT1jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0"
+			+ "MIIBLQYDVR0SBIIBJDCCASCGdGxkYXA6Ly9kaXIudGMuZGV1dHNjaGUtcmVudGVudmVyc2ljaGVy"
+			+ "dW5nLmRlL2NuPTE0NTUxOCxvdT1RQyUyMFJvb3QlMjBDQSxjbj1QdWJsaWMsbz1EUlYsYz1ERT9h"
+			+ "dHRybmFtZT1jQUNlcnRpZmljYXRlhoGnaHR0cDovL2Rpci50Yy5kZXV0c2NoZS1yZW50ZW52ZXJz"
+			+ "aWNoZXJ1bmcuZGU6ODA4OS9zZXJ2bGV0L0Rpclh3ZWIvQ2EveC5jZXI/ZG49Y24lM0QxNDU1MTgl"
+			+ "MkNvdSUzRFFDJTIwUm9vdCUyMENBJTJDY24lM0RQdWJsaWMlMkNvJTNERFJWJTJDYyUzRERFJmF0"
+			+ "dHJuYW1lPWNBQ2VydGlmaWNhdGUwDgYDVR0PAQH/BAQDAgZAMDsGA1UdCQQ0MDIwMAYDVQQDMSkT"
+			+ "J1FDIFRTUCBEZXV0c2NoZSBSZW50ZW52ZXJzaWNoZXJ1bmcgMTpQTjAMBgNVHRMBAf8EAjAAMA0G"
+			+ "CSqGSIb3DQEBCwUAA4IBAQCCrWe3Pd3ioX7d8phXvVAa859Rvgf0k3pZ6R4GMj8h/k6MNjNIrdAs"
+			+ "wgUVkBbXMLLBk0smsvTdFIVtTBdp1urb9l7vXjDA4MckXBOXPcz4fN8Oswk92d+fM9XU1jKVPsFG"
+			+ "PV6j8lAqfq5jwaRxOnS96UBGLKG+NdcrEyiMp/ZkpqnEQZZfu2mkeq6CPahnbBTZqsE0jgY351gU"
+			+ "9T6SFVvLIFH7cOxJqsoxPqv5YEcgiXPpOyyu2rpQqKYBYcnerF6/zx5hmWHxTd7MWaTHm0gJI/Im"
+			+ "d8esbW+xyaJuAVUcBA+sDmSe8AAoRVxwBRY+xi9ApaJHpmwT+0n2K2GsL3wIMIIEMTCCAxmgAwIB"
+			+ "AgIDAjhuMA0GCSqGSIb3DQEBCwUAMEgxCzAJBgNVBAYTAkRFMSQwIgYDVQQKDBtEZXV0c2NoZSBS"
+			+ "ZW50ZW52ZXJzaWNoZXJ1bmcxEzARBgNVBAsMClFDIFJvb3QgQ0EwHhcNMDcwNzI3MjAyMTExWhcN"
+			+ "MTIwNzI3MjAyMTExWjBIMQswCQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVy"
+			+ "c2ljaGVydW5nMRMwEQYDVQQLDApRQyBSb290IENBMIIBJDANBgkqhkiG9w0BAQEFAAOCAREAMIIB"
+			+ "DAKCAQEAzuhBdo9c84DdzsggjWOgfC4jJ2jYqpsOpBo3DVyem+5R26QK4feZdyFnaGvyG+TLcdLO"
+			+ "iCecGmrRGD+ey4IhjCONb7hsQQhJWTyDEtBblzYB0yjY8+9fnNeR61W+M/KlMgC6Rw/w+zwzklTM"
+			+ "MWwIbxLHm8l9jTSKFjAWTwjE8bCzpUCwN8+4JbFTwjwOJ5lsVA5Xa34wpgr6lgL3WrVTV1NSprqR"
+			+ "ZYDWg477tht0KkyOJt3guF3RONKBBuTO2qCbpUeI8m4v3tznoopYbV5Gp5wu5gqd6lTfgju3ldql"
+			+ "bxtuCLZd0nAI5rLEOPItDKl4vPXllmmtGIrtDZlwr86cbwIFAJvMJpGjggEgMIIBHDAPBgNVHRMB"
+			+ "Af8EBTADAQH/MBEGA1UdDgQKBAhAnn7gZn5X3jB3BgNVHSAEcDBuMGwGDSsGAQQBga08AQgBAQEw"
+			+ "WzBZBggrBgEFBQcCARZNaHR0cDovL3d3dy5kZXV0c2NoZS1yZW50ZW52ZXJzaWNoZXJ1bmctYnVu"
+			+ "ZC5kZS9zdGF0aWMvdHJ1c3RjZW50ZXIvcG9saWN5Lmh0bWwwUwYDVR0JBEwwSjBIBgNVBAMxQRM/"
+			+ "UUMgV3VyemVsemVydGlmaXppZXJ1bmdzc3RlbGxlIERldXRzY2hlIFJlbnRlbnZlcnNpY2hlcnVu"
+			+ "ZyAxOlBOMBgGCCsGAQUFBwEDBAwwCjAIBgYEAI5GAQEwDgYDVR0PAQH/BAQDAgIEMA0GCSqGSIb3"
+			+ "DQEBCwUAA4IBAQBNGs7Dnc1yzzpZrkuC+oLv+NhbORTEYNgpaOetB1JQ1EbUBoPuNN4ih0ngy/uJ"
+			+ "D2O+h4JsNkmELgaehLWyFwATqCYZY4cTAGVoEwgn93x3aW8JbMDQf+YEJDSDsXcm4oIDFPqv5M6o"
+			+ "HZUWfsPka3mxKivfKtWhooTz1/+BEGReVQ2oOAvlwXlkEab9e3GOqXQUcLPYDTl8BQxiYhtQtf3d"
+			+ "kORiUkuGiGX1YJ5JnZnG3ElMjPgOl8rOiYU7oj9uv1HVb5sdAwuVw0BR/eiMVDBT8DNyfoJmPeQQ"
+			+ "A9pXtoAYO0Ya7wNNmCY2Y63YfBlRCF+9VQv2RZ4TdO1KGWwxR98OMYIC1zCCAtMCAQEwTzBIMQsw"
+			+ "CQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2ljaGVydW5nMRMwEQYDVQQL"
+			+ "DApRQyBSb290IENBAgMDdaYwDQYJYIZIAWUDBAIBBQCgggFZMBoGCSqGSIb3DQEJAzENBgsqhkiG"
+			+ "9w0BCRABBDAvBgkqhkiG9w0BCQQxIgQgO7FFODWWwF5RUjo6wjIkgkD5u7dH+NICiCpSgRRqd/Aw"
+			+ "ggEIBgsqhkiG9w0BCRACLzGB+DCB9TCB8jB3BCAMMZqK/5pZxOb3ruCbcgxStaTDwDHaf2glEo6P"
+			+ "+89t8TBTMEykSjBIMQswCQYDVQQGEwJERTEkMCIGA1UECgwbRGV1dHNjaGUgUmVudGVudmVyc2lj"
+			+ "aGVydW5nMRMwEQYDVQQLDApRQyBSb290IENBAgMDdaYwdwQgl7vwI+P47kpxhWLoIdEco7UfGwZ2"
+			+ "X4el3jaZ67q5/9IwUzBMpEowSDELMAkGA1UEBhMCREUxJDAiBgNVBAoMG0RldXRzY2hlIFJlbnRl"
+			+ "bnZlcnNpY2hlcnVuZzETMBEGA1UECwwKUUMgUm9vdCBDQQIDAjhuMA0GCSqGSIb3DQEBCwUABIIB"
+			+ "AIOYgpDI0BaeG4RF/EB5QzkUqAZ9nX6w895+m2hHyRKrAKdj3913j5QI+aEVIG3DVbFaAfdKeKfn"
+			+ "xsTW48aWs6aARtPAc+1OXwoGUSYElOFqqVpSeTaXe+kjY5bsLSQeETB+EPvXl8EcKTaxTRCNOqJU"
+			+ "XbnyYRgWTI55A2jH6IsQQVHc5DaIcmbdI8iATaRTHY5eUeVuI+Q/3RMVBFAb5qRhM61Ddcrjq058"
+			+ "C0uiH9G2IB5QRyu6RsCUgrkeMTMBqlIBlnDBy+EgLouDU4Dehxy5uzEl5DBKZEewZpQZOTO/kAgL"
+			+ "WruAAg/Lj4r0f9vN12wRlHoS2UKDjrE1DnUBbrM=");
+
+		public string Name
+		{
+			get { return "ParseTest"; }
+		}
+
+		private static void requestParse(
+			byte[]	request,
+			string	algorithm)
+		{
+			TimeStampRequest req = new TimeStampRequest(request);
+
+			if (!req.MessageImprintAlgOid.Equals(algorithm))
+			{
+				Assert.Fail("failed to get expected algorithm - got "
+					+ req.MessageImprintAlgOid + " not " + algorithm);
+			}
+
+			if (request != sha1Request && request != sha1noNonse)
+			{
+				if (!req.ReqPolicy.Equals(TspTestUtil.EuroPkiTsaTestPolicy.Id))
+				{
+					Assert.Fail("" + algorithm + " failed policy check.");
+				}
+
+				if (request == ripemd160Request)
+				{
+					if (!req.CertReq)
+					{
+						Assert.Fail("" + algorithm + " failed certReq check.");
+					}
+				}
+			}
+
+			Assert.AreEqual(1, req.Version, "version not 1");
+
+			Assert.IsNull(req.GetCriticalExtensionOids(), "critical extensions found when none expected");
+
+			Assert.IsNull(req.GetNonCriticalExtensionOids(), "non-critical extensions found when none expected");
+
+			if (request != sha1noNonse)
+			{
+				if (req.Nonce == null)
+				{
+					Assert.Fail("" + algorithm + " nonse not found when one expected.");
+				}
+			}
+			else
+			{
+				if (req.Nonce != null)
+				{
+					Assert.Fail("" + algorithm + " nonse not found when one not expected.");
+				}
+			}
+
+			try
+			{
+				req.Validate(TspAlgorithms.Allowed, null, null);
+			}
+			catch (Exception)
+			{
+				Assert.Fail("validation exception.");
+			}
+
+			if (!Arrays.AreEqual(req.GetEncoded(), request))
+			{
+				Assert.Fail("" + algorithm + " failed encode check.");
+			}
+		}
+
+		private static void responseParse(
+			byte[]	request,
+			byte[]	response,
+			string	algorithm)
+		{
+			TimeStampRequest req = new TimeStampRequest(request);
+			TimeStampResponse resp = new TimeStampResponse(response);
+
+			resp.Validate(req);
+
+			X509Certificate cert = new X509CertificateParser().ReadCertificate(signingCert);
+
+			resp.TimeStampToken.Validate(cert);
+		}
+
+		private static void unacceptableResponseParse(
+			byte[] response)
+		{
+			TimeStampResponse resp = new TimeStampResponse(response);
+
+			if (resp.Status != (int) PkiStatus.Rejection)
+			{
+				Assert.Fail("request not rejected.");
+			}
+
+			if (resp.GetFailInfo().IntValue != PkiFailureInfo.UnacceptedPolicy)
+			{
+				Assert.Fail("request not rejected.");
+			}
+		}
+
+		private static void generalizedTimeParse(
+			byte[] response)
+		{
+			TimeStampResponse resp = new TimeStampResponse(response);
+
+			if (resp.Status != (int) PkiStatus.Granted)
+			{
+				Assert.Fail("request not rejected.");
+			}
+		}
+
+		[Test]
+		public void TestSha1()
+		{
+			requestParse(sha1Request, TspAlgorithms.Sha1);
+			requestParse(sha1noNonse, TspAlgorithms.Sha1);
+			responseParse(sha1Request, sha1Response, TspAlgorithms.Sha1);
+			responseParse(sha1noNonse, sha1noNonseResponse, TspAlgorithms.Sha1);
+		}
+
+		[Test]
+		public void TestMD5()
+		{
+			requestParse(md5Request, TspAlgorithms.MD5);
+			responseParse(md5Request, md5Response, TspAlgorithms.MD5);
+		}
+
+		[Test]
+		public void TestRipeMD160()
+		{
+			requestParse(ripemd160Request, TspAlgorithms.RipeMD160);
+		}
+
+		[Test]
+		public void TestUnacceptable()
+		{
+			unacceptableResponseParse(unacceptablePolicy);
+		}
+
+		[Test]
+		public void TestGeneralizedTime()
+		{
+			generalizedTimeParse(generalizedTime);
+		}
+
+		[Test]
+		public void TestV2SigningResponseParse()
+		{
+			v2SigningResponseParse(v2SigningCertResponse);
+		}
+
+		private void v2SigningResponseParse(
+			byte[] encoded)
+		{
+			TimeStampResponse response = new TimeStampResponse(encoded);
+
+			IX509Store store = response.TimeStampToken.GetCertificates("Collection");
+			X509Certificate cert = (X509Certificate)
+				new ArrayList(store.GetMatches(response.TimeStampToken.SignerID))[0];
+
+			response.TimeStampToken.Validate(cert);
+		}
+
+//		public static void parse(
+//			byte[]	encoded,
+//			bool	tokenPresent)
+//		{
+//			TimeStampResponse response = new TimeStampResponse(encoded);
+//
+//			if (tokenPresent && response.TimeStampToken == null)
+//			{
+//				Assert.Fail("token not found when expected.");
+//			}
+//		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTest.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTest.cs
new file mode 100644
index 0000000..e56d4ec
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTest.cs
@@ -0,0 +1,548 @@
+using System;
+using System.Collections;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.Cmp;
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.Pkcs;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.X509;
+using Org.BouncyCastle.X509.Store;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+	[TestFixture]
+	public class TspTest
+	{
+		private static AsymmetricKeyParameter privateKey;
+		private static X509Certificate cert;
+		private static IX509Store certs;
+
+		static TspTest()
+		{
+			string signDN = "O=Bouncy Castle, C=AU";
+			AsymmetricCipherKeyPair signKP = TspTestUtil.MakeKeyPair();
+			X509Certificate signCert = TspTestUtil.MakeCACertificate(signKP, signDN, signKP, signDN);
+
+			string origDN = "CN=Eric H. Echidna, E=eric at bouncycastle.org, O=Bouncy Castle, C=AU";
+			AsymmetricCipherKeyPair origKP = TspTestUtil.MakeKeyPair();
+			privateKey = origKP.Private;
+
+			cert = TspTestUtil.MakeCertificate(origKP, origDN, signKP, signDN);
+
+			IList certList = new ArrayList();
+			certList.Add(cert);
+			certList.Add(signCert);
+
+			certs = X509StoreFactory.Create(
+				"Certificate/Collection",
+				new X509CollectionStoreParameters(certList));
+		}
+
+		[Test]
+		public void TestBasic()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken  tsToken = tsResp.TimeStampToken;
+
+			tsToken.Validate(cert);
+
+			AttributeTable table = tsToken.SignedAttributes;
+
+			Assert.IsNotNull(table[PkcsObjectIdentifiers.IdAASigningCertificate], "no signingCertificate attribute found");
+		}
+
+		[Test]
+		public void TestResponseValidation()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.MD5, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			tsToken.Validate(cert);
+
+			//
+			// check validation
+			//
+			tsResp.Validate(request);
+
+			try
+			{
+				request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(101));
+
+				tsResp.Validate(request);
+
+				Assert.Fail("response validation failed on invalid nonce.");
+			}
+			catch (TspValidationException)
+			{
+				// ignore
+			}
+
+			try
+			{
+				request = reqGen.Generate(TspAlgorithms.Sha1, new byte[22], BigInteger.ValueOf(100));
+
+				tsResp.Validate(request);
+
+				Assert.Fail("response validation failed on wrong digest.");
+			}
+			catch (TspValidationException)
+			{
+				// ignore
+			}
+
+			try
+			{
+				request = reqGen.Generate(TspAlgorithms.MD5, new byte[20], BigInteger.ValueOf(100));
+
+				tsResp.Validate(request);
+
+				Assert.Fail("response validation failed on wrong digest.");
+			}
+			catch (TspValidationException)
+			{
+				// ignore
+			}
+		}
+
+		[Test]
+		public void TestIncorrectHash()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[16]);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			if (tsToken != null)
+			{
+				Assert.Fail("incorrectHash - token not null.");
+			}
+
+			PkiFailureInfo failInfo = tsResp.GetFailInfo();
+
+			if (failInfo == null)
+			{
+				Assert.Fail("incorrectHash - failInfo set to null.");
+			}
+
+			if (failInfo.IntValue != PkiFailureInfo.BadDataFormat)
+			{
+				Assert.Fail("incorrectHash - wrong failure info returned.");
+			}
+		}
+
+		[Test]
+		public void TestBadAlgorithm()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate("1.2.3.4.5", new byte[20]);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken  tsToken = tsResp.TimeStampToken;
+
+			if (tsToken != null)
+			{
+				Assert.Fail("badAlgorithm - token not null.");
+			}
+
+			PkiFailureInfo failInfo = tsResp.GetFailInfo();
+
+			if (failInfo == null)
+			{
+				Assert.Fail("badAlgorithm - failInfo set to null.");
+			}
+
+			if (failInfo.IntValue != PkiFailureInfo.BadAlg)
+			{
+				Assert.Fail("badAlgorithm - wrong failure info returned.");
+			}
+		}
+
+		[Test]
+		public void TestTimeNotAvailable()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate("1.2.3.4.5", new byte[20]);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(
+				tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, new BigInteger("23"), null);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			if (tsToken != null)
+			{
+				Assert.Fail("timeNotAvailable - token not null.");
+			}
+
+			PkiFailureInfo failInfo = tsResp.GetFailInfo();
+
+			if (failInfo == null)
+			{
+				Assert.Fail("timeNotAvailable - failInfo set to null.");
+			}
+
+			if (failInfo.IntValue != PkiFailureInfo.TimeNotAvailable)
+			{
+				Assert.Fail("timeNotAvailable - wrong failure info returned.");
+			}
+		}
+
+		[Test]
+		public void TestBadPolicy()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+
+			reqGen.SetReqPolicy("1.1");
+
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20]);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed, new ArrayList());
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			if (tsToken != null)
+			{
+				Assert.Fail("badPolicy - token not null.");
+			}
+
+			PkiFailureInfo  failInfo = tsResp.GetFailInfo();
+
+			if (failInfo == null)
+			{
+				Assert.Fail("badPolicy - failInfo set to null.");
+			}
+
+			if (failInfo.IntValue != PkiFailureInfo.UnacceptedPolicy)
+			{
+				Assert.Fail("badPolicy - wrong failure info returned.");
+			}
+		}
+
+		[Test]
+		public void TestCertReq()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.MD5, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+
+			//
+			// request with certReq false
+			//
+			reqGen.SetCertReq(false);
+
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			Assert.IsNull(tsToken.TimeStampInfo.GenTimeAccuracy); // check for abscence of accuracy
+
+			Assert.AreEqual("1.2", tsToken.TimeStampInfo.Policy);
+
+			try
+			{
+				tsToken.Validate(cert);
+			}
+			catch (TspValidationException)
+			{
+				Assert.Fail("certReq(false) verification of token failed.");
+			}
+
+			IX509Store respCerts = tsToken.GetCertificates("Collection");
+
+			ICollection certsColl = respCerts.GetMatches(null);
+
+			if (certsColl.Count != 0)
+			{
+				Assert.Fail("certReq(false) found certificates in response.");
+			}
+		}
+
+		[Test]
+		public void TestTokenEncoding()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.Sha1, "1.2.3.4.5.6");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator  reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest           request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+			TimeStampResponse          tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampResponse tsResponse = new TimeStampResponse(tsResp.GetEncoded());
+
+			if (!Arrays.AreEqual(tsResponse.GetEncoded(), tsResp.GetEncoded())
+				|| !Arrays.AreEqual(tsResponse.TimeStampToken.GetEncoded(),
+							tsResp.TimeStampToken.GetEncoded()))
+			{
+				Assert.Fail();
+			}
+		}
+
+		[Test]
+		public void TestAccuracyZeroCerts()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.MD5, "1.2");
+
+			tsTokenGen.SetCertificates(certs);
+
+			tsTokenGen.SetAccuracySeconds(1);
+			tsTokenGen.SetAccuracyMillis(2);
+			tsTokenGen.SetAccuracyMicros(3);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken  tsToken = tsResp.TimeStampToken;
+
+			tsToken.Validate(cert);
+
+			//
+			// check validation
+			//
+			tsResp.Validate(request);
+
+			//
+			// check tstInfo
+			//
+			TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo;
+
+			//
+			// check accuracy
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.AreEqual(1, accuracy.Seconds);
+			Assert.AreEqual(2, accuracy.Millis);
+			Assert.AreEqual(3, accuracy.Micros);
+
+			Assert.AreEqual(BigInteger.ValueOf(23), tstInfo.SerialNumber);
+
+			Assert.AreEqual("1.2", tstInfo.Policy);
+
+			//
+			// test certReq
+			//
+			IX509Store store = tsToken.GetCertificates("Collection");
+
+			ICollection certificates = store.GetMatches(null);
+
+			Assert.AreEqual(0, certificates.Count);
+		}
+
+		[Test]
+		public void TestAccuracyWithCertsAndOrdering()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.MD5, "1.2.3");
+
+			tsTokenGen.SetCertificates(certs);
+
+			tsTokenGen.SetAccuracySeconds(3);
+			tsTokenGen.SetAccuracyMillis(1);
+			tsTokenGen.SetAccuracyMicros(2);
+
+			tsTokenGen.SetOrdering(true);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+
+			reqGen.SetCertReq(true);
+
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20], BigInteger.ValueOf(100));
+
+			Assert.IsTrue(request.CertReq);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(23), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			tsToken.Validate(cert);
+
+			//
+			// check validation
+			//
+			tsResp.Validate(request);
+
+			//
+			// check tstInfo
+			//
+			TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo;
+
+			//
+			// check accuracy
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.AreEqual(3, accuracy.Seconds);
+			Assert.AreEqual(1, accuracy.Millis);
+			Assert.AreEqual(2, accuracy.Micros);
+
+			Assert.AreEqual(BigInteger.ValueOf(23), tstInfo.SerialNumber);
+
+			Assert.AreEqual("1.2.3", tstInfo.Policy);
+
+			Assert.AreEqual(true, tstInfo.IsOrdered);
+
+			Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100));
+
+			//
+			// test certReq
+			//
+			IX509Store store = tsToken.GetCertificates("Collection");
+
+			ICollection certificates = store.GetMatches(null);
+
+			Assert.AreEqual(2, certificates.Count);
+		}
+
+		[Test]
+		public void TestNoNonce()
+		{
+			TimeStampTokenGenerator tsTokenGen = new TimeStampTokenGenerator(
+				privateKey, cert, TspAlgorithms.MD5, "1.2.3");
+
+			tsTokenGen.SetCertificates(certs);
+
+			TimeStampRequestGenerator reqGen = new TimeStampRequestGenerator();
+			TimeStampRequest request = reqGen.Generate(TspAlgorithms.Sha1, new byte[20]);
+
+			Assert.IsFalse(request.CertReq);
+
+			TimeStampResponseGenerator tsRespGen = new TimeStampResponseGenerator(tsTokenGen, TspAlgorithms.Allowed);
+
+			TimeStampResponse tsResp = tsRespGen.Generate(request, BigInteger.ValueOf(24), DateTime.UtcNow);
+
+			tsResp = new TimeStampResponse(tsResp.GetEncoded());
+
+			TimeStampToken tsToken = tsResp.TimeStampToken;
+
+			tsToken.Validate(cert);
+
+			//
+			// check validation
+			//
+			tsResp.Validate(request);
+
+			//
+			// check tstInfo
+			//
+			TimeStampTokenInfo tstInfo = tsToken.TimeStampInfo;
+
+			//
+			// check accuracy
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.IsNull(accuracy);
+
+			Assert.AreEqual(BigInteger.ValueOf(24), tstInfo.SerialNumber);
+
+			Assert.AreEqual("1.2.3", tstInfo.Policy);
+
+			Assert.IsFalse(tstInfo.IsOrdered);
+
+			Assert.IsNull(tstInfo.Nonce);
+
+			//
+			// test certReq
+			//
+			IX509Store store = tsToken.GetCertificates("Collection");
+
+			ICollection certificates = store.GetMatches(null);
+
+			Assert.AreEqual(0, certificates.Count);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTestUtil.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTestUtil.cs
new file mode 100644
index 0000000..f7b0c83
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/TSPTestUtil.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Text;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Encoders;
+using Org.BouncyCastle.X509;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+	public class TspTestUtil
+	{
+		public static SecureRandom rand = new SecureRandom();
+		public static IAsymmetricCipherKeyPairGenerator kpg;
+		public static CipherKeyGenerator desede128kg;
+		public static CipherKeyGenerator desede192kg;
+		public static CipherKeyGenerator rc240kg;
+		public static CipherKeyGenerator rc264kg;
+		public static CipherKeyGenerator rc2128kg;
+		public static BigInteger serialNumber = BigInteger.One;
+		public static readonly bool Debug = true;
+		public static DerObjectIdentifier EuroPkiTsaTestPolicy = new DerObjectIdentifier("1.3.6.1.4.1.5255.5.1");
+
+		static TspTestUtil()
+		{
+			rand = new SecureRandom();
+
+			kpg = GeneratorUtilities.GetKeyPairGenerator("RSA");
+			kpg.Init(new RsaKeyGenerationParameters(
+				BigInteger.ValueOf(0x10001), rand, 1024, 25));
+
+			desede128kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
+			desede128kg.Init(new KeyGenerationParameters(rand, 112));
+
+			desede192kg = GeneratorUtilities.GetKeyGenerator("DESEDE");
+			desede192kg.Init(new KeyGenerationParameters(rand, 168));
+
+			rc240kg = GeneratorUtilities.GetKeyGenerator("RC2");
+			rc240kg.Init(new KeyGenerationParameters(rand, 40));
+
+			rc264kg = GeneratorUtilities.GetKeyGenerator("RC2");
+			rc264kg.Init(new KeyGenerationParameters(rand, 64));
+
+			rc2128kg = GeneratorUtilities.GetKeyGenerator("RC2");
+			rc2128kg.Init(new KeyGenerationParameters(rand, 128));
+
+			serialNumber = BigInteger.One;
+		}
+
+		public static string DumpBase64(
+			byte[] data)
+		{
+			StringBuilder buf = new StringBuilder();
+
+			data = Base64.Encode(data);
+
+			for (int i = 0; i < data.Length; i += 64)
+			{
+				if (i + 64 < data.Length)
+				{
+					buf.Append(Encoding.ASCII.GetString(data, i, 64));
+				}
+				else
+				{
+					buf.Append(Encoding.ASCII.GetString(data, i, data.Length - i));
+				}
+				buf.Append('\n');
+			}
+
+			return buf.ToString();
+		}
+
+		public static AsymmetricCipherKeyPair MakeKeyPair()
+		{
+			return kpg.GenerateKeyPair();
+		}
+
+		public static KeyParameter MakeDesede128Key()
+		{
+			return new DesEdeParameters(desede128kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeDesede192Key()
+		{
+			return new DesEdeParameters(desede192kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC240Key()
+		{
+			return new RC2Parameters(rc240kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC264Key()
+		{
+			return new RC2Parameters(rc264kg.GenerateKey());
+		}
+
+		public static KeyParameter MakeRC2128Key()
+		{
+			return new RC2Parameters(rc2128kg.GenerateKey());
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, false);
+		}
+
+		public static X509Certificate MakeCACertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN)
+		{
+			return MakeCertificate(_subKP, _subDN, _issKP, _issDN, true);
+		}
+
+		public static X509Certificate MakeCertificate(AsymmetricCipherKeyPair _subKP,
+			string _subDN, AsymmetricCipherKeyPair _issKP, string _issDN, bool _ca)
+		{
+			AsymmetricKeyParameter _subPub = _subKP.Public;
+			AsymmetricKeyParameter _issPriv = _issKP.Private;
+			AsymmetricKeyParameter _issPub = _issKP.Public;
+
+			X509V3CertificateGenerator _v3CertGen = new X509V3CertificateGenerator();
+
+			_v3CertGen.Reset();
+			_v3CertGen.SetSerialNumber(allocateSerialNumber());
+			_v3CertGen.SetIssuerDN(new X509Name(_issDN));
+			_v3CertGen.SetNotBefore(DateTime.UtcNow);
+			_v3CertGen.SetNotAfter(DateTime.UtcNow.AddDays(100));
+			_v3CertGen.SetSubjectDN(new X509Name(_subDN));
+			_v3CertGen.SetPublicKey(_subPub);
+			_v3CertGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+
+			_v3CertGen.AddExtension(X509Extensions.SubjectKeyIdentifier, false,
+					createSubjectKeyId(_subPub));
+
+			_v3CertGen.AddExtension(X509Extensions.AuthorityKeyIdentifier, false,
+					createAuthorityKeyId(_issPub));
+
+			if (_ca)
+			{
+				_v3CertGen.AddExtension(X509Extensions.BasicConstraints, false,
+						new BasicConstraints(_ca));
+			}
+			else
+			{
+				_v3CertGen.AddExtension(X509Extensions.ExtendedKeyUsage, true,
+					ExtendedKeyUsage.GetInstance(new DerSequence(KeyPurposeID.IdKPTimeStamping)));
+			}
+
+			X509Certificate _cert = _v3CertGen.Generate(_issPriv);
+
+			_cert.CheckValidity(DateTime.UtcNow);
+			_cert.Verify(_issPub);
+
+			return _cert;
+		}
+
+		/*
+		*
+		*  INTERNAL METHODS
+		*
+		*/
+		private static AuthorityKeyIdentifier createAuthorityKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			return new AuthorityKeyIdentifier(
+				SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey));
+		}
+
+//		private static AuthorityKeyIdentifier createAuthorityKeyId(
+//			AsymmetricKeyParameter _pubKey, X509Name _name, int _sNumber)
+//		{
+//			SubjectPublicKeyInfo _info = SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey);
+//
+//			GeneralName _genName = new GeneralName(_name);
+//
+//			return new AuthorityKeyIdentifier(_info, GeneralNames.GetInstance(
+//				new DerSequence(_genName)), BigInteger.ValueOf(_sNumber));
+//		}
+
+		private static SubjectKeyIdentifier createSubjectKeyId(
+			AsymmetricKeyParameter _pubKey)
+		{
+			return new SubjectKeyIdentifier(
+				SubjectPublicKeyInfoFactory.CreateSubjectPublicKeyInfo(_pubKey));
+		}
+
+		private static BigInteger allocateSerialNumber()
+		{
+			BigInteger _tmp = serialNumber;
+			serialNumber = serialNumber.Add(BigInteger.One);
+			return _tmp;
+		}
+	}
+}
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/tsp/test/TimeStampTokenInfoTest.cs b/BouncyCastle.AxCrypt/test/src/tsp/test/TimeStampTokenInfoTest.cs
new file mode 100644
index 0000000..5a26f5e
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/tsp/test/TimeStampTokenInfoTest.cs
@@ -0,0 +1,145 @@
+using System;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1;
+using Org.BouncyCastle.Asn1.Tsp;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Date;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.Tsp.Tests
+{
+	[TestFixture]
+	public class TimeStampTokenInfoUnitTest
+	{
+		private static readonly byte[] tstInfo1 = Hex.Decode(
+			  "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000"
+			+ "020118180f32303035313130313038313732315a");
+
+		private static readonly byte[] tstInfo2 = Hex.Decode(
+			  "304c02010106022a033021300906052b0e03021a05000414ffffffffffffffffffffffffffffffffffffffff"
+			+ "020117180f32303035313130313038323934355a3009020103800101810102020164");
+
+		private static readonly byte[] tstInfo3 = Hex.Decode(
+			  "304f02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000"
+			+ "020117180f32303035313130313038343733355a30090201038001018101020101ff020164");
+
+		private static readonly byte[] tstInfoDudDate = Hex.Decode(
+			  "303e02010106022a033021300906052b0e03021a050004140000000000000000000000000000000000000000"
+			+ "020118180f32303056313130313038313732315a");
+
+		[Test]
+		public void TestTstInfo1()
+		{
+			TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo1);
+
+			//
+			// verify
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.IsNull(accuracy);
+
+			Assert.AreEqual(new BigInteger("24"), tstInfo.SerialNumber);
+
+			Assert.AreEqual(1130833041000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime));
+
+			Assert.AreEqual("1.2.3", tstInfo.Policy);
+
+			Assert.AreEqual(false, tstInfo.IsOrdered);
+
+			Assert.IsNull(tstInfo.Nonce);
+
+			Assert.AreEqual(TspAlgorithms.Sha1, tstInfo.MessageImprintAlgOid);
+
+			Assert.IsTrue(Arrays.AreEqual(new byte[20], tstInfo.GetMessageImprintDigest()));
+
+			Assert.IsTrue(Arrays.AreEqual(tstInfo1, tstInfo.GetEncoded()));
+		}
+
+	    [Test]
+		public void TestTstInfo2()
+		{
+			TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo2);
+
+			//
+			// verify
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.AreEqual(3, accuracy.Seconds);
+			Assert.AreEqual(1, accuracy.Millis);
+			Assert.AreEqual(2, accuracy.Micros);
+
+			Assert.AreEqual(new BigInteger("23"), tstInfo.SerialNumber);
+
+			Assert.AreEqual(1130833785000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime));
+
+			Assert.AreEqual("1.2.3", tstInfo.Policy);
+
+			Assert.AreEqual(false, tstInfo.IsOrdered);
+
+			Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100));
+
+			Assert.IsTrue(Arrays.AreEqual(Hex.Decode("ffffffffffffffffffffffffffffffffffffffff"), tstInfo.GetMessageImprintDigest()));
+
+			Assert.IsTrue(Arrays.AreEqual(tstInfo2, tstInfo.GetEncoded()));
+		}
+
+	    [Test]
+		public void TestTstInfo3()
+		{
+			TimeStampTokenInfo tstInfo = getTimeStampTokenInfo(tstInfo3);
+
+			//
+			// verify
+			//
+			GenTimeAccuracy accuracy = tstInfo.GenTimeAccuracy;
+
+			Assert.AreEqual(3, accuracy.Seconds);
+			Assert.AreEqual(1, accuracy.Millis);
+			Assert.AreEqual(2, accuracy.Micros);
+
+			Assert.AreEqual(new BigInteger("23"), tstInfo.SerialNumber);
+
+			Assert.AreEqual(1130834855000L, DateTimeUtilities.DateTimeToUnixMs(tstInfo.GenTime));
+
+			Assert.AreEqual("1.2.3", tstInfo.Policy);
+
+			Assert.AreEqual(true, tstInfo.IsOrdered);
+
+			Assert.AreEqual(tstInfo.Nonce, BigInteger.ValueOf(100));
+
+			Assert.AreEqual(TspAlgorithms.Sha1, tstInfo.MessageImprintAlgOid);
+
+			Assert.IsTrue(Arrays.AreEqual(new byte[20], tstInfo.GetMessageImprintDigest()));
+
+			Assert.IsTrue(Arrays.AreEqual(tstInfo3, tstInfo.GetEncoded()));
+		}
+
+		[Test]
+		public void TestTstInfoDudDate()
+		{
+			try
+			{
+				getTimeStampTokenInfo(tstInfoDudDate);
+
+				Assert.Fail("dud date not detected.");
+			}
+			catch (TspException)
+			{
+				// expected
+			}
+		}
+
+		private TimeStampTokenInfo getTimeStampTokenInfo(
+			byte[] tstInfo)
+		{
+			return new TimeStampTokenInfo(
+				TstInfo.GetInstance(
+					Asn1Object.FromByteArray(tstInfo)));
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/io/pem/test/AllTests.cs b/BouncyCastle.AxCrypt/test/src/util/io/pem/test/AllTests.cs
new file mode 100644
index 0000000..3dd8322
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/io/pem/test/AllTests.cs
@@ -0,0 +1,79 @@
+#if !LIB
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.IO;
+using System.Text;
+
+using NUnit.Core;
+using NUnit.Framework;
+
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Generators;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Test;
+
+namespace Org.BouncyCastle.Utilities.IO.Pem.Tests
+{
+	[TestFixture]
+	public class AllTests
+	{
+		[Suite]
+		public static TestSuite Suite
+		{
+			get
+			{
+				TestSuite suite = new TestSuite("PEM Utilities Tests");
+				suite.Add(new AllTests());
+				return suite;
+			}
+		}
+
+		[Test]
+		public void TestPemLength()
+		{
+			for (int i = 1; i != 60; i++)
+			{
+				lengthTest("CERTIFICATE", new ArrayList(), new byte[i]);
+			}
+
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[100]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[101]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[102]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[103]);
+
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[1000]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[1001]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[1002]);
+			lengthTest("CERTIFICATE", new ArrayList(), new byte[1003]);
+
+			IList headers = new ArrayList();
+			headers.Add(new PemHeader("Proc-Type", "4,ENCRYPTED"));
+			headers.Add(new PemHeader("DEK-Info", "DES3,0001020304050607"));
+			lengthTest("RSA PRIVATE KEY", headers, new byte[103]);
+		}
+
+		private void lengthTest(string type, IList headers, byte[] data)
+		{
+			StringWriter sw = new StringWriter();
+			PemWriter pWrt = new PemWriter(sw);
+
+			PemObject pemObj = new PemObject(type, headers, data);
+			pWrt.WriteObject(pemObj);
+			pWrt.Writer.Close();
+
+			Assert.AreEqual(sw.ToString().Length, pWrt.GetOutputSize(pemObj));
+		}
+
+		public static void Main(
+			string[] args)
+        {
+            //junit.textui.TestRunner.run(suite());
+            EventListener el = new NullListener();
+            Suite.Run(el);
+        }
+	}
+}
+#endif
\ No newline at end of file
diff --git a/BouncyCastle.AxCrypt/test/src/util/net/test/IPAddressTest.cs b/BouncyCastle.AxCrypt/test/src/util/net/test/IPAddressTest.cs
new file mode 100644
index 0000000..ec40c52
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/net/test/IPAddressTest.cs
@@ -0,0 +1,61 @@
+using System;
+
+using NUnit.Framework;
+
+namespace Org.BouncyCastle.Utilities.Net.Tests
+{
+	[TestFixture]
+	public class IPTest
+	{
+		private static readonly string[] validIP4v = new string[]
+		{ "0.0.0.0", "255.255.255.255", "192.168.0.0" };
+
+		private static readonly string[] invalidIP4v = new string[]
+		{ "0.0.0.0.1", "256.255.255.255", "1", "A.B.C", "1:.4.6.5" };
+
+		private static readonly string[] validIP6v = new string[]
+		{ "0:0:0:0:0:0:0:0", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF",
+				"0:1:2:3:FFFF:5:FFFF:1" };
+
+		private static readonly string[] invalidIP6v = new string[]
+		{ "0.0.0.0:1", "FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFFF" };
+
+		private void doTestIP(
+			string[]	valid,
+			string[]	invalid)
+		{
+			for (int i = 0; i < valid.Length; i++)
+			{
+				if (!IPAddress.IsValid(valid[i]))
+				{
+					Assert.Fail("Valid input string not accepted: " + valid[i] + ".");
+				}
+			}
+
+			for (int i = 0; i < invalid.Length; i++)
+			{
+				if (IPAddress.IsValid(invalid[i]))
+				{
+					Assert.Fail("Invalid input string accepted: " + invalid[i] + ".");
+				}
+			}
+		}
+
+		public string Name
+		{
+			get { return "IPTest"; }
+		}
+
+		[Test]
+		public void TestIPv4()
+		{
+			doTestIP(validIP4v, invalidIP4v);
+		}
+
+		[Test]
+		public void TestIPv6()
+		{
+			doTestIP(validIP6v, invalidIP6v);
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/FixedSecureRandom.cs b/BouncyCastle.AxCrypt/test/src/util/test/FixedSecureRandom.cs
new file mode 100644
index 0000000..15a2e9b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/FixedSecureRandom.cs
@@ -0,0 +1,64 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Security;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+	public class FixedSecureRandom
+		: SecureRandom
+	{
+		private byte[]       _data;
+		private int          _index;
+
+		protected FixedSecureRandom(
+			byte[] data)
+		{
+			_data = data;
+		}
+
+		public static FixedSecureRandom From(
+			params byte[][] values)
+		{
+			MemoryStream bOut = new MemoryStream();
+
+			for (int i = 0; i != values.Length; i++)
+			{
+				try
+				{
+					byte[] v = values[i];
+					bOut.Write(v, 0, v.Length);
+				}
+				catch (IOException)
+				{
+					throw new ArgumentException("can't save value array.");
+				}
+			}
+
+			return new FixedSecureRandom(bOut.ToArray());
+		}
+
+		public override void NextBytes(
+			byte[] buf)
+		{
+			Array.Copy(_data, _index, buf, 0, buf.Length);
+
+			_index += buf.Length;
+		}
+
+		public override void NextBytes(
+			byte[]	buf,
+			int		off,
+			int		len)
+		{
+			Array.Copy(_data, _index, buf, off, len);
+
+			_index += len;
+		}
+
+		public bool IsExhausted
+		{
+			get { return _index == _data.Length; }
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/ITest.cs b/BouncyCastle.AxCrypt/test/src/util/test/ITest.cs
new file mode 100644
index 0000000..30ad827
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/ITest.cs
@@ -0,0 +1,17 @@
+using System;
+
+using NUnit.Framework;
+
+/*
+ Basic test interface
+ */
+namespace Org.BouncyCastle.Utilities.Test
+{
+    public interface ITest
+    {
+        string Name { get; }
+
+		[Test]
+        ITestResult Perform();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/ITestResult.cs b/BouncyCastle.AxCrypt/test/src/util/test/ITestResult.cs
new file mode 100644
index 0000000..25f0442
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/ITestResult.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+    public interface ITestResult
+    {
+        bool IsSuccessful();
+
+        Exception GetException();
+
+        string ToString();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/NumberParsing.cs b/BouncyCastle.AxCrypt/test/src/util/test/NumberParsing.cs
new file mode 100644
index 0000000..f9624ef
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/NumberParsing.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Globalization;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+    /**
+    * Parsing
+    */
+    public sealed class NumberParsing
+    {
+        private NumberParsing()
+        {
+            // Hide constructor
+        }
+
+		public static long DecodeLongFromHex(
+			string longAsString)
+        {
+            if ((longAsString[1] == 'x')
+                || (longAsString[1] == 'X'))
+            {
+                longAsString = longAsString.Substring(2);
+            }
+
+			return long.Parse(longAsString, NumberStyles.HexNumber);
+        }
+
+		public static int DecodeIntFromHex(
+			string intAsString)
+        {
+            if ((intAsString[1] == 'x')
+                || (intAsString[1] == 'X'))
+            {
+                intAsString = intAsString.Substring(2);
+            }
+
+			return int.Parse(intAsString, NumberStyles.HexNumber);
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/SimpleTest.cs b/BouncyCastle.AxCrypt/test/src/util/test/SimpleTest.cs
new file mode 100644
index 0000000..10c8337
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/SimpleTest.cs
@@ -0,0 +1,164 @@
+using System;
+using System.Collections;
+using System.IO;
+using System.Reflection;
+using System.Text;
+
+using Org.BouncyCastle.Utilities;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+    public abstract class SimpleTest
+        : ITest
+    {
+		public abstract string Name
+		{
+			get;
+		}
+
+		private ITestResult Success()
+        {
+            return SimpleTestResult.Successful(this, "Okay");
+        }
+
+        internal void Fail(
+            string message)
+        {
+            throw new TestFailedException(SimpleTestResult.Failed(this, message));
+        }
+
+        internal void Fail(
+            string		message,
+            Exception	throwable)
+        {
+            throw new TestFailedException(SimpleTestResult.Failed(this, message, throwable));
+        }
+
+		internal void Fail(
+            string message,
+            object expected,
+            object found)
+        {
+            throw new TestFailedException(SimpleTestResult.Failed(this, message, expected, found));
+        }
+
+		internal bool AreEqual(
+            byte[] a,
+            byte[] b)
+        {
+			return Arrays.AreEqual(a, b);
+		}
+
+		public virtual ITestResult Perform()
+        {
+            try
+            {
+                PerformTest();
+
+				return Success();
+            }
+            catch (TestFailedException e)
+            {
+                return e.GetResult();
+            }
+            catch (Exception e)
+            {
+                return SimpleTestResult.Failed(this, "Exception: " +  e, e);
+            }
+        }
+
+		internal static void RunTest(
+            ITest test)
+        {
+            RunTest(test, Console.Out);
+        }
+
+		internal static void RunTest(
+            ITest		test,
+            TextWriter	outStream)
+        {
+            ITestResult result = test.Perform();
+
+			outStream.WriteLine(result.ToString());
+            if (result.GetException() != null)
+            {
+                outStream.WriteLine(result.GetException().StackTrace);
+            }
+        }
+
+		internal static Stream GetTestDataAsStream(
+			string name)
+		{
+			string fullName = GetFullName(name);
+
+			return Assembly.GetExecutingAssembly().GetManifestResourceStream(fullName);
+		}
+
+		internal static string[] GetTestDataEntries(
+			string prefix)
+		{
+			string fullPrefix = GetFullName(prefix);
+
+			ArrayList result = new ArrayList();
+			string[] fullNames = Assembly.GetExecutingAssembly().GetManifestResourceNames();
+			foreach (string fullName in fullNames)
+			{
+				if (fullName.StartsWith(fullPrefix))
+				{
+					string name = GetShortName(fullName);
+					result.Add(name);
+				}
+			}
+			return (string[])result.ToArray(typeof(String));
+		}
+
+		private static string GetFullName(
+			string name)
+		{
+// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent
+#if BC_BUILD_MONODEVELOP
+			return "test.data." + name;
+#else
+			return "crypto.tests." + name;
+#endif
+		}
+
+		private static string GetShortName(
+			string fullName)
+		{
+// TODO MonoDevelop/Visual Studio embedded resource ids still inconsistent
+#if BC_BUILD_MONODEVELOP
+			return fullName.Substring("test.data.".Length);
+#else
+			return fullName.Substring("crypto.tests.".Length);
+#endif
+		}
+
+#if NETCF_1_0 || NETCF_2_0
+		private static string GetNewLine()
+		{
+			MemoryStream buf = new MemoryStream();
+			StreamWriter w = new StreamWriter(buf, Encoding.ASCII);
+			w.WriteLine();
+			w.Close();
+			byte[] bs = buf.ToArray();
+			return Encoding.ASCII.GetString(bs, 0, bs.Length);
+		}
+
+		internal static string GetEnvironmentVariable(
+			string variable)
+		{
+			return null;
+		}
+#else
+		private static string GetNewLine()
+		{
+			return Environment.NewLine;
+		}
+#endif
+
+		internal static readonly string NewLine = GetNewLine();
+
+		public abstract void PerformTest();
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/SimpleTestResult.cs b/BouncyCastle.AxCrypt/test/src/util/test/SimpleTestResult.cs
new file mode 100644
index 0000000..294f575
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/SimpleTestResult.cs
@@ -0,0 +1,91 @@
+using System;
+using System.Text;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+    public class SimpleTestResult : ITestResult
+    {
+        private static readonly string Separator = SimpleTest.NewLine;
+
+        private bool success;
+        private string message;
+        private Exception exception;
+
+        public SimpleTestResult(
+			bool	success,
+			string	message)
+        {
+            this.success = success;
+            this.message = message;
+        }
+
+        public SimpleTestResult(
+			bool		success,
+			string		message,
+			Exception	exception)
+        {
+            this.success = success;
+            this.message = message;
+            this.exception = exception;
+        }
+
+		public static ITestResult Successful(
+            ITest	test,
+            string	message)
+        {
+            return new SimpleTestResult(true, test.Name + ": " + message);
+        }
+
+        public static ITestResult Failed(
+            ITest	test,
+            string	message)
+        {
+            return new SimpleTestResult(false, test.Name + ": " + message);
+        }
+
+        public static ITestResult Failed(
+            ITest		test,
+            string		message,
+            Exception	t)
+        {
+            return new SimpleTestResult(false, test.Name + ": " + message, t);
+        }
+
+        public static ITestResult Failed(
+            ITest	test,
+            string	message,
+            object	expected,
+            object	found)
+        {
+            return Failed(test, message + Separator + "Expected: " + expected + Separator + "Found   : " + found);
+        }
+
+        public static string FailedMessage(
+			string	algorithm,
+			string	testName,
+			string	expected,
+            string	actual)
+        {
+            StringBuilder sb = new StringBuilder(algorithm);
+            sb.Append(" failing ").Append(testName);
+            sb.Append(Separator).Append("    expected: ").Append(expected);
+            sb.Append(Separator).Append("    got     : ").Append(actual);
+            return sb.ToString();
+        }
+
+		public bool IsSuccessful()
+        {
+            return success;
+        }
+
+        public override string ToString()
+        {
+            return message;
+        }
+
+		public Exception GetException()
+        {
+            return exception;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/TestFailedException.cs b/BouncyCastle.AxCrypt/test/src/util/test/TestFailedException.cs
new file mode 100644
index 0000000..ecd7e7d
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/TestFailedException.cs
@@ -0,0 +1,24 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT)
+    [Serializable]
+#endif
+    public class TestFailedException
+        : Exception
+    {
+        private ITestResult _result;
+
+        public TestFailedException(
+            ITestResult result)
+        {
+            _result = result;
+        }
+
+        public ITestResult GetResult()
+        {
+            return _result;
+        }
+    }
+}
diff --git a/BouncyCastle.AxCrypt/test/src/util/test/UncloseableStream.cs b/BouncyCastle.AxCrypt/test/src/util/test/UncloseableStream.cs
new file mode 100644
index 0000000..23eab5b
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/util/test/UncloseableStream.cs
@@ -0,0 +1,22 @@
+using System;
+using System.IO;
+
+using Org.BouncyCastle.Asn1.Utilities;
+
+namespace Org.BouncyCastle.Utilities.Test
+{
+	public class UncloseableStream
+		: FilterStream
+	{
+		public UncloseableStream(
+			Stream s)
+			: base(s)
+		{
+		}
+
+        //public override void Close()
+        //{
+        //    throw new Exception("Close() called on UncloseableStream");
+        //}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/test/src/x509/test/TestCertificateGen.cs b/BouncyCastle.AxCrypt/test/src/x509/test/TestCertificateGen.cs
new file mode 100644
index 0000000..8ec5929
--- /dev/null
+++ b/BouncyCastle.AxCrypt/test/src/x509/test/TestCertificateGen.cs
@@ -0,0 +1,715 @@
+using System;
+using System.Collections;
+using System.Text;
+
+using NUnit.Framework;
+
+using Org.BouncyCastle.Asn1.X509;
+using Org.BouncyCastle.Crypto.Digests;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Crypto.Signers;
+using Org.BouncyCastle.Math;
+using Org.BouncyCastle.Math.EC;
+using Org.BouncyCastle.Utilities.Collections;
+using Org.BouncyCastle.Utilities.Encoders;
+
+namespace Org.BouncyCastle.X509.Tests
+{
+    [TestFixture]
+    public class TestCertificateGen
+    {
+        public TestCertificateGen()
+        {
+        }
+
+		[Test]
+        public void TestRsaDigestSigner()
+        {
+            BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
+            BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+            BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+            BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+            BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+            BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+            BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
+			RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+            byte[] msg = new byte[] { 1, 6, 3, 32, 7, 43, 2, 5, 7, 78, 4, 23 };
+
+            RsaDigestSigner signer = new RsaDigestSigner(new Sha1Digest());
+            signer.Init(true, rsaPrivate);
+            signer.BlockUpdate(msg, 0, msg.Length);
+            byte[] sig = signer.GenerateSignature();
+
+            signer.Init(false,rsaPublic);
+            signer.BlockUpdate(msg, 0, msg.Length);
+            Assert.IsTrue(signer.VerifySignature(sig), "RSA IDigest Signer failed.");
+        }
+
+        [Test]
+        public void TestCreationRSA()
+        {
+            BigInteger rsaPubMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPubExp = new BigInteger(Base64.Decode("EQ=="));
+            BigInteger rsaPrivMod = new BigInteger(Base64.Decode("AIASoe2PQb1IP7bTyC9usjHP7FvnUMVpKW49iuFtrw/dMpYlsMMoIU2jupfifDpdFxIktSB4P+6Ymg5WjvHKTIrvQ7SR4zV4jaPTu56Ys0pZ9EDA6gb3HLjtU+8Bb1mfWM+yjKxcPDuFjwEtjGlPHg1Vq+CA9HNcMSKNn2+tW6qt"));
+            BigInteger rsaPrivDP = new BigInteger(Base64.Decode("JXzfzG5v+HtLJIZqYMUefJfFLu8DPuJGaLD6lI3cZ0babWZ/oPGoJa5iHpX4Ul/7l3s1PFsuy1GhzCdOdlfRcQ=="));
+            BigInteger rsaPrivDQ = new BigInteger(Base64.Decode("YNdJhw3cn0gBoVmMIFRZzflPDNthBiWy/dUMSRfJCxoZjSnr1gysZHK01HteV1YYNGcwPdr3j4FbOfri5c6DUQ=="));
+            BigInteger rsaPrivExp = new BigInteger(Base64.Decode("DxFAOhDajr00rBjqX+7nyZ/9sHWRCCp9WEN5wCsFiWVRPtdB+NeLcou7mWXwf1Y+8xNgmmh//fPV45G2dsyBeZbXeJwB7bzx9NMEAfedchyOwjR8PYdjK3NpTLKtZlEJ6Jkh4QihrXpZMO4fKZWUm9bid3+lmiq43FwW+Hof8/E="));
+            BigInteger rsaPrivP = new BigInteger(Base64.Decode("AJ9StyTVW+AL/1s7RBtFwZGFBgd3zctBqzzwKPda6LbtIFDznmwDCqAlIQH9X14X7UPLokCDhuAa76OnDXb1OiE="));
+            BigInteger rsaPrivQ = new BigInteger(Base64.Decode("AM3JfD79dNJ5A3beScSzPtWxx/tSLi0QHFtkuhtSizeXdkv5FSba7lVzwEOGKHmW829bRoNxThDy4ds1IihW1w0="));
+            BigInteger rsaPrivQinv = new BigInteger(Base64.Decode("Lt0g7wrsNsQxuDdB8q/rH8fSFeBXMGLtCIqfOec1j7FEIuYA/ACiRDgXkHa0WgN7nLXSjHoy630wC5Toq8vvUg=="));
+            RsaKeyParameters rsaPublic = new RsaKeyParameters(false, rsaPubMod, rsaPubExp);
+			RsaPrivateCrtKeyParameters rsaPrivate = new RsaPrivateCrtKeyParameters(rsaPrivMod, rsaPubExp, rsaPrivExp, rsaPrivP, rsaPrivQ, rsaPrivDP, rsaPrivDQ, rsaPrivQinv);
+
+			IDictionary attrs = new Hashtable();
+            attrs[X509Name.C] = "AU";
+            attrs[X509Name.O] = "The Legion of the Bouncy Castle";
+            attrs[X509Name.L] = "Melbourne";
+            attrs[X509Name.ST] = "Victoria";
+            attrs[X509Name.E] = "feedback-crypto at bouncycastle.org";
+
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+			IList values = new ArrayList();
+			values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+
+            certGen.SetIssuerDN(new X509Name(ord, attrs));
+			certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));
+			certGen.SetNotAfter(DateTime.UtcNow.AddDays(1));
+            certGen.SetSubjectDN(new X509Name(ord, attrs));
+            certGen.SetPublicKey(rsaPublic);
+            certGen.SetSignatureAlgorithm("MD5WithRSAEncryption");
+
+			X509Certificate cert = certGen.Generate(rsaPrivate);
+
+//			Assert.IsTrue((cert.IsValidNow && cert.Verify(rsaPublic)),"Certificate failed to be valid (RSA)");
+			cert.CheckValidity();
+			cert.Verify(rsaPublic);
+
+			//Console.WriteLine(ASN1Dump.DumpAsString(cert.ToAsn1Object()));
+
+            //ISet dummySet = cert.GetNonCriticalExtensionOids();
+
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+
+            //dummySet = cert.GetNonCriticalExtensionOids();
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+        }
+
+		[Test]
+        public void TestCreationDSA()
+        {
+            BigInteger DSAParaG = new BigInteger(Base64.Decode("AL0fxOTq10OHFbCf8YldyGembqEu08EDVzxyLL29Zn/t4It661YNol1rnhPIs+cirw+yf9zeCe+KL1IbZ/qIMZM="));
+            BigInteger DSAParaP = new BigInteger(Base64.Decode("AM2b/UeQA+ovv3dL05wlDHEKJ+qhnJBsRT5OB9WuyRC830G79y0R8wuq8jyIYWCYcTn1TeqVPWqiTv6oAoiEeOs="));
+            BigInteger DSAParaQ = new BigInteger(Base64.Decode("AIlJT7mcKL6SUBMmvm24zX1EvjNx"));
+            BigInteger DSAPublicY = new BigInteger(Base64.Decode("TtWy2GuT9yGBWOHi1/EpCDa/bWJCk2+yAdr56rAcqP0eHGkMnA9s9GJD2nGU8sFjNHm55swpn6JQb8q0agrCfw=="));
+            BigInteger DsaPrivateX = new BigInteger(Base64.Decode("MMpBAxNlv7eYfxLTZ2BItJeD31A="));
+
+            DsaParameters para = new DsaParameters(DSAParaP, DSAParaQ, DSAParaG);
+            DsaPrivateKeyParameters dsaPriv = new DsaPrivateKeyParameters(DsaPrivateX, para);
+            DsaPublicKeyParameters dsaPub = new DsaPublicKeyParameters(DSAPublicY, para);
+
+            IDictionary attrs = new Hashtable();
+            attrs[X509Name.C] = "AU";
+            attrs[X509Name.O] = "The Legion of the Bouncy Castle";
+            attrs[X509Name.L] = "Melbourne";
+            attrs[X509Name.ST] = "Victoria";
+            attrs[X509Name.E] = "feedback-crypto at bouncycastle.org";
+
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+            IList values = new ArrayList();
+			values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+			certGen.SetSerialNumber(BigInteger.One);
+
+            certGen.SetIssuerDN(new X509Name(ord, attrs));
+			certGen.SetNotBefore(DateTime.UtcNow.AddDays(-1));
+			certGen.SetNotAfter(DateTime.UtcNow.AddDays(1));
+            certGen.SetSubjectDN(new X509Name(ord, attrs));
+            certGen.SetPublicKey(dsaPub);
+            certGen.SetSignatureAlgorithm("SHA1WITHDSA");
+
+            X509Certificate cert = certGen.Generate(dsaPriv);
+
+//			Assert.IsTrue((cert.IsValidNow && cert.Verify(dsaPub)), "Certificate failed to be valid (DSA Test)");
+			cert.CheckValidity();
+			cert.Verify(dsaPub);
+
+            //ISet dummySet = cert.GetNonCriticalExtensionOids();
+
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+
+            //dummySet = cert.GetNonCriticalExtensionOids();
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+        }
+
+		[Test]
+        public void TestCreationECDSA()
+        {
+            BigInteger ECParraGX = new BigInteger(Base64.Decode("D/qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqv"));
+            BigInteger ECParraGY = new BigInteger(Base64.Decode("AhQXGxb1olGRv6s1LPRfuatMF+cx3ZTGgzSE/Q5R"));
+            BigInteger ECParraH = new BigInteger(Base64.Decode("AQ=="));
+            BigInteger ECParraN = new BigInteger(Base64.Decode("f///////////////f///nl6an12QcfvRUiaIkJ0L"));
+            BigInteger ECPubQX = new BigInteger(Base64.Decode("HWWi17Yb+Bm3PYr/DMjLOYNFhyOwX1QY7ZvqqM+l"));
+            BigInteger ECPubQY = new BigInteger(Base64.Decode("JrlJfxu3WGhqwtL/55BOs/wsUeiDFsvXcGhB8DGx"));
+            BigInteger ECPrivD = new BigInteger(Base64.Decode("GYQmd/NF1B+He1iMkWt3by2Az6Eu07t0ynJ4YCAo"));
+            FpCurve curve = new FpCurve(
+               new BigInteger("883423532389192164791648750360308885314476597252960362792450860609699839"), // q
+                new BigInteger("7fffffffffffffffffffffff7fffffffffff8000000000007ffffffffffc", 16), // a
+                new BigInteger("6b016c3bdcf18941d0d654921475ca71a9db2fb27d1d37796185c2942c0a", 16)); // b
+            ECDomainParameters ecDomain =
+                new ECDomainParameters(curve, new FpPoint(curve, curve.FromBigInteger(ECParraGX), curve.FromBigInteger(ECParraGY)), ECParraN);
+            ECPublicKeyParameters ecPub = new ECPublicKeyParameters(
+				"ECDSA",
+				new FpPoint(curve,
+					curve.FromBigInteger(ECPubQX),
+					curve.FromBigInteger(ECPubQY)),
+				ecDomain);
+            ECPrivateKeyParameters ecPriv = new ECPrivateKeyParameters("ECDSA", ECPrivD, ecDomain);
+
+
+            IDictionary attrs = new Hashtable();
+			attrs[X509Name.C] = "AU";
+            attrs[X509Name.O] = "The Legion of the Bouncy Castle";
+            attrs[X509Name.L] = "Melbourne";
+            attrs[X509Name.ST] = "Victoria";
+            attrs[X509Name.E] = "feedback-crypto at bouncycastle.org";
+
+            IList ord = new ArrayList();
+            ord.Add(X509Name.C);
+            ord.Add(X509Name.O);
+            ord.Add(X509Name.L);
+            ord.Add(X509Name.ST);
+            ord.Add(X509Name.E);
+
+			IList values = new ArrayList();
+			values.Add("AU");
+            values.Add("The Legion of the Bouncy Castle");
+            values.Add("Melbourne");
+            values.Add("Victoria");
+            values.Add("feedback-crypto at bouncycastle.org");
+
+            X509V3CertificateGenerator certGen = new X509V3CertificateGenerator();
+
+            certGen.SetSerialNumber(BigInteger.One);
+
+            certGen.SetIssuerDN(new X509Name(ord, attrs));
+            certGen.SetNotBefore(DateTime.Today.Subtract(new TimeSpan(1, 0, 0, 0)));
+            certGen.SetNotAfter(DateTime.Today.AddDays(1));
+            certGen.SetSubjectDN(new X509Name(ord, attrs));
+            certGen.SetPublicKey(ecPub);
+            certGen.SetSignatureAlgorithm("SHA1WITHECDSA");
+
+
+            X509Certificate cert = certGen.Generate(ecPriv);
+
+//            Assert.IsTrue((cert.IsValidNow && cert.Verify(ecPub)), "Certificate failed to be valid (ECDSA)");
+			cert.CheckValidity();
+			cert.Verify(ecPub);
+
+            //ISet dummySet = cert.GetNonCriticalExtensionOids();
+
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+
+            //dummySet = cert.GetNonCriticalExtensionOids();
+
+            //if (dummySet != null)
+            //{
+            //    foreach (string key in dummySet)
+            //    {
+            //        Console.WriteLine("\t{0}:\t{1}", key);
+            //    }
+            //}
+
+            //Console.WriteLine();
+        }
+
+		[Test]
+		public void TestCertLoading()
+        {
+            byte[] cert1 = Base64.Decode(
+                   "MIIDXjCCAsegAwIBAgIBBzANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+                 + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+                 + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+                 + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+                 + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU2MjFaFw0wMTA2"
+                 + "MDIwNzU2MjFaMIG4MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+                 + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+                 + "dGQxFzAVBgNVBAsTDldlYnNlcnZlciBUZWFtMR0wGwYDVQQDExR3d3cyLmNvbm5l"
+                 + "Y3Q0LmNvbS5hdTEoMCYGCSqGSIb3DQEJARYZd2VibWFzdGVyQGNvbm5lY3Q0LmNv"
+                 + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArvDxclKAhyv7Q/Wmr2re"
+                 + "Gw4XL9Cnh9e+6VgWy2AWNy/MVeXdlxzd7QAuc1eOWQkGQEiLPy5XQtTY+sBUJ3AO"
+                 + "Rvd2fEVJIcjf29ey7bYua9J/vz5MG2KYo9/WCHIwqD9mmG9g0xLcfwq/s8ZJBswE"
+                 + "7sb85VU+h94PTvsWOsWuKaECAwEAAaN3MHUwJAYDVR0RBB0wG4EZd2VibWFzdGVy"
+                 + "QGNvbm5lY3Q0LmNvbS5hdTA6BglghkgBhvhCAQ0ELRYrbW9kX3NzbCBnZW5lcmF0"
+                 + "ZWQgY3VzdG9tIHNlcnZlciBjZXJ0aWZpY2F0ZTARBglghkgBhvhCAQEEBAMCBkAw"
+                 + "DQYJKoZIhvcNAQEEBQADgYEAotccfKpwSsIxM1Hae8DR7M/Rw8dg/RqOWx45HNVL"
+                 + "iBS4/3N/TO195yeQKbfmzbAA2jbPVvIvGgTxPgO1MP4ZgvgRhasaa0qCJCkWvpM4"
+                 + "yQf33vOiYQbpv4rTwzU8AmRlBG45WdjyNIigGV+oRc61aKCTnLq7zB8N3z1TF/bF"
+                 + "5/8=");
+
+			try
+			{
+                Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert1));
+            }
+			catch (Exception)
+            {
+                Assert.Fail("Reading first test certificate.");
+            }
+
+
+			// ca.crt
+            //
+            byte[] cert2 = Base64.Decode(
+                   "MIIDbDCCAtWgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBtzELMAkGA1UEBhMCQVUx"
+                 + "ETAPBgNVBAgTCFZpY3RvcmlhMRgwFgYDVQQHEw9Tb3V0aCBNZWxib3VybmUxGjAY"
+                 + "BgNVBAoTEUNvbm5lY3QgNCBQdHkgTHRkMR4wHAYDVQQLExVDZXJ0aWZpY2F0ZSBB"
+                 + "dXRob3JpdHkxFTATBgNVBAMTDENvbm5lY3QgNCBDQTEoMCYGCSqGSIb3DQEJARYZ"
+                 + "d2VibWFzdGVyQGNvbm5lY3Q0LmNvbS5hdTAeFw0wMDA2MDIwNzU1MzNaFw0wMTA2"
+                 + "MDIwNzU1MzNaMIG3MQswCQYDVQQGEwJBVTERMA8GA1UECBMIVmljdG9yaWExGDAW"
+                 + "BgNVBAcTD1NvdXRoIE1lbGJvdXJuZTEaMBgGA1UEChMRQ29ubmVjdCA0IFB0eSBM"
+                 + "dGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhvcml0eTEVMBMGA1UEAxMMQ29u"
+                 + "bmVjdCA0IENBMSgwJgYJKoZIhvcNAQkBFhl3ZWJtYXN0ZXJAY29ubmVjdDQuY29t"
+                 + "LmF1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDgs5ptNG6Qv1ZpCDuUNGmv"
+                 + "rhjqMDPd3ri8JzZNRiiFlBA4e6/ReaO1U8ASewDeQMH6i9R6degFdQRLngbuJP0s"
+                 + "xcEE+SksEWNvygfzLwV9J/q+TQDyJYK52utb++lS0b48A1KPLwEsyL6kOAgelbur"
+                 + "ukwxowprKUIV7Knf1ajetQIDAQABo4GFMIGCMCQGA1UdEQQdMBuBGXdlYm1hc3Rl"
+                 + "ckBjb25uZWN0NC5jb20uYXUwDwYDVR0TBAgwBgEB/wIBADA2BglghkgBhvhCAQ0E"
+                 + "KRYnbW9kX3NzbCBnZW5lcmF0ZWQgY3VzdG9tIENBIGNlcnRpZmljYXRlMBEGCWCG"
+                 + "SAGG+EIBAQQEAwICBDANBgkqhkiG9w0BAQQFAAOBgQCsGvfdghH8pPhlwm1r3pQk"
+                 + "msnLAVIBb01EhbXm2861iXZfWqGQjrGAaA0ZpXNk9oo110yxoqEoSJSzniZa7Xtz"
+                 + "soTwNUpE0SLHvWf/SlKdFWlzXA+vOZbzEv4UmjeelekTm7lc01EEa5QRVzOxHFtQ"
+                 + "DhkaJ8VqOMajkQFma2r9iA==");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert2));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading second test certificate.");
+			}
+
+
+            //
+            // testx509.pem
+            //
+            byte[] cert3 = Base64.Decode(
+                   "MIIBWzCCAQYCARgwDQYJKoZIhvcNAQEEBQAwODELMAkGA1UEBhMCQVUxDDAKBgNV"
+                 + "BAgTA1FMRDEbMBkGA1UEAxMSU1NMZWF5L3JzYSB0ZXN0IENBMB4XDTk1MDYxOTIz"
+                 + "MzMxMloXDTk1MDcxNzIzMzMxMlowOjELMAkGA1UEBhMCQVUxDDAKBgNVBAgTA1FM"
+                 + "RDEdMBsGA1UEAxMUU1NMZWF5L3JzYSB0ZXN0IGNlcnQwXDANBgkqhkiG9w0BAQEF"
+                 + "AANLADBIAkEAqtt6qS5GTxVxGZYWa0/4u+IwHf7p2LNZbcPBp9/OfIcYAXBQn8hO"
+                 + "/Re1uwLKXdCjIoaGs4DLdG88rkzfyK5dPQIDAQABMAwGCCqGSIb3DQIFBQADQQAE"
+                 + "Wc7EcF8po2/ZO6kNCwK/ICH6DobgLekA5lSLr5EvuioZniZp5lFzAw4+YzPQ7XKJ"
+                 + "zl9HYIMxATFyqSiD9jsx");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert3));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading third test certificate. (X509.pem)");
+			}
+
+
+			//
+            // v3-cert1.pem
+            //
+            byte[] cert4 = Base64.Decode(
+                   "MIICjTCCAfigAwIBAgIEMaYgRzALBgkqhkiG9w0BAQQwRTELMAkGA1UEBhMCVVMx"
+                 + "NjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFuZCBTcGFjZSBBZG1pbmlz"
+                 + "dHJhdGlvbjAmFxE5NjA1MjgxMzQ5MDUrMDgwMBcROTgwNTI4MTM0OTA1KzA4MDAw"
+                 + "ZzELMAkGA1UEBhMCVVMxNjA0BgNVBAoTLU5hdGlvbmFsIEFlcm9uYXV0aWNzIGFu"
+                 + "ZCBTcGFjZSBBZG1pbmlzdHJhdGlvbjEgMAkGA1UEBRMCMTYwEwYDVQQDEwxTdGV2"
+                 + "ZSBTY2hvY2gwWDALBgkqhkiG9w0BAQEDSQAwRgJBALrAwyYdgxmzNP/ts0Uyf6Bp"
+                 + "miJYktU/w4NG67ULaN4B5CnEz7k57s9o3YY3LecETgQ5iQHmkwlYDTL2fTgVfw0C"
+                 + "AQOjgaswgagwZAYDVR0ZAQH/BFowWDBWMFQxCzAJBgNVBAYTAlVTMTYwNAYDVQQK"
+                 + "Ey1OYXRpb25hbCBBZXJvbmF1dGljcyBhbmQgU3BhY2UgQWRtaW5pc3RyYXRpb24x"
+                 + "DTALBgNVBAMTBENSTDEwFwYDVR0BAQH/BA0wC4AJODMyOTcwODEwMBgGA1UdAgQR"
+                 + "MA8ECTgzMjk3MDgyM4ACBSAwDQYDVR0KBAYwBAMCBkAwCwYJKoZIhvcNAQEEA4GB"
+                 + "AH2y1VCEw/A4zaXzSYZJTTUi3uawbbFiS2yxHvgf28+8Js0OHXk1H1w2d6qOHH21"
+                 + "X82tZXd/0JtG0g1T9usFFBDvYK8O0ebgz/P5ELJnBL2+atObEuJy1ZZ0pBDWINR3"
+                 + "WkDNLCGiTkCKp0F5EWIrVDwh54NNevkCQRZita+z4IBO");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert4));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading fourth test certificate. (X509 V3 Pem)");
+			}
+
+
+			//
+            // v3-cert2.pem
+            //
+            byte[] cert5 = Base64.Decode(
+                   "MIICiTCCAfKgAwIBAgIEMeZfHzANBgkqhkiG9w0BAQQFADB9MQswCQYDVQQGEwJD"
+                 + "YTEPMA0GA1UEBxMGTmVwZWFuMR4wHAYDVQQLExVObyBMaWFiaWxpdHkgQWNjZXB0"
+                 + "ZWQxHzAdBgNVBAoTFkZvciBEZW1vIFB1cnBvc2VzIE9ubHkxHDAaBgNVBAMTE0Vu"
+                 + "dHJ1c3QgRGVtbyBXZWIgQ0EwHhcNOTYwNzEyMTQyMDE1WhcNOTYxMDEyMTQyMDE1"
+                 + "WjB0MSQwIgYJKoZIhvcNAQkBExVjb29rZUBpc3NsLmF0bC5ocC5jb20xCzAJBgNV"
+                 + "BAYTAlVTMScwJQYDVQQLEx5IZXdsZXR0IFBhY2thcmQgQ29tcGFueSAoSVNTTCkx"
+                 + "FjAUBgNVBAMTDVBhdWwgQS4gQ29va2UwXDANBgkqhkiG9w0BAQEFAANLADBIAkEA"
+                 + "6ceSq9a9AU6g+zBwaL/yVmW1/9EE8s5you1mgjHnj0wAILuoB3L6rm6jmFRy7QZT"
+                 + "G43IhVZdDua4e+5/n1ZslwIDAQABo2MwYTARBglghkgBhvhCAQEEBAMCB4AwTAYJ"
+                 + "YIZIAYb4QgENBD8WPVRoaXMgY2VydGlmaWNhdGUgaXMgb25seSBpbnRlbmRlZCBm"
+                 + "b3IgZGVtb25zdHJhdGlvbiBwdXJwb3Nlcy4wDQYJKoZIhvcNAQEEBQADgYEAi8qc"
+                 + "F3zfFqy1sV8NhjwLVwOKuSfhR/Z8mbIEUeSTlnH3QbYt3HWZQ+vXI8mvtZoBc2Fz"
+                 + "lexKeIkAZXCesqGbs6z6nCt16P6tmdfbZF3I3AWzLquPcOXjPf4HgstkyvVBn0Ap"
+                 + "jAFN418KF/Cx4qyHB4cjdvLrRjjQLnb2+ibo7QU=");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert5));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading fifth test certificate. (X509 V3 Pem)");
+			}
+
+
+            //
+            // pem encoded pkcs7
+            //
+            byte[] cert6 = Base64.Decode(
+                  "MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAoIIJbzCCAj0w"
+                + "ggGmAhEAzbp/VvDf5LxU/iKss3KqVTANBgkqhkiG9w0BAQIFADBfMQswCQYDVQQGEwJVUzEXMBUG"
+                + "A1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGljIFByaW1hcnkgQ2Vy"
+                + "dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTYwMTI5MDAwMDAwWhcNMjgwODAxMjM1OTU5WjBfMQsw"
+                + "CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVi"
+                + "bGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwgZ8wDQYJKoZIhvcNAQEBBQADgY0A"
+                + "MIGJAoGBAOUZv22jVmEtmUhx9mfeuY3rt56GgAqRDvo4Ja9GiILlc6igmyRdDR/MZW4MsNBWhBiH"
+                + "mgabEKFz37RYOWtuwfYV1aioP6oSBo0xrH+wNNePNGeICc0UEeJORVZpH3gCgNrcR5EpuzbJY1zF"
+                + "4Ncth3uhtzKwezC6Ki8xqu6jZ9rbAgMBAAEwDQYJKoZIhvcNAQECBQADgYEATD+4i8Zo3+5DMw5d"
+                + "6abLB4RNejP/khv0Nq3YlSI2aBFsfELM85wuxAc/FLAPT/+Qknb54rxK6Y/NoIAK98Up8YIiXbix"
+                + "3YEjo3slFUYweRb46gVLlH8dwhzI47f0EEA8E8NfH1PoSOSGtHuhNbB7Jbq4046rPzidADQAmPPR"
+                + "cZQwggMuMIICl6ADAgECAhEA0nYujRQMPX2yqCVdr+4NdTANBgkqhkiG9w0BAQIFADBfMQswCQYD"
+                + "VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xNzA1BgNVBAsTLkNsYXNzIDEgUHVibGlj"
+                + "IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNOTgwNTEyMDAwMDAwWhcNMDgwNTEy"
+                + "MjM1OTU5WjCBzDEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy"
+                + "dXN0IE5ldHdvcmsxRjBEBgNVBAsTPXd3dy52ZXJpc2lnbi5jb20vcmVwb3NpdG9yeS9SUEEgSW5j"
+                + "b3JwLiBCeSBSZWYuLExJQUIuTFREKGMpOTgxSDBGBgNVBAMTP1ZlcmlTaWduIENsYXNzIDEgQ0Eg"
+                + "SW5kaXZpZHVhbCBTdWJzY3JpYmVyLVBlcnNvbmEgTm90IFZhbGlkYXRlZDCBnzANBgkqhkiG9w0B"
+                + "AQEFAAOBjQAwgYkCgYEAu1pEigQWu1X9A3qKLZRPFXg2uA1Ksm+cVL+86HcqnbnwaLuV2TFBcHqB"
+                + "S7lIE1YtxwjhhEKrwKKSq0RcqkLwgg4C6S/7wju7vsknCl22sDZCM7VuVIhPh0q/Gdr5FegPh7Yc"
+                + "48zGmo5/aiSS4/zgZbqnsX7vyds3ashKyAkG5JkCAwEAAaN8MHowEQYJYIZIAYb4QgEBBAQDAgEG"
+                + "MEcGA1UdIARAMD4wPAYLYIZIAYb4RQEHAQEwLTArBggrBgEFBQcCARYfd3d3LnZlcmlzaWduLmNv"
+                + "bS9yZXBvc2l0b3J5L1JQQTAPBgNVHRMECDAGAQH/AgEAMAsGA1UdDwQEAwIBBjANBgkqhkiG9w0B"
+                + "AQIFAAOBgQCIuDc73dqUNwCtqp/hgQFxHpJqbS/28Z3TymQ43BuYDAeGW4UVag+5SYWklfEXfWe0"
+                + "fy0s3ZpCnsM+tI6q5QsG3vJWKvozx74Z11NMw73I4xe1pElCY+zCphcPXVgaSTyQXFWjZSAA/Rgg"
+                + "5V+CprGoksVYasGNAzzrw80FopCubjCCA/gwggNhoAMCAQICEBbbn/1G1zppD6KsP01bwywwDQYJ"
+                + "KoZIhvcNAQEEBQAwgcwxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln"
+                + "biBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3JlcG9zaXRvcnkvUlBB"
+                + "IEluY29ycC4gQnkgUmVmLixMSUFCLkxURChjKTk4MUgwRgYDVQQDEz9WZXJpU2lnbiBDbGFzcyAx"
+                + "IENBIEluZGl2aWR1YWwgU3Vic2NyaWJlci1QZXJzb25hIE5vdCBWYWxpZGF0ZWQwHhcNMDAxMDAy"
+                + "MDAwMDAwWhcNMDAxMjAxMjM1OTU5WjCCAQcxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYD"
+                + "VQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMUYwRAYDVQQLEz13d3cudmVyaXNpZ24uY29tL3Jl"
+                + "cG9zaXRvcnkvUlBBIEluY29ycC4gYnkgUmVmLixMSUFCLkxURChjKTk4MR4wHAYDVQQLExVQZXJz"
+                + "b25hIE5vdCBWYWxpZGF0ZWQxJzAlBgNVBAsTHkRpZ2l0YWwgSUQgQ2xhc3MgMSAtIE1pY3Jvc29m"
+                + "dDETMBEGA1UEAxQKRGF2aWQgUnlhbjElMCMGCSqGSIb3DQEJARYWZGF2aWRAbGl2ZW1lZGlhLmNv"
+                + "bS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAqxBsdeNmSvFqhMNwhQgNzM8mdjX9eSXb"
+                + "DawpHtQHjmh0AKJSa3IwUY0VIsyZHuXWktO/CgaMBVPt6OVf/n0R2sQigMP6Y+PhEiS0vCJBL9aK"
+                + "0+pOo2qXrjVBmq+XuCyPTnc+BOSrU26tJsX0P9BYorwySiEGxGanBNATdVL4NdUCAwEAAaOBnDCB"
+                + "mTAJBgNVHRMEAjAAMEQGA1UdIAQ9MDswOQYLYIZIAYb4RQEHAQgwKjAoBggrBgEFBQcCARYcaHR0"
+                + "cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTARBglghkgBhvhCAQEEBAMCB4AwMwYDVR0fBCwwKjAo"
+                + "oCagJIYiaHR0cDovL2NybC52ZXJpc2lnbi5jb20vY2xhc3MxLmNybDANBgkqhkiG9w0BAQQFAAOB"
+                + "gQBC8yIIdVGpFTf8/YiL14cMzcmL0nIRm4kGR3U59z7UtcXlfNXXJ8MyaeI/BnXwG/gD5OKYqW6R"
+                + "yca9vZOxf1uoTBl82gInk865ED3Tej6msCqFzZffnSUQvOIeqLxxDlqYRQ6PmW2nAnZeyjcnbI5Y"
+                + "syQSM2fmo7n6qJFP+GbFezGCAkUwggJBAgEBMIHhMIHMMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5j"
+                + "LjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazFGMEQGA1UECxM9d3d3LnZlcmlzaWdu"
+                + "LmNvbS9yZXBvc2l0b3J5L1JQQSBJbmNvcnAuIEJ5IFJlZi4sTElBQi5MVEQoYyk5ODFIMEYGA1UE"
+                + "AxM/VmVyaVNpZ24gQ2xhc3MgMSBDQSBJbmRpdmlkdWFsIFN1YnNjcmliZXItUGVyc29uYSBOb3Qg"
+                + "VmFsaWRhdGVkAhAW25/9Rtc6aQ+irD9NW8MsMAkGBSsOAwIaBQCggbowGAYJKoZIhvcNAQkDMQsG"
+                + "CSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMDAxMDAyMTczNTE4WjAjBgkqhkiG9w0BCQQxFgQU"
+                + "gZjSaBEY2oxGvlQUIMnxSXhivK8wWwYJKoZIhvcNAQkPMU4wTDAKBggqhkiG9w0DBzAOBggqhkiG"
+                + "9w0DAgICAIAwDQYIKoZIhvcNAwICAUAwBwYFKw4DAgcwDQYIKoZIhvcNAwICASgwBwYFKw4DAh0w"
+                + "DQYJKoZIhvcNAQEBBQAEgYAzk+PU91/ZFfoiuKOECjxEh9fDYE2jfDCheBIgh5gdcCo+sS1WQs8O"
+                + "HreQ9Nop/JdJv1DQMBK6weNBBDoP0EEkRm1XCC144XhXZC82jBZohYmi2WvDbbC//YN58kRMYMyy"
+                + "srrfn4Z9I+6kTriGXkrpGk9Q0LSGjmG2BIsqiF0dvwAAAAAAAA==");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert6));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading sixth test certificate. (Pkcs7)");
+			}
+
+
+            //
+            // dsaWithSHA1 cert
+            //
+            byte[] cert7 = Base64.Decode(
+                  "MIIEXAYJKoZIhvcNAQcCoIIETTCCBEkCAQExCzAJBgUrDgMCGgUAMAsGCSqG"
+                + "SIb3DQEHAaCCAsMwggK/MIIB4AIBADCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7"
+                + "d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULjw3GobwaJX13kquPh"
+                + "fVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABj"
+                + "TUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/z"
+                + "m8Q12PFp/PjOhh+nMA4xDDAKBgNVBAMTA0lEMzAeFw05NzEwMDEwMDAwMDBa"
+                + "Fw0zODAxMDEwMDAwMDBaMA4xDDAKBgNVBAMTA0lEMzCB8DCBpwYFKw4DAhsw"
+                + "gZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61TX5k+7NU4XPf1TULj"
+                + "w3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BUj+pJOF9ROBM4u+FE"
+                + "WA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqjijUHfXKTrHL1OEqV3"
+                + "SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nA0QAAkEAkYkXLYMtGVGWj9OnzjPn"
+                + "sB9sefSRPrVegZJCZbpW+Iv0/1RP1u04pHG9vtRpIQLjzUiWvLMU9EKQTThc"
+                + "eNMmWDCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxg"
+                + "Y61TX5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/Q"
+                + "F4BUj+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jH"
+                + "SqjijUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nAy8AMCwC"
+                + "FBY3dBSdeprGcqpr6wr3xbG+6WW+AhRMm/facKJNxkT3iKgJbp7R8Xd3QTGC"
+                + "AWEwggFdAgEBMBMwDjEMMAoGA1UEAxMDSUQzAgEAMAkGBSsOAwIaBQCgXTAY"
+                + "BgkqhkiG9w0BCQMxCwYJKoZIhvcNAQcBMBwGCSqGSIb3DQEJBTEPFw0wMjA1"
+                + "MjQyMzEzMDdaMCMGCSqGSIb3DQEJBDEWBBS4WMsoJhf7CVbZYCFcjoTRzPkJ"
+                + "xjCBpwYFKw4DAhswgZ0CQQEkJRHP+mN7d8miwTMN55CUSmo3TO8WGCxgY61T"
+                + "X5k+7NU4XPf1TULjw3GobwaJX13kquPhfVXk+gVy46n4Iw3hAhUBSe/QF4BU"
+                + "j+pJOF9ROBM4u+FEWA8CQQD4mSJbrABjTUWrlnAte8pS22Tq4/FPO7jHSqji"
+                + "jUHfXKTrHL1OEqV3SVWcFy5j/cqBgX/zm8Q12PFp/PjOhh+nBC8wLQIVALID"
+                + "dt+MHwawrDrwsO1Z6sXBaaJsAhRaKssrpevmLkbygKPV07XiAKBG02Zvb2Jh"
+                + "cg==");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(cert7));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading seventh test certificate. (DSAWITHSHA1)");
+			}
+
+
+            //
+            // ecdsa cert with extra octet string.
+            //
+            byte[] oldEcdsa = Base64.Decode(
+                  "MIICljCCAkCgAwIBAgIBATALBgcqhkjOPQQBBQAwgY8xCzAJBgNVBAYTAkFVMSgwJ"
+                + "gYDVQQKEx9UaGUgTGVnaW9uIG9mIHRoZSBCb3VuY3kgQ2FzdGxlMRIwEAYDVQQHEw"
+                + "lNZWxib3VybmUxETAPBgNVBAgTCFZpY3RvcmlhMS8wLQYJKoZIhvcNAQkBFiBmZWV"
+                + "kYmFjay1jcnlwdG9AYm91bmN5Y2FzdGxlLm9yZzAeFw0wMTEyMDcwMTAwMDRaFw0w"
+                + "MTEyMDcwMTAxNDRaMIGPMQswCQYDVQQGEwJBVTEoMCYGA1UEChMfVGhlIExlZ2lvb"
+                + "iBvZiB0aGUgQm91bmN5IENhc3RsZTESMBAGA1UEBxMJTWVsYm91cm5lMREwDwYDVQ"
+                + "QIEwhWaWN0b3JpYTEvMC0GCSqGSIb3DQEJARYgZmVlZGJhY2stY3J5cHRvQGJvdW5"
+                + "jeWNhc3RsZS5vcmcwgeQwgb0GByqGSM49AgEwgbECAQEwKQYHKoZIzj0BAQIef///"
+                + "////////////f///////gAAAAAAAf///////MEAEHn///////////////3///////"
+                + "4AAAAAAAH///////AQeawFsO9zxiUHQ1lSSFHXKcanbL7J9HTd5YYXClCwKBB8CD/"
+                + "qWPNyogWzMM7hkK+35BcPTWFc9Pyf7vTs8uaqvAh5///////////////9///+eXpq"
+                + "fXZBx+9FSJoiQnQsDIgAEHwJbbcU7xholSP+w9nFHLebJUhqdLSU05lq/y9X+DHAw"
+                + "CwYHKoZIzj0EAQUAA0MAMEACHnz6t4UNoVROp74ma4XNDjjGcjaqiIWPZLK8Bdw3G"
+                + "QIeLZ4j3a6ividZl344UH+UPUE7xJxlYGuy7ejTsqRR");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(oldEcdsa));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading old ECDSA Certificate.");
+			}
+
+
+            byte[] uncompressedPtEC = Base64.Decode(
+                  "MIIDKzCCAsGgAwIBAgICA+kwCwYHKoZIzj0EAQUAMGYxCzAJBgNVBAYTAkpQ"
+                + "MRUwEwYDVQQKEwxuaXRlY2guYWMuanAxDjAMBgNVBAsTBWFpbGFiMQ8wDQYD"
+                + "VQQDEwZ0ZXN0Y2ExHzAdBgkqhkiG9w0BCQEWEHRlc3RjYUBsb2NhbGhvc3Qw"
+                + "HhcNMDExMDEzMTE1MzE3WhcNMjAxMjEyMTE1MzE3WjBmMQswCQYDVQQGEwJK"
+                + "UDEVMBMGA1UEChMMbml0ZWNoLmFjLmpwMQ4wDAYDVQQLEwVhaWxhYjEPMA0G"
+                + "A1UEAxMGdGVzdGNhMR8wHQYJKoZIhvcNAQkBFhB0ZXN0Y2FAbG9jYWxob3N0"
+                + "MIIBczCCARsGByqGSM49AgEwggEOAgEBMDMGByqGSM49AQECKEdYWnajFmnZ"
+                + "tzrukK2XWdle2v+GsD9l1ZiR6g7ozQDbhFH/bBiMDQcwVAQoJ5EQKrI54/CT"
+                + "xOQ2pMsd/fsXD+EX8YREd8bKHWiLz8lIVdD5cBNeVwQoMKSc6HfI7vKZp8Q2"
+                + "zWgIFOarx1GQoWJbMcSt188xsl30ncJuJT2OoARRBAqJ4fD+q6hbqgNSjTQ7"
+                + "htle1KO3eiaZgcJ8rrnyN8P+5A8+5K+H9aQ/NbBR4Gs7yto5PXIUZEUgodHA"
+                + "TZMSAcSq5ZYt4KbnSYaLY0TtH9CqAigEwZ+hglbT21B7ZTzYX2xj0x+qooJD"
+                + "hVTLtIPaYJK2HrMPxTw6/zfrAgEPA1IABAnvfFcFDgD/JicwBGn6vR3N8MIn"
+                + "mptZf/mnJ1y649uCF60zOgdwIyI7pVSxBFsJ7ohqXEHW0x7LrGVkdSEiipiH"
+                + "LYslqh3xrqbAgPbl93GUo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB"
+                + "/wQEAwIBxjAdBgNVHQ4EFgQUAEo62Xm9H6DcsE0zUDTza4BRG90wCwYHKoZI"
+                + "zj0EAQUAA1cAMFQCKAQsCHHSNOqfJXLgt3bg5+k49hIBGVr/bfG0B9JU3rNt"
+                + "Ycl9Y2zfRPUCKAK2ccOQXByAWfsasDu8zKHxkZv7LVDTFjAIffz3HaCQeVhD"
+                + "z+fauEg=");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(uncompressedPtEC));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading uncompressed ECPoint Certificate.");
+			}
+
+
+			byte[] keyUsage = Base64.Decode(
+                  "MIIE7TCCBFagAwIBAgIEOAOR7jANBgkqhkiG9w0BAQQFADCByTELMAkGA1UE"
+                + "BhMCVVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MUgwRgYDVQQLFD93d3cuZW50"
+                + "cnVzdC5uZXQvQ2xpZW50X0NBX0luZm8vQ1BTIGluY29ycC4gYnkgcmVmLiBs"
+                + "aW1pdHMgbGlhYi4xJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExp"
+                + "bWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENsaWVudCBDZXJ0aWZpY2F0"
+                + "aW9uIEF1dGhvcml0eTAeFw05OTEwMTIxOTI0MzBaFw0xOTEwMTIxOTU0MzBa"
+                + "MIHJMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxSDBGBgNV"
+                + "BAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0FfSW5mby9DUFMgaW5jb3Jw"
+                + "LiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UECxMcKGMpIDE5OTkgRW50"
+                + "cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5uZXQgQ2xpZW50"
+                + "IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GL"
+                + "ADCBhwKBgQDIOpleMRffrCdvkHvkGf9FozTC28GoT/Bo6oT9n3V5z8GKUZSv"
+                + "x1cDR2SerYIbWtp/N3hHuzeYEpbOxhN979IMMFGpOZ5V+Pux5zDeg7K6PvHV"
+                + "iTs7hbqqdCz+PzFur5GVbgbUB01LLFZHGARS2g4Qk79jkJvh34zmAqTmT173"
+                + "iwIBA6OCAeAwggHcMBEGCWCGSAGG+EIBAQQEAwIABzCCASIGA1UdHwSCARkw"
+                + "ggEVMIHkoIHhoIHepIHbMIHYMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50"
+                + "cnVzdC5uZXQxSDBGBgNVBAsUP3d3dy5lbnRydXN0Lm5ldC9DbGllbnRfQ0Ff"
+                + "SW5mby9DUFMgaW5jb3JwLiBieSByZWYuIGxpbWl0cyBsaWFiLjElMCMGA1UE"
+                + "CxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50"
+                + "cnVzdC5uZXQgQ2xpZW50IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYD"
+                + "VQQDEwRDUkwxMCygKqAohiZodHRwOi8vd3d3LmVudHJ1c3QubmV0L0NSTC9D"
+                + "bGllbnQxLmNybDArBgNVHRAEJDAigA8xOTk5MTAxMjE5MjQzMFqBDzIwMTkx"
+                + "MDEyMTkyNDMwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUxPucKXuXzUyW"
+                + "/O5bs8qZdIuV6kwwHQYDVR0OBBYEFMT7nCl7l81MlvzuW7PKmXSLlepMMAwG"
+                + "A1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI"
+                + "hvcNAQEEBQADgYEAP66K8ddmAwWePvrqHEa7pFuPeJoSSJn59DXeDDYHAmsQ"
+                + "OokUgZwxpnyyQbJq5wcBoUv5nyU7lsqZwz6hURzzwy5E97BnRqqS5TvaHBkU"
+                + "ODDV4qIxJS7x7EU47fgGWANzYrAQMY9Av2TgXD7FTx/aEkP/TOYGJqibGapE"
+                + "PHayXOw=");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(keyUsage));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading Cert with Key Usage.");
+			}
+
+
+            byte[] nameCert = Base64.Decode(
+                "MIIEFjCCA3+gAwIBAgIEdS8BozANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJE" +
+                "RTERMA8GA1UEChQIREFURVYgZUcxKDAMBgcCggYBCgcUEwExMBgGA1UEAxQRQ0Eg" +
+                "REFURVYgRDAzIDE6UE4wIhgPMjAwMTA1MTAxMDIyNDhaGA8yMDA0MDUwOTEwMjI0" +
+                "OFowgYQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIFAZCYXllcm4xEjAQBgNVBAcUCU7I" +
+                "dXJuYmVyZzERMA8GA1UEChQIREFURVYgZUcxHTAbBgNVBAUTFDAwMDAwMDAwMDA4" +
+                "OTU3NDM2MDAxMR4wHAYDVQQDFBVEaWV0bWFyIFNlbmdlbmxlaXRuZXIwgaEwDQYJ" +
+                "KoZIhvcNAQEBBQADgY8AMIGLAoGBAJLI/LJLKaHoMk8fBECW/od8u5erZi6jI8Ug" +
+                "C0a/LZyQUO/R20vWJs6GrClQtXB+AtfiBSnyZOSYzOdfDI8yEKPEv8qSuUPpOHps" +
+                "uNCFdLZF1vavVYGEEWs2+y+uuPmg8q1oPRyRmUZ+x9HrDvCXJraaDfTEd9olmB/Z" +
+                "AuC/PqpjAgUAwAAAAaOCAcYwggHCMAwGA1UdEwEB/wQCMAAwDwYDVR0PAQH/BAUD" +
+                "AwdAADAxBgNVHSAEKjAoMCYGBSskCAEBMB0wGwYIKwYBBQUHAgEWD3d3dy56cy5k" +
+                "YXRldi5kZTApBgNVHREEIjAggR5kaWV0bWFyLnNlbmdlbmxlaXRuZXJAZGF0ZXYu" +
+                "ZGUwgYQGA1UdIwR9MHuhc6RxMG8xCzAJBgNVBAYTAkRFMT0wOwYDVQQKFDRSZWd1" +
+                "bGllcnVuZ3NiZWjIb3JkZSBmyHVyIFRlbGVrb21tdW5pa2F0aW9uIHVuZCBQb3N0" +
+                "MSEwDAYHAoIGAQoHFBMBMTARBgNVBAMUCjVSLUNBIDE6UE6CBACm8LkwDgYHAoIG" +
+                "AQoMAAQDAQEAMEcGA1UdHwRAMD4wPKAUoBKGEHd3dy5jcmwuZGF0ZXYuZGWiJKQi" +
+                "MCAxCzAJBgNVBAYTAkRFMREwDwYDVQQKFAhEQVRFViBlRzAWBgUrJAgDBAQNMAsT" +
+                "A0VVUgIBBQIBATAdBgNVHQ4EFgQUfv6xFP0xk7027folhy+ziZvBJiwwLAYIKwYB" +
+                "BQUHAQEEIDAeMBwGCCsGAQUFBzABhhB3d3cuZGlyLmRhdGV2LmRlMA0GCSqGSIb3" +
+                "DQEBBQUAA4GBAEOVX6uQxbgtKzdgbTi6YLffMftFr2mmNwch7qzpM5gxcynzgVkg" +
+                "pnQcDNlm5AIbS6pO8jTCLfCd5TZ5biQksBErqmesIl3QD+VqtB+RNghxectZ3VEs" +
+                "nCUtcE7tJ8O14qwCb3TxS9dvIUFiVi4DjbxX46TdcTbTaK8/qr6AIf+l");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(nameCert));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading Named Certificate.");
+			}
+
+
+			byte[] probSelfSignedCert = Base64.Decode(
+                   "MIICxTCCAi6gAwIBAgIQAQAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQUFADBF"
+                 + "MScwJQYDVQQKEx4gRElSRUNUSU9OIEdFTkVSQUxFIERFUyBJTVBPVFMxGjAYBgNV"
+                 + "BAMTESBBQyBNSU5FRkkgQiBURVNUMB4XDTA0MDUwNzEyMDAwMFoXDTE0MDUwNzEy"
+                 + "MDAwMFowRTEnMCUGA1UEChMeIERJUkVDVElPTiBHRU5FUkFMRSBERVMgSU1QT1RT"
+                 + "MRowGAYDVQQDExEgQUMgTUlORUZJIEIgVEVTVDCBnzANBgkqhkiG9w0BAQEFAAOB"
+                 + "jQAwgYkCgYEAveoCUOAukZdcFCs2qJk76vSqEX0ZFzHqQ6faBPZWjwkgUNwZ6m6m"
+                 + "qWvvyq1cuxhoDvpfC6NXILETawYc6MNwwxsOtVVIjuXlcF17NMejljJafbPximEt"
+                 + "DQ4LcQeSp4K7FyFlIAMLyt3BQ77emGzU5fjFTvHSUNb3jblx0sV28c0CAwEAAaOB"
+                 + "tTCBsjAfBgNVHSMEGDAWgBSEJ4bLbvEQY8cYMAFKPFD1/fFXlzAdBgNVHQ4EFgQU"
+                 + "hCeGy27xEGPHGDABSjxQ9f3xV5cwDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIB"
+                 + "AQQEAwIBBjA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vYWRvbmlzLnBrNy5jZXJ0"
+                 + "cGx1cy5uZXQvZGdpLXRlc3QuY3JsMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN"
+                 + "AQEFBQADgYEAmToHJWjd3+4zknfsP09H6uMbolHNGG0zTS2lrLKpzcmkQfjhQpT9"
+                 + "LUTBvfs1jdjo9fGmQLvOG+Sm51Rbjglb8bcikVI5gLbclOlvqLkm77otjl4U4Z2/"
+                 + "Y0vP14Aov3Sn3k+17EfReYUZI4liuB95ncobC4e8ZM++LjQcIM0s+Vs=");
+
+			try
+			{
+				Assert.IsNotNull(new X509CertificateParser().ReadCertificate(probSelfSignedCert));
+			}
+			catch (Exception)
+			{
+				Assert.Fail("Reading busted Certificate.");
+			}
+		}
+	}
+}
diff --git a/BouncyCastle.AxCrypt/testcfg.nunit b/BouncyCastle.AxCrypt/testcfg.nunit
new file mode 100644
index 0000000..e4061da
--- /dev/null
+++ b/BouncyCastle.AxCrypt/testcfg.nunit
@@ -0,0 +1,6 @@
+<NUnitProject>
+  <Settings activeconfig="Default" />
+  <Config name="Default" binpathtype="Auto">
+    <assembly path="./test/bin/BCTest.dll" />
+  </Config>
+</NUnitProject>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..f9b518b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,6015 @@
+2014-09-14 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor where types are registered to facilitate for other targets
+	[4ac08ba9d9c2]tip
+
+2014-09-13 Svante Seleborg <svante at axantum.com>
+
+ 	* Building in Visual Studio, MonoDevelop and Xamarin Studio is not
+	easy
+	[1dff961f23b5]
+
+2014-09-12 svante <svante at axantum.com>
+
+ 	* Updates for Linux build compatibility
+	[b0c8720e3d5d]
+
+2014-09-13 Svante Seleborg <svante at axantum.com>
+
+ 	* Update factory registration, change portable library profile
+	[ff7db403aaf4]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Update ignore list
+	[a372972fcadc]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Repair test broken after move to different assembly
+	[189232f9ded1]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* AxCrypt-MonoTouch builds (but does not quite run) again
+	[28e001dd8dd5]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Add strong name file
+	[94f1872b70bc]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix a compilation error on Xamarin
+	[c5211b6cbaf5]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Move FileWatcher and DataProtection to new Desktop assembly so the
+	mono assembly can be used in iOS and Android
+	[3667d6fabc58]
+
+2014-09-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Move DataProtection into the Forms / Desktop assembly
+	[1ac44e51c218]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove unused method, which is not supported in iOS and Android
+	[dae5a186f269]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Changes to .csproj-files enforced by Xamarin Studio
+	[6bde83e74a9a]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Removed unused fields to compile in Xamarin Studio
+	[4fc9d4c22dfd]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Merge of changes for Xamarin build
+	[5ed98645ca39]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove extra files
+	[f94f0c65040e]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove extra files
+	[0964589e37e7]
+
+2014-09-10 Svante Seleborg <svante at axantum.com>
+
+ 	* Major refactoring to enable Portable Class Library build, and update
+	to .NET 4.5
+	[36ce2b1892e4]
+
+2014-09-06 Svante Seleborg <svante at axantum.com>
+
+ 	* Various minor fixes in order to compile and pass unit tests in
+	Xamarin Studion on Mac
+	[28ba9329d800]
+
+2014-09-06 Svante Seleborg <svante at axantum.com>
+
+ 	* Add basic support for asymmetric key wrap header blocks
+	[60e8c66ac078]
+
+2014-08-28 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix to use V2-encryption for the AsymmetricKeysStore.
+	[fd6797ea568e]
+
+2014-08-28 Svante Seleborg <svante at axantum.com>
+
+ 	* Support for login to AsymmetricUserKeysStore.
+	[dd9a5fb882c0]
+
+2014-08-21 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug with update of recent files
+	[074739973d1c]
+
+2014-08-14 Svante Seleborg <svante at axantum.com>
+
+ 	* Add support for asymmetric recpients in file header
+	[e115427bdc55]
+
+2014-08-14 Svante Seleborg <svante at axantum.com>
+
+ 	* RSA OEAP validation tests suite complete
+	[7ee5f9240327]
+
+2014-08-14 Svante Seleborg <svante at axantum.com>
+
+ 	* RSA OEAP validation tests, Example 6
+	[192c7053a2e8]
+
+2014-08-14 Svante Seleborg <svante at axantum.com>
+
+ 	* RSA OEAP validation tests, Example 5
+	[6b331d2fffb2]
+
+2014-08-13 Svante Seleborg <svante at axantum.com>
+
+ 	* More RSA OAEP validation tests, fixed Example 3.4
+	[4fed56470429]
+
+2014-08-13 Svante Seleborg <svante at axantum.com>
+
+ 	* More RSA OAEP validation tests
+	[f85eca0dfa2f]
+
+2014-08-12 Svante Seleborg <svante at axantum.com>
+
+ 	* More RSA OAEP validation tests
+	[65c4c064d7ab]
+
+2014-08-12 Svante Seleborg <svante at axantum.com>
+
+ 	* Add RSA OAEP validation tests, example 1.
+	[aa4de3a37a07]
+
+2014-08-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor and implement the asymmetric core code
+	[06a04b1d67b9]
+
+2014-08-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Basic implementation of RSA-encryption with OAEP padding
+	[6d9bf9781792]
+
+2014-08-02 svante <svante at axantum.com>
+
+ 	* Continued work on Managed (Asymmetric) Encryption
+	[00c88bdbddee]
+
+2014-07-31 svante <svante at axantum.com>
+
+ 	* Some initial low level code for managed (public key) encryption
+	[3e5e43dc1e70]
+
+2014-07-24 Svante Seleborg <svante at axantum.com>
+
+ 	* Improve handling of document opening in Windows 8 apps.
+	[f93cc92a7ded]
+
+2014-07-23 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug causing unnecessary re-encryptions when opening files.
+	[2b64bf3df578]
+
+2014-07-21 Svante Seleborg <svante at axantum.com>
+
+ 	* Change how files are opened from the Windows Explorer interface.
+	[338a01df31fc]
+
+2014-07-21 Svante Seleborg <svante at axantum.com>
+
+ 	* Minor fix to the fix to avoid risk for dead-lock in ThreadWorker
+	[adccdcd8e0ca]
+
+2014-07-20 Svante Seleborg <svante at axantum.com>
+
+ 	* Minor fix to avoid risk for dead-lock in ThreadWorker
+	[893431ba1d9f]
+
+2014-07-03 svante <svante at axantum.com>
+
+ 	* Fix a race condition in Dispose() of ThreadWorker()
+	[f31955618983]
+
+2014-07-03 svante <svante at axantum.com>
+
+ 	* Interim checkin - continued work on watched folder dialog.
+	[a9ed8456c7c6]
+
+2014-07-03 svante <svante at axantum.com>
+
+ 	* Interim checkin - working on moving away from tabbed view in main.
+	[4d0bab4b3bf8]
+
+2014-07-03 svante <svante at axantum.com>
+
+ 	* Fix bug when opening file with a second passphrase. (Cascading fixes
+	due to change in identity handling.)
+	[7c7ebc4f447c]
+
+2014-06-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Start process of removing tabs, by moving logging to a non-modal
+	window.
+	[cb9d8617d586]
+
+2014-06-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix MSBuild bug causing external projects to fail.
+	[2494c556039e]
+
+2014-06-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix issues caused by the removal of the named identity concept.
+	[343c40e62553]
+
+2014-06-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix MSBuild script bug causing unnecessary rebuilds.
+	[81867461931a]
+
+2014-06-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove concept of named 'classic' passphrase identities.
+	[80013b05e82b]
+
+2014-06-05 svante <svante at axantum.com>
+
+ 	* Fix bug where file was deleted before opened. Tweak UI handling of
+	windows restoration etc.
+	[b0b2a7e09a5d]
+
+2014-06-04 svante <svante at axantum.com>
+
+ 	* Support pending request on startup.
+	[ab5ea9d76e1f]
+
+2014-06-04 svante <svante at axantum.com>
+
+ 	* Enforce log on at startup.
+	[ed5127f67bd2]
+
+2014-06-02 svante <svante at axantum.com>
+
+ 	* Clean empty work folder directories after re-encryption.
+	[8368946d8841]
+
+2014-06-02 svante <svante at axantum.com>
+
+ 	* Fix bug where files got decrypted to the wrong location when
+	encrypted files are dropped into the recent files list.
+	[8ad381ce0920]
+
+2014-06-02 svante <svante at axantum.com>
+
+ 	* Minor changes to reduce flickering in the listview a little bit.
+	Still a problem though.
+	[1b2324fc02f7]
+
+2014-06-01 svante <svante at axantum.com>
+
+ 	* Minor rename of ActiveFileStatus.NoLongerActive => Inactive
+	[e8bd6d23185b]
+
+2014-06-01 svante <svante at axantum.com>
+
+ 	* Fix issues occuring when files are renamed/moved/deleted/updated
+	etc. Do not actually remove files from ActiveFiles, just mark them
+	as inactive.
+	[567c7bf51ff6]
+
+2014-06-01 svante <svante at axantum.com>
+
+ 	* Fix ILMerge against .NET 4.5 but the target is actually .NET 4.0,
+	causing failure if .NET 4.5 is not installed.
+	[0aa683eab859]
+
+2014-05-31 svante <svante at axantum.com>
+
+ 	* Add Json.NET as a source code dependency.
+	[3a730423a7a0]
+
+2014-05-31 svante <svante at axantum.com>
+
+ 	* Merge
+	[14e9b269f1f9]
+
+2014-05-31 svante <svante at axantum.com>
+
+ 	* Retarget BounceCastle.AxCrypt again to .NET 4.0 since the PCL
+	profile requires a much more complex build environment, including
+	Phone SDK.
+	[c96e2577ae2d]
+
+2014-05-31 Svante Seleborg <svante at axantum.com>
+
+ 	* README.md edited online with Bitbucket
+	[09cf4501cc65]
+
+2014-05-31 Svante Seleborg <svante at axantum.com>
+
+ 	* README.md edited online with Bitbucket
+	[b29ca21a9e6a]
+
+2014-05-31 Svante Seleborg <svante at axantum.com>
+
+ 	* README.md edited online with Bitbucket
+	[8580ae3b445d]
+
+2014-05-31 svante <svante at axantum.com>
+
+ 	* Add BouncyCastle as a source code dependency instead of binary.
+	Retarget to .NET 4 again. Fix minor bug when adding new encrypted
+	files.
+	[2f32d88c3b8a]
+
+2014-05-20 svante <svante at axantum.com>
+
+ 	* Support notification of renamed encrypted files, so recent files
+	list may be kept updated.
+	[f40b3e89fdf8]
+
+2014-05-20 svante <svante at axantum.com>
+
+ 	* Watch folders with active files for disappearences of active files
+	so the ActiveFiles list can be updated accordingly.
+	[38b54304c624]
+
+2014-05-19 svante <svante at axantum.com>
+
+ 	* Refactor to make unit testing full file decryption less painful,
+	also preparing for new strategy handling IAxCryptDocument - using a
+	masterkey cache rather than keeping document instances around with
+	open streams etc.
+	[6c0c54ec8b08]
+
+2014-05-19 svante <svante at axantum.com>
+
+ 	* Add regression tests for V2 AES-128 decryption
+	[12539f689617]
+
+2014-05-19 svante <svante at axantum.com>
+
+ 	* Added regression tests for V2 AES-256 decryption.
+	[a7fe632ebdf5]
+
+2014-05-19 svante <svante at axantum.com>
+
+ 	* Minor change of RewrapMasterKey - pass keyWrapIterations as a
+	parameter so it too can be updated when the master key is rewrapped.
+	[94f0e7360178]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Minor refactoring
+	[e270808a1a12]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Remove unused parameter 'factory' from V2AesCrypto etc.
+	[5da43a30c54e]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* FxCop
+	[d4d59fa52c49]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Rename VxPassphrase to VxDerivedKey etc, as it is now more
+	appropriate.
+	[849268f88774]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Minor refactoring, moving the placement of crypto id-definitions
+	etc.
+	[f4058fcfa9ca]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Remove unused method from ICrypto
+	[292396038f39]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Rename ICryptoFactory methods to clearer names
+	[ae685e5b7379]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Refactor, reduce ICryptoFactory further by one superfluous method.
+	[158a9157dceb]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Refactor, remove redundant method from ICryptoFactory.
+	[2ced05ef028e]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Remove need for GenericPassphrase
+	[10e479dabc6f]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Refactor use SymmetricKey instead of IDerivedKey for Subkey
+	[079dd4ab77e5]
+
+2014-05-18 svante <svante at axantum.com>
+
+ 	* Refactor ICryptoFactory and ICrypto to use SymmetricKey instead of
+	IDerivedKey
+	[5e491bf1b2a7]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refactor away CryptoId from IDerivedKey
+	[19983ce6a443]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refactor away Passphrase property of IDerivedKey
+	[539989b3bebe]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refactor. Remvoe one more use of Passphrase property of IDerivedKey.
+	[a663ba3562a6]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refctor. Remove one more use of Passphrase property of IDerivedKey.
+	[55b5fbb404c8]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refactoring identifying crypto id from known passphrases etc.
+	[435094a2a6c1]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* More cleanup, now it seems fairly stable again.
+	[71460c6c32f9]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Cleanup IDerivedKey - remove superfluous Thumbprint property
+	[a9a30326596c]
+
+2014-05-17 svante <svante at axantum.com>
+
+ 	* Refactor Passphrase/IDerviedKey - basic functionality restored.
+	[a711e53bfd96]
+
+2014-05-16 svante <svante at axantum.com>
+
+ 	* Interim checkin - refactor Passphrase/IDerivedKey. BROKEN! DO NOT
+	USE!
+	[c3766b45f12a]
+
+2014-05-16 svante <svante at axantum.com>
+
+ 	* Add Passphrase implementation, preparing for removing passphrase
+	from IDerivedKey
+	[05a7e31e5deb]
+
+2014-05-16 svante <svante at axantum.com>
+
+ 	* Rename IPassphrase to the much more appropriate IDerivedKey
+	[42bb1d3fad00]
+
+2014-05-15 svante <svante at axantum.com>
+
+ 	* Make sure ilmerge uses the correct name for languages to work.
+	[34d1c201d210]
+
+2014-05-14 svante <svante at axantum.com>
+
+ 	* Support running the setup project interactively with a potentially
+	re- merged executable.
+	[99409deb52ce]
+
+2014-05-14 svante <svante at axantum.com>
+
+ 	* Fix bug where it crashes if non-.NET assemblies are in the folder.
+	[ea11496e2ca2]
+
+2014-05-13 svante <svante at axantum.com>
+
+ 	* Do not delaysign with ILMerge when building GPL build. Use .NET 4.5
+	reference assemblies for ILMerge.
+	[44c5c28d136f]
+
+2014-05-13 svante <svante at axantum.com>
+
+ 	* Use installed ILMerge instead of embedded
+	[035bc31e90c1]
+
+2014-05-13 svante <svante at axantum.com>
+
+ 	* Fix so ilmerge is run even when not internal build
+	[f74c0a61a742]
+
+2014-05-13 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix so ilmerge is run even if we're not signing.
+	[1bdab479d800]
+
+2014-05-13 svante <svante at axantum.com>
+
+ 	* Update target framework version to be consistently 4.5
+	[66e83983a249]
+
+2014-05-12 svante <svante at axantum.com>
+
+ 	* Fix name of executable in MSBuild script
+	[ae46bb144969]
+
+2014-05-12 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix path to authenticode signing tool
+	[3c51a978a433]
+
+2014-05-11 svante <svante at axantum.com>
+
+ 	* Implement priority-based default crypto policy, and a property to
+	support disabling a policy such as 'Pro'.
+	[4993e9cab3df]
+
+2014-05-11 svante <svante at axantum.com>
+
+ 	* Refactor the build slightly
+	[e348c06944b8]
+
+2014-05-11 svante <svante at axantum.com>
+
+ 	* Add some argument checking
+	[509e30f03540]
+
+2014-05-11 svante <svante at axantum.com>
+
+ 	* Fix potential bug with mistaken use of static in abstract
+	V2CryptoBase et. al. Also use correct TransformBlock, not
+	TransformFinalBlock in key wrap.
+	[79efbbb55e14]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Load ICryptoPolicy implementations dynamically
+	[928fa998692a]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Fix bug where locked files cause Unknown error for example when
+	encrypting.
+	[7ba319acf875]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Refactor the type discovery process to be generic in order to reuse.
+	[330c65493a82]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Remove dead code from CryptoPolicy - legacy selection is handled
+	otherwise.
+	[c9735e5d6980]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Clean up ICryptoPolicy
+	[f085f4103564]
+
+2014-05-10 svante <svante at axantum.com>
+
+ 	* Scan assemblies for ICryptoFactory implementations to use
+	[d8c0671969fb]
+
+2014-05-09 svante <svante at axantum.com>
+
+ 	* Move common V2 Crypto-code to V2CryptoBase
+	[b7d41cc9855d]
+
+2014-05-09 svante <svante at axantum.com>
+
+ 	* Correction of bad comment and dead definition.
+	[0bc9a4ea4dbf]
+
+2014-05-09 svante <svante at axantum.com>
+
+ 	* Remove concept of 'Preferred' CryptoFactory - that's controlled by
+	ICryptoPolicy and add concept of 'Minimum', which is independent of
+	the policy and use this for SymmetricThumbprint generation. Also
+	implement versioning support for settings and configuration. Only
+	reset supported now, but in the future it could be handled
+	transparently when possible.
+	[5a2cee000af8]
+
+2014-05-09 svante <svante at axantum.com>
+
+ 	* FxCop
+	[3f2d9b949e38]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix some static code analysis issues.
+	[6b2f6ec4d176]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Support decryption with the correct passphrase but under different
+	policy.
+	[b18b48f717fa]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor away some dead code.
+	[96b6ad7be193]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Use correct CryptoFactory in V2DocumentHeaders, not
+	CryptoPolicy.Default
+	[2c566b6c0fc2]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix failing unit test, and implement and support LegacyCryptoPolicy
+	[38a207360ed2]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Move ProgressBackground component to separate assembly to reduce
+	designer issues
+	[3d71835cef9a]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix building process, sometimes causing ILMerge to crash with
+	'Duplicate Types'
+	[9af5b4c1732f]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Support check-boxes for Crypto-policy choice
+	[caacbbd2ad37]
+
+2014-05-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Avoid exception when exiting sometimes.
+	[64db1059e9b0]
+
+2014-05-07 svante <svante at axantum.com>
+
+ 	* Tweak ILMerge process so the internal assembly name is properly set
+	to Axantum.AxCrypt.exe, regardless of the actual name AxCrypt.exe.
+	[6b9058ccff8c]
+
+2014-05-04 svante <svante at axantum.com>
+
+ 	* Remove warning about open files except when exiting, partially
+	because it's annoying and also because it won't be correct due to
+	the asynchronous nature of how the work is done.
+	[f6e56db25d18]
+
+2014-05-02 svante <svante at axantum.com>
+
+ 	* Change how form closing works to work on Mono as well
+	[9d56ab816ff5]
+
+2014-05-02 svante <svante at axantum.com>
+
+ 	* Change how validation works in order to work better on Mono which
+	does not support anything but the strictest AutoValidation mode.
+	[1d59c4f0a32b]
+
+2014-05-02 svante <svante at axantum.com>
+
+ 	* Improve behavior of LogOn dialog and validation
+	[54e8f9bf8572]
+
+2014-05-02 svante <svante at axantum.com>
+
+ 	* Avoid some Windows desktop-specific things on other platforms.
+	[00f6e563dd10]
+
+2014-05-02 svante <svante at axantum.com>
+
+ 	* Unfix irrelevant earlier attempted fix for Linux-problems.
+	[91e9508d05ae]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Remove unusual icon formats
+	[0e82f58ab6e5]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Revert resources, linking / embedding was not the problem.
+	[128098e76607]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Embed images in the resources.resx file for perhaps better Mono
+	compatibility
+	[7baac9d7c10c]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Embed the icons in the resources.resx file for perhaps better Mono
+	compatibility
+	[728226d4079d]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Fix yet another bug in V2AxCryptDataSTream that now only appeared in
+	.NET
+	[02ab855c8e65]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Fix bug V2AxCryptDataStream that did not appear in .NET but did in
+	Mono.
+	[f12a51bc13a1]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Fix Linux-incompatible test-setup
+	[7d00d275f2c4]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* More fixes to path handling to compensate for platform differences.
+	[75c0dfba4ceb]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Make handling of paths more agnostic to operating system differences
+	in directory path separator.
+	[a898187295fa]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Fix various, but not all, issues ocurring when building with
+	MonoDevelop on Linux
+	[cb5375bbf12e]
+
+2014-05-01 svante <svante at axantum.com>
+
+ 	* Fix various, but not all, issues ocurring when building with
+	MonoDevelop on Linux
+	[32c71da7eb9b]
+
+2014-04-30 svante <svante at axantum.com>
+
+ 	* Fix failing unit test.
+	[45de1198668d]
+
+2014-04-30 svante <svante at axantum.com>
+
+ 	* Update CommandLine handling to a more reasonable syntax and use.
+	[edb2a23131f9]
+
+2014-04-20 svante <svante at axantum.com>
+
+ 	* Support random rename of encrypted files from command line / shell
+	extension.
+	[b5d388c3760e]
+
+2014-04-19 svante <svante at axantum.com>
+
+ 	* Change revision numbering scheme to use build number instead of VCS
+	revision.
+	[318bf8e21520]
+
+2014-04-18 svante <svante at axantum.com>
+
+ 	* Fix options bug, and support registration (simple via URL, but
+	still).
+	[491d0527a146]
+
+2014-04-18 svante <svante at axantum.com>
+
+ 	* Add basic support for 'About' in Windows Explorer Shell Extension
+	[5fe6c23b3532]
+
+2014-04-18 svante <svante at axantum.com>
+
+ 	* Basic support for wipe and log off from Shell Extension
+	[d0e17036e8ea]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Support decrypt from Windows Explorer Shell Extension
+	[f08c62e9db89]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Adjust so signing takes place for Debug as well as Release and also
+	not flagging it as a failed build.
+	[6133aeb5e4c8]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Show output from signtool in order to debug failed signing on build
+	server.
+	[5e4a7cddd965]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Fix unit tests as a result of changed behavior in previous check-
+	ins.
+	[8c23a41404fe]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Add *.bak to ignore-liste
+	[62e0c9fefe45]
+
+2014-04-17 svante <svante at axantum.com>
+
+ 	* Add support for right-click Encrypt in Windows Explorer when
+	installed.
+	[81a7f11625b1]
+
+2014-04-15 svante <svante at axantum.com>
+
+ 	* Add support for -b batch in command line, although ignoring for now.
+	[8022bca761b3]
+
+2014-04-14 Svante Seleborg <svante at axantum.com>
+
+ 	* Generate merged version of AxCrypt.exe for debug build as well.
+	[b5b1e352d608]
+
+2014-04-08 Svante Seleborg <svante at axantum.com>
+
+ 	* FxCop
+	[92921fcd2860]
+
+2014-04-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Add message when adding a folder for watching that is already
+	watched.
+	[24294d95aff4]
+
+2014-04-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug with orphaned files in recent files view when removing a
+	watched folder.
+	[b8d8b400cf47]
+
+2014-04-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Ensure that the right type of IPassphrase is used for the
+	appropriate ICryptoFactory. Also some clarification refactoring
+	concerning iterations, renaming and more consistent type use of int
+	vs. long.
+	[5ca40b9d8db7]
+
+2014-04-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Improved error handling by introducing FileOperationContext which
+	combines a status with a full path and file name of the file in
+	question.
+	[35a38a61a662]
+
+2014-04-07 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug when adding a new file with a new identity when at least one
+	identity is already known. It now prompts for a new identity name as
+	it should instead of saying the passphrase is wrong.
+	[0b987ef1a103]
+
+2014-04-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove association of CryptoId with PassphraseIdentity, and various
+	related refactorings. Use list of CryptoId's to try and match a
+	passphrase with an encrypted document when required.
+	[f6b4125bb91b]
+
+2014-04-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Various fixes for SymmetricKeyThumbprint - most important use
+	constant Preferred algorithm for key-wrap, should be the strongest
+	and fastest available. Refactor so SymmetricKey returns a Size in
+	bits rather than Length in bytes. Change KeyWrapCalculator to use
+	CryptoId as parameter rather than fixed for V1 and V2.
+	[408b49dbd2a2]
+
+2014-04-04 Svante Seleborg <svante at axantum.com>
+
+ 	* Partial fix for legacy not working.
+	[630eee92ce93]
+
+2014-04-04 Svante Seleborg <svante at axantum.com>
+
+ 	* Use correct CryptoId when decrypting, also try available CryptoIds
+	not just default.
+	[f031f70ffba0]
+
+2014-04-04 Svante Seleborg <svante at axantum.com>
+
+ 	* Implement different policies for selecting encryption algorithm via
+	ICryptoPolicy. Fix a bug in logging, needs to Post to UI thread
+	otherwise a deadlock occurs.
+	[e13ec877f6a0]
+
+2014-03-31 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove another direct call to V1, using CryptoFactory instead.
+	[e51085dfc232]
+
+2014-03-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Interim checkin. Cleaning and preparing for multiple V2-algorithms.
+	[216b7c1a2dfc]
+
+2014-03-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Add feature to completely reset settings and state (mostly during
+	development when incompatible changes are frequent).
+	[5b9b3ab3dc16]
+
+2014-03-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Add support for algorithm name and version column in user list view.
+	[a28c53cd8daa]
+
+2014-03-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Remove knowledge of IV size when creating ICrypto with zero IV.
+	[3e69ba59b860]
+
+2014-03-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Change handling of ids and use id instead of IsLegacy to identify
+	type. This is in preparation of displaying basic parameters in the
+	active file window.
+	[b879196583f2]
+
+2014-03-29 svante <svante at axantum.com>
+
+ 	* Implement support for knowing if a IPassphrase or IAxCryptDocument
+	is legacy.
+	[c9a1214a3ee0]
+
+2014-03-27 svante <svante at axantum.com>
+
+ 	* Optimize V2KeyWrapHeaderBlock since it was simply too slow
+	[a9eae1f106b9]
+
+2014-03-27 svante <svante at axantum.com>
+
+ 	* Fix race condition with Dispose during process exit event handling.
+	[e888fe4532ee]
+
+2014-03-27 svante <svante at axantum.com>
+
+ 	* Refactor away use of byte[] for salts and generalize KeyWrapSalt to
+	Salt
+	[7d2768b43322]
+
+2014-03-27 svante <svante at axantum.com>
+
+ 	* Use CryptoFactory instead of concrete constructors for V*AesCrypto
+	[3768de48747d]
+
+2014-03-26 svante <svante at axantum.com>
+
+ 	* Partial implementation of discoverable crypto implementations.
+	[d295c802b294]
+
+2014-03-20 svante <svante at axantum.com>
+
+ 	* Start working on pluggable algorithms. Refactor VxAesCrypto to be
+	able to use the same arguments for instantiation, i.e. remove
+	padding and mode from construction of V1AesCrypto. Add support for
+	CryptoFactory et. al.
+	[53947d22d9ee]
+
+2014-03-19 svante <svante at axantum.com>
+
+ 	* Implement IKeyWrapTransform et. al. including cascading changes +
+	FxCop
+	[35d13c9d1ad3]
+
+2014-03-19 svante <svante at axantum.com>
+
+ 	* Minor refactoring preparing to modify ICrypto to not expose
+	SymmetricAlgorithm via CreateAlgorithm for KeyWrap in order to pave
+	the way for a stream cipher based implementation of ICrypto should
+	it ever prove interesting.
+	[3e971b0d0520]
+
+2014-03-18 svante <svante at axantum.com>
+
+ 	* Fix missing generalization of Unwrap. Use _A as reference for half
+	block size.
+	[e8065714defc]
+
+2014-03-16 svante <svante at axantum.com>
+
+ 	* Added test for AxCryptFactor plus refactoring as a result. Back at
+	100% code coverage for Axantum.AxCrypt.Core.
+	[123d219e66e3]
+
+2014-03-16 svante <svante at axantum.com>
+
+ 	* Added more tests for V2AxCryptDocument, and did some refactoring as
+	a result.
+	[8f2bcac45c7e]
+
+2014-03-15 svante <svante at axantum.com>
+
+ 	* Add tests for V1AxCryptDocument and remove some irrelevant code
+	[8a317ac2109e]
+
+2014-03-14 svante <svante at axantum.com>
+
+ 	* FxCop
+	[42e182a6ae91]
+
+2014-03-14 svante <svante at axantum.com>
+
+ 	* Added more tests for V2HmacStream
+	[c0de27681f0c]
+
+2014-03-14 Svante Seleborg <svante at axantum.com>
+
+ 	* Merge
+	[e57b7c4da5e6]
+
+2014-03-14 Svante Seleborg <svante at axantum.com>
+
+ 	* Clarify how the AxCrxypt GUID is stored binary
+	[8527cdbbfa63]
+
+2014-03-14 svante <svante at axantum.com>
+
+ 	* Added tests for V2AxCryptDataStream
+	[9ffb8f5876f2]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Add tests for KnownFoldersViewModel
+	[86e7f51e8eca]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for LogOnViewModel
+	[37a7e771685e]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for NewPassphraseViewModel
+	[302c665a5aac]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Add more tests for IdentityViewModel
+	[5e735a98c667]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Fix tests for FileOperationViewModel and handle exceptions on UI
+	thread.
+	[cfc621d2036c]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Add more tests for MainVieModel
+	[7125de641d09]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for PassphraseBase and RandomGenerator
+	[a8e71af39d2e]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for Pbkdf2HmacSha512
+	[b1c6467d6670]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for V2AesCrypto
+	[f736792924c2]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Handle IDisposable properly in tests too
+	[0a52c4fc6446]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Added more tests for CounterModeCryptoTransform
+	[ad0c100a1bd9]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[c12e63bcdc1e]
+
+2014-03-13 svante <svante at axantum.com>
+
+ 	* Add more tests for KeyWrap, V2DocumentHeaders and
+	EncryptedDataPartBlock
+	[f4c52ff62049]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Refactor EncryptedHeaderBlock-s with consistent naming and
+	constructor setting of HeaderCrypto when encrypting.
+	[299566cde48f]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Ensure consistent implementation of Clone() for
+	EncryptedHeaderBlock:s
+	[d7e12c3df5f2]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Added more tests for V2PlainTextLengthsHeaderBlock
+	[7e28251767c9]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Added more tests for HeaderBlock
+	[07f5e726aa1d]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Added more tests for V2HmacHeaderBlock
+	[2a0f0a6e8230]
+
+2014-03-12 svante <svante at axantum.com>
+
+ 	* Added more tests for V2UnicodeFileNameInfoHeaderBlock
+	[cca9f15e143e]
+
+2014-03-11 svante <svante at axantum.com>
+
+ 	* Add tests for V2CompressionHeaderBlock
+	[bd6d28350737]
+
+2014-03-11 svante <svante at axantum.com>
+
+ 	* Add more tests for VersionHeaderBlock
+	[41593d981e16]
+
+2014-03-11 svante <svante at axantum.com>
+
+ 	* Add more tests for V2KeyWrapHeaderBlock
+	[b92ec5d3d44d]
+
+2014-03-11 svante <svante at axantum.com>
+
+ 	* Added new tests for V2DocumentHeaders
+	[0880cbb2e391]
+
+2014-03-11 svante <svante at axantum.com>
+
+ 	* Add some tests for Headers
+	[231753f0e10d]
+
+2014-03-04 Svante Seleborg <svante at axantum.com>
+
+ 	* Add various test for various extensions to make tests complete
+	again.
+	[10f748a68c2c]
+
+2014-03-04 Svante Seleborg <svante at axantum.com>
+
+ 	* Add tests for KnownFolder
+	[7fa2022dd02e]
+
+2014-03-01 svante <svante at axantum.com>
+
+ 	* Add unit test for SessionNotificationType.EncryptPendingFiles with
+	logged on folders.
+	[c25cde8495d9]
+
+2014-02-28 svante <svante at axantum.com>
+
+ 	* Remove special handling of logged on folders when watching for
+	deletions of ActiveFiles.
+	[76ca2f035440]
+
+2014-02-28 svante <svante at axantum.com>
+
+ 	* Generalize KeyWrap to be block-size independent.
+	[cf68a3a9f503]
+
+2014-02-28 svante <svante at axantum.com>
+
+ 	* Set the key derivation to work with a fixed amount of iteration, but
+	still encoded in persisted data so it can be changed in the future.
+	[534c8b83726d]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Name changes and refactorizations
+	[a54bacb42e61]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Added Unit Tests for *AxCryptReader
+	[def60fc8d94c]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Handle the case of logging on to a specific file, showing the
+	correct message.
+	[559733f06288]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Fix bad unit tests, and add FakeIterationCalculator so tests are run
+	faster.
+	[96c289d8a02c]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Fix Log On to known Identity without a specific file
+	[6c8f94ffc360]
+
+2014-02-27 svante <svante at axantum.com>
+
+ 	* Fix various scenarios when logging on to behave more intuitively
+	[bbfc3bb89de2]
+
+2014-02-26 svante <svante at axantum.com>
+
+ 	* Change New Identity GUI to show file name, if any.
+	[7b3280404458]
+
+2014-02-26 svante <svante at axantum.com>
+
+ 	* Include file name (optionally) in the New Identity dialog
+	[36fdc3df42df]
+
+2014-02-26 svante <svante at axantum.com>
+
+ 	* Fix unit testing error due to changed behavior of validation
+	[ac293591d3d0]
+
+2014-02-26 svante <svante at axantum.com>
+
+ 	* Use enum for CryptoName, improve UI handling of logging on.
+	[fa3667b01210]
+
+2014-02-25 svante <svante at axantum.com>
+
+ 	* FxCop
+	[3b78ffbf54c8]
+
+2014-02-25 svante <svante at axantum.com>
+
+ 	* Merge of Pull-request from slamti
+	[e29195e0e2f9]
+
+2014-02-25 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Xamarin Studio doesn't seem to understand the
+	StreamExtensions.CopyTo extension method, so changed to a static
+	invocation
+	[884e0e2beb23]
+
+2014-02-25 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged from main after 289 commits
+	[be56cb4e8b28]
+
+2013-06-29 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added v1.2 AppStore Images
+	[867a2b1e24ae]
+
+2013-06-29 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Ignoring any git files, enabling cloning
+	[2295165df05d]
+
+2013-06-16 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Cleaned out some dirt
+	[f3834fb90b21]
+
+2013-06-16 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* iPad version now automatically refreshes its file listing
+	[ef92cb27cf36]
+
+2013-06-16 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Now showing loading indicator when loading external web pages
+	[4dbe3aaefe83]
+
+2013-06-15 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* The AxCrypt logo and text is now centered
+	[ee9f6fcb816d]
+
+2013-06-15 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* The iPad UI now shows a file listing for both received and
+	transferred files, allowing the user to manipulate the file lists in
+	the main interface
+	[6913d28d8e2a]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added a themed file element
+	[a06a4c8fcbf5]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Renamed the recent folder to Received documents and local to
+	Transferred documents; added theming to file listing
+	[beaa602da132]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Updated FilePresenter to have a better chance of dismissing the
+	document on app deactivation
+	[0eaf65014606]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added BigTed's BTProgressHUD as activity indicator during decryption
+	[f4becb255afc]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Implemented the Troubleshooting link
+	[92b442cf861e]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* AxCrypt no longer maintains its document preview when it's dismissed
+	as it's presenting the document view controller's action menu
+	[e47d6e5b7815]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added WebViewController and routed the FAQ and Troubleshooting
+	through it. Also replaced the About dialog with a web request for
+	easier maintenance
+	[a26b411b6156]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Now reading version string from property list. Also updated version
+	to 1.3
+	[cde6a83c9f67]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Fixed a bug where the app would hang if interrupted during
+	passphrase collection
+	[396b3c423f54]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Implemented FAQ button
+	[8c594a580f28]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* We're now giving the user a little more information about the
+	commands, if they're on a iPhone 5 or an iPad (more vertical space
+	to play with)
+	[f94468d80592]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Implemented deletion of received files
+	[bf0ac7b396d3]
+
+2013-06-09 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added DecryptionViewController.cs
+	[24b65f507c6a]
+
+2013-06-08 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Implemented the new about alert, feedback view, separate file
+	listings for received vs. transferred files
+	[f225580cb67e]
+
+2013-06-04 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Corrected a bug which would have crashed the app if user tried to
+	open an .axx document with the same name as a previous document;
+	themed the main UI; added FileListingController
+	[77e24e637bd6]
+
+2013-05-26 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Accommodated the latest changes to AxCrypt.Core
+	[14b6d141b374]
+
+2013-05-25 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged axantum/axcrypt-net into default
+	[c609c7aa5290]
+
+2013-05-25 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Removed unused source (.axx) file reference, stopped monitoring
+	active windows and refactored magic strings into constant fields
+	[c0ca61617f36]
+
+2013-05-21 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added *.Mac.csproj and moved specific launch and runtime behaviours
+	for the platform there. AxCrypt can now successfully maintain the
+	state of several different opened files at the same time. Updated
+	version number to 2.0.2.1
+	[0ce01606a8ed]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Adjusted for API changes
+	[dfa234409551]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged axantum/axcrypt-net into Default
+	[de5368c1d2f0]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Added a fancy Version Information window (and pushed version to
+	2.0.2.0)
+	[ac3e7ed0db26]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* It's now possible to double-click an encrypted file in Finder, enter
+	passphrase, edit file and have it be re-encrypted using the same key
+	as the app is closing
+	[5b4403e60b5f]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* .axx files are now properly registered with the AxCrypt icon in the
+	system
+	[2cc331e49f60]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* AxCrypt now lets you edit encrypted files using its
+	preview/quicklook icon
+	[9fa7f72eb36b]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Restructured the project for easier overview
+	[e7006fa1d719]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Fixed a thread-access issue when trying to open an encrypted file,
+	providing the wrong passphrase
+	[a4b0b4a2c5fe]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Fixed a thread-access issue when opening an encrypted file
+	[3c38aaf9edb6]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Updated framework references to .NET 4 across the board.
+	[be0821715af0]
+
+2013-05-19 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged axantum/axcrypt-net into default
+	[087d73732ade]
+
+2013-05-12 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged axantum/axcrypt-net into default
+	[7108f4bf3919]
+
+2013-01-24 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Resolved conflicts
+	[db571360de72]
+
+2013-01-24 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Version 1.1 - Distribute decrypted files
+	[99ad22dfb4f0]
+
+2014-02-25 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2. Major change to accomodate V1/V2
+	passphrases.
+	[4712af79e106]
+
+2014-02-25 svante <svante at axantum.com>
+
+ 	* Remove invisible space in thumbprint spec.
+	[cdefa2fa2019]
+
+2014-02-25 svante <svante at axantum.com>
+
+ 	* Updating thumbprint of code signing certificate
+	[b4ec4399a0e5]
+
+2014-02-21 Svante Seleborg <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2. Continue preparing for V1/V2 policy
+	handling. Added property CryptoName to IPassphrase, and factory
+	method to instantiate an appropriate ICrypto from a given
+	IPassphrase using CryptoName as determinator.
+	[33022bf9cd10]
+
+2014-02-20 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2. Minor fixes, preparing for V1/V2 policy
+	handling.
+	[a43b6c47da4e]
+
+2014-02-19 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2. Substituted SymmetricKey for IPassphrase
+	in most places in order to give encryption access to original
+	passphrase so it can provide per encryption-specific parameters to
+	the key derivation function, i.e. iterations and salt.
+	[f5bfc70d7444]
+
+2014-02-19 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2 functionality. Renaming mostly. Added new
+	IterationCalculators.
+	[6e24691f6a30]
+
+2014-02-19 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2 functionality. Decrypt mostly feature
+	complete.
+	[e5a354256da1]
+
+2014-02-19 svante <svante at axantum.com>
+
+ 	* Interim checkin for V1/V2 functionality.
+	[c464d82e2624]
+
+2014-02-19 svante <svante at axantum.com>
+
+ 	* Add more Pbkdf2HmacSha512 tests and simplify it for AxCrypt needs.
+	[1a9b07e892c5]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Implement V2Passphrase including IPassphrase and Pbkdf2HmacSha512
+	[ba1f67365838]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Differentiate constructors for encryption and decryption for
+	V1AxCryptDocument
+	[a36a6f09acc4]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Pass key wrap iterations as a parameter instead to V1AxCryptDocument
+	[d866b511d648]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* FxCop
+	[17cd7ca8f2ac]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Implement V2AxCryptDocument as IAxCryptDocument
+	[5a8638775f26]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Changed to use IAxCryptDocument abstraction, preparing for V2
+	functionality
+	[6516da83254b]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Prepare for and start using the IAxCryptDocument abstraction
+	[8a4a4bd22818]
+
+2014-02-18 svante <svante at axantum.com>
+
+ 	* Rename previous AES-specific type to algorithm agnostic names
+	[5b87ddf3d348]
+
+2014-02-17 svante <svante at axantum.com>
+
+ 	* Start working on IAxCryptDocument common abstraction for V1 & V2
+	[db96df7b7040]
+
+2014-02-17 svante <svante at axantum.com>
+
+ 	* Minor refactoring of Headers
+	[6814c540d8df]
+
+2014-02-17 svante <svante at axantum.com>
+
+ 	* Add tests with compression enabled as well.
+	[b50203b7757f]
+
+2014-02-17 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug with double-readahead in V2AxCryptDataStream
+	[e26919dfb3e0]
+
+2014-02-17 svante <svante at axantum.com>
+
+ 	* Interim checkin - still some problems triggered by (disabled) unit
+	tests.
+	[f625b2e0dac1]
+
+2014-02-16 svante <svante at axantum.com>
+
+ 	* Chunk encrypted data stream writing
+	[55623e980526]
+
+2014-02-16 svante <svante at axantum.com>
+
+ 	* V2AxCryptDocument.EncryptTo() and DecryptTo() feature-complete
+	w/simple test.
+	[10b849ce364f]
+
+2014-02-16 svante <svante at axantum.com>
+
+ 	* Rename DocumentHeaders to the more appropriate Headers
+	[ef8c54b08263]
+
+2014-02-15 svante <svante at axantum.com>
+
+ 	* Rename DocumentHeadersCommon to DocumentHeaders and other minor
+	changes.
+	[9472bc296f32]
+
+2014-02-15 svante <svante at axantum.com>
+
+ 	* Implement V2AxCryptReader
+	[7679eee8619b]
+
+2014-02-15 svante <svante at axantum.com>
+
+ 	* Refactor AxCryptReader into base class and specialization for V1
+	(and then V2)
+	[ae11076f1e7e]
+
+2014-02-14 svante <svante at axantum.com>
+
+ 	* Move HMAC handling up to prepare for reuse of AxCryptReader for V2
+	[ab83b9c53480]
+
+2014-02-14 svante <svante at axantum.com>
+
+ 	* Minor changes preparing for reading V2 files.
+	[ee46ff9151d8]
+
+2014-02-14 svante <svante at axantum.com>
+
+ 	* Support for writing V2Hmac complete, including basic test.
+	[75be23b19852]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Add V2PlainTextLengthsHeaderBlock
+	[39984000384d]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[43e14f9a2032]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Add V2HmacStream with HMAC-SHA-512 support
+	[b6899bf441b1]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[5cf9c2121977]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Add support for Unicode file name in V2DocumentHeaders
+	[fdc267595e7a]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Add support for Compression header
+	[5f88e4bd85b8]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Use ICrypto in V1DocumentHeaders constructor and cascading changes
+	[c7966421ce69]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Move common ICrypto functionality into CryptoBase
+	[b89bd00a71b7]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Continue moving use of ICrypto up the call chain instead of AesKey
+	[06fc631b89b5]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Remove IDisposable from ICrypto
+	[2c16f99730b7]
+
+2014-02-13 svante <svante at axantum.com>
+
+ 	* Start transition from AesKey to ICrypto to facilitate multiple
+	algorithms.
+	[28f169827d0c]
+
+2014-02-12 svante <svante at axantum.com>
+
+ 	* Continued on V2DocumentHeaders
+	[56f06b9a0dbb]
+
+2014-02-12 svante <svante at axantum.com>
+
+ 	* Added test for unwrapping V2 Key Wrap with 256 bit key and non-zero
+	IV and salt.
+	[55f9254379fe]
+
+2014-02-12 svante <svante at axantum.com>
+
+ 	* Add tests with 256 bit key encrypting key and 256 bit data to wrap
+	[3900b8bfc13b]
+
+2014-02-12 svante <svante at axantum.com>
+
+ 	* Continue work on V2DocumentHeaders. Refactor out PRNG from
+	Environment.
+	[3d09c19393e9]
+
+2014-02-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Interim check-in, starting on V2DocumentHeaders
+	[cf554c138e33]
+
+2014-02-07 Svante Seleborg <svante at axantum.com>
+
+ 	* Implement CounterModeCryptTransform
+	[0aa5704d8856]
+
+2014-02-06 Svante Seleborg <svante at axantum.com>
+
+ 	* FxCop
+	[e956789de01d]
+
+2014-02-06 Svante Seleborg <svante at axantum.com>
+
+ 	* Added tests using NIST test vectors for V2AesCrypto
+	[a7b5636d828b]
+
+2014-02-06 Svante Seleborg <svante at axantum.com>
+
+ 	* Started on V2AesCrypto and tests for same
+	[f0521db14394]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Splitting functionality for headers etc for V1 and V2
+	[5ff2204078ac]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Clean up AesKeyThumbprint slightly
+	[a20e4c29319d]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Add ignore pattern
+	[71ad9fcbb29b]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Prepare AesKey for different key lengths.
+	[afda4f870c24]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Prepare KeyWrap for different length keys <= 512 bits.
+	[de678772f9bc]
+
+2014-02-05 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor AxCryptDocument to facilitate implementation of 256-bit and
+	FFV4.
+	[0bc98e53b516]
+
+2014-01-15 svante <svante at axantum.com>
+
+ 	* Fix the GUI layout so the toobar buttons actually fit.
+	[751c717e489d]
+
+2014-01-15 svante <svante at axantum.com>
+
+ 	* Support indication and clean up of pending files in watched folders
+	[1cb4cf314c5a]
+
+2014-01-14 svante <svante at axantum.com>
+
+ 	* Add support for KnownFolders, i.e. My Documents, DropBox etc with a
+	'My AxCrypt' folder created and watched in those locations.
+	[0b507381428d]
+
+2014-01-13 svante <svante at axantum.com>
+
+ 	* Change so folders can be dropped in the recent files view as well.
+	[caa8e2eaa25d]
+
+2014-01-13 svante <svante at axantum.com>
+
+ 	* Fix bug not logging off old key when logging on with new
+	[753843735bef]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* FxCop
+	[f091faa377fb]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Update Copyright to 2014
+	[dad3b75655bd]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Remove effectively dead code that was not feasible to reach
+	[7c3717c69ec7]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Added tests
+	[3160bbcc275a]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Added tests
+	[14e07d03294c]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Added tests
+	[6e3781ee2b58]
+
+2014-01-11 svante <svante at axantum.com>
+
+ 	* Add tests
+	[7935a807f26a]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[9a14445af6c1]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[1e37accdda55]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[06f3911c1a14]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[d6da4748e0b0]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[fdd319a077ef]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[827f628ab090]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[7271198844b4]
+
+2014-01-10 svante <svante at axantum.com>
+
+ 	* Add tests
+	[2a4c9eb4841a]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* FxCop
+	[3a1670e84f84]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Refactor IProgressContext SingleThread support again and also handle
+	IDisposable properly for the SingleThread Semaphore.
+	[f654ff3e8c36]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Refactor IProgressContext SingleThread support
+	[7f0c68c59d3b]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Support deterministic sequencing of calls to UI in a worker group.
+	[2f4322602621]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Add tests
+	[3aac638036ab]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Remove irrelevant support for skipping when adding encrypted files.
+	[1c7bc7dbf17d]
+
+2014-01-09 svante <svante at axantum.com>
+
+ 	* Add tests and fix bug with UI-triggered cancellation caused
+	subsequent dialogs anyway.
+	[ba94dfe34b53]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Add tests.
+	[b51464d86269]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Make AxCrypt.Document virtual to make it mockable etc.
+	[7bb2ce44ab19]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Added tests for EncryptFilesAction
+	[6fa6493b3b8e]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Clean up tests for FileOperationViewModel a little bit
+	[f36b9ef0b1a0]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Added tests
+	[d14fd5ce08c1]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Break out tests for FileOperationViewModel from tests of
+	MainViewModel
+	[27c372917b14]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Added tests
+	[ce3571aca4ed]
+
+2014-01-08 svante <svante at axantum.com>
+
+ 	* Separate FileOperationViewModel from MainViewModel Add support for
+	post action dependencies for singleton registration Fix circular
+	dependency involving WorkFolder and UserSettings
+	[67ca7778fcca]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Refactor out file operations to FileOperationViewModel
+	[b6d46c83bdfe]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Improve some naming
+	[1a158b989cfc]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Add more tests
+	[97c970d9eceb]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Change how notifications are handled, removing the delay handling
+	and instead delegating to the event handler to determine such. For
+	now, no queueing but just running the tasks one by one in the
+	background.
+	[b1a568ba6f6c]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Remove unnecessary switch to UI-thread, the property binder switches
+	if required.
+	[a556dc0811e7]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Add Tests
+	[b880092446a2]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* FxCop
+	[205ff08dd777]
+
+2014-01-07 svante <svante at axantum.com>
+
+ 	* Refactor to increase testability and fix deadlock bug on exit
+	[71d55fa07c39]
+
+2014-01-05 svante <svante at axantum.com>
+
+ 	* Refactor to increase testability
+	[98b83908ed2d]
+
+2014-01-02 svante <svante at axantum.com>
+
+ 	* Minor refactoring
+	[02c2e1b73ce3]
+
+2014-01-02 svante <svante at axantum.com>
+
+ 	* Add more tests for MainViewModel
+	[9ca5e70925d4]
+
+2014-01-02 svante <svante at axantum.com>
+
+ 	* Add more tests for MainViewModel
+	[fa9d70e4cee9]
+
+2014-01-02 svante <svante at axantum.com>
+
+ 	* Add more tests for MainViewModel
+	[1be6427559e1]
+
+2014-01-02 svante <svante at axantum.com>
+
+ 	* Add more tests for MainViewModel
+	[4ff67718a2e8]
+
+2013-12-30 svante <svante at axantum.com>
+
+ 	* Make AxCryptFile a little bit more testable by changing from static
+	methods.
+	[4485dc9b3659]
+
+2013-12-30 svante <svante at axantum.com>
+
+ 	* Add tests for RemoveRecentFiles() and PurgeRecentFiles()
+	[83d170a6d341]
+
+2013-12-30 svante <svante at axantum.com>
+
+ 	* Fix AddWatchedFolder test and fix bug in SessionNotificationMonitor
+	[57cdafa61073]
+
+2013-12-27 Svante Seleborg <svante at axantum.com>
+
+ 	* Add test for AddWatchedFolder and inject FileSystemState dependency
+	into MainViewModel instead of via singleton factory.
+	[16373bb2ec41]
+
+2013-12-25 Svante Seleborg <svante at axantum.com>
+
+ 	* Added test for RecentFilesComparer
+	[c1cb73f24fc2]
+
+2013-12-25 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix bug in column sorting for recent files not toggling when
+	clicking twice.
+	[c7935f9826ff]
+
+2013-12-23 Svante Seleborg <svante at axantum.com>
+
+ 	* Add tests for droppable as watched folder
+	[eb7da88c4411]
+
+2013-12-22 Svante Seleborg <svante at axantum.com>
+
+ 	* Add tests for droppable
+	[23d21d006b7d]
+
+2013-12-22 Svante Seleborg <svante at axantum.com>
+
+ 	* Add test for CurrentVersion property bind
+	[3402707eec8c]
+
+2013-12-22 Svante Seleborg <svante at axantum.com>
+
+ 	* Start testing MainViewModel, also use Moq more.
+	[12e57043ebec]
+
+2013-12-21 svante <svante at axantum.com>
+
+ 	* Start working with tests for MainViewModel
+	[58c87e30e604]
+
+2013-12-20 Svante Seleborg <svante at axantum.com>
+
+ 	* FxCop
+	[21210c12e785]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Added tests for CommandService and CommandServiceArgs
+	[7642ec869d39]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests for CommandService
+	[b5a821118897]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add more tests to make testing of UserSettings complete.
+	[5f064938a13c]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Undo the nuget of Moq - doesn't work in Xamarin Studio in Linux or
+	the Mac.
+	[8953decd0ed9]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Added more tests for UserSettings, added KeyWrapIterationCalculator
+	as injected dependency instead of static, and added nuget for moq
+	and start use moq for dependency mocking and faking.
+	[b196143ce003]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Added some tests for UserSettings.
+	[4494b3b797d3]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests and refactor away some unused public properties.
+	[388fd8a2ed15]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests and remove dead code.
+	[3f0aab0642f0]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests and rename ParallelBackground to ParallelFileOperation.
+	[d500661243bd]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests for skipping in FileOperationsController.
+	[ac24bb880d20]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests for ProgressContext.RemoveCount()
+	[c6936c935e91]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests for PassphraseIdentity
+	[5f13eb1a260c]
+
+2013-12-20 svante <svante at axantum.com>
+
+ 	* Add tests for ActiveFileComparer
+	[75bc8b780885]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Refactor syntax for use of class factory
+	[e8e0b0a7b88a]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Added tests
+	[20207f49a138]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Add tests
+	[9a1bd2094e8e]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Add tests for SessionNotification and fix a bug found. Tests rule.
+	[ad56bc4179f0]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* More refactoring, more dependency injection and less use of
+	singletons etc.
+	[41ab0f596233]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Refactor and FxCop
+	[f7d34f6697e3]
+
+2013-12-19 svante <svante at axantum.com>
+
+ 	* Add tests.
+	[f50f9805d9ec]
+
+2013-12-18 svante <svante at axantum.com>
+
+ 	* Added tests
+	[17c8d4aef155]
+
+2013-12-18 svante <svante at axantum.com>
+
+ 	* More refactoring.
+	[01800e4c2b1f]
+
+2013-12-18 svante <svante at axantum.com>
+
+ 	* Starting refactor FileSystemStateActions
+	[cfe5ae9878a0]
+
+2013-12-17 svante <svante at axantum.com>
+
+ 	* Refactor SessionEvent into SessionNotification with a separate
+	Manager class.
+	[81012db36279]
+
+2013-12-16 svante <svante at axantum.com>
+
+ 	* Add tests
+	[93e61e6b2fa2]
+
+2013-12-16 svante <svante at axantum.com>
+
+ 	* Add tests
+	[61389ece7c7e]
+
+2013-12-16 svante <svante at axantum.com>
+
+ 	* Add tests
+	[67463ecc57f3]
+
+2013-12-16 svante <svante at axantum.com>
+
+ 	* Fix ThreadWorker to behave more consistently and increase test code
+	coverage.
+	[11a88e8dee70]
+
+2013-12-16 svante <svante at axantum.com>
+
+ 	* Move all commands to use the IAction (really ICommand, but locally
+	implemented) interface.
+	[7d256592fcbc]
+
+2013-12-14 svante <svante at axantum.com>
+
+ 	* FxCop
+	[3bce1490d2bc]
+
+2013-12-14 svante <svante at axantum.com>
+
+ 	* FxCop
+	[223384018bef]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[6f3f771f2053]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* Use lazy initialization of Singletons in FactoryRegistry. Fix
+	disposal bug.
+	[ce1e11e2486a]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* Minor refactoring
+	[a4722e54c04c]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* Move Logging implementation to FactoryRegistry and tracelistener
+	from MainForm.
+	[22f2737b8818]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* Clean and reorganize MainForm a little bit.
+	[3dcd74fd4242]
+
+2013-12-13 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix initial restoration of size and position by delaying attaching
+	events.
+	[3c1c35c7da42]
+
+2013-12-13 svante <svante at axantum.com>
+
+ 	* Move PurgeActiveFiles from MainForm
+	[6556fee23634]
+
+2013-12-12 svante <svante at axantum.com>
+
+ 	* Move SessionChanged handling from MainForm
+	[a2a747f51ef2]
+
+2013-12-12 svante <svante at axantum.com>
+
+ 	* Remove RecentFilesPresentation.cs, moving it back to MainForm
+	[83a9231d9514]
+
+2013-12-10 svante <svante at axantum.com>
+
+ 	* Move sorting to ViewModel
+	[b424a9fb759b]
+
+2013-12-06 svante <svante at axantum.com>
+
+ 	* Fix bug causing password to be name of new identity
+	[77314506f54f]
+
+2013-12-06 svante <svante at axantum.com>
+
+ 	* Move debug mode handling to ViewModel
+	[a3d876b0ab37]
+
+2013-12-05 svante <svante at axantum.com>
+
+ 	* Move update checking to ViewModel
+	[1d5548bcc902]
+
+2013-12-04 svante <svante at axantum.com>
+
+ 	* Use Environment.SpecialFolder.LocalApplicationData for the
+	WorkFolder instead of Temp.
+	[3505d861a6c3]
+
+2013-12-04 svante <svante at axantum.com>
+
+ 	* Move KeyWrapIterations and ThumbprintSalt to UserSettings, and also
+	simplify implementation a bit.
+	[761f352ef5a7]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Create ViewModel for LogOnDialog
+	[699e77a86f8f]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Rename EncryptPassphraseDialog to the more appropriate
+	NewPassphraseDialog.
+	[abf419ccae6d]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Add Copyright and License notice where missing
+	[b42e57427473]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Add test for property existing in IDataErrorInfo base implementation
+	[d6fdfffe999d]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Implement NewPassphraseViewModel and support validation in
+	ViewModelBase
+	[7baae944738a]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Remove IMainView and move identity name handling to ViewModel
+	[3b98e0c2c986]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Remove DragEventArgsExtensions
+	[046022626e34]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Improve Fallback-syntax and implementation
+	[acf15cd0d7f1]
+
+2013-12-03 svante <svante at axantum.com>
+
+ 	* Change how settings are handled, splitting into Core and UI-specific
+	among other changes.
+	[772f2a13d342]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* More code moved to ViewModel
+	[07f0c2095b5e]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* Change WatchedFolders property to use strings.
+	[b00ecc6c67e5]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* More moved to ViewModel
+	[966b29753715]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* More code to ViewModel
+	[710ded2b242c]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* Refactor away more code from GUI.
+	[9d22c2c2edcf]
+
+2013-12-02 svante <svante at axantum.com>
+
+ 	* More refactoring code from View to ViewModel
+	[44bc405a5c1b]
+
+2013-11-30 svante <svante at axantum.com>
+
+ 	* Minor tweaks
+	[3d2e90363c0c]
+
+2013-11-30 svante <svante at axantum.com>
+
+ 	* Move wipe-function to ViewModel
+	[6fcd89e19702]
+
+2013-11-30 svante <svante at axantum.com>
+
+ 	* Starting to add support for drag and drop to ViewModel
+	[4f6e66bf8f2d]
+
+2013-11-30 svante <svante at axantum.com>
+
+ 	* Implement MVVM for open encrypted from folder
+	[bee88ad1ad95]
+
+2013-11-29 svante <svante at axantum.com>
+
+ 	* More MVVM moving code
+	[f5193a6c1b93]
+
+2013-11-29 svante <svante at axantum.com>
+
+ 	* Continue moving code into MVVM model
+	[e0813f40f438]
+
+2013-11-29 svante <svante at axantum.com>
+
+ 	* More moved into ViewModel
+	[828ce786fce0]
+
+2013-11-29 svante <svante at axantum.com>
+
+ 	* Minor cleanup
+	[03b674616361]
+
+2013-11-29 svante <svante at axantum.com>
+
+ 	* Continut moving code to MVVM pattern
+	[47b9ee926cbb]
+
+2013-11-29 Svante Seleborg <svante at axantum.com>
+
+ 	* Interim checkin - working towards a more MVVM-like programming model
+	[52838e1baad8]
+
+2013-11-28 svante <svante at axantum.com>
+
+ 	* FxCop
+	[18eb02a3f878]
+
+2013-11-28 svante <svante at axantum.com>
+
+ 	* Initial support for command line and single instance local function
+	server.
+	[fa7cd5844108]
+
+2013-11-27 svante <svante at axantum.com>
+
+ 	* Change name of ActiveFileChanged event to the more appropriate name
+	[ad7a7e506bbb]
+
+2013-11-26 svante <svante at axantum.com>
+
+ 	* Change name of build server
+	[9bb8c7012b21]
+
+2013-11-26 svante <svante at axantum.com>
+
+ 	* Make clear passphrase memory work without restart
+	[666c954622b3]
+
+2013-11-25 svante <svante at axantum.com>
+
+ 	* Implement simple Clear Passphrase Memory command. Needs restart for
+	now.
+	[df6fee6dc428]
+
+2013-11-21 svante <svante at axantum.com>
+
+ 	* Implement Drag and Drop on tool strip buttons.
+	[d1abdaae6f09]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Removing dead code
+	[38be09fb20fa]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Simplify how parallel background operations are defined and called,
+	handling the threadworker internally instead.
+	[ce51d0421198]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Minor clean up an ordering of methods.
+	[61491ed5abd3]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Refactor and rename parameters etc.
+	[f59339dd274b]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Refactor naming and use of IRuntimeFileInfo instead of string in
+	most places.
+	[6055d8dd3c78]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Start refactoring background work and threading
+	[163acc8b5449]
+
+2013-11-19 svante <svante at axantum.com>
+
+ 	* Change DecryptFilesUniqueWithWipeOfOriginal to process files multi-
+	threaded in background.
+	[1148ca963c37]
+
+2013-11-18 svante <svante at axantum.com>
+
+ 	* Make ProgressContext handle multiple worker threads better via
+	CancelContext wrapper.
+	[fd4cc7938476]
+
+2013-11-18 svante <svante at axantum.com>
+
+ 	* Improve Cancellation handling so temporaries get cleaned up.
+	[8a790610774a]
+
+2013-11-17 svante <svante at axantum.com>
+
+ 	* Make ActiveFile really immutable and remove IDisposable from it.
+	[4590890cf410]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Refactor FileSystemState use of locks etc.
+	[5309ce116a9c]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Refactor ActiveFile to remove (faulty) need for dual indexing on
+	decrypted path.
+	[339ae55a6263]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Use a more appropriate overload for ActiveFile constructor.
+	[7d4c9fa24731]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Start refactor of ActiveFile to remove reference to Process and
+	IDisposable
+	[6ca86715cbed]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Various fixes how events and exceptions are handled.
+	[ba9b65ee7fd6]
+
+2013-11-15 svante <svante at axantum.com>
+
+ 	* Fix bug causing adding new identities to fail. Add feature bringing
+	passphrase along when clicking 'New' for new identity.
+	[20c9b83df0d6]
+
+2013-11-14 svante <svante at axantum.com>
+
+ 	* Add file name to decryption dialog
+	[1357e246a4e6]
+
+2013-11-14 svante <svante at axantum.com>
+
+ 	* Set form Language to (Default). The designer does strange things
+	when not.
+	[6950be63c3f9]
+
+2013-11-14 svante <svante at axantum.com>
+
+ 	* Remove dead code. Start adding function to display file name when
+	asking for decryption passphrase.
+	[e9359543bab2]
+
+2013-11-14 svante <svante at axantum.com>
+
+ 	* Make cancel from dialog work for several files in drag and drop
+	[2bf28ea411c4]
+
+2013-11-14 svante <svante at axantum.com>
+
+ 	* More language translation clean up and consistency fixes.
+	[d1c0c251018d]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[42a916fb6d23]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Add basic support for drop of encrypted files to main window
+	[95b91714ad1c]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* More text-tweaks
+	[1229ee1e671b]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Update translations
+	[ea5ab338002d]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* FxCop
+	[2d50f8d68d34]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Fix some language texts that are not refactored when member names
+	are changed...
+	[9ba193b9cf3e]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Fix and simplify how FileSystemState is instantiated and thawed.
+	[75988da122ae]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Change how DelayedAction works, let caller code worry about thread
+	marshalling.
+	[8fb16be1a849]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Fix drag and drop on Linux
+	[2b57130c80fd]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Remove dependency on System.Configuration.Settings, roll our own
+	instead. Too buggy in Mono, and also it's better to have it platform
+	independent.
+	[afe498b42fc4]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Remove unused field.
+	[d4895e15dc57]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Fix unit test to handle different exceptions depending on platform.
+	[7f2a83c43af5]
+
+2013-11-13 svante <svante at axantum.com>
+
+ 	* Separate some more presentation logic from MainForm.
+	[f1d41ba34c3e]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* On Mono the ColumnWidthChanged event is called so early, a null
+	check is needed.
+	[5edc121139e7]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Fix how alternate directory separator chars are handled to work on
+	Linux etc.
+	[b3ef16743f41]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Fix how alternate directory separator chars are handled to work on
+	Linux etc.
+	[daa9d3423521]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Avoid error in MonoDevelop of assigned but its value is never used.
+	[1f24224fefb4]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Avoid error in MonoDevelop of assigned but its value is never used.
+	[e9697ef20e59]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Fix bug with tab page causing crash when logging on
+	[ebb050180b78]
+
+2013-11-12 svante <svante at axantum.com>
+
+ 	* Added user preference persistance and column sorting for recent
+	files.
+	[25b78eb1b3c0]
+
+2013-11-11 svante <svante at axantum.com>
+
+ 	* Fix minor bug causing cancel not to work when logging on.
+	[6530708c7caa]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* Refactor to pass PassphraseIdentity instead of string
+	[108468b3f1a9]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* When decrypting and thumbprint is a known identity, show name in log
+	on.
+	[fbcff98c5b65]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* FxCop
+	[0e875bbe6e90]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* Various feature tweaks and field renaming
+	[1b0bdb811bc8]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* Auto log on if decryping with a known identity.
+	[a1898654b6c3]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* Simplify event handling using FileSystemState.Notify. Add handling
+	of LogOff event.
+	[9ae874dece17]
+
+2013-11-09 svante <svante at axantum.com>
+
+ 	* Minor refactoring to use FileSystemState singleton instead of
+	parameter
+	[4ff5ceab1b5e]
+
+2013-11-08 svante <svante at axantum.com>
+
+ 	* Move FileSytemState handling to FactoryRegistry Singleton handling.
+	[5aa296149393]
+
+2013-11-08 svante <svante at axantum.com>
+
+ 	* Minor refactoring, adding Passphrase.Derive() as a convenience
+	method.
+	[0f284e4150bb]
+
+2013-11-08 svante <svante at axantum.com>
+
+ 	* Refactor singletons to use the FactoryRegistry
+	[455abcc63604]
+
+2013-11-08 svante <svante at axantum.com>
+
+ 	* Add Thumbprint to WatchedFolder. Improved the passphrase dialogs.
+	[363d815fc22b]
+
+2013-11-07 svante <svante at axantum.com>
+
+ 	* Support a more strict Log On paradigm with a user name etc.
+	[155fa7dae6ae]
+
+2013-11-06 svante <svante at axantum.com>
+
+ 	* Primitive support for drag and drop of encryptable files.
+	[4a033e202daa]
+
+2013-11-06 svante <svante at axantum.com>
+
+ 	* Further refactoring to allow better use of background processing
+	[8e0042a54e1b]
+
+2013-11-06 svante <svante at axantum.com>
+
+ 	* Refactoring extensions and changing IRuntimeFileInfo to be slightly
+	simpler.
+	[3243afabbbce]
+
+2013-11-05 svante <svante at axantum.com>
+
+ 	* FxCop
+	[3f322d6fd0fb]
+
+2013-11-05 svante <svante at axantum.com>
+
+ 	* Preparation for drag-n-drop in RecentFiles. Move UI-thread-awareness
+	code to Core.
+	[0b42ea2b2b0f]
+
+2013-11-05 svante <svante at axantum.com>
+
+ 	* Refactor to prepare for more functions in RecentFiles list view.
+	[e8d9541f6d60]
+
+2013-11-05 svante <svante at axantum.com>
+
+ 	* Move ActiveFile visual representation calculation into Core
+	[46441674365b]
+
+2013-11-02 svante <svante at axantum.com>
+
+ 	* Added tests for WatchedFolderChangedEventArgs. Back to 100% code
+	coverage of Axantum.AxCrypt.Core .
+	[a8b139afa2e9]
+
+2013-11-02 svante <svante at axantum.com>
+
+ 	* Added tests for SessionEvent
+	[d15bfc0409b3]
+
+2013-11-02 svante <svante at axantum.com>
+
+ 	* Add tests for FactoryRegistry
+	[b092bfda0790]
+
+2013-11-02 svante <svante at axantum.com>
+
+ 	* Enhance factory and change FileSystemStateExtensions to testable
+	mockable FileSystemStateActions class instead.
+	[efc716c3d2de]
+
+2013-11-02 svante <svante at axantum.com>
+
+ 	* Add simple mocking capabilities in order to enable reasonable unit-
+	tests of high-level utility code.
+	[6ef4bff36f00]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Fix test errors.
+	[f6062b93bb68]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Modified test to increase code coverage.
+	[26c59ccfccac]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Added tests.
+	[7781b71db64b]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Added AxCryptFile tests
+	[04ac6f9c228c]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Added and updated tests.
+	[bfec8d230972]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Add support for environment variables, and path filters based on
+	such.
+	[8fd4d6186bce]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Fix faulty naming due to earlier functionality changes
+	WorkFolderChanged -> SessionChanged
+	[2a0dfbc41c8f]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Moved background-aware code back into MainForm from
+	WatchedFoldersCore
+	[5eb067c9ffc4]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* FxCop Fix bug with attempted encryption at startup Add support for
+	temporary folder decryption
+	[98f126737dd3]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* FxCop
+	[475e0d963366]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Add support for filters to skip files matching patterns, i.e.
+	.dropbox etc. Use Begin-/EndUpdate() instead of list item sorter
+	tricks to avoid flickering. Fix issue where readonly directories
+	where not recognized as directories.
+	[163028b9e273]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* FxCop
+	[23c12470f9f9]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Refactor Watched Folders UI-functionality away from MainForm to
+	WatchedFoldersCore instead.
+	[48d911e8a48d]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Change name SessionChanged handling. Change how events are raised
+	for watched folders at startup. Change how the watched folder tab is
+	shown at startup. Support double-click to open a watched folder in
+	explorer.
+	[3ff0bd6195ef]
+
+2013-11-01 svante <svante at axantum.com>
+
+ 	* Add handling of KnownKeyChange event
+	[1933f449c463]
+
+2013-10-31 Svante Seleborg <svante at axantum.com>
+
+ 	* Start handling SessionState events as discrete operations.
+	[f4a4c6ed4288]
+
+2013-10-30 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor how SessionEvents are handled.
+	[86143b5939b0]
+
+2013-10-29 Svante Seleborg <svante at axantum.com>
+
+ 	* Interim checkin - not tested! Changing to specify what kind of
+	notification occurrs and sending enough data to do it in the
+	background via SessionEventArgs.
+	[7c48137b66ee]
+
+2013-10-29 Svante Seleborg <svante at axantum.com>
+
+ 	* Fix failing unit tests, due to changed semantics of MoveTo.
+	[67de16635df7]
+
+2013-10-29 Svante Seleborg <svante at axantum.com>
+
+ 	* Improve handling of duplicate file names, reducing risk of
+	collissions and overwrites.
+	[fbb31cdb0b3e]
+
+2013-10-28 Svante Seleborg <svante at axantum.com>
+
+ 	* Refactor watched folders logic, moving more out of the main form.
+	[0159adfddcaa]
+
+2013-10-28 Svante Seleborg <svante at axantum.com>
+
+ 	* Support deletion of WatchedFolder, and only show WatchedFolders when
+	logged on. To do: only show specific watched folders that use the
+	log on currently active.
+	[7b17f1744c5f]
+
+2013-10-28 Svante Seleborg <svante at axantum.com>
+
+ 	* Hooked up WatchedFolders changed to global change notification.
+	[7ee83f691808]
+
+2013-10-27 svante <svante at axantum.com>
+
+ 	* Interim checkin - problem with PersistentState and WatchedFolders
+	does not work with the Load() method and deserialization at this
+	point. Wrong instance get's the events attached.
+	[213ee4a1afde]
+
+2013-10-27 svante <svante at axantum.com>
+
+ 	* Clear all known keys when 'logging out', and update active files
+	accordingly.
+	[c48d3f313643]
+
+2013-09-16 svante <svante at axantum.com>
+
+ 	* Add simple display of watched folders in main window
+	[7fc101dffe64]
+
+2013-09-08 Svante Seleborg <svante at axantum.com>
+
+ 	* Add WatchedFolderChanged event
+	[c6aef54c02aa]
+
+2013-05-21 svante <svante at axantum.com>
+
+ 	* Interim check-in for encrypting files in watched folders.
+	[0d6ea5418d49]
+
+2013-05-18 svante <svante at axantum.com>
+
+ 	* Added some string translations
+	[70fa397662dc]
+
+2013-05-18 svante <svante at axantum.com>
+
+ 	* FxCop
+	[600ddcdb6bc4]
+
+2013-05-18 svante <svante at axantum.com>
+
+ 	* Add method to scan for decrypted files in watched folders +
+	renaming, commenting and minor refactorization.
+	[252a46bf53f7]
+
+2013-05-16 svante <svante at axantum.com>
+
+ 	* FxCop
+	[d8ff34d421e0]
+
+2013-05-16 svante <svante at axantum.com>
+
+ 	* Clarify naming, and add and correct some API comments.
+	[0fe604ff7813]
+
+2013-05-16 svante <svante at axantum.com>
+
+ 	* Add tests for DelayedAction class. Back to 100% code coverage.
+	[7c999721b008]
+
+2013-05-15 svante <svante at axantum.com>
+
+ 	* Move handling of working file state changes into Core, and do some
+	renaming to clarify the functionality. The GUI layer now only needs
+	to attach to one event, with handling of thread affinity and delayed
+	action all handled by Core.
+	[7dcabd558d1a]
+
+2013-05-12 svante <svante at axantum.com>
+
+ 	* Make WatchedFolder a first class citizen, not just a string.
+	[04fb41643486]
+
+2013-05-11 svante <svante at axantum.com>
+
+ 	* Add WatchedFoldes to FileSystemState, and add tests for
+	KeyWrapIteration calculation, including refactoring to make it
+	testable.
+	[91992a01ccab]
+
+2013-03-11 Svante Seleborg <svante at axantum.com>
+
+ 	* Change how Thumbprints are handled and persisted. They are now user-
+	local only, but do reveal if the same file has the same key as
+	another one. It is judged to be acceptable, since it's a fair guess
+	anyway for files in the same computer by the same user.
+	[82b6ae0fbd57]
+
+2013-01-20 svante <svante at axantum.com>
+
+ 	* Change thumbprint handling
+	[fe5efff81f22]
+
+2013-01-18 svante <svante at axantum.com>
+
+ 	* Introduce the concept of 'logging on' to AxCrypt, by redefining
+	'Default Encryption' to being 'Logged On'.
+	[14328ce0a4d6]
+
+2013-01-17 svante <svante at axantum.com>
+
+ 	* Change icon for files with known keys, and improve how known keys
+	are monitored, using an event instead.
+	[95fec45de197]
+
+2012-11-13 svante <svante at axantum.com>
+
+ 	* Include creation of bin-folder in all project configurations when
+	building for MonoTouch
+	[fba26cd207fc]
+
+2012-11-13 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged in axcrypt-net
+	[b5b91f4d79bd]
+
+2012-11-13 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Updated MonoTouch and iOS project files to create output paths as
+	needed
+	[0447bca1e9d4]
+
+2012-11-13 svante <svante at axantum.com>
+
+ 	* Update REST API URL for version check
+	[d44cd677af43]
+
+2012-11-12 svante <svante at axantum.com>
+
+ 	* Dummy-update the Swedish Icon to see if it get's serialized better
+	since it crashes on Linux when using Swedish.
+	[7d04a4235f97]
+
+2012-11-12 svante <svante at axantum.com>
+
+ 	* Avoid localization issues with ImageLists by building them manually
+	instead of via designer.
+	[acf35386b0d2]
+
+2012-11-12 svante <svante at axantum.com>
+
+ 	* Add Json.NET license to PublicResources and a test for it as well.
+	[0743ce106ea4]
+
+2012-11-12 svante <svante at axantum.com>
+
+ 	* Exlude SolutionItems from building in Mono for Android Release-build
+	[e281b8899e12]
+
+2012-11-12 svante <svante at axantum.com>
+
+ 	* Add Silverlight-version of Newtonsoft.Json and reference it in the
+	Mono for Android project.
+	[1f3f475c72a1]
+
+2012-11-11 svante <svante at axantum.com>
+
+ 	* Clean up and document rationale for the MonoTouch project
+	configuration and dependency handling.
+	[eda78a336777]
+
+2012-11-11 svante <svante at axantum.com>
+
+ 	* Add some explanation about the assemblies and how to build, also
+	update some build configurations.
+	[819e0d3b490a]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Add explanation about how to build MonoTouch
+	[4d62de6ae843]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Add 3rd party dependencies as explicit references
+	[192a7dd6159d]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Change MonoTouch solution to use binary references to
+	Axantum.AxCrypt.Core by copying from that projects bin-folder.
+	[fc5d4767bb92]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Add reference to Newtonsoft.Json
+	[8f0e1b867d41]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Change to use Newtonsoft.Json for JSON serialization to be
+	MonoTouch-compatible.
+	[4a22c8f6dc05]
+
+2012-11-10 svante <svante at axantum.com>
+
+ 	* Add comments and include all in Axantum.AxCrypt.Core.MonoTouch.
+	Partially broken at this point, because UpdateCheck.cs needs to be
+	refactored to use a JSon serializer that works in MonoTouch as well.
+	[41b3dcbf75b9]
+
+2012-11-09 svante <svante at axantum.com>
+
+ 	* Remove unused files
+	[81aaecb8082d]
+
+2012-11-09 svante <svante at axantum.com>
+
+ 	* Update how the MonoTouch dependencies are built
+	[3fd1d0adee20]
+
+2012-11-09 svante <svante at axantum.com>
+
+ 	* Added new project for MonoTouch-version
+	[55c412346e30]
+
+2012-11-09 svante <svante at axantum.com>
+
+ 	* Added new project for MonoMac-version
+	[20204fdcb651]
+
+2012-11-09 svante <svante at axantum.com>
+
+ 	* Interim checkin - partially broken. Fix some merge effects from Mac,
+	and start cleanup of configurations, platforms and solutions.
+	Separate solutions for separate targets, and linked projects when
+	necessary.
+	[8d9fc8ab7d6f]
+
+2012-11-07 svante <svante at axantum.com>
+
+ 	* Update concerning the MonoDevelop issue on Windows and xbuild
+	[51857c1f140b]
+
+2012-11-07 svante <svante at axantum.com>
+
+ 	* Remove characters not allowed in Windows
+	[c4a97d1baae0]
+
+2012-11-07 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merge adjustments
+	[158a84f06fb2]
+
+2012-11-07 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Merged in axantum/axcrypt-net
+	[027415c7abf7]
+
+2012-11-07 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Temporarilly removed Axantum.AxCrypt.Core/Os.cs to resolve casing
+	issues
+	[f347398786b8]
+
+2012-10-16 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Spotlight & Settings Icons
+	[f85e2edbfd27]
+
+2012-10-16 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* AxCrypt for iOS
+	[37b6466e28a9]
+
+2012-10-03 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* User-friendly 'Invalid password' handling
+	[bd462cf19dd0]
+
+2012-10-27 svante <svante at axantum.com>
+
+ 	* Change how Axantum-builds are distinguished
+	[7a69d22606da]
+
+2012-10-26 svante <svante at axantum.com>
+
+ 	* Tests for new and modified code. Back at 100% code coverage.
+	[b7d886e8e930]
+
+2012-10-25 svante <svante at axantum.com>
+
+ 	* Fix the broken icons once again. Now include them as resources in
+	project as well for future reference.
+	[914ed2dc991c]
+
+2012-10-25 svante <svante at axantum.com>
+
+ 	* FxCop
+	[68ffdcea10e8]
+
+2012-10-25 svante <svante at axantum.com>
+
+ 	* Add the LockingStream to the Android-build as well.
+	[c8adde4a8315]
+
+2012-10-25 svante <svante at axantum.com>
+
+ 	* Include internal locking for all file access in order to minimize
+	race situations.
+	[35a4dba611b5]
+
+2012-10-25 svante <svante at axantum.com>
+
+ 	* Add basic functionality for secure delete (Wipe)
+	[8c5aecd1bc69]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Add Wiping of files.
+	[8b3c7b89d443]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Add maximizing the number of recent files, and a Text for the
+	NotifyIcon
+	[6d0610d0a1b1]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Add function to decrypt files on most recent list.
+	[5ea550a08bbe]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Do not show anything when cancelling an operation, it's just
+	annoying.
+	[2b0742e78b78]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Add handling of default passphrase in GUI
+	[f7c4689231cb]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Ignore already encrypted files.
+	[1c58c1a4d22f]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Support multi-file select when removing from recent files list.
+	[e8dfd241d3f3]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Minor refactoring.
+	[853638ccaece]
+
+2012-10-24 svante <svante at axantum.com>
+
+ 	* Once again complete code coverage, along with some refactorings
+	indicated by this.
+	[1b5589056837]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* FxCop
+	[e823ed73930f]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* Minor cleanup of WorkerGroup handling
+	[5dd34964be22]
+
+2012-10-23 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* More threading tweaking to get it to work on Mono in Linux at least
+	[0ec38b0e1a28]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* Change how threads are disposed
+	[a8f518b451a1]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* Ignore test-results
+	[330254bcea32]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* More changes due to problems on Mac OS X
+	[2d8439e9f87c]
+
+2012-10-23 svante <svante at axantum.com>
+
+ 	* Change again how progress is monitored, and how threads are disposed
+	etc. Avoids at least one race condition leading to blocking, and
+	should also be compatible with much earlier implementation of
+	progress possibly fixing the progress problems of the Mac demo
+	version.
+	[925331b81656]
+
+2012-10-22 svante <svante at axantum.com>
+
+ 	* Changes for Mac
+	[ff534ea0bb09]
+
+2012-10-22 svante <svante at axantum.com>
+
+ 	* More test-tweaks and FxCop
+	[60ffa021e18d]
+
+2012-10-22 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Tweak tests for Mono
+	[eb65da1a0bfe]
+
+2012-10-22 svante <svante at axantum.com>
+
+ 	* Merge
+	[f0831b340fdd]
+
+2012-10-22 svante <svante at axantum.com>
+
+ 	* Change how common fixture setup is performed to avoid issues in
+	MonoDevelop since not all attributes appear to be honored there.
+	[c3120da9ea2c]
+
+2012-10-22 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Update and merge
+	[3c5b58154285]
+
+2012-10-22 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Add to ignore
+	[93e3c9cf27c3]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* Threading tweaks and more tests.
+	[8459209c3987]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* More tests - back at 100. Also refactor how ProgessContext and
+	WorkerGroup interacts. It is now ProgressContext ensuring that
+	progress is reported on the appropriate thread.
+	[302c221cd9a2]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* More tests
+	[dd6204717e34]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* Tests for WorkerGroup, and also led to need for minor
+	refactorization in how ThreadWorker instances are handled and
+	returned.
+	[ca9e1baca60f]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* More tests
+	[4a7cb6fc3dcd]
+
+2012-10-21 svante <svante at axantum.com>
+
+ 	* More tests
+	[2403d07afc23]
+
+2012-10-20 svante <svante at axantum.com>
+
+ 	* More tests
+	[708ac033c492]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* FxCop
+	[1bc352482b85]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* More tests.
+	[45ae98c880d2]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* More tests for new and modified code.
+	[97c62a641b74]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* FxCop
+	[c6de97ffbcdc]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* More refactoring and documentation
+	[464d571428f4]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* Refactoring and adding documentation
+	[6bba75e4e8c2]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* FxCop
+	[9bcc959e452e]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* Fix unit tests.
+	[38b216a285cf]
+
+2012-10-19 svante <svante at axantum.com>
+
+ 	* Interim checkin - tests are failing, next step is a clean up and
+	rewrite of tests affected.
+	[37968010d5f2]
+
+2012-10-18 svante <svante at axantum.com>
+
+ 	* Partial, not yet active, refactoring moving code into
+	FileOperationsController to handle asynchronous processing.
+	[34cbf8d0f9f8]
+
+2012-10-18 svante <svante at axantum.com>
+
+ 	* Add WorkerGroup to Android project as well.
+	[190a4cf20d82]
+
+2012-10-18 svante <svante at axantum.com>
+
+ 	* Interim checkin - improve how multi-threaded progress interact with
+	the user and the GUI
+	[771668d405b1]
+
+2012-10-16 svante <svante at axantum.com>
+
+ 	* Interim checkin - improve how multi-threaded operations interact
+	with the user and the GUI
+	[a1211b757408]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* Minor GUI updates
+	[188dd6d3b795]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* FxCop
+	[8a8e856ff2b0]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* More tests.
+	[cf8bffd2515f]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* More test cases to cover new code
+	[cf89af4cb901]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* Remove unused file
+	[19c68833195d]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* More GUI function tweaks.
+	[455bfc4597ed]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* Add file to recent files when encrypting
+	[b5cb3c5b584b]
+
+2012-10-14 svante <svante at axantum.com>
+
+ 	* Further GUI refactoring and FxCop
+	[4cf2e980fec8]
+
+2012-10-13 svante <svante at axantum.com>
+
+ 	* Refctor how recent and open files are handled
+	[9e107a50a017]
+
+2012-10-13 svante <svante at axantum.com>
+
+ 	* Start merging open and recent files list views
+	[5561bd0950da]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* Documenting and updating solution builds etc.
+	[42fb42d79c03]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* Fix solution configurations and some minor errors caused by
+	refactoring and new tests.
+	[b4036e939cf1]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* Remove Mac-project from 'Any CPU' solutions builds.
+	[2fd3817695d0]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* More cleanup of solution configurations etc...
+	[8b851480d0fe]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* Update Mixed Platforms solution configuration.
+	[3b30d3ec002b]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* Back at 100% test coverage
+	[8e47a43922d6]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* More tests
+	[3ad78423dec3]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* More tests.
+	[e414a230f4e0]
+
+2012-10-11 svante <svante at axantum.com>
+
+ 	* More tests
+	[b739843b81d2]
+
+2012-10-10 svante <svante at axantum.com>
+
+ 	* More tests, and some refactoring as a result
+	[9d0c1285f517]
+
+2012-10-10 svante <svante at axantum.com>
+
+ 	* More tests FileOperationsController
+	[84a4e3cfe585]
+
+2012-10-10 svante <svante at axantum.com>
+
+ 	* More FileOperationsController-tests
+	[f62fcf16f1cb]
+
+2012-10-10 svante <svante at axantum.com>
+
+ 	* New tests for FileOperationsController and some fixes as a result
+	[2ee90fc93fbf]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* FxCop
+	[bbcc4a60da71]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests
+	[d7411ae88ea6]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests for FileSystemState, and proper use of Dispose since it's
+	IDisposable
+	[35871dc70fd8]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests for UpdateCheck
+	[78eed4555f52]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests for FileOperation
+	[232659d8d515]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests for ThreadWorker
+	[4df3c10c3cfb]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* Refactor ThreadWorker to use events more consistently
+	[25965e776d7d]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* More tests for ThreadWorker, and fix a bug in Win Forms progress bar
+	display.
+	[25c9968c260f]
+
+2012-10-09 svante <svante at axantum.com>
+
+ 	* Initial tests for ThreadWorker
+	[70fc9ea608c5]
+
+2012-10-08 svante <svante at axantum.com>
+
+ 	* Add tests for DelegateTraceListener
+	[034b2a9cce9a]
+
+2012-10-08 svante <svante at axantum.com>
+
+ 	* Ignore .orig
+	[0ae2cc05f76e]
+
+2012-10-08 svante <svante at axantum.com>
+
+ 	* Add unit tests for Resources in Core
+	[b17b57f8eebb]
+
+2012-10-08 svante <svante at axantum.com>
+
+ 	* Avoid designer collision with 'System', so rename our 'System' to
+	'Runtime'.
+	[155e3316bc9a]
+
+2012-10-04 svante <svante at axantum.com>
+
+ 	* Fix problem with process tracking when disabled
+	[937fa88398d8]
+
+2012-10-04 svante <svante at axantum.com>
+
+ 	* Fix problem when we're not tracking processes
+	[23d5e6696e42]
+
+2012-10-04 svante <svante at axantum.com>
+
+ 	* Clean up handling of process tracking, still making it work on Mac
+	OS X
+	[6bf9e7fc48a4]
+
+2012-10-04 svante <svante at axantum.com>
+
+ 	* Fix hang-on-exit in Mac OS X
+	[0bf1a57e95ec]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Fix the components so they are actually disposed...
+	[36eda94e9e58]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Ensure disposal of all ActiveFile references held by FileSystemState
+	[ecb3275f41c8]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Changes caused by MonoDevelop - possibly ping-pong effect with
+	Visual Studio.
+	[774a1cf652e1]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Improve keeping track of background threads and waiting for them.
+	[f4104aba694b]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Add files to hgignore
+	[a41426bd0f5d]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Change case of file name to reflect the actual class
+	[443cfb97d8ea]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Merge
+	[8e24866d5581]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Backed out changeset: 9356f8c77961
+	[28739e454513]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Change case of file name to reflect the actual class
+	[9356f8c77961]
+
+2012-10-03 svante <svante at axantum.com>
+
+ 	* Add files to hgignore
+	[47f58d78b832]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Clean x64 configuration, we don't need it or want it. It's just
+	troublesome to maintain. Either use x86 or Any CPU.
+	[531fc9c98f4c]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Minor project changes for Android in Mac
+	[54ed643bd05c]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Update the icon
+	[8aa0925d7ec5]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Make the NotifyIcon / Tray handling platform-specific (should
+	migrate perhaps)
+	[246d39942f57]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Add TRACE compilation constat to project files
+	[8fd35da807a2]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Project changes etc for Mac-version
+	[e7c7a6af4d83]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Remove test-results which should not be checked in.
+	[689946fec9a3]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Fix definition of AxantumStrongName.pfx as AssemblyOriginatorKey
+	[28bda43953c7]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Project changes etc for Mac-version
+	[d7e71822c218]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Remove files that should not be checked in
+	[0a7b8d6a1ff5]
+
+2012-10-02 svante <svante at axantum.com>
+
+ 	* Rename the Mac-version of the project file
+	[72eab041db2b]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* Remove file that should not have been part of merge
+	[f781ca0e914c]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* Merge from slamti, Mac code
+	[177e8e093680]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[f2758d4df10a]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[a451b8fca851]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[3f501782f3b5]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[09ba283a5274]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[f9d63ca37359]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[4ca7cc68eeef]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* More casing collissions.
+	[bd1319377637]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* Try to avoid casing conflict
+	[13280fb01a73]
+
+2012-10-01 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Changed the View operation (discard changes) into an Open operation
+	(keep changes and re-encrypt)
+	[cb065ebb29c3]
+
+2012-10-01 Sami Lamti <sami.lamti at gmail.com>
+
+ 	* Adding the Mac Client
+	[2c79a1364a21]
+
+2012-10-01 svante <svante at axantum.com>
+
+ 	* Partial refactoring of the MainForm, to consistent naming etc. More
+	to come.
+	[861b7ca0c234]
+
+2012-09-30 svante <svante at axantum.com>
+
+ 	* Various refactoring of FileOperations, better naming etc.
+	[5b19fa14a906]
+
+2012-09-29 svante <svante at axantum.com>
+
+ 	* Refactor more code into Core from MainForm
+	[653a04344bae]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* More assembly description text updated concerning FxCop-policy
+	[1354556441d3]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Update assembly description
+	[b0e9f2bd27b4]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Refactor more file operations into FileOperationsController
+	[332407e7697c]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Better name for BackgroundMonitor
+	[0cf21a383308]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* FxCop
+	[75b846fcc945]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Refactor ProgressBackgroundWorker into a Component with events.
+	[79f3ef884a89]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Refactor away WorkerArguments and some properties of
+	ThreadWorkerEventArgs
+	[e16e9bed126f]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* Refactor the support for progress bar during background processing
+	[1d4cd9c0b57a]
+
+2012-09-28 svante <svante at axantum.com>
+
+ 	* More code into Core, ensure that progress is called exactly once,
+	guaranteed, at 100%
+	[083174d1bf06]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Start refactoring UI interaction in a more MVC-style with a
+	controller and events, thus moving more re-usable and testable logic
+	into Axantum.AxCrypt.Core
+	[35217256007c]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Refactor and rename EncryptedFileManager to just Background - that's
+	all that's left of it.
+	[2549d6dcb9e0]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Enable use of events for tracking changes during Load of
+	FileSystemState
+	[8386a4a7d52b]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Change the way the UI is updated via events from FileSystemState
+	[9705167737db]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Change the way AXANTUM constant is set, to avoid confusing Visual
+	Studio property pages.
+	[76811bda3ed3]
+
+2012-09-27 svante <svante at axantum.com>
+
+ 	* Enable logging in FakeLogger, so all code is exercised during tests.
+	[2dbe9107972a]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Move DataProtection to target-dependent interface. Implement linked
+	build of Android version of Core
+	[587be5162328]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Create IntermediateOutputPath directory if it does not exist.
+	[9be8bd6b5500]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Move logging to system specific implementation
+	[2ba4e7deb5b9]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Renaming refactoring to make use of common platform-dependent
+	functions less clumsy.
+	[0eb3757d7dbc]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Visual Studio inflicted-noop-change
+	[997ac002d0a3]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Add AssemblyOriginatorKeyFile
+	[9b3f5cedba8f]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* More icons added/fixed
+	[f478ac4c1daa]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Fix Swedish icons as well.
+	[3808fcb148e1]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* New attempt to get the right icon into the form.
+	[b0027e6a4368]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Update embedded icons in resources as well
+	[89f46976bf2f]
+
+2012-09-26 svante <svante at axantum.com>
+
+ 	* Remove 256x256 png icon as it appears this crashes Mono
+	[3af28c0360bc]
+
+2012-09-25 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Fix the test on non-Windows so it's even more correct...
+	[27f4353f6829]
+
+2012-09-25 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Fix test to account for Mono-bug
+	[2731e82951ac]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Use Environment.CurrentDirectory instead of SystemDirectory to
+	determine path root, since it does not work in Linux otherwise
+	[452e2e5cd0bd]
+
+2012-09-25 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Remove more warnings only in MonoDevelop
+	[1a2c73c12cf1]
+
+2012-09-25 ubuntu <ubuntu at ubuntu-VirtualBox>
+
+ 	* Remove unused variables
+	[3af3b3c457d1]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Remove unused variable that Mono compiler detects, but not VS
+	[d9548adc6edf]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Enable AssemblyInfo-compilation and inclusion when not at Axantum
+	[bf21f1c21cca]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Include nunit.framework.dll in the solution to make it compile
+	without having NUnit installed.
+	[7fe183bbc190]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* More renames - MonoDevelop only shows on error at a time
+	apparently...
+	[0359154eeef5]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* More lower-case issues with the resx designer causing problems on
+	Linux etc.
+	[0f99e77324f3]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* More lowercasing to allow for case-sensitive file systems, and
+	resources designer quirk causing Resources to become 'resources'.
+	[df3c57cf1bf8]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Change name of the Resources folder to be lower-case, since the
+	resource designer lower-cases the name, and that won't work on case
+	sensitive file systems unless the folder actually is lower case.
+	[f5362a940428]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Remove still-remaining references to .NET 4.0 in designer files etc.
+	Rename some files that appear to have trouble in different file
+	systems, i.e. Linux
+	[fddf6b625073]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Change framework version to work better with MonoDevelop
+	[74a2b57681df]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Add 'AboutThisAssembly.txt' to explain the strategy for each
+	assembly Move platform-specific implementations to the Mono-assembly
+	Make platform implemenations internal, but still visible to the
+	test-assembly FxCop
+	[8acb4e69aa76]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Move out some implementations to new Axantum.AxCrypt.Mono and .Test
+	assemblies Change the way signing is performed, the goal being that
+	the .csproj should be generic enough to work as-is in MonoDevelop.
+	FxCop fixes.
+	[02d449b8272e]
+
+2012-09-25 svante <svante at axantum.com>
+
+ 	* Backup framework requirement to 3.5 Client Profile due to MonoTouch
+	etc.
+	[faa0167afcf3]
+
+2012-09-24 svante <svante at axantum.com>
+
+ 	* Improve robustness of testing of FileWatcher
+	[54461662fec1]
+
+2012-09-24 svante <svante at axantum.com>
+
+ 	* Avoid overwriting the backing resource in test, causing errors in
+	later tests.
+	[de09063b504b]
+
+2012-09-24 svante <svante at axantum.com>
+
+ 	* Remove dependencies on Windows-style paths and newlines.
+	[8199aeded6d5]
+
+2012-09-22 svante <svante at axantum.com>
+
+ 	* Add license text comment
+	[af9e6f3d527c]
+
+2012-09-22 svante <svante at axantum.com>
+
+ 	* Require explicit setting of RuntimeEnvironment, no default in
+	library.
+	[ca7754fac3a6]
+
+2012-09-22 svante <svante at axantum.com>
+
+ 	* Extend the Platform concept to more than just Windows or Linux.
+	[0d657227871a]
+
+2012-09-21 svante <svante at axantum.com>
+
+ 	* Minor refactoring to move code from ThreadFacade
+	[08889e366da0]
+
+2012-09-21 svante <svante at axantum.com>
+
+ 	* Avoid use of TableLayoutPanel to workaround Mono bug
+	https://bugzilla.novell.com/show_bug.cgi?id=497562 and
+	https://bugzilla.novell.com/show_bug.cgi?id=522783 .
+	[607322fe820d]
+
+2012-09-21 svante <svante at axantum.com>
+
+ 	* Improve build to produce a versioned executable file name, and also
+	clean better
+	[ba3246875233]
+
+2012-09-21 svante <svante at axantum.com>
+
+ 	* Make UpdateCheck resond directly to changes in restApiUrl etc.
+	[70876ec5b800]
+
+2012-09-20 svante <svante at axantum.com>
+
+ 	* FxCop
+	[f50681d82116]
+
+2012-09-20 svante <svante at axantum.com>
+
+ 	* FxCop
+	[d33d8f528e21]
+
+2012-09-09 svante <svante at axantum.com>
+
+ 	* Use CryptServiceProvider AES instead of Managed
+	[a1da08e394da]
+
+2012-09-09 svante <svante at axantum.com>
+
+ 	* FxCop
+	[b2cb7059a96e]
+
+2012-08-12 svante <svante at axantum.com>
+
+ 	* Add show hide passphrase for Decrypt dialog
+	[ad98a9a5212c]
+
+2012-08-12 svante <svante at axantum.com>
+
+ 	* Fix Encrypt Passphrase dialog to hide or show
+	[7e673067c4b8]
+
+2012-08-11 svante <svante at axantum.com>
+
+ 	* More tests.
+	[8ee6b8381e76]
+
+2012-08-11 svante <svante at axantum.com>
+
+ 	* More tests
+	[7e8651e7db5c]
+
+2012-08-11 svante <svante at axantum.com>
+
+ 	* Added tests
+	[6d5746dee092]
+
+2012-08-09 svante <svante at axantum.com>
+
+ 	* Start adding tests for FileOperation
+	[640ae9a095f1]
+
+2012-08-08 svante <svante at axantum.com>
+
+ 	* Fixes for Ubuntu
+	[fb2f239524d9]
+
+2012-08-08 svante <svante at axantum.com>
+
+ 	* More code moving out of EncryptedFileManager
+	[84cf8336c736]
+
+2012-08-08 svante <svante at axantum.com>
+
+ 	* Refactor to move code into Core from WebForm code
+	[8f22168fa2bf]
+
+2012-08-07 svante <svante at axantum.com>
+
+ 	* More build fixes
+	[0f382816910d]
+
+2012-08-07 svante <svante at axantum.com>
+
+ 	* Cleanup
+	[44f5f4f8b6c4]
+
+2012-08-07 svante <svante at axantum.com>
+
+ 	* FxCop and clean up and tweak the strong naming logic
+	[827a1ce53e5b]
+
+2012-08-06 svante <svante at axantum.com>
+
+ 	* Remove from this location, it should be in the solution directory.
+	[a4321fd0901d]
+
+2012-08-06 svante <svante at axantum.com>
+
+ 	* Update ilmerge.exe and update to support proper strongnaming and
+	signing.
+	[d05447ed426c]
+
+2012-08-05 svante <svante at axantum.com>
+
+ 	* Exclude SolutionItems from build since there is nothing to build
+	[a53d1bed7ec1]
+
+2012-08-05 svante <svante at axantum.com>
+
+ 	* XML comments for public members in the Axantum.AxCrypt.Core.Crypto
+	namespace.
+	[acf00a7a7d14]
+
+2012-08-05 svante <svante at axantum.com>
+
+ 	* Refactor the solution structure to support Visual Studio 2010
+	Express
+	[22c3bed8d970]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Fix Unit-test error. Disable test-building in Release-mode.
+	[6f08801a0962]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Add the signtool too.
+	[2f86f5f8e708]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Add Authenticode signing to the merged result in Release
+	configuration
+	[08e42aa21bfc]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Add launch of help page on help button click
+	[fe4bdd0eae87]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Add about box and various debugging support
+	[9af1be8de0de]
+
+2012-08-03 svante <svante at axantum.com>
+
+ 	* Move LastUpdateCheck out from FileSystemState, add NewestVersion to
+	persisted values
+	[2d0201917e0d]
+
+2012-08-02 svante <svante at axantum.com>
+
+ 	* Fix translations to Swedish of new texts.
+	[117a3501487d]
+
+2012-08-02 svante <svante at axantum.com>
+
+ 	* FxCop-fixes
+	[775ed86e8965]
+
+2012-08-02 svante <svante at axantum.com>
+
+ 	* Refactor UpdateCheck, fix coverage and various issues in the UI
+	[ed8d8281b4ad]
+
+2012-08-02 svante <svante at axantum.com>
+
+ 	* Added most support for WebCaller and UpdateCheck. Failed to get
+	ilmerge to produce a strong name. FxCop fixes.
+	[c7a5980854b0]
+
+2012-08-01 svante <svante at axantum.com>
+
+ 	* Add icon to image
+	[bb9431a073ee]
+
+2012-08-01 svante <svante at axantum.com>
+
+ 	* Add ILMerge to a single assembly
+	[19abcb4b9d92]
+
+2012-08-01 svante <svante at axantum.com>
+
+ 	* Add ILMerge to a single assembly
+	[f8a986eb17b8]
+
+2012-07-31 svante <svante at axantum.com>
+
+ 	* Continue to implement automatic versioning
+	[3249e9024cc3]
+
+2012-07-31 svante <svante at axantum.com>
+
+ 	* Continue to implement automatic versioning
+	[079c077145dd]
+
+2012-07-31 svante <svante at axantum.com>
+
+ 	* Add automatic versioning
+	[d9f7754d8012]
+
+2012-07-29 svante <svante at axantum.com>
+
+ 	* Change name to LastActivityTimeUtc and enable raising of events from
+	process
+	[37b06a636dc6]
+
+2012-07-29 svante <svante at axantum.com>
+
+ 	* Move DecryptedActiveFiles from UI code to Core and add test
+	[eb4c2b852211]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Make the test more robust and less load sensitive
+	[02676041fc9e]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Added tests for WorkerArguments
+	[3dfbcf6afc69]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Refactor away ProgressManager
+	[d09400d1f3d0]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Added tests for KnownKeys
+	[7684b4d27736]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Refactor KnownKeys to be a non-static class
+	[71142c38b7de]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Added tests and abstraction for Timing to make it properly testable.
+	[a1c17469dfa8]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* Added tests for ProgressEventArgs
+	[32e187c96147]
+
+2012-07-16 svante <svante at axantum.com>
+
+ 	* More tests and Copyright and License preambles
+	[b6a4a94f0c2d]
+
+2012-07-15 svante <svante at axantum.com>
+
+ 	* Added tests for logging
+	[c1b90db7c63e]
+
+2012-07-15 svante <svante at axantum.com>
+
+ 	* Added tests for Logging
+	[76ac781ba8ad]
+
+2012-07-09 svante <svante at axantum.com>
+
+ 	* Added test for FileSystemStateExtensions.PurgeActiveFiles
+	[517d8d178e62]
+
+2012-07-09 svante <svante at axantum.com>
+
+ 	* Added test for FileSystemStateExtensions.PurgeActiveFiles
+	[a84b42c42ace]
+
+2012-07-09 svante <svante at axantum.com>
+
+ 	* Added tests for FileSystemStateExtensions
+	[22976b589332]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Refactor - make process invocation testable.
+	[34950b10788a]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Refactor and add events to FakeFileInfo
+	[191d2261d645]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Added test TestCheckActiveFilesNoDeleteWhenNotDesktopWindows
+	[5802676a9af1]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* FxCop
+	[c9f7806c7cb1]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Added test TestCheckActiveFilesNotDecryptedAndDoesNotExist
+	[fb58da97818f]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Added test TestCheckActiveFilesKeyIsNotSetWithoutKnownKey
+	[6bd6eaa64e97]
+
+2012-07-01 svante <svante at axantum.com>
+
+ 	* Added test TestCheckActiveFilesKeyIsNotSetWithKnownKey
+	[248961129204]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added test TestCheckActiveFilesKeyIsSet
+	[3a7dcb5f608a]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added TestCheckActiveFilesSkipIfTooRecent
+	[01b9adfe5183]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added test
+	[7681767df668]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added test and refactored for testable time
+	[050e6a8fac56]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added test of FileSystemState.ForEach
+	[288fa65b70ac]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Added test for CreateDirectory()
+	[7494a9d6959c]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Refactor
+	[82fd420142b4]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Refactor
+	[2a03fbf72bf5]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Refactor
+	[39d5899dcdf7]
+
+2012-06-30 svante <svante at axantum.com>
+
+ 	* Refactor
+	[de218a681941]
+
+2012-06-24 svante <svante at axantum.com>
+
+ 	* Refactor
+	[72b78a58b88a]
+
+2012-06-24 svante <svante at axantum.com>
+
+ 	* Add FakeFileWatcher and refactored use of CreateDirectory()
+	[8acf56db2ed3]
+
+2012-06-24 svante <svante at axantum.com>
+
+ 	* TestFileWatcher added
+	[d868d1411279]
+
+2012-06-24 svante <svante at axantum.com>
+
+ 	* Refactor out FileWatcher
+	[16ea08260d6a]
+
+2012-06-23 svante <svante at axantum.com>
+
+ 	* More tests
+	[27c1d02bb2a7]
+
+2012-06-23 svante <svante at axantum.com>
+
+ 	* More tests
+	[21c2bcfe9059]
+
+2012-06-23 svante <svante at axantum.com>
+
+ 	* FxCop
+	[a47a909151de]
+
+2012-06-23 svante <svante at axantum.com>
+
+ 	* More tests
+	[8c4759e30115]
+
+2012-06-22 svante <svante at axantum.com>
+
+ 	* More tests
+	[d7457986a3dc]
+
+2012-06-22 svante <svante at axantum.com>
+
+ 	* Add test
+	[2d7721471dc8]
+
+2012-06-19 svante <svante at axantum.com>
+
+ 	* More tests
+	[635754f24c95]
+
+2012-06-19 svante <svante at axantum.com>
+
+ 	* More refactoring away use of FileInfo and some more tests.
+	[3228e25ae038]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* More tests
+	[41a406cafcb7]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* Refactor FileLock and restore unit test code coverage
+	[7130948b6fe3]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* Add some comments and change some names
+	[520c291f16fa]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* More refactoring
+	[62f0e37928ed]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* More ActiveFile refactoring
+	[2ca2a7d55d0a]
+
+2012-06-18 svante <svante at axantum.com>
+
+ 	* Name changes
+	[4431379845bd]
+
+2012-06-17 svante <svante at axantum.com>
+
+ 	* More refactoring - some problem with editing in Notepad now though.
+	[cacca69ec7ff]
+
+2012-06-17 svante <svante at axantum.com>
+
+ 	* More ActiveFile refactoring
+	[d0e25306d1fa]
+
+2012-06-16 svante <svante at axantum.com>
+
+ 	* Tests plus ActiveFile refactoring
+	[49f10a397430]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tests
+	[9402e234ef02]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tests.
+	[4750a6140bca]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tets.
+	[b251ea386087]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tests.
+	[88d85068ca1a]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tests.
+	[556ece681509]
+
+2012-06-13 svante <svante at axantum.com>
+
+ 	* More tests
+	[7a3121ba1c5f]
+
+2012-06-12 svante <svante at axantum.com>
+
+ 	* More tests.
+	[77514b8571c7]
+
+2012-06-12 svante <svante at axantum.com>
+
+ 	* More tests.
+	[8a590b29f3b7]
+
+2012-06-11 svante <svante at axantum.com>
+
+ 	* FxCop
+	[7e4c42a2d7ff]
+
+2012-06-11 svante <svante at axantum.com>
+
+ 	* More tests and added NullArgumentException checks.
+	[0a3dfaebc8ac]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* FxCop
+	[f2dc5bfe3a40]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[b4b818467b5d]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests.
+	[93204fea5e70]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[01320e38795f]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[f5aebb62e9eb]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[6376d43dcdf4]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[a1ef3b33776e]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* Improve exception handling
+	[23f8e5c6a5c6]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests
+	[5df64ee5c1c2]
+
+2012-06-10 svante <svante at axantum.com>
+
+ 	* More tests and code coverage, and improved code as a result.
+	[a1bfb846dcbf]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Added tests
+	[ec79471ce143]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* More translation
+	[ad5770a59e95]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Remove UserPreferences class since Ubuntu/Mono does not work with
+	UserSettings of custom types apparently.
+	[c4469c2b62be]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Added Multi Lanuage add in temp files to ignore pattern
+	[bd5f4c90fa2b]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Add check mark to current language.
+	[b802732f0303]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Add language selection menu and more texts
+	[d3e1d3e23e2f]
+
+2012-06-09 svante <svante at axantum.com>
+
+ 	* Add language selection menu
+	[cb32c0d1d119]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Add minimize to tray
+	[d81822bf927a]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Make the close open files button smarter
+	[53edfa831c96]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Refactoring - move types to 'Core.System'.
+	[6e8981036e1f]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Translation via Multi Language software
+	[1c7116e4eff4]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Refactor proper order of background worker delegates, ensure event
+	dissociation and background worker disposal.
+	[c66e8fbe8744]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* FxCop
+	[2c0cba3050f4]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* CodeMaid cleanup of using etc.
+	[b12c629614c2]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Refactor code move to Axantum.AxCrypt.Core, step 1. Also include
+	Copyright.
+	[c6cdedd0aef2]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* FxCop
+	[4a35c30f207f]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Fix a failing test since the contract it tests has changed.
+	[db8beaf2af40]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Don't know where BouncyCastle got lost, but it should be here I
+	think.
+	[ff5fe03f29bd]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* Improve buffering and implement progress throttling so we don't
+	overload the GUI thread.
+	[6825cbfaca70]
+
+2012-06-08 svante <svante at axantum.com>
+
+ 	* More logging and remove unnecessary BeginInvoke
+	[6fc2e46ea334]
+
+2012-06-07 svante <svante at axantum.com>
+
+ 	* More logging fixes to support Debug/Verbose better.
+	[a2db78a7c0a3]
+
+2012-06-07 svante <svante at axantum.com>
+
+ 	* Move logging, fix logging level in AxCrypt reader. Improve componen
+	EncryptedFileManager design support, add menu support for commands.
+	[09656ca9670e]
+
+2012-06-07 svante <svante at axantum.com>
+
+ 	* More handling of Cancel
+	[147e52927df8]
+
+2012-06-07 svante <svante at axantum.com>
+
+ 	* Cancellation at decrypt for open
+	[6e77167b57a6]
+
+2012-06-05 svante <svante at axantum.com>
+
+ 	* Refactor
+	[5cb6e50e6d2b]
+
+2012-06-04 svante <svante at axantum.com>
+
+ 	* Start work on Cancellation
+	[994eb124c7bb]
+
+2012-06-04 svante <svante at axantum.com>
+
+ 	* Remove dead code
+	[e11dd8c13e61]
+
+2012-06-04 svante <svante at axantum.com>
+
+ 	* Refactor background code into MainFormThreadFacade and fix some
+	FxCop issues.
+	[056a5a86cbb9]
+
+2012-06-04 svante <svante at axantum.com>
+
+ 	* Adding more progress context and background operations
+	[315117247810]
+
+2012-06-03 svante <svante at axantum.com>
+
+ 	* Threading improvements
+	[71ee6be0964d]
+
+2012-06-02 svante <svante at axantum.com>
+
+ 	* Progress indication for open and launch
+	[bb11e65b77cf]
+
+2012-06-02 svante <svante at axantum.com>
+
+ 	* Progress on decyption as well
+	[eec1410c4829]
+
+2012-05-31 svante <svante at axantum.com>
+
+ 	* FxCop
+	[118906bc77af]
+
+2012-05-31 svante <svante at axantum.com>
+
+ 	* Continue work on background process
+	[78fccc91b1ff]
+
+2012-05-31 svante <svante at axantum.com>
+
+ 	* Fix problem encrypting file without extension
+	[3002af765179]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* Ensure FileInfo is refreshed, Linux also requires it although .NET
+	does not.
+	[0e5b81528502]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* FxCop
+	[74242553e238]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* Start on the thread facade
+	[79f79e07d2f4]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* Start working on cleaning up the borders between GUI and non-GUI
+	[d953047c1f6b]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* Fix wrong use of LastWriteTime causing never deletion
+	[8ab009c04e44]
+
+2012-05-30 svante <svante at axantum.com>
+
+ 	* Implement key recognition via thumbprint
+	[fc58df2f9e69]
+
+2012-05-29 svante <svante at axantum.com>
+
+ 	* Add test for open files at exit and a close menu and button choice
+	[ed59e43c971a]
+
+2012-05-28 svante <svante at axantum.com>
+
+ 	* Revert to timer triggered by file system change events for now.
+	[b070bf8021ea]
+
+2012-05-28 svante <svante at axantum.com>
+
+ 	* Continued work on file system change event driven mode, still far
+	from ok.
+	[0a957c558460]
+
+2012-05-27 svante <svante at axantum.com>
+
+ 	* Context menu proof of concept
+	[dce7ea2c0f80]
+
+2012-05-27 svante <svante at axantum.com>
+
+ 	* FxCop and minor tweaks
+	[c7ae04d49037]
+
+2012-05-27 svante <svante at axantum.com>
+
+ 	* Fix log output to a tab
+	[0b61be90f11a]
+
+2012-05-27 svante <svante at axantum.com>
+
+ 	* Fix anchor etc of tab and progress control
+	[7320803499d1]
+
+2012-05-27 svante <svante at axantum.com>
+
+ 	* Proof of concept, progress bar
+	[d130e016b8ff]
+
+2012-05-26 svante <svante at axantum.com>
+
+ 	* Proof of concept using background worker
+	[064456b77871]
+
+2012-05-25 svante <svante at axantum.com>
+
+ 	* More progress
+	[f340019955e7]
+
+2012-05-25 svante <svante at axantum.com>
+
+ 	* Refactor the various file handling classes away from static etc.
+	[688684696088]
+
+2012-05-24 svante <svante at axantum.com>
+
+ 	* Work in progress on progress-handling
+	[43f1b2435f7a]
+
+2012-05-23 svante <svante at axantum.com>
+
+ 	* Use larger buffers for Stream.CopyTo
+	[873821e1d1ca]
+
+2012-05-22 svante <svante at axantum.com>
+
+ 	* FxCop and MoMA
+	[d05b25920789]
+
+2012-05-22 svante <svante at axantum.com>
+
+ 	* Basic decryption of files
+	[22a896805dc4]
+
+2012-05-22 svante <svante at axantum.com>
+
+ 	* Basic encryption passphrase dialog
+	[d4155615ee0e]
+
+2012-05-21 svante <svante at axantum.com>
+
+ 	* Save as + FxCop
+	[a68d38754c9e]
+
+2012-05-21 svante <svante at axantum.com>
+
+ 	* Basic encrytion functionality
+	[91d1543cc87d]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Start working on Encrypt document
+	[ec5a272a1cd7]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Add check for existing key and default key in KnownKeys
+	[769f47096194]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Refactor FileSystemState
+	[87e4944f247f]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* FxCop
+	[786a6db9ca4e]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Refactor active file handling
+	[207b3b5b27a7]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Active file tweaks
+	[31596b2bf0e4]
+
+2012-05-20 svante <svante at axantum.com>
+
+ 	* Partial refactor of FileSystemState etc. This code is not quite
+	working.
+	[fe136e882322]
+
+2012-05-19 svante <svante at axantum.com>
+
+ 	* Fixed cancel button and default extension etc
+	[adfd420e8390]
+
+2012-05-19 svante <svante at axantum.com>
+
+ 	* FxCop
+	[d75bb1a4c0ea]
+
+2012-05-19 svante <svante at axantum.com>
+
+ 	* Basic encryption/decryption functionality
+	[310dc4213827]
+
+2012-05-19 svante <svante at axantum.com>
+
+ 	* More work on handling the status
+	[0a3df80cedc3]
+
+2012-05-19 svante <svante at axantum.com>
+
+ 	* More work with the state machine of active and deleted files.
+	[5c263a0bf215]
+
+2012-05-18 svante <svante at axantum.com>
+
+ 	* Add environment specific handling
+	[151dfc9fc7fa]
+
+2012-05-18 svante <svante at axantum.com>
+
+ 	* Added logging support and some changes to how files are opened and
+	cleaned
+	[05ac2067ca18]
+
+2012-05-18 svante <svante at axantum.com>
+
+ 	* Add IDisposable to ActiveFile
+	[530415b11f40]
+
+2012-05-18 svante <svante at axantum.com>
+
+ 	* Use process also in determination, mostly because it should improve
+	Linux use.
+	[221c07f6ce0b]
+
+2012-05-17 svante <svante at axantum.com>
+
+ 	* FxCop
+	[85f10b93745e]
+
+2012-05-17 svante <svante at axantum.com>
+
+ 	* User setting persistence proof of concept.
+	[db6793a8c25e]
+
+2012-05-17 svante <svante at axantum.com>
+
+ 	* Double click implementation
+	[a9314d3c85b0]
+
+2012-05-17 svante <svante at axantum.com>
+
+ 	* Implemented basic serialization
+	[de741df389ab]
+
+2012-05-17 svante <svante at axantum.com>
+
+ 	* Minor tweaks to accessibility etc of ActiveFileMonitor
+	[b7356d92c0c0]
+
+2012-05-15 svante <svante at axantum.com>
+
+ 	* FxCop
+	[d576066cf8fe]
+
+2012-05-15 svante <svante at axantum.com>
+
+ 	* More work with the ListView
+	[09185f6029b4]
+
+2012-05-14 svante <svante at axantum.com>
+
+ 	* FxCop
+	[4acae21b3d08]
+
+2012-05-14 svante <svante at axantum.com>
+
+ 	* More tweaking of handling of active file status etc
+	[8cb6d73035ff]
+
+2012-05-14 svante <svante at axantum.com>
+
+ 	* Improve handling of file monitoring
+	[45c949de01f4]
+
+2012-05-13 svante <svante at axantum.com>
+
+ 	* Interim work on active file state
+	[fffd12bd389d]
+
+2012-05-13 svante <svante at axantum.com>
+
+ 	* Work with the active file list
+	[97308c525f88]
+
+2012-05-12 svante <svante at axantum.com>
+
+ 	* Start experimenting with the open file list view
+	[bf7966c8f41a]
+
+2012-05-12 svante <svante at axantum.com>
+
+ 	* Minor refactoring
+	[d0b8353f0786]
+
+2012-05-12 svante <svante at axantum.com>
+
+ 	* Proof of concept code for polling and re-encrypting when not locked.
+	[910faaf5a846]
+
+2012-05-11 svante <svante at axantum.com>
+
+ 	* Started working on the active file state poller
+	[3cc84d1e0016]
+
+2012-05-11 svante <svante at axantum.com>
+
+ 	* Extract MessageBox because of the clumsy form recommended by FxCop
+	[05a7218c4a80]
+
+2012-05-10 svante <svante at axantum.com>
+
+ 	* Fix FxCop issues
+	[3deed122d1da]
+
+2012-05-06 svante <svante at axantum.com>
+
+ 	* Added embryo of GUI application, mostly just to have it available
+	and backed up
+	[dd1605799a84]
+
+2012-05-05 svante <svante at axantum.com>
+
+ 	* Added embryo of GUI application, mostly just to have it available
+	and backed up
+	[41a8e8ab456d]
+
+2012-04-23 svante <svante at axantum.com>
+
+ 	* Original version of AxCrypt 2.0 design ideas, before revising for
+	the .NET/Mono decision.
+	[f0c3fb75d85e]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Removing extra references
+	[8287b170ea21]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Avoid some FxCop messages
+	[1b12411d7832]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Add more tests
+	[e8984e80bd75]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Add tests for KeyWrap1 Set
+	[c920fe71fe40]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Added tests and change how current version is handled.
+	[e8211c669dcc]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Add test for bad file name block without ending nul
+	[8aa08d2bb7be]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Change the way EncryptionInfoBlock is initially set.
+	[4554b7e58714]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Add test for too new file version
+	[c7fd5f86e095]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Add tests for invalid arguments to EncryptTo
+	[cad88ddf6bff]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Refactor and implement encryption without compression and add tests.
+	[4d217abff37d]
+
+2012-04-21 svante <svante at axantum.com>
+
+ 	* Added test for CompressionInfoHeader bug in 1.x
+	[abc819ad677e]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Fix bug when providing wrong key and add tests for wrong key in
+	DocumentHeaders
+	[8f2bfd513e5e]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Refactor how cipher stream length is passed
+	[c89ccb4369a6]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Refactor DocumentHeaders.Write to clarify things.
+	[1e228d830e46]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Add tests for DocumentHeaders
+	[0a666d462c18]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Add CompressionHeaderBlock when encrypting
+	[e3bb5b049e27]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Fix test code to ensure header block length is correct by default.
+	[de259d61dcf2]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Add more tests for AxCryptReader
+	[bcb120bace81]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* More tests
+	[7677f2f89144]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Remove FxCop warnings
+	[524c1bca310a]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* More tests.
+	[d071512b21c3]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Add tests for HMAC in AxCryptReader
+	[4170ae00c3f1]
+
+2012-04-20 svante <svante at axantum.com>
+
+ 	* Minor refactoring and more tests for AxCryptReader
+	[47b5e2a47e01]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add start of tests for AxCryptStreamReader / AxCryptReader
+	[abbfb1dd553f]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add tests for RuntimeFileInfo
+	[5de9d63b95a7]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add tests for NonClosingStream
+	[b60e2b3970b9]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add 'test' of Flush()
+	[83908f8bff03]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add tests for LookAheadStream
+	[73f187e67eae]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add test-cases to increase code coverage.
+	[c69ad736b7d8]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Fix FxCop error
+	[59348c60c1cc]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add tests for HmacStream and fix some errors found
+	[ef7ab266578f]
+
+2012-04-19 svante <svante at axantum.com>
+
+ 	* Add tests to complete code coverage, and throw on Flush()
+	[a21fb714d5a0]
+
+2012-04-18 svante <svante at axantum.com>
+
+ 	* Add tests for AxCryptDataStream
+	[c5b356e78b4d]
+
+2012-04-18 svante <svante at axantum.com>
+
+ 	* Refactor how the hmac stream is handled in AxCryptReader to
+	streamline it a bit.
+	[09c79c3b5c9b]
+
+2012-04-18 svante <svante at axantum.com>
+
+ 	* Prepare to add tests for IO Streams
+	[d90ca544cf17]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests for Subkey
+	[45fc9357418e]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests for Passphrase
+	[1015998d009a]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Fix bad test
+	[a0e3f4722e00]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests for KeyWrapSalt
+	[26325138228a]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add more tests to ensure code coverage.
+	[f774e8b61ffe]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* More KeyWrap tests and tweaks to remove useless code.
+	[772d990ed409]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* More tests for DataHmac
+	[e3d4a7bea1b7]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests for DataHmac
+	[1a6d93c60c26]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Added tests for AxCryptHMACSHA1
+	[e1121e6fc1ce]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Remove meaningless copy constructor (the class is immutable) and add
+	a few tests.
+	[3bebee935bfc]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests for AesKey
+	[8ddda9b70c65]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Added tests for AesIV
+	[a45d21fd15f4]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* More tests
+	[e5a3997082ef]
+
+2012-04-17 svante <svante at axantum.com>
+
+ 	* Add tests to complete code coverage
+	[898f14a14833]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Fix som FxCop issues.
+	[e840cfee61fd]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* More tests
+	[c4d14166065e]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* More tests
+	[9421f2e0f39f]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Add test for invalid passphrase
+	[ffe92bfb8bcc]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Use the right overloads to cover more code
+	[979ce4e6d29f]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* More tests for exceptions
+	[821f87b15ccd]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Add code to test exceptions including serialization and
+	deserialization
+	[86c8e99b3f2f]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Remove effectively dead code
+	[faeefd31937d]
+
+2012-04-16 svante <svante at axantum.com>
+
+ 	* Added test for invalid HMAC detection in input for CopyEncryptedTo
+	[3ff7746078db]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Add tests for various invalid argument situations etc.
+	[91ab88fff82e]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Fix typo using wrong test DateTime
+	[e6018e83c2dc]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Added test of encryption of larger file
+	[034ddc784e09]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Clear up some FxCop issues
+	[0587cff9765a]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Implement support for renaming algorithm
+	[e9d26917b7a5]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Avoid a Mono todo
+	[674e239433dd]
+
+2012-04-15 svante <svante at axantum.com>
+
+ 	* Support setting of file times
+	[0cd47eb0abb6]
+
+2012-04-14 svante <svante at axantum.com>
+
+ 	* Refactor AxCryptDocument a bit, and implement == for DataHmac
+	[c9484b2eaa87]
+
+2012-04-14 svante <svante at axantum.com>
+
+ 	* Refactor the way AxCryptDocument relates to the AxCryptReader, so it
+	holds the reference.
+	[aa2f73a2e520]
+
+2012-04-13 svante <svante at axantum.com>
+
+ 	* Implement file decrypt and implement simple round-trip test
+	[006f2bd57fc1]
+
+2012-04-13 svante <svante at axantum.com>
+
+ 	* Implement basic file encryption and non-testing test
+	[f016c4f48620]
+
+2012-04-13 svante <svante at axantum.com>
+
+ 	* Fix some naming issues
+	[87d58f4d3ff0]
+
+2012-04-13 svante <svante at axantum.com>
+
+ 	* Start working on higher level functions such as file encryption
+	[5624fd808552]
+
+2012-04-12 svante <svante at axantum.com>
+
+ 	* Rename AxCryptReaderSettings to Passphrase and other refactoring.
+	Added one Trace output.
+	[227ad5d60b8d]
+
+2012-04-12 svante <svante at axantum.com>
+
+ 	* Fix some FxCop issues.
+	[f5fcc741f057]
+
+2012-04-12 svante <svante at axantum.com>
+
+ 	* Basic implementation of AxCrypt Encryption
+	[0ba22953972e]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* Support for more headers to write and added DataHmac type
+	[77cd6f369be5]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* Started working on implementing encryption.
+	[f9d239b8dbad]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* Move more to Crypto, correct bad namespace renaming earlier
+	[5f1c006021cb]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* Refactor KeyWrapSalt etc
+	[90aff41af2f0]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* More renaming and refactoring and FxCop:ing
+	[7581d5085750]
+
+2012-04-11 svante <svante at axantum.com>
+
+ 	* Refactor, rename and add new class for IV
+	[fb64077ab462]
+
+2012-04-10 svante <svante at axantum.com>
+
+ 	* Refactor to use immutable AesKey instead of byte[] and move things
+	to Crypto namespace
+	[e5331462a34a]
+
+2012-04-10 svante <svante at axantum.com>
+
+ 	* Implement iteration calculation etc
+	[f3179faa520f]
+
+2012-04-10 svante <svante at axantum.com>
+
+ 	* Refactoring
+	[6ae743926303]
+
+2012-04-09 svante <svante at axantum.com>
+
+ 	* Refactoring
+	[b9d2fab8adc3]
+
+2012-04-09 svante <svante at axantum.com>
+
+ 	* Refactoring handling of settings, which in the end will just be the
+	key most likely
+	[2c78fe2a7159]
+
+2012-04-09 svante <svante at axantum.com>
+
+ 	* Tweak the implementation of DocumentHeaders and AxCryptDocument
+	[ee9cb1e6d178]
+
+2012-04-08 svante <svante at axantum.com>
+
+ 	* Refactor out DocumentHeaders
+	[65748898c3f9]
+
+2012-04-07 svante <svante at axantum.com>
+
+ 	* Implement simple passphrase changing and thus basic writing of an
+	AxCrypt stream.
+	[6e1172eb2097]
+
+2012-04-07 svante <svante at axantum.com>
+
+ 	* Add support for wrapping of key
+	[2ae671c357c3]
+
+2012-03-19 svante <svante at axantum.com>
+
+ 	* Continued on encryption
+	[ef3ad1c21a94]
+
+2012-03-19 svante <svante at axantum.com>
+
+ 	* Start working on encryption
+	[88a36504c97f]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* FxCop cleanup
+	[6eb58da4dae7]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Support for file times with conversion from Windows FILETIME format.
+	[27e5ad9ee132]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Add some support for legacy files.
+	[3ad2a6a19151]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* A few more tests.
+	[ccc206456e12]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Include check for valid key when loading an AxCryptDocument
+	[794d4c9aea4a]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Add error status in order to be able to provide localized user
+	messages later.
+	[9c2e88f7ef7f]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Simplify the code a bit
+	[bedbaaffadae]
+
+2012-03-12 svante <svante at axantum.com>
+
+ 	* Cleaner logic
+	[6738fe911aa9]
+
+2012-03-11 svante <svante at axantum.com>
+
+ 	* Remove some dead code
+	[bfdefe6faf71]
+
+2012-03-09 svante <svante at axantum.com>
+
+ 	* Fixed comment and some better names and increased test code
+	coverage.
+	[f20a84199627]
+
+2012-03-09 svante <svante at axantum.com>
+
+ 	* Basic support for decrypting compressed files using Bouncy Castle
+	[477b9d4373f0]
+
+2012-03-07 svante <svante at axantum.com>
+
+ 	* HMAC basic verification and calculation implemented.
+	[59223f8114cd]
+
+2012-03-06 svante <svante at axantum.com>
+
+ 	* Continued work on supporting HMAC calculation
+	[6a265e17b0ca]
+
+2012-03-05 svante <svante at axantum.com>
+
+ 	* Starting work on supporting HMAC
+	[657fa0bc22f2]
+
+2012-03-05 svante <svante at axantum.com>
+
+ 	* Basic decryption of uncompressed stream implemented
+	[b9ac7f8e24d8]
+
+2012-03-04 svante <svante at axantum.com>
+
+ 	* Start implementing decryption of the data stream
+	[fea740543953]
+
+2012-03-04 svante <svante at axantum.com>
+
+ 	* Add test for IsCompressed and fix more FxCop warnings
+	[9a4c9571ef58]
+
+2012-03-03 svante <svante at axantum.com>
+
+ 	* Renames according to FxCop
+	[87e022b29fa9]
+
+2012-03-03 svante <svante at axantum.com>
+
+ 	* Added support for UnicodeFileName, test for hmac and removed some
+	FxCop issues
+	[d467042c3cbf]
+
+2012-03-02 svante <svante at axantum.com>
+
+ 	* Basic functionality of header decryption ok. Design still needs some
+	work.
+	[920eefa64ad8]
+
+2012-02-22 svante <svante at axantum.com>
+
+ 	* Started work on decrypting the headers and some tests
+	[c31902aa1b88]
+
+2012-02-11 svante <svante at axantum.com>
+
+ 	* Started some work on AxCryptDocument
+	[cfdba80caf3f]
+
+2012-02-10 svante <svante at axantum.com>
+
+ 	* Some more tests for Magic Guid, which also found a bug!
+	[9f3b1e79f777]
+
+2012-02-10 svante <svante at axantum.com>
+
+ 	* Added test for bad KeyWrapMode
+	[1f5500c9d73e]
+
+2012-02-10 svante <svante at axantum.com>
+
+ 	* Added tests for endian optimization
+	[89cb5e185681]
+
+2012-02-10 svante <svante at axantum.com>
+
+ 	* Add tests for extension methods.
+	[e44977e8c228]
+
+2012-02-10 svante <svante at axantum.com>
+
+ 	* Add ExcludeFromCodeCoverage attribute
+	[8a0d1ca20257]
+
+2012-02-08 svante <svante at axantum.com>
+
+ 	* Added test for ArgumentException
+	[d518a0c38e6e]
+
+2012-02-05 svante <svante at axantum.com>
+
+ 	* Added license texts. Fixed KeyWrap compatibility with AxCrypt.
+	[ddca1886f9a4]
+
+2012-02-04 svante <svante at axantum.com>
+
+ 	* Minor refactorisation to fix FxCop warnings etc
+	[a96250d74cd2]
+
+2012-02-03 svante <svante at axantum.com>
+
+ 	* Unwrap validates with the test vector
+	[d875f7308acb]
+
+2012-02-03 svante <svante at axantum.com>
+
+ 	* Iterim - does not build.
+	[880b6e8f4d59]
+
+2012-01-26 svante <svante at axantum.com>
+
+ 	* Started working on AxCryptDocument and KeyWrap
+	[55afff211fcb]
+
+2012-01-20 svante <svante at axantum.com>
+
+ 	* Add test for IdTag and fix handling of AxCrypt1Guid better
+	[71d96cf04107]
+
+2012-01-20 svante <svante at axantum.com>
+
+ 	* Tweak the use of the datablock array, allow forward compatiblity
+	with unknown header blocktypes.
+	[b9694ed2fe00]
+
+2012-01-19 svante <svante at axantum.com>
+
+ 	* Additional tests for preamble
+	[09229ccfdb38]
+
+2012-01-16 svante <svante at axantum.com>
+
+ 	* Add another test, and change the way HeaderBlocks are constructed.
+	[641972f772c5]
+
+2012-01-15 svante <svante at axantum.com>
+
+ 	* Exclude warnings about too few in a namespace for now
+	[c514c39ef936]
+
+2012-01-15 svante <svante at axantum.com>
+
+ 	* Add more HeaderBlocks and teset for Preamble
+	[3948025c1a56]
+
+2012-01-15 svante <svante at axantum.com>
+
+ 	* Add code and simple test for VersionHeaderBlock
+	[ab5fe3ad94d7]
+
+2012-01-13 svante <svante at axantum.com>
+
+ 	* Minor FxCop violations
+	[ed56d931f7e2]
+
+2012-01-13 svante <svante at axantum.com>
+
+ 	* Added test with a real AxCrypt-file in resources.
+	[313052314837]
+
+2012-01-13 svante <svante at axantum.com>
+
+ 	* Added more copyright statements
+	[218649b97c6c]
+
+2012-01-13 svante <svante>
+
+ 	* Added a copyright statement to one file and fixed an ignore file.
+	[9f6e80f6c759]
+
+2012-01-13 svante <svante>
+
+ 	* Intial
+	[9db471ef98ae]
+
diff --git a/CustomDictionary.xml b/CustomDictionary.xml
new file mode 100644
index 0000000..929b397
--- /dev/null
+++ b/CustomDictionary.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- http://msdn.microsoft.com/en-us/library/bb514188.aspx -->
+<Dictionary>
+    <Words>
+        <Unrecognized>
+            <Word></Word>
+        </Unrecognized>
+        <Recognized>
+            <Word>Axantum</Word>
+            <Word>Svenska</Word>
+            <Word>bouncycastle</Word>
+            <Word>Ios</Word>
+            <Word>Osx</Word>
+            <Word>Pem</Word>
+        </Recognized>
+        <Deprecated>
+            <Term PreferredAlternate=""></Term>
+        </Deprecated>
+        <Compound>
+            <Term CompoundAlternate=""></Term>
+        </Compound>
+        <DiscreteExceptions>
+            <Term></Term>
+        </DiscreteExceptions>
+    </Words>
+    <Acronyms>
+        <CasingExceptions>
+            <Acronym>Ax</Acronym>
+        </CasingExceptions>
+    </Acronyms>
+</Dictionary>
\ No newline at end of file
diff --git a/Newtonsoft.Json/AxantumStrongName.pfx b/Newtonsoft.Json/AxantumStrongName.pfx
new file mode 100644
index 0000000..be0e522
Binary files /dev/null and b/Newtonsoft.Json/AxantumStrongName.pfx differ
diff --git a/Newtonsoft.Json/Bson/BsonBinaryType.cs b/Newtonsoft.Json/Bson/BsonBinaryType.cs
new file mode 100644
index 0000000..cde425d
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonBinaryType.cs
@@ -0,0 +1,44 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Bson
+{
+    internal enum BsonBinaryType : byte
+    {
+        Binary = 0x00,
+        Function = 0x01,
+
+        [Obsolete("This type has been deprecated in the BSON specification. Use Binary instead.")]
+        BinaryOld = 0x02,
+
+        [Obsolete("This type has been deprecated in the BSON specification. Use Uuid instead.")]
+        UuidOld = 0x03,
+        Uuid = 0x04,
+        Md5 = 0x05,
+        UserDefined = 0x80
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonBinaryWriter.cs b/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
new file mode 100644
index 0000000..b16b3f2
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonBinaryWriter.cs
@@ -0,0 +1,325 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Bson
+{
+    internal class BsonBinaryWriter
+    {
+        private static readonly Encoding Encoding = new UTF8Encoding(false);
+
+        private readonly BinaryWriter _writer;
+
+        private byte[] _largeByteBuffer;
+
+        public DateTimeKind DateTimeKindHandling { get; set; }
+
+        public BsonBinaryWriter(BinaryWriter writer)
+        {
+            DateTimeKindHandling = DateTimeKind.Utc;
+            _writer = writer;
+        }
+
+        public void Flush()
+        {
+            _writer.Flush();
+        }
+
+        public void Close()
+        {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            _writer.Close();
+#else
+            _writer.Dispose();
+#endif
+        }
+
+        public void WriteToken(BsonToken t)
+        {
+            CalculateSize(t);
+            WriteTokenInternal(t);
+        }
+
+        private void WriteTokenInternal(BsonToken t)
+        {
+            switch (t.Type)
+            {
+                case BsonType.Object:
+                {
+                    BsonObject value = (BsonObject)t;
+                    _writer.Write(value.CalculatedSize);
+                    foreach (BsonProperty property in value)
+                    {
+                        _writer.Write((sbyte)property.Value.Type);
+                        WriteString((string)property.Name.Value, property.Name.ByteCount, null);
+                        WriteTokenInternal(property.Value);
+                    }
+                    _writer.Write((byte)0);
+                }
+                    break;
+                case BsonType.Array:
+                {
+                    BsonArray value = (BsonArray)t;
+                    _writer.Write(value.CalculatedSize);
+                    ulong index = 0;
+                    foreach (BsonToken c in value)
+                    {
+                        _writer.Write((sbyte)c.Type);
+                        WriteString(index.ToString(CultureInfo.InvariantCulture), MathUtils.IntLength(index), null);
+                        WriteTokenInternal(c);
+                        index++;
+                    }
+                    _writer.Write((byte)0);
+                }
+                    break;
+                case BsonType.Integer:
+                {
+                    BsonValue value = (BsonValue)t;
+                    _writer.Write(Convert.ToInt32(value.Value, CultureInfo.InvariantCulture));
+                }
+                    break;
+                case BsonType.Long:
+                {
+                    BsonValue value = (BsonValue)t;
+                    _writer.Write(Convert.ToInt64(value.Value, CultureInfo.InvariantCulture));
+                }
+                    break;
+                case BsonType.Number:
+                {
+                    BsonValue value = (BsonValue)t;
+                    _writer.Write(Convert.ToDouble(value.Value, CultureInfo.InvariantCulture));
+                }
+                    break;
+                case BsonType.String:
+                {
+                    BsonString value = (BsonString)t;
+                    WriteString((string)value.Value, value.ByteCount, value.CalculatedSize - 4);
+                }
+                    break;
+                case BsonType.Boolean:
+                {
+                    BsonValue value = (BsonValue)t;
+                    _writer.Write((bool)value.Value);
+                }
+                    break;
+                case BsonType.Null:
+                case BsonType.Undefined:
+                    break;
+                case BsonType.Date:
+                {
+                    BsonValue value = (BsonValue)t;
+
+                    long ticks = 0;
+
+                    if (value.Value is DateTime)
+                    {
+                        DateTime dateTime = (DateTime)value.Value;
+                        if (DateTimeKindHandling == DateTimeKind.Utc)
+                            dateTime = dateTime.ToUniversalTime();
+                        else if (DateTimeKindHandling == DateTimeKind.Local)
+                            dateTime = dateTime.ToLocalTime();
+
+                        ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTime, false);
+                    }
+#if !NET20
+                    else
+                    {
+                        DateTimeOffset dateTimeOffset = (DateTimeOffset)value.Value;
+                        ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(dateTimeOffset.UtcDateTime, dateTimeOffset.Offset);
+                    }
+#endif
+
+                    _writer.Write(ticks);
+                }
+                    break;
+                case BsonType.Binary:
+                {
+                    BsonBinary value = (BsonBinary)t;
+
+                    byte[] data = (byte[])value.Value;
+                    _writer.Write(data.Length);
+                    _writer.Write((byte)value.BinaryType);
+                    _writer.Write(data);
+                }
+                    break;
+                case BsonType.Oid:
+                {
+                    BsonValue value = (BsonValue)t;
+
+                    byte[] data = (byte[])value.Value;
+                    _writer.Write(data);
+                }
+                    break;
+                case BsonType.Regex:
+                {
+                    BsonRegex value = (BsonRegex)t;
+
+                    WriteString((string)value.Pattern.Value, value.Pattern.ByteCount, null);
+                    WriteString((string)value.Options.Value, value.Options.ByteCount, null);
+                }
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
+            }
+        }
+
+        private void WriteString(string s, int byteCount, int? calculatedlengthPrefix)
+        {
+            if (calculatedlengthPrefix != null)
+                _writer.Write(calculatedlengthPrefix.Value);
+
+            WriteUtf8Bytes(s, byteCount);
+
+            _writer.Write((byte)0);
+        }
+
+        public void WriteUtf8Bytes(string s, int byteCount)
+        {
+            if (s != null)
+            {
+                if (_largeByteBuffer == null)
+                {
+                    _largeByteBuffer = new byte[256];
+                }
+                if (byteCount <= 256)
+                {
+                    Encoding.GetBytes(s, 0, s.Length, _largeByteBuffer, 0);
+                    _writer.Write(_largeByteBuffer, 0, byteCount);
+                }
+                else
+                {
+                    byte[] bytes = Encoding.GetBytes(s);
+                    _writer.Write(bytes);
+                }
+            }
+        }
+
+        private int CalculateSize(int stringByteCount)
+        {
+            return stringByteCount + 1;
+        }
+
+        private int CalculateSizeWithLength(int stringByteCount, bool includeSize)
+        {
+            int baseSize = (includeSize)
+                ? 5 // size bytes + terminator
+                : 1; // terminator
+
+            return baseSize + stringByteCount;
+        }
+
+        private int CalculateSize(BsonToken t)
+        {
+            switch (t.Type)
+            {
+                case BsonType.Object:
+                {
+                    BsonObject value = (BsonObject)t;
+
+                    int bases = 4;
+                    foreach (BsonProperty p in value)
+                    {
+                        int size = 1;
+                        size += CalculateSize(p.Name);
+                        size += CalculateSize(p.Value);
+
+                        bases += size;
+                    }
+                    bases += 1;
+                    value.CalculatedSize = bases;
+                    return bases;
+                }
+                case BsonType.Array:
+                {
+                    BsonArray value = (BsonArray)t;
+
+                    int size = 4;
+                    ulong index = 0;
+                    foreach (BsonToken c in value)
+                    {
+                        size += 1;
+                        size += CalculateSize(MathUtils.IntLength(index));
+                        size += CalculateSize(c);
+                        index++;
+                    }
+                    size += 1;
+                    value.CalculatedSize = size;
+
+                    return value.CalculatedSize;
+                }
+                case BsonType.Integer:
+                    return 4;
+                case BsonType.Long:
+                    return 8;
+                case BsonType.Number:
+                    return 8;
+                case BsonType.String:
+                {
+                    BsonString value = (BsonString)t;
+                    string s = (string)value.Value;
+                    value.ByteCount = (s != null) ? Encoding.GetByteCount(s) : 0;
+                    value.CalculatedSize = CalculateSizeWithLength(value.ByteCount, value.IncludeLength);
+
+                    return value.CalculatedSize;
+                }
+                case BsonType.Boolean:
+                    return 1;
+                case BsonType.Null:
+                case BsonType.Undefined:
+                    return 0;
+                case BsonType.Date:
+                    return 8;
+                case BsonType.Binary:
+                {
+                    BsonBinary value = (BsonBinary)t;
+
+                    byte[] data = (byte[])value.Value;
+                    value.CalculatedSize = 4 + 1 + data.Length;
+
+                    return value.CalculatedSize;
+                }
+                case BsonType.Oid:
+                    return 12;
+                case BsonType.Regex:
+                {
+                    BsonRegex value = (BsonRegex)t;
+                    int size = 0;
+                    size += CalculateSize(value.Pattern);
+                    size += CalculateSize(value.Options);
+                    value.CalculatedSize = size;
+
+                    return value.CalculatedSize;
+                }
+                default:
+                    throw new ArgumentOutOfRangeException("t", "Unexpected token when writing BSON: {0}".FormatWith(CultureInfo.InvariantCulture, t.Type));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonObjectId.cs b/Newtonsoft.Json/Bson/BsonObjectId.cs
new file mode 100644
index 0000000..cb93f0b
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonObjectId.cs
@@ -0,0 +1,55 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Bson
+{
+    /// <summary>
+    /// Represents a BSON Oid (object id).
+    /// </summary>
+    public class BsonObjectId
+    {
+        /// <summary>
+        /// Gets or sets the value of the Oid.
+        /// </summary>
+        /// <value>The value of the Oid.</value>
+        public byte[] Value { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonObjectId"/> class.
+        /// </summary>
+        /// <param name="value">The Oid value.</param>
+        public BsonObjectId(byte[] value)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+            if (value.Length != 12)
+                throw new ArgumentException("An ObjectId must be 12 bytes", "value");
+
+            Value = value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonReader.cs b/Newtonsoft.Json/Bson/BsonReader.cs
new file mode 100644
index 0000000..5035f1e
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonReader.cs
@@ -0,0 +1,849 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using System.IO;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Bson
+{
+    /// <summary>
+    /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+    /// </summary>
+    public class BsonReader : JsonReader
+    {
+        private const int MaxCharBytesSize = 128;
+        private static readonly byte[] SeqRange1 = new byte[] { 0, 127 }; // range of 1-byte sequence
+        private static readonly byte[] SeqRange2 = new byte[] { 194, 223 }; // range of 2-byte sequence
+        private static readonly byte[] SeqRange3 = new byte[] { 224, 239 }; // range of 3-byte sequence
+        private static readonly byte[] SeqRange4 = new byte[] { 240, 244 }; // range of 4-byte sequence
+
+        private readonly BinaryReader _reader;
+        private readonly List<ContainerContext> _stack;
+
+        private byte[] _byteBuffer;
+        private char[] _charBuffer;
+
+        private BsonType _currentElementType;
+        private BsonReaderState _bsonReaderState;
+        private ContainerContext _currentContext;
+
+        private bool _readRootValueAsArray;
+        private bool _jsonNet35BinaryCompatibility;
+        private DateTimeKind _dateTimeKindHandling;
+
+        private enum BsonReaderState
+        {
+            Normal,
+            ReferenceStart,
+            ReferenceRef,
+            ReferenceId,
+            CodeWScopeStart,
+            CodeWScopeCode,
+            CodeWScopeScope,
+            CodeWScopeScopeObject,
+            CodeWScopeScopeEnd
+        }
+
+        private class ContainerContext
+        {
+            public readonly BsonType Type;
+            public int Length;
+            public int Position;
+
+            public ContainerContext(BsonType type)
+            {
+                Type = type;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether binary data reading should compatible with incorrect Json.NET 3.5 written binary.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, <c>false</c>.
+        /// </value>
+        [Obsolete("JsonNet35BinaryCompatibility will be removed in a future version of Json.NET.")]
+        public bool JsonNet35BinaryCompatibility
+        {
+            get { return _jsonNet35BinaryCompatibility; }
+            set { _jsonNet35BinaryCompatibility = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the root object will be read as a JSON array.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if the root object will be read as a JSON array; otherwise, <c>false</c>.
+        /// </value>
+        public bool ReadRootValueAsArray
+        {
+            get { return _readRootValueAsArray; }
+            set { _readRootValueAsArray = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.
+        /// </summary>
+        /// <value>The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</value>
+        public DateTimeKind DateTimeKindHandling
+        {
+            get { return _dateTimeKindHandling; }
+            set { _dateTimeKindHandling = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonReader"/> class.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        public BsonReader(Stream stream)
+            : this(stream, false, DateTimeKind.Local)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonReader"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        public BsonReader(BinaryReader reader)
+            : this(reader, false, DateTimeKind.Local)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonReader"/> class.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        /// <param name="readRootValueAsArray">if set to <c>true</c> the root object will be read as a JSON array.</param>
+        /// <param name="dateTimeKindHandling">The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</param>
+        public BsonReader(Stream stream, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
+        {
+            ValidationUtils.ArgumentNotNull(stream, "stream");
+            _reader = new BinaryReader(stream);
+            _stack = new List<ContainerContext>();
+            _readRootValueAsArray = readRootValueAsArray;
+            _dateTimeKindHandling = dateTimeKindHandling;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonReader"/> class.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        /// <param name="readRootValueAsArray">if set to <c>true</c> the root object will be read as a JSON array.</param>
+        /// <param name="dateTimeKindHandling">The <see cref="DateTimeKind" /> used when reading <see cref="DateTime"/> values from BSON.</param>
+        public BsonReader(BinaryReader reader, bool readRootValueAsArray, DateTimeKind dateTimeKindHandling)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+            _reader = reader;
+            _stack = new List<ContainerContext>();
+            _readRootValueAsArray = readRootValueAsArray;
+            _dateTimeKindHandling = dateTimeKindHandling;
+        }
+
+        private string ReadElement()
+        {
+            _currentElementType = ReadType();
+            string elementName = ReadString();
+            return elementName;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
+        /// </returns>
+        public override byte[] ReadAsBytes()
+        {
+            return ReadAsBytesInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override decimal? ReadAsDecimal()
+        {
+            return ReadAsDecimalInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override int? ReadAsInt32()
+        {
+            return ReadAsInt32Internal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="String"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override string ReadAsString()
+        {
+            return ReadAsStringInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTime? ReadAsDateTime()
+        {
+            return ReadAsDateTimeInternal();
+        }
+
+#if !NET20
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.
+        /// </returns>
+        public override DateTimeOffset? ReadAsDateTimeOffset()
+        {
+            return ReadAsDateTimeOffsetInternal();
+        }
+#endif
+
+        /// <summary>
+        /// Reads the next JSON token from the stream.
+        /// </summary>
+        /// <returns>
+        /// true if the next token was read successfully; false if there are no more tokens to read.
+        /// </returns>
+        public override bool Read()
+        {
+            _readType = Json.ReadType.Read;
+
+            return ReadInternal();
+        }
+
+        internal override bool ReadInternal()
+        {
+            try
+            {
+                bool success;
+
+                switch (_bsonReaderState)
+                {
+                    case BsonReaderState.Normal:
+                        success = ReadNormal();
+                        break;
+                    case BsonReaderState.ReferenceStart:
+                    case BsonReaderState.ReferenceRef:
+                    case BsonReaderState.ReferenceId:
+                        success = ReadReference();
+                        break;
+                    case BsonReaderState.CodeWScopeStart:
+                    case BsonReaderState.CodeWScopeCode:
+                    case BsonReaderState.CodeWScopeScope:
+                    case BsonReaderState.CodeWScopeScopeObject:
+                    case BsonReaderState.CodeWScopeScopeEnd:
+                        success = ReadCodeWScope();
+                        break;
+                    default:
+                        throw JsonReaderException.Create(this, "Unexpected state: {0}".FormatWith(CultureInfo.InvariantCulture, _bsonReaderState));
+                }
+
+                if (!success)
+                {
+                    SetToken(JsonToken.None);
+                    return false;
+                }
+
+                return true;
+            }
+            catch (EndOfStreamException)
+            {
+                SetToken(JsonToken.None);
+                return false;
+            }
+        }
+
+        /// <summary>
+        /// Changes the <see cref="JsonReader.State"/> to Closed.
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+
+            if (CloseInput && _reader != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                _reader.Close();
+#else
+                _reader.Dispose();
+#endif
+        }
+
+        private bool ReadCodeWScope()
+        {
+            switch (_bsonReaderState)
+            {
+                case BsonReaderState.CodeWScopeStart:
+                    SetToken(JsonToken.PropertyName, "$code");
+                    _bsonReaderState = BsonReaderState.CodeWScopeCode;
+                    return true;
+                case BsonReaderState.CodeWScopeCode:
+                    // total CodeWScope size - not used
+                    ReadInt32();
+
+                    SetToken(JsonToken.String, ReadLengthString());
+                    _bsonReaderState = BsonReaderState.CodeWScopeScope;
+                    return true;
+                case BsonReaderState.CodeWScopeScope:
+                    if (CurrentState == State.PostValue)
+                    {
+                        SetToken(JsonToken.PropertyName, "$scope");
+                        return true;
+                    }
+                    else
+                    {
+                        SetToken(JsonToken.StartObject);
+                        _bsonReaderState = BsonReaderState.CodeWScopeScopeObject;
+
+                        ContainerContext newContext = new ContainerContext(BsonType.Object);
+                        PushContext(newContext);
+                        newContext.Length = ReadInt32();
+
+                        return true;
+                    }
+                case BsonReaderState.CodeWScopeScopeObject:
+                    bool result = ReadNormal();
+                    if (result && TokenType == JsonToken.EndObject)
+                        _bsonReaderState = BsonReaderState.CodeWScopeScopeEnd;
+
+                    return result;
+                case BsonReaderState.CodeWScopeScopeEnd:
+                    SetToken(JsonToken.EndObject);
+                    _bsonReaderState = BsonReaderState.Normal;
+                    return true;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        private bool ReadReference()
+        {
+            switch (CurrentState)
+            {
+                case State.ObjectStart:
+                {
+                    SetToken(JsonToken.PropertyName, JsonTypeReflector.RefPropertyName);
+                    _bsonReaderState = BsonReaderState.ReferenceRef;
+                    return true;
+                }
+                case State.Property:
+                {
+                    if (_bsonReaderState == BsonReaderState.ReferenceRef)
+                    {
+                        SetToken(JsonToken.String, ReadLengthString());
+                        return true;
+                    }
+                    else if (_bsonReaderState == BsonReaderState.ReferenceId)
+                    {
+                        SetToken(JsonToken.Bytes, ReadBytes(12));
+                        return true;
+                    }
+                    else
+                    {
+                        throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
+                    }
+                }
+                case State.PostValue:
+                {
+                    if (_bsonReaderState == BsonReaderState.ReferenceRef)
+                    {
+                        SetToken(JsonToken.PropertyName, JsonTypeReflector.IdPropertyName);
+                        _bsonReaderState = BsonReaderState.ReferenceId;
+                        return true;
+                    }
+                    else if (_bsonReaderState == BsonReaderState.ReferenceId)
+                    {
+                        SetToken(JsonToken.EndObject);
+                        _bsonReaderState = BsonReaderState.Normal;
+                        return true;
+                    }
+                    else
+                    {
+                        throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + _bsonReaderState);
+                    }
+                }
+                default:
+                    throw JsonReaderException.Create(this, "Unexpected state when reading BSON reference: " + CurrentState);
+            }
+        }
+
+        private bool ReadNormal()
+        {
+            switch (CurrentState)
+            {
+                case State.Start:
+                {
+                    JsonToken token = (!_readRootValueAsArray) ? JsonToken.StartObject : JsonToken.StartArray;
+                    BsonType type = (!_readRootValueAsArray) ? BsonType.Object : BsonType.Array;
+
+                    SetToken(token);
+                    ContainerContext newContext = new ContainerContext(type);
+                    PushContext(newContext);
+                    newContext.Length = ReadInt32();
+                    return true;
+                }
+                case State.Complete:
+                case State.Closed:
+                    return false;
+                case State.Property:
+                {
+                    ReadType(_currentElementType);
+                    return true;
+                }
+                case State.ObjectStart:
+                case State.ArrayStart:
+                case State.PostValue:
+                    ContainerContext context = _currentContext;
+                    if (context == null)
+                        return false;
+
+                    int lengthMinusEnd = context.Length - 1;
+
+                    if (context.Position < lengthMinusEnd)
+                    {
+                        if (context.Type == BsonType.Array)
+                        {
+                            ReadElement();
+                            ReadType(_currentElementType);
+                            return true;
+                        }
+                        else
+                        {
+                            SetToken(JsonToken.PropertyName, ReadElement());
+                            return true;
+                        }
+                    }
+                    else if (context.Position == lengthMinusEnd)
+                    {
+                        if (ReadByte() != 0)
+                            throw JsonReaderException.Create(this, "Unexpected end of object byte value.");
+
+                        PopContext();
+                        if (_currentContext != null)
+                            MovePosition(context.Length);
+
+                        JsonToken endToken = (context.Type == BsonType.Object) ? JsonToken.EndObject : JsonToken.EndArray;
+                        SetToken(endToken);
+                        return true;
+                    }
+                    else
+                    {
+                        throw JsonReaderException.Create(this, "Read past end of current container context.");
+                    }
+                case State.ConstructorStart:
+                    break;
+                case State.Constructor:
+                    break;
+                case State.Error:
+                    break;
+                case State.Finished:
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+
+            return false;
+        }
+
+        private void PopContext()
+        {
+            _stack.RemoveAt(_stack.Count - 1);
+            if (_stack.Count == 0)
+                _currentContext = null;
+            else
+                _currentContext = _stack[_stack.Count - 1];
+        }
+
+        private void PushContext(ContainerContext newContext)
+        {
+            _stack.Add(newContext);
+            _currentContext = newContext;
+        }
+
+        private byte ReadByte()
+        {
+            MovePosition(1);
+            return _reader.ReadByte();
+        }
+
+        private void ReadType(BsonType type)
+        {
+            switch (type)
+            {
+                case BsonType.Number:
+                    double d = ReadDouble();
+
+                    if (_floatParseHandling == FloatParseHandling.Decimal)
+                        SetToken(JsonToken.Float, Convert.ToDecimal(d, CultureInfo.InvariantCulture));
+                    else
+                        SetToken(JsonToken.Float, d);
+                    break;
+                case BsonType.String:
+                case BsonType.Symbol:
+                    SetToken(JsonToken.String, ReadLengthString());
+                    break;
+                case BsonType.Object:
+                {
+                    SetToken(JsonToken.StartObject);
+
+                    ContainerContext newContext = new ContainerContext(BsonType.Object);
+                    PushContext(newContext);
+                    newContext.Length = ReadInt32();
+                    break;
+                }
+                case BsonType.Array:
+                {
+                    SetToken(JsonToken.StartArray);
+
+                    ContainerContext newContext = new ContainerContext(BsonType.Array);
+                    PushContext(newContext);
+                    newContext.Length = ReadInt32();
+                    break;
+                }
+                case BsonType.Binary:
+                    SetToken(JsonToken.Bytes, ReadBinary());
+                    break;
+                case BsonType.Undefined:
+                    SetToken(JsonToken.Undefined);
+                    break;
+                case BsonType.Oid:
+                    byte[] oid = ReadBytes(12);
+                    SetToken(JsonToken.Bytes, oid);
+                    break;
+                case BsonType.Boolean:
+                    bool b = Convert.ToBoolean(ReadByte());
+                    SetToken(JsonToken.Boolean, b);
+                    break;
+                case BsonType.Date:
+                    long ticks = ReadInt64();
+                    DateTime utcDateTime = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+                    DateTime dateTime;
+                    switch (DateTimeKindHandling)
+                    {
+                        case DateTimeKind.Unspecified:
+                            dateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Unspecified);
+                            break;
+                        case DateTimeKind.Local:
+                            dateTime = utcDateTime.ToLocalTime();
+                            break;
+                        default:
+                            dateTime = utcDateTime;
+                            break;
+                    }
+
+                    SetToken(JsonToken.Date, dateTime);
+                    break;
+                case BsonType.Null:
+                    SetToken(JsonToken.Null);
+                    break;
+                case BsonType.Regex:
+                    string expression = ReadString();
+                    string modifiers = ReadString();
+
+                    string regex = @"/" + expression + @"/" + modifiers;
+                    SetToken(JsonToken.String, regex);
+                    break;
+                case BsonType.Reference:
+                    SetToken(JsonToken.StartObject);
+                    _bsonReaderState = BsonReaderState.ReferenceStart;
+                    break;
+                case BsonType.Code:
+                    SetToken(JsonToken.String, ReadLengthString());
+                    break;
+                case BsonType.CodeWScope:
+                    SetToken(JsonToken.StartObject);
+                    _bsonReaderState = BsonReaderState.CodeWScopeStart;
+                    break;
+                case BsonType.Integer:
+                    SetToken(JsonToken.Integer, (long)ReadInt32());
+                    break;
+                case BsonType.TimeStamp:
+                case BsonType.Long:
+                    SetToken(JsonToken.Integer, ReadInt64());
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException("type", "Unexpected BsonType value: " + type);
+            }
+        }
+
+        private byte[] ReadBinary()
+        {
+            int dataLength = ReadInt32();
+
+            BsonBinaryType binaryType = (BsonBinaryType)ReadByte();
+
+#pragma warning disable 612,618
+            // the old binary type has the data length repeated in the data for some reason
+            if (binaryType == BsonBinaryType.BinaryOld && !_jsonNet35BinaryCompatibility)
+            {
+                dataLength = ReadInt32();
+            }
+#pragma warning restore 612,618
+
+            return ReadBytes(dataLength);
+        }
+
+        private string ReadString()
+        {
+            EnsureBuffers();
+
+            StringBuilder builder = null;
+
+            int totalBytesRead = 0;
+            // used in case of left over multibyte characters in the buffer
+            int offset = 0;
+            do
+            {
+                int count = offset;
+                byte b;
+                while (count < MaxCharBytesSize && (b = _reader.ReadByte()) > 0)
+                {
+                    _byteBuffer[count++] = b;
+                }
+                int byteCount = count - offset;
+                totalBytesRead += byteCount;
+
+                if (count < MaxCharBytesSize && builder == null)
+                {
+                    // pref optimization to avoid reading into a string builder
+                    // if string is smaller than the buffer then return it directly
+                    int length = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
+
+                    MovePosition(totalBytesRead + 1);
+                    return new string(_charBuffer, 0, length);
+                }
+                else
+                {
+                    // calculate the index of the end of the last full character in the buffer
+                    int lastFullCharStop = GetLastFullCharStop(count - 1);
+
+                    int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
+
+                    if (builder == null)
+                        builder = new StringBuilder(MaxCharBytesSize * 2);
+
+                    builder.Append(_charBuffer, 0, charCount);
+
+                    if (lastFullCharStop < byteCount - 1)
+                    {
+                        offset = byteCount - lastFullCharStop - 1;
+                        // copy left over multi byte characters to beginning of buffer for next iteration
+                        Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
+                    }
+                    else
+                    {
+                        // reached end of string
+                        if (count < MaxCharBytesSize)
+                        {
+                            MovePosition(totalBytesRead + 1);
+                            return builder.ToString();
+                        }
+
+                        offset = 0;
+                    }
+                }
+            } while (true);
+        }
+
+        private string ReadLengthString()
+        {
+            int length = ReadInt32();
+
+            MovePosition(length);
+
+            string s = GetString(length - 1);
+            _reader.ReadByte();
+
+            return s;
+        }
+
+        private string GetString(int length)
+        {
+            if (length == 0)
+                return string.Empty;
+
+            EnsureBuffers();
+
+            StringBuilder builder = null;
+
+            int totalBytesRead = 0;
+
+            // used in case of left over multibyte characters in the buffer
+            int offset = 0;
+            do
+            {
+                int count = ((length - totalBytesRead) > MaxCharBytesSize - offset)
+                    ? MaxCharBytesSize - offset
+                    : length - totalBytesRead;
+
+                int byteCount = _reader.Read(_byteBuffer, offset, count);
+
+                if (byteCount == 0)
+                    throw new EndOfStreamException("Unable to read beyond the end of the stream.");
+
+                totalBytesRead += byteCount;
+
+                // Above, byteCount is how many bytes we read this time.
+                // Below, byteCount is how many bytes are in the _byteBuffer.
+                byteCount += offset;
+
+                if (byteCount == length)
+                {
+                    // pref optimization to avoid reading into a string builder
+                    // first iteration and all bytes read then return string directly
+                    int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, byteCount, _charBuffer, 0);
+                    return new string(_charBuffer, 0, charCount);
+                }
+                else
+                {
+                    int lastFullCharStop = GetLastFullCharStop(byteCount - 1);
+
+                    if (builder == null)
+                        builder = new StringBuilder(length);
+
+                    int charCount = Encoding.UTF8.GetChars(_byteBuffer, 0, lastFullCharStop + 1, _charBuffer, 0);
+                    builder.Append(_charBuffer, 0, charCount);
+
+                    if (lastFullCharStop < byteCount - 1)
+                    {
+                        offset = byteCount - lastFullCharStop - 1;
+                        // copy left over multi byte characters to beginning of buffer for next iteration
+                        Array.Copy(_byteBuffer, lastFullCharStop + 1, _byteBuffer, 0, offset);
+                    }
+                    else
+                    {
+                        offset = 0;
+                    }
+                }
+            } while (totalBytesRead < length);
+
+            return builder.ToString();
+        }
+
+        private int GetLastFullCharStop(int start)
+        {
+            int lookbackPos = start;
+            int bis = 0;
+            while (lookbackPos >= 0)
+            {
+                bis = BytesInSequence(_byteBuffer[lookbackPos]);
+                if (bis == 0)
+                {
+                    lookbackPos--;
+                    continue;
+                }
+                else if (bis == 1)
+                {
+                    break;
+                }
+                else
+                {
+                    lookbackPos--;
+                    break;
+                }
+            }
+            if (bis == start - lookbackPos)
+            {
+                //Full character.
+                return start;
+            }
+            else
+            {
+                return lookbackPos;
+            }
+        }
+
+        private int BytesInSequence(byte b)
+        {
+            if (b <= SeqRange1[1]) return 1;
+            if (b >= SeqRange2[0] && b <= SeqRange2[1]) return 2;
+            if (b >= SeqRange3[0] && b <= SeqRange3[1]) return 3;
+            if (b >= SeqRange4[0] && b <= SeqRange4[1]) return 4;
+            return 0;
+        }
+
+        private void EnsureBuffers()
+        {
+            if (_byteBuffer == null)
+            {
+                _byteBuffer = new byte[MaxCharBytesSize];
+            }
+            if (_charBuffer == null)
+            {
+                int charBufferSize = Encoding.UTF8.GetMaxCharCount(MaxCharBytesSize);
+                _charBuffer = new char[charBufferSize];
+            }
+        }
+
+        private double ReadDouble()
+        {
+            MovePosition(8);
+            return _reader.ReadDouble();
+        }
+
+        private int ReadInt32()
+        {
+            MovePosition(4);
+            return _reader.ReadInt32();
+        }
+
+        private long ReadInt64()
+        {
+            MovePosition(8);
+            return _reader.ReadInt64();
+        }
+
+        private BsonType ReadType()
+        {
+            MovePosition(1);
+            return (BsonType)_reader.ReadSByte();
+        }
+
+        private void MovePosition(int count)
+        {
+            _currentContext.Position += count;
+        }
+
+        private byte[] ReadBytes(int count)
+        {
+            MovePosition(count);
+            return _reader.ReadBytes(count);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonToken.cs b/Newtonsoft.Json/Bson/BsonToken.cs
new file mode 100644
index 0000000..7bc2f13
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonToken.cs
@@ -0,0 +1,157 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Bson
+{
+    internal abstract class BsonToken
+    {
+        public abstract BsonType Type { get; }
+        public BsonToken Parent { get; set; }
+        public int CalculatedSize { get; set; }
+    }
+
+    internal class BsonObject : BsonToken, IEnumerable<BsonProperty>
+    {
+        private readonly List<BsonProperty> _children = new List<BsonProperty>();
+
+        public void Add(string name, BsonToken token)
+        {
+            _children.Add(new BsonProperty { Name = new BsonString(name, false), Value = token });
+            token.Parent = this;
+        }
+
+        public override BsonType Type
+        {
+            get { return BsonType.Object; }
+        }
+
+        public IEnumerator<BsonProperty> GetEnumerator()
+        {
+            return _children.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+
+    internal class BsonArray : BsonToken, IEnumerable<BsonToken>
+    {
+        private readonly List<BsonToken> _children = new List<BsonToken>();
+
+        public void Add(BsonToken token)
+        {
+            _children.Add(token);
+            token.Parent = this;
+        }
+
+        public override BsonType Type
+        {
+            get { return BsonType.Array; }
+        }
+
+        public IEnumerator<BsonToken> GetEnumerator()
+        {
+            return _children.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+    }
+
+    internal class BsonValue : BsonToken
+    {
+        private readonly object _value;
+        private readonly BsonType _type;
+
+        public BsonValue(object value, BsonType type)
+        {
+            _value = value;
+            _type = type;
+        }
+
+        public object Value
+        {
+            get { return _value; }
+        }
+
+        public override BsonType Type
+        {
+            get { return _type; }
+        }
+    }
+
+    internal class BsonString : BsonValue
+    {
+        public int ByteCount { get; set; }
+        public bool IncludeLength { get; set; }
+
+        public BsonString(object value, bool includeLength)
+            : base(value, BsonType.String)
+        {
+            IncludeLength = includeLength;
+        }
+    }
+
+    internal class BsonBinary : BsonValue
+    {
+        public BsonBinaryType BinaryType { get; set; }
+
+        public BsonBinary(byte[] value, BsonBinaryType binaryType)
+            : base(value, BsonType.Binary)
+        {
+            BinaryType = binaryType;
+        }
+    }
+
+    internal class BsonRegex : BsonToken
+    {
+        public BsonString Pattern { get; set; }
+        public BsonString Options { get; set; }
+
+        public BsonRegex(string pattern, string options)
+        {
+            Pattern = new BsonString(pattern, false);
+            Options = new BsonString(options, false);
+        }
+
+        public override BsonType Type
+        {
+            get { return BsonType.Regex; }
+        }
+    }
+
+    internal class BsonProperty
+    {
+        public BsonString Name { get; set; }
+        public BsonToken Value { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonType.cs b/Newtonsoft.Json/Bson/BsonType.cs
new file mode 100644
index 0000000..7ff76fe
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonType.cs
@@ -0,0 +1,51 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Bson
+{
+    internal enum BsonType : sbyte
+    {
+        Number = 1,
+        String = 2,
+        Object = 3,
+        Array = 4,
+        Binary = 5,
+        Undefined = 6,
+        Oid = 7,
+        Boolean = 8,
+        Date = 9,
+        Null = 10,
+        Regex = 11,
+        Reference = 12,
+        Code = 13,
+        Symbol = 14,
+        CodeWScope = 15,
+        Integer = 16,
+        TimeStamp = 17,
+        Long = 18,
+        MinKey = -1,
+        MaxKey = 127
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Bson/BsonWriter.cs b/Newtonsoft.Json/Bson/BsonWriter.cs
new file mode 100644
index 0000000..3f8ae0d
--- /dev/null
+++ b/Newtonsoft.Json/Bson/BsonWriter.cs
@@ -0,0 +1,517 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Bson
+{
+    /// <summary>
+    /// Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data.
+    /// </summary>
+    public class BsonWriter : JsonWriter
+    {
+        private readonly BsonBinaryWriter _writer;
+
+        private BsonToken _root;
+        private BsonToken _parent;
+        private string _propertyName;
+
+        /// <summary>
+        /// Gets or sets the <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.
+        /// When set to <see cref="DateTimeKind.Unspecified" /> no conversion will occur.
+        /// </summary>
+        /// <value>The <see cref="DateTimeKind" /> used when writing <see cref="DateTime"/> values to BSON.</value>
+        public DateTimeKind DateTimeKindHandling
+        {
+            get { return _writer.DateTimeKindHandling; }
+            set { _writer.DateTimeKindHandling = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonWriter"/> class.
+        /// </summary>
+        /// <param name="stream">The stream.</param>
+        public BsonWriter(Stream stream)
+        {
+            ValidationUtils.ArgumentNotNull(stream, "stream");
+            _writer = new BsonBinaryWriter(new BinaryWriter(stream));
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BsonWriter"/> class.
+        /// </summary>
+        /// <param name="writer">The writer.</param>
+        public BsonWriter(BinaryWriter writer)
+        {
+            ValidationUtils.ArgumentNotNull(writer, "writer");
+            _writer = new BsonBinaryWriter(writer);
+        }
+
+        /// <summary>
+        /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+        /// </summary>
+        public override void Flush()
+        {
+            _writer.Flush();
+        }
+
+        /// <summary>
+        /// Writes the end.
+        /// </summary>
+        /// <param name="token">The token.</param>
+        protected override void WriteEnd(JsonToken token)
+        {
+            base.WriteEnd(token);
+            RemoveParent();
+
+            if (Top == 0)
+            {
+                _writer.WriteToken(_root);
+            }
+        }
+
+        /// <summary>
+        /// Writes out a comment <code>/*...*/</code> containing the specified text.
+        /// </summary>
+        /// <param name="text">Text to place inside the comment.</param>
+        public override void WriteComment(string text)
+        {
+            throw JsonWriterException.Create(this, "Cannot write JSON comment as BSON.", null);
+        }
+
+        /// <summary>
+        /// Writes the start of a constructor with the given name.
+        /// </summary>
+        /// <param name="name">The name of the constructor.</param>
+        public override void WriteStartConstructor(string name)
+        {
+            throw JsonWriterException.Create(this, "Cannot write JSON constructor as BSON.", null);
+        }
+
+        /// <summary>
+        /// Writes raw JSON.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public override void WriteRaw(string json)
+        {
+            throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
+        }
+
+        /// <summary>
+        /// Writes raw JSON where a value is expected and updates the writer's state.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public override void WriteRawValue(string json)
+        {
+            throw JsonWriterException.Create(this, "Cannot write raw JSON as BSON.", null);
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json array.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            base.WriteStartArray();
+
+            AddParent(new BsonArray());
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json object.
+        /// </summary>
+        public override void WriteStartObject()
+        {
+            base.WriteStartObject();
+
+            AddParent(new BsonObject());
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a Json object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        public override void WritePropertyName(string name)
+        {
+            base.WritePropertyName(name);
+
+            _propertyName = name;
+        }
+
+        /// <summary>
+        /// Closes this stream and the underlying stream.
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+
+            if (CloseOutput && _writer != null)
+                _writer.Close();
+        }
+
+        private void AddParent(BsonToken container)
+        {
+            AddToken(container);
+            _parent = container;
+        }
+
+        private void RemoveParent()
+        {
+            _parent = _parent.Parent;
+        }
+
+        private void AddValue(object value, BsonType type)
+        {
+            AddToken(new BsonValue(value, type));
+        }
+
+        internal void AddToken(BsonToken token)
+        {
+            if (_parent != null)
+            {
+                if (_parent is BsonObject)
+                {
+                    ((BsonObject)_parent).Add(_propertyName, token);
+                    _propertyName = null;
+                }
+                else
+                {
+                    ((BsonArray)_parent).Add(token);
+                }
+            }
+            else
+            {
+                if (token.Type != BsonType.Object && token.Type != BsonType.Array)
+                    throw JsonWriterException.Create(this, "Error writing {0} value. BSON must start with an Object or Array.".FormatWith(CultureInfo.InvariantCulture, token.Type), null);
+
+                _parent = token;
+                _root = token;
+            }
+        }
+
+        #region WriteValue methods
+        /// <summary>
+        /// Writes a <see cref="Object"/> value.
+        /// An error will raised if the value cannot be written as a single JSON token.
+        /// </summary>
+        /// <param name="value">The <see cref="Object"/> value to write.</param>
+        public override void WriteValue(object value)
+        {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+            if (value is BigInteger)
+            {
+                InternalWriteValue(JsonToken.Integer);
+                AddToken(new BsonBinary(((BigInteger)value).ToByteArray(), BsonBinaryType.Binary));
+            }
+            else
+#endif
+            {
+                base.WriteValue(value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a null value.
+        /// </summary>
+        public override void WriteNull()
+        {
+            base.WriteNull();
+            AddValue(null, BsonType.Null);
+        }
+
+        /// <summary>
+        /// Writes an undefined value.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            base.WriteUndefined();
+            AddValue(null, BsonType.Undefined);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="String"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="String"/> value to write.</param>
+        public override void WriteValue(string value)
+        {
+            base.WriteValue(value);
+            if (value == null)
+                AddValue(null, BsonType.Null);
+            else
+                AddToken(new BsonString(value, true));
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int32"/> value to write.</param>
+        public override void WriteValue(int value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt32"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(uint value)
+        {
+            if (value > int.MaxValue)
+                throw JsonWriterException.Create(this, "Value is too large to fit in a signed 32 bit integer. BSON does not support unsigned values.", null);
+
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int64"/> value to write.</param>
+        public override void WriteValue(long value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Long);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt64"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ulong value)
+        {
+            if (value > long.MaxValue)
+                throw JsonWriterException.Create(this, "Value is too large to fit in a signed 64 bit integer. BSON does not support unsigned values.", null);
+
+            base.WriteValue(value);
+            AddValue(value, BsonType.Long);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Single"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Single"/> value to write.</param>
+        public override void WriteValue(float value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Number);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Double"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Double"/> value to write.</param>
+        public override void WriteValue(double value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Number);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Boolean"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Boolean"/> value to write.</param>
+        public override void WriteValue(bool value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Boolean);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int16"/> value to write.</param>
+        public override void WriteValue(short value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt16"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ushort value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Char"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Char"/> value to write.</param>
+        public override void WriteValue(char value)
+        {
+            base.WriteValue(value);
+            string s = null;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            s = value.ToString(CultureInfo.InvariantCulture);
+#else
+            s = value.ToString();
+#endif
+            AddToken(new BsonString(s, true));
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Byte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Byte"/> value to write.</param>
+        public override void WriteValue(byte value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="SByte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="SByte"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(sbyte value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Decimal"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Decimal"/> value to write.</param>
+        public override void WriteValue(decimal value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Number);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="DateTime"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTime"/> value to write.</param>
+        public override void WriteValue(DateTime value)
+        {
+            base.WriteValue(value);
+            value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
+            AddValue(value, BsonType.Date);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Writes a <see cref="DateTimeOffset"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
+        public override void WriteValue(DateTimeOffset value)
+        {
+            base.WriteValue(value);
+            AddValue(value, BsonType.Date);
+        }
+#endif
+
+        /// <summary>
+        /// Writes a <see cref="T:Byte[]"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
+        public override void WriteValue(byte[] value)
+        {
+            base.WriteValue(value);
+            AddToken(new BsonBinary(value, BsonBinaryType.Binary));
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Guid"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Guid"/> value to write.</param>
+        public override void WriteValue(Guid value)
+        {
+            base.WriteValue(value);
+            AddToken(new BsonBinary(value.ToByteArray(), BsonBinaryType.Uuid));
+        }
+
+        /// <summary>
+        /// Writes a <see cref="TimeSpan"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
+        public override void WriteValue(TimeSpan value)
+        {
+            base.WriteValue(value);
+            AddToken(new BsonString(value.ToString(), true));
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Uri"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Uri"/> value to write.</param>
+        public override void WriteValue(Uri value)
+        {
+            base.WriteValue(value);
+            AddToken(new BsonString(value.ToString(), true));
+        }
+        #endregion
+
+        /// <summary>
+        /// Writes a <see cref="T:Byte[]"/> value that represents a BSON object id.
+        /// </summary>
+        /// <param name="value">The Object ID value to write.</param>
+        public void WriteObjectId(byte[] value)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+
+            if (value.Length != 12)
+                throw JsonWriterException.Create(this, "An object id must be 12 bytes", null);
+
+            // hack to update the writer state
+            UpdateScopeWithFinishedValue();
+            AutoComplete(JsonToken.Undefined);
+            AddValue(value, BsonType.Oid);
+        }
+
+        /// <summary>
+        /// Writes a BSON regex.
+        /// </summary>
+        /// <param name="pattern">The regex pattern.</param>
+        /// <param name="options">The regex options.</param>
+        public void WriteRegex(string pattern, string options)
+        {
+            ValidationUtils.ArgumentNotNull(pattern, "pattern");
+
+            // hack to update the writer state
+            UpdateScopeWithFinishedValue();
+            AutoComplete(JsonToken.Undefined);
+            AddToken(new BsonRegex(pattern, options));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/ConstructorHandling.cs b/Newtonsoft.Json/ConstructorHandling.cs
new file mode 100644
index 0000000..007bc60
--- /dev/null
+++ b/Newtonsoft.Json/ConstructorHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how constructors are used when initializing objects during deserialization by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum ConstructorHandling
+    {
+        /// <summary>
+        /// First attempt to use the public default constructor, then fall back to single paramatized constructor, then the non-public default constructor.
+        /// </summary>
+        Default = 0,
+
+        /// <summary>
+        /// Json.NET will use a non-public default constructor before falling back to a paramatized constructor.
+        /// </summary>
+        AllowNonPublicDefaultConstructor = 1
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/BinaryConverter.cs b/Newtonsoft.Json/Converters/BinaryConverter.cs
new file mode 100644
index 0000000..2988705
--- /dev/null
+++ b/Newtonsoft.Json/Converters/BinaryConverter.cs
@@ -0,0 +1,183 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data.SqlTypes;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Converters
+{
+#if !NET20
+    internal interface IBinary
+    {
+        byte[] ToArray();
+    }
+#endif
+
+    /// <summary>
+    /// Converts a binary value to and from a base 64 string value.
+    /// </summary>
+    public class BinaryConverter : JsonConverter
+    {
+#if !NET20
+        private const string BinaryTypeName = "System.Data.Linq.Binary";
+#endif
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            if (value == null)
+            {
+                writer.WriteNull();
+                return;
+            }
+
+            byte[] data = GetByteArray(value);
+
+            writer.WriteValue(data);
+        }
+
+        private byte[] GetByteArray(object value)
+        {
+#if !(NET20)
+            if (value.GetType().AssignableToTypeName(BinaryTypeName))
+            {
+                IBinary binary = DynamicWrapper.CreateWrapper<IBinary>(value);
+                return binary.ToArray();
+            }
+#endif
+            if (value is SqlBinary)
+                return ((SqlBinary)value).Value;
+
+            throw new JsonSerializationException("Unexpected value type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            Type t = (ReflectionUtils.IsNullableType(objectType))
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            if (reader.TokenType == JsonToken.Null)
+            {
+                if (!ReflectionUtils.IsNullable(objectType))
+                    throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+                return null;
+            }
+
+            byte[] data;
+
+            if (reader.TokenType == JsonToken.StartArray)
+            {
+                data = ReadByteArray(reader);
+            }
+            else if (reader.TokenType == JsonToken.String)
+            {
+                // current token is already at base64 string
+                // unable to call ReadAsBytes so do it the old fashion way
+                string encodedData = reader.Value.ToString();
+                data = Convert.FromBase64String(encodedData);
+            }
+            else
+            {
+                throw JsonSerializationException.Create(reader, "Unexpected token parsing binary. Expected String or StartArray, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+
+
+#if !NET20
+            if (t.AssignableToTypeName(BinaryTypeName))
+                return Activator.CreateInstance(t, data);
+#endif
+
+            if (t == typeof(SqlBinary))
+                return new SqlBinary(data);
+
+            throw JsonSerializationException.Create(reader, "Unexpected object type when writing binary: {0}".FormatWith(CultureInfo.InvariantCulture, objectType));
+        }
+
+        private byte[] ReadByteArray(JsonReader reader)
+        {
+            List<byte> byteList = new List<byte>();
+
+            while (reader.Read())
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.Integer:
+                        byteList.Add(Convert.ToByte(reader.Value, CultureInfo.InvariantCulture));
+                        break;
+                    case JsonToken.EndArray:
+                        return byteList.ToArray();
+                    case JsonToken.Comment:
+                        // skip
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when reading bytes: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+                }
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end when reading bytes.");
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+#if !NET20
+            if (objectType.AssignableToTypeName(BinaryTypeName))
+                return true;
+#endif
+
+            if (objectType == typeof(SqlBinary) || objectType == typeof(SqlBinary?))
+                return true;
+
+            return false;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs b/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs
new file mode 100644
index 0000000..7fe2b76
--- /dev/null
+++ b/Newtonsoft.Json/Converters/BsonObjectIdConverter.cs
@@ -0,0 +1,89 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Bson;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="BsonObjectId"/> to and from JSON and BSON.
+    /// </summary>
+    public class BsonObjectIdConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            BsonObjectId objectId = (BsonObjectId)value;
+
+            BsonWriter bsonWriter = writer as BsonWriter;
+            if (bsonWriter != null)
+            {
+                bsonWriter.WriteObjectId(objectId.Value);
+            }
+            else
+            {
+                writer.WriteValue(objectId.Value);
+            }
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType != JsonToken.Bytes)
+                throw new JsonSerializationException("Expected Bytes but got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            byte[] value = (byte[])reader.Value;
+
+            return new BsonObjectId(value);
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return (objectType == typeof(BsonObjectId));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/CustomCreationConverter.cs b/Newtonsoft.Json/Converters/CustomCreationConverter.cs
new file mode 100644
index 0000000..b79e211
--- /dev/null
+++ b/Newtonsoft.Json/Converters/CustomCreationConverter.cs
@@ -0,0 +1,99 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Create a custom object
+    /// </summary>
+    /// <typeparam name="T">The object type to convert.</typeparam>
+    public abstract class CustomCreationConverter<T> : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            throw new NotSupportedException("CustomCreationConverter should only be used while deserializing.");
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.Null)
+                return null;
+
+            T value = Create(objectType);
+            if (value == null)
+                throw new JsonSerializationException("No object created.");
+
+            serializer.Populate(reader, value);
+            return value;
+        }
+
+        /// <summary>
+        /// Creates an object which will then be populated by the serializer.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>The created object.</returns>
+        public abstract T Create(Type objectType);
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return typeof(T).IsAssignableFrom(objectType);
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
+        /// </value>
+        public override bool CanWrite
+        {
+            get { return false; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/DataSetConverter.cs b/Newtonsoft.Json/Converters/DataSetConverter.cs
new file mode 100644
index 0000000..28183bb
--- /dev/null
+++ b/Newtonsoft.Json/Converters/DataSetConverter.cs
@@ -0,0 +1,112 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="DataSet"/> to and from JSON.
+    /// </summary>
+    public class DataSetConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            DataSet dataSet = (DataSet)value;
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            DataTableConverter converter = new DataTableConverter();
+
+            writer.WriteStartObject();
+
+            foreach (DataTable table in dataSet.Tables)
+            {
+                writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(table.TableName) : table.TableName);
+
+                converter.WriteJson(writer, table, serializer);
+            }
+
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            // handle typed datasets
+            DataSet ds = (objectType == typeof(DataSet))
+                ? new DataSet()
+                : (DataSet)Activator.CreateInstance(objectType);
+
+            DataTableConverter converter = new DataTableConverter();
+
+            reader.Read();
+
+            while (reader.TokenType == JsonToken.PropertyName)
+            {
+                DataTable dt = ds.Tables[(string)reader.Value];
+                bool exists = (dt != null);
+
+                dt = (DataTable)converter.ReadJson(reader, typeof(DataTable), dt, serializer);
+
+                if (!exists)
+                    ds.Tables.Add(dt);
+
+                reader.Read();
+            }
+
+            return ds;
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified value type.
+        /// </summary>
+        /// <param name="valueType">Type of the value.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type valueType)
+        {
+            return typeof(DataSet).IsAssignableFrom(valueType);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/DataTableConverter.cs b/Newtonsoft.Json/Converters/DataTableConverter.cs
new file mode 100644
index 0000000..89e474d
--- /dev/null
+++ b/Newtonsoft.Json/Converters/DataTableConverter.cs
@@ -0,0 +1,220 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Data;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="DataTable"/> to and from JSON.
+    /// </summary>
+    public class DataTableConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            DataTable table = (DataTable)value;
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            writer.WriteStartArray();
+
+            foreach (DataRow row in table.Rows)
+            {
+                writer.WriteStartObject();
+                foreach (DataColumn column in row.Table.Columns)
+                {
+                    if (serializer.NullValueHandling == NullValueHandling.Ignore && (row[column] == null || row[column] == DBNull.Value))
+                        continue;
+
+                    writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(column.ColumnName) : column.ColumnName);
+                    serializer.Serialize(writer, row[column]);
+                }
+                writer.WriteEndObject();
+            }
+
+            writer.WriteEndArray();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            DataTable dt = existingValue as DataTable;
+
+            if (dt == null)
+            {
+                // handle typed datasets
+                dt = (objectType == typeof(DataTable))
+                    ? new DataTable()
+                    : (DataTable)Activator.CreateInstance(objectType);
+            }
+
+            if (reader.TokenType == JsonToken.PropertyName)
+            {
+                dt.TableName = (string)reader.Value;
+
+                reader.Read();
+            }
+
+            if (reader.TokenType == JsonToken.StartArray)
+                reader.Read();
+
+            while (reader.TokenType != JsonToken.EndArray)
+            {
+                CreateRow(reader, dt);
+
+                reader.Read();
+            }
+
+            return dt;
+        }
+
+        private static void CreateRow(JsonReader reader, DataTable dt)
+        {
+            DataRow dr = dt.NewRow();
+            reader.Read();
+
+            while (reader.TokenType == JsonToken.PropertyName)
+            {
+                string columnName = (string)reader.Value;
+
+                reader.Read();
+
+                DataColumn column = dt.Columns[columnName];
+                if (column == null)
+                {
+                    Type columnType = GetColumnDataType(reader);
+                    column = new DataColumn(columnName, columnType);
+                    dt.Columns.Add(column);
+                }
+
+                if (column.DataType == typeof(DataTable))
+                {
+                    if (reader.TokenType == JsonToken.StartArray)
+                        reader.Read();
+
+                    DataTable nestedDt = new DataTable();
+
+                    while (reader.TokenType != JsonToken.EndArray)
+                    {
+                        CreateRow(reader, nestedDt);
+
+                        reader.Read();
+                    }
+
+                    dr[columnName] = nestedDt;
+                }
+                else if (column.DataType.IsArray)
+                {
+                    if (reader.TokenType == JsonToken.StartArray)
+                        reader.Read();
+
+                    List<object> o = new List<object>();
+
+                    while (reader.TokenType != JsonToken.EndArray)
+                    {
+                        o.Add(reader.Value);
+                        reader.Read();
+                    }
+
+                    Array destinationArray = Array.CreateInstance(column.DataType.GetElementType(), o.Count);
+                    Array.Copy(o.ToArray(), destinationArray, o.Count);
+
+                    dr[columnName] = destinationArray;
+                }
+                else
+                {
+                    dr[columnName] = reader.Value ?? DBNull.Value;
+                }
+                
+                reader.Read();
+            }
+
+            dr.EndEdit();
+            dt.Rows.Add(dr);
+        }
+
+        private static Type GetColumnDataType(JsonReader reader)
+        {
+            JsonToken tokenType = reader.TokenType;
+
+            switch (tokenType)
+            {
+                case JsonToken.Integer:
+                    return typeof(long);
+                case JsonToken.Float:
+                    return typeof(double);
+                case JsonToken.String:
+                case JsonToken.Null:
+                case JsonToken.Undefined:
+                    return typeof(string);
+                case JsonToken.Boolean:
+                    return typeof(bool);
+                case JsonToken.Date:
+                    return typeof(DateTime);
+                case JsonToken.StartArray:
+                    reader.Read();
+                    if (reader.TokenType == JsonToken.StartObject)
+                        return typeof(DataTable); // nested datatable
+
+                    Type arrayType = GetColumnDataType(reader);
+                    return arrayType.MakeArrayType();
+                default:
+                    throw new JsonException("Unexpected JSON token while reading DataTable: {0}".FormatWith(CultureInfo.InvariantCulture, tokenType));
+            }
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified value type.
+        /// </summary>
+        /// <param name="valueType">Type of the value.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type valueType)
+        {
+            return typeof(DataTable).IsAssignableFrom(valueType);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/DateTimeConverterBase.cs b/Newtonsoft.Json/Converters/DateTimeConverterBase.cs
new file mode 100644
index 0000000..89401dc
--- /dev/null
+++ b/Newtonsoft.Json/Converters/DateTimeConverterBase.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Provides a base class for converting a <see cref="DateTime"/> to and from JSON.
+    /// </summary>
+    public abstract class DateTimeConverterBase : JsonConverter
+    {
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            if (objectType == typeof(DateTime) || objectType == typeof(DateTime?))
+                return true;
+#if !NET20
+            if (objectType == typeof(DateTimeOffset) || objectType == typeof(DateTimeOffset?))
+                return true;
+#endif
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs b/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs
new file mode 100644
index 0000000..ce1a056
--- /dev/null
+++ b/Newtonsoft.Json/Converters/DiscriminatedUnionConverter.cs
@@ -0,0 +1,184 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || NETFX_CORE)
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Reflection;
+using Newtonsoft.Json.Serialization;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a F# discriminated union type to and from JSON.
+    /// </summary>
+    public class DiscriminatedUnionConverter : JsonConverter
+    {
+        private const string CasePropertyName = "Case";
+        private const string FieldsPropertyName = "Fields";
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            Type t = value.GetType();
+
+            object result = FSharpUtils.GetUnionFields(null, value, t, null);
+            object info = FSharpUtils.GetUnionCaseInfo(result);
+            object fields = FSharpUtils.GetUnionCaseFields(result);
+            object caseName = FSharpUtils.GetUnionCaseInfoName(info);
+
+            writer.WriteStartObject();
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(CasePropertyName) : CasePropertyName);
+            writer.WriteValue((string)caseName);
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(FieldsPropertyName) : FieldsPropertyName);
+            serializer.Serialize(writer, fields);
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.Null)
+                return null;
+
+            IEnumerable cases = (IEnumerable)FSharpUtils.GetUnionCases(null, objectType, null);
+
+            ReadAndAssertProperty(reader, CasePropertyName);
+            ReadAndAssert(reader);
+
+            string caseName = reader.Value.ToString();
+
+            object matchingCaseInfo = null;
+            foreach (object c in cases)
+            {
+                if ((string)FSharpUtils.GetUnionCaseInfoName(c) == caseName)
+                {
+                    matchingCaseInfo = c;
+                    break;
+                }
+            }
+
+            if (matchingCaseInfo == null)
+                throw new JsonSerializationException("No union type found with the name '{0}'.".FormatWith(CultureInfo.InvariantCulture, caseName));
+
+            ReadAndAssertProperty(reader, FieldsPropertyName);
+            // start array
+            ReadAndAssert(reader);
+            // first value
+            ReadAndAssert(reader);
+
+            PropertyInfo[] fieldProperties = (PropertyInfo[])FSharpUtils.GetUnionCaseInfoFields(matchingCaseInfo);
+            List<object> fieldValues = new List<object>();
+            foreach (PropertyInfo field in fieldProperties)
+            {
+                fieldValues.Add(serializer.Deserialize(reader, field.PropertyType));
+                ReadAndAssert(reader);
+            }
+
+            // end object
+            ReadAndAssert(reader);
+
+            return FSharpUtils.MakeUnion(null, matchingCaseInfo, fieldValues.ToArray(), null);
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            if (typeof(IEnumerable).IsAssignableFrom(objectType))
+                return false;
+
+            // all fsharp objects have CompilationMappingAttribute
+            // get the fsharp assembly from the attribute and initialize latebound methods
+            object[] attributes;
+#if !(NETFX_CORE || PORTABLE)
+            attributes = objectType.GetCustomAttributes(true);
+#else
+            attributes = objectType.GetTypeInfo().GetCustomAttributes(true).ToArray();
+#endif
+
+            bool isFSharpType = false;
+            foreach (object attribute in attributes)
+            {
+                Type attributeType = attribute.GetType();
+                if (attributeType.Name == "CompilationMappingAttribute")
+                {
+                    FSharpUtils.EnsureInitialized(attributeType.Assembly());
+
+                    isFSharpType = true;
+                    break;
+                }
+            }
+
+            if (!isFSharpType)
+                return false;
+
+            return (bool)FSharpUtils.IsUnion(null, objectType, null);
+        }
+
+        private static void ReadAndAssertProperty(JsonReader reader, string propertyName)
+        {
+            ReadAndAssert(reader);
+
+            if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase))
+                throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName));
+        }
+
+        private static void ReadAndAssert(JsonReader reader)
+        {
+            if (!reader.Read())
+                throw new JsonSerializationException("Unexpected end.");
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs b/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs
new file mode 100644
index 0000000..9de9787
--- /dev/null
+++ b/Newtonsoft.Json/Converters/EntityKeyMemberConverter.cs
@@ -0,0 +1,146 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using Newtonsoft.Json.Serialization;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    internal interface IEntityKeyMember
+    {
+        string Key { get; set; }
+        object Value { get; set; }
+    }
+
+    /// <summary>
+    /// Converts an Entity Framework EntityKey to and from JSON.
+    /// </summary>
+    public class EntityKeyMemberConverter : JsonConverter
+    {
+        private const string EntityKeyMemberFullTypeName = "System.Data.EntityKeyMember";
+
+        private const string KeyPropertyName = "Key";
+        private const string TypePropertyName = "Type";
+        private const string ValuePropertyName = "Value";
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(value);
+            Type keyType = (entityKeyMember.Value != null) ? entityKeyMember.Value.GetType() : null;
+
+            writer.WriteStartObject();
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyPropertyName) : KeyPropertyName);
+            writer.WriteValue(entityKeyMember.Key);
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(TypePropertyName) : TypePropertyName);
+            writer.WriteValue((keyType != null) ? keyType.FullName : null);
+
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValuePropertyName) : ValuePropertyName);
+
+            if (keyType != null)
+            {
+                string valueJson;
+                if (JsonSerializerInternalWriter.TryConvertToString(entityKeyMember.Value, keyType, out valueJson))
+                    writer.WriteValue(valueJson);
+                else
+                    writer.WriteValue(entityKeyMember.Value);
+            }
+            else
+            {
+                writer.WriteNull();
+            }
+
+            writer.WriteEndObject();
+        }
+
+        private static void ReadAndAssertProperty(JsonReader reader, string propertyName)
+        {
+            ReadAndAssert(reader);
+
+            if (reader.TokenType != JsonToken.PropertyName || !string.Equals(reader.Value.ToString(), propertyName, StringComparison.OrdinalIgnoreCase))
+                throw new JsonSerializationException("Expected JSON property '{0}'.".FormatWith(CultureInfo.InvariantCulture, propertyName));
+        }
+
+        private static void ReadAndAssert(JsonReader reader)
+        {
+            if (!reader.Read())
+                throw new JsonSerializationException("Unexpected end.");
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            IEntityKeyMember entityKeyMember = DynamicWrapper.CreateWrapper<IEntityKeyMember>(Activator.CreateInstance(objectType));
+
+            ReadAndAssertProperty(reader, KeyPropertyName);
+            ReadAndAssert(reader);
+            entityKeyMember.Key = reader.Value.ToString();
+
+            ReadAndAssertProperty(reader, TypePropertyName);
+            ReadAndAssert(reader);
+            string type = reader.Value.ToString();
+
+            Type t = Type.GetType(type);
+
+            ReadAndAssertProperty(reader, ValuePropertyName);
+            ReadAndAssert(reader);
+            entityKeyMember.Value = serializer.Deserialize(reader, t);
+
+            ReadAndAssert(reader);
+
+            return DynamicWrapper.GetUnderlyingObject(entityKeyMember);
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return objectType.AssignableToTypeName(EntityKeyMemberFullTypeName);
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs b/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs
new file mode 100644
index 0000000..e09d326
--- /dev/null
+++ b/Newtonsoft.Json/Converters/ExpandoObjectConverter.cs
@@ -0,0 +1,165 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts an ExpandoObject to and from JSON.
+    /// </summary>
+    public class ExpandoObjectConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            // can write is set to false
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            return ReadValue(reader);
+        }
+
+        private object ReadValue(JsonReader reader)
+        {
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                if (!reader.Read())
+                    throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+            }
+
+            switch (reader.TokenType)
+            {
+                case JsonToken.StartObject:
+                    return ReadObject(reader);
+                case JsonToken.StartArray:
+                    return ReadList(reader);
+                default:
+                    if (JsonReader.IsPrimitiveToken(reader.TokenType))
+                        return reader.Value;
+
+                    throw JsonSerializationException.Create(reader, "Unexpected token when converting ExpandoObject: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+        }
+
+        private object ReadList(JsonReader reader)
+        {
+            IList<object> list = new List<object>();
+
+            while (reader.Read())
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.Comment:
+                        break;
+                    default:
+                        object v = ReadValue(reader);
+
+                        list.Add(v);
+                        break;
+                    case JsonToken.EndArray:
+                        return list;
+                }
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+        }
+
+        private object ReadObject(JsonReader reader)
+        {
+            IDictionary<string, object> expandoObject = new ExpandoObject();
+
+            while (reader.Read())
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        string propertyName = reader.Value.ToString();
+
+                        if (!reader.Read())
+                            throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+
+                        object v = ReadValue(reader);
+
+                        expandoObject[propertyName] = v;
+                        break;
+                    case JsonToken.Comment:
+                        break;
+                    case JsonToken.EndObject:
+                        return expandoObject;
+                }
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end when reading ExpandoObject.");
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return (objectType == typeof(ExpandoObject));
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.
+        /// </value>
+        public override bool CanWrite
+        {
+            get { return false; }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs b/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
new file mode 100644
index 0000000..5410ff6
--- /dev/null
+++ b/Newtonsoft.Json/Converters/IsoDateTimeConverter.cs
@@ -0,0 +1,169 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="DateTime"/> to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z).
+    /// </summary>
+    public class IsoDateTimeConverter : DateTimeConverterBase
+    {
+        private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+        private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind;
+        private string _dateTimeFormat;
+        private CultureInfo _culture;
+
+        /// <summary>
+        /// Gets or sets the date time styles used when converting a date to and from JSON.
+        /// </summary>
+        /// <value>The date time styles used when converting a date to and from JSON.</value>
+        public DateTimeStyles DateTimeStyles
+        {
+            get { return _dateTimeStyles; }
+            set { _dateTimeStyles = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the date time format used when converting a date to and from JSON.
+        /// </summary>
+        /// <value>The date time format used when converting a date to and from JSON.</value>
+        public string DateTimeFormat
+        {
+            get { return _dateTimeFormat ?? string.Empty; }
+            set { _dateTimeFormat = StringUtils.NullEmptyString(value); }
+        }
+
+        /// <summary>
+        /// Gets or sets the culture used when converting a date to and from JSON.
+        /// </summary>
+        /// <value>The culture used when converting a date to and from JSON.</value>
+        public CultureInfo Culture
+        {
+            get { return _culture ?? CultureInfo.CurrentCulture; }
+            set { _culture = value; }
+        }
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            string text;
+
+            if (value is DateTime)
+            {
+                DateTime dateTime = (DateTime)value;
+
+                if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+                    || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+                    dateTime = dateTime.ToUniversalTime();
+
+                text = dateTime.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+            }
+#if !NET20
+            else if (value is DateTimeOffset)
+            {
+                DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+                if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal
+                    || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal)
+                    dateTimeOffset = dateTimeOffset.ToUniversalTime();
+
+                text = dateTimeOffset.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture);
+            }
+#endif
+            else
+            {
+                throw new JsonSerializationException("Unexpected value when converting date. Expected DateTime or DateTimeOffset, got {0}.".FormatWith(CultureInfo.InvariantCulture, ReflectionUtils.GetObjectType(value)));
+            }
+
+            writer.WriteValue(text);
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            bool nullable = ReflectionUtils.IsNullableType(objectType);
+            Type t = (nullable)
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            if (reader.TokenType == JsonToken.Null)
+            {
+                if (!ReflectionUtils.IsNullableType(objectType))
+                    throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+                return null;
+            }
+
+            if (reader.TokenType == JsonToken.Date)
+            {
+#if !NET20
+                if (t == typeof(DateTimeOffset))
+                    return reader.Value is DateTimeOffset ? reader.Value : new DateTimeOffset((DateTime)reader.Value);
+#endif
+
+                return reader.Value;
+            }
+
+            if (reader.TokenType != JsonToken.String)
+                throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected String, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            string dateText = reader.Value.ToString();
+
+            if (string.IsNullOrEmpty(dateText) && nullable)
+                return null;
+
+#if !NET20
+            if (t == typeof(DateTimeOffset))
+            {
+                if (!string.IsNullOrEmpty(_dateTimeFormat))
+                    return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+                else
+                    return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles);
+            }
+#endif
+
+            if (!string.IsNullOrEmpty(_dateTimeFormat))
+                return DateTime.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles);
+            else
+                return DateTime.Parse(dateText, Culture, _dateTimeStyles);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs b/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
new file mode 100644
index 0000000..129ed84
--- /dev/null
+++ b/Newtonsoft.Json/Converters/JavaScriptDateTimeConverter.cs
@@ -0,0 +1,118 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="DateTime"/> to and from a JavaScript date constructor (e.g. new Date(52231943)).
+    /// </summary>
+    public class JavaScriptDateTimeConverter : DateTimeConverterBase
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            long ticks;
+
+            if (value is DateTime)
+            {
+                DateTime dateTime = (DateTime)value;
+                DateTime utcDateTime = dateTime.ToUniversalTime();
+                ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTime);
+            }
+#if !NET20
+            else if (value is DateTimeOffset)
+            {
+                DateTimeOffset dateTimeOffset = (DateTimeOffset)value;
+                DateTimeOffset utcDateTimeOffset = dateTimeOffset.ToUniversalTime();
+                ticks = DateTimeUtils.ConvertDateTimeToJavaScriptTicks(utcDateTimeOffset.UtcDateTime);
+            }
+#endif
+            else
+            {
+                throw new JsonSerializationException("Expected date object value.");
+            }
+
+            writer.WriteStartConstructor("Date");
+            writer.WriteValue(ticks);
+            writer.WriteEndConstructor();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            Type t = (ReflectionUtils.IsNullableType(objectType))
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            if (reader.TokenType == JsonToken.Null)
+            {
+                if (!ReflectionUtils.IsNullable(objectType))
+                    throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+                return null;
+            }
+
+            if (reader.TokenType != JsonToken.StartConstructor || !string.Equals(reader.Value.ToString(), "Date", StringComparison.Ordinal))
+                throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing date. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
+
+            reader.Read();
+
+            if (reader.TokenType != JsonToken.Integer)
+                throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected Integer, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            long ticks = (long)reader.Value;
+
+            DateTime d = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+            reader.Read();
+
+            if (reader.TokenType != JsonToken.EndConstructor)
+                throw JsonSerializationException.Create(reader, "Unexpected token parsing date. Expected EndConstructor, got {0}.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+#if !NET20
+            if (t == typeof(DateTimeOffset))
+                return new DateTimeOffset(d);
+#endif
+
+            return d;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/JsonValueConverter.cs b/Newtonsoft.Json/Converters/JsonValueConverter.cs
new file mode 100644
index 0000000..a6e2c35
--- /dev/null
+++ b/Newtonsoft.Json/Converters/JsonValueConverter.cs
@@ -0,0 +1,225 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+
+#if NETFX_CORE
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Security;
+using Newtonsoft.Json.Utilities;
+using Windows.Data.Json;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="IJsonValue"/> to and from JSON.
+    /// </summary>
+    public class JsonValueConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            WriteJsonValue(writer, (IJsonValue)value);
+        }
+
+        private void WriteJsonValue(JsonWriter writer, IJsonValue value)
+        {
+            switch (value.ValueType)
+            {
+                case JsonValueType.Array:
+                {
+                    JsonArray a = value.GetArray();
+                    writer.WriteStartArray();
+                    for (int i = 0; i < a.Count; i++)
+                    {
+                        WriteJsonValue(writer, a[i]);
+                    }
+                    writer.WriteEndArray();
+                }
+                    break;
+                case JsonValueType.Boolean:
+                {
+                    writer.WriteValue(value.GetBoolean());
+                }
+                    break;
+                case JsonValueType.Null:
+                {
+                    writer.WriteNull();
+                }
+                    break;
+                case JsonValueType.Number:
+                {
+                    // JsonValue doesn't support integers
+                    // serialize whole numbers without a decimal point
+                    double d = value.GetNumber();
+                    bool isInteger = (d % 1 == 0);
+                    if (isInteger && d <= long.MaxValue && d >= long.MinValue)
+                        writer.WriteValue(Convert.ToInt64(d));
+                    else
+                        writer.WriteValue(d);
+                }
+                    break;
+                case JsonValueType.Object:
+                {
+                    JsonObject o = value.GetObject();
+                    writer.WriteStartObject();
+                    foreach (KeyValuePair<string, IJsonValue> v in o)
+                    {
+                        writer.WritePropertyName(v.Key);
+                        WriteJsonValue(writer, v.Value);
+                    }
+                    writer.WriteEndObject();
+                }
+                    break;
+                case JsonValueType.String:
+                {
+                    writer.WriteValue(value.GetString());
+                }
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException("ValueType");
+            }
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.None)
+                reader.Read();
+
+            IJsonValue value = CreateJsonValue(reader);
+
+            if (!objectType.IsAssignableFrom(value.GetType()))
+                throw JsonSerializationException.Create(reader, "Could not convert '{0}' to '{1}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), objectType));
+
+            return value;
+        }
+
+        private IJsonValue CreateJsonValue(JsonReader reader)
+        {
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                if (!reader.Read())
+                    throw JsonSerializationException.Create(reader, "Unexpected end.");
+            }
+
+            switch (reader.TokenType)
+            {
+                case JsonToken.StartObject:
+                {
+                    return CreateJsonObject(reader);
+                }
+                case JsonToken.StartArray:
+                {
+                    JsonArray a = new JsonArray();
+
+                    while (reader.Read())
+                    {
+                        switch (reader.TokenType)
+                        {
+                            case JsonToken.EndArray:
+                                return a;
+                            default:
+                                IJsonValue value = CreateJsonValue(reader);
+                                a.Add(value);
+                                break;
+                        }
+                    }
+                }
+                    break;
+                case JsonToken.Integer:
+                case JsonToken.Float:
+                    return JsonValue.CreateNumberValue(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
+                case JsonToken.String:
+                    return JsonValue.CreateStringValue(reader.Value.ToString());
+                case JsonToken.Boolean:
+                    return JsonValue.CreateBooleanValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+                case JsonToken.Null:
+                    // surely there is a better way to create a null value than this?
+                    return JsonValue.Parse("null");
+                case JsonToken.Date:
+                    return JsonValue.CreateStringValue(reader.Value.ToString());
+                case JsonToken.Bytes:
+                    return JsonValue.CreateStringValue(reader.Value.ToString());
+                default:
+                    throw JsonSerializationException.Create(reader, "Unexpected or unsupported token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end.");
+        }
+
+        private JsonObject CreateJsonObject(JsonReader reader)
+        {
+            JsonObject o = new JsonObject();
+            string propertyName = null;
+
+            while (reader.Read())
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        propertyName = (string)reader.Value;
+                        break;
+                    case JsonToken.EndObject:
+                        return o;
+                    case JsonToken.Comment:
+                        break;
+                    default:
+                        IJsonValue propertyValue = CreateJsonValue(reader);
+                        o.Add(propertyName, propertyValue);
+                        break;
+                }
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end.");
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return typeof(IJsonValue).IsAssignableFrom(objectType);
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/KeyValuePairConverter.cs b/Newtonsoft.Json/Converters/KeyValuePairConverter.cs
new file mode 100644
index 0000000..eeb5846
--- /dev/null
+++ b/Newtonsoft.Json/Converters/KeyValuePairConverter.cs
@@ -0,0 +1,145 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="KeyValuePair{TKey,TValue}"/> to and from JSON.
+    /// </summary>
+    public class KeyValuePairConverter : JsonConverter
+    {
+        private const string KeyName = "Key";
+        private const string ValueName = "Value";
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            Type t = value.GetType();
+            IList<Type> genericArguments = t.GetGenericArguments();
+            Type keyType = genericArguments[0];
+            Type valueType = genericArguments[1];
+
+            PropertyInfo keyProperty = t.GetProperty(KeyName);
+            PropertyInfo valueProperty = t.GetProperty(ValueName);
+
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            writer.WriteStartObject();
+
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(KeyName) : KeyName);
+            serializer.Serialize(writer, ReflectionUtils.GetMemberValue(keyProperty, value), keyType);
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(ValueName) : ValueName);
+            serializer.Serialize(writer, ReflectionUtils.GetMemberValue(valueProperty, value), valueType);
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            bool isNullable = ReflectionUtils.IsNullableType(objectType);
+
+            if (reader.TokenType == JsonToken.Null)
+            {
+                if (!isNullable)
+                    throw JsonSerializationException.Create(reader, "Cannot convert null value to KeyValuePair.");
+
+                return null;
+            }
+
+            Type t = (isNullable)
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            IList<Type> genericArguments = t.GetGenericArguments();
+            Type keyType = genericArguments[0];
+            Type valueType = genericArguments[1];
+
+            object key = null;
+            object value = null;
+
+            reader.Read();
+
+            while (reader.TokenType == JsonToken.PropertyName)
+            {
+                string propertyName = reader.Value.ToString();
+                if (string.Equals(propertyName, KeyName, StringComparison.OrdinalIgnoreCase))
+                {
+                    reader.Read();
+                    key = serializer.Deserialize(reader, keyType);
+                }
+                else if (string.Equals(propertyName, ValueName, StringComparison.OrdinalIgnoreCase))
+                {
+                    reader.Read();
+                    value = serializer.Deserialize(reader, valueType);
+                }
+                else
+                {
+                    reader.Skip();
+                }
+
+                reader.Read();
+            }
+
+            return Activator.CreateInstance(t, key, value);
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            Type t = (ReflectionUtils.IsNullableType(objectType))
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            if (t.IsValueType() && t.IsGenericType())
+                return (t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/RegexConverter.cs b/Newtonsoft.Json/Converters/RegexConverter.cs
new file mode 100644
index 0000000..f067aac
--- /dev/null
+++ b/Newtonsoft.Json/Converters/RegexConverter.cs
@@ -0,0 +1,201 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Text.RegularExpressions;
+using Newtonsoft.Json.Bson;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="Regex"/> to and from JSON and BSON.
+    /// </summary>
+    public class RegexConverter : JsonConverter
+    {
+        private const string PatternName = "Pattern";
+        private const string OptionsName = "Options";
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            Regex regex = (Regex)value;
+
+            BsonWriter bsonWriter = writer as BsonWriter;
+            if (bsonWriter != null)
+                WriteBson(bsonWriter, regex);
+            else
+                WriteJson(writer, regex, serializer);
+        }
+
+        private bool HasFlag(RegexOptions options, RegexOptions flag)
+        {
+            return ((options & flag) == flag);
+        }
+
+        private void WriteBson(BsonWriter writer, Regex regex)
+        {
+            // Regular expression - The first cstring is the regex pattern, the second
+            // is the regex options string. Options are identified by characters, which 
+            // must be stored in alphabetical order. Valid options are 'i' for case 
+            // insensitive matching, 'm' for multiline matching, 'x' for verbose mode, 
+            // 'l' to make \w, \W, etc. locale dependent, 's' for dotall mode 
+            // ('.' matches everything), and 'u' to make \w, \W, etc. match unicode.
+
+            string options = null;
+
+            if (HasFlag(regex.Options, RegexOptions.IgnoreCase))
+                options += "i";
+
+            if (HasFlag(regex.Options, RegexOptions.Multiline))
+                options += "m";
+
+            if (HasFlag(regex.Options, RegexOptions.Singleline))
+                options += "s";
+
+            options += "u";
+
+            if (HasFlag(regex.Options, RegexOptions.ExplicitCapture))
+                options += "x";
+
+            writer.WriteRegex(regex.ToString(), options);
+        }
+
+        private void WriteJson(JsonWriter writer, Regex regex, JsonSerializer serializer)
+        {
+            DefaultContractResolver resolver = serializer.ContractResolver as DefaultContractResolver;
+
+            writer.WriteStartObject();
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(PatternName) : PatternName);
+            writer.WriteValue(regex.ToString());
+            writer.WritePropertyName((resolver != null) ? resolver.GetResolvedPropertyName(OptionsName) : OptionsName);
+            serializer.Serialize(writer, regex.Options);
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.StartObject)
+                return ReadRegexObject(reader, serializer);
+
+            if (reader.TokenType == JsonToken.String)
+                return ReadRegexString(reader);
+
+            throw JsonSerializationException.Create(reader, "Unexpected token when reading Regex.");
+        }
+
+        private object ReadRegexString(JsonReader reader)
+        {
+            string regexText = (string)reader.Value;
+            int patternOptionDelimiterIndex = regexText.LastIndexOf('/');
+
+            string patternText = regexText.Substring(1, patternOptionDelimiterIndex - 1);
+            string optionsText = regexText.Substring(patternOptionDelimiterIndex + 1);
+
+            RegexOptions options = RegexOptions.None;
+            foreach (char c in optionsText)
+            {
+                switch (c)
+                {
+                    case 'i':
+                        options |= RegexOptions.IgnoreCase;
+                        break;
+                    case 'm':
+                        options |= RegexOptions.Multiline;
+                        break;
+                    case 's':
+                        options |= RegexOptions.Singleline;
+                        break;
+                    case 'x':
+                        options |= RegexOptions.ExplicitCapture;
+                        break;
+                }
+            }
+
+            return new Regex(patternText, options);
+        }
+
+        private Regex ReadRegexObject(JsonReader reader, JsonSerializer serializer)
+        {
+            string pattern = null;
+            RegexOptions? options = null;
+
+            while (reader.Read())
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        string propertyName = reader.Value.ToString();
+
+                        if (!reader.Read())
+                            throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
+
+                        if (string.Equals(propertyName, PatternName, StringComparison.OrdinalIgnoreCase))
+                            pattern = (string)reader.Value;
+                        else if (string.Equals(propertyName, OptionsName, StringComparison.OrdinalIgnoreCase))
+                            options = serializer.Deserialize<RegexOptions>(reader);
+                        else
+                            reader.Skip();
+                        break;
+                    case JsonToken.Comment:
+                        break;
+                    case JsonToken.EndObject:
+                        if (pattern == null)
+                            throw JsonSerializationException.Create(reader, "Error deserializing Regex. No pattern found.");
+
+                        return new Regex(pattern, options ?? RegexOptions.None);
+                }
+            }
+
+            throw JsonSerializationException.Create(reader, "Unexpected end when reading Regex.");
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return (objectType == typeof(Regex));
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/StringEnumConverter.cs b/Newtonsoft.Json/Converters/StringEnumConverter.cs
new file mode 100644
index 0000000..21bd6da
--- /dev/null
+++ b/Newtonsoft.Json/Converters/StringEnumConverter.cs
@@ -0,0 +1,239 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts an <see cref="Enum"/> to and from its name string value.
+    /// </summary>
+    public class StringEnumConverter : JsonConverter
+    {
+        private static readonly ThreadSafeStore<Type, BidirectionalDictionary<string, string>> EnumMemberNamesPerType = new ThreadSafeStore<Type, BidirectionalDictionary<string, string>>(InitializeEnumType);
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the written enum text should be camel case.
+        /// </summary>
+        /// <value><c>true</c> if the written enum text will be camel case; otherwise, <c>false</c>.</value>
+        public bool CamelCaseText { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether integer values are allowed.
+        /// </summary>
+        /// <value><c>true</c> if integers are allowed; otherwise, <c>false</c>.</value>
+        public bool AllowIntegerValues { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="StringEnumConverter"/> class.
+        /// </summary>
+        public StringEnumConverter()
+        {
+            AllowIntegerValues = true;
+        }
+
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            if (value == null)
+            {
+                writer.WriteNull();
+                return;
+            }
+
+            Enum e = (Enum)value;
+
+            string enumName = e.ToString("G");
+
+            if (char.IsNumber(enumName[0]) || enumName[0] == '-')
+            {
+                // enum value has no name so write number
+                writer.WriteValue(value);
+            }
+            else
+            {
+                BidirectionalDictionary<string, string> map = EnumMemberNamesPerType.Get(e.GetType());
+
+                string[] names = enumName.Split(',');
+                for (int i = 0; i < names.Length; i++)
+                {
+                    string name = names[i].Trim();
+
+                    string resolvedEnumName;
+                    map.TryGetByFirst(name, out resolvedEnumName);
+                    resolvedEnumName = resolvedEnumName ?? name;
+
+                    if (CamelCaseText)
+                        resolvedEnumName = StringUtils.ToCamelCase(resolvedEnumName);
+
+                    names[i] = resolvedEnumName;
+                }
+
+                string finalName = string.Join(", ", names);
+
+                writer.WriteValue(finalName);
+            }
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            bool isNullable = ReflectionUtils.IsNullableType(objectType);
+            Type t = isNullable ? Nullable.GetUnderlyingType(objectType) : objectType;
+
+            if (reader.TokenType == JsonToken.Null)
+            {
+                if (!ReflectionUtils.IsNullableType(objectType))
+                    throw JsonSerializationException.Create(reader, "Cannot convert null value to {0}.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+                return null;
+            }
+
+            try
+            {
+                if (reader.TokenType == JsonToken.String)
+                {
+                    string enumText = reader.Value.ToString();
+                    if (enumText == string.Empty && isNullable)
+                        return null;
+
+                    string finalEnumText;
+
+                    BidirectionalDictionary<string, string> map = EnumMemberNamesPerType.Get(t);
+                    if (enumText.IndexOf(',') != -1)
+                    {
+                        string[] names = enumText.Split(',');
+                        for (int i = 0; i < names.Length; i++)
+                        {
+                            string name = names[i].Trim();
+
+                            names[i] = ResolvedEnumName(map, name);
+                        }
+
+                        finalEnumText = string.Join(", ", names);
+                    }
+                    else
+                    {
+                        finalEnumText = ResolvedEnumName(map, enumText);
+                    }
+
+                    return Enum.Parse(t, finalEnumText, true);
+                }
+
+                if (reader.TokenType == JsonToken.Integer)
+                {
+                    if (!AllowIntegerValues)
+                        throw JsonSerializationException.Create(reader, "Integer value {0} is not allowed.".FormatWith(CultureInfo.InvariantCulture, reader.Value));
+
+                    return ConvertUtils.ConvertOrCast(reader.Value, CultureInfo.InvariantCulture, t);
+                }
+            }
+            catch (Exception ex)
+            {
+                throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(reader.Value), objectType), ex);
+            }
+
+            // we don't actually expect to get here.
+            throw JsonSerializationException.Create(reader, "Unexpected token {0} when parsing enum.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+        }
+
+        private static string ResolvedEnumName(BidirectionalDictionary<string, string> map, string enumText)
+        {
+            string resolvedEnumName;
+            map.TryGetBySecond(enumText, out resolvedEnumName);
+            resolvedEnumName = resolvedEnumName ?? enumText;
+            return resolvedEnumName;
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            Type t = (ReflectionUtils.IsNullableType(objectType))
+                ? Nullable.GetUnderlyingType(objectType)
+                : objectType;
+
+            return t.IsEnum();
+        }
+
+        private static BidirectionalDictionary<string, string> InitializeEnumType(Type type)
+        {
+            BidirectionalDictionary<string, string> map = new BidirectionalDictionary<string, string>(
+                StringComparer.OrdinalIgnoreCase,
+                StringComparer.OrdinalIgnoreCase);
+
+            foreach (FieldInfo f in type.GetFields())
+            {
+                string n1 = f.Name;
+                string n2;
+
+#if !NET20
+                n2 = f.GetCustomAttributes(typeof(EnumMemberAttribute), true)
+                    .Cast<EnumMemberAttribute>()
+                    .Select(a => a.Value)
+                    .SingleOrDefault() ?? f.Name;
+#else
+                n2 = f.Name;
+#endif
+
+                string s;
+                if (map.TryGetBySecond(n2, out s))
+                    throw new InvalidOperationException("Enum name '{0}' already exists on enum '{1}'.".FormatWith(CultureInfo.InvariantCulture, n2, type.Name));
+
+                map.Set(n1, n2);
+            }
+
+            return map;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/VersionConverter.cs b/Newtonsoft.Json/Converters/VersionConverter.cs
new file mode 100644
index 0000000..9adf680
--- /dev/null
+++ b/Newtonsoft.Json/Converters/VersionConverter.cs
@@ -0,0 +1,106 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Converters
+{
+    /// <summary>
+    /// Converts a <see cref="Version"/> to and from a string (e.g. "1.2.3.4").
+    /// </summary>
+    public class VersionConverter : JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            if (value == null)
+            {
+                writer.WriteNull();
+            }
+            else if (value is Version)
+            {
+                writer.WriteValue(value.ToString());
+            }
+            else
+            {
+                throw new JsonSerializationException("Expected Version object value");
+            }
+        }
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing property value of the JSON that is being converted.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.Null)
+            {
+                return null;
+            }
+            else
+            {
+                if (reader.TokenType == JsonToken.String)
+                {
+                    try
+                    {
+                        Version v = new Version((string)reader.Value);
+                        return v;
+                    }
+                    catch (Exception ex)
+                    {
+                        throw JsonSerializationException.Create(reader, "Error parsing version string: {0}".FormatWith(CultureInfo.InvariantCulture, reader.Value), ex);
+                    }
+                }
+                else
+                {
+                    throw JsonSerializationException.Create(reader, "Unexpected token or value when parsing version. Token: {0}, Value: {1}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType, reader.Value));
+                }
+            }
+        }
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type objectType)
+        {
+            return objectType == typeof(Version);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Converters/XmlNodeConverter.cs b/Newtonsoft.Json/Converters/XmlNodeConverter.cs
new file mode 100644
index 0000000..fa65091
--- /dev/null
+++ b/Newtonsoft.Json/Converters/XmlNodeConverter.cs
@@ -0,0 +1,1758 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !PORTABLE40
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Xml;
+#if !(NET20 || PORTABLE40)
+using System.Xml.Linq;
+#endif
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Converters
+{
+    #region XmlNodeWrappers
+#if !NETFX_CORE && !PORTABLE && !PORTABLE40
+    internal class XmlDocumentWrapper : XmlNodeWrapper, IXmlDocument
+    {
+        private readonly XmlDocument _document;
+
+        public XmlDocumentWrapper(XmlDocument document)
+            : base(document)
+        {
+            _document = document;
+        }
+
+        public IXmlNode CreateComment(string data)
+        {
+            return new XmlNodeWrapper(_document.CreateComment(data));
+        }
+
+        public IXmlNode CreateTextNode(string text)
+        {
+            return new XmlNodeWrapper(_document.CreateTextNode(text));
+        }
+
+        public IXmlNode CreateCDataSection(string data)
+        {
+            return new XmlNodeWrapper(_document.CreateCDataSection(data));
+        }
+
+        public IXmlNode CreateWhitespace(string text)
+        {
+            return new XmlNodeWrapper(_document.CreateWhitespace(text));
+        }
+
+        public IXmlNode CreateSignificantWhitespace(string text)
+        {
+            return new XmlNodeWrapper(_document.CreateSignificantWhitespace(text));
+        }
+
+        public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
+        {
+            return new XmlDeclarationWrapper(_document.CreateXmlDeclaration(version, encoding, standalone));
+        }
+
+        public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
+        {
+            return new XmlDocumentTypeWrapper(_document.CreateDocumentType(name, publicId, systemId, null));
+        }
+
+        public IXmlNode CreateProcessingInstruction(string target, string data)
+        {
+            return new XmlNodeWrapper(_document.CreateProcessingInstruction(target, data));
+        }
+
+        public IXmlElement CreateElement(string elementName)
+        {
+            return new XmlElementWrapper(_document.CreateElement(elementName));
+        }
+
+        public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
+        {
+            return new XmlElementWrapper(_document.CreateElement(qualifiedName, namespaceUri));
+        }
+
+        public IXmlNode CreateAttribute(string name, string value)
+        {
+            XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(name));
+            attribute.Value = value;
+
+            return attribute;
+        }
+
+        public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
+        {
+            XmlNodeWrapper attribute = new XmlNodeWrapper(_document.CreateAttribute(qualifiedName, namespaceUri));
+            attribute.Value = value;
+
+            return attribute;
+        }
+
+        public IXmlElement DocumentElement
+        {
+            get
+            {
+                if (_document.DocumentElement == null)
+                    return null;
+
+                return new XmlElementWrapper(_document.DocumentElement);
+            }
+        }
+    }
+
+    internal class XmlElementWrapper : XmlNodeWrapper, IXmlElement
+    {
+        private readonly XmlElement _element;
+
+        public XmlElementWrapper(XmlElement element)
+            : base(element)
+        {
+            _element = element;
+        }
+
+        public void SetAttributeNode(IXmlNode attribute)
+        {
+            XmlNodeWrapper xmlAttributeWrapper = (XmlNodeWrapper)attribute;
+
+            _element.SetAttributeNode((XmlAttribute)xmlAttributeWrapper.WrappedNode);
+        }
+
+        public string GetPrefixOfNamespace(string namespaceUri)
+        {
+            return _element.GetPrefixOfNamespace(namespaceUri);
+        }
+
+        public bool IsEmpty
+        {
+            get { return _element.IsEmpty; }
+        }
+    }
+
+    internal class XmlDeclarationWrapper : XmlNodeWrapper, IXmlDeclaration
+    {
+        private readonly XmlDeclaration _declaration;
+
+        public XmlDeclarationWrapper(XmlDeclaration declaration)
+            : base(declaration)
+        {
+            _declaration = declaration;
+        }
+
+        public string Version
+        {
+            get { return _declaration.Version; }
+        }
+
+        public string Encoding
+        {
+            get { return _declaration.Encoding; }
+            set { _declaration.Encoding = value; }
+        }
+
+        public string Standalone
+        {
+            get { return _declaration.Standalone; }
+            set { _declaration.Standalone = value; }
+        }
+    }
+
+    internal class XmlDocumentTypeWrapper : XmlNodeWrapper, IXmlDocumentType
+    {
+        private readonly XmlDocumentType _documentType;
+
+        public XmlDocumentTypeWrapper(XmlDocumentType documentType)
+            : base(documentType)
+        {
+            _documentType = documentType;
+        }
+
+        public string Name
+        {
+            get { return _documentType.Name; }
+        }
+
+        public string System
+        {
+            get { return _documentType.SystemId; }
+        }
+
+        public string Public
+        {
+            get { return _documentType.PublicId; }
+        }
+
+        public string InternalSubset
+        {
+            get { return _documentType.InternalSubset; }
+        }
+
+        public new string LocalName
+        {
+            get { return "DOCTYPE"; }
+        }
+    }
+
+    internal class XmlNodeWrapper : IXmlNode
+    {
+        private readonly XmlNode _node;
+
+        public XmlNodeWrapper(XmlNode node)
+        {
+            _node = node;
+        }
+
+        public object WrappedNode
+        {
+            get { return _node; }
+        }
+
+        public XmlNodeType NodeType
+        {
+            get { return _node.NodeType; }
+        }
+
+        public string LocalName
+        {
+            get { return _node.LocalName; }
+        }
+
+        public IList<IXmlNode> ChildNodes
+        {
+            get { return _node.ChildNodes.Cast<XmlNode>().Select(n => WrapNode(n)).ToList(); }
+        }
+
+        private IXmlNode WrapNode(XmlNode node)
+        {
+            switch (node.NodeType)
+            {
+                case XmlNodeType.Element:
+                    return new XmlElementWrapper((XmlElement)node);
+                case XmlNodeType.XmlDeclaration:
+                    return new XmlDeclarationWrapper((XmlDeclaration)node);
+                case XmlNodeType.DocumentType:
+                    return new XmlDocumentTypeWrapper((XmlDocumentType)node);
+                default:
+                    return new XmlNodeWrapper(node);
+            }
+        }
+
+        public IList<IXmlNode> Attributes
+        {
+            get
+            {
+                if (_node.Attributes == null)
+                    return null;
+
+                return _node.Attributes.Cast<XmlAttribute>().Select(a => WrapNode(a)).ToList();
+            }
+        }
+
+        public IXmlNode ParentNode
+        {
+            get
+            {
+                XmlNode node = (_node is XmlAttribute)
+                    ? ((XmlAttribute)_node).OwnerElement
+                    : _node.ParentNode;
+
+                if (node == null)
+                    return null;
+
+                return WrapNode(node);
+            }
+        }
+
+        public string Value
+        {
+            get { return _node.Value; }
+            set { _node.Value = value; }
+        }
+
+        public IXmlNode AppendChild(IXmlNode newChild)
+        {
+            XmlNodeWrapper xmlNodeWrapper = (XmlNodeWrapper)newChild;
+            _node.AppendChild(xmlNodeWrapper._node);
+
+            return newChild;
+        }
+
+        public string NamespaceUri
+        {
+            get { return _node.NamespaceURI; }
+        }
+    }
+#endif
+    #endregion
+
+    #region Interfaces
+    internal interface IXmlDocument : IXmlNode
+    {
+        IXmlNode CreateComment(string text);
+        IXmlNode CreateTextNode(string text);
+        IXmlNode CreateCDataSection(string data);
+        IXmlNode CreateWhitespace(string text);
+        IXmlNode CreateSignificantWhitespace(string text);
+        IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone);
+        IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset);
+        IXmlNode CreateProcessingInstruction(string target, string data);
+        IXmlElement CreateElement(string elementName);
+        IXmlElement CreateElement(string qualifiedName, string namespaceUri);
+        IXmlNode CreateAttribute(string name, string value);
+        IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value);
+
+        IXmlElement DocumentElement { get; }
+    }
+
+    internal interface IXmlDeclaration : IXmlNode
+    {
+        string Version { get; }
+        string Encoding { get; set; }
+        string Standalone { get; set; }
+    }
+
+    internal interface IXmlDocumentType : IXmlNode
+    {
+        string Name { get; }
+        string System { get; }
+        string Public { get; }
+        string InternalSubset { get; }
+    }
+
+    internal interface IXmlElement : IXmlNode
+    {
+        void SetAttributeNode(IXmlNode attribute);
+        string GetPrefixOfNamespace(string namespaceUri);
+        bool IsEmpty { get; }
+    }
+
+    internal interface IXmlNode
+    {
+        XmlNodeType NodeType { get; }
+        string LocalName { get; }
+        IList<IXmlNode> ChildNodes { get; }
+        IList<IXmlNode> Attributes { get; }
+        IXmlNode ParentNode { get; }
+        string Value { get; set; }
+        IXmlNode AppendChild(IXmlNode newChild);
+        string NamespaceUri { get; }
+        object WrappedNode { get; }
+    }
+    #endregion
+
+    #region XNodeWrappers
+#if !NET20
+    internal class XDeclarationWrapper : XObjectWrapper, IXmlDeclaration
+    {
+        internal XDeclaration Declaration { get; private set; }
+
+        public XDeclarationWrapper(XDeclaration declaration)
+            : base(null)
+        {
+            Declaration = declaration;
+        }
+
+        public override XmlNodeType NodeType
+        {
+            get { return XmlNodeType.XmlDeclaration; }
+        }
+
+        public string Version
+        {
+            get { return Declaration.Version; }
+        }
+
+        public string Encoding
+        {
+            get { return Declaration.Encoding; }
+            set { Declaration.Encoding = value; }
+        }
+
+        public string Standalone
+        {
+            get { return Declaration.Standalone; }
+            set { Declaration.Standalone = value; }
+        }
+    }
+
+    internal class XDocumentTypeWrapper : XObjectWrapper, IXmlDocumentType
+    {
+        private readonly XDocumentType _documentType;
+
+        public XDocumentTypeWrapper(XDocumentType documentType)
+            : base(documentType)
+        {
+            _documentType = documentType;
+        }
+
+        public string Name
+        {
+            get { return _documentType.Name; }
+        }
+
+        public string System
+        {
+            get { return _documentType.SystemId; }
+        }
+
+        public string Public
+        {
+            get { return _documentType.PublicId; }
+        }
+
+        public string InternalSubset
+        {
+            get { return _documentType.InternalSubset; }
+        }
+
+        public new string LocalName
+        {
+            get { return "DOCTYPE"; }
+        }
+    }
+
+    internal class XDocumentWrapper : XContainerWrapper, IXmlDocument
+    {
+        private XDocument Document
+        {
+            get { return (XDocument)WrappedNode; }
+        }
+
+        public XDocumentWrapper(XDocument document)
+            : base(document)
+        {
+        }
+
+        public override IList<IXmlNode> ChildNodes
+        {
+            get
+            {
+                IList<IXmlNode> childNodes = base.ChildNodes;
+
+                if (Document.Declaration != null)
+                    childNodes.Insert(0, new XDeclarationWrapper(Document.Declaration));
+
+                return childNodes;
+            }
+        }
+
+        public IXmlNode CreateComment(string text)
+        {
+            return new XObjectWrapper(new XComment(text));
+        }
+
+        public IXmlNode CreateTextNode(string text)
+        {
+            return new XObjectWrapper(new XText(text));
+        }
+
+        public IXmlNode CreateCDataSection(string data)
+        {
+            return new XObjectWrapper(new XCData(data));
+        }
+
+        public IXmlNode CreateWhitespace(string text)
+        {
+            return new XObjectWrapper(new XText(text));
+        }
+
+        public IXmlNode CreateSignificantWhitespace(string text)
+        {
+            return new XObjectWrapper(new XText(text));
+        }
+
+        public IXmlNode CreateXmlDeclaration(string version, string encoding, string standalone)
+        {
+            return new XDeclarationWrapper(new XDeclaration(version, encoding, standalone));
+        }
+
+        public IXmlNode CreateXmlDocumentType(string name, string publicId, string systemId, string internalSubset)
+        {
+            return new XDocumentTypeWrapper(new XDocumentType(name, publicId, systemId, internalSubset));
+        }
+
+        public IXmlNode CreateProcessingInstruction(string target, string data)
+        {
+            return new XProcessingInstructionWrapper(new XProcessingInstruction(target, data));
+        }
+
+        public IXmlElement CreateElement(string elementName)
+        {
+            return new XElementWrapper(new XElement(elementName));
+        }
+
+        public IXmlElement CreateElement(string qualifiedName, string namespaceUri)
+        {
+            string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
+            return new XElementWrapper(new XElement(XName.Get(localName, namespaceUri)));
+        }
+
+        public IXmlNode CreateAttribute(string name, string value)
+        {
+            return new XAttributeWrapper(new XAttribute(name, value));
+        }
+
+        public IXmlNode CreateAttribute(string qualifiedName, string namespaceUri, string value)
+        {
+            string localName = MiscellaneousUtils.GetLocalName(qualifiedName);
+            return new XAttributeWrapper(new XAttribute(XName.Get(localName, namespaceUri), value));
+        }
+
+        public IXmlElement DocumentElement
+        {
+            get
+            {
+                if (Document.Root == null)
+                    return null;
+
+                return new XElementWrapper(Document.Root);
+            }
+        }
+
+        public override IXmlNode AppendChild(IXmlNode newChild)
+        {
+            XDeclarationWrapper declarationWrapper = newChild as XDeclarationWrapper;
+            if (declarationWrapper != null)
+            {
+                Document.Declaration = declarationWrapper.Declaration;
+                return declarationWrapper;
+            }
+            else
+            {
+                return base.AppendChild(newChild);
+            }
+        }
+    }
+
+    internal class XTextWrapper : XObjectWrapper
+    {
+        private XText Text
+        {
+            get { return (XText)WrappedNode; }
+        }
+
+        public XTextWrapper(XText text)
+            : base(text)
+        {
+        }
+
+        public override string Value
+        {
+            get { return Text.Value; }
+            set { Text.Value = value; }
+        }
+
+        public override IXmlNode ParentNode
+        {
+            get
+            {
+                if (Text.Parent == null)
+                    return null;
+
+                return XContainerWrapper.WrapNode(Text.Parent);
+            }
+        }
+    }
+
+    internal class XCommentWrapper : XObjectWrapper
+    {
+        private XComment Text
+        {
+            get { return (XComment)WrappedNode; }
+        }
+
+        public XCommentWrapper(XComment text)
+            : base(text)
+        {
+        }
+
+        public override string Value
+        {
+            get { return Text.Value; }
+            set { Text.Value = value; }
+        }
+
+        public override IXmlNode ParentNode
+        {
+            get
+            {
+                if (Text.Parent == null)
+                    return null;
+
+                return XContainerWrapper.WrapNode(Text.Parent);
+            }
+        }
+    }
+
+    internal class XProcessingInstructionWrapper : XObjectWrapper
+    {
+        private XProcessingInstruction ProcessingInstruction
+        {
+            get { return (XProcessingInstruction)WrappedNode; }
+        }
+
+        public XProcessingInstructionWrapper(XProcessingInstruction processingInstruction)
+            : base(processingInstruction)
+        {
+        }
+
+        public override string LocalName
+        {
+            get { return ProcessingInstruction.Target; }
+        }
+
+        public override string Value
+        {
+            get { return ProcessingInstruction.Data; }
+            set { ProcessingInstruction.Data = value; }
+        }
+    }
+
+    internal class XContainerWrapper : XObjectWrapper
+    {
+        private XContainer Container
+        {
+            get { return (XContainer)WrappedNode; }
+        }
+
+        public XContainerWrapper(XContainer container)
+            : base(container)
+        {
+        }
+
+        public override IList<IXmlNode> ChildNodes
+        {
+            get { return Container.Nodes().Select(n => WrapNode(n)).ToList(); }
+        }
+
+        public override IXmlNode ParentNode
+        {
+            get
+            {
+                if (Container.Parent == null)
+                    return null;
+
+                return WrapNode(Container.Parent);
+            }
+        }
+
+        internal static IXmlNode WrapNode(XObject node)
+        {
+            if (node is XDocument)
+                return new XDocumentWrapper((XDocument)node);
+            else if (node is XElement)
+                return new XElementWrapper((XElement)node);
+            else if (node is XContainer)
+                return new XContainerWrapper((XContainer)node);
+            else if (node is XProcessingInstruction)
+                return new XProcessingInstructionWrapper((XProcessingInstruction)node);
+            else if (node is XText)
+                return new XTextWrapper((XText)node);
+            else if (node is XComment)
+                return new XCommentWrapper((XComment)node);
+            else if (node is XAttribute)
+                return new XAttributeWrapper((XAttribute)node);
+            else if (node is XDocumentType)
+                return new XDocumentTypeWrapper((XDocumentType)node);
+            else
+                return new XObjectWrapper(node);
+        }
+
+        public override IXmlNode AppendChild(IXmlNode newChild)
+        {
+            Container.Add(newChild.WrappedNode);
+            return newChild;
+        }
+    }
+
+    internal class XObjectWrapper : IXmlNode
+    {
+        private readonly XObject _xmlObject;
+
+        public XObjectWrapper(XObject xmlObject)
+        {
+            _xmlObject = xmlObject;
+        }
+
+        public object WrappedNode
+        {
+            get { return _xmlObject; }
+        }
+
+        public virtual XmlNodeType NodeType
+        {
+            get { return _xmlObject.NodeType; }
+        }
+
+        public virtual string LocalName
+        {
+            get { return null; }
+        }
+
+        public virtual IList<IXmlNode> ChildNodes
+        {
+            get { return new List<IXmlNode>(); }
+        }
+
+        public virtual IList<IXmlNode> Attributes
+        {
+            get { return null; }
+        }
+
+        public virtual IXmlNode ParentNode
+        {
+            get { return null; }
+        }
+
+        public virtual string Value
+        {
+            get { return null; }
+            set { throw new InvalidOperationException(); }
+        }
+
+        public virtual IXmlNode AppendChild(IXmlNode newChild)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public virtual string NamespaceUri
+        {
+            get { return null; }
+        }
+    }
+
+    internal class XAttributeWrapper : XObjectWrapper
+    {
+        private XAttribute Attribute
+        {
+            get { return (XAttribute)WrappedNode; }
+        }
+
+        public XAttributeWrapper(XAttribute attribute)
+            : base(attribute)
+        {
+        }
+
+        public override string Value
+        {
+            get { return Attribute.Value; }
+            set { Attribute.Value = value; }
+        }
+
+        public override string LocalName
+        {
+            get { return Attribute.Name.LocalName; }
+        }
+
+        public override string NamespaceUri
+        {
+            get { return Attribute.Name.NamespaceName; }
+        }
+
+        public override IXmlNode ParentNode
+        {
+            get
+            {
+                if (Attribute.Parent == null)
+                    return null;
+
+                return XContainerWrapper.WrapNode(Attribute.Parent);
+            }
+        }
+    }
+
+    internal class XElementWrapper : XContainerWrapper, IXmlElement
+    {
+        private XElement Element
+        {
+            get { return (XElement)WrappedNode; }
+        }
+
+        public XElementWrapper(XElement element)
+            : base(element)
+        {
+        }
+
+        public void SetAttributeNode(IXmlNode attribute)
+        {
+            XObjectWrapper wrapper = (XObjectWrapper)attribute;
+            Element.Add(wrapper.WrappedNode);
+        }
+
+        public override IList<IXmlNode> Attributes
+        {
+            get { return Element.Attributes().Select(a => new XAttributeWrapper(a)).Cast<IXmlNode>().ToList(); }
+        }
+
+        public override string Value
+        {
+            get { return Element.Value; }
+            set { Element.Value = value; }
+        }
+
+        public override string LocalName
+        {
+            get { return Element.Name.LocalName; }
+        }
+
+        public override string NamespaceUri
+        {
+            get { return Element.Name.NamespaceName; }
+        }
+
+        public string GetPrefixOfNamespace(string namespaceUri)
+        {
+            return Element.GetPrefixOfNamespace(namespaceUri);
+        }
+
+        public bool IsEmpty
+        {
+            get { return Element.IsEmpty; }
+        }
+    }
+#endif
+    #endregion
+
+    /// <summary>
+    /// Converts XML to and from JSON.
+    /// </summary>
+    public class XmlNodeConverter : JsonConverter
+    {
+        private const string TextName = "#text";
+        private const string CommentName = "#comment";
+        private const string CDataName = "#cdata-section";
+        private const string WhitespaceName = "#whitespace";
+        private const string SignificantWhitespaceName = "#significant-whitespace";
+        private const string DeclarationName = "?xml";
+        private const string JsonNamespaceUri = "http://james.newtonking.com/projects/json";
+
+        /// <summary>
+        /// Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements.
+        /// </summary>
+        /// <value>The name of the deserialize root element.</value>
+        public string DeserializeRootElementName { get; set; }
+
+        /// <summary>
+        /// Gets or sets a flag to indicate whether to write the Json.NET array attribute.
+        /// This attribute helps preserve arrays when converting the written XML back to JSON.
+        /// </summary>
+        /// <value><c>true</c> if the array attibute is written to the XML; otherwise, <c>false</c>.</value>
+        public bool WriteArrayAttribute { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to write the root JSON object.
+        /// </summary>
+        /// <value><c>true</c> if the JSON root object is omitted; otherwise, <c>false</c>.</value>
+        public bool OmitRootObject { get; set; }
+
+        #region Writing
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <param name="value">The value.</param>
+        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+        {
+            IXmlNode node = WrapXml(value);
+
+            XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
+            PushParentNamespaces(node, manager);
+
+            if (!OmitRootObject)
+                writer.WriteStartObject();
+
+            SerializeNode(writer, node, manager, !OmitRootObject);
+
+            if (!OmitRootObject)
+                writer.WriteEndObject();
+        }
+
+        private IXmlNode WrapXml(object value)
+        {
+#if !NET20
+            if (value is XObject)
+                return XContainerWrapper.WrapNode((XObject)value);
+#endif
+#if !(NETFX_CORE || PORTABLE)
+            if (value is XmlNode)
+                return new XmlNodeWrapper((XmlNode)value);
+#endif
+
+            throw new ArgumentException("Value must be an XML object.", "value");
+        }
+
+        private void PushParentNamespaces(IXmlNode node, XmlNamespaceManager manager)
+        {
+            List<IXmlNode> parentElements = null;
+
+            IXmlNode parent = node;
+            while ((parent = parent.ParentNode) != null)
+            {
+                if (parent.NodeType == XmlNodeType.Element)
+                {
+                    if (parentElements == null)
+                        parentElements = new List<IXmlNode>();
+
+                    parentElements.Add(parent);
+                }
+            }
+
+            if (parentElements != null)
+            {
+                parentElements.Reverse();
+
+                foreach (IXmlNode parentElement in parentElements)
+                {
+                    manager.PushScope();
+                    foreach (IXmlNode attribute in parentElement.Attributes)
+                    {
+                        if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/" && attribute.LocalName != "xmlns")
+                            manager.AddNamespace(attribute.LocalName, attribute.Value);
+                    }
+                }
+            }
+        }
+
+        private string ResolveFullName(IXmlNode node, XmlNamespaceManager manager)
+        {
+            string prefix = (node.NamespaceUri == null || (node.LocalName == "xmlns" && node.NamespaceUri == "http://www.w3.org/2000/xmlns/"))
+                ? null
+                : manager.LookupPrefix(node.NamespaceUri);
+
+            if (!string.IsNullOrEmpty(prefix))
+                return prefix + ":" + node.LocalName;
+            else
+                return node.LocalName;
+        }
+
+        private string GetPropertyName(IXmlNode node, XmlNamespaceManager manager)
+        {
+            switch (node.NodeType)
+            {
+                case XmlNodeType.Attribute:
+                    if (node.NamespaceUri == JsonNamespaceUri)
+                        return "$" + node.LocalName;
+                    else
+                        return "@" + ResolveFullName(node, manager);
+                case XmlNodeType.CDATA:
+                    return CDataName;
+                case XmlNodeType.Comment:
+                    return CommentName;
+                case XmlNodeType.Element:
+                    return ResolveFullName(node, manager);
+                case XmlNodeType.ProcessingInstruction:
+                    return "?" + ResolveFullName(node, manager);
+                case XmlNodeType.DocumentType:
+                    return "!" + ResolveFullName(node, manager);
+                case XmlNodeType.XmlDeclaration:
+                    return DeclarationName;
+                case XmlNodeType.SignificantWhitespace:
+                    return SignificantWhitespaceName;
+                case XmlNodeType.Text:
+                    return TextName;
+                case XmlNodeType.Whitespace:
+                    return WhitespaceName;
+                default:
+                    throw new JsonSerializationException("Unexpected XmlNodeType when getting node name: " + node.NodeType);
+            }
+        }
+
+        private bool IsArray(IXmlNode node)
+        {
+            IXmlNode jsonArrayAttribute = (node.Attributes != null)
+                ? node.Attributes.SingleOrDefault(a => a.LocalName == "Array" && a.NamespaceUri == JsonNamespaceUri)
+                : null;
+
+            return (jsonArrayAttribute != null && XmlConvert.ToBoolean(jsonArrayAttribute.Value));
+        }
+
+        private void SerializeGroupedNodes(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
+        {
+            // group nodes together by name
+            Dictionary<string, List<IXmlNode>> nodesGroupedByName = new Dictionary<string, List<IXmlNode>>();
+
+            for (int i = 0; i < node.ChildNodes.Count; i++)
+            {
+                IXmlNode childNode = node.ChildNodes[i];
+                string nodeName = GetPropertyName(childNode, manager);
+
+                List<IXmlNode> nodes;
+                if (!nodesGroupedByName.TryGetValue(nodeName, out nodes))
+                {
+                    nodes = new List<IXmlNode>();
+                    nodesGroupedByName.Add(nodeName, nodes);
+                }
+
+                nodes.Add(childNode);
+            }
+
+            // loop through grouped nodes. write single name instances as normal,
+            // write multiple names together in an array
+            foreach (KeyValuePair<string, List<IXmlNode>> nodeNameGroup in nodesGroupedByName)
+            {
+                List<IXmlNode> groupedNodes = nodeNameGroup.Value;
+                bool writeArray;
+
+                if (groupedNodes.Count == 1)
+                {
+                    writeArray = IsArray(groupedNodes[0]);
+                }
+                else
+                {
+                    writeArray = true;
+                }
+
+                if (!writeArray)
+                {
+                    SerializeNode(writer, groupedNodes[0], manager, writePropertyName);
+                }
+                else
+                {
+                    string elementNames = nodeNameGroup.Key;
+
+                    if (writePropertyName)
+                        writer.WritePropertyName(elementNames);
+
+                    writer.WriteStartArray();
+
+                    for (int i = 0; i < groupedNodes.Count; i++)
+                    {
+                        SerializeNode(writer, groupedNodes[i], manager, false);
+                    }
+
+                    writer.WriteEndArray();
+                }
+            }
+        }
+
+        private void SerializeNode(JsonWriter writer, IXmlNode node, XmlNamespaceManager manager, bool writePropertyName)
+        {
+            switch (node.NodeType)
+            {
+                case XmlNodeType.Document:
+                case XmlNodeType.DocumentFragment:
+                    SerializeGroupedNodes(writer, node, manager, writePropertyName);
+                    break;
+                case XmlNodeType.Element:
+                    if (IsArray(node) && node.ChildNodes.All(n => n.LocalName == node.LocalName) && node.ChildNodes.Count > 0)
+                    {
+                        SerializeGroupedNodes(writer, node, manager, false);
+                    }
+                    else
+                    {
+                        manager.PushScope();
+
+                        foreach (IXmlNode attribute in node.Attributes)
+                        {
+                            if (attribute.NamespaceUri == "http://www.w3.org/2000/xmlns/")
+                            {
+                                string namespacePrefix = (attribute.LocalName != "xmlns")
+                                    ? attribute.LocalName
+                                    : string.Empty;
+                                string namespaceUri = attribute.Value;
+
+                                manager.AddNamespace(namespacePrefix, namespaceUri);
+                            }
+                        }
+
+                        if (writePropertyName)
+                            writer.WritePropertyName(GetPropertyName(node, manager));
+
+                        if (!ValueAttributes(node.Attributes).Any() && node.ChildNodes.Count == 1
+                            && node.ChildNodes[0].NodeType == XmlNodeType.Text)
+                        {
+                            // write elements with a single text child as a name value pair
+                            writer.WriteValue(node.ChildNodes[0].Value);
+                        }
+                        else if (node.ChildNodes.Count == 0 && CollectionUtils.IsNullOrEmpty(node.Attributes))
+                        {
+                            IXmlElement element = (IXmlElement)node;
+
+                            // empty element
+                            if (element.IsEmpty)
+                                writer.WriteNull();
+                            else
+                                writer.WriteValue(string.Empty);
+                        }
+                        else
+                        {
+                            writer.WriteStartObject();
+
+                            for (int i = 0; i < node.Attributes.Count; i++)
+                            {
+                                SerializeNode(writer, node.Attributes[i], manager, true);
+                            }
+
+                            SerializeGroupedNodes(writer, node, manager, true);
+
+                            writer.WriteEndObject();
+                        }
+
+                        manager.PopScope();
+                    }
+
+                    break;
+                case XmlNodeType.Comment:
+                    if (writePropertyName)
+                        writer.WriteComment(node.Value);
+                    break;
+                case XmlNodeType.Attribute:
+                case XmlNodeType.Text:
+                case XmlNodeType.CDATA:
+                case XmlNodeType.ProcessingInstruction:
+                case XmlNodeType.Whitespace:
+                case XmlNodeType.SignificantWhitespace:
+                    if (node.NamespaceUri == "http://www.w3.org/2000/xmlns/" && node.Value == JsonNamespaceUri)
+                        return;
+
+                    if (node.NamespaceUri == JsonNamespaceUri)
+                    {
+                        if (node.LocalName == "Array")
+                            return;
+                    }
+
+                    if (writePropertyName)
+                        writer.WritePropertyName(GetPropertyName(node, manager));
+                    writer.WriteValue(node.Value);
+                    break;
+                case XmlNodeType.XmlDeclaration:
+                    IXmlDeclaration declaration = (IXmlDeclaration)node;
+                    writer.WritePropertyName(GetPropertyName(node, manager));
+                    writer.WriteStartObject();
+
+                    if (!string.IsNullOrEmpty(declaration.Version))
+                    {
+                        writer.WritePropertyName("@version");
+                        writer.WriteValue(declaration.Version);
+                    }
+                    if (!string.IsNullOrEmpty(declaration.Encoding))
+                    {
+                        writer.WritePropertyName("@encoding");
+                        writer.WriteValue(declaration.Encoding);
+                    }
+                    if (!string.IsNullOrEmpty(declaration.Standalone))
+                    {
+                        writer.WritePropertyName("@standalone");
+                        writer.WriteValue(declaration.Standalone);
+                    }
+
+                    writer.WriteEndObject();
+                    break;
+                case XmlNodeType.DocumentType:
+                    IXmlDocumentType documentType = (IXmlDocumentType)node;
+                    writer.WritePropertyName(GetPropertyName(node, manager));
+                    writer.WriteStartObject();
+
+                    if (!string.IsNullOrEmpty(documentType.Name))
+                    {
+                        writer.WritePropertyName("@name");
+                        writer.WriteValue(documentType.Name);
+                    }
+                    if (!string.IsNullOrEmpty(documentType.Public))
+                    {
+                        writer.WritePropertyName("@public");
+                        writer.WriteValue(documentType.Public);
+                    }
+                    if (!string.IsNullOrEmpty(documentType.System))
+                    {
+                        writer.WritePropertyName("@system");
+                        writer.WriteValue(documentType.System);
+                    }
+                    if (!string.IsNullOrEmpty(documentType.InternalSubset))
+                    {
+                        writer.WritePropertyName("@internalSubset");
+                        writer.WriteValue(documentType.InternalSubset);
+                    }
+
+                    writer.WriteEndObject();
+                    break;
+                default:
+                    throw new JsonSerializationException("Unexpected XmlNodeType when serializing nodes: " + node.NodeType);
+            }
+        }
+        #endregion
+
+        #region Reading
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+        {
+            if (reader.TokenType == JsonToken.Null)
+                return null;
+
+            XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
+            IXmlDocument document = null;
+            IXmlNode rootNode = null;
+
+#if !NET20
+            if (typeof(XObject).IsAssignableFrom(objectType))
+            {
+                if (objectType != typeof(XDocument) && objectType != typeof(XElement))
+                    throw new JsonSerializationException("XmlNodeConverter only supports deserializing XDocument or XElement.");
+
+                XDocument d = new XDocument();
+                document = new XDocumentWrapper(d);
+                rootNode = document;
+            }
+#endif
+#if !(NETFX_CORE || PORTABLE)
+            if (typeof(XmlNode).IsAssignableFrom(objectType))
+            {
+                if (objectType != typeof(XmlDocument))
+                    throw new JsonSerializationException("XmlNodeConverter only supports deserializing XmlDocuments");
+
+                XmlDocument d = new XmlDocument();
+                document = new XmlDocumentWrapper(d);
+                rootNode = document;
+            }
+#endif
+
+            if (document == null || rootNode == null)
+                throw new JsonSerializationException("Unexpected type when converting XML: " + objectType);
+
+            if (reader.TokenType != JsonToken.StartObject)
+                throw new JsonSerializationException("XmlNodeConverter can only convert JSON that begins with an object.");
+
+            if (!string.IsNullOrEmpty(DeserializeRootElementName))
+            {
+                //rootNode = document.CreateElement(DeserializeRootElementName);
+                //document.AppendChild(rootNode);
+                ReadElement(reader, document, rootNode, DeserializeRootElementName, manager);
+            }
+            else
+            {
+                reader.Read();
+                DeserializeNode(reader, document, manager, rootNode);
+            }
+
+#if !NET20
+            if (objectType == typeof(XElement))
+            {
+                XElement element = (XElement)document.DocumentElement.WrappedNode;
+                element.Remove();
+
+                return element;
+            }
+#endif
+
+            return document.WrappedNode;
+        }
+
+        private void DeserializeValue(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, string propertyName, IXmlNode currentNode)
+        {
+            switch (propertyName)
+            {
+                case TextName:
+                    currentNode.AppendChild(document.CreateTextNode(reader.Value.ToString()));
+                    break;
+                case CDataName:
+                    currentNode.AppendChild(document.CreateCDataSection(reader.Value.ToString()));
+                    break;
+                case WhitespaceName:
+                    currentNode.AppendChild(document.CreateWhitespace(reader.Value.ToString()));
+                    break;
+                case SignificantWhitespaceName:
+                    currentNode.AppendChild(document.CreateSignificantWhitespace(reader.Value.ToString()));
+                    break;
+                default:
+                    // processing instructions and the xml declaration start with ?
+                    if (!string.IsNullOrEmpty(propertyName) && propertyName[0] == '?')
+                    {
+                        CreateInstruction(reader, document, currentNode, propertyName);
+                    }
+                    else if (string.Equals(propertyName, "!DOCTYPE", StringComparison.OrdinalIgnoreCase))
+                    {
+                        CreateDocumentType(reader, document, currentNode);
+                    }
+                    else
+                    {
+                        if (reader.TokenType == JsonToken.StartArray)
+                        {
+                            // handle nested arrays
+                            ReadArrayElements(reader, document, propertyName, currentNode, manager);
+                            return;
+                        }
+
+                        // have to wait until attributes have been parsed before creating element
+                        // attributes may contain namespace info used by the element
+                        ReadElement(reader, document, currentNode, propertyName, manager);
+                    }
+                    break;
+            }
+        }
+
+        private void ReadElement(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName, XmlNamespaceManager manager)
+        {
+            if (string.IsNullOrEmpty(propertyName))
+                throw new JsonSerializationException("XmlNodeConverter cannot convert JSON with an empty property name to XML.");
+
+            Dictionary<string, string> attributeNameValues = ReadAttributeElements(reader, manager);
+
+            string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
+
+            if (propertyName.StartsWith("@"))
+            {
+                string attributeName = propertyName.Substring(1);
+                string attributeValue = reader.Value.ToString();
+
+                string attributePrefix = MiscellaneousUtils.GetPrefix(attributeName);
+
+                IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
+                    ? document.CreateAttribute(attributeName, manager.LookupNamespace(attributePrefix), attributeValue)
+                    : document.CreateAttribute(attributeName, attributeValue);
+
+                ((IXmlElement)currentNode).SetAttributeNode(attribute);
+            }
+            else
+            {
+                IXmlElement element = CreateElement(propertyName, document, elementPrefix, manager);
+
+                currentNode.AppendChild(element);
+
+                // add attributes to newly created element
+                foreach (KeyValuePair<string, string> nameValue in attributeNameValues)
+                {
+                    string attributePrefix = MiscellaneousUtils.GetPrefix(nameValue.Key);
+
+                    IXmlNode attribute = (!string.IsNullOrEmpty(attributePrefix))
+                        ? document.CreateAttribute(nameValue.Key, manager.LookupNamespace(attributePrefix), nameValue.Value)
+                        : document.CreateAttribute(nameValue.Key, nameValue.Value);
+
+                    element.SetAttributeNode(attribute);
+                }
+
+                if (reader.TokenType == JsonToken.String
+                    || reader.TokenType == JsonToken.Integer
+                    || reader.TokenType == JsonToken.Float
+                    || reader.TokenType == JsonToken.Boolean
+                    || reader.TokenType == JsonToken.Date)
+                {
+                    element.AppendChild(document.CreateTextNode(ConvertTokenToXmlValue(reader)));
+                }
+                else if (reader.TokenType == JsonToken.Null)
+                {
+                    // empty element. do nothing
+                }
+                else
+                {
+                    // finished element will have no children to deserialize
+                    if (reader.TokenType != JsonToken.EndObject)
+                    {
+                        manager.PushScope();
+                        DeserializeNode(reader, document, manager, element);
+                        manager.PopScope();
+                    }
+
+                    manager.RemoveNamespace(string.Empty, manager.DefaultNamespace);
+                }
+            }
+        }
+
+        private string ConvertTokenToXmlValue(JsonReader reader)
+        {
+            if (reader.TokenType == JsonToken.String)
+            {
+                return reader.Value.ToString();
+            }
+            else if (reader.TokenType == JsonToken.Integer)
+            {
+                return XmlConvert.ToString(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
+            }
+            else if (reader.TokenType == JsonToken.Float)
+            {
+                if (reader.Value is decimal)
+                    return XmlConvert.ToString((decimal)reader.Value);
+                if (reader.Value is float)
+                    return XmlConvert.ToString((float)reader.Value);
+                
+                return XmlConvert.ToString(Convert.ToDouble(reader.Value, CultureInfo.InvariantCulture));
+            }
+            else if (reader.TokenType == JsonToken.Boolean)
+            {
+                return XmlConvert.ToString(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+            }
+            else if (reader.TokenType == JsonToken.Date)
+            {
+#if !NET20
+                if (reader.Value is DateTimeOffset)
+                    return XmlConvert.ToString((DateTimeOffset)reader.Value);
+#endif
+
+                DateTime d = Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture);
+#if !(NETFX_CORE || PORTABLE)
+                return XmlConvert.ToString(d, DateTimeUtils.ToSerializationMode(d.Kind));
+#else
+                return XmlConvert.ToString(d);
+#endif
+            }
+            else if (reader.TokenType == JsonToken.Null)
+            {
+                return null;
+            }
+            else
+            {
+                throw JsonSerializationException.Create(reader, "Cannot get an XML string value from token type '{0}'.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+        }
+
+        private void ReadArrayElements(JsonReader reader, IXmlDocument document, string propertyName, IXmlNode currentNode, XmlNamespaceManager manager)
+        {
+            string elementPrefix = MiscellaneousUtils.GetPrefix(propertyName);
+
+            IXmlElement nestedArrayElement = CreateElement(propertyName, document, elementPrefix, manager);
+
+            currentNode.AppendChild(nestedArrayElement);
+
+            int count = 0;
+            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+            {
+                DeserializeValue(reader, document, manager, propertyName, nestedArrayElement);
+                count++;
+            }
+
+            if (WriteArrayAttribute)
+            {
+                AddJsonArrayAttribute(nestedArrayElement, document);
+            }
+
+            if (count == 1 && WriteArrayAttribute)
+            {
+                IXmlElement arrayElement = nestedArrayElement.ChildNodes.OfType<IXmlElement>().Single(n => n.LocalName == propertyName);
+                AddJsonArrayAttribute(arrayElement, document);
+            }
+        }
+
+        private void AddJsonArrayAttribute(IXmlElement element, IXmlDocument document)
+        {
+            element.SetAttributeNode(document.CreateAttribute("json:Array", JsonNamespaceUri, "true"));
+
+#if !NET20
+            // linq to xml doesn't automatically include prefixes via the namespace manager
+            if (element is XElementWrapper)
+            {
+                if (element.GetPrefixOfNamespace(JsonNamespaceUri) == null)
+                {
+                    element.SetAttributeNode(document.CreateAttribute("xmlns:json", "http://www.w3.org/2000/xmlns/", JsonNamespaceUri));
+                }
+            }
+#endif
+        }
+
+        private Dictionary<string, string> ReadAttributeElements(JsonReader reader, XmlNamespaceManager manager)
+        {
+            Dictionary<string, string> attributeNameValues = new Dictionary<string, string>();
+            bool finishedAttributes = false;
+            bool finishedElement = false;
+
+            // a string token means the element only has a single text child
+            if (reader.TokenType != JsonToken.String
+                && reader.TokenType != JsonToken.Null
+                && reader.TokenType != JsonToken.Boolean
+                && reader.TokenType != JsonToken.Integer
+                && reader.TokenType != JsonToken.Float
+                && reader.TokenType != JsonToken.Date
+                && reader.TokenType != JsonToken.StartConstructor)
+            {
+                // read properties until first non-attribute is encountered
+                while (!finishedAttributes && !finishedElement && reader.Read())
+                {
+                    switch (reader.TokenType)
+                    {
+                        case JsonToken.PropertyName:
+                            string attributeName = reader.Value.ToString();
+
+                            if (!string.IsNullOrEmpty(attributeName))
+                            {
+                                char firstChar = attributeName[0];
+                                string attributeValue;
+
+                                switch (firstChar)
+                                {
+                                    case '@':
+                                        attributeName = attributeName.Substring(1);
+                                        reader.Read();
+                                        attributeValue = ConvertTokenToXmlValue(reader);
+                                        attributeNameValues.Add(attributeName, attributeValue);
+
+                                        string namespacePrefix;
+                                        if (IsNamespaceAttribute(attributeName, out namespacePrefix))
+                                        {
+                                            manager.AddNamespace(namespacePrefix, attributeValue);
+                                        }
+                                        break;
+                                    case '$':
+                                        attributeName = attributeName.Substring(1);
+                                        reader.Read();
+                                        attributeValue = reader.Value.ToString();
+
+                                        // check that JsonNamespaceUri is in scope
+                                        // if it isn't then add it to document and namespace manager
+                                        string jsonPrefix = manager.LookupPrefix(JsonNamespaceUri);
+                                        if (jsonPrefix == null)
+                                        {
+                                            // ensure that the prefix used is free
+                                            int? i = null;
+                                            while (manager.LookupNamespace("json" + i) != null)
+                                            {
+                                                i = i.GetValueOrDefault() + 1;
+                                            }
+                                            jsonPrefix = "json" + i;
+
+                                            attributeNameValues.Add("xmlns:" + jsonPrefix, JsonNamespaceUri);
+                                            manager.AddNamespace(jsonPrefix, JsonNamespaceUri);
+                                        }
+
+                                        attributeNameValues.Add(jsonPrefix + ":" + attributeName, attributeValue);
+                                        break;
+                                    default:
+                                        finishedAttributes = true;
+                                        break;
+                                }
+                            }
+                            else
+                            {
+                               
+                                finishedAttributes = true;
+                            }
+
+                            break;
+                        case JsonToken.EndObject:
+                            finishedElement = true;
+                            break;
+                        default:
+                            throw new JsonSerializationException("Unexpected JsonToken: " + reader.TokenType);
+                    }
+                }
+            }
+
+            return attributeNameValues;
+        }
+
+        private void CreateInstruction(JsonReader reader, IXmlDocument document, IXmlNode currentNode, string propertyName)
+        {
+            if (propertyName == DeclarationName)
+            {
+                string version = null;
+                string encoding = null;
+                string standalone = null;
+                while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+                {
+                    switch (reader.Value.ToString())
+                    {
+                        case "@version":
+                            reader.Read();
+                            version = reader.Value.ToString();
+                            break;
+                        case "@encoding":
+                            reader.Read();
+                            encoding = reader.Value.ToString();
+                            break;
+                        case "@standalone":
+                            reader.Read();
+                            standalone = reader.Value.ToString();
+                            break;
+                        default:
+                            throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
+                    }
+                }
+
+                IXmlNode declaration = document.CreateXmlDeclaration(version, encoding, standalone);
+                currentNode.AppendChild(declaration);
+            }
+            else
+            {
+                IXmlNode instruction = document.CreateProcessingInstruction(propertyName.Substring(1), reader.Value.ToString());
+                currentNode.AppendChild(instruction);
+            }
+        }
+
+        private void CreateDocumentType(JsonReader reader, IXmlDocument document, IXmlNode currentNode)
+        {
+            string name = null;
+            string publicId = null;
+            string systemId = null;
+            string internalSubset = null;
+            while (reader.Read() && reader.TokenType != JsonToken.EndObject)
+            {
+                switch (reader.Value.ToString())
+                {
+                    case "@name":
+                        reader.Read();
+                        name = reader.Value.ToString();
+                        break;
+                    case "@public":
+                        reader.Read();
+                        publicId = reader.Value.ToString();
+                        break;
+                    case "@system":
+                        reader.Read();
+                        systemId = reader.Value.ToString();
+                        break;
+                    case "@internalSubset":
+                        reader.Read();
+                        internalSubset = reader.Value.ToString();
+                        break;
+                    default:
+                        throw new JsonSerializationException("Unexpected property name encountered while deserializing XmlDeclaration: " + reader.Value);
+                }
+            }
+
+            IXmlNode documentType = document.CreateXmlDocumentType(name, publicId, systemId, internalSubset);
+            currentNode.AppendChild(documentType);
+        }
+
+        private IXmlElement CreateElement(string elementName, IXmlDocument document, string elementPrefix, XmlNamespaceManager manager)
+        {
+            string ns = string.IsNullOrEmpty(elementPrefix) ? manager.DefaultNamespace : manager.LookupNamespace(elementPrefix);
+
+            IXmlElement element = (!string.IsNullOrEmpty(ns)) ? document.CreateElement(elementName, ns) : document.CreateElement(elementName);
+
+            return element;
+        }
+
+        private void DeserializeNode(JsonReader reader, IXmlDocument document, XmlNamespaceManager manager, IXmlNode currentNode)
+        {
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        if (currentNode.NodeType == XmlNodeType.Document && document.DocumentElement != null)
+                            throw new JsonSerializationException("JSON root object has multiple properties. The root object must have a single property in order to create a valid XML document. Consider specifing a DeserializeRootElementName.");
+
+                        string propertyName = reader.Value.ToString();
+                        reader.Read();
+
+                        if (reader.TokenType == JsonToken.StartArray)
+                        {
+                            int count = 0;
+                            while (reader.Read() && reader.TokenType != JsonToken.EndArray)
+                            {
+                                DeserializeValue(reader, document, manager, propertyName, currentNode);
+                                count++;
+                            }
+
+                            if (count == 1 && WriteArrayAttribute)
+                            {
+                                IXmlElement arrayElement = currentNode.ChildNodes.OfType<IXmlElement>().Single(n => n.LocalName == propertyName);
+                                AddJsonArrayAttribute(arrayElement, document);
+                            }
+                        }
+                        else
+                        {
+                            DeserializeValue(reader, document, manager, propertyName, currentNode);
+                        }
+                        break;
+                    case JsonToken.StartConstructor:
+                        string constructorName = reader.Value.ToString();
+
+                        while (reader.Read() && reader.TokenType != JsonToken.EndConstructor)
+                        {
+                            DeserializeValue(reader, document, manager, constructorName, currentNode);
+                        }
+                        break;
+                    case JsonToken.Comment:
+                        currentNode.AppendChild(document.CreateComment((string)reader.Value));
+                        break;
+                    case JsonToken.EndObject:
+                    case JsonToken.EndArray:
+                        return;
+                    default:
+                        throw new JsonSerializationException("Unexpected JsonToken when deserializing node: " + reader.TokenType);
+                }
+            } while (reader.TokenType == JsonToken.PropertyName || reader.Read());
+            // don't read if current token is a property. token was already read when parsing element attributes
+        }
+
+        /// <summary>
+        /// Checks if the attributeName is a namespace attribute.
+        /// </summary>
+        /// <param name="attributeName">Attribute name to test.</param>
+        /// <param name="prefix">The attribute name prefix if it has one, otherwise an empty string.</param>
+        /// <returns>True if attribute name is for a namespace attribute, otherwise false.</returns>
+        private bool IsNamespaceAttribute(string attributeName, out string prefix)
+        {
+            if (attributeName.StartsWith("xmlns", StringComparison.Ordinal))
+            {
+                if (attributeName.Length == 5)
+                {
+                    prefix = string.Empty;
+                    return true;
+                }
+                else if (attributeName[5] == ':')
+                {
+                    prefix = attributeName.Substring(6, attributeName.Length - 6);
+                    return true;
+                }
+            }
+            prefix = null;
+            return false;
+        }
+
+        private IEnumerable<IXmlNode> ValueAttributes(IEnumerable<IXmlNode> c)
+        {
+            return c.Where(a => a.NamespaceUri != JsonNamespaceUri);
+        }
+        #endregion
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified value type.
+        /// </summary>
+        /// <param name="valueType">Type of the value.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified value type; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool CanConvert(Type valueType)
+        {
+#if !NET20
+            if (typeof(XObject).IsAssignableFrom(valueType))
+                return true;
+#endif
+#if !(NETFX_CORE || PORTABLE)
+            if (typeof(XmlNode).IsAssignableFrom(valueType))
+                return true;
+#endif
+
+            return false;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/DateFormatHandling.cs b/Newtonsoft.Json/DateFormatHandling.cs
new file mode 100644
index 0000000..2f884c3
--- /dev/null
+++ b/Newtonsoft.Json/DateFormatHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how dates are formatted when writing JSON text.
+    /// </summary>
+    public enum DateFormatHandling
+    {
+        /// <summary>
+        /// Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z".
+        /// </summary>
+        IsoDateFormat,
+
+        /// <summary>
+        /// Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/".
+        /// </summary>
+        MicrosoftDateFormat
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/DateParseHandling.cs b/Newtonsoft.Json/DateParseHandling.cs
new file mode 100644
index 0000000..0c9bd1a
--- /dev/null
+++ b/Newtonsoft.Json/DateParseHandling.cs
@@ -0,0 +1,49 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text.
+    /// </summary>
+    public enum DateParseHandling
+    {
+        /// <summary>
+        /// Date formatted strings are not parsed to a date type and are read as strings.
+        /// </summary>
+        None,
+
+        /// <summary>
+        /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to <see cref="DateTime"/>.
+        /// </summary>
+        DateTime,
+#if !NET20
+        /// <summary>
+        /// Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to <see cref="DateTimeOffset"/>.
+        /// </summary>
+        DateTimeOffset
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/DateTimeZoneHandling.cs b/Newtonsoft.Json/DateTimeZoneHandling.cs
new file mode 100644
index 0000000..38db347
--- /dev/null
+++ b/Newtonsoft.Json/DateTimeZoneHandling.cs
@@ -0,0 +1,56 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how to treat the time value when converting between string and <see cref="DateTime"/>.
+    /// </summary>
+    public enum DateTimeZoneHandling
+    {
+        /// <summary>
+        /// Treat as local time. If the <see cref="DateTime"/> object represents a Coordinated Universal Time (UTC), it is converted to the local time.
+        /// </summary>
+        Local,
+
+        /// <summary>
+        /// Treat as a UTC. If the <see cref="DateTime"/> object represents a local time, it is converted to a UTC.
+        /// </summary>
+        Utc,
+
+        /// <summary>
+        /// Treat as a local time if a <see cref="DateTime"/> is being converted to a string.
+        /// If a string is being converted to <see cref="DateTime"/>, convert to a local time if a time zone is specified.
+        /// </summary>
+        Unspecified,
+
+        /// <summary>
+        /// Time zone information should be preserved when converting.
+        /// </summary>
+        RoundtripKind
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/DefaultValueHandling.cs b/Newtonsoft.Json/DefaultValueHandling.cs
new file mode 100644
index 0000000..f9d3806
--- /dev/null
+++ b/Newtonsoft.Json/DefaultValueHandling.cs
@@ -0,0 +1,67 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.ComponentModel;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies default value handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeDefaultValueHandlingObject" title="DefaultValueHandling Class" />
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeDefaultValueHandlingExample" title="DefaultValueHandling Ignore Example" />
+    /// </example>
+    [Flags]
+    public enum DefaultValueHandling
+    {
+        /// <summary>
+        /// Include members where the member value is the same as the member's default value when serializing objects.
+        /// Included members are written to JSON. Has no effect when deserializing.
+        /// </summary>
+        Include = 0,
+
+        /// <summary>
+        /// Ignore members where the member value is the same as the member's default value when serializing objects
+        /// so that is is not written to JSON.
+        /// This option will ignore all default values (e.g. <c>null</c> for objects and nullable types; <c>0</c> for integers,
+        /// decimals and floating point numbers; and <c>false</c> for booleans). The default value ignored can be changed by
+        /// placing the <see cref="DefaultValueAttribute"/> on the property.
+        /// </summary>
+        Ignore = 1,
+
+        /// <summary>
+        /// Members with a default value but no JSON will be set to their default value when deserializing.
+        /// </summary>
+        Populate = 2,
+
+        /// <summary>
+        /// Ignore members where the member value is the same as the member's default value when serializing objects
+        /// and sets members to their default value when deserializing.
+        /// </summary>
+        IgnoreAndPopulate = Ignore | Populate
+    }
+}
diff --git a/Newtonsoft.Json/Dynamic.snk b/Newtonsoft.Json/Dynamic.snk
new file mode 100644
index 0000000..2225208
Binary files /dev/null and b/Newtonsoft.Json/Dynamic.snk differ
diff --git a/Newtonsoft.Json/FloatFormatHandling.cs b/Newtonsoft.Json/FloatFormatHandling.cs
new file mode 100644
index 0000000..09fe40a
--- /dev/null
+++ b/Newtonsoft.Json/FloatFormatHandling.cs
@@ -0,0 +1,50 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies float format handling options when writing special floating point numbers, e.g. <see cref="F:System.Double.NaN"/>,
+    /// <see cref="F:System.Double.PositiveInfinity"/> and <see cref="F:System.Double.NegativeInfinity"/> with <see cref="JsonWriter"/>.
+    /// </summary>
+    public enum FloatFormatHandling
+    {
+        /// <summary>
+        /// Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity".
+        /// </summary>
+        String,
+
+        /// <summary>
+        /// Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity.
+        /// Note that this will produce non-valid JSON.
+        /// </summary>
+        Symbol,
+
+        /// <summary>
+        /// Write special floating point values as the property's default value in JSON, e.g. 0.0 for a <see cref="System.Double"/> property, null for a <see cref="System.Nullable{Double}"/> property.
+        /// </summary>
+        DefaultValue
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/FloatParseHandling.cs b/Newtonsoft.Json/FloatParseHandling.cs
new file mode 100644
index 0000000..3cf09d4
--- /dev/null
+++ b/Newtonsoft.Json/FloatParseHandling.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+    /// </summary>
+    public enum FloatParseHandling
+    {
+        /// <summary>
+        /// Floating point numbers are parsed to <see cref="Double"/>.
+        /// </summary>
+        Double,
+
+        /// <summary>
+        /// Floating point numbers are parsed to <see cref="Decimal"/>.
+        /// </summary>
+        Decimal
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/FormatterAssemblyStyle.cs b/Newtonsoft.Json/FormatterAssemblyStyle.cs
new file mode 100644
index 0000000..5730d9c
--- /dev/null
+++ b/Newtonsoft.Json/FormatterAssemblyStyle.cs
@@ -0,0 +1,23 @@
+
+#if PocketPC || NETFX_CORE || PORTABLE40 || PORTABLE
+
+namespace System.Runtime.Serialization.Formatters
+{
+    /// <summary>
+    /// Indicates the method that will be used during deserialization for locating and loading assemblies.
+    /// </summary>
+    public enum FormatterAssemblyStyle
+    {
+        /// <summary>
+        /// In simple mode, the assembly used during deserialization need not match exactly the assembly used during serialization. Specifically, the version numbers need not match as the LoadWithPartialName method is used to load the assembly.
+        /// </summary>
+        Simple,
+
+        /// <summary>
+        /// In full mode, the assembly used during deserialization must match exactly the assembly used during serialization. The Load method of the Assembly class is used to load the assembly.
+        /// </summary>
+        Full
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Formatting.cs b/Newtonsoft.Json/Formatting.cs
new file mode 100644
index 0000000..64ab143
--- /dev/null
+++ b/Newtonsoft.Json/Formatting.cs
@@ -0,0 +1,43 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies formatting options for the <see cref="JsonTextWriter"/>.
+    /// </summary>
+    public enum Formatting
+    {
+        /// <summary>
+        /// No special formatting is applied. This is the default.
+        /// </summary>
+        None,
+
+        /// <summary>
+        /// Causes child objects to be indented according to the <see cref="JsonTextWriter.Indentation"/> and <see cref="JsonTextWriter.IndentChar"/> settings.
+        /// </summary>
+        Indented
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/IJsonLineInfo.cs b/Newtonsoft.Json/IJsonLineInfo.cs
new file mode 100644
index 0000000..cbacc10
--- /dev/null
+++ b/Newtonsoft.Json/IJsonLineInfo.cs
@@ -0,0 +1,53 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Provides an interface to enable a class to return line and position information.
+    /// </summary>
+    public interface IJsonLineInfo
+    {
+        /// <summary>
+        /// Gets a value indicating whether the class can return line information.
+        /// </summary>
+        /// <returns>
+        /// 	<c>true</c> if LineNumber and LinePosition can be provided; otherwise, <c>false</c>.
+        /// </returns>
+        bool HasLineInfo();
+
+        /// <summary>
+        /// Gets the current line number.
+        /// </summary>
+        /// <value>The current line number or 0 if no line information is available (for example, HasLineInfo returns false).</value>
+        int LineNumber { get; }
+
+        /// <summary>
+        /// Gets the current line position.
+        /// </summary>
+        /// <value>The current line position or 0 if no line information is available (for example, HasLineInfo returns false).</value>
+        int LinePosition { get; }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonArrayAttribute.cs b/Newtonsoft.Json/JsonArrayAttribute.cs
new file mode 100644
index 0000000..338466c
--- /dev/null
+++ b/Newtonsoft.Json/JsonArrayAttribute.cs
@@ -0,0 +1,73 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> how to serialize the collection.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+    public sealed class JsonArrayAttribute : JsonContainerAttribute
+    {
+        private bool _allowNullItems;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether null items are allowed in the collection.
+        /// </summary>
+        /// <value><c>true</c> if null items are allowed in the collection; otherwise, <c>false</c>.</value>
+        public bool AllowNullItems
+        {
+            get { return _allowNullItems; }
+            set { _allowNullItems = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonArrayAttribute"/> class.
+        /// </summary>
+        public JsonArrayAttribute()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonObjectAttribute"/> class with a flag indicating whether the array can contain null items
+        /// </summary>
+        /// <param name="allowNullItems">A flag indicating whether the array can contain null items.</param>
+        public JsonArrayAttribute(bool allowNullItems)
+        {
+            _allowNullItems = allowNullItems;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonArrayAttribute"/> class with the specified container Id.
+        /// </summary>
+        /// <param name="id">The container Id.</param>
+        public JsonArrayAttribute(string id)
+            : base(id)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonConstructorAttribute.cs b/Newtonsoft.Json/JsonConstructorAttribute.cs
new file mode 100644
index 0000000..d7eb044
--- /dev/null
+++ b/Newtonsoft.Json/JsonConstructorAttribute.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> to use the specified constructor when deserializing that object.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)]
+    public sealed class JsonConstructorAttribute : Attribute
+    {
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonContainerAttribute.cs b/Newtonsoft.Json/JsonContainerAttribute.cs
new file mode 100644
index 0000000..9c70885
--- /dev/null
+++ b/Newtonsoft.Json/JsonContainerAttribute.cs
@@ -0,0 +1,127 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> how to serialize the object.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+    public abstract class JsonContainerAttribute : Attribute
+    {
+        /// <summary>
+        /// Gets or sets the id.
+        /// </summary>
+        /// <value>The id.</value>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// Gets or sets the title.
+        /// </summary>
+        /// <value>The title.</value>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// Gets or sets the description.
+        /// </summary>
+        /// <value>The description.</value>
+        public string Description { get; set; }
+
+        /// <summary>
+        /// Gets the collection's items converter.
+        /// </summary>
+        /// <value>The collection's items converter.</value>
+        public Type ItemConverterType { get; set; }
+
+        // yuck. can't set nullable properties on an attribute in C#
+        // have to use this approach to get an unset default state
+        internal bool? _isReference;
+        internal bool? _itemIsReference;
+        internal ReferenceLoopHandling? _itemReferenceLoopHandling;
+        internal TypeNameHandling? _itemTypeNameHandling;
+
+        /// <summary>
+        /// Gets or sets a value that indicates whether to preserve object references.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> to keep object reference; otherwise, <c>false</c>. The default is <c>false</c>.
+        /// </value>
+        public bool IsReference
+        {
+            get { return _isReference ?? default(bool); }
+            set { _isReference = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value that indicates whether to preserve collection's items references.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> to keep collection's items object references; otherwise, <c>false</c>. The default is <c>false</c>.
+        /// </value>
+        public bool ItemIsReference
+        {
+            get { return _itemIsReference ?? default(bool); }
+            set { _itemIsReference = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the reference loop handling used when serializing the collection's items.
+        /// </summary>
+        /// <value>The reference loop handling.</value>
+        public ReferenceLoopHandling ItemReferenceLoopHandling
+        {
+            get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
+            set { _itemReferenceLoopHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the type name handling used when serializing the collection's items.
+        /// </summary>
+        /// <value>The type name handling.</value>
+        public TypeNameHandling ItemTypeNameHandling
+        {
+            get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
+            set { _itemTypeNameHandling = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonContainerAttribute"/> class.
+        /// </summary>
+        protected JsonContainerAttribute()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonContainerAttribute"/> class with the specified container Id.
+        /// </summary>
+        /// <param name="id">The container Id.</param>
+        protected JsonContainerAttribute(string id)
+        {
+            Id = id;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonConvert.cs b/Newtonsoft.Json/JsonConvert.cs
new file mode 100644
index 0000000..4ff2b63
--- /dev/null
+++ b/Newtonsoft.Json/JsonConvert.cs
@@ -0,0 +1,1117 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.IO;
+using System.Globalization;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+using System.Threading.Tasks;
+#endif
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+using System.Xml;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using System.Text;
+#if !(NET20 || PORTABLE40)
+using System.Xml.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Provides methods for converting between common language runtime types and JSON types.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="SerializeObject" title="Serializing and Deserializing JSON with JsonConvert" />
+    /// </example>
+    public static class JsonConvert
+    {
+        /// <summary>
+        /// Gets or sets a function that creates default <see cref="JsonSerializerSettings"/>.
+        /// Default settings are automatically used by serialization methods on <see cref="JsonConvert"/>,
+        /// and <see cref="JToken.ToObject{T}()"/> and <see cref="JToken.FromObject(object)"/> on <see cref="JToken"/>.
+        /// To serialize without using any default settings create a <see cref="JsonSerializer"/> with
+        /// <see cref="JsonSerializer.Create()"/>.
+        /// </summary>
+        public static Func<JsonSerializerSettings> DefaultSettings { get; set; }
+
+        /// <summary>
+        /// Represents JavaScript's boolean value true as a string. This field is read-only.
+        /// </summary>
+        public static readonly string True = "true";
+
+        /// <summary>
+        /// Represents JavaScript's boolean value false as a string. This field is read-only.
+        /// </summary>
+        public static readonly string False = "false";
+
+        /// <summary>
+        /// Represents JavaScript's null as a string. This field is read-only.
+        /// </summary>
+        public static readonly string Null = "null";
+
+        /// <summary>
+        /// Represents JavaScript's undefined as a string. This field is read-only.
+        /// </summary>
+        public static readonly string Undefined = "undefined";
+
+        /// <summary>
+        /// Represents JavaScript's positive infinity as a string. This field is read-only.
+        /// </summary>
+        public static readonly string PositiveInfinity = "Infinity";
+
+        /// <summary>
+        /// Represents JavaScript's negative infinity as a string. This field is read-only.
+        /// </summary>
+        public static readonly string NegativeInfinity = "-Infinity";
+
+        /// <summary>
+        /// Represents JavaScript's NaN as a string. This field is read-only.
+        /// </summary>
+        public static readonly string NaN = "NaN";
+
+        /// <summary>
+        /// Converts the <see cref="DateTime"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="DateTime"/>.</returns>
+        public static string ToString(DateTime value)
+        {
+            return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="DateTime"/> to its JSON string representation using the <see cref="DateFormatHandling"/> specified.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <param name="format">The format the date will be converted to.</param>
+        /// <param name="timeZoneHandling">The time zone handling when the date is converted to a string.</param>
+        /// <returns>A JSON string representation of the <see cref="DateTime"/>.</returns>
+        public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling)
+        {
+            DateTime updatedDateTime = DateTimeUtils.EnsureDateTime(value, timeZoneHandling);
+
+            using (StringWriter writer = StringUtils.CreateStringWriter(64))
+            {
+                writer.Write('"');
+                DateTimeUtils.WriteDateTimeString(writer, updatedDateTime, format, null, CultureInfo.InvariantCulture);
+                writer.Write('"');
+                return writer.ToString();
+            }
+        }
+
+#if !NET20
+        /// <summary>
+        /// Converts the <see cref="DateTimeOffset"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="DateTimeOffset"/>.</returns>
+        public static string ToString(DateTimeOffset value)
+        {
+            return ToString(value, DateFormatHandling.IsoDateFormat);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="DateTimeOffset"/> to its JSON string representation using the <see cref="DateFormatHandling"/> specified.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <param name="format">The format the date will be converted to.</param>
+        /// <returns>A JSON string representation of the <see cref="DateTimeOffset"/>.</returns>
+        public static string ToString(DateTimeOffset value, DateFormatHandling format)
+        {
+            using (StringWriter writer = StringUtils.CreateStringWriter(64))
+            {
+                writer.Write('"');
+                DateTimeUtils.WriteDateTimeOffsetString(writer, value, format, null, CultureInfo.InvariantCulture);
+                writer.Write('"');
+                return writer.ToString();
+            }
+        }
+#endif
+
+        /// <summary>
+        /// Converts the <see cref="Boolean"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Boolean"/>.</returns>
+        public static string ToString(bool value)
+        {
+            return (value) ? True : False;
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Char"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Char"/>.</returns>
+        public static string ToString(char value)
+        {
+            return ToString(char.ToString(value));
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Enum"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Enum"/>.</returns>
+        public static string ToString(Enum value)
+        {
+            return value.ToString("D");
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Int32"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Int32"/>.</returns>
+        public static string ToString(int value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Int16"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Int16"/>.</returns>
+        public static string ToString(short value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="UInt16"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="UInt16"/>.</returns>
+        [CLSCompliant(false)]
+        public static string ToString(ushort value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="UInt32"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="UInt32"/>.</returns>
+        [CLSCompliant(false)]
+        public static string ToString(uint value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Int64"/>  to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Int64"/>.</returns>
+        public static string ToString(long value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+        private static string ToStringInternal(BigInteger value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+#endif
+
+        /// <summary>
+        /// Converts the <see cref="UInt64"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="UInt64"/>.</returns>
+        [CLSCompliant(false)]
+        public static string ToString(ulong value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Single"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Single"/>.</returns>
+        public static string ToString(float value)
+        {
+            return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
+        }
+
+        internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+        {
+            return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
+        }
+
+        private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+        {
+            if (floatFormatHandling == FloatFormatHandling.Symbol || !(double.IsInfinity(value) || double.IsNaN(value)))
+                return text;
+
+            if (floatFormatHandling == FloatFormatHandling.DefaultValue)
+                return (!nullable) ? "0.0" : Null;
+
+            return quoteChar + text + quoteChar;
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Double"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Double"/>.</returns>
+        public static string ToString(double value)
+        {
+            return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture));
+        }
+
+        internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable)
+        {
+            return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable);
+        }
+
+        private static string EnsureDecimalPlace(double value, string text)
+        {
+            if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1)
+                return text;
+
+            return text + ".0";
+        }
+
+        private static string EnsureDecimalPlace(string text)
+        {
+            if (text.IndexOf('.') != -1)
+                return text;
+
+            return text + ".0";
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Byte"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Byte"/>.</returns>
+        public static string ToString(byte value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="SByte"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
+        [CLSCompliant(false)]
+        public static string ToString(sbyte value)
+        {
+            return value.ToString(null, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Decimal"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="SByte"/>.</returns>
+        public static string ToString(decimal value)
+        {
+            return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture));
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Guid"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Guid"/>.</returns>
+        public static string ToString(Guid value)
+        {
+            return ToString(value, '"');
+        }
+
+        internal static string ToString(Guid value, char quoteChar)
+        {
+            string text = null;
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            text = value.ToString("D", CultureInfo.InvariantCulture);
+#else
+            text = value.ToString("D");
+#endif
+
+            return quoteChar + text + quoteChar;
+        }
+
+        /// <summary>
+        /// Converts the <see cref="TimeSpan"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="TimeSpan"/>.</returns>
+        public static string ToString(TimeSpan value)
+        {
+            return ToString(value, '"');
+        }
+
+        internal static string ToString(TimeSpan value, char quoteChar)
+        {
+            return ToString(value.ToString(), quoteChar);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Uri"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Uri"/>.</returns>
+        public static string ToString(Uri value)
+        {
+            if (value == null)
+                return Null;
+
+            return ToString(value, '"');
+        }
+
+        internal static string ToString(Uri value, char quoteChar)
+        {
+            return ToString(value.OriginalString, quoteChar);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="String"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
+        public static string ToString(string value)
+        {
+            return ToString(value, '"');
+        }
+
+        /// <summary>
+        /// Converts the <see cref="String"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <param name="delimiter">The string delimiter character.</param>
+        /// <returns>A JSON string representation of the <see cref="String"/>.</returns>
+        public static string ToString(string value, char delimiter)
+        {
+            if (delimiter != '"' && delimiter != '\'')
+                throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter");
+
+            return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, true);
+        }
+
+        /// <summary>
+        /// Converts the <see cref="Object"/> to its JSON string representation.
+        /// </summary>
+        /// <param name="value">The value to convert.</param>
+        /// <returns>A JSON string representation of the <see cref="Object"/>.</returns>
+        public static string ToString(object value)
+        {
+            if (value == null)
+                return Null;
+
+            PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(value);
+
+            switch (typeCode)
+            {
+                case PrimitiveTypeCode.String:
+                    return ToString((string)value);
+                case PrimitiveTypeCode.Char:
+                    return ToString((char)value);
+                case PrimitiveTypeCode.Boolean:
+                    return ToString((bool)value);
+                case PrimitiveTypeCode.SByte:
+                    return ToString((sbyte)value);
+                case PrimitiveTypeCode.Int16:
+                    return ToString((short)value);
+                case PrimitiveTypeCode.UInt16:
+                    return ToString((ushort)value);
+                case PrimitiveTypeCode.Int32:
+                    return ToString((int)value);
+                case PrimitiveTypeCode.Byte:
+                    return ToString((byte)value);
+                case PrimitiveTypeCode.UInt32:
+                    return ToString((uint)value);
+                case PrimitiveTypeCode.Int64:
+                    return ToString((long)value);
+                case PrimitiveTypeCode.UInt64:
+                    return ToString((ulong)value);
+                case PrimitiveTypeCode.Single:
+                    return ToString((float)value);
+                case PrimitiveTypeCode.Double:
+                    return ToString((double)value);
+                case PrimitiveTypeCode.DateTime:
+                    return ToString((DateTime)value);
+                case PrimitiveTypeCode.Decimal:
+                    return ToString((decimal)value);
+#if !(NETFX_CORE || PORTABLE)
+                case PrimitiveTypeCode.DBNull:
+                    return Null;
+#endif
+#if !NET20
+                case PrimitiveTypeCode.DateTimeOffset:
+                    return ToString((DateTimeOffset)value);
+#endif
+                case PrimitiveTypeCode.Guid:
+                    return ToString((Guid)value);
+                case PrimitiveTypeCode.Uri:
+                    return ToString((Uri)value);
+                case PrimitiveTypeCode.TimeSpan:
+                    return ToString((TimeSpan)value);
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                case PrimitiveTypeCode.BigInteger:
+                    return ToStringInternal((BigInteger)value);
+#endif
+            }
+
+            throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+        }
+
+        #region Serialize
+        /// <summary>
+        /// Serializes the specified object to a JSON string.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <returns>A JSON string representation of the object.</returns>
+        public static string SerializeObject(object value)
+        {
+            return SerializeObject(value, null, (JsonSerializerSettings)null);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using formatting.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <returns>
+        /// A JSON string representation of the object.
+        /// </returns>
+        public static string SerializeObject(object value, Formatting formatting)
+        {
+            return SerializeObject(value, formatting, (JsonSerializerSettings)null);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using a collection of <see cref="JsonConverter"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="converters">A collection converters used while serializing.</param>
+        /// <returns>A JSON string representation of the object.</returns>
+        public static string SerializeObject(object value, params JsonConverter[] converters)
+        {
+            JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+                ? new JsonSerializerSettings { Converters = converters }
+                : null;
+
+            return SerializeObject(value, null, settings);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using formatting and a collection of <see cref="JsonConverter"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="converters">A collection converters used while serializing.</param>
+        /// <returns>A JSON string representation of the object.</returns>
+        public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters)
+        {
+            JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+                ? new JsonSerializerSettings { Converters = converters }
+                : null;
+
+            return SerializeObject(value, null, formatting, settings);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+        /// If this is null, default serialization settings will be is used.</param>
+        /// <returns>
+        /// A JSON string representation of the object.
+        /// </returns>
+        public static string SerializeObject(object value, JsonSerializerSettings settings)
+        {
+            return SerializeObject(value, null, settings);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+        /// If this is null, default serialization settings will be is used.</param>
+        /// <param name="type">
+        /// The type of the value being serialized.
+        /// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match.
+        /// Specifing the type is optional.
+        /// </param>
+        /// <returns>
+        /// A JSON string representation of the object.
+        /// </returns>
+        public static string SerializeObject(object value, Type type, JsonSerializerSettings settings)
+        {
+            JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+            return SerializeObjectInternal(value, type, jsonSerializer);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using formatting and <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+        /// If this is null, default serialization settings will be is used.</param>
+        /// <returns>
+        /// A JSON string representation of the object.
+        /// </returns>
+        public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings)
+        {
+            return SerializeObject(value, null, formatting, settings);
+        }
+
+        /// <summary>
+        /// Serializes the specified object to a JSON string using a type, formatting and <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+        /// If this is null, default serialization settings will be is used.</param>
+        /// <param name="type">
+        /// The type of the value being serialized.
+        /// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match.
+        /// Specifing the type is optional.
+        /// </param>
+        /// <returns>
+        /// A JSON string representation of the object.
+        /// </returns>
+        public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings)
+        {
+            JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+            jsonSerializer.Formatting = formatting;
+
+            return SerializeObjectInternal(value, type, jsonSerializer);
+        }
+
+        private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer)
+        {
+            StringBuilder sb = new StringBuilder(256);
+            StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
+            using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
+            {
+                jsonWriter.Formatting = jsonSerializer.Formatting;
+
+                jsonSerializer.Serialize(jsonWriter, value, type);
+            }
+
+            return sw.ToString();
+        }
+
+#if !(NET20 || NET35 || PORTABLE40)
+        /// <summary>
+        /// Asynchronously serializes the specified object to a JSON string.
+        /// Serialization will happen on a new thread.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <returns>
+        /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+        /// </returns>
+        [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value))")]
+        public static Task<string> SerializeObjectAsync(object value)
+        {
+            return SerializeObjectAsync(value, Formatting.None, null);
+        }
+
+        /// <summary>
+        /// Asynchronously serializes the specified object to a JSON string using formatting.
+        /// Serialization will happen on a new thread.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <returns>
+        /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+        /// </returns>
+        [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value, formatting))")]
+        public static Task<string> SerializeObjectAsync(object value, Formatting formatting)
+        {
+            return SerializeObjectAsync(value, formatting, null);
+        }
+
+        /// <summary>
+        /// Asynchronously serializes the specified object to a JSON string using formatting and a collection of <see cref="JsonConverter"/>.
+        /// Serialization will happen on a new thread.
+        /// </summary>
+        /// <param name="value">The object to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="settings">The <see cref="JsonSerializerSettings"/> used to serialize the object.
+        /// If this is null, default serialization settings will be is used.</param>
+        /// <returns>
+        /// A task that represents the asynchronous serialize operation. The value of the <c>TResult</c> parameter contains a JSON string representation of the object.
+        /// </returns>
+        [ObsoleteAttribute("SerializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to serialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.SerializeObject(value, formatting, settings))")]
+        public static Task<string> SerializeObjectAsync(object value, Formatting formatting, JsonSerializerSettings settings)
+        {
+            return Task.Factory.StartNew(() => SerializeObject(value, formatting, settings));
+        }
+#endif
+        #endregion
+
+        #region Deserialize
+        /// <summary>
+        /// Deserializes the JSON to a .NET object.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <returns>The deserialized object from the Json string.</returns>
+        public static object DeserializeObject(string value)
+        {
+            return DeserializeObject(value, null, (JsonSerializerSettings)null);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to a .NET object using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>The deserialized object from the JSON string.</returns>
+        public static object DeserializeObject(string value, JsonSerializerSettings settings)
+        {
+            return DeserializeObject(value, null, settings);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="type">The <see cref="Type"/> of object being deserialized.</param>
+        /// <returns>The deserialized object from the Json string.</returns>
+        public static object DeserializeObject(string value, Type type)
+        {
+            return DeserializeObject(value, type, (JsonSerializerSettings)null);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type.
+        /// </summary>
+        /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <returns>The deserialized object from the Json string.</returns>
+        public static T DeserializeObject<T>(string value)
+        {
+            return DeserializeObject<T>(value, (JsonSerializerSettings)null);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the given anonymous type.
+        /// </summary>
+        /// <typeparam name="T">
+        /// The anonymous type to deserialize to. This can't be specified
+        /// traditionally and must be infered from the anonymous type passed
+        /// as a parameter.
+        /// </typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="anonymousTypeObject">The anonymous type object.</param>
+        /// <returns>The deserialized anonymous type from the JSON string.</returns>
+        public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject)
+        {
+            return DeserializeObject<T>(value);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the given anonymous type using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <typeparam name="T">
+        /// The anonymous type to deserialize to. This can't be specified
+        /// traditionally and must be infered from the anonymous type passed
+        /// as a parameter.
+        /// </typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="anonymousTypeObject">The anonymous type object.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>The deserialized anonymous type from the JSON string.</returns>
+        public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings)
+        {
+            return DeserializeObject<T>(value, settings);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
+        /// </summary>
+        /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="converters">Converters to use while deserializing.</param>
+        /// <returns>The deserialized object from the JSON string.</returns>
+        public static T DeserializeObject<T>(string value, params JsonConverter[] converters)
+        {
+            return (T)DeserializeObject(value, typeof(T), converters);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+        /// <param name="value">The object to deserialize.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>The deserialized object from the JSON string.</returns>
+        public static T DeserializeObject<T>(string value, JsonSerializerSettings settings)
+        {
+            return (T)DeserializeObject(value, typeof(T), settings);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type using a collection of <see cref="JsonConverter"/>.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="type">The type of the object to deserialize.</param>
+        /// <param name="converters">Converters to use while deserializing.</param>
+        /// <returns>The deserialized object from the JSON string.</returns>
+        public static object DeserializeObject(string value, Type type, params JsonConverter[] converters)
+        {
+            JsonSerializerSettings settings = (converters != null && converters.Length > 0)
+                ? new JsonSerializerSettings { Converters = converters }
+                : null;
+
+            return DeserializeObject(value, type, settings);
+        }
+
+        /// <summary>
+        /// Deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="type">The type of the object to deserialize to.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>The deserialized object from the JSON string.</returns>
+        public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+
+            JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+            // by default DeserializeObject should check for additional content
+            if (!jsonSerializer.IsCheckAdditionalContentSet())
+                jsonSerializer.CheckAdditionalContent = true;
+
+            using (var reader = new JsonTextReader(new StringReader(value)))
+            {
+                return jsonSerializer.Deserialize(reader, type);
+            }
+        }
+
+#if !(NET20 || NET35 || PORTABLE40)
+        /// <summary>
+        /// Asynchronously deserializes the JSON to the specified .NET type.
+        /// Deserialization will happen on a new thread.
+        /// </summary>
+        /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <returns>
+        /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+        /// </returns>
+        [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(value))")]
+        public static Task<T> DeserializeObjectAsync<T>(string value)
+        {
+            return DeserializeObjectAsync<T>(value, null);
+        }
+
+        /// <summary>
+        /// Asynchronously deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
+        /// Deserialization will happen on a new thread.
+        /// </summary>
+        /// <typeparam name="T">The type of the object to deserialize to.</typeparam>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>
+        /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+        /// </returns>
+        [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(value, settings))")]
+        public static Task<T> DeserializeObjectAsync<T>(string value, JsonSerializerSettings settings)
+        {
+            return Task.Factory.StartNew(() => DeserializeObject<T>(value, settings));
+        }
+
+        /// <summary>
+        /// Asynchronously deserializes the JSON to the specified .NET type.
+        /// Deserialization will happen on a new thread.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <returns>
+        /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+        /// </returns>
+        [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value))")]
+        public static Task<object> DeserializeObjectAsync(string value)
+        {
+            return DeserializeObjectAsync(value, null, null);
+        }
+
+        /// <summary>
+        /// Asynchronously deserializes the JSON to the specified .NET type using <see cref="JsonSerializerSettings"/>.
+        /// Deserialization will happen on a new thread.
+        /// </summary>
+        /// <param name="value">The JSON to deserialize.</param>
+        /// <param name="type">The type of the object to deserialize to.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>
+        /// A task that represents the asynchronous deserialize operation. The value of the <c>TResult</c> parameter contains the deserialized object from the JSON string.
+        /// </returns>
+        [ObsoleteAttribute("DeserializeObjectAsync is obsolete. Use the Task.Factory.StartNew method to deserialize JSON asynchronously: Task.Factory.StartNew(() => JsonConvert.DeserializeObject(value, type, settings))")]
+        public static Task<object> DeserializeObjectAsync(string value, Type type, JsonSerializerSettings settings)
+        {
+            return Task.Factory.StartNew(() => DeserializeObject(value, type, settings));
+        }
+#endif
+        #endregion
+
+        /// <summary>
+        /// Populates the object with values from the JSON string.
+        /// </summary>
+        /// <param name="value">The JSON to populate values from.</param>
+        /// <param name="target">The target object to populate values onto.</param>
+        public static void PopulateObject(string value, object target)
+        {
+            PopulateObject(value, target, null);
+        }
+
+        /// <summary>
+        /// Populates the object with values from the JSON string using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The JSON to populate values from.</param>
+        /// <param name="target">The target object to populate values onto.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        public static void PopulateObject(string value, object target, JsonSerializerSettings settings)
+        {
+            JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings);
+
+            using (JsonReader jsonReader = new JsonTextReader(new StringReader(value)))
+            {
+                jsonSerializer.Populate(jsonReader, target);
+
+                if (jsonReader.Read() && jsonReader.TokenType != JsonToken.Comment)
+                    throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
+            }
+        }
+
+#if !(NET20 || NET35 || PORTABLE40)
+        /// <summary>
+        /// Asynchronously populates the object with values from the JSON string using <see cref="JsonSerializerSettings"/>.
+        /// </summary>
+        /// <param name="value">The JSON to populate values from.</param>
+        /// <param name="target">The target object to populate values onto.</param>
+        /// <param name="settings">
+        /// The <see cref="JsonSerializerSettings"/> used to deserialize the object.
+        /// If this is null, default serialization settings will be is used.
+        /// </param>
+        /// <returns>
+        /// A task that represents the asynchronous populate operation.
+        /// </returns>
+        [ObsoleteAttribute("PopulateObjectAsync is obsolete. Use the Task.Factory.StartNew method to populate an object with JSON values asynchronously: Task.Factory.StartNew(() => JsonConvert.PopulateObject(value, target, settings))")]
+        public static Task PopulateObjectAsync(string value, object target, JsonSerializerSettings settings)
+        {
+            return Task.Factory.StartNew(() => PopulateObject(value, target, settings));
+        }
+#endif
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+        /// <summary>
+        /// Serializes the XML node to a JSON string.
+        /// </summary>
+        /// <param name="node">The node to serialize.</param>
+        /// <returns>A JSON string of the XmlNode.</returns>
+        public static string SerializeXmlNode(XmlNode node)
+        {
+            return SerializeXmlNode(node, Formatting.None);
+        }
+
+        /// <summary>
+        /// Serializes the XML node to a JSON string using formatting.
+        /// </summary>
+        /// <param name="node">The node to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <returns>A JSON string of the XmlNode.</returns>
+        public static string SerializeXmlNode(XmlNode node, Formatting formatting)
+        {
+            XmlNodeConverter converter = new XmlNodeConverter();
+
+            return SerializeObject(node, formatting, converter);
+        }
+
+        /// <summary>
+        /// Serializes the XML node to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
+        /// </summary>
+        /// <param name="node">The node to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="omitRootObject">Omits writing the root object.</param>
+        /// <returns>A JSON string of the XmlNode.</returns>
+        public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject)
+        {
+            XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
+
+            return SerializeObject(node, formatting, converter);
+        }
+
+        /// <summary>
+        /// Deserializes the XmlNode from a JSON string.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <returns>The deserialized XmlNode</returns>
+        public static XmlDocument DeserializeXmlNode(string value)
+        {
+            return DeserializeXmlNode(value, null);
+        }
+
+        /// <summary>
+        /// Deserializes the XmlNode from a JSON string nested in a root elment specified by <paramref name="deserializeRootElementName"/>.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+        /// <returns>The deserialized XmlNode</returns>
+        public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName)
+        {
+            return DeserializeXmlNode(value, deserializeRootElementName, false);
+        }
+
+        /// <summary>
+        /// Deserializes the XmlNode from a JSON string nested in a root elment specified by <paramref name="deserializeRootElementName"/>
+        /// and writes a .NET array attribute for collections.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+        /// <param name="writeArrayAttribute">
+        /// A flag to indicate whether to write the Json.NET array attribute.
+        /// This attribute helps preserve arrays when converting the written XML back to JSON.
+        /// </param>
+        /// <returns>The deserialized XmlNode</returns>
+        public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+        {
+            XmlNodeConverter converter = new XmlNodeConverter();
+            converter.DeserializeRootElementName = deserializeRootElementName;
+            converter.WriteArrayAttribute = writeArrayAttribute;
+
+            return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), converter);
+        }
+#endif
+
+#if !NET20 && !PORTABLE40
+        /// <summary>
+        /// Serializes the <see cref="XNode"/> to a JSON string.
+        /// </summary>
+        /// <param name="node">The node to convert to JSON.</param>
+        /// <returns>A JSON string of the XNode.</returns>
+        public static string SerializeXNode(XObject node)
+        {
+            return SerializeXNode(node, Formatting.None);
+        }
+
+        /// <summary>
+        /// Serializes the <see cref="XNode"/> to a JSON string using formatting.
+        /// </summary>
+        /// <param name="node">The node to convert to JSON.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <returns>A JSON string of the XNode.</returns>
+        public static string SerializeXNode(XObject node, Formatting formatting)
+        {
+            return SerializeXNode(node, formatting, false);
+        }
+
+        /// <summary>
+        /// Serializes the <see cref="XNode"/> to a JSON string using formatting and omits the root object if <paramref name="omitRootObject"/> is <c>true</c>.
+        /// </summary>
+        /// <param name="node">The node to serialize.</param>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="omitRootObject">Omits writing the root object.</param>
+        /// <returns>A JSON string of the XNode.</returns>
+        public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject)
+        {
+            XmlNodeConverter converter = new XmlNodeConverter { OmitRootObject = omitRootObject };
+
+            return SerializeObject(node, formatting, converter);
+        }
+
+        /// <summary>
+        /// Deserializes the <see cref="XNode"/> from a JSON string.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <returns>The deserialized XNode</returns>
+        public static XDocument DeserializeXNode(string value)
+        {
+            return DeserializeXNode(value, null);
+        }
+
+        /// <summary>
+        /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root elment specified by <paramref name="deserializeRootElementName"/>.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+        /// <returns>The deserialized XNode</returns>
+        public static XDocument DeserializeXNode(string value, string deserializeRootElementName)
+        {
+            return DeserializeXNode(value, deserializeRootElementName, false);
+        }
+
+        /// <summary>
+        /// Deserializes the <see cref="XNode"/> from a JSON string nested in a root elment specified by <paramref name="deserializeRootElementName"/>
+        /// and writes a .NET array attribute for collections.
+        /// </summary>
+        /// <param name="value">The JSON string.</param>
+        /// <param name="deserializeRootElementName">The name of the root element to append when deserializing.</param>
+        /// <param name="writeArrayAttribute">
+        /// A flag to indicate whether to write the Json.NET array attribute.
+        /// This attribute helps preserve arrays when converting the written XML back to JSON.
+        /// </param>
+        /// <returns>The deserialized XNode</returns>
+        public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute)
+        {
+            XmlNodeConverter converter = new XmlNodeConverter();
+            converter.DeserializeRootElementName = deserializeRootElementName;
+            converter.WriteArrayAttribute = writeArrayAttribute;
+
+            return (XDocument)DeserializeObject(value, typeof(XDocument), converter);
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonConverter.cs b/Newtonsoft.Json/JsonConverter.cs
new file mode 100644
index 0000000..2e70996
--- /dev/null
+++ b/Newtonsoft.Json/JsonConverter.cs
@@ -0,0 +1,93 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Schema;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Converts an object to and from JSON.
+    /// </summary>
+    public abstract class JsonConverter
+    {
+        /// <summary>
+        /// Writes the JSON representation of the object.
+        /// </summary>
+        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer);
+
+        /// <summary>
+        /// Reads the JSON representation of the object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
+        /// <param name="objectType">Type of the object.</param>
+        /// <param name="existingValue">The existing value of object being read.</param>
+        /// <param name="serializer">The calling serializer.</param>
+        /// <returns>The object value.</returns>
+        public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer);
+
+        /// <summary>
+        /// Determines whether this instance can convert the specified object type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>
+        /// 	<c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
+        /// </returns>
+        public abstract bool CanConvert(Type objectType);
+
+        /// <summary>
+        /// Gets the <see cref="JsonSchema"/> of the JSON produced by the JsonConverter.
+        /// </summary>
+        /// <returns>The <see cref="JsonSchema"/> of the JSON produced by the JsonConverter.</returns>
+        public virtual JsonSchema GetSchema()
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this <see cref="JsonConverter"/> can read JSON.
+        /// </summary>
+        /// <value><c>true</c> if this <see cref="JsonConverter"/> can read JSON; otherwise, <c>false</c>.</value>
+        public virtual bool CanRead
+        {
+            get { return true; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this <see cref="JsonConverter"/> can write JSON.
+        /// </summary>
+        /// <value><c>true</c> if this <see cref="JsonConverter"/> can write JSON; otherwise, <c>false</c>.</value>
+        public virtual bool CanWrite
+        {
+            get { return true; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonConverterAttribute.cs b/Newtonsoft.Json/JsonConverterAttribute.cs
new file mode 100644
index 0000000..6480493
--- /dev/null
+++ b/Newtonsoft.Json/JsonConverterAttribute.cs
@@ -0,0 +1,73 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> to use the specified <see cref="JsonConverter"/> when serializing the member or class.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Enum | AttributeTargets.Parameter, AllowMultiple = false)]
+    public sealed class JsonConverterAttribute : Attribute
+    {
+        private readonly Type _converterType;
+
+        /// <summary>
+        /// Gets the type of the converter.
+        /// </summary>
+        /// <value>The type of the converter.</value>
+        public Type ConverterType
+        {
+            get { return _converterType; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonConverterAttribute"/> class.
+        /// </summary>
+        /// <param name="converterType">Type of the converter.</param>
+        public JsonConverterAttribute(Type converterType)
+        {
+            if (converterType == null)
+                throw new ArgumentNullException("converterType");
+
+            _converterType = converterType;
+        }
+
+        internal static JsonConverter CreateJsonConverterInstance(Type converterType)
+        {
+            try
+            {
+                return (JsonConverter)Activator.CreateInstance(converterType);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonException("Error creating {0}".FormatWith(CultureInfo.InvariantCulture, converterType), ex);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonConverterCollection.cs b/Newtonsoft.Json/JsonConverterCollection.cs
new file mode 100644
index 0000000..4263521
--- /dev/null
+++ b/Newtonsoft.Json/JsonConverterCollection.cs
@@ -0,0 +1,39 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections.ObjectModel;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Represents a collection of <see cref="JsonConverter"/>.
+    /// </summary>
+    public class JsonConverterCollection : Collection<JsonConverter>
+    {
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonDictionaryAttribute.cs b/Newtonsoft.Json/JsonDictionaryAttribute.cs
new file mode 100644
index 0000000..f062901
--- /dev/null
+++ b/Newtonsoft.Json/JsonDictionaryAttribute.cs
@@ -0,0 +1,52 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> how to serialize the collection.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)]
+    public sealed class JsonDictionaryAttribute : JsonContainerAttribute
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonDictionaryAttribute"/> class.
+        /// </summary>
+        public JsonDictionaryAttribute()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonDictionaryAttribute"/> class with the specified container Id.
+        /// </summary>
+        /// <param name="id">The container Id.</param>
+        public JsonDictionaryAttribute(string id)
+            : base(id)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonException.cs b/Newtonsoft.Json/JsonException.cs
new file mode 100644
index 0000000..117ba6c
--- /dev/null
+++ b/Newtonsoft.Json/JsonException.cs
@@ -0,0 +1,92 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// The exception thrown when an error occurs during Json serialization or deserialization.
+    /// </summary>
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+    [Serializable]
+#endif
+    public class JsonException : Exception
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonException"/> class.
+        /// </summary>
+        public JsonException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonException"/> class
+        /// with a specified error message.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        public JsonException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonException"/> class
+        /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+        public JsonException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        public JsonException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+#endif
+
+        internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message)
+        {
+            message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+            return new JsonException(message);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonExtensionDataAttribute.cs b/Newtonsoft.Json/JsonExtensionDataAttribute.cs
new file mode 100644
index 0000000..572b91e
--- /dev/null
+++ b/Newtonsoft.Json/JsonExtensionDataAttribute.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> to deserialize properties with no matching class member into the specified collection
+    /// and write values during serialization.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+    public class JsonExtensionDataAttribute : Attribute
+    {
+        /// <summary>
+        /// Gets or sets a value that indicates whether to write extension data when serializing the object.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> to write extension data when serializing the object; otherwise, <c>false</c>. The default is <c>true</c>.
+        /// </value>
+        public bool WriteData { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value that indicates whether to read extension data when deserializing the object.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> to read extension data when deserializing the object; otherwise, <c>false</c>. The default is <c>true</c>.
+        /// </value>
+        public bool ReadData { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonExtensionDataAttribute"/> class.
+        /// </summary>
+        public JsonExtensionDataAttribute()
+        {
+            WriteData = true;
+            ReadData = true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonIgnoreAttribute.cs b/Newtonsoft.Json/JsonIgnoreAttribute.cs
new file mode 100644
index 0000000..b100c58
--- /dev/null
+++ b/Newtonsoft.Json/JsonIgnoreAttribute.cs
@@ -0,0 +1,39 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> not to serialize the public field or public read/write property value.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false)]
+    public sealed class JsonIgnoreAttribute : Attribute
+    {
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonObjectAttribute.cs b/Newtonsoft.Json/JsonObjectAttribute.cs
new file mode 100644
index 0000000..9594dfa
--- /dev/null
+++ b/Newtonsoft.Json/JsonObjectAttribute.cs
@@ -0,0 +1,89 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> how to serialize the object.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)]
+    public sealed class JsonObjectAttribute : JsonContainerAttribute
+    {
+        private MemberSerialization _memberSerialization = MemberSerialization.OptOut;
+
+        // yuck. can't set nullable properties on an attribute in C#
+        // have to use this approach to get an unset default state
+        internal Required? _itemRequired;
+
+        /// <summary>
+        /// Gets or sets the member serialization.
+        /// </summary>
+        /// <value>The member serialization.</value>
+        public MemberSerialization MemberSerialization
+        {
+            get { return _memberSerialization; }
+            set { _memberSerialization = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value that indicates whether the object's properties are required.
+        /// </summary>
+        /// <value>
+        /// 	A value indicating whether the object's properties are required.
+        /// </value>
+        public Required ItemRequired
+        {
+            get { return _itemRequired ?? default(Required); }
+            set { _itemRequired = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonObjectAttribute"/> class.
+        /// </summary>
+        public JsonObjectAttribute()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonObjectAttribute"/> class with the specified member serialization.
+        /// </summary>
+        /// <param name="memberSerialization">The member serialization.</param>
+        public JsonObjectAttribute(MemberSerialization memberSerialization)
+        {
+            MemberSerialization = memberSerialization;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonObjectAttribute"/> class with the specified container Id.
+        /// </summary>
+        /// <param name="id">The container Id.</param>
+        public JsonObjectAttribute(string id)
+            : base(id)
+        {
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonPosition.cs b/Newtonsoft.Json/JsonPosition.cs
new file mode 100644
index 0000000..cfe48cc
--- /dev/null
+++ b/Newtonsoft.Json/JsonPosition.cs
@@ -0,0 +1,115 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+    internal enum JsonContainerType
+    {
+        None,
+        Object,
+        Array,
+        Constructor
+    }
+
+    internal struct JsonPosition
+    {
+        internal JsonContainerType Type;
+        internal int Position;
+        internal string PropertyName;
+        internal bool HasIndex;
+
+        public JsonPosition(JsonContainerType type)
+        {
+            Type = type;
+            HasIndex = TypeHasIndex(type);
+            Position = -1;
+            PropertyName = null;
+        }
+
+        internal void WriteTo(StringBuilder sb)
+        {
+            switch (Type)
+            {
+                case JsonContainerType.Object:
+                    if (sb.Length > 0)
+                        sb.Append(".");
+                    sb.Append(PropertyName);
+                    break;
+                case JsonContainerType.Array:
+                case JsonContainerType.Constructor:
+                    sb.Append("[");
+                    sb.Append(Position);
+                    sb.Append("]");
+                    break;
+            }
+        }
+
+        internal static bool TypeHasIndex(JsonContainerType type)
+        {
+            return (type == JsonContainerType.Array || type == JsonContainerType.Constructor);
+        }
+
+        internal static string BuildPath(IEnumerable<JsonPosition> positions)
+        {
+            StringBuilder sb = new StringBuilder();
+
+            foreach (JsonPosition state in positions)
+            {
+                state.WriteTo(sb);
+            }
+
+            return sb.ToString();
+        }
+
+        internal static string FormatMessage(IJsonLineInfo lineInfo, string path, string message)
+        {
+            // don't add a fullstop and space when message ends with a new line
+            if (!message.EndsWith(Environment.NewLine))
+            {
+                message = message.Trim();
+
+                if (!message.EndsWith("."))
+                    message += ".";
+
+                message += " ";
+            }
+
+            message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path);
+
+            if (lineInfo != null && lineInfo.HasLineInfo())
+                message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition);
+
+            message += ".";
+
+            return message;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonPropertyAttribute.cs b/Newtonsoft.Json/JsonPropertyAttribute.cs
new file mode 100644
index 0000000..438c966
--- /dev/null
+++ b/Newtonsoft.Json/JsonPropertyAttribute.cs
@@ -0,0 +1,190 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Instructs the <see cref="JsonSerializer"/> to always serialize the member with the specified name.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false)]
+    public sealed class JsonPropertyAttribute : Attribute
+    {
+        // yuck. can't set nullable properties on an attribute in C#
+        // have to use this approach to get an unset default state
+        internal NullValueHandling? _nullValueHandling;
+        internal DefaultValueHandling? _defaultValueHandling;
+        internal ReferenceLoopHandling? _referenceLoopHandling;
+        internal ObjectCreationHandling? _objectCreationHandling;
+        internal TypeNameHandling? _typeNameHandling;
+        internal bool? _isReference;
+        internal int? _order;
+        internal Required? _required;
+        internal bool? _itemIsReference;
+        internal ReferenceLoopHandling? _itemReferenceLoopHandling;
+        internal TypeNameHandling? _itemTypeNameHandling;
+
+        /// <summary>
+        /// Gets or sets the converter used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items converter.</value>
+        public Type ItemConverterType { get; set; }
+
+        /// <summary>
+        /// Gets or sets the null value handling used when serializing this property.
+        /// </summary>
+        /// <value>The null value handling.</value>
+        public NullValueHandling NullValueHandling
+        {
+            get { return _nullValueHandling ?? default(NullValueHandling); }
+            set { _nullValueHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the default value handling used when serializing this property.
+        /// </summary>
+        /// <value>The default value handling.</value>
+        public DefaultValueHandling DefaultValueHandling
+        {
+            get { return _defaultValueHandling ?? default(DefaultValueHandling); }
+            set { _defaultValueHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the reference loop handling used when serializing this property.
+        /// </summary>
+        /// <value>The reference loop handling.</value>
+        public ReferenceLoopHandling ReferenceLoopHandling
+        {
+            get { return _referenceLoopHandling ?? default(ReferenceLoopHandling); }
+            set { _referenceLoopHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the object creation handling used when deserializing this property.
+        /// </summary>
+        /// <value>The object creation handling.</value>
+        public ObjectCreationHandling ObjectCreationHandling
+        {
+            get { return _objectCreationHandling ?? default(ObjectCreationHandling); }
+            set { _objectCreationHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the type name handling used when serializing this property.
+        /// </summary>
+        /// <value>The type name handling.</value>
+        public TypeNameHandling TypeNameHandling
+        {
+            get { return _typeNameHandling ?? default(TypeNameHandling); }
+            set { _typeNameHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets whether this property's value is serialized as a reference.
+        /// </summary>
+        /// <value>Whether this property's value is serialized as a reference.</value>
+        public bool IsReference
+        {
+            get { return _isReference ?? default(bool); }
+            set { _isReference = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the order of serialization and deserialization of a member.
+        /// </summary>
+        /// <value>The numeric order of serialization or deserialization.</value>
+        public int Order
+        {
+            get { return _order ?? default(int); }
+            set { _order = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this property is required.
+        /// </summary>
+        /// <value>
+        /// 	A value indicating whether this property is required.
+        /// </value>
+        public Required Required
+        {
+            get { return _required ?? Required.Default; }
+            set { _required = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the name of the property.
+        /// </summary>
+        /// <value>The name of the property.</value>
+        public string PropertyName { get; set; }
+
+        /// <summary>
+        /// Gets or sets the the reference loop handling used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items reference loop handling.</value>
+        public ReferenceLoopHandling ItemReferenceLoopHandling
+        {
+            get { return _itemReferenceLoopHandling ?? default(ReferenceLoopHandling); }
+            set { _itemReferenceLoopHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the the type name handling used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items type name handling.</value>
+        public TypeNameHandling ItemTypeNameHandling
+        {
+            get { return _itemTypeNameHandling ?? default(TypeNameHandling); }
+            set { _itemTypeNameHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets whether this property's collection items are serialized as a reference.
+        /// </summary>
+        /// <value>Whether this property's collection items are serialized as a reference.</value>
+        public bool ItemIsReference
+        {
+            get { return _itemIsReference ?? default(bool); }
+            set { _itemIsReference = value; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonPropertyAttribute"/> class.
+        /// </summary>
+        public JsonPropertyAttribute()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonPropertyAttribute"/> class with the specified name.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        public JsonPropertyAttribute(string propertyName)
+        {
+            PropertyName = propertyName;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonReader.cs b/Newtonsoft.Json/JsonReader.cs
new file mode 100644
index 0000000..a4181fe
--- /dev/null
+++ b/Newtonsoft.Json/JsonReader.cs
@@ -0,0 +1,1010 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+    /// </summary>
+    public abstract class JsonReader : IDisposable
+    {
+        /// <summary>
+        /// Specifies the state of the reader.
+        /// </summary>
+        protected internal enum State
+        {
+            /// <summary>
+            /// The Read method has not been called.
+            /// </summary>
+            Start,
+
+            /// <summary>
+            /// The end of the file has been reached successfully.
+            /// </summary>
+            Complete,
+
+            /// <summary>
+            /// Reader is at a property.
+            /// </summary>
+            Property,
+
+            /// <summary>
+            /// Reader is at the start of an object.
+            /// </summary>
+            ObjectStart,
+
+            /// <summary>
+            /// Reader is in an object.
+            /// </summary>
+            Object,
+
+            /// <summary>
+            /// Reader is at the start of an array.
+            /// </summary>
+            ArrayStart,
+
+            /// <summary>
+            /// Reader is in an array.
+            /// </summary>
+            Array,
+
+            /// <summary>
+            /// The Close method has been called.
+            /// </summary>
+            Closed,
+
+            /// <summary>
+            /// Reader has just read a value.
+            /// </summary>
+            PostValue,
+
+            /// <summary>
+            /// Reader is at the start of a constructor.
+            /// </summary>
+            ConstructorStart,
+
+            /// <summary>
+            /// Reader in a constructor.
+            /// </summary>
+            Constructor,
+
+            /// <summary>
+            /// An error occurred that prevents the read operation from continuing.
+            /// </summary>
+            Error,
+
+            /// <summary>
+            /// The end of the file has been reached successfully.
+            /// </summary>
+            Finished
+        }
+
+        // current Token data
+        private JsonToken _tokenType;
+        private object _value;
+        internal char _quoteChar;
+        internal State _currentState;
+        internal ReadType _readType;
+        private JsonPosition _currentPosition;
+        private CultureInfo _culture;
+        private DateTimeZoneHandling _dateTimeZoneHandling;
+        private int? _maxDepth;
+        private bool _hasExceededMaxDepth;
+        internal DateParseHandling _dateParseHandling;
+        internal FloatParseHandling _floatParseHandling;
+        private string _dateFormatString;
+        private readonly List<JsonPosition> _stack;
+
+        /// <summary>
+        /// Gets the current reader state.
+        /// </summary>
+        /// <value>The current reader state.</value>
+        protected State CurrentState
+        {
+            get { return _currentState; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the underlying stream or
+        /// <see cref="TextReader"/> should be closed when the reader is closed.
+        /// </summary>
+        /// <value>
+        /// true to close the underlying stream or <see cref="TextReader"/> when
+        /// the reader is closed; otherwise false. The default is true.
+        /// </value>
+        public bool CloseInput { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether multiple pieces of JSON content can
+        /// be read from a continuous stream without erroring.
+        /// </summary>
+        /// <value>
+        /// true to support reading multiple pieces of JSON content; otherwise false. The default is false.
+        /// </value>
+        public bool SupportMultipleContent { get; set; }
+
+        /// <summary>
+        /// Gets the quotation mark character used to enclose the value of a string.
+        /// </summary>
+        public virtual char QuoteChar
+        {
+            get { return _quoteChar; }
+            protected internal set { _quoteChar = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> time zones are handling when reading JSON.
+        /// </summary>
+        public DateTimeZoneHandling DateTimeZoneHandling
+        {
+            get { return _dateTimeZoneHandling; }
+            set { _dateTimeZoneHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+        /// </summary>
+        public DateParseHandling DateParseHandling
+        {
+            get { return _dateParseHandling; }
+            set { _dateParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+        /// </summary>
+        public FloatParseHandling FloatParseHandling
+        {
+            get { return _floatParseHandling; }
+            set { _floatParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how custom date formatted strings are parsed when reading JSON.
+        /// </summary>
+        public string DateFormatString
+        {
+            get { return _dateFormatString; }
+            set { _dateFormatString = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
+        /// </summary>
+        public int? MaxDepth
+        {
+            get { return _maxDepth; }
+            set
+            {
+                if (value <= 0)
+                    throw new ArgumentException("Value must be positive.", "value");
+
+                _maxDepth = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets the type of the current JSON token. 
+        /// </summary>
+        public virtual JsonToken TokenType
+        {
+            get { return _tokenType; }
+        }
+
+        /// <summary>
+        /// Gets the text value of the current JSON token.
+        /// </summary>
+        public virtual object Value
+        {
+            get { return _value; }
+        }
+
+        /// <summary>
+        /// Gets The Common Language Runtime (CLR) type for the current JSON token.
+        /// </summary>
+        public virtual Type ValueType
+        {
+            get { return (_value != null) ? _value.GetType() : null; }
+        }
+
+        /// <summary>
+        /// Gets the depth of the current token in the JSON document.
+        /// </summary>
+        /// <value>The depth of the current token in the JSON document.</value>
+        public virtual int Depth
+        {
+            get
+            {
+                int depth = _stack.Count;
+                if (IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None)
+                    return depth;
+                else
+                    return depth + 1;
+            }
+        }
+
+        /// <summary>
+        /// Gets the path of the current JSON token. 
+        /// </summary>
+        public virtual string Path
+        {
+            get
+            {
+                if (_currentPosition.Type == JsonContainerType.None)
+                    return string.Empty;
+
+                bool insideContainer = (_currentState != State.ArrayStart
+                                        && _currentState != State.ConstructorStart
+                                        && _currentState != State.ObjectStart);
+
+                IEnumerable<JsonPosition> positions = (!insideContainer)
+                    ? _stack
+                    : _stack.Concat(new[] { _currentPosition });
+
+                return JsonPosition.BuildPath(positions);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
+        /// </summary>
+        public CultureInfo Culture
+        {
+            get { return _culture ?? CultureInfo.InvariantCulture; }
+            set { _culture = value; }
+        }
+
+        internal JsonPosition GetPosition(int depth)
+        {
+            if (depth < _stack.Count)
+                return _stack[depth];
+
+            return _currentPosition;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
+        /// </summary>
+        protected JsonReader()
+        {
+            _currentState = State.Start;
+            _stack = new List<JsonPosition>(4);
+            _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+            _dateParseHandling = DateParseHandling.DateTime;
+            _floatParseHandling = FloatParseHandling.Double;
+
+            CloseInput = true;
+        }
+
+        private void Push(JsonContainerType value)
+        {
+            UpdateScopeWithFinishedValue();
+
+            if (_currentPosition.Type == JsonContainerType.None)
+            {
+                _currentPosition = new JsonPosition(value);
+            }
+            else
+            {
+                _stack.Add(_currentPosition);
+                _currentPosition = new JsonPosition(value);
+
+                // this is a little hacky because Depth increases when first property/value is written but only testing here is faster/simpler
+                if (_maxDepth != null && Depth + 1 > _maxDepth && !_hasExceededMaxDepth)
+                {
+                    _hasExceededMaxDepth = true;
+                    throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth));
+                }
+            }
+        }
+
+        private JsonContainerType Pop()
+        {
+            JsonPosition oldPosition;
+            if (_stack.Count > 0)
+            {
+                oldPosition = _currentPosition;
+                _currentPosition = _stack[_stack.Count - 1];
+                _stack.RemoveAt(_stack.Count - 1);
+            }
+            else
+            {
+                oldPosition = _currentPosition;
+                _currentPosition = new JsonPosition();
+            }
+
+            if (_maxDepth != null && Depth <= _maxDepth)
+                _hasExceededMaxDepth = false;
+
+            return oldPosition.Type;
+        }
+
+        private JsonContainerType Peek()
+        {
+            return _currentPosition.Type;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream.
+        /// </summary>
+        /// <returns>true if the next token was read successfully; false if there are no more tokens to read.</returns>
+        public abstract bool Read();
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract int? ReadAsInt32();
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="String"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract string ReadAsString();
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
+        /// </summary>
+        /// <returns>A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract byte[] ReadAsBytes();
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract decimal? ReadAsDecimal();
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract DateTime? ReadAsDateTime();
+
+#if !NET20
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public abstract DateTimeOffset? ReadAsDateTimeOffset();
+#endif
+
+        internal virtual bool ReadInternal()
+        {
+            throw new NotImplementedException();
+        }
+
+#if !NET20
+        internal DateTimeOffset? ReadAsDateTimeOffsetInternal()
+        {
+            _readType = ReadType.ReadAsDateTimeOffset;
+
+            JsonToken t;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+                else
+                {
+                    t = TokenType;
+                }
+            } while (t == JsonToken.Comment);
+
+            if (t == JsonToken.Date)
+            {
+                if (Value is DateTime)
+                    SetToken(JsonToken.Date, new DateTimeOffset((DateTime)Value), false);
+
+                return (DateTimeOffset)Value;
+            }
+
+            if (t == JsonToken.Null)
+                return null;
+
+            DateTimeOffset dt;
+            if (t == JsonToken.String)
+            {
+                string s = (string)Value;
+                if (string.IsNullOrEmpty(s))
+                {
+                    SetToken(JsonToken.Null);
+                    return null;
+                }
+
+                object temp;
+                if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTimeOffset, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
+                {
+                    dt = (DateTimeOffset)temp;
+                    SetToken(JsonToken.Date, dt, false);
+                    return dt;
+                }
+
+                if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
+                {
+                    SetToken(JsonToken.Date, dt, false);
+                    return dt;
+                }
+                
+                throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+            }
+
+            if (t == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+        }
+#endif
+
+        internal byte[] ReadAsBytesInternal()
+        {
+            _readType = ReadType.ReadAsBytes;
+
+            JsonToken t;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+                else
+                {
+                    t = TokenType;
+                }
+            } while (t == JsonToken.Comment);
+
+            if (IsWrappedInTypeObject())
+            {
+                byte[] data = ReadAsBytes();
+                ReadInternal();
+                SetToken(JsonToken.Bytes, data, false);
+                return data;
+            }
+
+            // attempt to convert possible base 64 string to bytes
+            if (t == JsonToken.String)
+            {
+                string s = (string)Value;
+                byte[] data = (s.Length == 0) ? new byte[0] : Convert.FromBase64String(s);
+                SetToken(JsonToken.Bytes, data, false);
+                return data;
+            }
+
+            if (t == JsonToken.Null)
+                return null;
+
+            if (t == JsonToken.Bytes)
+                return (byte[])Value;
+
+            if (t == JsonToken.StartArray)
+            {
+                List<byte> data = new List<byte>();
+
+                while (ReadInternal())
+                {
+                    t = TokenType;
+                    switch (t)
+                    {
+                        case JsonToken.Integer:
+                            data.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture));
+                            break;
+                        case JsonToken.EndArray:
+                            byte[] d = data.ToArray();
+                            SetToken(JsonToken.Bytes, d, false);
+                            return d;
+                        case JsonToken.Comment:
+                            // skip
+                            break;
+                        default:
+                            throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+                    }
+                }
+
+                throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
+            }
+
+            if (t == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+        }
+
+        internal decimal? ReadAsDecimalInternal()
+        {
+            _readType = ReadType.ReadAsDecimal;
+
+            JsonToken t;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+                else
+                {
+                    t = TokenType;
+                }
+            } while (t == JsonToken.Comment);
+
+            if (t == JsonToken.Integer || t == JsonToken.Float)
+            {
+                if (!(Value is decimal))
+                    SetToken(JsonToken.Float, Convert.ToDecimal(Value, CultureInfo.InvariantCulture), false);
+
+                return (decimal)Value;
+            }
+
+            if (t == JsonToken.Null)
+                return null;
+
+            decimal d;
+            if (t == JsonToken.String)
+            {
+                string s = (string)Value;
+                if (string.IsNullOrEmpty(s))
+                {
+                    SetToken(JsonToken.Null);
+                    return null;
+                }
+
+                if (decimal.TryParse(s, NumberStyles.Number, Culture, out d))
+                {
+                    SetToken(JsonToken.Float, d, false);
+                    return d;
+                }
+                else
+                {
+                    throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+                }
+            }
+
+            if (t == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+        }
+
+        internal int? ReadAsInt32Internal()
+        {
+            _readType = ReadType.ReadAsInt32;
+
+            JsonToken t;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+                else
+                {
+                    t = TokenType;
+                }
+            } while (t == JsonToken.Comment);
+
+            if (t == JsonToken.Integer || t == JsonToken.Float)
+            {
+                if (!(Value is int))
+                    SetToken(JsonToken.Integer, Convert.ToInt32(Value, CultureInfo.InvariantCulture), false);
+
+                return (int)Value;
+            }
+
+            if (t == JsonToken.Null)
+                return null;
+
+            int i;
+            if (t == JsonToken.String)
+            {
+                string s = (string)Value;
+                if (string.IsNullOrEmpty(s))
+                {
+                    SetToken(JsonToken.Null);
+                    return null;
+                }
+
+                if (int.TryParse(s, NumberStyles.Integer, Culture, out i))
+                {
+                    SetToken(JsonToken.Integer, i, false);
+                    return i;
+                }
+                else
+                {
+                    throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+                }
+            }
+
+            if (t == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+        }
+
+        internal string ReadAsStringInternal()
+        {
+            _readType = ReadType.ReadAsString;
+
+            JsonToken t;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+                else
+                {
+                    t = TokenType;
+                }
+            } while (t == JsonToken.Comment);
+
+            if (t == JsonToken.String)
+                return (string)Value;
+
+            if (t == JsonToken.Null)
+                return null;
+
+            if (IsPrimitiveToken(t))
+            {
+                if (Value != null)
+                {
+                    string s;
+                    if (Value is IFormattable)
+                        s = ((IFormattable)Value).ToString(null, Culture);
+                    else
+                        s = Value.ToString();
+
+                    SetToken(JsonToken.String, s, false);
+                    return s;
+                }
+            }
+
+            if (t == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, t));
+        }
+
+        internal DateTime? ReadAsDateTimeInternal()
+        {
+            _readType = ReadType.ReadAsDateTime;
+
+            do
+            {
+                if (!ReadInternal())
+                {
+                    SetToken(JsonToken.None);
+                    return null;
+                }
+            } while (TokenType == JsonToken.Comment);
+
+            if (TokenType == JsonToken.Date)
+                return (DateTime)Value;
+
+            if (TokenType == JsonToken.Null)
+                return null;
+
+            DateTime dt;
+            if (TokenType == JsonToken.String)
+            {
+                string s = (string)Value;
+                if (string.IsNullOrEmpty(s))
+                {
+                    SetToken(JsonToken.Null);
+                    return null;
+                }
+
+                object temp;
+                if (DateTimeUtils.TryParseDateTime(s, DateParseHandling.DateTime, DateTimeZoneHandling, _dateFormatString, Culture, out temp))
+                {
+                    dt = (DateTime)temp;
+                    dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
+                    SetToken(JsonToken.Date, dt, false);
+                    return dt;
+                }
+
+                if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt))
+                {
+                    dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling);
+                    SetToken(JsonToken.Date, dt, false);
+                    return dt;
+                }
+
+                throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, Value));
+            }
+
+            if (TokenType == JsonToken.EndArray)
+                return null;
+
+            throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType));
+        }
+
+        private bool IsWrappedInTypeObject()
+        {
+            _readType = ReadType.Read;
+
+            if (TokenType == JsonToken.StartObject)
+            {
+                if (!ReadInternal())
+                    throw JsonReaderException.Create(this, "Unexpected end when reading bytes.");
+
+                if (Value.ToString() == JsonTypeReflector.TypePropertyName)
+                {
+                    ReadInternal();
+                    if (Value != null && Value.ToString().StartsWith("System.Byte[]"))
+                    {
+                        ReadInternal();
+                        if (Value.ToString() == JsonTypeReflector.ValuePropertyName)
+                        {
+                            return true;
+                        }
+                    }
+                }
+
+                throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject));
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// Skips the children of the current token.
+        /// </summary>
+        public void Skip()
+        {
+            if (TokenType == JsonToken.PropertyName)
+                Read();
+
+            if (IsStartToken(TokenType))
+            {
+                int depth = Depth;
+
+                while (Read() && (depth < Depth))
+                {
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sets the current token.
+        /// </summary>
+        /// <param name="newToken">The new token.</param>
+        protected void SetToken(JsonToken newToken)
+        {
+            SetToken(newToken, null, true);
+        }
+
+        /// <summary>
+        /// Sets the current token and value.
+        /// </summary>
+        /// <param name="newToken">The new token.</param>
+        /// <param name="value">The value.</param>
+        protected void SetToken(JsonToken newToken, object value)
+        {
+            SetToken(newToken, value, true);
+        }
+
+        internal void SetToken(JsonToken newToken, object value, bool updateIndex)
+        {
+            _tokenType = newToken;
+            _value = value;
+
+            switch (newToken)
+            {
+                case JsonToken.StartObject:
+                    _currentState = State.ObjectStart;
+                    Push(JsonContainerType.Object);
+                    break;
+                case JsonToken.StartArray:
+                    _currentState = State.ArrayStart;
+                    Push(JsonContainerType.Array);
+                    break;
+                case JsonToken.StartConstructor:
+                    _currentState = State.ConstructorStart;
+                    Push(JsonContainerType.Constructor);
+                    break;
+                case JsonToken.EndObject:
+                    ValidateEnd(JsonToken.EndObject);
+                    break;
+                case JsonToken.EndArray:
+                    ValidateEnd(JsonToken.EndArray);
+                    break;
+                case JsonToken.EndConstructor:
+                    ValidateEnd(JsonToken.EndConstructor);
+                    break;
+                case JsonToken.PropertyName:
+                    _currentState = State.Property;
+
+                    _currentPosition.PropertyName = (string)value;
+                    break;
+                case JsonToken.Undefined:
+                case JsonToken.Integer:
+                case JsonToken.Float:
+                case JsonToken.Boolean:
+                case JsonToken.Null:
+                case JsonToken.Date:
+                case JsonToken.String:
+                case JsonToken.Raw:
+                case JsonToken.Bytes:
+                    if (Peek() != JsonContainerType.None)
+                        _currentState = State.PostValue;
+                    else
+                        SetFinished();
+
+                    if (updateIndex)
+                        UpdateScopeWithFinishedValue();
+                    break;
+            }
+        }
+
+        private void UpdateScopeWithFinishedValue()
+        {
+            if (_currentPosition.HasIndex)
+                _currentPosition.Position++;
+        }
+
+        private void ValidateEnd(JsonToken endToken)
+        {
+            JsonContainerType currentObject = Pop();
+
+            if (GetTypeForCloseToken(endToken) != currentObject)
+                throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, currentObject));
+
+            if (Peek() != JsonContainerType.None)
+                _currentState = State.PostValue;
+            else
+                SetFinished();
+        }
+
+        /// <summary>
+        /// Sets the state based on current token type.
+        /// </summary>
+        protected void SetStateBasedOnCurrent()
+        {
+            JsonContainerType currentObject = Peek();
+
+            switch (currentObject)
+            {
+                case JsonContainerType.Object:
+                    _currentState = State.Object;
+                    break;
+                case JsonContainerType.Array:
+                    _currentState = State.Array;
+                    break;
+                case JsonContainerType.Constructor:
+                    _currentState = State.Constructor;
+                    break;
+                case JsonContainerType.None:
+                    SetFinished();
+                    break;
+                default:
+                    throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, currentObject));
+            }
+        }
+
+        private void SetFinished()
+        {
+            if (SupportMultipleContent)
+                _currentState = State.Start;
+            else
+                _currentState = State.Finished;
+        }
+
+        internal static bool IsPrimitiveToken(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.Integer:
+                case JsonToken.Float:
+                case JsonToken.String:
+                case JsonToken.Boolean:
+                case JsonToken.Undefined:
+                case JsonToken.Null:
+                case JsonToken.Date:
+                case JsonToken.Bytes:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        internal static bool IsStartToken(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.StartObject:
+                case JsonToken.StartArray:
+                case JsonToken.StartConstructor:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        private JsonContainerType GetTypeForCloseToken(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.EndObject:
+                    return JsonContainerType.Object;
+                case JsonToken.EndArray:
+                    return JsonContainerType.Array;
+                case JsonToken.EndConstructor:
+                    return JsonContainerType.Constructor;
+                default:
+                    throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token));
+            }
+        }
+
+        /// <summary>
+        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+        /// </summary>
+        void IDisposable.Dispose()
+        {
+            Dispose(true);
+        }
+
+        /// <summary>
+        /// Releases unmanaged and - optionally - managed resources
+        /// </summary>
+        /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+        protected virtual void Dispose(bool disposing)
+        {
+            if (_currentState != State.Closed && disposing)
+                Close();
+        }
+
+        /// <summary>
+        /// Changes the <see cref="State"/> to Closed. 
+        /// </summary>
+        public virtual void Close()
+        {
+            _currentState = State.Closed;
+            _tokenType = JsonToken.None;
+            _value = null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonReaderException.cs b/Newtonsoft.Json/JsonReaderException.cs
new file mode 100644
index 0000000..2d47ffd
--- /dev/null
+++ b/Newtonsoft.Json/JsonReaderException.cs
@@ -0,0 +1,139 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// The exception thrown when an error occurs while reading Json text.
+    /// </summary>
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+    [Serializable]
+#endif
+    public class JsonReaderException : JsonException
+    {
+        /// <summary>
+        /// Gets the line number indicating where the error occurred.
+        /// </summary>
+        /// <value>The line number indicating where the error occurred.</value>
+        public int LineNumber { get; private set; }
+
+        /// <summary>
+        /// Gets the line position indicating where the error occurred.
+        /// </summary>
+        /// <value>The line position indicating where the error occurred.</value>
+        public int LinePosition { get; private set; }
+
+        /// <summary>
+        /// Gets the path to the JSON where the error occurred.
+        /// </summary>
+        /// <value>The path to the JSON where the error occurred.</value>
+        public string Path { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReaderException"/> class.
+        /// </summary>
+        public JsonReaderException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReaderException"/> class
+        /// with a specified error message.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        public JsonReaderException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReaderException"/> class
+        /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+        public JsonReaderException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReaderException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        public JsonReaderException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+#endif
+
+        internal JsonReaderException(string message, Exception innerException, string path, int lineNumber, int linePosition)
+            : base(message, innerException)
+        {
+            Path = path;
+            LineNumber = lineNumber;
+            LinePosition = linePosition;
+        }
+
+        internal static JsonReaderException Create(JsonReader reader, string message)
+        {
+            return Create(reader, message, null);
+        }
+
+        internal static JsonReaderException Create(JsonReader reader, string message, Exception ex)
+        {
+            return Create(reader as IJsonLineInfo, reader.Path, message, ex);
+        }
+
+        internal static JsonReaderException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
+        {
+            message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+            int lineNumber;
+            int linePosition;
+            if (lineInfo != null && lineInfo.HasLineInfo())
+            {
+                lineNumber = lineInfo.LineNumber;
+                linePosition = lineInfo.LinePosition;
+            }
+            else
+            {
+                lineNumber = 0;
+                linePosition = 0;
+            }
+
+            return new JsonReaderException(message, ex, path, lineNumber, linePosition);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonSerializationException.cs b/Newtonsoft.Json/JsonSerializationException.cs
new file mode 100644
index 0000000..a7c784b
--- /dev/null
+++ b/Newtonsoft.Json/JsonSerializationException.cs
@@ -0,0 +1,100 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// The exception thrown when an error occurs during Json serialization or deserialization.
+    /// </summary>
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+    [Serializable]
+#endif
+    public class JsonSerializationException : JsonException
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializationException"/> class.
+        /// </summary>
+        public JsonSerializationException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializationException"/> class
+        /// with a specified error message.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        public JsonSerializationException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializationException"/> class
+        /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+        public JsonSerializationException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializationException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        public JsonSerializationException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+#endif
+
+        internal static JsonSerializationException Create(JsonReader reader, string message)
+        {
+            return Create(reader, message, null);
+        }
+
+        internal static JsonSerializationException Create(JsonReader reader, string message, Exception ex)
+        {
+            return Create(reader as IJsonLineInfo, reader.Path, message, ex);
+        }
+
+        internal static JsonSerializationException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex)
+        {
+            message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+            return new JsonSerializationException(message, ex);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonSerializer.cs b/Newtonsoft.Json/JsonSerializer.cs
new file mode 100644
index 0000000..202e65a
--- /dev/null
+++ b/Newtonsoft.Json/JsonSerializer.cs
@@ -0,0 +1,925 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Runtime.Serialization.Formatters;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+using System.Runtime.Serialization;
+using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Serializes and deserializes objects into and from the JSON format.
+    /// The <see cref="JsonSerializer"/> enables you to control how objects are encoded into JSON.
+    /// </summary>
+    public class JsonSerializer
+    {
+        #region Properties_binder
+        internal TypeNameHandling _typeNameHandling;
+        internal FormatterAssemblyStyle _typeNameAssemblyFormat;
+        internal PreserveReferencesHandling _preserveReferencesHandling;
+        internal ReferenceLoopHandling _referenceLoopHandling;
+        internal MissingMemberHandling _missingMemberHandling;
+        internal ObjectCreationHandling _objectCreationHandling;
+        internal NullValueHandling _nullValueHandling;
+        internal DefaultValueHandling _defaultValueHandling;
+        internal ConstructorHandling _constructorHandling;
+        internal MetadataPropertyHandling _metadataPropertyHandling;
+        internal JsonConverterCollection _converters;
+        internal IContractResolver _contractResolver;
+        internal ITraceWriter _traceWriter;
+        internal SerializationBinder _binder;
+        internal StreamingContext _context;
+        private IReferenceResolver _referenceResolver;
+
+        private Formatting? _formatting;
+        private DateFormatHandling? _dateFormatHandling;
+        private DateTimeZoneHandling? _dateTimeZoneHandling;
+        private DateParseHandling? _dateParseHandling;
+        private FloatFormatHandling? _floatFormatHandling;
+        private FloatParseHandling? _floatParseHandling;
+        private StringEscapeHandling? _stringEscapeHandling;
+        private CultureInfo _culture;
+        private int? _maxDepth;
+        private bool _maxDepthSet;
+        private bool? _checkAdditionalContent;
+        private string _dateFormatString;
+        private bool _dateFormatStringSet;
+
+        /// <summary>
+        /// Occurs when the <see cref="JsonSerializer"/> errors during serialization and deserialization.
+        /// </summary>
+        public virtual event EventHandler<ErrorEventArgs> Error;
+
+        /// <summary>
+        /// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
+        /// </summary>
+        public virtual IReferenceResolver ReferenceResolver
+        {
+            get { return GetReferenceResolver(); }
+            set
+            {
+                if (value == null)
+                    throw new ArgumentNullException("value", "Reference resolver cannot be null.");
+
+                _referenceResolver = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="SerializationBinder"/> used by the serializer when resolving type names.
+        /// </summary>
+        public virtual SerializationBinder Binder
+        {
+            get { return _binder; }
+            set
+            {
+                if (value == null)
+                    throw new ArgumentNullException("value", "Serialization binder cannot be null.");
+
+                _binder = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages.
+        /// </summary>
+        /// <value>The trace writer.</value>
+        public virtual ITraceWriter TraceWriter
+        {
+            get { return _traceWriter; }
+            set { _traceWriter = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how type name writing and reading is handled by the serializer.
+        /// </summary>
+        public virtual TypeNameHandling TypeNameHandling
+        {
+            get { return _typeNameHandling; }
+            set
+            {
+                if (value < TypeNameHandling.None || value > TypeNameHandling.Auto)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _typeNameHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how a type name assembly is written and resolved by the serializer.
+        /// </summary>
+        /// <value>The type name assembly format.</value>
+        public virtual FormatterAssemblyStyle TypeNameAssemblyFormat
+        {
+            get { return _typeNameAssemblyFormat; }
+            set
+            {
+                if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _typeNameAssemblyFormat = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how object references are preserved by the serializer.
+        /// </summary>
+        public virtual PreserveReferencesHandling PreserveReferencesHandling
+        {
+            get { return _preserveReferencesHandling; }
+            set
+            {
+                if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _preserveReferencesHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Get or set how reference loops (e.g. a class referencing itself) is handled.
+        /// </summary>
+        public virtual ReferenceLoopHandling ReferenceLoopHandling
+        {
+            get { return _referenceLoopHandling; }
+            set
+            {
+                if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _referenceLoopHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Get or set how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
+        /// </summary>
+        public virtual MissingMemberHandling MissingMemberHandling
+        {
+            get { return _missingMemberHandling; }
+            set
+            {
+                if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _missingMemberHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Get or set how null values are handled during serialization and deserialization.
+        /// </summary>
+        public virtual NullValueHandling NullValueHandling
+        {
+            get { return _nullValueHandling; }
+            set
+            {
+                if (value < NullValueHandling.Include || value > NullValueHandling.Ignore)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _nullValueHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Get or set how null default are handled during serialization and deserialization.
+        /// </summary>
+        public virtual DefaultValueHandling DefaultValueHandling
+        {
+            get { return _defaultValueHandling; }
+            set
+            {
+                if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _defaultValueHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how objects are created during deserialization.
+        /// </summary>
+        /// <value>The object creation handling.</value>
+        public virtual ObjectCreationHandling ObjectCreationHandling
+        {
+            get { return _objectCreationHandling; }
+            set
+            {
+                if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _objectCreationHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how constructors are used during deserialization.
+        /// </summary>
+        /// <value>The constructor handling.</value>
+        public virtual ConstructorHandling ConstructorHandling
+        {
+            get { return _constructorHandling; }
+            set
+            {
+                if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _constructorHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how metadata properties are used during deserialization.
+        /// </summary>
+        /// <value>The metadata properties handling.</value>
+        public virtual MetadataPropertyHandling MetadataPropertyHandling
+        {
+            get { return _metadataPropertyHandling; }
+            set
+            {
+                if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.ReadAhead)
+                    throw new ArgumentOutOfRangeException("value");
+
+                _metadataPropertyHandling = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets a collection <see cref="JsonConverter"/> that will be used during serialization.
+        /// </summary>
+        /// <value>Collection <see cref="JsonConverter"/> that will be used during serialization.</value>
+        public virtual JsonConverterCollection Converters
+        {
+            get
+            {
+                if (_converters == null)
+                    _converters = new JsonConverterCollection();
+
+                return _converters;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the contract resolver used by the serializer when
+        /// serializing .NET objects to JSON and vice versa.
+        /// </summary>
+        public virtual IContractResolver ContractResolver
+        {
+            get { return _contractResolver; }
+            set { _contractResolver = value ?? DefaultContractResolver.Instance; }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="StreamingContext"/> used by the serializer when invoking serialization callback methods.
+        /// </summary>
+        /// <value>The context.</value>
+        public virtual StreamingContext Context
+        {
+            get { return _context; }
+            set { _context = value; }
+        }
+
+        /// <summary>
+        /// Indicates how JSON text output is formatted.
+        /// </summary>
+        public virtual Formatting Formatting
+        {
+            get { return _formatting ?? JsonSerializerSettings.DefaultFormatting; }
+            set { _formatting = value; }
+        }
+
+        /// <summary>
+        /// Get or set how dates are written to JSON text.
+        /// </summary>
+        public virtual DateFormatHandling DateFormatHandling
+        {
+            get { return _dateFormatHandling ?? JsonSerializerSettings.DefaultDateFormatHandling; }
+            set { _dateFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> time zones are handling during serialization and deserialization.
+        /// </summary>
+        public virtual DateTimeZoneHandling DateTimeZoneHandling
+        {
+            get { return _dateTimeZoneHandling ?? JsonSerializerSettings.DefaultDateTimeZoneHandling; }
+            set { _dateTimeZoneHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+        /// </summary>
+        public virtual DateParseHandling DateParseHandling
+        {
+            get { return _dateParseHandling ?? JsonSerializerSettings.DefaultDateParseHandling; }
+            set { _dateParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+        /// </summary>
+        public virtual FloatParseHandling FloatParseHandling
+        {
+            get { return _floatParseHandling ?? JsonSerializerSettings.DefaultFloatParseHandling; }
+            set { _floatParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how special floating point numbers, e.g. <see cref="F:System.Double.NaN"/>,
+        /// <see cref="F:System.Double.PositiveInfinity"/> and <see cref="F:System.Double.NegativeInfinity"/>,
+        /// are written as JSON text.
+        /// </summary>
+        public virtual FloatFormatHandling FloatFormatHandling
+        {
+            get { return _floatFormatHandling ?? JsonSerializerSettings.DefaultFloatFormatHandling; }
+            set { _floatFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how strings are escaped when writing JSON text.
+        /// </summary>
+        public virtual StringEscapeHandling StringEscapeHandling
+        {
+            get { return _stringEscapeHandling ?? JsonSerializerSettings.DefaultStringEscapeHandling; }
+            set { _stringEscapeHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> and <see cref="DateTimeOffset"/> values are formatting when writing JSON text.
+        /// </summary>
+        public virtual string DateFormatString
+        {
+            get { return _dateFormatString ?? JsonSerializerSettings.DefaultDateFormatString; }
+            set
+            {
+                _dateFormatString = value;
+                _dateFormatStringSet = true;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
+        /// </summary>
+        public virtual CultureInfo Culture
+        {
+            get { return _culture ?? JsonSerializerSettings.DefaultCulture; }
+            set { _culture = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
+        /// </summary>
+        public virtual int? MaxDepth
+        {
+            get { return _maxDepth; }
+            set
+            {
+                if (value <= 0)
+                    throw new ArgumentException("Value must be positive.", "value");
+
+                _maxDepth = value;
+                _maxDepthSet = true;
+            }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether there will be a check for additional JSON content after deserializing an object.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if there will be a check for additional JSON content after deserializing an object; otherwise, <c>false</c>.
+        /// </value>
+        public virtual bool CheckAdditionalContent
+        {
+            get { return _checkAdditionalContent ?? JsonSerializerSettings.DefaultCheckAdditionalContent; }
+            set { _checkAdditionalContent = value; }
+        }
+
+        internal bool IsCheckAdditionalContentSet()
+        {
+            return (_checkAdditionalContent != null);
+        }
+        #endregion
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializer"/> class.
+        /// </summary>
+        public JsonSerializer()
+        {
+            _referenceLoopHandling = JsonSerializerSettings.DefaultReferenceLoopHandling;
+            _missingMemberHandling = JsonSerializerSettings.DefaultMissingMemberHandling;
+            _nullValueHandling = JsonSerializerSettings.DefaultNullValueHandling;
+            _defaultValueHandling = JsonSerializerSettings.DefaultDefaultValueHandling;
+            _objectCreationHandling = JsonSerializerSettings.DefaultObjectCreationHandling;
+            _preserveReferencesHandling = JsonSerializerSettings.DefaultPreserveReferencesHandling;
+            _constructorHandling = JsonSerializerSettings.DefaultConstructorHandling;
+            _typeNameHandling = JsonSerializerSettings.DefaultTypeNameHandling;
+            _metadataPropertyHandling = JsonSerializerSettings.DefaultMetadataPropertyHandling;
+            _context = JsonSerializerSettings.DefaultContext;
+            _binder = DefaultSerializationBinder.Instance;
+
+            _culture = JsonSerializerSettings.DefaultCulture;
+            _contractResolver = DefaultContractResolver.Instance;
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="JsonSerializer"/> instance.
+        /// The <see cref="JsonSerializer"/> will not use default settings.
+        /// </summary>
+        /// <returns>
+        /// A new <see cref="JsonSerializer"/> instance.
+        /// The <see cref="JsonSerializer"/> will not use default settings.
+        /// </returns>
+        public static JsonSerializer Create()
+        {
+            return new JsonSerializer();
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="JsonSerializer"/> instance using the specified <see cref="JsonSerializerSettings"/>.
+        /// The <see cref="JsonSerializer"/> will not use default settings.
+        /// </summary>
+        /// <param name="settings">The settings to be applied to the <see cref="JsonSerializer"/>.</param>
+        /// <returns>
+        /// A new <see cref="JsonSerializer"/> instance using the specified <see cref="JsonSerializerSettings"/>.
+        /// The <see cref="JsonSerializer"/> will not use default settings.
+        /// </returns>
+        public static JsonSerializer Create(JsonSerializerSettings settings)
+        {
+            JsonSerializer serializer = Create();
+
+            if (settings != null)
+                ApplySerializerSettings(serializer, settings);
+
+            return serializer;
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="JsonSerializer"/> instance.
+        /// The <see cref="JsonSerializer"/> will use default settings.
+        /// </summary>
+        /// <returns>
+        /// A new <see cref="JsonSerializer"/> instance.
+        /// The <see cref="JsonSerializer"/> will use default settings.
+        /// </returns>
+        public static JsonSerializer CreateDefault()
+        {
+            // copy static to local variable to avoid concurrency issues
+            Func<JsonSerializerSettings> defaultSettingsCreator = JsonConvert.DefaultSettings;
+            JsonSerializerSettings defaultSettings = (defaultSettingsCreator != null) ? defaultSettingsCreator() : null;
+
+            return Create(defaultSettings);
+        }
+
+        /// <summary>
+        /// Creates a new <see cref="JsonSerializer"/> instance using the specified <see cref="JsonSerializerSettings"/>.
+        /// The <see cref="JsonSerializer"/> will use default settings.
+        /// </summary>
+        /// <param name="settings">The settings to be applied to the <see cref="JsonSerializer"/>.</param>
+        /// <returns>
+        /// A new <see cref="JsonSerializer"/> instance using the specified <see cref="JsonSerializerSettings"/>.
+        /// The <see cref="JsonSerializer"/> will use default settings.
+        /// </returns>
+        public static JsonSerializer CreateDefault(JsonSerializerSettings settings)
+        {
+            JsonSerializer serializer = CreateDefault();
+            if (settings != null)
+                ApplySerializerSettings(serializer, settings);
+
+            return serializer;
+        }
+
+        private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings)
+        {
+            if (!CollectionUtils.IsNullOrEmpty(settings.Converters))
+            {
+                // insert settings converters at the beginning so they take precedence
+                // if user wants to remove one of the default converters they will have to do it manually
+                for (int i = 0; i < settings.Converters.Count; i++)
+                {
+                    serializer.Converters.Insert(i, settings.Converters[i]);
+                }
+            }
+
+            // serializer specific
+            if (settings._typeNameHandling != null)
+                serializer.TypeNameHandling = settings.TypeNameHandling;
+            if (settings._metadataPropertyHandling != null)
+                serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling;
+            if (settings._typeNameAssemblyFormat != null)
+                serializer.TypeNameAssemblyFormat = settings.TypeNameAssemblyFormat;
+            if (settings._preserveReferencesHandling != null)
+                serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling;
+            if (settings._referenceLoopHandling != null)
+                serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling;
+            if (settings._missingMemberHandling != null)
+                serializer.MissingMemberHandling = settings.MissingMemberHandling;
+            if (settings._objectCreationHandling != null)
+                serializer.ObjectCreationHandling = settings.ObjectCreationHandling;
+            if (settings._nullValueHandling != null)
+                serializer.NullValueHandling = settings.NullValueHandling;
+            if (settings._defaultValueHandling != null)
+                serializer.DefaultValueHandling = settings.DefaultValueHandling;
+            if (settings._constructorHandling != null)
+                serializer.ConstructorHandling = settings.ConstructorHandling;
+            if (settings._context != null)
+                serializer.Context = settings.Context;
+            if (settings._checkAdditionalContent != null)
+                serializer._checkAdditionalContent = settings._checkAdditionalContent;
+
+            if (settings.Error != null)
+                serializer.Error += settings.Error;
+
+            if (settings.ContractResolver != null)
+                serializer.ContractResolver = settings.ContractResolver;
+            if (settings.ReferenceResolver != null)
+                serializer.ReferenceResolver = settings.ReferenceResolver;
+            if (settings.TraceWriter != null)
+                serializer.TraceWriter = settings.TraceWriter;
+            if (settings.Binder != null)
+                serializer.Binder = settings.Binder;
+
+            // reader/writer specific
+            // unset values won't override reader/writer set values
+            if (settings._formatting != null)
+                serializer._formatting = settings._formatting;
+            if (settings._dateFormatHandling != null)
+                serializer._dateFormatHandling = settings._dateFormatHandling;
+            if (settings._dateTimeZoneHandling != null)
+                serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling;
+            if (settings._dateParseHandling != null)
+                serializer._dateParseHandling = settings._dateParseHandling;
+            if (settings._dateFormatStringSet)
+            {
+                serializer._dateFormatString = settings._dateFormatString;
+                serializer._dateFormatStringSet = settings._dateFormatStringSet;
+            }
+            if (settings._floatFormatHandling != null)
+                serializer._floatFormatHandling = settings._floatFormatHandling;
+            if (settings._floatParseHandling != null)
+                serializer._floatParseHandling = settings._floatParseHandling;
+            if (settings._stringEscapeHandling != null)
+                serializer._stringEscapeHandling = settings._stringEscapeHandling;
+            if (settings._culture != null)
+                serializer._culture = settings._culture;
+            if (settings._maxDepthSet)
+            {
+                serializer._maxDepth = settings._maxDepth;
+                serializer._maxDepthSet = settings._maxDepthSet;
+            }
+        }
+
+        /// <summary>
+        /// Populates the JSON values onto the target object.
+        /// </summary>
+        /// <param name="reader">The <see cref="TextReader"/> that contains the JSON structure to reader values from.</param>
+        /// <param name="target">The target object to populate values onto.</param>
+        public void Populate(TextReader reader, object target)
+        {
+            Populate(new JsonTextReader(reader), target);
+        }
+
+        /// <summary>
+        /// Populates the JSON values onto the target object.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> that contains the JSON structure to reader values from.</param>
+        /// <param name="target">The target object to populate values onto.</param>
+        public void Populate(JsonReader reader, object target)
+        {
+            PopulateInternal(reader, target);
+        }
+
+        internal virtual void PopulateInternal(JsonReader reader, object target)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+            ValidationUtils.ArgumentNotNull(target, "target");
+
+            JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
+            serializerReader.Populate(reader, target);
+        }
+
+        /// <summary>
+        /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> that contains the JSON structure to deserialize.</param>
+        /// <returns>The <see cref="Object"/> being deserialized.</returns>
+        public object Deserialize(JsonReader reader)
+        {
+            return Deserialize(reader, null);
+        }
+
+        /// <summary>
+        /// Deserializes the Json structure contained by the specified <see cref="StringReader"/>
+        /// into an instance of the specified type.
+        /// </summary>
+        /// <param name="reader">The <see cref="TextReader"/> containing the object.</param>
+        /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
+        /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
+        public object Deserialize(TextReader reader, Type objectType)
+        {
+            return Deserialize(new JsonTextReader(reader), objectType);
+        }
+
+        /// <summary>
+        /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>
+        /// into an instance of the specified type.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> containing the object.</param>
+        /// <typeparam name="T">The type of the object to deserialize.</typeparam>
+        /// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
+        public T Deserialize<T>(JsonReader reader)
+        {
+            return (T)Deserialize(reader, typeof(T));
+        }
+
+        /// <summary>
+        /// Deserializes the Json structure contained by the specified <see cref="JsonReader"/>
+        /// into an instance of the specified type.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> containing the object.</param>
+        /// <param name="objectType">The <see cref="Type"/> of object being deserialized.</param>
+        /// <returns>The instance of <paramref name="objectType"/> being deserialized.</returns>
+        public object Deserialize(JsonReader reader, Type objectType)
+        {
+            return DeserializeInternal(reader, objectType);
+        }
+
+        internal virtual object DeserializeInternal(JsonReader reader, Type objectType)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            // set serialization options onto reader
+            CultureInfo previousCulture = null;
+            if (_culture != null && !_culture.Equals(reader.Culture))
+            {
+                previousCulture = reader.Culture;
+                reader.Culture = _culture;
+            }
+
+            DateTimeZoneHandling? previousDateTimeZoneHandling = null;
+            if (_dateTimeZoneHandling != null && reader.DateTimeZoneHandling != _dateTimeZoneHandling)
+            {
+                previousDateTimeZoneHandling = reader.DateTimeZoneHandling;
+                reader.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
+            }
+
+            DateParseHandling? previousDateParseHandling = null;
+            if (_dateParseHandling != null && reader.DateParseHandling != _dateParseHandling)
+            {
+                previousDateParseHandling = reader.DateParseHandling;
+                reader.DateParseHandling = _dateParseHandling.Value;
+            }
+
+            FloatParseHandling? previousFloatParseHandling = null;
+            if (_floatParseHandling != null && reader.FloatParseHandling != _floatParseHandling)
+            {
+                previousFloatParseHandling = reader.FloatParseHandling;
+                reader.FloatParseHandling = _floatParseHandling.Value;
+            }
+
+            int? previousMaxDepth = null;
+            if (_maxDepthSet && reader.MaxDepth != _maxDepth)
+            {
+                previousMaxDepth = reader.MaxDepth;
+                reader.MaxDepth = _maxDepth;
+            }
+
+            string previousDateFormatString = null;
+            if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString)
+            {
+                previousDateFormatString = reader.DateFormatString;
+                reader.DateFormatString = _dateFormatString;
+            }
+
+            TraceJsonReader traceJsonReader = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                ? new TraceJsonReader(reader)
+                : null;
+
+            JsonSerializerInternalReader serializerReader = new JsonSerializerInternalReader(this);
+            object value = serializerReader.Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent);
+
+            if (traceJsonReader != null)
+                TraceWriter.Trace(TraceLevel.Verbose, "Deserialized JSON: " + Environment.NewLine + traceJsonReader.GetJson(), null);
+
+            // reset reader back to previous options
+            if (previousCulture != null)
+                reader.Culture = previousCulture;
+            if (previousDateTimeZoneHandling != null)
+                reader.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
+            if (previousDateParseHandling != null)
+                reader.DateParseHandling = previousDateParseHandling.Value;
+            if (previousFloatParseHandling != null)
+                reader.FloatParseHandling = previousFloatParseHandling.Value;
+            if (_maxDepthSet)
+                reader.MaxDepth = previousMaxDepth;
+            if (_dateFormatStringSet)
+                reader.DateFormatString = previousDateFormatString;
+
+            return value;
+        }
+
+        /// <summary>
+        /// Serializes the specified <see cref="Object"/> and writes the Json structure
+        /// to a <c>Stream</c> using the specified <see cref="TextWriter"/>. 
+        /// </summary>
+        /// <param name="textWriter">The <see cref="TextWriter"/> used to write the Json structure.</param>
+        /// <param name="value">The <see cref="Object"/> to serialize.</param>
+        public void Serialize(TextWriter textWriter, object value)
+        {
+            Serialize(new JsonTextWriter(textWriter), value);
+        }
+
+        /// <summary>
+        /// Serializes the specified <see cref="Object"/> and writes the Json structure
+        /// to a <c>Stream</c> using the specified <see cref="TextWriter"/>. 
+        /// </summary>
+        /// <param name="jsonWriter">The <see cref="JsonWriter"/> used to write the Json structure.</param>
+        /// <param name="value">The <see cref="Object"/> to serialize.</param>
+        /// <param name="objectType">
+        /// The type of the value being serialized.
+        /// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match.
+        /// Specifing the type is optional.
+        /// </param>
+        public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
+        {
+            SerializeInternal(jsonWriter, value, objectType);
+        }
+
+        /// <summary>
+        /// Serializes the specified <see cref="Object"/> and writes the Json structure
+        /// to a <c>Stream</c> using the specified <see cref="TextWriter"/>. 
+        /// </summary>
+        /// <param name="textWriter">The <see cref="TextWriter"/> used to write the Json structure.</param>
+        /// <param name="value">The <see cref="Object"/> to serialize.</param>
+        /// <param name="objectType">
+        /// The type of the value being serialized.
+        /// This parameter is used when <see cref="TypeNameHandling"/> is Auto to write out the type name if the type of the value does not match.
+        /// Specifing the type is optional.
+        /// </param>
+        public void Serialize(TextWriter textWriter, object value, Type objectType)
+        {
+            Serialize(new JsonTextWriter(textWriter), value, objectType);
+        }
+
+        /// <summary>
+        /// Serializes the specified <see cref="Object"/> and writes the Json structure
+        /// to a <c>Stream</c> using the specified <see cref="JsonWriter"/>. 
+        /// </summary>
+        /// <param name="jsonWriter">The <see cref="JsonWriter"/> used to write the Json structure.</param>
+        /// <param name="value">The <see cref="Object"/> to serialize.</param>
+        public void Serialize(JsonWriter jsonWriter, object value)
+        {
+            SerializeInternal(jsonWriter, value, null);
+        }
+
+        internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType)
+        {
+            ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter");
+
+            // set serialization options onto writer
+            Formatting? previousFormatting = null;
+            if (_formatting != null && jsonWriter.Formatting != _formatting)
+            {
+                previousFormatting = jsonWriter.Formatting;
+                jsonWriter.Formatting = _formatting.Value;
+            }
+
+            DateFormatHandling? previousDateFormatHandling = null;
+            if (_dateFormatHandling != null && jsonWriter.DateFormatHandling != _dateFormatHandling)
+            {
+                previousDateFormatHandling = jsonWriter.DateFormatHandling;
+                jsonWriter.DateFormatHandling = _dateFormatHandling.Value;
+            }
+
+            DateTimeZoneHandling? previousDateTimeZoneHandling = null;
+            if (_dateTimeZoneHandling != null && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling)
+            {
+                previousDateTimeZoneHandling = jsonWriter.DateTimeZoneHandling;
+                jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.Value;
+            }
+
+            FloatFormatHandling? previousFloatFormatHandling = null;
+            if (_floatFormatHandling != null && jsonWriter.FloatFormatHandling != _floatFormatHandling)
+            {
+                previousFloatFormatHandling = jsonWriter.FloatFormatHandling;
+                jsonWriter.FloatFormatHandling = _floatFormatHandling.Value;
+            }
+
+            StringEscapeHandling? previousStringEscapeHandling = null;
+            if (_stringEscapeHandling != null && jsonWriter.StringEscapeHandling != _stringEscapeHandling)
+            {
+                previousStringEscapeHandling = jsonWriter.StringEscapeHandling;
+                jsonWriter.StringEscapeHandling = _stringEscapeHandling.Value;
+            }
+
+            CultureInfo previousCulture = null;
+            if (_culture != null && !_culture.Equals(jsonWriter.Culture))
+            {
+                previousCulture = jsonWriter.Culture;
+                jsonWriter.Culture = _culture;
+            }
+
+            string previousDateFormatString = null;
+            if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString)
+            {
+                previousDateFormatString = jsonWriter.DateFormatString;
+                jsonWriter.DateFormatString = _dateFormatString;
+            }
+
+            TraceJsonWriter traceJsonWriter = (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                ? new TraceJsonWriter(jsonWriter)
+                : null;
+
+            JsonSerializerInternalWriter serializerWriter = new JsonSerializerInternalWriter(this);
+            serializerWriter.Serialize(traceJsonWriter ?? jsonWriter, value, objectType);
+
+            if (traceJsonWriter != null)
+                TraceWriter.Trace(TraceLevel.Verbose, "Serialized JSON: " + Environment.NewLine + traceJsonWriter.GetJson(), null);
+
+            // reset writer back to previous options
+            if (previousFormatting != null)
+                jsonWriter.Formatting = previousFormatting.Value;
+            if (previousDateFormatHandling != null)
+                jsonWriter.DateFormatHandling = previousDateFormatHandling.Value;
+            if (previousDateTimeZoneHandling != null)
+                jsonWriter.DateTimeZoneHandling = previousDateTimeZoneHandling.Value;
+            if (previousFloatFormatHandling != null)
+                jsonWriter.FloatFormatHandling = previousFloatFormatHandling.Value;
+            if (previousStringEscapeHandling != null)
+                jsonWriter.StringEscapeHandling = previousStringEscapeHandling.Value;
+            if (_dateFormatStringSet)
+                jsonWriter.DateFormatString = previousDateFormatString;
+            if (previousCulture != null)
+                jsonWriter.Culture = previousCulture;
+        }
+
+        internal IReferenceResolver GetReferenceResolver()
+        {
+            if (_referenceResolver == null)
+                _referenceResolver = new DefaultReferenceResolver();
+
+            return _referenceResolver;
+        }
+
+        internal JsonConverter GetMatchingConverter(Type type)
+        {
+            return GetMatchingConverter(_converters, type);
+        }
+
+        internal static JsonConverter GetMatchingConverter(IList<JsonConverter> converters, Type objectType)
+        {
+#if DEBUG
+            ValidationUtils.ArgumentNotNull(objectType, "objectType");
+#endif
+
+            if (converters != null)
+            {
+                for (int i = 0; i < converters.Count; i++)
+                {
+                    JsonConverter converter = converters[i];
+
+                    if (converter.CanConvert(objectType))
+                        return converter;
+                }
+            }
+
+            return null;
+        }
+
+        internal void OnError(ErrorEventArgs e)
+        {
+            EventHandler<ErrorEventArgs> error = Error;
+            if (error != null)
+                error(this, e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonSerializerSettings.cs b/Newtonsoft.Json/JsonSerializerSettings.cs
new file mode 100644
index 0000000..3bdacdb
--- /dev/null
+++ b/Newtonsoft.Json/JsonSerializerSettings.cs
@@ -0,0 +1,365 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Runtime.Serialization.Formatters;
+using Newtonsoft.Json.Serialization;
+using System.Runtime.Serialization;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies the settings on a <see cref="JsonSerializer"/> object.
+    /// </summary>
+    public class JsonSerializerSettings
+    {
+        internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error;
+        internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore;
+        internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include;
+        internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include;
+        internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto;
+        internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None;
+        internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default;
+        internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None;
+        internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default;
+        internal const FormatterAssemblyStyle DefaultTypeNameAssemblyFormat = FormatterAssemblyStyle.Simple;
+        internal static readonly StreamingContext DefaultContext;
+
+        internal const Formatting DefaultFormatting = Formatting.None;
+        internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat;
+        internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+        internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime;
+        internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double;
+        internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String;
+        internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default;
+        internal const FormatterAssemblyStyle DefaultFormatterAssemblyStyle = FormatterAssemblyStyle.Simple;
+        internal static readonly CultureInfo DefaultCulture;
+        internal const bool DefaultCheckAdditionalContent = false;
+        internal const string DefaultDateFormatString = @"yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK";
+
+        internal Formatting? _formatting;
+        internal DateFormatHandling? _dateFormatHandling;
+        internal DateTimeZoneHandling? _dateTimeZoneHandling;
+        internal DateParseHandling? _dateParseHandling;
+        internal FloatFormatHandling? _floatFormatHandling;
+        internal FloatParseHandling? _floatParseHandling;
+        internal StringEscapeHandling? _stringEscapeHandling;
+        internal CultureInfo _culture;
+        internal bool? _checkAdditionalContent;
+        internal int? _maxDepth;
+        internal bool _maxDepthSet;
+        internal string _dateFormatString;
+        internal bool _dateFormatStringSet;
+        internal FormatterAssemblyStyle? _typeNameAssemblyFormat;
+        internal DefaultValueHandling? _defaultValueHandling;
+        internal PreserveReferencesHandling? _preserveReferencesHandling;
+        internal NullValueHandling? _nullValueHandling;
+        internal ObjectCreationHandling? _objectCreationHandling;
+        internal MissingMemberHandling? _missingMemberHandling;
+        internal ReferenceLoopHandling? _referenceLoopHandling;
+        internal StreamingContext? _context;
+        internal ConstructorHandling? _constructorHandling;
+        internal TypeNameHandling? _typeNameHandling;
+        internal MetadataPropertyHandling? _metadataPropertyHandling;
+
+        /// <summary>
+        /// Gets or sets how reference loops (e.g. a class referencing itself) is handled.
+        /// </summary>
+        /// <value>Reference loop handling.</value>
+        public ReferenceLoopHandling ReferenceLoopHandling
+        {
+            get { return _referenceLoopHandling ?? DefaultReferenceLoopHandling; }
+            set { _referenceLoopHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization.
+        /// </summary>
+        /// <value>Missing member handling.</value>
+        public MissingMemberHandling MissingMemberHandling
+        {
+            get { return _missingMemberHandling ?? DefaultMissingMemberHandling; }
+            set { _missingMemberHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how objects are created during deserialization.
+        /// </summary>
+        /// <value>The object creation handling.</value>
+        public ObjectCreationHandling ObjectCreationHandling
+        {
+            get { return _objectCreationHandling ?? DefaultObjectCreationHandling; }
+            set { _objectCreationHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how null values are handled during serialization and deserialization.
+        /// </summary>
+        /// <value>Null value handling.</value>
+        public NullValueHandling NullValueHandling
+        {
+            get { return _nullValueHandling ?? DefaultNullValueHandling; }
+            set { _nullValueHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how null default are handled during serialization and deserialization.
+        /// </summary>
+        /// <value>The default value handling.</value>
+        public DefaultValueHandling DefaultValueHandling
+        {
+            get { return _defaultValueHandling ?? DefaultDefaultValueHandling; }
+            set { _defaultValueHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a collection <see cref="JsonConverter"/> that will be used during serialization.
+        /// </summary>
+        /// <value>The converters.</value>
+        public IList<JsonConverter> Converters { get; set; }
+
+        /// <summary>
+        /// Gets or sets how object references are preserved by the serializer.
+        /// </summary>
+        /// <value>The preserve references handling.</value>
+        public PreserveReferencesHandling PreserveReferencesHandling
+        {
+            get { return _preserveReferencesHandling ?? DefaultPreserveReferencesHandling; }
+            set { _preserveReferencesHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how type name writing and reading is handled by the serializer.
+        /// </summary>
+        /// <value>The type name handling.</value>
+        public TypeNameHandling TypeNameHandling
+        {
+            get { return _typeNameHandling ?? DefaultTypeNameHandling; }
+            set { _typeNameHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how metadata properties are used during deserialization.
+        /// </summary>
+        /// <value>The metadata properties handling.</value>
+        public MetadataPropertyHandling MetadataPropertyHandling
+        {
+            get { return _metadataPropertyHandling ?? DefaultMetadataPropertyHandling; }
+            set { _metadataPropertyHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how a type name assembly is written and resolved by the serializer.
+        /// </summary>
+        /// <value>The type name assembly format.</value>
+        public FormatterAssemblyStyle TypeNameAssemblyFormat
+        {
+            get { return _typeNameAssemblyFormat ?? DefaultFormatterAssemblyStyle; }
+            set { _typeNameAssemblyFormat = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets how constructors are used during deserialization.
+        /// </summary>
+        /// <value>The constructor handling.</value>
+        public ConstructorHandling ConstructorHandling
+        {
+            get { return _constructorHandling ?? DefaultConstructorHandling; }
+            set { _constructorHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the contract resolver used by the serializer when
+        /// serializing .NET objects to JSON and vice versa.
+        /// </summary>
+        /// <value>The contract resolver.</value>
+        public IContractResolver ContractResolver { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="IReferenceResolver"/> used by the serializer when resolving references.
+        /// </summary>
+        /// <value>The reference resolver.</value>
+        public IReferenceResolver ReferenceResolver { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="ITraceWriter"/> used by the serializer when writing trace messages.
+        /// </summary>
+        /// <value>The trace writer.</value>
+        public ITraceWriter TraceWriter { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="SerializationBinder"/> used by the serializer when resolving type names.
+        /// </summary>
+        /// <value>The binder.</value>
+        public SerializationBinder Binder { get; set; }
+
+        /// <summary>
+        /// Gets or sets the error handler called during serialization and deserialization.
+        /// </summary>
+        /// <value>The error handler called during serialization and deserialization.</value>
+        public EventHandler<ErrorEventArgs> Error { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="StreamingContext"/> used by the serializer when invoking serialization callback methods.
+        /// </summary>
+        /// <value>The context.</value>
+        public StreamingContext Context
+        {
+            get { return _context ?? DefaultContext; }
+            set { _context = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> and <see cref="DateTimeOffset"/> values are formatting when writing JSON text.
+        /// </summary>
+        public string DateFormatString
+        {
+            get { return _dateFormatString ?? DefaultDateFormatString; }
+            set
+            {
+                _dateFormatString = value;
+                _dateFormatStringSet = true;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a <see cref="JsonReaderException"/>.
+        /// </summary>
+        public int? MaxDepth
+        {
+            get { return _maxDepth; }
+            set
+            {
+                if (value <= 0)
+                    throw new ArgumentException("Value must be positive.", "value");
+
+                _maxDepth = value;
+                _maxDepthSet = true;
+            }
+        }
+
+        /// <summary>
+        /// Indicates how JSON text output is formatted.
+        /// </summary>
+        public Formatting Formatting
+        {
+            get { return _formatting ?? DefaultFormatting; }
+            set { _formatting = value; }
+        }
+
+        /// <summary>
+        /// Get or set how dates are written to JSON text.
+        /// </summary>
+        public DateFormatHandling DateFormatHandling
+        {
+            get { return _dateFormatHandling ?? DefaultDateFormatHandling; }
+            set { _dateFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> time zones are handling during serialization and deserialization.
+        /// </summary>
+        public DateTimeZoneHandling DateTimeZoneHandling
+        {
+            get { return _dateTimeZoneHandling ?? DefaultDateTimeZoneHandling; }
+            set { _dateTimeZoneHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON.
+        /// </summary>
+        public DateParseHandling DateParseHandling
+        {
+            get { return _dateParseHandling ?? DefaultDateParseHandling; }
+            set { _dateParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how special floating point numbers, e.g. <see cref="F:System.Double.NaN"/>,
+        /// <see cref="F:System.Double.PositiveInfinity"/> and <see cref="F:System.Double.NegativeInfinity"/>,
+        /// are written as JSON.
+        /// </summary>
+        public FloatFormatHandling FloatFormatHandling
+        {
+            get { return _floatFormatHandling ?? DefaultFloatFormatHandling; }
+            set { _floatFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text.
+        /// </summary>
+        public FloatParseHandling FloatParseHandling
+        {
+            get { return _floatParseHandling ?? DefaultFloatParseHandling; }
+            set { _floatParseHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how strings are escaped when writing JSON text.
+        /// </summary>
+        public StringEscapeHandling StringEscapeHandling
+        {
+            get { return _stringEscapeHandling ?? DefaultStringEscapeHandling; }
+            set { _stringEscapeHandling = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the culture used when reading JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
+        /// </summary>
+        public CultureInfo Culture
+        {
+            get { return _culture ?? DefaultCulture; }
+            set { _culture = value; }
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether there will be a check for additional content after deserializing an object.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if there will be a check for additional content after deserializing an object; otherwise, <c>false</c>.
+        /// </value>
+        public bool CheckAdditionalContent
+        {
+            get { return _checkAdditionalContent ?? DefaultCheckAdditionalContent; }
+            set { _checkAdditionalContent = value; }
+        }
+
+        static JsonSerializerSettings()
+        {
+            DefaultContext = new StreamingContext();
+            DefaultCulture = CultureInfo.InvariantCulture;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSerializerSettings"/> class.
+        /// </summary>
+        public JsonSerializerSettings()
+        {
+            Converters = new List<JsonConverter>();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonTextReader.cs b/Newtonsoft.Json/JsonTextReader.cs
new file mode 100644
index 0000000..5244fd0
--- /dev/null
+++ b/Newtonsoft.Json/JsonTextReader.cs
@@ -0,0 +1,1615 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using System.IO;
+using System.Xml;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+    internal enum ReadType
+    {
+        Read,
+        ReadAsInt32,
+        ReadAsBytes,
+        ReadAsString,
+        ReadAsDecimal,
+        ReadAsDateTime,
+#if !NET20
+        ReadAsDateTimeOffset
+#endif
+    }
+
+    /// <summary>
+    /// Represents a reader that provides fast, non-cached, forward-only access to JSON text data.
+    /// </summary>
+    public class JsonTextReader : JsonReader, IJsonLineInfo
+    {
+        private const char UnicodeReplacementChar = '\uFFFD';
+
+        private readonly TextReader _reader;
+        private char[] _chars;
+        private int _charsUsed;
+        private int _charPos;
+        private int _lineStartPos;
+        private int _lineNumber;
+        private bool _isEndOfFile;
+        private StringBuffer _buffer;
+        private StringReference _stringReference;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonReader"/> class with the specified <see cref="TextReader"/>.
+        /// </summary>
+        /// <param name="reader">The <c>TextReader</c> containing the XML data to read.</param>
+        public JsonTextReader(TextReader reader)
+        {
+            if (reader == null)
+                throw new ArgumentNullException("reader");
+
+            _reader = reader;
+            _lineNumber = 1;
+            _chars = new char[1025];
+        }
+
+#if DEBUG
+        internal void SetCharBuffer(char[] chars)
+        {
+            _chars = chars;
+        }
+#endif
+
+        private StringBuffer GetBuffer()
+        {
+            if (_buffer == null)
+            {
+                _buffer = new StringBuffer(1025);
+            }
+            else
+            {
+                _buffer.Position = 0;
+            }
+
+            return _buffer;
+        }
+
+        private void OnNewLine(int pos)
+        {
+            _lineNumber++;
+            _lineStartPos = pos - 1;
+        }
+
+        private void ParseString(char quote)
+        {
+            _charPos++;
+
+            ShiftBufferIfNeeded();
+            ReadStringIntoBuffer(quote);
+
+            if (_readType == ReadType.ReadAsBytes)
+            {
+                byte[] data;
+                if (_stringReference.Length == 0)
+                {
+                    data = new byte[0];
+                }
+                else
+                {
+                    data = Convert.FromBase64CharArray(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length);
+                }
+
+                SetToken(JsonToken.Bytes, data);
+            }
+            else if (_readType == ReadType.ReadAsString)
+            {
+                string text = _stringReference.ToString();
+
+                SetToken(JsonToken.String, text);
+                _quoteChar = quote;
+            }
+            else
+            {
+                string text = _stringReference.ToString();
+
+                if (_dateParseHandling != DateParseHandling.None)
+                {
+                    DateParseHandling dateParseHandling;
+                    if (_readType == ReadType.ReadAsDateTime)
+                        dateParseHandling = DateParseHandling.DateTime;
+#if !NET20
+                    else if (_readType == ReadType.ReadAsDateTimeOffset)
+                        dateParseHandling = DateParseHandling.DateTimeOffset;
+#endif
+                    else
+                        dateParseHandling = _dateParseHandling;
+
+                    object dt;
+                    if (DateTimeUtils.TryParseDateTime(text, dateParseHandling, DateTimeZoneHandling, DateFormatString, Culture, out dt))
+                    {
+                        SetToken(JsonToken.Date, dt);
+                        return;
+                    }
+                }
+
+                SetToken(JsonToken.String, text);
+                _quoteChar = quote;
+            }
+        }
+
+        private static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count)
+        {
+            const int charByteCount = 2;
+
+            Buffer.BlockCopy(src, srcOffset * charByteCount, dst, dstOffset * charByteCount, count * charByteCount);
+        }
+
+        private void ShiftBufferIfNeeded()
+        {
+            // once in the last 10% of the buffer shift the remainling content to the start to avoid
+            // unnessesarly increasing the buffer size when reading numbers/strings
+            int length = _chars.Length;
+            if (length - _charPos <= length * 0.1)
+            {
+                int count = _charsUsed - _charPos;
+                if (count > 0)
+                    BlockCopyChars(_chars, _charPos, _chars, 0, count);
+
+                _lineStartPos -= _charPos;
+                _charPos = 0;
+                _charsUsed = count;
+                _chars[_charsUsed] = '\0';
+            }
+        }
+
+        private int ReadData(bool append)
+        {
+            return ReadData(append, 0);
+        }
+
+        private int ReadData(bool append, int charsRequired)
+        {
+            if (_isEndOfFile)
+                return 0;
+
+            // char buffer is full
+            if (_charsUsed + charsRequired >= _chars.Length - 1)
+            {
+                if (append)
+                {
+                    // copy to new array either double the size of the current or big enough to fit required content
+                    int newArrayLength = Math.Max(_chars.Length * 2, _charsUsed + charsRequired + 1);
+
+                    // increase the size of the buffer
+                    char[] dst = new char[newArrayLength];
+
+                    BlockCopyChars(_chars, 0, dst, 0, _chars.Length);
+
+                    _chars = dst;
+                }
+                else
+                {
+                    int remainingCharCount = _charsUsed - _charPos;
+
+                    if (remainingCharCount + charsRequired + 1 >= _chars.Length)
+                    {
+                        // the remaining count plus the required is bigger than the current buffer size
+                        char[] dst = new char[remainingCharCount + charsRequired + 1];
+
+                        if (remainingCharCount > 0)
+                            BlockCopyChars(_chars, _charPos, dst, 0, remainingCharCount);
+
+                        _chars = dst;
+                    }
+                    else
+                    {
+                        // copy any remaining data to the beginning of the buffer if needed and reset positions
+                        if (remainingCharCount > 0)
+                            BlockCopyChars(_chars, _charPos, _chars, 0, remainingCharCount);
+                    }
+
+                    _lineStartPos -= _charPos;
+                    _charPos = 0;
+                    _charsUsed = remainingCharCount;
+                }
+            }
+
+            int attemptCharReadCount = _chars.Length - _charsUsed - 1;
+
+            int charsRead = _reader.Read(_chars, _charsUsed, attemptCharReadCount);
+
+            _charsUsed += charsRead;
+
+            if (charsRead == 0)
+                _isEndOfFile = true;
+
+            _chars[_charsUsed] = '\0';
+            return charsRead;
+        }
+
+        private bool EnsureChars(int relativePosition, bool append)
+        {
+            if (_charPos + relativePosition >= _charsUsed)
+                return ReadChars(relativePosition, append);
+
+            return true;
+        }
+
+        private bool ReadChars(int relativePosition, bool append)
+        {
+            if (_isEndOfFile)
+                return false;
+
+            int charsRequired = _charPos + relativePosition - _charsUsed + 1;
+
+            int totalCharsRead = 0;
+
+            // it is possible that the TextReader doesn't return all data at once
+            // repeat read until the required text is returned or the reader is out of content
+            do
+            {
+                int charsRead = ReadData(append, charsRequired - totalCharsRead);
+
+                // no more content
+                if (charsRead == 0)
+                    break;
+
+                totalCharsRead += charsRead;
+            } while (totalCharsRead < charsRequired);
+
+            if (totalCharsRead < charsRequired)
+                return false;
+            return true;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream.
+        /// </summary>
+        /// <returns>
+        /// true if the next token was read successfully; false if there are no more tokens to read.
+        /// </returns>
+        [DebuggerStepThrough]
+        public override bool Read()
+        {
+            _readType = ReadType.Read;
+            if (!ReadInternal())
+            {
+                SetToken(JsonToken.None);
+                return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
+        /// </returns>
+        public override byte[] ReadAsBytes()
+        {
+            return ReadAsBytesInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override decimal? ReadAsDecimal()
+        {
+            return ReadAsDecimalInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override int? ReadAsInt32()
+        {
+            return ReadAsInt32Internal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="String"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override string ReadAsString()
+        {
+            return ReadAsStringInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTime? ReadAsDateTime()
+        {
+            return ReadAsDateTimeInternal();
+        }
+
+#if !NET20
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <returns>A <see cref="DateTimeOffset"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTimeOffset? ReadAsDateTimeOffset()
+        {
+            return ReadAsDateTimeOffsetInternal();
+        }
+#endif
+
+        internal override bool ReadInternal()
+        {
+            while (true)
+            {
+                switch (_currentState)
+                {
+                    case State.Start:
+                    case State.Property:
+                    case State.Array:
+                    case State.ArrayStart:
+                    case State.Constructor:
+                    case State.ConstructorStart:
+                        return ParseValue();
+                    case State.Complete:
+                        break;
+                    case State.Object:
+                    case State.ObjectStart:
+                        return ParseObject();
+                    case State.PostValue:
+                        // returns true if it hits
+                        // end of object or array
+                        if (ParsePostValue())
+                            return true;
+                        break;
+                    case State.Finished:
+                        if (EnsureChars(0, false))
+                        {
+                            EatWhitespace(false);
+                            if (_isEndOfFile)
+                            {
+                                return false;
+                            }
+                            if (_chars[_charPos] == '/')
+                            {
+                                ParseComment();
+                                return true;
+                            }
+                            else
+                            {
+                                throw JsonReaderException.Create(this, "Additional text encountered after finished reading JSON content: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+                            }
+                        }
+                        return false;
+                    case State.Closed:
+                        break;
+                    case State.Error:
+                        break;
+                    default:
+                        throw JsonReaderException.Create(this, "Unexpected state: {0}.".FormatWith(CultureInfo.InvariantCulture, CurrentState));
+                }
+            }
+        }
+
+        private void ReadStringIntoBuffer(char quote)
+        {
+            int charPos = _charPos;
+            int initialPosition = _charPos;
+            int lastWritePosition = _charPos;
+            StringBuffer buffer = null;
+
+            while (true)
+            {
+                switch (_chars[charPos++])
+                {
+                    case '\0':
+                        if (_charsUsed == charPos - 1)
+                        {
+                            charPos--;
+
+                            if (ReadData(true) == 0)
+                            {
+                                _charPos = charPos;
+                                throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
+                            }
+                        }
+                        break;
+                    case '\\':
+                        _charPos = charPos;
+                        if (!EnsureChars(0, true))
+                        {
+                            _charPos = charPos;
+                            throw JsonReaderException.Create(this, "Unterminated string. Expected delimiter: {0}.".FormatWith(CultureInfo.InvariantCulture, quote));
+                        }
+
+                        // start of escape sequence
+                        int escapeStartPos = charPos - 1;
+
+                        char currentChar = _chars[charPos];
+
+                        char writeChar;
+
+                        switch (currentChar)
+                        {
+                            case 'b':
+                                charPos++;
+                                writeChar = '\b';
+                                break;
+                            case 't':
+                                charPos++;
+                                writeChar = '\t';
+                                break;
+                            case 'n':
+                                charPos++;
+                                writeChar = '\n';
+                                break;
+                            case 'f':
+                                charPos++;
+                                writeChar = '\f';
+                                break;
+                            case 'r':
+                                charPos++;
+                                writeChar = '\r';
+                                break;
+                            case '\\':
+                                charPos++;
+                                writeChar = '\\';
+                                break;
+                            case '"':
+                            case '\'':
+                            case '/':
+                                writeChar = currentChar;
+                                charPos++;
+                                break;
+                            case 'u':
+                                charPos++;
+                                _charPos = charPos;
+                                writeChar = ParseUnicode();
+
+                                if (StringUtils.IsLowSurrogate(writeChar))
+                                {
+                                    // low surrogate with no preceding high surrogate; this char is replaced
+                                    writeChar = UnicodeReplacementChar;
+                                }
+                                else if (StringUtils.IsHighSurrogate(writeChar))
+                                {
+                                    bool anotherHighSurrogate;
+
+                                    // loop for handling situations where there are multiple consecutive high surrogates
+                                    do
+                                    {
+                                        anotherHighSurrogate = false;
+
+                                        // potential start of a surrogate pair
+                                        if (EnsureChars(2, true) && _chars[_charPos] == '\\' && _chars[_charPos + 1] == 'u')
+                                        {
+                                            char highSurrogate = writeChar;
+
+                                            _charPos += 2;
+                                            writeChar = ParseUnicode();
+
+                                            if (StringUtils.IsLowSurrogate(writeChar))
+                                            {
+                                                // a valid surrogate pair!
+                                            }
+                                            else if (StringUtils.IsHighSurrogate(writeChar))
+                                            {
+                                                // another high surrogate; replace current and start check over
+                                                highSurrogate = UnicodeReplacementChar;
+                                                anotherHighSurrogate = true;
+                                            }
+                                            else
+                                            {
+                                                // high surrogate not followed by low surrogate; original char is replaced
+                                                highSurrogate = UnicodeReplacementChar;
+                                            }
+
+                                            if (buffer == null)
+                                                buffer = GetBuffer();
+
+                                            WriteCharToBuffer(buffer, highSurrogate, lastWritePosition, escapeStartPos);
+                                            lastWritePosition = _charPos;
+                                        }
+                                        else
+                                        {
+                                            // there are not enough remaining chars for the low surrogate or is not follow by unicode sequence
+                                            // replace high surrogate and continue on as usual
+                                            writeChar = UnicodeReplacementChar;
+                                        }
+                                    } while (anotherHighSurrogate);
+                                }
+
+                                charPos = _charPos;
+                                break;
+                            default:
+                                charPos++;
+                                _charPos = charPos;
+                                throw JsonReaderException.Create(this, "Bad JSON escape sequence: {0}.".FormatWith(CultureInfo.InvariantCulture, @"\" + currentChar));
+                        }
+
+                        if (buffer == null)
+                            buffer = GetBuffer();
+
+                        WriteCharToBuffer(buffer, writeChar, lastWritePosition, escapeStartPos);
+
+                        lastWritePosition = charPos;
+                        break;
+                    case StringUtils.CarriageReturn:
+                        _charPos = charPos - 1;
+                        ProcessCarriageReturn(true);
+                        charPos = _charPos;
+                        break;
+                    case StringUtils.LineFeed:
+                        _charPos = charPos - 1;
+                        ProcessLineFeed();
+                        charPos = _charPos;
+                        break;
+                    case '"':
+                    case '\'':
+                        if (_chars[charPos - 1] == quote)
+                        {
+                            charPos--;
+
+                            if (initialPosition == lastWritePosition)
+                            {
+                                _stringReference = new StringReference(_chars, initialPosition, charPos - initialPosition);
+                            }
+                            else
+                            {
+                                if (buffer == null)
+                                    buffer = GetBuffer();
+
+                                if (charPos > lastWritePosition)
+                                    buffer.Append(_chars, lastWritePosition, charPos - lastWritePosition);
+
+                                _stringReference = new StringReference(buffer.GetInternalBuffer(), 0, buffer.Position);
+                            }
+
+                            charPos++;
+                            _charPos = charPos;
+                            return;
+                        }
+                        break;
+                }
+            }
+        }
+
+        private void WriteCharToBuffer(StringBuffer buffer, char writeChar, int lastWritePosition, int writeToPosition)
+        {
+            if (writeToPosition > lastWritePosition)
+            {
+                buffer.Append(_chars, lastWritePosition, writeToPosition - lastWritePosition);
+            }
+
+            buffer.Append(writeChar);
+        }
+
+        private char ParseUnicode()
+        {
+            char writeChar;
+            if (EnsureChars(4, true))
+            {
+                string hexValues = new string(_chars, _charPos, 4);
+                char hexChar = Convert.ToChar(int.Parse(hexValues, NumberStyles.HexNumber, NumberFormatInfo.InvariantInfo));
+                writeChar = hexChar;
+
+                _charPos += 4;
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Unexpected end while parsing unicode character.");
+            }
+            return writeChar;
+        }
+
+        private void ReadNumberIntoBuffer()
+        {
+            int charPos = _charPos;
+
+            while (true)
+            {
+                switch (_chars[charPos++])
+                {
+                    case '\0':
+                        if (_charsUsed == charPos - 1)
+                        {
+                            charPos--;
+                            _charPos = charPos;
+                            if (ReadData(true) == 0)
+                                return;
+                        }
+                        else
+                        {
+                            _charPos = charPos - 1;
+                            return;
+                        }
+                        break;
+                    case '-':
+                    case '+':
+                    case 'a':
+                    case 'A':
+                    case 'b':
+                    case 'B':
+                    case 'c':
+                    case 'C':
+                    case 'd':
+                    case 'D':
+                    case 'e':
+                    case 'E':
+                    case 'f':
+                    case 'F':
+                    case 'x':
+                    case 'X':
+                    case '.':
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        break;
+                    default:
+                        _charPos = charPos - 1;
+                        return;
+                }
+            }
+        }
+
+        private void ClearRecentString()
+        {
+            if (_buffer != null)
+                _buffer.Position = 0;
+
+            _stringReference = new StringReference();
+        }
+
+        private bool ParsePostValue()
+        {
+            while (true)
+            {
+                char currentChar = _chars[_charPos];
+
+                switch (currentChar)
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(false) == 0)
+                            {
+                                _currentState = State.Finished;
+                                return false;
+                            }
+                        }
+                        else
+                        {
+                            _charPos++;
+                        }
+                        break;
+                    case '}':
+                        _charPos++;
+                        SetToken(JsonToken.EndObject);
+                        return true;
+                    case ']':
+                        _charPos++;
+                        SetToken(JsonToken.EndArray);
+                        return true;
+                    case ')':
+                        _charPos++;
+                        SetToken(JsonToken.EndConstructor);
+                        return true;
+                    case '/':
+                        ParseComment();
+                        return true;
+                    case ',':
+                        _charPos++;
+
+                        // finished parsing
+                        SetStateBasedOnCurrent();
+                        return false;
+                    case ' ':
+                    case StringUtils.Tab:
+                        // eat
+                        _charPos++;
+                        break;
+                    case StringUtils.CarriageReturn:
+                        ProcessCarriageReturn(false);
+                        break;
+                    case StringUtils.LineFeed:
+                        ProcessLineFeed();
+                        break;
+                    default:
+                        if (char.IsWhiteSpace(currentChar))
+                        {
+                            // eat
+                            _charPos++;
+                        }
+                        else
+                        {
+                            throw JsonReaderException.Create(this, "After parsing a value an unexpected character was encountered: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+                        }
+                        break;
+                }
+            }
+        }
+
+        private bool ParseObject()
+        {
+            while (true)
+            {
+                char currentChar = _chars[_charPos];
+
+                switch (currentChar)
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(false) == 0)
+                                return false;
+                        }
+                        else
+                        {
+                            _charPos++;
+                        }
+                        break;
+                    case '}':
+                        SetToken(JsonToken.EndObject);
+                        _charPos++;
+                        return true;
+                    case '/':
+                        ParseComment();
+                        return true;
+                    case StringUtils.CarriageReturn:
+                        ProcessCarriageReturn(false);
+                        break;
+                    case StringUtils.LineFeed:
+                        ProcessLineFeed();
+                        break;
+                    case ' ':
+                    case StringUtils.Tab:
+                        // eat
+                        _charPos++;
+                        break;
+                    default:
+                        if (char.IsWhiteSpace(currentChar))
+                        {
+                            // eat
+                            _charPos++;
+                        }
+                        else
+                        {
+                            return ParseProperty();
+                        }
+                        break;
+                }
+            }
+        }
+
+        private bool ParseProperty()
+        {
+            char firstChar = _chars[_charPos];
+            char quoteChar;
+
+            if (firstChar == '"' || firstChar == '\'')
+            {
+                _charPos++;
+                quoteChar = firstChar;
+                ShiftBufferIfNeeded();
+                ReadStringIntoBuffer(quoteChar);
+            }
+            else if (ValidIdentifierChar(firstChar))
+            {
+                quoteChar = '\0';
+                ShiftBufferIfNeeded();
+                ParseUnquotedProperty();
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Invalid property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+            }
+
+            string propertyName = _stringReference.ToString();
+
+            EatWhitespace(false);
+
+            if (_chars[_charPos] != ':')
+                throw JsonReaderException.Create(this, "Invalid character after parsing property name. Expected ':' but got: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+            _charPos++;
+
+            SetToken(JsonToken.PropertyName, propertyName);
+            _quoteChar = quoteChar;
+            ClearRecentString();
+
+            return true;
+        }
+
+        private bool ValidIdentifierChar(char value)
+        {
+            return (char.IsLetterOrDigit(value) || value == '_' || value == '$');
+        }
+
+        private void ParseUnquotedProperty()
+        {
+            int initialPosition = _charPos;
+
+            // parse unquoted property name until whitespace or colon
+            while (true)
+            {
+                switch (_chars[_charPos])
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(true) == 0)
+                                throw JsonReaderException.Create(this, "Unexpected end while parsing unquoted property name.");
+
+                            break;
+                        }
+
+                        _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+                        return;
+                    default:
+                        char currentChar = _chars[_charPos];
+
+                        if (ValidIdentifierChar(currentChar))
+                        {
+                            _charPos++;
+                            break;
+                        }
+                        else if (char.IsWhiteSpace(currentChar) || currentChar == ':')
+                        {
+                            _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+                            return;
+                        }
+
+                        throw JsonReaderException.Create(this, "Invalid JavaScript property identifier character: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+                }
+            }
+        }
+
+        private bool ParseValue()
+        {
+            while (true)
+            {
+                char currentChar = _chars[_charPos];
+
+                switch (currentChar)
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(false) == 0)
+                                return false;
+                        }
+                        else
+                        {
+                            _charPos++;
+                        }
+                        break;
+                    case '"':
+                    case '\'':
+                        ParseString(currentChar);
+                        return true;
+                    case 't':
+                        ParseTrue();
+                        return true;
+                    case 'f':
+                        ParseFalse();
+                        return true;
+                    case 'n':
+                        if (EnsureChars(1, true))
+                        {
+                            char next = _chars[_charPos + 1];
+
+                            if (next == 'u')
+                                ParseNull();
+                            else if (next == 'e')
+                                ParseConstructor();
+                            else
+                                throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+                        }
+                        else
+                        {
+                            throw JsonReaderException.Create(this, "Unexpected end.");
+                        }
+                        return true;
+                    case 'N':
+                        ParseNumberNaN();
+                        return true;
+                    case 'I':
+                        ParseNumberPositiveInfinity();
+                        return true;
+                    case '-':
+                        if (EnsureChars(1, true) && _chars[_charPos + 1] == 'I')
+                            ParseNumberNegativeInfinity();
+                        else
+                            ParseNumber();
+                        return true;
+                    case '/':
+                        ParseComment();
+                        return true;
+                    case 'u':
+                        ParseUndefined();
+                        return true;
+                    case '{':
+                        _charPos++;
+                        SetToken(JsonToken.StartObject);
+                        return true;
+                    case '[':
+                        _charPos++;
+                        SetToken(JsonToken.StartArray);
+                        return true;
+                    case ']':
+                        _charPos++;
+                        SetToken(JsonToken.EndArray);
+                        return true;
+                    case ',':
+                        // don't increment position, the next call to read will handle comma
+                        // this is done to handle multiple empty comma values
+                        SetToken(JsonToken.Undefined);
+                        return true;
+                    case ')':
+                        _charPos++;
+                        SetToken(JsonToken.EndConstructor);
+                        return true;
+                    case StringUtils.CarriageReturn:
+                        ProcessCarriageReturn(false);
+                        break;
+                    case StringUtils.LineFeed:
+                        ProcessLineFeed();
+                        break;
+                    case ' ':
+                    case StringUtils.Tab:
+                        // eat
+                        _charPos++;
+                        break;
+                    default:
+                        if (char.IsWhiteSpace(currentChar))
+                        {
+                            // eat
+                            _charPos++;
+                            break;
+                        }
+                        else if (char.IsNumber(currentChar) || currentChar == '-' || currentChar == '.')
+                        {
+                            ParseNumber();
+                            return true;
+                        }
+                        else
+                        {
+                            throw JsonReaderException.Create(this, "Unexpected character encountered while parsing value: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+                        }
+                }
+            }
+        }
+
+        private void ProcessLineFeed()
+        {
+            _charPos++;
+            OnNewLine(_charPos);
+        }
+
+        private void ProcessCarriageReturn(bool append)
+        {
+            _charPos++;
+
+            if (EnsureChars(1, append) && _chars[_charPos] == StringUtils.LineFeed)
+                _charPos++;
+
+            OnNewLine(_charPos);
+        }
+
+        private bool EatWhitespace(bool oneOrMore)
+        {
+            bool finished = false;
+            bool ateWhitespace = false;
+            while (!finished)
+            {
+                char currentChar = _chars[_charPos];
+
+                switch (currentChar)
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(false) == 0)
+                                finished = true;
+                        }
+                        else
+                        {
+                            _charPos++;
+                        }
+                        break;
+                    case StringUtils.CarriageReturn:
+                        ProcessCarriageReturn(false);
+                        break;
+                    case StringUtils.LineFeed:
+                        ProcessLineFeed();
+                        break;
+                    default:
+                        if (currentChar == ' ' || char.IsWhiteSpace(currentChar))
+                        {
+                            ateWhitespace = true;
+                            _charPos++;
+                        }
+                        else
+                        {
+                            finished = true;
+                        }
+                        break;
+                }
+            }
+
+            return (!oneOrMore || ateWhitespace);
+        }
+
+        private void ParseConstructor()
+        {
+            if (MatchValueWithTrailingSeparator("new"))
+            {
+                EatWhitespace(false);
+
+                int initialPosition = _charPos;
+                int endPosition;
+
+                while (true)
+                {
+                    char currentChar = _chars[_charPos];
+                    if (currentChar == '\0')
+                    {
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(true) == 0)
+                                throw JsonReaderException.Create(this, "Unexpected end while parsing constructor.");
+                        }
+                        else
+                        {
+                            endPosition = _charPos;
+                            _charPos++;
+                            break;
+                        }
+                    }
+                    else if (char.IsLetterOrDigit(currentChar))
+                    {
+                        _charPos++;
+                    }
+                    else if (currentChar == StringUtils.CarriageReturn)
+                    {
+                        endPosition = _charPos;
+                        ProcessCarriageReturn(true);
+                        break;
+                    }
+                    else if (currentChar == StringUtils.LineFeed)
+                    {
+                        endPosition = _charPos;
+                        ProcessLineFeed();
+                        break;
+                    }
+                    else if (char.IsWhiteSpace(currentChar))
+                    {
+                        endPosition = _charPos;
+                        _charPos++;
+                        break;
+                    }
+                    else if (currentChar == '(')
+                    {
+                        endPosition = _charPos;
+                        break;
+                    }
+                    else
+                    {
+                        throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, currentChar));
+                    }
+                }
+
+                _stringReference = new StringReference(_chars, initialPosition, endPosition - initialPosition);
+                string constructorName = _stringReference.ToString();
+
+                EatWhitespace(false);
+
+                if (_chars[_charPos] != '(')
+                    throw JsonReaderException.Create(this, "Unexpected character while parsing constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+                _charPos++;
+
+                ClearRecentString();
+
+                SetToken(JsonToken.StartConstructor, constructorName);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Unexpected content while parsing JSON.");
+            }
+        }
+
+        private void ParseNumber()
+        {
+            ShiftBufferIfNeeded();
+
+            char firstChar = _chars[_charPos];
+            int initialPosition = _charPos;
+
+            ReadNumberIntoBuffer();
+
+            _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+
+            object numberValue;
+            JsonToken numberType;
+
+            bool singleDigit = (char.IsDigit(firstChar) && _stringReference.Length == 1);
+            bool nonBase10 = (firstChar == '0' && _stringReference.Length > 1
+                              && _stringReference.Chars[_stringReference.StartIndex + 1] != '.'
+                              && _stringReference.Chars[_stringReference.StartIndex + 1] != 'e'
+                              && _stringReference.Chars[_stringReference.StartIndex + 1] != 'E');
+
+            if (_readType == ReadType.ReadAsInt32)
+            {
+                if (singleDigit)
+                {
+                    // digit char values start at 48
+                    numberValue = firstChar - 48;
+                }
+                else if (nonBase10)
+                {
+                    string number = _stringReference.ToString();
+
+                    // decimal.Parse doesn't support parsing hexadecimal values
+                    int integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+                        ? Convert.ToInt32(number, 16)
+                        : Convert.ToInt32(number, 8);
+
+                    numberValue = integer;
+                }
+                else
+                {
+                    int value;
+                    ParseResult parseResult = ConvertUtils.Int32TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value);
+                    if (parseResult == ParseResult.Success)
+                        numberValue = value;
+                    else if (parseResult == ParseResult.Overflow)
+                        throw JsonReaderException.Create(this, "JSON integer {0} is too large or small for an Int32.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+                    else
+                        throw JsonReaderException.Create(this, "Input string '{0}' is not a valid integer.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+                }
+
+                numberType = JsonToken.Integer;
+            }
+            else if (_readType == ReadType.ReadAsDecimal)
+            {
+                if (singleDigit)
+                {
+                    // digit char values start at 48
+                    numberValue = (decimal)firstChar - 48;
+                }
+                else if (nonBase10)
+                {
+                    string number = _stringReference.ToString();
+
+                    // decimal.Parse doesn't support parsing hexadecimal values
+                    long integer = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+                        ? Convert.ToInt64(number, 16)
+                        : Convert.ToInt64(number, 8);
+
+                    numberValue = Convert.ToDecimal(integer);
+                }
+                else
+                {
+                    string number = _stringReference.ToString();
+
+                    decimal value;
+                    if (decimal.TryParse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out value))
+                        numberValue = value;
+                    else
+                        throw JsonReaderException.Create(this, "Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+                }
+
+                numberType = JsonToken.Float;
+            }
+            else
+            {
+                if (singleDigit)
+                {
+                    // digit char values start at 48
+                    numberValue = (long)firstChar - 48;
+                    numberType = JsonToken.Integer;
+                }
+                else if (nonBase10)
+                {
+                    string number = _stringReference.ToString();
+
+                    numberValue = number.StartsWith("0x", StringComparison.OrdinalIgnoreCase)
+                        ? Convert.ToInt64(number, 16)
+                        : Convert.ToInt64(number, 8);
+                    numberType = JsonToken.Integer;
+                }
+                else
+                {
+                    long value;
+                    ParseResult parseResult = ConvertUtils.Int64TryParse(_stringReference.Chars, _stringReference.StartIndex, _stringReference.Length, out value);
+                    if (parseResult == ParseResult.Success)
+                    {
+                        numberValue = value;
+                        numberType = JsonToken.Integer;
+                    }
+                    else if (parseResult == ParseResult.Overflow)
+                    {
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                        string number = _stringReference.ToString();
+                        numberValue = BigInteger.Parse(number, CultureInfo.InvariantCulture);
+                        numberType = JsonToken.Integer;
+#else
+                        throw JsonReaderException.Create(this, "JSON integer {0} is too large or small for an Int64.".FormatWith(CultureInfo.InvariantCulture, _stringReference.ToString()));
+#endif
+                    }
+                    else
+                    {
+                        string number = _stringReference.ToString();
+
+                        if (_floatParseHandling == FloatParseHandling.Decimal)
+                        {
+                            decimal d;
+                            if (decimal.TryParse(number, NumberStyles.Number | NumberStyles.AllowExponent, CultureInfo.InvariantCulture, out d))
+                                numberValue = d;
+                            else
+                                throw JsonReaderException.Create(this, "Input string '{0}' is not a valid decimal.".FormatWith(CultureInfo.InvariantCulture, number));
+                        }
+                        else
+                        {
+                            double d;
+                            if (double.TryParse(number, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d))
+                                numberValue = d;
+                            else
+                                throw JsonReaderException.Create(this, "Input string '{0}' is not a valid number.".FormatWith(CultureInfo.InvariantCulture, number));
+                        }
+
+                        numberType = JsonToken.Float;
+                    }
+                }
+            }
+
+            ClearRecentString();
+
+            SetToken(numberType, numberValue);
+        }
+
+        private void ParseComment()
+        {
+            // should have already parsed / character before reaching this method
+            _charPos++;
+
+            if (!EnsureChars(1, false))
+                throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
+
+            bool singlelineComment;
+
+            if (_chars[_charPos] == '*')
+                singlelineComment = false;
+            else if (_chars[_charPos] == '/')
+                singlelineComment = true;
+            else
+                throw JsonReaderException.Create(this, "Error parsing comment. Expected: *, got {0}.".FormatWith(CultureInfo.InvariantCulture, _chars[_charPos]));
+
+            _charPos++;
+
+            int initialPosition = _charPos;
+
+            bool commentFinished = false;
+
+            while (!commentFinished)
+            {
+                switch (_chars[_charPos])
+                {
+                    case '\0':
+                        if (_charsUsed == _charPos)
+                        {
+                            if (ReadData(true) == 0)
+                            {
+                                if (!singlelineComment)
+                                    throw JsonReaderException.Create(this, "Unexpected end while parsing comment.");
+
+                                _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+                                commentFinished = true;
+                            }
+                        }
+                        else
+                        {
+                            _charPos++;
+                        }
+                        break;
+                    case '*':
+                        _charPos++;
+
+                        if (!singlelineComment)
+                        {
+                            if (EnsureChars(0, true))
+                            {
+                                if (_chars[_charPos] == '/')
+                                {
+                                    _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition - 1);
+
+                                    _charPos++;
+                                    commentFinished = true;
+                                }
+                            }
+                        }
+                        break;
+                    case StringUtils.CarriageReturn:
+                        if (singlelineComment)
+                        {
+                            _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+                            commentFinished = true;
+                        }
+                        ProcessCarriageReturn(true);
+                        break;
+                    case StringUtils.LineFeed:
+                        if (singlelineComment)
+                        {
+                            _stringReference = new StringReference(_chars, initialPosition, _charPos - initialPosition);
+                            commentFinished = true;
+                        }
+                        ProcessLineFeed();
+                        break;
+                    default:
+                        _charPos++;
+                        break;
+                }
+            }
+
+            SetToken(JsonToken.Comment, _stringReference.ToString());
+
+            ClearRecentString();
+        }
+
+        private bool MatchValue(string value)
+        {
+            if (!EnsureChars(value.Length - 1, true))
+                return false;
+
+            for (int i = 0; i < value.Length; i++)
+            {
+                if (_chars[_charPos + i] != value[i])
+                {
+                    return false;
+                }
+            }
+
+            _charPos += value.Length;
+
+            return true;
+        }
+
+        private bool MatchValueWithTrailingSeparator(string value)
+        {
+            // will match value and then move to the next character, checking that it is a separator character
+            bool match = MatchValue(value);
+
+            if (!match)
+                return false;
+
+            if (!EnsureChars(0, false))
+                return true;
+
+            return IsSeparator(_chars[_charPos]) || _chars[_charPos] == '\0';
+        }
+
+        private bool IsSeparator(char c)
+        {
+            switch (c)
+            {
+                case '}':
+                case ']':
+                case ',':
+                    return true;
+                case '/':
+                    // check next character to see if start of a comment
+                    if (!EnsureChars(1, false))
+                        return false;
+
+                    var nextChart = _chars[_charPos + 1];
+
+                    return (nextChart == '*' || nextChart == '/');
+                case ')':
+                    if (CurrentState == State.Constructor || CurrentState == State.ConstructorStart)
+                        return true;
+                    break;
+                case ' ':
+                case StringUtils.Tab:
+                case StringUtils.LineFeed:
+                case StringUtils.CarriageReturn:
+                    return true;
+                default:
+                    if (char.IsWhiteSpace(c))
+                        return true;
+                    break;
+            }
+
+            return false;
+        }
+
+        private void ParseTrue()
+        {
+            // check characters equal 'true'
+            // and that it is followed by either a separator character
+            // or the text ends
+            if (MatchValueWithTrailingSeparator(JsonConvert.True))
+            {
+                SetToken(JsonToken.Boolean, true);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing boolean value.");
+            }
+        }
+
+        private void ParseNull()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.Null))
+            {
+                SetToken(JsonToken.Null);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing null value.");
+            }
+        }
+
+        private void ParseUndefined()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.Undefined))
+            {
+                SetToken(JsonToken.Undefined);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing undefined value.");
+            }
+        }
+
+        private void ParseFalse()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.False))
+            {
+                SetToken(JsonToken.Boolean, false);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing boolean value.");
+            }
+        }
+
+        private void ParseNumberNegativeInfinity()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.NegativeInfinity))
+            {
+                if (_floatParseHandling == FloatParseHandling.Decimal)
+                    throw new JsonReaderException("Cannot read -Infinity as a decimal.");
+
+                SetToken(JsonToken.Float, double.NegativeInfinity);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing negative infinity value.");
+            }
+        }
+
+        private void ParseNumberPositiveInfinity()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.PositiveInfinity))
+            {
+                if (_floatParseHandling == FloatParseHandling.Decimal)
+                    throw new JsonReaderException("Cannot read Infinity as a decimal.");
+
+                SetToken(JsonToken.Float, double.PositiveInfinity);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing positive infinity value.");
+            }
+        }
+
+        private void ParseNumberNaN()
+        {
+            if (MatchValueWithTrailingSeparator(JsonConvert.NaN))
+            {
+                if (_floatParseHandling == FloatParseHandling.Decimal)
+                    throw new JsonReaderException("Cannot read NaN as a decimal.");
+
+                SetToken(JsonToken.Float, double.NaN);
+            }
+            else
+            {
+                throw JsonReaderException.Create(this, "Error parsing NaN value.");
+            }
+        }
+
+        /// <summary>
+        /// Changes the state to closed. 
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+
+            if (CloseInput && _reader != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                _reader.Close();
+#else
+                _reader.Dispose();
+#endif
+
+            if (_buffer != null)
+                _buffer.Clear();
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether the class can return line information.
+        /// </summary>
+        /// <returns>
+        /// 	<c>true</c> if LineNumber and LinePosition can be provided; otherwise, <c>false</c>.
+        /// </returns>
+        public bool HasLineInfo()
+        {
+            return true;
+        }
+
+        /// <summary>
+        /// Gets the current line number.
+        /// </summary>
+        /// <value>
+        /// The current line number or 0 if no line information is available (for example, HasLineInfo returns false).
+        /// </value>
+        public int LineNumber
+        {
+            get
+            {
+                if (CurrentState == State.Start && LinePosition == 0)
+                    return 0;
+
+                return _lineNumber;
+            }
+        }
+
+        /// <summary>
+        /// Gets the current line position.
+        /// </summary>
+        /// <value>
+        /// The current line position or 0 if no line information is available (for example, HasLineInfo returns false).
+        /// </value>
+        public int LinePosition
+        {
+            get { return _charPos - _lineStartPos; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonTextWriter.cs b/Newtonsoft.Json/JsonTextWriter.cs
new file mode 100644
index 0000000..1ed5f14
--- /dev/null
+++ b/Newtonsoft.Json/JsonTextWriter.cs
@@ -0,0 +1,731 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using System.IO;
+using System.Xml;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+    /// </summary>
+    public class JsonTextWriter : JsonWriter
+    {
+        private readonly TextWriter _writer;
+        private Base64Encoder _base64Encoder;
+        private char _indentChar;
+        private int _indentation;
+        private char _quoteChar;
+        private bool _quoteName;
+        private bool[] _charEscapeFlags;
+        private char[] _writeBuffer;
+
+        private Base64Encoder Base64Encoder
+        {
+            get
+            {
+                if (_base64Encoder == null)
+                    _base64Encoder = new Base64Encoder(_writer);
+
+                return _base64Encoder;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets how many IndentChars to write for each level in the hierarchy when <see cref="Formatting"/> is set to <c>Formatting.Indented</c>.
+        /// </summary>
+        public int Indentation
+        {
+            get { return _indentation; }
+            set
+            {
+                if (value < 0)
+                    throw new ArgumentException("Indentation value must be greater than 0.");
+
+                _indentation = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets which character to use to quote attribute values.
+        /// </summary>
+        public char QuoteChar
+        {
+            get { return _quoteChar; }
+            set
+            {
+                if (value != '"' && value != '\'')
+                    throw new ArgumentException(@"Invalid JavaScript string quote character. Valid quote characters are ' and "".");
+
+                _quoteChar = value;
+                UpdateCharEscapeFlags();
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets which character to use for indenting when <see cref="Formatting"/> is set to <c>Formatting.Indented</c>.
+        /// </summary>
+        public char IndentChar
+        {
+            get { return _indentChar; }
+            set { _indentChar = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether object names will be surrounded with quotes.
+        /// </summary>
+        public bool QuoteName
+        {
+            get { return _quoteName; }
+            set { _quoteName = value; }
+        }
+
+        /// <summary>
+        /// Creates an instance of the <c>JsonWriter</c> class using the specified <see cref="TextWriter"/>. 
+        /// </summary>
+        /// <param name="textWriter">The <c>TextWriter</c> to write to.</param>
+        public JsonTextWriter(TextWriter textWriter)
+        {
+            if (textWriter == null)
+                throw new ArgumentNullException("textWriter");
+
+            _writer = textWriter;
+            _quoteChar = '"';
+            _quoteName = true;
+            _indentChar = ' ';
+            _indentation = 2;
+
+            UpdateCharEscapeFlags();
+        }
+
+        /// <summary>
+        /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+        /// </summary>
+        public override void Flush()
+        {
+            _writer.Flush();
+        }
+
+        /// <summary>
+        /// Closes this stream and the underlying stream.
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+
+            if (CloseOutput && _writer != null)
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                _writer.Close();
+#else
+                _writer.Dispose();
+#endif
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json object.
+        /// </summary>
+        public override void WriteStartObject()
+        {
+            InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object);
+
+            _writer.Write("{");
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json array.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array);
+
+            _writer.Write("[");
+        }
+
+        /// <summary>
+        /// Writes the start of a constructor with the given name.
+        /// </summary>
+        /// <param name="name">The name of the constructor.</param>
+        public override void WriteStartConstructor(string name)
+        {
+            InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor);
+
+            _writer.Write("new ");
+            _writer.Write(name);
+            _writer.Write("(");
+        }
+
+        /// <summary>
+        /// Writes the specified end token.
+        /// </summary>
+        /// <param name="token">The end token to write.</param>
+        protected override void WriteEnd(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.EndObject:
+                    _writer.Write("}");
+                    break;
+                case JsonToken.EndArray:
+                    _writer.Write("]");
+                    break;
+                case JsonToken.EndConstructor:
+                    _writer.Write(")");
+                    break;
+                default:
+                    throw JsonWriterException.Create(this, "Invalid JsonToken: " + token, null);
+            }
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a Json object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        public override void WritePropertyName(string name)
+        {
+            InternalWritePropertyName(name);
+
+            WriteEscapedString(name, _quoteName);
+
+            _writer.Write(':');
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a JSON object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        /// <param name="escape">A flag to indicate whether the text should be escaped when it is written as a JSON property name.</param>
+        public override void WritePropertyName(string name, bool escape)
+        {
+            InternalWritePropertyName(name);
+
+            if (escape)
+            {
+                WriteEscapedString(name, _quoteName);
+            }
+            else
+            {
+                if (_quoteName)
+                    _writer.Write(_quoteChar);
+
+                _writer.Write(name);
+
+                if (_quoteName)
+                    _writer.Write(_quoteChar);
+            }
+
+            _writer.Write(':');
+        }
+
+        internal override void OnStringEscapeHandlingChanged()
+        {
+            UpdateCharEscapeFlags();
+        }
+
+        private void UpdateCharEscapeFlags()
+        {
+            if (StringEscapeHandling == StringEscapeHandling.EscapeHtml)
+                _charEscapeFlags = JavaScriptUtils.HtmlCharEscapeFlags;
+            else if (_quoteChar == '"')
+                _charEscapeFlags = JavaScriptUtils.DoubleQuoteCharEscapeFlags;
+            else
+                _charEscapeFlags = JavaScriptUtils.SingleQuoteCharEscapeFlags;
+        }
+
+        /// <summary>
+        /// Writes indent characters.
+        /// </summary>
+        protected override void WriteIndent()
+        {
+            _writer.Write(Environment.NewLine);
+
+            // levels of indentation multiplied by the indent count
+            int currentIndentCount = Top * _indentation;
+
+            while (currentIndentCount > 0)
+            {
+                // write up to a max of 10 characters at once to avoid creating too many new strings
+                int writeCount = Math.Min(currentIndentCount, 10);
+
+                _writer.Write(new string(_indentChar, writeCount));
+
+                currentIndentCount -= writeCount;
+            }
+        }
+
+        /// <summary>
+        /// Writes the JSON value delimiter.
+        /// </summary>
+        protected override void WriteValueDelimiter()
+        {
+            _writer.Write(',');
+        }
+
+        /// <summary>
+        /// Writes an indent space.
+        /// </summary>
+        protected override void WriteIndentSpace()
+        {
+            _writer.Write(' ');
+        }
+
+        private void WriteValueInternal(string value, JsonToken token)
+        {
+            _writer.Write(value);
+        }
+
+        #region WriteValue methods
+        /// <summary>
+        /// Writes a <see cref="Object"/> value.
+        /// An error will raised if the value cannot be written as a single JSON token.
+        /// </summary>
+        /// <param name="value">The <see cref="Object"/> value to write.</param>
+        public override void WriteValue(object value)
+        {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+            if (value is BigInteger)
+            {
+                InternalWriteValue(JsonToken.Integer);
+                WriteValueInternal(((BigInteger)value).ToString(CultureInfo.InvariantCulture), JsonToken.String);
+            }
+            else
+#endif
+            {
+                base.WriteValue(value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a null value.
+        /// </summary>
+        public override void WriteNull()
+        {
+            InternalWriteValue(JsonToken.Null);
+            WriteValueInternal(JsonConvert.Null, JsonToken.Null);
+        }
+
+        /// <summary>
+        /// Writes an undefined value.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            InternalWriteValue(JsonToken.Undefined);
+            WriteValueInternal(JsonConvert.Undefined, JsonToken.Undefined);
+        }
+
+        /// <summary>
+        /// Writes raw JSON.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public override void WriteRaw(string json)
+        {
+            InternalWriteRaw();
+
+            _writer.Write(json);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="String"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="String"/> value to write.</param>
+        public override void WriteValue(string value)
+        {
+            InternalWriteValue(JsonToken.String);
+
+            if (value == null)
+                WriteValueInternal(JsonConvert.Null, JsonToken.Null);
+            else
+                WriteEscapedString(value, true);
+        }
+
+        private void WriteEscapedString(string value, bool quote)
+        {
+            EnsureWriteBuffer();
+            JavaScriptUtils.WriteEscapedJavaScriptString(_writer, value, _quoteChar, quote, _charEscapeFlags, StringEscapeHandling, ref _writeBuffer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int32"/> value to write.</param>
+        public override void WriteValue(int value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt32"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(uint value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int64"/> value to write.</param>
+        public override void WriteValue(long value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt64"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ulong value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Single"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Single"/> value to write.</param>
+        public override void WriteValue(float value)
+        {
+            InternalWriteValue(JsonToken.Float);
+            WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Single}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Single}"/> value to write.</param>
+        public override void WriteValue(float? value)
+        {
+            if (value == null)
+            {
+                WriteNull();
+            }
+            else
+            {
+                InternalWriteValue(JsonToken.Float);
+                WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float);
+            }
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Double"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Double"/> value to write.</param>
+        public override void WriteValue(double value)
+        {
+            InternalWriteValue(JsonToken.Float);
+            WriteValueInternal(JsonConvert.ToString(value, FloatFormatHandling, QuoteChar, false), JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Double}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Double}"/> value to write.</param>
+        public override void WriteValue(double? value)
+        {
+            if (value == null)
+            {
+                WriteNull();
+            }
+            else
+            {
+                InternalWriteValue(JsonToken.Float);
+                WriteValueInternal(JsonConvert.ToString(value.Value, FloatFormatHandling, QuoteChar, true), JsonToken.Float);
+            }
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Boolean"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Boolean"/> value to write.</param>
+        public override void WriteValue(bool value)
+        {
+            InternalWriteValue(JsonToken.Boolean);
+            WriteValueInternal(JsonConvert.ToString(value), JsonToken.Boolean);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int16"/> value to write.</param>
+        public override void WriteValue(short value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt16"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ushort value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Char"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Char"/> value to write.</param>
+        public override void WriteValue(char value)
+        {
+            InternalWriteValue(JsonToken.String);
+            WriteValueInternal(JsonConvert.ToString(value), JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Byte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Byte"/> value to write.</param>
+        public override void WriteValue(byte value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="SByte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="SByte"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(sbyte value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+            WriteIntegerValue(value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Decimal"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Decimal"/> value to write.</param>
+        public override void WriteValue(decimal value)
+        {
+            InternalWriteValue(JsonToken.Float);
+            WriteValueInternal(JsonConvert.ToString(value), JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="DateTime"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTime"/> value to write.</param>
+        public override void WriteValue(DateTime value)
+        {
+            InternalWriteValue(JsonToken.Date);
+            value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
+
+            if (string.IsNullOrEmpty(DateFormatString))
+            {
+                EnsureWriteBuffer();
+
+                int pos = 0;
+                _writeBuffer[pos++] = _quoteChar;
+                pos = DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, value, null, value.Kind, DateFormatHandling);
+                _writeBuffer[pos++] = _quoteChar;
+
+                _writer.Write(_writeBuffer, 0, pos);
+            }
+            else
+            {
+                _writer.Write(_quoteChar);
+                _writer.Write(value.ToString(DateFormatString, Culture));
+                _writer.Write(_quoteChar);
+            }
+        }
+
+        /// <summary>
+        /// Writes a <see cref="T:Byte[]"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
+        public override void WriteValue(byte[] value)
+        {
+            if (value == null)
+            {
+                WriteNull();
+            }
+            else
+            {
+                InternalWriteValue(JsonToken.Bytes);
+                _writer.Write(_quoteChar);
+                Base64Encoder.Encode(value, 0, value.Length);
+                Base64Encoder.Flush();
+                _writer.Write(_quoteChar);
+            }
+        }
+
+#if !NET20
+        /// <summary>
+        /// Writes a <see cref="DateTimeOffset"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
+        public override void WriteValue(DateTimeOffset value)
+        {
+            InternalWriteValue(JsonToken.Date);
+
+            if (string.IsNullOrEmpty(DateFormatString))
+            {
+                EnsureWriteBuffer();
+
+                int pos = 0;
+                _writeBuffer[pos++] = _quoteChar;
+                pos = DateTimeUtils.WriteDateTimeString(_writeBuffer, pos, (DateFormatHandling == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, DateFormatHandling);
+                _writeBuffer[pos++] = _quoteChar;
+
+                _writer.Write(_writeBuffer, 0, pos);
+            }
+            else
+            {
+                _writer.Write(_quoteChar);
+                _writer.Write(value.ToString(DateFormatString, Culture));
+                _writer.Write(_quoteChar);
+            }
+        }
+#endif
+
+        /// <summary>
+        /// Writes a <see cref="Guid"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Guid"/> value to write.</param>
+        public override void WriteValue(Guid value)
+        {
+            InternalWriteValue(JsonToken.String);
+            WriteValueInternal(JsonConvert.ToString(value, _quoteChar), JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="TimeSpan"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
+        public override void WriteValue(TimeSpan value)
+        {
+            InternalWriteValue(JsonToken.String);
+            WriteValueInternal(JsonConvert.ToString(value, _quoteChar), JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Uri"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Uri"/> value to write.</param>
+        public override void WriteValue(Uri value)
+        {
+            if (value == null)
+            {
+                WriteNull();
+            }
+            else
+            {
+                InternalWriteValue(JsonToken.String);
+                WriteValueInternal(JsonConvert.ToString(value, _quoteChar), JsonToken.String);
+            }
+        }
+        #endregion
+
+        /// <summary>
+        /// Writes out a comment <code>/*...*/</code> containing the specified text. 
+        /// </summary>
+        /// <param name="text">Text to place inside the comment.</param>
+        public override void WriteComment(string text)
+        {
+            InternalWriteComment();
+
+            _writer.Write("/*");
+            _writer.Write(text);
+            _writer.Write("*/");
+        }
+
+        /// <summary>
+        /// Writes out the given white space.
+        /// </summary>
+        /// <param name="ws">The string of white space characters.</param>
+        public override void WriteWhitespace(string ws)
+        {
+            InternalWriteWhitespace(ws);
+
+            _writer.Write(ws);
+        }
+
+        private void EnsureWriteBuffer()
+        {
+            if (_writeBuffer == null)
+                _writeBuffer = new char[64];
+        }
+
+        private void WriteIntegerValue(long value)
+        {
+            EnsureWriteBuffer();
+
+            if (value >= 0 && value <= 9)
+            {
+                _writer.Write((char)('0' + value));
+            }
+            else
+            {
+                ulong uvalue = (value < 0) ? (ulong)-value : (ulong)value;
+
+                if (value < 0)
+                    _writer.Write('-');
+
+                WriteIntegerValue(uvalue);
+            }
+        }
+
+        private void WriteIntegerValue(ulong uvalue)
+        {
+            EnsureWriteBuffer();
+
+            if (uvalue <= 9)
+            {
+                _writer.Write((char)('0' + uvalue));
+            }
+            else
+            {
+                int totalLength = MathUtils.IntLength(uvalue);
+                int length = 0;
+
+                do
+                {
+                    _writeBuffer[totalLength - ++length] = (char)('0' + (uvalue % 10));
+                    uvalue /= 10;
+                } while (uvalue != 0);
+
+                _writer.Write(_writeBuffer, 0, length);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonToken.cs b/Newtonsoft.Json/JsonToken.cs
new file mode 100644
index 0000000..f3a71f9
--- /dev/null
+++ b/Newtonsoft.Json/JsonToken.cs
@@ -0,0 +1,127 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies the type of Json token.
+    /// </summary>
+    public enum JsonToken
+    {
+        /// <summary>
+        /// This is returned by the <see cref="JsonReader"/> if a <see cref="JsonReader.Read"/> method has not been called. 
+        /// </summary>
+        None,
+
+        /// <summary>
+        /// An object start token.
+        /// </summary>
+        StartObject,
+
+        /// <summary>
+        /// An array start token.
+        /// </summary>
+        StartArray,
+
+        /// <summary>
+        /// A constructor start token.
+        /// </summary>
+        StartConstructor,
+
+        /// <summary>
+        /// An object property name.
+        /// </summary>
+        PropertyName,
+
+        /// <summary>
+        /// A comment.
+        /// </summary>
+        Comment,
+
+        /// <summary>
+        /// Raw JSON.
+        /// </summary>
+        Raw,
+
+        /// <summary>
+        /// An integer.
+        /// </summary>
+        Integer,
+
+        /// <summary>
+        /// A float.
+        /// </summary>
+        Float,
+
+        /// <summary>
+        /// A string.
+        /// </summary>
+        String,
+
+        /// <summary>
+        /// A boolean.
+        /// </summary>
+        Boolean,
+
+        /// <summary>
+        /// A null token.
+        /// </summary>
+        Null,
+
+        /// <summary>
+        /// An undefined token.
+        /// </summary>
+        Undefined,
+
+        /// <summary>
+        /// An object end token.
+        /// </summary>
+        EndObject,
+
+        /// <summary>
+        /// An array end token.
+        /// </summary>
+        EndArray,
+
+        /// <summary>
+        /// A constructor end token.
+        /// </summary>
+        EndConstructor,
+
+        /// <summary>
+        /// A Date.
+        /// </summary>
+        Date,
+
+        /// <summary>
+        /// Byte data.
+        /// </summary>
+        Bytes
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonValidatingReader.cs b/Newtonsoft.Json/JsonValidatingReader.cs
new file mode 100644
index 0000000..3c3f823
--- /dev/null
+++ b/Newtonsoft.Json/JsonValidatingReader.cs
@@ -0,0 +1,917 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Schema;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.IO;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Represents a reader that provides <see cref="JsonSchema"/> validation.
+    /// </summary>
+    public class JsonValidatingReader : JsonReader, IJsonLineInfo
+    {
+        private class SchemaScope
+        {
+            private readonly JTokenType _tokenType;
+            private readonly IList<JsonSchemaModel> _schemas;
+            private readonly Dictionary<string, bool> _requiredProperties;
+
+            public string CurrentPropertyName { get; set; }
+            public int ArrayItemCount { get; set; }
+            public bool IsUniqueArray { get; set; }
+            public bool IsEnum { get; set; }
+            public IList<JToken> UniqueArrayItems { get; set; }
+            public JTokenWriter CurrentItemWriter { get; set; }
+
+            public IList<JsonSchemaModel> Schemas
+            {
+                get { return _schemas; }
+            }
+
+            public Dictionary<string, bool> RequiredProperties
+            {
+                get { return _requiredProperties; }
+            }
+
+            public JTokenType TokenType
+            {
+                get { return _tokenType; }
+            }
+
+            public SchemaScope(JTokenType tokenType, IList<JsonSchemaModel> schemas)
+            {
+                _tokenType = tokenType;
+                _schemas = schemas;
+
+                _requiredProperties = schemas.SelectMany<JsonSchemaModel, string>(GetRequiredProperties).Distinct().ToDictionary(p => p, p => false);
+
+                if (tokenType == JTokenType.Array && schemas.Any(s => s.UniqueItems))
+                {
+                    IsUniqueArray = true;
+                    UniqueArrayItems = new List<JToken>();
+                }
+            }
+
+            private IEnumerable<string> GetRequiredProperties(JsonSchemaModel schema)
+            {
+                if (schema == null || schema.Properties == null)
+                    return Enumerable.Empty<string>();
+
+                return schema.Properties.Where(p => p.Value.Required).Select(p => p.Key);
+            }
+        }
+
+        private readonly JsonReader _reader;
+        private readonly Stack<SchemaScope> _stack;
+        private JsonSchema _schema;
+        private JsonSchemaModel _model;
+        private SchemaScope _currentScope;
+
+        /// <summary>
+        /// Sets an event handler for receiving schema validation errors.
+        /// </summary>
+        public event ValidationEventHandler ValidationEventHandler;
+
+        /// <summary>
+        /// Gets the text value of the current JSON token.
+        /// </summary>
+        /// <value></value>
+        public override object Value
+        {
+            get { return _reader.Value; }
+        }
+
+        /// <summary>
+        /// Gets the depth of the current token in the JSON document.
+        /// </summary>
+        /// <value>The depth of the current token in the JSON document.</value>
+        public override int Depth
+        {
+            get { return _reader.Depth; }
+        }
+
+        /// <summary>
+        /// Gets the path of the current JSON token. 
+        /// </summary>
+        public override string Path
+        {
+            get { return _reader.Path; }
+        }
+
+        /// <summary>
+        /// Gets the quotation mark character used to enclose the value of a string.
+        /// </summary>
+        /// <value></value>
+        public override char QuoteChar
+        {
+            get { return _reader.QuoteChar; }
+            protected internal set { }
+        }
+
+        /// <summary>
+        /// Gets the type of the current JSON token.
+        /// </summary>
+        /// <value></value>
+        public override JsonToken TokenType
+        {
+            get { return _reader.TokenType; }
+        }
+
+        /// <summary>
+        /// Gets the Common Language Runtime (CLR) type for the current JSON token.
+        /// </summary>
+        /// <value></value>
+        public override Type ValueType
+        {
+            get { return _reader.ValueType; }
+        }
+
+        private void Push(SchemaScope scope)
+        {
+            _stack.Push(scope);
+            _currentScope = scope;
+        }
+
+        private SchemaScope Pop()
+        {
+            SchemaScope poppedScope = _stack.Pop();
+            _currentScope = (_stack.Count != 0)
+                ? _stack.Peek()
+                : null;
+
+            return poppedScope;
+        }
+
+        private IList<JsonSchemaModel> CurrentSchemas
+        {
+            get { return _currentScope.Schemas; }
+        }
+
+        private static readonly IList<JsonSchemaModel> EmptySchemaList = new List<JsonSchemaModel>();
+
+        private IList<JsonSchemaModel> CurrentMemberSchemas
+        {
+            get
+            {
+                if (_currentScope == null)
+                    return new List<JsonSchemaModel>(new[] { _model });
+
+                if (_currentScope.Schemas == null || _currentScope.Schemas.Count == 0)
+                    return EmptySchemaList;
+
+                switch (_currentScope.TokenType)
+                {
+                    case JTokenType.None:
+                        return _currentScope.Schemas;
+                    case JTokenType.Object:
+                    {
+                        if (_currentScope.CurrentPropertyName == null)
+                            throw new JsonReaderException("CurrentPropertyName has not been set on scope.");
+
+                        IList<JsonSchemaModel> schemas = new List<JsonSchemaModel>();
+
+                        foreach (JsonSchemaModel schema in CurrentSchemas)
+                        {
+                            JsonSchemaModel propertySchema;
+                            if (schema.Properties != null && schema.Properties.TryGetValue(_currentScope.CurrentPropertyName, out propertySchema))
+                            {
+                                schemas.Add(propertySchema);
+                            }
+                            if (schema.PatternProperties != null)
+                            {
+                                foreach (KeyValuePair<string, JsonSchemaModel> patternProperty in schema.PatternProperties)
+                                {
+                                    if (Regex.IsMatch(_currentScope.CurrentPropertyName, patternProperty.Key))
+                                    {
+                                        schemas.Add(patternProperty.Value);
+                                    }
+                                }
+                            }
+
+                            if (schemas.Count == 0 && schema.AllowAdditionalProperties && schema.AdditionalProperties != null)
+                                schemas.Add(schema.AdditionalProperties);
+                        }
+
+                        return schemas;
+                    }
+                    case JTokenType.Array:
+                    {
+                        IList<JsonSchemaModel> schemas = new List<JsonSchemaModel>();
+
+                        foreach (JsonSchemaModel schema in CurrentSchemas)
+                        {
+                            if (!schema.PositionalItemsValidation)
+                            {
+                                if (schema.Items != null && schema.Items.Count > 0)
+                                    schemas.Add(schema.Items[0]);
+                            }
+                            else
+                            {
+                                if (schema.Items != null && schema.Items.Count > 0)
+                                {
+                                    if (schema.Items.Count > (_currentScope.ArrayItemCount - 1))
+                                        schemas.Add(schema.Items[_currentScope.ArrayItemCount - 1]);
+                                }
+
+                                if (schema.AllowAdditionalItems && schema.AdditionalItems != null)
+                                    schemas.Add(schema.AdditionalItems);
+                            }
+                        }
+
+                        return schemas;
+                    }
+                    case JTokenType.Constructor:
+                        return EmptySchemaList;
+                    default:
+                        throw new ArgumentOutOfRangeException("TokenType", "Unexpected token type: {0}".FormatWith(CultureInfo.InvariantCulture, _currentScope.TokenType));
+                }
+            }
+        }
+
+        private void RaiseError(string message, JsonSchemaModel schema)
+        {
+            IJsonLineInfo lineInfo = this;
+
+            string exceptionMessage = (lineInfo.HasLineInfo())
+                ? message + " Line {0}, position {1}.".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition)
+                : message;
+
+            OnValidationEvent(new JsonSchemaException(exceptionMessage, null, Path, lineInfo.LineNumber, lineInfo.LinePosition));
+        }
+
+        private void OnValidationEvent(JsonSchemaException exception)
+        {
+            ValidationEventHandler handler = ValidationEventHandler;
+            if (handler != null)
+                handler(this, new ValidationEventArgs(exception));
+            else
+                throw exception;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonValidatingReader"/> class that
+        /// validates the content returned from the given <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read from while validating.</param>
+        public JsonValidatingReader(JsonReader reader)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+            _reader = reader;
+            _stack = new Stack<SchemaScope>();
+        }
+
+        /// <summary>
+        /// Gets or sets the schema.
+        /// </summary>
+        /// <value>The schema.</value>
+        public JsonSchema Schema
+        {
+            get { return _schema; }
+            set
+            {
+                if (TokenType != JsonToken.None)
+                    throw new InvalidOperationException("Cannot change schema while validating JSON.");
+
+                _schema = value;
+                _model = null;
+            }
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JsonReader"/> used to construct this <see cref="JsonValidatingReader"/>.
+        /// </summary>
+        /// <value>The <see cref="JsonReader"/> specified in the constructor.</value>
+        public JsonReader Reader
+        {
+            get { return _reader; }
+        }
+
+        private void ValidateNotDisallowed(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            JsonSchemaType? currentNodeType = GetCurrentNodeSchemaType();
+            if (currentNodeType != null)
+            {
+                if (JsonSchemaGenerator.HasFlag(schema.Disallow, currentNodeType.Value))
+                    RaiseError("Type {0} is disallowed.".FormatWith(CultureInfo.InvariantCulture, currentNodeType), schema);
+            }
+        }
+
+        private JsonSchemaType? GetCurrentNodeSchemaType()
+        {
+            switch (_reader.TokenType)
+            {
+                case JsonToken.StartObject:
+                    return JsonSchemaType.Object;
+                case JsonToken.StartArray:
+                    return JsonSchemaType.Array;
+                case JsonToken.Integer:
+                    return JsonSchemaType.Integer;
+                case JsonToken.Float:
+                    return JsonSchemaType.Float;
+                case JsonToken.String:
+                    return JsonSchemaType.String;
+                case JsonToken.Boolean:
+                    return JsonSchemaType.Boolean;
+                case JsonToken.Null:
+                    return JsonSchemaType.Null;
+                default:
+                    return null;
+            }
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Int32}"/>.</returns>
+        public override int? ReadAsInt32()
+        {
+            int? i = _reader.ReadAsInt32();
+
+            ValidateCurrentToken();
+            return i;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null.
+        /// </returns>
+        public override byte[] ReadAsBytes()
+        {
+            byte[] data = _reader.ReadAsBytes();
+
+            ValidateCurrentToken();
+            return data;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Decimal}"/>.</returns>
+        public override decimal? ReadAsDecimal()
+        {
+            decimal? d = _reader.ReadAsDecimal();
+
+            ValidateCurrentToken();
+            return d;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="String"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override string ReadAsString()
+        {
+            string s = _reader.ReadAsString();
+
+            ValidateCurrentToken();
+            return s;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTime? ReadAsDateTime()
+        {
+            DateTime? dateTime = _reader.ReadAsDateTime();
+
+            ValidateCurrentToken();
+            return dateTime;
+        }
+
+#if !NET20
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{DateTimeOffset}"/>.</returns>
+        public override DateTimeOffset? ReadAsDateTimeOffset()
+        {
+            DateTimeOffset? dateTimeOffset = _reader.ReadAsDateTimeOffset();
+
+            ValidateCurrentToken();
+            return dateTimeOffset;
+        }
+#endif
+
+        /// <summary>
+        /// Reads the next JSON token from the stream.
+        /// </summary>
+        /// <returns>
+        /// true if the next token was read successfully; false if there are no more tokens to read.
+        /// </returns>
+        public override bool Read()
+        {
+            if (!_reader.Read())
+                return false;
+
+            if (_reader.TokenType == JsonToken.Comment)
+                return true;
+
+            ValidateCurrentToken();
+            return true;
+        }
+
+        private void ValidateCurrentToken()
+        {
+            // first time validate has been called. build model
+            if (_model == null)
+            {
+                JsonSchemaModelBuilder builder = new JsonSchemaModelBuilder();
+                _model = builder.Build(_schema);
+
+                if (!JsonWriter.IsStartToken(_reader.TokenType))
+                    Push(new SchemaScope(JTokenType.None, CurrentMemberSchemas));
+            }
+
+            switch (_reader.TokenType)
+            {
+                case JsonToken.StartObject:
+                    ProcessValue();
+                    IList<JsonSchemaModel> objectSchemas = CurrentMemberSchemas.Where(ValidateObject).ToList();
+                    Push(new SchemaScope(JTokenType.Object, objectSchemas));
+                    WriteToken(CurrentSchemas);
+                    break;
+                case JsonToken.StartArray:
+                    ProcessValue();
+                    IList<JsonSchemaModel> arraySchemas = CurrentMemberSchemas.Where(ValidateArray).ToList();
+                    Push(new SchemaScope(JTokenType.Array, arraySchemas));
+                    WriteToken(CurrentSchemas);
+                    break;
+                case JsonToken.StartConstructor:
+                    ProcessValue();
+                    Push(new SchemaScope(JTokenType.Constructor, null));
+                    WriteToken(CurrentSchemas);
+                    break;
+                case JsonToken.PropertyName:
+                    WriteToken(CurrentSchemas);
+                    foreach (JsonSchemaModel schema in CurrentSchemas)
+                    {
+                        ValidatePropertyName(schema);
+                    }
+                    break;
+                case JsonToken.Raw:
+                    ProcessValue();
+                    break;
+                case JsonToken.Integer:
+                    ProcessValue();
+                    WriteToken(CurrentMemberSchemas);
+                    foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+                    {
+                        ValidateInteger(schema);
+                    }
+                    break;
+                case JsonToken.Float:
+                    ProcessValue();
+                    WriteToken(CurrentMemberSchemas);
+                    foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+                    {
+                        ValidateFloat(schema);
+                    }
+                    break;
+                case JsonToken.String:
+                    ProcessValue();
+                    WriteToken(CurrentMemberSchemas);
+                    foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+                    {
+                        ValidateString(schema);
+                    }
+                    break;
+                case JsonToken.Boolean:
+                    ProcessValue();
+                    WriteToken(CurrentMemberSchemas);
+                    foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+                    {
+                        ValidateBoolean(schema);
+                    }
+                    break;
+                case JsonToken.Null:
+                    ProcessValue();
+                    WriteToken(CurrentMemberSchemas);
+                    foreach (JsonSchemaModel schema in CurrentMemberSchemas)
+                    {
+                        ValidateNull(schema);
+                    }
+                    break;
+                case JsonToken.EndObject:
+                    WriteToken(CurrentSchemas);
+                    foreach (JsonSchemaModel schema in CurrentSchemas)
+                    {
+                        ValidateEndObject(schema);
+                    }
+                    Pop();
+                    break;
+                case JsonToken.EndArray:
+                    WriteToken(CurrentSchemas);
+                    foreach (JsonSchemaModel schema in CurrentSchemas)
+                    {
+                        ValidateEndArray(schema);
+                    }
+                    Pop();
+                    break;
+                case JsonToken.EndConstructor:
+                    WriteToken(CurrentSchemas);
+                    Pop();
+                    break;
+                case JsonToken.Undefined:
+                case JsonToken.Date:
+                case JsonToken.Bytes:
+                    // these have no equivalent in JSON schema
+                    WriteToken(CurrentMemberSchemas);
+                    break;
+                case JsonToken.None:
+                    // no content, do nothing
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        private void WriteToken(IList<JsonSchemaModel> schemas)
+        {
+            foreach (SchemaScope schemaScope in _stack)
+            {
+                bool isInUniqueArray = (schemaScope.TokenType == JTokenType.Array && schemaScope.IsUniqueArray && schemaScope.ArrayItemCount > 0);
+
+                if (isInUniqueArray || schemaScope.IsEnum || schemas.Any(s => s.Enum != null))
+                {
+                    if (schemaScope.CurrentItemWriter == null)
+                    {
+                        if (JsonWriter.IsEndToken(_reader.TokenType))
+                            continue;
+
+                        schemaScope.CurrentItemWriter = new JTokenWriter();
+                    }
+
+                    schemaScope.CurrentItemWriter.WriteToken(_reader, false);
+
+                    // finished writing current item
+                    if (schemaScope.CurrentItemWriter.Top == 0 && _reader.TokenType != JsonToken.PropertyName)
+                    {
+                        JToken finishedItem = schemaScope.CurrentItemWriter.Token;
+
+                        // start next item with new writer
+                        schemaScope.CurrentItemWriter = null;
+
+                        if (isInUniqueArray)
+                        {
+                            if (schemaScope.UniqueArrayItems.Contains(finishedItem, JToken.EqualityComparer))
+                                RaiseError("Non-unique array item at index {0}.".FormatWith(CultureInfo.InvariantCulture, schemaScope.ArrayItemCount - 1), schemaScope.Schemas.First(s => s.UniqueItems));
+
+                            schemaScope.UniqueArrayItems.Add(finishedItem);
+                        }
+                        else if (schemaScope.IsEnum || schemas.Any(s => s.Enum != null))
+                        {
+                            foreach (JsonSchemaModel schema in schemas)
+                            {
+                                if (schema.Enum != null)
+                                {
+                                    if (!schema.Enum.ContainsValue(finishedItem, JToken.EqualityComparer))
+                                    {
+                                        StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+                                        finishedItem.WriteTo(new JsonTextWriter(sw));
+
+                                        RaiseError("Value {0} is not defined in enum.".FormatWith(CultureInfo.InvariantCulture, sw.ToString()), schema);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        private void ValidateEndObject(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            Dictionary<string, bool> requiredProperties = _currentScope.RequiredProperties;
+
+            if (requiredProperties != null)
+            {
+                List<string> unmatchedRequiredProperties =
+                    requiredProperties.Where(kv => !kv.Value).Select(kv => kv.Key).ToList();
+
+                if (unmatchedRequiredProperties.Count > 0)
+                    RaiseError("Required properties are missing from object: {0}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", unmatchedRequiredProperties.ToArray())), schema);
+            }
+        }
+
+        private void ValidateEndArray(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            int arrayItemCount = _currentScope.ArrayItemCount;
+
+            if (schema.MaximumItems != null && arrayItemCount > schema.MaximumItems)
+                RaiseError("Array item count {0} exceeds maximum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MaximumItems), schema);
+
+            if (schema.MinimumItems != null && arrayItemCount < schema.MinimumItems)
+                RaiseError("Array item count {0} is less than minimum count of {1}.".FormatWith(CultureInfo.InvariantCulture, arrayItemCount, schema.MinimumItems), schema);
+        }
+
+        private void ValidateNull(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            if (!TestType(schema, JsonSchemaType.Null))
+                return;
+
+            ValidateNotDisallowed(schema);
+        }
+
+        private void ValidateBoolean(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            if (!TestType(schema, JsonSchemaType.Boolean))
+                return;
+
+            ValidateNotDisallowed(schema);
+        }
+
+        private void ValidateString(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            if (!TestType(schema, JsonSchemaType.String))
+                return;
+
+            ValidateNotDisallowed(schema);
+
+            string value = _reader.Value.ToString();
+
+            if (schema.MaximumLength != null && value.Length > schema.MaximumLength)
+                RaiseError("String '{0}' exceeds maximum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MaximumLength), schema);
+
+            if (schema.MinimumLength != null && value.Length < schema.MinimumLength)
+                RaiseError("String '{0}' is less than minimum length of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.MinimumLength), schema);
+
+            if (schema.Patterns != null)
+            {
+                foreach (string pattern in schema.Patterns)
+                {
+                    if (!Regex.IsMatch(value, pattern))
+                        RaiseError("String '{0}' does not match regex pattern '{1}'.".FormatWith(CultureInfo.InvariantCulture, value, pattern), schema);
+                }
+            }
+        }
+
+        private void ValidateInteger(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            if (!TestType(schema, JsonSchemaType.Integer))
+                return;
+
+            ValidateNotDisallowed(schema);
+
+            object value = _reader.Value;
+
+            if (schema.Maximum != null)
+            {
+                if (JValue.Compare(JTokenType.Integer, value, schema.Maximum) > 0)
+                    RaiseError("Integer {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema);
+                if (schema.ExclusiveMaximum && JValue.Compare(JTokenType.Integer, value, schema.Maximum) == 0)
+                    RaiseError("Integer {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Maximum), schema);
+            }
+
+            if (schema.Minimum != null)
+            {
+                if (JValue.Compare(JTokenType.Integer, value, schema.Minimum) < 0)
+                    RaiseError("Integer {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema);
+                if (schema.ExclusiveMinimum && JValue.Compare(JTokenType.Integer, value, schema.Minimum) == 0)
+                    RaiseError("Integer {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, value, schema.Minimum), schema);
+            }
+
+            if (schema.DivisibleBy != null)
+            {
+                bool notDivisible;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                if (value is BigInteger)
+                {
+                    // not that this will lose any decimal point on DivisibleBy
+                    // so manually raise an error if DivisibleBy is not an integer and value is not zero
+                    BigInteger i = (BigInteger)value;
+                    bool divisibleNonInteger = !Math.Abs(schema.DivisibleBy.Value - Math.Truncate(schema.DivisibleBy.Value)).Equals(0);
+                    if (divisibleNonInteger)
+                        notDivisible = i != 0;
+                    else
+                        notDivisible = i % new BigInteger(schema.DivisibleBy.Value) != 0;
+                }
+                else
+#endif
+                    notDivisible = !IsZero(Convert.ToInt64(value, CultureInfo.InvariantCulture) % schema.DivisibleBy.Value);
+
+                if (notDivisible)
+                    RaiseError("Integer {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema);
+            }
+        }
+
+        private void ProcessValue()
+        {
+            if (_currentScope != null && _currentScope.TokenType == JTokenType.Array)
+            {
+                _currentScope.ArrayItemCount++;
+
+                foreach (JsonSchemaModel currentSchema in CurrentSchemas)
+                {
+                    // if there is positional validation and the array index is past the number of item validation schemas and there is no additonal items then error
+                    if (currentSchema != null
+                        && currentSchema.PositionalItemsValidation
+                        && !currentSchema.AllowAdditionalItems
+                        && (currentSchema.Items == null || _currentScope.ArrayItemCount - 1 >= currentSchema.Items.Count))
+                    {
+                        RaiseError("Index {0} has not been defined and the schema does not allow additional items.".FormatWith(CultureInfo.InvariantCulture, _currentScope.ArrayItemCount), currentSchema);
+                    }
+                }
+            }
+        }
+
+        private void ValidateFloat(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            if (!TestType(schema, JsonSchemaType.Float))
+                return;
+
+            ValidateNotDisallowed(schema);
+
+            double value = Convert.ToDouble(_reader.Value, CultureInfo.InvariantCulture);
+
+            if (schema.Maximum != null)
+            {
+                if (value > schema.Maximum)
+                    RaiseError("Float {0} exceeds maximum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema);
+                if (schema.ExclusiveMaximum && value == schema.Maximum)
+                    RaiseError("Float {0} equals maximum value of {1} and exclusive maximum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Maximum), schema);
+            }
+
+            if (schema.Minimum != null)
+            {
+                if (value < schema.Minimum)
+                    RaiseError("Float {0} is less than minimum value of {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Minimum), schema);
+                if (schema.ExclusiveMinimum && value == schema.Minimum)
+                    RaiseError("Float {0} equals minimum value of {1} and exclusive minimum is true.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.Minimum), schema);
+            }
+
+            if (schema.DivisibleBy != null)
+            {
+                double remainder = FloatingPointRemainder(value, schema.DivisibleBy.Value);
+
+                if (!IsZero(remainder))
+                    RaiseError("Float {0} is not evenly divisible by {1}.".FormatWith(CultureInfo.InvariantCulture, JsonConvert.ToString(value), schema.DivisibleBy), schema);
+            }
+        }
+
+        private static double FloatingPointRemainder(double dividend, double divisor)
+        {
+            return dividend - Math.Floor(dividend / divisor) * divisor;
+        }
+
+        private static bool IsZero(double value)
+        {
+            const double epsilon = 2.2204460492503131e-016;
+
+            return Math.Abs(value) < 20.0 * epsilon;
+        }
+
+        private void ValidatePropertyName(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return;
+
+            string propertyName = Convert.ToString(_reader.Value, CultureInfo.InvariantCulture);
+
+            if (_currentScope.RequiredProperties.ContainsKey(propertyName))
+                _currentScope.RequiredProperties[propertyName] = true;
+
+            if (!schema.AllowAdditionalProperties)
+            {
+                bool propertyDefinied = IsPropertyDefinied(schema, propertyName);
+
+                if (!propertyDefinied)
+                    RaiseError("Property '{0}' has not been defined and the schema does not allow additional properties.".FormatWith(CultureInfo.InvariantCulture, propertyName), schema);
+            }
+
+            _currentScope.CurrentPropertyName = propertyName;
+        }
+
+        private bool IsPropertyDefinied(JsonSchemaModel schema, string propertyName)
+        {
+            if (schema.Properties != null && schema.Properties.ContainsKey(propertyName))
+                return true;
+
+            if (schema.PatternProperties != null)
+            {
+                foreach (string pattern in schema.PatternProperties.Keys)
+                {
+                    if (Regex.IsMatch(propertyName, pattern))
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        private bool ValidateArray(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return true;
+
+            return (TestType(schema, JsonSchemaType.Array));
+        }
+
+        private bool ValidateObject(JsonSchemaModel schema)
+        {
+            if (schema == null)
+                return true;
+
+            return (TestType(schema, JsonSchemaType.Object));
+        }
+
+        private bool TestType(JsonSchemaModel currentSchema, JsonSchemaType currentType)
+        {
+            if (!JsonSchemaGenerator.HasFlag(currentSchema.Type, currentType))
+            {
+                RaiseError("Invalid type. Expected {0} but got {1}.".FormatWith(CultureInfo.InvariantCulture, currentSchema.Type, currentType), currentSchema);
+                return false;
+            }
+
+            return true;
+        }
+
+        bool IJsonLineInfo.HasLineInfo()
+        {
+            IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+            return lineInfo != null && lineInfo.HasLineInfo();
+        }
+
+        int IJsonLineInfo.LineNumber
+        {
+            get
+            {
+                IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+                return (lineInfo != null) ? lineInfo.LineNumber : 0;
+            }
+        }
+
+        int IJsonLineInfo.LinePosition
+        {
+            get
+            {
+                IJsonLineInfo lineInfo = _reader as IJsonLineInfo;
+                return (lineInfo != null) ? lineInfo.LinePosition : 0;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonWriter.cs b/Newtonsoft.Json/JsonWriter.cs
new file mode 100644
index 0000000..a070e71
--- /dev/null
+++ b/Newtonsoft.Json/JsonWriter.cs
@@ -0,0 +1,1523 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+    /// </summary>
+    public abstract class JsonWriter : IDisposable
+    {
+        internal enum State
+        {
+            Start,
+            Property,
+            ObjectStart,
+            Object,
+            ArrayStart,
+            Array,
+            ConstructorStart,
+            Constructor,
+            Closed,
+            Error
+        }
+
+        // array that gives a new state based on the current state an the token being written
+        private static readonly State[][] StateArray;
+
+        internal static readonly State[][] StateArrayTempate = new[]
+        {
+            //                                      Start                    PropertyName            ObjectStart         Object            ArrayStart              Array                   ConstructorStart        Constructor             Closed          Error
+            //
+            /* None                        */new[] { State.Error,            State.Error,            State.Error,        State.Error,      State.Error,            State.Error,            State.Error,            State.Error,            State.Error,    State.Error },
+            /* StartObject                 */new[] { State.ObjectStart,      State.ObjectStart,      State.Error,        State.Error,      State.ObjectStart,      State.ObjectStart,      State.ObjectStart,      State.ObjectStart,      State.Error,    State.Error },
+            /* StartArray                  */new[] { State.ArrayStart,       State.ArrayStart,       State.Error,        State.Error,      State.ArrayStart,       State.ArrayStart,       State.ArrayStart,       State.ArrayStart,       State.Error,    State.Error },
+            /* StartConstructor            */new[] { State.ConstructorStart, State.ConstructorStart, State.Error,        State.Error,      State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error,    State.Error },
+            /* Property                    */new[] { State.Property,         State.Error,            State.Property,     State.Property,   State.Error,            State.Error,            State.Error,            State.Error,            State.Error,    State.Error },
+            /* Comment                     */new[] { State.Start,            State.Property,         State.ObjectStart,  State.Object,     State.ArrayStart,       State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error },
+            /* Raw                         */new[] { State.Start,            State.Property,         State.ObjectStart,  State.Object,     State.ArrayStart,       State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error },
+            /* Value (this will be copied) */new[] { State.Start,            State.Object,           State.Error,        State.Error,      State.Array,            State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error }
+        };
+
+        internal static State[][] BuildStateArray()
+        {
+            var allStates = StateArrayTempate.ToList();
+            var errorStates = StateArrayTempate[0];
+            var valueStates = StateArrayTempate[7];
+
+            foreach (JsonToken valueToken in EnumUtils.GetValues(typeof(JsonToken)))
+            {
+                if (allStates.Count <= (int)valueToken)
+                {
+                    switch (valueToken)
+                    {
+                        case JsonToken.Integer:
+                        case JsonToken.Float:
+                        case JsonToken.String:
+                        case JsonToken.Boolean:
+                        case JsonToken.Null:
+                        case JsonToken.Undefined:
+                        case JsonToken.Date:
+                        case JsonToken.Bytes:
+                            allStates.Add(valueStates);
+                            break;
+                        default:
+                            allStates.Add(errorStates);
+                            break;
+                    }
+                }
+            }
+
+            return allStates.ToArray();
+        }
+
+        static JsonWriter()
+        {
+            StateArray = BuildStateArray();
+        }
+
+        private readonly List<JsonPosition> _stack;
+        private JsonPosition _currentPosition;
+        private State _currentState;
+        private Formatting _formatting;
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the underlying stream or
+        /// <see cref="TextReader"/> should be closed when the writer is closed.
+        /// </summary>
+        /// <value>
+        /// true to close the underlying stream or <see cref="TextReader"/> when
+        /// the writer is closed; otherwise false. The default is true.
+        /// </value>
+        public bool CloseOutput { get; set; }
+
+        /// <summary>
+        /// Gets the top.
+        /// </summary>
+        /// <value>The top.</value>
+        protected internal int Top
+        {
+            get
+            {
+                int depth = _stack.Count;
+                if (Peek() != JsonContainerType.None)
+                    depth++;
+
+                return depth;
+            }
+        }
+
+        /// <summary>
+        /// Gets the state of the writer.
+        /// </summary>
+        public WriteState WriteState
+        {
+            get
+            {
+                switch (_currentState)
+                {
+                    case State.Error:
+                        return WriteState.Error;
+                    case State.Closed:
+                        return WriteState.Closed;
+                    case State.Object:
+                    case State.ObjectStart:
+                        return WriteState.Object;
+                    case State.Array:
+                    case State.ArrayStart:
+                        return WriteState.Array;
+                    case State.Constructor:
+                    case State.ConstructorStart:
+                        return WriteState.Constructor;
+                    case State.Property:
+                        return WriteState.Property;
+                    case State.Start:
+                        return WriteState.Start;
+                    default:
+                        throw JsonWriterException.Create(this, "Invalid state: " + _currentState, null);
+                }
+            }
+        }
+
+        internal string ContainerPath
+        {
+            get
+            {
+                if (_currentPosition.Type == JsonContainerType.None)
+                    return string.Empty;
+
+                return JsonPosition.BuildPath(_stack);
+            }
+        }
+
+        /// <summary>
+        /// Gets the path of the writer. 
+        /// </summary>
+        public string Path
+        {
+            get
+            {
+                if (_currentPosition.Type == JsonContainerType.None)
+                    return string.Empty;
+
+                bool insideContainer = (_currentState != State.ArrayStart
+                                        && _currentState != State.ConstructorStart
+                                        && _currentState != State.ObjectStart);
+
+                IEnumerable<JsonPosition> positions = (!insideContainer)
+                    ? _stack
+                    : _stack.Concat(new[] { _currentPosition });
+
+                return JsonPosition.BuildPath(positions);
+            }
+        }
+
+        private DateFormatHandling _dateFormatHandling;
+        private DateTimeZoneHandling _dateTimeZoneHandling;
+        private StringEscapeHandling _stringEscapeHandling;
+        private FloatFormatHandling _floatFormatHandling;
+        private string _dateFormatString;
+        private CultureInfo _culture;
+
+        /// <summary>
+        /// Indicates how JSON text output is formatted.
+        /// </summary>
+        public Formatting Formatting
+        {
+            get { return _formatting; }
+            set { _formatting = value; }
+        }
+
+        /// <summary>
+        /// Get or set how dates are written to JSON text.
+        /// </summary>
+        public DateFormatHandling DateFormatHandling
+        {
+            get { return _dateFormatHandling; }
+            set { _dateFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> time zones are handling when writing JSON text.
+        /// </summary>
+        public DateTimeZoneHandling DateTimeZoneHandling
+        {
+            get { return _dateTimeZoneHandling; }
+            set { _dateTimeZoneHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how strings are escaped when writing JSON text.
+        /// </summary>
+        public StringEscapeHandling StringEscapeHandling
+        {
+            get { return _stringEscapeHandling; }
+            set
+            {
+                _stringEscapeHandling = value;
+                OnStringEscapeHandlingChanged();
+            }
+        }
+
+        internal virtual void OnStringEscapeHandlingChanged()
+        {
+            // hacky but there is a calculated value that relies on StringEscapeHandling
+        }
+
+        /// <summary>
+        /// Get or set how special floating point numbers, e.g. <see cref="F:System.Double.NaN"/>,
+        /// <see cref="F:System.Double.PositiveInfinity"/> and <see cref="F:System.Double.NegativeInfinity"/>,
+        /// are written to JSON text.
+        /// </summary>
+        public FloatFormatHandling FloatFormatHandling
+        {
+            get { return _floatFormatHandling; }
+            set { _floatFormatHandling = value; }
+        }
+
+        /// <summary>
+        /// Get or set how <see cref="DateTime"/> and <see cref="DateTimeOffset"/> values are formatting when writing JSON text.
+        /// </summary>
+        public string DateFormatString
+        {
+            get { return _dateFormatString; }
+            set { _dateFormatString = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets the culture used when writing JSON. Defaults to <see cref="CultureInfo.InvariantCulture"/>.
+        /// </summary>
+        public CultureInfo Culture
+        {
+            get { return _culture ?? CultureInfo.InvariantCulture; }
+            set { _culture = value; }
+        }
+
+        /// <summary>
+        /// Creates an instance of the <c>JsonWriter</c> class. 
+        /// </summary>
+        protected JsonWriter()
+        {
+            _stack = new List<JsonPosition>(4);
+            _currentState = State.Start;
+            _formatting = Formatting.None;
+            _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind;
+
+            CloseOutput = true;
+        }
+
+        internal void UpdateScopeWithFinishedValue()
+        {
+            if (_currentPosition.HasIndex)
+                _currentPosition.Position++;
+        }
+
+        private void Push(JsonContainerType value)
+        {
+            if (_currentPosition.Type != JsonContainerType.None)
+                _stack.Add(_currentPosition);
+
+            _currentPosition = new JsonPosition(value);
+        }
+
+        private JsonContainerType Pop()
+        {
+            JsonPosition oldPosition = _currentPosition;
+
+            if (_stack.Count > 0)
+            {
+                _currentPosition = _stack[_stack.Count - 1];
+                _stack.RemoveAt(_stack.Count - 1);
+            }
+            else
+            {
+                _currentPosition = new JsonPosition();
+            }
+
+            return oldPosition.Type;
+        }
+
+        private JsonContainerType Peek()
+        {
+            return _currentPosition.Type;
+        }
+
+        /// <summary>
+        /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+        /// </summary>
+        public abstract void Flush();
+
+        /// <summary>
+        /// Closes this stream and the underlying stream.
+        /// </summary>
+        public virtual void Close()
+        {
+            AutoCompleteAll();
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json object.
+        /// </summary>
+        public virtual void WriteStartObject()
+        {
+            InternalWriteStart(JsonToken.StartObject, JsonContainerType.Object);
+        }
+
+        /// <summary>
+        /// Writes the end of a Json object.
+        /// </summary>
+        public virtual void WriteEndObject()
+        {
+            InternalWriteEnd(JsonContainerType.Object);
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json array.
+        /// </summary>
+        public virtual void WriteStartArray()
+        {
+            InternalWriteStart(JsonToken.StartArray, JsonContainerType.Array);
+        }
+
+        /// <summary>
+        /// Writes the end of an array.
+        /// </summary>
+        public virtual void WriteEndArray()
+        {
+            InternalWriteEnd(JsonContainerType.Array);
+        }
+
+        /// <summary>
+        /// Writes the start of a constructor with the given name.
+        /// </summary>
+        /// <param name="name">The name of the constructor.</param>
+        public virtual void WriteStartConstructor(string name)
+        {
+            InternalWriteStart(JsonToken.StartConstructor, JsonContainerType.Constructor);
+        }
+
+        /// <summary>
+        /// Writes the end constructor.
+        /// </summary>
+        public virtual void WriteEndConstructor()
+        {
+            InternalWriteEnd(JsonContainerType.Constructor);
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a JSON object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        public virtual void WritePropertyName(string name)
+        {
+            InternalWritePropertyName(name);
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a JSON object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        /// <param name="escape">A flag to indicate whether the text should be escaped when it is written as a JSON property name.</param>
+        public virtual void WritePropertyName(string name, bool escape)
+        {
+            WritePropertyName(name);
+        }
+
+        /// <summary>
+        /// Writes the end of the current Json object or array.
+        /// </summary>
+        public virtual void WriteEnd()
+        {
+            WriteEnd(Peek());
+        }
+
+        /// <summary>
+        /// Writes the current <see cref="JsonReader"/> token and its children.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
+        public void WriteToken(JsonReader reader)
+        {
+            WriteToken(reader, true, true);
+        }
+
+        /// <summary>
+        /// Writes the current <see cref="JsonReader"/> token.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
+        /// <param name="writeChildren">A flag indicating whether the current token's children should be written.</param>
+        public void WriteToken(JsonReader reader, bool writeChildren)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            WriteToken(reader, writeChildren, true);
+        }
+
+        internal void WriteToken(JsonReader reader, bool writeChildren, bool writeDateConstructorAsDate)
+        {
+            int initialDepth;
+
+            if (reader.TokenType == JsonToken.None)
+                initialDepth = -1;
+            else if (!IsStartToken(reader.TokenType))
+                initialDepth = reader.Depth + 1;
+            else
+                initialDepth = reader.Depth;
+
+            WriteToken(reader, initialDepth, writeChildren, writeDateConstructorAsDate);
+        }
+
+        internal void WriteToken(JsonReader reader, int initialDepth, bool writeChildren, bool writeDateConstructorAsDate)
+        {
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.None:
+                        // read to next
+                        break;
+                    case JsonToken.StartObject:
+                        WriteStartObject();
+                        break;
+                    case JsonToken.StartArray:
+                        WriteStartArray();
+                        break;
+                    case JsonToken.StartConstructor:
+                        string constructorName = reader.Value.ToString();
+                        // write a JValue date when the constructor is for a date
+                        if (writeDateConstructorAsDate && string.Equals(constructorName, "Date", StringComparison.Ordinal))
+                            WriteConstructorDate(reader);
+                        else
+                            WriteStartConstructor(reader.Value.ToString());
+                        break;
+                    case JsonToken.PropertyName:
+                        WritePropertyName(reader.Value.ToString());
+                        break;
+                    case JsonToken.Comment:
+                        WriteComment((reader.Value != null) ? reader.Value.ToString() : null);
+                        break;
+                    case JsonToken.Integer:
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+                        if (reader.Value is BigInteger)
+                        {
+                            WriteValue((BigInteger)reader.Value);
+                        }
+                        else
+#endif
+                        {
+                            WriteValue(Convert.ToInt64(reader.Value, CultureInfo.InvariantCulture));
+                        }
+                        break;
+                    case JsonToken.Float:
+                        object value = reader.Value;
+
+                        if (value is decimal)
+                            WriteValue((decimal)value);
+                        else if (value is double)
+                            WriteValue((double)value);
+                        else if (value is float)
+                            WriteValue((float)value);
+                        else
+                            WriteValue(Convert.ToDouble(value, CultureInfo.InvariantCulture));
+                        break;
+                    case JsonToken.String:
+                        WriteValue(reader.Value.ToString());
+                        break;
+                    case JsonToken.Boolean:
+                        WriteValue(Convert.ToBoolean(reader.Value, CultureInfo.InvariantCulture));
+                        break;
+                    case JsonToken.Null:
+                        WriteNull();
+                        break;
+                    case JsonToken.Undefined:
+                        WriteUndefined();
+                        break;
+                    case JsonToken.EndObject:
+                        WriteEndObject();
+                        break;
+                    case JsonToken.EndArray:
+                        WriteEndArray();
+                        break;
+                    case JsonToken.EndConstructor:
+                        WriteEndConstructor();
+                        break;
+                    case JsonToken.Date:
+#if !NET20
+                        if (reader.Value is DateTimeOffset)
+                            WriteValue((DateTimeOffset)reader.Value);
+                        else
+#endif
+                            WriteValue(Convert.ToDateTime(reader.Value, CultureInfo.InvariantCulture));
+                        break;
+                    case JsonToken.Raw:
+                        WriteRawValue((reader.Value != null) ? reader.Value.ToString() : null);
+                        break;
+                    case JsonToken.Bytes:
+                        WriteValue((byte[])reader.Value);
+                        break;
+                    default:
+                        throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", reader.TokenType, "Unexpected token type.");
+                }
+            } while (
+                // stop if we have reached the end of the token being read
+                initialDepth - 1 < reader.Depth - (IsEndToken(reader.TokenType) ? 1 : 0)
+                && writeChildren
+                && reader.Read());
+        }
+
+        private void WriteConstructorDate(JsonReader reader)
+        {
+            if (!reader.Read())
+                throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
+            if (reader.TokenType != JsonToken.Integer)
+                throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected Integer, got " + reader.TokenType, null);
+
+            long ticks = (long)reader.Value;
+            DateTime date = DateTimeUtils.ConvertJavaScriptTicksToDateTime(ticks);
+
+            if (!reader.Read())
+                throw JsonWriterException.Create(this, "Unexpected end when reading date constructor.", null);
+            if (reader.TokenType != JsonToken.EndConstructor)
+                throw JsonWriterException.Create(this, "Unexpected token when reading date constructor. Expected EndConstructor, got " + reader.TokenType, null);
+
+            WriteValue(date);
+        }
+
+        internal static bool IsEndToken(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.EndObject:
+                case JsonToken.EndArray:
+                case JsonToken.EndConstructor:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        internal static bool IsStartToken(JsonToken token)
+        {
+            switch (token)
+            {
+                case JsonToken.StartObject:
+                case JsonToken.StartArray:
+                case JsonToken.StartConstructor:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        private void WriteEnd(JsonContainerType type)
+        {
+            switch (type)
+            {
+                case JsonContainerType.Object:
+                    WriteEndObject();
+                    break;
+                case JsonContainerType.Array:
+                    WriteEndArray();
+                    break;
+                case JsonContainerType.Constructor:
+                    WriteEndConstructor();
+                    break;
+                default:
+                    throw JsonWriterException.Create(this, "Unexpected type when writing end: " + type, null);
+            }
+        }
+
+        private void AutoCompleteAll()
+        {
+            while (Top > 0)
+            {
+                WriteEnd();
+            }
+        }
+
+        private JsonToken GetCloseTokenForType(JsonContainerType type)
+        {
+            switch (type)
+            {
+                case JsonContainerType.Object:
+                    return JsonToken.EndObject;
+                case JsonContainerType.Array:
+                    return JsonToken.EndArray;
+                case JsonContainerType.Constructor:
+                    return JsonToken.EndConstructor;
+                default:
+                    throw JsonWriterException.Create(this, "No close token for type: " + type, null);
+            }
+        }
+
+        private void AutoCompleteClose(JsonContainerType type)
+        {
+            // write closing symbol and calculate new state
+            int levelsToComplete = 0;
+
+            if (_currentPosition.Type == type)
+            {
+                levelsToComplete = 1;
+            }
+            else
+            {
+                int top = Top - 2;
+                for (int i = top; i >= 0; i--)
+                {
+                    int currentLevel = top - i;
+
+                    if (_stack[currentLevel].Type == type)
+                    {
+                        levelsToComplete = i + 2;
+                        break;
+                    }
+                }
+            }
+
+            if (levelsToComplete == 0)
+                throw JsonWriterException.Create(this, "No token to close.", null);
+
+            for (int i = 0; i < levelsToComplete; i++)
+            {
+                JsonToken token = GetCloseTokenForType(Pop());
+
+                if (_currentState == State.Property)
+                    WriteNull();
+
+                if (_formatting == Formatting.Indented)
+                {
+                    if (_currentState != State.ObjectStart && _currentState != State.ArrayStart)
+                        WriteIndent();
+                }
+
+                WriteEnd(token);
+
+                JsonContainerType currentLevelType = Peek();
+
+                switch (currentLevelType)
+                {
+                    case JsonContainerType.Object:
+                        _currentState = State.Object;
+                        break;
+                    case JsonContainerType.Array:
+                        _currentState = State.Array;
+                        break;
+                    case JsonContainerType.Constructor:
+                        _currentState = State.Array;
+                        break;
+                    case JsonContainerType.None:
+                        _currentState = State.Start;
+                        break;
+                    default:
+                        throw JsonWriterException.Create(this, "Unknown JsonType: " + currentLevelType, null);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Writes the specified end token.
+        /// </summary>
+        /// <param name="token">The end token to write.</param>
+        protected virtual void WriteEnd(JsonToken token)
+        {
+        }
+
+        /// <summary>
+        /// Writes indent characters.
+        /// </summary>
+        protected virtual void WriteIndent()
+        {
+        }
+
+        /// <summary>
+        /// Writes the JSON value delimiter.
+        /// </summary>
+        protected virtual void WriteValueDelimiter()
+        {
+        }
+
+        /// <summary>
+        /// Writes an indent space.
+        /// </summary>
+        protected virtual void WriteIndentSpace()
+        {
+        }
+
+        internal void AutoComplete(JsonToken tokenBeingWritten)
+        {
+            // gets new state based on the current state and what is being written
+            State newState = StateArray[(int)tokenBeingWritten][(int)_currentState];
+
+            if (newState == State.Error)
+                throw JsonWriterException.Create(this, "Token {0} in state {1} would result in an invalid JSON object.".FormatWith(CultureInfo.InvariantCulture, tokenBeingWritten.ToString(), _currentState.ToString()), null);
+
+            if ((_currentState == State.Object || _currentState == State.Array || _currentState == State.Constructor) && tokenBeingWritten != JsonToken.Comment)
+            {
+                WriteValueDelimiter();
+            }
+
+            if (_formatting == Formatting.Indented)
+            {
+                if (_currentState == State.Property)
+                    WriteIndentSpace();
+
+                // don't indent a property when it is the first token to be written (i.e. at the start)
+                if ((_currentState == State.Array || _currentState == State.ArrayStart || _currentState == State.Constructor || _currentState == State.ConstructorStart)
+                    || (tokenBeingWritten == JsonToken.PropertyName && _currentState != State.Start))
+                    WriteIndent();
+            }
+
+            _currentState = newState;
+        }
+
+        #region WriteValue methods
+        /// <summary>
+        /// Writes a null value.
+        /// </summary>
+        public virtual void WriteNull()
+        {
+            InternalWriteValue(JsonToken.Null);
+        }
+
+        /// <summary>
+        /// Writes an undefined value.
+        /// </summary>
+        public virtual void WriteUndefined()
+        {
+            InternalWriteValue(JsonToken.Undefined);
+        }
+
+        /// <summary>
+        /// Writes raw JSON without changing the writer's state.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public virtual void WriteRaw(string json)
+        {
+            InternalWriteRaw();
+        }
+
+        /// <summary>
+        /// Writes raw JSON where a value is expected and updates the writer's state.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public virtual void WriteRawValue(string json)
+        {
+            // hack. want writer to change state as if a value had been written
+            UpdateScopeWithFinishedValue();
+            AutoComplete(JsonToken.Undefined);
+            WriteRaw(json);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="String"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="String"/> value to write.</param>
+        public virtual void WriteValue(string value)
+        {
+            InternalWriteValue(JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int32"/> value to write.</param>
+        public virtual void WriteValue(int value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt32"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(uint value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int64"/> value to write.</param>
+        public virtual void WriteValue(long value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt64"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(ulong value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Single"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Single"/> value to write.</param>
+        public virtual void WriteValue(float value)
+        {
+            InternalWriteValue(JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Double"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Double"/> value to write.</param>
+        public virtual void WriteValue(double value)
+        {
+            InternalWriteValue(JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Boolean"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Boolean"/> value to write.</param>
+        public virtual void WriteValue(bool value)
+        {
+            InternalWriteValue(JsonToken.Boolean);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int16"/> value to write.</param>
+        public virtual void WriteValue(short value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt16"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(ushort value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Char"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Char"/> value to write.</param>
+        public virtual void WriteValue(char value)
+        {
+            InternalWriteValue(JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Byte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Byte"/> value to write.</param>
+        public virtual void WriteValue(byte value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="SByte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="SByte"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(sbyte value)
+        {
+            InternalWriteValue(JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Decimal"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Decimal"/> value to write.</param>
+        public virtual void WriteValue(decimal value)
+        {
+            InternalWriteValue(JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="DateTime"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTime"/> value to write.</param>
+        public virtual void WriteValue(DateTime value)
+        {
+            InternalWriteValue(JsonToken.Date);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Writes a <see cref="DateTimeOffset"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
+        public virtual void WriteValue(DateTimeOffset value)
+        {
+            InternalWriteValue(JsonToken.Date);
+        }
+#endif
+
+        /// <summary>
+        /// Writes a <see cref="Guid"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Guid"/> value to write.</param>
+        public virtual void WriteValue(Guid value)
+        {
+            InternalWriteValue(JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="TimeSpan"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
+        public virtual void WriteValue(TimeSpan value)
+        {
+            InternalWriteValue(JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Int32}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Int32}"/> value to write.</param>
+        public virtual void WriteValue(int? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{UInt32}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{UInt32}"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(uint? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Int64}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Int64}"/> value to write.</param>
+        public virtual void WriteValue(long? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{UInt64}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{UInt64}"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(ulong? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Single}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Single}"/> value to write.</param>
+        public virtual void WriteValue(float? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Double}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Double}"/> value to write.</param>
+        public virtual void WriteValue(double? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Boolean}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Boolean}"/> value to write.</param>
+        public virtual void WriteValue(bool? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Int16}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Int16}"/> value to write.</param>
+        public virtual void WriteValue(short? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{UInt16}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{UInt16}"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(ushort? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Char}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Char}"/> value to write.</param>
+        public virtual void WriteValue(char? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Byte}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Byte}"/> value to write.</param>
+        public virtual void WriteValue(byte? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{SByte}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{SByte}"/> value to write.</param>
+        [CLSCompliant(false)]
+        public virtual void WriteValue(sbyte? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Decimal}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Decimal}"/> value to write.</param>
+        public virtual void WriteValue(decimal? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{DateTime}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{DateTime}"/> value to write.</param>
+        public virtual void WriteValue(DateTime? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Writes a <see cref="Nullable{DateTimeOffset}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{DateTimeOffset}"/> value to write.</param>
+        public virtual void WriteValue(DateTimeOffset? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+#endif
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{Guid}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{Guid}"/> value to write.</param>
+        public virtual void WriteValue(Guid? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Nullable{TimeSpan}"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Nullable{TimeSpan}"/> value to write.</param>
+        public virtual void WriteValue(TimeSpan? value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                WriteValue(value.Value);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="T:Byte[]"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
+        public virtual void WriteValue(byte[] value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                InternalWriteValue(JsonToken.Bytes);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Uri"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Uri"/> value to write.</param>
+        public virtual void WriteValue(Uri value)
+        {
+            if (value == null)
+                WriteNull();
+            else
+                InternalWriteValue(JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Object"/> value.
+        /// An error will raised if the value cannot be written as a single JSON token.
+        /// </summary>
+        /// <param name="value">The <see cref="Object"/> value to write.</param>
+        public virtual void WriteValue(object value)
+        {
+            if (value == null)
+            {
+                WriteNull();
+            }
+            else
+            {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+                // this is here because adding a WriteValue(BigInteger) to JsonWriter will
+                // mean the user has to add a reference to System.Numerics.dll
+                if (value is BigInteger)
+                    throw CreateUnsupportedTypeException(this, value);
+#endif
+
+                WriteValue(this, ConvertUtils.GetTypeCode(value), value);
+            }
+        }
+        #endregion
+
+        /// <summary>
+        /// Writes out a comment <code>/*...*/</code> containing the specified text. 
+        /// </summary>
+        /// <param name="text">Text to place inside the comment.</param>
+        public virtual void WriteComment(string text)
+        {
+            InternalWriteComment();
+        }
+
+        /// <summary>
+        /// Writes out the given white space.
+        /// </summary>
+        /// <param name="ws">The string of white space characters.</param>
+        public virtual void WriteWhitespace(string ws)
+        {
+            InternalWriteWhitespace(ws);
+        }
+
+        void IDisposable.Dispose()
+        {
+            Dispose(true);
+        }
+
+        private void Dispose(bool disposing)
+        {
+            if (_currentState != State.Closed)
+                Close();
+        }
+
+        internal static void WriteValue(JsonWriter writer, PrimitiveTypeCode typeCode, object value)
+        {
+            switch (typeCode)
+            {
+                case PrimitiveTypeCode.Char:
+                    writer.WriteValue((char)value);
+                    break;
+                case PrimitiveTypeCode.CharNullable:
+                    writer.WriteValue((value == null) ? (char?)null : (char)value);
+                    break;
+                case PrimitiveTypeCode.Boolean:
+                    writer.WriteValue((bool)value);
+                    break;
+                case PrimitiveTypeCode.BooleanNullable:
+                    writer.WriteValue((value == null) ? (bool?)null : (bool)value);
+                    break;
+                case PrimitiveTypeCode.SByte:
+                    writer.WriteValue((sbyte)value);
+                    break;
+                case PrimitiveTypeCode.SByteNullable:
+                    writer.WriteValue((value == null) ? (sbyte?)null : (sbyte)value);
+                    break;
+                case PrimitiveTypeCode.Int16:
+                    writer.WriteValue((short)value);
+                    break;
+                case PrimitiveTypeCode.Int16Nullable:
+                    writer.WriteValue((value == null) ? (short?)null : (short)value);
+                    break;
+                case PrimitiveTypeCode.UInt16:
+                    writer.WriteValue((ushort)value);
+                    break;
+                case PrimitiveTypeCode.UInt16Nullable:
+                    writer.WriteValue((value == null) ? (ushort?)null : (ushort)value);
+                    break;
+                case PrimitiveTypeCode.Int32:
+                    writer.WriteValue((int)value);
+                    break;
+                case PrimitiveTypeCode.Int32Nullable:
+                    writer.WriteValue((value == null) ? (int?)null : (int)value);
+                    break;
+                case PrimitiveTypeCode.Byte:
+                    writer.WriteValue((byte)value);
+                    break;
+                case PrimitiveTypeCode.ByteNullable:
+                    writer.WriteValue((value == null) ? (byte?)null : (byte)value);
+                    break;
+                case PrimitiveTypeCode.UInt32:
+                    writer.WriteValue((uint)value);
+                    break;
+                case PrimitiveTypeCode.UInt32Nullable:
+                    writer.WriteValue((value == null) ? (uint?)null : (uint)value);
+                    break;
+                case PrimitiveTypeCode.Int64:
+                    writer.WriteValue((long)value);
+                    break;
+                case PrimitiveTypeCode.Int64Nullable:
+                    writer.WriteValue((value == null) ? (long?)null : (long)value);
+                    break;
+                case PrimitiveTypeCode.UInt64:
+                    writer.WriteValue((ulong)value);
+                    break;
+                case PrimitiveTypeCode.UInt64Nullable:
+                    writer.WriteValue((value == null) ? (ulong?)null : (ulong)value);
+                    break;
+                case PrimitiveTypeCode.Single:
+                    writer.WriteValue((float)value);
+                    break;
+                case PrimitiveTypeCode.SingleNullable:
+                    writer.WriteValue((value == null) ? (float?)null : (float)value);
+                    break;
+                case PrimitiveTypeCode.Double:
+                    writer.WriteValue((double)value);
+                    break;
+                case PrimitiveTypeCode.DoubleNullable:
+                    writer.WriteValue((value == null) ? (double?)null : (double)value);
+                    break;
+                case PrimitiveTypeCode.DateTime:
+                    writer.WriteValue((DateTime)value);
+                    break;
+                case PrimitiveTypeCode.DateTimeNullable:
+                    writer.WriteValue((value == null) ? (DateTime?)null : (DateTime)value);
+                    break;
+#if !NET20
+                case PrimitiveTypeCode.DateTimeOffset:
+                    writer.WriteValue((DateTimeOffset)value);
+                    break;
+                case PrimitiveTypeCode.DateTimeOffsetNullable:
+                    writer.WriteValue((value == null) ? (DateTimeOffset?)null : (DateTimeOffset)value);
+                    break;
+#endif
+                case PrimitiveTypeCode.Decimal:
+                    writer.WriteValue((decimal)value);
+                    break;
+                case PrimitiveTypeCode.DecimalNullable:
+                    writer.WriteValue((value == null) ? (decimal?)null : (decimal)value);
+                    break;
+                case PrimitiveTypeCode.Guid:
+                    writer.WriteValue((Guid)value);
+                    break;
+                case PrimitiveTypeCode.GuidNullable:
+                    writer.WriteValue((value == null) ? (Guid?)null : (Guid)value);
+                    break;
+                case PrimitiveTypeCode.TimeSpan:
+                    writer.WriteValue((TimeSpan)value);
+                    break;
+                case PrimitiveTypeCode.TimeSpanNullable:
+                    writer.WriteValue((value == null) ? (TimeSpan?)null : (TimeSpan)value);
+                    break;
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+                case PrimitiveTypeCode.BigInteger:
+                    // this will call to WriteValue(object)
+                    writer.WriteValue((BigInteger)value);
+                    break;
+                case PrimitiveTypeCode.BigIntegerNullable:
+                    // this will call to WriteValue(object)
+                    writer.WriteValue((value == null) ? (BigInteger?)null : (BigInteger)value);
+                    break;
+#endif
+                case PrimitiveTypeCode.Uri:
+                    writer.WriteValue((Uri)value);
+                    break;
+                case PrimitiveTypeCode.String:
+                    writer.WriteValue((string)value);
+                    break;
+                case PrimitiveTypeCode.Bytes:
+                    writer.WriteValue((byte[])value);
+                    break;
+#if !(PORTABLE || NETFX_CORE)
+                case PrimitiveTypeCode.DBNull:
+                    writer.WriteNull();
+                    break;
+#endif
+                default:
+#if !(PORTABLE || NETFX_CORE)
+                    if (value is IConvertible)
+                    {
+                        // the value is a non-standard IConvertible
+                        // convert to the underlying value and retry
+                        IConvertible convertable = (IConvertible)value;
+
+                        TypeInformation typeInformation = ConvertUtils.GetTypeInformation(convertable);
+
+                        // if convertable has an underlying typecode of Object then attempt to convert it to a string
+                        PrimitiveTypeCode resolvedTypeCode = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? PrimitiveTypeCode.String : typeInformation.TypeCode;
+                        Type resolvedType = (typeInformation.TypeCode == PrimitiveTypeCode.Object) ? typeof(string) : typeInformation.Type;
+
+                        object convertedValue = convertable.ToType(resolvedType, CultureInfo.InvariantCulture);
+
+                        WriteValue(writer, resolvedTypeCode, convertedValue);
+                        break;
+                    }
+                    else
+#endif
+                    {
+                        throw CreateUnsupportedTypeException(writer, value);
+                    }
+            }
+        }
+
+        private static JsonWriterException CreateUnsupportedTypeException(JsonWriter writer, object value)
+        {
+            return JsonWriterException.Create(writer, "Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null);
+        }
+
+        /// <summary>
+        /// Sets the state of the JsonWriter,
+        /// </summary>
+        /// <param name="token">The JsonToken being written.</param>
+        /// <param name="value">The value being written.</param>
+        protected void SetWriteState(JsonToken token, object value)
+        {
+            switch (token)
+            {
+                case JsonToken.StartObject:
+                    InternalWriteStart(token, JsonContainerType.Object);
+                    break;
+                case JsonToken.StartArray:
+                    InternalWriteStart(token, JsonContainerType.Array);
+                    break;
+                case JsonToken.StartConstructor:
+                    InternalWriteStart(token, JsonContainerType.Constructor);
+                    break;
+                case JsonToken.PropertyName:
+                    if (!(value is string))
+                        throw new ArgumentException("A name is required when setting property name state.", "value");
+
+                    InternalWritePropertyName((string)value);
+                    break;
+                case JsonToken.Comment:
+                    InternalWriteComment();
+                    break;
+                case JsonToken.Raw:
+                    InternalWriteRaw();
+                    break;
+                case JsonToken.Integer:
+                case JsonToken.Float:
+                case JsonToken.String:
+                case JsonToken.Boolean:
+                case JsonToken.Date:
+                case JsonToken.Bytes:
+                case JsonToken.Null:
+                case JsonToken.Undefined:
+                    InternalWriteValue(token);
+                    break;
+                case JsonToken.EndObject:
+                    InternalWriteEnd(JsonContainerType.Object);
+                    break;
+                case JsonToken.EndArray:
+                    InternalWriteEnd(JsonContainerType.Array);
+                    break;
+                case JsonToken.EndConstructor:
+                    InternalWriteEnd(JsonContainerType.Constructor);
+                    break;
+                default:
+                    throw new ArgumentOutOfRangeException("token");
+            }
+        }
+
+        internal void InternalWriteEnd(JsonContainerType container)
+        {
+            AutoCompleteClose(container);
+        }
+
+        internal void InternalWritePropertyName(string name)
+        {
+            _currentPosition.PropertyName = name;
+            AutoComplete(JsonToken.PropertyName);
+        }
+
+        internal void InternalWriteRaw()
+        {
+        }
+
+        internal void InternalWriteStart(JsonToken token, JsonContainerType container)
+        {
+            UpdateScopeWithFinishedValue();
+            AutoComplete(token);
+            Push(container);
+        }
+
+        internal void InternalWriteValue(JsonToken token)
+        {
+            UpdateScopeWithFinishedValue();
+            AutoComplete(token);
+        }
+
+        internal void InternalWriteWhitespace(string ws)
+        {
+            if (ws != null)
+            {
+                if (!StringUtils.IsWhiteSpace(ws))
+                    throw JsonWriterException.Create(this, "Only white space characters should be used.", null);
+            }
+        }
+
+        internal void InternalWriteComment()
+        {
+            AutoComplete(JsonToken.Comment);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/JsonWriterException.cs b/Newtonsoft.Json/JsonWriterException.cs
new file mode 100644
index 0000000..d1044e7
--- /dev/null
+++ b/Newtonsoft.Json/JsonWriterException.cs
@@ -0,0 +1,107 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// The exception thrown when an error occurs while reading Json text.
+    /// </summary>
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+    [Serializable]
+#endif
+    public class JsonWriterException : JsonException
+    {
+        /// <summary>
+        /// Gets the path to the JSON where the error occurred.
+        /// </summary>
+        /// <value>The path to the JSON where the error occurred.</value>
+        public string Path { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonWriterException"/> class.
+        /// </summary>
+        public JsonWriterException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonWriterException"/> class
+        /// with a specified error message.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        public JsonWriterException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonWriterException"/> class
+        /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+        public JsonWriterException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonWriterException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        public JsonWriterException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+#endif
+
+        internal JsonWriterException(string message, Exception innerException, string path)
+            : base(message, innerException)
+        {
+            Path = path;
+        }
+
+        internal static JsonWriterException Create(JsonWriter writer, string message, Exception ex)
+        {
+            return Create(writer.ContainerPath, message, ex);
+        }
+
+        internal static JsonWriterException Create(string path, string message, Exception ex)
+        {
+            message = JsonPosition.FormatMessage(null, path, message);
+
+            return new JsonWriterException(message, ex, path);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/Extensions.cs b/Newtonsoft.Json/Linq/Extensions.cs
new file mode 100644
index 0000000..7f6919d
--- /dev/null
+++ b/Newtonsoft.Json/Linq/Extensions.cs
@@ -0,0 +1,312 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Contains the LINQ to JSON extension methods.
+    /// </summary>
+    public static class Extensions
+    {
+        /// <summary>
+        /// Returns a collection of tokens that contains the ancestors of every token in the source collection.
+        /// </summary>
+        /// <typeparam name="T">The type of the objects in source, constrained to <see cref="JToken"/>.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the ancestors of every node in the source collection.</returns>
+        public static IJEnumerable<JToken> Ancestors<T>(this IEnumerable<T> source) where T : JToken
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            return source.SelectMany(j => j.Ancestors()).AsJEnumerable();
+        }
+
+        //TODO
+        //public static IEnumerable<JObject> AncestorsAndSelf<T>(this IEnumerable<T> source) where T : JObject
+        //{
+        //  ValidationUtils.ArgumentNotNull(source, "source");
+
+        //  return source.SelectMany(j => j.AncestorsAndSelf());
+        //}
+
+        /// <summary>
+        /// Returns a collection of tokens that contains the descendants of every token in the source collection.
+        /// </summary>
+        /// <typeparam name="T">The type of the objects in source, constrained to <see cref="JContainer"/>.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the descendants of every node in the source collection.</returns>
+        public static IJEnumerable<JToken> Descendants<T>(this IEnumerable<T> source) where T : JContainer
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            return source.SelectMany(j => j.Descendants()).AsJEnumerable();
+        }
+
+        //TODO
+        //public static IEnumerable<JObject> DescendantsAndSelf<T>(this IEnumerable<T> source) where T : JContainer
+        //{
+        //  ValidationUtils.ArgumentNotNull(source, "source");
+
+        //  return source.SelectMany(j => j.DescendantsAndSelf());
+        //}
+
+        /// <summary>
+        /// Returns a collection of child properties of every object in the source collection.
+        /// </summary>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JObject"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JProperty"/> that contains the properties of every object in the source collection.</returns>
+        public static IJEnumerable<JProperty> Properties(this IEnumerable<JObject> source)
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            return source.SelectMany(d => d.Properties()).AsJEnumerable();
+        }
+
+        /// <summary>
+        /// Returns a collection of child values of every object in the source collection with the given key.
+        /// </summary>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <param name="key">The token key.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection with the given key.</returns>
+        public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source, object key)
+        {
+            return Values<JToken, JToken>(source, key).AsJEnumerable();
+        }
+
+        /// <summary>
+        /// Returns a collection of child values of every object in the source collection.
+        /// </summary>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection.</returns>
+        public static IJEnumerable<JToken> Values(this IEnumerable<JToken> source)
+        {
+            return source.Values(null);
+        }
+
+        /// <summary>
+        /// Returns a collection of converted child values of every object in the source collection with the given key.
+        /// </summary>
+        /// <typeparam name="U">The type to convert the values to.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <param name="key">The token key.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection with the given key.</returns>
+        public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source, object key)
+        {
+            return Values<JToken, U>(source, key);
+        }
+
+        /// <summary>
+        /// Returns a collection of converted child values of every object in the source collection.
+        /// </summary>
+        /// <typeparam name="U">The type to convert the values to.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection.</returns>
+        public static IEnumerable<U> Values<U>(this IEnumerable<JToken> source)
+        {
+            return Values<JToken, U>(source, null);
+        }
+
+        /// <summary>
+        /// Converts the value.
+        /// </summary>
+        /// <typeparam name="U">The type to convert the value to.</typeparam>
+        /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
+        /// <returns>A converted value.</returns>
+        public static U Value<U>(this IEnumerable<JToken> value)
+        {
+            return value.Value<JToken, U>();
+        }
+
+        /// <summary>
+        /// Converts the value.
+        /// </summary>
+        /// <typeparam name="T">The source collection type.</typeparam>
+        /// <typeparam name="U">The type to convert the value to.</typeparam>
+        /// <param name="value">A <see cref="JToken"/> cast as a <see cref="IEnumerable{T}"/> of <see cref="JToken"/>.</param>
+        /// <returns>A converted value.</returns>
+        public static U Value<T, U>(this IEnumerable<T> value) where T : JToken
+        {
+            ValidationUtils.ArgumentNotNull(value, "source");
+
+            JToken token = value as JToken;
+            if (token == null)
+                throw new ArgumentException("Source value must be a JToken.");
+
+            return token.Convert<JToken, U>();
+        }
+
+
+        internal static IEnumerable<U> Values<T, U>(this IEnumerable<T> source, object key) where T : JToken
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            foreach (JToken token in source)
+            {
+                if (key == null)
+                {
+                    if (token is JValue)
+                    {
+                        yield return Convert<JValue, U>((JValue)token);
+                    }
+                    else
+                    {
+                        foreach (JToken t in token.Children())
+                        {
+                            yield return t.Convert<JToken, U>();
+                        }
+                    }
+                }
+                else
+                {
+                    JToken value = token[key];
+                    if (value != null)
+                        yield return value.Convert<JToken, U>();
+                }
+            }
+
+            yield break;
+        }
+
+        //TODO
+        //public static IEnumerable<T> InDocumentOrder<T>(this IEnumerable<T> source) where T : JObject;
+
+        //public static IEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
+        //{
+        //  ValidationUtils.ArgumentNotNull(source, "source");
+
+        //  return source.SelectMany(c => c.Children());
+        //}
+
+        /// <summary>
+        /// Returns a collection of child tokens of every array in the source collection.
+        /// </summary>
+        /// <typeparam name="T">The source collection type.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the values of every node in the source collection.</returns>
+        public static IJEnumerable<JToken> Children<T>(this IEnumerable<T> source) where T : JToken
+        {
+            return Children<T, JToken>(source).AsJEnumerable();
+        }
+
+        /// <summary>
+        /// Returns a collection of converted child tokens of every array in the source collection.
+        /// </summary>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <typeparam name="U">The type to convert the values to.</typeparam>
+        /// <typeparam name="T">The source collection type.</typeparam>
+        /// <returns>An <see cref="IEnumerable{T}"/> that contains the converted values of every node in the source collection.</returns>
+        public static IEnumerable<U> Children<T, U>(this IEnumerable<T> source) where T : JToken
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            return source.SelectMany(c => c.Children()).Convert<JToken, U>();
+        }
+
+        internal static IEnumerable<U> Convert<T, U>(this IEnumerable<T> source) where T : JToken
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+
+            foreach (T token in source)
+            {
+                yield return Convert<JToken, U>(token);
+            }
+        }
+
+        internal static U Convert<T, U>(this T token) where T : JToken
+        {
+            if (token == null)
+                return default(U);
+
+            if (token is U
+                // don't want to cast JValue to its interfaces, want to get the internal value
+                && typeof(U) != typeof(IComparable) && typeof(U) != typeof(IFormattable))
+            {
+                // HACK
+                return (U)(object)token;
+            }
+            else
+            {
+                JValue value = token as JValue;
+                if (value == null)
+                    throw new InvalidCastException("Cannot cast {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, token.GetType(), typeof(T)));
+
+                if (value.Value is U)
+                    return (U)value.Value;
+
+                Type targetType = typeof(U);
+
+                if (ReflectionUtils.IsNullableType(targetType))
+                {
+                    if (value.Value == null)
+                        return default(U);
+
+                    targetType = Nullable.GetUnderlyingType(targetType);
+                }
+
+                return (U)System.Convert.ChangeType(value.Value, targetType, CultureInfo.InvariantCulture);
+            }
+        }
+
+        //TODO
+        //public static void Remove<T>(this IEnumerable<T> source) where T : JContainer;
+
+        /// <summary>
+        /// Returns the input typed as <see cref="IJEnumerable{T}"/>.
+        /// </summary>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
+        public static IJEnumerable<JToken> AsJEnumerable(this IEnumerable<JToken> source)
+        {
+            return source.AsJEnumerable<JToken>();
+        }
+
+        /// <summary>
+        /// Returns the input typed as <see cref="IJEnumerable{T}"/>.
+        /// </summary>
+        /// <typeparam name="T">The source collection type.</typeparam>
+        /// <param name="source">An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> that contains the source collection.</param>
+        /// <returns>The input typed as <see cref="IJEnumerable{T}"/>.</returns>
+        public static IJEnumerable<T> AsJEnumerable<T>(this IEnumerable<T> source) where T : JToken
+        {
+            if (source == null)
+                return null;
+            else if (source is IJEnumerable<T>)
+                return (IJEnumerable<T>)source;
+            else
+                return new JEnumerable<T>(source);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/IJEnumerable.cs b/Newtonsoft.Json/Linq/IJEnumerable.cs
new file mode 100644
index 0000000..4ae22fb
--- /dev/null
+++ b/Newtonsoft.Json/Linq/IJEnumerable.cs
@@ -0,0 +1,46 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a collection of <see cref="JToken"/> objects.
+    /// </summary>
+    /// <typeparam name="T">The type of token</typeparam>
+    public interface IJEnumerable<
+#if !(NET20 || NET35 || PORTABLE40)
+        out
+#endif
+            T> : IEnumerable<T> where T : JToken
+    {
+        /// <summary>
+        /// Gets the <see cref="IJEnumerable{JToken}"/> with the specified key.
+        /// </summary>
+        /// <value></value>
+        IJEnumerable<JToken> this[object key] { get; }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JArray.cs b/Newtonsoft.Json/Linq/JArray.cs
new file mode 100644
index 0000000..8461762
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JArray.cs
@@ -0,0 +1,356 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.IO;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a JSON array.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
+    /// </example>
+    public class JArray : JContainer, IList<JToken>
+    {
+        private readonly List<JToken> _values = new List<JToken>();
+
+        /// <summary>
+        /// Gets the container's children tokens.
+        /// </summary>
+        /// <value>The container's children tokens.</value>
+        protected override IList<JToken> ChildrenTokens
+        {
+            get { return _values; }
+        }
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public override JTokenType Type
+        {
+            get { return JTokenType.Array; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JArray"/> class.
+        /// </summary>
+        public JArray()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JArray"/> class from another <see cref="JArray"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JArray"/> object to copy from.</param>
+        public JArray(JArray other)
+            : base(other)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JArray"/> class with the specified content.
+        /// </summary>
+        /// <param name="content">The contents of the array.</param>
+        public JArray(params object[] content)
+            : this((object)content)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JArray"/> class with the specified content.
+        /// </summary>
+        /// <param name="content">The contents of the array.</param>
+        public JArray(object content)
+        {
+            Add(content);
+        }
+
+        internal override bool DeepEquals(JToken node)
+        {
+            JArray t = node as JArray;
+            return (t != null && ContentsEqual(t));
+        }
+
+        internal override JToken CloneToken()
+        {
+            return new JArray(this);
+        }
+
+        /// <summary>
+        /// Loads an <see cref="JArray"/> from a <see cref="JsonReader"/>. 
+        /// </summary>
+        /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JArray"/>.</param>
+        /// <returns>A <see cref="JArray"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
+        public new static JArray Load(JsonReader reader)
+        {
+            if (reader.TokenType == JsonToken.None)
+            {
+                if (!reader.Read())
+                    throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader.");
+            }
+
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                reader.Read();
+            }
+
+            if (reader.TokenType != JsonToken.StartArray)
+                throw JsonReaderException.Create(reader, "Error reading JArray from JsonReader. Current JsonReader item is not an array: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            JArray a = new JArray();
+            a.SetLineInfo(reader as IJsonLineInfo);
+
+            a.ReadTokenFrom(reader);
+
+            return a;
+        }
+
+        /// <summary>
+        /// Load a <see cref="JArray"/> from a string that contains JSON.
+        /// </summary>
+        /// <param name="json">A <see cref="String"/> that contains JSON.</param>
+        /// <returns>A <see cref="JArray"/> populated from the string that contains JSON.</returns>
+        /// <example>
+        ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParseArray" title="Parsing a JSON Array from Text" />
+        /// </example>
+        public new static JArray Parse(string json)
+        {
+            using (JsonReader reader = new JsonTextReader(new StringReader(json)))
+            {
+                JArray a = Load(reader);
+
+                if (reader.Read() && reader.TokenType != JsonToken.Comment)
+                    throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
+
+                return a;
+            }
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JArray"/> from an object.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JArray"/>.</param>
+        /// <returns>A <see cref="JArray"/> with the values of the specified object</returns>
+        public new static JArray FromObject(object o)
+        {
+            return FromObject(o, JsonSerializer.CreateDefault());
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JArray"/> from an object.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JArray"/>.</param>
+        /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used to read the object.</param>
+        /// <returns>A <see cref="JArray"/> with the values of the specified object</returns>
+        public new static JArray FromObject(object o, JsonSerializer jsonSerializer)
+        {
+            JToken token = FromObjectInternal(o, jsonSerializer);
+
+            if (token.Type != JTokenType.Array)
+                throw new ArgumentException("Object serialized to {0}. JArray instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+            return (JArray)token;
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+        {
+            writer.WriteStartArray();
+
+            for (int i = 0; i < _values.Count; i++)
+            {
+                _values[i].WriteTo(writer, converters);
+            }
+
+            writer.WriteEndArray();
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JToken"/> with the specified key.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> with the specified key.</value>
+        public override JToken this[object key]
+        {
+            get
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                if (!(key is int))
+                    throw new ArgumentException("Accessed JArray values with invalid key value: {0}. Array position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                return GetItem((int)key);
+            }
+            set
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                if (!(key is int))
+                    throw new ArgumentException("Set JArray values with invalid key value: {0}. Array position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                SetItem((int)key, value);
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="Newtonsoft.Json.Linq.JToken"/> at the specified index.
+        /// </summary>
+        /// <value></value>
+        public JToken this[int index]
+        {
+            get { return GetItem(index); }
+            set { SetItem(index, value); }
+        }
+
+        #region IList<JToken> Members
+        /// <summary>
+        /// Determines the index of a specific item in the <see cref="T:System.Collections.Generic.IList`1"/>.
+        /// </summary>
+        /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+        /// <returns>
+        /// The index of <paramref name="item"/> if found in the list; otherwise, -1.
+        /// </returns>
+        public int IndexOf(JToken item)
+        {
+            return IndexOfItem(item);
+        }
+
+        /// <summary>
+        /// Inserts an item to the <see cref="T:System.Collections.Generic.IList`1"/> at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index at which <paramref name="item"/> should be inserted.</param>
+        /// <param name="item">The object to insert into the <see cref="T:System.Collections.Generic.IList`1"/>.</param>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        /// 	<paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
+        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
+        public void Insert(int index, JToken item)
+        {
+            InsertItem(index, item, false);
+        }
+
+        /// <summary>
+        /// Removes the <see cref="T:System.Collections.Generic.IList`1"/> item at the specified index.
+        /// </summary>
+        /// <param name="index">The zero-based index of the item to remove.</param>
+        /// <exception cref="T:System.ArgumentOutOfRangeException">
+        /// 	<paramref name="index"/> is not a valid index in the <see cref="T:System.Collections.Generic.IList`1"/>.</exception>
+        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.IList`1"/> is read-only.</exception>
+        public void RemoveAt(int index)
+        {
+            RemoveItemAt(index);
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> that can be used to iterate through the collection.
+        /// </returns>
+        public IEnumerator<JToken> GetEnumerator()
+        {
+            return Children().GetEnumerator();
+        }
+        #endregion
+
+        #region ICollection<JToken> Members
+        /// <summary>
+        /// Adds an item to the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+        /// </summary>
+        /// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
+        public void Add(JToken item)
+        {
+            Add((object)item);
+        }
+
+        /// <summary>
+        /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+        /// </summary>
+        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
+        public void Clear()
+        {
+            ClearItems();
+        }
+
+        /// <summary>
+        /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
+        /// </summary>
+        /// <param name="item">The object to locate in the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+        /// <returns>
+        /// true if <paramref name="item"/> is found in the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false.
+        /// </returns>
+        public bool Contains(JToken item)
+        {
+            return ContainsItem(item);
+        }
+
+        /// <summary>
+        /// Copies to.
+        /// </summary>
+        /// <param name="array">The array.</param>
+        /// <param name="arrayIndex">Index of the array.</param>
+        public void CopyTo(JToken[] array, int arrayIndex)
+        {
+            CopyItemsTo(array, arrayIndex);
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only.
+        /// </summary>
+        /// <returns>true if the <see cref="T:System.Collections.Generic.ICollection`1" /> is read-only; otherwise, false.</returns>
+        public bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        /// <summary>
+        /// Removes the first occurrence of a specific object from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
+        /// </summary>
+        /// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param>
+        /// <returns>
+        /// true if <paramref name="item"/> was successfully removed from the <see cref="T:System.Collections.Generic.ICollection`1"/>; otherwise, false. This method also returns false if <paramref name="item"/> is not found in the original <see cref="T:System.Collections.Generic.ICollection`1"/>.
+        /// </returns>
+        /// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
+        public bool Remove(JToken item)
+        {
+            return RemoveItem(item);
+        }
+        #endregion
+
+        internal override int GetDeepHashCode()
+        {
+            return ContentsHashCode();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JConstructor.cs b/Newtonsoft.Json/Linq/JConstructor.cs
new file mode 100644
index 0000000..119145b
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JConstructor.cs
@@ -0,0 +1,206 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a JSON constructor.
+    /// </summary>
+    public class JConstructor : JContainer
+    {
+        private string _name;
+        private readonly List<JToken> _values = new List<JToken>();
+
+        /// <summary>
+        /// Gets the container's children tokens.
+        /// </summary>
+        /// <value>The container's children tokens.</value>
+        protected override IList<JToken> ChildrenTokens
+        {
+            get { return _values; }
+        }
+
+        /// <summary>
+        /// Gets or sets the name of this constructor.
+        /// </summary>
+        /// <value>The constructor name.</value>
+        public string Name
+        {
+            get { return _name; }
+            set { _name = value; }
+        }
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public override JTokenType Type
+        {
+            get { return JTokenType.Constructor; }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JConstructor"/> class.
+        /// </summary>
+        public JConstructor()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JConstructor"/> class from another <see cref="JConstructor"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JConstructor"/> object to copy from.</param>
+        public JConstructor(JConstructor other)
+            : base(other)
+        {
+            _name = other.Name;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
+        /// </summary>
+        /// <param name="name">The constructor name.</param>
+        /// <param name="content">The contents of the constructor.</param>
+        public JConstructor(string name, params object[] content)
+            : this(name, (object)content)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name and content.
+        /// </summary>
+        /// <param name="name">The constructor name.</param>
+        /// <param name="content">The contents of the constructor.</param>
+        public JConstructor(string name, object content)
+            : this(name)
+        {
+            Add(content);
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JConstructor"/> class with the specified name.
+        /// </summary>
+        /// <param name="name">The constructor name.</param>
+        public JConstructor(string name)
+        {
+            ValidationUtils.ArgumentNotNullOrEmpty(name, "name");
+
+            _name = name;
+        }
+
+        internal override bool DeepEquals(JToken node)
+        {
+            JConstructor c = node as JConstructor;
+            return (c != null && _name == c.Name && ContentsEqual(c));
+        }
+
+        internal override JToken CloneToken()
+        {
+            return new JConstructor(this);
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+        {
+            writer.WriteStartConstructor(_name);
+
+            foreach (JToken token in Children())
+            {
+                token.WriteTo(writer, converters);
+            }
+
+            writer.WriteEndConstructor();
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JToken"/> with the specified key.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> with the specified key.</value>
+        public override JToken this[object key]
+        {
+            get
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                if (!(key is int))
+                    throw new ArgumentException("Accessed JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                return GetItem((int)key);
+            }
+            set
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                if (!(key is int))
+                    throw new ArgumentException("Set JConstructor values with invalid key value: {0}. Argument position index expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                SetItem((int)key, value);
+            }
+        }
+
+        internal override int GetDeepHashCode()
+        {
+            return _name.GetHashCode() ^ ContentsHashCode();
+        }
+
+        /// <summary>
+        /// Loads an <see cref="JConstructor"/> from a <see cref="JsonReader"/>. 
+        /// </summary>
+        /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JConstructor"/>.</param>
+        /// <returns>A <see cref="JConstructor"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
+        public new static JConstructor Load(JsonReader reader)
+        {
+            if (reader.TokenType == JsonToken.None)
+            {
+                if (!reader.Read())
+                    throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader.");
+            }
+
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                reader.Read();
+            }
+
+            if (reader.TokenType != JsonToken.StartConstructor)
+                throw JsonReaderException.Create(reader, "Error reading JConstructor from JsonReader. Current JsonReader item is not a constructor: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            JConstructor c = new JConstructor((string)reader.Value);
+            c.SetLineInfo(reader as IJsonLineInfo);
+
+            c.ReadTokenFrom(reader);
+
+            return c;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JContainer.cs b/Newtonsoft.Json/Linq/JContainer.cs
new file mode 100644
index 0000000..91bbbd4
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JContainer.cs
@@ -0,0 +1,1011 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !PORTABLE40
+using System.Collections.Specialized;
+#endif
+using System.Threading;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+using System.Globalization;
+using System.ComponentModel;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a token that can contain other tokens.
+    /// </summary>
+    public abstract class JContainer : JToken, IList<JToken>
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        , ITypedList, IBindingList
+#elif PORTABLE
+    , INotifyCollectionChanged
+#endif
+        , IList
+#if !(NET20 || NET35 || NETFX_CORE || PORTABLE40 || PORTABLE)
+        , INotifyCollectionChanged
+#endif
+    {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        internal ListChangedEventHandler _listChanged;
+        internal AddingNewEventHandler _addingNew;
+
+        /// <summary>
+        /// Occurs when the list changes or an item in the list changes.
+        /// </summary>
+        public event ListChangedEventHandler ListChanged
+        {
+            add { _listChanged += value; }
+            remove { _listChanged -= value; }
+        }
+
+        /// <summary>
+        /// Occurs before an item is added to the collection.
+        /// </summary>
+        public event AddingNewEventHandler AddingNew
+        {
+            add { _addingNew += value; }
+            remove { _addingNew -= value; }
+        }
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+        internal NotifyCollectionChangedEventHandler _collectionChanged;
+
+        /// <summary>
+        /// Occurs when the items list of the collection has changed, or the collection is reset.
+        /// </summary>
+        public event NotifyCollectionChangedEventHandler CollectionChanged
+        {
+            add { _collectionChanged += value; }
+            remove { _collectionChanged -= value; }
+        }
+#endif
+
+        /// <summary>
+        /// Gets the container's children tokens.
+        /// </summary>
+        /// <value>The container's children tokens.</value>
+        protected abstract IList<JToken> ChildrenTokens { get; }
+
+        private object _syncRoot;
+#if !(PORTABLE40)
+        private bool _busy;
+#endif
+
+        internal JContainer()
+        {
+        }
+
+        internal JContainer(JContainer other)
+            : this()
+        {
+            ValidationUtils.ArgumentNotNull(other, "c");
+
+            foreach (JToken child in other)
+            {
+                Add(child);
+            }
+        }
+
+        internal void CheckReentrancy()
+        {
+#if !(PORTABLE40)
+            if (_busy)
+                throw new InvalidOperationException("Cannot change {0} during a collection change event.".FormatWith(CultureInfo.InvariantCulture, GetType()));
+#endif
+        }
+
+        internal virtual IList<JToken> CreateChildrenCollection()
+        {
+            return new List<JToken>();
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Raises the <see cref="AddingNew"/> event.
+        /// </summary>
+        /// <param name="e">The <see cref="AddingNewEventArgs"/> instance containing the event data.</param>
+        protected virtual void OnAddingNew(AddingNewEventArgs e)
+        {
+            AddingNewEventHandler handler = _addingNew;
+            if (handler != null)
+                handler(this, e);
+        }
+
+        /// <summary>
+        /// Raises the <see cref="ListChanged"/> event.
+        /// </summary>
+        /// <param name="e">The <see cref="ListChangedEventArgs"/> instance containing the event data.</param>
+        protected virtual void OnListChanged(ListChangedEventArgs e)
+        {
+            ListChangedEventHandler handler = _listChanged;
+
+            if (handler != null)
+            {
+                _busy = true;
+                try
+                {
+                    handler(this, e);
+                }
+                finally
+                {
+                    _busy = false;
+                }
+            }
+        }
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+        /// <summary>
+        /// Raises the <see cref="CollectionChanged"/> event.
+        /// </summary>
+        /// <param name="e">The <see cref="NotifyCollectionChangedEventArgs"/> instance containing the event data.</param>
+        protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+        {
+            NotifyCollectionChangedEventHandler handler = _collectionChanged;
+
+            if (handler != null)
+            {
+                _busy = true;
+                try
+                {
+                    handler(this, e);
+                }
+                finally
+                {
+                    _busy = false;
+                }
+            }
+        }
+#endif
+
+        /// <summary>
+        /// Gets a value indicating whether this token has child tokens.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this token has child values; otherwise, <c>false</c>.
+        /// </value>
+        public override bool HasValues
+        {
+            get { return ChildrenTokens.Count > 0; }
+        }
+
+        internal bool ContentsEqual(JContainer container)
+        {
+            if (container == this)
+                return true;
+
+            IList<JToken> t1 = ChildrenTokens;
+            IList<JToken> t2 = container.ChildrenTokens;
+
+            if (t1.Count != t2.Count)
+                return false;
+
+            for (int i = 0; i < t1.Count; i++)
+            {
+                if (!t1[i].DeepEquals(t2[i]))
+                    return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Get the first child token of this token.
+        /// </summary>
+        /// <value>
+        /// A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.
+        /// </value>
+        public override JToken First
+        {
+            get { return ChildrenTokens.FirstOrDefault(); }
+        }
+
+        /// <summary>
+        /// Get the last child token of this token.
+        /// </summary>
+        /// <value>
+        /// A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.
+        /// </value>
+        public override JToken Last
+        {
+            get { return ChildrenTokens.LastOrDefault(); }
+        }
+
+        /// <summary>
+        /// Returns a collection of the child tokens of this token, in document order.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.
+        /// </returns>
+        public override JEnumerable<JToken> Children()
+        {
+            return new JEnumerable<JToken>(ChildrenTokens);
+        }
+
+        /// <summary>
+        /// Returns a collection of the child values of this token, in document order.
+        /// </summary>
+        /// <typeparam name="T">The type to convert the values to.</typeparam>
+        /// <returns>
+        /// A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.
+        /// </returns>
+        public override IEnumerable<T> Values<T>()
+        {
+            return ChildrenTokens.Convert<JToken, T>();
+        }
+
+        /// <summary>
+        /// Returns a collection of the descendant tokens for this token in document order.
+        /// </summary>
+        /// <returns>An <see cref="IEnumerable{JToken}"/> containing the descendant tokens of the <see cref="JToken"/>.</returns>
+        public IEnumerable<JToken> Descendants()
+        {
+            foreach (JToken o in ChildrenTokens)
+            {
+                yield return o;
+                JContainer c = o as JContainer;
+                if (c != null)
+                {
+                    foreach (JToken d in c.Descendants())
+                    {
+                        yield return d;
+                    }
+                }
+            }
+        }
+
+        internal bool IsMultiContent(object content)
+        {
+            return (content is IEnumerable && !(content is string) && !(content is JToken) && !(content is byte[]));
+        }
+
+        internal JToken EnsureParentToken(JToken item, bool skipParentCheck)
+        {
+            if (item == null)
+                return new JValue((object)null);
+
+            if (skipParentCheck)
+                return item;
+
+            // to avoid a token having multiple parents or creating a recursive loop, create a copy if...
+            // the item already has a parent
+            // the item is being added to itself
+            // the item is being added to the root parent of itself
+            if (item.Parent != null || item == this || (item.HasValues && Root == item))
+                item = item.CloneToken();
+
+            return item;
+        }
+
+        private class JTokenReferenceEqualityComparer : IEqualityComparer<JToken>
+        {
+            public static readonly JTokenReferenceEqualityComparer Instance = new JTokenReferenceEqualityComparer();
+
+            public bool Equals(JToken x, JToken y)
+            {
+                return ReferenceEquals(x, y);
+            }
+
+            public int GetHashCode(JToken obj)
+            {
+                if (obj == null)
+                    return 0;
+
+                return obj.GetHashCode();
+            }
+        }
+
+        internal int IndexOfItem(JToken item)
+        {
+            return ChildrenTokens.IndexOf(item, JTokenReferenceEqualityComparer.Instance);
+        }
+
+        internal virtual void InsertItem(int index, JToken item, bool skipParentCheck)
+        {
+            if (index > ChildrenTokens.Count)
+                throw new ArgumentOutOfRangeException("index", "Index must be within the bounds of the List.");
+
+            CheckReentrancy();
+
+            item = EnsureParentToken(item, skipParentCheck);
+
+            JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+            // haven't inserted new token yet so next token is still at the inserting index
+            JToken next = (index == ChildrenTokens.Count) ? null : ChildrenTokens[index];
+
+            ValidateToken(item, null);
+
+            item.Parent = this;
+
+            item.Previous = previous;
+            if (previous != null)
+                previous.Next = item;
+
+            item.Next = next;
+            if (next != null)
+                next.Previous = item;
+
+            ChildrenTokens.Insert(index, item);
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (_listChanged != null)
+                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_collectionChanged != null)
+                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item, index));
+#endif
+        }
+
+        internal virtual void RemoveItemAt(int index)
+        {
+            if (index < 0)
+                throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+            if (index >= ChildrenTokens.Count)
+                throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
+
+            CheckReentrancy();
+
+            JToken item = ChildrenTokens[index];
+            JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+            JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+            if (previous != null)
+                previous.Next = next;
+            if (next != null)
+                next.Previous = previous;
+
+            item.Parent = null;
+            item.Previous = null;
+            item.Next = null;
+
+            ChildrenTokens.RemoveAt(index);
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (_listChanged != null)
+                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_collectionChanged != null)
+                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item, index));
+#endif
+        }
+
+        internal virtual bool RemoveItem(JToken item)
+        {
+            int index = IndexOfItem(item);
+            if (index >= 0)
+            {
+                RemoveItemAt(index);
+                return true;
+            }
+
+            return false;
+        }
+
+        internal virtual JToken GetItem(int index)
+        {
+            return ChildrenTokens[index];
+        }
+
+        internal virtual void SetItem(int index, JToken item)
+        {
+            if (index < 0)
+                throw new ArgumentOutOfRangeException("index", "Index is less than 0.");
+            if (index >= ChildrenTokens.Count)
+                throw new ArgumentOutOfRangeException("index", "Index is equal to or greater than Count.");
+
+            JToken existing = ChildrenTokens[index];
+
+            if (IsTokenUnchanged(existing, item))
+                return;
+
+            CheckReentrancy();
+
+            item = EnsureParentToken(item, false);
+
+            ValidateToken(item, existing);
+
+            JToken previous = (index == 0) ? null : ChildrenTokens[index - 1];
+            JToken next = (index == ChildrenTokens.Count - 1) ? null : ChildrenTokens[index + 1];
+
+            item.Parent = this;
+
+            item.Previous = previous;
+            if (previous != null)
+                previous.Next = item;
+
+            item.Next = next;
+            if (next != null)
+                next.Previous = item;
+
+            ChildrenTokens[index] = item;
+
+            existing.Parent = null;
+            existing.Previous = null;
+            existing.Next = null;
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+            if (_listChanged != null)
+                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, index));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_collectionChanged != null)
+                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, item, existing, index));
+#endif
+        }
+
+        internal virtual void ClearItems()
+        {
+            CheckReentrancy();
+
+            foreach (JToken item in ChildrenTokens)
+            {
+                item.Parent = null;
+                item.Previous = null;
+                item.Next = null;
+            }
+
+            ChildrenTokens.Clear();
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (_listChanged != null)
+                OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_collectionChanged != null)
+                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+#endif
+        }
+
+        internal virtual void ReplaceItem(JToken existing, JToken replacement)
+        {
+            if (existing == null || existing.Parent != this)
+                return;
+
+            int index = IndexOfItem(existing);
+            SetItem(index, replacement);
+        }
+
+        internal virtual bool ContainsItem(JToken item)
+        {
+            return (IndexOfItem(item) != -1);
+        }
+
+        internal virtual void CopyItemsTo(Array array, int arrayIndex)
+        {
+            if (array == null)
+                throw new ArgumentNullException("array");
+            if (arrayIndex < 0)
+                throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
+            if (arrayIndex >= array.Length && arrayIndex != 0)
+                throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
+            if (Count > array.Length - arrayIndex)
+                throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
+
+            int index = 0;
+            foreach (JToken token in ChildrenTokens)
+            {
+                array.SetValue(token, arrayIndex + index);
+                index++;
+            }
+        }
+
+        internal static bool IsTokenUnchanged(JToken currentValue, JToken newValue)
+        {
+            JValue v1 = currentValue as JValue;
+            if (v1 != null)
+            {
+                // null will get turned into a JValue of type null
+                if (v1.Type == JTokenType.Null && newValue == null)
+                    return true;
+
+                return v1.Equals(newValue);
+            }
+
+            return false;
+        }
+
+        internal virtual void ValidateToken(JToken o, JToken existing)
+        {
+            ValidationUtils.ArgumentNotNull(o, "o");
+
+            if (o.Type == JTokenType.Property)
+                throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
+        }
+
+        /// <summary>
+        /// Adds the specified content as children of this <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="content">The content to be added.</param>
+        public virtual void Add(object content)
+        {
+            AddInternal(ChildrenTokens.Count, content, false);
+        }
+
+        internal void AddAndSkipParentCheck(JToken token)
+        {
+            AddInternal(ChildrenTokens.Count, token, true);
+        }
+
+        /// <summary>
+        /// Adds the specified content as the first children of this <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="content">The content to be added.</param>
+        public void AddFirst(object content)
+        {
+            AddInternal(0, content, false);
+        }
+
+        internal void AddInternal(int index, object content, bool skipParentCheck)
+        {
+            if (IsMultiContent(content))
+            {
+                IEnumerable enumerable = (IEnumerable)content;
+
+                int multiIndex = index;
+                foreach (object c in enumerable)
+                {
+                    AddInternal(multiIndex, c, skipParentCheck);
+                    multiIndex++;
+                }
+            }
+            else
+            {
+                JToken item = CreateFromContent(content);
+
+                InsertItem(index, item, skipParentCheck);
+            }
+        }
+
+        internal JToken CreateFromContent(object content)
+        {
+            if (content is JToken)
+                return (JToken)content;
+
+            return new JValue(content);
+        }
+
+        /// <summary>
+        /// Creates an <see cref="JsonWriter"/> that can be used to add tokens to the <see cref="JToken"/>.
+        /// </summary>
+        /// <returns>An <see cref="JsonWriter"/> that is ready to have content written to it.</returns>
+        public JsonWriter CreateWriter()
+        {
+            return new JTokenWriter(this);
+        }
+
+        /// <summary>
+        /// Replaces the children nodes of this token with the specified content.
+        /// </summary>
+        /// <param name="content">The content.</param>
+        public void ReplaceAll(object content)
+        {
+            ClearItems();
+            Add(content);
+        }
+
+        /// <summary>
+        /// Removes the child nodes from this token.
+        /// </summary>
+        public void RemoveAll()
+        {
+            ClearItems();
+        }
+
+        internal void ReadTokenFrom(JsonReader reader)
+        {
+            int startDepth = reader.Depth;
+
+            if (!reader.Read())
+                throw JsonReaderException.Create(reader, "Error reading {0} from JsonReader.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
+
+            ReadContentFrom(reader);
+
+            int endDepth = reader.Depth;
+
+            if (endDepth > startDepth)
+                throw JsonReaderException.Create(reader, "Unexpected end of content while loading {0}.".FormatWith(CultureInfo.InvariantCulture, GetType().Name));
+        }
+
+        internal void ReadContentFrom(JsonReader r)
+        {
+            ValidationUtils.ArgumentNotNull(r, "r");
+            IJsonLineInfo lineInfo = r as IJsonLineInfo;
+
+            JContainer parent = this;
+
+            do
+            {
+                if (parent is JProperty && ((JProperty)parent).Value != null)
+                {
+                    if (parent == this)
+                        return;
+
+                    parent = parent.Parent;
+                }
+
+                switch (r.TokenType)
+                {
+                    case JsonToken.None:
+                        // new reader. move to actual content
+                        break;
+                    case JsonToken.StartArray:
+                        JArray a = new JArray();
+                        a.SetLineInfo(lineInfo);
+                        parent.Add(a);
+                        parent = a;
+                        break;
+
+                    case JsonToken.EndArray:
+                        if (parent == this)
+                            return;
+
+                        parent = parent.Parent;
+                        break;
+                    case JsonToken.StartObject:
+                        JObject o = new JObject();
+                        o.SetLineInfo(lineInfo);
+                        parent.Add(o);
+                        parent = o;
+                        break;
+                    case JsonToken.EndObject:
+                        if (parent == this)
+                            return;
+
+                        parent = parent.Parent;
+                        break;
+                    case JsonToken.StartConstructor:
+                        JConstructor constructor = new JConstructor(r.Value.ToString());
+                        constructor.SetLineInfo(lineInfo);
+                        parent.Add(constructor);
+                        parent = constructor;
+                        break;
+                    case JsonToken.EndConstructor:
+                        if (parent == this)
+                            return;
+
+                        parent = parent.Parent;
+                        break;
+                    case JsonToken.String:
+                    case JsonToken.Integer:
+                    case JsonToken.Float:
+                    case JsonToken.Date:
+                    case JsonToken.Boolean:
+                    case JsonToken.Bytes:
+                        JValue v = new JValue(r.Value);
+                        v.SetLineInfo(lineInfo);
+                        parent.Add(v);
+                        break;
+                    case JsonToken.Comment:
+                        v = JValue.CreateComment(r.Value.ToString());
+                        v.SetLineInfo(lineInfo);
+                        parent.Add(v);
+                        break;
+                    case JsonToken.Null:
+                        v = new JValue(null, JTokenType.Null);
+                        v.SetLineInfo(lineInfo);
+                        parent.Add(v);
+                        break;
+                    case JsonToken.Undefined:
+                        v = new JValue(null, JTokenType.Undefined);
+                        v.SetLineInfo(lineInfo);
+                        parent.Add(v);
+                        break;
+                    case JsonToken.PropertyName:
+                        string propertyName = r.Value.ToString();
+                        JProperty property = new JProperty(propertyName);
+                        property.SetLineInfo(lineInfo);
+                        JObject parentObject = (JObject)parent;
+                        // handle multiple properties with the same name in JSON
+                        JProperty existingPropertyWithName = parentObject.Property(propertyName);
+                        if (existingPropertyWithName == null)
+                            parent.Add(property);
+                        else
+                            existingPropertyWithName.Replace(property);
+                        parent = property;
+                        break;
+                    default:
+                        throw new InvalidOperationException("The JsonReader should not be on a token of type {0}.".FormatWith(CultureInfo.InvariantCulture, r.TokenType));
+                }
+            } while (r.Read());
+        }
+
+        internal int ContentsHashCode()
+        {
+            int hashCode = 0;
+            foreach (JToken item in ChildrenTokens)
+            {
+                hashCode ^= item.GetDeepHashCode();
+            }
+            return hashCode;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        string ITypedList.GetListName(PropertyDescriptor[] listAccessors)
+        {
+            return string.Empty;
+        }
+
+        PropertyDescriptorCollection ITypedList.GetItemProperties(PropertyDescriptor[] listAccessors)
+        {
+            ICustomTypeDescriptor d = First as ICustomTypeDescriptor;
+            if (d != null)
+                return d.GetProperties();
+
+            return null;
+        }
+#endif
+
+        #region IList<JToken> Members
+        int IList<JToken>.IndexOf(JToken item)
+        {
+            return IndexOfItem(item);
+        }
+
+        void IList<JToken>.Insert(int index, JToken item)
+        {
+            InsertItem(index, item, false);
+        }
+
+        void IList<JToken>.RemoveAt(int index)
+        {
+            RemoveItemAt(index);
+        }
+
+        JToken IList<JToken>.this[int index]
+        {
+            get { return GetItem(index); }
+            set { SetItem(index, value); }
+        }
+        #endregion
+
+        #region ICollection<JToken> Members
+        void ICollection<JToken>.Add(JToken item)
+        {
+            Add(item);
+        }
+
+        void ICollection<JToken>.Clear()
+        {
+            ClearItems();
+        }
+
+        bool ICollection<JToken>.Contains(JToken item)
+        {
+            return ContainsItem(item);
+        }
+
+        void ICollection<JToken>.CopyTo(JToken[] array, int arrayIndex)
+        {
+            CopyItemsTo(array, arrayIndex);
+        }
+
+        bool ICollection<JToken>.IsReadOnly
+        {
+            get { return false; }
+        }
+
+        bool ICollection<JToken>.Remove(JToken item)
+        {
+            return RemoveItem(item);
+        }
+        #endregion
+
+        private JToken EnsureValue(object value)
+        {
+            if (value == null)
+                return null;
+
+            if (value is JToken)
+                return (JToken)value;
+
+            throw new ArgumentException("Argument is not a JToken.");
+        }
+
+        #region IList Members
+        int IList.Add(object value)
+        {
+            Add(EnsureValue(value));
+            return Count - 1;
+        }
+
+        void IList.Clear()
+        {
+            ClearItems();
+        }
+
+        bool IList.Contains(object value)
+        {
+            return ContainsItem(EnsureValue(value));
+        }
+
+        int IList.IndexOf(object value)
+        {
+            return IndexOfItem(EnsureValue(value));
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            InsertItem(index, EnsureValue(value), false);
+        }
+
+        bool IList.IsFixedSize
+        {
+            get { return false; }
+        }
+
+        bool IList.IsReadOnly
+        {
+            get { return false; }
+        }
+
+        void IList.Remove(object value)
+        {
+            RemoveItem(EnsureValue(value));
+        }
+
+        void IList.RemoveAt(int index)
+        {
+            RemoveItemAt(index);
+        }
+
+        object IList.this[int index]
+        {
+            get { return GetItem(index); }
+            set { SetItem(index, EnsureValue(value)); }
+        }
+        #endregion
+
+        #region ICollection Members
+        void ICollection.CopyTo(Array array, int index)
+        {
+            CopyItemsTo(array, index);
+        }
+
+        /// <summary>
+        /// Gets the count of child JSON tokens.
+        /// </summary>
+        /// <value>The count of child JSON tokens</value>
+        public int Count
+        {
+            get { return ChildrenTokens.Count; }
+        }
+
+        bool ICollection.IsSynchronized
+        {
+            get { return false; }
+        }
+
+        object ICollection.SyncRoot
+        {
+            get
+            {
+                if (_syncRoot == null)
+                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
+
+                return _syncRoot;
+            }
+        }
+        #endregion
+
+        #region IBindingList Members
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        void IBindingList.AddIndex(PropertyDescriptor property)
+        {
+        }
+
+        object IBindingList.AddNew()
+        {
+            AddingNewEventArgs args = new AddingNewEventArgs();
+            OnAddingNew(args);
+
+            if (args.NewObject == null)
+                throw new JsonException("Could not determine new value to add to '{0}'.".FormatWith(CultureInfo.InvariantCulture, GetType()));
+
+            if (!(args.NewObject is JToken))
+                throw new JsonException("New item to be added to collection must be compatible with {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JToken)));
+
+            JToken newItem = (JToken)args.NewObject;
+            Add(newItem);
+
+            return newItem;
+        }
+
+        bool IBindingList.AllowEdit
+        {
+            get { return true; }
+        }
+
+        bool IBindingList.AllowNew
+        {
+            get { return true; }
+        }
+
+        bool IBindingList.AllowRemove
+        {
+            get { return true; }
+        }
+
+        void IBindingList.ApplySort(PropertyDescriptor property, ListSortDirection direction)
+        {
+            throw new NotSupportedException();
+        }
+
+        int IBindingList.Find(PropertyDescriptor property, object key)
+        {
+            throw new NotSupportedException();
+        }
+
+        bool IBindingList.IsSorted
+        {
+            get { return false; }
+        }
+
+        void IBindingList.RemoveIndex(PropertyDescriptor property)
+        {
+        }
+
+        void IBindingList.RemoveSort()
+        {
+            throw new NotSupportedException();
+        }
+
+        ListSortDirection IBindingList.SortDirection
+        {
+            get { return ListSortDirection.Ascending; }
+        }
+
+        PropertyDescriptor IBindingList.SortProperty
+        {
+            get { return null; }
+        }
+
+        bool IBindingList.SupportsChangeNotification
+        {
+            get { return true; }
+        }
+
+        bool IBindingList.SupportsSearching
+        {
+            get { return false; }
+        }
+
+        bool IBindingList.SupportsSorting
+        {
+            get { return false; }
+        }
+#endif
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JEnumerable.cs b/Newtonsoft.Json/Linq/JEnumerable.cs
new file mode 100644
index 0000000..26973df
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JEnumerable.cs
@@ -0,0 +1,118 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a collection of <see cref="JToken"/> objects.
+    /// </summary>
+    /// <typeparam name="T">The type of token</typeparam>
+    public struct JEnumerable<T> : IJEnumerable<T> where T : JToken
+    {
+        /// <summary>
+        /// An empty collection of <see cref="JToken"/> objects.
+        /// </summary>
+        public static readonly JEnumerable<T> Empty = new JEnumerable<T>(Enumerable.Empty<T>());
+
+        private readonly IEnumerable<T> _enumerable;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JEnumerable{T}"/> struct.
+        /// </summary>
+        /// <param name="enumerable">The enumerable.</param>
+        public JEnumerable(IEnumerable<T> enumerable)
+        {
+            ValidationUtils.ArgumentNotNull(enumerable, "enumerable");
+
+            _enumerable = enumerable;
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+        /// </returns>
+        public IEnumerator<T> GetEnumerator()
+        {
+            return _enumerable.GetEnumerator();
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through a collection.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
+        /// </returns>
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        /// <summary>
+        /// Gets the <see cref="IJEnumerable{JToken}"/> with the specified key.
+        /// </summary>
+        /// <value></value>
+        public IJEnumerable<JToken> this[object key]
+        {
+            get { return new JEnumerable<JToken>(Extensions.Values<T, JToken>(_enumerable, key)); }
+        }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="System.Object"/> is equal to this instance.
+        /// </summary>
+        /// <param name="obj">The <see cref="System.Object"/> to compare with this instance.</param>
+        /// <returns>
+        /// 	<c>true</c> if the specified <see cref="System.Object"/> is equal to this instance; otherwise, <c>false</c>.
+        /// </returns>
+        public override bool Equals(object obj)
+        {
+            if (obj is JEnumerable<T>)
+                return _enumerable.Equals(((JEnumerable<T>)obj)._enumerable);
+
+            return false;
+        }
+
+        /// <summary>
+        /// Returns a hash code for this instance.
+        /// </summary>
+        /// <returns>
+        /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. 
+        /// </returns>
+        public override int GetHashCode()
+        {
+            return _enumerable.GetHashCode();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JObject.cs b/Newtonsoft.Json/Linq/JObject.cs
new file mode 100644
index 0000000..3c5888b
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JObject.cs
@@ -0,0 +1,790 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if !PORTABLE40
+using System.Collections.Specialized;
+#endif
+using System.ComponentModel;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
+using System.IO;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a JSON object.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
+    /// </example>
+    public class JObject : JContainer, IDictionary<string, JToken>, INotifyPropertyChanged
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        , ICustomTypeDescriptor
+#endif
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+        , INotifyPropertyChanging
+#endif
+    {
+        private readonly JPropertyKeyedCollection _properties = new JPropertyKeyedCollection();
+
+        /// <summary>
+        /// Gets the container's children tokens.
+        /// </summary>
+        /// <value>The container's children tokens.</value>
+        protected override IList<JToken> ChildrenTokens
+        {
+            get { return _properties; }
+        }
+
+        /// <summary>
+        /// Occurs when a property value changes.
+        /// </summary>
+        public event PropertyChangedEventHandler PropertyChanged;
+
+#if !(NET20 || NETFX_CORE || PORTABLE || PORTABLE40)
+        /// <summary>
+        /// Occurs when a property value is changing.
+        /// </summary>
+        public event PropertyChangingEventHandler PropertyChanging;
+#endif
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JObject"/> class.
+        /// </summary>
+        public JObject()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JObject"/> class from another <see cref="JObject"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JObject"/> object to copy from.</param>
+        public JObject(JObject other)
+            : base(other)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JObject"/> class with the specified content.
+        /// </summary>
+        /// <param name="content">The contents of the object.</param>
+        public JObject(params object[] content)
+            : this((object)content)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JObject"/> class with the specified content.
+        /// </summary>
+        /// <param name="content">The contents of the object.</param>
+        public JObject(object content)
+        {
+            Add(content);
+        }
+
+        internal override bool DeepEquals(JToken node)
+        {
+            JObject t = node as JObject;
+            if (t == null)
+                return false;
+
+            return _properties.Compare(t._properties);
+        }
+
+        internal override void InsertItem(int index, JToken item, bool skipParentCheck)
+        {
+            // don't add comments to JObject, no name to reference comment by
+            if (item != null && item.Type == JTokenType.Comment)
+                return;
+
+            base.InsertItem(index, item, skipParentCheck);
+        }
+
+        internal override void ValidateToken(JToken o, JToken existing)
+        {
+            ValidationUtils.ArgumentNotNull(o, "o");
+
+            if (o.Type != JTokenType.Property)
+                throw new ArgumentException("Can not add {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, o.GetType(), GetType()));
+
+            JProperty newProperty = (JProperty)o;
+
+            if (existing != null)
+            {
+                JProperty existingProperty = (JProperty)existing;
+
+                if (newProperty.Name == existingProperty.Name)
+                    return;
+            }
+
+            if (_properties.TryGetValue(newProperty.Name, out existing))
+                throw new ArgumentException("Can not add property {0} to {1}. Property with the same name already exists on object.".FormatWith(CultureInfo.InvariantCulture, newProperty.Name, GetType()));
+        }
+
+        internal void InternalPropertyChanged(JProperty childProperty)
+        {
+            OnPropertyChanged(childProperty.Name);
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (_listChanged != null)
+                OnListChanged(new ListChangedEventArgs(ListChangedType.ItemChanged, IndexOfItem(childProperty)));
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_collectionChanged != null)
+                OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, childProperty, childProperty, IndexOfItem(childProperty)));
+#endif
+        }
+
+        internal void InternalPropertyChanging(JProperty childProperty)
+        {
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+            OnPropertyChanging(childProperty.Name);
+#endif
+        }
+
+        internal override JToken CloneToken()
+        {
+            return new JObject(this);
+        }
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public override JTokenType Type
+        {
+            get { return JTokenType.Object; }
+        }
+
+        /// <summary>
+        /// Gets an <see cref="IEnumerable{JProperty}"/> of this object's properties.
+        /// </summary>
+        /// <returns>An <see cref="IEnumerable{JProperty}"/> of this object's properties.</returns>
+        public IEnumerable<JProperty> Properties()
+        {
+            return _properties.Cast<JProperty>();
+        }
+
+        /// <summary>
+        /// Gets a <see cref="JProperty"/> the specified name.
+        /// </summary>
+        /// <param name="name">The property name.</param>
+        /// <returns>A <see cref="JProperty"/> with the specified name or null.</returns>
+        public JProperty Property(string name)
+        {
+            if (name == null)
+                return null;
+
+            JToken property;
+            _properties.TryGetValue(name, out property);
+            return (JProperty)property;
+        }
+
+        /// <summary>
+        /// Gets an <see cref="JEnumerable{JToken}"/> of this object's property values.
+        /// </summary>
+        /// <returns>An <see cref="JEnumerable{JToken}"/> of this object's property values.</returns>
+        public JEnumerable<JToken> PropertyValues()
+        {
+            return new JEnumerable<JToken>(Properties().Select(p => p.Value));
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JToken"/> with the specified key.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> with the specified key.</value>
+        public override JToken this[object key]
+        {
+            get
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                string propertyName = key as string;
+                if (propertyName == null)
+                    throw new ArgumentException("Accessed JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                return this[propertyName];
+            }
+            set
+            {
+                ValidationUtils.ArgumentNotNull(key, "o");
+
+                string propertyName = key as string;
+                if (propertyName == null)
+                    throw new ArgumentException("Set JObject values with invalid key value: {0}. Object property name expected.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.ToString(key)));
+
+                this[propertyName] = value;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
+        /// </summary>
+        /// <value></value>
+        public JToken this[string propertyName]
+        {
+            get
+            {
+                ValidationUtils.ArgumentNotNull(propertyName, "propertyName");
+
+                JProperty property = Property(propertyName);
+
+                return (property != null) ? property.Value : null;
+            }
+            set
+            {
+                JProperty property = Property(propertyName);
+                if (property != null)
+                {
+                    property.Value = value;
+                }
+                else
+                {
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+                    OnPropertyChanging(propertyName);
+#endif
+                    Add(new JProperty(propertyName, value));
+                    OnPropertyChanged(propertyName);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Loads an <see cref="JObject"/> from a <see cref="JsonReader"/>. 
+        /// </summary>
+        /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JObject"/>.</param>
+        /// <returns>A <see cref="JObject"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
+        public new static JObject Load(JsonReader reader)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            if (reader.TokenType == JsonToken.None)
+            {
+                if (!reader.Read())
+                    throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader.");
+            }
+
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                reader.Read();
+            }
+
+            if (reader.TokenType != JsonToken.StartObject)
+            {
+                throw JsonReaderException.Create(reader, "Error reading JObject from JsonReader. Current JsonReader item is not an object: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+
+            JObject o = new JObject();
+            o.SetLineInfo(reader as IJsonLineInfo);
+
+            o.ReadTokenFrom(reader);
+
+            return o;
+        }
+
+        /// <summary>
+        /// Load a <see cref="JObject"/> from a string that contains JSON.
+        /// </summary>
+        /// <param name="json">A <see cref="String"/> that contains JSON.</param>
+        /// <returns>A <see cref="JObject"/> populated from the string that contains JSON.</returns>
+        /// <example>
+        ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\LinqToJsonTests.cs" region="LinqToJsonCreateParse" title="Parsing a JSON Object from Text" />
+        /// </example>
+        public new static JObject Parse(string json)
+        {
+            using (JsonReader reader = new JsonTextReader(new StringReader(json)))
+            {
+                JObject o = Load(reader);
+
+                if (reader.Read() && reader.TokenType != JsonToken.Comment)
+                    throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
+
+                return o;
+            }
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JObject"/> from an object.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JObject"/>.</param>
+        /// <returns>A <see cref="JObject"/> with the values of the specified object</returns>
+        public new static JObject FromObject(object o)
+        {
+            return FromObject(o, JsonSerializer.CreateDefault());
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JArray"/> from an object.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JArray"/>.</param>
+        /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used to read the object.</param>
+        /// <returns>A <see cref="JArray"/> with the values of the specified object</returns>
+        public new static JObject FromObject(object o, JsonSerializer jsonSerializer)
+        {
+            JToken token = FromObjectInternal(o, jsonSerializer);
+
+            if (token != null && token.Type != JTokenType.Object)
+                throw new ArgumentException("Object serialized to {0}. JObject instance expected.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+            return (JObject)token;
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+        {
+            writer.WriteStartObject();
+
+            for (int i = 0; i < _properties.Count; i++)
+            {
+                _properties[i].WriteTo(writer, converters);
+            }
+
+            writer.WriteEndObject();
+        }
+
+        /// <summary>
+        /// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
+        public JToken GetValue(string propertyName)
+        {
+            return GetValue(propertyName, StringComparison.Ordinal);
+        }
+
+        /// <summary>
+        /// Gets the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
+        /// The exact property name will be searched for first and if no matching property is found then
+        /// the <see cref="StringComparison"/> will be used to match a property.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
+        /// <returns>The <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.</returns>
+        public JToken GetValue(string propertyName, StringComparison comparison)
+        {
+            if (propertyName == null)
+                return null;
+
+            // attempt to get value via dictionary first for performance
+            JProperty property = Property(propertyName);
+            if (property != null)
+                return property.Value;
+
+            // test above already uses this comparison so no need to repeat
+            if (comparison != StringComparison.Ordinal)
+            {
+                foreach (JProperty p in _properties)
+                {
+                    if (string.Equals(p.Name, propertyName, comparison))
+                        return p.Value;
+                }
+            }
+
+            return null;
+        }
+
+        /// <summary>
+        /// Tries to get the <see cref="Newtonsoft.Json.Linq.JToken"/> with the specified property name.
+        /// The exact property name will be searched for first and if no matching property is found then
+        /// the <see cref="StringComparison"/> will be used to match a property.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <param name="value">The value.</param>
+        /// <param name="comparison">One of the enumeration values that specifies how the strings will be compared.</param>
+        /// <returns>true if a value was successfully retrieved; otherwise, false.</returns>
+        public bool TryGetValue(string propertyName, StringComparison comparison, out JToken value)
+        {
+            value = GetValue(propertyName, comparison);
+            return (value != null);
+        }
+
+        #region IDictionary<string,JToken> Members
+        /// <summary>
+        /// Adds the specified property name.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <param name="value">The value.</param>
+        public void Add(string propertyName, JToken value)
+        {
+            Add(new JProperty(propertyName, value));
+        }
+
+        bool IDictionary<string, JToken>.ContainsKey(string key)
+        {
+            return _properties.Contains(key);
+        }
+
+        ICollection<string> IDictionary<string, JToken>.Keys
+        {
+            // todo: make order the collection returned match JObject order
+            get { return _properties.Keys; }
+        }
+
+        /// <summary>
+        /// Removes the property with the specified name.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>true if item was successfully removed; otherwise, false.</returns>
+        public bool Remove(string propertyName)
+        {
+            JProperty property = Property(propertyName);
+            if (property == null)
+                return false;
+
+            property.Remove();
+            return true;
+        }
+
+        /// <summary>
+        /// Tries the get value.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <param name="value">The value.</param>
+        /// <returns>true if a value was successfully retrieved; otherwise, false.</returns>
+        public bool TryGetValue(string propertyName, out JToken value)
+        {
+            JProperty property = Property(propertyName);
+            if (property == null)
+            {
+                value = null;
+                return false;
+            }
+
+            value = property.Value;
+            return true;
+        }
+
+        ICollection<JToken> IDictionary<string, JToken>.Values
+        {
+            get
+            {
+                // todo: need to wrap _properties.Values with a collection to get the JProperty value
+                throw new NotImplementedException();
+            }
+        }
+        #endregion
+
+        #region ICollection<KeyValuePair<string,JToken>> Members
+        void ICollection<KeyValuePair<string, JToken>>.Add(KeyValuePair<string, JToken> item)
+        {
+            Add(new JProperty(item.Key, item.Value));
+        }
+
+        void ICollection<KeyValuePair<string, JToken>>.Clear()
+        {
+            RemoveAll();
+        }
+
+        bool ICollection<KeyValuePair<string, JToken>>.Contains(KeyValuePair<string, JToken> item)
+        {
+            JProperty property = Property(item.Key);
+            if (property == null)
+                return false;
+
+            return (property.Value == item.Value);
+        }
+
+        void ICollection<KeyValuePair<string, JToken>>.CopyTo(KeyValuePair<string, JToken>[] array, int arrayIndex)
+        {
+            if (array == null)
+                throw new ArgumentNullException("array");
+            if (arrayIndex < 0)
+                throw new ArgumentOutOfRangeException("arrayIndex", "arrayIndex is less than 0.");
+            if (arrayIndex >= array.Length && arrayIndex != 0)
+                throw new ArgumentException("arrayIndex is equal to or greater than the length of array.");
+            if (Count > array.Length - arrayIndex)
+                throw new ArgumentException("The number of elements in the source JObject is greater than the available space from arrayIndex to the end of the destination array.");
+
+            int index = 0;
+            foreach (JProperty property in _properties)
+            {
+                array[arrayIndex + index] = new KeyValuePair<string, JToken>(property.Name, property.Value);
+                index++;
+            }
+        }
+
+        bool ICollection<KeyValuePair<string, JToken>>.IsReadOnly
+        {
+            get { return false; }
+        }
+
+        bool ICollection<KeyValuePair<string, JToken>>.Remove(KeyValuePair<string, JToken> item)
+        {
+            if (!((ICollection<KeyValuePair<string, JToken>>)this).Contains(item))
+                return false;
+
+            ((IDictionary<string, JToken>)this).Remove(item.Key);
+            return true;
+        }
+        #endregion
+
+        internal override int GetDeepHashCode()
+        {
+            return ContentsHashCode();
+        }
+
+        /// <summary>
+        /// Returns an enumerator that iterates through the collection.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
+        /// </returns>
+        public IEnumerator<KeyValuePair<string, JToken>> GetEnumerator()
+        {
+            foreach (JProperty property in _properties)
+            {
+                yield return new KeyValuePair<string, JToken>(property.Name, property.Value);
+            }
+        }
+
+        /// <summary>
+        /// Raises the <see cref="PropertyChanged"/> event with the provided arguments.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        protected virtual void OnPropertyChanged(string propertyName)
+        {
+            if (PropertyChanged != null)
+                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE || NET20)
+        /// <summary>
+        /// Raises the <see cref="PropertyChanging"/> event with the provided arguments.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        protected virtual void OnPropertyChanging(string propertyName)
+        {
+            if (PropertyChanging != null)
+                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
+        }
+#endif
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        // include custom type descriptor on JObject rather than use a provider because the properties are specific to a type
+
+        #region ICustomTypeDescriptor
+        /// <summary>
+        /// Returns the properties for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the properties for this component instance.
+        /// </returns>
+        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
+        {
+            return ((ICustomTypeDescriptor)this).GetProperties(null);
+        }
+
+        /// <summary>
+        /// Returns the properties for this instance of a component using the attribute array as a filter.
+        /// </summary>
+        /// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
+        /// <returns>
+        /// A <see cref="T:System.ComponentModel.PropertyDescriptorCollection"/> that represents the filtered properties for this component instance.
+        /// </returns>
+        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
+        {
+            PropertyDescriptorCollection descriptors = new PropertyDescriptorCollection(null);
+
+            foreach (KeyValuePair<string, JToken> propertyValue in this)
+            {
+                descriptors.Add(new JPropertyDescriptor(propertyValue.Key));
+            }
+
+            return descriptors;
+        }
+
+        /// <summary>
+        /// Returns a collection of custom attributes for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.ComponentModel.AttributeCollection"/> containing the attributes for this object.
+        /// </returns>
+        AttributeCollection ICustomTypeDescriptor.GetAttributes()
+        {
+            return AttributeCollection.Empty;
+        }
+
+        /// <summary>
+        /// Returns the class name of this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// The class name of the object, or null if the class does not have a name.
+        /// </returns>
+        string ICustomTypeDescriptor.GetClassName()
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Returns the name of this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// The name of the object, or null if the object does not have a name.
+        /// </returns>
+        string ICustomTypeDescriptor.GetComponentName()
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Returns a type converter for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.ComponentModel.TypeConverter"/> that is the converter for this object, or null if there is no <see cref="T:System.ComponentModel.TypeConverter"/> for this object.
+        /// </returns>
+        TypeConverter ICustomTypeDescriptor.GetConverter()
+        {
+            return new TypeConverter();
+        }
+
+        /// <summary>
+        /// Returns the default event for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.ComponentModel.EventDescriptor"/> that represents the default event for this object, or null if this object does not have events.
+        /// </returns>
+        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Returns the default property for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the default property for this object, or null if this object does not have properties.
+        /// </returns>
+        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Returns an editor of the specified type for this instance of a component.
+        /// </summary>
+        /// <param name="editorBaseType">A <see cref="T:System.Type"/> that represents the editor for this object.</param>
+        /// <returns>
+        /// An <see cref="T:System.Object"/> of the specified type that is the editor for this object, or null if the editor cannot be found.
+        /// </returns>
+        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
+        {
+            return null;
+        }
+
+        /// <summary>
+        /// Returns the events for this instance of a component using the specified attribute array as a filter.
+        /// </summary>
+        /// <param name="attributes">An array of type <see cref="T:System.Attribute"/> that is used as a filter.</param>
+        /// <returns>
+        /// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the filtered events for this component instance.
+        /// </returns>
+        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
+        {
+            return EventDescriptorCollection.Empty;
+        }
+
+        /// <summary>
+        /// Returns the events for this instance of a component.
+        /// </summary>
+        /// <returns>
+        /// An <see cref="T:System.ComponentModel.EventDescriptorCollection"/> that represents the events for this component instance.
+        /// </returns>
+        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
+        {
+            return EventDescriptorCollection.Empty;
+        }
+
+        /// <summary>
+        /// Returns an object that contains the property described by the specified property descriptor.
+        /// </summary>
+        /// <param name="pd">A <see cref="T:System.ComponentModel.PropertyDescriptor"/> that represents the property whose owner is to be found.</param>
+        /// <returns>
+        /// An <see cref="T:System.Object"/> that represents the owner of the specified property.
+        /// </returns>
+        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
+        {
+            return null;
+        }
+        #endregion
+
+#endif
+
+#if !(NET35 || NET20 || PORTABLE40)
+        /// <summary>
+        /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+        /// </summary>
+        /// <param name="parameter">The expression tree representation of the runtime value.</param>
+        /// <returns>
+        /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+        /// </returns>
+        protected override DynamicMetaObject GetMetaObject(Expression parameter)
+        {
+            return new DynamicProxyMetaObject<JObject>(parameter, this, new JObjectDynamicProxy(), true);
+        }
+
+        private class JObjectDynamicProxy : DynamicProxy<JObject>
+        {
+            public override bool TryGetMember(JObject instance, GetMemberBinder binder, out object result)
+            {
+                // result can be null
+                result = instance[binder.Name];
+                return true;
+            }
+
+            public override bool TrySetMember(JObject instance, SetMemberBinder binder, object value)
+            {
+                JToken v = value as JToken;
+
+                // this can throw an error if value isn't a valid for a JValue
+                if (v == null)
+                    v = new JValue(value);
+
+                instance[binder.Name] = v;
+                return true;
+            }
+
+            public override IEnumerable<string> GetDynamicMemberNames(JObject instance)
+            {
+                return instance.Properties().Select(p => p.Name);
+            }
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JProperty.cs b/Newtonsoft.Json/Linq/JProperty.cs
new file mode 100644
index 0000000..cb8a7c1
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JProperty.cs
@@ -0,0 +1,258 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a JSON property.
+    /// </summary>
+    public class JProperty : JContainer
+    {
+        private readonly List<JToken> _content = new List<JToken>();
+        private readonly string _name;
+
+        /// <summary>
+        /// Gets the container's children tokens.
+        /// </summary>
+        /// <value>The container's children tokens.</value>
+        protected override IList<JToken> ChildrenTokens
+        {
+            get { return _content; }
+        }
+
+        /// <summary>
+        /// Gets the property name.
+        /// </summary>
+        /// <value>The property name.</value>
+        public string Name
+        {
+            [DebuggerStepThrough]
+            get { return _name; }
+        }
+
+        /// <summary>
+        /// Gets or sets the property value.
+        /// </summary>
+        /// <value>The property value.</value>
+        public JToken Value
+        {
+            [DebuggerStepThrough]
+            get { return (_content.Count > 0) ? _content[0] : null; }
+            set
+            {
+                CheckReentrancy();
+
+                JToken newValue = value ?? new JValue((object)null);
+
+                if (_content.Count == 0)
+                {
+                    InsertItem(0, newValue, false);
+                }
+                else
+                {
+                    SetItem(0, newValue);
+                }
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JProperty"/> class from another <see cref="JProperty"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JProperty"/> object to copy from.</param>
+        public JProperty(JProperty other)
+            : base(other)
+        {
+            _name = other.Name;
+        }
+
+        internal override JToken GetItem(int index)
+        {
+            if (index != 0)
+                throw new ArgumentOutOfRangeException();
+
+            return Value;
+        }
+
+        internal override void SetItem(int index, JToken item)
+        {
+            if (index != 0)
+                throw new ArgumentOutOfRangeException();
+
+            if (IsTokenUnchanged(Value, item))
+                return;
+
+            if (Parent != null)
+                ((JObject)Parent).InternalPropertyChanging(this);
+
+            base.SetItem(0, item);
+
+            if (Parent != null)
+                ((JObject)Parent).InternalPropertyChanged(this);
+        }
+
+        internal override bool RemoveItem(JToken item)
+        {
+            throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+        }
+
+        internal override void RemoveItemAt(int index)
+        {
+            throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+        }
+
+        internal override void InsertItem(int index, JToken item, bool skipParentCheck)
+        {
+            // don't add comments to JProperty
+            if (item != null && item.Type == JTokenType.Comment)
+                return;
+
+            if (Value != null)
+                throw new JsonException("{0} cannot have multiple values.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+
+            base.InsertItem(0, item, false);
+        }
+
+        internal override bool ContainsItem(JToken item)
+        {
+            return (Value == item);
+        }
+
+        internal override void ClearItems()
+        {
+            throw new JsonException("Cannot add or remove items from {0}.".FormatWith(CultureInfo.InvariantCulture, typeof(JProperty)));
+        }
+
+        internal override bool DeepEquals(JToken node)
+        {
+            JProperty t = node as JProperty;
+            return (t != null && _name == t.Name && ContentsEqual(t));
+        }
+
+        internal override JToken CloneToken()
+        {
+            return new JProperty(this);
+        }
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public override JTokenType Type
+        {
+            [DebuggerStepThrough]
+            get { return JTokenType.Property; }
+        }
+
+        internal JProperty(string name)
+        {
+            // called from JTokenWriter
+            ValidationUtils.ArgumentNotNull(name, "name");
+
+            _name = name;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JProperty"/> class.
+        /// </summary>
+        /// <param name="name">The property name.</param>
+        /// <param name="content">The property content.</param>
+        public JProperty(string name, params object[] content)
+            : this(name, (object)content)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JProperty"/> class.
+        /// </summary>
+        /// <param name="name">The property name.</param>
+        /// <param name="content">The property content.</param>
+        public JProperty(string name, object content)
+        {
+            ValidationUtils.ArgumentNotNull(name, "name");
+
+            _name = name;
+
+            Value = IsMultiContent(content)
+                ? new JArray(content)
+                : CreateFromContent(content);
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+        {
+            writer.WritePropertyName(_name);
+
+            JToken value = Value;
+            if (value != null)
+                value.WriteTo(writer, converters);
+            else
+                writer.WriteNull();
+        }
+
+        internal override int GetDeepHashCode()
+        {
+            return _name.GetHashCode() ^ ((Value != null) ? Value.GetDeepHashCode() : 0);
+        }
+
+        /// <summary>
+        /// Loads an <see cref="JProperty"/> from a <see cref="JsonReader"/>. 
+        /// </summary>
+        /// <param name="reader">A <see cref="JsonReader"/> that will be read for the content of the <see cref="JProperty"/>.</param>
+        /// <returns>A <see cref="JProperty"/> that contains the JSON that was read from the specified <see cref="JsonReader"/>.</returns>
+        public new static JProperty Load(JsonReader reader)
+        {
+            if (reader.TokenType == JsonToken.None)
+            {
+                if (!reader.Read())
+                    throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader.");
+            }
+
+            while (reader.TokenType == JsonToken.Comment)
+            {
+                reader.Read();
+            }
+
+            if (reader.TokenType != JsonToken.PropertyName)
+                throw JsonReaderException.Create(reader, "Error reading JProperty from JsonReader. Current JsonReader item is not a property: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+
+            JProperty p = new JProperty((string)reader.Value);
+            p.SetLineInfo(reader as IJsonLineInfo);
+
+            p.ReadTokenFrom(reader);
+
+            return p;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JPropertyDescriptor.cs b/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
new file mode 100644
index 0000000..66bc2d0
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JPropertyDescriptor.cs
@@ -0,0 +1,166 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+using System;
+using System.ComponentModel;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a view of a <see cref="JProperty"/>.
+    /// </summary>
+    public class JPropertyDescriptor : PropertyDescriptor
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JPropertyDescriptor"/> class.
+        /// </summary>
+        /// <param name="name">The name.</param>
+        public JPropertyDescriptor(string name)
+            : base(name, null)
+        {
+        }
+
+        private static JObject CastInstance(object instance)
+        {
+            return (JObject)instance;
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, returns whether resetting an object changes its value.
+        /// </summary>
+        /// <returns>
+        /// true if resetting the component changes its value; otherwise, false.
+        /// </returns>
+        /// <param name="component">The component to test for reset capability. 
+        ///                 </param>
+        public override bool CanResetValue(object component)
+        {
+            return false;
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets the current value of the property on a component.
+        /// </summary>
+        /// <returns>
+        /// The value of a property for a given component.
+        /// </returns>
+        /// <param name="component">The component with the property for which to retrieve the value. 
+        ///                 </param>
+        public override object GetValue(object component)
+        {
+            JToken token = CastInstance(component)[Name];
+
+            return token;
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, resets the value for this property of the component to the default value.
+        /// </summary>
+        /// <param name="component">The component with the property value that is to be reset to the default value. 
+        ///                 </param>
+        public override void ResetValue(object component)
+        {
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, sets the value of the component to a different value.
+        /// </summary>
+        /// <param name="component">The component with the property value that is to be set. 
+        ///                 </param><param name="value">The new value. 
+        ///                 </param>
+        public override void SetValue(object component, object value)
+        {
+            JToken token = (value is JToken) ? (JToken)value : new JValue(value);
+
+            CastInstance(component)[Name] = token;
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted.
+        /// </summary>
+        /// <returns>
+        /// true if the property should be persisted; otherwise, false.
+        /// </returns>
+        /// <param name="component">The component with the property to be examined for persistence. 
+        ///                 </param>
+        public override bool ShouldSerializeValue(object component)
+        {
+            return false;
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets the type of the component this property is bound to.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.Type"/> that represents the type of component this property is bound to. When the <see cref="M:System.ComponentModel.PropertyDescriptor.GetValue(System.Object)"/> or <see cref="M:System.ComponentModel.PropertyDescriptor.SetValue(System.Object,System.Object)"/> methods are invoked, the object specified might be an instance of this type.
+        /// </returns>
+        public override Type ComponentType
+        {
+            get { return typeof(JObject); }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets a value indicating whether this property is read-only.
+        /// </summary>
+        /// <returns>
+        /// true if the property is read-only; otherwise, false.
+        /// </returns>
+        public override bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, gets the type of the property.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.Type"/> that represents the type of the property.
+        /// </returns>
+        public override Type PropertyType
+        {
+            get { return typeof(object); }
+        }
+
+        /// <summary>
+        /// Gets the hash code for the name of the member.
+        /// </summary>
+        /// <value></value>
+        /// <returns>
+        /// The hash code for the name of the member.
+        /// </returns>
+        protected override int NameHashCode
+        {
+            get
+            {
+                // override property to fix up an error in its documentation
+                int nameHashCode = base.NameHashCode;
+                return nameHashCode;
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs b/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs
new file mode 100644
index 0000000..945c6c1
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JPropertyKeyedCollection.cs
@@ -0,0 +1,231 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Newtonsoft.Json.Linq
+{
+    internal class JPropertyKeyedCollection : Collection<JToken>
+    {
+        private static readonly IEqualityComparer<string> Comparer = StringComparer.Ordinal;
+
+        private Dictionary<string, JToken> _dictionary;
+
+        private void AddKey(string key, JToken item)
+        {
+            EnsureDictionary();
+            _dictionary[key] = item;
+        }
+
+        protected void ChangeItemKey(JToken item, string newKey)
+        {
+            if (!ContainsItem(item))
+                throw new ArgumentException("The specified item does not exist in this KeyedCollection.");
+
+            string keyForItem = GetKeyForItem(item);
+            if (!Comparer.Equals(keyForItem, newKey))
+            {
+                if (newKey != null)
+                    AddKey(newKey, item);
+
+                if (keyForItem != null)
+                    RemoveKey(keyForItem);
+            }
+        }
+
+        protected override void ClearItems()
+        {
+            base.ClearItems();
+
+            if (_dictionary != null)
+                _dictionary.Clear();
+        }
+
+        public bool Contains(string key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            if (_dictionary != null)
+                return _dictionary.ContainsKey(key);
+
+            return false;
+        }
+
+        private bool ContainsItem(JToken item)
+        {
+            if (_dictionary == null)
+                return false;
+
+            string key = GetKeyForItem(item);
+            JToken value;
+            return _dictionary.TryGetValue(key, out value);
+        }
+
+        private void EnsureDictionary()
+        {
+            if (_dictionary == null)
+                _dictionary = new Dictionary<string, JToken>(Comparer);
+        }
+
+        private string GetKeyForItem(JToken item)
+        {
+            return ((JProperty)item).Name;
+        }
+
+        protected override void InsertItem(int index, JToken item)
+        {
+            AddKey(GetKeyForItem(item), item);
+            base.InsertItem(index, item);
+        }
+
+        public bool Remove(string key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            if (_dictionary != null)
+                return _dictionary.ContainsKey(key) && Remove(_dictionary[key]);
+
+            return false;
+        }
+
+        protected override void RemoveItem(int index)
+        {
+            string keyForItem = GetKeyForItem(Items[index]);
+            RemoveKey(keyForItem);
+            base.RemoveItem(index);
+        }
+
+        private void RemoveKey(string key)
+        {
+            if (_dictionary != null)
+                _dictionary.Remove(key);
+        }
+
+        protected override void SetItem(int index, JToken item)
+        {
+            string keyForItem = GetKeyForItem(item);
+            string keyAtIndex = GetKeyForItem(Items[index]);
+
+            if (Comparer.Equals(keyAtIndex, keyForItem))
+            {
+                if (_dictionary != null)
+                    _dictionary[keyForItem] = item;
+            }
+            else
+            {
+                AddKey(keyForItem, item);
+
+                if (keyAtIndex != null)
+                    RemoveKey(keyAtIndex);
+            }
+            base.SetItem(index, item);
+        }
+
+        public JToken this[string key]
+        {
+            get
+            {
+                if (key == null)
+                    throw new ArgumentNullException("key");
+
+                if (_dictionary != null)
+                    return _dictionary[key];
+
+                throw new KeyNotFoundException();
+            }
+        }
+
+        public bool TryGetValue(string key, out JToken value)
+        {
+            if (_dictionary == null)
+            {
+                value = null;
+                return false;
+            }
+
+            return _dictionary.TryGetValue(key, out value);
+        }
+
+        public ICollection<string> Keys
+        {
+            get
+            {
+                EnsureDictionary();
+                return _dictionary.Keys;
+            }
+        }
+
+        public ICollection<JToken> Values
+        {
+            get
+            {
+                EnsureDictionary();
+                return _dictionary.Values;
+            }
+        }
+
+        public bool Compare(JPropertyKeyedCollection other)
+        {
+            if (this == other)
+                return true;
+
+            // dictionaries in JavaScript aren't ordered
+            // ignore order when comparing properties
+            Dictionary<string, JToken> d1 = _dictionary;
+            Dictionary<string, JToken> d2 = other._dictionary;
+
+            if (d1 == null && d2 == null)
+                return true;
+
+            if (d1 == null)
+                return (d2.Count == 0);
+
+            if (d2 == null)
+                return (d1.Count == 0);
+
+            if (d1.Count != d2.Count)
+                return false;
+
+            foreach (KeyValuePair<string, JToken> keyAndProperty in d1)
+            {
+                JToken secondValue;
+                if (!d2.TryGetValue(keyAndProperty.Key, out secondValue))
+                    return false;
+
+                JProperty p1 = (JProperty)keyAndProperty.Value;
+                JProperty p2 = (JProperty)secondValue;
+
+                if (!p1.Value.DeepEquals(p2.Value))
+                    return false;
+            }
+
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JRaw.cs b/Newtonsoft.Json/Linq/JRaw.cs
new file mode 100644
index 0000000..da042c6
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JRaw.cs
@@ -0,0 +1,75 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Globalization;
+using System.IO;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a raw JSON string.
+    /// </summary>
+    public class JRaw : JValue
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JRaw"/> class from another <see cref="JRaw"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JRaw"/> object to copy from.</param>
+        public JRaw(JRaw other)
+            : base(other)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JRaw"/> class.
+        /// </summary>
+        /// <param name="rawJson">The raw json.</param>
+        public JRaw(object rawJson)
+            : base(rawJson, JTokenType.Raw)
+        {
+        }
+
+        /// <summary>
+        /// Creates an instance of <see cref="JRaw"/> with the content of the reader's current token.
+        /// </summary>
+        /// <param name="reader">The reader.</param>
+        /// <returns>An instance of <see cref="JRaw"/> with the content of the reader's current token.</returns>
+        public static JRaw Create(JsonReader reader)
+        {
+            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
+            using (JsonTextWriter jsonWriter = new JsonTextWriter(sw))
+            {
+                jsonWriter.WriteToken(reader);
+
+                return new JRaw(sw.ToString());
+            }
+        }
+
+        internal override JToken CloneToken()
+        {
+            return new JRaw(this);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JToken.cs b/Newtonsoft.Json/Linq/JToken.cs
new file mode 100644
index 0000000..f668c13
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JToken.cs
@@ -0,0 +1,2023 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq.JsonPath;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using System.Diagnostics;
+using System.Globalization;
+using System.Collections;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents an abstract JSON token.
+    /// </summary>
+    public abstract class JToken : IJEnumerable<JToken>, IJsonLineInfo
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        , ICloneable
+#endif
+#if !(NET35 || NET20 || PORTABLE40)
+        , IDynamicMetaObjectProvider
+#endif
+    {
+        private JContainer _parent;
+        private JToken _previous;
+        private JToken _next;
+        private static JTokenEqualityComparer _equalityComparer;
+
+        private int? _lineNumber;
+        private int? _linePosition;
+
+        private static readonly JTokenType[] BooleanTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean };
+        private static readonly JTokenType[] NumberTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean };
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+        private static readonly JTokenType[] BigIntegerTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes };
+#endif
+        private static readonly JTokenType[] StringTypes = new[] { JTokenType.Date, JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Boolean, JTokenType.Bytes, JTokenType.Guid, JTokenType.TimeSpan, JTokenType.Uri };
+        private static readonly JTokenType[] GuidTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Guid, JTokenType.Bytes };
+        private static readonly JTokenType[] TimeSpanTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.TimeSpan };
+        private static readonly JTokenType[] UriTypes = new[] { JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Uri };
+        private static readonly JTokenType[] CharTypes = new[] { JTokenType.Integer, JTokenType.Float, JTokenType.String, JTokenType.Comment, JTokenType.Raw };
+        private static readonly JTokenType[] DateTimeTypes = new[] { JTokenType.Date, JTokenType.String, JTokenType.Comment, JTokenType.Raw };
+        private static readonly JTokenType[] BytesTypes = new[] { JTokenType.Bytes, JTokenType.String, JTokenType.Comment, JTokenType.Raw, JTokenType.Integer };
+
+        /// <summary>
+        /// Gets a comparer that can compare two tokens for value equality.
+        /// </summary>
+        /// <value>A <see cref="JTokenEqualityComparer"/> that can compare two nodes for value equality.</value>
+        public static JTokenEqualityComparer EqualityComparer
+        {
+            get
+            {
+                if (_equalityComparer == null)
+                    _equalityComparer = new JTokenEqualityComparer();
+
+                return _equalityComparer;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the parent.
+        /// </summary>
+        /// <value>The parent.</value>
+        public JContainer Parent
+        {
+            [DebuggerStepThrough]
+            get { return _parent; }
+            internal set { _parent = value; }
+        }
+
+        /// <summary>
+        /// Gets the root <see cref="JToken"/> of this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The root <see cref="JToken"/> of this <see cref="JToken"/>.</value>
+        public JToken Root
+        {
+            get
+            {
+                JContainer parent = Parent;
+                if (parent == null)
+                    return this;
+
+                while (parent.Parent != null)
+                {
+                    parent = parent.Parent;
+                }
+
+                return parent;
+            }
+        }
+
+        internal abstract JToken CloneToken();
+        internal abstract bool DeepEquals(JToken node);
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public abstract JTokenType Type { get; }
+
+        /// <summary>
+        /// Gets a value indicating whether this token has child tokens.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this token has child values; otherwise, <c>false</c>.
+        /// </value>
+        public abstract bool HasValues { get; }
+
+        /// <summary>
+        /// Compares the values of two tokens, including the values of all descendant tokens.
+        /// </summary>
+        /// <param name="t1">The first <see cref="JToken"/> to compare.</param>
+        /// <param name="t2">The second <see cref="JToken"/> to compare.</param>
+        /// <returns>true if the tokens are equal; otherwise false.</returns>
+        public static bool DeepEquals(JToken t1, JToken t2)
+        {
+            return (t1 == t2 || (t1 != null && t2 != null && t1.DeepEquals(t2)));
+        }
+
+        /// <summary>
+        /// Gets the next sibling token of this node.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> that contains the next sibling token.</value>
+        public JToken Next
+        {
+            get { return _next; }
+            internal set { _next = value; }
+        }
+
+        /// <summary>
+        /// Gets the previous sibling token of this node.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> that contains the previous sibling token.</value>
+        public JToken Previous
+        {
+            get { return _previous; }
+            internal set { _previous = value; }
+        }
+
+        /// <summary>
+        /// Gets the path of the JSON token. 
+        /// </summary>
+        public string Path
+        {
+            get
+            {
+                if (Parent == null)
+                    return string.Empty;
+
+                IList<JToken> ancestors = Ancestors().Reverse().ToList();
+                ancestors.Add(this);
+
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < ancestors.Count; i++)
+                {
+                    JToken current = ancestors[i];
+                    JToken next = null;
+                    if (i + 1 < ancestors.Count)
+                        next = ancestors[i + 1];
+                    else if (ancestors[i].Type == JTokenType.Property)
+                        next = ancestors[i];
+
+                    if (next != null)
+                    {
+                        switch (current.Type)
+                        {
+                            case JTokenType.Property:
+                                JProperty property = (JProperty)current;
+
+                                if (sb.Length > 0)
+                                    sb.Append(".");
+
+                                sb.Append(property.Name);
+                                break;
+                            case JTokenType.Array:
+                            case JTokenType.Constructor:
+                                int index = ((IList<JToken>)current).IndexOf(next);
+
+                                sb.Append("[");
+                                sb.Append(index);
+                                sb.Append("]");
+                                break;
+                        }
+                    }
+                }
+
+                return sb.ToString();
+            }
+        }
+
+        internal JToken()
+        {
+        }
+
+        /// <summary>
+        /// Adds the specified content immediately after this token.
+        /// </summary>
+        /// <param name="content">A content object that contains simple content or a collection of content objects to be added after this token.</param>
+        public void AddAfterSelf(object content)
+        {
+            if (_parent == null)
+                throw new InvalidOperationException("The parent is missing.");
+
+            int index = _parent.IndexOfItem(this);
+            _parent.AddInternal(index + 1, content, false);
+        }
+
+        /// <summary>
+        /// Adds the specified content immediately before this token.
+        /// </summary>
+        /// <param name="content">A content object that contains simple content or a collection of content objects to be added before this token.</param>
+        public void AddBeforeSelf(object content)
+        {
+            if (_parent == null)
+                throw new InvalidOperationException("The parent is missing.");
+
+            int index = _parent.IndexOfItem(this);
+            _parent.AddInternal(index, content, false);
+        }
+
+        /// <summary>
+        /// Returns a collection of the ancestor tokens of this token.
+        /// </summary>
+        /// <returns>A collection of the ancestor tokens of this token.</returns>
+        public IEnumerable<JToken> Ancestors()
+        {
+            for (JToken parent = Parent; parent != null; parent = parent.Parent)
+            {
+                yield return parent;
+            }
+        }
+
+        /// <summary>
+        /// Returns a collection of the sibling tokens after this token, in document order.
+        /// </summary>
+        /// <returns>A collection of the sibling tokens after this tokens, in document order.</returns>
+        public IEnumerable<JToken> AfterSelf()
+        {
+            if (Parent == null)
+                yield break;
+
+            for (JToken o = Next; o != null; o = o.Next)
+            {
+                yield return o;
+            }
+        }
+
+        /// <summary>
+        /// Returns a collection of the sibling tokens before this token, in document order.
+        /// </summary>
+        /// <returns>A collection of the sibling tokens before this token, in document order.</returns>
+        public IEnumerable<JToken> BeforeSelf()
+        {
+            for (JToken o = Parent.First; o != this; o = o.Next)
+            {
+                yield return o;
+            }
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JToken"/> with the specified key.
+        /// </summary>
+        /// <value>The <see cref="JToken"/> with the specified key.</value>
+        public virtual JToken this[object key]
+        {
+            get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
+            set { throw new InvalidOperationException("Cannot set child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JToken"/> with the specified key converted to the specified type.
+        /// </summary>
+        /// <typeparam name="T">The type to convert the token to.</typeparam>
+        /// <param name="key">The token key.</param>
+        /// <returns>The converted token value.</returns>
+        public virtual T Value<T>(object key)
+        {
+            JToken token = this[key];
+
+            // null check to fix MonoTouch issue - https://github.com/dolbz/Newtonsoft.Json/commit/a24e3062846b30ee505f3271ac08862bb471b822
+            return token == null ? default(T) : Extensions.Convert<JToken, T>(token);
+        }
+
+        /// <summary>
+        /// Get the first child token of this token.
+        /// </summary>
+        /// <value>A <see cref="JToken"/> containing the first child token of the <see cref="JToken"/>.</value>
+        public virtual JToken First
+        {
+            get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
+        }
+
+        /// <summary>
+        /// Get the last child token of this token.
+        /// </summary>
+        /// <value>A <see cref="JToken"/> containing the last child token of the <see cref="JToken"/>.</value>
+        public virtual JToken Last
+        {
+            get { throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType())); }
+        }
+
+        /// <summary>
+        /// Returns a collection of the child tokens of this token, in document order.
+        /// </summary>
+        /// <returns>An <see cref="IEnumerable{T}"/> of <see cref="JToken"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
+        public virtual JEnumerable<JToken> Children()
+        {
+            return JEnumerable<JToken>.Empty;
+        }
+
+        /// <summary>
+        /// Returns a collection of the child tokens of this token, in document order, filtered by the specified type.
+        /// </summary>
+        /// <typeparam name="T">The type to filter the child tokens on.</typeparam>
+        /// <returns>A <see cref="JEnumerable{T}"/> containing the child tokens of this <see cref="JToken"/>, in document order.</returns>
+        public JEnumerable<T> Children<T>() where T : JToken
+        {
+            return new JEnumerable<T>(Children().OfType<T>());
+        }
+
+        /// <summary>
+        /// Returns a collection of the child values of this token, in document order.
+        /// </summary>
+        /// <typeparam name="T">The type to convert the values to.</typeparam>
+        /// <returns>A <see cref="IEnumerable{T}"/> containing the child values of this <see cref="JToken"/>, in document order.</returns>
+        public virtual IEnumerable<T> Values<T>()
+        {
+            throw new InvalidOperationException("Cannot access child value on {0}.".FormatWith(CultureInfo.InvariantCulture, GetType()));
+        }
+
+        /// <summary>
+        /// Removes this token from its parent.
+        /// </summary>
+        public void Remove()
+        {
+            if (_parent == null)
+                throw new InvalidOperationException("The parent is missing.");
+
+            _parent.RemoveItem(this);
+        }
+
+        /// <summary>
+        /// Replaces this token with the specified token.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public void Replace(JToken value)
+        {
+            if (_parent == null)
+                throw new InvalidOperationException("The parent is missing.");
+
+            _parent.ReplaceItem(this, value);
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public abstract void WriteTo(JsonWriter writer, params JsonConverter[] converters);
+
+        /// <summary>
+        /// Returns the indented JSON for this token.
+        /// </summary>
+        /// <returns>
+        /// The indented JSON for this token.
+        /// </returns>
+        public override string ToString()
+        {
+            return ToString(Formatting.Indented);
+        }
+
+        /// <summary>
+        /// Returns the JSON for this token using the given formatting and converters.
+        /// </summary>
+        /// <param name="formatting">Indicates how the output is formatted.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        /// <returns>The JSON for this token using the given formatting and converters.</returns>
+        public string ToString(Formatting formatting, params JsonConverter[] converters)
+        {
+            using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
+            {
+                JsonTextWriter jw = new JsonTextWriter(sw);
+                jw.Formatting = formatting;
+
+                WriteTo(jw, converters);
+
+                return sw.ToString();
+            }
+        }
+
+        private static JValue EnsureValue(JToken value)
+        {
+            if (value == null)
+                throw new ArgumentNullException("value");
+
+            if (value is JProperty)
+                value = ((JProperty)value).Value;
+
+            JValue v = value as JValue;
+
+            return v;
+        }
+
+        private static string GetType(JToken token)
+        {
+            ValidationUtils.ArgumentNotNull(token, "token");
+
+            if (token is JProperty)
+                token = ((JProperty)token).Value;
+
+            return token.Type.ToString();
+        }
+
+        private static bool ValidateToken(JToken o, JTokenType[] validTypes, bool nullable)
+        {
+            return (Array.IndexOf(validTypes, o.Type) != -1) || (nullable && (o.Type == JTokenType.Null || o.Type == JTokenType.Undefined));
+        }
+
+        #region Cast from operators
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Boolean"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator bool(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, BooleanTypes, false))
+                throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return Convert.ToBoolean((int)(BigInteger)v.Value);
+#endif
+
+            return Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.DateTimeOffset"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator DateTimeOffset(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, DateTimeTypes, false))
+                throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value is DateTimeOffset)
+                return (DateTimeOffset)v.Value;
+            if (v.Value is string)
+                return DateTimeOffset.Parse((string)v.Value, CultureInfo.InvariantCulture);
+            return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture));
+        }
+#endif
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Boolean}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator bool?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, BooleanTypes, true))
+                throw new ArgumentException("Can not convert {0} to Boolean.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return Convert.ToBoolean((int)(BigInteger)v.Value);
+#endif
+
+            return (v.Value != null) ? (bool?)Convert.ToBoolean(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int64"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator long(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (long)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToInt64(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator DateTime?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, DateTimeTypes, true))
+                throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !NET20
+            if (v.Value is DateTimeOffset)
+                return ((DateTimeOffset)v.Value).DateTime;
+#endif
+
+            return (v.Value != null) ? (DateTime?)Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+#if !NET20
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator DateTimeOffset?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, DateTimeTypes, true))
+                throw new ArgumentException("Can not convert {0} to DateTimeOffset.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+            if (v.Value is DateTimeOffset)
+                return (DateTimeOffset?)v.Value;
+            if (v.Value is string)
+                return DateTimeOffset.Parse((string)v.Value, CultureInfo.InvariantCulture);
+            return new DateTimeOffset(Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture));
+        }
+#endif
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator decimal?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (decimal?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (decimal?)Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Double}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator double?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (double?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (double?)Convert.ToDouble(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Char}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator char?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, CharTypes, true))
+                throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (char?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (char?)Convert.ToChar(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int32"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator int(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (int)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToInt32(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Int16"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator short(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (short)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToInt16(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt16"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator ushort(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (ushort)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Char"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator char(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, CharTypes, false))
+                throw new ArgumentException("Can not convert {0} to Char.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (char)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToChar(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Byte"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator byte(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (byte)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToByte(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.SByte"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator sbyte(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (sbyte)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToSByte(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator int?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Int32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (int?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (int?)Convert.ToInt32(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int16}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator short?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Int16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (short?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (short?)Convert.ToInt16(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt16}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator ushort?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to UInt16.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (ushort?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (ushort?)Convert.ToUInt16(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Byte}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator byte?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Byte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (byte?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (byte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{SByte}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator sbyte?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to SByte.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (sbyte?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (sbyte?)Convert.ToByte(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.DateTime"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator DateTime(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, DateTimeTypes, false))
+                throw new ArgumentException("Can not convert {0} to DateTime.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !NET20
+            if (v.Value is DateTimeOffset)
+                return ((DateTimeOffset)v.Value).DateTime;
+#endif
+
+            return Convert.ToDateTime(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Int64}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator long?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Int64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (long?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (long?)Convert.ToInt64(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{Single}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator float?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (float?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (float?)Convert.ToSingle(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Decimal"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator decimal(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Decimal.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (decimal)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToDecimal(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt32}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator uint?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (uint?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (uint?)Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="Nullable{UInt64}"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator ulong?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, true))
+                throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (ulong?)(BigInteger)v.Value;
+#endif
+
+            return (v.Value != null) ? (ulong?)Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture) : null;
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Double"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator double(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Double.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (double)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToDouble(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Single"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator float(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to Single.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (float)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToSingle(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.String"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator string(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, StringTypes, true))
+                throw new ArgumentException("Can not convert {0} to String.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+            if (v.Value is byte[])
+                return Convert.ToBase64String((byte[])v.Value);
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return ((BigInteger)v.Value).ToString(CultureInfo.InvariantCulture);
+#endif
+
+            return Convert.ToString(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt32"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator uint(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to UInt32.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (uint)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToUInt32(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.UInt64"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        [CLSCompliant(false)]
+        public static explicit operator ulong(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, NumberTypes, false))
+                throw new ArgumentException("Can not convert {0} to UInt64.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return (ulong)(BigInteger)v.Value;
+#endif
+
+            return Convert.ToUInt64(v.Value, CultureInfo.InvariantCulture);
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="T:System.Byte[]"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator byte[](JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, BytesTypes, false))
+                throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value is string)
+                return Convert.FromBase64String(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (v.Value is BigInteger)
+                return ((BigInteger)v.Value).ToByteArray();
+#endif
+
+            if (v.Value is byte[])
+                return (byte[])v.Value;
+
+            throw new ArgumentException("Can not convert {0} to byte array.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Guid"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator Guid(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, GuidTypes, false))
+                throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value is byte[])
+                return new Guid((byte[])v.Value);
+
+            return (v.Value is Guid) ? (Guid)v.Value : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Guid"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator Guid?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, GuidTypes, true))
+                throw new ArgumentException("Can not convert {0} to Guid.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+
+            if (v.Value is byte[])
+                return new Guid((byte[])v.Value);
+
+            return (v.Value is Guid) ? (Guid)v.Value : new Guid(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.TimeSpan"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator TimeSpan(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, TimeSpanTypes, false))
+                throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            return (v.Value is TimeSpan) ? (TimeSpan)v.Value : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.TimeSpan"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator TimeSpan?(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, TimeSpanTypes, true))
+                throw new ArgumentException("Can not convert {0} to TimeSpan.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+
+            return (v.Value is TimeSpan) ? (TimeSpan)v.Value : ConvertUtils.ParseTimeSpan(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+        }
+
+        /// <summary>
+        /// Performs an explicit conversion from <see cref="Newtonsoft.Json.Linq.JToken"/> to <see cref="System.Uri"/>.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>The result of the conversion.</returns>
+        public static explicit operator Uri(JToken value)
+        {
+            if (value == null)
+                return null;
+
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, UriTypes, true))
+                throw new ArgumentException("Can not convert {0} to Uri.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+
+            return (v.Value is Uri) ? (Uri)v.Value : new Uri(Convert.ToString(v.Value, CultureInfo.InvariantCulture));
+        }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+        private static BigInteger ToBigInteger(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, BigIntegerTypes, false))
+                throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            return ConvertUtils.ToBigInteger(v.Value);
+        }
+
+        private static BigInteger? ToBigIntegerNullable(JToken value)
+        {
+            JValue v = EnsureValue(value);
+            if (v == null || !ValidateToken(v, BigIntegerTypes, true))
+                throw new ArgumentException("Can not convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, GetType(value)));
+
+            if (v.Value == null)
+                return null;
+
+            return ConvertUtils.ToBigInteger(v.Value);
+        }
+#endif
+        #endregion
+
+        #region Cast to operators
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Boolean"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(bool value)
+        {
+            return new JValue(value);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="DateTimeOffset"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(DateTimeOffset value)
+        {
+            return new JValue(value);
+        }
+#endif
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Byte"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(byte value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Byte}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(byte? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="SByte"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(sbyte value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{SByte}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(sbyte? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Boolean}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(bool? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Int64}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(long value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{DateTime}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(DateTime? value)
+        {
+            return new JValue(value);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{DateTimeOffset}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(DateTimeOffset? value)
+        {
+            return new JValue(value);
+        }
+#endif
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Decimal}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(decimal? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Double}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(double? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Int16"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(short value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="UInt16"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(ushort value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Int32"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(int value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Int32}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(int? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="DateTime"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(DateTime value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Int64}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(long? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Single}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(float? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Decimal"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(decimal value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Int16}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(short? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{UInt16}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(ushort? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{UInt32}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(uint? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{UInt64}"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(ulong? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Double"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(double value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Single"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(float value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="String"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(string value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="UInt32"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(uint value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="UInt64"/> to <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        [CLSCompliant(false)]
+        public static implicit operator JToken(ulong value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="T:System.Byte[]"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(byte[] value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="T:System.Uri"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(Uri value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="T:System.TimeSpan"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(TimeSpan value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{TimeSpan}"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(TimeSpan? value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="T:System.Guid"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(Guid value)
+        {
+            return new JValue(value);
+        }
+
+        /// <summary>
+        /// Performs an implicit conversion from <see cref="Nullable{Guid}"/> to <see cref="Newtonsoft.Json.Linq.JToken"/>.
+        /// </summary>
+        /// <param name="value">The value to create a <see cref="JValue"/> from.</param>
+        /// <returns>The <see cref="JValue"/> initialized with the specified value.</returns>
+        public static implicit operator JToken(Guid? value)
+        {
+            return new JValue(value);
+        }
+        #endregion
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return ((IEnumerable<JToken>)this).GetEnumerator();
+        }
+
+        IEnumerator<JToken> IEnumerable<JToken>.GetEnumerator()
+        {
+            return Children().GetEnumerator();
+        }
+
+        internal abstract int GetDeepHashCode();
+
+        IJEnumerable<JToken> IJEnumerable<JToken>.this[object key]
+        {
+            get { return this[key]; }
+        }
+
+        /// <summary>
+        /// Creates an <see cref="JsonReader"/> for this token.
+        /// </summary>
+        /// <returns>An <see cref="JsonReader"/> that can be used to read this token and its descendants.</returns>
+        public JsonReader CreateReader()
+        {
+            return new JTokenReader(this, Path);
+        }
+
+        internal static JToken FromObjectInternal(object o, JsonSerializer jsonSerializer)
+        {
+            ValidationUtils.ArgumentNotNull(o, "o");
+            ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer");
+
+            JToken token;
+            using (JTokenWriter jsonWriter = new JTokenWriter())
+            {
+                jsonSerializer.Serialize(jsonWriter, o);
+                token = jsonWriter.Token;
+            }
+
+            return token;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JToken"/> from an object.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
+        /// <returns>A <see cref="JToken"/> with the value of the specified object</returns>
+        public static JToken FromObject(object o)
+        {
+            return FromObjectInternal(o, JsonSerializer.CreateDefault());
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JToken"/> from an object using the specified <see cref="JsonSerializer"/>.
+        /// </summary>
+        /// <param name="o">The object that will be used to create <see cref="JToken"/>.</param>
+        /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when reading the object.</param>
+        /// <returns>A <see cref="JToken"/> with the value of the specified object</returns>
+        public static JToken FromObject(object o, JsonSerializer jsonSerializer)
+        {
+            return FromObjectInternal(o, jsonSerializer);
+        }
+
+        /// <summary>
+        /// Creates the specified .NET type from the <see cref="JToken"/>.
+        /// </summary>
+        /// <typeparam name="T">The object type that the token will be deserialized to.</typeparam>
+        /// <returns>The new object created from the JSON value.</returns>
+        public T ToObject<T>()
+        {
+            return (T)ToObject(typeof(T));
+        }
+
+        /// <summary>
+        /// Creates the specified .NET type from the <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="objectType">The object type that the token will be deserialized to.</param>
+        /// <returns>The new object created from the JSON value.</returns>
+        public object ToObject(Type objectType)
+        {
+            if (JsonConvert.DefaultSettings == null)
+            {
+                PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(objectType);
+
+                switch (typeCode)
+                {
+                    case PrimitiveTypeCode.BooleanNullable:
+                        return (bool?)this;
+                    case PrimitiveTypeCode.Boolean:
+                        return (bool)this;
+                    case PrimitiveTypeCode.CharNullable:
+                        return (char?)this;
+                    case PrimitiveTypeCode.Char:
+                        return (char)this;
+                    case PrimitiveTypeCode.SByte:
+                        return (sbyte?)this;
+                    case PrimitiveTypeCode.SByteNullable:
+                        return (sbyte)this;
+                    case PrimitiveTypeCode.ByteNullable:
+                        return (byte?)this;
+                    case PrimitiveTypeCode.Byte:
+                        return (byte)this;
+                    case PrimitiveTypeCode.Int16Nullable:
+                        return (short?)this;
+                    case PrimitiveTypeCode.Int16:
+                        return (short)this;
+                    case PrimitiveTypeCode.UInt16Nullable:
+                        return (ushort?)this;
+                    case PrimitiveTypeCode.UInt16:
+                        return (ushort)this;
+                    case PrimitiveTypeCode.Int32Nullable:
+                        return (int?)this;
+                    case PrimitiveTypeCode.Int32:
+                        return (int)this;
+                    case PrimitiveTypeCode.UInt32Nullable:
+                        return (uint?)this;
+                    case PrimitiveTypeCode.UInt32:
+                        return (uint)this;
+                    case PrimitiveTypeCode.Int64Nullable:
+                        return (long?)this;
+                    case PrimitiveTypeCode.Int64:
+                        return (long)this;
+                    case PrimitiveTypeCode.UInt64Nullable:
+                        return (ulong?)this;
+                    case PrimitiveTypeCode.UInt64:
+                        return (ulong)this;
+                    case PrimitiveTypeCode.SingleNullable:
+                        return (float?)this;
+                    case PrimitiveTypeCode.Single:
+                        return (float)this;
+                    case PrimitiveTypeCode.DoubleNullable:
+                        return (double?)this;
+                    case PrimitiveTypeCode.Double:
+                        return (double)this;
+                    case PrimitiveTypeCode.DecimalNullable:
+                        return (decimal?)this;
+                    case PrimitiveTypeCode.Decimal:
+                        return (decimal)this;
+                    case PrimitiveTypeCode.DateTimeNullable:
+                        return (DateTime?)this;
+                    case PrimitiveTypeCode.DateTime:
+                        return (DateTime)this;
+#if !NET20
+                    case PrimitiveTypeCode.DateTimeOffsetNullable:
+                        return (DateTimeOffset?)this;
+                    case PrimitiveTypeCode.DateTimeOffset:
+                        return (DateTimeOffset)this;
+#endif
+                    case PrimitiveTypeCode.String:
+                        return (string)this;
+                    case PrimitiveTypeCode.GuidNullable:
+                        return (Guid?)this;
+                    case PrimitiveTypeCode.Guid:
+                        return (Guid)this;
+                    case PrimitiveTypeCode.Uri:
+                        return (Uri)this;
+                    case PrimitiveTypeCode.TimeSpanNullable:
+                        return (TimeSpan?)this;
+                    case PrimitiveTypeCode.TimeSpan:
+                        return (TimeSpan)this;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                    case PrimitiveTypeCode.BigIntegerNullable:
+                        return ToBigIntegerNullable(this);
+                    case PrimitiveTypeCode.BigInteger:
+                        return ToBigInteger(this);
+#endif
+                }
+            }
+
+            return ToObject(objectType, JsonSerializer.CreateDefault());
+        }
+
+        /// <summary>
+        /// Creates the specified .NET type from the <see cref="JToken"/> using the specified <see cref="JsonSerializer"/>.
+        /// </summary>
+        /// <typeparam name="T">The object type that the token will be deserialized to.</typeparam>
+        /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when creating the object.</param>
+        /// <returns>The new object created from the JSON value.</returns>
+        public T ToObject<T>(JsonSerializer jsonSerializer)
+        {
+            return (T)ToObject(typeof(T), jsonSerializer);
+        }
+
+        /// <summary>
+        /// Creates the specified .NET type from the <see cref="JToken"/> using the specified <see cref="JsonSerializer"/>.
+        /// </summary>
+        /// <param name="objectType">The object type that the token will be deserialized to.</param>
+        /// <param name="jsonSerializer">The <see cref="JsonSerializer"/> that will be used when creating the object.</param>
+        /// <returns>The new object created from the JSON value.</returns>
+        public object ToObject(Type objectType, JsonSerializer jsonSerializer)
+        {
+            ValidationUtils.ArgumentNotNull(jsonSerializer, "jsonSerializer");
+
+            using (JTokenReader jsonReader = new JTokenReader(this))
+            {
+                return jsonSerializer.Deserialize(jsonReader, objectType);
+            }
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">An <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
+        /// <returns>
+        /// An <see cref="JToken"/> that contains the token and its descendant tokens
+        /// that were read from the reader. The runtime type of the token is determined
+        /// by the token type of the first token encountered in the reader.
+        /// </returns>
+        public static JToken ReadFrom(JsonReader reader)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            if (reader.TokenType == JsonToken.None)
+            {
+                if (!reader.Read())
+                    throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader.");
+            }
+
+            if (reader.TokenType == JsonToken.StartObject)
+                return JObject.Load(reader);
+
+            if (reader.TokenType == JsonToken.StartArray)
+                return JArray.Load(reader);
+
+            if (reader.TokenType == JsonToken.PropertyName)
+                return JProperty.Load(reader);
+
+            if (reader.TokenType == JsonToken.StartConstructor)
+                return JConstructor.Load(reader);
+
+            if (!JsonReader.IsStartToken(reader.TokenType))
+                return new JValue(reader.Value);
+
+            throw JsonReaderException.Create(reader, "Error reading JToken from JsonReader. Unexpected token: {0}".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+        }
+
+        /// <summary>
+        /// Load a <see cref="JToken"/> from a string that contains JSON.
+        /// </summary>
+        /// <param name="json">A <see cref="String"/> that contains JSON.</param>
+        /// <returns>A <see cref="JToken"/> populated from the string that contains JSON.</returns>
+        public static JToken Parse(string json)
+        {
+            using (JsonReader reader = new JsonTextReader(new StringReader(json)))
+            {
+                JToken t = Load(reader);
+
+                if (reader.Read() && reader.TokenType != JsonToken.Comment)
+                    throw JsonReaderException.Create(reader, "Additional text found in JSON string after parsing content.");
+
+                return t;
+            }
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JToken"/> from a <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">An <see cref="JsonReader"/> positioned at the token to read into this <see cref="JToken"/>.</param>
+        /// <returns>
+        /// An <see cref="JToken"/> that contains the token and its descendant tokens
+        /// that were read from the reader. The runtime type of the token is determined
+        /// by the token type of the first token encountered in the reader.
+        /// </returns>
+        public static JToken Load(JsonReader reader)
+        {
+            return ReadFrom(reader);
+        }
+
+        internal void SetLineInfo(IJsonLineInfo lineInfo)
+        {
+            if (lineInfo == null || !lineInfo.HasLineInfo())
+                return;
+
+            SetLineInfo(lineInfo.LineNumber, lineInfo.LinePosition);
+        }
+
+        internal void SetLineInfo(int lineNumber, int linePosition)
+        {
+            _lineNumber = lineNumber;
+            _linePosition = linePosition;
+        }
+
+        bool IJsonLineInfo.HasLineInfo()
+        {
+            return (_lineNumber != null && _linePosition != null);
+        }
+
+        int IJsonLineInfo.LineNumber
+        {
+            get { return _lineNumber ?? 0; }
+        }
+
+        int IJsonLineInfo.LinePosition
+        {
+            get { return _linePosition ?? 0; }
+        }
+
+        /// <summary>
+        /// Selects a <see cref="JToken"/> using a JPath expression. Selects the token that matches the object path.
+        /// </summary>
+        /// <param name="path">
+        /// A <see cref="String"/> that contains a JPath expression.
+        /// </param>
+        /// <returns>A <see cref="JToken"/>, or null.</returns>
+        public JToken SelectToken(string path)
+        {
+            return SelectToken(path, false);
+        }
+
+        /// <summary>
+        /// Selects a <see cref="JToken"/> using a JPath expression. Selects the token that matches the object path.
+        /// </summary>
+        /// <param name="path">
+        /// A <see cref="String"/> that contains a JPath expression.
+        /// </param>
+        /// <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.</param>
+        /// <returns>A <see cref="JToken"/>.</returns>
+        public JToken SelectToken(string path, bool errorWhenNoMatch)
+        {
+            JPath p = new JPath(path);
+
+            JToken token = null;
+            foreach (JToken t in p.Evaluate(this, errorWhenNoMatch))
+            {
+                if (token != null)
+                    throw new JsonException("Path returned multiple tokens.");
+
+                token = t;
+            }
+
+            return token;
+        }
+
+        /// <summary>
+        /// Selects a collection of elements using a JPath expression.
+        /// </summary>
+        /// <param name="path">
+        /// A <see cref="String"/> that contains a JPath expression.
+        /// </param>
+        /// <returns>An <see cref="IEnumerable{JToken}"/> that contains the selected elements.</returns>
+        public IEnumerable<JToken> SelectTokens(string path)
+        {
+            return SelectTokens(path, false);
+        }
+
+        /// <summary>
+        /// Selects a collection of elements using a JPath expression.
+        /// </summary>
+        /// <param name="path">
+        /// A <see cref="String"/> that contains a JPath expression.
+        /// </param>
+        /// <param name="errorWhenNoMatch">A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression.</param>
+        /// <returns>An <see cref="IEnumerable{JToken}"/> that contains the selected elements.</returns>
+        public IEnumerable<JToken> SelectTokens(string path, bool errorWhenNoMatch)
+        {
+            JPath p = new JPath(path);
+            return p.Evaluate(this, errorWhenNoMatch);
+        }
+
+#if !(NET35 || NET20 || PORTABLE40)
+        /// <summary>
+        /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+        /// </summary>
+        /// <param name="parameter">The expression tree representation of the runtime value.</param>
+        /// <returns>
+        /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+        /// </returns>
+        protected virtual DynamicMetaObject GetMetaObject(Expression parameter)
+        {
+            return new DynamicProxyMetaObject<JToken>(parameter, this, new DynamicProxy<JToken>(), true);
+        }
+
+        /// <summary>
+        /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+        /// </summary>
+        /// <param name="parameter">The expression tree representation of the runtime value.</param>
+        /// <returns>
+        /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+        /// </returns>
+        DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)
+        {
+            return GetMetaObject(parameter);
+        }
+#endif
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        object ICloneable.Clone()
+        {
+            return DeepClone();
+        }
+#endif
+
+        /// <summary>
+        /// Creates a new instance of the <see cref="JToken"/>. All child tokens are recursively cloned.
+        /// </summary>
+        /// <returns>A new instance of the <see cref="JToken"/>.</returns>
+        public JToken DeepClone()
+        {
+            return CloneToken();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs b/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs
new file mode 100644
index 0000000..285cdd3
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JTokenEqualityComparer.cs
@@ -0,0 +1,62 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Compares tokens to determine whether they are equal.
+    /// </summary>
+    public class JTokenEqualityComparer : IEqualityComparer<JToken>
+    {
+        /// <summary>
+        /// Determines whether the specified objects are equal.
+        /// </summary>
+        /// <param name="x">The first object of type <see cref="JToken"/> to compare.</param>
+        /// <param name="y">The second object of type <see cref="JToken"/> to compare.</param>
+        /// <returns>
+        /// true if the specified objects are equal; otherwise, false.
+        /// </returns>
+        public bool Equals(JToken x, JToken y)
+        {
+            return JToken.DeepEquals(x, y);
+        }
+
+        /// <summary>
+        /// Returns a hash code for the specified object.
+        /// </summary>
+        /// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param>
+        /// <returns>A hash code for the specified object.</returns>
+        /// <exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
+        public int GetHashCode(JToken obj)
+        {
+            if (obj == null)
+                return 0;
+
+            return obj.GetDeepHashCode();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JTokenReader.cs b/Newtonsoft.Json/Linq/JTokenReader.cs
new file mode 100644
index 0000000..9be2bfc
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JTokenReader.cs
@@ -0,0 +1,355 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a reader that provides fast, non-cached, forward-only access to serialized Json data.
+    /// </summary>
+    public class JTokenReader : JsonReader, IJsonLineInfo
+    {
+        private readonly string _initialPath;
+        private readonly JToken _root;
+        private JToken _parent;
+        internal JToken _current;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JTokenReader"/> class.
+        /// </summary>
+        /// <param name="token">The token to read from.</param>
+        public JTokenReader(JToken token)
+        {
+            ValidationUtils.ArgumentNotNull(token, "token");
+
+            _root = token;
+            _current = token;
+        }
+
+        internal JTokenReader(JToken token, string initialPath)
+            : this(token)
+        {
+            _initialPath = initialPath;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="T:Byte[]"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:Byte[]"/> or a null reference if the next JSON token is null. This method will return <c>null</c> at the end of an array.
+        /// </returns>
+        public override byte[] ReadAsBytes()
+        {
+            return ReadAsBytesInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Decimal}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Decimal}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override decimal? ReadAsDecimal()
+        {
+            return ReadAsDecimalInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{Int32}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{Int32}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override int? ReadAsInt32()
+        {
+            return ReadAsInt32Internal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="String"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override string ReadAsString()
+        {
+            return ReadAsStringInternal();
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTime}"/>.
+        /// </summary>
+        /// <returns>A <see cref="String"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTime? ReadAsDateTime()
+        {
+            return ReadAsDateTimeInternal();
+        }
+
+#if !NET20
+        /// <summary>
+        /// Reads the next JSON token from the stream as a <see cref="Nullable{DateTimeOffset}"/>.
+        /// </summary>
+        /// <returns>A <see cref="Nullable{DateTimeOffset}"/>. This method will return <c>null</c> at the end of an array.</returns>
+        public override DateTimeOffset? ReadAsDateTimeOffset()
+        {
+            return ReadAsDateTimeOffsetInternal();
+        }
+#endif
+
+        internal override bool ReadInternal()
+        {
+            if (CurrentState != State.Start)
+            {
+                JContainer container = _current as JContainer;
+                if (container != null && _parent != container)
+                    return ReadInto(container);
+                else
+                    return ReadOver(_current);
+            }
+
+            SetToken(_current);
+            return true;
+        }
+
+        /// <summary>
+        /// Reads the next JSON token from the stream.
+        /// </summary>
+        /// <returns>
+        /// true if the next token was read successfully; false if there are no more tokens to read.
+        /// </returns>
+        public override bool Read()
+        {
+            _readType = ReadType.Read;
+
+            return ReadInternal();
+        }
+
+        private bool ReadOver(JToken t)
+        {
+            if (t == _root)
+                return ReadToEnd();
+
+            JToken next = t.Next;
+            if ((next == null || next == t) || t == t.Parent.Last)
+            {
+                if (t.Parent == null)
+                    return ReadToEnd();
+
+                return SetEnd(t.Parent);
+            }
+            else
+            {
+                _current = next;
+                SetToken(_current);
+                return true;
+            }
+        }
+
+        private bool ReadToEnd()
+        {
+            SetToken(JsonToken.None);
+            return false;
+        }
+
+        private bool IsEndElement
+        {
+            get { return (_current == _parent); }
+        }
+
+        private JsonToken? GetEndToken(JContainer c)
+        {
+            switch (c.Type)
+            {
+                case JTokenType.Object:
+                    return JsonToken.EndObject;
+                case JTokenType.Array:
+                    return JsonToken.EndArray;
+                case JTokenType.Constructor:
+                    return JsonToken.EndConstructor;
+                case JTokenType.Property:
+                    return null;
+                default:
+                    throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", c.Type, "Unexpected JContainer type.");
+            }
+        }
+
+        private bool ReadInto(JContainer c)
+        {
+            JToken firstChild = c.First;
+            if (firstChild == null)
+            {
+                return SetEnd(c);
+            }
+            else
+            {
+                SetToken(firstChild);
+                _current = firstChild;
+                _parent = c;
+                return true;
+            }
+        }
+
+        private bool SetEnd(JContainer c)
+        {
+            JsonToken? endToken = GetEndToken(c);
+            if (endToken != null)
+            {
+                SetToken(endToken.Value);
+                _current = c;
+                _parent = c;
+                return true;
+            }
+            else
+            {
+                return ReadOver(c);
+            }
+        }
+
+        private void SetToken(JToken token)
+        {
+            switch (token.Type)
+            {
+                case JTokenType.Object:
+                    SetToken(JsonToken.StartObject);
+                    break;
+                case JTokenType.Array:
+                    SetToken(JsonToken.StartArray);
+                    break;
+                case JTokenType.Constructor:
+                    SetToken(JsonToken.StartConstructor, ((JConstructor)token).Name);
+                    break;
+                case JTokenType.Property:
+                    SetToken(JsonToken.PropertyName, ((JProperty)token).Name);
+                    break;
+                case JTokenType.Comment:
+                    SetToken(JsonToken.Comment, ((JValue)token).Value);
+                    break;
+                case JTokenType.Integer:
+                    SetToken(JsonToken.Integer, ((JValue)token).Value);
+                    break;
+                case JTokenType.Float:
+                    SetToken(JsonToken.Float, ((JValue)token).Value);
+                    break;
+                case JTokenType.String:
+                    SetToken(JsonToken.String, ((JValue)token).Value);
+                    break;
+                case JTokenType.Boolean:
+                    SetToken(JsonToken.Boolean, ((JValue)token).Value);
+                    break;
+                case JTokenType.Null:
+                    SetToken(JsonToken.Null, ((JValue)token).Value);
+                    break;
+                case JTokenType.Undefined:
+                    SetToken(JsonToken.Undefined, ((JValue)token).Value);
+                    break;
+                case JTokenType.Date:
+                    SetToken(JsonToken.Date, ((JValue)token).Value);
+                    break;
+                case JTokenType.Raw:
+                    SetToken(JsonToken.Raw, ((JValue)token).Value);
+                    break;
+                case JTokenType.Bytes:
+                    SetToken(JsonToken.Bytes, ((JValue)token).Value);
+                    break;
+                case JTokenType.Guid:
+                    SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
+                    break;
+                case JTokenType.Uri:
+                    SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
+                    break;
+                case JTokenType.TimeSpan:
+                    SetToken(JsonToken.String, SafeToString(((JValue)token).Value));
+                    break;
+                default:
+                    throw MiscellaneousUtils.CreateArgumentOutOfRangeException("Type", token.Type, "Unexpected JTokenType.");
+            }
+        }
+
+        private string SafeToString(object value)
+        {
+            return (value != null) ? value.ToString() : null;
+        }
+
+        bool IJsonLineInfo.HasLineInfo()
+        {
+            if (CurrentState == State.Start)
+                return false;
+
+            IJsonLineInfo info = IsEndElement ? null : _current;
+            return (info != null && info.HasLineInfo());
+        }
+
+        int IJsonLineInfo.LineNumber
+        {
+            get
+            {
+                if (CurrentState == State.Start)
+                    return 0;
+
+                IJsonLineInfo info = IsEndElement ? null : _current;
+                if (info != null)
+                    return info.LineNumber;
+
+                return 0;
+            }
+        }
+
+        int IJsonLineInfo.LinePosition
+        {
+            get
+            {
+                if (CurrentState == State.Start)
+                    return 0;
+
+                IJsonLineInfo info = IsEndElement ? null : _current;
+                if (info != null)
+                    return info.LinePosition;
+
+                return 0;
+            }
+        }
+
+        /// <summary>
+        /// Gets the path of the current JSON token. 
+        /// </summary>
+        public override string Path
+        {
+            get
+            {
+                string path = base.Path;
+
+                if (!string.IsNullOrEmpty(_initialPath))
+                {
+                    if (string.IsNullOrEmpty(path))
+                        return _initialPath;
+
+                    if (_initialPath.EndsWith("]", StringComparison.OrdinalIgnoreCase)
+                        || path.StartsWith("[", StringComparison.OrdinalIgnoreCase))
+                        path = _initialPath + path;
+                    else
+                        path = _initialPath + "." + path;
+                }
+
+                return path;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JTokenType.cs b/Newtonsoft.Json/Linq/JTokenType.cs
new file mode 100644
index 0000000..78dfaec
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JTokenType.cs
@@ -0,0 +1,123 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Specifies the type of token.
+    /// </summary>
+    public enum JTokenType
+    {
+        /// <summary>
+        /// No token type has been set.
+        /// </summary>
+        None,
+
+        /// <summary>
+        /// A JSON object.
+        /// </summary>
+        Object,
+
+        /// <summary>
+        /// A JSON array.
+        /// </summary>
+        Array,
+
+        /// <summary>
+        /// A JSON constructor.
+        /// </summary>
+        Constructor,
+
+        /// <summary>
+        /// A JSON object property.
+        /// </summary>
+        Property,
+
+        /// <summary>
+        /// A comment.
+        /// </summary>
+        Comment,
+
+        /// <summary>
+        /// An integer value.
+        /// </summary>
+        Integer,
+
+        /// <summary>
+        /// A float value.
+        /// </summary>
+        Float,
+
+        /// <summary>
+        /// A string value.
+        /// </summary>
+        String,
+
+        /// <summary>
+        /// A boolean value.
+        /// </summary>
+        Boolean,
+
+        /// <summary>
+        /// A null value.
+        /// </summary>
+        Null,
+
+        /// <summary>
+        /// An undefined value.
+        /// </summary>
+        Undefined,
+
+        /// <summary>
+        /// A date value.
+        /// </summary>
+        Date,
+
+        /// <summary>
+        /// A raw JSON value.
+        /// </summary>
+        Raw,
+
+        /// <summary>
+        /// A collection of bytes value.
+        /// </summary>
+        Bytes,
+
+        /// <summary>
+        /// A Guid value.
+        /// </summary>
+        Guid,
+
+        /// <summary>
+        /// A Uri value.
+        /// </summary>
+        Uri,
+
+        /// <summary>
+        /// A TimeSpan value.
+        /// </summary>
+        TimeSpan
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JTokenWriter.cs b/Newtonsoft.Json/Linq/JTokenWriter.cs
new file mode 100644
index 0000000..71e7f0e
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JTokenWriter.cs
@@ -0,0 +1,456 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
+    /// </summary>
+    public class JTokenWriter : JsonWriter
+    {
+        private JContainer _token;
+        private JContainer _parent;
+        // used when writer is writing single value and the value has no containing parent
+        private JValue _value;
+
+        /// <summary>
+        /// Gets the token being writen.
+        /// </summary>
+        /// <value>The token being writen.</value>
+        public JToken Token
+        {
+            get
+            {
+                if (_token != null)
+                    return _token;
+
+                return _value;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JTokenWriter"/> class writing to the given <see cref="JContainer"/>.
+        /// </summary>
+        /// <param name="container">The container being written to.</param>
+        public JTokenWriter(JContainer container)
+        {
+            ValidationUtils.ArgumentNotNull(container, "container");
+
+            _token = container;
+            _parent = container;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JTokenWriter"/> class.
+        /// </summary>
+        public JTokenWriter()
+        {
+        }
+
+        /// <summary>
+        /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
+        /// </summary>
+        public override void Flush()
+        {
+        }
+
+        /// <summary>
+        /// Closes this stream and the underlying stream.
+        /// </summary>
+        public override void Close()
+        {
+            base.Close();
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json object.
+        /// </summary>
+        public override void WriteStartObject()
+        {
+            base.WriteStartObject();
+
+            AddParent(new JObject());
+        }
+
+        private void AddParent(JContainer container)
+        {
+            if (_parent == null)
+                _token = container;
+            else
+                _parent.AddAndSkipParentCheck(container);
+
+            _parent = container;
+        }
+
+        private void RemoveParent()
+        {
+            _parent = _parent.Parent;
+
+            if (_parent != null && _parent.Type == JTokenType.Property)
+                _parent = _parent.Parent;
+        }
+
+        /// <summary>
+        /// Writes the beginning of a Json array.
+        /// </summary>
+        public override void WriteStartArray()
+        {
+            base.WriteStartArray();
+
+            AddParent(new JArray());
+        }
+
+        /// <summary>
+        /// Writes the start of a constructor with the given name.
+        /// </summary>
+        /// <param name="name">The name of the constructor.</param>
+        public override void WriteStartConstructor(string name)
+        {
+            base.WriteStartConstructor(name);
+
+            AddParent(new JConstructor(name));
+        }
+
+        /// <summary>
+        /// Writes the end.
+        /// </summary>
+        /// <param name="token">The token.</param>
+        protected override void WriteEnd(JsonToken token)
+        {
+            RemoveParent();
+        }
+
+        /// <summary>
+        /// Writes the property name of a name/value pair on a Json object.
+        /// </summary>
+        /// <param name="name">The name of the property.</param>
+        public override void WritePropertyName(string name)
+        {
+            base.WritePropertyName(name);
+
+            AddParent(new JProperty(name));
+        }
+
+        private void AddValue(object value, JsonToken token)
+        {
+            AddValue(new JValue(value), token);
+        }
+
+        internal void AddValue(JValue value, JsonToken token)
+        {
+            if (_parent != null)
+            {
+                _parent.Add(value);
+
+                if (_parent.Type == JTokenType.Property)
+                    _parent = _parent.Parent;
+            }
+            else
+            {
+                _value = value ?? new JValue((object)null);
+            }
+        }
+
+        #region WriteValue methods
+        /// <summary>
+        /// Writes a <see cref="Object"/> value.
+        /// An error will raised if the value cannot be written as a single JSON token.
+        /// </summary>
+        /// <param name="value">The <see cref="Object"/> value to write.</param>
+        public override void WriteValue(object value)
+        {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+            if (value is BigInteger)
+            {
+                InternalWriteValue(JsonToken.Integer);
+                AddValue(value, JsonToken.Integer);
+            }
+            else
+#endif
+            {
+                base.WriteValue(value);
+            }
+        }
+
+        /// <summary>
+        /// Writes a null value.
+        /// </summary>
+        public override void WriteNull()
+        {
+            base.WriteNull();
+            AddValue(null, JsonToken.Null);
+        }
+
+        /// <summary>
+        /// Writes an undefined value.
+        /// </summary>
+        public override void WriteUndefined()
+        {
+            base.WriteUndefined();
+            AddValue(null, JsonToken.Undefined);
+        }
+
+        /// <summary>
+        /// Writes raw JSON.
+        /// </summary>
+        /// <param name="json">The raw JSON to write.</param>
+        public override void WriteRaw(string json)
+        {
+            base.WriteRaw(json);
+            AddValue(new JRaw(json), JsonToken.Raw);
+        }
+
+        /// <summary>
+        /// Writes out a comment <code>/*...*/</code> containing the specified text.
+        /// </summary>
+        /// <param name="text">Text to place inside the comment.</param>
+        public override void WriteComment(string text)
+        {
+            base.WriteComment(text);
+            AddValue(JValue.CreateComment(text), JsonToken.Comment);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="String"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="String"/> value to write.</param>
+        public override void WriteValue(string value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int32"/> value to write.</param>
+        public override void WriteValue(int value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt32"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt32"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(uint value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int64"/> value to write.</param>
+        public override void WriteValue(long value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt64"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt64"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ulong value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Single"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Single"/> value to write.</param>
+        public override void WriteValue(float value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Double"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Double"/> value to write.</param>
+        public override void WriteValue(double value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Boolean"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Boolean"/> value to write.</param>
+        public override void WriteValue(bool value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Boolean);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Int16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Int16"/> value to write.</param>
+        public override void WriteValue(short value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="UInt16"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="UInt16"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(ushort value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Char"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Char"/> value to write.</param>
+        public override void WriteValue(char value)
+        {
+            base.WriteValue(value);
+            string s = null;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            s = value.ToString(CultureInfo.InvariantCulture);
+#else
+            s = value.ToString();
+#endif
+            AddValue(s, JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Byte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Byte"/> value to write.</param>
+        public override void WriteValue(byte value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="SByte"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="SByte"/> value to write.</param>
+        [CLSCompliant(false)]
+        public override void WriteValue(sbyte value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Integer);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Decimal"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Decimal"/> value to write.</param>
+        public override void WriteValue(decimal value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Float);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="DateTime"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTime"/> value to write.</param>
+        public override void WriteValue(DateTime value)
+        {
+            base.WriteValue(value);
+            value = DateTimeUtils.EnsureDateTime(value, DateTimeZoneHandling);
+            AddValue(value, JsonToken.Date);
+        }
+
+#if !NET20
+        /// <summary>
+        /// Writes a <see cref="DateTimeOffset"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="DateTimeOffset"/> value to write.</param>
+        public override void WriteValue(DateTimeOffset value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Date);
+        }
+#endif
+
+        /// <summary>
+        /// Writes a <see cref="T:Byte[]"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="T:Byte[]"/> value to write.</param>
+        public override void WriteValue(byte[] value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.Bytes);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="TimeSpan"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="TimeSpan"/> value to write.</param>
+        public override void WriteValue(TimeSpan value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Guid"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Guid"/> value to write.</param>
+        public override void WriteValue(Guid value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.String);
+        }
+
+        /// <summary>
+        /// Writes a <see cref="Uri"/> value.
+        /// </summary>
+        /// <param name="value">The <see cref="Uri"/> value to write.</param>
+        public override void WriteValue(Uri value)
+        {
+            base.WriteValue(value);
+            AddValue(value, JsonToken.String);
+        }
+        #endregion
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JValue.cs b/Newtonsoft.Json/Linq/JValue.cs
new file mode 100644
index 0000000..78bc032
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JValue.cs
@@ -0,0 +1,1037 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+using System.Linq.Expressions;
+#endif
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+
+#endif
+
+namespace Newtonsoft.Json.Linq
+{
+    /// <summary>
+    /// Represents a value in JSON (string, integer, date, etc).
+    /// </summary>
+    public class JValue : JToken, IEquatable<JValue>, IFormattable, IComparable, IComparable<JValue>
+#if !(NETFX_CORE || PORTABLE)
+        , IConvertible
+#endif
+    {
+        private JTokenType _valueType;
+        private object _value;
+
+        internal JValue(object value, JTokenType type)
+        {
+            _value = value;
+            _valueType = type;
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class from another <see cref="JValue"/> object.
+        /// </summary>
+        /// <param name="other">A <see cref="JValue"/> object to copy from.</param>
+        public JValue(JValue other)
+            : this(other.Value, other.Type)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(long value)
+            : this(value, JTokenType.Integer)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(decimal value)
+            : this(value, JTokenType.Float)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(char value)
+            : this(value, JTokenType.String)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        [CLSCompliant(false)]
+        public JValue(ulong value)
+            : this(value, JTokenType.Integer)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(double value)
+            : this(value, JTokenType.Float)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(float value)
+            : this(value, JTokenType.Float)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(DateTime value)
+            : this(value, JTokenType.Date)
+        {
+        }
+
+#if !NET20
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(DateTimeOffset value)
+            : this(value, JTokenType.Date)
+        {
+        }
+#endif
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(bool value)
+            : this(value, JTokenType.Boolean)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(string value)
+            : this(value, JTokenType.String)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(Guid value)
+            : this(value, JTokenType.Guid)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(Uri value)
+            : this(value, (value != null) ? JTokenType.Uri : JTokenType.Null)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(TimeSpan value)
+            : this(value, JTokenType.TimeSpan)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JValue"/> class with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        public JValue(object value)
+            : this(value, GetValueType(null, value))
+        {
+        }
+
+        internal override bool DeepEquals(JToken node)
+        {
+            JValue other = node as JValue;
+            if (other == null)
+                return false;
+            if (other == this)
+                return true;
+
+            return ValuesEquals(this, other);
+        }
+
+        /// <summary>
+        /// Gets a value indicating whether this token has child tokens.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this token has child values; otherwise, <c>false</c>.
+        /// </value>
+        public override bool HasValues
+        {
+            get { return false; }
+        }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+        private static int CompareBigInteger(BigInteger i1, object i2)
+        {
+            int result = i1.CompareTo(ConvertUtils.ToBigInteger(i2));
+
+            if (result != 0)
+                return result;
+
+            // converting a fractional number to a BigInteger will lose the fraction
+            // check for fraction if result is two numbers are equal
+            if (i2 is decimal)
+            {
+                decimal d = (decimal)i2;
+                return (0m).CompareTo(Math.Abs(d - Math.Truncate(d)));
+            }
+            else if (i2 is double || i2 is float)
+            {
+                double d = Convert.ToDouble(i2, CultureInfo.InvariantCulture);
+                return (0d).CompareTo(Math.Abs(d - Math.Truncate(d)));
+            }
+
+            return result;
+        }
+#endif
+
+        internal static int Compare(JTokenType valueType, object objA, object objB)
+        {
+            if (objA == null && objB == null)
+                return 0;
+            if (objA != null && objB == null)
+                return 1;
+            if (objA == null && objB != null)
+                return -1;
+
+            switch (valueType)
+            {
+                case JTokenType.Integer:
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                    if (objA is BigInteger)
+                        return CompareBigInteger((BigInteger)objA, objB);
+                    if (objB is BigInteger)
+                        return -CompareBigInteger((BigInteger)objB, objA);
+#endif
+                    if (objA is ulong || objB is ulong || objA is decimal || objB is decimal)
+                        return Convert.ToDecimal(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToDecimal(objB, CultureInfo.InvariantCulture));
+                    else if (objA is float || objB is float || objA is double || objB is double)
+                        return CompareFloat(objA, objB);
+                    else
+                        return Convert.ToInt64(objA, CultureInfo.InvariantCulture).CompareTo(Convert.ToInt64(objB, CultureInfo.InvariantCulture));
+                case JTokenType.Float:
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                    if (objA is BigInteger)
+                        return CompareBigInteger((BigInteger)objA, objB);
+                    if (objB is BigInteger)
+                        return -CompareBigInteger((BigInteger)objB, objA);
+#endif
+                    return CompareFloat(objA, objB);
+                case JTokenType.Comment:
+                case JTokenType.String:
+                case JTokenType.Raw:
+                    string s1 = Convert.ToString(objA, CultureInfo.InvariantCulture);
+                    string s2 = Convert.ToString(objB, CultureInfo.InvariantCulture);
+
+                    return string.CompareOrdinal(s1, s2);
+                case JTokenType.Boolean:
+                    bool b1 = Convert.ToBoolean(objA, CultureInfo.InvariantCulture);
+                    bool b2 = Convert.ToBoolean(objB, CultureInfo.InvariantCulture);
+
+                    return b1.CompareTo(b2);
+                case JTokenType.Date:
+#if !NET20
+                    if (objA is DateTime)
+                    {
+#endif
+                        DateTime date1 = (DateTime)objA;
+                        DateTime date2;
+
+#if !NET20
+                        if (objB is DateTimeOffset)
+                            date2 = ((DateTimeOffset)objB).DateTime;
+                        else
+#endif
+                            date2 = Convert.ToDateTime(objB, CultureInfo.InvariantCulture);
+
+                        return date1.CompareTo(date2);
+#if !NET20
+                    }
+                    else
+                    {
+                        DateTimeOffset date1 = (DateTimeOffset)objA;
+                        DateTimeOffset date2;
+
+                        if (objB is DateTimeOffset)
+                            date2 = (DateTimeOffset)objB;
+                        else
+                            date2 = new DateTimeOffset(Convert.ToDateTime(objB, CultureInfo.InvariantCulture));
+
+                        return date1.CompareTo(date2);
+                    }
+#endif
+                case JTokenType.Bytes:
+                    if (!(objB is byte[]))
+                        throw new ArgumentException("Object must be of type byte[].");
+
+                    byte[] bytes1 = objA as byte[];
+                    byte[] bytes2 = objB as byte[];
+                    if (bytes1 == null)
+                        return -1;
+                    if (bytes2 == null)
+                        return 1;
+
+                    return MiscellaneousUtils.ByteArrayCompare(bytes1, bytes2);
+                case JTokenType.Guid:
+                    if (!(objB is Guid))
+                        throw new ArgumentException("Object must be of type Guid.");
+
+                    Guid guid1 = (Guid)objA;
+                    Guid guid2 = (Guid)objB;
+
+                    return guid1.CompareTo(guid2);
+                case JTokenType.Uri:
+                    if (!(objB is Uri))
+                        throw new ArgumentException("Object must be of type Uri.");
+
+                    Uri uri1 = (Uri)objA;
+                    Uri uri2 = (Uri)objB;
+
+                    return Comparer<string>.Default.Compare(uri1.ToString(), uri2.ToString());
+                case JTokenType.TimeSpan:
+                    if (!(objB is TimeSpan))
+                        throw new ArgumentException("Object must be of type TimeSpan.");
+
+                    TimeSpan ts1 = (TimeSpan)objA;
+                    TimeSpan ts2 = (TimeSpan)objB;
+
+                    return ts1.CompareTo(ts2);
+                default:
+                    throw MiscellaneousUtils.CreateArgumentOutOfRangeException("valueType", valueType, "Unexpected value type: {0}".FormatWith(CultureInfo.InvariantCulture, valueType));
+            }
+        }
+
+        private static int CompareFloat(object objA, object objB)
+        {
+            double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
+            double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
+
+            // take into account possible floating point errors
+            if (MathUtils.ApproxEquals(d1, d2))
+                return 0;
+
+            return d1.CompareTo(d2);
+        }
+
+#if !(NET35 || NET20 || PORTABLE40)
+        private static bool Operation(ExpressionType operation, object objA, object objB, out object result)
+        {
+            if (objA is string || objB is string)
+            {
+                if (operation == ExpressionType.Add || operation == ExpressionType.AddAssign)
+                {
+                    result = ((objA != null) ? objA.ToString() : null) + ((objB != null) ? objB.ToString() : null);
+                    return true;
+                }
+            }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (objA is BigInteger || objB is BigInteger)
+            {
+                if (objA == null || objB == null)
+                {
+                    result = null;
+                    return true;
+                }
+
+                // not that this will lose the fraction
+                // BigInteger doesn't have operators with non-integer types
+                BigInteger i1 = ConvertUtils.ToBigInteger(objA);
+                BigInteger i2 = ConvertUtils.ToBigInteger(objB);
+
+                switch (operation)
+                {
+                    case ExpressionType.Add:
+                    case ExpressionType.AddAssign:
+                        result = i1 + i2;
+                        return true;
+                    case ExpressionType.Subtract:
+                    case ExpressionType.SubtractAssign:
+                        result = i1 - i2;
+                        return true;
+                    case ExpressionType.Multiply:
+                    case ExpressionType.MultiplyAssign:
+                        result = i1 * i2;
+                        return true;
+                    case ExpressionType.Divide:
+                    case ExpressionType.DivideAssign:
+                        result = i1 / i2;
+                        return true;
+                }
+            }
+            else
+#endif
+                if (objA is ulong || objB is ulong || objA is decimal || objB is decimal)
+                {
+                    if (objA == null || objB == null)
+                    {
+                        result = null;
+                        return true;
+                    }
+
+                    decimal d1 = Convert.ToDecimal(objA, CultureInfo.InvariantCulture);
+                    decimal d2 = Convert.ToDecimal(objB, CultureInfo.InvariantCulture);
+
+                    switch (operation)
+                    {
+                        case ExpressionType.Add:
+                        case ExpressionType.AddAssign:
+                            result = d1 + d2;
+                            return true;
+                        case ExpressionType.Subtract:
+                        case ExpressionType.SubtractAssign:
+                            result = d1 - d2;
+                            return true;
+                        case ExpressionType.Multiply:
+                        case ExpressionType.MultiplyAssign:
+                            result = d1 * d2;
+                            return true;
+                        case ExpressionType.Divide:
+                        case ExpressionType.DivideAssign:
+                            result = d1 / d2;
+                            return true;
+                    }
+                }
+                else if (objA is float || objB is float || objA is double || objB is double)
+                {
+                    if (objA == null || objB == null)
+                    {
+                        result = null;
+                        return true;
+                    }
+
+                    double d1 = Convert.ToDouble(objA, CultureInfo.InvariantCulture);
+                    double d2 = Convert.ToDouble(objB, CultureInfo.InvariantCulture);
+
+                    switch (operation)
+                    {
+                        case ExpressionType.Add:
+                        case ExpressionType.AddAssign:
+                            result = d1 + d2;
+                            return true;
+                        case ExpressionType.Subtract:
+                        case ExpressionType.SubtractAssign:
+                            result = d1 - d2;
+                            return true;
+                        case ExpressionType.Multiply:
+                        case ExpressionType.MultiplyAssign:
+                            result = d1 * d2;
+                            return true;
+                        case ExpressionType.Divide:
+                        case ExpressionType.DivideAssign:
+                            result = d1 / d2;
+                            return true;
+                    }
+                }
+                else if (objA is int || objA is uint || objA is long || objA is short || objA is ushort || objA is sbyte || objA is byte ||
+                         objB is int || objB is uint || objB is long || objB is short || objB is ushort || objB is sbyte || objB is byte)
+                {
+                    if (objA == null || objB == null)
+                    {
+                        result = null;
+                        return true;
+                    }
+
+                    long l1 = Convert.ToInt64(objA, CultureInfo.InvariantCulture);
+                    long l2 = Convert.ToInt64(objB, CultureInfo.InvariantCulture);
+
+                    switch (operation)
+                    {
+                        case ExpressionType.Add:
+                        case ExpressionType.AddAssign:
+                            result = l1 + l2;
+                            return true;
+                        case ExpressionType.Subtract:
+                        case ExpressionType.SubtractAssign:
+                            result = l1 - l2;
+                            return true;
+                        case ExpressionType.Multiply:
+                        case ExpressionType.MultiplyAssign:
+                            result = l1 * l2;
+                            return true;
+                        case ExpressionType.Divide:
+                        case ExpressionType.DivideAssign:
+                            result = l1 / l2;
+                            return true;
+                    }
+                }
+
+            result = null;
+            return false;
+        }
+#endif
+
+        internal override JToken CloneToken()
+        {
+            return new JValue(this);
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JValue"/> comment with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>A <see cref="JValue"/> comment with the given value.</returns>
+        public static JValue CreateComment(string value)
+        {
+            return new JValue(value, JTokenType.Comment);
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JValue"/> string with the given value.
+        /// </summary>
+        /// <param name="value">The value.</param>
+        /// <returns>A <see cref="JValue"/> string with the given value.</returns>
+        public static JValue CreateString(string value)
+        {
+            return new JValue(value, JTokenType.String);
+        }
+
+        private static JTokenType GetValueType(JTokenType? current, object value)
+        {
+            if (value == null)
+                return JTokenType.Null;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            else if (value == DBNull.Value)
+                return JTokenType.Null;
+#endif
+            else if (value is string)
+                return GetStringValueType(current);
+            else if (value is long || value is int || value is short || value is sbyte
+                     || value is ulong || value is uint || value is ushort || value is byte)
+                return JTokenType.Integer;
+            else if (value is Enum)
+                return JTokenType.Integer;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            else if (value is BigInteger)
+                return JTokenType.Integer;
+#endif
+            else if (value is double || value is float || value is decimal)
+                return JTokenType.Float;
+            else if (value is DateTime)
+                return JTokenType.Date;
+#if !NET20
+            else if (value is DateTimeOffset)
+                return JTokenType.Date;
+#endif
+            else if (value is byte[])
+                return JTokenType.Bytes;
+            else if (value is bool)
+                return JTokenType.Boolean;
+            else if (value is Guid)
+                return JTokenType.Guid;
+            else if (value is Uri)
+                return JTokenType.Uri;
+            else if (value is TimeSpan)
+                return JTokenType.TimeSpan;
+
+            throw new ArgumentException("Could not determine JSON object type for type {0}.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+        }
+
+        private static JTokenType GetStringValueType(JTokenType? current)
+        {
+            if (current == null)
+                return JTokenType.String;
+
+            switch (current.Value)
+            {
+                case JTokenType.Comment:
+                case JTokenType.String:
+                case JTokenType.Raw:
+                    return current.Value;
+                default:
+                    return JTokenType.String;
+            }
+        }
+
+        /// <summary>
+        /// Gets the node type for this <see cref="JToken"/>.
+        /// </summary>
+        /// <value>The type.</value>
+        public override JTokenType Type
+        {
+            get { return _valueType; }
+        }
+
+        /// <summary>
+        /// Gets or sets the underlying token value.
+        /// </summary>
+        /// <value>The underlying token value.</value>
+        public object Value
+        {
+            get { return _value; }
+            set
+            {
+                Type currentType = (_value != null) ? _value.GetType() : null;
+                Type newType = (value != null) ? value.GetType() : null;
+
+                if (currentType != newType)
+                    _valueType = GetValueType(_valueType, value);
+
+                _value = value;
+            }
+        }
+
+        /// <summary>
+        /// Writes this token to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="converters">A collection of <see cref="JsonConverter"/> which will be used when writing the token.</param>
+        public override void WriteTo(JsonWriter writer, params JsonConverter[] converters)
+        {
+            if (converters != null && converters.Length > 0 && _value != null)
+            {
+                JsonConverter matchingConverter = JsonSerializer.GetMatchingConverter(converters, _value.GetType());
+                if (matchingConverter != null && matchingConverter.CanWrite)
+                {
+                    matchingConverter.WriteJson(writer, _value, JsonSerializer.CreateDefault());
+                    return;
+                }
+            }
+
+            switch (_valueType)
+            {
+                case JTokenType.Comment:
+                    writer.WriteComment((_value != null) ? _value.ToString() : null);
+                    return;
+                case JTokenType.Raw:
+                    writer.WriteRawValue((_value != null) ? _value.ToString() : null);
+                    return;
+                case JTokenType.Null:
+                    writer.WriteNull();
+                    return;
+                case JTokenType.Undefined:
+                    writer.WriteUndefined();
+                    return;
+                case JTokenType.Integer:
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+                    if (_value is BigInteger)
+                        writer.WriteValue((BigInteger)_value);
+                    else
+#endif
+                        writer.WriteValue(Convert.ToInt64(_value, CultureInfo.InvariantCulture));
+                    return;
+                case JTokenType.Float:
+                    if (_value is decimal)
+                        writer.WriteValue((decimal)_value);
+                    else if (_value is double)
+                        writer.WriteValue((double)_value);
+                    else if (_value is float)
+                        writer.WriteValue((float)_value);
+                    else
+                        writer.WriteValue(Convert.ToDouble(_value, CultureInfo.InvariantCulture));
+                    return;
+                case JTokenType.String:
+                    writer.WriteValue((_value != null) ? _value.ToString() : null);
+                    return;
+                case JTokenType.Boolean:
+                    writer.WriteValue(Convert.ToBoolean(_value, CultureInfo.InvariantCulture));
+                    return;
+                case JTokenType.Date:
+#if !NET20
+                    if (_value is DateTimeOffset)
+                        writer.WriteValue((DateTimeOffset)_value);
+                    else
+#endif
+                        writer.WriteValue(Convert.ToDateTime(_value, CultureInfo.InvariantCulture));
+                    return;
+                case JTokenType.Bytes:
+                    writer.WriteValue((byte[])_value);
+                    return;
+                case JTokenType.Guid:
+                case JTokenType.Uri:
+                case JTokenType.TimeSpan:
+                    writer.WriteValue((_value != null) ? _value.ToString() : null);
+                    return;
+            }
+
+            throw MiscellaneousUtils.CreateArgumentOutOfRangeException("TokenType", _valueType, "Unexpected token type.");
+        }
+
+        internal override int GetDeepHashCode()
+        {
+            int valueHashCode = (_value != null) ? _value.GetHashCode() : 0;
+
+            return _valueType.GetHashCode() ^ valueHashCode;
+        }
+
+        private static bool ValuesEquals(JValue v1, JValue v2)
+        {
+            return (v1 == v2 || (v1._valueType == v2._valueType && Compare(v1._valueType, v1._value, v2._value) == 0));
+        }
+
+        /// <summary>
+        /// Indicates whether the current object is equal to another object of the same type.
+        /// </summary>
+        /// <returns>
+        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
+        /// </returns>
+        /// <param name="other">An object to compare with this object.</param>
+        public bool Equals(JValue other)
+        {
+            if (other == null)
+                return false;
+
+            return ValuesEquals(this, other);
+        }
+
+        /// <summary>
+        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
+        /// </summary>
+        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>.</param>
+        /// <returns>
+        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
+        /// </returns>
+        /// <exception cref="T:System.NullReferenceException">
+        /// The <paramref name="obj"/> parameter is null.
+        /// </exception>
+        public override bool Equals(object obj)
+        {
+            if (obj == null)
+                return false;
+
+            JValue otherValue = obj as JValue;
+            if (otherValue != null)
+                return Equals(otherValue);
+
+            return base.Equals(obj);
+        }
+
+        /// <summary>
+        /// Serves as a hash function for a particular type.
+        /// </summary>
+        /// <returns>
+        /// A hash code for the current <see cref="T:System.Object"/>.
+        /// </returns>
+        public override int GetHashCode()
+        {
+            if (_value == null)
+                return 0;
+
+            return _value.GetHashCode();
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String"/> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="System.String"/> that represents this instance.
+        /// </returns>
+        public override string ToString()
+        {
+            if (_value == null)
+                return string.Empty;
+
+            return _value.ToString();
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String"/> that represents this instance.
+        /// </summary>
+        /// <param name="format">The format.</param>
+        /// <returns>
+        /// A <see cref="System.String"/> that represents this instance.
+        /// </returns>
+        public string ToString(string format)
+        {
+            return ToString(format, CultureInfo.CurrentCulture);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String"/> that represents this instance.
+        /// </summary>
+        /// <param name="formatProvider">The format provider.</param>
+        /// <returns>
+        /// A <see cref="System.String"/> that represents this instance.
+        /// </returns>
+        public string ToString(IFormatProvider formatProvider)
+        {
+            return ToString(null, formatProvider);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="System.String"/> that represents this instance.
+        /// </summary>
+        /// <param name="format">The format.</param>
+        /// <param name="formatProvider">The format provider.</param>
+        /// <returns>
+        /// A <see cref="System.String"/> that represents this instance.
+        /// </returns>
+        public string ToString(string format, IFormatProvider formatProvider)
+        {
+            if (_value == null)
+                return string.Empty;
+
+            IFormattable formattable = _value as IFormattable;
+            if (formattable != null)
+                return formattable.ToString(format, formatProvider);
+            else
+                return _value.ToString();
+        }
+
+#if !(NET35 || NET20 || PORTABLE40)
+        /// <summary>
+        /// Returns the <see cref="T:System.Dynamic.DynamicMetaObject"/> responsible for binding operations performed on this object.
+        /// </summary>
+        /// <param name="parameter">The expression tree representation of the runtime value.</param>
+        /// <returns>
+        /// The <see cref="T:System.Dynamic.DynamicMetaObject"/> to bind this object.
+        /// </returns>
+        protected override DynamicMetaObject GetMetaObject(Expression parameter)
+        {
+            return new DynamicProxyMetaObject<JValue>(parameter, this, new JValueDynamicProxy(), true);
+        }
+
+        private class JValueDynamicProxy : DynamicProxy<JValue>
+        {
+            public override bool TryConvert(JValue instance, ConvertBinder binder, out object result)
+            {
+                if (binder.Type == typeof(JValue))
+                {
+                    result = instance;
+                    return true;
+                }
+
+                object value = instance.Value;
+
+                if (value == null)
+                {
+                    result = null;
+                    return ReflectionUtils.IsNullable(binder.Type);
+                }
+
+                result = ConvertUtils.Convert(instance.Value, CultureInfo.InvariantCulture, binder.Type);
+                return true;
+            }
+
+            public override bool TryBinaryOperation(JValue instance, BinaryOperationBinder binder, object arg, out object result)
+            {
+                object compareValue = (arg is JValue) ? ((JValue)arg).Value : arg;
+
+                switch (binder.Operation)
+                {
+                    case ExpressionType.Equal:
+                        result = (Compare(instance.Type, instance.Value, compareValue) == 0);
+                        return true;
+                    case ExpressionType.NotEqual:
+                        result = (Compare(instance.Type, instance.Value, compareValue) != 0);
+                        return true;
+                    case ExpressionType.GreaterThan:
+                        result = (Compare(instance.Type, instance.Value, compareValue) > 0);
+                        return true;
+                    case ExpressionType.GreaterThanOrEqual:
+                        result = (Compare(instance.Type, instance.Value, compareValue) >= 0);
+                        return true;
+                    case ExpressionType.LessThan:
+                        result = (Compare(instance.Type, instance.Value, compareValue) < 0);
+                        return true;
+                    case ExpressionType.LessThanOrEqual:
+                        result = (Compare(instance.Type, instance.Value, compareValue) <= 0);
+                        return true;
+                    case ExpressionType.Add:
+                    case ExpressionType.AddAssign:
+                    case ExpressionType.Subtract:
+                    case ExpressionType.SubtractAssign:
+                    case ExpressionType.Multiply:
+                    case ExpressionType.MultiplyAssign:
+                    case ExpressionType.Divide:
+                    case ExpressionType.DivideAssign:
+                        if (Operation(binder.Operation, instance.Value, compareValue, out result))
+                        {
+                            result = new JValue(result);
+                            return true;
+                        }
+                        break;
+                }
+
+                result = null;
+                return false;
+            }
+        }
+#endif
+
+        int IComparable.CompareTo(object obj)
+        {
+            if (obj == null)
+                return 1;
+
+            object otherValue = (obj is JValue) ? ((JValue)obj).Value : obj;
+
+            return Compare(_valueType, _value, otherValue);
+        }
+
+        /// <summary>
+        /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
+        /// </summary>
+        /// <param name="obj">An object to compare with this instance.</param>
+        /// <returns>
+        /// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings:
+        /// Value
+        /// Meaning
+        /// Less than zero
+        /// This instance is less than <paramref name="obj"/>.
+        /// Zero
+        /// This instance is equal to <paramref name="obj"/>.
+        /// Greater than zero
+        /// This instance is greater than <paramref name="obj"/>.
+        /// </returns>
+        /// <exception cref="T:System.ArgumentException">
+        /// 	<paramref name="obj"/> is not the same type as this instance.
+        /// </exception>
+        public int CompareTo(JValue obj)
+        {
+            if (obj == null)
+                return 1;
+
+            return Compare(_valueType, _value, obj._value);
+        }
+
+#if !(NETFX_CORE || PORTABLE)
+        TypeCode IConvertible.GetTypeCode()
+        {
+            if (_value == null)
+                return TypeCode.Empty;
+
+#if !NET20
+            if (_value is DateTimeOffset)
+                return TypeCode.DateTime;
+#endif
+#if !(NET20 || NET35 || PORTABLE40)
+            if (_value is BigInteger)
+                return TypeCode.Object;
+#endif
+
+            return System.Type.GetTypeCode(_value.GetType());
+        }
+
+        bool IConvertible.ToBoolean(IFormatProvider provider)
+        {
+            return (bool)this;
+        }
+
+        char IConvertible.ToChar(IFormatProvider provider)
+        {
+            return (char)this;
+        }
+
+        sbyte IConvertible.ToSByte(IFormatProvider provider)
+        {
+            return (sbyte)this;
+        }
+
+        byte IConvertible.ToByte(IFormatProvider provider)
+        {
+            return (byte)this;
+        }
+
+        short IConvertible.ToInt16(IFormatProvider provider)
+        {
+            return (short)this;
+        }
+
+        ushort IConvertible.ToUInt16(IFormatProvider provider)
+        {
+            return (ushort)this;
+        }
+
+        int IConvertible.ToInt32(IFormatProvider provider)
+        {
+            return (int)this;
+        }
+
+        uint IConvertible.ToUInt32(IFormatProvider provider)
+        {
+            return (uint)this;
+        }
+
+        long IConvertible.ToInt64(IFormatProvider provider)
+        {
+            return (long)this;
+        }
+
+        ulong IConvertible.ToUInt64(IFormatProvider provider)
+        {
+            return (ulong)this;
+        }
+
+        float IConvertible.ToSingle(IFormatProvider provider)
+        {
+            return (float)this;
+        }
+
+        double IConvertible.ToDouble(IFormatProvider provider)
+        {
+            return (double)this;
+        }
+
+        decimal IConvertible.ToDecimal(IFormatProvider provider)
+        {
+            return (decimal)this;
+        }
+
+        DateTime IConvertible.ToDateTime(IFormatProvider provider)
+        {
+            return (DateTime)this;
+        }
+
+        object IConvertible.ToType(Type conversionType, IFormatProvider provider)
+        {
+            return ToObject(conversionType);
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs b/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs
new file mode 100644
index 0000000..f3e5443
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/ArrayIndexFilter.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class ArrayIndexFilter : PathFilter
+    {
+        public int? Index { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken t in current)
+            {
+                if (Index != null)
+                {
+                    JToken v = GetTokenIndex(t, errorWhenNoMatch, Index.Value);
+
+                    if (v != null)
+                        yield return v;
+                }
+                else
+                {
+                    if (t is JArray || t is JConstructor)
+                    {
+                        foreach (JToken v in t)
+                        {
+                            yield return v;
+                        }
+                    }
+                    else
+                    {
+                        if (errorWhenNoMatch)
+                            throw new JsonException("Index * not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs b/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs
new file mode 100644
index 0000000..0a9e40e
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/ArrayMultipleIndexFilter.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class ArrayMultipleIndexFilter : PathFilter
+    {
+        public List<int> Indexes { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken t in current)
+            {
+                foreach (int i in Indexes)
+                {
+                    JToken v = GetTokenIndex(t, errorWhenNoMatch, i);
+
+                    if (v != null)
+                        yield return v;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs b/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs
new file mode 100644
index 0000000..da41eb5
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/ArraySliceFilter.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class ArraySliceFilter : PathFilter
+    {
+        public int? Start { get; set; }
+        public int? End { get; set; }
+        public int? Step { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            if (Step == 0)
+                throw new JsonException("Step cannot be zero.");
+
+            foreach (JToken t in current)
+            {
+                JArray a = t as JArray;
+                if (a != null)
+                {
+                    // set defaults for null arguments
+                    int stepCount = Step ?? 1;
+                    int startIndex = Start ?? ((stepCount > 0) ? 0 : a.Count - 1);
+                    int stopIndex = End ?? ((stepCount > 0) ? a.Count : -1);
+
+                    // start from the end of the list if start is negitive
+                    if (Start < 0) startIndex = a.Count + startIndex;
+
+                    // end from the start of the list if stop is negitive
+                    if (End < 0) stopIndex = a.Count + stopIndex;
+
+                    // ensure indexes keep within collection bounds
+                    startIndex = Math.Max(startIndex, (stepCount > 0) ? 0 : int.MinValue);
+                    startIndex = Math.Min(startIndex, (stepCount > 0) ? a.Count : a.Count - 1);
+                    stopIndex = Math.Max(stopIndex, -1);
+                    stopIndex = Math.Min(stopIndex, a.Count);
+
+                    bool positiveStep = (stepCount > 0);
+
+                    if (IsValid(startIndex, stopIndex, positiveStep))
+                    {
+                        for (int i = startIndex; IsValid(i, stopIndex, positiveStep); i += stepCount)
+                        {
+                            yield return a[i];
+                        }
+                    }
+                    else
+                    {
+                        if (errorWhenNoMatch)
+                            throw new JsonException("Array slice of {0} to {1} returned no results.".FormatWith(CultureInfo.InvariantCulture,
+                                Start != null ? Start.Value.ToString(CultureInfo.InvariantCulture) : "*",
+                                End != null ? End.Value.ToString(CultureInfo.InvariantCulture) : "*"));
+                    }
+                }
+                else
+                {
+                    if (errorWhenNoMatch)
+                        throw new JsonException("Array slice is not valid on {0}.".FormatWith(CultureInfo.InvariantCulture, t.GetType().Name));
+                }
+            }
+        }
+
+        private bool IsValid(int index, int stopIndex, bool positiveStep)
+        {
+            if (positiveStep)
+                return (index < stopIndex);
+
+            return (index > stopIndex);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs b/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs
new file mode 100644
index 0000000..b55f8a2
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/FieldFilter.cs
@@ -0,0 +1,43 @@
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class FieldFilter : PathFilter
+    {
+        public string Name { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken t in current)
+            {
+                JObject o = t as JObject;
+                if (o != null)
+                {
+                    if (Name != null)
+                    {
+                        JToken v = o[Name];
+
+                        if (v != null)
+                            yield return v;
+                        else if (errorWhenNoMatch)
+                            throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, Name));
+                    }
+                    else
+                    {
+                        foreach (KeyValuePair<string, JToken> p in o)
+                        {
+                            yield return p.Value;
+                        }
+                    }
+                }
+                else
+                {
+                    if (errorWhenNoMatch)
+                        throw new JsonException("Property '{0}' not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, Name ?? "*", t.GetType().Name));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs b/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs
new file mode 100644
index 0000000..cc64ead
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/FieldMultipleFilter.cs
@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class FieldMultipleFilter : PathFilter
+    {
+        public List<string> Names { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken t in current)
+            {
+                JObject o = t as JObject;
+                if (o != null)
+                {
+                    foreach (string name in Names)
+                    {
+                        JToken v = o[name];
+
+                        if (v != null)
+                            yield return v;
+
+                        if (errorWhenNoMatch)
+                            throw new JsonException("Property '{0}' does not exist on JObject.".FormatWith(CultureInfo.InvariantCulture, name));
+                    }
+                }
+                else
+                {
+                    if (errorWhenNoMatch)
+                        throw new JsonException("Properties {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, string.Join(", ", Names.Select(n => "'" + n + "'").ToArray()), t.GetType().Name));
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/JPath.cs b/Newtonsoft.Json/Linq/JsonPath/JPath.cs
new file mode 100644
index 0000000..629a5d2
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/JPath.cs
@@ -0,0 +1,681 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class JPath
+    {
+        private readonly string _expression;
+        public List<PathFilter> Filters { get; private set; }
+
+        private int _currentIndex;
+
+        public JPath(string expression)
+        {
+            ValidationUtils.ArgumentNotNull(expression, "expression");
+            _expression = expression;
+            Filters = new List<PathFilter>();
+
+            ParseMain();
+        }
+
+        private void ParseMain()
+        {
+            int currentPartStartIndex = _currentIndex;
+
+            EatWhitespace();
+
+            if (_expression.Length == _currentIndex)
+                return;
+
+            if (_expression[_currentIndex] == '$')
+            {
+                if (_expression.Length == 1)
+                    return;
+
+                // only increment position for "$." or "$["
+                // otherwise assume property that starts with $
+                char c = _expression[_currentIndex + 1];
+                if (c == '.' || c == '[')
+                {
+                    _currentIndex++;
+                    currentPartStartIndex = _currentIndex;
+                }
+            }
+
+            if (!ParsePath(Filters, currentPartStartIndex, false))
+            {
+                int lastCharacterIndex = _currentIndex;
+
+                EatWhitespace();
+
+                if (_currentIndex < _expression.Length)
+                    throw new JsonException("Unexpected character while parsing path: " + _expression[lastCharacterIndex]);
+            }
+        }
+
+        private bool ParsePath(List<PathFilter> filters, int currentPartStartIndex, bool query)
+        {
+            bool scan = false;
+            bool followingIndexer = false;
+            bool followingDot = false;
+
+            bool ended = false;
+            while (_currentIndex < _expression.Length && !ended)
+            {
+                char currentChar = _expression[_currentIndex];
+
+                switch (currentChar)
+                {
+                    case '[':
+                    case '(':
+                        if (_currentIndex > currentPartStartIndex)
+                        {
+                            string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
+                            PathFilter filter = (scan) ? (PathFilter)new ScanFilter() { Name = member } : new FieldFilter() { Name = member };
+                            filters.Add(filter);
+                            scan = false;
+                        }
+
+                        filters.Add(ParseIndexer(currentChar));
+                        _currentIndex++;
+                        currentPartStartIndex = _currentIndex;
+                        followingIndexer = true;
+                        followingDot = false;
+                        break;
+                    case ']':
+                    case ')':
+                        ended = true;
+                        break;
+                    case ' ':
+                        //EatWhitespace();
+                        if (_currentIndex < _expression.Length)
+                            ended = true;
+                        break;
+                    case '.':
+                        if (_currentIndex > currentPartStartIndex)
+                        {
+                            string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex);
+                            if (member == "*")
+                                member = null;
+                            PathFilter filter = (scan) ? (PathFilter)new ScanFilter() { Name = member } : new FieldFilter() { Name = member };
+                            filters.Add(filter);
+                            scan = false;
+                        }
+                        if (_currentIndex + 1 < _expression.Length && _expression[_currentIndex + 1] == '.')
+                        {
+                            scan = true;
+                            _currentIndex++;
+                        }
+                        _currentIndex++;
+                        currentPartStartIndex = _currentIndex;
+                        followingIndexer = false;
+                        followingDot = true;
+                        break;
+                    default:
+                        if (query && (currentChar == '=' || currentChar == '<' || currentChar == '!' || currentChar == '>' || currentChar == '|' || currentChar == '&'))
+                        {
+                            ended = true;
+                        }
+                        else
+                        {
+                            if (followingIndexer)
+                                throw new JsonException("Unexpected character following indexer: " + currentChar);
+
+                            _currentIndex++;
+                        }
+                        break;
+                }
+            }
+
+            bool atPathEnd = (_currentIndex == _expression.Length);
+
+            if (_currentIndex > currentPartStartIndex)
+            {
+                string member = _expression.Substring(currentPartStartIndex, _currentIndex - currentPartStartIndex).TrimEnd();
+                if (member == "*")
+                    member = null;
+                PathFilter filter = (scan) ? (PathFilter)new ScanFilter() { Name = member } : new FieldFilter() { Name = member };
+                filters.Add(filter);
+            }
+            else
+            {
+                // no field name following dot in path and at end of base path/query
+                if (followingDot && (atPathEnd || query))
+                    throw new JsonException("Unexpected end while parsing path.");
+            }
+
+            return atPathEnd;
+        }
+
+        private PathFilter ParseIndexer(char indexerOpenChar)
+        {
+            _currentIndex++;
+
+            char indexerCloseChar = (indexerOpenChar == '[') ? ']' : ')';
+
+            EnsureLength("Path ended with open indexer.");
+
+            EatWhitespace();
+
+            if (_expression[_currentIndex] == '\'')
+            {
+                return ParseQuotedField(indexerCloseChar);
+            }
+            else if (_expression[_currentIndex] == '?')
+            {
+                return ParseQuery(indexerCloseChar);
+            }
+            else
+            {
+                return ParseArrayIndexer(indexerCloseChar);
+            }
+        }
+
+        private PathFilter ParseArrayIndexer(char indexerCloseChar)
+        {
+            int start = _currentIndex;
+            int? end = null;
+            List<int> indexes = null;
+            int colonCount = 0;
+            int? startIndex = null;
+            int? endIndex = null;
+            int? step = null;
+
+            while (_currentIndex < _expression.Length)
+            {
+                char currentCharacter = _expression[_currentIndex];
+
+                if (currentCharacter == ' ')
+                {
+                    end = _currentIndex;
+                    EatWhitespace();
+                    continue;
+                }
+
+                if (currentCharacter == indexerCloseChar)
+                {
+                    int length = (end ?? _currentIndex) - start;
+
+                    if (indexes != null)
+                    {
+                        if (length == 0)
+                            throw new JsonException("Array index expected.");
+
+                        string indexer = _expression.Substring(start, length);
+                        int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
+
+                        indexes.Add(index);
+                        return new ArrayMultipleIndexFilter { Indexes = indexes };
+                    }
+                    else if (colonCount > 0)
+                    {
+                        if (length > 0)
+                        {
+                            string indexer = _expression.Substring(start, length);
+                            int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
+
+                            if (colonCount == 1)
+                                endIndex = index;
+                            else
+                                step = index;
+                        }
+
+                        return new ArraySliceFilter { Start = startIndex, End = endIndex, Step = step };
+                    }
+                    else
+                    {
+                        if (length == 0)
+                            throw new JsonException("Array index expected.");
+
+                        string indexer = _expression.Substring(start, length);
+                        int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
+
+                        return new ArrayIndexFilter { Index = index };
+                    }
+                } else if (currentCharacter == ',')
+                {
+                    int length = (end ?? _currentIndex) - start;
+
+                    if (length == 0)
+                        throw new JsonException("Array index expected.");
+
+                    if (indexes == null)
+                        indexes = new List<int>();
+
+                    string indexer = _expression.Substring(start, length);
+                    indexes.Add(Convert.ToInt32(indexer, CultureInfo.InvariantCulture));
+
+                    _currentIndex++;
+
+                    EatWhitespace();
+
+                    start = _currentIndex;
+                    end = null;
+                }
+                else if (currentCharacter == '*')
+                {
+                    _currentIndex++;
+                    EnsureLength("Path ended with open indexer.");
+                    EatWhitespace();
+
+                    if (_expression[_currentIndex] != indexerCloseChar)
+                        throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
+
+                    return new ArrayIndexFilter();
+                }
+                else if (currentCharacter == ':')
+                {
+                    int length = (end ?? _currentIndex) - start;
+
+                    if (length > 0)
+                    {
+                        string indexer = _expression.Substring(start, length);
+                        int index = Convert.ToInt32(indexer, CultureInfo.InvariantCulture);
+
+                        if (colonCount == 0)
+                            startIndex = index;
+                        else if (colonCount == 1)
+                            endIndex = index;
+                        else
+                            step = index;
+                    }
+
+                    colonCount++;
+
+                    _currentIndex++;
+
+                    EatWhitespace();
+
+                    start = _currentIndex;
+                    end = null;
+                }
+                else if (!char.IsDigit(currentCharacter) && currentCharacter != '-')
+                {
+                    throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
+                }
+                else
+                {
+                    if (end != null)
+                        throw new JsonException("Unexpected character while parsing path indexer: " + currentCharacter);
+
+                    _currentIndex++;
+                }
+
+            }
+
+            throw new JsonException("Path ended with open indexer.");
+        }
+
+        private void EatWhitespace()
+        {
+            while (_currentIndex < _expression.Length)
+            {
+                if (_expression[_currentIndex] != ' ')
+                    break;
+
+                _currentIndex++;
+            }
+        }
+
+        private PathFilter ParseQuery(char indexerCloseChar)
+        {
+            _currentIndex++;
+            EnsureLength("Path ended with open indexer.");
+
+            if (_expression[_currentIndex] != '(')
+                throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
+
+            _currentIndex++;
+
+            QueryExpression expression = ParseExpression();
+
+            _currentIndex++;
+            EnsureLength("Path ended with open indexer.");
+            EatWhitespace();
+
+            if (_expression[_currentIndex] != indexerCloseChar)
+                throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
+
+            return new QueryFilter
+            {
+                Expression = expression
+            };
+        }
+
+        private QueryExpression ParseExpression()
+        {
+            QueryExpression rootExpression = null;
+            CompositeExpression parentExpression = null;
+
+            while (_currentIndex < _expression.Length)
+            {
+                EatWhitespace();
+
+                if (_expression[_currentIndex] != '@')
+                    throw new JsonException("Unexpected character while parsing path query: " + _expression[_currentIndex]);
+
+                _currentIndex++;
+
+                List<PathFilter> expressionPath = new List<PathFilter>();
+
+                if (ParsePath(expressionPath, _currentIndex, true))
+                    throw new JsonException("Path ended with open query.");
+
+                EatWhitespace();
+                EnsureLength("Path ended with open query.");
+
+                QueryOperator op;
+                object value = null;
+                if (_expression[_currentIndex] == ')'
+                    || _expression[_currentIndex] == '|'
+                    || _expression[_currentIndex] == '&')
+                {
+                    op = QueryOperator.Exists;
+                }
+                else
+                {
+                    op = ParseOperator();
+
+                    EatWhitespace();
+                    EnsureLength("Path ended with open query.");
+
+                    value = ParseValue();
+
+                    EatWhitespace();
+                    EnsureLength("Path ended with open query.");
+                }
+
+                BooleanQueryExpression booleanExpression = new BooleanQueryExpression
+                {
+                    Path = expressionPath,
+                    Operator = op,
+                    Value = (op != QueryOperator.Exists) ? new JValue(value) : null
+                };
+
+                if (_expression[_currentIndex] == ')')
+                {
+                    if (parentExpression != null)
+                    {
+                        parentExpression.Expressions.Add(booleanExpression);
+                        return rootExpression;
+                    }
+                    
+                    return booleanExpression;
+                }
+                if (_expression[_currentIndex] == '&' && Match("&&"))
+                {
+                    if (parentExpression == null || parentExpression.Operator != QueryOperator.And)
+                    {
+                        CompositeExpression andExpression = new CompositeExpression { Operator = QueryOperator.And };
+
+                        if (parentExpression != null)
+                            parentExpression.Expressions.Add(andExpression);
+
+                        parentExpression = andExpression;
+
+                        if (rootExpression == null)
+                            rootExpression = parentExpression;
+                    }
+
+                    parentExpression.Expressions.Add(booleanExpression);
+                }
+                if (_expression[_currentIndex] == '|' && Match("||"))
+                {
+                    if (parentExpression == null || parentExpression.Operator != QueryOperator.Or)
+                    {
+                        CompositeExpression orExpression = new CompositeExpression { Operator = QueryOperator.Or };
+
+                        if (parentExpression != null)
+                            parentExpression.Expressions.Add(orExpression);
+
+                        parentExpression = orExpression;
+
+                        if (rootExpression == null)
+                            rootExpression = parentExpression;
+                    }
+
+                    parentExpression.Expressions.Add(booleanExpression);
+                }
+            }
+
+            throw new JsonException("Path ended with open query.");
+        }
+
+        private object ParseValue()
+        {
+            char currentChar = _expression[_currentIndex];
+            if (currentChar == '\'')
+            {
+                return ReadQuotedString();
+            }
+            else if (char.IsDigit(currentChar) || currentChar == '-')
+            {
+                StringBuilder sb = new StringBuilder();
+                sb.Append(currentChar);
+
+                _currentIndex++;
+                while (_currentIndex < _expression.Length)
+                {
+                    currentChar = _expression[_currentIndex];
+                    if (currentChar == ' ' || currentChar == ')')
+                    {
+                        string numberText = sb.ToString();
+
+                        if (numberText.IndexOfAny(new char[] { '.', 'E', 'e' }) != -1)
+                        {
+                            double d;
+                            if (double.TryParse(numberText, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out d))
+                                return d;
+                            else
+                                throw new JsonException("Could not read query value.");
+                        }
+                        else
+                        {
+                            long l;
+                            if (long.TryParse(numberText, NumberStyles.Integer, CultureInfo.InvariantCulture, out l))
+                                return l;
+                            else
+                                throw new JsonException("Could not read query value.");
+                        }
+                    }
+                    else
+                    {
+                        sb.Append(currentChar);
+                        _currentIndex++;
+                    }
+                }
+            }
+            else if (currentChar == 't')
+            {
+                if (Match("true"))
+                    return true;
+            }
+            else if (currentChar == 'f')
+            {
+                if (Match("false"))
+                    return false;
+            }
+            else if (currentChar == 'n')
+            {
+                if (Match("null"))
+                    return null;
+            }
+
+            throw new JsonException("Could not read query value.");
+        }
+
+        private string ReadQuotedString()
+        {
+            StringBuilder sb = new StringBuilder();
+
+            _currentIndex++;
+            while (_currentIndex < _expression.Length)
+            {
+                char currentChar = _expression[_currentIndex];
+                if (currentChar == '\\' && _currentIndex + 1 < _expression.Length)
+                {
+                    _currentIndex++;
+
+                    if (_expression[_currentIndex] == '\'')
+                        sb.Append('\'');
+                    else if (_expression[_currentIndex] == '\\')
+                        sb.Append('\\');
+                    else
+                        throw new JsonException(@"Unknown escape chracter: \" + _expression[_currentIndex]);
+
+                    _currentIndex++;
+                }
+                else if (currentChar == '\'')
+                {
+                    _currentIndex++;
+                    {
+                        return sb.ToString();
+                    }
+                }
+                else
+                {
+                    _currentIndex++;
+                    sb.Append(currentChar);
+                }
+            }
+
+            throw new JsonException("Path ended with an open string.");
+        }
+
+        private bool Match(string s)
+        {
+            int currentPosition = _currentIndex;
+            foreach (char c in s)
+            {
+                if (currentPosition < _expression.Length && _expression[currentPosition] == c)
+                    currentPosition++;
+                else
+                    return false;
+            }
+
+            _currentIndex = currentPosition;
+            return true;
+        }
+
+        private QueryOperator ParseOperator()
+        {
+            if (_currentIndex + 1 >= _expression.Length)
+                throw new JsonException("Path ended with open query.");
+
+            if (Match("=="))
+                return QueryOperator.Equals;
+            if (Match("!=") || Match("<>"))
+                return QueryOperator.NotEquals;
+            if (Match("<="))
+                return QueryOperator.LessThanOrEquals;
+            if (Match("<"))
+                return QueryOperator.LessThan;
+            if (Match(">="))
+                return QueryOperator.GreaterThanOrEquals;
+            if (Match(">"))
+                return QueryOperator.GreaterThan;
+
+            throw new JsonException("Could not read query operator.");
+        }
+
+        private PathFilter ParseQuotedField(char indexerCloseChar)
+        {
+            //_currentIndex++;
+            //int start = _currentIndex;
+
+            List<string> fields = null;
+
+            while (_currentIndex < _expression.Length)
+            {
+                string field = ReadQuotedString();
+
+                //_currentIndex++;
+                //EnsureLength("Path ended with open indexer.");
+                EatWhitespace();
+                EnsureLength("Path ended with open indexer.");
+
+                if (_expression[_currentIndex] == indexerCloseChar)
+                {
+                    _currentIndex++;
+
+                    if (fields != null)
+                    {
+                        fields.Add(field);
+                        return new FieldMultipleFilter { Names = fields };
+                    }
+                    else
+                    {
+                        return new FieldFilter { Name = field };
+                    }
+                }
+                else if (_expression[_currentIndex] == ',')
+                {
+                    _currentIndex++;
+                    EatWhitespace();
+
+                    if (fields == null)
+                        fields = new List<string>();
+
+                    fields.Add(field);
+                }
+                else
+                {
+                    throw new JsonException("Unexpected character while parsing path indexer: " + _expression[_currentIndex]);
+                }
+            }
+
+            throw new JsonException("Path ended with open indexer.");
+        }
+
+        private void EnsureLength(string message)
+        {
+            if (_currentIndex >= _expression.Length)
+                throw new JsonException(message);
+        }
+
+        internal IEnumerable<JToken> Evaluate(JToken t, bool errorWhenNoMatch)
+        {
+            return Evaluate(Filters, t, errorWhenNoMatch);
+        }
+
+        internal static IEnumerable<JToken> Evaluate(List<PathFilter> filters, JToken t, bool errorWhenNoMatch)
+        {
+            IEnumerable<JToken> current = new[] { t };
+            foreach (PathFilter filter in filters)
+            {
+                current = filter.ExecuteFilter(current, errorWhenNoMatch);
+            }
+
+            return current;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs b/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs
new file mode 100644
index 0000000..fb5fbed
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/PathFilter.cs
@@ -0,0 +1,49 @@
+using System.Collections.Generic;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal abstract class PathFilter
+    {
+        public abstract IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch);
+
+        protected static JToken GetTokenIndex(JToken t, bool errorWhenNoMatch, int index)
+        {
+            JArray a = t as JArray;
+            JConstructor c = t as JConstructor;
+
+            if (a != null)
+            {
+                if (a.Count <= index)
+                {
+                    if (errorWhenNoMatch)
+                        throw new JsonException("Index {0} outside the bounds of JArray.".FormatWith(CultureInfo.InvariantCulture, index));
+
+                    return null;
+                }
+
+                return a[index];
+            }
+            else if (c != null)
+            {
+                if (c.Count <= index)
+                {
+                    if (errorWhenNoMatch)
+                        throw new JsonException("Index {0} outside the bounds of JConstructor.".FormatWith(CultureInfo.InvariantCulture, index));
+
+                    return null;
+                }
+
+                return c[index];
+            }
+            else
+            {
+                if (errorWhenNoMatch)
+                    throw new JsonException("Index {0} not valid on {1}.".FormatWith(CultureInfo.InvariantCulture, index, t.GetType().Name));
+
+                return null;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs b/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs
new file mode 100644
index 0000000..df80d9c
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/QueryExpression.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal enum QueryOperator
+    {
+        None,
+        Equals,
+        NotEquals,
+        Exists,
+        LessThan,
+        LessThanOrEquals,
+        GreaterThan,
+        GreaterThanOrEquals,
+        And,
+        Or
+    }
+
+    internal abstract class QueryExpression
+    {
+        public QueryOperator Operator { get; set; }
+
+        public abstract bool IsMatch(JToken t);
+    }
+
+    internal class CompositeExpression : QueryExpression
+    {
+        public List<QueryExpression> Expressions { get; set; }
+
+        public CompositeExpression()
+        {
+            Expressions = new List<QueryExpression>();
+        }
+
+        public override bool IsMatch(JToken t)
+        {
+            switch (Operator)
+            {
+                case QueryOperator.And:
+                    foreach (QueryExpression e in Expressions)
+                    {
+                        if (!e.IsMatch(t))
+                            return false;
+                    }
+                    return true;
+                case QueryOperator.Or:
+                    foreach (QueryExpression e in Expressions)
+                    {
+                        if (e.IsMatch(t))
+                            return true;
+                    }
+                    return false;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+    }
+
+    internal class BooleanQueryExpression : QueryExpression
+    {
+        public List<PathFilter> Path { get; set; }
+        public JValue Value { get; set; }
+
+        public override bool IsMatch(JToken t)
+        {
+            IEnumerable<JToken> pathResult = JPath.Evaluate(Path, t, false);
+
+            foreach (JToken r in pathResult)
+            {
+                JValue v = r as JValue;
+                switch (Operator)
+                {
+                    case QueryOperator.Equals:
+                        if (v != null && v.Equals(Value))
+                            return true;
+                        break;
+                    case QueryOperator.NotEquals:
+                        if (v != null && !v.Equals(Value))
+                            return true;
+                        break;
+                    case QueryOperator.GreaterThan:
+                        if (v != null && v.CompareTo(Value) > 0)
+                            return true;
+                        break;
+                    case QueryOperator.GreaterThanOrEquals:
+                        if (v != null && v.CompareTo(Value) >= 0)
+                            return true;
+                        break;
+                    case QueryOperator.LessThan:
+                        if (v != null && v.CompareTo(Value) < 0)
+                            return true;
+                        break;
+                    case QueryOperator.LessThanOrEquals:
+                        if (v != null && v.CompareTo(Value) <= 0)
+                            return true;
+                        break;
+                    case QueryOperator.Exists:
+                        return true;
+                    default:
+                        throw new ArgumentOutOfRangeException();
+                }
+            }
+
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs b/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs
new file mode 100644
index 0000000..ae4964e
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/QueryFilter.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class QueryFilter : PathFilter
+    {
+        public QueryExpression Expression { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken t in current)
+            {
+                foreach (JToken v in t)
+                {
+                    if (Expression.IsMatch(v))
+                        yield return v;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs b/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs
new file mode 100644
index 0000000..857e7d8
--- /dev/null
+++ b/Newtonsoft.Json/Linq/JsonPath/ScanFilter.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Linq.JsonPath
+{
+    internal class ScanFilter : PathFilter
+    {
+        public string Name { get; set; }
+
+        public override IEnumerable<JToken> ExecuteFilter(IEnumerable<JToken> current, bool errorWhenNoMatch)
+        {
+            foreach (JToken root in current)
+            {
+                if (Name == null)
+                    yield return root;
+
+                JToken value = root;
+                JToken container = root;
+
+                while (true)
+                {
+                    if (container != null)
+                    {
+                        value = container.First;
+                    }
+                    else
+                    {
+                        while (value != null && value != root && value == value.Parent.Last)
+                        {
+                            value = value.Parent;
+                        }
+
+                        if (value == null || value == root)
+                            break;
+
+                        value = value.Next;
+                    }
+
+                    JProperty e = value as JProperty;
+                    if (e != null)
+                    {
+                        if (e.Name == Name)
+                            yield return e.Value;
+                    }
+                    else
+                    {
+                        if (Name == null)
+                            yield return value;
+                    }
+
+                    container = value as JContainer;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/MemberSerialization.cs b/Newtonsoft.Json/MemberSerialization.cs
new file mode 100644
index 0000000..4fafdc5
--- /dev/null
+++ b/Newtonsoft.Json/MemberSerialization.cs
@@ -0,0 +1,58 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies the member serialization options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum MemberSerialization
+    {
+#pragma warning disable 1584,1711,1572,1581,1580,1574
+        /// <summary>
+        /// All public members are serialized by default. Members can be excluded using <see cref="JsonIgnoreAttribute"/> or <see cref="NonSerializedAttribute"/>.
+        /// This is the default member serialization mode.
+        /// </summary>
+        OptOut,
+
+        /// <summary>
+        /// Only members must be marked with <see cref="JsonPropertyAttribute"/> or <see cref="DataMemberAttribute"/> are serialized.
+        /// This member serialization mode can also be set by marking the class with <see cref="DataContractAttribute"/>.
+        /// </summary>
+        OptIn,
+
+        /// <summary>
+        /// All public and private fields are serialized. Members can be excluded using <see cref="JsonIgnoreAttribute"/> or <see cref="NonSerializedAttribute"/>.
+        /// This member serialization mode can also be set by marking the class with <see cref="SerializableAttribute"/>
+        /// and setting IgnoreSerializableAttribute on <see cref="DefaultContractResolver"/> to false.
+        /// </summary>
+        Fields
+#pragma warning restore 1584,1711,1572,1581,1580,1574
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/MetadataPropertyHandling.cs b/Newtonsoft.Json/MetadataPropertyHandling.cs
new file mode 100644
index 0000000..51ab34b
--- /dev/null
+++ b/Newtonsoft.Json/MetadataPropertyHandling.cs
@@ -0,0 +1,47 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies metadata property handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum MetadataPropertyHandling
+    {
+        /// <summary>
+        /// Read metadata properties located at the start of a JSON object.
+        /// </summary>
+        Default = 0,
+
+        /// <summary>
+        /// Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance.
+        /// </summary>
+        ReadAhead = 1,
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/MissingMemberHandling.cs b/Newtonsoft.Json/MissingMemberHandling.cs
new file mode 100644
index 0000000..95dd9b9
--- /dev/null
+++ b/Newtonsoft.Json/MissingMemberHandling.cs
@@ -0,0 +1,47 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies missing member handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum MissingMemberHandling
+    {
+        /// <summary>
+        /// Ignore a missing member and do not attempt to deserialize it.
+        /// </summary>
+        Ignore = 0,
+
+        /// <summary>
+        /// Throw a <see cref="JsonSerializationException"/> when a missing member is encountered during deserialization.
+        /// </summary>
+        Error = 1
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj b/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj
new file mode 100644
index 0000000..182ebb1
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.Net20.csproj
@@ -0,0 +1,291 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <SignAssembly>false</SignAssembly>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <SccProjectName>
+    </SccProjectName>
+    <SccLocalPath>
+    </SccLocalPath>
+    <SccAuxPath>
+    </SccAuxPath>
+    <SccProvider>
+    </SccProvider>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Net20\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;NET20</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Net20\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRules>
+    </CodeAnalysisRules>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Net20\</OutputPath>
+    <DefineConstants>TRACE;NET20</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Net20\Newtonsoft.Json.xml</DocumentationFile>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj b/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj
new file mode 100644
index 0000000..5f6cf0a
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.Net35.csproj
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.30729</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <SignAssembly>false</SignAssembly>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <SccProjectName>
+    </SccProjectName>
+    <SccLocalPath>
+    </SccLocalPath>
+    <SccAuxPath>
+    </SccAuxPath>
+    <SccProvider>
+    </SccProvider>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkProfile>Client</TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Net35\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS;NET35</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Net35\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRules>
+    </CodeAnalysisRules>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Net35\</OutputPath>
+    <DefineConstants>TRACE;NET35</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Net35\Newtonsoft.Json.xml</DocumentationFile>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Runtime.Serialization">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="TraceLevel.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\FSharpUtils.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Dynamic.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj b/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj
new file mode 100644
index 0000000..f55f7be
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.Net40.csproj
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A9AE40FF-1A21-414A-9FE7-3BE13644CC6D}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <SignAssembly>false</SignAssembly>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <SccProjectName>
+    </SccProjectName>
+    <SccLocalPath>
+    </SccLocalPath>
+    <SccAuxPath>
+    </SccAuxPath>
+    <SccProvider>
+    </SccProvider>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Net40\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;NET40;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Net40\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRules>
+    </CodeAnalysisRules>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <UseVSHostingProcess>true</UseVSHostingProcess>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Net40\</OutputPath>
+    <DefineConstants>TRACE;NET40;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Net40\Newtonsoft.Json.xml</DocumentationFile>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <UseVSHostingProcess>true</UseVSHostingProcess>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Runtime.Serialization">
+      <RequiredTargetFramework>3.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="System.Xml" />
+    <Reference Include="System.Xml.Linq">
+      <RequiredTargetFramework>3.5</RequiredTargetFramework>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\FSharpUtils.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 2.0 %28x86%29</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.0 %28x86%29</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Dynamic.snk" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="AxantumStrongName.pfx" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="ReadMe-AxCrypt.txt" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj b/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj
new file mode 100644
index 0000000..6bfc08b
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.Portable.csproj
@@ -0,0 +1,243 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{959F7F85-C98B-4876-971A-9036224578E4}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Profile259</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Portable\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;PORTABLE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Portable\</OutputPath>
+    <DefineConstants>TRACE;PORTABLE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Portable\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="TraceLevel.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\FSharpUtils.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj b/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj
new file mode 100644
index 0000000..7160907
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.Portable40.csproj
@@ -0,0 +1,251 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{959F7F85-C98B-4876-971A-9036224578E4}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <TargetFrameworkProfile>Profile158</TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>4.0</OldToolsVersion>
+    <AssemblyOriginatorKeyFile>AxantumStrongName.pfx</AssemblyOriginatorKeyFile>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Portable40\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS;PORTABLE40</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Portable40\</OutputPath>
+    <DefineConstants>TRACE;CODE_ANALYSIS;PORTABLE40</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Portable40\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="TraceLevel.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\FSharpUtils.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
+  <Import Project="..\SolutionItems\Axantum.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.WinRT.csproj b/Newtonsoft.Json/Newtonsoft.Json.WinRT.csproj
new file mode 100644
index 0000000..7663968
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.WinRT.csproj
@@ -0,0 +1,316 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{263136A2-B89B-424E-A87A-F988CAA8D032}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <DefaultLanguage>en-US</DefaultLanguage>
+    <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{BC8A1FFA-BEE3-4634-8014-F334798102B3};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\WinRT\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>3</WarningLevel>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\WinRT\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\WinRT\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\ARM\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
+    <OutputPath>bin\ARM\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>ARM</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x64\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+    <OutputPath>bin\x64\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x64</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\x86\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>full</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
+    <OutputPath>bin\x86\Release\</OutputPath>
+    <DefineConstants>TRACE;NETFX_CORE</DefineConstants>
+    <Optimize>true</Optimize>
+    <NoWarn>;2008</NoWarn>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>x86</PlatformTarget>
+    <UseVSHostingProcess>false</UseVSHostingProcess>
+    <ErrorReport>prompt</ErrorReport>
+    <CodeAnalysisRuleSet>ExpressRules.ruleset</CodeAnalysisRuleSet>
+    <Prefer32Bit>true</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\JsonValueConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="TraceLevel.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
+    <VisualStudioVersion>12.0</VisualStudioVersion>
+  </PropertyGroup>
+  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.csproj b/Newtonsoft.Json/Newtonsoft.Json.csproj
new file mode 100644
index 0000000..8907265
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.csproj
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProjectGuid>{EEEA67F9-9089-481D-A4DC-0966DEC9FD7D}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>Newtonsoft.Json</RootNamespace>
+    <AssemblyName>Newtonsoft.Json</AssemblyName>
+    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\Net45\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Debug\Net45\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+    <UseVSHostingProcess>true</UseVSHostingProcess>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\Net45\</OutputPath>
+    <DefineConstants>TRACE;CODE_ANALYSIS</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>bin\Release\Net45\Newtonsoft.Json.xml</DocumentationFile>
+    <RunCodeAnalysis>true</RunCodeAnalysis>
+    <CodeAnalysisRuleSet>Newtonsoft.Json.ruleset</CodeAnalysisRuleSet>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Numerics" />
+    <Reference Include="System.Runtime.Serialization" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="Bson\BsonBinaryType.cs" />
+    <Compile Include="Bson\BsonBinaryWriter.cs" />
+    <Compile Include="Bson\BsonObjectId.cs" />
+    <Compile Include="Bson\BsonReader.cs" />
+    <Compile Include="Bson\BsonToken.cs" />
+    <Compile Include="Bson\BsonType.cs" />
+    <Compile Include="Bson\BsonWriter.cs" />
+    <Compile Include="ConstructorHandling.cs" />
+    <Compile Include="Converters\BinaryConverter.cs" />
+    <Compile Include="Converters\BsonObjectIdConverter.cs" />
+    <Compile Include="Converters\CustomCreationConverter.cs" />
+    <Compile Include="Converters\DataSetConverter.cs" />
+    <Compile Include="Converters\DataTableConverter.cs" />
+    <Compile Include="Converters\DateTimeConverterBase.cs" />
+    <Compile Include="Converters\DiscriminatedUnionConverter.cs" />
+    <Compile Include="Converters\EntityKeyMemberConverter.cs" />
+    <Compile Include="Converters\ExpandoObjectConverter.cs" />
+    <Compile Include="Converters\IsoDateTimeConverter.cs" />
+    <Compile Include="Converters\JavaScriptDateTimeConverter.cs" />
+    <Compile Include="Converters\JsonValueConverter.cs" />
+    <Compile Include="Converters\KeyValuePairConverter.cs" />
+    <Compile Include="Converters\RegexConverter.cs" />
+    <Compile Include="Converters\StringEnumConverter.cs" />
+    <Compile Include="Converters\VersionConverter.cs" />
+    <Compile Include="Converters\XmlNodeConverter.cs" />
+    <Compile Include="FloatParseHandling.cs" />
+    <Compile Include="DateFormatHandling.cs" />
+    <Compile Include="DateParseHandling.cs" />
+    <Compile Include="DateTimeZoneHandling.cs" />
+    <Compile Include="DefaultValueHandling.cs" />
+    <Compile Include="FloatFormatHandling.cs" />
+    <Compile Include="FormatterAssemblyStyle.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="IJsonLineInfo.cs" />
+    <Compile Include="JsonArrayAttribute.cs" />
+    <Compile Include="JsonConstructorAttribute.cs" />
+    <Compile Include="JsonContainerAttribute.cs" />
+    <Compile Include="JsonConvert.cs" />
+    <Compile Include="JsonConverter.cs" />
+    <Compile Include="JsonConverterAttribute.cs" />
+    <Compile Include="JsonConverterCollection.cs" />
+    <Compile Include="JsonDictionaryAttribute.cs" />
+    <Compile Include="JsonException.cs" />
+    <Compile Include="JsonExtensionDataAttribute.cs" />
+    <Compile Include="JsonIgnoreAttribute.cs" />
+    <Compile Include="JsonObjectAttribute.cs" />
+    <Compile Include="JsonPosition.cs" />
+    <Compile Include="JsonPropertyAttribute.cs" />
+    <Compile Include="JsonReader.cs" />
+    <Compile Include="JsonReaderException.cs" />
+    <Compile Include="JsonSerializationException.cs" />
+    <Compile Include="JsonSerializer.cs" />
+    <Compile Include="JsonSerializerSettings.cs" />
+    <Compile Include="JsonTextReader.cs" />
+    <Compile Include="JsonTextWriter.cs" />
+    <Compile Include="JsonToken.cs" />
+    <Compile Include="JsonValidatingReader.cs" />
+    <Compile Include="JsonWriter.cs" />
+    <Compile Include="JsonWriterException.cs" />
+    <Compile Include="Linq\Extensions.cs" />
+    <Compile Include="Linq\IJEnumerable.cs" />
+    <Compile Include="Linq\JArray.cs" />
+    <Compile Include="Linq\JConstructor.cs" />
+    <Compile Include="Linq\JContainer.cs" />
+    <Compile Include="Linq\JEnumerable.cs" />
+    <Compile Include="Linq\JObject.cs" />
+    <Compile Include="Linq\JsonPath\ArrayIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArrayMultipleIndexFilter.cs" />
+    <Compile Include="Linq\JsonPath\ArraySliceFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldFilter.cs" />
+    <Compile Include="Linq\JsonPath\FieldMultipleFilter.cs" />
+    <Compile Include="Linq\JsonPath\JPath.cs" />
+    <Compile Include="Linq\JProperty.cs" />
+    <Compile Include="Linq\JPropertyDescriptor.cs" />
+    <Compile Include="Linq\JPropertyKeyedCollection.cs" />
+    <Compile Include="Linq\JRaw.cs" />
+    <Compile Include="Linq\JsonPath\PathFilter.cs" />
+    <Compile Include="Linq\JsonPath\QueryExpression.cs" />
+    <Compile Include="Linq\JsonPath\QueryFilter.cs" />
+    <Compile Include="Linq\JsonPath\ScanFilter.cs" />
+    <Compile Include="Linq\JToken.cs" />
+    <Compile Include="Linq\JTokenEqualityComparer.cs" />
+    <Compile Include="Linq\JTokenReader.cs" />
+    <Compile Include="Linq\JTokenType.cs" />
+    <Compile Include="Linq\JTokenWriter.cs" />
+    <Compile Include="Linq\JValue.cs" />
+    <Compile Include="MemberSerialization.cs" />
+    <Compile Include="MetadataPropertyHandling.cs" />
+    <Compile Include="MissingMemberHandling.cs" />
+    <Compile Include="NullValueHandling.cs" />
+    <Compile Include="ObjectCreationHandling.cs" />
+    <Compile Include="PreserveReferencesHandling.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <Compile Include="ReferenceLoopHandling.cs" />
+    <Compile Include="Required.cs" />
+    <Compile Include="Schema\Extensions.cs" />
+    <Compile Include="Schema\JsonSchema.cs" />
+    <Compile Include="Schema\JsonSchemaBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaConstants.cs" />
+    <Compile Include="Schema\JsonSchemaException.cs" />
+    <Compile Include="Schema\JsonSchemaGenerator.cs" />
+    <Compile Include="Schema\JsonSchemaModel.cs" />
+    <Compile Include="Schema\JsonSchemaModelBuilder.cs" />
+    <Compile Include="Schema\JsonSchemaNode.cs" />
+    <Compile Include="Schema\JsonSchemaNodeCollection.cs" />
+    <Compile Include="Schema\JsonSchemaResolver.cs" />
+    <Compile Include="Schema\JsonSchemaType.cs" />
+    <Compile Include="Schema\JsonSchemaWriter.cs" />
+    <Compile Include="Schema\UndefinedSchemaIdHandling.cs" />
+    <Compile Include="Schema\ValidationEventArgs.cs" />
+    <Compile Include="Schema\ValidationEventHandler.cs" />
+    <Compile Include="SerializationBinder.cs" />
+    <Compile Include="Serialization\CachedAttributeGetter.cs" />
+    <Compile Include="Serialization\CamelCasePropertyNamesContractResolver.cs" />
+    <Compile Include="Serialization\DefaultContractResolver.cs" />
+    <Compile Include="Serialization\DefaultReferenceResolver.cs" />
+    <Compile Include="Serialization\DefaultSerializationBinder.cs" />
+    <Compile Include="Serialization\DiagnosticsTraceWriter.cs" />
+    <Compile Include="Serialization\DynamicValueProvider.cs" />
+    <Compile Include="Serialization\ErrorContext.cs" />
+    <Compile Include="Serialization\ErrorEventArgs.cs" />
+    <Compile Include="Serialization\ExpressionValueProvider.cs" />
+    <Compile Include="Serialization\IContractResolver.cs" />
+    <Compile Include="Serialization\IReferenceResolver.cs" />
+    <Compile Include="Serialization\ITraceWriter.cs" />
+    <Compile Include="Serialization\IValueProvider.cs" />
+    <Compile Include="Serialization\JsonArrayContract.cs" />
+    <Compile Include="Serialization\JsonContainerContract.cs" />
+    <Compile Include="Serialization\JsonContract.cs" />
+    <Compile Include="Serialization\JsonDictionaryContract.cs" />
+    <Compile Include="Serialization\JsonDynamicContract.cs" />
+    <Compile Include="Serialization\JsonFormatterConverter.cs" />
+    <Compile Include="Serialization\JsonISerializableContract.cs" />
+    <Compile Include="Serialization\JsonLinqContract.cs" />
+    <Compile Include="Serialization\JsonObjectContract.cs" />
+    <Compile Include="Serialization\JsonPrimitiveContract.cs" />
+    <Compile Include="Serialization\JsonProperty.cs" />
+    <Compile Include="Serialization\JsonPropertyCollection.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalBase.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalReader.cs" />
+    <Compile Include="Serialization\JsonSerializerInternalWriter.cs" />
+    <Compile Include="Serialization\JsonSerializerProxy.cs" />
+    <Compile Include="Serialization\JsonStringContract.cs" />
+    <Compile Include="Serialization\JsonTypeReflector.cs" />
+    <Compile Include="Serialization\LateBoundMetadataTypeAttribute.cs" />
+    <Compile Include="Serialization\MemoryTraceWriter.cs" />
+    <Compile Include="Serialization\ObjectConstructor.cs" />
+    <Compile Include="Serialization\OnErrorAttribute.cs" />
+    <Compile Include="Serialization\ReflectionValueProvider.cs" />
+    <Compile Include="Serialization\TraceJsonReader.cs" />
+    <Compile Include="Serialization\TraceJsonWriter.cs" />
+    <Compile Include="StringEscapeHandling.cs" />
+    <Compile Include="TraceLevel.cs" />
+    <Compile Include="TypeNameHandling.cs" />
+    <Compile Include="Utilities\Base64Encoder.cs" />
+    <Compile Include="Utilities\BidirectionalDictionary.cs" />
+    <Compile Include="Utilities\CollectionUtils.cs" />
+    <Compile Include="Utilities\CollectionWrapper.cs" />
+    <Compile Include="Utilities\ConvertUtils.cs" />
+    <Compile Include="Utilities\DateTimeParser.cs" />
+    <Compile Include="Utilities\DateTimeUtils.cs" />
+    <Compile Include="Utilities\DictionaryWrapper.cs" />
+    <Compile Include="Utilities\DynamicProxy.cs" />
+    <Compile Include="Utilities\DynamicProxyMetaObject.cs" />
+    <Compile Include="Utilities\DynamicReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\DynamicUtils.cs" />
+    <Compile Include="Utilities\DynamicWrapper.cs" />
+    <Compile Include="Utilities\EnumUtils.cs" />
+    <Compile Include="Utilities\EnumValue.cs" />
+    <Compile Include="Utilities\EnumValues.cs" />
+    <Compile Include="Utilities\ExpressionReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\FSharpUtils.cs" />
+    <Compile Include="Utilities\ILGeneratorExtensions.cs" />
+    <Compile Include="Utilities\ImmutableCollectionsUtils.cs" />
+    <Compile Include="Utilities\JavaScriptUtils.cs" />
+    <Compile Include="Utilities\LateBoundReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\LinqBridge.cs" />
+    <Compile Include="Utilities\MathUtils.cs" />
+    <Compile Include="Utilities\MethodCall.cs" />
+    <Compile Include="Utilities\MiscellaneousUtils.cs" />
+    <Compile Include="Utilities\ReflectionDelegateFactory.cs" />
+    <Compile Include="Utilities\ReflectionUtils.cs" />
+    <Compile Include="Utilities\StringBuffer.cs" />
+    <Compile Include="Utilities\StringReference.cs" />
+    <Compile Include="Utilities\StringUtils.cs" />
+    <Compile Include="Utilities\ThreadSafeStore.cs" />
+    <Compile Include="Utilities\TypeExtensions.cs" />
+    <Compile Include="Utilities\ValidationUtils.cs" />
+    <Compile Include="WriteState.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Dynamic.snk" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/Newtonsoft.Json/Newtonsoft.Json.ruleset b/Newtonsoft.Json/Newtonsoft.Json.ruleset
new file mode 100644
index 0000000..cba89c3
--- /dev/null
+++ b/Newtonsoft.Json/Newtonsoft.Json.ruleset
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RuleSet Name="Newtonsoft.Json.ruleset" ToolsVersion="12.0">
+  <IncludeAll Action="Warning" />
+  <Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
+    <Rule Id="CA1000" Action="None" />
+    <Rule Id="CA1001" Action="None" />
+    <Rule Id="CA1002" Action="None" />
+    <Rule Id="CA1003" Action="None" />
+    <Rule Id="CA1004" Action="None" />
+    <Rule Id="CA1005" Action="None" />
+    <Rule Id="CA1006" Action="None" />
+    <Rule Id="CA1007" Action="None" />
+    <Rule Id="CA1008" Action="None" />
+    <Rule Id="CA1009" Action="None" />
+    <Rule Id="CA1010" Action="None" />
+    <Rule Id="CA1011" Action="None" />
+    <Rule Id="CA1012" Action="None" />
+    <Rule Id="CA1013" Action="None" />
+    <Rule Id="CA1014" Action="None" />
+    <Rule Id="CA1016" Action="None" />
+    <Rule Id="CA1017" Action="None" />
+    <Rule Id="CA1018" Action="None" />
+    <Rule Id="CA1019" Action="None" />
+    <Rule Id="CA1020" Action="None" />
+    <Rule Id="CA1021" Action="None" />
+    <Rule Id="CA1023" Action="None" />
+    <Rule Id="CA1024" Action="None" />
+    <Rule Id="CA1025" Action="None" />
+    <Rule Id="CA1026" Action="None" />
+    <Rule Id="CA1027" Action="None" />
+    <Rule Id="CA1028" Action="None" />
+    <Rule Id="CA1030" Action="None" />
+    <Rule Id="CA1031" Action="None" />
+    <Rule Id="CA1032" Action="None" />
+    <Rule Id="CA1033" Action="None" />
+    <Rule Id="CA1034" Action="None" />
+    <Rule Id="CA1035" Action="None" />
+    <Rule Id="CA1036" Action="None" />
+    <Rule Id="CA1038" Action="None" />
+    <Rule Id="CA1039" Action="None" />
+    <Rule Id="CA1040" Action="None" />
+    <Rule Id="CA1041" Action="None" />
+    <Rule Id="CA1043" Action="None" />
+    <Rule Id="CA1044" Action="None" />
+    <Rule Id="CA1045" Action="None" />
+    <Rule Id="CA1046" Action="None" />
+    <Rule Id="CA1047" Action="None" />
+    <Rule Id="CA1048" Action="None" />
+    <Rule Id="CA1049" Action="None" />
+    <Rule Id="CA1050" Action="None" />
+    <Rule Id="CA1051" Action="None" />
+    <Rule Id="CA1052" Action="None" />
+    <Rule Id="CA1053" Action="None" />
+    <Rule Id="CA1054" Action="None" />
+    <Rule Id="CA1055" Action="None" />
+    <Rule Id="CA1056" Action="None" />
+    <Rule Id="CA1057" Action="None" />
+    <Rule Id="CA1058" Action="None" />
+    <Rule Id="CA1059" Action="None" />
+    <Rule Id="CA1060" Action="None" />
+    <Rule Id="CA1061" Action="None" />
+    <Rule Id="CA1062" Action="None" />
+    <Rule Id="CA1063" Action="None" />
+    <Rule Id="CA1064" Action="None" />
+    <Rule Id="CA1065" Action="None" />
+    <Rule Id="CA1300" Action="None" />
+    <Rule Id="CA1301" Action="None" />
+    <Rule Id="CA1302" Action="None" />
+    <Rule Id="CA1303" Action="None" />
+    <Rule Id="CA1304" Action="Error" />
+    <Rule Id="CA1305" Action="Error" />
+    <Rule Id="CA1306" Action="None" />
+    <Rule Id="CA1307" Action="None" />
+    <Rule Id="CA1308" Action="None" />
+    <Rule Id="CA1309" Action="None" />
+    <Rule Id="CA1400" Action="None" />
+    <Rule Id="CA1401" Action="None" />
+    <Rule Id="CA1402" Action="None" />
+    <Rule Id="CA1403" Action="None" />
+    <Rule Id="CA1404" Action="None" />
+    <Rule Id="CA1405" Action="None" />
+    <Rule Id="CA1406" Action="None" />
+    <Rule Id="CA1407" Action="None" />
+    <Rule Id="CA1408" Action="None" />
+    <Rule Id="CA1409" Action="None" />
+    <Rule Id="CA1410" Action="None" />
+    <Rule Id="CA1411" Action="None" />
+    <Rule Id="CA1412" Action="None" />
+    <Rule Id="CA1413" Action="None" />
+    <Rule Id="CA1414" Action="None" />
+    <Rule Id="CA1415" Action="None" />
+    <Rule Id="CA1500" Action="None" />
+    <Rule Id="CA1501" Action="None" />
+    <Rule Id="CA1502" Action="None" />
+    <Rule Id="CA1504" Action="None" />
+    <Rule Id="CA1505" Action="None" />
+    <Rule Id="CA1506" Action="None" />
+    <Rule Id="CA1600" Action="None" />
+    <Rule Id="CA1601" Action="None" />
+    <Rule Id="CA1700" Action="None" />
+    <Rule Id="CA1701" Action="None" />
+    <Rule Id="CA1702" Action="None" />
+    <Rule Id="CA1703" Action="None" />
+    <Rule Id="CA1704" Action="None" />
+    <Rule Id="CA1707" Action="None" />
+    <Rule Id="CA1708" Action="None" />
+    <Rule Id="CA1709" Action="None" />
+    <Rule Id="CA1710" Action="None" />
+    <Rule Id="CA1711" Action="None" />
+    <Rule Id="CA1712" Action="None" />
+    <Rule Id="CA1713" Action="None" />
+    <Rule Id="CA1714" Action="None" />
+    <Rule Id="CA1715" Action="None" />
+    <Rule Id="CA1716" Action="None" />
+    <Rule Id="CA1717" Action="None" />
+    <Rule Id="CA1719" Action="None" />
+    <Rule Id="CA1720" Action="None" />
+    <Rule Id="CA1721" Action="None" />
+    <Rule Id="CA1722" Action="None" />
+    <Rule Id="CA1724" Action="None" />
+    <Rule Id="CA1725" Action="None" />
+    <Rule Id="CA1726" Action="None" />
+    <Rule Id="CA1800" Action="None" />
+    <Rule Id="CA1801" Action="None" />
+    <Rule Id="CA1802" Action="None" />
+    <Rule Id="CA1804" Action="None" />
+    <Rule Id="CA1806" Action="None" />
+    <Rule Id="CA1809" Action="None" />
+    <Rule Id="CA1810" Action="None" />
+    <Rule Id="CA1811" Action="None" />
+    <Rule Id="CA1812" Action="None" />
+    <Rule Id="CA1813" Action="None" />
+    <Rule Id="CA1814" Action="None" />
+    <Rule Id="CA1815" Action="None" />
+    <Rule Id="CA1816" Action="None" />
+    <Rule Id="CA1819" Action="None" />
+    <Rule Id="CA1820" Action="None" />
+    <Rule Id="CA1821" Action="None" />
+    <Rule Id="CA1822" Action="None" />
+    <Rule Id="CA1823" Action="None" />
+    <Rule Id="CA1824" Action="None" />
+    <Rule Id="CA1900" Action="None" />
+    <Rule Id="CA1901" Action="None" />
+    <Rule Id="CA1903" Action="Error" />
+    <Rule Id="CA2000" Action="None" />
+    <Rule Id="CA2001" Action="None" />
+    <Rule Id="CA2002" Action="None" />
+    <Rule Id="CA2003" Action="None" />
+    <Rule Id="CA2004" Action="None" />
+    <Rule Id="CA2006" Action="None" />
+    <Rule Id="CA2100" Action="None" />
+    <Rule Id="CA2101" Action="None" />
+    <Rule Id="CA2102" Action="None" />
+    <Rule Id="CA2103" Action="None" />
+    <Rule Id="CA2104" Action="None" />
+    <Rule Id="CA2105" Action="None" />
+    <Rule Id="CA2106" Action="None" />
+    <Rule Id="CA2107" Action="None" />
+    <Rule Id="CA2108" Action="None" />
+    <Rule Id="CA2109" Action="None" />
+    <Rule Id="CA2111" Action="None" />
+    <Rule Id="CA2112" Action="None" />
+    <Rule Id="CA2114" Action="None" />
+    <Rule Id="CA2115" Action="None" />
+    <Rule Id="CA2116" Action="None" />
+    <Rule Id="CA2117" Action="None" />
+    <Rule Id="CA2118" Action="None" />
+    <Rule Id="CA2119" Action="None" />
+    <Rule Id="CA2120" Action="None" />
+    <Rule Id="CA2121" Action="None" />
+    <Rule Id="CA2122" Action="None" />
+    <Rule Id="CA2123" Action="None" />
+    <Rule Id="CA2124" Action="None" />
+    <Rule Id="CA2126" Action="None" />
+    <Rule Id="CA2130" Action="None" />
+    <Rule Id="CA2131" Action="None" />
+    <Rule Id="CA2132" Action="None" />
+    <Rule Id="CA2133" Action="None" />
+    <Rule Id="CA2134" Action="None" />
+    <Rule Id="CA2135" Action="None" />
+    <Rule Id="CA2136" Action="None" />
+    <Rule Id="CA2137" Action="None" />
+    <Rule Id="CA2138" Action="None" />
+    <Rule Id="CA2139" Action="None" />
+    <Rule Id="CA2140" Action="None" />
+    <Rule Id="CA2141" Action="None" />
+    <Rule Id="CA2142" Action="None" />
+    <Rule Id="CA2143" Action="None" />
+    <Rule Id="CA2144" Action="None" />
+    <Rule Id="CA2145" Action="None" />
+    <Rule Id="CA2146" Action="None" />
+    <Rule Id="CA2147" Action="None" />
+    <Rule Id="CA2149" Action="None" />
+    <Rule Id="CA2200" Action="None" />
+    <Rule Id="CA2201" Action="None" />
+    <Rule Id="CA2202" Action="None" />
+    <Rule Id="CA2204" Action="None" />
+    <Rule Id="CA2205" Action="None" />
+    <Rule Id="CA2207" Action="None" />
+    <Rule Id="CA2208" Action="None" />
+    <Rule Id="CA2210" Action="None" />
+    <Rule Id="CA2211" Action="None" />
+    <Rule Id="CA2212" Action="None" />
+    <Rule Id="CA2213" Action="None" />
+    <Rule Id="CA2214" Action="None" />
+    <Rule Id="CA2215" Action="None" />
+    <Rule Id="CA2216" Action="None" />
+    <Rule Id="CA2217" Action="None" />
+    <Rule Id="CA2218" Action="None" />
+    <Rule Id="CA2219" Action="None" />
+    <Rule Id="CA2220" Action="None" />
+    <Rule Id="CA2221" Action="None" />
+    <Rule Id="CA2222" Action="None" />
+    <Rule Id="CA2223" Action="None" />
+    <Rule Id="CA2224" Action="None" />
+    <Rule Id="CA2225" Action="None" />
+    <Rule Id="CA2226" Action="None" />
+    <Rule Id="CA2227" Action="None" />
+    <Rule Id="CA2228" Action="None" />
+    <Rule Id="CA2229" Action="None" />
+    <Rule Id="CA2230" Action="None" />
+    <Rule Id="CA2231" Action="None" />
+    <Rule Id="CA2232" Action="None" />
+    <Rule Id="CA2233" Action="None" />
+    <Rule Id="CA2234" Action="None" />
+    <Rule Id="CA2235" Action="None" />
+    <Rule Id="CA2236" Action="None" />
+    <Rule Id="CA2237" Action="None" />
+    <Rule Id="CA2238" Action="None" />
+    <Rule Id="CA2239" Action="None" />
+    <Rule Id="CA2240" Action="None" />
+    <Rule Id="CA2241" Action="None" />
+    <Rule Id="CA2242" Action="None" />
+    <Rule Id="CA2243" Action="None" />
+  </Rules>
+</RuleSet>
\ No newline at end of file
diff --git a/Newtonsoft.Json/NullValueHandling.cs b/Newtonsoft.Json/NullValueHandling.cs
new file mode 100644
index 0000000..2b99b12
--- /dev/null
+++ b/Newtonsoft.Json/NullValueHandling.cs
@@ -0,0 +1,47 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies null value handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeNullValueHandlingObject" title="NullValueHandling Class" />
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeNullValueHandlingExample" title="NullValueHandling Ignore Example" />
+    /// </example>
+    public enum NullValueHandling
+    {
+        /// <summary>
+        /// Include null values when serializing and deserializing objects.
+        /// </summary>
+        Include = 0,
+
+        /// <summary>
+        /// Ignore null values when serializing and deserializing objects.
+        /// </summary>
+        Ignore = 1
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/ObjectCreationHandling.cs b/Newtonsoft.Json/ObjectCreationHandling.cs
new file mode 100644
index 0000000..993ad07
--- /dev/null
+++ b/Newtonsoft.Json/ObjectCreationHandling.cs
@@ -0,0 +1,48 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how object creation is handled by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum ObjectCreationHandling
+    {
+        /// <summary>
+        /// Reuse existing objects, create new objects when needed.
+        /// </summary>
+        Auto = 0,
+
+        /// <summary>
+        /// Only reuse existing objects.
+        /// </summary>
+        Reuse = 1,
+
+        /// <summary>
+        /// Always create new objects.
+        /// </summary>
+        Replace = 2
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/PreserveReferencesHandling.cs b/Newtonsoft.Json/PreserveReferencesHandling.cs
new file mode 100644
index 0000000..639e3c5
--- /dev/null
+++ b/Newtonsoft.Json/PreserveReferencesHandling.cs
@@ -0,0 +1,62 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies reference handling options for the <see cref="JsonSerializer"/>.
+    /// Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement ISerializable.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="PreservingObjectReferencesOn" title="Preserve Object References" />       
+    /// </example>
+    [Flags]
+    public enum PreserveReferencesHandling
+    {
+        /// <summary>
+        /// Do not preserve references when serializing types.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// Preserve references when serializing into a JSON object structure.
+        /// </summary>
+        Objects = 1,
+
+        /// <summary>
+        /// Preserve references when serializing into a JSON array structure.
+        /// </summary>
+        Arrays = 2,
+
+        /// <summary>
+        /// Preserve references when serializing.
+        /// </summary>
+        All = Objects | Arrays
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Properties/AssemblyInfo.cs b/Newtonsoft.Json/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..479dd8d
--- /dev/null
+++ b/Newtonsoft.Json/Properties/AssemblyInfo.cs
@@ -0,0 +1,94 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Security;
+
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+#if PORTABLE40
+[assembly: AssemblyTitle("Json.NET Portable .NET 4.0")]
+#elif PORTABLE
+[assembly: AssemblyTitle("Json.NET Portable")]
+#elif NETFX_CORE
+[assembly: AssemblyTitle("Json.NET WinRT")]
+#elif NET20
+[assembly: AssemblyTitle("Json.NET .NET 2.0")]
+[assembly: AllowPartiallyTrustedCallers]
+#elif NET35
+[assembly: AssemblyTitle("Json.NET .NET 3.5")]
+[assembly: AllowPartiallyTrustedCallers]
+#elif NET40
+[assembly: AssemblyTitle("Json.NET .NET 4.0")]
+[assembly: AllowPartiallyTrustedCallers]
+#else
+[assembly: AssemblyTitle("Json.NET")]
+[assembly: AllowPartiallyTrustedCallers]
+#endif
+
+#if !SIGNED
+
+#else
+[assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")]
+#endif
+
+[assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")]
+[assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Newtonsoft")]
+[assembly: AssemblyProduct("Json.NET")]
+[assembly: AssemblyCopyright("Copyright � James Newton-King 2008")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+#if !(PORTABLE40 || PORTABLE)
+// Setting ComVisible to false makes the types in this assembly not visible 
+// to COM componenets.  If you need to access a type in this assembly from 
+// COM, set the ComVisible attribute to true on that type.
+
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+
+[assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")]
+#endif
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("6.0.0.0")]
+[assembly: AssemblyFileVersion("6.0.3.17227")]
+[assembly: CLSCompliant(true)]
diff --git a/Newtonsoft.Json/ReadMe-AxCrypt.txt b/Newtonsoft.Json/ReadMe-AxCrypt.txt
new file mode 100644
index 0000000..b030ef2
--- /dev/null
+++ b/Newtonsoft.Json/ReadMe-AxCrypt.txt
@@ -0,0 +1,19 @@
+This is Json.NET by James Newton-King version 6.0.3
+
+Json60r3.zip
+MD5 adc001d9c0681d864396cfda910d577f
+SHA1 b676186555ad2987f4f32cd52b69d25089291ee4
+
+The source code is minimally modified in order to compile. The project is modified to
+target the .NET 4.0 profile instead of the client profile to be consistent with the
+other projects in the Windows build.
+
+For consistency, the assembly is signed with the Axantum strong name key if available.
+
+The unit tests are not included, since AxCrypt has it's own unit tests, and to keep the
+payload to a reasonable level. It's essentially a binary dependency, the only reason to
+include the source code is to ensure that it can be rebuilt from source code only, which
+is important for a cryptographic application.
+
+Axantum Software AB
+2014-05-31
\ No newline at end of file
diff --git a/Newtonsoft.Json/ReferenceLoopHandling.cs b/Newtonsoft.Json/ReferenceLoopHandling.cs
new file mode 100644
index 0000000..03e407f
--- /dev/null
+++ b/Newtonsoft.Json/ReferenceLoopHandling.cs
@@ -0,0 +1,52 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies reference loop handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public enum ReferenceLoopHandling
+    {
+        /// <summary>
+        /// Throw a <see cref="JsonSerializationException"/> when a loop is encountered.
+        /// </summary>
+        Error = 0,
+
+        /// <summary>
+        /// Ignore loop references and do not serialize.
+        /// </summary>
+        Ignore = 1,
+
+        /// <summary>
+        /// Serialize loop references.
+        /// </summary>
+        Serialize = 2
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Required.cs b/Newtonsoft.Json/Required.cs
new file mode 100644
index 0000000..1d121a0
--- /dev/null
+++ b/Newtonsoft.Json/Required.cs
@@ -0,0 +1,48 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Indicating whether a property is required.
+    /// </summary>
+    public enum Required
+    {
+        /// <summary>
+        /// The property is not required. The default state.
+        /// </summary>
+        Default,
+
+        /// <summary>
+        /// The property must be defined in JSON but can be a null value.
+        /// </summary>
+        AllowNull,
+
+        /// <summary>
+        /// The property must be defined in JSON and cannot be a null value.
+        /// </summary>
+        Always
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/Extensions.cs b/Newtonsoft.Json/Schema/Extensions.cs
new file mode 100644
index 0000000..91bc7b0
--- /dev/null
+++ b/Newtonsoft.Json/Schema/Extensions.cs
@@ -0,0 +1,104 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Contains the JSON schema extension methods.
+    /// </summary>
+    public static class Extensions
+    {
+        /// <summary>
+        /// Determines whether the <see cref="JToken"/> is valid.
+        /// </summary>
+        /// <param name="source">The source <see cref="JToken"/> to test.</param>
+        /// <param name="schema">The schema to test with.</param>
+        /// <returns>
+        /// 	<c>true</c> if the specified <see cref="JToken"/> is valid; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsValid(this JToken source, JsonSchema schema)
+        {
+            bool valid = true;
+            source.Validate(schema, (sender, args) => { valid = false; });
+            return valid;
+        }
+
+        /// <summary>
+        /// Determines whether the <see cref="JToken"/> is valid.
+        /// </summary>
+        /// <param name="source">The source <see cref="JToken"/> to test.</param>
+        /// <param name="schema">The schema to test with.</param>
+        /// <param name="errorMessages">When this method returns, contains any error messages generated while validating. </param>
+        /// <returns>
+        /// 	<c>true</c> if the specified <see cref="JToken"/> is valid; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsValid(this JToken source, JsonSchema schema, out IList<string> errorMessages)
+        {
+            IList<string> errors = new List<string>();
+
+            source.Validate(schema, (sender, args) => errors.Add(args.Message));
+
+            errorMessages = errors;
+            return (errorMessages.Count == 0);
+        }
+
+        /// <summary>
+        /// Validates the specified <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="source">The source <see cref="JToken"/> to test.</param>
+        /// <param name="schema">The schema to test with.</param>
+        public static void Validate(this JToken source, JsonSchema schema)
+        {
+            source.Validate(schema, null);
+        }
+
+        /// <summary>
+        /// Validates the specified <see cref="JToken"/>.
+        /// </summary>
+        /// <param name="source">The source <see cref="JToken"/> to test.</param>
+        /// <param name="schema">The schema to test with.</param>
+        /// <param name="validationEventHandler">The validation event handler.</param>
+        public static void Validate(this JToken source, JsonSchema schema, ValidationEventHandler validationEventHandler)
+        {
+            ValidationUtils.ArgumentNotNull(source, "source");
+            ValidationUtils.ArgumentNotNull(schema, "schema");
+
+            using (JsonValidatingReader reader = new JsonValidatingReader(source.CreateReader()))
+            {
+                reader.Schema = schema;
+                if (validationEventHandler != null)
+                    reader.ValidationEventHandler += validationEventHandler;
+
+                while (reader.Read())
+                {
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchema.cs b/Newtonsoft.Json/Schema/JsonSchema.cs
new file mode 100644
index 0000000..51fbde0
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchema.cs
@@ -0,0 +1,350 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// An in-memory representation of a JSON Schema.
+    /// </summary>
+    public class JsonSchema
+    {
+        /// <summary>
+        /// Gets or sets the id.
+        /// </summary>
+        public string Id { get; set; }
+
+        /// <summary>
+        /// Gets or sets the title.
+        /// </summary>
+        public string Title { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether the object is required.
+        /// </summary>
+        public bool? Required { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether the object is read only.
+        /// </summary>
+        public bool? ReadOnly { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether the object is visible to users.
+        /// </summary>
+        public bool? Hidden { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether the object is transient.
+        /// </summary>
+        public bool? Transient { get; set; }
+
+        /// <summary>
+        /// Gets or sets the description of the object.
+        /// </summary>
+        public string Description { get; set; }
+
+        /// <summary>
+        /// Gets or sets the types of values allowed by the object.
+        /// </summary>
+        /// <value>The type.</value>
+        public JsonSchemaType? Type { get; set; }
+
+        /// <summary>
+        /// Gets or sets the pattern.
+        /// </summary>
+        /// <value>The pattern.</value>
+        public string Pattern { get; set; }
+
+        /// <summary>
+        /// Gets or sets the minimum length.
+        /// </summary>
+        /// <value>The minimum length.</value>
+        public int? MinimumLength { get; set; }
+
+        /// <summary>
+        /// Gets or sets the maximum length.
+        /// </summary>
+        /// <value>The maximum length.</value>
+        public int? MaximumLength { get; set; }
+
+        /// <summary>
+        /// Gets or sets a number that the value should be divisble by.
+        /// </summary>
+        /// <value>A number that the value should be divisble by.</value>
+        public double? DivisibleBy { get; set; }
+
+        /// <summary>
+        /// Gets or sets the minimum.
+        /// </summary>
+        /// <value>The minimum.</value>
+        public double? Minimum { get; set; }
+
+        /// <summary>
+        /// Gets or sets the maximum.
+        /// </summary>
+        /// <value>The maximum.</value>
+        public double? Maximum { get; set; }
+
+        /// <summary>
+        /// Gets or sets a flag indicating whether the value can not equal the number defined by the "minimum" attribute.
+        /// </summary>
+        /// <value>A flag indicating whether the value can not equal the number defined by the "minimum" attribute.</value>
+        public bool? ExclusiveMinimum { get; set; }
+
+        /// <summary>
+        /// Gets or sets a flag indicating whether the value can not equal the number defined by the "maximum" attribute.
+        /// </summary>
+        /// <value>A flag indicating whether the value can not equal the number defined by the "maximum" attribute.</value>
+        public bool? ExclusiveMaximum { get; set; }
+
+        /// <summary>
+        /// Gets or sets the minimum number of items.
+        /// </summary>
+        /// <value>The minimum number of items.</value>
+        public int? MinimumItems { get; set; }
+
+        /// <summary>
+        /// Gets or sets the maximum number of items.
+        /// </summary>
+        /// <value>The maximum number of items.</value>
+        public int? MaximumItems { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="JsonSchema"/> of items.
+        /// </summary>
+        /// <value>The <see cref="JsonSchema"/> of items.</value>
+        public IList<JsonSchema> Items { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether items in an array are validated using the <see cref="JsonSchema"/> instance at their array position from <see cref="JsonSchema.Items"/>.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if items are validated using their array position; otherwise, <c>false</c>.
+        /// </value>
+        public bool PositionalItemsValidation { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="JsonSchema"/> of additional items.
+        /// </summary>
+        /// <value>The <see cref="JsonSchema"/> of additional items.</value>
+        public JsonSchema AdditionalItems { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether additional items are allowed.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if additional items are allowed; otherwise, <c>false</c>.
+        /// </value>
+        public bool AllowAdditionalItems { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether the array items must be unique.
+        /// </summary>
+        public bool UniqueItems { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="JsonSchema"/> of properties.
+        /// </summary>
+        /// <value>The <see cref="JsonSchema"/> of properties.</value>
+        public IDictionary<string, JsonSchema> Properties { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="JsonSchema"/> of additional properties.
+        /// </summary>
+        /// <value>The <see cref="JsonSchema"/> of additional properties.</value>
+        public JsonSchema AdditionalProperties { get; set; }
+
+        /// <summary>
+        /// Gets or sets the pattern properties.
+        /// </summary>
+        /// <value>The pattern properties.</value>
+        public IDictionary<string, JsonSchema> PatternProperties { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether additional properties are allowed.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if additional properties are allowed; otherwise, <c>false</c>.
+        /// </value>
+        public bool AllowAdditionalProperties { get; set; }
+
+        /// <summary>
+        /// Gets or sets the required property if this property is present.
+        /// </summary>
+        /// <value>The required property if this property is present.</value>
+        public string Requires { get; set; }
+
+        /// <summary>
+        /// Gets or sets the a collection of valid enum values allowed.
+        /// </summary>
+        /// <value>A collection of valid enum values allowed.</value>
+        public IList<JToken> Enum { get; set; }
+
+        /// <summary>
+        /// Gets or sets disallowed types.
+        /// </summary>
+        /// <value>The disallow types.</value>
+        public JsonSchemaType? Disallow { get; set; }
+
+        /// <summary>
+        /// Gets or sets the default value.
+        /// </summary>
+        /// <value>The default value.</value>
+        public JToken Default { get; set; }
+
+        /// <summary>
+        /// Gets or sets the collection of <see cref="JsonSchema"/> that this schema extends.
+        /// </summary>
+        /// <value>The collection of <see cref="JsonSchema"/> that this schema extends.</value>
+        public IList<JsonSchema> Extends { get; set; }
+
+        /// <summary>
+        /// Gets or sets the format.
+        /// </summary>
+        /// <value>The format.</value>
+        public string Format { get; set; }
+
+        internal string Location { get; set; }
+
+        private readonly string _internalId = Guid.NewGuid().ToString("N");
+
+        internal string InternalId
+        {
+            get { return _internalId; }
+        }
+
+        // if this is set then this schema instance is just a deferred reference
+        // and will be replaced when the schema reference is resolved
+        internal string DeferredReference { get; set; }
+        internal bool ReferencesResolved { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchema"/> class.
+        /// </summary>
+        public JsonSchema()
+        {
+            AllowAdditionalProperties = true;
+            AllowAdditionalItems = true;
+        }
+
+        /// <summary>
+        /// Reads a <see cref="JsonSchema"/> from the specified <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> containing the JSON Schema to read.</param>
+        /// <returns>The <see cref="JsonSchema"/> object representing the JSON Schema.</returns>
+        public static JsonSchema Read(JsonReader reader)
+        {
+            return Read(reader, new JsonSchemaResolver());
+        }
+
+        /// <summary>
+        /// Reads a <see cref="JsonSchema"/> from the specified <see cref="JsonReader"/>.
+        /// </summary>
+        /// <param name="reader">The <see cref="JsonReader"/> containing the JSON Schema to read.</param>
+        /// <param name="resolver">The <see cref="JsonSchemaResolver"/> to use when resolving schema references.</param>
+        /// <returns>The <see cref="JsonSchema"/> object representing the JSON Schema.</returns>
+        public static JsonSchema Read(JsonReader reader, JsonSchemaResolver resolver)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+            ValidationUtils.ArgumentNotNull(resolver, "resolver");
+
+            JsonSchemaBuilder builder = new JsonSchemaBuilder(resolver);
+            return builder.Read(reader);
+        }
+
+        /// <summary>
+        /// Load a <see cref="JsonSchema"/> from a string that contains schema JSON.
+        /// </summary>
+        /// <param name="json">A <see cref="String"/> that contains JSON.</param>
+        /// <returns>A <see cref="JsonSchema"/> populated from the string that contains JSON.</returns>
+        public static JsonSchema Parse(string json)
+        {
+            return Parse(json, new JsonSchemaResolver());
+        }
+
+        /// <summary>
+        /// Parses the specified json.
+        /// </summary>
+        /// <param name="json">The json.</param>
+        /// <param name="resolver">The resolver.</param>
+        /// <returns>A <see cref="JsonSchema"/> populated from the string that contains JSON.</returns>
+        public static JsonSchema Parse(string json, JsonSchemaResolver resolver)
+        {
+            ValidationUtils.ArgumentNotNull(json, "json");
+
+            using (JsonReader reader = new JsonTextReader(new StringReader(json)))
+            {
+                return Read(reader, resolver);
+            }
+        }
+
+        /// <summary>
+        /// Writes this schema to a <see cref="JsonWriter"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        public void WriteTo(JsonWriter writer)
+        {
+            WriteTo(writer, new JsonSchemaResolver());
+        }
+
+        /// <summary>
+        /// Writes this schema to a <see cref="JsonWriter"/> using the specified <see cref="JsonSchemaResolver"/>.
+        /// </summary>
+        /// <param name="writer">A <see cref="JsonWriter"/> into which this method will write.</param>
+        /// <param name="resolver">The resolver used.</param>
+        public void WriteTo(JsonWriter writer, JsonSchemaResolver resolver)
+        {
+            ValidationUtils.ArgumentNotNull(writer, "writer");
+            ValidationUtils.ArgumentNotNull(resolver, "resolver");
+
+            JsonSchemaWriter schemaWriter = new JsonSchemaWriter(writer, resolver);
+            schemaWriter.WriteSchema(this);
+        }
+
+        /// <summary>
+        /// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
+        /// </returns>
+        public override string ToString()
+        {
+            StringWriter writer = new StringWriter(CultureInfo.InvariantCulture);
+            JsonTextWriter jsonWriter = new JsonTextWriter(writer);
+            jsonWriter.Formatting = Formatting.Indented;
+
+            WriteTo(jsonWriter);
+
+            return writer.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs b/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs
new file mode 100644
index 0000000..c5120ab
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaBuilder.cs
@@ -0,0 +1,448 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using Newtonsoft.Json.Serialization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaBuilder
+    {
+        private readonly IList<JsonSchema> _stack;
+        private readonly JsonSchemaResolver _resolver;
+        private readonly IDictionary<string, JsonSchema> _documentSchemas;
+        private JsonSchema _currentSchema;
+        private JObject _rootSchema;
+
+        public JsonSchemaBuilder(JsonSchemaResolver resolver)
+        {
+            _stack = new List<JsonSchema>();
+            _documentSchemas = new Dictionary<string, JsonSchema>();
+            _resolver = resolver;
+        }
+
+        private void Push(JsonSchema value)
+        {
+            _currentSchema = value;
+            _stack.Add(value);
+            _resolver.LoadedSchemas.Add(value);
+            _documentSchemas.Add(value.Location, value);
+        }
+
+        private JsonSchema Pop()
+        {
+            JsonSchema poppedSchema = _currentSchema;
+            _stack.RemoveAt(_stack.Count - 1);
+            _currentSchema = _stack.LastOrDefault();
+
+            return poppedSchema;
+        }
+
+        private JsonSchema CurrentSchema
+        {
+            get { return _currentSchema; }
+        }
+
+        internal JsonSchema Read(JsonReader reader)
+        {
+            JToken schemaToken = JToken.ReadFrom(reader);
+
+            _rootSchema = schemaToken as JObject;
+
+            JsonSchema schema = BuildSchema(schemaToken);
+
+            ResolveReferences(schema);
+
+            return schema;
+        }
+
+        private string UnescapeReference(string reference)
+        {
+            return Uri.UnescapeDataString(reference).Replace("~1", "/").Replace("~0", "~");
+        }
+
+        private JsonSchema ResolveReferences(JsonSchema schema)
+        {
+            if (schema.DeferredReference != null)
+            {
+                string reference = schema.DeferredReference;
+
+                bool locationReference = (reference.StartsWith("#", StringComparison.OrdinalIgnoreCase));
+                if (locationReference)
+                    reference = UnescapeReference(reference);
+
+                JsonSchema resolvedSchema = _resolver.GetSchema(reference);
+
+                if (resolvedSchema == null)
+                {
+                    if (locationReference)
+                    {
+                        string[] escapedParts = schema.DeferredReference.TrimStart('#').Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
+                        JToken currentToken = _rootSchema;
+                        foreach (string escapedPart in escapedParts)
+                        {
+                            string part = UnescapeReference(escapedPart);
+
+                            if (currentToken.Type == JTokenType.Object)
+                            {
+                                currentToken = currentToken[part];
+                            }
+                            else if (currentToken.Type == JTokenType.Array || currentToken.Type == JTokenType.Constructor)
+                            {
+                                int index;
+                                if (int.TryParse(part, out index) && index >= 0 && index < currentToken.Count())
+                                    currentToken = currentToken[index];
+                                else
+                                    currentToken = null;
+                            }
+
+                            if (currentToken == null)
+                                break;
+                        }
+
+                        if (currentToken != null)
+                            resolvedSchema = BuildSchema(currentToken);
+                    }
+
+                    if (resolvedSchema == null)
+                        throw new JsonException("Could not resolve schema reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, schema.DeferredReference));
+                }
+
+                schema = resolvedSchema;
+            }
+
+            if (schema.ReferencesResolved)
+                return schema;
+
+            schema.ReferencesResolved = true;
+
+            if (schema.Extends != null)
+            {
+                for (int i = 0; i < schema.Extends.Count; i++)
+                {
+                    schema.Extends[i] = ResolveReferences(schema.Extends[i]);
+                }
+            }
+
+            if (schema.Items != null)
+            {
+                for (int i = 0; i < schema.Items.Count; i++)
+                {
+                    schema.Items[i] = ResolveReferences(schema.Items[i]);
+                }
+            }
+
+            if (schema.AdditionalItems != null)
+                schema.AdditionalItems = ResolveReferences(schema.AdditionalItems);
+
+            if (schema.PatternProperties != null)
+            {
+                foreach (KeyValuePair<string, JsonSchema> patternProperty in schema.PatternProperties.ToList())
+                {
+                    schema.PatternProperties[patternProperty.Key] = ResolveReferences(patternProperty.Value);
+                }
+            }
+
+            if (schema.Properties != null)
+            {
+                foreach (KeyValuePair<string, JsonSchema> property in schema.Properties.ToList())
+                {
+                    schema.Properties[property.Key] = ResolveReferences(property.Value);
+                }
+            }
+
+            if (schema.AdditionalProperties != null)
+                schema.AdditionalProperties = ResolveReferences(schema.AdditionalProperties);
+
+            return schema;
+        }
+
+        private JsonSchema BuildSchema(JToken token)
+        {
+            JObject schemaObject = token as JObject;
+            if (schemaObject == null)
+                throw JsonException.Create(token, token.Path, "Expected object while parsing schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+            JToken referenceToken;
+            if (schemaObject.TryGetValue(JsonTypeReflector.RefPropertyName, out referenceToken))
+            {
+                JsonSchema deferredSchema = new JsonSchema();
+                deferredSchema.DeferredReference = (string)referenceToken;
+
+                return deferredSchema;
+            }
+
+            string location = token.Path.Replace(".", "/").Replace("[", "/").Replace("]", string.Empty);
+            if (!string.IsNullOrEmpty(location))
+                location = "/" + location;
+            location = "#" + location;
+
+            JsonSchema existingSchema;
+            if (_documentSchemas.TryGetValue(location, out existingSchema))
+                return existingSchema;
+
+            Push(new JsonSchema { Location = location });
+
+            ProcessSchemaProperties(schemaObject);
+
+            return Pop();
+        }
+
+        private void ProcessSchemaProperties(JObject schemaObject)
+        {
+            foreach (KeyValuePair<string, JToken> property in schemaObject)
+            {
+                switch (property.Key)
+                {
+                    case JsonSchemaConstants.TypePropertyName:
+                        CurrentSchema.Type = ProcessType(property.Value);
+                        break;
+                    case JsonSchemaConstants.IdPropertyName:
+                        CurrentSchema.Id = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.TitlePropertyName:
+                        CurrentSchema.Title = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.DescriptionPropertyName:
+                        CurrentSchema.Description = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.PropertiesPropertyName:
+                        CurrentSchema.Properties = ProcessProperties(property.Value);
+                        break;
+                    case JsonSchemaConstants.ItemsPropertyName:
+                        ProcessItems(property.Value);
+                        break;
+                    case JsonSchemaConstants.AdditionalPropertiesPropertyName:
+                        ProcessAdditionalProperties(property.Value);
+                        break;
+                    case JsonSchemaConstants.AdditionalItemsPropertyName:
+                        ProcessAdditionalItems(property.Value);
+                        break;
+                    case JsonSchemaConstants.PatternPropertiesPropertyName:
+                        CurrentSchema.PatternProperties = ProcessProperties(property.Value);
+                        break;
+                    case JsonSchemaConstants.RequiredPropertyName:
+                        CurrentSchema.Required = (bool)property.Value;
+                        break;
+                    case JsonSchemaConstants.RequiresPropertyName:
+                        CurrentSchema.Requires = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.MinimumPropertyName:
+                        CurrentSchema.Minimum = (double)property.Value;
+                        break;
+                    case JsonSchemaConstants.MaximumPropertyName:
+                        CurrentSchema.Maximum = (double)property.Value;
+                        break;
+                    case JsonSchemaConstants.ExclusiveMinimumPropertyName:
+                        CurrentSchema.ExclusiveMinimum = (bool)property.Value;
+                        break;
+                    case JsonSchemaConstants.ExclusiveMaximumPropertyName:
+                        CurrentSchema.ExclusiveMaximum = (bool)property.Value;
+                        break;
+                    case JsonSchemaConstants.MaximumLengthPropertyName:
+                        CurrentSchema.MaximumLength = (int)property.Value;
+                        break;
+                    case JsonSchemaConstants.MinimumLengthPropertyName:
+                        CurrentSchema.MinimumLength = (int)property.Value;
+                        break;
+                    case JsonSchemaConstants.MaximumItemsPropertyName:
+                        CurrentSchema.MaximumItems = (int)property.Value;
+                        break;
+                    case JsonSchemaConstants.MinimumItemsPropertyName:
+                        CurrentSchema.MinimumItems = (int)property.Value;
+                        break;
+                    case JsonSchemaConstants.DivisibleByPropertyName:
+                        CurrentSchema.DivisibleBy = (double)property.Value;
+                        break;
+                    case JsonSchemaConstants.DisallowPropertyName:
+                        CurrentSchema.Disallow = ProcessType(property.Value);
+                        break;
+                    case JsonSchemaConstants.DefaultPropertyName:
+                        CurrentSchema.Default = property.Value.DeepClone();
+                        break;
+                    case JsonSchemaConstants.HiddenPropertyName:
+                        CurrentSchema.Hidden = (bool)property.Value;
+                        break;
+                    case JsonSchemaConstants.ReadOnlyPropertyName:
+                        CurrentSchema.ReadOnly = (bool)property.Value;
+                        break;
+                    case JsonSchemaConstants.FormatPropertyName:
+                        CurrentSchema.Format = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.PatternPropertyName:
+                        CurrentSchema.Pattern = (string)property.Value;
+                        break;
+                    case JsonSchemaConstants.EnumPropertyName:
+                        ProcessEnum(property.Value);
+                        break;
+                    case JsonSchemaConstants.ExtendsPropertyName:
+                        ProcessExtends(property.Value);
+                        break;
+                    case JsonSchemaConstants.UniqueItemsPropertyName:
+                        CurrentSchema.UniqueItems = (bool)property.Value;
+                        break;
+                }
+            }
+        }
+
+        private void ProcessExtends(JToken token)
+        {
+            IList<JsonSchema> schemas = new List<JsonSchema>();
+
+            if (token.Type == JTokenType.Array)
+            {
+                foreach (JToken schemaObject in token)
+                {
+                    schemas.Add(BuildSchema(schemaObject));
+                }
+            }
+            else
+            {
+                JsonSchema schema = BuildSchema(token);
+                if (schema != null)
+                    schemas.Add(schema);
+            }
+
+            if (schemas.Count > 0)
+                CurrentSchema.Extends = schemas;
+        }
+
+        private void ProcessEnum(JToken token)
+        {
+            if (token.Type != JTokenType.Array)
+                throw JsonException.Create(token, token.Path, "Expected Array token while parsing enum values, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+            CurrentSchema.Enum = new List<JToken>();
+
+            foreach (JToken enumValue in token)
+            {
+                CurrentSchema.Enum.Add(enumValue.DeepClone());
+            }
+        }
+
+        private void ProcessAdditionalProperties(JToken token)
+        {
+            if (token.Type == JTokenType.Boolean)
+                CurrentSchema.AllowAdditionalProperties = (bool)token;
+            else
+                CurrentSchema.AdditionalProperties = BuildSchema(token);
+        }
+
+        private void ProcessAdditionalItems(JToken token)
+        {
+            if (token.Type == JTokenType.Boolean)
+                CurrentSchema.AllowAdditionalItems = (bool)token;
+            else
+                CurrentSchema.AdditionalItems = BuildSchema(token);
+        }
+
+        private IDictionary<string, JsonSchema> ProcessProperties(JToken token)
+        {
+            IDictionary<string, JsonSchema> properties = new Dictionary<string, JsonSchema>();
+
+            if (token.Type != JTokenType.Object)
+                throw JsonException.Create(token, token.Path, "Expected Object token while parsing schema properties, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+            foreach (JProperty propertyToken in token)
+            {
+                if (properties.ContainsKey(propertyToken.Name))
+                    throw new JsonException("Property {0} has already been defined in schema.".FormatWith(CultureInfo.InvariantCulture, propertyToken.Name));
+
+                properties.Add(propertyToken.Name, BuildSchema(propertyToken.Value));
+            }
+
+            return properties;
+        }
+
+        private void ProcessItems(JToken token)
+        {
+            CurrentSchema.Items = new List<JsonSchema>();
+
+            switch (token.Type)
+            {
+                case JTokenType.Object:
+                    CurrentSchema.Items.Add(BuildSchema(token));
+                    CurrentSchema.PositionalItemsValidation = false;
+                    break;
+                case JTokenType.Array:
+                    CurrentSchema.PositionalItemsValidation = true;
+                    foreach (JToken schemaToken in token)
+                    {
+                        CurrentSchema.Items.Add(BuildSchema(schemaToken));
+                    }
+                    break;
+                default:
+                    throw JsonException.Create(token, token.Path, "Expected array or JSON schema object, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+            }
+        }
+
+        private JsonSchemaType? ProcessType(JToken token)
+        {
+            switch (token.Type)
+            {
+                case JTokenType.Array:
+                    // ensure type is in blank state before ORing values
+                    JsonSchemaType? type = JsonSchemaType.None;
+
+                    foreach (JToken typeToken in token)
+                    {
+                        if (typeToken.Type != JTokenType.String)
+                            throw JsonException.Create(typeToken, typeToken.Path, "Exception JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+
+                        type = type | MapType((string)typeToken);
+                    }
+
+                    return type;
+                case JTokenType.String:
+                    return MapType((string)token);
+                default:
+                    throw JsonException.Create(token, token.Path, "Expected array or JSON schema type string token, got {0}.".FormatWith(CultureInfo.InvariantCulture, token.Type));
+            }
+        }
+
+        internal static JsonSchemaType MapType(string type)
+        {
+            JsonSchemaType mappedType;
+            if (!JsonSchemaConstants.JsonSchemaTypeMapping.TryGetValue(type, out mappedType))
+                throw new JsonException("Invalid JSON schema type: {0}".FormatWith(CultureInfo.InvariantCulture, type));
+
+            return mappedType;
+        }
+
+        internal static string MapType(JsonSchemaType type)
+        {
+            return JsonSchemaConstants.JsonSchemaTypeMapping.Single(kv => kv.Value == type).Key;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaConstants.cs b/Newtonsoft.Json/Schema/JsonSchemaConstants.cs
new file mode 100644
index 0000000..3f8eec8
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaConstants.cs
@@ -0,0 +1,78 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+
+namespace Newtonsoft.Json.Schema
+{
+    internal static class JsonSchemaConstants
+    {
+        public const string TypePropertyName = "type";
+        public const string PropertiesPropertyName = "properties";
+        public const string ItemsPropertyName = "items";
+        public const string AdditionalItemsPropertyName = "additionalItems";
+        public const string RequiredPropertyName = "required";
+        public const string PatternPropertiesPropertyName = "patternProperties";
+        public const string AdditionalPropertiesPropertyName = "additionalProperties";
+        public const string RequiresPropertyName = "requires";
+        public const string MinimumPropertyName = "minimum";
+        public const string MaximumPropertyName = "maximum";
+        public const string ExclusiveMinimumPropertyName = "exclusiveMinimum";
+        public const string ExclusiveMaximumPropertyName = "exclusiveMaximum";
+        public const string MinimumItemsPropertyName = "minItems";
+        public const string MaximumItemsPropertyName = "maxItems";
+        public const string PatternPropertyName = "pattern";
+        public const string MaximumLengthPropertyName = "maxLength";
+        public const string MinimumLengthPropertyName = "minLength";
+        public const string EnumPropertyName = "enum";
+        public const string ReadOnlyPropertyName = "readonly";
+        public const string TitlePropertyName = "title";
+        public const string DescriptionPropertyName = "description";
+        public const string FormatPropertyName = "format";
+        public const string DefaultPropertyName = "default";
+        public const string TransientPropertyName = "transient";
+        public const string DivisibleByPropertyName = "divisibleBy";
+        public const string HiddenPropertyName = "hidden";
+        public const string DisallowPropertyName = "disallow";
+        public const string ExtendsPropertyName = "extends";
+        public const string IdPropertyName = "id";
+        public const string UniqueItemsPropertyName = "uniqueItems";
+
+        public const string OptionValuePropertyName = "value";
+        public const string OptionLabelPropertyName = "label";
+
+        public static readonly IDictionary<string, JsonSchemaType> JsonSchemaTypeMapping = new Dictionary<string, JsonSchemaType>
+        {
+            { "string", JsonSchemaType.String },
+            { "object", JsonSchemaType.Object },
+            { "integer", JsonSchemaType.Integer },
+            { "number", JsonSchemaType.Float },
+            { "null", JsonSchemaType.Null },
+            { "boolean", JsonSchemaType.Boolean },
+            { "array", JsonSchemaType.Array },
+            { "any", JsonSchemaType.Any }
+        };
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaException.cs b/Newtonsoft.Json/Schema/JsonSchemaException.cs
new file mode 100644
index 0000000..1ad8cea
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaException.cs
@@ -0,0 +1,108 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Runtime.Serialization;
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Returns detailed information about the schema exception.
+    /// </summary>
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+    [Serializable]
+#endif
+    public class JsonSchemaException : JsonException
+    {
+        /// <summary>
+        /// Gets the line number indicating where the error occurred.
+        /// </summary>
+        /// <value>The line number indicating where the error occurred.</value>
+        public int LineNumber { get; private set; }
+
+
+        /// <summary>
+        /// Gets the line position indicating where the error occurred.
+        /// </summary>
+        /// <value>The line position indicating where the error occurred.</value>
+        public int LinePosition { get; private set; }
+
+        /// <summary>
+        /// Gets the path to the JSON where the error occurred.
+        /// </summary>
+        /// <value>The path to the JSON where the error occurred.</value>
+        public string Path { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchemaException"/> class.
+        /// </summary>
+        public JsonSchemaException()
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchemaException"/> class
+        /// with a specified error message.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        public JsonSchemaException(string message)
+            : base(message)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchemaException"/> class
+        /// with a specified error message and a reference to the inner exception that is the cause of this exception.
+        /// </summary>
+        /// <param name="message">The error message that explains the reason for the exception.</param>
+        /// <param name="innerException">The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified.</param>
+        public JsonSchemaException(string message, Exception innerException)
+            : base(message, innerException)
+        {
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchemaException"/> class.
+        /// </summary>
+        /// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo"/> that holds the serialized object data about the exception being thrown.</param>
+        /// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext"/> that contains contextual information about the source or destination.</param>
+        /// <exception cref="T:System.ArgumentNullException">The <paramref name="info"/> parameter is null. </exception>
+        /// <exception cref="T:System.Runtime.Serialization.SerializationException">The class name is null or <see cref="P:System.Exception.HResult"/> is zero (0). </exception>
+        public JsonSchemaException(SerializationInfo info, StreamingContext context)
+            : base(info, context)
+        {
+        }
+#endif
+
+        internal JsonSchemaException(string message, Exception innerException, string path, int lineNumber, int linePosition)
+            : base(message, innerException)
+        {
+            Path = path;
+            LineNumber = lineNumber;
+            LinePosition = linePosition;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs b/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs
new file mode 100644
index 0000000..970e3a1
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaGenerator.cs
@@ -0,0 +1,473 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.ComponentModel;
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Serialization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Generates a <see cref="JsonSchema"/> from a specified <see cref="Type"/>.
+    /// </summary>
+    public class JsonSchemaGenerator
+    {
+        /// <summary>
+        /// Gets or sets how undefined schemas are handled by the serializer.
+        /// </summary>
+        public UndefinedSchemaIdHandling UndefinedSchemaIdHandling { get; set; }
+
+        private IContractResolver _contractResolver;
+
+        /// <summary>
+        /// Gets or sets the contract resolver.
+        /// </summary>
+        /// <value>The contract resolver.</value>
+        public IContractResolver ContractResolver
+        {
+            get
+            {
+                if (_contractResolver == null)
+                    return DefaultContractResolver.Instance;
+
+                return _contractResolver;
+            }
+            set { _contractResolver = value; }
+        }
+
+        private class TypeSchema
+        {
+            public Type Type { get; private set; }
+            public JsonSchema Schema { get; private set; }
+
+            public TypeSchema(Type type, JsonSchema schema)
+            {
+                ValidationUtils.ArgumentNotNull(type, "type");
+                ValidationUtils.ArgumentNotNull(schema, "schema");
+
+                Type = type;
+                Schema = schema;
+            }
+        }
+
+        private JsonSchemaResolver _resolver;
+        private readonly IList<TypeSchema> _stack = new List<TypeSchema>();
+        private JsonSchema _currentSchema;
+
+        private JsonSchema CurrentSchema
+        {
+            get { return _currentSchema; }
+        }
+
+        private void Push(TypeSchema typeSchema)
+        {
+            _currentSchema = typeSchema.Schema;
+            _stack.Add(typeSchema);
+            _resolver.LoadedSchemas.Add(typeSchema.Schema);
+        }
+
+        private TypeSchema Pop()
+        {
+            TypeSchema popped = _stack[_stack.Count - 1];
+            _stack.RemoveAt(_stack.Count - 1);
+            TypeSchema newValue = _stack.LastOrDefault();
+            if (newValue != null)
+            {
+                _currentSchema = newValue.Schema;
+            }
+            else
+            {
+                _currentSchema = null;
+            }
+
+            return popped;
+        }
+
+        /// <summary>
+        /// Generate a <see cref="JsonSchema"/> from the specified type.
+        /// </summary>
+        /// <param name="type">The type to generate a <see cref="JsonSchema"/> from.</param>
+        /// <returns>A <see cref="JsonSchema"/> generated from the specified type.</returns>
+        public JsonSchema Generate(Type type)
+        {
+            return Generate(type, new JsonSchemaResolver(), false);
+        }
+
+        /// <summary>
+        /// Generate a <see cref="JsonSchema"/> from the specified type.
+        /// </summary>
+        /// <param name="type">The type to generate a <see cref="JsonSchema"/> from.</param>
+        /// <param name="resolver">The <see cref="JsonSchemaResolver"/> used to resolve schema references.</param>
+        /// <returns>A <see cref="JsonSchema"/> generated from the specified type.</returns>
+        public JsonSchema Generate(Type type, JsonSchemaResolver resolver)
+        {
+            return Generate(type, resolver, false);
+        }
+
+        /// <summary>
+        /// Generate a <see cref="JsonSchema"/> from the specified type.
+        /// </summary>
+        /// <param name="type">The type to generate a <see cref="JsonSchema"/> from.</param>
+        /// <param name="rootSchemaNullable">Specify whether the generated root <see cref="JsonSchema"/> will be nullable.</param>
+        /// <returns>A <see cref="JsonSchema"/> generated from the specified type.</returns>
+        public JsonSchema Generate(Type type, bool rootSchemaNullable)
+        {
+            return Generate(type, new JsonSchemaResolver(), rootSchemaNullable);
+        }
+
+        /// <summary>
+        /// Generate a <see cref="JsonSchema"/> from the specified type.
+        /// </summary>
+        /// <param name="type">The type to generate a <see cref="JsonSchema"/> from.</param>
+        /// <param name="resolver">The <see cref="JsonSchemaResolver"/> used to resolve schema references.</param>
+        /// <param name="rootSchemaNullable">Specify whether the generated root <see cref="JsonSchema"/> will be nullable.</param>
+        /// <returns>A <see cref="JsonSchema"/> generated from the specified type.</returns>
+        public JsonSchema Generate(Type type, JsonSchemaResolver resolver, bool rootSchemaNullable)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+            ValidationUtils.ArgumentNotNull(resolver, "resolver");
+
+            _resolver = resolver;
+
+            return GenerateInternal(type, (!rootSchemaNullable) ? Required.Always : Required.Default, false);
+        }
+
+        private string GetTitle(Type type)
+        {
+            JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
+
+            if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Title))
+                return containerAttribute.Title;
+
+            return null;
+        }
+
+        private string GetDescription(Type type)
+        {
+            JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
+
+            if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Description))
+                return containerAttribute.Description;
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            DescriptionAttribute descriptionAttribute = ReflectionUtils.GetAttribute<DescriptionAttribute>(type);
+            if (descriptionAttribute != null)
+                return descriptionAttribute.Description;
+#endif
+
+            return null;
+        }
+
+        private string GetTypeId(Type type, bool explicitOnly)
+        {
+            JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(type);
+
+            if (containerAttribute != null && !string.IsNullOrEmpty(containerAttribute.Id))
+                return containerAttribute.Id;
+
+            if (explicitOnly)
+                return null;
+
+            switch (UndefinedSchemaIdHandling)
+            {
+                case UndefinedSchemaIdHandling.UseTypeName:
+                    return type.FullName;
+                case UndefinedSchemaIdHandling.UseAssemblyQualifiedName:
+                    return type.AssemblyQualifiedName;
+                default:
+                    return null;
+            }
+        }
+
+        private JsonSchema GenerateInternal(Type type, Required valueRequired, bool required)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+
+            string resolvedId = GetTypeId(type, false);
+            string explicitId = GetTypeId(type, true);
+
+            if (!string.IsNullOrEmpty(resolvedId))
+            {
+                JsonSchema resolvedSchema = _resolver.GetSchema(resolvedId);
+                if (resolvedSchema != null)
+                {
+                    // resolved schema is not null but referencing member allows nulls
+                    // change resolved schema to allow nulls. hacky but what are ya gonna do?
+                    if (valueRequired != Required.Always && !HasFlag(resolvedSchema.Type, JsonSchemaType.Null))
+                        resolvedSchema.Type |= JsonSchemaType.Null;
+                    if (required && resolvedSchema.Required != true)
+                        resolvedSchema.Required = true;
+
+                    return resolvedSchema;
+                }
+            }
+
+            // test for unresolved circular reference
+            if (_stack.Any(tc => tc.Type == type))
+            {
+                throw new JsonException("Unresolved circular reference for type '{0}'. Explicitly define an Id for the type using a JsonObject/JsonArray attribute or automatically generate a type Id using the UndefinedSchemaIdHandling property.".FormatWith(CultureInfo.InvariantCulture, type));
+            }
+
+            JsonContract contract = ContractResolver.ResolveContract(type);
+            JsonConverter converter;
+            if ((converter = contract.Converter) != null || (converter = contract.InternalConverter) != null)
+            {
+                JsonSchema converterSchema = converter.GetSchema();
+                if (converterSchema != null)
+                    return converterSchema;
+            }
+
+            Push(new TypeSchema(type, new JsonSchema()));
+
+            if (explicitId != null)
+                CurrentSchema.Id = explicitId;
+
+            if (required)
+                CurrentSchema.Required = true;
+            CurrentSchema.Title = GetTitle(type);
+            CurrentSchema.Description = GetDescription(type);
+
+            if (converter != null)
+            {
+                // todo: Add GetSchema to JsonConverter and use here?
+                CurrentSchema.Type = JsonSchemaType.Any;
+            }
+            else
+            {
+                switch (contract.ContractType)
+                {
+                    case JsonContractType.Object:
+                        CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
+                        CurrentSchema.Id = GetTypeId(type, false);
+                        GenerateObjectSchema(type, (JsonObjectContract)contract);
+                        break;
+                    case JsonContractType.Array:
+                        CurrentSchema.Type = AddNullType(JsonSchemaType.Array, valueRequired);
+
+                        CurrentSchema.Id = GetTypeId(type, false);
+
+                        JsonArrayAttribute arrayAttribute = JsonTypeReflector.GetJsonContainerAttribute(type) as JsonArrayAttribute;
+                        bool allowNullItem = (arrayAttribute == null || arrayAttribute.AllowNullItems);
+
+                        Type collectionItemType = ReflectionUtils.GetCollectionItemType(type);
+                        if (collectionItemType != null)
+                        {
+                            CurrentSchema.Items = new List<JsonSchema>();
+                            CurrentSchema.Items.Add(GenerateInternal(collectionItemType, (!allowNullItem) ? Required.Always : Required.Default, false));
+                        }
+                        break;
+                    case JsonContractType.Primitive:
+                        CurrentSchema.Type = GetJsonSchemaType(type, valueRequired);
+
+                        if (CurrentSchema.Type == JsonSchemaType.Integer && type.IsEnum() && !type.IsDefined(typeof(FlagsAttribute), true))
+                        {
+                            CurrentSchema.Enum = new List<JToken>();
+
+                            EnumValues<long> enumValues = EnumUtils.GetNamesAndValues<long>(type);
+                            foreach (EnumValue<long> enumValue in enumValues)
+                            {
+                                JToken value = JToken.FromObject(enumValue.Value);
+
+                                CurrentSchema.Enum.Add(value);
+                            }
+                        }
+                        break;
+                    case JsonContractType.String:
+                        JsonSchemaType schemaType = (!ReflectionUtils.IsNullable(contract.UnderlyingType))
+                            ? JsonSchemaType.String
+                            : AddNullType(JsonSchemaType.String, valueRequired);
+
+                        CurrentSchema.Type = schemaType;
+                        break;
+                    case JsonContractType.Dictionary:
+                        CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
+
+                        Type keyType;
+                        Type valueType;
+                        ReflectionUtils.GetDictionaryKeyValueTypes(type, out keyType, out valueType);
+
+                        if (keyType != null)
+                        {
+                            JsonContract keyContract = ContractResolver.ResolveContract(keyType);
+
+                            // can be converted to a string
+                            if (keyContract.ContractType == JsonContractType.Primitive)
+                            {
+                                CurrentSchema.AdditionalProperties = GenerateInternal(valueType, Required.Default, false);
+                            }
+                        }
+                        break;
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+                    case JsonContractType.Serializable:
+                        CurrentSchema.Type = AddNullType(JsonSchemaType.Object, valueRequired);
+                        CurrentSchema.Id = GetTypeId(type, false);
+                        GenerateISerializableContract(type, (JsonISerializableContract)contract);
+                        break;
+#endif
+#if !(NET35 || NET20 || PORTABLE40)
+                    case JsonContractType.Dynamic:
+#endif
+                    case JsonContractType.Linq:
+                        CurrentSchema.Type = JsonSchemaType.Any;
+                        break;
+                    default:
+                        throw new JsonException("Unexpected contract type: {0}".FormatWith(CultureInfo.InvariantCulture, contract));
+                }
+            }
+
+            return Pop().Schema;
+        }
+
+        private JsonSchemaType AddNullType(JsonSchemaType type, Required valueRequired)
+        {
+            if (valueRequired != Required.Always)
+                return type | JsonSchemaType.Null;
+
+            return type;
+        }
+
+        private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
+        {
+            return ((value & flag) == flag);
+        }
+
+        private void GenerateObjectSchema(Type type, JsonObjectContract contract)
+        {
+            CurrentSchema.Properties = new Dictionary<string, JsonSchema>();
+            foreach (JsonProperty property in contract.Properties)
+            {
+                if (!property.Ignored)
+                {
+                    bool optional = property.NullValueHandling == NullValueHandling.Ignore ||
+                                    HasFlag(property.DefaultValueHandling.GetValueOrDefault(), DefaultValueHandling.Ignore) ||
+                                    property.ShouldSerialize != null ||
+                                    property.GetIsSpecified != null;
+
+                    JsonSchema propertySchema = GenerateInternal(property.PropertyType, property.Required, !optional);
+
+                    if (property.DefaultValue != null)
+                        propertySchema.Default = JToken.FromObject(property.DefaultValue);
+
+                    CurrentSchema.Properties.Add(property.PropertyName, propertySchema);
+                }
+            }
+
+            if (type.IsSealed())
+                CurrentSchema.AllowAdditionalProperties = false;
+        }
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        private void GenerateISerializableContract(Type type, JsonISerializableContract contract)
+        {
+            CurrentSchema.AllowAdditionalProperties = true;
+        }
+#endif
+
+        internal static bool HasFlag(JsonSchemaType? value, JsonSchemaType flag)
+        {
+            // default value is Any
+            if (value == null)
+                return true;
+
+            bool match = ((value & flag) == flag);
+            if (match)
+                return true;
+
+            // integer is a subset of float
+            if (flag == JsonSchemaType.Integer && (value & JsonSchemaType.Float) == JsonSchemaType.Float)
+                return true;
+
+            return false;
+        }
+
+        private JsonSchemaType GetJsonSchemaType(Type type, Required valueRequired)
+        {
+            JsonSchemaType schemaType = JsonSchemaType.None;
+            if (valueRequired != Required.Always && ReflectionUtils.IsNullable(type))
+            {
+                schemaType = JsonSchemaType.Null;
+                if (ReflectionUtils.IsNullableType(type))
+                    type = Nullable.GetUnderlyingType(type);
+            }
+
+            PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(type);
+
+            switch (typeCode)
+            {
+                case PrimitiveTypeCode.Empty:
+                case PrimitiveTypeCode.Object:
+                    return schemaType | JsonSchemaType.String;
+#if !(NETFX_CORE || PORTABLE)
+                case PrimitiveTypeCode.DBNull:
+                    return schemaType | JsonSchemaType.Null;
+#endif
+                case PrimitiveTypeCode.Boolean:
+                    return schemaType | JsonSchemaType.Boolean;
+                case PrimitiveTypeCode.Char:
+                    return schemaType | JsonSchemaType.String;
+                case PrimitiveTypeCode.SByte:
+                case PrimitiveTypeCode.Byte:
+                case PrimitiveTypeCode.Int16:
+                case PrimitiveTypeCode.UInt16:
+                case PrimitiveTypeCode.Int32:
+                case PrimitiveTypeCode.UInt32:
+                case PrimitiveTypeCode.Int64:
+                case PrimitiveTypeCode.UInt64:
+#if !(PORTABLE || NET35 || NET20)
+                case PrimitiveTypeCode.BigInteger:
+#endif
+                    return schemaType | JsonSchemaType.Integer;
+                case PrimitiveTypeCode.Single:
+                case PrimitiveTypeCode.Double:
+                case PrimitiveTypeCode.Decimal:
+                    return schemaType | JsonSchemaType.Float;
+                    // convert to string?
+                case PrimitiveTypeCode.DateTime:
+#if !NET20
+                case PrimitiveTypeCode.DateTimeOffset:
+#endif
+                    return schemaType | JsonSchemaType.String;
+                case PrimitiveTypeCode.String:
+                case PrimitiveTypeCode.Uri:
+                case PrimitiveTypeCode.Guid:
+                case PrimitiveTypeCode.TimeSpan:
+                case PrimitiveTypeCode.Bytes:
+                    return schemaType | JsonSchemaType.String;
+                default:
+                    throw new JsonException("Unexpected type code '{0}' for type '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeCode, type));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaModel.cs b/Newtonsoft.Json/Schema/JsonSchemaModel.cs
new file mode 100644
index 0000000..65f9880
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaModel.cs
@@ -0,0 +1,119 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaModel
+    {
+        public bool Required { get; set; }
+        public JsonSchemaType Type { get; set; }
+        public int? MinimumLength { get; set; }
+        public int? MaximumLength { get; set; }
+        public double? DivisibleBy { get; set; }
+        public double? Minimum { get; set; }
+        public double? Maximum { get; set; }
+        public bool ExclusiveMinimum { get; set; }
+        public bool ExclusiveMaximum { get; set; }
+        public int? MinimumItems { get; set; }
+        public int? MaximumItems { get; set; }
+        public IList<string> Patterns { get; set; }
+        public IList<JsonSchemaModel> Items { get; set; }
+        public IDictionary<string, JsonSchemaModel> Properties { get; set; }
+        public IDictionary<string, JsonSchemaModel> PatternProperties { get; set; }
+        public JsonSchemaModel AdditionalProperties { get; set; }
+        public JsonSchemaModel AdditionalItems { get; set; }
+        public bool PositionalItemsValidation { get; set; }
+        public bool AllowAdditionalProperties { get; set; }
+        public bool AllowAdditionalItems { get; set; }
+        public bool UniqueItems { get; set; }
+        public IList<JToken> Enum { get; set; }
+        public JsonSchemaType Disallow { get; set; }
+
+        public JsonSchemaModel()
+        {
+            Type = JsonSchemaType.Any;
+            AllowAdditionalProperties = true;
+            AllowAdditionalItems = true;
+            Required = false;
+        }
+
+        public static JsonSchemaModel Create(IList<JsonSchema> schemata)
+        {
+            JsonSchemaModel model = new JsonSchemaModel();
+
+            foreach (JsonSchema schema in schemata)
+            {
+                Combine(model, schema);
+            }
+
+            return model;
+        }
+
+        private static void Combine(JsonSchemaModel model, JsonSchema schema)
+        {
+            // Version 3 of the Draft JSON Schema has the default value of Not Required
+            model.Required = model.Required || (schema.Required ?? false);
+            model.Type = model.Type & (schema.Type ?? JsonSchemaType.Any);
+
+            model.MinimumLength = MathUtils.Max(model.MinimumLength, schema.MinimumLength);
+            model.MaximumLength = MathUtils.Min(model.MaximumLength, schema.MaximumLength);
+
+            // not sure what is the best way to combine divisibleBy
+            model.DivisibleBy = MathUtils.Max(model.DivisibleBy, schema.DivisibleBy);
+
+            model.Minimum = MathUtils.Max(model.Minimum, schema.Minimum);
+            model.Maximum = MathUtils.Max(model.Maximum, schema.Maximum);
+            model.ExclusiveMinimum = model.ExclusiveMinimum || (schema.ExclusiveMinimum ?? false);
+            model.ExclusiveMaximum = model.ExclusiveMaximum || (schema.ExclusiveMaximum ?? false);
+
+            model.MinimumItems = MathUtils.Max(model.MinimumItems, schema.MinimumItems);
+            model.MaximumItems = MathUtils.Min(model.MaximumItems, schema.MaximumItems);
+            model.PositionalItemsValidation = model.PositionalItemsValidation || schema.PositionalItemsValidation;
+            model.AllowAdditionalProperties = model.AllowAdditionalProperties && schema.AllowAdditionalProperties;
+            model.AllowAdditionalItems = model.AllowAdditionalItems && schema.AllowAdditionalItems;
+            model.UniqueItems = model.UniqueItems || schema.UniqueItems;
+            if (schema.Enum != null)
+            {
+                if (model.Enum == null)
+                    model.Enum = new List<JToken>();
+
+                model.Enum.AddRangeDistinct(schema.Enum, JToken.EqualityComparer);
+            }
+            model.Disallow = model.Disallow | (schema.Disallow ?? JsonSchemaType.None);
+
+            if (schema.Pattern != null)
+            {
+                if (model.Patterns == null)
+                    model.Patterns = new List<string>();
+
+                model.Patterns.AddDistinct(schema.Pattern);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs b/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs
new file mode 100644
index 0000000..79b116e
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaModelBuilder.cs
@@ -0,0 +1,191 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaModelBuilder
+    {
+        private JsonSchemaNodeCollection _nodes = new JsonSchemaNodeCollection();
+        private Dictionary<JsonSchemaNode, JsonSchemaModel> _nodeModels = new Dictionary<JsonSchemaNode, JsonSchemaModel>();
+        private JsonSchemaNode _node;
+
+        public JsonSchemaModel Build(JsonSchema schema)
+        {
+            _nodes = new JsonSchemaNodeCollection();
+            _node = AddSchema(null, schema);
+
+            _nodeModels = new Dictionary<JsonSchemaNode, JsonSchemaModel>();
+            JsonSchemaModel model = BuildNodeModel(_node);
+
+            return model;
+        }
+
+        public JsonSchemaNode AddSchema(JsonSchemaNode existingNode, JsonSchema schema)
+        {
+            string newId;
+            if (existingNode != null)
+            {
+                if (existingNode.Schemas.Contains(schema))
+                    return existingNode;
+
+                newId = JsonSchemaNode.GetId(existingNode.Schemas.Union(new[] { schema }));
+            }
+            else
+            {
+                newId = JsonSchemaNode.GetId(new[] { schema });
+            }
+
+            if (_nodes.Contains(newId))
+                return _nodes[newId];
+
+            JsonSchemaNode currentNode = (existingNode != null)
+                ? existingNode.Combine(schema)
+                : new JsonSchemaNode(schema);
+
+            _nodes.Add(currentNode);
+
+            AddProperties(schema.Properties, currentNode.Properties);
+
+            AddProperties(schema.PatternProperties, currentNode.PatternProperties);
+
+            if (schema.Items != null)
+            {
+                for (int i = 0; i < schema.Items.Count; i++)
+                {
+                    AddItem(currentNode, i, schema.Items[i]);
+                }
+            }
+
+            if (schema.AdditionalItems != null)
+                AddAdditionalItems(currentNode, schema.AdditionalItems);
+
+            if (schema.AdditionalProperties != null)
+                AddAdditionalProperties(currentNode, schema.AdditionalProperties);
+
+            if (schema.Extends != null)
+            {
+                foreach (JsonSchema jsonSchema in schema.Extends)
+                {
+                    currentNode = AddSchema(currentNode, jsonSchema);
+                }
+            }
+
+            return currentNode;
+        }
+
+        public void AddProperties(IDictionary<string, JsonSchema> source, IDictionary<string, JsonSchemaNode> target)
+        {
+            if (source != null)
+            {
+                foreach (KeyValuePair<string, JsonSchema> property in source)
+                {
+                    AddProperty(target, property.Key, property.Value);
+                }
+            }
+        }
+
+        public void AddProperty(IDictionary<string, JsonSchemaNode> target, string propertyName, JsonSchema schema)
+        {
+            JsonSchemaNode propertyNode;
+            target.TryGetValue(propertyName, out propertyNode);
+
+            target[propertyName] = AddSchema(propertyNode, schema);
+        }
+
+        public void AddItem(JsonSchemaNode parentNode, int index, JsonSchema schema)
+        {
+            JsonSchemaNode existingItemNode = (parentNode.Items.Count > index)
+                ? parentNode.Items[index]
+                : null;
+
+            JsonSchemaNode newItemNode = AddSchema(existingItemNode, schema);
+
+            if (!(parentNode.Items.Count > index))
+            {
+                parentNode.Items.Add(newItemNode);
+            }
+            else
+            {
+                parentNode.Items[index] = newItemNode;
+            }
+        }
+
+        public void AddAdditionalProperties(JsonSchemaNode parentNode, JsonSchema schema)
+        {
+            parentNode.AdditionalProperties = AddSchema(parentNode.AdditionalProperties, schema);
+        }
+
+        public void AddAdditionalItems(JsonSchemaNode parentNode, JsonSchema schema)
+        {
+            parentNode.AdditionalItems = AddSchema(parentNode.AdditionalItems, schema);
+        }
+
+        private JsonSchemaModel BuildNodeModel(JsonSchemaNode node)
+        {
+            JsonSchemaModel model;
+            if (_nodeModels.TryGetValue(node, out model))
+                return model;
+
+            model = JsonSchemaModel.Create(node.Schemas);
+            _nodeModels[node] = model;
+
+            foreach (KeyValuePair<string, JsonSchemaNode> property in node.Properties)
+            {
+                if (model.Properties == null)
+                    model.Properties = new Dictionary<string, JsonSchemaModel>();
+
+                model.Properties[property.Key] = BuildNodeModel(property.Value);
+            }
+            foreach (KeyValuePair<string, JsonSchemaNode> property in node.PatternProperties)
+            {
+                if (model.PatternProperties == null)
+                    model.PatternProperties = new Dictionary<string, JsonSchemaModel>();
+
+                model.PatternProperties[property.Key] = BuildNodeModel(property.Value);
+            }
+            foreach (JsonSchemaNode t in node.Items)
+            {
+                if (model.Items == null)
+                    model.Items = new List<JsonSchemaModel>();
+
+                model.Items.Add(BuildNodeModel(t));
+            }
+            if (node.AdditionalProperties != null)
+                model.AdditionalProperties = BuildNodeModel(node.AdditionalProperties);
+            if (node.AdditionalItems != null)
+                model.AdditionalItems = BuildNodeModel(node.AdditionalItems);
+
+            return model;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaNode.cs b/Newtonsoft.Json/Schema/JsonSchemaNode.cs
new file mode 100644
index 0000000..298456b
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaNode.cs
@@ -0,0 +1,80 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaNode
+    {
+        public string Id { get; private set; }
+        public ReadOnlyCollection<JsonSchema> Schemas { get; private set; }
+        public Dictionary<string, JsonSchemaNode> Properties { get; private set; }
+        public Dictionary<string, JsonSchemaNode> PatternProperties { get; private set; }
+        public List<JsonSchemaNode> Items { get; private set; }
+        public JsonSchemaNode AdditionalProperties { get; set; }
+        public JsonSchemaNode AdditionalItems { get; set; }
+
+        public JsonSchemaNode(JsonSchema schema)
+        {
+            Schemas = new ReadOnlyCollection<JsonSchema>(new[] { schema });
+            Properties = new Dictionary<string, JsonSchemaNode>();
+            PatternProperties = new Dictionary<string, JsonSchemaNode>();
+            Items = new List<JsonSchemaNode>();
+
+            Id = GetId(Schemas);
+        }
+
+        private JsonSchemaNode(JsonSchemaNode source, JsonSchema schema)
+        {
+            Schemas = new ReadOnlyCollection<JsonSchema>(source.Schemas.Union(new[] { schema }).ToList());
+            Properties = new Dictionary<string, JsonSchemaNode>(source.Properties);
+            PatternProperties = new Dictionary<string, JsonSchemaNode>(source.PatternProperties);
+            Items = new List<JsonSchemaNode>(source.Items);
+            AdditionalProperties = source.AdditionalProperties;
+            AdditionalItems = source.AdditionalItems;
+
+            Id = GetId(Schemas);
+        }
+
+        public JsonSchemaNode Combine(JsonSchema schema)
+        {
+            return new JsonSchemaNode(this, schema);
+        }
+
+        public static string GetId(IEnumerable<JsonSchema> schemata)
+        {
+            return string.Join("-", schemata.Select(s => s.InternalId).OrderBy(id => id, StringComparer.Ordinal).ToArray());
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs b/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs
new file mode 100644
index 0000000..8521c84
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaNodeCollection.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.ObjectModel;
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaNodeCollection : KeyedCollection<string, JsonSchemaNode>
+    {
+        protected override string GetKeyForItem(JsonSchemaNode item)
+        {
+            return item.Id;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaResolver.cs b/Newtonsoft.Json/Schema/JsonSchemaResolver.cs
new file mode 100644
index 0000000..1b8fcec
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaResolver.cs
@@ -0,0 +1,71 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Resolves <see cref="JsonSchema"/> from an id.
+    /// </summary>
+    public class JsonSchemaResolver
+    {
+        /// <summary>
+        /// Gets or sets the loaded schemas.
+        /// </summary>
+        /// <value>The loaded schemas.</value>
+        public IList<JsonSchema> LoadedSchemas { get; protected set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonSchemaResolver"/> class.
+        /// </summary>
+        public JsonSchemaResolver()
+        {
+            LoadedSchemas = new List<JsonSchema>();
+        }
+
+        /// <summary>
+        /// Gets a <see cref="JsonSchema"/> for the specified reference.
+        /// </summary>
+        /// <param name="reference">The id.</param>
+        /// <returns>A <see cref="JsonSchema"/> for the specified reference.</returns>
+        public virtual JsonSchema GetSchema(string reference)
+        {
+            JsonSchema schema = LoadedSchemas.SingleOrDefault(s => string.Equals(s.Id, reference, StringComparison.Ordinal));
+
+            if (schema == null)
+                schema = LoadedSchemas.SingleOrDefault(s => string.Equals(s.Location, reference, StringComparison.Ordinal));
+
+            return schema;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaType.cs b/Newtonsoft.Json/Schema/JsonSchemaType.cs
new file mode 100644
index 0000000..53e0cdf
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaType.cs
@@ -0,0 +1,81 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// The value types allowed by the <see cref="JsonSchema"/>.
+    /// </summary>
+    [Flags]
+    public enum JsonSchemaType
+    {
+        /// <summary>
+        /// No type specified.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// String type.
+        /// </summary>
+        String = 1,
+
+        /// <summary>
+        /// Float type.
+        /// </summary>
+        Float = 2,
+
+        /// <summary>
+        /// Integer type.
+        /// </summary>
+        Integer = 4,
+
+        /// <summary>
+        /// Boolean type.
+        /// </summary>
+        Boolean = 8,
+
+        /// <summary>
+        /// Object type.
+        /// </summary>
+        Object = 16,
+
+        /// <summary>
+        /// Array type.
+        /// </summary>
+        Array = 32,
+
+        /// <summary>
+        /// Null type.
+        /// </summary>
+        Null = 64,
+
+        /// <summary>
+        /// Any type.
+        /// </summary>
+        Any = String | Float | Integer | Boolean | Object | Array | Null
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/JsonSchemaWriter.cs b/Newtonsoft.Json/Schema/JsonSchemaWriter.cs
new file mode 100644
index 0000000..816c606
--- /dev/null
+++ b/Newtonsoft.Json/Schema/JsonSchemaWriter.cs
@@ -0,0 +1,243 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.Generic;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Serialization;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Schema
+{
+    internal class JsonSchemaWriter
+    {
+        private readonly JsonWriter _writer;
+        private readonly JsonSchemaResolver _resolver;
+
+        public JsonSchemaWriter(JsonWriter writer, JsonSchemaResolver resolver)
+        {
+            ValidationUtils.ArgumentNotNull(writer, "writer");
+            _writer = writer;
+            _resolver = resolver;
+        }
+
+        private void ReferenceOrWriteSchema(JsonSchema schema)
+        {
+            if (schema.Id != null && _resolver.GetSchema(schema.Id) != null)
+            {
+                _writer.WriteStartObject();
+                _writer.WritePropertyName(JsonTypeReflector.RefPropertyName);
+                _writer.WriteValue(schema.Id);
+                _writer.WriteEndObject();
+            }
+            else
+            {
+                WriteSchema(schema);
+            }
+        }
+
+        public void WriteSchema(JsonSchema schema)
+        {
+            ValidationUtils.ArgumentNotNull(schema, "schema");
+
+            if (!_resolver.LoadedSchemas.Contains(schema))
+                _resolver.LoadedSchemas.Add(schema);
+
+            _writer.WriteStartObject();
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.IdPropertyName, schema.Id);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.TitlePropertyName, schema.Title);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.DescriptionPropertyName, schema.Description);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.RequiredPropertyName, schema.Required);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.ReadOnlyPropertyName, schema.ReadOnly);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.HiddenPropertyName, schema.Hidden);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.TransientPropertyName, schema.Transient);
+            if (schema.Type != null)
+                WriteType(JsonSchemaConstants.TypePropertyName, _writer, schema.Type.Value);
+            if (!schema.AllowAdditionalProperties)
+            {
+                _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName);
+                _writer.WriteValue(schema.AllowAdditionalProperties);
+            }
+            else
+            {
+                if (schema.AdditionalProperties != null)
+                {
+                    _writer.WritePropertyName(JsonSchemaConstants.AdditionalPropertiesPropertyName);
+                    ReferenceOrWriteSchema(schema.AdditionalProperties);
+                }
+            }
+            if (!schema.AllowAdditionalItems)
+            {
+                _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName);
+                _writer.WriteValue(schema.AllowAdditionalItems);
+            }
+            else
+            {
+                if (schema.AdditionalItems != null)
+                {
+                    _writer.WritePropertyName(JsonSchemaConstants.AdditionalItemsPropertyName);
+                    ReferenceOrWriteSchema(schema.AdditionalItems);
+                }
+            }
+            WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PropertiesPropertyName, schema.Properties);
+            WriteSchemaDictionaryIfNotNull(_writer, JsonSchemaConstants.PatternPropertiesPropertyName, schema.PatternProperties);
+            WriteItems(schema);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumPropertyName, schema.Minimum);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumPropertyName, schema.Maximum);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMinimumPropertyName, schema.ExclusiveMinimum);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.ExclusiveMaximumPropertyName, schema.ExclusiveMaximum);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumLengthPropertyName, schema.MinimumLength);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumLengthPropertyName, schema.MaximumLength);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MinimumItemsPropertyName, schema.MinimumItems);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.MaximumItemsPropertyName, schema.MaximumItems);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.DivisibleByPropertyName, schema.DivisibleBy);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.FormatPropertyName, schema.Format);
+            WritePropertyIfNotNull(_writer, JsonSchemaConstants.PatternPropertyName, schema.Pattern);
+            if (schema.Enum != null)
+            {
+                _writer.WritePropertyName(JsonSchemaConstants.EnumPropertyName);
+                _writer.WriteStartArray();
+                foreach (JToken token in schema.Enum)
+                {
+                    token.WriteTo(_writer);
+                }
+                _writer.WriteEndArray();
+            }
+            if (schema.Default != null)
+            {
+                _writer.WritePropertyName(JsonSchemaConstants.DefaultPropertyName);
+                schema.Default.WriteTo(_writer);
+            }
+            if (schema.Disallow != null)
+                WriteType(JsonSchemaConstants.DisallowPropertyName, _writer, schema.Disallow.Value);
+            if (schema.Extends != null && schema.Extends.Count > 0)
+            {
+                _writer.WritePropertyName(JsonSchemaConstants.ExtendsPropertyName);
+                if (schema.Extends.Count == 1)
+                {
+                    ReferenceOrWriteSchema(schema.Extends[0]);
+                }
+                else
+                {
+                    _writer.WriteStartArray();
+                    foreach (JsonSchema jsonSchema in schema.Extends)
+                    {
+                        ReferenceOrWriteSchema(jsonSchema);
+                    }
+                    _writer.WriteEndArray();
+                }
+            }
+            _writer.WriteEndObject();
+        }
+
+        private void WriteSchemaDictionaryIfNotNull(JsonWriter writer, string propertyName, IDictionary<string, JsonSchema> properties)
+        {
+            if (properties != null)
+            {
+                writer.WritePropertyName(propertyName);
+                writer.WriteStartObject();
+                foreach (KeyValuePair<string, JsonSchema> property in properties)
+                {
+                    writer.WritePropertyName(property.Key);
+                    ReferenceOrWriteSchema(property.Value);
+                }
+                writer.WriteEndObject();
+            }
+        }
+
+        private void WriteItems(JsonSchema schema)
+        {
+            if (schema.Items == null && !schema.PositionalItemsValidation)
+                return;
+
+            _writer.WritePropertyName(JsonSchemaConstants.ItemsPropertyName);
+
+            if (!schema.PositionalItemsValidation)
+            {
+                if (schema.Items != null && schema.Items.Count > 0)
+                {
+                    ReferenceOrWriteSchema(schema.Items[0]);
+                }
+                else
+                {
+                    _writer.WriteStartObject();
+                    _writer.WriteEndObject();
+                }
+                return;
+            }
+
+            _writer.WriteStartArray();
+            if (schema.Items != null)
+            {
+                foreach (JsonSchema itemSchema in schema.Items)
+                {
+                    ReferenceOrWriteSchema(itemSchema);
+                }
+            }
+            _writer.WriteEndArray();
+        }
+
+        private void WriteType(string propertyName, JsonWriter writer, JsonSchemaType type)
+        {
+            IList<JsonSchemaType> types;
+            if (System.Enum.IsDefined(typeof(JsonSchemaType), type))
+                types = new List<JsonSchemaType> { type };
+            else
+                types = EnumUtils.GetFlagsValues(type).Where(v => v != JsonSchemaType.None).ToList();
+
+            if (types.Count == 0)
+                return;
+
+            writer.WritePropertyName(propertyName);
+
+            if (types.Count == 1)
+            {
+                writer.WriteValue(JsonSchemaBuilder.MapType(types[0]));
+                return;
+            }
+
+            writer.WriteStartArray();
+            foreach (JsonSchemaType jsonSchemaType in types)
+            {
+                writer.WriteValue(JsonSchemaBuilder.MapType(jsonSchemaType));
+            }
+            writer.WriteEndArray();
+        }
+
+        private void WritePropertyIfNotNull(JsonWriter writer, string propertyName, object value)
+        {
+            if (value != null)
+            {
+                writer.WritePropertyName(propertyName);
+                writer.WriteValue(value);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs b/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs
new file mode 100644
index 0000000..fc08593
--- /dev/null
+++ b/Newtonsoft.Json/Schema/UndefinedSchemaIdHandling.cs
@@ -0,0 +1,48 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Specifies undefined schema Id handling options for the <see cref="JsonSchemaGenerator"/>.
+    /// </summary>
+    public enum UndefinedSchemaIdHandling
+    {
+        /// <summary>
+        /// Do not infer a schema Id.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// Use the .NET type name as the schema Id.
+        /// </summary>
+        UseTypeName = 1,
+
+        /// <summary>
+        /// Use the assembly qualified .NET type name as the schema Id.
+        /// </summary>
+        UseAssemblyQualifiedName = 2,
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/ValidationEventArgs.cs b/Newtonsoft.Json/Schema/ValidationEventArgs.cs
new file mode 100644
index 0000000..b078138
--- /dev/null
+++ b/Newtonsoft.Json/Schema/ValidationEventArgs.cs
@@ -0,0 +1,71 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Returns detailed information related to the <see cref="ValidationEventHandler"/>.
+    /// </summary>
+    public class ValidationEventArgs : EventArgs
+    {
+        private readonly JsonSchemaException _ex;
+
+        internal ValidationEventArgs(JsonSchemaException ex)
+        {
+            ValidationUtils.ArgumentNotNull(ex, "ex");
+            _ex = ex;
+        }
+
+        /// <summary>
+        /// Gets the <see cref="JsonSchemaException"/> associated with the validation error.
+        /// </summary>
+        /// <value>The JsonSchemaException associated with the validation error.</value>
+        public JsonSchemaException Exception
+        {
+            get { return _ex; }
+        }
+
+        /// <summary>
+        /// Gets the path of the JSON location where the validation error occurred.
+        /// </summary>
+        /// <value>The path of the JSON location where the validation error occurred.</value>
+        public string Path
+        {
+            get { return _ex.Path; }
+        }
+
+        /// <summary>
+        /// Gets the text description corresponding to the validation error.
+        /// </summary>
+        /// <value>The text description.</value>
+        public string Message
+        {
+            get { return _ex.Message; }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Schema/ValidationEventHandler.cs b/Newtonsoft.Json/Schema/ValidationEventHandler.cs
new file mode 100644
index 0000000..11e7ecf
--- /dev/null
+++ b/Newtonsoft.Json/Schema/ValidationEventHandler.cs
@@ -0,0 +1,32 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Schema
+{
+    /// <summary>
+    /// Represents the callback method that will handle JSON schema validation events and the <see cref="ValidationEventArgs"/>.
+    /// </summary>
+    public delegate void ValidationEventHandler(object sender, ValidationEventArgs e);
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs b/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs
new file mode 100644
index 0000000..db898b1
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/CachedAttributeGetter.cs
@@ -0,0 +1,41 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal static class CachedAttributeGetter<T> where T : Attribute
+    {
+        private static readonly ThreadSafeStore<object, T> TypeAttributeCache = new ThreadSafeStore<object, T>(JsonTypeReflector.GetAttribute<T>);
+
+        public static T GetAttribute(object type)
+        {
+            return TypeAttributeCache.Get(type);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs b/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
new file mode 100644
index 0000000..e39109a
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/CamelCasePropertyNamesContractResolver.cs
@@ -0,0 +1,55 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Resolves member mappings for a type, camel casing property names.
+    /// </summary>
+    public class CamelCasePropertyNamesContractResolver : DefaultContractResolver
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="CamelCasePropertyNamesContractResolver"/> class.
+        /// </summary>
+        public CamelCasePropertyNamesContractResolver()
+            : base(true)
+        {
+        }
+
+        /// <summary>
+        /// Resolves the name of the property.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>The property name camel cased.</returns>
+        protected internal override string ResolvePropertyName(string propertyName)
+        {
+            // lower case the first letter of the passed in name
+            return StringUtils.ToCamelCase(propertyName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/DefaultContractResolver.cs b/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
new file mode 100644
index 0000000..ed8d15a
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/DefaultContractResolver.cs
@@ -0,0 +1,1342 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+#if !(NET35 || NET20 || PORTABLE || PORTABLE40)
+using System.Collections.Concurrent;
+#endif
+using System.Collections.Generic;
+using System.ComponentModel;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+#endif
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.Serialization;
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+using System.Security.Permissions;
+#endif
+using System.Xml.Serialization;
+using Newtonsoft.Json.Converters;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+using System.Runtime.CompilerServices;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal struct ResolverContractKey : IEquatable<ResolverContractKey>
+    {
+        private readonly Type _resolverType;
+        private readonly Type _contractType;
+
+        public ResolverContractKey(Type resolverType, Type contractType)
+        {
+            _resolverType = resolverType;
+            _contractType = contractType;
+        }
+
+        public override int GetHashCode()
+        {
+            return _resolverType.GetHashCode() ^ _contractType.GetHashCode();
+        }
+
+        public override bool Equals(object obj)
+        {
+            if (!(obj is ResolverContractKey))
+                return false;
+
+            return Equals((ResolverContractKey)obj);
+        }
+
+        public bool Equals(ResolverContractKey other)
+        {
+            return (_resolverType == other._resolverType && _contractType == other._contractType);
+        }
+    }
+
+    /// <summary>
+    /// Used by <see cref="JsonSerializer"/> to resolves a <see cref="JsonContract"/> for a given <see cref="Type"/>.
+    /// </summary>
+    public class DefaultContractResolver : IContractResolver
+    {
+        private static readonly IContractResolver _instance = new DefaultContractResolver(true);
+
+        internal static IContractResolver Instance
+        {
+            get { return _instance; }
+        }
+
+        private static readonly IList<JsonConverter> BuiltInConverters = new List<JsonConverter>
+        {
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+            new EntityKeyMemberConverter(),
+#endif
+#if !(NET35 || NET20 || PORTABLE40)
+            new ExpandoObjectConverter(),
+#endif
+#if !(PORTABLE40)
+            new XmlNodeConverter(),
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            new BinaryConverter(),
+            new DataSetConverter(),
+            new DataTableConverter(),
+#endif
+#if NETFX_CORE
+            new JsonValueConverter(),
+#endif
+#if !(NET35 || NET20 || NETFX_CORE)
+            new DiscriminatedUnionConverter(),
+#endif
+            new KeyValuePairConverter(),
+            new BsonObjectIdConverter(),
+            new RegexConverter()
+        };
+
+        private static Dictionary<ResolverContractKey, JsonContract> _sharedContractCache;
+        private static readonly object _typeContractCacheLock = new object();
+
+        private Dictionary<ResolverContractKey, JsonContract> _instanceContractCache;
+        private readonly bool _sharedCache;
+
+        /// <summary>
+        /// Gets a value indicating whether members are being get and set using dynamic code generation.
+        /// This value is determined by the runtime permissions available.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if using dynamic code generation; otherwise, <c>false</c>.
+        /// </value>
+        public bool DynamicCodeGeneration
+        {
+            get { return JsonTypeReflector.DynamicCodeGeneration; }
+        }
+
+#if !(NETFX_CORE || PORTABLE)
+        /// <summary>
+        /// Gets or sets the default members search flags.
+        /// </summary>
+        /// <value>The default members search flags.</value>
+        [ObsoleteAttribute("DefaultMembersSearchFlags is obsolete. To modify the members serialized inherit from DefaultContractResolver and override the GetSerializableMembers method instead.")] 
+        public BindingFlags DefaultMembersSearchFlags { get; set; }
+#else
+        private BindingFlags DefaultMembersSearchFlags = BindingFlags.Instance | BindingFlags.Public;
+#endif
+
+        /// <summary>
+        /// Gets or sets a value indicating whether compiler generated members should be serialized.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if serialized compiler generated members; otherwise, <c>false</c>.
+        /// </value>
+        public bool SerializeCompilerGeneratedMembers { get; set; }
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        /// <summary>
+        /// Gets or sets a value indicating whether to ignore the <see cref="ISerializable"/> interface when serializing and deserializing types.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if the <see cref="ISerializable"/> interface will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
+        /// </value>
+        public bool IgnoreSerializableInterface { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to ignore the <see cref="SerializableAttribute"/> attribute when serializing and deserializing types.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if the <see cref="SerializableAttribute"/> attribute will be ignored when serializing and deserializing types; otherwise, <c>false</c>.
+        /// </value>
+        public bool IgnoreSerializableAttribute { get; set; }
+#endif
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DefaultContractResolver"/> class.
+        /// </summary>
+        public DefaultContractResolver()
+            : this(false)
+        {
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DefaultContractResolver"/> class.
+        /// </summary>
+        /// <param name="shareCache">
+        /// If set to <c>true</c> the <see cref="DefaultContractResolver"/> will use a cached shared with other resolvers of the same type.
+        /// Sharing the cache will significantly performance because expensive reflection will only happen once but could cause unexpected
+        /// behavior if different instances of the resolver are suppose to produce different results. When set to false it is highly
+        /// recommended to reuse <see cref="DefaultContractResolver"/> instances with the <see cref="JsonSerializer"/>.
+        /// </param>
+        public DefaultContractResolver(bool shareCache)
+        {
+#if !NETFX_CORE
+#pragma warning disable 618
+            DefaultMembersSearchFlags = BindingFlags.Public | BindingFlags.Instance;
+#pragma warning restore 618
+#endif
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+            IgnoreSerializableAttribute = true;
+#endif
+
+            _sharedCache = shareCache;
+        }
+
+        private Dictionary<ResolverContractKey, JsonContract> GetCache()
+        {
+            if (_sharedCache)
+                return _sharedContractCache;
+            else
+                return _instanceContractCache;
+        }
+
+        private void UpdateCache(Dictionary<ResolverContractKey, JsonContract> cache)
+        {
+            if (_sharedCache)
+                _sharedContractCache = cache;
+            else
+                _instanceContractCache = cache;
+        }
+
+        /// <summary>
+        /// Resolves the contract for a given type.
+        /// </summary>
+        /// <param name="type">The type to resolve a contract for.</param>
+        /// <returns>The contract for a given type.</returns>
+        public virtual JsonContract ResolveContract(Type type)
+        {
+            if (type == null)
+                throw new ArgumentNullException("type");
+
+            JsonContract contract;
+            ResolverContractKey key = new ResolverContractKey(GetType(), type);
+            Dictionary<ResolverContractKey, JsonContract> cache = GetCache();
+            if (cache == null || !cache.TryGetValue(key, out contract))
+            {
+                contract = CreateContract(type);
+
+                // avoid the possibility of modifying the cache dictionary while another thread is accessing it
+                lock (_typeContractCacheLock)
+                {
+                    cache = GetCache();
+                    Dictionary<ResolverContractKey, JsonContract> updatedCache =
+                        (cache != null)
+                            ? new Dictionary<ResolverContractKey, JsonContract>(cache)
+                            : new Dictionary<ResolverContractKey, JsonContract>();
+                    updatedCache[key] = contract;
+
+                    UpdateCache(updatedCache);
+                }
+            }
+
+            return contract;
+        }
+
+        /// <summary>
+        /// Gets the serializable members for the type.
+        /// </summary>
+        /// <param name="objectType">The type to get serializable members for.</param>
+        /// <returns>The serializable members for the type.</returns>
+        protected virtual List<MemberInfo> GetSerializableMembers(Type objectType)
+        {
+            bool ignoreSerializableAttribute;
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+            ignoreSerializableAttribute = IgnoreSerializableAttribute;
+#else
+            ignoreSerializableAttribute = true;
+#endif
+
+            MemberSerialization memberSerialization = JsonTypeReflector.GetObjectMemberSerialization(objectType, ignoreSerializableAttribute);
+
+            List<MemberInfo> allMembers = ReflectionUtils.GetFieldsAndProperties(objectType, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)
+                .Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
+
+            List<MemberInfo> serializableMembers = new List<MemberInfo>();
+
+            if (memberSerialization != MemberSerialization.Fields)
+            {
+#if !NET20
+                DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(objectType);
+#endif
+
+#pragma warning disable 618
+                List<MemberInfo> defaultMembers = ReflectionUtils.GetFieldsAndProperties(objectType, DefaultMembersSearchFlags)
+                    .Where(m => !ReflectionUtils.IsIndexedProperty(m)).ToList();
+#pragma warning restore 618
+
+                foreach (MemberInfo member in allMembers)
+                {
+                    // exclude members that are compiler generated if set
+                    if (SerializeCompilerGeneratedMembers || !member.IsDefined(typeof(CompilerGeneratedAttribute), true))
+                    {
+                        if (defaultMembers.Contains(member))
+                        {
+                            // add all members that are found by default member search
+                            serializableMembers.Add(member);
+                        }
+                        else
+                        {
+                            // add members that are explicitly marked with JsonProperty/DataMember attribute
+                            // or are a field if serializing just fields
+                            if (JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(member) != null)
+                                serializableMembers.Add(member);
+#if !NET20
+                            else if (dataContractAttribute != null && JsonTypeReflector.GetAttribute<DataMemberAttribute>(member) != null)
+                                serializableMembers.Add(member);
+#endif
+                            else if (memberSerialization == MemberSerialization.Fields && member.MemberType() == MemberTypes.Field)
+                                serializableMembers.Add(member);
+                        }
+                    }
+                }
+
+#if !NET20
+                Type match;
+                // don't include EntityKey on entities objects... this is a bit hacky
+                if (objectType.AssignableToTypeName("System.Data.Objects.DataClasses.EntityObject", out match))
+                    serializableMembers = serializableMembers.Where(ShouldSerializeEntityMember).ToList();
+#endif
+            }
+            else
+            {
+                // serialize all fields
+                foreach (MemberInfo member in allMembers)
+                {
+                    FieldInfo field = member as FieldInfo;
+                    if (field != null && !field.IsStatic)
+                        serializableMembers.Add(member);
+                }
+            }
+
+            return serializableMembers;
+        }
+
+#if !NET20
+        private bool ShouldSerializeEntityMember(MemberInfo memberInfo)
+        {
+            PropertyInfo propertyInfo = memberInfo as PropertyInfo;
+            if (propertyInfo != null)
+            {
+                if (propertyInfo.PropertyType.IsGenericType() && propertyInfo.PropertyType.GetGenericTypeDefinition().FullName == "System.Data.Objects.DataClasses.EntityReference`1")
+                    return false;
+            }
+
+            return true;
+        }
+#endif
+
+        /// <summary>
+        /// Creates a <see cref="JsonObjectContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonObjectContract"/> for the given type.</returns>
+        protected virtual JsonObjectContract CreateObjectContract(Type objectType)
+        {
+            JsonObjectContract contract = new JsonObjectContract(objectType);
+            InitializeContract(contract);
+
+            bool ignoreSerializableAttribute;
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+            ignoreSerializableAttribute = IgnoreSerializableAttribute;
+#else
+            ignoreSerializableAttribute = true;
+#endif
+
+            contract.MemberSerialization = JsonTypeReflector.GetObjectMemberSerialization(contract.NonNullableUnderlyingType, ignoreSerializableAttribute);
+            contract.Properties.AddRange(CreateProperties(contract.NonNullableUnderlyingType, contract.MemberSerialization));
+
+            JsonObjectAttribute attribute = JsonTypeReflector.GetJsonObjectAttribute(contract.NonNullableUnderlyingType);
+            if (attribute != null)
+                contract.ItemRequired = attribute._itemRequired;
+
+            ConstructorInfo overrideConstructor = GetAttributeConstructor(contract.NonNullableUnderlyingType);
+
+            // check if a JsonConstructorAttribute has been defined and use that
+            if (overrideConstructor != null)
+            {
+                contract.OverrideConstructor = overrideConstructor;
+                contract.ConstructorParameters.AddRange(CreateConstructorParameters(overrideConstructor, contract.Properties));
+            }
+            else if (contract.MemberSerialization == MemberSerialization.Fields)
+            {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                // mimic DataContractSerializer behaviour when populating fields by overriding default creator to create an uninitialized object
+                // note that this is only possible when the application is fully trusted so fall back to using the default constructor (if available) in partial trust
+                if (JsonTypeReflector.FullyTrusted)
+                    contract.DefaultCreator = contract.GetUninitializedObject;
+#endif
+            }
+            else if (contract.DefaultCreator == null || contract.DefaultCreatorNonPublic)
+            {
+                ConstructorInfo constructor = GetParametrizedConstructor(contract.NonNullableUnderlyingType);
+                if (constructor != null)
+                {
+                    contract.ParametrizedConstructor = constructor;
+                    contract.ConstructorParameters.AddRange(CreateConstructorParameters(constructor, contract.Properties));
+                }
+            }
+
+            MemberInfo extensionDataMember = GetExtensionDataMemberForType(contract.NonNullableUnderlyingType);
+            if (extensionDataMember != null)
+                SetExtensionDataDelegates(contract, extensionDataMember);
+
+            return contract;
+        }
+
+        private MemberInfo GetExtensionDataMemberForType(Type type)
+        {
+            IEnumerable<MemberInfo> members = GetClassHierarchyForType(type).SelectMany(baseType =>
+            {
+                IList<MemberInfo> m = new List<MemberInfo>();
+                m.AddRange(baseType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+                m.AddRange(baseType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
+
+                return m;
+            });
+
+            MemberInfo extensionDataMember = members.LastOrDefault(m =>
+            {
+                MemberTypes memberType = m.MemberType();
+                if (memberType != MemberTypes.Property && memberType != MemberTypes.Field)
+                    return false;
+
+                // last instance of attribute wins on type if there are multiple
+                if (!m.IsDefined(typeof(JsonExtensionDataAttribute), false))
+                    return false;
+
+                Type t = ReflectionUtils.GetMemberUnderlyingType(m);
+
+                Type dictionaryType;
+                if (ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out dictionaryType))
+                {
+                    Type keyType = dictionaryType.GetGenericArguments()[0];
+                    Type valueType = dictionaryType.GetGenericArguments()[1];
+
+                    if (keyType.IsAssignableFrom(typeof(string)) && valueType.IsAssignableFrom(typeof(JToken)))
+                        return true;
+                }
+
+                throw new JsonException("Invalid extension data attribute on '{0}'. Member '{1}' type must implement IDictionary<string, JToken>.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(m.DeclaringType), m.Name));
+            });
+
+            return extensionDataMember;
+        }
+
+        private static void SetExtensionDataDelegates(JsonObjectContract contract, MemberInfo member)
+        {
+            JsonExtensionDataAttribute extensionDataAttribute = ReflectionUtils.GetAttribute<JsonExtensionDataAttribute>(member);
+            if (extensionDataAttribute == null)
+                return;
+
+            Type t = ReflectionUtils.GetMemberUnderlyingType(member);
+
+            Type dictionaryType;
+            ReflectionUtils.ImplementsGenericDefinition(t, typeof(IDictionary<,>), out dictionaryType);
+
+            Type keyType = dictionaryType.GetGenericArguments()[0];
+            Type valueType = dictionaryType.GetGenericArguments()[1];
+            bool isJTokenValueType = typeof(JToken).IsAssignableFrom(valueType);
+
+            // change type to a class if it is the base interface so it can be instantiated if needed
+            if (ReflectionUtils.IsGenericDefinition(t, typeof(IDictionary<,>)))
+                t = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
+
+            MethodInfo addMethod = t.GetMethod("Add", new[] { keyType, valueType });
+            Func<object, object> getExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(member);
+            Action<object, object> setExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(member);
+            Func<object> createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(t);
+            MethodCall<object, object> setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(addMethod);
+
+            ExtensionDataSetter extensionDataSetter = (o, key, value) =>
+            {
+                object dictionary = getExtensionDataDictionary(o);
+                if (dictionary == null)
+                {
+                    dictionary = createExtensionDataDictionary();
+                    setExtensionDataDictionary(o, dictionary);
+                }
+
+                // convert object value to JToken so it is compatible with dictionary
+                // could happen because of primitive types, type name handling and references
+                if (isJTokenValueType && !(value is JToken))
+                    value = (value != null) ? JToken.FromObject(value) : new JValue(null, JTokenType.Null);
+
+                setExtensionDataDictionaryValue(dictionary, key, value);
+            };
+
+            Type enumerableWrapper = typeof(DictionaryEnumerator<,>).MakeGenericType(keyType, valueType);
+            ConstructorInfo constructors = enumerableWrapper.GetConstructors().First();
+            MethodCall<object, object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(constructors);
+
+            ExtensionDataGetter extensionDataGetter = o =>
+            {
+                object dictionary = getExtensionDataDictionary(o);
+                if (dictionary == null)
+                    return null;
+
+                return (IEnumerable<KeyValuePair<object, object>>)createEnumerableWrapper(null, dictionary);
+            };
+
+            if (extensionDataAttribute.ReadData)
+                contract.ExtensionDataSetter = extensionDataSetter;
+
+            if (extensionDataAttribute.WriteData)
+                contract.ExtensionDataGetter = extensionDataGetter;
+        }
+
+        internal struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IEnumerable<KeyValuePair<object, object>>, IEnumerator<KeyValuePair<object, object>>
+        {
+            private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
+
+            public DictionaryEnumerator(IEnumerable<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
+            {
+                ValidationUtils.ArgumentNotNull(e, "e");
+                _e = e.GetEnumerator();
+            }
+
+            public bool MoveNext()
+            {
+                return _e.MoveNext();
+            }
+
+            public void Reset()
+            {
+                _e.Reset();
+            }
+
+            public KeyValuePair<object, object> Current
+            {
+                get { return new KeyValuePair<object, object>(_e.Current.Key, _e.Current.Value); }
+            }
+
+            public void Dispose()
+            {
+                _e.Dispose();
+            }
+
+            object IEnumerator.Current
+            {
+                get { return Current; }
+            }
+
+            public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
+            {
+                return this;
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return this;
+            }
+        }
+
+        private ConstructorInfo GetAttributeConstructor(Type objectType)
+        {
+            IList<ConstructorInfo> markedConstructors = objectType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Where(c => c.IsDefined(typeof(JsonConstructorAttribute), true)).ToList();
+
+            if (markedConstructors.Count > 1)
+                throw new JsonException("Multiple constructors with the JsonConstructorAttribute.");
+            else if (markedConstructors.Count == 1)
+                return markedConstructors[0];
+
+            // little hack to get Version objects to deserialize correctly
+            if (objectType == typeof(Version))
+                return objectType.GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(int) });
+
+            return null;
+        }
+
+        private ConstructorInfo GetParametrizedConstructor(Type objectType)
+        {
+            IList<ConstructorInfo> constructors = objectType.GetConstructors(BindingFlags.Public | BindingFlags.Instance).ToList();
+
+            if (constructors.Count == 1)
+                return constructors[0];
+            else
+                return null;
+        }
+
+        /// <summary>
+        /// Creates the constructor parameters.
+        /// </summary>
+        /// <param name="constructor">The constructor to create properties for.</param>
+        /// <param name="memberProperties">The type's member properties.</param>
+        /// <returns>Properties for the given <see cref="ConstructorInfo"/>.</returns>
+        protected virtual IList<JsonProperty> CreateConstructorParameters(ConstructorInfo constructor, JsonPropertyCollection memberProperties)
+        {
+            var constructorParameters = constructor.GetParameters();
+
+            JsonPropertyCollection parameterCollection = new JsonPropertyCollection(constructor.DeclaringType);
+
+            foreach (ParameterInfo parameterInfo in constructorParameters)
+            {
+                // it is possible to generate a ParameterInfo with a null name using Reflection.Emit
+                // protect against an ArgumentNullException from GetClosestMatchProperty by testing for null here
+                JsonProperty matchingMemberProperty = (parameterInfo.Name != null) ? memberProperties.GetClosestMatchProperty(parameterInfo.Name) : null;
+
+                // type must match as well as name
+                if (matchingMemberProperty != null && matchingMemberProperty.PropertyType != parameterInfo.ParameterType)
+                    matchingMemberProperty = null;
+
+                // ensure that property will have a name from matching property or from parameterinfo
+                // parameterinfo could have no name if generated by a proxy (I'm looking at you Castle)
+                if (matchingMemberProperty != null || parameterInfo.Name != null)
+                {
+                    JsonProperty property = CreatePropertyFromConstructorParameter(matchingMemberProperty, parameterInfo);
+
+                    if (property != null)
+                    {
+                        parameterCollection.AddProperty(property);
+                    }
+                }
+            }
+
+            return parameterCollection;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonProperty"/> for the given <see cref="ParameterInfo"/>.
+        /// </summary>
+        /// <param name="matchingMemberProperty">The matching member property.</param>
+        /// <param name="parameterInfo">The constructor parameter.</param>
+        /// <returns>A created <see cref="JsonProperty"/> for the given <see cref="ParameterInfo"/>.</returns>
+        protected virtual JsonProperty CreatePropertyFromConstructorParameter(JsonProperty matchingMemberProperty, ParameterInfo parameterInfo)
+        {
+            JsonProperty property = new JsonProperty();
+            property.PropertyType = parameterInfo.ParameterType;
+
+            bool allowNonPublicAccess;
+            SetPropertySettingsFromAttributes(property, parameterInfo, parameterInfo.Name, parameterInfo.Member.DeclaringType, MemberSerialization.OptOut, out allowNonPublicAccess);
+
+            property.Readable = false;
+            property.Writable = true;
+
+            // "inherit" values from matching member property if unset on parameter
+            if (matchingMemberProperty != null)
+            {
+                property.PropertyName = (property.PropertyName != parameterInfo.Name) ? property.PropertyName : matchingMemberProperty.PropertyName;
+                property.Converter = property.Converter ?? matchingMemberProperty.Converter;
+                property.MemberConverter = property.MemberConverter ?? matchingMemberProperty.MemberConverter;
+
+                if (!property._hasExplicitDefaultValue && matchingMemberProperty._hasExplicitDefaultValue)
+                    property.DefaultValue = matchingMemberProperty.DefaultValue;
+
+                property._required = property._required ?? matchingMemberProperty._required;
+                property.IsReference = property.IsReference ?? matchingMemberProperty.IsReference;
+                property.NullValueHandling = property.NullValueHandling ?? matchingMemberProperty.NullValueHandling;
+                property.DefaultValueHandling = property.DefaultValueHandling ?? matchingMemberProperty.DefaultValueHandling;
+                property.ReferenceLoopHandling = property.ReferenceLoopHandling ?? matchingMemberProperty.ReferenceLoopHandling;
+                property.ObjectCreationHandling = property.ObjectCreationHandling ?? matchingMemberProperty.ObjectCreationHandling;
+                property.TypeNameHandling = property.TypeNameHandling ?? matchingMemberProperty.TypeNameHandling;
+            }
+
+            return property;
+        }
+
+        /// <summary>
+        /// Resolves the default <see cref="JsonConverter" /> for the contract.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>The contract's default <see cref="JsonConverter" />.</returns>
+        protected virtual JsonConverter ResolveContractConverter(Type objectType)
+        {
+            return JsonTypeReflector.GetJsonConverter(objectType, objectType);
+        }
+
+        private Func<object> GetDefaultCreator(Type createdType)
+        {
+            return JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(createdType);
+        }
+
+#if !NET20
+        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Portability", "CA1903:UseOnlyApiFromTargetedFramework", MessageId = "System.Runtime.Serialization.DataContractAttribute.#get_IsReference()")]
+#endif
+        private void InitializeContract(JsonContract contract)
+        {
+            JsonContainerAttribute containerAttribute = JsonTypeReflector.GetJsonContainerAttribute(contract.NonNullableUnderlyingType);
+            if (containerAttribute != null)
+            {
+                contract.IsReference = containerAttribute._isReference;
+            }
+#if !NET20
+            else
+            {
+                DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(contract.NonNullableUnderlyingType);
+                // doesn't have a null value
+                if (dataContractAttribute != null && dataContractAttribute.IsReference)
+                    contract.IsReference = true;
+            }
+#endif
+
+            contract.Converter = ResolveContractConverter(contract.NonNullableUnderlyingType);
+
+            // then see whether object is compadible with any of the built in converters
+            contract.InternalConverter = JsonSerializer.GetMatchingConverter(BuiltInConverters, contract.NonNullableUnderlyingType);
+
+            if (ReflectionUtils.HasDefaultConstructor(contract.CreatedType, true)
+                || contract.CreatedType.IsValueType())
+            {
+                contract.DefaultCreator = GetDefaultCreator(contract.CreatedType);
+
+                contract.DefaultCreatorNonPublic = (!contract.CreatedType.IsValueType() &&
+                                                    ReflectionUtils.GetDefaultConstructor(contract.CreatedType) == null);
+            }
+
+            ResolveCallbackMethods(contract, contract.NonNullableUnderlyingType);
+        }
+
+        private void ResolveCallbackMethods(JsonContract contract, Type t)
+        {
+            List<SerializationCallback> onSerializing;
+            List<SerializationCallback> onSerialized;
+            List<SerializationCallback> onDeserializing;
+            List<SerializationCallback> onDeserialized;
+            List<SerializationErrorCallback> onError;
+
+            GetCallbackMethodsForType(t, out onSerializing, out onSerialized, out onDeserializing, out onDeserialized, out onError);
+
+            if (onSerializing != null)
+            {
+#if !(NET35 || NET20 || NETFX_CORE)
+                if (t.Name != FSharpUtils.FSharpSetTypeName && t.Name != FSharpUtils.FSharpMapTypeName)
+#endif
+                {
+#if NETFX_CORE
+                    if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
+                         contract.OnSerializingCallbacks.AddRange(onSerializing);
+#else
+                    contract.OnSerializingCallbacks.AddRange(onSerializing);
+#endif
+                }
+            }
+
+            if (onSerialized != null)
+                contract.OnSerializedCallbacks.AddRange(onSerialized);
+
+            if (onDeserializing != null)
+            {
+                contract.OnDeserializingCallbacks.AddRange(onDeserializing);
+            }
+
+            if (onDeserialized != null)
+            {
+#if !(NET35 || NET20 || NETFX_CORE)
+                if (t.Name != FSharpUtils.FSharpSetTypeName && t.Name != FSharpUtils.FSharpMapTypeName)
+#endif
+                {
+                    // ConcurrentDictionary throws an error here so don't use its OnDeserialized - http://json.codeplex.com/discussions/257093
+#if !(NET35 || NET20 || PORTABLE || PORTABLE40)
+                    if (!t.IsGenericType() || (t.GetGenericTypeDefinition() != typeof(ConcurrentDictionary<,>)))
+                        contract.OnDeserializedCallbacks.AddRange(onDeserialized);
+#else
+                    contract.OnDeserializedCallbacks.AddRange(onDeserialized);
+#endif
+                }
+            }
+
+            if (onError != null)
+                contract.OnErrorCallbacks.AddRange(onError);
+        }
+
+        private void GetCallbackMethodsForType(Type type, out List<SerializationCallback> onSerializing, out List<SerializationCallback> onSerialized, out List<SerializationCallback> onDeserializing, out List<SerializationCallback> onDeserialized, out List<SerializationErrorCallback> onError)
+        {
+            onSerializing = null;
+            onSerialized = null;
+            onDeserializing = null;
+            onDeserialized = null;
+            onError = null;
+
+            foreach (Type baseType in GetClassHierarchyForType(type))
+            {
+                // while we allow more than one OnSerialized total, only one can be defined per class
+                MethodInfo currentOnSerializing = null;
+                MethodInfo currentOnSerialized = null;
+                MethodInfo currentOnDeserializing = null;
+                MethodInfo currentOnDeserialized = null;
+                MethodInfo currentOnError = null;
+
+                foreach (MethodInfo method in baseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
+                {
+                    // compact framework errors when getting parameters for a generic method
+                    // lame, but generic methods should not be callbacks anyway
+                    if (method.ContainsGenericParameters)
+                        continue;
+
+                    Type prevAttributeType = null;
+                    ParameterInfo[] parameters = method.GetParameters();
+
+                    if (IsValidCallback(method, parameters, typeof(OnSerializingAttribute), currentOnSerializing, ref prevAttributeType))
+                    {
+                        onSerializing = onSerializing ?? new List<SerializationCallback>();
+                        onSerializing.Add(JsonContract.CreateSerializationCallback(method));
+                        currentOnSerializing = method;
+                    }
+                    if (IsValidCallback(method, parameters, typeof(OnSerializedAttribute), currentOnSerialized, ref prevAttributeType))
+                    {
+                        onSerialized = onSerialized ?? new List<SerializationCallback>();
+                        onSerialized.Add(JsonContract.CreateSerializationCallback(method));
+                        currentOnSerialized = method;
+                    }
+                    if (IsValidCallback(method, parameters, typeof(OnDeserializingAttribute), currentOnDeserializing, ref prevAttributeType))
+                    {
+                        onDeserializing = onDeserializing ?? new List<SerializationCallback>();
+                        onDeserializing.Add(JsonContract.CreateSerializationCallback(method));
+                        currentOnDeserializing = method;
+                    }
+                    if (IsValidCallback(method, parameters, typeof(OnDeserializedAttribute), currentOnDeserialized, ref prevAttributeType))
+                    {
+                        onDeserialized = onDeserialized ?? new List<SerializationCallback>();
+                        onDeserialized.Add(JsonContract.CreateSerializationCallback(method));
+                        currentOnDeserialized = method;
+                    }
+                    if (IsValidCallback(method, parameters, typeof(OnErrorAttribute), currentOnError, ref prevAttributeType))
+                    {
+                        onError = onError ?? new List<SerializationErrorCallback>();
+                        onError.Add(JsonContract.CreateSerializationErrorCallback(method));
+                        currentOnError = method;
+                    }
+                }
+            }
+        }
+
+        private List<Type> GetClassHierarchyForType(Type type)
+        {
+            List<Type> ret = new List<Type>();
+
+            Type current = type;
+            while (current != null && current != typeof(object))
+            {
+                ret.Add(current);
+                current = current.BaseType();
+            }
+
+            // Return the class list in order of simple => complex
+            ret.Reverse();
+            return ret;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonDictionaryContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonDictionaryContract"/> for the given type.</returns>
+        protected virtual JsonDictionaryContract CreateDictionaryContract(Type objectType)
+        {
+            JsonDictionaryContract contract = new JsonDictionaryContract(objectType);
+            InitializeContract(contract);
+
+            contract.PropertyNameResolver = ResolvePropertyName;
+
+            return contract;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonArrayContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonArrayContract"/> for the given type.</returns>
+        protected virtual JsonArrayContract CreateArrayContract(Type objectType)
+        {
+            JsonArrayContract contract = new JsonArrayContract(objectType);
+            InitializeContract(contract);
+
+            return contract;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonPrimitiveContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonPrimitiveContract"/> for the given type.</returns>
+        protected virtual JsonPrimitiveContract CreatePrimitiveContract(Type objectType)
+        {
+            JsonPrimitiveContract contract = new JsonPrimitiveContract(objectType);
+            InitializeContract(contract);
+
+            return contract;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonLinqContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonLinqContract"/> for the given type.</returns>
+        protected virtual JsonLinqContract CreateLinqContract(Type objectType)
+        {
+            JsonLinqContract contract = new JsonLinqContract(objectType);
+            InitializeContract(contract);
+
+            return contract;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        /// <summary>
+        /// Creates a <see cref="JsonISerializableContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonISerializableContract"/> for the given type.</returns>
+        protected virtual JsonISerializableContract CreateISerializableContract(Type objectType)
+        {
+            JsonISerializableContract contract = new JsonISerializableContract(objectType);
+            InitializeContract(contract);
+
+            ConstructorInfo constructorInfo = contract.NonNullableUnderlyingType.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new[] { typeof(SerializationInfo), typeof(StreamingContext) }, null);
+            if (constructorInfo != null)
+            {
+                MethodCall<object, object> methodCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(constructorInfo);
+
+                contract.ISerializableCreator = (args => methodCall(null, args));
+            }
+
+            return contract;
+        }
+#endif
+
+#if !(NET35 || NET20 || PORTABLE40)
+        /// <summary>
+        /// Creates a <see cref="JsonDynamicContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonDynamicContract"/> for the given type.</returns>
+        protected virtual JsonDynamicContract CreateDynamicContract(Type objectType)
+        {
+            JsonDynamicContract contract = new JsonDynamicContract(objectType);
+            InitializeContract(contract);
+
+            contract.PropertyNameResolver = ResolvePropertyName;
+            contract.Properties.AddRange(CreateProperties(objectType, MemberSerialization.OptOut));
+
+            return contract;
+        }
+#endif
+
+        /// <summary>
+        /// Creates a <see cref="JsonStringContract"/> for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonStringContract"/> for the given type.</returns>
+        protected virtual JsonStringContract CreateStringContract(Type objectType)
+        {
+            JsonStringContract contract = new JsonStringContract(objectType);
+            InitializeContract(contract);
+
+            return contract;
+        }
+
+        /// <summary>
+        /// Determines which contract type is created for the given type.
+        /// </summary>
+        /// <param name="objectType">Type of the object.</param>
+        /// <returns>A <see cref="JsonContract"/> for the given type.</returns>
+        protected virtual JsonContract CreateContract(Type objectType)
+        {
+            Type t = ReflectionUtils.EnsureNotNullableType(objectType);
+
+            if (IsJsonPrimitiveType(objectType))
+                return CreatePrimitiveContract(objectType);
+
+            if (JsonTypeReflector.GetJsonObjectAttribute(t) != null)
+                return CreateObjectContract(objectType);
+
+            if (JsonTypeReflector.GetJsonArrayAttribute(t) != null)
+                return CreateArrayContract(objectType);
+
+            if (JsonTypeReflector.GetJsonDictionaryAttribute(t) != null)
+                return CreateDictionaryContract(objectType);
+
+            if (t == typeof(JToken) || t.IsSubclassOf(typeof(JToken)))
+                return CreateLinqContract(objectType);
+
+            if (CollectionUtils.IsDictionaryType(t))
+                return CreateDictionaryContract(objectType);
+
+            if (typeof(IEnumerable).IsAssignableFrom(t))
+                return CreateArrayContract(objectType);
+
+            if (CanConvertToString(t))
+                return CreateStringContract(objectType);
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (!IgnoreSerializableInterface && typeof(ISerializable).IsAssignableFrom(t))
+                return CreateISerializableContract(objectType);
+#endif
+
+#if !(NET35 || NET20 || PORTABLE40)
+            if (typeof(IDynamicMetaObjectProvider).IsAssignableFrom(t))
+                return CreateDynamicContract(objectType);
+#endif
+
+#if !(PORTABLE || NETFX_CORE)
+            // tested last because it is not possible to automatically deserialize custom IConvertible types
+            if (IsIConvertible(t))
+                return CreatePrimitiveContract(t);
+#endif
+
+            return CreateObjectContract(objectType);
+        }
+
+        internal static bool IsJsonPrimitiveType(Type t)
+        {
+            PrimitiveTypeCode typeCode = ConvertUtils.GetTypeCode(t);
+
+            return (typeCode != PrimitiveTypeCode.Empty && typeCode != PrimitiveTypeCode.Object);
+        }
+
+#if !(PORTABLE || NETFX_CORE)
+        internal static bool IsIConvertible(Type t)
+        {
+            if (typeof(IConvertible).IsAssignableFrom(t)
+                || (ReflectionUtils.IsNullableType(t) && typeof(IConvertible).IsAssignableFrom(Nullable.GetUnderlyingType(t))))
+            {
+                return !typeof(JToken).IsAssignableFrom(t);
+            }
+
+            return false;
+        }
+#endif
+
+        internal static bool CanConvertToString(Type type)
+        {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            TypeConverter converter = ConvertUtils.GetConverter(type);
+
+            // use the objectType's TypeConverter if it has one and can convert to a string
+            if (converter != null
+                && !(converter is ComponentConverter)
+                && !(converter is ReferenceConverter)
+                && converter.GetType() != typeof(TypeConverter))
+            {
+                if (converter.CanConvertTo(typeof(string)))
+                    return true;
+            }
+#endif
+
+            if (type == typeof(Type) || type.IsSubclassOf(typeof(Type)))
+                return true;
+
+            return false;
+        }
+
+        private static bool IsValidCallback(MethodInfo method, ParameterInfo[] parameters, Type attributeType, MethodInfo currentCallback, ref Type prevAttributeType)
+        {
+            if (!method.IsDefined(attributeType, false))
+                return false;
+
+            if (currentCallback != null)
+                throw new JsonException("Invalid attribute. Both '{0}' and '{1}' in type '{2}' have '{3}'.".FormatWith(CultureInfo.InvariantCulture, method, currentCallback, GetClrTypeFullName(method.DeclaringType), attributeType));
+
+            if (prevAttributeType != null)
+                throw new JsonException("Invalid Callback. Method '{3}' in type '{2}' has both '{0}' and '{1}'.".FormatWith(CultureInfo.InvariantCulture, prevAttributeType, attributeType, GetClrTypeFullName(method.DeclaringType), method));
+
+            if (method.IsVirtual)
+                throw new JsonException("Virtual Method '{0}' of type '{1}' cannot be marked with '{2}' attribute.".FormatWith(CultureInfo.InvariantCulture, method, GetClrTypeFullName(method.DeclaringType), attributeType));
+
+            if (method.ReturnType != typeof(void))
+                throw new JsonException("Serialization Callback '{1}' in type '{0}' must return void.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method));
+
+            if (attributeType == typeof(OnErrorAttribute))
+            {
+                if (parameters == null || parameters.Length != 2 || parameters[0].ParameterType != typeof(StreamingContext) || parameters[1].ParameterType != typeof(ErrorContext))
+                    throw new JsonException("Serialization Error Callback '{1}' in type '{0}' must have two parameters of type '{2}' and '{3}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext), typeof(ErrorContext)));
+            }
+            else
+            {
+                if (parameters == null || parameters.Length != 1 || parameters[0].ParameterType != typeof(StreamingContext))
+                    throw new JsonException("Serialization Callback '{1}' in type '{0}' must have a single parameter of type '{2}'.".FormatWith(CultureInfo.InvariantCulture, GetClrTypeFullName(method.DeclaringType), method, typeof(StreamingContext)));
+            }
+
+            prevAttributeType = attributeType;
+
+            return true;
+        }
+
+        internal static string GetClrTypeFullName(Type type)
+        {
+            if (type.IsGenericTypeDefinition() || !type.ContainsGenericParameters())
+                return type.FullName;
+
+            return string.Format(CultureInfo.InvariantCulture, "{0}.{1}", new object[] { type.Namespace, type.Name });
+        }
+
+        /// <summary>
+        /// Creates properties for the given <see cref="JsonContract"/>.
+        /// </summary>
+        /// <param name="type">The type to create properties for.</param>
+        /// /// <param name="memberSerialization">The member serialization mode for the type.</param>
+        /// <returns>Properties for the given <see cref="JsonContract"/>.</returns>
+        protected virtual IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
+        {
+            List<MemberInfo> members = GetSerializableMembers(type);
+            if (members == null)
+                throw new JsonSerializationException("Null collection of seralizable members returned.");
+
+            JsonPropertyCollection properties = new JsonPropertyCollection(type);
+
+            foreach (MemberInfo member in members)
+            {
+                JsonProperty property = CreateProperty(member, memberSerialization);
+
+                if (property != null)
+                    properties.AddProperty(property);
+            }
+
+            IList<JsonProperty> orderedProperties = properties.OrderBy(p => p.Order ?? -1).ToList();
+            return orderedProperties;
+        }
+
+        /// <summary>
+        /// Creates the <see cref="IValueProvider"/> used by the serializer to get and set values from a member.
+        /// </summary>
+        /// <param name="member">The member.</param>
+        /// <returns>The <see cref="IValueProvider"/> used by the serializer to get and set values from a member.</returns>
+        protected virtual IValueProvider CreateMemberValueProvider(MemberInfo member)
+        {
+            // warning - this method use to cause errors with Intellitrace. Retest in VS Ultimate after changes
+            IValueProvider valueProvider;
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+            if (DynamicCodeGeneration)
+                valueProvider = new DynamicValueProvider(member);
+            else
+                valueProvider = new ReflectionValueProvider(member);
+#elif !(PORTABLE40)
+      valueProvider = new ExpressionValueProvider(member);
+#else
+            valueProvider = new ReflectionValueProvider(member);
+#endif
+
+            return valueProvider;
+        }
+
+        /// <summary>
+        /// Creates a <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.
+        /// </summary>
+        /// <param name="memberSerialization">The member's parent <see cref="MemberSerialization"/>.</param>
+        /// <param name="member">The member to create a <see cref="JsonProperty"/> for.</param>
+        /// <returns>A created <see cref="JsonProperty"/> for the given <see cref="MemberInfo"/>.</returns>
+        protected virtual JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
+        {
+            JsonProperty property = new JsonProperty();
+            property.PropertyType = ReflectionUtils.GetMemberUnderlyingType(member);
+            property.DeclaringType = member.DeclaringType;
+            property.ValueProvider = CreateMemberValueProvider(member);
+
+            bool allowNonPublicAccess;
+            SetPropertySettingsFromAttributes(property, member, member.Name, member.DeclaringType, memberSerialization, out allowNonPublicAccess);
+
+            if (memberSerialization != MemberSerialization.Fields)
+            {
+                property.Readable = ReflectionUtils.CanReadMemberValue(member, allowNonPublicAccess);
+                property.Writable = ReflectionUtils.CanSetMemberValue(member, allowNonPublicAccess, property.HasMemberAttribute);
+            }
+            else
+            {
+                // write to readonly fields
+                property.Readable = true;
+                property.Writable = true;
+            }
+            property.ShouldSerialize = CreateShouldSerializeTest(member);
+
+            SetIsSpecifiedActions(property, member, allowNonPublicAccess);
+
+            return property;
+        }
+
+        private void SetPropertySettingsFromAttributes(JsonProperty property, object attributeProvider, string name, Type declaringType, MemberSerialization memberSerialization, out bool allowNonPublicAccess)
+        {
+#if !NET20
+            DataContractAttribute dataContractAttribute = JsonTypeReflector.GetDataContractAttribute(declaringType);
+
+            MemberInfo memberInfo = attributeProvider as MemberInfo;
+
+            DataMemberAttribute dataMemberAttribute;
+            if (dataContractAttribute != null && memberInfo != null)
+                dataMemberAttribute = JsonTypeReflector.GetDataMemberAttribute((MemberInfo)memberInfo);
+            else
+                dataMemberAttribute = null;
+#endif
+
+            JsonPropertyAttribute propertyAttribute = JsonTypeReflector.GetAttribute<JsonPropertyAttribute>(attributeProvider);
+            if (propertyAttribute != null)
+                property.HasMemberAttribute = true;
+
+            string mappedName;
+            if (propertyAttribute != null && propertyAttribute.PropertyName != null)
+                mappedName = propertyAttribute.PropertyName;
+#if !NET20
+            else if (dataMemberAttribute != null && dataMemberAttribute.Name != null)
+                mappedName = dataMemberAttribute.Name;
+#endif
+            else
+                mappedName = name;
+
+            property.PropertyName = ResolvePropertyName(mappedName);
+            property.UnderlyingName = name;
+
+            bool hasMemberAttribute = false;
+            if (propertyAttribute != null)
+            {
+                property._required = propertyAttribute._required;
+                property.Order = propertyAttribute._order;
+                property.DefaultValueHandling = propertyAttribute._defaultValueHandling;
+                hasMemberAttribute = true;
+            }
+#if !NET20
+            else if (dataMemberAttribute != null)
+            {
+                property._required = (dataMemberAttribute.IsRequired) ? Required.AllowNull : Required.Default;
+                property.Order = (dataMemberAttribute.Order != -1) ? (int?)dataMemberAttribute.Order : null;
+                property.DefaultValueHandling = (!dataMemberAttribute.EmitDefaultValue) ? (DefaultValueHandling?)DefaultValueHandling.Ignore : null;
+                hasMemberAttribute = true;
+            }
+#endif
+
+            bool hasJsonIgnoreAttribute =
+                JsonTypeReflector.GetAttribute<JsonIgnoreAttribute>(attributeProvider) != null
+                    // automatically ignore extension data dictionary property if it is public
+                || JsonTypeReflector.GetAttribute<JsonExtensionDataAttribute>(attributeProvider) != null
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                || JsonTypeReflector.GetAttribute<NonSerializedAttribute>(attributeProvider) != null
+#endif
+                ;
+
+            if (memberSerialization != MemberSerialization.OptIn)
+            {
+                bool hasIgnoreDataMemberAttribute = false;
+
+#if !(NET20 || NET35)
+                hasIgnoreDataMemberAttribute = (JsonTypeReflector.GetAttribute<IgnoreDataMemberAttribute>(attributeProvider) != null);
+#endif
+
+                // ignored if it has JsonIgnore or NonSerialized or IgnoreDataMember attributes
+                property.Ignored = (hasJsonIgnoreAttribute || hasIgnoreDataMemberAttribute);
+            }
+            else
+            {
+                // ignored if it has JsonIgnore/NonSerialized or does not have DataMember or JsonProperty attributes
+                property.Ignored = (hasJsonIgnoreAttribute || !hasMemberAttribute);
+            }
+
+            // resolve converter for property
+            // the class type might have a converter but the property converter takes presidence
+            property.Converter = JsonTypeReflector.GetJsonConverter(attributeProvider, property.PropertyType);
+            property.MemberConverter = JsonTypeReflector.GetJsonConverter(attributeProvider, property.PropertyType);
+
+            DefaultValueAttribute defaultValueAttribute = JsonTypeReflector.GetAttribute<DefaultValueAttribute>(attributeProvider);
+            if (defaultValueAttribute != null)
+                property.DefaultValue = defaultValueAttribute.Value;
+
+            property.NullValueHandling = (propertyAttribute != null) ? propertyAttribute._nullValueHandling : null;
+            property.ReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._referenceLoopHandling : null;
+            property.ObjectCreationHandling = (propertyAttribute != null) ? propertyAttribute._objectCreationHandling : null;
+            property.TypeNameHandling = (propertyAttribute != null) ? propertyAttribute._typeNameHandling : null;
+            property.IsReference = (propertyAttribute != null) ? propertyAttribute._isReference : null;
+
+            property.ItemIsReference = (propertyAttribute != null) ? propertyAttribute._itemIsReference : null;
+            property.ItemConverter =
+                (propertyAttribute != null && propertyAttribute.ItemConverterType != null)
+                    ? JsonConverterAttribute.CreateJsonConverterInstance(propertyAttribute.ItemConverterType)
+                    : null;
+            property.ItemReferenceLoopHandling = (propertyAttribute != null) ? propertyAttribute._itemReferenceLoopHandling : null;
+            property.ItemTypeNameHandling = (propertyAttribute != null) ? propertyAttribute._itemTypeNameHandling : null;
+
+            allowNonPublicAccess = false;
+#pragma warning disable 618
+            if ((DefaultMembersSearchFlags & BindingFlags.NonPublic) == BindingFlags.NonPublic)
+                allowNonPublicAccess = true;
+#pragma warning restore 618
+            if (propertyAttribute != null)
+                allowNonPublicAccess = true;
+            if (memberSerialization == MemberSerialization.Fields)
+                allowNonPublicAccess = true;
+
+#if !NET20
+            if (dataMemberAttribute != null)
+            {
+                allowNonPublicAccess = true;
+                property.HasMemberAttribute = true;
+            }
+#endif
+        }
+
+        private Predicate<object> CreateShouldSerializeTest(MemberInfo member)
+        {
+            MethodInfo shouldSerializeMethod = member.DeclaringType.GetMethod(JsonTypeReflector.ShouldSerializePrefix + member.Name, ReflectionUtils.EmptyTypes);
+
+            if (shouldSerializeMethod == null || shouldSerializeMethod.ReturnType != typeof(bool))
+                return null;
+
+            MethodCall<object, object> shouldSerializeCall =
+                JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(shouldSerializeMethod);
+
+            return o => (bool)shouldSerializeCall(o);
+        }
+
+        private void SetIsSpecifiedActions(JsonProperty property, MemberInfo member, bool allowNonPublicAccess)
+        {
+            MemberInfo specifiedMember = member.DeclaringType.GetProperty(member.Name + JsonTypeReflector.SpecifiedPostfix);
+            if (specifiedMember == null)
+                specifiedMember = member.DeclaringType.GetField(member.Name + JsonTypeReflector.SpecifiedPostfix);
+
+            if (specifiedMember == null || ReflectionUtils.GetMemberUnderlyingType(specifiedMember) != typeof(bool))
+            {
+                return;
+            }
+
+            Func<object, object> specifiedPropertyGet = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(specifiedMember);
+
+            property.GetIsSpecified = o => (bool)specifiedPropertyGet(o);
+
+            if (ReflectionUtils.CanSetMemberValue(specifiedMember, allowNonPublicAccess, false))
+                property.SetIsSpecified = JsonTypeReflector.ReflectionDelegateFactory.CreateSet<object>(specifiedMember);
+        }
+
+        /// <summary>
+        /// Resolves the name of the property.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>Name of the property.</returns>
+        protected internal virtual string ResolvePropertyName(string propertyName)
+        {
+            return propertyName;
+        }
+
+        /// <summary>
+        /// Gets the resolved name of the property.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>Name of the property.</returns>
+        public string GetResolvedPropertyName(string propertyName)
+        {
+            // this is a new method rather than changing the visibility of ResolvePropertyName to avoid
+            // a breaking change for anyone who has overidden the method
+            return ResolvePropertyName(propertyName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs b/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs
new file mode 100644
index 0000000..fe5470a
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/DefaultReferenceResolver.cs
@@ -0,0 +1,83 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class DefaultReferenceResolver : IReferenceResolver
+    {
+        private int _referenceCount;
+
+        private BidirectionalDictionary<string, object> GetMappings(object context)
+        {
+            JsonSerializerInternalBase internalSerializer;
+
+            if (context is JsonSerializerInternalBase)
+                internalSerializer = (JsonSerializerInternalBase)context;
+            else if (context is JsonSerializerProxy)
+                internalSerializer = ((JsonSerializerProxy)context).GetInternalSerializer();
+            else
+                throw new JsonException("The DefaultReferenceResolver can only be used internally.");
+
+            return internalSerializer.DefaultReferenceMappings;
+        }
+
+        public object ResolveReference(object context, string reference)
+        {
+            object value;
+            GetMappings(context).TryGetByFirst(reference, out value);
+            return value;
+        }
+
+        public string GetReference(object context, object value)
+        {
+            var mappings = GetMappings(context);
+
+            string reference;
+            if (!mappings.TryGetBySecond(value, out reference))
+            {
+                _referenceCount++;
+                reference = _referenceCount.ToString(CultureInfo.InvariantCulture);
+                mappings.Set(reference, value);
+            }
+
+            return reference;
+        }
+
+        public void AddReference(object context, string reference, object value)
+        {
+            GetMappings(context).Set(reference, value);
+        }
+
+        public bool IsReferenced(object context, object value)
+        {
+            string reference;
+            return GetMappings(context).TryGetBySecond(value, out reference);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs b/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs
new file mode 100644
index 0000000..f400698
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/DefaultSerializationBinder.cs
@@ -0,0 +1,157 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Runtime.Serialization;
+using System.Reflection;
+using System.Globalization;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// The default serialization binder used when resolving and loading classes from type names.
+    /// </summary>
+    public class DefaultSerializationBinder : SerializationBinder
+    {
+        internal static readonly DefaultSerializationBinder Instance = new DefaultSerializationBinder();
+
+        private readonly ThreadSafeStore<TypeNameKey, Type> _typeCache = new ThreadSafeStore<TypeNameKey, Type>(GetTypeFromTypeNameKey);
+
+        private static Type GetTypeFromTypeNameKey(TypeNameKey typeNameKey)
+        {
+            string assemblyName = typeNameKey.AssemblyName;
+            string typeName = typeNameKey.TypeName;
+
+            if (assemblyName != null)
+            {
+                Assembly assembly;
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                // look, I don't like using obsolete methods as much as you do but this is the only way
+                // Assembly.Load won't check the GAC for a partial name
+#pragma warning disable 618,612
+                assembly = Assembly.LoadWithPartialName(assemblyName);
+#pragma warning restore 618,612
+#elif NETFX_CORE || PORTABLE
+        assembly = Assembly.Load(new AssemblyName(assemblyName));
+#else
+                assembly = Assembly.Load(assemblyName);
+#endif
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+                if (assembly == null)
+                {
+                    // will find assemblies loaded with Assembly.LoadFile outside of the main directory
+                    Assembly[] loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
+                    foreach (Assembly a in loadedAssemblies)
+                    {
+                        if (a.FullName == assemblyName)
+                        {
+                            assembly = a;
+                            break;
+                        }
+                    }
+                }
+#endif
+
+                if (assembly == null)
+                    throw new JsonSerializationException("Could not load assembly '{0}'.".FormatWith(CultureInfo.InvariantCulture, assemblyName));
+
+                Type type = assembly.GetType(typeName);
+                if (type == null)
+                    throw new JsonSerializationException("Could not find type '{0}' in assembly '{1}'.".FormatWith(CultureInfo.InvariantCulture, typeName, assembly.FullName));
+
+                return type;
+            }
+            else
+            {
+                return Type.GetType(typeName);
+            }
+        }
+
+        internal struct TypeNameKey : IEquatable<TypeNameKey>
+        {
+            internal readonly string AssemblyName;
+            internal readonly string TypeName;
+
+            public TypeNameKey(string assemblyName, string typeName)
+            {
+                AssemblyName = assemblyName;
+                TypeName = typeName;
+            }
+
+            public override int GetHashCode()
+            {
+                return ((AssemblyName != null) ? AssemblyName.GetHashCode() : 0) ^ ((TypeName != null) ? TypeName.GetHashCode() : 0);
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (!(obj is TypeNameKey))
+                    return false;
+
+                return Equals((TypeNameKey)obj);
+            }
+
+            public bool Equals(TypeNameKey other)
+            {
+                return (AssemblyName == other.AssemblyName && TypeName == other.TypeName);
+            }
+        }
+
+        /// <summary>
+        /// When overridden in a derived class, controls the binding of a serialized object to a type.
+        /// </summary>
+        /// <param name="assemblyName">Specifies the <see cref="T:System.Reflection.Assembly"/> name of the serialized object.</param>
+        /// <param name="typeName">Specifies the <see cref="T:System.Type"/> name of the serialized object.</param>
+        /// <returns>
+        /// The type of the object the formatter creates a new instance of.
+        /// </returns>
+        public override Type BindToType(string assemblyName, string typeName)
+        {
+            return _typeCache.Get(new TypeNameKey(assemblyName, typeName));
+        }
+
+#if !(NET35 || NET20)
+        /// <summary>
+        /// When overridden in a derived class, controls the binding of a serialized object to a type.
+        /// </summary>
+        /// <param name="serializedType">The type of the object the formatter creates a new instance of.</param>
+        /// <param name="assemblyName">Specifies the <see cref="T:System.Reflection.Assembly"/> name of the serialized object. </param>
+        /// <param name="typeName">Specifies the <see cref="T:System.Type"/> name of the serialized object. </param>
+        public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
+        {
+#if NETFX_CORE || PORTABLE
+            assemblyName = serializedType.GetTypeInfo().Assembly.FullName;
+            typeName = serializedType.FullName;
+#else
+            assemblyName = serializedType.Assembly.FullName;
+            typeName = serializedType.FullName;
+#endif
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs b/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs
new file mode 100644
index 0000000..2fadd3b
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/DiagnosticsTraceWriter.cs
@@ -0,0 +1,75 @@
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+using System;
+using System.Diagnostics;
+using DiagnosticsTrace = System.Diagnostics.Trace;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Represents a trace writer that writes to the application's <see cref="TraceListener"/> instances.
+    /// </summary>
+    public class DiagnosticsTraceWriter : ITraceWriter
+    {
+        /// <summary>
+        /// Gets the <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.
+        /// For example a filter level of <code>Info</code> will exclude <code>Verbose</code> messages and include <code>Info</code>,
+        /// <code>Warning</code> and <code>Error</code> messages.
+        /// </summary>
+        /// <value>
+        /// The <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.
+        /// </value>
+        public TraceLevel LevelFilter { get; set; }
+
+        private TraceEventType GetTraceEventType(TraceLevel level)
+        {
+            switch (level)
+            {
+                case TraceLevel.Error:
+                    return TraceEventType.Error;
+                case TraceLevel.Warning:
+                    return TraceEventType.Warning;
+                case TraceLevel.Info:
+                    return TraceEventType.Information;
+                case TraceLevel.Verbose:
+                    return TraceEventType.Verbose;
+                default:
+                    throw new ArgumentOutOfRangeException("level");
+            }
+        }
+
+        /// <summary>
+        /// Writes the specified trace level, message and optional exception.
+        /// </summary>
+        /// <param name="level">The <see cref="TraceLevel"/> at which to write this trace.</param>
+        /// <param name="message">The trace message.</param>
+        /// <param name="ex">The trace exception. This parameter is optional.</param>
+        public void Trace(TraceLevel level, string message, Exception ex)
+        {
+            if (level == TraceLevel.Off)
+                return;
+
+            TraceEventCache eventCache = new TraceEventCache();
+            TraceEventType traceEventType = GetTraceEventType(level);
+
+            foreach (TraceListener listener in DiagnosticsTrace.Listeners)
+            {
+                if (!listener.IsThreadSafe)
+                {
+                    lock (listener)
+                    {
+                        listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message);
+                    }
+                }
+                else
+                {
+                    listener.TraceEvent(eventCache, "Newtonsoft.Json", traceEventType, 0, message);
+                }
+
+                if (DiagnosticsTrace.AutoFlush)
+                    listener.Flush();
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/DynamicValueProvider.cs b/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
new file mode 100644
index 0000000..2e995ab
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/DynamicValueProvider.cs
@@ -0,0 +1,114 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+using System.Text;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Get and set values for a <see cref="MemberInfo"/> using dynamic methods.
+    /// </summary>
+    public class DynamicValueProvider : IValueProvider
+    {
+        private readonly MemberInfo _memberInfo;
+        private Func<object, object> _getter;
+        private Action<object, object> _setter;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="DynamicValueProvider"/> class.
+        /// </summary>
+        /// <param name="memberInfo">The member info.</param>
+        public DynamicValueProvider(MemberInfo memberInfo)
+        {
+            ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo");
+            _memberInfo = memberInfo;
+        }
+
+        /// <summary>
+        /// Sets the value.
+        /// </summary>
+        /// <param name="target">The target to set the value on.</param>
+        /// <param name="value">The value to set on the target.</param>
+        public void SetValue(object target, object value)
+        {
+            try
+            {
+                if (_setter == null)
+                    _setter = DynamicReflectionDelegateFactory.Instance.CreateSet<object>(_memberInfo);
+
+#if DEBUG
+                // dynamic method doesn't check whether the type is 'legal' to set
+                // add this check for unit tests
+                if (value == null)
+                {
+                    if (!ReflectionUtils.IsNullable(ReflectionUtils.GetMemberUnderlyingType(_memberInfo)))
+                        throw new JsonSerializationException("Incompatible value. Cannot set {0} to null.".FormatWith(CultureInfo.InvariantCulture, _memberInfo));
+                }
+                else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsAssignableFrom(value.GetType()))
+                {
+                    throw new JsonSerializationException("Incompatible value. Cannot set {0} to type {1}.".FormatWith(CultureInfo.InvariantCulture, _memberInfo, value.GetType()));
+                }
+#endif
+
+                _setter(target, value);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+
+        /// <summary>
+        /// Gets the value.
+        /// </summary>
+        /// <param name="target">The target to get the value from.</param>
+        /// <returns>The value.</returns>
+        public object GetValue(object target)
+        {
+            try
+            {
+                if (_getter == null)
+                    _getter = DynamicReflectionDelegateFactory.Instance.CreateGet<object>(_memberInfo);
+
+                return _getter(target);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ErrorContext.cs b/Newtonsoft.Json/Serialization/ErrorContext.cs
new file mode 100644
index 0000000..0e6413e
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ErrorContext.cs
@@ -0,0 +1,75 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Provides information surrounding an error.
+    /// </summary>
+    public class ErrorContext
+    {
+        internal ErrorContext(object originalObject, object member, string path, Exception error)
+        {
+            OriginalObject = originalObject;
+            Member = member;
+            Error = error;
+            Path = path;
+        }
+
+        internal bool Traced { get; set; }
+
+        /// <summary>
+        /// Gets the error.
+        /// </summary>
+        /// <value>The error.</value>
+        public Exception Error { get; private set; }
+
+        /// <summary>
+        /// Gets the original object that caused the error.
+        /// </summary>
+        /// <value>The original object that caused the error.</value>
+        public object OriginalObject { get; private set; }
+
+        /// <summary>
+        /// Gets the member that caused the error.
+        /// </summary>
+        /// <value>The member that caused the error.</value>
+        public object Member { get; private set; }
+
+        /// <summary>
+        /// Gets the path of the JSON location where the error occurred.
+        /// </summary>
+        /// <value>The path of the JSON location where the error occurred.</value>
+        public string Path { get; private set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="ErrorContext"/> is handled.
+        /// </summary>
+        /// <value><c>true</c> if handled; otherwise, <c>false</c>.</value>
+        public bool Handled { get; set; }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ErrorEventArgs.cs b/Newtonsoft.Json/Serialization/ErrorEventArgs.cs
new file mode 100644
index 0000000..f4485dc
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ErrorEventArgs.cs
@@ -0,0 +1,58 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Provides data for the Error event.
+    /// </summary>
+    public class ErrorEventArgs : EventArgs
+    {
+        /// <summary>
+        /// Gets the current object the error event is being raised against.
+        /// </summary>
+        /// <value>The current object the error event is being raised against.</value>
+        public object CurrentObject { get; private set; }
+
+        /// <summary>
+        /// Gets the error context.
+        /// </summary>
+        /// <value>The error context.</value>
+        public ErrorContext ErrorContext { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ErrorEventArgs"/> class.
+        /// </summary>
+        /// <param name="currentObject">The current object.</param>
+        /// <param name="errorContext">The error context.</param>
+        public ErrorEventArgs(object currentObject, ErrorContext errorContext)
+        {
+            CurrentObject = currentObject;
+            ErrorContext = errorContext;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs b/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs
new file mode 100644
index 0000000..f985e2e
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ExpressionValueProvider.cs
@@ -0,0 +1,114 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET20 || NET35 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+using System.Text;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Get and set values for a <see cref="MemberInfo"/> using dynamic methods.
+    /// </summary>
+    public class ExpressionValueProvider : IValueProvider
+    {
+        private readonly MemberInfo _memberInfo;
+        private Func<object, object> _getter;
+        private Action<object, object> _setter;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ExpressionValueProvider"/> class.
+        /// </summary>
+        /// <param name="memberInfo">The member info.</param>
+        public ExpressionValueProvider(MemberInfo memberInfo)
+        {
+            ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo");
+            _memberInfo = memberInfo;
+        }
+
+        /// <summary>
+        /// Sets the value.
+        /// </summary>
+        /// <param name="target">The target to set the value on.</param>
+        /// <param name="value">The value to set on the target.</param>
+        public void SetValue(object target, object value)
+        {
+            try
+            {
+                if (_setter == null)
+                    _setter = ExpressionReflectionDelegateFactory.Instance.CreateSet<object>(_memberInfo);
+
+#if DEBUG
+                // dynamic method doesn't check whether the type is 'legal' to set
+                // add this check for unit tests
+                if (value == null)
+                {
+                    if (!ReflectionUtils.IsNullable(ReflectionUtils.GetMemberUnderlyingType(_memberInfo)))
+                        throw new JsonSerializationException("Incompatible value. Cannot set {0} to null.".FormatWith(CultureInfo.InvariantCulture, _memberInfo));
+                }
+                else if (!ReflectionUtils.GetMemberUnderlyingType(_memberInfo).IsAssignableFrom(value.GetType()))
+                {
+                    throw new JsonSerializationException("Incompatible value. Cannot set {0} to type {1}.".FormatWith(CultureInfo.InvariantCulture, _memberInfo, value.GetType()));
+                }
+#endif
+
+                _setter(target, value);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+
+        /// <summary>
+        /// Gets the value.
+        /// </summary>
+        /// <param name="target">The target to get the value from.</param>
+        /// <returns>The value.</returns>
+        public object GetValue(object target)
+        {
+            try
+            {
+                if (_getter == null)
+                    _getter = ExpressionReflectionDelegateFactory.Instance.CreateGet<object>(_memberInfo);
+
+                return _getter(target);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/IContractResolver.cs b/Newtonsoft.Json/Serialization/IContractResolver.cs
new file mode 100644
index 0000000..da6a84d
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/IContractResolver.cs
@@ -0,0 +1,46 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Used by <see cref="JsonSerializer"/> to resolves a <see cref="JsonContract"/> for a given <see cref="Type"/>.
+    /// </summary>
+    /// <example>
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeContractResolverObject" title="IContractResolver Class" />
+    ///   <code lang="cs" source="..\Src\Newtonsoft.Json.Tests\Documentation\SerializationTests.cs" region="ReducingSerializedJsonSizeContractResolverExample" title="IContractResolver Example" />
+    /// </example>
+    public interface IContractResolver
+    {
+        /// <summary>
+        /// Resolves the contract for a given type.
+        /// </summary>
+        /// <param name="type">The type to resolve a contract for.</param>
+        /// <returns>The contract for a given type.</returns>
+        JsonContract ResolveContract(Type type);
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/IReferenceResolver.cs b/Newtonsoft.Json/Serialization/IReferenceResolver.cs
new file mode 100644
index 0000000..e8bf475
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/IReferenceResolver.cs
@@ -0,0 +1,67 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Used to resolve references when serializing and deserializing JSON by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public interface IReferenceResolver
+    {
+        /// <summary>
+        /// Resolves a reference to its object.
+        /// </summary>
+        /// <param name="context">The serialization context.</param>
+        /// <param name="reference">The reference to resolve.</param>
+        /// <returns>The object that</returns>
+        object ResolveReference(object context, string reference);
+
+        /// <summary>
+        /// Gets the reference for the sepecified object.
+        /// </summary>
+        /// <param name="context">The serialization context.</param>
+        /// <param name="value">The object to get a reference for.</param>
+        /// <returns>The reference to the object.</returns>
+        string GetReference(object context, object value);
+
+        /// <summary>
+        /// Determines whether the specified object is referenced.
+        /// </summary>
+        /// <param name="context">The serialization context.</param>
+        /// <param name="value">The object to test for a reference.</param>
+        /// <returns>
+        /// 	<c>true</c> if the specified object is referenced; otherwise, <c>false</c>.
+        /// </returns>
+        bool IsReferenced(object context, object value);
+
+        /// <summary>
+        /// Adds a reference to the specified object.
+        /// </summary>
+        /// <param name="context">The serialization context.</param>
+        /// <param name="reference">The reference.</param>
+        /// <param name="value">The object to reference.</param>
+        void AddReference(object context, string reference, object value);
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ITraceWriter.cs b/Newtonsoft.Json/Serialization/ITraceWriter.cs
new file mode 100644
index 0000000..ea2fbf0
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ITraceWriter.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Represents a trace writer.
+    /// </summary>
+    public interface ITraceWriter
+    {
+        /// <summary>
+        /// Gets the <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.
+        /// For example a filter level of <code>Info</code> will exclude <code>Verbose</code> messages and include <code>Info</code>,
+        /// <code>Warning</code> and <code>Error</code> messages.
+        /// </summary>
+        /// <value>The <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.</value>
+        TraceLevel LevelFilter { get; }
+
+        /// <summary>
+        /// Writes the specified trace level, message and optional exception.
+        /// </summary>
+        /// <param name="level">The <see cref="TraceLevel"/> at which to write this trace.</param>
+        /// <param name="message">The trace message.</param>
+        /// <param name="ex">The trace exception. This parameter is optional.</param>
+        void Trace(TraceLevel level, string message, Exception ex);
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/IValueProvider.cs b/Newtonsoft.Json/Serialization/IValueProvider.cs
new file mode 100644
index 0000000..ae21a9f
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/IValueProvider.cs
@@ -0,0 +1,47 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Provides methods to get and set values.
+    /// </summary>
+    public interface IValueProvider
+    {
+        /// <summary>
+        /// Sets the value.
+        /// </summary>
+        /// <param name="target">The target to set the value on.</param>
+        /// <param name="value">The value to set on the target.</param>
+        void SetValue(object target, object value);
+
+        /// <summary>
+        /// Gets the value.
+        /// </summary>
+        /// <param name="target">The target to get the value from.</param>
+        /// <returns>The value.</returns>
+        object GetValue(object target);
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonArrayContract.cs b/Newtonsoft.Json/Serialization/JsonArrayContract.cs
new file mode 100644
index 0000000..d708ff8
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonArrayContract.cs
@@ -0,0 +1,248 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonArrayContract : JsonContainerContract
+    {
+        /// <summary>
+        /// Gets the <see cref="Type"/> of the collection items.
+        /// </summary>
+        /// <value>The <see cref="Type"/> of the collection items.</value>
+        public Type CollectionItemType { get; private set; }
+
+        /// <summary>
+        /// Gets a value indicating whether the collection type is a multidimensional array.
+        /// </summary>
+        /// <value><c>true</c> if the collection type is a multidimensional array; otherwise, <c>false</c>.</value>
+        public bool IsMultidimensionalArray { get; private set; }
+
+#if (NET20 || NET35)
+        private readonly bool _isCollectionItemTypeNullableType;
+#endif
+        private readonly Type _genericCollectionDefinitionType;
+
+        private Type _genericWrapperType;
+        private MethodCall<object, object> _genericWrapperCreator;
+        private Func<object> _genericTemporaryCollectionCreator;
+
+        internal bool IsArray { get; private set; }
+        internal bool ShouldCreateWrapper { get; private set; }
+        internal bool CanDeserialize { get; private set; }
+        internal MethodBase ParametrizedConstructor { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonArrayContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonArrayContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Array;
+            IsArray = CreatedType.IsArray;
+
+            bool canDeserialize;
+
+            Type tempCollectionType;
+            if (IsArray)
+            {
+                CollectionItemType = ReflectionUtils.GetCollectionItemType(UnderlyingType);
+                IsReadOnlyOrFixedSize = true;
+                _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
+
+                canDeserialize = true;
+                IsMultidimensionalArray = (IsArray && UnderlyingType.GetArrayRank() > 1);
+            }
+            else if (typeof(IList).IsAssignableFrom(underlyingType))
+            {
+                if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
+                    CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
+                else
+                    CollectionItemType = ReflectionUtils.GetCollectionItemType(underlyingType);
+
+                if (underlyingType == typeof(IList))
+                    CreatedType = typeof(List<object>);
+
+                if (CollectionItemType != null)
+                    ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
+
+                IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyCollection<>));
+                canDeserialize = true;
+            }
+            else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(ICollection<>), out _genericCollectionDefinitionType))
+            {
+                CollectionItemType = _genericCollectionDefinitionType.GetGenericArguments()[0];
+
+                if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ICollection<>))
+                    || ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IList<>)))
+                    CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
+
+#if !(NET20 || NET35 || PORTABLE40)
+                if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(ISet<>)))
+                    CreatedType = typeof(HashSet<>).MakeGenericType(CollectionItemType);
+#endif
+
+                ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
+                canDeserialize = true;
+                ShouldCreateWrapper = true;
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>), out tempCollectionType))
+            {
+                CollectionItemType = underlyingType.GetGenericArguments()[0];
+
+                if (ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyCollection<>))
+                    || ReflectionUtils.IsGenericDefinition(underlyingType, typeof(IReadOnlyList<>)))
+                    CreatedType = typeof(ReadOnlyCollection<>).MakeGenericType(CollectionItemType);
+
+                _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
+                ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(CreatedType, CollectionItemType);
+                IsReadOnlyOrFixedSize = true;
+                canDeserialize = (ParametrizedConstructor != null);
+            }
+#endif
+            else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IEnumerable<>), out tempCollectionType))
+            {
+                CollectionItemType = tempCollectionType.GetGenericArguments()[0];
+
+                if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IEnumerable<>)))
+                    CreatedType = typeof(List<>).MakeGenericType(CollectionItemType);
+
+                ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(underlyingType, CollectionItemType);
+
+#if !(NET35 || NET20 || NETFX_CORE)
+                if (ParametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpListTypeName)
+                {
+                    FSharpUtils.EnsureInitialized(underlyingType.Assembly());
+                    ParametrizedConstructor = FSharpUtils.CreateSeq(CollectionItemType);
+                }
+#endif
+
+                if (underlyingType.IsGenericType() && underlyingType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+                {
+                    _genericCollectionDefinitionType = tempCollectionType;
+
+                    IsReadOnlyOrFixedSize = false;
+                    ShouldCreateWrapper = false;
+                    canDeserialize = true;
+                }
+                else
+                {
+                    _genericCollectionDefinitionType = typeof(List<>).MakeGenericType(CollectionItemType);
+
+                    IsReadOnlyOrFixedSize = true;
+                    ShouldCreateWrapper = true;
+                    canDeserialize = (ParametrizedConstructor != null);
+                }
+            }
+            else
+            {
+                // types that implement IEnumerable and nothing else
+                canDeserialize = false;
+                ShouldCreateWrapper = true;
+            }
+
+            CanDeserialize = canDeserialize;
+
+#if (NET20 || NET35)
+            if (CollectionItemType != null)
+            _isCollectionItemTypeNullableType = ReflectionUtils.IsNullableType(CollectionItemType);
+
+    // bug in .NET 2.0 & 3.5 that List<Nullable<T>> throws an error when adding null via IList.Add(object)
+    // wrapper will handle calling Add(T) instead
+      if (_isCollectionItemTypeNullableType
+        && (ReflectionUtils.InheritsGenericDefinition(CreatedType, typeof(List<>), out tempCollectionType)
+        || (IsArray && !IsMultidimensionalArray)))
+      {
+        ShouldCreateWrapper = true;
+      }
+#endif
+
+#if !(NET20 || NET35 || NET40 || PORTABLE40)
+            Type immutableCreatedType;
+            MethodBase immutableParameterizedCreator;
+            if (ImmutableCollectionsUtils.TryBuildImmutableForArrayContract(underlyingType, CollectionItemType, out immutableCreatedType, out immutableParameterizedCreator))
+            {
+                CreatedType = immutableCreatedType;
+                ParametrizedConstructor = immutableParameterizedCreator;
+                IsReadOnlyOrFixedSize = true;
+                CanDeserialize = true;
+            }
+#endif
+        }
+
+        internal IWrappedCollection CreateWrapper(object list)
+        {
+            if (_genericWrapperCreator == null)
+            {
+                _genericWrapperType = typeof(CollectionWrapper<>).MakeGenericType(CollectionItemType);
+
+                Type constructorArgument;
+
+                if (ReflectionUtils.InheritsGenericDefinition(_genericCollectionDefinitionType, typeof(List<>))
+                    || _genericCollectionDefinitionType.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+                    constructorArgument = typeof(ICollection<>).MakeGenericType(CollectionItemType);
+                else
+                    constructorArgument = _genericCollectionDefinitionType;
+
+                ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { constructorArgument });
+                _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(genericWrapperConstructor);
+            }
+
+            return (IWrappedCollection)_genericWrapperCreator(null, list);
+        }
+
+        internal IList CreateTemporaryCollection()
+        {
+            if (_genericTemporaryCollectionCreator == null)
+            {
+                // multidimensional array will also have array instances in it
+                Type collectionItemType = (IsMultidimensionalArray) ? typeof(object) : CollectionItemType;
+                Type temporaryListType = typeof(List<>).MakeGenericType(collectionItemType);
+                _genericTemporaryCollectionCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(temporaryListType);
+            }
+
+            return (IList)_genericTemporaryCollectionCreator();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonContainerContract.cs b/Newtonsoft.Json/Serialization/JsonContainerContract.cs
new file mode 100644
index 0000000..47097a1
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonContainerContract.cs
@@ -0,0 +1,116 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonContainerContract : JsonContract
+    {
+        private JsonContract _itemContract;
+        private JsonContract _finalItemContract;
+
+        // will be null for containers that don't have an item type (e.g. IList) or for complex objects
+        internal JsonContract ItemContract
+        {
+            get { return _itemContract; }
+            set
+            {
+                _itemContract = value;
+                if (_itemContract != null)
+                {
+                    _finalItemContract = (_itemContract.UnderlyingType.IsSealed()) ? _itemContract : null;
+                }
+                else
+                {
+                    _finalItemContract = null;
+                }
+            }
+        }
+
+        // the final (i.e. can't be inherited from like a sealed class or valuetype) item contract
+        internal JsonContract FinalItemContract
+        {
+            get { return _finalItemContract; }
+        }
+
+        /// <summary>
+        /// Gets or sets the default collection items <see cref="JsonConverter" />.
+        /// </summary>
+        /// <value>The converter.</value>
+        public JsonConverter ItemConverter { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the collection items preserve object references.
+        /// </summary>
+        /// <value><c>true</c> if collection items preserve object references; otherwise, <c>false</c>.</value>
+        public bool? ItemIsReference { get; set; }
+
+        /// <summary>
+        /// Gets or sets the collection item reference loop handling.
+        /// </summary>
+        /// <value>The reference loop handling.</value>
+        public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets the collection item type name handling.
+        /// </summary>
+        /// <value>The type name handling.</value>
+        public TypeNameHandling? ItemTypeNameHandling { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonContainerContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        internal JsonContainerContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            JsonContainerAttribute jsonContainerAttribute = JsonTypeReflector.GetJsonContainerAttribute(underlyingType);
+
+            if (jsonContainerAttribute != null)
+            {
+                if (jsonContainerAttribute.ItemConverterType != null)
+                    ItemConverter = JsonConverterAttribute.CreateJsonConverterInstance(jsonContainerAttribute.ItemConverterType);
+
+                ItemIsReference = jsonContainerAttribute._itemIsReference;
+                ItemReferenceLoopHandling = jsonContainerAttribute._itemReferenceLoopHandling;
+                ItemTypeNameHandling = jsonContainerAttribute._itemTypeNameHandling;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonContract.cs b/Newtonsoft.Json/Serialization/JsonContract.cs
new file mode 100644
index 0000000..e11b97e
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonContract.cs
@@ -0,0 +1,407 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal enum JsonContractType
+    {
+        None,
+        Object,
+        Array,
+        Primitive,
+        String,
+        Dictionary,
+#if !(NET35 || NET20 || PORTABLE40)
+        Dynamic,
+#endif
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        Serializable,
+#endif
+        Linq
+    }
+
+    /// <summary>
+    /// Handles <see cref="JsonSerializer"/> serialization callback events.
+    /// </summary>
+    /// <param name="o">The object that raised the callback event.</param>
+    /// <param name="context">The streaming context.</param>
+    public delegate void SerializationCallback(object o, StreamingContext context);
+
+    /// <summary>
+    /// Handles <see cref="JsonSerializer"/> serialization error callback events.
+    /// </summary>
+    /// <param name="o">The object that raised the callback event.</param>
+    /// <param name="context">The streaming context.</param>
+    /// <param name="errorContext">The error context.</param>
+    public delegate void SerializationErrorCallback(object o, StreamingContext context, ErrorContext errorContext);
+
+    /// <summary>
+    /// Sets extension data for an object during deserialization.
+    /// </summary>
+    /// <param name="o">The object to set extension data on.</param>
+    /// <param name="key">The extension data key.</param>
+    /// <param name="value">The extension data value.</param>
+    public delegate void ExtensionDataSetter(object o, string key, object value);
+
+    /// <summary>
+    /// Gets extension data for an object during serialization.
+    /// </summary>
+    /// <param name="o">The object to set extension data on.</param>
+    public delegate IEnumerable<KeyValuePair<object, object>> ExtensionDataGetter(object o);
+
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public abstract class JsonContract
+    {
+        internal bool IsNullable;
+        internal bool IsConvertable;
+        internal bool IsSealed;
+        internal bool IsEnum;
+        internal Type NonNullableUnderlyingType;
+        internal ReadType InternalReadType;
+        internal JsonContractType ContractType;
+        internal bool IsReadOnlyOrFixedSize;
+        internal bool IsInstantiable;
+
+        private List<SerializationCallback> _onDeserializedCallbacks;
+        private IList<SerializationCallback> _onDeserializingCallbacks;
+        private IList<SerializationCallback> _onSerializedCallbacks;
+        private IList<SerializationCallback> _onSerializingCallbacks;
+        private IList<SerializationErrorCallback> _onErrorCallbacks;
+
+        /// <summary>
+        /// Gets the underlying type for the contract.
+        /// </summary>
+        /// <value>The underlying type for the contract.</value>
+        public Type UnderlyingType { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the type created during deserialization.
+        /// </summary>
+        /// <value>The type created during deserialization.</value>
+        public Type CreatedType { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether this type contract is serialized as a reference.
+        /// </summary>
+        /// <value>Whether this type contract is serialized as a reference.</value>
+        public bool? IsReference { get; set; }
+
+        /// <summary>
+        /// Gets or sets the default <see cref="JsonConverter" /> for this contract.
+        /// </summary>
+        /// <value>The converter.</value>
+        public JsonConverter Converter { get; set; }
+
+        // internally specified JsonConverter's to override default behavour
+        // checked for after passed in converters and attribute specified converters
+        internal JsonConverter InternalConverter { get; set; }
+
+        /// <summary>
+        /// Gets or sets all methods called immediately after deserialization of the object.
+        /// </summary>
+        /// <value>The methods called immediately after deserialization of the object.</value>
+        public IList<SerializationCallback> OnDeserializedCallbacks
+        {
+            get
+            {
+                if (_onDeserializedCallbacks == null)
+                    _onDeserializedCallbacks = new List<SerializationCallback>();
+
+                return _onDeserializedCallbacks;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets all methods called during deserialization of the object.
+        /// </summary>
+        /// <value>The methods called during deserialization of the object.</value>
+        public IList<SerializationCallback> OnDeserializingCallbacks
+        {
+            get
+            {
+                if (_onDeserializingCallbacks == null)
+                    _onDeserializingCallbacks = new List<SerializationCallback>();
+
+                return _onDeserializingCallbacks;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets all methods called after serialization of the object graph.
+        /// </summary>
+        /// <value>The methods called after serialization of the object graph.</value>
+        public IList<SerializationCallback> OnSerializedCallbacks
+        {
+            get
+            {
+                if (_onSerializedCallbacks == null)
+                    _onSerializedCallbacks = new List<SerializationCallback>();
+
+                return _onSerializedCallbacks;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets all methods called before serialization of the object.
+        /// </summary>
+        /// <value>The methods called before serialization of the object.</value>
+        public IList<SerializationCallback> OnSerializingCallbacks
+        {
+            get
+            {
+                if (_onSerializingCallbacks == null)
+                    _onSerializingCallbacks = new List<SerializationCallback>();
+
+                return _onSerializingCallbacks;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets all method called when an error is thrown during the serialization of the object.
+        /// </summary>
+        /// <value>The methods called when an error is thrown during the serialization of the object.</value>
+        public IList<SerializationErrorCallback> OnErrorCallbacks
+        {
+            get
+            {
+                if (_onErrorCallbacks == null)
+                    _onErrorCallbacks = new List<SerializationErrorCallback>();
+
+                return _onErrorCallbacks;
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the method called immediately after deserialization of the object.
+        /// </summary>
+        /// <value>The method called immediately after deserialization of the object.</value>
+        [Obsolete("This property is obsolete and has been replaced by the OnDeserializedCallbacks collection.")]
+        public MethodInfo OnDeserialized
+        {
+            get { return (OnDeserializedCallbacks.Count > 0) ? OnDeserializedCallbacks[0].Method() : null; }
+            set
+            {
+                OnDeserializedCallbacks.Clear();
+                OnDeserializedCallbacks.Add(CreateSerializationCallback(value));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the method called during deserialization of the object.
+        /// </summary>
+        /// <value>The method called during deserialization of the object.</value>
+        [Obsolete("This property is obsolete and has been replaced by the OnDeserializingCallbacks collection.")]
+        public MethodInfo OnDeserializing
+        {
+            get { return (OnDeserializingCallbacks.Count > 0) ? OnDeserializingCallbacks[0].Method() : null; }
+            set
+            {
+                OnDeserializingCallbacks.Clear();
+                OnDeserializingCallbacks.Add(CreateSerializationCallback(value));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the method called after serialization of the object graph.
+        /// </summary>
+        /// <value>The method called after serialization of the object graph.</value>
+        [Obsolete("This property is obsolete and has been replaced by the OnSerializedCallbacks collection.")]
+        public MethodInfo OnSerialized
+        {
+            get { return (OnSerializedCallbacks.Count > 0) ? OnSerializedCallbacks[0].Method() : null; }
+            set
+            {
+                OnSerializedCallbacks.Clear();
+                OnSerializedCallbacks.Add(CreateSerializationCallback(value));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the method called before serialization of the object.
+        /// </summary>
+        /// <value>The method called before serialization of the object.</value>
+        [Obsolete("This property is obsolete and has been replaced by the OnSerializingCallbacks collection.")]
+        public MethodInfo OnSerializing
+        {
+            get { return (OnSerializingCallbacks.Count > 0) ? OnSerializingCallbacks[0].Method() : null; }
+            set
+            {
+                OnSerializingCallbacks.Clear();
+                OnSerializingCallbacks.Add(CreateSerializationCallback(value));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the method called when an error is thrown during the serialization of the object.
+        /// </summary>
+        /// <value>The method called when an error is thrown during the serialization of the object.</value>
+        [Obsolete("This property is obsolete and has been replaced by the OnErrorCallbacks collection.")]
+        public MethodInfo OnError
+        {
+            get { return (OnErrorCallbacks.Count > 0) ? OnErrorCallbacks[0].Method() : null; }
+            set
+            {
+                OnErrorCallbacks.Clear();
+                OnErrorCallbacks.Add(CreateSerializationErrorCallback(value));
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the default creator method used to create the object.
+        /// </summary>
+        /// <value>The default creator method used to create the object.</value>
+        public Func<object> DefaultCreator { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the default creator is non public.
+        /// </summary>
+        /// <value><c>true</c> if the default object creator is non-public; otherwise, <c>false</c>.</value>
+        public bool DefaultCreatorNonPublic { get; set; }
+
+        internal JsonContract(Type underlyingType)
+        {
+            ValidationUtils.ArgumentNotNull(underlyingType, "underlyingType");
+
+            UnderlyingType = underlyingType;
+
+            IsSealed = underlyingType.IsSealed();
+            IsInstantiable = !(underlyingType.IsInterface() || underlyingType.IsAbstract());
+
+            IsNullable = ReflectionUtils.IsNullable(underlyingType);
+            NonNullableUnderlyingType = (IsNullable && ReflectionUtils.IsNullableType(underlyingType)) ? Nullable.GetUnderlyingType(underlyingType) : underlyingType;
+
+            CreatedType = NonNullableUnderlyingType;
+
+            IsConvertable = ConvertUtils.IsConvertible(NonNullableUnderlyingType);
+            IsEnum = NonNullableUnderlyingType.IsEnum();
+
+            if (NonNullableUnderlyingType == typeof(byte[]))
+            {
+                InternalReadType = ReadType.ReadAsBytes;
+            }
+            else if (NonNullableUnderlyingType == typeof(int))
+            {
+                InternalReadType = ReadType.ReadAsInt32;
+            }
+            else if (NonNullableUnderlyingType == typeof(decimal))
+            {
+                InternalReadType = ReadType.ReadAsDecimal;
+            }
+            else if (NonNullableUnderlyingType == typeof(string))
+            {
+                InternalReadType = ReadType.ReadAsString;
+            }
+            else if (NonNullableUnderlyingType == typeof(DateTime))
+            {
+                InternalReadType = ReadType.ReadAsDateTime;
+            }
+#if !NET20
+            else if (NonNullableUnderlyingType == typeof(DateTimeOffset))
+            {
+                InternalReadType = ReadType.ReadAsDateTimeOffset;
+            }
+#endif
+            else
+            {
+                InternalReadType = ReadType.Read;
+            }
+        }
+
+        internal void InvokeOnSerializing(object o, StreamingContext context)
+        {
+            if (_onSerializingCallbacks != null)
+            {
+                foreach (SerializationCallback callback in _onSerializingCallbacks)
+                {
+                    callback(o, context);
+                }
+            }
+        }
+
+        internal void InvokeOnSerialized(object o, StreamingContext context)
+        {
+            if (_onSerializedCallbacks != null)
+            {
+                foreach (SerializationCallback callback in _onSerializedCallbacks)
+                {
+                    callback(o, context);
+                }
+            }
+        }
+
+        internal void InvokeOnDeserializing(object o, StreamingContext context)
+        {
+            if (_onDeserializingCallbacks != null)
+            {
+                foreach (SerializationCallback callback in _onDeserializingCallbacks)
+                {
+                    callback(o, context);
+                }
+            }
+        }
+
+        internal void InvokeOnDeserialized(object o, StreamingContext context)
+        {
+            if (_onDeserializedCallbacks != null)
+            {
+                foreach (SerializationCallback callback in _onDeserializedCallbacks)
+                {
+                    callback(o, context);
+                }
+            }
+        }
+
+        internal void InvokeOnError(object o, StreamingContext context, ErrorContext errorContext)
+        {
+            if (_onErrorCallbacks != null)
+            {
+                foreach (SerializationErrorCallback callback in _onErrorCallbacks)
+                {
+                    callback(o, context, errorContext);
+                }
+            }
+        }
+
+        internal static SerializationCallback CreateSerializationCallback(MethodInfo callbackMethodInfo)
+        {
+            return (o, context) => callbackMethodInfo.Invoke(o, new object[] { context });
+        }
+
+        internal static SerializationErrorCallback CreateSerializationErrorCallback(MethodInfo callbackMethodInfo)
+        {
+            return (o, context, econtext) => callbackMethodInfo.Invoke(o, new object[] { context, econtext });
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs b/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs
new file mode 100644
index 0000000..ef88683
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonDictionaryContract.cs
@@ -0,0 +1,191 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonDictionaryContract : JsonContainerContract
+    {
+        /// <summary>
+        /// Gets or sets the property name resolver.
+        /// </summary>
+        /// <value>The property name resolver.</value>
+        public Func<string, string> PropertyNameResolver { get; set; }
+
+        /// <summary>
+        /// Gets the <see cref="Type"/> of the dictionary keys.
+        /// </summary>
+        /// <value>The <see cref="Type"/> of the dictionary keys.</value>
+        public Type DictionaryKeyType { get; private set; }
+
+        /// <summary>
+        /// Gets the <see cref="Type"/> of the dictionary values.
+        /// </summary>
+        /// <value>The <see cref="Type"/> of the dictionary values.</value>
+        public Type DictionaryValueType { get; private set; }
+
+        internal JsonContract KeyContract { get; set; }
+
+#if (NET20 || NET35)
+        private readonly bool _isDictionaryValueTypeNullableType;
+#endif
+        private readonly Type _genericCollectionDefinitionType;
+
+        private Type _genericWrapperType;
+        private MethodCall<object, object> _genericWrapperCreator;
+
+        private Func<object> _genericTemporaryDictionaryCreator;
+
+        internal bool ShouldCreateWrapper { get; private set; }
+        internal MethodBase ParametrizedConstructor { get; private set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonDictionaryContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonDictionaryContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Dictionary;
+
+            Type keyType;
+            Type valueType;
+
+            if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IDictionary<,>), out _genericCollectionDefinitionType))
+            {
+                keyType = _genericCollectionDefinitionType.GetGenericArguments()[0];
+                valueType = _genericCollectionDefinitionType.GetGenericArguments()[1];
+
+                if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IDictionary<,>)))
+                    CreatedType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType);
+
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                IsReadOnlyOrFixedSize = ReflectionUtils.InheritsGenericDefinition(underlyingType, typeof(ReadOnlyDictionary<,>));
+#endif
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (ReflectionUtils.ImplementsGenericDefinition(underlyingType, typeof(IReadOnlyDictionary<,>), out _genericCollectionDefinitionType))
+            {
+                keyType = _genericCollectionDefinitionType.GetGenericArguments()[0];
+                valueType = _genericCollectionDefinitionType.GetGenericArguments()[1];
+
+                if (ReflectionUtils.IsGenericDefinition(UnderlyingType, typeof(IReadOnlyDictionary<,>)))
+                    CreatedType = typeof(ReadOnlyDictionary<,>).MakeGenericType(keyType, valueType);
+
+                IsReadOnlyOrFixedSize = true;
+            }
+#endif
+            else
+            {
+                ReflectionUtils.GetDictionaryKeyValueTypes(UnderlyingType, out keyType, out valueType);
+
+                if (UnderlyingType == typeof(IDictionary))
+                    CreatedType = typeof(Dictionary<object, object>);
+            }
+
+            if (keyType != null && valueType != null)
+            {
+                ParametrizedConstructor = CollectionUtils.ResolveEnumableCollectionConstructor(CreatedType, typeof(KeyValuePair<,>).MakeGenericType(keyType, valueType));
+
+#if !(NET35 || NET20 || NETFX_CORE)
+                if (ParametrizedConstructor == null && underlyingType.Name == FSharpUtils.FSharpMapTypeName)
+                {
+                    FSharpUtils.EnsureInitialized(underlyingType.Assembly());
+                    ParametrizedConstructor = FSharpUtils.CreateMap(keyType, valueType);
+                }
+#endif
+            }
+
+            ShouldCreateWrapper = !typeof(IDictionary).IsAssignableFrom(CreatedType);
+
+            DictionaryKeyType = keyType;
+            DictionaryValueType = valueType;
+
+#if (NET20 || NET35)
+            if (DictionaryValueType != null)
+            _isDictionaryValueTypeNullableType = ReflectionUtils.IsNullableType(DictionaryValueType);
+
+      Type tempDictioanryType;
+
+        // bug in .NET 2.0 & 3.5 that Dictionary<TKey, Nullable<TValue>> throws an error when adding null via IDictionary[key] = object
+      // wrapper will handle calling Add(T) instead
+      if (_isDictionaryValueTypeNullableType
+        && (ReflectionUtils.InheritsGenericDefinition(CreatedType, typeof(Dictionary<,>), out tempDictioanryType)))
+      {
+        ShouldCreateWrapper = true;
+      }
+#endif
+
+#if !(NET20 || NET35 || NET40 || PORTABLE40)
+            Type immutableCreatedType;
+            MethodBase immutableParameterizedCreator;
+            if (ImmutableCollectionsUtils.TryBuildImmutableForDictionaryContract(underlyingType, DictionaryKeyType, DictionaryValueType, out immutableCreatedType, out immutableParameterizedCreator))
+            {
+                CreatedType = immutableCreatedType;
+                ParametrizedConstructor = immutableParameterizedCreator;
+                IsReadOnlyOrFixedSize = true;
+            }
+#endif
+        }
+
+        internal IWrappedDictionary CreateWrapper(object dictionary)
+        {
+            if (_genericWrapperCreator == null)
+            {
+                _genericWrapperType = typeof(DictionaryWrapper<,>).MakeGenericType(DictionaryKeyType, DictionaryValueType);
+
+                ConstructorInfo genericWrapperConstructor = _genericWrapperType.GetConstructor(new[] { _genericCollectionDefinitionType });
+                _genericWrapperCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(genericWrapperConstructor);
+            }
+
+            return (IWrappedDictionary)_genericWrapperCreator(null, dictionary);
+        }
+
+        internal IDictionary CreateTemporaryDictionary()
+        {
+            if (_genericTemporaryDictionaryCreator == null)
+            {
+                Type temporaryDictionaryType = typeof(Dictionary<,>).MakeGenericType(DictionaryKeyType, DictionaryValueType);
+
+                _genericTemporaryDictionaryCreator = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(temporaryDictionaryType);
+            }
+
+            return (IDictionary)_genericTemporaryDictionaryCreator();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonDynamicContract.cs b/Newtonsoft.Json/Serialization/JsonDynamicContract.cs
new file mode 100644
index 0000000..84a8100
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonDynamicContract.cs
@@ -0,0 +1,119 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using Newtonsoft.Json.Utilities;
+using System.Collections;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonDynamicContract : JsonContainerContract
+    {
+        /// <summary>
+        /// Gets the object's properties.
+        /// </summary>
+        /// <value>The object's properties.</value>
+        public JsonPropertyCollection Properties { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the property name resolver.
+        /// </summary>
+        /// <value>The property name resolver.</value>
+        public Func<string, string> PropertyNameResolver { get; set; }
+
+        private readonly ThreadSafeStore<string, CallSite<Func<CallSite, object, object>>> _callSiteGetters =
+            new ThreadSafeStore<string, CallSite<Func<CallSite, object, object>>>(CreateCallSiteGetter);
+
+        private readonly ThreadSafeStore<string, CallSite<Func<CallSite, object, object, object>>> _callSiteSetters =
+            new ThreadSafeStore<string, CallSite<Func<CallSite, object, object, object>>>(CreateCallSiteSetter);
+
+        private static CallSite<Func<CallSite, object, object>> CreateCallSiteGetter(string name)
+        {
+            GetMemberBinder getMemberBinder = (GetMemberBinder)DynamicUtils.BinderWrapper.GetMember(name, typeof(DynamicUtils));
+
+            return CallSite<Func<CallSite, object, object>>.Create(new NoThrowGetBinderMember(getMemberBinder));
+        }
+
+        private static CallSite<Func<CallSite, object, object, object>> CreateCallSiteSetter(string name)
+        {
+            SetMemberBinder binder = (SetMemberBinder)DynamicUtils.BinderWrapper.SetMember(name, typeof(DynamicUtils));
+
+            return CallSite<Func<CallSite, object, object, object>>.Create(new NoThrowSetBinderMember(binder));
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonDynamicContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonDynamicContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Dynamic;
+
+            Properties = new JsonPropertyCollection(UnderlyingType);
+        }
+
+        internal bool TryGetMember(IDynamicMetaObjectProvider dynamicProvider, string name, out object value)
+        {
+            ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
+
+            CallSite<Func<CallSite, object, object>> callSite = _callSiteGetters.Get(name);
+
+            object result = callSite.Target(callSite, dynamicProvider);
+
+            if (!ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult))
+            {
+                value = result;
+                return true;
+            }
+            else
+            {
+                value = null;
+                return false;
+            }
+        }
+
+        internal bool TrySetMember(IDynamicMetaObjectProvider dynamicProvider, string name, object value)
+        {
+            ValidationUtils.ArgumentNotNull(dynamicProvider, "dynamicProvider");
+
+            CallSite<Func<CallSite, object, object, object>> callSite = _callSiteSetters.Get(name);
+
+            object result = callSite.Target(callSite, dynamicProvider, value);
+
+            return !ReferenceEquals(result, NoThrowExpressionVisitor.ErrorResult);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs b/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs
new file mode 100644
index 0000000..47fceea
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonFormatterConverter.cs
@@ -0,0 +1,152 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Globalization;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Utilities;
+using Newtonsoft.Json.Linq;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class JsonFormatterConverter : IFormatterConverter
+    {
+        private readonly JsonSerializer _serializer;
+
+        public JsonFormatterConverter(JsonSerializer serializer)
+        {
+            ValidationUtils.ArgumentNotNull(serializer, "serializer");
+
+            _serializer = serializer;
+        }
+
+        private T GetTokenValue<T>(object value)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+
+            JValue v = (JValue)value;
+            return (T)System.Convert.ChangeType(v.Value, typeof(T), CultureInfo.InvariantCulture);
+        }
+
+        public object Convert(object value, Type type)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+
+            JToken token = value as JToken;
+            if (token == null)
+                throw new ArgumentException("Value is not a JToken.", "value");
+
+            return _serializer.Deserialize(token.CreateReader(), type);
+        }
+
+        public object Convert(object value, TypeCode typeCode)
+        {
+            ValidationUtils.ArgumentNotNull(value, "value");
+
+            if (value is JValue)
+                value = ((JValue)value).Value;
+
+            return System.Convert.ChangeType(value, typeCode, CultureInfo.InvariantCulture);
+        }
+
+        public bool ToBoolean(object value)
+        {
+            return GetTokenValue<bool>(value);
+        }
+
+        public byte ToByte(object value)
+        {
+            return GetTokenValue<byte>(value);
+        }
+
+        public char ToChar(object value)
+        {
+            return GetTokenValue<char>(value);
+        }
+
+        public DateTime ToDateTime(object value)
+        {
+            return GetTokenValue<DateTime>(value);
+        }
+
+        public decimal ToDecimal(object value)
+        {
+            return GetTokenValue<decimal>(value);
+        }
+
+        public double ToDouble(object value)
+        {
+            return GetTokenValue<double>(value);
+        }
+
+        public short ToInt16(object value)
+        {
+            return GetTokenValue<short>(value);
+        }
+
+        public int ToInt32(object value)
+        {
+            return GetTokenValue<int>(value);
+        }
+
+        public long ToInt64(object value)
+        {
+            return GetTokenValue<long>(value);
+        }
+
+        public sbyte ToSByte(object value)
+        {
+            return GetTokenValue<sbyte>(value);
+        }
+
+        public float ToSingle(object value)
+        {
+            return GetTokenValue<float>(value);
+        }
+
+        public string ToString(object value)
+        {
+            return GetTokenValue<string>(value);
+        }
+
+        public ushort ToUInt16(object value)
+        {
+            return GetTokenValue<ushort>(value);
+        }
+
+        public uint ToUInt32(object value)
+        {
+            return GetTokenValue<uint>(value);
+        }
+
+        public ulong ToUInt64(object value)
+        {
+            return GetTokenValue<ulong>(value);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonISerializableContract.cs b/Newtonsoft.Json/Serialization/JsonISerializableContract.cs
new file mode 100644
index 0000000..6c6d7d9
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonISerializableContract.cs
@@ -0,0 +1,54 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonISerializableContract : JsonContainerContract
+    {
+        /// <summary>
+        /// Gets or sets the ISerializable object constructor.
+        /// </summary>
+        /// <value>The ISerializable object constructor.</value>
+        public ObjectConstructor<object> ISerializableCreator { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonISerializableContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonISerializableContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Serializable;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonLinqContract.cs b/Newtonsoft.Json/Serialization/JsonLinqContract.cs
new file mode 100644
index 0000000..121607d
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonLinqContract.cs
@@ -0,0 +1,45 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonLinqContract : JsonContract
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonLinqContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonLinqContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Linq;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonObjectContract.cs b/Newtonsoft.Json/Serialization/JsonObjectContract.cs
new file mode 100644
index 0000000..b4867a8
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonObjectContract.cs
@@ -0,0 +1,147 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Reflection;
+using System.Runtime.Serialization;
+using System.Security;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonObjectContract : JsonContainerContract
+    {
+        /// <summary>
+        /// Gets or sets the object member serialization.
+        /// </summary>
+        /// <value>The member object serialization.</value>
+        public MemberSerialization MemberSerialization { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value that indicates whether the object's properties are required.
+        /// </summary>
+        /// <value>
+        /// 	A value indicating whether the object's properties are required.
+        /// </value>
+        public Required? ItemRequired { get; set; }
+
+        /// <summary>
+        /// Gets the object's properties.
+        /// </summary>
+        /// <value>The object's properties.</value>
+        public JsonPropertyCollection Properties { get; private set; }
+
+        /// <summary>
+        /// Gets the constructor parameters required for any non-default constructor
+        /// </summary>
+        public JsonPropertyCollection ConstructorParameters { get; private set; }
+
+        /// <summary>
+        /// Gets or sets the override constructor used to create the object.
+        /// This is set when a constructor is marked up using the
+        /// JsonConstructor attribute.
+        /// </summary>
+        /// <value>The override constructor.</value>
+        public ConstructorInfo OverrideConstructor { get; set; }
+
+        /// <summary>
+        /// Gets or sets the parametrized constructor used to create the object.
+        /// </summary>
+        /// <value>The parametrized constructor.</value>
+        public ConstructorInfo ParametrizedConstructor { get; set; }
+
+        /// <summary>
+        /// Gets or sets the extension data setter.
+        /// </summary>
+        public ExtensionDataSetter ExtensionDataSetter { get; set; }
+
+        /// <summary>
+        /// Gets or sets the extension data getter.
+        /// </summary>
+        public ExtensionDataGetter ExtensionDataGetter { get; set; }
+
+        private bool? _hasRequiredOrDefaultValueProperties;
+
+        internal bool HasRequiredOrDefaultValueProperties
+        {
+            get
+            {
+                if (_hasRequiredOrDefaultValueProperties == null)
+                {
+                    _hasRequiredOrDefaultValueProperties = false;
+
+                    if (ItemRequired.GetValueOrDefault(Required.Default) != Required.Default)
+                    {
+                        _hasRequiredOrDefaultValueProperties = true;
+                    }
+                    else
+                    {
+                        foreach (JsonProperty property in Properties)
+                        {
+                            if (property.Required != Required.Default || ((property.DefaultValueHandling & DefaultValueHandling.Populate) == DefaultValueHandling.Populate) && property.Writable)
+                            {
+                                _hasRequiredOrDefaultValueProperties = true;
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                return _hasRequiredOrDefaultValueProperties.Value;
+            }
+        }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonObjectContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonObjectContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Object;
+
+            Properties = new JsonPropertyCollection(UnderlyingType);
+            ConstructorParameters = new JsonPropertyCollection(UnderlyingType);
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+#if !(NET20 || NET35)
+        [SecuritySafeCritical]
+#endif
+        internal object GetUninitializedObject()
+        {
+            // we should never get here if the environment is not fully trusted, check just in case
+            if (!JsonTypeReflector.FullyTrusted)
+                throw new JsonException("Insufficient permissions. Creating an uninitialized '{0}' type requires full trust.".FormatWith(CultureInfo.InvariantCulture, NonNullableUnderlyingType));
+
+            return FormatterServices.GetUninitializedObject(NonNullableUnderlyingType);
+        }
+#endif
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs b/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs
new file mode 100644
index 0000000..b810766
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonPrimitiveContract.cs
@@ -0,0 +1,51 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonPrimitiveContract : JsonContract
+    {
+        internal PrimitiveTypeCode TypeCode { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonPrimitiveContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonPrimitiveContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.Primitive;
+
+            TypeCode = ConvertUtils.GetTypeCode(underlyingType);
+            IsReadOnlyOrFixedSize = true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonProperty.cs b/Newtonsoft.Json/Serialization/JsonProperty.cs
new file mode 100644
index 0000000..98c45ba
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonProperty.cs
@@ -0,0 +1,282 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Utilities;
+
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Maps a JSON property to a .NET member or constructor parameter.
+    /// </summary>
+    public class JsonProperty
+    {
+        internal Required? _required;
+        internal bool _hasExplicitDefaultValue;
+        internal object _defaultValue;
+
+        private string _propertyName;
+        private bool _skipPropertyNameEscape;
+
+        // use to cache contract during deserialization
+        internal JsonContract PropertyContract { get; set; }
+
+        /// <summary>
+        /// Gets or sets the name of the property.
+        /// </summary>
+        /// <value>The name of the property.</value>
+        public string PropertyName
+        {
+            get { return _propertyName; }
+            set
+            {
+                _propertyName = value;
+                CalculateSkipPropertyNameEscape();
+            }
+        }
+
+        private void CalculateSkipPropertyNameEscape()
+        {
+            if (_propertyName == null)
+            {
+                _skipPropertyNameEscape = false;
+            }
+            else
+            {
+                _skipPropertyNameEscape = true;
+                foreach (char c in _propertyName)
+                {
+                    if (!char.IsLetterOrDigit(c) && c != '_' && c != '@')
+                    {
+                        _skipPropertyNameEscape = false;
+                        break;
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Gets or sets the type that declared this property.
+        /// </summary>
+        /// <value>The type that declared this property.</value>
+        public Type DeclaringType { get; set; }
+
+        /// <summary>
+        /// Gets or sets the order of serialization and deserialization of a member.
+        /// </summary>
+        /// <value>The numeric order of serialization or deserialization.</value>
+        public int? Order { get; set; }
+
+        /// <summary>
+        /// Gets or sets the name of the underlying member or parameter.
+        /// </summary>
+        /// <value>The name of the underlying member or parameter.</value>
+        public string UnderlyingName { get; set; }
+
+        /// <summary>
+        /// Gets the <see cref="IValueProvider"/> that will get and set the <see cref="JsonProperty"/> during serialization.
+        /// </summary>
+        /// <value>The <see cref="IValueProvider"/> that will get and set the <see cref="JsonProperty"/> during serialization.</value>
+        public IValueProvider ValueProvider { get; set; }
+
+        /// <summary>
+        /// Gets or sets the type of the property.
+        /// </summary>
+        /// <value>The type of the property.</value>
+        public Type PropertyType { get; set; }
+
+        /// <summary>
+        /// Gets or sets the <see cref="JsonConverter" /> for the property.
+        /// If set this converter takes presidence over the contract converter for the property type.
+        /// </summary>
+        /// <value>The converter.</value>
+        public JsonConverter Converter { get; set; }
+
+        /// <summary>
+        /// Gets or sets the member converter.
+        /// </summary>
+        /// <value>The member converter.</value>
+        public JsonConverter MemberConverter { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="JsonProperty"/> is ignored.
+        /// </summary>
+        /// <value><c>true</c> if ignored; otherwise, <c>false</c>.</value>
+        public bool Ignored { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="JsonProperty"/> is readable.
+        /// </summary>
+        /// <value><c>true</c> if readable; otherwise, <c>false</c>.</value>
+        public bool Readable { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="JsonProperty"/> is writable.
+        /// </summary>
+        /// <value><c>true</c> if writable; otherwise, <c>false</c>.</value>
+        public bool Writable { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="JsonProperty"/> has a member attribute.
+        /// </summary>
+        /// <value><c>true</c> if has a member attribute; otherwise, <c>false</c>.</value>
+        public bool HasMemberAttribute { get; set; }
+
+        /// <summary>
+        /// Gets the default value.
+        /// </summary>
+        /// <value>The default value.</value>
+        public object DefaultValue
+        {
+            get { return _defaultValue; }
+            set
+            {
+                _hasExplicitDefaultValue = true;
+                _defaultValue = value;
+            }
+        }
+
+        internal object GetResolvedDefaultValue()
+        {
+            if (!_hasExplicitDefaultValue && PropertyType != null)
+                return ReflectionUtils.GetDefaultValue(PropertyType);
+
+            return _defaultValue;
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this <see cref="JsonProperty"/> is required.
+        /// </summary>
+        /// <value>A value indicating whether this <see cref="JsonProperty"/> is required.</value>
+        public Required Required
+        {
+            get { return _required ?? Required.Default; }
+            set { _required = value; }
+        }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether this property preserves object references.
+        /// </summary>
+        /// <value>
+        /// 	<c>true</c> if this instance is reference; otherwise, <c>false</c>.
+        /// </value>
+        public bool? IsReference { get; set; }
+
+        /// <summary>
+        /// Gets or sets the property null value handling.
+        /// </summary>
+        /// <value>The null value handling.</value>
+        public NullValueHandling? NullValueHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets the property default value handling.
+        /// </summary>
+        /// <value>The default value handling.</value>
+        public DefaultValueHandling? DefaultValueHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets the property reference loop handling.
+        /// </summary>
+        /// <value>The reference loop handling.</value>
+        public ReferenceLoopHandling? ReferenceLoopHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets the property object creation handling.
+        /// </summary>
+        /// <value>The object creation handling.</value>
+        public ObjectCreationHandling? ObjectCreationHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets or sets the type name handling.
+        /// </summary>
+        /// <value>The type name handling.</value>
+        public TypeNameHandling? TypeNameHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets a predicate used to determine whether the property should be serialize.
+        /// </summary>
+        /// <value>A predicate used to determine whether the property should be serialize.</value>
+        public Predicate<object> ShouldSerialize { get; set; }
+
+        /// <summary>
+        /// Gets or sets a predicate used to determine whether the property should be serialized.
+        /// </summary>
+        /// <value>A predicate used to determine whether the property should be serialized.</value>
+        public Predicate<object> GetIsSpecified { get; set; }
+
+        /// <summary>
+        /// Gets or sets an action used to set whether the property has been deserialized.
+        /// </summary>
+        /// <value>An action used to set whether the property has been deserialized.</value>
+        public Action<object, object> SetIsSpecified { get; set; }
+
+        /// <summary>
+        /// Returns a <see cref="String"/> that represents this instance.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="String"/> that represents this instance.
+        /// </returns>
+        public override string ToString()
+        {
+            return PropertyName;
+        }
+
+        /// <summary>
+        /// Gets or sets the converter used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items converter.</value>
+        public JsonConverter ItemConverter { get; set; }
+
+        /// <summary>
+        /// Gets or sets whether this property's collection items are serialized as a reference.
+        /// </summary>
+        /// <value>Whether this property's collection items are serialized as a reference.</value>
+        public bool? ItemIsReference { get; set; }
+
+        /// <summary>
+        /// Gets or sets the the type name handling used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items type name handling.</value>
+        public TypeNameHandling? ItemTypeNameHandling { get; set; }
+
+        /// <summary>
+        /// Gets or sets the the reference loop handling used when serializing the property's collection items.
+        /// </summary>
+        /// <value>The collection's items reference loop handling.</value>
+        public ReferenceLoopHandling? ItemReferenceLoopHandling { get; set; }
+
+        internal void WritePropertyName(JsonWriter writer)
+        {
+            if (_skipPropertyNameEscape)
+                writer.WritePropertyName(PropertyName, false);
+            else
+                writer.WritePropertyName(PropertyName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs b/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
new file mode 100644
index 0000000..0588d76
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonPropertyCollection.cs
@@ -0,0 +1,165 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Collections.ObjectModel;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// A collection of <see cref="JsonProperty"/> objects.
+    /// </summary>
+    public class JsonPropertyCollection : KeyedCollection<string, JsonProperty>
+    {
+        private readonly Type _type;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonPropertyCollection"/> class.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        public JsonPropertyCollection(Type type)
+            : base(StringComparer.Ordinal)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+            _type = type;
+        }
+
+        /// <summary>
+        /// When implemented in a derived class, extracts the key from the specified element.
+        /// </summary>
+        /// <param name="item">The element from which to extract the key.</param>
+        /// <returns>The key for the specified element.</returns>
+        protected override string GetKeyForItem(JsonProperty item)
+        {
+            return item.PropertyName;
+        }
+
+        /// <summary>
+        /// Adds a <see cref="JsonProperty"/> object.
+        /// </summary>
+        /// <param name="property">The property to add to the collection.</param>
+        public void AddProperty(JsonProperty property)
+        {
+            if (Contains(property.PropertyName))
+            {
+                // don't overwrite existing property with ignored property
+                if (property.Ignored)
+                    return;
+
+                JsonProperty existingProperty = this[property.PropertyName];
+                bool duplicateProperty = true;
+
+                if (existingProperty.Ignored)
+                {
+                    // remove ignored property so it can be replaced in collection
+                    Remove(existingProperty);
+                    duplicateProperty = false;
+                }
+                else
+                {
+                    if (property.DeclaringType != null && existingProperty.DeclaringType != null)
+                    {
+                        if (property.DeclaringType.IsSubclassOf(existingProperty.DeclaringType))
+                        {
+                            // current property is on a derived class and hides the existing
+                            Remove(existingProperty);
+                            duplicateProperty = false;
+                        }
+                        if (existingProperty.DeclaringType.IsSubclassOf(property.DeclaringType))
+                        {
+                            // current property is hidden by the existing so don't add it
+                            return;
+                        }
+                    }
+                }
+
+                if (duplicateProperty)
+                    throw new JsonSerializationException("A member with the name '{0}' already exists on '{1}'. Use the JsonPropertyAttribute to specify another name.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, _type));
+            }
+
+            Add(property);
+        }
+
+        /// <summary>
+        /// Gets the closest matching <see cref="JsonProperty"/> object.
+        /// First attempts to get an exact case match of propertyName and then
+        /// a case insensitive match.
+        /// </summary>
+        /// <param name="propertyName">Name of the property.</param>
+        /// <returns>A matching property if found.</returns>
+        public JsonProperty GetClosestMatchProperty(string propertyName)
+        {
+            JsonProperty property = GetProperty(propertyName, StringComparison.Ordinal);
+            if (property == null)
+                property = GetProperty(propertyName, StringComparison.OrdinalIgnoreCase);
+
+            return property;
+        }
+
+        private bool TryGetValue(string key, out JsonProperty item)
+        {
+            if (Dictionary == null)
+            {
+                item = default(JsonProperty);
+                return false;
+            }
+
+            return Dictionary.TryGetValue(key, out item);
+        }
+
+        /// <summary>
+        /// Gets a property by property name.
+        /// </summary>
+        /// <param name="propertyName">The name of the property to get.</param>
+        /// <param name="comparisonType">Type property name string comparison.</param>
+        /// <returns>A matching property if found.</returns>
+        public JsonProperty GetProperty(string propertyName, StringComparison comparisonType)
+        {
+            // KeyedCollection has an ordinal comparer
+            if (comparisonType == StringComparison.Ordinal)
+            {
+                JsonProperty property;
+                if (TryGetValue(propertyName, out property))
+                    return property;
+
+                return null;
+            }
+
+            foreach (JsonProperty property in this)
+            {
+                if (string.Equals(propertyName, property.PropertyName, comparisonType))
+                {
+                    return property;
+                }
+            }
+
+            return null;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs b/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs
new file mode 100644
index 0000000..922e0b1
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonSerializerInternalBase.cs
@@ -0,0 +1,141 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Net;
+using System.Runtime.CompilerServices;
+using Newtonsoft.Json.Utilities;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal abstract class JsonSerializerInternalBase
+    {
+        private class ReferenceEqualsEqualityComparer : IEqualityComparer<object>
+        {
+            bool IEqualityComparer<object>.Equals(object x, object y)
+            {
+                return ReferenceEquals(x, y);
+            }
+
+            int IEqualityComparer<object>.GetHashCode(object obj)
+            {
+#if !(NETFX_CORE)
+                // put objects in a bucket based on their reference
+                return RuntimeHelpers.GetHashCode(obj);
+#else
+    // put all objects in the same bucket so ReferenceEquals is called on all
+        return -1;
+#endif
+            }
+        }
+
+        private ErrorContext _currentErrorContext;
+        private BidirectionalDictionary<string, object> _mappings;
+        private bool _serializing;
+
+        internal readonly JsonSerializer Serializer;
+        internal readonly ITraceWriter TraceWriter;
+
+        protected JsonSerializerInternalBase(JsonSerializer serializer)
+        {
+            ValidationUtils.ArgumentNotNull(serializer, "serializer");
+
+            Serializer = serializer;
+            TraceWriter = serializer.TraceWriter;
+
+            // kind of a hack but meh. might clean this up later
+            _serializing = (GetType() == typeof(JsonSerializerInternalWriter));
+        }
+
+        internal BidirectionalDictionary<string, object> DefaultReferenceMappings
+        {
+            get
+            {
+                // override equality comparer for object key dictionary
+                // object will be modified as it deserializes and might have mutable hashcode
+                if (_mappings == null)
+                    _mappings = new BidirectionalDictionary<string, object>(
+                        EqualityComparer<string>.Default,
+                        new ReferenceEqualsEqualityComparer(),
+                        "A different value already has the Id '{0}'.",
+                        "A different Id has already been assigned for value '{0}'.");
+
+                return _mappings;
+            }
+        }
+
+        private ErrorContext GetErrorContext(object currentObject, object member, string path, Exception error)
+        {
+            if (_currentErrorContext == null)
+                _currentErrorContext = new ErrorContext(currentObject, member, path, error);
+
+            if (_currentErrorContext.Error != error)
+                throw new InvalidOperationException("Current error context error is different to requested error.");
+
+            return _currentErrorContext;
+        }
+
+        protected void ClearErrorContext()
+        {
+            if (_currentErrorContext == null)
+                throw new InvalidOperationException("Could not clear error context. Error context is already null.");
+
+            _currentErrorContext = null;
+        }
+
+        protected bool IsErrorHandled(object currentObject, JsonContract contract, object keyValue, IJsonLineInfo lineInfo, string path, Exception ex)
+        {
+            ErrorContext errorContext = GetErrorContext(currentObject, keyValue, path, ex);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Error && !errorContext.Traced)
+            {
+                // only write error once
+                errorContext.Traced = true;
+
+                string message = (_serializing) ? "Error serializing" : "Error deserializing";
+                if (contract != null)
+                    message += " " + contract.UnderlyingType;
+                message += ". " + ex.Message;
+
+                // add line information to non-json.net exception message
+                if (!(ex is JsonException))
+                    message = JsonPosition.FormatMessage(lineInfo, path, message);
+
+                TraceWriter.Trace(TraceLevel.Error, message, ex);
+            }
+
+            // attribute method is non-static so don't invoke if no object
+            if (contract != null && currentObject != null)
+                contract.InvokeOnError(currentObject, Serializer.Context, errorContext);
+
+            if (!errorContext.Handled)
+                Serializer.OnError(new ErrorEventArgs(currentObject, errorContext));
+
+            return errorContext.Handled;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs b/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
new file mode 100644
index 0000000..7596c59
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs
@@ -0,0 +1,2062 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.ComponentModel;
+using System.Dynamic;
+#endif
+using System.Diagnostics;
+using System.Globalization;
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+using System.Numerics;
+#endif
+using System.Reflection;
+using System.Runtime.Serialization;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class JsonSerializerInternalReader : JsonSerializerInternalBase
+    {
+        internal enum PropertyPresence
+        {
+            None,
+            Null,
+            Value
+        }
+
+        private JsonSerializerProxy _internalSerializer;
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        private JsonFormatterConverter _formatterConverter;
+#endif
+
+        public JsonSerializerInternalReader(JsonSerializer serializer)
+            : base(serializer)
+        {
+        }
+
+        public void Populate(JsonReader reader, object target)
+        {
+            ValidationUtils.ArgumentNotNull(target, "target");
+
+            Type objectType = target.GetType();
+
+            JsonContract contract = Serializer._contractResolver.ResolveContract(objectType);
+
+            if (reader.TokenType == JsonToken.None)
+                reader.Read();
+
+            if (reader.TokenType == JsonToken.StartArray)
+            {
+                if (contract.ContractType == JsonContractType.Array)
+                {
+                    JsonArrayContract arrayContract = (JsonArrayContract)contract;
+
+                    PopulateList((arrayContract.ShouldCreateWrapper) ? arrayContract.CreateWrapper(target) : (IList)target, reader, arrayContract, null, null);
+                }
+                else
+                {
+                    throw JsonSerializationException.Create(reader, "Cannot populate JSON array onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
+                }
+            }
+            else if (reader.TokenType == JsonToken.StartObject)
+            {
+                CheckedRead(reader);
+
+                string id = null;
+                if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.IdPropertyName, StringComparison.Ordinal))
+                {
+                    CheckedRead(reader);
+                    id = (reader.Value != null) ? reader.Value.ToString() : null;
+                    CheckedRead(reader);
+                }
+
+                if (contract.ContractType == JsonContractType.Dictionary)
+                {
+                    JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)contract;
+                    PopulateDictionary((dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(target) : (IDictionary)target, reader, dictionaryContract, null, id);
+                }
+                else if (contract.ContractType == JsonContractType.Object)
+                {
+                    PopulateObject(target, reader, (JsonObjectContract)contract, null, id);
+                }
+                else
+                {
+                    throw JsonSerializationException.Create(reader, "Cannot populate JSON object onto type '{0}'.".FormatWith(CultureInfo.InvariantCulture, objectType));
+                }
+            }
+            else
+            {
+                throw JsonSerializationException.Create(reader, "Unexpected initial token '{0}' when populating object. Expected JSON object or array.".FormatWith(CultureInfo.InvariantCulture, reader.TokenType));
+            }
+        }
+
+        private JsonContract GetContractSafe(Type type)
+        {
+            if (type == null)
+                return null;
+
+            return Serializer._contractResolver.ResolveContract(type);
+        }
+
+        public object Deserialize(JsonReader reader, Type objectType, bool checkAdditionalContent)
+        {
+            if (reader == null)
+                throw new ArgumentNullException("reader");
+
+            JsonContract contract = GetContractSafe(objectType);
+
+            try
+            {
+                JsonConverter converter = GetConverter(contract, null, null, null);
+
+                if (reader.TokenType == JsonToken.None && !ReadForType(reader, contract, converter != null))
+                {
+                    if (contract != null && !contract.IsNullable)
+                        throw JsonSerializationException.Create(reader, "No JSON content found and type '{0}' is not nullable.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                    return null;
+                }
+
+                object deserializedValue;
+
+                if (converter != null && converter.CanRead)
+                    deserializedValue = DeserializeConvertable(converter, reader, objectType, null);
+                else
+                    deserializedValue = CreateValueInternal(reader, objectType, contract, null, null, null, null);
+
+                if (checkAdditionalContent)
+                {
+                    if (reader.Read() && reader.TokenType != JsonToken.Comment)
+                        throw new JsonSerializationException("Additional text found in JSON string after finishing deserializing object.");
+                }
+
+                return deserializedValue;
+            }
+            catch (Exception ex)
+            {
+                if (IsErrorHandled(null, contract, null, reader as IJsonLineInfo, reader.Path, ex))
+                {
+                    HandleError(reader, false, 0);
+                    return null;
+                }
+                else
+                {
+                    // clear context in case serializer is being used inside a converter
+                    // if the converter wraps the error then not clearing the context will cause this error:
+                    // "Current error context error is different to requested error."
+                    ClearErrorContext();
+                    throw;
+                }
+            }
+        }
+
+        private JsonSerializerProxy GetInternalSerializer()
+        {
+            if (_internalSerializer == null)
+                _internalSerializer = new JsonSerializerProxy(this);
+
+            return _internalSerializer;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        private JsonFormatterConverter GetFormatterConverter()
+        {
+            if (_formatterConverter == null)
+                _formatterConverter = new JsonFormatterConverter(GetInternalSerializer());
+
+            return _formatterConverter;
+        }
+#endif
+
+        private JToken CreateJToken(JsonReader reader, JsonContract contract)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            if (contract != null && contract.UnderlyingType == typeof(JRaw))
+            {
+                return JRaw.Create(reader);
+            }
+            else
+            {
+                JToken token;
+                using (JTokenWriter writer = new JTokenWriter())
+                {
+                    writer.WriteToken(reader);
+                    token = writer.Token;
+                }
+
+                return token;
+            }
+        }
+
+        private JToken CreateJObject(JsonReader reader)
+        {
+            ValidationUtils.ArgumentNotNull(reader, "reader");
+
+            // this is needed because we've already read inside the object, looking for metadata properties
+            using (JTokenWriter writer = new JTokenWriter())
+            {
+                writer.WriteStartObject();
+
+                do
+                {
+                    if (reader.TokenType == JsonToken.PropertyName)
+                    {
+                        string propertyName = (string)reader.Value;
+                        if (!reader.Read())
+                            break;
+
+                        if (CheckPropertyName(reader, propertyName))
+                            continue;
+
+                        writer.WritePropertyName(propertyName);
+                        writer.WriteToken(reader, true, true);
+                    }
+                    else
+                    {
+                        writer.WriteEndObject();
+                        return writer.Token;
+                    }
+                } while (reader.Read());
+
+                throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
+            }
+        }
+
+        private object CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
+        {
+            if (contract != null && contract.ContractType == JsonContractType.Linq)
+                return CreateJToken(reader, contract);
+
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    // populate a typed object or generic dictionary/array
+                    // depending upon whether an objectType was supplied
+                    case JsonToken.StartObject:
+                        return CreateObject(reader, objectType, contract, member, containerContract, containerMember, existingValue);
+                    case JsonToken.StartArray:
+                        return CreateList(reader, objectType, contract, member, existingValue, null);
+                    case JsonToken.Integer:
+                    case JsonToken.Float:
+                    case JsonToken.Boolean:
+                    case JsonToken.Date:
+                    case JsonToken.Bytes:
+                        return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
+                    case JsonToken.String:
+                        string s = (string)reader.Value;
+
+                        // convert empty string to null automatically for nullable types
+                        if (string.IsNullOrEmpty(s) && objectType != typeof(string) && objectType != typeof(object) && contract != null && contract.IsNullable)
+                            return null;
+
+                        // string that needs to be returned as a byte array should be base 64 decoded
+                        if (objectType == typeof(byte[]))
+                            return Convert.FromBase64String(s);
+
+                        return EnsureType(reader, s, CultureInfo.InvariantCulture, contract, objectType);
+                    case JsonToken.StartConstructor:
+                        string constructorName = reader.Value.ToString();
+
+                        return EnsureType(reader, constructorName, CultureInfo.InvariantCulture, contract, objectType);
+                    case JsonToken.Null:
+                    case JsonToken.Undefined:
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                        if (objectType == typeof(DBNull))
+                            return DBNull.Value;
+#endif
+
+                        return EnsureType(reader, reader.Value, CultureInfo.InvariantCulture, contract, objectType);
+                    case JsonToken.Raw:
+                        return new JRaw((string)reader.Value);
+                    case JsonToken.Comment:
+                        // ignore
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token while deserializing object: " + reader.TokenType);
+                }
+            } while (reader.Read());
+
+            throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
+        }
+
+        internal string GetExpectedDescription(JsonContract contract)
+        {
+            switch (contract.ContractType)
+            {
+                case JsonContractType.Object:
+                case JsonContractType.Dictionary:
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+                case JsonContractType.Serializable:
+#endif
+#if !(NET35 || NET20 || PORTABLE40)
+                case JsonContractType.Dynamic:
+#endif
+                    return @"JSON object (e.g. {""name"":""value""})";
+                case JsonContractType.Array:
+                    return @"JSON array (e.g. [1,2,3])";
+                case JsonContractType.Primitive:
+                    return @"JSON primitive value (e.g. string, number, boolean, null)";
+                case JsonContractType.String:
+                    return @"JSON string value";
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        private JsonConverter GetConverter(JsonContract contract, JsonConverter memberConverter, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            JsonConverter converter = null;
+            if (memberConverter != null)
+            {
+                // member attribute converter
+                converter = memberConverter;
+            }
+            else if (containerProperty != null && containerProperty.ItemConverter != null)
+            {
+                converter = containerProperty.ItemConverter;
+            }
+            else if (containerContract != null && containerContract.ItemConverter != null)
+            {
+                converter = containerContract.ItemConverter;
+            }
+            else if (contract != null)
+            {
+                JsonConverter matchingConverter;
+                if (contract.Converter != null)
+                    // class attribute converter
+                    converter = contract.Converter;
+                else if ((matchingConverter = Serializer.GetMatchingConverter(contract.UnderlyingType)) != null)
+                    // passed in converters
+                    converter = matchingConverter;
+                else if (contract.InternalConverter != null)
+                    // internally specified converter
+                    converter = contract.InternalConverter;
+            }
+            return converter;
+        }
+
+        private object CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue)
+        {
+            string id;
+            object newValue;
+            Type resolvedObjectType = objectType;
+
+            if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead)
+            {
+                var tokenReader = reader as JTokenReader;
+                if (tokenReader == null)
+                {
+                    JToken t = JToken.ReadFrom(reader);
+                    tokenReader = (JTokenReader)t.CreateReader();
+
+                    // start
+                    CheckedRead(tokenReader);
+
+                    reader = tokenReader;
+                }
+
+                if (ReadMetadataPropertiesToken(tokenReader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
+                    return newValue;
+            }
+            else
+            {
+                CheckedRead(reader);
+                if (ReadMetadataProperties(reader, ref resolvedObjectType, ref contract, member, containerContract, containerMember, existingValue, out newValue, out id))
+                    return newValue;
+            }
+
+            if (HasNoDefinedType(contract))
+                return CreateJObject(reader);
+
+            switch (contract.ContractType)
+            {
+                case JsonContractType.Object:
+                {
+                    bool createdFromNonDefaultConstructor = false;
+                    JsonObjectContract objectContract = (JsonObjectContract)contract;
+                    object targetObject;
+                    // check that if type name handling is being used that the existing value is compatible with the specified type
+                    if (existingValue != null && (resolvedObjectType == objectType || resolvedObjectType.IsAssignableFrom(existingValue.GetType())))
+                        targetObject = existingValue;
+                    else
+                        targetObject = CreateNewObject(reader, objectContract, member, containerMember, id, out createdFromNonDefaultConstructor);
+
+                    // don't populate if read from non-default constructor because the object has already been read
+                    if (createdFromNonDefaultConstructor)
+                        return targetObject;
+
+                    return PopulateObject(targetObject, reader, objectContract, member, id);
+                }
+                case JsonContractType.Primitive:
+                {
+                    JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
+                    // if the content is inside $value then read past it
+                    if (reader.TokenType == JsonToken.PropertyName && string.Equals(reader.Value.ToString(), JsonTypeReflector.ValuePropertyName, StringComparison.Ordinal))
+                    {
+                        CheckedRead(reader);
+
+                        // the token should not be an object because the $type value could have been included in the object
+                        // without needing the $value property
+                        if (reader.TokenType == JsonToken.StartObject)
+                            throw JsonSerializationException.Create(reader, "Unexpected token when deserializing primitive value: " + reader.TokenType);
+
+                        object value = CreateValueInternal(reader, resolvedObjectType, primitiveContract, member, null, null, existingValue);
+
+                        CheckedRead(reader);
+                        return value;
+                    }
+                    break;
+                }
+                case JsonContractType.Dictionary:
+                {
+                    JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)contract;
+                    object targetDictionary;
+
+                    if (existingValue == null)
+                    {
+                        bool createdFromNonDefaultConstructor;
+                        IDictionary dictionary = CreateNewDictionary(reader, dictionaryContract, out createdFromNonDefaultConstructor);
+
+                        if (createdFromNonDefaultConstructor)
+                        {
+                            if (id != null)
+                                throw JsonSerializationException.Create(reader, "Cannot preserve reference to readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                            if (contract.OnSerializingCallbacks.Count > 0)
+                                throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on readonly dictionary, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                            if (contract.OnErrorCallbacks.Count > 0)
+                                throw JsonSerializationException.Create(reader, "Cannot call OnError on readonly list, or dictionary created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                            if (dictionaryContract.ParametrizedConstructor == null)
+                                throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size dictionary: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+                        }
+
+                        PopulateDictionary(dictionary, reader, dictionaryContract, member, id);
+
+                        if (createdFromNonDefaultConstructor)
+                        {
+                            ConstructorInfo constructor = dictionaryContract.ParametrizedConstructor as ConstructorInfo;
+                            if (constructor != null)
+                                return constructor.Invoke(new object[] { dictionary });
+
+                            return dictionaryContract.ParametrizedConstructor.Invoke(null, new object[] { dictionary });
+                        }
+                        else if (dictionary is IWrappedDictionary)
+                        {
+                            return ((IWrappedDictionary)dictionary).UnderlyingDictionary;
+                        }
+
+                        targetDictionary = dictionary;
+                    }
+                    else
+                    {
+                        targetDictionary = PopulateDictionary(dictionaryContract.ShouldCreateWrapper ? dictionaryContract.CreateWrapper(existingValue) : (IDictionary)existingValue, reader, dictionaryContract, member, id);
+                    }
+
+                    return targetDictionary;
+                }
+#if !(NET35 || NET20 || PORTABLE40)
+                case JsonContractType.Dynamic:
+                    JsonDynamicContract dynamicContract = (JsonDynamicContract)contract;
+                    return CreateDynamic(reader, dynamicContract, member, id);
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                case JsonContractType.Serializable:
+                    JsonISerializableContract serializableContract = (JsonISerializableContract)contract;
+                    return CreateISerializable(reader, serializableContract, member, id);
+#endif
+            }
+
+            throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON object (e.g. {{""name"":""value""}}) into type '{0}' because the type requires a {1} to deserialize correctly.
+To fix this error either change the JSON to a {1} or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
+".FormatWith(CultureInfo.InvariantCulture, resolvedObjectType, GetExpectedDescription(contract)));
+        }
+
+        private bool ReadMetadataPropertiesToken(JTokenReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
+        {
+            id = null;
+            newValue = null;
+
+            if (reader.TokenType == JsonToken.StartObject)
+            {
+                JObject current = (JObject)reader._current;
+
+                JToken refToken = current[JsonTypeReflector.RefPropertyName];
+                if (refToken != null)
+                {
+                    if (refToken.Type != JTokenType.String && refToken.Type != JTokenType.Null)
+                        throw JsonSerializationException.Create(refToken, refToken.Path, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
+
+                    JToken property = refToken.Parent;
+                    JToken additionalContent = null;
+                    if (property.Next != null)
+                        additionalContent = property.Next;
+                    else if (property.Previous != null)
+                        additionalContent = property.Previous;
+
+                    string reference = (string)refToken;
+
+                    if (reference != null)
+                    {
+                        if (additionalContent != null)
+                            throw JsonSerializationException.Create(additionalContent, additionalContent.Path, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName), null);
+
+                        newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference);
+
+                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                            TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null);
+
+                        reader.Skip();
+                        return true;
+                    }
+                }
+                JToken typeToken = current[JsonTypeReflector.TypePropertyName];
+                if (typeToken != null)
+                {
+                    string qualifiedTypeName = (string)typeToken;
+                    JsonReader typeTokenReader = typeToken.CreateReader();
+                    CheckedRead(typeTokenReader);
+                    ResolveTypeName(typeTokenReader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName);
+
+                    JToken valueToken = current[JsonTypeReflector.ValuePropertyName];
+                    if (valueToken != null)
+                    {
+                        while (true)
+                        {
+                            CheckedRead(reader);
+                            if (reader.TokenType == JsonToken.PropertyName)
+                            {
+                                if ((string)reader.Value == JsonTypeReflector.ValuePropertyName)
+                                    return false;
+                            }
+
+                            CheckedRead(reader);
+                            reader.Skip();
+                        }
+                    }
+                }
+                JToken idToken = current[JsonTypeReflector.IdPropertyName];
+                if (idToken != null)
+                {
+                    id = (string)idToken;
+                }
+                JToken valuesToken = current[JsonTypeReflector.ArrayValuesPropertyName];
+                if (valuesToken != null)
+                {
+                    JsonReader listReader = valuesToken.CreateReader();
+                    CheckedRead(listReader);
+                    newValue = CreateList(listReader, objectType, contract, member, existingValue, id);
+
+                    reader.Skip();
+                    return true;
+                }
+            }
+
+            CheckedRead(reader);
+            return false;
+        }
+
+        private bool ReadMetadataProperties(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, object existingValue, out object newValue, out string id)
+        {
+            id = null;
+            newValue = null;
+
+            if (reader.TokenType == JsonToken.PropertyName)
+            {
+                string propertyName = reader.Value.ToString();
+
+                if (propertyName.Length > 0 && propertyName[0] == '$')
+                {
+                    // read metadata properties
+                    // $type, $id, $ref, etc
+                    bool metadataProperty;
+
+                    do
+                    {
+                        propertyName = reader.Value.ToString();
+
+                        if (string.Equals(propertyName, JsonTypeReflector.RefPropertyName, StringComparison.Ordinal))
+                        {
+                            CheckedRead(reader);
+                            if (reader.TokenType != JsonToken.String && reader.TokenType != JsonToken.Null)
+                                throw JsonSerializationException.Create(reader, "JSON reference {0} property must have a string or null value.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));
+
+                            string reference = (reader.Value != null) ? reader.Value.ToString() : null;
+
+                            CheckedRead(reader);
+
+                            if (reference != null)
+                            {
+                                if (reader.TokenType == JsonToken.PropertyName)
+                                    throw JsonSerializationException.Create(reader, "Additional content found in JSON reference object. A JSON reference object should only have a {0} property.".FormatWith(CultureInfo.InvariantCulture, JsonTypeReflector.RefPropertyName));
+
+                                newValue = Serializer.GetReferenceResolver().ResolveReference(this, reference);
+
+                                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved object reference '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, reference, newValue.GetType())), null);
+
+                                return true;
+                            }
+                            else
+                            {
+                                metadataProperty = true;
+                            }
+                        }
+                        else if (string.Equals(propertyName, JsonTypeReflector.TypePropertyName, StringComparison.Ordinal))
+                        {
+                            CheckedRead(reader);
+                            string qualifiedTypeName = reader.Value.ToString();
+
+                            ResolveTypeName(reader, ref objectType, ref contract, member, containerContract, containerMember, qualifiedTypeName);
+
+                            CheckedRead(reader);
+
+                            metadataProperty = true;
+                        }
+                        else if (string.Equals(propertyName, JsonTypeReflector.IdPropertyName, StringComparison.Ordinal))
+                        {
+                            CheckedRead(reader);
+
+                            id = (reader.Value != null) ? reader.Value.ToString() : null;
+
+                            CheckedRead(reader);
+                            metadataProperty = true;
+                        }
+                        else if (string.Equals(propertyName, JsonTypeReflector.ArrayValuesPropertyName, StringComparison.Ordinal))
+                        {
+                            CheckedRead(reader);
+                            object list = CreateList(reader, objectType, contract, member, existingValue, id);
+                            CheckedRead(reader);
+                            newValue = list;
+                            return true;
+                        }
+                        else
+                        {
+                            metadataProperty = false;
+                        }
+                    } while (metadataProperty && reader.TokenType == JsonToken.PropertyName);
+                }
+            }
+            return false;
+        }
+
+        private void ResolveTypeName(JsonReader reader, ref Type objectType, ref JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, string qualifiedTypeName)
+        {
+            TypeNameHandling resolvedTypeNameHandling =
+                ((member != null) ? member.TypeNameHandling : null)
+                ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
+                ?? ((containerMember != null) ? containerMember.ItemTypeNameHandling : null)
+                ?? Serializer._typeNameHandling;
+
+            if (resolvedTypeNameHandling != TypeNameHandling.None)
+            {
+                string typeName;
+                string assemblyName;
+                ReflectionUtils.SplitFullyQualifiedTypeName(qualifiedTypeName, out typeName, out assemblyName);
+
+                Type specifiedType;
+                try
+                {
+                    specifiedType = Serializer._binder.BindToType(assemblyName, typeName);
+                }
+                catch (Exception ex)
+                {
+                    throw JsonSerializationException.Create(reader, "Error resolving type specified in JSON '{0}'.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName), ex);
+                }
+
+                if (specifiedType == null)
+                    throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' was not resolved.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName));
+
+                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                    TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Resolved type '{0}' to {1}.".FormatWith(CultureInfo.InvariantCulture, qualifiedTypeName, specifiedType)), null);
+
+                if (objectType != null
+#if !(NET35 || NET20 || PORTABLE40)
+                    && objectType != typeof(IDynamicMetaObjectProvider)
+#endif
+                    && !objectType.IsAssignableFrom(specifiedType))
+                    throw JsonSerializationException.Create(reader, "Type specified in JSON '{0}' is not compatible with '{1}'.".FormatWith(CultureInfo.InvariantCulture, specifiedType.AssemblyQualifiedName, objectType.AssemblyQualifiedName));
+
+                objectType = specifiedType;
+                contract = GetContractSafe(specifiedType);
+            }
+        }
+
+        private JsonArrayContract EnsureArrayContract(JsonReader reader, Type objectType, JsonContract contract)
+        {
+            if (contract == null)
+                throw JsonSerializationException.Create(reader, "Could not resolve type '{0}' to a JsonContract.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+            JsonArrayContract arrayContract = contract as JsonArrayContract;
+            if (arrayContract == null)
+                throw JsonSerializationException.Create(reader, @"Cannot deserialize the current JSON array (e.g. [1,2,3]) into type '{0}' because the type requires a {1} to deserialize correctly.
+To fix this error either change the JSON to a {1} or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
+".FormatWith(CultureInfo.InvariantCulture, objectType, GetExpectedDescription(contract)));
+
+            return arrayContract;
+        }
+
+        private void CheckedRead(JsonReader reader)
+        {
+            if (!reader.Read())
+                throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
+        }
+
+        private object CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, object existingValue, string id)
+        {
+            object value;
+
+            if (HasNoDefinedType(contract))
+                return CreateJToken(reader, contract);
+
+            JsonArrayContract arrayContract = EnsureArrayContract(reader, objectType, contract);
+
+            if (existingValue == null)
+            {
+                bool createdFromNonDefaultConstructor;
+                IList list = CreateNewList(reader, arrayContract, out createdFromNonDefaultConstructor);
+
+                if (createdFromNonDefaultConstructor)
+                {
+                    if (id != null)
+                        throw JsonSerializationException.Create(reader, "Cannot preserve reference to array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                    if (contract.OnSerializingCallbacks.Count > 0)
+                        throw JsonSerializationException.Create(reader, "Cannot call OnSerializing on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                    if (contract.OnErrorCallbacks.Count > 0)
+                        throw JsonSerializationException.Create(reader, "Cannot call OnError on an array or readonly list, or list created from a non-default constructor: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+                    if (arrayContract.ParametrizedConstructor == null && !arrayContract.IsArray)
+                        throw JsonSerializationException.Create(reader, "Cannot deserialize readonly or fixed size list: {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+                }
+
+                if (!arrayContract.IsMultidimensionalArray)
+                    PopulateList(list, reader, arrayContract, member, id);
+                else
+                    PopulateMultidimensionalArray(list, reader, arrayContract, member, id);
+
+                if (createdFromNonDefaultConstructor)
+                {
+                    if (arrayContract.IsMultidimensionalArray)
+                    {
+                        list = CollectionUtils.ToMultidimensionalArray(list, arrayContract.CollectionItemType, contract.CreatedType.GetArrayRank());
+                    }
+                    else if (arrayContract.IsArray)
+                    {
+                        Array a = Array.CreateInstance(arrayContract.CollectionItemType, list.Count);
+                        list.CopyTo(a, 0);
+                        list = a;
+                    }
+                    else
+                    {
+                        // call constructor that takes IEnumerable<T>
+                        ConstructorInfo constructor = arrayContract.ParametrizedConstructor as ConstructorInfo;
+                        if (constructor != null)
+                            return constructor.Invoke(new object[] { list });
+
+                        return arrayContract.ParametrizedConstructor.Invoke(null, new object[] { list });
+                    }
+                }
+                else if (list is IWrappedCollection)
+                {
+                    return ((IWrappedCollection)list).UnderlyingCollection;
+                }
+
+                value = list;
+            }
+            else
+            {
+                value = PopulateList((arrayContract.ShouldCreateWrapper) ? arrayContract.CreateWrapper(existingValue) : (IList)existingValue, reader, arrayContract, member, id);
+            }
+
+            return value;
+        }
+
+        private bool HasNoDefinedType(JsonContract contract)
+        {
+            return (contract == null || contract.UnderlyingType == typeof(object) || contract.ContractType == JsonContractType.Linq
+#if !(NET35 || NET20 || PORTABLE40)
+                    || contract.UnderlyingType == typeof(IDynamicMetaObjectProvider)
+#endif
+                );
+        }
+
+        private object EnsureType(JsonReader reader, object value, CultureInfo culture, JsonContract contract, Type targetType)
+        {
+            if (targetType == null)
+                return value;
+
+            Type valueType = ReflectionUtils.GetObjectType(value);
+
+            // type of value and type of target don't match
+            // attempt to convert value's type to target's type
+            if (valueType != targetType)
+            {
+                if (value == null && contract.IsNullable)
+                    return null;
+
+                try
+                {
+                    if (contract.IsConvertable)
+                    {
+                        JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
+
+                        if (contract.IsEnum)
+                        {
+                            if (value is string)
+                                return Enum.Parse(contract.NonNullableUnderlyingType, value.ToString(), true);
+                            else if (ConvertUtils.IsInteger(primitiveContract.TypeCode))
+                                return Enum.ToObject(contract.NonNullableUnderlyingType, value);
+                        }
+
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+                        if (value is BigInteger)
+                            return ConvertUtils.FromBigInteger((BigInteger)value, targetType);
+#endif
+
+                        // this won't work when converting to a custom IConvertible
+                        return Convert.ChangeType(value, contract.NonNullableUnderlyingType, culture);
+                    }
+
+                    return ConvertUtils.ConvertOrCast(value, culture, contract.NonNullableUnderlyingType);
+                }
+                catch (Exception ex)
+                {
+                    throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(value), targetType), ex);
+                }
+            }
+
+            return value;
+        }
+
+        private bool SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target)
+        {
+            object currentValue;
+            bool useExistingValue;
+            JsonContract propertyContract;
+            bool gottenCurrentValue;
+
+            if (CalculatePropertyDetails(property, ref propertyConverter, containerContract, containerProperty, reader, target, out useExistingValue, out currentValue, out propertyContract, out gottenCurrentValue))
+                return false;
+
+            object value;
+
+            if (propertyConverter != null && propertyConverter.CanRead)
+            {
+                if (!gottenCurrentValue && target != null && property.Readable)
+                    currentValue = property.ValueProvider.GetValue(target);
+
+                value = DeserializeConvertable(propertyConverter, reader, property.PropertyType, currentValue);
+            }
+            else
+            {
+                value = CreateValueInternal(reader, property.PropertyType, propertyContract, property, containerContract, containerProperty, (useExistingValue) ? currentValue : null);
+            }
+
+            // always set the value if useExistingValue is false,
+            // otherwise also set it if CreateValue returns a new value compared to the currentValue
+            // this could happen because of a JsonConverter against the type
+            if ((!useExistingValue || value != currentValue)
+                && ShouldSetPropertyValue(property, value))
+            {
+                property.ValueProvider.SetValue(target, value);
+
+                if (property.SetIsSpecified != null)
+                {
+                    if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                        TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "IsSpecified for property '{0}' on {1} set to true.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType)), null);
+
+                    property.SetIsSpecified(target, true);
+                }
+
+                return true;
+            }
+
+            // the value wasn't set be JSON was populated onto the existing value
+            return useExistingValue;
+        }
+
+        private bool CalculatePropertyDetails(JsonProperty property, ref JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, object target, out bool useExistingValue, out object currentValue, out JsonContract propertyContract, out bool gottenCurrentValue)
+        {
+            currentValue = null;
+            useExistingValue = false;
+            propertyContract = null;
+            gottenCurrentValue = false;
+
+            if (property.Ignored)
+                return true;
+
+            JsonToken tokenType = reader.TokenType;
+
+            if (property.PropertyContract == null)
+                property.PropertyContract = GetContractSafe(property.PropertyType);
+
+            ObjectCreationHandling objectCreationHandling =
+                property.ObjectCreationHandling.GetValueOrDefault(Serializer._objectCreationHandling);
+
+            if ((objectCreationHandling != ObjectCreationHandling.Replace)
+                && (tokenType == JsonToken.StartArray || tokenType == JsonToken.StartObject)
+                && property.Readable)
+            {
+                currentValue = property.ValueProvider.GetValue(target);
+                gottenCurrentValue = true;
+
+                if (currentValue != null)
+                {
+                    propertyContract = GetContractSafe(currentValue.GetType());
+
+                    useExistingValue = (!propertyContract.IsReadOnlyOrFixedSize && !propertyContract.UnderlyingType.IsValueType());
+                }
+            }
+
+            if (!property.Writable && !useExistingValue)
+                return true;
+
+            // test tokentype here because null might not be convertable to some types, e.g. ignoring null when applied to DateTime
+            if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && tokenType == JsonToken.Null)
+                return true;
+
+            // test tokentype here because default value might not be convertable to actual type, e.g. default of "" for DateTime
+            if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
+                && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate)
+                && JsonReader.IsPrimitiveToken(tokenType)
+                && MiscellaneousUtils.ValueEquals(reader.Value, property.GetResolvedDefaultValue()))
+                return true;
+
+            if (currentValue == null)
+            {
+                propertyContract = property.PropertyContract;
+            }
+            else
+            {
+                propertyContract = GetContractSafe(currentValue.GetType());
+
+                if (propertyContract != property.PropertyContract)
+                    propertyConverter = GetConverter(propertyContract, property.MemberConverter, containerContract, containerProperty);
+            }
+
+            return false;
+        }
+
+        private void AddReference(JsonReader reader, string id, object value)
+        {
+            try
+            {
+                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                    TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Read object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, id, value.GetType())), null);
+
+                Serializer.GetReferenceResolver().AddReference(this, id, value);
+            }
+            catch (Exception ex)
+            {
+                throw JsonSerializationException.Create(reader, "Error reading object reference '{0}'.".FormatWith(CultureInfo.InvariantCulture, id), ex);
+            }
+        }
+
+        private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
+        {
+            return ((value & flag) == flag);
+        }
+
+        private bool ShouldSetPropertyValue(JsonProperty property, object value)
+        {
+            if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore && value == null)
+                return false;
+
+            if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
+                && !HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate)
+                && MiscellaneousUtils.ValueEquals(value, property.GetResolvedDefaultValue()))
+                return false;
+
+            if (!property.Writable)
+                return false;
+
+            return true;
+        }
+
+        private IList CreateNewList(JsonReader reader, JsonArrayContract contract, out bool createdFromNonDefaultConstructor)
+        {
+            // some types like non-generic IEnumerable can be serialized but not deserialized
+            if (!contract.CanDeserialize)
+                throw JsonSerializationException.Create(reader, "Cannot create and populate list type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.CreatedType));
+
+            if (contract.IsReadOnlyOrFixedSize)
+            {
+                createdFromNonDefaultConstructor = true;
+                IList list = contract.CreateTemporaryCollection();
+
+                if (contract.ShouldCreateWrapper)
+                    list = contract.CreateWrapper(list);
+
+                return list;
+            }
+            else if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
+            {
+                object list = contract.DefaultCreator();
+
+                if (contract.ShouldCreateWrapper)
+                    list = contract.CreateWrapper(list);
+
+                createdFromNonDefaultConstructor = false;
+                return (IList)list;
+            }
+            else if (contract.ParametrizedConstructor != null)
+            {
+                createdFromNonDefaultConstructor = true;
+                return contract.CreateTemporaryCollection();
+            }
+            else
+            {
+                throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+            }
+        }
+
+        private IDictionary CreateNewDictionary(JsonReader reader, JsonDictionaryContract contract, out bool createdFromNonDefaultConstructor)
+        {
+            if (contract.IsReadOnlyOrFixedSize)
+            {
+                createdFromNonDefaultConstructor = true;
+                return contract.CreateTemporaryDictionary();
+            }
+            else if (contract.DefaultCreator != null && (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
+            {
+                object dictionary = contract.DefaultCreator();
+
+                if (contract.ShouldCreateWrapper)
+                    dictionary = contract.CreateWrapper(dictionary);
+
+                createdFromNonDefaultConstructor = false;
+                return (IDictionary)dictionary;
+            }
+            else if (contract.ParametrizedConstructor != null)
+            {
+                createdFromNonDefaultConstructor = true;
+                return contract.CreateTemporaryDictionary();
+            }
+            else
+            {
+                throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+            }
+        }
+
+        private void OnDeserializing(JsonReader reader, JsonContract contract, object value)
+        {
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
+
+            contract.InvokeOnDeserializing(value, Serializer._context);
+        }
+
+        private void OnDeserialized(JsonReader reader, JsonContract contract, object value)
+        {
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
+
+            contract.InvokeOnDeserialized(value, Serializer._context);
+        }
+
+        private object PopulateDictionary(IDictionary dictionary, JsonReader reader, JsonDictionaryContract contract, JsonProperty containerProperty, string id)
+        {
+            IWrappedDictionary wrappedDictionary = dictionary as IWrappedDictionary;
+            object underlyingDictionary = wrappedDictionary != null ? wrappedDictionary.UnderlyingDictionary : dictionary;
+
+            if (id != null)
+                AddReference(reader, id, underlyingDictionary);
+
+            OnDeserializing(reader, contract, underlyingDictionary);
+
+            int initialDepth = reader.Depth;
+
+            if (contract.KeyContract == null)
+                contract.KeyContract = GetContractSafe(contract.DictionaryKeyType);
+
+            if (contract.ItemContract == null)
+                contract.ItemContract = GetContractSafe(contract.DictionaryValueType);
+
+            JsonConverter dictionaryValueConverter = contract.ItemConverter ?? GetConverter(contract.ItemContract, null, contract, containerProperty);
+            PrimitiveTypeCode keyTypeCode = (contract.KeyContract is JsonPrimitiveContract) ? ((JsonPrimitiveContract)contract.KeyContract).TypeCode : PrimitiveTypeCode.Empty;
+
+            bool finished = false;
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        object keyValue = reader.Value;
+                        if (CheckPropertyName(reader, keyValue.ToString()))
+                            continue;
+
+                        try
+                        {
+                            try
+                            {
+                                DateParseHandling dateParseHandling;
+                                switch (keyTypeCode)
+                                {
+                                    case PrimitiveTypeCode.DateTime:
+                                    case PrimitiveTypeCode.DateTimeNullable:
+                                        dateParseHandling = DateParseHandling.DateTime;
+                                        break;
+#if !NET20
+                                    case PrimitiveTypeCode.DateTimeOffset:
+                                    case PrimitiveTypeCode.DateTimeOffsetNullable:
+                                        dateParseHandling = DateParseHandling.DateTimeOffset;
+                                        break;
+#endif
+                                    default:
+                                        dateParseHandling = DateParseHandling.None;
+                                        break;
+                                }
+
+                                // this is for correctly reading ISO and MS formatted dictionary keys
+                                object dt;
+                                if (dateParseHandling != DateParseHandling.None && DateTimeUtils.TryParseDateTime(keyValue.ToString(), dateParseHandling, reader.DateTimeZoneHandling, reader.DateFormatString, reader.Culture, out dt))
+                                    keyValue = dt;
+                                else
+                                    keyValue = EnsureType(reader, keyValue, CultureInfo.InvariantCulture, contract.KeyContract, contract.DictionaryKeyType);
+                            }
+                            catch (Exception ex)
+                            {
+                                throw JsonSerializationException.Create(reader, "Could not convert string '{0}' to dictionary key type '{1}'. Create a TypeConverter to convert from the string to the key type object.".FormatWith(CultureInfo.InvariantCulture, reader.Value, contract.DictionaryKeyType), ex);
+                            }
+
+                            if (!ReadForType(reader, contract.ItemContract, dictionaryValueConverter != null))
+                                throw JsonSerializationException.Create(reader, "Unexpected end when deserializing object.");
+
+                            object itemValue;
+                            if (dictionaryValueConverter != null && dictionaryValueConverter.CanRead)
+                                itemValue = DeserializeConvertable(dictionaryValueConverter, reader, contract.DictionaryValueType, null);
+                            else
+                                itemValue = CreateValueInternal(reader, contract.DictionaryValueType, contract.ItemContract, null, contract, containerProperty, null);
+
+                            dictionary[keyValue] = itemValue;
+                        }
+                        catch (Exception ex)
+                        {
+                            if (IsErrorHandled(underlyingDictionary, contract, keyValue, reader as IJsonLineInfo, reader.Path, ex))
+                                HandleError(reader, true, initialDepth);
+                            else
+                                throw;
+                        }
+                        break;
+                    case JsonToken.Comment:
+                        break;
+                    case JsonToken.EndObject:
+                        finished = true;
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
+                }
+            } while (!finished && reader.Read());
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, underlyingDictionary, "Unexpected end when deserializing object.");
+
+            OnDeserialized(reader, contract, underlyingDictionary);
+            return underlyingDictionary;
+        }
+
+        private object PopulateMultidimensionalArray(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
+        {
+            int rank = contract.UnderlyingType.GetArrayRank();
+
+            if (id != null)
+                AddReference(reader, id, list);
+
+            OnDeserializing(reader, contract, list);
+
+            JsonContract collectionItemContract = GetContractSafe(contract.CollectionItemType);
+            JsonConverter collectionItemConverter = GetConverter(collectionItemContract, null, contract, containerProperty);
+
+            int? previousErrorIndex = null;
+            Stack<IList> listStack = new Stack<IList>();
+            listStack.Push(list);
+            IList currentList = list;
+
+            bool finished = false;
+            do
+            {
+                int initialDepth = reader.Depth;
+
+                if (listStack.Count == rank)
+                {
+                    try
+                    {
+                        if (ReadForType(reader, collectionItemContract, collectionItemConverter != null))
+                        {
+                            switch (reader.TokenType)
+                            {
+                                case JsonToken.EndArray:
+                                    listStack.Pop();
+                                    currentList = listStack.Peek();
+                                    previousErrorIndex = null;
+                                    break;
+                                case JsonToken.Comment:
+                                    break;
+                                default:
+                                    object value;
+
+                                    if (collectionItemConverter != null && collectionItemConverter.CanRead)
+                                        value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null);
+                                    else
+                                        value = CreateValueInternal(reader, contract.CollectionItemType, collectionItemContract, null, contract, containerProperty, null);
+
+                                    currentList.Add(value);
+                                    break;
+                            }
+                        }
+                        else
+                        {
+                            break;
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        JsonPosition errorPosition = reader.GetPosition(initialDepth);
+
+                        if (IsErrorHandled(list, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex))
+                        {
+                            HandleError(reader, true, initialDepth);
+
+                            if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position)
+                            {
+                                // reader index has not moved since previous error handling
+                                // break out of reading array to prevent infinite loop
+                                throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
+                            }
+                            else
+                            {
+                                previousErrorIndex = errorPosition.Position;
+                            }
+                        }
+                        else
+                        {
+                            throw;
+                        }
+                    }
+                }
+                else
+                {
+                    if (reader.Read())
+                    {
+                        switch (reader.TokenType)
+                        {
+                            case JsonToken.StartArray:
+                                IList newList = new List<object>();
+                                currentList.Add(newList);
+                                listStack.Push(newList);
+                                currentList = newList;
+                                break;
+                            case JsonToken.EndArray:
+                                listStack.Pop();
+
+                                if (listStack.Count > 0)
+                                {
+                                    currentList = listStack.Peek();
+                                }
+                                else
+                                {
+                                    finished = true;
+                                }
+                                break;
+                            case JsonToken.Comment:
+                                break;
+                            default:
+                                throw JsonSerializationException.Create(reader, "Unexpected token when deserializing multidimensional array: " + reader.TokenType);
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+            } while (!finished);
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, list, "Unexpected end when deserializing array.");
+
+            OnDeserialized(reader, contract, list);
+            return list;
+        }
+
+        private void ThrowUnexpectedEndException(JsonReader reader, JsonContract contract, object currentObject, string message)
+        {
+            try
+            {
+                throw JsonSerializationException.Create(reader, message);
+            }
+            catch (Exception ex)
+            {
+                if (IsErrorHandled(currentObject, contract, null, reader as IJsonLineInfo, reader.Path, ex))
+                    HandleError(reader, false, 0);
+                else
+                    throw;
+            }
+        }
+
+        private object PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, string id)
+        {
+            IWrappedCollection wrappedCollection = list as IWrappedCollection;
+            object underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : list;
+
+            if (id != null)
+                AddReference(reader, id, underlyingList);
+
+            // can't populate an existing array
+            if (list.IsFixedSize)
+            {
+                reader.Skip();
+                return underlyingList;
+            }
+
+            OnDeserializing(reader, contract, underlyingList);
+
+            int initialDepth = reader.Depth;
+
+            if (contract.ItemContract == null)
+                contract.ItemContract = GetContractSafe(contract.CollectionItemType);
+
+            JsonConverter collectionItemConverter = GetConverter(contract.ItemContract, null, contract, containerProperty);
+
+            int? previousErrorIndex = null;
+
+            bool finished = false;
+            do
+            {
+                try
+                {
+                    if (ReadForType(reader, contract.ItemContract, collectionItemConverter != null))
+                    {
+                        switch (reader.TokenType)
+                        {
+                            case JsonToken.EndArray:
+                                finished = true;
+                                break;
+                            case JsonToken.Comment:
+                                break;
+                            default:
+                                object value;
+
+                                if (collectionItemConverter != null && collectionItemConverter.CanRead)
+                                    value = DeserializeConvertable(collectionItemConverter, reader, contract.CollectionItemType, null);
+                                else
+                                    value = CreateValueInternal(reader, contract.CollectionItemType, contract.ItemContract, null, contract, containerProperty, null);
+
+                                list.Add(value);
+                                break;
+                        }
+                    }
+                    else
+                    {
+                        break;
+                    }
+                }
+                catch (Exception ex)
+                {
+                    JsonPosition errorPosition = reader.GetPosition(initialDepth);
+
+                    if (IsErrorHandled(underlyingList, contract, errorPosition.Position, reader as IJsonLineInfo, reader.Path, ex))
+                    {
+                        HandleError(reader, true, initialDepth);
+
+                        if (previousErrorIndex != null && previousErrorIndex == errorPosition.Position)
+                        {
+                            // reader index has not moved since previous error handling
+                            // break out of reading array to prevent infinite loop
+                            throw JsonSerializationException.Create(reader, "Infinite loop detected from error handling.", ex);
+                        }
+                        else
+                        {
+                            previousErrorIndex = errorPosition.Position;
+                        }
+                    }
+                    else
+                    {
+                        throw;
+                    }
+                }
+            } while (!finished);
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, underlyingList, "Unexpected end when deserializing array.");
+
+            OnDeserialized(reader, contract, underlyingList);
+            return underlyingList;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        private object CreateISerializable(JsonReader reader, JsonISerializableContract contract, JsonProperty member, string id)
+        {
+            Type objectType = contract.UnderlyingType;
+
+            if (!JsonTypeReflector.FullyTrusted)
+            {
+                throw JsonSerializationException.Create(reader, @"Type '{0}' implements ISerializable but cannot be deserialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data.
+To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.
+".FormatWith(CultureInfo.InvariantCulture, objectType));
+            }
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using ISerializable constructor.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
+
+            SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, GetFormatterConverter());
+
+            bool finished = false;
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        string memberName = reader.Value.ToString();
+                        if (!reader.Read())
+                            throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+                        if (reader.TokenType == JsonToken.StartObject)
+                        {
+                            // this will read any potential type names embedded in json
+                            object o = CreateObject(reader, null, null, null, contract, member, null);
+                            serializationInfo.AddValue(memberName, o);
+                        }
+                        else
+                        {
+                            serializationInfo.AddValue(memberName, JToken.ReadFrom(reader));
+                        }
+                        break;
+                    case JsonToken.Comment:
+                        break;
+                    case JsonToken.EndObject:
+                        finished = true;
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
+                }
+            } while (!finished && reader.Read());
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, serializationInfo, "Unexpected end when deserializing object.");
+
+            if (contract.ISerializableCreator == null)
+                throw JsonSerializationException.Create(reader, "ISerializable type '{0}' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present.".FormatWith(CultureInfo.InvariantCulture, objectType));
+
+            object createdObject = contract.ISerializableCreator(serializationInfo, Serializer._context);
+
+            if (id != null)
+                AddReference(reader, id, createdObject);
+
+            // these are together because OnDeserializing takes an object but for an ISerializable the object is fully created in the constructor
+            OnDeserializing(reader, contract, createdObject);
+            OnDeserialized(reader, contract, createdObject);
+
+            return createdObject;
+        }
+#endif
+
+#if !(NET35 || NET20 || PORTABLE40)
+        private object CreateDynamic(JsonReader reader, JsonDynamicContract contract, JsonProperty member, string id)
+        {
+            IDynamicMetaObjectProvider newObject;
+
+            if (!contract.IsInstantiable)
+                throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+            if (contract.DefaultCreator != null &&
+                (!contract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor))
+                newObject = (IDynamicMetaObjectProvider)contract.DefaultCreator();
+            else
+                throw JsonSerializationException.Create(reader, "Unable to find a default constructor to use for type {0}.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType));
+
+            if (id != null)
+                AddReference(reader, id, newObject);
+
+            OnDeserializing(reader, contract, newObject);
+
+            int initialDepth = reader.Depth;
+
+            bool finished = false;
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        string memberName = reader.Value.ToString();
+
+                        try
+                        {
+                            if (!reader.Read())
+                                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+                            // first attempt to find a settable property, otherwise fall back to a dynamic set without type
+                            JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);
+
+                            if (property != null && property.Writable && !property.Ignored)
+                            {
+                                if (property.PropertyContract == null)
+                                    property.PropertyContract = GetContractSafe(property.PropertyType);
+
+                                JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, null, null);
+
+                                if (!SetPropertyValue(property, propertyConverter, null, member, reader, newObject))
+                                    reader.Skip();
+                            }
+                            else
+                            {
+                                Type t = (JsonReader.IsPrimitiveToken(reader.TokenType)) ? reader.ValueType : typeof(IDynamicMetaObjectProvider);
+
+                                JsonContract dynamicMemberContract = GetContractSafe(t);
+                                JsonConverter dynamicMemberConverter = GetConverter(dynamicMemberContract, null, null, member);
+
+                                object value;
+                                if (dynamicMemberConverter != null && dynamicMemberConverter.CanRead)
+                                    value = DeserializeConvertable(dynamicMemberConverter, reader, t, null);
+                                else
+                                    value = CreateValueInternal(reader, t, dynamicMemberContract, null, null, member, null);
+
+                                contract.TrySetMember(newObject, memberName, value);
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, ex))
+                                HandleError(reader, true, initialDepth);
+                            else
+                                throw;
+                        }
+                        break;
+                    case JsonToken.EndObject:
+                        finished = true;
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
+                }
+            } while (!finished && reader.Read());
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");
+
+            OnDeserialized(reader, contract, newObject);
+
+            return newObject;
+        }
+#endif
+
+        private object CreateObjectFromNonDefaultConstructor(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ConstructorInfo constructorInfo, string id)
+        {
+            ValidationUtils.ArgumentNotNull(constructorInfo, "constructorInfo");
+
+            // only need to keep a track of properies presence if they are required or a value should be defaulted if missing
+            Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate))
+                ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None)
+                : null;
+
+            Type objectType = contract.UnderlyingType;
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Deserializing {0} using a non-default constructor '{1}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType, constructorInfo)), null);
+
+            IDictionary<string, object> extensionData;
+            IDictionary<JsonProperty, object> propertyValues = ResolvePropertyAndConstructorValues(contract, containerProperty, reader, objectType, out extensionData);
+
+            IDictionary<ParameterInfo, object> constructorParameters = constructorInfo.GetParameters().ToDictionary(p => p, p => (object)null);
+            IDictionary<JsonProperty, object> remainingPropertyValues = new Dictionary<JsonProperty, object>();
+
+            foreach (KeyValuePair<JsonProperty, object> propertyValue in propertyValues)
+            {
+                ParameterInfo matchingConstructorParameter = constructorParameters.ForgivingCaseSensitiveFind(kv => kv.Key.Name, propertyValue.Key.UnderlyingName).Key;
+                if (matchingConstructorParameter != null)
+                    constructorParameters[matchingConstructorParameter] = propertyValue.Value;
+                else
+                    remainingPropertyValues.Add(propertyValue);
+
+                if (propertiesPresence != null)
+                {
+                    // map from constructor property to normal property
+                    var property = propertiesPresence.Keys.FirstOrDefault(p => p.PropertyName == propertyValue.Key.PropertyName);
+                    if (property != null)
+                        propertiesPresence[property] = (propertyValue.Value == null) ? PropertyPresence.Null : PropertyPresence.Value;
+                }
+            }
+
+            object createdObject = constructorInfo.Invoke(constructorParameters.Values.ToArray());
+
+            if (id != null)
+                AddReference(reader, id, createdObject);
+
+            OnDeserializing(reader, contract, createdObject);
+
+            // go through unused values and set the newly created object's properties
+            foreach (KeyValuePair<JsonProperty, object> remainingPropertyValue in remainingPropertyValues)
+            {
+                JsonProperty property = remainingPropertyValue.Key;
+                object value = remainingPropertyValue.Value;
+
+                if (ShouldSetPropertyValue(property, value))
+                {
+                    property.ValueProvider.SetValue(createdObject, value);
+                }
+                else if (!property.Writable && value != null)
+                {
+                    // handle readonly collection/dictionary properties
+                    JsonContract propertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);
+
+                    if (propertyContract.ContractType == JsonContractType.Array)
+                    {
+                        JsonArrayContract propertyArrayContract = (JsonArrayContract)propertyContract;
+
+                        object createdObjectCollection = property.ValueProvider.GetValue(createdObject);
+                        if (createdObjectCollection != null)
+                        {
+                            IWrappedCollection createdObjectCollectionWrapper = propertyArrayContract.CreateWrapper(createdObjectCollection);
+                            IWrappedCollection newValues = propertyArrayContract.CreateWrapper(value);
+
+                            foreach (object newValue in newValues)
+                            {
+                                createdObjectCollectionWrapper.Add(newValue);
+                            }
+                        }
+                    }
+                    else if (propertyContract.ContractType == JsonContractType.Dictionary)
+                    {
+                        JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)propertyContract;
+
+                        object createdObjectDictionary = property.ValueProvider.GetValue(createdObject);
+                        if (createdObjectDictionary != null)
+                        {
+                            IDictionary targetDictionary = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(createdObjectDictionary) : (IDictionary)createdObjectDictionary;
+                            IDictionary newValues = (dictionaryContract.ShouldCreateWrapper) ? dictionaryContract.CreateWrapper(value) : (IDictionary)value;
+
+                            foreach (DictionaryEntry newValue in newValues)
+                            {
+                                targetDictionary.Add(newValue.Key, newValue.Value);
+                            }
+                        }
+                    }
+                }
+            }
+
+            if (extensionData != null)
+            {
+                foreach (KeyValuePair<string, object> e in extensionData)
+                {
+                    contract.ExtensionDataSetter(createdObject, e.Key, e.Value);
+                }
+            }
+
+            EndObject(createdObject, reader, contract, reader.Depth, propertiesPresence);
+
+            OnDeserialized(reader, contract, createdObject);
+            return createdObject;
+        }
+
+        private object DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, object existingValue)
+        {
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Started deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null);
+
+            object value = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer());
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Finished deserializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, objectType, converter.GetType())), null);
+
+            return value;
+        }
+
+        private IDictionary<JsonProperty, object> ResolvePropertyAndConstructorValues(JsonObjectContract contract, JsonProperty containerProperty, JsonReader reader, Type objectType, out IDictionary<string, object> extensionData)
+        {
+            extensionData = (contract.ExtensionDataSetter != null) ? new Dictionary<string, object>() : null;
+
+            IDictionary<JsonProperty, object> propertyValues = new Dictionary<JsonProperty, object>();
+            bool exit = false;
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                        string memberName = reader.Value.ToString();
+
+                        // attempt exact case match first
+                        // then try match ignoring case
+                        JsonProperty property = contract.ConstructorParameters.GetClosestMatchProperty(memberName) ??
+                                                contract.Properties.GetClosestMatchProperty(memberName);
+
+                        if (property != null)
+                        {
+                            if (property.PropertyContract == null)
+                                property.PropertyContract = GetContractSafe(property.PropertyType);
+
+                            JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, containerProperty);
+
+                            if (!ReadForType(reader, property.PropertyContract, propertyConverter != null))
+                                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+                            if (!property.Ignored)
+                            {
+                                if (property.PropertyContract == null)
+                                    property.PropertyContract = GetContractSafe(property.PropertyType);
+
+                                object propertyValue;
+                                if (propertyConverter != null && propertyConverter.CanRead)
+                                    propertyValue = DeserializeConvertable(propertyConverter, reader, property.PropertyType, null);
+                                else
+                                    propertyValue = CreateValueInternal(reader, property.PropertyType, property.PropertyContract, property, contract, containerProperty, null);
+
+                                propertyValues[property] = propertyValue;
+                                continue;
+                            }
+                        }
+                        else
+                        {
+                            if (!reader.Read())
+                                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+                            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}.".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);
+
+                            if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
+                                throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, objectType.Name));
+                        }
+
+                        if (extensionData != null)
+                        {
+                            object value = CreateValueInternal(reader, null, null, null, contract, containerProperty, null);
+                            extensionData[memberName] = value;
+                        }
+                        else
+                        {
+                            reader.Skip();
+                        }
+                        break;
+                    case JsonToken.Comment:
+                        break;
+                    case JsonToken.EndObject:
+                        exit = true;
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
+                }
+            } while (!exit && reader.Read());
+
+            return propertyValues;
+        }
+
+        private bool ReadForType(JsonReader reader, JsonContract contract, bool hasConverter)
+        {
+            // don't read properties with converters as a specific value
+            // the value might be a string which will then get converted which will error if read as date for example
+            if (hasConverter)
+                return reader.Read();
+
+            ReadType t = (contract != null) ? contract.InternalReadType : ReadType.Read;
+
+            switch (t)
+            {
+                case ReadType.Read:
+                    do
+                    {
+                        if (!reader.Read())
+                            return false;
+                    } while (reader.TokenType == JsonToken.Comment);
+
+                    return true;
+                case ReadType.ReadAsInt32:
+                    reader.ReadAsInt32();
+                    break;
+                case ReadType.ReadAsDecimal:
+                    reader.ReadAsDecimal();
+                    break;
+                case ReadType.ReadAsBytes:
+                    reader.ReadAsBytes();
+                    break;
+                case ReadType.ReadAsString:
+                    reader.ReadAsString();
+                    break;
+                case ReadType.ReadAsDateTime:
+                    reader.ReadAsDateTime();
+                    break;
+#if !NET20
+                case ReadType.ReadAsDateTimeOffset:
+                    reader.ReadAsDateTimeOffset();
+                    break;
+#endif
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+
+            return (reader.TokenType != JsonToken.None);
+        }
+
+        public object CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty containerMember, JsonProperty containerProperty, string id, out bool createdFromNonDefaultConstructor)
+        {
+            object newObject = null;
+
+            if (!objectContract.IsInstantiable)
+                throw JsonSerializationException.Create(reader, "Could not create an instance of type {0}. Type is an interface or abstract class and cannot be instantiated.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));
+
+            if (objectContract.OverrideConstructor != null)
+            {
+                if (objectContract.OverrideConstructor.GetParameters().Length > 0)
+                {
+                    createdFromNonDefaultConstructor = true;
+                    return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.OverrideConstructor, id);
+                }
+
+                newObject = objectContract.OverrideConstructor.Invoke(null);
+            }
+            else if (objectContract.DefaultCreator != null &&
+                     (!objectContract.DefaultCreatorNonPublic || Serializer._constructorHandling == ConstructorHandling.AllowNonPublicDefaultConstructor || objectContract.ParametrizedConstructor == null))
+            {
+                // use the default constructor if it is...
+                // public
+                // non-public and the user has change constructor handling settings
+                // non-public and there is no other constructor
+                newObject = objectContract.DefaultCreator();
+            }
+            else if (objectContract.ParametrizedConstructor != null)
+            {
+                createdFromNonDefaultConstructor = true;
+                return CreateObjectFromNonDefaultConstructor(reader, objectContract, containerMember, objectContract.ParametrizedConstructor, id);
+            }
+
+            if (newObject == null)
+                throw JsonSerializationException.Create(reader, "Unable to find a constructor to use for type {0}. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.".FormatWith(CultureInfo.InvariantCulture, objectContract.UnderlyingType));
+
+            createdFromNonDefaultConstructor = false;
+            return newObject;
+        }
+
+        private object PopulateObject(object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, string id)
+        {
+            OnDeserializing(reader, contract, newObject);
+
+            // only need to keep a track of properies presence if they are required or a value should be defaulted if missing
+            Dictionary<JsonProperty, PropertyPresence> propertiesPresence = (contract.HasRequiredOrDefaultValueProperties || HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Populate))
+                ? contract.Properties.ToDictionary(m => m, m => PropertyPresence.None)
+                : null;
+
+            if (id != null)
+                AddReference(reader, id, newObject);
+
+            int initialDepth = reader.Depth;
+
+            bool finished = false;
+            do
+            {
+                switch (reader.TokenType)
+                {
+                    case JsonToken.PropertyName:
+                    {
+                        string memberName = reader.Value.ToString();
+
+                        if (CheckPropertyName(reader, memberName))
+                            continue;
+
+                        try
+                        {
+                            // attempt exact case match first
+                            // then try match ignoring case
+                            JsonProperty property = contract.Properties.GetClosestMatchProperty(memberName);
+
+                            if (property == null)
+                            {
+                                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                                    TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(reader as IJsonLineInfo, reader.Path, "Could not find member '{0}' on {1}".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType)), null);
+
+                                if (Serializer._missingMemberHandling == MissingMemberHandling.Error)
+                                    throw JsonSerializationException.Create(reader, "Could not find member '{0}' on object of type '{1}'".FormatWith(CultureInfo.InvariantCulture, memberName, contract.UnderlyingType.Name));
+
+                                if (!reader.Read())
+                                    break;
+
+                                SetExtensionData(contract, member, reader, memberName, newObject);
+                                continue;
+                            }
+
+                            if (property.PropertyContract == null)
+                                property.PropertyContract = GetContractSafe(property.PropertyType);
+
+                            JsonConverter propertyConverter = GetConverter(property.PropertyContract, property.MemberConverter, contract, member);
+
+                            if (!ReadForType(reader, property.PropertyContract, propertyConverter != null))
+                                throw JsonSerializationException.Create(reader, "Unexpected end when setting {0}'s value.".FormatWith(CultureInfo.InvariantCulture, memberName));
+
+                            SetPropertyPresence(reader, property, propertiesPresence);
+
+                            // set extension data if property is ignored or readonly
+                            if (!SetPropertyValue(property, propertyConverter, contract, member, reader, newObject))
+                                SetExtensionData(contract, member, reader, memberName, newObject);
+                        }
+                        catch (Exception ex)
+                        {
+                            if (IsErrorHandled(newObject, contract, memberName, reader as IJsonLineInfo, reader.Path, ex))
+                                HandleError(reader, true, initialDepth);
+                            else
+                                throw;
+                        }
+                        break;
+                    }
+                    case JsonToken.EndObject:
+                        finished = true;
+                        break;
+                    case JsonToken.Comment:
+                        // ignore
+                        break;
+                    default:
+                        throw JsonSerializationException.Create(reader, "Unexpected token when deserializing object: " + reader.TokenType);
+                }
+            } while (!finished && reader.Read());
+
+            if (!finished)
+                ThrowUnexpectedEndException(reader, contract, newObject, "Unexpected end when deserializing object.");
+
+            EndObject(newObject, reader, contract, initialDepth, propertiesPresence);
+
+            OnDeserialized(reader, contract, newObject);
+            return newObject;
+        }
+
+        private bool CheckPropertyName(JsonReader reader, string memberName)
+        {
+            if (Serializer.MetadataPropertyHandling == MetadataPropertyHandling.ReadAhead)
+            {
+                switch (memberName)
+                {
+                    case JsonTypeReflector.IdPropertyName:
+                    case JsonTypeReflector.RefPropertyName:
+                    case JsonTypeReflector.TypePropertyName:
+                    case JsonTypeReflector.ArrayValuesPropertyName:
+                        reader.Skip();
+                        return true;
+                }
+            }
+            return false;
+        }
+
+        private void SetExtensionData(JsonObjectContract contract, JsonProperty member, JsonReader reader, string memberName, object o)
+        {
+            if (contract.ExtensionDataSetter != null)
+            {
+                try
+                {
+                    object value = CreateValueInternal(reader, null, null, null, contract, member, null);
+
+                    contract.ExtensionDataSetter(o, memberName, value);
+                }
+                catch (Exception ex)
+                {
+                    throw JsonSerializationException.Create(reader, "Error setting value in extension data for type '{0}'.".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType), ex);
+                }
+            }
+            else
+            {
+                reader.Skip();
+            }
+        }
+
+        private void EndObject(object newObject, JsonReader reader, JsonObjectContract contract, int initialDepth, Dictionary<JsonProperty, PropertyPresence> propertiesPresence)
+        {
+            if (propertiesPresence != null)
+            {
+                foreach (KeyValuePair<JsonProperty, PropertyPresence> propertyPresence in propertiesPresence)
+                {
+                    JsonProperty property = propertyPresence.Key;
+                    PropertyPresence presence = propertyPresence.Value;
+
+                    if (presence == PropertyPresence.None || presence == PropertyPresence.Null)
+                    {
+                        try
+                        {
+                            Required resolvedRequired = property._required ?? contract.ItemRequired ?? Required.Default;
+
+                            switch (presence)
+                            {
+                                case PropertyPresence.None:
+                                    if (resolvedRequired == Required.AllowNull || resolvedRequired == Required.Always)
+                                        throw JsonSerializationException.Create(reader, "Required property '{0}' not found in JSON.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
+
+                                    if (property.PropertyContract == null)
+                                        property.PropertyContract = GetContractSafe(property.PropertyType);
+
+                                    if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Populate) && property.Writable)
+                                        property.ValueProvider.SetValue(newObject, EnsureType(reader, property.GetResolvedDefaultValue(), CultureInfo.InvariantCulture, property.PropertyContract, property.PropertyType));
+                                    break;
+                                case PropertyPresence.Null:
+                                    if (resolvedRequired == Required.Always)
+                                        throw JsonSerializationException.Create(reader, "Required property '{0}' expects a value but got null.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName));
+                                    break;
+                            }
+                        }
+                        catch (Exception ex)
+                        {
+                            if (IsErrorHandled(newObject, contract, property.PropertyName, reader as IJsonLineInfo, reader.Path, ex))
+                                HandleError(reader, true, initialDepth);
+                            else
+                                throw;
+                        }
+                    }
+                }
+            }
+        }
+
+        private void SetPropertyPresence(JsonReader reader, JsonProperty property, Dictionary<JsonProperty, PropertyPresence> requiredProperties)
+        {
+            if (property != null && requiredProperties != null)
+            {
+                requiredProperties[property] = (reader.TokenType == JsonToken.Null || reader.TokenType == JsonToken.Undefined)
+                    ? PropertyPresence.Null
+                    : PropertyPresence.Value;
+            }
+        }
+
+        private void HandleError(JsonReader reader, bool readPastError, int initialDepth)
+        {
+            ClearErrorContext();
+
+            if (readPastError)
+            {
+                reader.Skip();
+
+                while (reader.Depth > (initialDepth + 1))
+                {
+                    if (!reader.Read())
+                        break;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs b/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs
new file mode 100644
index 0000000..1211463
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonSerializerInternalWriter.cs
@@ -0,0 +1,1031 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+#if !(NET35 || NET20 || PORTABLE40)
+using System.Dynamic;
+#endif
+using System.Diagnostics;
+using System.Globalization;
+using System.IO;
+using System.Security;
+using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Utilities;
+using System.Runtime.Serialization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class JsonSerializerInternalWriter : JsonSerializerInternalBase
+    {
+        private JsonContract _rootContract;
+        private int _rootLevel;
+        private readonly List<object> _serializeStack = new List<object>();
+        private JsonSerializerProxy _internalSerializer;
+
+        public JsonSerializerInternalWriter(JsonSerializer serializer)
+            : base(serializer)
+        {
+        }
+
+        public void Serialize(JsonWriter jsonWriter, object value, Type objectType)
+        {
+            if (jsonWriter == null)
+                throw new ArgumentNullException("jsonWriter");
+
+            _rootContract = (objectType != null) ? Serializer._contractResolver.ResolveContract(objectType) : null;
+            _rootLevel = _serializeStack.Count + 1;
+
+            JsonContract contract = GetContractSafe(value);
+
+            try
+            {
+                SerializeValue(jsonWriter, value, contract, null, null, null);
+            }
+            catch (Exception ex)
+            {
+                if (IsErrorHandled(null, contract, null, null, jsonWriter.Path, ex))
+                {
+                    HandleError(jsonWriter, 0);
+                }
+                else
+                {
+                    // clear context in case serializer is being used inside a converter
+                    // if the converter wraps the error then not clearing the context will cause this error:
+                    // "Current error context error is different to requested error."
+                    ClearErrorContext();
+                    throw;
+                }
+            }
+            finally
+            {
+                // clear root contract to ensure that if level was > 1 then it won't
+                // accidently be used for non root values
+                _rootContract = null;
+            }
+        }
+
+        private JsonSerializerProxy GetInternalSerializer()
+        {
+            if (_internalSerializer == null)
+                _internalSerializer = new JsonSerializerProxy(this);
+
+            return _internalSerializer;
+        }
+
+        private JsonContract GetContractSafe(object value)
+        {
+            if (value == null)
+                return null;
+
+            return Serializer._contractResolver.ResolveContract(value.GetType());
+        }
+
+        private void SerializePrimitive(JsonWriter writer, object value, JsonPrimitiveContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            if (contract.TypeCode == PrimitiveTypeCode.Bytes)
+            {
+                // if type name handling is enabled then wrap the base64 byte string in an object with the type name
+                bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Objects, contract, member, containerContract, containerProperty);
+                if (includeTypeDetails)
+                {
+                    writer.WriteStartObject();
+                    WriteTypeProperty(writer, contract.CreatedType);
+                    writer.WritePropertyName(JsonTypeReflector.ValuePropertyName, false);
+
+                    JsonWriter.WriteValue(writer, contract.TypeCode, value);
+
+                    writer.WriteEndObject();
+                    return;
+                }
+            }
+
+            JsonWriter.WriteValue(writer, contract.TypeCode, value);
+        }
+
+        private void SerializeValue(JsonWriter writer, object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            if (value == null)
+            {
+                writer.WriteNull();
+                return;
+            }
+
+            JsonConverter converter;
+            if ((((converter = (member != null) ? member.Converter : null) != null)
+                 || ((converter = (containerProperty != null) ? containerProperty.ItemConverter : null) != null)
+                 || ((converter = (containerContract != null) ? containerContract.ItemConverter : null) != null)
+                 || ((converter = valueContract.Converter) != null)
+                 || ((converter = Serializer.GetMatchingConverter(valueContract.UnderlyingType)) != null)
+                 || ((converter = valueContract.InternalConverter) != null))
+                && converter.CanWrite)
+            {
+                SerializeConvertable(writer, converter, value, valueContract, containerContract, containerProperty);
+                return;
+            }
+
+            switch (valueContract.ContractType)
+            {
+                case JsonContractType.Object:
+                    SerializeObject(writer, value, (JsonObjectContract)valueContract, member, containerContract, containerProperty);
+                    break;
+                case JsonContractType.Array:
+                    JsonArrayContract arrayContract = (JsonArrayContract)valueContract;
+                    if (!arrayContract.IsMultidimensionalArray)
+                        SerializeList(writer, (IEnumerable)value, arrayContract, member, containerContract, containerProperty);
+                    else
+                        SerializeMultidimensionalArray(writer, (Array)value, arrayContract, member, containerContract, containerProperty);
+                    break;
+                case JsonContractType.Primitive:
+                    SerializePrimitive(writer, value, (JsonPrimitiveContract)valueContract, member, containerContract, containerProperty);
+                    break;
+                case JsonContractType.String:
+                    SerializeString(writer, value, (JsonStringContract)valueContract);
+                    break;
+                case JsonContractType.Dictionary:
+                    JsonDictionaryContract dictionaryContract = (JsonDictionaryContract)valueContract;
+                    SerializeDictionary(writer, (value is IDictionary) ? (IDictionary)value : dictionaryContract.CreateWrapper(value), dictionaryContract, member, containerContract, containerProperty);
+                    break;
+#if !(NET35 || NET20 || PORTABLE40)
+                case JsonContractType.Dynamic:
+                    SerializeDynamic(writer, (IDynamicMetaObjectProvider)value, (JsonDynamicContract)valueContract, member, containerContract, containerProperty);
+                    break;
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                case JsonContractType.Serializable:
+                    SerializeISerializable(writer, (ISerializable)value, (JsonISerializableContract)valueContract, member, containerContract, containerProperty);
+                    break;
+#endif
+                case JsonContractType.Linq:
+                    ((JToken)value).WriteTo(writer, Serializer.Converters.ToArray());
+                    break;
+            }
+        }
+
+        private bool? ResolveIsReference(JsonContract contract, JsonProperty property, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            bool? isReference = null;
+
+            // value could be coming from a dictionary or array and not have a property
+            if (property != null)
+                isReference = property.IsReference;
+
+            if (isReference == null && containerProperty != null)
+                isReference = containerProperty.ItemIsReference;
+
+            if (isReference == null && collectionContract != null)
+                isReference = collectionContract.ItemIsReference;
+
+            if (isReference == null)
+                isReference = contract.IsReference;
+
+            return isReference;
+        }
+
+        private bool ShouldWriteReference(object value, JsonProperty property, JsonContract valueContract, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            if (value == null)
+                return false;
+            if (valueContract.ContractType == JsonContractType.Primitive || valueContract.ContractType == JsonContractType.String)
+                return false;
+
+            bool? isReference = ResolveIsReference(valueContract, property, collectionContract, containerProperty);
+
+            if (isReference == null)
+            {
+                if (valueContract.ContractType == JsonContractType.Array)
+                    isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
+                else
+                    isReference = HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects);
+            }
+
+            if (!isReference.Value)
+                return false;
+
+            return Serializer.GetReferenceResolver().IsReferenced(this, value);
+        }
+
+        private bool ShouldWriteProperty(object memberValue, JsonProperty property)
+        {
+            if (property.NullValueHandling.GetValueOrDefault(Serializer._nullValueHandling) == NullValueHandling.Ignore &&
+                memberValue == null)
+                return false;
+
+            if (HasFlag(property.DefaultValueHandling.GetValueOrDefault(Serializer._defaultValueHandling), DefaultValueHandling.Ignore)
+                && MiscellaneousUtils.ValueEquals(memberValue, property.GetResolvedDefaultValue()))
+                return false;
+
+            return true;
+        }
+
+        private bool CheckForCircularReference(JsonWriter writer, object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            if (value == null || contract.ContractType == JsonContractType.Primitive || contract.ContractType == JsonContractType.String)
+                return true;
+
+            ReferenceLoopHandling? referenceLoopHandling = null;
+
+            if (property != null)
+                referenceLoopHandling = property.ReferenceLoopHandling;
+
+            if (referenceLoopHandling == null && containerProperty != null)
+                referenceLoopHandling = containerProperty.ItemReferenceLoopHandling;
+
+            if (referenceLoopHandling == null && containerContract != null)
+                referenceLoopHandling = containerContract.ItemReferenceLoopHandling;
+
+            if (_serializeStack.IndexOf(value) != -1)
+            {
+                string message = "Self referencing loop detected";
+                if (property != null)
+                    message += " for property '{0}'".FormatWith(CultureInfo.InvariantCulture, property.PropertyName);
+                message += " with type '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType());
+
+                switch (referenceLoopHandling.GetValueOrDefault(Serializer._referenceLoopHandling))
+                {
+                    case ReferenceLoopHandling.Error:
+                        throw JsonSerializationException.Create(null, writer.ContainerPath, message, null);
+                    case ReferenceLoopHandling.Ignore:
+                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                            TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Skipping serializing self referenced value."), null);
+
+                        return false;
+                    case ReferenceLoopHandling.Serialize:
+                        if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                            TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, message + ". Serializing self referenced value."), null);
+
+                        return true;
+                }
+            }
+
+            return true;
+        }
+
+        private void WriteReference(JsonWriter writer, object value)
+        {
+            string reference = GetReference(writer, value);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference to Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, value.GetType())), null);
+
+            writer.WriteStartObject();
+            writer.WritePropertyName(JsonTypeReflector.RefPropertyName, false);
+            writer.WriteValue(reference);
+            writer.WriteEndObject();
+        }
+
+        private string GetReference(JsonWriter writer, object value)
+        {
+            try
+            {
+                string reference = Serializer.GetReferenceResolver().GetReference(this, value);
+
+                return reference;
+            }
+            catch (Exception ex)
+            {
+                throw JsonSerializationException.Create(null, writer.ContainerPath, "Error writing object reference for '{0}'.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), ex);
+            }
+        }
+
+        internal static bool TryConvertToString(object value, Type type, out string s)
+        {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            TypeConverter converter = ConvertUtils.GetConverter(type);
+
+            // use the objectType's TypeConverter if it has one and can convert to a string
+            if (converter != null
+                && !(converter is ComponentConverter)
+                && converter.GetType() != typeof(TypeConverter))
+            {
+                if (converter.CanConvertTo(typeof(string)))
+                {
+                    s = converter.ConvertToInvariantString(value);
+                    return true;
+                }
+            }
+#endif
+
+#if NETFX_CORE || PORTABLE
+      if (value is Guid || value is Uri || value is TimeSpan)
+      {
+        s = value.ToString();
+        return true;
+      }
+#endif
+
+            if (value is Type)
+            {
+                s = ((Type)value).AssemblyQualifiedName;
+                return true;
+            }
+
+            s = null;
+            return false;
+        }
+
+        private void SerializeString(JsonWriter writer, object value, JsonStringContract contract)
+        {
+            OnSerializing(writer, contract, value);
+
+            string s;
+            TryConvertToString(value, contract.UnderlyingType, out s);
+            writer.WriteValue(s);
+
+            OnSerialized(writer, contract, value);
+        }
+
+        private void OnSerializing(JsonWriter writer, JsonContract contract, object value)
+        {
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
+
+            contract.InvokeOnSerializing(value, Serializer._context);
+        }
+
+        private void OnSerialized(JsonWriter writer, JsonContract contract, object value)
+        {
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0}".FormatWith(CultureInfo.InvariantCulture, contract.UnderlyingType)), null);
+
+            contract.InvokeOnSerialized(value, Serializer._context);
+        }
+
+        private void SerializeObject(JsonWriter writer, object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            OnSerializing(writer, contract, value);
+
+            _serializeStack.Add(value);
+
+            WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
+
+            int initialDepth = writer.Top;
+
+            for (int index = 0; index < contract.Properties.Count; index++)
+            {
+                JsonProperty property = contract.Properties[index];
+                try
+                {
+                    object memberValue;
+                    JsonContract memberContract;
+
+                    if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
+                        continue;
+
+                    property.WritePropertyName(writer);
+                    SerializeValue(writer, memberValue, memberContract, property, contract, member);
+                }
+                catch (Exception ex)
+                {
+                    if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
+                        HandleError(writer, initialDepth);
+                    else
+                        throw;
+                }
+            }
+
+            if (contract.ExtensionDataGetter != null)
+            {
+                IEnumerable<KeyValuePair<object, object>> extensionData = contract.ExtensionDataGetter(value);
+                if (extensionData != null)
+                {
+                    foreach (KeyValuePair<object, object> e in extensionData)
+                    {
+                        JsonContract keyContract = GetContractSafe(e.Key);
+                        JsonContract valueContract = GetContractSafe(e.Value);
+
+                        bool escape;
+                        string propertyName = GetPropertyName(writer, e.Key, keyContract, out escape);
+
+                        if (ShouldWriteReference(e.Value, null, valueContract, contract, member))
+                        {
+                            writer.WritePropertyName(propertyName);
+                            WriteReference(writer, e.Value);
+                        }
+                        else
+                        {
+                            if (!CheckForCircularReference(writer, e.Value, null, valueContract, contract, member))
+                                continue;
+
+                            writer.WritePropertyName(propertyName);
+
+                            SerializeValue(writer, e.Value, valueContract, null, contract, member);
+                        }
+                    }
+                }
+            }
+
+            writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+
+            OnSerialized(writer, contract, value);
+        }
+
+        private bool CalculatePropertyValues(JsonWriter writer, object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, out JsonContract memberContract, out object memberValue)
+        {
+            if (!property.Ignored && property.Readable && ShouldSerialize(writer, property, value) && IsSpecified(writer, property, value))
+            {
+                if (property.PropertyContract == null)
+                    property.PropertyContract = Serializer._contractResolver.ResolveContract(property.PropertyType);
+
+                memberValue = property.ValueProvider.GetValue(value);
+                memberContract = (property.PropertyContract.IsSealed) ? property.PropertyContract : GetContractSafe(memberValue);
+
+                if (ShouldWriteProperty(memberValue, property))
+                {
+                    if (ShouldWriteReference(memberValue, property, memberContract, contract, member))
+                    {
+                        property.WritePropertyName(writer);
+                        WriteReference(writer, memberValue);
+                        return false;
+                    }
+
+                    if (!CheckForCircularReference(writer, memberValue, property, memberContract, contract, member))
+                        return false;
+
+                    if (memberValue == null)
+                    {
+                        JsonObjectContract objectContract = contract as JsonObjectContract;
+                        Required resolvedRequired = property._required ?? ((objectContract != null) ? objectContract.ItemRequired : null) ?? Required.Default;
+                        if (resolvedRequired == Required.Always)
+                            throw JsonSerializationException.Create(null, writer.ContainerPath, "Cannot write a null value for property '{0}'. Property requires a value.".FormatWith(CultureInfo.InvariantCulture, property.PropertyName), null);
+                    }
+
+                    return true;
+                }
+            }
+
+            memberContract = null;
+            memberValue = null;
+            return false;
+        }
+
+        private void WriteObjectStart(JsonWriter writer, object value, JsonContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            writer.WriteStartObject();
+
+            bool isReference = ResolveIsReference(contract, member, collectionContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Objects);
+            if (isReference)
+            {
+                WriteReferenceIdProperty(writer, contract.UnderlyingType, value);
+            }
+            if (ShouldWriteType(TypeNameHandling.Objects, contract, member, collectionContract, containerProperty))
+            {
+                WriteTypeProperty(writer, contract.UnderlyingType);
+            }
+        }
+
+        private void WriteReferenceIdProperty(JsonWriter writer, Type type, object value)
+        {
+            string reference = GetReference(writer, value);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing object reference Id '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, reference, type)), null);
+
+            writer.WritePropertyName(JsonTypeReflector.IdPropertyName, false);
+            writer.WriteValue(reference);
+        }
+
+        private void WriteTypeProperty(JsonWriter writer, Type type)
+        {
+            string typeName = ReflectionUtils.GetTypeName(type, Serializer._typeNameAssemblyFormat, Serializer._binder);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "Writing type name '{0}' for {1}.".FormatWith(CultureInfo.InvariantCulture, typeName, type)), null);
+
+            writer.WritePropertyName(JsonTypeReflector.TypePropertyName, false);
+            writer.WriteValue(typeName);
+        }
+
+        private bool HasFlag(DefaultValueHandling value, DefaultValueHandling flag)
+        {
+            return ((value & flag) == flag);
+        }
+
+        private bool HasFlag(PreserveReferencesHandling value, PreserveReferencesHandling flag)
+        {
+            return ((value & flag) == flag);
+        }
+
+        private bool HasFlag(TypeNameHandling value, TypeNameHandling flag)
+        {
+            return ((value & flag) == flag);
+        }
+
+        private void SerializeConvertable(JsonWriter writer, JsonConverter converter, object value, JsonContract contract, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            if (ShouldWriteReference(value, null, contract, collectionContract, containerProperty))
+            {
+                WriteReference(writer, value);
+            }
+            else
+            {
+                if (!CheckForCircularReference(writer, value, null, contract, collectionContract, containerProperty))
+                    return;
+
+                _serializeStack.Add(value);
+
+                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Started serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
+
+                converter.WriteJson(writer, value, GetInternalSerializer());
+
+                if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Info)
+                    TraceWriter.Trace(TraceLevel.Info, JsonPosition.FormatMessage(null, writer.Path, "Finished serializing {0} with converter {1}.".FormatWith(CultureInfo.InvariantCulture, value.GetType(), converter.GetType())), null);
+
+                _serializeStack.RemoveAt(_serializeStack.Count - 1);
+            }
+        }
+
+        private void SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            IWrappedCollection wrappedCollection = values as IWrappedCollection;
+            object underlyingList = wrappedCollection != null ? wrappedCollection.UnderlyingCollection : values;
+
+            OnSerializing(writer, contract, underlyingList);
+
+            _serializeStack.Add(underlyingList);
+
+            bool hasWrittenMetadataObject = WriteStartArray(writer, underlyingList, contract, member, collectionContract, containerProperty);
+
+            writer.WriteStartArray();
+
+            int initialDepth = writer.Top;
+
+            int index = 0;
+            // note that an error in the IEnumerable won't be caught
+            foreach (object value in values)
+            {
+                try
+                {
+                    JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
+
+                    if (ShouldWriteReference(value, null, valueContract, contract, member))
+                    {
+                        WriteReference(writer, value);
+                    }
+                    else
+                    {
+                        if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
+                        {
+                            SerializeValue(writer, value, valueContract, null, contract, member);
+                        }
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (IsErrorHandled(underlyingList, contract, index, null, writer.ContainerPath, ex))
+                        HandleError(writer, initialDepth);
+                    else
+                        throw;
+                }
+                finally
+                {
+                    index++;
+                }
+            }
+
+            writer.WriteEndArray();
+
+            if (hasWrittenMetadataObject)
+                writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+
+            OnSerialized(writer, contract, underlyingList);
+        }
+
+        private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            OnSerializing(writer, contract, values);
+
+            _serializeStack.Add(values);
+
+            bool hasWrittenMetadataObject = WriteStartArray(writer, values, contract, member, collectionContract, containerProperty);
+
+            SerializeMultidimensionalArray(writer, values, contract, member, writer.Top, new int[0]);
+
+            if (hasWrittenMetadataObject)
+                writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+
+            OnSerialized(writer, contract, values);
+        }
+
+        private void SerializeMultidimensionalArray(JsonWriter writer, Array values, JsonArrayContract contract, JsonProperty member, int initialDepth, int[] indices)
+        {
+            int dimension = indices.Length;
+            int[] newIndices = new int[dimension + 1];
+            for (int i = 0; i < dimension; i++)
+            {
+                newIndices[i] = indices[i];
+            }
+
+            writer.WriteStartArray();
+
+            for (int i = 0; i < values.GetLength(dimension); i++)
+            {
+                newIndices[dimension] = i;
+                bool isTopLevel = (newIndices.Length == values.Rank);
+
+                if (isTopLevel)
+                {
+                    object value = values.GetValue(newIndices);
+
+                    try
+                    {
+                        JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
+
+                        if (ShouldWriteReference(value, null, valueContract, contract, member))
+                        {
+                            WriteReference(writer, value);
+                        }
+                        else
+                        {
+                            if (CheckForCircularReference(writer, value, null, valueContract, contract, member))
+                            {
+                                SerializeValue(writer, value, valueContract, null, contract, member);
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        if (IsErrorHandled(values, contract, i, null, writer.ContainerPath, ex))
+                            HandleError(writer, initialDepth + 1);
+                        else
+                            throw;
+                    }
+                }
+                else
+                {
+                    SerializeMultidimensionalArray(writer, values, contract, member, initialDepth + 1, newIndices);
+                }
+            }
+
+            writer.WriteEndArray();
+        }
+
+        private bool WriteStartArray(JsonWriter writer, object values, JsonArrayContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            bool isReference = ResolveIsReference(contract, member, containerContract, containerProperty) ?? HasFlag(Serializer._preserveReferencesHandling, PreserveReferencesHandling.Arrays);
+            bool includeTypeDetails = ShouldWriteType(TypeNameHandling.Arrays, contract, member, containerContract, containerProperty);
+            bool writeMetadataObject = isReference || includeTypeDetails;
+
+            if (writeMetadataObject)
+            {
+                writer.WriteStartObject();
+
+                if (isReference)
+                {
+                    WriteReferenceIdProperty(writer, contract.UnderlyingType, values);
+                }
+                if (includeTypeDetails)
+                {
+                    WriteTypeProperty(writer, values.GetType());
+                }
+                writer.WritePropertyName(JsonTypeReflector.ArrayValuesPropertyName, false);
+            }
+
+            if (contract.ItemContract == null)
+                contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.CollectionItemType ?? typeof(object));
+
+            return writeMetadataObject;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+#if !(NET20 || NET35)
+        [SecuritySafeCritical]
+#endif
+        private void SerializeISerializable(JsonWriter writer, ISerializable value, JsonISerializableContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            if (!JsonTypeReflector.FullyTrusted)
+            {
+                throw JsonSerializationException.Create(null, writer.ContainerPath, @"Type '{0}' implements ISerializable but cannot be serialized using the ISerializable interface because the current application is not fully trusted and ISerializable can expose secure data.
+To fix this error either change the environment to be fully trusted, change the application to not deserialize the type, add JsonObjectAttribute to the type or change the JsonSerializer setting ContractResolver to use a new DefaultContractResolver with IgnoreSerializableInterface set to true.".FormatWith(CultureInfo.InvariantCulture, value.GetType()), null);
+            }
+
+            OnSerializing(writer, contract, value);
+            _serializeStack.Add(value);
+
+            WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
+
+            SerializationInfo serializationInfo = new SerializationInfo(contract.UnderlyingType, new FormatterConverter());
+            value.GetObjectData(serializationInfo, Serializer._context);
+
+            foreach (SerializationEntry serializationEntry in serializationInfo)
+            {
+                JsonContract valueContract = GetContractSafe(serializationEntry.Value);
+
+                if (CheckForCircularReference(writer, serializationEntry.Value, null, valueContract, contract, member))
+                {
+                    writer.WritePropertyName(serializationEntry.Name);
+                    SerializeValue(writer, serializationEntry.Value, valueContract, null, contract, member);
+                }
+            }
+
+            writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+            OnSerialized(writer, contract, value);
+        }
+#endif
+
+#if !(NET35 || NET20 || PORTABLE40)
+        private void SerializeDynamic(JsonWriter writer, IDynamicMetaObjectProvider value, JsonDynamicContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            OnSerializing(writer, contract, value);
+            _serializeStack.Add(value);
+
+            WriteObjectStart(writer, value, contract, member, collectionContract, containerProperty);
+
+            int initialDepth = writer.Top;
+
+            for (int index = 0; index < contract.Properties.Count; index++)
+            {
+                JsonProperty property = contract.Properties[index];
+
+                // only write non-dynamic properties that have an explicit attribute
+                if (property.HasMemberAttribute)
+                {
+                    try
+                    {
+                        object memberValue;
+                        JsonContract memberContract;
+
+                        if (!CalculatePropertyValues(writer, value, contract, member, property, out memberContract, out memberValue))
+                            continue;
+
+                        property.WritePropertyName(writer);
+                        SerializeValue(writer, memberValue, memberContract, property, contract, member);
+                    }
+                    catch (Exception ex)
+                    {
+                        if (IsErrorHandled(value, contract, property.PropertyName, null, writer.ContainerPath, ex))
+                            HandleError(writer, initialDepth);
+                        else
+                            throw;
+                    }
+                }
+            }
+
+            foreach (string memberName in value.GetDynamicMemberNames())
+            {
+                object memberValue;
+                if (contract.TryGetMember(value, memberName, out memberValue))
+                {
+                    try
+                    {
+                        JsonContract valueContract = GetContractSafe(memberValue);
+
+                        if (!ShouldWriteDynamicProperty(memberValue))
+                            continue;
+
+                        if (CheckForCircularReference(writer, memberValue, null, valueContract, contract, member))
+                        {
+                            string resolvedPropertyName = (contract.PropertyNameResolver != null)
+                                ? contract.PropertyNameResolver(memberName)
+                                : memberName;
+
+                            writer.WritePropertyName(resolvedPropertyName);
+                            SerializeValue(writer, memberValue, valueContract, null, contract, member);
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        if (IsErrorHandled(value, contract, memberName, null, writer.ContainerPath, ex))
+                            HandleError(writer, initialDepth);
+                        else
+                            throw;
+                    }
+                }
+            }
+
+            writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+            OnSerialized(writer, contract, value);
+        }
+#endif
+
+        private bool ShouldWriteDynamicProperty(object memberValue)
+        {
+            if (Serializer._nullValueHandling == NullValueHandling.Ignore && memberValue == null)
+                return false;
+
+            if (HasFlag(Serializer._defaultValueHandling, DefaultValueHandling.Ignore) &&
+                (memberValue == null || MiscellaneousUtils.ValueEquals(memberValue, ReflectionUtils.GetDefaultValue(memberValue.GetType()))))
+                return false;
+
+            return true;
+        }
+
+        private bool ShouldWriteType(TypeNameHandling typeNameHandlingFlag, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
+        {
+            TypeNameHandling resolvedTypeNameHandling =
+                ((member != null) ? member.TypeNameHandling : null)
+                ?? ((containerProperty != null) ? containerProperty.ItemTypeNameHandling : null)
+                ?? ((containerContract != null) ? containerContract.ItemTypeNameHandling : null)
+                ?? Serializer._typeNameHandling;
+
+            if (HasFlag(resolvedTypeNameHandling, typeNameHandlingFlag))
+                return true;
+
+            // instance type and the property's type's contract default type are different (no need to put the type in JSON because the type will be created by default)
+            if (HasFlag(resolvedTypeNameHandling, TypeNameHandling.Auto))
+            {
+                if (member != null)
+                {
+                    if (contract.UnderlyingType != member.PropertyContract.CreatedType)
+                        return true;
+                }
+                else if (containerContract != null)
+                {
+                    if (containerContract.ItemContract == null || contract.UnderlyingType != containerContract.ItemContract.CreatedType)
+                        return true;
+                }
+                else if (_rootContract != null && _serializeStack.Count == _rootLevel)
+                {
+                    if (contract.UnderlyingType != _rootContract.CreatedType)
+                        return true;
+                }
+            }
+
+            return false;
+        }
+
+        private void SerializeDictionary(JsonWriter writer, IDictionary values, JsonDictionaryContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)
+        {
+            IWrappedDictionary wrappedDictionary = values as IWrappedDictionary;
+            object underlyingDictionary = wrappedDictionary != null ? wrappedDictionary.UnderlyingDictionary : values;
+
+            OnSerializing(writer, contract, underlyingDictionary);
+            _serializeStack.Add(underlyingDictionary);
+
+            WriteObjectStart(writer, underlyingDictionary, contract, member, collectionContract, containerProperty);
+
+            if (contract.ItemContract == null)
+                contract.ItemContract = Serializer._contractResolver.ResolveContract(contract.DictionaryValueType ?? typeof(object));
+
+            if (contract.KeyContract == null)
+                contract.KeyContract = Serializer._contractResolver.ResolveContract(contract.DictionaryKeyType ?? typeof(object));
+
+            int initialDepth = writer.Top;
+
+            foreach (DictionaryEntry entry in values)
+            {
+                bool escape;
+                string propertyName = GetPropertyName(writer, entry.Key, contract.KeyContract, out escape);
+
+                propertyName = (contract.PropertyNameResolver != null)
+                    ? contract.PropertyNameResolver(propertyName)
+                    : propertyName;
+
+                try
+                {
+                    object value = entry.Value;
+                    JsonContract valueContract = contract.FinalItemContract ?? GetContractSafe(value);
+
+                    if (ShouldWriteReference(value, null, valueContract, contract, member))
+                    {
+                        writer.WritePropertyName(propertyName, escape);
+                        WriteReference(writer, value);
+                    }
+                    else
+                    {
+                        if (!CheckForCircularReference(writer, value, null, valueContract, contract, member))
+                            continue;
+
+                        writer.WritePropertyName(propertyName, escape);
+
+                        SerializeValue(writer, value, valueContract, null, contract, member);
+                    }
+                }
+                catch (Exception ex)
+                {
+                    if (IsErrorHandled(underlyingDictionary, contract, propertyName, null, writer.ContainerPath, ex))
+                        HandleError(writer, initialDepth);
+                    else
+                        throw;
+                }
+            }
+
+            writer.WriteEndObject();
+
+            _serializeStack.RemoveAt(_serializeStack.Count - 1);
+
+            OnSerialized(writer, contract, underlyingDictionary);
+        }
+
+        private string GetPropertyName(JsonWriter writer, object name, JsonContract contract, out bool escape)
+        {
+            string propertyName;
+
+            if (contract.ContractType == JsonContractType.Primitive)
+            {
+                JsonPrimitiveContract primitiveContract = (JsonPrimitiveContract)contract;
+                if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTime || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeNullable)
+                {
+                    escape = false;
+                    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+                    DateTimeUtils.WriteDateTimeString(sw, (DateTime)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
+                    return sw.ToString();
+                }
+#if !NET20
+                else if (primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffset || primitiveContract.TypeCode == PrimitiveTypeCode.DateTimeOffsetNullable)
+                {
+                    escape = false;
+                    StringWriter sw = new StringWriter(CultureInfo.InvariantCulture);
+                    DateTimeUtils.WriteDateTimeOffsetString(sw, (DateTimeOffset)name, writer.DateFormatHandling, writer.DateFormatString, writer.Culture);
+                    return sw.ToString();
+                }
+#endif
+                else
+                {
+                    escape = true;
+                    return Convert.ToString(name, CultureInfo.InvariantCulture);
+                }
+            }
+            else if (TryConvertToString(name, name.GetType(), out propertyName))
+            {
+                escape = true;
+                return propertyName;
+            }
+            else
+            {
+                escape = true;
+                return name.ToString();
+            }
+        }
+
+        private void HandleError(JsonWriter writer, int initialDepth)
+        {
+            ClearErrorContext();
+
+            if (writer.WriteState == WriteState.Property)
+                writer.WriteNull();
+
+            while (writer.Top > initialDepth)
+            {
+                writer.WriteEnd();
+            }
+        }
+
+        private bool ShouldSerialize(JsonWriter writer, JsonProperty property, object target)
+        {
+            if (property.ShouldSerialize == null)
+                return true;
+
+            bool shouldSerialize = property.ShouldSerialize(target);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "ShouldSerialize result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, shouldSerialize)), null);
+
+            return shouldSerialize;
+        }
+
+        private bool IsSpecified(JsonWriter writer, JsonProperty property, object target)
+        {
+            if (property.GetIsSpecified == null)
+                return true;
+
+            bool isSpecified = property.GetIsSpecified(target);
+
+            if (TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose)
+                TraceWriter.Trace(TraceLevel.Verbose, JsonPosition.FormatMessage(null, writer.Path, "IsSpecified result for property '{0}' on {1}: {2}".FormatWith(CultureInfo.InvariantCulture, property.PropertyName, property.DeclaringType, isSpecified)), null);
+
+            return isSpecified;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs b/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs
new file mode 100644
index 0000000..e155bfa
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonSerializerProxy.cs
@@ -0,0 +1,255 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Runtime.Serialization.Formatters;
+using Newtonsoft.Json.Utilities;
+using System.Runtime.Serialization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class JsonSerializerProxy : JsonSerializer
+    {
+        private readonly JsonSerializerInternalReader _serializerReader;
+        private readonly JsonSerializerInternalWriter _serializerWriter;
+        private readonly JsonSerializer _serializer;
+
+        public override event EventHandler<ErrorEventArgs> Error
+        {
+            add { _serializer.Error += value; }
+            remove { _serializer.Error -= value; }
+        }
+
+        public override IReferenceResolver ReferenceResolver
+        {
+            get { return _serializer.ReferenceResolver; }
+            set { _serializer.ReferenceResolver = value; }
+        }
+
+        public override ITraceWriter TraceWriter
+        {
+            get { return _serializer.TraceWriter; }
+            set { _serializer.TraceWriter = value; }
+        }
+
+        public override JsonConverterCollection Converters
+        {
+            get { return _serializer.Converters; }
+        }
+
+        public override DefaultValueHandling DefaultValueHandling
+        {
+            get { return _serializer.DefaultValueHandling; }
+            set { _serializer.DefaultValueHandling = value; }
+        }
+
+        public override IContractResolver ContractResolver
+        {
+            get { return _serializer.ContractResolver; }
+            set { _serializer.ContractResolver = value; }
+        }
+
+        public override MissingMemberHandling MissingMemberHandling
+        {
+            get { return _serializer.MissingMemberHandling; }
+            set { _serializer.MissingMemberHandling = value; }
+        }
+
+        public override NullValueHandling NullValueHandling
+        {
+            get { return _serializer.NullValueHandling; }
+            set { _serializer.NullValueHandling = value; }
+        }
+
+        public override ObjectCreationHandling ObjectCreationHandling
+        {
+            get { return _serializer.ObjectCreationHandling; }
+            set { _serializer.ObjectCreationHandling = value; }
+        }
+
+        public override ReferenceLoopHandling ReferenceLoopHandling
+        {
+            get { return _serializer.ReferenceLoopHandling; }
+            set { _serializer.ReferenceLoopHandling = value; }
+        }
+
+        public override PreserveReferencesHandling PreserveReferencesHandling
+        {
+            get { return _serializer.PreserveReferencesHandling; }
+            set { _serializer.PreserveReferencesHandling = value; }
+        }
+
+        public override TypeNameHandling TypeNameHandling
+        {
+            get { return _serializer.TypeNameHandling; }
+            set { _serializer.TypeNameHandling = value; }
+        }
+
+        public override MetadataPropertyHandling MetadataPropertyHandling
+        {
+            get { return _serializer.MetadataPropertyHandling; }
+            set { _serializer.MetadataPropertyHandling = value; }
+        }
+
+        public override FormatterAssemblyStyle TypeNameAssemblyFormat
+        {
+            get { return _serializer.TypeNameAssemblyFormat; }
+            set { _serializer.TypeNameAssemblyFormat = value; }
+        }
+
+        public override ConstructorHandling ConstructorHandling
+        {
+            get { return _serializer.ConstructorHandling; }
+            set { _serializer.ConstructorHandling = value; }
+        }
+
+        public override SerializationBinder Binder
+        {
+            get { return _serializer.Binder; }
+            set { _serializer.Binder = value; }
+        }
+
+        public override StreamingContext Context
+        {
+            get { return _serializer.Context; }
+            set { _serializer.Context = value; }
+        }
+
+        public override Formatting Formatting
+        {
+            get { return _serializer.Formatting; }
+            set { _serializer.Formatting = value; }
+        }
+
+        public override DateFormatHandling DateFormatHandling
+        {
+            get { return _serializer.DateFormatHandling; }
+            set { _serializer.DateFormatHandling = value; }
+        }
+
+        public override DateTimeZoneHandling DateTimeZoneHandling
+        {
+            get { return _serializer.DateTimeZoneHandling; }
+            set { _serializer.DateTimeZoneHandling = value; }
+        }
+
+        public override DateParseHandling DateParseHandling
+        {
+            get { return _serializer.DateParseHandling; }
+            set { _serializer.DateParseHandling = value; }
+        }
+
+        public override FloatFormatHandling FloatFormatHandling
+        {
+            get { return _serializer.FloatFormatHandling; }
+            set { _serializer.FloatFormatHandling = value; }
+        }
+
+        public override FloatParseHandling FloatParseHandling
+        {
+            get { return _serializer.FloatParseHandling; }
+            set { _serializer.FloatParseHandling = value; }
+        }
+
+        public override StringEscapeHandling StringEscapeHandling
+        {
+            get { return _serializer.StringEscapeHandling; }
+            set { _serializer.StringEscapeHandling = value; }
+        }
+
+        public override string DateFormatString
+        {
+            get { return _serializer.DateFormatString; }
+            set { _serializer.DateFormatString = value; }
+        }
+
+        public override CultureInfo Culture
+        {
+            get { return _serializer.Culture; }
+            set { _serializer.Culture = value; }
+        }
+
+        public override int? MaxDepth
+        {
+            get { return _serializer.MaxDepth; }
+            set { _serializer.MaxDepth = value; }
+        }
+
+        public override bool CheckAdditionalContent
+        {
+            get { return _serializer.CheckAdditionalContent; }
+            set { _serializer.CheckAdditionalContent = value; }
+        }
+
+        internal JsonSerializerInternalBase GetInternalSerializer()
+        {
+            if (_serializerReader != null)
+                return _serializerReader;
+            else
+                return _serializerWriter;
+        }
+
+        public JsonSerializerProxy(JsonSerializerInternalReader serializerReader)
+        {
+            ValidationUtils.ArgumentNotNull(serializerReader, "serializerReader");
+
+            _serializerReader = serializerReader;
+            _serializer = serializerReader.Serializer;
+        }
+
+        public JsonSerializerProxy(JsonSerializerInternalWriter serializerWriter)
+        {
+            ValidationUtils.ArgumentNotNull(serializerWriter, "serializerWriter");
+
+            _serializerWriter = serializerWriter;
+            _serializer = serializerWriter.Serializer;
+        }
+
+        internal override object DeserializeInternal(JsonReader reader, Type objectType)
+        {
+            if (_serializerReader != null)
+                return _serializerReader.Deserialize(reader, objectType, false);
+            else
+                return _serializer.Deserialize(reader, objectType);
+        }
+
+        internal override void PopulateInternal(JsonReader reader, object target)
+        {
+            if (_serializerReader != null)
+                _serializerReader.Populate(reader, target);
+            else
+                _serializer.Populate(reader, target);
+        }
+
+        internal override void SerializeInternal(JsonWriter jsonWriter, object value, Type rootType)
+        {
+            if (_serializerWriter != null)
+                _serializerWriter.Serialize(jsonWriter, value, rootType);
+            else
+                _serializer.Serialize(jsonWriter, value);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonStringContract.cs b/Newtonsoft.Json/Serialization/JsonStringContract.cs
new file mode 100644
index 0000000..4a1ebbd
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonStringContract.cs
@@ -0,0 +1,45 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Contract details for a <see cref="Type"/> used by the <see cref="JsonSerializer"/>.
+    /// </summary>
+    public class JsonStringContract : JsonPrimitiveContract
+    {
+        /// <summary>
+        /// Initializes a new instance of the <see cref="JsonStringContract"/> class.
+        /// </summary>
+        /// <param name="underlyingType">The underlying type for the contract.</param>
+        public JsonStringContract(Type underlyingType)
+            : base(underlyingType)
+        {
+            ContractType = JsonContractType.String;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/JsonTypeReflector.cs b/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
new file mode 100644
index 0000000..b72a238
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/JsonTypeReflector.cs
@@ -0,0 +1,424 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.ComponentModel;
+using System.Globalization;
+using System.Reflection;
+using System.Security;
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+using System.Security.Permissions;
+#endif
+using Newtonsoft.Json.Utilities;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Runtime.Serialization;
+
+namespace Newtonsoft.Json.Serialization
+{
+#if !NET20 && !NETFX_CORE
+    internal interface IMetadataTypeAttribute
+    {
+        Type MetadataClassType { get; }
+    }
+#endif
+
+    internal static class JsonTypeReflector
+    {
+        private static bool? _dynamicCodeGeneration;
+        private static bool? _fullyTrusted;
+
+        public const string IdPropertyName = "$id";
+        public const string RefPropertyName = "$ref";
+        public const string TypePropertyName = "$type";
+        public const string ValuePropertyName = "$value";
+        public const string ArrayValuesPropertyName = "$values";
+
+        public const string ShouldSerializePrefix = "ShouldSerialize";
+        public const string SpecifiedPostfix = "Specified";
+
+        private static readonly ThreadSafeStore<object, Type> JsonConverterTypeCache = new ThreadSafeStore<object, Type>(GetJsonConverterTypeFromAttribute);
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+        private static readonly ThreadSafeStore<Type, Type> AssociatedMetadataTypesCache = new ThreadSafeStore<Type, Type>(GetAssociateMetadataTypeFromAttribute);
+
+        private const string MetadataTypeAttributeTypeName =
+            "System.ComponentModel.DataAnnotations.MetadataTypeAttribute, System.ComponentModel.DataAnnotations, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+
+        private static Type _cachedMetadataTypeAttributeType;
+#endif
+
+        public static JsonContainerAttribute GetJsonContainerAttribute(Type type)
+        {
+            return CachedAttributeGetter<JsonContainerAttribute>.GetAttribute(type);
+        }
+
+        public static JsonObjectAttribute GetJsonObjectAttribute(Type type)
+        {
+            return GetJsonContainerAttribute(type) as JsonObjectAttribute;
+        }
+
+        public static JsonArrayAttribute GetJsonArrayAttribute(Type type)
+        {
+            return GetJsonContainerAttribute(type) as JsonArrayAttribute;
+        }
+
+        public static JsonDictionaryAttribute GetJsonDictionaryAttribute(Type type)
+        {
+            return GetJsonContainerAttribute(type) as JsonDictionaryAttribute;
+        }
+
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+        public static SerializableAttribute GetSerializableAttribute(Type type)
+        {
+            return CachedAttributeGetter<SerializableAttribute>.GetAttribute(type);
+        }
+#endif
+
+#if !NET20
+        public static DataContractAttribute GetDataContractAttribute(Type type)
+        {
+            // DataContractAttribute does not have inheritance
+            Type currentType = type;
+
+            while (currentType != null)
+            {
+                DataContractAttribute result = CachedAttributeGetter<DataContractAttribute>.GetAttribute(currentType);
+                if (result != null)
+                    return result;
+
+                currentType = currentType.BaseType();
+            }
+
+            return null;
+        }
+
+        public static DataMemberAttribute GetDataMemberAttribute(MemberInfo memberInfo)
+        {
+            // DataMemberAttribute does not have inheritance
+
+            // can't override a field
+            if (memberInfo.MemberType() == MemberTypes.Field)
+                return CachedAttributeGetter<DataMemberAttribute>.GetAttribute(memberInfo);
+
+            // search property and then search base properties if nothing is returned and the property is virtual
+            PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
+            DataMemberAttribute result = CachedAttributeGetter<DataMemberAttribute>.GetAttribute(propertyInfo);
+            if (result == null)
+            {
+                if (propertyInfo.IsVirtual())
+                {
+                    Type currentType = propertyInfo.DeclaringType;
+
+                    while (result == null && currentType != null)
+                    {
+                        PropertyInfo baseProperty = (PropertyInfo)ReflectionUtils.GetMemberInfoFromType(currentType, propertyInfo);
+                        if (baseProperty != null && baseProperty.IsVirtual())
+                            result = CachedAttributeGetter<DataMemberAttribute>.GetAttribute(baseProperty);
+
+                        currentType = currentType.BaseType();
+                    }
+                }
+            }
+
+            return result;
+        }
+#endif
+
+        public static MemberSerialization GetObjectMemberSerialization(Type objectType, bool ignoreSerializableAttribute)
+        {
+            JsonObjectAttribute objectAttribute = GetJsonObjectAttribute(objectType);
+            if (objectAttribute != null)
+                return objectAttribute.MemberSerialization;
+
+#if !NET20
+            DataContractAttribute dataContractAttribute = GetDataContractAttribute(objectType);
+            if (dataContractAttribute != null)
+                return MemberSerialization.OptIn;
+#endif
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (!ignoreSerializableAttribute)
+            {
+                SerializableAttribute serializableAttribute = GetSerializableAttribute(objectType);
+                if (serializableAttribute != null)
+                    return MemberSerialization.Fields;
+            }
+#endif
+
+            // the default
+            return MemberSerialization.OptOut;
+        }
+
+        private static Type GetJsonConverterType(object attributeProvider)
+        {
+            return JsonConverterTypeCache.Get(attributeProvider);
+        }
+
+        private static Type GetJsonConverterTypeFromAttribute(object attributeProvider)
+        {
+            JsonConverterAttribute converterAttribute = GetAttribute<JsonConverterAttribute>(attributeProvider);
+            return (converterAttribute != null)
+                ? converterAttribute.ConverterType
+                : null;
+        }
+
+        public static JsonConverter GetJsonConverter(object attributeProvider, Type targetConvertedType)
+        {
+            Type converterType = GetJsonConverterType(attributeProvider);
+
+            if (converterType != null)
+            {
+                JsonConverter memberConverter = JsonConverterAttribute.CreateJsonConverterInstance(converterType);
+
+                return memberConverter;
+            }
+
+            return null;
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        public static TypeConverter GetTypeConverter(Type type)
+        {
+            return TypeDescriptor.GetConverter(type);
+        }
+#endif
+
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+        private static Type GetAssociatedMetadataType(Type type)
+        {
+            return AssociatedMetadataTypesCache.Get(type);
+        }
+
+        private static Type GetAssociateMetadataTypeFromAttribute(Type type)
+        {
+            Type metadataTypeAttributeType = GetMetadataTypeAttributeType();
+            if (metadataTypeAttributeType == null)
+                return null;
+
+            object attribute = type.GetCustomAttributes(metadataTypeAttributeType, true).SingleOrDefault();
+            if (attribute == null)
+                return null;
+
+            IMetadataTypeAttribute metadataTypeAttribute = (DynamicCodeGeneration)
+                ? DynamicWrapper.CreateWrapper<IMetadataTypeAttribute>(attribute)
+                : new LateBoundMetadataTypeAttribute(attribute);
+
+            return metadataTypeAttribute.MetadataClassType;
+        }
+
+        private static Type GetMetadataTypeAttributeType()
+        {
+            // always attempt to get the metadata type attribute type
+            // the assembly may have been loaded since last time
+            if (_cachedMetadataTypeAttributeType == null)
+            {
+                Type metadataTypeAttributeType = Type.GetType(MetadataTypeAttributeTypeName);
+
+                if (metadataTypeAttributeType != null)
+                    _cachedMetadataTypeAttributeType = metadataTypeAttributeType;
+                else
+                    return null;
+            }
+
+            return _cachedMetadataTypeAttributeType;
+        }
+#endif
+
+        private static T GetAttribute<T>(Type type) where T : Attribute
+        {
+            T attribute;
+
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+            Type metadataType = GetAssociatedMetadataType(type);
+            if (metadataType != null)
+            {
+                attribute = ReflectionUtils.GetAttribute<T>(metadataType, true);
+                if (attribute != null)
+                    return attribute;
+            }
+#endif
+
+            attribute = ReflectionUtils.GetAttribute<T>(type, true);
+            if (attribute != null)
+                return attribute;
+
+            foreach (Type typeInterface in type.GetInterfaces())
+            {
+                attribute = ReflectionUtils.GetAttribute<T>(typeInterface, true);
+                if (attribute != null)
+                    return attribute;
+            }
+
+            return null;
+        }
+
+        private static T GetAttribute<T>(MemberInfo memberInfo) where T : Attribute
+        {
+            T attribute;
+
+#if !(NET20 || NETFX_CORE || PORTABLE40 || PORTABLE)
+            Type metadataType = GetAssociatedMetadataType(memberInfo.DeclaringType);
+            if (metadataType != null)
+            {
+                MemberInfo metadataTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(metadataType, memberInfo);
+
+                if (metadataTypeMemberInfo != null)
+                {
+                    attribute = ReflectionUtils.GetAttribute<T>(metadataTypeMemberInfo, true);
+                    if (attribute != null)
+                        return attribute;
+                }
+            }
+#endif
+
+            attribute = ReflectionUtils.GetAttribute<T>(memberInfo, true);
+            if (attribute != null)
+                return attribute;
+
+            if (memberInfo.DeclaringType != null)
+            {
+                foreach (Type typeInterface in memberInfo.DeclaringType.GetInterfaces())
+                {
+                    MemberInfo interfaceTypeMemberInfo = ReflectionUtils.GetMemberInfoFromType(typeInterface, memberInfo);
+
+                    if (interfaceTypeMemberInfo != null)
+                    {
+                        attribute = ReflectionUtils.GetAttribute<T>(interfaceTypeMemberInfo, true);
+                        if (attribute != null)
+                            return attribute;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        public static T GetAttribute<T>(object provider) where T : Attribute
+        {
+            Type type = provider as Type;
+            if (type != null)
+                return GetAttribute<T>(type);
+
+            MemberInfo memberInfo = provider as MemberInfo;
+            if (memberInfo != null)
+                return GetAttribute<T>(memberInfo);
+
+            return ReflectionUtils.GetAttribute<T>(provider, true);
+        }
+
+#if DEBUG
+        internal static void SetFullyTrusted(bool fullyTrusted)
+        {
+            _fullyTrusted = fullyTrusted;
+        }
+
+        internal static void SetDynamicCodeGeneration(bool dynamicCodeGeneration)
+        {
+            _dynamicCodeGeneration = dynamicCodeGeneration;
+        }
+#endif
+
+        public static bool DynamicCodeGeneration
+        {
+#if !(NET20 || NET35 || NETFX_CORE || PORTABLE)
+            [SecuritySafeCritical]
+#endif
+                get
+            {
+                if (_dynamicCodeGeneration == null)
+                {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+                    try
+                    {
+                        new ReflectionPermission(ReflectionPermissionFlag.MemberAccess).Demand();
+                        new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess).Demand();
+                        new SecurityPermission(SecurityPermissionFlag.SkipVerification).Demand();
+                        new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();
+                        new SecurityPermission(PermissionState.Unrestricted).Demand();
+                        _dynamicCodeGeneration = true;
+                    }
+                    catch (Exception)
+                    {
+                        _dynamicCodeGeneration = false;
+                    }
+#else
+                    _dynamicCodeGeneration = false;
+#endif
+                }
+
+                return _dynamicCodeGeneration.Value;
+            }
+        }
+
+        public static bool FullyTrusted
+        {
+            get
+            {
+                if (_fullyTrusted == null)
+                {
+#if (NETFX_CORE || PORTABLE || PORTABLE40)
+                    _fullyTrusted = false;
+#elif !(NET20 || NET35 || PORTABLE40)
+                    AppDomain appDomain = AppDomain.CurrentDomain;
+
+                    _fullyTrusted = appDomain.IsHomogenous && appDomain.IsFullyTrusted;
+#else
+          try
+          {
+            new SecurityPermission(PermissionState.Unrestricted).Demand();
+            _fullyTrusted = true;
+          }
+          catch (Exception)
+          {
+            _fullyTrusted = false;
+          }
+#endif
+                }
+
+                return _fullyTrusted.Value;
+            }
+        }
+
+        public static ReflectionDelegateFactory ReflectionDelegateFactory
+        {
+            get
+            {
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+                if (DynamicCodeGeneration)
+                    return DynamicReflectionDelegateFactory.Instance;
+
+                return LateBoundReflectionDelegateFactory.Instance;
+#elif !(PORTABLE40)
+        return ExpressionReflectionDelegateFactory.Instance;
+#else
+                return LateBoundReflectionDelegateFactory.Instance;
+#endif
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs b/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs
new file mode 100644
index 0000000..0d70afd
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/LateBoundMetadataTypeAttribute.cs
@@ -0,0 +1,60 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !NET20 && !NETFX_CORE
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Newtonsoft.Json.Utilities;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class LateBoundMetadataTypeAttribute : IMetadataTypeAttribute
+    {
+        private static PropertyInfo _metadataClassTypeProperty;
+
+        private readonly object _attribute;
+
+        public LateBoundMetadataTypeAttribute(object attribute)
+        {
+            _attribute = attribute;
+        }
+
+        public Type MetadataClassType
+        {
+            get
+            {
+                if (_metadataClassTypeProperty == null)
+                    _metadataClassTypeProperty = _attribute.GetType().GetProperty("MetadataClassType");
+
+                return (Type)ReflectionUtils.GetMemberValue(_metadataClassTypeProperty, _attribute);
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs b/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs
new file mode 100644
index 0000000..68ddeca
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/MemoryTraceWriter.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Text;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Represents a trace writer that writes to memory. When the trace message limit is
+    /// reached then old trace messages will be removed as new messages are added.
+    /// </summary>
+    public class MemoryTraceWriter : ITraceWriter
+    {
+        private readonly Queue<string> _traceMessages;
+
+        /// <summary>
+        /// Gets the <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.
+        /// For example a filter level of <code>Info</code> will exclude <code>Verbose</code> messages and include <code>Info</code>,
+        /// <code>Warning</code> and <code>Error</code> messages.
+        /// </summary>
+        /// <value>
+        /// The <see cref="TraceLevel"/> that will be used to filter the trace messages passed to the writer.
+        /// </value>
+        public TraceLevel LevelFilter { get; set; }
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="MemoryTraceWriter"/> class.
+        /// </summary>
+        public MemoryTraceWriter()
+        {
+            LevelFilter = TraceLevel.Verbose;
+            _traceMessages = new Queue<string>();
+        }
+
+        /// <summary>
+        /// Writes the specified trace level, message and optional exception.
+        /// </summary>
+        /// <param name="level">The <see cref="TraceLevel"/> at which to write this trace.</param>
+        /// <param name="message">The trace message.</param>
+        /// <param name="ex">The trace exception. This parameter is optional.</param>
+        public void Trace(TraceLevel level, string message, Exception ex)
+        {
+            string traceMessage = DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff", CultureInfo.InvariantCulture) + " " + level.ToString("g") + " " + message;
+
+            if (_traceMessages.Count >= 1000)
+                _traceMessages.Dequeue();
+
+            _traceMessages.Enqueue(traceMessage);
+        }
+
+        /// <summary>
+        /// Returns an enumeration of the most recent trace messages.
+        /// </summary>
+        /// <returns>An enumeration of the most recent trace messages.</returns>
+        public IEnumerable<string> GetTraceMessages()
+        {
+            return _traceMessages;
+        }
+
+        /// <summary>
+        /// Returns a <see cref="String"/> of the most recent trace messages.
+        /// </summary>
+        /// <returns>
+        /// A <see cref="String"/> of the most recent trace messages.
+        /// </returns>
+        public override string ToString()
+        {
+            StringBuilder sb = new StringBuilder();
+            foreach (string traceMessage in _traceMessages)
+            {
+                if (sb.Length > 0)
+                    sb.AppendLine();
+
+                sb.Append(traceMessage);
+            }
+
+            return sb.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ObjectConstructor.cs b/Newtonsoft.Json/Serialization/ObjectConstructor.cs
new file mode 100644
index 0000000..352d9b9
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ObjectConstructor.cs
@@ -0,0 +1,33 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Represents a method that constructs an object.
+    /// </summary>
+    /// <typeparam name="T">The object type to create.</typeparam>
+    public delegate object ObjectConstructor<T>(params object[] args);
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/OnErrorAttribute.cs b/Newtonsoft.Json/Serialization/OnErrorAttribute.cs
new file mode 100644
index 0000000..459b282
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/OnErrorAttribute.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// When applied to a method, specifies that the method is called when an error occurs serializing an object.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Method, Inherited = false)]
+    public sealed class OnErrorAttribute : Attribute
+    {
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs b/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs
new file mode 100644
index 0000000..dfb322a
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/ReflectionValueProvider.cs
@@ -0,0 +1,84 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Reflection;
+using Newtonsoft.Json.Utilities;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Serialization
+{
+    /// <summary>
+    /// Get and set values for a <see cref="MemberInfo"/> using reflection.
+    /// </summary>
+    public class ReflectionValueProvider : IValueProvider
+    {
+        private readonly MemberInfo _memberInfo;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="ReflectionValueProvider"/> class.
+        /// </summary>
+        /// <param name="memberInfo">The member info.</param>
+        public ReflectionValueProvider(MemberInfo memberInfo)
+        {
+            ValidationUtils.ArgumentNotNull(memberInfo, "memberInfo");
+            _memberInfo = memberInfo;
+        }
+
+        /// <summary>
+        /// Sets the value.
+        /// </summary>
+        /// <param name="target">The target to set the value on.</param>
+        /// <param name="value">The value to set on the target.</param>
+        public void SetValue(object target, object value)
+        {
+            try
+            {
+                ReflectionUtils.SetMemberValue(_memberInfo, target, value);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error setting value to '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+
+        /// <summary>
+        /// Gets the value.
+        /// </summary>
+        /// <param name="target">The target to get the value from.</param>
+        /// <returns>The value.</returns>
+        public object GetValue(object target)
+        {
+            try
+            {
+                return ReflectionUtils.GetMemberValue(_memberInfo, target);
+            }
+            catch (Exception ex)
+            {
+                throw new JsonSerializationException("Error getting value from '{0}' on '{1}'.".FormatWith(CultureInfo.InvariantCulture, _memberInfo.Name, target.GetType()), ex);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/TraceJsonReader.cs b/Newtonsoft.Json/Serialization/TraceJsonReader.cs
new file mode 100644
index 0000000..c0b1d30
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/TraceJsonReader.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class TraceJsonReader : JsonReader, IJsonLineInfo
+    {
+        private readonly JsonReader _innerReader;
+        private readonly JsonTextWriter _textWriter;
+        private readonly StringWriter _sw;
+
+        public TraceJsonReader(JsonReader innerReader)
+        {
+            _innerReader = innerReader;
+
+            _sw = new StringWriter(CultureInfo.InvariantCulture);
+            _textWriter = new JsonTextWriter(_sw);
+            _textWriter.Formatting = Formatting.Indented;
+        }
+
+        public string GetJson()
+        {
+            return _sw.ToString();
+        }
+
+        public override bool Read()
+        {
+            var value = _innerReader.Read();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+        public override int? ReadAsInt32()
+        {
+            var value = _innerReader.ReadAsInt32();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+        public override string ReadAsString()
+        {
+            var value = _innerReader.ReadAsString();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+        public override byte[] ReadAsBytes()
+        {
+            var value = _innerReader.ReadAsBytes();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+        public override decimal? ReadAsDecimal()
+        {
+            var value = _innerReader.ReadAsDecimal();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+        public override DateTime? ReadAsDateTime()
+        {
+            var value = _innerReader.ReadAsDateTime();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+
+#if !NET20
+        public override DateTimeOffset? ReadAsDateTimeOffset()
+        {
+            var value = _innerReader.ReadAsDateTimeOffset();
+            _textWriter.WriteToken(_innerReader, false, false);
+            return value;
+        }
+#endif
+
+        public override int Depth
+        {
+            get { return _innerReader.Depth; }
+        }
+
+        public override string Path
+        {
+            get { return _innerReader.Path; }
+        }
+
+        public override char QuoteChar
+        {
+            get { return _innerReader.QuoteChar; }
+            protected internal set { _innerReader.QuoteChar = value; }
+        }
+
+        public override JsonToken TokenType
+        {
+            get { return _innerReader.TokenType; }
+        }
+
+        public override object Value
+        {
+            get { return _innerReader.Value; }
+        }
+
+        public override Type ValueType
+        {
+            get { return _innerReader.ValueType; }
+        }
+
+        public override void Close()
+        {
+            _innerReader.Close();
+        }
+
+        bool IJsonLineInfo.HasLineInfo()
+        {
+            IJsonLineInfo lineInfo = _innerReader as IJsonLineInfo;
+            return lineInfo != null && lineInfo.HasLineInfo();
+        }
+
+        int IJsonLineInfo.LineNumber
+        {
+            get
+            {
+                IJsonLineInfo lineInfo = _innerReader as IJsonLineInfo;
+                return (lineInfo != null) ? lineInfo.LineNumber : 0;
+            }
+        }
+
+        int IJsonLineInfo.LinePosition
+        {
+            get
+            {
+                IJsonLineInfo lineInfo = _innerReader as IJsonLineInfo;
+                return (lineInfo != null) ? lineInfo.LinePosition : 0;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Serialization/TraceJsonWriter.cs b/Newtonsoft.Json/Serialization/TraceJsonWriter.cs
new file mode 100644
index 0000000..b273c98
--- /dev/null
+++ b/Newtonsoft.Json/Serialization/TraceJsonWriter.cs
@@ -0,0 +1,348 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+using System.Numerics;
+#endif
+using System.Text;
+
+namespace Newtonsoft.Json.Serialization
+{
+    internal class TraceJsonWriter : JsonWriter
+    {
+        private readonly JsonWriter _innerWriter;
+        private readonly JsonTextWriter _textWriter;
+        private readonly StringWriter _sw;
+
+        public TraceJsonWriter(JsonWriter innerWriter)
+        {
+            _innerWriter = innerWriter;
+
+            _sw = new StringWriter(CultureInfo.InvariantCulture);
+            _textWriter = new JsonTextWriter(_sw);
+            _textWriter.Formatting = Formatting.Indented;
+            _textWriter.Culture = innerWriter.Culture;
+            _textWriter.DateFormatHandling = innerWriter.DateFormatHandling;
+            _textWriter.DateFormatString = innerWriter.DateFormatString;
+            _textWriter.DateTimeZoneHandling = innerWriter.DateTimeZoneHandling;
+            _textWriter.FloatFormatHandling = innerWriter.FloatFormatHandling;
+        }
+
+        public string GetJson()
+        {
+            return _sw.ToString();
+        }
+
+        public override void WriteValue(decimal value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(bool value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(byte value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(byte? value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(char value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(byte[] value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(DateTime value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+#if !NET20
+        public override void WriteValue(DateTimeOffset value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+#endif
+
+        public override void WriteValue(double value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteUndefined()
+        {
+            _textWriter.WriteUndefined();
+            _innerWriter.WriteUndefined();
+            base.WriteUndefined();
+        }
+
+        public override void WriteNull()
+        {
+            _textWriter.WriteNull();
+            _innerWriter.WriteNull();
+            base.WriteUndefined();
+        }
+
+        public override void WriteValue(float value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(Guid value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(int value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(long value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(object value)
+        {
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+            if (value is BigInteger)
+            {
+                _textWriter.WriteValue(value);
+                _innerWriter.WriteValue(value);
+                InternalWriteValue(JsonToken.Integer);
+            }
+            else
+#endif
+            {
+                _textWriter.WriteValue(value);
+                _innerWriter.WriteValue(value);
+                base.WriteValue(value);
+            }
+        }
+
+        public override void WriteValue(sbyte value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(short value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(string value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(TimeSpan value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(uint value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(ulong value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(Uri value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteValue(ushort value)
+        {
+            _textWriter.WriteValue(value);
+            _innerWriter.WriteValue(value);
+            base.WriteValue(value);
+        }
+
+        public override void WriteWhitespace(string ws)
+        {
+            _textWriter.WriteWhitespace(ws);
+            _innerWriter.WriteWhitespace(ws);
+            base.WriteWhitespace(ws);
+        }
+
+        //protected override void WriteValueDelimiter()
+        //{
+        //  _textWriter.WriteValueDelimiter();
+        //  _innerWriter.WriteValueDelimiter();
+        //  base.WriteValueDelimiter();
+        //}
+
+        //protected override void WriteIndent()
+        //{
+        //  base.WriteIndent();
+        //}
+
+        public override void WriteComment(string text)
+        {
+            _textWriter.WriteComment(text);
+            _innerWriter.WriteComment(text);
+            base.WriteComment(text);
+        }
+
+        //public override void WriteEnd()
+        //{
+        //  _textWriter.WriteEnd();
+        //  _innerWriter.WriteEnd();
+        //  base.WriteEnd();
+        //}
+
+        //protected override void WriteEnd(JsonToken token)
+        //{
+        //  base.WriteEnd(token);
+        //}
+
+        public override void WriteStartArray()
+        {
+            _textWriter.WriteStartArray();
+            _innerWriter.WriteStartArray();
+            base.WriteStartArray();
+        }
+
+        public override void WriteEndArray()
+        {
+            _textWriter.WriteEndArray();
+            _innerWriter.WriteEndArray();
+            base.WriteEndArray();
+        }
+
+        public override void WriteStartConstructor(string name)
+        {
+            _textWriter.WriteStartConstructor(name);
+            _innerWriter.WriteStartConstructor(name);
+            base.WriteStartConstructor(name);
+        }
+
+        public override void WriteEndConstructor()
+        {
+            _textWriter.WriteEndConstructor();
+            _innerWriter.WriteEndConstructor();
+            base.WriteEndConstructor();
+        }
+
+        public override void WritePropertyName(string name)
+        {
+            _textWriter.WritePropertyName(name);
+            _innerWriter.WritePropertyName(name);
+            base.WritePropertyName(name);
+        }
+
+        public override void WritePropertyName(string name, bool escape)
+        {
+            _textWriter.WritePropertyName(name, escape);
+            _innerWriter.WritePropertyName(name, escape);
+
+            // method with escape will error
+            base.WritePropertyName(name);
+        }
+
+        public override void WriteStartObject()
+        {
+            _textWriter.WriteStartObject();
+            _innerWriter.WriteStartObject();
+            base.WriteStartObject();
+        }
+
+        public override void WriteEndObject()
+        {
+            _textWriter.WriteEndObject();
+            _innerWriter.WriteEndObject();
+            base.WriteEndObject();
+        }
+
+        public override void WriteRaw(string json)
+        {
+            _textWriter.WriteRaw(json);
+            _innerWriter.WriteRaw(json);
+            base.WriteRaw(json);
+        }
+
+        public override void WriteRawValue(string json)
+        {
+            _textWriter.WriteRawValue(json);
+            _innerWriter.WriteRawValue(json);
+            base.WriteRawValue(json);
+        }
+
+        //protected override void WriteIndentSpace()
+        //{
+        //  _textWriter.WriteIndentSpace();
+        //  _innerWriter.WriteIndentSpace();
+        //  base.WriteIndentSpace();
+        //}
+
+        public override void Close()
+        {
+            _textWriter.Close();
+            _innerWriter.Close();
+            base.Close();
+        }
+
+        public override void Flush()
+        {
+            _textWriter.Flush();
+            _innerWriter.Flush();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/SerializationBinder.cs b/Newtonsoft.Json/SerializationBinder.cs
new file mode 100644
index 0000000..9ceb867
--- /dev/null
+++ b/Newtonsoft.Json/SerializationBinder.cs
@@ -0,0 +1,35 @@
+
+#if PocketPC || NETFX_CORE || PORTABLE40 || PORTABLE
+using System;
+using System.Reflection;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Allows users to control class loading and mandate what class to load.
+    /// </summary>
+    public abstract class SerializationBinder
+    {
+        /// <summary>
+        /// When overridden in a derived class, controls the binding of a serialized object to a type.
+        /// </summary>
+        /// <param name="assemblyName">Specifies the <see cref="Assembly"/> name of the serialized object.</param>
+        /// <param name="typeName">Specifies the <see cref="Type"/> name of the serialized object</param>
+        /// <returns>The type of the object the formatter creates a new instance of.</returns>
+        public abstract Type BindToType(string assemblyName, string typeName);
+
+        /// <summary>
+        /// When overridden in a derived class, controls the binding of a serialized object to a type.
+        /// </summary>
+        /// <param name="serializedType">The type of the object the formatter creates a new instance of.</param>
+        /// <param name="assemblyName">Specifies the <see cref="Assembly"/> name of the serialized object.</param>
+        /// <param name="typeName">Specifies the <see cref="Type"/> name of the serialized object.</param>
+        public virtual void BindToName(Type serializedType, out string assemblyName, out string typeName)
+        {
+            assemblyName = null;
+            typeName = null;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/StringEscapeHandling.cs b/Newtonsoft.Json/StringEscapeHandling.cs
new file mode 100644
index 0000000..a538a8d
--- /dev/null
+++ b/Newtonsoft.Json/StringEscapeHandling.cs
@@ -0,0 +1,48 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies how strings are escaped when writing JSON text.
+    /// </summary>
+    public enum StringEscapeHandling
+    {
+        /// <summary>
+        /// Only control characters (e.g. newline) are escaped.
+        /// </summary>
+        Default,
+
+        /// <summary>
+        /// All non-ASCII and control characters (e.g. newline) are escaped.
+        /// </summary>
+        EscapeNonAscii,
+
+        /// <summary>
+        /// HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped.
+        /// </summary>
+        EscapeHtml
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/TraceLevel.cs b/Newtonsoft.Json/TraceLevel.cs
new file mode 100644
index 0000000..0cce1cd
--- /dev/null
+++ b/Newtonsoft.Json/TraceLevel.cs
@@ -0,0 +1,39 @@
+
+#if (NETFX_CORE || PORTABLE40 || PORTABLE)
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies what messages to output for the <see cref="ITraceWriter"/> class.
+    /// </summary>
+    public enum TraceLevel
+    {
+        /// <summary>
+        /// Output no tracing and debugging messages.
+        /// </summary>
+        Off,
+
+        /// <summary>
+        /// Output error-handling messages.
+        /// </summary>
+        Error,
+
+        /// <summary>
+        /// Output warnings and error-handling messages.
+        /// </summary>
+        Warning,
+
+        /// <summary>
+        /// Output informational messages, warnings, and error-handling messages.
+        /// </summary>
+        Info,
+
+        /// <summary>
+        /// Output all debugging and tracing messages.
+        /// </summary>
+        Verbose
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/TypeNameHandling.cs b/Newtonsoft.Json/TypeNameHandling.cs
new file mode 100644
index 0000000..add0d79
--- /dev/null
+++ b/Newtonsoft.Json/TypeNameHandling.cs
@@ -0,0 +1,61 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies type name handling options for the <see cref="JsonSerializer"/>.
+    /// </summary>
+    [Flags]
+    public enum TypeNameHandling
+    {
+        /// <summary>
+        /// Do not include the .NET type name when serializing types.
+        /// </summary>
+        None = 0,
+
+        /// <summary>
+        /// Include the .NET type name when serializing into a JSON object structure.
+        /// </summary>
+        Objects = 1,
+
+        /// <summary>
+        /// Include the .NET type name when serializing into a JSON array structure.
+        /// </summary>
+        Arrays = 2,
+
+        /// <summary>
+        /// Always include the .NET type name when serializing.
+        /// </summary>
+        All = Objects | Arrays,
+
+        /// <summary>
+        /// Include the .NET type name when the type of the object being serialized is not the same as its declared type.
+        /// </summary>
+        Auto = 4
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/Base64Encoder.cs b/Newtonsoft.Json/Utilities/Base64Encoder.cs
new file mode 100644
index 0000000..c3c1fd1
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/Base64Encoder.cs
@@ -0,0 +1,120 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.IO;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class Base64Encoder
+    {
+        private const int Base64LineSize = 76;
+        private const int LineSizeInBytes = 57;
+
+        private readonly char[] _charsLine = new char[Base64LineSize];
+        private readonly TextWriter _writer;
+
+        private byte[] _leftOverBytes;
+        private int _leftOverBytesCount;
+
+        public Base64Encoder(TextWriter writer)
+        {
+            ValidationUtils.ArgumentNotNull(writer, "writer");
+            _writer = writer;
+        }
+
+        public void Encode(byte[] buffer, int index, int count)
+        {
+            if (buffer == null)
+                throw new ArgumentNullException("buffer");
+
+            if (index < 0)
+                throw new ArgumentOutOfRangeException("index");
+
+            if (count < 0)
+                throw new ArgumentOutOfRangeException("count");
+
+            if (count > (buffer.Length - index))
+                throw new ArgumentOutOfRangeException("count");
+
+            if (_leftOverBytesCount > 0)
+            {
+                int leftOverBytesCount = _leftOverBytesCount;
+                while (leftOverBytesCount < 3 && count > 0)
+                {
+                    _leftOverBytes[leftOverBytesCount++] = buffer[index++];
+                    count--;
+                }
+                if (count == 0 && leftOverBytesCount < 3)
+                {
+                    _leftOverBytesCount = leftOverBytesCount;
+                    return;
+                }
+                int num2 = Convert.ToBase64CharArray(_leftOverBytes, 0, 3, _charsLine, 0);
+                WriteChars(_charsLine, 0, num2);
+            }
+            _leftOverBytesCount = count % 3;
+            if (_leftOverBytesCount > 0)
+            {
+                count -= _leftOverBytesCount;
+                if (_leftOverBytes == null)
+                {
+                    _leftOverBytes = new byte[3];
+                }
+                for (int i = 0; i < _leftOverBytesCount; i++)
+                {
+                    _leftOverBytes[i] = buffer[(index + count) + i];
+                }
+            }
+            int num4 = index + count;
+            int length = LineSizeInBytes;
+            while (index < num4)
+            {
+                if ((index + length) > num4)
+                {
+                    length = num4 - index;
+                }
+                int num6 = Convert.ToBase64CharArray(buffer, index, length, _charsLine, 0);
+                WriteChars(_charsLine, 0, num6);
+                index += length;
+            }
+        }
+
+        public void Flush()
+        {
+            if (_leftOverBytesCount > 0)
+            {
+                int count = Convert.ToBase64CharArray(_leftOverBytes, 0, _leftOverBytesCount, _charsLine, 0);
+                WriteChars(_charsLine, 0, count);
+                _leftOverBytesCount = 0;
+            }
+        }
+
+        private void WriteChars(char[] chars, int index, int count)
+        {
+            _writer.Write(chars, index, count);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs b/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs
new file mode 100644
index 0000000..c299c8b
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/BidirectionalDictionary.cs
@@ -0,0 +1,93 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class BidirectionalDictionary<TFirst, TSecond>
+    {
+        private readonly IDictionary<TFirst, TSecond> _firstToSecond;
+        private readonly IDictionary<TSecond, TFirst> _secondToFirst;
+        private readonly string _duplicateFirstErrorMessage;
+        private readonly string _duplicateSecondErrorMessage;
+
+        public BidirectionalDictionary()
+            : this(EqualityComparer<TFirst>.Default, EqualityComparer<TSecond>.Default)
+        {
+        }
+
+        public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer)
+            : this(
+                firstEqualityComparer,
+                secondEqualityComparer,
+                "Duplicate item already exists for '{0}'.",
+                "Duplicate item already exists for '{0}'.")
+        {
+        }
+
+        public BidirectionalDictionary(IEqualityComparer<TFirst> firstEqualityComparer, IEqualityComparer<TSecond> secondEqualityComparer,
+            string duplicateFirstErrorMessage, string duplicateSecondErrorMessage)
+        {
+            _firstToSecond = new Dictionary<TFirst, TSecond>(firstEqualityComparer);
+            _secondToFirst = new Dictionary<TSecond, TFirst>(secondEqualityComparer);
+            _duplicateFirstErrorMessage = duplicateFirstErrorMessage;
+            _duplicateSecondErrorMessage = duplicateSecondErrorMessage;
+        }
+
+        public void Set(TFirst first, TSecond second)
+        {
+            TFirst existingFirst;
+            TSecond existingSecond;
+
+            if (_firstToSecond.TryGetValue(first, out existingSecond))
+            {
+                if (!existingSecond.Equals(second))
+                    throw new ArgumentException(_duplicateFirstErrorMessage.FormatWith(CultureInfo.InvariantCulture, first));
+            }
+
+            if (_secondToFirst.TryGetValue(second, out existingFirst))
+            {
+                if (!existingFirst.Equals(first))
+                    throw new ArgumentException(_duplicateSecondErrorMessage.FormatWith(CultureInfo.InvariantCulture, second));
+            }
+
+            _firstToSecond.Add(first, second);
+            _secondToFirst.Add(second, first);
+        }
+
+        public bool TryGetByFirst(TFirst first, out TSecond second)
+        {
+            return _firstToSecond.TryGetValue(first, out second);
+        }
+
+        public bool TryGetBySecond(TSecond second, out TFirst first)
+        {
+            return _secondToFirst.TryGetValue(second, out first);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/CollectionUtils.cs b/Newtonsoft.Json/Utilities/CollectionUtils.cs
new file mode 100644
index 0000000..fe7c5bc
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/CollectionUtils.cs
@@ -0,0 +1,281 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Reflection;
+using System.Text;
+using System.Collections;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class CollectionUtils
+    {
+        /// <summary>
+        /// Determines whether the collection is null or empty.
+        /// </summary>
+        /// <param name="collection">The collection.</param>
+        /// <returns>
+        /// 	<c>true</c> if the collection is null or empty; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsNullOrEmpty<T>(ICollection<T> collection)
+        {
+            if (collection != null)
+            {
+                return (collection.Count == 0);
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// Adds the elements of the specified collection to the specified generic IList.
+        /// </summary>
+        /// <param name="initial">The list to add to.</param>
+        /// <param name="collection">The collection of elements to add.</param>
+        public static void AddRange<T>(this IList<T> initial, IEnumerable<T> collection)
+        {
+            if (initial == null)
+                throw new ArgumentNullException("initial");
+
+            if (collection == null)
+                return;
+
+            foreach (T value in collection)
+            {
+                initial.Add(value);
+            }
+        }
+
+#if (NET20 || NET35 || PORTABLE40)
+        public static void AddRange<T>(this IList<T> initial, IEnumerable collection)
+        {
+            ValidationUtils.ArgumentNotNull(initial, "initial");
+
+            // because earlier versions of .NET didn't support covariant generics
+            initial.AddRange(collection.Cast<T>());
+        }
+#endif
+
+        public static bool IsDictionaryType(Type type)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+
+            if (typeof(IDictionary).IsAssignableFrom(type))
+                return true;
+            if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IDictionary<,>)))
+                return true;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            if (ReflectionUtils.ImplementsGenericDefinition(type, typeof(IReadOnlyDictionary<,>)))
+                return true;
+#endif
+
+            return false;
+        }
+
+        public static ConstructorInfo ResolveEnumableCollectionConstructor(Type collectionType, Type collectionItemType)
+        {
+            Type genericEnumerable = typeof(IEnumerable<>).MakeGenericType(collectionItemType);
+
+            foreach (ConstructorInfo constructor in collectionType.GetConstructors(BindingFlags.Public | BindingFlags.Instance))
+            {
+                IList<ParameterInfo> parameters = constructor.GetParameters();
+
+                if (parameters.Count == 1)
+                {
+                    if (genericEnumerable.IsAssignableFrom(parameters[0].ParameterType))
+                        return constructor;
+                }
+            }
+
+            return null;
+        }
+
+        public static bool AddDistinct<T>(this IList<T> list, T value)
+        {
+            return list.AddDistinct(value, EqualityComparer<T>.Default);
+        }
+
+        public static bool AddDistinct<T>(this IList<T> list, T value, IEqualityComparer<T> comparer)
+        {
+            if (list.ContainsValue(value, comparer))
+                return false;
+
+            list.Add(value);
+            return true;
+        }
+
+        // this is here because LINQ Bridge doesn't support Contains with IEqualityComparer<T>
+        public static bool ContainsValue<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
+        {
+            if (comparer == null)
+                comparer = EqualityComparer<TSource>.Default;
+
+            if (source == null)
+                throw new ArgumentNullException("source");
+
+            foreach (TSource local in source)
+            {
+                if (comparer.Equals(local, value))
+                    return true;
+            }
+
+            return false;
+        }
+
+        public static bool AddRangeDistinct<T>(this IList<T> list, IEnumerable<T> values, IEqualityComparer<T> comparer)
+        {
+            bool allAdded = true;
+            foreach (T value in values)
+            {
+                if (!list.AddDistinct(value, comparer))
+                    allAdded = false;
+            }
+
+            return allAdded;
+        }
+
+        public static int IndexOf<T>(this IEnumerable<T> collection, Func<T, bool> predicate)
+        {
+            int index = 0;
+            foreach (T value in collection)
+            {
+                if (predicate(value))
+                    return index;
+
+                index++;
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer.
+        /// </summary>
+        /// <typeparam name="TSource">The type of the elements of source.</typeparam>
+        /// <param name="list">A sequence in which to locate a value.</param>
+        /// <param name="value">The object to locate in the sequence</param>
+        /// <param name="comparer">An equality comparer to compare values.</param>
+        /// <returns>The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, �1.</returns>
+        public static int IndexOf<TSource>(this IEnumerable<TSource> list, TSource value, IEqualityComparer<TSource> comparer)
+        {
+            int index = 0;
+            foreach (TSource item in list)
+            {
+                if (comparer.Equals(item, value))
+                {
+                    return index;
+                }
+                index++;
+            }
+            return -1;
+        }
+
+        private static IList<int> GetDimensions(IList values)
+        {
+            IList<int> dimensions = new List<int>();
+
+            IList currentArray = values;
+            while (true)
+            {
+                dimensions.Add(currentArray.Count);
+                if (currentArray.Count == 0)
+                    break;
+
+                object v = currentArray[0];
+                if (v is IList)
+                    currentArray = (IList)v;
+                else
+                    break;
+            }
+
+            return dimensions;
+        }
+
+        private static void CopyFromJaggedToMultidimensionalArray(IList values, Array multidimensionalArray, int[] indices)
+        {
+            int dimension = indices.Length;
+            if (dimension == multidimensionalArray.Rank)
+            {
+                multidimensionalArray.SetValue(JaggedArrayGetValue(values, indices), indices);
+                return;
+            }
+
+            int dimensionLength = multidimensionalArray.GetLength(dimension);
+            IList list = (IList)JaggedArrayGetValue(values, indices);
+            int currentValuesLength = list.Count;
+            if (currentValuesLength != dimensionLength)
+                throw new Exception("Cannot deserialize non-cubical array as multidimensional array.");
+
+            int[] newIndices = new int[dimension + 1];
+            for (int i = 0; i < dimension; i++)
+            {
+                newIndices[i] = indices[i];
+            }
+
+            for (int i = 0; i < multidimensionalArray.GetLength(dimension); i++)
+            {
+                newIndices[dimension] = i;
+                CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, newIndices);
+            }
+        }
+
+        private static object JaggedArrayGetValue(IList values, int[] indices)
+        {
+            IList currentList = values;
+            for (int i = 0; i < indices.Length; i++)
+            {
+                int index = indices[i];
+                if (i == indices.Length - 1)
+                    return currentList[index];
+                else
+                    currentList = (IList)currentList[index];
+            }
+            return currentList;
+        }
+
+        public static Array ToMultidimensionalArray(IList values, Type type, int rank)
+        {
+            IList<int> dimensions = GetDimensions(values);
+
+            while (dimensions.Count < rank)
+            {
+                dimensions.Add(0);
+            }
+
+            Array multidimensionalArray = Array.CreateInstance(type, dimensions.ToArray());
+            CopyFromJaggedToMultidimensionalArray(values, multidimensionalArray, new int[0]);
+
+            return multidimensionalArray;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/CollectionWrapper.cs b/Newtonsoft.Json/Utilities/CollectionWrapper.cs
new file mode 100644
index 0000000..5b4544d
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/CollectionWrapper.cs
@@ -0,0 +1,282 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Threading;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal interface IWrappedCollection : IList
+    {
+        object UnderlyingCollection { get; }
+    }
+
+    internal class CollectionWrapper<T> : ICollection<T>, IWrappedCollection
+    {
+        private readonly IList _list;
+        private readonly ICollection<T> _genericCollection;
+        private object _syncRoot;
+
+        public CollectionWrapper(IList list)
+        {
+            ValidationUtils.ArgumentNotNull(list, "list");
+
+            if (list is ICollection<T>)
+                _genericCollection = (ICollection<T>)list;
+            else
+                _list = list;
+        }
+
+        public CollectionWrapper(ICollection<T> list)
+        {
+            ValidationUtils.ArgumentNotNull(list, "list");
+
+            _genericCollection = list;
+        }
+
+        public virtual void Add(T item)
+        {
+            if (_genericCollection != null)
+                _genericCollection.Add(item);
+            else
+                _list.Add(item);
+        }
+
+        public virtual void Clear()
+        {
+            if (_genericCollection != null)
+                _genericCollection.Clear();
+            else
+                _list.Clear();
+        }
+
+        public virtual bool Contains(T item)
+        {
+            if (_genericCollection != null)
+                return _genericCollection.Contains(item);
+            else
+                return _list.Contains(item);
+        }
+
+        public virtual void CopyTo(T[] array, int arrayIndex)
+        {
+            if (_genericCollection != null)
+                _genericCollection.CopyTo(array, arrayIndex);
+            else
+                _list.CopyTo(array, arrayIndex);
+        }
+
+        public virtual int Count
+        {
+            get
+            {
+                if (_genericCollection != null)
+                    return _genericCollection.Count;
+                else
+                    return _list.Count;
+            }
+        }
+
+        public virtual bool IsReadOnly
+        {
+            get
+            {
+                if (_genericCollection != null)
+                    return _genericCollection.IsReadOnly;
+                else
+                    return _list.IsReadOnly;
+            }
+        }
+
+        public virtual bool Remove(T item)
+        {
+            if (_genericCollection != null)
+            {
+                return _genericCollection.Remove(item);
+            }
+            else
+            {
+                bool contains = _list.Contains(item);
+
+                if (contains)
+                    _list.Remove(item);
+
+                return contains;
+            }
+        }
+
+        public virtual IEnumerator<T> GetEnumerator()
+        {
+            if (_genericCollection != null)
+                return _genericCollection.GetEnumerator();
+
+            return _list.Cast<T>().GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            if (_genericCollection != null)
+                return _genericCollection.GetEnumerator();
+            else
+                return _list.GetEnumerator();
+        }
+
+        int IList.Add(object value)
+        {
+            VerifyValueType(value);
+            Add((T)value);
+
+            return (Count - 1);
+        }
+
+        bool IList.Contains(object value)
+        {
+            if (IsCompatibleObject(value))
+                return Contains((T)value);
+
+            return false;
+        }
+
+        int IList.IndexOf(object value)
+        {
+            if (_genericCollection != null)
+                throw new InvalidOperationException("Wrapped ICollection<T> does not support IndexOf.");
+
+            if (IsCompatibleObject(value))
+                return _list.IndexOf((T)value);
+
+            return -1;
+        }
+
+        void IList.RemoveAt(int index)
+        {
+            if (_genericCollection != null)
+                throw new InvalidOperationException("Wrapped ICollection<T> does not support RemoveAt.");
+
+            _list.RemoveAt(index);
+        }
+
+        void IList.Insert(int index, object value)
+        {
+            if (_genericCollection != null)
+                throw new InvalidOperationException("Wrapped ICollection<T> does not support Insert.");
+
+            VerifyValueType(value);
+            _list.Insert(index, (T)value);
+        }
+
+        bool IList.IsFixedSize
+        {
+            get
+            {
+                if (_genericCollection != null)
+                    // ICollection<T> only has IsReadOnly
+                    return _genericCollection.IsReadOnly;
+                else
+                    return _list.IsFixedSize;
+            }
+        }
+
+        void IList.Remove(object value)
+        {
+            if (IsCompatibleObject(value))
+                Remove((T)value);
+        }
+
+        object IList.this[int index]
+        {
+            get
+            {
+                if (_genericCollection != null)
+                    throw new InvalidOperationException("Wrapped ICollection<T> does not support indexer.");
+
+                return _list[index];
+            }
+            set
+            {
+                if (_genericCollection != null)
+                    throw new InvalidOperationException("Wrapped ICollection<T> does not support indexer.");
+
+                VerifyValueType(value);
+                _list[index] = (T)value;
+            }
+        }
+
+        void ICollection.CopyTo(Array array, int arrayIndex)
+        {
+            CopyTo((T[])array, arrayIndex);
+        }
+
+        bool ICollection.IsSynchronized
+        {
+            get { return false; }
+        }
+
+        object ICollection.SyncRoot
+        {
+            get
+            {
+                if (_syncRoot == null)
+                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
+
+                return _syncRoot;
+            }
+        }
+
+        private static void VerifyValueType(object value)
+        {
+            if (!IsCompatibleObject(value))
+                throw new ArgumentException("The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, value, typeof(T)), "value");
+        }
+
+        private static bool IsCompatibleObject(object value)
+        {
+            if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T)))))
+                return false;
+
+            return true;
+        }
+
+        public object UnderlyingCollection
+        {
+            get
+            {
+                if (_genericCollection != null)
+                    return _genericCollection;
+                else
+                    return _list;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ConvertUtils.cs b/Newtonsoft.Json/Utilities/ConvertUtils.cs
new file mode 100644
index 0000000..a022a0b
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ConvertUtils.cs
@@ -0,0 +1,763 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.ComponentModel;
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+using System.Numerics;
+#endif
+using System.Text;
+using Newtonsoft.Json.Serialization;
+using System.Reflection;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System.Data.SqlTypes;
+
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal enum PrimitiveTypeCode
+    {
+        Empty,
+        Object,
+        Char,
+        CharNullable,
+        Boolean,
+        BooleanNullable,
+        SByte,
+        SByteNullable,
+        Int16,
+        Int16Nullable,
+        UInt16,
+        UInt16Nullable,
+        Int32,
+        Int32Nullable,
+        Byte,
+        ByteNullable,
+        UInt32,
+        UInt32Nullable,
+        Int64,
+        Int64Nullable,
+        UInt64,
+        UInt64Nullable,
+        Single,
+        SingleNullable,
+        Double,
+        DoubleNullable,
+        DateTime,
+        DateTimeNullable,
+#if !NET20
+        DateTimeOffset,
+        DateTimeOffsetNullable,
+#endif
+        Decimal,
+        DecimalNullable,
+        Guid,
+        GuidNullable,
+        TimeSpan,
+        TimeSpanNullable,
+#if !(PORTABLE || NET35 || NET20)
+        BigInteger,
+        BigIntegerNullable,
+#endif
+        Uri,
+        String,
+        Bytes,
+        DBNull
+    }
+
+    internal class TypeInformation
+    {
+        public Type Type { get; set; }
+        public PrimitiveTypeCode TypeCode { get; set; }
+    }
+
+    internal enum ParseResult
+    {
+        None,
+        Success,
+        Overflow,
+        Invalid
+    }
+
+    internal static class ConvertUtils
+    {
+        private static readonly Dictionary<Type, PrimitiveTypeCode> TypeCodeMap =
+            new Dictionary<Type, PrimitiveTypeCode>
+            {
+                { typeof(char), PrimitiveTypeCode.Char },
+                { typeof(char?), PrimitiveTypeCode.CharNullable },
+                { typeof(bool), PrimitiveTypeCode.Boolean },
+                { typeof(bool?), PrimitiveTypeCode.BooleanNullable },
+                { typeof(sbyte), PrimitiveTypeCode.SByte },
+                { typeof(sbyte?), PrimitiveTypeCode.SByteNullable },
+                { typeof(short), PrimitiveTypeCode.Int16 },
+                { typeof(short?), PrimitiveTypeCode.Int16Nullable },
+                { typeof(ushort), PrimitiveTypeCode.UInt16 },
+                { typeof(ushort?), PrimitiveTypeCode.UInt16Nullable },
+                { typeof(int), PrimitiveTypeCode.Int32 },
+                { typeof(int?), PrimitiveTypeCode.Int32Nullable },
+                { typeof(byte), PrimitiveTypeCode.Byte },
+                { typeof(byte?), PrimitiveTypeCode.ByteNullable },
+                { typeof(uint), PrimitiveTypeCode.UInt32 },
+                { typeof(uint?), PrimitiveTypeCode.UInt32Nullable },
+                { typeof(long), PrimitiveTypeCode.Int64 },
+                { typeof(long?), PrimitiveTypeCode.Int64Nullable },
+                { typeof(ulong), PrimitiveTypeCode.UInt64 },
+                { typeof(ulong?), PrimitiveTypeCode.UInt64Nullable },
+                { typeof(float), PrimitiveTypeCode.Single },
+                { typeof(float?), PrimitiveTypeCode.SingleNullable },
+                { typeof(double), PrimitiveTypeCode.Double },
+                { typeof(double?), PrimitiveTypeCode.DoubleNullable },
+                { typeof(DateTime), PrimitiveTypeCode.DateTime },
+                { typeof(DateTime?), PrimitiveTypeCode.DateTimeNullable },
+#if !NET20
+                { typeof(DateTimeOffset), PrimitiveTypeCode.DateTimeOffset },
+                { typeof(DateTimeOffset?), PrimitiveTypeCode.DateTimeOffsetNullable },
+#endif
+                { typeof(decimal), PrimitiveTypeCode.Decimal },
+                { typeof(decimal?), PrimitiveTypeCode.DecimalNullable },
+                { typeof(Guid), PrimitiveTypeCode.Guid },
+                { typeof(Guid?), PrimitiveTypeCode.GuidNullable },
+                { typeof(TimeSpan), PrimitiveTypeCode.TimeSpan },
+                { typeof(TimeSpan?), PrimitiveTypeCode.TimeSpanNullable },
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+                { typeof(BigInteger), PrimitiveTypeCode.BigInteger },
+                { typeof(BigInteger?), PrimitiveTypeCode.BigIntegerNullable },
+#endif
+                { typeof(Uri), PrimitiveTypeCode.Uri },
+                { typeof(string), PrimitiveTypeCode.String },
+                { typeof(byte[]), PrimitiveTypeCode.Bytes },
+#if !(PORTABLE || PORTABLE40 || NETFX_CORE)
+                { typeof(DBNull), PrimitiveTypeCode.DBNull }
+#endif
+            };
+
+        private static readonly List<TypeInformation> PrimitiveTypeCodes = new List<TypeInformation>
+        {
+            new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty },
+            new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Object },
+            new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.DBNull },
+            new TypeInformation { Type = typeof(bool), TypeCode = PrimitiveTypeCode.Boolean },
+            new TypeInformation { Type = typeof(char), TypeCode = PrimitiveTypeCode.Char },
+            new TypeInformation { Type = typeof(sbyte), TypeCode = PrimitiveTypeCode.SByte },
+            new TypeInformation { Type = typeof(byte), TypeCode = PrimitiveTypeCode.Byte },
+            new TypeInformation { Type = typeof(short), TypeCode = PrimitiveTypeCode.Int16 },
+            new TypeInformation { Type = typeof(ushort), TypeCode = PrimitiveTypeCode.UInt16 },
+            new TypeInformation { Type = typeof(int), TypeCode = PrimitiveTypeCode.Int32 },
+            new TypeInformation { Type = typeof(uint), TypeCode = PrimitiveTypeCode.UInt32 },
+            new TypeInformation { Type = typeof(long), TypeCode = PrimitiveTypeCode.Int64 },
+            new TypeInformation { Type = typeof(ulong), TypeCode = PrimitiveTypeCode.UInt64 },
+            new TypeInformation { Type = typeof(float), TypeCode = PrimitiveTypeCode.Single },
+            new TypeInformation { Type = typeof(double), TypeCode = PrimitiveTypeCode.Double },
+            new TypeInformation { Type = typeof(decimal), TypeCode = PrimitiveTypeCode.Decimal },
+            new TypeInformation { Type = typeof(DateTime), TypeCode = PrimitiveTypeCode.DateTime },
+            new TypeInformation { Type = typeof(object), TypeCode = PrimitiveTypeCode.Empty }, // no 17 in TypeCode for some reason
+            new TypeInformation { Type = typeof(string), TypeCode = PrimitiveTypeCode.String }
+        };
+
+        public static PrimitiveTypeCode GetTypeCode(Type t)
+        {
+            PrimitiveTypeCode typeCode;
+            if (TypeCodeMap.TryGetValue(t, out typeCode))
+                return typeCode;
+
+            if (t.IsEnum())
+                return GetTypeCode(Enum.GetUnderlyingType(t));
+
+            // performance?
+            if (ReflectionUtils.IsNullableType(t))
+            {
+                Type nonNullable = Nullable.GetUnderlyingType(t);
+                if (nonNullable.IsEnum())
+                {
+                    Type nullableUnderlyingType = typeof(Nullable<>).MakeGenericType(Enum.GetUnderlyingType(nonNullable));
+                    return GetTypeCode(nullableUnderlyingType);
+                }
+            }
+
+            return PrimitiveTypeCode.Object;
+        }
+
+        public static PrimitiveTypeCode GetTypeCode(object o)
+        {
+            return GetTypeCode(o.GetType());
+        }
+
+#if !(NETFX_CORE || PORTABLE)
+        public static TypeInformation GetTypeInformation(IConvertible convertable)
+        {
+            TypeInformation typeInformation = PrimitiveTypeCodes[(int)convertable.GetTypeCode()];
+            return typeInformation;
+        }
+#endif
+
+        public static bool IsConvertible(Type t)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return typeof(IConvertible).IsAssignableFrom(t);
+#else
+      return (
+        t == typeof(bool) || t == typeof(byte) || t == typeof(char) || t == typeof(DateTime) || t == typeof(decimal) || t == typeof(double) || t == typeof(short) || t == typeof(int) ||
+        t == typeof(long) || t == typeof(sbyte) || t == typeof(float) || t == typeof(string) || t == typeof(ushort) || t == typeof(uint) || t == typeof(ulong) || t.IsEnum());
+#endif
+        }
+
+        public static TimeSpan ParseTimeSpan(string input)
+        {
+#if !(NET35 || NET20)
+            return TimeSpan.Parse(input, CultureInfo.InvariantCulture);
+#else
+            return TimeSpan.Parse(input);
+#endif
+        }
+
+        internal struct TypeConvertKey : IEquatable<TypeConvertKey>
+        {
+            private readonly Type _initialType;
+            private readonly Type _targetType;
+
+            public Type InitialType
+            {
+                get { return _initialType; }
+            }
+
+            public Type TargetType
+            {
+                get { return _targetType; }
+            }
+
+            public TypeConvertKey(Type initialType, Type targetType)
+            {
+                _initialType = initialType;
+                _targetType = targetType;
+            }
+
+            public override int GetHashCode()
+            {
+                return _initialType.GetHashCode() ^ _targetType.GetHashCode();
+            }
+
+            public override bool Equals(object obj)
+            {
+                if (!(obj is TypeConvertKey))
+                    return false;
+
+                return Equals((TypeConvertKey)obj);
+            }
+
+            public bool Equals(TypeConvertKey other)
+            {
+                return (_initialType == other._initialType && _targetType == other._targetType);
+            }
+        }
+
+        private static readonly ThreadSafeStore<TypeConvertKey, Func<object, object>> CastConverters =
+            new ThreadSafeStore<TypeConvertKey, Func<object, object>>(CreateCastConverter);
+
+        private static Func<object, object> CreateCastConverter(TypeConvertKey t)
+        {
+            MethodInfo castMethodInfo = t.TargetType.GetMethod("op_Implicit", new[] { t.InitialType });
+            if (castMethodInfo == null)
+                castMethodInfo = t.TargetType.GetMethod("op_Explicit", new[] { t.InitialType });
+
+            if (castMethodInfo == null)
+                return null;
+
+            MethodCall<object, object> call = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(castMethodInfo);
+
+            return o => call(null, o);
+        }
+
+#if !(NET20 || NET35 || PORTABLE || PORTABLE40)
+        internal static BigInteger ToBigInteger(object value)
+        {
+            if (value is BigInteger)
+                return (BigInteger)value;
+            if (value is string)
+                return BigInteger.Parse((string)value, CultureInfo.InvariantCulture);
+            if (value is float)
+                return new BigInteger((float)value);
+            if (value is double)
+                return new BigInteger((double)value);
+            if (value is decimal)
+                return new BigInteger((decimal)value);
+            if (value is int)
+                return new BigInteger((int)value);
+            if (value is long)
+                return new BigInteger((long)value);
+            if (value is uint)
+                return new BigInteger((uint)value);
+            if (value is ulong)
+                return new BigInteger((ulong)value);
+            if (value is byte[])
+                return new BigInteger((byte[])value);
+
+            throw new InvalidCastException("Cannot convert {0} to BigInteger.".FormatWith(CultureInfo.InvariantCulture, value.GetType()));
+        }
+
+        public static object FromBigInteger(BigInteger i, Type targetType)
+        {
+            if (targetType == typeof(decimal))
+                return (decimal)i;
+            if (targetType == typeof(double))
+                return (double)i;
+            if (targetType == typeof(float))
+                return (float)i;
+            if (targetType == typeof(ulong))
+                return (ulong)i;
+
+            try
+            {
+                return System.Convert.ChangeType((long)i, targetType, CultureInfo.InvariantCulture);
+            }
+            catch (Exception ex)
+            {
+                throw new InvalidOperationException("Can not convert from BigInteger to {0}.".FormatWith(CultureInfo.InvariantCulture, targetType), ex);
+            }
+        }
+#endif
+
+        #region TryConvert
+        internal enum ConvertResult
+        {
+            Success,
+            CannotConvertNull,
+            NotInstantiableType,
+            NoValidConversion
+        }
+
+        public static object Convert(object initialValue, CultureInfo culture, Type targetType)
+        {
+            object value;
+            switch (TryConvertInternal(initialValue, culture, targetType, out value))
+            {
+                case ConvertResult.Success:
+                    return value;
+                case ConvertResult.CannotConvertNull:
+                    throw new Exception("Can not convert null {0} into non-nullable {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType));
+                case ConvertResult.NotInstantiableType:
+                    throw new ArgumentException("Target type {0} is not a value type or a non-abstract class.".FormatWith(CultureInfo.InvariantCulture, targetType), "targetType");
+                case ConvertResult.NoValidConversion:
+                    throw new InvalidOperationException("Can not convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, initialValue.GetType(), targetType));
+                default:
+                    throw new InvalidOperationException("Unexpected conversion result.");
+            }
+        }
+
+        private static bool TryConvert(object initialValue, CultureInfo culture, Type targetType, out object value)
+        {
+            try
+            {
+                if (TryConvertInternal(initialValue, culture, targetType, out value) == ConvertResult.Success)
+                    return true;
+
+                value = null;
+                return false;
+            }
+            catch
+            {
+                value = null;
+                return false;
+            }
+        }
+
+        private static ConvertResult TryConvertInternal(object initialValue, CultureInfo culture, Type targetType, out object value)
+        {
+            if (initialValue == null)
+                throw new ArgumentNullException("initialValue");
+
+            if (ReflectionUtils.IsNullableType(targetType))
+                targetType = Nullable.GetUnderlyingType(targetType);
+
+            Type initialType = initialValue.GetType();
+
+            if (targetType == initialType)
+            {
+                value = initialValue;
+                return ConvertResult.Success;
+            }
+
+            // use Convert.ChangeType if both types are IConvertible
+            if (ConvertUtils.IsConvertible(initialValue.GetType()) && ConvertUtils.IsConvertible(targetType))
+            {
+                if (targetType.IsEnum())
+                {
+                    if (initialValue is string)
+                    {
+                        value = Enum.Parse(targetType, initialValue.ToString(), true);
+                        return ConvertResult.Success;
+                    }
+                    else if (IsInteger(initialValue))
+                    {
+                        value = Enum.ToObject(targetType, initialValue);
+                        return ConvertResult.Success;
+                    }
+                }
+
+                value = System.Convert.ChangeType(initialValue, targetType, culture);
+                return ConvertResult.Success;
+            }
+
+#if !NET20
+            if (initialValue is DateTime && targetType == typeof(DateTimeOffset))
+            {
+                value = new DateTimeOffset((DateTime)initialValue);
+                return ConvertResult.Success;
+            }
+#endif
+
+            if (initialValue is byte[] && targetType == typeof(Guid))
+            {
+                value = new Guid((byte[])initialValue);
+                return ConvertResult.Success;
+            }
+
+            if (initialValue is string)
+            {
+                if (targetType == typeof(Guid))
+                {
+                    value = new Guid((string)initialValue);
+                    return ConvertResult.Success;
+                }
+                if (targetType == typeof(Uri))
+                {
+                    value = new Uri((string)initialValue, UriKind.RelativeOrAbsolute);
+                    return ConvertResult.Success;
+                }
+                if (targetType == typeof(TimeSpan))
+                {
+                    value = ParseTimeSpan((string)initialValue);
+                    return ConvertResult.Success;
+                }
+                if (targetType == typeof(byte[]))
+                {
+                    value = System.Convert.FromBase64String((string)initialValue);
+                    return ConvertResult.Success;
+                }
+                if (typeof(Type).IsAssignableFrom(targetType))
+                {
+                    value = Type.GetType((string)initialValue, true);
+                    return ConvertResult.Success;
+                }
+            }
+
+#if !(NET20 || NET35 || PORTABLE40 || PORTABLE)
+            if (targetType == typeof(BigInteger))
+            {
+                value = ToBigInteger(initialValue);
+                return ConvertResult.Success;
+            }
+            if (initialValue is BigInteger)
+            {
+                value = FromBigInteger((BigInteger)initialValue, targetType);
+                return ConvertResult.Success;
+            }
+#endif
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            // see if source or target types have a TypeConverter that converts between the two
+            TypeConverter toConverter = GetConverter(initialType);
+
+            if (toConverter != null && toConverter.CanConvertTo(targetType))
+            {
+                value = toConverter.ConvertTo(null, culture, initialValue, targetType);
+                return ConvertResult.Success;
+            }
+
+            TypeConverter fromConverter = GetConverter(targetType);
+
+            if (fromConverter != null && fromConverter.CanConvertFrom(initialType))
+            {
+                value = fromConverter.ConvertFrom(null, culture, initialValue);
+                return ConvertResult.Success;
+            }
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            // handle DBNull and INullable
+            if (initialValue == DBNull.Value)
+            {
+                if (ReflectionUtils.IsNullable(targetType))
+                {
+                    value = EnsureTypeAssignable(null, initialType, targetType);
+                    return ConvertResult.Success;
+                }
+
+                // cannot convert null to non-nullable
+                value = null;
+                return ConvertResult.CannotConvertNull;
+            }
+#endif
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            if (initialValue is INullable)
+            {
+                value = EnsureTypeAssignable(ToValue((INullable)initialValue), initialType, targetType);
+                return ConvertResult.Success;
+            }
+#endif
+
+            if (targetType.IsInterface() || targetType.IsGenericTypeDefinition() || targetType.IsAbstract())
+            {
+                value = null;
+                return ConvertResult.NotInstantiableType;
+            }
+
+            value = null;
+            return ConvertResult.NoValidConversion;
+        }
+        #endregion
+
+        #region ConvertOrCast
+        /// <summary>
+        /// Converts the value to the specified type. If the value is unable to be converted, the
+        /// value is checked whether it assignable to the specified type.
+        /// </summary>
+        /// <param name="initialValue">The value to convert.</param>
+        /// <param name="culture">The culture to use when converting.</param>
+        /// <param name="targetType">The type to convert or cast the value to.</param>
+        /// <returns>
+        /// The converted type. If conversion was unsuccessful, the initial value
+        /// is returned if assignable to the target type.
+        /// </returns>
+        public static object ConvertOrCast(object initialValue, CultureInfo culture, Type targetType)
+        {
+            object convertedValue;
+
+            if (targetType == typeof(object))
+                return initialValue;
+
+            if (initialValue == null && ReflectionUtils.IsNullable(targetType))
+                return null;
+
+            if (TryConvert(initialValue, culture, targetType, out convertedValue))
+                return convertedValue;
+
+            return EnsureTypeAssignable(initialValue, ReflectionUtils.GetObjectType(initialValue), targetType);
+        }
+        #endregion
+
+        private static object EnsureTypeAssignable(object value, Type initialType, Type targetType)
+        {
+            Type valueType = (value != null) ? value.GetType() : null;
+
+            if (value != null)
+            {
+                if (targetType.IsAssignableFrom(valueType))
+                    return value;
+
+                Func<object, object> castConverter = CastConverters.Get(new TypeConvertKey(valueType, targetType));
+                if (castConverter != null)
+                    return castConverter(value);
+            }
+            else
+            {
+                if (ReflectionUtils.IsNullable(targetType))
+                    return null;
+            }
+
+            throw new ArgumentException("Could not cast or convert from {0} to {1}.".FormatWith(CultureInfo.InvariantCulture, (initialType != null) ? initialType.ToString() : "{null}", targetType));
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        public static object ToValue(INullable nullableValue)
+        {
+            if (nullableValue == null)
+                return null;
+            else if (nullableValue is SqlInt32)
+                return ToValue((SqlInt32)nullableValue);
+            else if (nullableValue is SqlInt64)
+                return ToValue((SqlInt64)nullableValue);
+            else if (nullableValue is SqlBoolean)
+                return ToValue((SqlBoolean)nullableValue);
+            else if (nullableValue is SqlString)
+                return ToValue((SqlString)nullableValue);
+            else if (nullableValue is SqlDateTime)
+                return ToValue((SqlDateTime)nullableValue);
+
+            throw new ArgumentException("Unsupported INullable type: {0}".FormatWith(CultureInfo.InvariantCulture, nullableValue.GetType()));
+        }
+#endif
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        internal static TypeConverter GetConverter(Type t)
+        {
+            return JsonTypeReflector.GetTypeConverter(t);
+        }
+#endif
+
+        public static bool IsInteger(object value)
+        {
+            switch (GetTypeCode(value))
+            {
+                case PrimitiveTypeCode.SByte:
+                case PrimitiveTypeCode.Byte:
+                case PrimitiveTypeCode.Int16:
+                case PrimitiveTypeCode.UInt16:
+                case PrimitiveTypeCode.Int32:
+                case PrimitiveTypeCode.UInt32:
+                case PrimitiveTypeCode.Int64:
+                case PrimitiveTypeCode.UInt64:
+                    return true;
+                default:
+                    return false;
+            }
+        }
+
+        public static ParseResult Int32TryParse(char[] chars, int start, int length, out int value)
+        {
+            value = 0;
+
+            if (length == 0)
+                return ParseResult.Invalid;
+
+            bool isNegative = (chars[start] == '-');
+
+            if (isNegative)
+            {
+                // text just a negative sign
+                if (length == 1)
+                    return ParseResult.Invalid;
+
+                start++;
+                length--;
+            }
+
+            int end = start + length;
+
+            for (int i = start; i < end; i++)
+            {
+                int c = chars[i] - '0';
+
+                if (c < 0 || c > 9)
+                    return ParseResult.Invalid;
+
+                int newValue = (10 * value) - c;
+
+                // overflow has caused the number to loop around
+                if (newValue > value)
+                {
+                    i++;
+
+                    // double check the rest of the string that there wasn't anything invalid
+                    // invalid result takes precedence over overflow result
+                    for (; i < end; i++)
+                    {
+                        c = chars[i] - '0';
+
+                        if (c < 0 || c > 9)
+                            return ParseResult.Invalid;
+                    }
+
+                    return ParseResult.Overflow;
+                }
+
+                value = newValue;
+            }
+
+            // go from negative to positive to avoids overflow
+            // negative can be slightly bigger than positive
+            if (!isNegative)
+            {
+                // negative integer can be one bigger than positive
+                if (value == int.MinValue)
+                    return ParseResult.Overflow;
+
+                value = -value;
+            }
+
+            return ParseResult.Success;
+        }
+
+        public static ParseResult Int64TryParse(char[] chars, int start, int length, out long value)
+        {
+            value = 0;
+
+            if (length == 0)
+                return ParseResult.Invalid;
+
+            bool isNegative = (chars[start] == '-');
+
+            if (isNegative)
+            {
+                // text just a negative sign
+                if (length == 1)
+                    return ParseResult.Invalid;
+
+                start++;
+                length--;
+            }
+
+            int end = start + length;
+
+            for (int i = start; i < end; i++)
+            {
+                int c = chars[i] - '0';
+
+                if (c < 0 || c > 9)
+                    return ParseResult.Invalid;
+
+                long newValue = (10 * value) - c;
+
+                // overflow has caused the number to loop around
+                if (newValue > value)
+                {
+                    i++;
+
+                    // double check the rest of the string that there wasn't anything invalid
+                    // invalid result takes precedence over overflow result
+                    for (; i < end; i++)
+                    {
+                        c = chars[i] - '0';
+
+                        if (c < 0 || c > 9)
+                            return ParseResult.Invalid;
+                    }
+
+                    return ParseResult.Overflow;
+                }
+
+                value = newValue;
+            }
+
+            // go from negative to positive to avoids overflow
+            // negative can be slightly bigger than positive
+            if (!isNegative)
+            {
+                // negative integer can be one bigger than positive
+                if (value == long.MinValue)
+                    return ParseResult.Overflow;
+
+                value = -value;
+            }
+
+            return ParseResult.Success;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DateTimeParser.cs b/Newtonsoft.Json/Utilities/DateTimeParser.cs
new file mode 100644
index 0000000..c7ca673
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DateTimeParser.cs
@@ -0,0 +1,265 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal enum ParserTimeZone
+    {
+        Unspecified,
+        Utc,
+        LocalWestOfUtc,
+        LocalEastOfUtc
+    }
+
+    internal struct DateTimeParser
+    {
+        static DateTimeParser()
+        {
+            Power10 = new[] { -1, 10, 100, 1000, 10000, 100000, 1000000 };
+
+            Lzyyyy = "yyyy".Length;
+            Lzyyyy_ = "yyyy-".Length;
+            Lzyyyy_MM = "yyyy-MM".Length;
+            Lzyyyy_MM_ = "yyyy-MM-".Length;
+            Lzyyyy_MM_dd = "yyyy-MM-dd".Length;
+            Lzyyyy_MM_ddT = "yyyy-MM-ddT".Length;
+            LzHH = "HH".Length;
+            LzHH_ = "HH:".Length;
+            LzHH_mm = "HH:mm".Length;
+            LzHH_mm_ = "HH:mm:".Length;
+            LzHH_mm_ss = "HH:mm:ss".Length;
+            Lz_ = "-".Length;
+            Lz_zz = "-zz".Length;
+        }
+
+        public int Year;
+        public int Month;
+        public int Day;
+        public int Hour;
+        public int Minute;
+        public int Second;
+        public int Fraction;
+        public int ZoneHour;
+        public int ZoneMinute;
+        public ParserTimeZone Zone;
+
+        private string _text;
+        private int _length;
+
+        private static readonly int[] Power10;
+
+        private static readonly int Lzyyyy;
+        private static readonly int Lzyyyy_;
+        private static readonly int Lzyyyy_MM;
+        private static readonly int Lzyyyy_MM_;
+        private static readonly int Lzyyyy_MM_dd;
+        private static readonly int Lzyyyy_MM_ddT;
+        private static readonly int LzHH;
+        private static readonly int LzHH_;
+        private static readonly int LzHH_mm;
+        private static readonly int LzHH_mm_;
+        private static readonly int LzHH_mm_ss;
+        private static readonly int Lz_;
+        private static readonly int Lz_zz;
+
+        private const short MaxFractionDigits = 7;
+
+        public bool Parse(string text)
+        {
+            _text = text;
+            _length = text.Length;
+
+            if (ParseDate(0) && ParseChar(Lzyyyy_MM_dd, 'T') && ParseTimeAndZoneAndWhitespace(Lzyyyy_MM_ddT))
+                return true;
+
+            return false;
+        }
+
+        private bool ParseDate(int start)
+        {
+            return (Parse4Digit(start, out Year)
+                    && 1 <= Year
+                    && ParseChar(start + Lzyyyy, '-')
+                    && Parse2Digit(start + Lzyyyy_, out Month)
+                    && 1 <= Month
+                    && Month <= 12
+                    && ParseChar(start + Lzyyyy_MM, '-')
+                    && Parse2Digit(start + Lzyyyy_MM_, out Day)
+                    && 1 <= Day
+                    && Day <= DateTime.DaysInMonth(Year, Month));
+        }
+
+        private bool ParseTimeAndZoneAndWhitespace(int start)
+        {
+            return (ParseTime(ref start) && ParseZone(start));
+        }
+
+        private bool ParseTime(ref int start)
+        {
+            if (!(Parse2Digit(start, out Hour)
+                  && Hour < 24
+                  && ParseChar(start + LzHH, ':')
+                  && Parse2Digit(start + LzHH_, out Minute)
+                  && Minute < 60
+                  && ParseChar(start + LzHH_mm, ':')
+                  && Parse2Digit(start + LzHH_mm_, out Second)
+                  && Second < 60))
+            {
+                return false;
+            }
+
+            start += LzHH_mm_ss;
+            if (ParseChar(start, '.'))
+            {
+                Fraction = 0;
+                int numberOfDigits = 0;
+
+                while (++start < _length && numberOfDigits < MaxFractionDigits)
+                {
+                    int digit = _text[start] - '0';
+                    if (digit < 0 || digit > 9)
+                        break;
+
+                    Fraction = (Fraction * 10) + digit;
+
+                    numberOfDigits++;
+                }
+
+                if (numberOfDigits < MaxFractionDigits)
+                {
+                    if (numberOfDigits == 0)
+                        return false;
+
+                    Fraction *= Power10[MaxFractionDigits - numberOfDigits];
+                }
+            }
+            return true;
+        }
+
+        private bool ParseZone(int start)
+        {
+            if (start < _length)
+            {
+                char ch = _text[start];
+                if (ch == 'Z' || ch == 'z')
+                {
+                    Zone = ParserTimeZone.Utc;
+                    start++;
+                }
+                else
+                {
+                    if (start + 2 < _length
+                        && Parse2Digit(start + Lz_, out ZoneHour)
+                        && ZoneHour <= 99)
+                    {
+                        switch (ch)
+                        {
+                            case '-':
+                                Zone = ParserTimeZone.LocalWestOfUtc;
+                                start += Lz_zz;
+                                break;
+
+                            case '+':
+                                Zone = ParserTimeZone.LocalEastOfUtc;
+                                start += Lz_zz;
+                                break;
+                        }
+                    }
+
+                    if (start < _length)
+                    {
+                        if (ParseChar(start, ':'))
+                        {
+                            start += 1;
+
+                            if (start + 1 < _length
+                                && Parse2Digit(start, out ZoneMinute)
+                                && ZoneMinute <= 99)
+                            {
+                                start += 2;
+                            }
+                        }
+                        else
+                        {
+                            if (start + 1 < _length
+                                && Parse2Digit(start, out ZoneMinute)
+                                && ZoneMinute <= 99)
+                            {
+                                start += 2;
+                            }
+                        }
+                    }
+                }
+            }
+
+            return (start == _length);
+        }
+
+        private bool Parse4Digit(int start, out int num)
+        {
+            if (start + 3 < _length)
+            {
+                int digit1 = _text[start] - '0';
+                int digit2 = _text[start + 1] - '0';
+                int digit3 = _text[start + 2] - '0';
+                int digit4 = _text[start + 3] - '0';
+                if (0 <= digit1 && digit1 < 10
+                    && 0 <= digit2 && digit2 < 10
+                    && 0 <= digit3 && digit3 < 10
+                    && 0 <= digit4 && digit4 < 10)
+                {
+                    num = (((((digit1 * 10) + digit2) * 10) + digit3) * 10) + digit4;
+                    return true;
+                }
+            }
+            num = 0;
+            return false;
+        }
+
+        private bool Parse2Digit(int start, out int num)
+        {
+            if (start + 1 < _length)
+            {
+                int digit1 = _text[start] - '0';
+                int digit2 = _text[start + 1] - '0';
+                if (0 <= digit1 && digit1 < 10
+                    && 0 <= digit2 && digit2 < 10)
+                {
+                    num = (digit1 * 10) + digit2;
+                    return true;
+                }
+            }
+            num = 0;
+            return false;
+        }
+
+        private bool ParseChar(int start, char ch)
+        {
+            return (start < _length && _text[start] == ch);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DateTimeUtils.cs b/Newtonsoft.Json/Utilities/DateTimeUtils.cs
new file mode 100644
index 0000000..326760f
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DateTimeUtils.cs
@@ -0,0 +1,613 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class DateTimeUtils
+    {
+        internal static readonly long InitialJavaScriptDateTicks = 621355968000000000;
+
+        private const int DaysPer100Years = 36524;
+        private const int DaysPer400Years = 146097;
+        private const int DaysPer4Years = 1461;
+        private const int DaysPerYear = 365;
+        private const long TicksPerDay = 864000000000L;
+        private static readonly int[] DaysToMonth365;
+        private static readonly int[] DaysToMonth366;
+
+        static DateTimeUtils()
+        {
+            DaysToMonth365 = new[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+            DaysToMonth366 = new[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
+        }
+
+        public static TimeSpan GetUtcOffset(this DateTime d)
+        {
+#if NET20
+      return TimeZone.CurrentTimeZone.GetUtcOffset(d);
+#else
+            return TimeZoneInfo.Local.GetUtcOffset(d);
+#endif
+        }
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+        public static XmlDateTimeSerializationMode ToSerializationMode(DateTimeKind kind)
+        {
+            switch (kind)
+            {
+                case DateTimeKind.Local:
+                    return XmlDateTimeSerializationMode.Local;
+                case DateTimeKind.Unspecified:
+                    return XmlDateTimeSerializationMode.Unspecified;
+                case DateTimeKind.Utc:
+                    return XmlDateTimeSerializationMode.Utc;
+                default:
+                    throw MiscellaneousUtils.CreateArgumentOutOfRangeException("kind", kind, "Unexpected DateTimeKind value.");
+            }
+        }
+#endif
+
+        internal static DateTime EnsureDateTime(DateTime value, DateTimeZoneHandling timeZone)
+        {
+            switch (timeZone)
+            {
+                case DateTimeZoneHandling.Local:
+                    value = SwitchToLocalTime(value);
+                    break;
+                case DateTimeZoneHandling.Utc:
+                    value = SwitchToUtcTime(value);
+                    break;
+                case DateTimeZoneHandling.Unspecified:
+                    value = new DateTime(value.Ticks, DateTimeKind.Unspecified);
+                    break;
+                case DateTimeZoneHandling.RoundtripKind:
+                    break;
+                default:
+                    throw new ArgumentException("Invalid date time handling value.");
+            }
+
+            return value;
+        }
+
+        private static DateTime SwitchToLocalTime(DateTime value)
+        {
+            switch (value.Kind)
+            {
+                case DateTimeKind.Unspecified:
+                    return new DateTime(value.Ticks, DateTimeKind.Local);
+
+                case DateTimeKind.Utc:
+                    return value.ToLocalTime();
+
+                case DateTimeKind.Local:
+                    return value;
+            }
+            return value;
+        }
+
+        private static DateTime SwitchToUtcTime(DateTime value)
+        {
+            switch (value.Kind)
+            {
+                case DateTimeKind.Unspecified:
+                    return new DateTime(value.Ticks, DateTimeKind.Utc);
+
+                case DateTimeKind.Utc:
+                    return value;
+
+                case DateTimeKind.Local:
+                    return value.ToUniversalTime();
+            }
+            return value;
+        }
+
+        private static long ToUniversalTicks(DateTime dateTime)
+        {
+            if (dateTime.Kind == DateTimeKind.Utc)
+                return dateTime.Ticks;
+
+            return ToUniversalTicks(dateTime, dateTime.GetUtcOffset());
+        }
+
+        private static long ToUniversalTicks(DateTime dateTime, TimeSpan offset)
+        {
+            // special case min and max value
+            // they never have a timezone appended to avoid issues
+            if (dateTime.Kind == DateTimeKind.Utc || dateTime == DateTime.MaxValue || dateTime == DateTime.MinValue)
+                return dateTime.Ticks;
+
+            long ticks = dateTime.Ticks - offset.Ticks;
+            if (ticks > 3155378975999999999L)
+                return 3155378975999999999L;
+
+            if (ticks < 0L)
+                return 0L;
+
+            return ticks;
+        }
+
+        internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, TimeSpan offset)
+        {
+            long universialTicks = ToUniversalTicks(dateTime, offset);
+
+            return UniversialTicksToJavaScriptTicks(universialTicks);
+        }
+
+        internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime)
+        {
+            return ConvertDateTimeToJavaScriptTicks(dateTime, true);
+        }
+
+        internal static long ConvertDateTimeToJavaScriptTicks(DateTime dateTime, bool convertToUtc)
+        {
+            long ticks = (convertToUtc) ? ToUniversalTicks(dateTime) : dateTime.Ticks;
+
+            return UniversialTicksToJavaScriptTicks(ticks);
+        }
+
+        private static long UniversialTicksToJavaScriptTicks(long universialTicks)
+        {
+            long javaScriptTicks = (universialTicks - InitialJavaScriptDateTicks) / 10000;
+
+            return javaScriptTicks;
+        }
+
+        internal static DateTime ConvertJavaScriptTicksToDateTime(long javaScriptTicks)
+        {
+            DateTime dateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc);
+
+            return dateTime;
+        }
+
+        #region Parse
+        internal static bool TryParseDateIso(string text, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, out object dt)
+        {
+            DateTimeParser dateTimeParser = new DateTimeParser();
+            if (!dateTimeParser.Parse(text))
+            {
+                dt = null;
+                return false;
+            }
+
+            DateTime d = new DateTime(dateTimeParser.Year, dateTimeParser.Month, dateTimeParser.Day, dateTimeParser.Hour, dateTimeParser.Minute, dateTimeParser.Second);
+            d = d.AddTicks(dateTimeParser.Fraction);
+
+#if !NET20
+            if (dateParseHandling == DateParseHandling.DateTimeOffset)
+            {
+                TimeSpan offset;
+
+                switch (dateTimeParser.Zone)
+                {
+                    case ParserTimeZone.Utc:
+                        offset = new TimeSpan(0L);
+                        break;
+                    case ParserTimeZone.LocalWestOfUtc:
+                        offset = new TimeSpan(-dateTimeParser.ZoneHour, -dateTimeParser.ZoneMinute, 0);
+                        break;
+                    case ParserTimeZone.LocalEastOfUtc:
+                        offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
+                        break;
+                    default:
+                        offset = TimeZoneInfo.Local.GetUtcOffset(d);
+                        break;
+                }
+
+                long ticks = d.Ticks - offset.Ticks;
+                if (ticks < 0 || ticks > 3155378975999999999)
+                {
+                    dt = null;
+                    return false;
+                }
+
+                dt = new DateTimeOffset(d, offset);
+                return true;
+            }
+            else
+#endif
+            {
+                long ticks;
+
+                switch (dateTimeParser.Zone)
+                {
+                    case ParserTimeZone.Utc:
+                        d = new DateTime(d.Ticks, DateTimeKind.Utc);
+                        break;
+
+                    case ParserTimeZone.LocalWestOfUtc:
+                    {
+                        TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
+                        ticks = d.Ticks + offset.Ticks;
+                        if (ticks <= DateTime.MaxValue.Ticks)
+                        {
+                            d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
+                        }
+                        else
+                        {
+                            ticks += d.GetUtcOffset().Ticks;
+                            if (ticks > DateTime.MaxValue.Ticks)
+                                ticks = DateTime.MaxValue.Ticks;
+
+                            d = new DateTime(ticks, DateTimeKind.Local);
+                        }
+                        break;
+                    }
+                    case ParserTimeZone.LocalEastOfUtc:
+                    {
+                        TimeSpan offset = new TimeSpan(dateTimeParser.ZoneHour, dateTimeParser.ZoneMinute, 0);
+                        ticks = d.Ticks - offset.Ticks;
+                        if (ticks >= DateTime.MinValue.Ticks)
+                        {
+                            d = new DateTime(ticks, DateTimeKind.Utc).ToLocalTime();
+                        }
+                        else
+                        {
+                            ticks += d.GetUtcOffset().Ticks;
+                            if (ticks < DateTime.MinValue.Ticks)
+                                ticks = DateTime.MinValue.Ticks;
+
+                            d = new DateTime(ticks, DateTimeKind.Local);
+                        }
+                        break;
+                    }
+                }
+
+                dt = EnsureDateTime(d, dateTimeZoneHandling);
+                return true;
+            }
+        }
+
+        internal static bool TryParseDateTime(string s, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out object dt)
+        {
+            if (s.Length > 0)
+            {
+                if (s[0] == '/')
+                {
+                    if (s.StartsWith("/Date(", StringComparison.Ordinal) && s.EndsWith(")/", StringComparison.Ordinal))
+                    {
+                        if (TryParseDateMicrosoft(s, dateParseHandling, dateTimeZoneHandling, out dt))
+                            return true;
+                    }
+                }
+                else if (s.Length >= 19 && s.Length <= 40 && char.IsDigit(s[0]) && s[10] == 'T')
+                {
+                    if (TryParseDateIso(s, dateParseHandling, dateTimeZoneHandling, out dt))
+                        return true;
+                }
+
+                if (!string.IsNullOrEmpty(dateFormatString))
+                {
+                    if (TryParseDateExact(s, dateParseHandling, dateTimeZoneHandling, dateFormatString, culture, out dt))
+                        return true;
+                }
+            }
+
+            dt = null;
+            return false;
+        }
+
+        private static bool TryParseDateMicrosoft(string text, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, out object dt)
+        {
+            string value = text.Substring(6, text.Length - 8);
+            DateTimeKind kind = DateTimeKind.Utc;
+
+            int index = value.IndexOf('+', 1);
+
+            if (index == -1)
+                index = value.IndexOf('-', 1);
+
+            TimeSpan offset = TimeSpan.Zero;
+
+            if (index != -1)
+            {
+                kind = DateTimeKind.Local;
+                offset = ReadOffset(value.Substring(index));
+                value = value.Substring(0, index);
+            }
+
+            long javaScriptTicks = long.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
+
+            DateTime utcDateTime = ConvertJavaScriptTicksToDateTime(javaScriptTicks);
+
+#if !NET20
+            if (dateParseHandling == DateParseHandling.DateTimeOffset)
+            {
+                dt = new DateTimeOffset(utcDateTime.Add(offset).Ticks, offset);
+                return true;
+            }
+            else
+#endif
+            {
+                DateTime dateTime;
+
+                switch (kind)
+                {
+                    case DateTimeKind.Unspecified:
+                        dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
+                        break;
+                    case DateTimeKind.Local:
+                        dateTime = utcDateTime.ToLocalTime();
+                        break;
+                    default:
+                        dateTime = utcDateTime;
+                        break;
+                }
+
+                dt = EnsureDateTime(dateTime, dateTimeZoneHandling);
+                return true;
+            }
+        }
+
+        private static bool TryParseDateExact(string text, DateParseHandling dateParseHandling, DateTimeZoneHandling dateTimeZoneHandling, string dateFormatString, CultureInfo culture, out object dt)
+        {
+#if !NET20
+            if (dateParseHandling == DateParseHandling.DateTimeOffset)
+            {
+                DateTimeOffset temp;
+                if (DateTimeOffset.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
+                {
+                    dt = temp;
+                    return true;
+                }
+            }
+            else
+#endif
+            {
+                DateTime temp;
+                if (DateTime.TryParseExact(text, dateFormatString, culture, DateTimeStyles.RoundtripKind, out temp))
+                {
+                    temp = EnsureDateTime(temp, dateTimeZoneHandling);
+                    dt = temp;
+                    return true;
+                }
+            }
+
+            dt = null;
+            return false;
+        }
+
+        private static TimeSpan ReadOffset(string offsetText)
+        {
+            bool negative = (offsetText[0] == '-');
+
+            int hours = int.Parse(offsetText.Substring(1, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
+            int minutes = 0;
+            if (offsetText.Length >= 5)
+                minutes = int.Parse(offsetText.Substring(3, 2), NumberStyles.Integer, CultureInfo.InvariantCulture);
+
+            TimeSpan offset = TimeSpan.FromHours(hours) + TimeSpan.FromMinutes(minutes);
+            if (negative)
+                offset = offset.Negate();
+
+            return offset;
+        }
+        #endregion
+
+        #region Write
+        internal static void WriteDateTimeString(TextWriter writer, DateTime value, DateFormatHandling format, string formatString, CultureInfo culture)
+        {
+            if (string.IsNullOrEmpty(formatString))
+            {
+                char[] chars = new char[64];
+                int pos = WriteDateTimeString(chars, 0, value, null, value.Kind, format);
+                writer.Write(chars, 0, pos);
+            }
+            else
+            {
+                writer.Write(value.ToString(formatString, culture));
+            }
+        }
+
+        internal static int WriteDateTimeString(char[] chars, int start, DateTime value, TimeSpan? offset, DateTimeKind kind, DateFormatHandling format)
+        {
+            int pos = start;
+
+            if (format == DateFormatHandling.MicrosoftDateFormat)
+            {
+                TimeSpan o = offset ?? value.GetUtcOffset();
+
+                long javaScriptTicks = ConvertDateTimeToJavaScriptTicks(value, o);
+
+                @"\/Date(".CopyTo(0, chars, pos, 7);
+                pos += 7;
+
+                string ticksText = javaScriptTicks.ToString(CultureInfo.InvariantCulture);
+                ticksText.CopyTo(0, chars, pos, ticksText.Length);
+                pos += ticksText.Length;
+
+                switch (kind)
+                {
+                    case DateTimeKind.Unspecified:
+                        if (value != DateTime.MaxValue && value != DateTime.MinValue)
+                            pos = WriteDateTimeOffset(chars, pos, o, format);
+                        break;
+                    case DateTimeKind.Local:
+                        pos = WriteDateTimeOffset(chars, pos, o, format);
+                        break;
+                }
+
+                @")\/".CopyTo(0, chars, pos, 3);
+                pos += 3;
+            }
+            else
+            {
+                pos = WriteDefaultIsoDate(chars, pos, value);
+
+                switch (kind)
+                {
+                    case DateTimeKind.Local:
+                        pos = WriteDateTimeOffset(chars, pos, offset ?? value.GetUtcOffset(), format);
+                        break;
+                    case DateTimeKind.Utc:
+                        chars[pos++] = 'Z';
+                        break;
+                }
+            }
+
+            return pos;
+        }
+
+        internal static int WriteDefaultIsoDate(char[] chars, int start, DateTime dt)
+        {
+            int length = 19;
+
+            int year;
+            int month;
+            int day;
+            GetDateValues(dt, out year, out month, out day);
+
+            CopyIntToCharArray(chars, start, year, 4);
+            chars[start + 4] = '-';
+            CopyIntToCharArray(chars, start + 5, month, 2);
+            chars[start + 7] = '-';
+            CopyIntToCharArray(chars, start + 8, day, 2);
+            chars[start + 10] = 'T';
+            CopyIntToCharArray(chars, start + 11, dt.Hour, 2);
+            chars[start + 13] = ':';
+            CopyIntToCharArray(chars, start + 14, dt.Minute, 2);
+            chars[start + 16] = ':';
+            CopyIntToCharArray(chars, start + 17, dt.Second, 2);
+
+            int fraction = (int)(dt.Ticks % 10000000L);
+
+            if (fraction != 0)
+            {
+                int digits = 7;
+                while ((fraction % 10) == 0)
+                {
+                    digits--;
+                    fraction /= 10;
+                }
+
+                chars[start + 19] = '.';
+                CopyIntToCharArray(chars, start + 20, fraction, digits);
+
+                length += digits + 1;
+            }
+
+            return start + length;
+        }
+
+        private static void CopyIntToCharArray(char[] chars, int start, int value, int digits)
+        {
+            while (digits-- != 0)
+            {
+                chars[start + digits] = (char)((value % 10) + 48);
+                value /= 10;
+            }
+        }
+
+        internal static int WriteDateTimeOffset(char[] chars, int start, TimeSpan offset, DateFormatHandling format)
+        {
+            chars[start++] = (offset.Ticks >= 0L) ? '+' : '-';
+
+            int absHours = Math.Abs(offset.Hours);
+            CopyIntToCharArray(chars, start, absHours, 2);
+            start += 2;
+
+            if (format == DateFormatHandling.IsoDateFormat)
+                chars[start++] = ':';
+
+            int absMinutes = Math.Abs(offset.Minutes);
+            CopyIntToCharArray(chars, start, absMinutes, 2);
+            start += 2;
+
+            return start;
+        }
+
+#if !NET20
+        internal static void WriteDateTimeOffsetString(TextWriter writer, DateTimeOffset value, DateFormatHandling format, string formatString, CultureInfo culture)
+        {
+            if (string.IsNullOrEmpty(formatString))
+            {
+                char[] chars = new char[64];
+                int pos = WriteDateTimeString(chars, 0, (format == DateFormatHandling.IsoDateFormat) ? value.DateTime : value.UtcDateTime, value.Offset, DateTimeKind.Local, format);
+
+                writer.Write(chars, 0, pos);
+            }
+            else
+            {
+                writer.Write(value.ToString(formatString, culture));
+            }
+        }
+#endif
+        #endregion
+
+        private static void GetDateValues(DateTime td, out int year, out int month, out int day)
+        {
+            long ticks = td.Ticks;
+            // n = number of days since 1/1/0001
+            int n = (int)(ticks / TicksPerDay);
+            // y400 = number of whole 400-year periods since 1/1/0001
+            int y400 = n / DaysPer400Years;
+            // n = day number within 400-year period
+            n -= y400 * DaysPer400Years;
+            // y100 = number of whole 100-year periods within 400-year period
+            int y100 = n / DaysPer100Years;
+            // Last 100-year period has an extra day, so decrement result if 4
+            if (y100 == 4)
+                y100 = 3;
+            // n = day number within 100-year period
+            n -= y100 * DaysPer100Years;
+            // y4 = number of whole 4-year periods within 100-year period
+            int y4 = n / DaysPer4Years;
+            // n = day number within 4-year period
+            n -= y4 * DaysPer4Years;
+            // y1 = number of whole years within 4-year period
+            int y1 = n / DaysPerYear;
+            // Last year has an extra day, so decrement result if 4
+            if (y1 == 4)
+                y1 = 3;
+
+            year = y400 * 400 + y100 * 100 + y4 * 4 + y1 + 1;
+
+            // n = day number within year
+            n -= y1 * DaysPerYear;
+
+            // Leap year calculation looks different from IsLeapYear since y1, y4,
+            // and y100 are relative to year 1, not year 0
+            bool leapYear = y1 == 3 && (y4 != 24 || y100 == 3);
+            int[] days = leapYear ? DaysToMonth366 : DaysToMonth365;
+            // All months have less than 32 days, so n >> 5 is a good conservative
+            // estimate for the month
+            int m = n >> 5 + 1;
+            // m = 1-based month number
+            while (n >= days[m])
+            {
+                m++;
+            }
+
+            month = m;
+
+            // Return 1-based day-of-month
+            day = n - days[m - 1] + 1;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DictionaryWrapper.cs b/Newtonsoft.Json/Utilities/DictionaryWrapper.cs
new file mode 100644
index 0000000..2d01323
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DictionaryWrapper.cs
@@ -0,0 +1,556 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections;
+using System.Threading;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal interface IWrappedDictionary
+        : IDictionary
+    {
+        object UnderlyingDictionary { get; }
+    }
+
+    internal class DictionaryWrapper<TKey, TValue> : IDictionary<TKey, TValue>, IWrappedDictionary
+    {
+        private readonly IDictionary _dictionary;
+        private readonly IDictionary<TKey, TValue> _genericDictionary;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+        private readonly IReadOnlyDictionary<TKey, TValue> _readOnlyDictionary;
+#endif
+        private object _syncRoot;
+
+        public DictionaryWrapper(IDictionary dictionary)
+        {
+            ValidationUtils.ArgumentNotNull(dictionary, "dictionary");
+
+            _dictionary = dictionary;
+        }
+
+        public DictionaryWrapper(IDictionary<TKey, TValue> dictionary)
+        {
+            ValidationUtils.ArgumentNotNull(dictionary, "dictionary");
+
+            _genericDictionary = dictionary;
+        }
+
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+        public DictionaryWrapper(IReadOnlyDictionary<TKey, TValue> dictionary)
+        {
+            ValidationUtils.ArgumentNotNull(dictionary, "dictionary");
+
+            _readOnlyDictionary = dictionary;
+        }
+#endif
+
+        public void Add(TKey key, TValue value)
+        {
+            if (_dictionary != null)
+                _dictionary.Add(key, value);
+            else if (_genericDictionary != null)
+                _genericDictionary.Add(key, value);
+            else
+                throw new NotSupportedException();
+        }
+
+        public bool ContainsKey(TKey key)
+        {
+            if (_dictionary != null)
+                return _dictionary.Contains(key);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                return _readOnlyDictionary.ContainsKey(key);
+#endif
+            else
+                return _genericDictionary.ContainsKey(key);
+        }
+
+        public ICollection<TKey> Keys
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary.Keys.Cast<TKey>().ToList();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary.Keys.ToList();
+#endif
+                else
+                    return _genericDictionary.Keys;
+            }
+        }
+
+        public bool Remove(TKey key)
+        {
+            if (_dictionary != null)
+            {
+                if (_dictionary.Contains(key))
+                {
+                    _dictionary.Remove(key);
+                    return true;
+                }
+                else
+                {
+                    return false;
+                }
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+            {
+                throw new NotSupportedException();
+            }
+#endif
+            else
+            {
+                return _genericDictionary.Remove(key);
+            }
+        }
+
+        public bool TryGetValue(TKey key, out TValue value)
+        {
+            if (_dictionary != null)
+            {
+                if (!_dictionary.Contains(key))
+                {
+                    value = default(TValue);
+                    return false;
+                }
+                else
+                {
+                    value = (TValue)_dictionary[key];
+                    return true;
+                }
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+            {
+                throw new NotSupportedException();
+            }
+#endif
+            else
+            {
+                return _genericDictionary.TryGetValue(key, out value);
+            }
+        }
+
+        public ICollection<TValue> Values
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary.Values.Cast<TValue>().ToList();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary.Values.ToList();
+#endif
+                else
+                    return _genericDictionary.Values;
+            }
+        }
+
+        public TValue this[TKey key]
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return (TValue)_dictionary[key];
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary[key];
+#endif
+                else
+                    return _genericDictionary[key];
+            }
+            set
+            {
+                if (_dictionary != null)
+                    _dictionary[key] = value;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    throw new NotSupportedException();
+#endif
+                else
+                    _genericDictionary[key] = value;
+            }
+        }
+
+        public void Add(KeyValuePair<TKey, TValue> item)
+        {
+            if (_dictionary != null)
+                ((IList)_dictionary).Add(item);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                throw new NotSupportedException();
+#endif
+            else if (_genericDictionary != null)
+                _genericDictionary.Add(item);
+        }
+
+        public void Clear()
+        {
+            if (_dictionary != null)
+                _dictionary.Clear();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                throw new NotSupportedException();
+#endif
+            else
+                _genericDictionary.Clear();
+        }
+
+        public bool Contains(KeyValuePair<TKey, TValue> item)
+        {
+            if (_dictionary != null)
+                return ((IList)_dictionary).Contains(item);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                return _readOnlyDictionary.Contains(item);
+#endif
+            else
+                return _genericDictionary.Contains(item);
+        }
+
+        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        {
+            if (_dictionary != null)
+            {
+                foreach (DictionaryEntry item in _dictionary)
+                {
+                    array[arrayIndex++] = new KeyValuePair<TKey, TValue>((TKey)item.Key, (TValue)item.Value);
+                }
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+            {
+                throw new NotSupportedException();
+            }
+#endif
+            else
+            {
+                _genericDictionary.CopyTo(array, arrayIndex);
+            }
+        }
+
+        public int Count
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary.Count;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary.Count;
+#endif
+                else
+                    return _genericDictionary.Count;
+            }
+        }
+
+        public bool IsReadOnly
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary.IsReadOnly;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return true;
+#endif
+                else
+                    return _genericDictionary.IsReadOnly;
+            }
+        }
+
+        public bool Remove(KeyValuePair<TKey, TValue> item)
+        {
+            if (_dictionary != null)
+            {
+                if (_dictionary.Contains(item.Key))
+                {
+                    object value = _dictionary[item.Key];
+
+                    if (object.Equals(value, item.Value))
+                    {
+                        _dictionary.Remove(item.Key);
+                        return true;
+                    }
+                    else
+                    {
+                        return false;
+                    }
+                }
+                else
+                {
+                    return true;
+                }
+            }
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+            {
+                throw new NotSupportedException();
+            }
+#endif
+            else
+            {
+                return _genericDictionary.Remove(item);
+            }
+        }
+
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            if (_dictionary != null)
+                return _dictionary.Cast<DictionaryEntry>().Select(de => new KeyValuePair<TKey, TValue>((TKey)de.Key, (TValue)de.Value)).GetEnumerator();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                return _readOnlyDictionary.GetEnumerator();
+#endif
+            else
+                return _genericDictionary.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return GetEnumerator();
+        }
+
+        void IDictionary.Add(object key, object value)
+        {
+            if (_dictionary != null)
+                _dictionary.Add(key, value);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                throw new NotSupportedException();
+#endif
+            else
+                _genericDictionary.Add((TKey)key, (TValue)value);
+        }
+
+        object IDictionary.this[object key]
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary[key];
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary[(TKey)key];
+#endif
+                else
+                    return _genericDictionary[(TKey)key];
+            }
+            set
+            {
+                if (_dictionary != null)
+                    _dictionary[key] = value;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    throw new NotSupportedException();
+#endif
+                else
+                    _genericDictionary[(TKey)key] = (TValue)value;
+            }
+        }
+
+        private struct DictionaryEnumerator<TEnumeratorKey, TEnumeratorValue> : IDictionaryEnumerator
+        {
+            private readonly IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> _e;
+
+            public DictionaryEnumerator(IEnumerator<KeyValuePair<TEnumeratorKey, TEnumeratorValue>> e)
+            {
+                ValidationUtils.ArgumentNotNull(e, "e");
+                _e = e;
+            }
+
+            public DictionaryEntry Entry
+            {
+                get { return (DictionaryEntry)Current; }
+            }
+
+            public object Key
+            {
+                get { return Entry.Key; }
+            }
+
+            public object Value
+            {
+                get { return Entry.Value; }
+            }
+
+            public object Current
+            {
+                get { return new DictionaryEntry(_e.Current.Key, _e.Current.Value); }
+            }
+
+            public bool MoveNext()
+            {
+                return _e.MoveNext();
+            }
+
+            public void Reset()
+            {
+                _e.Reset();
+            }
+        }
+
+        IDictionaryEnumerator IDictionary.GetEnumerator()
+        {
+            if (_dictionary != null)
+                return _dictionary.GetEnumerator();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                return new DictionaryEnumerator<TKey, TValue>(_readOnlyDictionary.GetEnumerator());
+#endif
+            else
+                return new DictionaryEnumerator<TKey, TValue>(_genericDictionary.GetEnumerator());
+        }
+
+        bool IDictionary.Contains(object key)
+        {
+            if (_genericDictionary != null)
+                return _genericDictionary.ContainsKey((TKey)key);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                return _readOnlyDictionary.ContainsKey((TKey)key);
+#endif
+            else
+                return _dictionary.Contains(key);
+        }
+
+        bool IDictionary.IsFixedSize
+        {
+            get
+            {
+                if (_genericDictionary != null)
+                    return false;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return true;
+#endif
+                else
+                    return _dictionary.IsFixedSize;
+            }
+        }
+
+        ICollection IDictionary.Keys
+        {
+            get
+            {
+                if (_genericDictionary != null)
+                    return _genericDictionary.Keys.ToList();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary.Keys.ToList();
+#endif
+                else
+                    return _dictionary.Keys;
+            }
+        }
+
+        public void Remove(object key)
+        {
+            if (_dictionary != null)
+                _dictionary.Remove(key);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                throw new NotSupportedException();
+#endif
+            else
+                _genericDictionary.Remove((TKey)key);
+        }
+
+        ICollection IDictionary.Values
+        {
+            get
+            {
+                if (_genericDictionary != null)
+                    return _genericDictionary.Values.ToList();
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary.Values.ToList();
+#endif
+                else
+                    return _dictionary.Values;
+            }
+        }
+
+        void ICollection.CopyTo(Array array, int index)
+        {
+            if (_dictionary != null)
+                _dictionary.CopyTo(array, index);
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+            else if (_readOnlyDictionary != null)
+                throw new NotSupportedException();
+#endif
+            else
+                _genericDictionary.CopyTo((KeyValuePair<TKey, TValue>[])array, index);
+        }
+
+        bool ICollection.IsSynchronized
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary.IsSynchronized;
+                else
+                    return false;
+            }
+        }
+
+        object ICollection.SyncRoot
+        {
+            get
+            {
+                if (_syncRoot == null)
+                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
+
+                return _syncRoot;
+            }
+        }
+
+        public object UnderlyingDictionary
+        {
+            get
+            {
+                if (_dictionary != null)
+                    return _dictionary;
+#if !(NET40 || NET35 || NET20 || PORTABLE40)
+                else if (_readOnlyDictionary != null)
+                    return _readOnlyDictionary;
+#endif
+                else
+                    return _genericDictionary;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DynamicProxy.cs b/Newtonsoft.Json/Utilities/DynamicProxy.cs
new file mode 100644
index 0000000..9e22a43
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DynamicProxy.cs
@@ -0,0 +1,113 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class DynamicProxy<T>
+    {
+        public virtual IEnumerable<string> GetDynamicMemberNames(T instance)
+        {
+            return new string[0];
+        }
+
+        public virtual bool TryBinaryOperation(T instance, BinaryOperationBinder binder, object arg, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryConvert(T instance, ConvertBinder binder, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryCreateInstance(T instance, CreateInstanceBinder binder, object[] args, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryDeleteIndex(T instance, DeleteIndexBinder binder, object[] indexes)
+        {
+            return false;
+        }
+
+        public virtual bool TryDeleteMember(T instance, DeleteMemberBinder binder)
+        {
+            return false;
+        }
+
+        public virtual bool TryGetIndex(T instance, GetIndexBinder binder, object[] indexes, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryGetMember(T instance, GetMemberBinder binder, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryInvoke(T instance, InvokeBinder binder, object[] args, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TryInvokeMember(T instance, InvokeMemberBinder binder, object[] args, out object result)
+        {
+            result = null;
+            return false;
+        }
+
+        public virtual bool TrySetIndex(T instance, SetIndexBinder binder, object[] indexes, object value)
+        {
+            return false;
+        }
+
+        public virtual bool TrySetMember(T instance, SetMemberBinder binder, object value)
+        {
+            return false;
+        }
+
+        public virtual bool TryUnaryOperation(T instance, UnaryOperationBinder binder, out object result)
+        {
+            result = null;
+            return false;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs b/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs
new file mode 100644
index 0000000..64f4100
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DynamicProxyMetaObject.cs
@@ -0,0 +1,423 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal sealed class DynamicProxyMetaObject<T> : DynamicMetaObject
+    {
+        private readonly DynamicProxy<T> _proxy;
+        private readonly bool _dontFallbackFirst;
+
+        internal DynamicProxyMetaObject(Expression expression, T value, DynamicProxy<T> proxy, bool dontFallbackFirst)
+            : base(expression, BindingRestrictions.Empty, value)
+        {
+            _proxy = proxy;
+            _dontFallbackFirst = dontFallbackFirst;
+        }
+
+        private new T Value
+        {
+            get { return (T)base.Value; }
+        }
+
+        private bool IsOverridden(string method)
+        {
+            return ReflectionUtils.IsMethodOverridden(_proxy.GetType(), typeof(DynamicProxy<T>), method);
+        }
+
+        public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
+        {
+            return IsOverridden("TryGetMember")
+                ? CallMethodWithResult("TryGetMember", binder, NoArgs, e => binder.FallbackGetMember(this, e))
+                : base.BindGetMember(binder);
+        }
+
+        public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
+        {
+            return IsOverridden("TrySetMember")
+                ? CallMethodReturnLast("TrySetMember", binder, GetArgs(value), e => binder.FallbackSetMember(this, value, e))
+                : base.BindSetMember(binder, value);
+        }
+
+        public override DynamicMetaObject BindDeleteMember(DeleteMemberBinder binder)
+        {
+            return IsOverridden("TryDeleteMember")
+                ? CallMethodNoResult("TryDeleteMember", binder, NoArgs, e => binder.FallbackDeleteMember(this, e))
+                : base.BindDeleteMember(binder);
+        }
+
+
+        public override DynamicMetaObject BindConvert(ConvertBinder binder)
+        {
+            return IsOverridden("TryConvert")
+                ? CallMethodWithResult("TryConvert", binder, NoArgs, e => binder.FallbackConvert(this, e))
+                : base.BindConvert(binder);
+        }
+
+        public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
+        {
+            if (!IsOverridden("TryInvokeMember"))
+                return base.BindInvokeMember(binder, args);
+
+            //
+            // Generate a tree like:
+            //
+            // {
+            //   object result;
+            //   TryInvokeMember(payload, out result)
+            //      ? result
+            //      : TryGetMember(payload, out result)
+            //          ? FallbackInvoke(result)
+            //          : fallbackResult
+            // }
+            //
+            // Then it calls FallbackInvokeMember with this tree as the
+            // "error", giving the language the option of using this
+            // tree or doing .NET binding.
+            //
+            Fallback fallback = e => binder.FallbackInvokeMember(this, args, e);
+
+            DynamicMetaObject call = BuildCallMethodWithResult(
+                "TryInvokeMember",
+                binder,
+                GetArgArray(args),
+                BuildCallMethodWithResult(
+                    "TryGetMember",
+                    new GetBinderAdapter(binder),
+                    NoArgs,
+                    fallback(null),
+                    e => binder.FallbackInvoke(e, args, null)
+                    ),
+                null
+                );
+
+            return _dontFallbackFirst ? call : fallback(call);
+        }
+
+
+        public override DynamicMetaObject BindCreateInstance(CreateInstanceBinder binder, DynamicMetaObject[] args)
+        {
+            return IsOverridden("TryCreateInstance")
+                ? CallMethodWithResult("TryCreateInstance", binder, GetArgArray(args), e => binder.FallbackCreateInstance(this, args, e))
+                : base.BindCreateInstance(binder, args);
+        }
+
+        public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)
+        {
+            return IsOverridden("TryInvoke")
+                ? CallMethodWithResult("TryInvoke", binder, GetArgArray(args), e => binder.FallbackInvoke(this, args, e))
+                : base.BindInvoke(binder, args);
+        }
+
+        public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
+        {
+            return IsOverridden("TryBinaryOperation")
+                ? CallMethodWithResult("TryBinaryOperation", binder, GetArgs(arg), e => binder.FallbackBinaryOperation(this, arg, e))
+                : base.BindBinaryOperation(binder, arg);
+        }
+
+        public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder)
+        {
+            return IsOverridden("TryUnaryOperation")
+                ? CallMethodWithResult("TryUnaryOperation", binder, NoArgs, e => binder.FallbackUnaryOperation(this, e))
+                : base.BindUnaryOperation(binder);
+        }
+
+        public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
+        {
+            return IsOverridden("TryGetIndex")
+                ? CallMethodWithResult("TryGetIndex", binder, GetArgArray(indexes), e => binder.FallbackGetIndex(this, indexes, e))
+                : base.BindGetIndex(binder, indexes);
+        }
+
+        public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
+        {
+            return IsOverridden("TrySetIndex")
+                ? CallMethodReturnLast("TrySetIndex", binder, GetArgArray(indexes, value), e => binder.FallbackSetIndex(this, indexes, value, e))
+                : base.BindSetIndex(binder, indexes, value);
+        }
+
+        public override DynamicMetaObject BindDeleteIndex(DeleteIndexBinder binder, DynamicMetaObject[] indexes)
+        {
+            return IsOverridden("TryDeleteIndex")
+                ? CallMethodNoResult("TryDeleteIndex", binder, GetArgArray(indexes), e => binder.FallbackDeleteIndex(this, indexes, e))
+                : base.BindDeleteIndex(binder, indexes);
+        }
+
+        private delegate DynamicMetaObject Fallback(DynamicMetaObject errorSuggestion);
+
+        private static readonly Expression[] NoArgs = new Expression[0];
+
+        private static Expression[] GetArgs(params DynamicMetaObject[] args)
+        {
+            return args.Select(arg => Expression.Convert(arg.Expression, typeof(object))).ToArray();
+        }
+
+        private static Expression[] GetArgArray(DynamicMetaObject[] args)
+        {
+            return new[] { Expression.NewArrayInit(typeof(object), GetArgs(args)) };
+        }
+
+        private static Expression[] GetArgArray(DynamicMetaObject[] args, DynamicMetaObject value)
+        {
+            return new Expression[]
+            {
+                Expression.NewArrayInit(typeof(object), GetArgs(args)),
+                Expression.Convert(value.Expression, typeof(object))
+            };
+        }
+
+        private static ConstantExpression Constant(DynamicMetaObjectBinder binder)
+        {
+            Type t = binder.GetType();
+            while (!t.IsVisible())
+                t = t.BaseType();
+            return Expression.Constant(binder, t);
+        }
+
+        /// <summary>
+        /// Helper method for generating a MetaObject which calls a
+        /// specific method on Dynamic that returns a result
+        /// </summary>
+        private DynamicMetaObject CallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback, Fallback fallbackInvoke = null)
+        {
+            //
+            // First, call fallback to do default binding
+            // This produces either an error or a call to a .NET member
+            //
+            DynamicMetaObject fallbackResult = fallback(null);
+
+            DynamicMetaObject callDynamic = BuildCallMethodWithResult(methodName, binder, args, fallbackResult, fallbackInvoke);
+
+            //
+            // Now, call fallback again using our new MO as the error
+            // When we do this, one of two things can happen:
+            //   1. Binding will succeed, and it will ignore our call to
+            //      the dynamic method, OR
+            //   2. Binding will fail, and it will use the MO we created
+            //      above.
+            //
+
+            return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+        }
+
+        private DynamicMetaObject BuildCallMethodWithResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, DynamicMetaObject fallbackResult, Fallback fallbackInvoke)
+        {
+            //
+            // Build a new expression like:
+            // {
+            //   object result;
+            //   TryGetMember(payload, out result) ? fallbackInvoke(result) : fallbackResult
+            // }
+            //
+            ParameterExpression result = Expression.Parameter(typeof(object), null);
+
+            IList<Expression> callArgs = new List<Expression>();
+            callArgs.Add(Expression.Convert(Expression, typeof(T)));
+            callArgs.Add(Constant(binder));
+            callArgs.AddRange(args);
+            callArgs.Add(result);
+
+            DynamicMetaObject resultMetaObject = new DynamicMetaObject(result, BindingRestrictions.Empty);
+
+            // Need to add a conversion if calling TryConvert
+            if (binder.ReturnType != typeof(object))
+            {
+                UnaryExpression convert = Expression.Convert(resultMetaObject.Expression, binder.ReturnType);
+                // will always be a cast or unbox
+
+                resultMetaObject = new DynamicMetaObject(convert, resultMetaObject.Restrictions);
+            }
+
+            if (fallbackInvoke != null)
+                resultMetaObject = fallbackInvoke(resultMetaObject);
+
+            DynamicMetaObject callDynamic = new DynamicMetaObject(
+                Expression.Block(
+                    new[] { result },
+                    Expression.Condition(
+                        Expression.Call(
+                            Expression.Constant(_proxy),
+                            typeof(DynamicProxy<T>).GetMethod(methodName),
+                            callArgs
+                            ),
+                        resultMetaObject.Expression,
+                        fallbackResult.Expression,
+                        binder.ReturnType
+                        )
+                    ),
+                GetRestrictions().Merge(resultMetaObject.Restrictions).Merge(fallbackResult.Restrictions)
+                );
+
+            return callDynamic;
+        }
+
+        /// <summary>
+        /// Helper method for generating a MetaObject which calls a
+        /// specific method on Dynamic, but uses one of the arguments for
+        /// the result.
+        /// </summary>
+        private DynamicMetaObject CallMethodReturnLast(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
+        {
+            //
+            // First, call fallback to do default binding
+            // This produces either an error or a call to a .NET member
+            //
+            DynamicMetaObject fallbackResult = fallback(null);
+
+            //
+            // Build a new expression like:
+            // {
+            //   object result;
+            //   TrySetMember(payload, result = value) ? result : fallbackResult
+            // }
+            //
+            ParameterExpression result = Expression.Parameter(typeof(object), null);
+
+            IList<Expression> callArgs = new List<Expression>();
+            callArgs.Add(Expression.Convert(Expression, typeof(T)));
+            callArgs.Add(Constant(binder));
+            callArgs.AddRange(args);
+            callArgs[args.Length + 1] = Expression.Assign(result, callArgs[args.Length + 1]);
+
+            DynamicMetaObject callDynamic = new DynamicMetaObject(
+                Expression.Block(
+                    new[] { result },
+                    Expression.Condition(
+                        Expression.Call(
+                            Expression.Constant(_proxy),
+                            typeof(DynamicProxy<T>).GetMethod(methodName),
+                            callArgs
+                            ),
+                        result,
+                        fallbackResult.Expression,
+                        typeof(object)
+                        )
+                    ),
+                GetRestrictions().Merge(fallbackResult.Restrictions)
+                );
+
+            //
+            // Now, call fallback again using our new MO as the error
+            // When we do this, one of two things can happen:
+            //   1. Binding will succeed, and it will ignore our call to
+            //      the dynamic method, OR
+            //   2. Binding will fail, and it will use the MO we created
+            //      above.
+            //
+            return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+        }
+
+        /// <summary>
+        /// Helper method for generating a MetaObject which calls a
+        /// specific method on Dynamic, but uses one of the arguments for
+        /// the result.
+        /// </summary>
+        private DynamicMetaObject CallMethodNoResult(string methodName, DynamicMetaObjectBinder binder, Expression[] args, Fallback fallback)
+        {
+            //
+            // First, call fallback to do default binding
+            // This produces either an error or a call to a .NET member
+            //
+            DynamicMetaObject fallbackResult = fallback(null);
+
+            IList<Expression> callArgs = new List<Expression>();
+            callArgs.Add(Expression.Convert(Expression, typeof(T)));
+            callArgs.Add(Constant(binder));
+            callArgs.AddRange(args);
+
+            //
+            // Build a new expression like:
+            //   if (TryDeleteMember(payload)) { } else { fallbackResult }
+            //
+            DynamicMetaObject callDynamic = new DynamicMetaObject(
+                Expression.Condition(
+                    Expression.Call(
+                        Expression.Constant(_proxy),
+                        typeof(DynamicProxy<T>).GetMethod(methodName),
+                        callArgs
+                        ),
+                    Expression.Empty(),
+                    fallbackResult.Expression,
+                    typeof(void)
+                    ),
+                GetRestrictions().Merge(fallbackResult.Restrictions)
+                );
+
+            //
+            // Now, call fallback again using our new MO as the error
+            // When we do this, one of two things can happen:
+            //   1. Binding will succeed, and it will ignore our call to
+            //      the dynamic method, OR
+            //   2. Binding will fail, and it will use the MO we created
+            //      above.
+            //
+            return _dontFallbackFirst ? callDynamic : fallback(callDynamic);
+        }
+
+        /// <summary>
+        /// Returns a Restrictions object which includes our current restrictions merged
+        /// with a restriction limiting our type
+        /// </summary>
+        private BindingRestrictions GetRestrictions()
+        {
+            return (Value == null && HasValue)
+                ? BindingRestrictions.GetInstanceRestriction(Expression, null)
+                : BindingRestrictions.GetTypeRestriction(Expression, LimitType);
+        }
+
+        public override IEnumerable<string> GetDynamicMemberNames()
+        {
+            return _proxy.GetDynamicMemberNames(Value);
+        }
+
+        // It is okay to throw NotSupported from this binder. This object
+        // is only used by DynamicObject.GetMember--it is not expected to
+        // (and cannot) implement binding semantics. It is just so the DO
+        // can use the Name and IgnoreCase properties.
+        private sealed class GetBinderAdapter : GetMemberBinder
+        {
+            internal GetBinderAdapter(InvokeMemberBinder binder) :
+                base(binder.Name, binder.IgnoreCase)
+            {
+            }
+
+            public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
+            {
+                throw new NotSupportedException();
+            }
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs b/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
new file mode 100644
index 0000000..fd72500
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DynamicReflectionDelegateFactory.cs
@@ -0,0 +1,230 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(PORTABLE || NETFX_CORE || PORTABLE40)
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+using System.Reflection;
+using System.Reflection.Emit;
+using Newtonsoft.Json.Serialization;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class DynamicReflectionDelegateFactory : ReflectionDelegateFactory
+    {
+        public static DynamicReflectionDelegateFactory Instance = new DynamicReflectionDelegateFactory();
+
+        private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
+        {
+            DynamicMethod dynamicMethod = !owner.IsInterface()
+                ? new DynamicMethod(name, returnType, parameterTypes, owner, true)
+                : new DynamicMethod(name, returnType, parameterTypes, owner.Module, true);
+
+            return dynamicMethod;
+        }
+
+        public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateMethodCallIL(method, generator);
+
+            return (MethodCall<T, object>)dynamicMethod.CreateDelegate(typeof(MethodCall<T, object>));
+        }
+
+        private void GenerateCreateMethodCallIL(MethodBase method, ILGenerator generator)
+        {
+            ParameterInfo[] args = method.GetParameters();
+
+            Label argsOk = generator.DefineLabel();
+
+            generator.Emit(OpCodes.Ldarg_1);
+            generator.Emit(OpCodes.Ldlen);
+            generator.Emit(OpCodes.Ldc_I4, args.Length);
+            generator.Emit(OpCodes.Beq, argsOk);
+
+            generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(ReflectionUtils.EmptyTypes));
+            generator.Emit(OpCodes.Throw);
+
+            generator.MarkLabel(argsOk);
+
+            if (!method.IsConstructor && !method.IsStatic)
+                generator.PushInstance(method.DeclaringType);
+
+            for (int i = 0; i < args.Length; i++)
+            {
+                generator.Emit(OpCodes.Ldarg_1);
+                generator.Emit(OpCodes.Ldc_I4, i);
+                generator.Emit(OpCodes.Ldelem_Ref);
+
+                generator.UnboxIfNeeded(args[i].ParameterType);
+            }
+
+            if (method.IsConstructor)
+                generator.Emit(OpCodes.Newobj, (ConstructorInfo)method);
+            else
+                generator.CallMethod((MethodInfo)method);
+
+            Type returnType = method.IsConstructor
+                ? method.DeclaringType
+                : ((MethodInfo)method).ReturnType;
+
+            if (returnType != typeof(void))
+                generator.BoxIfNeeded(returnType);
+            else
+                generator.Emit(OpCodes.Ldnull);
+
+            generator.Return();
+        }
+
+        public override Func<T> CreateDefaultConstructor<T>(Type type)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(T), ReflectionUtils.EmptyTypes, type);
+            dynamicMethod.InitLocals = true;
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateDefaultConstructorIL(type, generator);
+
+            return (Func<T>)dynamicMethod.CreateDelegate(typeof(Func<T>));
+        }
+
+        private void GenerateCreateDefaultConstructorIL(Type type, ILGenerator generator)
+        {
+            if (type.IsValueType())
+            {
+                generator.DeclareLocal(type);
+                generator.Emit(OpCodes.Ldloc_0);
+                generator.Emit(OpCodes.Box, type);
+            }
+            else
+            {
+                ConstructorInfo constructorInfo =
+                    type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
+                        ReflectionUtils.EmptyTypes, null);
+
+                if (constructorInfo == null)
+                    throw new ArgumentException("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type));
+
+                generator.Emit(OpCodes.Newobj, constructorInfo);
+            }
+
+            generator.Return();
+        }
+
+        public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateGetPropertyIL(propertyInfo, generator);
+
+            return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
+        }
+
+        private void GenerateCreateGetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator)
+        {
+            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
+            if (getMethod == null)
+                throw new ArgumentException("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture, propertyInfo.Name));
+
+            if (!getMethod.IsStatic)
+                generator.PushInstance(propertyInfo.DeclaringType);
+
+            generator.CallMethod(getMethod);
+            generator.BoxIfNeeded(propertyInfo.PropertyType);
+            generator.Return();
+        }
+
+        public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateGetFieldIL(fieldInfo, generator);
+
+            return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
+        }
+
+        private void GenerateCreateGetFieldIL(FieldInfo fieldInfo, ILGenerator generator)
+        {
+            if (!fieldInfo.IsStatic)
+                generator.PushInstance(fieldInfo.DeclaringType);
+
+            generator.Emit(OpCodes.Ldfld, fieldInfo);
+            generator.BoxIfNeeded(fieldInfo.FieldType);
+            generator.Return();
+        }
+
+        public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(T), typeof(object) }, fieldInfo.DeclaringType);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateSetFieldIL(fieldInfo, generator);
+
+            return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
+        }
+
+        internal static void GenerateCreateSetFieldIL(FieldInfo fieldInfo, ILGenerator generator)
+        {
+            if (!fieldInfo.IsStatic)
+                generator.PushInstance(fieldInfo.DeclaringType);
+
+            generator.Emit(OpCodes.Ldarg_1);
+            generator.UnboxIfNeeded(fieldInfo.FieldType);
+            generator.Emit(OpCodes.Stfld, fieldInfo);
+            generator.Return();
+        }
+
+        public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
+        {
+            DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(T), typeof(object) }, propertyInfo.DeclaringType);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+
+            GenerateCreateSetPropertyIL(propertyInfo, generator);
+
+            return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
+        }
+
+        internal static void GenerateCreateSetPropertyIL(PropertyInfo propertyInfo, ILGenerator generator)
+        {
+            MethodInfo setMethod = propertyInfo.GetSetMethod(true);
+            if (!setMethod.IsStatic)
+                generator.PushInstance(propertyInfo.DeclaringType);
+
+            generator.Emit(OpCodes.Ldarg_1);
+            generator.UnboxIfNeeded(propertyInfo.PropertyType);
+            generator.CallMethod(setMethod);
+            generator.Return();
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DynamicUtils.cs b/Newtonsoft.Json/Utilities/DynamicUtils.cs
new file mode 100644
index 0000000..68f215f
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DynamicUtils.cs
@@ -0,0 +1,206 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET35 || NET20 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+using System.Dynamic;
+using System.Linq;
+using System.Linq.Expressions;
+#if !(PORTABLE)
+using System.Reflection;
+#else
+using Microsoft.CSharp.RuntimeBinder;
+#endif
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class DynamicUtils
+    {
+        internal static class BinderWrapper
+        {
+#if !(PORTABLE)
+            public const string CSharpAssemblyName = "Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+
+            private const string BinderTypeName = "Microsoft.CSharp.RuntimeBinder.Binder, " + CSharpAssemblyName;
+            private const string CSharpArgumentInfoTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo, " + CSharpAssemblyName;
+            private const string CSharpArgumentInfoFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfoFlags, " + CSharpAssemblyName;
+            private const string CSharpBinderFlagsTypeName = "Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags, " + CSharpAssemblyName;
+
+            private static object _getCSharpArgumentInfoArray;
+            private static object _setCSharpArgumentInfoArray;
+            private static MethodCall<object, object> _getMemberCall;
+            private static MethodCall<object, object> _setMemberCall;
+            private static bool _init;
+
+            private static void Init()
+            {
+                if (!_init)
+                {
+                    Type binderType = Type.GetType(BinderTypeName, false);
+                    if (binderType == null)
+                        throw new InvalidOperationException("Could not resolve type '{0}'. You may need to add a reference to Microsoft.CSharp.dll to work with dynamic types.".FormatWith(CultureInfo.InvariantCulture, BinderTypeName));
+
+                    // None
+                    _getCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0);
+                    // None, Constant | UseCompileTimeType
+                    _setCSharpArgumentInfoArray = CreateSharpArgumentInfoArray(0, 3);
+                    CreateMemberCalls();
+
+                    _init = true;
+                }
+            }
+
+            private static object CreateSharpArgumentInfoArray(params int[] values)
+            {
+                Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName);
+                Type csharpArgumentInfoFlags = Type.GetType(CSharpArgumentInfoFlagsTypeName);
+
+                Array a = Array.CreateInstance(csharpArgumentInfoType, values.Length);
+
+                for (int i = 0; i < values.Length; i++)
+                {
+                    MethodInfo createArgumentInfoMethod = csharpArgumentInfoType.GetMethod("Create", new[] { csharpArgumentInfoFlags, typeof(string) });
+                    object arg = createArgumentInfoMethod.Invoke(null, new object[] { 0, null });
+                    a.SetValue(arg, i);
+                }
+
+                return a;
+            }
+
+            private static void CreateMemberCalls()
+            {
+                Type csharpArgumentInfoType = Type.GetType(CSharpArgumentInfoTypeName, true);
+                Type csharpBinderFlagsType = Type.GetType(CSharpBinderFlagsTypeName, true);
+                Type binderType = Type.GetType(BinderTypeName, true);
+
+                Type csharpArgumentInfoTypeEnumerableType = typeof(IEnumerable<>).MakeGenericType(csharpArgumentInfoType);
+
+                MethodInfo getMemberMethod = binderType.GetMethod("GetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
+                _getMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getMemberMethod);
+
+                MethodInfo setMemberMethod = binderType.GetMethod("SetMember", new[] { csharpBinderFlagsType, typeof(string), typeof(Type), csharpArgumentInfoTypeEnumerableType });
+                _setMemberCall = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(setMemberMethod);
+            }
+#endif
+
+            public static CallSiteBinder GetMember(string name, Type context)
+            {
+#if !(PORTABLE)
+                Init();
+                return (CallSiteBinder)_getMemberCall(null, 0, name, context, _getCSharpArgumentInfoArray);
+#else
+        return Binder.GetMember(
+          CSharpBinderFlags.None, name, context, new[] {CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
+#endif
+            }
+
+            public static CallSiteBinder SetMember(string name, Type context)
+            {
+#if !(PORTABLE)
+                Init();
+                return (CallSiteBinder)_setMemberCall(null, 0, name, context, _setCSharpArgumentInfoArray);
+#else
+        return Binder.SetMember(
+          CSharpBinderFlags.None, name, context, new[]
+                                                   {
+                                                     CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.UseCompileTimeType, null),
+                                                     CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null)
+                                                   });
+#endif
+            }
+        }
+
+        public static IEnumerable<string> GetDynamicMemberNames(this IDynamicMetaObjectProvider dynamicProvider)
+        {
+            DynamicMetaObject metaObject = dynamicProvider.GetMetaObject(Expression.Constant(dynamicProvider));
+            return metaObject.GetDynamicMemberNames();
+        }
+    }
+
+    internal class NoThrowGetBinderMember : GetMemberBinder
+    {
+        private readonly GetMemberBinder _innerBinder;
+
+        public NoThrowGetBinderMember(GetMemberBinder innerBinder)
+            : base(innerBinder.Name, innerBinder.IgnoreCase)
+        {
+            _innerBinder = innerBinder;
+        }
+
+        public override DynamicMetaObject FallbackGetMember(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
+        {
+            DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { });
+
+            NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
+            Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
+
+            DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
+            return finalMetaObject;
+        }
+    }
+
+    internal class NoThrowSetBinderMember : SetMemberBinder
+    {
+        private readonly SetMemberBinder _innerBinder;
+
+        public NoThrowSetBinderMember(SetMemberBinder innerBinder)
+            : base(innerBinder.Name, innerBinder.IgnoreCase)
+        {
+            _innerBinder = innerBinder;
+        }
+
+        public override DynamicMetaObject FallbackSetMember(DynamicMetaObject target, DynamicMetaObject value, DynamicMetaObject errorSuggestion)
+        {
+            DynamicMetaObject retMetaObject = _innerBinder.Bind(target, new DynamicMetaObject[] { value });
+
+            NoThrowExpressionVisitor noThrowVisitor = new NoThrowExpressionVisitor();
+            Expression resultExpression = noThrowVisitor.Visit(retMetaObject.Expression);
+
+            DynamicMetaObject finalMetaObject = new DynamicMetaObject(resultExpression, retMetaObject.Restrictions);
+            return finalMetaObject;
+        }
+    }
+
+    internal class NoThrowExpressionVisitor : ExpressionVisitor
+    {
+        internal static readonly object ErrorResult = new object();
+
+        protected override Expression VisitConditional(ConditionalExpression node)
+        {
+            // if the result of a test is to throw an error, rewrite to result an error result value
+            if (node.IfFalse.NodeType == ExpressionType.Throw)
+                return Expression.Condition(node.Test, node.IfTrue, Expression.Constant(ErrorResult));
+
+            return base.VisitConditional(node);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/DynamicWrapper.cs b/Newtonsoft.Json/Utilities/DynamicWrapper.cs
new file mode 100644
index 0000000..6bd6be7
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/DynamicWrapper.cs
@@ -0,0 +1,266 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Resources;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class DynamicWrapperBase
+    {
+        protected internal object UnderlyingObject;
+    }
+
+    internal static class DynamicWrapper
+    {
+        private static readonly object _lock = new object();
+        private static readonly WrapperDictionary _wrapperDictionary = new WrapperDictionary();
+
+        private static ModuleBuilder _moduleBuilder;
+
+        private static ModuleBuilder ModuleBuilder
+        {
+            get
+            {
+                Init();
+                return _moduleBuilder;
+            }
+        }
+
+        private static void Init()
+        {
+            if (_moduleBuilder == null)
+            {
+                lock (_lock)
+                {
+                    if (_moduleBuilder == null)
+                    {
+                        AssemblyName assemblyName = new AssemblyName("Newtonsoft.Json.Dynamic");
+                        assemblyName.KeyPair = new StrongNameKeyPair(GetStrongKey());
+
+                        AssemblyBuilder assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
+                        _moduleBuilder = assembly.DefineDynamicModule("Newtonsoft.Json.DynamicModule", false);
+                    }
+                }
+            }
+        }
+
+        private static byte[] GetStrongKey()
+        {
+            const string name = "Newtonsoft.Json.Dynamic.snk";
+
+            using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(name))
+            {
+                if (stream == null)
+                    throw new MissingManifestResourceException("Should have " + name + " as an embedded resource.");
+
+                int length = (int)stream.Length;
+                byte[] buffer = new byte[length];
+                stream.Read(buffer, 0, length);
+
+                return buffer;
+            }
+        }
+
+        public static Type GetWrapper(Type interfaceType, Type realObjectType)
+        {
+            Type wrapperType = _wrapperDictionary.GetType(interfaceType, realObjectType);
+
+            if (wrapperType == null)
+            {
+                lock (_lock)
+                {
+                    wrapperType = _wrapperDictionary.GetType(interfaceType, realObjectType);
+
+                    if (wrapperType == null)
+                    {
+                        wrapperType = GenerateWrapperType(interfaceType, realObjectType);
+                        _wrapperDictionary.SetType(interfaceType, realObjectType, wrapperType);
+                    }
+                }
+            }
+
+            return wrapperType;
+        }
+
+        public static object GetUnderlyingObject(object wrapper)
+        {
+            DynamicWrapperBase wrapperBase = wrapper as DynamicWrapperBase;
+            if (wrapperBase == null)
+                throw new ArgumentException("Object is not a wrapper.", "wrapper");
+
+            return wrapperBase.UnderlyingObject;
+        }
+
+        private static Type GenerateWrapperType(Type interfaceType, Type underlyingType)
+        {
+            TypeBuilder wrapperBuilder = ModuleBuilder.DefineType(
+                "{0}_{1}_Wrapper".FormatWith(CultureInfo.InvariantCulture, interfaceType.Name, underlyingType.Name),
+                TypeAttributes.NotPublic | TypeAttributes.Sealed,
+                typeof(DynamicWrapperBase),
+                new[] { interfaceType });
+
+            WrapperMethodBuilder wrapperMethod = new WrapperMethodBuilder(underlyingType, wrapperBuilder);
+
+            foreach (MethodInfo method in interfaceType.GetAllMethods())
+            {
+                wrapperMethod.Generate(method);
+            }
+
+            return wrapperBuilder.CreateType();
+        }
+
+        public static T CreateWrapper<T>(object realObject) where T : class
+        {
+            var dynamicType = GetWrapper(typeof(T), realObject.GetType());
+            var dynamicWrapper = (DynamicWrapperBase)Activator.CreateInstance(dynamicType);
+
+            dynamicWrapper.UnderlyingObject = realObject;
+
+            return dynamicWrapper as T;
+        }
+    }
+
+    internal class WrapperMethodBuilder
+    {
+        private readonly Type _realObjectType;
+        private readonly TypeBuilder _wrapperBuilder;
+
+        public WrapperMethodBuilder(Type realObjectType, TypeBuilder proxyBuilder)
+        {
+            _realObjectType = realObjectType;
+            _wrapperBuilder = proxyBuilder;
+        }
+
+        public void Generate(MethodInfo newMethod)
+        {
+            if (newMethod.IsGenericMethod)
+                newMethod = newMethod.GetGenericMethodDefinition();
+
+            FieldInfo srcField = typeof(DynamicWrapperBase).GetField("UnderlyingObject", BindingFlags.Instance | BindingFlags.NonPublic);
+
+            var parameters = newMethod.GetParameters();
+            var parameterTypes = parameters.Select(parameter => parameter.ParameterType).ToArray();
+
+            MethodBuilder methodBuilder = _wrapperBuilder.DefineMethod(
+                newMethod.Name,
+                MethodAttributes.Public | MethodAttributes.Virtual,
+                newMethod.ReturnType,
+                parameterTypes);
+
+            if (newMethod.IsGenericMethod)
+            {
+                methodBuilder.DefineGenericParameters(
+                    newMethod.GetGenericArguments().Select(arg => arg.Name).ToArray());
+            }
+
+            ILGenerator ilGenerator = methodBuilder.GetILGenerator();
+
+            LoadUnderlyingObject(ilGenerator, srcField);
+            PushParameters(parameters, ilGenerator);
+            ExecuteMethod(newMethod, parameterTypes, ilGenerator);
+            Return(ilGenerator);
+        }
+
+        private static void Return(ILGenerator ilGenerator)
+        {
+            ilGenerator.Emit(OpCodes.Ret);
+        }
+
+        private void ExecuteMethod(MethodBase newMethod, Type[] parameterTypes, ILGenerator ilGenerator)
+        {
+            MethodInfo srcMethod = GetMethod(newMethod, parameterTypes);
+
+            if (srcMethod == null)
+                throw new MissingMethodException("Unable to find method " + newMethod.Name + " on " + _realObjectType.FullName);
+
+            ilGenerator.Emit(OpCodes.Call, srcMethod);
+        }
+
+        private MethodInfo GetMethod(MethodBase realMethod, Type[] parameterTypes)
+        {
+            if (realMethod.IsGenericMethod)
+                return _realObjectType.GetGenericMethod(realMethod.Name, parameterTypes);
+
+            return _realObjectType.GetMethod(realMethod.Name, parameterTypes);
+        }
+
+        private static void PushParameters(ICollection<ParameterInfo> parameters, ILGenerator ilGenerator)
+        {
+            for (int i = 1; i < parameters.Count + 1; i++)
+                ilGenerator.Emit(OpCodes.Ldarg, i);
+        }
+
+        private static void LoadUnderlyingObject(ILGenerator ilGenerator, FieldInfo srcField)
+        {
+            ilGenerator.Emit(OpCodes.Ldarg_0);
+            ilGenerator.Emit(OpCodes.Ldfld, srcField);
+        }
+    }
+
+    internal class WrapperDictionary
+    {
+        private readonly Dictionary<string, Type> _wrapperTypes = new Dictionary<string, Type>();
+
+        private static string GenerateKey(Type interfaceType, Type realObjectType)
+        {
+            return interfaceType.Name + "_" + realObjectType.Name;
+        }
+
+        public Type GetType(Type interfaceType, Type realObjectType)
+        {
+            string key = GenerateKey(interfaceType, realObjectType);
+
+            if (_wrapperTypes.ContainsKey(key))
+                return _wrapperTypes[key];
+
+            return null;
+        }
+
+        public void SetType(Type interfaceType, Type realObjectType, Type wrapperType)
+        {
+            string key = GenerateKey(interfaceType, realObjectType);
+
+            if (_wrapperTypes.ContainsKey(key))
+                _wrapperTypes[key] = wrapperType;
+            else
+                _wrapperTypes.Add(key, wrapperType);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/EnumUtils.cs b/Newtonsoft.Json/Utilities/EnumUtils.cs
new file mode 100644
index 0000000..7cc78f1
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/EnumUtils.cs
@@ -0,0 +1,147 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using System.Reflection;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class EnumUtils
+    {
+        public static IList<T> GetFlagsValues<T>(T value) where T : struct
+        {
+            Type enumType = typeof(T);
+
+            if (!enumType.IsDefined(typeof(FlagsAttribute), false))
+                throw new ArgumentException("Enum type {0} is not a set of flags.".FormatWith(CultureInfo.InvariantCulture, enumType));
+
+            Type underlyingType = Enum.GetUnderlyingType(value.GetType());
+
+            ulong num = Convert.ToUInt64(value, CultureInfo.InvariantCulture);
+            EnumValues<ulong> enumNameValues = GetNamesAndValues<T>();
+            IList<T> selectedFlagsValues = new List<T>();
+
+            foreach (EnumValue<ulong> enumNameValue in enumNameValues)
+            {
+                if ((num & enumNameValue.Value) == enumNameValue.Value && enumNameValue.Value != 0)
+                    selectedFlagsValues.Add((T)Convert.ChangeType(enumNameValue.Value, underlyingType, CultureInfo.CurrentCulture));
+            }
+
+            if (selectedFlagsValues.Count == 0 && enumNameValues.SingleOrDefault(v => v.Value == 0) != null)
+                selectedFlagsValues.Add(default(T));
+
+            return selectedFlagsValues;
+        }
+
+        /// <summary>
+        /// Gets a dictionary of the names and values of an Enum type.
+        /// </summary>
+        /// <returns></returns>
+        public static EnumValues<ulong> GetNamesAndValues<T>() where T : struct
+        {
+            return GetNamesAndValues<ulong>(typeof(T));
+        }
+
+        /// <summary>
+        /// Gets a dictionary of the names and values of an Enum type.
+        /// </summary>
+        /// <param name="enumType">The enum type to get names and values for.</param>
+        /// <returns></returns>
+        public static EnumValues<TUnderlyingType> GetNamesAndValues<TUnderlyingType>(Type enumType) where TUnderlyingType : struct
+        {
+            if (enumType == null)
+                throw new ArgumentNullException("enumType");
+
+            ValidationUtils.ArgumentTypeIsEnum(enumType, "enumType");
+
+            IList<object> enumValues = GetValues(enumType);
+            IList<string> enumNames = GetNames(enumType);
+
+            EnumValues<TUnderlyingType> nameValues = new EnumValues<TUnderlyingType>();
+
+            for (int i = 0; i < enumValues.Count; i++)
+            {
+                try
+                {
+                    nameValues.Add(new EnumValue<TUnderlyingType>(enumNames[i], (TUnderlyingType)Convert.ChangeType(enumValues[i], typeof(TUnderlyingType), CultureInfo.CurrentCulture)));
+                }
+                catch (OverflowException e)
+                {
+                    throw new InvalidOperationException(
+                        string.Format(CultureInfo.InvariantCulture, "Value from enum with the underlying type of {0} cannot be added to dictionary with a value type of {1}. Value was too large: {2}",
+                            Enum.GetUnderlyingType(enumType), typeof(TUnderlyingType), Convert.ToUInt64(enumValues[i], CultureInfo.InvariantCulture)), e);
+                }
+            }
+
+            return nameValues;
+        }
+
+        public static IList<object> GetValues(Type enumType)
+        {
+            if (!enumType.IsEnum())
+                throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
+
+            List<object> values = new List<object>();
+
+            var fields = from field in enumType.GetFields()
+                where field.IsLiteral
+                select field;
+
+            foreach (FieldInfo field in fields)
+            {
+                object value = field.GetValue(enumType);
+                values.Add(value);
+            }
+
+            return values;
+        }
+
+        public static IList<string> GetNames(Type enumType)
+        {
+            if (!enumType.IsEnum())
+                throw new ArgumentException("Type '" + enumType.Name + "' is not an enum.");
+
+            List<string> values = new List<string>();
+
+            var fields = from field in enumType.GetFields()
+                where field.IsLiteral
+                select field;
+
+            foreach (FieldInfo field in fields)
+            {
+                values.Add(field.Name);
+            }
+
+            return values;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/EnumValue.cs b/Newtonsoft.Json/Utilities/EnumValue.cs
new file mode 100644
index 0000000..7ec8332
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/EnumValue.cs
@@ -0,0 +1,49 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class EnumValue<T> where T : struct
+    {
+        private readonly string _name;
+        private readonly T _value;
+
+        public string Name
+        {
+            get { return _name; }
+        }
+
+        public T Value
+        {
+            get { return _value; }
+        }
+
+        public EnumValue(string name, T value)
+        {
+            _name = name;
+            _value = value;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/EnumValues.cs b/Newtonsoft.Json/Utilities/EnumValues.cs
new file mode 100644
index 0000000..9092b56
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/EnumValues.cs
@@ -0,0 +1,37 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Collections.ObjectModel;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class EnumValues<T> : KeyedCollection<string, EnumValue<T>> where T : struct
+    {
+        protected override string GetKeyForItem(EnumValue<T> item)
+        {
+            return item.Name;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs b/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs
new file mode 100644
index 0000000..1016cc1
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs
@@ -0,0 +1,269 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(PORTABLE40 || NET20 || NET35)
+using System;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class ExpressionReflectionDelegateFactory : ReflectionDelegateFactory
+    {
+        private static readonly ExpressionReflectionDelegateFactory _instance = new ExpressionReflectionDelegateFactory();
+
+        internal static ReflectionDelegateFactory Instance
+        {
+            get { return _instance; }
+        }
+
+        public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
+        {
+            ValidationUtils.ArgumentNotNull(method, "method");
+
+            Type type = typeof(object);
+
+            ParameterExpression targetParameterExpression = Expression.Parameter(type, "target");
+            ParameterExpression argsParameterExpression = Expression.Parameter(typeof(object[]), "args");
+
+            ParameterInfo[] parametersInfo = method.GetParameters();
+
+            Expression[] argsExpression = new Expression[parametersInfo.Length];
+
+            for (int i = 0; i < parametersInfo.Length; i++)
+            {
+                Expression indexExpression = Expression.Constant(i);
+
+                Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
+
+                paramAccessorExpression = EnsureCastExpression(paramAccessorExpression, parametersInfo[i].ParameterType);
+
+                argsExpression[i] = paramAccessorExpression;
+            }
+
+            Expression callExpression;
+            if (method.IsConstructor)
+            {
+                callExpression = Expression.New((ConstructorInfo)method, argsExpression);
+            }
+            else if (method.IsStatic)
+            {
+                callExpression = Expression.Call((MethodInfo)method, argsExpression);
+            }
+            else
+            {
+                Expression readParameter = EnsureCastExpression(targetParameterExpression, method.DeclaringType);
+
+                callExpression = Expression.Call(readParameter, (MethodInfo)method, argsExpression);
+            }
+
+            if (method is MethodInfo)
+            {
+                MethodInfo m = (MethodInfo)method;
+                if (m.ReturnType != typeof(void))
+                    callExpression = EnsureCastExpression(callExpression, type);
+                else
+                    callExpression = Expression.Block(callExpression, Expression.Constant(null));
+            }
+            else
+            {
+                callExpression = EnsureCastExpression(callExpression, type);
+            }
+
+            LambdaExpression lambdaExpression = Expression.Lambda(typeof(MethodCall<T, object>), callExpression, targetParameterExpression, argsParameterExpression);
+
+            MethodCall<T, object> compiled = (MethodCall<T, object>)lambdaExpression.Compile();
+            return compiled;
+        }
+
+        public override Func<T> CreateDefaultConstructor<T>(Type type)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+
+            // avoid error from expressions compiler because of abstract class
+            if (type.IsAbstract())
+                return () => (T)Activator.CreateInstance(type);
+
+            try
+            {
+                Type resultType = typeof(T);
+
+                Expression expression = Expression.New(type);
+
+                expression = EnsureCastExpression(expression, resultType);
+
+                LambdaExpression lambdaExpression = Expression.Lambda(typeof(Func<T>), expression);
+
+                Func<T> compiled = (Func<T>)lambdaExpression.Compile();
+                return compiled;
+            }
+            catch
+            {
+                // an error can be thrown if constructor is not valid on Win8
+                // will have INVOCATION_FLAGS_NON_W8P_FX_API invocation flag
+                return () => (T)Activator.CreateInstance(type);
+            }
+        }
+
+        public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            Type instanceType = typeof(T);
+            Type resultType = typeof(object);
+
+            ParameterExpression parameterExpression = Expression.Parameter(instanceType, "instance");
+            Expression resultExpression;
+
+            MethodInfo getMethod = propertyInfo.GetGetMethod(true);
+
+            if (getMethod.IsStatic)
+            {
+                resultExpression = Expression.MakeMemberAccess(null, propertyInfo);
+            }
+            else
+            {
+                Expression readParameter = EnsureCastExpression(parameterExpression, propertyInfo.DeclaringType);
+
+                resultExpression = Expression.MakeMemberAccess(readParameter, propertyInfo);
+            }
+
+            resultExpression = EnsureCastExpression(resultExpression, resultType);
+
+            LambdaExpression lambdaExpression = Expression.Lambda(typeof(Func<T, object>), resultExpression, parameterExpression);
+
+            Func<T, object> compiled = (Func<T, object>)lambdaExpression.Compile();
+            return compiled;
+        }
+
+        public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
+        {
+            ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
+            ParameterExpression sourceParameter = Expression.Parameter(typeof(T), "source");
+
+            Expression fieldExpression;
+            if (fieldInfo.IsStatic)
+            {
+                fieldExpression = Expression.Field(null, fieldInfo);
+            }
+            else
+            {
+                Expression sourceExpression = EnsureCastExpression(sourceParameter, fieldInfo.DeclaringType);
+
+                fieldExpression = Expression.Field(sourceExpression, fieldInfo);
+            }
+
+            fieldExpression = EnsureCastExpression(fieldExpression, typeof(object));
+
+            Func<T, object> compiled = Expression.Lambda<Func<T, object>>(fieldExpression, sourceParameter).Compile();
+            return compiled;
+        }
+
+        public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
+        {
+            ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
+            // use reflection for structs
+            // expression doesn't correctly set value
+            if (fieldInfo.DeclaringType.IsValueType() || fieldInfo.IsInitOnly)
+                return LateBoundReflectionDelegateFactory.Instance.CreateSet<T>(fieldInfo);
+
+            ParameterExpression sourceParameterExpression = Expression.Parameter(typeof(T), "source");
+            ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object), "value");
+
+            Expression fieldExpression;
+            if (fieldInfo.IsStatic)
+            {
+                fieldExpression = Expression.Field(null, fieldInfo);
+            }
+            else
+            {
+                Expression sourceExpression = EnsureCastExpression(sourceParameterExpression, fieldInfo.DeclaringType);
+
+                fieldExpression = Expression.Field(sourceExpression, fieldInfo);
+            }
+
+            Expression valueExpression = EnsureCastExpression(valueParameterExpression, fieldExpression.Type);
+
+            BinaryExpression assignExpression = Expression.Assign(fieldExpression, valueExpression);
+
+            LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action<T, object>), assignExpression, sourceParameterExpression, valueParameterExpression);
+
+            Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
+            return compiled;
+        }
+
+        public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            // use reflection for structs
+            // expression doesn't correctly set value
+            if (propertyInfo.DeclaringType.IsValueType())
+                return LateBoundReflectionDelegateFactory.Instance.CreateSet<T>(propertyInfo);
+
+            Type instanceType = typeof(T);
+            Type valueType = typeof(object);
+
+            ParameterExpression instanceParameter = Expression.Parameter(instanceType, "instance");
+
+            ParameterExpression valueParameter = Expression.Parameter(valueType, "value");
+            Expression readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType);
+
+            MethodInfo setMethod = propertyInfo.GetSetMethod(true);
+
+            Expression setExpression;
+            if (setMethod.IsStatic)
+            {
+                setExpression = Expression.Call(setMethod, readValueParameter);
+            }
+            else
+            {
+                Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType);
+
+                setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter);
+            }
+
+            LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action<T, object>), setExpression, instanceParameter, valueParameter);
+
+            Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
+            return compiled;
+        }
+
+        private Expression EnsureCastExpression(Expression expression, Type targetType)
+        {
+            Type expressionType = expression.Type;
+
+            // check if a cast or conversion is required
+            if (expressionType == targetType || (!expressionType.IsValueType() && targetType.IsAssignableFrom(expressionType)))
+                return expression;
+
+            return Expression.Convert(expression, targetType);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/FSharpUtils.cs b/Newtonsoft.Json/Utilities/FSharpUtils.cs
new file mode 100644
index 0000000..23cad7c
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/FSharpUtils.cs
@@ -0,0 +1,156 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System.Threading;
+#if !(NET35 || NET20 || NETFX_CORE)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class FSharpUtils
+    {
+        private static readonly object Lock = new object();
+
+        private static bool _initialized;
+        private static MethodInfo _ofSeq;
+
+        public static Assembly FSharpCoreAssembly { get; private set; }
+        public static MethodCall<object, object> IsUnion { get; private set; }
+        public static MethodCall<object, object> GetUnionFields { get; private set; }
+        public static MethodCall<object, object> GetUnionCases { get; private set; }
+        public static MethodCall<object, object> MakeUnion { get; private set; }
+        public static Func<object, object> GetUnionCaseInfoName { get; private set; }
+        public static Func<object, object> GetUnionCaseInfo { get; private set; }
+        public static Func<object, object> GetUnionCaseFields { get; private set; }
+        public static MethodCall<object, object> GetUnionCaseInfoFields { get; private set; }
+
+        public const string FSharpSetTypeName = "FSharpSet`1";
+        public const string FSharpListTypeName = "FSharpList`1";
+        public const string FSharpMapTypeName = "FSharpMap`2";
+
+        public static void EnsureInitialized(Assembly fsharpCoreAssembly)
+        {
+            if (!_initialized)
+            {
+                lock (Lock)
+                {
+                    if (!_initialized)
+                    {
+                        FSharpCoreAssembly = fsharpCoreAssembly;
+
+                        Type fsharpType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpType");
+
+                        MethodInfo isUnionMethodInfo = fsharpType.GetMethod("IsUnion", BindingFlags.Public | BindingFlags.Static);
+                        IsUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(isUnionMethodInfo);
+
+                        MethodInfo getUnionCasesMethodInfo = fsharpType.GetMethod("GetUnionCases", BindingFlags.Public | BindingFlags.Static);
+                        GetUnionCases = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionCasesMethodInfo);
+
+                        Type fsharpValue = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.FSharpValue");
+
+                        MethodInfo getUnionFieldsMethodInfo = fsharpValue.GetMethod("GetUnionFields", BindingFlags.Public | BindingFlags.Static);
+                        GetUnionFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(getUnionFieldsMethodInfo);
+
+                        GetUnionCaseInfo = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item1"));
+                        GetUnionCaseFields = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(getUnionFieldsMethodInfo.ReturnType.GetProperty("Item2"));
+
+                        MethodInfo makeUnionMethodInfo = fsharpValue.GetMethod("MakeUnion", BindingFlags.Public | BindingFlags.Static);
+                        MakeUnion = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(makeUnionMethodInfo);
+
+                        Type unionCaseInfo = fsharpCoreAssembly.GetType("Microsoft.FSharp.Reflection.UnionCaseInfo");
+
+                        GetUnionCaseInfoName = JsonTypeReflector.ReflectionDelegateFactory.CreateGet<object>(unionCaseInfo.GetProperty("Name"));
+                        GetUnionCaseInfoFields = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(unionCaseInfo.GetMethod("GetFields"));
+
+                        Type listModule = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.ListModule");
+                        _ofSeq = listModule.GetMethod("OfSeq");
+
+#if !(NETFX_CORE || PORTABLE)
+                        Thread.MemoryBarrier();
+#endif
+                        _initialized = true;
+                    }
+                }
+            }
+        }
+
+        public static MethodInfo CreateSeq(Type t)
+        {
+            MethodInfo seqType = _ofSeq.MakeGenericMethod(t);
+
+            return seqType;
+        }
+
+        public static MethodInfo CreateMap(Type keyType, Type valueType)
+        {
+            Type t = typeof(FSharpMapCreator<,>).MakeGenericType(keyType, valueType);
+
+            MethodInfo initializeMethod = t.GetMethod("EnsureInitialized");
+
+            initializeMethod.Invoke(null, new object[] { FSharpCoreAssembly });
+
+            MethodInfo typedCreateMethod = t.GetMethod("CreateMapGeneric");
+
+            return typedCreateMethod;
+        }
+
+    }
+
+    internal static class FSharpMapCreator<TKey, TValue>
+    {
+        private static bool _initialized;
+        private static MethodCall<object, object> _createMap;
+
+        public static void EnsureInitialized(Assembly fsharpCoreAssembly)
+        {
+            if (!_initialized)
+            {
+                Type mapType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpMap`2");
+
+                Type genericMapType = mapType.MakeGenericType(typeof(TKey), typeof(TValue));
+
+                ConstructorInfo ctor = genericMapType.GetConstructor(new[] { typeof(IEnumerable<Tuple<TKey, TValue>>) });
+
+                _createMap = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(ctor);
+                
+                _initialized = true;
+            }
+        }
+
+        public static object CreateMapGeneric(IEnumerable<KeyValuePair<TKey, TValue>> values)
+        {
+            IEnumerable<Tuple<TKey, TValue>> tupleValues = values.Select(kv => new Tuple<TKey, TValue>(kv.Key, kv.Value));
+
+            object map = _createMap(null, tupleValues);
+            return map;
+        }
+    }
+}
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs b/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs
new file mode 100644
index 0000000..30fe674
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ILGeneratorExtensions.cs
@@ -0,0 +1,75 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(PORTABLE40 || PORTABLE || NETFX_CORE)
+using System;
+using System.Reflection.Emit;
+using System.Reflection;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class ILGeneratorExtensions
+    {
+        public static void PushInstance(this ILGenerator generator, Type type)
+        {
+            generator.Emit(OpCodes.Ldarg_0);
+            if (type.IsValueType())
+                generator.Emit(OpCodes.Unbox, type);
+            else
+                generator.Emit(OpCodes.Castclass, type);
+        }
+
+        public static void BoxIfNeeded(this ILGenerator generator, Type type)
+        {
+            if (type.IsValueType())
+                generator.Emit(OpCodes.Box, type);
+            else
+                generator.Emit(OpCodes.Castclass, type);
+        }
+
+        public static void UnboxIfNeeded(this ILGenerator generator, Type type)
+        {
+            if (type.IsValueType())
+                generator.Emit(OpCodes.Unbox_Any, type);
+            else
+                generator.Emit(OpCodes.Castclass, type);
+        }
+
+        public static void CallMethod(this ILGenerator generator, MethodInfo methodInfo)
+        {
+            if (methodInfo.IsFinal || !methodInfo.IsVirtual)
+                generator.Emit(OpCodes.Call, methodInfo);
+            else
+                generator.Emit(OpCodes.Callvirt, methodInfo);
+        }
+
+        public static void Return(this ILGenerator generator)
+        {
+            generator.Emit(OpCodes.Ret);
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs b/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs
new file mode 100644
index 0000000..13f54be
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ImmutableCollectionsUtils.cs
@@ -0,0 +1,167 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+#if !(NET20 || NET35 || NET40 || PORTABLE40)
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class ImmutableCollectionsUtils
+    {
+        internal class ImmutableCollectionTypeInfo
+        {
+            public ImmutableCollectionTypeInfo(string contractTypeName, string createdTypeName, string builderTypeName)
+            {
+                ContractTypeName = contractTypeName;
+                CreatedTypeName = createdTypeName;
+                BuilderTypeName = builderTypeName;
+            }
+
+            public string ContractTypeName { get; set; }
+            public string CreatedTypeName { get; set; }
+            public string BuilderTypeName { get; set; }
+        }
+
+        private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
+        private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
+        private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
+        private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
+
+        private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
+        private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
+
+        private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
+        private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
+
+        private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
+        private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
+
+        private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
+        private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
+
+        private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
+        private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
+
+        private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
+        private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
+
+        private static readonly IList<ImmutableCollectionTypeInfo> ArrayContractImmutableCollectionDefinitions = new List<ImmutableCollectionTypeInfo>
+        {
+            new ImmutableCollectionTypeInfo(ImmutableListGenericInterfaceTypeName, ImmutableListGenericTypeName, ImmutableListTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableListGenericTypeName, ImmutableListGenericTypeName, ImmutableListTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableQueueGenericInterfaceTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableQueueGenericTypeName, ImmutableQueueGenericTypeName, ImmutableQueueTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableStackGenericInterfaceTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableStackGenericTypeName, ImmutableStackGenericTypeName, ImmutableStackTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableSetGenericInterfaceTypeName, ImmutableSortedSetGenericTypeName, ImmutableSortedSetTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableSortedSetGenericTypeName, ImmutableSortedSetGenericTypeName, ImmutableSortedSetTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableHashSetGenericTypeName, ImmutableHashSetGenericTypeName, ImmutableHashSetTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableArrayGenericTypeName, ImmutableArrayGenericTypeName, ImmutableArrayTypeName)
+        };
+
+        private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDictionary`2";
+
+        private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
+        private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
+
+        private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary";
+        private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDictionary`2";
+
+        private static readonly IList<ImmutableCollectionTypeInfo> DictionaryContractImmutableCollectionDefinitions = new List<ImmutableCollectionTypeInfo>
+        {
+            new ImmutableCollectionTypeInfo(ImmutableDictionaryGenericInterfaceTypeName, ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryGenericTypeName, ImmutableSortedDictionaryTypeName),
+            new ImmutableCollectionTypeInfo(ImmutableDictionaryGenericTypeName, ImmutableDictionaryGenericTypeName, ImmutableDictionaryTypeName)
+        };
+
+        internal static bool TryBuildImmutableForArrayContract(Type underlyingType, Type collectionItemType, out Type createdType, out MethodBase parameterizedCreator)
+        {
+            if (underlyingType.IsGenericType())
+            {
+                string name = underlyingType.GetGenericTypeDefinition().FullName;
+                ImmutableCollectionTypeInfo definition = ArrayContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name);
+                if (definition != null)
+                {
+                    Type createdTypeDefinition = Type.GetType(definition.CreatedTypeName + ", System.Collections.Immutable");
+                    Type builderTypeDefinition = Type.GetType(definition.BuilderTypeName + ", System.Collections.Immutable");
+                    if (createdTypeDefinition != null && builderTypeDefinition != null)
+                    {
+                        MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m => m.Name == "CreateRange" && m.GetParameters().Length == 1);
+                        if (mb != null)
+                        {
+                            createdType = createdTypeDefinition.MakeGenericType(collectionItemType);
+                            parameterizedCreator = mb.MakeGenericMethod(collectionItemType);
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            createdType = null;
+            parameterizedCreator = null;
+            return false;
+        }
+
+        internal static bool TryBuildImmutableForDictionaryContract(Type underlyingType, Type keyItemType, Type valueItemType, out Type createdType, out MethodBase parameterizedCreator)
+        {
+            if (underlyingType.IsGenericType())
+            {
+                string name = underlyingType.GetGenericTypeDefinition().FullName;
+                ImmutableCollectionTypeInfo definition = DictionaryContractImmutableCollectionDefinitions.FirstOrDefault(d => d.ContractTypeName == name);
+                if (definition != null)
+                {
+                    Type createdTypeDefinition = Type.GetType(definition.CreatedTypeName + ", System.Collections.Immutable");
+                    Type builderTypeDefinition = Type.GetType(definition.BuilderTypeName + ", System.Collections.Immutable");
+                    if (createdTypeDefinition != null && builderTypeDefinition != null)
+                    {
+                        MethodInfo mb = builderTypeDefinition.GetMethods().FirstOrDefault(m =>
+                        {
+                            ParameterInfo[] parameters = m.GetParameters();
+
+                            return m.Name == "CreateRange" && parameters.Length == 1 && parameters[0].ParameterType.IsGenericType() && parameters[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>);
+                        });
+                        if (mb != null)
+                        {
+                            createdType = createdTypeDefinition.MakeGenericType(keyItemType, valueItemType);
+                            parameterizedCreator = mb.MakeGenericMethod(keyItemType, valueItemType);
+                            return true;
+                        }
+                    }
+                }
+            }
+
+            createdType = null;
+            parameterizedCreator = null;
+            return false;
+        }
+    }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/JavaScriptUtils.cs b/Newtonsoft.Json/Utilities/JavaScriptUtils.cs
new file mode 100644
index 0000000..58f8635
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/JavaScriptUtils.cs
@@ -0,0 +1,222 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class JavaScriptUtils
+    {
+        internal static readonly bool[] SingleQuoteCharEscapeFlags = new bool[128];
+        internal static readonly bool[] DoubleQuoteCharEscapeFlags = new bool[128];
+        internal static readonly bool[] HtmlCharEscapeFlags = new bool[128];
+
+        static JavaScriptUtils()
+        {
+            IList<char> escapeChars = new List<char>
+            {
+                '\n', '\r', '\t', '\\', '\f', '\b',
+            };
+            for (int i = 0; i < ' '; i++)
+            {
+                escapeChars.Add((char)i);
+            }
+
+            foreach (var escapeChar in escapeChars.Union(new[] { '\'' }))
+            {
+                SingleQuoteCharEscapeFlags[escapeChar] = true;
+            }
+            foreach (var escapeChar in escapeChars.Union(new[] { '"' }))
+            {
+                DoubleQuoteCharEscapeFlags[escapeChar] = true;
+            }
+            foreach (var escapeChar in escapeChars.Union(new[] { '"', '\'', '<', '>', '&' }))
+            {
+                HtmlCharEscapeFlags[escapeChar] = true;
+            }
+        }
+
+        private const string EscapedUnicodeText = "!";
+
+        public static void WriteEscapedJavaScriptString(TextWriter writer, string s, char delimiter, bool appendDelimiters,
+            bool[] charEscapeFlags, StringEscapeHandling stringEscapeHandling, ref char[] writeBuffer)
+        {
+            // leading delimiter
+            if (appendDelimiters)
+                writer.Write(delimiter);
+
+            if (s != null)
+            {
+                int lastWritePosition = 0;
+
+                for (int i = 0; i < s.Length; i++)
+                {
+                    var c = s[i];
+
+                    if (c < charEscapeFlags.Length && !charEscapeFlags[c])
+                        continue;
+
+                    string escapedValue;
+
+                    switch (c)
+                    {
+                        case '\t':
+                            escapedValue = @"\t";
+                            break;
+                        case '\n':
+                            escapedValue = @"\n";
+                            break;
+                        case '\r':
+                            escapedValue = @"\r";
+                            break;
+                        case '\f':
+                            escapedValue = @"\f";
+                            break;
+                        case '\b':
+                            escapedValue = @"\b";
+                            break;
+                        case '\\':
+                            escapedValue = @"\\";
+                            break;
+                        case '\u0085': // Next Line
+                            escapedValue = @"\u0085";
+                            break;
+                        case '\u2028': // Line Separator
+                            escapedValue = @"\u2028";
+                            break;
+                        case '\u2029': // Paragraph Separator
+                            escapedValue = @"\u2029";
+                            break;
+                        default:
+                            if (c < charEscapeFlags.Length || stringEscapeHandling == StringEscapeHandling.EscapeNonAscii)
+                            {
+                                if (c == '\'' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
+                                {
+                                    escapedValue = @"\'";
+                                }
+                                else if (c == '"' && stringEscapeHandling != StringEscapeHandling.EscapeHtml)
+                                {
+                                    escapedValue = @"\""";
+                                }
+                                else
+                                {
+                                    if (writeBuffer == null)
+                                        writeBuffer = new char[6];
+
+                                    StringUtils.ToCharAsUnicode(c, writeBuffer);
+
+                                    // slightly hacky but it saves multiple conditions in if test
+                                    escapedValue = EscapedUnicodeText;
+                                }
+                            }
+                            else
+                            {
+                                escapedValue = null;
+                            }
+                            break;
+                    }
+
+                    if (escapedValue == null)
+                        continue;
+
+                    bool isEscapedUnicodeText = string.Equals(escapedValue, EscapedUnicodeText);
+
+                    if (i > lastWritePosition)
+                    {
+                        int length = i - lastWritePosition + ((isEscapedUnicodeText) ? 6 : 0);
+                        int start = (isEscapedUnicodeText) ? 6 : 0;
+
+                        if (writeBuffer == null || writeBuffer.Length < length)
+                        {
+                            char[] newBuffer = new char[length];
+
+                            // the unicode text is already in the buffer
+                            // copy it over when creating new buffer
+                            if (isEscapedUnicodeText)
+                                Array.Copy(writeBuffer, newBuffer, 6);
+
+                            writeBuffer = newBuffer;
+                        }
+
+                        s.CopyTo(lastWritePosition, writeBuffer, start, length - start);
+
+                        // write unchanged chars before writing escaped text
+                        writer.Write(writeBuffer, start, length - start);
+                    }
+
+                    lastWritePosition = i + 1;
+                    if (!isEscapedUnicodeText)
+                        writer.Write(escapedValue);
+                    else
+                        writer.Write(writeBuffer, 0, 6);
+                }
+
+                if (lastWritePosition == 0)
+                {
+                    // no escaped text, write entire string
+                    writer.Write(s);
+                }
+                else
+                {
+                    int length = s.Length - lastWritePosition;
+
+                    if (writeBuffer == null || writeBuffer.Length < length)
+                        writeBuffer = new char[length];
+
+                    s.CopyTo(lastWritePosition, writeBuffer, 0, length);
+
+                    // write remaining text
+                    writer.Write(writeBuffer, 0, length);
+                }
+            }
+
+            // trailing delimiter
+            if (appendDelimiters)
+                writer.Write(delimiter);
+        }
+
+        public static string ToEscapedJavaScriptString(string value, char delimiter, bool appendDelimiters)
+        {
+            using (StringWriter w = StringUtils.CreateStringWriter(StringUtils.GetLength(value) ?? 16))
+            {
+                char[] buffer = null;
+                WriteEscapedJavaScriptString(w, value, delimiter, appendDelimiters, (delimiter == '"') ? DoubleQuoteCharEscapeFlags : SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, ref buffer);
+                return w.ToString();
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs b/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs
new file mode 100644
index 0000000..8755fd0
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/LateBoundReflectionDelegateFactory.cs
@@ -0,0 +1,96 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using Newtonsoft.Json.Serialization;
+using System.Reflection;
+
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class LateBoundReflectionDelegateFactory : ReflectionDelegateFactory
+    {
+        private static readonly LateBoundReflectionDelegateFactory _instance = new LateBoundReflectionDelegateFactory();
+
+        internal static ReflectionDelegateFactory Instance
+        {
+            get { return _instance; }
+        }
+
+        public override MethodCall<T, object> CreateMethodCall<T>(MethodBase method)
+        {
+            ValidationUtils.ArgumentNotNull(method, "method");
+
+            ConstructorInfo c = method as ConstructorInfo;
+            if (c != null)
+                return (o, a) => c.Invoke(a);
+
+            return (o, a) => method.Invoke(o, a);
+        }
+
+        public override Func<T> CreateDefaultConstructor<T>(Type type)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+
+            if (type.IsValueType())
+                return () => (T)Activator.CreateInstance(type);
+
+            ConstructorInfo constructorInfo = ReflectionUtils.GetDefaultConstructor(type, true);
+
+            return () => (T)constructorInfo.Invoke(null);
+        }
+
+        public override Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            return o => propertyInfo.GetValue(o, null);
+        }
+
+        public override Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
+        {
+            ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
+            return o => fieldInfo.GetValue(o);
+        }
+
+        public override Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
+        {
+            ValidationUtils.ArgumentNotNull(fieldInfo, "fieldInfo");
+
+            return (o, v) => fieldInfo.SetValue(o, v);
+        }
+
+        public override Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            return (o, v) => propertyInfo.SetValue(o, v, null);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/LinqBridge.cs b/Newtonsoft.Json/Utilities/LinqBridge.cs
new file mode 100644
index 0000000..771d834
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/LinqBridge.cs
@@ -0,0 +1,3014 @@
+
+#if NET20
+
+#region License, Terms and Author(s)
+//
+// LINQBridge
+// Copyright (c) 2007-9 Atif Aziz, Joseph Albahari. All rights reserved.
+//
+//  Author(s):
+//
+//      Atif Aziz, http://www.raboof.com
+//
+// This library is free software; you can redistribute it and/or modify it 
+// under the terms of the New BSD License, a copy of which should have 
+// been delivered along with this distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities.LinqBridge
+{
+  /// <summary>
+  /// Provides a set of static (Shared in Visual Basic) methods for 
+  /// querying objects that implement <see cref="IEnumerable{T}" />.
+  /// </summary>
+  internal static partial class Enumerable
+  {
+    /// <summary>
+    /// Returns the input typed as <see cref="IEnumerable{T}"/>.
+    /// </summary>
+
+    public static IEnumerable<TSource> AsEnumerable<TSource>(IEnumerable<TSource> source)
+    {
+      return source;
+    }
+
+    /// <summary>
+    /// Returns an empty <see cref="IEnumerable{T}"/> that has the 
+    /// specified type argument.
+    /// </summary>
+
+    public static IEnumerable<TResult> Empty<TResult>()
+    {
+      return Sequence<TResult>.Empty;
+    }
+
+    /// <summary>
+    /// Converts the elements of an <see cref="IEnumerable"/> to the 
+    /// specified type.
+    /// </summary>
+
+    public static IEnumerable<TResult> Cast<TResult>(
+      this IEnumerable source)
+    {
+      CheckNotNull(source, "source");
+
+      return CastYield<TResult>(source);
+    }
+
+    private static IEnumerable<TResult> CastYield<TResult>(
+      IEnumerable source)
+    {
+      foreach (var item in source)
+        yield return (TResult) item;
+    }
+
+    /// <summary>
+    /// Filters the elements of an <see cref="IEnumerable"/> based on a specified type.
+    /// </summary>
+
+    public static IEnumerable<TResult> OfType<TResult>(
+      this IEnumerable source)
+    {
+      CheckNotNull(source, "source");
+
+      return OfTypeYield<TResult>(source);
+    }
+
+    private static IEnumerable<TResult> OfTypeYield<TResult>(
+      IEnumerable source)
+    {
+      foreach (var item in source)
+        if (item is TResult)
+          yield return (TResult) item;
+    }
+
+    /// <summary>
+    /// Generates a sequence of integral numbers within a specified range.
+    /// </summary>
+    /// <param name="start">The value of the first integer in the sequence.</param>
+    /// <param name="count">The number of sequential integers to generate.</param>
+
+    public static IEnumerable<int> Range(int start, int count)
+    {
+      if (count < 0)
+        throw new ArgumentOutOfRangeException("count", count, null);
+
+      var end = (long) start + count;
+      if (end - 1 >= int.MaxValue)
+        throw new ArgumentOutOfRangeException("count", count, null);
+
+      return RangeYield(start, end);
+    }
+
+    private static IEnumerable<int> RangeYield(int start, long end)
+    {
+      for (var i = start; i < end; i++)
+        yield return i;
+    }
+
+    /// <summary>
+    /// Generates a sequence that contains one repeated value.
+    /// </summary>
+
+    public static IEnumerable<TResult> Repeat<TResult>(TResult element, int count)
+    {
+      if (count < 0) throw new ArgumentOutOfRangeException("count", count, null);
+
+      return RepeatYield(element, count);
+    }
+
+    private static IEnumerable<TResult> RepeatYield<TResult>(TResult element, int count)
+    {
+      for (var i = 0; i < count; i++)
+        yield return element;
+    }
+
+    /// <summary>
+    /// Filters a sequence of values based on a predicate.
+    /// </summary>
+
+    public static IEnumerable<TSource> Where<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      CheckNotNull(predicate, "predicate");
+
+      return source.Where((item, i) => predicate(item));
+    }
+
+    /// <summary>
+    /// Filters a sequence of values based on a predicate. 
+    /// Each element's index is used in the logic of the predicate function.
+    /// </summary>
+
+    public static IEnumerable<TSource> Where<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(predicate, "predicate");
+
+      return WhereYield(source, predicate);
+    }
+
+    private static IEnumerable<TSource> WhereYield<TSource>(
+      IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      var i = 0;
+      foreach (var item in source)
+        if (predicate(item, i++))
+          yield return item;
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence into a new form.
+    /// </summary>
+
+    public static IEnumerable<TResult> Select<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TResult> selector)
+    {
+      CheckNotNull(selector, "selector");
+
+      return source.Select((item, i) => selector(item));
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence into a new form by 
+    /// incorporating the element's index.
+    /// </summary>
+
+    public static IEnumerable<TResult> Select<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, TResult> selector)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(selector, "selector");
+
+      return SelectYield(source, selector);
+    }
+
+    private static IEnumerable<TResult> SelectYield<TSource, TResult>(
+      IEnumerable<TSource> source,
+      Func<TSource, int, TResult> selector)
+    {
+      var i = 0;
+      foreach (var item in source)
+        yield return selector(item, i++);
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence to an <see cref="IEnumerable{T}" /> 
+    /// and flattens the resulting sequences into one sequence.
+    /// </summary>
+
+    public static IEnumerable<TResult> SelectMany<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, IEnumerable<TResult>> selector)
+    {
+      CheckNotNull(selector, "selector");
+
+      return source.SelectMany((item, i) => selector(item));
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence to an <see cref="IEnumerable{T}" />, 
+    /// and flattens the resulting sequences into one sequence. The 
+    /// index of each source element is used in the projected form of 
+    /// that element.
+    /// </summary>
+
+    public static IEnumerable<TResult> SelectMany<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, IEnumerable<TResult>> selector)
+    {
+      CheckNotNull(selector, "selector");
+
+      return source.SelectMany(selector, (item, subitem) => subitem);
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence to an <see cref="IEnumerable{T}" />, 
+    /// flattens the resulting sequences into one sequence, and invokes 
+    /// a result selector function on each element therein.
+    /// </summary>
+
+    public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, IEnumerable<TCollection>> collectionSelector,
+      Func<TSource, TCollection, TResult> resultSelector)
+    {
+      CheckNotNull(collectionSelector, "collectionSelector");
+
+      return source.SelectMany((item, i) => collectionSelector(item), resultSelector);
+    }
+
+    /// <summary>
+    /// Projects each element of a sequence to an <see cref="IEnumerable{T}" />, 
+    /// flattens the resulting sequences into one sequence, and invokes 
+    /// a result selector function on each element therein. The index of 
+    /// each source element is used in the intermediate projected form 
+    /// of that element.
+    /// </summary>
+
+    public static IEnumerable<TResult> SelectMany<TSource, TCollection, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
+      Func<TSource, TCollection, TResult> resultSelector)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(collectionSelector, "collectionSelector");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      return SelectManyYield(source, collectionSelector, resultSelector);
+    }
+
+    private static IEnumerable<TResult> SelectManyYield<TSource, TCollection, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
+      Func<TSource, TCollection, TResult> resultSelector)
+    {
+      var i = 0;
+      foreach (var item in source)
+        foreach (var subitem in collectionSelector(item, i++))
+          yield return resultSelector(item, subitem);
+    }
+
+    /// <summary>
+    /// Returns elements from a sequence as long as a specified condition is true.
+    /// </summary>
+
+    public static IEnumerable<TSource> TakeWhile<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      CheckNotNull(predicate, "predicate");
+
+      return source.TakeWhile((item, i) => predicate(item));
+    }
+
+    /// <summary>
+    /// Returns elements from a sequence as long as a specified condition is true.
+    /// The element's index is used in the logic of the predicate function.
+    /// </summary>
+
+    public static IEnumerable<TSource> TakeWhile<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(predicate, "predicate");
+
+      return TakeWhileYield(source, predicate);
+    }
+
+    private static IEnumerable<TSource> TakeWhileYield<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      var i = 0;
+      foreach (var item in source)
+        if (predicate(item, i++))
+          yield return item;
+        else
+          break;
+    }
+
+    private static class Futures<T>
+    {
+      public static readonly Func<T> Default = () => default(T);
+      public static readonly Func<T> Undefined = () => { throw new InvalidOperationException(); };
+    }
+
+    /// <summary>
+    /// Base implementation of First operator.
+    /// </summary>
+
+    private static TSource FirstImpl<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource> empty)
+    {
+      CheckNotNull(source, "source");
+      Debug.Assert(empty != null);
+
+      var list = source as IList<TSource>; // optimized case for lists
+      if (list != null)
+        return list.Count > 0 ? list[0] : empty();
+
+      using (var e = source.GetEnumerator()) // fallback for enumeration
+        return e.MoveNext() ? e.Current : empty();
+    }
+
+    /// <summary>
+    /// Returns the first element of a sequence.
+    /// </summary>
+
+    public static TSource First<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.FirstImpl(Futures<TSource>.Undefined);
+    }
+
+    /// <summary>
+    /// Returns the first element in a sequence that satisfies a specified condition.
+    /// </summary>
+
+    public static TSource First<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return First(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Returns the first element of a sequence, or a default value if 
+    /// the sequence contains no elements.
+    /// </summary>
+
+    public static TSource FirstOrDefault<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.FirstImpl(Futures<TSource>.Default);
+    }
+
+    /// <summary>
+    /// Returns the first element of the sequence that satisfies a 
+    /// condition or a default value if no such element is found.
+    /// </summary>
+
+    public static TSource FirstOrDefault<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return FirstOrDefault(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Base implementation of Last operator.
+    /// </summary>
+
+    private static TSource LastImpl<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource> empty)
+    {
+      CheckNotNull(source, "source");
+
+      var list = source as IList<TSource>; // optimized case for lists
+      if (list != null)
+        return list.Count > 0 ? list[list.Count - 1] : empty();
+
+      using (var e = source.GetEnumerator())
+      {
+        if (!e.MoveNext())
+          return empty();
+
+        var last = e.Current;
+        while (e.MoveNext())
+          last = e.Current;
+
+        return last;
+      }
+    }
+
+    /// <summary>
+    /// Returns the last element of a sequence.
+    /// </summary>
+    public static TSource Last<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.LastImpl(Futures<TSource>.Undefined);
+    }
+
+    /// <summary>
+    /// Returns the last element of a sequence that satisfies a 
+    /// specified condition.
+    /// </summary>
+
+    public static TSource Last<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return Last(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Returns the last element of a sequence, or a default value if 
+    /// the sequence contains no elements.
+    /// </summary>
+
+    public static TSource LastOrDefault<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.LastImpl(Futures<TSource>.Default);
+    }
+
+    /// <summary>
+    /// Returns the last element of a sequence that satisfies a 
+    /// condition or a default value if no such element is found.
+    /// </summary>
+
+    public static TSource LastOrDefault<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return LastOrDefault(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Base implementation of Single operator.
+    /// </summary>
+
+    private static TSource SingleImpl<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource> empty)
+    {
+      CheckNotNull(source, "source");
+
+      using (var e = source.GetEnumerator())
+      {
+        if (e.MoveNext())
+        {
+          var single = e.Current;
+          if (!e.MoveNext())
+            return single;
+
+          throw new InvalidOperationException();
+        }
+
+        return empty();
+      }
+    }
+
+    /// <summary>
+    /// Returns the only element of a sequence, and throws an exception 
+    /// if there is not exactly one element in the sequence.
+    /// </summary>
+
+    public static TSource Single<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.SingleImpl(Futures<TSource>.Undefined);
+    }
+
+    /// <summary>
+    /// Returns the only element of a sequence that satisfies a 
+    /// specified condition, and throws an exception if more than one 
+    /// such element exists.
+    /// </summary>
+
+    public static TSource Single<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return Single(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Returns the only element of a sequence, or a default value if 
+    /// the sequence is empty; this method throws an exception if there 
+    /// is more than one element in the sequence.
+    /// </summary>
+
+    public static TSource SingleOrDefault<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.SingleImpl(Futures<TSource>.Default);
+    }
+
+    /// <summary>
+    /// Returns the only element of a sequence that satisfies a 
+    /// specified condition or a default value if no such element 
+    /// exists; this method throws an exception if more than one element 
+    /// satisfies the condition.
+    /// </summary>
+
+    public static TSource SingleOrDefault<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return SingleOrDefault(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Returns the element at a specified index in a sequence.
+    /// </summary>
+
+    public static TSource ElementAt<TSource>(
+      this IEnumerable<TSource> source,
+      int index)
+    {
+      CheckNotNull(source, "source");
+
+      if (index < 0)
+        throw new ArgumentOutOfRangeException("index", index, null);
+
+      var list = source as IList<TSource>;
+      if (list != null)
+        return list[index];
+
+      try
+      {
+        return source.SkipWhile((item, i) => i < index).First();
+      }
+      catch (InvalidOperationException) // if thrown by First
+      {
+        throw new ArgumentOutOfRangeException("index", index, null);
+      }
+    }
+
+    /// <summary>
+    /// Returns the element at a specified index in a sequence or a 
+    /// default value if the index is out of range.
+    /// </summary>
+
+    public static TSource ElementAtOrDefault<TSource>(
+      this IEnumerable<TSource> source,
+      int index)
+    {
+      CheckNotNull(source, "source");
+
+      if (index < 0)
+        return default(TSource);
+
+      var list = source as IList<TSource>;
+      if (list != null)
+        return index < list.Count ? list[index] : default(TSource);
+
+      return source.SkipWhile((item, i) => i < index).FirstOrDefault();
+    }
+
+    /// <summary>
+    /// Inverts the order of the elements in a sequence.
+    /// </summary>
+
+    public static IEnumerable<TSource> Reverse<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      CheckNotNull(source, "source");
+
+      return ReverseYield(source);
+    }
+
+    private static IEnumerable<TSource> ReverseYield<TSource>(IEnumerable<TSource> source)
+    {
+      var stack = new Stack<TSource>();
+      foreach (var item in source)
+        stack.Push(item);
+
+      foreach (var item in stack)
+        yield return item;
+    }
+
+    /// <summary>
+    /// Returns a specified number of contiguous elements from the start 
+    /// of a sequence.
+    /// </summary>
+
+    public static IEnumerable<TSource> Take<TSource>(
+      this IEnumerable<TSource> source,
+      int count)
+    {
+      return source.Where((item, i) => i < count);
+    }
+
+    /// <summary>
+    /// Bypasses a specified number of elements in a sequence and then 
+    /// returns the remaining elements.
+    /// </summary>
+
+    public static IEnumerable<TSource> Skip<TSource>(
+      this IEnumerable<TSource> source,
+      int count)
+    {
+      return source.Where((item, i) => i >= count);
+    }
+
+    /// <summary>
+    /// Bypasses elements in a sequence as long as a specified condition 
+    /// is true and then returns the remaining elements.
+    /// </summary>
+
+    public static IEnumerable<TSource> SkipWhile<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      CheckNotNull(predicate, "predicate");
+
+      return source.SkipWhile((item, i) => predicate(item));
+    }
+
+    /// <summary>
+    /// Bypasses elements in a sequence as long as a specified condition 
+    /// is true and then returns the remaining elements. The element's 
+    /// index is used in the logic of the predicate function.
+    /// </summary>
+
+    public static IEnumerable<TSource> SkipWhile<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(predicate, "predicate");
+
+      return SkipWhileYield(source, predicate);
+    }
+
+    private static IEnumerable<TSource> SkipWhileYield<TSource>(
+      IEnumerable<TSource> source,
+      Func<TSource, int, bool> predicate)
+    {
+      using (var e = source.GetEnumerator())
+      {
+        for (var i = 0;; i++)
+        {
+          if (!e.MoveNext())
+            yield break;
+
+          if (!predicate(e.Current, i))
+            break;
+        }
+
+        do
+        {
+          yield return e.Current;
+        } while (e.MoveNext());
+      }
+    }
+
+    /// <summary>
+    /// Returns the number of elements in a sequence.
+    /// </summary>
+
+    public static int Count<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      CheckNotNull(source, "source");
+
+      var collection = source as ICollection;
+      return collection != null
+               ? collection.Count
+               : source.Aggregate(0, (count, item) => checked(count + 1));
+    }
+
+    /// <summary>
+    /// Returns a number that represents how many elements in the 
+    /// specified sequence satisfy a condition.
+    /// </summary>
+
+    public static int Count<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return Count(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Returns an <see cref="Int64"/> that represents the total number 
+    /// of elements in a sequence.
+    /// </summary>
+
+    public static long LongCount<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      CheckNotNull(source, "source");
+
+      var array = source as Array;
+      return array != null
+               ? array.LongLength
+               : source.Aggregate(0L, (count, item) => count + 1);
+    }
+
+    /// <summary>
+    /// Returns an <see cref="Int64"/> that represents how many elements 
+    /// in a sequence satisfy a condition.
+    /// </summary>
+
+    public static long LongCount<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return LongCount(source.Where(predicate));
+    }
+
+    /// <summary>
+    /// Concatenates two sequences.
+    /// </summary>
+
+    public static IEnumerable<TSource> Concat<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      CheckNotNull(first, "first");
+      CheckNotNull(second, "second");
+
+      return ConcatYield(first, second);
+    }
+
+    private static IEnumerable<TSource> ConcatYield<TSource>(
+      IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      foreach (var item in first)
+        yield return item;
+
+      foreach (var item in second)
+        yield return item;
+    }
+
+    /// <summary>
+    /// Creates a <see cref="List{T}"/> from an <see cref="IEnumerable{T}"/>.
+    /// </summary>
+
+    public static List<TSource> ToList<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      CheckNotNull(source, "source");
+
+      return new List<TSource>(source);
+    }
+
+    /// <summary>
+    /// Creates an array from an <see cref="IEnumerable{T}"/>.
+    /// </summary>
+
+    public static TSource[] ToArray<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.ToList().ToArray();
+    }
+
+    /// <summary>
+    /// Returns distinct elements from a sequence by using the default 
+    /// equality comparer to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Distinct<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return Distinct(source, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Returns distinct elements from a sequence by using a specified 
+    /// <see cref="IEqualityComparer{T}"/> to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Distinct<TSource>(
+      this IEnumerable<TSource> source,
+      IEqualityComparer<TSource> comparer)
+    {
+      CheckNotNull(source, "source");
+
+      return DistinctYield(source, comparer);
+    }
+
+    private static IEnumerable<TSource> DistinctYield<TSource>(
+      IEnumerable<TSource> source,
+      IEqualityComparer<TSource> comparer)
+    {
+      var set = new Dictionary<TSource, object>(comparer);
+      var gotNull = false;
+
+      foreach (var item in source)
+      {
+        if (item == null)
+        {
+          if (gotNull)
+            continue;
+          gotNull = true;
+        }
+        else
+        {
+          if (set.ContainsKey(item))
+            continue;
+          set.Add(item, null);
+        }
+
+        yield return item;
+      }
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Lookup{TKey,TElement}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function.
+    /// </summary>
+
+    public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return ToLookup(source, keySelector, e => e, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Lookup{TKey,TElement}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function and a key comparer.
+    /// </summary>
+
+    public static ILookup<TKey, TSource> ToLookup<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      return ToLookup(source, keySelector, e => e, comparer);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Lookup{TKey,TElement}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to specified key 
+    /// and element selector functions.
+    /// </summary>
+
+    public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector)
+    {
+      return ToLookup(source, keySelector, elementSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Lookup{TKey,TElement}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function, a comparer and an element selector function.
+    /// </summary>
+
+    public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+      CheckNotNull(elementSelector, "elementSelector");
+
+      var lookup = new Lookup<TKey, TElement>(comparer);
+
+      foreach (var item in source)
+      {
+        var key = keySelector(item);
+
+        var grouping = (Grouping<TKey, TElement>) lookup.Find(key);
+        if (grouping == null)
+        {
+          grouping = new Grouping<TKey, TElement>(key);
+          lookup.Add(grouping);
+        }
+
+        grouping.Add(elementSelector(item));
+      }
+
+      return lookup;
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function.
+    /// </summary>
+
+    public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return GroupBy(source, keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and compares the keys by using a specified 
+    /// comparer.
+    /// </summary>
+
+    public static IEnumerable<IGrouping<TKey, TSource>> GroupBy<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      return GroupBy(source, keySelector, e => e, comparer);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and projects the elements for each group by 
+    /// using a specified function.
+    /// </summary>
+
+    public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector)
+    {
+      return GroupBy(source, keySelector, elementSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and creates a result value from each group and 
+    /// its key.
+    /// </summary>
+
+    public static IEnumerable<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+      CheckNotNull(elementSelector, "elementSelector");
+
+      return ToLookup(source, keySelector, elementSelector, comparer);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a key selector 
+    /// function. The keys are compared by using a comparer and each 
+    /// group's elements are projected by using a specified function.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
+    {
+      return GroupBy(source, keySelector, resultSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and creates a result value from each group and 
+    /// its key. The elements of each group are projected by using a 
+    /// specified function.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupBy<TSource, TKey, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      return ToLookup(source, keySelector, comparer).Select(g => resultSelector(g.Key, g));
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and creates a result value from each group and 
+    /// its key. The keys are compared by using a specified comparer.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector,
+      Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+    {
+      return GroupBy(source, keySelector, elementSelector, resultSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Groups the elements of a sequence according to a specified key 
+    /// selector function and creates a result value from each group and 
+    /// its key. Key values are compared by using a specified comparer, 
+    /// and the elements of each group are projected by using a 
+    /// specified function.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector,
+      Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+      CheckNotNull(elementSelector, "elementSelector");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      return ToLookup(source, keySelector, elementSelector, comparer)
+        .Select(g => resultSelector(g.Key, g));
+    }
+
+    /// <summary>
+    /// Applies an accumulator function over a sequence.
+    /// </summary>
+
+    public static TSource Aggregate<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TSource, TSource> func)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(func, "func");
+
+      using (var e = source.GetEnumerator())
+      {
+        if (!e.MoveNext())
+          throw new InvalidOperationException();
+
+        return e.Renumerable().Skip(1).Aggregate(e.Current, func);
+      }
+    }
+
+    /// <summary>
+    /// Applies an accumulator function over a sequence. The specified 
+    /// seed value is used as the initial accumulator value.
+    /// </summary>
+
+    public static TAccumulate Aggregate<TSource, TAccumulate>(
+      this IEnumerable<TSource> source,
+      TAccumulate seed,
+      Func<TAccumulate, TSource, TAccumulate> func)
+    {
+      return Aggregate(source, seed, func, r => r);
+    }
+
+    /// <summary>
+    /// Applies an accumulator function over a sequence. The specified 
+    /// seed value is used as the initial accumulator value, and the 
+    /// specified function is used to select the result value.
+    /// </summary>
+
+    public static TResult Aggregate<TSource, TAccumulate, TResult>(
+      this IEnumerable<TSource> source,
+      TAccumulate seed,
+      Func<TAccumulate, TSource, TAccumulate> func,
+      Func<TAccumulate, TResult> resultSelector)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(func, "func");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      var result = seed;
+
+      foreach (var item in source)
+        result = func(result, item);
+
+      return resultSelector(result);
+    }
+
+    /// <summary>
+    /// Produces the set union of two sequences by using the default 
+    /// equality comparer.
+    /// </summary>
+
+    public static IEnumerable<TSource> Union<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      return Union(first, second, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Produces the set union of two sequences by using a specified 
+    /// <see cref="IEqualityComparer{T}" />.
+    /// </summary>
+
+    public static IEnumerable<TSource> Union<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second,
+      IEqualityComparer<TSource> comparer)
+    {
+      return first.Concat(second).Distinct(comparer);
+    }
+
+    /// <summary>
+    /// Returns the elements of the specified sequence or the type 
+    /// parameter's default value in a singleton collection if the 
+    /// sequence is empty.
+    /// </summary>
+
+    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      return source.DefaultIfEmpty(default(TSource));
+    }
+
+    /// <summary>
+    /// Returns the elements of the specified sequence or the specified 
+    /// value in a singleton collection if the sequence is empty.
+    /// </summary>
+
+    public static IEnumerable<TSource> DefaultIfEmpty<TSource>(
+      this IEnumerable<TSource> source,
+      TSource defaultValue)
+    {
+      CheckNotNull(source, "source");
+
+      return DefaultIfEmptyYield(source, defaultValue);
+    }
+
+    private static IEnumerable<TSource> DefaultIfEmptyYield<TSource>(
+      IEnumerable<TSource> source,
+      TSource defaultValue)
+    {
+      using (var e = source.GetEnumerator())
+      {
+        if (!e.MoveNext())
+          yield return defaultValue;
+        else
+          do
+          {
+            yield return e.Current;
+          } while (e.MoveNext());
+      }
+    }
+
+    /// <summary>
+    /// Determines whether all elements of a sequence satisfy a condition.
+    /// </summary>
+
+    public static bool All<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(predicate, "predicate");
+
+      foreach (var item in source)
+        if (!predicate(item))
+          return false;
+
+      return true;
+    }
+
+    /// <summary>
+    /// Determines whether a sequence contains any elements.
+    /// </summary>
+
+    public static bool Any<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      CheckNotNull(source, "source");
+
+      using (var e = source.GetEnumerator())
+        return e.MoveNext();
+    }
+
+    /// <summary>
+    /// Determines whether any element of a sequence satisfies a 
+    /// condition.
+    /// </summary>
+
+    public static bool Any<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, bool> predicate)
+    {
+      return source.Where(predicate).Any();
+    }
+
+    /// <summary>
+    /// Determines whether a sequence contains a specified element by 
+    /// using the default equality comparer.
+    /// </summary>
+
+    public static bool Contains<TSource>(
+      this IEnumerable<TSource> source,
+      TSource value)
+    {
+      return source.Contains(value, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Determines whether a sequence contains a specified element by 
+    /// using a specified <see cref="IEqualityComparer{T}" />.
+    /// </summary>
+
+    public static bool Contains<TSource>(
+      this IEnumerable<TSource> source,
+      TSource value,
+      IEqualityComparer<TSource> comparer)
+    {
+      CheckNotNull(source, "source");
+
+      if (comparer == null)
+      {
+        var collection = source as ICollection<TSource>;
+        if (collection != null)
+          return collection.Contains(value);
+      }
+
+      comparer = comparer ?? EqualityComparer<TSource>.Default;
+      return source.Any(item => comparer.Equals(item, value));
+    }
+
+    /// <summary>
+    /// Determines whether two sequences are equal by comparing the 
+    /// elements by using the default equality comparer for their type.
+    /// </summary>
+
+    public static bool SequenceEqual<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      return first.SequenceEqual(second, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Determines whether two sequences are equal by comparing their 
+    /// elements by using a specified <see cref="IEqualityComparer{T}" />.
+    /// </summary>
+
+    public static bool SequenceEqual<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second,
+      IEqualityComparer<TSource> comparer)
+    {
+      CheckNotNull(first, "frist");
+      CheckNotNull(second, "second");
+
+      comparer = comparer ?? EqualityComparer<TSource>.Default;
+
+      using (IEnumerator<TSource> lhs = first.GetEnumerator(),
+                                  rhs = second.GetEnumerator())
+      {
+        do
+        {
+          if (!lhs.MoveNext())
+            return !rhs.MoveNext();
+
+          if (!rhs.MoveNext())
+            return false;
+        } while (comparer.Equals(lhs.Current, rhs.Current));
+      }
+
+      return false;
+    }
+
+    /// <summary>
+    /// Base implementation for Min/Max operator.
+    /// </summary>
+
+    private static TSource MinMaxImpl<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TSource, bool> lesser)
+    {
+      CheckNotNull(source, "source");
+      Debug.Assert(lesser != null);
+
+      return source.Aggregate((a, item) => lesser(a, item) ? a : item);
+    }
+
+    /// <summary>
+    /// Base implementation for Min/Max operator for nullable types.
+    /// </summary>
+
+    private static TSource? MinMaxImpl<TSource>(
+      this IEnumerable<TSource?> source,
+      TSource? seed, Func<TSource?, TSource?, bool> lesser) where TSource : struct
+    {
+      CheckNotNull(source, "source");
+      Debug.Assert(lesser != null);
+
+      return source.Aggregate(seed, (a, item) => lesser(a, item) ? a : item);
+      //  == MinMaxImpl(Repeat<TSource?>(null, 1).Concat(source), lesser);
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a generic sequence.
+    /// </summary>
+
+    public static TSource Min<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      var comparer = Comparer<TSource>.Default;
+      return source.MinMaxImpl((x, y) => comparer.Compare(x, y) < 0);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a generic 
+    /// sequence and returns the minimum resulting value.
+    /// </summary>
+
+    public static TResult Min<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TResult> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a generic sequence.
+    /// </summary>
+
+    public static TSource Max<TSource>(
+      this IEnumerable<TSource> source)
+    {
+      var comparer = Comparer<TSource>.Default;
+      return source.MinMaxImpl((x, y) => comparer.Compare(x, y) > 0);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a generic 
+    /// sequence and returns the maximum resulting value.
+    /// </summary>
+
+    public static TResult Max<TSource, TResult>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TResult> selector)
+    {
+      return source.Select(selector).Max();
+    }
+
+    /// <summary>
+    /// Makes an enumerator seen as enumerable once more.
+    /// </summary>
+    /// <remarks>
+    /// The supplied enumerator must have been started. The first element
+    /// returned is the element the enumerator was on when passed in.
+    /// DO NOT use this method if the caller must be a generator. It is
+    /// mostly safe among aggregate operations.
+    /// </remarks>
+
+    private static IEnumerable<T> Renumerable<T>(this IEnumerator<T> e)
+    {
+      Debug.Assert(e != null);
+
+      do
+      {
+        yield return e.Current;
+      } while (e.MoveNext());
+    }
+
+    /// <summary>
+    /// Sorts the elements of a sequence in ascending order according to a key.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return source.OrderBy(keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Sorts the elements of a sequence in ascending order by using a 
+    /// specified comparer.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+
+      return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, /* descending */ false);
+    }
+
+    /// <summary>
+    /// Sorts the elements of a sequence in descending order according to a key.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return source.OrderByDescending(keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    ///  Sorts the elements of a sequence in descending order by using a 
+    /// specified comparer. 
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(source, "keySelector");
+
+      return new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, /* descending */ true);
+    }
+
+    /// <summary>
+    /// Performs a subsequent ordering of the elements in a sequence in 
+    /// ascending order according to a key.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(
+      this IOrderedEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return source.ThenBy(keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Performs a subsequent ordering of the elements in a sequence in 
+    /// ascending order by using a specified comparer.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(
+      this IOrderedEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+
+      return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ false);
+    }
+
+    /// <summary>
+    /// Performs a subsequent ordering of the elements in a sequence in 
+    /// descending order, according to a key.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(
+      this IOrderedEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return source.ThenByDescending(keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Performs a subsequent ordering of the elements in a sequence in 
+    /// descending order by using a specified comparer.
+    /// </summary>
+
+    public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(
+      this IOrderedEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+
+      return source.CreateOrderedEnumerable(keySelector, comparer, /* descending */ true);
+    }
+
+    /// <summary>
+    /// Base implementation for Intersect and Except operators.
+    /// </summary>
+
+    private static IEnumerable<TSource> IntersectExceptImpl<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second,
+      IEqualityComparer<TSource> comparer,
+      bool flag)
+    {
+      CheckNotNull(first, "first");
+      CheckNotNull(second, "second");
+
+      var keys = new List<TSource>();
+      var flags = new Dictionary<TSource, bool>(comparer);
+
+      foreach (var item in first.Where(k => !flags.ContainsKey(k)))
+      {
+        flags.Add(item, !flag);
+        keys.Add(item);
+      }
+
+      foreach (var item in second.Where(flags.ContainsKey))
+        flags[item] = flag;
+
+      //
+      // As per docs, "the marked elements are yielded in the order in 
+      // which they were collected.
+      //
+
+      return keys.Where(item => flags[item]);
+    }
+
+    /// <summary>
+    /// Produces the set intersection of two sequences by using the 
+    /// default equality comparer to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Intersect<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      return first.Intersect(second, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Produces the set intersection of two sequences by using the 
+    /// specified <see cref="IEqualityComparer{T}" /> to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Intersect<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second,
+      IEqualityComparer<TSource> comparer)
+    {
+      return IntersectExceptImpl(first, second, comparer, /* flag */ true);
+    }
+
+    /// <summary>
+    /// Produces the set difference of two sequences by using the 
+    /// default equality comparer to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Except<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second)
+    {
+      return first.Except(second, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Produces the set difference of two sequences by using the 
+    /// specified <see cref="IEqualityComparer{T}" /> to compare values.
+    /// </summary>
+
+    public static IEnumerable<TSource> Except<TSource>(
+      this IEnumerable<TSource> first,
+      IEnumerable<TSource> second,
+      IEqualityComparer<TSource> comparer)
+    {
+      return IntersectExceptImpl(first, second, comparer, /* flag */ false);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Dictionary{TKey,TValue}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function.
+    /// </summary>
+
+    public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector)
+    {
+      return source.ToDictionary(keySelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Dictionary{TKey,TValue}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function and key comparer.
+    /// </summary>
+
+    public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      return source.ToDictionary(keySelector, e => e);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Dictionary{TKey,TValue}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to specified key 
+    /// selector and element selector functions.
+    /// </summary>
+
+    public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector)
+    {
+      return source.ToDictionary(keySelector, elementSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Creates a <see cref="Dictionary{TKey,TValue}" /> from an 
+    /// <see cref="IEnumerable{T}" /> according to a specified key 
+    /// selector function, a comparer, and an element selector function.
+    /// </summary>
+
+    public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
+      this IEnumerable<TSource> source,
+      Func<TSource, TKey> keySelector,
+      Func<TSource, TElement> elementSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(source, "source");
+      CheckNotNull(keySelector, "keySelector");
+      CheckNotNull(elementSelector, "elementSelector");
+
+      var dict = new Dictionary<TKey, TElement>(comparer);
+
+      foreach (var item in source)
+      {
+        //
+        // ToDictionary is meant to throw ArgumentNullException if
+        // keySelector produces a key that is null and 
+        // Argument exception if keySelector produces duplicate keys 
+        // for two elements. Incidentally, the doucmentation for
+        // IDictionary<TKey, TValue>.Add says that the Add method
+        // throws the same exceptions under the same circumstances
+        // so we don't need to do any additional checking or work
+        // here and let the Add implementation do all the heavy
+        // lifting.
+        //
+
+        dict.Add(keySelector(item), elementSelector(item));
+      }
+
+      return dict;
+    }
+
+    /// <summary>
+    /// Correlates the elements of two sequences based on matching keys. 
+    /// The default equality comparer is used to compare keys.
+    /// </summary>
+
+    public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
+      this IEnumerable<TOuter> outer,
+      IEnumerable<TInner> inner,
+      Func<TOuter, TKey> outerKeySelector,
+      Func<TInner, TKey> innerKeySelector,
+      Func<TOuter, TInner, TResult> resultSelector)
+    {
+      return outer.Join(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Correlates the elements of two sequences based on matching keys. 
+    /// The default equality comparer is used to compare keys. A 
+    /// specified <see cref="IEqualityComparer{T}" /> is used to compare keys.
+    /// </summary>
+
+    public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
+      this IEnumerable<TOuter> outer,
+      IEnumerable<TInner> inner,
+      Func<TOuter, TKey> outerKeySelector,
+      Func<TInner, TKey> innerKeySelector,
+      Func<TOuter, TInner, TResult> resultSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(outer, "outer");
+      CheckNotNull(inner, "inner");
+      CheckNotNull(outerKeySelector, "outerKeySelector");
+      CheckNotNull(innerKeySelector, "innerKeySelector");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      var lookup = inner.ToLookup(innerKeySelector, comparer);
+
+      return
+        from o in outer
+        from i in lookup[outerKeySelector(o)]
+        select resultSelector(o, i);
+    }
+
+    /// <summary>
+    /// Correlates the elements of two sequences based on equality of 
+    /// keys and groups the results. The default equality comparer is 
+    /// used to compare keys.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
+      this IEnumerable<TOuter> outer,
+      IEnumerable<TInner> inner,
+      Func<TOuter, TKey> outerKeySelector,
+      Func<TInner, TKey> innerKeySelector,
+      Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
+    {
+      return outer.GroupJoin(inner, outerKeySelector, innerKeySelector, resultSelector, /* comparer */ null);
+    }
+
+    /// <summary>
+    /// Correlates the elements of two sequences based on equality of 
+    /// keys and groups the results. The default equality comparer is 
+    /// used to compare keys. A specified <see cref="IEqualityComparer{T}" /> 
+    /// is used to compare keys.
+    /// </summary>
+
+    public static IEnumerable<TResult> GroupJoin<TOuter, TInner, TKey, TResult>(
+      this IEnumerable<TOuter> outer,
+      IEnumerable<TInner> inner,
+      Func<TOuter, TKey> outerKeySelector,
+      Func<TInner, TKey> innerKeySelector,
+      Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
+      IEqualityComparer<TKey> comparer)
+    {
+      CheckNotNull(outer, "outer");
+      CheckNotNull(inner, "inner");
+      CheckNotNull(outerKeySelector, "outerKeySelector");
+      CheckNotNull(innerKeySelector, "innerKeySelector");
+      CheckNotNull(resultSelector, "resultSelector");
+
+      var lookup = inner.ToLookup(innerKeySelector, comparer);
+      return outer.Select(o => resultSelector(o, lookup[outerKeySelector(o)]));
+    }
+
+    [DebuggerStepThrough]
+    private static void CheckNotNull<T>(T value, string name) where T : class
+    {
+      if (value == null)
+        throw new ArgumentNullException(name);
+    }
+
+    private static class Sequence<T>
+    {
+      public static readonly IEnumerable<T> Empty = new T[0];
+    }
+
+    private sealed class Grouping<K, V> : List<V>, IGrouping<K, V>
+    {
+      internal Grouping(K key)
+      {
+        Key = key;
+      }
+
+      public K Key { get; private set; }
+    }
+  }
+
+  internal partial class Enumerable
+  {
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static int Sum(
+      this IEnumerable<int> source)
+    {
+      CheckNotNull(source, "source");
+
+      int sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + num);
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Int32" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static int Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static double Average(
+      this IEnumerable<int> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      long count = 0;
+
+      foreach (var num in source)
+        checked
+        {
+          sum += (int) num;
+          count++;
+        }
+
+      if (count == 0)
+        throw new InvalidOperationException();
+
+      return (double) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Int32" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static int? Sum(
+      this IEnumerable<int?> source)
+    {
+      CheckNotNull(source, "source");
+
+      int sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + (num ?? 0));
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Int32" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static int? Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int?> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static double? Average(
+      this IEnumerable<int?> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      long count = 0;
+
+      foreach (var num in source.Where(n => n != null))
+        checked
+        {
+          sum += (int) num;
+          count++;
+        }
+
+      if (count == 0)
+        return null;
+
+      return (double?) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Int32" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double? Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int?> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a sequence of nullable 
+    /// <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static int? Min(
+      this IEnumerable<int?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the minimum nullable <see cref="System.Int32" /> value.
+    /// </summary>
+
+    public static int? Min<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int?> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a sequence of nullable 
+    /// <see cref="System.Int32" /> values.
+    /// </summary>
+
+    public static int? Max(
+      this IEnumerable<int?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null),
+                        null, (max, x) => x == null || (max != null && x.Value < max.Value));
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the maximum nullable <see cref="System.Int32" /> value.
+    /// </summary>
+
+    public static int? Max<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, int?> selector)
+    {
+      return source.Select(selector).Max();
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static long Sum(
+      this IEnumerable<long> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + num);
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Int64" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static long Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static double Average(
+      this IEnumerable<long> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      long count = 0;
+
+      foreach (var num in source)
+        checked
+        {
+          sum += (long) num;
+          count++;
+        }
+
+      if (count == 0)
+        throw new InvalidOperationException();
+
+      return (double) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Int64" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static long? Sum(
+      this IEnumerable<long?> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + (num ?? 0));
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Int64" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static long? Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long?> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static double? Average(
+      this IEnumerable<long?> source)
+    {
+      CheckNotNull(source, "source");
+
+      long sum = 0;
+      long count = 0;
+
+      foreach (var num in source.Where(n => n != null))
+        checked
+        {
+          sum += (long) num;
+          count++;
+        }
+
+      if (count == 0)
+        return null;
+
+      return (double?) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Int64" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double? Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long?> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a sequence of nullable 
+    /// <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static long? Min(
+      this IEnumerable<long?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the minimum nullable <see cref="System.Int64" /> value.
+    /// </summary>
+
+    public static long? Min<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long?> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a sequence of nullable 
+    /// <see cref="System.Int64" /> values.
+    /// </summary>
+
+    public static long? Max(
+      this IEnumerable<long?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null),
+                        null, (max, x) => x == null || (max != null && x.Value < max.Value));
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the maximum nullable <see cref="System.Int64" /> value.
+    /// </summary>
+
+    public static long? Max<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, long?> selector)
+    {
+      return source.Select(selector).Max();
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float Sum(
+      this IEnumerable<float> source)
+    {
+      CheckNotNull(source, "source");
+
+      float sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + num);
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Single" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static float Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float Average(
+      this IEnumerable<float> source)
+    {
+      CheckNotNull(source, "source");
+
+      float sum = 0;
+      long count = 0;
+
+      foreach (var num in source)
+        checked
+        {
+          sum += (float) num;
+          count++;
+        }
+
+      if (count == 0)
+        throw new InvalidOperationException();
+
+      return (float) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Single" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static float Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float? Sum(
+      this IEnumerable<float?> source)
+    {
+      CheckNotNull(source, "source");
+
+      float sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + (num ?? 0));
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Single" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static float? Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float?> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float? Average(
+      this IEnumerable<float?> source)
+    {
+      CheckNotNull(source, "source");
+
+      float sum = 0;
+      long count = 0;
+
+      foreach (var num in source.Where(n => n != null))
+        checked
+        {
+          sum += (float) num;
+          count++;
+        }
+
+      if (count == 0)
+        return null;
+
+      return (float?) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Single" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static float? Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float?> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a sequence of nullable 
+    /// <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float? Min(
+      this IEnumerable<float?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the minimum nullable <see cref="System.Single" /> value.
+    /// </summary>
+
+    public static float? Min<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float?> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a sequence of nullable 
+    /// <see cref="System.Single" /> values.
+    /// </summary>
+
+    public static float? Max(
+      this IEnumerable<float?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null),
+                        null, (max, x) => x == null || (max != null && x.Value < max.Value));
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the maximum nullable <see cref="System.Single" /> value.
+    /// </summary>
+
+    public static float? Max<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, float?> selector)
+    {
+      return source.Select(selector).Max();
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double Sum(
+      this IEnumerable<double> source)
+    {
+      CheckNotNull(source, "source");
+
+      double sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + num);
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Double" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static double Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double Average(
+      this IEnumerable<double> source)
+    {
+      CheckNotNull(source, "source");
+
+      double sum = 0;
+      long count = 0;
+
+      foreach (var num in source)
+        checked
+        {
+          sum += (double) num;
+          count++;
+        }
+
+      if (count == 0)
+        throw new InvalidOperationException();
+
+      return (double) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Double" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double? Sum(
+      this IEnumerable<double?> source)
+    {
+      CheckNotNull(source, "source");
+
+      double sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + (num ?? 0));
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Double" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static double? Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double?> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double? Average(
+      this IEnumerable<double?> source)
+    {
+      CheckNotNull(source, "source");
+
+      double sum = 0;
+      long count = 0;
+
+      foreach (var num in source.Where(n => n != null))
+        checked
+        {
+          sum += (double) num;
+          count++;
+        }
+
+      if (count == 0)
+        return null;
+
+      return (double?) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Double" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static double? Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double?> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a sequence of nullable 
+    /// <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double? Min(
+      this IEnumerable<double?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the minimum nullable <see cref="System.Double" /> value.
+    /// </summary>
+
+    public static double? Min<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double?> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a sequence of nullable 
+    /// <see cref="System.Double" /> values.
+    /// </summary>
+
+    public static double? Max(
+      this IEnumerable<double?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null),
+                        null, (max, x) => x == null || (max != null && x.Value < max.Value));
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the maximum nullable <see cref="System.Double" /> value.
+    /// </summary>
+
+    public static double? Max<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, double?> selector)
+    {
+      return source.Select(selector).Max();
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal Sum(
+      this IEnumerable<decimal> source)
+    {
+      CheckNotNull(source, "source");
+
+      decimal sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + num);
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of nullable <see cref="System.Decimal" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static decimal Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal Average(
+      this IEnumerable<decimal> source)
+    {
+      CheckNotNull(source, "source");
+
+      decimal sum = 0;
+      long count = 0;
+
+      foreach (var num in source)
+        checked
+        {
+          sum += (decimal) num;
+          count++;
+        }
+
+      if (count == 0)
+        throw new InvalidOperationException();
+
+      return (decimal) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of nullable <see cref="System.Decimal" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static decimal Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal? Sum(
+      this IEnumerable<decimal?> source)
+    {
+      CheckNotNull(source, "source");
+
+      decimal sum = 0;
+      foreach (var num in source)
+        sum = checked(sum + (num ?? 0));
+
+      return sum;
+    }
+
+    /// <summary>
+    /// Computes the sum of a sequence of <see cref="System.Decimal" /> 
+    /// values that are obtained by invoking a transform function on 
+    /// each element of the input sequence.
+    /// </summary>
+
+    public static decimal? Sum<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal?> selector)
+    {
+      return source.Select(selector).Sum();
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal? Average(
+      this IEnumerable<decimal?> source)
+    {
+      CheckNotNull(source, "source");
+
+      decimal sum = 0;
+      long count = 0;
+
+      foreach (var num in source.Where(n => n != null))
+        checked
+        {
+          sum += (decimal) num;
+          count++;
+        }
+
+      if (count == 0)
+        return null;
+
+      return (decimal?) sum/count;
+    }
+
+    /// <summary>
+    /// Computes the average of a sequence of <see cref="System.Decimal" /> values 
+    /// that are obtained by invoking a transform function on each 
+    /// element of the input sequence.
+    /// </summary>
+
+    public static decimal? Average<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal?> selector)
+    {
+      return source.Select(selector).Average();
+    }
+
+    /// <summary>
+    /// Returns the minimum value in a sequence of nullable 
+    /// <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal? Min(
+      this IEnumerable<decimal?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null), null, (min, x) => min < x);
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the minimum nullable <see cref="System.Decimal" /> value.
+    /// </summary>
+
+    public static decimal? Min<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal?> selector)
+    {
+      return source.Select(selector).Min();
+    }
+
+    /// <summary>
+    /// Returns the maximum value in a sequence of nullable 
+    /// <see cref="System.Decimal" /> values.
+    /// </summary>
+
+    public static decimal? Max(
+      this IEnumerable<decimal?> source)
+    {
+      CheckNotNull(source, "source");
+
+      return MinMaxImpl(source.Where(x => x != null),
+                        null, (max, x) => x == null || (max != null && x.Value < max.Value));
+    }
+
+    /// <summary>
+    /// Invokes a transform function on each element of a sequence and 
+    /// returns the maximum nullable <see cref="System.Decimal" /> value.
+    /// </summary>
+
+    public static decimal? Max<TSource>(
+      this IEnumerable<TSource> source,
+      Func<TSource, decimal?> selector)
+    {
+      return source.Select(selector).Max();
+    }
+  }
+
+  /// <summary>
+  /// Represents a collection of objects that have a common key.
+  /// </summary>
+  internal partial interface IGrouping<TKey, TElement> : IEnumerable<TElement>
+  {
+    /// <summary>
+    /// Gets the key of the <see cref="IGrouping{TKey,TElement}" />.
+    /// </summary>
+
+    TKey Key { get; }
+  }
+
+  /// <summary>
+  /// Defines an indexer, size property, and Boolean search method for 
+  /// data structures that map keys to <see cref="IEnumerable{T}"/> 
+  /// sequences of values.
+  /// </summary>
+  internal partial interface ILookup<TKey, TElement> : IEnumerable<IGrouping<TKey, TElement>>
+  {
+    bool Contains(TKey key);
+    int Count { get; }
+    IEnumerable<TElement> this[TKey key] { get; }
+  }
+
+  /// <summary>
+  /// Represents a sorted sequence.
+  /// </summary>
+  internal partial interface IOrderedEnumerable<TElement> : IEnumerable<TElement>
+  {
+    /// <summary>
+    /// Performs a subsequent ordering on the elements of an 
+    /// <see cref="IOrderedEnumerable{T}"/> according to a key.
+    /// </summary>
+
+    IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(
+      Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending);
+  }
+
+  /// <summary>
+  /// Represents a collection of keys each mapped to one or more values.
+  /// </summary>
+  internal sealed class Lookup<TKey, TElement> : ILookup<TKey, TElement>
+  {
+    private readonly Dictionary<TKey, IGrouping<TKey, TElement>> _map;
+
+    internal Lookup(IEqualityComparer<TKey> comparer)
+    {
+      _map = new Dictionary<TKey, IGrouping<TKey, TElement>>(comparer);
+    }
+
+    internal void Add(IGrouping<TKey, TElement> item)
+    {
+      _map.Add(item.Key, item);
+    }
+
+    internal IEnumerable<TElement> Find(TKey key)
+    {
+      IGrouping<TKey, TElement> grouping;
+      return _map.TryGetValue(key, out grouping) ? grouping : null;
+    }
+
+    /// <summary>
+    /// Gets the number of key/value collection pairs in the <see cref="Lookup{TKey,TElement}" />.
+    /// </summary>
+
+    public int Count
+    {
+      get { return _map.Count; }
+    }
+
+    /// <summary>
+    /// Gets the collection of values indexed by the specified key.
+    /// </summary>
+
+    public IEnumerable<TElement> this[TKey key]
+    {
+      get
+      {
+        IGrouping<TKey, TElement> result;
+        return _map.TryGetValue(key, out result) ? result : Enumerable.Empty<TElement>();
+      }
+    }
+
+    /// <summary>
+    /// Determines whether a specified key is in the <see cref="Lookup{TKey,TElement}" />.
+    /// </summary>
+
+    public bool Contains(TKey key)
+    {
+      return _map.ContainsKey(key);
+    }
+
+    /// <summary>
+    /// Applies a transform function to each key and its associated 
+    /// values and returns the results.
+    /// </summary>
+
+    public IEnumerable<TResult> ApplyResultSelector<TResult>(
+      Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+    {
+      if (resultSelector == null)
+        throw new ArgumentNullException("resultSelector");
+
+      foreach (var pair in _map)
+        yield return resultSelector(pair.Key, pair.Value);
+    }
+
+    /// <summary>
+    /// Returns a generic enumerator that iterates through the <see cref="Lookup{TKey,TElement}" />.
+    /// </summary>
+
+    public IEnumerator<IGrouping<TKey, TElement>> GetEnumerator()
+    {
+      return _map.Values.GetEnumerator();
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+      return GetEnumerator();
+    }
+  }
+
+  internal sealed class OrderedEnumerable<T, K> : IOrderedEnumerable<T>
+  {
+    private readonly IEnumerable<T> _source;
+    private readonly List<Comparison<T>> _comparisons;
+
+    public OrderedEnumerable(IEnumerable<T> source,
+                             Func<T, K> keySelector, IComparer<K> comparer, bool descending) :
+                               this(source, null, keySelector, comparer, descending)
+    {
+    }
+
+    private OrderedEnumerable(IEnumerable<T> source, List<Comparison<T>> comparisons,
+                              Func<T, K> keySelector, IComparer<K> comparer, bool descending)
+    {
+      if (source == null) throw new ArgumentNullException("source");
+      if (keySelector == null) throw new ArgumentNullException("keySelector");
+
+      _source = source;
+
+      comparer = comparer ?? Comparer<K>.Default;
+
+      if (comparisons == null)
+        comparisons = new List<Comparison<T>>( /* capacity */ 4);
+
+      comparisons.Add((x, y)
+                      => (descending ? -1 : 1)*comparer.Compare(keySelector(x), keySelector(y)));
+
+      _comparisons = comparisons;
+    }
+
+    public IOrderedEnumerable<T> CreateOrderedEnumerable<KK>(
+      Func<T, KK> keySelector, IComparer<KK> comparer, bool descending)
+    {
+      return new OrderedEnumerable<T, KK>(_source, _comparisons, keySelector, comparer, descending);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+      //
+      // We sort using List<T>.Sort, but docs say that it performs an 
+      // unstable sort. LINQ, on the other hand, says OrderBy performs 
+      // a stable sort. So convert the source sequence into a sequence 
+      // of tuples where the second element tags the position of the 
+      // element from the source sequence (First). The position is 
+      // then used as a tie breaker when all keys compare equal,
+      // thus making the sort stable.
+      //
+
+      var list = _source.Select(new Func<T, int, Tuple<T, int>>(TagPosition)).ToList();
+
+      list.Sort((x, y) =>
+        {
+          //
+          // Compare keys from left to right.
+          //
+
+          var comparisons = _comparisons;
+          for (var i = 0; i < comparisons.Count; i++)
+          {
+            var result = comparisons[i](x.First, y.First);
+            if (result != 0)
+              return result;
+          }
+
+          //
+          // All keys compared equal so now break the tie by their
+          // position in the original sequence, making the sort stable.
+          //
+
+          return x.Second.CompareTo(y.Second);
+        });
+
+      return list.Select(new Func<Tuple<T, int>, T>(GetFirst)).GetEnumerator();
+
+    }
+
+    /// <remarks>
+    /// See <a href="http://code.google.com/p/linqbridge/issues/detail?id=11">issue #11</a>
+    /// for why this method is needed and cannot be expressed as a 
+    /// lambda at the call site.
+    /// </remarks>
+
+    private static Tuple<T, int> TagPosition(T e, int i)
+    {
+      return new Tuple<T, int>(e, i);
+    }
+
+    /// <remarks>
+    /// See <a href="http://code.google.com/p/linqbridge/issues/detail?id=11">issue #11</a>
+    /// for why this method is needed and cannot be expressed as a 
+    /// lambda at the call site.
+    /// </remarks>
+
+    private static T GetFirst(Tuple<T, int> pv)
+    {
+      return pv.First;
+    }
+
+    IEnumerator IEnumerable.GetEnumerator()
+    {
+      return GetEnumerator();
+    }
+  }
+
+  [Serializable]
+  internal struct Tuple<TFirst, TSecond> : IEquatable<Tuple<TFirst, TSecond>>
+  {
+    public TFirst First { get; private set; }
+    public TSecond Second { get; private set; }
+
+    public Tuple(TFirst first, TSecond second)
+      : this()
+    {
+      First = first;
+      Second = second;
+    }
+
+    public override bool Equals(object obj)
+    {
+      return obj != null
+             && obj is Tuple<TFirst, TSecond>
+             && base.Equals((Tuple<TFirst, TSecond>) obj);
+    }
+
+    public bool Equals(Tuple<TFirst, TSecond> other)
+    {
+      return EqualityComparer<TFirst>.Default.Equals(other.First, First)
+             && EqualityComparer<TSecond>.Default.Equals(other.Second, Second);
+    }
+
+    public override int GetHashCode()
+    {
+      var num = 0x7a2f0b42;
+      num = (-1521134295*num) + EqualityComparer<TFirst>.Default.GetHashCode(First);
+      return (-1521134295*num) + EqualityComparer<TSecond>.Default.GetHashCode(Second);
+    }
+
+    public override string ToString()
+    {
+      return string.Format(CultureInfo.InvariantCulture, @"{{ First = {0}, Second = {1} }}", First, Second);
+    }
+  }
+}
+
+namespace Newtonsoft.Json.Serialization
+{
+#pragma warning disable 1591
+  public delegate TResult Func<TResult>();
+
+  public delegate TResult Func<T, TResult>(T a);
+
+  public delegate TResult Func<T1, T2, TResult>(T1 arg1, T2 arg2);
+
+  public delegate TResult Func<T1, T2, T3, TResult>(T1 arg1, T2 arg2, T3 arg3);
+
+  public delegate TResult Func<T1, T2, T3, T4, TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+
+  public delegate void Action();
+
+  public delegate void Action<T1, T2>(T1 arg1, T2 arg2);
+
+  public delegate void Action<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3);
+
+  public delegate void Action<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3, T4 arg4);
+#pragma warning restore 1591
+}
+
+namespace System.Runtime.CompilerServices
+{
+  /// <remarks>
+  /// This attribute allows us to define extension methods without 
+  /// requiring .NET Framework 3.5. For more information, see the section,
+  /// <a href="http://msdn.microsoft.com/en-us/magazine/cc163317.aspx#S7">Extension Methods in .NET Framework 2.0 Apps</a>,
+  /// of <a href="http://msdn.microsoft.com/en-us/magazine/cc163317.aspx">Basic Instincts: Extension Methods</a>
+  /// column in <a href="http://msdn.microsoft.com/msdnmag/">MSDN Magazine</a>, 
+  /// issue <a href="http://msdn.microsoft.com/en-us/magazine/cc135410.aspx">Nov 2007</a>.
+  /// </remarks>
+
+  [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Assembly)]
+  internal sealed class ExtensionAttribute : Attribute { }
+}
+
+#endif
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/MathUtils.cs b/Newtonsoft.Json/Utilities/MathUtils.cs
new file mode 100644
index 0000000..cb2838b
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/MathUtils.cs
@@ -0,0 +1,117 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class MathUtils
+    {
+        public static int IntLength(ulong i)
+        {
+            if (i < 10000000000)
+            {
+                if (i < 10) return 1;
+                if (i < 100) return 2;
+                if (i < 1000) return 3;
+                if (i < 10000) return 4;
+                if (i < 100000) return 5;
+                if (i < 1000000) return 6;
+                if (i < 10000000) return 7;
+                if (i < 100000000) return 8;
+                if (i < 1000000000) return 9;
+
+                return 10;
+            }
+            else
+            {
+                if (i < 100000000000) return 11;
+                if (i < 1000000000000) return 12;
+                if (i < 10000000000000) return 13;
+                if (i < 100000000000000) return 14;
+                if (i < 1000000000000000) return 15;
+                if (i < 10000000000000000) return 16;
+                if (i < 100000000000000000) return 17;
+                if (i < 1000000000000000000) return 18;
+                if (i < 10000000000000000000) return 19;
+
+                return 20;
+            }
+        }
+
+        public static char IntToHex(int n)
+        {
+            if (n <= 9)
+                return (char)(n + 48);
+
+            return (char)((n - 10) + 97);
+        }
+
+        public static int? Min(int? val1, int? val2)
+        {
+            if (val1 == null)
+                return val2;
+            if (val2 == null)
+                return val1;
+
+            return Math.Min(val1.Value, val2.Value);
+        }
+
+        public static int? Max(int? val1, int? val2)
+        {
+            if (val1 == null)
+                return val2;
+            if (val2 == null)
+                return val1;
+
+            return Math.Max(val1.Value, val2.Value);
+        }
+
+        public static double? Max(double? val1, double? val2)
+        {
+            if (val1 == null)
+                return val2;
+            if (val2 == null)
+                return val1;
+
+            return Math.Max(val1.Value, val2.Value);
+        }
+
+        public static bool ApproxEquals(double d1, double d2)
+        {
+            const double epsilon = 2.2204460492503131E-16;
+
+            if (d1 == d2)
+                return true;
+
+            double tolerance = ((Math.Abs(d1) + Math.Abs(d2)) + 10.0) * epsilon;
+            double difference = d1 - d2;
+
+            return (-tolerance < difference && tolerance > difference);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/MethodCall.cs b/Newtonsoft.Json/Utilities/MethodCall.cs
new file mode 100644
index 0000000..0f759c3
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/MethodCall.cs
@@ -0,0 +1,29 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal delegate TResult MethodCall<T, TResult>(T target, params object[] args);
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs b/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
new file mode 100644
index 0000000..f7679da
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/MiscellaneousUtils.cs
@@ -0,0 +1,140 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Reflection;
+using System.Text;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal delegate T Creator<T>();
+
+    internal static class MiscellaneousUtils
+    {
+        public static bool ValueEquals(object objA, object objB)
+        {
+            if (objA == null && objB == null)
+                return true;
+            if (objA != null && objB == null)
+                return false;
+            if (objA == null && objB != null)
+                return false;
+
+            // comparing an Int32 and Int64 both of the same value returns false
+            // make types the same then compare
+            if (objA.GetType() != objB.GetType())
+            {
+                if (ConvertUtils.IsInteger(objA) && ConvertUtils.IsInteger(objB))
+                    return Convert.ToDecimal(objA, CultureInfo.CurrentCulture).Equals(Convert.ToDecimal(objB, CultureInfo.CurrentCulture));
+                else if ((objA is double || objA is float || objA is decimal) && (objB is double || objB is float || objB is decimal))
+                    return MathUtils.ApproxEquals(Convert.ToDouble(objA, CultureInfo.CurrentCulture), Convert.ToDouble(objB, CultureInfo.CurrentCulture));
+                else
+                    return false;
+            }
+
+            return objA.Equals(objB);
+        }
+
+        public static ArgumentOutOfRangeException CreateArgumentOutOfRangeException(string paramName, object actualValue, string message)
+        {
+            string newMessage = message + Environment.NewLine + @"Actual value was {0}.".FormatWith(CultureInfo.InvariantCulture, actualValue);
+
+            return new ArgumentOutOfRangeException(paramName, newMessage);
+        }
+
+        public static string ToString(object value)
+        {
+            if (value == null)
+                return "{null}";
+
+            return (value is string) ? @"""" + value.ToString() + @"""" : value.ToString();
+        }
+
+        public static int ByteArrayCompare(byte[] a1, byte[] a2)
+        {
+            int lengthCompare = a1.Length.CompareTo(a2.Length);
+            if (lengthCompare != 0)
+                return lengthCompare;
+
+            for (int i = 0; i < a1.Length; i++)
+            {
+                int valueCompare = a1[i].CompareTo(a2[i]);
+                if (valueCompare != 0)
+                    return valueCompare;
+            }
+
+            return 0;
+        }
+
+        public static string GetPrefix(string qualifiedName)
+        {
+            string prefix;
+            string localName;
+            GetQualifiedNameParts(qualifiedName, out prefix, out localName);
+
+            return prefix;
+        }
+
+        public static string GetLocalName(string qualifiedName)
+        {
+            string prefix;
+            string localName;
+            GetQualifiedNameParts(qualifiedName, out prefix, out localName);
+
+            return localName;
+        }
+
+        public static void GetQualifiedNameParts(string qualifiedName, out string prefix, out string localName)
+        {
+            int colonPosition = qualifiedName.IndexOf(':');
+
+            if ((colonPosition == -1 || colonPosition == 0) || (qualifiedName.Length - 1) == colonPosition)
+            {
+                prefix = null;
+                localName = qualifiedName;
+            }
+            else
+            {
+                prefix = qualifiedName.Substring(0, colonPosition);
+                localName = qualifiedName.Substring(colonPosition + 1);
+            }
+        }
+
+        internal static string FormatValueForPrint(object value)
+        {
+            if (value == null)
+                return "{null}";
+
+            if (value is string)
+                return @"""" + value + @"""";
+
+            return value.ToString();
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs b/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs
new file mode 100644
index 0000000..ae4bc60
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ReflectionDelegateFactory.cs
@@ -0,0 +1,72 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Globalization;
+using System.Reflection;
+using Newtonsoft.Json.Serialization;
+
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal abstract class ReflectionDelegateFactory
+    {
+        public Func<T, object> CreateGet<T>(MemberInfo memberInfo)
+        {
+            PropertyInfo propertyInfo = memberInfo as PropertyInfo;
+            if (propertyInfo != null)
+                return CreateGet<T>(propertyInfo);
+
+            FieldInfo fieldInfo = memberInfo as FieldInfo;
+            if (fieldInfo != null)
+                return CreateGet<T>(fieldInfo);
+
+            throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
+        }
+
+        public Action<T, object> CreateSet<T>(MemberInfo memberInfo)
+        {
+            PropertyInfo propertyInfo = memberInfo as PropertyInfo;
+            if (propertyInfo != null)
+                return CreateSet<T>(propertyInfo);
+
+            FieldInfo fieldInfo = memberInfo as FieldInfo;
+            if (fieldInfo != null)
+                return CreateSet<T>(fieldInfo);
+
+            throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
+        }
+
+        public abstract MethodCall<T, object> CreateMethodCall<T>(MethodBase method);
+        public abstract Func<T> CreateDefaultConstructor<T>(Type type);
+        public abstract Func<T, object> CreateGet<T>(PropertyInfo propertyInfo);
+        public abstract Func<T, object> CreateGet<T>(FieldInfo fieldInfo);
+        public abstract Action<T, object> CreateSet<T>(FieldInfo fieldInfo);
+        public abstract Action<T, object> CreateSet<T>(PropertyInfo propertyInfo);
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ReflectionUtils.cs b/Newtonsoft.Json/Utilities/ReflectionUtils.cs
new file mode 100644
index 0000000..239ba4c
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ReflectionUtils.cs
@@ -0,0 +1,968 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+using System.Numerics;
+#endif
+using System.Reflection;
+using System.Collections;
+using System.Globalization;
+using System.Runtime.Serialization;
+using System.Runtime.Serialization.Formatters;
+using System.Text;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+#if (NETFX_CORE || PORTABLE || PORTABLE40)
+    internal enum MemberTypes
+    {
+        Property,
+        Field,
+        Event,
+        Method,
+        Other
+    }
+#endif
+
+#if NETFX_CORE || PORTABLE
+    [Flags]
+    internal enum BindingFlags
+    {
+        Default = 0,
+        IgnoreCase = 1,
+        DeclaredOnly = 2,
+        Instance = 4,
+        Static = 8,
+        Public = 16,
+        NonPublic = 32,
+        FlattenHierarchy = 64,
+        InvokeMethod = 256,
+        CreateInstance = 512,
+        GetField = 1024,
+        SetField = 2048,
+        GetProperty = 4096,
+        SetProperty = 8192,
+        PutDispProperty = 16384,
+        ExactBinding = 65536,
+        PutRefDispProperty = 32768,
+        SuppressChangeType = 131072,
+        OptionalParamBinding = 262144,
+        IgnoreReturn = 16777216
+    }
+#endif
+
+    internal static class ReflectionUtils
+    {
+        public static readonly Type[] EmptyTypes;
+
+        static ReflectionUtils()
+        {
+#if !(NETFX_CORE || PORTABLE40 || PORTABLE)
+            EmptyTypes = Type.EmptyTypes;
+#else
+            EmptyTypes = new Type[0];
+#endif
+        }
+
+        public static bool IsVirtual(this PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            MethodInfo m = propertyInfo.GetGetMethod();
+            if (m != null && m.IsVirtual)
+                return true;
+
+            m = propertyInfo.GetSetMethod();
+            if (m != null && m.IsVirtual)
+                return true;
+
+            return false;
+        }
+
+        public static MethodInfo GetBaseDefinition(this PropertyInfo propertyInfo)
+        {
+            ValidationUtils.ArgumentNotNull(propertyInfo, "propertyInfo");
+
+            MethodInfo m = propertyInfo.GetGetMethod();
+            if (m != null)
+                return m.GetBaseDefinition();
+
+            m = propertyInfo.GetSetMethod();
+            if (m != null)
+                return m.GetBaseDefinition();
+
+            return null;
+        }
+
+        public static bool IsPublic(PropertyInfo property)
+        {
+            if (property.GetGetMethod() != null && property.GetGetMethod().IsPublic)
+                return true;
+            if (property.GetSetMethod() != null && property.GetSetMethod().IsPublic)
+                return true;
+
+            return false;
+        }
+
+        public static Type GetObjectType(object v)
+        {
+            return (v != null) ? v.GetType() : null;
+        }
+
+        public static string GetTypeName(Type t, FormatterAssemblyStyle assemblyFormat, SerializationBinder binder)
+        {
+            string fullyQualifiedTypeName;
+#if !(NET20 || NET35)
+            if (binder != null)
+            {
+                string assemblyName, typeName;
+                binder.BindToName(t, out assemblyName, out typeName);
+                fullyQualifiedTypeName = typeName + (assemblyName == null ? "" : ", " + assemblyName);
+            }
+            else
+            {
+                fullyQualifiedTypeName = t.AssemblyQualifiedName;
+            }
+#else
+            fullyQualifiedTypeName = t.AssemblyQualifiedName;
+#endif
+
+            switch (assemblyFormat)
+            {
+                case FormatterAssemblyStyle.Simple:
+                    return RemoveAssemblyDetails(fullyQualifiedTypeName);
+                case FormatterAssemblyStyle.Full:
+                    return fullyQualifiedTypeName;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        private static string RemoveAssemblyDetails(string fullyQualifiedTypeName)
+        {
+            StringBuilder builder = new StringBuilder();
+
+            // loop through the type name and filter out qualified assembly details from nested type names
+            bool writingAssemblyName = false;
+            bool skippingAssemblyDetails = false;
+            for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
+            {
+                char current = fullyQualifiedTypeName[i];
+                switch (current)
+                {
+                    case '[':
+                        writingAssemblyName = false;
+                        skippingAssemblyDetails = false;
+                        builder.Append(current);
+                        break;
+                    case ']':
+                        writingAssemblyName = false;
+                        skippingAssemblyDetails = false;
+                        builder.Append(current);
+                        break;
+                    case ',':
+                        if (!writingAssemblyName)
+                        {
+                            writingAssemblyName = true;
+                            builder.Append(current);
+                        }
+                        else
+                        {
+                            skippingAssemblyDetails = true;
+                        }
+                        break;
+                    default:
+                        if (!skippingAssemblyDetails)
+                            builder.Append(current);
+                        break;
+                }
+            }
+
+            return builder.ToString();
+        }
+
+        public static bool HasDefaultConstructor(Type t, bool nonPublic)
+        {
+            ValidationUtils.ArgumentNotNull(t, "t");
+
+            if (t.IsValueType())
+                return true;
+
+            return (GetDefaultConstructor(t, nonPublic) != null);
+        }
+
+        public static ConstructorInfo GetDefaultConstructor(Type t)
+        {
+            return GetDefaultConstructor(t, false);
+        }
+
+        public static ConstructorInfo GetDefaultConstructor(Type t, bool nonPublic)
+        {
+            BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public;
+            if (nonPublic)
+                bindingFlags = bindingFlags | BindingFlags.NonPublic;
+
+            return t.GetConstructors(bindingFlags).SingleOrDefault(c => !c.GetParameters().Any());
+        }
+
+        public static bool IsNullable(Type t)
+        {
+            ValidationUtils.ArgumentNotNull(t, "t");
+
+            if (t.IsValueType())
+                return IsNullableType(t);
+
+            return true;
+        }
+
+        public static bool IsNullableType(Type t)
+        {
+            ValidationUtils.ArgumentNotNull(t, "t");
+
+            return (t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(Nullable<>));
+        }
+
+        public static Type EnsureNotNullableType(Type t)
+        {
+            return (IsNullableType(t))
+                ? Nullable.GetUnderlyingType(t)
+                : t;
+        }
+
+        public static bool IsGenericDefinition(Type type, Type genericInterfaceDefinition)
+        {
+            if (!type.IsGenericType())
+                return false;
+
+            Type t = type.GetGenericTypeDefinition();
+            return (t == genericInterfaceDefinition);
+        }
+
+        public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition)
+        {
+            Type implementingType;
+            return ImplementsGenericDefinition(type, genericInterfaceDefinition, out implementingType);
+        }
+
+        public static bool ImplementsGenericDefinition(Type type, Type genericInterfaceDefinition, out Type implementingType)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+            ValidationUtils.ArgumentNotNull(genericInterfaceDefinition, "genericInterfaceDefinition");
+
+            if (!genericInterfaceDefinition.IsInterface() || !genericInterfaceDefinition.IsGenericTypeDefinition())
+                throw new ArgumentNullException("'{0}' is not a generic interface definition.".FormatWith(CultureInfo.InvariantCulture, genericInterfaceDefinition));
+
+            if (type.IsInterface())
+            {
+                if (type.IsGenericType())
+                {
+                    Type interfaceDefinition = type.GetGenericTypeDefinition();
+
+                    if (genericInterfaceDefinition == interfaceDefinition)
+                    {
+                        implementingType = type;
+                        return true;
+                    }
+                }
+            }
+
+            foreach (Type i in type.GetInterfaces())
+            {
+                if (i.IsGenericType())
+                {
+                    Type interfaceDefinition = i.GetGenericTypeDefinition();
+
+                    if (genericInterfaceDefinition == interfaceDefinition)
+                    {
+                        implementingType = i;
+                        return true;
+                    }
+                }
+            }
+
+            implementingType = null;
+            return false;
+        }
+
+        public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition)
+        {
+            Type implementingType;
+            return InheritsGenericDefinition(type, genericClassDefinition, out implementingType);
+        }
+
+        public static bool InheritsGenericDefinition(Type type, Type genericClassDefinition, out Type implementingType)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+            ValidationUtils.ArgumentNotNull(genericClassDefinition, "genericClassDefinition");
+
+            if (!genericClassDefinition.IsClass() || !genericClassDefinition.IsGenericTypeDefinition())
+                throw new ArgumentNullException("'{0}' is not a generic class definition.".FormatWith(CultureInfo.InvariantCulture, genericClassDefinition));
+
+            return InheritsGenericDefinitionInternal(type, genericClassDefinition, out implementingType);
+        }
+
+        private static bool InheritsGenericDefinitionInternal(Type currentType, Type genericClassDefinition, out Type implementingType)
+        {
+            if (currentType.IsGenericType())
+            {
+                Type currentGenericClassDefinition = currentType.GetGenericTypeDefinition();
+
+                if (genericClassDefinition == currentGenericClassDefinition)
+                {
+                    implementingType = currentType;
+                    return true;
+                }
+            }
+
+            if (currentType.BaseType() == null)
+            {
+                implementingType = null;
+                return false;
+            }
+
+            return InheritsGenericDefinitionInternal(currentType.BaseType(), genericClassDefinition, out implementingType);
+        }
+
+        /// <summary>
+        /// Gets the type of the typed collection's items.
+        /// </summary>
+        /// <param name="type">The type.</param>
+        /// <returns>The type of the typed collection's items.</returns>
+        public static Type GetCollectionItemType(Type type)
+        {
+            ValidationUtils.ArgumentNotNull(type, "type");
+            Type genericListType;
+
+            if (type.IsArray)
+            {
+                return type.GetElementType();
+            }
+            else if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out genericListType))
+            {
+                if (genericListType.IsGenericTypeDefinition())
+                    throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
+
+                return genericListType.GetGenericArguments()[0];
+            }
+            else if (typeof(IEnumerable).IsAssignableFrom(type))
+            {
+                return null;
+            }
+            else
+            {
+                throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
+            }
+        }
+
+        public static void GetDictionaryKeyValueTypes(Type dictionaryType, out Type keyType, out Type valueType)
+        {
+            ValidationUtils.ArgumentNotNull(dictionaryType, "type");
+
+            Type genericDictionaryType;
+            if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out genericDictionaryType))
+            {
+                if (genericDictionaryType.IsGenericTypeDefinition())
+                    throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
+
+                Type[] dictionaryGenericArguments = genericDictionaryType.GetGenericArguments();
+
+                keyType = dictionaryGenericArguments[0];
+                valueType = dictionaryGenericArguments[1];
+                return;
+            }
+            else if (typeof(IDictionary).IsAssignableFrom(dictionaryType))
+            {
+                keyType = null;
+                valueType = null;
+                return;
+            }
+            else
+            {
+                throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
+            }
+        }
+
+        /// <summary>
+        /// Gets the member's underlying type.
+        /// </summary>
+        /// <param name="member">The member.</param>
+        /// <returns>The underlying type of the member.</returns>
+        public static Type GetMemberUnderlyingType(MemberInfo member)
+        {
+            ValidationUtils.ArgumentNotNull(member, "member");
+
+            switch (member.MemberType())
+            {
+                case MemberTypes.Field:
+                    return ((FieldInfo)member).FieldType;
+                case MemberTypes.Property:
+                    return ((PropertyInfo)member).PropertyType;
+                case MemberTypes.Event:
+                    return ((EventInfo)member).EventHandlerType;
+                default:
+                    throw new ArgumentException("MemberInfo must be of type FieldInfo, PropertyInfo or EventInfo", "member");
+            }
+        }
+
+        /// <summary>
+        /// Determines whether the member is an indexed property.
+        /// </summary>
+        /// <param name="member">The member.</param>
+        /// <returns>
+        /// 	<c>true</c> if the member is an indexed property; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsIndexedProperty(MemberInfo member)
+        {
+            ValidationUtils.ArgumentNotNull(member, "member");
+
+            PropertyInfo propertyInfo = member as PropertyInfo;
+
+            if (propertyInfo != null)
+                return IsIndexedProperty(propertyInfo);
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// Determines whether the property is an indexed property.
+        /// </summary>
+        /// <param name="property">The property.</param>
+        /// <returns>
+        /// 	<c>true</c> if the property is an indexed property; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsIndexedProperty(PropertyInfo property)
+        {
+            ValidationUtils.ArgumentNotNull(property, "property");
+
+            return (property.GetIndexParameters().Length > 0);
+        }
+
+        /// <summary>
+        /// Gets the member's value on the object.
+        /// </summary>
+        /// <param name="member">The member.</param>
+        /// <param name="target">The target object.</param>
+        /// <returns>The member's value on the object.</returns>
+        public static object GetMemberValue(MemberInfo member, object target)
+        {
+            ValidationUtils.ArgumentNotNull(member, "member");
+            ValidationUtils.ArgumentNotNull(target, "target");
+
+            switch (member.MemberType())
+            {
+                case MemberTypes.Field:
+                    return ((FieldInfo)member).GetValue(target);
+                case MemberTypes.Property:
+                    try
+                    {
+                        return ((PropertyInfo)member).GetValue(target, null);
+                    }
+                    catch (TargetParameterCountException e)
+                    {
+                        throw new ArgumentException("MemberInfo '{0}' has index parameters".FormatWith(CultureInfo.InvariantCulture, member.Name), e);
+                    }
+                default:
+                    throw new ArgumentException("MemberInfo '{0}' is not of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, CultureInfo.InvariantCulture, member.Name), "member");
+            }
+        }
+
+        /// <summary>
+        /// Sets the member's value on the target object.
+        /// </summary>
+        /// <param name="member">The member.</param>
+        /// <param name="target">The target.</param>
+        /// <param name="value">The value.</param>
+        public static void SetMemberValue(MemberInfo member, object target, object value)
+        {
+            ValidationUtils.ArgumentNotNull(member, "member");
+            ValidationUtils.ArgumentNotNull(target, "target");
+
+            switch (member.MemberType())
+            {
+                case MemberTypes.Field:
+                    ((FieldInfo)member).SetValue(target, value);
+                    break;
+                case MemberTypes.Property:
+                    ((PropertyInfo)member).SetValue(target, value, null);
+                    break;
+                default:
+                    throw new ArgumentException("MemberInfo '{0}' must be of type FieldInfo or PropertyInfo".FormatWith(CultureInfo.InvariantCulture, member.Name), "member");
+            }
+        }
+
+        /// <summary>
+        /// Determines whether the specified MemberInfo can be read.
+        /// </summary>
+        /// <param name="member">The MemberInfo to determine whether can be read.</param>
+        /// /// <param name="nonPublic">if set to <c>true</c> then allow the member to be gotten non-publicly.</param>
+        /// <returns>
+        /// 	<c>true</c> if the specified MemberInfo can be read; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool CanReadMemberValue(MemberInfo member, bool nonPublic)
+        {
+            switch (member.MemberType())
+            {
+                case MemberTypes.Field:
+                    FieldInfo fieldInfo = (FieldInfo)member;
+
+                    if (nonPublic)
+                        return true;
+                    else if (fieldInfo.IsPublic)
+                        return true;
+                    return false;
+                case MemberTypes.Property:
+                    PropertyInfo propertyInfo = (PropertyInfo)member;
+
+                    if (!propertyInfo.CanRead)
+                        return false;
+                    if (nonPublic)
+                        return true;
+                    return (propertyInfo.GetGetMethod(nonPublic) != null);
+                default:
+                    return false;
+            }
+        }
+
+        /// <summary>
+        /// Determines whether the specified MemberInfo can be set.
+        /// </summary>
+        /// <param name="member">The MemberInfo to determine whether can be set.</param>
+        /// <param name="nonPublic">if set to <c>true</c> then allow the member to be set non-publicly.</param>
+        /// <param name="canSetReadOnly">if set to <c>true</c> then allow the member to be set if read-only.</param>
+        /// <returns>
+        /// 	<c>true</c> if the specified MemberInfo can be set; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool CanSetMemberValue(MemberInfo member, bool nonPublic, bool canSetReadOnly)
+        {
+            switch (member.MemberType())
+            {
+                case MemberTypes.Field:
+                    FieldInfo fieldInfo = (FieldInfo)member;
+
+                    if (fieldInfo.IsInitOnly && !canSetReadOnly)
+                        return false;
+                    if (nonPublic)
+                        return true;
+                    else if (fieldInfo.IsPublic)
+                        return true;
+                    return false;
+                case MemberTypes.Property:
+                    PropertyInfo propertyInfo = (PropertyInfo)member;
+
+                    if (!propertyInfo.CanWrite)
+                        return false;
+                    if (nonPublic)
+                        return true;
+                    return (propertyInfo.GetSetMethod(nonPublic) != null);
+                default:
+                    return false;
+            }
+        }
+
+        public static List<MemberInfo> GetFieldsAndProperties(Type type, BindingFlags bindingAttr)
+        {
+            List<MemberInfo> targetMembers = new List<MemberInfo>();
+
+            targetMembers.AddRange(GetFields(type, bindingAttr));
+            targetMembers.AddRange(GetProperties(type, bindingAttr));
+
+            // for some reason .NET returns multiple members when overriding a generic member on a base class
+            // http://social.msdn.microsoft.com/Forums/en-US/b5abbfee-e292-4a64-8907-4e3f0fb90cd9/reflection-overriden-abstract-generic-properties?forum=netfxbcl
+            // filter members to only return the override on the topmost class
+            // update: I think this is fixed in .NET 3.5 SP1 - leave this in for now...
+            List<MemberInfo> distinctMembers = new List<MemberInfo>(targetMembers.Count);
+
+            foreach (var groupedMember in targetMembers.GroupBy(m => m.Name))
+            {
+                int count = groupedMember.Count();
+                IList<MemberInfo> members = groupedMember.ToList();
+
+                if (count == 1)
+                {
+                    distinctMembers.Add(members.First());
+                }
+                else
+                {
+                    IList<MemberInfo> resolvedMembers = new List<MemberInfo>();
+                    foreach (MemberInfo memberInfo in members)
+                    {
+                        // this is a bit hacky
+                        // if the hiding property is hiding a base property and it is virtual
+                        // then this ensures the derived property gets used
+                        if (resolvedMembers.Count == 0)
+                            resolvedMembers.Add(memberInfo);
+                        else if (!IsOverridenGenericMember(memberInfo, bindingAttr) || memberInfo.Name == "Item")
+                            resolvedMembers.Add(memberInfo);
+                    }
+
+                    distinctMembers.AddRange(resolvedMembers);
+                }
+            }
+
+            return distinctMembers;
+        }
+
+        private static bool IsOverridenGenericMember(MemberInfo memberInfo, BindingFlags bindingAttr)
+        {
+            if (memberInfo.MemberType() != MemberTypes.Property)
+                return false;
+
+            PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
+            if (!IsVirtual(propertyInfo))
+                return false;
+
+            Type declaringType = propertyInfo.DeclaringType;
+            if (!declaringType.IsGenericType())
+                return false;
+            Type genericTypeDefinition = declaringType.GetGenericTypeDefinition();
+            if (genericTypeDefinition == null)
+                return false;
+            MemberInfo[] members = genericTypeDefinition.GetMember(propertyInfo.Name, bindingAttr);
+            if (members.Length == 0)
+                return false;
+            Type memberUnderlyingType = GetMemberUnderlyingType(members[0]);
+            if (!memberUnderlyingType.IsGenericParameter)
+                return false;
+
+            return true;
+        }
+
+        public static T GetAttribute<T>(object attributeProvider) where T : Attribute
+        {
+            return GetAttribute<T>(attributeProvider, true);
+        }
+
+        public static T GetAttribute<T>(object attributeProvider, bool inherit) where T : Attribute
+        {
+            T[] attributes = GetAttributes<T>(attributeProvider, inherit);
+
+            return (attributes != null) ? attributes.SingleOrDefault() : null;
+        }
+
+#if !(NETFX_CORE || PORTABLE)
+        public static T[] GetAttributes<T>(object attributeProvider, bool inherit) where T : Attribute
+        {
+            ValidationUtils.ArgumentNotNull(attributeProvider, "attributeProvider");
+
+            object provider = attributeProvider;
+
+            // http://hyperthink.net/blog/getcustomattributes-gotcha/
+            // ICustomAttributeProvider doesn't do inheritance
+
+            if (provider is Type)
+                return (T[])((Type)provider).GetCustomAttributes(typeof(T), inherit);
+
+            if (provider is Assembly)
+                return (T[])Attribute.GetCustomAttributes((Assembly)provider, typeof(T));
+
+            if (provider is MemberInfo)
+                return (T[])Attribute.GetCustomAttributes((MemberInfo)provider, typeof(T), inherit);
+
+#if !PORTABLE40
+            if (provider is Module)
+                return (T[])Attribute.GetCustomAttributes((Module)provider, typeof(T), inherit);
+#endif
+
+            if (provider is ParameterInfo)
+                return (T[])Attribute.GetCustomAttributes((ParameterInfo)provider, typeof(T), inherit);
+
+#if !PORTABLE40
+            return (T[])((ICustomAttributeProvider)attributeProvider).GetCustomAttributes(typeof(T), inherit);
+#else
+            throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
+#endif
+        }
+#else
+        public static T[] GetAttributes<T>(object provider, bool inherit) where T : Attribute
+        {
+            if (provider is Type)
+                return ((Type) provider).GetTypeInfo().GetCustomAttributes<T>(inherit).ToArray();
+
+            if (provider is Assembly)
+                return ((Assembly) provider).GetCustomAttributes<T>().ToArray();
+
+            if (provider is MemberInfo)
+                return ((MemberInfo) provider).GetCustomAttributes<T>(inherit).ToArray();
+
+            if (provider is Module)
+                return ((Module) provider).GetCustomAttributes<T>().ToArray();
+
+            if (provider is ParameterInfo)
+                return ((ParameterInfo) provider).GetCustomAttributes<T>(inherit).ToArray();
+
+            throw new Exception("Cannot get attributes from '{0}'.".FormatWith(CultureInfo.InvariantCulture, provider));
+        }
+#endif
+
+        public static void SplitFullyQualifiedTypeName(string fullyQualifiedTypeName, out string typeName, out string assemblyName)
+        {
+            int? assemblyDelimiterIndex = GetAssemblyDelimiterIndex(fullyQualifiedTypeName);
+
+            if (assemblyDelimiterIndex != null)
+            {
+                typeName = fullyQualifiedTypeName.Substring(0, assemblyDelimiterIndex.Value).Trim();
+                assemblyName = fullyQualifiedTypeName.Substring(assemblyDelimiterIndex.Value + 1, fullyQualifiedTypeName.Length - assemblyDelimiterIndex.Value - 1).Trim();
+            }
+            else
+            {
+                typeName = fullyQualifiedTypeName;
+                assemblyName = null;
+            }
+        }
+
+        private static int? GetAssemblyDelimiterIndex(string fullyQualifiedTypeName)
+        {
+            // we need to get the first comma following all surrounded in brackets because of generic types
+            // e.g. System.Collections.Generic.Dictionary`2[[System.String, mscorlib,Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+            int scope = 0;
+            for (int i = 0; i < fullyQualifiedTypeName.Length; i++)
+            {
+                char current = fullyQualifiedTypeName[i];
+                switch (current)
+                {
+                    case '[':
+                        scope++;
+                        break;
+                    case ']':
+                        scope--;
+                        break;
+                    case ',':
+                        if (scope == 0)
+                            return i;
+                        break;
+                }
+            }
+
+            return null;
+        }
+
+        public static MemberInfo GetMemberInfoFromType(Type targetType, MemberInfo memberInfo)
+        {
+            const BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+
+            switch (memberInfo.MemberType())
+            {
+                case MemberTypes.Property:
+                    PropertyInfo propertyInfo = (PropertyInfo)memberInfo;
+
+                    Type[] types = propertyInfo.GetIndexParameters().Select(p => p.ParameterType).ToArray();
+
+                    return targetType.GetProperty(propertyInfo.Name, bindingAttr, null, propertyInfo.PropertyType, types, null);
+                default:
+                    return targetType.GetMember(memberInfo.Name, memberInfo.MemberType(), bindingAttr).SingleOrDefault();
+            }
+        }
+
+        public static IEnumerable<FieldInfo> GetFields(Type targetType, BindingFlags bindingAttr)
+        {
+            ValidationUtils.ArgumentNotNull(targetType, "targetType");
+
+            List<MemberInfo> fieldInfos = new List<MemberInfo>(targetType.GetFields(bindingAttr));
+#if !(NETFX_CORE || PORTABLE)
+            // Type.GetFields doesn't return inherited private fields
+            // manually find private fields from base class
+            GetChildPrivateFields(fieldInfos, targetType, bindingAttr);
+#endif
+
+            return fieldInfos.Cast<FieldInfo>();
+        }
+
+        private static void GetChildPrivateFields(IList<MemberInfo> initialFields, Type targetType, BindingFlags bindingAttr)
+        {
+            // fix weirdness with private FieldInfos only being returned for the current Type
+            // find base type fields and add them to result
+            if ((bindingAttr & BindingFlags.NonPublic) != 0)
+            {
+                // modify flags to not search for public fields
+                BindingFlags nonPublicBindingAttr = bindingAttr.RemoveFlag(BindingFlags.Public);
+
+                while ((targetType = targetType.BaseType()) != null)
+                {
+                    // filter out protected fields
+                    IEnumerable<MemberInfo> childPrivateFields =
+                        targetType.GetFields(nonPublicBindingAttr).Where(f => f.IsPrivate).Cast<MemberInfo>();
+
+                    initialFields.AddRange(childPrivateFields);
+                }
+            }
+        }
+
+        public static IEnumerable<PropertyInfo> GetProperties(Type targetType, BindingFlags bindingAttr)
+        {
+            ValidationUtils.ArgumentNotNull(targetType, "targetType");
+
+            List<PropertyInfo> propertyInfos = new List<PropertyInfo>(targetType.GetProperties(bindingAttr));
+            GetChildPrivateProperties(propertyInfos, targetType, bindingAttr);
+
+            // a base class private getter/setter will be inaccessable unless the property was gotten from the base class
+            for (int i = 0; i < propertyInfos.Count; i++)
+            {
+                PropertyInfo member = propertyInfos[i];
+                if (member.DeclaringType != targetType)
+                {
+                    PropertyInfo declaredMember = (PropertyInfo)GetMemberInfoFromType(member.DeclaringType, member);
+                    propertyInfos[i] = declaredMember;
+                }
+            }
+
+            return propertyInfos;
+        }
+
+        public static BindingFlags RemoveFlag(this BindingFlags bindingAttr, BindingFlags flag)
+        {
+            return ((bindingAttr & flag) == flag)
+                ? bindingAttr ^ flag
+                : bindingAttr;
+        }
+
+        private static void GetChildPrivateProperties(IList<PropertyInfo> initialProperties, Type targetType, BindingFlags bindingAttr)
+        {
+            // fix weirdness with private PropertyInfos only being returned for the current Type
+            // find base type properties and add them to result
+
+            // also find base properties that have been hidden by subtype properties with the same name
+
+            while ((targetType = targetType.BaseType()) != null)
+            {
+                foreach (PropertyInfo propertyInfo in targetType.GetProperties(bindingAttr))
+                {
+                    PropertyInfo subTypeProperty = propertyInfo;
+
+                    if (!IsPublic(subTypeProperty))
+                    {
+                        // have to test on name rather than reference because instances are different
+                        // depending on the type that GetProperties was called on
+                        int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name);
+                        if (index == -1)
+                        {
+                            initialProperties.Add(subTypeProperty);
+                        }
+                        else
+                        {
+                            PropertyInfo childProperty = initialProperties[index];
+                            // don't replace public child with private base
+                            if (!IsPublic(childProperty))
+                            {
+                                // replace nonpublic properties for a child, but gotten from
+                                // the parent with the one from the child
+                                // the property gotten from the child will have access to private getter/setter
+                                initialProperties[index] = subTypeProperty;
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if (!subTypeProperty.IsVirtual())
+                        {
+                            int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
+                                                                       && p.DeclaringType == subTypeProperty.DeclaringType);
+
+                            if (index == -1)
+                                initialProperties.Add(subTypeProperty);
+                        }
+                        else
+                        {
+                            int index = initialProperties.IndexOf(p => p.Name == subTypeProperty.Name
+                                                                       && p.IsVirtual()
+                                                                       && p.GetBaseDefinition() != null
+                                                                       && p.GetBaseDefinition().DeclaringType.IsAssignableFrom(subTypeProperty.DeclaringType));
+
+                            if (index == -1)
+                                initialProperties.Add(subTypeProperty);
+                        }
+                    }
+                }
+            }
+        }
+
+        public static bool IsMethodOverridden(Type currentType, Type methodDeclaringType, string method)
+        {
+            bool isMethodOverriden = currentType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
+                .Any(info =>
+                    info.Name == method &&
+                    // check that the method overrides the original on DynamicObjectProxy
+                    info.DeclaringType != methodDeclaringType
+                    && info.GetBaseDefinition().DeclaringType == methodDeclaringType
+                );
+
+            return isMethodOverriden;
+        }
+
+        public static object GetDefaultValue(Type type)
+        {
+            if (!type.IsValueType())
+                return null;
+
+            switch (ConvertUtils.GetTypeCode(type))
+            {
+                case PrimitiveTypeCode.Boolean:
+                    return false;
+                case PrimitiveTypeCode.Char:
+                case PrimitiveTypeCode.SByte:
+                case PrimitiveTypeCode.Byte:
+                case PrimitiveTypeCode.Int16:
+                case PrimitiveTypeCode.UInt16:
+                case PrimitiveTypeCode.Int32:
+                case PrimitiveTypeCode.UInt32:
+                    return 0;
+                case PrimitiveTypeCode.Int64:
+                case PrimitiveTypeCode.UInt64:
+                    return 0L;
+                case PrimitiveTypeCode.Single:
+                    return 0f;
+                case PrimitiveTypeCode.Double:
+                    return 0.0;
+                case PrimitiveTypeCode.Decimal:
+                    return 0m;
+                case PrimitiveTypeCode.DateTime:
+                    return new DateTime();
+#if !(PORTABLE || PORTABLE40 || NET35 || NET20)
+                case PrimitiveTypeCode.BigInteger:
+                    return new BigInteger();
+#endif
+                case PrimitiveTypeCode.Guid:
+                    return new Guid();
+#if !NET20
+                case PrimitiveTypeCode.DateTimeOffset:
+                    return new DateTimeOffset();
+#endif
+            }
+
+            if (IsNullable(type))
+                return null;
+
+            // possibly use IL initobj for perf here?
+            return Activator.CreateInstance(type);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/StringBuffer.cs b/Newtonsoft.Json/Utilities/StringBuffer.cs
new file mode 100644
index 0000000..8e46de8
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/StringBuffer.cs
@@ -0,0 +1,107 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json.Utilities
+{
+    /// <summary>
+    /// Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer.
+    /// </summary>
+    internal class StringBuffer
+    {
+        private char[] _buffer;
+        private int _position;
+
+        private static readonly char[] EmptyBuffer = new char[0];
+
+        public int Position
+        {
+            get { return _position; }
+            set { _position = value; }
+        }
+
+        public StringBuffer()
+        {
+            _buffer = EmptyBuffer;
+        }
+
+        public StringBuffer(int initalSize)
+        {
+            _buffer = new char[initalSize];
+        }
+
+        public void Append(char value)
+        {
+            // test if the buffer array is large enough to take the value
+            if (_position == _buffer.Length)
+                EnsureSize(1);
+
+            // set value and increment poisition
+            _buffer[_position++] = value;
+        }
+
+        public void Append(char[] buffer, int startIndex, int count)
+        {
+            if (_position + count >= _buffer.Length)
+                EnsureSize(count);
+
+            Array.Copy(buffer, startIndex, _buffer, _position, count);
+
+            _position += count;
+        }
+
+        public void Clear()
+        {
+            _buffer = EmptyBuffer;
+            _position = 0;
+        }
+
+        private void EnsureSize(int appendLength)
+        {
+            char[] newBuffer = new char[(_position + appendLength) * 2];
+
+            Array.Copy(_buffer, newBuffer, _position);
+
+            _buffer = newBuffer;
+        }
+
+        public override string ToString()
+        {
+            return ToString(0, _position);
+        }
+
+        public string ToString(int start, int length)
+        {
+            // TODO: validation
+            return new string(_buffer, start, length);
+        }
+
+        public char[] GetInternalBuffer()
+        {
+            return _buffer;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/StringReference.cs b/Newtonsoft.Json/Utilities/StringReference.cs
new file mode 100644
index 0000000..522c7c7
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/StringReference.cs
@@ -0,0 +1,61 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal struct StringReference
+    {
+        private readonly char[] _chars;
+        private readonly int _startIndex;
+        private readonly int _length;
+
+        public char[] Chars
+        {
+            get { return _chars; }
+        }
+
+        public int StartIndex
+        {
+            get { return _startIndex; }
+        }
+
+        public int Length
+        {
+            get { return _length; }
+        }
+
+        public StringReference(char[] chars, int startIndex, int length)
+        {
+            _chars = chars;
+            _startIndex = startIndex;
+            _length = length;
+        }
+
+        public override string ToString()
+        {
+            return new string(_chars, _startIndex, _length);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/StringUtils.cs b/Newtonsoft.Json/Utilities/StringUtils.cs
new file mode 100644
index 0000000..6999dd3
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/StringUtils.cs
@@ -0,0 +1,201 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Globalization;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class StringUtils
+    {
+        public const string CarriageReturnLineFeed = "\r\n";
+        public const string Empty = "";
+        public const char CarriageReturn = '\r';
+        public const char LineFeed = '\n';
+        public const char Tab = '\t';
+
+        public static string FormatWith(this string format, IFormatProvider provider, object arg0)
+        {
+            return format.FormatWith(provider, new[] { arg0 });
+        }
+
+        public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1)
+        {
+            return format.FormatWith(provider, new[] { arg0, arg1 });
+        }
+
+        public static string FormatWith(this string format, IFormatProvider provider, object arg0, object arg1, object arg2)
+        {
+            return format.FormatWith(provider, new[] { arg0, arg1, arg2 });
+        }
+
+        public static string FormatWith(this string format, IFormatProvider provider, params object[] args)
+        {
+            ValidationUtils.ArgumentNotNull(format, "format");
+
+            return string.Format(provider, format, args);
+        }
+
+        /// <summary>
+        /// Determines whether the string is all white space. Empty string will return false.
+        /// </summary>
+        /// <param name="s">The string to test whether it is all white space.</param>
+        /// <returns>
+        /// 	<c>true</c> if the string is all white space; otherwise, <c>false</c>.
+        /// </returns>
+        public static bool IsWhiteSpace(string s)
+        {
+            if (s == null)
+                throw new ArgumentNullException("s");
+
+            if (s.Length == 0)
+                return false;
+
+            for (int i = 0; i < s.Length; i++)
+            {
+                if (!char.IsWhiteSpace(s[i]))
+                    return false;
+            }
+
+            return true;
+        }
+
+        /// <summary>
+        /// Nulls an empty string.
+        /// </summary>
+        /// <param name="s">The string.</param>
+        /// <returns>Null if the string was null, otherwise the string unchanged.</returns>
+        public static string NullEmptyString(string s)
+        {
+            return (string.IsNullOrEmpty(s)) ? null : s;
+        }
+
+        public static StringWriter CreateStringWriter(int capacity)
+        {
+            StringBuilder sb = new StringBuilder(capacity);
+            StringWriter sw = new StringWriter(sb, CultureInfo.InvariantCulture);
+
+            return sw;
+        }
+
+        public static int? GetLength(string value)
+        {
+            if (value == null)
+                return null;
+            else
+                return value.Length;
+        }
+
+        public static void ToCharAsUnicode(char c, char[] buffer)
+        {
+            buffer[0] = '\\';
+            buffer[1] = 'u';
+            buffer[2] = MathUtils.IntToHex((c >> 12) & '\x000f');
+            buffer[3] = MathUtils.IntToHex((c >> 8) & '\x000f');
+            buffer[4] = MathUtils.IntToHex((c >> 4) & '\x000f');
+            buffer[5] = MathUtils.IntToHex(c & '\x000f');
+        }
+
+        public static TSource ForgivingCaseSensitiveFind<TSource>(this IEnumerable<TSource> source, Func<TSource, string> valueSelector, string testValue)
+        {
+            if (source == null)
+                throw new ArgumentNullException("source");
+            if (valueSelector == null)
+                throw new ArgumentNullException("valueSelector");
+
+            var caseInsensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.OrdinalIgnoreCase));
+            if (caseInsensitiveResults.Count() <= 1)
+            {
+                return caseInsensitiveResults.SingleOrDefault();
+            }
+            else
+            {
+                // multiple results returned. now filter using case sensitivity
+                var caseSensitiveResults = source.Where(s => string.Equals(valueSelector(s), testValue, StringComparison.Ordinal));
+                return caseSensitiveResults.SingleOrDefault();
+            }
+        }
+
+        public static string ToCamelCase(string s)
+        {
+            if (string.IsNullOrEmpty(s))
+                return s;
+
+            if (!char.IsUpper(s[0]))
+                return s;
+
+            StringBuilder sb = new StringBuilder();
+            for (int i = 0; i < s.Length; i++)
+            {
+                bool hasNext = (i + 1 < s.Length);
+                if ((i == 0 || !hasNext) || char.IsUpper(s[i + 1]))
+                {
+                    char lowerCase;
+#if !(NETFX_CORE || PORTABLE)
+                    lowerCase = char.ToLower(s[i], CultureInfo.InvariantCulture);
+#else
+                    lowerCase = char.ToLower(s[i]);
+#endif
+
+                    sb.Append(lowerCase);
+                }
+                else
+                {
+                    sb.Append(s.Substring(i));
+                    break;
+                }
+            }
+
+            return sb.ToString();
+        }
+
+        public static bool IsHighSurrogate(char c)
+        {
+#if !(PORTABLE40 || PORTABLE)
+            return char.IsHighSurrogate(c);
+#else
+            return (c >= 55296 && c <= 56319);
+#endif
+        }
+
+        public static bool IsLowSurrogate(char c)
+        {
+#if !(PORTABLE40 || PORTABLE)
+            return char.IsLowSurrogate(c);
+#else
+            return (c >= 56320 && c <= 57343);
+#endif
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ThreadSafeStore.cs b/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
new file mode 100644
index 0000000..50e3142
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ThreadSafeStore.cs
@@ -0,0 +1,91 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#endif
+using System.Threading;
+using Newtonsoft.Json.Serialization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal class ThreadSafeStore<TKey, TValue>
+    {
+        private readonly object _lock = new object();
+        private Dictionary<TKey, TValue> _store;
+        private readonly Func<TKey, TValue> _creator;
+
+        public ThreadSafeStore(Func<TKey, TValue> creator)
+        {
+            if (creator == null)
+                throw new ArgumentNullException("creator");
+
+            _creator = creator;
+            _store = new Dictionary<TKey, TValue>();
+        }
+
+        public TValue Get(TKey key)
+        {
+            TValue value;
+            if (!_store.TryGetValue(key, out value))
+                return AddValue(key);
+
+            return value;
+        }
+
+        private TValue AddValue(TKey key)
+        {
+            TValue value = _creator(key);
+
+            lock (_lock)
+            {
+                if (_store == null)
+                {
+                    _store = new Dictionary<TKey, TValue>();
+                    _store[key] = value;
+                }
+                else
+                {
+                    // double check locking
+                    TValue checkValue;
+                    if (_store.TryGetValue(key, out checkValue))
+                        return checkValue;
+
+                    Dictionary<TKey, TValue> newStore = new Dictionary<TKey, TValue>(_store);
+                    newStore[key] = value;
+
+#if !(NETFX_CORE || PORTABLE)
+                    Thread.MemoryBarrier();
+#endif
+                    _store = newStore;
+                }
+
+                return value;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/TypeExtensions.cs b/Newtonsoft.Json/Utilities/TypeExtensions.cs
new file mode 100644
index 0000000..69d5341
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/TypeExtensions.cs
@@ -0,0 +1,624 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+#if NET20
+using Newtonsoft.Json.Utilities.LinqBridge;
+#else
+using System.Linq;
+#endif
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class TypeExtensions
+    {
+#if NETFX_CORE || PORTABLE
+        private static BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
+
+        public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo)
+        {
+            return propertyInfo.GetGetMethod(false);
+        }
+
+        public static MethodInfo GetGetMethod(this PropertyInfo propertyInfo, bool nonPublic)
+        {
+            MethodInfo getMethod = propertyInfo.GetMethod;
+            if (getMethod != null && (getMethod.IsPublic || nonPublic))
+                return getMethod;
+
+            return null;
+        }
+
+        public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo)
+        {
+            return propertyInfo.GetSetMethod(false);
+        }
+
+        public static MethodInfo GetSetMethod(this PropertyInfo propertyInfo, bool nonPublic)
+        {
+            MethodInfo setMethod = propertyInfo.SetMethod;
+            if (setMethod != null && (setMethod.IsPublic || nonPublic))
+                return setMethod;
+
+            return null;
+        }
+
+        public static bool IsSubclassOf(this Type type, Type c)
+        {
+            return type.GetTypeInfo().IsSubclassOf(c);
+        }
+
+        public static bool IsAssignableFrom(this Type type, Type c)
+        {
+            return type.GetTypeInfo().IsAssignableFrom(c.GetTypeInfo());
+        }
+#endif
+
+        public static MethodInfo Method(this Delegate d)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return d.Method;
+#else
+            return d.GetMethodInfo();
+#endif
+        }
+
+        public static MemberTypes MemberType(this MemberInfo memberInfo)
+        {
+#if !(NETFX_CORE || PORTABLE || PORTABLE40)
+            return memberInfo.MemberType;
+#else
+            if (memberInfo is PropertyInfo)
+                return MemberTypes.Property;
+            else if (memberInfo is FieldInfo)
+                return MemberTypes.Field;
+            else if (memberInfo is EventInfo)
+                return MemberTypes.Event;
+            else if (memberInfo is MethodInfo)
+                return MemberTypes.Method;
+            else
+                return MemberTypes.Other;
+#endif
+        }
+
+        public static bool ContainsGenericParameters(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.ContainsGenericParameters;
+#else
+            return type.GetTypeInfo().ContainsGenericParameters;
+#endif
+        }
+
+        public static bool IsInterface(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsInterface;
+#else
+            return type.GetTypeInfo().IsInterface;
+#endif
+        }
+
+        public static bool IsGenericType(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsGenericType;
+#else
+            return type.GetTypeInfo().IsGenericType;
+#endif
+        }
+
+        public static bool IsGenericTypeDefinition(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsGenericTypeDefinition;
+#else
+            return type.GetTypeInfo().IsGenericTypeDefinition;
+#endif
+        }
+
+        public static Type BaseType(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.BaseType;
+#else
+            return type.GetTypeInfo().BaseType;
+#endif
+        }
+
+        public static Assembly Assembly(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.Assembly;
+#else
+            return type.GetTypeInfo().Assembly;
+#endif
+        }
+
+        public static bool IsEnum(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsEnum;
+#else
+            return type.GetTypeInfo().IsEnum;
+#endif
+        }
+
+        public static bool IsClass(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsClass;
+#else
+            return type.GetTypeInfo().IsClass;
+#endif
+        }
+
+        public static bool IsSealed(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsSealed;
+#else
+            return type.GetTypeInfo().IsSealed;
+#endif
+        }
+
+#if PORTABLE40
+        public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object placeholder1, Type propertyType, IList<Type> indexParameters, object placeholder2)
+        {
+            IList<PropertyInfo> propertyInfos = type.GetProperties(bindingFlags);
+
+            return propertyInfos.Where(p =>
+            {
+                if (name != null && name != p.Name)
+                    return false;
+                if (propertyType != null && propertyType != p.PropertyType)
+                    return false;
+                if (indexParameters != null)
+                {
+                    if (!p.GetIndexParameters().Select(ip => ip.ParameterType).SequenceEqual(indexParameters))
+                        return false;
+                }
+
+                return true;
+            }).SingleOrDefault();
+        }
+
+        public static IEnumerable<MemberInfo> GetMember(this Type type, string name, MemberTypes memberType, BindingFlags bindingFlags)
+        {
+            return type.GetMembers(bindingFlags).Where(m =>
+            {
+                if (name != null && name != m.Name)
+                    return false;
+                if (m.MemberType() != memberType)
+                    return false;
+
+                return true;
+            });
+        }
+#endif
+
+#if (NETFX_CORE || PORTABLE)
+        public static MethodInfo GetBaseDefinition(this MethodInfo method)
+        {
+            return method.GetRuntimeBaseDefinition();
+        }
+#endif
+
+#if (NETFX_CORE || PORTABLE)
+        public static bool IsDefined(this Type type, Type attributeType, bool inherit)
+        {
+            return type.GetTypeInfo().CustomAttributes.Any(a => a.AttributeType == attributeType);
+        }
+
+        public static MethodInfo GetMethod(this Type type, string name)
+        {
+            return type.GetMethod(name, DefaultFlags);
+        }
+
+        public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().GetDeclaredMethod(name);
+        }
+
+        public static MethodInfo GetMethod(this Type type, IList<Type> parameterTypes)
+        {
+            return type.GetMethod(null, parameterTypes);
+        }
+
+        public static MethodInfo GetMethod(this Type type, string name, IList<Type> parameterTypes)
+        {
+            return type.GetMethod(name, DefaultFlags, null, parameterTypes, null);
+        }
+
+        public static MethodInfo GetMethod(this Type type, string name, BindingFlags bindingFlags, object placeHolder1, IList<Type> parameterTypes, object placeHolder2)
+        {
+            return type.GetTypeInfo().DeclaredMethods.Where(m =>
+                                                                {
+                                                                    if (name != null && m.Name != name)
+                                                                        return false;
+
+                                                                    if (!TestAccessibility(m, bindingFlags))
+                                                                        return false;
+
+                                                                    return m.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes);
+                                                                }).SingleOrDefault();
+        }
+
+        public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags, object placeholder1, Type propertyType, IList<Type> indexParameters, object placeholder2)
+        {
+            return type.GetTypeInfo().DeclaredProperties.Where(p =>
+                                                                   {
+                                                                       if (name != null && name != p.Name)
+                                                                           return false;
+                                                                       if (propertyType != null && propertyType != p.PropertyType)
+                                                                           return false;
+                                                                       if (indexParameters != null)
+                                                                       {
+                                                                           if (!p.GetIndexParameters().Select(ip => ip.ParameterType).SequenceEqual(indexParameters))
+                                                                               return false;
+                                                                       }
+
+                                                                       return true;
+                                                                   }).SingleOrDefault();
+        }
+
+        public static IEnumerable<MemberInfo> GetMember(this Type type, string name, MemberTypes memberType, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().GetMembersRecursive().Where(m =>
+                                                                      {
+                                                                          if (name != null && name != m.Name)
+                                                                              return false;
+                                                                          if (m.MemberType() != memberType)
+                                                                              return false;
+                                                                          if (!TestAccessibility(m, bindingFlags))
+                                                                              return false;
+
+                                                                          return true;
+                                                                      });
+        }
+
+        public static IEnumerable<ConstructorInfo> GetConstructors(this Type type)
+        {
+            return type.GetConstructors(DefaultFlags);
+        }
+
+        public static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags)
+        {
+            return type.GetConstructors(bindingFlags, null);
+        }
+
+        private static IEnumerable<ConstructorInfo> GetConstructors(this Type type, BindingFlags bindingFlags, IList<Type> parameterTypes)
+        {
+            return type.GetTypeInfo().DeclaredConstructors.Where(c =>
+                                                                     {
+                                                                         if (!TestAccessibility(c, bindingFlags))
+                                                                             return false;
+
+                                                                         if (parameterTypes != null && !c.GetParameters().Select(p => p.ParameterType).SequenceEqual(parameterTypes))
+                                                                             return false;
+
+                                                                         return true;
+                                                                     });
+        }
+
+        public static ConstructorInfo GetConstructor(this Type type, IList<Type> parameterTypes)
+        {
+            return type.GetConstructor(DefaultFlags, null, parameterTypes, null);
+        }
+
+        public static ConstructorInfo GetConstructor(this Type type, BindingFlags bindingFlags, object placeholder1, IList<Type> parameterTypes, object placeholder2)
+        {
+            return type.GetConstructors(bindingFlags, parameterTypes).SingleOrDefault();
+        }
+
+        public static MemberInfo[] GetMember(this Type type, string member)
+        {
+            return type.GetMember(member, DefaultFlags);
+        }
+
+        public static MemberInfo[] GetMember(this Type type, string member, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().GetMembersRecursive().Where(m => m.Name == member && TestAccessibility(m, bindingFlags)).ToArray();
+        }
+
+        public static MemberInfo GetField(this Type type, string member)
+        {
+            return type.GetField(member, DefaultFlags);
+        }
+
+        public static MemberInfo GetField(this Type type, string member, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().GetDeclaredField(member);
+        }
+
+        public static IEnumerable<PropertyInfo> GetProperties(this Type type, BindingFlags bindingFlags)
+        {
+            IList<PropertyInfo> properties = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
+                                                 ? type.GetTypeInfo().DeclaredProperties.ToList()
+                                                 : type.GetTypeInfo().GetPropertiesRecursive();
+
+            return properties.Where(p => TestAccessibility(p, bindingFlags));
+        }
+
+        private static IList<MemberInfo> GetMembersRecursive(this TypeInfo type)
+        {
+            TypeInfo t = type;
+            IList<MemberInfo> members = new List<MemberInfo>();
+            while (t != null)
+            {
+                foreach (var member in t.DeclaredMembers)
+                {
+                    if (!members.Any(p => p.Name == member.Name))
+                        members.Add(member);
+                }
+                t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
+            }
+
+            return members;
+        }
+
+        private static IList<PropertyInfo> GetPropertiesRecursive(this TypeInfo type)
+        {
+            TypeInfo t = type;
+            IList<PropertyInfo> properties = new List<PropertyInfo>();
+            while (t != null)
+            {
+                foreach (var member in t.DeclaredProperties)
+                {
+                    if (!properties.Any(p => p.Name == member.Name))
+                        properties.Add(member);
+                }
+                t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
+            }
+
+            return properties;
+        }
+
+        private static IList<FieldInfo> GetFieldsRecursive(this TypeInfo type)
+        {
+            TypeInfo t = type;
+            IList<FieldInfo> fields = new List<FieldInfo>();
+            while (t != null)
+            {
+                foreach (var member in t.DeclaredFields)
+                {
+                    if (!fields.Any(p => p.Name == member.Name))
+                        fields.Add(member);
+                }
+                t = (t.BaseType != null) ? t.BaseType.GetTypeInfo() : null;
+            }
+
+            return fields;
+        }
+
+        public static IEnumerable<MethodInfo> GetMethods(this Type type, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().DeclaredMethods;
+        }
+
+        public static PropertyInfo GetProperty(this Type type, string name)
+        {
+            return type.GetProperty(name, DefaultFlags);
+        }
+
+        public static PropertyInfo GetProperty(this Type type, string name, BindingFlags bindingFlags)
+        {
+            return type.GetTypeInfo().GetDeclaredProperty(name);
+        }
+
+        public static IEnumerable<FieldInfo> GetFields(this Type type)
+        {
+            return type.GetFields(DefaultFlags);
+        }
+
+        public static IEnumerable<FieldInfo> GetFields(this Type type, BindingFlags bindingFlags)
+        {
+            IList<FieldInfo> fields = (bindingFlags.HasFlag(BindingFlags.DeclaredOnly))
+                                          ? type.GetTypeInfo().DeclaredFields.ToList()
+                                          : type.GetTypeInfo().GetFieldsRecursive();
+
+            return fields.Where(f => TestAccessibility(f, bindingFlags)).ToList();
+        }
+
+        private static bool TestAccessibility(PropertyInfo member, BindingFlags bindingFlags)
+        {
+            if (member.GetMethod != null && TestAccessibility(member.GetMethod, bindingFlags))
+                return true;
+
+            if (member.SetMethod != null && TestAccessibility(member.SetMethod, bindingFlags))
+                return true;
+
+            return false;
+        }
+
+        private static bool TestAccessibility(MemberInfo member, BindingFlags bindingFlags)
+        {
+            if (member is FieldInfo)
+            {
+                return TestAccessibility((FieldInfo) member, bindingFlags);
+            }
+            else if (member is MethodBase)
+            {
+                return TestAccessibility((MethodBase) member, bindingFlags);
+            }
+            else if (member is PropertyInfo)
+            {
+                return TestAccessibility((PropertyInfo) member, bindingFlags);
+            }
+
+            throw new Exception("Unexpected member type.");
+        }
+
+        private static bool TestAccessibility(FieldInfo member, BindingFlags bindingFlags)
+        {
+            bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) ||
+                              (!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic));
+
+            bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) ||
+                            (!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance));
+
+            return visibility && instance;
+        }
+
+        private static bool TestAccessibility(MethodBase member, BindingFlags bindingFlags)
+        {
+            bool visibility = (member.IsPublic && bindingFlags.HasFlag(BindingFlags.Public)) ||
+                              (!member.IsPublic && bindingFlags.HasFlag(BindingFlags.NonPublic));
+
+            bool instance = (member.IsStatic && bindingFlags.HasFlag(BindingFlags.Static)) ||
+                            (!member.IsStatic && bindingFlags.HasFlag(BindingFlags.Instance));
+
+            return visibility && instance;
+        }
+
+        public static Type[] GetGenericArguments(this Type type)
+        {
+            return type.GetTypeInfo().GenericTypeArguments;
+        }
+
+        public static IEnumerable<Type> GetInterfaces(this Type type)
+        {
+            return type.GetTypeInfo().ImplementedInterfaces;
+        }
+
+        public static IEnumerable<MethodInfo> GetMethods(this Type type)
+        {
+            return type.GetTypeInfo().DeclaredMethods;
+        }
+#endif
+
+        public static bool IsAbstract(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsAbstract;
+#else
+            return type.GetTypeInfo().IsAbstract;
+#endif
+        }
+
+        public static bool IsVisible(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsVisible;
+#else
+            return type.GetTypeInfo().IsVisible;
+#endif
+        }
+
+        public static bool IsValueType(this Type type)
+        {
+#if !(NETFX_CORE || PORTABLE)
+            return type.IsValueType;
+#else
+            return type.GetTypeInfo().IsValueType;
+#endif
+        }
+
+        public static bool AssignableToTypeName(this Type type, string fullTypeName, out Type match)
+        {
+            Type current = type;
+
+            while (current != null)
+            {
+                if (string.Equals(current.FullName, fullTypeName, StringComparison.Ordinal))
+                {
+                    match = current;
+                    return true;
+                }
+
+                current = current.BaseType();
+            }
+
+            foreach (Type i in type.GetInterfaces())
+            {
+                if (string.Equals(i.Name, fullTypeName, StringComparison.Ordinal))
+                {
+                    match = type;
+                    return true;
+                }
+            }
+
+            match = null;
+            return false;
+        }
+
+        public static bool AssignableToTypeName(this Type type, string fullTypeName)
+        {
+            Type match;
+            return type.AssignableToTypeName(fullTypeName, out match);
+        }
+
+        public static MethodInfo GetGenericMethod(this Type type, string name, params Type[] parameterTypes)
+        {
+            var methods = type.GetMethods().Where(method => method.Name == name);
+
+            foreach (var method in methods)
+            {
+                if (method.HasParameters(parameterTypes))
+                    return method;
+            }
+
+            return null;
+        }
+
+        public static bool HasParameters(this MethodInfo method, params Type[] parameterTypes)
+        {
+            var methodParameters = method.GetParameters().Select(parameter => parameter.ParameterType).ToArray();
+
+            if (methodParameters.Length != parameterTypes.Length)
+                return false;
+
+            for (int i = 0; i < methodParameters.Length; i++)
+                if (methodParameters[i].ToString() != parameterTypes[i].ToString())
+                    return false;
+
+            return true;
+        }
+
+        public static IEnumerable<Type> GetAllInterfaces(this Type target)
+        {
+            foreach (var i in target.GetInterfaces())
+            {
+                yield return i;
+                foreach (var ci in i.GetInterfaces())
+                {
+                    yield return ci;
+                }
+            }
+        }
+
+        public static IEnumerable<MethodInfo> GetAllMethods(this Type target)
+        {
+            var allTypes = target.GetAllInterfaces().ToList();
+            allTypes.Add(target);
+
+            return from type in allTypes
+                   from method in type.GetMethods()
+                   select method;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/Utilities/ValidationUtils.cs b/Newtonsoft.Json/Utilities/ValidationUtils.cs
new file mode 100644
index 0000000..0e16805
--- /dev/null
+++ b/Newtonsoft.Json/Utilities/ValidationUtils.cs
@@ -0,0 +1,59 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+using System.Globalization;
+
+namespace Newtonsoft.Json.Utilities
+{
+    internal static class ValidationUtils
+    {
+        public static void ArgumentNotNullOrEmpty(string value, string parameterName)
+        {
+            if (value == null)
+                throw new ArgumentNullException(parameterName);
+
+            if (value.Length == 0)
+                throw new ArgumentException("'{0}' cannot be empty.".FormatWith(CultureInfo.InvariantCulture, parameterName), parameterName);
+        }
+
+        public static void ArgumentTypeIsEnum(Type enumType, string parameterName)
+        {
+            ArgumentNotNull(enumType, "enumType");
+
+            if (!enumType.IsEnum())
+                throw new ArgumentException("Type {0} is not an Enum.".FormatWith(CultureInfo.InvariantCulture, enumType), parameterName);
+        }
+
+        public static void ArgumentNotNull(object value, string parameterName)
+        {
+            if (value == null)
+                throw new ArgumentNullException(parameterName);
+        }
+    }
+}
\ No newline at end of file
diff --git a/Newtonsoft.Json/WriteState.cs b/Newtonsoft.Json/WriteState.cs
new file mode 100644
index 0000000..b2233f4
--- /dev/null
+++ b/Newtonsoft.Json/WriteState.cs
@@ -0,0 +1,72 @@
+#region License
+// Copyright (c) 2007 James Newton-King
+//
+// Permission is hereby granted, free of charge, to any person
+// obtaining a copy of this software and associated documentation
+// files (the "Software"), to deal in the Software without
+// restriction, including without limitation the rights to use,
+// copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the
+// Software is furnished to do so, subject to the following
+// conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+#endregion
+
+using System;
+
+namespace Newtonsoft.Json
+{
+    /// <summary>
+    /// Specifies the state of the <see cref="JsonWriter"/>.
+    /// </summary>
+    public enum WriteState
+    {
+        /// <summary>
+        /// An exception has been thrown, which has left the <see cref="JsonWriter"/> in an invalid state.
+        /// You may call the <see cref="JsonWriter.Close"/> method to put the <see cref="JsonWriter"/> in the <c>Closed</c> state.
+        /// Any other <see cref="JsonWriter"/> method calls results in an <see cref="InvalidOperationException"/> being thrown. 
+        /// </summary>
+        Error,
+
+        /// <summary>
+        /// The <see cref="JsonWriter.Close"/> method has been called. 
+        /// </summary>
+        Closed,
+
+        /// <summary>
+        /// An object is being written. 
+        /// </summary>
+        Object,
+
+        /// <summary>
+        /// A array is being written.
+        /// </summary>
+        Array,
+
+        /// <summary>
+        /// A constructor is being written.
+        /// </summary>
+        Constructor,
+
+        /// <summary>
+        /// A property is being written.
+        /// </summary>
+        Property,
+
+        /// <summary>
+        /// A write method has not been called.
+        /// </summary>
+        Start
+    }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..266c597
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+# README #
+
+AxCrypt 2.x - Portable Open Source Encryption in C# for .NET/Mono.
+
+### AxCrypt 2.x ###
+
+This is still pre-release software. Use with care. API:s may break at any moment.
+
+### How To Build? ###
+
+For Windows, download the source code and open in Visual Studio. There
+are no external dependencies.
+
+Unit tests require a NUnit-compatible unit test runnere.
+
+### How to Contribute ###
+
+Talk to me. Due to the nature of the application, pull requests are audited very carefully.
+Before requesting a pull it's best if we discuss things.
+
+Minimum requirements is that FxCop/Static Code Analysis passes without warnings, as well as
+compilation. There should be tests covering every line of code in Axantum.AxCrypt.Core.
+
+### Contact ###
+
+Contact me, Svante Seleborg, Axantum Software AB via svante at axantum.com .
\ No newline at end of file
diff --git a/Solution.FxCop b/Solution.FxCop
new file mode 100644
index 0000000..54c7529
--- /dev/null
+++ b/Solution.FxCop
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FxCopProject Version="10.0" Name="AxCrypt.NET">
+ <ProjectOptions>
+  <SharedProject>True</SharedProject>
+  <Stylesheet Apply="False">$(FxCopDir)\Xml\FxCopReport.xsl</Stylesheet>
+  <SaveMessages>
+   <Project Status="Active, Excluded" NewOnly="False" />
+   <Report Status="Active" NewOnly="False" />
+  </SaveMessages>
+  <ProjectFile Compress="True" DefaultTargetCheck="True" DefaultRuleCheck="True" SaveByRuleGroup="" Deterministic="True" />
+  <EnableMultithreadedLoad>True</EnableMultithreadedLoad>
+  <EnableMultithreadedAnalysis>True</EnableMultithreadedAnalysis>
+  <SourceLookup>True</SourceLookup>
+  <AnalysisExceptionsThreshold>10</AnalysisExceptionsThreshold>
+  <RuleExceptionsThreshold>1</RuleExceptionsThreshold>
+  <Spelling Locale="en-US" />
+  <OverrideRuleVisibilities>False</OverrideRuleVisibilities>
+  <CustomDictionaries SearchFxCopDir="True" SearchUserProfile="True" SearchProjectDir="True" />
+  <SearchGlobalAssemblyCache>False</SearchGlobalAssemblyCache>
+  <DeadlockDetectionTimeout>120</DeadlockDetectionTimeout>
+  <IgnoreGeneratedCode>True</IgnoreGeneratedCode>
+  <TargetFrameworkVersion>3.5</TargetFrameworkVersion>
+ </ProjectOptions>
+ <Targets>
+  <AssemblyReferenceDirectories>
+   <Directory>$(ProjectDir)/Axantum.AxCrypt.Core/bin/Debug/</Directory>
+  </AssemblyReferenceDirectories>
+  <Target Name="$(ProjectDir)/Axantum.AxCrypt.Core.Test/bin/Debug/Axantum.AxCrypt.Core.Test.dll" Analyze="True" AnalyzeAllChildren="True" />
+  <Target Name="$(ProjectDir)/Axantum.AxCrypt.Mono.Test/bin/Debug/Axantum.AxCrypt.Mono.Test.dll" Analyze="True" AnalyzeAllChildren="True" />
+  <Target Name="$(ProjectDir)/Axantum.AxCrypt.Mono/bin/Debug/Axantum.AxCrypt.Mono.dll" Analyze="True" AnalyzeAllChildren="True" />
+  <Target Name="$(ProjectDir)/Axantum.AxCrypt/bin/Debug/Axantum.AxCrypt.Core.dll" Analyze="True" AnalyzeAllChildren="True" />
+  <Target Name="$(ProjectDir)/Axantum.AxCrypt/bin/Debug/Axantum.AxCrypt.exe" Analyze="True" AnalyzeAllChildren="True" />
+ </Targets>
+ <Rules>
+  <RuleFiles>
+   <RuleFile Name="$(FxCopDir)\Rules\DesignRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\GlobalizationRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\InteroperabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\MobilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\NamingRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\PerformanceRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\PortabilityRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\SecurityRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\SecurityTransparencyRules.dll" Enabled="True" AllRulesEnabled="True" />
+   <RuleFile Name="$(FxCopDir)\Rules\UsageRules.dll" Enabled="True" AllRulesEnabled="True" />
+  </RuleFiles>
+  <Groups />
+  <Settings />
+ </Rules>
+ <FxCopReport Version="10.0" />
+</FxCopProject>
diff --git a/SolutionItems/AxCrypt 2.0 Design.html b/SolutionItems/AxCrypt 2.0 Design.html
new file mode 100644
index 0000000..b195550
--- /dev/null
+++ b/SolutionItems/AxCrypt 2.0 Design.html	
@@ -0,0 +1,200 @@
+<html>
+<head>
+    <meta name="GENERATOR" content="Microsoft Visual Studio 8.0">
+    <title></title>
+</head>
+<body>
+    <h1>
+        Introduction</h1>
+    <p>
+        AxCrypt version 2 is intended to extend and improve on AxCrypt 1.x in various ways,
+        based on the almost 10 years of experience with version 1.</p>
+    <h1>
+        Main Design Goals</h1>
+    <p>
+        The main design goals lists features and behavior that will be realized by version
+        2. Some are the same as in version 1, some are different etc.</p>
+    <ul>
+        <li>Portability - AxCrypt was designed to use and exploit the Win32 API as much as possible.
+            AxCrypt2 will instead focus on cross platform portability, primarily for Linux and
+            Mac, and secondary for mobile platforms (the idea being that differences will be
+            reduced in time). This will be achieved by use of .NET/Mono for as much of the core
+            as possible:
+            <ul>
+                <ul>
+                    <li>Third party libraries used must also be Mono compatible. Initially only BouncyCastle
+                        is used, and that for the ZLib implementation and the potential to use the cryptography
+                        features in the future.</li>
+                </ul>
+            </ul>
+        </li>
+        <li>Simpler build process - AxCrypt has a very complex build process with extensive
+            scripting for various reasons. Some customization of the build will be required,
+            but the goal is to keep it as simple as possible - possibly even at the expense
+            of some convenience.</li>
+        <li>No installation will be required, but will be offered for additinal functionality.
+            The regular AxCrypt executable should as far as is possible be a simple executable
+            without any need for installation. There may be some need for ILMerge, but if it
+            turns out we're only using ZLib from third party source it may be better to
+            include it via source than to require ILMerg.</li>
+        <li>MSI-based installer via Wi.</li>
+        <li>Less dependence on advanced features of Visual Studio - Should be buildable and
+            compileable with Visual Studio Express.</li>
+        <li>More forgiving for fatal errors during uninstallation - an uninstall should probably
+            never give up. It may ask the users permission to continue if an error is encountered,
+            but it really should complete.</li>
+        <li>No scripting logic to handle OEM adaptions. This will be handled by branching in
+            the repository instead - but all OEM-variable texts and data should be concentrated
+            to as few files as possible.</li>
+        <li>No use of registry for user settings. User settings are stored in a monitored XML
+            file, which is stored in a platform-dependent user-local location. Global settings,
+            if any are stored in an XML file in a platform-dependent location, typically the
+            same folder as the program or in application data local settings (%LOCALAPPDATA%).</li>
+        <li>Less use of advanced features - much more robust handling of automatic reencryption,
+            possibly at the expense of some manual operation.</li>
+    </ul>
+    <h1>
+        Main Anti Goals</h1>
+    <ul>
+        <li>Less worry about clear-text in memory. Keeping the local system clean to this extent
+            is really hard. We may use the SecureString class, but it's very inconvenient
+            and questionable all-in all it's not only strings that needs to be kept safe.
+            Using ProtectedMemory is not really a solution either since the clear text needs
+            to be there anyway at least briefly.</li>
+    </ul>
+    <p>
+    </p>
+    <h1>
+        Design Details</h1>
+    <h2>
+        Decrypt-Modify-EncDecrypt-Modify-Encrypt</h2>
+    <p>
+        The current implementation in AxCrypt works reasonably well in many cases, but is
+        very platform dependent, and very hard to port. It's also rather sensitive to
+        various smarter applications, and their creative behavior. Notably Open Office,
+        and proably more recent versions of Microsof Office as well.</p>
+    <p>
+        A more robust scheme should depend as little as possible on advanced platform features.
+        Waitable applications are probably ok, but non-returning and too-quick-returning
+        applications must be handled. Turning this on it's head... Opportunistic re-encryption?
+        As soon as it's modified, and we can get exclusive access, re-encrypt. Keep a "transaction
+        log", recording what is in the temp folder, where it came from and thus should be
+        re-encrypted to.</p>
+    <p>
+        Use of platform dependent file watching should be ok, in Windows use file system
+        watcher, otherwise a polling implementation.</p>
+    <p>
+        Deletion of a sucessfully re-encrypted file that could be opened exclusively should
+        be ok. If it's kept in memory by the app, and then re-saved nothing bad should happen,
+        as long as we know where it came from we can still re-encrypt.</p>
+    <p>
+        If we can keep the transaction log in plain text, that will facilitate. This should
+        be doable, since the only sensitive information is the file names, and they will
+        be removed from  the log when the corresponding file is removed.</p>
+    <ol>
+        <li>A file is decrypted (if required, it may already be decrypted), and the application
+            launched. The fact is noted in the user transaction log, which contains the source
+            path, the temp path, the key thumbprint and the time of the original. Nothing more
+            happens in this thread.</li>
+        <li>A watcher thread will check if a file is modified later than what is recorded in
+            the transaction log. Every time a modification is noted, and the clear text file
+            can be accessed exclusively, it is re-encrypted. The watcher thread could be driven
+            by file system watchers, but for simplicity sake it just polls every X seconds,
+            or when it is kicked. When something happens, the wiper thread is kicked to ensure
+            that things happen rapidly.</li>
+        <li>A wiper thread will check every Y seconds if a file in the transaction log can be
+            accessed excusively with no change. Y is dynamic and stored in the transaction log,
+            so it can grow and shrink. If the file can be access exclusively, it is wiped. This
+            is really the only weakness, an application could let go of all handles, and still
+            expect to read more from the file - if so it will be somewhat surprised to see it
+            gone...</li>
+        <li>(Conditional wiping is handled by associating applications with enabled and disabled
+            automatic wipe. An unknown associated application prompts the user, with the recommendation
+            being automatic.This is platform dependent, but the idea is that there should be
+            a pre-populated list of the most common applications.)</li>
+        <li>Deferred wiping occurs during system shutdown, logout and with a manual dialog.>The
+            transaction loThe transaction log can also mark a directory as encrypted, in which
+            case files placed there will be automatically encrypted (as long as AxCrypt is running
+            of course).</li>
+        <li>(A user request for encryption of a plain-text-file, or a directory, is actually
+            accomplished by entering it into the transaction log, and kicking the watcher thread.
+            Maybe...)</li>
+        <li>Command line operations typically mimic the same operations as performed by the
+            GUI, as if entered via the GUI (with some obvious extensions) - but they must be
+            possible to run synchronously so that operations are waitable. For real batch operations,
+            a new non-interactive flag will be introduced, which will cause no GUI at all to
+            be invoked, and a purely synchronous execution model - no transaction log etc.
+            <h2>
+                Inter Process Communication</h2>
+            <p>
+                This should be minimized and simplified... But how? We want and need a resident
+                process for reencryption and wiper threads, and we probably need to keep keys there.</p>
+            <p>
+                The shell extension and similar components can launch AxCrypt as a child process,
+                and can thus provide a pipe for IPC. How this secondary delegating process actually
+                communicates with the primary work process is less of a problem since it's an internal
+                issue. But since we can now use the secondary delegating instance as a proxy, there's
+                a single simple interface to use along side with the command line.</p>
+            <p>
+                In any way, command line launching is always GUI-free, thus bypassing all complex
+                windowing problems of AxCrypt 1. A client that wants to provide a GUI will have
+                to do so by itself.</p>
+            <p>
+                The command line can have an option specifying a file descriptor to write status
+                messages, progress etc to. These will be text-free, since it's supposed the client
+                will have to handle localization issues. Text-only, localized messages, are provided
+                on stderr (possibly only if requested).</p>
+            <p>
+                This means the shell extension passphrase dialog and progress dialog will by necessity
+                be managed by the shell extension. Progress information etc will have to be communicated
+                from the main instance via IPC, as well as passphrase info. Should be ok.</p>
+            <p>
+                Options for IPC are:</p>
+            Options for IPC are:</p>
+            <ol>
+                <li>Shared Memory</li>
+                <li>Shared Files (This is probably the only portable one).</li>
+                <li>Named Pipes</li>
+                <li>TCP/IP</li>
+            </ol>
+            <h2>
+                Primary GUI Worker/Secondary Proxy design</h2>
+            <p>
+                The same basic design is used as in AxCrypt 1, but the difference is that the secondary
+                processes never have any GUI actions. They may emit output to standard output and/or
+                standard error, just like a command line utility. (They also offer the capability
+                to accept commands via stdin instead, and emit protocol rather than text responses
+                and progress feedback etc via stdout.) The secondary processes are 'waitable'
+                for typical operations such as encrypt and decrypt. Real progress is shown via the
+                primary tray process, but the shell extension can show a message box with an animation
+                and reference to the tray process.</p>
+            <p>
+                AxCrypt started without arguments starts the tray app in full visible window mode.
+                With arguments it can be started in tray mode, or as a secondary.</p>
+            <p>
+                The primary process, at least in Windows, is a tray application with full GUI interaction.
+                It may be started as a stand-alone program or as the result of for example Shell
+                Extension call via the command line.</p>
+            <p>
+                IPC between Primary and Secondary is implemented using... ?.
+                <p>
+                    For now, the decision is to go with shared files, but the mechanism will be implemented
+                    as a concrete implementation of an interface so it can upgraded/changed at a later
+                    time. Also, for now, the shared file will be written in clear text, no encryption
+                    altough wiped as soon as possible. The window is small, and in most cases a wipe
+                    should be effective. Focus is not on paraoid keeping of key material secure on the
+                    local PC.</p>
+                <h2>
+                    GUI behavior</h2>
+                <p>
+                    The GUI will be a app with drag and drop and file open dialogs to select files for
+                    encryption or decryption. Passphrase entry will be a typical modal dialog box. Progress
+                    indication will be a separate element in the window, and also visible in the tray
+                    icon (for windows) and when hovering. Pop-ups from the tray can be used to indicate
+                    things like files being re-encrypted etc.
+                </p>
+                <h2>
+                Shell Extension ImplementationThe shell extension has been fraught with problems
+                due to the issues of cross process communication and windowing.</p>
+</body>
+</html>
\ No newline at end of file
diff --git a/SolutionItems/Axantum.targets b/SolutionItems/Axantum.targets
new file mode 100644
index 0000000..198c145
--- /dev/null
+++ b/SolutionItems/Axantum.targets
@@ -0,0 +1,266 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * AxCrypt - Copyright 2014, Svante Seleborg, All Rights Reserved
+ *
+ * This file is part of AxCrypt.
+ *
+ * AxCrypt is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * AxCrypt 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with AxCrypt.  If not, see <http://www.gnu.org/licenses />.
+ *
+ * The source is maintained at http://bitbucket.org/axantum/axcrypt-net please visit for
+ * updates, contributions and contact with the author. You may also visit
+ * http://www.axantum.com for more information about the author.
+ */
+-->
+
+<!--
+    When this file is modified, close and re-open the solution to have Visual Studio recognize the change.
+
+    The encrypted private key file is part of the distribution, but is protected with a private password.
+    In Axantum build environment, the private key is loaded into a key-container, defined by Visual Studio
+    to be named VS_KEY_xxxxxxxxx, and resolved by $(KeyContainerName) . For a private build, you may need
+    to create your own key pair, or disable assembly strong naming. Also, for Visual Studio to handle the
+    key-container, you need to have KeyOriginatorFile set before loading Microsoft.CSharp.targets. An easy
+    way to achieve this is to use properties, enable Signing, select AxantumStrongName.pfx, then disable
+    signing. The KeyOriginatorFile property remains set, shown by being grey in the GUI. Go figure.
+
+    The Microsoft build files are typically found at:
+    C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.CSharp.targets
+    C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets
+-->
+<Project ToolsVersion="4.0"
+         DefaultTargets="Build"
+         xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_AxCryptMajor>2</_AxCryptMajor>
+    <_AxCryptMinor>0</_AxCryptMinor>
+    <AxBuildNumber Condition=" '$(AxBuildNumber)' == '' ">0</AxBuildNumber>
+  </PropertyGroup>
+  <PropertyGroup>
+    <_AxCanonicalName>AxCrypt</_AxCanonicalName>
+    <_AxIsAxantumDeveloper>false</_AxIsAxantumDeveloper>
+    <_AxIsAxantumDeveloper Condition=" '$(AX_AXANTUM)' == 'True' ">true</_AxIsAxantumDeveloper>
+    <_AxIsAxantumBuildServer>false</_AxIsAxantumBuildServer>
+    <_AxIsAxantumBuildServer Condition=" '$(COMPUTERNAME)' == 'SHADOW' ">true</_AxIsAxantumBuildServer>
+    <_AxIsAxantum>false</_AxIsAxantum>
+    <_AxIsAxantum Condition=" '$(_AxIsAxantumDeveloper)' == 'true' Or '$(_AxIsAxantumBuildServer)' == 'true' ">true</_AxIsAxantum>
+    <_AxSignToolPath>$(MSBuildThisFileDirectory)signtool.exe</_AxSignToolPath>
+    <_AxIsAxantumBuild>true</_AxIsAxantumBuild>
+    <_AxBuildserverDistinguishingPath>C:\Build</_AxBuildserverDistinguishingPath>
+    <_AxIsBuildServerBuild>false</_AxIsBuildServerBuild>
+    <_AxIsBuildServerBuild Condition=" Exists('$(_AxBuildserverDistinguishingPath)') ">true</_AxIsBuildServerBuild>
+    <_AxTimeStampUrl>http://timestamp.comodoca.com/authenticode</_AxTimeStampUrl>
+    <_AxCertificateThumbprint>fc898fdc88b037ff88ea154ff25a24aea11eda9c</_AxCertificateThumbprint>
+    <_AxIlMergePath Condition=" '$(_AxIlMergePath)' == '' And Exists('$(ProgramFiles(x86))\Microsoft\ILMerge\ILMerge.exe') ">$(ProgramFiles(x86))\Microsoft\ILMerge\ILMerge.exe</_AxIlMergePath>
+    <_AxIlMergePath Condition=" '$(_AxIlMergePath)' == '' And Exists('$(ProgramFiles)\Microsoft\ILMerge\ILMerge.exe') ">$(ProgramFiles)\Microsoft\ILMerge\ILMerge.exe</_AxIlMergePath>
+    <_AxIlMergePath Condition=" '$(_AxIlMergePath)' == '' And Exists('$(MSBuildThisFileDirectory)Ilmerge.exe') ">$(MSBuildThisFileDirectory)Ilmerge.exe</_AxIlMergePath>
+        <_AxIlMergePath Condition=" '$(XAMARINSTUDIO_LAUNCHER)' != '' "></_AxIlMergePath>
+  </PropertyGroup>
+  <PropertyGroup>
+    <UseHostCompilerIfAvailable>false</UseHostCompilerIfAvailable>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(_AxIsBuildServerBuild)' == 'true' ">
+    <_AxIgnoreSignToolErrors>false</_AxIgnoreSignToolErrors>
+  </PropertyGroup>
+
+  <PropertyGroup Condition=" '$(_AxIsBuildServerBuild)' == 'false' ">
+    <_AxIgnoreSignToolErrors>true</_AxIgnoreSignToolErrors>
+  </PropertyGroup>
+
+  <!-- Use the parameter AxAuthenticodeFile to determine the file name. -->
+  <Target Name="AxAuthenticodeSignOneFile">
+    <Exec Command=""$(_AxSignToolPath)" sign /sha1 $(_AxCertificateThumbprint) /sm /v /t "$(_AxTimeStampUrl)" "$(AxAuthenticodeFile)""
+          Condition=" Exists('$(_AxSignToolPath)') "
+          ContinueOnError="true">
+      <Output TaskParameter="ExitCode"
+              PropertyName="_AxExitCode" />
+    </Exec>
+    <!-- Retry once if there's an error we're not ignoring errors-->
+    <Exec Command=""$(_AxSignToolPath)" sign /sha1 $(_AxCertificateThumbprint) /sm /v /t "$(_AxTimeStampUrl)" "$(AxAuthenticodeFile)" >nul"
+          Condition=" Exists('$(_AxSignToolPath)') And '$(_AxExitCode)' != '0' And '$(_AxIgnoreSignToolErrors)' == 'false' "
+          ContinueOnError="true">
+      <Output TaskParameter="ExitCode"
+              PropertyName="_AxExitCode" />
+    </Exec>
+    <!-- Retry again if there's an error we're not ignoring errors-->
+    <Exec Command=""$(_AxSignToolPath)" sign /sha1 $(_AxCertificateThumbprint) /sm /v /t "$(_AxTimeStampUrl)" "$(AxAuthenticodeFile)" >nul"
+          Condition=" Exists('$(_AxSignToolPath)') And '$(_AxExitCode)' != '0' And '$(_AxIgnoreSignToolErrors)' == 'false' "
+          ContinueOnError="true">
+      <Output TaskParameter="ExitCode"
+              PropertyName="_AxExitCode" />
+    </Exec>
+    <!-- Really fail if we're still in error, and we're not ignoring errors. -->
+    <Error Text="Authenticode signing failed even after three retries."
+           Condition=" '$(_AxExitCode)' != 0 And '$(_AxIgnoreSignToolErrors)' == 'false' " />
+    <Message Text="$(MSBuildProjectName) -> Authenticode signed $(AxAuthenticodeFile)"
+             Importance="high" />
+  </Target>
+
+  <UsingTask TaskName="TemplateFileTask"
+             AssemblyFile="..\SolutionItems\MSBuild.Axantum.Tasks.dll" />
+
+  <Target Name="_AxMergeExe"
+            Condition="'$(OutputType)' == 'Winexe' And '$(_AxIlMergePath)' != ''">
+    <PropertyGroup>
+      <_AxIlMergeStrongNameArguments Condition=" '$(KeyContainerName)' != '' And '$(SignAssembly)' == 'true' ">/delaysign "/keyfile:$(MSBuildThisFileDirectory)AxantumStrongName.pub"</_AxIlMergeStrongNameArguments>
+    </PropertyGroup>
+    <Exec Command=""$(_AxIlMergePath)" $(_AxIlMergeStrongNameArguments) /attr:"@(MainAssembly)" /targetplatform:v4,"$(ProgramFiles)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5" /out:"$(OutputPath)$(_AxMergedBaseFileName).exe" "$(_AxMergeMainExecutable)" @(_AxIlMergeAssemblies->'"%(FullPath)"', ' ')" />
+    <Copy SourceFiles="$(IntermediateOutputPath)$(AssemblyName).pdb"
+          DestinationFiles="$(OutputPath)$(_AxMergedBaseFileName).pdb" />
+    <ItemGroup>
+      <FileWrites Include="$(OutputPath)$(_AxMergedBaseFileName).exe" />
+      <FileWrites Include="$(OutputPath)$(_AxMergedBaseFileName).pdb" />
+    </ItemGroup>
+  </Target>
+
+  <Target Name="_AxSignExe"
+          Condition="'$(OutputType)' == 'Winexe' And '$(KeyContainerName)' != '' And '$(SignAssembly)' == 'true' ">
+    <Exec Command=""$(MSBuildThisFileDirectory)sn.exe" -Rca "$(OutputPath)$(_AxMergedBaseFileName).exe" $(KeyContainerName)" />
+    <MSBuild Projects="$(MSBuildProjectFullPath)"
+             Targets="AxAuthenticodeSignOneFile"
+             Properties="AxAuthenticodeFile=$(OutputPath)$(_AxMergedBaseFileName).exe" />
+  </Target>
+
+  <Target Name="_AxRecopyMerged" Condition=" '$(_AxIsBuildServerBuild)' != 'true' ">
+    <Copy SourceFiles="$(OutputPath)$(_AxMergedBaseFileName).exe"
+          DestinationFiles="$(MSBuildThisFileDirectory)..\Axantum.AxCrypt\bin\$(Configuration)\$(_AxCanonicalName).exe"
+          SkipUnchangedFiles="true"
+          Condition=" '$(_AxMergedBaseFileName)' != '$(_AxCanonicalName)' " />
+  </Target>
+
+  <Target Name="_AxMergeAndSign"
+          Inputs="$(MSBuildProjectFullPath);@(MainAssembly);@(_AxIlMergeAssemblies)"
+          Outputs="$(OutputPath)$(_AxMergedBaseFileName).exe"
+          DependsOnTargets="_AxMergeExe;_AxSignExe;_AxRecopyMerged"
+          Condition=" '$(OutputType)' == 'Winexe' And '$(_AxIlMergePath)' != '' ">
+  </Target>
+
+  <Target Name="_AxSetVersionedFileName">
+    <PropertyGroup Condition=" '$(AxBuildNumber)' != '' ">
+      <_AxVersionedFileName>AxCrypt-$(_AxCryptMajor).$(_AxCryptMinor).$(AxBuildNumber).0.exe</_AxVersionedFileName>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxCopyToVersionedFileName"
+          Inputs="$(OutputPath)$(_AxMergedBaseFileName).exe"
+          Outputs="$(OutputPath)$(_AxVersionedFileName)"
+          Condition=" '$(_AxVersionedFileName)' != '' ">
+    <Copy SourceFiles="$(OutputPath)$(_AxMergedBaseFileName).exe"
+          DestinationFiles="$(OutputPath)$(_AxVersionedFileName)"
+          SkipUnchangedFiles="true" />
+    <ItemGroup>
+      <FileWrites Include="$(OutputPath)$(_AxVersionedFileName)" />
+    </ItemGroup>
+  </Target>
+
+  <Target Name="_AxSetRevisionAndCopyToVersionedFileName"
+          DependsOnTargets="_AxSetVersionedFileName;_AxCopyToVersionedFileName"
+          Condition=" '$(Configuration)' == 'Release' And '$(OutputType)' == 'Winexe' And '$(KeyContainerName)' != '' And '$(SignAssembly)' == 'true' ">
+  </Target>
+
+  <Target Name="_AxFindIlMergeAssemblies">
+    <CreateItem Include="@(ReferencePath)"
+                Condition="'%(CopyLocal)'=='true'">
+      <Output TaskParameter="Include"
+              ItemName="_AxIlMergeAssemblies" />
+    </CreateItem>
+    <PropertyGroup>
+      <_AxMergedBaseFileName>$(_AxCanonicalName)</_AxMergedBaseFileName>
+      <_AxMergeMainExecutable>@(MainAssembly)</_AxMergeMainExecutable>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxFixupVersion"
+          Inputs="Properties\AssemblyInfo.template;$(MSBuildProjectFullPath)"
+          Outputs="$(IntermediateOutputPath)AssemblyInfo.cs"
+          Condition=" Exists('Properties\AssemblyInfo.template') ">
+    <MakeDir Directories="$(IntermediateOutputPath)" />
+    <ItemGroup>
+      <_AxTemplateValues Include="$REVNUM$">
+        <Value>$(AxBuildNumber)</Value>
+      </_AxTemplateValues>
+      <_AxTemplateValues Include="$DIRTY$">
+        <Value>0</Value>
+      </_AxTemplateValues>
+    </ItemGroup>
+    <TemplateFileTask TemplateFile="Properties\AssemblyInfo.template"
+                      TargetFile="$(IntermediateOutputPath)AssemblyInfo.cs"
+                      Values="@(_AxTemplateValues)" />
+    <ItemGroup>
+      <Compile Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
+      <FileWrites Include="$(IntermediateOutputPath)AssemblyInfo.cs" />
+    </ItemGroup>
+  </Target>
+
+  <Target Name="_AxFixupAssemblyStrongNaming"
+          Condition=" '$(KeyContainerName)' == '' And '$(KeyOriginatorFile)' == 'AxantumStrongName.pfx' ">
+    <PropertyGroup>
+      <KeyOriginatorFile></KeyOriginatorFile>
+      <SignAssembly>false</SignAssembly>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxBeforeBuild"
+          DependsOnTargets="_AxFixupVersion">
+    <PropertyGroup Condition=" '$(_AxIsAxantum)' == 'true' ">
+      <_AxPreviousDefineConstants>$(DefineConstants)</_AxPreviousDefineConstants>
+      <DefineConstants>$(DefineConstants);AXANTUM</DefineConstants>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxAfterBuild">
+    <PropertyGroup Condition=" '$(_AxIsAxantum)' == 'true' ">
+      <DefineConstants>$(_AxPreviousDefineConstants)</DefineConstants>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxSetupStrongNaming"
+          Condition=" '$(_AxIsAxantum)' == 'true' ">
+    <PropertyGroup>
+      <KeyOriginatorFile>AxantumStrongName.pfx</KeyOriginatorFile>
+      <SignAssembly>true</SignAssembly>
+    </PropertyGroup>
+  </Target>
+
+  <Target Name="_AxCheckBuildEnvironment">
+  </Target>
+
+  <PropertyGroup>
+    <PrepareForRunDependsOn>
+      $(PrepareForRunDependsOn);
+      _AxFindIlMergeAssemblies;_AxMergeAndSign
+    </PrepareForRunDependsOn>
+  </PropertyGroup>
+
+  <PropertyGroup Condition=" '$(_AxIsAxantum)' == 'true' ">
+    <CoreBuildDependsOn>
+      _AxCheckBuildEnvironment;
+      _AxSetupStrongNaming;
+      $(CoreBuildDependsOn)
+    </CoreBuildDependsOn>
+    <BuildDependsOn>
+      _AxBeforeBuild;
+      $(BuildDependsOn);
+      _AxAfterBuild
+    </BuildDependsOn>
+    <PrepareForRunDependsOn>
+      $(PrepareForRunDependsOn);
+      _AxSetRevisionAndCopyToVersionedFileName
+    </PrepareForRunDependsOn>
+  </PropertyGroup>
+
+  <Target Name="BeforeCompile"
+          DependsOnTargets="_AxFixupAssemblyStrongNaming">
+  </Target>
+</Project>
\ No newline at end of file
diff --git a/SolutionItems/AxantumStrongName.pub b/SolutionItems/AxantumStrongName.pub
new file mode 100644
index 0000000..ed74af9
Binary files /dev/null and b/SolutionItems/AxantumStrongName.pub differ
diff --git a/SolutionItems/CustomDictionary.xml b/SolutionItems/CustomDictionary.xml
new file mode 100644
index 0000000..b16df34
--- /dev/null
+++ b/SolutionItems/CustomDictionary.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- http://msdn.microsoft.com/en-us/library/bb514188.aspx -->
+<Dictionary>
+    <Words>
+        <Unrecognized>
+            <Word></Word>
+        </Unrecognized>
+        <Recognized>
+            <Word>Axantum</Word>
+            <Word>Svenska</Word>
+        </Recognized>
+        <Deprecated>
+            <Term PreferredAlternate=""></Term>
+        </Deprecated>
+        <Compound>
+            <Term CompoundAlternate=""></Term>
+        </Compound>
+        <DiscreteExceptions>
+            <Term></Term>
+        </DiscreteExceptions>
+    </Words>
+    <Acronyms>
+        <CasingExceptions>
+            <Acronym>Ax</Acronym>
+        </CasingExceptions>
+    </Acronyms>
+</Dictionary>
\ No newline at end of file
diff --git a/SolutionItems/HowToBuild.txt b/SolutionItems/HowToBuild.txt
new file mode 100644
index 0000000..880e962
--- /dev/null
+++ b/SolutionItems/HowToBuild.txt
@@ -0,0 +1,54 @@
+About SolutionItems.dll
+=======================
+
+The project 'SolutionItems' is a dummy project to bridge the missing feature of a generic MSBuild project
+and also to compensate for Visual Studio Express not supporting the 'Solution Items' feature of the
+non-Express editions of Visual Studio.
+
+How To Build
+============
+
+Windows: Visual Studio 2010 (Any version including Express) or MonoDevelop. Load the solution and hit 'Build'.
+
+Linux: (Tested on Ubuntu) MonoDevelop. If earlier than 2.11, also need 'mono-gmcs' to compile against 3.5 profile.
+
+MonoDevelop: Under "MonoDevelop | Tools | Options | Preferences | Build | General" enable "Compile projects using MSBuild / XBuild".
+            (Avoid MonoDevlop issue: "Error while trying to invoke 'al2' to generate satellite assembly for 'XX' culture, File Not Found")
+
+About Configuration and Platforms
+=================================
+
+One solution file is used for to build all configurations and platforms.
+
+Supported configurations are:
+
+AppStore         - Mac OS X on the Mac with MonoDevelop. Defined for Axantum.AxCrypt.Core, Axantum.AxCrypt.Mono, Axantum.AxCrypt.Mac
+Debug            - Debugging and development. Defined for Axantum.AxCrypt, Axantum.AxCrypt.Core, Axantum.AxCrypt.Core.Test, Axantum.AxCrypt.Mono, Axantum.AxCrypt.Mono.Test
+DebugAndroid     - Android debugging and development. Defined for Axantum.AxCrypt.Core.Android
+Release          - Distributable. Defined for Axantum.AxCrypt, Axantum.AxCrypt.Core, Axantum.AxCrypt.Mono
+ReleaseAndroid   - Distributable. Defined for Axantum.AxCrypt.Core.Android
+
+Target platforms are:
+
+Mixed Platforms  - x86 for Axantum.AxCrypt, and Any CPU for all rest
+x86              - Defined for all but Axantum.AxCrypt.Core.Android
+Any CPU          - Defined for all
+
+The primary plaform is Any CPU except for Axantum.AxCrypt development where it is x86 due to better edit-and-continue support as well as being the Visual Studio
+default, and also except Axantum.AxCrypt.Mac which only supports x86.
+
+Typical combinations used:
+
+Debug|Mixed Platforms   - Development on Windows
+Release|Mixed Platforms - Testing release-builds on Windows (not actual production builds)
+Release|Any CPU         - Deployable release builds for desktop Mono (Windows, Linux and Mac OS X)
+DebugAndroid|Any CPU    - Development for Android
+ReleaseAndroid|Any CPU  - Release builds for Android
+Debug|x86               - Development for Mac OS X
+Release|x86             - Testing release-buidls for Mac OS X
+AppStore|x86            - Deployable release builds for Mac OS X
+
+Build combinations from a development scenario:
+
+Mono Desktop on Windows - Debug|Mixed Platforms
+Android on Windows      - DebugAndroid|Any CPU
diff --git a/SolutionItems/ILMerge.exe b/SolutionItems/ILMerge.exe
new file mode 100644
index 0000000..9667425
Binary files /dev/null and b/SolutionItems/ILMerge.exe differ
diff --git a/SolutionItems/MSBuild.Axantum.Tasks.dll b/SolutionItems/MSBuild.Axantum.Tasks.dll
new file mode 100644
index 0000000..e74f131
Binary files /dev/null and b/SolutionItems/MSBuild.Axantum.Tasks.dll differ
diff --git a/SolutionItems/MSBuildVersioning.dll b/SolutionItems/MSBuildVersioning.dll
new file mode 100644
index 0000000..da44189
Binary files /dev/null and b/SolutionItems/MSBuildVersioning.dll differ
diff --git a/SolutionItems/Moq/lib/net35/Moq.dll b/SolutionItems/Moq/lib/net35/Moq.dll
new file mode 100644
index 0000000..6988463
Binary files /dev/null and b/SolutionItems/Moq/lib/net35/Moq.dll differ
diff --git a/SolutionItems/Moq/lib/net35/Moq.xml b/SolutionItems/Moq/lib/net35/Moq.xml
new file mode 100644
index 0000000..3b8205d
--- /dev/null
+++ b/SolutionItems/Moq/lib/net35/Moq.xml
@@ -0,0 +1,6034 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>Moq</name>
+    </assembly>
+    <members>
+        <member name="T:Moq.Language.ISetupConditionResult`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.Setup(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+            The expectation will be considered only in the former condition.
+            </summary>
+            <param name="expression"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.Setup``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            The expectation will be considered only in the former condition.
+            </summary>
+            <typeparam name="TResult"></typeparam>
+            <param name="expression"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Setups the get.
+            </summary>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+            <param name="expression">The expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupSet``1(System.Action{`0})">
+            <summary>
+            Setups the set.
+            </summary>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+            <param name="setterExpression">The setter expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupSet(System.Action{`0})">
+            <summary>
+            Setups the set.
+            </summary>
+            <param name="setterExpression">The setter expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.IInterceptStrategy.HandleIntercept(Moq.Proxy.ICallContext,Moq.InterceptStrategyContext)">
+            <summary>
+            Handle interception
+            </summary>
+            <param name="invocation">the current invocation context</param>
+            <param name="ctx">shared data among the strategies during an interception</param>
+            <returns>true if further interception has to be processed, otherwise false</returns>
+        </member>
+        <member name="T:Moq.IMock`1">
+            <summary>
+            Covarient interface for Mock<T> such that casts between IMock<Employee> to IMock<Person>
+            are possible. Only covers the covariant members of Mock<T>.
+            </summary>
+        </member>
+        <member name="P:Moq.IMock`1.Object">
+            <summary>
+			Exposes the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.Behavior">
+            <summary>
+			Behavior of the mock, according to the value set in the constructor.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.CallBase">
+            <summary>
+			Whether the base member virtual implementation will be called
+			for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.DefaultValue">
+            <summary>
+			Specifies the behavior to use when returning default values for
+			unexpected invocations on loose mocks.
+		</summary>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetEventFromName(System.String)">
+            <summary>
+            Get an eventInfo for a given event name.  Search type ancestors depth first if necessary.
+            </summary>
+            <param name="eventName">Name of the event, with the set_ or get_ prefix already removed</param>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetNonPublicEventFromName(System.String)">
+            <summary>
+            Get an eventInfo for a given event name.  Search type ancestors depth first if necessary.
+            Searches also in non public events.
+            </summary>
+            <param name="eventName">Name of the event, with the set_ or get_ prefix already removed</param>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetAncestorTypes(System.Type)">
+            <summary>
+            Given a type return all of its ancestors, both types and interfaces.
+            </summary>
+            <param name="initialType">The type to find immediate ancestors of</param>
+        </member>
+        <member name="T:Moq.Language.ICallback">
+            <summary>
+            Defines the <c>Callback</c> verb and overloads.
+            </summary>
+        </member>
+        <member name="T:Moq.IHideObjectMembers">
+            <summary>
+            Helper interface used to hide the base <see cref="T:System.Object"/> 
+            members from the fluent API to make it much cleaner 
+            in Visual Studio intellisense.
+            </summary>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.GetType">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.GetHashCode">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.ToString">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.Equals(System.Object)">
+            <summary/>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the method is called.
+            </summary>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            The following example specifies a callback to set a boolean 
+            value that can be used later:
+            <code>
+            var called = false;
+            mock.Setup(x => x.Execute())
+                .Callback(() => called = true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``1(System.Action{``0})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T">The argument type of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the concrete invocation argument value. 
+            <para>
+            Notice how the specific string argument is retrieved by simply declaring 
+            it as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Callback((string command) => Console.WriteLine(command));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``2(System.Action{``0,``1})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2) => Console.WriteLine(arg1 + arg2));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``3(System.Action{``0,``1,``2})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3) => Console.WriteLine(arg1 + arg2 + arg3));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``4(System.Action{``0,``1,``2,``3})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``5(System.Action{``0,``1,``2,``3,``4})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``6(System.Action{``0,``1,``2,``3,``4,``5})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``7(System.Action{``0,``1,``2,``3,``4,``5,``6})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``8(System.Action{``0,``1,``2,``3,``4,``5,``6,``7})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``9(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``10(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``11(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``12(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``13(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``14(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``15(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``16(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15, string arg16) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.ICallback`2">
+            <summary>
+            Defines the <c>Callback</c> verb and overloads for callbacks on
+            setups that return a value.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TResult">Type of the return value of the setup.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the method is called.
+            </summary>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            The following example specifies a callback to set a boolean value that can be used later:
+            <code>
+            var called = false;
+            mock.Setup(x => x.Execute())
+                .Callback(() => called = true)
+                .Returns(true);
+            </code>
+            Note that in the case of value-returning methods, after the <c>Callback</c>
+            call you can still specify the return value.
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``1(System.Action{``0})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T">The type of the argument of the invoked method.</typeparam>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the concrete invocation argument value.
+            <para>
+            Notice how the specific string argument is retrieved by simply declaring
+            it as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Callback(command => Console.WriteLine(command))
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``2(System.Action{``0,``1})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2) => Console.WriteLine(arg1 + arg2));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``3(System.Action{``0,``1,``2})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3) => Console.WriteLine(arg1 + arg2 + arg3));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``4(System.Action{``0,``1,``2,``3})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``5(System.Action{``0,``1,``2,``3,``4})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``6(System.Action{``0,``1,``2,``3,``4,``5})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``7(System.Action{``0,``1,``2,``3,``4,``5,``6})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``8(System.Action{``0,``1,``2,``3,``4,``5,``6,``7})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``9(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``10(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``11(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``12(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``13(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``14(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``15(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``16(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.IRaise`1">
+            <summary>
+            Defines the <c>Raises</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)">
+            <summary>
+            Specifies the event that will be raised 
+            when the setup is met.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="args">The event arguments to pass for the raised event.</param>
+            <example>
+            The following example shows how to raise an event when 
+            the setup is met:
+            <code>
+            var mock = new Mock<IContainer>();
+            
+            mock.Setup(add => add.Add(It.IsAny<string>(), It.IsAny<object>()))
+                .Raises(add => add.Added += null, EventArgs.Empty);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.Func{System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised 
+            when the setup is matched.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="func">A function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.Object[])">
+            <summary>
+            Specifies the custom event that will be raised 
+            when the setup is matched.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="args">The arguments to pass to the custom delegate (non EventHandler-compatible).</param>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``1(System.Action{`0},System.Func{``0,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``2(System.Action{`0},System.Func{``0,``1,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``3(System.Action{`0},System.Func{``0,``1,``2,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``4(System.Action{`0},System.Func{``0,``1,``2,``3,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``5(System.Action{`0},System.Func{``0,``1,``2,``3,``4,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``6(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``7(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``8(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``9(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``10(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``11(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``12(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``13(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``14(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``15(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``16(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="T:Moq.Language.IReturns`2">
+            <summary>
+            Defines the <c>Returns</c> verb.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TResult">Type of the return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns(`1)">
+            <summary>
+            Specifies the value to return.
+            </summary>
+            <param name="value">The value to return, or <see langword="null"/>.</param>
+            <example>
+            Return a <c>true</c> value from the method call:
+            <code>
+            mock.Setup(x => x.Execute("ping"))
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns(System.Func{`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method.
+            </summary>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example group="returns">
+            Return a calculated value when the method is called:
+            <code>
+            mock.Setup(x => x.Execute("ping"))
+                .Returns(() => returnValues[0]);
+            </code>
+            The lambda expression to retrieve the return value is lazy-executed, 
+            meaning that its value may change depending on the moment the method 
+            is executed and the value the <c>returnValues</c> array has at 
+            that moment.
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``1(System.Func{``0,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T">The type of the argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example group="returns">
+            Return a calculated value which is evaluated lazily at the time of the invocation.
+            <para>
+            The lookup list can change between invocations and the setup 
+            will return different values accordingly. Also, notice how the specific 
+            string argument is retrieved by simply declaring it as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Returns((string command) => returnValues[command]);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.CallBase">
+            <summary>
+            Calls the real method of the object and returns its return value.
+            </summary>
+            <returns>The value calculated by the real method of the object.</returns>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``2(System.Func{``0,``1,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2) => arg1 + arg2);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``3(System.Func{``0,``1,``2,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3) => arg1 + arg2 + arg3);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``4(System.Func{``0,``1,``2,``3,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4) => arg1 + arg2 + arg3 + arg4);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``5(System.Func{``0,``1,``2,``3,``4,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5) => arg1 + arg2 + arg3 + arg4 + arg5);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``6(System.Func{``0,``1,``2,``3,``4,``5,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``7(System.Func{``0,``1,``2,``3,``4,``5,``6,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``8(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``9(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``10(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``11(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``12(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``13(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``14(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``15(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``16(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15, string arg16) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.ISetupSequentialResult`1">
+            <summary>
+            Language for ReturnSequence
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Returns(`0)">
+            <summary>
+            Returns value
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Throws(System.Exception)">
+            <summary>
+            Throws an exception
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Throws``1">
+            <summary>
+            Throws an exception
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.CallBase">
+            <summary>
+            Calls original method
+            </summary>
+        </member>
+        <member name="F:Moq.Linq.FluentMockVisitor.isFirst">
+            <summary>
+            The first method call or member access will be the 
+            last segment of the expression (depth-first traversal), 
+            which is the one we have to Setup rather than FluentMock.
+            And the last one is the one we have to Mock.Get rather 
+            than FluentMock.
+            </summary>
+        </member>
+        <member name="T:Moq.Mock">
+            <summary>
+			Base class for mocks and static helper class with methods that
+			apply to mocked objects, such as <see cref="M:Moq.Mock.Get``1(``0)"/> to
+			retrieve a <see cref="T:Moq.Mock`1"/> from an object instance.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Of``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mock.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="predicate">The predicate with the specification of how the mocked object should behave.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mock.#ctor">
+            <summary>
+			Initializes a new instance of the <see cref="T:Moq.Mock"/> class.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Get``1(``0)">
+            <summary>
+			Retrieves the mock object for the given object instance.
+		</summary><typeparam name="T">
+			Type of the mock to retrieve. Can be omitted as it's inferred
+			from the object instance passed in as the <paramref name="mocked"/> instance.
+		</typeparam><param name="mocked">The instance of the mocked object.</param><returns>The mock associated with the mocked object.</returns><exception cref="T:System.ArgumentException">
+			The received <paramref name="mocked"/> instance
+			was not created by Moq.
+		</exception><example group="advanced">
+			The following example shows how to add a new setup to an object
+			instance which is not the original <see cref="T:Moq.Mock`1"/> but rather
+			the object associated with it:
+			<code>
+				// Typed instance, not the mock, is retrieved from some test API.
+				HttpContextBase context = GetMockContext();
+
+				// context.Request is the typed object from the "real" API
+				// so in order to add a setup to it, we need to get
+				// the mock that "owns" it
+				Mock<HttpRequestBase> request = Mock.Get(context.Request);
+				mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
+					 .Returns(tempUrl);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock.OnGetObject">
+            <summary>
+			Returns the mocked object value.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Verify">
+            <summary>
+			Verifies that all verifiable expectations have been met.
+		</summary><example group="verification">
+			This example sets up an expectation and marks it as verifiable. After
+			the mock is used, a <c>Verify()</c> call is issued on the mock
+			to ensure the method in the setup was invoked:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				this.Setup(x => x.HasInventory(TALISKER, 50)).Verifiable().Returns(true);
+				...
+				// other test code
+				...
+				// Will throw if the test code has didn't call HasInventory.
+				this.Verify();
+			</code>
+		</example><exception cref="T:Moq.MockException">Not all verifiable expectations were met.</exception>
+        </member>
+        <member name="M:Moq.Mock.VerifyAll">
+            <summary>
+			Verifies all expectations regardless of whether they have
+			been flagged as verifiable.
+		</summary><example group="verification">
+			This example sets up an expectation without marking it as verifiable. After
+			the mock is used, a <see cref="M:Moq.Mock.VerifyAll"/> call is issued on the mock
+			to ensure that all expectations are met:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				this.Setup(x => x.HasInventory(TALISKER, 50)).Returns(true);
+				...
+				// other test code
+				...
+				// Will throw if the test code has didn't call HasInventory, even
+				// that expectation was not marked as verifiable.
+				this.VerifyAll();
+			</code>
+		</example><exception cref="T:Moq.MockException">At least one expectation was not met.</exception>        
+        </member>
+        <member name="M:Moq.Mock.GetInterceptor(System.Linq.Expressions.Expression,Moq.Mock)">
+            <summary>
+            Gets the interceptor target for the given expression and root mock, 
+            building the intermediate hierarchy of mock objects if necessary.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.DoRaise(System.Reflection.EventInfo,System.EventArgs)">
+            <summary>
+            Raises the associated event with the given 
+            event argument data.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.DoRaise(System.Reflection.EventInfo,System.Object[])">
+            <summary>
+            Raises the associated event with the given 
+            event argument data.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.As``1">
+            <summary>
+			Adds an interface implementation to the mock,
+			allowing setups to be specified for it.
+		</summary><remarks>
+			This method can only be called before the first use
+			of the mock <see cref="P:Moq.Mock.Object"/> property, at which
+			point the runtime type has already been generated
+			and no more interfaces can be added to it.
+			<para>
+				Also, <typeparamref name="TInterface"/> must be an
+				interface and not a class, which must be specified
+				when creating the mock instead.
+			</para>
+		</remarks><exception cref="T:System.InvalidOperationException">
+			The mock type
+			has already been generated by accessing the <see cref="P:Moq.Mock.Object"/> property.
+		</exception><exception cref="T:System.ArgumentException">
+			The <typeparamref name="TInterface"/> specified
+			is not an interface.
+		</exception><example>
+			The following example creates a mock for the main interface
+			and later adds <see cref="T:System.IDisposable"/> to it to verify
+			it's called by the consumer code:
+			<code>
+				var mock = new Mock<IProcessor>();
+				mock.Setup(x => x.Execute("ping"));
+
+				// add IDisposable interface
+				var disposable = mock.As<IDisposable>();
+				disposable.Setup(d => d.Dispose()).Verifiable();
+			</code>
+		</example><typeparam name="TInterface">Type of interface to cast the mock to.</typeparam>
+        </member>
+        <member name="M:Moq.Mock.SetReturnsDefault``1(``0)">
+            <!-- No matching elements were found for the following include tag --><include file="Mock.Generic.xdoc" path="docs/doc[@for="Mock.SetReturnDefault{TReturn}"]/*"/>
+        </member>
+        <member name="P:Moq.Mock.Behavior">
+            <summary>
+			Behavior of the mock, according to the value set in the constructor.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.CallBase">
+            <summary>
+			Whether the base member virtual implementation will be called
+			for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.DefaultValue">
+            <summary>
+			Specifies the behavior to use when returning default values for
+			unexpected invocations on loose mocks.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.Object">
+            <summary>
+			Gets the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.MockedType">
+            <summary>
+            Retrieves the type of the mocked object, its generic type argument.
+            This is used in the auto-mocking of hierarchy access.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.DelegateInterfaceMethod">
+            <summary>
+            If this is a mock of a delegate, this property contains the method
+            on the autogenerated interface so that we can convert setup + verify
+            expressions on the delegate into expressions on the interface proxy.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.IsDelegateMock">
+            <summary>
+            Allows to check whether expression conversion to the <see cref="P:Moq.Mock.DelegateInterfaceMethod"/> 
+            must be performed on the mock, without causing unnecessarily early initialization of 
+            the mock instance, which breaks As{T}.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.DefaultValueProvider">
+            <summary>
+            Specifies the class that will determine the default 
+            value to return when invocations are made that 
+            have no setups and need to return a default 
+            value (for loose mocks).
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.ImplementedInterfaces">
+            <summary>
+            Exposes the list of extra interfaces implemented by the mock.
+            </summary>
+        </member>
+        <member name="T:Moq.MockRepository">
+            <summary>
+            Utility repository class to use to construct multiple 
+            mocks when consistent verification is 
+            desired for all of them.
+            </summary>
+            <remarks>
+            If multiple mocks will be created during a test, passing 
+            the desired <see cref="T:Moq.MockBehavior"/> (if different than the 
+            <see cref="F:Moq.MockBehavior.Default"/> or the one 
+            passed to the repository constructor) and later verifying each
+            mock can become repetitive and tedious.
+            <para>
+            This repository class helps in that scenario by providing a 
+            simplified creation of multiple mocks with a default 
+            <see cref="T:Moq.MockBehavior"/> (unless overriden by calling 
+            <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/>) and posterior verification.
+            </para>
+            </remarks>
+            <example group="repository">
+            The following is a straightforward example on how to 
+            create and automatically verify strict mocks using a <see cref="T:Moq.MockRepository"/>:
+            <code>
+            var repository = new MockRepository(MockBehavior.Strict);
+            
+            var foo = repository.Create<IFoo>();
+            var bar = repository.Create<IBar>();
+            
+            // no need to call Verifiable() on the setup 
+            // as we'll be validating all of them anyway.
+            foo.Setup(f => f.Do());
+            bar.Setup(b => b.Redo());
+            
+            // exercise the mocks here
+            
+            repository.VerifyAll(); 
+            // At this point all setups are already checked 
+            // and an optional MockException might be thrown. 
+            // Note also that because the mocks are strict, any invocation 
+            // that doesn't have a matching setup will also throw a MockException.
+            </code>
+            The following examples shows how to setup the repository 
+            to create loose mocks and later verify only verifiable setups:
+            <code>
+            var repository = new MockRepository(MockBehavior.Loose);
+            
+            var foo = repository.Create<IFoo>();
+            var bar = repository.Create<IBar>();
+            
+            // this setup will be verified when we verify the repository
+            foo.Setup(f => f.Do()).Verifiable();
+            	
+            // this setup will NOT be verified 
+            foo.Setup(f => f.Calculate());
+            	
+            // this setup will be verified when we verify the repository
+            bar.Setup(b => b.Redo()).Verifiable();
+            
+            // exercise the mocks here
+            // note that because the mocks are Loose, members 
+            // called in the interfaces for which no matching
+            // setups exist will NOT throw exceptions, 
+            // and will rather return default values.
+            
+            repository.Verify();
+            // At this point verifiable setups are already checked 
+            // and an optional MockException might be thrown.
+            </code>
+            The following examples shows how to setup the repository with a 
+            default strict behavior, overriding that default for a 
+            specific mock:
+            <code>
+            var repository = new MockRepository(MockBehavior.Strict);
+            
+            // this particular one we want loose
+            var foo = repository.Create<IFoo>(MockBehavior.Loose);
+            var bar = repository.Create<IBar>();
+            
+            // specify setups
+            
+            // exercise the mocks here
+            
+            repository.Verify();
+            </code>
+            </example>
+            <seealso cref="T:Moq.MockBehavior"/>
+        </member>
+        <member name="T:Moq.MockFactory">
+            <summary>
+            Utility factory class to use to construct multiple 
+            mocks when consistent verification is 
+            desired for all of them.
+            </summary>
+            <remarks>
+            If multiple mocks will be created during a test, passing 
+            the desired <see cref="T:Moq.MockBehavior"/> (if different than the 
+            <see cref="F:Moq.MockBehavior.Default"/> or the one 
+            passed to the factory constructor) and later verifying each
+            mock can become repetitive and tedious.
+            <para>
+            This factory class helps in that scenario by providing a 
+            simplified creation of multiple mocks with a default 
+            <see cref="T:Moq.MockBehavior"/> (unless overriden by calling 
+            <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/>) and posterior verification.
+            </para>
+            </remarks>
+            <example group="factory">
+            The following is a straightforward example on how to 
+            create and automatically verify strict mocks using a <see cref="T:Moq.MockFactory"/>:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>();
+            var bar = factory.Create<IBar>();
+            
+            // no need to call Verifiable() on the setup 
+            // as we'll be validating all of them anyway.
+            foo.Setup(f => f.Do());
+            bar.Setup(b => b.Redo());
+            
+            // exercise the mocks here
+            
+            factory.VerifyAll(); 
+            // At this point all setups are already checked 
+            // and an optional MockException might be thrown. 
+            // Note also that because the mocks are strict, any invocation 
+            // that doesn't have a matching setup will also throw a MockException.
+            </code>
+            The following examples shows how to setup the factory 
+            to create loose mocks and later verify only verifiable setups:
+            <code>
+            var factory = new MockFactory(MockBehavior.Loose);
+            
+            var foo = factory.Create<IFoo>();
+            var bar = factory.Create<IBar>();
+            
+            // this setup will be verified when we verify the factory
+            foo.Setup(f => f.Do()).Verifiable();
+            	
+            // this setup will NOT be verified 
+            foo.Setup(f => f.Calculate());
+            	
+            // this setup will be verified when we verify the factory
+            bar.Setup(b => b.Redo()).Verifiable();
+            
+            // exercise the mocks here
+            // note that because the mocks are Loose, members 
+            // called in the interfaces for which no matching
+            // setups exist will NOT throw exceptions, 
+            // and will rather return default values.
+            
+            factory.Verify();
+            // At this point verifiable setups are already checked 
+            // and an optional MockException might be thrown.
+            </code>
+            The following examples shows how to setup the factory with a 
+            default strict behavior, overriding that default for a 
+            specific mock:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            // this particular one we want loose
+            var foo = factory.Create<IFoo>(MockBehavior.Loose);
+            var bar = factory.Create<IBar>();
+            
+            // specify setups
+            
+            // exercise the mocks here
+            
+            factory.Verify();
+            </code>
+            </example>
+            <seealso cref="T:Moq.MockBehavior"/>
+        </member>
+        <member name="M:Moq.MockFactory.#ctor(Moq.MockBehavior)">
+            <summary>
+            Initializes the factory with the given <paramref name="defaultBehavior"/> 
+            for newly created mocks from the factory.
+            </summary>
+            <param name="defaultBehavior">The behavior to use for mocks created 
+            using the <see cref="M:Moq.MockFactory.Create``1"/> factory method if not overriden 
+            by using the <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/> overload.</param>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1">
+            <summary>
+            Creates a new mock with the default <see cref="T:Moq.MockBehavior"/> 
+            specified at factory construction time.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example ignore="true">
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>();
+            // use mock on tests
+            
+            factory.VerifyAll();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(System.Object[])">
+            <summary>
+            Creates a new mock with the default <see cref="T:Moq.MockBehavior"/> 
+            specified at factory construction time and with the 
+            the given constructor arguments for the class.
+            </summary>
+            <remarks>
+            The mock will try to find the best match constructor given the 
+            constructor arguments, and invoke that to initialize the instance. 
+            This applies only to classes, not interfaces.
+            </remarks>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="args">Constructor arguments for mocked classes.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example ignore="true">
+            <code>
+            var factory = new MockFactory(MockBehavior.Default);
+            
+            var mock = factory.Create<MyBase>("Foo", 25, true);
+            // use mock on tests
+            
+            factory.Verify();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(Moq.MockBehavior)">
+            <summary>
+            Creates a new mock with the given <paramref name="behavior"/>.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">Behavior to use for the mock, which overrides 
+            the default behavior specified at factory construction time.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example group="factory">
+            The following example shows how to create a mock with a different 
+            behavior to that specified as the default for the factory:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>(MockBehavior.Loose);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(Moq.MockBehavior,System.Object[])">
+            <summary>
+            Creates a new mock with the given <paramref name="behavior"/> 
+            and with the the given constructor arguments for the class.
+            </summary>
+            <remarks>
+            The mock will try to find the best match constructor given the 
+            constructor arguments, and invoke that to initialize the instance. 
+            This applies only to classes, not interfaces.
+            </remarks>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">Behavior to use for the mock, which overrides 
+            the default behavior specified at factory construction time.</param>
+            <param name="args">Constructor arguments for mocked classes.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example group="factory">
+            The following example shows how to create a mock with a different 
+            behavior to that specified as the default for the factory, passing 
+            constructor arguments:
+            <code>
+            var factory = new MockFactory(MockBehavior.Default);
+            
+            var mock = factory.Create<MyBase>(MockBehavior.Strict, "Foo", 25, true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.CreateMock``1(Moq.MockBehavior,System.Object[])">
+            <summary>
+            Implements creation of a new mock within the factory.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">The behavior for the new mock.</param>
+            <param name="args">Optional arguments for the construction of the mock.</param>
+        </member>
+        <member name="M:Moq.MockFactory.Verify">
+            <summary>
+            Verifies all verifiable expectations on all mocks created 
+            by this factory.
+            </summary>
+            <seealso cref="M:Moq.Mock.Verify"/>
+            <exception cref="T:Moq.MockException">One or more mocks had expectations that were not satisfied.</exception>
+        </member>
+        <member name="M:Moq.MockFactory.VerifyAll">
+            <summary>
+            Verifies all verifiable expectations on all mocks created 
+            by this factory.
+            </summary>
+            <seealso cref="M:Moq.Mock.Verify"/>
+            <exception cref="T:Moq.MockException">One or more mocks had expectations that were not satisfied.</exception>
+        </member>
+        <member name="M:Moq.MockFactory.VerifyMocks(System.Action{Moq.Mock})">
+            <summary>
+            Invokes <paramref name="verifyAction"/> for each mock 
+            in <see cref="P:Moq.MockFactory.Mocks"/>, and accumulates the resulting 
+            <see cref="T:Moq.MockVerificationException"/> that might be 
+            thrown from the action.
+            </summary>
+            <param name="verifyAction">The action to execute against 
+            each mock.</param>
+        </member>
+        <member name="P:Moq.MockFactory.CallBase">
+            <summary>
+            Whether the base member virtual implementation will be called 
+            for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+            </summary>
+        </member>
+        <member name="P:Moq.MockFactory.DefaultValue">
+            <summary>
+            Specifies the behavior to use when returning default values for 
+            unexpected invocations on loose mocks.
+            </summary>
+        </member>
+        <member name="P:Moq.MockFactory.Mocks">
+            <summary>
+            Gets the mocks that have been created by this factory and 
+            that will get verified together.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.Of``1">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.MockRepository.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.MockRepository.OneOf``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.MockRepository.OneOf``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.MockRepository.CreateMockQuery``1">
+            <summary>
+            Creates the mock query with the underlying queriable implementation.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.CreateQueryable``1">
+            <summary>
+            Wraps the enumerator inside a queryable.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.CreateMocks``1">
+            <summary>
+            Method that is turned into the actual call from .Query{T}, to 
+            transform the queryable query into a normal enumerable query.
+            This method is never used directly by consumers.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.#ctor(Moq.MockBehavior)">
+            <summary>
+            Initializes the repository with the given <paramref name="defaultBehavior"/> 
+            for newly created mocks from the repository.
+            </summary>
+            <param name="defaultBehavior">The behavior to use for mocks created 
+            using the <see cref="M:Moq.MockFactory.Create``1"/> repository method if not overriden 
+            by using the <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/> overload.</param>
+        </member>
+        <member name="T:Moq.EmptyDefaultValueProvider">
+            <summary>
+            A <see cref="T:Moq.IDefaultValueProvider"/> that returns an empty default value 
+            for invocations that do not have setups or return values, with loose mocks.
+            This is the default behavior for a mock.
+            </summary>
+        </member>
+        <member name="T:Moq.IDefaultValueProvider">
+            <summary>
+			Interface to be implemented by classes that determine the
+			default value of non-expected invocations.
+		</summary>
+        </member>
+        <member name="M:Moq.IDefaultValueProvider.DefineDefault``1(``0)">
+            <summary>
+			Defines the default value to return in all the methods returning <typeparamref name="T"/>.
+		</summary><typeparam name="T">The type of the return value.</typeparam><param name="value">The value to set as default.</param>
+        </member>
+        <member name="M:Moq.IDefaultValueProvider.ProvideDefault(System.Reflection.MethodInfo)">
+            <summary>
+			Provides a value for the given member and arguments.
+		</summary><param name="member">
+			The member to provide a default	value for.
+		</param>
+        </member>
+        <member name="T:Moq.ExpressionStringBuilder">
+            <summary>
+            The intention of <see cref="T:Moq.ExpressionStringBuilder"/> is to create a more readable 
+            string representation for the failure message.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ICallbackResult">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IThrows">
+            <summary>
+            Defines the <c>Throws</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IThrows.Throws(System.Exception)">
+            <summary>
+            Specifies the exception to throw when the method is invoked.
+            </summary>
+            <param name="exception">Exception instance to throw.</param>
+            <example>
+            This example shows how to throw an exception when the method is 
+            invoked with an empty string argument:
+            <code>
+            mock.Setup(x => x.Execute(""))
+                .Throws(new ArgumentException());
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IThrows.Throws``1">
+            <summary>
+            Specifies the type of exception to throw when the method is invoked.
+            </summary>
+            <typeparam name="TException">Type of exception to instantiate and throw when the setup is matched.</typeparam>
+            <example>
+            This example shows how to throw an exception when the method is 
+            invoked with an empty string argument:
+            <code>
+            mock.Setup(x => x.Execute(""))
+                .Throws<ArgumentException>();
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.IThrowsResult">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IOccurrence">
+            <summary>
+            Defines occurrence members to constraint setups.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IOccurrence.AtMostOnce">
+            <summary>
+            The expected invocation can happen at most once.
+            </summary>
+            <example>
+            <code>
+            var mock = new Mock<ICommand>();
+            mock.Setup(foo => foo.Execute("ping"))
+                .AtMostOnce();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IOccurrence.AtMost(System.Int32)">
+            <summary>
+            The expected invocation can happen at most specified number of times.
+            </summary>
+            <param name="callCount">The number of times to accept calls.</param>
+            <example>
+            <code>
+            var mock = new Mock<ICommand>();
+            mock.Setup(foo => foo.Execute("ping"))
+                .AtMost( 5 );
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.IVerifies">
+            <summary>
+            Defines the <c>Verifiable</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IVerifies.Verifiable">
+            <summary>
+            Marks the expectation as verifiable, meaning that a call 
+            to <see cref="M:Moq.Mock.Verify"/> will check if this particular 
+            expectation was met.
+            </summary>
+            <example>
+            The following example marks the expectation as verifiable:
+            <code>
+            mock.Expect(x => x.Execute("ping"))
+                .Returns(true)
+                .Verifiable();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IVerifies.Verifiable(System.String)">
+            <summary>
+            Marks the expectation as verifiable, meaning that a call 
+            to <see cref="M:Moq.Mock.Verify"/> will check if this particular 
+            expectation was met, and specifies a message for failures.
+            </summary>
+            <example>
+            The following example marks the expectation as verifiable:
+            <code>
+            mock.Expect(x => x.Execute("ping"))
+                .Returns(true)
+                .Verifiable("Ping should be executed always!");
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetup`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.MethodCallReturn">
+            <devdoc>
+            We need this non-generics base class so that 
+            we can use <see cref="P:Moq.MethodCallReturn.HasReturnValue"/> from 
+            generic code.
+            </devdoc>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetup`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsThrows`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetupGetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.ICallbackGetter`2">
+            <summary>
+            Defines the <c>Callback</c> verb for property getter setups.
+            </summary>
+            <seealso cref="M:Moq.Mock`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})"/>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallbackGetter`2.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the property is retrieved.
+            </summary>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the property value being set. 
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Callback(() => called = true)
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsThrowsGetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IReturnsGetter`2">
+            <summary>
+            Defines the <c>Returns</c> verb for property get setups.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.Returns(`1)">
+            <summary>
+            Specifies the value to return.
+            </summary>
+            <param name="value">The value to return, or <see langword="null"/>.</param>
+            <example>
+            Return a <c>true</c> value from the property getter call:
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.Returns(System.Func{`1})">
+            <summary>
+            Specifies a function that will calculate the value to return for the property.
+            </summary>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example>
+            Return a calculated value when the property is retrieved:
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Returns(() => returnValues[0]);
+            </code>
+            The lambda expression to retrieve the return value is lazy-executed, 
+            meaning that its value may change depending on the moment the property  
+            is retrieved and the value the <c>returnValues</c> array has at 
+            that moment.
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.CallBase">
+            <summary>
+            Calls the real property of the object and returns its return value.
+            </summary>
+            <returns>The value calculated by the real property of the object.</returns>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsResult`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:System.Action`5">
+            <summary>
+            Encapsulates a method that has five parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`6">
+            <summary>
+            Encapsulates a method that has five parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`6">
+            <summary>
+            Encapsulates a method that has six parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`7">
+            <summary>
+            Encapsulates a method that has six parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`7">
+            <summary>
+            Encapsulates a method that has seven parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`8">
+            <summary>
+            Encapsulates a method that has seven parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`8">
+            <summary>
+            Encapsulates a method that has eight parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`9">
+            <summary>
+            Encapsulates a method that has eight parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`9">
+            <summary>
+            Encapsulates a method that has nine parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`10">
+            <summary>
+            Encapsulates a method that has nine parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`10">
+            <summary>
+            Encapsulates a method that has ten parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`11">
+            <summary>
+            Encapsulates a method that has ten parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`11">
+            <summary>
+            Encapsulates a method that has eleven parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`12">
+            <summary>
+            Encapsulates a method that has eleven parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`12">
+            <summary>
+            Encapsulates a method that has twelve parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`13">
+            <summary>
+            Encapsulates a method that has twelve parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`13">
+            <summary>
+            Encapsulates a method that has thirteen parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`14">
+            <summary>
+            Encapsulates a method that has thirteen parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`14">
+            <summary>
+            Encapsulates a method that has fourteen parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`15">
+            <summary>
+            Encapsulates a method that has fourteen parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`15">
+            <summary>
+            Encapsulates a method that has fifteen parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`16">
+            <summary>
+            Encapsulates a method that has fifteen parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:System.Action`16">
+            <summary>
+            Encapsulates a method that has sixteen parameters and does not return a value.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+        </member>
+        <member name="T:System.Func`17">
+            <summary>
+            Encapsulates a method that has sixteen parameters and returns a value of the type specified by the <typeparamref name="TResult" /> parameter.
+            </summary>
+            <typeparam name="T1">The type of the first parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T2">The type of the second parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T3">The type of the third parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T4">The type of the fourth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T5">The type of the fifth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T6">The type of the sixth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T7">The type of the seventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T8">The type of the eighth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T9">The type of the nineth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T10">The type of the tenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T11">The type of the eleventh parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T12">The type of the twelfth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T13">The type of the thirteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T14">The type of the fourteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T15">The type of the fifteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="T16">The type of the sixteenth parameter of the method that this delegate encapsulates.</typeparam>
+            <typeparam name="TResult">The type of the return value of the method that this delegate encapsulates.</typeparam>
+            <param name="arg1">The first parameter of the method that this delegate encapsulates.</param>
+            <param name="arg2">The second parameter of the method that this delegate encapsulates.</param>
+            <param name="arg3">The third parameter of the method that this delegate encapsulates.</param>
+            <param name="arg4">The fourth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg5">The fifth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg6">The sixth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg7">The seventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg8">The eighth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg9">The nineth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg10">The tenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg11">The eleventh parameter of the method that this delegate encapsulates.</param>
+            <param name="arg12">The twelfth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg13">The thirteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg14">The fourteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg15">The fifteenth parameter of the method that this delegate encapsulates.</param>
+            <param name="arg16">The sixteenth parameter of the method that this delegate encapsulates.</param>
+            <return>The return value of the method that this delegate encapsulates.</return>
+        </member>
+        <member name="T:Moq.MockExtensions">
+            <summary>
+            Provides additional methods on mocks.
+            </summary>
+            <remarks>
+            Those methods are useful for Testeroids support. 
+            </remarks>
+        </member>
+        <member name="M:Moq.MockExtensions.ResetCalls(Moq.Mock)">
+            <summary>
+            Resets the calls previously made on the specified mock.
+            </summary>
+            <param name="mock">The mock whose calls need to be reset.</param>
+        </member>
+        <member name="T:Moq.MockSequence">
+            <summary>
+            Helper class to setup a full trace between many mocks
+            </summary>
+        </member>
+        <member name="M:Moq.MockSequence.#ctor">
+            <summary>
+            Initialize a trace setup
+            </summary>
+        </member>
+        <member name="P:Moq.MockSequence.Cyclic">
+            <summary>
+            Allow sequence to be repeated
+            </summary>
+        </member>
+        <member name="T:Moq.MockSequenceHelper">
+            <summary>
+            define nice api
+            </summary>
+        </member>
+        <member name="M:Moq.MockSequenceHelper.InSequence``1(Moq.Mock{``0},Moq.MockSequence)">
+            <summary>
+            Perform an expectation in the trace.
+            </summary>
+        </member>
+        <member name="T:Moq.MatcherAttribute">
+            <summary>
+            Marks a method as a matcher, which allows complete replacement 
+            of the built-in <see cref="T:Moq.It"/> class with your own argument 
+            matching rules.
+            </summary>
+            <remarks>
+            <b>This feature has been deprecated in favor of the new 
+            and simpler <see cref="T:Moq.Match`1"/>.
+            </b>
+            <para>
+            The argument matching is used to determine whether a concrete 
+            invocation in the mock matches a given setup. This 
+            matching mechanism is fully extensible. 
+            </para>
+            <para>
+            There are two parts of a matcher: the compiler matcher 
+            and the runtime matcher.
+            <list type="bullet">
+            <item>
+            <term>Compiler matcher</term>
+            <description>Used to satisfy the compiler requirements for the 
+            argument. Needs to be a method optionally receiving any arguments 
+            you might need for the matching, but with a return type that 
+            matches that of the argument. 
+            <para>
+            Let's say I want to match a lists of orders that contains 
+            a particular one. I might create a compiler matcher like the following:
+            </para>
+            <code>
+            public static class Orders
+            {
+              [Matcher]
+              public static IEnumerable<Order> Contains(Order order)
+              {
+                return null;
+              }
+            }
+            </code>
+            Now we can invoke this static method instead of an argument in an 
+            invocation:
+            <code>
+            var order = new Order { ... };
+            var mock = new Mock<IRepository<Order>>();
+            
+            mock.Setup(x => x.Save(Orders.Contains(order)))
+                .Throws<ArgumentException>();
+            </code>
+            Note that the return value from the compiler matcher is irrelevant. 
+            This method will never be called, and is just used to satisfy the 
+            compiler and to signal Moq that this is not a method that we want 
+            to be invoked at runtime.
+            </description>
+            </item>
+            <item>
+            <term>Runtime matcher</term>
+            <description>
+            The runtime matcher is the one that will actually perform evaluation 
+            when the test is run, and is defined by convention to have the 
+            same signature as the compiler matcher, but where the return 
+            value is the first argument to the call, which contains the 
+            object received by the actual invocation at runtime:
+            <code>
+              public static bool Contains(IEnumerable<Order> orders, Order order)
+              {
+                return orders.Contains(order);
+              }
+            </code>
+            At runtime, the mocked method will be invoked with a specific 
+            list of orders. This value will be passed to this runtime 
+            matcher as the first argument, while the second argument is the 
+            one specified in the setup (<c>x.Save(Orders.Contains(order))</c>).
+            <para>
+            The boolean returned determines whether the given argument has been 
+            matched. If all arguments to the expected method are matched, then 
+            the setup matches and is evaluated.
+            </para>
+            </description>
+            </item>
+            </list>
+            </para>
+            Using this extensible infrastructure, you can easily replace the entire 
+            <see cref="T:Moq.It"/> set of matchers with your own. You can also avoid the 
+            typical (and annoying) lengthy expressions that result when you have 
+            multiple arguments that use generics.
+            </remarks>
+            <example>
+            The following is the complete example explained above:
+            <code>
+            public static class Orders
+            {
+              [Matcher]
+              public static IEnumerable<Order> Contains(Order order)
+              {
+                return null;
+              }
+              
+              public static bool Contains(IEnumerable<Order> orders, Order order)
+              {
+                return orders.Contains(order);
+              }
+            }
+            </code>
+            And the concrete test using this matcher:
+            <code>
+            var order = new Order { ... };
+            var mock = new Mock<IRepository<Order>>();
+            
+            mock.Setup(x => x.Save(Orders.Contains(order)))
+                .Throws<ArgumentException>();
+                
+            // use mock, invoke Save, and have the matcher filter.
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Mock`1">
+            <summary>
+			Provides a mock implementation of <typeparamref name="T"/>.
+		</summary><remarks>
+			Any interface type can be used for mocking, but for classes, only abstract and virtual members can be mocked.
+			<para>
+				The behavior of the mock with regards to the setups and the actual calls is determined
+				by the optional <see cref="T:Moq.MockBehavior"/> that can be passed to the <see cref="M:Moq.Mock`1.#ctor(Moq.MockBehavior)"/>
+				constructor.
+			</para>
+		</remarks><typeparam name="T">Type to mock, which can be an interface or a class.</typeparam><example group="overview" order="0">
+			The following example shows establishing setups with specific values
+			for method invocations:
+			<code>
+				// Arrange
+				var order = new Order(TALISKER, 50);
+				var mock = new Mock<IWarehouse>();
+
+				mock.Setup(x => x.HasInventory(TALISKER, 50)).Returns(true);
+
+				// Act
+				order.Fill(mock.Object);
+
+				// Assert
+				Assert.True(order.IsFilled);
+			</code>
+			The following example shows how to use the <see cref="T:Moq.It"/> class
+			to specify conditions for arguments instead of specific values:
+			<code>
+				// Arrange
+				var order = new Order(TALISKER, 50);
+				var mock = new Mock<IWarehouse>();
+
+				// shows how to expect a value within a range
+				mock.Setup(x => x.HasInventory(
+							It.IsAny<string>(),
+							It.IsInRange(0, 100, Range.Inclusive)))
+					 .Returns(false);
+
+				// shows how to throw for unexpected calls.
+				mock.Setup(x => x.Remove(
+							It.IsAny<string>(),
+							It.IsAny<int>()))
+					 .Throws(new InvalidOperationException());
+
+				// Act
+				order.Fill(mock.Object);
+
+				// Assert
+				Assert.False(order.IsFilled);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Expect(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.Expect``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectSet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectSet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},``0)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(System.Boolean)">
+            <summary>
+            Ctor invoked by AsTInterface exclusively.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor">
+            <summary>
+			Initializes an instance of the mock with <see cref="F:Moq.MockBehavior.Default">default behavior</see>.
+		</summary><example>
+			<code>var mock = new Mock<IFormatProvider>();</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(System.Object[])">
+            <summary>
+			Initializes an instance of the mock with <see cref="F:Moq.MockBehavior.Default">default behavior</see> and with
+			the given constructor arguments for the class. (Only valid when <typeparamref name="T"/> is a class)
+		</summary><remarks>
+			The mock will try to find the best match constructor given the constructor arguments, and invoke that
+			to initialize the instance. This applies only for classes, not interfaces.
+		</remarks><example>
+			<code>var mock = new Mock<MyProvider>(someArgument, 25);</code>
+		</example><param name="args">Optional constructor arguments if the mocked type is a class.</param>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(Moq.MockBehavior)">
+            <summary>
+			Initializes an instance of the mock with the specified <see cref="T:Moq.MockBehavior">behavior</see>.
+		</summary><example>
+			<code>var mock = new Mock<IFormatProvider>(MockBehavior.Relaxed);</code>
+		</example><param name="behavior">Behavior of the mock.</param>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(Moq.MockBehavior,System.Object[])">
+            <summary>
+			Initializes an instance of the mock with a specific <see cref="T:Moq.MockBehavior">behavior</see> with
+			the given constructor arguments for the class.
+		</summary><remarks>
+			The mock will try to find the best match constructor given the constructor arguments, and invoke that
+			to initialize the instance. This applies only to classes, not interfaces.
+		</remarks><example>
+			<code>var mock = new Mock<MyProvider>(someArgument, 25);</code>
+		</example><param name="behavior">Behavior of the mock.</param><param name="args">Optional constructor arguments if the mocked type is a class.</param>
+        </member>
+        <member name="M:Moq.Mock`1.OnGetObject">
+            <summary>
+            Returns the mocked object value.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.Setup(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a void method.
+		</summary><remarks>
+			If more than one setup is specified for the same method or property,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="expression">Lambda expression that specifies the expected method invocation.</param><example group="setups">
+			<code>
+				var mock = new Mock<IProcessor>();
+				mock.Setup(x => x.Execute("ping"));
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Setup``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a value returning method.
+		</summary><typeparam name="TResult">Type of the return value. Typically omitted as it can be inferred from the expression.</typeparam><remarks>
+			If more than one setup is specified for the same method or property,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="expression">Lambda expression that specifies the method invocation.</param><example group="setups">
+			<code>
+				mock.Setup(x => x.HasInventory("Talisker", 50)).Returns(true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property getter.
+		</summary><remarks>
+			If more than one setup is set for the same property getter,
+			the latest one wins and is the one that will be executed.
+		</remarks><typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam><param name="expression">Lambda expression that specifies the property getter.</param><example group="setups">
+			<code>
+				mock.SetupGet(x => x.Suspended)
+					 .Returns(true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupSet``1(System.Action{`0})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property setter.
+		</summary><remarks>
+			If more than one setup is set for the same property setter,
+			the latest one wins and is the one that will be executed.
+			<para>
+				This overloads allows the use of a callback already
+				typed for the property type.
+			</para>
+		</remarks><typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam><param name="setterExpression">The Lambda expression that sets a property to a value.</param><example group="setups">
+			<code>
+				mock.SetupSet(x => x.Suspended = true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupSet(System.Action{`0})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property setter.
+		</summary><remarks>
+			If more than one setup is set for the same property setter,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="setterExpression">Lambda expression that sets a property to a value.</param><example group="setups">
+			<code>
+				mock.SetupSet(x => x.Suspended = true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupProperty``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies that the given property should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. (this is also
+			known as "stubbing").
+		</summary><typeparam name="TProperty">
+			Type of the property, inferred from the property
+			expression (does not need to be specified).
+		</typeparam><param name="property">Property expression to stub.</param><example>
+			If you have an interface with an int property <c>Value</c>, you might
+			stub it using the following straightforward call:
+			<code>
+				var mock = new Mock<IHaveValue>();
+				mock.Stub(v => v.Value);
+			</code>
+			After the <c>Stub</c> call has been issued, setting and
+			retrieving the object value will behave as expected:
+			<code>
+				IHaveValue v = mock.Object;
+
+				v.Value = 5;
+				Assert.Equal(5, v.Value);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupProperty``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},``0)">
+            <summary>
+			Specifies that the given property should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. This overload
+			allows setting the initial value for the property. (this is also
+			known as "stubbing").
+		</summary><typeparam name="TProperty">
+			Type of the property, inferred from the property
+			expression (does not need to be specified).
+		</typeparam><param name="property">Property expression to stub.</param><param name="initialValue">Initial value for the property.</param><example>
+			If you have an interface with an int property <c>Value</c>, you might
+			stub it using the following straightforward call:
+			<code>
+				var mock = new Mock<IHaveValue>();
+				mock.SetupProperty(v => v.Value, 5);
+			</code>
+			After the <c>SetupProperty</c> call has been issued, setting and
+			retrieving the object value will behave as expected:
+			<code>
+				IHaveValue v = mock.Object;
+				// Initial value was stored
+				Assert.Equal(5, v.Value);
+
+				// New value set which changes the initial value
+				v.Value = 6;
+				Assert.Equal(6, v.Value);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupAllProperties">
+            <summary>
+			Specifies that the all properties on the mock should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. (this is also
+			known as "stubbing"). The default value for each property will be the
+			one generated as specified by the <see cref="P:Moq.Mock.DefaultValue"/> property for the mock.
+		</summary><remarks>
+			If the mock <see cref="P:Moq.Mock.DefaultValue"/> is set to <see cref="F:Moq.DefaultValue.Mock"/>,
+			the mocked default values will also get all properties setup recursively.
+		</remarks>
+        </member>
+        <member name="M:Moq.Mock`1.When(System.Func{System.Boolean})">
+            <!-- No matching elements were found for the following include tag --><include file="Mock.Generic.xdoc" path="docs/doc[@for="Mock{T}.When"]/*"/>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IProcessor>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call Execute with a "ping" string argument.
+				mock.Verify(proc => proc.Execute("ping"));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},Moq.Times)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IProcessor>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call Execute with a "ping" string argument.
+				mock.Verify(proc => proc.Execute("ping"));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call HasInventory.
+				mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock. Use in conjuntion
+			with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock. Use in conjuntion
+			with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock, specifying a failure
+			error message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given invocation
+			with specific parameters was performed:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call HasInventory.
+				mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50), "When filling orders, inventory has to be checked");
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was retrieved from it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't retrieve the IsClosed property.
+				mock.VerifyGet(warehouse => warehouse.IsClosed);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times)">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was retrieved from it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't retrieve the IsClosed property.
+				mock.VerifyGet(warehouse => warehouse.IsClosed);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0})">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was set on it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't set the IsClosed property.
+				mock.VerifySet(warehouse => warehouse.IsClosed = true);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},Moq.Times)">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was set on it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't set the IsClosed property.
+				mock.VerifySet(warehouse => warehouse.IsClosed = true, "Warehouse should always be closed after the action");
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},Moq.Times,System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Raise(System.Action{`0},System.EventArgs)">
+            <summary>
+			Raises the event referenced in <paramref name="eventExpression"/> using
+			the given <paramref name="args"/> argument.
+		</summary><exception cref="T:System.ArgumentException">
+			The <paramref name="args"/> argument is
+			invalid for the target event invocation, or the <paramref name="eventExpression"/> is
+			not an event attach or detach expression.
+		</exception><example>
+			The following example shows how to raise a <see cref="E:System.ComponentModel.INotifyPropertyChanged.PropertyChanged"/> event:
+			<code>
+				var mock = new Mock<IViewModel>();
+
+				mock.Raise(x => x.PropertyChanged -= null, new PropertyChangedEventArgs("Name"));
+			</code>
+		</example><example>
+			This example shows how to invoke an event with a custom event arguments
+			class in a view that will cause its corresponding presenter to
+			react by changing its state:
+			<code>
+				var mockView = new Mock<IOrdersView>();
+				var presenter = new OrdersPresenter(mockView.Object);
+
+				// Check that the presenter has no selection by default
+				Assert.Null(presenter.SelectedOrder);
+
+				// Raise the event with a specific arguments data
+				mockView.Raise(v => v.SelectionChanged += null, new OrderEventArgs { Order = new Order("moq", 500) });
+
+				// Now the presenter reacted to the event, and we have a selected order
+				Assert.NotNull(presenter.SelectedOrder);
+				Assert.Equal("moq", presenter.SelectedOrder.ProductName);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Raise(System.Action{`0},System.Object[])">
+            <summary>
+			Raises the event referenced in <paramref name="eventExpression"/> using
+			the given <paramref name="args"/> argument for a non-EventHandler typed event.
+		</summary><exception cref="T:System.ArgumentException">
+			The <paramref name="args"/> arguments are
+			invalid for the target event invocation, or the <paramref name="eventExpression"/> is
+			not an event attach or detach expression.
+		</exception><example>
+			The following example shows how to raise a custom event that does not adhere to 
+			the standard <c>EventHandler</c>:
+			<code>
+				var mock = new Mock<IViewModel>();
+
+				mock.Raise(x => x.MyEvent -= null, "Name", bool, 25);
+			</code>
+		</example>
+        </member>
+        <member name="P:Moq.Mock`1.Object">
+            <summary>
+			Exposes the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock`1.DelegateInterfaceMethod">
+            <inheritdoc />
+        </member>
+        <member name="T:Moq.MockLegacyExtensions">
+            <summary>
+            Provides legacy API members as extensions so that 
+            existing code continues to compile, but new code 
+            doesn't see then.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.SetupSet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1,System.String)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="T:Moq.ObsoleteMockExtensions">
+            <summary>
+            Provides additional methods on mocks.
+            </summary>
+            <devdoc>
+            Provided as extension methods as they confuse the compiler 
+            with the overloads taking Action.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.SetupSet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Specifies a setup on the mocked type for a call to 
+            to a property setter, regardless of its value.
+            </summary>
+            <remarks>
+            If more than one setup is set for the same property setter, 
+            the latest one wins and is the one that will be executed.
+            </remarks>
+            <typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam>
+            <typeparam name="T">Type of the mock.</typeparam>
+            <param name="mock">The target mock for the setup.</param>
+            <param name="expression">Lambda expression that specifies the property setter.</param>
+            <example group="setups">
+            <code>
+            mock.SetupSet(x => x.Suspended);
+            </code>
+            </example>
+            <devdoc>
+            This method is not legacy, but must be on an extension method to avoid 
+            confusing the compiler with the new Action syntax.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Verifies that a property has been set on the mock, regarless of its value.
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <param name="expression">Expression to verify.</param>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.String)">
+            <summary>
+            Verifies that a property has been set on the mock, specifying a failure  
+            error message. 
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <param name="expression">Expression to verify.</param>
+            <param name="failMessage">Message to show if verification fails.</param>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},Moq.Times)">
+            <summary>
+            Verifies that a property has been set on the mock, regardless 
+            of the value but only the specified number of times.
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="expression">Expression to verify.</param>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},Moq.Times,System.String)">
+            <summary>
+            Verifies that a property has been set on the mock, regardless 
+            of the value but only the specified number of times, and specifying a failure  
+            error message. 
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="failMessage">Message to show if verification fails.</param>
+            <param name="expression">Expression to verify.</param>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="T:Moq.SequenceExtensions">
+            <summary>
+            Helper for sequencing return values in the same method.
+            </summary>
+        </member>
+        <member name="M:Moq.SequenceExtensions.SetupSequence``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Return a sequence of values, once per call.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToLambda(System.Linq.Expressions.Expression)">
+            <summary>
+            Casts the expression to a lambda expression, removing 
+            a cast if there's any.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToMethodCall(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Casts the body of the lambda expression to a <see cref="T:System.Linq.Expressions.MethodCallExpression"/>.
+            </summary>
+            <exception cref="T:System.ArgumentException">If the body is not a method call.</exception>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToPropertyInfo(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Converts the body of the lambda expression into the <see cref="T:System.Reflection.PropertyInfo"/> referenced by it.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsProperty(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Checks whether the body of the lambda expression is a property access.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsProperty(System.Linq.Expressions.Expression)">
+            <summary>
+            Checks whether the expression is a property access.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsPropertyIndexer(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Checks whether the body of the lambda expression is a property indexer, which is true 
+            when the expression is an <see cref="T:System.Linq.Expressions.MethodCallExpression"/> whose 
+            <see cref="P:System.Linq.Expressions.MethodCallExpression.Method"/> has <see cref="P:System.Reflection.MethodBase.IsSpecialName"/> 
+            equal to <see langword="true"/>.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsPropertyIndexer(System.Linq.Expressions.Expression)">
+            <summary>
+            Checks whether the expression is a property indexer, which is true 
+            when the expression is an <see cref="T:System.Linq.Expressions.MethodCallExpression"/> whose 
+            <see cref="P:System.Linq.Expressions.MethodCallExpression.Method"/> has <see cref="P:System.Reflection.MethodBase.IsSpecialName"/> 
+            equal to <see langword="true"/>.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.CastTo``1(System.Linq.Expressions.Expression)">
+            <summary>
+            Creates an expression that casts the given expression to the <typeparamref name="T"/> 
+            type.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToStringFixed(System.Linq.Expressions.Expression)">
+            <devdoc>
+            TODO: remove this code when https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=331583 
+            is fixed.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.GetCallInfo(System.Linq.Expressions.LambdaExpression,Moq.Mock)">
+            <summary>
+            Extracts, into a common form, information from a <see cref="T:System.Linq.Expressions.LambdaExpression"/>
+            around either a <see cref="T:System.Linq.Expressions.MethodCallExpression"/> (for a normal method call)
+            or a <see cref="T:System.Linq.Expressions.InvocationExpression"/> (for a delegate invocation).
+            </summary>
+        </member>
+        <member name="M:Moq.Extensions.IsDelegate(System.Type)">
+            <summary>
+            Tests if a type is a delegate type (subclasses <see cref="T:System.Delegate"/>).
+            </summary>
+        </member>
+        <member name="T:Moq.Evaluator">
+            <summary>
+            Provides partial evaluation of subtrees, whenever they can be evaluated locally.
+            </summary>
+            <author>Matt Warren: http://blogs.msdn.com/mattwar</author>
+            <contributor>Documented by InSTEDD: http://www.instedd.org</contributor>
+        </member>
+        <member name="M:Moq.Evaluator.PartialEval(System.Linq.Expressions.Expression,System.Func{System.Linq.Expressions.Expression,System.Boolean})">
+            <summary>
+            Performs evaluation and replacement of independent sub-trees
+            </summary>
+            <param name="expression">The root of the expression tree.</param>
+            <param name="fnCanBeEvaluated">A function that decides whether a given expression
+            node can be part of the local function.</param>
+            <returns>A new tree with sub-trees evaluated and replaced.</returns>
+        </member>
+        <member name="M:Moq.Evaluator.PartialEval(System.Linq.Expressions.Expression)">
+            <summary>
+            Performs evaluation and replacement of independent sub-trees
+            </summary>
+            <param name="expression">The root of the expression tree.</param>
+            <returns>A new tree with sub-trees evaluated and replaced.</returns>
+        </member>
+        <member name="T:Moq.Evaluator.SubtreeEvaluator">
+            <summary>
+            Evaluates and replaces sub-trees when first candidate is reached (top-down)
+            </summary>
+        </member>
+        <member name="T:Moq.Evaluator.Nominator">
+            <summary>
+            Performs bottom-up analysis to determine which nodes can possibly
+            be part of an evaluated sub-tree.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotNull``1(System.Linq.Expressions.Expression{System.Func{``0}},``0)">
+            <summary>
+            Ensures the given <paramref name="value"/> is not null.
+            Throws <see cref="T:System.ArgumentNullException"/> otherwise.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotNullOrEmpty(System.Linq.Expressions.Expression{System.Func{System.String}},System.String)">
+            <summary>
+            Ensures the given string <paramref name="value"/> is not null or empty.
+            Throws <see cref="T:System.ArgumentNullException"/> in the first case, or 
+            <see cref="T:System.ArgumentException"/> in the latter.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotOutOfRangeInclusive``1(System.Linq.Expressions.Expression{System.Func{``0}},``0,``0,``0)">
+            <summary>
+            Checks an argument to ensure it is in the specified range including the edges.
+            </summary>
+            <typeparam name="T">Type of the argument to check, it must be an <see cref="T:System.IComparable"/> type.
+            </typeparam>
+            <param name="reference">The expression containing the name of the argument.</param>
+            <param name="value">The argument value to check.</param>
+            <param name="from">The minimun allowed value for the argument.</param>
+            <param name="to">The maximun allowed value for the argument.</param>
+        </member>
+        <member name="M:Moq.Guard.NotOutOfRangeExclusive``1(System.Linq.Expressions.Expression{System.Func{``0}},``0,``0,``0)">
+            <summary>
+            Checks an argument to ensure it is in the specified range excluding the edges.
+            </summary>
+            <typeparam name="T">Type of the argument to check, it must be an <see cref="T:System.IComparable"/> type.
+            </typeparam>
+            <param name="reference">The expression containing the name of the argument.</param>
+            <param name="value">The argument value to check.</param>
+            <param name="from">The minimun allowed value for the argument.</param>
+            <param name="to">The maximun allowed value for the argument.</param>
+        </member>
+        <member name="T:Moq.IMocked`1">
+            <summary>
+            Implemented by all generated mock object instances.
+            </summary>
+        </member>
+        <member name="T:Moq.IMocked">
+            <summary>
+            Implemented by all generated mock object instances.
+            </summary>
+        </member>
+        <member name="P:Moq.IMocked.Mock">
+            <summary>
+            Reference the Mock that contains this as the <c>mock.Object</c> value.
+            </summary>
+        </member>
+        <member name="P:Moq.IMocked`1.Mock">
+            <summary>
+            Reference the Mock that contains this as the <c>mock.Object</c> value.
+            </summary>
+        </member>
+        <member name="T:Moq.Interceptor">
+            <summary>
+            Implements the actual interception and method invocation for 
+            all mocks.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetupSetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.ICallbackSetter`1">
+            <summary>
+            Defines the <c>Callback</c> verb for property setter setups.
+            </summary>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallbackSetter`1.Callback(System.Action{`0})">
+            <summary>
+            Specifies a callback to invoke when the property is set that receives the 
+            property value being set.
+            </summary>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the property value being set. 
+            <code>
+            mock.SetupSet(x => x.Suspended)
+                .Callback((bool state) => Console.WriteLine(state));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.It">
+            <summary>
+			Allows the specification of a matching condition for an
+			argument in a method invocation, rather than a specific
+			argument value. "It" refers to the argument being matched.
+		</summary><remarks>
+			This class allows the setup to match a method invocation
+			with an arbitrary value, with a value in a specified range, or
+			even one that matches a given predicate.
+		</remarks>
+        </member>
+        <member name="M:Moq.It.IsAny``1">
+            <summary>
+			Matches any value of the given <typeparamref name="TValue"/> type.
+		</summary><remarks>
+			Typically used when the actual argument value for a method
+			call is not relevant.
+		</remarks><example>
+			<code>
+				// Throws an exception for a call to Remove with any string value.
+				mock.Setup(x => x.Remove(It.IsAny<string>())).Throws(new InvalidOperationException());
+			</code>
+		</example><typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.It.IsNotNull``1">
+            <summary>
+         Matches any value of the given <typeparamref name="TValue"/> type, except null.
+      </summary><typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.It.Is``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+			Matches any value that satisfies the given predicate.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="match">The predicate used to match the method argument.</param><remarks>
+			Allows the specification of a predicate to perform matching
+			of method call arguments.
+		</remarks><example>
+			This example shows how to return the value <c>1</c> whenever the argument to the
+			<c>Do</c> method is an even number.
+			<code>
+				mock.Setup(x => x.Do(It.Is<int>(i => i % 2 == 0)))
+				.Returns(1);
+			</code>
+			This example shows how to throw an exception if the argument to the
+			method is a negative number:
+			<code>
+				mock.Setup(x => x.GetUser(It.Is<int>(i => i < 0)))
+				.Throws(new ArgumentException());
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsInRange``1(``0,``0,Moq.Range)">
+            <summary>
+			Matches any value that is in the range specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="from">The lower bound of the range.</param><param name="to">The upper bound of the range.</param><param name="rangeKind">
+			The kind of range. See <see cref="T:Moq.Range"/>.
+		</param><example>
+			The following example shows how to expect a method call
+			with an integer argument within the 0..100 range.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsInRange(0, 100, Range.Inclusive)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsIn``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+			Matches any value that is present in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of possible values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with value from a list.
+			<code>
+				var values = new List<int> { 1, 2, 3 };
+			
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsIn(values)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsIn``1(``0[])">
+            <summary>
+			Matches any value that is present in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of possible values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with a value of 1, 2, or 3.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsIn(1, 2, 3)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsNotIn``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+			Matches any value that is not found in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of disallowed values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with value not found from a list.
+			<code>
+				var values = new List<int> { 1, 2, 3 };
+				
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsNotIn(values)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsNotIn``1(``0[])">
+            <summary>
+			Matches any value that is not found in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of disallowed values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument of any value except 1, 2, or 3.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsNotIn(1, 2, 3)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsRegex(System.String)">
+            <summary>
+			Matches a string argument if it matches the given regular expression pattern.
+		</summary><param name="regex">The pattern to use to match the string argument value.</param><example>
+			The following example shows how to expect a call to a method where the
+			string argument matches the given regular expression:
+			<code>
+				mock.Setup(x => x.Check(It.IsRegex("[a-z]+"))).Returns(1);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsRegex(System.String,System.Text.RegularExpressions.RegexOptions)">
+            <summary>
+			Matches a string argument if it matches the given regular expression pattern.
+		</summary><param name="regex">The pattern to use to match the string argument value.</param><param name="options">The options used to interpret the pattern.</param><example>
+			The following example shows how to expect a call to a method where the
+			string argument matches the given regular expression, in a case insensitive way:
+			<code>
+				mock.Setup(x => x.Check(It.IsRegex("[a-z]+", RegexOptions.IgnoreCase))).Returns(1);
+			</code>
+		</example>
+        </member>
+        <member name="T:Moq.Matchers.MatcherAttributeMatcher">
+            <summary>
+            Matcher to treat static functions as matchers.
+            
+            mock.Setup(x => x.StringMethod(A.MagicString()));
+            
+            public static class A 
+            {
+                [Matcher]
+                public static string MagicString() { return null; }
+                public static bool MagicString(string arg)
+                {
+                    return arg == "magic";
+                }
+            }
+            
+            Will succeed if: mock.Object.StringMethod("magic");
+            and fail with any other call.
+            </summary>
+        </member>
+        <member name="T:Moq.MockBehavior">
+            <summary>
+            Options to customize the behavior of the mock. 
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Strict">
+            <summary>
+            Causes the mock to always throw 
+            an exception for invocations that don't have a 
+            corresponding setup.
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Loose">
+            <summary>
+            Will never throw exceptions, returning default  
+            values when necessary (null for reference types, 
+            zero for value types or empty enumerables and arrays).
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Default">
+            <summary>
+            Default mock behavior, which equals <see cref="F:Moq.MockBehavior.Loose"/>.
+            </summary>
+        </member>
+        <member name="T:Moq.MockException">
+            <summary>
+            Exception thrown by mocks when setups are not matched, 
+            the mock is not properly setup, etc.
+            </summary>
+            <remarks>
+            A distinct exception type is provided so that exceptions 
+            thrown by the mock can be differentiated in tests that 
+            expect other exceptions to be thrown (i.e. ArgumentException).
+            <para>
+            Richer exception hierarchy/types are not provided as 
+            tests typically should <b>not</b> catch or expect exceptions 
+            from the mocks. These are typically the result of changes 
+            in the tested class or its collaborators implementation, and 
+            result in fixes in the mock setup so that they dissapear and 
+            allow the test to pass.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:Moq.MockException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+            <param name="info">Serialization information.</param>
+            <param name="context">Streaming context.</param>
+        </member>
+        <member name="M:Moq.MockException.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+            <param name="info">Serialization information.</param>
+            <param name="context">Streaming context.</param>
+        </member>
+        <member name="P:Moq.MockException.IsVerificationError">
+            <summary>
+            Indicates whether this exception is a verification fault raised by Verify()
+            </summary>
+        </member>
+        <member name="T:Moq.MockException.ExceptionReason">
+            <summary>
+            Made internal as it's of no use for 
+            consumers, but it's important for 
+            our own tests.
+            </summary>
+        </member>
+        <member name="T:Moq.MockVerificationException">
+            <devdoc>
+            Used by the mock factory to accumulate verification 
+            failures.
+            </devdoc>
+        </member>
+        <member name="M:Moq.MockVerificationException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+        </member>
+        <member name="T:Moq.Properties.Resources">
+            <summary>
+              A strongly-typed resource class, for looking up localized strings, etc.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ResourceManager">
+            <summary>
+              Returns the cached ResourceManager instance used by this class.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.Culture">
+            <summary>
+              Overrides the current thread's CurrentUICulture property for all
+              resource lookups using this strongly typed resource class.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.AlreadyInitialized">
+            <summary>
+              Looks up a localized string similar to Mock type has already been initialized by accessing its Object property. Adding interfaces must be done before that..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ArgumentCannotBeEmpty">
+            <summary>
+              Looks up a localized string similar to Value cannot be an empty string..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.AsMustBeInterface">
+            <summary>
+              Looks up a localized string similar to Can only add interfaces to the mock..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.CantSetReturnValueForVoid">
+            <summary>
+              Looks up a localized string similar to Can't set return value for void method {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorArgsForDelegate">
+            <summary>
+              Looks up a localized string similar to Constructor arguments cannot be passed for delegate mocks..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorArgsForInterface">
+            <summary>
+              Looks up a localized string similar to Constructor arguments cannot be passed for interface mocks..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorNotFound">
+            <summary>
+              Looks up a localized string similar to A matching constructor for the given arguments was not found on the mocked type..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.EventNofFound">
+            <summary>
+              Looks up a localized string similar to Could not locate event for attach or detach method {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.FieldsNotSupported">
+            <summary>
+              Looks up a localized string similar to Expression {0} involves a field access, which is not supported. Use properties instead..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.InvalidMockClass">
+            <summary>
+              Looks up a localized string similar to Type to mock must be an interface or an abstract or non-sealed class. .
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.InvalidMockGetType">
+             <summary>
+               Looks up a localized string similar to Cannot retrieve a mock with the given object type {0} as it's not the main type of the mock or any of its additional interfaces.
+            Please cast the argument to one of the supported types: {1}.
+            Remember that there's no generics covariance in the CLR, so your object must be one of these types in order for the call to succeed..
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqBinaryOperatorNotSupported">
+            <summary>
+              Looks up a localized string similar to The equals ("==" or "=" in VB) and the conditional 'and' ("&&" or "AndAlso" in VB) operators are the only ones supported in the query specification expression. Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqMethodNotSupported">
+            <summary>
+              Looks up a localized string similar to LINQ method '{0}' not supported..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqMethodNotVirtual">
+            <summary>
+              Looks up a localized string similar to Expression contains a call to a method which is not virtual (overridable in VB) or abstract. Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MemberMissing">
+            <summary>
+              Looks up a localized string similar to Member {0}.{1} does not exist..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MethodIsPublic">
+             <summary>
+               Looks up a localized string similar to Method {0}.{1} is public. Use strong-typed Expect overload instead:
+            mock.Setup(x => x.{1}());
+            .
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MockExceptionMessage">
+             <summary>
+               Looks up a localized string similar to {0} invocation failed with mock behavior {1}.
+            {2}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MoreThanNCalls">
+            <summary>
+              Looks up a localized string similar to Expected only {0} calls to {1}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MoreThanOneCall">
+            <summary>
+              Looks up a localized string similar to Expected only one call to {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtLeast">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at least {2} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtLeastOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at least once, but was never performed: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtMost">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at most {3} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtMostOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at most once, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsBetweenExclusive">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock between {2} and {3} times (Exclusive), but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsBetweenInclusive">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock between {2} and {3} times (Inclusive), but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsExactly">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock exactly {2} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsNever">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock should never have been performed, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock once, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoSetup">
+            <summary>
+              Looks up a localized string similar to All invocations on the mock must have a corresponding setup..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ObjectInstanceNotMock">
+            <summary>
+              Looks up a localized string similar to Object instance was not created by Moq..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.OutExpressionMustBeConstantValue">
+            <summary>
+              Looks up a localized string similar to Out expression must evaluate to a constant value..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyGetNotFound">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not have a getter..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyMissing">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not exist..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyNotReadable">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} is write-only..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyNotWritable">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} is read-only..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertySetNotFound">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not have a setter..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.RaisedUnassociatedEvent">
+            <summary>
+              Looks up a localized string similar to Cannot raise a mocked event unless it has been associated (attached) to a concrete event in a mocked object..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.RefExpressionMustBeConstantValue">
+            <summary>
+              Looks up a localized string similar to Ref expression must evaluate to a constant value..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ReturnValueRequired">
+            <summary>
+              Looks up a localized string similar to Invocation needs to return a value and therefore must have a corresponding setup that provides it..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupLambda">
+            <summary>
+              Looks up a localized string similar to A lambda expression is expected as the argument to It.Is<T>..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNever">
+            <summary>
+              Looks up a localized string similar to Invocation {0} should not have been made..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotMethod">
+            <summary>
+              Looks up a localized string similar to Expression is not a method invocation: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotProperty">
+            <summary>
+              Looks up a localized string similar to Expression is not a property access: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotSetter">
+            <summary>
+              Looks up a localized string similar to Expression is not a property setter invocation..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupOnNonMemberMethod">
+            <summary>
+              Looks up a localized string similar to Expression references a method that does not belong to the mocked object: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupOnNonOverridableMember">
+            <summary>
+              Looks up a localized string similar to Invalid setup on a non-virtual (overridable in VB) member: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.TypeNotImplementInterface">
+            <summary>
+              Looks up a localized string similar to Type {0} does not implement required interface {1}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.TypeNotInheritFromType">
+            <summary>
+              Looks up a localized string similar to Type {0} does not from required type {1}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnexpectedPublicProperty">
+             <summary>
+               Looks up a localized string similar to To specify a setup for public property {0}.{1}, use the typed overloads, such as:
+            mock.Setup(x => x.{1}).Returns(value);
+            mock.SetupGet(x => x.{1}).Returns(value); //equivalent to previous one
+            mock.SetupSet(x => x.{1}).Callback(callbackDelegate);
+            .
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedExpression">
+            <summary>
+              Looks up a localized string similar to Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedIntermediateExpression">
+            <summary>
+              Looks up a localized string similar to Only property accesses are supported in intermediate invocations on a setup. Unsupported expression {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedIntermediateType">
+            <summary>
+              Looks up a localized string similar to Expression contains intermediate property access {0}.{1} which is of type {2} and cannot be mocked. Unsupported expression {3}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedMatcherParamsForSetter">
+            <summary>
+              Looks up a localized string similar to Setter expression cannot use argument matchers that receive parameters..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedMember">
+            <summary>
+              Looks up a localized string similar to Member {0} is not supported for protected mocking..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedNonStaticMatcherForSetter">
+            <summary>
+              Looks up a localized string similar to Setter expression can only use static custom matchers..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.VerficationFailed">
+             <summary>
+               Looks up a localized string similar to The following setups were not matched:
+            {0}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.VerifyOnNonVirtualMember">
+            <summary>
+              Looks up a localized string similar to Invalid verify on a non-virtual (overridable in VB) member: {0}.
+            </summary>
+        </member>
+        <member name="T:Moq.Protected.IProtectedMock`1">
+            <summary>
+            Allows setups to be specified for protected members by using their 
+            name as a string, rather than strong-typing them which is not possible 
+            due to their visibility.
+            </summary>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Setup(System.String,System.Object[])">
+            <summary>
+            Specifies a setup for a void method invocation with the given 
+            <paramref name="voidMethodName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <param name="voidMethodName">The name of the void method to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Setup``1(System.String,System.Object[])">
+            <summary>
+            Specifies a setup for an invocation on a property or a non void method with the given 
+            <paramref name="methodOrPropertyName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <param name="methodOrPropertyName">The name of the method or property to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <typeparam name="TResult">The return type of the method or property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.SetupGet``1(System.String)">
+            <summary>
+            Specifies a setup for an invocation on a property getter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.SetupSet``1(System.String,System.Object)">
+            <summary>
+            Specifies a setup for an invocation on a property setter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <param name="value">The property value. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Verify(System.String,Moq.Times,System.Object[])">
+            <summary>
+            Specifies a verify for a void method with the given <paramref name="methodName"/>,
+            optionally specifying arguments for the method call. Use in conjuntion with the default
+            <see cref="F:Moq.MockBehavior.Loose"/>.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="methodName">The name of the void method to be verified.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Verify``1(System.String,Moq.Times,System.Object[])">
+            <summary>
+            Specifies a verify for an invocation on a property or a non void method with the given 
+            <paramref name="methodName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            <param name="methodName">The name of the method or property to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <typeparam name="TResult">The type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.VerifyGet``1(System.String,Moq.Times)">
+            <summary>
+            Specifies a verify for an invocation on a property getter with the given 
+            <paramref name="propertyName"/>.
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.VerifySet``1(System.String,Moq.Times,System.Object)">
+            <summary>
+            Specifies a setup for an invocation on a property setter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            <param name="propertyName">The name of the property.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="value">The property value.</param>
+            <typeparam name="TProperty">The type of the property. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</typeparam>
+        </member>
+        <member name="T:Moq.Protected.ItExpr">
+            <summary>
+            Allows the specification of a matching condition for an 
+            argument in a protected member setup, rather than a specific 
+            argument value. "ItExpr" refers to the argument being matched.
+            </summary>
+            <remarks>
+            <para>Use this variant of argument matching instead of 
+            <see cref="T:Moq.It"/> for protected setups.</para>
+            This class allows the setup to match a method invocation 
+            with an arbitrary value, with a value in a specified range, or 
+            even one that matches a given predicate, or null.
+            </remarks>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsNull``1">
+            <summary>
+            Matches a null value of the given <typeparamref name="TValue"/> type.
+            </summary>
+            <remarks>
+            Required for protected mocks as the null value cannot be used 
+            directly as it prevents proper method overload selection.
+            </remarks>
+            <example>
+            <code>
+            // Throws an exception for a call to Remove with a null string value.
+            mock.Protected()
+                .Setup("Remove", ItExpr.IsNull<string>())
+                .Throws(new InvalidOperationException());
+            </code>
+            </example>
+            <typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsAny``1">
+            <summary>
+            Matches any value of the given <typeparamref name="TValue"/> type.
+            </summary>
+            <remarks>
+            Typically used when the actual argument value for a method 
+            call is not relevant.
+            </remarks>
+            <example>
+            <code>
+            // Throws an exception for a call to Remove with any string value.
+            mock.Protected()
+                .Setup("Remove", ItExpr.IsAny<string>())
+                .Throws(new InvalidOperationException());
+            </code>
+            </example>
+            <typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.Is``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Matches any value that satisfies the given predicate.
+            </summary>
+            <typeparam name="TValue">Type of the argument to check.</typeparam>
+            <param name="match">The predicate used to match the method argument.</param>
+            <remarks>
+            Allows the specification of a predicate to perform matching 
+            of method call arguments.
+            </remarks>
+            <example>
+            This example shows how to return the value <c>1</c> whenever the argument to the 
+            <c>Do</c> method is an even number.
+            <code>
+            mock.Protected()
+                .Setup("Do", ItExpr.Is<int>(i => i % 2 == 0))
+                .Returns(1);
+            </code>
+            This example shows how to throw an exception if the argument to the 
+            method is a negative number:
+            <code>
+            mock.Protected()
+                .Setup("GetUser", ItExpr.Is<int>(i => i < 0))
+                .Throws(new ArgumentException());
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsInRange``1(``0,``0,Moq.Range)">
+            <summary>
+            Matches any value that is in the range specified.
+            </summary>
+            <typeparam name="TValue">Type of the argument to check.</typeparam>
+            <param name="from">The lower bound of the range.</param>
+            <param name="to">The upper bound of the range.</param>
+            <param name="rangeKind">The kind of range. See <see cref="T:Moq.Range"/>.</param>
+            <example>
+            The following example shows how to expect a method call 
+            with an integer argument within the 0..100 range.
+            <code>
+            mock.Protected()
+                .Setup("HasInventory",
+                        ItExpr.IsAny<string>(),
+                        ItExpr.IsInRange(0, 100, Range.Inclusive))
+                .Returns(false);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsRegex(System.String)">
+            <summary>
+            Matches a string argument if it matches the given regular expression pattern.
+            </summary>
+            <param name="regex">The pattern to use to match the string argument value.</param>
+            <example>
+            The following example shows how to expect a call to a method where the 
+            string argument matches the given regular expression:
+            <code>
+            mock.Protected()
+                .Setup("Check", ItExpr.IsRegex("[a-z]+"))
+                .Returns(1);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsRegex(System.String,System.Text.RegularExpressions.RegexOptions)">
+            <summary>
+            Matches a string argument if it matches the given regular expression pattern.
+            </summary>
+            <param name="regex">The pattern to use to match the string argument value.</param>
+            <param name="options">The options used to interpret the pattern.</param>
+            <example>
+            The following example shows how to expect a call to a method where the 
+            string argument matches the given regular expression, in a case insensitive way:
+            <code>
+            mock.Protected()
+                .Setup("Check", ItExpr.IsRegex("[a-z]+", RegexOptions.IgnoreCase))
+                .Returns(1);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Protected.ProtectedExtension">
+            <summary>
+            Enables the <c>Protected()</c> method on <see cref="T:Moq.Mock`1"/>, 
+            allowing setups to be set for protected members by using their 
+            name as a string, rather than strong-typing them which is not possible 
+            due to their visibility.
+            </summary>
+        </member>
+        <member name="M:Moq.Protected.ProtectedExtension.Protected``1(Moq.Mock{``0})">
+            <summary>
+            Enable protected setups for the mock.
+            </summary>
+            <typeparam name="T">Mocked object type. Typically omitted as it can be inferred from the mock instance.</typeparam>
+            <param name="mock">The mock to set the protected setups on.</param>
+        </member>
+        <member name="T:ThisAssembly">
+            <group name="overview" title="Overview" order="0" />
+            <group name="setups" title="Specifying setups" order="1" />
+            <group name="returns" title="Returning values from members" order="2" />
+            <group name="verification" title="Verifying setups" order="3" />
+            <group name="advanced" title="Advanced scenarios" order="99" />
+            <group name="factory" title="Using MockFactory for consistency across mocks" order="4" />
+        </member>
+        <member name="T:Moq.Range">
+            <summary>
+            Kind of range to use in a filter specified through 
+            <see cref="M:Moq.It.IsInRange``1(``0,``0,Moq.Range)"/>.
+            </summary>
+        </member>
+        <member name="F:Moq.Range.Inclusive">
+            <summary>
+            The range includes the <c>to</c> and 
+            <c>from</c> values.
+            </summary>
+        </member>
+        <member name="F:Moq.Range.Exclusive">
+            <summary>
+            The range does not include the <c>to</c> and 
+            <c>from</c> values.
+            </summary>
+        </member>
+        <member name="T:Moq.DefaultValue">
+            <summary>
+            Determines the way default values are generated 
+            calculated for loose mocks.
+            </summary>
+        </member>
+        <member name="F:Moq.DefaultValue.Empty">
+            <summary>
+            Default behavior, which generates empty values for 
+            value types (i.e. default(int)), empty array and 
+            enumerables, and nulls for all other reference types.
+            </summary>
+        </member>
+        <member name="F:Moq.DefaultValue.Mock">
+            <summary>
+            Whenever the default value generated by <see cref="F:Moq.DefaultValue.Empty"/> 
+            is null, replaces this value with a mock (if the type 
+            can be mocked). 
+            </summary>
+            <remarks>
+            For sealed classes, a null value will be generated.
+            </remarks>
+        </member>
+        <member name="T:Moq.Linq.MockQueryable`1">
+            <summary>
+            A default implementation of IQueryable for use with QueryProvider
+            </summary>
+        </member>
+        <member name="M:Moq.Linq.MockQueryable`1.#ctor(System.Linq.Expressions.MethodCallExpression)">
+            <summary>
+            The <paramref name="underlyingCreateMocks"/> is a 
+            static method that returns an IQueryable of Mocks of T which is used to 
+            apply the linq specification to.
+            </summary>
+        </member>
+        <member name="T:Moq.Match">
+            <summary>
+			Allows creation custom value matchers that can be used on setups and verification,
+			completely replacing the built-in <see cref="T:Moq.It"/> class with your own argument
+			matching rules.
+		</summary><remarks>
+			 See also <see cref="T:Moq.Match`1"/>.
+		</remarks>
+        </member>
+        <member name="M:Moq.Match.Matcher``1">
+            <devdoc>
+            Provided for the sole purpose of rendering the delegate passed to the 
+            matcher constructor if no friendly render lambda is provided.
+            </devdoc>
+        </member>
+        <member name="M:Moq.Match.Create``1(System.Predicate{``0})">
+            <summary>
+			Initializes the match with the condition that
+			will be checked in order to match invocation
+			values.
+		</summary><param name="condition">The condition to match against actual values.</param><remarks>
+			 <seealso cref="T:Moq.Match`1"/>
+		</remarks>
+        </member>
+        <member name="M:Moq.Match.Create``1(System.Predicate{``0},System.Linq.Expressions.Expression{System.Func{``0}})">
+            <!-- No matching elements were found for the following include tag --><include file="Match.xdoc" path="docs/doc[@for="Match.Create{T}(condition,renderExpression"]/*"/>
+        </member>
+        <member name="M:Moq.Match.SetLastMatch``1(Moq.Match{``0})">
+            <devdoc>
+            This method is used to set an expression as the last matcher invoked, 
+            which is used in the SetupSet to allow matchers in the prop = value 
+            delegate expression. This delegate is executed in "fluent" mode in 
+            order to capture the value being set, and construct the corresponding 
+            methodcall.
+            This is also used in the MatcherFactory for each argument expression.
+            This method ensures that when we execute the delegate, we 
+            also track the matcher that was invoked, so that when we create the 
+            methodcall we build the expression using it, rather than the null/default 
+            value returned from the actual invocation.
+            </devdoc>
+        </member>
+        <member name="T:Moq.Match`1">
+            <summary>
+			Allows creation custom value matchers that can be used on setups and verification,
+			completely replacing the built-in <see cref="T:Moq.It"/> class with your own argument
+			matching rules.
+		</summary><typeparam name="T">Type of the value to match.</typeparam><remarks>
+			The argument matching is used to determine whether a concrete
+			invocation in the mock matches a given setup. This
+			matching mechanism is fully extensible.
+		</remarks><example>
+			Creating a custom matcher is straightforward. You just need to create a method
+			that returns a value from a call to <see cref="M:Moq.Match.Create``1(System.Predicate{``0})"/> with 
+			your matching condition and optional friendly render expression:
+			<code>
+				[Matcher]
+				public Order IsBigOrder()
+				{
+					return Match<Order>.Create(
+						o => o.GrandTotal >= 5000, 
+						/* a friendly expression to render on failures */
+						() => IsBigOrder());
+				}
+			</code>
+			This method can be used in any mock setup invocation:
+			<code>
+				mock.Setup(m => m.Submit(IsBigOrder()).Throws<UnauthorizedAccessException>();
+			</code>
+			At runtime, Moq knows that the return value was a matcher (note that the method MUST be 
+			annotated with the [Matcher] attribute in order to determine this) and
+			evaluates your predicate with the actual value passed into your predicate.
+			<para>
+				Another example might be a case where you want to match a lists of orders
+				that contains a particular one. You might create matcher like the following:
+			</para>
+			<code>
+				public static class Orders
+				{
+					[Matcher]
+					public static IEnumerable<Order> Contains(Order order)
+					{
+						return Match<IEnumerable<Order>>.Create(orders => orders.Contains(order));
+					}
+				}
+			</code>
+			Now we can invoke this static method instead of an argument in an
+			invocation:
+			<code>
+				var order = new Order { ... };
+				var mock = new Mock<IRepository<Order>>();
+
+				mock.Setup(x => x.Save(Orders.Contains(order)))
+					 .Throws<ArgumentException>();
+			</code>
+		</example>
+        </member>
+        <member name="T:Moq.FluentMockContext">
+            <summary>
+            Tracks the current mock and interception context.
+            </summary>
+        </member>
+        <member name="P:Moq.FluentMockContext.IsActive">
+            <summary>
+            Having an active fluent mock context means that the invocation 
+            is being performed in "trial" mode, just to gather the 
+            target method and arguments that need to be matched later 
+            when the actual invocation is made.
+            </summary>
+        </member>
+        <member name="T:Moq.MockDefaultValueProvider">
+            <summary>
+            A <see cref="T:Moq.IDefaultValueProvider"/> that returns an empty default value 
+            for non-mockeable types, and mocks for all other types (interfaces and 
+            non-sealed classes) that can be mocked.
+            </summary>
+        </member>
+        <member name="T:Moq.Mocks">
+            <summary>
+            Allows querying the universe of mocks for those that behave 
+            according to the LINQ query specification.
+            </summary>
+            <devdoc>
+            This entry-point into Linq to Mocks is the only one in the root Moq 
+            namespace to ease discovery. But to get all the mocking extension 
+            methods on Object, a using of Moq.Linq must be done, so that the 
+            polluting of the intellisense for all objects is an explicit opt-in.
+            </devdoc>
+        </member>
+        <member name="M:Moq.Mocks.Of``1">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.Mocks.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.Mocks.OneOf``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mocks.OneOf``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mocks.CreateMockQuery``1">
+            <summary>
+            Creates the mock query with the underlying queriable implementation.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.CreateQueryable``1">
+            <summary>
+            Wraps the enumerator inside a queryable.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.CreateMocks``1">
+            <summary>
+            Method that is turned into the actual call from .Query{T}, to 
+            transform the queryable query into a normal enumerable query.
+            This method is never used directly by consumers.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.SetPropery``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Extension method used to support Linq-like setup properties that are not virtual but do have 
+            a getter and a setter, thereby allowing the use of Linq to Mocks to quickly initialize Dtos too :)
+            </summary>
+        </member>
+        <member name="T:Moq.QueryableMockExtensions">
+            <summary>
+            Helper extensions that are used by the query translator.
+            </summary>
+        </member>
+        <member name="M:Moq.QueryableMockExtensions.FluentMock``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Retrieves a fluent mock from the given setup expression.
+            </summary>
+        </member>
+        <member name="M:Moq.Proxy.IProxyFactory.GetDelegateProxyInterface(System.Type,System.Reflection.MethodInfo@)">
+            <summary>
+            Gets an autogenerated interface with a method on it that matches the signature of the specified
+            <paramref name="delegateType"/>.
+            </summary>
+            <remarks>
+            Such an interface can then be mocked, and a delegate pointed at the method on the mocked instance.
+            This is how we support delegate mocking.  The factory caches such interfaces and reuses them
+            for repeated requests for the same delegate type.
+            </remarks>
+            <param name="delegateType">The delegate type for which an interface is required.</param>
+            <param name="delegateInterfaceMethod">The method on the autogenerated interface.</param>
+        </member>
+        <member name="M:Moq.Proxy.CastleProxyFactory.CreateProxy(System.Type,Moq.Proxy.ICallInterceptor,System.Type[],System.Object[])">
+            <inheritdoc />
+        </member>
+        <member name="M:Moq.Proxy.CastleProxyFactory.GetDelegateProxyInterface(System.Type,System.Reflection.MethodInfo@)">
+            <inheritdoc />
+        </member>
+        <member name="T:Moq.Times">
+            <summary>
+			Defines the number of invocations allowed by a mocked method.
+		</summary>
+        </member>
+        <member name="M:Moq.Times.AtLeast(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked <paramref name="callCount"/> times as minimum.
+		</summary><param name="callCount">The minimun number of times.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtLeastOnce">
+            <summary>
+			Specifies that a mocked method should be invoked one time as minimum.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtMost(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked <paramref name="callCount"/> time as maximun.
+		</summary><param name="callCount">The maximun number of times.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtMostOnce">
+            <summary>
+			Specifies that a mocked method should be invoked one time as maximun.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Between(System.Int32,System.Int32,Moq.Range)">
+            <summary>
+			Specifies that a mocked method should be invoked between <paramref name="callCountFrom"/> and
+			<paramref name="callCountTo"/> times.
+		</summary><param name="callCountFrom">The minimun number of times.</param><param name="callCountTo">The maximun number of times.</param><param name="rangeKind">
+			The kind of range. See <see cref="T:Moq.Range"/>.
+		</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Exactly(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked exactly <paramref name="callCount"/> times.
+		</summary><param name="callCount">The times that a method or property can be called.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Never">
+            <summary>
+			Specifies that a mocked method should not be invoked.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Once">
+            <summary>
+			Specifies that a mocked method should be invoked exactly one time.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Equals(System.Object)">
+            <summary>
+			Determines whether the specified <see cref="T:System.Object"/> is equal to this instance.
+		</summary><param name="obj">
+			The <see cref="T:System.Object"/> to compare with this instance.
+		</param><returns>
+			<c>true</c> if the specified <see cref="T:System.Object"/> is equal to this instance; otherwise, <c>false</c>.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.GetHashCode">
+            <summary>
+			Returns a hash code for this instance.
+		</summary><returns>
+			A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.op_Equality(Moq.Times,Moq.Times)">
+            <summary>
+			Determines whether two specified <see cref="T:Moq.Times"/> objects have the same value.
+		</summary><param name="left">
+			The first <see cref="T:Moq.Times"/>.
+		</param><param name="right">
+			The second <see cref="T:Moq.Times"/>.
+		</param><returns>
+			<c>true</c> if the value of left is the same as the value of right; otherwise, <c>false</c>.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.op_Inequality(Moq.Times,Moq.Times)">
+            <summary>
+			Determines whether two specified <see cref="T:Moq.Times"/> objects have different values.
+		</summary><param name="left">
+			The first <see cref="T:Moq.Times"/>.
+		</param><param name="right">
+			The second <see cref="T:Moq.Times"/>.
+		</param><returns>
+			<c>true</c> if the value of left is different from the value of right; otherwise, <c>false</c>.
+		</returns>
+        </member>
+    </members>
+</doc>
diff --git a/SolutionItems/Moq/lib/net40/Moq.dll b/SolutionItems/Moq/lib/net40/Moq.dll
new file mode 100644
index 0000000..9f32452
Binary files /dev/null and b/SolutionItems/Moq/lib/net40/Moq.dll differ
diff --git a/SolutionItems/Moq/lib/net40/Moq.xml b/SolutionItems/Moq/lib/net40/Moq.xml
new file mode 100644
index 0000000..d28b628
--- /dev/null
+++ b/SolutionItems/Moq/lib/net40/Moq.xml
@@ -0,0 +1,5401 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>Moq</name>
+    </assembly>
+    <members>
+        <member name="T:Moq.Language.ISetupConditionResult`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.Setup(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+            The expectation will be considered only in the former condition.
+            </summary>
+            <param name="expression"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.Setup``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            The expectation will be considered only in the former condition.
+            </summary>
+            <typeparam name="TResult"></typeparam>
+            <param name="expression"></param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Setups the get.
+            </summary>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+            <param name="expression">The expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupSet``1(System.Action{`0})">
+            <summary>
+            Setups the set.
+            </summary>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+            <param name="setterExpression">The setter expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.Language.ISetupConditionResult`1.SetupSet(System.Action{`0})">
+            <summary>
+            Setups the set.
+            </summary>
+            <param name="setterExpression">The setter expression.</param>
+            <returns></returns>
+        </member>
+        <member name="M:Moq.IInterceptStrategy.HandleIntercept(Moq.Proxy.ICallContext,Moq.InterceptStrategyContext)">
+            <summary>
+            Handle interception
+            </summary>
+            <param name="invocation">the current invocation context</param>
+            <param name="ctx">shared data among the strategies during an interception</param>
+            <returns>true if further interception has to be processed, otherwise false</returns>
+        </member>
+        <member name="T:Moq.IMock`1">
+            <summary>
+            Covarient interface for Mock<T> such that casts between IMock<Employee> to IMock<Person>
+            are possible. Only covers the covariant members of Mock<T>.
+            </summary>
+        </member>
+        <member name="P:Moq.IMock`1.Object">
+            <summary>
+			Exposes the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.Behavior">
+            <summary>
+			Behavior of the mock, according to the value set in the constructor.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.CallBase">
+            <summary>
+			Whether the base member virtual implementation will be called
+			for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+		</summary>
+        </member>
+        <member name="P:Moq.IMock`1.DefaultValue">
+            <summary>
+			Specifies the behavior to use when returning default values for
+			unexpected invocations on loose mocks.
+		</summary>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetEventFromName(System.String)">
+            <summary>
+            Get an eventInfo for a given event name.  Search type ancestors depth first if necessary.
+            </summary>
+            <param name="eventName">Name of the event, with the set_ or get_ prefix already removed</param>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetNonPublicEventFromName(System.String)">
+            <summary>
+            Get an eventInfo for a given event name.  Search type ancestors depth first if necessary.
+            Searches also in non public events.
+            </summary>
+            <param name="eventName">Name of the event, with the set_ or get_ prefix already removed</param>
+        </member>
+        <member name="M:Moq.AddActualInvocation.GetAncestorTypes(System.Type)">
+            <summary>
+            Given a type return all of its ancestors, both types and interfaces.
+            </summary>
+            <param name="initialType">The type to find immediate ancestors of</param>
+        </member>
+        <member name="T:Moq.Language.ICallback">
+            <summary>
+            Defines the <c>Callback</c> verb and overloads.
+            </summary>
+        </member>
+        <member name="T:Moq.IHideObjectMembers">
+            <summary>
+            Helper interface used to hide the base <see cref="T:System.Object"/> 
+            members from the fluent API to make it much cleaner 
+            in Visual Studio intellisense.
+            </summary>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.GetType">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.GetHashCode">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.ToString">
+            <summary/>
+        </member>
+        <member name="M:Moq.IHideObjectMembers.Equals(System.Object)">
+            <summary/>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the method is called.
+            </summary>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            The following example specifies a callback to set a boolean 
+            value that can be used later:
+            <code>
+            var called = false;
+            mock.Setup(x => x.Execute())
+                .Callback(() => called = true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``1(System.Action{``0})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T">The argument type of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the concrete invocation argument value. 
+            <para>
+            Notice how the specific string argument is retrieved by simply declaring 
+            it as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Callback((string command) => Console.WriteLine(command));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``2(System.Action{``0,``1})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2) => Console.WriteLine(arg1 + arg2));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``3(System.Action{``0,``1,``2})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3) => Console.WriteLine(arg1 + arg2 + arg3));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``4(System.Action{``0,``1,``2,``3})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``5(System.Action{``0,``1,``2,``3,``4})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``6(System.Action{``0,``1,``2,``3,``4,``5})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``7(System.Action{``0,``1,``2,``3,``4,``5,``6})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``8(System.Action{``0,``1,``2,``3,``4,``5,``6,``7})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``9(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``10(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``11(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``12(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``13(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``14(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``15(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback.Callback``16(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.ICallbackResult"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15, string arg16) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.ICallback`2">
+            <summary>
+            Defines the <c>Callback</c> verb and overloads for callbacks on
+            setups that return a value.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TResult">Type of the return value of the setup.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the method is called.
+            </summary>
+            <param name="action">The callback method to invoke.</param>
+            <example>
+            The following example specifies a callback to set a boolean value that can be used later:
+            <code>
+            var called = false;
+            mock.Setup(x => x.Execute())
+                .Callback(() => called = true)
+                .Returns(true);
+            </code>
+            Note that in the case of value-returning methods, after the <c>Callback</c>
+            call you can still specify the return value.
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``1(System.Action{``0})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original arguments.
+            </summary>
+            <typeparam name="T">The type of the argument of the invoked method.</typeparam>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the concrete invocation argument value.
+            <para>
+            Notice how the specific string argument is retrieved by simply declaring
+            it as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Callback(command => Console.WriteLine(command))
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``2(System.Action{``0,``1})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2) => Console.WriteLine(arg1 + arg2));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``3(System.Action{``0,``1,``2})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3) => Console.WriteLine(arg1 + arg2 + arg3));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``4(System.Action{``0,``1,``2,``3})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4) => Console.WriteLine(arg1 + arg2 + arg3 + arg4));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``5(System.Action{``0,``1,``2,``3,``4})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``6(System.Action{``0,``1,``2,``3,``4,``5})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``7(System.Action{``0,``1,``2,``3,``4,``5,``6})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``8(System.Action{``0,``1,``2,``3,``4,``5,``6,``7})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``9(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``10(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``11(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``12(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``13(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``14(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``15(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15));
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.ICallback`2.Callback``16(System.Action{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15})">
+            <summary>
+            Specifies a callback to invoke when the method is called that receives the original
+            arguments.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="action">The callback method to invoke.</param>
+            <returns>A reference to <see cref="T:Moq.Language.Flow.IReturnsThrows`2"/> interface.</returns>
+            <example>
+            Invokes the given callback with the concrete invocation arguments values. 
+            <para>
+            Notice how the specific arguments are retrieved by simply declaring 
+            them as part of the lambda expression for the callback:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>(),
+                                 It.IsAny<string>()))
+                .Callback((arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16) => Console.WriteLine(arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.IRaise`1">
+            <summary>
+            Defines the <c>Raises</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)">
+            <summary>
+            Specifies the event that will be raised 
+            when the setup is met.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="args">The event arguments to pass for the raised event.</param>
+            <example>
+            The following example shows how to raise an event when 
+            the setup is met:
+            <code>
+            var mock = new Mock<IContainer>();
+            
+            mock.Setup(add => add.Add(It.IsAny<string>(), It.IsAny<object>()))
+                .Raises(add => add.Added += null, EventArgs.Empty);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.Func{System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised 
+            when the setup is matched.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="func">A function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.Object[])">
+            <summary>
+            Specifies the custom event that will be raised 
+            when the setup is matched.
+            </summary>
+            <param name="eventExpression">An expression that represents an event attach or detach action.</param>
+            <param name="args">The arguments to pass to the custom delegate (non EventHandler-compatible).</param>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``1(System.Action{`0},System.Func{``0,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``2(System.Action{`0},System.Func{``0,``1,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``3(System.Action{`0},System.Func{``0,``1,``2,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``4(System.Action{`0},System.Func{``0,``1,``2,``3,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``5(System.Action{`0},System.Func{``0,``1,``2,``3,``4,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``6(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``7(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``8(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``9(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``10(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``11(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``12(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``13(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``14(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``15(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="M:Moq.Language.IRaise`1.Raises``16(System.Action{`0},System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15,System.EventArgs})">
+            <summary>
+            Specifies the event that will be raised when the setup is matched.
+            </summary>
+            <param name="eventExpression">The expression that represents an event attach or detach action.</param>
+            <param name="func">The function that will build the <see cref="T:System.EventArgs"/> 
+            to pass when raising the event.</param>
+            <typeparam name="T1">The type of the first argument received by the expected invocation.</typeparam>
+            <typeparam name="T2">The type of the second argument received by the expected invocation.</typeparam>
+            <typeparam name="T3">The type of the third argument received by the expected invocation.</typeparam>
+            <typeparam name="T4">The type of the fourth argument received by the expected invocation.</typeparam>
+            <typeparam name="T5">The type of the fifth argument received by the expected invocation.</typeparam>
+            <typeparam name="T6">The type of the sixth argument received by the expected invocation.</typeparam>
+            <typeparam name="T7">The type of the seventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T8">The type of the eighth argument received by the expected invocation.</typeparam>
+            <typeparam name="T9">The type of the nineth argument received by the expected invocation.</typeparam>
+            <typeparam name="T10">The type of the tenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument received by the expected invocation.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument received by the expected invocation.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument received by the expected invocation.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument received by the expected invocation.</typeparam>
+            <seealso cref="M:Moq.Language.IRaise`1.Raises(System.Action{`0},System.EventArgs)"/>
+        </member>
+        <member name="T:Moq.Language.IReturns`2">
+            <summary>
+            Defines the <c>Returns</c> verb.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TResult">Type of the return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns(`1)">
+            <summary>
+            Specifies the value to return.
+            </summary>
+            <param name="value">The value to return, or <see langword="null"/>.</param>
+            <example>
+            Return a <c>true</c> value from the method call:
+            <code>
+            mock.Setup(x => x.Execute("ping"))
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns(System.Func{`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method.
+            </summary>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example group="returns">
+            Return a calculated value when the method is called:
+            <code>
+            mock.Setup(x => x.Execute("ping"))
+                .Returns(() => returnValues[0]);
+            </code>
+            The lambda expression to retrieve the return value is lazy-executed, 
+            meaning that its value may change depending on the moment the method 
+            is executed and the value the <c>returnValues</c> array has at 
+            that moment.
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``1(System.Func{``0,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T">The type of the argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example group="returns">
+            Return a calculated value which is evaluated lazily at the time of the invocation.
+            <para>
+            The lookup list can change between invocations and the setup 
+            will return different values accordingly. Also, notice how the specific 
+            string argument is retrieved by simply declaring it as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(It.IsAny<string>()))
+                .Returns((string command) => returnValues[command]);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.CallBase">
+            <summary>
+            Calls the real method of the object and returns its return value.
+            </summary>
+            <returns>The value calculated by the real method of the object.</returns>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``2(System.Func{``0,``1,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2) => arg1 + arg2);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``3(System.Func{``0,``1,``2,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3) => arg1 + arg2 + arg3);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``4(System.Func{``0,``1,``2,``3,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4) => arg1 + arg2 + arg3 + arg4);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``5(System.Func{``0,``1,``2,``3,``4,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5) => arg1 + arg2 + arg3 + arg4 + arg5);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``6(System.Func{``0,``1,``2,``3,``4,``5,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``7(System.Func{``0,``1,``2,``3,``4,``5,``6,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``8(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``9(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``10(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``11(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``12(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``13(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``14(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``15(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturns`2.Returns``16(System.Func{``0,``1,``2,``3,``4,``5,``6,``7,``8,``9,``10,``11,``12,``13,``14,``15,`1})">
+            <summary>
+            Specifies a function that will calculate the value to return from the method, 
+            retrieving the arguments for the invocation.
+            </summary>
+            <typeparam name="T1">The type of the first argument of the invoked method.</typeparam>
+            <typeparam name="T2">The type of the second argument of the invoked method.</typeparam>
+            <typeparam name="T3">The type of the third argument of the invoked method.</typeparam>
+            <typeparam name="T4">The type of the fourth argument of the invoked method.</typeparam>
+            <typeparam name="T5">The type of the fifth argument of the invoked method.</typeparam>
+            <typeparam name="T6">The type of the sixth argument of the invoked method.</typeparam>
+            <typeparam name="T7">The type of the seventh argument of the invoked method.</typeparam>
+            <typeparam name="T8">The type of the eighth argument of the invoked method.</typeparam>
+            <typeparam name="T9">The type of the nineth argument of the invoked method.</typeparam>
+            <typeparam name="T10">The type of the tenth argument of the invoked method.</typeparam>
+            <typeparam name="T11">The type of the eleventh argument of the invoked method.</typeparam>
+            <typeparam name="T12">The type of the twelfth argument of the invoked method.</typeparam>
+            <typeparam name="T13">The type of the thirteenth argument of the invoked method.</typeparam>
+            <typeparam name="T14">The type of the fourteenth argument of the invoked method.</typeparam>
+            <typeparam name="T15">The type of the fifteenth argument of the invoked method.</typeparam>
+            <typeparam name="T16">The type of the sixteenth argument of the invoked method.</typeparam>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <return>Returns a calculated value which is evaluated lazily at the time of the invocation.</return>
+            <example>
+            <para>
+            The return value is calculated from the value of the actual method invocation arguments. 
+            Notice how the arguments are retrieved by simply declaring them as part of the lambda 
+            expression:
+            </para>
+            <code>
+            mock.Setup(x => x.Execute(
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>(), 
+                                 It.IsAny<int>()))
+                .Returns((string arg1, string arg2, string arg3, string arg4, string arg5, string arg6, string arg7, string arg8, string arg9, string arg10, string arg11, string arg12, string arg13, string arg14, string arg15, string arg16) => arg1 + arg2 + arg3 + arg4 + arg5 + arg6 + arg7 + arg8 + arg9 + arg10 + arg11 + arg12 + arg13 + arg14 + arg15 + arg16);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.ReturnsExtensions">
+            <summary>
+            Defines async extension methods on IReturns.
+            </summary>
+        </member>
+        <member name="M:Moq.ReturnsExtensions.ReturnsAsync``2(Moq.Language.IReturns{``0,System.Threading.Tasks.Task{``1}},``1)">
+            <summary>
+            Allows to specify the return value of an asynchronous method.
+            </summary>
+        </member>
+        <member name="M:Moq.ReturnsExtensions.ThrowsAsync``2(Moq.Language.IReturns{``0,System.Threading.Tasks.Task{``1}},System.Exception)">
+            <summary>
+            Allows to specify the exception thrown by an asynchronous method.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.ISetupSequentialResult`1">
+            <summary>
+            Language for ReturnSequence
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Returns(`0)">
+            <summary>
+            Returns value
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Throws(System.Exception)">
+            <summary>
+            Throws an exception
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.Throws``1">
+            <summary>
+            Throws an exception
+            </summary>
+        </member>
+        <member name="M:Moq.Language.ISetupSequentialResult`1.CallBase">
+            <summary>
+            Calls original method
+            </summary>
+        </member>
+        <member name="F:Moq.Linq.FluentMockVisitor.isFirst">
+            <summary>
+            The first method call or member access will be the 
+            last segment of the expression (depth-first traversal), 
+            which is the one we have to Setup rather than FluentMock.
+            And the last one is the one we have to Mock.Get rather 
+            than FluentMock.
+            </summary>
+        </member>
+        <member name="T:Moq.Mock">
+            <summary>
+			Base class for mocks and static helper class with methods that
+			apply to mocked objects, such as <see cref="M:Moq.Mock.Get``1(``0)"/> to
+			retrieve a <see cref="T:Moq.Mock`1"/> from an object instance.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Of``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mock.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="predicate">The predicate with the specification of how the mocked object should behave.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mock.#ctor">
+            <summary>
+			Initializes a new instance of the <see cref="T:Moq.Mock"/> class.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Get``1(``0)">
+            <summary>
+			Retrieves the mock object for the given object instance.
+		</summary><typeparam name="T">
+			Type of the mock to retrieve. Can be omitted as it's inferred
+			from the object instance passed in as the <paramref name="mocked"/> instance.
+		</typeparam><param name="mocked">The instance of the mocked object.</param><returns>The mock associated with the mocked object.</returns><exception cref="T:System.ArgumentException">
+			The received <paramref name="mocked"/> instance
+			was not created by Moq.
+		</exception><example group="advanced">
+			The following example shows how to add a new setup to an object
+			instance which is not the original <see cref="T:Moq.Mock`1"/> but rather
+			the object associated with it:
+			<code>
+				// Typed instance, not the mock, is retrieved from some test API.
+				HttpContextBase context = GetMockContext();
+
+				// context.Request is the typed object from the "real" API
+				// so in order to add a setup to it, we need to get
+				// the mock that "owns" it
+				Mock<HttpRequestBase> request = Mock.Get(context.Request);
+				mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
+					 .Returns(tempUrl);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock.OnGetObject">
+            <summary>
+			Returns the mocked object value.
+		</summary>
+        </member>
+        <member name="M:Moq.Mock.Verify">
+            <summary>
+			Verifies that all verifiable expectations have been met.
+		</summary><example group="verification">
+			This example sets up an expectation and marks it as verifiable. After
+			the mock is used, a <c>Verify()</c> call is issued on the mock
+			to ensure the method in the setup was invoked:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				this.Setup(x => x.HasInventory(TALISKER, 50)).Verifiable().Returns(true);
+				...
+				// other test code
+				...
+				// Will throw if the test code has didn't call HasInventory.
+				this.Verify();
+			</code>
+		</example><exception cref="T:Moq.MockException">Not all verifiable expectations were met.</exception>
+        </member>
+        <member name="M:Moq.Mock.VerifyAll">
+            <summary>
+			Verifies all expectations regardless of whether they have
+			been flagged as verifiable.
+		</summary><example group="verification">
+			This example sets up an expectation without marking it as verifiable. After
+			the mock is used, a <see cref="M:Moq.Mock.VerifyAll"/> call is issued on the mock
+			to ensure that all expectations are met:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				this.Setup(x => x.HasInventory(TALISKER, 50)).Returns(true);
+				...
+				// other test code
+				...
+				// Will throw if the test code has didn't call HasInventory, even
+				// that expectation was not marked as verifiable.
+				this.VerifyAll();
+			</code>
+		</example><exception cref="T:Moq.MockException">At least one expectation was not met.</exception>        
+        </member>
+        <member name="M:Moq.Mock.GetInterceptor(System.Linq.Expressions.Expression,Moq.Mock)">
+            <summary>
+            Gets the interceptor target for the given expression and root mock, 
+            building the intermediate hierarchy of mock objects if necessary.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.DoRaise(System.Reflection.EventInfo,System.EventArgs)">
+            <summary>
+            Raises the associated event with the given 
+            event argument data.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.DoRaise(System.Reflection.EventInfo,System.Object[])">
+            <summary>
+            Raises the associated event with the given 
+            event argument data.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock.As``1">
+            <summary>
+			Adds an interface implementation to the mock,
+			allowing setups to be specified for it.
+		</summary><remarks>
+			This method can only be called before the first use
+			of the mock <see cref="P:Moq.Mock.Object"/> property, at which
+			point the runtime type has already been generated
+			and no more interfaces can be added to it.
+			<para>
+				Also, <typeparamref name="TInterface"/> must be an
+				interface and not a class, which must be specified
+				when creating the mock instead.
+			</para>
+		</remarks><exception cref="T:System.InvalidOperationException">
+			The mock type
+			has already been generated by accessing the <see cref="P:Moq.Mock.Object"/> property.
+		</exception><exception cref="T:System.ArgumentException">
+			The <typeparamref name="TInterface"/> specified
+			is not an interface.
+		</exception><example>
+			The following example creates a mock for the main interface
+			and later adds <see cref="T:System.IDisposable"/> to it to verify
+			it's called by the consumer code:
+			<code>
+				var mock = new Mock<IProcessor>();
+				mock.Setup(x => x.Execute("ping"));
+
+				// add IDisposable interface
+				var disposable = mock.As<IDisposable>();
+				disposable.Setup(d => d.Dispose()).Verifiable();
+			</code>
+		</example><typeparam name="TInterface">Type of interface to cast the mock to.</typeparam>
+        </member>
+        <member name="M:Moq.Mock.SetReturnsDefault``1(``0)">
+            <!-- No matching elements were found for the following include tag --><include file="Mock.Generic.xdoc" path="docs/doc[@for="Mock.SetReturnDefault{TReturn}"]/*"/>
+        </member>
+        <member name="P:Moq.Mock.Behavior">
+            <summary>
+			Behavior of the mock, according to the value set in the constructor.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.CallBase">
+            <summary>
+			Whether the base member virtual implementation will be called
+			for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.DefaultValue">
+            <summary>
+			Specifies the behavior to use when returning default values for
+			unexpected invocations on loose mocks.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.Object">
+            <summary>
+			Gets the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock.MockedType">
+            <summary>
+            Retrieves the type of the mocked object, its generic type argument.
+            This is used in the auto-mocking of hierarchy access.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.DelegateInterfaceMethod">
+            <summary>
+            If this is a mock of a delegate, this property contains the method
+            on the autogenerated interface so that we can convert setup + verify
+            expressions on the delegate into expressions on the interface proxy.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.IsDelegateMock">
+            <summary>
+            Allows to check whether expression conversion to the <see cref="P:Moq.Mock.DelegateInterfaceMethod"/> 
+            must be performed on the mock, without causing unnecessarily early initialization of 
+            the mock instance, which breaks As{T}.
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.DefaultValueProvider">
+            <summary>
+            Specifies the class that will determine the default 
+            value to return when invocations are made that 
+            have no setups and need to return a default 
+            value (for loose mocks).
+            </summary>
+        </member>
+        <member name="P:Moq.Mock.ImplementedInterfaces">
+            <summary>
+            Exposes the list of extra interfaces implemented by the mock.
+            </summary>
+        </member>
+        <member name="T:Moq.MockRepository">
+            <summary>
+            Utility repository class to use to construct multiple 
+            mocks when consistent verification is 
+            desired for all of them.
+            </summary>
+            <remarks>
+            If multiple mocks will be created during a test, passing 
+            the desired <see cref="T:Moq.MockBehavior"/> (if different than the 
+            <see cref="F:Moq.MockBehavior.Default"/> or the one 
+            passed to the repository constructor) and later verifying each
+            mock can become repetitive and tedious.
+            <para>
+            This repository class helps in that scenario by providing a 
+            simplified creation of multiple mocks with a default 
+            <see cref="T:Moq.MockBehavior"/> (unless overriden by calling 
+            <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/>) and posterior verification.
+            </para>
+            </remarks>
+            <example group="repository">
+            The following is a straightforward example on how to 
+            create and automatically verify strict mocks using a <see cref="T:Moq.MockRepository"/>:
+            <code>
+            var repository = new MockRepository(MockBehavior.Strict);
+            
+            var foo = repository.Create<IFoo>();
+            var bar = repository.Create<IBar>();
+            
+            // no need to call Verifiable() on the setup 
+            // as we'll be validating all of them anyway.
+            foo.Setup(f => f.Do());
+            bar.Setup(b => b.Redo());
+            
+            // exercise the mocks here
+            
+            repository.VerifyAll(); 
+            // At this point all setups are already checked 
+            // and an optional MockException might be thrown. 
+            // Note also that because the mocks are strict, any invocation 
+            // that doesn't have a matching setup will also throw a MockException.
+            </code>
+            The following examples shows how to setup the repository 
+            to create loose mocks and later verify only verifiable setups:
+            <code>
+            var repository = new MockRepository(MockBehavior.Loose);
+            
+            var foo = repository.Create<IFoo>();
+            var bar = repository.Create<IBar>();
+            
+            // this setup will be verified when we verify the repository
+            foo.Setup(f => f.Do()).Verifiable();
+            	
+            // this setup will NOT be verified 
+            foo.Setup(f => f.Calculate());
+            	
+            // this setup will be verified when we verify the repository
+            bar.Setup(b => b.Redo()).Verifiable();
+            
+            // exercise the mocks here
+            // note that because the mocks are Loose, members 
+            // called in the interfaces for which no matching
+            // setups exist will NOT throw exceptions, 
+            // and will rather return default values.
+            
+            repository.Verify();
+            // At this point verifiable setups are already checked 
+            // and an optional MockException might be thrown.
+            </code>
+            The following examples shows how to setup the repository with a 
+            default strict behavior, overriding that default for a 
+            specific mock:
+            <code>
+            var repository = new MockRepository(MockBehavior.Strict);
+            
+            // this particular one we want loose
+            var foo = repository.Create<IFoo>(MockBehavior.Loose);
+            var bar = repository.Create<IBar>();
+            
+            // specify setups
+            
+            // exercise the mocks here
+            
+            repository.Verify();
+            </code>
+            </example>
+            <seealso cref="T:Moq.MockBehavior"/>
+        </member>
+        <member name="T:Moq.MockFactory">
+            <summary>
+            Utility factory class to use to construct multiple 
+            mocks when consistent verification is 
+            desired for all of them.
+            </summary>
+            <remarks>
+            If multiple mocks will be created during a test, passing 
+            the desired <see cref="T:Moq.MockBehavior"/> (if different than the 
+            <see cref="F:Moq.MockBehavior.Default"/> or the one 
+            passed to the factory constructor) and later verifying each
+            mock can become repetitive and tedious.
+            <para>
+            This factory class helps in that scenario by providing a 
+            simplified creation of multiple mocks with a default 
+            <see cref="T:Moq.MockBehavior"/> (unless overriden by calling 
+            <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/>) and posterior verification.
+            </para>
+            </remarks>
+            <example group="factory">
+            The following is a straightforward example on how to 
+            create and automatically verify strict mocks using a <see cref="T:Moq.MockFactory"/>:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>();
+            var bar = factory.Create<IBar>();
+            
+            // no need to call Verifiable() on the setup 
+            // as we'll be validating all of them anyway.
+            foo.Setup(f => f.Do());
+            bar.Setup(b => b.Redo());
+            
+            // exercise the mocks here
+            
+            factory.VerifyAll(); 
+            // At this point all setups are already checked 
+            // and an optional MockException might be thrown. 
+            // Note also that because the mocks are strict, any invocation 
+            // that doesn't have a matching setup will also throw a MockException.
+            </code>
+            The following examples shows how to setup the factory 
+            to create loose mocks and later verify only verifiable setups:
+            <code>
+            var factory = new MockFactory(MockBehavior.Loose);
+            
+            var foo = factory.Create<IFoo>();
+            var bar = factory.Create<IBar>();
+            
+            // this setup will be verified when we verify the factory
+            foo.Setup(f => f.Do()).Verifiable();
+            	
+            // this setup will NOT be verified 
+            foo.Setup(f => f.Calculate());
+            	
+            // this setup will be verified when we verify the factory
+            bar.Setup(b => b.Redo()).Verifiable();
+            
+            // exercise the mocks here
+            // note that because the mocks are Loose, members 
+            // called in the interfaces for which no matching
+            // setups exist will NOT throw exceptions, 
+            // and will rather return default values.
+            
+            factory.Verify();
+            // At this point verifiable setups are already checked 
+            // and an optional MockException might be thrown.
+            </code>
+            The following examples shows how to setup the factory with a 
+            default strict behavior, overriding that default for a 
+            specific mock:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            // this particular one we want loose
+            var foo = factory.Create<IFoo>(MockBehavior.Loose);
+            var bar = factory.Create<IBar>();
+            
+            // specify setups
+            
+            // exercise the mocks here
+            
+            factory.Verify();
+            </code>
+            </example>
+            <seealso cref="T:Moq.MockBehavior"/>
+        </member>
+        <member name="M:Moq.MockFactory.#ctor(Moq.MockBehavior)">
+            <summary>
+            Initializes the factory with the given <paramref name="defaultBehavior"/> 
+            for newly created mocks from the factory.
+            </summary>
+            <param name="defaultBehavior">The behavior to use for mocks created 
+            using the <see cref="M:Moq.MockFactory.Create``1"/> factory method if not overriden 
+            by using the <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/> overload.</param>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1">
+            <summary>
+            Creates a new mock with the default <see cref="T:Moq.MockBehavior"/> 
+            specified at factory construction time.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example ignore="true">
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>();
+            // use mock on tests
+            
+            factory.VerifyAll();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(System.Object[])">
+            <summary>
+            Creates a new mock with the default <see cref="T:Moq.MockBehavior"/> 
+            specified at factory construction time and with the 
+            the given constructor arguments for the class.
+            </summary>
+            <remarks>
+            The mock will try to find the best match constructor given the 
+            constructor arguments, and invoke that to initialize the instance. 
+            This applies only to classes, not interfaces.
+            </remarks>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="args">Constructor arguments for mocked classes.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example ignore="true">
+            <code>
+            var factory = new MockFactory(MockBehavior.Default);
+            
+            var mock = factory.Create<MyBase>("Foo", 25, true);
+            // use mock on tests
+            
+            factory.Verify();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(Moq.MockBehavior)">
+            <summary>
+            Creates a new mock with the given <paramref name="behavior"/>.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">Behavior to use for the mock, which overrides 
+            the default behavior specified at factory construction time.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example group="factory">
+            The following example shows how to create a mock with a different 
+            behavior to that specified as the default for the factory:
+            <code>
+            var factory = new MockFactory(MockBehavior.Strict);
+            
+            var foo = factory.Create<IFoo>(MockBehavior.Loose);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.Create``1(Moq.MockBehavior,System.Object[])">
+            <summary>
+            Creates a new mock with the given <paramref name="behavior"/> 
+            and with the the given constructor arguments for the class.
+            </summary>
+            <remarks>
+            The mock will try to find the best match constructor given the 
+            constructor arguments, and invoke that to initialize the instance. 
+            This applies only to classes, not interfaces.
+            </remarks>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">Behavior to use for the mock, which overrides 
+            the default behavior specified at factory construction time.</param>
+            <param name="args">Constructor arguments for mocked classes.</param>
+            <returns>A new <see cref="T:Moq.Mock`1"/>.</returns>
+            <example group="factory">
+            The following example shows how to create a mock with a different 
+            behavior to that specified as the default for the factory, passing 
+            constructor arguments:
+            <code>
+            var factory = new MockFactory(MockBehavior.Default);
+            
+            var mock = factory.Create<MyBase>(MockBehavior.Strict, "Foo", 25, true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.MockFactory.CreateMock``1(Moq.MockBehavior,System.Object[])">
+            <summary>
+            Implements creation of a new mock within the factory.
+            </summary>
+            <typeparam name="T">Type to mock.</typeparam>
+            <param name="behavior">The behavior for the new mock.</param>
+            <param name="args">Optional arguments for the construction of the mock.</param>
+        </member>
+        <member name="M:Moq.MockFactory.Verify">
+            <summary>
+            Verifies all verifiable expectations on all mocks created 
+            by this factory.
+            </summary>
+            <seealso cref="M:Moq.Mock.Verify"/>
+            <exception cref="T:Moq.MockException">One or more mocks had expectations that were not satisfied.</exception>
+        </member>
+        <member name="M:Moq.MockFactory.VerifyAll">
+            <summary>
+            Verifies all verifiable expectations on all mocks created 
+            by this factory.
+            </summary>
+            <seealso cref="M:Moq.Mock.Verify"/>
+            <exception cref="T:Moq.MockException">One or more mocks had expectations that were not satisfied.</exception>
+        </member>
+        <member name="M:Moq.MockFactory.VerifyMocks(System.Action{Moq.Mock})">
+            <summary>
+            Invokes <paramref name="verifyAction"/> for each mock 
+            in <see cref="P:Moq.MockFactory.Mocks"/>, and accumulates the resulting 
+            <see cref="T:Moq.MockVerificationException"/> that might be 
+            thrown from the action.
+            </summary>
+            <param name="verifyAction">The action to execute against 
+            each mock.</param>
+        </member>
+        <member name="P:Moq.MockFactory.CallBase">
+            <summary>
+            Whether the base member virtual implementation will be called 
+            for mocked classes if no setup is matched. Defaults to <see langword="false"/>.
+            </summary>
+        </member>
+        <member name="P:Moq.MockFactory.DefaultValue">
+            <summary>
+            Specifies the behavior to use when returning default values for 
+            unexpected invocations on loose mocks.
+            </summary>
+        </member>
+        <member name="P:Moq.MockFactory.Mocks">
+            <summary>
+            Gets the mocks that have been created by this factory and 
+            that will get verified together.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.Of``1">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.MockRepository.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.MockRepository.OneOf``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.MockRepository.OneOf``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.MockRepository.CreateMockQuery``1">
+            <summary>
+            Creates the mock query with the underlying queriable implementation.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.CreateQueryable``1">
+            <summary>
+            Wraps the enumerator inside a queryable.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.CreateMocks``1">
+            <summary>
+            Method that is turned into the actual call from .Query{T}, to 
+            transform the queryable query into a normal enumerable query.
+            This method is never used directly by consumers.
+            </summary>
+        </member>
+        <member name="M:Moq.MockRepository.#ctor(Moq.MockBehavior)">
+            <summary>
+            Initializes the repository with the given <paramref name="defaultBehavior"/> 
+            for newly created mocks from the repository.
+            </summary>
+            <param name="defaultBehavior">The behavior to use for mocks created 
+            using the <see cref="M:Moq.MockFactory.Create``1"/> repository method if not overriden 
+            by using the <see cref="M:Moq.MockFactory.Create``1(Moq.MockBehavior)"/> overload.</param>
+        </member>
+        <member name="T:Moq.EmptyDefaultValueProvider">
+            <summary>
+            A <see cref="T:Moq.IDefaultValueProvider"/> that returns an empty default value 
+            for invocations that do not have setups or return values, with loose mocks.
+            This is the default behavior for a mock.
+            </summary>
+        </member>
+        <member name="T:Moq.IDefaultValueProvider">
+            <summary>
+			Interface to be implemented by classes that determine the
+			default value of non-expected invocations.
+		</summary>
+        </member>
+        <member name="M:Moq.IDefaultValueProvider.DefineDefault``1(``0)">
+            <summary>
+			Defines the default value to return in all the methods returning <typeparamref name="T"/>.
+		</summary><typeparam name="T">The type of the return value.</typeparam><param name="value">The value to set as default.</param>
+        </member>
+        <member name="M:Moq.IDefaultValueProvider.ProvideDefault(System.Reflection.MethodInfo)">
+            <summary>
+			Provides a value for the given member and arguments.
+		</summary><param name="member">
+			The member to provide a default	value for.
+		</param>
+        </member>
+        <member name="T:Moq.ExpressionStringBuilder">
+            <summary>
+            The intention of <see cref="T:Moq.ExpressionStringBuilder"/> is to create a more readable 
+            string representation for the failure message.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ICallbackResult">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IThrows">
+            <summary>
+            Defines the <c>Throws</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IThrows.Throws(System.Exception)">
+            <summary>
+            Specifies the exception to throw when the method is invoked.
+            </summary>
+            <param name="exception">Exception instance to throw.</param>
+            <example>
+            This example shows how to throw an exception when the method is 
+            invoked with an empty string argument:
+            <code>
+            mock.Setup(x => x.Execute(""))
+                .Throws(new ArgumentException());
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IThrows.Throws``1">
+            <summary>
+            Specifies the type of exception to throw when the method is invoked.
+            </summary>
+            <typeparam name="TException">Type of exception to instantiate and throw when the setup is matched.</typeparam>
+            <example>
+            This example shows how to throw an exception when the method is 
+            invoked with an empty string argument:
+            <code>
+            mock.Setup(x => x.Execute(""))
+                .Throws<ArgumentException>();
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.IThrowsResult">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IOccurrence">
+            <summary>
+            Defines occurrence members to constraint setups.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IOccurrence.AtMostOnce">
+            <summary>
+            The expected invocation can happen at most once.
+            </summary>
+            <example>
+            <code>
+            var mock = new Mock<ICommand>();
+            mock.Setup(foo => foo.Execute("ping"))
+                .AtMostOnce();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IOccurrence.AtMost(System.Int32)">
+            <summary>
+            The expected invocation can happen at most specified number of times.
+            </summary>
+            <param name="callCount">The number of times to accept calls.</param>
+            <example>
+            <code>
+            var mock = new Mock<ICommand>();
+            mock.Setup(foo => foo.Execute("ping"))
+                .AtMost( 5 );
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.IVerifies">
+            <summary>
+            Defines the <c>Verifiable</c> verb.
+            </summary>
+        </member>
+        <member name="M:Moq.Language.IVerifies.Verifiable">
+            <summary>
+            Marks the expectation as verifiable, meaning that a call 
+            to <see cref="M:Moq.Mock.Verify"/> will check if this particular 
+            expectation was met.
+            </summary>
+            <example>
+            The following example marks the expectation as verifiable:
+            <code>
+            mock.Expect(x => x.Execute("ping"))
+                .Returns(true)
+                .Verifiable();
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IVerifies.Verifiable(System.String)">
+            <summary>
+            Marks the expectation as verifiable, meaning that a call 
+            to <see cref="M:Moq.Mock.Verify"/> will check if this particular 
+            expectation was met, and specifies a message for failures.
+            </summary>
+            <example>
+            The following example marks the expectation as verifiable:
+            <code>
+            mock.Expect(x => x.Execute("ping"))
+                .Returns(true)
+                .Verifiable("Ping should be executed always!");
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetup`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.MethodCallReturn">
+            <devdoc>
+            We need this non-generics base class so that 
+            we can use <see cref="P:Moq.MethodCallReturn.HasReturnValue"/> from 
+            generic code.
+            </devdoc>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetup`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsThrows`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetupGetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.ICallbackGetter`2">
+            <summary>
+            Defines the <c>Callback</c> verb for property getter setups.
+            </summary>
+            <seealso cref="M:Moq.Mock`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})"/>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallbackGetter`2.Callback(System.Action)">
+            <summary>
+            Specifies a callback to invoke when the property is retrieved.
+            </summary>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the property value being set. 
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Callback(() => called = true)
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsThrowsGetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.IReturnsGetter`2">
+            <summary>
+            Defines the <c>Returns</c> verb for property get setups.
+            </summary>
+            <typeparam name="TMock">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.Returns(`1)">
+            <summary>
+            Specifies the value to return.
+            </summary>
+            <param name="value">The value to return, or <see langword="null"/>.</param>
+            <example>
+            Return a <c>true</c> value from the property getter call:
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Returns(true);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.Returns(System.Func{`1})">
+            <summary>
+            Specifies a function that will calculate the value to return for the property.
+            </summary>
+            <param name="valueFunction">The function that will calculate the return value.</param>
+            <example>
+            Return a calculated value when the property is retrieved:
+            <code>
+            mock.SetupGet(x => x.Suspended)
+                .Returns(() => returnValues[0]);
+            </code>
+            The lambda expression to retrieve the return value is lazy-executed, 
+            meaning that its value may change depending on the moment the property  
+            is retrieved and the value the <c>returnValues</c> array has at 
+            that moment.
+            </example>
+        </member>
+        <member name="M:Moq.Language.IReturnsGetter`2.CallBase">
+            <summary>
+            Calls the real property of the object and returns its return value.
+            </summary>
+            <returns>The value calculated by the real property of the object.</returns>
+        </member>
+        <member name="T:Moq.Language.Flow.IReturnsResult`1">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.MockExtensions">
+            <summary>
+            Provides additional methods on mocks.
+            </summary>
+            <remarks>
+            Those methods are useful for Testeroids support. 
+            </remarks>
+        </member>
+        <member name="M:Moq.MockExtensions.ResetCalls(Moq.Mock)">
+            <summary>
+            Resets the calls previously made on the specified mock.
+            </summary>
+            <param name="mock">The mock whose calls need to be reset.</param>
+        </member>
+        <member name="T:Moq.MockSequence">
+            <summary>
+            Helper class to setup a full trace between many mocks
+            </summary>
+        </member>
+        <member name="M:Moq.MockSequence.#ctor">
+            <summary>
+            Initialize a trace setup
+            </summary>
+        </member>
+        <member name="P:Moq.MockSequence.Cyclic">
+            <summary>
+            Allow sequence to be repeated
+            </summary>
+        </member>
+        <member name="T:Moq.MockSequenceHelper">
+            <summary>
+            define nice api
+            </summary>
+        </member>
+        <member name="M:Moq.MockSequenceHelper.InSequence``1(Moq.Mock{``0},Moq.MockSequence)">
+            <summary>
+            Perform an expectation in the trace.
+            </summary>
+        </member>
+        <member name="T:Moq.MatcherAttribute">
+            <summary>
+            Marks a method as a matcher, which allows complete replacement 
+            of the built-in <see cref="T:Moq.It"/> class with your own argument 
+            matching rules.
+            </summary>
+            <remarks>
+            <b>This feature has been deprecated in favor of the new 
+            and simpler <see cref="T:Moq.Match`1"/>.
+            </b>
+            <para>
+            The argument matching is used to determine whether a concrete 
+            invocation in the mock matches a given setup. This 
+            matching mechanism is fully extensible. 
+            </para>
+            <para>
+            There are two parts of a matcher: the compiler matcher 
+            and the runtime matcher.
+            <list type="bullet">
+            <item>
+            <term>Compiler matcher</term>
+            <description>Used to satisfy the compiler requirements for the 
+            argument. Needs to be a method optionally receiving any arguments 
+            you might need for the matching, but with a return type that 
+            matches that of the argument. 
+            <para>
+            Let's say I want to match a lists of orders that contains 
+            a particular one. I might create a compiler matcher like the following:
+            </para>
+            <code>
+            public static class Orders
+            {
+              [Matcher]
+              public static IEnumerable<Order> Contains(Order order)
+              {
+                return null;
+              }
+            }
+            </code>
+            Now we can invoke this static method instead of an argument in an 
+            invocation:
+            <code>
+            var order = new Order { ... };
+            var mock = new Mock<IRepository<Order>>();
+            
+            mock.Setup(x => x.Save(Orders.Contains(order)))
+                .Throws<ArgumentException>();
+            </code>
+            Note that the return value from the compiler matcher is irrelevant. 
+            This method will never be called, and is just used to satisfy the 
+            compiler and to signal Moq that this is not a method that we want 
+            to be invoked at runtime.
+            </description>
+            </item>
+            <item>
+            <term>Runtime matcher</term>
+            <description>
+            The runtime matcher is the one that will actually perform evaluation 
+            when the test is run, and is defined by convention to have the 
+            same signature as the compiler matcher, but where the return 
+            value is the first argument to the call, which contains the 
+            object received by the actual invocation at runtime:
+            <code>
+              public static bool Contains(IEnumerable<Order> orders, Order order)
+              {
+                return orders.Contains(order);
+              }
+            </code>
+            At runtime, the mocked method will be invoked with a specific 
+            list of orders. This value will be passed to this runtime 
+            matcher as the first argument, while the second argument is the 
+            one specified in the setup (<c>x.Save(Orders.Contains(order))</c>).
+            <para>
+            The boolean returned determines whether the given argument has been 
+            matched. If all arguments to the expected method are matched, then 
+            the setup matches and is evaluated.
+            </para>
+            </description>
+            </item>
+            </list>
+            </para>
+            Using this extensible infrastructure, you can easily replace the entire 
+            <see cref="T:Moq.It"/> set of matchers with your own. You can also avoid the 
+            typical (and annoying) lengthy expressions that result when you have 
+            multiple arguments that use generics.
+            </remarks>
+            <example>
+            The following is the complete example explained above:
+            <code>
+            public static class Orders
+            {
+              [Matcher]
+              public static IEnumerable<Order> Contains(Order order)
+              {
+                return null;
+              }
+              
+              public static bool Contains(IEnumerable<Order> orders, Order order)
+              {
+                return orders.Contains(order);
+              }
+            }
+            </code>
+            And the concrete test using this matcher:
+            <code>
+            var order = new Order { ... };
+            var mock = new Mock<IRepository<Order>>();
+            
+            mock.Setup(x => x.Save(Orders.Contains(order)))
+                .Throws<ArgumentException>();
+                
+            // use mock, invoke Save, and have the matcher filter.
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Mock`1">
+            <summary>
+			Provides a mock implementation of <typeparamref name="T"/>.
+		</summary><remarks>
+			Any interface type can be used for mocking, but for classes, only abstract and virtual members can be mocked.
+			<para>
+				The behavior of the mock with regards to the setups and the actual calls is determined
+				by the optional <see cref="T:Moq.MockBehavior"/> that can be passed to the <see cref="M:Moq.Mock`1.#ctor(Moq.MockBehavior)"/>
+				constructor.
+			</para>
+		</remarks><typeparam name="T">Type to mock, which can be an interface or a class.</typeparam><example group="overview" order="0">
+			The following example shows establishing setups with specific values
+			for method invocations:
+			<code>
+				// Arrange
+				var order = new Order(TALISKER, 50);
+				var mock = new Mock<IWarehouse>();
+
+				mock.Setup(x => x.HasInventory(TALISKER, 50)).Returns(true);
+
+				// Act
+				order.Fill(mock.Object);
+
+				// Assert
+				Assert.True(order.IsFilled);
+			</code>
+			The following example shows how to use the <see cref="T:Moq.It"/> class
+			to specify conditions for arguments instead of specific values:
+			<code>
+				// Arrange
+				var order = new Order(TALISKER, 50);
+				var mock = new Mock<IWarehouse>();
+
+				// shows how to expect a value within a range
+				mock.Setup(x => x.HasInventory(
+							It.IsAny<string>(),
+							It.IsInRange(0, 100, Range.Inclusive)))
+					 .Returns(false);
+
+				// shows how to throw for unexpected calls.
+				mock.Setup(x => x.Remove(
+							It.IsAny<string>(),
+							It.IsAny<int>()))
+					 .Throws(new InvalidOperationException());
+
+				// Act
+				order.Fill(mock.Object);
+
+				// Assert
+				Assert.False(order.IsFilled);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Expect(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.Expect``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectSet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.ExpectSet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},``0)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(System.Boolean)">
+            <summary>
+            Ctor invoked by AsTInterface exclusively.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor">
+            <summary>
+			Initializes an instance of the mock with <see cref="F:Moq.MockBehavior.Default">default behavior</see>.
+		</summary><example>
+			<code>var mock = new Mock<IFormatProvider>();</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(System.Object[])">
+            <summary>
+			Initializes an instance of the mock with <see cref="F:Moq.MockBehavior.Default">default behavior</see> and with
+			the given constructor arguments for the class. (Only valid when <typeparamref name="T"/> is a class)
+		</summary><remarks>
+			The mock will try to find the best match constructor given the constructor arguments, and invoke that
+			to initialize the instance. This applies only for classes, not interfaces.
+		</remarks><example>
+			<code>var mock = new Mock<MyProvider>(someArgument, 25);</code>
+		</example><param name="args">Optional constructor arguments if the mocked type is a class.</param>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(Moq.MockBehavior)">
+            <summary>
+			Initializes an instance of the mock with the specified <see cref="T:Moq.MockBehavior">behavior</see>.
+		</summary><example>
+			<code>var mock = new Mock<IFormatProvider>(MockBehavior.Relaxed);</code>
+		</example><param name="behavior">Behavior of the mock.</param>
+        </member>
+        <member name="M:Moq.Mock`1.#ctor(Moq.MockBehavior,System.Object[])">
+            <summary>
+			Initializes an instance of the mock with a specific <see cref="T:Moq.MockBehavior">behavior</see> with
+			the given constructor arguments for the class.
+		</summary><remarks>
+			The mock will try to find the best match constructor given the constructor arguments, and invoke that
+			to initialize the instance. This applies only to classes, not interfaces.
+		</remarks><example>
+			<code>var mock = new Mock<MyProvider>(someArgument, 25);</code>
+		</example><param name="behavior">Behavior of the mock.</param><param name="args">Optional constructor arguments if the mocked type is a class.</param>
+        </member>
+        <member name="M:Moq.Mock`1.OnGetObject">
+            <summary>
+            Returns the mocked object value.
+            </summary>
+        </member>
+        <member name="M:Moq.Mock`1.Setup(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a void method.
+		</summary><remarks>
+			If more than one setup is specified for the same method or property,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="expression">Lambda expression that specifies the expected method invocation.</param><example group="setups">
+			<code>
+				var mock = new Mock<IProcessor>();
+				mock.Setup(x => x.Execute("ping"));
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Setup``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a value returning method.
+		</summary><typeparam name="TResult">Type of the return value. Typically omitted as it can be inferred from the expression.</typeparam><remarks>
+			If more than one setup is specified for the same method or property,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="expression">Lambda expression that specifies the method invocation.</param><example group="setups">
+			<code>
+				mock.Setup(x => x.HasInventory("Talisker", 50)).Returns(true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property getter.
+		</summary><remarks>
+			If more than one setup is set for the same property getter,
+			the latest one wins and is the one that will be executed.
+		</remarks><typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam><param name="expression">Lambda expression that specifies the property getter.</param><example group="setups">
+			<code>
+				mock.SetupGet(x => x.Suspended)
+					 .Returns(true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupSet``1(System.Action{`0})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property setter.
+		</summary><remarks>
+			If more than one setup is set for the same property setter,
+			the latest one wins and is the one that will be executed.
+			<para>
+				This overloads allows the use of a callback already
+				typed for the property type.
+			</para>
+		</remarks><typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam><param name="setterExpression">The Lambda expression that sets a property to a value.</param><example group="setups">
+			<code>
+				mock.SetupSet(x => x.Suspended = true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupSet(System.Action{`0})">
+            <summary>
+			Specifies a setup on the mocked type for a call to
+			to a property setter.
+		</summary><remarks>
+			If more than one setup is set for the same property setter,
+			the latest one wins and is the one that will be executed.
+		</remarks><param name="setterExpression">Lambda expression that sets a property to a value.</param><example group="setups">
+			<code>
+				mock.SetupSet(x => x.Suspended = true);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupProperty``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Specifies that the given property should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. (this is also
+			known as "stubbing").
+		</summary><typeparam name="TProperty">
+			Type of the property, inferred from the property
+			expression (does not need to be specified).
+		</typeparam><param name="property">Property expression to stub.</param><example>
+			If you have an interface with an int property <c>Value</c>, you might
+			stub it using the following straightforward call:
+			<code>
+				var mock = new Mock<IHaveValue>();
+				mock.Stub(v => v.Value);
+			</code>
+			After the <c>Stub</c> call has been issued, setting and
+			retrieving the object value will behave as expected:
+			<code>
+				IHaveValue v = mock.Object;
+
+				v.Value = 5;
+				Assert.Equal(5, v.Value);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupProperty``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},``0)">
+            <summary>
+			Specifies that the given property should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. This overload
+			allows setting the initial value for the property. (this is also
+			known as "stubbing").
+		</summary><typeparam name="TProperty">
+			Type of the property, inferred from the property
+			expression (does not need to be specified).
+		</typeparam><param name="property">Property expression to stub.</param><param name="initialValue">Initial value for the property.</param><example>
+			If you have an interface with an int property <c>Value</c>, you might
+			stub it using the following straightforward call:
+			<code>
+				var mock = new Mock<IHaveValue>();
+				mock.SetupProperty(v => v.Value, 5);
+			</code>
+			After the <c>SetupProperty</c> call has been issued, setting and
+			retrieving the object value will behave as expected:
+			<code>
+				IHaveValue v = mock.Object;
+				// Initial value was stored
+				Assert.Equal(5, v.Value);
+
+				// New value set which changes the initial value
+				v.Value = 6;
+				Assert.Equal(6, v.Value);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.SetupAllProperties">
+            <summary>
+			Specifies that the all properties on the mock should have "property behavior",
+			meaning that setting its value will cause it to be saved and
+			later returned when the property is requested. (this is also
+			known as "stubbing"). The default value for each property will be the
+			one generated as specified by the <see cref="P:Moq.Mock.DefaultValue"/> property for the mock.
+		</summary><remarks>
+			If the mock <see cref="P:Moq.Mock.DefaultValue"/> is set to <see cref="F:Moq.DefaultValue.Mock"/>,
+			the mocked default values will also get all properties setup recursively.
+		</remarks>
+        </member>
+        <member name="M:Moq.Mock`1.When(System.Func{System.Boolean})">
+            <!-- No matching elements were found for the following include tag --><include file="Mock.Generic.xdoc" path="docs/doc[@for="Mock{T}.When"]/*"/>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IProcessor>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call Execute with a "ping" string argument.
+				mock.Verify(proc => proc.Execute("ping"));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},Moq.Times)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IProcessor>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call Execute with a "ping" string argument.
+				mock.Verify(proc => proc.Execute("ping"));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify(System.Linq.Expressions.Expression{System.Action{`0}},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock,
+			specifying a failure error message. Use in conjuntion with the default
+			<see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Verifies that a specific invocation matching the given expression was performed on the mock. Use
+			in conjuntion with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><example group="verification">
+			This example assumes that the mock has been used, and later we want to verify that a given
+			invocation with specific parameters was performed:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call HasInventory.
+				mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50));
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock. Use in conjuntion
+			with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock. Use in conjuntion
+			with the default <see cref="F:Moq.MockBehavior.Loose"/>.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock, specifying a failure
+			error message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given invocation
+			with specific parameters was performed:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't call HasInventory.
+				mock.Verify(warehouse => warehouse.HasInventory(TALISKER, 50), "When filling orders, inventory has to be checked");
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.Verify``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a specific invocation matching the given
+			expression was performed on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="expression">Expression to verify.</param><param name="times">The number of times a method is allowed to be called.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TResult">Type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was retrieved from it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't retrieve the IsClosed property.
+				mock.VerifyGet(warehouse => warehouse.IsClosed);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times)">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a property was read on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was retrieved from it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't retrieve the IsClosed property.
+				mock.VerifyGet(warehouse => warehouse.IsClosed);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},Moq.Times,System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifyGet``1(System.Linq.Expressions.Expression{System.Func{`0,``0}},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a property was read on the mock, specifying a failure
+			error message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="expression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param><typeparam name="TProperty">
+			Type of the property to verify. Typically omitted as it can
+			be inferred from the expression's return type.
+		</typeparam>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0})">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was set on it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't set the IsClosed property.
+				mock.VerifySet(warehouse => warehouse.IsClosed = true);
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},Moq.Times)">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.Func{Moq.Times})">
+            <summary>
+			Verifies that a property was set on the mock.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><example group="verification">
+			This example assumes that the mock has been used,
+			and later we want to verify that a given property
+			was set on it:
+			<code>
+				var mock = new Mock<IWarehouse>();
+				// exercise mock
+				//...
+				// Will throw if the test code didn't set the IsClosed property.
+				mock.VerifySet(warehouse => warehouse.IsClosed = true, "Warehouse should always be closed after the action");
+			</code>
+		</example><exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},Moq.Times,System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.VerifySet(System.Action{`0},System.Func{Moq.Times},System.String)">
+            <summary>
+			Verifies that a property was set on the mock, specifying
+			a failure message.
+		</summary><exception cref="T:Moq.MockException">
+			The invocation was not call the times specified by
+			<paramref name="times"/>.
+		</exception><param name="times">The number of times a method is allowed to be called.</param><param name="setterExpression">Expression to verify.</param><param name="failMessage">Message to show if verification fails.</param>
+        </member>
+        <member name="M:Moq.Mock`1.Raise(System.Action{`0},System.EventArgs)">
+            <summary>
+			Raises the event referenced in <paramref name="eventExpression"/> using
+			the given <paramref name="args"/> argument.
+		</summary><exception cref="T:System.ArgumentException">
+			The <paramref name="args"/> argument is
+			invalid for the target event invocation, or the <paramref name="eventExpression"/> is
+			not an event attach or detach expression.
+		</exception><example>
+			The following example shows how to raise a <see cref="E:System.ComponentModel.INotifyPropertyChanged.PropertyChanged"/> event:
+			<code>
+				var mock = new Mock<IViewModel>();
+
+				mock.Raise(x => x.PropertyChanged -= null, new PropertyChangedEventArgs("Name"));
+			</code>
+		</example><example>
+			This example shows how to invoke an event with a custom event arguments
+			class in a view that will cause its corresponding presenter to
+			react by changing its state:
+			<code>
+				var mockView = new Mock<IOrdersView>();
+				var presenter = new OrdersPresenter(mockView.Object);
+
+				// Check that the presenter has no selection by default
+				Assert.Null(presenter.SelectedOrder);
+
+				// Raise the event with a specific arguments data
+				mockView.Raise(v => v.SelectionChanged += null, new OrderEventArgs { Order = new Order("moq", 500) });
+
+				// Now the presenter reacted to the event, and we have a selected order
+				Assert.NotNull(presenter.SelectedOrder);
+				Assert.Equal("moq", presenter.SelectedOrder.ProductName);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.Mock`1.Raise(System.Action{`0},System.Object[])">
+            <summary>
+			Raises the event referenced in <paramref name="eventExpression"/> using
+			the given <paramref name="args"/> argument for a non-EventHandler typed event.
+		</summary><exception cref="T:System.ArgumentException">
+			The <paramref name="args"/> arguments are
+			invalid for the target event invocation, or the <paramref name="eventExpression"/> is
+			not an event attach or detach expression.
+		</exception><example>
+			The following example shows how to raise a custom event that does not adhere to 
+			the standard <c>EventHandler</c>:
+			<code>
+				var mock = new Mock<IViewModel>();
+
+				mock.Raise(x => x.MyEvent -= null, "Name", bool, 25);
+			</code>
+		</example>
+        </member>
+        <member name="P:Moq.Mock`1.Object">
+            <summary>
+			Exposes the mocked object instance.
+		</summary>
+        </member>
+        <member name="P:Moq.Mock`1.DelegateInterfaceMethod">
+            <inheritdoc />
+        </member>
+        <member name="T:Moq.MockLegacyExtensions">
+            <summary>
+            Provides legacy API members as extensions so that 
+            existing code continues to compile, but new code 
+            doesn't see then.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.SetupSet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="M:Moq.MockLegacyExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1,System.String)">
+            <summary>
+            Obsolete.
+            </summary>
+        </member>
+        <member name="T:Moq.ObsoleteMockExtensions">
+            <summary>
+            Provides additional methods on mocks.
+            </summary>
+            <devdoc>
+            Provided as extension methods as they confuse the compiler 
+            with the overloads taking Action.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.SetupSet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Specifies a setup on the mocked type for a call to 
+            to a property setter, regardless of its value.
+            </summary>
+            <remarks>
+            If more than one setup is set for the same property setter, 
+            the latest one wins and is the one that will be executed.
+            </remarks>
+            <typeparam name="TProperty">Type of the property. Typically omitted as it can be inferred from the expression.</typeparam>
+            <typeparam name="T">Type of the mock.</typeparam>
+            <param name="mock">The target mock for the setup.</param>
+            <param name="expression">Lambda expression that specifies the property setter.</param>
+            <example group="setups">
+            <code>
+            mock.SetupSet(x => x.Suspended);
+            </code>
+            </example>
+            <devdoc>
+            This method is not legacy, but must be on an extension method to avoid 
+            confusing the compiler with the new Action syntax.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Verifies that a property has been set on the mock, regarless of its value.
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <param name="expression">Expression to verify.</param>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.String)">
+            <summary>
+            Verifies that a property has been set on the mock, specifying a failure  
+            error message. 
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <param name="expression">Expression to verify.</param>
+            <param name="failMessage">Message to show if verification fails.</param>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},Moq.Times)">
+            <summary>
+            Verifies that a property has been set on the mock, regardless 
+            of the value but only the specified number of times.
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="expression">Expression to verify.</param>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="M:Moq.ObsoleteMockExtensions.VerifySet``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},Moq.Times,System.String)">
+            <summary>
+            Verifies that a property has been set on the mock, regardless 
+            of the value but only the specified number of times, and specifying a failure  
+            error message. 
+            </summary>
+            <example group="verification">
+            This example assumes that the mock has been used, 
+            and later we want to verify that a given invocation 
+            with specific parameters was performed:
+            <code>
+            var mock = new Mock<IWarehouse>();
+            // exercise mock
+            //...
+            // Will throw if the test code didn't set the IsClosed property.
+            mock.VerifySet(warehouse => warehouse.IsClosed);
+            </code>
+            </example>
+            <exception cref="T:Moq.MockException">The invocation was not performed on the mock.</exception>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="mock">The mock instance.</param>
+            <typeparam name="T">Mocked type.</typeparam>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="failMessage">Message to show if verification fails.</param>
+            <param name="expression">Expression to verify.</param>
+            <typeparam name="TProperty">Type of the property to verify. Typically omitted as it can 
+            be inferred from the expression's return type.</typeparam>
+        </member>
+        <member name="T:Moq.SequenceExtensions">
+            <summary>
+            Helper for sequencing return values in the same method.
+            </summary>
+        </member>
+        <member name="M:Moq.SequenceExtensions.SetupSequence``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Return a sequence of values, once per call.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToLambda(System.Linq.Expressions.Expression)">
+            <summary>
+            Casts the expression to a lambda expression, removing 
+            a cast if there's any.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToMethodCall(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Casts the body of the lambda expression to a <see cref="T:System.Linq.Expressions.MethodCallExpression"/>.
+            </summary>
+            <exception cref="T:System.ArgumentException">If the body is not a method call.</exception>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToPropertyInfo(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Converts the body of the lambda expression into the <see cref="T:System.Reflection.PropertyInfo"/> referenced by it.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsProperty(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Checks whether the body of the lambda expression is a property access.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsProperty(System.Linq.Expressions.Expression)">
+            <summary>
+            Checks whether the expression is a property access.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsPropertyIndexer(System.Linq.Expressions.LambdaExpression)">
+            <summary>
+            Checks whether the body of the lambda expression is a property indexer, which is true 
+            when the expression is an <see cref="T:System.Linq.Expressions.MethodCallExpression"/> whose 
+            <see cref="P:System.Linq.Expressions.MethodCallExpression.Method"/> has <see cref="P:System.Reflection.MethodBase.IsSpecialName"/> 
+            equal to <see langword="true"/>.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.IsPropertyIndexer(System.Linq.Expressions.Expression)">
+            <summary>
+            Checks whether the expression is a property indexer, which is true 
+            when the expression is an <see cref="T:System.Linq.Expressions.MethodCallExpression"/> whose 
+            <see cref="P:System.Linq.Expressions.MethodCallExpression.Method"/> has <see cref="P:System.Reflection.MethodBase.IsSpecialName"/> 
+            equal to <see langword="true"/>.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.CastTo``1(System.Linq.Expressions.Expression)">
+            <summary>
+            Creates an expression that casts the given expression to the <typeparamref name="T"/> 
+            type.
+            </summary>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.ToStringFixed(System.Linq.Expressions.Expression)">
+            <devdoc>
+            TODO: remove this code when https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=331583 
+            is fixed.
+            </devdoc>
+        </member>
+        <member name="M:Moq.ExpressionExtensions.GetCallInfo(System.Linq.Expressions.LambdaExpression,Moq.Mock)">
+            <summary>
+            Extracts, into a common form, information from a <see cref="T:System.Linq.Expressions.LambdaExpression"/>
+            around either a <see cref="T:System.Linq.Expressions.MethodCallExpression"/> (for a normal method call)
+            or a <see cref="T:System.Linq.Expressions.InvocationExpression"/> (for a delegate invocation).
+            </summary>
+        </member>
+        <member name="M:Moq.Extensions.IsDelegate(System.Type)">
+            <summary>
+            Tests if a type is a delegate type (subclasses <see cref="T:System.Delegate"/>).
+            </summary>
+        </member>
+        <member name="T:Moq.Evaluator">
+            <summary>
+            Provides partial evaluation of subtrees, whenever they can be evaluated locally.
+            </summary>
+            <author>Matt Warren: http://blogs.msdn.com/mattwar</author>
+            <contributor>Documented by InSTEDD: http://www.instedd.org</contributor>
+        </member>
+        <member name="M:Moq.Evaluator.PartialEval(System.Linq.Expressions.Expression,System.Func{System.Linq.Expressions.Expression,System.Boolean})">
+            <summary>
+            Performs evaluation and replacement of independent sub-trees
+            </summary>
+            <param name="expression">The root of the expression tree.</param>
+            <param name="fnCanBeEvaluated">A function that decides whether a given expression
+            node can be part of the local function.</param>
+            <returns>A new tree with sub-trees evaluated and replaced.</returns>
+        </member>
+        <member name="M:Moq.Evaluator.PartialEval(System.Linq.Expressions.Expression)">
+            <summary>
+            Performs evaluation and replacement of independent sub-trees
+            </summary>
+            <param name="expression">The root of the expression tree.</param>
+            <returns>A new tree with sub-trees evaluated and replaced.</returns>
+        </member>
+        <member name="T:Moq.Evaluator.SubtreeEvaluator">
+            <summary>
+            Evaluates and replaces sub-trees when first candidate is reached (top-down)
+            </summary>
+        </member>
+        <member name="T:Moq.Evaluator.Nominator">
+            <summary>
+            Performs bottom-up analysis to determine which nodes can possibly
+            be part of an evaluated sub-tree.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotNull``1(System.Linq.Expressions.Expression{System.Func{``0}},``0)">
+            <summary>
+            Ensures the given <paramref name="value"/> is not null.
+            Throws <see cref="T:System.ArgumentNullException"/> otherwise.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotNullOrEmpty(System.Linq.Expressions.Expression{System.Func{System.String}},System.String)">
+            <summary>
+            Ensures the given string <paramref name="value"/> is not null or empty.
+            Throws <see cref="T:System.ArgumentNullException"/> in the first case, or 
+            <see cref="T:System.ArgumentException"/> in the latter.
+            </summary>
+        </member>
+        <member name="M:Moq.Guard.NotOutOfRangeInclusive``1(System.Linq.Expressions.Expression{System.Func{``0}},``0,``0,``0)">
+            <summary>
+            Checks an argument to ensure it is in the specified range including the edges.
+            </summary>
+            <typeparam name="T">Type of the argument to check, it must be an <see cref="T:System.IComparable"/> type.
+            </typeparam>
+            <param name="reference">The expression containing the name of the argument.</param>
+            <param name="value">The argument value to check.</param>
+            <param name="from">The minimun allowed value for the argument.</param>
+            <param name="to">The maximun allowed value for the argument.</param>
+        </member>
+        <member name="M:Moq.Guard.NotOutOfRangeExclusive``1(System.Linq.Expressions.Expression{System.Func{``0}},``0,``0,``0)">
+            <summary>
+            Checks an argument to ensure it is in the specified range excluding the edges.
+            </summary>
+            <typeparam name="T">Type of the argument to check, it must be an <see cref="T:System.IComparable"/> type.
+            </typeparam>
+            <param name="reference">The expression containing the name of the argument.</param>
+            <param name="value">The argument value to check.</param>
+            <param name="from">The minimun allowed value for the argument.</param>
+            <param name="to">The maximun allowed value for the argument.</param>
+        </member>
+        <member name="T:Moq.IMocked`1">
+            <summary>
+            Implemented by all generated mock object instances.
+            </summary>
+        </member>
+        <member name="T:Moq.IMocked">
+            <summary>
+            Implemented by all generated mock object instances.
+            </summary>
+        </member>
+        <member name="P:Moq.IMocked.Mock">
+            <summary>
+            Reference the Mock that contains this as the <c>mock.Object</c> value.
+            </summary>
+        </member>
+        <member name="P:Moq.IMocked`1.Mock">
+            <summary>
+            Reference the Mock that contains this as the <c>mock.Object</c> value.
+            </summary>
+        </member>
+        <member name="T:Moq.Interceptor">
+            <summary>
+            Implements the actual interception and method invocation for 
+            all mocks.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.Flow.ISetupSetter`2">
+            <summary>
+            Implements the fluent API.
+            </summary>
+        </member>
+        <member name="T:Moq.Language.ICallbackSetter`1">
+            <summary>
+            Defines the <c>Callback</c> verb for property setter setups.
+            </summary>
+            <typeparam name="TProperty">Type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Language.ICallbackSetter`1.Callback(System.Action{`0})">
+            <summary>
+            Specifies a callback to invoke when the property is set that receives the 
+            property value being set.
+            </summary>
+            <param name="action">Callback method to invoke.</param>
+            <example>
+            Invokes the given callback with the property value being set. 
+            <code>
+            mock.SetupSet(x => x.Suspended)
+                .Callback((bool state) => Console.WriteLine(state));
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.It">
+            <summary>
+			Allows the specification of a matching condition for an
+			argument in a method invocation, rather than a specific
+			argument value. "It" refers to the argument being matched.
+		</summary><remarks>
+			This class allows the setup to match a method invocation
+			with an arbitrary value, with a value in a specified range, or
+			even one that matches a given predicate.
+		</remarks>
+        </member>
+        <member name="M:Moq.It.IsAny``1">
+            <summary>
+			Matches any value of the given <typeparamref name="TValue"/> type.
+		</summary><remarks>
+			Typically used when the actual argument value for a method
+			call is not relevant.
+		</remarks><example>
+			<code>
+				// Throws an exception for a call to Remove with any string value.
+				mock.Setup(x => x.Remove(It.IsAny<string>())).Throws(new InvalidOperationException());
+			</code>
+		</example><typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.It.IsNotNull``1">
+            <summary>
+         Matches any value of the given <typeparamref name="TValue"/> type, except null.
+      </summary><typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.It.Is``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+			Matches any value that satisfies the given predicate.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="match">The predicate used to match the method argument.</param><remarks>
+			Allows the specification of a predicate to perform matching
+			of method call arguments.
+		</remarks><example>
+			This example shows how to return the value <c>1</c> whenever the argument to the
+			<c>Do</c> method is an even number.
+			<code>
+				mock.Setup(x => x.Do(It.Is<int>(i => i % 2 == 0)))
+				.Returns(1);
+			</code>
+			This example shows how to throw an exception if the argument to the
+			method is a negative number:
+			<code>
+				mock.Setup(x => x.GetUser(It.Is<int>(i => i < 0)))
+				.Throws(new ArgumentException());
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsInRange``1(``0,``0,Moq.Range)">
+            <summary>
+			Matches any value that is in the range specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="from">The lower bound of the range.</param><param name="to">The upper bound of the range.</param><param name="rangeKind">
+			The kind of range. See <see cref="T:Moq.Range"/>.
+		</param><example>
+			The following example shows how to expect a method call
+			with an integer argument within the 0..100 range.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsInRange(0, 100, Range.Inclusive)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsIn``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+			Matches any value that is present in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of possible values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with value from a list.
+			<code>
+				var values = new List<int> { 1, 2, 3 };
+			
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsIn(values)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsIn``1(``0[])">
+            <summary>
+			Matches any value that is present in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of possible values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with a value of 1, 2, or 3.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsIn(1, 2, 3)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsNotIn``1(System.Collections.Generic.IEnumerable{``0})">
+            <summary>
+			Matches any value that is not found in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of disallowed values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument with value not found from a list.
+			<code>
+				var values = new List<int> { 1, 2, 3 };
+				
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsNotIn(values)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsNotIn``1(``0[])">
+            <summary>
+			Matches any value that is not found in the sequence specified.
+		</summary><typeparam name="TValue">Type of the argument to check.</typeparam><param name="items">The sequence of disallowed values.</param><example>
+			The following example shows how to expect a method call
+			with an integer argument of any value except 1, 2, or 3.
+			<code>
+				mock.Setup(x => x.HasInventory(
+				It.IsAny<string>(),
+				It.IsNotIn(1, 2, 3)))
+				.Returns(false);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsRegex(System.String)">
+            <summary>
+			Matches a string argument if it matches the given regular expression pattern.
+		</summary><param name="regex">The pattern to use to match the string argument value.</param><example>
+			The following example shows how to expect a call to a method where the
+			string argument matches the given regular expression:
+			<code>
+				mock.Setup(x => x.Check(It.IsRegex("[a-z]+"))).Returns(1);
+			</code>
+		</example>
+        </member>
+        <member name="M:Moq.It.IsRegex(System.String,System.Text.RegularExpressions.RegexOptions)">
+            <summary>
+			Matches a string argument if it matches the given regular expression pattern.
+		</summary><param name="regex">The pattern to use to match the string argument value.</param><param name="options">The options used to interpret the pattern.</param><example>
+			The following example shows how to expect a call to a method where the
+			string argument matches the given regular expression, in a case insensitive way:
+			<code>
+				mock.Setup(x => x.Check(It.IsRegex("[a-z]+", RegexOptions.IgnoreCase))).Returns(1);
+			</code>
+		</example>
+        </member>
+        <member name="T:Moq.Matchers.MatcherAttributeMatcher">
+            <summary>
+            Matcher to treat static functions as matchers.
+            
+            mock.Setup(x => x.StringMethod(A.MagicString()));
+            
+            public static class A 
+            {
+                [Matcher]
+                public static string MagicString() { return null; }
+                public static bool MagicString(string arg)
+                {
+                    return arg == "magic";
+                }
+            }
+            
+            Will succeed if: mock.Object.StringMethod("magic");
+            and fail with any other call.
+            </summary>
+        </member>
+        <member name="T:Moq.MockBehavior">
+            <summary>
+            Options to customize the behavior of the mock. 
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Strict">
+            <summary>
+            Causes the mock to always throw 
+            an exception for invocations that don't have a 
+            corresponding setup.
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Loose">
+            <summary>
+            Will never throw exceptions, returning default  
+            values when necessary (null for reference types, 
+            zero for value types or empty enumerables and arrays).
+            </summary>
+        </member>
+        <member name="F:Moq.MockBehavior.Default">
+            <summary>
+            Default mock behavior, which equals <see cref="F:Moq.MockBehavior.Loose"/>.
+            </summary>
+        </member>
+        <member name="T:Moq.MockException">
+            <summary>
+            Exception thrown by mocks when setups are not matched, 
+            the mock is not properly setup, etc.
+            </summary>
+            <remarks>
+            A distinct exception type is provided so that exceptions 
+            thrown by the mock can be differentiated in tests that 
+            expect other exceptions to be thrown (i.e. ArgumentException).
+            <para>
+            Richer exception hierarchy/types are not provided as 
+            tests typically should <b>not</b> catch or expect exceptions 
+            from the mocks. These are typically the result of changes 
+            in the tested class or its collaborators implementation, and 
+            result in fixes in the mock setup so that they dissapear and 
+            allow the test to pass.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:Moq.MockException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+            <param name="info">Serialization information.</param>
+            <param name="context">Streaming context.</param>
+        </member>
+        <member name="M:Moq.MockException.GetObjectData(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+            <param name="info">Serialization information.</param>
+            <param name="context">Streaming context.</param>
+        </member>
+        <member name="P:Moq.MockException.IsVerificationError">
+            <summary>
+            Indicates whether this exception is a verification fault raised by Verify()
+            </summary>
+        </member>
+        <member name="T:Moq.MockException.ExceptionReason">
+            <summary>
+            Made internal as it's of no use for 
+            consumers, but it's important for 
+            our own tests.
+            </summary>
+        </member>
+        <member name="T:Moq.MockVerificationException">
+            <devdoc>
+            Used by the mock factory to accumulate verification 
+            failures.
+            </devdoc>
+        </member>
+        <member name="M:Moq.MockVerificationException.#ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext)">
+            <summary>
+            Supports the serialization infrastructure.
+            </summary>
+        </member>
+        <member name="T:Moq.Properties.Resources">
+            <summary>
+              A strongly-typed resource class, for looking up localized strings, etc.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ResourceManager">
+            <summary>
+              Returns the cached ResourceManager instance used by this class.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.Culture">
+            <summary>
+              Overrides the current thread's CurrentUICulture property for all
+              resource lookups using this strongly typed resource class.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.AlreadyInitialized">
+            <summary>
+              Looks up a localized string similar to Mock type has already been initialized by accessing its Object property. Adding interfaces must be done before that..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ArgumentCannotBeEmpty">
+            <summary>
+              Looks up a localized string similar to Value cannot be an empty string..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.AsMustBeInterface">
+            <summary>
+              Looks up a localized string similar to Can only add interfaces to the mock..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.CantSetReturnValueForVoid">
+            <summary>
+              Looks up a localized string similar to Can't set return value for void method {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorArgsForDelegate">
+            <summary>
+              Looks up a localized string similar to Constructor arguments cannot be passed for delegate mocks..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorArgsForInterface">
+            <summary>
+              Looks up a localized string similar to Constructor arguments cannot be passed for interface mocks..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ConstructorNotFound">
+            <summary>
+              Looks up a localized string similar to A matching constructor for the given arguments was not found on the mocked type..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.EventNofFound">
+            <summary>
+              Looks up a localized string similar to Could not locate event for attach or detach method {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.FieldsNotSupported">
+            <summary>
+              Looks up a localized string similar to Expression {0} involves a field access, which is not supported. Use properties instead..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.InvalidMockClass">
+            <summary>
+              Looks up a localized string similar to Type to mock must be an interface or an abstract or non-sealed class. .
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.InvalidMockGetType">
+             <summary>
+               Looks up a localized string similar to Cannot retrieve a mock with the given object type {0} as it's not the main type of the mock or any of its additional interfaces.
+            Please cast the argument to one of the supported types: {1}.
+            Remember that there's no generics covariance in the CLR, so your object must be one of these types in order for the call to succeed..
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqBinaryOperatorNotSupported">
+            <summary>
+              Looks up a localized string similar to The equals ("==" or "=" in VB) and the conditional 'and' ("&&" or "AndAlso" in VB) operators are the only ones supported in the query specification expression. Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqMethodNotSupported">
+            <summary>
+              Looks up a localized string similar to LINQ method '{0}' not supported..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.LinqMethodNotVirtual">
+            <summary>
+              Looks up a localized string similar to Expression contains a call to a method which is not virtual (overridable in VB) or abstract. Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MemberMissing">
+            <summary>
+              Looks up a localized string similar to Member {0}.{1} does not exist..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MethodIsPublic">
+             <summary>
+               Looks up a localized string similar to Method {0}.{1} is public. Use strong-typed Expect overload instead:
+            mock.Setup(x => x.{1}());
+            .
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MockExceptionMessage">
+             <summary>
+               Looks up a localized string similar to {0} invocation failed with mock behavior {1}.
+            {2}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MoreThanNCalls">
+            <summary>
+              Looks up a localized string similar to Expected only {0} calls to {1}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.MoreThanOneCall">
+            <summary>
+              Looks up a localized string similar to Expected only one call to {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtLeast">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at least {2} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtLeastOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at least once, but was never performed: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtMost">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at most {3} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsAtMostOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock at most once, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsBetweenExclusive">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock between {2} and {3} times (Exclusive), but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsBetweenInclusive">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock between {2} and {3} times (Inclusive), but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsExactly">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock exactly {2} times, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsNever">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock should never have been performed, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoMatchingCallsOnce">
+             <summary>
+               Looks up a localized string similar to {0}
+            Expected invocation on the mock once, but was {4} times: {1}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.NoSetup">
+            <summary>
+              Looks up a localized string similar to All invocations on the mock must have a corresponding setup..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ObjectInstanceNotMock">
+            <summary>
+              Looks up a localized string similar to Object instance was not created by Moq..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.OutExpressionMustBeConstantValue">
+            <summary>
+              Looks up a localized string similar to Out expression must evaluate to a constant value..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyGetNotFound">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not have a getter..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyMissing">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not exist..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyNotReadable">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} is write-only..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertyNotWritable">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} is read-only..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.PropertySetNotFound">
+            <summary>
+              Looks up a localized string similar to Property {0}.{1} does not have a setter..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.RaisedUnassociatedEvent">
+            <summary>
+              Looks up a localized string similar to Cannot raise a mocked event unless it has been associated (attached) to a concrete event in a mocked object..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.RefExpressionMustBeConstantValue">
+            <summary>
+              Looks up a localized string similar to Ref expression must evaluate to a constant value..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.ReturnValueRequired">
+            <summary>
+              Looks up a localized string similar to Invocation needs to return a value and therefore must have a corresponding setup that provides it..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupLambda">
+            <summary>
+              Looks up a localized string similar to A lambda expression is expected as the argument to It.Is<T>..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNever">
+            <summary>
+              Looks up a localized string similar to Invocation {0} should not have been made..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotMethod">
+            <summary>
+              Looks up a localized string similar to Expression is not a method invocation: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotProperty">
+            <summary>
+              Looks up a localized string similar to Expression is not a property access: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupNotSetter">
+            <summary>
+              Looks up a localized string similar to Expression is not a property setter invocation..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupOnNonMemberMethod">
+            <summary>
+              Looks up a localized string similar to Expression references a method that does not belong to the mocked object: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.SetupOnNonOverridableMember">
+            <summary>
+              Looks up a localized string similar to Invalid setup on a non-virtual (overridable in VB) member: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.TypeNotImplementInterface">
+            <summary>
+              Looks up a localized string similar to Type {0} does not implement required interface {1}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.TypeNotInheritFromType">
+            <summary>
+              Looks up a localized string similar to Type {0} does not from required type {1}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnexpectedPublicProperty">
+             <summary>
+               Looks up a localized string similar to To specify a setup for public property {0}.{1}, use the typed overloads, such as:
+            mock.Setup(x => x.{1}).Returns(value);
+            mock.SetupGet(x => x.{1}).Returns(value); //equivalent to previous one
+            mock.SetupSet(x => x.{1}).Callback(callbackDelegate);
+            .
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedExpression">
+            <summary>
+              Looks up a localized string similar to Unsupported expression: {0}.
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedIntermediateExpression">
+            <summary>
+              Looks up a localized string similar to Only property accesses are supported in intermediate invocations on a setup. Unsupported expression {0}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedIntermediateType">
+            <summary>
+              Looks up a localized string similar to Expression contains intermediate property access {0}.{1} which is of type {2} and cannot be mocked. Unsupported expression {3}..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedMatcherParamsForSetter">
+            <summary>
+              Looks up a localized string similar to Setter expression cannot use argument matchers that receive parameters..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedMember">
+            <summary>
+              Looks up a localized string similar to Member {0} is not supported for protected mocking..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.UnsupportedNonStaticMatcherForSetter">
+            <summary>
+              Looks up a localized string similar to Setter expression can only use static custom matchers..
+            </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.VerficationFailed">
+             <summary>
+               Looks up a localized string similar to The following setups were not matched:
+            {0}.
+             </summary>
+        </member>
+        <member name="P:Moq.Properties.Resources.VerifyOnNonVirtualMember">
+            <summary>
+              Looks up a localized string similar to Invalid verify on a non-virtual (overridable in VB) member: {0}.
+            </summary>
+        </member>
+        <member name="T:Moq.Protected.IProtectedMock`1">
+            <summary>
+            Allows setups to be specified for protected members by using their 
+            name as a string, rather than strong-typing them which is not possible 
+            due to their visibility.
+            </summary>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Setup(System.String,System.Object[])">
+            <summary>
+            Specifies a setup for a void method invocation with the given 
+            <paramref name="voidMethodName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <param name="voidMethodName">The name of the void method to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Setup``1(System.String,System.Object[])">
+            <summary>
+            Specifies a setup for an invocation on a property or a non void method with the given 
+            <paramref name="methodOrPropertyName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <param name="methodOrPropertyName">The name of the method or property to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <typeparam name="TResult">The return type of the method or property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.SetupGet``1(System.String)">
+            <summary>
+            Specifies a setup for an invocation on a property getter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.SetupSet``1(System.String,System.Object)">
+            <summary>
+            Specifies a setup for an invocation on a property setter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <param name="value">The property value. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Verify(System.String,Moq.Times,System.Object[])">
+            <summary>
+            Specifies a verify for a void method with the given <paramref name="methodName"/>,
+            optionally specifying arguments for the method call. Use in conjuntion with the default
+            <see cref="F:Moq.MockBehavior.Loose"/>.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by
+            <paramref name="times"/>.</exception>
+            <param name="methodName">The name of the void method to be verified.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.Verify``1(System.String,Moq.Times,System.Object[])">
+            <summary>
+            Specifies a verify for an invocation on a property or a non void method with the given 
+            <paramref name="methodName"/>, optionally specifying arguments for the method call.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            <param name="methodName">The name of the method or property to be invoked.</param>
+            <param name="args">The optional arguments for the invocation. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <typeparam name="TResult">The type of return value from the expression.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.VerifyGet``1(System.String,Moq.Times)">
+            <summary>
+            Specifies a verify for an invocation on a property getter with the given 
+            <paramref name="propertyName"/>.
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            </summary>
+            <param name="propertyName">The name of the property.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <typeparam name="TProperty">The type of the property.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.IProtectedMock`1.VerifySet``1(System.String,Moq.Times,System.Object)">
+            <summary>
+            Specifies a setup for an invocation on a property setter with the given 
+            <paramref name="propertyName"/>.
+            </summary>
+            <exception cref="T:Moq.MockException">The invocation was not call the times specified by 
+            <paramref name="times"/>.</exception>
+            <param name="propertyName">The name of the property.</param>
+            <param name="times">The number of times a method is allowed to be called.</param>
+            <param name="value">The property value.</param>
+            <typeparam name="TProperty">The type of the property. If argument matchers are used, 
+            remember to use <see cref="T:Moq.Protected.ItExpr"/> rather than <see cref="T:Moq.It"/>.</typeparam>
+        </member>
+        <member name="T:Moq.Protected.ItExpr">
+            <summary>
+            Allows the specification of a matching condition for an 
+            argument in a protected member setup, rather than a specific 
+            argument value. "ItExpr" refers to the argument being matched.
+            </summary>
+            <remarks>
+            <para>Use this variant of argument matching instead of 
+            <see cref="T:Moq.It"/> for protected setups.</para>
+            This class allows the setup to match a method invocation 
+            with an arbitrary value, with a value in a specified range, or 
+            even one that matches a given predicate, or null.
+            </remarks>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsNull``1">
+            <summary>
+            Matches a null value of the given <typeparamref name="TValue"/> type.
+            </summary>
+            <remarks>
+            Required for protected mocks as the null value cannot be used 
+            directly as it prevents proper method overload selection.
+            </remarks>
+            <example>
+            <code>
+            // Throws an exception for a call to Remove with a null string value.
+            mock.Protected()
+                .Setup("Remove", ItExpr.IsNull<string>())
+                .Throws(new InvalidOperationException());
+            </code>
+            </example>
+            <typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsAny``1">
+            <summary>
+            Matches any value of the given <typeparamref name="TValue"/> type.
+            </summary>
+            <remarks>
+            Typically used when the actual argument value for a method 
+            call is not relevant.
+            </remarks>
+            <example>
+            <code>
+            // Throws an exception for a call to Remove with any string value.
+            mock.Protected()
+                .Setup("Remove", ItExpr.IsAny<string>())
+                .Throws(new InvalidOperationException());
+            </code>
+            </example>
+            <typeparam name="TValue">Type of the value.</typeparam>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.Is``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Matches any value that satisfies the given predicate.
+            </summary>
+            <typeparam name="TValue">Type of the argument to check.</typeparam>
+            <param name="match">The predicate used to match the method argument.</param>
+            <remarks>
+            Allows the specification of a predicate to perform matching 
+            of method call arguments.
+            </remarks>
+            <example>
+            This example shows how to return the value <c>1</c> whenever the argument to the 
+            <c>Do</c> method is an even number.
+            <code>
+            mock.Protected()
+                .Setup("Do", ItExpr.Is<int>(i => i % 2 == 0))
+                .Returns(1);
+            </code>
+            This example shows how to throw an exception if the argument to the 
+            method is a negative number:
+            <code>
+            mock.Protected()
+                .Setup("GetUser", ItExpr.Is<int>(i => i < 0))
+                .Throws(new ArgumentException());
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsInRange``1(``0,``0,Moq.Range)">
+            <summary>
+            Matches any value that is in the range specified.
+            </summary>
+            <typeparam name="TValue">Type of the argument to check.</typeparam>
+            <param name="from">The lower bound of the range.</param>
+            <param name="to">The upper bound of the range.</param>
+            <param name="rangeKind">The kind of range. See <see cref="T:Moq.Range"/>.</param>
+            <example>
+            The following example shows how to expect a method call 
+            with an integer argument within the 0..100 range.
+            <code>
+            mock.Protected()
+                .Setup("HasInventory",
+                        ItExpr.IsAny<string>(),
+                        ItExpr.IsInRange(0, 100, Range.Inclusive))
+                .Returns(false);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsRegex(System.String)">
+            <summary>
+            Matches a string argument if it matches the given regular expression pattern.
+            </summary>
+            <param name="regex">The pattern to use to match the string argument value.</param>
+            <example>
+            The following example shows how to expect a call to a method where the 
+            string argument matches the given regular expression:
+            <code>
+            mock.Protected()
+                .Setup("Check", ItExpr.IsRegex("[a-z]+"))
+                .Returns(1);
+            </code>
+            </example>
+        </member>
+        <member name="M:Moq.Protected.ItExpr.IsRegex(System.String,System.Text.RegularExpressions.RegexOptions)">
+            <summary>
+            Matches a string argument if it matches the given regular expression pattern.
+            </summary>
+            <param name="regex">The pattern to use to match the string argument value.</param>
+            <param name="options">The options used to interpret the pattern.</param>
+            <example>
+            The following example shows how to expect a call to a method where the 
+            string argument matches the given regular expression, in a case insensitive way:
+            <code>
+            mock.Protected()
+                .Setup("Check", ItExpr.IsRegex("[a-z]+", RegexOptions.IgnoreCase))
+                .Returns(1);
+            </code>
+            </example>
+        </member>
+        <member name="T:Moq.Protected.ProtectedExtension">
+            <summary>
+            Enables the <c>Protected()</c> method on <see cref="T:Moq.Mock`1"/>, 
+            allowing setups to be set for protected members by using their 
+            name as a string, rather than strong-typing them which is not possible 
+            due to their visibility.
+            </summary>
+        </member>
+        <member name="M:Moq.Protected.ProtectedExtension.Protected``1(Moq.Mock{``0})">
+            <summary>
+            Enable protected setups for the mock.
+            </summary>
+            <typeparam name="T">Mocked object type. Typically omitted as it can be inferred from the mock instance.</typeparam>
+            <param name="mock">The mock to set the protected setups on.</param>
+        </member>
+        <member name="T:ThisAssembly">
+            <group name="overview" title="Overview" order="0" />
+            <group name="setups" title="Specifying setups" order="1" />
+            <group name="returns" title="Returning values from members" order="2" />
+            <group name="verification" title="Verifying setups" order="3" />
+            <group name="advanced" title="Advanced scenarios" order="99" />
+            <group name="factory" title="Using MockFactory for consistency across mocks" order="4" />
+        </member>
+        <member name="T:Moq.Range">
+            <summary>
+            Kind of range to use in a filter specified through 
+            <see cref="M:Moq.It.IsInRange``1(``0,``0,Moq.Range)"/>.
+            </summary>
+        </member>
+        <member name="F:Moq.Range.Inclusive">
+            <summary>
+            The range includes the <c>to</c> and 
+            <c>from</c> values.
+            </summary>
+        </member>
+        <member name="F:Moq.Range.Exclusive">
+            <summary>
+            The range does not include the <c>to</c> and 
+            <c>from</c> values.
+            </summary>
+        </member>
+        <member name="T:Moq.DefaultValue">
+            <summary>
+            Determines the way default values are generated 
+            calculated for loose mocks.
+            </summary>
+        </member>
+        <member name="F:Moq.DefaultValue.Empty">
+            <summary>
+            Default behavior, which generates empty values for 
+            value types (i.e. default(int)), empty array and 
+            enumerables, and nulls for all other reference types.
+            </summary>
+        </member>
+        <member name="F:Moq.DefaultValue.Mock">
+            <summary>
+            Whenever the default value generated by <see cref="F:Moq.DefaultValue.Empty"/> 
+            is null, replaces this value with a mock (if the type 
+            can be mocked). 
+            </summary>
+            <remarks>
+            For sealed classes, a null value will be generated.
+            </remarks>
+        </member>
+        <member name="T:Moq.Linq.MockQueryable`1">
+            <summary>
+            A default implementation of IQueryable for use with QueryProvider
+            </summary>
+        </member>
+        <member name="M:Moq.Linq.MockQueryable`1.#ctor(System.Linq.Expressions.MethodCallExpression)">
+            <summary>
+            The <paramref name="underlyingCreateMocks"/> is a 
+            static method that returns an IQueryable of Mocks of T which is used to 
+            apply the linq specification to.
+            </summary>
+        </member>
+        <member name="T:Moq.Match">
+            <summary>
+			Allows creation custom value matchers that can be used on setups and verification,
+			completely replacing the built-in <see cref="T:Moq.It"/> class with your own argument
+			matching rules.
+		</summary><remarks>
+			 See also <see cref="T:Moq.Match`1"/>.
+		</remarks>
+        </member>
+        <member name="M:Moq.Match.Matcher``1">
+            <devdoc>
+            Provided for the sole purpose of rendering the delegate passed to the 
+            matcher constructor if no friendly render lambda is provided.
+            </devdoc>
+        </member>
+        <member name="M:Moq.Match.Create``1(System.Predicate{``0})">
+            <summary>
+			Initializes the match with the condition that
+			will be checked in order to match invocation
+			values.
+		</summary><param name="condition">The condition to match against actual values.</param><remarks>
+			 <seealso cref="T:Moq.Match`1"/>
+		</remarks>
+        </member>
+        <member name="M:Moq.Match.Create``1(System.Predicate{``0},System.Linq.Expressions.Expression{System.Func{``0}})">
+            <!-- No matching elements were found for the following include tag --><include file="Match.xdoc" path="docs/doc[@for="Match.Create{T}(condition,renderExpression"]/*"/>
+        </member>
+        <member name="M:Moq.Match.SetLastMatch``1(Moq.Match{``0})">
+            <devdoc>
+            This method is used to set an expression as the last matcher invoked, 
+            which is used in the SetupSet to allow matchers in the prop = value 
+            delegate expression. This delegate is executed in "fluent" mode in 
+            order to capture the value being set, and construct the corresponding 
+            methodcall.
+            This is also used in the MatcherFactory for each argument expression.
+            This method ensures that when we execute the delegate, we 
+            also track the matcher that was invoked, so that when we create the 
+            methodcall we build the expression using it, rather than the null/default 
+            value returned from the actual invocation.
+            </devdoc>
+        </member>
+        <member name="T:Moq.Match`1">
+            <summary>
+			Allows creation custom value matchers that can be used on setups and verification,
+			completely replacing the built-in <see cref="T:Moq.It"/> class with your own argument
+			matching rules.
+		</summary><typeparam name="T">Type of the value to match.</typeparam><remarks>
+			The argument matching is used to determine whether a concrete
+			invocation in the mock matches a given setup. This
+			matching mechanism is fully extensible.
+		</remarks><example>
+			Creating a custom matcher is straightforward. You just need to create a method
+			that returns a value from a call to <see cref="M:Moq.Match.Create``1(System.Predicate{``0})"/> with 
+			your matching condition and optional friendly render expression:
+			<code>
+				[Matcher]
+				public Order IsBigOrder()
+				{
+					return Match<Order>.Create(
+						o => o.GrandTotal >= 5000, 
+						/* a friendly expression to render on failures */
+						() => IsBigOrder());
+				}
+			</code>
+			This method can be used in any mock setup invocation:
+			<code>
+				mock.Setup(m => m.Submit(IsBigOrder()).Throws<UnauthorizedAccessException>();
+			</code>
+			At runtime, Moq knows that the return value was a matcher (note that the method MUST be 
+			annotated with the [Matcher] attribute in order to determine this) and
+			evaluates your predicate with the actual value passed into your predicate.
+			<para>
+				Another example might be a case where you want to match a lists of orders
+				that contains a particular one. You might create matcher like the following:
+			</para>
+			<code>
+				public static class Orders
+				{
+					[Matcher]
+					public static IEnumerable<Order> Contains(Order order)
+					{
+						return Match<IEnumerable<Order>>.Create(orders => orders.Contains(order));
+					}
+				}
+			</code>
+			Now we can invoke this static method instead of an argument in an
+			invocation:
+			<code>
+				var order = new Order { ... };
+				var mock = new Mock<IRepository<Order>>();
+
+				mock.Setup(x => x.Save(Orders.Contains(order)))
+					 .Throws<ArgumentException>();
+			</code>
+		</example>
+        </member>
+        <member name="T:Moq.FluentMockContext">
+            <summary>
+            Tracks the current mock and interception context.
+            </summary>
+        </member>
+        <member name="P:Moq.FluentMockContext.IsActive">
+            <summary>
+            Having an active fluent mock context means that the invocation 
+            is being performed in "trial" mode, just to gather the 
+            target method and arguments that need to be matched later 
+            when the actual invocation is made.
+            </summary>
+        </member>
+        <member name="T:Moq.MockDefaultValueProvider">
+            <summary>
+            A <see cref="T:Moq.IDefaultValueProvider"/> that returns an empty default value 
+            for non-mockeable types, and mocks for all other types (interfaces and 
+            non-sealed classes) that can be mocked.
+            </summary>
+        </member>
+        <member name="T:Moq.Mocks">
+            <summary>
+            Allows querying the universe of mocks for those that behave 
+            according to the LINQ query specification.
+            </summary>
+            <devdoc>
+            This entry-point into Linq to Mocks is the only one in the root Moq 
+            namespace to ease discovery. But to get all the mocking extension 
+            methods on Object, a using of Moq.Linq must be done, so that the 
+            polluting of the intellisense for all objects is an explicit opt-in.
+            </devdoc>
+        </member>
+        <member name="M:Moq.Mocks.Of``1">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.Mocks.Of``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Access the universe of mocks of the given type, to retrieve those 
+            that behave according to the LINQ query specification.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object to query.</typeparam>
+        </member>
+        <member name="M:Moq.Mocks.OneOf``1">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mocks.OneOf``1(System.Linq.Expressions.Expression{System.Func{``0,System.Boolean}})">
+            <summary>
+            Creates an mock object of the indicated type.
+            </summary>
+            <param name="specification">The predicate with the setup expressions.</param>
+            <typeparam name="T">The type of the mocked object.</typeparam>
+            <returns>The mocked object created.</returns>
+        </member>
+        <member name="M:Moq.Mocks.CreateMockQuery``1">
+            <summary>
+            Creates the mock query with the underlying queriable implementation.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.CreateQueryable``1">
+            <summary>
+            Wraps the enumerator inside a queryable.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.CreateMocks``1">
+            <summary>
+            Method that is turned into the actual call from .Query{T}, to 
+            transform the queryable query into a normal enumerable query.
+            This method is never used directly by consumers.
+            </summary>
+        </member>
+        <member name="M:Moq.Mocks.SetPropery``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}},``1)">
+            <summary>
+            Extension method used to support Linq-like setup properties that are not virtual but do have 
+            a getter and a setter, thereby allowing the use of Linq to Mocks to quickly initialize Dtos too :)
+            </summary>
+        </member>
+        <member name="T:Moq.QueryableMockExtensions">
+            <summary>
+            Helper extensions that are used by the query translator.
+            </summary>
+        </member>
+        <member name="M:Moq.QueryableMockExtensions.FluentMock``2(Moq.Mock{``0},System.Linq.Expressions.Expression{System.Func{``0,``1}})">
+            <summary>
+            Retrieves a fluent mock from the given setup expression.
+            </summary>
+        </member>
+        <member name="M:Moq.Proxy.IProxyFactory.GetDelegateProxyInterface(System.Type,System.Reflection.MethodInfo@)">
+            <summary>
+            Gets an autogenerated interface with a method on it that matches the signature of the specified
+            <paramref name="delegateType"/>.
+            </summary>
+            <remarks>
+            Such an interface can then be mocked, and a delegate pointed at the method on the mocked instance.
+            This is how we support delegate mocking.  The factory caches such interfaces and reuses them
+            for repeated requests for the same delegate type.
+            </remarks>
+            <param name="delegateType">The delegate type for which an interface is required.</param>
+            <param name="delegateInterfaceMethod">The method on the autogenerated interface.</param>
+        </member>
+        <member name="M:Moq.Proxy.CastleProxyFactory.CreateProxy(System.Type,Moq.Proxy.ICallInterceptor,System.Type[],System.Object[])">
+            <inheritdoc />
+        </member>
+        <member name="M:Moq.Proxy.CastleProxyFactory.GetDelegateProxyInterface(System.Type,System.Reflection.MethodInfo@)">
+            <inheritdoc />
+        </member>
+        <member name="T:Moq.Times">
+            <summary>
+			Defines the number of invocations allowed by a mocked method.
+		</summary>
+        </member>
+        <member name="M:Moq.Times.AtLeast(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked <paramref name="callCount"/> times as minimum.
+		</summary><param name="callCount">The minimun number of times.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtLeastOnce">
+            <summary>
+			Specifies that a mocked method should be invoked one time as minimum.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtMost(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked <paramref name="callCount"/> time as maximun.
+		</summary><param name="callCount">The maximun number of times.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.AtMostOnce">
+            <summary>
+			Specifies that a mocked method should be invoked one time as maximun.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Between(System.Int32,System.Int32,Moq.Range)">
+            <summary>
+			Specifies that a mocked method should be invoked between <paramref name="callCountFrom"/> and
+			<paramref name="callCountTo"/> times.
+		</summary><param name="callCountFrom">The minimun number of times.</param><param name="callCountTo">The maximun number of times.</param><param name="rangeKind">
+			The kind of range. See <see cref="T:Moq.Range"/>.
+		</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Exactly(System.Int32)">
+            <summary>
+			Specifies that a mocked method should be invoked exactly <paramref name="callCount"/> times.
+		</summary><param name="callCount">The times that a method or property can be called.</param><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Never">
+            <summary>
+			Specifies that a mocked method should not be invoked.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Once">
+            <summary>
+			Specifies that a mocked method should be invoked exactly one time.
+		</summary><returns>An object defining the allowed number of invocations.</returns>
+        </member>
+        <member name="M:Moq.Times.Equals(System.Object)">
+            <summary>
+			Determines whether the specified <see cref="T:System.Object"/> is equal to this instance.
+		</summary><param name="obj">
+			The <see cref="T:System.Object"/> to compare with this instance.
+		</param><returns>
+			<c>true</c> if the specified <see cref="T:System.Object"/> is equal to this instance; otherwise, <c>false</c>.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.GetHashCode">
+            <summary>
+			Returns a hash code for this instance.
+		</summary><returns>
+			A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.op_Equality(Moq.Times,Moq.Times)">
+            <summary>
+			Determines whether two specified <see cref="T:Moq.Times"/> objects have the same value.
+		</summary><param name="left">
+			The first <see cref="T:Moq.Times"/>.
+		</param><param name="right">
+			The second <see cref="T:Moq.Times"/>.
+		</param><returns>
+			<c>true</c> if the value of left is the same as the value of right; otherwise, <c>false</c>.
+		</returns>
+        </member>
+        <member name="M:Moq.Times.op_Inequality(Moq.Times,Moq.Times)">
+            <summary>
+			Determines whether two specified <see cref="T:Moq.Times"/> objects have different values.
+		</summary><param name="left">
+			The first <see cref="T:Moq.Times"/>.
+		</param><param name="right">
+			The second <see cref="T:Moq.Times"/>.
+		</param><returns>
+			<c>true</c> if the value of left is different from the value of right; otherwise, <c>false</c>.
+		</returns>
+        </member>
+    </members>
+</doc>
diff --git a/SolutionItems/Silverlight/Newtonsoft.Json.dll b/SolutionItems/Silverlight/Newtonsoft.Json.dll
new file mode 100644
index 0000000..b3898cd
Binary files /dev/null and b/SolutionItems/Silverlight/Newtonsoft.Json.dll differ
diff --git a/SolutionItems/SolutionItems.csproj b/SolutionItems/SolutionItems.csproj
new file mode 100644
index 0000000..fd0841c
--- /dev/null
+++ b/SolutionItems/SolutionItems.csproj
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{A60D139A-7DBC-4BC5-976A-D89C32C913AD}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SolutionItems</RootNamespace>
+    <AssemblyName>SolutionItems</AssemblyName>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <OutputPath>bin\Debug\</OutputPath>
+    <TargetFrameworkProfile />
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)' == 'Debug'">
+    <Prefer32Bit>false</Prefer32Bit>
+  </PropertyGroup>
+  <ItemGroup>
+    <None Include="Axantum.targets">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="..\Solution.FxCop" />
+    <None Include="AxantumStrongName.pub" />
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="..\AboutTheSolutions.txt">
+      <Link>AboutTheSolutions.txt</Link>
+    </Content>
+    <Content Include="AxCrypt 2.0 Design.html" />
+    <Content Include="..\CustomDictionary.xml">
+      <SubType>Designer</SubType>
+    </Content>
+    <Content Include="ILMerge.exe" />
+    <Content Include="Moq\lib\net35\Moq.dll" />
+    <Content Include="Moq\lib\net35\Moq.xml" />
+    <Content Include="Moq\lib\net40\Moq.dll" />
+    <Content Include="Moq\lib\net40\Moq.xml" />
+    <Content Include="MSBuild.Axantum.Tasks.dll" />
+    <Content Include="MSBuildVersioning.dll" />
+    <Content Include="HowToBuild.txt" />
+    <Content Include="nunit.framework.dll" />
+    <Content Include="signtool.exe" />
+    <Content Include="sn.exe" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
diff --git a/SolutionItems/nunit.framework.dll b/SolutionItems/nunit.framework.dll
new file mode 100644
index 0000000..215767d
Binary files /dev/null and b/SolutionItems/nunit.framework.dll differ
diff --git a/SolutionItems/signtool.exe b/SolutionItems/signtool.exe
new file mode 100644
index 0000000..e631c35
Binary files /dev/null and b/SolutionItems/signtool.exe differ
diff --git a/SolutionItems/sn.exe b/SolutionItems/sn.exe
new file mode 100644
index 0000000..4ca2499
Binary files /dev/null and b/SolutionItems/sn.exe differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-edu/pkg-team/axcrypt.git.git



More information about the debian-edu-commits mailing list